Version in base suite: 1.4.3+dfsg-1 Base version: clamav_1.4.3+dfsg-1 Target version: clamav_1.4.6+dfsg-1~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/c/clamav/clamav_1.4.3+dfsg-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/c/clamav/clamav_1.4.6+dfsg-1~deb13u1.dsc /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/data/metadata-only.flac |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random-3be.bin |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random-3le.bin |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/200x300.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/300x300.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/400x300.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.png.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-cmr.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-gauss.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-lcz2.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-near.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-tri.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/test.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaleup/tinycross.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badbitcount.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badplanes.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_clrsUsed.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_height.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_pal8oversizepal.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_reallybig.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_rletopdown.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_shortfile.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_unusual_extend_buffer_usage.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_width.bad_bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_1_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_4_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_8_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V4_24_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V5_24_Bit.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2color.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rle.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rlecut.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rletrns.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8badindex.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8rle.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v4.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v5.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-231.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-565.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb24.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32-111110.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32bf.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba16-1924.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32-61754.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32.bmp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/cropping - data window differs display window.exr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/cropping - uncropped original.exr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient - data window equals display window.exr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient.hdr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/acid2.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn0g04.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbgn3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbrn2c08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbwn3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbyn3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tm3n3p02.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n0g08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n2c08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp1n3p08.ff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/any-disposal.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/border_touching_layers.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/interlaced.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/issue_1455_undersized.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-combine.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-full-frame-replace.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/mixed-disposal.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/oob.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/alpha_gif_a.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/issue_1455_oversized.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/sample_1.gif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/hdr/images/image1.hdr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/hdr/images/rgbr4x4.hdr |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/Bad_smile-incorrect-image-length.bad_ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-24bpp-mask.ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-32bpp-alpha.ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/png-32bpp-alpha.ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/smile.ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/3.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/cat.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/test.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/pbm/images/issue-794.pbm |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/16bpc/basn6a16.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/apng/ball.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/debug_triangle_corners_widescreen.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#2026.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#403.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/interlaced/basi2c08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/acid2.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn0g04.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbgn3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbrn2c08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbwn3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbyn3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tm3n3p02.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n0g08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n2c08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp1n3p08.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/qoi/basic-test.qoi |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/encoding/black_white.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/cbw8.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ccm8.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ctc24.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ubw8.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ucm8.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc16.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc24.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc32.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict.tiff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_cmyk.tiff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_packbits.tiff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/mandrill.tiff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/rgb-3c-16b.tiff |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/anim.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/lossy_alpha.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/2-color.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/multi-color.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/simple.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-gray.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-rgb.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2.bmp.da27594.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rle.bmp.288e4371.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8badindex.bmp.4500d02.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8rle.bmp.38454155.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v4.bmp.38454155.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v5.bmp.38454155.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-565.bmp.80839b35.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16.bmp.46dd68ad.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb24.bmp.25bba0a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32.bmp.25bba0a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32.bmp.e041b498.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/any-disposal.gif.ace8cccc.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/interlaced.gif.ad3a4823.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/oob.gif.da695a00.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/sample_1.gif.c33b036b.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.hdr.bd02cf8f.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.raw |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.hdr.72ffeca1.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.raw |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/smile.ico.291e3bb0.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/3.jpg.79e90ab0.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/cat.jpg.a1b69d49.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/test.jpg.f0362c80.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/pbm/images/issue-794.pbm.80cbc790.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/16bpc/basn6a16.png.87be531.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.1c840a9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_01_01c840a9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_04_26897da3.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_05_123fe3c5.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_06_69c299ea.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_07_765d3648.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_08_e44a80f7.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_09_dd6883db.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_10_3b68b97b.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_12_0796c12e.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_13_bf335902.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_14_ee765a97.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_15_56f89914.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_16_cd899432.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_17_0c3b039a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_18_611a8f5d.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_19_d7316ce1.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_20_1e8b755f.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/issue#403.png.b0818cef.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/interlaced/basi2c08.png.7855b9bf.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/acid2.png.8de8ca3f.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbrn2c08.png.370ef89.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n2c08.png.b426b350.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n3p08.png.15493236.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ctc24.tga.b7096b3.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc24.tga.b7096b3.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc32.tga.134a83ba.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/anim.webp.f6449d24.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/lossy_alpha.webp.37efcff9.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/2-color.webp.d5b9a8bd.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/multi-color.webp.d98bd812.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/simple.webp.18d31ac3.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-gray.webp.6b294f50.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-rgb.webp.4bb22be5.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/ico/crash-981fee302fe0fc543ee48292cc3d6ace7e97e633.ico |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/jpg/oss-fuzz-36829.jpeg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/bad-color-map.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height2.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/overfull-image.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap2.tga |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tiff/clusterfuzz-testcase-minimized-fuzzer_script_tiff-5026894169374720.tif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/webp/panic.webp |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/imgref/imgref.png |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/inflate/tests/issue_14.zlib |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_grayscale.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_progressive.jpg |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/subsubifds.tif |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/libwit_bindgen_cabi.a |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.o |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.o |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.o |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/wasi-cli@0.2.0.wasm |binary /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/y4m/scripts/id_rsa.enc |binary clamav-1.4.6+dfsg/.cargo/vendor/adler/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/adler/CHANGELOG.md | 63 clamav-1.4.6+dfsg/.cargo/vendor/adler/Cargo.toml | 64 clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-0BSD | 12 clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/adler/README.md | 39 clamav-1.4.6+dfsg/.cargo/vendor/adler/RELEASE_PROCESS.md | 13 clamav-1.4.6+dfsg/.cargo/vendor/adler/benches/bench.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/adler/src/algo.rs | 146 clamav-1.4.6+dfsg/.cargo/vendor/adler/src/lib.rs | 287 clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/adler2/CHANGELOG.md | 84 clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.lock | 16 clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml | 91 clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml.orig | 71 clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-0BSD | 12 clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/adler2/README.md | 46 clamav-1.4.6+dfsg/.cargo/vendor/adler2/RELEASE_PROCESS.md | 13 clamav-1.4.6+dfsg/.cargo/vendor/adler2/benches/bench.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/algo.rs | 155 clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/lib.rs | 287 clamav-1.4.6+dfsg/.cargo/vendor/adler32/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/adler32/Cargo.toml | 61 clamav-1.4.6+dfsg/.cargo/vendor/adler32/LICENSE | 43 clamav-1.4.6+dfsg/.cargo/vendor/adler32/README.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/bench.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/lib.rs | 324 clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.github/workflows/ci.yml | 148 clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.vim/coc-settings.json | 12 clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/Cargo.toml.orig | 74 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.lock | 96 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml | 60 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml.orig | 26 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/README.md | 12 clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/lib.rs | 1419 + clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/raw.rs | 415 clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/aligned/.github/workflows/ci.yml | 11 clamav-1.4.6+dfsg/.cargo/vendor/aligned/CHANGELOG.md | 122 clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.lock | 25 clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml | 44 clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/aligned/README.md | 22 clamav-1.4.6+dfsg/.cargo/vendor/aligned/bors.toml | 3 clamav-1.4.6+dfsg/.cargo/vendor/aligned/src/lib.rs | 869 clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/Cargo.toml.orig | 15 clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/Cargo.toml.orig | 20 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/workflows/ci.yml | 147 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.lock | 488 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml | 132 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml.orig | 40 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/README.md | 181 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/build.rs | 232 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/rust-toolchain.toml | 2 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/backtrace.rs | 410 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/chain.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/context.rs | 193 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ensure.rs | 935 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/error.rs | 1218 + clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/fmt.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/kind.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/lib.rs | 736 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/macros.rs | 245 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/nightly.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ptr.rs | 199 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/wrapper.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/common/mod.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/compiletest.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/drop/mod.rs | 53 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_autotrait.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_backtrace.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_boxed.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_chain.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_context.rs | 172 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_convert.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_downcast.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ensure.rs | 754 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ffi.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_fmt.rs | 93 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_macros.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_repr.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_source.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.stderr | 10 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.stderr | 103 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.stderr | 32 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.github/workflows/rust.yml | 63 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/CHANGELOG.md | 553 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.lock | 63 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml | 72 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml.orig | 42 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-MIT | 27 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/README.md | 139 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/examples/derive_enum.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/publish.sh | 14 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/error.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/borrow.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/boxed.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/binary_heap.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_map.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_set.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/linked_list.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/mod.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/vec_deque.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/c_str.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/mod.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/rc.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/string.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/sync.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/vec.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/array.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/bool.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cell.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/char.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cmp.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/iter.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/marker.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/mod.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/num.rs | 141 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/ops.rs | 127 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/option.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/result.rs | 31 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/slice.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/str.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/atomic.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/time.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/tuple.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/unit.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/mod.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_map.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_set.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/mod.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/c_str.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/mod.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/os_str.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/mod.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/net.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/path.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/sync.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/lib.rs | 608 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/size_hint.rs | 149 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/tests.rs | 316 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/unstructured.rs | 1071 + clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/bound.rs | 142 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/derive.rs | 402 clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/path.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml | 41 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/README.md | 49 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/src/lib.rs | 280 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/enums.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.github/workflows/ci.yml | 92 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/CHANGELOG.md | 328 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml | 111 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml.orig | 62 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/README.md | 27 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/arraystring.rs | 90 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/extend.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/array_string.rs | 716 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec.rs | 1348 + clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec_impl.rs | 87 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/char.rs | 92 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/errors.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/lib.rs | 63 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/utils.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/borsh.rs | 73 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/serde.rs | 79 clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/tests.rs | 779 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.travis.yml | 12 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/CHANGELOG.md | 65 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml | 25 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml.orig | 16 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/README.md | 21 clamav-1.4.6+dfsg/.cargo/vendor/as-slice/src/lib.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/autocfg/Cargo.toml.orig | 15 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/av-scenechange.yml | 91 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/dependabot.yml | 24 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/deploy.yml | 79 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/CHANGELOG.md | 123 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.lock | 1138 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml | 182 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml.orig | 72 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/README.md | 9 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/build.rs | 252 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/rustfmt.toml | 18 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/fast.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/importance.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/inter.rs | 1882 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra.rs | 374 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra/simd_x86.rs | 134 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/mod.rs | 417 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/standard.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred.S | 5245 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred16.S | 5639 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc.S | 3310 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc16.S | 3611 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/satd.S | 1473 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/util.S | 229 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/asm.S | 291 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/tables.S | 337 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx2.asm | 4992 ++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx512.asm | 833 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_sse.asm | 4076 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx2.asm | 5387 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx512.asm | 1432 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_sse.asm | 5398 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx2.asm | 5879 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx512.asm | 4858 ++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_sse.asm | 8731 ++++++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx2.asm | 5669 +++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx512.asm | 4538 ++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_sse.asm | 9599 +++++++++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_avx.asm | 204 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_plane.asm | 183 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_sse2.asm | 354 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd.asm | 979 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd16_avx2.asm | 1129 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/tables.asm | 563 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/x86inc.asm | 1902 + clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/cpu.rs | 309 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/block.rs | 286 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/frame.rs | 174 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/hadamard.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc.rs | 307 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_neon.rs | 187 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_x86.rs | 225 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mod.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/motion.rs | 320 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/plane.rs | 547 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/prediction.rs | 148 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad/simd_x86.rs | 65 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd.rs | 127 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_neon.rs | 200 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_x86.rs | 242 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/tests.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/superblock.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/tile.rs | 420 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/decoder.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/ffmpeg.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/lib.rs | 216 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/main.rs | 135 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/vapoursynth.rs | 200 clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/y4m.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-compact.yml | 50 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-macos.yml | 50 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-ubuntu.yml | 185 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-windows.yml | 81 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/dependabot.yml | 24 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/CHANGELOG.md | 42 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.lock | 398 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml | 199 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml.orig | 156 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/LICENSE | 25 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/README.md | 47 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/rustfmt.toml | 18 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/create.rs | 467 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/ffmpeg.rs | 276 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver.rs | 1159 + clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver/util.rs | 234 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/vapoursynth.rs | 180 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/estimate.rs | 71 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/lib.rs | 114 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/parse.rs | 797 clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/util.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.lock | 203 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml | 65 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/LICENSE | 29 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/README.md | 21 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/boxes.rs | 654 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/constants.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/lib.rs | 507 clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/writer.rs | 143 clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/base64/.circleci/config.yml | 135 clamav-1.4.6+dfsg/.cargo/vendor/base64/.github/ISSUE_TEMPLATE/general-purpose-issue.md | 21 clamav-1.4.6+dfsg/.cargo/vendor/base64/Cargo.toml.orig | 60 clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bindgen/Cargo.toml.orig | 59 clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.travis.yml | 16 clamav-1.4.6+dfsg/.cargo/vendor/bit_field/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.github/workflows/rust.yml | 56 clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/Cargo.toml.orig | 39 clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/tests/compile-fail/.gitignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bitflags/Cargo.toml.orig | 43 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.github/workflows/ci.yml | 42 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/CHANGES.md | 62 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.lock | 25 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml | 87 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml.orig | 24 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/README.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-read.rs | 148 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-write.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/byte_io.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/huffman.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/lib.rs | 3762 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/read.rs | 2508 ++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/write.rs | 3033 ++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/huffman.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random.bin | 1 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read.rs | 1043 + clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read_seek.rs | 133 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/roundtrip.rs | 484 clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/write.rs | 2116 ++ clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/Cargo.toml.orig | 15 clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/built/.devcontainer/devcontainer.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/built/.github/workflows/check.yml | 88 clamav-1.4.6+dfsg/.cargo/vendor/built/CHANGELOG.md | 129 clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.lock | 974 clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml | 76 clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml.orig | 27 clamav-1.4.6+dfsg/.cargo/vendor/built/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/built/README.md | 73 clamav-1.4.6+dfsg/.cargo/vendor/built/src/dependencies.rs | 276 clamav-1.4.6+dfsg/.cargo/vendor/built/src/environment.rs | 527 clamav-1.4.6+dfsg/.cargo/vendor/built/src/git.rs | 332 clamav-1.4.6+dfsg/.cargo/vendor/built/src/krono.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/built/src/lib.rs | 526 clamav-1.4.6+dfsg/.cargo/vendor/built/src/util.rs | 219 clamav-1.4.6+dfsg/.cargo/vendor/built/tests/testbox_tests.rs | 906 clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/Cargo.toml.orig | 58 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo/config.toml | 4 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/FUNDING.yml | 3 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/workflows/rust.yml | 111 clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/Cargo.toml.orig | 116 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml | 57 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/LICENSE-MIT | 21 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/README.md | 12 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/UNLICENSE | 24 clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/io.rs | 1066 + clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/lib.rs | 3983 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.github/workflows/ci.yml | 183 clamav-1.4.6+dfsg/.cargo/vendor/byteorder/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/bytes/.github/workflows/ci.yml | 211 clamav-1.4.6+dfsg/.cargo/vendor/bytes/CHANGELOG.md | 43 clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.lock | 444 clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml | 31 clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml.orig | 45 clamav-1.4.6+dfsg/.cargo/vendor/bytes/README.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/miri.sh | 3 clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/panic-abort.sh | 4 clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/test-stable.sh | 7 clamav-1.4.6+dfsg/.cargo/vendor/bytes/clippy.toml | 2 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_impl.rs | 1560 + clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_mut.rs | 60 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/chain.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/take.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/vec_deque.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes.rs | 128 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes_mut.rs | 81 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/lib.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/loom.rs | 3 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf.rs | 455 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf_mut.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes.rs | 93 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes_vec_alloc.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_chain.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_limit.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_reader.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_take.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.github/workflows/ci.yml | 96 clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/Cargo.toml.orig | 36 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.clippy.toml | 2 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/cbindgen.yml | 87 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/deploy.yml | 56 clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/Cargo.toml.orig | 52 clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/cc/Cargo.toml.orig | 42 clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.github/workflows/ci.yml | 31 clamav-1.4.6+dfsg/.cargo/vendor/cexpr/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.github/workflows/main.yml | 56 clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/Cargo.toml.orig | 25 clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/chrono/Cargo.toml.orig | 76 clamav-1.4.6+dfsg/.cargo/vendor/chrono/README.md | 92 clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ci.yml | 49 clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ssh.yml | 40 clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/Cargo.toml.orig | 62 clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.github/workflows/rust.yml | 38 clamav-1.4.6+dfsg/.cargo/vendor/color_quant/Cargo.toml.orig | 8 clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/Cargo.toml.orig | 22 clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/core2/.github/workflows/ci.yml | 91 clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml | 31 clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml.orig | 21 clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-APACHE | 202 clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-MIT | 19 clamav-1.4.6+dfsg/.cargo/vendor/core2/README.md | 66 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/error.rs | 473 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/buffered.rs | 1111 + clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/cursor.rs | 272 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/error.rs | 458 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/impls.rs | 176 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/mod.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/traits.rs | 1363 + clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/util.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/core2/src/lib.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/core2/tests/tests.rs | 501 clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/Cargo.toml.orig | 27 clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.travis.yml | 50 clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/Cargo.toml.orig | 29 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/Cargo.toml.orig | 31 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/CHANGELOG.md | 12 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.lock | 298 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml | 62 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml.orig | 59 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/build.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/atomic.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/collector.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/default.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/deferred.rs | 3 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/epoch.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/guard.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/internal.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/lib.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/list.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/queue.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/Cargo.toml.orig | 43 clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/crunchy/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/Cargo.toml.orig | 27 clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/delharc/Cargo.toml.orig | 116 clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/digest/Cargo.toml.orig | 35 clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/either/.github/workflows/ci.yml | 92 clamav-1.4.6+dfsg/.cargo/vendor/either/Cargo.toml.orig | 38 clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/Cargo.toml.orig | 45 clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.gitlab-ci.yml | 43 clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/Cargo.toml.orig | 26 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.lock | 47 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml | 42 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml.orig | 18 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/README.md | 35 clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/src/lib.rs | 840 clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.lock | 204 clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml | 41 clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml.orig | 16 clamav-1.4.6+dfsg/.cargo/vendor/equator/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/equator/README.md | 35 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/decompose.rs | 326 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/lib.rs | 372 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/by_val.rs | 203 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/debug.rs | 132 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/sized.rs | 160 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/structures.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/equator/src/traits.rs | 469 clamav-1.4.6+dfsg/.cargo/vendor/equator/tests/test_asm.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/dependabot.yml | 10 clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/workflows/main.yml | 68 clamav-1.4.6+dfsg/.cargo/vendor/errno/Cargo.toml.orig | 33 clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/bug_report.md | 19 clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/feature_request.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/other.md | 6 clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/question.md | 11 clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/workflows/rust.yml | 127 clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.lock | 310 clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml | 195 clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml.orig | 113 clamav-1.4.6+dfsg/.cargo/vendor/exr/README.md | 14 clamav-1.4.6+dfsg/.cargo/vendor/exr/benches/pixel_format_conversion.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/exr/examples/README.md | 3 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/chunk.rs | 117 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/lines.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/mod.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/reader.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/writer.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/b44/mod.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/mod.rs | 209 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/huffman.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/mod.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/pxr24.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/rle.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/zip.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/error.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/mod.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/image.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/specific_channels.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/channels.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/mod.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/io.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/attribute.rs | 339 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/header.rs | 262 clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/mod.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/across_compression.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/roundtrip.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/fastrand/Cargo.toml.orig | 37 clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.lock | 120 clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml | 77 clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/fax/README.md | 8 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/bitdiff.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/check.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2pbm.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2tiff.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/pbm2fax.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/validate.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/fax/src/decoder.rs | 265 clamav-1.4.6+dfsg/.cargo/vendor/fax/src/encoder.rs | 134 clamav-1.4.6+dfsg/.cargo/vendor/fax/src/lib.rs | 294 clamav-1.4.6+dfsg/.cargo/vendor/fax/src/maps.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/fax/src/tiff.rs | 73 clamav-1.4.6+dfsg/.cargo/vendor/fax/tests/check.rs | 167 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.lock | 47 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml | 40 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml.orig | 16 clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/src/lib.rs | 391 clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/Cargo.toml.orig | 25 clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.lock | 136 clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml | 210 clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml.orig | 52 clamav-1.4.6+dfsg/.cargo/vendor/flate2/LICENSE-MIT | 2 clamav-1.4.6+dfsg/.cargo/vendor/flate2/MAINTENANCE.md | 15 clamav-1.4.6+dfsg/.cargo/vendor/flate2/README.md | 31 clamav-1.4.6+dfsg/.cargo/vendor/flate2/examples/decompress_file.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/crc.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/bufread.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/mod.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/read.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/write.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/c.rs | 241 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/mod.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/rust.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/bufread.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/mod.rs | 56 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/read.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/write.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/lib.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/mem.rs | 111 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zio.rs | 31 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/bufread.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/mod.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/read.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/write.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/flume/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/flume/CHANGELOG.md | 134 clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.lock | 1312 - clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.toml | 110 clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/flume/README.md | 86 clamav-1.4.6+dfsg/.cargo/vendor/flume/benches/basic.rs | 474 clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/async.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/perf.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/select.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/simple.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/flume/src/async.rs | 543 clamav-1.4.6+dfsg/.cargo/vendor/flume/src/lib.rs | 1142 - clamav-1.4.6+dfsg/.cargo/vendor/flume/src/select.rs | 405 clamav-1.4.6+dfsg/.cargo/vendor/flume/src/signal.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/after.rs | 339 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/array.rs | 657 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/async.rs | 276 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/basic.rs | 428 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/check_same_channel.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/golang.rs | 1445 - clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/iter.rs | 112 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/list.rs | 536 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/method_sharing.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/mpsc.rs | 2095 -- clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/never.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/ready.rs | 837 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/same_channel.rs | 114 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select.rs | 1304 - clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select_macro.rs | 1440 - clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/stream.rs | 255 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/thread_locals.rs | 53 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/tick.rs | 353 clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/zero.rs | 557 clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/generic-array/Cargo.toml.orig | 43 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/CHANGELOG.md | 673 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.lock | 292 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml | 133 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml.orig | 100 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/README.md | 386 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/SECURITY.md | 13 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/benches/buffer.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/build.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends.rs | 209 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/apple_other.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/custom.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/efi_rng.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/esp_idf.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/fuchsia.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getentropy.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getrandom.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/hermit.rs | 53 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_android_with_fallback.rs | 103 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_raw.rs | 143 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/netbsd.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rdrand.rs | 182 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rndr.rs | 145 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/sanitizer.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solaris.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solid.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/unsupported.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/use_file.rs | 234 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/vxworks.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p1.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p2.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasm_js.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows_legacy.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error.rs | 212 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error_std_impls.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lazy.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lib.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util_libc.rs | 81 clamav-1.4.6+dfsg/.cargo/vendor/getrandom/tests/mod.rs | 297 clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.lock | 379 clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml | 43 clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml.orig | 57 clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/decode.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/rgb_frame.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/common.rs | 235 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/encoder.rs | 187 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/lib.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/converter.rs | 111 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/decoder.rs | 633 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/mod.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/gif/src/traits.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/glob/.github/workflows/rust.yml | 35 clamav-1.4.6+dfsg/.cargo/vendor/glob/Cargo.toml.orig | 17 clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/half/.reuse/dep5 | 7 clamav-1.4.6+dfsg/.cargo/vendor/half/Cargo.toml.orig | 55 clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/Cargo.toml.orig | 60 clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/heck/Cargo.toml.orig | 20 clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/Cargo.toml.orig | 11 clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/hex/.github/workflows/rust.yml | 32 clamav-1.4.6+dfsg/.cargo/vendor/hex/.gitlab-ci.yml | 47 clamav-1.4.6+dfsg/.cargo/vendor/hex/.travis.yml | 32 clamav-1.4.6+dfsg/.cargo/vendor/hex/Cargo.toml.orig | 40 clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/home/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/Cargo.toml.orig | 16 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.clang-format | 9 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/dependabot.yml | 12 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/workflows/rust.yml | 389 clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/Cargo.toml.orig | 42 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.lock | 352 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml | 63 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml.orig | 26 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-APACHE | 177 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/README.md | 65 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/alpha_blending.rs | 130 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/decoder.rs | 1030 + clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/encoder.rs | 855 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/extended.rs | 327 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/huffman.rs | 248 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lib.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/loop_filter.rs | 437 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless.rs | 825 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless_transform.rs | 716 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/mod.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/transform.rs | 83 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8.rs | 2897 ++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8_arithmetic_decoder.rs | 613 clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/yuv.rs | 452 clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/image/CHANGES.md | 165 clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.lock | 1125 - clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml | 223 clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.orig | 123 clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.public-private-dependencies | 98 clamav-1.4.6+dfsg/.cargo/vendor/image/README.md | 303 clamav-1.4.6+dfsg/.cargo/vendor/image/benches/blur.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/image/benches/copy_from.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/image/benches/decode.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/image/benches/encode.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/image/benches/fast_blur.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/image/deny.toml | 38 clamav-1.4.6+dfsg/.cargo/vendor/image/docs/2019-04-23-memory-unsafety.md | 54 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/main.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/convert.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/decode.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/gradient/main.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/opening.rs | 31 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/main.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaleup/main.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/image/examples/tile/main.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/image/release.sh | 24 clamav-1.4.6+dfsg/.cargo/vendor/image/src/animation.rs | 65 clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer.rs | 1805 - clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer_par.rs | 496 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/decoder.rs | 653 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/encoder.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/mod.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/ycgco.rs | 419 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/yuv.rs | 1279 + clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/decoder.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/encoder.rs | 207 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dds.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dxt.rs | 577 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/farbfeld.rs | 53 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/gif.rs | 153 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/decoder.rs | 476 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/encoder.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/decoder.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/encoder.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/decoder.rs | 1426 - clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/encoder.rs | 309 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/openexr.rs | 164 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/png.rs | 441 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/autobreak.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/decoder.rs | 525 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/encoder.rs | 179 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/header.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/mod.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/qoi.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/decoder.rs | 626 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/encoder.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/header.rs | 35 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tiff.rs | 354 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/decoder.rs | 450 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/encoder.rs | 856 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/extended.rs | 868 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/huffman.rs | 200 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/loop_filter.rs | 147 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless.rs | 781 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless_transform.rs | 461 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/mod.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/transform.rs | 77 clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/vp8.rs | 2916 -- clamav-1.4.6+dfsg/.cargo/vendor/image/src/color.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/image/src/dynimage.rs | 1378 - clamav-1.4.6+dfsg/.cargo/vendor/image/src/error.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/image/src/flat.rs | 1738 - clamav-1.4.6+dfsg/.cargo/vendor/image/src/hooks.rs | 139 clamav-1.4.6+dfsg/.cargo/vendor/image/src/image.rs | 2008 - clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/affine.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/colorops.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/fast_blur.rs | 573 clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/filter_1d.rs | 1000 clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/mod.rs | 105 clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/sample.rs | 714 clamav-1.4.6+dfsg/.cargo/vendor/image/src/images.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer.rs | 2214 ++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer_par.rs | 496 clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/dynimage.rs | 2246 ++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/flat.rs | 1716 + clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/generic_image.rs | 608 clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/sub_image.rs | 263 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/decoder.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/encoder.rs | 132 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/format.rs | 470 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/free_functions.rs | 696 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/image_reader_type.rs | 363 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/limits.rs | 172 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/mod.rs | 180 clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/reader.rs | 239 clamav-1.4.6+dfsg/.cargo/vendor/image/src/lib.rs | 136 clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/rect.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/utils.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata.rs | 192 clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata/cicp.rs | 1632 + clamav-1.4.6+dfsg/.cargo/vendor/image/src/traits.rs | 257 clamav-1.4.6+dfsg/.cargo/vendor/image/src/utils/mod.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/conversions.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/LICENSE | 16 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits.rs | 229 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits_anim.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/README.txt | 7 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference_images.rs | 350 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression.rs | 81 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/save_jpeg.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/image/tests/truncate_images.rs | 101 clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/imgref/.github/workflows/cargo.yml | 31 clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.lock | 7 clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml | 59 clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml.orig | 25 clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-CC0 | 121 clamav-1.4.6+dfsg/.cargo/vendor/imgref/README.md | 63 clamav-1.4.6+dfsg/.cargo/vendor/imgref/benches/iterbench.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/iter.rs | 345 clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/lib.rs | 972 clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/ops.rs | 128 clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/traits.rs | 150 clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.github/workflows/ci.yml | 114 clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.rustfmt.toml | 1 clamav-1.4.6+dfsg/.cargo/vendor/indexmap/Cargo.toml.orig | 65 clamav-1.4.6+dfsg/.cargo/vendor/inflate/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/inflate/Cargo.toml | 26 clamav-1.4.6+dfsg/.cargo/vendor/inflate/LICENSE | 22 clamav-1.4.6+dfsg/.cargo/vendor/inflate/README.md | 58 clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/checksum.rs | 92 clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/lib.rs | 1039 - clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/reader.rs | 358 clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/utils.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/writer.rs | 88 clamav-1.4.6+dfsg/.cargo/vendor/inflate/tests/test.rs | 156 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.lock | 47 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml | 42 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml.orig | 20 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/README.md | 28 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/examples/rename.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/src/lib.rs | 204 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_name.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_test.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.github/workflows/ci.yml | 40 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.rustfmt.toml | 3 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/CHANGELOG.md | 380 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml | 88 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml.orig | 79 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/README.md | 44 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/bench1.rs | 877 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations.rs | 125 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations_with_replacement.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/mod.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/zipslices.rs | 188 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/fold_specialization.rs | 73 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/powerset.rs | 44 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tree_fold1.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuple_combinations.rs | 113 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuples.rs | 213 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/clippy.toml | 1 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.data | 150 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.rs | 137 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/coalesce.rs | 235 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/map.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/mod.rs | 1151 + clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/multi_product.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations.rs | 128 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations_with_replacement.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/concat_impl.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/cons_tuples_impl.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/diff.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/duplicates_impl.rs | 216 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/either_or_both.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/exactly_one_err.rs | 110 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/extrema_set.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/flatten_ok.rs | 165 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/format.rs | 113 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/free.rs | 286 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/group_map.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/groupbylazy.rs | 571 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/grouping_map.rs | 535 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/impl_macros.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/intersperse.rs | 118 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/k_smallest.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/kmerge_impl.rs | 227 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lazy_buffer.rs | 63 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lib.rs | 3784 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/merge_join.rs | 169 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/minmax.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/multipeek_impl.rs | 101 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/pad_tail.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peek_nth.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peeking_take_while.rs | 154 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/permutations.rs | 277 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/powerset.rs | 90 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/process_results_impl.rs | 97 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/put_back_n_impl.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/rciter_impl.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/repeatn.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/size_hint.rs | 119 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/sources.rs | 183 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tee.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tuple_impl.rs | 331 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unique_impl.rs | 179 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unziptuple.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/with_position.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_eq_impl.rs | 60 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_longest.rs | 83 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/ziptuple.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/adaptors_no_collect.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/flatten_ok.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/macros_hygiene.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/merge_join.rs | 108 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/peeking_take_while.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/quick.rs | 1749 + clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/specializations.rs | 153 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_core.rs | 317 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_std.rs | 1168 + clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/tuples.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/zip.rs | 77 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.codecov.yml | 7 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/dependabot.yml | 6 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/ci.yml | 101 clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/coverage.yml | 34 clamav-1.4.6+dfsg/.cargo/vendor/itertools/CHANGELOG.md | 190 clamav-1.4.6+dfsg/.cargo/vendor/itertools/CONTRIBUTING.md | 189 clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.lock | 740 clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml | 144 clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml.orig | 81 clamav-1.4.6+dfsg/.cargo/vendor/itertools/README.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/bench1.rs | 290 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/combinations.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/mod.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/zipslices.rs | 188 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/fold_specialization.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/k_smallest.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/powerset.rs | 67 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/specializations.rs | 669 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_fold1.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_reduce.rs | 150 clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tuples.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/itertools/clippy.toml | 1 clamav-1.4.6+dfsg/.cargo/vendor/itertools/examples/iris.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/coalesce.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/map.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/mod.rs | 960 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/multi_product.rs | 333 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations.rs | 324 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations_with_replacement.rs | 155 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/concat_impl.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/cons_tuples_impl.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/diff.rs | 71 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/duplicates_impl.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/either_or_both.rs | 314 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/exactly_one_err.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/extrema_set.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/flatten_ok.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/format.rs | 113 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/free.rs | 137 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/group_map.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/groupbylazy.rs | 252 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/grouping_map.rs | 349 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/impl_macros.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/intersperse.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/iter_index.rs | 116 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/k_smallest.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/kmerge_impl.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lazy_buffer.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lib.rs | 2051 +- clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/merge_join.rs | 393 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/minmax.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/multipeek_impl.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/next_array.rs | 269 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/pad_tail.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peek_nth.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peeking_take_while.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/permutations.rs | 331 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/powerset.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/process_results_impl.rs | 95 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/put_back_n_impl.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/rciter_impl.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/repeatn.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/size_hint.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/sources.rs | 98 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/take_while_inclusive.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tee.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tuple_impl.rs | 252 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unique_impl.rs | 117 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unziptuple.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/with_position.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_eq_impl.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_longest.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/ziptuple.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/adaptors_no_collect.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/laziness.rs | 283 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/macros_hygiene.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/merge_join.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/peeking_take_while.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/quick.rs | 572 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/specializations.rs | 498 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_core.rs | 180 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_std.rs | 831 clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/zip.rs | 35 clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/workflows/ci.yml | 108 clamav-1.4.6+dfsg/.cargo/vendor/itoa/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/actions/compile-make/action.yml | 36 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/dependabot.yml | 8 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/main.yml | 110 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/publish.yml | 15 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml | 58 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml.orig | 45 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/README.md | 33 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/error.rs | 95 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/lib.rs | 704 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/unix.rs | 651 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/wasm.rs | 106 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/windows.rs | 290 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client-of-myself.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client.rs | 192 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/helper.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/make-as-a-client.rs | 81 clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/server.rs | 181 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/CHANGELOG.md | 163 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.lock | 661 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.toml | 80 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-MIT | 21 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/README.md | 41 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/appveyor.yml | 20 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/decoding_benchmark.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/examples/decode.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/rust-toolchain | 1 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/mod.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/neon.rs | 221 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/ssse3.rs | 288 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/wasm.rs | 277 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder.rs | 1508 - clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder/lossless.rs | 260 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/error.rs | 75 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/huffman.rs | 346 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/idct.rs | 657 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/lib.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/marker.rs | 136 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/parser.rs | 704 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/upsampler.rs | 250 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/immediate.rs | 79 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/mod.rs | 128 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/multithreaded.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/rayon.rs | 219 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/lib.rs | 170 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon-0.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon-1.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon-2.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/js-sys/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/js-sys/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/lazycell/Cargo.toml.orig | 27 clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/lebe/.github/workflows/rust.yml | 22 clamav-1.4.6+dfsg/.cargo/vendor/lebe/Cargo.toml.orig | 42 clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/libc/Cargo.toml.orig | 146 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.github/workflows/rust.yml | 36 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/CHANGELOG.md | 292 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.lock | 193 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml | 48 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml.orig | 33 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/README.md | 103 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/build.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/ci/script.sh | 45 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/CMakeLists.txt | 182 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltins.h | 34 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltinsMsvc.h | 67 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCommand.h | 179 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCorpus.h | 592 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCrossOver.cpp | 51 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.cpp | 288 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.h | 137 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDefs.h | 55 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDictionary.h | 125 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDriver.cpp | 934 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.def | 50 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.h | 34 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsDlsym.cpp | 51 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWeak.cpp | 54 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWindows.cpp | 83 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCounters.cpp | 34 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersDarwin.cpp | 22 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersWindows.cpp | 80 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFlags.def | 212 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.cpp | 494 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.h | 24 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.cpp | 220 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.h | 118 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOPosix.cpp | 179 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOWindows.cpp | 423 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterceptors.cpp | 254 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterface.h | 79 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInternal.h | 178 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerLoop.cpp | 946 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMain.cpp | 21 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.cpp | 539 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.h | 93 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.cpp | 596 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.h | 156 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerOptions.h | 93 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerPlatform.h | 147 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerRandom.h | 47 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.cpp | 224 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.h | 32 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.cpp | 685 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.h | 298 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.cpp | 237 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.h | 122 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilDarwin.cpp | 175 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilFuchsia.cpp | 619 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilLinux.cpp | 53 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilPosix.cpp | 193 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilWindows.cpp | 266 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerValueBitMap.h | 73 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/README.txt | 1 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/afl/afl_driver.cpp | 267 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/build.sh | 11 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.cpp | 205 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.h | 32 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlowCallbacks.cpp | 86 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/scripts/unbalanced_allocs.py | 100 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/standalone/StandaloneFuzzTargetMain.c | 41 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/CMakeLists.txt | 92 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzedDataProviderUnittest.cpp | 450 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzerUnittest.cpp | 1430 + clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/rust-toolchain | 1 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/src/lib.rs | 749 clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/update-libfuzzer.sh | 27 clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/libloading/.github/workflows/libloading.yml | 105 clamav-1.4.6+dfsg/.cargo/vendor/libloading/Cargo.toml.orig | 33 clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/Cargo.toml.orig | 45 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/Cargo.toml | 60 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/build.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/lib.rs | 116 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/mutex.rs | 964 clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/remutex.rs | 1057 - clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/rwlock.rs | 2886 -- clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/log/.github/workflows/main.yml | 153 clamav-1.4.6+dfsg/.cargo/vendor/log/Cargo.toml.orig | 81 clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml | 38 clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml.orig | 22 clamav-1.4.6+dfsg/.cargo/vendor/loop9/LICENSE | 7 clamav-1.4.6+dfsg/.cargo/vendor/loop9/README.md | 5 clamav-1.4.6+dfsg/.cargo/vendor/loop9/src/lib.rs | 187 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/CHANGELOG.md | 4 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml | 30 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml.orig | 18 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/rustfmt.toml | 5 clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/src/lib.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/memchr/.ignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/memchr/.vim/coc-settings.json | 16 clamav-1.4.6+dfsg/.cargo/vendor/memchr/Cargo.toml.orig | 79 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/bug_report.md | 41 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/custom.md | 21 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/documentation.md | 16 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/feature_request.md | 27 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/question.md | 11 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/bug_fix.md | 27 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/custom.md | 22 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/documentation.md | 21 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Cross.yml | 90 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Features.yml | 23 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/OSX.yml | 40 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Simple.yml | 41 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Valgrind.yml | 24 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.gitmodules | 4 clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/Cargo.toml.orig | 37 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.lock | 103 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml | 57 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml.orig | 54 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE | 4 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-MIT.md | 3 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-ZLIB.md | 3 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Readme.md | 19 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/buffer.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/core.rs | 507 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/mod.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/stored.rs | 305 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/zlib.rs | 112 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/core.rs | 840 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/mod.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/output_buffer.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/stream.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/lib.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/big_array.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/mod.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/shared.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/FUNDING.yml | 3 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/build_push.yml | 123 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/nightly_fuzzing.yml | 17 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/no-response.yml | 26 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/publish_release.yml | 23 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.lock | 174 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml | 79 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml.orig | 49 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE-APACHE.md | 201 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE.md | 26 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/README.md | 74 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chad.rs | 172 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chromaticity.rs | 143 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/cicp.rs | 642 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator.rs | 1037 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator_q0_15.rs | 1030 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3.rs | 350 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3_q0_15.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/mod.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz.rs | 311 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_opt.rs | 314 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13.rs | 314 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13_opt.rs | 302 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3.rs | 350 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3_q0_15.rs | 232 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/mod.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_opt.rs | 417 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_q2_13_opt.rs | 467 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/bpc.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb.rs | 388 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb_extended.rs | 383 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/interpolator.rs | 599 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/finalizers.rs | 118 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md3x3.rs | 483 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md4x3.rs | 321 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_3xn.rs | 284 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_nx3.rs | 294 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_pipeline.rs | 393 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/mod.rs | 56 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/pcs_stages.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/rgb_xyz.rs | 162 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/stages.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_lab.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_rgb.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x3.rs | 428 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x4.rs | 249 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut4.rs | 360 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut_transforms.rs | 802 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab.rs | 559 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab4x3.rs | 307 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mba3x4.rs | 302 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_lut.rs | 728 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_luts_factory.rs | 188 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mod.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator.rs | 869 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator_q0_15.rs | 915 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3.rs | 329 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3_q0_15.rs | 226 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/mod.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz.rs | 440 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_opt.rs | 429 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q1_30_opt.rs | 408 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13.rs | 424 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13_opt.rs | 403 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3.rs | 341 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3_q0_15.rs | 242 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/prelude_lut_xyz_rgb.rs | 328 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray.rs | 189 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray_extended.rs | 181 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb_xyz_factory.rs | 395 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz.rs | 899 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_fixed.rs | 560 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_float.rs | 330 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator.rs | 443 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator_q0_15.rs | 442 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3.rs | 333 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3_q0_15.rs | 219 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/mod.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz.rs | 154 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_opt.rs | 157 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13.rs | 177 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13_opt.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3.rs | 349 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3_q0_15.rs | 236 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_3.rs | 266 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_4.rs | 274 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut4_to_3.rs | 351 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/xyz_lab.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dat.rs | 154 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/defaults.rs | 604 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dt_ucs.rs | 359 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/err.rs | 143 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamma.rs | 1078 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamut.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/helpers.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/ictcp.rs | 192 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzazbz.rs | 434 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzczhz.rs | 375 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lab.rs | 240 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lib.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lut_hint.rs | 106 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/luv.rs | 698 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/curve_shape.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/degeneration.rs | 60 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/discontinuity.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/mod.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/monotonic.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/slope_limit.rs | 84 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/math/mod.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matrix.rs | 1272 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/mlaf.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/nd_array.rs | 1404 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklab.rs | 354 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklch.rs | 294 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/profile.rs | 1385 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/reader.rs | 1004 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/rgb.rs | 723 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/safe_math.rs | 103 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/srlab2.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/tag.rs | 271 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/transform.rs | 1334 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/trc.rs | 1583 + clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/writer.rs | 925 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/xyy.rs | 98 clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/yrg.rs | 177 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.travis.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.lock | 7 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml | 36 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml.orig | 15 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/README.md | 42 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/examples/simple.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/src/lib.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/tests/check.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/CHANGELOG.md | 1551 + clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.lock | 282 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml | 168 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml.orig | 142 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/LICENSE | 20 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/README.md | 331 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/doc/nom_recipes.md | 395 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/complete.rs | 197 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/mod.rs | 179 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/streaming.rs | 170 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/mod.rs | 267 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/tests.rs | 142 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/complete.rs | 756 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/mod.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/streaming.rs | 700 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/tests.rs | 636 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/complete.rs | 1227 + clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/mod.rs | 116 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/streaming.rs | 1182 + clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/tests.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/mod.rs | 809 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/tests.rs | 275 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/error.rs | 831 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/internal.rs | 489 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/lib.rs | 464 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/macros.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/mod.rs | 1049 + clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/tests.rs | 534 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/complete.rs | 2126 ++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/mod.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/streaming.rs | 2206 ++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/mod.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/tests.rs | 290 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/str.rs | 536 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/traits.rs | 1441 + clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic_ast.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/css.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/custom_errors.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/escaped.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/float.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/fnmut.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini.rs | 207 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini_str.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/issues.rs | 242 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/json.rs | 236 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/mp4.rs | 320 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/multiline.rs | 31 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/overflow.rs | 145 clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/reborrow_fold.rs | 31 clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/nom/CHANGELOG.md | 202 clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.lock | 222 clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml | 86 clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml.orig | 149 clamav-1.4.6+dfsg/.cargo/vendor/nom/README.md | 114 clamav-1.4.6+dfsg/.cargo/vendor/nom/doc/nom_recipes.md | 80 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/complete.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/mod.rs | 35 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/streaming.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/mod.rs | 243 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/tests.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/complete.rs | 516 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/mod.rs | 1038 + clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/streaming.rs | 447 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/tests.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/complete.rs | 396 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/mod.rs | 410 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/streaming.rs | 370 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/tests.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/mod.rs | 701 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/tests.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/error.rs | 405 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/internal.rs | 598 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/lib.rs | 88 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/mod.rs | 1425 + clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/tests.rs | 397 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/complete.rs | 506 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/mod.rs | 1467 + clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/streaming.rs | 510 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/mod.rs | 222 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/tests.rs | 35 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/str.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/nom/src/traits.rs | 1558 - clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic_ast.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/css.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/custom_errors.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/expression_ast.rs | 169 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/float.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/fnmut.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini_str.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/issues.rs | 119 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/json.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/mp4.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/multiline.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/overflow.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/reborrow_fold.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml | 26 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml.orig | 15 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/README.md | 17 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/src/lib.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/serde.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/wasm_bindgen.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml | 107 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml.orig | 75 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/README.md | 84 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/RELEASES.md | 343 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/bigint.rs | 450 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/factorial.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/gcd.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/rng/mod.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/roots.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/shootout-pidigits.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint.rs | 1229 + clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/addition.rs | 239 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/arbitrary.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/bits.rs | 531 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/convert.rs | 472 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/division.rs | 513 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/multiplication.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/power.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/serde.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/shift.rs | 107 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/subtraction.rs | 300 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigrand.rs | 285 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint.rs | 1206 + clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/addition.rs | 256 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/arbitrary.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/bits.rs | 93 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/convert.rs | 866 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/division.rs | 704 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/iter.rs | 361 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/monty.rs | 226 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/multiplication.rs | 626 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/power.rs | 258 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/serde.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/shift.rs | 173 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/subtraction.rs | 312 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/lib.rs | 268 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/macros.rs | 473 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint.rs | 1475 + clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_bitwise.rs | 177 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_scalar.rs | 157 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint.rs | 1921 + clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint_scalar.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/consts/mod.rs | 51 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/fuzzed.rs | 185 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/macros/mod.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/modpow.rs | 181 clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/roots.rs | 159 clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-complex/Cargo.toml.orig | 53 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml | 68 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml.orig | 48 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/README.md | 69 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/RELEASES.md | 129 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/src/lib.rs | 1004 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/empty_enum.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-16.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-6.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-9.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2015.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2018.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype.rs | 108 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/no_implicit_prelude.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/num_derive_without_num.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2015.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2018.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/with_custom_values.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-integer/Cargo.toml.orig | 30 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml | 79 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml.orig | 47 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/README.md | 51 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/RELEASES.md | 174 clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/lib.rs | 3131 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/pow.rs | 173 clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/num-traits/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.github/workflows/ci.yaml | 28 clamav-1.4.6+dfsg/.cargo/vendor/once_cell/Cargo.toml.orig | 86 clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/workflows/ci.yml | 82 clamav-1.4.6+dfsg/.cargo/vendor/paste/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/dependabot.yml | 11 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/release-butler.toml | 13 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/ci.yml | 102 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/release.yml | 25 clamav-1.4.6+dfsg/.cargo/vendor/pastey/.vscode/settings.json | 3 clamav-1.4.6+dfsg/.cargo/vendor/pastey/CHANGELOG.md | 27 clamav-1.4.6+dfsg/.cargo/vendor/pastey/CONTRIBUTING.md | 61 clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.lock | 7 clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml | 45 clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml.orig | 21 clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/pastey/README.md | 243 clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/attr.rs | 171 clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/error.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/lib.rs | 326 clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/segment.rs | 281 clamav-1.4.6+dfsg/.cargo/vendor/pastey/test.sh | 33 clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.travis.yml | 18 clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/png/CHANGES.md | 107 clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.lock | 1756 - clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml | 85 clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml.orig | 75 clamav-1.4.6+dfsg/.cargo/vendor/png/README.md | 19 clamav-1.4.6+dfsg/.cargo/vendor/png/benches/adam7.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/png/benches/decoder.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/png/benches/unfilter.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/png/examples/change-png-info.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/png/examples/corpus-bench.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/png/examples/pngcheck.rs | 182 clamav-1.4.6+dfsg/.cargo/vendor/png/examples/show.rs | 198 clamav-1.4.6+dfsg/.cargo/vendor/png/src/adam7.rs | 1185 - clamav-1.4.6+dfsg/.cargo/vendor/png/src/benchable_apis.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/png/src/chunk.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/png/src/common.rs | 337 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/interlace_info.rs | 128 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/mod.rs | 663 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/read_decoder.rs | 153 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/stream.rs | 1743 + clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform/palette.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/unfiltering_buffer.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/zlib.rs | 229 clamav-1.4.6+dfsg/.cargo/vendor/png/src/encoder.rs | 734 clamav-1.4.6+dfsg/.cargo/vendor/png/src/filter.rs | 503 clamav-1.4.6+dfsg/.cargo/vendor/png/src/lib.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/png/src/test_utils.rs | 1 clamav-1.4.6+dfsg/.cargo/vendor/png/src/text_metadata.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/CHANGELOG.md | 10 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml | 52 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/generic.rs | 872 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/lib.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/soft.rs | 480 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/types.rs | 298 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/mod.rs | 441 clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/sse2.rs | 1711 + clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/workflows/ci.yml | 113 clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/Cargo.toml.orig | 41 clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/examples/.tokeignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/primal-check/Cargo.toml.orig | 24 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/workflows/ci.yml | 232 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.lock | 326 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml | 67 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml.orig | 67 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/README.md | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build.rs | 169 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build/probe.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/extra.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/fallback.rs | 416 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/lib.rs | 366 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/location.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/num.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/parse.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span.rs | 51 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_file.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_location.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rcvec.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rustc_literal_escaper.rs | 701 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/wrapper.rs | 303 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/comments.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/features.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/marker.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test.rs | 231 clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test_size.rs | 65 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml | 52 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml.orig | 27 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/README.md | 246 clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/src/lib.rs | 140 clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.lock | 786 clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml | 107 clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml.orig | 52 clamav-1.4.6+dfsg/.cargo/vendor/profiling/README.md | 246 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/empty_impl.rs | 52 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/lib.rs | 167 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/optick_impl.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/puffin_impl.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/superluminal_impl.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracing_impl.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracy_impl.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/type_check_impl.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.lock | 25 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml | 56 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE-APACHE.md | 201 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE.md | 26 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/README.md | 5 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acos.rs | 349 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acosf.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospi.rs | 369 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospif.rs | 136 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin.rs | 490 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin_eval_dyadic.rs | 1478 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinf.rs | 203 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpi.rs | 370 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpif.rs | 294 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha0.rs | 292 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha1.rs | 296 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/bessel_exp.rs | 157 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta0.rs | 260 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta1.rs | 264 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0.rs | 1118 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0e.rs | 834 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0ef.rs | 335 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0f.rs | 354 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1.rs | 656 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1e.rs | 460 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1ef.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1f.rs | 210 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2.rs | 587 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2f.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0.rs | 631 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_remez.rs | 1347 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_taylor.rs | 1292 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f.rs | 425 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f_coeffs.rs | 1050 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1.rs | 702 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs.rs | 1543 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs_taylor.rs | 1282 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f.rs | 427 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f_coeffs.rs | 857 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpi.rs | 408 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpif.rs | 417 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0.rs | 643 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0e.rs | 434 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0ef.rs | 184 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0f.rs | 184 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1.rs | 644 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1e.rs | 425 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1ef.rs | 240 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1f.rs | 240 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k2f.rs | 262 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/mod.rs | 107 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/trigo_bessel.rs | 285 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0.rs | 1022 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs.rs | 1517 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs_taylor.rs | 1478 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f.rs | 341 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f_coeffs.rs | 1236 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1.rs | 1117 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs.rs | 1068 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs_taylor.rs | 1030 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f.rs | 353 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f_coeffs.rs | 923 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bits.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/common.rs | 437 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_d.rs | 485 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1.rs | 573 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1f.rs | 439 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compoundf.rs | 1000 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/mod.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1f.rs | 260 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cosm1.rs | 219 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/csc.rs | 152 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrt.rs | 231 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrtf.rs | 170 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/mod.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrt.rs | 311 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrtf.rs | 176 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/double_double.rs | 1095 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/dyadic_float.rs | 881 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf.rs | 319 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf_poly.rs | 177 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfc.rs | 960 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcx.rs | 421 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcxf.rs | 229 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erff.rs | 472 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erffc.rs | 345 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverf.rs | 692 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfc.rs | 704 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfcf.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverff.rs | 359 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/mod.rs | 56 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf.rs | 233 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf_poly.rs | 1331 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerff.rs | 468 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/auxiliary.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp.rs | 444 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10.rs | 271 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10f.rs | 256 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1.rs | 591 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1f.rs | 174 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2.rs | 268 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2f.rs | 355 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1.rs | 696 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1f.rs | 188 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp_f128.rs | 289 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expf.rs | 841 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1.rs | 542 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1f.rs | 232 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logistic.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logisticf.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/mod.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/beta.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaf.rs | 95 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betainc.rs | 190 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaincf.rs | 187 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma.rs | 455 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma_coeffs.rs | 839 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digammaf.rs | 416 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_p.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_pf.rs | 163 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_q.rs | 241 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_qf.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma.rs | 1129 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_r.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_rf.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgammaf.rs | 90 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbeta.rs | 95 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbetaf.rs | 92 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/mod.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgamma.rs | 344 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgammaf.rs | 233 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigamma.rs | 602 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigammaf.rs | 266 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acosh.rs | 693 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acoshf.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinh.rs | 349 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinhf.rs | 400 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanh.rs | 407 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanhf.rs | 98 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/cosh.rs | 291 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/coshf.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/mod.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinh.rs | 329 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinhf.rs | 232 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanh.rs | 277 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanhf.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/lib.rs | 153 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log.rs | 120 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log_dd.rs | 369 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log.rs | 465 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10.rs | 500 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd_coeffs.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10f.rs | 281 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1.rs | 269 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1_tables.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1f.rs | 332 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td.rs | 132 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td_coeffs.rs | 227 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p.rs | 814 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dd.rs | 258 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic.rs | 129 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic_tables.rs | 865 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pf.rs | 220 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmx.rs | 392 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmxf.rs | 105 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2.rs | 678 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd.rs | 120 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd_coeffs.rs | 228 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2f.rs | 395 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1.rs | 486 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_dyadic_tables.rs | 2503 ++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_tables.rs | 822 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1f.rs | 329 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td.rs | 119 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td_coeffs.rs | 229 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd.rs | 218 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd_coeffs.rs | 228 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dyadic.rs | 3134 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_range_reduction.rs | 163 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td.rs | 130 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td_table.rs | 229 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logf.rs | 528 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logit.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logitf.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/mod.rs | 104 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/polyeval.rs | 1074 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow.rs | 562 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_exec.rs | 772 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_tables.rs | 1118 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf.rs | 895 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf_tables.rs | 560 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/ceil.rs | 172 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/floor.rs | 181 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/mod.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rint.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rintf.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round.rs | 189 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round_ties_even.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/trunc.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/truncf.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sec.rs | 149 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/shared_eval.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin.rs | 524 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction.rs | 434 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction_pi.rs | 93 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosf.rs | 208 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosm1f.rs | 110 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cospif.rs | 218 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cscf.rs | 220 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/mod.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/secf.rs | 219 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincf.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf.rs | 267 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf_eval.rs | 453 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincospif.rs | 313 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincpif.rs | 212 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinf.rs | 206 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinmxf.rs | 110 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinpif.rs | 264 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_helper.rs | 294 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_table.rs | 287 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinc.rs | 147 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos.rs | 253 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_dyadic.rs | 558 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce.rs | 555 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce_tables.rs | 817 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi.rs | 1274 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi_tables.rs | 169 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincpi.rs | 485 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinmx.rs | 212 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/mod.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrt.rs | 149 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrtf.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1.rs | 225 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1f.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrtf.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan.rs | 419 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2.rs | 1029 + clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2f.rs | 323 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pi.rs | 445 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pif.rs | 185 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanf.rs | 179 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpi.rs | 471 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpif.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cot.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotf.rs | 112 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpi.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpif.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/evalf.rs | 214 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/mod.rs | 65 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tan.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanf.rs | 216 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi.rs | 235 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi_table.rs | 430 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpif.rs | 197 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetus.rs | 142 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetusf.rs | 134 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot.rs | 295 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot3f.rs | 125 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypotf.rs | 139 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/mod.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triple_double.rs | 389 clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/qoi/.github/workflows/ci.yml | 37 clamav-1.4.6+dfsg/.cargo/vendor/qoi/.gitmodules | 3 clamav-1.4.6+dfsg/.cargo/vendor/qoi/Cargo.toml.orig | 45 clamav-1.4.6+dfsg/.cargo/vendor/qoi/ext/qoi/.gitignore | 5 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.travis.yml | 31 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.lock | 5 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml | 24 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml.orig | 14 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-APACHE | 202 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-MIT | 19 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/README.rst | 66 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/bulk.yaml | 8 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/examples/context.rs | 43 clamav-1.4.6+dfsg/.cargo/vendor/quick-error/src/lib.rs | 1336 + clamav-1.4.6+dfsg/.cargo/vendor/quick-error/vagga.yaml | 36 clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/workflows/ci.yml | 104 clamav-1.4.6+dfsg/.cargo/vendor/quote/Cargo.toml.orig | 36 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/publish.yml | 39 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/rust-tests.yml | 125 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/AUTHORS | 74 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.lock | 16 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml | 70 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml.orig | 51 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Makefile | 85 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/NEWS.md | 301 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/README.md | 99 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/freestanding.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/gop-query.rs | 188 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/hello-world.rs | 55 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/base.rs | 993 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/hii.rs | 1300 + clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/lib.rs | 182 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/absolute_pointer.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/block_io.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/bus_specific_driver_override.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debug_support.rs | 835 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debugport.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/decompress.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path.rs | 82 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_from_text.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_to_text.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_utilities.rs | 63 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io2.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_binding.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_diagnostics2.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_family_override.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/file.rs | 183 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/graphics_output.rs | 103 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_database.rs | 299 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font.rs | 87 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font_ex.rs | 107 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_package_list.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_string.rs | 71 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip4.rs | 202 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip6.rs | 264 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file2.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image_device_path.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/managed_network.rs | 147 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/memory_attribute.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/mp_services.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/pci_io.rs | 203 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/platform_driver_override.rs | 46 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/rng.rs | 83 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/service_binding.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell.rs | 295 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_dynamic_command.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_parameters.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_file_system.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_network.rs | 196 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input_ex.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_output.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp4.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp6.rs | 202 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/timestamp.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp4.rs | 151 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp6.rs | 137 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/system.rs | 1130 + clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor/intel/console_control.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rand/CHANGELOG.md | 822 clamav-1.4.6+dfsg/.cargo/vendor/rand/COPYRIGHT | 12 clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.lock | 280 clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml | 124 clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml.orig | 84 clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/rand/README.md | 120 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/bernoulli.rs | 243 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/distribution.rs | 269 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/float.rs | 344 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/integer.rs | 307 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/mod.rs | 214 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/other.rs | 444 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/slice.rs | 167 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform.rs | 622 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_float.rs | 454 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_int.rs | 903 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_other.rs | 319 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/utils.rs | 408 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/mod.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/weighted_index.rs | 631 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/lib.rs | 360 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/prelude.rs | 35 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rng.rs | 657 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mock.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mod.rs | 110 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/reseeding.rs | 295 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/small.rs | 120 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/std.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/thread.rs | 212 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro128plusplus.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro256plusplus.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/coin_flipper.rs | 160 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/increasing_uniform.rs | 108 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/index.rs | 696 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/iterator.rs | 672 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/mod.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/slice.rs | 770 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/CHANGELOG.md | 46 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/COPYRIGHT | 12 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.lock | 232 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml | 81 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml.orig | 36 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/README.md | 48 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/chacha.rs | 651 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/guts.rs | 287 clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/lib.rs | 106 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/CHANGELOG.md | 125 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/COPYRIGHT | 12 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.lock | 178 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml | 67 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-APACHE | 187 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/README.md | 56 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/block.rs | 534 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/impls.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/le.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/lib.rs | 771 clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/os.rs | 115 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.lock | 2523 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml | 385 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml.orig | 232 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/LICENSE | 25 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/PATENTS | 108 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/README.md | 188 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/build.rs | 279 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/cbindgen.toml | 20 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/activity.rs | 275 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/by_gop.rs | 382 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/data.rs | 382 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/mod.rs | 368 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/color.rs | 270 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/encoder.rs | 347 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/mod.rs | 458 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/rate.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/speedsettings.rs | 451 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/context.rs | 471 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/internal.rs | 1735 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/lookahead.rs | 284 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/mod.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/test.rs | 2381 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/util.rs | 301 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef.S | 540 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef16.S | 233 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef_tmpl.S | 515 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred.S | 2937 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred16.S | 3254 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx.S | 3343 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx16.S | 3625 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter.S | 868 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter16.S | 859 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration.S | 791 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration16.S | 801 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_common.S | 453 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_tmpl.S | 600 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc.S | 3340 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc16.S | 3658 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/msac.S | 575 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/util.S | 184 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef.S | 520 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef16.S | 229 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_dist.S | 250 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_tmpl.S | 511 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred.S | 5245 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred16.S | 5639 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx.S | 3270 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx16.S | 3648 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter.S | 1129 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter16.S | 925 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration.S | 1336 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration16.S | 1419 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_common.S | 432 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_tmpl.S | 597 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc.S | 3310 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc16.S | 3611 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/msac.S | 480 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sad.S | 499 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/satd.S | 1473 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sse.S | 522 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/util.S | 229 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/asm.S | 291 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/tables.S | 337 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/cdef.rs | 414 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/cdef_dist.rs | 191 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/mod.rs | 629 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/sse.rs | 252 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mc.rs | 490 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mod.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/predict.rs | 701 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/forward.rs | 461 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/inverse.rs | 322 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/mod.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/mod.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/cdef_dist.rs | 164 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/mod.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/sse.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/mod.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/predict.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/forward.rs | 111 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/inverse.rs | 274 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/mod.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/cdef.rs | 501 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/cdef_dist.rs | 243 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/mod.rs | 970 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/sse.rs | 224 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/ec.rs | 122 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/lrf.rs | 646 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mc.rs | 833 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mod.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/predict.rs | 928 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/quantize.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/forward.rs | 457 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/inverse.rs | 563 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/mod.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/common.rs | 721 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/mod.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/y4m.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/error.rs | 51 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/kv.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/ivf.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/mod.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/y4m.rs | 105 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e-ch.rs | 600 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e.rs | 584 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/stats.rs | 777 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/capi.rs | 1529 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cdef.rs | 625 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/block_unit.rs | 2017 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/cdf_context.rs | 745 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/frame_header.rs | 275 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/mod.rs | 246 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/partition_unit.rs | 550 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/superblock_unit.rs | 127 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/transform_unit.rs | 986 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/aarch64.rs | 116 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/mod.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/rust.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/x86.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/deblock.rs | 1668 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/dist.rs | 534 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ec.rs | 1152 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/encoder.rs | 3858 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/entropymode.rs | 1083 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ext/x86/x86inc.asm | 1902 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/mod.rs | 104 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/plane.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/fuzzing.rs | 384 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/header.rs | 1244 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/levels.rs | 116 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lib.rs | 329 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lrf.rs | 1586 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/mc.rs | 480 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/me.rs | 1523 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/partition.rs | 1061 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/predict.rs | 1694 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/mod.rs | 385 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/tables.rs | 207 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rate.rs | 1647 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo.rs | 2752 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo_tables.rs | 1083 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/recon_intra.rs | 450 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/scan_order.rs | 1321 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/segmentation.rs | 196 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/stats.rs | 87 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/aom.rs | 174 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/dav1d.rs | 185 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/mod.rs | 1073 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/mod.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/plane_region.rs | 787 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_blocks.rs | 310 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_motion_stats.rs | 146 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_restoration_state.rs | 426 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_state.rs | 265 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tiler.rs | 874 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/token_cdfs.rs | 3984 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward.rs | 162 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward_shared.rs | 1799 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/inverse.rs | 1712 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/mod.rs | 619 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/align.rs | 77 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/cdf.rs | 136 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/kmeans.rs | 123 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/logexp.rs | 360 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/mod.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/pixel.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/uninit.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx2.asm | 877 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx512.asm | 622 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_sse.asm | 1033 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx2.asm | 1772 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx512.asm | 860 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_dist.asm | 233 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_rav1e.asm | 266 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_sse.asm | 1357 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx2.asm | 2248 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx512.asm | 932 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_sse.asm | 3421 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx2.asm | 2107 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx512.asm | 813 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_common.asm | 46 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_sse.asm | 3233 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx2.asm | 4992 ++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx512.asm | 833 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_sse.asm | 4076 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx2.asm | 5387 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx512.asm | 1432 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_sse.asm | 5398 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx2.asm | 8599 ++++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx512.asm | 6056 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_sse.asm | 8135 +++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx2.asm | 5542 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx512.asm | 7507 +++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_sse.asm | 6533 ++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx2.asm | 1161 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx512.asm | 912 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_sse.asm | 1793 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx2.asm | 1569 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx512.asm | 1534 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_sse.asm | 2348 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx2.asm | 2540 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx512.asm | 2524 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_sse.asm | 3723 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx2.asm | 2237 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx512.asm | 2122 ++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_sse.asm | 3681 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx2.asm | 5879 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx512.asm | 4858 ++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_sse.asm | 8731 ++++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx2.asm | 5669 +++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx512.asm | 4538 ++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_sse.asm | 9599 +++++++++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/me.asm | 98 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/msac.asm | 667 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_avx.asm | 204 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_sse2.asm | 354 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd.asm | 979 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd16_avx2.asm | 1129 + clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sse.asm | 511 clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/tables.asm | 563 clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.lock | 794 clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml | 102 clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml.orig | 44 clamav-1.4.6+dfsg/.cargo/vendor/ravif/LICENSE | 29 clamav-1.4.6+dfsg/.cargo/vendor/ravif/README.md | 7 clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/av1encoder.rs | 736 clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/dirtyalpha.rs | 135 clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/error.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/lib.rs | 143 clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/Cargo.toml.orig | 68 clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rayon/Cargo.toml.orig | 39 clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/Cargo.toml.orig | 110 clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/Cargo.toml.orig | 51 clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/regex/.vim/coc-settings.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/regex/Cargo.toml.orig | 261 clamav-1.4.6+dfsg/.cargo/vendor/regex/record/old-bench-log/.gitignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.lock | 193 clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml | 110 clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml.orig | 58 clamav-1.4.6+dfsg/.cargo/vendor/rgb/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/rgb/README.md | 89 clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/example.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/serde.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/as_bytes.rs | 138 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/bytemuck_impl.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/abgr.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/argb.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgr.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgra.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_a.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_alpha.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/grb.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgb.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgba.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/inherent_impls.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/alt.rs | 301 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/array.rs | 112 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/mod.rs | 504 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/tuple.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/ops.rs | 498 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/pixel.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgb.rs | 238 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgba.rs | 434 clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/lib.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rustdct/Cargo.toml.orig | 21 clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.github/workflows/run_test.yml | 147 clamav-1.4.6+dfsg/.cargo/vendor/rustfft/Cargo.toml.orig | 50 clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/rustix/Cargo.toml.orig | 250 clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/workflows/ci.yml | 113 clamav-1.4.6+dfsg/.cargo/vendor/ryu/Cargo.toml.orig | 35 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.lock | 7 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.toml | 43 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/README.md | 102 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/examples/readme.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/src/lib.rs | 595 clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/serde/Cargo.toml.orig | 69 clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.github/workflows/ci.yml | 138 clamav-1.4.6+dfsg/.cargo/vendor/serde_json/Cargo.toml.orig | 88 clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/sha1/Cargo.toml.orig | 39 clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/sha2/Cargo.toml.orig | 43 clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/shlex/.github/workflows/test.yml | 36 clamav-1.4.6+dfsg/.cargo/vendor/shlex/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/build.yaml | 173 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/fuzz.yaml | 59 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/publish.yaml | 35 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.rustfmt.toml | 2 clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/Cargo.toml.orig | 39 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo_vcs_info.json | 5 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml | 28 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml.orig | 17 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/README.md | 18 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/src/lib.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/tests/cold_for.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.github/workflows/main.yml | 110 clamav-1.4.6+dfsg/.cargo/vendor/smallvec/Cargo.toml.orig | 50 clamav-1.4.6+dfsg/.cargo/vendor/spin/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/spin/CHANGELOG.md | 146 clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.lock | 623 clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.toml | 80 clamav-1.4.6+dfsg/.cargo/vendor/spin/LICENSE | 21 clamav-1.4.6+dfsg/.cargo/vendor/spin/README.md | 143 clamav-1.4.6+dfsg/.cargo/vendor/spin/benches/mutex.rs | 126 clamav-1.4.6+dfsg/.cargo/vendor/spin/examples/debug.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/spin/script/doc-upload.cfg | 3 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/barrier.rs | 239 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lazy.rs | 118 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lib.rs | 221 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex.rs | 340 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/fair.rs | 735 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/spin.rs | 543 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/ticket.rs | 537 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/once.rs | 789 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/relax.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/spin/src/rwlock.rs | 1165 - clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.lock | 7 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml | 41 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml.orig | 17 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-MIT | 25 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/README.md | 23 clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/src/lib.rs | 202 clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/Cargo.toml.orig | 91 clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.lock | 2093 ++ clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml | 219 clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml.orig | 95 clamav-1.4.6+dfsg/.cargo/vendor/syn/README.md | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/file.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/rust.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/attr.rs | 103 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/buffer.rs | 191 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/classify.rs | 311 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/custom_punctuation.rs | 3 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/data.rs | 193 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/derive.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/discouraged.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/drops.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/error.rs | 93 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/expr.rs | 2096 +- clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ext.rs | 45 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/file.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/fixup.rs | 773 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/clone.rs | 418 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/debug.rs | 430 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/eq.rs | 768 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/fold.rs | 1117 - clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/hash.rs | 441 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/token.css | 737 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/visit.rs | 799 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen/visit_mut.rs | 1172 - clamav-1.4.6+dfsg/.cargo/vendor/syn/src/gen_helper.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/generics.rs | 661 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/group.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ident.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/item.rs | 398 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lib.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lifetime.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lit.rs | 440 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lookahead.rs | 195 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/mac.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/macros.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/op.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse.rs | 108 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_macro_input.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_quote.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/pat.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/path.rs | 283 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/precedence.rs | 210 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/punctuated.rs | 110 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/restriction.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/scan_expr.rs | 268 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/stmt.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/token.rs | 145 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/tt.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ty.rs | 207 clamav-1.4.6+dfsg/.cargo/vendor/syn/src/verbatim.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/eq.rs | 274 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/mod.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/parse.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/visit.rs | 119 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/gen.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/mod.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/macros/mod.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/repo/mod.rs | 365 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/snapshot/mod.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_asyncness.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_attribute.rs | 54 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_derive_input.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_expr.rs | 1250 + clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_generics.rs | 104 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_grouping.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_item.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_iterators.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_lit.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_meta.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_buffer.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_quote.rs | 42 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_stream.rs | 28 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_pat.rs | 30 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_path.rs | 76 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_precedence.rs | 175 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_punctuated.rs | 92 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_receiver.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_round_trip.rs | 103 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_shebang.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_size.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_stmt.rs | 55 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_token_trees.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_ty.rs | 134 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_unparenthesize.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_visibility.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/dependabot.yml | 10 clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/workflows/ci.yml | 85 clamav-1.4.6+dfsg/.cargo/vendor/tempfile/Cargo.toml.orig | 37 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/workflows/ci.yml | 106 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml | 48 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/README.md | 222 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build.rs | 121 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build/probe.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/rust-toolchain.toml | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/aserror.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/display.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/lib.rs | 260 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/provide.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/compiletest.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_backtrace.rs | 274 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_deprecated.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_display.rs | 358 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_error.rs | 56 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_expr.rs | 88 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_from.rs | 64 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_generics.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_lints.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_option.rs | 105 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_path.rs | 37 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_source.rs | 65 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_transparent.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.stderr | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.stderr | 16 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.stderr | 13 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.stderr | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.stderr | 18 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.stderr | 18 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml | 36 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml.orig | 21 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-APACHE | 176 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/ast.rs | 161 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/attr.rs | 247 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/expand.rs | 562 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/fmt.rs | 173 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/generics.rs | 83 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/lib.rs | 36 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/prop.rs | 147 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/span.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/valid.rs | 237 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.lock | 47 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml | 24 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/ast.rs | 106 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/attr.rs | 157 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/expand.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fallback.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fmt.rs | 350 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/generics.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/lib.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/prop.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/scan_expr.rs | 264 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/span.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/unraw.rs | 142 clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/valid.rs | 87 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/workflows/ci.yml | 128 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.lock | 295 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml | 83 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml.orig | 50 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/README.md | 44 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build/probe.rs | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/aserror.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/display.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/lib.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/private.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/provide.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/var.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/compiletest.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_backtrace.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_deprecated.rs | 10 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_display.rs | 154 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_error.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_expr.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_generics.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_lints.rs | 80 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_option.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_path.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_source.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_transparent.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/concat-display.stderr | 4 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.stderr | 18 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.stderr | 24 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/fallback-impl-with-display.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/from-not-source.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/lifetime.rs | 2 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/missing-display.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.stderr | 30 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.stderr | 21 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr | 4 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr | 4 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.rs | 9 clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.stderr | 21 clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/tiff/.github/workflows/rust.yml | 94 clamav-1.4.6+dfsg/.cargo/vendor/tiff/CHANGES.md | 59 clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock | 841 clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock.msrv | 638 clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml | 93 clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml.orig | 47 clamav-1.4.6+dfsg/.cargo/vendor/tiff/README.md | 6 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/bytecast.rs | 6 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/cycles.rs | 169 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/ifd.rs | 197 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/image.rs | 298 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/mod.rs | 1367 - clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/stream.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/tag_reader.rs | 44 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/directory.rs | 166 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/colortype.rs | 108 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/deflate.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/lzw.rs | 3 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/mod.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/packbits.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/uncompressed.rs | 3 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/mod.rs | 458 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/tiff_value.rs | 58 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/writer.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/error.rs | 497 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/lib.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/tags.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/COPYRIGHT | 4 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_fp16_images.rs | 195 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_geotiff_images.rs | 63 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_images.rs | 194 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images.rs | 155 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images_with_compression.rs | 39 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/predict.rs | 231 clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/subsubifds.rs | 41 clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.github/workflows/rust.yml | 47 clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/Cargo.toml.orig | 94 clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/toml/Cargo.toml.orig | 52 clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/transpose/Cargo.toml.orig | 28 clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/check.yml | 96 clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/publish.yml | 27 clamav-1.4.6+dfsg/.cargo/vendor/typenum/Cargo.toml.orig | 40 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/FUNDING.yml | 1 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/workflows/ci.yml | 89 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/Cargo.toml.orig | 34 clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/tests/fst/.gitignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/Cargo.toml.orig | 38 clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/uuid/Cargo.toml.orig | 193 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.github/workflows/crate.yml | 90 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/CHANGELOG.md | 39 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.lock | 745 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml | 80 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml.orig | 59 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/LICENSE | 25 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/README.md | 11 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/benches/bench.rs | 125 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/clippy.toml | 1 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/frame.rs | 67 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/lib.rs | 89 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/math.rs | 136 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/pixel.rs | 316 clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/plane.rs | 1243 + clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/version_check/.github/workflows/ci.yml | 42 clamav-1.4.6+dfsg/.cargo/vendor/version_check/.travis.yml | 6 clamav-1.4.6+dfsg/.cargo/vendor/version_check/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.lock | 41 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml | 97 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml.orig | 48 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/README.md | 117 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command-no_std.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command.rs | 14 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world-no_std.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world.rs | 7 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy-no_std.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy.rs | 25 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/command.rs | 627 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/mod.rs | 8 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/std.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/imports.rs |10238 ++++++++++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/lib.rs | 296 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/proxy.rs | 7447 +++++++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/command.wit | 10 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/environment.wit | 22 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/exit.wit | 17 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/imports.wit | 36 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/run.wit | 6 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/stdio.wit | 26 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/terminal.wit | 62 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/monotonic-clock.wit | 50 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/timezone.wit | 55 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/wall-clock.wit | 46 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/world.wit | 11 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/preopens.wit | 11 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/types.wit | 676 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/world.wit | 9 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/handler.wit | 49 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/proxy.wit | 50 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/types.wit | 688 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/error.wit | 34 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/poll.wit | 47 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/streams.wit | 290 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/world.wit | 10 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure-seed.wit | 27 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure.wit | 25 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/random.wit | 29 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/world.wit | 13 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/instance-network.wit | 11 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/ip-name-lookup.wit | 56 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/network.wit | 169 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp-create-socket.wit | 30 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp.wit | 387 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp-create-socket.wit | 30 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp.wit | 288 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/world.wit | 19 clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/wasi-crate.wit | 1 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/Cargo.toml.orig | 26 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/Cargo.toml.orig | 25 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/Cargo.toml.orig | 31 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/Cargo.toml.orig | 19 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo/config | 17 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/action.yml | 6 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/main.js | 24 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/workflows/main.yml | 520 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/Cargo.toml.orig | 110 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/examples/.gitignore | 4 clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/guide/.gitignore | 1 clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo_vcs_info.json | 7 clamav-1.4.6+dfsg/.cargo/vendor/weezl/.github/workflows/rust.yml | 53 clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.lock | 522 clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml | 49 clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml.orig | 90 clamav-1.4.6+dfsg/.cargo/vendor/weezl/Changes.md | 33 clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/decode.rs | 740 clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/encode.rs | 78 clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/end_of_buffer.rs | 12 clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip.rs | 150 clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip_vec.rs | 29 clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/which/.github/workflows/rust.yml | 102 clamav-1.4.6+dfsg/.cargo/vendor/which/Cargo.toml.orig | 30 clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/widestring/.reuse/dep5 | 7 clamav-1.4.6+dfsg/.cargo/vendor/widestring/Cargo.toml.orig | 35 clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows-core/Cargo.toml.orig | 23 clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/Cargo.toml.orig | 256 clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/Cargo.toml.orig | 38 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/Cargo.toml.orig | 13 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.lock | 428 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml | 88 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml.orig | 37 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-Apache-2.0_WITH_LLVM-exception | 220 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-MIT | 23 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/README.md | 45 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/build.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples.rs | 55 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_0_world_imports.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_1_interface_imports.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_2_imported_resources.rs | 22 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_3_world_exports.rs | 47 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_4_exported_resources.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/lib.rs | 881 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support.rs | 634 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/abi_buffer.rs | 417 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/cabi.rs | 112 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/error_context.rs | 94 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/future_support.rs | 734 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/stream_support.rs | 604 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/subtask.rs | 289 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable.rs | 466 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable_set.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/mod.rs | 230 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.c | 20 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.c | 10 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.rs | 11 clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.c | 12 clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/y4m/.travis.yml | 16 clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.lock | 16 clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml | 31 clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml.orig | 14 clamav-1.4.6+dfsg/.cargo/vendor/y4m/LICENSE | 22 clamav-1.4.6+dfsg/.cargo/vendor/y4m/README.md | 37 clamav-1.4.6+dfsg/.cargo/vendor/y4m/examples/resize.rs | 57 clamav-1.4.6+dfsg/.cargo/vendor/y4m/scripts/travis-doc-upload.cfg | 3 clamav-1.4.6+dfsg/.cargo/vendor/y4m/src/lib.rs | 675 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.lock | 266 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml | 200 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml.orig | 56 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-APACHE | 202 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-BSD | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/enum.rs | 386 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/ext.rs | 114 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/lib.rs | 1883 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/output_tests.rs | 2362 ++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/repr.rs | 849 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/crate_path.rs | 189 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/deprecated.rs | 48 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_from_zeros.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_known_layout.rs | 50 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_no_cell.rs | 51 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_to_bytes.rs | 133 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_try_from_bytes.rs | 644 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_unaligned.rs | 49 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/eq.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hash.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hygiene.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/include.rs | 129 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/issue_2117.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/paths_and_modules.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/priv_in_pub.rs | 34 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_bytes.rs | 77 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_zeros.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_known_layout.rs | 114 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_no_cell.rs | 97 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_to_bytes.rs | 203 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_try_from_bytes.rs | 259 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_unaligned.rs | 96 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/trybuild.rs | 60 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr | 89 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.rs | 577 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.stderr | 406 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs | 272 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr | 97 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr | 97 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.stderr | 25 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.stderr | 281 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.stderr | 84 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr | 169 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.rs | 577 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.stderr | 555 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs | 272 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr | 331 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr | 109 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.stderr | 525 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.stderr | 138 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.rs | 38 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.stderr | 144 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.rs | 577 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.stderr | 502 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs | 272 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.rs | 85 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr | 236 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs | 61 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr | 109 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.stderr | 445 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.rs | 109 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.stderr | 130 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_bytes.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_zeros.rs | 69 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_known_layout.rs | 66 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_no_cell.rs | 68 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_to_bytes.rs | 75 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_try_from_bytes.rs | 183 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_unaligned.rs | 77 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/unsafe_cell.rs | 33 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CHANGELOG.md | 43 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CONTRIBUTING.md | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.lock | 296 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml | 127 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml.orig | 111 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-APACHE | 202 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-BSD | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-MIT | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/POLICIES.md | 119 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/README.md | 213 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/build.rs | 256 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/cargo.sh | 14 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_all_toolchains_tested.sh | 25 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_fmt.sh | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_job_dependencies.sh | 35 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_readme.sh | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_todo.sh | 34 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_versions.sh | 70 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/release_crate_version.sh | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/clippy.toml | 10 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/githooks/pre-push | 49 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/rustfmt.toml | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byte_slice.rs | 397 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byteorder.rs | 1530 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/deprecated.rs | 211 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/doctests.rs | 125 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/error.rs | 1081 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/impls.rs | 2081 ++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/layout.rs | 2066 ++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/lib.rs | 6786 ++++++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/macros.rs | 1623 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/inner.rs | 747 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/invariant.rs | 253 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/mod.rs | 40 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/ptr.rs | 1460 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/transmute.rs | 479 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/ref.rs | 1175 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/split_at.rs | 904 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macro_util.rs | 1335 + clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macros.rs | 941 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/mod.rs | 827 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/wrappers.rs | 752 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/testdata/include_value/data | 1 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/trybuild.rs | 55 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr | 159 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr | 40 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.stderr | 7 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr | 42 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.stderr | 25 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.stderr | 25 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr | 37 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr | 50 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr | 50 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr | 25 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr | 49 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr | 27 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr | 139 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr | 45 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.stderr | 60 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.stderr | 60 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.stderr | 34 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr | 88 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr | 120 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr | 95 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr | 95 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.stderr | 32 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr | 120 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr | 63 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.rs | 59 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr | 44 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr | 22 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs | 32 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr | 139 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.rs | 99 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.stderr | 5 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.stderr | 31 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr | 183 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr | 11 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr | 12 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr | 45 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr | 183 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr | 15 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.stderr | 50 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.stderr | 50 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs | 16 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr | 8 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.stderr | 29 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs | 18 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr | 73 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.stderr | 26 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr | 100 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs | 21 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr | 17 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr | 80 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.rs | 24 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr | 80 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.rs | 19 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.stderr | 32 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr | 100 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr | 9 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs | 20 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr | 53 clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/win-cargo.bat | 16 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/CHANGELOG.md | 22 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml | 36 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml.orig | 22 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/README.md | 15 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bit_depth.rs | 170 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream.rs | 23 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/reader.rs | 477 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/traits.rs | 160 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/writer.rs | 353 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/colorspace.rs | 126 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/lib.rs | 44 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/log.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/decoder.rs | 657 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/encoder.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/result.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/serde.rs | 53 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/CHANGELOG.md | 22 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.lock | 72 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml | 46 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml.orig | 22 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-MIT | 21 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-ZLIB | 19 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/README.md | 15 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bit_depth.rs | 170 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader.rs | 462 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/no_std_readers.rs | 198 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/std_readers.rs | 100 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/traits.rs | 146 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer.rs | 262 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/no_std_writer.rs | 70 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/std_writer.rs | 27 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/colorspace.rs | 175 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/lib.rs | 62 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/log.rs | 74 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options.rs | 13 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/decoder.rs | 666 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/encoder.rs | 217 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/result.rs | 72 clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/serde.rs | 63 clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo-checksum.json | 2 clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/Cargo.toml.orig | 22 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Benches.md | 79 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.lock | 25 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml | 65 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml.orig | 32 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Changelog.md | 64 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/README.md | 104 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/bitstream.rs | 703 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/avx.rs | 297 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/neon64.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/scalar.rs | 139 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/components.rs | 213 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/decoder.rs | 910 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/errors.rs | 158 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/headers.rs | 578 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/huffman.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct.rs | 147 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/avx2.rs | 289 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/neon.rs | 295 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/scalar.rs | 212 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/lib.rs | 130 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/marker.rs | 86 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu.rs | 705 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu_prog.rs | 652 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/misc.rs | 474 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_avx2.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_neon.rs | 331 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler.rs | 105 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler/scalar.rs | 124 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/worker.rs | 469 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo-checksum.json | 1 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo_vcs_info.json | 6 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Benches.md | 79 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.lock | 25 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml | 67 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml.orig | 35 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Changelog.md | 95 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-APACHE | 201 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-MIT | 21 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-ZLIB | 19 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/README.md | 104 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/bitstream.rs | 811 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert.rs | 102 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/avx.rs | 297 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/neon64.rs | 144 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/scalar.rs | 139 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/components.rs | 231 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/decoder.rs | 1007 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/errors.rs | 167 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/headers.rs | 643 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/huffman.rs | 254 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct.rs | 206 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/avx2.rs | 398 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/neon.rs | 280 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/scalar.rs | 293 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/lib.rs | 193 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/marker.rs | 91 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu.rs | 822 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu_prog.rs | 700 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/misc.rs | 485 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils.rs | 4 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_avx2.rs | 223 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_neon.rs | 331 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler.rs | 343 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/avx2.rs | 197 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/neon.rs | 189 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/portable_simd.rs | 168 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/scalar.rs | 126 clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/worker.rs | 573 clamav-1.4.6+dfsg/CMakeLists.txt | 10 clamav-1.4.6+dfsg/Cargo.lock | 707 clamav-1.4.6+dfsg/INSTALL.md | 2 clamav-1.4.6+dfsg/Jenkinsfile | 6 clamav-1.4.6+dfsg/NEWS.md | 197 clamav-1.4.6+dfsg/clamav-config.h.cmake.in | 3 clamav-1.4.6+dfsg/clamd/scanner.c | 60 clamav-1.4.6+dfsg/clamd/server-th.c | 2 clamav-1.4.6+dfsg/clamd/session.c | 15 clamav-1.4.6+dfsg/clamd/session.h | 1 clamav-1.4.6+dfsg/clamd/thrmgr.c | 630 clamav-1.4.6+dfsg/clamd/thrmgr.h | 3 clamav-1.4.6+dfsg/clamdscan/client.c | 40 clamav-1.4.6+dfsg/clamdscan/proto.c | 297 clamav-1.4.6+dfsg/clamonacc/client/client.c | 92 clamav-1.4.6+dfsg/clamonacc/client/protocol.c | 138 clamav-1.4.6+dfsg/clamonacc/client/protocol.h | 5 clamav-1.4.6+dfsg/clamonacc/client/socket.c | 7 clamav-1.4.6+dfsg/clamonacc/client/socket.h | 3 clamav-1.4.6+dfsg/clamonacc/inotif/hash.c | 2 clamav-1.4.6+dfsg/clamscan/manager.c | 202 clamav-1.4.6+dfsg/cmake/FindRust.cmake | 29 clamav-1.4.6+dfsg/common/actions.c | 3739 +++ clamav-1.4.6+dfsg/common/actions.h | 74 clamav-1.4.6+dfsg/common/clamdcom.c | 153 clamav-1.4.6+dfsg/common/clamdcom.h | 9 clamav-1.4.6+dfsg/common/output.c | 2 clamav-1.4.6+dfsg/common/scanmem.c | 277 clamav-1.4.6+dfsg/common/scanmem.h | 6 clamav-1.4.6+dfsg/debian/.git-dpm | 14 clamav-1.4.6+dfsg/debian/README.Debian | 6 clamav-1.4.6+dfsg/debian/changelog | 51 clamav-1.4.6+dfsg/debian/clamav-base.postinst.in | 9 clamav-1.4.6+dfsg/debian/clamav-base.sysusers | 1 clamav-1.4.6+dfsg/debian/clamav-base.tmpfiles | 2 clamav-1.4.6+dfsg/debian/clamav-daemon.install | 9 clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.paranoid | 12 clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.server | 2 clamav-1.4.6+dfsg/debian/clamav-daemon.manpages | 3 clamav-1.4.6+dfsg/debian/clamav-daemon.postinst.in | 8 clamav-1.4.6+dfsg/debian/clamav-freshclam.install | 7 clamav-1.4.6+dfsg/debian/clamav-freshclam.logcheck.ignore.server | 14 clamav-1.4.6+dfsg/debian/clamav-freshclam.postinst.in | 17 clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.paranoid | 8 clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.server | 4 clamav-1.4.6+dfsg/debian/control | 16 clamav-1.4.6+dfsg/debian/libclamav12.symbols | 8 clamav-1.4.6+dfsg/debian/not-installed | 2 clamav-1.4.6+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch | 2 clamav-1.4.6+dfsg/debian/po/ca.po | 1509 + clamav-1.4.6+dfsg/debian/po/ro.po | 1533 + clamav-1.4.6+dfsg/debian/rules | 21 clamav-1.4.6+dfsg/debian/usr.sbin.clamd | 5 clamav-1.4.6+dfsg/docs/man/clamd.8.in | 24 clamav-1.4.6+dfsg/docs/man/clamdscan.1.in | 47 clamav-1.4.6+dfsg/libclamav/7z/7zIn.c | 2 clamav-1.4.6+dfsg/libclamav/bytecode_api.h | 3 clamav-1.4.6+dfsg/libclamav/dmg.c | 57 clamav-1.4.6+dfsg/libclamav/gpt.c | 2 clamav-1.4.6+dfsg/libclamav/ishield.c | 60 clamav-1.4.6+dfsg/libclamav/libclamav.map | 3 clamav-1.4.6+dfsg/libclamav/macho.c | 75 clamav-1.4.6+dfsg/libclamav/mpool.c | 4 clamav-1.4.6+dfsg/libclamav/mpool.h | 7 clamav-1.4.6+dfsg/libclamav/ole2_extract.c | 135 clamav-1.4.6+dfsg/libclamav/others.h | 4 clamav-1.4.6+dfsg/libclamav/others_common.c | 68 clamav-1.4.6+dfsg/libclamav/pdf.c | 2 clamav-1.4.6+dfsg/libclamav/pe.c | 2 clamav-1.4.6+dfsg/libclamav/rebuildpe.c | 34 clamav-1.4.6+dfsg/libclamav/spin.c | 112 clamav-1.4.6+dfsg/libclamav/xar.c | 190 clamav-1.4.6+dfsg/libclamav/xlm_extract.c | 4 clamav-1.4.6+dfsg/libclamav_rust/Cargo.toml | 6 clamav-1.4.6+dfsg/libclamav_rust/build.rs | 1 clamav-1.4.6+dfsg/libclamav_rust/src/alz.rs | 1557 + clamav-1.4.6+dfsg/libclamav_rust/src/css_image_extract.rs | 143 clamav-1.4.6+dfsg/libclamav_rust/src/evidence.rs | 2 clamav-1.4.6+dfsg/libclamav_rust/src/fmap.rs | 2 clamav-1.4.6+dfsg/libclamav_rust/src/onenote.rs | 2 clamav-1.4.6+dfsg/libclamav_rust/src/scanners.rs | 330 clamav-1.4.6+dfsg/libclamav_rust/src/sys.rs | 6 clamav-1.4.6+dfsg/libclamav_rust/src/util.rs | 48 clamav-1.4.6+dfsg/unit_tests/CMakeLists.txt | 5 clamav-1.4.6+dfsg/unit_tests/check_clamav.c | 161 clamav-1.4.6+dfsg/unit_tests/check_clamd.c | 583 clamav-1.4.6+dfsg/unit_tests/clamd_test.py | 209 clamav-1.4.6+dfsg/unit_tests/clamscan/alz_test.py | 324 clamav-1.4.6+dfsg/unit_tests/clamscan/quarantine_toctou_test.py | 907 clamav-1.4.6+dfsg/unit_tests/clamscan/xar_test.py | 153 clamav-1.4.6+dfsg/unit_tests/valgrind.supp | 9 4184 files changed, 956485 insertions(+), 84455 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkzzc8ds6/clamav_1.4.3+dfsg-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkzzc8ds6/clamav_1.4.6+dfsg-1~deb13u1.dsc: no acceptable signature found diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/adler/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/adler/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"737088e45fdf27fe2cfedce163332d8ce08c58fd86ca287de2de34c0fbaf63e7","Cargo.toml":"f410869f0f1a5697f65a8a77be03da7aeecc0be26e7cf3a1feb1acaa4f518770","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"308c50cdb42b9573743068158339570b45ca3f895015ca3b87ba983edb0a21e6","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"c07ce370e3680c602e415f8d1ec4e543ea2163ab22a09b6b82d93e8a30adca82","src/algo.rs":"b664b131f724a809591394a10b9023f40ab5963e32a83fa3163c2668e59c8b66","src/lib.rs":"b55ba9c629b30360d08168b2ca0c96275432856a539737a105a6d6ae6bf7e88f"},"package":"f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/adler/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler/CHANGELOG.md 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -# Changelog - -## Unreleased - -No changes. - -## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2) - -- Fix doctest on big-endian systems ([#9]). - -[#9]: https://github.com/jonas-schievink/adler/pull/9 - -## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1) - -### Fixes - -- Fix documentation on docs.rs. - -## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0) - -### Fixes - -- Fix `cargo test --no-default-features` ([#5]). - -### Improvements - -- Extended and clarified documentation. -- Added more rustdoc examples. -- Extended CI to test the crate with `--no-default-features`. - -### Breaking Changes - -- `adler32_reader` now takes its generic argument by value instead of as a `&mut`. -- Renamed `adler32_reader` to `adler32`. - -## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3) - -- Process 4 Bytes at a time, improving performance by up to 50% ([#2]). - -## [0.2.2 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.2) - -- Bump MSRV to 1.31.0. - -## [0.2.1 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.1) - -- Add a few `#[inline]` annotations to small functions. -- Fix CI badge. -- Allow integration into libstd. - -## [0.2.0 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.0) - -- Support `#![no_std]` when using `default-features = false`. -- Improve performance by around 7x. -- Support Rust 1.8.0. -- Improve API naming. - -## [0.1.0 - 2020-06-26](https://github.com/jonas-schievink/adler/releases/tag/v0.1.0) - -Initial release. - - -[#2]: https://github.com/jonas-schievink/adler/pull/2 -[#5]: https://github.com/jonas-schievink/adler/pull/5 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/adler/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/adler/Cargo.toml 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "adler" -version = "1.0.2" -authors = ["Jonas Schievink "] -description = "A simple clean-room implementation of the Adler-32 checksum" -documentation = "https://docs.rs/adler/" -readme = "README.md" -keywords = ["checksum", "integrity", "hash", "adler32", "zlib"] -categories = ["algorithms"] -license = "0BSD OR MIT OR Apache-2.0" -repository = "https://github.com/jonas-schievink/adler.git" -[package.metadata.docs.rs] -rustdoc-args = ["--cfg=docsrs"] - -[package.metadata.release] -no-dev-version = true -pre-release-commit-message = "Release {{version}}" -tag-message = "{{version}}" - -[[package.metadata.release.pre-release-replacements]] -file = "CHANGELOG.md" -replace = "## Unreleased\n\nNo changes.\n\n## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}})\n" -search = "## Unreleased\n" - -[[package.metadata.release.pre-release-replacements]] -file = "README.md" -replace = "adler = \"{{version}}\"" -search = "adler = \"[a-z0-9\\\\.-]+\"" - -[[package.metadata.release.pre-release-replacements]] -file = "src/lib.rs" -replace = "https://docs.rs/adler/{{version}}" -search = "https://docs.rs/adler/[a-z0-9\\.-]+" - -[[bench]] -name = "bench" -harness = false -[dependencies.compiler_builtins] -version = "0.1.2" -optional = true - -[dependencies.core] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-core" -[dev-dependencies.criterion] -version = "0.3.2" - -[features] -default = ["std"] -rustc-dep-of-std = ["core", "compiler_builtins"] -std = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-0BSD clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-0BSD --- clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-0BSD 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-0BSD 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -Copyright (C) Jonas Schievink - -Permission to use, copy, modify, and/or distribute this software for -any purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-APACHE 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/LICENSE-2.0 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/adler/LICENSE-MIT 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/README.md clamav-1.4.6+dfsg/.cargo/vendor/adler/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler/README.md 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -# Adler-32 checksums for Rust - -[![crates.io](https://img.shields.io/crates/v/adler.svg)](https://crates.io/crates/adler) -[![docs.rs](https://docs.rs/adler/badge.svg)](https://docs.rs/adler/) -![CI](https://github.com/jonas-schievink/adler/workflows/CI/badge.svg) - -This crate provides a simple implementation of the Adler-32 checksum, used in -the zlib compression format. - -Please refer to the [changelog](CHANGELOG.md) to see what changed in the last -releases. - -## Features - -- Permissively licensed (0BSD) clean-room implementation. -- Zero dependencies. -- Zero `unsafe`. -- Decent performance (3-4 GB/s). -- Supports `#![no_std]` (with `default-features = false`). - -## Usage - -Add an entry to your `Cargo.toml`: - -```toml -[dependencies] -adler = "1.0.2" -``` - -Check the [API Documentation](https://docs.rs/adler/) for how to use the -crate's functionality. - -## Rust version support - -Currently, this crate supports all Rust versions starting at Rust 1.31.0. - -Bumping the Minimum Supported Rust Version (MSRV) is *not* considered a breaking -change, but will not be done without good reasons. The latest 3 stable Rust -versions will always be supported no matter what. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/RELEASE_PROCESS.md clamav-1.4.6+dfsg/.cargo/vendor/adler/RELEASE_PROCESS.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler/RELEASE_PROCESS.md 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/RELEASE_PROCESS.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -# What to do to publish a new release - -1. Ensure all notable changes are in the changelog under "Unreleased". - -2. Execute `cargo release ` to bump version(s), tag and publish - everything. External subcommand, must be installed with `cargo install - cargo-release`. - - `` can be one of `major|minor|patch`. If this is the first release - (`0.1.0`), use `minor`, since the version starts out as `0.0.0`. - -3. Go to the GitHub releases, edit the just-pushed tag. Copy the release notes - from the changelog. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/benches/bench.rs clamav-1.4.6+dfsg/.cargo/vendor/adler/benches/bench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler/benches/bench.rs 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/benches/bench.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -extern crate adler; -extern crate criterion; - -use adler::{adler32_slice, Adler32}; -use criterion::{criterion_group, criterion_main, Criterion, Throughput}; - -fn simple(c: &mut Criterion) { - { - const SIZE: usize = 100; - - let mut group = c.benchmark_group("simple-100b"); - group.throughput(Throughput::Bytes(SIZE as u64)); - group.bench_function("zeroes-100", |bencher| { - bencher.iter(|| { - adler32_slice(&[0; SIZE]); - }); - }); - group.bench_function("ones-100", |bencher| { - bencher.iter(|| { - adler32_slice(&[0xff; SIZE]); - }); - }); - } - - { - const SIZE: usize = 1024; - - let mut group = c.benchmark_group("simple-1k"); - group.throughput(Throughput::Bytes(SIZE as u64)); - - group.bench_function("zeroes-1k", |bencher| { - bencher.iter(|| { - adler32_slice(&[0; SIZE]); - }); - }); - - group.bench_function("ones-1k", |bencher| { - bencher.iter(|| { - adler32_slice(&[0xff; SIZE]); - }); - }); - } - - { - const SIZE: usize = 1024 * 1024; - - let mut group = c.benchmark_group("simple-1m"); - group.throughput(Throughput::Bytes(SIZE as u64)); - group.bench_function("zeroes-1m", |bencher| { - bencher.iter(|| { - adler32_slice(&[0; SIZE]); - }); - }); - - group.bench_function("ones-1m", |bencher| { - bencher.iter(|| { - adler32_slice(&[0xff; SIZE]); - }); - }); - } -} - -fn chunked(c: &mut Criterion) { - const SIZE: usize = 16 * 1024 * 1024; - - let data = vec![0xAB; SIZE]; - - let mut group = c.benchmark_group("chunked-16m"); - group.throughput(Throughput::Bytes(SIZE as u64)); - group.bench_function("5552", |bencher| { - bencher.iter(|| { - let mut h = Adler32::new(); - for chunk in data.chunks(5552) { - h.write_slice(chunk); - } - h.checksum() - }); - }); - group.bench_function("8k", |bencher| { - bencher.iter(|| { - let mut h = Adler32::new(); - for chunk in data.chunks(8 * 1024) { - h.write_slice(chunk); - } - h.checksum() - }); - }); - group.bench_function("64k", |bencher| { - bencher.iter(|| { - let mut h = Adler32::new(); - for chunk in data.chunks(64 * 1024) { - h.write_slice(chunk); - } - h.checksum() - }); - }); - group.bench_function("1m", |bencher| { - bencher.iter(|| { - let mut h = Adler32::new(); - for chunk in data.chunks(1024 * 1024) { - h.write_slice(chunk); - } - h.checksum() - }); - }); -} - -criterion_group!(benches, simple, chunked); -criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/src/algo.rs clamav-1.4.6+dfsg/.cargo/vendor/adler/src/algo.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler/src/algo.rs 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/src/algo.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -use crate::Adler32; -use std::ops::{AddAssign, MulAssign, RemAssign}; - -impl Adler32 { - pub(crate) fn compute(&mut self, bytes: &[u8]) { - // The basic algorithm is, for every byte: - // a = (a + byte) % MOD - // b = (b + a) % MOD - // where MOD = 65521. - // - // For efficiency, we can defer the `% MOD` operations as long as neither a nor b overflows: - // - Between calls to `write`, we ensure that a and b are always in range 0..MOD. - // - We use 32-bit arithmetic in this function. - // - Therefore, a and b must not increase by more than 2^32-MOD without performing a `% MOD` - // operation. - // - // According to Wikipedia, b is calculated as follows for non-incremental checksumming: - // b = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n*1 (mod 65521) - // Where n is the number of bytes and Di is the i-th Byte. We need to change this to account - // for the previous values of a and b, as well as treat every input Byte as being 255: - // b_inc = n×255 + (n-1)×255 + ... + 255 + n*65520 - // Or in other words: - // b_inc = n*65520 + n(n+1)/2*255 - // The max chunk size is thus the largest value of n so that b_inc <= 2^32-65521. - // 2^32-65521 = n*65520 + n(n+1)/2*255 - // Plugging this into an equation solver since I can't math gives n = 5552.18..., so 5552. - // - // On top of the optimization outlined above, the algorithm can also be parallelized with a - // bit more work: - // - // Note that b is a linear combination of a vector of input bytes (D1, ..., Dn). - // - // If we fix some value k Self { - U32X4([ - u32::from(bytes[0]), - u32::from(bytes[1]), - u32::from(bytes[2]), - u32::from(bytes[3]), - ]) - } -} - -impl AddAssign for U32X4 { - fn add_assign(&mut self, other: Self) { - for (s, o) in self.0.iter_mut().zip(other.0.iter()) { - *s += o; - } - } -} - -impl RemAssign for U32X4 { - fn rem_assign(&mut self, quotient: u32) { - for s in self.0.iter_mut() { - *s %= quotient; - } - } -} - -impl MulAssign for U32X4 { - fn mul_assign(&mut self, rhs: u32) { - for s in self.0.iter_mut() { - *s *= rhs; - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/adler/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler/src/lib.rs 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,287 +0,0 @@ -//! Adler-32 checksum implementation. -//! -//! This implementation features: -//! -//! - Permissively licensed (0BSD) clean-room implementation. -//! - Zero dependencies. -//! - Zero `unsafe`. -//! - Decent performance (3-4 GB/s). -//! - `#![no_std]` support (with `default-features = false`). - -#![doc(html_root_url = "https://docs.rs/adler/1.0.2")] -// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default -#![doc(test(attr(deny(unused_imports, unused_must_use))))] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_debug_implementations)] -#![forbid(unsafe_code)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(not(feature = "std"))] -extern crate core as std; - -mod algo; - -use std::hash::Hasher; - -#[cfg(feature = "std")] -use std::io::{self, BufRead}; - -/// Adler-32 checksum calculator. -/// -/// An instance of this type is equivalent to an Adler-32 checksum: It can be created in the default -/// state via [`new`] (or the provided `Default` impl), or from a precalculated checksum via -/// [`from_checksum`], and the currently stored checksum can be fetched via [`checksum`]. -/// -/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any -/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although -/// that is not recommended (while every checksum is a hash function, they are not necessarily a -/// good one). -/// -/// # Examples -/// -/// Basic, piecewise checksum calculation: -/// -/// ``` -/// use adler::Adler32; -/// -/// let mut adler = Adler32::new(); -/// -/// adler.write_slice(&[0, 1, 2]); -/// adler.write_slice(&[3, 4, 5]); -/// -/// assert_eq!(adler.checksum(), 0x00290010); -/// ``` -/// -/// Using `Hash` to process structures: -/// -/// ``` -/// use std::hash::Hash; -/// use adler::Adler32; -/// -/// #[derive(Hash)] -/// struct Data { -/// byte: u8, -/// word: u16, -/// big: u64, -/// } -/// -/// let mut adler = Adler32::new(); -/// -/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 }; -/// data.hash(&mut adler); -/// -/// // hash value depends on architecture endianness -/// if cfg!(target_endian = "little") { -/// assert_eq!(adler.checksum(), 0x33410990); -/// } -/// if cfg!(target_endian = "big") { -/// assert_eq!(adler.checksum(), 0x331F0990); -/// } -/// -/// ``` -/// -/// [`new`]: #method.new -/// [`from_checksum`]: #method.from_checksum -/// [`checksum`]: #method.checksum -#[derive(Debug, Copy, Clone)] -pub struct Adler32 { - a: u16, - b: u16, -} - -impl Adler32 { - /// Creates a new Adler-32 instance with default state. - #[inline] - pub fn new() -> Self { - Self::default() - } - - /// Creates an `Adler32` instance from a precomputed Adler-32 checksum. - /// - /// This allows resuming checksum calculation without having to keep the `Adler32` instance - /// around. - /// - /// # Example - /// - /// ``` - /// # use adler::Adler32; - /// let parts = [ - /// "rust", - /// "acean", - /// ]; - /// let whole = adler::adler32_slice(b"rustacean"); - /// - /// let mut sum = Adler32::new(); - /// sum.write_slice(parts[0].as_bytes()); - /// let partial = sum.checksum(); - /// - /// // ...later - /// - /// let mut sum = Adler32::from_checksum(partial); - /// sum.write_slice(parts[1].as_bytes()); - /// assert_eq!(sum.checksum(), whole); - /// ``` - #[inline] - pub fn from_checksum(sum: u32) -> Self { - Adler32 { - a: sum as u16, - b: (sum >> 16) as u16, - } - } - - /// Returns the calculated checksum at this point in time. - #[inline] - pub fn checksum(&self) -> u32 { - (u32::from(self.b) << 16) | u32::from(self.a) - } - - /// Adds `bytes` to the checksum calculation. - /// - /// If efficiency matters, this should be called with Byte slices that contain at least a few - /// thousand Bytes. - pub fn write_slice(&mut self, bytes: &[u8]) { - self.compute(bytes); - } -} - -impl Default for Adler32 { - #[inline] - fn default() -> Self { - Adler32 { a: 1, b: 0 } - } -} - -impl Hasher for Adler32 { - #[inline] - fn finish(&self) -> u64 { - u64::from(self.checksum()) - } - - fn write(&mut self, bytes: &[u8]) { - self.write_slice(bytes); - } -} - -/// Calculates the Adler-32 checksum of a byte slice. -/// -/// This is a convenience function around the [`Adler32`] type. -/// -/// [`Adler32`]: struct.Adler32.html -pub fn adler32_slice(data: &[u8]) -> u32 { - let mut h = Adler32::new(); - h.write_slice(data); - h.checksum() -} - -/// Calculates the Adler-32 checksum of a `BufRead`'s contents. -/// -/// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an -/// error). -/// -/// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling -/// this function. -/// -/// # Errors -/// -/// Any error returned by the reader are bubbled up by this function. -/// -/// # Examples -/// -/// ```no_run -/// # fn run() -> Result<(), Box> { -/// use adler::adler32; -/// -/// use std::fs::File; -/// use std::io::BufReader; -/// -/// let file = File::open("input.txt")?; -/// let mut file = BufReader::new(file); -/// -/// adler32(&mut file)?; -/// # Ok(()) } -/// # fn main() { run().unwrap() } -/// ``` -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub fn adler32(mut reader: R) -> io::Result { - let mut h = Adler32::new(); - loop { - let len = { - let buf = reader.fill_buf()?; - if buf.is_empty() { - return Ok(h.checksum()); - } - - h.write_slice(buf); - buf.len() - }; - reader.consume(len); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn zeroes() { - assert_eq!(adler32_slice(&[]), 1); - assert_eq!(adler32_slice(&[0]), 1 | 1 << 16); - assert_eq!(adler32_slice(&[0, 0]), 1 | 2 << 16); - assert_eq!(adler32_slice(&[0; 100]), 0x00640001); - assert_eq!(adler32_slice(&[0; 1024]), 0x04000001); - assert_eq!(adler32_slice(&[0; 1024 * 1024]), 0x00f00001); - } - - #[test] - fn ones() { - assert_eq!(adler32_slice(&[0xff; 1024]), 0x79a6fc2e); - assert_eq!(adler32_slice(&[0xff; 1024 * 1024]), 0x8e88ef11); - } - - #[test] - fn mixed() { - assert_eq!(adler32_slice(&[1]), 2 | 2 << 16); - assert_eq!(adler32_slice(&[40]), 41 | 41 << 16); - - assert_eq!(adler32_slice(&[0xA5; 1024 * 1024]), 0xd5009ab1); - } - - /// Example calculation from https://en.wikipedia.org/wiki/Adler-32. - #[test] - fn wiki() { - assert_eq!(adler32_slice(b"Wikipedia"), 0x11E60398); - } - - #[test] - fn resume() { - let mut adler = Adler32::new(); - adler.write_slice(&[0xff; 1024]); - let partial = adler.checksum(); - assert_eq!(partial, 0x79a6fc2e); // from above - adler.write_slice(&[0xff; 1024 * 1024 - 1024]); - assert_eq!(adler.checksum(), 0x8e88ef11); // from above - - // Make sure that we can resume computing from the partial checksum via `from_checksum`. - let mut adler = Adler32::from_checksum(partial); - adler.write_slice(&[0xff; 1024 * 1024 - 1024]); - assert_eq!(adler.checksum(), 0x8e88ef11); // from above - } - - #[cfg(feature = "std")] - #[test] - fn bufread() { - use std::io::BufReader; - fn test(data: &[u8], checksum: u32) { - // `BufReader` uses an 8 KB buffer, so this will test buffer refilling. - let mut buf = BufReader::new(data); - let real_sum = adler32(&mut buf).unwrap(); - assert_eq!(checksum, real_sum); - } - - test(&[], 1); - test(&[0; 1024], 0x04000001); - test(&[0; 1024 * 1024], 0x00f00001); - test(&[0xA5; 1024 * 1024], 0xd5009ab1); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"08071a308400282ad18ca2de0df6d1f2dc270475f69aa483740ce311af3f63e0","CHANGELOG.md":"04fa29ec6eb6b05b706247ecac2cbc7075792dbfcea0bf52715782cf42132e94","Cargo.lock":"3e44ced212a9e7ddc0a5450bcebb48ec67f32a058529856458efa36415554e53","Cargo.toml":"8f30dbd092f3acc475b9d339736cd7b64c6489bc47cd234a7f2232fc52e2d490","Cargo.toml.orig":"077df9094ac86443a4d05305f74782bd237c1f15fa39640463e4c62e9e4a310a","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cd955d5d6a49161e6f7a04df4a5963581b66ed43fd5096b2dedca8e295efe4f9","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"d67bef1c7f36ed300a8fbcf9d50b9dfdead1fd340bf87a4d47d99a0c1c042c04","src/algo.rs":"932c2bc591d13fe4470185125617b5aaa660a3898f23b553acc85df0bf49dded","src/lib.rs":"4acd41668fe30daffa37084e7e223f268957b816afc1864ffb3f5d6d7adf0890"},"package":"320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "89a031a0f42eeff31c70dc598b398cbf31f1680f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/adler2/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +--- +## [2.0.1](https://github.com/Frommi/miniz_oxide/compare/2.0.0..2.0.1) - 2025-06-09 + +### Other + +- Remove `compiler-builtins` from `rustc-dep-of-std` dependencies - ([7cdbd39](https://github.com/Frommi/miniz_oxide/commit/7cdbd3925a7f61cc075f44367b5d383861571b0a)) - Trevor Gross + +--- +## [2.0.0](https://github.com/Frommi/miniz_oxide/compare/1.0.2..2.0.0) - 2024-08-04 + +First release of adler2 - fork of adler crate as the original is unmaintained and archived + +##### Changes since last version of Adler: + +### Bug Fixes + +- **(core)** change to rust 2021 edition, update repository info and links, update author info - ([867b115](https://github.com/Frommi/miniz_oxide/commit/867b115bad79bf62098f2acccc81bf53ec5a125d)) - oyvindln +- **(core)** simplify some code and fix benches - ([128fb9c](https://github.com/Frommi/miniz_oxide/commit/128fb9cb6cad5c3a54fb0b6c68549d80b79a1fe0)) - oyvindln + +### Changelog of original adler crate + +--- + +## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2) + +- Fix doctest on big-endian systems ([#9]). + +[#9]: https://github.com/jonas-schievink/adler/pull/9 + +## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1) + +### Fixes + +- Fix documentation on docs.rs. + +## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0) + +### Fixes + +- Fix `cargo test --no-default-features` ([#5]). + +### Improvements + +- Extended and clarified documentation. +- Added more rustdoc examples. +- Extended CI to test the crate with `--no-default-features`. + +### Breaking Changes + +- `adler32_reader` now takes its generic argument by value instead of as a `&mut`. +- Renamed `adler32_reader` to `adler32`. + +## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3) + +- Process 4 Bytes at a time, improving performance by up to 50% ([#2]). + +## [0.2.2 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.2) + +- Bump MSRV to 1.31.0. + +## [0.2.1 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.1) + +- Add a few `#[inline]` annotations to small functions. +- Fix CI badge. +- Allow integration into libstd. + +## [0.2.0 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.0) + +- Support `#![no_std]` when using `default-features = false`. +- Improve performance by around 7x. +- Support Rust 1.8.0. +- Improve API naming. + +## [0.1.0 - 2020-06-26](https://github.com/jonas-schievink/adler/releases/tag/v0.1.0) + +Initial release. + + +[#2]: https://github.com/jonas-schievink/adler/pull/2 +[#5]: https://github.com/jonas-schievink/adler/pull/5 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +dependencies = [ + "rustc-std-workspace-core", +] + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,91 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "adler2" +version = "2.0.1" +authors = [ + "Jonas Schievink ", + "oyvindln ", +] +build = false +exclude = [".*"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A simple clean-room implementation of the Adler-32 checksum" +documentation = "https://docs.rs/adler2/" +readme = "README.md" +keywords = [ + "checksum", + "integrity", + "hash", + "adler32", + "zlib", +] +categories = ["algorithms"] +license = "0BSD OR MIT OR Apache-2.0" +repository = "https://github.com/oyvindln/adler2" + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg=docsrs"] + +[package.metadata.release] +no-dev-version = true +pre-release-commit-message = "Release {{version}}" +tag-message = "{{version}}" + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = """ +## Unreleased + +No changes. + +## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}}) +""" +search = """ +## Unreleased +""" + +[[package.metadata.release.pre-release-replacements]] +file = "README.md" +replace = 'adler = "{{version}}"' +search = 'adler = "[a-z0-9\\.-]+"' + +[[package.metadata.release.pre-release-replacements]] +file = "src/lib.rs" +replace = "https://docs.rs/adler/{{version}}" +search = 'https://docs.rs/adler/[a-z0-9\.-]+' + +[features] +default = ["std"] +rustc-dep-of-std = ["core"] +std = [] + +[lib] +name = "adler2" +path = "src/lib.rs" + +[[bench]] +name = "bench" +path = "benches/bench.rs" +harness = false + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[dev-dependencies] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,71 @@ +[package] +name = "adler2" +version = "2.0.1" +authors = ["Jonas Schievink ", "oyvindln "] +description = "A simple clean-room implementation of the Adler-32 checksum" +documentation = "https://docs.rs/adler2/" +repository = "https://github.com/oyvindln/adler2" +keywords = ["checksum", "integrity", "hash", "adler32", "zlib"] +categories = ["algorithms"] +readme = "README.md" +license = "0BSD OR MIT OR Apache-2.0" +edition = "2021" +exclude = [".*"] + +[[bench]] +name = "bench" +harness = false + +[dependencies] +# Internal features, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } + +[dev-dependencies] +## Messes with minimum rust version and drags in deps just for running tests +## so just comment out for now and enable manually when needed for enabling benches +## criterion = "0.3.2" + +[features] +# Disable default features to enable `#![no_std]` support. +default = ["std"] +std = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core'] + + +[package.metadata.docs.rs] +rustdoc-args = [ "--cfg=docsrs" ] + +# cargo-release configuration +[package.metadata.release] +tag-message = "{{version}}" +no-dev-version = true +pre-release-commit-message = "Release {{version}}" + +# Change the changelog's `Unreleased` section to refer to this release and +# prepend a new `Unreleased` section +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "## Unreleased\n" +replace = """ +## Unreleased + +No changes. + +## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}}) +""" + +# Bump the version inside the example manifest in `README.md` +[[package.metadata.release.pre-release-replacements]] +file = "README.md" +search = 'adler = "[a-z0-9\\.-]+"' +replace = 'adler = "{{version}}"' + +# Bump the version referenced by the `html_root_url` attribute in `lib.rs` +[[package.metadata.release.pre-release-replacements]] +file = "src/lib.rs" +search = "https://docs.rs/adler/[a-z0-9\\.-]+" +replace = "https://docs.rs/adler/{{version}}" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-0BSD clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-0BSD --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-0BSD 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-0BSD 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +Copyright (C) Jonas Schievink + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/README.md clamav-1.4.6+dfsg/.cargo/vendor/adler2/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +# Adler-32 checksums for Rust + +This is a fork of the adler crate as the [original](https://github.com/jonas-schievink/adler) has been archived and is no longer updated by it's author + +[![crates.io](https://img.shields.io/crates/v/adler.svg)](https://crates.io/crates/adler) +[![docs.rs](https://docs.rs/adler/badge.svg)](https://docs.rs/adler/) +![CI](https://github.com/jonas-schievink/adler/workflows/CI/badge.svg) + +This crate provides a simple implementation of the Adler-32 checksum, used in +the zlib compression format. + +Please refer to the [changelog](CHANGELOG.md) to see what changed in the last +releases. + +## Features + +- Permissively licensed (0BSD) clean-room implementation. +- Zero dependencies. +- Zero `unsafe`. +- Decent performance (3-4 GB/s) (see note). +- Supports `#![no_std]` (with `default-features = false`). + +## Usage + +Add an entry to your `Cargo.toml`: + +```toml +[dependencies] +adler2 = "2.0.0" +``` + +Check the [API Documentation](https://docs.rs/adler/) for how to use the +crate's functionality. + +## Rust version support + +Currently, this crate supports all Rust versions starting at Rust 1.56.0. + +Bumping the Minimum Supported Rust Version (MSRV) is *not* considered a breaking +change, but will not be done without good reasons. The latest 3 stable Rust +versions will always be supported no matter what. + +## Performance + +Due to the way the algorithm works this crate and the fact that it's not possible to use explicit simd in safe rust currently, this crate benefits drastically from being compiled with newer cpu instructions enabled (using e.g ```RUSTFLAGS=-C target-feature'+sse4.1``` or ```-C target-cpu=x86-64-v2```/```-C target-cpu=x86-64-v3``` arguments depending on what cpu support is being targeted.) +Judging by the crate benchmarks, on a Ryzen 5600, compiling with SSE 4.1 (enabled in x86-64-v2 feature level) enabled can give a ~50-150% speedup, enabling the LZCNT instruction (enabled in x86-64-v3 feature level) can give a further ~50% speedup, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/RELEASE_PROCESS.md clamav-1.4.6+dfsg/.cargo/vendor/adler2/RELEASE_PROCESS.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/RELEASE_PROCESS.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/RELEASE_PROCESS.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +# What to do to publish a new release + +1. Ensure all notable changes are in the changelog under "Unreleased". + +2. Execute `cargo release ` to bump version(s), tag and publish + everything. External subcommand, must be installed with `cargo install + cargo-release`. + + `` can be one of `major|minor|patch`. If this is the first release + (`0.1.0`), use `minor`, since the version starts out as `0.0.0`. + +3. Go to the GitHub releases, edit the just-pushed tag. Copy the release notes + from the changelog. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/benches/bench.rs clamav-1.4.6+dfsg/.cargo/vendor/adler2/benches/bench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/benches/bench.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/benches/bench.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +extern crate adler2; +extern crate criterion; + +use adler2::{adler32_slice, Adler32}; +use criterion::{criterion_group, criterion_main, Criterion, Throughput}; + +fn simple(c: &mut Criterion) { + { + const SIZE: usize = 100; + + let mut group = c.benchmark_group("simple-100b"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("zeroes-100", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + group.bench_function("ones-100", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } + + { + const SIZE: usize = 1024; + + let mut group = c.benchmark_group("simple-1k"); + group.throughput(Throughput::Bytes(SIZE as u64)); + + group.bench_function("zeroes-1k", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + + group.bench_function("ones-1k", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } + + { + const SIZE: usize = 1024 * 1024; + + let mut group = c.benchmark_group("simple-1m"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("zeroes-1m", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + + group.bench_function("ones-1m", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } +} + +fn chunked(c: &mut Criterion) { + const SIZE: usize = 16 * 1024 * 1024; + + let data = vec![0xAB; SIZE]; + + let mut group = c.benchmark_group("chunked-16m"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("5552", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(5552) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("8k", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(8 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("64k", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(64 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("1m", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(1024 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); +} + +criterion_group!(benches, simple, chunked); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/src/algo.rs clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/algo.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/src/algo.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/algo.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,155 @@ +use crate::Adler32; +use std::ops::{AddAssign, MulAssign, RemAssign}; + +impl Adler32 { + pub(crate) fn compute(&mut self, bytes: &[u8]) { + // The basic algorithm is, for every byte: + // a = (a + byte) % MOD + // b = (b + a) % MOD + // where MOD = 65521. + // + // For efficiency, we can defer the `% MOD` operations as long as neither a nor b overflows: + // - Between calls to `write`, we ensure that a and b are always in range 0..MOD. + // - We use 32-bit arithmetic in this function. + // - Therefore, a and b must not increase by more than 2^32-MOD without performing a `% MOD` + // operation. + // + // According to Wikipedia, b is calculated as follows for non-incremental checksumming: + // b = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n*1 (mod 65521) + // Where n is the number of bytes and Di is the i-th Byte. We need to change this to account + // for the previous values of a and b, as well as treat every input Byte as being 255: + // b_inc = n×255 + (n-1)×255 + ... + 255 + n*65520 + // Or in other words: + // b_inc = n*65520 + n(n+1)/2*255 + // The max chunk size is thus the largest value of n so that b_inc <= 2^32-65521. + // 2^32-65521 = n*65520 + n(n+1)/2*255 + // Plugging this into an equation solver since I can't math gives n = 5552.18..., so 5552. + // + // On top of the optimization outlined above, the algorithm can also be parallelized with a + // bit more work: + // + // Note that b is a linear combination of a vector of input bytes (D1, ..., Dn). + // + // If we fix some value k Self { + U32X4([ + u32::from(bytes[0]), + u32::from(bytes[1]), + u32::from(bytes[2]), + u32::from(bytes[3]), + ]) + } +} + +impl AddAssign for U32X4 { + #[inline] + fn add_assign(&mut self, other: Self) { + // Implement this in a primitive manner to help out the compiler a bit. + self.0[0] += other.0[0]; + self.0[1] += other.0[1]; + self.0[2] += other.0[2]; + self.0[3] += other.0[3]; + } +} + +impl RemAssign for U32X4 { + #[inline] + fn rem_assign(&mut self, quotient: u32) { + self.0[0] %= quotient; + self.0[1] %= quotient; + self.0[2] %= quotient; + self.0[3] %= quotient; + } +} + +impl MulAssign for U32X4 { + #[inline] + fn mul_assign(&mut self, rhs: u32) { + self.0[0] *= rhs; + self.0[1] *= rhs; + self.0[2] *= rhs; + self.0[3] *= rhs; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler2/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler2/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler2/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,287 @@ +//! Adler-32 checksum implementation. +//! +//! This implementation features: +//! +//! - Permissively licensed (0BSD) clean-room implementation. +//! - Zero dependencies. +//! - Zero `unsafe`. +//! - Decent performance (3-4 GB/s). +//! - `#![no_std]` support (with `default-features = false`). + +#![doc(html_root_url = "https://docs.rs/adler2/2.0.0")] +// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default +#![doc(test(attr(deny(unused_imports, unused_must_use))))] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn(missing_debug_implementations)] +#![forbid(unsafe_code)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate core as std; + +mod algo; + +use std::hash::Hasher; + +#[cfg(feature = "std")] +use std::io::{self, BufRead}; + +/// Adler-32 checksum calculator. +/// +/// An instance of this type is equivalent to an Adler-32 checksum: It can be created in the default +/// state via [`new`] (or the provided `Default` impl), or from a precalculated checksum via +/// [`from_checksum`], and the currently stored checksum can be fetched via [`checksum`]. +/// +/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any +/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although +/// that is not recommended (while every checksum is a hash function, they are not necessarily a +/// good one). +/// +/// # Examples +/// +/// Basic, piecewise checksum calculation: +/// +/// ``` +/// use adler2::Adler32; +/// +/// let mut adler = Adler32::new(); +/// +/// adler.write_slice(&[0, 1, 2]); +/// adler.write_slice(&[3, 4, 5]); +/// +/// assert_eq!(adler.checksum(), 0x00290010); +/// ``` +/// +/// Using `Hash` to process structures: +/// +/// ``` +/// use std::hash::Hash; +/// use adler2::Adler32; +/// +/// #[derive(Hash)] +/// struct Data { +/// byte: u8, +/// word: u16, +/// big: u64, +/// } +/// +/// let mut adler = Adler32::new(); +/// +/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 }; +/// data.hash(&mut adler); +/// +/// // hash value depends on architecture endianness +/// if cfg!(target_endian = "little") { +/// assert_eq!(adler.checksum(), 0x33410990); +/// } +/// if cfg!(target_endian = "big") { +/// assert_eq!(adler.checksum(), 0x331F0990); +/// } +/// +/// ``` +/// +/// [`new`]: #method.new +/// [`from_checksum`]: #method.from_checksum +/// [`checksum`]: #method.checksum +#[derive(Debug, Copy, Clone)] +pub struct Adler32 { + a: u16, + b: u16, +} + +impl Adler32 { + /// Creates a new Adler-32 instance with default state. + #[inline] + pub fn new() -> Self { + Self::default() + } + + /// Creates an `Adler32` instance from a precomputed Adler-32 checksum. + /// + /// This allows resuming checksum calculation without having to keep the `Adler32` instance + /// around. + /// + /// # Example + /// + /// ``` + /// # use adler2::Adler32; + /// let parts = [ + /// "rust", + /// "acean", + /// ]; + /// let whole = adler2::adler32_slice(b"rustacean"); + /// + /// let mut sum = Adler32::new(); + /// sum.write_slice(parts[0].as_bytes()); + /// let partial = sum.checksum(); + /// + /// // ...later + /// + /// let mut sum = Adler32::from_checksum(partial); + /// sum.write_slice(parts[1].as_bytes()); + /// assert_eq!(sum.checksum(), whole); + /// ``` + #[inline] + pub const fn from_checksum(sum: u32) -> Self { + Adler32 { + a: sum as u16, + b: (sum >> 16) as u16, + } + } + + /// Returns the calculated checksum at this point in time. + #[inline] + pub fn checksum(&self) -> u32 { + (u32::from(self.b) << 16) | u32::from(self.a) + } + + /// Adds `bytes` to the checksum calculation. + /// + /// If efficiency matters, this should be called with Byte slices that contain at least a few + /// thousand Bytes. + pub fn write_slice(&mut self, bytes: &[u8]) { + self.compute(bytes); + } +} + +impl Default for Adler32 { + #[inline] + fn default() -> Self { + Adler32 { a: 1, b: 0 } + } +} + +impl Hasher for Adler32 { + #[inline] + fn finish(&self) -> u64 { + u64::from(self.checksum()) + } + + fn write(&mut self, bytes: &[u8]) { + self.write_slice(bytes); + } +} + +/// Calculates the Adler-32 checksum of a byte slice. +/// +/// This is a convenience function around the [`Adler32`] type. +/// +/// [`Adler32`]: struct.Adler32.html +pub fn adler32_slice(data: &[u8]) -> u32 { + let mut h = Adler32::new(); + h.write_slice(data); + h.checksum() +} + +/// Calculates the Adler-32 checksum of a `BufRead`'s contents. +/// +/// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an +/// error). +/// +/// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling +/// this function. +/// +/// # Errors +/// +/// Any error returned by the reader are bubbled up by this function. +/// +/// # Examples +/// +/// ```no_run +/// # fn run() -> Result<(), Box> { +/// use adler2::adler32; +/// +/// use std::fs::File; +/// use std::io::BufReader; +/// +/// let file = File::open("input.txt")?; +/// let mut file = BufReader::new(file); +/// +/// adler32(&mut file)?; +/// # Ok(()) } +/// # fn main() { run().unwrap() } +/// ``` +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn adler32(mut reader: R) -> io::Result { + let mut h = Adler32::new(); + loop { + let len = { + let buf = reader.fill_buf()?; + if buf.is_empty() { + return Ok(h.checksum()); + } + + h.write_slice(buf); + buf.len() + }; + reader.consume(len); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn zeroes() { + assert_eq!(adler32_slice(&[]), 1); + assert_eq!(adler32_slice(&[0]), 1 | 1 << 16); + assert_eq!(adler32_slice(&[0, 0]), 1 | 2 << 16); + assert_eq!(adler32_slice(&[0; 100]), 0x00640001); + assert_eq!(adler32_slice(&[0; 1024]), 0x04000001); + assert_eq!(adler32_slice(&[0; 1024 * 1024]), 0x00f00001); + } + + #[test] + fn ones() { + assert_eq!(adler32_slice(&[0xff; 1024]), 0x79a6fc2e); + assert_eq!(adler32_slice(&[0xff; 1024 * 1024]), 0x8e88ef11); + } + + #[test] + fn mixed() { + assert_eq!(adler32_slice(&[1]), 2 | 2 << 16); + assert_eq!(adler32_slice(&[40]), 41 | 41 << 16); + + assert_eq!(adler32_slice(&[0xA5; 1024 * 1024]), 0xd5009ab1); + } + + /// Example calculation from https://en.wikipedia.org/wiki/Adler-32. + #[test] + fn wiki() { + assert_eq!(adler32_slice(b"Wikipedia"), 0x11E60398); + } + + #[test] + fn resume() { + let mut adler = Adler32::new(); + adler.write_slice(&[0xff; 1024]); + let partial = adler.checksum(); + assert_eq!(partial, 0x79a6fc2e); // from above + adler.write_slice(&[0xff; 1024 * 1024 - 1024]); + assert_eq!(adler.checksum(), 0x8e88ef11); // from above + + // Make sure that we can resume computing from the partial checksum via `from_checksum`. + let mut adler = Adler32::from_checksum(partial); + adler.write_slice(&[0xff; 1024 * 1024 - 1024]); + assert_eq!(adler.checksum(), 0x8e88ef11); // from above + } + + #[cfg(feature = "std")] + #[test] + fn bufread() { + use std::io::BufReader; + fn test(data: &[u8], checksum: u32) { + // `BufReader` uses an 8 KB buffer, so this will test buffer refilling. + let mut buf = BufReader::new(data); + let real_sum = adler32(&mut buf).unwrap(); + assert_eq!(checksum, real_sum); + } + + test(&[], 1); + test(&[0; 1024], 0x04000001); + test(&[0; 1024 * 1024], 0x00f00001); + test(&[0xA5; 1024 * 1024], 0xd5009ab1); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/adler32/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"9e33701960053fa4c3fe2e5700bdd1fc17c6a7ff3d1cd617cb4f23cc01123a0c","LICENSE":"f5af8beef8f5f88f1b78494703bbfa019c4f3630ac111344390d6f9975ab22ed","README.md":"022d9b80f7ecec822a9f005f311d990f94a061970e7b982c85978675ff48de17","src/bench.rs":"bf3353d119660f44e4c2ef06d34c74e9585984cd7a82df609d51250476bdf2d0","src/lib.rs":"4f203fd48b12052f950213249a55db0b1c6cde93fe3bdf26b70a6eb42c6c9dee"},"package":"aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/adler32/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/Cargo.toml 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "adler32" -version = "1.2.0" -authors = ["Remi Rampin "] -description = "Minimal Adler32 implementation for Rust." -documentation = "https://docs.rs/adler32/" -readme = "README.md" -keywords = ["adler32", "hash", "rolling"] -license = "Zlib" -repository = "https://github.com/remram44/adler32-rs" - -[lib] -bench = false - -[[bench]] -name = "bench" -path = "src/bench.rs" -harness = false -[dependencies.compiler_builtins] -version = "0.1.2" -optional = true - -[dependencies.core] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-core" -[dev-dependencies.criterion] -version = "0.3" - -[dev-dependencies.getrandom] -version = "0.1" -features = ["wasm-bindgen"] - -[dev-dependencies.humansize] -version = "1.1" - -[dev-dependencies.rand] -version = "0.7" - -[features] -default = ["std"] -rustc-dep-of-std = ["core", "compiler_builtins"] -std = [] -[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen] -version = "0.2.63" - -[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test] -version = "0.3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/adler32/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/LICENSE 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -Copyright notice for the Rust port: - - (C) 2016 Remi Rampin and adler32-rs contributors - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -Copyright notice for the original C code from the zlib project: - - (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/README.md clamav-1.4.6+dfsg/.cargo/vendor/adler32/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/README.md 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -[![Build Status](https://github.com/remram44/adler32-rs/workflows/Test/badge.svg)](https://github.com/remram44/adler32-rs/actions) -[![Win Build](https://ci.appveyor.com/api/projects/status/ekyg20rd6rwrus64/branch/master?svg=true)](https://ci.appveyor.com/project/remram44/adler32-rs) -[![Crates.io](https://img.shields.io/crates/v/adler32.svg)](https://crates.io/crates/adler32) -[![Documentation](https://docs.rs/adler32/badge.svg)](https://docs.rs/adler32) -[![License](https://img.shields.io/crates/l/adler32.svg)](https://github.com/remram44/adler32-rs/blob/master/LICENSE) - -What is this? -============= - -It is an implementation of the [Adler32 rolling hash algorithm](https://en.wikipedia.org/wiki/Adler-32) in the [Rust programming language](https://www.rust-lang.org/). - -It is adapted from Jean-Loup Gailly's and Mark Adler's [original implementation in zlib](https://github.com/madler/zlib/blob/2fa463bacfff79181df1a5270fb67cc679a53e71/adler32.c). - - -#### Minimum Supported Version of Rust (MSRV) - -`adler32-rs` can be built with Rust version 1.33 or later. This version may be raised in the future but that will be accompanied by a minor version increase. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/src/bench.rs clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/bench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/src/bench.rs 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/bench.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -use adler32::RollingAdler32; -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; -use humansize::{file_size_opts, FileSize}; -use rand::Rng; - -fn bench_update_buffer(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let mut group = c.benchmark_group("update_buffer"); - for &size in [512, 100 * 1024].iter() { - let mut adler = RollingAdler32::new(); - let formatted_size = size.file_size(file_size_opts::BINARY).unwrap(); - let in_bytes = { - let mut in_bytes = vec![0u8; size]; - rng.fill(&mut in_bytes[..]); - in_bytes - }; - - group.throughput(Throughput::Bytes(size as u64)); - group.bench_with_input( - BenchmarkId::from_parameter(formatted_size), - &in_bytes, - |b, data| { - b.iter(|| adler.update_buffer(data)); - }, - ); - } -} - -criterion_group!(bench_default, bench_update_buffer); -criterion_main!(bench_default); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/adler32/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/adler32/src/lib.rs 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/adler32/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,324 +0,0 @@ -//! A minimal implementation of Adler32 for Rust. -//! -//! This provides the simple method adler32(), that exhausts a Read and -//! computes the Adler32 hash, as well as the RollingAdler32 struct, that can -//! build a hash byte-by-byte, allowing to 'forget' past bytes in a rolling -//! fashion. -//! -//! The adler32 code has been translated (as accurately as I could manage) from -//! the zlib implementation. - -#![forbid(unsafe_code)] -#![cfg_attr(not(feature = "std"), no_std)] - - -// adler32 algorithm and implementation taken from zlib; http://www.zlib.net/ -// It was translated into Rust as accurately as I could manage -// The (slow) reference was taken from Wikipedia; https://en.wikipedia.org/ - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 - - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -*/ - -// largest prime smaller than 65536 -const BASE: u32 = 65521; - -// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 -const NMAX: usize = 5552; - -#[inline(always)] -fn do1(adler: &mut u32, sum2: &mut u32, buf: &[u8]) { - *adler += u32::from(buf[0]); - *sum2 += *adler; -} - -#[inline(always)] -fn do2(adler: &mut u32, sum2: &mut u32, buf: &[u8]) { - do1(adler, sum2, &buf[0..1]); - do1(adler, sum2, &buf[1..2]); -} - -#[inline(always)] -fn do4(adler: &mut u32, sum2: &mut u32, buf: &[u8]) { - do2(adler, sum2, &buf[0..2]); - do2(adler, sum2, &buf[2..4]); -} - -#[inline(always)] -fn do8(adler: &mut u32, sum2: &mut u32, buf: &[u8]) { - do4(adler, sum2, &buf[0..4]); - do4(adler, sum2, &buf[4..8]); -} - -#[inline(always)] -fn do16(adler: &mut u32, sum2: &mut u32, buf: &[u8]) { - do8(adler, sum2, &buf[0..8]); - do8(adler, sum2, &buf[8..16]); -} - -/// A rolling version of the Adler32 hash, which can 'forget' past bytes. -/// -/// Calling remove() will update the hash to the value it would have if that -/// past byte had never been fed to the algorithm. This allows you to get the -/// hash of a rolling window very efficiently. -#[derive(Clone)] -pub struct RollingAdler32 { - a: u32, - b: u32, -} - -impl Default for RollingAdler32 { - fn default() -> RollingAdler32 { - RollingAdler32::new() - } -} - -impl RollingAdler32 { - /// Creates an empty Adler32 context (with hash 1). - pub fn new() -> RollingAdler32 { - Self::from_value(1) - } - - /// Creates an Adler32 context with the given initial value. - pub fn from_value(adler32: u32) -> RollingAdler32 { - let a = adler32 & 0xFFFF; - let b = adler32 >> 16; - RollingAdler32 { a, b } - } - - /// Convenience function initializing a context from the hash of a buffer. - pub fn from_buffer(buffer: &[u8]) -> RollingAdler32 { - let mut hash = RollingAdler32::new(); - hash.update_buffer(buffer); - hash - } - - /// Returns the current hash. - pub fn hash(&self) -> u32 { - (self.b << 16) | self.a - } - - /// Removes the given `byte` that was fed to the algorithm `size` bytes ago. - pub fn remove(&mut self, size: usize, byte: u8) { - let byte = u32::from(byte); - self.a = (self.a + BASE - byte) % BASE; - self.b = ((self.b + BASE - 1) - .wrapping_add(BASE.wrapping_sub(size as u32).wrapping_mul(byte))) - % BASE; - } - - /// Feeds a new `byte` to the algorithm to update the hash. - pub fn update(&mut self, byte: u8) { - let byte = u32::from(byte); - self.a = (self.a + byte) % BASE; - self.b = (self.b + self.a) % BASE; - } - - /// Feeds a vector of bytes to the algorithm to update the hash. - pub fn update_buffer(&mut self, buffer: &[u8]) { - let len = buffer.len(); - - // in case user likes doing a byte at a time, keep it fast - if len == 1 { - self.update(buffer[0]); - return; - } - - // in case short lengths are provided, keep it somewhat fast - if len < 16 { - for byte in buffer.iter().take(len) { - self.a += u32::from(*byte); - self.b += self.a; - } - if self.a >= BASE { - self.a -= BASE; - } - self.b %= BASE; - return; - } - - let mut pos = 0; - - // do length NMAX blocks -- requires just one modulo operation; - while pos + NMAX <= len { - let end = pos + NMAX; - while pos < end { - // 16 sums unrolled - do16(&mut self.a, &mut self.b, &buffer[pos..pos + 16]); - pos += 16; - } - self.a %= BASE; - self.b %= BASE; - } - - // do remaining bytes (less than NMAX, still just one modulo) - if pos < len { - // avoid modulos if none remaining - while len - pos >= 16 { - do16(&mut self.a, &mut self.b, &buffer[pos..pos + 16]); - pos += 16; - } - while len - pos > 0 { - self.a += u32::from(buffer[pos]); - self.b += self.a; - pos += 1; - } - self.a %= BASE; - self.b %= BASE; - } - } -} - -/// Consume a Read object and returns the Adler32 hash. -#[cfg(feature = "std")] -pub fn adler32(mut reader: R) -> std::io::Result { - let mut hash = RollingAdler32::new(); - let mut buffer = [0u8; NMAX]; - let mut read = reader.read(&mut buffer)?; - while read > 0 { - hash.update_buffer(&buffer[..read]); - read = reader.read(&mut buffer)?; - } - Ok(hash.hash()) -} - -#[cfg(test)] -mod test { - use rand::Rng; - use std::io; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test; - - use super::{adler32, RollingAdler32, BASE}; - - fn adler32_slow(reader: R) -> io::Result { - let mut a: u32 = 1; - let mut b: u32 = 0; - - for byte in reader.bytes() { - let byte = byte? as u32; - a = (a + byte) % BASE; - b = (b + a) % BASE; - } - - Ok((b << 16) | a) - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn testvectors() { - fn do_test(v: u32, bytes: &[u8]) { - let mut hash = RollingAdler32::new(); - hash.update_buffer(&bytes); - assert_eq!(hash.hash(), v); - - let r = io::Cursor::new(bytes); - assert_eq!(adler32(r).unwrap(), v); - } - do_test(0x00000001, b""); - do_test(0x00620062, b"a"); - do_test(0x024d0127, b"abc"); - do_test(0x29750586, b"message digest"); - do_test(0x90860b20, b"abcdefghijklmnopqrstuvwxyz"); - do_test( - 0x8adb150c, - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789", - ); - do_test( - 0x97b61069, - b"1234567890123456789012345678901234567890\ - 1234567890123456789012345678901234567890", - ); - do_test(0xD6251498, &[255; 64000]); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn compare() { - let mut rng = rand::thread_rng(); - let mut data = vec![0u8; 5589]; - for size in [ - 0, 1, 3, 4, 5, 31, 32, 33, 67, 5550, 5552, 5553, 5568, 5584, 5589, - ] - .iter() - .cloned() - { - rng.fill(&mut data[..size]); - let r1 = io::Cursor::new(&data[..size]); - let r2 = r1.clone(); - if adler32_slow(r1).unwrap() != adler32(r2).unwrap() { - panic!("Comparison failed, size={}", size); - } - } - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn rolling() { - assert_eq!(RollingAdler32::from_value(0x01020304).hash(), 0x01020304); - - fn do_test(a: &[u8], b: &[u8]) { - let mut total = Vec::with_capacity(a.len() + b.len()); - total.extend(a); - total.extend(b); - let mut h = RollingAdler32::from_buffer(&total[..(b.len())]); - for i in 0..(a.len()) { - h.remove(b.len(), a[i]); - h.update(total[b.len() + i]); - } - assert_eq!(h.hash(), adler32(b).unwrap()); - } - do_test(b"a", b"b"); - do_test(b"", b"this a test"); - do_test(b"th", b"is a test"); - do_test(b"this a ", b"test"); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn long_window_remove() { - let mut hash = RollingAdler32::new(); - let w = 65536; - assert!(w as u32 > BASE); - - let mut bytes = vec![0; w * 3]; - for (i, b) in bytes.iter_mut().enumerate() { - *b = i as u8; - } - - for (i, b) in bytes.iter().enumerate() { - if i >= w { - hash.remove(w, bytes[i - w]); - } - hash.update(*b); - if i > 0 && i % w == 0 { - assert_eq!(hash.hash(), 0x433a8772); - } - } - assert_eq!(hash.hash(), 0xbbba8772); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"88c12a803c6c06c47cd9dabc8bcdba81f35d3bab637221d2106a86a543532731","DESIGN.md":"59c960e1b73b1d7fb41e4df6c0c1b1fcf44dd2ebc8a349597a7d0595f8cb5130","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"afc4d559a98cf190029af0bf320fc0022725e349cd2a303aac860254e28f3c53","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"c699c07df70be45c666e128509ad571a7649d2073e4ae16ac1efd6793c9c6890","src/automaton.rs":"22258a3e118672413119f8f543a9b912cce954e63524575c0ebfdf9011f9c2dd","src/dfa.rs":"bfef1a94c5e7410584b1beb4e857b40d1ae2031b881cbc06fb1300409bbd555f","src/lib.rs":"2a92d5c5e930f2d306508802e8a929135e1f41c9f5f8deda8f7eb98947179dd2","src/macros.rs":"c6c52ae05b24433cffaca7b78b3645d797862c5d5feffddf9f54909095ed6e05","src/nfa/contiguous.rs":"aeb6ee5fd80eea04decbc4b46aa27d1ab270b78d416a644da25b7934f009ee66","src/nfa/mod.rs":"ee7b3109774d14bbad5239c16bb980dd6b8185ec136d94fbaf2f0dc27d5ffa15","src/nfa/noncontiguous.rs":"de94f02b04efd8744fb096759a8897c22012b0e0ca3ace161fd87c71befefe04","src/packed/api.rs":"160d3b10823316f7b0924e13c3afd222c8a7db5c0a00432401f311ef27d6a1b7","src/packed/ext.rs":"66be06fde8558429da23a290584d4b9fae665bf64c2578db4fe5f5f3ee864869","src/packed/mod.rs":"0020cd6f07ba5c8955923a9516d7f758864260eda53a6b6f629131c45ddeec62","src/packed/pattern.rs":"1e3a289a730c141fc30b295811e372d046c6619c7fd670308299b889a06c7673","src/packed/rabinkarp.rs":"403146eb1d838a84601d171393542340513cd1ee7ff750f2372161dd47746586","src/packed/teddy/README.md":"3a43194b64e221543d885176aba3beb1224a927385a20eca842daf6b0ea2f342","src/packed/teddy/builder.rs":"08ec116a4a842a2bb1221d296a2515ef3672c54906bed588fb733364c07855d3","src/packed/teddy/generic.rs":"ea252ab05b32cea7dd9d71e332071d243db7dd0362e049252a27e5881ba2bf39","src/packed/teddy/mod.rs":"17d741f7e2fb9dbac5ba7d1bd4542cf1e35e9f146ace728e23fe6bbed20028b2","src/packed/tests.rs":"8e2f56eb3890ed3876ecb47d3121996e416563127b6430110d7b516df3f83b4b","src/packed/vector.rs":"70c325cfa6f7c5c4c9a6af7b133b75a29e65990a7fe0b9a4c4ce3c3d5a0fe587","src/tests.rs":"c68192ab97b6161d0d6ee96fefd80cc7d14e4486ddcd8d1f82b5c92432c24ed5","src/transducer.rs":"02daa33a5d6dac41dcfd67f51df7c0d4a91c5131c781fb54c4de3520c585a6e1","src/util/alphabet.rs":"6dc22658a38deddc0279892035b18870d4585069e35ba7c7e649a24509acfbcc","src/util/buffer.rs":"f9e37f662c46c6ecd734458dedbe76c3bb0e84a93b6b0117c0d4ad3042413891","src/util/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/util/debug.rs":"ab301ad59aa912529cb97233a54a05914dd3cb2ec43e6fec7334170b97ac5998","src/util/error.rs":"ecccd60e7406305023efcc6adcc826eeeb083ab8f7fbfe3d97469438cd4c4e5c","src/util/int.rs":"e264e6abebf5622b59f6500210773db36048371c4e509c930263334095959a52","src/util/mod.rs":"7ab28d11323ecdbd982087f32eb8bceeee84f1a2583f3aae27039c36d58cf12c","src/util/prefilter.rs":"9fa4498f18bf70478b1996c1a013698b626d15f119aa81dbc536673c9f045718","src/util/primitives.rs":"f89f3fa1d8db4e37de9ca767c6d05e346404837cade6d063bba68972fafa610b","src/util/remapper.rs":"9f12d911583a325c11806eeceb46d0dfec863cfcfa241aed84d31af73da746e5","src/util/search.rs":"6af803e08b8b8c8a33db100623f1621b0d741616524ce40893d8316897f27ffe","src/util/special.rs":"7d2f9cb9dd9771f59816e829b2d96b1239996f32939ba98764e121696c52b146"},"package":"8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"69f4ef9c995781116d3f30c158ef6b558916fa67130ede33f22564251b580a1f",".github/workflows/ci.yml":"0605d9327a4633916dc789008d5686c692656bb3e1ee57f821f8537e9ad7d7b4",".vim/coc-settings.json":"8237c8f41db352b0d83f1bb10a60bc2f60f56f3234afbf696b4075c8d4d62d9b","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"88c12a803c6c06c47cd9dabc8bcdba81f35d3bab637221d2106a86a543532731","Cargo.toml.orig":"9526bde160fb3ea38179bd295cd94ddf1e3d8cd8cc1ed3a153664e3c90d3c970","DESIGN.md":"59c960e1b73b1d7fb41e4df6c0c1b1fcf44dd2ebc8a349597a7d0595f8cb5130","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"afc4d559a98cf190029af0bf320fc0022725e349cd2a303aac860254e28f3c53","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"c699c07df70be45c666e128509ad571a7649d2073e4ae16ac1efd6793c9c6890","src/automaton.rs":"22258a3e118672413119f8f543a9b912cce954e63524575c0ebfdf9011f9c2dd","src/dfa.rs":"bfef1a94c5e7410584b1beb4e857b40d1ae2031b881cbc06fb1300409bbd555f","src/lib.rs":"2a92d5c5e930f2d306508802e8a929135e1f41c9f5f8deda8f7eb98947179dd2","src/macros.rs":"c6c52ae05b24433cffaca7b78b3645d797862c5d5feffddf9f54909095ed6e05","src/nfa/contiguous.rs":"aeb6ee5fd80eea04decbc4b46aa27d1ab270b78d416a644da25b7934f009ee66","src/nfa/mod.rs":"ee7b3109774d14bbad5239c16bb980dd6b8185ec136d94fbaf2f0dc27d5ffa15","src/nfa/noncontiguous.rs":"de94f02b04efd8744fb096759a8897c22012b0e0ca3ace161fd87c71befefe04","src/packed/api.rs":"160d3b10823316f7b0924e13c3afd222c8a7db5c0a00432401f311ef27d6a1b7","src/packed/ext.rs":"66be06fde8558429da23a290584d4b9fae665bf64c2578db4fe5f5f3ee864869","src/packed/mod.rs":"0020cd6f07ba5c8955923a9516d7f758864260eda53a6b6f629131c45ddeec62","src/packed/pattern.rs":"1e3a289a730c141fc30b295811e372d046c6619c7fd670308299b889a06c7673","src/packed/rabinkarp.rs":"403146eb1d838a84601d171393542340513cd1ee7ff750f2372161dd47746586","src/packed/teddy/README.md":"3a43194b64e221543d885176aba3beb1224a927385a20eca842daf6b0ea2f342","src/packed/teddy/builder.rs":"08ec116a4a842a2bb1221d296a2515ef3672c54906bed588fb733364c07855d3","src/packed/teddy/generic.rs":"ea252ab05b32cea7dd9d71e332071d243db7dd0362e049252a27e5881ba2bf39","src/packed/teddy/mod.rs":"17d741f7e2fb9dbac5ba7d1bd4542cf1e35e9f146ace728e23fe6bbed20028b2","src/packed/tests.rs":"8e2f56eb3890ed3876ecb47d3121996e416563127b6430110d7b516df3f83b4b","src/packed/vector.rs":"70c325cfa6f7c5c4c9a6af7b133b75a29e65990a7fe0b9a4c4ce3c3d5a0fe587","src/tests.rs":"c68192ab97b6161d0d6ee96fefd80cc7d14e4486ddcd8d1f82b5c92432c24ed5","src/transducer.rs":"02daa33a5d6dac41dcfd67f51df7c0d4a91c5131c781fb54c4de3520c585a6e1","src/util/alphabet.rs":"6dc22658a38deddc0279892035b18870d4585069e35ba7c7e649a24509acfbcc","src/util/buffer.rs":"f9e37f662c46c6ecd734458dedbe76c3bb0e84a93b6b0117c0d4ad3042413891","src/util/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/util/debug.rs":"ab301ad59aa912529cb97233a54a05914dd3cb2ec43e6fec7334170b97ac5998","src/util/error.rs":"ecccd60e7406305023efcc6adcc826eeeb083ab8f7fbfe3d97469438cd4c4e5c","src/util/int.rs":"e264e6abebf5622b59f6500210773db36048371c4e509c930263334095959a52","src/util/mod.rs":"7ab28d11323ecdbd982087f32eb8bceeee84f1a2583f3aae27039c36d58cf12c","src/util/prefilter.rs":"9fa4498f18bf70478b1996c1a013698b626d15f119aa81dbc536673c9f045718","src/util/primitives.rs":"f89f3fa1d8db4e37de9ca767c6d05e346404837cade6d063bba68972fafa610b","src/util/remapper.rs":"9f12d911583a325c11806eeceb46d0dfec863cfcfa241aed84d31af73da746e5","src/util/search.rs":"6af803e08b8b8c8a33db100623f1621b0d741616524ce40893d8316897f27ffe","src/util/special.rs":"7d2f9cb9dd9771f59816e829b2d96b1239996f32939ba98764e121696c52b146"},"package":"8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "56256dca1bcd2365fd1dc987c1c06195429a2e2c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,148 @@ +name: ci +on: + pull_request: + push: + branches: + - master + schedule: + - cron: '00 01 * * *' + +# The section is needed to drop write-all permissions that are granted on +# `schedule` event. By specifying any permission explicitly all others are set +# to none. By using the principle of least privilege the damage a compromised +# workflow can do (because of an injection or compromised third party tool or +# action) is restricted. Currently the worklow doesn't need any additional +# permission except for pulling the code. Adding labels to issues, commenting +# on pull-requests, etc. may need additional permissions: +# +# Syntax for this section: +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions +# +# Reference for how to assign permissions on a job-by-job basis: +# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs +# +# Reference for available permissions that we can enable if needed: +# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token +permissions: + # to fetch code (actions/checkout) + contents: read + +jobs: + test: + name: test + env: + # For some builds, we use cross to test on 32-bit and big-endian + # systems. + CARGO: cargo + # When CARGO is set to CROSS, TARGET is set to `--target matrix.target`. + # Note that we only use cross on Linux, so setting a target on a + # different OS will just use normal cargo. + TARGET: + # Bump this as appropriate. We pin to a version to make sure CI + # continues to work as cross releases in the past have broken things + # in subtle ways. + CROSS_VERSION: v0.2.5 + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - build: pinned + os: ubuntu-latest + rust: 1.60.0 + - build: stable + os: ubuntu-latest + rust: stable + - build: stable-x86 + os: ubuntu-latest + rust: stable + target: i686-unknown-linux-gnu + - build: stable-aarch64 + os: ubuntu-latest + rust: stable + target: aarch64-unknown-linux-gnu + - build: stable-powerpc64 + os: ubuntu-latest + rust: stable + target: powerpc64-unknown-linux-gnu + - build: stable-s390x + os: ubuntu-latest + rust: stable + target: s390x-unknown-linux-gnu + - build: beta + os: ubuntu-latest + rust: beta + - build: nightly + os: ubuntu-latest + rust: nightly + - build: macos + os: macos-latest + rust: stable + - build: win-msvc + os: windows-latest + rust: stable + - build: win-gnu + os: windows-latest + rust: stable-x86_64-gnu + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - name: Install and configure Cross + if: matrix.os == 'ubuntu-latest' && matrix.target != '' + run: | + # In the past, new releases of 'cross' have broken CI. So for now, we + # pin it. We also use their pre-compiled binary releases because cross + # has over 100 dependencies and takes a bit to compile. + dir="$RUNNER_TEMP/cross-download" + mkdir "$dir" + echo "$dir" >> $GITHUB_PATH + cd "$dir" + curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz" + tar xf cross-x86_64-unknown-linux-musl.tar.gz + + # We used to install 'cross' from master, but it kept failing. So now + # we build from a known-good version until 'cross' becomes more stable + # or we find an alternative. Notably, between v0.2.1 and current + # master (2022-06-14), the number of Cross's dependencies has doubled. + echo "CARGO=cross" >> $GITHUB_ENV + echo "TARGET=--target ${{ matrix.target }}" >> $GITHUB_ENV + - name: Show command used for Cargo + run: | + echo "cargo command is: ${{ env.CARGO }}" + echo "target flag is: ${{ env.TARGET }}" + - name: Show CPU info for debugging + if: matrix.os == 'ubuntu-latest' + run: lscpu + # See: https://github.com/rust-lang/regex/blob/a2887636930156023172e4b376a6febad4e49120/.github/workflows/ci.yml#L145-L163 + - name: Pin memchr to 2.6.2 + if: matrix.build == 'pinned' + run: cargo update -p memchr --precise 2.6.2 + - run: ${{ env.CARGO }} build --verbose $TARGET + - run: ${{ env.CARGO }} doc --verbose $TARGET + - run: ${{ env.CARGO }} test --verbose $TARGET + - run: ${{ env.CARGO }} test --lib --verbose --no-default-features --features std,perf-literal $TARGET + - run: ${{ env.CARGO }} test --lib --verbose --no-default-features $TARGET + - run: ${{ env.CARGO }} test --lib --verbose --no-default-features --features std $TARGET + - run: ${{ env.CARGO }} test --lib --verbose --no-default-features --features perf-literal $TARGET + - run: ${{ env.CARGO }} test --lib --verbose --no-default-features --features std,perf-literal,logging $TARGET + - if: matrix.build == 'nightly' + run: ${{ env.CARGO }} build --manifest-path aho-corasick-debug/Cargo.toml $TARGET + + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - name: Check formatting + run: | + cargo fmt --all -- --check diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.vim/coc-settings.json clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.vim/coc-settings.json --- clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/.vim/coc-settings.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/.vim/coc-settings.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "rust-analyzer.linkedProjects": [ + "aho-corasick-debug/Cargo.toml", + "benchmarks/engines/rust-aho-corasick/Cargo.toml", + "benchmarks/engines/rust-daachorse/Cargo.toml", + "benchmarks/engines/rust-jetscii/Cargo.toml", + "benchmarks/engines/naive/Cargo.toml", + "benchmarks/shared/Cargo.toml", + "fuzz/Cargo.toml", + "Cargo.toml" + ] +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/aho-corasick/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aho-corasick/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +[package] +name = "aho-corasick" +version = "1.1.3" #:version +authors = ["Andrew Gallant "] +description = "Fast multiple substring searching." +homepage = "https://github.com/BurntSushi/aho-corasick" +repository = "https://github.com/BurntSushi/aho-corasick" +readme = "README.md" +keywords = ["string", "search", "text", "pattern", "multi"] +license = "Unlicense OR MIT" +categories = ["text-processing"] +autotests = false +exclude = ["/aho-corasick-debug", "/benchmarks", "/tmp"] +edition = "2021" +rust-version = "1.60.0" + +[lib] +name = "aho_corasick" + +[features] +default = ["std", "perf-literal"] +std = ["memchr?/std"] + +# Enables prefilter optimizations that depend on external crates. +perf-literal = ["dep:memchr"] + +# Enable logging via the 'log' crate. This is useful for seeing messages about +# internal decisions and metrics. For example, how the choice of the internal +# Aho-Corasick implementation is used or the heap usage of an automaton. +logging = ["dep:log"] + +# Provides a trait impl for fst::Automaton for nfa::noncontiguous::NFA, +# nfa::contiguous::NFA and dfa::DFA. This is useful for searching an +# FST with an Aho-Corasick automaton. Note that this does not apply +# to the top-level 'AhoCorasick' type, as it does not implement the +# aho_corasick::automaton::Automaton trait, and thus enabling this feature does +# not cause it to implement fst::Automaton either. +# +# NOTE: Currently this feature is not available as `fst` is not at 1.0 yet, +# and this would make `fst` a public dependency. If you absolutely need this, +# you can copy the (very small) src/transducer.rs file to your tree. It +# specifically does not use any private APIs and should work after replacing +# 'crate::' with 'aho_corasick::'. +# +# NOTE: I think my current plan is to flip this around an add an optional +# dependency on 'aho-corasick' to the 'fst' crate and move the trait impls +# there. But I haven't gotten around to it yet. +# transducer = ["fst"] + +[dependencies] +log = { version = "0.4.17", optional = true } +memchr = { version = "2.4.0", default-features = false, optional = true } + +[dev-dependencies] +doc-comment = "0.3.3" +# fst = "0.4.5" + +[package.metadata.docs.rs] +# We want to document all features. +all-features = true +# This opts into a nightly unstable option to show the features that need to be +# enabled for public API items. To do that, we set 'docsrs', and when that's +# enabled, we enable the 'doc_auto_cfg' feature. +# +# To test this locally, run: +# +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features +rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"] + +[profile.release] +debug = true + +[profile.bench] +debug = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"336cad224bf0129d9a06f98030bd62364032703de1b08994b99e9b5d717c802e",".github/workflows/ci.yml":"9b5a782cf1e8686e72e3b5fff1982b4a2efde1c4f9904f61330d81ba094860ba","CHANGELOG.md":"cbe3d02b3f8225c11024cded68947c59bd7b5dbf0f05afda3501b79e6c11ab5f","Cargo.lock":"85d4b0192caa7753ffe82164009dd07c13a57eabe393e02367ae183f5deb1e8b","Cargo.toml":"2251347152627ee098bd5688d4b37683588be80814f4b88f0d5ed6ea446eb5ed","Cargo.toml.orig":"8104bcada256667eb654fdcb3a335934e1703a25e4832d7ebafe2888d0039bac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"035e70219855119df4273b3c5b97543ae82e0dd60c520416e759107c602f651b","README.md":"8d00f833cad16186fb28e0e12934f28787bd377b9892b84649f6758a5fe02778","bors.toml":"b96eaac6b3dc8487a2bcc6cb415e745a28d9a61937090df48186c62d2b614aeb","src/lib.rs":"7def13ff0b37b50f7bfdd4d75830ebf27110290b78af896837648bbb4fd9c75f"},"package":"ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f13f8e56db5ab99257209758d14d3096a851ff04" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/aligned/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: cargo test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo test \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/aligned/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,122 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [v0.4.3] - 2025-12-14 + +### Added + +- Support indexing with most `core::ops::Range*` types. + +### Changed + +### Removed + +## [v0.4.2] - 2024-03-24 + +### Added + +- Add `A1` type +- Make the `Alignment` trait public, but unimplementable +- Add some `Borrow`/`BorrowMut` trait impls + +### Changed + +### Removed + +## [v0.4.1] - 2022-05-30 + +### Added + +- `Aligned` implements `Copy` if `T` implements `Copy` + +## [v0.4.0] - 2021-07-24 + +### Changed + +- `as-slice` dependency bumped to 0.2.0 + +### Removed + +- [breaking-change] removed compatibility withe version 0.1.0 of `AsSlice` and `AsMutSlice` traits (`as-slice` crate) + +## [v0.3.5] - 2021-07-17 + +- added `A32` and `A64` types + +## [v0.3.4] - 2020-07-31 + +### Added + +- `Aligned` now implements the `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` traits. + +## [v0.3.3] - 2020-07-28 + +### Added + +- `Aligned` now implements the `Clone`, `Default`, `Debug` and `Display` traits. +- `Aligned` has been marked `repr(C)` + +## [v0.3.2] - 2019-11-26 + +### Added + +- `Aligned<_, [T]>` now implements the `Index>` trait; slicing + this value to end returns an `Aligned<_, [T]>` slice. + +## [v0.3.1] - 2018-11-07 + +### Changed + +- Make deref work on Aligned. + +## [v0.3.0] - 2018-11-05 + +### Changed + +- [breaking-change] the alignment type parameter of `Aligned` must now be one + of: `A2`, `A4`, `A8` or `A16`. + +### Removed + +- [breaking-change] removed the `const-fn` feature. Const functions are now + provided by default. This crate now requires Rust 1.31+ to build. + +## [v0.2.0] - 2018-05-10 + +### Changed + +- [breaking-change] `const-fn` is no longer a default feature (i.e. a feature that's enabled by + default). The consequence is that this crate now compiles on 1.27 (beta) by default, and opting + into `const-fn` requires nightly. + +## [v0.1.2] - 2018-04-25 + +### Added + +- an opt-out "const-fn" Cargo feature. Disabling this feature removes all `const` constructors and + makes this crate compilable on stable. + +## [v0.1.1] - 2017-05-30 + +### Added + +- support for aligned slices + +## v0.1.0 - 2017-05-29 + +- Initial release + +[Unreleased]: https://github.com/japaric/aligned/compare/v0.4.1...HEAD +[v0.4.1]: https://github.com/japaric/aligned/compare/v0.4.0...v0.4.1 +[v0.4.0]: https://github.com/japaric/aligned/compare/v0.3.5...v0.4.0 +[v0.3.5]: https://github.com/japaric/aligned/compare/v0.3.4...v0.3.5 +[v0.3.4]: https://github.com/japaric/aligned/compare/v0.3.3...v0.3.4 +[v0.3.3]: https://github.com/japaric/aligned/compare/v0.3.2...v0.3.3 +[v0.3.2]: https://github.com/japaric/aligned/compare/v0.3.1...v0.3.2 +[v0.3.1]: https://github.com/japaric/aligned/compare/v0.3.0...v0.3.1 +[v0.3.0]: https://github.com/japaric/aligned/compare/v0.2.0...v0.3.0 +[v0.2.0]: https://github.com/japaric/aligned/compare/v0.1.2...v0.2.0 +[v0.1.2]: https://github.com/japaric/aligned/compare/v0.1.1...v0.1.2 +[v0.1.1]: https://github.com/japaric/aligned/compare/v0.1.0...v0.1.1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aligned" +version = "0.4.3" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,44 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +name = "aligned" +version = "0.4.3" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A newtype with alignment of at least `A` bytes" +documentation = "https://docs.rs/aligned" +readme = "README.md" +keywords = [ + "alignment", + "aligned", + "array", + "static", +] +categories = [ + "embedded", + "memory-management", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-embedded-community/aligned" + +[lib] +name = "aligned" +path = "src/lib.rs" + +[dependencies.as-slice] +version = "0.2.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +categories = ["embedded", "memory-management", "no-std"] +description = "A newtype with alignment of at least `A` bytes" +documentation = "https://docs.rs/aligned" +edition = "2024" +keywords = ["alignment", "aligned", "array", "static"] +license = "MIT OR Apache-2.0" +name = "aligned" +repository = "https://github.com/rust-embedded-community/aligned" +version = "0.4.3" + +[dependencies] +as-slice = "0.2.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2017 Jorge Aparicio + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/README.md clamav-1.4.6+dfsg/.cargo/vendor/aligned/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[![crates.io](https://img.shields.io/crates/v/aligned.svg)](https://crates.io/crates/aligned) +[![crates.io](https://img.shields.io/crates/d/aligned.svg)](https://crates.io/crates/aligned) + +# `aligned` + +> A newtype with alignment of at least `A` bytes + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/bors.toml clamav-1.4.6+dfsg/.cargo/vendor/aligned/bors.toml --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/bors.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/bors.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +status = [ + "continuous-integration/travis-ci/push", +] \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/aligned/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/aligned/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,869 @@ +//! A newtype with alignment of at least `A` bytes +//! +//! # Examples +//! +//! ``` +//! use std::mem; +//! +//! use aligned::{Aligned, A2, A4, A16}; +//! +//! // Array aligned to a 2 byte boundary +//! static X: Aligned = Aligned([0; 3]); +//! +//! // Array aligned to a 4 byte boundary +//! static Y: Aligned = Aligned([0; 3]); +//! +//! // Unaligned array +//! static Z: [u8; 3] = [0; 3]; +//! +//! // You can allocate the aligned arrays on the stack too +//! let w: Aligned = Aligned([0u8; 3]); +//! +//! assert_eq!(mem::align_of_val(&X), 2); +//! assert_eq!(mem::align_of_val(&Y), 4); +//! assert_eq!(mem::align_of_val(&Z), 1); +//! assert_eq!(mem::align_of_val(&w), 16); +//! ``` + +#![deny(missing_docs)] +#![deny(warnings)] +#![cfg_attr(not(test), no_std)] + +use core::{ + borrow::{Borrow, BorrowMut}, + cmp::Ordering, + fmt::{Debug, Display}, + hash::{Hash, Hasher}, + ops::{self}, +}; + +use as_slice::{AsMutSlice, AsSlice}; + +/// A marker trait for an alignment value. +pub trait Alignment: Copy + sealed::Sealed { + /// The alignment in bytes. + const ALIGN: usize; +} + +impl Alignment for A1 { + const ALIGN: usize = 1; +} +impl Alignment for A2 { + const ALIGN: usize = 2; +} +impl Alignment for A4 { + const ALIGN: usize = 4; +} +impl Alignment for A8 { + const ALIGN: usize = 8; +} +impl Alignment for A16 { + const ALIGN: usize = 16; +} +impl Alignment for A32 { + const ALIGN: usize = 32; +} +impl Alignment for A64 { + const ALIGN: usize = 64; +} + +mod sealed { + pub trait Sealed {} + + impl Sealed for super::A1 {} + impl Sealed for super::A2 {} + impl Sealed for super::A4 {} + impl Sealed for super::A8 {} + impl Sealed for super::A16 {} + impl Sealed for super::A32 {} + impl Sealed for super::A64 {} +} + +/// 1-byte alignment +#[derive(Clone, Copy)] +#[repr(align(1))] +pub struct A1; + +/// 2-byte alignment +#[derive(Clone, Copy)] +#[repr(align(2))] +pub struct A2; + +/// 4-byte alignment +#[derive(Clone, Copy)] +#[repr(align(4))] +pub struct A4; + +/// 8-byte alignment +#[derive(Clone, Copy)] +#[repr(align(8))] +pub struct A8; + +/// 16-byte alignment +#[derive(Clone, Copy)] +#[repr(align(16))] +pub struct A16; + +/// 32-byte alignment +#[derive(Clone, Copy)] +#[repr(align(32))] +pub struct A32; + +/// 64-byte alignment +#[derive(Clone, Copy)] +#[repr(align(64))] +pub struct A64; + +/// A newtype with alignment of at least `A` bytes +#[repr(C)] +pub struct Aligned +where + T: ?Sized, +{ + _alignment: [A; 0], + value: T, +} + +/// Changes the alignment of `value` to be at least `A` bytes +#[allow(non_snake_case)] +pub const fn Aligned(value: T) -> Aligned { + Aligned { + _alignment: [], + value, + } +} + +impl ops::Deref for Aligned +where + A: Alignment, + T: ?Sized, +{ + type Target = T; + + fn deref(&self) -> &T { + &self.value + } +} + +impl ops::DerefMut for Aligned +where + A: Alignment, + T: ?Sized, +{ + fn deref_mut(&mut self) -> &mut T { + &mut self.value + } +} + +impl Aligned +where + A: Alignment, +{ + fn is_index_aligned(index: usize) -> bool { + use core::mem::size_of; + + (index * size_of::()) % A::ALIGN == 0 + } + fn check_start_index(index: usize) { + if !Self::is_index_aligned(index) { + panic!("Unaligned start index"); + } + } +} + +impl ops::Index> for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::RangeFrom) -> &Aligned { + Self::check_start_index(range.start); + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::Index> for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::RangeTo) -> &Aligned { + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::Index> for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::RangeToInclusive) -> &Aligned { + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::Index> for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::RangeInclusive) -> &Aligned { + Self::check_start_index(*range.start()); + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::Index> for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::Range) -> &Aligned { + Self::check_start_index(range.start); + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::Index for Aligned +where + A: Alignment, +{ + type Output = Aligned; + + fn index(&self, range: ops::RangeFull) -> &Aligned { + unsafe { &*(&self.value[range] as *const [T] as *const Aligned) } + } +} + +impl ops::IndexMut> for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::RangeFrom) -> &mut Aligned { + Self::check_start_index(range.start); + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl ops::IndexMut> for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::RangeTo) -> &mut Aligned { + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl ops::IndexMut> for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::RangeToInclusive) -> &mut Aligned { + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl ops::IndexMut> for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::RangeInclusive) -> &mut Aligned { + Self::check_start_index(*range.start()); + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl ops::IndexMut> for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::Range) -> &mut Aligned { + Self::check_start_index(range.start); + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl ops::IndexMut for Aligned +where + A: Alignment, +{ + fn index_mut(&mut self, range: ops::RangeFull) -> &mut Aligned { + unsafe { &mut *(&mut self.value[range] as *mut [T] as *mut Aligned) } + } +} + +impl AsSlice for Aligned +where + A: Alignment, + T: AsSlice, +{ + type Element = T::Element; + + fn as_slice(&self) -> &[T::Element] { + T::as_slice(&**self) + } +} + +impl AsMutSlice for Aligned +where + A: Alignment, + T: AsMutSlice, +{ + fn as_mut_slice(&mut self) -> &mut [T::Element] { + T::as_mut_slice(&mut **self) + } +} + +impl Borrow for Aligned +where + A: Alignment, +{ + fn borrow(&self) -> &T { + &self.value + } +} + +impl BorrowMut for Aligned +where + A: Alignment, +{ + fn borrow_mut(&mut self) -> &mut T { + &mut self.value + } +} + +impl Borrow<[ as AsSlice>::Element]> for Aligned +where + A: Alignment, + Aligned: AsSlice, +{ + fn borrow(&self) -> &[ as AsSlice>::Element] { + self.as_slice() + } +} + +impl BorrowMut<[ as AsSlice>::Element]> for Aligned +where + A: Alignment, + Aligned: AsMutSlice, +{ + fn borrow_mut(&mut self) -> &mut [ as AsSlice>::Element] { + self.as_mut_slice() + } +} + +impl Clone for Aligned +where + A: Alignment, + T: Clone, +{ + fn clone(&self) -> Self { + Self { + _alignment: [], + value: self.value.clone(), + } + } +} + +impl Copy for Aligned +where + A: Alignment, + T: Copy, +{ +} + +impl Default for Aligned +where + A: Alignment, + T: Default, +{ + fn default() -> Self { + Self { + _alignment: [], + value: Default::default(), + } + } +} + +impl Debug for Aligned +where + A: Alignment, + T: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.value.fmt(f) + } +} + +impl Display for Aligned +where + A: Alignment, + T: Display, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.value.fmt(f) + } +} + +impl PartialEq for Aligned +where + A: Alignment, + T: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } +} + +impl Eq for Aligned +where + A: Alignment, + T: Eq, +{ +} + +impl Hash for Aligned +where + A: Alignment, + T: Hash, +{ + fn hash(&self, state: &mut H) { + self.value.hash(state); + } +} + +impl Ord for Aligned +where + A: Alignment, + T: Ord, +{ + fn cmp(&self, other: &Self) -> Ordering { + self.value.cmp(&other.value) + } +} + +impl PartialOrd for Aligned +where + A: Alignment, + T: PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.value.partial_cmp(&other.value) + } +} + +#[test] +fn sanity() { + use core::mem; + + let a: Aligned = Aligned([0u8; 3]); + let x: Aligned = Aligned([0u8; 3]); + let y: Aligned = Aligned([0u8; 3]); + let z: Aligned = Aligned([0u8; 3]); + let w: Aligned = Aligned([0u8; 3]); + + // check alignment + assert_eq!(mem::align_of_val(&a), 1); + assert_eq!(mem::align_of_val(&x), 2); + assert_eq!(mem::align_of_val(&y), 4); + assert_eq!(mem::align_of_val(&z), 8); + assert_eq!(mem::align_of_val(&w), 16); + + assert!(a.as_ptr() as usize % 1 == 0); + assert!(x.as_ptr() as usize % 2 == 0); + assert!(y.as_ptr() as usize % 4 == 0); + assert!(z.as_ptr() as usize % 8 == 0); + assert!(w.as_ptr() as usize % 16 == 0); + + // test `deref` + assert_eq!(a.len(), 3); + assert_eq!(x.len(), 3); + assert_eq!(y.len(), 3); + assert_eq!(z.len(), 3); + assert_eq!(w.len(), 3); + + // alignment should be preserved after slicing + let a: &Aligned<_, [_]> = &a; + let x: &Aligned<_, [_]> = &x; + let y: &Aligned<_, [_]> = &y; + let z: &Aligned<_, [_]> = &z; + let w: &Aligned<_, [_]> = &w; + + let a: &Aligned<_, _> = &a[..2]; + let x: &Aligned<_, _> = &x[..2]; + let y: &Aligned<_, _> = &y[..2]; + let z: &Aligned<_, _> = &z[..2]; + let w: &Aligned<_, _> = &w[..2]; + + assert!(a.as_ptr() as usize % 1 == 0); + assert!(x.as_ptr() as usize % 2 == 0); + assert!(y.as_ptr() as usize % 4 == 0); + assert!(z.as_ptr() as usize % 8 == 0); + assert!(w.as_ptr() as usize % 16 == 0); + + // alignment should be preserved after boxing + let a: Box> = Box::new(Aligned([0u8; 3])); + let x: Box> = Box::new(Aligned([0u8; 3])); + let y: Box> = Box::new(Aligned([0u8; 3])); + let z: Box> = Box::new(Aligned([0u8; 3])); + let w: Box> = Box::new(Aligned([0u8; 3])); + + assert_eq!(mem::align_of_val(&*a), 1); + assert_eq!(mem::align_of_val(&*x), 2); + assert_eq!(mem::align_of_val(&*y), 4); + assert_eq!(mem::align_of_val(&*z), 8); + assert_eq!(mem::align_of_val(&*w), 16); + + // test coercions + let x: Aligned = Aligned([0u8; 3]); + let y: &Aligned = &x; + let _: &[u8] = y; +} + +#[test] +fn test_range_to() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[..0]).as_slice(), &[],); + assert_eq!((&a[..1]).as_slice(), &[0],); + assert_eq!((&a[..2]).as_slice(), &[0, 1],); + assert_eq!((&a[..3]).as_slice(), &[0, 1, 2],); + assert_eq!((&a[..4]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_to_mut() { + let a: &mut Aligned = &mut Aligned::([0, 1, 2, 3]); + assert_eq!((&mut a[..0]).as_slice(), &[],); + assert_eq!((&mut a[..1]).as_slice(), &[0],); + assert_eq!((&mut a[..2]).as_slice(), &[0, 1],); + assert_eq!((&mut a[..3]).as_slice(), &[0, 1, 2],); + assert_eq!((&mut a[..4]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_to_inclusive() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[..=0]).as_slice(), &[0],); + assert_eq!((&a[..=1]).as_slice(), &[0, 1],); + assert_eq!((&a[..=2]).as_slice(), &[0, 1, 2],); + assert_eq!((&a[..=3]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_to_inclusive_mut() { + let a: &mut Aligned = &mut Aligned::([0, 1, 2, 3]); + assert_eq!((&mut a[..=0]).as_slice(), &[0],); + assert_eq!((&mut a[..=1]).as_slice(), &[0, 1],); + assert_eq!((&mut a[..=2]).as_slice(), &[0, 1, 2],); + assert_eq!((&mut a[..=3]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_full() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[..]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_full_mut() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[..]).as_slice(), &[0, 1, 2, 3],); +} + +#[test] +fn test_range_from() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[0..]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&a[2..]).as_slice(), &[2, 3],); + assert_eq!((&a[4..]).as_slice(), &[],); + + let a: &Aligned = &Aligned::([0, 1, 2]); + assert_eq!((&a[0..]).as_slice(), &[0, 1, 2],); + assert_eq!((&a[2..]).as_slice(), &[2],); + + let a: &Aligned = &Aligned::([0, 1, 2, 3, 4, 5, 6, 7]); + assert_eq!((&a[0..]).as_slice(), &[0, 1, 2, 3, 4, 5, 6, 7],); + assert_eq!((&a[4..]).as_slice(), &[4, 5, 6, 7],); + assert_eq!((&a[8..]).as_slice(), &[],); + + let a: &Aligned = &Aligned::([0, 1, 2, 3, 4, 5, 6]); + assert_eq!((&a[0..]).as_slice(), &[0, 1, 2, 3, 4, 5, 6],); + assert_eq!((&a[4..]).as_slice(), &[4, 5, 6],); + + let a: &Aligned = + &Aligned::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + assert_eq!( + (&a[0..]).as_slice(), + &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + ); + assert_eq!((&a[8..]).as_slice(), &[8, 9, 10, 11, 12, 13, 14, 15],); + assert_eq!((&a[16..]).as_slice(), &[],); + + let a: &Aligned = + &Aligned::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]); + assert_eq!( + (&a[0..]).as_slice(), + &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], + ); + assert_eq!((&a[8..]).as_slice(), &[8, 9, 10, 11, 12, 13, 14],); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 + ], + ); + assert_eq!( + (&a[16..]).as_slice(), + &[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], + ); + assert_eq!((&a[32..]).as_slice(), &[],); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30 + ], + ); + assert_eq!( + (&a[16..]).as_slice(), + &[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], + ); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 + ] + ); + assert_eq!( + (&a[32..]).as_slice(), + &[ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 + ] + ); + assert_eq!((&a[64..]).as_slice(), &[],); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62 + ] + ); + assert_eq!( + (&a[32..]).as_slice(), + &[ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62 + ] + ); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127 + ] + ); + assert_eq!( + (&a[64..]).as_slice(), + &[ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127 + ] + ); + assert_eq!((&a[128..]).as_slice(), &[]); + + let a: &Aligned = &Aligned::([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + ]); + assert_eq!( + (&a[0..]).as_slice(), + &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126 + ] + ); + assert_eq!( + (&a[64..]).as_slice(), + &[ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126 + ] + ); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_from_a2_invalid_alignment() { + let a: &Aligned = &Aligned::([0u8; 4]); + let _ = &a[1..]; +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_from_a4_invalid_alignment() { + let a: &Aligned = &Aligned::([0u8; 8]); + let _ = &a[6..]; +} + +#[test] +fn test_range_from_mut() { + let a: &mut Aligned = &mut Aligned::([0, 1, 2, 3]); + assert_eq!((&mut a[0..]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&mut a[2..]).as_slice(), &[2, 3],); + assert_eq!((&mut a[4..]).as_slice(), &[],); + + let a: &mut Aligned = &mut Aligned::([0, 1, 2]); + assert_eq!((&mut a[0..]).as_slice(), &[0, 1, 2],); + assert_eq!((&mut a[2..]).as_slice(), &[2],); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_from_mut_invalid_argument() { + let a: &mut Aligned = &mut Aligned::([0u8; 4]); + let _ = &mut a[1..]; +} + +#[test] +fn test_range() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[0..0]).as_slice(), &[],); + assert_eq!((&a[0..1]).as_slice(), &[0],); + assert_eq!((&a[0..2]).as_slice(), &[0, 1],); + assert_eq!((&a[0..3]).as_slice(), &[0, 1, 2],); + assert_eq!((&a[0..4]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&a[2..2]).as_slice(), &[],); + assert_eq!((&a[2..3]).as_slice(), &[2],); + assert_eq!((&a[2..4]).as_slice(), &[2, 3],); + assert_eq!((&a[4..4]).as_slice(), &[],); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_invalid_alignment() { + let a: &Aligned = &Aligned::([0u8; 4]); + let _ = &a[1..2]; +} + +#[test] +fn test_range_mut() { + let a: &mut Aligned = &mut Aligned::([0, 1, 2, 3]); + assert_eq!((&mut a[0..0]).as_slice(), &[],); + assert_eq!((&mut a[0..1]).as_slice(), &[0],); + assert_eq!((&mut a[0..2]).as_slice(), &[0, 1],); + assert_eq!((&mut a[0..3]).as_slice(), &[0, 1, 2],); + assert_eq!((&mut a[0..4]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&mut a[2..2]).as_slice(), &[],); + assert_eq!((&mut a[2..3]).as_slice(), &[2],); + assert_eq!((&mut a[2..4]).as_slice(), &[2, 3],); + assert_eq!((&mut a[4..4]).as_slice(), &[],); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_mut_invalid_alignment() { + let a: &mut Aligned = &mut Aligned::([0u8; 4]); + let _ = &mut a[1..2]; +} + +#[test] +fn test_range_inclusive() { + let a: &Aligned = &Aligned::([0, 1, 2, 3]); + assert_eq!((&a[0..=0]).as_slice(), &[0],); + assert_eq!((&a[0..=1]).as_slice(), &[0, 1],); + assert_eq!((&a[0..=2]).as_slice(), &[0, 1, 2],); + assert_eq!((&a[0..=3]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&a[2..=2]).as_slice(), &[2],); + assert_eq!((&a[2..=3]).as_slice(), &[2, 3],); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_inclusive_invalid_alignment() { + let a: &Aligned = &Aligned::([0u8; 4]); + let _ = &a[1..=2]; +} + +#[test] +fn test_range_inclusive_mut() { + let a: &mut Aligned = &mut Aligned::([0, 1, 2, 3]); + assert_eq!((&mut a[0..=0]).as_slice(), &[0],); + assert_eq!((&mut a[0..=1]).as_slice(), &[0, 1],); + assert_eq!((&mut a[0..=2]).as_slice(), &[0, 1, 2],); + assert_eq!((&mut a[0..=3]).as_slice(), &[0, 1, 2, 3],); + assert_eq!((&mut a[2..=2]).as_slice(), &[2],); + assert_eq!((&mut a[2..=3]).as_slice(), &[2, 3],); +} + +#[test] +#[should_panic(expected = "Unaligned start index")] +fn test_range_inclusive_mut_invalid_alignment() { + let a: &mut Aligned = &mut Aligned::([0u8; 4]); + let _ = &mut a[1..=2]; +} + +#[test] +#[should_panic(expected = "out of range")] +fn test_range_from_out_of_bounds() { + let a: &Aligned = &Aligned::([0u8; 4]); + let _ = &a[6..]; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"45d7f5511d43e3327eb36143eaa88a6ef3a12eaa65bcb7329850124353d11762","Cargo.lock":"2b8393f867ba757f162ef56f9edc9b89ca2e0739adaaeeff0d65e1b5be5ff2f2","Cargo.toml":"9267792e9e2025630fdf05e6e80fcc54a15a9715a324be14ea76931959cae4b9","Cargo.toml.orig":"52dc29a26b45a6e7c0b09814450acec08dab6d806969ca635a830df76140228e","LICENSE":"bf5a93d1014429b43e01c57d45bea928748fbf37d059306145a1a0a91aec2014","README.md":"26d647db3aadf5436ecfd0c39fbaf44027335781cf6850515b0b020593e44eb1","src/lib.rs":"35ec6d24a4f0c6a6937f02a0e636cd0b61042df4d701ff14f82bd64dd32f899a","src/raw.rs":"b2f8b89d48fd023d197edbd78c257c51e1f3ba063018c6510618c909f128e364"},"package":"dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6af6c18c831c93395f948a0e6527b8d6b9729784" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aligned-vec" +version = "0.6.4" +dependencies = [ + "bincode", + "equator", + "serde", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "aligned-vec" +version = "0.6.4" +authors = ["sarah <>"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Aligned vector and box containers" +readme = "README.md" +keywords = [ + "vec", + "allocation", + "box", + "slice", + "alignment", +] +license = "MIT" +repository = "https://github.com/sarah-ek/aligned-vec/" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +default = ["std"] +serde = ["dep:serde"] +std = [] + +[lib] +name = "aligned_vec" +path = "src/lib.rs" + +[dependencies.equator] +version = "0.4.1" + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dev-dependencies.bincode] +version = "1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +[package] +name = "aligned-vec" +version = "0.6.4" +edition = "2021" +authors = ["sarah <>"] +description = "Aligned vector and box containers" +readme = "README.md" +repository = "https://github.com/sarah-ek/aligned-vec/" +license = "MIT" +keywords = ["vec", "allocation", "box", "slice", "alignment"] + +[dependencies] +equator = "0.4.1" +serde = { version = "1.0", optional = true, default-features = false } + +[dev-dependencies] +bincode = { version = "1" } + +[features] +default = ["std"] +std = [] +serde = ["dep:serde"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 sarah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/README.md clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +# aligned-vec + +This crate provides the `AVec` and `ABox` types, which are intended to have a similar API +to `Vec` and `Box`, but align the data they contain to a runtime alignment value. + +This is useful for situations where the alignment of the data matters, such as when working with +numerical data that can get performance benefits from being aligned to a SIMD-compatible memory address. + +# Features + +- `std` (default feature): Links this crate to the `std-crate` instead of the `core-crate`. +- `serde`: Implements serialization and deserialization features for `ABox` and `AVec`. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1419 @@ +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] + +//! # aligned-vec +//! +//! This crate provides the `AVec` and `ABox` types, which are intended to have a similar API +//! to `Vec` and `Box`, but align the data they contain to a runtime alignment value. +//! +//! This is useful for situations where the alignment of the data matters, such as when working with +//! numerical data that can get performance benefits from being aligned to a SIMD-compatible memory address. +//! +//! # Features +//! +//! - `std` (default feature): Links this crate to the `std-crate` instead of the `core-crate`. +//! - `serde`: Implements serialization and deserialization features for `ABox` and `AVec`. + +use core::{ + alloc::Layout, + fmt::Debug, + marker::PhantomData, + mem::{align_of, size_of, ManuallyDrop}, + ops::{Deref, DerefMut}, + ptr::{null_mut, NonNull}, +}; +use equator::assert; +use raw::ARawVec; + +mod raw; +extern crate alloc; + +// https://rust-lang.github.io/hashbrown/src/crossbeam_utils/cache_padded.rs.html#128-130 +pub const CACHELINE_ALIGN: usize = { + #[cfg(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "powerpc64", + ))] + { + 128 + } + #[cfg(any( + target_arch = "arm", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + ))] + { + 32 + } + #[cfg(target_arch = "s390x")] + { + 256 + } + #[cfg(not(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "powerpc64", + target_arch = "arm", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + target_arch = "s390x", + )))] + { + 64 + } +}; + +mod private { + pub trait Seal {} +} + +/// Trait for types that wrap an alignment value. +pub trait Alignment: Copy + private::Seal { + /// Takes an alignment value and a minimum valid alignment, + /// and returns an alignment wrapper that contains a power of two alignment that is greater + /// than `minimum_align`, and if possible, greater than `align`. + #[must_use] + fn new(align: usize, minimum_align: usize) -> Self; + /// Takes a minimum valid alignment, + /// and returns an alignment wrapper that contains a power of two alignment that is greater + /// than `minimum_align`, and if possible, greater than the contained value. + #[must_use] + fn alignment(self, minimum_align: usize) -> usize; +} + +/// Type wrapping a runtime alignment value. +#[derive(Copy, Clone)] +pub struct RuntimeAlign { + align: usize, +} + +/// Type wrapping a compile-time alignment value. +#[derive(Copy, Clone)] +pub struct ConstAlign; + +impl private::Seal for RuntimeAlign {} +impl private::Seal for ConstAlign {} + +impl core::convert::From> for AVec { + #[inline] + fn from(value: ABox<[T], A>) -> Self { + let len = (*value).len(); + let (ptr, align) = ABox::into_raw_parts(value); + unsafe { AVec::::from_raw_parts(ptr as *mut T, align, len, len) } + } +} + +impl Alignment for RuntimeAlign { + #[inline] + #[track_caller] + fn new(align: usize, minimum_align: usize) -> Self { + if align != 0 { + assert!( + align.is_power_of_two(), + "alignment ({align}) is not a power of two.", + ); + } + RuntimeAlign { + align: fix_alignment(align, minimum_align), + } + } + + #[inline] + fn alignment(self, minimum_align: usize) -> usize { + let _ = minimum_align; + self.align + } +} +impl Alignment for ConstAlign { + #[inline] + #[track_caller] + fn new(align: usize, minimum_align: usize) -> Self { + let _ = minimum_align; + let max = Ord::max; + if align != 0 { + assert!( + align.is_power_of_two(), + "alignment ({align}) is not a power of two.", + ); + } + assert!( + ALIGN.is_power_of_two(), + "alignment ({ALIGN}) is not a power of two.", + ); + assert!( + align <= max(ALIGN, minimum_align), + "provided alignment ({align}) is greater than the specified constant value ({ALIGN})", + ); + ConstAlign:: + } + + #[inline] + fn alignment(self, minimum_align: usize) -> usize { + fix_alignment(ALIGN, minimum_align) + } +} + +/// Aligned vector. See [`Vec`] for more info. +/// +/// Note: passing an alignment value of `0` or a power of two that is less than the minimum alignment will cause the vector to use the minimum valid alignment for the type `T` and alignment type `A`. +pub struct AVec> { + buf: ARawVec, + len: usize, +} + +/// Aligned box. See [`Box`] for more info. +/// +/// Note: passing an alignment value of `0` or a power of two that is less than the minimum alignment will cause the vector to use the minimum valid alignment for the type `T` and alignment type `A`. +pub struct ABox> { + ptr: NonNull, + align: A, + _marker: PhantomData, +} + +impl Deref for ABox { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { &*self.ptr.as_ptr() } + } +} + +impl DerefMut for ABox { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.ptr.as_ptr() } + } +} + +impl AsRef for ABox { + #[inline] + fn as_ref(&self) -> &T { + &**self + } +} + +impl AsMut for ABox { + #[inline] + fn as_mut(&mut self) -> &mut T { + &mut **self + } +} + +struct AllocDrop { + ptr: *mut u8, + size_bytes: usize, + align: usize, +} +impl Drop for AllocDrop { + #[inline] + fn drop(&mut self) { + if self.size_bytes > 0 { + unsafe { + alloc::alloc::dealloc( + self.ptr, + alloc::alloc::Layout::from_size_align_unchecked(self.size_bytes, self.align), + ) + } + } + } +} + +impl Drop for ABox { + #[inline] + fn drop(&mut self) { + let size_bytes = core::mem::size_of_val(self.deref_mut()); + let align_bytes = core::mem::align_of_val(self.deref_mut()); + let ptr = self.deref_mut() as *mut T; + let _alloc_drop = AllocDrop { + ptr: ptr as *mut u8, + size_bytes, + align: self.align.alignment(align_bytes), + }; + unsafe { ptr.drop_in_place() }; + } +} + +impl Deref for AVec { + type Target = [T]; + + #[inline] + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} +impl DerefMut for AVec { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() + } +} + +impl AsRef<[T]> for AVec { + #[inline] + fn as_ref(&self) -> &[T] { + &**self + } +} + +impl AsMut<[T]> for AVec { + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut **self + } +} + +impl ABox { + /// Creates a new [`ABox`] containing `value` at an address aligned to `align` bytes. + #[inline] + #[track_caller] + pub fn new(align: usize, value: T) -> Self { + let align = A::new(align, align_of::()).alignment(align_of::()); + let ptr = if size_of::() == 0 { + null_mut::().wrapping_add(align) as *mut T + } else { + unsafe { raw::with_capacity_unchecked(1, align, size_of::()) as *mut T } + }; + unsafe { ptr.write(value) }; + unsafe { Self::from_raw_parts(align, ptr) } + } + + /// Returns the alignment of the box. + #[inline] + pub fn alignment(&self) -> usize { + self.align.alignment(align_of::()) + } +} + +impl ABox { + /// Creates a new [`ABox`] from its raw parts. + /// + /// # Safety + /// + /// The arguments to this function must be acquired from a previous call to + /// [`Self::into_raw_parts`]. + #[inline] + #[track_caller] + pub unsafe fn from_raw_parts(align: usize, ptr: *mut T) -> Self { + Self { + ptr: NonNull::::new_unchecked(ptr), + align: A::new(align, core::mem::align_of_val(&*ptr)), + _marker: PhantomData, + } + } + + /// Decomposes a [`ABox`] into its raw parts: `(ptr, alignment)`. + #[inline] + pub fn into_raw_parts(this: Self) -> (*mut T, usize) { + let this = ManuallyDrop::new(this); + let align = core::mem::align_of_val(unsafe { &*this.ptr.as_ptr() }); + (this.ptr.as_ptr(), this.align.alignment(align)) + } +} + +impl Drop for AVec { + #[inline] + fn drop(&mut self) { + // SAFETY: dropping initialized elements + unsafe { (self.as_mut_slice() as *mut [T]).drop_in_place() } + } +} + +#[inline] +fn fix_alignment(align: usize, base_align: usize) -> usize { + align.max(base_align) +} + +#[derive(Copy, Clone, Debug)] +pub enum TryReserveError { + CapacityOverflow, + AllocError { layout: Layout }, +} + +impl AVec { + /// Returns a new [`AVec`] with the provided alignment. + #[inline] + #[must_use] + #[track_caller] + pub fn new(align: usize) -> Self { + unsafe { + Self { + buf: ARawVec::new_unchecked( + A::new(align, align_of::()).alignment(align_of::()), + ), + len: 0, + } + } + } + + /// Creates a new empty vector with enough capacity for at least `capacity` elements to + /// be inserted in the vector. If `capacity` is 0, the vector will not allocate. + /// + /// # Panics + /// + /// Panics if the capacity exceeds `isize::MAX` bytes. + #[inline] + #[must_use] + #[track_caller] + pub fn with_capacity(align: usize, capacity: usize) -> Self { + unsafe { + Self { + buf: ARawVec::with_capacity_unchecked( + capacity, + A::new(align, align_of::()).alignment(align_of::()), + ), + len: 0, + } + } + } + + /// Returns a new [`AVec`] from its raw parts. + /// + /// # Safety + /// + /// The arguments to this function must be acquired from a previous call to + /// [`Self::into_raw_parts`]. + #[inline] + #[must_use] + pub unsafe fn from_raw_parts(ptr: *mut T, align: usize, len: usize, capacity: usize) -> Self { + Self { + buf: ARawVec::from_raw_parts(ptr, capacity, align), + len, + } + } + + /// Decomposes an [`AVec`] into its raw parts: `(ptr, alignment, length, capacity)`. + #[inline] + pub fn into_raw_parts(self) -> (*mut T, usize, usize, usize) { + let mut this = ManuallyDrop::new(self); + let len = this.len(); + let cap = this.capacity(); + let align = this.alignment(); + let ptr = this.as_mut_ptr(); + (ptr, align, len, cap) + } + + /// Returns the length of the vector. + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector's length is equal to `0`, and false otherwise. + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns the number of elements the vector can hold without needing to reallocate. + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Reserves enough capacity for at least `additional` more elements to be inserted in the + /// vector. After this call to `reserve`, capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + #[inline] + pub fn reserve(&mut self, additional: usize) { + if additional > self.capacity().wrapping_sub(self.len) { + unsafe { self.buf.grow_amortized(self.len, additional) }; + } + } + + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + if additional > self.capacity().wrapping_sub(self.len) { + unsafe { self.buf.try_grow_amortized(self.len, additional) } + } else { + Ok(()) + } + } + + /// Reserves enough capacity for exactly `additional` more elements to be inserted in the + /// vector. After this call to `reserve`, capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + if additional > self.capacity().wrapping_sub(self.len) { + unsafe { self.buf.grow_exact(self.len, additional) }; + } + } + + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + if additional > self.capacity().wrapping_sub(self.len) { + unsafe { self.buf.try_grow_exact(self.len, additional) } + } else { + Ok(()) + } + } + + /// Returns the alignment of the vector. + #[inline] + #[must_use] + pub fn alignment(&self) -> usize { + self.buf.align() + } + + /// Returns a pointer to the objects held by the vector. + #[inline] + #[must_use] + pub fn as_ptr(&self) -> *const T { + self.buf.as_ptr() + } + + /// Returns a mutable pointer to the objects held by the vector. + #[inline] + #[must_use] + pub fn as_mut_ptr(&mut self) -> *mut T { + self.buf.as_mut_ptr() + } + + /// Returns a reference to a slice over the objects held by the vector. + #[inline] + #[must_use] + pub fn as_slice(&self) -> &[T] { + let len = self.len(); + let ptr = self.as_ptr(); + + // ptr points to `len` initialized elements and is properly aligned since + // self.align is at least `align_of::()` + unsafe { core::slice::from_raw_parts(ptr, len) } + } + + /// Returns a mutable reference to a slice over the objects held by the vector. + #[inline] + #[must_use] + pub fn as_mut_slice(&mut self) -> &mut [T] { + let len = self.len(); + let ptr = self.as_mut_ptr(); + + // ptr points to `len` initialized elements and is properly aligned since + // self.align is at least `align_of::()` + unsafe { core::slice::from_raw_parts_mut(ptr, len) } + } + + /// Push the given value to the end of the vector, reallocating if needed. + #[inline] + pub fn push(&mut self, value: T) { + if self.len == self.capacity() { + unsafe { self.buf.grow_amortized(self.len, 1) }; + } + + // SAFETY: self.capacity is greater than self.len so the write is valid + unsafe { + let past_the_end = self.as_mut_ptr().add(self.len); + past_the_end.write(value); + self.len += 1; + } + } + + /// Remove the last value from the vector if it exists, otherwise returns `None`. + #[inline] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + // SAFETY: the len was greater than one so we had one valid element at the last address + Some(unsafe { self.as_mut_ptr().add(self.len()).read() }) + } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// The capacity will remain at least as large as both the length and the supplied value. + /// If the current capacity is less than the lower limit, this is a no-op. + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + let min_capacity = min_capacity.max(self.len()); + if self.capacity() > min_capacity { + unsafe { self.buf.shrink_to(min_capacity) }; + } + } + + /// Shrinks the capacity of the vector as much as possible without dropping any elements. + #[inline] + pub fn shrink_to_fit(&mut self) { + if self.capacity() > self.len { + unsafe { self.buf.shrink_to(self.len) }; + } + } + + /// Drops the last elements of the vector until its length is equal to `len`. + /// If `len` is greater than or equal to `self.len()`, this is a no-op. + #[inline] + pub fn truncate(&mut self, len: usize) { + if len < self.len { + let old_len = self.len; + self.len = len; + unsafe { + let ptr = self.as_mut_ptr(); + core::ptr::slice_from_raw_parts_mut(ptr.add(len), old_len - len).drop_in_place() + } + } + } + + /// Drops the all the elements of the vector, setting its length to `0`. + #[inline] + pub fn clear(&mut self) { + let old_len = self.len; + self.len = 0; + unsafe { + let ptr = self.as_mut_ptr(); + core::ptr::slice_from_raw_parts_mut(ptr, old_len).drop_in_place() + } + } + + /// Converts the vector into [`ABox`]. + /// This will drop any excess capacity. + #[inline] + pub fn into_boxed_slice(self) -> ABox<[T], A> { + let mut this = self; + this.shrink_to_fit(); + let (ptr, align, len, _) = this.into_raw_parts(); + unsafe { + ABox::<[T], A>::from_raw_parts(align, core::ptr::slice_from_raw_parts_mut(ptr, len)) + } + } + + /// Inserts an element at position `index` within the vector, shifting all elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + #[track_caller] + pub fn insert(&mut self, index: usize, element: T) { + // Copied somewhat from the standard library + #[cold] + #[inline(never)] + #[track_caller] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("insertion index (is {index}) should be <= len (is {len})"); + } + + let len = self.len(); + + // Add space for the new element + self.reserve(1); + + unsafe { + let p = self.as_mut_ptr().add(index); + if index < len { + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + core::ptr::copy(p, p.add(1), len - index); + } else if index == len { + // No elements need shifting. + } else { + assert_failed(index, len); + } + core::ptr::write(p, element); + + self.len += 1; + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + #[track_caller] + pub fn remove(&mut self, index: usize) -> T { + // Copied somewhat from the standard library + #[cold] + #[inline(never)] + #[track_caller] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("removal index (is {index}) should be < len (is {len})"); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + + unsafe { + // The place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // Copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + let ret = core::ptr::read(ptr); + + // Shift everything down to fill in that spot. + core::ptr::copy(ptr.add(1), ptr, len - index - 1); + + self.len -= 1; + + ret + } + } + + /// Collects an iterator into an [`AVec`] with the provided alignment. + #[inline] + pub fn from_iter>(align: usize, iter: I) -> Self { + Self::from_iter_impl(iter.into_iter(), align) + } + + /// Collects a slice into an [`AVec`] with the provided alignment. + #[inline] + pub fn from_slice(align: usize, slice: &[T]) -> Self + where + T: Clone, + { + let len = slice.len(); + let mut vec = AVec::with_capacity(align, len); + { + let len = &mut vec.len; + let ptr: *mut T = vec.buf.ptr.as_ptr(); + + for (i, item) in slice.iter().enumerate() { + unsafe { ptr.add(i).write(item.clone()) }; + *len += 1; + } + } + vec + } + + fn from_iter_impl>(mut iter: I, align: usize) -> Self { + let (lower_bound, upper_bound) = iter.size_hint(); + let mut this = Self::with_capacity(align, lower_bound); + + if upper_bound == Some(lower_bound) { + let len = &mut this.len; + let ptr = this.buf.ptr.as_ptr(); + + let first_chunk = iter.take(lower_bound); + first_chunk.enumerate().for_each(|(i, item)| { + unsafe { ptr.add(i).write(item) }; + *len += 1; + }); + } else { + let len = &mut this.len; + let ptr = this.buf.ptr.as_ptr(); + + let first_chunk = (&mut iter).take(lower_bound); + first_chunk.enumerate().for_each(|(i, item)| { + unsafe { ptr.add(i).write(item) }; + *len += 1; + }); + iter.for_each(|item| { + this.push(item); + }); + } + + this + } + + #[inline] + pub unsafe fn set_len(&mut self, new_len: usize) { + self.len = new_len; + } + + pub fn append(&mut self, other: &mut AVec) { + unsafe { + let len = self.len(); + let count = other.len(); + self.reserve(count); + core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count); + self.len += count; + other.len = 0; + } + } + + #[inline(always)] + #[doc(hidden)] + pub fn __from_elem(align: usize, elem: T, count: usize) -> Self + where + T: Clone, + { + Self::from_iter(align, core::iter::repeat(elem).take(count)) + } + + #[inline(always)] + #[doc(hidden)] + /// this is unsafe do not call this in user code + pub fn __copy_from_ptr(align: usize, src: *const T, len: usize) -> Self { + let mut v = Self::with_capacity(align, len); + let dst = v.as_mut_ptr(); + unsafe { core::ptr::copy_nonoverlapping(src, dst, len) }; + v.len = len; + v + } +} + +impl AVec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + pub fn resize(&mut self, new_len: usize, value: T) { + // Copied somewhat from the standard library + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, value) + } else { + self.truncate(new_len); + } + } + + /// Extend the vector by `n` clones of value. + fn extend_with(&mut self, n: usize, value: T) { + // Copied somewhat from the standard library + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + + // Write all elements except the last one + for _ in 1..n { + core::ptr::write(ptr, value.clone()); + ptr = ptr.add(1); + // Increment the length in every step in case clone() panics + self.len += 1; + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + core::ptr::write(ptr, value); + self.len += 1; + } + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + pub fn extend_from_slice(&mut self, other: &[T]) { + // Copied somewhat from the standard library + let count = other.len(); + self.reserve(count); + let len = self.len(); + unsafe { + core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count) + }; + self.len += count; + } +} + +impl Debug for AVec { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +impl Debug for ABox { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + (&**self).fmt(f) + } +} + +impl Clone for AVec { + fn clone(&self) -> Self { + Self::from_slice(self.alignment(), self.deref()) + } +} + +impl Clone for ABox { + fn clone(&self) -> Self { + ABox::new(self.align.alignment(align_of::()), self.deref().clone()) + } +} + +impl Clone for ABox<[T], A> { + fn clone(&self) -> Self { + AVec::from_slice(self.align.alignment(align_of::()), self.deref()).into_boxed_slice() + } +} + +impl PartialEq for AVec { + fn eq(&self, other: &Self) -> bool { + self.as_slice().eq(other.as_slice()) + } +} +impl Eq for AVec {} +impl PartialOrd for AVec { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} +impl Ord for AVec { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl PartialEq for ABox { + fn eq(&self, other: &Self) -> bool { + (&**self).eq(&**other) + } +} +impl Eq for ABox {} +impl PartialOrd for ABox { + fn partial_cmp(&self, other: &Self) -> Option { + (&**self).partial_cmp(&**other) + } +} +impl Ord for ABox { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + (&**self).cmp(&**other) + } +} +unsafe impl Sync for AVec {} +unsafe impl Send for AVec {} +unsafe impl Sync for ABox {} +unsafe impl Send for ABox {} + +#[cfg(feature = "serde")] +mod serde { + use super::*; + use ::serde::{Deserialize, Serialize}; + + #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] + impl Serialize for ABox { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { + (&**self).serialize(serializer) + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] + impl Serialize for AVec { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { + (&**self).serialize(serializer) + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] + impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for ABox> { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::Deserializer<'de>, + { + Ok(ABox::>::new( + N, + T::deserialize(deserializer)?, + )) + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] + impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for ABox<[T], ConstAlign> { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::Deserializer<'de>, + { + Ok(AVec::>::deserialize(deserializer)?.into_boxed_slice()) + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] + impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for AVec> { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::Deserializer<'de>, + { + struct AVecVisitor { + _marker: PhantomData AVec>>, + } + + impl<'de, T: Deserialize<'de>, const N: usize> ::serde::de::Visitor<'de> for AVecVisitor { + type Value = AVec>; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq(self, mut seq: S) -> Result + where + S: ::serde::de::SeqAccess<'de>, + { + let mut vec = + AVec::>::with_capacity(N, cautious::(seq.size_hint())); + + while let Some(elem) = seq.next_element::()? { + vec.push(elem) + } + + Ok(vec) + } + } + + deserializer.deserialize_seq(AVecVisitor { + _marker: PhantomData, + }) + } + } + + pub fn cautious(hint: Option) -> usize { + use core::{cmp, mem}; + + const MAX_PREALLOC_BYTES: usize = 1024 * 1024; + + if mem::size_of::() == 0 { + 0 + } else { + cmp::min( + hint.unwrap_or(0), + MAX_PREALLOC_BYTES / mem::size_of::(), + ) + } + } +} + +/// Creates a [`AVec`] containing the arguments. +/// +/// `avec!` follows similar syntax to `vec!` but allows for specifying an alignment value. +/// You can either specifiy the alignment value explicitly +/// ```rust +/// use aligned_vec::{avec, CACHELINE_ALIGN}; +/// let v = avec![[64]| 1, 2, 3, 4]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v.alignment(), 64); +/// assert_eq!(v.as_ptr().align_offset(64), 0); +/// ``` +/// or dont specify it, which will use the default alignment value of `CACHELINE_ALIGN` +/// ```rust +/// use aligned_vec::{avec, CACHELINE_ALIGN}; +/// let v = avec![1, 2, 3, 4]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v.alignment(), CACHELINE_ALIGN); +/// assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); +/// ``` +#[macro_export] +macro_rules! avec { + () => { + $crate::AVec::<_>::new(0) + }; + ([$align: expr]| ) => { + $crate::AVec::<_, $crate::ConstAlign::<$align>>::new(0) + }; + ([$align: expr]| $elem: expr; $count: expr) => { + $crate::AVec::<_, $crate::ConstAlign::<$align>>::__from_elem(0, $elem, $count) + }; + ([$align: expr]| $($elem: expr),*) => { + { + let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); + let __len = __data.len(); + let __ptr = __data.as_ptr(); + let mut __aligned_vec = $crate::AVec::<_, $crate::ConstAlign::<$align>>::__copy_from_ptr(0, __ptr, __len); + __aligned_vec + } + }; + ($elem: expr; $count: expr) => { + $crate::AVec::<_>::__from_elem(0, $elem, $count) + }; + ($($elem: expr),*) => { + { + let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); + let __len = __data.len(); + let __ptr = __data.as_ptr(); + let mut __aligned_vec = $crate::AVec::<_>::__copy_from_ptr(0, __ptr, __len); + __aligned_vec + } + }; +} + +/// Create a vector that is aligned to a runtime alignment value. +#[macro_export] +macro_rules! avec_rt { + ([$align: expr]$(|)?) => { + $crate::AVec::<_, $crate::RuntimeAlign>::new($align) + }; + ([$align: expr]| $elem: expr; $count: expr) => { + $crate::AVec::<_, $crate::RuntimeAlign>::__from_elem($align, $elem, $count) + }; + ([$align: expr]| $($elem: expr),*) => { + { + let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); + let __len = __data.len(); + let __ptr = __data.as_ptr(); + let mut __aligned_vec = $crate::AVec::<_>::__copy_from_ptr($align, __ptr, __len); + __aligned_vec + } + }; +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::vec; + use core::iter::repeat; + use equator::assert; + + #[test] + fn new() { + let v = AVec::::new(32); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), 0); + assert_eq!(v.alignment(), CACHELINE_ALIGN); + assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); + let v = AVec::<()>::new(32); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), usize::MAX); + assert_eq!(v.alignment(), CACHELINE_ALIGN); + assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); + + #[repr(align(4096))] + struct OverAligned; + let v = AVec::::new(32); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), usize::MAX); + assert_eq!(v.alignment(), 4096); + assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); + assert_eq!(v.as_ptr().align_offset(4096), 0); + } + + #[test] + fn collect() { + let v = AVec::<_>::from_iter(64, 0..4); + assert_eq!(&*v, &[0, 1, 2, 3]); + let v = AVec::<_>::from_iter(64, repeat(()).take(4)); + assert_eq!(&*v, &[(), (), (), ()]); + } + + #[test] + fn push() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + v.push(3); + assert_eq!(&*v, &[0, 1, 2, 3]); + + let mut v = AVec::<_>::from_iter(64, 0..4); + v.push(4); + v.push(5); + v.push(6); + v.push(7); + assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7]); + + let mut v = AVec::<_>::from_iter(64, repeat(()).take(4)); + v.push(()); + v.push(()); + v.push(()); + v.push(()); + assert_eq!(&*v, &[(), (), (), (), (), (), (), ()]); + } + + #[test] + fn insert() { + let mut v = AVec::::new(16); + v.insert(0, 1); + v.insert(1, 3); + v.insert(1, 2); + v.insert(0, 0); + assert_eq!(&*v, &[0, 1, 2, 3]); + + let mut v = AVec::<_>::from_iter(64, 0..4); + v.insert(0, -1); + v.insert(5, 5); + v.insert(5, 4); + v.insert(1, 0); + v.insert(2, 0); + assert_eq!(&*v, &[-1, 0, 0, 0, 1, 2, 3, 4, 5]); + + let mut v = AVec::<_>::from_iter(64, repeat(()).take(4)); + v.insert(3, ()); + v.insert(0, ()); + v.insert(2, ()); + v.insert(7, ()); + assert_eq!(&*v, &[(), (), (), (), (), (), (), ()]); + } + + #[test] + fn pop() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + v.push(3); + assert_eq!(v.pop(), Some(3)); + assert_eq!(v.pop(), Some(2)); + assert_eq!(v.pop(), Some(1)); + assert_eq!(v.pop(), Some(0)); + assert_eq!(v.pop(), None); + assert_eq!(v.pop(), None); + assert_eq!(&*v, &[]); + assert!(v.is_empty()); + + let mut v = AVec::<()>::new(16); + v.push(()); + v.push(()); + v.push(()); + v.push(()); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), None); + assert_eq!(v.pop(), None); + assert_eq!(&*v, &[]); + assert!(v.is_empty()); + } + + #[test] + fn remove() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + v.push(3); + assert_eq!(v.remove(2), 2); + assert_eq!(v.remove(2), 3); + assert_eq!(v.remove(0), 0); + assert_eq!(v.remove(0), 1); + assert_eq!(&*v, &[]); + assert!(v.is_empty()); + + let mut v = AVec::<()>::new(16); + v.push(()); + v.push(()); + v.push(()); + v.push(()); + assert_eq!(v.remove(0), ()); + assert_eq!(v.remove(0), ()); + assert_eq!(v.remove(0), ()); + assert_eq!(v.remove(0), ()); + assert_eq!(&*v, &[]); + assert!(v.is_empty()); + } + + #[test] + fn shrink() { + let mut v = AVec::::with_capacity(16, 10); + v.push(0); + v.push(1); + v.push(2); + + assert_eq!(v.capacity(), 10); + v.shrink_to_fit(); + assert_eq!(v.len(), 3); + assert_eq!(v.capacity(), 3); + + let mut v = AVec::::with_capacity(16, 10); + v.push(0); + v.push(1); + v.push(2); + + assert_eq!(v.capacity(), 10); + v.shrink_to(0); + assert_eq!(v.len(), 3); + assert_eq!(v.capacity(), 3); + } + + #[test] + fn truncate() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + + v.truncate(1); + assert_eq!(v.len(), 1); + assert_eq!(&*v, &[0]); + + v.clear(); + assert_eq!(v.len(), 0); + assert_eq!(&*v, &[]); + + let mut v = AVec::<()>::new(16); + v.push(()); + v.push(()); + v.push(()); + + v.truncate(1); + assert_eq!(v.len(), 1); + assert_eq!(&*v, &[()]); + + v.clear(); + assert_eq!(v.len(), 0); + assert_eq!(&*v, &[]); + } + + #[test] + fn extend_from_slice() { + let mut v = AVec::::new(16); + v.extend_from_slice(&[0, 1, 2, 3]); + v.extend_from_slice(&[4, 5, 6, 7, 8]); + assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8]); + + let mut v = AVec::<()>::new(16); + v.extend_from_slice(&[(), (), (), ()]); + v.extend_from_slice(&[(), (), ()]); + assert_eq!(&*v, &[(), (), (), (), (), (), ()]); + } + + #[test] + fn resize() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + + v.resize(1, 10); + assert_eq!(v.len(), 1); + assert_eq!(&*v, &[0]); + + v.resize(3, 20); + assert_eq!(v.len(), 3); + assert_eq!(&*v, &[0, 20, 20]); + + let mut v = AVec::<()>::new(16); + v.push(()); + v.push(()); + v.push(()); + + v.resize(2, ()); + assert_eq!(v.len(), 2); + assert_eq!(&*v, &[(), ()]); + + v.resize(3, ()); + assert_eq!(v.len(), 3); + assert_eq!(&*v, &[(), (), ()]); + } + + #[test] + fn into_boxed_slice() { + let mut v = AVec::::new(16); + v.push(0); + v.push(1); + v.push(2); + + let boxed = v.into_boxed_slice(); + assert_eq!(&*boxed, &[0, 1, 2]); + } + + #[test] + fn box_new() { + let boxed = ABox::<_>::new(64, 3); + assert_eq!(&*boxed, &3); + } + + #[test] + fn box_clone() { + let boxed = ABox::<_>::new(64, 3); + assert_eq!(boxed, boxed.clone()); + } + + #[test] + fn box_slice_clone() { + let boxed = AVec::<_>::from_iter(64, 0..123).into_boxed_slice(); + assert_eq!(boxed, boxed.clone()); + } + + #[test] + fn macros() { + let u: AVec<()> = avec![]; + assert_eq!(u.len(), 0); + assert_eq!(u.as_ptr().align_offset(CACHELINE_ALIGN), 0); + + let v = avec![0; 4]; + assert_eq!(v.len(), 4); + assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); + + let mut w = avec![vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; + w[0].push(2); + w[3].pop(); + assert_eq!(w.len(), 4); + assert_eq!(w.as_ptr().align_offset(CACHELINE_ALIGN), 0); + assert_eq!(w[0], vec![0, 1, 2]); + assert_eq!(w[1], vec![3, 4]); + assert_eq!(w[2], vec![5, 6]); + assert_eq!(w[3], vec![7]); + } + + #[test] + fn macros_2() { + let u: AVec<(), _> = avec![[4096]| ]; + assert_eq!(u.len(), 0); + assert_eq!(u.as_ptr().align_offset(4096), 0); + + let v = avec![[4096]| 0; 4]; + assert_eq!(v.len(), 4); + assert_eq!(v.as_ptr().align_offset(4096), 0); + + let mut w = avec![[4096] | vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; + w[0].push(2); + w[3].pop(); + assert_eq!(w.len(), 4); + assert_eq!(w.as_ptr().align_offset(4096), 0); + assert_eq!(w[0], vec![0, 1, 2]); + assert_eq!(w[1], vec![3, 4]); + assert_eq!(w[2], vec![5, 6]); + assert_eq!(w[3], vec![7]); + } + + #[test] + fn macros_rt() { + let u: AVec<(), _> = avec_rt![[32]]; + assert_eq!(u.len(), 0); + assert_eq!(u.as_ptr().align_offset(32), 0); + + let v = avec_rt![[32]| 0; 4]; + assert_eq!(v.len(), 4); + assert_eq!(v.as_ptr().align_offset(32), 0); + + let mut w = avec_rt![[64] | vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; + w[0].push(2); + w[3].pop(); + assert_eq!(w.len(), 4); + assert_eq!(w.as_ptr().align_offset(64), 0); + assert_eq!(w[0], vec![0, 1, 2]); + assert_eq!(w[1], vec![3, 4]); + assert_eq!(w[2], vec![5, 6]); + assert_eq!(w[3], vec![7]); + } +} + +#[cfg(all(test, feature = "serde"))] +mod serde_tests { + use super::*; + + use ::serde::Deserialize; + use bincode::{DefaultOptions, Deserializer, Options}; + + #[test] + fn can_limit_deserialization_size() { + // Malformed serialized data indicating a sequence of length u64::MAX. + let ser = vec![ + 253, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1, 1, 1, + ]; + + let options = DefaultOptions::new().with_limit(12); + + let mut deserializer = Deserializer::from_slice(&ser, options); + let result = as Deserialize>::deserialize(&mut deserializer); + + let err = match result { + Ok(_) => panic!("Expected a failure"), + Err(e) => e, + }; + + match *err { + bincode::ErrorKind::SizeLimit => {} + _ => panic!("Expected ErrorKind::SizeLimit, got {err:#?}"), + }; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/src/raw.rs clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/raw.rs --- clamav-1.4.3+dfsg/.cargo/vendor/aligned-vec/src/raw.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/aligned-vec/src/raw.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,415 @@ +use crate::{Alignment, TryReserveError}; +use alloc::alloc::{alloc, dealloc, handle_alloc_error, realloc, Layout}; +use core::{ + marker::PhantomData, + mem::{align_of, size_of}, + ptr::{null_mut, NonNull}, +}; + +pub struct ARawVec { + pub ptr: NonNull, + pub capacity: usize, + pub align: A, + _marker: PhantomData, +} + +impl Drop for ARawVec { + #[inline] + fn drop(&mut self) { + // this can't overflow since we already have this much stored in a slice + let size_bytes = self.capacity * size_of::(); + if size_bytes > 0 { + // SAFETY: memory was allocated with alloc::alloc::alloc + unsafe { + dealloc( + self.ptr.as_ptr() as *mut u8, + Layout::from_size_align_unchecked( + size_bytes, + self.align.alignment(align_of::()), + ), + ) + } + } + } +} + +pub fn capacity_overflow() -> ! { + panic!("capacity overflow") +} + +impl ARawVec { + /// # Safety + /// + /// `align` must be a power of two. + /// `align` must be greater than or equal to `core::mem::align_of::()`. + #[inline] + pub unsafe fn new_unchecked(align: usize) -> Self { + let cap = if size_of::() == 0 { usize::MAX } else { 0 }; + Self::from_raw_parts(null_mut::().wrapping_add(align) as *mut T, cap, align) + } + + /// # Safety + /// + /// `align` must be a power of two. + /// `align` must be greater than or equal to `core::mem::align_of::()`. + #[inline] + pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize) -> Self { + if capacity == 0 || size_of::() == 0 { + Self::new_unchecked(align) + } else { + Self { + ptr: NonNull::::new_unchecked(with_capacity_unchecked( + capacity, + align, + size_of::(), + ) as *mut T), + capacity, + align: A::new(align, align_of::()), + _marker: PhantomData, + } + } + } + + /// # Safety + /// + /// `align` must be a power of two. + /// `align` must be greater than or equal to `core::mem::align_of::()`. + #[inline] + pub unsafe fn try_with_capacity_unchecked( + capacity: usize, + align: usize, + ) -> Result { + if capacity == 0 || size_of::() == 0 { + Ok(Self::new_unchecked(align)) + } else { + Ok(Self { + ptr: NonNull::::new_unchecked(try_with_capacity_unchecked( + capacity, + align, + size_of::(), + )? as *mut T), + capacity, + align: A::new(align, align_of::()), + _marker: PhantomData, + }) + } + } + + const MIN_NON_ZERO_CAP: usize = if size_of::() == 1 { + 8 + } else if size_of::() <= 1024 { + 4 + } else { + 1 + }; + + pub unsafe fn grow_amortized(&mut self, len: usize, additional: usize) { + debug_assert!(additional > 0); + if self.capacity == 0 { + *self = Self::with_capacity_unchecked( + additional.max(Self::MIN_NON_ZERO_CAP), + self.align.alignment(align_of::()), + ); + return; + } + + if size_of::() == 0 { + debug_assert_eq!(self.capacity, usize::MAX); + capacity_overflow(); + } + + let new_cap = match len.checked_add(additional) { + Some(cap) => cap, + None => capacity_overflow(), + }; + + // self.cap * 2 can't overflow because it's less than isize::MAX + let new_cap = new_cap.max(self.capacity * 2); + let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP); + + let ptr = { + grow_unchecked( + self.as_mut_ptr() as *mut u8, + self.capacity, + new_cap, + self.align.alignment(align_of::()), + size_of::(), + ) as *mut T + }; + + self.capacity = new_cap; + self.ptr = NonNull::::new_unchecked(ptr); + } + + pub unsafe fn grow_exact(&mut self, len: usize, additional: usize) { + debug_assert!(additional > 0); + if size_of::() == 0 { + debug_assert_eq!(self.capacity, usize::MAX); + capacity_overflow(); + } + + if self.capacity == 0 { + *self = + Self::with_capacity_unchecked(additional, self.align.alignment(align_of::())); + return; + } + + let new_cap = match len.checked_add(additional) { + Some(cap) => cap, + None => capacity_overflow(), + }; + + let ptr = grow_unchecked( + self.as_mut_ptr() as *mut u8, + self.capacity, + new_cap, + self.align.alignment(align_of::()), + size_of::(), + ) as *mut T; + + self.capacity = new_cap; + self.ptr = NonNull::::new_unchecked(ptr); + } + + pub unsafe fn try_grow_amortized( + &mut self, + len: usize, + additional: usize, + ) -> Result<(), TryReserveError> { + debug_assert!(additional > 0); + if self.capacity == 0 { + *self = Self::try_with_capacity_unchecked( + additional.max(Self::MIN_NON_ZERO_CAP), + self.align.alignment(align_of::()), + )?; + return Ok(()); + } + + if size_of::() == 0 { + debug_assert_eq!(self.capacity, usize::MAX); + return Err(TryReserveError::CapacityOverflow); + } + + let new_cap = match len.checked_add(additional) { + Some(cap) => cap, + None => return Err(TryReserveError::CapacityOverflow), + }; + + // self.cap * 2 can't overflow because it's less than isize::MAX + let new_cap = new_cap.max(self.capacity * 2); + let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP); + + let ptr = { + try_grow_unchecked( + self.as_mut_ptr() as *mut u8, + self.capacity, + new_cap, + self.align.alignment(align_of::()), + size_of::(), + )? as *mut T + }; + + self.capacity = new_cap; + self.ptr = NonNull::::new_unchecked(ptr); + Ok(()) + } + + pub unsafe fn try_grow_exact( + &mut self, + len: usize, + additional: usize, + ) -> Result<(), TryReserveError> { + debug_assert!(additional > 0); + if size_of::() == 0 { + debug_assert_eq!(self.capacity, usize::MAX); + return Err(TryReserveError::CapacityOverflow); + } + + if self.capacity == 0 { + *self = Self::try_with_capacity_unchecked( + additional, + self.align.alignment(align_of::()), + )?; + return Ok(()); + } + + let new_cap = match len.checked_add(additional) { + Some(cap) => cap, + None => return Err(TryReserveError::CapacityOverflow), + }; + + let ptr = try_grow_unchecked( + self.as_mut_ptr() as *mut u8, + self.capacity, + new_cap, + self.align.alignment(align_of::()), + size_of::(), + )? as *mut T; + + self.capacity = new_cap; + self.ptr = NonNull::::new_unchecked(ptr); + Ok(()) + } + + pub unsafe fn shrink_to(&mut self, len: usize) { + if size_of::() == 0 { + return; + } + + debug_assert!(len < self.capacity()); + let size_of = size_of::(); + let old_capacity = self.capacity; + let align = self.align; + let old_ptr = self.ptr.as_ptr() as *mut u8; + + // this cannot overflow or exceed isize::MAX bytes since len < cap and the same was true + // for cap + let new_size_bytes = len * size_of; + let old_size_bytes = old_capacity * size_of; + let old_layout = + Layout::from_size_align_unchecked(old_size_bytes, align.alignment(align_of::())); + + let ptr = realloc(old_ptr, old_layout, new_size_bytes); + let ptr = ptr as *mut T; + self.capacity = len; + self.ptr = NonNull::::new_unchecked(ptr); + } + + #[inline] + pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize, align: usize) -> Self { + Self { + ptr: NonNull::::new_unchecked(ptr), + capacity, + align: A::new(align, align_of::()), + _marker: PhantomData, + } + } + + /// Returns the capacity of the vector. + #[inline] + pub fn capacity(&self) -> usize { + self.capacity + } + + #[inline] + pub fn align(&self) -> usize { + self.align.alignment(align_of::()) + } + + #[inline] + pub fn as_ptr(&self) -> *const T { + self.ptr.as_ptr() + } + + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self.ptr.as_ptr() + } +} + +pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize, size_of: usize) -> *mut u8 { + let size_bytes = match capacity.checked_mul(size_of) { + Some(size_bytes) => size_bytes, + None => capacity_overflow(), + }; + debug_assert!(size_bytes > 0); + let will_overflow = size_bytes > usize::MAX - (align - 1); + if will_overflow || !is_valid_alloc(size_bytes) { + capacity_overflow(); + } + + let layout = Layout::from_size_align_unchecked(size_bytes, align); + let ptr = alloc(layout); + if ptr.is_null() { + handle_alloc_error(layout); + } + ptr +} + +unsafe fn grow_unchecked( + old_ptr: *mut u8, + old_capacity: usize, + new_capacity: usize, + align: usize, + size_of: usize, +) -> *mut u8 { + let new_size_bytes = match new_capacity.checked_mul(size_of) { + Some(size_bytes) => size_bytes, + None => capacity_overflow(), + }; + let will_overflow = new_size_bytes > usize::MAX - (align - 1); + if will_overflow || !is_valid_alloc(new_size_bytes) { + capacity_overflow(); + } + + // can't overflow because we already allocated this much + let old_size_bytes = old_capacity * size_of; + let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align); + + let ptr = realloc(old_ptr, old_layout, new_size_bytes); + + if ptr.is_null() { + let new_layout = Layout::from_size_align_unchecked(new_size_bytes, align); + handle_alloc_error(new_layout); + } + + ptr +} + +pub unsafe fn try_with_capacity_unchecked( + capacity: usize, + align: usize, + size_of: usize, +) -> Result<*mut u8, TryReserveError> { + let size_bytes = match capacity.checked_mul(size_of) { + Some(size_bytes) => size_bytes, + None => return Err(TryReserveError::CapacityOverflow), + }; + debug_assert!(size_bytes > 0); + let will_overflow = size_bytes > usize::MAX - (align - 1); + if will_overflow || !is_valid_alloc(size_bytes) { + return Err(TryReserveError::CapacityOverflow); + } + + let layout = Layout::from_size_align_unchecked(size_bytes, align); + let ptr = alloc(layout); + if ptr.is_null() { + return Err(TryReserveError::AllocError { layout }); + } + Ok(ptr) +} + +unsafe fn try_grow_unchecked( + old_ptr: *mut u8, + old_capacity: usize, + new_capacity: usize, + align: usize, + size_of: usize, +) -> Result<*mut u8, TryReserveError> { + let new_size_bytes = match new_capacity.checked_mul(size_of) { + Some(size_bytes) => size_bytes, + None => return Err(TryReserveError::CapacityOverflow), + }; + let will_overflow = new_size_bytes > usize::MAX - (align - 1); + if will_overflow || !is_valid_alloc(new_size_bytes) { + return Err(TryReserveError::CapacityOverflow); + } + + // can't overflow because we already allocated this much + let old_size_bytes = old_capacity * size_of; + let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align); + + let ptr = realloc(old_ptr, old_layout, new_size_bytes); + + if ptr.is_null() { + let layout = Layout::from_size_align_unchecked(new_size_bytes, align); + return Err(TryReserveError::AllocError { layout }); + } + + Ok(ptr) +} + +#[inline] +fn is_valid_alloc(alloc_size: usize) -> bool { + !(usize::BITS < 64 && alloc_size > isize::MAX as usize) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"a87d9acc9827a50c7a96a88720c5dd055cbc08b1144dff95bd572ff977d4a79a","LICENSE-APACHE":"4458503dd48e88c4e0b945fb252a08b93c40ec757309b8ffa7c594dfa1e35104","LICENSE-MIT":"002c2696d92b5c8cf956c11072baa58eaf9f6ade995c031ea635c6a1ee342ad1","README.md":"6dfe0c602dc61eebe118900ed66a2c1f7887b9fe95b36e1c2974c4e8fa7ebd4b","src/lib.rs":"8f421233df83f82e737930ca8a2ad254966334183148bcc170f9c405df230de2","src/tzdata.rs":"78920925b04219910511e9a1f036f468cd2925c0054f280d6a00b106529046e7"},"package":"e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"6846a0ea8f7eba50594e2ad628b52cb3b450f361eae3734f8b3dd2001fee91b5","Cargo.toml":"a87d9acc9827a50c7a96a88720c5dd055cbc08b1144dff95bd572ff977d4a79a","Cargo.toml.orig":"9cf5570fbbad8241eb368f96f3e3d4982c93342143cd9e1c849a461167f8c18a","LICENSE-APACHE":"4458503dd48e88c4e0b945fb252a08b93c40ec757309b8ffa7c594dfa1e35104","LICENSE-MIT":"002c2696d92b5c8cf956c11072baa58eaf9f6ade995c031ea635c6a1ee342ad1","README.md":"6dfe0c602dc61eebe118900ed66a2c1f7887b9fe95b36e1c2974c4e8fa7ebd4b","src/lib.rs":"8f421233df83f82e737930ca8a2ad254966334183148bcc170f9c405df230de2","src/tzdata.rs":"78920925b04219910511e9a1f036f468cd2925c0054f280d6a00b106529046e7"},"package":"e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "230368ebd6aa911bc56401202808d11019411dc4" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/android-tzdata/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android-tzdata/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +[package] +name = "android-tzdata" +version = "0.1.1" +authors = ["RumovZ"] +edition = "2018" +license = "MIT OR Apache-2.0" +description = "Parser for the Android-specific tzdata file" +repository = "https://github.com/RumovZ/android-tzdata" +readme = "README.md" +categories = ["date-and-time"] +keywords = ["parser", "android", "timezone"] +include = ["src/**/*", "LICENSE-*", "README.md"] + +[dev-dependencies] +zip = "0.6.4" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"0834cb3b5e092977688d73d219a05bed23ae0ecb54b6d6e5d866ce07f6583b5e","Cargo.lock":"37ffc00dbbbec58fd27b4f4cb597e5402d6cf615ce0458f62a73a7f0d987e5bd","Cargo.toml":"e9e8c037cdef7adc9794b17c13e5a014421524d67ea5048bc09cf70ef13c782c","LICENSE-APACHE":"216486f29671a4262efe32af6d84a75bef398127f8c5f369b5c8305983887a06","LICENSE-MIT":"80f275e90d799911ed3830a7f242a2ef5a4ade2092fe0aa07bfb2d2cf2f2b95e","README.md":"aba8ff5dbd0712326d97d32bc6a3b66b24d1980a446c238f7e14b96784766cd1","examples/time_zone.rs":"8edb32a946ef2680146ba9ac16c233dd94391ac9f98464e9fb6f87d3954b72a9","src/lib.rs":"0004133d6c3805bf449e7183d2931e9640167511bea6cd12b400805073c4305d"},"package":"819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"86f505a9258ea3098b18bb2b6c02cb45a2e0c368a9bef6814ee8865a3f169797","CONTRIBUTING.md":"0834cb3b5e092977688d73d219a05bed23ae0ecb54b6d6e5d866ce07f6583b5e","Cargo.lock":"37ffc00dbbbec58fd27b4f4cb597e5402d6cf615ce0458f62a73a7f0d987e5bd","Cargo.toml":"e9e8c037cdef7adc9794b17c13e5a014421524d67ea5048bc09cf70ef13c782c","Cargo.toml.orig":"749ab935be1cb6485115a677e36d680c2be95dcea8eb00c7b115006224ff926a","LICENSE-APACHE":"216486f29671a4262efe32af6d84a75bef398127f8c5f369b5c8305983887a06","LICENSE-MIT":"80f275e90d799911ed3830a7f242a2ef5a4ade2092fe0aa07bfb2d2cf2f2b95e","README.md":"aba8ff5dbd0712326d97d32bc6a3b66b24d1980a446c238f7e14b96784766cd1","examples/time_zone.rs":"8edb32a946ef2680146ba9ac16c233dd94391ac9f98464e9fb6f87d3954b72a9","src/lib.rs":"0004133d6c3805bf449e7183d2931e9640167511bea6cd12b400805073c4305d"},"package":"819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "fb87625f1807dff7623db2d80df682a199358515" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/android_system_properties/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/android_system_properties/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +[package] +name = "android_system_properties" +description = "Minimal Android system properties wrapper" +version = "0.1.5" +authors = ["Nicolas Silva "] +edition = "2018" +license = "MIT/Apache-2.0" +repository = "https://github.com/nical/android_system_properties" +homepage = "https://github.com/nical/android_system_properties" +documentation = "https://docs.rs/android_system_properties" +readme = "README.md" +keywords = [ + "android", +] + +[dependencies] +libc = "0.2.126" + +[package.metadata.docs.rs] +targets = ["arm-linux-androideabi", "armv7-linux-androideabi", "aarch64-linux-android", "i686-linux-android", "x86_64-linux-android", "x86_64-unknown-linux-gnu"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"d4c848de330bfd6ebf67040f6bc145cabba6b31d955cbc53f80a7d2d8f6fc1a7",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"eede1ddc498416c9ab11a436c9e20052e14e9edeec7d359f6386e4ae1cc6dbeb","Cargo.lock":"ab057b16b6abc081942386815511d21864c86835f645d970a88f5e13fbc00347","Cargo.toml":"823e6f663811c68c45a963e2ff119dc90a6ef09c71034fefc36b86b3ffc315e2","Cargo.toml.orig":"1d00eaf10f4b9e3e7fcb65786d0fea644a3dd77de82c0bd3bd014d89aade750e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"136d2b44cc4060192516f18e43ec3eafb65693c1819a80a867e7a00c60a45ee6","build.rs":"29240b1fb13d1d5f058a8197d8efb459fac757bc101a3743dddba3fbe803a83f","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"17f1925e1bed4752e0a542bdb1503a33279c0afac312229adf2b383a40263afc","src/chain.rs":"85af447405f075633fab186b7f1c94d7f33a36474f239c50a961b2d6197d5426","src/context.rs":"8b106e43df7a66fbc3e85b87a4d7f8a780d43d3ee0cd1ae86c571950ecf07d13","src/ensure.rs":"709524741c8f9365e01cb36fc2349a8724513de02cf9e253809a93af8d6a7b6e","src/error.rs":"9f3891ac4d1419f2d4f3c0f3367a41b23bd290f1899db1402be0aa6d0fb8fc30","src/fmt.rs":"adf4be906b29900153bfb4b767a6049d58697dc3bcce7dfbb85ca773f5de5b33","src/kind.rs":"ddcabf15b3b47a4ef16ed361c45cc0cc82e7be90622995ff6c04b3fec78bb04f","src/lib.rs":"23a5df991ad13d286f375173c4b69ec53175e03e60b9ed31bb15019064777998","src/macros.rs":"696e6a8aac614525a29697aedc7561e98beccf3d43aed3ada1cc93daa99da8ba","src/nightly.rs":"1c0aeadfcdbe22f8f807b185dec1a7448c378bddb37689714944b60473b58049","src/ptr.rs":"4cb31d2f815b178daf951bfb94a1930383e056c0ca68d494603f45d8eea35d50","src/wrapper.rs":"079218e1d8c9374f52311b1c7971f7fbdeba4d7af1b0749c0d535010f1232697","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"4e381aa8ca3eabb7ac14d1e0c3700b3223e47640547a6988cfa13ad68255f60f","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"ba9bc18416115cb48fd08675a3e7fc89584de7926dad6b2be6645dc13d5931df","tests/test_backtrace.rs":"60afdd7ee5850dc22625ff486fe41c47fd322db874a93c4871ddfed2bf603930","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"3a8a8d7569913bd98c0e27c69d0bda35101e7fde7c056ed57cdd8ed018e4cbcb","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"98b6a5f2edfaab68ad0b0e65f3d054fc62ee12cd1a282a92bd1d3cee232c1abf","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"0e49b48f08e4faaf03e2f202e1efc5250018876c4e1b01b8379d7a38ae8df870","tests/test_macros.rs":"68673942662a43bceee62aaed69c25d7ddbc55e25d62d528e13033c3e2e756cd","tests/test_repr.rs":"034dee888abd08741e11ac2e95ef4fcb2ab3943d0a76e8e976db404658e1a252","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"315782f5f4246290fe190e3767b22c3dcaffaabc19c5ace0373537d53e765278","tests/ui/ensure-nonbool.rs":"7e57cb93fbcd82959b36586ed6bd2ad978b051fe5facd5274651fde6b1600905","tests/ui/ensure-nonbool.stderr":"fef8aff2cedca3437b225dfb10e8eb47baeb49ec28605caef1485fa3fae839d0","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"8b1cb7fca632396a22bb3a642f2df3ab62b3e9a87951e20fa40bdd548d002162","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"c472de95483aa234728c7f57039c88fc3456892838329976a75cd167c3c172c9","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"171f6c1c962503855480696e5d39e68946ec2a027b61a6f36ca1ad1b40265c5d","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "18c2598afa0f996f56217ef128aa3a20ea1e9512" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.82.0, 1.80.0, 1.76.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - name: Enable nightly-only tests + run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=anyhow_nightly_testing >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + - run: cargo check --no-default-features + - run: cargo check --features backtrace + if: matrix.rust != '1.80.0' && matrix.rust != '1.76.0' + - uses: actions/upload-artifact@v4 + if: matrix.rust == 'nightly' && always() + with: + name: Cargo.lock + path: Cargo.lock + continue-on-error: true + + build: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [1.67.0, 1.65.0, 1.52.0, 1.51.0, 1.50.0, 1.39.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - run: cargo check --manifest-path tests/crate/Cargo.toml + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked --features backtrace + + windows: + name: Windows + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: windows-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + with: + components: rust-src + - run: cargo check --features backtrace + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,488 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gimli 0.31.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "anyhow" +version = "1.0.100" +dependencies = [ + "backtrace 0.3.75 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 2.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "trybuild 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "addr2line 0.24.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "object 0.36.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "windows-targets 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "equivalent 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler2 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.7.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-ident 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_core" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_spanned" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-triple" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 2.0.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "indexmap 2.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_spanned 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml_datetime 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml_parser 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml_writer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winnow 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml_datetime" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml_parser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winnow 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml_writer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "trybuild" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dissimilar 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)", + "target-triple 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "windows-sys 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "windows-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_aarch64_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_i686_gnu 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_i686_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_i686_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_x86_64_gnu 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_x86_64_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_x86_64_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum addr2line 0.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +"checksum adler2 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +"checksum backtrace 0.3.75 (registry+https://github.com/rust-lang/crates.io-index)" = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +"checksum cfg-if 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +"checksum dissimilar 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" +"checksum equivalent 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +"checksum futures 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +"checksum futures-channel 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +"checksum futures-core 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +"checksum futures-io 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +"checksum futures-sink 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +"checksum futures-task 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +"checksum futures-util 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +"checksum gimli 0.31.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +"checksum glob 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +"checksum hashbrown 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +"checksum indexmap 2.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +"checksum itoa 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +"checksum libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)" = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +"checksum memchr 2.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +"checksum miniz_oxide 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +"checksum object 0.36.7 (registry+https://github.com/rust-lang/crates.io-index)" = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +"checksum pin-project-lite 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +"checksum proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +"checksum quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +"checksum rustc-demangle 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +"checksum rustversion 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +"checksum ryu 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +"checksum serde 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)" = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +"checksum serde_core 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)" = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +"checksum serde_derive 1.0.225 (registry+https://github.com/rust-lang/crates.io-index)" = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" +"checksum serde_json 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)" = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +"checksum serde_spanned 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +"checksum syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +"checksum target-triple 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" +"checksum termcolor 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +"checksum thiserror 2.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +"checksum thiserror-impl 2.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +"checksum toml 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +"checksum toml_datetime 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +"checksum toml_parser 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +"checksum toml_writer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" +"checksum trybuild 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "0ded9fdb81f30a5708920310bfcd9ea7482ff9cba5f54601f7a19a877d5c2392" +"checksum unicode-ident 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +"checksum winapi-util 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +"checksum windows-link 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +"checksum windows-sys 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +"checksum windows-targets 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +"checksum windows_aarch64_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +"checksum windows_aarch64_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +"checksum windows_i686_gnu 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +"checksum windows_i686_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +"checksum windows_i686_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +"checksum windows_x86_64_gnu 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +"checksum windows_x86_64_gnullvm 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +"checksum windows_x86_64_msvc 0.52.6 (registry+https://github.com/rust-lang/crates.io-index)" = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +"checksum winnow 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,132 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.39" +name = "anyhow" +version = "1.0.100" +authors = ["David Tolnay "] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Flexible concrete Error type built on std::error::Error" +documentation = "https://docs.rs/anyhow" +readme = "README.md" +keywords = [ + "error", + "error-handling", +] +categories = [ + "rust-patterns", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/anyhow" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] + +[features] +default = ["std"] +std = [] + +[lib] +name = "anyhow" +path = "src/lib.rs" + +[[test]] +name = "compiletest" +path = "tests/compiletest.rs" + +[[test]] +name = "test_autotrait" +path = "tests/test_autotrait.rs" + +[[test]] +name = "test_backtrace" +path = "tests/test_backtrace.rs" + +[[test]] +name = "test_boxed" +path = "tests/test_boxed.rs" + +[[test]] +name = "test_chain" +path = "tests/test_chain.rs" + +[[test]] +name = "test_context" +path = "tests/test_context.rs" + +[[test]] +name = "test_convert" +path = "tests/test_convert.rs" + +[[test]] +name = "test_downcast" +path = "tests/test_downcast.rs" + +[[test]] +name = "test_ensure" +path = "tests/test_ensure.rs" + +[[test]] +name = "test_ffi" +path = "tests/test_ffi.rs" + +[[test]] +name = "test_fmt" +path = "tests/test_fmt.rs" + +[[test]] +name = "test_macros" +path = "tests/test_macros.rs" + +[[test]] +name = "test_repr" +path = "tests/test_repr.rs" + +[[test]] +name = "test_source" +path = "tests/test_source.rs" + +[dependencies.backtrace] +version = "0.3.51" +optional = true + +[dev-dependencies.futures] +version = "0.3" +default-features = false + +[dev-dependencies.rustversion] +version = "1.0.6" + +[dev-dependencies.syn] +version = "2.0" +features = ["full"] + +[dev-dependencies.thiserror] +version = "2" + +[dev-dependencies.trybuild] +version = "1.0.108" +features = ["diff"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +[package] +name = "anyhow" +version = "1.0.100" +authors = ["David Tolnay "] +categories = ["rust-patterns", "no-std"] +description = "Flexible concrete Error type built on std::error::Error" +documentation = "https://docs.rs/anyhow" +edition = "2018" +keywords = ["error", "error-handling"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/anyhow" +rust-version = "1.39" + +[features] +default = ["std"] +std = [] + +[dependencies] +# On compilers older than 1.65, features=["backtrace"] may be used to enable +# backtraces via the `backtrace` crate. This feature has no effect on 1.65+ +# besides bringing in an unused dependency, as `std::backtrace` is always +# preferred. +backtrace = { version = "0.3.51", optional = true } + +[dev-dependencies] +futures = { version = "0.3", default-features = false } +rustversion = "1.0.6" +syn = { version = "2.0", features = ["full"] } +thiserror = "2" +trybuild = { version = "1.0.108", features = ["diff"] } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/README.md clamav-1.4.6+dfsg/.cargo/vendor/anyhow/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,181 @@ +Anyhow ¯\\\_(°ペ)\_/¯ +========================== + +[github](https://github.com/dtolnay/anyhow) +[crates.io](https://crates.io/crates/anyhow) +[docs.rs](https://docs.rs/anyhow) +[build status](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster) + +This library provides [`anyhow::Error`][Error], a trait object based error type +for easy idiomatic error handling in Rust applications. + +[Error]: https://docs.rs/anyhow/1.0/anyhow/struct.Error.html + +```toml +[dependencies] +anyhow = "1.0" +``` + +*Compiler support: requires rustc 1.39+* + +
+ +## Details + +- Use `Result`, or equivalently `anyhow::Result`, as the + return type of any fallible function. + + Within the function, use `?` to easily propagate any error that implements the + [`std::error::Error`] trait. + + ```rust + use anyhow::Result; + + fn get_cluster_info() -> Result { + let config = std::fs::read_to_string("cluster.json")?; + let map: ClusterMap = serde_json::from_str(&config)?; + Ok(map) + } + ``` + + [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html + +- Attach context to help the person troubleshooting the error understand where + things went wrong. A low-level error like "No such file or directory" can be + annoying to debug without more context about what higher level step the + application was in the middle of. + + ```rust + use anyhow::{Context, Result}; + + fn main() -> Result<()> { + ... + it.detach().context("Failed to detach the important thing")?; + + let content = std::fs::read(path) + .with_context(|| format!("Failed to read instrs from {}", path))?; + ... + } + ``` + + ```console + Error: Failed to read instrs from ./path/to/instrs.json + + Caused by: + No such file or directory (os error 2) + ``` + +- Downcasting is supported and can be by value, by shared reference, or by + mutable reference as needed. + + ```rust + // If the error was caused by redaction, then return a + // tombstone instead of the content. + match root_cause.downcast_ref::() { + Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), + None => Err(error), + } + ``` + +- If using Rust ≥ 1.65, a backtrace is captured and printed with the error if + the underlying error type does not already provide its own. In order to see + backtraces, they must be enabled through the environment variables described + in [`std::backtrace`]: + + - If you want panics and errors to both have backtraces, set + `RUST_BACKTRACE=1`; + - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`; + - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and + `RUST_LIB_BACKTRACE=0`. + + [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables + +- Anyhow works with any error type that has an impl of `std::error::Error`, + including ones defined in your crate. We do not bundle a `derive(Error)` macro + but you can write the impls yourself or use a standalone macro like + [thiserror]. + + ```rust + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum FormatError { + #[error("Invalid header (expected {expected:?}, got {found:?})")] + InvalidHeader { + expected: String, + found: String, + }, + #[error("Missing attribute: {0}")] + MissingAttribute(String), + } + ``` + +- One-off error messages can be constructed using the `anyhow!` macro, which + supports string interpolation and produces an `anyhow::Error`. + + ```rust + return Err(anyhow!("Missing attribute: {}", missing)); + ``` + + A `bail!` macro is provided as a shorthand for the same early return. + + ```rust + bail!("Missing attribute: {}", missing); + ``` + +
+ +## No-std support + +In no_std mode, almost all of the same API is available and works the same way. +To depend on Anyhow in no_std mode, disable our default enabled "std" feature in +Cargo.toml. A global allocator is required. + +```toml +[dependencies] +anyhow = { version = "1.0", default-features = false } +``` + +With versions of Rust older than 1.81, no_std mode may require an additional +`.map_err(Error::msg)` when working with a non-Anyhow error type inside a +function that returns Anyhow's error type, as the trait that `?`-based error +conversions are defined by is only available in std in those old versions. + +
+ +## Comparison to failure + +The `anyhow::Error` type works something like `failure::Error`, but unlike +failure ours is built around the standard library's `std::error::Error` trait +rather than a separate trait `failure::Fail`. The standard library has adopted +the necessary improvements for this to be possible as part of [RFC 2504]. + +[RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md + +
+ +## Comparison to thiserror + +Use Anyhow if you don't care what error type your functions return, you just +want it to be easy. This is common in application code. Use [thiserror] if you +are a library that wants to design your own dedicated error type(s) so that on +failures the caller gets exactly the information that you choose. + +[thiserror]: https://github.com/dtolnay/thiserror + +
+ +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/build.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +use std::env; +use std::ffi::OsString; +use std::fs; +use std::io::ErrorKind; +use std::iter; +use std::path::Path; +use std::process::{self, Command, Stdio}; +use std::str; + +#[cfg(all(feature = "backtrace", not(feature = "std")))] +compile_error! { + "`backtrace` feature without `std` feature is not supported" +} + +fn main() { + let mut error_generic_member_access = false; + if cfg!(feature = "std") { + println!("cargo:rerun-if-changed=src/nightly.rs"); + + let consider_rustc_bootstrap; + if compile_probe(false) { + // This is a nightly or dev compiler, so it supports unstable + // features regardless of RUSTC_BOOTSTRAP. No need to rerun build + // script if RUSTC_BOOTSTRAP is changed. + error_generic_member_access = true; + consider_rustc_bootstrap = false; + } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { + if compile_probe(true) { + // This is a stable or beta compiler for which the user has set + // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build + // script if they change it. + error_generic_member_access = true; + consider_rustc_bootstrap = true; + } else if rustc_bootstrap == "1" { + // This compiler does not support the generic member access API + // in the form that anyhow expects. No need to pay attention to + // RUSTC_BOOTSTRAP. + error_generic_member_access = false; + consider_rustc_bootstrap = false; + } else { + // This is a stable or beta compiler for which RUSTC_BOOTSTRAP + // is set to restrict the use of unstable features by this + // crate. + error_generic_member_access = false; + consider_rustc_bootstrap = true; + } + } else { + // Without RUSTC_BOOTSTRAP, this compiler does not support the + // generic member access API in the form that anyhow expects, but + // try again if the user turns on unstable features. + error_generic_member_access = false; + consider_rustc_bootstrap = true; + } + + if error_generic_member_access { + println!("cargo:rustc-cfg=std_backtrace"); + println!("cargo:rustc-cfg=error_generic_member_access"); + } + + if consider_rustc_bootstrap { + println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); + } + } + + let rustc = match rustc_minor_version() { + Some(rustc) => rustc, + None => return, + }; + + if rustc >= 80 { + println!("cargo:rustc-check-cfg=cfg(anyhow_build_probe)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_nightly_testing)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_clippy_format_args)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_core_error)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_core_unwind_safe)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_fmt_arguments_as_str)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_ptr_addr_of)"); + println!("cargo:rustc-check-cfg=cfg(anyhow_no_unsafe_op_in_unsafe_fn_lint)"); + println!("cargo:rustc-check-cfg=cfg(error_generic_member_access)"); + println!("cargo:rustc-check-cfg=cfg(std_backtrace)"); + } + + if rustc < 51 { + // core::ptr::addr_of + // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis + println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of"); + } + + if rustc < 52 { + // core::fmt::Arguments::as_str + // https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html#stabilized-apis + println!("cargo:rustc-cfg=anyhow_no_fmt_arguments_as_str"); + + // #![deny(unsafe_op_in_unsafe_fn)] + // https://github.com/rust-lang/rust/issues/71668 + println!("cargo:rustc-cfg=anyhow_no_unsafe_op_in_unsafe_fn_lint"); + } + + if rustc < 56 { + // core::panic::{UnwindSafe, RefUnwindSafe} + // https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html#stabilized-apis + println!("cargo:rustc-cfg=anyhow_no_core_unwind_safe"); + } + + if !error_generic_member_access && cfg!(feature = "std") && rustc >= 65 { + // std::backtrace::Backtrace + // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#stabilized-apis + println!("cargo:rustc-cfg=std_backtrace"); + } + + if rustc < 81 { + // core::error::Error + // https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror + println!("cargo:rustc-cfg=anyhow_no_core_error"); + } + + if rustc < 85 { + // #[clippy::format_args] + // https://doc.rust-lang.org/1.85.1/clippy/attribs.html#clippyformat_args + println!("cargo:rustc-cfg=anyhow_no_clippy_format_args"); + } +} + +fn compile_probe(rustc_bootstrap: bool) -> bool { + if env::var_os("RUSTC_STAGE").is_some() { + // We are running inside rustc bootstrap. This is a highly non-standard + // environment with issues such as: + // + // https://github.com/rust-lang/cargo/issues/11138 + // https://github.com/rust-lang/rust/issues/114839 + // + // Let's just not use nightly features here. + return false; + } + + let rustc = cargo_env_var("RUSTC"); + let out_dir = cargo_env_var("OUT_DIR"); + let out_subdir = Path::new(&out_dir).join("probe"); + let probefile = Path::new("src").join("nightly.rs"); + + if let Err(err) = fs::create_dir(&out_subdir) { + if err.kind() != ErrorKind::AlreadyExists { + eprintln!("Failed to create {}: {}", out_subdir.display(), err); + process::exit(1); + } + } + + let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); + let rustc_workspace_wrapper = + env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); + let mut rustc = rustc_wrapper + .into_iter() + .chain(rustc_workspace_wrapper) + .chain(iter::once(rustc)); + let mut cmd = Command::new(rustc.next().unwrap()); + cmd.args(rustc); + + if !rustc_bootstrap { + cmd.env_remove("RUSTC_BOOTSTRAP"); + } + + cmd.stderr(Stdio::null()) + .arg("--cfg=anyhow_build_probe") + .arg("--edition=2018") + .arg("--crate-name=anyhow") + .arg("--crate-type=lib") + .arg("--cap-lints=allow") + .arg("--emit=dep-info,metadata") + .arg("--out-dir") + .arg(&out_subdir) + .arg(probefile); + + if let Some(target) = env::var_os("TARGET") { + cmd.arg("--target").arg(target); + } + + // If Cargo wants to set RUSTFLAGS, use that. + if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + for arg in rustflags.split('\x1f') { + cmd.arg(arg); + } + } + } + + let success = match cmd.status() { + Ok(status) => status.success(), + Err(_) => false, + }; + + // Clean up to avoid leaving nondeterministic absolute paths in the dep-info + // file in OUT_DIR, which causes nonreproducible builds in build systems + // that treat the entire OUT_DIR as an artifact. + if let Err(err) = fs::remove_dir_all(&out_subdir) { + // libc::ENOTEMPTY + // Some filesystems (NFSv3) have timing issues under load where '.nfs*' + // dummy files can continue to get created for a short period after the + // probe command completes, breaking remove_dir_all. + // To be replaced with ErrorKind::DirectoryNotEmpty (Rust 1.83+). + const ENOTEMPTY: i32 = 39; + + if !(err.kind() == ErrorKind::NotFound + || (cfg!(target_os = "linux") && err.raw_os_error() == Some(ENOTEMPTY))) + { + eprintln!("Failed to clean up {}: {}", out_subdir.display(), err); + process::exit(1); + } + } + + success +} + +fn rustc_minor_version() -> Option { + let rustc = cargo_env_var("RUSTC"); + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + pieces.next()?.parse().ok() +} + +fn cargo_env_var(key: &str) -> OsString { + env::var_os(key).unwrap_or_else(|| { + eprintln!( + "Environment variable ${} is not set during execution of build script", + key, + ); + process::exit(1); + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/rust-toolchain.toml clamav-1.4.6+dfsg/.cargo/vendor/anyhow/rust-toolchain.toml --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/rust-toolchain.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/rust-toolchain.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +[toolchain] +components = ["rust-src"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/backtrace.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/backtrace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/backtrace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/backtrace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,410 @@ +#[cfg(std_backtrace)] +pub(crate) use std::backtrace::{Backtrace, BacktraceStatus}; + +#[cfg(all(not(std_backtrace), feature = "backtrace"))] +pub(crate) use self::capture::{Backtrace, BacktraceStatus}; + +#[cfg(not(any(std_backtrace, feature = "backtrace")))] +pub(crate) enum Backtrace {} + +#[cfg(std_backtrace)] +macro_rules! impl_backtrace { + () => { + std::backtrace::Backtrace + }; +} + +#[cfg(all(not(std_backtrace), feature = "backtrace"))] +macro_rules! impl_backtrace { + () => { + impl core::fmt::Debug + core::fmt::Display + }; +} + +#[cfg(any(std_backtrace, feature = "backtrace"))] +macro_rules! backtrace { + () => { + Some(crate::backtrace::Backtrace::capture()) + }; +} + +#[cfg(not(any(std_backtrace, feature = "backtrace")))] +macro_rules! backtrace { + () => { + None + }; +} + +#[cfg(error_generic_member_access)] +macro_rules! backtrace_if_absent { + ($err:expr) => { + match $crate::nightly::request_ref_backtrace($err as &dyn core::error::Error) { + Some(_) => None, + None => backtrace!(), + } + }; +} + +#[cfg(all( + any(feature = "std", not(anyhow_no_core_error)), + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") +))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + backtrace!() + }; +} + +#[cfg(all( + any(feature = "std", not(anyhow_no_core_error)), + not(std_backtrace), + not(feature = "backtrace"), +))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + None + }; +} + +#[cfg(all(not(std_backtrace), feature = "backtrace"))] +mod capture { + use alloc::borrow::{Cow, ToOwned as _}; + use alloc::vec::Vec; + use backtrace::{BacktraceFmt, BytesOrWideString, Frame, PrintFmt, SymbolName}; + use core::cell::UnsafeCell; + use core::fmt::{self, Debug, Display}; + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::env; + use std::path::{self, Path, PathBuf}; + use std::sync::Once; + + pub(crate) struct Backtrace { + inner: Inner, + } + + pub(crate) enum BacktraceStatus { + Unsupported, + Disabled, + Captured, + } + + enum Inner { + Unsupported, + Disabled, + Captured(LazilyResolvedCapture), + } + + struct Capture { + actual_start: usize, + resolved: bool, + frames: Vec, + } + + struct BacktraceFrame { + frame: Frame, + symbols: Vec, + } + + struct BacktraceSymbol { + name: Option>, + filename: Option, + lineno: Option, + colno: Option, + } + + enum BytesOrWide { + Bytes(Vec), + Wide(Vec), + } + + impl Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str(""), + Inner::Disabled => return fmt.write_str(""), + Inner::Captured(c) => c.force(), + }; + + let frames = &capture.frames[capture.actual_start..]; + + write!(fmt, "Backtrace ")?; + + let mut dbg = fmt.debug_list(); + + for frame in frames { + if frame.frame.ip().is_null() { + continue; + } + + dbg.entries(&frame.symbols); + } + + dbg.finish() + } + } + + impl Debug for BacktraceFrame { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut dbg = fmt.debug_list(); + dbg.entries(&self.symbols); + dbg.finish() + } + } + + impl Debug for BacktraceSymbol { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{{ ")?; + + if let Some(fn_name) = self.name.as_ref().map(|b| SymbolName::new(b)) { + write!(fmt, "fn: \"{:#}\"", fn_name)?; + } else { + write!(fmt, "fn: ")?; + } + + if let Some(fname) = self.filename.as_ref() { + write!(fmt, ", file: \"{:?}\"", fname)?; + } + + if let Some(line) = self.lineno { + write!(fmt, ", line: {:?}", line)?; + } + + write!(fmt, " }}") + } + } + + impl Debug for BytesOrWide { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + output_filename( + fmt, + match self { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }, + PrintFmt::Short, + env::current_dir().as_ref().ok(), + ) + } + } + + impl Backtrace { + fn enabled() -> bool { + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(Ordering::Relaxed) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var_os("RUST_LIB_BACKTRACE") { + Some(s) => s != "0", + None => match env::var_os("RUST_BACKTRACE") { + Some(s) => s != "0", + None => false, + }, + }; + ENABLED.store(enabled as usize + 1, Ordering::Relaxed); + enabled + } + + #[inline(never)] // want to make sure there's a frame here to remove + pub(crate) fn capture() -> Backtrace { + if Backtrace::enabled() { + Backtrace::create(Backtrace::capture as usize) + } else { + let inner = Inner::Disabled; + Backtrace { inner } + } + } + + // Capture a backtrace which starts just before the function addressed + // by `ip` + fn create(ip: usize) -> Backtrace { + let mut frames = Vec::new(); + let mut actual_start = None; + backtrace::trace(|frame| { + frames.push(BacktraceFrame { + frame: frame.clone(), + symbols: Vec::new(), + }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len() + 1); + } + true + }); + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right + // now, and this should be a good enough approximation. + let inner = if frames.is_empty() { + Inner::Unsupported + } else { + Inner::Captured(LazilyResolvedCapture::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + Backtrace { inner } + } + + pub(crate) fn status(&self) -> BacktraceStatus { + match self.inner { + Inner::Unsupported => BacktraceStatus::Unsupported, + Inner::Disabled => BacktraceStatus::Disabled, + Inner::Captured(_) => BacktraceStatus::Captured, + } + } + } + + impl Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("unsupported backtrace"), + Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Captured(c) => c.force(), + }; + + let full = fmt.alternate(); + let (frames, style) = if full { + (&capture.frames[..], PrintFmt::Full) + } else { + (&capture.frames[capture.actual_start..], PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, + // otherwise we just print the path as-is. Note that we also only do + // this for the short format, because if it's full we presumably + // want to print everything. + let cwd = env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: BytesOrWideString| { + output_filename(fmt, path, style, cwd.as_ref().ok()) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + let mut f = f.frame(); + if frame.symbols.is_empty() { + f.print_raw(frame.frame.ip(), None, None, None)?; + } else { + for symbol in frame.symbols.iter() { + f.print_raw_with_column( + frame.frame.ip(), + symbol.name.as_ref().map(|b| SymbolName::new(b)), + symbol.filename.as_ref().map(|b| match b { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }), + symbol.lineno, + symbol.colno, + )?; + } + } + } + f.finish()?; + Ok(()) + } + } + + struct LazilyResolvedCapture { + sync: Once, + capture: UnsafeCell, + } + + impl LazilyResolvedCapture { + fn new(capture: Capture) -> Self { + LazilyResolvedCapture { + sync: Once::new(), + capture: UnsafeCell::new(capture), + } + } + + fn force(&self) -> &Capture { + self.sync.call_once(|| { + // Safety: This exclusive reference can't overlap with any + // others. `Once` guarantees callers will block until this + // closure returns. `Once` also guarantees only a single caller + // will enter this closure. + unsafe { &mut *self.capture.get() }.resolve(); + }); + + // Safety: This shared reference can't overlap with the exclusive + // reference above. + unsafe { &*self.capture.get() } + } + } + + // Safety: Access to the inner value is synchronized using a thread-safe + // `Once`. So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too + unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} + + impl Capture { + fn resolve(&mut self) { + // If we're already resolved, nothing to do! + if self.resolved { + return; + } + self.resolved = true; + + for frame in self.frames.iter_mut() { + let symbols = &mut frame.symbols; + let frame = &frame.frame; + backtrace::resolve_frame(frame, |symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().to_vec()), + filename: symbol.filename_raw().map(|b| match b { + BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()), + BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()), + }), + lineno: symbol.lineno(), + colno: symbol.colno(), + }); + }); + } + } + } + + // Prints the filename of the backtrace frame. + fn output_filename( + fmt: &mut fmt::Formatter, + bows: BytesOrWideString, + print_fmt: PrintFmt, + cwd: Option<&PathBuf>, + ) -> fmt::Result { + let file: Cow = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use std::os::unix::ffi::OsStrExt; + Path::new(std::ffi::OsStr::from_bytes(bytes)).into() + } + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(std::str::from_utf8(bytes).unwrap_or("")).into() + } + #[cfg(windows)] + BytesOrWideString::Wide(wide) => { + use std::os::windows::ffi::OsStringExt; + Cow::Owned(std::ffi::OsString::from_wide(wide).into()) + } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => Path::new("").into(), + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Some(cwd) = cwd { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); + } + } + } + } + Display::fmt(&file.display(), fmt) + } +} + +fn _assert_send_sync() { + fn assert() {} + assert::(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/chain.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/chain.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/chain.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/chain.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +use self::ChainState::*; +use crate::StdError; + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +use alloc::vec::{self, Vec}; + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +pub(crate) use crate::Chain; + +#[cfg(all(not(feature = "std"), anyhow_no_core_error))] +pub(crate) struct Chain<'a> { + state: ChainState<'a>, +} + +#[derive(Clone)] +pub(crate) enum ChainState<'a> { + Linked { + next: Option<&'a (dyn StdError + 'static)>, + }, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + Buffered { + rest: vec::IntoIter<&'a (dyn StdError + 'static)>, + }, +} + +impl<'a> Chain<'a> { + #[cold] + pub fn new(head: &'a (dyn StdError + 'static)) -> Self { + Chain { + state: ChainState::Linked { next: Some(head) }, + } + } +} + +impl<'a> Iterator for Chain<'a> { + type Item = &'a (dyn StdError + 'static); + + fn next(&mut self) -> Option { + match &mut self.state { + Linked { next } => { + let error = (*next)?; + *next = error.source(); + Some(error) + } + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + Buffered { rest } => rest.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl DoubleEndedIterator for Chain<'_> { + fn next_back(&mut self) -> Option { + match &mut self.state { + Linked { mut next } => { + let mut rest = Vec::new(); + while let Some(cause) = next { + next = cause.source(); + rest.push(cause); + } + let mut rest = rest.into_iter(); + let last = rest.next_back(); + self.state = Buffered { rest }; + last + } + Buffered { rest } => rest.next_back(), + } + } +} + +impl ExactSizeIterator for Chain<'_> { + fn len(&self) -> usize { + match &self.state { + Linked { mut next } => { + let mut len = 0; + while let Some(cause) = next { + next = cause.source(); + len += 1; + } + len + } + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + Buffered { rest } => rest.len(), + } + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl Default for Chain<'_> { + fn default() -> Self { + Chain { + state: ChainState::Buffered { + rest: Vec::new().into_iter(), + }, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/context.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/context.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +use crate::error::ContextError; +use crate::{Context, Error, StdError}; +use core::convert::Infallible; +use core::fmt::{self, Debug, Display, Write}; + +#[cfg(error_generic_member_access)] +use crate::nightly::{self, Request}; + +mod ext { + use super::*; + + pub trait StdError { + fn ext_context(self, context: C) -> Error + where + C: Display + Send + Sync + 'static; + } + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + impl StdError for E + where + E: crate::StdError + Send + Sync + 'static, + { + fn ext_context(self, context: C) -> Error + where + C: Display + Send + Sync + 'static, + { + let backtrace = backtrace_if_absent!(&self); + Error::construct_from_context(context, self, backtrace) + } + } + + impl StdError for Error { + fn ext_context(self, context: C) -> Error + where + C: Display + Send + Sync + 'static, + { + self.context(context) + } + } +} + +impl Context for Result +where + E: ext::StdError + Send + Sync + 'static, +{ + fn context(self, context: C) -> Result + where + C: Display + Send + Sync + 'static, + { + // Not using map_err to save 2 useless frames off the captured backtrace + // in ext_context. + match self { + Ok(ok) => Ok(ok), + Err(error) => Err(error.ext_context(context)), + } + } + + fn with_context(self, context: F) -> Result + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C, + { + match self { + Ok(ok) => Ok(ok), + Err(error) => Err(error.ext_context(context())), + } + } +} + +/// ``` +/// # type T = (); +/// # +/// use anyhow::{Context, Result}; +/// +/// fn maybe_get() -> Option { +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unimplemented!() +/// } +/// +/// fn demo() -> Result<()> { +/// let t = maybe_get().context("there is no T")?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unimplemented!() +/// } +/// ``` +impl Context for Option { + fn context(self, context: C) -> Result + where + C: Display + Send + Sync + 'static, + { + // Not using ok_or_else to save 2 useless frames off the captured + // backtrace. + match self { + Some(ok) => Ok(ok), + None => Err(Error::construct_from_display(context, backtrace!())), + } + } + + fn with_context(self, context: F) -> Result + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C, + { + match self { + Some(ok) => Ok(ok), + None => Err(Error::construct_from_display(context(), backtrace!())), + } + } +} + +impl Debug for ContextError +where + C: Display, + E: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Error") + .field("context", &Quoted(&self.context)) + .field("source", &self.error) + .finish() + } +} + +impl Display for ContextError +where + C: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.context, f) + } +} + +impl StdError for ContextError +where + C: Display, + E: StdError + 'static, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&self.error) + } + + #[cfg(error_generic_member_access)] + fn provide<'a>(&'a self, request: &mut Request<'a>) { + nightly::provide(&self.error, request); + } +} + +impl StdError for ContextError +where + C: Display, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) + } + + #[cfg(error_generic_member_access)] + fn provide<'a>(&'a self, request: &mut Request<'a>) { + Error::provide(&self.error, request); + } +} + +struct Quoted(C); + +impl Debug for Quoted +where + C: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_char('"')?; + Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; + formatter.write_char('"')?; + Ok(()) + } +} + +impl Write for Quoted<&mut fmt::Formatter<'_>> { + fn write_str(&mut self, s: &str) -> fmt::Result { + Display::fmt(&s.escape_debug(), self.0) + } +} + +pub(crate) mod private { + use super::*; + + pub trait Sealed {} + + impl Sealed for Result where E: ext::StdError {} + impl Sealed for Option {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/ensure.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ensure.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/ensure.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ensure.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,935 @@ +use crate::Error; +use alloc::string::String; +use core::fmt::{self, Debug, Write}; +use core::mem::MaybeUninit; +use core::ptr; +use core::slice; +use core::str; + +#[doc(hidden)] +pub trait BothDebug { + fn __dispatch_ensure(self, msg: &'static str) -> Error; +} + +impl BothDebug for (A, B) +where + A: Debug, + B: Debug, +{ + fn __dispatch_ensure(self, msg: &'static str) -> Error { + render(msg, &self.0, &self.1) + } +} + +#[doc(hidden)] +pub trait NotBothDebug { + fn __dispatch_ensure(self, msg: &'static str) -> Error; +} + +impl NotBothDebug for &(A, B) { + fn __dispatch_ensure(self, msg: &'static str) -> Error { + Error::msg(msg) + } +} + +struct Buf { + bytes: [MaybeUninit; 40], + written: usize, +} + +impl Buf { + fn new() -> Self { + Buf { + bytes: [MaybeUninit::uninit(); 40], + written: 0, + } + } + + fn as_str(&self) -> &str { + unsafe { + str::from_utf8_unchecked(slice::from_raw_parts( + self.bytes.as_ptr().cast::(), + self.written, + )) + } + } +} + +impl Write for Buf { + fn write_str(&mut self, s: &str) -> fmt::Result { + if s.bytes().any(|b| b == b' ' || b == b'\n') { + return Err(fmt::Error); + } + + let remaining = self.bytes.len() - self.written; + if s.len() > remaining { + return Err(fmt::Error); + } + + unsafe { + ptr::copy_nonoverlapping( + s.as_ptr(), + self.bytes.as_mut_ptr().add(self.written).cast::(), + s.len(), + ); + } + self.written += s.len(); + Ok(()) + } +} + +fn render(msg: &'static str, lhs: &dyn Debug, rhs: &dyn Debug) -> Error { + let mut lhs_buf = Buf::new(); + if fmt::write(&mut lhs_buf, format_args!("{:?}", lhs)).is_ok() { + let mut rhs_buf = Buf::new(); + if fmt::write(&mut rhs_buf, format_args!("{:?}", rhs)).is_ok() { + let lhs_str = lhs_buf.as_str(); + let rhs_str = rhs_buf.as_str(); + // "{msg} ({lhs} vs {rhs})" + let len = msg.len() + 2 + lhs_str.len() + 4 + rhs_str.len() + 1; + let mut string = String::with_capacity(len); + string.push_str(msg); + string.push_str(" ("); + string.push_str(lhs_str); + string.push_str(" vs "); + string.push_str(rhs_str); + string.push(')'); + return Error::msg(string); + } + } + Error::msg(msg) +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __parse_ensure { + (atom () $bail:tt $fuel:tt {($($rhs:tt)+) ($($lhs:tt)+) $op:tt} $dup:tt $(,)?) => { + $crate::__fancy_ensure!($($lhs)+, $op, $($rhs)+) + }; + + // low precedence control flow constructs + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt return $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt break $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt continue $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt yield $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt move $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + // unary operators + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($deref:tt $($dup:tt)*) * $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $deref) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($not:tt $($dup:tt)*) ! $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $not) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($let:tt $($dup:tt)*) let $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $let) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($lifetime:tt $colon:tt $($dup:tt)*) $label:lifetime : $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $lifetime $colon) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) &mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $raw:tt $mut:tt $($dup:tt)*) &raw mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and $raw $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $raw:tt $const:tt $($dup:tt)*) &raw const $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and $raw $const) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $mut:tt $($dup:tt)*) &&mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $raw:tt $mut:tt $($dup:tt)*) &&raw mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand $raw $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $raw:tt $const:tt $($dup:tt)*) &&raw const $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand $raw $const) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*) + }; + + // control flow constructs + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($if:tt $($dup:tt)*) if $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $if) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($match:tt $($dup:tt)*) match $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $match) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($while:tt $($dup:tt)*) while $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $while) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $($dup:tt)*) for $($rest:tt)*) => { + $crate::__parse_ensure!(pat (cond $stack) $bail ($($fuel)*) {($($buf)* $for) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom (cond $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(cond $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $if:tt $($dup:tt)*) else if $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $else $if) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $brace:tt $($dup:tt)*) else {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $else $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // atomic expressions + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($array:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($loop:tt $block:tt $($dup:tt)*) loop {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $loop $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $block:tt $($dup:tt)*) async {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $move:tt $block:tt $($dup:tt)*) async move {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $move $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $block:tt $($dup:tt)*) unsafe {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $unsafe $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($const:tt $block:tt $($dup:tt)*) const {$($body:tt)*} $($rest:tt)*) => { + // TODO: this is mostly useless due to https://github.com/rust-lang/rust/issues/86730 + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $const $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $literal) $($parse)*} ($($rest)*) $($rest)*) + }; + + // path expressions + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ident:tt $($dup:tt)*) $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (epath (atom $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: << $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath (arglist (epath $stack)))) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt :: <- - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $larrow:tt $($dup:tt)*) :: <- $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // trailer expressions + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($call:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($index:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($init:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($question:tt $($dup:tt)*) ? $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $question) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $langle:tt $($dup:tt)*) . $i:ident :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $langle:tt $($dup:tt)*) . $i:ident :: << $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath (arglist (atom $stack)))) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt . $i:ident :: <- - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $larrow:tt $($dup:tt)*) . $i:ident :: <- $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $field:tt $($dup:tt)*) . $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $field) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt . - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $index:tt $($dup:tt)*) . $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $index) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => { + $crate::__parse_ensure!(type (atom $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*) + }; + + // types + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $const:tt $($dup:tt)*) *const $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $const) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $mut:tt $($dup:tt)*) *mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $lifetime:tt $mut:tt $($dup:tt)*) & $l:lifetime mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) & mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $lifetime:tt $($dup:tt)*) & $l:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $lifetime:tt $mut:tt $($dup:tt)*) && $l:lifetime mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) && mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $lifetime:tt $($dup:tt)*) && $l:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt unsafe extern - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $(extern $($abi:literal)?)? fn $($dup:tt)*) unsafe $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $unsafe) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt extern - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt $abi:tt fn $($dup:tt)*) extern $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern $abi) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt fn $($dup:tt)*) extern $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $arrow:tt $($dup:tt)*) fn ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $fn $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $($dup:tt)*) fn ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $fn $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($impl:tt $($dup:tt)*) impl $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $impl) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dyn:tt $($dup:tt)*) dyn $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $dyn) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($never:tt $($dup:tt)*) ! $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $never) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $langle:tt $($dup:tt)*) for < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (type $stack) $bail ($($fuel)*) {($($buf)* $for $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + // path types + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ident:tt $($dup:tt)*) $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath $stack)) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) << $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath (arglist (tpath $stack)))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt <- - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($larrow:tt $($dup:tt)*) <- $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $larrow) $($parse)*} ($($dup)*) $($dup)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: << $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath (arglist (tpath $stack)))) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt :: <- - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $larrow:tt $($dup:tt)*) :: <- $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $arrow:tt $($dup:tt)*) ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $arrow:tt $($dup:tt)*) :: ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $colons $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $($dup:tt)*) :: ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $colons $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // qualified paths + + (qpath (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $ident:tt $($dup:tt)*) >> :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (qpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $ident:tt $($dup:tt)*) > :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (qpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*) + }; + + // trait objects + + (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $colons:tt $ident:tt $($dup:tt)*) + :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $ident:tt $($dup:tt)*) + $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (object (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + (object ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // angle bracketed generic arguments + + (generic (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) {($($buf)*) $($parse)*} ($rangle $($rest)*) $rangle $($rest)*) + }; + + (generic $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(generic $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($dup)*) $($dup)*) + }; + + (generic $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $literal) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($lifetime:tt $($dup:tt)*) $l:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $lifetime) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assoc:tt $eq:tt $($dup:tt)*) $ident:ident = $($rest:tt)*) => { + $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) {($($buf)* $assoc $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + (arglist $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($comma:tt $($dup:tt)*) , $($rest:tt)*) => { + $crate::__parse_ensure!(generic $stack $bail ($($fuel)*) {($($buf)* $comma) $($parse)*} ($($rest)*) $($rest)*) + }; + + (arglist (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)*) $rangle $($parse)*} ($($rest)*) $($rest)*) + }; + + (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) {($($buf)*) $($parse)*} ($rangle $($rest)*) $rangle $($rest)*) + }; + + // patterns + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($pipe:tt $($dup:tt)*) | $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $pipe) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) = $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($in:tt $($dup:tt)*) in $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $in) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ref:tt $($dup:tt)*) ref $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $ref) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mut:tt $($dup:tt)*) mut $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($at:tt $($dup:tt)*) @ $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $at) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($dup)*) $($dup)*) + }; + + (pat $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $literal) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) .. $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) ..= $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($content:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ident:tt $($dup:tt)*) $i:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (epath (pat $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + // comparison binary operators + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $eq} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $le} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $le) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $lt} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $lt) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ne} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ne) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ge} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ge) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom (split ()) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)* > ) > } ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $gt} ($($rest)*) $($rest)*) + }; + + (atom (split $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $gt) $($parse)*} ($($rest)*) $($rest)*) + }; + + // high precedence binary operators + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($add:tt $($dup:tt)*) + $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $add) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($sub:tt $($dup:tt)*) - $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $sub) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mul:tt $($dup:tt)*) * $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $mul) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($div:tt $($dup:tt)*) / $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $div) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rem:tt $($dup:tt)*) % $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $rem) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxor:tt $($dup:tt)*) ^ $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitxor) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitand:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitand) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitor:tt $($dup:tt)*) | $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitor) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shl:tt $($dup:tt)*) << $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shl) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shr:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shr) $($parse)*} ($($rest)*) $($rest)*) + }; + + // low precedence binary operators + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($or:tt $($dup:tt)*) || $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $or) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assign:tt $($dup:tt)*) = $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $assign) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($addeq:tt $($dup:tt)*) += $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $addeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($subeq:tt $($dup:tt)*) -= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $subeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($muleq:tt $($dup:tt)*) *= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $muleq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($diveq:tt $($dup:tt)*) /= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $diveq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($remeq:tt $($dup:tt)*) %= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $remeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxoreq:tt $($dup:tt)*) ^= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitxoreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitandeq:tt $($dup:tt)*) &= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitandeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitoreq:tt $($dup:tt)*) |= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitoreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shleq:tt $($dup:tt)*) <<= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shleq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shreq:tt $($dup:tt)*) >>= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + // unrecognized expression + + ($state:tt $stack:tt ($($bail:tt)*) $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __fancy_ensure { + ($lhs:expr, $op:tt, $rhs:expr) => { + match (&$lhs, &$rhs) { + (lhs, rhs) => { + if !(lhs $op rhs) { + #[allow(unused_imports)] + use $crate::__private::{BothDebug, NotBothDebug}; + return Err((lhs, rhs).__dispatch_ensure( + $crate::__private::concat!( + "Condition failed: `", + $crate::__private::stringify!($lhs), + " ", + $crate::__private::stringify!($op), + " ", + $crate::__private::stringify!($rhs), + "`", + ), + )); + } + } + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __fallback_ensure { + ($cond:expr $(,)?) => { + if $crate::__private::not($cond) { + return $crate::__private::Err($crate::Error::msg( + $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`") + )); + } + }; + ($cond:expr, $msg:literal $(,)?) => { + if $crate::__private::not($cond) { + return $crate::__private::Err($crate::__anyhow!($msg)); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if $crate::__private::not($cond) { + return $crate::__private::Err($crate::__anyhow!($err)); + } + }; + ($cond:expr, $fmt:expr, $($arg:tt)*) => { + if $crate::__private::not($cond) { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)); + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1218 @@ +use crate::backtrace::Backtrace; +use crate::chain::Chain; +#[cfg(error_generic_member_access)] +use crate::nightly::{self, Request}; +#[cfg(any(feature = "std", not(anyhow_no_core_error), anyhow_no_ptr_addr_of))] +use crate::ptr::Mut; +use crate::ptr::{Own, Ref}; +use crate::{Error, StdError}; +use alloc::boxed::Box; +use core::any::TypeId; +use core::fmt::{self, Debug, Display}; +use core::mem::ManuallyDrop; +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +use core::ops::{Deref, DerefMut}; +#[cfg(not(anyhow_no_core_unwind_safe))] +use core::panic::{RefUnwindSafe, UnwindSafe}; +#[cfg(not(anyhow_no_ptr_addr_of))] +use core::ptr; +use core::ptr::NonNull; +#[cfg(all(feature = "std", anyhow_no_core_unwind_safe))] +use std::panic::{RefUnwindSafe, UnwindSafe}; + +impl Error { + /// Create a new error object from any error type. + /// + /// The error type must be threadsafe and `'static`, so that the `Error` + /// will be as well. + /// + /// If the error type does not provide a backtrace, a backtrace will be + /// created here to ensure that a backtrace exists. + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + #[must_use] + pub fn new(error: E) -> Self + where + E: StdError + Send + Sync + 'static, + { + let backtrace = backtrace_if_absent!(&error); + Error::construct_from_std(error, backtrace) + } + + /// Create a new error object from a printable error message. + /// + /// If the argument implements std::error::Error, prefer `Error::new` + /// instead which preserves the underlying error's cause chain and + /// backtrace. If the argument may or may not implement std::error::Error + /// now or in the future, use `anyhow!(err)` which handles either way + /// correctly. + /// + /// `Error::msg("...")` is equivalent to `anyhow!("...")` but occasionally + /// convenient in places where a function is preferable over a macro, such + /// as iterator or stream combinators: + /// + /// ``` + /// # mod ffi { + /// # pub struct Input; + /// # pub struct Output; + /// # pub async fn do_some_work(_: Input) -> Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # use ffi::{Input, Output}; + /// # + /// use anyhow::{Error, Result}; + /// use futures::stream::{Stream, StreamExt, TryStreamExt}; + /// + /// async fn demo(stream: S) -> Result> + /// where + /// S: Stream, + /// { + /// stream + /// .then(ffi::do_some_work) // returns Result + /// .map_err(Error::msg) + /// .try_collect() + /// .await + /// } + /// ``` + #[cold] + #[must_use] + pub fn msg(message: M) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + Error::construct_from_adhoc(message, backtrace!()) + } + + /// Construct an error object from a type-erased standard library error. + /// + /// This is mostly useful for interop with other error libraries. + /// + /// # Example + /// + /// Here is a skeleton of a library that provides its own error abstraction. + /// The pair of `From` impls provide bidirectional support for `?` + /// conversion between `Report` and `anyhow::Error`. + /// + /// ``` + /// use std::error::Error as StdError; + /// + /// pub struct Report {/* ... */} + /// + /// impl From for Report + /// where + /// E: Into, + /// Result<(), E>: anyhow::Context<(), E>, + /// { + /// fn from(error: E) -> Self { + /// let anyhow_error: anyhow::Error = error.into(); + /// let boxed_error: Box = anyhow_error.into(); + /// Report::from_boxed(boxed_error) + /// } + /// } + /// + /// impl From for anyhow::Error { + /// fn from(report: Report) -> Self { + /// let boxed_error: Box = report.into_boxed(); + /// anyhow::Error::from_boxed(boxed_error) + /// } + /// } + /// + /// impl Report { + /// fn from_boxed(boxed_error: Box) -> Self { + /// todo!() + /// } + /// fn into_boxed(self) -> Box { + /// todo!() + /// } + /// } + /// + /// // Example usage: can use `?` in both directions. + /// fn a() -> anyhow::Result<()> { + /// b()?; + /// Ok(()) + /// } + /// fn b() -> Result<(), Report> { + /// a()?; + /// Ok(()) + /// } + /// ``` + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + #[must_use] + pub fn from_boxed(boxed_error: Box) -> Self { + let backtrace = backtrace_if_absent!(&*boxed_error); + Error::construct_from_boxed(boxed_error, backtrace) + } + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + pub(crate) fn construct_from_std(error: E, backtrace: Option) -> Self + where + E: StdError + Send + Sync + 'static, + { + let vtable = &ErrorVTable { + object_drop: object_drop::, + object_ref: object_ref::, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::, + object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, + object_drop_rest: object_drop_front::, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: no_backtrace, + }; + + // Safety: passing vtable that operates on the right type E. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cold] + pub(crate) fn construct_from_adhoc(message: M, backtrace: Option) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + use crate::wrapper::MessageError; + let error: MessageError = MessageError(message); + let vtable = &ErrorVTable { + object_drop: object_drop::>, + object_ref: object_ref::>, + #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] + object_mut: object_mut::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::>, + object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, + object_drop_rest: object_drop_front::, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: no_backtrace, + }; + + // Safety: MessageError is repr(transparent) so it is okay for the + // vtable to allow casting the MessageError to M. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cold] + pub(crate) fn construct_from_display(message: M, backtrace: Option) -> Self + where + M: Display + Send + Sync + 'static, + { + use crate::wrapper::DisplayError; + let error: DisplayError = DisplayError(message); + let vtable = &ErrorVTable { + object_drop: object_drop::>, + object_ref: object_ref::>, + #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] + object_mut: object_mut::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::>, + object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, + object_drop_rest: object_drop_front::, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: no_backtrace, + }; + + // Safety: DisplayError is repr(transparent) so it is okay for the + // vtable to allow casting the DisplayError to M. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + pub(crate) fn construct_from_context( + context: C, + error: E, + backtrace: Option, + ) -> Self + where + C: Display + Send + Sync + 'static, + E: StdError + Send + Sync + 'static, + { + let error: ContextError = ContextError { context, error }; + + let vtable = &ErrorVTable { + object_drop: object_drop::>, + object_ref: object_ref::>, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::>, + object_downcast: context_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_downcast_mut::, + object_drop_rest: context_drop_rest::, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: no_backtrace, + }; + + // Safety: passing vtable that operates on the right type. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + pub(crate) fn construct_from_boxed( + error: Box, + backtrace: Option, + ) -> Self { + use crate::wrapper::BoxedError; + let error = BoxedError(error); + let vtable = &ErrorVTable { + object_drop: object_drop::, + object_ref: object_ref::, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::, + object_downcast: object_downcast::>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::>, + object_drop_rest: object_drop_front::>, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: no_backtrace, + }; + + // Safety: BoxedError is repr(transparent) so it is okay for the vtable + // to allow casting to Box. + unsafe { Error::construct(error, vtable, backtrace) } + } + + // Takes backtrace as argument rather than capturing it here so that the + // user sees one fewer layer of wrapping noise in the backtrace. + // + // Unsafe because the given vtable must have sensible behavior on the error + // value of type E. + #[cold] + unsafe fn construct( + error: E, + vtable: &'static ErrorVTable, + backtrace: Option, + ) -> Self + where + E: StdError + Send + Sync + 'static, + { + let inner: Box> = Box::new(ErrorImpl { + vtable, + backtrace, + _object: error, + }); + // Erase the concrete type of E from the compile-time type system. This + // is equivalent to the safe unsize coercion from Box> to + // Box> except that the + // result is a thin pointer. The necessary behavior for manipulating the + // underlying ErrorImpl is preserved in the vtable provided by the + // caller rather than a builtin fat pointer vtable. + let inner = Own::new(inner).cast::(); + Error { inner } + } + + /// Wrap the error value with additional context. + /// + /// For attaching context to a `Result` as it is propagated, the + /// [`Context`][crate::Context] extension trait may be more convenient than + /// this function. + /// + /// The primary reason to use `error.context(...)` instead of + /// `result.context(...)` via the `Context` trait would be if the context + /// needs to depend on some data held by the underlying error: + /// + /// ``` + /// # use std::fmt::{self, Debug, Display}; + /// # + /// # type T = (); + /// # + /// # impl std::error::Error for ParseError {} + /// # impl Debug for ParseError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # impl Display for ParseError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use anyhow::Result; + /// use std::fs::File; + /// use std::path::Path; + /// + /// struct ParseError { + /// line: usize, + /// column: usize, + /// } + /// + /// fn parse_impl(file: File) -> Result { + /// # const IGNORE: &str = stringify! { + /// ... + /// # }; + /// # unimplemented!() + /// } + /// + /// pub fn parse(path: impl AsRef) -> Result { + /// let file = File::open(&path)?; + /// parse_impl(file).map_err(|error| { + /// let context = format!( + /// "only the first {} lines of {} are valid", + /// error.line, path.as_ref().display(), + /// ); + /// anyhow::Error::new(error).context(context) + /// }) + /// } + /// ``` + #[cold] + #[must_use] + pub fn context(self, context: C) -> Self + where + C: Display + Send + Sync + 'static, + { + let error: ContextError = ContextError { + context, + error: self, + }; + + let vtable = &ErrorVTable { + object_drop: object_drop::>, + object_ref: object_ref::>, + #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] + object_mut: object_mut::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: object_boxed::>, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: object_reallocate_boxed::>, + object_downcast: context_chain_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_chain_downcast_mut::, + object_drop_rest: context_chain_drop_rest::, + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: context_backtrace::, + }; + + // As the cause is anyhow::Error, we already have a backtrace for it. + let backtrace = None; + + // Safety: passing vtable that operates on the right type. + unsafe { Error::construct(error, vtable, backtrace) } + } + + /// Get the backtrace for this Error. + /// + /// In order for the backtrace to be meaningful, one of the two environment + /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined + /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat + /// expensive to capture in Rust, so we don't necessarily want to be + /// capturing them all over the place all the time. + /// + /// - If you want panics and errors to both have backtraces, set + /// `RUST_BACKTRACE=1`; + /// - If you want only errors to have backtraces, set + /// `RUST_LIB_BACKTRACE=1`; + /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and + /// `RUST_LIB_BACKTRACE=0`. + /// + /// # Stability + /// + /// Standard library backtraces are only available when using Rust ≥ + /// 1.65. On older compilers, this function is only available if the crate's + /// "backtrace" feature is enabled, and will use the `backtrace` crate as + /// the underlying backtrace implementation. The return type of this + /// function on old compilers is `&(impl Debug + Display)`. + /// + /// ```toml + /// [dependencies] + /// anyhow = { version = "1.0", features = ["backtrace"] } + /// ``` + #[cfg(any(std_backtrace, feature = "backtrace"))] + pub fn backtrace(&self) -> &impl_backtrace!() { + unsafe { ErrorImpl::backtrace(self.inner.by_ref()) } + } + + /// An iterator of the chain of source errors contained by this Error. + /// + /// This iterator will visit every error in the cause chain of this error + /// object, beginning with the error that this error object was created + /// from. + /// + /// # Example + /// + /// ``` + /// use anyhow::Error; + /// use std::io; + /// + /// pub fn underlying_io_error_kind(error: &Error) -> Option { + /// for cause in error.chain() { + /// if let Some(io_error) = cause.downcast_ref::() { + /// return Some(io_error.kind()); + /// } + /// } + /// None + /// } + /// ``` + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[cold] + pub fn chain(&self) -> Chain { + unsafe { ErrorImpl::chain(self.inner.by_ref()) } + } + + /// The lowest level cause of this error — this error's cause's + /// cause's cause etc. + /// + /// The root cause is the last error in the iterator produced by + /// [`chain()`][Error::chain]. + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[allow(clippy::double_ended_iterator_last)] + pub fn root_cause(&self) -> &(dyn StdError + 'static) { + self.chain().last().unwrap() + } + + /// Returns true if `E` is the type held by this error object. + /// + /// For errors with context, this method returns true if `E` matches the + /// type of the context `C` **or** the type of the error on which the + /// context has been attached. For details about the interaction between + /// context and downcasting, [see here]. + /// + /// [see here]: crate::Context#effect-on-downcasting + pub fn is(&self) -> bool + where + E: Display + Debug + Send + Sync + 'static, + { + self.downcast_ref::().is_some() + } + + /// Attempt to downcast the error object to a concrete type. + pub fn downcast(mut self) -> Result + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::(); + let inner = self.inner.by_mut(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { + Some(addr) => addr.by_mut().extend(), + None => return Err(self), + }; + #[cfg(anyhow_no_ptr_addr_of)] + let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) { + Some(addr) => addr.extend(), + None => return Err(self), + }; + + // Prepare to read E out of the data structure. We'll drop the rest + // of the data structure separately so that E is not dropped. + let outer = ManuallyDrop::new(self); + + // Read E from where the vtable found it. + let error = addr.cast::().read(); + + // Drop rest of the data structure outside of E. + (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target); + + Ok(error) + } + } + + /// Downcast this error object by reference. + /// + /// # Example + /// + /// ``` + /// # use anyhow::anyhow; + /// # use std::fmt::{self, Display}; + /// # use std::task::Poll; + /// # + /// # #[derive(Debug)] + /// # enum DataStoreError { + /// # Censored(()), + /// # } + /// # + /// # impl Display for DataStoreError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # impl std::error::Error for DataStoreError {} + /// # + /// # const REDACTED_CONTENT: () = (); + /// # + /// # let error = anyhow!("..."); + /// # let root_cause = &error; + /// # + /// # let ret = + /// // If the error was caused by redaction, then return a tombstone instead + /// // of the content. + /// match root_cause.downcast_ref::() { + /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), + /// None => Err(error), + /// } + /// # ; + /// ``` + pub fn downcast_ref(&self) -> Option<&E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?; + Some(addr.cast::().deref()) + } + } + + /// Downcast this error object by mutable reference. + pub fn downcast_mut(&mut self) -> Option<&mut E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = + (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?; + + Some(addr.cast::().deref_mut()) + } + } + + /// Convert to a standard library error trait object. + /// + /// This is implemented as a cheap pointer cast that does not allocate or + /// deallocate memory. Like [`anyhow::Error::from_boxed`], it's useful for + /// interop with other error libraries. + /// + /// The same conversion is also available as + /// impl From<anyhow::Error> + /// for Box<dyn Error + Send + Sync + 'static>. + /// + /// If a backtrace was collected during construction of the `anyhow::Error`, + /// that backtrace remains accessible using the standard library `Error` + /// trait's provider API, but as a consequence, the resulting boxed error + /// can no longer be downcast to its original underlying type. + /// + /// ``` + #[cfg_attr(not(error_generic_member_access), doc = "# _ = stringify! {")] + /// #![feature(error_generic_member_access)] + /// + /// use anyhow::anyhow; + /// use std::backtrace::Backtrace; + /// use thiserror::Error; + /// + /// #[derive(Error, Debug)] + /// #[error("...")] + /// struct MyError; + /// + /// let anyhow_error = anyhow!(MyError); + /// println!("{}", anyhow_error.backtrace()); // has Backtrace + /// assert!(anyhow_error.downcast_ref::().is_some()); // can downcast + /// + /// let boxed_dyn_error = anyhow_error.into_boxed_dyn_error(); + /// assert!(std::error::request_ref::(&*boxed_dyn_error).is_some()); // has Backtrace + /// assert!(boxed_dyn_error.downcast_ref::().is_none()); // can no longer downcast + #[cfg_attr(not(error_generic_member_access), doc = "# };")] + /// ``` + /// + /// [`anyhow::Error::from_boxed`]: Self::from_boxed + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[must_use] + pub fn into_boxed_dyn_error(self) -> Box { + let outer = ManuallyDrop::new(self); + unsafe { + // Use vtable to attach ErrorImpl's native StdError vtable for + // the right original type E. + (vtable(outer.inner.ptr).object_boxed)(outer.inner) + } + } + + /// Convert to a standard library error trait object. + /// + /// Unlike `self.into_boxed_dyn_error()`, this method relocates the + /// underlying error into a new allocation in order to make it downcastable + /// to `&E` or `Box` for its original underlying error type. Any + /// backtrace collected during construction of the `anyhow::Error` is + /// discarded. + /// + /// ``` + #[cfg_attr(not(error_generic_member_access), doc = "# _ = stringify!{")] + /// #![feature(error_generic_member_access)] + /// + /// use anyhow::anyhow; + /// use std::backtrace::Backtrace; + /// use thiserror::Error; + /// + /// #[derive(Error, Debug)] + /// #[error("...")] + /// struct MyError; + /// + /// let anyhow_error = anyhow!(MyError); + /// println!("{}", anyhow_error.backtrace()); // has Backtrace + /// assert!(anyhow_error.downcast_ref::().is_some()); // can downcast + /// + /// let boxed_dyn_error = anyhow_error.reallocate_into_boxed_dyn_error_without_backtrace(); + /// assert!(std::error::request_ref::(&*boxed_dyn_error).is_none()); // Backtrace lost + /// assert!(boxed_dyn_error.downcast_ref::().is_some()); // can downcast to &MyError + /// assert!(boxed_dyn_error.downcast::().is_ok()); // can downcast to Box + #[cfg_attr(not(error_generic_member_access), doc = "# };")] + /// ``` + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[must_use] + pub fn reallocate_into_boxed_dyn_error_without_backtrace( + self, + ) -> Box { + let outer = ManuallyDrop::new(self); + unsafe { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + (vtable(outer.inner.ptr).object_reallocate_boxed)(outer.inner) + } + } + + #[cfg(error_generic_member_access)] + pub(crate) fn provide<'a>(&'a self, request: &mut Request<'a>) { + unsafe { ErrorImpl::provide(self.inner.by_ref(), request) } + } + + // Called by thiserror when you have `#[source] anyhow::Error`. This provide + // implementation includes the anyhow::Error's Backtrace if any, unlike + // deref'ing to dyn Error where the provide implementation would include + // only the original error's Backtrace from before it got wrapped into an + // anyhow::Error. + #[cfg(error_generic_member_access)] + #[doc(hidden)] + pub fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { + Self::provide(self, request); + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl From for Error +where + E: StdError + Send + Sync + 'static, +{ + #[cold] + fn from(error: E) -> Self { + let backtrace = backtrace_if_absent!(&error); + Error::construct_from_std(error, backtrace) + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl Deref for Error { + type Target = dyn StdError + Send + Sync + 'static; + + fn deref(&self) -> &Self::Target { + unsafe { ErrorImpl::error(self.inner.by_ref()) } + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl DerefMut for Error { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { ErrorImpl::error_mut(self.inner.by_mut()) } + } +} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) } + } +} + +impl Debug for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) } + } +} + +impl Drop for Error { + fn drop(&mut self) { + unsafe { + // Invoke the vtable's drop behavior. + (vtable(self.inner.ptr).object_drop)(self.inner); + } + } +} + +struct ErrorVTable { + object_drop: unsafe fn(Own), + object_ref: unsafe fn(Ref) -> Ref, + #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] + object_mut: unsafe fn(Mut) -> &mut (dyn StdError + Send + Sync + 'static), + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_boxed: unsafe fn(Own) -> Box, + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + object_reallocate_boxed: unsafe fn(Own) -> Box, + object_downcast: unsafe fn(Ref, TypeId) -> Option>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: unsafe fn(Mut, TypeId) -> Option>, + object_drop_rest: unsafe fn(Own, TypeId), + #[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") + ))] + object_backtrace: unsafe fn(Ref) -> Option<&Backtrace>, +} + +// Safety: requires layout of *e to match ErrorImpl. +unsafe fn object_drop(e: Own) { + // Cast back to ErrorImpl so that the allocator receives the correct + // Layout to deallocate the Box's memory. + let unerased_own = e.cast::>(); + drop(unsafe { unerased_own.boxed() }); +} + +// Safety: requires layout of *e to match ErrorImpl. +unsafe fn object_drop_front(e: Own, target: TypeId) { + // Drop the fields of ErrorImpl other than E as well as the Box allocation, + // without dropping E itself. This is used by downcast after doing a + // ptr::read to take ownership of the E. + let _ = target; + let unerased_own = e.cast::>>(); + drop(unsafe { unerased_own.boxed() }); +} + +// Safety: requires layout of *e to match ErrorImpl. +unsafe fn object_ref(e: Ref) -> Ref +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + + let unerased_ref = e.cast::>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Ref::from_raw(unsafe { + NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) + }); + + #[cfg(anyhow_no_ptr_addr_of)] + return Ref::new(unsafe { &unerased_ref.deref()._object }); +} + +// Safety: requires layout of *e to match ErrorImpl, and for `e` to be derived +// from a `&mut` +#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] +unsafe fn object_mut(e: Mut) -> &mut (dyn StdError + Send + Sync + 'static) +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + let unerased_mut = e.cast::>(); + unsafe { &mut unerased_mut.deref_mut()._object } +} + +// Safety: requires layout of *e to match ErrorImpl. +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +unsafe fn object_boxed(e: Own) -> Box +where + E: StdError + Send + Sync + 'static, +{ + // Attach ErrorImpl's native StdError vtable. The StdError impl is below. + let unerased_own = e.cast::>(); + unsafe { unerased_own.boxed() } +} + +// Safety: requires layout of *e to match ErrorImpl. +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +unsafe fn object_reallocate_boxed(e: Own) -> Box +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable. + let unerased_own = e.cast::>(); + Box::new(unsafe { unerased_own.boxed() }._object) +} + +// Safety: requires layout of *e to match ErrorImpl. +unsafe fn object_downcast(e: Ref, target: TypeId) -> Option> +where + E: 'static, +{ + if TypeId::of::() == target { + // Caller is looking for an E pointer and e is ErrorImpl, take a + // pointer to its E field. + + let unerased_ref = e.cast::>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Some( + Ref::from_raw(unsafe { + NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) + }) + .cast::<()>(), + ); + + #[cfg(anyhow_no_ptr_addr_of)] + return Some(Ref::new(unsafe { &unerased_ref.deref()._object }).cast::<()>()); + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl. +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn object_downcast_mut(e: Mut, target: TypeId) -> Option> +where + E: 'static, +{ + if TypeId::of::() == target { + // Caller is looking for an E pointer and e is ErrorImpl, take a + // pointer to its E field. + let unerased_mut = e.cast::>(); + let unerased = unsafe { unerased_mut.deref_mut() }; + Some(Mut::new(&mut unerased._object).cast::<()>()) + } else { + None + } +} + +#[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") +))] +fn no_backtrace(e: Ref) -> Option<&Backtrace> { + let _ = e; + None +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +unsafe fn context_downcast(e: Ref, target: TypeId) -> Option> +where + C: 'static, + E: 'static, +{ + if TypeId::of::() == target { + let unerased_ref = e.cast::>>(); + let unerased = unsafe { unerased_ref.deref() }; + Some(Ref::new(&unerased._object.context).cast::<()>()) + } else if TypeId::of::() == target { + let unerased_ref = e.cast::>>(); + let unerased = unsafe { unerased_ref.deref() }; + Some(Ref::new(&unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] +unsafe fn context_downcast_mut(e: Mut, target: TypeId) -> Option> +where + C: 'static, + E: 'static, +{ + if TypeId::of::() == target { + let unerased_mut = e.cast::>>(); + let unerased = unsafe { unerased_mut.deref_mut() }; + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else if TypeId::of::() == target { + let unerased_mut = e.cast::>>(); + let unerased = unsafe { unerased_mut.deref_mut() }; + Some(Mut::new(&mut unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +unsafe fn context_drop_rest(e: Own, target: TypeId) +where + C: 'static, + E: 'static, +{ + // Called after downcasting by value to either the C or the E and doing a + // ptr::read to take ownership of that value. + if TypeId::of::() == target { + let unerased_own = e.cast::, E>>>(); + drop(unsafe { unerased_own.boxed() }); + } else { + let unerased_own = e.cast::>>>(); + drop(unsafe { unerased_own.boxed() }); + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +unsafe fn context_chain_downcast(e: Ref, target: TypeId) -> Option> +where + C: 'static, +{ + let unerased_ref = e.cast::>>(); + let unerased = unsafe { unerased_ref.deref() }; + if TypeId::of::() == target { + Some(Ref::new(&unerased._object.context).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &unerased._object.error; + unsafe { (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) } + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn context_chain_downcast_mut(e: Mut, target: TypeId) -> Option> +where + C: 'static, +{ + let unerased_mut = e.cast::>>(); + let unerased = unsafe { unerased_mut.deref_mut() }; + if TypeId::of::() == target { + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &mut unerased._object.error; + unsafe { (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target) } + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +unsafe fn context_chain_drop_rest(e: Own, target: TypeId) +where + C: 'static, +{ + // Called after downcasting by value to either the C or one of the causes + // and doing a ptr::read to take ownership of that value. + if TypeId::of::() == target { + let unerased_own = e.cast::, Error>>>(); + // Drop the entire rest of the data structure rooted in the next Error. + drop(unsafe { unerased_own.boxed() }); + } else { + let unerased_own = e.cast::>>>(); + let unerased = unsafe { unerased_own.boxed() }; + // Read the Own from the next error. + let inner = unerased._object.error.inner; + drop(unerased); + let vtable = unsafe { vtable(inner.ptr) }; + // Recursively drop the next error using the same target typeid. + unsafe { (vtable.object_drop_rest)(inner, target) }; + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(all( + not(error_generic_member_access), + any(std_backtrace, feature = "backtrace") +))] +#[allow(clippy::unnecessary_wraps)] +unsafe fn context_backtrace(e: Ref) -> Option<&Backtrace> +where + C: 'static, +{ + let unerased_ref = e.cast::>>(); + let unerased = unsafe { unerased_ref.deref() }; + let backtrace = unsafe { ErrorImpl::backtrace(unerased._object.error.inner.by_ref()) }; + Some(backtrace) +} + +// NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor +// of raw pointers and `NonNull`. +// repr C to ensure that E remains in the final position. +#[repr(C)] +pub(crate) struct ErrorImpl { + vtable: &'static ErrorVTable, + backtrace: Option, + // NOTE: Don't use directly. Use only through vtable. Erased type may have + // different alignment. + _object: E, +} + +// Reads the vtable out of `p`. This is the same as `p.as_ref().vtable`, but +// avoids converting `p` into a reference. +unsafe fn vtable(p: NonNull) -> &'static ErrorVTable { + // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl. + unsafe { *(p.as_ptr() as *const &'static ErrorVTable) } +} + +// repr C to ensure that ContextError has the same layout as +// ContextError, E> and ContextError>. +#[repr(C)] +pub(crate) struct ContextError { + pub context: C, + pub error: E, +} + +impl ErrorImpl { + fn erase(&self) -> Ref { + // Erase the concrete type of E but preserve the vtable in self.vtable + // for manipulating the resulting thin pointer. This is analogous to an + // unsize coercion. + Ref::new(self).cast::() + } +} + +impl ErrorImpl { + pub(crate) unsafe fn error(this: Ref) -> &(dyn StdError + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + unsafe { (vtable(this.ptr).object_ref)(this).deref() } + } + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + pub(crate) unsafe fn error_mut(this: Mut) -> &mut (dyn StdError + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + + #[cfg(not(anyhow_no_ptr_addr_of))] + return unsafe { + (vtable(this.ptr).object_ref)(this.by_ref()) + .by_mut() + .deref_mut() + }; + + #[cfg(anyhow_no_ptr_addr_of)] + return unsafe { (vtable(this.ptr).object_mut)(this) }; + } + + #[cfg(any(std_backtrace, feature = "backtrace"))] + pub(crate) unsafe fn backtrace(this: Ref) -> &Backtrace { + // This unwrap can only panic if the underlying error's backtrace method + // is nondeterministic, which would only happen in maliciously + // constructed code. + unsafe { this.deref() } + .backtrace + .as_ref() + .or_else(|| { + #[cfg(error_generic_member_access)] + return nightly::request_ref_backtrace(unsafe { Self::error(this) }); + #[cfg(not(error_generic_member_access))] + return unsafe { (vtable(this.ptr).object_backtrace)(this) }; + }) + .expect("backtrace capture failed") + } + + #[cfg(error_generic_member_access)] + unsafe fn provide<'a>(this: Ref<'a, Self>, request: &mut Request<'a>) { + if let Some(backtrace) = unsafe { &this.deref().backtrace } { + nightly::provide_ref_backtrace(request, backtrace); + } + nightly::provide(unsafe { Self::error(this) }, request); + } + + #[cold] + pub(crate) unsafe fn chain(this: Ref) -> Chain { + Chain::new(unsafe { Self::error(this) }) + } +} + +impl StdError for ErrorImpl +where + E: StdError, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + unsafe { ErrorImpl::error(self.erase()).source() } + } + + #[cfg(error_generic_member_access)] + fn provide<'a>(&'a self, request: &mut Request<'a>) { + unsafe { ErrorImpl::provide(self.erase(), request) } + } +} + +impl Debug for ErrorImpl +where + E: Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::debug(self.erase(), formatter) } + } +} + +impl Display for ErrorImpl +where + E: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) } + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl From for Box { + #[cold] + fn from(error: Error) -> Self { + error.into_boxed_dyn_error() + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl From for Box { + #[cold] + fn from(error: Error) -> Self { + error.into_boxed_dyn_error() + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl From for Box { + #[cold] + fn from(error: Error) -> Self { + error.into_boxed_dyn_error() + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl AsRef for Error { + fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) { + &**self + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl AsRef for Error { + fn as_ref(&self) -> &(dyn StdError + 'static) { + &**self + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_unwind_safe)))] +impl UnwindSafe for Error {} + +#[cfg(any(feature = "std", not(anyhow_no_core_unwind_safe)))] +impl RefUnwindSafe for Error {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,158 @@ +use crate::chain::Chain; +use crate::error::ErrorImpl; +use crate::ptr::Ref; +use core::fmt::{self, Debug, Write}; + +impl ErrorImpl { + pub(crate) unsafe fn display(this: Ref, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", unsafe { Self::error(this) })?; + + if f.alternate() { + let chain = unsafe { Self::chain(this) }; + for cause in chain.skip(1) { + write!(f, ": {}", cause)?; + } + } + + Ok(()) + } + + pub(crate) unsafe fn debug(this: Ref, f: &mut fmt::Formatter) -> fmt::Result { + let error = unsafe { Self::error(this) }; + + if f.alternate() { + return Debug::fmt(error, f); + } + + write!(f, "{}", error)?; + + if let Some(cause) = error.source() { + write!(f, "\n\nCaused by:")?; + let multiple = cause.source().is_some(); + for (n, error) in Chain::new(cause).enumerate() { + writeln!(f)?; + let mut indented = Indented { + inner: f, + number: if multiple { Some(n) } else { None }, + started: false, + }; + write!(indented, "{}", error)?; + } + } + + #[cfg(any(std_backtrace, feature = "backtrace"))] + { + use crate::backtrace::BacktraceStatus; + use alloc::string::ToString; + + let backtrace = unsafe { Self::backtrace(this) }; + if let BacktraceStatus::Captured = backtrace.status() { + let mut backtrace = backtrace.to_string(); + write!(f, "\n\n")?; + if backtrace.starts_with("stack backtrace:") { + // Capitalize to match "Caused by:" + backtrace.replace_range(0..1, "S"); + } else { + // "stack backtrace:" prefix was removed in + // https://github.com/rust-lang/backtrace-rs/pull/286 + writeln!(f, "Stack backtrace:")?; + } + backtrace.truncate(backtrace.trim_end().len()); + write!(f, "{}", backtrace)?; + } + } + + Ok(()) + } +} + +struct Indented<'a, D> { + inner: &'a mut D, + number: Option, + started: bool, +} + +impl Write for Indented<'_, T> +where + T: Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for (i, line) in s.split('\n').enumerate() { + if !self.started { + self.started = true; + match self.number { + Some(number) => write!(self.inner, "{: >5}: ", number)?, + None => self.inner.write_str(" ")?, + } + } else if i > 0 { + self.inner.write_char('\n')?; + if self.number.is_some() { + self.inner.write_str(" ")?; + } else { + self.inner.write_str(" ")?; + } + } + + self.inner.write_str(line)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::string::String; + + #[test] + fn one_digit() { + let input = "verify\nthis"; + let expected = " 2: verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: Some(2), + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn two_digits() { + let input = "verify\nthis"; + let expected = " 12: verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: Some(12), + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn no_digits() { + let input = "verify\nthis"; + let expected = " verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: None, + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/kind.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/kind.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/kind.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/kind.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +// Tagged dispatch mechanism for resolving the behavior of `anyhow!($expr)`. +// +// When anyhow! is given a single expr argument to turn into anyhow::Error, we +// want the resulting Error to pick up the input's implementation of source() +// and backtrace() if it has a std::error::Error impl, otherwise require nothing +// more than Display and Debug. +// +// Expressed in terms of specialization, we want something like: +// +// trait AnyhowNew { +// fn new(self) -> Error; +// } +// +// impl AnyhowNew for T +// where +// T: Display + Debug + Send + Sync + 'static, +// { +// default fn new(self) -> Error { +// /* no std error impl */ +// } +// } +// +// impl AnyhowNew for T +// where +// T: std::error::Error + Send + Sync + 'static, +// { +// fn new(self) -> Error { +// /* use std error's source() and backtrace() */ +// } +// } +// +// Since specialization is not stable yet, instead we rely on autoref behavior +// of method resolution to perform tagged dispatch. Here we have two traits +// AdhocKind and TraitKind that both have an anyhow_kind() method. AdhocKind is +// implemented whether or not the caller's type has a std error impl, while +// TraitKind is implemented only when a std error impl does exist. The ambiguity +// is resolved by AdhocKind requiring an extra autoref so that it has lower +// precedence. +// +// The anyhow! macro will set up the call in this form: +// +// #[allow(unused_imports)] +// use $crate::__private::{AdhocKind, TraitKind}; +// let error = $msg; +// (&error).anyhow_kind().new(error) + +use crate::Error; +use core::fmt::{Debug, Display}; + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +use crate::StdError; +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +use alloc::boxed::Box; + +pub struct Adhoc; + +#[doc(hidden)] +pub trait AdhocKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Adhoc { + Adhoc + } +} + +impl AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {} + +impl Adhoc { + #[cold] + pub fn new(self, message: M) -> Error + where + M: Display + Debug + Send + Sync + 'static, + { + Error::construct_from_adhoc(message, backtrace!()) + } +} + +pub struct Trait; + +#[doc(hidden)] +pub trait TraitKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Trait { + Trait + } +} + +impl TraitKind for E where E: Into {} + +impl Trait { + #[cold] + pub fn new(self, error: E) -> Error + where + E: Into, + { + error.into() + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +pub struct Boxed; + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +#[doc(hidden)] +pub trait BoxedKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Boxed { + Boxed + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl BoxedKind for Box {} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl Boxed { + #[cold] + pub fn new(self, error: Box) -> Error { + let backtrace = backtrace_if_absent!(&*error); + Error::construct_from_boxed(error, backtrace) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,736 @@ +//! [![github]](https://github.com/dtolnay/anyhow) [![crates-io]](https://crates.io/crates/anyhow) [![docs-rs]](https://docs.rs/anyhow) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//!
+//! +//! This library provides [`anyhow::Error`][Error], a trait object based error +//! type for easy idiomatic error handling in Rust applications. +//! +//!
+//! +//! # Details +//! +//! - Use `Result`, or equivalently `anyhow::Result`, as +//! the return type of any fallible function. +//! +//! Within the function, use `?` to easily propagate any error that implements +//! the [`std::error::Error`] trait. +//! +//! ``` +//! # pub trait Deserialize {} +//! # +//! # mod serde_json { +//! # use super::Deserialize; +//! # use std::io; +//! # +//! # pub fn from_str(json: &str) -> io::Result { +//! # unimplemented!() +//! # } +//! # } +//! # +//! # struct ClusterMap; +//! # +//! # impl Deserialize for ClusterMap {} +//! # +//! use anyhow::Result; +//! +//! fn get_cluster_info() -> Result { +//! let config = std::fs::read_to_string("cluster.json")?; +//! let map: ClusterMap = serde_json::from_str(&config)?; +//! Ok(map) +//! } +//! # +//! # fn main() {} +//! ``` +//! +//! - Attach context to help the person troubleshooting the error understand +//! where things went wrong. A low-level error like "No such file or +//! directory" can be annoying to debug without more context about what higher +//! level step the application was in the middle of. +//! +//! ``` +//! # struct It; +//! # +//! # impl It { +//! # fn detach(&self) -> Result<()> { +//! # unimplemented!() +//! # } +//! # } +//! # +//! use anyhow::{Context, Result}; +//! +//! fn main() -> Result<()> { +//! # return Ok(()); +//! # +//! # const _: &str = stringify! { +//! ... +//! # }; +//! # +//! # let it = It; +//! # let path = "./path/to/instrs.json"; +//! # +//! it.detach().context("Failed to detach the important thing")?; +//! +//! let content = std::fs::read(path) +//! .with_context(|| format!("Failed to read instrs from {}", path))?; +//! # +//! # const _: &str = stringify! { +//! ... +//! # }; +//! # +//! # Ok(()) +//! } +//! ``` +//! +//! ```console +//! Error: Failed to read instrs from ./path/to/instrs.json +//! +//! Caused by: +//! No such file or directory (os error 2) +//! ``` +//! +//! - Downcasting is supported and can be by value, by shared reference, or by +//! mutable reference as needed. +//! +//! ``` +//! # use anyhow::anyhow; +//! # use std::fmt::{self, Display}; +//! # use std::task::Poll; +//! # +//! # #[derive(Debug)] +//! # enum DataStoreError { +//! # Censored(()), +//! # } +//! # +//! # impl Display for DataStoreError { +//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +//! # unimplemented!() +//! # } +//! # } +//! # +//! # impl std::error::Error for DataStoreError {} +//! # +//! # const REDACTED_CONTENT: () = (); +//! # +//! # let error = anyhow!("..."); +//! # let root_cause = &error; +//! # +//! # let ret = +//! // If the error was caused by redaction, then return a +//! // tombstone instead of the content. +//! match root_cause.downcast_ref::() { +//! Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), +//! None => Err(error), +//! } +//! # ; +//! ``` +//! +//! - If using Rust ≥ 1.65, a backtrace is captured and printed with the +//! error if the underlying error type does not already provide its own. In +//! order to see backtraces, they must be enabled through the environment +//! variables described in [`std::backtrace`]: +//! +//! - If you want panics and errors to both have backtraces, set +//! `RUST_BACKTRACE=1`; +//! - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`; +//! - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and +//! `RUST_LIB_BACKTRACE=0`. +//! +//! [`std::backtrace`]: std::backtrace#environment-variables +//! +//! - Anyhow works with any error type that has an impl of `std::error::Error`, +//! including ones defined in your crate. We do not bundle a `derive(Error)` +//! macro but you can write the impls yourself or use a standalone macro like +//! [thiserror]. +//! +//! [thiserror]: https://github.com/dtolnay/thiserror +//! +//! ``` +//! use thiserror::Error; +//! +//! #[derive(Error, Debug)] +//! pub enum FormatError { +//! #[error("Invalid header (expected {expected:?}, got {found:?})")] +//! InvalidHeader { +//! expected: String, +//! found: String, +//! }, +//! #[error("Missing attribute: {0}")] +//! MissingAttribute(String), +//! } +//! ``` +//! +//! - One-off error messages can be constructed using the `anyhow!` macro, which +//! supports string interpolation and produces an `anyhow::Error`. +//! +//! ``` +//! # use anyhow::{anyhow, Result}; +//! # +//! # fn demo() -> Result<()> { +//! # let missing = "..."; +//! return Err(anyhow!("Missing attribute: {}", missing)); +//! # Ok(()) +//! # } +//! ``` +//! +//! A `bail!` macro is provided as a shorthand for the same early return. +//! +//! ``` +//! # use anyhow::{bail, Result}; +//! # +//! # fn demo() -> Result<()> { +//! # let missing = "..."; +//! bail!("Missing attribute: {}", missing); +//! # Ok(()) +//! # } +//! ``` +//! +//!
+//! +//! # No-std support +//! +//! In no_std mode, almost all of the same API is available and works the same +//! way. To depend on Anyhow in no_std mode, disable our default enabled "std" +//! feature in Cargo.toml. A global allocator is required. +//! +//! ```toml +//! [dependencies] +//! anyhow = { version = "1.0", default-features = false } +//! ``` +//! +//! With versions of Rust older than 1.81, no_std mode may require an additional +//! `.map_err(Error::msg)` when working with a non-Anyhow error type inside a +//! function that returns Anyhow's error type, as the trait that `?`-based error +//! conversions are defined by is only available in std in those old versions. + +#![doc(html_root_url = "https://docs.rs/anyhow/1.0.100")] +#![cfg_attr(error_generic_member_access, feature(error_generic_member_access))] +#![no_std] +#![deny(dead_code, unused_imports, unused_mut)] +#![cfg_attr( + not(anyhow_no_unsafe_op_in_unsafe_fn_lint), + deny(unsafe_op_in_unsafe_fn) +)] +#![cfg_attr(anyhow_no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))] +#![allow( + clippy::doc_markdown, + clippy::elidable_lifetime_names, + clippy::enum_glob_use, + clippy::explicit_auto_deref, + clippy::extra_unused_type_parameters, + clippy::incompatible_msrv, + clippy::let_underscore_untyped, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_doctest_main, + clippy::needless_lifetimes, + clippy::new_ret_no_self, + clippy::redundant_else, + clippy::return_self_not_must_use, + clippy::struct_field_names, + clippy::unused_self, + clippy::used_underscore_binding, + clippy::wildcard_imports, + clippy::wrong_self_convention +)] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] + +#[cfg(all( + anyhow_nightly_testing, + feature = "std", + not(error_generic_member_access) +))] +compile_error!("Build script probe failed to compile."); + +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[macro_use] +mod backtrace; +mod chain; +mod context; +mod ensure; +mod error; +mod fmt; +mod kind; +mod macros; +#[cfg(error_generic_member_access)] +mod nightly; +mod ptr; +mod wrapper; + +use crate::error::ErrorImpl; +use crate::ptr::Own; +use core::fmt::Display; + +#[cfg(all(not(feature = "std"), anyhow_no_core_error))] +use core::fmt::Debug; + +#[cfg(feature = "std")] +use std::error::Error as StdError; + +#[cfg(not(any(feature = "std", anyhow_no_core_error)))] +use core::error::Error as StdError; + +#[cfg(all(not(feature = "std"), anyhow_no_core_error))] +trait StdError: Debug + Display { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + None + } +} + +#[doc(no_inline)] +pub use anyhow as format_err; + +/// The `Error` type, a wrapper around a dynamic error type. +/// +/// `Error` works a lot like `Box`, but with these +/// differences: +/// +/// - `Error` requires that the error is `Send`, `Sync`, and `'static`. +/// - `Error` guarantees that a backtrace is available, even if the underlying +/// error type does not provide one. +/// - `Error` is represented as a narrow pointer — exactly one word in +/// size instead of two. +/// +///
+/// +/// # Display representations +/// +/// When you print an error object using "{}" or to_string(), only the outermost +/// underlying error or context is printed, not any of the lower level causes. +/// This is exactly as if you had called the Display impl of the error from +/// which you constructed your anyhow::Error. +/// +/// ```console +/// Failed to read instrs from ./path/to/instrs.json +/// ``` +/// +/// To print causes as well using anyhow's default formatting of causes, use the +/// alternate selector "{:#}". +/// +/// ```console +/// Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2) +/// ``` +/// +/// The Debug format "{:?}" includes your backtrace if one was captured. Note +/// that this is the representation you get by default if you return an error +/// from `fn main` instead of printing it explicitly yourself. +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// ``` +/// +/// and if there is a backtrace available: +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// +/// Stack backtrace: +/// 0: ::ext_context +/// at /git/anyhow/src/backtrace.rs:26 +/// 1: core::result::Result::map_err +/// at /git/rustc/src/libcore/result.rs:596 +/// 2: anyhow::context:: for core::result::Result>::with_context +/// at /git/anyhow/src/context.rs:58 +/// 3: testing::main +/// at src/main.rs:5 +/// 4: std::rt::lang_start +/// at /git/rustc/src/libstd/rt.rs:61 +/// 5: main +/// 6: __libc_start_main +/// 7: _start +/// ``` +/// +/// To see a conventional struct-style Debug representation, use "{:#?}". +/// +/// ```console +/// Error { +/// context: "Failed to read instrs from ./path/to/instrs.json", +/// source: Os { +/// code: 2, +/// kind: NotFound, +/// message: "No such file or directory", +/// }, +/// } +/// ``` +/// +/// If none of the built-in representations are appropriate and you would prefer +/// to render the error and its cause chain yourself, it can be done something +/// like this: +/// +/// ``` +/// use anyhow::{Context, Result}; +/// +/// fn main() { +/// if let Err(err) = try_main() { +/// eprintln!("ERROR: {}", err); +/// err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause)); +/// std::process::exit(1); +/// } +/// } +/// +/// fn try_main() -> Result<()> { +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # Ok(()) +/// } +/// ``` +#[repr(transparent)] +pub struct Error { + inner: Own, +} + +/// Iterator of a chain of source errors. +/// +/// This type is the iterator returned by [`Error::chain`]. +/// +/// # Example +/// +/// ``` +/// use anyhow::Error; +/// use std::io; +/// +/// pub fn underlying_io_error_kind(error: &Error) -> Option { +/// for cause in error.chain() { +/// if let Some(io_error) = cause.downcast_ref::() { +/// return Some(io_error.kind()); +/// } +/// } +/// None +/// } +/// ``` +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +#[derive(Clone)] +pub struct Chain<'a> { + state: crate::chain::ChainState<'a>, +} + +/// `Result` +/// +/// This is a reasonable return type to use throughout your application but also +/// for `fn main`; if you do, failures will be printed along with any +/// [context][Context] and a backtrace if one was captured. +/// +/// `anyhow::Result` may be used with one *or* two type parameters. +/// +/// ```rust +/// use anyhow::Result; +/// +/// # const IGNORE: &str = stringify! { +/// fn demo1() -> Result {...} +/// // ^ equivalent to std::result::Result +/// +/// fn demo2() -> Result {...} +/// // ^ equivalent to std::result::Result +/// # }; +/// ``` +/// +/// # Example +/// +/// ``` +/// # pub trait Deserialize {} +/// # +/// # mod serde_json { +/// # use super::Deserialize; +/// # use std::io; +/// # +/// # pub fn from_str(json: &str) -> io::Result { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # #[derive(Debug)] +/// # struct ClusterMap; +/// # +/// # impl Deserialize for ClusterMap {} +/// # +/// use anyhow::Result; +/// +/// fn main() -> Result<()> { +/// # return Ok(()); +/// let config = std::fs::read_to_string("cluster.json")?; +/// let map: ClusterMap = serde_json::from_str(&config)?; +/// println!("cluster info: {:#?}", map); +/// Ok(()) +/// } +/// ``` +pub type Result = core::result::Result; + +/// Provides the `context` method for `Result`. +/// +/// This trait is sealed and cannot be implemented for types outside of +/// `anyhow`. +/// +///
+/// +/// # Example +/// +/// ``` +/// use anyhow::{Context, Result}; +/// use std::fs; +/// use std::path::PathBuf; +/// +/// pub struct ImportantThing { +/// path: PathBuf, +/// } +/// +/// impl ImportantThing { +/// # const IGNORE: &'static str = stringify! { +/// pub fn detach(&mut self) -> Result<()> {...} +/// # }; +/// # fn detach(&mut self) -> Result<()> { +/// # unimplemented!() +/// # } +/// } +/// +/// pub fn do_it(mut it: ImportantThing) -> Result> { +/// it.detach().context("Failed to detach the important thing")?; +/// +/// let path = &it.path; +/// let content = fs::read(path) +/// .with_context(|| format!("Failed to read instrs from {}", path.display()))?; +/// +/// Ok(content) +/// } +/// ``` +/// +/// When printed, the outermost context would be printed first and the lower +/// level underlying causes would be enumerated below. +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// ``` +/// +/// Refer to the [Display representations] documentation for other forms in +/// which this context chain can be rendered. +/// +/// [Display representations]: Error#display-representations +/// +///
+/// +/// # Effect on downcasting +/// +/// After attaching context of type `C` onto an error of type `E`, the resulting +/// `anyhow::Error` may be downcast to `C` **or** to `E`. +/// +/// That is, in codebases that rely on downcasting, Anyhow's context supports +/// both of the following use cases: +/// +/// - **Attaching context whose type is insignificant onto errors whose type +/// is used in downcasts.** +/// +/// In other error libraries whose context is not designed this way, it can +/// be risky to introduce context to existing code because new context might +/// break existing working downcasts. In Anyhow, any downcast that worked +/// before adding context will continue to work after you add a context, so +/// you should freely add human-readable context to errors wherever it would +/// be helpful. +/// +/// ``` +/// # use anyhow::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct SuspiciousError; +/// # +/// # fn helper() -> Result<()> { +/// # bail!(SuspiciousError); +/// # } +/// # +/// use anyhow::{Context, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().context("Failed to complete the work")?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::() { +/// // If helper() returned SuspiciousError, this downcast will +/// // correctly succeed even with the context in between. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +/// +/// - **Attaching context whose type is used in downcasts onto errors whose +/// type is insignificant.** +/// +/// Some codebases prefer to use machine-readable context to categorize +/// lower level errors in a way that will be actionable to higher levels of +/// the application. +/// +/// ``` +/// # use anyhow::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct HelperFailed; +/// # +/// # fn helper() -> Result<()> { +/// # bail!("no such file or directory"); +/// # } +/// # +/// use anyhow::{Context, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().context(HelperFailed)?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::() { +/// // If helper failed, this downcast will succeed because +/// // HelperFailed is the context that has been attached to +/// // that error. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +pub trait Context: context::private::Sealed { + /// Wrap the error value with additional context. + fn context(self, context: C) -> Result + where + C: Display + Send + Sync + 'static; + + /// Wrap the error value with additional context that is evaluated lazily + /// only once an error does occur. + fn with_context(self, f: F) -> Result + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C; +} + +/// Equivalent to `Ok::<_, anyhow::Error>(value)`. +/// +/// This simplifies creation of an `anyhow::Result` in places where type +/// inference cannot deduce the `E` type of the result — without needing +/// to write`Ok::<_, anyhow::Error>(value)`. +/// +/// One might think that `anyhow::Result::Ok(value)` would work in such cases +/// but it does not. +/// +/// ```console +/// error[E0282]: type annotations needed for `std::result::Result` +/// --> src/main.rs:11:13 +/// | +/// 11 | let _ = anyhow::Result::Ok(1); +/// | - ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result` +/// | | +/// | consider giving this pattern the explicit type `std::result::Result`, where the type parameter `E` is specified +/// ``` +#[allow(non_snake_case)] +pub fn Ok(value: T) -> Result { + Result::Ok(value) +} + +// Not public API. Referenced by macro-generated code. +#[doc(hidden)] +pub mod __private { + use self::not::Bool; + use crate::Error; + use alloc::fmt; + use core::fmt::Arguments; + + #[doc(hidden)] + pub use crate::ensure::{BothDebug, NotBothDebug}; + #[doc(hidden)] + pub use alloc::format; + #[doc(hidden)] + pub use core::result::Result::Err; + #[doc(hidden)] + pub use core::{concat, format_args, stringify}; + + #[doc(hidden)] + pub mod kind { + #[doc(hidden)] + pub use crate::kind::{AdhocKind, TraitKind}; + + #[cfg(any(feature = "std", not(anyhow_no_core_error)))] + #[doc(hidden)] + pub use crate::kind::BoxedKind; + } + + #[doc(hidden)] + #[inline] + #[cold] + pub fn format_err(args: Arguments) -> Error { + #[cfg(anyhow_no_fmt_arguments_as_str)] + let fmt_arguments_as_str = None::<&str>; + #[cfg(not(anyhow_no_fmt_arguments_as_str))] + let fmt_arguments_as_str = args.as_str(); + + if let Some(message) = fmt_arguments_as_str { + // anyhow!("literal"), can downcast to &'static str + Error::msg(message) + } else { + // anyhow!("interpolate {var}"), can downcast to String + Error::msg(fmt::format(args)) + } + } + + #[doc(hidden)] + #[inline] + #[cold] + #[must_use] + pub fn must_use(error: Error) -> Error { + error + } + + #[doc(hidden)] + #[inline] + pub fn not(cond: impl Bool) -> bool { + cond.not() + } + + mod not { + #[doc(hidden)] + pub trait Bool { + fn not(self) -> bool; + } + + impl Bool for bool { + #[inline] + fn not(self) -> bool { + !self + } + } + + impl Bool for &bool { + #[inline] + fn not(self) -> bool { + !*self + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,245 @@ +/// Return early with an error. +/// +/// This macro is equivalent to +/// return Err([anyhow!($args\...)][anyhow!]). +/// +/// The surrounding function's or closure's return value is required to be +/// Result<_, [anyhow::Error][crate::Error]>. +/// +/// [anyhow!]: crate::anyhow +/// +/// # Example +/// +/// ``` +/// # use anyhow::{bail, Result}; +/// # +/// # fn has_permission(user: usize, resource: usize) -> bool { +/// # true +/// # } +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # let resource = 0; +/// # +/// if !has_permission(user, resource) { +/// bail!("permission denied for accessing {}", resource); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use anyhow::{bail, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # +/// if depth > MAX_DEPTH { +/// bail!(ScienceError::RecursionLimitExceeded); +/// } +/// # Ok(()) +/// # } +/// ``` +#[macro_export] +#[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)] +macro_rules! bail { + ($msg:literal $(,)?) => { + return $crate::__private::Err($crate::__anyhow!($msg)) + }; + ($err:expr $(,)?) => { + return $crate::__private::Err($crate::__anyhow!($err)) + }; + ($fmt:expr, $($arg:tt)*) => { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)) + }; +} + +macro_rules! __ensure { + ($ensure:item) => { + /// Return early with an error if a condition is not satisfied. + /// + /// This macro is equivalent to + /// if !$cond { return Err([anyhow!($args\...)][anyhow!]); }. + /// + /// The surrounding function's or closure's return value is required to be + /// Result<_, [anyhow::Error][crate::Error]>. + /// + /// Analogously to `assert!`, `ensure!` takes a condition and exits the function + /// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error` + /// rather than panicking. + /// + /// [anyhow!]: crate::anyhow + /// + /// # Example + /// + /// ``` + /// # use anyhow::{ensure, Result}; + /// # + /// # fn main() -> Result<()> { + /// # let user = 0; + /// # + /// ensure!(user == 0, "only user 0 is allowed"); + /// # Ok(()) + /// # } + /// ``` + /// + /// ``` + /// # use anyhow::{ensure, Result}; + /// # use thiserror::Error; + /// # + /// # const MAX_DEPTH: usize = 1; + /// # + /// #[derive(Error, Debug)] + /// enum ScienceError { + /// #[error("recursion limit exceeded")] + /// RecursionLimitExceeded, + /// # #[error("...")] + /// # More = (stringify! { + /// ... + /// # }, 1).1, + /// } + /// + /// # fn main() -> Result<()> { + /// # let depth = 0; + /// # + /// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded); + /// # Ok(()) + /// # } + /// ``` + $ensure + }; +} + +#[cfg(doc)] +__ensure![ + #[macro_export] + macro_rules! ensure { + ($cond:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::Error::msg( + $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`") + )); + } + }; + ($cond:expr, $msg:literal $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($msg)); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($err)); + } + }; + ($cond:expr, $fmt:expr, $($arg:tt)*) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)); + } + }; + } +]; + +#[cfg(not(doc))] +__ensure![ + #[macro_export] + #[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)] + macro_rules! ensure { + ($($tt:tt)*) => { + $crate::__parse_ensure!( + /* state */ 0 + /* stack */ () + /* bail */ ($($tt)*) + /* fuel */ (~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~) + /* parse */ {()} + /* dup */ ($($tt)*) + /* rest */ $($tt)* + ) + }; + } +]; + +/// Construct an ad-hoc error from a string or existing non-`anyhow` error +/// value. +/// +/// This evaluates to an [`Error`][crate::Error]. It can take either just a +/// string, or a format string with arguments. It also can take any custom type +/// which implements `Debug` and `Display`. +/// +/// If called with a single argument whose type implements `std::error::Error` +/// (in addition to `Debug` and `Display`, which are always required), then that +/// Error impl's `source` is preserved as the `source` of the resulting +/// `anyhow::Error`. +/// +/// # Example +/// +/// ``` +/// # type V = (); +/// # +/// use anyhow::{anyhow, Result}; +/// +/// fn lookup(key: &str) -> Result { +/// if key.len() != 16 { +/// return Err(anyhow!("key length must be 16 characters, got {:?}", key)); +/// } +/// +/// // ... +/// # Ok(()) +/// } +/// ``` +#[macro_export] +#[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)] +macro_rules! anyhow { + ($msg:literal $(,)?) => { + $crate::__private::must_use({ + let error = $crate::__private::format_err($crate::__private::format_args!($msg)); + error + }) + }; + ($err:expr $(,)?) => { + $crate::__private::must_use({ + use $crate::__private::kind::*; + let error = match $err { + error => (&error).anyhow_kind().new(error), + }; + error + }) + }; + ($fmt:expr, $($arg:tt)*) => { + $crate::Error::msg($crate::__private::format!($fmt, $($arg)*)) + }; +} + +// Not public API. This is used in the implementation of some of the other +// macros, in which the must_use call is not needed because the value is known +// to be used. +#[doc(hidden)] +#[macro_export] +macro_rules! __anyhow { + ($msg:literal $(,)?) => ({ + let error = $crate::__private::format_err($crate::__private::format_args!($msg)); + error + }); + ($err:expr $(,)?) => ({ + use $crate::__private::kind::*; + let error = match $err { + error => (&error).anyhow_kind().new(error), + }; + error + }); + ($fmt:expr, $($arg:tt)*) => { + $crate::Error::msg($crate::__private::format!($fmt, $($arg)*)) + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/nightly.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/nightly.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/nightly.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/nightly.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,58 @@ +// This code exercises the surface area that we expect of the Error generic +// member access API. If the current toolchain is able to compile it, then +// anyhow is able to provide backtrace support. + +#![cfg_attr(anyhow_build_probe, feature(error_generic_member_access))] + +use core::error::{self, Error}; +use std::backtrace::Backtrace; + +pub use core::error::Request; + +#[cfg(anyhow_build_probe)] +const _: () = { + use core::fmt::{self, Debug, Display}; + + struct MyError(Backtrace); + + impl Debug for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } + } + + impl Display for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } + } + + impl Error for MyError { + fn provide<'a>(&'a self, request: &mut Request<'a>) { + provide_ref_backtrace(request, &self.0); + } + } +}; + +// Include in sccache cache key. +#[cfg(anyhow_build_probe)] +const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); + +pub fn request_ref_backtrace(err: &dyn Error) -> Option<&Backtrace> { + request_ref::(err) +} + +fn request_ref<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<&'a T> +where + T: 'static + ?Sized, +{ + error::request_ref::(err) +} + +pub fn provide_ref_backtrace<'a>(request: &mut Request<'a>, backtrace: &'a Backtrace) { + Request::provide_ref(request, backtrace); +} + +pub fn provide<'a>(err: &'a (impl Error + ?Sized), request: &mut Request<'a>) { + Error::provide(err, request); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/ptr.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ptr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/ptr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/ptr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,199 @@ +use alloc::boxed::Box; +use core::marker::PhantomData; +use core::ptr::NonNull; + +#[repr(transparent)] +pub struct Own +where + T: ?Sized, +{ + pub ptr: NonNull, +} + +unsafe impl Send for Own where T: ?Sized {} + +unsafe impl Sync for Own where T: ?Sized {} + +impl Copy for Own where T: ?Sized {} + +impl Clone for Own +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Own +where + T: ?Sized, +{ + pub fn new(ptr: Box) -> Self { + Own { + ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, + } + } + + pub fn cast(self) -> Own { + Own { + ptr: self.ptr.cast(), + } + } + + pub unsafe fn boxed(self) -> Box { + unsafe { Box::from_raw(self.ptr.as_ptr()) } + } + + pub fn by_ref(&self) -> Ref { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn by_mut(&mut self) -> Mut { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } +} + +#[repr(transparent)] +pub struct Ref<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Ref<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Ref<'a, T> +where + T: ?Sized, +{ + pub fn new(ptr: &'a T) -> Self { + Ref { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn from_raw(ptr: NonNull) -> Self { + Ref { + ptr, + lifetime: PhantomData, + } + } + + pub fn cast(self) -> Ref<'a, U::Target> { + Ref { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_mut(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn as_ptr(self) -> *const T { + self.ptr.as_ptr() as *const T + } + + pub unsafe fn deref(self) -> &'a T { + unsafe { &*self.ptr.as_ptr() } + } +} + +#[repr(transparent)] +pub struct Mut<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull, + lifetime: PhantomData<&'a mut T>, +} + +impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Mut<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Mut<'a, T> +where + T: ?Sized, +{ + #[cfg(anyhow_no_ptr_addr_of)] + pub fn new(ptr: &'a mut T) -> Self { + Mut { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + pub fn cast(self) -> Mut<'a, U::Target> { + Mut { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_ref(self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn extend<'b>(self) -> Mut<'b, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub unsafe fn deref_mut(self) -> &'a mut T { + unsafe { &mut *self.ptr.as_ptr() } + } +} + +impl<'a, T> Mut<'a, T> { + pub unsafe fn read(self) -> T { + unsafe { self.ptr.as_ptr().read() } + } +} + +// Force turbofish on all calls of `.cast::()`. +pub trait CastTo { + type Target; +} + +impl CastTo for T { + type Target = T; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/wrapper.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/wrapper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/src/wrapper.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/src/wrapper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +use crate::StdError; +use core::fmt::{self, Debug, Display}; + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +use alloc::boxed::Box; + +#[cfg(error_generic_member_access)] +use crate::nightly::{self, Request}; + +#[repr(transparent)] +pub struct MessageError(pub M); + +impl Debug for MessageError +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +impl Display for MessageError +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl StdError for MessageError where M: Display + Debug + 'static {} + +#[repr(transparent)] +pub struct DisplayError(pub M); + +impl Debug for DisplayError +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl Display for DisplayError +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl StdError for DisplayError where M: Display + 'static {} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +#[repr(transparent)] +pub struct BoxedError(pub Box); + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl Debug for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl Display for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +#[cfg(any(feature = "std", not(anyhow_no_core_error)))] +impl StdError for BoxedError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.0.source() + } + + #[cfg(error_generic_member_access)] + fn provide<'a>(&'a self, request: &mut Request<'a>) { + nightly::provide(&*self.0, request); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/common/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/common/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/common/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/common/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +use anyhow::{bail, Result}; +use std::io; + +pub fn bail_literal() -> Result<()> { + bail!("oh no!"); +} + +pub fn bail_fmt() -> Result<()> { + bail!("{} {}!", "oh", "no"); +} + +pub fn bail_error() -> Result<()> { + bail!(io::Error::new(io::ErrorKind::Other, "oh no!")); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/compiletest.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/compiletest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/compiletest.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/compiletest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +#[rustversion::attr(not(nightly), ignore = "requires nightly")] +#[cfg_attr(miri, ignore = "incompatible with miri")] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/drop/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/drop/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/drop/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/drop/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +#![allow(clippy::module_name_repetitions)] + +use std::error::Error as StdError; +use std::fmt::{self, Display}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +#[derive(Debug)] +pub struct Flag { + atomic: Arc, +} + +impl Flag { + pub fn new() -> Self { + Flag { + atomic: Arc::new(AtomicBool::new(false)), + } + } + + pub fn get(&self) -> bool { + self.atomic.load(Ordering::Relaxed) + } +} + +#[derive(Debug)] +pub struct DetectDrop { + has_dropped: Flag, +} + +impl DetectDrop { + pub fn new(has_dropped: &Flag) -> Self { + DetectDrop { + has_dropped: Flag { + atomic: Arc::clone(&has_dropped.atomic), + }, + } + } +} + +impl StdError for DetectDrop {} + +impl Display for DetectDrop { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "oh no!") + } +} + +impl Drop for DetectDrop { + fn drop(&mut self) { + let already_dropped = self.has_dropped.atomic.swap(true, Ordering::Relaxed); + assert!(!already_dropped); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_autotrait.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_autotrait.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_autotrait.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_autotrait.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +#![allow(clippy::extra_unused_type_parameters)] + +use anyhow::Error; +use std::panic::{RefUnwindSafe, UnwindSafe}; + +#[test] +fn test_send() { + fn assert_send() {} + assert_send::(); +} + +#[test] +fn test_sync() { + fn assert_sync() {} + assert_sync::(); +} + +#[test] +fn test_unwind_safe() { + fn assert_unwind_safe() {} + assert_unwind_safe::(); +} + +#[test] +fn test_ref_unwind_safe() { + fn assert_ref_unwind_safe() {} + assert_ref_unwind_safe::(); +} + +#[test] +fn test_unpin() { + fn assert_unpin() {} + assert_unpin::(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_backtrace.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_backtrace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_backtrace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_backtrace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +#![allow(clippy::let_underscore_untyped)] + +#[rustversion::not(nightly)] +#[ignore = "requires nightly"] +#[test] +fn test_backtrace() {} + +#[rustversion::nightly] +#[test] +fn test_backtrace() { + use anyhow::anyhow; + + let error = anyhow!("oh no!"); + let _ = error.backtrace(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_boxed.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_boxed.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_boxed.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_boxed.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +#![allow( + // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422 + clippy::nonstandard_macro_braces, +)] + +use anyhow::anyhow; +use std::error::Error as StdError; +use std::io; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("outer")] +struct MyError { + source: io::Error, +} + +#[test] +fn test_boxed_str() { + let error = Box::::from("oh no!"); + let error = anyhow!(error); + assert_eq!("oh no!", error.to_string()); + assert_eq!( + "oh no!", + error + .downcast_ref::>() + .unwrap() + .to_string() + ); +} + +#[test] +fn test_boxed_thiserror() { + let error = MyError { + source: io::Error::new(io::ErrorKind::Other, "oh no!"), + }; + let error = anyhow!(error); + assert_eq!("oh no!", error.source().unwrap().to_string()); +} + +#[test] +fn test_boxed_anyhow() { + let error = anyhow!("oh no!").context("it failed"); + let error = anyhow!(error); + assert_eq!("oh no!", error.source().unwrap().to_string()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_chain.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_chain.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_chain.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_chain.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +use anyhow::{anyhow, Chain, Error}; + +fn error() -> Error { + anyhow!({ 0 }).context(1).context(2).context(3) +} + +#[test] +fn test_iter() { + let e = error(); + let mut chain = e.chain(); + assert_eq!("3", chain.next().unwrap().to_string()); + assert_eq!("2", chain.next().unwrap().to_string()); + assert_eq!("1", chain.next().unwrap().to_string()); + assert_eq!("0", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); + assert!(chain.next_back().is_none()); +} + +#[test] +fn test_rev() { + let e = error(); + let mut chain = e.chain().rev(); + assert_eq!("0", chain.next().unwrap().to_string()); + assert_eq!("1", chain.next().unwrap().to_string()); + assert_eq!("2", chain.next().unwrap().to_string()); + assert_eq!("3", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); + assert!(chain.next_back().is_none()); +} + +#[test] +fn test_len() { + let e = error(); + let mut chain = e.chain(); + assert_eq!(4, chain.len()); + assert_eq!((4, Some(4)), chain.size_hint()); + assert_eq!("3", chain.next().unwrap().to_string()); + assert_eq!(3, chain.len()); + assert_eq!((3, Some(3)), chain.size_hint()); + assert_eq!("0", chain.next_back().unwrap().to_string()); + assert_eq!(2, chain.len()); + assert_eq!((2, Some(2)), chain.size_hint()); + assert_eq!("2", chain.next().unwrap().to_string()); + assert_eq!(1, chain.len()); + assert_eq!((1, Some(1)), chain.size_hint()); + assert_eq!("1", chain.next_back().unwrap().to_string()); + assert_eq!(0, chain.len()); + assert_eq!((0, Some(0)), chain.size_hint()); + assert!(chain.next().is_none()); +} + +#[test] +fn test_default() { + let mut c = Chain::default(); + assert!(c.next().is_none()); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn test_clone() { + let e = error(); + let mut chain = e.chain().clone(); + assert_eq!("3", chain.next().unwrap().to_string()); + assert_eq!("2", chain.next().unwrap().to_string()); + assert_eq!("1", chain.next().unwrap().to_string()); + assert_eq!("0", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); + assert!(chain.next_back().is_none()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_context.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_context.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,172 @@ +#![allow( + // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422 + clippy::nonstandard_macro_braces, +)] + +mod drop; + +use crate::drop::{DetectDrop, Flag}; +use anyhow::{Context, Error, Result}; +use std::fmt::{self, Display}; +use thiserror::Error; + +// https://github.com/dtolnay/anyhow/issues/18 +#[test] +fn test_inference() -> Result<()> { + let x = "1"; + let y: u32 = x.parse().context("...")?; + assert_eq!(y, 1); + Ok(()) +} + +macro_rules! context_type { + ($name:ident) => { + #[derive(Debug)] + struct $name { + message: &'static str, + #[allow(dead_code)] + drop: DetectDrop, + } + + impl Display for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.message) + } + } + }; +} + +context_type!(HighLevel); +context_type!(MidLevel); + +#[derive(Error, Debug)] +#[error("{message}")] +struct LowLevel { + message: &'static str, + drop: DetectDrop, +} + +struct Dropped { + low: Flag, + mid: Flag, + high: Flag, +} + +impl Dropped { + fn none(&self) -> bool { + !self.low.get() && !self.mid.get() && !self.high.get() + } + + fn all(&self) -> bool { + self.low.get() && self.mid.get() && self.high.get() + } +} + +fn make_chain() -> (Error, Dropped) { + let dropped = Dropped { + low: Flag::new(), + mid: Flag::new(), + high: Flag::new(), + }; + + let low = LowLevel { + message: "no such file or directory", + drop: DetectDrop::new(&dropped.low), + }; + + // impl Context for Result + let mid = Err::<(), LowLevel>(low) + .context(MidLevel { + message: "failed to load config", + drop: DetectDrop::new(&dropped.mid), + }) + .unwrap_err(); + + // impl Context for Result + let high = Err::<(), Error>(mid) + .context(HighLevel { + message: "failed to start server", + drop: DetectDrop::new(&dropped.high), + }) + .unwrap_err(); + + (high, dropped) +} + +#[test] +fn test_downcast_ref() { + let (err, dropped) = make_chain(); + + assert!(!err.is::()); + assert!(err.downcast_ref::().is_none()); + + assert!(err.is::()); + let high = err.downcast_ref::().unwrap(); + assert_eq!(high.to_string(), "failed to start server"); + + assert!(err.is::()); + let mid = err.downcast_ref::().unwrap(); + assert_eq!(mid.to_string(), "failed to load config"); + + assert!(err.is::()); + let low = err.downcast_ref::().unwrap(); + assert_eq!(low.to_string(), "no such file or directory"); + + assert!(dropped.none()); + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_downcast_high() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.high.get()); + assert!(dropped.low.get() && dropped.mid.get()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_downcast_mid() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.mid.get()); + assert!(dropped.low.get() && dropped.high.get()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_downcast_low() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.low.get()); + assert!(dropped.mid.get() && dropped.high.get()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_unsuccessful_downcast() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap_err(); + assert!(dropped.none()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_root_cause() { + let (err, _) = make_chain(); + + assert_eq!(err.root_cause().to_string(), "no such file or directory"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_convert.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_convert.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_convert.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +#![allow(clippy::unnecessary_wraps)] + +mod drop; + +use self::drop::{DetectDrop, Flag}; +use anyhow::{Error, Result}; +use std::error::Error as StdError; + +#[test] +fn test_convert() { + let has_dropped = Flag::new(); + let error = Error::new(DetectDrop::new(&has_dropped)); + let box_dyn = Box::::from(error); + assert_eq!("oh no!", box_dyn.to_string()); + drop(box_dyn); + assert!(has_dropped.get()); +} + +#[test] +fn test_convert_send() { + let has_dropped = Flag::new(); + let error = Error::new(DetectDrop::new(&has_dropped)); + let box_dyn = Box::::from(error); + assert_eq!("oh no!", box_dyn.to_string()); + drop(box_dyn); + assert!(has_dropped.get()); +} + +#[test] +fn test_convert_send_sync() { + let has_dropped = Flag::new(); + let error = Error::new(DetectDrop::new(&has_dropped)); + let box_dyn = Box::::from(error); + assert_eq!("oh no!", box_dyn.to_string()); + drop(box_dyn); + assert!(has_dropped.get()); +} + +#[test] +fn test_question_mark() -> Result<(), Box> { + fn f() -> Result<()> { + Ok(()) + } + f()?; + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_downcast.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_downcast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_downcast.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_downcast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +#![allow(clippy::assertions_on_result_states, clippy::wildcard_imports)] + +mod common; +mod drop; + +use self::common::*; +use self::drop::{DetectDrop, Flag}; +use anyhow::Error; +use std::error::Error as StdError; +use std::fmt::{self, Display}; +use std::io; + +#[test] +fn test_downcast() { + assert_eq!( + "oh no!", + bail_literal().unwrap_err().downcast::<&str>().unwrap(), + ); + assert_eq!( + "oh no!", + bail_fmt().unwrap_err().downcast::().unwrap(), + ); + assert_eq!( + "oh no!", + bail_error() + .unwrap_err() + .downcast::() + .unwrap() + .to_string(), + ); +} + +#[test] +fn test_downcast_ref() { + assert_eq!( + "oh no!", + *bail_literal().unwrap_err().downcast_ref::<&str>().unwrap(), + ); + assert_eq!( + "oh no!", + bail_fmt().unwrap_err().downcast_ref::().unwrap(), + ); + assert_eq!( + "oh no!", + bail_error() + .unwrap_err() + .downcast_ref::() + .unwrap() + .to_string(), + ); +} + +#[test] +fn test_downcast_mut() { + assert_eq!( + "oh no!", + *bail_literal().unwrap_err().downcast_mut::<&str>().unwrap(), + ); + assert_eq!( + "oh no!", + bail_fmt().unwrap_err().downcast_mut::().unwrap(), + ); + assert_eq!( + "oh no!", + bail_error() + .unwrap_err() + .downcast_mut::() + .unwrap() + .to_string(), + ); + + let mut bailed = bail_fmt().unwrap_err(); + *bailed.downcast_mut::().unwrap() = "clobber".to_string(); + assert_eq!(bailed.downcast_ref::().unwrap(), "clobber"); + assert_eq!(bailed.downcast_mut::().unwrap(), "clobber"); + assert_eq!(bailed.downcast::().unwrap(), "clobber"); +} + +#[test] +fn test_drop() { + let has_dropped = Flag::new(); + let error = Error::new(DetectDrop::new(&has_dropped)); + drop(error.downcast::().unwrap()); + assert!(has_dropped.get()); +} + +#[test] +fn test_as_ref() { + let error = bail_error().unwrap_err(); + let ref_dyn: &dyn StdError = error.as_ref(); + assert_eq!("oh no!", ref_dyn.to_string()); + let ref_dyn_send_sync: &(dyn StdError + Send + Sync) = error.as_ref(); + assert_eq!("oh no!", ref_dyn_send_sync.to_string()); +} + +#[test] +fn test_large_alignment() { + #[repr(align(64))] + #[derive(Debug)] + struct LargeAlignedError(&'static str); + + impl Display for LargeAlignedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.0) + } + } + + impl StdError for LargeAlignedError {} + + let error = Error::new(LargeAlignedError("oh no!")); + assert_eq!( + "oh no!", + error.downcast_ref::().unwrap().0 + ); +} + +#[test] +fn test_unsuccessful_downcast() { + let mut error = bail_error().unwrap_err(); + assert!(error.downcast_ref::<&str>().is_none()); + assert!(error.downcast_mut::<&str>().is_none()); + assert!(error.downcast::<&str>().is_err()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_ensure.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ensure.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_ensure.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ensure.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,754 @@ +#![allow( + clippy::bool_to_int_with_if, + clippy::char_lit_as_u8, + clippy::deref_addrof, + clippy::diverging_sub_expression, + clippy::erasing_op, + clippy::extra_unused_type_parameters, + clippy::if_same_then_else, + clippy::ifs_same_cond, + clippy::ignored_unit_patterns, + clippy::items_after_statements, + clippy::let_and_return, + clippy::let_underscore_untyped, + clippy::literal_string_with_formatting_args, + clippy::match_bool, + clippy::needless_else, + clippy::never_loop, + clippy::overly_complex_bool_expr, + clippy::redundant_closure_call, + clippy::redundant_pattern_matching, + clippy::too_many_lines, + clippy::unit_arg, + clippy::unnecessary_cast, + clippy::while_immutable_condition, + clippy::zero_ptr, + irrefutable_let_patterns +)] + +use self::Enum::Generic; +use anyhow::{anyhow, ensure, Chain, Error, Result}; +use std::fmt::{self, Debug}; +use std::iter; +use std::marker::{PhantomData, PhantomData as P}; +use std::mem; +use std::ops::Add; +use std::ptr; + +struct S; + +impl Add for S { + type Output = bool; + fn add(self, rhs: T) -> Self::Output { + let _ = rhs; + false + } +} + +trait Trait: Sized { + const V: usize = 0; + fn t(self, i: i32) -> i32 { + i + } +} + +impl Trait for T {} + +enum Enum { + #[allow(dead_code)] + Thing(PhantomData), + Generic, +} + +impl PartialEq for Enum { + fn eq(&self, rhs: &Self) -> bool { + mem::discriminant(self) == mem::discriminant(rhs) + } +} + +impl Debug for Enum { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Generic") + } +} + +#[track_caller] +fn assert_err(result: impl FnOnce() -> Result, expected: &'static str) { + let actual = result().unwrap_err().to_string(); + + // In general different rustc versions will format the interpolated lhs and + // rhs $:expr fragment with insignificant differences in whitespace or + // punctuation, so we check the message in full against nightly and do just + // a cursory test on older toolchains. + if rustversion::cfg!(nightly) && !cfg!(miri) { + assert_eq!(actual, expected); + } else { + assert_eq!(actual.contains(" vs "), expected.contains(" vs ")); + } +} + +#[test] +fn test_recursion() { + // Must not blow the default #[recursion_limit], which is 128. + #[rustfmt::skip] + let test = || Ok(ensure!( + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false | + false | false | false | false | false | false | false | false | false + )); + + test().unwrap_err(); +} + +#[test] +fn test_low_precedence_control_flow() { + #[allow(unreachable_code)] + let test = || { + let val = loop { + // Break has lower precedence than the comparison operators so the + // expression here is `S + (break (1 == 1))`. It would be bad if the + // ensure macro partitioned this input into `(S + break 1) == (1)` + // because that means a different thing than what was written. + ensure!(S + break 1 == 1); + }; + Ok(val) + }; + + assert!(test().unwrap()); +} + +#[test] +fn test_low_precedence_binary_operator() { + // Must not partition as `false == (true && false)`. + let test = || Ok(ensure!(false == true && false)); + assert_err(test, "Condition failed: `false == true && false`"); + + // But outside the root level, it is fine. + let test = || Ok(ensure!(while false == true && false {} < ())); + assert_err( + test, + "Condition failed: `while false == true && false {} < ()` (() vs ())", + ); + + let a = 15; + let b = 3; + let test = || Ok(ensure!(a <= b || a - b <= 10)); + assert_err(test, "Condition failed: `a <= b || a - b <= 10`"); +} + +#[test] +fn test_high_precedence_binary_operator() { + let a = 15; + let b = 3; + let test = || Ok(ensure!(a - b <= 10)); + assert_err(test, "Condition failed: `a - b <= 10` (12 vs 10)"); +} + +#[test] +fn test_closure() { + // Must not partition as `(S + move) || (1 == 1)` by treating move as an + // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the + // closure precedence. + let test = || Ok(ensure!(S + move || 1 == 1)); + assert_err(test, "Condition failed: `S + move || 1 == 1`"); + + let test = || Ok(ensure!(S + || 1 == 1)); + assert_err(test, "Condition failed: `S + || 1 == 1`"); + + // Must not partition as `S + ((move | ()) | 1) == 1` by treating those + // pipes as bitwise-or. + let test = || Ok(ensure!(S + move |()| 1 == 1)); + assert_err(test, "Condition failed: `S + move |()| 1 == 1`"); + + let test = || Ok(ensure!(S + |()| 1 == 1)); + assert_err(test, "Condition failed: `S + |()| 1 == 1`"); +} + +#[test] +fn test_unary() { + let mut x = &1; + let test = || Ok(ensure!(*x == 2)); + assert_err(test, "Condition failed: `*x == 2` (1 vs 2)"); + + let test = || Ok(ensure!(!x == 1)); + assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)"); + + let test = || Ok(ensure!(-x == 1)); + assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)"); + + let test = || Ok(ensure!(&x == &&2)); + assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)"); + + let test = || Ok(ensure!(&mut x == *&&mut &2)); + assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)"); +} + +#[rustversion::since(1.82)] +#[test] +fn test_raw_addr() { + let mut x = 1; + let test = || Ok(ensure!(S + &raw const x != S + &raw mut x)); + assert_err( + test, + "Condition failed: `S + &raw const x != S + &raw mut x` (false vs false)", + ); +} + +#[test] +fn test_if() { + #[rustfmt::skip] + let test = || Ok(ensure!(if false {}.t(1) == 2)); + assert_err(test, "Condition failed: `if false {}.t(1) == 2` (1 vs 2)"); + + #[rustfmt::skip] + let test = || Ok(ensure!(if false {} else {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `if false {} else {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `if false {} else if false {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `if let 1 = 2 {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `if let 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `if let | 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)", + ); +} + +#[test] +fn test_loop() { + #[rustfmt::skip] + let test = || Ok(ensure!(1 + loop { break 1 } == 1)); + assert_err( + test, + "Condition failed: `1 + loop { break 1 } == 1` (2 vs 1)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1)); + assert_err( + test, + "Condition failed: `1 + 'a: loop { break 'a 1 } == 1` (2 vs 1)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(while false {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `while false {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(while let None = Some(1) {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `while let None = Some(1) {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(for _x in iter::once(0) {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `for _x in iter::once(0) {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(for | _x in iter::once(0) {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `for | _x in iter::once(0) {}.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(for true | false in iter::empty() {}.t(1) == 2)); + assert_err( + test, + "Condition failed: `for true | false in iter::empty() {}.t(1) == 2` (1 vs 2)", + ); +} + +#[test] +fn test_match() { + #[rustfmt::skip] + let test = || Ok(ensure!(match 1 == 1 { true => 1, false => 0 } == 2)); + assert_err( + test, + "Condition failed: `match 1 == 1 { true => 1, false => 0 } == 2` (1 vs 2)", + ); +} + +#[test] +fn test_atom() { + let test = || Ok(ensure!([false, false].len() > 3)); + assert_err( + test, + "Condition failed: `[false, false].len() > 3` (2 vs 3)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!({ let x = 1; x } >= 3)); + assert_err(test, "Condition failed: `{ let x = 1; x } >= 3` (1 vs 3)"); + + let test = || Ok(ensure!(S + async { 1 } == true)); + assert_err( + test, + "Condition failed: `S + async { 1 } == true` (false vs true)", + ); + + let test = || Ok(ensure!(S + async move { 1 } == true)); + assert_err( + test, + "Condition failed: `S + async move { 1 } == true` (false vs true)", + ); + + let x = &1; + let test = || Ok(ensure!(S + unsafe { ptr::read(x) } == true)); + assert_err( + test, + "Condition failed: `S + unsafe { ptr::read(x) } == true` (false vs true)", + ); +} + +#[test] +fn test_path() { + let test = || Ok(ensure!(crate::S.t(1) == 2)); + assert_err(test, "Condition failed: `crate::S.t(1) == 2` (1 vs 2)"); + + let test = || Ok(ensure!(::anyhow::Error::root_cause.t(1) == 2)); + assert_err( + test, + "Condition failed: `::anyhow::Error::root_cause.t(1) == 2` (1 vs 2)", + ); + + let test = || Ok(ensure!(Error::msg::<&str>.t(1) == 2)); + assert_err( + test, + "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(Error::msg::<&str,>.t(1) == 2)); + assert_err( + test, + "Condition failed: `Error::msg::<&str,>.t(1) == 2` (1 vs 2)", + ); + + let test = || Ok(ensure!(Error::msg::<::Owned>.t(1) == 2)); + assert_err( + test, + "Condition failed: `Error::msg::<::Owned>.t(1) == 2` (1 vs 2)", + ); + + let test = || Ok(ensure!(Chain::<'static>::new.t(1) == 2)); + assert_err( + test, + "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(Chain::<'static,>::new.t(1) == 2)); + assert_err( + test, + "Condition failed: `Chain::<'static,>::new.t(1) == 2` (1 vs 2)", + ); + + fn f() {} + let test = || Ok(ensure!(f::<1>() != ())); + assert_err(test, "Condition failed: `f::<1>() != ()` (() vs ())"); + let test = || Ok(ensure!(f::<-1>() != ())); + assert_err(test, "Condition failed: `f::<-1>() != ()` (() vs ())"); + + fn g() {} + let test = || Ok(ensure!(g::() != ())); + assert_err(test, "Condition failed: `g::() != ()` (() vs ())"); + let test = || Ok(ensure!(g::() != ())); + assert_err(test, "Condition failed: `g::() != ()` (() vs ())"); + + #[derive(PartialOrd, PartialEq, Debug)] + enum E<'a, T> { + #[allow(dead_code)] + T(&'a T), + U, + } + + #[rustfmt::skip] + let test = || Ok(ensure!(E::U::<>>E::U::)); + assert_err(test, "Condition failed: `E::U::<> > E::U::` (U vs U)"); + + #[rustfmt::skip] + let test = || Ok(ensure!(E::U::>E::U)); + assert_err(test, "Condition failed: `E::U:: > E::U` (U vs U)"); + + #[rustfmt::skip] + let test = || Ok(ensure!(E::U::>E::U)); + assert_err(test, "Condition failed: `E::U:: > E::U` (U vs U)"); + + let test = || Ok(ensure!(Generic:: != Generic)); + assert_err( + test, + "Condition failed: `Generic:: != Generic` (Generic vs Generic)", + ); + + let test = || Ok(ensure!(Generic:: != Generic)); + assert_err( + test, + "Condition failed: `Generic:: != Generic` (Generic vs Generic)", + ); + + #[rustfmt::skip] + let test = || { + Ok(ensure!( + Generic:: != Generic + )) + }; + assert_err( + test, + "Condition failed: `Generic:: != Generic` (Generic vs Generic)", + ); +} + +#[test] +fn test_macro() { + let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1)); + assert_err( + test, + "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)", + ); + + let test = || Ok(ensure!(vec![1].len() < 1)); + assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)"); + + let test = || Ok(ensure!(stringify! {} != "")); + assert_err( + test, + "Condition failed: `stringify! {} != \"\"` (\"\" vs \"\")", + ); +} + +#[test] +fn test_trailer() { + let test = || Ok(ensure!((|| 1)() == 2)); + assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)"); + + let test = || Ok(ensure!(b"hmm"[1] == b'c')); + assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)"); + + let test = || Ok(ensure!(PhantomData:: {} != PhantomData)); + assert_err( + test, + "Condition failed: `PhantomData:: {} != PhantomData` (PhantomData vs PhantomData)", + ); + + let result = Ok::<_, Error>(1); + let test = || Ok(ensure!(result? == 2)); + assert_err(test, "Condition failed: `result? == 2` (1 vs 2)"); + + let test = || Ok(ensure!((2, 3).1 == 2)); + assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)"); + + #[rustfmt::skip] + let test = || Ok(ensure!((2, (3, 4)). 1.1 == 2)); + assert_err(test, "Condition failed: `(2, (3, 4)).1.1 == 2` (4 vs 2)"); + + let err = anyhow!(""); + let test = || Ok(ensure!(err.is::<&str>() == false)); + assert_err( + test, + "Condition failed: `err.is::<&str>() == false` (true vs false)", + ); + + let test = || Ok(ensure!(err.is::<::Owned>() == true)); + assert_err( + test, + "Condition failed: `err.is::<::Owned>() == true` (false vs true)", + ); +} + +#[test] +fn test_whitespace() { + #[derive(Debug)] + pub struct Point { + #[allow(dead_code)] + pub x: i32, + #[allow(dead_code)] + pub y: i32, + } + + let point = Point { x: 0, y: 0 }; + let test = || Ok(ensure!("" == format!("{:#?}", point))); + assert_err( + test, + "Condition failed: `\"\" == format!(\"{:#?}\", point)`", + ); +} + +#[test] +fn test_too_long() { + let test = || Ok(ensure!("" == "x".repeat(10))); + assert_err( + test, + "Condition failed: `\"\" == \"x\".repeat(10)` (\"\" vs \"xxxxxxxxxx\")", + ); + + let test = || Ok(ensure!("" == "x".repeat(80))); + assert_err(test, "Condition failed: `\"\" == \"x\".repeat(80)`"); +} + +#[test] +fn test_as() { + let test = || Ok(ensure!('\0' as u8 > 1)); + assert_err(test, "Condition failed: `'\\0' as u8 > 1` (0 vs 1)"); + + let test = || Ok(ensure!('\0' as ::std::primitive::u8 > 1)); + assert_err( + test, + "Condition failed: `'\\0' as ::std::primitive::u8 > 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(&[0] as &[i32] == [1])); + assert_err( + test, + "Condition failed: `&[0] as &[i32] == [1]` ([0] vs [1])", + ); + + let test = || Ok(ensure!(0 as *const () as *mut _ == 1 as *mut ())); + assert_err( + test, + "Condition failed: `0 as *const () as *mut _ == 1 as *mut ()` (0x0 vs 0x1)", + ); + + let s = ""; + let test = || Ok(ensure!(s as &str != s)); + assert_err(test, "Condition failed: `s as &str != s` (\"\" vs \"\")"); + + let test = || Ok(ensure!(&s as &&str != &s)); + assert_err(test, "Condition failed: `&s as &&str != &s` (\"\" vs \"\")"); + + let test = || Ok(ensure!(s as &'static str != s)); + assert_err( + test, + "Condition failed: `s as &'static str != s` (\"\" vs \"\")", + ); + + let test = || Ok(ensure!(&s as &&'static str != &s)); + assert_err( + test, + "Condition failed: `&s as &&'static str != &s` (\"\" vs \"\")", + ); + + let m: &mut str = Default::default(); + let test = || Ok(ensure!(m as &mut str != s)); + assert_err( + test, + "Condition failed: `m as &mut str != s` (\"\" vs \"\")", + ); + + let test = || Ok(ensure!(&m as &&mut str != &s)); + assert_err( + test, + "Condition failed: `&m as &&mut str != &s` (\"\" vs \"\")", + ); + + let test = || Ok(ensure!(&m as &&'static mut str != &s)); + assert_err( + test, + "Condition failed: `&m as &&'static mut str != &s` (\"\" vs \"\")", + ); + + let f = || {}; + let test = || Ok(ensure!(f as fn() as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as fn() as usize * 0 != 0` (0 vs 0)", + ); + + let test = || Ok(ensure!(f as fn() -> () as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as fn() -> () as usize * 0 != 0` (0 vs 0)", + ); + + let test = || Ok(ensure!(f as for<'a> fn() as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as for<'a> fn() as usize * 0 != 0` (0 vs 0)", + ); + + let test = || Ok(ensure!(f as unsafe fn() as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as unsafe fn() as usize * 0 != 0` (0 vs 0)", + ); + + #[rustfmt::skip] + let test = || Ok(ensure!(f as extern "Rust" fn() as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as extern \"Rust\" fn() as usize * 0 != 0` (0 vs 0)", + ); + + extern "C" fn extern_fn() {} + #[rustfmt::skip] + #[allow(missing_abi)] + let test = || Ok(ensure!(extern_fn as extern fn() as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `extern_fn as extern fn() as usize * 0 != 0` (0 vs 0)", + ); + + let f = || -> ! { panic!() }; + let test = || Ok(ensure!(f as fn() -> ! as usize * 0 != 0)); + assert_err( + test, + "Condition failed: `f as fn() -> ! as usize * 0 != 0` (0 vs 0)", + ); + + trait EqDebug: PartialEq + Debug { + type Assoc; + } + + impl EqDebug for S + where + S: PartialEq + Debug, + { + type Assoc = bool; + } + + let test = || Ok(ensure!(&0 as &dyn EqDebug != &0)); + assert_err( + test, + "Condition failed: `&0 as &dyn EqDebug != &0` (0 vs 0)", + ); + + let test = || { + Ok(ensure!( + PhantomData as PhantomData<::Owned> != PhantomData + )) + }; + assert_err( + test, + "Condition failed: `PhantomData as PhantomData<::Owned> != PhantomData` (PhantomData vs PhantomData)", + ); + + macro_rules! int { + (...) => { + u8 + }; + } + + let test = || Ok(ensure!(0 as int!(...) != 0)); + assert_err(test, "Condition failed: `0 as int!(...) != 0` (0 vs 0)"); + + let test = || Ok(ensure!(0 as int![...] != 0)); + assert_err(test, "Condition failed: `0 as int![...] != 0` (0 vs 0)"); + + let test = || Ok(ensure!(0 as int! {...} != 0)); + assert_err(test, "Condition failed: `0 as int! {...} != 0` (0 vs 0)"); +} + +#[test] +fn test_pat() { + let test = || Ok(ensure!(if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let -1..=1 = 0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let -1..=1 = 0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let &0 = &0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let &0 = &0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let &&0 = &&0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let &&0 = &&0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let &mut 0 = &mut 0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let &mut 0 = &mut 0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let (0, 1) = (0, 1) { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let (0, 1) = (0, 1) { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let [0] = b"\0" { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let [0] = b\"\\0\" { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let p = PhantomData::; + let test = || Ok(ensure!(if let P:: {} = p { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let P:: {} = p { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(if let ::std::marker::PhantomData = p {} != ())); + assert_err( + test, + "Condition failed: `if let ::std::marker::PhantomData = p {} != ()` (() vs ())", + ); + + let test = || Ok(ensure!(if let ::V = 0 { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let ::V = 0 { 0 } else { 1 } == 1` (0 vs 1)", + ); + + let test = || Ok(ensure!(for _ in iter::once(()) {} != ())); + assert_err( + test, + "Condition failed: `for _ in iter::once(()) {} != ()` (() vs ())", + ); + + let test = || Ok(ensure!(if let stringify!(x) = "x" { 0 } else { 1 } == 1)); + assert_err( + test, + "Condition failed: `if let stringify!(x) = \"x\" { 0 } else { 1 } == 1` (0 vs 1)", + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_ffi.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ffi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_ffi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_ffi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +#![deny(improper_ctypes, improper_ctypes_definitions)] + +use anyhow::anyhow; + +#[no_mangle] +pub extern "C" fn anyhow1(err: anyhow::Error) { + println!("{:?}", err); +} + +#[no_mangle] +pub extern "C" fn anyhow2(err: &mut Option) { + *err = Some(anyhow!("ffi error")); +} + +#[no_mangle] +pub extern "C" fn anyhow3() -> Option { + Some(anyhow!("ffi error")) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,93 @@ +use anyhow::{bail, Context, Result}; +use std::io; + +fn f() -> Result<()> { + bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); +} + +fn g() -> Result<()> { + f().context("f failed") +} + +fn h() -> Result<()> { + g().context("g failed") +} + +const EXPECTED_ALTDISPLAY_F: &str = "oh no!"; + +const EXPECTED_ALTDISPLAY_G: &str = "f failed: oh no!"; + +const EXPECTED_ALTDISPLAY_H: &str = "g failed: f failed: oh no!"; + +const EXPECTED_DEBUG_F: &str = "oh no!"; + +const EXPECTED_DEBUG_G: &str = "\ +f failed + +Caused by: + oh no!\ +"; + +const EXPECTED_DEBUG_H: &str = "\ +g failed + +Caused by: + 0: f failed + 1: oh no!\ +"; + +const EXPECTED_ALTDEBUG_F: &str = "\ +Custom { + kind: PermissionDenied, + error: \"oh no!\", +}\ +"; + +const EXPECTED_ALTDEBUG_G: &str = "\ +Error { + context: \"f failed\", + source: Custom { + kind: PermissionDenied, + error: \"oh no!\", + }, +}\ +"; + +const EXPECTED_ALTDEBUG_H: &str = "\ +Error { + context: \"g failed\", + source: Error { + context: \"f failed\", + source: Custom { + kind: PermissionDenied, + error: \"oh no!\", + }, + }, +}\ +"; + +#[test] +fn test_display() { + assert_eq!("g failed", h().unwrap_err().to_string()); +} + +#[test] +fn test_altdisplay() { + assert_eq!(EXPECTED_ALTDISPLAY_F, format!("{:#}", f().unwrap_err())); + assert_eq!(EXPECTED_ALTDISPLAY_G, format!("{:#}", g().unwrap_err())); + assert_eq!(EXPECTED_ALTDISPLAY_H, format!("{:#}", h().unwrap_err())); +} + +#[test] +fn test_debug() { + assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err())); + assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err())); + assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err())); +} + +#[test] +fn test_altdebug() { + assert_eq!(EXPECTED_ALTDEBUG_F, format!("{:#?}", f().unwrap_err())); + assert_eq!(EXPECTED_ALTDEBUG_G, format!("{:#?}", g().unwrap_err())); + assert_eq!(EXPECTED_ALTDEBUG_H, format!("{:#?}", h().unwrap_err())); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_macros.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +#![allow( + clippy::assertions_on_result_states, + clippy::eq_op, + clippy::incompatible_msrv, // https://github.com/rust-lang/rust-clippy/issues/12257 + clippy::items_after_statements, + clippy::match_single_binding, + clippy::needless_pass_by_value, + clippy::shadow_unrelated, + clippy::wildcard_imports +)] + +mod common; + +use self::common::*; +use anyhow::{anyhow, ensure, Result}; +use std::cell::Cell; +use std::future; + +#[test] +fn test_messages() { + assert_eq!("oh no!", bail_literal().unwrap_err().to_string()); + assert_eq!("oh no!", bail_fmt().unwrap_err().to_string()); + assert_eq!("oh no!", bail_error().unwrap_err().to_string()); +} + +#[test] +fn test_ensure() { + let f = || { + ensure!(1 + 1 == 2, "This is correct"); + Ok(()) + }; + assert!(f().is_ok()); + + let v = 1; + let f = || { + ensure!(v + v == 2, "This is correct, v: {}", v); + Ok(()) + }; + assert!(f().is_ok()); + + let f = || { + ensure!(v + v == 1, "This is not correct, v: {}", v); + Ok(()) + }; + assert!(f().is_err()); + + let f = || { + ensure!(v + v == 1); + Ok(()) + }; + assert_eq!( + f().unwrap_err().to_string(), + "Condition failed: `v + v == 1` (2 vs 1)", + ); +} + +#[test] +fn test_ensure_nonbool() -> Result<()> { + struct Struct { + condition: bool, + } + + let s = Struct { condition: true }; + match &s { + Struct { condition } => ensure!(condition), // &bool + } + + Ok(()) +} + +#[test] +fn test_temporaries() { + fn require_send_sync(_: impl Send + Sync) {} + + require_send_sync(async { + // If anyhow hasn't dropped any temporary format_args it creates by the + // time it's done evaluating, those will stick around until the + // semicolon, which is on the other side of the await point, making the + // enclosing future non-Send. + future::ready(anyhow!("...")).await; + }); + + fn message(cell: Cell<&str>) -> &str { + cell.get() + } + + require_send_sync(async { + future::ready(anyhow!(message(Cell::new("...")))).await; + }); +} + +#[test] +fn test_brace_escape() { + let err = anyhow!("unterminated ${{..}} expression"); + assert_eq!("unterminated ${..} expression", err.to_string()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_repr.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_repr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_repr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_repr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +#![allow(clippy::extra_unused_type_parameters)] + +mod drop; + +use self::drop::{DetectDrop, Flag}; +use anyhow::Error; +use std::mem; + +#[test] +fn test_error_size() { + assert_eq!(mem::size_of::(), mem::size_of::()); +} + +#[test] +fn test_null_pointer_optimization() { + assert_eq!(mem::size_of::>(), mem::size_of::()); +} + +#[test] +fn test_autotraits() { + fn assert() {} + assert::(); +} + +#[test] +fn test_drop() { + let has_dropped = Flag::new(); + drop(Error::new(DetectDrop::new(&has_dropped))); + assert!(has_dropped.get()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_source.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/test_source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/test_source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +use anyhow::anyhow; +use std::error::Error as StdError; +use std::fmt::{self, Display}; +use std::io; + +#[derive(Debug)] +enum TestError { + Io(io::Error), +} + +impl Display for TestError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { + TestError::Io(e) => Display::fmt(e, formatter), + } + } +} + +impl StdError for TestError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match self { + TestError::Io(io) => Some(io), + } + } +} + +#[test] +fn test_literal_source() { + let error = anyhow!("oh no!"); + assert!(error.source().is_none()); +} + +#[test] +fn test_variable_source() { + let msg = "oh no!"; + let error = anyhow!(msg); + assert!(error.source().is_none()); + + let msg = msg.to_owned(); + let error = anyhow!(msg); + assert!(error.source().is_none()); +} + +#[test] +fn test_fmt_source() { + let error = anyhow!("{} {}!", "oh", "no"); + assert!(error.source().is_none()); +} + +#[test] +fn test_io_source() { + let io = io::Error::new(io::ErrorKind::Other, "oh no!"); + let error = anyhow!(TestError::Io(io)); + assert_eq!("oh no!", error.source().unwrap().to_string()); +} + +#[test] +fn test_anyhow_from_anyhow() { + let error = anyhow!("oh no!").context("context"); + let error = anyhow!(error); + assert_eq!("oh no!", error.source().unwrap().to_string()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +use anyhow::{ensure, Result}; + +fn main() -> Result<()> { + // `ensure!` must not partition this into `(false) == (false == true)` + // because Rust doesn't ordinarily allow this form of expression. + ensure!(false == false == true); + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/chained-comparison.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +error: comparison operators cannot be chained + --> tests/ui/chained-comparison.rs:6:19 + | +6 | ensure!(false == false == true); + | ^^ ^^ + | +help: split the comparison into two + | +6 | ensure!(false == false && false == true); + | ++++++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +use anyhow::{ensure, Result}; + +fn main() -> Result<()> { + ensure!(); + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/empty-ensure.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error: unexpected end of macro invocation + --> tests/ui/empty-ensure.rs:4:5 + | +4 | ensure!(); + | ^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$cond:expr` + --> src/ensure.rs + | + | ($cond:expr $(,)?) => { + | ^^^^^^^^^^ + = note: this error originates in the macro `$crate::__parse_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +use anyhow::{ensure, Result}; +use std::ops::{Deref, Not}; + +struct Bool(bool); + +struct DerefBool(bool); + +struct NotBool(bool); + +impl Deref for DerefBool { + type Target = bool; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Not for NotBool { + type Output = bool; + fn not(self) -> Self::Output { + !self.0 + } +} + +fn main() -> Result<()> { + ensure!("..."); + + let mut s = Bool(true); + match &mut s { + Bool(cond) => ensure!(cond), + } + + let db = DerefBool(true); + ensure!(db); + ensure!(&db); + + let nb = NotBool(true); + ensure!(nb); + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/ensure-nonbool.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +error[E0277]: the trait bound `&str: __private::not::Bool` is not satisfied + --> tests/ui/ensure-nonbool.rs:25:13 + | +25 | ensure!("..."); + | --------^^^^^- + | | | + | | the trait `__private::not::Bool` is not implemented for `&str` + | required by a bound introduced by this call + | + = help: the following other types implement trait `__private::not::Bool`: + &bool + bool +note: required by a bound in `anyhow::__private::not` + --> src/lib.rs + | + | pub fn not(cond: impl Bool) -> bool { + | ^^^^ required by this bound in `not` + +error[E0277]: the trait bound `&mut bool: __private::not::Bool` is not satisfied + --> tests/ui/ensure-nonbool.rs:29:31 + | +29 | Bool(cond) => ensure!(cond), + | --------^^^^- + | | | + | | the trait `__private::not::Bool` is not implemented for `&mut bool` + | required by a bound introduced by this call + | + = note: `__private::not::Bool` is implemented for `&bool`, but not for `&mut bool` +note: required by a bound in `anyhow::__private::not` + --> src/lib.rs + | + | pub fn not(cond: impl Bool) -> bool { + | ^^^^ required by this bound in `not` +help: consider dereferencing here + | +29 | Bool(cond) => ensure!(*cond), + | + + +error[E0277]: the trait bound `DerefBool: __private::not::Bool` is not satisfied + --> tests/ui/ensure-nonbool.rs:33:13 + | +33 | ensure!(db); + | --------^^- + | | | + | | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `__private::not::Bool` is not implemented for `DerefBool` + --> tests/ui/ensure-nonbool.rs:6:1 + | + 6 | struct DerefBool(bool); + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `anyhow::__private::not` + --> src/lib.rs + | + | pub fn not(cond: impl Bool) -> bool { + | ^^^^ required by this bound in `not` +help: consider dereferencing here + | +33 | ensure!(*db); + | + + +error[E0277]: the trait bound `&DerefBool: __private::not::Bool` is not satisfied + --> tests/ui/ensure-nonbool.rs:34:13 + | +34 | ensure!(&db); + | --------^^^- + | | | + | | the trait `__private::not::Bool` is not implemented for `&DerefBool` + | required by a bound introduced by this call + | +note: required by a bound in `anyhow::__private::not` + --> src/lib.rs + | + | pub fn not(cond: impl Bool) -> bool { + | ^^^^ required by this bound in `not` +help: consider dereferencing here + | +34 | ensure!(&*db); + | + + +error[E0277]: the trait bound `NotBool: __private::not::Bool` is not satisfied + --> tests/ui/ensure-nonbool.rs:37:13 + | +37 | ensure!(nb); + | --------^^- + | | | + | | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `__private::not::Bool` is not implemented for `NotBool` + --> tests/ui/ensure-nonbool.rs:8:1 + | + 8 | struct NotBool(bool); + | ^^^^^^^^^^^^^^ + = help: the following other types implement trait `__private::not::Bool`: + &bool + bool +note: required by a bound in `anyhow::__private::not` + --> src/lib.rs + | + | pub fn not(cond: impl Bool) -> bool { + | ^^^^ required by this bound in `not` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +#![deny(unused_must_use)] + +use anyhow::anyhow; + +fn main() -> anyhow::Result<()> { + if true { + // meant to write bail! + anyhow!("it failed"); + } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/must-use.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error: unused return value of `anyhow::__private::must_use` that must be used + --> tests/ui/must-use.rs:8:9 + | +8 | anyhow!("it failed"); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/must-use.rs:1:9 + | +1 | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +8 | let _ = anyhow!("it failed"); + | +++++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +use anyhow::anyhow; + +#[derive(Debug)] +struct Error; + +fn main() { + let _ = anyhow!(Error); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/no-impl.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its trait bounds were not satisfied + --> tests/ui/no-impl.rs:7:13 + | +4 | struct Error; + | ------------ doesn't satisfy `Error: Into`, `Error: anyhow::kind::TraitKind` or `Error: std::fmt::Display` +... +7 | let _ = anyhow!(Error); + | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Error: Into` + which is required by `Error: anyhow::kind::TraitKind` + `Error: std::fmt::Display` + which is required by `&Error: anyhow::kind::AdhocKind` + `&Error: Into` + which is required by `&Error: anyhow::kind::TraitKind` +note: the traits `Into` and `std::fmt::Display` must be implemented + --> $RUST/core/src/fmt/mod.rs + | + | pub trait Display: PointeeSized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + ::: $RUST/core/src/convert/mod.rs + | + | pub const trait Into: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `anyhow_kind`, perhaps you need to implement one of them: + candidate #1: `anyhow::kind::AdhocKind` + candidate #2: `anyhow::kind::BoxedKind` + candidate #3: `anyhow::kind::TraitKind` + = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +use anyhow::anyhow; + +fn main() { + let _ = anyhow!(&String::new()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/temporary-value.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0716]: temporary value dropped while borrowed + --> tests/ui/temporary-value.rs:4:22 + | +4 | let _ = anyhow!(&String::new()); + | ---------^^^^^^^^^^^^^- + | | | + | | creates a temporary value which is freed while still in use + | temporary value is freed at the end of this statement + | argument requires that borrow lasts for `'static` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.rs clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.rs --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +use anyhow::{bail, Result}; + +fn main() -> Result<()> { + bail!("{} not found"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.stderr clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/anyhow/tests/ui/wrong-interpolation.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: 1 positional argument in format string, but no arguments were given + --> tests/ui/wrong-interpolation.rs:4:12 + | +4 | bail!("{} not found"); + | ^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"4ccfce7ed08cd9e4c7c6dde4ba7150998c79fe9e2bea9789a67db2e11826ca0f",".github/workflows/rust.yml":"547c39288b203a13a0067413953d28d9f40f12c3cabe3e93b497addc97243b93","CHANGELOG.md":"0635d44ea4dd7af870a570661568dfff09175dafa88f999b1904d8dc81024262","Cargo.lock":"dc6ed543396cf073d2b0e045f09505a77b80a54e1b4a7ec71b8edde4f3454d65","Cargo.toml":"18431fa35c62df4019339b0b105a0ee12e8db49ca178e68f0fb3b9b7e5e8ec01","Cargo.toml.orig":"4c37498742093f3ae1e828f2f9a3678e16fb599cae3c7d8ac6f2816d9c28f851","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"15656cc11a8331f28c0986b8ab97220d3e76f98e60ed388b5ffad37dfac4710c","README.md":"480774d6a0bedd284549aac8ce7757d8e7cdcc4713fd64214742088975f58f7d","examples/derive_enum.rs":"45d11d8cd0461716b276e2df4a5b31e7ae7ece36f05d42a0d4c055a5e4f02ab1","publish.sh":"752e221bdd960666b127df15effddd3d789ff3f1762498961fc79ae99f9a27f1","src/error.rs":"9340da1575e92d57169798bc23f5356d9e97963497fdc6b2d6f8b8c2d7fd5be6","src/foreign/alloc/borrow.rs":"2741eea43a139e7c83b92ab237a60f421224c539ef90ae3125be34b1e6943e54","src/foreign/alloc/boxed.rs":"2ea6fe8795b644de7785ff5373ab6728399de531c2bf50b8f501d48e15dc92db","src/foreign/alloc/collections/binary_heap.rs":"69e648323514313a6f9b6e24b1dbe03d3b24830608f04ad8acac043e6eb44a2b","src/foreign/alloc/collections/btree_map.rs":"158e9e611cb7b03b3190ee8bbebe855cf2291bf14c2adc774d4e6edf5ec47650","src/foreign/alloc/collections/btree_set.rs":"16ad32b9edaa871c046a2543614eb18513801fd880f8926343c2cc74ee7251a4","src/foreign/alloc/collections/linked_list.rs":"cad35cd65f824ef4f0931fa6c200d737b2ac56c3940321a7c7c7b7d9b2d86f1f","src/foreign/alloc/collections/mod.rs":"e81c20370de8903f79d53dd89552c00d3ce6ff12280b379a5ab8d8d1adcecaa5","src/foreign/alloc/collections/vec_deque.rs":"0821db085c8303f8f9e4a316a6dbb5529330488ed06c19284a22a6ef72313270","src/foreign/alloc/ffi/c_str.rs":"16228949035611dfa6522fdc8f25f5afc188eef74febbf06769e9edb88a8430f","src/foreign/alloc/ffi/mod.rs":"9e612467614f7a53369b11278d624bca71f1f44156fcb58d891c7d06f6f1425f","src/foreign/alloc/mod.rs":"27e0cdebd51ee3626ac7ae0b6926c25fdacc9c74b337318d35573d33cc9996b9","src/foreign/alloc/rc.rs":"d17102fc5573461b33b995b5e69553f4d1115f40d70a500c6b86cdf1af766e48","src/foreign/alloc/string.rs":"4c67871b59fb0ce1c13c54b2df2e2054cf02986152bcead7a701fc272ded3cbd","src/foreign/alloc/sync.rs":"e95b2d61962247a03524583aa5ecd1ad5abeb2cfe6590b3ccf7f26649f1287ac","src/foreign/alloc/vec.rs":"57ca9806b9381d6b53e46a0b15fa97c1c698ef950686a1502d0b034656a3f23e","src/foreign/core/array.rs":"1d8c7d794f9990ea43166744a7b25937d43f5f438d0a2c0ab086d88ea07258bd","src/foreign/core/bool.rs":"0f8eff3a2520c85d4bf0ea72895c45e809bf99e45cc10b3e6d3f571ada05de52","src/foreign/core/cell.rs":"b594f71084136f441d49340c74e5df734df9f6d91a3fd9945d96595c440f0a2b","src/foreign/core/char.rs":"a4ce48e71e3acd09c5b42259455c131522d1d21534324cd62f34027d3db5336a","src/foreign/core/cmp.rs":"55cceee1523a0cefbcd7fa2bbe4b6661b473bf950115f41c64e9fffd77276dce","src/foreign/core/iter.rs":"8e5ea3c9885db203cdfb55585c7f6d46f70aa626188abf80af58f2c96df38f53","src/foreign/core/marker.rs":"67386fd457adfabcca6c6fdfbc6883782f6ee3bdd8c344e316adc4587de886af","src/foreign/core/mod.rs":"f5c98383dc33e4a45bc32136ca26c985f2b45771573ac7152a9335992456bc24","src/foreign/core/num.rs":"294b4977e7707d274461d3029fc7b3225fe2dc4d21e0b86f01bed16b24f901b6","src/foreign/core/ops.rs":"f9bfaef1d11aac50dbefbcd2122b912999401a5a1a165caadc7c3e7aa844d61a","src/foreign/core/option.rs":"173f8a9193b075f2c7fe754177912432d8b4f06fdeeca55cab8ebce332a8ccaa","src/foreign/core/result.rs":"13ea4aab756af7de3e1cc1e38aa0a68045c213636809862193a047c36f13f0a7","src/foreign/core/slice.rs":"f42caa49d1a55461c9d515d386fc2b7b2bfc5f0ac8a229d5ca465af5573a453f","src/foreign/core/str.rs":"add0bc52fcc06adcf294f16bf95f3c513ce07a2fd614d8474976cbf743922e2a","src/foreign/core/sync/atomic.rs":"541583cb54d26c65b99254e788e1d4a6a14e4fdba351f14e700fdbc0416e8326","src/foreign/core/sync/mod.rs":"a5ae8ce1fc6b462b1f57993f94bd8cf014d5375728e67dd9c24a21b66cba95c8","src/foreign/core/time.rs":"fa0f1383c65e44c185f2f5112c22a6ca58f9688c5bac1b130c5d91d11c0fa7a4","src/foreign/core/tuple.rs":"66e9361bec0d62d2f4214ddab266fee2258cbf52c1243f8882612861b2bd98f1","src/foreign/core/unit.rs":"1035c63c6a7757bae8940bf0fbdcc8c49a2ca2ea004d8c39666c5d0b22d921e1","src/foreign/mod.rs":"9ab162a3dc28ad93acf2a8fc2942d0f409de349a4282f42538e09669aec4aaa5","src/foreign/std/collections/hash_map.rs":"aa6c7e6e7cf4afcb207fa43f1edf95dd3ec4d78cc5fe86bf40a8b98b116d5f0f","src/foreign/std/collections/hash_set.rs":"4b36b1e6f096c8690c7c6b106505c53cd58370f9fb9b4683cd753fa7f393bda4","src/foreign/std/collections/mod.rs":"54399ce5574fd1d84b7b0cb4238fa3e898575e89a6724299be009d2172bda02e","src/foreign/std/ffi/c_str.rs":"80c4bcd6e3d79999503b50c9b82c234539cd63905c0745f9f755b91e1fe54f9a","src/foreign/std/ffi/mod.rs":"7b6b2f64278961fb440787161924427fb6f4ebc376243932ecab9409e1dab755","src/foreign/std/ffi/os_str.rs":"e20cce997e2139d51dc345375e3ad8da3385de7d46e3dc288fc4963835fcb0e6","src/foreign/std/mod.rs":"f304d0482650833ce7f3a785add71590019c3e00ce39f68740b98a966100acf3","src/foreign/std/net.rs":"e391211150bd94fc6fd7f8dac0e1e7e0454b6421f69790996efd93fcd5e277a8","src/foreign/std/path.rs":"8ef7a801595763c99a1342eeaa222a08a46e5c5770bc4a167d36cfd933ad9649","src/foreign/std/sync.rs":"bfbde00300424956e7f06df3194547c0cf2a463ec60df47b0ec90d920e063f8b","src/lib.rs":"62eb6dfc34cc0e97e4be4c43de1071e698d2848349871395a2c3b13dd5883f7c","src/size_hint.rs":"2e409df461eabb90c4b3e6788e99cb9469a134bb28b95bb7faf1ca5061a6be91","src/tests.rs":"9044f1cf9fbf4879c4e91181376b52700d4dacbcdd1c792743c8abd69281d59a","src/unstructured.rs":"b775c04198c786ebc1a022ffbcf4c6f8d3a0406e4900d8829577b59268759dc0","tests/bound.rs":"32b8ce8083419ecadd66e1fde4da427b437ac9e007ed9d6b5229a4ef24a5d772","tests/derive.rs":"ea65d058a28fce8b54c0b707027907547a1e512038d621b778b1e2987f1a8755","tests/path.rs":"7e3e5fa26d5671ac19e99ba010a2fa0894fafe996c5d28ee587919e486d7c7c1"},"package":"c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "dc22fdefd5456a0f4d2f190c6d3e017e3c7ddd8e" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +name: Rust + +on: [push, pull_request] + +jobs: + vanilla_build: + name: Vanilla Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - name: Build + run: cargo build --verbose --all + - name: Run tests + run: cargo test --verbose --all + all_features_build: + name: All Features Enabled Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - name: Build + run: cargo build --verbose --all-features --all + - name: Run tests + run: cargo test --verbose --all-features --all + - name: Build Examples + run: cargo build --examples --all-features --all + msrv: + name: Minimum Supported Rust Version + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup toolchain add 1.63 + - name: Build + run: cargo +1.63 check --lib --all-features + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: rustup component add clippy + - run: cargo clippy --all-features --workspace -- -Dclippy::all + rustfmt: + name: Check rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: rustup component add rustfmt --toolchain stable + - run: cargo +stable fmt --all -- --check + fuzz: + name: Run `int_in_range` fuzz target + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - name: "Install nightly" + run: rustup toolchain install nightly && rustup default nightly + - name: "Install `cargo-fuzz`" + run: cargo install cargo-fuzz + - name: "Fuzz for 3 minutes" + run: cargo fuzz run int_in_range -- -max_total_time=$((3 * 60)) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,553 @@ +## Unreleased + +Released YYYY-MM-DD. + +### Added + +* TODO (or remove section if none) + +### Changed + +* TODO (or remove section if none) + +### Deprecated + +* TODO (or remove section if none) + +### Removed + +* TODO (or remove section if none) + +### Fixed + +* TODO (or remove section if none) + +### Security + +* TODO (or remove section if none) + +-------------------------------------------------------------------------------- + +## 1.4.2 + +Released 2025-08-13. + +### Added + +* Added formal MSRV policy: "We reserve the right to increment the MSRV on minor + releases, however we will strive to only do it deliberately and for good + reasons." The current MSRV is 1.63.0. +* Added an `Arbitrary` implementation for `core::cmp::Reverse`. + +### Changed + +* Landed a handful of changes to the code generated by `#[derive(Arbitrary)]` + that speed up compilation. + +### Fixed + +* Better documented bias and behavior when running out of entropy, fixed some + outdated and incorrect docs related to this. + +-------------------------------------------------------------------------------- + +## 1.4.1 + +Released 2024-11-05. + +-------------------------------------------------------------------------------- + +## 1.4.0 + +Released 2024-10-30. + +### Added + +* Added an `Arbitrary` implementation for `PhantomPinned`. +* Added the `Unstructured::choose_iter` helper method. +* Added `#[arbitrary(skip)]` for `enum` variants in the derive macro. +* Added the `Arbitrary::try_size_hint` trait method. + +### Changed + +* Implement `Arbitrary` for `PhantomData` even when `A` does not implement + `Arbitrary` and when `A` is `?Sized`. +* Make `usize`'s underlying encoding independent of machine word size so that + corpora are more portable. + +### Fixed + +* Make `derive(Arbitrary)` work for local definitions of `struct Option`. + +-------------------------------------------------------------------------------- + +## 1.3.2 + +Released 2023-10-30. + +### Added + +* Added `Arbitrary` implementations for `Arc<[T]>` and + `Rc<[T]>`. [#160](https://github.com/rust-fuzz/arbitrary/pull/160) + +-------------------------------------------------------------------------------- + +## 1.3.1 + +Released 2023-10-11. + +### Fixed + +* Fixed an issue with generating collections of collections in + `arbitrary_take_rest` where `>>::arbitrary_take_rest` would never + generate `vec![vec![]]` for example. See + [#159](https://github.com/rust-fuzz/arbitrary/pull/159) for details. + +-------------------------------------------------------------------------------- + +## 1.3.0 + +Released 2023-03-13. + +### Added + +* Added the ability to manually specify derived trait bounds for + `Arbitrary`. See [#138](https://github.com/rust-fuzz/arbitrary/pull/138) for + details. + +### Fixed + +* Fixed minimal versions correctness for `syn`. + +-------------------------------------------------------------------------------- + +## 1.2.3 + +Released 2023-01-20. + +### Fixed + +* The `derive(Arbitrary)` will now annotate the generated `impl`s with a `#[automatically_derived]` + attribute to indicate to e.g. clippy that lints should not fire for the code within the derived + implementation. + +## 1.2.2 + +Released 2023-01-03. + +### Fixed + +* Ensured that `arbitrary` and `derive_arbitrary` versions are synced up so that + they don't, e.g., emit generated code that depends on newer versions of + `arbitrary` than the one currently in + use. [#134](https://github.com/rust-fuzz/arbitrary/issues/134) + +## 1.2.1 + +### Fixed + +* Fixed an issue where `std::thread_local!` macro invocations in derive code + were not fully prefixed, causing confusing build errors in certain situations. + +## 1.2.0 + +Released 2022-10-20. + +### Added + +* Support custom arbitrary implementation for fields on + derive. [#129](https://github.com/rust-fuzz/arbitrary/pull/129) + +-------------------------------------------------------------------------------- + +## 1.1.6 + +Released 2022-09-20. + +### Fixed + +* Fixed a potential panic due to an off-by-one error in the `Arbitrary` + implementation for `std::ops::Bound`. + +-------------------------------------------------------------------------------- + +## 1.1.5 + +Released 2022-09-08. + +### Added + +* Implemented `Arbitrary` for `std::ops::Bound`. + +### Fixed + +* Fixed a bug where `Unstructured::int_in_range` could return out-of-range + integers when generating arbitrary signed integers. + +-------------------------------------------------------------------------------- + +## 1.1.4 + +Released 2022-08-29. + +### Added + +* Implemented `Arbitrary` for `Rc` and `Arc` + +### Changed + +* Allow overriding the error type in `arbitrary::Result` +* The `Unstructured::arbitrary_loop` method will consume fewer bytes of input + now. + +### Fixed + +* Fixed a bug where `Unstructured::int_in_range` could return out-of-range + integers. + +-------------------------------------------------------------------------------- + +## 1.1.3 + +Released 2022-06-23. + +### Fixed + +* Fixed some potential (but highly unlikely) name-clashes inside + `derive(Arbitrary)`'s generated + code. [#111](https://github.com/rust-fuzz/arbitrary/pull/111) +* Fixed an edge case where `derive(Arbitrary)` for recursive types that detected + an overflow would not reset the overflow + detection. [#111](https://github.com/rust-fuzz/arbitrary/pull/111) + +-------------------------------------------------------------------------------- + +## 1.1.2 + +Released 2022-06-16. + +### Fixed + +* Fixed a warning inside `derive(Arbitrary)`-generated + code. [#110](https://github.com/rust-fuzz/arbitrary/pull/110) + +-------------------------------------------------------------------------------- + +## 1.1.1 + +Released 2022-06-14. + +### Fixed + +* Fixed a stack overflow when using `derive(Arbitrary)` with recursive types and + empty inputs. [#109](https://github.com/rust-fuzz/arbitrary/pull/109) + +-------------------------------------------------------------------------------- + +## 1.1.0 + +Released 2022-02-09. + +### Added + +* Added the `Unstructured::ratio` method to generate a boolean that is `true` at + the given rate. + +* Added the `Unstructured::arbitrary_loop` method to call a function an + arbitrary number of times. + +-------------------------------------------------------------------------------- + +## 1.0.3 + +Released 2021-11-20. + +### Fixed + +* Fixed documentation for `Unstructured::fill_bytes`. We forgot to update this + way back in [#53](https://github.com/rust-fuzz/arbitrary/pull/53) when the + behavior changed. + +-------------------------------------------------------------------------------- + +## 1.0.2 + +Released 2021-08-25. + +### Added + +* `Arbitrary` impls for `HashMap`s and `HashSet`s with custom `Hasher`s + [#87](https://github.com/rust-fuzz/arbitrary/pull/87) + +-------------------------------------------------------------------------------- + +## 1.0.1 + +Released 2021-05-20. + +### Added + +* `Arbitrary` impls for `NonZeroX` types [#79](https://github.com/rust-fuzz/arbitrary/pull/79) +* `Arbitrary` impls for all arrays using const generics [#55](https://github.com/rust-fuzz/arbitrary/pull/55) +* `Arbitrary` impls for `Ipv4Addr` and `Ipv6Addr` [#84](https://github.com/rust-fuzz/arbitrary/pull/84) + +### Fixed + +* Use fewer bytes for `Unstructured::int_in_range()` [#80](https://github.com/rust-fuzz/arbitrary/pull/80) +* Use correct range for `char` generation [#83](https://github.com/rust-fuzz/arbitrary/pull/83) + +-------------------------------------------------------------------------------- + +## 1.0.0 + +Released 2020-02-24. + +See 1.0.0-rc1 and 1.0.0-rc2 for changes since 0.4.7, which was the last main +line release. + +-------------------------------------------------------------------------------- + +## 1.0.0-rc2 + +Released 2021-02-09. + +### Added + +* The `Arbitrary` trait is now implemented for `&[u8]`. [#67](https://github.com/rust-fuzz/arbitrary/pull/67) + +### Changed + +* Rename `Unstructured#get_bytes` to `Unstructured#bytes`. [#70](https://github.com/rust-fuzz/arbitrary/pull/70) +* Passing an empty slice of choices to `Unstructured#choose` returns an error. Previously it would panic. [71](https://github.com/rust-fuzz/arbitrary/pull/71) + +-------------------------------------------------------------------------------- + +## 1.0.0-rc1 + +Released 2020-11-25. + +### Added + +* The `Arbitrary` trait is now implemented for `&str`. [#63](https://github.com/rust-fuzz/arbitrary/pull/63) + +### Changed + +* The `Arbitrary` trait now has a lifetime parameter, allowing `Arbitrary` implementations that borrow from the raw input (e.g. the new `&str` implementaton). The `derive(Arbitrary)` macro also supports deriving `Arbitrary` on types with lifetimes now. [#63](https://github.com/rust-fuzz/arbitrary/pull/63) + +### Removed + +* The `shrink` method on the `Arbitrary` trait has been removed. + + We have found that, in practice, using [internal reduction](https://drmaciver.github.io/papers/reduction-via-generation-preview.pdf) via approaches like `cargo fuzz tmin`, where the raw input bytes are reduced rather than the `T: Arbitrary` type constructed from those raw bytes, has the best efficiency-to-maintenance ratio. To the best of our knowledge, no one is relying on or using the `Arbitrary::shrink` method. If you *are* using and relying on the `Arbitrary::shrink` method, please reach out by [dropping a comment here](https://github.com/rust-fuzz/arbitrary/issues/62) and explaining how you're using it and what your use case is. We'll figure out what the best solution is, including potentially adding shrinking functionality back to the `arbitrary` crate. + +-------------------------------------------------------------------------------- + +## 0.4.7 + +Released 2020-10-14. + +### Added + +* Added an optimization to avoid unnecessarily consuming bytes from the + underlying data when there is only one possible choice in + `Unstructured::{int_in_range, choose, etc..}`. + +* Added license files to the derive crate. + +### Changed + +* The `Arbitrary` implementation for `std::time::Duration` should now be faster + and produce durations with a more-uniform distribution of nanoseconds. + +-------------------------------------------------------------------------------- + +## 0.4.6 + +Released 2020-08-22. + +### Added + +* Added the `Unstructured::peek_bytes` method. + +### Changed + +* Test case reduction via `cargo fuzz tmin` should be much more effective at + reducing the sizes of collections now. (See + [#53](https://github.com/rust-fuzz/arbitrary/pull/53) and the commit messages + for details.) + +* Fuzzing with mutation-based fuzzers (like libFuzzer) should be more efficient + now. (See [#53](https://github.com/rust-fuzz/arbitrary/pull/53) and the commit + messages for details) + +-------------------------------------------------------------------------------- + +## 0.4.5 + +Released 2020-06-18. + +### Added + +* Implement `Arbitrary` for zero length arrays. +* Implement `Arbitrary` for `Range` and `RangeInclusive`. + +-------------------------------------------------------------------------------- + +## 0.4.4 + +Released 2020-04-29. + +### Fixed + +* Fixed the custom derive for enums when used via its full path (like + `#[derive(arbitrary::Arbitrary)]` rather than like `#[derive(Arbitrary)]`). + + +## 0.4.3 + +Released 2020-04-28. + +### Fixed + +* Fixed the custom derive when used via its full path (like + `#[derive(arbitrary::Arbitrary)]` rather than like `#[derive(Arbitrary)]`). + +-------------------------------------------------------------------------------- + +## 0.4.2 + +Released 2020-04-17. + +### Changed + +* We forgot to release a new version of the `derive_arbitrary` crate last + release. This release fixes that and so the `synstructure` dependency is + finally actually removed in the cargo releases. + +-------------------------------------------------------------------------------- + +## 0.4.1 + +Released 2020-03-18. + +### Removed + +* Removed an internal dependency on the `synstructure` crate when the `derive` + feature is enabled. This should not have any visible downstream effects other + than faster build times! + +-------------------------------------------------------------------------------- + +## 0.4.0 + +Released 2020-01-22. + +This is technically a breaking change, but we expect that nearly everyone should +be able to upgrade without any compilation errors. The only exception is if you +were implementing the `Arbitrary::size_hint` method by hand. If so, see the +"changed" section below and the [API docs for +`Arbitrary::shrink`](https://docs.rs/arbitrary/0.4.0/arbitrary/trait.Arbitrary.html#method.size_hint) +for details. + +### Added + +* Added [the `arbitary::size_hint::recursion_guard` helper + function][recursion_guard] for guarding against infinite recursion in + `size_hint` implementations for recursive types. + +### Changed + +* The `Arbitrary::size_hint` signature now takes a `depth: usize` + parameter. This should be passed along unmodified to any nested calls of other + `size_hint` methods. If you're implementing `size_hint` for a recursive type + (like a linked list or tree) or a generic type with type parameters, you + should use [the new `arbitrary::size_hint::recursion_guard` helper + function][recursion_guard]. + +### Fixed + +* Fixed infinite recursion in generated `size_hint` implementations + from `#[derive(Arbitrary)]` for recursive types. + +[recursion_guard]: https://docs.rs/arbitrary/0.4.0/arbitrary/size_hint/fn.recursion_guard.html + +-------------------------------------------------------------------------------- + +## 0.3.2 + +Released 2020-01-16. + +### Changed + +* Updated the custom derive's dependencies. + +-------------------------------------------------------------------------------- + +## 0.3.2 + +Released 2020-01-15. + +### Fixed + +* Fixed an over-eager assertion condition in `Unstructured::int_in_range` that + would incorrectly trigger when given valid ranges of length one. + +-------------------------------------------------------------------------------- + +## 0.3.1 + +Released 2020-01-14. + +### Fixed + +* Fixed some links and version numbers in README. + +-------------------------------------------------------------------------------- + +## 0.3.0 + +Released 2020-01-14. + +### Added + +* Added the `"derive"` cargo feature, to enable `#[derive(Arbitrary)]` for + custom types. Enabling this feature re-exports functionality from the + `derive_arbitrary` crate. +* The custom derive for `Arbitrary` implements the shrink method for you now. +* All implementations of `Arbitrary` for `std` types implement shrinking now. +* Added the `Arbitrary::arbitrary_take_rest` method allows an `Arbitrary` + implementation to consume all of the rest of the remaining raw input. It has a + default implementation that forwards to `Arbitrary::arbitrary` and the custom + derive creates a smart implementation for your custom types. +* Added the `Arbitrary::size_hint` method for hinting how many raw bytes an + implementation needs to construct itself. This has a default implementation, + but the custom derive creates a smart implementation for your custom types. +* Added the `Unstructured::choose` method to choose one thing among a set of + choices. +* Added the `Unstructured::arbitrary_len` method to get an arbitrary length for + a collection of some arbitrary type. +* Added the `Unstructured::arbitrary_iter` method to create an iterator of + arbitrary instance of some type. + +### Changed + +* The `Arbitrary` trait was simplified a bit. +* `Unstructured` is a concrete type now, not a trait. +* Switched to Rust 2018 edition. + +### Removed + +* `RingBuffer` and `FiniteBuffer` are removed. Use `Unstructured` instead. + +### Fixed + +* Better `Arbitrary` implementation for `char`. +* Better `Arbitrary` implementation for `String`. + +-------------------------------------------------------------------------------- + +## 0.2.0 + +-------------------------------------------------------------------------------- + +## 0.1.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.4.2" +dependencies = [ + "derive_arbitrary", + "exhaustigen", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "exhaustigen" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d88f747710a968a0a32ce4c4ae90ead21dc36a06aceabbb4367452679a95eb6" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63.0" +name = "arbitrary" +version = "1.4.2" +authors = [ + "The Rust-Fuzz Project Developers", + "Nick Fitzgerald ", + "Manish Goregaokar ", + "Simonas Kazlauskas ", + "Brian L. Troutwine ", + "Corey Farwell ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "The trait for generating structured data from unstructured data" +documentation = "https://docs.rs/arbitrary/" +readme = "README.md" +keywords = [ + "arbitrary", + "testing", +] +categories = ["development-tools::testing"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-fuzz/arbitrary/" + +[features] +derive = ["derive_arbitrary"] + +[lib] +name = "arbitrary" +path = "src/lib.rs" + +[[example]] +name = "derive_enum" +path = "examples/derive_enum.rs" +required-features = ["derive"] + +[[test]] +name = "bound" +path = "tests/bound.rs" + +[[test]] +name = "derive" +path = "tests/derive.rs" +required-features = ["derive"] + +[[test]] +name = "path" +path = "tests/path.rs" + +[dependencies.derive_arbitrary] +version = "~1.4.0" +optional = true + +[dev-dependencies.exhaustigen] +version = "0.1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +[package] +name = "arbitrary" +version = "1.4.2" # Make sure this matches the derive crate version (not including the patch version) +authors = [ + "The Rust-Fuzz Project Developers", + "Nick Fitzgerald ", + "Manish Goregaokar ", + "Simonas Kazlauskas ", + "Brian L. Troutwine ", + "Corey Farwell ", +] +categories = ["development-tools::testing"] +edition = "2021" +keywords = ["arbitrary", "testing"] +readme = "README.md" +description = "The trait for generating structured data from unstructured data" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-fuzz/arbitrary/" +documentation = "https://docs.rs/arbitrary/" +rust-version = "1.63.0" # Keep in sync with version documented in the README.md + +[dependencies] +derive_arbitrary = { version = "~1.4.0", path = "./derive", optional = true } + +[features] +# Turn this feature on to enable support for `#[derive(Arbitrary)]`. +derive = ["derive_arbitrary"] + +[[example]] +name = "derive_enum" +required-features = ["derive"] + +[[test]] +name = "derive" +path = "./tests/derive.rs" +required-features = ["derive"] + +[workspace] +members = ["./fuzz"] + +[dev-dependencies] +exhaustigen = "0.1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +MIT License + +Copyright (c) 2019 Manish Goregaokar + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/README.md clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +
+ +

Arbitrary

+ +

The trait for generating structured data from arbitrary, unstructured input.

+ + GitHub Actions Status + +
+ +## About + +The `Arbitrary` crate lets you construct arbitrary instances of a type. + +This crate is primarily intended to be combined with a fuzzer like [libFuzzer +and `cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz) or +[AFL](https://github.com/rust-fuzz/afl.rs), and to help you turn the raw, +untyped byte buffers that they produce into well-typed, valid, structured +values. This allows you to combine structure-aware test case generation with +coverage-guided, mutation-based fuzzers. + +## Documentation + +[**Read the API documentation on `docs.rs`!**](https://docs.rs/arbitrary) + +## Example + +Say you're writing a color conversion library, and you have an `Rgb` struct to +represent RGB colors. You might want to implement `Arbitrary` for `Rgb` so that +you could take arbitrary `Rgb` instances in a test function that asserts some +property (for example, asserting that RGB converted to HSL and converted back to +RGB always ends up exactly where we started). + +### Automatically Deriving `Arbitrary` + +Automatically deriving the `Arbitrary` trait is the recommended way to implement +`Arbitrary` for your types. + +Automatically deriving `Arbitrary` requires you to enable the `"derive"` cargo +feature: + +```toml +# Cargo.toml + +[dependencies] +arbitrary = { version = "1", features = ["derive"] } +``` + +And then you can simply add `#[derive(Arbitrary)]` annotations to your types: + +```rust +// rgb.rs + +use arbitrary::Arbitrary; + +#[derive(Arbitrary)] +pub struct Rgb { + pub r: u8, + pub g: u8, + pub b: u8, +} +``` + +#### Customizing single fields + +This can be particular handy if your structure uses a type that does not implement `Arbitrary` or you want to have more customization for particular fields. + +```rust +#[derive(Arbitrary)] +pub struct Rgba { + // set `r` to Default::default() + #[arbitrary(default)] + pub r: u8, + + // set `g` to 255 + #[arbitrary(value = 255)] + pub g: u8, + + // Generate `b` with a custom function of type + // + // fn(&mut Unstructured) -> arbitrary::Result + // + // where `T` is the field's type. + #[arbitrary(with = arbitrary_b)] + pub b: u8, + + // Generate `a` with a custom closure (shortcut to avoid a custom function) + #[arbitrary(with = |u: &mut Unstructured| u.int_in_range(0..=64))] + pub a: u8, +} + +fn arbitrary_b(u: &mut Unstructured) -> arbitrary::Result { + u.int_in_range(64..=128) +} +``` + +### Implementing `Arbitrary` By Hand + +Alternatively, you can write an `Arbitrary` implementation by hand: + +```rust +// rgb.rs + +use arbitrary::{Arbitrary, Result, Unstructured}; + +#[derive(Copy, Clone, Debug)] +pub struct Rgb { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl<'a> Arbitrary<'a> for Rgb { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let r = u8::arbitrary(u)?; + let g = u8::arbitrary(u)?; + let b = u8::arbitrary(u)?; + Ok(Rgb { r, g, b }) + } +} +``` + +## Minimum Supported Rust Version (MSRV) + + + +This crate is guaranteed to compile on stable Rust **1.63.0** and up. It might +compile with older versions but that may change in any new patch release. + +We reserve the right to increment the MSRV on minor releases, however we will +strive to only do it deliberately and for good reasons. + +## License + +Licensed under dual MIT or Apache-2.0 at your choice. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this project by you, as defined in the Apache-2.0 license, +shall be dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/examples/derive_enum.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/examples/derive_enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/examples/derive_enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/examples/derive_enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +//! A simple example of deriving the `Arbitrary` trait for an `enum`. +//! +//! Note that this requires enabling the "derive" cargo feature. + +// Various enums/fields that we are deriving `Arbitrary` for aren't actually +// used except to show off the derive. +#![allow(dead_code)] + +use arbitrary::{Arbitrary, Unstructured}; + +#[derive(Arbitrary, Debug)] +enum MyEnum { + Unit, + Tuple(bool, u32), + Struct { + x: i8, + y: (u8, i32), + }, + + #[arbitrary(skip)] + Skipped(usize), +} + +fn main() { + let raw = b"This is some raw, unstructured data!"; + + let mut unstructured = Unstructured::new(raw); + + let instance = MyEnum::arbitrary(&mut unstructured) + .expect("`unstructured` has enough underlying data to create all variants of `MyEnum`"); + + println!("Here is an arbitrary enum: {:?}", instance); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/publish.sh clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/publish.sh --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/publish.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/publish.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -eux + +cd $(dirname $0)/derive + +cargo publish + +cd .. + +# Let the crates.io index figure out we've published `derive_arbitrary` already. +sleep 5 + +cargo publish diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +use std::{error, fmt}; + +/// An enumeration of buffer creation errors +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// No choices were provided to the Unstructured::choose call + EmptyChoose, + /// There was not enough underlying data to fulfill some request for raw + /// bytes. + /// + /// Note that outside of [`Unstructured::bytes`][crate::Unstructured::bytes], + /// most APIs do *not* return this error when running out of underlying arbitrary bytes + /// but silently return some default value instead. + NotEnoughData, + /// The input bytes were not of the right format + IncorrectFormat, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::EmptyChoose => write!( + f, + "`arbitrary::Unstructured::choose` must be given a non-empty set of choices" + ), + Error::NotEnoughData => write!( + f, + "There is not enough underlying raw data to construct an `Arbitrary` instance" + ), + Error::IncorrectFormat => write!( + f, + "The raw data is not of the correct format to construct this type" + ), + } + } +} + +impl error::Error for Error {} + +/// A `Result` with the error type fixed as `arbitrary::Error`. +/// +/// Either an `Ok(T)` or `Err(arbitrary::Error)`. +pub type Result = std::result::Result; + +#[cfg(test)] +mod tests { + // Often people will import our custom `Result` type because 99.9% of + // results in a file will be `arbitrary::Result` but then have that one last + // 0.1% that want to have a custom error type. Don't make them prefix that + // 0.1% as `std::result::Result`; instead, let `arbitrary::Result` have an + // overridable error type. + #[test] + fn can_use_custom_error_types_with_result() -> super::Result<(), String> { + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/borrow.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/borrow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/borrow.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/borrow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + std::borrow::{Cow, ToOwned}, +}; + +impl<'a, A> Arbitrary<'a> for Cow<'a, A> +where + A: ToOwned + ?Sized + 'a, +
::Owned: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Cow::Owned) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + size_hint::try_recursion_guard(depth, |depth| { + <::Owned as Arbitrary>::try_size_hint(depth) + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/boxed.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/boxed.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/boxed.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/boxed.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + std::boxed::Box, +}; + +impl<'a, A> Arbitrary<'a> for Box +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + size_hint::try_recursion_guard(depth, ::try_size_hint) + } +} + +impl<'a, A> Arbitrary<'a> for Box<[A]> +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} + +impl<'a> Arbitrary<'a> for Box { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + ::arbitrary(u).map(|x| x.into_boxed_str()) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + ::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/binary_heap.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/binary_heap.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/binary_heap.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/binary_heap.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::collections::binary_heap::BinaryHeap, +}; + +impl<'a, A> Arbitrary<'a> for BinaryHeap +where + A: Arbitrary<'a> + Ord, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_map.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_map.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_map.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::collections::btree_map::BTreeMap, +}; + +impl<'a, K, V> Arbitrary<'a> for BTreeMap +where + K: Arbitrary<'a> + Ord, + V: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_set.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_set.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_set.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/btree_set.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::collections::btree_set::BTreeSet, +}; + +impl<'a, A> Arbitrary<'a> for BTreeSet +where + A: Arbitrary<'a> + Ord, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/linked_list.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/linked_list.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/linked_list.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/linked_list.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::collections::linked_list::LinkedList, +}; + +impl<'a, A> Arbitrary<'a> for LinkedList +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +mod binary_heap; +mod btree_map; +mod btree_set; +mod linked_list; +mod vec_deque; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/vec_deque.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/vec_deque.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/vec_deque.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/collections/vec_deque.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::collections::vec_deque::VecDeque, +}; + +impl<'a, A> Arbitrary<'a> for VecDeque +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/c_str.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/c_str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/c_str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/c_str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::ffi::CString, +}; + +impl<'a> Arbitrary<'a> for CString { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + as Arbitrary>::arbitrary(u).map(|mut x| { + x.retain(|&c| c != 0); + // SAFETY: all zero bytes have been removed + unsafe { Self::from_vec_unchecked(x) } + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + as Arbitrary>::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/ffi/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +mod c_str; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +//! Implementations of [`Arbitrary`] for [`alloc`] types, +//! excluding those in [`core`]. +//! +//! [`Arbitrary`]: crate::Arbitrary + +mod borrow; +mod boxed; +mod collections; +mod ffi; +mod rc; +mod string; +mod sync; +mod vec; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/rc.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/rc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/rc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/rc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + std::rc::Rc, +}; + +impl<'a, A> Arbitrary<'a> for Rc +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + size_hint::try_recursion_guard(depth, ::try_size_hint) + } +} + +impl<'a, A> Arbitrary<'a> for Rc<[A]> +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} + +impl<'a> Arbitrary<'a> for Rc { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + <&str as Arbitrary>::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/string.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/string.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/string.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/string.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::string::String, +}; + +impl<'a> Arbitrary<'a> for String { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + <&str as Arbitrary>::arbitrary_take_rest(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + <&str as Arbitrary>::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/sync.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/sync.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/sync.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/sync.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + std::sync::Arc, +}; + +impl<'a, A> Arbitrary<'a> for Arc +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + size_hint::try_recursion_guard(depth, ::try_size_hint) + } +} + +impl<'a, A> Arbitrary<'a> for Arc<[A]> +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} + +impl<'a> Arbitrary<'a> for Arc { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + <&str as Arbitrary>::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/vec.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/vec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/vec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/alloc/vec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::vec::Vec, +}; + +impl<'a, A> Arbitrary<'a> for Vec +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/array.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/array.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/array.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + core::{ + array, + mem::{self, MaybeUninit}, + ptr, + }, +}; + +/// Helper to safely create arrays since the standard library doesn't +/// provide one yet. Shouldn't be necessary in the future. +struct ArrayGuard { + dst: *mut T, + initialized: usize, +} + +impl Drop for ArrayGuard { + fn drop(&mut self) { + debug_assert!(self.initialized <= N); + let initialized_part = ptr::slice_from_raw_parts_mut(self.dst, self.initialized); + unsafe { + ptr::drop_in_place(initialized_part); + } + } +} + +fn try_create_array(mut cb: F) -> Result<[T; N]> +where + F: FnMut(usize) -> Result, +{ + let mut array: MaybeUninit<[T; N]> = MaybeUninit::uninit(); + let array_ptr = array.as_mut_ptr(); + let dst = array_ptr as _; + let mut guard: ArrayGuard = ArrayGuard { + dst, + initialized: 0, + }; + unsafe { + for (idx, value_ptr) in (*array.as_mut_ptr()).iter_mut().enumerate() { + ptr::write(value_ptr, cb(idx)?); + guard.initialized += 1; + } + mem::forget(guard); + Ok(array.assume_init()) + } +} + +impl<'a, T, const N: usize> Arbitrary<'a> for [T; N] +where + T: Arbitrary<'a>, +{ + #[inline] + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + try_create_array(|_| >::arbitrary(u)) + } + + #[inline] + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { + let mut array = Self::arbitrary(&mut u)?; + if let Some(last) = array.last_mut() { + *last = Arbitrary::arbitrary_take_rest(u)?; + } + Ok(array) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + let hint = ::try_size_hint(depth)?; + Ok(size_hint::and_all(&array::from_fn::<_, N, _>(|_| hint))) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/bool.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/bool.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/bool.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/bool.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +use crate::{Arbitrary, Result, Unstructured}; + +/// Returns false, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for bool { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(>::arbitrary(u)? & 1 == 1) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + >::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cell.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +use { + crate::{Arbitrary, MaxRecursionReached, Result, Unstructured}, + core::cell::{Cell, RefCell, UnsafeCell}, +}; + +impl<'a, A> Arbitrary<'a> for Cell +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + >::try_size_hint(depth) + } +} + +impl<'a, A> Arbitrary<'a> for RefCell +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + >::try_size_hint(depth) + } +} + +impl<'a, A> Arbitrary<'a> for UnsafeCell +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + >::try_size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/char.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/char.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/char.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/char.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +use crate::{Arbitrary, Result, Unstructured}; + +/// Returns '\0', not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for char { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + // The highest unicode code point is 0x11_FFFF + const CHAR_END: u32 = 0x11_0000; + // The size of the surrogate blocks + const SURROGATES_START: u32 = 0xD800; + let mut c = >::arbitrary(u)? % CHAR_END; + if let Some(c) = char::from_u32(c) { + Ok(c) + } else { + // We found a surrogate, wrap and try again + c -= SURROGATES_START; + Ok(char::from_u32(c) + .expect("Generated character should be valid! This is a bug in arbitrary-rs")) + } + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + >::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cmp.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cmp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cmp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/cmp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + core::cmp::Reverse, +}; + +impl<'a, A> Arbitrary<'a> for Reverse +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), crate::MaxRecursionReached> { + size_hint::try_recursion_guard(depth, ::try_size_hint) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/iter.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/iter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/iter.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/iter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + core::iter::{empty, Empty}, +}; + +impl<'a, A> Arbitrary<'a> for Empty +where + A: Arbitrary<'a>, +{ + fn arbitrary(_: &mut Unstructured<'a>) -> Result { + Ok(empty()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, Some(0)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/marker.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/marker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/marker.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/marker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + core::marker::{PhantomData, PhantomPinned}, +}; + +impl<'a, A> Arbitrary<'a> for PhantomData +where + A: ?Sized, +{ + fn arbitrary(_: &mut Unstructured<'a>) -> Result { + Ok(PhantomData) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, Some(0)) + } +} + +impl<'a> Arbitrary<'a> for PhantomPinned { + fn arbitrary(_: &mut Unstructured<'a>) -> Result { + Ok(PhantomPinned) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, Some(0)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +//! Implementations of [`Arbitrary`] for [`core`] types. +//! +//! [`Arbitrary`]: crate::Arbitrary + +mod array; +mod bool; +mod cell; +mod char; +mod cmp; +mod iter; +mod marker; +mod num; +mod ops; +mod option; +mod result; +mod slice; +mod str; +mod sync; +mod time; +mod tuple; +mod unit; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/num.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/num.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/num.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/num.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,141 @@ +use { + crate::{Arbitrary, Error, MaxRecursionReached, Result, Unstructured}, + core::{ + mem, + num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, + }, + }, +}; + +macro_rules! impl_arbitrary_for_integers { + ( $( $ty:ty; )* ) => { + $( + impl<'a> Arbitrary<'a> for $ty { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let mut buf = [0; mem::size_of::<$ty>()]; + u.fill_buffer(&mut buf)?; + Ok(Self::from_le_bytes(buf)) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + let n = mem::size_of::<$ty>(); + (n, Some(n)) + } + + } + )* + } +} + +impl_arbitrary_for_integers! { + u8; + u16; + u32; + u64; + u128; + i8; + i16; + i32; + i64; + i128; +} + +// Note: We forward Arbitrary for i/usize to i/u64 in order to simplify corpus +// compatibility between 32-bit and 64-bit builds. This introduces dead space in +// 32-bit builds but keeps the input layout independent of the build platform. +impl<'a> Arbitrary<'a> for usize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary::().map(|x| x as usize) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + ::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for isize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary::().map(|x| x as isize) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + ::size_hint(depth) + } +} + +macro_rules! impl_arbitrary_for_floats { + ( $( $ty:ident : $unsigned:ty; )* ) => { + $( + impl<'a> Arbitrary<'a> for $ty { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + <$unsigned as Arbitrary<'a>>::size_hint(depth) + } + } + )* + } +} + +impl_arbitrary_for_floats! { + f32: u32; + f64: u64; +} + +macro_rules! implement_nonzero_int { + ($nonzero:ty, $int:ty) => { + impl<'a> Arbitrary<'a> for $nonzero { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + match Self::new(<$int as Arbitrary<'a>>::arbitrary(u)?) { + Some(n) => Ok(n), + None => Err(Error::IncorrectFormat), + } + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + <$int as Arbitrary<'a>>::size_hint(depth) + } + } + }; +} + +implement_nonzero_int! { NonZeroI8, i8 } +implement_nonzero_int! { NonZeroI16, i16 } +implement_nonzero_int! { NonZeroI32, i32 } +implement_nonzero_int! { NonZeroI64, i64 } +implement_nonzero_int! { NonZeroI128, i128 } +implement_nonzero_int! { NonZeroIsize, isize } +implement_nonzero_int! { NonZeroU8, u8 } +implement_nonzero_int! { NonZeroU16, u16 } +implement_nonzero_int! { NonZeroU32, u32 } +implement_nonzero_int! { NonZeroU64, u64 } +implement_nonzero_int! { NonZeroU128, u128 } +implement_nonzero_int! { NonZeroUsize, usize } + +impl<'a, A> Arbitrary<'a> for Wrapping +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Wrapping) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + >::try_size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/ops.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/ops.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/ops.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/ops.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,127 @@ +use { + crate::{size_hint, Arbitrary, MaxRecursionReached, Result, Unstructured}, + core::{ + mem, + ops::{Bound, Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}, + }, +}; + +macro_rules! impl_range { + ( + $range:ty, + $value_closure:expr, + $value_ty:ty, + $fun:ident($fun_closure:expr), + $size_hint_closure:expr + ) => { + impl<'a, A> Arbitrary<'a> for $range + where + A: Arbitrary<'a> + Clone + PartialOrd, + { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let value: $value_ty = Arbitrary::arbitrary(u)?; + Ok($fun(value, $fun_closure)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + #[allow(clippy::redundant_closure_call)] + $size_hint_closure(depth) + } + } + }; +} +impl_range!( + Range, + |r: &Range| (r.start.clone(), r.end.clone()), + (A, A), + bounded_range(|(a, b)| a..b), + |depth| Ok(crate::size_hint::and( + ::try_size_hint(depth)?, + ::try_size_hint(depth)?, + )) +); +impl_range!( + RangeFrom, + |r: &RangeFrom| r.start.clone(), + A, + unbounded_range(|a| a..), + |depth| ::try_size_hint(depth) +); +impl_range!( + RangeInclusive, + |r: &RangeInclusive| (r.start().clone(), r.end().clone()), + (A, A), + bounded_range(|(a, b)| a..=b), + |depth| Ok(crate::size_hint::and( + ::try_size_hint(depth)?, + ::try_size_hint(depth)?, + )) +); +impl_range!( + RangeTo, + |r: &RangeTo| r.end.clone(), + A, + unbounded_range(|b| ..b), + |depth| ::try_size_hint(depth) +); +impl_range!( + RangeToInclusive, + |r: &RangeToInclusive| r.end.clone(), + A, + unbounded_range(|b| ..=b), + |depth| ::try_size_hint(depth) +); + +pub(crate) fn bounded_range(bounds: (I, I), cb: CB) -> R +where + CB: Fn((I, I)) -> R, + I: PartialOrd, + R: RangeBounds, +{ + let (mut start, mut end) = bounds; + if start > end { + mem::swap(&mut start, &mut end); + } + cb((start, end)) +} + +pub(crate) fn unbounded_range(bound: I, cb: CB) -> R +where + CB: Fn(I) -> R, + R: RangeBounds, +{ + cb(bound) +} + +impl<'a, A> Arbitrary<'a> for Bound +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + match u.int_in_range::(0..=2)? { + 0 => Ok(Bound::Included(A::arbitrary(u)?)), + 1 => Ok(Bound::Excluded(A::arbitrary(u)?)), + 2 => Ok(Bound::Unbounded), + _ => unreachable!(), + } + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + Ok(size_hint::or( + size_hint::and((1, Some(1)), A::try_size_hint(depth)?), + (1, Some(1)), + )) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/option.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/option.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/option.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/option.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +use crate::{size_hint, Arbitrary, MaxRecursionReached, Result, Unstructured}; + +/// Returns `None`, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a, A> Arbitrary<'a> for Option +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(if >::arbitrary(u)? { + Some(Arbitrary::arbitrary(u)?) + } else { + None + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + Ok(size_hint::and( + ::try_size_hint(depth)?, + size_hint::or((0, Some(0)), ::try_size_hint(depth)?), + )) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/result.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/result.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/result.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/result.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +use crate::{size_hint, Arbitrary, Error, MaxRecursionReached, Unstructured}; + +impl<'a, T, E> Arbitrary<'a> for Result +where + T: Arbitrary<'a>, + E: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(if >::arbitrary(u)? { + Ok(::arbitrary(u)?) + } else { + Err(::arbitrary(u)?) + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + Ok(size_hint::and( + ::size_hint(depth), + size_hint::or( + ::try_size_hint(depth)?, + ::try_size_hint(depth)?, + ), + )) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/slice.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/slice.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/slice.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/slice.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +use crate::{Arbitrary, Result, Unstructured}; + +impl<'a> Arbitrary<'a> for &'a [u8] { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let len = u.arbitrary_len::()?; + u.bytes(len) + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + Ok(u.take_rest()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/str.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + core::str, +}; + +fn arbitrary_str<'a>(u: &mut Unstructured<'a>, size: usize) -> Result<&'a str> { + match str::from_utf8(u.peek_bytes(size).unwrap()) { + Ok(s) => { + u.bytes(size).unwrap(); + Ok(s) + } + Err(e) => { + let i = e.valid_up_to(); + let valid = u.bytes(i).unwrap(); + let s = unsafe { + debug_assert!(str::from_utf8(valid).is_ok()); + str::from_utf8_unchecked(valid) + }; + Ok(s) + } + } +} + +impl<'a> Arbitrary<'a> for &'a str { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let size = u.arbitrary_len::()?; + arbitrary_str(u, size) + } + + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { + let size = u.len(); + arbitrary_str(&mut u, size) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/atomic.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/atomic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/atomic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/atomic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + core::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize}, +}; + +/// Returns false, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for AtomicBool { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + >::size_hint(depth) + } +} + +/// Returns zero, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for AtomicIsize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + >::size_hint(depth) + } +} + +/// Returns zero, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for AtomicUsize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + >::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/sync/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +mod atomic; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/time.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/time.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/time.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/time.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + core::time::Duration, +}; + +/// Returns zero, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. +impl<'a> Arbitrary<'a> for Duration { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(Self::new( + ::arbitrary(u)?, + u.int_in_range(0..=999_999_999)?, + )) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + size_hint::and( + ::size_hint(depth), + ::size_hint(depth), + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/tuple.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/tuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/tuple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/tuple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +use crate::{size_hint, Arbitrary, MaxRecursionReached, Result, Unstructured}; + +macro_rules! arbitrary_tuple { + () => {}; + ($last: ident $($xs: ident)*) => { + arbitrary_tuple!($($xs)*); + + impl<'a, $($xs,)* $last> Arbitrary<'a> for ($($xs,)* $last,) + where + $($xs: Arbitrary<'a>,)* + $last: Arbitrary<'a>, + { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) + } + + #[allow(unused_mut, non_snake_case)] + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { + $(let $xs = $xs::arbitrary(&mut u)?;)* + let $last = $last::arbitrary_take_rest(u)?; + Ok(($($xs,)* $last,)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + Ok(size_hint::and_all(&[ + <$last as Arbitrary>::try_size_hint(depth)?, + $( <$xs as Arbitrary>::try_size_hint(depth)?),* + ])) + } + } + }; +} +arbitrary_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/unit.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/unit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/core/unit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/core/unit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use crate::{Arbitrary, Result, Unstructured}; + +impl<'a> Arbitrary<'a> for () { + fn arbitrary(_: &mut Unstructured<'a>) -> Result { + Ok(()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, Some(0)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +//! Implementations of [`Arbitrary`] for foreign types. +//! +//! [`Arbitrary`]: crate::Arbitrary + +mod alloc; +mod core; +mod std; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_map.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_map.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_map.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::{ + collections::hash_map::HashMap, + hash::{BuildHasher, Hash}, + }, +}; + +impl<'a, K, V, S> Arbitrary<'a> for HashMap +where + K: Arbitrary<'a> + Eq + Hash, + V: Arbitrary<'a>, + S: BuildHasher + Default, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_set.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_set.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_set.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/hash_set.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::{ + collections::hash_set::HashSet, + hash::{BuildHasher, Hash}, + }, +}; + +impl<'a, A, S> Arbitrary<'a> for HashSet +where + A: Arbitrary<'a> + Eq + Hash, + S: BuildHasher + Default, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (0, None) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/collections/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +mod hash_map; +mod hash_set; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/c_str.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/c_str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/c_str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/c_str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +// impl Arbitrary for Box { +// fn arbitrary(u: &mut Unstructured<'_>) -> Result { +// ::arbitrary(u).map(|x| x.into_boxed_c_str()) +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +mod c_str; +mod os_str; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/os_str.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/os_str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/os_str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/ffi/os_str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::ffi::OsString, +}; + +impl<'a> Arbitrary<'a> for OsString { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + ::arbitrary(u).map(From::from) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + ::size_hint(depth) + } +} + +// impl Arbitrary for Box { +// fn arbitrary(u: &mut Unstructured<'_>) -> Result { +// ::arbitrary(u).map(|x| x.into_boxed_osstr()) +// +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +//! Implementations of [`Arbitrary`] for [`std`] types, +//! excluding those in [`core`] and [`alloc`]. +//! +//! [`Arbitrary`]: crate::Arbitrary + +mod collections; +mod ffi; +mod net; +mod path; +mod sync; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/net.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/net.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/net.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/net.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +use { + crate::{size_hint, Arbitrary, Result, Unstructured}, + std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, +}; + +impl<'a> Arbitrary<'a> for Ipv4Addr { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(Ipv4Addr::from(u32::arbitrary(u)?)) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (4, Some(4)) + } +} + +impl<'a> Arbitrary<'a> for Ipv6Addr { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(Ipv6Addr::from(u128::arbitrary(u)?)) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option) { + (16, Some(16)) + } +} + +impl<'a> Arbitrary<'a> for IpAddr { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + if u.arbitrary()? { + Ok(IpAddr::V4(u.arbitrary()?)) + } else { + Ok(IpAddr::V6(u.arbitrary()?)) + } + } + + fn size_hint(depth: usize) -> (usize, Option) { + size_hint::and( + bool::size_hint(depth), + size_hint::or(Ipv4Addr::size_hint(depth), Ipv6Addr::size_hint(depth)), + ) + } +} + +impl<'a> Arbitrary<'a> for SocketAddrV4 { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(SocketAddrV4::new(u.arbitrary()?, u.arbitrary()?)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + size_hint::and(Ipv4Addr::size_hint(depth), u16::size_hint(depth)) + } +} + +impl<'a> Arbitrary<'a> for SocketAddrV6 { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Ok(SocketAddrV6::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + )) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + size_hint::and( + Ipv6Addr::size_hint(depth), + size_hint::and( + u16::size_hint(depth), + size_hint::and(u32::size_hint(depth), u32::size_hint(depth)), + ), + ) + } +} + +impl<'a> Arbitrary<'a> for SocketAddr { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + if u.arbitrary()? { + Ok(SocketAddr::V4(u.arbitrary()?)) + } else { + Ok(SocketAddr::V6(u.arbitrary()?)) + } + } + + fn size_hint(depth: usize) -> (usize, Option) { + size_hint::and( + bool::size_hint(depth), + size_hint::or( + SocketAddrV4::size_hint(depth), + SocketAddrV6::size_hint(depth), + ), + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/path.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +use { + crate::{Arbitrary, Result, Unstructured}, + std::{ffi::OsString, path::PathBuf}, +}; + +impl<'a> Arbitrary<'a> for PathBuf { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + ::arbitrary(u).map(From::from) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + ::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/sync.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/sync.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/foreign/std/sync.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/foreign/std/sync.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +use { + crate::{Arbitrary, MaxRecursionReached, Result, Unstructured}, + std::sync::Mutex, +}; + +impl<'a, A> Arbitrary<'a> for Mutex +where + A: Arbitrary<'a>, +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + Self::try_size_hint(depth).unwrap_or_default() + } + + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + A::try_size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,608 @@ +// Copyright © 2019 The Rust Fuzz Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The `Arbitrary` trait crate. +//! +//! This trait provides an [`Arbitrary`] trait to +//! produce well-typed, structured values, from raw, byte buffers. It is +//! generally intended to be used with fuzzers like AFL or libFuzzer. See the +//! [`Arbitrary`] trait's documentation for details on +//! automatically deriving, implementing, and/or using the trait. + +#![deny(bad_style)] +#![deny(missing_docs)] +#![deny(future_incompatible)] +#![deny(nonstandard_style)] +#![deny(rust_2018_compatibility)] +#![deny(rust_2018_idioms)] +#![deny(unused)] + +mod error; +mod foreign; +pub mod size_hint; +pub mod unstructured; + +#[cfg(test)] +mod tests; + +pub use error::*; + +#[cfg(feature = "derive_arbitrary")] +pub use derive_arbitrary::*; + +#[doc(inline)] +pub use unstructured::Unstructured; + +/// Error indicating that the maximum recursion depth has been reached while calculating [`Arbitrary::size_hint`]() +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct MaxRecursionReached {} + +impl core::fmt::Display for MaxRecursionReached { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str("Maximum recursion depth has been reached") + } +} + +impl std::error::Error for MaxRecursionReached {} + +/// Generate arbitrary structured values from raw, unstructured data. +/// +/// The `Arbitrary` trait allows you to generate valid structured values, like +/// `HashMap`s, or ASTs, or `MyTomlConfig`, or any other data structure from +/// raw, unstructured bytes provided by a fuzzer. +/// +/// # Deriving `Arbitrary` +/// +/// Automatically deriving the `Arbitrary` trait is the recommended way to +/// implement `Arbitrary` for your types. +/// +/// Using the custom derive requires that you enable the `"derive"` cargo +/// feature in your `Cargo.toml`: +/// +/// ```toml +/// [dependencies] +/// arbitrary = { version = "1", features = ["derive"] } +/// ``` +/// +/// Then, you add the `#[derive(Arbitrary)]` annotation to your `struct` or +/// `enum` type definition: +/// +/// ``` +/// # #[cfg(feature = "derive")] mod foo { +/// use arbitrary::Arbitrary; +/// use std::collections::HashSet; +/// +/// #[derive(Arbitrary)] +/// pub struct AddressBook { +/// friends: HashSet, +/// } +/// +/// #[derive(Arbitrary, Hash, Eq, PartialEq)] +/// pub enum Friend { +/// Buddy { name: String }, +/// Pal { age: usize }, +/// } +/// # } +/// ``` +/// +/// Every member of the `struct` or `enum` must also implement `Arbitrary`. +/// +/// It is also possible to change the default bounds added by the derive: +/// +/// ``` +/// # #[cfg(feature = "derive")] mod foo { +/// use arbitrary::Arbitrary; +/// +/// trait Trait { +/// type Assoc: for<'a> Arbitrary<'a>; +/// } +/// +/// #[derive(Arbitrary)] +/// // The bounds are used verbatim, so any existing trait bounds will need to be repeated. +/// #[arbitrary(bound = "T: Trait")] +/// struct Point { +/// x: T::Assoc, +/// } +/// # } +/// ``` +/// +/// # Implementing `Arbitrary` By Hand +/// +/// Implementing `Arbitrary` mostly involves nested calls to other `Arbitrary` +/// arbitrary implementations for each of your `struct` or `enum`'s members. But +/// sometimes you need some amount of raw data, or you need to generate a +/// variably-sized collection type, or something of that sort. The +/// [`Unstructured`] type helps you with these tasks. +/// +/// ``` +/// # #[cfg(feature = "derive")] mod foo { +/// # pub struct MyCollection { _t: std::marker::PhantomData } +/// # impl MyCollection { +/// # pub fn new() -> Self { MyCollection { _t: std::marker::PhantomData } } +/// # pub fn insert(&mut self, element: T) {} +/// # } +/// use arbitrary::{Arbitrary, Result, Unstructured}; +/// +/// impl<'a, T> Arbitrary<'a> for MyCollection +/// where +/// T: Arbitrary<'a>, +/// { +/// fn arbitrary(u: &mut Unstructured<'a>) -> Result { +/// // Get an iterator of arbitrary `T`s. +/// let iter = u.arbitrary_iter::()?; +/// +/// // And then create a collection! +/// let mut my_collection = MyCollection::new(); +/// for elem_result in iter { +/// let elem = elem_result?; +/// my_collection.insert(elem); +/// } +/// +/// Ok(my_collection) +/// } +/// } +/// # } +/// ``` +/// +/// # A Note On Output Distributions +/// +/// There is no requirement for a particular distribution of the values. For +/// example, it is not required that every value appears with the same +/// probability. That being said, the main use for `Arbitrary` is for fuzzing, +/// so in many cases a uniform distribution will make the most sense in order to +/// provide the best coverage of the domain. In other cases this is not +/// desirable or even possible, for example when sampling from a uniform +/// distribution is computationally expensive or in the case of collections that +/// may grow indefinitely. +pub trait Arbitrary<'a>: Sized { + /// Generate an arbitrary value of `Self` from the given unstructured data. + /// + /// Calling `Arbitrary::arbitrary` requires that you have some raw data, + /// perhaps given to you by a fuzzer like AFL or libFuzzer. You wrap this + /// raw data in an `Unstructured`, and then you can call `::arbitrary` to construct an arbitrary instance of `MyType` + /// from that unstructured data. + /// + /// Implementations may return an error if there is not enough data to + /// construct a full instance of `Self`, or they may fill out the rest of + /// `Self` with dummy values. Using dummy values when the underlying data is + /// exhausted can help avoid accidentally "defeating" some of the fuzzer's + /// mutations to the underlying byte stream that might otherwise lead to + /// interesting runtime behavior or new code coverage if only we had just a + /// few more bytes. However, it also requires that implementations for + /// recursive types (e.g. `struct Foo(Option>)`) avoid infinite + /// recursion when the underlying data is exhausted. + /// + /// ``` + /// # #[cfg(feature = "derive")] fn foo() { + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// #[derive(Arbitrary)] + /// pub struct MyType { + /// // ... + /// } + /// + /// // Get the raw data from the fuzzer or wherever else. + /// # let get_raw_data_from_fuzzer = || &[]; + /// let raw_data: &[u8] = get_raw_data_from_fuzzer(); + /// + /// // Wrap that raw data in an `Unstructured`. + /// let mut unstructured = Unstructured::new(raw_data); + /// + /// // Generate an arbitrary instance of `MyType` and do stuff with it. + /// if let Ok(value) = MyType::arbitrary(&mut unstructured) { + /// # let do_stuff = |_| {}; + /// do_stuff(value); + /// } + /// # } + /// ``` + /// + /// See also the documentation for [`Unstructured`]. + fn arbitrary(u: &mut Unstructured<'a>) -> Result; + + /// Generate an arbitrary value of `Self` from the entirety of the given + /// unstructured data. + /// + /// This is similar to Arbitrary::arbitrary, however it assumes that it is + /// the last consumer of the given data, and is thus able to consume it all + /// if it needs. See also the documentation for + /// [`Unstructured`]. + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { + Self::arbitrary(&mut u) + } + + /// Get a size hint for how many bytes out of an `Unstructured` this type + /// needs to construct itself. + /// + /// This is useful for determining how many elements we should insert when + /// creating an arbitrary collection. + /// + /// The return value is similar to [`Iterator::size_hint`]: it returns a + /// tuple where the first element is a lower bound on the number of bytes + /// required, and the second element is an optional upper bound. + /// + /// The default implementation return `(0, None)` which is correct for any + /// type, but not ultimately that useful. Using `#[derive(Arbitrary)]` will + /// create a better implementation. If you are writing an `Arbitrary` + /// implementation by hand, and your type can be part of a dynamically sized + /// collection (such as `Vec`), you are strongly encouraged to override this + /// default with a better implementation, and also override + /// [`try_size_hint`]. + /// + /// ## How to implement this + /// + /// If the size hint calculation is a trivial constant and does not recurse + /// into any other `size_hint` call, you should implement it in `size_hint`: + /// + /// ``` + /// use arbitrary::{size_hint, Arbitrary, Result, Unstructured}; + /// + /// struct SomeStruct(u8); + /// + /// impl<'a> Arbitrary<'a> for SomeStruct { + /// fn arbitrary(u: &mut Unstructured<'a>) -> Result { + /// let buf = &mut [0]; + /// u.fill_buffer(buf)?; + /// Ok(SomeStruct(buf[0])) + /// } + /// + /// #[inline] + /// fn size_hint(depth: usize) -> (usize, Option) { + /// let _ = depth; + /// (1, Some(1)) + /// } + /// } + /// ``` + /// + /// Otherwise, it should instead be implemented in [`try_size_hint`], + /// and the `size_hint` implementation should forward to it: + /// + /// ``` + /// use arbitrary::{size_hint, Arbitrary, MaxRecursionReached, Result, Unstructured}; + /// + /// struct SomeStruct { + /// a: A, + /// b: B, + /// } + /// + /// impl<'a, A: Arbitrary<'a>, B: Arbitrary<'a>> Arbitrary<'a> for SomeStruct { + /// fn arbitrary(u: &mut Unstructured<'a>) -> Result { + /// // ... + /// # todo!() + /// } + /// + /// fn size_hint(depth: usize) -> (usize, Option) { + /// // Return the value of try_size_hint + /// // + /// // If the recursion fails, return the default, always valid `(0, None)` + /// Self::try_size_hint(depth).unwrap_or_default() + /// } + /// + /// fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + /// // Protect against potential infinite recursion with + /// // `try_recursion_guard`. + /// size_hint::try_recursion_guard(depth, |depth| { + /// // If we aren't too deep, then `recursion_guard` calls + /// // this closure, which implements the natural size hint. + /// // Don't forget to use the new `depth` in all nested + /// // `try_size_hint` calls! We recommend shadowing the + /// // parameter, like what is done here, so that you can't + /// // accidentally use the wrong depth. + /// Ok(size_hint::and( + /// ::try_size_hint(depth)?, + /// ::try_size_hint(depth)?, + /// )) + /// }) + /// } + /// } + /// ``` + /// + /// ## Invariant + /// + /// It must be possible to construct every possible output using only inputs + /// of lengths bounded by these parameters. This applies to both + /// [`Arbitrary::arbitrary`] and [`Arbitrary::arbitrary_take_rest`]. + /// + /// This is trivially true for `(0, None)`. To restrict this further, it + /// must be proven that all inputs that are now excluded produced redundant + /// outputs which are still possible to produce using the reduced input + /// space. + /// + /// [iterator-size-hint]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.size_hint + /// [`try_size_hint`]: Arbitrary::try_size_hint + #[inline] + fn size_hint(depth: usize) -> (usize, Option) { + let _ = depth; + (0, None) + } + + /// Get a size hint for how many bytes out of an `Unstructured` this type + /// needs to construct itself. + /// + /// Unlike [`size_hint`], this function keeps the information that the + /// recursion limit was reached. This is required to "short circuit" the + /// calculation and avoid exponential blowup with recursive structures. + /// + /// If you are implementing [`size_hint`] for a struct that could be + /// recursive, you should implement `try_size_hint` and call the + /// `try_size_hint` when recursing + /// + /// + /// The return value is similar to [`core::iter::Iterator::size_hint`]: it + /// returns a tuple where the first element is a lower bound on the number + /// of bytes required, and the second element is an optional upper bound. + /// + /// The default implementation returns the value of [`size_hint`] which is + /// correct for any type, but might lead to exponential blowup when dealing + /// with recursive types. + /// + /// ## Invariant + /// + /// It must be possible to construct every possible output using only inputs + /// of lengths bounded by these parameters. This applies to both + /// [`Arbitrary::arbitrary`] and [`Arbitrary::arbitrary_take_rest`]. + /// + /// This is trivially true for `(0, None)`. To restrict this further, it + /// must be proven that all inputs that are now excluded produced redundant + /// outputs which are still possible to produce using the reduced input + /// space. + /// + /// ## When to implement `try_size_hint` + /// + /// If you 100% know that the type you are implementing `Arbitrary` for is + /// not a recursive type, or your implementation is not transitively calling + /// any other `size_hint` methods, you may implement [`size_hint`], and the + /// default `try_size_hint` implementation will use it. + /// + /// Note that if you are implementing `Arbitrary` for a generic type, you + /// cannot guarantee the lack of type recursion! + /// + /// Otherwise, when there is possible type recursion, you should implement + /// `try_size_hint` instead. + /// + /// ## The `depth` parameter + /// + /// When implementing `try_size_hint`, you need to use + /// [`arbitrary::size_hint::try_recursion_guard(depth)`][crate::size_hint::try_recursion_guard] + /// to prevent potential infinite recursion when calculating size hints for + /// potentially recursive types: + /// + /// ``` + /// use arbitrary::{size_hint, Arbitrary, MaxRecursionReached, Unstructured}; + /// + /// // This can potentially be a recursive type if `L` or `R` contain + /// // something like `Box>>`! + /// enum MyEither { + /// Left(L), + /// Right(R), + /// } + /// + /// impl<'a, L, R> Arbitrary<'a> for MyEither + /// where + /// L: Arbitrary<'a>, + /// R: Arbitrary<'a>, + /// { + /// fn arbitrary(u: &mut Unstructured) -> arbitrary::Result { + /// // ... + /// # unimplemented!() + /// } + /// + /// fn size_hint(depth: usize) -> (usize, Option) { + /// // Return the value of `try_size_hint` + /// // + /// // If the recursion fails, return the default `(0, None)` range, + /// // which is always valid. + /// Self::try_size_hint(depth).unwrap_or_default() + /// } + /// + /// fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + /// // Protect against potential infinite recursion with + /// // `try_recursion_guard`. + /// size_hint::try_recursion_guard(depth, |depth| { + /// // If we aren't too deep, then `recursion_guard` calls + /// // this closure, which implements the natural size hint. + /// // Don't forget to use the new `depth` in all nested + /// // `try_size_hint` calls! We recommend shadowing the + /// // parameter, like what is done here, so that you can't + /// // accidentally use the wrong depth. + /// Ok(size_hint::or( + /// ::try_size_hint(depth)?, + /// ::try_size_hint(depth)?, + /// )) + /// }) + /// } + /// } + /// ``` + #[inline] + fn try_size_hint(depth: usize) -> Result<(usize, Option), MaxRecursionReached> { + Ok(Self::size_hint(depth)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn exhausted_entropy() { + let mut u = Unstructured::new(&[]); + assert_eq!(u.arbitrary::().unwrap(), false); + assert_eq!(u.arbitrary::().unwrap(), 0); + assert_eq!(u.arbitrary::().unwrap(), 0); + assert_eq!(u.arbitrary::().unwrap(), 0.0); + assert_eq!(u.arbitrary::().unwrap(), 0.0); + assert_eq!(u.arbitrary::>().unwrap(), None); + assert_eq!(u.int_in_range(4..=100).unwrap(), 4); + assert_eq!(u.choose_index(10).unwrap(), 0); + assert_eq!(u.ratio(5, 7).unwrap(), true); + } +} + +/// Multiple conflicting arbitrary attributes are used on the same field: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// struct Point { +/// #[arbitrary(value = 2)] +/// #[arbitrary(value = 2)] +/// x: i32, +/// } +/// ``` +/// +/// An unknown attribute: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// struct Point { +/// #[arbitrary(unknown_attr)] +/// x: i32, +/// } +/// ``` +/// +/// An unknown attribute with a value: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// struct Point { +/// #[arbitrary(unknown_attr = 13)] +/// x: i32, +/// } +/// ``` +/// +/// `value` without RHS: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// struct Point { +/// #[arbitrary(value)] +/// x: i32, +/// } +/// ``` +/// +/// `with` without RHS: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// struct Point { +/// #[arbitrary(with)] +/// x: i32, +/// } +/// ``` +/// +/// Multiple conflicting bounds at the container-level: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// #[arbitrary(bound = "T: Default")] +/// #[arbitrary(bound = "T: Default")] +/// struct Point { +/// #[arbitrary(default)] +/// x: T, +/// } +/// ``` +/// +/// Multiple conflicting bounds in a single bound attribute: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// #[arbitrary(bound = "T: Default, T: Default")] +/// struct Point { +/// #[arbitrary(default)] +/// x: T, +/// } +/// ``` +/// +/// Multiple conflicting bounds in multiple bound attributes: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// #[arbitrary(bound = "T: Default", bound = "T: Default")] +/// struct Point { +/// #[arbitrary(default)] +/// x: T, +/// } +/// ``` +/// +/// Too many bounds supplied: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// #[arbitrary(bound = "T: Default")] +/// struct Point { +/// x: i32, +/// } +/// ``` +/// +/// Too many bounds supplied across multiple attributes: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// #[arbitrary(bound = "T: Default")] +/// #[arbitrary(bound = "U: Default")] +/// struct Point { +/// #[arbitrary(default)] +/// x: T, +/// } +/// ``` +/// +/// Attempt to use the derive attribute on an enum variant: +/// ```compile_fail +/// #[derive(::arbitrary::Arbitrary)] +/// enum Enum { +/// #[arbitrary(default)] +/// Variant(T), +/// } +/// ``` +#[cfg(all(doctest, feature = "derive"))] +pub struct CompileFailTests; + +// Support for `#[derive(Arbitrary)]`. +#[doc(hidden)] +#[cfg(feature = "derive")] +pub mod details { + use super::*; + + // Hidden trait that papers over the difference between `&mut Unstructured` and + // `Unstructured` arguments so that `with_recursive_count` can be used for both + // `arbitrary` and `arbitrary_take_rest`. + pub trait IsEmpty { + fn is_empty(&self) -> bool; + } + + impl IsEmpty for Unstructured<'_> { + fn is_empty(&self) -> bool { + Unstructured::is_empty(self) + } + } + + impl IsEmpty for &mut Unstructured<'_> { + fn is_empty(&self) -> bool { + Unstructured::is_empty(self) + } + } + + // Calls `f` with a recursive count guard. + #[inline] + pub fn with_recursive_count( + u: U, + recursive_count: &'static std::thread::LocalKey>, + f: impl FnOnce(U) -> Result, + ) -> Result { + let guard_against_recursion = u.is_empty(); + if guard_against_recursion { + recursive_count.with(|count| { + if count.get() > 0 { + return Err(Error::NotEnoughData); + } + count.set(count.get() + 1); + Ok(()) + })?; + } + + let result = f(u); + + if guard_against_recursion { + recursive_count.with(|count| { + count.set(count.get() - 1); + }); + } + + result + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/size_hint.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/size_hint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/size_hint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/size_hint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,149 @@ +//! Utilities for working with and combining the results of +//! [`Arbitrary::size_hint`][crate::Arbitrary::size_hint]. + +pub(crate) const MAX_DEPTH: usize = 20; + +/// Protects against potential infinite recursion when calculating size hints +/// due to indirect type recursion. +/// +/// When the depth is not too deep, calls `f` with `depth + 1` to calculate the +/// size hint. +/// +/// Otherwise, returns the default size hint: `(0, None)`. +/// +/// +#[inline] +#[deprecated(note = "use `try_recursion_guard` instead")] +pub fn recursion_guard( + depth: usize, + f: impl FnOnce(usize) -> (usize, Option), +) -> (usize, Option) { + if depth > MAX_DEPTH { + (0, None) + } else { + f(depth + 1) + } +} + +/// Protects against potential infinite recursion when calculating size hints +/// due to indirect type recursion. +/// +/// When the depth is not too deep, calls `f` with `depth + 1` to calculate the +/// size hint. +/// +/// Otherwise, returns an error. +/// +/// This should be used when implementing [`try_size_hint`](crate::Arbitrary::try_size_hint) +#[inline] +pub fn try_recursion_guard( + depth: usize, + f: impl FnOnce(usize) -> Result<(usize, Option), crate::MaxRecursionReached>, +) -> Result<(usize, Option), crate::MaxRecursionReached> { + if depth > MAX_DEPTH { + Err(crate::MaxRecursionReached {}) + } else { + f(depth + 1) + } +} + +/// Take the sum of the `lhs` and `rhs` size hints. +#[inline] +pub fn and(lhs: (usize, Option), rhs: (usize, Option)) -> (usize, Option) { + let lower = lhs.0 + rhs.0; + let upper = lhs.1.and_then(|lhs| rhs.1.map(|rhs| lhs + rhs)); + (lower, upper) +} + +/// Take the sum of all of the given size hints. +/// +/// If `hints` is empty, returns `(0, Some(0))`, aka the size of consuming +/// nothing. +#[inline] +pub fn and_all(hints: &[(usize, Option)]) -> (usize, Option) { + hints.iter().copied().fold((0, Some(0)), and) +} + +/// Take the minimum of the lower bounds and maximum of the upper bounds in the +/// `lhs` and `rhs` size hints. +#[inline] +pub fn or(lhs: (usize, Option), rhs: (usize, Option)) -> (usize, Option) { + let lower = std::cmp::min(lhs.0, rhs.0); + let upper = lhs + .1 + .and_then(|lhs| rhs.1.map(|rhs| std::cmp::max(lhs, rhs))); + (lower, upper) +} + +/// Take the maximum of the `lhs` and `rhs` size hints. +/// +/// If `hints` is empty, returns `(0, Some(0))`, aka the size of consuming +/// nothing. +#[inline] +pub fn or_all(hints: &[(usize, Option)]) -> (usize, Option) { + if let Some(head) = hints.first().copied() { + hints[1..].iter().copied().fold(head, or) + } else { + (0, Some(0)) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn and() { + assert_eq!((5, Some(5)), super::and((2, Some(2)), (3, Some(3)))); + assert_eq!((5, None), super::and((2, Some(2)), (3, None))); + assert_eq!((5, None), super::and((2, None), (3, Some(3)))); + assert_eq!((5, None), super::and((2, None), (3, None))); + } + + #[test] + fn or() { + assert_eq!((2, Some(3)), super::or((2, Some(2)), (3, Some(3)))); + assert_eq!((2, None), super::or((2, Some(2)), (3, None))); + assert_eq!((2, None), super::or((2, None), (3, Some(3)))); + assert_eq!((2, None), super::or((2, None), (3, None))); + } + + #[test] + fn and_all() { + assert_eq!((0, Some(0)), super::and_all(&[])); + assert_eq!( + (7, Some(7)), + super::and_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, Some(1)), (2, Some(2)), (4, None)]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, Some(1)), (2, None), (4, Some(4))]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, None), (2, Some(2)), (4, Some(4))]) + ); + } + + #[test] + fn or_all() { + assert_eq!((0, Some(0)), super::or_all(&[])); + assert_eq!( + (1, Some(4)), + super::or_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, Some(1)), (2, Some(2)), (4, None)]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, Some(1)), (2, None), (4, Some(4))]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, None), (2, Some(2)), (4, Some(4))]) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,316 @@ +use { + super::{Arbitrary, Result, Unstructured}, + std::{collections::HashSet, fmt::Debug, hash::Hash, rc::Rc, sync::Arc}, +}; + +/// Assert that the given expected values are all generated. +/// +/// Exhaustively enumerates all buffers up to length 10 containing the +/// following bytes: `0x00`, `0x01`, `0x61` (aka ASCII 'a'), and `0xff` +fn assert_generates(expected_values: impl IntoIterator) +where + T: Clone + Debug + Hash + Eq + for<'a> Arbitrary<'a>, +{ + let expected_values: HashSet<_> = expected_values.into_iter().collect(); + let mut arbitrary_expected = expected_values.clone(); + let mut arbitrary_take_rest_expected = expected_values; + + let bytes = [0, 1, b'a', 0xff]; + let max_len = 10; + + let mut buf = Vec::with_capacity(max_len); + + let mut g = exhaustigen::Gen::new(); + while !g.done() { + let len = g.gen(max_len); + + buf.clear(); + buf.extend( + std::iter::repeat_with(|| { + let index = g.gen(bytes.len() - 1); + bytes[index] + }) + .take(len), + ); + + let mut u = Unstructured::new(&buf); + let val = T::arbitrary(&mut u).unwrap(); + arbitrary_expected.remove(&val); + + let u = Unstructured::new(&buf); + let val = T::arbitrary_take_rest(u).unwrap(); + arbitrary_take_rest_expected.remove(&val); + + if arbitrary_expected.is_empty() && arbitrary_take_rest_expected.is_empty() { + return; + } + } + + panic!( + "failed to generate all expected values!\n\n\ + T::arbitrary did not generate: {arbitrary_expected:#?}\n\n\ + T::arbitrary_take_rest did not generate {arbitrary_take_rest_expected:#?}" + ) +} + +/// Generates an arbitrary `T`, and checks that the result is consistent with the +/// `size_hint()` reported by `T`. +fn checked_arbitrary<'a, T: Arbitrary<'a>>(u: &mut Unstructured<'a>) -> Result { + let (min, max) = T::size_hint(0); + + let len_before = u.len(); + let result = T::arbitrary(u); + + let consumed = len_before - u.len(); + + if let Some(max) = max { + assert!( + consumed <= max, + "incorrect maximum size: indicated {}, actually consumed {}", + max, + consumed + ); + } + + if result.is_ok() { + assert!( + consumed >= min, + "incorrect minimum size: indicated {}, actually consumed {}", + min, + consumed + ); + } + + result +} + +/// Like `checked_arbitrary()`, but calls `arbitrary_take_rest()` instead of `arbitrary()`. +fn checked_arbitrary_take_rest<'a, T: Arbitrary<'a>>(u: Unstructured<'a>) -> Result { + let (min, _) = T::size_hint(0); + + let len_before = u.len(); + let result = T::arbitrary_take_rest(u); + + if result.is_ok() { + assert!( + len_before >= min, + "incorrect minimum size: indicated {}, worked with {}", + min, + len_before + ); + } + + result +} + +#[test] +fn finite_buffer_fill_buffer() { + let x = [1, 2, 3, 4]; + let mut rb = Unstructured::new(&x); + let mut z = [0; 2]; + rb.fill_buffer(&mut z).unwrap(); + assert_eq!(z, [1, 2]); + rb.fill_buffer(&mut z).unwrap(); + assert_eq!(z, [3, 4]); + rb.fill_buffer(&mut z).unwrap(); + assert_eq!(z, [0, 0]); +} + +#[test] +fn arbitrary_for_integers() { + let x = [1, 2, 3, 4]; + let mut buf = Unstructured::new(&x); + let expected = 1 | (2 << 8) | (3 << 16) | (4 << 24); + let actual = checked_arbitrary::(&mut buf).unwrap(); + assert_eq!(expected, actual); + + assert_generates([ + i32::from_ne_bytes([0, 0, 0, 0]), + i32::from_ne_bytes([0, 0, 0, 1]), + i32::from_ne_bytes([0, 0, 1, 0]), + i32::from_ne_bytes([0, 1, 0, 0]), + i32::from_ne_bytes([1, 0, 0, 0]), + i32::from_ne_bytes([1, 1, 1, 1]), + i32::from_ne_bytes([0xff, 0xff, 0xff, 0xff]), + ]); +} + +#[test] +fn arbitrary_for_bytes() { + let x = [1, 2, 3, 4, 4]; + let mut buf = Unstructured::new(&x); + let expected = &[1, 2, 3, 4]; + let actual = checked_arbitrary::<&[u8]>(&mut buf).unwrap(); + assert_eq!(expected, actual); +} + +#[test] +fn arbitrary_take_rest_for_bytes() { + let x = [1, 2, 3, 4]; + let buf = Unstructured::new(&x); + let expected = &[1, 2, 3, 4]; + let actual = checked_arbitrary_take_rest::<&[u8]>(buf).unwrap(); + assert_eq!(expected, actual); +} + +#[test] +fn arbitrary_for_vec_u8() { + assert_generates::>([ + vec![], + vec![0], + vec![1], + vec![0, 0], + vec![0, 1], + vec![1, 0], + vec![1, 1], + vec![0, 0, 0], + vec![0, 0, 1], + vec![0, 1, 0], + vec![0, 1, 1], + vec![1, 0, 0], + vec![1, 0, 1], + vec![1, 1, 0], + vec![1, 1, 1], + ]); +} + +#[test] +fn arbitrary_for_vec_vec_u8() { + assert_generates::>>([ + vec![], + vec![vec![]], + vec![vec![0]], + vec![vec![1]], + vec![vec![0, 1]], + vec![vec![], vec![]], + vec![vec![0], vec![]], + vec![vec![], vec![1]], + vec![vec![0], vec![1]], + vec![vec![0, 1], vec![]], + vec![vec![], vec![1, 0]], + vec![vec![], vec![], vec![]], + ]); +} + +#[test] +fn arbitrary_for_vec_vec_vec_u8() { + assert_generates::>>>([ + vec![], + vec![vec![]], + vec![vec![vec![0]]], + vec![vec![vec![1]]], + vec![vec![vec![0, 1]]], + vec![vec![], vec![]], + vec![vec![], vec![vec![]]], + vec![vec![vec![]], vec![]], + vec![vec![vec![]], vec![vec![]]], + vec![vec![vec![0]], vec![]], + vec![vec![], vec![vec![1]]], + vec![vec![vec![0]], vec![vec![1]]], + vec![vec![vec![0, 1]], vec![]], + vec![vec![], vec![vec![0, 1]]], + vec![vec![], vec![], vec![]], + vec![vec![vec![]], vec![], vec![]], + vec![vec![], vec![vec![]], vec![]], + vec![vec![], vec![], vec![vec![]]], + ]); +} + +#[test] +fn arbitrary_for_string() { + assert_generates::(["".into(), "a".into(), "aa".into(), "aaa".into()]); +} + +#[test] +fn arbitrary_collection() { + let x = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 12, + ]; + assert_eq!( + checked_arbitrary::<&[u8]>(&mut Unstructured::new(&x)).unwrap(), + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3] + ); + assert_eq!( + checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), + &[2, 4, 6, 8, 1] + ); + assert_eq!( + &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), + &[2, 4, 6, 8, 1] + ); + assert_eq!( + &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), + &[2, 4, 6, 8, 1] + ); + assert_eq!( + &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), + &[2, 4, 6, 8, 1] + ); + assert_eq!( + checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), + &[84148994] + ); + assert_eq!( + checked_arbitrary::(&mut Unstructured::new(&x)).unwrap(), + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03" + ); +} + +#[test] +fn arbitrary_take_rest() { + // Basic examples + let x = [1, 2, 3, 4]; + assert_eq!( + checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&x)).unwrap(), + &[1, 2, 3, 4] + ); + assert_eq!( + checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), + &[2, 4] + ); + assert_eq!( + &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), + &[2, 4] + ); + assert_eq!( + &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), + &[2, 4] + ); + assert_eq!( + &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), + &[2, 4] + ); + assert_eq!( + checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), + &[0x040302] + ); + assert_eq!( + checked_arbitrary_take_rest::(Unstructured::new(&x)).unwrap(), + "\x01\x02\x03\x04" + ); + + // Empty remainder + assert_eq!( + checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&[])).unwrap(), + &[] + ); + assert_eq!( + checked_arbitrary_take_rest::>(Unstructured::new(&[])).unwrap(), + &[] + ); + + // Cannot consume all but can consume part of the input + assert_eq!( + checked_arbitrary_take_rest::(Unstructured::new(&[1, 0xFF, 2])).unwrap(), + "\x01" + ); +} + +#[test] +fn size_hint_for_tuples() { + assert_eq!( + (7, Some(7)), + <(bool, u16, i32) as Arbitrary<'_>>::size_hint(0) + ); + assert_eq!((1, None), <(u8, Vec) as Arbitrary>::size_hint(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/unstructured.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/unstructured.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/src/unstructured.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/src/unstructured.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1071 @@ +// Copyright © 2019 The Rust Fuzz Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Wrappers around raw, unstructured bytes. + +use crate::{Arbitrary, Error, Result}; +use std::marker::PhantomData; +use std::ops::ControlFlow; +use std::{mem, ops}; + +/// A source of unstructured data. +/// +/// An `Unstructured` helps `Arbitrary` implementations interpret raw data +/// (typically provided by a fuzzer) as a "DNA string" that describes how to +/// construct the `Arbitrary` type. The goal is that a small change to the "DNA +/// string" (the raw data wrapped by an `Unstructured`) results in a small +/// change to the generated `Arbitrary` instance. This helps a fuzzer +/// efficiently explore the `Arbitrary`'s input space. +/// +/// `Unstructured` is deterministic: given the same raw data, the same series of +/// API calls will return the same results (modulo system resource constraints, +/// like running out of memory). However, `Unstructured` does not guarantee +/// anything beyond that: it makes not guarantee that it will yield bytes from +/// the underlying data in any particular order. +/// +/// You shouldn't generally need to use an `Unstructured` unless you are writing +/// a custom `Arbitrary` implementation by hand, instead of deriving it. Mostly, +/// you should just be passing it through to nested `Arbitrary::arbitrary` +/// calls. +/// +/// # Example +/// +/// Imagine you were writing a color conversion crate. You might want to write +/// fuzz tests that take a random RGB color and assert various properties, run +/// functions and make sure nothing panics, etc. +/// +/// Below is what translating the fuzzer's raw input into an `Unstructured` and +/// using that to generate an arbitrary RGB color might look like: +/// +/// ``` +/// # #[cfg(feature = "derive")] fn foo() { +/// use arbitrary::{Arbitrary, Unstructured}; +/// +/// /// An RGB color. +/// #[derive(Arbitrary)] +/// pub struct Rgb { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// +/// // Get the raw bytes from the fuzzer. +/// # let get_input_from_fuzzer = || &[]; +/// let raw_data: &[u8] = get_input_from_fuzzer(); +/// +/// // Wrap it in an `Unstructured`. +/// let mut unstructured = Unstructured::new(raw_data); +/// +/// // Generate an `Rgb` color and run our checks. +/// if let Ok(rgb) = Rgb::arbitrary(&mut unstructured) { +/// # let run_my_color_conversion_checks = |_| {}; +/// run_my_color_conversion_checks(rgb); +/// } +/// # } +/// ``` +#[derive(Debug)] +pub struct Unstructured<'a> { + data: &'a [u8], +} + +impl<'a> Unstructured<'a> { + /// Create a new `Unstructured` from the given raw data. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let u = Unstructured::new(&[1, 2, 3, 4]); + /// ``` + pub fn new(data: &'a [u8]) -> Self { + Unstructured { data } + } + + /// Get the number of remaining bytes of underlying data that are still + /// available. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3]); + /// + /// // Initially have three bytes of data. + /// assert_eq!(u.len(), 3); + /// + /// // Generating a `bool` consumes one byte from the underlying data, so + /// // we are left with two bytes afterwards. + /// let _ = bool::arbitrary(&mut u); + /// assert_eq!(u.len(), 2); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.data.len() + } + + /// Is the underlying unstructured data exhausted? + /// + /// `unstructured.is_empty()` is the same as `unstructured.len() == 0`. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// // Initially, we are not empty. + /// assert!(!u.is_empty()); + /// + /// // Generating a `u32` consumes all four bytes of the underlying data, so + /// // we become empty afterwards. + /// let _ = u32::arbitrary(&mut u); + /// assert!(u.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Generate an arbitrary instance of `A`. + /// + /// This is simply a helper method that is equivalent to `::arbitrary(self)`. This helper is a little bit more concise, + /// and can be used in situations where Rust's type inference will figure + /// out what `A` should be. + /// + /// # Example + /// + /// ``` + /// # #[cfg(feature="derive")] fn foo() -> arbitrary::Result<()> { + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// #[derive(Arbitrary)] + /// struct MyType { + /// // ... + /// } + /// + /// fn do_stuff(value: MyType) { + /// # let _ = value; + /// // ... + /// } + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// // Rust's type inference can figure out that `value` should be of type + /// // `MyType` here: + /// let value = u.arbitrary()?; + /// do_stuff(value); + /// # Ok(()) } + /// ``` + pub fn arbitrary(&mut self) -> Result + where + A: Arbitrary<'a>, + { + >::arbitrary(self) + } + + /// Get the number of elements to insert when building up a collection of + /// arbitrary `ElementType`s. + /// + /// This uses the [`::size_hint`][crate::Arbitrary::size_hint] method to smartly + /// choose a length such that we most likely have enough underlying bytes to + /// construct that many arbitrary `ElementType`s. + /// + /// This should only be called within an `Arbitrary` implementation. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Result, Unstructured}; + /// # pub struct MyCollection { _t: std::marker::PhantomData } + /// # impl MyCollection { + /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: std::marker::PhantomData } } + /// # pub fn insert(&mut self, element: T) {} + /// # } + /// + /// impl<'a, T> Arbitrary<'a> for MyCollection + /// where + /// T: Arbitrary<'a>, + /// { + /// fn arbitrary(u: &mut Unstructured<'a>) -> Result { + /// // Get the number of `T`s we should insert into our collection. + /// let len = u.arbitrary_len::()?; + /// + /// // And then create a collection of that length! + /// let mut my_collection = MyCollection::with_capacity(len); + /// for _ in 0..len { + /// let element = T::arbitrary(u)?; + /// my_collection.insert(element); + /// } + /// + /// Ok(my_collection) + /// } + /// } + /// ``` + pub fn arbitrary_len(&mut self) -> Result + where + ElementType: Arbitrary<'a>, + { + let byte_size = self.arbitrary_byte_size()?; + let (lower, upper) = ::size_hint(0); + let elem_size = upper.unwrap_or(lower * 2); + let elem_size = std::cmp::max(1, elem_size); + Ok(byte_size / elem_size) + } + + fn arbitrary_byte_size(&mut self) -> Result { + if self.data.is_empty() { + Ok(0) + } else if self.data.len() == 1 { + self.data = &[]; + Ok(0) + } else { + // Take lengths from the end of the data, since the `libFuzzer` folks + // found that this lets fuzzers more efficiently explore the input + // space. + // + // https://github.com/rust-fuzz/libfuzzer-sys/blob/0c450753/libfuzzer/utils/FuzzedDataProvider.h#L92-L97 + + // We only consume as many bytes as necessary to cover the entire + // range of the byte string. + // Note: We cast to u64 so we don't overflow when checking u32::MAX + 4 on 32-bit archs + let len = if self.data.len() as u64 <= u8::MAX as u64 + 1 { + let bytes = 1; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u8, for_size.iter().copied())?.0 as usize + } else if self.data.len() as u64 <= u16::MAX as u64 + 2 { + let bytes = 2; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u16, for_size.iter().copied())?.0 as usize + } else if self.data.len() as u64 <= u32::MAX as u64 + 4 { + let bytes = 4; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u32, for_size.iter().copied())?.0 as usize + } else { + let bytes = 8; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u64, for_size.iter().copied())?.0 as usize + }; + + Ok(len) + } + } + + /// Generate an integer within the given range. + /// + /// Do not use this to generate the size of a collection. Use + /// `arbitrary_len` instead. + /// + /// The probability distribution of the return value is not necessarily uniform. + /// + /// Returns `range.start()`, not an error, + /// if this `Unstructured` [is empty][Unstructured::is_empty]. + /// + /// # Panics + /// + /// Panics if `range.start > range.end`. That is, the given range must be + /// non-empty. + /// + /// # Example + /// + /// ``` + /// # fn foo() -> arbitrary::Result<()> { + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// let x: i32 = u.int_in_range(-5_000..=-1_000)?; + /// + /// assert!(-5_000 <= x); + /// assert!(x <= -1_000); + /// # Ok(()) } + /// ``` + pub fn int_in_range(&mut self, range: ops::RangeInclusive) -> Result + where + T: Int, + { + let (result, bytes_consumed) = Self::int_in_range_impl(range, self.data.iter().cloned())?; + self.data = &self.data[bytes_consumed..]; + Ok(result) + } + + fn int_in_range_impl( + range: ops::RangeInclusive, + mut bytes: impl Iterator, + ) -> Result<(T, usize)> + where + T: Int, + { + let start = *range.start(); + let end = *range.end(); + assert!( + start <= end, + "`arbitrary::Unstructured::int_in_range` requires a non-empty range" + ); + + // When there is only one possible choice, don't waste any entropy from + // the underlying data. + if start == end { + return Ok((start, 0)); + } + + // From here on out we work with the unsigned representation. All of the + // operations performed below work out just as well whether or not `T` + // is a signed or unsigned integer. + let start = start.to_unsigned(); + let end = end.to_unsigned(); + + let delta = end.wrapping_sub(start); + debug_assert_ne!(delta, T::Unsigned::ZERO); + + // Compute an arbitrary integer offset from the start of the range. We + // do this by consuming `size_of(T)` bytes from the input to create an + // arbitrary integer and then clamping that int into our range bounds + // with a modulo operation. + let mut arbitrary_int = T::Unsigned::ZERO; + let mut bytes_consumed: usize = 0; + + while (bytes_consumed < mem::size_of::()) + && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO + { + let byte = match bytes.next() { + None => break, + Some(b) => b, + }; + bytes_consumed += 1; + + // Combine this byte into our arbitrary integer, but avoid + // overflowing the shift for `u8` and `i8`. + arbitrary_int = if mem::size_of::() == 1 { + T::Unsigned::from_u8(byte) + } else { + (arbitrary_int << 8) | T::Unsigned::from_u8(byte) + }; + } + + let offset = if delta == T::Unsigned::MAX { + arbitrary_int + } else { + arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) + }; + + // Finally, we add `start` to our offset from `start` to get the result + // actual value within the range. + let result = start.wrapping_add(offset); + + // And convert back to our maybe-signed representation. + let result = T::from_unsigned(result); + debug_assert!(*range.start() <= result); + debug_assert!(result <= *range.end()); + + Ok((result, bytes_consumed)) + } + + /// Choose one of the given choices. + /// + /// This should only be used inside of `Arbitrary` implementations. + /// + /// The probability distribution of choices is not necessarily uniform. + /// + /// Returns the first choice, not an error, + /// if this `Unstructured` [is empty][Unstructured::is_empty]. + /// + /// Returns an error if no choices are provided. + /// + /// # Examples + /// + /// Selecting from an array of choices: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let choices = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + /// + /// let choice = u.choose(&choices).unwrap(); + /// + /// println!("chose {}", choice); + /// ``` + /// + /// An error is returned if no choices are provided: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let choices: [char; 0] = []; + /// + /// let result = u.choose(&choices); + /// + /// assert!(result.is_err()); + /// ``` + pub fn choose<'b, T>(&mut self, choices: &'b [T]) -> Result<&'b T> { + let idx = self.choose_index(choices.len())?; + Ok(&choices[idx]) + } + + /// Choose one of the given iterator choices. + /// + /// This should only be used inside of `Arbitrary` implementations. + /// + /// The probability distribution of choices is not necessarily uniform. + /// + /// Returns the first choice, not an error, + /// if this `Unstructured` [is empty][Unstructured::is_empty]. + /// + /// Returns an error if no choices are provided. + /// + /// # Examples + /// + /// Selecting a random item from a set: + /// + /// ``` + /// use std::collections::BTreeSet; + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let set = BTreeSet::from(['a', 'b', 'c']); + /// + /// let choice = u.choose_iter(set.iter()).unwrap(); + /// + /// println!("chose {}", choice); + /// ``` + pub fn choose_iter(&mut self, choices: I) -> Result + where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, + { + let mut choices = choices.into_iter(); + let idx = self.choose_index(choices.len())?; + let choice = choices + .nth(idx) + .expect("ExactSizeIterator should have correct len"); + Ok(choice) + } + + /// Choose a value in `0..len`. + /// + /// The probability distribution of return values is not necessarily uniform. + /// + /// Returns zero, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. + /// + /// Returns an error if the `len` is zero. + /// + /// # Examples + /// + /// Using Fisher–Yates shuffle shuffle to generate an arbitrary permutation. + /// + /// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let mut permutation = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + /// let mut to_permute = &mut permutation[..]; + /// while to_permute.len() > 1 { + /// let idx = u.choose_index(to_permute.len()).unwrap(); + /// to_permute.swap(0, idx); + /// to_permute = &mut to_permute[1..]; + /// } + /// + /// println!("permutation: {:?}", permutation); + /// ``` + /// + /// An error is returned if the length is zero: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let array: [i32; 0] = []; + /// + /// let result = u.choose_index(array.len()); + /// + /// assert!(result.is_err()); + /// ``` + pub fn choose_index(&mut self, len: usize) -> Result { + if len == 0 { + return Err(Error::EmptyChoose); + } + let idx = self.int_in_range(0..=len - 1)?; + Ok(idx) + } + + /// Generate a boolean which is true with probability approximately the given ratio. + /// + /// Returns true, not an error, if this `Unstructured` [is empty][Unstructured::is_empty]. + /// + /// # Panics + /// + /// Panics when the numerator and denominator do not meet these constraints: + /// + /// * `0 < numerator <= denominator` + /// + /// # Example + /// + /// Generate a boolean that is `true` five sevenths of the time: + /// + /// ``` + /// # fn foo() -> arbitrary::Result<()> { + /// use arbitrary::Unstructured; + /// + /// # let my_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + /// let mut u = Unstructured::new(&my_data); + /// + /// if u.ratio(5, 7)? { + /// // Take this branch approximately 5/7 of the time. + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn ratio(&mut self, numerator: T, denominator: T) -> Result + where + T: Int, + { + assert!(T::ZERO < numerator); + assert!(numerator <= denominator); + let x = self.int_in_range(T::ONE..=denominator)?; + Ok(x <= numerator) + } + + /// Fill a `buffer` with bytes from the underlying raw data. + /// + /// This should only be called within an `Arbitrary` implementation. This is + /// a very low-level operation. You should generally prefer calling nested + /// `Arbitrary` implementations like `>::arbitrary` and + /// `String::arbitrary` over using this method directly. + /// + /// If this `Unstructured` does not have enough underlying data to fill the + /// whole `buffer`, it pads the buffer out with zeros. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// let mut buf = [0; 2]; + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [1, 2]); + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [3, 4]); + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [0, 0]); + /// ``` + pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> { + let n = std::cmp::min(buffer.len(), self.data.len()); + buffer[..n].copy_from_slice(&self.data[..n]); + for byte in buffer[n..].iter_mut() { + *byte = 0; + } + self.data = &self.data[n..]; + Ok(()) + } + + /// Provide `size` bytes from the underlying raw data. + /// + /// This should only be called within an `Arbitrary` implementation. This is + /// a very low-level operation. You should generally prefer calling nested + /// `Arbitrary` implementations like `>::arbitrary` and + /// `String::arbitrary` over using this method directly. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// assert!(u.bytes(2).unwrap() == &[1, 2]); + /// assert!(u.bytes(2).unwrap() == &[3, 4]); + /// ``` + pub fn bytes(&mut self, size: usize) -> Result<&'a [u8]> { + if self.data.len() < size { + return Err(Error::NotEnoughData); + } + + let (for_buf, rest) = self.data.split_at(size); + self.data = rest; + Ok(for_buf) + } + + /// Peek at `size` number of bytes of the underlying raw input. + /// + /// Does not consume the bytes, only peeks at them. + /// + /// Returns `None` if there are not `size` bytes left in the underlying raw + /// input. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let u = Unstructured::new(&[1, 2, 3]); + /// + /// assert_eq!(u.peek_bytes(0).unwrap(), []); + /// assert_eq!(u.peek_bytes(1).unwrap(), [1]); + /// assert_eq!(u.peek_bytes(2).unwrap(), [1, 2]); + /// assert_eq!(u.peek_bytes(3).unwrap(), [1, 2, 3]); + /// + /// assert!(u.peek_bytes(4).is_none()); + /// ``` + pub fn peek_bytes(&self, size: usize) -> Option<&'a [u8]> { + self.data.get(..size) + } + + /// Consume all of the rest of the remaining underlying bytes. + /// + /// Returns a slice of all the remaining, unconsumed bytes. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3]); + /// + /// let mut remaining = u.take_rest(); + /// + /// assert_eq!(remaining, [1, 2, 3]); + /// ``` + pub fn take_rest(mut self) -> &'a [u8] { + mem::take(&mut self.data) + } + + /// Provide an iterator over elements for constructing a collection + /// + /// This is useful for implementing [`Arbitrary::arbitrary`] on collections + /// since the implementation is simply `u.arbitrary_iter()?.collect()` + pub fn arbitrary_iter<'b, ElementType: Arbitrary<'a>>( + &'b mut self, + ) -> Result> { + Ok(ArbitraryIter { + u: &mut *self, + _marker: PhantomData, + }) + } + + /// Provide an iterator over elements for constructing a collection from + /// all the remaining bytes. + /// + /// This is useful for implementing [`Arbitrary::arbitrary_take_rest`] on collections + /// since the implementation is simply `u.arbitrary_take_rest_iter()?.collect()` + pub fn arbitrary_take_rest_iter>( + self, + ) -> Result> { + Ok(ArbitraryTakeRestIter { + u: self, + _marker: PhantomData, + }) + } + + /// Call the given function an arbitrary number of times. + /// + /// The function is given this `Unstructured` so that it can continue to + /// generate arbitrary data and structures. + /// + /// You may optionaly specify minimum and maximum bounds on the number of + /// times the function is called. + /// + /// You may break out of the loop early by returning + /// `Ok(std::ops::ControlFlow::Break)`. To continue the loop, return + /// `Ok(std::ops::ControlFlow::Continue)`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Example + /// + /// Call a closure that generates an arbitrary type inside a context an + /// arbitrary number of times: + /// + /// ``` + /// use arbitrary::{Result, Unstructured}; + /// use std::ops::ControlFlow; + /// + /// enum Type { + /// /// A boolean type. + /// Bool, + /// + /// /// An integer type. + /// Int, + /// + /// /// A list of the `i`th type in this type's context. + /// List(usize), + /// } + /// + /// fn arbitrary_types_context(u: &mut Unstructured) -> Result> { + /// let mut context = vec![]; + /// + /// u.arbitrary_loop(Some(10), Some(20), |u| { + /// let num_choices = if context.is_empty() { + /// 2 + /// } else { + /// 3 + /// }; + /// let ty = match u.int_in_range::(1..=num_choices)? { + /// 1 => Type::Bool, + /// 2 => Type::Int, + /// 3 => Type::List(u.int_in_range(0..=context.len() - 1)?), + /// _ => unreachable!(), + /// }; + /// context.push(ty); + /// Ok(ControlFlow::Continue(())) + /// })?; + /// + /// // The number of loop iterations are constrained by the min/max + /// // bounds that we provided. + /// assert!(context.len() >= 10); + /// assert!(context.len() <= 20); + /// + /// Ok(context) + /// } + /// ``` + pub fn arbitrary_loop( + &mut self, + min: Option, + max: Option, + mut f: impl FnMut(&mut Self) -> Result>, + ) -> Result<()> { + let min = min.unwrap_or(0); + let max = max.unwrap_or(u32::MAX); + + for _ in 0..self.int_in_range(min..=max)? { + match f(self)? { + ControlFlow::Continue(_) => continue, + ControlFlow::Break(_) => break, + } + } + + Ok(()) + } +} + +/// Utility iterator produced by [`Unstructured::arbitrary_iter`] +pub struct ArbitraryIter<'a, 'b, ElementType> { + u: &'b mut Unstructured<'a>, + _marker: PhantomData, +} + +impl<'a, ElementType: Arbitrary<'a>> Iterator for ArbitraryIter<'a, '_, ElementType> { + type Item = Result; + fn next(&mut self) -> Option> { + let keep_going = self.u.arbitrary().unwrap_or(false); + if keep_going { + Some(Arbitrary::arbitrary(self.u)) + } else { + None + } + } +} + +/// Utility iterator produced by [`Unstructured::arbitrary_take_rest_iter`] +pub struct ArbitraryTakeRestIter<'a, ElementType> { + u: Unstructured<'a>, + _marker: PhantomData, +} + +impl<'a, ElementType: Arbitrary<'a>> Iterator for ArbitraryTakeRestIter<'a, ElementType> { + type Item = Result; + fn next(&mut self) -> Option> { + let keep_going = self.u.arbitrary().unwrap_or(false); + if keep_going { + Some(Arbitrary::arbitrary(&mut self.u)) + } else { + None + } + } +} + +/// A trait that is implemented for all of the primitive integers: +/// +/// * `u8` +/// * `u16` +/// * `u32` +/// * `u64` +/// * `u128` +/// * `usize` +/// * `i8` +/// * `i16` +/// * `i32` +/// * `i64` +/// * `i128` +/// * `isize` +/// +/// Don't implement this trait yourself. +pub trait Int: + Copy + + std::fmt::Debug + + PartialOrd + + Ord + + ops::Sub + + ops::Rem + + ops::Shr + + ops::Shl + + ops::BitOr +{ + #[doc(hidden)] + type Unsigned: Int; + + #[doc(hidden)] + const ZERO: Self; + + #[doc(hidden)] + const ONE: Self; + + #[doc(hidden)] + const MAX: Self; + + #[doc(hidden)] + fn from_u8(b: u8) -> Self; + + #[doc(hidden)] + fn from_usize(u: usize) -> Self; + + #[doc(hidden)] + fn checked_add(self, rhs: Self) -> Option; + + #[doc(hidden)] + fn wrapping_add(self, rhs: Self) -> Self; + + #[doc(hidden)] + fn wrapping_sub(self, rhs: Self) -> Self; + + #[doc(hidden)] + fn to_unsigned(self) -> Self::Unsigned; + + #[doc(hidden)] + fn from_unsigned(unsigned: Self::Unsigned) -> Self; +} + +macro_rules! impl_int { + ( $( $ty:ty : $unsigned_ty: ty ; )* ) => { + $( + impl Int for $ty { + type Unsigned = $unsigned_ty; + + const ZERO: Self = 0; + + const ONE: Self = 1; + + const MAX: Self = Self::MAX; + + fn from_u8(b: u8) -> Self { + b as Self + } + + fn from_usize(u: usize) -> Self { + u as Self + } + + fn checked_add(self, rhs: Self) -> Option { + <$ty>::checked_add(self, rhs) + } + + fn wrapping_add(self, rhs: Self) -> Self { + <$ty>::wrapping_add(self, rhs) + } + + fn wrapping_sub(self, rhs: Self) -> Self { + <$ty>::wrapping_sub(self, rhs) + } + + fn to_unsigned(self) -> Self::Unsigned { + self as $unsigned_ty + } + + fn from_unsigned(unsigned: $unsigned_ty) -> Self { + unsigned as Self + } + } + )* + } +} + +impl_int! { + u8: u8; + u16: u16; + u32: u32; + u64: u64; + u128: u128; + usize: usize; + i8: u8; + i16: u16; + i32: u32; + i64: u64; + i128: u128; + isize: usize; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_byte_size() { + let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); + // Should take one byte off the end + assert_eq!(u.arbitrary_byte_size().unwrap(), 6); + assert_eq!(u.len(), 9); + let mut v = vec![0; 260]; + v.push(1); + v.push(4); + let mut u = Unstructured::new(&v); + // Should read two bytes off the end + assert_eq!(u.arbitrary_byte_size().unwrap(), 0x104); + assert_eq!(u.len(), 260); + } + + #[test] + fn int_in_range_of_one() { + let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); + let x = u.int_in_range(0..=0).unwrap(); + assert_eq!(x, 0); + let choice = *u.choose(&[42]).unwrap(); + assert_eq!(choice, 42) + } + + #[test] + fn int_in_range_uses_minimal_amount_of_bytes() { + let mut u = Unstructured::new(&[1, 2]); + assert_eq!(1, u.int_in_range::(0..=u8::MAX).unwrap()); + assert_eq!(u.len(), 1); + + let mut u = Unstructured::new(&[1, 2]); + assert_eq!(1, u.int_in_range::(0..=u8::MAX as u32).unwrap()); + assert_eq!(u.len(), 1); + + let mut u = Unstructured::new(&[1]); + assert_eq!(1, u.int_in_range::(0..=u8::MAX as u32 + 1).unwrap()); + assert!(u.is_empty()); + } + + #[test] + fn int_in_range_in_bounds() { + for input in u8::MIN..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(1..=u8::MAX).unwrap(); + assert_ne!(x, 0); + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); + assert_ne!(x, u8::MAX); + } + } + + #[test] + fn int_in_range_covers_unsigned_range() { + // Test that we generate all values within the range given to + // `int_in_range`. + + let mut full = [false; u8::MAX as usize + 1]; + let mut no_zero = [false; u8::MAX as usize]; + let mut no_max = [false; u8::MAX as usize]; + let mut narrow = [false; 10]; + + for input in u8::MIN..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX).unwrap(); + full[x as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(1..=u8::MAX).unwrap(); + no_zero[x as usize - 1] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); + no_max[x as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(100..=109).unwrap(); + narrow[x as usize - 100] = true; + } + + for (i, covered) in full.iter().enumerate() { + assert!(covered, "full[{}] should have been generated", i); + } + for (i, covered) in no_zero.iter().enumerate() { + assert!(covered, "no_zero[{}] should have been generated", i); + } + for (i, covered) in no_max.iter().enumerate() { + assert!(covered, "no_max[{}] should have been generated", i); + } + for (i, covered) in narrow.iter().enumerate() { + assert!(covered, "narrow[{}] should have been generated", i); + } + } + + #[test] + fn int_in_range_covers_signed_range() { + // Test that we generate all values within the range given to + // `int_in_range`. + + let mut full = [false; u8::MAX as usize + 1]; + let mut no_min = [false; u8::MAX as usize]; + let mut no_max = [false; u8::MAX as usize]; + let mut narrow = [false; 21]; + + let abs_i8_min: isize = 128; + + for input in 0..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN..=i8::MAX).unwrap(); + full[(x as isize + abs_i8_min) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN + 1..=i8::MAX).unwrap(); + no_min[(x as isize + abs_i8_min - 1) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN..=i8::MAX - 1).unwrap(); + no_max[(x as isize + abs_i8_min) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(-10..=10).unwrap(); + narrow[(x as isize + 10) as usize] = true; + } + + for (i, covered) in full.iter().enumerate() { + assert!(covered, "full[{}] should have been generated", i); + } + for (i, covered) in no_min.iter().enumerate() { + assert!(covered, "no_min[{}] should have been generated", i); + } + for (i, covered) in no_max.iter().enumerate() { + assert!(covered, "no_max[{}] should have been generated", i); + } + for (i, covered) in narrow.iter().enumerate() { + assert!(covered, "narrow[{}] should have been generated", i); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/bound.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/bound.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/bound.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/bound.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,142 @@ +#![cfg(feature = "derive")] + +use arbitrary::{Arbitrary, Unstructured}; + +fn arbitrary_from<'a, T: Arbitrary<'a>>(input: &'a [u8]) -> T { + let mut buf = Unstructured::new(input); + T::arbitrary(&mut buf).expect("can create arbitrary instance OK") +} + +/// This wrapper trait *implies* `Arbitrary`, but the compiler isn't smart enough to work that out +/// so when using this wrapper we *must* opt-out of the auto-generated `T: Arbitrary` bounds. +pub trait WrapperTrait: for<'a> Arbitrary<'a> {} + +impl WrapperTrait for u32 {} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: WrapperTrait")] +struct GenericSingleBound { + t: T, +} + +#[test] +fn single_bound() { + let v: GenericSingleBound = arbitrary_from(&[0, 0, 0, 0]); + assert_eq!(v.t, 0); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: WrapperTrait, U: WrapperTrait")] +struct GenericMultipleBoundsSingleAttribute { + t: T, + u: U, +} + +#[test] +fn multiple_bounds_single_attribute() { + let v: GenericMultipleBoundsSingleAttribute = + arbitrary_from(&[1, 0, 0, 0, 2, 0, 0, 0]); + assert_eq!(v.t, 1); + assert_eq!(v.u, 2); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: WrapperTrait")] +#[arbitrary(bound = "U: Default")] +struct GenericMultipleArbitraryAttributes { + t: T, + #[arbitrary(default)] + u: U, +} + +#[test] +fn multiple_arbitrary_attributes() { + let v: GenericMultipleArbitraryAttributes = arbitrary_from(&[1, 0, 0, 0]); + assert_eq!(v.t, 1); + assert_eq!(v.u, 0); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: WrapperTrait", bound = "U: Default")] +struct GenericMultipleBoundAttributes { + t: T, + #[arbitrary(default)] + u: U, +} + +#[test] +fn multiple_bound_attributes() { + let v: GenericMultipleBoundAttributes = arbitrary_from(&[1, 0, 0, 0]); + assert_eq!(v.t, 1); + assert_eq!(v.u, 0); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: WrapperTrait", bound = "U: Default")] +#[arbitrary(bound = "V: WrapperTrait, W: Default")] +struct GenericMultipleArbitraryAndBoundAttributes< + T: WrapperTrait, + U: Default, + V: WrapperTrait, + W: Default, +> { + t: T, + #[arbitrary(default)] + u: U, + v: V, + #[arbitrary(default)] + w: W, +} + +#[test] +fn multiple_arbitrary_and_bound_attributes() { + let v: GenericMultipleArbitraryAndBoundAttributes = + arbitrary_from(&[1, 0, 0, 0, 2, 0, 0, 0]); + assert_eq!(v.t, 1); + assert_eq!(v.u, 0); + assert_eq!(v.v, 2); + assert_eq!(v.w, 0); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "T: Default")] +struct GenericDefault { + #[arbitrary(default)] + x: T, +} + +#[test] +fn default_bound() { + // We can write a generic func without any `Arbitrary` bound. + fn generic_default() -> GenericDefault { + arbitrary_from(&[]) + } + + assert_eq!(generic_default::().x, 0); + assert_eq!(generic_default::().x, String::new()); + assert_eq!(generic_default::>().x, Vec::new()); +} + +#[derive(Arbitrary)] +#[arbitrary()] +struct EmptyArbitraryAttribute { + t: u32, +} + +#[test] +fn empty_arbitrary_attribute() { + let v: EmptyArbitraryAttribute = arbitrary_from(&[1, 0, 0, 0]); + assert_eq!(v.t, 1); +} + +#[derive(Arbitrary)] +#[arbitrary(bound = "")] +struct EmptyBoundAttribute { + t: u32, +} + +#[test] +fn empty_bound_attribute() { + let v: EmptyBoundAttribute = arbitrary_from(&[1, 0, 0, 0]); + assert_eq!(v.t, 1); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/derive.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/derive.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/derive.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/derive.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,402 @@ +#![cfg(feature = "derive")] +// Various structs/fields that we are deriving `Arbitrary` for aren't actually +// used except to exercise the derive. +#![allow(dead_code)] +// Various assert_eq! are used to compare result of bool amongst other data types +// In this case, using assert! is less explicit and readable +#![allow(clippy::bool_assert_comparison)] + +use arbitrary::*; + +fn arbitrary_from<'a, T: Arbitrary<'a>>(input: &'a [u8]) -> T { + let mut buf = Unstructured::new(input); + T::arbitrary(&mut buf).expect("can create arbitrary instance OK") +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Arbitrary)] +pub struct Rgb { + pub r: u8, + pub g: u8, + pub b: u8, +} + +#[test] +fn struct_with_named_fields() { + let rgb: Rgb = arbitrary_from(&[4, 5, 6]); + assert_eq!(rgb.r, 4); + assert_eq!(rgb.g, 5); + assert_eq!(rgb.b, 6); + + assert_eq!((3, Some(3)), ::size_hint(0)); +} + +#[derive(Copy, Clone, Debug, Arbitrary)] +struct MyTupleStruct(u8, bool); + +#[test] +fn tuple_struct() { + let s: MyTupleStruct = arbitrary_from(&[43, 42]); + assert_eq!(s.0, 43); + assert_eq!(s.1, false); + + let s: MyTupleStruct = arbitrary_from(&[42, 43]); + assert_eq!(s.0, 42); + assert_eq!(s.1, true); + + assert_eq!((2, Some(2)), ::size_hint(0)); +} + +#[derive(Clone, Debug, Arbitrary)] +struct EndingInVec(u8, bool, u32, Vec); +#[derive(Clone, Debug, Arbitrary)] +struct EndingInString(u8, bool, u32, String); + +#[test] +fn test_take_rest() { + let bytes = [1, 1, 1, 2, 3, 4, 5, 6, 7, 8]; + let s1 = EndingInVec::arbitrary_take_rest(Unstructured::new(&bytes)).unwrap(); + let s2 = EndingInString::arbitrary_take_rest(Unstructured::new(&bytes)).unwrap(); + assert_eq!(s1.0, 1); + assert_eq!(s2.0, 1); + assert_eq!(s1.1, true); + assert_eq!(s2.1, true); + assert_eq!(s1.2, 0x4030201); + assert_eq!(s2.2, 0x4030201); + assert_eq!(s1.3, vec![0x0706]); + assert_eq!(s2.3, "\x05\x06\x07\x08"); +} + +#[derive(Copy, Clone, Debug, Arbitrary)] +enum MyEnum { + Unit, + Tuple(u8, u16), + Struct { a: u32, b: (bool, u64) }, +} + +#[test] +fn derive_enum() { + let mut raw = vec![ + // The choice of which enum variant takes 4 bytes. + 1, 2, 3, 4, + // And then we need up to 13 bytes for creating `MyEnum::Struct`, the + // largest variant. + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + ]; + + let mut saw_unit = false; + let mut saw_tuple = false; + let mut saw_struct = false; + + for i in 0..=255 { + // Choose different variants each iteration. + for el in &mut raw[..4] { + *el = i; + } + + let e: MyEnum = arbitrary_from(&raw); + + match e { + MyEnum::Unit => { + saw_unit = true; + } + MyEnum::Tuple(a, b) => { + saw_tuple = true; + assert_eq!(a, arbitrary_from(&raw[4..5])); + assert_eq!(b, arbitrary_from(&raw[5..])); + } + MyEnum::Struct { a, b } => { + saw_struct = true; + assert_eq!(a, arbitrary_from(&raw[4..8])); + assert_eq!(b, arbitrary_from(&raw[8..])); + } + } + } + + assert!(saw_unit); + assert!(saw_tuple); + assert!(saw_struct); + + assert_eq!((4, Some(17)), ::size_hint(0)); +} + +// This should result in a compiler-error: +// #[derive(Arbitrary, Debug)] +// enum Never { +// #[arbitrary(skip)] +// Nope, +// } + +#[derive(Arbitrary, Debug)] +enum SkipVariant { + Always, + #[arbitrary(skip)] + Never, +} + +#[test] +fn test_skip_variant() { + (0..=u8::MAX).for_each(|byte| { + let buffer = [byte]; + let unstructured = Unstructured::new(&buffer); + let skip_variant = SkipVariant::arbitrary_take_rest(unstructured).unwrap(); + assert!(!matches!(skip_variant, SkipVariant::Never)); + }) +} + +#[derive(Arbitrary, Debug)] +enum RecursiveTree { + Leaf, + Node { + left: Box, + right: Box, + }, +} + +#[derive(Arbitrary, Debug)] +struct WideRecursiveStruct { + a: Option>, + b: Option>, + c: Option>, + d: Option>, + e: Option>, + f: Option>, + g: Option>, + h: Option>, + i: Option>, + k: Option>, +} + +#[derive(Arbitrary, Debug)] +enum WideRecursiveEnum { + None, + A(Box), + B(Box), + C(Box), + D(Box), + E(Box), + F(Box), + G(Box), + H(Box), + I(Box), + K(Box), +} + +#[derive(Arbitrary, Debug)] +enum WideRecursiveMixedEnum { + None, + A(Box), + B(Box), + C(Box), + D(Box), + E(Box), + F(Box), + G(Box), + H(Box), + I(Box), + K(Box), +} + +#[derive(Arbitrary, Debug)] +struct WideRecursiveMixedStruct { + a: Option>, + b: Option>, + c: Option>, + d: Option>, + e: Option>, + f: Option>, + g: Option>, + h: Option>, + i: Option>, + k: Option>, +} + +#[test] +fn recursive() { + let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let _rec: RecursiveTree = arbitrary_from(&raw); + let _rec: WideRecursiveStruct = arbitrary_from(&raw); + let _rec: WideRecursiveEnum = arbitrary_from(&raw); + let _rec: WideRecursiveMixedStruct = arbitrary_from(&raw); + let _rec: WideRecursiveMixedEnum = arbitrary_from(&raw); + + assert_eq!((0, None), ::size_hint(0)); + assert_eq!((0, None), ::size_hint(0)); + assert_eq!( + (0, None), + ::size_hint(0) + ); + assert_eq!( + (0, None), + ::size_hint(0) + ); + + let (lower, upper) = ::size_hint(0); + assert_eq!(lower, 0, "Cannot compute size hint of recursive structure"); + assert!( + upper.is_none(), + "potentially infinitely recursive, so no upper bound" + ); +} + +#[derive(Arbitrary, Debug)] +struct Generic { + inner: T, +} + +#[test] +fn generics() { + let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let gen: Generic = arbitrary_from(&raw); + assert!(gen.inner); + + let (lower, upper) = as Arbitrary>::size_hint(0); + assert_eq!(lower, 4); + assert_eq!(upper, Some(4)); +} + +#[derive(Arbitrary, Debug)] +struct OneLifetime<'a> { + alpha: &'a str, +} + +#[test] +fn one_lifetime() { + // Last byte is used for length + let raw: Vec = vec![97, 98, 99, 100, 3]; + let lifetime: OneLifetime = arbitrary_from(&raw); + assert_eq!("abc", lifetime.alpha); + + let (lower, upper) = ::size_hint(0); + assert_eq!(lower, 0); + assert_eq!(upper, None); +} + +#[derive(Arbitrary, Debug)] +struct TwoLifetimes<'a, 'b> { + alpha: &'a str, + beta: &'b str, +} + +#[test] +fn two_lifetimes() { + // Last byte is used for length + let raw: Vec = vec![97, 98, 99, 100, 101, 102, 103, 3]; + let lifetime: TwoLifetimes = arbitrary_from(&raw); + assert_eq!("abc", lifetime.alpha); + assert_eq!("def", lifetime.beta); + + let (lower, upper) = ::size_hint(0); + assert_eq!(lower, 0); + assert_eq!(upper, None); +} + +#[test] +fn recursive_and_empty_input() { + // None of the following derives should result in a stack overflow. See + // https://github.com/rust-fuzz/arbitrary/issues/107 for details. + + #[derive(Debug, Arbitrary)] + enum Nat { + Succ(Box), + Zero, + } + + let _ = Nat::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Arbitrary)] + enum Nat2 { + Zero, + Succ(Box), + } + + let _ = Nat2::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Arbitrary)] + struct Nat3 { + f: Option>, + } + + let _ = Nat3::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Arbitrary)] + struct Nat4(Option>); + + let _ = Nat4::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Arbitrary)] + enum Nat5 { + Zero, + Succ { f: Box }, + } + + let _ = Nat5::arbitrary(&mut Unstructured::new(&[])); +} + +#[test] +fn test_field_attributes() { + // A type that DOES NOT implement Arbitrary + #[derive(Debug)] + struct Weight(u8); + + #[derive(Debug, Arbitrary)] + struct Parcel { + #[arbitrary(with = arbitrary_weight)] + weight: Weight, + + #[arbitrary(default)] + width: u8, + + #[arbitrary(value = 2 + 2)] + length: u8, + + height: u8, + + #[arbitrary(with = |u: &mut Unstructured| u.int_in_range(0..=100))] + price: u8, + } + + fn arbitrary_weight(u: &mut Unstructured) -> arbitrary::Result { + u.int_in_range(45..=56).map(Weight) + } + + let parcel: Parcel = arbitrary_from(&[6, 199, 17]); + + // 45 + 6 = 51 + assert_eq!(parcel.weight.0, 51); + + // u8::default() + assert_eq!(parcel.width, 0); + + // 2 + 2 = 4 + assert_eq!(parcel.length, 4); + + // 199 is the 2nd byte used by arbitrary + assert_eq!(parcel.height, 199); + + // 17 is the 3rd byte used by arbitrary + assert_eq!(parcel.price, 17); +} + +#[test] +fn derive_structs_named_same_as_core() { + #[derive(Debug, Arbitrary)] + struct Option { + f: core::option::Option, + } + + let _ = Option::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Default, Arbitrary)] + struct Default { + f: u32, + } + + let _ = Default::arbitrary(&mut Unstructured::new(&[])); + + #[derive(Debug, Arbitrary)] + struct Result { + f: core::result::Result, + } + + let _ = Result::arbitrary(&mut Unstructured::new(&[])); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/path.rs clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arbitrary/tests/path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arbitrary/tests/path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +#![cfg(feature = "derive")] +// Various structs/fields that we are deriving `Arbitrary` for aren't actually +// used except to show off the derive. +#![allow(dead_code)] + +// Regression test for ensuring the derives work without Arbitrary being imported + +#[derive(arbitrary::Arbitrary, Clone, Debug)] +pub struct Struct { + x: u8, + y: u8, +} + +#[derive(arbitrary::Arbitrary, Clone, Debug)] +pub struct Tuple(u8); + +#[derive(arbitrary::Arbitrary, Clone, Debug)] +pub struct Unit(u8); + +#[derive(arbitrary::Arbitrary, Clone, Debug)] +pub enum Enum { + X(u8), + Y(u8), +} + +#[derive(arbitrary::Arbitrary, Clone, Debug)] +struct EndingInVec(u8, bool, u32, Vec); + +#[derive(arbitrary::Arbitrary, Debug)] +struct Generic { + inner: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"1699d9475067ff8e7705650feab97b9bfc5e9270bce4ed3ecd08af7d5e036e15","Cargo.toml":"efdb6941b4d8f9e857a333f367e2a365022ab5e43b42e53ebfa10d874c636d0f","Cargo.toml.orig":"90f8c8463bfeb206fee90a0623d18e12824dbb06c0158176980a553e9ac03c79","LICENSE":"8eb4fb5a6505da473ee195f326007c8c7e28357e3e6a11e293ce2a480384030c","README.md":"aaaac51fd031e62c69fa3d155c7073ff59e8c8e5eb50d3db5826d495ef03f73a","src/lib.rs":"b6bcd1913cccdd449a4087b22f5297de5c0cd82c3136b4b375e5741db616df70","tests/enums.rs":"6e23010f47d7e6b5e5a5d6b3abdea7730230735c838808706665b399bbed7f06","tests/ui/complex-enum.rs":"929666dae4c9ff225d2d0ce9fccf3a2276ff59b78ddb77469170e3f376ac1526","tests/ui/complex-enum.stderr":"452de0af1cffc86325e6b616a222d3c2817fe1d3a607cfcaef3e35c7eaef920d","tests/ui/derive-not-on-enum.rs":"d782fdc7e494b7f4abaf2089d2b9bec7e86265be7a542d673f52a598d419e658","tests/ui/derive-not-on-enum.stderr":"b6b70d28bdbc1103f6d0bf0de39f3cf9f96428ca74164e6ba47ebb591c2d8ef8"},"package":"0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "28b02f0ef1eb548e1e75bd24effde08d64be3101" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "arg_enum_proc_macro" +version = "0.3.4" +authors = ["Luca Barbato "] +description = "A procedural macro compatible with clap arg_enum" +readme = "README.md" +keywords = [ + "proc_macro", + "arg_enum", +] +license = "MIT" +repository = "https://github.com/lu-zero/arg_enum_proc_macro" + +[lib] +test = false +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" +features = ["extra-traits"] + +[dev-dependencies.trybuild] +version = "1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "arg_enum_proc_macro" +version = "0.3.4" +authors = ["Luca Barbato "] +description = "A procedural macro compatible with clap arg_enum" +repository = "https://github.com/lu-zero/arg_enum_proc_macro" +readme = "README.md" +keywords = ["proc_macro", "arg_enum"] +license = "MIT" +edition = "2018" + +[lib] +proc-macro = true +test = false + +[dependencies] +syn = { version = "2.0", features = ["extra-traits"] } +quote = "1.0" +proc-macro2 = "1.0" + +[dev-dependencies] +trybuild = "1.0" + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Luca Barbato + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/README.md clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +# Procedural macro derive that mimics `arg_enum!` from [clap](https://clap.rs) + +![Crates.io](https://img.shields.io/crates/v/arg_enum_proc_macro) +![docs.rs](https://docs.rs/mio/badge.svg) +[![dependency status](https://deps.rs/repo/github/lu-zero/arg_enum_proc_macro/status.svg)](https://deps.rs/repo/github/lu-zero/arg_enum_proc_macro) + +## Usage + +In `Cargo.toml`: +``` toml +[dependencies] +arg_enum_proc_macro = "0.3" +``` + +In the rust code: +``` rust +use arg_enum_proc_macro::ArgEnum; + +/// All the possible states of Foo +#[derive(ArgEnum)] +pub enum Foo { + /// Initial state + Unk, + /// Foo is on + On, + /// Foo is off + Off, +} +``` + +### Aliases + +It is possible to express an alias using the attribute `arg_enum(alias = "AliasVariant")`. +The `FromStr` will map the "AliasVariant" string to the decorated enum variant: + +``` rust +/// All the possible states of Foo +#[derive(ArgEnum)] +pub enum Foo { + /// Initial state + Unk, + /// Foo is on + #[arg_enum(alias = "Up")] + On, + /// Foo is off + #[arg_enum(alias = "Down")] + Off, +} +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,280 @@ +//! # arg_enum_proc_macro +//! +//! This crate consists in a procedural macro derive that provides the +//! same implementations that clap the [`clap::arg_enum`][1] macro provides: +//! [`std::fmt::Display`], [`std::str::FromStr`] and a `variants()` function. +//! +//! By using a procedural macro it allows documenting the enum fields +//! correctly and avoids the requirement of expanding the macro to use +//! the structure with [cbindgen](https://crates.io/crates/cbindgen). +//! +//! [1]: https://docs.rs/clap/2.32.0/clap/macro.arg_enum.html +//! + +#![recursion_limit = "128"] + +extern crate proc_macro; + +use proc_macro2::{Literal, Punct, Span, TokenStream, TokenTree}; +use quote::{quote, quote_spanned}; +use std::iter::FromIterator; + +use syn::Lit::{self}; +use syn::Meta::{self}; +use syn::{parse_macro_input, Data, DeriveInput, Expr, ExprLit, Ident, LitStr}; + +/// Implement [`std::fmt::Display`], [`std::str::FromStr`] and `variants()`. +/// +/// The invocation: +/// ``` no_run +/// use arg_enum_proc_macro::ArgEnum; +/// +/// #[derive(ArgEnum)] +/// enum Foo { +/// A, +/// /// Describe B +/// #[arg_enum(alias = "Bar")] +/// B, +/// /// Describe C +/// /// Multiline +/// #[arg_enum(name = "Baz")] +/// C, +/// } +/// ``` +/// +/// produces: +/// ``` no_run +/// enum Foo { +/// A, +/// B, +/// C +/// } +/// impl ::std::str::FromStr for Foo { +/// type Err = String; +/// +/// fn from_str(s: &str) -> ::std::result::Result { +/// match s { +/// "A" | _ if s.eq_ignore_ascii_case("A") => Ok(Foo::A), +/// "B" | _ if s.eq_ignore_ascii_case("B") => Ok(Foo::B), +/// "Bar" | _ if s.eq_ignore_ascii_case("Bar") => Ok(Foo::B), +/// "Baz" | _ if s.eq_ignore_ascii_case("Baz") => Ok(Foo::C), +/// _ => Err({ +/// let v = vec![ "A", "B", "Bar", "Baz" ]; +/// format!("valid values: {}", v.join(" ,")) +/// }), +/// } +/// } +/// } +/// impl ::std::fmt::Display for Foo { +/// fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { +/// match *self { +/// Foo::A => write!(f, "A"), +/// Foo::B => write!(f, "B"), +/// Foo::C => write!(f, "C"), +/// } +/// } +/// } +/// +/// impl Foo { +/// /// Returns an array of valid values which can be converted into this enum. +/// #[allow(dead_code)] +/// pub fn variants() -> [&'static str; 4] { +/// [ "A", "B", "Bar", "Baz", ] +/// } +/// #[allow(dead_code)] +/// pub fn descriptions() -> [(&'static [&'static str], &'static [&'static str]) ;3] { +/// [(&["A"], &[]), +/// (&["B", "Bar"], &[" Describe B"]), +/// (&["Baz"], &[" Describe C", " Multiline"]),] +/// } +/// } +/// ``` +#[proc_macro_derive(ArgEnum, attributes(arg_enum))] +pub fn arg_enum(items: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(items as DeriveInput); + + let name = input.ident; + let variants = if let Data::Enum(data) = input.data { + data.variants + } else { + panic!("Only enum supported"); + }; + + let all_variants: Vec<(TokenTree, &Ident)> = variants + .iter() + .flat_map(|item| { + let id = &item.ident; + if !item.fields.is_empty() { + panic!( + "Only enum with unit variants are supported! \n\ + Variant {}::{} is not an unit variant", + name, + &id.to_string() + ); + } + + let lit: TokenTree = Literal::string(&id.to_string()).into(); + let mut all_lits = vec![(lit, id)]; + item.attrs + .iter() + .filter(|attr| attr.path().is_ident("arg_enum")) + // .flat_map(|attr| { + .for_each(|attr| { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("alias") { + let val = meta.value()?; + let alias: Literal = val.parse()?; + all_lits.push((alias.into(), id)); + } + if meta.path.is_ident("name") { + let val = meta.value()?; + let name: Literal = val.parse()?; + all_lits[0] = (name.into(), id); + } + Ok(()) + }) + .unwrap(); + }); + all_lits.into_iter() + }) + .collect(); + + let len = all_variants.len(); + + let from_str_match = all_variants.iter().flat_map(|(lit, id)| { + let pat: TokenStream = quote! { + #lit | _ if s.eq_ignore_ascii_case(#lit) => Ok(#name::#id), + }; + + pat.into_iter() + }); + + let from_str_match = TokenStream::from_iter(from_str_match); + + let all_descriptions: Vec<(Vec, Vec)> = variants + .iter() + .map(|item| { + let id = &item.ident; + let description = item + .attrs + .iter() + .filter_map(|attr| { + let expr = match &attr.meta { + Meta::NameValue(name_value) if name_value.path.is_ident("doc") => { + Some(name_value.value.to_owned()) + } + _ => + // non #[doc = "..."] attributes are not our concern + // we leave them for rustc to handle + { + None + } + }; + + expr.and_then(|expr| { + if let Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) = expr + { + Some(s) + } else { + None + } + }) + }) + .collect(); + let lit: TokenTree = Literal::string(&id.to_string()).into(); + let mut all_names = vec![lit]; + item.attrs + .iter() + .filter(|attr| attr.path().is_ident("arg_enum")) + // .flat_map(|attr| { + .for_each(|attr| { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("alias") { + let val = meta.value()?; + let alias: Literal = val.parse()?; + all_names.push(alias.into()); + } + if meta.path.is_ident("name") { + let val = meta.value()?; + let name: Literal = val.parse()?; + all_names[0] = name.into(); + } + Ok(()) + }) + .unwrap(); + }); + + (all_names, description) + }) + .collect(); + + let display_match = variants.iter().flat_map(|item| { + let id = &item.ident; + let lit: TokenTree = Literal::string(&id.to_string()).into(); + + let pat: TokenStream = quote! { + #name::#id => write!(f, #lit), + }; + + pat.into_iter() + }); + + let display_match = TokenStream::from_iter(display_match); + + let comma: TokenTree = Punct::new(',', proc_macro2::Spacing::Alone).into(); + let array_items = all_variants + .iter() + .flat_map(|(tok, _id)| vec![tok.clone(), comma.clone()].into_iter()); + + let array_items = TokenStream::from_iter(array_items); + + let array_descriptions = all_descriptions.iter().map(|(names, descr)| { + quote! { + (&[ #(#names),* ], &[ #(#descr),* ]), + } + }); + let array_descriptions = TokenStream::from_iter(array_descriptions); + + let len_descriptions = all_descriptions.len(); + + let ret: TokenStream = quote_spanned! { + Span::call_site() => + impl ::std::str::FromStr for #name { + type Err = String; + + fn from_str(s: &str) -> ::std::result::Result { + match s { + #from_str_match + _ => { + let values = [ #array_items ]; + + Err(format!("valid values: {}", values.join(" ,"))) + } + } + } + } + impl ::std::fmt::Display for #name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + #display_match + } + } + } + impl #name { + #[allow(dead_code)] + /// Returns an array of valid values which can be converted into this enum. + pub fn variants() -> [&'static str; #len] { + [ #array_items ] + } + #[allow(dead_code)] + /// Returns an array of touples (variants, description) + pub fn descriptions() -> [(&'static [&'static str], &'static [&'static str]); #len_descriptions] { + [ #array_descriptions ] + } + } + }; + + ret.into() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/enums.rs clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/enums.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/enums.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/enums.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,115 @@ +use arg_enum_proc_macro::ArgEnum; + +#[derive(ArgEnum, PartialEq, Debug)] +pub enum Foo { + Bar, + /// Foo + Baz, +} + +#[test] +fn parse() { + let v: Foo = "Baz".parse().unwrap(); + + assert_eq!(v, Foo::Baz); +} + +#[test] +fn variants() { + assert_eq!(&Foo::variants(), &["Bar", "Baz"]); +} + +mod alias { + use arg_enum_proc_macro::ArgEnum; + + #[derive(ArgEnum, PartialEq, Debug)] + pub enum Bar { + A, + B, + #[arg_enum(alias = "Cat")] + C, + } + + #[test] + fn parse() { + let v: Bar = "Cat".parse().unwrap(); + + assert_eq!(v, Bar::C); + } + + #[test] + fn variants() { + assert_eq!(&Bar::variants(), &["A", "B", "C", "Cat"]); + } +} + +mod name { + use arg_enum_proc_macro::ArgEnum; + + #[derive(ArgEnum, PartialEq, Debug)] + pub enum Bar { + A, + B, + #[arg_enum(name = "Cat", alias = "Feline")] + C, + } + + #[test] + fn parse() { + let v: Bar = "Cat".parse().unwrap(); + + assert_eq!(v, Bar::C); + } + + #[test] + fn variants() { + assert_eq!(&Bar::variants(), &["A", "B", "Cat", "Feline"]); + } +} + +mod description { + use arg_enum_proc_macro::ArgEnum; + + #[derive(ArgEnum, PartialEq, Debug)] + pub enum Bar { + /// This is A and it's description is a single line + A, + /// This is B and it's description contains " for no specific reason + /// and is in two lines. + B, + /// This is C, normally known as "Cat" or "Feline" + #[arg_enum(name = "Cat", alias = "Feline")] + C, + } + + #[test] + fn descriptions() { + let expected: [(&'static [&'static str], &'static [&'static str]); 3usize] = [ + ( + &["A"], + &[" This is A and it's description is a single line"], + ), + ( + &["B"], + &[ + " This is B and it's description contains \" for no specific reason", + " and is in two lines.", + ], + ), + ( + &["Cat", "Feline"], + &[" This is C, normally known as \"Cat\" or \"Feline\""], + ), + ]; + assert_eq!(&Bar::descriptions(), &expected); + } +} + +mod ui { + #[test] + fn invalid_applications() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/complex-enum.rs"); + t.compile_fail("tests/ui/derive-not-on-enum.rs"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.rs clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +use arg_enum_proc_macro::ArgEnum; + +pub enum Foo { + Bar, + /// Foo + Baz, +} + +#[derive(ArgEnum)] +pub enum Complex { + A, + B(Foo), + C { a: usize, b: usize }, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.stderr clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/complex-enum.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error: proc-macro derive panicked + --> $DIR/complex-enum.rs:9:10 + | +9 | #[derive(ArgEnum)] + | ^^^^^^^ + | + = help: message: Only enum with unit variants are supported! + Variant Complex::B is not an unit variant diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.rs clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use arg_enum_proc_macro::ArgEnum; + +#[derive(ArgEnum)] +pub struct Complicated { + pub foo: u8, + pub bar: u8, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.stderr clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arg_enum_proc_macro/tests/ui/derive-not-on-enum.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error: proc-macro derive panicked + --> $DIR/derive-not-on-enum.rs:3:10 + | +3 | #[derive(ArgEnum)] + | ^^^^^^^ + | + = help: message: Only enum supported diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"1ef8308fb4d0d339fa4af5def4c223fd1448028393815c87fbb1bf894ffa263d",".github/workflows/ci.yml":"df50bd3ef1d26b528d59387b33da8a2ec2dc709ca3c64d773052088cff7a6378","CHANGELOG.md":"b6cd865fb2685cf241e61f216686c87fd78e7d4b8ba4faf03857c8a2b920eee6","Cargo.toml":"ed90cef00235d8e2b9a3027e11baed38b66a2cf6003bccd805c056c1ec70c722","Cargo.toml.orig":"005452a286b000b817a3b0671af8d450894eea0f58e5563477844b70081752fc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"4da95ec4ecb65b738d470b7d762894ad9c97da93e6cbfb18b570fc2c96f4b871","README.md":"2264c34c62ea4c617d72047b00749b4786dfb9dff2fac24e0320170ee0cd19c8","benches/arraystring.rs":"fad1cecef71c290375befc77c75a868988b8d74135e8f8732bc5b58c85a8ab46","benches/extend.rs":"c38ecedbc88217a7e9fe1a73f916b168a96e48010a7ccd3dba5c3f8dea030d5d","src/array_string.rs":"9840c5b95af997584374467dfc365e4ab747175db8e0574be4f148454514fc8f","src/arrayvec.rs":"42923c20659346e48fd551529cb58b8e646c404637818ba466455665cb037dc4","src/arrayvec_impl.rs":"e2642ae566c83ef37ad9aec6af7e3c50af310ba304553f38b2a787666b507580","src/char.rs":"1de50e1d6045af2b3496426492315ba774986f9bc8301ffa391de861a08cc9cb","src/errors.rs":"7fa2ff2350f811d52a210a7346c526d6715cacefd38a46e2d3b57ab7dc62b1ab","src/lib.rs":"8919a7e0c20890b1f094996147a1486d20578579aef03692315cd509e1745222","src/utils.rs":"d1cdc508dfca385e63f1f57bc8b53ed4a7f515e4ac1ebaa97b1d543fc8369432","tests/borsh.rs":"4ea4d21cc311d68d8f234cd77699a88158af26cbc3a69ae1f25c0052663f861d","tests/serde.rs":"117eb2961b5954d13c577edf60bbb07cb7481685cc9d6c49760a981d71465849","tests/tests.rs":"19a9bce4b55506be9ffb7584f47dbfb1d59c66dbfaab55b7a28d827cc0411e78"},"package":"7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0aede877fe0bfb1ba5e3c2024df8c0958d503a83" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +name: Continuous integration + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + +jobs: + tests: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + matrix: + include: + - rust: 1.51.0 # MSRV + features: serde + experimental: false + - rust: 1.70.0 + features: serde + experimental: false + - rust: stable + features: + bench: true + experimental: false + - rust: beta + features: serde + experimental: false + - rust: nightly + features: serde, borsh, zeroize + experimental: false + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - name: Pin versions for MSRV + if: "${{ matrix.rust == '1.51.0' }}" + run: | + cargo update -p serde_test --precise 1.0.163 + cargo update -p serde --precise 1.0.69 + - name: Build + run: | + cargo build -v --no-default-features + cargo build --verbose --features "${{ matrix.features }}" + - name: Tests + run: | + cargo doc --verbose --features "${{ matrix.features }}" --no-deps + cargo test --verbose --features "${{ matrix.features }}" + cargo test --release --verbose --features "${{ matrix.features }}" + - name: Test run benchmarks + if: matrix.bench != '' + run: cargo test -v --benches + + nostd: + runs-on: ubuntu-latest + continue-on-error: false + strategy: + matrix: + include: + - rust: stable + target: thumbv6m-none-eabi + features: zeroize + + name: nostd/${{ matrix.target }}/${{ matrix.rust }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - name: Tests + run: | + cargo rustc "--target=${{ matrix.target }}" --no-default-features --features "${{ matrix.features }}" + + + miri: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Miri + run: | + rustup toolchain install nightly --component miri + rustup override set nightly + cargo miri setup + - name: Test with Miri + run: cargo miri test --all-features diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,328 @@ +Recent Changes (arrayvec) +========================= + +## 0.7.6 + +- Fix no-std build [#274](https://github.com/bluss/arrayvec/pull/274) + +## 0.7.5 + +- Add `as_ptr` and `as_mut_ptr` to `ArrayString` [@YuhanLiin](https://github.com/YuhanLiin) [#260](https://github.com/bluss/arrayvec/pull/260) +- Add borsh serialization support by @honzasp and @Fuuzetsu [#259](https://github.com/bluss/arrayvec/pull/259) +- Move length field before before data in ArrayVec and ArrayString by @JakkuSakura [#255](https://github.com/bluss/arrayvec/pull/255) +- Fix miri error for ZST case in extend by @bluss +- implement AsRef for ArrayString by [@Zoybean](https://github.com/Zoybean) [#218](https://github.com/bluss/arrayvec/pull/218) +- Fix typos in changelog by [@striezel](https://github.com/striezel) [#241](https://github.com/bluss/arrayvec/pull/241) +- Add `as_slice`, `as_mut_slice` methods to `IntoIter` by [@clarfonthey](https://github.com/clarfonthey) [#224](https://github.com/bluss/arrayvec/pull/224) + + +## 0.7.4 + +- Add feature zeroize to support the `Zeroize` trait by @elichai + +## 0.7.3 + +- Use track_caller on multiple methods like push and similar, for capacity + overflows by @kornelski +- impl BorrowMut for ArrayString by @msrd0 +- Fix stacked borrows violations by @clubby789 +- Update Miri CI by @RalfJung + +## 0.7.2 + +- Add `.as_mut_str()` to `ArrayString` by @clarfonthey +- Add `remaining_capacity` to `ArrayString` by @bhgomes +- Add `zero_filled` constructor by @c410-f3r +- Optimize `retain` by @TennyZhuang and @niklasf +- Make the following methods `const` by @bhgomes: + - len + - is_empty + - capacity + - is_full + - remaining_capacity + - CapacityError::new + +## 0.7.1 + +- Add new ArrayVec methods `.take()` and `.into_inner_unchecked()` by @conradludgate +- `clone_from` now uses `truncate` when needed by @a1phyr + +## 0.7.0 + +- `fn new_const` is now the way to const-construct arrayvec and arraystring, + and `fn new` has been reverted to a regular "non-const" function. + This works around performance issue #182, where the const fn version did not + optimize well. Change by @bluss with thanks to @rodrimati1992 and @niklasf + for analyzing the problem. + +- The deprecated feature flag `unstable-const-fn` was removed, since it's not needed + +- Optimize `.retain()` by using the same algorithm as in std, change by @niklasf, + issue #174. Original optimization in Rust std by @oxalica in rust-lang/rust/pull/81126 + +## 0.6.1 + +- The ``ArrayVec::new`` and ``ArrayString::new`` constructors are properly + const fns on stable and the feature flag ``unstable-const-fn`` is now deprecated. + by @rodrimati1992 + +- Small fix to the capacity check macro by @Xaeroxe +- Typo fix in documentation by @cuviper +- Small code cleanup by @bluss + +## 0.6.0 + +- The **const generics** release 🎉. Arrayvec finally implements what it + wanted to implement, since its first version: a vector backed by an array, + with generic parameters for the arbitrary element type *and* backing array + capacity. + + The New type syntax is `ArrayVec` where `CAP` is the arrayvec capacity. + For arraystring the syntax is `ArrayString`. + + Length is stored internally as u32; this limits the maximum capacity. The size + of the `ArrayVec` or `ArrayString` structs for the same capacity may grow + slightly compared with the previous version (depending on padding requirements + for the element type). Change by @bluss. + +- Arrayvec's `.extend()` and `FromIterator`/`.collect()` to arrayvec now + **panic** if the capacity of the arrayvec is exceeded. Change by @bluss. + +- Arraystring now implements `TryFrom<&str>` and `TryFrom` by + @c410-f3r + +- Minimum supported rust version is Rust 1.51 + +## 0.5.2 + +- Add `is_empty` methods for ArrayVec and ArrayString by @nicbn +- Implement `TryFrom` for ArrayVec by @paulkernfeld +- Add `unstable-const-fn` to make `new` methods const by @m-ou-se +- Run miri in CI and a few related fixes by @RalfJung +- Fix outdated comment by @Phlosioneer +- Move changelog to a separate file by @Luro02 +- Remove deprecated `Error::description` by @AnderEnder +- Use pointer method `add` by @hbina + +## 0.5.1 + +- Add `as_ptr`, `as_mut_ptr` accessors directly on the `ArrayVec` by @tbu- + (matches the same addition to `Vec` which happened in Rust 1.37). +- Add method `ArrayString::len` (now available directly, not just through deref to str). +- Use raw pointers instead of `&mut [u8]` for encoding chars into `ArrayString` + (uninit best practice fix). +- Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation + (uninit best practice fix). +- Changed inline hints on many methods, mainly removing inline hints +- `ArrayVec::dispose` is now deprecated (it has no purpose anymore) + +## 0.4.12 + +- Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation. + +## 0.5.0 + +- Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayVec` +- Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayString` +- The crate feature for serde serialization is now named `serde`. +- Updated the `Array` trait interface, and it is now easier to use for + users outside the crate. +- Add `FromStr` impl for `ArrayString` by @despawnerer +- Add method `try_extend_from_slice` to `ArrayVec`, which is always + efficient by @Thomasdezeeuw. +- Add method `remaining_capacity` by @Thomasdezeeuw +- Improve performance of the `extend` method. +- The index type of zero capacity vectors is now itself zero size, by + @clarfon +- Use `drop_in_place` for truncate and clear methods. This affects drop order + and resume from panic during drop. +- Use Rust 2018 edition for the implementation +- Require Rust 1.36 or later, for the unconditional `MaybeUninit` + improvements. + +## Older releases + +- 0.4.11 + + - In Rust 1.36 or later, use newly stable `MaybeUninit`. This extends the + soundness work introduced in 0.4.9, we are finally able to use this in + stable. We use feature detection (build script) to enable this at build + time. + +- 0.4.10 + + - Use `repr(C)` in the `union` version that was introduced in 0.4.9, to + allay some soundness concerns. + +- 0.4.9 + + - Use `union` in the implementation on when this is detected to be supported + (nightly only for now). This is a better solution for treating uninitialized + regions correctly, and we'll use it in stable Rust as soon as we are able. + When this is enabled, the `ArrayVec` has no space overhead in its memory + layout, although the size of the vec should not be relied upon. (See [#114](https://github.com/bluss/arrayvec/pull/114)) + - `ArrayString` updated to not use uninitialized memory, it instead zeros its + backing array. This will be refined in the next version, since we + need to make changes to the user visible API. + - The `use_union` feature now does nothing (like its documentation foretold). + + +- 0.4.8 + + - Implement Clone and Debug for `IntoIter` by @clarcharr + - Add more array sizes under crate features. These cover all in the range + up to 128 and 129 to 255 respectively (we have a few of those by default): + + - `array-size-33-128` + - `array-size-129-255` + +- 0.4.7 + + - Fix future compat warning about raw pointer casts + - Use `drop_in_place` when dropping the arrayvec by-value iterator + - Decrease minimum Rust version (see docs) by @jeehoonkang + +- 0.3.25 + + - Fix future compat warning about raw pointer casts + +- 0.4.6 + + - Fix compilation on 16-bit targets. This means, the 65536 array size is not + included on these targets. + +- 0.3.24 + + - Fix compilation on 16-bit targets. This means, the 65536 array size is not + included on these targets. + - Fix license files so that they are both included (was fixed in 0.4 before) + +- 0.4.5 + + - Add methods to `ArrayString` by @DenialAdams: + + - `.pop() -> Option` + - `.truncate(new_len)` + - `.remove(index) -> char` + + - Remove dependency on crate odds + - Document debug assertions in unsafe methods better + +- 0.4.4 + + - Add method `ArrayVec::truncate()` by @niklasf + +- 0.4.3 + + - Improve performance for `ArrayVec::extend` with a lower level + implementation (#74) + - Small cleanup in dependencies (use no std for crates where we don't need more) + +- 0.4.2 + + - Add constructor method `new` to `CapacityError`. + +- 0.4.1 + + - Add `Default` impl to `ArrayString` by @tbu- + +- 0.4.0 + + - Reformed signatures and error handling by @bluss and @tbu-: + + - `ArrayVec`'s `push, insert, remove, swap_remove` now match `Vec`'s + corresponding signature and panic on capacity errors where applicable. + - Add fallible methods `try_push, insert` and checked methods + `pop_at, swap_pop`. + - Similar changes to `ArrayString`'s push methods. + + - Use a local version of the `RangeArgument` trait + - Add array sizes 50, 150, 200 by @daboross + - Support serde 1.0 by @daboross + - New method `.push_unchecked()` by @niklasf + - `ArrayString` implements `PartialOrd, Ord` by @tbu- + - Require Rust 1.14 + - crate feature `use_generic_array` was dropped. + +- 0.3.23 + + - Implement `PartialOrd, Ord` as well as `PartialOrd` for + `ArrayString`. + +- 0.3.22 + + - Implement `Array` for the 65536 size + +- 0.3.21 + + - Use `encode_utf8` from crate odds + - Add constructor `ArrayString::from_byte_string` + +- 0.3.20 + + - Simplify and speed up `ArrayString`’s `.push(char)`- + +- 0.3.19 + + - Add new crate feature `use_generic_array` which allows using their + `GenericArray` just like a regular fixed size array for the storage + of an `ArrayVec`. + +- 0.3.18 + + - Fix bounds check in `ArrayVec::insert`! + It would be buggy if `self.len() < index < self.capacity()`. Take note of + the push out behavior specified in the docs. + +- 0.3.17 + + - Added crate feature `use_union` which forwards to the nodrop crate feature + - Added methods `.is_full()` to `ArrayVec` and `ArrayString`. + +- 0.3.16 + + - Added method `.retain()` to `ArrayVec`. + - Added methods `.as_slice(), .as_mut_slice()` to `ArrayVec` and `.as_str()` + to `ArrayString`. + +- 0.3.15 + + - Add feature std, which you can opt out of to use `no_std` (requires Rust 1.6 + to opt out). + - Implement `Clone::clone_from` for ArrayVec and ArrayString + +- 0.3.14 + + - Add `ArrayString::from(&str)` + +- 0.3.13 + + - Added `DerefMut` impl for `ArrayString`. + - Added method `.simplify()` to drop the element for `CapacityError`. + - Added method `.dispose()` to `ArrayVec` + +- 0.3.12 + + - Added ArrayString, a fixed capacity analogy of String + +- 0.3.11 + + - Added trait impls Default, PartialOrd, Ord, Write for ArrayVec + +- 0.3.10 + + - Go back to using external NoDrop, fixing a panic safety bug (issue #3) + +- 0.3.8 + + - Inline the non-dropping logic to remove one drop flag in the + ArrayVec representation. + +- 0.3.7 + + - Added method .into_inner() + - Added unsafe method .set_len() diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,111 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.51" +name = "arrayvec" +version = "0.7.6" +authors = ["bluss"] +build = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." +documentation = "https://docs.rs/arrayvec/" +readme = "README.md" +keywords = [ + "stack", + "vector", + "array", + "data-structure", + "no_std", +] +categories = [ + "data-structures", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/bluss/arrayvec" + +[package.metadata.docs.rs] +features = [ + "borsh", + "serde", + "zeroize", +] + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[profile.bench] +debug = 2 + +[profile.release] +debug = 2 + +[lib] +name = "arrayvec" +path = "src/lib.rs" + +[[test]] +name = "borsh" +path = "tests/borsh.rs" + +[[test]] +name = "serde" +path = "tests/serde.rs" + +[[test]] +name = "tests" +path = "tests/tests.rs" + +[[bench]] +name = "arraystring" +path = "benches/arraystring.rs" +harness = false + +[[bench]] +name = "extend" +path = "benches/extend.rs" +harness = false + +[dependencies.borsh] +version = "1.2.0" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.zeroize] +version = "1.4" +optional = true +default-features = false + +[dev-dependencies.bencher] +version = "0.1.4" + +[dev-dependencies.matches] +version = "0.1" + +[dev-dependencies.serde_test] +version = "1.0" + +[build-dependencies] + +[features] +default = ["std"] +std = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +[package] +name = "arrayvec" +version = "0.7.6" +authors = ["bluss"] +license = "MIT OR Apache-2.0" +edition = "2018" +rust-version = "1.51" + +description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." +documentation = "https://docs.rs/arrayvec/" +repository = "https://github.com/bluss/arrayvec" + +keywords = ["stack", "vector", "array", "data-structure", "no_std"] +categories = ["data-structures", "no-std"] + +[build-dependencies] + +[dependencies.borsh] +version = "1.2.0" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.zeroize] +version = "1.4" +optional = true +default-features = false + +[dev-dependencies.serde_test] +version = "1.0" + +[dev-dependencies] +matches = { version = "0.1" } +bencher = "0.1.4" + +[[bench]] +name = "extend" +harness = false + +[[bench]] +name = "arraystring" +harness = false + +[features] +default = ["std"] +std = [] + +[profile.bench] +debug = true +[profile.release] +debug = true + +[package.metadata.docs.rs] +features = ["borsh", "serde", "zeroize"] + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) Ulrik Sverdrup "bluss" 2015-2023 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/README.md clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ + +arrayvec +======== +[![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) +[![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) +[![Build Status](https://github.com/bluss/arrayvec/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/arrayvec/actions) + + + + +[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE) +OR +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +A vector with fixed capacity. + +Please read the [`API documentation here`](https://docs.rs/arrayvec) + +# License + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +http://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/benches/arraystring.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/arraystring.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/benches/arraystring.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/arraystring.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,90 @@ + +extern crate arrayvec; +#[macro_use] extern crate bencher; + +use arrayvec::ArrayString; + +use bencher::Bencher; + +fn try_push_c(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + b.iter(|| { + v.clear(); + while v.try_push('c').is_ok() { + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn try_push_alpha(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + b.iter(|| { + v.clear(); + while v.try_push('α').is_ok() { + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +// Yes, pushing a string char-by-char is slow. Use .push_str. +fn try_push_string(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + let input = "abcαβγ“”"; + b.iter(|| { + v.clear(); + for ch in input.chars().cycle() { + if !v.try_push(ch).is_ok() { + break; + } + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_c(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + b.iter(|| { + v.clear(); + while !v.is_full() { + v.push('c'); + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_alpha(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + b.iter(|| { + v.clear(); + while !v.is_full() { + v.push('α'); + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_string(b: &mut Bencher) { + let mut v = ArrayString::<512>::new(); + let input = "abcαβγ“”"; + b.iter(|| { + v.clear(); + for ch in input.chars().cycle() { + if !v.is_full() { + v.push(ch); + } else { + break; + } + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +benchmark_group!(benches, try_push_c, try_push_alpha, try_push_string, push_c, + push_alpha, push_string); +benchmark_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/benches/extend.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/extend.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/benches/extend.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/benches/extend.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ + +extern crate arrayvec; +#[macro_use] extern crate bencher; + +use std::io::Write; + +use arrayvec::ArrayVec; + +use bencher::Bencher; +use bencher::black_box; + +fn extend_with_constant(b: &mut Bencher) { + let mut v = ArrayVec::::new(); + let cap = v.capacity(); + b.iter(|| { + v.clear(); + let constant = black_box(1); + v.extend((0..cap).map(move |_| constant)); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_range(b: &mut Bencher) { + let mut v = ArrayVec::::new(); + let cap = v.capacity(); + b.iter(|| { + v.clear(); + let range = 0..cap; + v.extend(range.map(|x| black_box(x as _))); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_slice(b: &mut Bencher) { + let mut v = ArrayVec::::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + let iter = data.iter().map(|&x| x); + v.extend(iter); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_write(b: &mut Bencher) { + let mut v = ArrayVec::::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + v.write(&data[..]).ok(); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_from_slice(b: &mut Bencher) { + let mut v = ArrayVec::::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + v.try_extend_from_slice(&data).ok(); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +benchmark_group!(benches, + extend_with_constant, + extend_with_range, + extend_with_slice, + extend_with_write, + extend_from_slice +); + +benchmark_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/array_string.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/array_string.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/array_string.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/array_string.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,716 @@ +use std::borrow::{Borrow, BorrowMut}; +use std::cmp; +use std::convert::TryFrom; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::mem::MaybeUninit; +use std::ops::{Deref, DerefMut}; +#[cfg(feature="std")] +use std::path::Path; +use std::ptr; +use std::slice; +use std::str; +use std::str::FromStr; +use std::str::Utf8Error; + +use crate::CapacityError; +use crate::LenUint; +use crate::char::encode_utf8; +use crate::utils::MakeMaybeUninit; + +#[cfg(feature="serde")] +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + + +/// A string with a fixed capacity. +/// +/// The `ArrayString` is a string backed by a fixed size array. It keeps track +/// of its length, and is parameterized by `CAP` for the maximum capacity. +/// +/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger +/// arrayvecs with larger capacity will panic. +/// +/// The string is a contiguous value that you can store directly on the stack +/// if needed. +#[derive(Copy)] +#[repr(C)] +pub struct ArrayString { + // the `len` first elements of the array are initialized + len: LenUint, + xs: [MaybeUninit; CAP], +} + +impl Default for ArrayString +{ + /// Return an empty `ArrayString` + fn default() -> ArrayString { + ArrayString::new() + } +} + +impl ArrayString +{ + /// Create a new empty `ArrayString`. + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<16>::new(); + /// string.push_str("foo"); + /// assert_eq!(&string[..], "foo"); + /// assert_eq!(string.capacity(), 16); + /// ``` + pub fn new() -> ArrayString { + assert_capacity_limit!(CAP); + unsafe { + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } + } + } + + /// Create a new empty `ArrayString` (const fn). + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); + /// ``` + pub const fn new_const() -> ArrayString { + assert_capacity_limit_const!(CAP); + ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } + } + + /// Return the length of the string. + #[inline] + pub const fn len(&self) -> usize { self.len as usize } + + /// Returns whether the string is empty. + #[inline] + pub const fn is_empty(&self) -> bool { self.len() == 0 } + + /// Create a new `ArrayString` from a `str`. + /// + /// Capacity is inferred from the type parameter. + /// + /// **Errors** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<3>::from("foo").unwrap(); + /// assert_eq!(&string[..], "foo"); + /// assert_eq!(string.len(), 3); + /// assert_eq!(string.capacity(), 3); + /// ``` + pub fn from(s: &str) -> Result> { + let mut arraystr = Self::new(); + arraystr.try_push_str(s)?; + Ok(arraystr) + } + + /// Create a new `ArrayString` from a byte string literal. + /// + /// **Errors** if the byte string literal is not valid UTF-8. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); + /// ``` + pub fn from_byte_string(b: &[u8; CAP]) -> Result { + let len = str::from_utf8(b)?.len(); + debug_assert_eq!(len, CAP); + let mut vec = Self::new(); + unsafe { + (b as *const [u8; CAP] as *const [MaybeUninit; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); + vec.set_len(CAP); + } + Ok(vec) + } + + /// Create a new `ArrayString` value fully filled with ASCII NULL characters (`\0`). Useful + /// to be used as a buffer to collect external data or as a buffer for intermediate processing. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::<16>::zero_filled(); + /// assert_eq!(string.len(), 16); + /// ``` + #[inline] + pub fn zero_filled() -> Self { + assert_capacity_limit!(CAP); + // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and + // `zeroed` fully fills the array with nulls. + unsafe { + ArrayString { + xs: MaybeUninit::zeroed().assume_init(), + len: CAP as _ + } + } + } + + /// Return the capacity of the `ArrayString`. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::<3>::new(); + /// assert_eq!(string.capacity(), 3); + /// ``` + #[inline(always)] + pub const fn capacity(&self) -> usize { CAP } + + /// Return if the `ArrayString` is completely filled. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<1>::new(); + /// assert!(!string.is_full()); + /// string.push_str("A"); + /// assert!(string.is_full()); + /// ``` + pub const fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Returns the capacity left in the `ArrayString`. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<3>::from("abc").unwrap(); + /// string.pop(); + /// assert_eq!(string.remaining_capacity(), 1); + /// ``` + pub const fn remaining_capacity(&self) -> usize { + self.capacity() - self.len() + } + + /// Adds the given char to the end of the string. + /// + /// ***Panics*** if the backing array is not large enough to fit the additional char. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<2>::new(); + /// + /// string.push('a'); + /// string.push('b'); + /// + /// assert_eq!(&string[..], "ab"); + /// ``` + #[track_caller] + pub fn push(&mut self, c: char) { + self.try_push(c).unwrap(); + } + + /// Adds the given char to the end of the string. + /// + /// Returns `Ok` if the push succeeds. + /// + /// **Errors** if the backing array is not large enough to fit the additional char. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<2>::new(); + /// + /// string.try_push('a').unwrap(); + /// string.try_push('b').unwrap(); + /// let overflow = string.try_push('c'); + /// + /// assert_eq!(&string[..], "ab"); + /// assert_eq!(overflow.unwrap_err().element(), 'c'); + /// ``` + pub fn try_push(&mut self, c: char) -> Result<(), CapacityError> { + let len = self.len(); + unsafe { + let ptr = self.as_mut_ptr().add(len); + let remaining_cap = self.capacity() - len; + match encode_utf8(c, ptr, remaining_cap) { + Ok(n) => { + self.set_len(len + n); + Ok(()) + } + Err(_) => Err(CapacityError::new(c)), + } + } + } + + /// Adds the given string slice to the end of the string. + /// + /// ***Panics*** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<2>::new(); + /// + /// string.push_str("a"); + /// string.push_str("d"); + /// + /// assert_eq!(&string[..], "ad"); + /// ``` + #[track_caller] + pub fn push_str(&mut self, s: &str) { + self.try_push_str(s).unwrap() + } + + /// Adds the given string slice to the end of the string. + /// + /// Returns `Ok` if the push succeeds. + /// + /// **Errors** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<2>::new(); + /// + /// string.try_push_str("a").unwrap(); + /// let overflow1 = string.try_push_str("bc"); + /// string.try_push_str("d").unwrap(); + /// let overflow2 = string.try_push_str("ef"); + /// + /// assert_eq!(&string[..], "ad"); + /// assert_eq!(overflow1.unwrap_err().element(), "bc"); + /// assert_eq!(overflow2.unwrap_err().element(), "ef"); + /// ``` + pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { + if s.len() > self.capacity() - self.len() { + return Err(CapacityError::new(s)); + } + unsafe { + let dst = self.as_mut_ptr().add(self.len()); + let src = s.as_ptr(); + ptr::copy_nonoverlapping(src, dst, s.len()); + let newl = self.len() + s.len(); + self.set_len(newl); + } + Ok(()) + } + + /// Removes the last character from the string and returns it. + /// + /// Returns `None` if this `ArrayString` is empty. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut s = ArrayString::<3>::from("foo").unwrap(); + /// + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('f')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option { + let ch = match self.chars().rev().next() { + Some(ch) => ch, + None => return None, + }; + let new_len = self.len() - ch.len_utf8(); + unsafe { + self.set_len(new_len); + } + Some(ch) + } + + /// Shortens this `ArrayString` to the specified length. + /// + /// If `new_len` is greater than the string’s current length, this has no + /// effect. + /// + /// ***Panics*** if `new_len` does not lie on a `char` boundary. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<6>::from("foobar").unwrap(); + /// string.truncate(3); + /// assert_eq!(&string[..], "foo"); + /// string.truncate(4); + /// assert_eq!(&string[..], "foo"); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + unsafe { + // In libstd truncate is called on the underlying vector, + // which in turns drops each element. + // As we know we don't have to worry about Drop, + // we can just set the length (a la clear.) + self.set_len(new_len); + } + } + } + + /// Removes a `char` from this `ArrayString` at a byte position and returns it. + /// + /// This is an `O(n)` operation, as it requires copying every element in the + /// array. + /// + /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length, + /// or if it does not lie on a `char` boundary. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut s = ArrayString::<3>::from("foo").unwrap(); + /// + /// assert_eq!(s.remove(0), 'f'); + /// assert_eq!(s.remove(1), 'o'); + /// assert_eq!(s.remove(0), 'o'); + /// ``` + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + let ptr = self.as_mut_ptr(); + unsafe { + ptr::copy( + ptr.add(next), + ptr.add(idx), + len - next); + self.set_len(len - (next - idx)); + } + ch + } + + /// Make the string empty. + pub fn clear(&mut self) { + unsafe { + self.set_len(0); + } + } + + /// Set the strings’s length. + /// + /// This function is `unsafe` because it changes the notion of the + /// number of “valid” bytes in the string. Use with care. + /// + /// This method uses *debug assertions* to check the validity of `length` + /// and may use other debug assertions. + pub unsafe fn set_len(&mut self, length: usize) { + // type invariant that capacity always fits in LenUint + debug_assert!(length <= self.capacity()); + self.len = length as LenUint; + } + + /// Return a string slice of the whole `ArrayString`. + pub fn as_str(&self) -> &str { + self + } + + /// Return a mutable string slice of the whole `ArrayString`. + pub fn as_mut_str(&mut self) -> &mut str { + self + } + + /// Return a raw pointer to the string's buffer. + pub fn as_ptr(&self) -> *const u8 { + self.xs.as_ptr() as *const u8 + } + + /// Return a raw mutable pointer to the string's buffer. + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.xs.as_mut_ptr() as *mut u8 + } +} + +impl Deref for ArrayString +{ + type Target = str; + #[inline] + fn deref(&self) -> &str { + unsafe { + let sl = slice::from_raw_parts(self.as_ptr(), self.len()); + str::from_utf8_unchecked(sl) + } + } +} + +impl DerefMut for ArrayString +{ + #[inline] + fn deref_mut(&mut self) -> &mut str { + unsafe { + let len = self.len(); + let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len); + str::from_utf8_unchecked_mut(sl) + } + } +} + +impl PartialEq for ArrayString +{ + fn eq(&self, rhs: &Self) -> bool { + **self == **rhs + } +} + +impl PartialEq for ArrayString +{ + fn eq(&self, rhs: &str) -> bool { + &**self == rhs + } +} + +impl PartialEq> for str +{ + fn eq(&self, rhs: &ArrayString) -> bool { + self == &**rhs + } +} + +impl Eq for ArrayString +{ } + +impl Hash for ArrayString +{ + fn hash(&self, h: &mut H) { + (**self).hash(h) + } +} + +impl Borrow for ArrayString +{ + fn borrow(&self) -> &str { self } +} + +impl BorrowMut for ArrayString +{ + fn borrow_mut(&mut self) -> &mut str { self } +} + +impl AsRef for ArrayString +{ + fn as_ref(&self) -> &str { self } +} + +impl fmt::Debug for ArrayString +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +#[cfg(feature="std")] +impl AsRef for ArrayString { + fn as_ref(&self) -> &Path { + self.as_str().as_ref() + } +} + +impl fmt::Display for ArrayString +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +/// `Write` appends written data to the end of the string. +impl fmt::Write for ArrayString +{ + fn write_char(&mut self, c: char) -> fmt::Result { + self.try_push(c).map_err(|_| fmt::Error) + } + + fn write_str(&mut self, s: &str) -> fmt::Result { + self.try_push_str(s).map_err(|_| fmt::Error) + } +} + +impl Clone for ArrayString +{ + fn clone(&self) -> ArrayString { + *self + } + fn clone_from(&mut self, rhs: &Self) { + // guaranteed to fit due to types matching. + self.clear(); + self.try_push_str(rhs).ok(); + } +} + +impl PartialOrd for ArrayString +{ + fn partial_cmp(&self, rhs: &Self) -> Option { + (**self).partial_cmp(&**rhs) + } + fn lt(&self, rhs: &Self) -> bool { **self < **rhs } + fn le(&self, rhs: &Self) -> bool { **self <= **rhs } + fn gt(&self, rhs: &Self) -> bool { **self > **rhs } + fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } +} + +impl PartialOrd for ArrayString +{ + fn partial_cmp(&self, rhs: &str) -> Option { + (**self).partial_cmp(rhs) + } + fn lt(&self, rhs: &str) -> bool { &**self < rhs } + fn le(&self, rhs: &str) -> bool { &**self <= rhs } + fn gt(&self, rhs: &str) -> bool { &**self > rhs } + fn ge(&self, rhs: &str) -> bool { &**self >= rhs } +} + +impl PartialOrd> for str +{ + fn partial_cmp(&self, rhs: &ArrayString) -> Option { + self.partial_cmp(&**rhs) + } + fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } +} + +impl Ord for ArrayString +{ + fn cmp(&self, rhs: &Self) -> cmp::Ordering { + (**self).cmp(&**rhs) + } +} + +impl FromStr for ArrayString +{ + type Err = CapacityError; + + fn from_str(s: &str) -> Result { + Self::from(s).map_err(CapacityError::simplify) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl Serialize for ArrayString +{ + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_str(&*self) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString +{ + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + use serde::de::{self, Visitor}; + use std::marker::PhantomData; + + struct ArrayStringVisitor(PhantomData<[u8; CAP]>); + + impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { + type Value = ArrayString; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a string no more than {} bytes long", CAP) + } + + fn visit_str(self, v: &str) -> Result + where E: de::Error, + { + ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: de::Error, + { + let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?; + + ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self)) + } + } + + deserializer.deserialize_str(ArrayStringVisitor(PhantomData)) + } +} + +#[cfg(feature = "borsh")] +/// Requires crate feature `"borsh"` +impl borsh::BorshSerialize for ArrayString { + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + ::serialize(&*self, writer) + } +} + +#[cfg(feature = "borsh")] +/// Requires crate feature `"borsh"` +impl borsh::BorshDeserialize for ArrayString { + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let len = ::deserialize_reader(reader)? as usize; + if len > CAP { + return Err(borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + format!("Expected a string no more than {} bytes long", CAP), + )) + } + + let mut buf = [0u8; CAP]; + let buf = &mut buf[..len]; + reader.read_exact(buf)?; + + let s = str::from_utf8(&buf).map_err(|err| { + borsh::io::Error::new(borsh::io::ErrorKind::InvalidData, err.to_string()) + })?; + Ok(Self::from(s).unwrap()) + } +} + +impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString +{ + type Error = CapacityError<&'a str>; + + fn try_from(f: &'a str) -> Result { + let mut v = Self::new(); + v.try_push_str(f)?; + Ok(v) + } +} + +impl<'a, const CAP: usize> TryFrom> for ArrayString +{ + type Error = CapacityError; + + fn try_from(f: fmt::Arguments<'a>) -> Result { + use fmt::Write; + let mut v = Self::new(); + v.write_fmt(f).map_err(|e| CapacityError::new(e))?; + Ok(v) + } +} + +#[cfg(feature = "zeroize")] +/// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled. +/// +/// The length is set to 0, and the buffer is dropped and zeroized. +/// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack. +/// +/// ``` +/// use arrayvec::ArrayString; +/// use zeroize::Zeroize; +/// let mut string = ArrayString::<6>::from("foobar").unwrap(); +/// string.zeroize(); +/// assert_eq!(string.len(), 0); +/// unsafe { string.set_len(string.capacity()) }; +/// assert_eq!(&*string, "\0\0\0\0\0\0"); +/// ``` +impl zeroize::Zeroize for ArrayString { + fn zeroize(&mut self) { + // There are no elements to drop + self.clear(); + // Zeroize the backing array. + self.xs.zeroize(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/arrayvec.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/arrayvec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1348 @@ + +use std::cmp; +use std::iter; +use std::mem; +use std::ops::{Bound, Deref, DerefMut, RangeBounds}; +use std::ptr; +use std::slice; + +// extra traits +use std::borrow::{Borrow, BorrowMut}; +use std::hash::{Hash, Hasher}; +use std::fmt; + +#[cfg(feature="std")] +use std::io; + +use std::mem::ManuallyDrop; +use std::mem::MaybeUninit; + +#[cfg(feature="serde")] +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + +use crate::LenUint; +use crate::errors::CapacityError; +use crate::arrayvec_impl::ArrayVecImpl; +use crate::utils::MakeMaybeUninit; + +/// A vector with a fixed capacity. +/// +/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of +/// the number of initialized elements. The `ArrayVec` is parameterized +/// by `T` for the element type and `CAP` for the maximum capacity. +/// +/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger +/// arrayvecs with larger capacity will panic. +/// +/// The vector is a contiguous value (storing the elements inline) that you can store directly on +/// the stack if needed. +/// +/// It offers a simple API but also dereferences to a slice, so that the full slice API is +/// available. The ArrayVec can be converted into a by value iterator. +#[repr(C)] +pub struct ArrayVec { + len: LenUint, + // the `len` first elements of the array are initialized + xs: [MaybeUninit; CAP], +} + +impl Drop for ArrayVec { + fn drop(&mut self) { + self.clear(); + + // MaybeUninit inhibits array's drop + } +} + +macro_rules! panic_oob { + ($method_name:expr, $index:expr, $len:expr) => { + panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"), + $index, $len) + } +} + +impl ArrayVec { + /// Capacity + const CAPACITY: usize = CAP; + + /// Create a new empty `ArrayVec`. + /// + /// The maximum capacity is given by the generic parameter `CAP`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 16>::new(); + /// array.push(1); + /// array.push(2); + /// assert_eq!(&array[..], &[1, 2]); + /// assert_eq!(array.capacity(), 16); + /// ``` + #[inline] + #[track_caller] + pub fn new() -> ArrayVec { + assert_capacity_limit!(CAP); + unsafe { + ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } + } + } + + /// Create a new empty `ArrayVec` (const fn). + /// + /// The maximum capacity is given by the generic parameter `CAP`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// static ARRAY: ArrayVec = ArrayVec::new_const(); + /// ``` + pub const fn new_const() -> ArrayVec { + assert_capacity_limit_const!(CAP); + ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } + } + + /// Return the number of elements in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.len(), 2); + /// ``` + #[inline(always)] + pub const fn len(&self) -> usize { self.len as usize } + + /// Returns whether the `ArrayVec` is empty. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1]); + /// array.pop(); + /// assert_eq!(array.is_empty(), true); + /// ``` + #[inline] + pub const fn is_empty(&self) -> bool { self.len() == 0 } + + /// Return the capacity of the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let array = ArrayVec::from([1, 2, 3]); + /// assert_eq!(array.capacity(), 3); + /// ``` + #[inline(always)] + pub const fn capacity(&self) -> usize { CAP } + + /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 1>::new(); + /// assert!(!array.is_full()); + /// array.push(1); + /// assert!(array.is_full()); + /// ``` + pub const fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Returns the capacity left in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.remaining_capacity(), 1); + /// ``` + pub const fn remaining_capacity(&self) -> usize { + self.capacity() - self.len() + } + + /// Push `element` to the end of the vector. + /// + /// ***Panics*** if the vector is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.push(1); + /// array.push(2); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + #[track_caller] + pub fn push(&mut self, element: T) { + ArrayVecImpl::push(self, element) + } + + /// Push `element` to the end of the vector. + /// + /// Return `Ok` if the push succeeds, or return an error if the vector + /// is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// let push1 = array.try_push(1); + /// let push2 = array.try_push(2); + /// + /// assert!(push1.is_ok()); + /// assert!(push2.is_ok()); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// + /// let overflow = array.try_push(3); + /// + /// assert!(overflow.is_err()); + /// ``` + pub fn try_push(&mut self, element: T) -> Result<(), CapacityError> { + ArrayVecImpl::try_push(self, element) + } + + /// Push `element` to the end of the vector without checking the capacity. + /// + /// It is up to the caller to ensure the capacity of the vector is + /// sufficiently large. + /// + /// This method uses *debug assertions* to check that the arrayvec is not full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// if array.len() + 2 <= array.capacity() { + /// unsafe { + /// array.push_unchecked(1); + /// array.push_unchecked(2); + /// } + /// } + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + pub unsafe fn push_unchecked(&mut self, element: T) { + ArrayVecImpl::push_unchecked(self, element) + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector’s current length this has no + /// effect. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); + /// array.truncate(3); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// array.truncate(4); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + ArrayVecImpl::truncate(self, new_len) + } + + /// Remove all elements in the vector. + pub fn clear(&mut self) { + ArrayVecImpl::clear(self) + } + + + /// Get pointer to where element at `index` would be + unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { + self.as_mut_ptr().add(index) + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`. + /// + /// It is an error if the index is greater than the length or if the + /// arrayvec is full. + /// + /// ***Panics*** if the array is full or the `index` is out of bounds. See + /// `try_insert` for fallible version. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.insert(0, "x"); + /// array.insert(0, "y"); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + #[track_caller] + pub fn insert(&mut self, index: usize, element: T) { + self.try_insert(index, element).unwrap() + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`; the `index` must be less than + /// or equal to the length. + /// + /// Returns an error if vector is already at full capacity. + /// + /// ***Panics*** `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// assert!(array.try_insert(0, "x").is_ok()); + /// assert!(array.try_insert(0, "y").is_ok()); + /// assert!(array.try_insert(0, "z").is_err()); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError> { + if index > self.len() { + panic_oob!("try_insert", index, self.len()) + } + if self.len() == self.capacity() { + return Err(CapacityError::new(element)); + } + let len = self.len(); + + // follows is just like Vec + unsafe { // infallible + // The spot to put the new value + { + let p: *mut _ = self.get_unchecked_ptr(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + Ok(()) + } + + /// Remove the last element in the vector and return it. + /// + /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.push(1); + /// + /// assert_eq!(array.pop(), Some(1)); + /// assert_eq!(array.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option { + ArrayVecImpl::pop(self) + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This operation is O(1). + /// + /// Return the *element* if the index is in bounds, else panic. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_remove(0), 1); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_remove(1), 2); + /// assert_eq!(&array[..], &[3]); + /// ``` + pub fn swap_remove(&mut self, index: usize) -> T { + self.swap_pop(index) + .unwrap_or_else(|| { + panic_oob!("swap_remove", index, self.len()) + }) + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This is a checked version of `.swap_remove`. + /// This operation is O(1). + /// + /// Return `Some(` *element* `)` if the index is in bounds, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_pop(0), Some(1)); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_pop(10), None); + /// ``` + pub fn swap_pop(&mut self, index: usize) -> Option { + let len = self.len(); + if index >= len { + return None; + } + self.swap(index, len - 1); + self.pop() + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// The `index` must be strictly less than the length of the vector. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// let removed_elt = array.remove(0); + /// assert_eq!(removed_elt, 1); + /// assert_eq!(&array[..], &[2, 3]); + /// ``` + pub fn remove(&mut self, index: usize) -> T { + self.pop_at(index) + .unwrap_or_else(|| { + panic_oob!("remove", index, self.len()) + }) + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// This is a checked version of `.remove(index)`. Returns `None` if there + /// is no element at `index`. Otherwise, return the element inside `Some`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert!(array.pop_at(0).is_some()); + /// assert_eq!(&array[..], &[2, 3]); + /// + /// assert!(array.pop_at(2).is_none()); + /// assert!(array.pop_at(10).is_none()); + /// ``` + pub fn pop_at(&mut self, index: usize) -> Option { + if index >= self.len() { + None + } else { + self.drain(index..index + 1).next() + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns false. + /// This method operates in place and preserves the order of the retained + /// elements. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4]); + /// array.retain(|x| *x & 1 != 0 ); + /// assert_eq!(&array[..], &[1, 3]); + /// ``` + pub fn retain(&mut self, mut f: F) + where F: FnMut(&mut T) -> bool + { + // Check the implementation of + // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain + // for safety arguments (especially regarding panics in f and when + // dropping elements). Implementation closely mirrored here. + + let original_len = self.len(); + unsafe { self.set_len(0) }; + + struct BackshiftOnDrop<'a, T, const CAP: usize> { + v: &'a mut ArrayVec, + processed_len: usize, + deleted_cnt: usize, + original_len: usize, + } + + impl Drop for BackshiftOnDrop<'_, T, CAP> { + fn drop(&mut self) { + if self.deleted_cnt > 0 { + unsafe { + ptr::copy( + self.v.as_ptr().add(self.processed_len), + self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), + self.original_len - self.processed_len + ); + } + } + unsafe { + self.v.set_len(self.original_len - self.deleted_cnt); + } + } + } + + let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; + + #[inline(always)] + fn process_one bool, T, const CAP: usize, const DELETED: bool>( + f: &mut F, + g: &mut BackshiftOnDrop<'_, T, CAP> + ) -> bool { + let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) }; + if !f(unsafe { &mut *cur }) { + g.processed_len += 1; + g.deleted_cnt += 1; + unsafe { ptr::drop_in_place(cur) }; + return false; + } + if DELETED { + unsafe { + let hole_slot = cur.sub(g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; + true + } + + // Stage 1: Nothing was deleted. + while g.processed_len != original_len { + if !process_one::(&mut f, &mut g) { + break; + } + } + + // Stage 2: Some elements were deleted. + while g.processed_len != original_len { + process_one::(&mut f, &mut g); + } + + drop(g); + } + + /// Set the vector’s length without dropping or moving out elements + /// + /// This method is `unsafe` because it changes the notion of the + /// number of “valid” elements in the vector. Use with care. + /// + /// This method uses *debug assertions* to check that `length` is + /// not greater than the capacity. + pub unsafe fn set_len(&mut self, length: usize) { + // type invariant that capacity always fits in LenUint + debug_assert!(length <= self.capacity()); + self.len = length as LenUint; + } + + /// Copy all elements from the slice and append to the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut vec: ArrayVec = ArrayVec::new(); + /// vec.push(1); + /// vec.try_extend_from_slice(&[2, 3]).unwrap(); + /// assert_eq!(&vec[..], &[1, 2, 3]); + /// ``` + /// + /// # Errors + /// + /// This method will return an error if the capacity left (see + /// [`remaining_capacity`]) is smaller then the length of the provided + /// slice. + /// + /// [`remaining_capacity`]: #method.remaining_capacity + pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError> + where T: Copy, + { + if self.remaining_capacity() < other.len() { + return Err(CapacityError::new(())); + } + + let self_len = self.len(); + let other_len = other.len(); + + unsafe { + let dst = self.get_unchecked_ptr(self_len); + ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); + self.set_len(self_len + other_len); + } + Ok(()) + } + + /// Create a draining iterator that removes the specified range in the vector + /// and yields the removed items from start to end. The element range is + /// removed even if the iterator is not consumed until the end. + /// + /// Note: It is unspecified how many elements are removed from the vector, + /// if the `Drain` value is leaked. + /// + /// **Panics** if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut v1 = ArrayVec::from([1, 2, 3]); + /// let v2: ArrayVec<_, 3> = v1.drain(0..2).collect(); + /// assert_eq!(&v1[..], &[3]); + /// assert_eq!(&v2[..], &[1, 2]); + /// ``` + pub fn drain(&mut self, range: R) -> Drain + where R: RangeBounds + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(&i) => i, + Bound::Excluded(&i) => i.saturating_add(1), + }; + let end = match range.end_bound() { + Bound::Excluded(&j) => j, + Bound::Included(&j) => j.saturating_add(1), + Bound::Unbounded => len, + }; + self.drain_range(start, end) + } + + fn drain_range(&mut self, start: usize, end: usize) -> Drain + { + let len = self.len(); + + // bounds check happens here (before length is changed!) + let range_slice: *const _ = &self[start..end]; + + // Calling `set_len` creates a fresh and thus unique mutable references, making all + // older aliases we created invalid. So we cannot call that function. + self.len = start as LenUint; + + unsafe { + Drain { + tail_start: end, + tail_len: len - end, + iter: (*range_slice).iter(), + vec: self as *mut _, + } + } + } + + /// Return the inner fixed size array, if it is full to its capacity. + /// + /// Return an `Ok` value with the array if length equals capacity, + /// return an `Err` with self otherwise. + pub fn into_inner(self) -> Result<[T; CAP], Self> { + if self.len() < self.capacity() { + Err(self) + } else { + unsafe { Ok(self.into_inner_unchecked()) } + } + } + + /// Return the inner fixed size array. + /// + /// Safety: + /// This operation is safe if and only if length equals capacity. + pub unsafe fn into_inner_unchecked(self) -> [T; CAP] { + debug_assert_eq!(self.len(), self.capacity()); + let self_ = ManuallyDrop::new(self); + let array = ptr::read(self_.as_ptr() as *const [T; CAP]); + array + } + + /// Returns the ArrayVec, replacing the original with a new empty ArrayVec. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut v = ArrayVec::from([0, 1, 2, 3]); + /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap()); + /// assert!(v.is_empty()); + /// ``` + pub fn take(&mut self) -> Self { + mem::replace(self, Self::new()) + } + + /// Return a slice containing all elements of the vector. + pub fn as_slice(&self) -> &[T] { + ArrayVecImpl::as_slice(self) + } + + /// Return a mutable slice containing all elements of the vector. + pub fn as_mut_slice(&mut self) -> &mut [T] { + ArrayVecImpl::as_mut_slice(self) + } + + /// Return a raw pointer to the vector's buffer. + pub fn as_ptr(&self) -> *const T { + ArrayVecImpl::as_ptr(self) + } + + /// Return a raw mutable pointer to the vector's buffer. + pub fn as_mut_ptr(&mut self) -> *mut T { + ArrayVecImpl::as_mut_ptr(self) + } +} + +impl ArrayVecImpl for ArrayVec { + type Item = T; + const CAPACITY: usize = CAP; + + fn len(&self) -> usize { self.len() } + + unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= CAP); + self.len = length as LenUint; + } + + fn as_ptr(&self) -> *const Self::Item { + self.xs.as_ptr() as _ + } + + fn as_mut_ptr(&mut self) -> *mut Self::Item { + self.xs.as_mut_ptr() as _ + } +} + +impl Deref for ArrayVec { + type Target = [T]; + #[inline] + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl DerefMut for ArrayVec { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() + } +} + + +/// Create an `ArrayVec` from an array. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 3); +/// ``` +impl From<[T; CAP]> for ArrayVec { + #[track_caller] + fn from(array: [T; CAP]) -> Self { + let array = ManuallyDrop::new(array); + let mut vec = >::new(); + unsafe { + (&*array as *const [T; CAP] as *const [MaybeUninit; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); + vec.set_len(CAP); + } + vec + } +} + + +/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to +/// fit. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// use std::convert::TryInto as _; +/// +/// let array: ArrayVec<_, 4> = (&[1, 2, 3] as &[_]).try_into().unwrap(); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 4); +/// ``` +impl std::convert::TryFrom<&[T]> for ArrayVec + where T: Clone, +{ + type Error = CapacityError; + + fn try_from(slice: &[T]) -> Result { + if Self::CAPACITY < slice.len() { + Err(CapacityError::new(())) + } else { + let mut array = Self::new(); + array.extend_from_slice(slice); + Ok(array) + } + } +} + + +/// Iterate the `ArrayVec` with references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &array { +/// // ... +/// } +/// ``` +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +/// Iterate the `ArrayVec` with mutable references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &mut array { +/// // ... +/// } +/// ``` +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } +} + +/// Iterate the `ArrayVec` with each element by value. +/// +/// The vector is consumed by this operation. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// for elt in ArrayVec::from([1, 2, 3]) { +/// // ... +/// } +/// ``` +impl IntoIterator for ArrayVec { + type Item = T; + type IntoIter = IntoIter; + fn into_iter(self) -> IntoIter { + IntoIter { index: 0, v: self, } + } +} + + +#[cfg(feature = "zeroize")] +/// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled. +/// +/// The length is set to 0, and the buffer is dropped and zeroized. +/// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// use zeroize::Zeroize; +/// let mut array = ArrayVec::from([1, 2, 3]); +/// array.zeroize(); +/// assert_eq!(array.len(), 0); +/// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; +/// assert_eq!(data, [0, 0, 0]); +/// ``` +impl zeroize::Zeroize for ArrayVec { + fn zeroize(&mut self) { + // Zeroize all the contained elements. + self.iter_mut().zeroize(); + // Drop all the elements and set the length to 0. + self.clear(); + // Zeroize the backing array. + self.xs.zeroize(); + } +} + +/// By-value iterator for `ArrayVec`. +pub struct IntoIter { + index: usize, + v: ArrayVec, +} +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + pub fn as_slice(&self) -> &[T] { + &self.v[self.index..] + } + + /// Returns the remaining items of this iterator as a mutable slice. + pub fn as_mut_slice(&mut self) -> &mut [T] { + &mut self.v[self.index..] + } +} + +impl Iterator for IntoIter { + type Item = T; + + fn next(&mut self) -> Option { + if self.index == self.v.len() { + None + } else { + unsafe { + let index = self.index; + self.index = index + 1; + Some(ptr::read(self.v.get_unchecked_ptr(index))) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.v.len() - self.index; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + if self.index == self.v.len() { + None + } else { + unsafe { + let new_len = self.v.len() - 1; + self.v.set_len(new_len); + Some(ptr::read(self.v.get_unchecked_ptr(new_len))) + } + } + } +} + +impl ExactSizeIterator for IntoIter { } + +impl Drop for IntoIter { + fn drop(&mut self) { + // panic safety: Set length to 0 before dropping elements. + let index = self.index; + let len = self.v.len(); + unsafe { + self.v.set_len(0); + let elements = slice::from_raw_parts_mut( + self.v.get_unchecked_ptr(index), + len - index); + ptr::drop_in_place(elements); + } + } +} + +impl Clone for IntoIter +where T: Clone, +{ + fn clone(&self) -> IntoIter { + let mut v = ArrayVec::new(); + v.extend_from_slice(&self.v[self.index..]); + v.into_iter() + } +} + +impl fmt::Debug for IntoIter +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(&self.v[self.index..]) + .finish() + } +} + +/// A draining iterator for `ArrayVec`. +pub struct Drain<'a, T: 'a, const CAP: usize> { + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, T>, + vec: *mut ArrayVec, +} + +unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {} +unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {} + +impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { + type Item = T; + + fn next(&mut self) -> Option { + self.iter.next().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> +{ + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } +} + +impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} + +impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { + fn drop(&mut self) { + // len is currently 0 so panicking while dropping will not cause a double drop. + + // exhaust self first + while let Some(_) = self.next() { } + + if self.tail_len > 0 { + unsafe { + let source_vec = &mut *self.vec; + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.tail_start; + let ptr = source_vec.as_mut_ptr(); + ptr::copy(ptr.add(tail), ptr.add(start), self.tail_len); + source_vec.set_len(start + self.tail_len); + } + } + } +} + +struct ScopeExitGuard + where F: FnMut(&Data, &mut T) +{ + value: T, + data: Data, + f: F, +} + +impl Drop for ScopeExitGuard + where F: FnMut(&Data, &mut T) +{ + fn drop(&mut self) { + (self.f)(&self.data, &mut self.value) + } +} + + + +/// Extend the `ArrayVec` with an iterator. +/// +/// ***Panics*** if extending the vector exceeds its capacity. +impl Extend for ArrayVec { + /// Extend the `ArrayVec` with an iterator. + /// + /// ***Panics*** if extending the vector exceeds its capacity. + #[track_caller] + fn extend>(&mut self, iter: I) { + unsafe { + self.extend_from_iter::<_, true>(iter) + } + } +} + +#[inline(never)] +#[cold] +#[track_caller] +fn extend_panic() { + panic!("ArrayVec: capacity exceeded in extend/from_iter"); +} + +impl ArrayVec { + /// Extend the arrayvec from the iterable. + /// + /// ## Safety + /// + /// Unsafe because if CHECK is false, the length of the input is not checked. + /// The caller must ensure the length of the input fits in the capacity. + #[track_caller] + pub(crate) unsafe fn extend_from_iter(&mut self, iterable: I) + where I: IntoIterator + { + let take = self.capacity() - self.len(); + let len = self.len(); + let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); + let end_ptr = raw_ptr_add(ptr, take); + // Keep the length in a separate variable, write it back on scope + // exit. To help the compiler with alias analysis and stuff. + // We update the length to handle panic in the iteration of the + // user's iterator, without dropping any elements on the floor. + let mut guard = ScopeExitGuard { + value: &mut self.len, + data: len, + f: move |&len, self_len| { + **self_len = len as LenUint; + } + }; + let mut iter = iterable.into_iter(); + loop { + if let Some(elt) = iter.next() { + if ptr == end_ptr && CHECK { extend_panic(); } + debug_assert_ne!(ptr, end_ptr); + if mem::size_of::() != 0 { + ptr.write(elt); + } + ptr = raw_ptr_add(ptr, 1); + guard.data += 1; + } else { + return; // success + } + } + } + + /// Extend the ArrayVec with clones of elements from the slice; + /// the length of the slice must be <= the remaining capacity in the arrayvec. + pub(crate) fn extend_from_slice(&mut self, slice: &[T]) + where T: Clone + { + let take = self.capacity() - self.len(); + debug_assert!(slice.len() <= take); + unsafe { + let slice = if take < slice.len() { &slice[..take] } else { slice }; + self.extend_from_iter::<_, false>(slice.iter().cloned()); + } + } +} + +/// Rawptr add but uses arithmetic distance for ZST +unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { + if mem::size_of::() == 0 { + // Special case for ZST + ptr.cast::().wrapping_add(offset).cast::() + } else { + ptr.add(offset) + } +} + +/// Create an `ArrayVec` from an iterator. +/// +/// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. +impl iter::FromIterator for ArrayVec { + /// Create an `ArrayVec` from an iterator. + /// + /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. + fn from_iter>(iter: I) -> Self { + let mut array = ArrayVec::new(); + array.extend(iter); + array + } +} + +impl Clone for ArrayVec + where T: Clone +{ + fn clone(&self) -> Self { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, rhs: &Self) { + // recursive case for the common prefix + let prefix = cmp::min(self.len(), rhs.len()); + self[..prefix].clone_from_slice(&rhs[..prefix]); + + if prefix < self.len() { + // rhs was shorter + self.truncate(prefix); + } else { + let rhs_elems = &rhs[self.len()..]; + self.extend_from_slice(rhs_elems); + } + } +} + +impl Hash for ArrayVec + where T: Hash +{ + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +impl PartialEq for ArrayVec + where T: PartialEq +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl PartialEq<[T]> for ArrayVec + where T: PartialEq +{ + fn eq(&self, other: &[T]) -> bool { + **self == *other + } +} + +impl Eq for ArrayVec where T: Eq { } + +impl Borrow<[T]> for ArrayVec { + fn borrow(&self) -> &[T] { self } +} + +impl BorrowMut<[T]> for ArrayVec { + fn borrow_mut(&mut self) -> &mut [T] { self } +} + +impl AsRef<[T]> for ArrayVec { + fn as_ref(&self) -> &[T] { self } +} + +impl AsMut<[T]> for ArrayVec { + fn as_mut(&mut self) -> &mut [T] { self } +} + +impl fmt::Debug for ArrayVec where T: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl Default for ArrayVec { + /// Return an empty array + fn default() -> ArrayVec { + ArrayVec::new() + } +} + +impl PartialOrd for ArrayVec where T: PartialOrd { + fn partial_cmp(&self, other: &Self) -> Option { + (**self).partial_cmp(other) + } + + fn lt(&self, other: &Self) -> bool { + (**self).lt(other) + } + + fn le(&self, other: &Self) -> bool { + (**self).le(other) + } + + fn ge(&self, other: &Self) -> bool { + (**self).ge(other) + } + + fn gt(&self, other: &Self) -> bool { + (**self).gt(other) + } +} + +impl Ord for ArrayVec where T: Ord { + fn cmp(&self, other: &Self) -> cmp::Ordering { + (**self).cmp(other) + } +} + +#[cfg(feature="std")] +/// `Write` appends written data to the end of the vector. +/// +/// Requires `features="std"`. +impl io::Write for ArrayVec { + fn write(&mut self, data: &[u8]) -> io::Result { + let len = cmp::min(self.remaining_capacity(), data.len()); + let _result = self.try_extend_from_slice(&data[..len]); + debug_assert!(_result.is_ok()); + Ok(len) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl Serialize for ArrayVec { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.collect_seq(self) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + use serde::de::{Visitor, SeqAccess, Error}; + use std::marker::PhantomData; + + struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); + + impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { + type Value = ArrayVec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array with no more than {} items", CAP) + } + + fn visit_seq(self, mut seq: SA) -> Result + where SA: SeqAccess<'de>, + { + let mut values = ArrayVec::::new(); + + while let Some(value) = seq.next_element()? { + if let Err(_) = values.try_push(value) { + return Err(SA::Error::invalid_length(CAP + 1, &self)); + } + } + + Ok(values) + } + } + + deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) + } +} + +#[cfg(feature = "borsh")] +/// Requires crate feature `"borsh"` +impl borsh::BorshSerialize for ArrayVec +where + T: borsh::BorshSerialize, +{ + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + <[T] as borsh::BorshSerialize>::serialize(self.as_slice(), writer) + } +} + +#[cfg(feature = "borsh")] +/// Requires crate feature `"borsh"` +impl borsh::BorshDeserialize for ArrayVec +where + T: borsh::BorshDeserialize, +{ + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let mut values = Self::new(); + let len = ::deserialize_reader(reader)?; + for _ in 0..len { + let elem = ::deserialize_reader(reader)?; + if let Err(_) = values.try_push(elem) { + return Err(borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + format!("Expected an array with no more than {} items", CAP), + )); + } + } + + Ok(values) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/arrayvec_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/arrayvec_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/arrayvec_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,87 @@ +use std::ptr; +use std::slice; + +use crate::CapacityError; + +/// Implements basic arrayvec methods - based on a few required methods +/// for length and element access. +pub(crate) trait ArrayVecImpl { + type Item; + const CAPACITY: usize; + + fn len(&self) -> usize; + + unsafe fn set_len(&mut self, new_len: usize); + + /// Return a slice containing all elements of the vector. + fn as_slice(&self) -> &[Self::Item] { + let len = self.len(); + unsafe { + slice::from_raw_parts(self.as_ptr(), len) + } + } + + /// Return a mutable slice containing all elements of the vector. + fn as_mut_slice(&mut self) -> &mut [Self::Item] { + let len = self.len(); + unsafe { + std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } + } + + /// Return a raw pointer to the vector's buffer. + fn as_ptr(&self) -> *const Self::Item; + + /// Return a raw mutable pointer to the vector's buffer. + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + #[track_caller] + fn push(&mut self, element: Self::Item) { + self.try_push(element).unwrap() + } + + fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError> { + if self.len() < Self::CAPACITY { + unsafe { + self.push_unchecked(element); + } + Ok(()) + } else { + Err(CapacityError::new(element)) + } + } + + unsafe fn push_unchecked(&mut self, element: Self::Item) { + let len = self.len(); + debug_assert!(len < Self::CAPACITY); + ptr::write(self.as_mut_ptr().add(len), element); + self.set_len(len + 1); + } + + fn pop(&mut self) -> Option { + if self.len() == 0 { + return None; + } + unsafe { + let new_len = self.len() - 1; + self.set_len(new_len); + Some(ptr::read(self.as_ptr().add(new_len))) + } + } + + fn clear(&mut self) { + self.truncate(0) + } + + fn truncate(&mut self, new_len: usize) { + unsafe { + let len = self.len(); + if new_len < len { + self.set_len(new_len); + let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); + ptr::drop_in_place(tail); + } + } + } +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/char.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/char.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/char.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/char.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Original authors: alexchrichton, bluss + +// UTF-8 ranges and tags for encoding characters +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; + +/// Placeholder +pub struct EncodeUtf8Error; + +/// Encode a char into buf using UTF-8. +/// +/// On success, return the byte length of the encoding (1, 2, 3 or 4).
+/// On error, return `EncodeUtf8Error` if the buffer was too short for the char. +/// +/// Safety: `ptr` must be writable for `len` bytes. +#[inline] +pub unsafe fn encode_utf8(ch: char, ptr: *mut u8, len: usize) -> Result +{ + let code = ch as u32; + if code < MAX_ONE_B && len >= 1 { + ptr.add(0).write(code as u8); + return Ok(1); + } else if code < MAX_TWO_B && len >= 2 { + ptr.add(0).write((code >> 6 & 0x1F) as u8 | TAG_TWO_B); + ptr.add(1).write((code & 0x3F) as u8 | TAG_CONT); + return Ok(2); + } else if code < MAX_THREE_B && len >= 3 { + ptr.add(0).write((code >> 12 & 0x0F) as u8 | TAG_THREE_B); + ptr.add(1).write((code >> 6 & 0x3F) as u8 | TAG_CONT); + ptr.add(2).write((code & 0x3F) as u8 | TAG_CONT); + return Ok(3); + } else if len >= 4 { + ptr.add(0).write((code >> 18 & 0x07) as u8 | TAG_FOUR_B); + ptr.add(1).write((code >> 12 & 0x3F) as u8 | TAG_CONT); + ptr.add(2).write((code >> 6 & 0x3F) as u8 | TAG_CONT); + ptr.add(3).write((code & 0x3F) as u8 | TAG_CONT); + return Ok(4); + }; + Err(EncodeUtf8Error) +} + + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_encode_utf8() { + // Test that all codepoints are encoded correctly + let mut data = [0u8; 16]; + for codepoint in 0..=(std::char::MAX as u32) { + if let Some(ch) = std::char::from_u32(codepoint) { + for elt in &mut data { *elt = 0; } + let ptr = data.as_mut_ptr(); + let len = data.len(); + unsafe { + let res = encode_utf8(ch, ptr, len).ok().unwrap(); + assert_eq!(res, ch.len_utf8()); + } + let string = std::str::from_utf8(&data).unwrap(); + assert_eq!(string.chars().next(), Some(ch)); + } + } +} + +#[test] +fn test_encode_utf8_oob() { + // test that we report oob if the buffer is too short + let mut data = [0u8; 16]; + let chars = ['a', 'α', '�', '𐍈']; + for (len, &ch) in (1..=4).zip(&chars) { + assert_eq!(len, ch.len_utf8(), "Len of ch={}", ch); + let ptr = data.as_mut_ptr(); + unsafe { + assert!(matches::matches!(encode_utf8(ch, ptr, len - 1), Err(_))); + assert!(matches::matches!(encode_utf8(ch, ptr, len), Ok(_))); + } + } +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/errors.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/errors.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/errors.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/errors.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +use std::fmt; +#[cfg(feature="std")] +use std::any::Any; +#[cfg(feature="std")] +use std::error::Error; + +/// Error value indicating insufficient capacity +#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] +pub struct CapacityError { + element: T, +} + +impl CapacityError { + /// Create a new `CapacityError` from `element`. + pub const fn new(element: T) -> CapacityError { + CapacityError { + element: element, + } + } + + /// Extract the overflowing element + pub fn element(self) -> T { + self.element + } + + /// Convert into a `CapacityError` that does not carry an element. + pub fn simplify(self) -> CapacityError { + CapacityError { element: () } + } +} + +const CAPERROR: &'static str = "insufficient capacity"; + +#[cfg(feature="std")] +/// Requires `features="std"`. +impl Error for CapacityError {} + +impl fmt::Display for CapacityError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", CAPERROR) + } +} + +impl fmt::Debug for CapacityError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", "CapacityError", CAPERROR) + } +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +//! **arrayvec** provides the types [`ArrayVec`] and [`ArrayString`]: +//! array-backed vector and string types, which store their contents inline. +//! +//! The arrayvec package has the following cargo features: +//! +//! - `std` +//! - Optional, enabled by default +//! - Use libstd; disable to use `no_std` instead. +//! +//! - `serde` +//! - Optional +//! - Enable serialization for ArrayVec and ArrayString using serde 1.x +//! +//! - `zeroize` +//! - Optional +//! - Implement `Zeroize` for ArrayVec and ArrayString +//! +//! ## Rust Version +//! +//! This version of arrayvec requires Rust 1.51 or later. +//! +#![doc(html_root_url="https://docs.rs/arrayvec/0.7/")] +#![cfg_attr(not(feature="std"), no_std)] + +#[cfg(feature="serde")] +extern crate serde; + +#[cfg(not(feature="std"))] +extern crate core as std; + +pub(crate) type LenUint = u32; + +macro_rules! assert_capacity_limit { + ($cap:expr) => { + if std::mem::size_of::() > std::mem::size_of::() { + if $cap > LenUint::MAX as usize { + panic!("ArrayVec: largest supported capacity is u32::MAX") + } + } + } +} + +macro_rules! assert_capacity_limit_const { + ($cap:expr) => { + if std::mem::size_of::() > std::mem::size_of::() { + if $cap > LenUint::MAX as usize { + [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] + } + } + } +} + +mod arrayvec_impl; +mod arrayvec; +mod array_string; +mod char; +mod errors; +mod utils; + +pub use crate::array_string::ArrayString; +pub use crate::errors::CapacityError; + +pub use crate::arrayvec::{ArrayVec, IntoIter, Drain}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/utils.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/src/utils.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/src/utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use std::marker::PhantomData; +use std::mem::MaybeUninit; + +pub(crate) struct MakeMaybeUninit(PhantomData T>); + +impl MakeMaybeUninit { + pub(crate) const VALUE: MaybeUninit = MaybeUninit::uninit(); + + pub(crate) const ARRAY: [MaybeUninit; N] = [Self::VALUE; N]; +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/borsh.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/borsh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/borsh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/borsh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,73 @@ +#![cfg(feature = "borsh")] +use std::fmt; +extern crate arrayvec; +extern crate borsh; + +fn assert_ser(v: &T, expected_bytes: &[u8]) { + let mut actual_bytes = Vec::new(); + v.serialize(&mut actual_bytes).unwrap(); + assert_eq!(actual_bytes, expected_bytes); +} + +fn assert_roundtrip(v: &T) { + let mut bytes = Vec::new(); + v.serialize(&mut bytes).unwrap(); + let v_de = T::try_from_slice(&bytes).unwrap(); + assert_eq!(*v, v_de); +} + +mod array_vec { + use arrayvec::ArrayVec; + use super::{assert_ser, assert_roundtrip}; + + #[test] + fn test_empty() { + let vec = ArrayVec::::new(); + assert_ser(&vec, b"\0\0\0\0"); + assert_roundtrip(&vec); + } + + #[test] + fn test_full() { + let mut vec = ArrayVec::::new(); + vec.push(0xdeadbeef); + vec.push(0x123); + vec.push(0x456); + assert_ser(&vec, b"\x03\0\0\0\xef\xbe\xad\xde\x23\x01\0\0\x56\x04\0\0"); + assert_roundtrip(&vec); + } + + #[test] + fn test_with_free_capacity() { + let mut vec = ArrayVec::::new(); + vec.push(0xdeadbeef); + assert_ser(&vec, b"\x01\0\0\0\xef\xbe\xad\xde"); + assert_roundtrip(&vec); + } +} + +mod array_string { + use arrayvec::ArrayString; + use super::{assert_ser, assert_roundtrip}; + + #[test] + fn test_empty() { + let string = ArrayString::<0>::new(); + assert_ser(&string, b"\0\0\0\0"); + assert_roundtrip(&string); + } + + #[test] + fn test_full() { + let string = ArrayString::from_byte_string(b"hello world").unwrap(); + assert_ser(&string, b"\x0b\0\0\0hello world"); + assert_roundtrip(&string); + } + + #[test] + fn test_with_free_capacity() { + let string = ArrayString::<16>::from("hello world").unwrap(); + assert_ser(&string, b"\x0b\0\0\0hello world"); + assert_roundtrip(&string); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +#![cfg(feature = "serde")] +extern crate arrayvec; +extern crate serde_test; + +mod array_vec { + use arrayvec::ArrayVec; + + use serde_test::{Token, assert_tokens, assert_de_tokens_error}; + + #[test] + fn test_ser_de_empty() { + let vec = ArrayVec::::new(); + + assert_tokens(&vec, &[ + Token::Seq { len: Some(0) }, + Token::SeqEnd, + ]); + } + + + #[test] + fn test_ser_de() { + let mut vec = ArrayVec::::new(); + vec.push(20); + vec.push(55); + vec.push(123); + + assert_tokens(&vec, &[ + Token::Seq { len: Some(3) }, + Token::U32(20), + Token::U32(55), + Token::U32(123), + Token::SeqEnd, + ]); + } + + #[test] + fn test_de_too_large() { + assert_de_tokens_error::>(&[ + Token::Seq { len: Some(3) }, + Token::U32(13), + Token::U32(42), + Token::U32(68), + ], "invalid length 3, expected an array with no more than 2 items"); + } +} + +mod array_string { + use arrayvec::ArrayString; + + use serde_test::{Token, assert_tokens, assert_de_tokens_error}; + + #[test] + fn test_ser_de_empty() { + let string = ArrayString::<0>::new(); + + assert_tokens(&string, &[ + Token::Str(""), + ]); + } + + + #[test] + fn test_ser_de() { + let string = ArrayString::<9>::from("1234 abcd") + .expect("expected exact specified capacity to be enough"); + + assert_tokens(&string, &[ + Token::Str("1234 abcd"), + ]); + } + + #[test] + fn test_de_too_large() { + assert_de_tokens_error::>(&[ + Token::Str("afd") + ], "invalid length 3, expected a string no more than 2 bytes long"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/arrayvec/tests/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/arrayvec/tests/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,779 @@ +extern crate arrayvec; +#[macro_use] extern crate matches; + +use arrayvec::ArrayVec; +use arrayvec::ArrayString; +use std::mem; +use arrayvec::CapacityError; + +use std::collections::HashMap; + + +#[test] +fn test_simple() { + use std::ops::Add; + + let mut vec: ArrayVec, 3> = ArrayVec::new(); + + vec.push(vec![1, 2, 3, 4]); + vec.push(vec![10]); + vec.push(vec![-1, 13, -2]); + + for elt in &vec { + assert_eq!(elt.iter().fold(0, Add::add), 10); + } + + let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add); + assert_eq!(sum_len, 8); +} + +#[test] +fn test_capacity_left() { + let mut vec: ArrayVec = ArrayVec::new(); + assert_eq!(vec.remaining_capacity(), 4); + vec.push(1); + assert_eq!(vec.remaining_capacity(), 3); + vec.push(2); + assert_eq!(vec.remaining_capacity(), 2); + vec.push(3); + assert_eq!(vec.remaining_capacity(), 1); + vec.push(4); + assert_eq!(vec.remaining_capacity(), 0); +} + +#[test] +fn test_extend_from_slice() { + let mut vec: ArrayVec = ArrayVec::new(); + + vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); + assert_eq!(vec.len(), 3); + assert_eq!(&vec[..], &[1, 2, 3]); + assert_eq!(vec.pop(), Some(3)); + assert_eq!(&vec[..], &[1, 2]); +} + +#[test] +fn test_extend_from_slice_error() { + let mut vec: ArrayVec = ArrayVec::new(); + + vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); + let res = vec.try_extend_from_slice(&[0; 8]); + assert_matches!(res, Err(_)); + + let mut vec: ArrayVec = ArrayVec::new(); + let res = vec.try_extend_from_slice(&[0; 1]); + assert_matches!(res, Err(_)); +} + +#[test] +fn test_try_from_slice_error() { + use arrayvec::ArrayVec; + use std::convert::TryInto as _; + + let res: Result, _> = (&[1, 2, 3] as &[_]).try_into(); + assert_matches!(res, Err(_)); +} + +#[test] +fn test_u16_index() { + const N: usize = 4096; + let mut vec: ArrayVec<_, N> = ArrayVec::new(); + for _ in 0..N { + assert!(vec.try_push(1u8).is_ok()); + } + assert!(vec.try_push(0).is_err()); + assert_eq!(vec.len(), N); +} + +#[test] +fn test_iter() { + let mut iter = ArrayVec::from([1, 2, 3]).into_iter(); + assert_eq!(iter.size_hint(), (3, Some(3))); + assert_eq!(iter.next_back(), Some(3)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_drop() { + use std::cell::Cell; + + let flag = &Cell::new(0); + + #[derive(Clone)] + struct Bump<'a>(&'a Cell); + + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + } + } + + { + let mut array = ArrayVec::::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + } + assert_eq!(flag.get(), 2); + + // test something with the nullable pointer optimization + flag.set(0); + + { + let mut array = ArrayVec::<_, 3>::new(); + array.push(vec![Bump(flag)]); + array.push(vec![Bump(flag), Bump(flag)]); + array.push(vec![]); + let push4 = array.try_push(vec![Bump(flag)]); + assert_eq!(flag.get(), 0); + drop(push4); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 3); + } + + assert_eq!(flag.get(), 4); + + // test into_inner + flag.set(0); + { + let mut array = ArrayVec::<_, 3>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + let inner = array.into_inner(); + assert!(inner.is_ok()); + assert_eq!(flag.get(), 0); + drop(inner); + assert_eq!(flag.get(), 3); + } + + // test take + flag.set(0); + { + let mut array1 = ArrayVec::<_, 3>::new(); + array1.push(Bump(flag)); + array1.push(Bump(flag)); + array1.push(Bump(flag)); + let array2 = array1.take(); + assert_eq!(flag.get(), 0); + drop(array1); + assert_eq!(flag.get(), 0); + drop(array2); + assert_eq!(flag.get(), 3); + } + + // test cloning into_iter + flag.set(0); + { + let mut array = ArrayVec::<_, 3>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + let mut iter = array.into_iter(); + assert_eq!(flag.get(), 0); + iter.next(); + assert_eq!(flag.get(), 1); + let clone = iter.clone(); + assert_eq!(flag.get(), 1); + drop(clone); + assert_eq!(flag.get(), 3); + drop(iter); + assert_eq!(flag.get(), 5); + } +} + +#[test] +fn test_drop_panics() { + use std::cell::Cell; + use std::panic::catch_unwind; + use std::panic::AssertUnwindSafe; + + let flag = &Cell::new(0); + + struct Bump<'a>(&'a Cell); + + // Panic in the first drop + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + if n == 0 { + panic!("Panic in Bump's drop"); + } + } + } + // check if rust is new enough + flag.set(0); + { + let array = vec![Bump(flag), Bump(flag)]; + let res = catch_unwind(AssertUnwindSafe(|| { + drop(array); + })); + assert!(res.is_err()); + } + + if flag.get() != 2 { + println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place"); + return; + } + + flag.set(0); + { + let mut array = ArrayVec::::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + + let res = catch_unwind(AssertUnwindSafe(|| { + drop(array); + })); + assert!(res.is_err()); + } + // Check that all the elements drop, even if the first drop panics. + assert_eq!(flag.get(), 3); + + + flag.set(0); + { + let mut array = ArrayVec::::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + + let i = 2; + let tail_len = array.len() - i; + + let res = catch_unwind(AssertUnwindSafe(|| { + array.truncate(i); + })); + assert!(res.is_err()); + // Check that all the tail elements drop, even if the first drop panics. + assert_eq!(flag.get(), tail_len as i32); + } + + +} + +#[test] +fn test_extend() { + let mut range = 0..10; + + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); + assert_eq!(range.next(), Some(5)); + + array.extend(range.by_ref().take(0)); + assert_eq!(range.next(), Some(6)); + + let mut array: ArrayVec<_, 10> = (0..3).collect(); + assert_eq!(&array[..], &[0, 1, 2]); + array.extend(3..5); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); +} + +#[should_panic] +#[test] +fn test_extend_capacity_panic_1() { + let mut range = 0..10; + + let _: ArrayVec<_, 5> = range.by_ref().collect(); +} + +#[should_panic] +#[test] +fn test_extend_capacity_panic_2() { + let mut range = 0..10; + + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); + assert_eq!(range.next(), Some(5)); + array.extend(range.by_ref().take(1)); +} + +#[test] +fn test_is_send_sync() { + let data = ArrayVec::, 5>::new(); + &data as &dyn Send; + &data as &dyn Sync; +} + +#[test] +fn test_compact_size() { + // 4 bytes + padding + length + type ByteArray = ArrayVec; + println!("{}", mem::size_of::()); + assert!(mem::size_of::() <= 2 * mem::size_of::()); + + // just length + type EmptyArray = ArrayVec; + println!("{}", mem::size_of::()); + assert!(mem::size_of::() <= mem::size_of::()); + + // 3 elements + padding + length + type QuadArray = ArrayVec; + println!("{}", mem::size_of::()); + assert!(mem::size_of::() <= 4 * 4 + mem::size_of::()); +} + +#[test] +fn test_still_works_with_option_arrayvec() { + type RefArray = ArrayVec<&'static i32, 2>; + let array = Some(RefArray::new()); + assert!(array.is_some()); + println!("{:?}", array); +} + +#[test] +fn test_drain() { + let mut v = ArrayVec::from([0; 8]); + v.pop(); + v.drain(0..7); + assert_eq!(&v[..], &[]); + + v.extend(0..8); + v.drain(1..4); + assert_eq!(&v[..], &[0, 4, 5, 6, 7]); + let u: ArrayVec<_, 3> = v.drain(1..4).rev().collect(); + assert_eq!(&u[..], &[6, 5, 4]); + assert_eq!(&v[..], &[0, 7]); + v.drain(..); + assert_eq!(&v[..], &[]); +} + +#[test] +fn test_drain_range_inclusive() { + let mut v = ArrayVec::from([0; 8]); + v.drain(0..=7); + assert_eq!(&v[..], &[]); + + v.extend(0..8); + v.drain(1..=4); + assert_eq!(&v[..], &[0, 5, 6, 7]); + let u: ArrayVec<_, 3> = v.drain(1..=2).rev().collect(); + assert_eq!(&u[..], &[6, 5]); + assert_eq!(&v[..], &[0, 7]); + v.drain(..); + assert_eq!(&v[..], &[]); +} + +#[test] +#[should_panic] +fn test_drain_range_inclusive_oob() { + let mut v = ArrayVec::from([0; 0]); + v.drain(0..=0); +} + +#[test] +fn test_retain() { + let mut v = ArrayVec::from([0; 8]); + for (i, elt) in v.iter_mut().enumerate() { + *elt = i; + } + v.retain(|_| true); + assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5, 6, 7]); + v.retain(|elt| { + *elt /= 2; + *elt % 2 == 0 + }); + assert_eq!(&v[..], &[0, 0, 2, 2]); + v.retain(|_| false); + assert_eq!(&v[..], &[]); +} + +#[test] +#[should_panic] +fn test_drain_oob() { + let mut v = ArrayVec::from([0; 8]); + v.pop(); + v.drain(0..8); +} + +#[test] +#[should_panic] +fn test_drop_panic() { + struct DropPanic; + + impl Drop for DropPanic { + fn drop(&mut self) { + panic!("drop"); + } + } + + let mut array = ArrayVec::::new(); + array.push(DropPanic); +} + +#[test] +#[should_panic] +fn test_drop_panic_into_iter() { + struct DropPanic; + + impl Drop for DropPanic { + fn drop(&mut self) { + panic!("drop"); + } + } + + let mut array = ArrayVec::::new(); + array.push(DropPanic); + array.into_iter(); +} + +#[test] +fn test_insert() { + let mut v = ArrayVec::from([]); + assert_matches!(v.try_push(1), Err(_)); + + let mut v = ArrayVec::<_, 3>::new(); + v.insert(0, 0); + v.insert(1, 1); + //let ret1 = v.try_insert(3, 3); + //assert_matches!(ret1, Err(InsertError::OutOfBounds(_))); + assert_eq!(&v[..], &[0, 1]); + v.insert(2, 2); + assert_eq!(&v[..], &[0, 1, 2]); + + let ret2 = v.try_insert(1, 9); + assert_eq!(&v[..], &[0, 1, 2]); + assert_matches!(ret2, Err(_)); + + let mut v = ArrayVec::from([2]); + assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. })); + assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. })); + //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. })); +} + +#[test] +fn test_into_inner_1() { + let mut v = ArrayVec::from([1, 2]); + v.pop(); + let u = v.clone(); + assert_eq!(v.into_inner(), Err(u)); +} + +#[test] +fn test_into_inner_2() { + let mut v = ArrayVec::::new(); + v.push("a".into()); + v.push("b".into()); + v.push("c".into()); + v.push("d".into()); + assert_eq!(v.into_inner().unwrap(), ["a", "b", "c", "d"]); +} + +#[test] +fn test_into_inner_3() { + let mut v = ArrayVec::::new(); + v.extend(1..=4); + assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); +} + +#[test] +fn test_take() { + let mut v1 = ArrayVec::::new(); + v1.extend(1..=4); + let v2 = v1.take(); + assert!(v1.into_inner().is_err()); + assert_eq!(v2.into_inner().unwrap(), [1, 2, 3, 4]); +} + +#[cfg(feature="std")] +#[test] +fn test_write() { + use std::io::Write; + let mut v = ArrayVec::<_, 8>::new(); + write!(&mut v, "\x01\x02\x03").unwrap(); + assert_eq!(&v[..], &[1, 2, 3]); + let r = v.write(&[9; 16]).unwrap(); + assert_eq!(r, 5); + assert_eq!(&v[..], &[1, 2, 3, 9, 9, 9, 9, 9]); +} + +#[test] +fn array_clone_from() { + let mut v = ArrayVec::<_, 4>::new(); + v.push(vec![1, 2]); + v.push(vec![3, 4, 5]); + v.push(vec![6]); + let reference = v.to_vec(); + let mut u = ArrayVec::<_, 4>::new(); + u.clone_from(&v); + assert_eq!(&u, &reference[..]); + + let mut t = ArrayVec::<_, 4>::new(); + t.push(vec![97]); + t.push(vec![]); + t.push(vec![5, 6, 2]); + t.push(vec![2]); + t.clone_from(&v); + assert_eq!(&t, &reference[..]); + t.clear(); + t.clone_from(&v); + assert_eq!(&t, &reference[..]); +} + +#[cfg(feature="std")] +#[test] +fn test_string() { + use std::error::Error; + + let text = "hello world"; + let mut s = ArrayString::<16>::new(); + s.try_push_str(text).unwrap(); + assert_eq!(&s, text); + assert_eq!(text, &s); + + // Make sure Hash / Eq / Borrow match up so we can use HashMap + let mut map = HashMap::new(); + map.insert(s, 1); + assert_eq!(map[text], 1); + + let mut t = ArrayString::<2>::new(); + assert!(t.try_push_str(text).is_err()); + assert_eq!(&t, ""); + + t.push_str("ab"); + // DerefMut + let tmut: &mut str = &mut t; + assert_eq!(tmut, "ab"); + + // Test Error trait / try + let t = || -> Result<(), Box> { + let mut t = ArrayString::<2>::new(); + t.try_push_str(text)?; + Ok(()) + }(); + assert!(t.is_err()); +} + +#[test] +fn test_string_from() { + let text = "hello world"; + // Test `from` constructor + let u = ArrayString::<11>::from(text).unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_parse_from_str() { + let text = "hello world"; + let u: ArrayString<11> = text.parse().unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_from_bytes() { + let text = "hello world"; + let u = ArrayString::from_byte_string(b"hello world").unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_clone() { + let text = "hi"; + let mut s = ArrayString::<4>::new(); + s.push_str("abcd"); + let t = ArrayString::<4>::from(text).unwrap(); + s.clone_from(&t); + assert_eq!(&t, &s); +} + +#[test] +fn test_string_push() { + let text = "abcαβγ"; + let mut s = ArrayString::<8>::new(); + for c in text.chars() { + if let Err(_) = s.try_push(c) { + break; + } + } + assert_eq!("abcαβ", &s[..]); + s.push('x'); + assert_eq!("abcαβx", &s[..]); + assert!(s.try_push('x').is_err()); +} + + +#[test] +fn test_insert_at_length() { + let mut v = ArrayVec::<_, 8>::new(); + let result1 = v.try_insert(0, "a"); + let result2 = v.try_insert(1, "b"); + assert!(result1.is_ok() && result2.is_ok()); + assert_eq!(&v[..], &["a", "b"]); +} + +#[should_panic] +#[test] +fn test_insert_out_of_bounds() { + let mut v = ArrayVec::<_, 8>::new(); + let _ = v.try_insert(1, "test"); +} + +/* + * insert that pushes out the last + let mut u = ArrayVec::from([1, 2, 3, 4]); + let ret = u.try_insert(3, 99); + assert_eq!(&u[..], &[1, 2, 3, 99]); + assert_matches!(ret, Err(_)); + let ret = u.try_insert(4, 77); + assert_eq!(&u[..], &[1, 2, 3, 99]); + assert_matches!(ret, Err(_)); +*/ + +#[test] +fn test_drop_in_insert() { + use std::cell::Cell; + + let flag = &Cell::new(0); + + struct Bump<'a>(&'a Cell); + + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + } + } + + flag.set(0); + + { + let mut array = ArrayVec::<_, 2>::new(); + array.push(Bump(flag)); + array.insert(0, Bump(flag)); + assert_eq!(flag.get(), 0); + let ret = array.try_insert(1, Bump(flag)); + assert_eq!(flag.get(), 0); + assert_matches!(ret, Err(_)); + drop(ret); + assert_eq!(flag.get(), 1); + } + assert_eq!(flag.get(), 3); +} + +#[test] +fn test_pop_at() { + let mut v = ArrayVec::::new(); + let s = String::from; + v.push(s("a")); + v.push(s("b")); + v.push(s("c")); + v.push(s("d")); + + assert_eq!(v.pop_at(4), None); + assert_eq!(v.pop_at(1), Some(s("b"))); + assert_eq!(v.pop_at(1), Some(s("c"))); + assert_eq!(v.pop_at(2), None); + assert_eq!(&v[..], &["a", "d"]); +} + +#[test] +fn test_sizes() { + let v = ArrayVec::from([0u8; 1 << 16]); + assert_eq!(vec![0u8; v.len()], &v[..]); +} + +#[test] +fn test_default() { + use std::net; + let s: ArrayString<4> = Default::default(); + // Something without `Default` implementation. + let v: ArrayVec = Default::default(); + assert_eq!(s.len(), 0); + assert_eq!(v.len(), 0); +} + +#[test] +fn test_extend_zst() { + let mut range = 0..10; + #[derive(Copy, Clone, PartialEq, Debug)] + struct Z; // Zero sized type + + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect(); + assert_eq!(&array[..], &[Z; 5]); + assert_eq!(range.next(), Some(5)); + + array.extend(range.by_ref().take(0).map(|_| Z)); + assert_eq!(range.next(), Some(6)); + + let mut array: ArrayVec<_, 10> = (0..3).map(|_| Z).collect(); + assert_eq!(&array[..], &[Z; 3]); + array.extend((3..5).map(|_| Z)); + assert_eq!(&array[..], &[Z; 5]); + assert_eq!(array.len(), 5); +} + +#[test] +fn test_try_from_argument() { + use core::convert::TryFrom; + let v = ArrayString::<16>::try_from(format_args!("Hello {}", 123)).unwrap(); + assert_eq!(&v, "Hello 123"); +} + +#[test] +fn allow_max_capacity_arrayvec_type() { + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}>; +} + +#[should_panic(expected="largest supported capacity")] +#[test] +fn deny_max_capacity_arrayvec_value() { + if mem::size_of::() <= mem::size_of::() { + panic!("This test does not work on this platform. 'largest supported capacity'"); + } + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); +} + +#[should_panic(expected="index out of bounds")] +#[test] +fn deny_max_capacity_arrayvec_value_const() { + if mem::size_of::() <= mem::size_of::() { + panic!("This test does not work on this platform. 'index out of bounds'"); + } + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); +} + +#[test] +fn test_arrayvec_const_constructible() { + const OF_U8: ArrayVec, 10> = ArrayVec::new_const(); + + let mut var = OF_U8; + assert!(var.is_empty()); + assert_eq!(var, ArrayVec::new()); + var.push(vec![3, 5, 8]); + assert_eq!(var[..], [vec![3, 5, 8]]); +} + +#[test] +fn test_arraystring_const_constructible() { + const AS: ArrayString<10> = ArrayString::new_const(); + + let mut var = AS; + assert!(var.is_empty()); + assert_eq!(var, ArrayString::new()); + var.push_str("hello"); + assert_eq!(var, *"hello"); +} + + +#[test] +fn test_arraystring_zero_filled_has_some_sanity_checks() { + let string = ArrayString::<4>::zero_filled(); + assert_eq!(string.as_str(), "\0\0\0\0"); + assert_eq!(string.len(), 4); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"210aa07cd2923c5f184d9a260f7a9baf49dec732f886801b829b1d2f9d1d5d51",".travis.yml":"215b99c0f82fa7117b848ac3c207a9e32be1daf8be4e5a0a2df79e58d28c26ac","CHANGELOG.md":"c9bcec48014d5f3da73c2cf0ca9e064e20d764c80f4bd2e63f66ac58dd9c76af","Cargo.toml":"3c6be7429fc29c6f1090284598048e378868919ffc6d09380dc638e5fb4ed872","Cargo.toml.orig":"edad48c88e9244c7011f51c078ff13013c1e6028186f46ef0108b01af0f0e335","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c986bcdb83103d4ddf58aeb7b5302359782e54dc4eea14a0cc27c62dcbd50729","README.md":"78a81cdc2131a7698ec2258ac57373cf4842a0f62fa0f1403d900228700acb87","src/lib.rs":"60546d3d49a9716cf96d205efbbd33ddaba66359d5fcf9e973879ba70e32bc8f"},"package":"516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "c3687342bc9f3c9c202676a5d2e17288ff979c90" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/.travis.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,12 @@ +language: rust + +cache: cargo + +branches: + only: + - staging + - trying + +notifications: + email: + on_success: never diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/as-slice/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/CHANGELOG.md 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,65 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [v0.2.1] - 2021-03-25 + +### Added + +- Moved to `const generics` MVP + +## [v0.1.5] - 2021-03-02 + +### Fixed + +- Security issue. + +## [v0.1.4] - 2020-09-23 + +### Added + +- `generic_array` 0.14 support + +### Fixed + +- Handling of targets with small pointer types, e.g. AVR + +## [v0.1.3] - 2020-02-17 + +### Added + +- `As{,Mut}Slice` implementations for arrays whose lengths are powers of 2 up to + `1 << 16`. + +## [v0.1.2] - 2019-11-22 + +### Added + +- Support for v0.13.x of `generic-array`, in addition to the existing support + for v0.12.x of `generic-array`. + +## [v0.2.0] - 2019-08-29 - YANKED + +- The 0.1.1 release was a breaking change, now in 0.2.0 + +## [v0.1.1] - 2019-08-29 - YANKED + +- Bumped `generic_array` dependency + +## [v0.1.0] - 2018-05-23 + +- Initial release + +[Unreleased]: https://github.com/japaric/as-slice/compare/v0.2.1...HEAD +[v0.2.0]: https://github.com/japaric/as-slice/compare/v0.1.5...v0.2.1 +[v0.1.5]: https://github.com/japaric/as-slice/compare/v0.1.4...v0.1.5 +[v0.1.4]: https://github.com/japaric/as-slice/compare/v0.1.3...v0.1.4 +[v0.1.3]: https://github.com/japaric/as-slice/compare/v0.1.2...v0.1.3 +[v0.1.2]: https://github.com/japaric/as-slice/compare/v0.1.1...v0.1.2 +[v0.2.0]: https://github.com/japaric/as-slice/compare/v0.1.1...v0.2.0 +[v0.1.1]: https://github.com/japaric/as-slice/compare/v0.1.0...v0.1.1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "as-slice" +version = "0.2.1" +authors = ["Jorge Aparicio ", "Emil Fresk "] +description = "`AsSlice` and `AsMutSlice` traits" +readme = "README.md" +keywords = ["conversion", "slice", "array"] +categories = ["no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/japaric/as-slice" +[dependencies.stable_deref_trait] +version = "1.1.1" +default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/Cargo.toml.orig 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,16 @@ +[package] +authors = ["Jorge Aparicio ", "Emil Fresk "] +categories = [ "no-std"] +description = "`AsSlice` and `AsMutSlice` traits" +keywords = ["conversion", "slice", "array"] +license = "MIT OR Apache-2.0" +name = "as-slice" +readme = "README.md" +repository = "https://github.com/japaric/as-slice" +version = "0.2.1" + +[dependencies] + +[dependencies.stable_deref_trait] +default-features = false +version = "1.1.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-APACHE 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/LICENSE-MIT 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2018 Jorge Aparicio + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/README.md clamav-1.4.6+dfsg/.cargo/vendor/as-slice/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/README.md 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,21 @@ +# `as-slice` + +> `AsSlice` and `AsMutSlice` traits + +# [Change log](CHANGELOG.md) + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/as-slice/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/as-slice/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/as-slice/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/as-slice/src/lib.rs 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,94 @@ +//! `AsSlice` and `AsMutSlice` traits +//! +//! These traits are somewhat similar to the `AsRef` and `AsMut` except that they are **NOT** +//! polymorphic (no input type parameter) and their methods always return slices (`[T]`). +//! +//! The main use case of these traits is writing generic code that accepts (fixed size) buffers. For +//! example, a bound `T: StableDeref + AsMutSlice + 'static` will accepts types like +//! `&'static mut [u8]` and `&'static mut [u8; 128]` -- all +//! of them are appropriate for DMA transfers. +//! +//! # Minimal Supported Rust Version (MSRV) +//! +//! This crate is guaranteed to compile on stable Rust 1.51 and up. It *might* compile on older +//! versions but that may change in any new patch release. + +#![deny(missing_docs)] +#![deny(warnings)] +#![no_std] + +extern crate stable_deref_trait; + +/// Something that can be seen as an immutable slice +pub trait AsSlice { + /// The element type of the slice view + type Element; + + /// Returns the immutable slice view of `Self` + fn as_slice(&self) -> &[Self::Element]; +} + +/// Something that can be seen as an mutable slice +pub trait AsMutSlice: AsSlice { + /// Returns the mutable slice view of `Self` + fn as_mut_slice(&mut self) -> &mut [Self::Element]; +} + +impl<'a, S> AsSlice for &'a S +where + S: ?Sized + AsSlice, +{ + type Element = S::Element; + + fn as_slice(&self) -> &[S::Element] { + (**self).as_slice() + } +} + +impl<'a, S> AsSlice for &'a mut S +where + S: ?Sized + AsSlice, +{ + type Element = S::Element; + + fn as_slice(&self) -> &[S::Element] { + (**self).as_slice() + } +} + +impl<'a, S> AsMutSlice for &'a mut S +where + S: ?Sized + AsMutSlice, +{ + fn as_mut_slice(&mut self) -> &mut [S::Element] { + (**self).as_mut_slice() + } +} + +impl AsSlice for [T] { + type Element = T; + + fn as_slice(&self) -> &[T] { + self + } +} + +impl AsMutSlice for [T] { + fn as_mut_slice(&mut self) -> &mut [T] { + self + } +} + +impl AsSlice for [T; N] { + type Element = T; + + fn as_slice(&self) -> &[T] { + self + } +} + +impl AsMutSlice for [T; N] { + fn as_mut_slice(&mut self) -> &mut [T] { + self + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/autocfg/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/autocfg/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"8e60b691c883629c1e19c8dad7c4c18cded1a85c2e8f2e2a77e7a96957f865a7","Cargo.toml":"f8c2d5675773b7ddff8801c3c17ff9d26e9632fe2027a6b81ceb7bda67d71bfd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"51238410cbbb06b149a794d954ff4d5943da566a97e71dc3aa8b5fa5a9b538b6","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/nightly.rs":"ac8b5a9aa1e04465e44f5053b3c899b635e07af058c73aa8b45176bf4b5912f9","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"fd8ff67c64f7cd1b9f81325a81de4baa34c39d6ae298bdb33f9829cc91acac39","src/lib.rs":"7b00cd501b52bab797bf047ada2a446e16fc2b8b05567670d8b8b7ada3179f55","src/rustc.rs":"a8a213ddb64a05c1a1af933bcb331a98879e942b167c33d8f94f9f60ebb14e29","src/tests.rs":"594a1cff6fef4a0f8b5f962a668fda4030db5005f37f01eeb06d692fc48a60df","src/version.rs":"4f7d23b36f01c7be1871be86c038d6cb4689e145d67c82d3793690e9aa05b133","tests/no_std.rs":"cc5619466c6e955552f30ed2f80ba8ddf45c3d5d257f628f54dedc0da978f6aa","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f","tests/wrap_ignored":"a9e241edf584a0702066b25bc15c5bbfd8a1019e14fb655fc4f47a67360065ca","tests/wrappers.rs":"e8eb0eb5ac28ecd9e3473b5ddc321b1d4d523a6fb0c072255ac37d40674aa35c"},"package":"0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a5d8a865b09840faf94c7a4cacc1f181a885780be4c1188f9b9796b9f00e546f","Cargo.lock":"8e60b691c883629c1e19c8dad7c4c18cded1a85c2e8f2e2a77e7a96957f865a7","Cargo.toml":"f8c2d5675773b7ddff8801c3c17ff9d26e9632fe2027a6b81ceb7bda67d71bfd","Cargo.toml.orig":"346712cafd040a3d5abdf30787f37e487619082954926b7dcfd6d07d99904c44","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"51238410cbbb06b149a794d954ff4d5943da566a97e71dc3aa8b5fa5a9b538b6","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/nightly.rs":"ac8b5a9aa1e04465e44f5053b3c899b635e07af058c73aa8b45176bf4b5912f9","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"fd8ff67c64f7cd1b9f81325a81de4baa34c39d6ae298bdb33f9829cc91acac39","src/lib.rs":"7b00cd501b52bab797bf047ada2a446e16fc2b8b05567670d8b8b7ada3179f55","src/rustc.rs":"a8a213ddb64a05c1a1af933bcb331a98879e942b167c33d8f94f9f60ebb14e29","src/tests.rs":"594a1cff6fef4a0f8b5f962a668fda4030db5005f37f01eeb06d692fc48a60df","src/version.rs":"4f7d23b36f01c7be1871be86c038d6cb4689e145d67c82d3793690e9aa05b133","tests/no_std.rs":"cc5619466c6e955552f30ed2f80ba8ddf45c3d5d257f628f54dedc0da978f6aa","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f","tests/wrap_ignored":"a9e241edf584a0702066b25bc15c5bbfd8a1019e14fb655fc4f47a67360065ca","tests/wrappers.rs":"e8eb0eb5ac28ecd9e3473b5ddc321b1d4d523a6fb0c072255ac37d40674aa35c"},"package":"0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/autocfg/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/autocfg/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/autocfg/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6f5ba91def55bc6c875252785cb4b18d74b9f5df" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/autocfg/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/autocfg/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/autocfg/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/autocfg/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +[package] +name = "autocfg" +version = "1.3.0" +authors = ["Josh Stone "] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/cuviper/autocfg" +documentation = "https://docs.rs/autocfg/" +description = "Automatic cfg for Rust compiler features" +readme = "README.md" +keywords = ["rustc", "build", "autoconf"] +categories = ["development-tools::build-utils"] +exclude = ["/.github/**"] +rust-version = "1.0" + +[dependencies] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"0c42edce41949d430715604a47943d23dc8a8a593242f55ded67d9f9ca6d58bd",".github/workflows/av-scenechange.yml":"8647842b2d5bb6c0a77a7b1823ec39eaa1921474dae13c61570e7a54c5f40dac",".github/workflows/dependabot.yml":"4ad0c3f17f918c93f0891c22b13fbb70728702bd40aad831da881d8384245973",".github/workflows/deploy.yml":"defe8dd788d237faecc7b88346261f9f35f59e7b374dda2e81a88128b7dc1e8d","CHANGELOG.md":"3fe588d613e6da412dcf803f478e908ef4cd700e8aab5889b99eb83c4130398e","Cargo.lock":"62e13b644b1c95d8efc34297bc641b9d5604207607eade1c5130b7c93ef9f3c3","Cargo.toml":"0a9f5aa55e2817fa30ee29ce35789f38666ebf94b132ad7a3a833f5ade964049","Cargo.toml.orig":"b605ec0086164d85b08a4f88b850ce4b35bb7aab7e3a13691a2bc778f0a2e449","LICENSE":"1e27e28eafbc439fd153d0cca093fcb9ca83f269d93393e641ce5664181fd41b","README.md":"e224a5cf28fd95ca49fe11a80a34030459bc6049896880d3bf3d49f6e00095bc","build.rs":"ac91ff305fd1b0ab4607c3b6c4ad152b63563bbd8e6e4076aff47c837a9fda3e","rustfmt.toml":"93340ae47f53b368ad8bb1122ce383cf4cb79c814a241338f6f50258d809e24e","src/analyze/fast.rs":"61ef46631bff8472a6dcb567d5e89ecb3e45bcb1efec5d8e46f61a2e22754465","src/analyze/importance.rs":"d0b26d8630460d086c4d11990233e07e30c05b4bd12861d0fd676447e10bf047","src/analyze/inter.rs":"bf273a1ebdc16b16c75aad1a1ef63a799f8d436542a63053aedf4de8bca806ae","src/analyze/intra.rs":"6983a2e7319a60bf3304b31e0cf37b97bb4e98d03369c103242a64a204c67cf1","src/analyze/intra/simd_x86.rs":"106d639cb51935a4a4f5ba426a0dce635d735ce311469bcfc4775e820f327c4f","src/analyze/mod.rs":"2e37f3bcc536acb3176f0ffdfb8ccf4eb9a5a4ff41be99153f451d0248182a44","src/analyze/standard.rs":"9582eadcdc0566a48c0942c8c67922bddfdc212477f8aafaf5e94ecdd8512fc3","src/asm/arm/64/ipred.S":"70e86534b134eda6c1830e865bde325abcdbefa47dc7f59e1aa7d9465daeb3c2","src/asm/arm/64/ipred16.S":"6c48110be07d019c5baac60f8950775eea0e28dfd138607463582211b4082f02","src/asm/arm/64/mc.S":"bf8a84ba5e25244d82c3285323d696f40cdc103b62adf64154650c01fde71f3b","src/asm/arm/64/mc16.S":"e2ab08fa8a7277b2d154b57957e3d41014d5f1f32cb0e458c81754aedbaac260","src/asm/arm/64/satd.S":"eeebc8275726acec1d59400b0d9545e35641f49c12923003ae9462a0860a0331","src/asm/arm/64/util.S":"3b7bfc382e50ccdc6226adde333f7c022a048927d0f50c56611f45dad7e3898b","src/asm/arm/asm.S":"8216de47bc1833967894d6c00fe1b113b0a4dc70f45cba8761ff6e1716420225","src/asm/arm/tables.S":"3d76471a390492bb4e71a5681a72cf93703d4812ded92c774b0d0a6f702914c9","src/asm/x86/ipred16_avx2.asm":"68dceffaabf070cc2d6184f80716d25384c5926ca8f6c067733853977a507cf1","src/asm/x86/ipred16_avx512.asm":"250608ab2d3ae783237101b15b6efe7f2cb7df7edc840a87bf195522a989f850","src/asm/x86/ipred16_sse.asm":"9ddc64ca65961d9c00ef1650e6c95bab48c9e54eb8eeb62d02f4c691686436a7","src/asm/x86/ipred_avx2.asm":"91b36cb826cf1688377a24ffd22983a4c5f970b98a6ee5e920ee0073cdba49c9","src/asm/x86/ipred_avx512.asm":"4be059385cc6b37cfdd45a6ee301bbeddde137829441beeff5154e11559a1ed5","src/asm/x86/ipred_sse.asm":"d7b0ee1225864f8a81f8a6810c084062d120ae95b482ee3f6fba7f6398da24c8","src/asm/x86/mc16_avx2.asm":"53775acbb3d4ea935e5586025e74d1b8bc5d3d9d3306e1f633a8143798b7996d","src/asm/x86/mc16_avx512.asm":"5bd93079e30bcb5f318d8ef1bb2176d0fff70c40b77f1a03c4e4ff85af334307","src/asm/x86/mc16_sse.asm":"577f5fb402eae78240f9f7cecdc7d9e56d83b87ba2804d58b8b0637df5243952","src/asm/x86/mc_avx2.asm":"605ac72bb16db0ec2446a352cf0b8385792b9ca127b0a4339f230c3392b38860","src/asm/x86/mc_avx512.asm":"ce3ea3bb243e9e67e6dd699aee42cc1a955fdc1574da3ba55f4bd4e9d375f36a","src/asm/x86/mc_sse.asm":"ed437418e47da732a52056099d36628ddefeaa8ee9d6c1dc0e16ae7e35cd6dd5","src/asm/x86/sad_avx.asm":"d16bc57f1533bb5d2b372d0b7da8a5db387ae99ca7ab4d233ed8ad440fe6b455","src/asm/x86/sad_plane.asm":"7cc340ea2caf00363dbc671383279236bdaeec09b3da957646dd30fc6900c35d","src/asm/x86/sad_sse2.asm":"72e3cebb6c581fe6e90005372a23bc378397f03afae869e462da067b4e265012","src/asm/x86/satd.asm":"c98a27376dc104022182a09061656ac137b44e555f6dbb8c6fecd23359121b98","src/asm/x86/satd16_avx2.asm":"43b56ab47dc5fcf59708a7a980532b4e7f0a4d1209bc686609d07cebe7b51d18","src/asm/x86/tables.asm":"3407d4323a6f6e64386eced0c8797b8e2a8a80ed4028dcb8262ab3d4a68f759d","src/asm/x86/x86inc.asm":"895a17d18b987f63153ea16b5823923bcc72d1a14e57e2b6cc55e077b749fda7","src/cpu.rs":"d4f9db43cceb89eae26485ded095b00ab23d95736c96b5b2133d43b935071248","src/data/block.rs":"54c5be498a9d3a1ecd869a8f7628b2cbee6051b86b3c5528d83a4abcf104f032","src/data/frame.rs":"c066c48d3f6998b4638dc588c3b00cc82f24e1140db2507a6395add9cf06b083","src/data/hadamard.rs":"f780eb282803a09445439dfbb41689c3a6aea462f2cabebc37e89ba04cd9d31b","src/data/mc.rs":"41bbf1d9b6f3b80fd078a1fad520a3374e0112697114c503c0bbece2dc9a8651","src/data/mc/simd_neon.rs":"fdb25d4537040629515ee9a4e07946f9d09e34da8fe4221518c3b9eed743295f","src/data/mc/simd_x86.rs":"6e94c8c7ac7bad08d96fb84d01d512224271eb13bf2e326564c48f0681561900","src/data/mod.rs":"081c2d4ca8ef74eb72224e7054f8c6e19ef1ff47cee8104f34f864f5404dd1d6","src/data/motion.rs":"d83f686c8eab11ef49d0bf82cc0cdc4b52595ea478cfc4fcb7cd34717b5389bd","src/data/plane.rs":"2960971eb4ef0af80429cf5526056a1712cc741b6a0ea75d96570bde5090ccd6","src/data/prediction.rs":"21234724419e0e8df0ba1d5e8a90bd4ebe697f09909e37c9b2d8e0a5c25e4923","src/data/sad.rs":"0aec6ff5f63280b178afc512022a1b1fe4d23f1582585e35b1a78c79f70154d7","src/data/sad/simd_x86.rs":"fd1b53e685f60047c4bf9042a02ca0238da15b0c8bb93353ecca67c1af7fd097","src/data/satd.rs":"dac4a8ccd01e44fdb0e66fac55f4bd27a12d68656485ec159000022dd1277d8e","src/data/satd/simd_neon.rs":"f40fdb06295137d94acabbf113546b024d4ba5cc540712882f56e4f5e1f5dc78","src/data/satd/simd_x86.rs":"9fef64909a9d35d972b16f1cdefe6d18ba00d6705747637faf4e74e19d475635","src/data/satd/tests.rs":"0be3acbf95750433388aa1a5c886dae20d692c34bb122381410b9dafd47b756a","src/data/superblock.rs":"58bc3c6a0dc4de8fff5887bbed1f4845583a29c111a1692bed62f6a29db56916","src/data/tile.rs":"ef21feac8a182451e7c6af6fb66c54724b43a49352b539f265988218813be78e","src/decoder.rs":"9f36fb3edff8f6ef4123aaf2c4f166b1a80e623dee1d3b9539c8e409910bf85c","src/ffmpeg.rs":"d2ed432b5a26d167866afb62438ce7f4c0f6dda855b8bb7638ade163005597ee","src/lib.rs":"044f28aac4e18ed94d84a98ffe510ca880c82ac765a28ee901fae04af6708253","src/main.rs":"7556af76069e1b10471127a1884360878b7c24d28073e535b0d796559bfbfd85","src/vapoursynth.rs":"06caf9c8cd3a08034a38acc4ccbe777c14d4b5a3d39cc07c19f9f9804852ea4b","src/y4m.rs":"a17e6554a0de641bf70335ea5fd9e18e64c4a88aac902e22fab3d23825dda555"},"package":"0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae3d7e5f8f7d9fac3ba3813b8ffe57f7b3420a20" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/av-scenechange.yml clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/av-scenechange.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/av-scenechange.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/av-scenechange.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,91 @@ +name: av-scenechange + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + rustfmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install nightly + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Run rustfmt + run: | + cargo fmt -- --check + + build: + needs: [rustfmt] + strategy: + matrix: + platform: [ubuntu-latest, windows-latest, ubuntu-24.04-arm] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4 + - uses: ilammy/setup-nasm@v1 + + - name: Install stable + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + + - name: Set MSVC x86_64 linker path + if: matrix.platform == 'windows-latest' + run: | + $LinkGlob = "VC\Tools\MSVC\*\bin\Hostx64\x64" + $env:PATH = "$env:PATH;${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer" + $LinkPath = vswhere -latest -products * -find "$LinkGlob" | + Select-Object -Last 1 + echo "$LinkPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Clippy + run: cargo clippy --features binary,devel,tracing,serialize --tests --benches -- -D warnings + + - name: Build + run: cargo build --features binary,devel,tracing,serialize --tests --benches + + - name: Run tests + run: cargo test --features binary,devel,tracing,serialize + + - name: Generate docs + run: cargo doc --features binary,devel,tracing,serialize --no-deps + + code-coverage: + needs: [build] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: ilammy/setup-nasm@v1 + + - name: Install stable + uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@v2 + with: + tool: cargo-llvm-cov + + - name: Generate code coverage + run: cargo llvm-cov --features binary,tracing,serialize --lcov --output-path lcov.log --ignore-filename-regex tests\.rs + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.log + fail_ci_if_error: false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + commit-message: + prefix: "chore" + include: "scope" + labels: + - "dependencies" + - "rust" + groups: + rust-dependencies: + patterns: + - "*" + update-types: + - "minor" + - "patch" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/deploy.yml clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/deploy.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/.github/workflows/deploy.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/.github/workflows/deploy.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +name: deploy + +on: + push: + tags: + - "v*.*.*" + +jobs: + create-binaries: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install nasm + run: | + $NASM_VERSION="2.15.05" + $LINK="https://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/win64" + curl -LO "$LINK/nasm-$NASM_VERSION-win64.zip" + 7z e -y "nasm-$NASM_VERSION-win64.zip" -o"C:\nasm" + echo "C:\nasm" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable-x86_64-pc-windows-gnu + override: true + + - name: Build + run: | + cargo build --release + + - name: Create zip + run: | + $METRICS_PATH="$Env:GITHUB_WORKSPACE\target\release" + 7z a av-scenechange.zip ` + "$METRICS_PATH\av-scenechange.exe" + + - name: Upload binaries + uses: actions/upload-artifact@v2 + with: + name: av-scenechange-bins + path: av-scenechange.zip + + deploy: + needs: create-binaries + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Download the zip + uses: actions/download-artifact@v2 + + - name: Unzip av-scenechange Windows binaries + run: | + unzip av-scenechange-bins/av-scenechange.zip -d av-scenechange-bins + + - name: Handle release data and files + id: data + run: | + VERSION=$(head -n 1 CHANGELOG.md | tr -d "## Version ") + echo "::set-output name=version::$VERSION" + tail -n +2 CHANGELOG.md | sed -e '/^$/,$d' > CHANGELOG.txt + cd av-scenechange-bins + strip av-scenechange.exe + mv av-scenechange.exe .. + + - name: Create a release + uses: softprops/action-gh-release@v1 + with: + name: Version ${{ steps.data.outputs.version }} + body_path: CHANGELOG.txt + files: | + av-scenechange.exe + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +## Version 0.14.1 + +- Readd support for caching intra costs +- Expose structs for advanced API users + +## Version 0.14.0 + +- [Breaking/Feature] Add `SceneDetectionSpeed::None`, which will only place keyframes at fixed intervals without running dynamic detection +- Migrate detection code from rav1e into this crate + +## Version 0.13.0 + +- [Breaking] Update ffmpeg-the-third to 3.x +- Update all other dependencies to latest version + +## Version 0.12.2 + +- Enable threading for ffmpeg decoder, should greatly improve speed + +## Version 0.12.0 + +- [Breaking] Move `VideoDetails` struct from `y4m` module to `decoder` module, since it is not specific to y4m +- Add support for Ffmpeg decoder (requires Cargo `ffmpeg` feature, disabled by default) + +## Version 0.11.0 + +- Add support for Vapoursynth decoder (requires Cargo `vapoursynth` feature, disabled by default) +- Breaking change required to add a wrapper enum defining which decoder is being used + +## Version 0.10.0 + +- Bump `rav1e` dependency to `0.7` + +## Version 0.9.0 + +- Bump `y4m` dependency to `0.8` + +## Version 0.8.1 + +- Finally release a new version because we can depend on rav1e 0.6.1 + +## Version 0.8.0 + +- Upgrade clap to 4.0 +- Add frame limit arg to API +- [Breaking] Change `progress_callback` to take a &dyn Fn +- Misc improvements including some speedups from rav1e +- Update to Rust edition 2021 + +## Version 0.7.2 + +- Bump to the final release of rav1e 0.5 +- Bump other dependencies to latest versions +- Fix another inconsistency with rav1e's scene detection +- Improve precision of FPS calculation + +## Version 0.7.1 + +- Fix an inconsistency with how rav1e's scene detection works +- Fix some CLI help text + +## Version 0.7.0 + +- Bump rav1e dependency to 0.5-beta.2, which brings a new, improved scenechange algorithm. + Medium is equivalent to the old slow level, but with improvements. The fast level + also has improvements. The new slow level is a new algorithm with a higher accuracy + than the previous two algorithms. +- The `--fast-mode` CLI argument is removed in favor of a `--speed` or `-s` argument, + which takes a 0, 1, or 2 (for slow, medium, or fast). The default is 0 for slow. + +## Version 0.6.0 + +- Bump rav1e dependency to 0.5. This should bring significant performance improvements, + but may cause breaking changes. + +## Version 0.5.0 + +- Bump rav1e dependency to 0.4 +- Expose `new_detector` and `detect_scene_changes` since these + may be useful in some situations to use directly + +## Version 0.4.2 + +- Fix compilation on non-x86 targets +- Bump various dependencies + +## Version 0.4.1 + +- Improve performance and memory usage + +## Version 0.4.0 + +- [Breaking, New Feature] `detect_scene_changes` returns a `DetectionOptions` struct, + which includes the list of scenecut frames, and the total count + of frames in the video. The CLI output will reflect this as well. +- [Breaking] Replace the default algorithm with an 8x8-block cost-based algorithm. + This is more accurate in many cases. +- [Breaking] As a result of the above change, now requires nasm for compilation. + No action is needed if you use a prebuilt binary. +- [Breaking] Replace the `use_chroma` option with a `fast_analysis` option. + The new name is more accurate, as the updated algorithm will always analyze + only the luma plane. +- [Breaking] Move the `progress_callback` parameter from `DetectionOptions` + to `detect_scene_changes`, since it only applies to that interface. +- [New Feature] Expose the `SceneChangeDetector` struct, which allows + going frame-by-frame to analyze a clip. Needed for some use cases. + `detect_scene_changes` is the simpler, preferred interface. +- The library for inputting frame data has been replaced + with one that matches rav1e. +- Simplify/optimize some internal code. + +## Version 0.3.0 + +- [Breaking, New Feature] Add the ability to pass a `progress_callback` function + to the `DetectionOptions`. + +## Version 0.2.0 + +- [Breaking] Update `y4m` dependency to 0.5 + +## Version 0.1.0 + +- Initial release diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1138 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "cc", + "clap", + "console", + "fern", + "ffmpeg-the-third", + "libc", + "log", + "nasm-rs", + "num-rational", + "num-traits", + "pastey", + "rayon", + "serde", + "serde_json", + "thiserror 2.0.12", + "tracing", + "tracing-chrome", + "tracing-subscriber", + "v_frame", + "vapoursynth", + "y4m", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.9.1", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "cc" +version = "1.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c044c781163c001b913cd018fc95a628c50d0d2dfea8bca77dad71edb16e37" +dependencies = [ + "clang-sys", + "libc", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + +[[package]] +name = "ffmpeg-sys-the-third" +version = "3.0.0+ffmpeg-7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ac7541c97a452897b3b85648e2e6fcd862c272ea0085ee3cbd7c7e2cfed95b" +dependencies = [ + "bindgen", + "cc", + "clang", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ffmpeg-the-third" +version = "3.0.1+ffmpeg-7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79adca4fd8d80989bd449a19afdf31235849384ea5a6ef64489f155794e3be7f" +dependencies = [ + "bitflags 2.9.1", + "ffmpeg-sys-the-third", + "libc", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libloading" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" +dependencies = [ + "cfg-if", + "windows-targets 0.53.0", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nasm-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12fcfa1bd49e0342ec1d07ed2be83b59963e7acbeb9310e1bb2c07b69dadd959" +dependencies = [ + "jobserver", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pastey" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-chrome" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vapoursynth" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7df702c65dec1cfa3b93f824a1e58d5b0fdb82ac8a722596f43d7214282f56" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "lazy_static", + "thiserror 1.0.69", + "vapoursynth-sys", +] + +[[package]] +name = "vapoursynth-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b35092be61a799005aabfd2e9e95d074125984013142d87a5d3edecc039b9b5" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,182 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.74.1" +name = "av-scenechange" +version = "0.14.1" +authors = ["Josh Holmer "] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Estimates frames in a video where a scenecut would be ideal" +readme = "README.md" +license = "MIT" +repository = "https://github.com/rust-av/av-scenechange" + +[features] +asm = [ + "nasm-rs", + "cc", + "libc", +] +binary = [ + "clap", + "serialize", +] +default = [ + "binary", + "asm", +] +devel = [ + "console", + "fern", +] +ffmpeg = ["ffmpeg-the-third"] +libc = ["dep:libc"] +serialize = [ + "serde", + "serde_json", +] +tracing = [ + "tracing-subscriber", + "tracing-chrome", + "dep:tracing", +] + +[lib] +name = "av_scenechange" +path = "src/lib.rs" + +[[bin]] +name = "av-scenechange" +path = "src/main.rs" +required-features = ["binary"] + +[dependencies.aligned] +version = "0.4.2" + +[dependencies.anyhow] +version = "1.0.56" + +[dependencies.arg_enum_proc_macro] +version = "0.3.4" + +[dependencies.arrayvec] +version = "0.7.6" + +[dependencies.clap] +version = "4.0.22" +features = ["derive"] +optional = true + +[dependencies.console] +version = "0.15" +optional = true + +[dependencies.fern] +version = "0.7" +optional = true + +[dependencies.ffmpeg-the-third] +version = "3.0.0" +features = [ + "codec", + "format", +] +optional = true +default-features = false + +[dependencies.libc] +version = "0.2.172" +optional = true + +[dependencies.log] +version = "0.4.14" + +[dependencies.num-rational] +version = "0.4.2" +default-features = false + +[dependencies.num-traits] +version = "0.2.19" + +[dependencies.pastey] +version = "0.1.0" + +[dependencies.rayon] +version = "1.10.0" + +[dependencies.serde] +version = "1.0.123" +features = ["derive"] +optional = true + +[dependencies.serde_json] +version = "1.0.62" +optional = true + +[dependencies.thiserror] +version = "2.0.12" + +[dependencies.tracing] +version = "0.1.40" +optional = true + +[dependencies.tracing-chrome] +version = "0.7.1" +optional = true + +[dependencies.tracing-subscriber] +version = "0.3.18" +optional = true + +[dependencies.v_frame] +version = "0.3.8" + +[dependencies.vapoursynth] +version = "0.4.0" +features = [ + "vsscript-functions", + "vapoursynth-functions", + "vapoursynth-api-32", + "vsscript-api-31", +] +optional = true + +[dependencies.y4m] +version = "0.8.0" + +[build-dependencies.cc] +version = "1.2.23" +features = ["parallel"] +optional = true + +[build-dependencies.nasm-rs] +version = "0.3" +features = ["parallel"] +optional = true + +[lints.clippy] +inline_always = "warn" +missing_inline_in_public_items = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(asm_x86_64)", + "cfg(asm_neon)", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +[package] +name = "av-scenechange" +version = "0.14.1" +authors = ["Josh Holmer "] +edition = "2021" +rust-version = "1.74.1" +description = "Estimates frames in a video where a scenecut would be ideal" +license = "MIT" +repository = "https://github.com/rust-av/av-scenechange" +build = "build.rs" + +[dependencies] +aligned = "0.4.2" +anyhow = "1.0.56" +arg_enum_proc_macro = "0.3.4" +arrayvec = "0.7.6" +clap = { version = "4.0.22", optional = true, features = ["derive"] } +console = { version = "0.15", optional = true } +fern = { version = "0.7", optional = true } +ffmpeg-the-third = { version = "3.0.0", optional = true, default-features = false, features = [ + "codec", + "format", +] } +libc = { version = "0.2.172", optional = true } +log = { version = "0.4.14" } +num-rational = { version = "0.4.2", default-features = false } +num-traits = "0.2.19" +pastey = "0.1.0" +rayon = "1.10.0" +serde = { version = "1.0.123", optional = true, features = ["derive"] } +serde_json = { version = "1.0.62", optional = true } +thiserror = "2.0.12" +tracing = { version = "0.1.40", optional = true } +tracing-chrome = { version = "0.7.1", optional = true } +tracing-subscriber = { version = "0.3.18", optional = true } +v_frame = "0.3.8" +vapoursynth = { version = "0.4.0", features = [ + "vsscript-functions", + "vapoursynth-functions", + "vapoursynth-api-32", + "vsscript-api-31", +], optional = true } +y4m = "0.8.0" + + +[build-dependencies] +cc = { version = "1.2.23", optional = true, features = ["parallel"] } +nasm-rs = { version = "0.3", optional = true, features = ["parallel"] } + +[features] +default = ["binary", "asm"] +binary = ["clap", "serialize"] +serialize = ["serde", "serde_json"] +devel = ["console", "fern"] +tracing = ["tracing-subscriber", "tracing-chrome", "dep:tracing"] +ffmpeg = ["ffmpeg-the-third"] +asm = ["nasm-rs", "cc", "libc"] +libc = ["dep:libc"] + +[[bin]] +name = "av-scenechange" +path = "src/main.rs" +required-features = ["binary"] + +[lints.clippy] +inline_always = "warn" +missing_inline_in_public_items = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +# These custom cfgs are expected, so tell rustc not to output warnings for them +check-cfg = ['cfg(asm_x86_64)', 'cfg(asm_neon)'] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Multimedia and Rust + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/README.md clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +# av-scenechange + +[![Actions Status](https://github.com/rust-av/av-scenechange/workflows/av-scenechange/badge.svg)](https://github.com/rust-av/av-scenechange/actions) +[![docs.rs](https://img.shields.io/docsrs/av-scenechange)](https://docs.rs/av-scenechange/latest/av-scenechange/) +[![Crates.io Version](https://img.shields.io/crates/v/av-scenechange)](https://crates.io/crates/av-scenechange) +[![Crates.io License](https://img.shields.io/crates/l/av-scenechange)](LICENSE) + + +Scenechange detection tool diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/build.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,252 @@ +use std::{ + env, + fs, + path::{Path, PathBuf}, +}; + +fn rerun_dir>(dir: P) { + for entry in fs::read_dir(dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + println!("cargo:rerun-if-changed={}", path.to_string_lossy()); + + if path.is_dir() { + rerun_dir(path); + } + } +} + +fn hash_changed(files: &[&str], out_dir: &str, config: &Path) -> Option<([u8; 8], PathBuf)> { + use std::{collections::hash_map::DefaultHasher, hash::Hasher}; + + let mut hasher = DefaultHasher::new(); + + let paths = files + .iter() + .map(Path::new) + .chain(std::iter::once(config)) + .chain(std::iter::once(Path::new("build.rs"))); + + for path in paths { + if let Ok(buf) = std::fs::read(path) { + hasher.write(&buf); + } else { + panic!("Cannot open {}", path.display()); + } + } + + if let Some(cmd) = strip_command() { + hasher.write(cmd.as_bytes()); + } + + let hash = hasher.finish().to_be_bytes(); + + let hash_path = Path::new(&out_dir).join("asm.hash"); + + if let Ok(old_hash) = std::fs::read(&hash_path) { + if old_hash == hash { + return None; + } + } + + Some((hash, hash_path)) +} + +#[cfg(feature = "asm")] +fn build_nasm_files() { + let mut config = " +%pragma preproc sane_empty_expansion true +%define private_prefix avsc +%define ARCH_X86_32 0 +%define ARCH_X86_64 1 +%define PIC 1 +%define STACK_ALIGNMENT 16 +%define HAVE_AVX512ICL 1 +" + .to_owned(); + + if env::var("CARGO_CFG_TARGET_VENDOR").unwrap() == "apple" { + config += "%define PREFIX 1\n"; + } + + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("config.asm"); + std::fs::write(&dest_path, config).expect("can write config.asm"); + + let asm_files = &[ + // "src/asm/x86/cdef_avx2.asm", + // "src/asm/x86/cdef_avx512.asm", + // "src/asm/x86/cdef_dist.asm", + // "src/asm/x86/cdef_rav1e.asm", + // "src/asm/x86/cdef_sse.asm", + // "src/asm/x86/cdef16_avx2.asm", + // "src/asm/x86/cdef16_avx512.asm", + // "src/asm/x86/cdef16_sse.asm", + "src/asm/x86/ipred_avx2.asm", + "src/asm/x86/ipred_avx512.asm", + "src/asm/x86/ipred_sse.asm", + "src/asm/x86/ipred16_avx2.asm", + "src/asm/x86/ipred16_avx512.asm", + "src/asm/x86/ipred16_sse.asm", + // "src/asm/x86/itx_avx2.asm", + // "src/asm/x86/itx_avx512.asm", + // "src/asm/x86/itx_sse.asm", + // "src/asm/x86/itx16_avx2.asm", + // "src/asm/x86/itx16_avx512.asm", + // "src/asm/x86/itx16_sse.asm", + // "src/asm/x86/looprestoration_avx2.asm", + // "src/asm/x86/looprestoration_avx512.asm", + // "src/asm/x86/looprestoration_sse.asm", + // "src/asm/x86/looprestoration16_avx2.asm", + // "src/asm/x86/looprestoration16_avx512.asm", + // "src/asm/x86/looprestoration16_sse.asm", + "src/asm/x86/mc_avx2.asm", + "src/asm/x86/mc_avx512.asm", + "src/asm/x86/mc_sse.asm", + "src/asm/x86/mc16_avx2.asm", + "src/asm/x86/mc16_avx512.asm", + "src/asm/x86/mc16_sse.asm", + // "src/asm/x86/me.asm", + "src/asm/x86/sad_avx.asm", + "src/asm/x86/sad_plane.asm", + "src/asm/x86/sad_sse2.asm", + "src/asm/x86/satd.asm", + "src/asm/x86/satd16_avx2.asm", + // "src/asm/x86/sse.asm", + "src/asm/x86/tables.asm", + ]; + + if let Some((hash, hash_path)) = hash_changed(asm_files, &out_dir, &dest_path) { + let obj = nasm_rs::Build::new() + .min_version(2, 15, 0) + .include(&out_dir) + .include("src") + .files(asm_files) + .compile_objects() + .unwrap_or_else(|e| { + panic!("NASM build failed. Make sure you have nasm installed or disable the \"asm\" feature.\n\ + You can get NASM from https://nasm.us or your system's package manager.\n\ + \n\ + error: {e}"); + }); + + // cc is better at finding the correct archiver + let mut cc = cc::Build::new(); + for o in obj { + cc.object(o); + } + cc.compile("avscasm"); + + // Strip local symbols from the asm library since they + // confuse the debugger. + if let Some(strip) = strip_command() { + let _ = std::process::Command::new(strip) + .arg("-x") + .arg(Path::new(&out_dir).join("libavscasm.a")) + .status(); + } + + std::fs::write(hash_path, &hash[..]).unwrap(); + } else { + println!("cargo:rustc-link-search={out_dir}"); + } + println!("cargo:rustc-link-lib=static=avscasm"); + rerun_dir("src/asm/x86"); +} + +fn strip_command() -> Option { + let target = env::var("TARGET").expect("TARGET"); + // follows Cargo's naming convention for the linker setting + let normalized_target = target.replace('-', "_").to_uppercase(); + let explicit_strip = env::var(format!("CARGO_TARGET_{normalized_target}_STRIP")) + .ok() + .or_else(|| env::var("STRIP").ok()); + if explicit_strip.is_some() { + return explicit_strip; + } + + // strip command is target-specific, e.g. macOS's strip breaks MUSL's archives + let host = env::var("HOST").expect("HOST"); + if host != target { + return None; + } + + Some("strip".into()) +} + +#[cfg(feature = "asm")] +fn build_neon_asm_files() { + let mut config = " +#define PRIVATE_PREFIX avsc_ +#define ARCH_AARCH64 1 +#define ARCH_ARM 0 +#define CONFIG_LOG 1 +#define HAVE_ASM 1 +" + .to_owned(); + + if env::var("CARGO_CFG_TARGET_VENDOR").unwrap() == "apple" { + config += "#define PREFIX 1\n"; + } + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("config.h"); + std::fs::write(&dest_path, config).expect("can write config.h"); + + let asm_files = &[ + // "src/asm/arm/64/cdef.S", + // "src/asm/arm/64/cdef16.S", + // "src/asm/arm/64/cdef_dist.S", + "src/asm/arm/64/mc.S", + "src/asm/arm/64/mc16.S", + // "src/asm/arm/64/itx.S", + // "src/asm/arm/64/itx16.S", + "src/asm/arm/64/ipred.S", + "src/asm/arm/64/ipred16.S", + // "src/asm/arm/64/sad.S", + "src/asm/arm/64/satd.S", + // "src/asm/arm/64/sse.S", + "src/asm/arm/tables.S", + ]; + + if let Some((hash, hash_path)) = hash_changed(asm_files, &out_dir, &dest_path) { + cc::Build::new() + .files(asm_files) + .include(".") + .include(&out_dir) + .compile("avsc-aarch64"); + + std::fs::write(hash_path, &hash[..]).unwrap(); + } else { + println!("cargo:rustc-link-search={out_dir}"); + println!("cargo:rustc-link-lib=static=avsc-aarch64"); + } + rerun_dir("src/asm/arm"); +} + +#[allow(unused_variables)] +fn main() { + let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + let os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + // let env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); + + #[cfg(feature = "asm")] + { + if arch == "x86_64" { + println!("cargo:rustc-cfg=asm_x86_64"); + build_nasm_files() + } + if arch == "aarch64" { + println!("cargo:rustc-cfg=asm_neon"); + build_neon_asm_files() + } + } + + println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + if let Ok(value) = env::var("CARGO_CFG_TARGET_FEATURE") { + println!("cargo:rustc-env=CARGO_CFG_TARGET_FEATURE={value}"); + } + println!( + "cargo:rustc-env=CARGO_ENCODED_RUSTFLAGS={}", + env::var("CARGO_ENCODED_RUSTFLAGS").unwrap() + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +use_field_init_shorthand = true +use_try_shorthand = true + +# Unstable features--for future stabilization +imports_layout = "HorizontalVertical" +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +format_strings = true +format_macro_matchers = true +format_macro_bodies = true +hex_literal_case = "Lower" +normalize_comments = true +normalize_doc_attributes = true +overflow_delimited_expr = true +reorder_impl_items = true +wrap_comments = true +format_code_in_doc_comments = true +empty_item_single_line = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/fast.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/fast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/fast.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/fast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +use std::{cmp, sync::Arc}; + +use log::debug; +use v_frame::{frame::Frame, pixel::Pixel, plane::Plane}; + +use super::{fast_idiv, ScaleFunction, SceneChangeDetector, ScenecutResult}; +use crate::{data::sad::sad_plane, SceneDetectionSpeed}; + +/// Experiments have determined this to be an optimal threshold +pub(super) const FAST_THRESHOLD: f64 = 18.0; + +impl SceneChangeDetector { + /// The fast algorithm detects fast cuts using a raw difference + /// in pixel values between the scaled frames. + pub(super) fn fast_scenecut( + &mut self, + frame1: Arc>, + frame2: Arc>, + ) -> ScenecutResult { + if let Some(scale_func) = &self.scale_func { + // downscale both frames for faster comparison + if let Some(frame_buffer) = &mut self.downscaled_frame_buffer { + frame_buffer.swap(0, 1); + (scale_func.downscale_in_place)(&frame2.planes[0], &mut frame_buffer[1]); + } else { + self.downscaled_frame_buffer = Some([ + (scale_func.downscale)(&frame1.planes[0]), + (scale_func.downscale)(&frame2.planes[0]), + ]); + } + + if let Some(frame_buffer) = &self.downscaled_frame_buffer { + let &[first, second] = &frame_buffer; + let delta = self.delta_in_planes(first, second); + + ScenecutResult { + threshold: self.threshold, + inter_cost: delta, + imp_block_cost: delta, + forward_adjusted_cost: delta, + backward_adjusted_cost: delta, + } + } else { + unreachable!() + } + } else { + let delta = self.delta_in_planes(&frame1.planes[0], &frame2.planes[0]); + + ScenecutResult { + threshold: self.threshold, + inter_cost: delta, + imp_block_cost: delta, + backward_adjusted_cost: delta, + forward_adjusted_cost: delta, + } + } + } + + /// Calculates the average sum of absolute difference (SAD) per pixel + /// between 2 planes + fn delta_in_planes(&self, plane1: &Plane, plane2: &Plane) -> f64 { + let delta = sad_plane(plane1, plane2, self.cpu_feature_level); + + delta as f64 / self.scaled_pixels as f64 + } +} + +/// Scaling factor for frame in scene detection +pub(super) fn detect_scale_factor( + resolution: (usize, usize), + speed_mode: SceneDetectionSpeed, +) -> Option> { + let small_edge = cmp::min(resolution.0, resolution.1); + let scale_func = if speed_mode == SceneDetectionSpeed::Fast { + match small_edge { + 0..=240 => None, + 241..=480 => Some(ScaleFunction::from_scale::<2>()), + 481..=720 => Some(ScaleFunction::from_scale::<4>()), + 721..=1080 => Some(ScaleFunction::from_scale::<8>()), + 1081..=1600 => Some(ScaleFunction::from_scale::<16>()), + 1601..=usize::MAX => Some(ScaleFunction::from_scale::<32>()), + _ => None, + } + } else { + None + }; + + if let Some(scale_factor) = scale_func.as_ref().map(|x| x.factor) { + debug!( + "Scene detection scale factor {}, [{},{}] -> [{},{}]", + scale_factor, + resolution.0, + resolution.1, + fast_idiv(resolution.0, scale_factor), + fast_idiv(resolution.1, scale_factor) + ); + } + + scale_func +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/importance.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/importance.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/importance.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/importance.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +use std::sync::Arc; + +use v_frame::{ + frame::Frame, + pixel::{CastFromPrimitive, Pixel}, +}; + +use super::intra::BLOCK_TO_PLANE_SHIFT; +use crate::data::plane::{Area, AsRegion, PlaneRegion, Rect}; + +/// Size of blocks for the importance computation, in pixels. +pub const IMPORTANCE_BLOCK_SIZE: usize = + 1 << (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT); +pub const IMPORTANCE_BLOCK_TO_BLOCK_SHIFT: usize = 1; +pub const IMP_BLOCK_MV_UNITS_PER_PIXEL: i64 = 8; +pub const IMP_BLOCK_SIZE_IN_MV_UNITS: i64 = + IMPORTANCE_BLOCK_SIZE as i64 * IMP_BLOCK_MV_UNITS_PER_PIXEL; + +pub(crate) fn estimate_importance_block_difference( + frame: Arc>, + ref_frame: Arc>, +) -> f64 { + let plane_org = &frame.planes[0]; + let plane_ref = &ref_frame.planes[0]; + let h_in_imp_b = plane_org.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane_org.cfg.width / IMPORTANCE_BLOCK_SIZE; + + let mut imp_block_costs = 0; + + (0..h_in_imp_b).for_each(|y| { + (0..w_in_imp_b).for_each(|x| { + // Coordinates of the top-left corner of the reference block, in MV + // units. + let region_org = plane_org.region(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + let region_ref = plane_ref.region(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + let sum_8x8_block = |region: &PlaneRegion| { + region + .rows_iter() + .map(|row| { + // 16-bit precision is sufficient for an 8 px row, + // as `IMPORTANCE_BLOCK_SIZE * (2^12 - 1) < 2^16 - 1`, + // so overflow is not possible + row.iter().map(|pixel| u16::cast_from(*pixel)).sum::() as i64 + }) + .sum::() + }; + + let histogram_org_sum = sum_8x8_block(®ion_org); + let histogram_ref_sum = sum_8x8_block(®ion_ref); + + let count = (IMPORTANCE_BLOCK_SIZE * IMPORTANCE_BLOCK_SIZE) as i64; + + let mean = (((histogram_org_sum + count / 2) / count) + - ((histogram_ref_sum + count / 2) / count)) + .abs(); + + imp_block_costs += mean as u64; + }); + }); + + imp_block_costs as f64 / (w_in_imp_b * h_in_imp_b) as f64 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/inter.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/inter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/inter.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/inter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1882 @@ +use std::sync::Arc; + +use aligned::{Aligned, A64}; +use arrayvec::ArrayVec; +use num_rational::Rational32; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use v_frame::{ + frame::Frame, + math::{clamp, ILog}, + pixel::{ChromaSampling, Pixel}, + plane::{Plane, PlaneConfig, PlaneOffset}, +}; + +use super::importance::{ + IMPORTANCE_BLOCK_SIZE, + IMP_BLOCK_MV_UNITS_PER_PIXEL, + IMP_BLOCK_SIZE_IN_MV_UNITS, +}; +use crate::{ + cpu::CpuFeatureLevel, + data::{ + block::{BlockOffset, BlockSize, MIB_SIZE_LOG2}, + frame::{FrameInvariants, FrameState, RefType, ALLOWED_REF_FRAMES}, + motion::{ + MEStats, + MVSamplingMode, + MotionEstimationSubsets, + MotionVector, + ReadGuardMEStats, + RefMEStats, + TileMEStats, + MV_LOW, + MV_UPP, + }, + plane::{Area, AsRegion, PlaneBlockOffset, PlaneRegion, PlaneRegionMut, Rect}, + prediction::PredictionMode, + sad::get_sad, + satd::get_satd, + superblock::{ + SuperBlockOffset, + TileSuperBlockOffset, + MAX_SB_SIZE_LOG2, + MI_SIZE, + MI_SIZE_LOG2, + SB_SIZE, + }, + tile::{TileBlockOffset, TileRect, TileStateMut, TilingInfo}, + }, +}; + +/// Declares an array of motion vectors in structure of arrays syntax. +macro_rules! search_pattern_subpel { + ($field_a:ident: [$($ll_a:expr),*], $field_b:ident: [$($ll_b:expr),*]) => { + [ $(MotionVector { $field_a: $ll_a, $field_b: $ll_b } ),*] + }; +} + +/// Declares an array of motion vectors in structure of arrays syntax. +/// Compared to [`search_pattern_subpel`], this version creates motion vectors +/// in fullpel resolution (x8). +macro_rules! search_pattern { + ($field_a:ident: [$($ll_a:expr),*], $field_b:ident: [$($ll_b:expr),*]) => { + [ $(MotionVector { $field_a: $ll_a << 3, $field_b: $ll_b << 3 } ),*] + }; +} + +/// Diamond pattern of radius 1 as shown below. For fullpel search, use +/// `DIAMOND_R1_PATTERN_FULLPEL` since it has been scaled for fullpel search. +/// ```text +/// X +/// XoX +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const DIAMOND_R1_PATTERN_SUBPEL: [MotionVector; 4] = search_pattern_subpel!( + col: [ 0, 1, 0, -1], + row: [ 1, 0, -1, 0] +); + +/// Diamond pattern of radius 1 as shown below. Unlike `DIAMOND_R1_PATTERN`, the +/// vectors have been shifted fullpel scale. +/// ```text +/// X +/// XoX +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const DIAMOND_R1_PATTERN: [MotionVector; 4] = search_pattern!( + col: [ 0, 1, 0, -1], + row: [ 1, 0, -1, 0] +); + +/// Uneven multi-hexagon search pattern around a center point. Used for locating +/// irregular movement. +/// ```text +/// X +/// X X +/// X X +/// X X +/// X o X +/// X X +/// X X +/// X X +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const UMH_PATTERN: [MotionVector; 16] = search_pattern!( + col: [ -2, -1, 0, 1, 2, 3, 4, 3, 2, 1, 0, -1, -2, 3, -4, -3], + row: [ 4, 4, 4, 4, 4, 2, 0, -2, -4, -4, -4, -4, -4, -2, 0, 2] +); + +/// A hexagon pattern around a center point. The pattern is ordered so that the +/// offsets circle around the center. This is done to allow pruning locations +/// covered by the last iteration. +/// ```text +/// 21012 +/// 2 X X +/// 1 +/// 0 X o X +/// 1 +/// 2 X X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +/// +/// The illustration below shows the process of a hexagon search. +/// ```text +/// Step 1 Step 2 +/// 1 1 1 1 2 +/// +/// 1(0)1 => 1 0(1)2 +/// +/// 1 1 1 1 2 +/// ``` +/// The search above has gone through the following steps. +/// 1. Search '1' elements for better candidates than the center '0'. +/// 2. Recenter around the best candidate ('(1)') and hexagon candidates that +/// don't overlap with the previous search step (labeled '2'). +const HEXAGON_PATTERN: [MotionVector; 6] = search_pattern!( + col: [ 0, 2, 2, 0, -2, -2], + row: [ -2, -1, 1, 2, 1, -1] +); + +/// A small square pattern around a center point. +/// ```text +/// 101 +/// 1 XXX +/// 0 XoX +/// 1 XXX +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const SQUARE_REFINE_PATTERN: [MotionVector; 8] = search_pattern!( + col: [ -1, 0, 1, -1, 1, -1, 0, 1], + row: [ 1, 1, 1, 0, 0, -1, -1, -1] +); + +pub(crate) fn estimate_inter_costs( + frame: Arc>, + ref_frame: Arc>, + bit_depth: usize, + frame_rate: Rational32, + chroma_sampling: ChromaSampling, + buffer: RefMEStats, + cpu_feature_level: CpuFeatureLevel, +) -> f64 { + let last_fi = + FrameInvariants::new_key_frame(frame.planes[0].cfg.width, frame.planes[0].cfg.height); + let fi = FrameInvariants::new_inter_frame(&last_fi, 1).unwrap(); + + // Compute the motion vectors. + let mut fs = FrameState::new_with_frame_and_me_stats_and_rec(Arc::clone(&frame), buffer); + let mut tiling = TilingInfo::from_target_tiles( + frame.planes[0].cfg.width, + frame.planes[0].cfg.height, + *frame_rate.numer() as f64 / *frame_rate.denom() as f64, + TilingInfo::tile_log2(1, 0).unwrap(), + TilingInfo::tile_log2(1, 0).unwrap(), + chroma_sampling == ChromaSampling::Cs422, + ); + compute_motion_vectors(&fi, &mut fs, &mut tiling, bit_depth, cpu_feature_level); + + // Estimate inter costs + let plane_org = &frame.planes[0]; + let plane_ref = &ref_frame.planes[0]; + let h_in_imp_b = plane_org.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane_org.cfg.width / IMPORTANCE_BLOCK_SIZE; + let stats = &fs.frame_me_stats.read().expect("poisoned lock")[0]; + let bsize = BlockSize::from_width_and_height(IMPORTANCE_BLOCK_SIZE, IMPORTANCE_BLOCK_SIZE); + + let mut inter_costs = 0; + (0..h_in_imp_b).for_each(|y| { + (0..w_in_imp_b).for_each(|x| { + let mv = stats[y * 2][x * 2].mv; + + // Coordinates of the top-left corner of the reference block, in MV + // units. + let reference_x = x as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.col as i64; + let reference_y = y as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.row as i64; + + let region_org = plane_org.region(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + let region_ref = plane_ref.region(Area::Rect(Rect { + x: reference_x as isize / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + y: reference_y as isize / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + inter_costs += get_satd( + ®ion_org, + ®ion_ref, + bsize.width(), + bsize.height(), + bit_depth, + cpu_feature_level, + ) as u64; + }); + }); + inter_costs as f64 / (w_in_imp_b * h_in_imp_b) as f64 +} + +fn compute_motion_vectors( + fi: &FrameInvariants, + fs: &mut FrameState, + tiling_info: &mut TilingInfo, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) { + tiling_info + .tile_iter_mut(fs) + .collect::>() + .into_par_iter() + .for_each(|mut ctx| { + let ts = &mut ctx.ts; + estimate_tile_motion(fi, ts, bit_depth, cpu_feature_level); + }); +} + +fn estimate_tile_motion( + fi: &FrameInvariants, + ts: &mut TileStateMut<'_, T>, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) { + let init_size = MIB_SIZE_LOG2; + + let mut prev_ssdec: Option = None; + for mv_size_in_b_log2 in (2..=init_size).rev() { + let init = mv_size_in_b_log2 == init_size; + + // Choose subsampling. Pass one is quarter res and pass two is at half res. + let ssdec = match init_size - mv_size_in_b_log2 { + 0 => 2, + 1 => 1, + _ => 0, + }; + + let new_subsampling = if let Some(prev) = prev_ssdec { + prev != ssdec + } else { + false + }; + prev_ssdec = Some(ssdec); + + // 0.5 and 0.125 are a fudge factors + let lambda = 0; + + for sby in 0..ts.sb_height { + for sbx in 0..ts.sb_width { + let mut tested_frames_flags = 0; + for &ref_frame in ALLOWED_REF_FRAMES { + let frame_flag = 1 << fi.ref_frames[ref_frame.to_index()]; + if tested_frames_flags & frame_flag == frame_flag { + continue; + } + tested_frames_flags |= frame_flag; + + let tile_bo = TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby }) + .block_offset(0, 0); + + if new_subsampling { + refine_subsampled_sb_motion( + fi, + ts, + ref_frame, + mv_size_in_b_log2 + 1, + tile_bo, + ssdec, + lambda, + bit_depth, + cpu_feature_level, + ); + } + + estimate_sb_motion( + fi, + ts, + ref_frame, + mv_size_in_b_log2, + tile_bo, + init, + ssdec, + lambda, + bit_depth, + cpu_feature_level, + ); + } + } + } + } +} + +#[allow(clippy::too_many_arguments)] +fn refine_subsampled_sb_motion( + fi: &FrameInvariants, + ts: &mut TileStateMut<'_, T>, + ref_frame: RefType, + mv_size_in_b_log2: usize, + tile_bo: TileBlockOffset, + ssdec: u8, + lambda: u32, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) { + let pix_offset = tile_bo.to_luma_plane_offset(); + let sb_h: usize = SB_SIZE.min(ts.height - pix_offset.y as usize); + let sb_w: usize = SB_SIZE.min(ts.width - pix_offset.x as usize); + + let mv_size = MI_SIZE << mv_size_in_b_log2; + + // Process in blocks, cropping at edges. + for y in (0..sb_h).step_by(mv_size) { + for x in (0..sb_w).step_by(mv_size) { + let sub_bo = + tile_bo.with_offset(x as isize >> MI_SIZE_LOG2, y as isize >> MI_SIZE_LOG2); + + // Clamp to frame edge, rounding up in the case of subsampling. + // The rounding makes some assumptions about how subsampling is done. + let w = mv_size.min(sb_w - x + (1 << ssdec) - 1) >> ssdec; + let h = mv_size.min(sb_h - y + (1 << ssdec) - 1) >> ssdec; + + // Refine the existing motion estimate + if let Some(results) = refine_subsampled_motion_estimate( + fi, + ts, + w, + h, + sub_bo, + ref_frame, + ssdec, + lambda, + bit_depth, + cpu_feature_level, + ) { + // normalize sad to 128x128 block + let sad = + (((results.rd.sad as u64) << (MAX_SB_SIZE_LOG2 * 2)) / (w * h) as u64) as u32; + save_me_stats(ts, mv_size_in_b_log2, sub_bo, ref_frame, MEStats { + mv: results.mv, + normalized_sad: sad, + }); + } + } + } +} + +/// Refine motion estimation that was computed one level of subsampling up. +#[allow(clippy::too_many_arguments)] +fn refine_subsampled_motion_estimate( + fi: &FrameInvariants, + ts: &TileStateMut<'_, T>, + w: usize, + h: usize, + tile_bo: TileBlockOffset, + ref_frame: RefType, + ssdec: u8, + lambda: u32, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> Option { + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] { + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + get_mv_range(fi.w_in_b, fi.h_in_b, frame_bo, w << ssdec, h << ssdec); + + let pmv = [MotionVector { row: 0, col: 0 }; 2]; + + let po = frame_bo.to_luma_plane_offset(); + let (mvx_min, mvx_max, mvy_min, mvy_max) = ( + mvx_min >> ssdec, + mvx_max >> ssdec, + mvy_min >> ssdec, + mvy_max >> ssdec, + ); + let po = PlaneOffset { + x: po.x >> ssdec, + y: po.y >> ssdec, + }; + let p_ref = match ssdec { + 0 => &rec.frame.planes[0], + 1 => &rec.input_hres, + 2 => &rec.input_qres, + _ => unimplemented!(), + }; + + let org_region = &match ssdec { + 0 => ts.input_tile.planes[0].subregion(Area::BlockStartingAt { bo: tile_bo.0 }), + 1 => ts.input_hres.region(Area::StartingAt { x: po.x, y: po.y }), + 2 => ts.input_qres.region(Area::StartingAt { x: po.x, y: po.y }), + _ => unimplemented!(), + }; + + let mv = ts.me_stats[ref_frame.to_index()][tile_bo.0.y][tile_bo.0.x].mv >> ssdec; + + // Given a motion vector at 0 at higher subsampling: + // | -1 | 0 | 1 | + // then the vectors at -1 to 2 should be tested at the current subsampling. + // |-------------| + // | -2 -1 | 0 1 | 2 3 | + // This corresponds to a 4x4 full search. + let x_lo = po.x + (mv.col as isize / 8 - 1).max(mvx_min / 8); + let x_hi = po.x + (mv.col as isize / 8 + 2).min(mvx_max / 8); + let y_lo = po.y + (mv.row as isize / 8 - 1).max(mvy_min / 8); + let y_hi = po.y + (mv.row as isize / 8 + 2).min(mvy_max / 8); + let mut results = full_search( + x_lo, + x_hi, + y_lo, + y_hi, + w, + h, + org_region, + p_ref, + po, + 1, + lambda, + pmv, + bit_depth, + cpu_feature_level, + ); + + // Scale motion vectors to full res size + results.mv = results.mv << ssdec; + + Some(results) + } else { + None + } +} + +fn get_mv_range( + w_in_b: usize, + h_in_b: usize, + bo: PlaneBlockOffset, + blk_w: usize, + blk_h: usize, +) -> (isize, isize, isize, isize) { + let border_w = 128 + blk_w as isize * 8; + let border_h = 128 + blk_h as isize * 8; + let mvx_min = -(bo.0.x as isize) * (8 * MI_SIZE) as isize - border_w; + let mvx_max = ((w_in_b - bo.0.x) as isize - (blk_w / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_w; + let mvy_min = -(bo.0.y as isize) * (8 * MI_SIZE) as isize - border_h; + let mvy_max = ((h_in_b - bo.0.y) as isize - (blk_h / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_h; + + // + ( + mvx_min.max(MV_LOW as isize + 1), + mvx_max.min(MV_UPP as isize - 1), + mvy_min.max(MV_LOW as isize + 1), + mvy_max.min(MV_UPP as isize - 1), + ) +} + +#[allow(clippy::too_many_arguments)] +fn full_search( + x_lo: isize, + x_hi: isize, + y_lo: isize, + y_hi: isize, + w: usize, + h: usize, + org_region: &PlaneRegion, + p_ref: &Plane, + po: PlaneOffset, + step: usize, + lambda: u32, + pmv: [MotionVector; 2], + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> MotionSearchResult { + let search_region = p_ref.region(Area::Rect(Rect { + x: x_lo, + y: y_lo, + width: (x_hi - x_lo) as usize + w, + height: (y_hi - y_lo) as usize + h, + })); + + let mut best: MotionSearchResult = MotionSearchResult::empty(); + + // Select rectangular regions within search region with vert+horz windows + for vert_window in search_region.vert_windows(h).step_by(step) { + for ref_window in vert_window.horz_windows(w).step_by(step) { + let &Rect { x, y, .. } = ref_window.rect(); + + let mv = MotionVector { + row: 8 * (y as i16 - po.y as i16), + col: 8 * (x as i16 - po.x as i16), + }; + + let rd = compute_mv_rd( + pmv, + lambda, + false, + bit_depth, + w, + h, + mv, + org_region, + &ref_window, + cpu_feature_level, + ); + + if rd.cost < best.rd.cost { + best.rd = rd; + best.mv = mv; + } + } + } + + best +} + +/// Compute the rate distortion stats for a motion vector. +#[allow(clippy::too_many_arguments)] +fn compute_mv_rd( + pmv: [MotionVector; 2], + lambda: u32, + use_satd: bool, + bit_depth: usize, + w: usize, + h: usize, + cand_mv: MotionVector, + plane_org: &PlaneRegion<'_, T>, + plane_ref: &PlaneRegion<'_, T>, + cpu_feature_level: CpuFeatureLevel, +) -> MVCandidateRD { + let sad = if use_satd { + get_satd(plane_org, plane_ref, w, h, bit_depth, cpu_feature_level) + } else { + get_sad(plane_org, plane_ref, w, h, bit_depth, cpu_feature_level) + }; + + let rate1 = get_mv_rate(cand_mv, pmv[0]); + let rate2 = get_mv_rate(cand_mv, pmv[1]); + let rate = rate1.min(rate2 + 1); + + MVCandidateRD { + cost: 256 * sad as u64 + rate as u64 * lambda as u64, + sad, + } +} + +fn diff_to_rate(diff: i16) -> u32 { + let d = diff >> 1; + 2 * ILog::ilog(d.abs()) as u32 +} + +fn get_mv_rate(a: MotionVector, b: MotionVector) -> u32 { + diff_to_rate(a.row - b.row) + diff_to_rate(a.col - b.col) +} + +/// Result of motion search. +#[derive(Debug, Copy, Clone)] +pub struct MotionSearchResult { + /// Motion vector chosen by the motion search. + pub mv: MotionVector, + /// Rate distortion data associated with `mv`. + pub rd: MVCandidateRD, +} + +impl MotionSearchResult { + /// Creates an 'empty' value. + /// + /// To be considered empty, cost is set higher than any naturally occurring + /// cost value. The idea is that comparing to any valid rd output, the + /// search result will always be replaced. + pub fn empty() -> MotionSearchResult { + MotionSearchResult { + mv: MotionVector::default(), + rd: MVCandidateRD::empty(), + } + } + + /// Check if the value should be considered to be empty. + const fn is_empty(&self) -> bool { + self.rd.cost == u64::MAX + } +} + +/// Holds data from computing rate distortion of a motion vector. +#[derive(Debug, Copy, Clone)] +pub struct MVCandidateRD { + /// Rate distortion cost of the motion vector. + pub cost: u64, + /// Distortion metric value for the motion vector. + pub sad: u32, +} + +impl MVCandidateRD { + /// Creates an 'empty' value. + /// + /// To be considered empty, cost is set higher than any naturally occurring + /// cost value. The idea is that comparing to any valid rd output, the + /// search result will always be replaced. + const fn empty() -> MVCandidateRD { + MVCandidateRD { + sad: u32::MAX, + cost: u64::MAX, + } + } +} + +fn save_me_stats( + ts: &mut TileStateMut<'_, T>, + mv_size_in_b_log2: usize, + tile_bo: TileBlockOffset, + ref_frame: RefType, + stats: MEStats, +) { + let size_in_b = 1 << mv_size_in_b_log2; + let tile_me_stats = &mut ts.me_stats[ref_frame.to_index()]; + let tile_bo_x_end = (tile_bo.0.x + size_in_b).min(ts.mi_width); + let tile_bo_y_end = (tile_bo.0.y + size_in_b).min(ts.mi_height); + for mi_y in tile_bo.0.y..tile_bo_y_end { + for a in tile_me_stats[mi_y][tile_bo.0.x..tile_bo_x_end].iter_mut() { + *a = stats; + } + } +} + +#[allow(clippy::too_many_arguments)] +fn estimate_sb_motion( + fi: &FrameInvariants, + ts: &mut TileStateMut<'_, T>, + ref_frame: RefType, + mv_size_in_b_log2: usize, + tile_bo: TileBlockOffset, + init: bool, + ssdec: u8, + lambda: u32, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) { + let pix_offset = tile_bo.to_luma_plane_offset(); + let sb_h: usize = SB_SIZE.min(ts.height - pix_offset.y as usize); + let sb_w: usize = SB_SIZE.min(ts.width - pix_offset.x as usize); + + let mv_size = MI_SIZE << mv_size_in_b_log2; + + // Process in blocks, cropping at edges. + for y in (0..sb_h).step_by(mv_size) { + for x in (0..sb_w).step_by(mv_size) { + let corner: MVSamplingMode = if init { + MVSamplingMode::INIT + } else { + // Processing the block a size up produces data that can be used by + // the right and bottom corners. + MVSamplingMode::CORNER { + right: x & mv_size == mv_size, + bottom: y & mv_size == mv_size, + } + }; + + let sub_bo = + tile_bo.with_offset(x as isize >> MI_SIZE_LOG2, y as isize >> MI_SIZE_LOG2); + + // Clamp to frame edge, rounding up in the case of subsampling. + // The rounding makes some assumptions about how subsampling is done. + let w = mv_size.min(sb_w - x + (1 << ssdec) - 1) >> ssdec; + let h = mv_size.min(sb_h - y + (1 << ssdec) - 1) >> ssdec; + + // Run motion estimation. + // Note that the initial search (init) instructs the called function to + // perform a more extensive search. + if let Some(results) = estimate_motion( + fi, + ts, + w, + h, + sub_bo, + ref_frame, + None, + corner, + init, + ssdec, + Some(lambda), + bit_depth, + cpu_feature_level, + ) { + // normalize sad to 128x128 block + let sad = + (((results.rd.sad as u64) << (MAX_SB_SIZE_LOG2 * 2)) / (w * h) as u64) as u32; + save_me_stats(ts, mv_size_in_b_log2, sub_bo, ref_frame, MEStats { + mv: results.mv, + normalized_sad: sad, + }); + } + } + } +} + +#[allow(clippy::too_many_arguments)] +fn estimate_motion( + fi: &FrameInvariants, + ts: &TileStateMut<'_, T>, + w: usize, + h: usize, + tile_bo: TileBlockOffset, + ref_frame: RefType, + pmv: Option<[MotionVector; 2]>, + corner: MVSamplingMode, + extensive_search: bool, + ssdec: u8, + lambda: Option, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> Option { + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] { + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + get_mv_range(fi.w_in_b, fi.h_in_b, frame_bo, w << ssdec, h << ssdec); + + let lambda = lambda.unwrap_or(0); + + let global_mv = [MotionVector { row: 0, col: 0 }; 2]; + + let po = frame_bo.to_luma_plane_offset(); + let (mvx_min, mvx_max, mvy_min, mvy_max) = ( + mvx_min >> ssdec, + mvx_max >> ssdec, + mvy_min >> ssdec, + mvy_max >> ssdec, + ); + let po = PlaneOffset { + x: po.x >> ssdec, + y: po.y >> ssdec, + }; + let p_ref = match ssdec { + 0 => &rec.frame.planes[0], + 1 => &rec.input_hres, + 2 => &rec.input_qres, + _ => unimplemented!(), + }; + + let org_region = &match ssdec { + 0 => ts.input_tile.planes[0].subregion(Area::BlockStartingAt { bo: tile_bo.0 }), + 1 => ts.input_hres.region(Area::StartingAt { x: po.x, y: po.y }), + 2 => ts.input_qres.region(Area::StartingAt { x: po.x, y: po.y }), + _ => unimplemented!(), + }; + + let mut best: MotionSearchResult = full_pixel_me( + fi, + ts, + org_region, + p_ref, + tile_bo, + po, + lambda, + pmv.unwrap_or(global_mv), + w, + h, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + ref_frame, + corner, + extensive_search, + ssdec, + bit_depth, + cpu_feature_level, + ); + + if let Some(pmv) = pmv { + best.rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + true, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + best.mv, + cpu_feature_level, + ); + + sub_pixel_me( + fi, + po, + org_region, + p_ref, + lambda, + pmv, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + true, + &mut best, + ref_frame, + bit_depth, + cpu_feature_level, + ); + } + + // Scale motion vectors to full res size + best.mv = best.mv << ssdec; + + Some(best) + } else { + None + } +} + +#[allow(clippy::too_many_arguments)] +fn full_pixel_me( + fi: &FrameInvariants, + ts: &TileStateMut<'_, T>, + org_region: &PlaneRegion, + p_ref: &Plane, + tile_bo: TileBlockOffset, + po: PlaneOffset, + lambda: u32, + pmv: [MotionVector; 2], + w: usize, + h: usize, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + ref_frame: RefType, + corner: MVSamplingMode, + extensive_search: bool, + ssdec: u8, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> MotionSearchResult { + let ref_frame_id = ref_frame.to_index(); + let tile_me_stats = &ts.me_stats[ref_frame_id].as_const(); + let frame_ref = fi.rec_buffer.frames[fi.ref_frames[0] as usize] + .as_ref() + .map(|frame_ref| frame_ref.frame_me_stats.read().expect("poisoned lock")); + let subsets = get_subset_predictors( + tile_bo, + tile_me_stats, + frame_ref, + ref_frame_id, + w, + h, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + corner, + ssdec, + ); + + let try_cands = |predictors: &[MotionVector], best: &mut MotionSearchResult| { + let mut results = get_best_predictor( + po, + org_region, + p_ref, + predictors, + bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cpu_feature_level, + ); + fullpel_diamond_search( + po, + org_region, + p_ref, + &mut results, + bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cpu_feature_level, + ); + + if results.rd.cost < best.rd.cost { + *best = results; + } + }; + + let mut best: MotionSearchResult = MotionSearchResult::empty(); + if !extensive_search { + try_cands(&subsets.all_mvs(), &mut best); + best + } else { + // Perform a more thorough search before resorting to full search. + // Search the median, the best mvs of neighboring blocks, and motion vectors + // from the previous frame. Stop once a candidate with a sad less than a + // threshold is found. + + let thresh = (subsets.min_sad as f32 * 1.2) as u32 + (((w * h) as u32) << (bit_depth - 8)); + + if let Some(median) = subsets.median { + try_cands(&[median], &mut best); + + if best.rd.sad < thresh { + return best; + } + } + + try_cands(&subsets.subset_b, &mut best); + + if best.rd.sad < thresh { + return best; + } + + try_cands(&subsets.subset_c, &mut best); + + if best.rd.sad < thresh { + return best; + } + + // Preform UMH search, either as the last possible search when full search + // is disabled, or as the last search before resorting to full search. + // Use 24 merange, since it is the largest range that x264 uses. + uneven_multi_hex_search( + po, + org_region, + p_ref, + &mut best, + bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + 24, + cpu_feature_level, + ); + + best + } +} + +#[allow(clippy::too_many_arguments)] +fn sub_pixel_me( + fi: &FrameInvariants, + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + lambda: u32, + pmv: [MotionVector; 2], + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + use_satd: bool, + best: &mut MotionSearchResult, + ref_frame: RefType, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) { + subpel_diamond_search( + fi, + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + use_satd, + best, + ref_frame, + cpu_feature_level, + ); +} + +/// Run a subpixel diamond search. The search is run on multiple step sizes. +/// +/// For each step size, candidate motion vectors are examined for improvement +/// to the current search location. The search location is moved to the best +/// candidate (if any). This is repeated until the search location stops moving. +#[allow(clippy::too_many_arguments)] +fn subpel_diamond_search( + fi: &FrameInvariants, + po: PlaneOffset, + org_region: &PlaneRegion, + _p_ref: &Plane, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + use_satd: bool, + current: &mut MotionSearchResult, + ref_frame: RefType, + cpu_feature_level: CpuFeatureLevel, +) { + // Motion compensation assembly has special requirements for edges + let mc_w = w.next_power_of_two(); + let mc_h = (h + 1) & !1; + + // Metadata for subpel scratch pad. + let cfg = PlaneConfig::new(mc_w, mc_h, 0, 0, 0, 0, std::mem::size_of::()); + // Stack allocation for subpel scratch pad. + // SAFETY: We write to the array below before reading from it. + let mut buf: Aligned = Aligned([T::cast_from(0); 128 * 128]); + let mut tmp_region = PlaneRegionMut::from_slice(buf.as_mut(), &cfg, Rect { + x: 0, + y: 0, + width: cfg.width, + height: cfg.height, + }); + + // start at 1/2 pel and end at 1/4 or 1/8 pel + let (mut diamond_radius_log2, diamond_radius_end_log2) = (2u8, 1u8); + + loop { + // Find the best candidate from the diamond pattern. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &DIAMOND_R1_PATTERN_SUBPEL { + let cand_mv = current.mv + (offset << diamond_radius_log2); + + let rd = get_subpel_mv_rd( + fi, + po, + org_region, + bit_depth, + pmv, + lambda, + use_satd, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + &mut tmp_region, + ref_frame, + cpu_feature_level, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Continue the search at this scale until a better candidate isn't found. + if current.rd.cost <= best_cand.rd.cost { + if diamond_radius_log2 == diamond_radius_end_log2 { + break; + } else { + diamond_radius_log2 -= 1; + } + } else { + *current = best_cand; + } + } + + assert!(!current.is_empty()); +} + +#[allow(clippy::too_many_arguments)] +fn get_subpel_mv_rd( + fi: &FrameInvariants, + po: PlaneOffset, + org_region: &PlaneRegion, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + use_satd: bool, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + cand_mv: MotionVector, + tmp_region: &mut PlaneRegionMut, + ref_frame: RefType, + cpu_feature_level: CpuFeatureLevel, +) -> MVCandidateRD { + if (cand_mv.col as isize) < mvx_min + || (cand_mv.col as isize) > mvx_max + || (cand_mv.row as isize) < mvy_min + || (cand_mv.row as isize) > mvy_max + { + return MVCandidateRD::empty(); + } + + let tmp_width = tmp_region.rect().width; + let tmp_height = tmp_region.rect().height; + let tile_rect = TileRect { + x: 0, + y: 0, + width: tmp_width, + height: tmp_height, + }; + + PredictionMode::NEWMV.predict_inter_single( + fi, + tile_rect, + 0, + po, + tmp_region, + // motion comp's w & h on edges can be different from distortion's + tmp_width, + tmp_height, + ref_frame, + cand_mv, + bit_depth, + cpu_feature_level, + ); + let plane_ref = tmp_region.as_const(); + compute_mv_rd( + pmv, + lambda, + use_satd, + bit_depth, + w, + h, + cand_mv, + org_region, + &plane_ref, + cpu_feature_level, + ) +} + +/// Perform an uneven multi-hexagon search. There are 4 stages: +/// 1. Unsymmetrical-cross search: Search the horizontal and vertical directions +/// for the general direction of the motion. +/// 2. A 5x5 full search is done to refine the current candidate. +/// 3. Uneven multi-hexagon search. See [`UMH_PATTERN`]. +/// 4. Refinement using standard hexagon search. +/// +/// `current` provides the initial search location and serves as +/// the output for the final search results. +/// +/// `me_range` parameter determines how far these stages can search. +#[allow(clippy::too_many_arguments)] +fn uneven_multi_hex_search( + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + current: &mut MotionSearchResult, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + me_range: i16, + cpu_feature_level: CpuFeatureLevel, +) { + assert!(!current.is_empty()); + + // Search in a cross pattern to obtain a rough approximate of motion. + // The cross is split into a horizontal and vertical component. Video content + // tends to have more horizontal motion, so the horizontal part of the cross + // is twice as large as the vertical half. + // X - + // | <- me_range/2 + // X | + // X X X XoX X X X - + // X + // + // X + // |------| + // \ + // me_range + let center = current.mv; + + // The larger, horizontal, part of the cross search. + for i in (1..=me_range).step_by(2) { + const HORIZONTAL_LINE: [MotionVector; 2] = search_pattern!( + col: [ 0, 0], + row: [-1, 1] + ); + + for &offset in &HORIZONTAL_LINE { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // The smaller, vertical, part of the cross search + for i in (1..=me_range >> 1).step_by(2) { + const VERTICAL_LINE: [MotionVector; 2] = search_pattern!( + col: [-1, 1], + row: [ 0, 0] + ); + + for &offset in &VERTICAL_LINE { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // 5x5 full search. Search a 5x5 square region around the current best mv. + let center = current.mv; + for row in -2..=2 { + for col in -2..=2 { + if row == 0 && col == 0 { + continue; + } + let cand_mv = center + MotionVector { row, col }; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // Run the hexagons in uneven multi-hexagon. The hexagonal pattern is tested + // around the best vector at multiple scales. + // Example of the UMH pattern run on a scale of 1 and 2: + // 2 - + // | <- me_range + // 2 2 | + // | + // 2 1 2 | + // 1 1 | + // 2 1 1 2 | + // 1 1 | + // 2 1 o 1 2 | + // 1 1 | + // 2 1 1 2 | + // 1 1 | + // 2 1 2 | + // | + // 2 2 | + // | + // 2 - + // |---------------| + // \ + // me_range + let center = current.mv; + + // Divide by 4, the radius of the UMH's hexagon. + let iterations = me_range >> 2; + for i in 1..=iterations { + for &offset in &UMH_PATTERN { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // Refine the search results using a 'normal' hexagon search. + hexagon_search( + po, + org_region, + p_ref, + current, + bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cpu_feature_level, + ); +} + +#[allow(clippy::too_many_arguments)] +fn get_subset_predictors( + tile_bo: TileBlockOffset, + tile_me_stats: &TileMEStats<'_>, + frame_ref_opt: Option>, + ref_frame_id: usize, + pix_w: usize, + pix_h: usize, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + corner: MVSamplingMode, + ssdec: u8, +) -> MotionEstimationSubsets { + let mut min_sad: u32 = u32::MAX; + let mut subset_b = ArrayVec::::new(); + let mut subset_c = ArrayVec::::new(); + + // rounded up width in blocks + let w = ((pix_w << ssdec) + MI_SIZE - 1) >> MI_SIZE_LOG2; + let h = ((pix_h << ssdec) + MI_SIZE - 1) >> MI_SIZE_LOG2; + + // Get predictors from the same frame. + + let clipped_half_w = (w >> 1).min(tile_me_stats.cols() - 1 - tile_bo.0.x); + let clipped_half_h = (h >> 1).min(tile_me_stats.rows() - 1 - tile_bo.0.y); + + let mut process_cand = |stats: MEStats| -> MotionVector { + min_sad = min_sad.min(stats.normalized_sad); + let mv = stats.mv.quantize_to_fullpel(); + MotionVector { + col: clamp(mv.col as isize, mvx_min, mvx_max) as i16, + row: clamp(mv.row as isize, mvy_min, mvy_max) as i16, + } + }; + + // Sample the middle of all block edges bordering this one. + // Note: If motion vectors haven't been precomputed to a given blocksize, then + // the right and bottom edges will be duplicates of the center predictor when + // processing in raster order. + + // left + if tile_bo.0.x > 0 { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h][tile_bo.0.x - 1], + )); + } + // top + if tile_bo.0.y > 0 { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y - 1][tile_bo.0.x + clipped_half_w], + )); + } + + // Sampling far right and far bottom edges was tested, but had worse results + // without an extensive threshold test (with threshold being applied after + // checking median and the best of each subset). + + // right + if let MVSamplingMode::CORNER { + right: true, + bottom: _, + } = corner + { + if tile_bo.0.x + w < tile_me_stats.cols() { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h][tile_bo.0.x + w], + )); + } + } + // bottom + if let MVSamplingMode::CORNER { + right: _, + bottom: true, + } = corner + { + if tile_bo.0.y + h < tile_me_stats.rows() { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + h][tile_bo.0.x + clipped_half_w], + )); + } + } + + let median = if corner != MVSamplingMode::INIT { + // Sample the center of the current block. + Some(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h][tile_bo.0.x + clipped_half_w], + )) + } else if subset_b.len() != 3 { + None + } else { + let mut rows: ArrayVec = subset_b.iter().map(|&a| a.row).collect(); + let mut cols: ArrayVec = subset_b.iter().map(|&a| a.col).collect(); + rows.as_mut_slice().sort_unstable(); + cols.as_mut_slice().sort_unstable(); + Some(MotionVector { + row: rows[1], + col: cols[1], + }) + }; + + // Zero motion vector, don't use add_cand since it skips zero vectors. + subset_b.push(MotionVector::default()); + + // EPZS subset C predictors. + // Sample the middle of bordering side of the left, right, top and bottom + // blocks of the previous frame. + // Sample the middle of this block in the previous frame. + + if let Some(frame_me_stats) = frame_ref_opt { + let prev_frame = &frame_me_stats[ref_frame_id]; + + let frame_bo = PlaneBlockOffset(BlockOffset { + x: tile_me_stats.x() + tile_bo.0.x, + y: tile_me_stats.y() + tile_bo.0.y, + }); + let clipped_half_w = (w >> 1).min(prev_frame.cols - 1 - frame_bo.0.x); + let clipped_half_h = (h >> 1).min(prev_frame.rows - 1 - frame_bo.0.y); + + // left + if frame_bo.0.x > 0 { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x - 1], + )); + } + // top + if frame_bo.0.y > 0 { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y - 1][frame_bo.0.x + clipped_half_w], + )); + } + // right + if frame_bo.0.x + w < prev_frame.cols { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x + w], + )); + } + // bottom + if frame_bo.0.y + h < prev_frame.rows { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + h][frame_bo.0.x + clipped_half_w], + )); + } + + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x + clipped_half_w], + )); + } + + // Undo normalization to 128x128 block size + let min_sad = ((min_sad as u64 * (pix_w * pix_h) as u64) >> (MAX_SB_SIZE_LOG2 * 2)) as u32; + + let dec_mv = |mv: MotionVector| MotionVector { + col: mv.col >> ssdec, + row: mv.row >> ssdec, + }; + let median = median.map(dec_mv); + for mv in subset_b.iter_mut() { + *mv = dec_mv(*mv); + } + for mv in subset_c.iter_mut() { + *mv = dec_mv(*mv); + } + + MotionEstimationSubsets { + min_sad, + median, + subset_b, + subset_c, + } +} + +#[allow(clippy::too_many_arguments)] +fn get_best_predictor( + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + predictors: &[MotionVector], + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + cpu_feature_level: CpuFeatureLevel, +) -> MotionSearchResult { + let mut best: MotionSearchResult = MotionSearchResult::empty(); + + for &init_mv in predictors.iter() { + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + init_mv, + cpu_feature_level, + ); + + if rd.cost < best.rd.cost { + best.mv = init_mv; + best.rd = rd; + } + } + + best +} + +#[allow(clippy::too_many_arguments)] +fn get_fullpel_mv_rd( + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + use_satd: bool, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + cand_mv: MotionVector, + cpu_feature_level: CpuFeatureLevel, +) -> MVCandidateRD { + if (cand_mv.col as isize) < mvx_min + || (cand_mv.col as isize) > mvx_max + || (cand_mv.row as isize) < mvy_min + || (cand_mv.row as isize) > mvy_max + { + return MVCandidateRD::empty(); + } + + // Convert the motion vector into an full pixel offset. + let plane_ref = p_ref.region(Area::StartingAt { + x: po.x + (cand_mv.col / 8) as isize, + y: po.y + (cand_mv.row / 8) as isize, + }); + compute_mv_rd( + pmv, + lambda, + use_satd, + bit_depth, + w, + h, + cand_mv, + org_region, + &plane_ref, + cpu_feature_level, + ) +} + +/// Perform hexagon search and refine afterwards. +/// +/// In the hexagon search stage, candidate motion vectors are examined for +/// improvement to the current search location. The search location is moved to +/// the best candidate (if any). This is repeated until the search location +/// stops moving. +/// +/// Refinement uses a square pattern that fits between the hexagon candidates. +/// +/// The hexagon pattern is defined by [`HEXAGON_PATTERN`] and the refinement +/// is defined by [`SQUARE_REFINE_PATTERN`]. +/// +/// `current` provides the initial search location and serves as +/// the output for the final search results. +#[allow(clippy::too_many_arguments)] +fn hexagon_search( + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + current: &mut MotionSearchResult, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + cpu_feature_level: CpuFeatureLevel, +) { + // The first iteration of hexagon search is implemented separate from + // subsequent iterations, which overlap with previous iterations. + + // Holds what candidate is used (if any). This is used to determine which + // candidates have already been tested in a previous iteration and can be + // skipped. + let mut best_cand_idx: usize = 0; + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + + // First iteration of hexagon search. There are six candidates to consider. + for (i, &pattern_mv) in HEXAGON_PATTERN.iter().enumerate() { + let cand_mv = current.mv + pattern_mv; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < best_cand.rd.cost { + best_cand_idx = i; + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Run additional iterations of hexagon search until the search location + // doesn't update. + while best_cand.rd.cost < current.rd.cost { + // Update the search location. + *current = best_cand; + best_cand = MotionSearchResult::empty(); + + // Save the index/direction taken in the previous iteration to the current + // search location. + let center_cand_idx = best_cand_idx; + + // Look only at candidates that don't overlap with previous iterations. This + // corresponds with the three offsets (2D) with the closest direction to + // that traveled by the previous iteration. HEXAGON_PATTERN has clockwise + // order, so the last direction -1, +0, and +1 (mod 6) give the indices for + // these offsets. + for idx_offset_mod6 in 5..=7 { + let i = (center_cand_idx + idx_offset_mod6) % 6; + let cand_mv = current.mv + HEXAGON_PATTERN[i]; + + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < best_cand.rd.cost { + best_cand_idx = i; + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + } + + // Refine the motion after completing hexagon search. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &SQUARE_REFINE_PATTERN { + let cand_mv = current.mv + offset; + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + if best_cand.rd.cost < current.rd.cost { + *current = best_cand; + } + + assert!(!current.is_empty()); +} + +/// Run a full pixel diamond search. The search is run on multiple step sizes. +/// +/// For each step size, candidate motion vectors are examined for improvement +/// to the current search location. The search location is moved to the best +/// candidate (if any). This is repeated until the search location stops moving. +#[allow(clippy::too_many_arguments)] +fn fullpel_diamond_search( + po: PlaneOffset, + org_region: &PlaneRegion, + p_ref: &Plane, + current: &mut MotionSearchResult, + bit_depth: usize, + pmv: [MotionVector; 2], + lambda: u32, + mvx_min: isize, + mvx_max: isize, + mvy_min: isize, + mvy_max: isize, + w: usize, + h: usize, + cpu_feature_level: CpuFeatureLevel, +) { + // Define the initial and the final scale (log2) of the diamond. + let (mut diamond_radius_log2, diamond_radius_end_log2) = (1u8, 0u8); + + loop { + // Find the best candidate from the diamond pattern. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &DIAMOND_R1_PATTERN { + let cand_mv = current.mv + (offset << diamond_radius_log2); + let rd = get_fullpel_mv_rd( + po, + org_region, + p_ref, + bit_depth, + pmv, + lambda, + false, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + cpu_feature_level, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Continue the search at this scale until the can't find a better candidate + // to use. + if current.rd.cost <= best_cand.rd.cost { + if diamond_radius_log2 == diamond_radius_end_log2 { + break; + } else { + diamond_radius_log2 -= 1; + } + } else { + *current = best_cand; + } + } + + assert!(!current.is_empty()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra/simd_x86.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra/simd_x86.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra/simd_x86.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra/simd_x86.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,134 @@ +use v_frame::pixel::{Pixel, PixelType}; + +use super::IntraEdge; +use crate::{ + cpu::CpuFeatureLevel, + data::{block::TxSize, plane::PlaneRegionMut, prediction::PredictionVariant}, +}; + +macro_rules! decl_angular_ipred_fn { + ($($f:ident),+) => { + extern "C" { + $( + fn $f( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + ); + )* + } + }; + } + +decl_angular_ipred_fn! { + avsc_ipred_dc_8bpc_ssse3, + avsc_ipred_dc_8bpc_avx2, + avsc_ipred_dc_8bpc_avx512icl, + avsc_ipred_dc_left_8bpc_ssse3, + avsc_ipred_dc_left_8bpc_avx2, + avsc_ipred_dc_left_8bpc_avx512icl, + avsc_ipred_dc_128_8bpc_ssse3, + avsc_ipred_dc_128_8bpc_avx2, + avsc_ipred_dc_128_8bpc_avx512icl, + avsc_ipred_dc_top_8bpc_ssse3, + avsc_ipred_dc_top_8bpc_avx2, + avsc_ipred_dc_top_8bpc_avx512icl +} + +macro_rules! decl_angular_ipred_hbd_fn { + ($($f:ident),+) => { + extern "C" { + $( + fn $f( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + max_width: libc::c_int, max_height: libc::c_int, + bit_depth_max: libc::c_int, + ); + )* + } + }; + } + +decl_angular_ipred_hbd_fn! { + avsc_ipred_dc_16bpc_ssse3, + avsc_ipred_dc_16bpc_avx2, + avsc_ipred_dc_left_16bpc_ssse3, + avsc_ipred_dc_left_16bpc_avx2, + avsc_ipred_dc_128_16bpc_ssse3, + avsc_ipred_dc_128_16bpc_avx2, + avsc_ipred_dc_top_16bpc_ssse3, + avsc_ipred_dc_top_16bpc_avx2 +} + +pub(super) fn dispatch_predict_dc_intra( + variant: PredictionVariant, + dst: &mut PlaneRegionMut<'_, T>, + tx_size: TxSize, + bit_depth: usize, + edge_buf: &IntraEdge, + cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + super::rust::dispatch_predict_dc_intra(variant, dst, tx_size, bit_depth, edge_buf, cpu); + }; + + // SAFETY: Calls Assembly code. + unsafe { + let stride = T::to_asm_stride(dst.plane_cfg.stride) as libc::ptrdiff_t; + let w = tx_size.width() as libc::c_int; + let h = tx_size.height() as libc::c_int; + + match T::type_enum() { + PixelType::U8 => { + let dst_ptr = dst.data_ptr_mut() as *mut _; + let edge_ptr = edge_buf.top_left_ptr() as *const _; + if cpu >= CpuFeatureLevel::AVX512ICL { + (match variant { + PredictionVariant::NONE => avsc_ipred_dc_128_8bpc_avx512icl, + PredictionVariant::LEFT => avsc_ipred_dc_left_8bpc_avx512icl, + PredictionVariant::TOP => avsc_ipred_dc_top_8bpc_avx512icl, + PredictionVariant::BOTH => avsc_ipred_dc_8bpc_avx512icl, + })(dst_ptr, stride, edge_ptr, w, h, 0); + } else if cpu >= CpuFeatureLevel::AVX2 { + (match variant { + PredictionVariant::NONE => avsc_ipred_dc_128_8bpc_avx2, + PredictionVariant::LEFT => avsc_ipred_dc_left_8bpc_avx2, + PredictionVariant::TOP => avsc_ipred_dc_top_8bpc_avx2, + PredictionVariant::BOTH => avsc_ipred_dc_8bpc_avx2, + })(dst_ptr, stride, edge_ptr, w, h, 0); + } else if cpu >= CpuFeatureLevel::SSSE3 { + (match variant { + PredictionVariant::NONE => avsc_ipred_dc_128_8bpc_ssse3, + PredictionVariant::LEFT => avsc_ipred_dc_left_8bpc_ssse3, + PredictionVariant::TOP => avsc_ipred_dc_top_8bpc_ssse3, + PredictionVariant::BOTH => avsc_ipred_dc_8bpc_ssse3, + })(dst_ptr, stride, edge_ptr, w, h, 0); + } else { + call_rust(dst) + } + } + PixelType::U16 => { + let dst_ptr = dst.data_ptr_mut() as *mut _; + let edge_ptr = edge_buf.top_left_ptr() as *const _; + let bd_max = (1 << bit_depth) - 1; + if cpu >= CpuFeatureLevel::AVX2 { + (match variant { + PredictionVariant::NONE => avsc_ipred_dc_128_16bpc_avx2, + PredictionVariant::LEFT => avsc_ipred_dc_left_16bpc_avx2, + PredictionVariant::TOP => avsc_ipred_dc_top_16bpc_avx2, + PredictionVariant::BOTH => avsc_ipred_dc_16bpc_avx2, + })(dst_ptr, stride, edge_ptr, w, h, 0, 0, 0, bd_max); + } else if cpu >= CpuFeatureLevel::SSSE3 { + (match variant { + PredictionVariant::NONE => avsc_ipred_dc_128_16bpc_ssse3, + PredictionVariant::LEFT => avsc_ipred_dc_left_16bpc_ssse3, + PredictionVariant::TOP => avsc_ipred_dc_top_16bpc_ssse3, + PredictionVariant::BOTH => avsc_ipred_dc_16bpc_ssse3, + })(dst_ptr, stride, edge_ptr, w, h, 0, 0, 0, bd_max); + } else { + call_rust(dst) + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/intra.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,374 @@ +#[cfg(asm_x86_64)] +mod simd_x86; + +use std::mem::{transmute, MaybeUninit}; + +use aligned::{Aligned, A64}; +#[cfg(not(asm_x86_64))] +use rust::*; +#[cfg(asm_x86_64)] +use simd_x86::*; +use v_frame::{ + frame::Frame, + pixel::Pixel, + plane::{Plane, PlaneOffset}, +}; + +use super::importance::IMPORTANCE_BLOCK_SIZE; +use crate::{ + cpu::CpuFeatureLevel, + data::{ + block::{BlockSize, TxSize, MAX_TX_SIZE}, + plane::{Area, AsRegion, PlaneRegion, PlaneRegionMut, Rect}, + prediction::PredictionVariant, + satd::get_satd, + slice_assume_init_mut, + superblock::MI_SIZE_LOG2, + tile::TileRect, + }, +}; + +pub const BLOCK_TO_PLANE_SHIFT: usize = MI_SIZE_LOG2; + +mod rust { + use v_frame::pixel::Pixel; + + use super::IntraEdge; + use crate::{ + cpu::CpuFeatureLevel, + data::{block::TxSize, plane::PlaneRegionMut, prediction::PredictionVariant}, + }; + + #[cfg_attr( + all(asm_x86_64, any(target_feature = "ssse3", target_feature = "avx2")), + cold + )] + pub(super) fn dispatch_predict_dc_intra( + variant: PredictionVariant, + dst: &mut PlaneRegionMut<'_, T>, + tx_size: TxSize, + bit_depth: usize, + edge_buf: &IntraEdge, + _cpu: CpuFeatureLevel, + ) { + let width = tx_size.width(); + let height = tx_size.height(); + + // left pixels are ordered from bottom to top and right-aligned + let (left, _top_left, above) = edge_buf.as_slices(); + + let above_slice = above; + let left_slice = &left[left.len().saturating_sub(height)..]; + + (match variant { + PredictionVariant::NONE => pred_dc_128, + PredictionVariant::LEFT => pred_dc_left, + PredictionVariant::TOP => pred_dc_top, + PredictionVariant::BOTH => pred_dc, + })(dst, above_slice, left_slice, width, height, bit_depth) + } + + fn pred_dc( + output: &mut PlaneRegionMut<'_, T>, + above: &[T], + left: &[T], + width: usize, + height: usize, + _bit_depth: usize, + ) { + let edges = left[..height].iter().chain(above[..width].iter()); + let len = (width + height) as u32; + let avg = (edges.fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }) + (len >> 1)) + / len; + let avg = T::cast_from(avg); + + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } + + fn pred_dc_128( + output: &mut PlaneRegionMut<'_, T>, + _above: &[T], + _left: &[T], + width: usize, + height: usize, + bit_depth: usize, + ) { + let v = T::cast_from(128u32 << (bit_depth - 8)); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(v); + } + } + + fn pred_dc_left( + output: &mut PlaneRegionMut<'_, T>, + _above: &[T], + left: &[T], + width: usize, + height: usize, + _bit_depth: usize, + ) { + let sum = left[..].iter().fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }); + let avg = T::cast_from((sum + (height >> 1) as u32) / height as u32); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } + + fn pred_dc_top( + output: &mut PlaneRegionMut<'_, T>, + above: &[T], + _left: &[T], + width: usize, + height: usize, + _bit_depth: usize, + ) { + let sum = above[..width].iter().fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }); + let avg = T::cast_from((sum + (width >> 1) as u32) / width as u32); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } +} + +pub(crate) fn estimate_intra_costs( + temp_plane: &mut Plane, + frame: &Frame, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> Box<[u32]> { + let plane = &frame.planes[0]; + let plane_after_prediction = temp_plane; + + let bsize = BlockSize::from_width_and_height(IMPORTANCE_BLOCK_SIZE, IMPORTANCE_BLOCK_SIZE); + let tx_size = bsize.tx_size(); + + let h_in_imp_b = plane.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane.cfg.width / IMPORTANCE_BLOCK_SIZE; + let mut intra_costs = Vec::with_capacity(h_in_imp_b * w_in_imp_b); + + for y in 0..h_in_imp_b { + for x in 0..w_in_imp_b { + let plane_org = plane.region(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + // For scene detection, we are only going to support DC_PRED + // for simplicity and speed purposes. + let mut edge_buf = Aligned([MaybeUninit::uninit(); 4 * MAX_TX_SIZE + 1]); + let edge_buf = get_intra_edges( + &mut edge_buf, + &plane.as_region(), + PlaneOffset { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + }, + bit_depth, + ); + + let mut plane_after_prediction_region = + plane_after_prediction.region_mut(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + predict_dc_intra( + TileRect { + x: x * IMPORTANCE_BLOCK_SIZE, + y: y * IMPORTANCE_BLOCK_SIZE, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }, + &mut plane_after_prediction_region, + tx_size, + bit_depth, + &edge_buf, + cpu_feature_level, + ); + + let plane_after_prediction_region = plane_after_prediction.region(Area::Rect(Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + })); + + let intra_cost = get_satd( + &plane_org, + &plane_after_prediction_region, + bsize.width(), + bsize.height(), + bit_depth, + cpu_feature_level, + ); + + intra_costs.push(intra_cost); + } + } + + intra_costs.into_boxed_slice() +} + +pub fn get_intra_edges<'a, T: Pixel>( + edge_buf: &'a mut IntraEdgeBuffer, + dst: &PlaneRegion<'_, T>, + po: PlaneOffset, + bit_depth: usize, +) -> IntraEdge<'a, T> { + let tx_size = TxSize::TX_8X8; + let mut init_left: usize = 0; + let mut init_above: usize = 0; + + let base = 128u16 << (bit_depth - 8); + + { + // left pixels are ordered from bottom to top and right-aligned + let (left, not_left) = edge_buf.split_at_mut(2 * MAX_TX_SIZE); + let (top_left, above) = not_left.split_at_mut(1); + + let x = po.x as usize; + let y = po.y as usize; + + let needs_left = x != 0; + let needs_top = y != 0; + + let rect_w = dst + .rect() + .width + .min(dst.plane_cfg.width - dst.rect().x as usize); + let rect_h = dst + .rect() + .height + .min(dst.plane_cfg.height - dst.rect().y as usize); + + // Needs left + if needs_left { + let txh = if y + tx_size.height() > rect_h { + rect_h - y + } else { + tx_size.height() + }; + if x != 0 { + for i in 0..txh { + debug_assert!(y + i < rect_h); + left[2 * MAX_TX_SIZE - 1 - i].write(dst[y + i][x - 1]); + } + if txh < tx_size.height() { + let val = dst[y + txh - 1][x - 1]; + for i in txh..tx_size.height() { + left[2 * MAX_TX_SIZE - 1 - i].write(val); + } + } + } else { + let val = if y != 0 { + dst[y - 1][0] + } else { + T::cast_from(base + 1) + }; + for v in left[2 * MAX_TX_SIZE - tx_size.height()..].iter_mut() { + v.write(val); + } + } + init_left += tx_size.height(); + } + + // Needs top + if needs_top { + let txw = if x + tx_size.width() > rect_w { + rect_w - x + } else { + tx_size.width() + }; + if y != 0 { + above[..txw].copy_from_slice( + // SAFETY: &[T] and &[MaybeUninit] have the same layout + unsafe { transmute::<&[T], &[MaybeUninit]>(&dst[y - 1][x..x + txw]) }, + ); + if txw < tx_size.width() { + let val = dst[y - 1][x + txw - 1]; + for v in &mut above[txw..tx_size.width()] { + v.write(val); + } + } + } else { + let val = if x != 0 { + dst[0][x - 1] + } else { + T::cast_from(base - 1) + }; + for v in &mut above[..tx_size.width()] { + v.write(val); + } + } + init_above += tx_size.width(); + } + + top_left[0].write(T::cast_from(base)); + } + IntraEdge::new(edge_buf, init_left, init_above) +} + +pub fn predict_dc_intra( + tile_rect: TileRect, + dst: &mut PlaneRegionMut<'_, T>, + tx_size: TxSize, + bit_depth: usize, + edge_buf: &IntraEdge, + cpu: CpuFeatureLevel, +) { + let &Rect { + x: frame_x, + y: frame_y, + .. + } = dst.rect(); + debug_assert!(frame_x >= 0 && frame_y >= 0); + // x and y are expressed relative to the tile + let x = frame_x as usize - tile_rect.x; + let y = frame_y as usize - tile_rect.y; + + let variant = PredictionVariant::new(x, y); + + dispatch_predict_dc_intra::(variant, dst, tx_size, bit_depth, edge_buf, cpu); +} + +type IntraEdgeBuffer = Aligned; 4 * MAX_TX_SIZE + 1]>; + +pub struct IntraEdge<'a, T: Pixel>(&'a [T], &'a [T], &'a [T]); + +impl<'a, T: Pixel> IntraEdge<'a, T> { + fn new(edge_buf: &'a mut IntraEdgeBuffer, init_left: usize, init_above: usize) -> Self { + // SAFETY: Initialized in `get_intra_edges`. + let left = unsafe { + let begin_left = 2 * MAX_TX_SIZE - init_left; + let end_above = 2 * MAX_TX_SIZE + 1 + init_above; + slice_assume_init_mut(&mut edge_buf[begin_left..end_above]) + }; + let (left, top_left) = left.split_at(init_left); + let (top_left, above) = top_left.split_at(1); + Self(left, top_left, above) + } + + pub const fn as_slices(&self) -> (&'a [T], &'a [T], &'a [T]) { + (self.0, self.1, self.2) + } + + #[allow(dead_code)] + pub const fn top_left_ptr(&self) -> *const T { + self.1.as_ptr() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,417 @@ +use std::{cmp, collections::BTreeMap, num::NonZeroUsize, sync::Arc}; + +use log::debug; +use num_rational::Rational32; +use v_frame::{ + frame::Frame, + pixel::{ChromaSampling, Pixel}, + plane::Plane, +}; + +use self::fast::{detect_scale_factor, FAST_THRESHOLD}; +use crate::{data::motion::RefMEStats, CpuFeatureLevel, SceneDetectionSpeed}; + +mod fast; +mod importance; +mod inter; +mod intra; +mod standard; + +/// Experiments have determined this to be an optimal threshold +const IMP_BLOCK_DIFF_THRESHOLD: f64 = 7.0; + +/// Fast integer division where divisor is a nonzero power of 2 +pub(crate) fn fast_idiv(n: usize, d: NonZeroUsize) -> usize { + debug_assert!(d.is_power_of_two()); + + n >> d.trailing_zeros() +} + +struct ScaleFunction { + downscale_in_place: fn(/* &self: */ &Plane, /* in_plane: */ &mut Plane), + downscale: fn(/* &self: */ &Plane) -> Plane, + factor: NonZeroUsize, +} + +impl ScaleFunction { + fn from_scale() -> Self { + assert!( + SCALE.is_power_of_two(), + "Scaling factor needs to be a nonzero power of two" + ); + + Self { + downscale: Plane::downscale::, + downscale_in_place: Plane::downscale_in_place::, + factor: NonZeroUsize::new(SCALE).unwrap(), + } + } +} +/// Runs keyframe detection on frames from the lookahead queue. +/// +/// This struct is intended for advanced users who need the ability to analyze +/// a small subset of frames at a time, for example in a streaming fashion. +/// Most users will prefer to use `new_detector` and `detect_scene_changes` +/// at the top level of this crate. +pub struct SceneChangeDetector { + // User configuration options + /// Scenecut detection mode + scene_detection_mode: SceneDetectionSpeed, + /// Deque offset for current + lookahead_offset: usize, + /// Minimum number of frames between two scenecuts + min_key_frame_interval: usize, + /// Maximum number of frames between two scenecuts + max_key_frame_interval: usize, + /// The CPU feature level to be used. + cpu_feature_level: CpuFeatureLevel, + + // Internal configuration options + /// Minimum average difference between YUV deltas that will trigger a scene + /// change. + threshold: f64, + /// Width and height of the unscaled frame + resolution: (usize, usize), + /// The bit depth of the video. + bit_depth: usize, + /// The frame rate of the video. + frame_rate: Rational32, + /// The chroma subsampling of the video. + chroma_sampling: ChromaSampling, + /// Number of pixels in scaled frame for fast mode + scaled_pixels: usize, + /// Downscaling function for fast scene detection + scale_func: Option>, + + // Internal data structures + /// Start deque offset based on lookahead + deque_offset: usize, + /// Frame buffer for scaled frames + downscaled_frame_buffer: Option<[Plane; 2]>, + /// Scenechange results for adaptive threshold + score_deque: Vec, + /// Temporary buffer used by `estimate_intra_costs`. + /// We store it on the struct so we only need to allocate it once. + temp_plane: Option>, + /// Buffer for `FrameMEStats` for cost scenecut + frame_me_stats_buffer: Option, + + /// Calculated intra costs for each input frame. + /// These can be cached for reuse by advanced API users. + /// Caching will occur if this is not `None`. + pub intra_costs: Option>>, +} + +impl SceneChangeDetector { + /// Creates a new instance of the `SceneChangeDetector`. + #[allow(clippy::too_many_arguments)] + #[allow(clippy::missing_panics_doc)] + #[inline] + pub fn new( + resolution: (usize, usize), + bit_depth: usize, + frame_rate: Rational32, + chroma_sampling: ChromaSampling, + lookahead_distance: usize, + scene_detection_mode: SceneDetectionSpeed, + min_key_frame_interval: usize, + max_key_frame_interval: usize, + cpu_feature_level: CpuFeatureLevel, + ) -> Self { + // Downscaling function for fast scene detection + let scale_func = detect_scale_factor(resolution, scene_detection_mode); + + // Set lookahead offset to 5 if normal lookahead available + let lookahead_offset = if lookahead_distance >= 5 { 5 } else { 0 }; + let deque_offset = lookahead_offset; + + let score_deque = Vec::with_capacity(5 + lookahead_distance); + + // Downscaling factor for fast scenedetect (is currently always a power of 2) + let factor = scale_func.as_ref().map_or( + NonZeroUsize::new(1).expect("constant should not panic"), + |x| x.factor, + ); + + let pixels = if scene_detection_mode == SceneDetectionSpeed::Fast { + fast_idiv(resolution.1, factor) * fast_idiv(resolution.0, factor) + } else { + 1 + }; + + let threshold = FAST_THRESHOLD * (bit_depth as f64) / 8.0; + + Self { + threshold, + scene_detection_mode, + scale_func, + lookahead_offset, + deque_offset, + score_deque, + scaled_pixels: pixels, + bit_depth, + frame_rate, + chroma_sampling, + min_key_frame_interval, + max_key_frame_interval, + cpu_feature_level, + downscaled_frame_buffer: None, + resolution, + temp_plane: None, + frame_me_stats_buffer: None, + intra_costs: None, + } + } + + /// Enables caching of intra costs. For advanced API users. + #[inline] + pub fn enable_cache(&mut self) { + if self.intra_costs.is_none() { + self.intra_costs = Some(BTreeMap::new()); + } + } + + /// Runs keyframe detection on the next frame in the lookahead queue. + /// + /// This function requires that a subset of input frames + /// is passed to it in order, and that `keyframes` is only + /// updated from this method. `input_frameno` should correspond + /// to the second frame in `frame_set`. + /// + /// This will gracefully handle the first frame in the video as well. + #[inline] + pub fn analyze_next_frame( + &mut self, + frame_set: &[&Arc>], + input_frameno: usize, + previous_keyframe: usize, + ) -> bool { + // Use score deque for adaptive threshold for scene cut + // Declare score_deque offset based on lookahead for scene change scores + + // Find the distance to the previous keyframe. + let distance = input_frameno - previous_keyframe; + + if frame_set.len() <= self.lookahead_offset { + // Don't insert keyframes in the last few frames of the video + // This is basically a scene flash and a waste of bits + return false; + } + + if self.scene_detection_mode == SceneDetectionSpeed::None { + if let Some(true) = self.handle_min_max_intervals(distance) { + return true; + }; + return false; + } + + // Initialization of score deque + // based on frame set length + if self.deque_offset > 0 + && frame_set.len() > self.deque_offset + 1 + && self.score_deque.is_empty() + { + self.initialize_score_deque(frame_set, input_frameno, self.deque_offset); + } else if self.score_deque.is_empty() { + self.initialize_score_deque(frame_set, input_frameno, frame_set.len() - 1); + + self.deque_offset = frame_set.len() - 2; + } + // Running single frame comparison and adding it to deque + // Decrease deque offset if there is no new frames + if frame_set.len() > self.deque_offset + 1 { + self.run_comparison( + frame_set[self.deque_offset].clone(), + frame_set[self.deque_offset + 1].clone(), + input_frameno + self.deque_offset, + ); + } else { + self.deque_offset -= 1; + } + + // Adaptive scenecut check + let (scenecut, score) = self.adaptive_scenecut(); + let scenecut = self.handle_min_max_intervals(distance).unwrap_or(scenecut); + debug!( + "[SC-Detect] Frame {}: Raw={:5.1} ImpBl={:5.1} Bwd={:5.1} Fwd={:5.1} Th={:.1} {}", + input_frameno, + score.inter_cost, + score.imp_block_cost, + score.backward_adjusted_cost, + score.forward_adjusted_cost, + score.threshold, + if scenecut { "Scenecut" } else { "No cut" } + ); + + // Keep score deque of 5 backward frames + // and forward frames of length of lookahead offset + if self.score_deque.len() > 5 + self.lookahead_offset { + self.score_deque.pop(); + } + + scenecut + } + + fn handle_min_max_intervals(&mut self, distance: usize) -> Option { + // Handle minimum and maximum keyframe intervals. + if distance < self.min_key_frame_interval { + return Some(false); + } + if distance >= self.max_key_frame_interval { + return Some(true); + } + None + } + + // Initially fill score deque with frame scores + fn initialize_score_deque( + &mut self, + frame_set: &[&Arc>], + input_frameno: usize, + init_len: usize, + ) { + for x in 0..init_len { + self.run_comparison( + frame_set[x].clone(), + frame_set[x + 1].clone(), + input_frameno + x, + ); + } + } + + /// Runs scene change comparison between 2 given frames + /// Insert result to start of score deque + fn run_comparison( + &mut self, + frame1: Arc>, + frame2: Arc>, + input_frameno: usize, + ) { + let mut result = match self.scene_detection_mode { + SceneDetectionSpeed::Fast => self.fast_scenecut(frame1, frame2), + SceneDetectionSpeed::Standard => self.cost_scenecut(frame1, frame2, input_frameno), + _ => unreachable!(), + }; + + // Subtract the highest metric value of surrounding frames from the current one. + // It makes the peaks in the metric more distinct. + if self.scene_detection_mode == SceneDetectionSpeed::Standard && self.deque_offset > 0 { + if input_frameno == 1 { + // Accounts for the second frame not having a score to adjust against. + // It should always be 0 because the first frame of the video is always a + // keyframe. + result.backward_adjusted_cost = 0.0; + } else { + let mut adjusted_cost = f64::MAX; + for other_cost in self + .score_deque + .iter() + .take(self.deque_offset) + .map(|i| i.inter_cost) + { + let this_cost = result.inter_cost - other_cost; + if this_cost < adjusted_cost { + adjusted_cost = this_cost; + } + if adjusted_cost < 0.0 { + adjusted_cost = 0.0; + break; + } + } + result.backward_adjusted_cost = adjusted_cost; + } + if !self.score_deque.is_empty() { + for i in 0..cmp::min(self.deque_offset, self.score_deque.len()) { + let adjusted_cost = self.score_deque[i].inter_cost - result.inter_cost; + if i == 0 || adjusted_cost < self.score_deque[i].forward_adjusted_cost { + self.score_deque[i].forward_adjusted_cost = adjusted_cost; + } + if self.score_deque[i].forward_adjusted_cost < 0.0 { + self.score_deque[i].forward_adjusted_cost = 0.0; + } + } + } + } + self.score_deque.insert(0, result); + } + + /// Compares current scene score to adapted threshold based on previous + /// scores + /// + /// Value of current frame is offset by lookahead, if lookahead >=5 + /// + /// Returns true if current scene score is higher than adapted threshold + fn adaptive_scenecut(&mut self) -> (bool, ScenecutResult) { + let score = self.score_deque[self.deque_offset]; + + // We use the importance block algorithm's cost metrics as a secondary algorithm + // because, although it struggles in certain scenarios such as + // finding the end of a pan, it is very good at detecting hard scenecuts + // or detecting if a pan exists. + // + // Because of this, we only consider a frame for a scenechange if + // the importance block algorithm is over the threshold either on this frame + // (hard scenecut) or within the past few frames (pan). This helps + // filter out a few false positives produced by the cost-based + // algorithm. + let imp_block_threshold = IMP_BLOCK_DIFF_THRESHOLD * (self.bit_depth as f64) / 8.0; + if !&self.score_deque[self.deque_offset..] + .iter() + .any(|result| result.imp_block_cost >= imp_block_threshold) + { + return (false, score); + } + + let cost = score.forward_adjusted_cost; + if cost >= score.threshold { + let back_deque = &self.score_deque[self.deque_offset + 1..]; + let forward_deque = &self.score_deque[..self.deque_offset]; + let back_over_tr_count = back_deque + .iter() + .filter(|result| result.backward_adjusted_cost >= result.threshold) + .count(); + let forward_over_tr_count = forward_deque + .iter() + .filter(|result| result.forward_adjusted_cost >= result.threshold) + .count(); + + // Check for scenecut after the flashes + // No frames over threshold forward + // and some frames over threshold backward + let back_count_req = if self.scene_detection_mode == SceneDetectionSpeed::Fast { + // Fast scenecut is more sensitive to false flash detection, + // so we want more "evidence" of there being a flash before creating a keyframe. + 2 + } else { + 1 + }; + if forward_over_tr_count == 0 && back_over_tr_count >= back_count_req { + return (true, score); + } + + // Check for scenecut before flash + // If distance longer than max flash length + if back_over_tr_count == 0 + && forward_over_tr_count == 1 + && forward_deque[0].forward_adjusted_cost >= forward_deque[0].threshold + { + return (true, score); + } + + if back_over_tr_count != 0 || forward_over_tr_count != 0 { + return (false, score); + } + } + + (cost >= score.threshold, score) + } +} + +#[derive(Debug, Clone, Copy)] +struct ScenecutResult { + inter_cost: f64, + imp_block_cost: f64, + backward_adjusted_cost: f64, + forward_adjusted_cost: f64, + threshold: f64, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/standard.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/standard.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/analyze/standard.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/analyze/standard.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +use std::sync::Arc; + +use v_frame::{frame::Frame, math::Fixed, pixel::Pixel}; + +use super::{SceneChangeDetector, ScenecutResult}; +use crate::{ + analyze::{ + importance::estimate_importance_block_difference, + inter::estimate_inter_costs, + intra::estimate_intra_costs, + }, + data::motion::FrameMEStats, +}; + +impl SceneChangeDetector { + /// Run a comparison between two frames to determine if they qualify for a + /// scenecut. + /// + /// We gather both intra and inter costs for the frames, + /// as well as an importance-block-based difference, + /// and use all three metrics. + pub(super) fn cost_scenecut( + &mut self, + frame1: Arc>, + frame2: Arc>, + input_frameno: usize, + ) -> ScenecutResult { + let frame2_inter_ref = Arc::clone(&frame2); + let frame1_imp_ref = Arc::clone(&frame1); + let frame2_imp_ref = Arc::clone(&frame2); + + let mut intra_cost = 0.0; + let mut mv_inter_cost = 0.0; + let mut imp_block_cost = 0.0; + + let cols = 2 * self.resolution.0.align_power_of_two_and_shift(3); + let rows = 2 * self.resolution.1.align_power_of_two_and_shift(3); + + let buffer = if let Some(buffer) = &self.frame_me_stats_buffer { + Arc::clone(buffer) + } else { + let frame_me_stats = FrameMEStats::new_arc_array(cols, rows); + let clone = Arc::clone(&frame_me_stats); + self.frame_me_stats_buffer = Some(frame_me_stats); + clone + }; + + rayon::scope(|s| { + s.spawn(|_| { + let temp_plane = self + .temp_plane + .get_or_insert_with(|| frame2.planes[0].clone()); + + let intra_costs = estimate_intra_costs( + temp_plane, + &*frame2, + self.bit_depth, + self.cpu_feature_level, + ); + if let Some(ref mut intra_cache) = self.intra_costs { + intra_cache.insert(input_frameno, intra_costs.clone()); + } + + intra_cost = intra_costs.iter().map(|&cost| cost as u64).sum::() as f64 + / intra_costs.len() as f64; + }); + s.spawn(|_| { + mv_inter_cost = estimate_inter_costs( + frame2_inter_ref, + frame1, + self.bit_depth, + self.frame_rate, + self.chroma_sampling, + buffer, + self.cpu_feature_level, + ); + }); + s.spawn(|_| { + imp_block_cost = + estimate_importance_block_difference(frame2_imp_ref, frame1_imp_ref); + }); + }); + + // `BIAS` determines how likely we are + // to choose a keyframe, between 0.0-1.0. + // Higher values mean we are more likely to choose a keyframe. + // This value was chosen based on trials using the new + // adaptive scenecut code. + const BIAS: f64 = 0.7; + let threshold = intra_cost * (1.0 - BIAS); + + ScenecutResult { + inter_cost: mv_inter_cost, + imp_block_cost, + threshold, + backward_adjusted_cost: 0.0, + forward_adjusted_cost: 0.0, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5245 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/asm/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_128_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_128_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + movi v0.16b, #128 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + movi v1.16b, #128 +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + movi v1.16b, #128 + movi v2.16b, #128 + movi v3.16b, #128 +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_128_tbl): + .hword L(ipred_dc_128_tbl) - 640b + .hword L(ipred_dc_128_tbl) - 320b + .hword L(ipred_dc_128_tbl) - 16b + .hword L(ipred_dc_128_tbl) - 8b + .hword L(ipred_dc_128_tbl) - 4b +endfunc + +// void ipred_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_v_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #1 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2] +4: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] +8: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] +16: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_v_tbl): + .hword L(ipred_v_tbl) - 640b + .hword L(ipred_v_tbl) - 320b + .hword L(ipred_v_tbl) - 160b + .hword L(ipred_v_tbl) - 80b + .hword L(ipred_v_tbl) - 40b +endfunc + +// void ipred_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_h_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + sub x2, x2, #4 + sub x5, x5, w3, uxtw + mov x7, #-4 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + st1 {v3.s}[0], [x0], x1 + st1 {v2.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v1.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + st1 {v3.8b}, [x0], x1 + st1 {v2.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v1.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_h_tbl): + .hword L(ipred_h_tbl) - 64b + .hword L(ipred_h_tbl) - 32b + .hword L(ipred_h_tbl) - 16b + .hword L(ipred_h_tbl) - 8b + .hword L(ipred_h_tbl) - 4b +endfunc + +// void ipred_dc_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_top_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #1 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.8b, v0.b[0] +4: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.8b, v0.b[0] +8: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] +16: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add v2.4h, v0.4h, v1.4h + rshrn v2.8b, v2.8h, #5 + dup v0.16b, v2.b[0] + dup v1.16b, v2.b[0] +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v4.4h, v0.4h, v1.4h + add v5.4h, v2.4h, v3.4h + add v4.4h, v4.4h, v5.4h + rshrn v4.8b, v4.8h, #6 + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] + dup v2.16b, v4.b[0] + dup v3.16b, v4.b[0] +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_top_tbl): + .hword L(ipred_dc_top_tbl) - 640b + .hword L(ipred_dc_top_tbl) - 320b + .hword L(ipred_dc_top_tbl) - 160b + .hword L(ipred_dc_top_tbl) - 80b + .hword L(ipred_dc_top_tbl) - 40b +endfunc + +// void ipred_dc_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + clz w3, w3 + clz w7, w4 + adr x5, L(ipred_dc_left_tbl) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w7, w7, #25 + ldrh w3, [x5, w3, uxtw #1] + ldrh w7, [x5, w7, uxtw #1] + sub x3, x5, w3, uxtw + sub x5, x5, w7, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w4): + AARCH64_VALID_JUMP_TARGET + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt L(ipred_dc_left_w4) + ret + +L(ipred_dc_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w8): + AARCH64_VALID_JUMP_TARGET + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt L(ipred_dc_left_w8) + ret + +L(ipred_dc_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w16): + AARCH64_VALID_JUMP_TARGET + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt L(ipred_dc_left_w16) + ret + +L(ipred_dc_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add v0.4h, v0.4h, v1.4h + rshrn v0.8b, v0.8h, #5 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w32): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +1: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v0.4h, v0.4h, v1.4h + add v2.4h, v2.4h, v3.4h + add v0.4h, v0.4h, v2.4h + rshrn v0.8b, v0.8h, #6 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w64): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +1: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_tbl): + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h4) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w4) +endfunc + +// void ipred_dc_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + add w7, w3, w4 // width + height + clz w3, w3 + clz w6, w4 + dup v16.8h, w7 // width + height + adr x5, L(ipred_dc_tbl) + rbit w7, w7 // rbit(width + height) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w6, w6, #25 + clz w7, w7 // ctz(width + height) + ldrh w3, [x5, w3, uxtw #1] + ldrh w6, [x5, w6, uxtw #1] + neg w7, w7 // -ctz(width + height) + sub x3, x5, w3, uxtw + sub x5, x5, w6, uxtw + ushr v16.8h, v16.8h, #1 // (width + height) >> 1 + dup v17.8h, w7 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], #4 + ins v0.s[1], wzr + uaddlv h0, v0.8b + add x2, x2, #1 + br x3 +L(ipred_dc_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.s}[0], [x2] + ins v1.s[1], wzr + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.8b + cmp w4, #4 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x3334/2) + movk w16, #(0x5556/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8b, v0.b[0] +2: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], #8 + uaddlv h0, v0.8b + add x2, x2, #1 + br x3 +L(ipred_dc_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.8b + cmp w4, #8 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8b, v0.b[0] +2: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2], #16 + uaddlv h0, v0.16b + add x2, x2, #1 + br x3 +L(ipred_dc_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + cmp w4, #16 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/8/32/64 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.16b, v0.b[0] +2: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2], #32 + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add x2, x2, #1 + add v0.4h, v0.4h, v1.4h + br x3 +L(ipred_dc_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + uaddlv h2, v2.16b + cmp w4, #32 + add v0.4h, v0.4h, v1.4h + add v0.4h, v0.4h, v2.4h + ushl v4.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16/64 + cmp w4, #8 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v4.4h, v4.4h, v16.4h +1: + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] +2: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], #64 + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v0.4h, v0.4h, v1.4h + add v2.4h, v2.4h, v3.4h + add x2, x2, #1 + add v0.4h, v0.4h, v2.4h + br x3 +L(ipred_dc_w64): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b, v3.16b, v4.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + uaddlv h4, v4.16b + add v1.4h, v1.4h, v2.4h + add v3.4h, v3.4h, v4.4h + cmp w4, #64 + add v0.4h, v0.4h, v1.4h + add v0.4h, v0.4h, v3.4h + ushl v4.4h, v0.4h, v17.4h + b.eq 1f + // h = 16/32 + mov w16, #(0x5556/2) + movk w16, #(0x3334/2), lsl #16 + lsr w16, w16, w4 + dup v16.4h, w16 + sqdmulh v4.4h, v4.4h, v16.4h +1: + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] + dup v2.16b, v4.b[0] + dup v3.16b, v4.b[0] +2: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_tbl): + .hword L(ipred_dc_tbl) - L(ipred_dc_h64) + .hword L(ipred_dc_tbl) - L(ipred_dc_h32) + .hword L(ipred_dc_tbl) - L(ipred_dc_h16) + .hword L(ipred_dc_tbl) - L(ipred_dc_h8) + .hword L(ipred_dc_tbl) - L(ipred_dc_h4) + .hword L(ipred_dc_tbl) - L(ipred_dc_w64) + .hword L(ipred_dc_tbl) - L(ipred_dc_w32) + .hword L(ipred_dc_tbl) - L(ipred_dc_w16) + .hword L(ipred_dc_tbl) - L(ipred_dc_w8) + .hword L(ipred_dc_tbl) - L(ipred_dc_w4) +endfunc + +// void ipred_paeth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_8bpc_neon, export=1 + clz w9, w3 + adr x5, L(ipred_paeth_tbl) + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x2] + add x8, x2, #1 + sub x2, x2, #4 + sub x5, x5, w9, uxtw + mov x7, #-4 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.4s}, [x8] + usubl v6.8h, v5.8b, v4.8b // top - topleft +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + zip1 v0.2s, v0.2s, v1.2s + zip1 v2.2s, v2.2s, v3.2s + uaddw v16.8h, v6.8h, v0.8b + uaddw v17.8h, v6.8h, v2.8b + sqxtun v16.8b, v16.8h // base + sqxtun2 v16.16b, v17.8h + zip1 v0.2d, v0.2d, v2.2d + uabd v20.16b, v5.16b, v16.16b // tdiff + uabd v22.16b, v4.16b, v16.16b // tldiff + uabd v16.16b, v0.16b, v16.16b // ldiff + umin v18.16b, v20.16b, v22.16b // min(tdiff, tldiff) + cmhs v20.16b, v22.16b, v20.16b // tldiff >= tdiff + cmhs v16.16b, v18.16b, v16.16b // min(tdiff, tldiff) >= ldiff + bsl v20.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bit v20.16b, v0.16b, v16.16b // ldiff <= min ? left : ... + st1 {v20.s}[3], [x0], x1 + st1 {v20.s}[2], [x6], x1 + subs w4, w4, #4 + st1 {v20.s}[1], [x0], x1 + st1 {v20.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.2d}, [x8] + usubl v6.8h, v5.8b, v4.8b // top - topleft +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + uaddw v16.8h, v6.8h, v0.8b + uaddw v17.8h, v6.8h, v1.8b + uaddw v18.8h, v6.8h, v2.8b + uaddw v19.8h, v6.8h, v3.8b + sqxtun v16.8b, v16.8h // base + sqxtun2 v16.16b, v17.8h + sqxtun v18.8b, v18.8h + sqxtun2 v18.16b, v19.8h + zip1 v2.2d, v2.2d, v3.2d + zip1 v0.2d, v0.2d, v1.2d + uabd v21.16b, v5.16b, v18.16b // tdiff + uabd v20.16b, v5.16b, v16.16b + uabd v23.16b, v4.16b, v18.16b // tldiff + uabd v22.16b, v4.16b, v16.16b + uabd v17.16b, v2.16b, v18.16b // ldiff + uabd v16.16b, v0.16b, v16.16b + umin v19.16b, v21.16b, v23.16b // min(tdiff, tldiff) + umin v18.16b, v20.16b, v22.16b + cmhs v21.16b, v23.16b, v21.16b // tldiff >= tdiff + cmhs v20.16b, v22.16b, v20.16b + cmhs v17.16b, v19.16b, v17.16b // min(tdiff, tldiff) >= ldiff + cmhs v16.16b, v18.16b, v16.16b + bsl v21.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v20.16b, v5.16b, v4.16b + bit v21.16b, v2.16b, v17.16b // ldiff <= min ? left : ... + bit v20.16b, v0.16b, v16.16b + st1 {v21.d}[1], [x0], x1 + st1 {v21.d}[0], [x6], x1 + subs w4, w4, #4 + st1 {v20.d}[1], [x0], x1 + st1 {v20.d}[0], [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v5.16b}, [x8], #16 + mov w9, w3 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw +1: + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 +2: + usubl v6.8h, v5.8b, v4.8b // top - topleft + usubl2 v7.8h, v5.16b, v4.16b + uaddw v24.8h, v6.8h, v0.8b + uaddw v25.8h, v7.8h, v0.8b + uaddw v26.8h, v6.8h, v1.8b + uaddw v27.8h, v7.8h, v1.8b + uaddw v28.8h, v6.8h, v2.8b + uaddw v29.8h, v7.8h, v2.8b + uaddw v30.8h, v6.8h, v3.8b + uaddw v31.8h, v7.8h, v3.8b + sqxtun v17.8b, v26.8h // base + sqxtun2 v17.16b, v27.8h + sqxtun v16.8b, v24.8h + sqxtun2 v16.16b, v25.8h + sqxtun v19.8b, v30.8h + sqxtun2 v19.16b, v31.8h + sqxtun v18.8b, v28.8h + sqxtun2 v18.16b, v29.8h + uabd v23.16b, v5.16b, v19.16b // tdiff + uabd v22.16b, v5.16b, v18.16b + uabd v21.16b, v5.16b, v17.16b + uabd v20.16b, v5.16b, v16.16b + uabd v27.16b, v4.16b, v19.16b // tldiff + uabd v26.16b, v4.16b, v18.16b + uabd v25.16b, v4.16b, v17.16b + uabd v24.16b, v4.16b, v16.16b + uabd v19.16b, v3.16b, v19.16b // ldiff + uabd v18.16b, v2.16b, v18.16b + uabd v17.16b, v1.16b, v17.16b + uabd v16.16b, v0.16b, v16.16b + umin v31.16b, v23.16b, v27.16b // min(tdiff, tldiff) + umin v30.16b, v22.16b, v26.16b + umin v29.16b, v21.16b, v25.16b + umin v28.16b, v20.16b, v24.16b + cmhs v23.16b, v27.16b, v23.16b // tldiff >= tdiff + cmhs v22.16b, v26.16b, v22.16b + cmhs v21.16b, v25.16b, v21.16b + cmhs v20.16b, v24.16b, v20.16b + cmhs v19.16b, v31.16b, v19.16b // min(tdiff, tldiff) >= ldiff + cmhs v18.16b, v30.16b, v18.16b + cmhs v17.16b, v29.16b, v17.16b + cmhs v16.16b, v28.16b, v16.16b + bsl v23.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v22.16b, v5.16b, v4.16b + bsl v21.16b, v5.16b, v4.16b + bsl v20.16b, v5.16b, v4.16b + bit v23.16b, v3.16b, v19.16b // ldiff <= min ? left : ... + bit v22.16b, v2.16b, v18.16b + bit v21.16b, v1.16b, v17.16b + bit v20.16b, v0.16b, v16.16b + subs w3, w3, #16 + st1 {v23.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v21.16b}, [x5], #16 + st1 {v20.16b}, [x10], #16 + b.le 8f + ld1 {v5.16b}, [x8], #16 + b 2b +8: + subs w4, w4, #4 + b.le 9f + // End of horizontal loop, move pointers to next four rows + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + // Load the top row as early as possible + ld1 {v5.16b}, [x8], #16 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_paeth_tbl): + .hword L(ipred_paeth_tbl) - 640b + .hword L(ipred_paeth_tbl) - 320b + .hword L(ipred_paeth_tbl) - 160b + .hword L(ipred_paeth_tbl) - 80b + .hword L(ipred_paeth_tbl) - 40b +endfunc + +// void ipred_smooth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_8bpc_neon, export=1 + movrel x10, X(sm_weights) + add x11, x10, w4, uxtw + add x10, x10, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_tbl) + sub x12, x2, w4, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x12] // bottom + add x8, x2, #1 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2s}, [x8] // top + ld1r {v7.2s}, [x10] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + dup v5.16b, v6.b[3] // right + usubl v6.8h, v6.8b, v4.8b // top-bottom + uxtl v7.8h, v7.8b // weights_hor +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + zip1 v1.2s, v1.2s, v0.2s // left, flipped + zip1 v0.2s, v3.2s, v2.2s + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + shll v22.8h, v4.8b, #8 // bottom*256 + shll v23.8h, v4.8b, #8 + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + mla v20.8h, v0.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h + mla v22.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v23.8h, v6.8h, v18.8h + uhadd v20.8h, v20.8h, v22.8h + uhadd v21.8h, v21.8h, v23.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8b}, [x8] // top + ld1 {v7.8b}, [x10] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + dup v5.16b, v6.b[7] // right + usubl v6.8h, v6.8b, v4.8b // top-bottom + uxtl v7.8h, v7.8b // weights_hor +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + usubl v2.8h, v2.8b, v5.8b + usubl v3.8h, v3.8b, v5.8b + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + mla v20.8h, v3.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v2.8h, v7.8h // (left flipped) + mla v22.8h, v1.8h, v7.8h + mla v23.8h, v0.8h, v7.8h + mla v24.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v6.8h, v17.8h + mla v26.8h, v6.8h, v18.8h + mla v27.8h, v6.8h, v19.8h + uhadd v20.8h, v20.8h, v24.8h + uhadd v21.8h, v21.8h, v25.8h + uhadd v22.8h, v22.8h, v26.8h + uhadd v23.8h, v23.8h, v27.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v20.8b}, [x0], x1 + st1 {v21.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + add x12, x2, w3, uxtw + sub x2, x2, #2 + mov x7, #-2 + ld1r {v5.16b}, [x12] // right + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld2r {v0.8b, v1.8b}, [x2], x7 // left + ld2r {v16.8b, v17.8b}, [x11], #2 // weights_ver + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b +2: + ld1 {v7.16b}, [x10], #16 // weights_hor + ld1 {v3.16b}, [x8], #16 // top + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + usubl v2.8h, v3.8b, v4.8b // top-bottom + usubl2 v3.8h, v3.16b, v4.16b + mla v20.8h, v1.8h, v6.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h // (left flipped) + mla v22.8h, v0.8h, v6.8h + mla v23.8h, v0.8h, v7.8h + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + mla v24.8h, v2.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v3.8h, v16.8h + mla v26.8h, v2.8h, v17.8h + mla v27.8h, v3.8h, v17.8h + uhadd v20.8h, v20.8h, v24.8h + uhadd v21.8h, v21.8h, v25.8h + uhadd v22.8h, v22.8h, v26.8h + uhadd v23.8h, v23.8h, v27.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x8, w9, uxtw + sub x10, x10, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_tbl): + .hword L(ipred_smooth_tbl) - 640b + .hword L(ipred_smooth_tbl) - 320b + .hword L(ipred_smooth_tbl) - 160b + .hword L(ipred_smooth_tbl) - 80b + .hword L(ipred_smooth_tbl) - 40b +endfunc + +// void ipred_smooth_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_8bpc_neon, export=1 + movrel x7, X(sm_weights) + add x7, x7, w4, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_v_tbl) + sub x8, x2, w4, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x8] // bottom + add x2, x2, #1 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2s}, [x2] // top + usubl v6.8h, v6.8b, v4.8b // top-bottom +4: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + shll v22.8h, v4.8b, #8 // bottom*256 + shll v23.8h, v4.8b, #8 + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + mla v22.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v23.8h, v6.8h, v18.8h + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v22.s}[0], [x0], x1 + st1 {v22.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v23.s}[0], [x0], x1 + st1 {v23.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8b}, [x2] // top + usubl v6.8h, v6.8b, v4.8b // top-bottom +8: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + mla v24.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v6.8h, v17.8h + mla v26.8h, v6.8h, v18.8h + mla v27.8h, v6.8h, v19.8h + rshrn v24.8b, v24.8h, #8 + rshrn v25.8b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn v27.8b, v27.8h, #8 + st1 {v24.8b}, [x0], x1 + st1 {v25.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v26.8b}, [x0], x1 + st1 {v27.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + // Set up pointers for four rows in parallel; x0, x6, x5, x8 + add x5, x0, x1 + add x8, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b +2: + ld1 {v3.16b}, [x2], #16 // top + shll v20.8h, v4.8b, #8 // bottom*256 + shll v21.8h, v4.8b, #8 + shll v22.8h, v4.8b, #8 + shll v23.8h, v4.8b, #8 + shll v24.8h, v4.8b, #8 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + usubl v2.8h, v3.8b, v4.8b // top-bottom + usubl2 v3.8h, v3.16b, v4.16b + mla v20.8h, v2.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v21.8h, v3.8h, v16.8h + mla v22.8h, v2.8h, v17.8h + mla v23.8h, v3.8h, v17.8h + mla v24.8h, v2.8h, v18.8h + mla v25.8h, v3.8h, v18.8h + mla v26.8h, v2.8h, v19.8h + mla v27.8h, v3.8h, v19.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + rshrn v24.8b, v24.8h, #8 + rshrn2 v24.16b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn2 v26.16b, v27.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v24.16b}, [x5], #16 + st1 {v26.16b}, [x8], #16 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x2, x2, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x8, x8, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_v_tbl): + .hword L(ipred_smooth_v_tbl) - 640b + .hword L(ipred_smooth_v_tbl) - 320b + .hword L(ipred_smooth_v_tbl) - 160b + .hword L(ipred_smooth_v_tbl) - 80b + .hword L(ipred_smooth_v_tbl) - 40b +endfunc + +// void ipred_smooth_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_8bpc_neon, export=1 + movrel x8, X(sm_weights) + add x8, x8, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_h_tbl) + add x12, x2, w3, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v5.16b}, [x12] // right + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v7.2s}, [x8] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + uxtl v7.8h, v7.8b // weights_hor +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + zip1 v1.2s, v1.2s, v0.2s // left, flipped + zip1 v0.2s, v3.2s, v2.2s + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + mla v20.8h, v0.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v7.8b}, [x8] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + uxtl v7.8h, v7.8b // weights_hor +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + usubl v3.8h, v3.8b, v5.8b // left-right + usubl v2.8h, v2.8b, v5.8b + usubl v1.8h, v1.8b, v5.8b + usubl v0.8h, v0.8b, v5.8b + mla v20.8h, v3.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v2.8h, v7.8h // (left flipped) + mla v22.8h, v1.8h, v7.8h + mla v23.8h, v0.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v20.8b}, [x0], x1 + st1 {v21.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + sub x2, x2, #4 + mov x7, #-4 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + usubl v2.8h, v2.8b, v5.8b + usubl v3.8h, v3.8b, v5.8b +2: + ld1 {v7.16b}, [x8], #16 // weights_hor + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + shll v24.8h, v5.8b, #8 + shll v25.8h, v5.8b, #8 + shll v26.8h, v5.8b, #8 + shll v27.8h, v5.8b, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + mla v20.8h, v3.8h, v6.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v3.8h, v7.8h // (left flipped) + mla v22.8h, v2.8h, v6.8h + mla v23.8h, v2.8h, v7.8h + mla v24.8h, v1.8h, v6.8h + mla v25.8h, v1.8h, v7.8h + mla v26.8h, v0.8h, v6.8h + mla v27.8h, v0.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + rshrn v24.8b, v24.8h, #8 + rshrn2 v24.16b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn2 v26.16b, v27.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v24.16b}, [x5], #16 + st1 {v26.16b}, [x10], #16 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_h_tbl): + .hword L(ipred_smooth_h_tbl) - 640b + .hword L(ipred_smooth_h_tbl) - 320b + .hword L(ipred_smooth_h_tbl) - 160b + .hword L(ipred_smooth_h_tbl) - 80b + .hword L(ipred_smooth_h_tbl) - 40b +endfunc + +const padding_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +padding_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void ipred_z1_upsample_edge_8bpc_neon(pixel *out, const int hsz, +// const pixel *const in, const int end); +function ipred_z1_upsample_edge_8bpc_neon, export=1 + movrel x4, padding_mask + ld1 {v0.16b}, [x2] // in[] + add x5, x2, w3, uxtw // in[end] + sub x4, x4, w3, uxtw + + ld1r {v1.16b}, [x5] // padding + ld1 {v3.16b}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v1.16b, v3.16b // padded in[] + + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + + uaddl v16.8h, v4.8b, v5.8b // in[i+1] + in[i+2] + uaddl2 v17.8h, v4.16b, v5.16b + uaddl v18.8h, v0.8b, v6.8b // in[i+0] + in[i+3] + uaddl2 v19.8h, v0.16b, v6.16b + mul v16.8h, v16.8h, v31.8h // 9*(in[i+1] + in[i+2]) + mul v17.8h, v17.8h, v31.8h + sub v16.8h, v16.8h, v18.8h + sub v17.8h, v17.8h, v19.8h + + sqrshrun v16.8b, v16.8h, #4 + sqrshrun2 v16.16b, v17.8h, #4 + + zip1 v0.16b, v4.16b, v16.16b + zip2 v1.16b, v4.16b, v16.16b + + st1 {v0.16b, v1.16b}, [x0] + + ret +endfunc + +// void ipred_z2_upsample_edge_8bpc_neon(pixel *out, const int sz, +// const pixel *const in); +function ipred_z2_upsample_edge_8bpc_neon, export=1 + // Here, sz is 4 or 8, and we produce 2*sz+1 output elements. + movrel x4, padding_mask + ld1 {v0.16b}, [x2] // in[] + add x5, x2, w1, uxtw // in[sz] + sub x4, x4, w1, uxtw + + ld1r {v2.16b}, [x2] // in[0] for padding + ld1r {v1.16b}, [x5] // padding + ld1 {v3.16b}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v1.16b, v3.16b // padded in[] + + ext v4.16b, v2.16b, v0.16b, #15 + ext v5.16b, v0.16b, v1.16b, #1 + ext v6.16b, v0.16b, v1.16b, #2 + + uaddl v16.8h, v0.8b, v5.8b // in[i+0] + in[i+1] + uaddl v18.8h, v4.8b, v6.8b // in[i-1] + in[i+2] + mul v16.8h, v16.8h, v31.8h // 9*(in[i+1] + in[i+2]) + sub v16.8h, v16.8h, v18.8h + + sqrshrun v16.8b, v16.8h, #4 + + add x5, x0, #16 + + zip1 v2.16b, v0.16b, v16.16b + + st1 {v1.b}[0], [x5] + // In case sz=8, output one single pixel in out[16]. + st1 {v2.16b}, [x0] + + ret +endfunc + +const edge_filter + .byte 0, 4, 8, 0 + .byte 0, 5, 6, 0 +// Leaving out the coeffs for strength=3 +// .byte 2, 4, 4, 0 +endconst + +// void ipred_z1_filter_edge_8bpc_neon(pixel *out, const int sz, +// const pixel *const in, const int end, +// const int strength); +function ipred_z1_filter_edge_8bpc_neon, export=1 + cmp w4, #3 + b.eq L(fivetap) // if (strength == 3) goto fivetap + + movrel x5, edge_filter, -3 + add x5, x5, w4, uxtw #2 // edge_filter + (strength - 1)*4 + 1 + + ld1 {v31.h}[0], [x5] // kernel[1-2] + + ld1 {v0.16b}, [x2], #16 + + dup v30.16b, v31.b[0] + dup v31.16b, v31.b[1] +1: + // in[end], is the last valid pixel. We produce 16 pixels out by + // using 18 pixels in - the last pixel used is [17] of the ones + // read/buffered. + cmp w3, #17 + ld1 {v1.16b}, [x2], #16 + b.lt 2f + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + umull v4.8h, v0.8b, v30.8b + umlal v4.8h, v2.8b, v31.8b + umlal v4.8h, v3.8b, v30.8b + umull2 v5.8h, v0.16b, v30.16b + umlal2 v5.8h, v2.16b, v31.16b + umlal2 v5.8h, v3.16b, v30.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + rshrn v4.8b, v4.8h, #4 + rshrn2 v4.16b, v5.8h, #4 + sub w3, w3, #16 + st1 {v4.16b}, [x0], #16 + b.gt 1b + ret +2: + // Right padding + + // x2[w3-32] is the padding pixel (x2 points 32 bytes ahead) + movrel x5, padding_mask + sub w6, w3, #32 + sub x5, x5, w3, uxtw + add x6, x2, w6, sxtw + + ld1 {v2.16b}, [x5] // padding_mask + + ld1r {v1.16b}, [x6] + bit v0.16b, v1.16b, v2.16b // Pad v0-v1 + + // Filter one block + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + umull v4.8h, v0.8b, v30.8b + umlal v4.8h, v2.8b, v31.8b + umlal v4.8h, v3.8b, v30.8b + umull2 v5.8h, v0.16b, v30.16b + umlal2 v5.8h, v2.16b, v31.16b + umlal2 v5.8h, v3.16b, v30.16b + subs w1, w1, #16 + rshrn v4.8b, v4.8h, #4 + rshrn2 v4.16b, v5.8h, #4 + st1 {v4.16b}, [x0], #16 + b.le 9f +5: + // After one block, any remaining output would only be filtering + // padding - thus just store the padding. + subs w1, w1, #16 + st1 {v1.16b}, [x0], #16 + b.gt 5b +9: + ret + +L(fivetap): + sub x2, x2, #1 // topleft -= 1 + movi v29.16b, #2 + ld1 {v0.16b}, [x2], #16 + movi v30.16b, #4 + movi v31.16b, #4 + ins v0.b[0], v0.b[1] +1: + // in[end+1], is the last valid pixel. We produce 16 pixels out by + // using 20 pixels in - the last pixel used is [19] of the ones + // read/buffered. + cmp w3, #18 + ld1 {v1.16b}, [x2], #16 + b.lt 2f // if (end + 1 < 19) + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v0.16b, v1.16b, #3 + ext v5.16b, v0.16b, v1.16b, #4 + umull v6.8h, v0.8b, v29.8b + umlal v6.8h, v2.8b, v30.8b + umlal v6.8h, v3.8b, v31.8b + umlal v6.8h, v4.8b, v30.8b + umlal v6.8h, v5.8b, v29.8b + umull2 v7.8h, v0.16b, v29.16b + umlal2 v7.8h, v2.16b, v30.16b + umlal2 v7.8h, v3.16b, v31.16b + umlal2 v7.8h, v4.16b, v30.16b + umlal2 v7.8h, v5.16b, v29.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + rshrn v6.8b, v6.8h, #4 + rshrn2 v6.16b, v7.8h, #4 + sub w3, w3, #16 + st1 {v6.16b}, [x0], #16 + b.gt 1b + ret +2: + // Right padding + + // x2[w3+1-32] is the padding pixel (x2 points 32 bytes ahead) + movrel x5, padding_mask, -1 + sub w6, w3, #31 + sub x5, x5, w3, uxtw + add x6, x2, w6, sxtw + + ld1 {v2.16b, v3.16b}, [x5] // padding_mask + + ld1r {v28.16b}, [x6] + bit v0.16b, v28.16b, v2.16b // Pad v0-v1 + bit v1.16b, v28.16b, v3.16b +4: + // Filter one block + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v0.16b, v1.16b, #3 + ext v5.16b, v0.16b, v1.16b, #4 + umull v6.8h, v0.8b, v29.8b + umlal v6.8h, v2.8b, v30.8b + umlal v6.8h, v3.8b, v31.8b + umlal v6.8h, v4.8b, v30.8b + umlal v6.8h, v5.8b, v29.8b + umull2 v7.8h, v0.16b, v29.16b + umlal2 v7.8h, v2.16b, v30.16b + umlal2 v7.8h, v3.16b, v31.16b + umlal2 v7.8h, v4.16b, v30.16b + umlal2 v7.8h, v5.16b, v29.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + mov v1.16b, v28.16b + rshrn v6.8b, v6.8h, #4 + rshrn2 v6.16b, v7.8h, #4 + sub w3, w3, #16 + st1 {v6.16b}, [x0], #16 + b.le 9f + // v0-v1[w3+1] is the last valid pixel; if (w3 + 1 > 0) we need to + // filter properly once more - aka (w3 >= 0). + cmp w3, #0 + b.ge 4b +5: + // When w3 <= 0, all remaining pixels in v0-v1 are equal to the + // last valid pixel - thus just output that without filtering. + subs w1, w1, #16 + st1 {v1.16b}, [x0], #16 + b.gt 5b +9: + ret +endfunc + +// void ipred_pixel_set_8bpc_neon(pixel *out, const pixel px, +// const int n); +function ipred_pixel_set_8bpc_neon, export=1 + dup v0.16b, w1 +1: + subs w2, w2, #16 + st1 {v0.16b}, [x0], #16 + b.gt 1b + ret +endfunc + +// void ipred_z1_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const int width, const int height, +// const int dx, const int max_base_x); +function ipred_z1_fill1_8bpc_neon, export=1 + clz w9, w3 + adr x8, L(ipred_z1_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw // top[max_base_x] + sub x8, x8, w9, uxtw + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + br x8 +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + ldr d0, [x2, w8, uxtw] // top[base] + ldr d2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + ext v1.8b, v0.8b, v0.8b, #1 // top[base+1] + ext v3.8b, v2.8b, v2.8b, #1 + usubl v6.8h, v1.8b, v0.8b // top[base+1]-top[base] + usubl v7.8h, v3.8b, v2.8b + ushll v16.8h, v0.8b, #6 // top[base]*64 + ushll v17.8h, v2.8b, #6 + mla v16.4h, v6.4h, v4.4h // + top[base+1]*frac + mla v17.4h, v7.4h, v5.4h + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.s}[0], [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.s}[0], [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v31.s}[0], [x0], x1 + b.gt 49b + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.8b, w9 // frac + dup v5.8b, w11 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8b, w9 // 64 - frac + dup v7.8b, w11 + ext v1.16b, v0.16b, v0.16b, #1 // top[base+1] + ext v3.16b, v2.16b, v2.16b, #1 + umull v16.8h, v0.8b, v6.8b // top[base]*(64-frac) + umlal v16.8h, v1.8b, v4.8b // + top[base+1]*frac + umull v17.8h, v2.8b, v7.8b + umlal v17.8h, v3.8b, v5.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8b}, [x0], x1 + b.gt 89b + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + mov w12, w3 + + add x13, x0, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 169f + add x8, x2, w8, uxtw + add x10, x2, w10, uxtw + dup v4.16b, w9 // frac + dup v5.16b, w11 + ld1 {v0.16b, v1.16b}, [x8], #32 // top[base] + ld1 {v2.16b, v3.16b}, [x10], #32 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.16b, w9 // 64 - frac + dup v7.16b, w11 + add w7, w7, w5 // xpos += dx +2: + ext v16.16b, v0.16b, v1.16b, #1 // top[base+1] + ext v17.16b, v2.16b, v3.16b, #1 + subs w3, w3, #16 + umull v18.8h, v0.8b, v6.8b // top[base]*(64-frac) + umlal v18.8h, v16.8b, v4.8b // + top[base+1]*frac + umull2 v19.8h, v0.16b, v6.16b + umlal2 v19.8h, v16.16b, v4.16b + umull v20.8h, v2.8b, v7.8b + umlal v20.8h, v17.8b, v5.8b + umull2 v21.8h, v2.16b, v7.16b + umlal2 v21.8h, v17.16b, v5.16b + rshrn v16.8b, v18.8h, #6 + rshrn2 v16.16b, v19.8h, #6 + rshrn v17.8b, v20.8h, #6 + rshrn2 v17.16b, v21.8h, #6 + st1 {v16.16b}, [x0], #16 + st1 {v17.16b}, [x13], #16 + b.le 3f + mov v0.16b, v1.16b + ld1 {v1.16b}, [x8], #16 // top[base] + mov v2.16b, v3.16b + ld1 {v3.16b}, [x10], #16 + b 2b + +3: + subs w4, w4, #2 + b.le 9f + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 1b +9: + ret + +169: + st1 {v31.16b}, [x0], #16 + subs w3, w3, #16 + st1 {v31.16b}, [x13], #16 + b.gt 169b + subs w4, w4, #2 + b.le 9b + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 169b + +L(ipred_z1_fill1_tbl): + .hword L(ipred_z1_fill1_tbl) - 640b + .hword L(ipred_z1_fill1_tbl) - 320b + .hword L(ipred_z1_fill1_tbl) - 160b + .hword L(ipred_z1_fill1_tbl) - 80b + .hword L(ipred_z1_fill1_tbl) - 40b +endfunc + +function ipred_z1_fill2_8bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // top[max_base_x] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + b.eq 8f + +4: // w == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + ldr d0, [x2, w8, uxtw] // top[base] + ldr d2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8b, v0.8b, v0.8b // top[base+1] + uzp1 v0.8b, v0.8b, v0.8b // top[base] + uzp2 v3.8b, v2.8b, v2.8b + uzp1 v2.8b, v2.8b, v2.8b + usubl v6.8h, v1.8b, v0.8b // top[base+1]-top[base] + usubl v7.8h, v3.8b, v2.8b + ushll v16.8h, v0.8b, #6 // top[base]*64 + ushll v17.8h, v2.8b, #6 + mla v16.4h, v6.4h, v4.4h // + top[base+1]*frac + mla v17.4h, v7.4h, v5.4h + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.s}[0], [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.s}[0], [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v31.s}[0], [x0], x1 + b.gt 49b + ret + +8: // w == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.8b, w9 // frac + dup v5.8b, w11 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8b, w9 // 64 - frac + dup v7.8b, w11 + uzp2 v1.16b, v0.16b, v0.16b // top[base+1] + uzp1 v0.16b, v0.16b, v0.16b // top[base] + uzp2 v3.16b, v2.16b, v2.16b + uzp1 v2.16b, v2.16b, v2.16b + umull v16.8h, v1.8b, v4.8b // top[base+1]*frac + umlal v16.8h, v0.8b, v6.8b // + top[base]*(64-frac) + umull v17.8h, v3.8b, v5.8b + umlal v17.8h, v2.8b, v7.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8b}, [x0], x1 + b.gt 89b + ret +endfunc + +// void ipred_reverse_8bpc_neon(pixel *dst, const pixel *const src, +// const int n); +function ipred_reverse_8bpc_neon, export=1 + sub x1, x1, #16 + add x3, x0, #8 + mov x4, #16 +1: + ld1 {v0.16b}, [x1] + subs w2, w2, #16 + rev64 v0.16b, v0.16b + sub x1, x1, #16 + st1 {v0.d}[1], [x0], x4 + st1 {v0.d}[0], [x3], x4 + b.gt 1b + ret +endfunc + +const increments + .short 0, 1, 2, 3, 4, 5, 6, 7 + .short 8, 9, 10, 11, 12, 13, 14, 15 +endconst + +// void ipred_z2_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const pixel *const left, +// const int width, const int height, +// const int dx, const int dy); +function ipred_z2_fill1_8bpc_neon, export=1 + clz w10, w4 + adr x9, L(ipred_z2_fill1_tbl) + sub w10, w10, #25 + ldrh w10, [x9, w10, uxtw #1] + mov w8, #(1 << 6) // xpos = 1 << 6 + sub x9, x9, w10, uxtw + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + + br x9 +40: + AARCH64_VALID_JUMP_TARGET + + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // Worst case height for w=4 is 16, but we need at least h+1 elements + ld1 {v0.16b, v1.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + tbl v16.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2s, v30.2s, v28.2s // base_y + 1, base_y + 2 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v29.8b, #2 +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + // Cut corners here; only doing tbl over v0 here; we only + // seem to need the last pixel, from v1, after skipping to the + // left-only codepath below. + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + ext v3.8b, v2.8b, v2.8b, #1 // top[base_x+1] + ext v5.8b, v4.8b, v4.8b, #1 + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + trn1 v2.2s, v2.2s, v4.2s // top[base_x] + trn1 v3.2s, v3.2s, v5.2s // top[base_x+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 4b + +49: + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+2] + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 49b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // Worst case height for w=8 is 32, but we need at least h+1 elements + ld1 {v0.16b, v1.16b, v2.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + add v30.8b, v29.8b, v19.8b // base_y + 2 + add v29.8b, v29.8b, v17.8b // base_y + 1 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + + movi v24.8b, #2 // 2 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + // Cut corners here; only doing tbl over v0-v1 here; we only + // seem to need the last pixel, from v2, after skipping to the + // left-only codepath below. + tbl v19.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+1] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + tbl v20.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+2] + + ext v5.16b, v4.16b, v4.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 8b + +89: + tbl v19.8b, {v0.16b, v1.16b, v2.16b}, v29.8b // left[base_y+1] + tbl v20.8b, {v0.16b, v1.16b, v2.16b}, v30.8b // left[base_y+2] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 89b + +9: + ret + +160: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + add x11, x11, #16 // increments + + dup v18.8h, w7 // -dy + movi v17.16b, #1 + add x3, x3, #1 // Skip past left[0] + + ld1 {v14.8h}, [x11] // {8,9,10,11,12,13,14,15} + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + mul v19.8h, v14.8h, v18.8h // {8,9,10,11,12,13,14,15}* -dy + movi v25.16b, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + add v18.8h, v19.8h, v18.8h + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + xtn2 v31.16b, v14.8h // {8,9,10,11,12,13,14,15} + + // Worst case height is 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x3] // left[] + ld1r {v15.16b}, [x2] // left[0] == top[0] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v16.8h // (uint8_t)ypos + xtn2 v27.16b, v18.8h + shrn v29.8b, v16.8h, #6 // ypos >> 6 + shrn2 v29.16b, v18.8h, #6 + mov v18.16b, v15.16b // left[0] + and v27.16b, v27.16b, v25.16b // frac_y + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbx v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 + add v29.16b, v29.16b, v17.16b // base_y + 1 + + sub v28.16b, v26.16b, v27.16b // 64 - frac_y + + movi v24.16b, #2 // 2 +16: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 169f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw + add x11, x2, w11, sxtw + + ld1 {v4.16b, v5.16b}, [x9] // top[base_x] + mov v19.16b, v15.16b // left[0] + ld1 {v6.16b, v7.16b}, [x11] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + mov v20.16b, v15.16b // left[0] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn v22.8b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn v17.8b, v17.8h + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + trn1 v21.2d, v21.2d, v21.2d // first base_x + trn1 v22.2d, v22.2d, v22.2d + trn1 v16.2d, v16.2d, v16.2d // (uint8_t)xpos + trn1 v17.2d, v17.2d, v17.2d + + ext v5.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + + sub v8.16b, v26.16b, v16.16b // 64 - frac_x + sub v9.16b, v26.16b, v17.16b + + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + + add v21.16b, v21.16b, v31.16b // actual base_x + add v22.16b, v22.16b, v31.16b + + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v5.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v7.8b, v17.8b + umull2 v18.8h, v6.16b, v9.16b + umlal2 v18.8h, v7.16b, v17.16b + + cmge v21.16b, v21.16b, #0 + cmge v22.16b, v22.16b, #0 + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v18.8h, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.16b}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.16b}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 + add v30.16b, v30.16b, v24.16b // base_y += 2 + b 16b + +169: + mov v19.16b, v15.16b + mov v20.16b, v15.16b + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + umull v4.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v4.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v5.8h, v18.16b, v28.16b + umlal2 v5.8h, v19.16b, v27.16b + umull v6.8h, v19.8b, v28.8b + umlal v6.8h, v20.8b, v27.8b + umull2 v7.8h, v19.16b, v28.16b + umlal2 v7.8h, v20.16b, v27.16b + + rshrn v4.8b, v4.8h, #6 + rshrn2 v4.16b, v5.8h, #6 + rshrn v5.8b, v6.8h, #6 + rshrn2 v5.16b, v7.8h, #6 + + st1 {v4.16b}, [x0], x1 + subs w5, w5, #2 + st1 {v5.16b}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 + add v30.16b, v30.16b, v24.16b // base_y += 2 + b 169b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +320: +640: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + add x11, x11, #16 // increments + + dup v25.8h, w7 // -dy + add x3, x3, #1 // Skip past left[0] + + ld1 {v14.8h}, [x11] // {8,9,10,11,12,13,14,15} + + add x13, x0, x1 // alternating row + lsl x1, x1, #1 // stride *= 2 + sub x1, x1, w4, uxtw // stride -= width + + movi v11.8h, #8 + mul v26.8h, v31.8h, v25.8h // {0,1,2,3,4,5,6,7}* -dy + add v26.8h, v26.8h, v25.8h // -= dy + mul v25.8h, v25.8h, v11.8h // -8*dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + xtn2 v31.16b, v14.8h // {8,9,10,11,12,13,14,15} + + // Worst case height is 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x3] // left[] + ld1r {v15.16b}, [x2] // left[0] == top[0] + + mov w12, w4 // orig w + neg w14, w4 // -w + +1: + mov v23.16b, v26.16b // reset ypos + + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, w14 // base_x <= -w + asr w11, w8, #6 // base_x + b.le 329f + + dup v17.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + + add x9, x2, w9, sxtw + add x11, x2, w11, sxtw + + sqshrn v21.8b, v16.8h, #6 // first base_x + sqshrn v22.8b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn v17.8b, v17.8h + + ld1 {v4.16b}, [x9], #16 // top[base_x] + ld1 {v6.16b}, [x11], #16 + + trn1 v21.2d, v21.2d, v21.2d // first base_x + trn1 v22.2d, v22.2d, v22.2d + trn1 v16.2d, v16.2d, v16.2d // (uint8_t)xpos + trn1 v17.2d, v17.2d, v17.2d + + movi v10.16b, #0x3e + movi v11.16b, #64 + + and v16.16b, v16.16b, v10.16b // frac_x + and v17.16b, v17.16b, v10.16b + + sub v8.16b, v11.16b, v16.16b // 64 - frac_x + sub v9.16b, v11.16b, v17.16b + + add v21.16b, v21.16b, v31.16b // actual base_x + add v22.16b, v22.16b, v31.16b + +2: + add v13.8h, v23.8h, v25.8h // ypos -= 8*dy + movi v12.16b, #64 + movi v20.16b, #2 + movi v10.16b, #0x3e + + smov w10, v22.b[0] + + xtn v27.8b, v23.8h // (uint8_t)ypos + xtn2 v27.16b, v13.8h + shrn v29.8b, v23.8h, #6 // ypos >> 6 + shrn2 v29.16b, v13.8h, #6 + cmp w10, #0 // base_x (bottom left) >= 0 + and v27.16b, v27.16b, v10.16b // frac_y + + mov v18.16b, v15.16b // left[0] + + b.ge 4f + + add v23.8h, v13.8h, v25.8h // ypos -= 8*dy + movi v13.16b, #1 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v13.16b // base_y + 1 + mov v19.16b, v15.16b // left[0] + + sub v28.16b, v12.16b, v27.16b // 64 - frac_y + + ld1 {v5.16b}, [x9], #16 // top[base_x] + ld1 {v7.16b}, [x11], #16 + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v13.16b // base_y + 2 + + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + ext v18.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #1 + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v18.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v18.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v19.8b, v17.8b + umull2 v20.8h, v6.16b, v9.16b + umlal2 v20.8h, v19.16b, v17.16b + + cmge v18.16b, v21.16b, #0 + cmge v19.16b, v22.16b, #0 + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v20.8h, #6 + + bit v10.16b, v12.16b, v18.16b + bit v11.16b, v13.16b, v19.16b + + st1 {v10.16b}, [x0], #16 + subs w4, w4, #16 + st1 {v11.16b}, [x13], #16 + b.le 3f + + movi v10.16b, #16 + mov v4.16b, v5.16b + mov v6.16b, v7.16b + add v21.16b, v21.16b, v10.16b // base_x += 16 + add v22.16b, v22.16b, v10.16b + b 2b + +3: + subs w5, w5, #2 + b.le 9f + movi v10.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + mov w4, w12 // reset w + add v26.8h, v26.8h, v10.8h // ypos += 2*(1<<6) + b 1b + +4: // The rest of the row only predicted from top[] + ld1 {v5.16b}, [x9], #16 // top[base_x] + ld1 {v7.16b}, [x11], #16 + + ext v18.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #1 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v18.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v18.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v19.8b, v17.8b + umull2 v20.8h, v6.16b, v9.16b + umlal2 v20.8h, v19.16b, v17.16b + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v20.8h, #6 + + st1 {v12.16b}, [x0], #16 + subs w4, w4, #16 + st1 {v13.16b}, [x13], #16 + b.le 3b + + mov v4.16b, v5.16b + mov v6.16b, v7.16b + b 4b + +329: // The rest of the block only predicted from left[] + add x1, x1, w4, uxtw // restore stride + mov w12, w5 // orig remaining h +1: + add v13.8h, v23.8h, v25.8h // ypos -= 8*dy + movi v12.16b, #64 + movi v10.16b, #0x3e + + xtn v27.8b, v23.8h // (uint8_t)ypos + xtn2 v27.16b, v13.8h + shrn v29.8b, v23.8h, #6 // ypos >> 6 + shrn2 v29.16b, v13.8h, #6 + and v27.16b, v27.16b, v10.16b // frac_y + + mov v18.16b, v15.16b // left[0] + add v23.8h, v13.8h, v25.8h // ypos -= 8*dy + movi v21.16b, #1 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v21.16b // base_y + 1 + + sub v28.16b, v12.16b, v27.16b // 64 - frac_y +2: + mov v19.16b, v15.16b // left[0] + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v21.16b // base_y + 2 + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + add v29.16b, v29.16b, v21.16b // next base_y + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + st1 {v10.16b}, [x0], x1 + subs w5, w5, #2 + st1 {v11.16b}, [x13], x1 + b.le 3f + mov v18.16b, v20.16b + b 2b + +3: + subs w4, w4, #16 + b.le 9f + + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w5, w12 // reset h + b 1b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +L(ipred_z2_fill1_tbl): + .hword L(ipred_z2_fill1_tbl) - 640b + .hword L(ipred_z2_fill1_tbl) - 320b + .hword L(ipred_z2_fill1_tbl) - 160b + .hword L(ipred_z2_fill1_tbl) - 80b + .hword L(ipred_z2_fill1_tbl) - 40b +endfunc + +function ipred_z2_fill2_8bpc_neon, export=1 + cmp w4, #8 + mov w8, #(2 << 6) // xpos = 2 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + tbl v16.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2s, v30.2s, v28.2s // base_y + 1, base_y + 2 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v29.8b, #2 + add v31.8b, v31.8b, v31.8b // {0,2,4,6,0,2,4,6} +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + uzp2 v3.8b, v2.8b, v4.8b // top[base_x+1] + uzp1 v2.8b, v2.8b, v4.8b // top[base_x] + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 4b + +49: + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 49b + +9: + ret + +80: + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + add v30.8b, v29.8b, v19.8b // base_y + 2 + add v29.8b, v29.8b, v17.8b // base_y + 1 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + + movi v24.8b, #2 // 2 + add v31.16b, v31.16b, v31.16b // {0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14} +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + tbl v19.8b, {v0.16b}, v29.8b // left[base_y+1] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + tbl v20.8b, {v0.16b}, v30.8b // left[base_y+2] + + uzp2 v5.16b, v4.16b, v6.16b // top[base_x+1] + uzp1 v4.16b, v4.16b, v6.16b // top[base_x] + + and v16.16b, v16.16b, v25.16b // frac_x + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 8b + +89: + tbl v19.8b, {v0.16b}, v29.8b // left[base_y+1] + tbl v20.8b, {v0.16b}, v30.8b // left[base_y+2] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 89b + +9: + ret +endfunc + +function ipred_z2_fill3_8bpc_neon, export=1 + cmp w4, #8 + mov w8, #(1 << 6) // xpos = 1 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.16b, v1.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + add v24.8b, v30.8b, v19.8b // base_y + 3 + + trn1 v29.2s, v29.2s, v28.2s // base_y + 0, base_y + 2 + trn1 v30.2s, v30.2s, v24.2s // base_y + 1, base_y + 3 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v24.8b, #4 +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + tbl v16.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+0], left[base_y+2] + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+3] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + ext v3.8b, v2.8b, v2.8b, #1 // top[base_x+1] + ext v5.8b, v4.8b, v4.8b, #1 + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v2.2s, v2.2s, v4.2s // top[base_x] + trn1 v3.2s, v3.2s, v5.2s // top[base_x+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + add v29.8b, v29.8b, v24.8b // base_y += 4 + add v30.8b, v30.8b, v24.8b // base_y += 4 + b 4b + +49: + tbl v16.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+0], left[base_y+2] + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+3] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + add v29.8b, v29.8b, v24.8b // base_y += 4 + add v30.8b, v30.8b, v24.8b // base_y += 4 + b 49b + +9: + ret + +80: + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.16b, v1.16b, v2.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + add v28.8b, v29.8b, v17.8b // base_y + 1 + add v30.8b, v29.8b, v19.8b // base_y + 2 + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + add v24.8b, v28.8b, v19.8b // base_y + 3 + + trn1 v29.2d, v29.2d, v30.2d // base_y + 0, base_y + 2 + trn1 v30.2d, v28.2d, v24.2d // base_y + 1, base_y + 3 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + movi v24.16b, #4 + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + ext v5.16b, v4.16b, v4.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v17.8h, v18.16b, v28.16b + umlal2 v17.8h, v19.16b, v27.16b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 + add v30.16b, v30.16b, v24.16b // base_y += 4 + b 8b + +89: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v17.8h, v18.16b, v28.16b + umlal2 v17.8h, v19.16b, v27.16b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 + add v30.16b, v30.16b, v24.16b // base_y += 4 + b 89b + +9: + ret +endfunc + + +// void ipred_z3_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const left, +// const int width, const int height, +// const int dy, const int max_base_y); +function ipred_z3_fill1_8bpc_neon, export=1 + cmp w6, #64 + clz w9, w3 + adr x8, L(ipred_z3_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw // left[max_base_y] + sub x8, x8, w9, uxtw + movrel x11, increments + ld1r {v31.16b}, [x10] // padding + ld1 {v30.8h}, [x11] // increments + mov w7, w5 + b.gt L(ipred_z3_fill1_large_h16) + br x8 + +40: + AARCH64_VALID_JUMP_TARGET + dup v29.4h, w5 // dy + + mul v30.4h, v30.4h, v29.4h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is width+height-1, for w=4, h=16, <= 32 + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.4h, v29.4h, v30.4h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + mov v4.8b, v31.8b + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + + tbx v4.8b, {v0.16b, v1.16b}, v26.8b // left[base] + + trn1 v27.2s, v27.2s, v28.2s // base + 1, base + 2 + trn1 v24.2s, v24.2s, v24.2s // frac + trn1 v25.2s, v25.2s, v25.2s // 64 - frac +1: + mov v5.8b, v31.8b + tbx v5.8b, {v0.16b, v1.16b}, v27.8b // left[base+1], left[base+2] + + trn1 v4.2s, v4.2s, v5.2s // left[base], left[base+1] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + rshrn v16.8b, v16.8h, #6 + st1 {v16.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v4.8b, v5.8b, v5.8b, #4 + uqadd v27.8b, v27.8b, v21.8b // base += 2 + b 1b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + dup v29.8h, w5 // dy + + mul v30.8h, v30.8h, v29.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is width+height-1, for w=8, h=32, <= 48 + ld1 {v0.16b, v1.16b, v2.16b}, [x2] // left[] + add v30.8h, v29.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + mov v4.8b, v31.8b + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + + tbx v4.8b, {v0.16b, v1.16b, v2.16b}, v26.8b // left[base] +1: + mov v5.8b, v31.8b + mov v6.8b, v31.8b + tbx v5.8b, {v0.16b, v1.16b, v2.16b}, v27.8b // left[base+1] + tbx v6.8b, {v0.16b, v1.16b, v2.16b}, v28.8b // left[base+2] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull v17.8h, v5.8b, v25.8b + umlal v17.8h, v6.8b, v24.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.le 9f + + mov v4.8b, v6.8b + uqadd v27.8b, v27.8b, v21.8b // base += 2 + uqadd v28.8b, v28.8b, v21.8b // base += 2 + b 1b + +9: + ret + +160: + AARCH64_VALID_JUMP_TARGET + dup v28.8h, w5 // dy + + shl v29.8h, v28.8h, #3 // 8*dy + mul v30.8h, v30.8h, v28.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // This is only executed if we've checked that max_base_y <= 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] // left[] + add v28.8h, v28.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + add v29.8h, v28.8h, v29.8h // ypos + 8*dy + + xtn v24.8b, v28.8h // (uint8_t)ypos + xtn2 v24.16b, v29.8h + uqshrn v26.8b, v28.8h, #6 // base + uqshrn2 v26.16b, v29.8h, #6 + and v24.16b, v24.16b, v23.16b // frac + + mov v4.16b, v31.16b + uqadd v27.16b, v26.16b, v20.16b // base + 1 + uqadd v28.16b, v26.16b, v21.16b // base + 2 + sub v25.16b, v22.16b, v24.16b // 64 - frac + + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v26.16b // left[base] +1: + mov v5.16b, v31.16b + mov v6.16b, v31.16b + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v27.16b // left[base+1] + tbx v6.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v28.16b // left[base+2] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + umull v18.8h, v5.8b, v25.8b + umlal v18.8h, v6.8b, v24.8b + umull2 v19.8h, v5.16b, v25.16b + umlal2 v19.8h, v6.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn2 v16.16b, v17.8h, #6 + rshrn v17.8b, v18.8h, #6 + rshrn2 v17.16b, v19.8h, #6 + st1 {v16.16b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.16b}, [x0], x1 + b.le 9f + + mov v4.16b, v6.16b + uqadd v27.16b, v27.16b, v21.16b // base += 2 + uqadd v28.16b, v28.16b, v21.16b // base += 2 + b 1b + +9: + ret +320: +640: + AARCH64_VALID_JUMP_TARGET + dup v28.8h, w5 // dy + mov w12, w3 + + add x13, x0, x1 + + shl v29.8h, v28.8h, #3 // 8*dy + mul v30.8h, v30.8h, v28.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + add v30.8h, v28.8h, v30.8h // ypos + + // This is only executed if we've checked that max_base_y <= 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] // left[] + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + +1: + mov v26.16b, v30.16b // reset ypos + +2: + add v27.8h, v26.8h, v29.8h // ypos + 8*dy + uqshrn v16.8b, v26.8h, #6 // base + uqshrn2 v16.16b, v27.8h, #6 + xtn v24.8b, v26.8h // (uint8_t)ypos + xtn2 v24.16b, v27.8h + umov w14, v16.b[0] + and v24.16b, v24.16b, v23.16b // frac + + uqadd v17.16b, v16.16b, v20.16b // base + 1 + cmp w14, w6 // base >= max_base_y + uqadd v18.16b, v16.16b, v21.16b // base + 2 + sub v25.16b, v22.16b, v24.16b // 64 - frac + + b.ge 4f + + mov v4.16b, v31.16b + mov v5.16b, v31.16b + mov v6.16b, v31.16b + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v16.16b // left[base] + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v17.16b // left[base+1] + tbx v6.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v18.16b // left[base+2] + + subs w3, w3, #16 + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + umull v18.8h, v5.8b, v25.8b + umlal v18.8h, v6.8b, v24.8b + umull2 v19.8h, v5.16b, v25.16b + umlal2 v19.8h, v6.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn2 v16.16b, v17.8h, #6 + rshrn v17.8b, v18.8h, #6 + rshrn2 v17.16b, v19.8h, #6 + st1 {v16.16b}, [x0], #16 + st1 {v17.16b}, [x13], #16 + b.le 3f + add v26.8h, v27.8h, v29.8h // ypos += 16*dy + b 2b + +3: + subs w4, w4, #2 + b.le 9f + movi v16.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + add v30.8h, v30.8h, v16.8h // ypos = dy + y*(1<<6)*2 + mov w3, w12 + b 1b + +4: + subs w3, w3, #16 + st1 {v31.16b}, [x0], #16 + st1 {v31.16b}, [x13], #16 + b.gt 4b + b 3b + +9: + ret + +L(ipred_z3_fill1_large_h16): + // Fallback case for max_base_y > 64; similar to the z1 + // implementation. This does the filtering vertically, filling out + // a 2x pixel column at a time. + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + + mov w12, w4 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // ypos += dy + cmp w8, w6 // base >= max_base_y + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw + add x10, x2, w10, uxtw + dup v4.16b, w9 // frac + dup v5.16b, w11 + ld1 {v0.16b, v1.16b}, [x8], #32 // left[base] + ld1 {v2.16b, v3.16b}, [x10], #32 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.16b, w9 // 64 - frac + dup v7.16b, w11 + add w7, w7, w5 // ypos += dy +2: + ext v16.16b, v0.16b, v1.16b, #1 // left[base+1] + ext v17.16b, v2.16b, v3.16b, #1 + subs w4, w4, #16 + umull v18.8h, v16.8b, v4.8b // left[base+1]*frac + umlal v18.8h, v0.8b, v6.8b // + left[base]*(64-frac) + umull2 v19.8h, v16.16b, v4.16b + umlal2 v19.8h, v0.16b, v6.16b + umull v20.8h, v17.8b, v5.8b + umlal v20.8h, v2.8b, v7.8b + umull2 v21.8h, v17.16b, v5.16b + umlal2 v21.8h, v2.16b, v7.16b + rshrn v16.8b, v18.8h, #6 + rshrn2 v16.16b, v19.8h, #6 + rshrn v17.8b, v20.8h, #6 + rshrn2 v17.16b, v21.8h, #6 + zip1 v18.16b, v16.16b, v17.16b + zip2 v19.16b, v16.16b, v17.16b + st1 {v18.h}[0], [x0], x1 + st1 {v18.h}[1], [x13], x1 + st1 {v18.h}[2], [x0], x1 + st1 {v18.h}[3], [x13], x1 + st1 {v18.h}[4], [x0], x1 + st1 {v18.h}[5], [x13], x1 + st1 {v18.h}[6], [x0], x1 + st1 {v18.h}[7], [x13], x1 + st1 {v19.h}[0], [x0], x1 + st1 {v19.h}[1], [x13], x1 + st1 {v19.h}[2], [x0], x1 + st1 {v19.h}[3], [x13], x1 + st1 {v19.h}[4], [x0], x1 + st1 {v19.h}[5], [x13], x1 + st1 {v19.h}[6], [x0], x1 + st1 {v19.h}[7], [x13], x1 + b.le 3f + mov v0.16b, v1.16b + ld1 {v1.16b}, [x8], #16 // left[base] + mov v2.16b, v3.16b + ld1 {v3.16b}, [x10], #16 + b 2b + +3: + subs w3, w3, #2 + b.le 9f + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #2 + add x13, x13, #2 + mov w4, w12 + b 1b +9: + ret + +L(ipred_z3_fill1_tbl): + .hword L(ipred_z3_fill1_tbl) - 640b + .hword L(ipred_z3_fill1_tbl) - 320b + .hword L(ipred_z3_fill1_tbl) - 160b + .hword L(ipred_z3_fill1_tbl) - 80b + .hword L(ipred_z3_fill1_tbl) - 40b +endfunc + +function ipred_z3_fill_padding_neon, export=0 + cmp w3, #16 + adr x8, L(ipred_z3_fill_padding_tbl) + b.gt L(ipred_z3_fill_padding_wide) + // w3 = remaining width, w4 = constant height + mov w12, w4 + +1: + // Fill a WxH rectangle with padding. W can be any number; + // this fills the exact width by filling in the largest + // power of two in the remaining width, and repeating. + clz w9, w3 + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + sub x9, x8, w9, uxtw + br x9 + +2: + st1 {v31.h}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.h}[0], [x13], x1 + st1 {v31.h}[0], [x0], x1 + st1 {v31.h}[0], [x13], x1 + b.gt 2b + subs w3, w3, #2 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #2 + add x13, x13, #2 + mov w4, w12 + b 1b + +4: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.s}[0], [x13], x1 + st1 {v31.s}[0], [x0], x1 + st1 {v31.s}[0], [x13], x1 + b.gt 4b + subs w3, w3, #4 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b + +8: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #4 + st1 {v31.8b}, [x13], x1 + st1 {v31.8b}, [x0], x1 + st1 {v31.8b}, [x13], x1 + b.gt 4b + subs w3, w3, #8 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #8 + add x13, x13, #8 + mov w4, w12 + b 1b + +16: +32: +64: + st1 {v31.16b}, [x0], x1 + subs w4, w4, #4 + st1 {v31.16b}, [x13], x1 + st1 {v31.16b}, [x0], x1 + st1 {v31.16b}, [x13], x1 + b.gt 4b + subs w3, w3, #16 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w4, w12 + b 1b + +9: + ret + +L(ipred_z3_fill_padding_tbl): + .hword L(ipred_z3_fill_padding_tbl) - 64b + .hword L(ipred_z3_fill_padding_tbl) - 32b + .hword L(ipred_z3_fill_padding_tbl) - 16b + .hword L(ipred_z3_fill_padding_tbl) - 8b + .hword L(ipred_z3_fill_padding_tbl) - 4b + .hword L(ipred_z3_fill_padding_tbl) - 2b + +L(ipred_z3_fill_padding_wide): + // Fill a WxH rectangle with padding, with W > 16. + lsr x1, x1, #1 + mov w12, w3 + sub x1, x1, w3, uxtw +1: + ands w5, w3, #15 + b.eq 2f + // If the width isn't aligned to 16, first do one 16 byte write + // and align the start pointer. + sub w3, w3, w5 + st1 {v31.16b}, [x0] + add x0, x0, w5, uxtw +2: + // Fill the rest of the line with aligned 16 byte writes. + subs w3, w3, #16 + st1 {v31.16b}, [x0], #16 + b.gt 2b + subs w4, w4, #1 + add x0, x0, x1 + b.le 9f + mov w3, w12 + b 1b +9: + ret +endfunc + +function ipred_z3_fill2_8bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // left[max_base_y] + movrel x11, increments + ld1r {v31.16b}, [x10] // padding + ld1 {v30.8h}, [x11] // increments + b.eq 80f + +40: // w == 4 + dup v29.4h, w5 // dy + + mul v30.4h, v30.4h, v29.4h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is 2*(width+height)-2, but width+height <= 16, + // so max_base_y <= 32. + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.4h, v29.4h, v30.4h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + uqadd v29.8b, v27.8b, v21.8b // base + 3 + + trn1 v24.2s, v24.2s, v24.2s // frac + trn1 v26.2s, v26.2s, v28.2s // base + 0, base + 2 + trn1 v27.2s, v27.2s, v29.2s // base + 1, base + 3 + trn1 v25.2s, v25.2s, v25.2s // 64 - frac + + movi v21.16b, #4 +1: + mov v4.8b, v31.8b + mov v5.8b, v31.8b + tbx v4.8b, {v0.16b, v1.16b}, v26.8b // left[base], left[base+2] + tbx v5.8b, {v0.16b, v1.16b}, v27.8b // left[base+1], left[base+3] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + rshrn v16.8b, v16.8h, #6 + st1 {v16.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + uqadd v26.8b, v26.8b, v21.8b // base += 4 + uqadd v27.8b, v27.8b, v21.8b // base += 4 + b 1b + +9: + ret + +80: // w == 8 + dup v29.8h, w5 // dy + + mul v30.8h, v30.8h, v29.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is 2*(width+height)-2, but width+height <= 16, + // so max_base_y <= 32. + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.8h, v29.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + uqadd v29.8b, v27.8b, v21.8b // base + 3 + + trn1 v24.2d, v24.2d, v24.2d // frac + trn1 v26.2d, v26.2d, v28.2d // base + 0, base + 2 + trn1 v27.2d, v27.2d, v29.2d // base + 1, base + 3 + trn1 v25.2d, v25.2d, v25.2d // 64 - frac + + movi v21.16b, #4 +1: + mov v4.16b, v31.16b + mov v5.16b, v31.16b + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v26.16b // left[base], left[base+2] + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v27.16b // left[base+1], left[base+3] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.le 9f + + uqadd v26.16b, v26.16b, v21.16b // base += 4 + uqadd v27.16b, v27.16b, v21.16b // base += 4 + b 1b + +9: + ret +endfunc + + +// void ipred_filter_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height); +function ipred_filter_8bpc_neon, export=1 + and w5, w5, #511 + movrel x6, X(filter_intra_taps) + lsl w5, w5, #6 + add x6, x6, w5, uxtw + ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x6], #32 + clz w9, w3 + adr x5, L(ipred_filter_tbl) + ld1 {v20.8b, v21.8b, v22.8b}, [x6] + sub w9, w9, #26 + ldrh w9, [x5, w9, uxtw #1] + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + sub x5, x5, w9, uxtw + sxtl v18.8h, v18.8b + sxtl v19.8h, v19.8b + add x6, x0, x1 + lsl x1, x1, #1 + sxtl v20.8h, v20.8b + sxtl v21.8h, v21.8b + sxtl v22.8h, v22.8b + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ldur s0, [x2, #1] // top (0-3) + sub x2, x2, #2 + mov x7, #-2 + uxtl v0.8h, v0.8b // top (0-3) +4: + ld1 {v1.s}[0], [x2], x7 // left (0-1) + topleft (2) + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + uxtl v1.8h, v1.8b // left (0-1) + topleft (2) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + sqrshrun v2.8b, v2.8h, #4 + subs w4, w4, #2 + st1 {v2.s}[0], [x0], x1 + uxtl v0.8h, v2.8b + st1 {v2.s}[1], [x6], x1 + ext v0.16b, v0.16b, v0.16b, #8 // move top from [4-7] to [0-3] + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ldur d0, [x2, #1] // top (0-7) + sub x2, x2, #2 + mov x7, #-2 + uxtl v0.8h, v0.8b // top (0-7) +8: + ld1 {v1.s}[0], [x2], x7 // left (0-1) + topleft (2) + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + uxtl v1.8h, v1.8b // left (0-1) + topleft (2) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + mul v3.8h, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + sqrshrun v2.8b, v2.8h, #4 + uxtl v1.8h, v2.8b // first block, in 16 bit + mla v3.8h, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + mla v3.8h, v16.8h, v0.h[3] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v1.h[3] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v1.h[7] // p6(left[1]) * filter(6) + sqrshrun v3.8b, v3.8h, #4 + subs w4, w4, #2 + st2 {v2.s, v3.s}[0], [x0], x1 + zip2 v0.2s, v2.2s, v3.2s + st2 {v2.s, v3.s}[1], [x6], x1 + uxtl v0.8h, v0.8b + b.gt 8b + ret +160: +320: + AARCH64_VALID_JUMP_TARGET + add x8, x2, #1 + sub x2, x2, #2 + mov x7, #-2 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld1 {v0.s}[0], [x2], x7 // left (0-1) + topleft (2) + uxtl v0.8h, v0.8b // left (0-1) + topleft (2) +2: + ld1 {v2.16b}, [x8], #16 // top(0-15) + mul v3.8h, v16.8h, v0.h[2] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + uxtl v1.8h, v2.8b // top(0-7) + uxtl2 v2.8h, v2.16b // top(8-15) + mla v3.8h, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + mla v3.8h, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + mla v3.8h, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + mul v4.8h, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + mla v4.8h, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + mla v4.8h, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + sqrshrun v3.8b, v3.8h, #4 + uxtl v0.8h, v3.8b // first block, in 16 bit + mla v4.8h, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + mla v4.8h, v16.8h, v1.h[3] // p0(topleft) * filter(0) + mla v4.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v4.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + mul v5.8h, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + mla v5.8h, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + mla v5.8h, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + sqrshrun v4.8b, v4.8h, #4 + uxtl v0.8h, v4.8b // second block, in 16 bit + mla v5.8h, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + mla v5.8h, v16.8h, v1.h[7] // p0(topleft) * filter(0) + mla v5.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v5.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + mul v6.8h, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + mla v6.8h, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + mla v6.8h, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + sqrshrun v5.8b, v5.8h, #4 + uxtl v0.8h, v5.8b // third block, in 16 bit + mla v6.8h, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + mla v6.8h, v16.8h, v2.h[3] // p0(topleft) * filter(0) + mla v6.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v6.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + sqrshrun v6.8b, v6.8h, #4 + + st4 {v3.s, v4.s, v5.s, v6.s}[0], [x0], #16 + st4 {v3.s, v4.s, v5.s, v6.s}[1], [x6], #16 + b.le 8f + ins v0.h[2], v2.h[7] + ins v0.b[0], v6.b[7] + ins v0.b[2], v6.b[3] + b 2b +8: + subs w4, w4, #2 + b.le 9f + sub x8, x6, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_filter_tbl): + .hword L(ipred_filter_tbl) - 320b + .hword L(ipred_filter_tbl) - 160b + .hword L(ipred_filter_tbl) - 80b + .hword L(ipred_filter_tbl) - 40b +endfunc + +// void pal_pred_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_8bpc_neon, export=1 + ld1 {v0.8h}, [x2] + clz w9, w4 + adr x6, L(pal_pred_tbl) + sub w9, w9, #25 + ldrh w9, [x6, w9, uxtw #1] + xtn v0.8b, v0.8h + sub x6, x6, w9, uxtw + add x2, x0, x1 + lsl x1, x1, #1 + br x6 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b}, [x3], #16 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + st1 {v1.s}[0], [x0], x1 + st1 {v1.s}[1], [x2], x1 + st1 {v1.s}[2], [x0], x1 + st1 {v1.s}[3], [x2], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x3], #32 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + st1 {v1.d}[0], [x0], x1 + tbl v2.16b, {v0.16b}, v2.16b + st1 {v1.d}[1], [x2], x1 + st1 {v2.d}[0], [x0], x1 + st1 {v2.d}[1], [x2], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b, v3.16b, v4.16b}, [x3], #64 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + tbl v2.16b, {v0.16b}, v2.16b + st1 {v1.16b}, [x0], x1 + tbl v3.16b, {v0.16b}, v3.16b + st1 {v2.16b}, [x2], x1 + tbl v4.16b, {v0.16b}, v4.16b + st1 {v3.16b}, [x0], x1 + st1 {v4.16b}, [x2], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x3], #64 + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x3], #64 + subs w5, w5, #4 + tbl v16.16b, {v0.16b}, v16.16b + tbl v17.16b, {v0.16b}, v17.16b + tbl v18.16b, {v0.16b}, v18.16b + tbl v19.16b, {v0.16b}, v19.16b + tbl v20.16b, {v0.16b}, v20.16b + st1 {v16.16b, v17.16b}, [x0], x1 + tbl v21.16b, {v0.16b}, v21.16b + st1 {v18.16b, v19.16b}, [x2], x1 + tbl v22.16b, {v0.16b}, v22.16b + st1 {v20.16b, v21.16b}, [x0], x1 + tbl v23.16b, {v0.16b}, v23.16b + st1 {v22.16b, v23.16b}, [x2], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x3], #64 + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x3], #64 + subs w5, w5, #2 + tbl v16.16b, {v0.16b}, v16.16b + tbl v17.16b, {v0.16b}, v17.16b + tbl v18.16b, {v0.16b}, v18.16b + tbl v19.16b, {v0.16b}, v19.16b + st1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0], x1 + tbl v20.16b, {v0.16b}, v20.16b + tbl v21.16b, {v0.16b}, v21.16b + tbl v22.16b, {v0.16b}, v22.16b + tbl v23.16b, {v0.16b}, v23.16b + st1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x2], x1 + b.gt 64b + ret + +L(pal_pred_tbl): + .hword L(pal_pred_tbl) - 64b + .hword L(pal_pred_tbl) - 32b + .hword L(pal_pred_tbl) - 16b + .hword L(pal_pred_tbl) - 8b + .hword L(pal_pred_tbl) - 4b +endfunc + +// void ipred_cfl_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_128_8bpc_neon, export=1 + clz w9, w3 + adr x7, L(ipred_cfl_128_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + movi v0.8h, #128 // dc + dup v1.8h, w6 // alpha + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 +L(ipred_cfl_splat_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x5], #32 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + cmlt v4.8h, v2.8h, #0 // sign + cmlt v5.8h, v3.8h, #0 + add v2.8h, v2.8h, v4.8h // diff + sign + add v3.8h, v3.8h, v5.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [x0], x1 + st1 {v2.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v3.s}[0], [x0], x1 + st1 {v3.s}[1], [x6], x1 + b.gt L(ipred_cfl_splat_w4) + ret +L(ipred_cfl_splat_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x5], #64 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + mul v4.8h, v4.8h, v1.8h + mul v5.8h, v5.8h, v1.8h + cmlt v16.8h, v2.8h, #0 // sign + cmlt v17.8h, v3.8h, #0 + cmlt v18.8h, v4.8h, #0 + cmlt v19.8h, v5.8h, #0 + add v2.8h, v2.8h, v16.8h // diff + sign + add v3.8h, v3.8h, v17.8h + add v4.8h, v4.8h, v18.8h + add v5.8h, v5.8h, v19.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + srshr v4.8h, v4.8h, #6 + srshr v5.8h, v5.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + add v4.8h, v4.8h, v0.8h + add v5.8h, v5.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + st1 {v2.8b}, [x0], x1 + st1 {v3.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v4.8b}, [x0], x1 + st1 {v5.8b}, [x6], x1 + b.gt L(ipred_cfl_splat_w8) + ret +L(ipred_cfl_splat_w16): + AARCH64_VALID_JUMP_TARGET + add x7, x5, w3, uxtw #1 + sub x1, x1, w3, uxtw + mov w9, w3 +1: + ld1 {v2.8h, v3.8h}, [x5], #32 + ld1 {v4.8h, v5.8h}, [x7], #32 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + mul v4.8h, v4.8h, v1.8h + mul v5.8h, v5.8h, v1.8h + cmlt v16.8h, v2.8h, #0 // sign + cmlt v17.8h, v3.8h, #0 + cmlt v18.8h, v4.8h, #0 + cmlt v19.8h, v5.8h, #0 + add v2.8h, v2.8h, v16.8h // diff + sign + add v3.8h, v3.8h, v17.8h + add v4.8h, v4.8h, v18.8h + add v5.8h, v5.8h, v19.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + srshr v4.8h, v4.8h, #6 + srshr v5.8h, v5.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + add v4.8h, v4.8h, v0.8h + add v5.8h, v5.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + subs w3, w3, #16 + st1 {v2.8b, v3.8b}, [x0], #16 + st1 {v4.8b, v5.8b}, [x6], #16 + b.gt 1b + subs w4, w4, #2 + add x5, x5, w9, uxtw #1 + add x7, x7, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b.gt 1b + ret + +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w8) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w4) +endfunc + +// void ipred_cfl_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_top_8bpc_neon, export=1 + clz w9, w3 + adr x7, L(ipred_cfl_top_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + dup v1.8h, w6 // alpha + add x2, x2, #1 + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 +4: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v2.4h, v2.4h, v3.4h + urshr v2.4h, v2.4h, #5 + dup v0.8h, v2.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_top_tbl): + .hword L(ipred_cfl_top_tbl) - 32b + .hword L(ipred_cfl_top_tbl) - 16b + .hword L(ipred_cfl_top_tbl) - 8b + .hword L(ipred_cfl_top_tbl) - 4b +endfunc + +// void ipred_cfl_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_left_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + clz w9, w3 + clz w8, w4 + adr x10, L(ipred_cfl_splat_tbl) + adr x7, L(ipred_cfl_left_tbl) + sub w9, w9, #26 + sub w8, w8, #26 + ldrh w9, [x10, w9, uxtw #1] + ldrh w8, [x7, w8, uxtw #1] + dup v1.8h, w6 // alpha + sub x9, x10, w9, uxtw + sub x7, x7, w8, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 + +L(ipred_cfl_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v2.4h, v2.4h, v3.4h + urshr v2.4h, v2.4h, #5 + dup v0.8h, v2.h[0] + br x9 + +L(ipred_cfl_left_tbl): + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h32) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h16) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h8) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h4) +endfunc + +// void ipred_cfl_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + add w8, w3, w4 // width + height + dup v1.8h, w6 // alpha + clz w9, w3 + clz w6, w4 + dup v16.8h, w8 // width + height + adr x7, L(ipred_cfl_tbl) + rbit w8, w8 // rbit(width + height) + sub w9, w9, #22 // 26 leading bits, minus table offset 4 + sub w6, w6, #26 + clz w8, w8 // ctz(width + height) + ldrh w9, [x7, w9, uxtw #1] + ldrh w6, [x7, w6, uxtw #1] + neg w8, w8 // -ctz(width + height) + sub x9, x7, w9, uxtw + sub x7, x7, w6, uxtw + ushr v16.8h, v16.8h, #1 // (width + height) >> 1 + dup v17.8h, w8 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x7 + +L(ipred_cfl_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], #4 + ins v0.s[1], wzr + add x2, x2, #1 + uaddlv h0, v0.8b + br x9 +L(ipred_cfl_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.s}[0], [x2] + ins v2.s[1], wzr + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.8b + cmp w4, #4 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x3334/2) + movk w16, #(0x5556/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], #8 + uaddlv h0, v0.8b + add x2, x2, #1 + br x9 +L(ipred_cfl_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.8b + cmp w4, #8 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2], #16 + uaddlv h0, v0.16b + add x2, x2, #1 + br x9 +L(ipred_cfl_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.16b + cmp w4, #16 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/8/32 + cmp w4, #4 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2], #32 + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add x2, x2, #1 + add v0.4h, v2.4h, v3.4h + br x9 +L(ipred_cfl_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.16b + uaddlv h3, v3.16b + cmp w4, #32 + add v0.4h, v0.4h, v2.4h + add v0.4h, v0.4h, v3.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x5556/2) + movk w16, #(0x3334/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_tbl): + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h4) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w4) +endfunc + +// void cfl_ac_420_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_420_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_420_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v0.d}[1], [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + subs w8, w8, #2 + st1 {v0.8h}, [x0], #16 + add v16.8h, v16.8h, v0.8h + b.gt 1b + trn2 v1.2d, v0.2d, v0.2d + trn2 v0.2d, v0.2d, v0.2d +L(ipred_cfl_ac_420_w4_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + b.gt 2b +3: + // Aggregate the sums + add v0.8h, v16.8h, v17.8h + uaddlv s0, v0.8h // sum + sub x0, x0, w6, uxtw #3 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x10], x2 + ld1 {v2.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v3.16b}, [x10], x2 + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + add v0.8h, v0.8h, v1.8h + add v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v2.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + b.gt 1b + mov v0.16b, v1.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v0.d}[1], [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + dup v1.4h, v0.h[3] + dup v3.4h, v0.h[7] + trn2 v2.2d, v0.2d, v0.2d + subs w8, w8, #2 + st1 {v0.4h, v1.4h, v2.4h, v3.4h}, [x0], #32 + add v16.4h, v16.4h, v0.4h + add v17.4h, v17.4h, v1.4h + add v18.4h, v18.4h, v2.4h + add v19.4h, v19.4h, v3.4h + b.gt 1b + trn1 v0.2d, v2.2d, v3.2d + trn1 v1.2d, v2.2d, v3.2d + +L(ipred_cfl_ac_420_w8_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + add v18.8h, v18.8h, v0.8h + add v19.8h, v19.8h, v1.8h + b.gt 2b +3: + +L(ipred_cfl_ac_420_w8_calc_subtract_dc): + // Aggregate the sums + add v0.8h, v16.8h, v17.8h + add v2.8h, v18.8h, v19.8h + uaddlp v0.4s, v0.8h + uaddlp v2.4s, v2.8h + add v0.4s, v0.4s, v2.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #4 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +L(ipred_cfl_ac_420_w8_subtract_dc): +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + sub v2.8h, v2.8h, v4.8h + sub v3.8h, v3.8h, v4.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_420_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_420_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.16b, v1.16b}, [x1], x2 + ld1 {v2.16b, v3.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + ld1 {v4.16b, v5.16b}, [x1], x2 + uaddlp v1.8h, v1.16b + ld1 {v6.16b, v7.16b}, [x10], x2 + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + uaddlp v4.8h, v4.16b + uaddlp v5.8h, v5.16b + uaddlp v6.8h, v6.16b + uaddlp v7.8h, v7.16b + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + add v4.8h, v4.8h, v6.8h + add v5.8h, v5.8h, v7.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v1.8h, #1 + shl v2.8h, v4.8h, #1 + shl v3.8h, v5.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr d1, [x1, #16] + ld1 {v0.16b}, [x1], x2 + ldr d3, [x10, #16] + ld1 {v2.16b}, [x10], x2 + uaddlp v1.4h, v1.8b + ldr d5, [x1, #16] + uaddlp v0.8h, v0.16b + ld1 {v4.16b}, [x1], x2 + uaddlp v3.4h, v3.8b + ldr d7, [x10, #16] + uaddlp v2.8h, v2.16b + ld1 {v6.16b}, [x10], x2 + uaddlp v5.4h, v5.8b + uaddlp v4.8h, v4.16b + uaddlp v7.4h, v7.8b + uaddlp v6.8h, v6.16b + add v1.4h, v1.4h, v3.4h + add v0.8h, v0.8h, v2.8h + add v5.4h, v5.4h, v7.4h + add v4.8h, v4.8h, v6.8h + shl v1.4h, v1.4h, #1 + shl v0.8h, v0.8h, #1 + shl v3.4h, v5.4h, #1 + shl v2.8h, v4.8h, #1 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + ld1 {v4.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v6.16b}, [x10], x2 + uaddlp v2.8h, v2.16b + uaddlp v4.8h, v4.16b + uaddlp v6.8h, v6.16b + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v2.8h, v4.8h, #1 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + ld1 {v4.8b}, [x1], x2 + uaddlp v0.4h, v0.8b + ld1 {v6.8b}, [x10], x2 + uaddlp v2.4h, v2.8b + uaddlp v4.4h, v4.8b + uaddlp v6.4h, v6.8b + add v0.4h, v0.4h, v2.4h + add v4.4h, v4.4h, v6.4h + shl v0.4h, v0.4h, #1 + shl v2.4h, v4.4h, #1 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + +L(ipred_cfl_ac_420_w16_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 2b +3: + + // Double the height and reuse the w8 summing/subtracting + lsl w6, w6, #1 + b L(ipred_cfl_ac_420_w8_calc_subtract_dc) + +L(ipred_cfl_ac_420_tbl): + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w16) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w8) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w4) + .hword 0 + +L(ipred_cfl_ac_420_w16_tbl): + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad0) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad1) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad2) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad3) +endfunc + +// void cfl_ac_422_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_422_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_422_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8b}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v1.8b}, [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + subs w8, w8, #4 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x10], x2 + ld1 {v2.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v3.16b}, [x10], x2 + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + shl v2.8h, v2.8h, #2 + shl v3.8h, v3.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8b}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v2.8b}, [x1], x2 + ld1 {v2.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v2.8h, v2.16b + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v0.h[3] + dup v5.8h, v0.h[7] + dup v6.4h, v2.h[3] + dup v7.8h, v2.h[7] + trn2 v1.2d, v0.2d, v5.2d + trn1 v0.2d, v0.2d, v4.2d + trn2 v3.2d, v2.2d, v7.2d + trn1 v2.2d, v2.2d, v6.2d + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_422_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_422_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.16b, v1.16b}, [x1], x2 + ld1 {v2.16b, v3.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + shl v2.8h, v2.8h, #2 + shl v3.8h, v3.8h, #2 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr d1, [x1, #16] + ld1 {v0.16b}, [x1], x2 + ldr d3, [x10, #16] + ld1 {v2.16b}, [x10], x2 + uaddlp v1.4h, v1.8b + uaddlp v0.8h, v0.16b + uaddlp v3.4h, v3.8b + uaddlp v2.8h, v2.16b + shl v1.4h, v1.4h, #2 + shl v0.8h, v0.8h, #2 + shl v3.4h, v3.4h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v2.8h, v2.16b + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + uaddlp v0.4h, v0.8b + uaddlp v2.4h, v2.8b + shl v0.4h, v0.4h, #2 + shl v2.4h, v2.4h, #2 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_tbl): + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w16) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w8) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w4) + .hword 0 + +L(ipred_cfl_ac_422_w16_tbl): + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad0) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad1) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad2) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad3) +endfunc + +// void cfl_ac_444_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_444_tbl) + sub w8, w8, #26 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_444_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.s}[0], [x1], x2 + ld1 {v0.s}[1], [x10], x2 + ld1 {v1.s}[0], [x1], x2 + ld1 {v1.s}[1], [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v1.8h, v1.8b, #3 + subs w8, w8, #4 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v2.8b}, [x1], x2 + ushll v0.8h, v0.8b, #3 + ld1 {v3.8b}, [x10], x2 + ushll v1.8h, v1.8b, #3 + ushll v2.8h, v2.8b, #3 + ushll v3.8h, v3.8b, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + ld1 {v4.16b}, [x1], x2 + ushll2 v1.8h, v0.16b, #3 + ushll v0.8h, v0.8b, #3 + ld1 {v6.16b}, [x10], x2 + ushll2 v3.8h, v2.16b, #3 + ushll v2.8h, v2.8b, #3 + ushll2 v5.8h, v4.16b, #3 + ushll v4.8h, v4.8b, #3 + ushll2 v7.8h, v6.16b, #3 + ushll v6.8h, v6.8b, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + mov v0.16b, v6.16b + mov v1.16b, v7.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + ld1 {v4.8b}, [x1], x2 + ld1 {v6.8b}, [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v2.8h, v2.8b, #3 + ushll v4.8h, v4.8b, #3 + ushll v6.8h, v6.8b, #3 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + dup v5.8h, v4.h[7] + dup v7.8h, v6.h[7] + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + mov v0.16b, v6.16b + mov v1.16b, v7.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_444_w32_tbl) + ldrh w3, [x7, w3, uxtw] // (w3>>1) << 1 + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_444_w32_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, without padding + ld1 {v2.16b, v3.16b}, [x1], x2 + ld1 {v6.16b, v7.16b}, [x10], x2 + ushll v0.8h, v2.8b, #3 + ushll2 v1.8h, v2.16b, #3 + ushll v2.8h, v3.8b, #3 + ushll2 v3.8h, v3.16b, #3 + ushll v4.8h, v6.8b, #3 + ushll2 v5.8h, v6.16b, #3 + ushll v6.8h, v7.8b, #3 + ushll2 v7.8h, v7.16b, #3 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 8 + ldr d2, [x1, #16] + ld1 {v1.16b}, [x1], x2 + ldr d6, [x10, #16] + ld1 {v5.16b}, [x10], x2 + ushll v2.8h, v2.8b, #3 + ushll v0.8h, v1.8b, #3 + ushll2 v1.8h, v1.16b, #3 + ushll v6.8h, v6.8b, #3 + ushll v4.8h, v5.8b, #3 + ushll2 v5.8h, v5.16b, #3 + dup v3.8h, v2.h[7] + dup v7.8h, v6.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 16 + ld1 {v1.16b}, [x1], x2 + ld1 {v5.16b}, [x10], x2 + ushll v0.8h, v1.8b, #3 + ushll2 v1.8h, v1.16b, #3 + ushll v4.8h, v5.8b, #3 + ushll2 v5.8h, v5.16b, #3 + dup v2.8h, v1.h[7] + dup v3.8h, v1.h[7] + dup v6.8h, v5.h[7] + dup v7.8h, v5.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 24 + ld1 {v0.8b}, [x1], x2 + ld1 {v4.8b}, [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v4.8h, v4.8b, #3 + dup v1.8h, v0.h[7] + dup v2.8h, v0.h[7] + dup v3.8h, v0.h[7] + dup v5.8h, v4.h[7] + dup v6.8h, v4.h[7] + dup v7.8h, v4.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + +L(ipred_cfl_ac_444_w32_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #2 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 2b +3: + + // Quadruple the height and reuse the w8 subtracting + lsl w6, w6, #2 + // Aggregate the sums, with wider intermediates earlier than in + // ipred_cfl_ac_420_w8_calc_subtract_dc. + uaddlp v0.4s, v16.8h + uaddlp v1.4s, v17.8h + uaddlp v2.4s, v18.8h + uaddlp v3.4s, v19.8h + add v0.4s, v0.4s, v1.4s + add v2.4s, v2.4s, v3.4s + add v0.4s, v0.4s, v2.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #4 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] + b L(ipred_cfl_ac_420_w8_subtract_dc) + +L(ipred_cfl_ac_444_tbl): + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w32) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w16) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w8) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w4) + +L(ipred_cfl_ac_444_w32_tbl): + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad0) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad2) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad4) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad6) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred16.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred16.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/ipred16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5639 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/asm/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height, +// const int bitdepth_max); +function ipred_dc_128_16bpc_neon, export=1 + ldr w8, [sp] + clz w3, w3 + adr x5, L(ipred_dc_128_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + dup v0.8h, w8 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + urshr v0.8h, v0.8h, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b + sub x1, x1, #64 +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_128_tbl): + .hword L(ipred_dc_128_tbl) - 640b + .hword L(ipred_dc_128_tbl) - 320b + .hword L(ipred_dc_128_tbl) - 160b + .hword L(ipred_dc_128_tbl) - 8b + .hword L(ipred_dc_128_tbl) - 4b +endfunc + +// void ipred_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_v_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #2 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] +4: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] +8: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + sub x1, x1, #64 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_v_tbl): + .hword L(ipred_v_tbl) - 640b + .hword L(ipred_v_tbl) - 320b + .hword L(ipred_v_tbl) - 160b + .hword L(ipred_v_tbl) - 80b + .hword L(ipred_v_tbl) - 40b +endfunc + +// void ipred_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_h_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + sub x2, x2, #8 + sub x5, x5, w3, uxtw + mov x7, #-8 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + st1 {v3.4h}, [x0], x1 + st1 {v2.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v1.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + stp q3, q3, [x0, #64] + stp q2, q2, [x6, #64] + stp q3, q3, [x0, #96] + stp q2, q2, [x6, #96] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + stp q1, q1, [x0, #64] + stp q0, q0, [x6, #64] + stp q1, q1, [x0, #96] + stp q0, q0, [x6, #96] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_h_tbl): + .hword L(ipred_h_tbl) - 64b + .hword L(ipred_h_tbl) - 32b + .hword L(ipred_h_tbl) - 16b + .hword L(ipred_h_tbl) - 8b + .hword L(ipred_h_tbl) - 4b +endfunc + +// void ipred_dc_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_top_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #2 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.4h, v0.h[0] +4: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] +8: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addv h0, v0.8h + urshr v2.4h, v0.4h, #4 + dup v0.8h, v2.h[0] + dup v1.8h, v2.h[0] +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #5 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #6 + sub x1, x1, #64 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_top_tbl): + .hword L(ipred_dc_top_tbl) - 640b + .hword L(ipred_dc_top_tbl) - 320b + .hword L(ipred_dc_top_tbl) - 160b + .hword L(ipred_dc_top_tbl) - 80b + .hword L(ipred_dc_top_tbl) - 40b +endfunc + +// void ipred_dc_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_16bpc_neon, export=1 + sub x2, x2, w4, uxtw #1 + clz w3, w3 + clz w7, w4 + adr x5, L(ipred_dc_left_tbl) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w7, w7, #25 + ldrh w3, [x5, w3, uxtw #1] + ldrh w7, [x5, w7, uxtw #1] + sub x3, x5, w3, uxtw + sub x5, x5, w7, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + br x3 +L(ipred_dc_left_w4): + AARCH64_VALID_JUMP_TARGET + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt L(ipred_dc_left_w4) + ret + +L(ipred_dc_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x3 +L(ipred_dc_left_w8): + AARCH64_VALID_JUMP_TARGET + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt L(ipred_dc_left_w8) + ret + +L(ipred_dc_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addv h0, v0.8h + urshr v2.4h, v0.4h, #4 + dup v0.8h, v2.h[0] + dup v1.8h, v2.h[0] + br x3 +L(ipred_dc_left_w16): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +1: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + uaddlp v0.4s, v0.8h + addv s0, v0.4s + rshrn v4.4h, v0.4s, #5 + dup v0.8h, v4.h[0] + br x3 +L(ipred_dc_left_w32): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +1: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #6 + dup v0.8h, v4.h[0] + br x3 +L(ipred_dc_left_w64): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b + sub x1, x1, #64 +1: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_tbl): + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h4) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w4) +endfunc + +// void ipred_dc_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_16bpc_neon, export=1 + sub x2, x2, w4, uxtw #1 + add w7, w3, w4 // width + height + clz w3, w3 + clz w6, w4 + dup v16.4s, w7 // width + height + adr x5, L(ipred_dc_tbl) + rbit w7, w7 // rbit(width + height) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w6, w6, #25 + clz w7, w7 // ctz(width + height) + ldrh w3, [x5, w3, uxtw #1] + ldrh w6, [x5, w6, uxtw #1] + neg w7, w7 // -ctz(width + height) + sub x3, x5, w3, uxtw + sub x5, x5, w6, uxtw + ushr v16.4s, v16.4s, #1 // (width + height) >> 1 + dup v17.4s, w7 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], #8 + uaddlv s0, v0.4h + add x2, x2, #2 + br x3 +L(ipred_dc_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.4h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s1, v1.4h + cmp w4, #4 + add v0.2s, v0.2s, v1.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.4h, v0.h[0] +2: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2], #16 + uaddlv s0, v0.8h + add x2, x2, #2 + br x3 +L(ipred_dc_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s1, v1.8h + cmp w4, #8 + add v0.2s, v0.2s, v1.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] +2: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2], #32 + addp v0.8h, v0.8h, v1.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + uaddlv s1, v1.8h + cmp w4, #16 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/8/32/64 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h, v3.8h, v4.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + addp v3.8h, v3.8h, v4.8h + addp v1.8h, v1.8h, v3.8h + uaddlv s1, v1.8h + cmp w4, #32 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16/64 + cmp w4, #8 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w64): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h, v3.8h, v4.8h}, [x2], #64 + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x2] + addp v3.8h, v3.8h, v4.8h + addp v20.8h, v20.8h, v21.8h + addp v22.8h, v22.8h, v23.8h + addp v1.8h, v1.8h, v3.8h + addp v20.8h, v20.8h, v22.8h + addp v1.8h, v1.8h, v20.8h + uaddlv s1, v1.8h + cmp w4, #64 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 16/32 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + sub x1, x1, #64 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_tbl): + .hword L(ipred_dc_tbl) - L(ipred_dc_h64) + .hword L(ipred_dc_tbl) - L(ipred_dc_h32) + .hword L(ipred_dc_tbl) - L(ipred_dc_h16) + .hword L(ipred_dc_tbl) - L(ipred_dc_h8) + .hword L(ipred_dc_tbl) - L(ipred_dc_h4) + .hword L(ipred_dc_tbl) - L(ipred_dc_w64) + .hword L(ipred_dc_tbl) - L(ipred_dc_w32) + .hword L(ipred_dc_tbl) - L(ipred_dc_w16) + .hword L(ipred_dc_tbl) - L(ipred_dc_w8) + .hword L(ipred_dc_tbl) - L(ipred_dc_w4) +endfunc + +// void ipred_paeth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_16bpc_neon, export=1 + clz w9, w3 + adr x5, L(ipred_paeth_tbl) + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x2] + add x8, x2, #2 + sub x2, x2, #8 + sub x5, x5, w9, uxtw + mov x7, #-8 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.2d}, [x8] + sub v6.8h, v5.8h, v4.8h // top - topleft +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + add v16.8h, v6.8h, v0.8h // base + add v17.8h, v6.8h, v2.8h + sabd v20.8h, v5.8h, v16.8h // tdiff + sabd v21.8h, v5.8h, v17.8h + sabd v22.8h, v4.8h, v16.8h // tldiff + sabd v23.8h, v4.8h, v17.8h + sabd v16.8h, v0.8h, v16.8h // ldiff + sabd v17.8h, v2.8h, v17.8h + umin v18.8h, v20.8h, v22.8h // min(tdiff, tldiff) + umin v19.8h, v21.8h, v23.8h + cmge v20.8h, v22.8h, v20.8h // tldiff >= tdiff + cmge v21.8h, v23.8h, v21.8h + cmge v16.8h, v18.8h, v16.8h // min(tdiff, tldiff) >= ldiff + cmge v17.8h, v19.8h, v17.8h + bsl v21.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v20.16b, v5.16b, v4.16b + bit v21.16b, v2.16b, v17.16b // ldiff <= min ? left : ... + bit v20.16b, v0.16b, v16.16b + st1 {v21.d}[1], [x0], x1 + st1 {v21.d}[0], [x6], x1 + subs w4, w4, #4 + st1 {v20.d}[1], [x0], x1 + st1 {v20.d}[0], [x6], x1 + b.gt 4b + ret +80: +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v5.8h}, [x8], #16 + mov w9, w3 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 +1: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 +2: + sub v6.8h, v5.8h, v4.8h // top - topleft + add v16.8h, v6.8h, v0.8h // base + add v17.8h, v6.8h, v1.8h + add v18.8h, v6.8h, v2.8h + add v19.8h, v6.8h, v3.8h + sabd v20.8h, v5.8h, v16.8h // tdiff + sabd v21.8h, v5.8h, v17.8h + sabd v22.8h, v5.8h, v18.8h + sabd v23.8h, v5.8h, v19.8h + sabd v24.8h, v4.8h, v16.8h // tldiff + sabd v25.8h, v4.8h, v17.8h + sabd v26.8h, v4.8h, v18.8h + sabd v27.8h, v4.8h, v19.8h + sabd v16.8h, v0.8h, v16.8h // ldiff + sabd v17.8h, v1.8h, v17.8h + sabd v18.8h, v2.8h, v18.8h + sabd v19.8h, v3.8h, v19.8h + umin v28.8h, v20.8h, v24.8h // min(tdiff, tldiff) + umin v29.8h, v21.8h, v25.8h + umin v30.8h, v22.8h, v26.8h + umin v31.8h, v23.8h, v27.8h + cmge v20.8h, v24.8h, v20.8h // tldiff >= tdiff + cmge v21.8h, v25.8h, v21.8h + cmge v22.8h, v26.8h, v22.8h + cmge v23.8h, v27.8h, v23.8h + cmge v16.8h, v28.8h, v16.8h // min(tdiff, tldiff) >= ldiff + cmge v17.8h, v29.8h, v17.8h + cmge v18.8h, v30.8h, v18.8h + cmge v19.8h, v31.8h, v19.8h + bsl v23.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v22.16b, v5.16b, v4.16b + bsl v21.16b, v5.16b, v4.16b + bsl v20.16b, v5.16b, v4.16b + bit v23.16b, v3.16b, v19.16b // ldiff <= min ? left : ... + bit v22.16b, v2.16b, v18.16b + bit v21.16b, v1.16b, v17.16b + bit v20.16b, v0.16b, v16.16b + st1 {v23.8h}, [x0], #16 + st1 {v22.8h}, [x6], #16 + subs w3, w3, #8 + st1 {v21.8h}, [x5], #16 + st1 {v20.8h}, [x10], #16 + b.le 8f + ld1 {v5.8h}, [x8], #16 + b 2b +8: + subs w4, w4, #4 + b.le 9f + // End of horizontal loop, move pointers to next four rows + sub x8, x8, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + // Load the top row as early as possible + ld1 {v5.8h}, [x8], #16 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_paeth_tbl): + .hword L(ipred_paeth_tbl) - 640b + .hword L(ipred_paeth_tbl) - 320b + .hword L(ipred_paeth_tbl) - 160b + .hword L(ipred_paeth_tbl) - 80b + .hword L(ipred_paeth_tbl) - 40b +endfunc + +// void ipred_smooth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_16bpc_neon, export=1 + movrel x10, X(sm_weights) + add x11, x10, w4, uxtw + add x10, x10, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_tbl) + sub x12, x2, w4, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x12] // bottom + add x8, x2, #2 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2d}, [x8] // top + ld1r {v7.2s}, [x10] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + dup v5.8h, v6.h[3] // right + sub v6.8h, v6.8h, v4.8h // top-bottom + uxtl v7.8h, v7.8b // weights_hor + add v31.4h, v4.4h, v5.4h // bottom+right +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + zip1 v1.2d, v1.2d, v0.2d // left, flipped + zip1 v0.2d, v3.2d, v2.2d + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + smlal v20.4s, v0.4h, v7.4h // += (left-right)*weights_hor + smlal2 v21.4s, v0.8h, v7.8h + smlal v22.4s, v1.4h, v7.4h + smlal2 v23.4s, v1.8h, v7.8h + smlal v20.4s, v6.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v6.8h, v16.8h + smlal v22.4s, v6.4h, v18.4h + smlal2 v23.4s, v6.8h, v18.8h + rshrn v20.4h, v20.4s, #9 + rshrn v21.4h, v21.4s, #9 + rshrn v22.4h, v22.4s, #9 + rshrn v23.4h, v23.4s, #9 + st1 {v20.4h}, [x0], x1 + st1 {v21.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.4h}, [x0], x1 + st1 {v23.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8h}, [x8] // top + ld1 {v7.8b}, [x10] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + dup v5.8h, v6.h[7] // right + sub v6.8h, v6.8h, v4.8h // top-bottom + uxtl v7.8h, v7.8b // weights_hor + add v31.4h, v4.4h, v5.4h // bottom+right +8: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + ushll v24.4s, v31.4h, #8 + ushll v25.4s, v31.4h, #8 + ushll v26.4s, v31.4h, #8 + ushll v27.4s, v31.4h, #8 + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sub v2.8h, v2.8h, v5.8h + sub v3.8h, v3.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + smlal v20.4s, v3.4h, v7.4h // += (left-right)*weights_hor + smlal2 v21.4s, v3.8h, v7.8h // (left flipped) + smlal v22.4s, v2.4h, v7.4h + smlal2 v23.4s, v2.8h, v7.8h + smlal v24.4s, v1.4h, v7.4h + smlal2 v25.4s, v1.8h, v7.8h + smlal v26.4s, v0.4h, v7.4h + smlal2 v27.4s, v0.8h, v7.8h + smlal v20.4s, v6.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v6.8h, v16.8h + smlal v22.4s, v6.4h, v17.4h + smlal2 v23.4s, v6.8h, v17.8h + smlal v24.4s, v6.4h, v18.4h + smlal2 v25.4s, v6.8h, v18.8h + smlal v26.4s, v6.4h, v19.4h + smlal2 v27.4s, v6.8h, v19.8h + rshrn v20.4h, v20.4s, #9 + rshrn2 v20.8h, v21.4s, #9 + rshrn v21.4h, v22.4s, #9 + rshrn2 v21.8h, v23.4s, #9 + rshrn v22.4h, v24.4s, #9 + rshrn2 v22.8h, v25.4s, #9 + rshrn v23.4h, v26.4s, #9 + rshrn2 v23.8h, v27.4s, #9 + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + add x12, x2, w3, uxtw #1 + sub x1, x1, w3, uxtw #1 + ld1r {v5.8h}, [x12] // right + sub x2, x2, #4 + mov x7, #-4 + mov w9, w3 + add v31.4h, v4.4h, v5.4h // bottom+right + +1: + ld2r {v0.8h, v1.8h}, [x2], x7 // left + ld2r {v16.8b, v17.8b}, [x11], #2 // weights_ver + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b +2: + ld1 {v7.16b}, [x10], #16 // weights_hor + ld1 {v2.8h, v3.8h}, [x8], #32 // top + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + ushll v24.4s, v31.4h, #8 + ushll v25.4s, v31.4h, #8 + ushll v26.4s, v31.4h, #8 + ushll v27.4s, v31.4h, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + sub v2.8h, v2.8h, v4.8h // top-bottom + sub v3.8h, v3.8h, v4.8h + smlal v20.4s, v1.4h, v6.4h // += (left-right)*weights_hor + smlal2 v21.4s, v1.8h, v6.8h // (left flipped) + smlal v22.4s, v1.4h, v7.4h + smlal2 v23.4s, v1.8h, v7.8h + smlal v24.4s, v0.4h, v6.4h + smlal2 v25.4s, v0.8h, v6.8h + smlal v26.4s, v0.4h, v7.4h + smlal2 v27.4s, v0.8h, v7.8h + smlal v20.4s, v2.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v2.8h, v16.8h + smlal v22.4s, v3.4h, v16.4h + smlal2 v23.4s, v3.8h, v16.8h + smlal v24.4s, v2.4h, v17.4h + smlal2 v25.4s, v2.8h, v17.8h + smlal v26.4s, v3.4h, v17.4h + smlal2 v27.4s, v3.8h, v17.8h + rshrn v20.4h, v20.4s, #9 + rshrn2 v20.8h, v21.4s, #9 + rshrn v21.4h, v22.4s, #9 + rshrn2 v21.8h, v23.4s, #9 + rshrn v22.4h, v24.4s, #9 + rshrn2 v22.8h, v25.4s, #9 + rshrn v23.4h, v26.4s, #9 + rshrn2 v23.8h, v27.4s, #9 + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x8, w9, uxtw #1 + sub x10, x10, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_tbl): + .hword L(ipred_smooth_tbl) - 640b + .hword L(ipred_smooth_tbl) - 320b + .hword L(ipred_smooth_tbl) - 160b + .hword L(ipred_smooth_tbl) - 80b + .hword L(ipred_smooth_tbl) - 40b +endfunc + +// void ipred_smooth_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_16bpc_neon, export=1 + movrel x7, X(sm_weights) + add x7, x7, w4, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_v_tbl) + sub x8, x2, w4, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x8] // bottom + add x2, x2, #2 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2d}, [x2] // top + sub v6.8h, v6.8h, v4.8h // top-bottom +4: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v18.8h, v18.8b, #7 + sqrdmulh v20.8h, v6.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v6.8h, v18.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + st1 {v20.d}[0], [x0], x1 + st1 {v20.d}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.d}[0], [x0], x1 + st1 {v21.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8h}, [x2] // top + sub v6.8h, v6.8h, v4.8h // top-bottom +8: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v17.8h, v17.8b, #7 + ushll v18.8h, v18.8b, #7 + ushll v19.8h, v19.8b, #7 + sqrdmulh v20.8h, v6.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v6.8h, v17.8h + sqrdmulh v22.8h, v6.8h, v18.8h + sqrdmulh v23.8h, v6.8h, v19.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + add v22.8h, v22.8h, v4.8h + add v23.8h, v23.8h, v4.8h + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + // Set up pointers for four rows in parallel; x0, x6, x5, x8 + add x5, x0, x1 + add x8, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v17.8h, v17.8b, #7 + ushll v18.8h, v18.8b, #7 + ushll v19.8h, v19.8b, #7 +2: + ld1 {v2.8h, v3.8h}, [x2], #32 // top + sub v2.8h, v2.8h, v4.8h // top-bottom + sub v3.8h, v3.8h, v4.8h + sqrdmulh v20.8h, v2.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v3.8h, v16.8h + sqrdmulh v22.8h, v2.8h, v17.8h + sqrdmulh v23.8h, v3.8h, v17.8h + sqrdmulh v24.8h, v2.8h, v18.8h + sqrdmulh v25.8h, v3.8h, v18.8h + sqrdmulh v26.8h, v2.8h, v19.8h + sqrdmulh v27.8h, v3.8h, v19.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + add v22.8h, v22.8h, v4.8h + add v23.8h, v23.8h, v4.8h + add v24.8h, v24.8h, v4.8h + add v25.8h, v25.8h, v4.8h + add v26.8h, v26.8h, v4.8h + add v27.8h, v27.8h, v4.8h + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + st1 {v24.8h, v25.8h}, [x5], #32 + st1 {v26.8h, v27.8h}, [x8], #32 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x2, x2, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x8, x8, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_v_tbl): + .hword L(ipred_smooth_v_tbl) - 640b + .hword L(ipred_smooth_v_tbl) - 320b + .hword L(ipred_smooth_v_tbl) - 160b + .hword L(ipred_smooth_v_tbl) - 80b + .hword L(ipred_smooth_v_tbl) - 40b +endfunc + +// void ipred_smooth_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_16bpc_neon, export=1 + movrel x8, X(sm_weights) + add x8, x8, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_h_tbl) + add x12, x2, w3, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v5.8h}, [x12] // right + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v7.2s}, [x8] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + ushll v7.8h, v7.8b, #7 // weights_hor << 7 +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 // left + zip1 v1.2d, v1.2d, v0.2d // left, flipped + zip1 v0.2d, v3.2d, v2.2d + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sqrdmulh v20.8h, v0.8h, v7.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v1.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + st1 {v20.d}[0], [x0], x1 + st1 {v20.d}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.d}[0], [x0], x1 + st1 {v21.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v7.8b}, [x8] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + ushll v7.8h, v7.8b, #7 // weights_hor << 7 +8: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + sub v3.8h, v3.8h, v5.8h // left-right + sub v2.8h, v2.8h, v5.8h + sub v1.8h, v1.8h, v5.8h + sub v0.8h, v0.8h, v5.8h + sqrdmulh v20.8h, v3.8h, v7.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v2.8h, v7.8h // (left flipped) + sqrdmulh v22.8h, v1.8h, v7.8h + sqrdmulh v23.8h, v0.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + add v22.8h, v22.8h, v5.8h + add v23.8h, v23.8h, v5.8h + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + sub x2, x2, #8 + mov x7, #-8 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sub v2.8h, v2.8h, v5.8h + sub v3.8h, v3.8h, v5.8h +2: + ld1 {v7.16b}, [x8], #16 // weights_hor + ushll v6.8h, v7.8b, #7 // weights_hor << 7 + ushll2 v7.8h, v7.16b, #7 + sqrdmulh v20.8h, v3.8h, v6.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v3.8h, v7.8h // (left flipped) + sqrdmulh v22.8h, v2.8h, v6.8h + sqrdmulh v23.8h, v2.8h, v7.8h + sqrdmulh v24.8h, v1.8h, v6.8h + sqrdmulh v25.8h, v1.8h, v7.8h + sqrdmulh v26.8h, v0.8h, v6.8h + sqrdmulh v27.8h, v0.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + add v22.8h, v22.8h, v5.8h + add v23.8h, v23.8h, v5.8h + add v24.8h, v24.8h, v5.8h + add v25.8h, v25.8h, v5.8h + add v26.8h, v26.8h, v5.8h + add v27.8h, v27.8h, v5.8h + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + st1 {v24.8h, v25.8h}, [x5], #32 + st1 {v26.8h, v27.8h}, [x10], #32 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_h_tbl): + .hword L(ipred_smooth_h_tbl) - 640b + .hword L(ipred_smooth_h_tbl) - 320b + .hword L(ipred_smooth_h_tbl) - 160b + .hword L(ipred_smooth_h_tbl) - 80b + .hword L(ipred_smooth_h_tbl) - 40b +endfunc + +const padding_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +padding_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void ipred_z1_upsample_edge_16bpc_neon(pixel *out, const int hsz, +// const pixel *const in, const int end, +// const int bitdepth_max); +function ipred_z1_upsample_edge_16bpc_neon, export=1 + dup v30.8h, w4 // bitdepth_max + movrel x4, padding_mask + ld1 {v0.8h, v1.8h}, [x2] // in[] + add x5, x2, w3, uxtw #1 // in[end] + sub x4, x4, w3, uxtw #1 + + ld1r {v2.8h}, [x5] // padding + ld1 {v3.8h, v4.8h}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v2.16b, v3.16b // padded in[] + bit v1.16b, v2.16b, v4.16b + + ext v4.16b, v0.16b, v1.16b, #2 + ext v5.16b, v1.16b, v2.16b, #2 + ext v6.16b, v0.16b, v1.16b, #4 + ext v7.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + + add v18.8h, v4.8h, v6.8h // in[i+1] + in[i+2] + add v19.8h, v5.8h, v7.8h + add v20.8h, v0.8h, v16.8h + add v21.8h, v1.8h, v17.8h + umull v22.4s, v18.4h, v31.4h // 9*(in[i+1] + in[i+2]) + umull2 v23.4s, v18.8h, v31.8h + umull v24.4s, v19.4h, v31.4h + umull2 v25.4s, v19.8h, v31.8h + usubw v22.4s, v22.4s, v20.4h + usubw2 v23.4s, v23.4s, v20.8h + usubw v24.4s, v24.4s, v21.4h + usubw2 v25.4s, v25.4s, v21.8h + + sqrshrun v16.4h, v22.4s, #4 + sqrshrun2 v16.8h, v23.4s, #4 + sqrshrun v17.4h, v24.4s, #4 + sqrshrun2 v17.8h, v25.4s, #4 + + smin v16.8h, v16.8h, v30.8h + smin v17.8h, v17.8h, v30.8h + + zip1 v0.8h, v4.8h, v16.8h + zip2 v1.8h, v4.8h, v16.8h + zip1 v2.8h, v5.8h, v17.8h + zip2 v3.8h, v5.8h, v17.8h + + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + + ret +endfunc + +// void ipred_z2_upsample_edge_16bpc_neon(pixel *out, const int sz, +// const pixel *const in, +// const int bitdepth_max); +function ipred_z2_upsample_edge_16bpc_neon, export=1 + dup v30.8h, w3 // bitdepth_max + // Here, sz is 4 or 8, and we produce 2*sz+1 output elements. + movrel x4, padding_mask + ld1 {v0.8h, v1.8h}, [x2] // in[] + add x5, x2, w1, uxtw #1 // in[sz] + sub x4, x4, w1, uxtw #1 + + ld1r {v3.8h}, [x2] // in[0] for padding + ld1r {v2.8h}, [x5] // padding + ld1 {v4.8h, v5.8h}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v2.16b, v4.16b // padded in[] + bit v1.16b, v2.16b, v5.16b + + ext v4.16b, v3.16b, v0.16b, #14 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #4 + + add v16.8h, v0.8h, v5.8h // in[i+0] + in[i+1] + add v17.8h, v4.8h, v6.8h // in[i-1] + in[i+2] + umull v18.4s, v16.4h, v31.4h // 9*(in[i+1] + in[i+2]) + umull2 v19.4s, v16.8h, v31.8h + usubw v18.4s, v18.4s, v17.4h + usubw2 v19.4s, v19.4s, v17.8h + + sqrshrun v16.4h, v18.4s, #4 + sqrshrun2 v16.8h, v19.4s, #4 + + add x5, x0, #2*16 + + smin v16.8h, v16.8h, v30.8h + + zip1 v4.8h, v0.8h, v16.8h + zip2 v5.8h, v0.8h, v16.8h + + st1 {v2.h}[0], [x5] + // In case sz=8, output one single pixel in out[16]. + st1 {v4.8h, v5.8h}, [x0] + + ret +endfunc + +const edge_filter + .short 0, 4, 8, 0 + .short 0, 5, 6, 0 +// Leaving out the coeffs for strength=3 +// .byte 2, 4, 4, 0 +endconst + +// void ipred_z1_filter_edge_16bpc_neon(pixel *out, const int sz, +// const pixel *const in, const int end, +// const int strength); +function ipred_z1_filter_edge_16bpc_neon, export=1 + cmp w4, #3 + b.eq L(fivetap) // if (strength == 3) goto fivetap + + movrel x5, edge_filter, -6 + add x5, x5, w4, uxtw #3 // edge_filter + 2*((strength - 1)*4 + 1) + + ld1 {v31.s}[0], [x5] // kernel[1-2] + + ld1 {v0.8h}, [x2], #16 + + dup v30.8h, v31.h[0] + dup v31.8h, v31.h[1] +1: + // in[end], is the last valid pixel. We produce 16 pixels out by + // using 18 pixels in - the last pixel used is [17] of the ones + // read/buffered. + cmp w3, #17 + ld1 {v1.8h, v2.8h}, [x2], #32 + b.lt 2f + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + mul v16.8h, v0.8h, v30.8h + mla v16.8h, v3.8h, v31.8h + mla v16.8h, v5.8h, v30.8h + mul v17.8h, v1.8h, v30.8h + mla v17.8h, v4.8h, v31.8h + mla v17.8h, v6.8h, v30.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + urshr v16.8h, v16.8h, #4 + urshr v17.8h, v17.8h, #4 + sub w3, w3, #16 + st1 {v16.8h, v17.8h}, [x0], #32 + b.gt 1b + ret +2: + // Right padding + + // x2[w3-24] is the padding pixel (x2 points 24 pixels ahead) + movrel x5, padding_mask + sub w6, w3, #24 + sub x5, x5, w3, uxtw #1 + add x6, x2, w6, sxtw #1 + + ld1 {v3.8h, v4.8h}, [x5] // padding_mask + + ld1r {v2.8h}, [x6] + bit v0.16b, v2.16b, v3.16b // Pad v0-v1 + bit v1.16b, v2.16b, v4.16b + + // Filter one block + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + mul v16.8h, v0.8h, v30.8h + mla v16.8h, v3.8h, v31.8h + mla v16.8h, v5.8h, v30.8h + mul v17.8h, v1.8h, v30.8h + mla v17.8h, v4.8h, v31.8h + mla v17.8h, v6.8h, v30.8h + subs w1, w1, #16 + urshr v16.8h, v16.8h, #4 + urshr v17.8h, v17.8h, #4 + st1 {v16.8h, v17.8h}, [x0], #32 + b.le 9f +5: + // After one block, any remaining output would only be filtering + // padding - thus just store the padding. + subs w1, w1, #16 + st1 {v2.16b}, [x0], #16 + b.gt 5b +9: + ret + +L(fivetap): + sub x2, x2, #2 // topleft -= 1 pixel + movi v29.8h, #2 + ld1 {v0.8h}, [x2], #16 + movi v30.8h, #4 + movi v31.8h, #4 + ins v0.h[0], v0.h[1] +1: + // in[end+1], is the last valid pixel. We produce 16 pixels out by + // using 20 pixels in - the last pixel used is [19] of the ones + // read/buffered. + cmp w3, #18 + ld1 {v1.8h, v2.8h}, [x2], #32 + b.lt 2f // if (end + 1 < 19) + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + ext v18.16b, v0.16b, v1.16b, #8 + ext v19.16b, v1.16b, v2.16b, #8 + mul v20.8h, v0.8h, v29.8h + mla v20.8h, v3.8h, v30.8h + mla v20.8h, v5.8h, v31.8h + mla v20.8h, v16.8h, v30.8h + mla v20.8h, v18.8h, v29.8h + mul v21.8h, v1.8h, v29.8h + mla v21.8h, v4.8h, v30.8h + mla v21.8h, v6.8h, v31.8h + mla v21.8h, v17.8h, v30.8h + mla v21.8h, v19.8h, v29.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + urshr v20.8h, v20.8h, #4 + urshr v21.8h, v21.8h, #4 + sub w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + b.gt 1b + ret +2: + // Right padding + + // x2[w3+1-24] is the padding pixel (x2 points 24 pixels ahead) + movrel x5, padding_mask, -2 + sub w6, w3, #23 + sub x5, x5, w3, uxtw #1 + add x6, x2, w6, sxtw #1 + + ld1 {v3.8h, v4.8h, v5.8h}, [x5] // padding_mask + + ld1r {v28.8h}, [x6] + bit v0.16b, v28.16b, v3.16b // Pad v0-v2 + bit v1.16b, v28.16b, v4.16b + bit v2.16b, v28.16b, v5.16b +4: + // Filter one block + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + ext v18.16b, v0.16b, v1.16b, #8 + ext v19.16b, v1.16b, v2.16b, #8 + mul v20.8h, v0.8h, v29.8h + mla v20.8h, v3.8h, v30.8h + mla v20.8h, v5.8h, v31.8h + mla v20.8h, v16.8h, v30.8h + mla v20.8h, v18.8h, v29.8h + mul v21.8h, v1.8h, v29.8h + mla v21.8h, v4.8h, v30.8h + mla v21.8h, v6.8h, v31.8h + mla v21.8h, v17.8h, v30.8h + mla v21.8h, v19.8h, v29.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + mov v1.16b, v28.16b + mov v2.16b, v28.16b + urshr v20.8h, v20.8h, #4 + urshr v21.8h, v21.8h, #4 + sub w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + b.le 9f + // v0-v1[w3+1] is the last valid pixel; if (w3 + 1 > 0) we need to + // filter properly once more - aka (w3 >= 0). + cmp w3, #0 + b.ge 4b +5: + // When w3 <= 0, all remaining pixels in v0-v1 are equal to the + // last valid pixel - thus just output that without filtering. + subs w1, w1, #8 + st1 {v28.8h}, [x0], #16 + b.gt 5b +9: + ret +endfunc + +// void ipred_pixel_set_16bpc_neon(pixel *out, const pixel px, +// const int n); +function ipred_pixel_set_16bpc_neon, export=1 + dup v0.8h, w1 +1: + subs w2, w2, #8 + st1 {v0.8h}, [x0], #16 + b.gt 1b + ret +endfunc + +// void ipred_z1_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const int width, const int height, +// const int dx, const int max_base_x); +function ipred_z1_fill1_16bpc_neon, export=1 + clz w9, w3 + adr x8, L(ipred_z1_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw #1 // top[max_base_x] + sub x8, x8, w9, uxtw + ld1r {v31.8h}, [x10] // padding + mov w7, w5 + mov w15, #64 + br x8 +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + ext v1.16b, v0.16b, v0.16b, #2 // top[base+1] + ext v3.16b, v2.16b, v2.16b, #2 + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + st1 {v16.4h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.4h}, [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.4h}, [x0], x1 + b.gt 49b + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h}, [x8] // top[base] + ld1 {v2.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + ldr h1, [x8, #16] + ldr h3, [x10, #16] + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + ext v1.16b, v0.16b, v1.16b, #2 // top[base+1] + ext v3.16b, v2.16b, v3.16b, #2 + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v1.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v1.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v3.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v3.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + st1 {v16.8h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8h}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8h}, [x0], x1 + b.gt 89b + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + mov w12, w3 + + add x13, x0, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 169f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v6.8h, w9 // frac + dup v7.8h, w11 + ld1 {v0.8h, v1.8h, v2.8h}, [x8], #48 // top[base] + ld1 {v3.8h, v4.8h, v5.8h}, [x10], #48 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v16.8h, w9 // 64 - frac + dup v17.8h, w11 + add w7, w7, w5 // xpos += dx +2: + ext v18.16b, v0.16b, v1.16b, #2 // top[base+1] + ext v19.16b, v1.16b, v2.16b, #2 + ext v20.16b, v3.16b, v4.16b, #2 + ext v21.16b, v4.16b, v5.16b, #2 + subs w3, w3, #16 + umull v22.4s, v0.4h, v16.4h // top[base]*(64-frac) + umlal v22.4s, v18.4h, v6.4h // + top[base+1]*frac + umull2 v23.4s, v0.8h, v16.8h + umlal2 v23.4s, v18.8h, v6.8h + umull v24.4s, v1.4h, v16.4h + umlal v24.4s, v19.4h, v6.4h + umull2 v25.4s, v1.8h, v16.8h + umlal2 v25.4s, v19.8h, v6.8h + umull v26.4s, v3.4h, v17.4h + umlal v26.4s, v20.4h, v7.4h + umull2 v27.4s, v3.8h, v17.8h + umlal2 v27.4s, v20.8h, v7.8h + umull v28.4s, v4.4h, v17.4h + umlal v28.4s, v21.4h, v7.4h + umull2 v29.4s, v4.8h, v17.8h + umlal2 v29.4s, v21.8h, v7.8h + rshrn v22.4h, v22.4s, #6 + rshrn2 v22.8h, v23.4s, #6 + rshrn v23.4h, v24.4s, #6 + rshrn2 v23.8h, v25.4s, #6 + rshrn v24.4h, v26.4s, #6 + rshrn2 v24.8h, v27.4s, #6 + rshrn v25.4h, v28.4s, #6 + rshrn2 v25.8h, v29.4s, #6 + st1 {v22.8h, v23.8h}, [x0], #32 + st1 {v24.8h, v25.8h}, [x13], #32 + b.le 3f + mov v0.16b, v2.16b + ld1 {v1.8h, v2.8h}, [x8], #32 // top[base] + mov v3.16b, v5.16b + ld1 {v4.8h, v5.8h}, [x10], #32 + b 2b + +3: + subs w4, w4, #2 + b.le 9f + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 1b +9: + ret + +169: + st1 {v31.8h}, [x0], #16 + subs w3, w3, #8 + st1 {v31.8h}, [x13], #16 + b.gt 169b + subs w4, w4, #2 + b.le 9b + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 169b + +L(ipred_z1_fill1_tbl): + .hword L(ipred_z1_fill1_tbl) - 640b + .hword L(ipred_z1_fill1_tbl) - 320b + .hword L(ipred_z1_fill1_tbl) - 160b + .hword L(ipred_z1_fill1_tbl) - 80b + .hword L(ipred_z1_fill1_tbl) - 40b +endfunc + +function ipred_z1_fill2_16bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // top[max_base_x] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + b.eq 8f + +4: // w == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8h, v0.8h, v0.8h // top[base+1] + uzp1 v0.8h, v0.8h, v0.8h // top[base] + uzp2 v3.8h, v2.8h, v2.8h + uzp1 v2.8h, v2.8h, v2.8h + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + st1 {v16.4h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.4h}, [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.4h}, [x0], x1 + b.gt 49b + ret + +8: // w == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h, v1.8h}, [x8] // top[base] + ld1 {v2.8h, v3.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + uzp2 v20.8h, v0.8h, v1.8h // top[base+1] + uzp1 v0.8h, v0.8h, v1.8h // top[base] + uzp2 v21.8h, v2.8h, v3.8h + uzp1 v2.8h, v2.8h, v3.8h + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v20.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v20.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v21.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v21.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + st1 {v16.8h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8h}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8h}, [x0], x1 + b.gt 89b + ret +endfunc + +// void ipred_reverse_16bpc_neon(pixel *dst, const pixel *const src, +// const int n); +function ipred_reverse_16bpc_neon, export=1 + sub x1, x1, #16 + add x3, x0, #8 + mov x4, #16 +1: + ld1 {v0.8h}, [x1] + subs w2, w2, #8 + rev64 v0.8h, v0.8h + sub x1, x1, #16 + st1 {v0.d}[1], [x0], x4 + st1 {v0.d}[0], [x3], x4 + b.gt 1b + ret +endfunc + +const increments + .short 0, 1, 2, 3, 4, 5, 6, 7 +endconst + +// void ipred_z2_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const pixel *const left, +// const int width, const int height, +// const int dx, const int dy); +function ipred_z2_fill1_16bpc_neon, export=1 + clz w10, w4 + adr x9, L(ipred_z2_fill1_tbl) + sub w10, w10, #25 + ldrh w10, [x9, w10, uxtw #1] + mov w8, #(1 << 6) // xpos = 1 << 6 + sub x9, x9, w10, uxtw + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + + br x9 +40: + AARCH64_VALID_JUMP_TARGET + + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // Worst case height for w=4 is 16, but we need at least h+1 elements + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2d, v30.2d, v28.2d // base_y + 1, base_y + 2 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v29.16b, #4 +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + // Cut corners here; only doing tbl over v0-v1 here; we only + // seem to need the last pixel, from v2, after skipping to the + // left-only codepath below. + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + ext v5.16b, v4.16b, v4.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 4b + +49: + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+2] + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 49b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + add x3, x3, #2 // Skip past left[0] + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // Worst case height for w=8 is 32. + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x3] // left[] + ld1r {v15.8h}, [x2] // left[0] == top[0] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + mov v18.16b, v15.16b // left[0] + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + movi v17.16b, #2 + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbx v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 (*2) + add v29.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + mov v19.16b, v15.16b // left[0] + ld1 {v6.8h, v7.8h}, [x11] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + mov v20.16b, v15.16b // left[0] + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + ext v5.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v21.8h, v21.8h, #0 + cmge v22.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 8b + +89: + mov v19.16b, v15.16b + mov v20.16b, v15.16b + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v19.4h, v28.4h + umlal v6.4s, v20.4h, v27.4h + umull2 v7.4s, v19.8h, v28.8h + umlal2 v7.4s, v20.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v25.8h, w7 // -dy + add x3, x3, #2 // Skip past left[0] + + add x13, x0, x1 // alternating row + lsl x1, x1, #1 // stride *= 2 + sub x1, x1, w4, uxtw #1 // stride -= width + + movi v11.8h, #8 + mul v26.8h, v31.8h, v25.8h // {0,1,2,3,4,5,6,7}* -dy + add v26.8h, v26.8h, v25.8h // -= dy + mul v25.8h, v25.8h, v11.8h // -8*dy + + // Worst case height is 64, but we can only fit 32 pixels into + // v0-v3 usable within one tbx instruction. As long as base_y is + // up to 32, we use tbx. + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x3] // left[] + ld1r {v15.8h}, [x2] // left[0] == top[0] + + mov w12, w4 // orig w + neg w14, w4 // -w + +1: + mov v23.16b, v26.16b // reset ypos + + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, w14 // base_x <= -2*w + asr w11, w8, #6 // base_x + b.le 169f + + dup v17.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + ld1 {v4.8h}, [x9], #16 // top[base_x] + ld1 {v6.8h}, [x11], #16 + + movi v10.8h, #0x3e + movi v11.8h, #64 + + and v16.16b, v16.16b, v10.16b // frac_x + and v17.16b, v17.16b, v10.16b + + sub v8.8h, v11.8h, v16.8h // 64 - frac_x + sub v9.8h, v11.8h, v17.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + +2: + smov w10, v22.h[0] + + shrn v29.8b, v23.8h, #6 // ypos >> 6 + movi v12.8h, #64 + cmp w10, #0 // base_x (bottom left) >= 0 + smov w10, v29.b[0] // base_y[0] + movi v10.8h, #0x3e + + b.ge 4f + and v27.16b, v23.16b, v10.16b // frac_y + cmp w10, #(32-3) + + mov v18.16b, v15.16b // left[0] + sub v28.8h, v12.8h, v27.8h // 64 - frac_y + b.gt 22f + +21: + // base_y < 32, using tbx + shl v29.8b, v29.8b, #1 // 2*base_y + movi v11.8h, #1, lsl #8 + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v29.16b, v29.16b, v11.16b // 2*base, 2*base+1, ... + + movi v13.16b, #2 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + + add v29.16b, v29.16b, v13.16b // base_y + 1 (*2) + mov v19.16b, v15.16b // left[0] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + add v29.16b, v29.16b, v13.16b // base_y + 2 (*2) + mov v20.16b, v15.16b // left[0] + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + + b 23f + +22: + // base_y >= 32, using separate loads. + smov w15, v29.b[1] + smov w16, v29.b[2] + add x10, x3, w10, sxtw #1 + smov w17, v29.b[3] + add x15, x3, w15, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[0], [x10] + smov w10, v29.b[4] + add x16, x3, w16, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[1], [x15] + smov w15, v29.b[5] + add x17, x3, w17, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[2], [x16] + smov w16, v29.b[6] + add x10, x3, w10, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[3], [x17] + smov w17, v29.b[7] + add x15, x3, w15, sxtw #1 + add x16, x3, w16, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[4], [x10] + add x17, x3, w17, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[5], [x15] + ld3 {v18.h, v19.h, v20.h}[6], [x16] + ld3 {v18.h, v19.h, v20.h}[7], [x17] + +23: + + ld1 {v5.8h}, [x9], #16 // top[base_x] + ld1 {v7.8h}, [x11], #16 + + add v23.8h, v23.8h, v25.8h // ypos -= 8*dy + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + ext v18.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #2 + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v18.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v18.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v19.4h, v17.4h + umull2 v20.4s, v6.8h, v9.8h + umlal2 v20.4s, v19.8h, v17.8h + + cmge v18.8h, v21.8h, #0 + cmge v19.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v20.4s, #6 + + bit v10.16b, v12.16b, v18.16b + bit v11.16b, v13.16b, v19.16b + + st1 {v10.8h}, [x0], #16 + subs w4, w4, #8 + st1 {v11.8h}, [x13], #16 + b.le 3f + + movi v10.8h, #8 + mov v4.16b, v5.16b + mov v6.16b, v7.16b + add v21.8h, v21.8h, v10.8h // base_x += 8 + add v22.8h, v22.8h, v10.8h + b 2b + +3: + subs w5, w5, #2 + b.le 9f + movi v10.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + mov w4, w12 // reset w + add v26.8h, v26.8h, v10.8h // ypos += 2*(1<<6) + b 1b + +4: // The rest of the row only predicted from top[] + ld1 {v5.8h}, [x9], #16 // top[base_x] + ld1 {v7.8h}, [x11], #16 + + ext v18.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #2 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v18.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v18.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v19.4h, v17.4h + umull2 v20.4s, v6.8h, v9.8h + umlal2 v20.4s, v19.8h, v17.8h + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v20.4s, #6 + + st1 {v12.8h}, [x0], #16 + subs w4, w4, #8 + st1 {v13.8h}, [x13], #16 + b.le 3b + + mov v4.16b, v5.16b + mov v6.16b, v7.16b + b 4b + +169: // The rest of the block only predicted from left[] + add x1, x1, w4, uxtw #1 // restore stride + mov w12, w5 // orig remaining h +1: + movi v12.8h, #64 + movi v10.8h, #0x3e + + shrn v29.8b, v23.8h, #6 // ypos >> 6 + and v27.16b, v23.16b, v10.16b // frac_y + + smov w10, v29.b[0] // base_y[0] + + shl v29.8b, v29.8b, #1 // 2*base_y + movi v11.8h, #1, lsl #8 + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v23.8h, v23.8h, v25.8h // ypos -= 8*dy + add v29.16b, v29.16b, v11.16b // 2*base, 2*base+1, ... + + cmp w10, #(32-1) + + mov v18.16b, v15.16b // left[0] + movi v21.16b, #2 + + sub v28.8h, v12.8h, v27.8h // 64 - frac_y + + b.gt 31f + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v21.16b // base_y + 1 (*2) + +2: + // base_y < 32, using tbx. + smov w10, v29.b[0] // base_y[0] + mov v19.16b, v15.16b // left[0] + cmp w10, #(64-4) + b.gt 32f + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v21.16b // base_y + 2 (*2) + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + add v29.16b, v29.16b, v21.16b // next base_y + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v11.8h}, [x13], x1 + b.le 4f + mov v18.16b, v20.16b + b 2b + +31: // base_y >= 32, using separate loads, loading v18 if we had to bail + // in the prologue. + smov w10, v29.b[0] + smov w15, v29.b[2] + movi v21.16b, #2 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld1 {v18.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld1 {v18.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld1 {v18.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld1 {v18.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld1 {v18.h}[4], [x10] + add x17, x3, w17, sxtw + ld1 {v18.h}[5], [x15] + add v29.16b, v29.16b, v21.16b // next base_y + ld1 {v18.h}[6], [x16] + ld1 {v18.h}[7], [x17] + +32: // base_y >= 32, using separate loads. + cmp w5, #4 + b.lt 34f +33: // h >= 4, preserving v18 from the previous round, loading v19-v22. + smov w10, v29.b[0] + subs w5, w5, #4 + smov w15, v29.b[2] + movi v10.16b, #8 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[4], [x10] + add x17, x3, w17, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[5], [x15] + ld4 {v19.h, v20.h, v21.h, v22.h}[6], [x16] + add v29.16b, v29.16b, v10.16b // next base_y + ld4 {v19.h, v20.h, v21.h, v22.h}[7], [x17] + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v20.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v12.4s, v21.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v13.4s, v20.8h, v28.8h + umlal2 v13.4s, v21.8h, v27.8h + umull v14.4s, v21.4h, v28.4h + umlal v14.4s, v22.4h, v27.4h + umull2 v18.4s, v21.8h, v28.8h + umlal2 v18.4s, v22.8h, v27.8h + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + st1 {v10.8h}, [x0], x1 + cmp w5, #2 + st1 {v11.8h}, [x13], x1 + st1 {v12.8h}, [x0], x1 + st1 {v13.8h}, [x13], x1 + b.lt 4f + mov v18.16b, v22.16b + b.gt 33b + +34: // h == 2, preserving v18 from the previous round, loading v19-v20. + smov w10, v29.b[0] + smov w15, v29.b[2] + movi v21.16b, #4 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld2 {v19.h, v20.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld2 {v19.h, v20.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld2 {v19.h, v20.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld2 {v19.h, v20.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld2 {v19.h, v20.h}[4], [x10] + add x17, x3, w17, sxtw + ld2 {v19.h, v20.h}[5], [x15] + ld2 {v19.h, v20.h}[6], [x16] + add v29.16b, v29.16b, v21.16b // next base_y + ld2 {v19.h, v20.h}[7], [x17] + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + st1 {v10.8h}, [x0], x1 + st1 {v11.8h}, [x13], x1 + // The h==2 case only happens once at the end, if at all. + +4: + subs w4, w4, #8 + b.le 9f + + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w5, w12 // reset h + b 1b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +L(ipred_z2_fill1_tbl): + .hword L(ipred_z2_fill1_tbl) - 640b + .hword L(ipred_z2_fill1_tbl) - 320b + .hword L(ipred_z2_fill1_tbl) - 160b + .hword L(ipred_z2_fill1_tbl) - 80b + .hword L(ipred_z2_fill1_tbl) - 40b +endfunc + +function ipred_z2_fill2_16bpc_neon, export=1 + cmp w4, #8 + mov w8, #(2 << 6) // xpos = 2 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.8h, v1.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2d, v30.2d, v28.2d // base_y + 1, base_y + 2 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v29.16b, #4 + add v31.8h, v31.8h, v31.8h // {0,2,4,6,0,2,4,6} +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + uzp2 v5.8h, v4.8h, v6.8h // top[base_x+1] + uzp1 v4.8h, v4.8h, v6.8h // top[base_x] + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 4b + +49: + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 49b + +9: + ret + +80: + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.8h, v1.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + movi v17.16b, #2 + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbl v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 (*2) + add v29.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 + add v31.16b, v31.16b, v31.16b // {0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14} +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + ld1 {v6.8h, v7.8h}, [x11] + + tbl v19.16b, {v0.16b, v1.16b}, v29.16b // left[base_y+1] + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + tbl v20.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+2] + + uzp2 v2.8h, v4.8h, v5.8h // top[base_x+1] + uzp1 v4.8h, v4.8h, v5.8h // top[base_x] + uzp2 v3.8h, v6.8h, v7.8h + uzp1 v6.8h, v6.8h, v7.8h + mov v5.16b, v2.16b + mov v7.16b, v3.16b + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v21.8h, v21.8h, #0 + cmge v22.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 8b + +89: + tbl v19.16b, {v0.16b, v1.16b}, v29.16b // left[base_y+1] + tbl v20.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+2] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v19.4h, v28.4h + umlal v6.4s, v20.4h, v27.4h + umull2 v7.4s, v19.8h, v28.8h + umlal2 v7.4s, v20.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret +endfunc + +function ipred_z2_fill3_16bpc_neon, export=1 + cmp w4, #8 + mov w8, #(1 << 6) // xpos = 1 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #2 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + movi v19.16b, #4 + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + add v24.8b, v30.8b, v19.8b // base_y + 3 (*2) + + trn1 v29.2d, v29.2d, v28.2d // base_y + 0, base_y + 2 + trn1 v30.2d, v30.2d, v24.2d // base_y + 1, base_y + 3 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v24.16b, #8 +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + ext v5.16b, v4.16b, v4.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + movi v24.16b, #8 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 4 (*2) + b 4b + +49: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 4 (*2) + b 49b + +9: + ret + +80: + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + movi v17.16b, #2 + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 2 + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + mov v18.16b, v15.16b // left[0] + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + add v30.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + ld1 {v6.8h, v7.8h}, [x11] + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0] + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1] + add v30.16b, v30.16b, v24.16b + + sshr v22.8h, v16.8h, #6 // first base_x + tbl v20.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+2] + sshr v23.8h, v17.8h, #6 + tbl v21.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+3] + + ext v5.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v22.8h, v22.8h, v31.8h // actual base_x + add v23.8h, v23.8h, v31.8h + + umull v12.4s, v20.4h, v28.4h + umlal v12.4s, v21.4h, v27.4h + umull2 v13.4s, v20.8h, v28.8h + umlal2 v13.4s, v21.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v22.8h, v22.8h, #0 + cmge v23.8h, v23.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v22.16b + bit v11.16b, v13.16b, v23.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b + b 8b + +89: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0] + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1] + add v30.16b, v30.16b, v24.16b + tbl v20.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+2] + tbl v21.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+3] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v20.4h, v28.4h + umlal v6.4s, v21.4h, v27.4h + umull2 v7.4s, v20.8h, v28.8h + umlal2 v7.4s, v21.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret +endfunc + +// void ipred_z3_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const left, +// const int width, const int height, +// const int dy, const int max_base_y); +function ipred_z3_fill1_16bpc_neon, export=1 + clz w9, w4 + adr x8, L(ipred_z3_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw #1 // left[max_base_y] + sub x8, x8, w9, uxtw + ld1r {v31.8h}, [x10] // padding + mov w7, w5 + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + br x8 + +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // left[base] + ldr q2, [x2, w10, uxtw] + dup v4.8h, w9 // frac + dup v5.8h, w11 + ext v1.16b, v0.16b, v0.16b, #2 // left[base+1] + ext v3.16b, v2.16b, v2.16b, #2 + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + add w7, w7, w5 // xpos += dx + st1 {v18.s}[2], [x0] + st1 {v18.s}[3], [x13] + b.le 9f + sub x0, x0, x1 // ptr -= 4 * (2*stride) + sub x13, x13, x1 + add x0, x0, #4 + add x13, x13, #4 + b 4b +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h}, [x8] // left[base] + ld1 {v2.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + ldr h1, [x8, #16] + ldr h3, [x10, #16] + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + ext v1.16b, v0.16b, v1.16b, #2 // left[base+1] + ext v3.16b, v2.16b, v3.16b, #2 + umull v16.4s, v0.4h, v6.4h // left[base]*(64-frac) + umlal v16.4s, v1.4h, v4.4h // + left[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v1.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v3.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v3.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + zip2 v19.8h, v16.8h, v17.8h + add w7, w7, w5 // xpos += dx + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + b.le 9f + sub x0, x0, x1, lsl #2 // ptr -= 4 * (2*stride) + sub x13, x13, x1, lsl #2 + add x0, x0, #4 + add x13, x13, #4 + b 8b +9: + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + mov w12, w4 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // ypos += dy + cmp w8, w6 // base >= max_base_y + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v6.8h, w9 // frac + dup v7.8h, w11 + ld1 {v0.8h, v1.8h, v2.8h}, [x8], #48 // left[base] + ld1 {v3.8h, v4.8h, v5.8h}, [x10], #48 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v16.8h, w9 // 64 - frac + dup v17.8h, w11 + add w7, w7, w5 // ypos += dy +2: + ext v18.16b, v0.16b, v1.16b, #2 // left[base+1] + ext v19.16b, v1.16b, v2.16b, #2 + ext v20.16b, v3.16b, v4.16b, #2 + ext v21.16b, v4.16b, v5.16b, #2 + subs w4, w4, #16 + umull v22.4s, v0.4h, v16.4h // left[base]*(64-frac) + umlal v22.4s, v18.4h, v6.4h // + left[base+1]*frac + umull2 v23.4s, v0.8h, v16.8h + umlal2 v23.4s, v18.8h, v6.8h + umull v24.4s, v1.4h, v16.4h + umlal v24.4s, v19.4h, v6.4h + umull2 v25.4s, v1.8h, v16.8h + umlal2 v25.4s, v19.8h, v6.8h + umull v26.4s, v3.4h, v17.4h + umlal v26.4s, v20.4h, v7.4h + umull2 v27.4s, v3.8h, v17.8h + umlal2 v27.4s, v20.8h, v7.8h + umull v28.4s, v4.4h, v17.4h + umlal v28.4s, v21.4h, v7.4h + umull2 v29.4s, v4.8h, v17.8h + umlal2 v29.4s, v21.8h, v7.8h + rshrn v22.4h, v22.4s, #6 + rshrn2 v22.8h, v23.4s, #6 + rshrn v23.4h, v24.4s, #6 + rshrn2 v23.8h, v25.4s, #6 + rshrn v24.4h, v26.4s, #6 + rshrn2 v24.8h, v27.4s, #6 + rshrn v25.4h, v28.4s, #6 + rshrn2 v25.8h, v29.4s, #6 + zip1 v18.8h, v22.8h, v24.8h + zip2 v19.8h, v22.8h, v24.8h + zip1 v20.8h, v23.8h, v25.8h + zip2 v21.8h, v23.8h, v25.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x13], x1 + st1 {v20.s}[2], [x0], x1 + st1 {v20.s}[3], [x13], x1 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x13], x1 + st1 {v21.s}[2], [x0], x1 + st1 {v21.s}[3], [x13], x1 + b.le 3f + mov v0.16b, v2.16b + ld1 {v1.8h, v2.8h}, [x8], #32 // left[base] + mov v3.16b, v5.16b + ld1 {v4.8h, v5.8h}, [x10], #32 + b 2b + +3: + subs w3, w3, #2 + b.le 9f + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b +9: + ret + +L(ipred_z3_fill1_tbl): + .hword L(ipred_z3_fill1_tbl) - 640b + .hword L(ipred_z3_fill1_tbl) - 320b + .hword L(ipred_z3_fill1_tbl) - 160b + .hword L(ipred_z3_fill1_tbl) - 80b + .hword L(ipred_z3_fill1_tbl) - 40b +endfunc + +function ipred_z3_fill_padding_neon, export=0 + cmp w3, #8 + adr x8, L(ipred_z3_fill_padding_tbl) + b.gt L(ipred_z3_fill_padding_wide) + // w3 = remaining width, w4 = constant height + mov w12, w4 + +1: + // Fill a WxH rectangle with padding. W can be any number; + // this fills the exact width by filling in the largest + // power of two in the remaining width, and repeating. + clz w9, w3 + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + sub x9, x8, w9, uxtw + br x9 + +2: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.s}[0], [x13], x1 + st1 {v31.s}[0], [x0], x1 + st1 {v31.s}[0], [x13], x1 + b.gt 2b + subs w3, w3, #2 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b + +4: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #4 + st1 {v31.4h}, [x13], x1 + st1 {v31.4h}, [x0], x1 + st1 {v31.4h}, [x13], x1 + b.gt 4b + subs w3, w3, #4 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #8 + add x13, x13, #8 + mov w4, w12 + b 1b + +8: +16: +32: +64: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #4 + st1 {v31.8h}, [x13], x1 + st1 {v31.8h}, [x0], x1 + st1 {v31.8h}, [x13], x1 + b.gt 4b + subs w3, w3, #8 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w4, w12 + b 1b + +9: + ret + +L(ipred_z3_fill_padding_tbl): + .hword L(ipred_z3_fill_padding_tbl) - 64b + .hword L(ipred_z3_fill_padding_tbl) - 32b + .hword L(ipred_z3_fill_padding_tbl) - 16b + .hword L(ipred_z3_fill_padding_tbl) - 8b + .hword L(ipred_z3_fill_padding_tbl) - 4b + .hword L(ipred_z3_fill_padding_tbl) - 2b + +L(ipred_z3_fill_padding_wide): + // Fill a WxH rectangle with padding, with W > 8. + lsr x1, x1, #1 + mov w12, w3 + sub x1, x1, w3, uxtw #1 +1: + ands w5, w3, #7 + b.eq 2f + // If the width isn't aligned to 8, first do one 8 pixel write + // and align the start pointer. + sub w3, w3, w5 + st1 {v31.8h}, [x0] + add x0, x0, w5, uxtw #1 +2: + // Fill the rest of the line with aligned 8 pixel writes. + subs w3, w3, #8 + st1 {v31.8h}, [x0], #16 + b.gt 2b + subs w4, w4, #1 + add x0, x0, x1 + b.le 9f + mov w3, w12 + b 1b +9: + ret +endfunc + +function ipred_z3_fill2_16bpc_neon, export=1 + cmp w4, #8 + add x10, x2, w6, uxtw // left[max_base_y] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + b.eq 8f + +4: // h == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8h, v0.8h, v0.8h // top[base+1] + uzp1 v0.8h, v0.8h, v0.8h // top[base] + uzp2 v3.8h, v2.8h, v2.8h + uzp1 v2.8h, v2.8h, v2.8h + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + add w7, w7, w5 // xpos += dx + st1 {v18.s}[2], [x0] + st1 {v18.s}[3], [x13] + b.le 9f + sub x0, x0, x1 // ptr -= 4 * (2*stride) + sub x13, x13, x1 + add x0, x0, #4 + add x13, x13, #4 + b 4b +9: + ret + +8: // h == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h, v1.8h}, [x8] // top[base] + ld1 {v2.8h, v3.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + uzp2 v20.8h, v0.8h, v1.8h // top[base+1] + uzp1 v0.8h, v0.8h, v1.8h // top[base] + uzp2 v21.8h, v2.8h, v3.8h + uzp1 v2.8h, v2.8h, v3.8h + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v20.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v20.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v21.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v21.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + zip2 v19.8h, v16.8h, v17.8h + add w7, w7, w5 // xpos += dx + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + b.le 9f + sub x0, x0, x1, lsl #2 // ptr -= 4 * (2*stride) + sub x13, x13, x1, lsl #2 + add x0, x0, #4 + add x13, x13, #4 + b 8b +9: + ret +endfunc + + +// void ipred_filter_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height, +// const int bitdepth_max); +.macro filter_fn bpc +function ipred_filter_\bpc\()bpc_neon + and w5, w5, #511 + movrel x6, X(filter_intra_taps) + lsl w5, w5, #6 + add x6, x6, w5, uxtw + ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x6], #32 + clz w9, w3 + adr x5, L(ipred_filter\bpc\()_tbl) + ld1 {v20.8b, v21.8b, v22.8b}, [x6] + sub w9, w9, #26 + ldrh w9, [x5, w9, uxtw #1] + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + sub x5, x5, w9, uxtw + sxtl v18.8h, v18.8b + sxtl v19.8h, v19.8b + add x6, x0, x1 + lsl x1, x1, #1 + sxtl v20.8h, v20.8b + sxtl v21.8h, v21.8b + sxtl v22.8h, v22.8b + dup v31.8h, w8 +.if \bpc == 10 + movi v30.8h, #0 +.endif + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ldur d0, [x2, #2] // top (0-3) + sub x2, x2, #4 + mov x7, #-4 +4: + ld1 {v1.4h}, [x2], x7 // left (0-1) + topleft (2) +.if \bpc == 10 + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + srshr v2.8h, v2.8h, #4 + smax v2.8h, v2.8h, v30.8h +.else + smull v2.4s, v17.4h, v0.h[0] // p1(top[0]) * filter(1) + smlal v2.4s, v18.4h, v0.h[1] // p2(top[1]) * filter(2) + smlal v2.4s, v19.4h, v0.h[2] // p3(top[2]) * filter(3) + smlal v2.4s, v20.4h, v0.h[3] // p4(top[3]) * filter(4) + smlal v2.4s, v16.4h, v1.h[2] // p0(topleft) * filter(0) + smlal v2.4s, v21.4h, v1.h[1] // p5(left[0]) * filter(5) + smlal v2.4s, v22.4h, v1.h[0] // p6(left[1]) * filter(6) + smull2 v3.4s, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + smlal2 v3.4s, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + smlal2 v3.4s, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + smlal2 v3.4s, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + smlal2 v3.4s, v16.8h, v1.h[2] // p0(topleft) * filter(0) + smlal2 v3.4s, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + smlal2 v3.4s, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + sqrshrun v2.4h, v2.4s, #4 + sqrshrun2 v2.8h, v3.4s, #4 +.endif + smin v2.8h, v2.8h, v31.8h + subs w4, w4, #2 + st1 {v2.d}[0], [x0], x1 + ext v0.16b, v2.16b, v2.16b, #8 // move top from [4-7] to [0-3] + st1 {v2.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ldur q0, [x2, #2] // top (0-7) + sub x2, x2, #4 + mov x7, #-4 +8: + ld1 {v1.4h}, [x2], x7 // left (0-1) + topleft (2) +.if \bpc == 10 + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + mul v3.8h, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + srshr v2.8h, v2.8h, #4 + smax v2.8h, v2.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + mla v3.8h, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + mla v3.8h, v16.8h, v0.h[3] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v2.h[3] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v2.h[7] // p6(left[1]) * filter(6) + srshr v3.8h, v3.8h, #4 + smax v3.8h, v3.8h, v30.8h +.else + smull v2.4s, v17.4h, v0.h[0] // p1(top[0]) * filter(1) + smlal v2.4s, v18.4h, v0.h[1] // p2(top[1]) * filter(2) + smlal v2.4s, v19.4h, v0.h[2] // p3(top[2]) * filter(3) + smlal v2.4s, v20.4h, v0.h[3] // p4(top[3]) * filter(4) + smlal v2.4s, v16.4h, v1.h[2] // p0(topleft) * filter(0) + smlal v2.4s, v21.4h, v1.h[1] // p5(left[0]) * filter(5) + smlal v2.4s, v22.4h, v1.h[0] // p6(left[1]) * filter(6) + smull2 v3.4s, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + smlal2 v3.4s, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + smlal2 v3.4s, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + smlal2 v3.4s, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + smlal2 v3.4s, v16.8h, v1.h[2] // p0(topleft) * filter(0) + smlal2 v3.4s, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + smlal2 v3.4s, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + smull v4.4s, v17.4h, v0.h[4] // p1(top[0]) * filter(1) + smlal v4.4s, v18.4h, v0.h[5] // p2(top[1]) * filter(2) + smlal v4.4s, v19.4h, v0.h[6] // p3(top[2]) * filter(3) + sqrshrun v2.4h, v2.4s, #4 + sqrshrun2 v2.8h, v3.4s, #4 + smin v2.8h, v2.8h, v31.8h + smlal v4.4s, v20.4h, v0.h[7] // p4(top[3]) * filter(4) + smlal v4.4s, v16.4h, v0.h[3] // p0(topleft) * filter(0) + smlal v4.4s, v21.4h, v2.h[3] // p5(left[0]) * filter(5) + smlal v4.4s, v22.4h, v2.h[7] // p6(left[1]) * filter(6) + smull2 v5.4s, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + smlal2 v5.4s, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + smlal2 v5.4s, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + smlal2 v5.4s, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + smlal2 v5.4s, v16.8h, v0.h[3] // p0(topleft) * filter(0) + smlal2 v5.4s, v21.8h, v2.h[3] // p5(left[0]) * filter(5) + smlal2 v5.4s, v22.8h, v2.h[7] // p6(left[1]) * filter(6) + sqrshrun v3.4h, v4.4s, #4 + sqrshrun2 v3.8h, v5.4s, #4 +.endif + smin v3.8h, v3.8h, v31.8h + subs w4, w4, #2 + st2 {v2.d, v3.d}[0], [x0], x1 + zip2 v0.2d, v2.2d, v3.2d + st2 {v2.d, v3.d}[1], [x6], x1 + b.gt 8b + ret +160: +320: + AARCH64_VALID_JUMP_TARGET + add x8, x2, #2 + sub x2, x2, #4 + mov x7, #-4 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld1 {v0.4h}, [x2], x7 // left (0-1) + topleft (2) +2: + ld1 {v1.8h, v2.8h}, [x8], #32 // top(0-15) +.if \bpc == 10 + mul v3.8h, v16.8h, v0.h[2] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + mla v3.8h, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + mla v3.8h, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + mul v4.8h, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + mla v4.8h, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + mla v4.8h, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + srshr v3.8h, v3.8h, #4 + smax v3.8h, v3.8h, v30.8h + smin v3.8h, v3.8h, v31.8h + mla v4.8h, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + mla v4.8h, v16.8h, v1.h[3] // p0(topleft) * filter(0) + mla v4.8h, v21.8h, v3.h[3] // p5(left[0]) * filter(5) + mla v4.8h, v22.8h, v3.h[7] // p6(left[1]) * filter(6) + + mul v5.8h, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + mla v5.8h, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + mla v5.8h, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + srshr v4.8h, v4.8h, #4 + smax v4.8h, v4.8h, v30.8h + smin v4.8h, v4.8h, v31.8h + mla v5.8h, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + mla v5.8h, v16.8h, v1.h[7] // p0(topleft) * filter(0) + mla v5.8h, v21.8h, v4.h[3] // p5(left[0]) * filter(5) + mla v5.8h, v22.8h, v4.h[7] // p6(left[1]) * filter(6) + + mul v6.8h, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + mla v6.8h, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + mla v6.8h, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + srshr v5.8h, v5.8h, #4 + smax v5.8h, v5.8h, v30.8h + smin v5.8h, v5.8h, v31.8h + mla v6.8h, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + mla v6.8h, v16.8h, v2.h[3] // p0(topleft) * filter(0) + mla v6.8h, v21.8h, v5.h[3] // p5(left[0]) * filter(5) + mla v6.8h, v22.8h, v5.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + srshr v6.8h, v6.8h, #4 + smax v6.8h, v6.8h, v30.8h +.else + smull v3.4s, v16.4h, v0.h[2] // p0(topleft) * filter(0) + smlal v3.4s, v21.4h, v0.h[1] // p5(left[0]) * filter(5) + smlal v3.4s, v22.4h, v0.h[0] // p6(left[1]) * filter(6) + smlal v3.4s, v17.4h, v1.h[0] // p1(top[0]) * filter(1) + smlal v3.4s, v18.4h, v1.h[1] // p2(top[1]) * filter(2) + smlal v3.4s, v19.4h, v1.h[2] // p3(top[2]) * filter(3) + smlal v3.4s, v20.4h, v1.h[3] // p4(top[3]) * filter(4) + smull2 v4.4s, v16.8h, v0.h[2] // p0(topleft) * filter(0) + smlal2 v4.4s, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + smlal2 v4.4s, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + smlal2 v4.4s, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + smlal2 v4.4s, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + smlal2 v4.4s, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + smlal2 v4.4s, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + smull v5.4s, v17.4h, v1.h[4] // p1(top[0]) * filter(1) + smlal v5.4s, v18.4h, v1.h[5] // p2(top[1]) * filter(2) + smlal v5.4s, v19.4h, v1.h[6] // p3(top[2]) * filter(3) + sqrshrun v3.4h, v3.4s, #4 + sqrshrun2 v3.8h, v4.4s, #4 + smin v3.8h, v3.8h, v31.8h + smlal v5.4s, v20.4h, v1.h[7] // p4(top[3]) * filter(4) + smlal v5.4s, v16.4h, v1.h[3] // p0(topleft) * filter(0) + smlal v5.4s, v21.4h, v3.h[3] // p5(left[0]) * filter(5) + smlal v5.4s, v22.4h, v3.h[7] // p6(left[1]) * filter(6) + smull2 v6.4s, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + smlal2 v6.4s, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + smlal2 v6.4s, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + smlal2 v6.4s, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + smlal2 v6.4s, v16.8h, v1.h[3] // p0(topleft) * filter(0) + smlal2 v6.4s, v21.8h, v3.h[3] // p5(left[0]) * filter(5) + smlal2 v6.4s, v22.8h, v3.h[7] // p6(left[1]) * filter(6) + + smull v24.4s, v17.4h, v2.h[0] // p1(top[0]) * filter(1) + smlal v24.4s, v18.4h, v2.h[1] // p2(top[1]) * filter(2) + smlal v24.4s, v19.4h, v2.h[2] // p3(top[2]) * filter(3) + sqrshrun v4.4h, v5.4s, #4 + sqrshrun2 v4.8h, v6.4s, #4 + smin v4.8h, v4.8h, v31.8h + smlal v24.4s, v20.4h, v2.h[3] // p4(top[3]) * filter(4) + smlal v24.4s, v16.4h, v1.h[7] // p0(topleft) * filter(0) + smlal v24.4s, v21.4h, v4.h[3] // p5(left[0]) * filter(5) + smlal v24.4s, v22.4h, v4.h[7] // p6(left[1]) * filter(6) + smull2 v25.4s, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + smlal2 v25.4s, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + smlal2 v25.4s, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + smlal2 v25.4s, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + smlal2 v25.4s, v16.8h, v1.h[7] // p0(topleft) * filter(0) + smlal2 v25.4s, v21.8h, v4.h[3] // p5(left[0]) * filter(5) + smlal2 v25.4s, v22.8h, v4.h[7] // p6(left[1]) * filter(6) + + smull v26.4s, v17.4h, v2.h[4] // p1(top[0]) * filter(1) + smlal v26.4s, v18.4h, v2.h[5] // p2(top[1]) * filter(2) + smlal v26.4s, v19.4h, v2.h[6] // p3(top[2]) * filter(3) + sqrshrun v5.4h, v24.4s, #4 + sqrshrun2 v5.8h, v25.4s, #4 + smin v5.8h, v5.8h, v31.8h + smlal v26.4s, v20.4h, v2.h[7] // p4(top[3]) * filter(4) + smlal v26.4s, v16.4h, v2.h[3] // p0(topleft) * filter(0) + smlal v26.4s, v21.4h, v5.h[3] // p5(left[0]) * filter(5) + smlal v26.4s, v22.4h, v5.h[7] // p6(left[1]) * filter(6) + smull2 v27.4s, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + smlal2 v27.4s, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + smlal2 v27.4s, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + smlal2 v27.4s, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + smlal2 v27.4s, v16.8h, v2.h[3] // p0(topleft) * filter(0) + smlal2 v27.4s, v21.8h, v5.h[3] // p5(left[0]) * filter(5) + smlal2 v27.4s, v22.8h, v5.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + sqrshrun v6.4h, v26.4s, #4 + sqrshrun2 v6.8h, v27.4s, #4 +.endif + smin v6.8h, v6.8h, v31.8h + + ins v0.h[2], v2.h[7] + st4 {v3.d, v4.d, v5.d, v6.d}[0], [x0], #32 + ins v0.h[0], v6.h[7] + st4 {v3.d, v4.d, v5.d, v6.d}[1], [x6], #32 + ins v0.h[1], v6.h[3] + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x6, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_filter\bpc\()_tbl): + .hword L(ipred_filter\bpc\()_tbl) - 320b + .hword L(ipred_filter\bpc\()_tbl) - 160b + .hword L(ipred_filter\bpc\()_tbl) - 80b + .hword L(ipred_filter\bpc\()_tbl) - 40b +endfunc +.endm + +filter_fn 10 +filter_fn 12 + +function ipred_filter_16bpc_neon, export=1 + ldr w8, [sp] + cmp w8, 0x3ff + b.le ipred_filter_10bpc_neon + b ipred_filter_12bpc_neon +endfunc + +// void pal_pred_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_16bpc_neon, export=1 + ld1 {v30.8h}, [x2] + clz w9, w4 + adr x6, L(pal_pred_tbl) + sub w9, w9, #25 + ldrh w9, [x6, w9, uxtw #1] + movi v31.8h, #1, lsl #8 + sub x6, x6, w9, uxtw + br x6 +40: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +4: + ld1 {v1.16b}, [x3], #16 + subs w5, w5, #4 + // Restructure v1 from a, b, c, ... into 2*a, 2*a+1, 2*b, 2*b+1, 2*c, 2*c+1, ... + add v1.16b, v1.16b, v1.16b + zip1 v0.16b, v1.16b, v1.16b + zip2 v1.16b, v1.16b, v1.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + st1 {v0.d}[0], [x0], x1 + tbl v1.16b, {v30.16b}, v1.16b + st1 {v0.d}[1], [x2], x1 + st1 {v1.d}[0], [x0], x1 + st1 {v1.d}[1], [x2], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +8: + ld1 {v2.16b, v3.16b}, [x3], #32 + subs w5, w5, #4 + add v2.16b, v2.16b, v2.16b + add v3.16b, v3.16b, v3.16b + zip1 v0.16b, v2.16b, v2.16b + zip2 v1.16b, v2.16b, v2.16b + zip1 v2.16b, v3.16b, v3.16b + zip2 v3.16b, v3.16b, v3.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + tbl v1.16b, {v30.16b}, v1.16b + st1 {v0.8h}, [x0], x1 + tbl v2.16b, {v30.16b}, v2.16b + st1 {v1.8h}, [x2], x1 + tbl v3.16b, {v30.16b}, v3.16b + st1 {v2.8h}, [x0], x1 + st1 {v3.8h}, [x2], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +16: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #4 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + st1 {v2.8h, v3.8h}, [x2], x1 + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h}, [x0], x1 + st1 {v6.8h, v7.8h}, [x2], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +32: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #2 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + add x2, x0, #64 +64: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #1 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], x1 + b.gt 64b + ret + +L(pal_pred_tbl): + .hword L(pal_pred_tbl) - 640b + .hword L(pal_pred_tbl) - 320b + .hword L(pal_pred_tbl) - 160b + .hword L(pal_pred_tbl) - 80b + .hword L(pal_pred_tbl) - 40b +endfunc + +// void ipred_cfl_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_128_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + clz w9, w3 + adr x7, L(ipred_cfl_128_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + urshr v0.8h, v31.8h, #1 + dup v1.8h, w6 // alpha + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 +L(ipred_cfl_splat_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x5], #32 + subs w4, w4, #4 + smull v2.4s, v4.4h, v1.4h // diff = ac * alpha + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v16.4s, v2.4s, #0 // sign + cmlt v17.4s, v3.4s, #0 + cmlt v18.4s, v4.4s, #0 + cmlt v19.4s, v5.4s, #0 + add v2.4s, v2.4s, v16.4s // diff + sign + add v3.4s, v3.4s, v17.4s + add v4.4s, v4.4s, v18.4s + add v5.4s, v5.4s, v19.4s + rshrn v2.4h, v2.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + st1 {v2.d}[0], [x0], x1 + st1 {v2.d}[1], [x6], x1 + st1 {v3.d}[0], [x0], x1 + st1 {v3.d}[1], [x6], x1 + b.gt L(ipred_cfl_splat_w4) + ret +L(ipred_cfl_splat_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x5], #32 + subs w4, w4, #2 + smull v2.4s, v4.4h, v1.4h // diff = ac * alpha + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v16.4s, v2.4s, #0 // sign + cmlt v17.4s, v3.4s, #0 + cmlt v18.4s, v4.4s, #0 + cmlt v19.4s, v5.4s, #0 + add v2.4s, v2.4s, v16.4s // diff + sign + add v3.4s, v3.4s, v17.4s + add v4.4s, v4.4s, v18.4s + add v5.4s, v5.4s, v19.4s + rshrn v2.4h, v2.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + st1 {v2.8h}, [x0], x1 + st1 {v3.8h}, [x6], x1 + b.gt L(ipred_cfl_splat_w8) + ret +L(ipred_cfl_splat_w16): + AARCH64_VALID_JUMP_TARGET + add x7, x5, w3, uxtw #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 +1: + ld1 {v2.8h, v3.8h}, [x5], #32 + ld1 {v4.8h, v5.8h}, [x7], #32 + subs w3, w3, #16 + smull v16.4s, v2.4h, v1.4h // diff = ac * alpha + smull2 v17.4s, v2.8h, v1.8h + smull v18.4s, v3.4h, v1.4h + smull2 v19.4s, v3.8h, v1.8h + smull v2.4s, v4.4h, v1.4h + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v20.4s, v16.4s, #0 // sign + cmlt v21.4s, v17.4s, #0 + cmlt v22.4s, v18.4s, #0 + cmlt v23.4s, v19.4s, #0 + cmlt v24.4s, v2.4s, #0 + cmlt v25.4s, v3.4s, #0 + cmlt v26.4s, v4.4s, #0 + cmlt v27.4s, v5.4s, #0 + add v16.4s, v16.4s, v20.4s // diff + sign + add v17.4s, v17.4s, v21.4s + add v18.4s, v18.4s, v22.4s + add v19.4s, v19.4s, v23.4s + add v2.4s, v2.4s, v24.4s + add v3.4s, v3.4s, v25.4s + add v4.4s, v4.4s, v26.4s + add v5.4s, v5.4s, v27.4s + rshrn v16.4h, v16.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + rshrn v6.4h, v2.4s, #6 + rshrn2 v6.8h, v3.4s, #6 + rshrn v7.4h, v4.4s, #6 + rshrn2 v7.8h, v5.4s, #6 + add v2.8h, v16.8h, v0.8h // dc + apply_sign() + add v3.8h, v17.8h, v0.8h + add v4.8h, v6.8h, v0.8h + add v5.8h, v7.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smax v4.8h, v4.8h, v30.8h + smax v5.8h, v5.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + smin v4.8h, v4.8h, v31.8h + smin v5.8h, v5.8h, v31.8h + st1 {v2.8h, v3.8h}, [x0], #32 + st1 {v4.8h, v5.8h}, [x6], #32 + b.gt 1b + subs w4, w4, #2 + add x5, x5, w9, uxtw #1 + add x7, x7, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b.gt 1b + ret + +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w8) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w4) +endfunc + +// void ipred_cfl_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_top_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + clz w9, w3 + adr x7, L(ipred_cfl_top_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + dup v1.8h, w6 // alpha + add x2, x2, #2 + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + addp v0.8h, v2.8h, v3.8h + addv h0, v0.8h + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + uaddlv s0, v0.8h + rshrn v0.4h, v0.4s, #5 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_top_tbl): + .hword L(ipred_cfl_top_tbl) - 32b + .hword L(ipred_cfl_top_tbl) - 16b + .hword L(ipred_cfl_top_tbl) - 8b + .hword L(ipred_cfl_top_tbl) - 4b +endfunc + +// void ipred_cfl_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_left_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + sub x2, x2, w4, uxtw #1 + clz w9, w3 + clz w8, w4 + adr x10, L(ipred_cfl_splat_tbl) + adr x7, L(ipred_cfl_left_tbl) + sub w9, w9, #26 + sub w8, w8, #26 + ldrh w9, [x10, w9, uxtw #1] + ldrh w8, [x7, w8, uxtw #1] + dup v1.8h, w6 // alpha + sub x9, x10, w9, uxtw + sub x7, x7, w8, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 + +L(ipred_cfl_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + addp v0.8h, v2.8h, v3.8h + addv h0, v0.8h + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + uaddlv s0, v0.8h + rshrn v0.4h, v0.4s, #5 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_tbl): + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h32) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h16) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h8) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h4) +endfunc + +// void ipred_cfl_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + sub x2, x2, w4, uxtw #1 + add w8, w3, w4 // width + height + dup v1.8h, w6 // alpha + clz w9, w3 + clz w6, w4 + dup v16.4s, w8 // width + height + adr x7, L(ipred_cfl_tbl) + rbit w8, w8 // rbit(width + height) + sub w9, w9, #22 // 26 leading bits, minus table offset 4 + sub w6, w6, #26 + clz w8, w8 // ctz(width + height) + ldrh w9, [x7, w9, uxtw #1] + ldrh w6, [x7, w6, uxtw #1] + neg w8, w8 // -ctz(width + height) + sub x9, x7, w9, uxtw + sub x7, x7, w6, uxtw + ushr v16.4s, v16.4s, #1 // (width + height) >> 1 + dup v17.4s, w8 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 + +L(ipred_cfl_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], #8 + uaddlv s0, v0.4h + add x2, x2, #2 + br x9 +L(ipred_cfl_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.4h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s2, v2.4h + cmp w4, #4 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2], #16 + uaddlv s0, v0.8h + add x2, x2, #2 + br x9 +L(ipred_cfl_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s2, v2.8h + cmp w4, #8 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2], #32 + addp v0.8h, v2.8h, v3.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x9 +L(ipred_cfl_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v2.8h, v2.8h, v3.8h + uaddlv s2, v2.8h + cmp w4, #16 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/8/32 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2], #64 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x9 +L(ipred_cfl_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + add v0.4s, v0.4s, v16.4s + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v2.8h, v2.8h, v4.8h + cmp w4, #32 + uaddlv s2, v2.8h + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #8 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_tbl): + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h4) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w4) +endfunc + +// void cfl_ac_420_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_420_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_420_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v2.8h + addp v1.8h, v1.8h, v3.8h + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + subs w8, w8, #2 + st1 {v0.8h}, [x0], #16 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + b.gt 1b + trn2 v1.2d, v0.2d, v0.2d + trn2 v0.2d, v0.2d, v0.2d +L(ipred_cfl_ac_420_w4_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 2b +3: +L(ipred_cfl_ac_420_w4_calc_subtract_dc): + // Aggregate the sums + add v24.4s, v24.4s, v25.4s + add v26.4s, v26.4s, v27.4s + add v0.4s, v24.4s, v26.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #3 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v4.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + mov v0.16b, v1.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v2.8h + addp v1.8h, v1.8h, v3.8h + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + dup v1.4h, v0.h[3] + dup v3.4h, v0.h[7] + trn2 v2.2d, v0.2d, v0.2d + subs w8, w8, #2 + st1 {v0.4h, v1.4h, v2.4h, v3.4h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw v25.4s, v25.4s, v1.4h + uaddw v26.4s, v26.4s, v2.4h + uaddw v27.4s, v27.4s, v3.4h + b.gt 1b + trn1 v0.2d, v2.2d, v3.2d + trn1 v1.2d, v2.2d, v3.2d + +L(ipred_cfl_ac_420_w8_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 2b +3: + + // Double the height and reuse the w4 summing/subtracting + lsl w6, w6, #1 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_420_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_420_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x1], x2 + add v0.8h, v0.8h, v4.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x10], x2 + add v2.8h, v2.8h, v6.8h + addp v16.8h, v16.8h, v17.8h + addp v18.8h, v18.8h, v19.8h + addp v20.8h, v20.8h, v21.8h + addp v22.8h, v22.8h, v23.8h + add v16.8h, v16.8h, v20.8h + add v18.8h, v18.8h, v22.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v2.8h, #1 + shl v2.8h, v16.8h, #1 + shl v3.8h, v18.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr q2, [x1, #32] + ld1 {v0.8h, v1.8h}, [x1], x2 + ldr q5, [x10, #32] + ld1 {v3.8h, v4.8h}, [x10], x2 + addp v2.8h, v2.8h, v2.8h + addp v0.8h, v0.8h, v1.8h + addp v5.8h, v5.8h, v5.8h + addp v3.8h, v3.8h, v4.8h + ldr q18, [x1, #32] + add v2.4h, v2.4h, v5.4h + ld1 {v16.8h, v17.8h}, [x1], x2 + add v0.8h, v0.8h, v3.8h + ldr q21, [x10, #32] + ld1 {v19.8h, v20.8h}, [x10], x2 + addp v18.8h, v18.8h, v18.8h + addp v16.8h, v16.8h, v17.8h + addp v21.8h, v21.8h, v21.8h + addp v19.8h, v19.8h, v20.8h + add v18.4h, v18.4h, v21.4h + add v16.8h, v16.8h, v19.8h + shl v1.4h, v2.4h, #1 + shl v0.8h, v0.8h, #1 + shl v3.4h, v18.4h, #1 + shl v2.8h, v16.8h, #1 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v2.8h, v4.8h, #1 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + ld1 {v4.8h}, [x1], x2 + ld1 {v6.8h}, [x10], x2 + addp v0.8h, v0.8h, v4.8h + addp v2.8h, v2.8h, v6.8h + add v0.8h, v0.8h, v2.8h + shl v0.8h, v0.8h, #1 + dup v1.8h, v0.h[3] + dup v3.8h, v0.h[7] + trn2 v2.2d, v0.2d, v3.2d + trn1 v0.2d, v0.2d, v1.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + +L(ipred_cfl_ac_420_w16_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 2b +3: + + // Quadruple the height and reuse the w4 summing/subtracting + lsl w6, w6, #2 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_tbl): + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w16) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w8) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w4) + .hword 0 + +L(ipred_cfl_ac_420_w16_tbl): + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad0) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad1) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad2) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad3) +endfunc + +// void cfl_ac_422_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_422_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_422_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + shl v2.8h, v4.8h, #2 + shl v3.8h, v6.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v0.h[3] + dup v5.8h, v0.h[7] + dup v6.4h, v2.h[3] + dup v7.8h, v2.h[7] + trn2 v1.2d, v0.2d, v5.2d + trn1 v0.2d, v0.2d, v4.2d + trn2 v3.2d, v2.2d, v7.2d + trn1 v2.2d, v2.2d, v6.2d + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_422_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_422_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + shl v2.8h, v4.8h, #2 + shl v3.8h, v6.8h, #2 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr q2, [x1, #32] + ld1 {v0.8h, v1.8h}, [x1], x2 + ldr q6, [x10, #32] + ld1 {v4.8h, v5.8h}, [x10], x2 + addp v2.8h, v2.8h, v2.8h + addp v0.8h, v0.8h, v1.8h + addp v6.8h, v6.8h, v6.8h + addp v4.8h, v4.8h, v5.8h + shl v1.4h, v2.4h, #2 + shl v0.8h, v0.8h, #2 + shl v3.4h, v6.4h, #2 + shl v2.8h, v4.8h, #2 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + addp v0.8h, v0.8h, v0.8h + addp v2.8h, v2.8h, v2.8h + shl v0.4h, v0.4h, #2 + shl v2.4h, v2.4h, #2 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_tbl): + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w16) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w8) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w4) + .hword 0 + +L(ipred_cfl_ac_422_w16_tbl): + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad0) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad1) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad2) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad3) +endfunc + +// void cfl_ac_444_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_444_tbl) + sub w8, w8, #26 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_444_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.4h}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v1.4h}, [x1], x2 + ld1 {v1.d}[1], [x10], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + ld1 {v3.8h}, [x10], x2 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + shl v0.8h, v0.8h, #3 + shl v2.8h, v2.8h, #3 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_444_w32_tbl) + ldrh w3, [x7, w3, uxtw] // (w3>>1) << 1 + lsr x2, x2, #1 // Restore the stride to one line increments + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_444_w32_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 8 + ld1 {v0.8h, v1.8h, v2.8h}, [x1], x2 + shl v2.8h, v2.8h, #3 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + dup v3.8h, v2.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 16 + ld1 {v0.8h, v1.8h}, [x1], x2 + shl v1.8h, v1.8h, #3 + shl v0.8h, v0.8h, #3 + dup v2.8h, v1.h[7] + dup v3.8h, v1.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 24 + ld1 {v0.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + dup v1.8h, v0.h[7] + dup v2.8h, v0.h[7] + dup v3.8h, v0.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + +L(ipred_cfl_ac_444_w32_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 2b +3: + + // Multiply the height by eight and reuse the w4 subtracting + lsl w6, w6, #3 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_444_tbl): + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w32) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w16) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w8) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w4) + +L(ipred_cfl_ac_444_w32_tbl): + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad0) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad2) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad4) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad6) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3310 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/asm/arm/asm.S" +#include "util.S" + +.macro avg dst, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + add \t0\().8h, \t0\().8h, \t2\().8h + add \t1\().8h, \t1\().8h, \t3\().8h + sqrshrun \dst\().8b, \t0\().8h, #5 + sqrshrun2 \dst\().16b, \t1\().8h, #5 +.endm + +.macro w_avg dst, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sub \t0\().8h, \t2\().8h, \t0\().8h + sub \t1\().8h, \t3\().8h, \t1\().8h + sqdmulh \t0\().8h, \t0\().8h, v30.8h + sqdmulh \t1\().8h, \t1\().8h, v30.8h + add \t0\().8h, \t2\().8h, \t0\().8h + add \t1\().8h, \t3\().8h, \t1\().8h + sqrshrun \dst\().8b, \t0\().8h, #4 + sqrshrun2 \dst\().16b, \t1\().8h, #4 +.endm + +.macro mask dst, t0, t1, t2, t3 + ld1 {v30.16b}, [x6], 16 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + mul v30.16b, v30.16b, v31.16b + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + shll v28.8h, v30.8b, #8 + shll2 v29.8h, v30.16b, #8 + sub \t0\().8h, \t2\().8h, \t0\().8h + sub \t1\().8h, \t3\().8h, \t1\().8h + sqdmulh \t0\().8h, \t0\().8h, v28.8h + sqdmulh \t1\().8h, \t1\().8h, v29.8h + add \t0\().8h, \t2\().8h, \t0\().8h + add \t1\().8h, \t3\().8h, \t1\().8h + sqrshrun \dst\().8b, \t0\().8h, #4 + sqrshrun2 \dst\().16b, \t1\().8h, #4 +.endm + +.macro bidir_fn type +function \type\()_8bpc_neon, export=1 + clz w4, w4 +.ifc \type, w_avg + dup v30.8h, w6 + neg v30.8h, v30.8h + shl v30.8h, v30.8h, #11 +.endif +.ifc \type, mask + movi v31.16b, #256-2 +.endif + adr x7, L(\type\()_tbl) + sub w4, w4, #24 + ldrh w4, [x7, x4, lsl #1] + \type v4, v0, v1, v2, v3 + sub x7, x7, w4, uxtw + br x7 +40: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +4: + cmp w5, #4 + st1 {v4.s}[0], [x0], x1 + st1 {v4.s}[1], [x7], x1 + st1 {v4.s}[2], [x0], x1 + st1 {v4.s}[3], [x7], x1 + b.eq 0f + \type v5, v0, v1, v2, v3 + cmp w5, #8 + st1 {v5.s}[0], [x0], x1 + st1 {v5.s}[1], [x7], x1 + st1 {v5.s}[2], [x0], x1 + st1 {v5.s}[3], [x7], x1 + b.eq 0f + \type v4, v0, v1, v2, v3 + st1 {v4.s}[0], [x0], x1 + st1 {v4.s}[1], [x7], x1 + \type v5, v0, v1, v2, v3 + st1 {v4.s}[2], [x0], x1 + st1 {v4.s}[3], [x7], x1 + st1 {v5.s}[0], [x0], x1 + st1 {v5.s}[1], [x7], x1 + st1 {v5.s}[2], [x0], x1 + st1 {v5.s}[3], [x7], x1 + ret +80: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +8: + st1 {v4.d}[0], [x0], x1 + \type v5, v0, v1, v2, v3 + st1 {v4.d}[1], [x7], x1 + st1 {v5.d}[0], [x0], x1 + subs w5, w5, #4 + st1 {v5.d}[1], [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 8b +16: + AARCH64_VALID_JUMP_TARGET + \type v5, v0, v1, v2, v3 + st1 {v4.16b}, [x0], x1 + \type v6, v0, v1, v2, v3 + st1 {v5.16b}, [x0], x1 + \type v7, v0, v1, v2, v3 + st1 {v6.16b}, [x0], x1 + subs w5, w5, #4 + st1 {v7.16b}, [x0], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 16b +320: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +32: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + st1 {v4.16b,v5.16b}, [x0], x1 + \type v7, v0, v1, v2, v3 + subs w5, w5, #2 + st1 {v6.16b,v7.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 32b +640: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +64: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + \type v7, v0, v1, v2, v3 + \type v16, v0, v1, v2, v3 + \type v17, v0, v1, v2, v3 + st1 {v4.16b,v5.16b,v6.16b,v7.16b}, [x0], x1 + \type v18, v0, v1, v2, v3 + \type v19, v0, v1, v2, v3 + subs w5, w5, #2 + st1 {v16.16b,v17.16b,v18.16b,v19.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 64b +1280: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 +128: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + \type v7, v0, v1, v2, v3 + \type v16, v0, v1, v2, v3 + \type v17, v0, v1, v2, v3 + st1 {v4.16b,v5.16b,v6.16b,v7.16b}, [x0], x1 + \type v18, v0, v1, v2, v3 + \type v19, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v16.16b,v17.16b,v18.16b,v19.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 128b +0: + ret +L(\type\()_tbl): + .hword L(\type\()_tbl) - 1280b + .hword L(\type\()_tbl) - 640b + .hword L(\type\()_tbl) - 320b + .hword L(\type\()_tbl) - 16b + .hword L(\type\()_tbl) - 80b + .hword L(\type\()_tbl) - 40b +endfunc +.endm + +bidir_fn avg +bidir_fn w_avg +bidir_fn mask + + +.macro w_mask_fn type +function w_mask_\type\()_8bpc_neon, export=1 + clz w8, w4 + adr x9, L(w_mask_\type\()_tbl) + sub w8, w8, #24 + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + mov w10, #6903 + dup v0.8h, w10 +.if \type == 444 + movi v1.16b, #64 +.elseif \type == 422 + dup v2.8b, w7 + movi v3.8b, #129 + sub v3.8b, v3.8b, v2.8b +.elseif \type == 420 + dup v2.8h, w7 + movi v3.8h, #1, lsl #8 + sub v3.8h, v3.8h, v2.8h +.endif + add x12, x0, x1 + lsl x1, x1, #1 + br x9 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 (four rows at once) + ld1 {v6.8h, v7.8h}, [x3], #32 // tmp2 (four rows at once) + subs w5, w5, #4 + sub v16.8h, v6.8h, v4.8h + sub v17.8h, v7.8h, v5.8h + sabd v18.8h, v4.8h, v6.8h + sabd v19.8h, v5.8h, v7.8h + uqsub v18.8h, v0.8h, v18.8h + uqsub v19.8h, v0.8h, v19.8h + ushr v18.8h, v18.8h, #8 + ushr v19.8h, v19.8h, #8 + shl v20.8h, v18.8h, #9 + shl v21.8h, v19.8h, #9 + sqdmulh v20.8h, v20.8h, v16.8h + sqdmulh v21.8h, v21.8h, v17.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v5.8h + sqrshrun v22.8b, v20.8h, #4 + sqrshrun v23.8b, v21.8h, #4 +.if \type == 444 + uzp1 v18.16b, v18.16b, v19.16b // Same as xtn, xtn2 + sub v18.16b, v1.16b, v18.16b + st1 {v18.16b}, [x6], #16 +.elseif \type == 422 + addp v18.8h, v18.8h, v19.8h + xtn v18.8b, v18.8h + uhsub v18.8b, v3.8b, v18.8b + st1 {v18.8b}, [x6], #8 +.elseif \type == 420 + trn1 v24.2d, v18.2d, v19.2d + trn2 v25.2d, v18.2d, v19.2d + add v24.8h, v24.8h, v25.8h + addp v18.8h, v24.8h, v24.8h + sub v18.4h, v3.4h, v18.4h + rshrn v18.8b, v18.8h, #2 + st1 {v18.s}[0], [x6], #4 +.endif + st1 {v22.s}[0], [x0], x1 + st1 {v22.s}[1], [x12], x1 + st1 {v23.s}[0], [x0], x1 + st1 {v23.s}[1], [x12], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 + ld1 {v6.8h, v7.8h}, [x3], #32 + subs w5, w5, #2 + sub v16.8h, v6.8h, v4.8h + sub v17.8h, v7.8h, v5.8h + sabd v18.8h, v4.8h, v6.8h + sabd v19.8h, v5.8h, v7.8h + uqsub v18.8h, v0.8h, v18.8h + uqsub v19.8h, v0.8h, v19.8h + ushr v18.8h, v18.8h, #8 + ushr v19.8h, v19.8h, #8 + shl v20.8h, v18.8h, #9 + shl v21.8h, v19.8h, #9 + sqdmulh v20.8h, v20.8h, v16.8h + sqdmulh v21.8h, v21.8h, v17.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v5.8h + sqrshrun v22.8b, v20.8h, #4 + sqrshrun v23.8b, v21.8h, #4 +.if \type == 444 + uzp1 v18.16b, v18.16b, v19.16b // Same as xtn, xtn2 + sub v18.16b, v1.16b, v18.16b + st1 {v18.16b}, [x6], #16 +.elseif \type == 422 + addp v18.8h, v18.8h, v19.8h + xtn v18.8b, v18.8h + uhsub v18.8b, v3.8b, v18.8b + st1 {v18.8b}, [x6], #8 +.elseif \type == 420 + add v18.8h, v18.8h, v19.8h + addp v18.8h, v18.8h, v18.8h + sub v18.4h, v3.4h, v18.4h + rshrn v18.8b, v18.8h, #2 + st1 {v18.s}[0], [x6], #4 +.endif + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x12], x1 + b.gt 8b + ret +1280: +640: +320: +160: + AARCH64_VALID_JUMP_TARGET + mov w11, w4 + sub x1, x1, w4, uxtw +.if \type == 444 + add x10, x6, w4, uxtw +.elseif \type == 422 + add x10, x6, x11, lsr #1 +.endif + add x9, x3, w4, uxtw #1 + add x7, x2, w4, uxtw #1 +161: + mov w8, w4 +16: + ld1 {v4.8h, v5.8h}, [x2], #32 + ld1 {v6.8h, v7.8h}, [x3], #32 + ld1 {v16.8h, v17.8h}, [x7], #32 + ld1 {v18.8h, v19.8h}, [x9], #32 + subs w8, w8, #16 + sub v6.8h, v6.8h, v4.8h + sub v7.8h, v7.8h, v5.8h + sub v18.8h, v18.8h, v16.8h + sub v19.8h, v19.8h, v17.8h + abs v20.8h, v6.8h + abs v21.8h, v7.8h + abs v22.8h, v18.8h + abs v23.8h, v19.8h + uqsub v20.8h, v0.8h, v20.8h + uqsub v21.8h, v0.8h, v21.8h + uqsub v22.8h, v0.8h, v22.8h + uqsub v23.8h, v0.8h, v23.8h + ushr v20.8h, v20.8h, #8 + ushr v21.8h, v21.8h, #8 + ushr v22.8h, v22.8h, #8 + ushr v23.8h, v23.8h, #8 + shl v24.8h, v20.8h, #9 + shl v25.8h, v21.8h, #9 + shl v26.8h, v22.8h, #9 + shl v27.8h, v23.8h, #9 + sqdmulh v24.8h, v24.8h, v6.8h + sqdmulh v25.8h, v25.8h, v7.8h + sqdmulh v26.8h, v26.8h, v18.8h + sqdmulh v27.8h, v27.8h, v19.8h + add v24.8h, v24.8h, v4.8h + add v25.8h, v25.8h, v5.8h + add v26.8h, v26.8h, v16.8h + add v27.8h, v27.8h, v17.8h + sqrshrun v24.8b, v24.8h, #4 + sqrshrun v25.8b, v25.8h, #4 + sqrshrun v26.8b, v26.8h, #4 + sqrshrun v27.8b, v27.8h, #4 +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // Same as xtn, xtn2 + uzp1 v21.16b, v22.16b, v23.16b // Ditto + sub v20.16b, v1.16b, v20.16b + sub v21.16b, v1.16b, v21.16b + st1 {v20.16b}, [x6], #16 + st1 {v21.16b}, [x10], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h + addp v21.8h, v22.8h, v23.8h + xtn v20.8b, v20.8h + xtn v21.8b, v21.8h + uhsub v20.8b, v3.8b, v20.8b + uhsub v21.8b, v3.8b, v21.8b + st1 {v20.8b}, [x6], #8 + st1 {v21.8b}, [x10], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v22.8h + add v21.8h, v21.8h, v23.8h + addp v20.8h, v20.8h, v21.8h + sub v20.8h, v3.8h, v20.8h + rshrn v20.8b, v20.8h, #2 + st1 {v20.8b}, [x6], #8 +.endif + st1 {v24.8b, v25.8b}, [x0], #16 + st1 {v26.8b, v27.8b}, [x12], #16 + b.gt 16b + subs w5, w5, #2 + add x2, x2, w4, uxtw #1 + add x3, x3, w4, uxtw #1 + add x7, x7, w4, uxtw #1 + add x9, x9, w4, uxtw #1 +.if \type == 444 + add x6, x6, w4, uxtw + add x10, x10, w4, uxtw +.elseif \type == 422 + add x6, x6, x11, lsr #1 + add x10, x10, x11, lsr #1 +.endif + add x0, x0, x1 + add x12, x12, x1 + b.gt 161b + ret +L(w_mask_\type\()_tbl): + .hword L(w_mask_\type\()_tbl) - 1280b + .hword L(w_mask_\type\()_tbl) - 640b + .hword L(w_mask_\type\()_tbl) - 320b + .hword L(w_mask_\type\()_tbl) - 160b + .hword L(w_mask_\type\()_tbl) - 8b + .hword L(w_mask_\type\()_tbl) - 4b +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + + +function blend_8bpc_neon, export=1 + adr x6, L(blend_tbl) + clz w3, w3 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + br x6 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8b}, [x5], #8 + ld1 {v1.d}[0], [x2], #8 + ld1 {v0.s}[0], [x0] + subs w4, w4, #2 + ld1 {v0.s}[1], [x8] + sub v3.8b, v4.8b, v2.8b + umull v5.8h, v1.8b, v2.8b + umlal v5.8h, v0.8b, v3.8b + rshrn v6.8b, v5.8h, #6 + st1 {v6.s}[0], [x0], x1 + st1 {v6.s}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b}, [x5], #16 + ld1 {v1.16b}, [x2], #16 + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + sub v3.16b, v4.16b, v2.16b + subs w4, w4, #2 + umull v5.8h, v1.8b, v2.8b + umlal v5.8h, v0.8b, v3.8b + umull2 v6.8h, v1.16b, v2.16b + umlal2 v6.8h, v0.16b, v3.16b + rshrn v7.8b, v5.8h, #6 + rshrn2 v7.16b, v6.8h, #6 + st1 {v7.d}[0], [x0], x1 + st1 {v7.d}[1], [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x5], #32 + ld1 {v5.16b, v6.16b}, [x2], #32 + ld1 {v0.16b}, [x0] + subs w4, w4, #2 + sub v7.16b, v4.16b, v1.16b + sub v20.16b, v4.16b, v2.16b + ld1 {v3.16b}, [x8] + umull v16.8h, v5.8b, v1.8b + umlal v16.8h, v0.8b, v7.8b + umull2 v17.8h, v5.16b, v1.16b + umlal2 v17.8h, v0.16b, v7.16b + umull v21.8h, v6.8b, v2.8b + umlal v21.8h, v3.8b, v20.8b + umull2 v22.8h, v6.16b, v2.16b + umlal2 v22.8h, v3.16b, v20.16b + rshrn v18.8b, v16.8h, #6 + rshrn2 v18.16b, v17.8h, #6 + rshrn v19.8b, v21.8h, #6 + rshrn2 v19.16b, v22.8h, #6 + st1 {v18.16b}, [x0], x1 + st1 {v19.16b}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x5], #64 + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], #64 + ld1 {v20.16b, v21.16b}, [x0] + subs w4, w4, #2 + ld1 {v22.16b, v23.16b}, [x8] + sub v5.16b, v4.16b, v0.16b + sub v6.16b, v4.16b, v1.16b + sub v30.16b, v4.16b, v2.16b + sub v31.16b, v4.16b, v3.16b + umull v24.8h, v16.8b, v0.8b + umlal v24.8h, v20.8b, v5.8b + umull2 v26.8h, v16.16b, v0.16b + umlal2 v26.8h, v20.16b, v5.16b + umull v28.8h, v17.8b, v1.8b + umlal v28.8h, v21.8b, v6.8b + umull2 v7.8h, v17.16b, v1.16b + umlal2 v7.8h, v21.16b, v6.16b + umull v27.8h, v18.8b, v2.8b + umlal v27.8h, v22.8b, v30.8b + umull2 v1.8h, v18.16b, v2.16b + umlal2 v1.8h, v22.16b, v30.16b + umull v29.8h, v19.8b, v3.8b + umlal v29.8h, v23.8b, v31.8b + umull2 v21.8h, v19.16b, v3.16b + umlal2 v21.8h, v23.16b, v31.16b + rshrn v24.8b, v24.8h, #6 + rshrn2 v24.16b, v26.8h, #6 + rshrn v25.8b, v28.8h, #6 + rshrn2 v25.16b, v7.8h, #6 + rshrn v27.8b, v27.8h, #6 + rshrn2 v27.16b, v1.8h, #6 + rshrn v28.8b, v29.8h, #6 + rshrn2 v28.16b, v21.8h, #6 + st1 {v24.16b, v25.16b}, [x0], x1 + st1 {v27.16b, v28.16b}, [x8], x1 + b.gt 32b + ret +L(blend_tbl): + .hword L(blend_tbl) - 32b + .hword L(blend_tbl) - 16b + .hword L(blend_tbl) - 8b + .hword L(blend_tbl) - 4b +endfunc + +function blend_h_8bpc_neon, export=1 + adr x6, L(blend_h_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w4, uxtw + sub w4, w4, w4, lsr #2 + clz w7, w3 + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + sub w7, w7, #24 + ldrh w7, [x6, x7, lsl #1] + sub x6, x6, w7, uxtw + br x6 +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.h}[0], [x5], #2 + ld1 {v1.s}[0], [x2], #4 + subs w4, w4, #2 + ld1 {v2.h}[0], [x0] + zip1 v0.8b, v0.8b, v0.8b + sub v3.8b, v4.8b, v0.8b + ld1 {v2.h}[1], [x8] + umull v5.8h, v1.8b, v0.8b + umlal v5.8h, v2.8b, v3.8b + rshrn v5.8b, v5.8h, #6 + st1 {v5.h}[0], [x0], x1 + st1 {v5.h}[1], [x8], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.8b, v1.8b}, [x5], #2 + ld1 {v2.8b}, [x2], #8 + subs w4, w4, #2 + ext v0.8b, v0.8b, v1.8b, #4 + ld1 {v3.s}[0], [x0] + sub v5.8b, v4.8b, v0.8b + ld1 {v3.s}[1], [x8] + umull v6.8h, v2.8b, v0.8b + umlal v6.8h, v3.8b, v5.8b + rshrn v6.8b, v6.8h, #6 + st1 {v6.s}[0], [x0], x1 + st1 {v6.s}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.16b, v1.16b}, [x5], #2 + ld1 {v2.16b}, [x2], #16 + ld1 {v3.d}[0], [x0] + ext v0.16b, v0.16b, v1.16b, #8 + sub v5.16b, v4.16b, v0.16b + ld1 {v3.d}[1], [x8] + subs w4, w4, #2 + umull v6.8h, v0.8b, v2.8b + umlal v6.8h, v3.8b, v5.8b + umull2 v7.8h, v0.16b, v2.16b + umlal2 v7.8h, v3.16b, v5.16b + rshrn v16.8b, v6.8h, #6 + rshrn2 v16.16b, v7.8h, #6 + st1 {v16.d}[0], [x0], x1 + st1 {v16.d}[1], [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.16b, v1.16b}, [x5], #2 + ld1 {v2.16b, v3.16b}, [x2], #32 + ld1 {v5.16b}, [x0] + sub v7.16b, v4.16b, v0.16b + sub v16.16b, v4.16b, v1.16b + ld1 {v6.16b}, [x8] + subs w4, w4, #2 + umull v17.8h, v0.8b, v2.8b + umlal v17.8h, v5.8b, v7.8b + umull2 v18.8h, v0.16b, v2.16b + umlal2 v18.8h, v5.16b, v7.16b + umull v19.8h, v1.8b, v3.8b + umlal v19.8h, v6.8b, v16.8b + umull2 v20.8h, v1.16b, v3.16b + umlal2 v20.8h, v6.16b, v16.16b + rshrn v21.8b, v17.8h, #6 + rshrn2 v21.16b, v18.8h, #6 + rshrn v22.8b, v19.8h, #6 + rshrn2 v22.16b, v20.8h, #6 + st1 {v21.16b}, [x0], x1 + st1 {v22.16b}, [x8], x1 + b.gt 16b + ret +1280: +640: +320: + AARCH64_VALID_JUMP_TARGET + sub x1, x1, w3, uxtw + add x7, x2, w3, uxtw +321: + ld2r {v0.16b, v1.16b}, [x5], #2 + mov w6, w3 + sub v20.16b, v4.16b, v0.16b + sub v21.16b, v4.16b, v1.16b +32: + ld1 {v16.16b, v17.16b}, [x2], #32 + ld1 {v2.16b, v3.16b}, [x0] + subs w6, w6, #32 + umull v23.8h, v0.8b, v16.8b + umlal v23.8h, v2.8b, v20.8b + ld1 {v18.16b, v19.16b}, [x7], #32 + umull2 v27.8h, v0.16b, v16.16b + umlal2 v27.8h, v2.16b, v20.16b + ld1 {v6.16b, v7.16b}, [x8] + umull v24.8h, v0.8b, v17.8b + umlal v24.8h, v3.8b, v20.8b + umull2 v28.8h, v0.16b, v17.16b + umlal2 v28.8h, v3.16b, v20.16b + umull v25.8h, v1.8b, v18.8b + umlal v25.8h, v6.8b, v21.8b + umull2 v5.8h, v1.16b, v18.16b + umlal2 v5.8h, v6.16b, v21.16b + rshrn v29.8b, v23.8h, #6 + rshrn2 v29.16b, v27.8h, #6 + umull v26.8h, v1.8b, v19.8b + umlal v26.8h, v7.8b, v21.8b + umull2 v31.8h, v1.16b, v19.16b + umlal2 v31.8h, v7.16b, v21.16b + rshrn v30.8b, v24.8h, #6 + rshrn2 v30.16b, v28.8h, #6 + rshrn v23.8b, v25.8h, #6 + rshrn2 v23.16b, v5.8h, #6 + rshrn v24.8b, v26.8h, #6 + st1 {v29.16b, v30.16b}, [x0], #32 + rshrn2 v24.16b, v31.8h, #6 + st1 {v23.16b, v24.16b}, [x8], #32 + b.gt 32b + subs w4, w4, #2 + add x0, x0, x1 + add x8, x8, x1 + add x2, x2, w3, uxtw + add x7, x7, w3, uxtw + b.gt 321b + ret +L(blend_h_tbl): + .hword L(blend_h_tbl) - 1280b + .hword L(blend_h_tbl) - 640b + .hword L(blend_h_tbl) - 320b + .hword L(blend_h_tbl) - 16b + .hword L(blend_h_tbl) - 8b + .hword L(blend_h_tbl) - 4b + .hword L(blend_h_tbl) - 2b +endfunc + +function blend_v_8bpc_neon, export=1 + adr x6, L(blend_v_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w3, uxtw + clz w3, w3 + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + br x6 +20: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.8b}, [x5] + sub v1.8b, v4.8b, v0.8b +2: + ld1 {v2.h}[0], [x2], #2 + ld1 {v3.b}[0], [x0] + subs w4, w4, #2 + ld1 {v2.b}[1], [x2] + ld1 {v3.b}[1], [x8] + umull v5.8h, v2.8b, v0.8b + umlal v5.8h, v3.8b, v1.8b + rshrn v5.8b, v5.8h, #6 + add x2, x2, #2 + st1 {v5.b}[0], [x0], x1 + st1 {v5.b}[1], [x8], x1 + b.gt 2b + ret +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x5] + sub x1, x1, #2 + sub v1.8b, v4.8b, v0.8b +4: + ld1 {v2.8b}, [x2], #8 + ld1 {v3.s}[0], [x0] + ld1 {v3.s}[1], [x8] + subs w4, w4, #2 + umull v5.8h, v2.8b, v0.8b + umlal v5.8h, v3.8b, v1.8b + rshrn v5.8b, v5.8h, #6 + st1 {v5.h}[0], [x0], #2 + st1 {v5.h}[2], [x8], #2 + st1 {v5.b}[2], [x0], x1 + st1 {v5.b}[6], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2d}, [x5] + sub x1, x1, #4 + sub v1.16b, v4.16b, v0.16b +8: + ld1 {v2.16b}, [x2], #16 + ld1 {v3.d}[0], [x0] + ld1 {v3.d}[1], [x8] + subs w4, w4, #2 + umull v5.8h, v0.8b, v2.8b + umlal v5.8h, v3.8b, v1.8b + umull2 v6.8h, v0.16b, v2.16b + umlal2 v6.8h, v3.16b, v1.16b + rshrn v7.8b, v5.8h, #6 + rshrn2 v7.16b, v6.8h, #6 + st1 {v7.s}[0], [x0], #4 + st1 {v7.s}[2], [x8], #4 + st1 {v7.h}[2], [x0], x1 + st1 {v7.h}[6], [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x5] + sub x1, x1, #8 + sub v2.16b, v4.16b, v0.16b +16: + ld1 {v5.16b, v6.16b}, [x2], #32 + ld1 {v7.16b}, [x0] + subs w4, w4, #2 + ld1 {v16.16b}, [x8] + umull v17.8h, v5.8b, v0.8b + umlal v17.8h, v7.8b, v2.8b + umull2 v18.8h, v5.16b, v0.16b + umlal2 v18.8h, v7.16b, v2.16b + umull v20.8h, v6.8b, v0.8b + umlal v20.8h, v16.8b, v2.8b + umull2 v21.8h, v6.16b, v0.16b + umlal2 v21.8h, v16.16b, v2.16b + rshrn v19.8b, v17.8h, #6 + rshrn2 v19.16b, v18.8h, #6 + rshrn v22.8b, v20.8h, #6 + rshrn2 v22.16b, v21.8h, #6 + st1 {v19.8b}, [x0], #8 + st1 {v22.8b}, [x8], #8 + st1 {v19.s}[2], [x0], x1 + st1 {v22.s}[2], [x8], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x5] + sub x1, x1, #16 + sub v2.16b, v4.16b, v0.16b + sub v3.8b, v4.8b, v1.8b +32: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], #64 + ld1 {v5.16b, v6.16b}, [x0] + subs w4, w4, #2 + ld1 {v20.16b, v21.16b}, [x8] + umull v22.8h, v16.8b, v0.8b + umlal v22.8h, v5.8b, v2.8b + umull2 v23.8h, v16.16b, v0.16b + umlal2 v23.8h, v5.16b, v2.16b + umull v28.8h, v17.8b, v1.8b + umlal v28.8h, v6.8b, v3.8b + umull v30.8h, v18.8b, v0.8b + umlal v30.8h, v20.8b, v2.8b + umull2 v31.8h, v18.16b, v0.16b + umlal2 v31.8h, v20.16b, v2.16b + umull v25.8h, v19.8b, v1.8b + umlal v25.8h, v21.8b, v3.8b + rshrn v24.8b, v22.8h, #6 + rshrn2 v24.16b, v23.8h, #6 + rshrn v28.8b, v28.8h, #6 + rshrn v30.8b, v30.8h, #6 + rshrn2 v30.16b, v31.8h, #6 + rshrn v27.8b, v25.8h, #6 + st1 {v24.16b}, [x0], #16 + st1 {v30.16b}, [x8], #16 + st1 {v28.8b}, [x0], x1 + st1 {v27.8b}, [x8], x1 + b.gt 32b + ret +L(blend_v_tbl): + .hword L(blend_v_tbl) - 320b + .hword L(blend_v_tbl) - 160b + .hword L(blend_v_tbl) - 80b + .hword L(blend_v_tbl) - 40b + .hword L(blend_v_tbl) - 20b +endfunc + + +// This has got the same signature as the put_8tap functions, +// and assumes that x8 is set to (clz(w)-24). +function put_neon + adr x9, L(put_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.h}[0], [x2], x3 + ld1 {v1.h}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.h}[0], [x0], x1 + st1 {v1.h}[0], [x0], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], x3 + ld1 {v1.s}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.s}[0], [x0], x1 + st1 {v1.s}[0], [x0], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], x3 + ld1 {v1.8b}, [x2], x3 + subs w5, w5, #2 + st1 {v0.8b}, [x0], x1 + st1 {v1.8b}, [x0], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x8, x0, x1 + lsl x1, x1, #1 + add x9, x2, x3 + lsl x3, x3, #1 +16: + ld1 {v0.16b}, [x2], x3 + ld1 {v1.16b}, [x9], x3 + subs w5, w5, #2 + st1 {v0.16b}, [x0], x1 + st1 {v1.16b}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + subs w5, w5, #1 + stp x8, x9, [x0, #16] + add x2, x2, x3 + add x0, x0, x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + ldp x10, x11, [x2, #32] + stp x8, x9, [x0, #16] + subs w5, w5, #1 + ldp x12, x13, [x2, #48] + stp x10, x11, [x0, #32] + stp x12, x13, [x0, #48] + add x2, x2, x3 + add x0, x0, x1 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x2, x2, x3 + add x0, x0, x1 + b.gt 128b + ret + +L(put_tbl): + .hword L(put_tbl) - 128b + .hword L(put_tbl) - 64b + .hword L(put_tbl) - 32b + .hword L(put_tbl) - 160b + .hword L(put_tbl) - 8b + .hword L(put_tbl) - 4b + .hword L(put_tbl) - 2b +endfunc + + +// This has got the same signature as the prep_8tap functions, +// and assumes that x8 is set to (clz(w)-24), and x7 to w*2. +function prep_neon + adr x9, L(prep_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x1], x2 + ld1 {v1.s}[0], [x1], x2 + subs w4, w4, #2 + ushll v0.8h, v0.8b, #4 + ushll v1.8h, v1.8b, #4 + st1 {v0.4h, v1.4h}, [x0], #16 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x1], x2 + subs w4, w4, #2 + ushll v0.8h, v0.8b, #4 + ushll v1.8h, v1.8b, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +16: + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x9], x2 + subs w4, w4, #2 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + add x8, x0, w3, uxtw +32: + ld1 {v0.16b, v1.16b}, [x1], x2 + subs w4, w4, #2 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ld1 {v2.16b, v3.16b}, [x1], x2 + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + ushll v16.8h, v2.8b, #4 + st1 {v4.8h, v5.8h}, [x0], x7 + ushll2 v17.8h, v2.16b, #4 + st1 {v6.8h, v7.8h}, [x8], x7 + ushll v18.8h, v3.8b, #4 + st1 {v16.8h, v17.8h}, [x0], x7 + ushll2 v19.8h, v3.16b, #4 + st1 {v18.8h, v19.8h}, [x8], x7 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + add x8, x0, #32 + mov x6, #64 +64: + ldp q0, q1, [x1] + subs w4, w4, #1 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ldp q2, q3, [x1, #32] + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + add x1, x1, x2 + ushll v16.8h, v2.8b, #4 + st1 {v4.8h, v5.8h}, [x0], x6 + ushll2 v17.8h, v2.16b, #4 + ushll v18.8h, v3.8b, #4 + st1 {v6.8h, v7.8h}, [x8], x6 + ushll2 v19.8h, v3.16b, #4 + st1 {v16.8h, v17.8h}, [x0], x6 + st1 {v18.8h, v19.8h}, [x8], x6 + b.gt 64b + ret +1280: + AARCH64_VALID_JUMP_TARGET + add x8, x0, #64 + mov x6, #128 +128: + ldp q0, q1, [x1] + ldp q2, q3, [x1, #32] + ushll v16.8h, v0.8b, #4 + ushll2 v17.8h, v0.16b, #4 + ushll v18.8h, v1.8b, #4 + ushll2 v19.8h, v1.16b, #4 + ushll v20.8h, v2.8b, #4 + ushll2 v21.8h, v2.16b, #4 + ldp q4, q5, [x1, #64] + st1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x0], x6 + ushll v22.8h, v3.8b, #4 + ushll2 v23.8h, v3.16b, #4 + ushll v24.8h, v4.8b, #4 + ushll2 v25.8h, v4.16b, #4 + ushll v26.8h, v5.8b, #4 + ushll2 v27.8h, v5.16b, #4 + ldp q6, q7, [x1, #96] + st1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x8], x6 + ushll v28.8h, v6.8b, #4 + ushll2 v29.8h, v6.16b, #4 + ushll v30.8h, v7.8b, #4 + ushll2 v31.8h, v7.16b, #4 + subs w4, w4, #1 + add x1, x1, x2 + st1 {v24.8h, v25.8h, v26.8h, v27.8h}, [x0], x6 + st1 {v28.8h, v29.8h, v30.8h, v31.8h}, [x8], x6 + b.gt 128b + ret + +L(prep_tbl): + .hword L(prep_tbl) - 1280b + .hword L(prep_tbl) - 640b + .hword L(prep_tbl) - 320b + .hword L(prep_tbl) - 160b + .hword L(prep_tbl) - 8b + .hword L(prep_tbl) - 4b +endfunc + + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}[0], [\s0], \strd + ld1 {\d1\wd}[0], [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}[0], [\s0], \strd + ld1 {\d3\wd}[0], [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}[0], [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}[0], [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}[0], [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}, [\s0], \strd + ld1 {\d1\wd}, [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}, [\s0], \strd + ld1 {\d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}, [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}, [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}, [\s0], \strd +.endif +.endm +.macro load_h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_s s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .s, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_8b s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .8b, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_16b s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .16b, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro interleave_1 wd, r0, r1, r2, r3, r4 + trn1 \r0\wd, \r0\wd, \r1\wd + trn1 \r1\wd, \r1\wd, \r2\wd +.ifnb \r3 + trn1 \r2\wd, \r2\wd, \r3\wd + trn1 \r3\wd, \r3\wd, \r4\wd +.endif +.endm +.macro interleave_1_h r0, r1, r2, r3, r4 + interleave_1 .4h, \r0, \r1, \r2, \r3, \r4 +.endm +.macro interleave_1_s r0, r1, r2, r3, r4 + interleave_1 .2s, \r0, \r1, \r2, \r3, \r4 +.endm +.macro interleave_2 wd, r0, r1, r2, r3, r4, r5 + trn1 \r0\wd, \r0\wd, \r2\wd + trn1 \r1\wd, \r1\wd, \r3\wd + trn1 \r2\wd, \r2\wd, \r4\wd + trn1 \r3\wd, \r3\wd, \r5\wd +.endm +.macro interleave_2_s r0, r1, r2, r3, r4, r5 + interleave_2 .2s, \r0, \r1, \r2, \r3, \r4, \r5 +.endm +.macro uxtl_b r0, r1, r2, r3, r4, r5, r6 + uxtl \r0\().8h, \r0\().8b + uxtl \r1\().8h, \r1\().8b +.ifnb \r2 + uxtl \r2\().8h, \r2\().8b + uxtl \r3\().8h, \r3\().8b +.endif +.ifnb \r4 + uxtl \r4\().8h, \r4\().8b +.endif +.ifnb \r5 + uxtl \r5\().8h, \r5\().8b +.endif +.ifnb \r6 + uxtl \r6\().8h, \r6\().8b +.endif +.endm +.macro mul_mla_4 d, s0, s1, s2, s3, wd + mul \d\wd, \s0\wd, v0.h[0] + mla \d\wd, \s1\wd, v0.h[1] + mla \d\wd, \s2\wd, v0.h[2] + mla \d\wd, \s3\wd, v0.h[3] +.endm +// Interleaving the mul/mla chains actually hurts performance +// significantly on Cortex A53, thus keeping mul/mla tightly +// chained like this. +.macro mul_mla_8_0_4h d0, s0, s1, s2, s3, s4, s5, s6, s7 + mul \d0\().4h, \s0\().4h, v0.h[0] + mla \d0\().4h, \s1\().4h, v0.h[1] + mla \d0\().4h, \s2\().4h, v0.h[2] + mla \d0\().4h, \s3\().4h, v0.h[3] + mla \d0\().4h, \s4\().4h, v0.h[4] + mla \d0\().4h, \s5\().4h, v0.h[5] + mla \d0\().4h, \s6\().4h, v0.h[6] + mla \d0\().4h, \s7\().4h, v0.h[7] +.endm +.macro mul_mla_8_0 d0, s0, s1, s2, s3, s4, s5, s6, s7 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] +.endm +.macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] + mul \d1\().8h, \s1\().8h, v0.h[0] + mla \d1\().8h, \s2\().8h, v0.h[1] + mla \d1\().8h, \s3\().8h, v0.h[2] + mla \d1\().8h, \s4\().8h, v0.h[3] + mla \d1\().8h, \s5\().8h, v0.h[4] + mla \d1\().8h, \s6\().8h, v0.h[5] + mla \d1\().8h, \s7\().8h, v0.h[6] + mla \d1\().8h, \s8\().8h, v0.h[7] +.endm +.macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] + mul \d1\().8h, \s2\().8h, v0.h[0] + mla \d1\().8h, \s3\().8h, v0.h[1] + mla \d1\().8h, \s4\().8h, v0.h[2] + mla \d1\().8h, \s5\().8h, v0.h[3] + mla \d1\().8h, \s6\().8h, v0.h[4] + mla \d1\().8h, \s7\().8h, v0.h[5] + mla \d1\().8h, \s8\().8h, v0.h[6] + mla \d1\().8h, \s9\().8h, v0.h[7] +.endm +.macro sqrshrun_b shift, r0, r1, r2, r3 + sqrshrun \r0\().8b, \r0\().8h, #\shift +.ifnb \r1 + sqrshrun \r1\().8b, \r1\().8h, #\shift +.endif +.ifnb \r2 + sqrshrun \r2\().8b, \r2\().8h, #\shift + sqrshrun \r3\().8b, \r3\().8h, #\shift +.endif +.endm +.macro srshr_h shift, r0, r1, r2, r3 + srshr \r0\().8h, \r0\().8h, #\shift +.ifnb \r1 + srshr \r1\().8h, \r1\().8h, #\shift +.endif +.ifnb \r2 + srshr \r2\().8h, \r2\().8h, #\shift + srshr \r3\().8h, \r3\().8h, #\shift +.endif +.endm +.macro st_h strd, reg, lanes + st1 {\reg\().h}[0], [x0], \strd + st1 {\reg\().h}[1], [x8], \strd +.if \lanes > 2 + st1 {\reg\().h}[2], [x0], \strd + st1 {\reg\().h}[3], [x8], \strd +.endif +.endm +.macro st_s strd, r0, r1 + st1 {\r0\().s}[0], [x0], \strd + st1 {\r0\().s}[1], [x8], \strd +.ifnb \r1 + st1 {\r1\().s}[0], [x0], \strd + st1 {\r1\().s}[1], [x8], \strd +.endif +.endm +.macro st_d strd, r0, r1 + st1 {\r0\().d}[0], [x0], \strd + st1 {\r0\().d}[1], [x8], \strd +.ifnb \r1 + st1 {\r1\().d}[0], [x0], \strd + st1 {\r1\().d}[1], [x8], \strd +.endif +.endm +.macro shift_store_4 type, strd, r0, r1 +.ifc \type, put + sqrshrun_b 6, \r0, \r1 + st_s \strd, \r0, \r1 +.else + srshr_h 2, \r0, \r1 + st_d \strd, \r0, \r1 +.endif +.endm +.macro st_reg strd, wd, r0, r1, r2, r3, r4, r5, r6, r7 + st1 {\r0\wd}, [x0], \strd + st1 {\r1\wd}, [x8], \strd +.ifnb \r2 + st1 {\r2\wd}, [x0], \strd + st1 {\r3\wd}, [x8], \strd +.endif +.ifnb \r4 + st1 {\r4\wd}, [x0], \strd + st1 {\r5\wd}, [x8], \strd + st1 {\r6\wd}, [x0], \strd + st1 {\r7\wd}, [x8], \strd +.endif +.endm +.macro st_8b strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .8b, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro st_16b strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .16b, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro shift_store_8 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_b 6, \r0, \r1, \r2, \r3 + st_8b \strd, \r0, \r1, \r2, \r3 +.else + srshr_h 2, \r0, \r1, \r2, \r3 + st_16b \strd, \r0, \r1, \r2, \r3 +.endif +.endm +.macro shift_store_16 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun \r0\().8b, \r0\().8h, #6 + sqrshrun2 \r0\().16b, \r1\().8h, #6 + sqrshrun \r2\().8b, \r2\().8h, #6 + sqrshrun2 \r2\().16b, \r3\().8h, #6 + st_16b \strd, \r0, \r2 +.else + srshr_h 2, \r0, \r1, \r2, \r3 + st1 {\r0\().8h, \r1\().8h}, [x0], \strd + st1 {\r2\().8h, \r3\().8h}, [x8], \strd +.endif +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_8bpc_neon, export=1 + mov x8, \type_h + mov x9, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, xmx, my, xmy, ds2, sr2, shift_hv +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon + mov w10, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, w10 + mul \my, \my, w10 + add \mx, \mx, w8 // mx, 8tap_h, 4tap_h + add \my, \my, w9 // my, 8tap_v, 4tap_v +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz w8, \w + tst \mx, #(0x7f << 14) + sub w8, w8, #24 + movrel x10, X(mc_subpel_filters), -8 + b.ne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + b.ne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx w9, \mx, #7, #7 + and \mx, \mx, #0x7f + b.le 4f + mov \mx, w9 +4: + tst \my, #(0x7f << 14) + add \xmx, x10, \mx, uxtw #3 + b.ne L(\type\()_8tap_hv) + + adr x9, L(\type\()_8tap_h_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +2: + ld1 {v4.8b}, [\src], \s_strd + ld1 {v6.8b}, [\sr2], \s_strd + uxtl v4.8h, v4.8b + uxtl v6.8h, v6.8b + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + subs \h, \h, #2 + trn1 v3.2s, v4.2s, v6.2s + trn2 v6.2s, v4.2s, v6.2s + trn1 v4.2s, v5.2s, v7.2s + trn2 v7.2s, v5.2s, v7.2s + mul v3.4h, v3.4h, v0.h[0] + mla v3.4h, v4.4h, v0.h[1] + mla v3.4h, v6.4h, v0.h[2] + mla v3.4h, v7.4h, v0.h[3] + srshr v3.4h, v3.4h, #2 + sqrshrun v3.8b, v3.8h, #4 + st1 {v3.h}[0], [\dst], \d_strd + st1 {v3.h}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +4: + ld1 {v16.8b}, [\src], \s_strd + ld1 {v20.8b}, [\sr2], \s_strd + uxtl v16.8h, v16.8b + uxtl v20.8h, v20.8b + ext v17.16b, v16.16b, v16.16b, #2 + ext v18.16b, v16.16b, v16.16b, #4 + ext v19.16b, v16.16b, v16.16b, #6 + ext v21.16b, v20.16b, v20.16b, #2 + ext v22.16b, v20.16b, v20.16b, #4 + ext v23.16b, v20.16b, v20.16b, #6 + subs \h, \h, #2 + mul v16.4h, v16.4h, v0.h[0] + mla v16.4h, v17.4h, v0.h[1] + mla v16.4h, v18.4h, v0.h[2] + mla v16.4h, v19.4h, v0.h[3] + mul v20.4h, v20.4h, v0.h[0] + mla v20.4h, v21.4h, v0.h[1] + mla v20.4h, v22.4h, v0.h[2] + mla v20.4h, v23.4h, v0.h[3] + srshr v16.4h, v16.4h, #2 + srshr v20.4h, v20.4h, #2 +.ifc \type, put + sqrshrun v16.8b, v16.8h, #4 + sqrshrun v20.8b, v20.8h, #4 + st1 {v16.s}[0], [\dst], \d_strd + st1 {v20.s}[0], [\ds2], \d_strd +.else + st1 {v16.4h}, [\dst], \d_strd + st1 {v20.4h}, [\ds2], \d_strd +.endif + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +8: + ld1 {v16.8b, v17.8b}, [\src], \s_strd + ld1 {v20.8b, v21.8b}, [\sr2], \s_strd + uxtl v16.8h, v16.8b + uxtl v17.8h, v17.8b + uxtl v20.8h, v20.8b + uxtl v21.8h, v21.8b + + mul v18.8h, v16.8h, v0.h[0] + mul v22.8h, v20.8h, v0.h[0] +.irpc i, 1234567 + ext v19.16b, v16.16b, v17.16b, #(2*\i) + ext v23.16b, v20.16b, v21.16b, #(2*\i) + mla v18.8h, v19.8h, v0.h[\i] + mla v22.8h, v23.8h, v0.h[\i] +.endr + subs \h, \h, #2 + srshr v18.8h, v18.8h, #2 + srshr v22.8h, v22.8h, #2 +.ifc \type, put + sqrshrun v18.8b, v18.8h, #4 + sqrshrun v22.8b, v22.8h, #4 + st1 {v18.8b}, [\dst], \d_strd + st1 {v22.8b}, [\ds2], \d_strd +.else + st1 {v18.8h}, [\dst], \d_strd + st1 {v22.8h}, [\ds2], \d_strd +.endif + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + sub \s_strd, \s_strd, \w, uxtw + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw +.endif +161: + ld1 {v16.8b, v17.8b, v18.8b}, [\src], #24 + ld1 {v20.8b, v21.8b, v22.8b}, [\sr2], #24 + mov \mx, \w + uxtl v16.8h, v16.8b + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v20.8h, v20.8b + uxtl v21.8h, v21.8b + uxtl v22.8h, v22.8b + +16: + mul v24.8h, v16.8h, v0.h[0] + mul v25.8h, v17.8h, v0.h[0] + mul v26.8h, v20.8h, v0.h[0] + mul v27.8h, v21.8h, v0.h[0] +.irpc i, 1234567 + ext v28.16b, v16.16b, v17.16b, #(2*\i) + ext v29.16b, v17.16b, v18.16b, #(2*\i) + ext v30.16b, v20.16b, v21.16b, #(2*\i) + ext v31.16b, v21.16b, v22.16b, #(2*\i) + mla v24.8h, v28.8h, v0.h[\i] + mla v25.8h, v29.8h, v0.h[\i] + mla v26.8h, v30.8h, v0.h[\i] + mla v27.8h, v31.8h, v0.h[\i] +.endr + srshr v24.8h, v24.8h, #2 + srshr v25.8h, v25.8h, #2 + srshr v26.8h, v26.8h, #2 + srshr v27.8h, v27.8h, #2 + subs \mx, \mx, #16 +.ifc \type, put + sqrshrun v24.8b, v24.8h, #4 + sqrshrun2 v24.16b, v25.8h, #4 + sqrshrun v26.8b, v26.8h, #4 + sqrshrun2 v26.16b, v27.8h, #4 + st1 {v24.16b}, [\dst], #16 + st1 {v26.16b}, [\ds2], #16 +.else + st1 {v24.8h, v25.8h}, [\dst], #32 + st1 {v26.8h, v27.8h}, [\ds2], #32 +.endif + b.le 9f + + mov v16.16b, v18.16b + mov v20.16b, v22.16b + ld1 {v17.8b, v18.8b}, [\src], #16 + ld1 {v21.8b, v22.8b}, [\sr2], #16 + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v21.8h, v21.8b + uxtl v22.8h, v22.8b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_8tap_h_tbl): + .hword L(\type\()_8tap_h_tbl) - 1280b + .hword L(\type\()_8tap_h_tbl) - 640b + .hword L(\type\()_8tap_h_tbl) - 320b + .hword L(\type\()_8tap_h_tbl) - 160b + .hword L(\type\()_8tap_h_tbl) - 80b + .hword L(\type\()_8tap_h_tbl) - 40b + .hword L(\type\()_8tap_h_tbl) - 20b + .hword 0 + + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx w9, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w9 +4: + add \xmy, x10, \my, uxtw #3 + + adr x9, L(\type\()_8tap_v_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + b.gt 28f + + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + // 2x2 v + load_h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_h v1, v2, v3, v4, v5 + b.gt 24f + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .4h + sqrshrun_b 6, v6 + st_h \d_strd, v6, 2 + ret + +24: // 2x4 v + load_h \sr2, \src, \s_strd, v6, v7 + interleave_1_h v5, v6, v7 + interleave_2_s v1, v2, v3, v4, v5, v6 + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .8h + sqrshrun_b 6, v6 + st_h \d_strd, v6, 4 + ret + +28: // 2x6, 2x8, 2x12, 2x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + load_h \src, \sr2, \s_strd, v1, v2, v3, v4, v5, v6, v7 + interleave_1_h v1, v2, v3, v4, v5 + interleave_1_h v5, v6, v7 + interleave_2_s v1, v2, v3, v4, v5, v6 + uxtl_b v1, v2, v3, v4 +216: + subs \h, \h, #4 + load_h \sr2, \src, \s_strd, v16, v17, v18, v19 + interleave_1_h v7, v16, v17, v18, v19 + interleave_2_s v5, v6, v7, v16, v17, v18 + uxtl_b v5, v6, v7, v16 + mul_mla_8_0 v30, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_b 6, v30 + st_h \d_strd, v30, 4 + b.le 0f + cmp \h, #2 + mov v1.16b, v5.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + mov v4.16b, v16.16b + mov v5.16b, v17.16b + mov v6.16b, v18.16b + mov v7.16b, v19.16b + b.eq 26f + b 216b +26: + load_h \sr2, \src, \s_strd, v16, v17 + interleave_1_h v7, v16, v17 + uxtl_b v5, v6, v7, v16 + mul_mla_8_0_4h v30, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_b 6, v30 + st_h \d_strd, v30, 2 +0: + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + b.gt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_s v1, v2, v3, v4, v5 + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .8h + shift_store_4 \type, \d_strd, v6 + b.le 0f + load_s \sr2, \src, \s_strd, v6, v7 + interleave_1_s v5, v6, v7 + uxtl_b v5, v6 + mul_mla_4 v7, v3, v4, v5, v6, .8h + shift_store_4 \type, \d_strd, v7 +0: + ret + +480: // 4x6, 4x8, 4x12, 4x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + interleave_1_s v16, v17, v18 + interleave_1_s v18, v19, v20, v21, v22 + uxtl_b v16, v17 + uxtl_b v18, v19, v20, v21 + +48: + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v23, v24, v25, v26 + interleave_1_s v22, v23, v24, v25, v26 + uxtl_b v22, v23, v24, v25 + mul_mla_8_2 v1, v2, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 + shift_store_4 \type, \d_strd, v1, v2 + b.le 0f + load_s \sr2, \src, \s_strd, v27, v16 + subs \h, \h, #2 + interleave_1_s v26, v27, v16 + uxtl_b v26, v27 + mul_mla_8_0 v1, v20, v21, v22, v23, v24, v25, v26, v27 + shift_store_4 \type, \d_strd, v1 + b.le 0f + load_s \sr2, \src, \s_strd, v17, v18 + subs \h, \h, #2 + interleave_1_s v16, v17, v18 + uxtl_b v16, v17 + mul_mla_8_0 v2, v22, v23, v24, v25, v26, v27, v16, v17 + shift_store_4 \type, \d_strd, v2 + b.le 0f + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v19, v20, v21, v22 + interleave_1_s v18, v19, v20, v21, v22 + uxtl_b v18, v19, v20, v21 + mul_mla_8_2 v1, v2, v24, v25, v26, v27, v16, v17, v18, v19, v20, v21 + shift_store_4 \type, \d_strd, v1, v2 + b.gt 48b +0: + ret + +80: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_8b \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + uxtl_b v1, v2, v3, v4, v5 + mul_mla_4 v6, v1, v2, v3, v4, .8h + mul_mla_4 v7, v2, v3, v4, v5, .8h + shift_store_8 \type, \d_strd, v6, v7 + b.le 0f + load_8b \sr2, \src, \s_strd, v6, v7 + uxtl_b v6, v7 + mul_mla_4 v1, v3, v4, v5, v6, .8h + mul_mla_4 v2, v4, v5, v6, v7, .8h + shift_store_8 \type, \d_strd, v1, v2 +0: + ret + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmy] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_8b \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + uxtl_b v16, v17, v18, v19, v20, v21, v22 + +88: + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v23, v24 + uxtl_b v23, v24 + mul_mla_8_1 v1, v2, v16, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_8 \type, \d_strd, v1, v2 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v25, v26 + uxtl_b v25, v26 + mul_mla_8_1 v3, v4, v18, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_8 \type, \d_strd, v3, v4 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v27, v16 + uxtl_b v27, v16 + mul_mla_8_1 v1, v2, v20, v21, v22, v23, v24, v25, v26, v27, v16 + shift_store_8 \type, \d_strd, v1, v2 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v17, v18 + uxtl_b v17, v18 + mul_mla_8_1 v3, v4, v22, v23, v24, v25, v26, v27, v16, v17, v18 + shift_store_8 \type, \d_strd, v3, v4 + b.le 9f + subs \h, \h, #4 + load_8b \sr2, \src, \s_strd, v19, v20, v21, v22 + uxtl_b v19, v20, v21, v22 + mul_mla_8_1 v1, v2, v24, v25, v26, v27, v16, v17, v18, v19, v20 + mul_mla_8_1 v3, v4, v26, v27, v16, v17, v18, v19, v20, v21, v22 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.gt 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + ret + +160: + AARCH64_VALID_JUMP_TARGET + b.gt 1680b + + // 16x2, 16x4 v + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + cmp \h, #2 + load_16b \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + uxtl v16.8h, v1.8b + uxtl v17.8h, v2.8b + uxtl v18.8h, v3.8b + uxtl v19.8h, v4.8b + uxtl v20.8h, v5.8b + uxtl2 v23.8h, v1.16b + uxtl2 v24.8h, v2.16b + uxtl2 v25.8h, v3.16b + uxtl2 v26.8h, v4.16b + uxtl2 v27.8h, v5.16b + mul_mla_4 v1, v16, v17, v18, v19, .8h + mul_mla_4 v16, v17, v18, v19, v20, .8h + mul_mla_4 v2, v23, v24, v25, v26, .8h + mul_mla_4 v17, v24, v25, v26, v27, .8h + shift_store_16 \type, \d_strd, v1, v2, v16, v17 + b.le 0f + load_16b \sr2, \src, \s_strd, v6, v7 + uxtl v21.8h, v6.8b + uxtl v22.8h, v7.8b + uxtl2 v28.8h, v6.16b + uxtl2 v29.8h, v7.16b + mul_mla_4 v1, v18, v19, v20, v21, .8h + mul_mla_4 v3, v19, v20, v21, v22, .8h + mul_mla_4 v2, v25, v26, v27, v28, .8h + mul_mla_4 v4, v26, v27, v28, v29, .8h + shift_store_16 \type, \d_strd, v1, v2, v3, v4 +0: + ret + +L(\type\()_8tap_v_tbl): + .hword L(\type\()_8tap_v_tbl) - 1280b + .hword L(\type\()_8tap_v_tbl) - 640b + .hword L(\type\()_8tap_v_tbl) - 320b + .hword L(\type\()_8tap_v_tbl) - 160b + .hword L(\type\()_8tap_v_tbl) - 80b + .hword L(\type\()_8tap_v_tbl) - 40b + .hword L(\type\()_8tap_v_tbl) - 20b + .hword 0 + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx w9, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w9 +4: + add \xmy, x10, \my, uxtw #3 + + adr x9, L(\type\()_8tap_hv_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 280f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + + // 2x2, 2x4 hv + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v28.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + ext v29.16b, v28.16b, v28.16b, #2 + mul v28.4h, v28.4h, v0.4h + mul v29.4h, v29.4h, v0.4h + addp v28.4h, v28.4h, v29.4h + addp v16.4h, v28.4h, v28.4h + srshr v16.4h, v16.4h, #2 + bl L(\type\()_8tap_filter_2) + + trn1 v16.2s, v16.2s, v28.2s + mov v17.8b, v28.8b + +2: + bl L(\type\()_8tap_filter_2) + + ext v18.8b, v17.8b, v28.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v28.4h, v1.h[3] + + sqrshrn v2.4h, v2.4s, #\shift_hv + sqxtun v2.8b, v2.8h + subs \h, \h, #2 + st1 {v2.h}[0], [\dst], \d_strd + st1 {v2.h}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v28.8b + b 2b + +280: // 2x8, 2x16, 2x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v28.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + ext v29.16b, v28.16b, v28.16b, #2 + mul v28.4h, v28.4h, v0.4h + mul v29.4h, v29.4h, v0.4h + addp v28.4h, v28.4h, v29.4h + addp v16.4h, v28.4h, v28.4h + srshr v16.4h, v16.4h, #2 + + bl L(\type\()_8tap_filter_2) + trn1 v16.2s, v16.2s, v28.2s + mov v17.8b, v28.8b + bl L(\type\()_8tap_filter_2) + ext v18.8b, v17.8b, v28.8b, #4 + mov v19.8b, v28.8b + bl L(\type\()_8tap_filter_2) + ext v20.8b, v19.8b, v28.8b, #4 + mov v21.8b, v28.8b + +28: + bl L(\type\()_8tap_filter_2) + ext v22.8b, v21.8b, v28.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal v2.4s, v28.4h, v1.h[7] + + sqrshrn v2.4h, v2.4s, #\shift_hv + sqxtun v2.8b, v2.8h + subs \h, \h, #2 + st1 {v2.h}[0], [\dst], \d_strd + st1 {v2.h}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v28.8b + b 28b + +0: + ret x15 + +L(\type\()_8tap_filter_2): + ld1 {v28.8b}, [\sr2], \s_strd + ld1 {v30.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v30.8h, v30.8b + ext v29.16b, v28.16b, v28.16b, #2 + ext v31.16b, v30.16b, v30.16b, #2 + trn1 v27.2s, v28.2s, v30.2s + trn2 v30.2s, v28.2s, v30.2s + trn1 v28.2s, v29.2s, v31.2s + trn2 v31.2s, v29.2s, v31.2s + mul v27.4h, v27.4h, v0.h[0] + mla v27.4h, v28.4h, v0.h[1] + mla v27.4h, v30.4h, v0.h[2] + mla v27.4h, v31.4h, v0.h[3] + srshr v28.4h, v27.4h, #2 + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 480f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + // 4x2, 4x4 hv + ld1 {v26.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + srshr v16.4h, v31.4h, #2 + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v28.8b + mov v18.8b, v29.8b + +4: + bl L(\type\()_8tap_filter_4) + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v28.4h, v1.h[3] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v28.4h, v1.h[2] + smlal v3.4s, v29.4h, v1.h[3] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn v3.4h, v3.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [\dst], \d_strd + st1 {v3.s}[0], [\ds2], \d_strd +.else + st1 {v2.4h}, [\dst], \d_strd + st1 {v3.4h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v28.8b + mov v18.8b, v29.8b + b 4b + +480: // 4x8, 4x16, 4x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v26.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + srshr v16.4h, v31.4h, #2 + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v28.8b + mov v18.8b, v29.8b + bl L(\type\()_8tap_filter_4) + mov v19.8b, v28.8b + mov v20.8b, v29.8b + bl L(\type\()_8tap_filter_4) + mov v21.8b, v28.8b + mov v22.8b, v29.8b + +48: + bl L(\type\()_8tap_filter_4) + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal v2.4s, v28.4h, v1.h[7] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v19.4h, v1.h[2] + smlal v3.4s, v20.4h, v1.h[3] + smlal v3.4s, v21.4h, v1.h[4] + smlal v3.4s, v22.4h, v1.h[5] + smlal v3.4s, v28.4h, v1.h[6] + smlal v3.4s, v29.4h, v1.h[7] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn v3.4h, v3.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [\dst], \d_strd + st1 {v3.s}[0], [\ds2], \d_strd +.else + st1 {v2.4h}, [\dst], \d_strd + st1 {v3.4h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v28.8b + mov v22.8b, v29.8b + b 48b +0: + ret x15 + +L(\type\()_8tap_filter_4): + ld1 {v26.8b}, [\sr2], \s_strd + ld1 {v27.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + uxtl v27.8h, v27.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + ext v28.16b, v27.16b, v27.16b, #2 + ext v29.16b, v27.16b, v27.16b, #4 + ext v30.16b, v27.16b, v27.16b, #6 + mul v27.4h, v27.4h, v0.h[0] + mla v27.4h, v28.4h, v0.h[1] + mla v27.4h, v29.4h, v0.h[2] + mla v27.4h, v30.4h, v0.h[3] + srshr v28.4h, v31.4h, #2 + srshr v29.4h, v27.4h, #2 + ret + +80: +160: +320: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + add \xmy, \xmy, #2 + ld1 {v0.8b}, [\xmx] + ld1 {v1.s}[0], [\xmy] + sub \src, \src, #3 + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + bl L(\type\()_8tap_filter_8_first) + bl L(\type\()_8tap_filter_8) + mov v17.16b, v24.16b + mov v18.16b, v25.16b + +8: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v24.4h, v1.h[2] + smlal2 v5.4s, v24.8h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + smlal2 v3.4s, v24.8h, v1.h[3] + smlal v4.4s, v25.4h, v1.h[3] + smlal2 v5.4s, v25.8h, v1.h[3] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn2 v2.8h, v3.4s, #\shift_hv + sqrshrn v4.4h, v4.4s, #\shift_hv + sqrshrn2 v4.8h, v5.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v4.8b, v4.8h + st1 {v2.8b}, [\dst], \d_strd + st1 {v4.8b}, [\ds2], \d_strd +.else + st1 {v2.8h}, [\dst], \d_strd + st1 {v4.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v24.16b + mov v18.16b, v25.16b + b 8b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 164b + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + ld1 {v1.8b}, [\xmy] + sub \src, \src, #3 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + bl L(\type\()_8tap_filter_8_first) + bl L(\type\()_8tap_filter_8) + mov v17.16b, v24.16b + mov v18.16b, v25.16b + bl L(\type\()_8tap_filter_8) + mov v19.16b, v24.16b + mov v20.16b, v25.16b + bl L(\type\()_8tap_filter_8) + mov v21.16b, v24.16b + mov v22.16b, v25.16b + +88: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v19.4h, v1.h[2] + smlal2 v5.4s, v19.8h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal2 v3.4s, v19.8h, v1.h[3] + smlal v4.4s, v20.4h, v1.h[3] + smlal2 v5.4s, v20.8h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal2 v3.4s, v20.8h, v1.h[4] + smlal v4.4s, v21.4h, v1.h[4] + smlal2 v5.4s, v21.8h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal2 v3.4s, v21.8h, v1.h[5] + smlal v4.4s, v22.4h, v1.h[5] + smlal2 v5.4s, v22.8h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal2 v3.4s, v22.8h, v1.h[6] + smlal v4.4s, v24.4h, v1.h[6] + smlal2 v5.4s, v24.8h, v1.h[6] + smlal v2.4s, v24.4h, v1.h[7] + smlal2 v3.4s, v24.8h, v1.h[7] + smlal v4.4s, v25.4h, v1.h[7] + smlal2 v5.4s, v25.8h, v1.h[7] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn2 v2.8h, v3.4s, #\shift_hv + sqrshrn v4.4h, v4.4s, #\shift_hv + sqrshrn2 v4.8h, v5.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v4.8b, v4.8h + st1 {v2.8b}, [\dst], \d_strd + st1 {v4.8b}, [\ds2], \d_strd +.else + st1 {v2.8h}, [\dst], \d_strd + st1 {v4.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v24.16b + mov v22.16b, v25.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + ret x15 + +L(\type\()_8tap_filter_8_first): + ld1 {v28.8b, v29.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v29.8h, v29.8b + mul v16.8h, v28.8h, v0.h[0] + ext v24.16b, v28.16b, v29.16b, #(2*1) + ext v25.16b, v28.16b, v29.16b, #(2*2) + ext v26.16b, v28.16b, v29.16b, #(2*3) + ext v27.16b, v28.16b, v29.16b, #(2*4) + mla v16.8h, v24.8h, v0.h[1] + mla v16.8h, v25.8h, v0.h[2] + mla v16.8h, v26.8h, v0.h[3] + mla v16.8h, v27.8h, v0.h[4] + ext v24.16b, v28.16b, v29.16b, #(2*5) + ext v25.16b, v28.16b, v29.16b, #(2*6) + ext v26.16b, v28.16b, v29.16b, #(2*7) + mla v16.8h, v24.8h, v0.h[5] + mla v16.8h, v25.8h, v0.h[6] + mla v16.8h, v26.8h, v0.h[7] + srshr v16.8h, v16.8h, #2 + ret + +L(\type\()_8tap_filter_8): + ld1 {v28.8b, v29.8b}, [\sr2], \s_strd + ld1 {v30.8b, v31.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v29.8h, v29.8b + uxtl v30.8h, v30.8b + uxtl v31.8h, v31.8b + mul v24.8h, v28.8h, v0.h[0] + mul v25.8h, v30.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v28.16b, v29.16b, #(2*\i) + ext v27.16b, v30.16b, v31.16b, #(2*\i) + mla v24.8h, v26.8h, v0.h[\i] + mla v25.8h, v27.8h, v0.h[\i] +.endr + srshr v24.8h, v24.8h, #2 + srshr v25.8h, v25.8h, #2 + ret + +L(\type\()_8tap_hv_tbl): + .hword L(\type\()_8tap_hv_tbl) - 1280b + .hword L(\type\()_8tap_hv_tbl) - 640b + .hword L(\type\()_8tap_hv_tbl) - 320b + .hword L(\type\()_8tap_hv_tbl) - 160b + .hword L(\type\()_8tap_hv_tbl) - 80b + .hword L(\type\()_8tap_hv_tbl) - 40b + .hword L(\type\()_8tap_hv_tbl) - 20b + .hword 0 +endfunc + + +function \type\()_bilin_8bpc_neon, export=1 + dup v1.16b, \mx + dup v3.16b, \my + mov w9, #16 + sub w8, w9, \mx + sub w9, w9, \my + dup v0.16b, w8 + dup v2.16b, w9 +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz w8, \w + sub w8, w8, #24 + cbnz \mx, L(\type\()_bilin_h) + cbnz \my, L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cbnz \my, L(\type\()_bilin_hv) + + adr x9, L(\type\()_bilin_h_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + ld1 {v4.s}[0], [\src], \s_strd + ld1 {v6.s}[0], [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #1 + ext v7.8b, v6.8b, v6.8b, #1 + trn1 v4.4h, v4.4h, v6.4h + trn1 v5.4h, v5.4h, v7.4h + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + ld1 {v4.8b}, [\src], \s_strd + ld1 {v6.8b}, [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #1 + ext v7.8b, v6.8b, v6.8b, #1 + trn1 v4.2s, v4.2s, v6.2s + trn1 v5.2s, v5.2s, v7.2s + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + ld1 {v4.16b}, [\src], \s_strd + ld1 {v6.16b}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #1 + ext v7.16b, v6.16b, v6.16b, #1 + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umull v6.8h, v6.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b + umlal v6.8h, v7.8b, v1.8b +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn v6.8b, v6.8h, #4 + st1 {v4.8b}, [\dst], \d_strd + st1 {v6.8b}, [\ds2], \d_strd +.else + st1 {v4.8h}, [\dst], \d_strd + st1 {v6.8h}, [\ds2], \d_strd +.endif + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w, uxtw + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw +.endif +161: + ld1 {v16.d}[1], [\src], #8 + ld1 {v20.d}[1], [\sr2], #8 + mov \mx, \w + +16: + ld1 {v18.16b}, [\src], #16 + ld1 {v22.16b}, [\sr2], #16 + ext v17.16b, v16.16b, v18.16b, #8 + ext v19.16b, v16.16b, v18.16b, #9 + ext v21.16b, v20.16b, v22.16b, #8 + ext v23.16b, v20.16b, v22.16b, #9 + umull v16.8h, v17.8b, v0.8b + umull2 v17.8h, v17.16b, v0.16b + umull v20.8h, v21.8b, v0.8b + umull2 v21.8h, v21.16b, v0.16b + umlal v16.8h, v19.8b, v1.8b + umlal2 v17.8h, v19.16b, v1.16b + umlal v20.8h, v23.8b, v1.8b + umlal2 v21.8h, v23.16b, v1.16b + subs \mx, \mx, #16 +.ifc \type, put + uqrshrn v16.8b, v16.8h, #4 + uqrshrn2 v16.16b, v17.8h, #4 + uqrshrn v20.8b, v20.8h, #4 + uqrshrn2 v20.16b, v21.8h, #4 + st1 {v16.16b}, [\dst], #16 + st1 {v20.16b}, [\ds2], #16 +.else + st1 {v16.8h, v17.8h}, [\dst], #32 + st1 {v20.8h, v21.8h}, [\ds2], #32 +.endif + b.le 9f + + mov v16.16b, v18.16b + mov v20.16b, v22.16b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_bilin_h_tbl): + .hword L(\type\()_bilin_h_tbl) - 1280b + .hword L(\type\()_bilin_h_tbl) - 640b + .hword L(\type\()_bilin_h_tbl) - 320b + .hword L(\type\()_bilin_h_tbl) - 160b + .hword L(\type\()_bilin_h_tbl) - 80b + .hword L(\type\()_bilin_h_tbl) - 40b + .hword L(\type\()_bilin_h_tbl) - 20b + .hword 0 + + +L(\type\()_bilin_v): + cmp \h, #4 + adr x9, L(\type\()_bilin_v_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + ld1 {v16.h}[0], [\src], \s_strd + b.gt 24f +22: + ld1 {v17.h}[0], [\sr2], \s_strd + ld1 {v18.h}[0], [\src], \s_strd + trn1 v16.4h, v16.4h, v17.4h + trn1 v17.4h, v17.4h, v18.4h + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst] + st1 {v4.h}[1], [\ds2] + ret +24: // 2x4, 2x6, 2x8, ... v + ld1 {v17.h}[0], [\sr2], \s_strd + ld1 {v18.h}[0], [\src], \s_strd + ld1 {v19.h}[0], [\sr2], \s_strd + ld1 {v20.h}[0], [\src], \s_strd + sub \h, \h, #4 + trn1 v16.4h, v16.4h, v17.4h + trn1 v17.4h, v17.4h, v18.4h + trn1 v18.4h, v18.4h, v19.4h + trn1 v19.4h, v19.4h, v20.4h + trn1 v16.2s, v16.2s, v18.2s + trn1 v17.2s, v17.2s, v19.2s + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + cmp \h, #2 + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + st1 {v4.h}[2], [\dst], \d_strd + st1 {v4.h}[3], [\ds2], \d_strd + b.lt 0f + mov v16.8b, v20.8b + b.eq 22b + b 24b +0: + ret +.endif + +40: // 4xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.s}[0], [\src], \s_strd +4: + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + b 4b +0: + ret + +80: // 8xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.8b}, [\src], \s_strd +8: + ld1 {v17.8b}, [\sr2], \s_strd + ld1 {v18.8b}, [\src], \s_strd + umull v4.8h, v16.8b, v2.8b + umull v5.8h, v17.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + umlal v5.8h, v18.8b, v3.8b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn v5.8b, v5.8h, #4 + st1 {v4.8b}, [\dst], \d_strd + st1 {v5.8b}, [\ds2], \d_strd +.else + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + b 8b +0: + ret + +160: // 16xN, 32xN, ... +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v16.16b}, [\src], \s_strd +2: + ld1 {v17.16b}, [\sr2], \s_strd + ld1 {v18.16b}, [\src], \s_strd + umull v4.8h, v16.8b, v2.8b + umull2 v5.8h, v16.16b, v2.16b + umull v6.8h, v17.8b, v2.8b + umull2 v7.8h, v17.16b, v2.16b + umlal v4.8h, v17.8b, v3.8b + umlal2 v5.8h, v17.16b, v3.16b + umlal v6.8h, v18.8b, v3.8b + umlal2 v7.8h, v18.16b, v3.16b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn2 v4.16b, v5.8h, #4 + uqrshrn v6.8b, v6.8h, #4 + uqrshrn2 v6.16b, v7.8h, #4 + st1 {v4.16b}, [\dst], \d_strd + st1 {v6.16b}, [\ds2], \d_strd +.else + st1 {v4.8h, v5.8h}, [\dst], \d_strd + st1 {v6.8h, v7.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #16 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 +.ifc \type, put + add \dst, \dst, #16 +.else + add \dst, \dst, #32 +.endif + b 1b +0: + ret + +L(\type\()_bilin_v_tbl): + .hword L(\type\()_bilin_v_tbl) - 1280b + .hword L(\type\()_bilin_v_tbl) - 640b + .hword L(\type\()_bilin_v_tbl) - 320b + .hword L(\type\()_bilin_v_tbl) - 160b + .hword L(\type\()_bilin_v_tbl) - 80b + .hword L(\type\()_bilin_v_tbl) - 40b + .hword L(\type\()_bilin_v_tbl) - 20b + .hword 0 + +L(\type\()_bilin_hv): + uxtl v2.8h, v2.8b + uxtl v3.8h, v3.8b + adr x9, L(\type\()_bilin_hv_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN hv + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.s}[0], [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +2: + ld1 {v28.s}[0], [\sr2], \s_strd + ld1 {v30.s}[0], [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + ext v31.8b, v30.8b, v30.8b, #1 + trn1 v28.4h, v28.4h, v30.4h + trn1 v29.4h, v29.4h, v31.4h + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + + trn1 v16.2s, v16.2s, v17.2s + + mul v4.4h, v16.4h, v2.4h + mla v4.4h, v17.4h, v3.4h + uqrshrn v4.8b, v4.8h, #8 + subs \h, \h, #2 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2s, v17.2s, v17.2s + b 2b +0: + ret +.endif + +40: // 4xN hv + AARCH64_VALID_JUMP_TARGET + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.8b}, [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +4: + ld1 {v28.8b}, [\sr2], \s_strd + ld1 {v30.8b}, [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + ext v31.8b, v30.8b, v30.8b, #1 + trn1 v28.2s, v28.2s, v30.2s + trn1 v29.2s, v29.2s, v31.2s + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + + trn1 v16.2d, v16.2d, v17.2d + + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #8 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + urshr v4.8h, v4.8h, #4 + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.le 0f + trn2 v16.2d, v17.2d, v17.2d + b 4b +0: + ret + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.16b}, [\src], \s_strd + ext v29.16b, v28.16b, v28.16b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +2: + ld1 {v28.16b}, [\sr2], \s_strd + ld1 {v30.16b}, [\src], \s_strd + ext v29.16b, v28.16b, v28.16b, #1 + ext v31.16b, v30.16b, v30.16b, #1 + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + umull v18.8h, v30.8b, v0.8b + umlal v18.8h, v31.8b, v1.8b + + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v18.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #8 + uqrshrn v5.8b, v5.8h, #8 + st1 {v4.8b}, [\dst], \d_strd + st1 {v5.8b}, [\ds2], \d_strd +.else + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 1b +0: + ret + +L(\type\()_bilin_hv_tbl): + .hword L(\type\()_bilin_hv_tbl) - 1280b + .hword L(\type\()_bilin_hv_tbl) - 640b + .hword L(\type\()_bilin_hv_tbl) - 320b + .hword L(\type\()_bilin_hv_tbl) - 160b + .hword L(\type\()_bilin_hv_tbl) - 80b + .hword L(\type\()_bilin_hv_tbl) - 40b + .hword L(\type\()_bilin_hv_tbl) - 20b + .hword 0 +endfunc +.endm + +filter_fn put, x0, x1, x2, x3, w4, w5, w6, x6, w7, x7, x8, x9, 10 +filter_fn prep, x0, x7, x1, x2, w3, w4, w5, x5, w6, x6, x8, x9, 6 + +.macro load_filter_row dst, src, inc + asr w13, \src, #10 + add \src, \src, \inc + ldr \dst, [x11, w13, sxtw #3] +.endm + +function warp_filter_horz_neon + add w12, w5, #512 + + ld1 {v16.8b, v17.8b}, [x2], x3 + + load_filter_row d0, w12, w7 + load_filter_row d1, w12, w7 + load_filter_row d2, w12, w7 + load_filter_row d3, w12, w7 + load_filter_row d4, w12, w7 + load_filter_row d5, w12, w7 + load_filter_row d6, w12, w7 + // subtract by 128 to allow using smull + eor v16.8b, v16.8b, v22.8b + eor v17.8b, v17.8b, v22.8b + load_filter_row d7, w12, w7 + + ext v18.8b, v16.8b, v17.8b, #1 + ext v19.8b, v16.8b, v17.8b, #2 + smull v0.8h, v0.8b, v16.8b + smull v1.8h, v1.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #3 + ext v20.8b, v16.8b, v17.8b, #4 + smull v2.8h, v2.8b, v19.8b + smull v3.8h, v3.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #5 + ext v19.8b, v16.8b, v17.8b, #6 + smull v4.8h, v4.8b, v20.8b + smull v5.8h, v5.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #7 + smull v6.8h, v6.8b, v19.8b + smull v7.8h, v7.8b, v18.8b + + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + + addp v0.8h, v0.8h, v4.8h + + add w5, w5, w8 + + ret +endfunc + +// void dav1d_warp_affine_8x8_8bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my) +.macro warp t, shift +function warp_affine_8x8\t\()_8bpc_neon, export=1 + ldr x4, [x4] + sbfx x7, x4, #0, #16 + sbfx x8, x4, #16, #16 + sbfx x9, x4, #32, #16 + sbfx x4, x4, #48, #16 + mov w10, #8 + sub x2, x2, x3, lsl #1 + sub x2, x2, x3 + sub x2, x2, #3 + movrel x11, X(mc_warp_filter), 64*8 + mov x15, x30 +.ifnb \t + lsl x1, x1, #1 +.endif + + movi v22.8b, #128 +.ifb \t + movi v23.8h, #128 +.else + movi v23.8h, #8, lsl #8 +.endif + + bl warp_filter_horz_neon + srshr v24.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v25.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v26.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v27.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v28.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v29.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v30.8h, v0.8h, #3 + +1: + add w14, w6, #512 + bl warp_filter_horz_neon + srshr v31.8h, v0.8h, #3 + + load_filter_row d0, w14, w9 + load_filter_row d1, w14, w9 + load_filter_row d2, w14, w9 + load_filter_row d3, w14, w9 + load_filter_row d4, w14, w9 + load_filter_row d5, w14, w9 + load_filter_row d6, w14, w9 + load_filter_row d7, w14, w9 + transpose_8x8b_xtl v0, v1, v2, v3, v4, v5, v6, v7, sxtl + + // This ordering of smull/smlal/smull2/smlal2 is highly + // beneficial for Cortex A53 here. + smull v16.4s, v24.4h, v0.4h + smlal v16.4s, v25.4h, v1.4h + smlal v16.4s, v26.4h, v2.4h + smlal v16.4s, v27.4h, v3.4h + smlal v16.4s, v28.4h, v4.4h + smlal v16.4s, v29.4h, v5.4h + smlal v16.4s, v30.4h, v6.4h + smlal v16.4s, v31.4h, v7.4h + smull2 v17.4s, v24.8h, v0.8h + smlal2 v17.4s, v25.8h, v1.8h + smlal2 v17.4s, v26.8h, v2.8h + smlal2 v17.4s, v27.8h, v3.8h + smlal2 v17.4s, v28.8h, v4.8h + smlal2 v17.4s, v29.8h, v5.8h + smlal2 v17.4s, v30.8h, v6.8h + smlal2 v17.4s, v31.8h, v7.8h + + mov v24.16b, v25.16b + mov v25.16b, v26.16b + sqrshrn v16.4h, v16.4s, #\shift + mov v26.16b, v27.16b + sqrshrn2 v16.8h, v17.4s, #\shift + mov v27.16b, v28.16b + mov v28.16b, v29.16b + add v16.8h, v16.8h, v23.8h +.ifb \t + sqxtun v16.8b, v16.8h +.endif + mov v29.16b, v30.16b + mov v30.16b, v31.16b + subs w10, w10, #1 +.ifnb \t + st1 {v16.8h}, [x0], x1 +.else + st1 {v16.8b}, [x0], x1 +.endif + + add w6, w6, w4 + b.gt 1b + + ret x15 +endfunc +.endm + +warp , 11 +warp t, 7 + +// void dav1d_emu_edge_8bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_8bpc_neon, export=1 + ldp x8, x9, [sp] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub x12, x3, #1 // ih - 1 + cmp x5, x3 + sub x13, x2, #1 // iw - 1 + csel x12, x12, x5, ge // min(y, ih - 1) + cmp x4, x2 + bic x12, x12, x12, asr #63 // max(min(y, ih - 1), 0) + csel x13, x13, x4, ge // min(x, iw - 1) + bic x13, x13, x13, asr #63 // max(min(x, iw - 1), 0) + madd x8, x12, x9, x8 // ref += iclip() * stride + add x8, x8, x13 // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add x10, x5, x1 // y + bh + neg x5, x5 // -y + sub x10, x10, x3 // y + bh - ih + sub x12, x1, #1 // bh - 1 + cmp x10, x1 + bic x5, x5, x5, asr #63 // max(-y, 0) + csel x10, x10, x12, lt // min(y + bh - ih, bh-1) + cmp x5, x1 + bic x10, x10, x10, asr #63 // max(min(y + bh - ih, bh-1), 0) + csel x5, x5, x12, lt // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add x11, x4, x0 // x + bw + neg x4, x4 // -x + sub x11, x11, x2 // x + bw - iw + sub x13, x0, #1 // bw - 1 + cmp x11, x0 + bic x4, x4, x4, asr #63 // max(-x, 0) + csel x11, x11, x13, lt // min(x + bw - iw, bw-1) + cmp x4, x0 + bic x11, x11, x11, asr #63 // max(min(x + bw - iw, bw-1), 0) + csel x4, x4, x13, lt // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub x1, x1, x5 // bh - top_ext + madd x6, x5, x7, x6 + sub x2, x0, x4 // bw - left_ext + sub x1, x1, x10 // center_h = bh - top_ext - bottom_ext + sub x2, x2, x11 // center_w = bw - left_ext - right_ext + + mov x14, x6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + ld1r {v0.16b}, [x8] + mov x12, x6 // out = dst + mov x3, x4 +1: + subs x3, x3, #16 + st1 {v0.16b}, [x12], #16 + b.gt 1b +.endif + mov x13, x8 + add x12, x6, x4 // out = dst + left_ext + mov x3, x2 +1: + ld1 {v0.16b, v1.16b}, [x13], #32 + subs x3, x3, #32 + st1 {v0.16b, v1.16b}, [x12], #32 + b.gt 1b +.if \need_right + add x3, x8, x2 // in + center_w + sub x3, x3, #1 // in + center_w - 1 + add x12, x6, x4 // dst + left_ext + ld1r {v0.16b}, [x3] + add x12, x12, x2 // out = dst + left_ext + center_w + mov x3, x11 +1: + subs x3, x3, #16 + st1 {v0.16b}, [x12], #16 + b.gt 1b +.endif + + subs x1, x1, #1 // center_h-- + add x6, x6, x7 + add x8, x8, x9 + b.gt 0b +.endm + + cbz x4, 2f + // need_left + cbz x11, 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cbz x11, 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + + cbz x10, 3f + // need_bottom + sub x8, x6, x7 // ref = dst - stride + mov x4, x0 +1: + ld1 {v0.16b, v1.16b}, [x8], #32 + mov x3, x10 +2: + subs x3, x3, #1 + st1 {v0.16b, v1.16b}, [x6], x7 + b.gt 2b + msub x6, x7, x10, x6 // dst -= bottom_ext * stride + subs x4, x4, #32 // bw -= 32 + add x6, x6, #32 // dst += 32 + b.gt 1b + +3: + cbz x5, 3f + // need_top + msub x6, x7, x5, x14 // dst = stored_dst - top_ext * stride +1: + ld1 {v0.16b, v1.16b}, [x14], #32 + mov x3, x5 +2: + subs x3, x3, #1 + st1 {v0.16b, v1.16b}, [x6], x7 + b.gt 2b + msub x6, x7, x5, x6 // dst -= top_ext * stride + subs x0, x0, #32 // bw -= 32 + add x6, x6, #32 // dst += 32 + b.gt 1b + +3: + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc16.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc16.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/mc16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3611 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/asm/arm/asm.S" +#include "util.S" + +#define PREP_BIAS 8192 + +.macro avg d0, d1, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sqadd \t0\().8h, \t0\().8h, \t2\().8h + sqadd \t1\().8h, \t1\().8h, \t3\().8h + smax \t0\().8h, \t0\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + smax \t1\().8h, \t1\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sqsub \t0\().8h, \t0\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sqsub \t1\().8h, \t1\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sshl \d0\().8h, \t0\().8h, v29.8h // -(intermediate_bits+1) + sshl \d1\().8h, \t1\().8h, v29.8h // -(intermediate_bits+1) +.endm + +.macro w_avg d0, d1, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + // This difference requires a 17 bit range, and all bits are + // significant for the following multiplication. + ssubl \d0\().4s, \t2\().4h, \t0\().4h + ssubl2 \t0\().4s, \t2\().8h, \t0\().8h + ssubl \d1\().4s, \t3\().4h, \t1\().4h + ssubl2 \t1\().4s, \t3\().8h, \t1\().8h + mul \d0\().4s, \d0\().4s, v27.4s + mul \t0\().4s, \t0\().4s, v27.4s + mul \d1\().4s, \d1\().4s, v27.4s + mul \t1\().4s, \t1\().4s, v27.4s + sshr \d0\().4s, \d0\().4s, #4 + sshr \t0\().4s, \t0\().4s, #4 + sshr \d1\().4s, \d1\().4s, #4 + sshr \t1\().4s, \t1\().4s, #4 + saddw \d0\().4s, \d0\().4s, \t2\().4h + saddw2 \t0\().4s, \t0\().4s, \t2\().8h + saddw \d1\().4s, \d1\().4s, \t3\().4h + saddw2 \t1\().4s, \t1\().4s, \t3\().8h + uzp1 \d0\().8h, \d0\().8h, \t0\().8h // Same as xtn, xtn2 + uzp1 \d1\().8h, \d1\().8h, \t1\().8h // Ditto + srshl \d0\().8h, \d0\().8h, v29.8h // -intermediate_bits + srshl \d1\().8h, \d1\().8h, v29.8h // -intermediate_bits + add \d0\().8h, \d0\().8h, v28.8h // PREP_BIAS >> intermediate_bits + add \d1\().8h, \d1\().8h, v28.8h // PREP_BIAS >> intermediate_bits + smin \d0\().8h, \d0\().8h, v31.8h // bitdepth_max + smin \d1\().8h, \d1\().8h, v31.8h // bitdepth_max + smax \d0\().8h, \d0\().8h, v30.8h // 0 + smax \d1\().8h, \d1\().8h, v30.8h // 0 +.endm + +.macro mask d0, d1, t0, t1, t2, t3 + ld1 {v27.16b}, [x6], 16 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + neg v27.16b, v27.16b + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sxtl v26.8h, v27.8b + sxtl2 v27.8h, v27.16b + sxtl v24.4s, v26.4h + sxtl2 v25.4s, v26.8h + sxtl v26.4s, v27.4h + sxtl2 v27.4s, v27.8h + ssubl \d0\().4s, \t2\().4h, \t0\().4h + ssubl2 \t0\().4s, \t2\().8h, \t0\().8h + ssubl \d1\().4s, \t3\().4h, \t1\().4h + ssubl2 \t1\().4s, \t3\().8h, \t1\().8h + mul \d0\().4s, \d0\().4s, v24.4s + mul \t0\().4s, \t0\().4s, v25.4s + mul \d1\().4s, \d1\().4s, v26.4s + mul \t1\().4s, \t1\().4s, v27.4s + sshr \d0\().4s, \d0\().4s, #6 + sshr \t0\().4s, \t0\().4s, #6 + sshr \d1\().4s, \d1\().4s, #6 + sshr \t1\().4s, \t1\().4s, #6 + saddw \d0\().4s, \d0\().4s, \t2\().4h + saddw2 \t0\().4s, \t0\().4s, \t2\().8h + saddw \d1\().4s, \d1\().4s, \t3\().4h + saddw2 \t1\().4s, \t1\().4s, \t3\().8h + uzp1 \d0\().8h, \d0\().8h, \t0\().8h // Same as xtn, xtn2 + uzp1 \d1\().8h, \d1\().8h, \t1\().8h // Ditto + srshl \d0\().8h, \d0\().8h, v29.8h // -intermediate_bits + srshl \d1\().8h, \d1\().8h, v29.8h // -intermediate_bits + add \d0\().8h, \d0\().8h, v28.8h // PREP_BIAS >> intermediate_bits + add \d1\().8h, \d1\().8h, v28.8h // PREP_BIAS >> intermediate_bits + smin \d0\().8h, \d0\().8h, v31.8h // bitdepth_max + smin \d1\().8h, \d1\().8h, v31.8h // bitdepth_max + smax \d0\().8h, \d0\().8h, v30.8h // 0 + smax \d1\().8h, \d1\().8h, v30.8h // 0 +.endm + +.macro bidir_fn type, bdmax +function \type\()_16bpc_neon, export=1 + clz w4, w4 +.ifnc \type, avg + dup v31.8h, \bdmax // bitdepth_max + movi v30.8h, #0 +.endif + clz w7, \bdmax + sub w7, w7, #18 // intermediate_bits = clz(bitdepth_max) - 18 +.ifc \type, avg + mov w9, #1 + mov w8, #-2*PREP_BIAS + lsl w9, w9, w7 // 1 << intermediate_bits + add w7, w7, #1 + sub w8, w8, w9 // -2*PREP_BIAS - 1 << intermediate_bits + neg w7, w7 // -(intermediate_bits+1) + dup v28.8h, w8 // -2*PREP_BIAS - 1 << intermediate_bits + dup v29.8h, w7 // -(intermediate_bits+1) +.else + mov w8, #PREP_BIAS + lsr w8, w8, w7 // PREP_BIAS >> intermediate_bits + neg w7, w7 // -intermediate_bits + dup v28.8h, w8 // PREP_BIAS >> intermediate_bits + dup v29.8h, w7 // -intermediate_bits +.endif +.ifc \type, w_avg + dup v27.4s, w6 + neg v27.4s, v27.4s +.endif + adr x7, L(\type\()_tbl) + sub w4, w4, #24 + \type v4, v5, v0, v1, v2, v3 + ldrh w4, [x7, x4, lsl #1] + sub x7, x7, w4, uxtw + br x7 +40: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +4: + subs w5, w5, #4 + st1 {v4.d}[0], [x0], x1 + st1 {v4.d}[1], [x7], x1 + st1 {v5.d}[0], [x0], x1 + st1 {v5.d}[1], [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 4b +80: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +8: + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 8b +16: + AARCH64_VALID_JUMP_TARGET + \type v6, v7, v0, v1, v2, v3 + st1 {v4.8h, v5.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v6.8h, v7.8h}, [x0], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 16b +32: + AARCH64_VALID_JUMP_TARGET + \type v6, v7, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 32b +640: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 +64: + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + \type v18, v19, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 64b +1280: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 + mov x8, #128 + sub x1, x1, #128 +128: + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x8 + \type v18, v19, v0, v1, v2, v3 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x8 + \type v4, v5, v0, v1, v2, v3 + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + \type v18, v19, v0, v1, v2, v3 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 128b +0: + ret +L(\type\()_tbl): + .hword L(\type\()_tbl) - 1280b + .hword L(\type\()_tbl) - 640b + .hword L(\type\()_tbl) - 32b + .hword L(\type\()_tbl) - 16b + .hword L(\type\()_tbl) - 80b + .hword L(\type\()_tbl) - 40b +endfunc +.endm + +bidir_fn avg, w6 +bidir_fn w_avg, w7 +bidir_fn mask, w7 + + +.macro w_mask_fn type +function w_mask_\type\()_16bpc_neon, export=1 + ldr w8, [sp] + clz w9, w4 + adr x10, L(w_mask_\type\()_tbl) + dup v31.8h, w8 // bitdepth_max + sub w9, w9, #24 + clz w8, w8 // clz(bitdepth_max) + ldrh w9, [x10, x9, lsl #1] + sub x10, x10, w9, uxtw + sub w8, w8, #12 // sh = intermediate_bits + 6 = clz(bitdepth_max) - 12 + mov w9, #PREP_BIAS*64 + neg w8, w8 // -sh + mov w11, #27615 // (64 + 1 - 38)<> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + uxtl v22.4s, v20.4h + uxtl2 v23.4s, v20.8h + uxtl v24.4s, v21.4h + uxtl2 v25.4s, v21.8h + mla v4.4s, v16.4s, v22.4s // (tmp2-tmp1)*(64-m) + mla v5.4s, v17.4s, v23.4s + mla v6.4s, v18.4s, v24.4s + mla v7.4s, v19.4s, v25.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v6.4s + sqxtun2 v5.8h, v7.4s + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + sub v20.16b, v1.16b, v20.16b // m + st1 {v20.16b}, [x6], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + xtn v20.8b, v20.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + st1 {v20.8b}, [x6], #8 +.elseif \type == 420 + trn1 v24.2d, v20.2d, v21.2d + trn2 v25.2d, v20.2d, v21.2d + add v24.8h, v24.8h, v25.8h // (64 - my1) + (64 - my2) (row wise addition) + addp v20.8h, v24.8h, v24.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.4h, v3.4h, v20.4h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.s}[0], [x6], #4 +.endif + st1 {v4.d}[0], [x0], x1 + st1 {v4.d}[1], [x12], x1 + st1 {v5.d}[0], [x0], x1 + st1 {v5.d}[1], [x12], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 + ld1 {v6.8h, v7.8h}, [x3], #32 // tmp2 + subs w5, w5, #2 + sabd v20.8h, v4.8h, v6.8h // abs(tmp1 - tmp2) + sabd v21.8h, v5.8h, v7.8h + ssubl v16.4s, v6.4h, v4.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v17.4s, v6.8h, v4.8h + ssubl v18.4s, v7.4h, v5.4h + ssubl2 v19.4s, v7.8h, v5.8h + uqsub v20.8h, v0.8h, v20.8h // 27615 - abs() + uqsub v21.8h, v0.8h, v21.8h + sshll2 v7.4s, v5.8h, #6 // tmp1 << 6 + sshll v6.4s, v5.4h, #6 + sshll2 v5.4s, v4.8h, #6 + sshll v4.4s, v4.4h, #6 + ushr v20.8h, v20.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + uxtl v22.4s, v20.4h + uxtl2 v23.4s, v20.8h + uxtl v24.4s, v21.4h + uxtl2 v25.4s, v21.8h + mla v4.4s, v16.4s, v22.4s // (tmp2-tmp1)*(64-m) + mla v5.4s, v17.4s, v23.4s + mla v6.4s, v18.4s, v24.4s + mla v7.4s, v19.4s, v25.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v6.4s + sqxtun2 v5.8h, v7.4s + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + sub v20.16b, v1.16b, v20.16b // m + st1 {v20.16b}, [x6], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + xtn v20.8b, v20.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + st1 {v20.8b}, [x6], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v21.8h // (64 - my1) + (64 - my2) (row wise addition) + addp v20.8h, v20.8h, v20.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.4h, v3.4h, v20.4h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.s}[0], [x6], #4 +.endif + st1 {v4.8h}, [x0], x1 + st1 {v5.8h}, [x12], x1 + b.gt 8b + ret +1280: +640: +320: +160: + AARCH64_VALID_JUMP_TARGET + mov w11, w4 + sub x1, x1, w4, uxtw #1 +.if \type == 444 + add x10, x6, w4, uxtw +.elseif \type == 422 + add x10, x6, x11, lsr #1 +.endif + add x9, x3, w4, uxtw #1 + add x7, x2, w4, uxtw #1 +161: + mov w8, w4 +16: + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 + ld1 {v16.8h, v17.8h}, [x3], #32 // tmp2 + ld1 {v6.8h, v7.8h}, [x7], #32 + ld1 {v18.8h, v19.8h}, [x9], #32 + subs w8, w8, #16 + sabd v20.8h, v4.8h, v16.8h // abs(tmp1 - tmp2) + sabd v21.8h, v5.8h, v17.8h + ssubl v22.4s, v16.4h, v4.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v23.4s, v16.8h, v4.8h + ssubl v24.4s, v17.4h, v5.4h + ssubl2 v25.4s, v17.8h, v5.8h + uqsub v20.8h, v0.8h, v20.8h // 27615 - abs() + uqsub v21.8h, v0.8h, v21.8h + sshll2 v27.4s, v5.8h, #6 // tmp1 << 6 + sshll v26.4s, v5.4h, #6 + sshll2 v5.4s, v4.8h, #6 + sshll v4.4s, v4.4h, #6 + ushr v20.8h, v20.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v26.4s, v26.4s, v30.4s + add v27.4s, v27.4s, v30.4s + uxtl v16.4s, v20.4h + uxtl2 v17.4s, v20.8h + uxtl v28.4s, v21.4h + mla v4.4s, v22.4s, v16.4s // (tmp2-tmp1)*(64-m) + uxtl2 v16.4s, v21.8h + mla v5.4s, v23.4s, v17.4s + mla v26.4s, v24.4s, v28.4s + mla v27.4s, v25.4s, v16.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v26.4s, v26.4s, v29.4s + srshl v27.4s, v27.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v26.4s + sqxtun2 v5.8h, v27.4s + + // Start of other half + sabd v22.8h, v6.8h, v18.8h // abs(tmp1 - tmp2) + sabd v23.8h, v7.8h, v19.8h + + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h + + ssubl v16.4s, v18.4h, v6.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v17.4s, v18.8h, v6.8h + ssubl v18.4s, v19.4h, v7.4h + ssubl2 v19.4s, v19.8h, v7.8h + uqsub v22.8h, v0.8h, v22.8h // 27615 - abs() + uqsub v23.8h, v0.8h, v23.8h + sshll v24.4s, v6.4h, #6 // tmp1 << 6 + sshll2 v25.4s, v6.8h, #6 + sshll v26.4s, v7.4h, #6 + sshll2 v27.4s, v7.8h, #6 + ushr v22.8h, v22.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v23.8h, v23.8h, #10 + add v24.4s, v24.4s, v30.4s // += PREP_BIAS*64 + add v25.4s, v25.4s, v30.4s + add v26.4s, v26.4s, v30.4s + add v27.4s, v27.4s, v30.4s + uxtl v6.4s, v22.4h + uxtl2 v7.4s, v22.8h + uxtl v28.4s, v23.4h + mla v24.4s, v16.4s, v6.4s // (tmp2-tmp1)*(64-m) + uxtl2 v6.4s, v23.8h + mla v25.4s, v17.4s, v7.4s + mla v26.4s, v18.4s, v28.4s + mla v27.4s, v19.4s, v6.4s + srshl v24.4s, v24.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v25.4s, v25.4s, v29.4s + srshl v26.4s, v26.4s, v29.4s + srshl v27.4s, v27.4s, v29.4s + sqxtun v6.4h, v24.4s // iclip_pixel + sqxtun2 v6.8h, v25.4s + sqxtun v7.4h, v26.4s + sqxtun2 v7.8h, v27.4s + umin v6.8h, v6.8h, v31.8h // iclip_pixel + umin v7.8h, v7.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + uzp1 v21.16b, v22.16b, v23.16b + sub v20.16b, v1.16b, v20.16b // m + sub v21.16b, v1.16b, v21.16b + st1 {v20.16b}, [x6], #16 + st1 {v21.16b}, [x10], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + addp v21.8h, v22.8h, v23.8h + xtn v20.8b, v20.8h + xtn v21.8b, v21.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + uhsub v21.8b, v3.8b, v21.8b + st1 {v20.8b}, [x6], #8 + st1 {v21.8b}, [x10], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v22.8h // (64 - my1) + (64 - my2) (row wise addition) + add v21.8h, v21.8h, v23.8h + addp v20.8h, v20.8h, v21.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.8h, v3.8h, v20.8h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.8b}, [x6], #8 +.endif + st1 {v4.8h, v5.8h}, [x0], #32 + st1 {v6.8h, v7.8h}, [x12], #32 + b.gt 16b + subs w5, w5, #2 + add x2, x2, w4, uxtw #1 + add x3, x3, w4, uxtw #1 + add x7, x7, w4, uxtw #1 + add x9, x9, w4, uxtw #1 +.if \type == 444 + add x6, x6, w4, uxtw + add x10, x10, w4, uxtw +.elseif \type == 422 + add x6, x6, x11, lsr #1 + add x10, x10, x11, lsr #1 +.endif + add x0, x0, x1 + add x12, x12, x1 + b.gt 161b + ret +L(w_mask_\type\()_tbl): + .hword L(w_mask_\type\()_tbl) - 1280b + .hword L(w_mask_\type\()_tbl) - 640b + .hword L(w_mask_\type\()_tbl) - 320b + .hword L(w_mask_\type\()_tbl) - 160b + .hword L(w_mask_\type\()_tbl) - 8b + .hword L(w_mask_\type\()_tbl) - 4b +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + + +function blend_16bpc_neon, export=1 + adr x6, L(blend_tbl) + clz w3, w3 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + add x8, x0, x1 + br x6 +40: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +4: + ld1 {v2.8b}, [x5], #8 + ld1 {v1.8h}, [x2], #16 + ld1 {v0.d}[0], [x0] + neg v2.8b, v2.8b // -m + subs w4, w4, #2 + ld1 {v0.d}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.d}[0], [x0], x1 + st1 {v0.d}[1], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +8: + ld1 {v4.16b}, [x5], #16 + ld1 {v2.8h, v3.8h}, [x2], #32 + neg v5.16b, v4.16b // -m + ld1 {v0.8h}, [x0] + ld1 {v1.8h}, [x8] + sxtl v4.8h, v5.8b + sxtl2 v5.8h, v5.16b + shl v4.8h, v4.8h, #9 // -m << 9 + shl v5.8h, v5.8h, #9 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + subs w4, w4, #2 + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v5.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +16: + ld1 {v16.16b, v17.16b}, [x5], #32 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + subs w4, w4, #2 + neg v18.16b, v16.16b // -m + neg v19.16b, v17.16b + ld1 {v0.8h, v1.8h}, [x0] + sxtl v16.8h, v18.8b + sxtl2 v17.8h, v18.16b + sxtl v18.8h, v19.8b + sxtl2 v19.8h, v19.16b + ld1 {v2.8h, v3.8h}, [x8] + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + shl v18.8h, v18.8h, #9 + shl v19.8h, v19.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v17.8h + sqrdmulh v6.8h, v6.8h, v18.8h + sqrdmulh v7.8h, v7.8h, v19.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v2.8h, v3.8h}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b}, [x5], #32 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + subs w4, w4, #1 + neg v18.16b, v16.16b // -m + neg v19.16b, v17.16b + sxtl v16.8h, v18.8b + sxtl2 v17.8h, v18.16b + sxtl v18.8h, v19.8b + sxtl2 v19.8h, v19.16b + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + shl v18.8h, v18.8h, #9 + shl v19.8h, v19.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v17.8h + sqrdmulh v6.8h, v6.8h, v18.8h + sqrdmulh v7.8h, v7.8h, v19.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + b.gt 32b + ret +L(blend_tbl): + .hword L(blend_tbl) - 32b + .hword L(blend_tbl) - 160b + .hword L(blend_tbl) - 80b + .hword L(blend_tbl) - 40b +endfunc + +function blend_h_16bpc_neon, export=1 + adr x6, L(blend_h_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w4, uxtw + sub w4, w4, w4, lsr #2 + clz w7, w3 + add x8, x0, x1 + lsl x1, x1, #1 + sub w7, w7, #24 + ldrh w7, [x6, x7, lsl #1] + sub x6, x6, w7, uxtw + br x6 +2: + AARCH64_VALID_JUMP_TARGET + ld2r {v2.8b, v3.8b}, [x5], #2 + ld1 {v1.4h}, [x2], #8 + ext v2.8b, v2.8b, v3.8b, #6 + subs w4, w4, #2 + neg v2.8b, v2.8b // -m + ld1 {v0.s}[0], [x0] + ld1 {v0.s}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.4h, v2.4h, #9 // -m << 9 + sub v1.4h, v0.4h, v1.4h // a - b + sqrdmulh v1.4h, v1.4h, v2.4h // ((a-b)*-m + 32) >> 6 + add v0.4h, v0.4h, v1.4h + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[1], [x8], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld2r {v2.8b, v3.8b}, [x5], #2 + ld1 {v1.8h}, [x2], #16 + ext v2.8b, v2.8b, v3.8b, #4 + subs w4, w4, #2 + neg v2.8b, v2.8b // -m + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.d}[0], [x0], x1 + st1 {v0.d}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld2r {v4.8b, v5.8b}, [x5], #2 + ld1 {v2.8h, v3.8h}, [x2], #32 + neg v4.8b, v4.8b // -m + neg v5.8b, v5.8b + ld1 {v0.8h}, [x0] + subs w4, w4, #2 + sxtl v4.8h, v4.8b + sxtl v5.8h, v5.8b + ld1 {v1.8h}, [x8] + shl v4.8h, v4.8h, #9 // -m << 9 + shl v5.8h, v5.8h, #9 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v5.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld2r {v16.8b, v17.8b}, [x5], #2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + neg v16.8b, v16.8b // -m + neg v17.8b, v17.8b + ld1 {v0.8h, v1.8h}, [x0] + ld1 {v2.8h, v3.8h}, [x8] + subs w4, w4, #2 + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v16.8h + sqrdmulh v6.8h, v6.8h, v17.8h + sqrdmulh v7.8h, v7.8h, v17.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v2.8h, v3.8h}, [x8], x1 + b.gt 16b + ret +1280: +640: +320: + AARCH64_VALID_JUMP_TARGET + sub x1, x1, w3, uxtw #1 + add x7, x2, w3, uxtw #1 +321: + ld2r {v24.8b, v25.8b}, [x5], #2 + mov w6, w3 + neg v24.8b, v24.8b // -m + neg v25.8b, v25.8b + sxtl v24.8h, v24.8b + sxtl v25.8h, v25.8b + shl v24.8h, v24.8h, #9 // -m << 9 + shl v25.8h, v25.8h, #9 +32: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x2], #64 + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + subs w6, w6, #32 + sub v16.8h, v0.8h, v16.8h // a - b + sub v17.8h, v1.8h, v17.8h + sub v18.8h, v2.8h, v18.8h + sub v19.8h, v3.8h, v19.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x7], #64 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x8] + sqrdmulh v16.8h, v16.8h, v24.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v17.8h, v17.8h, v24.8h + sqrdmulh v18.8h, v18.8h, v24.8h + sqrdmulh v19.8h, v19.8h, v24.8h + sub v20.8h, v4.8h, v20.8h // a - b + sub v21.8h, v5.8h, v21.8h + sub v22.8h, v6.8h, v22.8h + sub v23.8h, v7.8h, v23.8h + add v0.8h, v0.8h, v16.8h + add v1.8h, v1.8h, v17.8h + add v2.8h, v2.8h, v18.8h + add v3.8h, v3.8h, v19.8h + sqrdmulh v20.8h, v20.8h, v25.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v21.8h, v21.8h, v25.8h + sqrdmulh v22.8h, v22.8h, v25.8h + sqrdmulh v23.8h, v23.8h, v25.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v4.8h, v4.8h, v20.8h + add v5.8h, v5.8h, v21.8h + add v6.8h, v6.8h, v22.8h + add v7.8h, v7.8h, v23.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x8], #64 + b.gt 32b + subs w4, w4, #2 + add x0, x0, x1 + add x8, x8, x1 + add x2, x2, w3, uxtw #1 + add x7, x7, w3, uxtw #1 + b.gt 321b + ret +L(blend_h_tbl): + .hword L(blend_h_tbl) - 1280b + .hword L(blend_h_tbl) - 640b + .hword L(blend_h_tbl) - 320b + .hword L(blend_h_tbl) - 16b + .hword L(blend_h_tbl) - 8b + .hword L(blend_h_tbl) - 4b + .hword L(blend_h_tbl) - 2b +endfunc + +function blend_v_16bpc_neon, export=1 + adr x6, L(blend_v_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w3, uxtw + clz w3, w3 + add x8, x0, x1 + lsl x1, x1, #1 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + br x6 +20: + AARCH64_VALID_JUMP_TARGET + ld1r {v2.8b}, [x5] + neg v2.8b, v2.8b // -m + sxtl v2.8h, v2.8b + shl v2.4h, v2.4h, #9 // -m << 9 +2: + ld1 {v1.s}[0], [x2], #4 + ld1 {v0.h}[0], [x0] + subs w4, w4, #2 + ld1 {v1.h}[1], [x2] + ld1 {v0.h}[1], [x8] + add x2, x2, #4 + sub v1.4h, v0.4h, v1.4h // a - b + sqrdmulh v1.4h, v1.4h, v2.4h // ((a-b)*-m + 32) >> 6 + add v0.4h, v0.4h, v1.4h + st1 {v0.h}[0], [x0], x1 + st1 {v0.h}[1], [x8], x1 + b.gt 2b + ret +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v2.2s}, [x5] + sub x1, x1, #4 + neg v2.8b, v2.8b // -m + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 +4: + ld1 {v1.8h}, [x2], #16 + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + subs w4, w4, #2 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.s}[0], [x0], #4 + st1 {v0.s}[2], [x8], #4 + st1 {v0.h}[2], [x0], x1 + st1 {v0.h}[6], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8b}, [x5] + sub x1, x1, #8 + neg v4.8b, v4.8b // -m + sxtl v4.8h, v4.8b + shl v4.8h, v4.8h, #9 // -m << 9 +8: + ld1 {v2.8h, v3.8h}, [x2], #32 + ld1 {v0.8h}, [x0] + ld1 {v1.8h}, [x8] + subs w4, w4, #2 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v4.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.d}[0], [x0], #8 + st1 {v1.d}[0], [x8], #8 + st1 {v0.s}[2], [x0], x1 + st1 {v1.s}[2], [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b}, [x5] + sub x1, x1, #16 + neg v17.16b, v16.16b // -m + sxtl v16.8h, v17.8b + sxtl2 v17.8h, v17.16b + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.4h, v17.4h, #9 +16: + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + ld1 {v0.8h, v1.8h}, [x0] + subs w4, w4, #2 + ld1 {v2.8h, v3.8h}, [x8] + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.4h, v1.4h, v5.4h + sub v6.8h, v2.8h, v6.8h + sub v7.4h, v3.4h, v7.4h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.4h, v5.4h, v17.4h + sqrdmulh v6.8h, v6.8h, v16.8h + sqrdmulh v7.4h, v7.4h, v17.4h + add v0.8h, v0.8h, v4.8h + add v1.4h, v1.4h, v5.4h + add v2.8h, v2.8h, v6.8h + add v3.4h, v3.4h, v7.4h + st1 {v0.8h}, [x0], #16 + st1 {v2.8h}, [x8], #16 + st1 {v1.4h}, [x0], x1 + st1 {v3.4h}, [x8], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v24.16b, v25.16b}, [x5] + neg v26.16b, v24.16b // -m + neg v27.8b, v25.8b + sxtl v24.8h, v26.8b + sxtl2 v25.8h, v26.16b + sxtl v26.8h, v27.8b + shl v24.8h, v24.8h, #9 // -m << 9 + shl v25.8h, v25.8h, #9 + shl v26.8h, v26.8h, #9 +32: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x2], #64 + ld1 {v0.8h, v1.8h, v2.8h}, [x0] + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x2], #64 + ld1 {v4.8h, v5.8h, v6.8h}, [x8] + subs w4, w4, #2 + sub v16.8h, v0.8h, v16.8h // a - b + sub v17.8h, v1.8h, v17.8h + sub v18.8h, v2.8h, v18.8h + sub v20.8h, v4.8h, v20.8h + sub v21.8h, v5.8h, v21.8h + sub v22.8h, v6.8h, v22.8h + sqrdmulh v16.8h, v16.8h, v24.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v17.8h, v17.8h, v25.8h + sqrdmulh v18.8h, v18.8h, v26.8h + sqrdmulh v20.8h, v20.8h, v24.8h + sqrdmulh v21.8h, v21.8h, v25.8h + sqrdmulh v22.8h, v22.8h, v26.8h + add v0.8h, v0.8h, v16.8h + add v1.8h, v1.8h, v17.8h + add v2.8h, v2.8h, v18.8h + add v4.8h, v4.8h, v20.8h + add v5.8h, v5.8h, v21.8h + add v6.8h, v6.8h, v22.8h + st1 {v0.8h, v1.8h, v2.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h}, [x8], x1 + b.gt 32b + ret +L(blend_v_tbl): + .hword L(blend_v_tbl) - 320b + .hword L(blend_v_tbl) - 160b + .hword L(blend_v_tbl) - 80b + .hword L(blend_v_tbl) - 40b + .hword L(blend_v_tbl) - 20b +endfunc + + +// This has got the same signature as the put_8tap functions, +// and assumes that x9 is set to (clz(w)-24). +function put_neon + adr x10, L(put_tbl) + ldrh w9, [x10, x9, lsl #1] + sub x10, x10, w9, uxtw + br x10 + +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], x3 + ld1 {v1.s}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.s}[0], [x0], x1 + st1 {v1.s}[0], [x0], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], x3 + ld1 {v1.4h}, [x2], x3 + subs w5, w5, #2 + st1 {v0.4h}, [x0], x1 + st1 {v1.4h}, [x0], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x8, x0, x1 + lsl x1, x1, #1 + add x9, x2, x3 + lsl x3, x3, #1 +8: + ld1 {v0.8h}, [x2], x3 + ld1 {v1.8h}, [x9], x3 + subs w5, w5, #2 + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + subs w5, w5, #1 + stp x8, x9, [x0, #16] + add x2, x2, x3 + add x0, x0, x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + ldp x10, x11, [x2, #32] + stp x8, x9, [x0, #16] + subs w5, w5, #1 + ldp x12, x13, [x2, #48] + stp x10, x11, [x0, #32] + stp x12, x13, [x0, #48] + add x2, x2, x3 + add x0, x0, x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x2, x2, x3 + add x0, x0, x1 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + ldp q16, q17, [x2, #128] + stp q6, q7, [x0, #96] + ldp q18, q19, [x2, #160] + stp q16, q17, [x0, #128] + ldp q20, q21, [x2, #192] + stp q18, q19, [x0, #160] + ldp q22, q23, [x2, #224] + stp q20, q21, [x0, #192] + stp q22, q23, [x0, #224] + add x2, x2, x3 + add x0, x0, x1 + b.gt 128b + ret + +L(put_tbl): + .hword L(put_tbl) - 128b + .hword L(put_tbl) - 64b + .hword L(put_tbl) - 32b + .hword L(put_tbl) - 16b + .hword L(put_tbl) - 80b + .hword L(put_tbl) - 4b + .hword L(put_tbl) - 2b +endfunc + + +// This has got the same signature as the prep_8tap functions, +// and assumes that x9 is set to (clz(w)-24), w7 to intermediate_bits and +// x8 to w*2. +function prep_neon + adr x10, L(prep_tbl) + ldrh w9, [x10, x9, lsl #1] + dup v31.8h, w7 // intermediate_bits + movi v30.8h, #(PREP_BIAS >> 8), lsl #8 + sub x10, x10, w9, uxtw + br x10 + +40: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +4: + ld1 {v0.d}[0], [x1], x2 + ld1 {v0.d}[1], [x9], x2 + subs w4, w4, #2 + sshl v0.8h, v0.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + st1 {v0.8h}, [x0], #16 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +8: + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x9], x2 + subs w4, w4, #2 + sshl v0.8h, v0.8h, v31.8h + sshl v1.8h, v1.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + add x1, x1, x2 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1] + add x1, x1, x2 + subs w4, w4, #2 + sshl v1.8h, v1.8h, v31.8h + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + add x1, x1, x2 + sshl v1.8h, v1.8h, v31.8h + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + subs w4, w4, #1 + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + subs w4, w4, #1 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + sshl v1.8h, v1.8h, v31.8h + ldp q4, q5, [x1, #64] + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + ldp q6, q7, [x1, #96] + add x1, x1, x2 + sshl v4.8h, v4.8h, v31.8h + sshl v5.8h, v5.8h, v31.8h + sshl v6.8h, v6.8h, v31.8h + sshl v7.8h, v7.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + stp q0, q1, [x0] + sub v4.8h, v4.8h, v30.8h + sub v5.8h, v5.8h, v30.8h + stp q2, q3, [x0, #32] + sub v6.8h, v6.8h, v30.8h + sub v7.8h, v7.8h, v30.8h + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x0, x0, x8 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + subs w4, w4, #1 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + sshl v1.8h, v1.8h, v31.8h + ldp q4, q5, [x1, #64] + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + ldp q6, q7, [x1, #96] + sshl v4.8h, v4.8h, v31.8h + sshl v5.8h, v5.8h, v31.8h + ldp q16, q17, [x1, #128] + sshl v6.8h, v6.8h, v31.8h + sshl v7.8h, v7.8h, v31.8h + ldp q18, q19, [x1, #160] + sshl v16.8h, v16.8h, v31.8h + sshl v17.8h, v17.8h, v31.8h + ldp q20, q21, [x1, #192] + sshl v18.8h, v18.8h, v31.8h + sshl v19.8h, v19.8h, v31.8h + ldp q22, q23, [x1, #224] + add x1, x1, x2 + sshl v20.8h, v20.8h, v31.8h + sshl v21.8h, v21.8h, v31.8h + sshl v22.8h, v22.8h, v31.8h + sshl v23.8h, v23.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + stp q0, q1, [x0] + sub v4.8h, v4.8h, v30.8h + sub v5.8h, v5.8h, v30.8h + stp q2, q3, [x0, #32] + sub v6.8h, v6.8h, v30.8h + sub v7.8h, v7.8h, v30.8h + stp q4, q5, [x0, #64] + sub v16.8h, v16.8h, v30.8h + sub v17.8h, v17.8h, v30.8h + stp q6, q7, [x0, #96] + sub v18.8h, v18.8h, v30.8h + sub v19.8h, v19.8h, v30.8h + stp q16, q17, [x0, #128] + sub v20.8h, v20.8h, v30.8h + sub v21.8h, v21.8h, v30.8h + stp q18, q19, [x0, #160] + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + stp q20, q21, [x0, #192] + stp q22, q23, [x0, #224] + add x0, x0, x8 + b.gt 128b + ret + +L(prep_tbl): + .hword L(prep_tbl) - 128b + .hword L(prep_tbl) - 64b + .hword L(prep_tbl) - 32b + .hword L(prep_tbl) - 16b + .hword L(prep_tbl) - 80b + .hword L(prep_tbl) - 40b +endfunc + + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}[0], [\s0], \strd + ld1 {\d1\wd}[0], [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}[0], [\s0], \strd + ld1 {\d3\wd}[0], [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}[0], [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}[0], [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}[0], [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}, [\s0], \strd + ld1 {\d1\wd}, [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}, [\s0], \strd + ld1 {\d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}, [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}, [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}, [\s0], \strd +.endif +.endm +.macro load_regpair s0, s1, strd, wd, d0, d1, d2, d3, d4, d5 + ld1 {\d0\wd, \d1\wd}, [\s0], \strd +.ifnb \d2 + ld1 {\d2\wd, \d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd, \d5\wd}, [\s0], \strd +.endif +.endm +.macro load_s s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .s, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_4h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .4h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_8h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .8h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_16h s0, s1, strd, d0, d1, d2, d3, d4, d5 + load_regpair \s0, \s1, \strd, .8h, \d0, \d1, \d2, \d3, \d4, \d5 +.endm +.macro interleave_1 wd, r0, r1, r2, r3, r4 + trn1 \r0\wd, \r0\wd, \r1\wd + trn1 \r1\wd, \r1\wd, \r2\wd +.ifnb \r3 + trn1 \r2\wd, \r2\wd, \r3\wd + trn1 \r3\wd, \r3\wd, \r4\wd +.endif +.endm +.macro interleave_1_s r0, r1, r2, r3, r4 + interleave_1 .2s, \r0, \r1, \r2, \r3, \r4 +.endm +.macro umin_h c, wd, r0, r1, r2, r3 + umin \r0\wd, \r0\wd, \c\wd +.ifnb \r1 + umin \r1\wd, \r1\wd, \c\wd +.endif +.ifnb \r2 + umin \r2\wd, \r2\wd, \c\wd + umin \r3\wd, \r3\wd, \c\wd +.endif +.endm +.macro sub_h c, wd, r0, r1, r2, r3 + sub \r0\wd, \r0\wd, \c\wd +.ifnb \r1 + sub \r1\wd, \r1\wd, \c\wd +.endif +.ifnb \r2 + sub \r2\wd, \r2\wd, \c\wd + sub \r3\wd, \r3\wd, \c\wd +.endif +.endm +.macro smull_smlal_4 d, s0, s1, s2, s3 + smull \d\().4s, \s0\().4h, v0.h[0] + smlal \d\().4s, \s1\().4h, v0.h[1] + smlal \d\().4s, \s2\().4h, v0.h[2] + smlal \d\().4s, \s3\().4h, v0.h[3] +.endm +.macro smull2_smlal2_4 d, s0, s1, s2, s3 + smull2 \d\().4s, \s0\().8h, v0.h[0] + smlal2 \d\().4s, \s1\().8h, v0.h[1] + smlal2 \d\().4s, \s2\().8h, v0.h[2] + smlal2 \d\().4s, \s3\().8h, v0.h[3] +.endm +.macro smull_smlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7 + smull \d\().4s, \s0\().4h, v0.h[0] + smlal \d\().4s, \s1\().4h, v0.h[1] + smlal \d\().4s, \s2\().4h, v0.h[2] + smlal \d\().4s, \s3\().4h, v0.h[3] + smlal \d\().4s, \s4\().4h, v0.h[4] + smlal \d\().4s, \s5\().4h, v0.h[5] + smlal \d\().4s, \s6\().4h, v0.h[6] + smlal \d\().4s, \s7\().4h, v0.h[7] +.endm +.macro smull2_smlal2_8 d, s0, s1, s2, s3, s4, s5, s6, s7 + smull2 \d\().4s, \s0\().8h, v0.h[0] + smlal2 \d\().4s, \s1\().8h, v0.h[1] + smlal2 \d\().4s, \s2\().8h, v0.h[2] + smlal2 \d\().4s, \s3\().8h, v0.h[3] + smlal2 \d\().4s, \s4\().8h, v0.h[4] + smlal2 \d\().4s, \s5\().8h, v0.h[5] + smlal2 \d\().4s, \s6\().8h, v0.h[6] + smlal2 \d\().4s, \s7\().8h, v0.h[7] +.endm +.macro sqrshrun_h shift, r0, r1, r2, r3 + sqrshrun \r0\().4h, \r0\().4s, #\shift +.ifnb \r1 + sqrshrun2 \r0\().8h, \r1\().4s, #\shift +.endif +.ifnb \r2 + sqrshrun \r2\().4h, \r2\().4s, #\shift + sqrshrun2 \r2\().8h, \r3\().4s, #\shift +.endif +.endm +.macro xtn_h r0, r1, r2, r3 + uzp1 \r0\().8h, \r0\().8h, \r1\().8h // Same as xtn, xtn2 +.ifnb \r2 + uzp1 \r2\().8h, \r2\().8h, \r3\().8h // Ditto +.endif +.endm +.macro srshl_s shift, r0, r1, r2, r3 + srshl \r0\().4s, \r0\().4s, \shift\().4s + srshl \r1\().4s, \r1\().4s, \shift\().4s +.ifnb \r2 + srshl \r2\().4s, \r2\().4s, \shift\().4s + srshl \r3\().4s, \r3\().4s, \shift\().4s +.endif +.endm +.macro st_s strd, reg, lanes + st1 {\reg\().s}[0], [x0], \strd + st1 {\reg\().s}[1], [x9], \strd +.if \lanes > 2 + st1 {\reg\().s}[2], [x0], \strd + st1 {\reg\().s}[3], [x9], \strd +.endif +.endm +.macro st_d strd, r0, r1 + st1 {\r0\().d}[0], [x0], \strd + st1 {\r0\().d}[1], [x9], \strd +.ifnb \r1 + st1 {\r1\().d}[0], [x0], \strd + st1 {\r1\().d}[1], [x9], \strd +.endif +.endm +.macro shift_store_4 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin_h v31, .8h, \r0, \r2 +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub_h v29, .8h, \r0, \r2 // PREP_BIAS +.endif + st_d \strd, \r0, \r2 +.endm +.macro st_reg strd, wd, r0, r1, r2, r3, r4, r5, r6, r7 + st1 {\r0\wd}, [x0], \strd + st1 {\r1\wd}, [x9], \strd +.ifnb \r2 + st1 {\r2\wd}, [x0], \strd + st1 {\r3\wd}, [x9], \strd +.endif +.ifnb \r4 + st1 {\r4\wd}, [x0], \strd + st1 {\r5\wd}, [x9], \strd + st1 {\r6\wd}, [x0], \strd + st1 {\r7\wd}, [x9], \strd +.endif +.endm +.macro st_8h strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .8h, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro shift_store_8 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin_h v31, .8h, \r0, \r2 +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub_h v29, .8h, \r0, \r2 // PREP_BIAS +.endif + st_8h \strd, \r0, \r2 +.endm +.macro shift_store_16 type, strd, dst, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin \r0\().8h, \r0\().8h, v31.8h + umin \r1\().8h, \r2\().8h, v31.8h +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub \r0\().8h, \r0\().8h, v29.8h + sub \r1\().8h, \r2\().8h, v29.8h +.endif + st1 {\r0\().8h, \r1\().8h}, [\dst], \strd +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_16bpc_neon, export=1 + mov w9, \type_h + mov w10, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, xmx, my, xmy, bdmax, ds2, sr2 +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon +.ifc \bdmax, w8 + ldr w8, [sp] +.endif + mov w11, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, w11 + mul \my, \my, w11 + add \mx, \mx, w9 // mx, 8tap_h, 4tap_h + add \my, \my, w10 // my, 8tap_v, 4tap_v +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + dup v31.8h, \bdmax // bitdepth_max + clz \bdmax, \bdmax + clz w9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + mov w12, #6 + tst \mx, #(0x7f << 14) + sub w9, w9, #24 + add w13, w12, \bdmax // 6 + intermediate_bits + sub w12, w12, \bdmax // 6 - intermediate_bits + movrel x11, X(mc_subpel_filters), -8 + b.ne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + b.ne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx w10, \mx, #7, #7 + and \mx, \mx, #0x7f + b.le 4f + mov \mx, w10 +4: + tst \my, #(0x7f << 14) + add \xmx, x11, \mx, uxtw #3 + b.ne L(\type\()_8tap_hv) + + adr x10, L(\type\()_8tap_h_tbl) + dup v30.4s, w12 // 6 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v30.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + dup v29.8h, \bdmax // intermediate_bits +.else + movi v28.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v29.8h, v29.8h // -intermediate_bits +.endif + br x10 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +2: + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + subs \h, \h, #2 + trn1 v3.2s, v4.2s, v6.2s + trn2 v6.2s, v4.2s, v6.2s + trn1 v4.2s, v5.2s, v7.2s + trn2 v7.2s, v5.2s, v7.2s + smull v3.4s, v3.4h, v0.h[0] + smlal v3.4s, v4.4h, v0.h[1] + smlal v3.4s, v6.4h, v0.h[2] + smlal v3.4s, v7.4h, v0.h[3] + srshl v3.4s, v3.4s, v30.4s // -(6-intermediate_bits) + sqxtun v3.4h, v3.4s + srshl v3.4h, v3.4h, v29.4h // -intermediate_bits + umin v3.4h, v3.4h, v31.4h + st1 {v3.s}[0], [\dst], \d_strd + st1 {v3.s}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +4: + ld1 {v16.8h}, [\src], \s_strd + ld1 {v20.8h}, [\sr2], \s_strd + ext v17.16b, v16.16b, v16.16b, #2 + ext v18.16b, v16.16b, v16.16b, #4 + ext v19.16b, v16.16b, v16.16b, #6 + ext v21.16b, v20.16b, v20.16b, #2 + ext v22.16b, v20.16b, v20.16b, #4 + ext v23.16b, v20.16b, v20.16b, #6 + subs \h, \h, #2 + smull v16.4s, v16.4h, v0.h[0] + smlal v16.4s, v17.4h, v0.h[1] + smlal v16.4s, v18.4h, v0.h[2] + smlal v16.4s, v19.4h, v0.h[3] + smull v20.4s, v20.4h, v0.h[0] + smlal v20.4s, v21.4h, v0.h[1] + smlal v20.4s, v22.4h, v0.h[2] + smlal v20.4s, v23.4h, v0.h[3] + srshl v16.4s, v16.4s, v30.4s // -(6-intermediate_bits) + srshl v20.4s, v20.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + sqxtun v16.4h, v16.4s + sqxtun2 v16.8h, v20.4s + srshl v16.8h, v16.8h, v29.8h // -intermediate_bits + umin v16.8h, v16.8h, v31.8h +.else + uzp1 v16.8h, v16.8h, v20.8h // Same as xtn, xtn2 + sub v16.8h, v16.8h, v28.8h // PREP_BIAS +.endif + st1 {v16.d}[0], [\dst], \d_strd + st1 {v16.d}[1], [\ds2], \d_strd + b.gt 4b + ret + +80: +160: +320: +640: +1280: // 8xN, 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #6 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + sub \s_strd, \s_strd, \w, uxtw #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw #1 +.endif +81: + ld1 {v16.8h, v17.8h}, [\src], #32 + ld1 {v20.8h, v21.8h}, [\sr2], #32 + mov \mx, \w + +8: + smull v18.4s, v16.4h, v0.h[0] + smull2 v19.4s, v16.8h, v0.h[0] + smull v22.4s, v20.4h, v0.h[0] + smull2 v23.4s, v20.8h, v0.h[0] +.irpc i, 1234567 + ext v24.16b, v16.16b, v17.16b, #(2*\i) + ext v25.16b, v20.16b, v21.16b, #(2*\i) + smlal v18.4s, v24.4h, v0.h[\i] + smlal2 v19.4s, v24.8h, v0.h[\i] + smlal v22.4s, v25.4h, v0.h[\i] + smlal2 v23.4s, v25.8h, v0.h[\i] +.endr + subs \mx, \mx, #8 + srshl v18.4s, v18.4s, v30.4s // -(6-intermediate_bits) + srshl v19.4s, v19.4s, v30.4s // -(6-intermediate_bits) + srshl v22.4s, v22.4s, v30.4s // -(6-intermediate_bits) + srshl v23.4s, v23.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + sqxtun v18.4h, v18.4s + sqxtun2 v18.8h, v19.4s + sqxtun v22.4h, v22.4s + sqxtun2 v22.8h, v23.4s + srshl v18.8h, v18.8h, v29.8h // -intermediate_bits + srshl v22.8h, v22.8h, v29.8h // -intermediate_bits + umin v18.8h, v18.8h, v31.8h + umin v22.8h, v22.8h, v31.8h +.else + uzp1 v18.8h, v18.8h, v19.8h // Same as xtn, xtn2 + uzp1 v22.8h, v22.8h, v23.8h // Ditto + sub v18.8h, v18.8h, v28.8h // PREP_BIAS + sub v22.8h, v22.8h, v28.8h // PREP_BIAS +.endif + st1 {v18.8h}, [\dst], #16 + st1 {v22.8h}, [\ds2], #16 + b.le 9f + + mov v16.16b, v17.16b + mov v20.16b, v21.16b + ld1 {v17.8h}, [\src], #16 + ld1 {v21.8h}, [\sr2], #16 + b 8b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 81b + ret + +L(\type\()_8tap_h_tbl): + .hword L(\type\()_8tap_h_tbl) - 1280b + .hword L(\type\()_8tap_h_tbl) - 640b + .hword L(\type\()_8tap_h_tbl) - 320b + .hword L(\type\()_8tap_h_tbl) - 160b + .hword L(\type\()_8tap_h_tbl) - 80b + .hword L(\type\()_8tap_h_tbl) - 40b + .hword L(\type\()_8tap_h_tbl) - 20b + .hword 0 + + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx w10, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w10 +4: + add \xmy, x11, \my, uxtw #3 + +.ifc \type, prep + dup v30.4s, w12 // 6 - intermediate_bits + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + adr x10, L(\type\()_8tap_v_tbl) + ldrh w9, [x10, x9, lsl #1] +.ifc \type, prep + neg v30.4s, v30.4s // -(6-intermediate_bits) +.endif + sub x10, x10, w9, uxtw + br x10 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + b.gt 28f + + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + // 2x2 v + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_s v1, v2, v3, v4, v5 + b.gt 24f + smull_smlal_4 v6, v1, v2, v3, v4 + sqrshrun_h 6, v6 + umin_h v31, .8h, v6 + st_s \d_strd, v6, 2 + ret + +24: // 2x4 v + load_s \sr2, \src, \s_strd, v6, v7 + interleave_1_s v5, v6, v7 + smull_smlal_4 v16, v1, v2, v3, v4 + smull_smlal_4 v17, v3, v4, v5, v6 + sqrshrun_h 6, v16, v17 + umin_h v31, .8h, v16 + st_s \d_strd, v16, 4 + ret + +28: // 2x6, 2x8, 2x12, 2x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5, v6, v7 + interleave_1_s v1, v2, v3, v4, v5 + interleave_1_s v5, v6, v7 +216: + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v16, v17, v18, v19 + interleave_1_s v7, v16, v17, v18, v19 + smull_smlal_8 v24, v1, v2, v3, v4, v5, v6, v7, v16 + smull_smlal_8 v25, v3, v4, v5, v6, v7, v16, v17, v18 + sqrshrun_h 6, v24, v25 + umin_h v31, .8h, v24 + st_s \d_strd, v24, 4 + b.le 0f + cmp \h, #2 + mov v1.16b, v5.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + mov v4.16b, v16.16b + mov v5.16b, v17.16b + mov v6.16b, v18.16b + mov v7.16b, v19.16b + b.eq 26f + b 216b +26: + load_s \sr2, \src, \s_strd, v16, v17 + interleave_1_s v7, v16, v17 + smull_smlal_8 v24, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_h 6, v24 + umin_h v31, .4h, v24 + st_s \d_strd, v24, 2 +0: + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + b.gt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_4h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + smull_smlal_4 v6, v1, v2, v3, v4 + smull_smlal_4 v7, v2, v3, v4, v5 + shift_store_4 \type, \d_strd, v6, v7 + b.le 0f + load_4h \sr2, \src, \s_strd, v6, v7 + smull_smlal_4 v1, v3, v4, v5, v6 + smull_smlal_4 v2, v4, v5, v6, v7 + shift_store_4 \type, \d_strd, v1, v2 +0: + ret + +480: // 4x6, 4x8, 4x12, 4x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_4h \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + +48: + subs \h, \h, #4 + load_4h \sr2, \src, \s_strd, v23, v24, v25, v26 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v2, v17, v18, v19, v20, v21, v22, v23, v24 + smull_smlal_8 v3, v18, v19, v20, v21, v22, v23, v24, v25 + smull_smlal_8 v4, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_4 \type, \d_strd, v1, v2, v3, v4 + b.le 0f + cmp \h, #2 + mov v16.8b, v20.8b + mov v17.8b, v21.8b + mov v18.8b, v22.8b + mov v19.8b, v23.8b + mov v20.8b, v24.8b + mov v21.8b, v25.8b + mov v22.8b, v26.8b + b.eq 46f + b 48b +46: + load_4h \sr2, \src, \s_strd, v23, v24 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v2, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_4 \type, \d_strd, v1, v2 +0: + ret + +80: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_8h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + smull_smlal_4 v16, v1, v2, v3, v4 + smull2_smlal2_4 v17, v1, v2, v3, v4 + smull_smlal_4 v18, v2, v3, v4, v5 + smull2_smlal2_4 v19, v2, v3, v4, v5 + shift_store_8 \type, \d_strd, v16, v17, v18, v19 + b.le 0f + load_8h \sr2, \src, \s_strd, v6, v7 + smull_smlal_4 v16, v3, v4, v5, v6 + smull2_smlal2_4 v17, v3, v4, v5, v6 + smull_smlal_4 v18, v4, v5, v6, v7 + smull2_smlal2_4 v19, v4, v5, v6, v7 + shift_store_8 \type, \d_strd, v16, v17, v18, v19 +0: + ret + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmy] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_8h \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + +88: + subs \h, \h, #2 + load_8h \sr2, \src, \s_strd, v23, v24 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull2_smlal2_8 v2, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v3, v17, v18, v19, v20, v21, v22, v23, v24 + smull2_smlal2_8 v4, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.le 9f + subs \h, \h, #2 + load_8h \sr2, \src, \s_strd, v25, v26 + smull_smlal_8 v1, v18, v19, v20, v21, v22, v23, v24, v25 + smull2_smlal2_8 v2, v18, v19, v20, v21, v22, v23, v24, v25 + smull_smlal_8 v3, v19, v20, v21, v22, v23, v24, v25, v26 + smull2_smlal2_8 v4, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.le 9f + mov v16.16b, v20.16b + mov v17.16b, v21.16b + mov v18.16b, v22.16b + mov v19.16b, v23.16b + mov v20.16b, v24.16b + mov v21.16b, v25.16b + mov v22.16b, v26.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + ret + +160: + AARCH64_VALID_JUMP_TARGET + b.gt 1680b + + // 16x2, 16x4 v + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + + load_16h \src, \src, \s_strd, v16, v17, v18, v19, v20, v21 +16: + load_16h \src, \src, \s_strd, v22, v23 + subs \h, \h, #1 + smull_smlal_4 v1, v16, v18, v20, v22 + smull2_smlal2_4 v2, v16, v18, v20, v22 + smull_smlal_4 v3, v17, v19, v21, v23 + smull2_smlal2_4 v4, v17, v19, v21, v23 + shift_store_16 \type, \d_strd, x0, v1, v2, v3, v4 + b.le 0f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v23.16b + b 16b +0: + ret + +L(\type\()_8tap_v_tbl): + .hword L(\type\()_8tap_v_tbl) - 1280b + .hword L(\type\()_8tap_v_tbl) - 640b + .hword L(\type\()_8tap_v_tbl) - 320b + .hword L(\type\()_8tap_v_tbl) - 160b + .hword L(\type\()_8tap_v_tbl) - 80b + .hword L(\type\()_8tap_v_tbl) - 40b + .hword L(\type\()_8tap_v_tbl) - 20b + .hword 0 + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx w10, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w10 +4: + add \xmy, x11, \my, uxtw #3 + + adr x10, L(\type\()_8tap_hv_tbl) + dup v30.4s, w12 // 6 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v30.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + dup v29.4s, w13 // 6 + intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v29.4s, v29.4s // -(6+intermediate_bits) +.endif + br x10 + +20: + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 280f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + + // 2x2, 2x4 hv + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v27.8h}, [\src], \s_strd + ext v28.16b, v27.16b, v27.16b, #2 + smull v27.4s, v27.4h, v0.4h + smull v28.4s, v28.4h, v0.4h + addp v27.4s, v27.4s, v28.4s + addp v16.4s, v27.4s, v27.4s + srshl v16.2s, v16.2s, v30.2s // -(6-intermediate_bits) + bl L(\type\()_8tap_filter_2) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + trn1 v16.2s, v16.2s, v24.2s + mov v17.8b, v24.8b + +2: + bl L(\type\()_8tap_filter_2) + + ext v18.8b, v17.8b, v24.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + umin v2.4h, v2.4h, v31.4h + subs \h, \h, #2 + st1 {v2.s}[0], [\dst], \d_strd + st1 {v2.s}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v24.8b + b 2b + +280: // 2x8, 2x16, 2x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v27.8h}, [\src], \s_strd + ext v28.16b, v27.16b, v27.16b, #2 + smull v27.4s, v27.4h, v0.4h + smull v28.4s, v28.4h, v0.4h + addp v27.4s, v27.4s, v28.4s + addp v16.4s, v27.4s, v27.4s + srshl v16.2s, v16.2s, v30.2s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + + bl L(\type\()_8tap_filter_2) + xtn v16.4h, v16.4s + trn1 v16.2s, v16.2s, v24.2s + mov v17.8b, v24.8b + bl L(\type\()_8tap_filter_2) + ext v18.8b, v17.8b, v24.8b, #4 + mov v19.8b, v24.8b + bl L(\type\()_8tap_filter_2) + ext v20.8b, v19.8b, v24.8b, #4 + mov v21.8b, v24.8b + +28: + bl L(\type\()_8tap_filter_2) + ext v22.8b, v21.8b, v24.8b, #4 + smull v3.4s, v16.4h, v1.h[0] + smlal v3.4s, v17.4h, v1.h[1] + smlal v3.4s, v18.4h, v1.h[2] + smlal v3.4s, v19.4h, v1.h[3] + smlal v3.4s, v20.4h, v1.h[4] + smlal v3.4s, v21.4h, v1.h[5] + smlal v3.4s, v22.4h, v1.h[6] + smlal v3.4s, v24.4h, v1.h[7] + + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + sqxtun v3.4h, v3.4s + umin v3.4h, v3.4h, v31.4h + subs \h, \h, #2 + st1 {v3.s}[0], [\dst], \d_strd + st1 {v3.s}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v24.8b + b 28b + +0: + ret x15 + +L(\type\()_8tap_filter_2): + ld1 {v25.8h}, [\sr2], \s_strd + ld1 {v27.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v28.16b, v27.16b, v27.16b, #2 + trn1 v24.2s, v25.2s, v27.2s + trn2 v27.2s, v25.2s, v27.2s + trn1 v25.2s, v26.2s, v28.2s + trn2 v28.2s, v26.2s, v28.2s + smull v24.4s, v24.4h, v0.h[0] + smlal v24.4s, v25.4h, v0.h[1] + smlal v24.4s, v27.4h, v0.h[2] + smlal v24.4s, v28.4h, v0.h[3] + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + xtn v24.4h, v24.4s + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 480f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + // 4x2, 4x4 hv + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v16.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v24.8b + mov v18.8b, v25.8b + +4: + bl L(\type\()_8tap_filter_4) + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v24.4h, v1.h[2] + smlal v3.4s, v25.4h, v1.h[3] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + umin v2.8h, v2.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + + st1 {v2.d}[0], [\dst], \d_strd + st1 {v2.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v24.8b + mov v18.8b, v25.8b + b 4b + +480: // 4x8, 4x16, 4x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v16.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v24.8b + mov v18.8b, v25.8b + bl L(\type\()_8tap_filter_4) + mov v19.8b, v24.8b + mov v20.8b, v25.8b + bl L(\type\()_8tap_filter_4) + mov v21.8b, v24.8b + mov v22.8b, v25.8b + +48: + bl L(\type\()_8tap_filter_4) + smull v3.4s, v16.4h, v1.h[0] + smlal v3.4s, v17.4h, v1.h[1] + smlal v3.4s, v18.4h, v1.h[2] + smlal v3.4s, v19.4h, v1.h[3] + smlal v3.4s, v20.4h, v1.h[4] + smlal v3.4s, v21.4h, v1.h[5] + smlal v3.4s, v22.4h, v1.h[6] + smlal v3.4s, v24.4h, v1.h[7] + smull v4.4s, v17.4h, v1.h[0] + smlal v4.4s, v18.4h, v1.h[1] + smlal v4.4s, v19.4h, v1.h[2] + smlal v4.4s, v20.4h, v1.h[3] + smlal v4.4s, v21.4h, v1.h[4] + smlal v4.4s, v22.4h, v1.h[5] + smlal v4.4s, v24.4h, v1.h[6] + smlal v4.4s, v25.4h, v1.h[7] +.ifc \type, put + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + sqxtun v3.4h, v3.4s + sqxtun2 v3.8h, v4.4s + umin v3.8h, v3.8h, v31.8h +.else + rshrn v3.4h, v3.4s, #6 + rshrn2 v3.8h, v4.4s, #6 + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v3.d}[0], [\dst], \d_strd + st1 {v3.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v24.8b + mov v22.8b, v25.8b + b 48b +0: + ret x15 + +L(\type\()_8tap_filter_4): + ld1 {v24.8h}, [\sr2], \s_strd + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v24.16b, v24.16b, #2 + ext v27.16b, v24.16b, v24.16b, #4 + ext v28.16b, v24.16b, v24.16b, #6 + smull v24.4s, v24.4h, v0.h[0] + smlal v24.4s, v26.4h, v0.h[1] + smlal v24.4s, v27.4h, v0.h[2] + smlal v24.4s, v28.4h, v0.h[3] + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + xtn v24.4h, v24.4s + xtn v25.4h, v25.4s + ret + +80: +160: +320: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + add \xmy, \xmy, #2 + ld1 {v0.8b}, [\xmx] + ld1 {v1.s}[0], [\xmy] + sub \src, \src, #6 + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + ld1 {v27.8h, v28.8h}, [\src], \s_strd + smull v24.4s, v27.4h, v0.h[0] + smull2 v25.4s, v27.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v27.16b, v28.16b, #(2*\i) + smlal v24.4s, v26.4h, v0.h[\i] + smlal2 v25.4s, v26.8h, v0.h[\i] +.endr + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53), + // and conserves register space (no need to clobber v8-v15). + uzp1 v16.8h, v24.8h, v25.8h // Same as xtn, xtn2 + + bl L(\type\()_8tap_filter_8) + mov v17.16b, v23.16b + mov v18.16b, v24.16b + +8: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v23.4h, v1.h[2] + smlal2 v5.4s, v23.8h, v1.h[2] + smlal v2.4s, v23.4h, v1.h[3] + smlal2 v3.4s, v23.8h, v1.h[3] + smlal v4.4s, v24.4h, v1.h[3] + smlal2 v5.4s, v24.8h, v1.h[3] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + srshl v5.4s, v5.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v31.8h + umin v3.8h, v3.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v2.8h}, [\dst], \d_strd + st1 {v3.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v23.16b + mov v18.16b, v24.16b + b 8b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 164b + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + ld1 {v1.8b}, [\xmy] + sub \src, \src, #6 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + ld1 {v27.8h, v28.8h}, [\src], \s_strd + smull v24.4s, v27.4h, v0.h[0] + smull2 v25.4s, v27.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v27.16b, v28.16b, #(2*\i) + smlal v24.4s, v26.4h, v0.h[\i] + smlal2 v25.4s, v26.8h, v0.h[\i] +.endr + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53), + // and conserves register space (no need to clobber v8-v15). + uzp1 v16.8h, v24.8h, v25.8h // Same as xtn, xtn2 + + bl L(\type\()_8tap_filter_8) + mov v17.16b, v23.16b + mov v18.16b, v24.16b + bl L(\type\()_8tap_filter_8) + mov v19.16b, v23.16b + mov v20.16b, v24.16b + bl L(\type\()_8tap_filter_8) + mov v21.16b, v23.16b + mov v22.16b, v24.16b + +88: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v19.4h, v1.h[2] + smlal2 v5.4s, v19.8h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal2 v3.4s, v19.8h, v1.h[3] + smlal v4.4s, v20.4h, v1.h[3] + smlal2 v5.4s, v20.8h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal2 v3.4s, v20.8h, v1.h[4] + smlal v4.4s, v21.4h, v1.h[4] + smlal2 v5.4s, v21.8h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal2 v3.4s, v21.8h, v1.h[5] + smlal v4.4s, v22.4h, v1.h[5] + smlal2 v5.4s, v22.8h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal2 v3.4s, v22.8h, v1.h[6] + smlal v4.4s, v23.4h, v1.h[6] + smlal2 v5.4s, v23.8h, v1.h[6] + smlal v2.4s, v23.4h, v1.h[7] + smlal2 v3.4s, v23.8h, v1.h[7] + smlal v4.4s, v24.4h, v1.h[7] + smlal2 v5.4s, v24.8h, v1.h[7] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + srshl v5.4s, v5.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v31.8h + umin v3.8h, v3.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v2.8h}, [\dst], \d_strd + st1 {v3.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v23.16b + mov v22.16b, v24.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + ret x15 + +L(\type\()_8tap_filter_8): + ld1 {v4.8h, v5.8h}, [\sr2], \s_strd + ld1 {v6.8h, v7.8h}, [\src], \s_strd + smull v25.4s, v4.4h, v0.h[0] + smull2 v26.4s, v4.8h, v0.h[0] + smull v27.4s, v6.4h, v0.h[0] + smull2 v28.4s, v6.8h, v0.h[0] +.irpc i, 1234567 + ext v23.16b, v4.16b, v5.16b, #(2*\i) + ext v24.16b, v6.16b, v7.16b, #(2*\i) + smlal v25.4s, v23.4h, v0.h[\i] + smlal2 v26.4s, v23.8h, v0.h[\i] + smlal v27.4s, v24.4h, v0.h[\i] + smlal2 v28.4s, v24.8h, v0.h[\i] +.endr + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + srshl v26.4s, v26.4s, v30.4s // -(6-intermediate_bits) + srshl v27.4s, v27.4s, v30.4s // -(6-intermediate_bits) + srshl v28.4s, v28.4s, v30.4s // -(6-intermediate_bits) + uzp1 v23.8h, v25.8h, v26.8h // Same as xtn, xtn2 + uzp1 v24.8h, v27.8h, v28.8h // Ditto + ret + +L(\type\()_8tap_hv_tbl): + .hword L(\type\()_8tap_hv_tbl) - 1280b + .hword L(\type\()_8tap_hv_tbl) - 640b + .hword L(\type\()_8tap_hv_tbl) - 320b + .hword L(\type\()_8tap_hv_tbl) - 160b + .hword L(\type\()_8tap_hv_tbl) - 80b + .hword L(\type\()_8tap_hv_tbl) - 40b + .hword L(\type\()_8tap_hv_tbl) - 20b + .hword 0 +endfunc + + +function \type\()_bilin_16bpc_neon, export=1 +.ifc \bdmax, w8 + ldr w8, [sp] +.endif + dup v1.8h, \mx + dup v3.8h, \my + mov w10, #16 + sub w9, w10, \mx + sub w10, w10, \my + dup v0.8h, w9 + dup v2.8h, w10 +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz \bdmax, \bdmax // bitdepth_max + clz w9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + mov w11, #4 + sub w9, w9, #24 + sub w11, w11, \bdmax // 4 - intermediate_bits + add w12, \bdmax, #4 // 4 + intermediate_bits + cbnz \mx, L(\type\()_bilin_h) + cbnz \my, L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cbnz \my, L(\type\()_bilin_hv) + + adr x10, L(\type\()_bilin_h_tbl) + dup v31.8h, w11 // 4 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v31.8h, v31.8h // -(4-intermediate_bits) +.ifc \type, put + dup v30.8h, \bdmax // intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v30.8h, v30.8h // -intermediate_bits +.endif + br x10 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + ld1 {v4.4h}, [\src], \s_strd + ld1 {v6.4h}, [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #2 + ext v7.8b, v6.8b, v6.8b, #2 + trn1 v4.2s, v4.2s, v6.2s + trn1 v5.2s, v5.2s, v7.2s + subs \h, \h, #2 + mul v4.4h, v4.4h, v0.4h + mla v4.4h, v5.4h, v1.4h + urshl v4.4h, v4.4h, v31.4h + urshl v4.4h, v4.4h, v30.4h + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + trn1 v4.2d, v4.2d, v6.2d + trn1 v5.2d, v5.2d, v7.2d + subs \h, \h, #2 + mul v4.8h, v4.8h, v0.8h + mla v4.8h, v5.8h, v1.8h + urshl v4.8h, v4.8h, v31.8h +.ifc \type, put + urshl v4.8h, v4.8h, v30.8h +.else + sub v4.8h, v4.8h, v29.8h +.endif + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + ldr h5, [\src, #16] + ldr h7, [\sr2, #16] + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v5.16b, #2 + ext v7.16b, v6.16b, v7.16b, #2 + subs \h, \h, #2 + mul v4.8h, v4.8h, v0.8h + mla v4.8h, v5.8h, v1.8h + mul v6.8h, v6.8h, v0.8h + mla v6.8h, v7.8h, v1.8h + urshl v4.8h, v4.8h, v31.8h + urshl v6.8h, v6.8h, v31.8h +.ifc \type, put + urshl v4.8h, v4.8h, v30.8h + urshl v6.8h, v6.8h, v30.8h +.else + sub v4.8h, v4.8h, v29.8h + sub v6.8h, v6.8h, v29.8h +.endif + st1 {v4.8h}, [\dst], \d_strd + st1 {v6.8h}, [\ds2], \d_strd + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w, uxtw #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw #1 +.endif +161: + ld1 {v16.8h}, [\src], #16 + ld1 {v21.8h}, [\sr2], #16 + mov \mx, \w + +16: + ld1 {v17.8h, v18.8h}, [\src], #32 + ld1 {v22.8h, v23.8h}, [\sr2], #32 + ext v19.16b, v16.16b, v17.16b, #2 + ext v20.16b, v17.16b, v18.16b, #2 + ext v24.16b, v21.16b, v22.16b, #2 + ext v25.16b, v22.16b, v23.16b, #2 + mul v16.8h, v16.8h, v0.8h + mla v16.8h, v19.8h, v1.8h + mul v17.8h, v17.8h, v0.8h + mla v17.8h, v20.8h, v1.8h + mul v21.8h, v21.8h, v0.8h + mla v21.8h, v24.8h, v1.8h + mul v22.8h, v22.8h, v0.8h + mla v22.8h, v25.8h, v1.8h + urshl v16.8h, v16.8h, v31.8h + urshl v17.8h, v17.8h, v31.8h + urshl v21.8h, v21.8h, v31.8h + urshl v22.8h, v22.8h, v31.8h + subs \mx, \mx, #16 +.ifc \type, put + urshl v16.8h, v16.8h, v30.8h + urshl v17.8h, v17.8h, v30.8h + urshl v21.8h, v21.8h, v30.8h + urshl v22.8h, v22.8h, v30.8h +.else + sub v16.8h, v16.8h, v29.8h + sub v17.8h, v17.8h, v29.8h + sub v21.8h, v21.8h, v29.8h + sub v22.8h, v22.8h, v29.8h +.endif + st1 {v16.8h, v17.8h}, [\dst], #32 + st1 {v21.8h, v22.8h}, [\ds2], #32 + b.le 9f + + mov v16.16b, v18.16b + mov v21.16b, v23.16b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_bilin_h_tbl): + .hword L(\type\()_bilin_h_tbl) - 1280b + .hword L(\type\()_bilin_h_tbl) - 640b + .hword L(\type\()_bilin_h_tbl) - 320b + .hword L(\type\()_bilin_h_tbl) - 160b + .hword L(\type\()_bilin_h_tbl) - 80b + .hword L(\type\()_bilin_h_tbl) - 40b + .hword L(\type\()_bilin_h_tbl) - 20b + .hword 0 + + +L(\type\()_bilin_v): + cmp \h, #4 + adr x10, L(\type\()_bilin_v_tbl) +.ifc \type, prep + dup v31.8h, w11 // 4 - intermediate_bits +.endif + ldrh w9, [x10, x9, lsl #1] +.ifc \type, prep + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 + neg v31.8h, v31.8h // -(4-intermediate_bits) +.endif + sub x10, x10, w9, uxtw + br x10 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + ld1 {v16.s}[0], [\src], \s_strd + b.gt 24f +22: + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + mul v4.4h, v16.4h, v2.4h + mla v4.4h, v17.4h, v3.4h + urshr v4.8h, v4.8h, #4 + st1 {v4.s}[0], [\dst] + st1 {v4.s}[1], [\ds2] + ret +24: // 2x4, 2x6, 2x8, ... v + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + ld1 {v19.s}[0], [\sr2], \s_strd + ld1 {v20.s}[0], [\src], \s_strd + sub \h, \h, #4 + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + trn1 v18.2s, v18.2s, v19.2s + trn1 v19.2s, v19.2s, v20.2s + trn1 v16.2d, v16.2d, v18.2d + trn1 v17.2d, v17.2d, v19.2d + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + cmp \h, #2 + urshr v4.8h, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + st1 {v4.s}[2], [\dst], \d_strd + st1 {v4.s}[3], [\ds2], \d_strd + b.lt 0f + mov v16.8b, v20.8b + b.eq 22b + b 24b +0: + ret +.endif + +40: // 4xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.4h}, [\src], \s_strd +4: + ld1 {v17.4h}, [\sr2], \s_strd + ld1 {v18.4h}, [\src], \s_strd + trn1 v16.2d, v16.2d, v17.2d + trn1 v17.2d, v17.2d, v18.2d + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + sub v4.8h, v4.8h, v29.8h +.endif + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + b 4b +0: + ret + +80: // 8xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.8h}, [\src], \s_strd +8: + ld1 {v17.8h}, [\sr2], \s_strd + ld1 {v18.8h}, [\src], \s_strd + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v18.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + urshl v5.8h, v5.8h, v31.8h + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h +.endif + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd + b.le 0f + mov v16.16b, v18.16b + b 8b +0: + ret + +160: // 16xN, 32xN, ... +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v16.8h, v17.8h}, [\src], \s_strd +2: + ld1 {v18.8h, v19.8h}, [\sr2], \s_strd + ld1 {v20.8h, v21.8h}, [\src], \s_strd + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v18.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v19.8h, v3.8h + mul v6.8h, v18.8h, v2.8h + mla v6.8h, v20.8h, v3.8h + mul v7.8h, v19.8h, v2.8h + mla v7.8h, v21.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 + urshr v6.8h, v6.8h, #4 + urshr v7.8h, v7.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + urshl v5.8h, v5.8h, v31.8h + urshl v6.8h, v6.8h, v31.8h + urshl v7.8h, v7.8h, v31.8h + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h + sub v6.8h, v6.8h, v29.8h + sub v7.8h, v7.8h, v29.8h +.endif + st1 {v4.8h, v5.8h}, [\dst], \d_strd + st1 {v6.8h, v7.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v20.16b + mov v17.16b, v21.16b + b 2b +9: + subs \w, \w, #16 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #32 + add \dst, \dst, #32 + b 1b +0: + ret + +L(\type\()_bilin_v_tbl): + .hword L(\type\()_bilin_v_tbl) - 1280b + .hword L(\type\()_bilin_v_tbl) - 640b + .hword L(\type\()_bilin_v_tbl) - 320b + .hword L(\type\()_bilin_v_tbl) - 160b + .hword L(\type\()_bilin_v_tbl) - 80b + .hword L(\type\()_bilin_v_tbl) - 40b + .hword L(\type\()_bilin_v_tbl) - 20b + .hword 0 + +L(\type\()_bilin_hv): + adr x10, L(\type\()_bilin_hv_tbl) + dup v31.8h, w11 // 4 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v31.8h, v31.8h // -(4-intermediate_bits) +.ifc \type, put + dup v30.4s, w12 // 4 + intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v30.4s, v30.4s // -(4+intermediate_bits) +.endif + br x10 + +20: // 2xN hv + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v20.4h}, [\src], \s_strd + ext v21.8b, v20.8b, v20.8b, #2 + mul v16.4h, v20.4h, v0.4h + mla v16.4h, v21.4h, v1.4h + urshl v16.4h, v16.4h, v31.4h + +2: + ld1 {v22.4h}, [\sr2], \s_strd + ld1 {v24.4h}, [\src], \s_strd + ext v23.8b, v22.8b, v22.8b, #2 + ext v25.8b, v24.8b, v24.8b, #2 + trn1 v22.2s, v22.2s, v24.2s + trn1 v23.2s, v23.2s, v25.2s + mul v17.4h, v22.4h, v0.4h + mla v17.4h, v23.4h, v1.4h + urshl v17.4h, v17.4h, v31.4h + + trn1 v16.2s, v16.2s, v17.2s + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + urshl v4.4s, v4.4s, v30.4s + xtn v4.4h, v4.4s + subs \h, \h, #2 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2s, v17.2s, v17.2s + b 2b +0: + ret +.endif + +40: // 4xN hv + AARCH64_VALID_JUMP_TARGET + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v20.8h}, [\src], \s_strd + ext v21.16b, v20.16b, v20.16b, #2 + mul v16.4h, v20.4h, v0.4h + mla v16.4h, v21.4h, v1.4h + urshl v16.4h, v16.4h, v31.4h + +4: + ld1 {v22.8h}, [\sr2], \s_strd + ld1 {v24.8h}, [\src], \s_strd + ext v23.16b, v22.16b, v22.16b, #2 + ext v25.16b, v24.16b, v24.16b, #2 + trn1 v22.2d, v22.2d, v24.2d + trn1 v23.2d, v23.2d, v25.2d + mul v17.8h, v22.8h, v0.8h + mla v17.8h, v23.8h, v1.8h + urshl v17.8h, v17.8h, v31.8h + + trn1 v16.2d, v16.2d, v17.2d + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + umull2 v5.4s, v16.8h, v2.8h + umlal2 v5.4s, v17.8h, v3.8h +.ifc \type, put + urshl v4.4s, v4.4s, v30.4s + urshl v5.4s, v5.4s, v30.4s + uzp1 v4.8h, v4.8h, v5.8h // Same as xtn, xtn2 +.else + rshrn v4.4h, v4.4s, #4 + rshrn2 v4.8h, v5.4s, #4 + sub v4.8h, v4.8h, v29.8h +.endif + subs \h, \h, #2 + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2d, v17.2d, v17.2d + b 4b +0: + ret + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ldr h21, [\src, #16] + ld1 {v20.8h}, [\src], \s_strd + ext v21.16b, v20.16b, v21.16b, #2 + mul v16.8h, v20.8h, v0.8h + mla v16.8h, v21.8h, v1.8h + urshl v16.8h, v16.8h, v31.8h + +2: + ldr h23, [\sr2, #16] + ld1 {v22.8h}, [\sr2], \s_strd + ldr h25, [\src, #16] + ld1 {v24.8h}, [\src], \s_strd + ext v23.16b, v22.16b, v23.16b, #2 + ext v25.16b, v24.16b, v25.16b, #2 + mul v17.8h, v22.8h, v0.8h + mla v17.8h, v23.8h, v1.8h + mul v18.8h, v24.8h, v0.8h + mla v18.8h, v25.8h, v1.8h + urshl v17.8h, v17.8h, v31.8h + urshl v18.8h, v18.8h, v31.8h + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + umull2 v5.4s, v16.8h, v2.8h + umlal2 v5.4s, v17.8h, v3.8h + umull v6.4s, v17.4h, v2.4h + umlal v6.4s, v18.4h, v3.4h + umull2 v7.4s, v17.8h, v2.8h + umlal2 v7.4s, v18.8h, v3.8h +.ifc \type, put + urshl v4.4s, v4.4s, v30.4s + urshl v5.4s, v5.4s, v30.4s + urshl v6.4s, v6.4s, v30.4s + urshl v7.4s, v7.4s, v30.4s + uzp1 v4.8h, v4.8h, v5.8h // Same as xtn, xtn2 + uzp1 v5.8h, v6.8h, v7.8h // Ditto +.else + rshrn v4.4h, v4.4s, #4 + rshrn2 v4.8h, v5.4s, #4 + rshrn v5.4h, v6.4s, #4 + rshrn2 v5.8h, v7.4s, #4 + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h +.endif + subs \h, \h, #2 + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 1b +0: + ret + +L(\type\()_bilin_hv_tbl): + .hword L(\type\()_bilin_hv_tbl) - 1280b + .hword L(\type\()_bilin_hv_tbl) - 640b + .hword L(\type\()_bilin_hv_tbl) - 320b + .hword L(\type\()_bilin_hv_tbl) - 160b + .hword L(\type\()_bilin_hv_tbl) - 80b + .hword L(\type\()_bilin_hv_tbl) - 40b + .hword L(\type\()_bilin_hv_tbl) - 20b + .hword 0 +endfunc +.endm + +filter_fn put, x0, x1, x2, x3, w4, w5, w6, x6, w7, x7, w8, x9, x10 +filter_fn prep, x0, x8, x1, x2, w3, w4, w5, x5, w6, x6, w7, x9, x10 + +.macro load_filter_row dst, src, inc + asr w13, \src, #10 + add \src, \src, \inc + ldr \dst, [x11, w13, sxtw #3] +.endm + +function warp_filter_horz_neon + add w12, w5, #512 + + ld1 {v16.8h, v17.8h}, [x2], x3 + + load_filter_row d0, w12, w7 + load_filter_row d1, w12, w7 + load_filter_row d2, w12, w7 + sxtl v0.8h, v0.8b + load_filter_row d3, w12, w7 + sxtl v1.8h, v1.8b + load_filter_row d4, w12, w7 + sxtl v2.8h, v2.8b + load_filter_row d5, w12, w7 + sxtl v3.8h, v3.8b + load_filter_row d6, w12, w7 + sxtl v4.8h, v4.8b + load_filter_row d7, w12, w7 + sxtl v5.8h, v5.8b + ext v18.16b, v16.16b, v17.16b, #2*1 + smull v8.4s, v16.4h, v0.4h + smull2 v9.4s, v16.8h, v0.8h + sxtl v6.8h, v6.8b + ext v19.16b, v16.16b, v17.16b, #2*2 + smull v10.4s, v18.4h, v1.4h + smull2 v11.4s, v18.8h, v1.8h + sxtl v7.8h, v7.8b + ext v20.16b, v16.16b, v17.16b, #2*3 + smull v0.4s, v19.4h, v2.4h + smull2 v1.4s, v19.8h, v2.8h + ext v21.16b, v16.16b, v17.16b, #2*4 + addp v8.4s, v8.4s, v9.4s + smull v2.4s, v20.4h, v3.4h + smull2 v3.4s, v20.8h, v3.8h + ext v22.16b, v16.16b, v17.16b, #2*5 + addp v9.4s, v10.4s, v11.4s + smull v10.4s, v21.4h, v4.4h + smull2 v11.4s, v21.8h, v4.8h + ext v23.16b, v16.16b, v17.16b, #2*6 + addp v0.4s, v0.4s, v1.4s + smull v18.4s, v22.4h, v5.4h + smull2 v19.4s, v22.8h, v5.8h + ext v16.16b, v16.16b, v17.16b, #2*7 + addp v1.4s, v2.4s, v3.4s + addp v2.4s, v10.4s, v11.4s + smull v20.4s, v23.4h, v6.4h + smull2 v21.4s, v23.8h, v6.8h + addp v3.4s, v18.4s, v19.4s + smull v22.4s, v16.4h, v7.4h + smull2 v23.4s, v16.8h, v7.8h + addp v4.4s, v20.4s, v21.4s + addp v5.4s, v22.4s, v23.4s + + addp v8.4s, v8.4s, v9.4s + addp v0.4s, v0.4s, v1.4s + addp v2.4s, v2.4s, v3.4s + addp v4.4s, v4.4s, v5.4s + + addp v16.4s, v8.4s, v0.4s + addp v17.4s, v2.4s, v4.4s + + add w5, w5, w8 + + srshl v16.4s, v16.4s, v14.4s // -(7 - intermediate_bits) + srshl v17.4s, v17.4s, v14.4s // -(7 - intermediate_bits) + + ret +endfunc + +// void dav1d_warp_affine_8x8_16bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my, +// const int bitdepth_max) +.macro warp t +function warp_affine_8x8\t\()_16bpc_neon, export=1 + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + +.ifb \t + dup v15.8h, w7 // bitdepth_max +.else + movi v15.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + clz w7, w7 + // intermediate_bits = clz(bitdepth_max) - 18 +.ifb \t + sub w8, w7, #11 // 7 + intermediate_bits = clz(bitdepth_max) - 18 + 7 +.endif + sub w7, w7, #25 // -(7 - intermediate_bits) +.ifb \t + neg w8, w8 // -(7 + intermediate_bits) +.endif + dup v14.4s, w7 // -(7 - intermediate_bits) +.ifb \t + dup v13.4s, w8 // -(7 + intermediate_bits) +.endif + + ldr x4, [x4] + sbfx x7, x4, #0, #16 + sbfx x8, x4, #16, #16 + sbfx x9, x4, #32, #16 + sbfx x4, x4, #48, #16 + mov w10, #8 + sub x2, x2, x3, lsl #1 + sub x2, x2, x3 + sub x2, x2, #6 + movrel x11, X(mc_warp_filter), 64*8 + mov x15, x30 +.ifnb \t + lsl x1, x1, #1 +.endif + + bl warp_filter_horz_neon + uzp1 v24.8h, v16.8h, v17.8h // Same as xtn, xtn2 + bl warp_filter_horz_neon + uzp1 v25.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v26.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v27.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v28.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v29.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v30.8h, v16.8h, v17.8h // Ditto + +1: + add w14, w6, #512 + bl warp_filter_horz_neon + uzp1 v31.8h, v16.8h, v17.8h // Same as xtn, xtn2 + + load_filter_row d0, w14, w9 + load_filter_row d1, w14, w9 + load_filter_row d2, w14, w9 + load_filter_row d3, w14, w9 + load_filter_row d4, w14, w9 + load_filter_row d5, w14, w9 + load_filter_row d6, w14, w9 + load_filter_row d7, w14, w9 + transpose_8x8b_xtl v0, v1, v2, v3, v4, v5, v6, v7, sxtl + + // This ordering of smull/smlal/smull2/smlal2 is highly + // beneficial for Cortex A53 here. + smull v16.4s, v24.4h, v0.4h + smlal v16.4s, v25.4h, v1.4h + smlal v16.4s, v26.4h, v2.4h + smlal v16.4s, v27.4h, v3.4h + smlal v16.4s, v28.4h, v4.4h + smlal v16.4s, v29.4h, v5.4h + smlal v16.4s, v30.4h, v6.4h + smlal v16.4s, v31.4h, v7.4h + smull2 v17.4s, v24.8h, v0.8h + smlal2 v17.4s, v25.8h, v1.8h + smlal2 v17.4s, v26.8h, v2.8h + smlal2 v17.4s, v27.8h, v3.8h + smlal2 v17.4s, v28.8h, v4.8h + smlal2 v17.4s, v29.8h, v5.8h + smlal2 v17.4s, v30.8h, v6.8h + smlal2 v17.4s, v31.8h, v7.8h + + mov v24.16b, v25.16b + mov v25.16b, v26.16b +.ifb \t + srshl v16.4s, v16.4s, v13.4s // -(7 + intermediate_bits) + srshl v17.4s, v17.4s, v13.4s // -(7 + intermediate_bits) +.else + rshrn v16.4h, v16.4s, #7 + rshrn2 v16.8h, v17.4s, #7 +.endif + mov v26.16b, v27.16b +.ifb \t + sqxtun v16.4h, v16.4s + sqxtun2 v16.8h, v17.4s +.else + sub v16.8h, v16.8h, v15.8h // PREP_BIAS +.endif + mov v27.16b, v28.16b + mov v28.16b, v29.16b +.ifb \t + umin v16.8h, v16.8h, v15.8h // bitdepth_max +.endif + mov v29.16b, v30.16b + mov v30.16b, v31.16b + subs w10, w10, #1 + st1 {v16.8h}, [x0], x1 + + add w6, w6, w4 + b.gt 1b + + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + + ret x15 +endfunc +.endm + +warp +warp t + +// void dav1d_emu_edge_16bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_16bpc_neon, export=1 + ldp x8, x9, [sp] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub x12, x3, #1 // ih - 1 + cmp x5, x3 + sub x13, x2, #1 // iw - 1 + csel x12, x12, x5, ge // min(y, ih - 1) + cmp x4, x2 + bic x12, x12, x12, asr #63 // max(min(y, ih - 1), 0) + csel x13, x13, x4, ge // min(x, iw - 1) + bic x13, x13, x13, asr #63 // max(min(x, iw - 1), 0) + madd x8, x12, x9, x8 // ref += iclip() * stride + add x8, x8, x13, lsl #1 // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add x10, x5, x1 // y + bh + neg x5, x5 // -y + sub x10, x10, x3 // y + bh - ih + sub x12, x1, #1 // bh - 1 + cmp x10, x1 + bic x5, x5, x5, asr #63 // max(-y, 0) + csel x10, x10, x12, lt // min(y + bh - ih, bh-1) + cmp x5, x1 + bic x10, x10, x10, asr #63 // max(min(y + bh - ih, bh-1), 0) + csel x5, x5, x12, lt // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add x11, x4, x0 // x + bw + neg x4, x4 // -x + sub x11, x11, x2 // x + bw - iw + sub x13, x0, #1 // bw - 1 + cmp x11, x0 + bic x4, x4, x4, asr #63 // max(-x, 0) + csel x11, x11, x13, lt // min(x + bw - iw, bw-1) + cmp x4, x0 + bic x11, x11, x11, asr #63 // max(min(x + bw - iw, bw-1), 0) + csel x4, x4, x13, lt // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub x1, x1, x5 // bh - top_ext + madd x6, x5, x7, x6 + sub x2, x0, x4 // bw - left_ext + sub x1, x1, x10 // center_h = bh - top_ext - bottom_ext + sub x2, x2, x11 // center_w = bw - left_ext - right_ext + + mov x14, x6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + ld1r {v0.8h}, [x8] + mov x12, x6 // out = dst + mov x3, x4 + mov v1.16b, v0.16b +1: + subs x3, x3, #16 + st1 {v0.8h, v1.8h}, [x12], #32 + b.gt 1b +.endif + mov x13, x8 + add x12, x6, x4, lsl #1 // out = dst + left_ext + mov x3, x2 +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x13], #64 + subs x3, x3, #32 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x12], #64 + b.gt 1b +.if \need_right + add x3, x8, x2, lsl #1 // in + center_w + sub x3, x3, #2 // in + center_w - 1 + add x12, x6, x4, lsl #1 // dst + left_ext + ld1r {v0.8h}, [x3] + add x12, x12, x2, lsl #1 // out = dst + left_ext + center_w + mov x3, x11 + mov v1.16b, v0.16b +1: + subs x3, x3, #16 + st1 {v0.8h, v1.8h}, [x12], #32 + b.gt 1b +.endif + + subs x1, x1, #1 // center_h-- + add x6, x6, x7 + add x8, x8, x9 + b.gt 0b +.endm + + cbz x4, 2f + // need_left + cbz x11, 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cbz x11, 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + + cbz x10, 3f + // need_bottom + sub x8, x6, x7 // ref = dst - stride + mov x4, x0 +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x8], #64 + mov x3, x10 +2: + subs x3, x3, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x7 + b.gt 2b + msub x6, x7, x10, x6 // dst -= bottom_ext * stride + subs x4, x4, #32 // bw -= 32 + add x6, x6, #64 // dst += 32 + b.gt 1b + +3: + cbz x5, 3f + // need_top + msub x6, x7, x5, x14 // dst = stored_dst - top_ext * stride +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x14], #64 + mov x3, x5 +2: + subs x3, x3, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x7 + b.gt 2b + msub x6, x7, x5, x6 // dst -= top_ext * stride + subs x0, x0, #32 // bw -= 32 + add x6, x6, #64 // dst += 32 + b.gt 1b + +3: + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/satd.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/satd.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/satd.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/satd.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1473 @@ +/* Copyright (c) 2022-2023, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "src/asm/arm/asm.S" +#include "util.S" + +.macro butterfly r0, r1, r2, r3, t=8h + add \r0\().\t, \r2\().\t, \r3\().\t + sub \r1\().\t, \r2\().\t, \r3\().\t +.endm + +.macro butterflyw r0, r1, r2, r3, r4, r5 + sxtl \r0\().4s, \r4\().4h + sxtl2 \r2\().4s, \r4\().8h + ssubw \r1\().4s, \r0\().4s, \r5\().4h + ssubw2 \r3\().4s, \r2\().4s, \r5\().8h + saddw \r0\().4s, \r0\().4s, \r5\().4h + saddw2 \r2\().4s, \r2\().4s, \r5\().8h +.endm + +.macro interleave r0, r1, r2, r3 + zip1 \r0\().8h, \r2\().8h, \r3\().8h + zip2 \r1\().8h, \r2\().8h, \r3\().8h +.endm + +.macro interleave_pairs r0, r1, r2, r3 + zip1 \r0\().4s, \r2\().4s, \r3\().4s + zip2 \r1\().4s, \r2\().4s, \r3\().4s +.endm + +.macro interleave_quads r0, r1, r2, r3 + zip1 \r0\().2d, \r2\().2d, \r3\().2d + zip2 \r1\().2d, \r2\().2d, \r3\().2d +.endm + +.macro normalize_4 + add w0, w0, 2 + lsr w0, w0, 2 +.endm + +.macro normalize_8 + add w0, w0, 4 + lsr w0, w0, 3 +.endm + +// x0: src: *const u8, +// x1: src_stride: isize, +// x2: dst: *const u8, +// x3: dst_stride: isize, +function satd4x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + ldr s0, [src] + ldr s1, [dst] + + // subtract; cast to 16-bit + usubl v0.8h, v0.8b, v1.8b + + ldr s1, [src, src_stride] + ldr s2, [dst, dst_stride] + + usubl v1.8h, v1.8b, v2.8b + + // stride * 2 + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr s2, [src, x8] + ldr s3, [dst, x9] + + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr s3, [src, x8] + ldr s4, [dst, x9] + + usubl v3.8h, v3.8b, v4.8b + + // pack rows 0-2, 1-3 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // Horizontal transform + + // v0 0 1 2 3 8 9 10 11 + // v1 4 5 6 7 12 13 14 15 + + butterfly v2, v3, v0, v1 + + // v2 [0+4][1+5][2+6][3+7] [8+12][9+13][10+14][11+15] + // v3 [0-4][1-5][2-6][3-7] [8-12][9-13][10-14][11-15] + + interleave v0, v1, v2, v3 + + // v0 [ 0+4][ 0-4][ 1+5][ 1-5] [2 + 6][2 - 6][3 + 7][3 - 7] + // v1 [8+12][8-12][9+13][9-13] [10+14][10-14][11+15][11-15] + + butterfly v2, v3, v0, v1 + + // v2 [0+4+8+12][0-4+8-12][1+5+9+13][1-5+9-13] [2+6+10+14][2-6+10-14][3+7+11+15][3-7+11-15] + // v3 [0+4-8-12][0-4-8+12][1+5-9-13][1-5-9+13] [2+6-10-14][2-6-10+14][3+7-11-15][3-7-11+15] + + interleave_pairs v0, v1, v2, v3 + + // Vertical transform + + butterfly v2, v3, v0, v1 + + interleave v0, v1, v2, v3 + + butterfly v2, v3, v0, v1 + + // sum up transform + abs v2.8h, v2.8h + abs v3.8h, v3.8h + + add v0.8h, v2.8h, v3.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro DOUBLE_HADAMARD_4X4 hbd=0 + // Horizontal transform + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave_pairs v0, v1, v2, v3 + interleave_pairs v4, v5, v6, v7 + + // Vertical transform + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + +.if \hbd == 0 + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 +.else + butterflyw v2, v3, v16, v17, v0, v1 + butterflyw v6, v7, v18, v19, v4, v5 +.endif +.endm + +.macro SUM_DOUBLE_HADAMARD_4X4 + abs v2.8h, v2.8h + abs v3.8h, v3.8h + abs v6.8h, v6.8h + abs v7.8h, v7.8h + + add v0.8h, v2.8h, v3.8h + add v1.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v1.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 +.endm + +function satd8x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + // load 8 pixel row + ldr d0, [src] + ldr d1, [dst] + + usubl v0.8h, v0.8b, v1.8b + + ldr d1, [src, src_stride] + ldr d2, [dst, dst_stride] + + usubl v1.8h, v1.8b, v2.8b + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr d2, [src, x8] + ldr d3, [dst, x9] + + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr d3, [src, x8] + ldr d4, [dst, x9] + + usubl v3.8h, v3.8b, v4.8b + + // extract top 64 bits out of register + // (4 x 16 bits = 64) + + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + + // pack rows 0-2, 1-3 (set 1) + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // pack rows 0-2, 1-3 (set 2) + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + + // v2-3 temp registers for first 4x4 block// + // 6-7 for second block + + DOUBLE_HADAMARD_4X4 + + SUM_DOUBLE_HADAMARD_4X4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro load_row n0, n1, src, dst, src_stride, dst_stride, should_add=1 + ldr s\n0, [\src] + ldr s\n1, [\dst] + + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b + +.if \should_add != 0 + add \src, \src, \src_stride + add \dst, \dst, \dst_stride +.endif +.endm + +.macro load_row2 n0, n1, src, dst, src_stride, dst_stride + ldr s\n0, [\src, \src_stride] + ldr s\n1, [\dst, \dst_stride] + + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b +.endm + +function satd4x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + // 0 * stride + load_row 0, 1, src, dst, src_stride, dst_stride, 0 + // 1 * stride + load_row2 1, 2, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + // pattern repeats + load_row 2, 3, src, dst, src_stride, dst_stride, 0 + load_row2 3, 4, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 4, 5, src, dst, src_stride, dst_stride, 0 + load_row2 5, 6, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 6, 7, src, dst, src_stride, dst_stride, 0 + load_row2 7, 8, src, dst, src_stride, dst_stride + + // pack rows + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + mov v4.d[1], v6.d[0] + mov v5.d[1], v7.d[0] + + DOUBLE_HADAMARD_4X4 + + SUM_DOUBLE_HADAMARD_4X4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +function satd16x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define ROW1 v0 + #define ROW2 v1 + #define TMP1 v2 + #define TMP2 v3 + + #define ROW3 v4 + #define ROW4 v5 + #define TMP3 v6 + #define TMP4 v7 + + #define ROW5 v16 + #define ROW6 v17 + #define TMP5 v20 + #define TMP6 v21 + + #define ROW7 v18 + #define ROW8 v19 + #define TMP7 v22 + #define TMP8 v23 + + // load 16 pixel row + ldr q0, [src] + ldr q1, [dst] + + usubl2 v16.8h, v0.16b, v1.16b + usubl v0.8h, v0.8b, v1.8b + + ldr q1, [src, src_stride] + ldr q2, [dst, dst_stride] + + usubl2 v17.8h, v1.16b, v2.16b + usubl v1.8h, v1.8b, v2.8b + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr q2, [src, x8] + ldr q3, [dst, x9] + + usubl2 v6.8h, v2.16b, v3.16b + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr q3, [src, x8] + ldr q4, [dst, x9] + + usubl2 v7.8h, v3.16b, v4.16b + usubl v3.8h, v3.8b, v4.8b + + // swap high/low 64 bits + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + ext v18.16b, v16.16b, v16.16b, 8 + ext v19.16b, v17.16b, v17.16b, 8 + + mov v16.d[1], v6.d[0] + mov v17.d[1], v7.d[0] + // 2-3 free + + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + // 6-7 free + mov v18.d[1], v6.d[1] + mov v19.d[1], v7.d[1] + + // 0,1 2,3 + // 4,5 6,7 + // 16,17 20,21 + // 18,19 22,23 + + // quadruple 4x4 hadamard + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave ROW1, ROW2, TMP1, TMP2 + interleave ROW3, ROW4, TMP3, TMP4 + interleave ROW5, ROW6, TMP5, TMP6 + interleave ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave_pairs ROW1, ROW2, TMP1, TMP2 + interleave_pairs ROW3, ROW4, TMP3, TMP4 + interleave_pairs ROW5, ROW6, TMP5, TMP6 + interleave_pairs ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave ROW1, ROW2, TMP1, TMP2 + interleave ROW3, ROW4, TMP3, TMP4 + interleave ROW5, ROW6, TMP5, TMP6 + interleave ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + // absolute value of transform coefficients + abs TMP1.8h, TMP1.8h + abs TMP2.8h, TMP2.8h + abs TMP3.8h, TMP3.8h + abs TMP4.8h, TMP4.8h + abs TMP5.8h, TMP5.8h + abs TMP6.8h, TMP6.8h + abs TMP7.8h, TMP7.8h + abs TMP8.8h, TMP8.8h + + // stage 1 sum + add TMP1.8h, TMP1.8h, TMP5.8h + add TMP2.8h, TMP2.8h, TMP6.8h + add TMP3.8h, TMP3.8h, TMP7.8h + add TMP4.8h, TMP4.8h, TMP8.8h + + // stage 2 sum + add TMP1.8h, TMP1.8h, TMP3.8h + add TMP2.8h, TMP2.8h, TMP4.8h + add v0.8h, TMP1.8h, TMP2.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef ROW1 + #undef TMP1 + #undef ROW2 + #undef TMP2 + #undef ROW3 + #undef TMP3 + #undef ROW4 + #undef TMP4 + #undef ROW5 + #undef TMP5 + #undef ROW6 + #undef TMP6 + #undef ROW7 + #undef TMP7 + #undef ROW8 + #undef TMP8 +endfunc + +function satd4x16_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + load_row 0, 1, src, dst, src_stride, dst_stride, 0 + load_row2 1, 2, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 2, 3, src, dst, src_stride, dst_stride, 0 + load_row2 3, 4, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 4, 5, src, dst, src_stride, dst_stride, 0 + load_row2 5, 6, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 6, 7, src, dst, src_stride, dst_stride, 0 + load_row2 7, 16, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 16, 17, src, dst, src_stride, dst_stride, 0 + load_row2 17, 18, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 18, 19, src, dst, src_stride, dst_stride, 0 + load_row2 19, 20, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 20, 21, src, dst, src_stride, dst_stride, 0 + load_row2 21, 22, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 22, 23, src, dst, src_stride, dst_stride, 0 + load_row2 23, 24, src, dst, src_stride, dst_stride + + // pack rows + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + mov v4.d[1], v6.d[0] + mov v5.d[1], v7.d[0] + + mov v16.d[1], v18.d[0] + mov v17.d[1], v19.d[0] + + mov v20.d[1], v22.d[0] + mov v21.d[1], v23.d[0] + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + interleave v16, v17, v18, v19 + interleave v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave_pairs v0, v1, v2, v3 + interleave_pairs v4, v5, v6, v7 + interleave_pairs v16, v17, v18, v19 + interleave_pairs v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + interleave v16, v17, v18, v19 + interleave v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + abs v2.8h, v2.8h + abs v3.8h, v3.8h + abs v6.8h, v6.8h + abs v7.8h, v7.8h + abs v18.8h, v18.8h + abs v19.8h, v19.8h + abs v22.8h, v22.8h + abs v23.8h, v23.8h + + add v2.8h, v2.8h, v3.8h + add v6.8h, v6.8h, v7.8h + add v18.8h, v18.8h, v19.8h + add v22.8h, v22.8h, v23.8h + + add v2.8h, v2.8h, v6.8h + add v18.8h, v18.8h, v22.8h + add v0.8h, v2.8h, v18.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro load_rows n0, n1, n2, src, dst, src_stride, dst_stride, n3=0, n4=0 +.if \n3 == 0 + ldr d\n0, [\src] + ldr d\n1, [\dst] +.else + ldr q\n0, [\src] + ldr q\n1, [\dst] + usubl2 v\n3\().8h, v\n0\().16b, v\n1\().16b +.endif + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b + +.if \n4 == 0 + ldr d\n1, [\src, \src_stride] + ldr d\n2, [\dst, \dst_stride] +.else + ldr q\n1, [\src, \src_stride] + ldr q\n2, [\dst, \dst_stride] + usubl2 v\n4\().8h, v\n1\().16b, v\n2\().16b +.endif + usubl v\n1\().8h, v\n1\().8b, v\n2\().8b + + add \src, \src, \src_stride, lsl 1 + add \dst, \dst, \dst_stride, lsl 1 +.endm + +.macro HADAMARD_8X8_H \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // Horizontal transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + + interleave v\a0, v\a1, v\b0, v\b1 + interleave v\a2, v\a3, v\b2, v\b3 + interleave v\a4, v\a5, v\b4, v\b5 + interleave v\a6, v\a7, v\b6, v\b7 + + butterfly v\b0, v\b2, v\a0, v\a2 + butterfly v\b1, v\b3, v\a1, v\a3 + butterfly v\b4, v\b6, v\a4, v\a6 + butterfly v\b5, v\b7, v\a5, v\a7 + + interleave_pairs v\a0, v\a2, v\b0, v\b2 + interleave_pairs v\a1, v\a3, v\b1, v\b3 + interleave_pairs v\a4, v\a6, v\b4, v\b6 + interleave_pairs v\a5, v\a7, v\b5, v\b7 + + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 + + interleave_quads v\a0, v\a4, v\b0, v\b4 + interleave_quads v\a1, v\a5, v\b1, v\b5 + interleave_quads v\a2, v\a6, v\b2, v\b6 + interleave_quads v\a3, v\a7, v\b3, v\b7 +.endm + +.macro HADAMARD_8X8_V \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // Vertical transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\b0, v\b2 + butterfly v\a1, v\a3, v\b1, v\b3 + butterfly v\a4, v\a6, v\b4, v\b6 + butterfly v\a5, v\a7, v\b5, v\b7 + + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 +.endm + +.macro SUM_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // absolute value of transform coefficients + abs v\b0\().8h, v\b0\().8h + abs v\b1\().8h, v\b1\().8h + abs v\b2\().8h, v\b2\().8h + abs v\b3\().8h, v\b3\().8h + abs v\b4\().8h, v\b4\().8h + abs v\b5\().8h, v\b5\().8h + abs v\b6\().8h, v\b6\().8h + abs v\b7\().8h, v\b7\().8h + + // stage 1 sum + sxtl v\a0\().4s, v\b0\().4h + sxtl v\a1\().4s, v\b1\().4h + sxtl v\a2\().4s, v\b2\().4h + sxtl v\a3\().4s, v\b3\().4h + saddw2 v\a0\().4s, v\a0\().4s, v\b0\().8h + saddw2 v\a1\().4s, v\a1\().4s, v\b1\().8h + saddw2 v\a2\().4s, v\a2\().4s, v\b2\().8h + saddw2 v\a3\().4s, v\a3\().4s, v\b3\().8h + saddw v\a0\().4s, v\a0\().4s, v\b4\().4h + saddw2 v\a1\().4s, v\a1\().4s, v\b4\().8h + saddw v\a2\().4s, v\a2\().4s, v\b5\().4h + saddw2 v\a3\().4s, v\a3\().4s, v\b5\().8h + saddw v\a0\().4s, v\a0\().4s, v\b6\().4h + saddw2 v\a1\().4s, v\a1\().4s, v\b6\().8h + saddw v\a2\().4s, v\a2\().4s, v\b7\().4h + saddw2 v\a3\().4s, v\a3\().4s, v\b7\().8h + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + + // stage 3 sum + add v0.4s, v\a0\().4s, v\a2\().4s + addv s0, v0.4s +.endm + +.macro SATD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + HADAMARD_8X8_H \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + HADAMARD_8X8_V \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + SUM_HADAMARD_8X8 \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 +.endm + + +function satd8x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define height w13 + + mov height, 8 + mov total, wzr + + // 0, 1; 2, 3 + // 4, 5; 6, 7 + // 16, 17; 20, 21 + // 18, 19; 22, 23 + +L(satd_w8): + load_rows 0, 1, 2, src, dst, src_stride, dst_stride + load_rows 4, 5, 6, src, dst, src_stride, dst_stride + load_rows 16, 17, 20, src, dst, src_stride, dst_stride + load_rows 18, 19, 22, src, dst, src_stride, dst_stride + + SATD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23 + + fmov subtotal, s0 + add total, subtotal, total + + subs height, height, #8 + bne L(satd_w8) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef height +endfunc + +.macro DOUBLE_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // Horizontal transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + butterfly v\a0, v\a1, v\c0, v\c1 + butterfly v\a2, v\a3, v\c2, v\c3 + butterfly v\a4, v\a5, v\c4, v\c5 + butterfly v\a6, v\a7, v\c6, v\c7 + + interleave v\c0, v\c1, v\b0, v\b1 + interleave v\c2, v\c3, v\b2, v\b3 + interleave v\c4, v\c5, v\b4, v\b5 + interleave v\c6, v\c7, v\b6, v\b7 + interleave v\b0, v\b1, v\a0, v\a1 + interleave v\b2, v\b3, v\a2, v\a3 + interleave v\b4, v\b5, v\a4, v\a5 + interleave v\b6, v\b7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\c0, v\c2 + butterfly v\a1, v\a3, v\c1, v\c3 + butterfly v\a4, v\a6, v\c4, v\c6 + butterfly v\a5, v\a7, v\c5, v\c7 + butterfly v\c0, v\c2, v\b0, v\b2 + butterfly v\c1, v\c3, v\b1, v\b3 + butterfly v\c4, v\c6, v\b4, v\b6 + butterfly v\c5, v\c7, v\b5, v\b7 + + interleave_pairs v\b0, v\b2, v\a0, v\a2 + interleave_pairs v\b1, v\b3, v\a1, v\a3 + interleave_pairs v\b4, v\b6, v\a4, v\a6 + interleave_pairs v\b5, v\b7, v\a5, v\a7 + interleave_pairs v\a0, v\a2, v\c0, v\c2 + interleave_pairs v\a1, v\a3, v\c1, v\c3 + interleave_pairs v\a4, v\a6, v\c4, v\c6 + interleave_pairs v\a5, v\a7, v\c5, v\c7 + + butterfly v\c0, v\c4, v\b0, v\b4 + butterfly v\c1, v\c5, v\b1, v\b5 + butterfly v\c2, v\c6, v\b2, v\b6 + butterfly v\c3, v\c7, v\b3, v\b7 + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 + + interleave_quads v\a0, v\a4, v\c0, v\c4 + interleave_quads v\a1, v\a5, v\c1, v\c5 + interleave_quads v\a2, v\a6, v\c2, v\c6 + interleave_quads v\a3, v\a7, v\c3, v\c7 + interleave_quads v\c0, v\c4, v\b0, v\b4 + interleave_quads v\c1, v\c5, v\b1, v\b5 + interleave_quads v\c2, v\c6, v\b2, v\b6 + interleave_quads v\c3, v\c7, v\b3, v\b7 + + // Vertical transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + butterfly v\a0, v\a1, v\c0, v\c1 + butterfly v\a2, v\a3, v\c2, v\c3 + butterfly v\a4, v\a5, v\c4, v\c5 + butterfly v\a6, v\a7, v\c6, v\c7 + + butterfly v\c0, v\c2, v\b0, v\b2 + butterfly v\c1, v\c3, v\b1, v\b3 + butterfly v\c4, v\c6, v\b4, v\b6 + butterfly v\c5, v\c7, v\b5, v\b7 + butterfly v\b0, v\b2, v\a0, v\a2 + butterfly v\b1, v\b3, v\a1, v\a3 + butterfly v\b4, v\b6, v\a4, v\a6 + butterfly v\b5, v\b7, v\a5, v\a7 + + butterfly v\a0, v\a4, v\c0, v\c4 + butterfly v\a1, v\a5, v\c1, v\c5 + butterfly v\a2, v\a6, v\c2, v\c6 + butterfly v\a3, v\a7, v\c3, v\c7 + butterfly v\c0, v\c4, v\b0, v\b4 + butterfly v\c1, v\c5, v\b1, v\b5 + butterfly v\c2, v\c6, v\b2, v\b6 + butterfly v\c3, v\c7, v\b3, v\b7 +.endm + +.macro SUM_DOUBLE_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // absolute value of transform coefficients + abs v\a0\().8h, v\a0\().8h + abs v\a1\().8h, v\a1\().8h + abs v\a2\().8h, v\a2\().8h + abs v\a3\().8h, v\a3\().8h + abs v\a4\().8h, v\a4\().8h + abs v\a5\().8h, v\a5\().8h + abs v\a6\().8h, v\a6\().8h + abs v\a7\().8h, v\a7\().8h + abs v\c0\().8h, v\c0\().8h + abs v\c1\().8h, v\c1\().8h + abs v\c2\().8h, v\c2\().8h + abs v\c3\().8h, v\c3\().8h + abs v\c4\().8h, v\c4\().8h + abs v\c5\().8h, v\c5\().8h + abs v\c6\().8h, v\c6\().8h + abs v\c7\().8h, v\c7\().8h + + // stage 1 sum + sxtl v\b0\().4s, v\a0\().4h + sxtl v\b1\().4s, v\a1\().4h + sxtl v\b2\().4s, v\a2\().4h + sxtl v\b3\().4s, v\a3\().4h + sxtl v\b4\().4s, v\a4\().4h + sxtl v\b5\().4s, v\a5\().4h + sxtl v\b6\().4s, v\a6\().4h + sxtl v\b7\().4s, v\a7\().4h + saddw2 v\b0\().4s, v\b0\().4s, v\a0\().8h + saddw2 v\b1\().4s, v\b1\().4s, v\a1\().8h + saddw2 v\b2\().4s, v\b2\().4s, v\a2\().8h + saddw2 v\b3\().4s, v\b3\().4s, v\a3\().8h + saddw2 v\b4\().4s, v\b4\().4s, v\a4\().8h + saddw2 v\b5\().4s, v\b5\().4s, v\a5\().8h + saddw2 v\b6\().4s, v\b6\().4s, v\a6\().8h + saddw2 v\b7\().4s, v\b7\().4s, v\a7\().8h + saddw v\b0\().4s, v\b0\().4s, v\c0\().4h + saddw2 v\b1\().4s, v\b1\().4s, v\c0\().8h + saddw v\b2\().4s, v\b2\().4s, v\c1\().4h + saddw2 v\b3\().4s, v\b3\().4s, v\c1\().8h + saddw v\b4\().4s, v\b4\().4s, v\c2\().4h + saddw2 v\b5\().4s, v\b5\().4s, v\c2\().8h + saddw v\b6\().4s, v\b6\().4s, v\c3\().4h + saddw2 v\b7\().4s, v\b7\().4s, v\c3\().8h + saddw v\b0\().4s, v\b0\().4s, v\c4\().4h + saddw2 v\b1\().4s, v\b1\().4s, v\c4\().8h + saddw v\b2\().4s, v\b2\().4s, v\c5\().4h + saddw2 v\b3\().4s, v\b3\().4s, v\c5\().8h + saddw v\b4\().4s, v\b4\().4s, v\c6\().4h + saddw2 v\b5\().4s, v\b5\().4s, v\c6\().8h + saddw v\b6\().4s, v\b6\().4s, v\c7\().4h + saddw2 v\b7\().4s, v\b7\().4s, v\c7\().8h + + // stage 2 sum + add v\b0\().4s, v\b0\().4s, v\b1\().4s + add v\b2\().4s, v\b2\().4s, v\b3\().4s + add v\b4\().4s, v\b4\().4s, v\b5\().4s + add v\b6\().4s, v\b6\().4s, v\b7\().4s + + // stage 3 sum + add v\b0\().4s, v\b0\().4s, v\b2\().4s + add v\b4\().4s, v\b4\().4s, v\b6\().4s + + // stage 4 sum + add v0.4s, v\b0\().4s, v\b4\().4s + addv s0, v0.4s +.endm + +function satd16x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define w_ext x11 + #define w_bak w11 + #define width w12 + #define height w13 + + mov height, 8 + mov width, 16 + sxtw w_ext, width + mov total, wzr + + // 0, 1; 2, 3; 24, 25 + // 4, 5; 6, 7; 26, 27 + // 16, 17; 20, 21; 28, 29 + // 18, 19; 22, 23; 30, 31 + +L(satd_w16up): + load_rows 0, 1, 2, src, dst, src_stride, dst_stride, 24, 25 + load_rows 4, 5, 6, src, dst, src_stride, dst_stride, 26, 27 + load_rows 16, 17, 20, src, dst, src_stride, dst_stride, 28, 29 + load_rows 18, 19, 22, src, dst, src_stride, dst_stride, 30, 31 + + DOUBLE_HADAMARD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + SUM_DOUBLE_HADAMARD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + fmov subtotal, s0 + add total, subtotal, total + + sub src, src, src_stride, lsl 3 + sub dst, dst, dst_stride, lsl 3 + add src, src, #16 + add dst, dst, #16 + subs width, width, #16 + bne L(satd_w16up) + + sub src, src, w_ext + sub dst, dst, w_ext + add src, src, src_stride, lsl 3 + add dst, dst, dst_stride, lsl 3 + subs height, height, #8 + mov width, w_bak + bne L(satd_w16up) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef w_ext + #undef w_bak + #undef subtotal + #undef total + #undef height + #undef width +endfunc + +.macro satd_x8up width, height +function satd\width\()x\height\()_neon, export=1 + mov w13, \height +.if \width == 8 + mov w10, wzr + b L(satd_w8) +.else + mov w12, \width + sxtw x11, w12 + mov w10, wzr + b L(satd_w16up) +.endif +endfunc +.endm + +satd_x8up 8, 16 +satd_x8up 8, 32 +satd_x8up 16, 16 +satd_x8up 16, 32 +satd_x8up 16, 64 +satd_x8up 32, 8 +satd_x8up 32, 16 +satd_x8up 32, 32 +satd_x8up 32, 64 +satd_x8up 64, 16 +satd_x8up 64, 32 +satd_x8up 64, 64 +satd_x8up 64, 128 +satd_x8up 128, 64 +satd_x8up 128, 128 + +.macro load_rows_hbd n0, n1, n2, src, dst, src_stride, dst_stride + ldr q\n0, [\src] + ldr q\n1, [\dst] + sub v\n0\().8h, v\n0\().8h, v\n1\().8h + + ldr q\n1, [\src, \src_stride] + ldr q\n2, [\dst, \dst_stride] + sub v\n1\().8h, v\n1\().8h, v\n2\().8h + + add \src, \src, \src_stride, lsl 1 + add \dst, \dst, \dst_stride, lsl 1 +.endm + +.macro HADAMARD_8X8_V_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // Vertical transform + + butterflyw v\b0, v\b1, v\c0, v\c1, v\a0, v\a1 + butterflyw v\b2, v\b3, v\c2, v\c3, v\a2, v\a3 + butterflyw v\b4, v\b5, v\c4, v\c5, v\a4, v\a5 + butterflyw v\b6, v\b7, v\c6, v\c7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\b0, v\b2, 4s + butterfly v\a1, v\a3, v\b1, v\b3, 4s + butterfly v\a4, v\a6, v\b4, v\b6, 4s + butterfly v\a5, v\a7, v\b5, v\b7, 4s + butterfly v\b0, v\b2, v\c0, v\c2, 4s + butterfly v\b1, v\b3, v\c1, v\c3, 4s + butterfly v\b4, v\b6, v\c4, v\c6, 4s + butterfly v\b5, v\b7, v\c5, v\c7, 4s + + butterfly v\c0, v\c4, v\a0, v\a4, 4s + butterfly v\c1, v\c5, v\a1, v\a5, 4s + butterfly v\c2, v\c6, v\a2, v\a6, 4s + butterfly v\c3, v\c7, v\a3, v\a7, 4s + butterfly v\a0, v\a4, v\b0, v\b4, 4s + butterfly v\a1, v\a5, v\b1, v\b5, 4s + butterfly v\a2, v\a6, v\b2, v\b6, 4s + butterfly v\a3, v\a7, v\b3, v\b7, 4s +.endm + +.macro SUM_HADAMARD_8X8_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // absolute value of transform coefficients + abs v\a0\().4s, v\a0\().4s + abs v\a1\().4s, v\a1\().4s + abs v\a2\().4s, v\a2\().4s + abs v\a3\().4s, v\a3\().4s + abs v\a4\().4s, v\a4\().4s + abs v\a5\().4s, v\a5\().4s + abs v\a6\().4s, v\a6\().4s + abs v\a7\().4s, v\a7\().4s + abs v\c0\().4s, v\c0\().4s + abs v\c1\().4s, v\c1\().4s + abs v\c2\().4s, v\c2\().4s + abs v\c3\().4s, v\c3\().4s + abs v\c4\().4s, v\c4\().4s + abs v\c5\().4s, v\c5\().4s + abs v\c6\().4s, v\c6\().4s + abs v\c7\().4s, v\c7\().4s + + // stage 1 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + add v\a4\().4s, v\a4\().4s, v\a5\().4s + add v\a6\().4s, v\a6\().4s, v\a7\().4s + add v\c0\().4s, v\c0\().4s, v\c1\().4s + add v\c2\().4s, v\c2\().4s, v\c3\().4s + add v\c4\().4s, v\c4\().4s, v\c5\().4s + add v\c6\().4s, v\c6\().4s, v\c7\().4s + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a2\().4s + add v\a4\().4s, v\a4\().4s, v\a6\().4s + add v\c0\().4s, v\c0\().4s, v\c2\().4s + add v\c4\().4s, v\c4\().4s, v\c6\().4s + + // stage 3 sum + add v\a0\().4s, v\a0\().4s, v\a4\().4s + add v\c0\().4s, v\c0\().4s, v\c4\().4s + + // stage 4 sum + add v0.4s, v\a0\().4s, v\c0\().4s + addv s0, v0.4s +.endm + + +.macro SATD_8X8_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + HADAMARD_8X8_H \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + HADAMARD_8X8_V_HBD \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7, \ + \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 + + SUM_HADAMARD_8X8_HBD \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 +.endm + +function satd8x8_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define w_ext x11 + #define w_bak w11 + #define width w12 + #define height w13 + + mov height, 8 + mov width, 8 + sxtw w_ext, width + mov total, wzr + + // 0, 1; 2, 3; 24, 25 + // 4, 5; 6, 7; 26, 27 + // 16, 17; 20, 21; 28, 29 + // 18, 19; 22, 23; 30, 31 + +L(satd_w8up_hbd): + load_rows_hbd 0, 1, 2, src, dst, src_stride, dst_stride + load_rows_hbd 4, 5, 6, src, dst, src_stride, dst_stride + load_rows_hbd 16, 17, 20, src, dst, src_stride, dst_stride + load_rows_hbd 18, 19, 22, src, dst, src_stride, dst_stride + + SATD_8X8_HBD \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + fmov subtotal, s0 + add total, subtotal, total + + sub src, src, src_stride, lsl 3 + sub dst, dst, dst_stride, lsl 3 + add src, src, #16 + add dst, dst, #16 + subs width, width, #8 + bne L(satd_w8up_hbd) + + sub src, src, w_ext, lsl 1 + sub dst, dst, w_ext, lsl 1 + add src, src, src_stride, lsl 3 + add dst, dst, dst_stride, lsl 3 + subs height, height, #8 + mov width, w_bak + bne L(satd_w8up_hbd) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef w_ext + #undef w_bak + #undef subtotal + #undef total + #undef height + #undef width +endfunc + +.macro satd_x8up_hbd width, height +function satd\width\()x\height\()_hbd_neon, export=1 + mov w13, \height + mov w12, \width + sxtw x11, w12 + mov w10, wzr + b L(satd_w8up_hbd) +endfunc +.endm + +satd_x8up_hbd 8, 16 +satd_x8up_hbd 8, 32 +satd_x8up_hbd 16, 8 +satd_x8up_hbd 16, 16 +satd_x8up_hbd 16, 32 +satd_x8up_hbd 16, 64 +satd_x8up_hbd 32, 8 +satd_x8up_hbd 32, 16 +satd_x8up_hbd 32, 32 +satd_x8up_hbd 32, 64 +satd_x8up_hbd 64, 16 +satd_x8up_hbd 64, 32 +satd_x8up_hbd 64, 64 +satd_x8up_hbd 64, 128 +satd_x8up_hbd 128, 64 +satd_x8up_hbd 128, 128 + +// x0: src: *const u16, +// x1: src_stride: isize, +// x2: dst: *const u16, +// x3: dst_stride: isize, +function satd4x4_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define height w13 + + mov height, 4 + mov total, wzr + +L(satd_w4_hbd): + ldr d0, [src] + ldr d1, [dst] + sub v0.8h, v0.8h, v1.8h + + ldr d1, [src, src_stride] + ldr d2, [dst, dst_stride] + sub v1.8h, v1.8h, v2.8h + + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + ldr d2, [src] + ldr d3, [dst] + sub v2.8h, v2.8h, v3.8h + + ldr d3, [src, src_stride] + ldr d4, [dst, src_stride] + sub v3.8h, v3.8h, v4.8h + + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + // pack rows 0-2, 1-3 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // Horizontal transform + butterfly v2, v3, v0, v1 + interleave v0, v1, v2, v3 + butterfly v2, v3, v0, v1 + interleave_pairs v0, v1, v2, v3 + // Vertical transform + + butterfly v2, v3, v0, v1 + interleave v0, v1, v2, v3 + butterflyw v2, v3, v4, v5, v0, v1 + + // absolute value of transform coefficients + abs v2.4s, v2.4s + abs v3.4s, v3.4s + abs v4.4s, v4.4s + abs v5.4s, v5.4s + + // stage 1 sum + add v2.4s, v2.4s, v3.4s + add v4.4s, v4.4s, v5.4s + + // stage 2 sum + add v0.4s, v2.4s, v4.4s + addv s0, v0.4s + + fmov subtotal, s0 + add total, subtotal, total + + subs height, height, #4 + bne L(satd_w4_hbd) + + mov w0, total + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef height +endfunc + +function satd4x8_hbd_neon, export=1 + mov w13, 8 + mov w10, wzr + b L(satd_w4_hbd) +endfunc + +function satd4x16_hbd_neon, export=1 + mov w13, 16 + mov w10, wzr + b L(satd_w4_hbd) +endfunc + +.macro SUM_DOUBLE_HADAMARD_4X4_HBD \ + a0 a1 a2 a3 c0 c1 c2 c3 + + // absolute value of transform coefficients + abs v\a0\().4s, v\a0\().4s + abs v\a1\().4s, v\a1\().4s + abs v\a2\().4s, v\a2\().4s + abs v\a3\().4s, v\a3\().4s + abs v\c0\().4s, v\c0\().4s + abs v\c1\().4s, v\c1\().4s + abs v\c2\().4s, v\c2\().4s + abs v\c3\().4s, v\c3\().4s + + // stage 1 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + add v\c0\().4s, v\c0\().4s, v\c1\().4s + add v\c2\().4s, v\c2\().4s, v\c3\().4s + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a2\().4s + add v\c0\().4s, v\c0\().4s, v\c2\().4s + + // stage 3 sum + add v0.4s, v\a0\().4s, v\c0\().4s + addv s0, v0.4s +.endm + +function satd8x4_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define width w12 + + mov width, 8 + mov total, wzr + +L(satd_h4_hbd): + ldr q0, [src] + ldr q1, [dst] + sub v0.8h, v0.8h, v1.8h + + ldr q1, [src, src_stride] + ldr q2, [dst, dst_stride] + sub v1.8h, v1.8h, v2.8h + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr q2, [src, x8] + ldr q3, [dst, x9] + sub v2.8h, v2.8h, v3.8h + + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr q3, [src, x8] + ldr q4, [dst, x9] + sub v3.8h, v3.8h, v4.8h + + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + + DOUBLE_HADAMARD_4X4 hbd=1 + SUM_DOUBLE_HADAMARD_4X4_HBD 2, 3, 16, 17, 6, 7, 18, 19 + + fmov subtotal, s0 + add total, subtotal, total + + add src, src, #16 + add dst, dst, #16 + subs width, width, #8 + bne L(satd_h4_hbd) + + mov w0, total + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef width +endfunc + +function satd16x4_hbd_neon, export=1 + mov w12, 16 + mov w10, wzr + b L(satd_h4_hbd) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/util.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/util.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/util.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/64/util.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2015 Martin Storsjo + * Copyright © 2015 Janne Grunau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef DAV1D_SRC_ARM_64_UTIL_S +#define DAV1D_SRC_ARM_64_UTIL_S + +#include "config.h" +#include "src/asm/arm/asm.S" + +.macro movrel rd, val, offset=0 +#if defined(__APPLE__) + .if \offset < 0 + adrp \rd, \val@PAGE + add \rd, \rd, \val@PAGEOFF + sub \rd, \rd, -(\offset) + .else + adrp \rd, \val+(\offset)@PAGE + add \rd, \rd, \val+(\offset)@PAGEOFF + .endif +#elif defined(PIC) && defined(_WIN32) + .if \offset < 0 + adrp \rd, \val + add \rd, \rd, :lo12:\val + sub \rd, \rd, -(\offset) + .else + adrp \rd, \val+(\offset) + add \rd, \rd, :lo12:\val+(\offset) + .endif +#elif defined(PIC) + adrp \rd, \val+(\offset) + add \rd, \rd, :lo12:\val+(\offset) +#else + ldr \rd, =\val+\offset +#endif +.endm + +.macro sub_sp space +#ifdef _WIN32 +.if \space > 8192 + // Here, we'd need to touch two (or more) pages while decrementing + // the stack pointer. + .error "sub_sp_align doesn't support values over 8K at the moment" +.elseif \space > 4096 + sub x16, sp, #4096 + ldr xzr, [x16] + sub sp, x16, #(\space - 4096) +.else + sub sp, sp, #\space +.endif +#else +.if \space >= 4096 + sub sp, sp, #(\space)/4096*4096 +.endif +.if (\space % 4096) != 0 + sub sp, sp, #(\space)%4096 +.endif +#endif +.endm + +.macro transpose_8x8b_xtl r0, r1, r2, r3, r4, r5, r6, r7, xtl + // a0 b0 a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 a6 b6 a7 b7 + zip1 \r0\().16b, \r0\().16b, \r1\().16b + // c0 d0 c1 d1 c2 d2 d3 d3 c4 d4 c5 d5 c6 d6 d7 d7 + zip1 \r2\().16b, \r2\().16b, \r3\().16b + // e0 f0 e1 f1 e2 f2 e3 f3 e4 f4 e5 f5 e6 f6 e7 f7 + zip1 \r4\().16b, \r4\().16b, \r5\().16b + // g0 h0 g1 h1 g2 h2 h3 h3 g4 h4 g5 h5 g6 h6 h7 h7 + zip1 \r6\().16b, \r6\().16b, \r7\().16b + + // a0 b0 c0 d0 a2 b2 c2 d2 a4 b4 c4 d4 a6 b6 c6 d6 + trn1 \r1\().8h, \r0\().8h, \r2\().8h + // a1 b1 c1 d1 a3 b3 c3 d3 a5 b5 c5 d5 a7 b7 c7 d7 + trn2 \r3\().8h, \r0\().8h, \r2\().8h + // e0 f0 g0 h0 e2 f2 g2 h2 e4 f4 g4 h4 e6 f6 g6 h6 + trn1 \r5\().8h, \r4\().8h, \r6\().8h + // e1 f1 g1 h1 e3 f3 g3 h3 e5 f5 g5 h5 e7 f7 g7 h7 + trn2 \r7\().8h, \r4\().8h, \r6\().8h + + // a0 b0 c0 d0 e0 f0 g0 h0 a4 b4 c4 d4 e4 f4 g4 h4 + trn1 \r0\().4s, \r1\().4s, \r5\().4s + // a2 b2 c2 d2 e2 f2 g2 h2 a6 b6 c6 d6 e6 f6 g6 h6 + trn2 \r2\().4s, \r1\().4s, \r5\().4s + // a1 b1 c1 d1 e1 f1 g1 h1 a5 b5 c5 d5 e5 f5 g5 h5 + trn1 \r1\().4s, \r3\().4s, \r7\().4s + // a3 b3 c3 d3 e3 f3 g3 h3 a7 b7 c7 d7 e7 f7 g7 h7 + trn2 \r3\().4s, \r3\().4s, \r7\().4s + + \xtl\()2 \r4\().8h, \r0\().16b + \xtl \r0\().8h, \r0\().8b + \xtl\()2 \r6\().8h, \r2\().16b + \xtl \r2\().8h, \r2\().8b + \xtl\()2 \r5\().8h, \r1\().16b + \xtl \r1\().8h, \r1\().8b + \xtl\()2 \r7\().8h, \r3\().16b + \xtl \r3\().8h, \r3\().8b +.endm + +.macro transpose_8x8h r0, r1, r2, r3, r4, r5, r6, r7, t8, t9 + trn1 \t8\().8h, \r0\().8h, \r1\().8h + trn2 \t9\().8h, \r0\().8h, \r1\().8h + trn1 \r1\().8h, \r2\().8h, \r3\().8h + trn2 \r3\().8h, \r2\().8h, \r3\().8h + trn1 \r0\().8h, \r4\().8h, \r5\().8h + trn2 \r5\().8h, \r4\().8h, \r5\().8h + trn1 \r2\().8h, \r6\().8h, \r7\().8h + trn2 \r7\().8h, \r6\().8h, \r7\().8h + + trn1 \r4\().4s, \r0\().4s, \r2\().4s + trn2 \r2\().4s, \r0\().4s, \r2\().4s + trn1 \r6\().4s, \r5\().4s, \r7\().4s + trn2 \r7\().4s, \r5\().4s, \r7\().4s + trn1 \r5\().4s, \t9\().4s, \r3\().4s + trn2 \t9\().4s, \t9\().4s, \r3\().4s + trn1 \r3\().4s, \t8\().4s, \r1\().4s + trn2 \t8\().4s, \t8\().4s, \r1\().4s + + trn1 \r0\().2d, \r3\().2d, \r4\().2d + trn2 \r4\().2d, \r3\().2d, \r4\().2d + trn1 \r1\().2d, \r5\().2d, \r6\().2d + trn2 \r5\().2d, \r5\().2d, \r6\().2d + trn2 \r6\().2d, \t8\().2d, \r2\().2d + trn1 \r2\().2d, \t8\().2d, \r2\().2d + trn1 \r3\().2d, \t9\().2d, \r7\().2d + trn2 \r7\().2d, \t9\().2d, \r7\().2d +.endm + +.macro transpose_8x16b r0, r1, r2, r3, r4, r5, r6, r7, t8, t9 + trn1 \t8\().16b, \r0\().16b, \r1\().16b + trn2 \t9\().16b, \r0\().16b, \r1\().16b + trn1 \r1\().16b, \r2\().16b, \r3\().16b + trn2 \r3\().16b, \r2\().16b, \r3\().16b + trn1 \r0\().16b, \r4\().16b, \r5\().16b + trn2 \r5\().16b, \r4\().16b, \r5\().16b + trn1 \r2\().16b, \r6\().16b, \r7\().16b + trn2 \r7\().16b, \r6\().16b, \r7\().16b + + trn1 \r4\().8h, \r0\().8h, \r2\().8h + trn2 \r2\().8h, \r0\().8h, \r2\().8h + trn1 \r6\().8h, \r5\().8h, \r7\().8h + trn2 \r7\().8h, \r5\().8h, \r7\().8h + trn1 \r5\().8h, \t9\().8h, \r3\().8h + trn2 \t9\().8h, \t9\().8h, \r3\().8h + trn1 \r3\().8h, \t8\().8h, \r1\().8h + trn2 \t8\().8h, \t8\().8h, \r1\().8h + + trn1 \r0\().4s, \r3\().4s, \r4\().4s + trn2 \r4\().4s, \r3\().4s, \r4\().4s + trn1 \r1\().4s, \r5\().4s, \r6\().4s + trn2 \r5\().4s, \r5\().4s, \r6\().4s + trn2 \r6\().4s, \t8\().4s, \r2\().4s + trn1 \r2\().4s, \t8\().4s, \r2\().4s + trn1 \r3\().4s, \t9\().4s, \r7\().4s + trn2 \r7\().4s, \t9\().4s, \r7\().4s +.endm + +.macro transpose_4x16b r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().16b, \r0\().16b, \r1\().16b + trn2 \t5\().16b, \r0\().16b, \r1\().16b + trn1 \t6\().16b, \r2\().16b, \r3\().16b + trn2 \t7\().16b, \r2\().16b, \r3\().16b + + trn1 \r0\().8h, \t4\().8h, \t6\().8h + trn2 \r2\().8h, \t4\().8h, \t6\().8h + trn1 \r1\().8h, \t5\().8h, \t7\().8h + trn2 \r3\().8h, \t5\().8h, \t7\().8h +.endm + +.macro transpose_4x4h r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().4h, \r0\().4h, \r1\().4h + trn2 \t5\().4h, \r0\().4h, \r1\().4h + trn1 \t6\().4h, \r2\().4h, \r3\().4h + trn2 \t7\().4h, \r2\().4h, \r3\().4h + + trn1 \r0\().2s, \t4\().2s, \t6\().2s + trn2 \r2\().2s, \t4\().2s, \t6\().2s + trn1 \r1\().2s, \t5\().2s, \t7\().2s + trn2 \r3\().2s, \t5\().2s, \t7\().2s +.endm + +.macro transpose_4x4s r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().4s, \r0\().4s, \r1\().4s + trn2 \t5\().4s, \r0\().4s, \r1\().4s + trn1 \t6\().4s, \r2\().4s, \r3\().4s + trn2 \t7\().4s, \r2\().4s, \r3\().4s + + trn1 \r0\().2d, \t4\().2d, \t6\().2d + trn2 \r2\().2d, \t4\().2d, \t6\().2d + trn1 \r1\().2d, \t5\().2d, \t7\().2d + trn2 \r3\().2d, \t5\().2d, \t7\().2d +.endm + +.macro transpose_4x8h r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().8h, \r0\().8h, \r1\().8h + trn2 \t5\().8h, \r0\().8h, \r1\().8h + trn1 \t6\().8h, \r2\().8h, \r3\().8h + trn2 \t7\().8h, \r2\().8h, \r3\().8h + + trn1 \r0\().4s, \t4\().4s, \t6\().4s + trn2 \r2\().4s, \t4\().4s, \t6\().4s + trn1 \r1\().4s, \t5\().4s, \t7\().4s + trn2 \r3\().4s, \t5\().4s, \t7\().4s +.endm + +#endif /* DAV1D_SRC_ARM_64_UTIL_S */ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/asm.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/asm.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/asm.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/asm.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,291 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV1D_SRC_ARM_ASM_S +#define DAV1D_SRC_ARM_ASM_S + +#include "config.h" + +#if ARCH_AARCH64 +#define x18 do_not_use_x18 +#define w18 do_not_use_w18 + +/* Support macros for + * - Armv8.3-A Pointer Authentication and + * - Armv8.5-A Branch Target Identification + * features which require emitting a .note.gnu.property section with the + * appropriate architecture-dependent feature bits set. + * + * |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to + * PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be + * used immediately before saving the LR register (x30) to the stack. + * |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring + * it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone + * with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also + * have the same value at the two points. For example: + * + * .global f + * f: + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or + * |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an + * indirect call target. In particular, all symbols exported from a file must + * begin with one of these macros. For example, a leaf function that does not + * save LR can instead use |AARCH64_VALID_CALL_TARGET|: + * + * .globl return_zero + * return_zero: + * AARCH64_VALID_CALL_TARGET + * mov x0, #0 + * ret + * + * A non-leaf function which does not immediately save LR may need both macros + * because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function + * may jump to an alternate implementation before setting up the stack: + * + * .globl with_early_jump + * with_early_jump: + * AARCH64_VALID_CALL_TARGET + * cmp x0, #128 + * b.lt .Lwith_early_jump_128 + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * .Lwith_early_jump_128: + * ... + * ret + * + * These annotations are only required with indirect calls. Private symbols that + * are only the target of direct calls do not require annotations. Also note + * that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not + * indirect jumps (BR). Indirect jumps in assembly are supported through + * |AARCH64_VALID_JUMP_TARGET|. Landing Pads which shall serve for jumps and + * calls can be created using |AARCH64_VALID_JUMP_CALL_TARGET|. + * + * Although not necessary, it is safe to use these macros in 32-bit ARM + * assembly. This may be used to simplify dual 32-bit and 64-bit files. + * + * References: + * - "ELF for the Arm® 64-bit Architecture" + * https: *github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst + * - "Providing protection for complex software" + * https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) +#define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has Branch Target Identification +#define AARCH64_VALID_JUMP_CALL_TARGET hint #38 // BTI 'jc' +#define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' +#define AARCH64_VALID_JUMP_TARGET hint #36 // BTI 'j' +#else +#define GNU_PROPERTY_AARCH64_BTI 0 // No Branch Target Identification +#define AARCH64_VALID_JUMP_CALL_TARGET +#define AARCH64_VALID_CALL_TARGET +#define AARCH64_VALID_JUMP_TARGET +#endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) + +#if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 0)) != 0) // authentication using key A +#define AARCH64_SIGN_LINK_REGISTER paciasp +#define AARCH64_VALIDATE_LINK_REGISTER autiasp +#elif ((__ARM_FEATURE_PAC_DEFAULT & (1 << 1)) != 0) // authentication using key B +#define AARCH64_SIGN_LINK_REGISTER pacibsp +#define AARCH64_VALIDATE_LINK_REGISTER autibsp +#else +#error Pointer authentication defines no valid key! +#endif +#if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 2)) != 0) // authentication of leaf functions +#error Authentication of leaf functions is enabled but not supported in dav1d! +#endif +#define GNU_PROPERTY_AARCH64_PAC (1 << 1) + +#elif defined(__APPLE__) && defined(__arm64e__) + +#define GNU_PROPERTY_AARCH64_PAC 0 +#define AARCH64_SIGN_LINK_REGISTER pacibsp +#define AARCH64_VALIDATE_LINK_REGISTER autibsp + +#else /* __ARM_FEATURE_PAC_DEFAULT */ + +#define GNU_PROPERTY_AARCH64_PAC 0 +#define AARCH64_SIGN_LINK_REGISTER +#define AARCH64_VALIDATE_LINK_REGISTER + +#endif /* !__ARM_FEATURE_PAC_DEFAULT */ + + +#if (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) + .pushsection .note.gnu.property, "a" + .balign 8 + .long 4 + .long 0x10 + .long 0x5 + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4 + .long (GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_PAC) + .long 0 + .popsection +#endif /* (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) */ +#endif /* ARCH_AARCH64 */ + +#if ARCH_ARM + .syntax unified +#ifdef __ELF__ + .arch armv7-a + .fpu neon + .eabi_attribute 10, 0 // suppress Tag_FP_arch + .eabi_attribute 12, 0 // suppress Tag_Advanced_SIMD_arch + .section .note.GNU-stack,"",%progbits // Mark stack as non-executable +#endif /* __ELF__ */ + +#ifdef _WIN32 +#define CONFIG_THUMB 1 +#else +#define CONFIG_THUMB 0 +#endif + +#if CONFIG_THUMB + .thumb +#define A @ +#define T +#else +#define A +#define T @ +#endif /* CONFIG_THUMB */ +#endif /* ARCH_ARM */ + +#if !defined(PIC) +#if defined(__PIC__) +#define PIC __PIC__ +#elif defined(__pic__) +#define PIC __pic__ +#endif +#endif + +#ifndef PRIVATE_PREFIX +#define PRIVATE_PREFIX dav1d_ +#endif + +#define PASTE(a,b) a ## b +#define CONCAT(a,b) PASTE(a,b) + +#ifdef PREFIX +#define EXTERN CONCAT(_,PRIVATE_PREFIX) +#else +#define EXTERN PRIVATE_PREFIX +#endif + +.macro function name, export=0, align=2 + .macro endfunc +#ifdef __ELF__ + .size \name, . - \name +#endif +#if HAVE_AS_FUNC + .endfunc +#endif + .purgem endfunc + .endm + .text + .align \align + .if \export + .global EXTERN\name +#ifdef __ELF__ + .type EXTERN\name, %function + .hidden EXTERN\name +#elif defined(__MACH__) + .private_extern EXTERN\name +#endif +#if HAVE_AS_FUNC + .func EXTERN\name +#endif +EXTERN\name: + .else +#ifdef __ELF__ + .type \name, %function +#endif +#if HAVE_AS_FUNC + .func \name +#endif + .endif +\name: +#if ARCH_AARCH64 + .if \export + AARCH64_VALID_CALL_TARGET + .endif +#endif +.endm + +.macro const name, export=0, align=2 + .macro endconst +#ifdef __ELF__ + .size \name, . - \name +#endif + .purgem endconst + .endm +#if defined(_WIN32) + .section .rdata +#elif !defined(__MACH__) + .section .rodata +#else + .const_data +#endif + .align \align + .if \export + .global EXTERN\name +#ifdef __ELF__ + .hidden EXTERN\name +#elif defined(__MACH__) + .private_extern EXTERN\name +#endif +EXTERN\name: + .endif +\name: +.endm + +#ifdef __APPLE__ +#define L(x) L ## x +#else +#define L(x) .L ## x +#endif + +#define X(x) CONCAT(EXTERN, x) + + +#endif /* DAV1D_SRC_ARM_ASM_S */ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/tables.S clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/tables.S --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/tables.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/arm/tables.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2019-2022, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Two Orioles, LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/asm/arm/asm.S" + +const mc_subpel_filters, export=1, align=3 +.byte 0, 1, -3, 63, 4, -1, 0, 0 /* REGULAR */ +.byte 0, 1, -5, 61, 9, -2, 0, 0 +.byte 0, 1, -6, 58, 14, -4, 1, 0 +.byte 0, 1, -7, 55, 19, -5, 1, 0 +.byte 0, 1, -7, 51, 24, -6, 1, 0 +.byte 0, 1, -8, 47, 29, -6, 1, 0 +.byte 0, 1, -7, 42, 33, -6, 1, 0 +.byte 0, 1, -7, 38, 38, -7, 1, 0 +.byte 0, 1, -6, 33, 42, -7, 1, 0 +.byte 0, 1, -6, 29, 47, -8, 1, 0 +.byte 0, 1, -6, 24, 51, -7, 1, 0 +.byte 0, 1, -5, 19, 55, -7, 1, 0 +.byte 0, 1, -4, 14, 58, -6, 1, 0 +.byte 0, 0, -2, 9, 61, -5, 1, 0 +.byte 0, 0, -1, 4, 63, -3, 1, 0 +.byte 0, 1, 14, 31, 17, 1, 0, 0 /* SMOOTH */ +.byte 0, 0, 13, 31, 18, 2, 0, 0 +.byte 0, 0, 11, 31, 20, 2, 0, 0 +.byte 0, 0, 10, 30, 21, 3, 0, 0 +.byte 0, 0, 9, 29, 22, 4, 0, 0 +.byte 0, 0, 8, 28, 23, 5, 0, 0 +.byte 0, -1, 8, 27, 24, 6, 0, 0 +.byte 0, -1, 7, 26, 26, 7, -1, 0 +.byte 0, 0, 6, 24, 27, 8, -1, 0 +.byte 0, 0, 5, 23, 28, 8, 0, 0 +.byte 0, 0, 4, 22, 29, 9, 0, 0 +.byte 0, 0, 3, 21, 30, 10, 0, 0 +.byte 0, 0, 2, 20, 31, 11, 0, 0 +.byte 0, 0, 2, 18, 31, 13, 0, 0 +.byte 0, 0, 1, 17, 31, 14, 1, 0 +.byte -1, 1, -3, 63, 4, -1, 1, 0 /* SHARP */ +.byte -1, 3, -6, 62, 8, -3, 2, -1 +.byte -1, 4, -9, 60, 13, -5, 3, -1 +.byte -2, 5, -11, 58, 19, -7, 3, -1 +.byte -2, 5, -11, 54, 24, -9, 4, -1 +.byte -2, 5, -12, 50, 30, -10, 4, -1 +.byte -2, 5, -12, 45, 35, -11, 5, -1 +.byte -2, 6, -12, 40, 40, -12, 6, -2 +.byte -1, 5, -11, 35, 45, -12, 5, -2 +.byte -1, 4, -10, 30, 50, -12, 5, -2 +.byte -1, 4, -9, 24, 54, -11, 5, -2 +.byte -1, 3, -7, 19, 58, -11, 5, -2 +.byte -1, 3, -5, 13, 60, -9, 4, -1 +.byte -1, 2, -3, 8, 62, -6, 3, -1 +.byte 0, 1, -1, 4, 63, -3, 1, -1 +.byte 0, 0, -2, 63, 4, -1, 0, 0 /* REGULAR 4 */ +.byte 0, 0, -4, 61, 9, -2, 0, 0 +.byte 0, 0, -5, 58, 14, -3, 0, 0 +.byte 0, 0, -6, 55, 19, -4, 0, 0 +.byte 0, 0, -6, 51, 24, -5, 0, 0 +.byte 0, 0, -7, 47, 29, -5, 0, 0 +.byte 0, 0, -6, 42, 33, -5, 0, 0 +.byte 0, 0, -6, 38, 38, -6, 0, 0 +.byte 0, 0, -5, 33, 42, -6, 0, 0 +.byte 0, 0, -5, 29, 47, -7, 0, 0 +.byte 0, 0, -5, 24, 51, -6, 0, 0 +.byte 0, 0, -4, 19, 55, -6, 0, 0 +.byte 0, 0, -3, 14, 58, -5, 0, 0 +.byte 0, 0, -2, 9, 61, -4, 0, 0 +.byte 0, 0, -1, 4, 63, -2, 0, 0 +.byte 0, 0, 15, 31, 17, 1, 0, 0 /* SMOOTH 4 */ +.byte 0, 0, 13, 31, 18, 2, 0, 0 +.byte 0, 0, 11, 31, 20, 2, 0, 0 +.byte 0, 0, 10, 30, 21, 3, 0, 0 +.byte 0, 0, 9, 29, 22, 4, 0, 0 +.byte 0, 0, 8, 28, 23, 5, 0, 0 +.byte 0, 0, 7, 27, 24, 6, 0, 0 +.byte 0, 0, 6, 26, 26, 6, 0, 0 +.byte 0, 0, 6, 24, 27, 7, 0, 0 +.byte 0, 0, 5, 23, 28, 8, 0, 0 +.byte 0, 0, 4, 22, 29, 9, 0, 0 +.byte 0, 0, 3, 21, 30, 10, 0, 0 +.byte 0, 0, 2, 20, 31, 11, 0, 0 +.byte 0, 0, 2, 18, 31, 13, 0, 0 +.byte 0, 0, 1, 17, 31, 15, 0, 0 +/* Bilin scaled being very rarely used, add a new table entry + * and use the put/prep_8tap_scaled code, thus acting as a + * scaled bilinear filter. */ +.byte 0, 0, 0, 60, 4, 0, 0, 0 +.byte 0, 0, 0, 56, 8, 0, 0, 0 +.byte 0, 0, 0, 52, 12, 0, 0, 0 +.byte 0, 0, 0, 48, 16, 0, 0, 0 +.byte 0, 0, 0, 44, 20, 0, 0, 0 +.byte 0, 0, 0, 40, 24, 0, 0, 0 +.byte 0, 0, 0, 36, 28, 0, 0, 0 +.byte 0, 0, 0, 32, 32, 0, 0, 0 +.byte 0, 0, 0, 28, 36, 0, 0, 0 +.byte 0, 0, 0, 24, 40, 0, 0, 0 +.byte 0, 0, 0, 20, 44, 0, 0, 0 +.byte 0, 0, 0, 16, 48, 0, 0, 0 +.byte 0, 0, 0, 12, 52, 0, 0, 0 +.byte 0, 0, 0, 8, 56, 0, 0, 0 +.byte 0, 0, 0, 4, 60, 0, 0, 0 +endconst + +const filter_intra_taps, export=1, align=4 +.byte -6, 10, -5, 2, -3, 1, -3, 1 /* 0 */ +.byte -4, 6, -3, 2, -3, 2, -3, 1 +.byte 0, 0, 10, 0, 1, 10, 1, 2 +.byte 0, 0, 6, 0, 2, 6, 2, 2 +.byte 0, 12, 0, 9, 0, 7, 10, 5 +.byte 0, 2, 0, 2, 0, 2, 6, 3 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 12, 0, 9, 0, 7, 0, 5, 0 +.byte -10, 16, -6, 0, -4, 0, -2, 0 /* 1 */ +.byte -10, 16, -6, 0, -4, 0, -2, 0 +.byte 0, 0, 16, 0, 0, 16, 0, 0 +.byte 0, 0, 16, 0, 0, 16, 0, 0 +.byte 0, 10, 0, 6, 0, 4, 16, 2 +.byte 0, 0, 0, 0, 0, 0, 16, 0 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 10, 0, 6, 0, 4, 0, 2, 0 +.byte -8, 8, -8, 0, -8, 0, -8, 0 /* 2 */ +.byte -4, 4, -4, 0, -4, 0, -4, 0 +.byte 0, 0, 8, 0, 0, 8, 0, 0 +.byte 0, 0, 4, 0, 0, 4, 0, 0 +.byte 0, 16, 0, 16, 0, 16, 8, 16 +.byte 0, 0, 0, 0, 0, 0, 4, 0 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 16, 0, 16, 0, 16, 0, 16, 0 +.byte -2, 8, -1, 3, -1, 2, 0, 1 /* 3 */ +.byte -1, 4, -1, 3, -1, 2, -1, 2 +.byte 0, 0, 8, 0, 3, 8, 2, 3 +.byte 0, 0, 4, 0, 3, 4, 2, 3 +.byte 0, 10, 0, 6, 0, 4, 8, 2 +.byte 0, 3, 0, 4, 0, 4, 4, 3 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 10, 0, 6, 0, 4, 0, 3, 0 +.byte -12, 14, -10, 0, -9, 0, -8, 0 /* 4 */ +.byte -10, 12, -9, 1, -8, 0, -7, 0 +.byte 0, 0, 14, 0, 0, 14, 0, 0 +.byte 0, 0, 12, 0, 0, 12, 0, 1 +.byte 0, 14, 0, 12, 0, 11, 14, 10 +.byte 0, 0, 0, 0, 0, 1, 12, 1 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 14, 0, 12, 0, 11, 0, 9, 0 +endconst + +const sgr_x_by_x, export=1, align=4 +.byte 255, 128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17 +.byte 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9 +.byte 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6 +.byte 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4 +.byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3 +.byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 +.byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 0 +endconst + +const mc_warp_filter, export=1, align=3 +/* [-1, 0) */ +.byte 0, 0, 127, 1, 0, 0, 0, 0, 0, - 1, 127, 2, 0, 0, 0, 0 +.byte 1, - 3, 127, 4, - 1, 0, 0, 0, 1, - 4, 126, 6, - 2, 1, 0, 0 +.byte 1, - 5, 126, 8, - 3, 1, 0, 0, 1, - 6, 125, 11, - 4, 1, 0, 0 +.byte 1, - 7, 124, 13, - 4, 1, 0, 0, 2, - 8, 123, 15, - 5, 1, 0, 0 +.byte 2, - 9, 122, 18, - 6, 1, 0, 0, 2, -10, 121, 20, - 6, 1, 0, 0 +.byte 2, -11, 120, 22, - 7, 2, 0, 0, 2, -12, 119, 25, - 8, 2, 0, 0 +.byte 3, -13, 117, 27, - 8, 2, 0, 0, 3, -13, 116, 29, - 9, 2, 0, 0 +.byte 3, -14, 114, 32, -10, 3, 0, 0, 3, -15, 113, 35, -10, 2, 0, 0 +.byte 3, -15, 111, 37, -11, 3, 0, 0, 3, -16, 109, 40, -11, 3, 0, 0 +.byte 3, -16, 108, 42, -12, 3, 0, 0, 4, -17, 106, 45, -13, 3, 0, 0 +.byte 4, -17, 104, 47, -13, 3, 0, 0, 4, -17, 102, 50, -14, 3, 0, 0 +.byte 4, -17, 100, 52, -14, 3, 0, 0, 4, -18, 98, 55, -15, 4, 0, 0 +.byte 4, -18, 96, 58, -15, 3, 0, 0, 4, -18, 94, 60, -16, 4, 0, 0 +.byte 4, -18, 91, 63, -16, 4, 0, 0, 4, -18, 89, 65, -16, 4, 0, 0 +.byte 4, -18, 87, 68, -17, 4, 0, 0, 4, -18, 85, 70, -17, 4, 0, 0 +.byte 4, -18, 82, 73, -17, 4, 0, 0, 4, -18, 80, 75, -17, 4, 0, 0 +.byte 4, -18, 78, 78, -18, 4, 0, 0, 4, -17, 75, 80, -18, 4, 0, 0 +.byte 4, -17, 73, 82, -18, 4, 0, 0, 4, -17, 70, 85, -18, 4, 0, 0 +.byte 4, -17, 68, 87, -18, 4, 0, 0, 4, -16, 65, 89, -18, 4, 0, 0 +.byte 4, -16, 63, 91, -18, 4, 0, 0, 4, -16, 60, 94, -18, 4, 0, 0 +.byte 3, -15, 58, 96, -18, 4, 0, 0, 4, -15, 55, 98, -18, 4, 0, 0 +.byte 3, -14, 52, 100, -17, 4, 0, 0, 3, -14, 50, 102, -17, 4, 0, 0 +.byte 3, -13, 47, 104, -17, 4, 0, 0, 3, -13, 45, 106, -17, 4, 0, 0 +.byte 3, -12, 42, 108, -16, 3, 0, 0, 3, -11, 40, 109, -16, 3, 0, 0 +.byte 3, -11, 37, 111, -15, 3, 0, 0, 2, -10, 35, 113, -15, 3, 0, 0 +.byte 3, -10, 32, 114, -14, 3, 0, 0, 2, - 9, 29, 116, -13, 3, 0, 0 +.byte 2, - 8, 27, 117, -13, 3, 0, 0, 2, - 8, 25, 119, -12, 2, 0, 0 +.byte 2, - 7, 22, 120, -11, 2, 0, 0, 1, - 6, 20, 121, -10, 2, 0, 0 +.byte 1, - 6, 18, 122, - 9, 2, 0, 0, 1, - 5, 15, 123, - 8, 2, 0, 0 +.byte 1, - 4, 13, 124, - 7, 1, 0, 0, 1, - 4, 11, 125, - 6, 1, 0, 0 +.byte 1, - 3, 8, 126, - 5, 1, 0, 0, 1, - 2, 6, 126, - 4, 1, 0, 0 +.byte 0, - 1, 4, 127, - 3, 1, 0, 0, 0, 0, 2, 127, - 1, 0, 0, 0 +/* [0, 1) */ +.byte 0, 0, 0, 127, 1, 0, 0, 0, 0, 0, -1, 127, 2, 0, 0, 0 +.byte 0, 1, -3, 127, 4, -2, 1, 0, 0, 1, -5, 127, 6, -2, 1, 0 +.byte 0, 2, -6, 126, 8, -3, 1, 0, -1, 2, -7, 126, 11, -4, 2, -1 +.byte -1, 3, -8, 125, 13, -5, 2, -1, -1, 3, -10, 124, 16, -6, 3, -1 +.byte -1, 4, -11, 123, 18, -7, 3, -1, -1, 4, -12, 122, 20, -7, 3, -1 +.byte -1, 4, -13, 121, 23, -8, 3, -1, -2, 5, -14, 120, 25, -9, 4, -1 +.byte -1, 5, -15, 119, 27, -10, 4, -1, -1, 5, -16, 118, 30, -11, 4, -1 +.byte -2, 6, -17, 116, 33, -12, 5, -1, -2, 6, -17, 114, 35, -12, 5, -1 +.byte -2, 6, -18, 113, 38, -13, 5, -1, -2, 7, -19, 111, 41, -14, 6, -2 +.byte -2, 7, -19, 110, 43, -15, 6, -2, -2, 7, -20, 108, 46, -15, 6, -2 +.byte -2, 7, -20, 106, 49, -16, 6, -2, -2, 7, -21, 104, 51, -16, 7, -2 +.byte -2, 7, -21, 102, 54, -17, 7, -2, -2, 8, -21, 100, 56, -18, 7, -2 +.byte -2, 8, -22, 98, 59, -18, 7, -2, -2, 8, -22, 96, 62, -19, 7, -2 +.byte -2, 8, -22, 94, 64, -19, 7, -2, -2, 8, -22, 91, 67, -20, 8, -2 +.byte -2, 8, -22, 89, 69, -20, 8, -2, -2, 8, -22, 87, 72, -21, 8, -2 +.byte -2, 8, -21, 84, 74, -21, 8, -2, -2, 8, -22, 82, 77, -21, 8, -2 +.byte -2, 8, -21, 79, 79, -21, 8, -2, -2, 8, -21, 77, 82, -22, 8, -2 +.byte -2, 8, -21, 74, 84, -21, 8, -2, -2, 8, -21, 72, 87, -22, 8, -2 +.byte -2, 8, -20, 69, 89, -22, 8, -2, -2, 8, -20, 67, 91, -22, 8, -2 +.byte -2, 7, -19, 64, 94, -22, 8, -2, -2, 7, -19, 62, 96, -22, 8, -2 +.byte -2, 7, -18, 59, 98, -22, 8, -2, -2, 7, -18, 56, 100, -21, 8, -2 +.byte -2, 7, -17, 54, 102, -21, 7, -2, -2, 7, -16, 51, 104, -21, 7, -2 +.byte -2, 6, -16, 49, 106, -20, 7, -2, -2, 6, -15, 46, 108, -20, 7, -2 +.byte -2, 6, -15, 43, 110, -19, 7, -2, -2, 6, -14, 41, 111, -19, 7, -2 +.byte -1, 5, -13, 38, 113, -18, 6, -2, -1, 5, -12, 35, 114, -17, 6, -2 +.byte -1, 5, -12, 33, 116, -17, 6, -2, -1, 4, -11, 30, 118, -16, 5, -1 +.byte -1, 4, -10, 27, 119, -15, 5, -1, -1, 4, -9, 25, 120, -14, 5, -2 +.byte -1, 3, -8, 23, 121, -13, 4, -1, -1, 3, -7, 20, 122, -12, 4, -1 +.byte -1, 3, -7, 18, 123, -11, 4, -1, -1, 3, -6, 16, 124, -10, 3, -1 +.byte -1, 2, -5, 13, 125, -8, 3, -1, -1, 2, -4, 11, 126, -7, 2, -1 +.byte 0, 1, -3, 8, 126, -6, 2, 0, 0, 1, -2, 6, 127, -5, 1, 0 +.byte 0, 1, -2, 4, 127, -3, 1, 0, 0, 0, 0, 2, 127, -1, 0, 0 +/* [1, 2) */ +.byte 0, 0, 0, 1, 127, 0, 0, 0, 0, 0, 0, - 1, 127, 2, 0, 0 +.byte 0, 0, 1, - 3, 127, 4, - 1, 0, 0, 0, 1, - 4, 126, 6, - 2, 1 +.byte 0, 0, 1, - 5, 126, 8, - 3, 1, 0, 0, 1, - 6, 125, 11, - 4, 1 +.byte 0, 0, 1, - 7, 124, 13, - 4, 1, 0, 0, 2, - 8, 123, 15, - 5, 1 +.byte 0, 0, 2, - 9, 122, 18, - 6, 1, 0, 0, 2, -10, 121, 20, - 6, 1 +.byte 0, 0, 2, -11, 120, 22, - 7, 2, 0, 0, 2, -12, 119, 25, - 8, 2 +.byte 0, 0, 3, -13, 117, 27, - 8, 2, 0, 0, 3, -13, 116, 29, - 9, 2 +.byte 0, 0, 3, -14, 114, 32, -10, 3, 0, 0, 3, -15, 113, 35, -10, 2 +.byte 0, 0, 3, -15, 111, 37, -11, 3, 0, 0, 3, -16, 109, 40, -11, 3 +.byte 0, 0, 3, -16, 108, 42, -12, 3, 0, 0, 4, -17, 106, 45, -13, 3 +.byte 0, 0, 4, -17, 104, 47, -13, 3, 0, 0, 4, -17, 102, 50, -14, 3 +.byte 0, 0, 4, -17, 100, 52, -14, 3, 0, 0, 4, -18, 98, 55, -15, 4 +.byte 0, 0, 4, -18, 96, 58, -15, 3, 0, 0, 4, -18, 94, 60, -16, 4 +.byte 0, 0, 4, -18, 91, 63, -16, 4, 0, 0, 4, -18, 89, 65, -16, 4 +.byte 0, 0, 4, -18, 87, 68, -17, 4, 0, 0, 4, -18, 85, 70, -17, 4 +.byte 0, 0, 4, -18, 82, 73, -17, 4, 0, 0, 4, -18, 80, 75, -17, 4 +.byte 0, 0, 4, -18, 78, 78, -18, 4, 0, 0, 4, -17, 75, 80, -18, 4 +.byte 0, 0, 4, -17, 73, 82, -18, 4, 0, 0, 4, -17, 70, 85, -18, 4 +.byte 0, 0, 4, -17, 68, 87, -18, 4, 0, 0, 4, -16, 65, 89, -18, 4 +.byte 0, 0, 4, -16, 63, 91, -18, 4, 0, 0, 4, -16, 60, 94, -18, 4 +.byte 0, 0, 3, -15, 58, 96, -18, 4, 0, 0, 4, -15, 55, 98, -18, 4 +.byte 0, 0, 3, -14, 52, 100, -17, 4, 0, 0, 3, -14, 50, 102, -17, 4 +.byte 0, 0, 3, -13, 47, 104, -17, 4, 0, 0, 3, -13, 45, 106, -17, 4 +.byte 0, 0, 3, -12, 42, 108, -16, 3, 0, 0, 3, -11, 40, 109, -16, 3 +.byte 0, 0, 3, -11, 37, 111, -15, 3, 0, 0, 2, -10, 35, 113, -15, 3 +.byte 0, 0, 3, -10, 32, 114, -14, 3, 0, 0, 2, - 9, 29, 116, -13, 3 +.byte 0, 0, 2, - 8, 27, 117, -13, 3, 0, 0, 2, - 8, 25, 119, -12, 2 +.byte 0, 0, 2, - 7, 22, 120, -11, 2, 0, 0, 1, - 6, 20, 121, -10, 2 +.byte 0, 0, 1, - 6, 18, 122, - 9, 2, 0, 0, 1, - 5, 15, 123, - 8, 2 +.byte 0, 0, 1, - 4, 13, 124, - 7, 1, 0, 0, 1, - 4, 11, 125, - 6, 1 +.byte 0, 0, 1, - 3, 8, 126, - 5, 1, 0, 0, 1, - 2, 6, 126, - 4, 1 +.byte 0, 0, 0, - 1, 4, 127, - 3, 1, 0, 0, 0, 0, 2, 127, - 1, 0 +/* dummy (replicate row index 191) */ +.byte 0, 0, 0, 0, 2, 127, - 1, 0 +endconst + +const sm_weights, export=1 +.byte 0, 0 /* Unused, because we always offset by bs, which is at least 2. */ +.byte 255, 128 /* bs = 2 */ +.byte 255, 149, 85, 64 /* bs = 4 */ +.byte 255, 197, 146, 105, 73, 50, 37, 32 /* bs = 8 */ +.byte 255, 225, 196, 170, 145, 123, 102, 84 /* bs = 16 */ +.byte 68, 54, 43, 33, 26, 20, 17, 16 +.byte 255, 240, 225, 210, 196, 182, 169, 157 /* bs =32 */ +.byte 145, 133, 122, 111, 101, 92, 83, 74 +.byte 66, 59, 52, 45, 39, 34, 29, 25 +.byte 21, 17, 14, 12, 10, 9, 8, 8 +.byte 255, 248, 240, 233, 225, 218, 210, 203 /* bs = 64 */ +.byte 196, 189, 182, 176, 169, 163, 156, 150 +.byte 144, 138, 133, 127, 121, 116, 111, 106 +.byte 101, 96, 91, 86, 82, 77, 73, 69 +.byte 65, 61, 57, 54, 50, 47, 44, 41 +.byte 38, 35, 32, 29, 27, 25, 22, 20 +.byte 18, 16, 15, 13, 12, 10, 9, 8 +.byte 7, 6, 6, 5, 5, 4, 4, 4 +endconst + +const obmc_masks, export=1, align=4 +.byte 0, 0 /* Unused */ +.byte 19, 0 /* 2 */ +.byte 25, 14, 5, 0 /* 4 */ +.byte 28, 22, 16, 11, 7, 3, 0, 0 /* 8 */ +.byte 30, 27, 24, 21, 18, 15, 12, 10 +.byte 8, 6, 4, 3, 0, 0, 0, 0 /* 16 */ +.byte 31, 29, 28, 26, 24, 23, 21, 20 +.byte 19, 17, 16, 14, 13, 12, 11, 9 +.byte 8, 7, 6, 5, 4, 4, 3, 2 +.byte 0, 0, 0, 0, 0, 0, 0, 0 /* 32 */ +endconst diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4992 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHTS 1-* +const smooth_weights_1d_16bpc ; sm_weights[] << 7 + %rep %0 + dw %1*128 + %rotate 1 + %endrep +const smooth_weights_2d_16bpc ; sm_weights[], 256 - sm_weights[] + %rep %0 + dw %1, 256-%1 + %rotate 1 + %endrep +%endmacro + +SMOOTH_WEIGHTS 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +%if ARCH_X86_64 + +ipred_hv_shuf: db 6, 7, 6, 7, 0, 1, 2, 3, 2, 3, 2, 3, 8, 9, 10, 11 + db 4, 5, 4, 5, 4, 5, 6, 7, 0, 1, 0, 1, 12, 13, 14, 15 +filter_shuf1: db 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 14, 15, 12, 13, -1, -1 +filter_shuf2: db 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4, 5, 2, 3, -1, -1 +filter_shuf3: db 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 8, 9, -1, -1 +pal_pred_shuf: db 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 + dw 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 +z_filter_t0: db 55,127, 39,127, 39,127, 7, 15, 31, 7, 15, 31, 0, 3, 31, 0 +z_filter_t1: db 39, 63, 19, 47, 19, 47, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 +z_filter_wh: db 7, 7, 11, 11, 15, 15, 19, 19, 19, 23, 23, 23, 31, 31, 31, 39 + db 39, 39, 47, 47, 47, 63, 63, 63, 79, 79, 79, -1 +pw_m1024: times 2 dw -1024 +pw_1to16: dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +pw_16to1: dw 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 +z2_ymul: dw 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4 +z2_ymul8: dw 1, 2, 5, 6, 3, 4, 7, 8, 5, 6, 16, 16, 7, 8 +pb_90: times 4 db 90 +z2_y_shuf_h4: dd 3, 7, 2, 6, 1, 5, 0, 4 +z_upsample: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_x_shuf: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +z2_y_shuf: db 6, 7, 14, 15, 4, 5, 12, 13, 4, 5, 12, 13, 2, 3, 10, 11 +z2_y_shuf_us: db 6, 7, 14, 15, 2, 3, 10, 11, 4, 5, 12, 13, 0, 1, 8, 9 +z_filter_k: dw 4, 4, 5, 5, 4, 4 + dw 8, 8, 6, 6, 4, 4 + dw 0, 0, 0, 0, 2, 2 + +%define pw_2 (z_filter_k+32) +%define pw_4 (z_filter_k+ 0) +%define pw_16 (z2_ymul8 +20) + +pw_1: times 2 dw 1 +pw_3: times 2 dw 3 +pw_62: times 2 dw 62 +pw_512: times 2 dw 512 +pw_2048: times 2 dw 2048 +pd_8: dd 8 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_16bpc_avx2_table (ipred_dc_16bpc_avx2_table + 10*4) +%define ipred_cfl_splat_16bpc_avx2_table (ipred_cfl_16bpc_avx2_table + 8*4) + +JMP_TABLE ipred_dc_16bpc, avx2, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left_16bpc, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_h_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3_16bpc, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_filter_16bpc, avx2, w4, w8, w16, w32 +JMP_TABLE ipred_cfl_16bpc, avx2, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left_16bpc, avx2, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_444_16bpc, avx2, w4, w8, w16, w32 +JMP_TABLE pal_pred_16bpc, avx2, w4, w8, w16, w32, w64 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_YMM avx2 +cglobal ipred_dc_top_16bpc, 3, 7, 6, dst, stride, tl, w, h + movifnidn hd, hm + add tlq, 2 + movd xm4, wd + pxor xm3, xm3 + pavgw xm4, xm3 + tzcnt wd, wd + movd xm5, wd + movu m0, [tlq] + lea r5, [ipred_dc_left_16bpc_avx2_table] + movsxd r6, [r5+wq*4] + add r6, r5 + add r5, ipred_dc_splat_16bpc_avx2_table-ipred_dc_left_16bpc_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + mov hd, hm + sub tlq, hq + movd xm4, hd + sub tlq, hq + pxor xm3, xm3 + pavgw xm4, xm3 + tzcnt r6d, hd + movd xm5, r6d + movu m0, [tlq] + lea r5, [ipred_dc_left_16bpc_avx2_table] + movsxd r6, [r5+r6*4] + add r6, r5 + add r5, ipred_dc_splat_16bpc_avx2_table-ipred_dc_left_16bpc_avx2_table + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + paddw m0, [tlq+96] + paddw m0, [tlq+64] +.h32: + paddw m0, [tlq+32] +.h16: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h8: + psrldq xm1, xm0, 8 + paddw xm0, xm1 +.h4: + punpcklwd xm0, xm3 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + paddd xm0, xm4 + psrld xm0, xm5 + lea stride3q, [strideq*3] + vpbroadcastw m0, xm0 + mova m1, m0 + mova m2, m0 + mova m3, m0 + jmp wq + +cglobal ipred_dc_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm4, r5d + tzcnt r5d, r5d + movd xm5, r5d + lea r5, [ipred_dc_16bpc_avx2_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pxor m3, m3 + psrlw xm4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movq xm0, [tlq-8] + jmp wq +.w4: + movq xm1, [tlq+2] + paddw m0, m4 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrld m1, m0, 16 + paddw m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + lea r2d, [hq*2] + mov r6d, 0xAAAB6667 + shrx r6d, r6d, r2d + punpckhwd xm1, xm0, xm3 + punpcklwd xm0, xm3 + paddd xm0, xm1 + movd xm1, r6d + psrld xm0, 2 + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w4_end: + vpbroadcastw xm0, xm0 +.s4: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + mova xm0, [tlq-16] + jmp wq +.w8: + vextracti128 xm1, m0, 1 + paddw xm0, [tlq+2] + paddw xm0, xm4 + paddw xm0, xm1 + psrld xm1, xm0, 16 + paddw xm0, xm1 + pblendw xm0, xm3, 0xAA + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w8_end: + vpbroadcastw xm0, xm0 +.s8: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova m0, [tlq-32] + jmp wq +.w16: + paddw m0, [tlq+2] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpckhwd xm1, xm0, xm3 + punpcklwd xm0, xm3 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-32] + jmp wq +.w32: + paddw m0, [tlq+ 2] + paddw m0, [tlq+34] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm3 + punpckhwd xm0, xm3 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x6667AAAB + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w32_end: + vpbroadcastw m0, xm0 + mova m1, m0 +.s32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m0 + mova [dstq+stride3q +32*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-128] + mova m1, [tlq- 96] + paddw m0, [tlq- 64] + paddw m1, [tlq- 32] + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 2] + paddw m0, [tlq+34] + paddw m1, [tlq+66] + paddw m0, [tlq+98] + paddw m0, m1 + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm3 + punpckhwd xm0, xm3 + paddd xm1, xm4 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 64 + je .w64_end + mov r6d, 0x6667AAAB + shrx r6d, r6d, hd + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w64_end: + vpbroadcastw m0, xm0 + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s64: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s64 + RET + +cglobal ipred_dc_128_16bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + mov r6d, r8m + shr r6d, 11 + lea r5, [ipred_dc_splat_16bpc_avx2_table] + tzcnt wd, wd + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_16bpc_avx2_table+pw_512+r6*4] + mova m1, m0 + mova m2, m0 + mova m3, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movu m0, [tlq+ 2] + movu m1, [tlq+34] + movu m2, [tlq+66] + movu m3, [tlq+98] + lea r5, [ipred_dc_splat_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +%macro IPRED_H 2 ; w, store_type + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + vpbroadcastw m2, [tlq-6] + vpbroadcastw m3, [tlq-8] + sub tlq, 8 + mov%2 [dstq+strideq*0], m0 + mov%2 [dstq+strideq*1], m1 + mov%2 [dstq+strideq*2], m2 + mov%2 [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +ALIGN function_align +%endmacro + +cglobal ipred_h_16bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + lea r5, [ipred_h_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +INIT_XMM avx2 +.w4: + IPRED_H 4, q +.w8: + IPRED_H 8, a +INIT_YMM avx2 +.w16: + IPRED_H 16, a +.w32: + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + vpbroadcastw m2, [tlq-6] + vpbroadcastw m3, [tlq-8] + sub tlq, 8 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m2 + mova [dstq+strideq*2+32*1], m2 + mova [dstq+stride3q +32*0], m3 + mova [dstq+stride3q +32*1], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +.w64: + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + sub tlq, 4 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*0+32*2], m0 + mova [dstq+strideq*0+32*3], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m1 + mova [dstq+strideq*1+32*3], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64 + RET + +%macro PAETH 3 ; top, signed_ldiff, ldiff + paddw m0, m%2, m1 + psubw m7, m3, m0 ; tldiff + psubw m0, m%1 ; tdiff + pabsw m7, m7 + pabsw m0, m0 + pminsw m7, m0 + pcmpeqw m0, m7 + pcmpgtw m7, m%3, m7 + vpblendvb m0, m3, m%1, m0 + vpblendvb m0, m1, m0, m7 +%endmacro + +cglobal ipred_paeth_16bpc, 3, 6, 8, dst, stride, tl, w, h +%define base r5-ipred_paeth_16bpc_avx2_table + movifnidn hd, hm + lea r5, [ipred_paeth_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + vpbroadcastw m3, [tlq] ; topleft + add wq, r5 + jmp wq +.w4: + vpbroadcastq m2, [tlq+2] ; top + movsldup m6, [base+ipred_hv_shuf] + lea r3, [strideq*3] + psubw m4, m2, m3 + pabsw m5, m4 +.w4_loop: + sub tlq, 8 + vpbroadcastq m1, [tlq] + pshufb m1, m6 ; left + PAETH 2, 4, 5 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + vbroadcasti128 m2, [tlq+2] + movsldup m6, [base+ipred_hv_shuf] + psubw m4, m2, m3 + pabsw m5, m4 +.w8_loop: + sub tlq, 4 + vpbroadcastd m1, [tlq] + pshufb m1, m6 + PAETH 2, 4, 5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + movu m2, [tlq+2] + psubw m4, m2, m3 + pabsw m5, m4 +.w16_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m2, [tlq+2] + movu m6, [tlq+34] +%if WIN64 + movaps r4m, xmm8 + movaps r6m, xmm9 +%endif + psubw m4, m2, m3 + psubw m8, m6, m3 + pabsw m5, m4 + pabsw m9, m8 +.w32_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq+32*0], m0 + PAETH 6, 8, 9 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w32_loop +%if WIN64 + movaps xmm8, r4m + movaps xmm9, r6m +%endif + RET +ALIGN function_align +.w64: + WIN64_SPILL_XMM 16 + movu m2, [tlq+ 2] + movu m6, [tlq+34] + movu m10, [tlq+66] + movu m13, [tlq+98] + psubw m4, m2, m3 + psubw m8, m6, m3 + psubw m11, m10, m3 + psubw m14, m13, m3 + pabsw m5, m4 + pabsw m9, m8 + pabsw m12, m11 + pabsw m15, m14 +.w64_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq+32*0], m0 + PAETH 6, 8, 9 + mova [dstq+32*1], m0 + PAETH 10, 11, 12 + mova [dstq+32*2], m0 + PAETH 13, 14, 15 + mova [dstq+32*3], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_16bpc, 3, 7, 6, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_16bpc_avx2_table + lea r6, [ipred_smooth_v_16bpc_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea weightsq, [base+smooth_weights_1d_16bpc+hq*4] + neg hq + vpbroadcastw m5, [tlq+hq*2] ; bottom + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [tlq+2] ; top + movsldup m3, [base+ipred_hv_shuf] + lea r6, [strideq*3] + psubw m4, m5 ; top - bottom +.w4_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m3 + pmulhrsw m0, m4 + paddw m0, m5 + vextracti128 xm1, m0, 1 + movhps [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movq [dstq+r6 ], xm0 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop +.ret: + RET +.w8: + vbroadcasti128 m4, [tlq+2] + movsldup m3, [base+ipred_hv_shuf] + lea r6, [strideq*3] + psubw m4, m5 +.w8_loop: + vpbroadcastd m0, [weightsq+hq*2+0] + vpbroadcastd m1, [weightsq+hq*2+4] + pshufb m0, m3 + pshufb m1, m3 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + vextracti128 [dstq+strideq*0], m0, 1 + mova [dstq+strideq*1], xm0 + vextracti128 [dstq+strideq*2], m1, 1 + mova [dstq+r6 ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + movu m4, [tlq+2] + lea r6, [strideq*3] + psubw m4, m5 +.w16_loop: + vpbroadcastw m0, [weightsq+hq*2+0] + vpbroadcastw m1, [weightsq+hq*2+2] + vpbroadcastw m2, [weightsq+hq*2+4] + vpbroadcastw m3, [weightsq+hq*2+6] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r6 ], m3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + WIN64_SPILL_XMM 7 + movu m4, [tlq+ 2] + movu m6, [tlq+34] + psubw m4, m5 + psubw m6, m5 +.w32_loop: + vpbroadcastw m1, [weightsq+hq*2+0] + vpbroadcastw m3, [weightsq+hq*2+2] + pmulhrsw m0, m4, m1 + pmulhrsw m1, m6 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m6 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + WIN64_SPILL_XMM 8 + movu m3, [tlq+ 2] + movu m4, [tlq+34] + movu m6, [tlq+66] + movu m7, [tlq+98] + REPX {psubw x, m5}, m3, m4, m6, m7 +.w64_loop: + vpbroadcastw m2, [weightsq+hq*2] + pmulhrsw m0, m3, m2 + pmulhrsw m1, m4, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*0], m0 + pmulhrsw m0, m6, m2 + mova [dstq+32*1], m1 + pmulhrsw m1, m7, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + add dstq, strideq + inc hq + jl .w64_loop + RET + +cglobal ipred_smooth_h_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 +%define base r6-ipred_smooth_h_16bpc_avx2_table + lea r6, [ipred_smooth_h_16bpc_avx2_table] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m5, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [r6+wq*4] + sub tlq, hq + lea stride3q, [strideq*3] + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [base+smooth_weights_1d_16bpc+4*2] + movsldup m3, [base+ipred_hv_shuf] +.w4_loop: + vpbroadcastq m0, [tlq+hq-8] ; left + pshufb m0, m3 + psubw m0, m5 ; left - right + pmulhrsw m0, m4 + paddw m0, m5 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w4_loop + RET +.w8: + vbroadcasti128 m4, [base+smooth_weights_1d_16bpc+8*2] + movsldup m3, [base+ipred_hv_shuf] +.w8_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastd m1, [tlq+hq-8] + pshufb m0, m3 + pshufb m1, m3 + psubw m0, m5 + psubw m1, m5 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w8_loop + RET +.w16: + movu m4, [base+smooth_weights_1d_16bpc+16*2] +.w16_loop: + vpbroadcastq m3, [tlq+hq-8] + punpcklwd m3, m3 + psubw m3, m5 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w16_loop + RET +.w32: + WIN64_SPILL_XMM 7 + movu m4, [base+smooth_weights_1d_16bpc+32*2] + movu m6, [base+smooth_weights_1d_16bpc+32*3] +.w32_loop: + vpbroadcastw m1, [tlq+hq-2] + vpbroadcastw m3, [tlq+hq-4] + psubw m1, m5 + psubw m3, m5 + pmulhrsw m0, m4, m1 + pmulhrsw m1, m6 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m6 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w32_loop + RET +.w64: + WIN64_SPILL_XMM 8 + movu m3, [base+smooth_weights_1d_16bpc+32*4] + movu m4, [base+smooth_weights_1d_16bpc+32*5] + movu m6, [base+smooth_weights_1d_16bpc+32*6] + movu m7, [base+smooth_weights_1d_16bpc+32*7] +.w64_loop: + vpbroadcastw m2, [tlq+hq-2] + psubw m2, m5 + pmulhrsw m0, m3, m2 + pmulhrsw m1, m4, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*0], m0 + pmulhrsw m0, m6, m2 + mova [dstq+32*1], m1 + pmulhrsw m1, m7, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + add dstq, strideq + sub hq, 1*2 + jg .w64_loop + RET + +%macro SMOOTH_2D_END 6 ; src[1-2], mul[1-2], add[1-2] + pmaddwd m0, m%1, m%3 + pmaddwd m1, m%2, m%4 + paddd m0, m%5 + paddd m1, m%6 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m5 +%endmacro + +cglobal ipred_smooth_16bpc, 3, 7, 6, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_16bpc_avx2_table + lea r6, [ipred_smooth_16bpc_avx2_table] + mov wd, wm + vpbroadcastw m4, [tlq+wq*2] ; right + tzcnt wd, wd + mov hd, hm + sub tlq, hq + sub tlq, hq + movsxd wq, [r6+wq*4] + pxor m5, m5 + add wq, r6 + lea v_weightsq, [base+smooth_weights_2d_16bpc+hq*4] + jmp wq +.w4: + WIN64_SPILL_XMM 11 + vpbroadcastw m0, [tlq] ; bottom + vpbroadcastq m6, [tlq+hq*2+2] + movsldup m7, [base+ipred_hv_shuf] + movshdup m9, [base+ipred_hv_shuf] + vbroadcasti128 m10, [base+smooth_weights_2d_16bpc+4*4] + punpcklwd m6, m0 ; top, bottom + punpcklqdq m8, m9, m9 + punpckhqdq m9, m9 + lea r3, [strideq*3] +.w4_loop: + vpbroadcastq m3, [tlq+hq*2-8] + vbroadcasti128 m1, [v_weightsq] + pshufb m3, m7 + punpcklwd m2, m3, m4 ; left, right + punpckhwd m3, m4 + pmaddwd m2, m10 + pmaddwd m3, m10 + pshufb m0, m1, m8 + pshufb m1, m9 + SMOOTH_2D_END 0, 1, 6, 6, 2, 3 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + add v_weightsq, 16 + sub hd, 4 + jg .w4_loop + RET +.w8: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + vpbroadcastw m0, [tlq] ; bottom + vbroadcasti128 m7, [tlq+hq*2+2] + movsldup m8, [base+ipred_hv_shuf] + movshdup m9, [base+ipred_hv_shuf] + vbroadcasti128 m10, [base+smooth_weights_2d_16bpc+8*4+16*0] + vbroadcasti128 m11, [base+smooth_weights_2d_16bpc+8*4+16*1] + punpcklwd m6, m7, m0 ; top, bottom + punpckhwd m7, m0 +.w8_loop: + vpbroadcastd m3, [tlq+hq*2-4] + vpbroadcastq m1, [v_weightsq] + pshufb m3, m8 + punpcklwd m2, m3, m4 ; left, right + punpckhwd m3, m4 + pmaddwd m2, m10 + pmaddwd m3, m11 + pshufb m1, m9 + SMOOTH_2D_END 1, 1, 6, 7, 2, 3 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add v_weightsq, 8 + sub hd, 2 + jg .w8_loop + RET +.w16: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 11 + vpbroadcastw m0, [tlq] ; bottom + movu m7, [tlq+hq*2+2] + mova xm8, [base+smooth_weights_2d_16bpc+16*4+16*0] + mova xm9, [base+smooth_weights_2d_16bpc+16*4+16*1] + vinserti128 m8, [base+smooth_weights_2d_16bpc+16*4+16*2], 1 + vinserti128 m9, [base+smooth_weights_2d_16bpc+16*4+16*3], 1 + punpcklwd m6, m7, m0 ; top, bottom + punpckhwd m7, m0 +.w16_loop: + vpbroadcastd m3, [tlq+hq*2-4] + vpbroadcastd m1, [v_weightsq+0] + punpcklwd m3, m4 ; left, right + pshufd m2, m3, q1111 + pmaddwd m10, m8, m2 + pmaddwd m2, m9 + pshufd m3, m3, q0000 + SMOOTH_2D_END 1, 1, 6, 7, 10, 2 + vpbroadcastd m1, [v_weightsq+4] + pmaddwd m2, m8, m3 + pmaddwd m3, m9 + mova [dstq+strideq*0], m0 + SMOOTH_2D_END 1, 1, 6, 7, 2, 3 + mova [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + add v_weightsq, 8 + sub hq, 2 + jg .w16_loop + RET +.w32: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastw m0, [tlq] ; bottom + movu m7, [tlq+hq*2+ 2] + movu m9, [tlq+hq*2+34] + mova xm10, [base+smooth_weights_2d_16bpc+32*4+16*0] + mova xm11, [base+smooth_weights_2d_16bpc+32*4+16*1] + vinserti128 m10, [base+smooth_weights_2d_16bpc+32*4+16*2], 1 + vinserti128 m11, [base+smooth_weights_2d_16bpc+32*4+16*3], 1 + mova xm12, [base+smooth_weights_2d_16bpc+32*4+16*4] + mova xm13, [base+smooth_weights_2d_16bpc+32*4+16*5] + vinserti128 m12, [base+smooth_weights_2d_16bpc+32*4+16*6], 1 + vinserti128 m13, [base+smooth_weights_2d_16bpc+32*4+16*7], 1 + punpcklwd m6, m7, m0 + punpckhwd m7, m0 + punpcklwd m8, m9, m0 + punpckhwd m9, m0 +.w32_loop: + vpbroadcastw m3, [tlq+hq*2-2] + vpbroadcastd m14, [v_weightsq] + punpcklwd m3, m4 + pmaddwd m1, m10, m3 + pmaddwd m2, m11, m3 + pmaddwd m0, m6, m14 + paddd m0, m1 + pmaddwd m1, m7, m14 + paddd m1, m2 + pmaddwd m2, m12, m3 + pmaddwd m3, m13 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m5 + mova [dstq+32*0], m0 + SMOOTH_2D_END 14, 14, 8, 9, 2, 3 + mova [dstq+32*1], m0 + add dstq, strideq + add v_weightsq, 4 + dec hd + jg .w32_loop + RET +.w64: +%assign stack_offset stack_offset - stack_size_padded + PROLOGUE 0, 11, 16, dst, stride, tl, tl_base, h, v_weights, dummy, v_weights_base, x, y, dst_base + mov dst_baseq, dstq + mov tl_baseq, tlq + mov v_weights_baseq, v_weightsq + xor xq, xq +.w64_loop_x: + mov yq, hq + lea tlq, [tl_baseq+hq*2] + vpbroadcastw m0, [tl_baseq] ; bottom + movu m7, [tlq+xq*2+ 2] + movu m9, [tlq+xq*2+34] + mova xm10, [base+smooth_weights_2d_16bpc+64*4+16*0] + mova xm11, [base+smooth_weights_2d_16bpc+64*4+16*1] + vinserti128 m10, [base+smooth_weights_2d_16bpc+64*4+16*2], 1 + vinserti128 m11, [base+smooth_weights_2d_16bpc+64*4+16*3], 1 + mova xm12, [base+smooth_weights_2d_16bpc+64*4+16*4] + mova xm13, [base+smooth_weights_2d_16bpc+64*4+16*5] + vinserti128 m12, [base+smooth_weights_2d_16bpc+64*4+16*6], 1 + vinserti128 m13, [base+smooth_weights_2d_16bpc+64*4+16*7], 1 + punpcklwd m6, m7, m0 + punpckhwd m7, m0 + punpcklwd m8, m9, m0 + punpckhwd m9, m0 + lea tlq, [tl_baseq-2] +.w64_loop_y: + vpbroadcastw m3, [tlq+yq*2] + vpbroadcastd m1, [v_weightsq] + punpcklwd m3, m4 + pmaddwd m14, m10, m3 + pmaddwd m15, m11, m3 + pmaddwd m2, m12, m3 + pmaddwd m3, m13 + pmaddwd m0, m6, m1 + paddd m0, m14 + pmaddwd m14, m7, m1 + paddd m14, m15 + psrld m0, 8 + psrld m14, 8 + packssdw m0, m14 + pavgw m0, m5 + mova [dstq+32*0], m0 + SMOOTH_2D_END 8, 9, 1, 1, 2, 3 + mova [dstq+32*1], m0 + add dstq, strideq + add v_weightsq, 4 + dec yq + jg .w64_loop_y + lea dstq, [dst_baseq+32*2] + add r6, 16*8 + mov v_weightsq, v_weights_baseq + add xq, 32 + test xb, 64 + jz .w64_loop_x + RET + +cglobal ipred_z1_16bpc, 3, 8, 0, dst, stride, tl, w, h, angle, dx, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z1_16bpc_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea r7, [dr_intra_derivative] + movsxd wq, [r6+wq*4] + add tlq, 2 + add wq, r6 + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + movzx dxd, word [r7+dxq] + xor angled, 0x4ff ; d = 90 - angle + vpbroadcastd m5, [pw_62] + jmp wq +.w4: + ALLOC_STACK -64, 7 + cmp angleb, 40 + jae .w4_no_upsample + lea r3d, [angleq-1024] + sar r3d, 7 + add r3d, hd + jg .w4_no_upsample ; !enable_intra_edge_filter || h > 8 || (h == 8 && is_sm) + vpbroadcastw xm3, [tlq+14] + movu xm1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + palignr xm0, xm3, xm1, 4 ; 3 4 5 6 7 8 8 8 + paddw xm0, [tlq- 2] ; 0 1 2 3 4 5 6 7 + add dxd, dxd + palignr xm2, xm3, xm1, 2 ; 2 3 4 5 6 7 8 8 + paddw xm2, xm1 ; -1 * a + 9 * b + 9 * c + -1 * d + psubw xm0, xm2, xm0 ; = (b + c - a - d + (b + c) << 3 + 8) >> 4 + psraw xm0, 3 ; = ((b + c - a - d) >> 3 + b + c + 1) >> 1 + pxor xm4, xm4 + paddw xm2, xm0 + vpbroadcastw xm0, r8m ; pixel_max + mova [rsp+32], xm3 + movd xm3, dxd + pmaxsw xm2, xm4 + mov r3d, dxd + pavgw xm2, xm4 + vpbroadcastw m3, xm3 + pminsw xm2, xm0 + punpcklwd xm0, xm1, xm2 + punpckhwd xm1, xm2 + lea r5, [strideq*3] + pslldq m2, m3, 8 + mova [rsp+ 0], xm0 + mova [rsp+16], xm1 + paddw m6, m3, m3 + paddw m3, m2 + vpblendd m4, m6, 0xf0 + paddw m6, m6 + paddw m3, m4 ; xpos0 xpos1 xpos2 xpos3 + vbroadcasti128 m4, [z_upsample] +.w4_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + movu xm2, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base2 + vinserti128 m1, [rsp+r3*2], 1 ; 0 2 + lea r3d, [r2+dxq] + shr r2d, 6 ; base3 + vinserti128 m2, [rsp+r2*2], 1 ; 1 3 + pshufb m1, m4 + pshufb m2, m4 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m5, m3 ; frac + psllw m2, 9 ; (a * (64 - frac) + b * frac + 32) >> 6 + psubw m1, m0 ; = a + (((b - a) * frac + 32) >> 6) + pmulhrsw m1, m2 ; = a + (((b - a) * (frac << 9) + 16384) >> 15) + paddw m3, m6 ; xpos += dx + paddw m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r5 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; w4/w8/w16 +%define base r3-z_filter_t0 + movd xm0, maxbased + lea r3, [z_filter_t0] + movd xm1, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m1, xm1 + pcmpeqb m0, [base+z_filter_wh] + mova xm2, [r3+angleq*8] + pand m0, m1 + pcmpgtb m0, m2 + pmovmskb r5d, m0 + ret +.w4_no_upsample: + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea maxbased, [hq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastw xm3, [tlq+14] + mova xm0, [tlq- 2] ; 0 1 2 3 4 5 6 7 + vpbroadcastd xm1, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd xm4, [base+z_filter_k-4+r5*4+12*0] + palignr xm2, xm3, xm0, 4 ; 2 3 4 5 6 7 8 8 + pmullw xm1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + paddw xm2, xm0 + pmullw xm2, xm4 + movd [rsp+16], xm3 + cmp r5d, 3 + jne .w4_3tap + paddw xm1, xm2 + palignr xm2, xm3, xm0, 6 ; 3 4 5 6 7 8 8 8 + pblendw xm0, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 + movzx r3d, word [tlq+14] + movzx r2d, word [tlq+12] + inc maxbased + paddw xm2, xm0 + sub r2d, r3d + paddw xm2, xm2 + lea r2d, [r2+r3*8+4] + shr r2d, 3 ; (1 * top[6] + 7 * top[7] + 4) >> 3 + mov [rsp+16], r2w +.w4_3tap: + pxor xm0, xm0 + paddw xm1, xm2 + mov tlq, rsp + psrlw xm1, 3 + cmp hd, 8 + sbb maxbased, -1 + pavgw xm0, xm1 + mova [tlq], xm0 +.w4_main: + movd xm3, dxd + vpbroadcastq m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] ; top[max_base_x] + shl maxbased, 6 + vpbroadcastw m3, xm3 + movd xm0, maxbased + mov r3d, dxd ; xpos + vpbroadcastw m0, xm0 + paddw m4, m3, m3 + psubw m1, m0 ; -max_base_x + vpblendd m3, m4, 0xcc + paddw m0, m4, m3 + vpblendd m3, m0, 0xf0 ; xpos0 xpos1 xpos2 xpos3 + paddw m4, m4 + paddw m3, m1 +.w4_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [tlq+r3*2] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + movu xm2, [tlq+r5*2] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + vinserti128 m1, [tlq+r3*2], 1 ; 0 2 + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + vinserti128 m2, [tlq+r5*2], 1 ; 1 3 + punpcklqdq m0, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + vpblendd m1, m2, 0xcc + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 ; xpos < max_base_x + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w4_loop + lea r6, [strideq*3] +.w4_end_loop: + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + movq [dstq+strideq*2], xm6 + movq [dstq+r6 ], xm6 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_end_loop +.w4_end: + RET +.w8: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 7 + lea r3d, [angleq+216] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + movu m2, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g _ + movu m0, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g _ _ + movu m1, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + cmp hd, 4 + jne .w8_upsample_h8 ; awkward single-pixel edge case + vpblendd m0, m2, 0x20 ; 3 4 5 6 7 8 9 a b c c _ _ _ _ _ +.w8_upsample_h8: + paddw m2, m1 + paddw m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + add dxd, dxd + psubw m0, m2, m0 + psraw m0, 3 + pxor m4, m4 + paddw m2, m0 + vpbroadcastw m0, r8m + movd xm3, dxd + pmaxsw m2, m4 + mov r3d, dxd + pavgw m2, m4 + vpbroadcastw m3, xm3 + pminsw m2, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + vbroadcasti128 m4, [z_upsample] + mova [rsp+ 0], xm0 + mova [rsp+16], xm1 + paddw m6, m3, m3 + vextracti128 [rsp+32], m0, 1 + vextracti128 [rsp+48], m1, 1 + vpblendd m3, m6, 0xf0 ; xpos0 xpos1 +.w8_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [rsp+r3*2] + movu xm2, [rsp+r3*2+16] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + vinserti128 m1, [rsp+r2*2], 1 + vinserti128 m2, [rsp+r2*2+16], 1 + pshufb m1, m4 + pshufb m2, m4 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m3, m6 + paddw m0, m1 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_upsample_loop + RET +.w8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(h+7, 15) + jmp .w8_main +.w8_no_upsample: + lea maxbased, [hq+7] + test angled, 0x400 + jnz .w8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w8_main + popcnt r5d, r5d + vpbroadcastd m1, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movu m2, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m2 + cmp hd, 8 + jl .w8_filter_h4 + punpckhwd m2, m2 + vpblendd m3, m2, [tlq+2], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + je .w8_filter_end ; 8x4 and 8x8 are always 3-tap + movzx r3d, word [tlq+30] + mov maxbased, 16 + mov [rsp+32], r3d + cmp r5d, 3 + jne .w8_filter_end + punpcklwd xm6, xm0, xm0 + vpblendd m2, [tlq+4], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g g g + vpblendd m6, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movzx r5d, word [tlq+28] + mov [rsp+34], r3w + paddw m2, m6 + sub r5d, r3d + inc maxbased + paddw m2, m2 + lea r3d, [r5+r3*8+4] + paddw m1, m2 + shr r3d, 3 + mov [rsp+32], r3w + jmp .w8_filter_end +.w8_filter_h4: + pshuflw m3, m2, q3321 + vinserti128 m3, [tlq+2], 0 ; 2 3 4 5 6 7 8 9 a b c c _ _ _ _ +.w8_filter_end: + paddw m0, m3 + pmullw m0, m4 + mov tlq, rsp + pxor m2, m2 + paddw m0, m1 + psrlw m0, 3 + pavgw m0, m2 + mova [tlq], m0 +.w8_main: + movd xm3, dxd + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m3, xm3 + movd xm0, maxbased + mov r3d, dxd + vpbroadcastw m0, xm0 + paddw m4, m3, m3 + psubw m1, m0 + vpblendd m3, m4, 0xf0 ; xpos0 xpos1 + paddw m3, m1 +.w8_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + movu xm0, [tlq+r3*2] + movu xm1, [tlq+r3*2+2] + lea r3d, [r5+dxq] + shr r5d, 6 + vinserti128 m0, [tlq+r5*2], 1 + vinserti128 m1, [tlq+r5*2+2], 1 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w8_loop +.w8_end_loop: + mova [dstq+strideq*0], xm6 + mova [dstq+strideq*1], xm6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_end_loop +.w8_end: + RET +.w16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(h+15, 31) + jmp .w16_main +.w16: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 7 + lea maxbased, [hq+15] + test angled, 0x400 + jnz .w16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w16_main + popcnt r5d, r5d + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + cmp r5d, 3 + jne .w16_filter_3tap + vpbroadcastd m2, [base+pw_3] + punpcklwd xm0, xm0 + vpblendd m0, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m1, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m0, m2 + pavgw m0, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m0, m1 + psrlw m0, 2 + movu m3, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m3, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + cmp hd, 8 + jl .w16_filter_5tap_h4 + punpckhwd m3, m3 + je .w16_filter_5tap_h8 + vpblendd m4, m3, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m3, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + movzx r3d, word [tlq+62] + movzx r2d, word [tlq+60] + pavgw m2, m4 + sub r2d, r3d + paddw m1, m3 + lea r2d, [r2+r3*8+4] + paddw m1, m2 + shr r2d, 3 + psrlw m1, 2 + mov [rsp+66], r3w + mov [rsp+64], r2w + mov tlq, rsp + mov r3d, 33 + cmp hd, 16 + cmovg maxbased, r3d + jmp .w16_filter_end2 +.w16_filter_5tap_h8: + vpblendd xm4, xm3, [tlq+36], 0x07 ; 4 5 6 7 8 9 9 9 + vpblendd xm3, [tlq+34], 0x07 ; 3 4 5 6 7 8 9 9 + pavgw xm2, xm4 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 + jmp .w16_filter_end2 +.w16_filter_5tap_h4: + pshuflw xm4, xm3, q3332 ; 4 5 5 5 + pshuflw xm3, xm3, q3321 ; 3 4 5 5 + pavgw xm2, xm4 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 + jmp .w16_filter_end2 +.w16_filter_3tap: + vpbroadcastd m3, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + pmullw m0, m3, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + movu m2, [tlq+32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m4 + pmullw m3, m2 + paddw m0, m1 + cmp hd, 8 + je .w16_filter_3tap_h8 + jl .w16_filter_3tap_h4 + punpckhwd m2, m2 + vpblendd m2, [tlq+34], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + jmp .w16_filter_end +.w16_filter_3tap_h4: + pshuflw xm2, xm2, q3321 ; 2 3 4 4 _ _ _ _ + jmp .w16_filter_end +.w16_filter_3tap_h8: + psrldq xm2, 2 + pshufhw xm2, xm2, q2210 ; 2 3 4 5 6 7 8 8 +.w16_filter_end: + paddw m2, [tlq+30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + pmullw m2, m4 + psrlw m0, 3 + pxor m1, m1 + paddw m2, m3 + psrlw m2, 3 + pavgw m0, m1 + pavgw m1, m2 +.w16_filter_end2: + mov tlq, rsp + mova [tlq+ 0], m0 + mova [tlq+32], m1 +.w16_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r3d, dxd + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + psubw m3, m0 +.w16_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + lea r3d, [r5+dxq] + shr r5d, 6 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m1, m0 + movu m0, [tlq+r5*2] + vpblendvb m2, m6, m1, m2 + movu m1, [tlq+r5*2+2] + mova [dstq+strideq*0], m2 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+strideq*1], m0 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w16_loop +.w16_end_loop: + mova [dstq+strideq*0], m6 + mova [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_end_loop +.w16_end: + RET +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK -160, 8 + lea maxbased, [hq+31] + mov r3d, 63 + cmp hd, 32 + cmova maxbased, r3d + test angled, 0x400 + jnz .w32_main + vpbroadcastd m2, [pw_3] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + vpblendd m1, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m0, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m1, m2 + paddw m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pavgw m1, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + mov r3, rsp + paddw m0, m1 + lea r5d, [maxbaseq-31] + psrlw m0, 2 + mova [r3], m0 +.w32_filter_loop: + mova m0, [tlq+30] + paddw m1, m2, [tlq+28] + add tlq, 32 + paddw m0, [tlq+0] + pavgw m1, [tlq+4] + paddw m0, [tlq+2] + add r3, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r3], m0 + sub r5d, 16 + jg .w32_filter_loop + movu m0, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + punpckhwd m1, m0, m0 + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m0, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + jl .w32_filter_h8 + vpblendd m3, m1, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m1, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + movzx r5d, word [tlq+62] + movzx r2d, word [tlq+60] + pavgw m2, m3 + sub r2d, r5d + paddw m0, m1 + lea r2d, [r2+r5*8+4] + paddw m0, m2 + shr r2d, 3 + psrlw m0, 2 + mova [r3+32], m0 + mov [r3+66], r5w + mov [r3+64], r2w + mov tlq, rsp + mov r3d, 65 + cmp hd, 64 + cmove maxbased, r3d + jmp .w32_main +.w32_filter_h8: + vpblendd xm3, xm1, [tlq+36], 0x07 ; 4 5 6 7 8 9 9 9 + vpblendd xm1, [tlq+34], 0x07 ; 3 4 5 6 7 8 9 9 + pavgw xm2, xm3 + paddw xm0, xm1 + mov tlq, rsp + paddw xm0, xm2 + psrlw xm0, 2 + mova [r3+32], xm0 +.w32_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r5d, dxd + vpbroadcastd m7, [pw_m1024] ; -16 * 64 + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + psubw m3, m0 +.w32_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + psraw m1, m3, 15 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*0], m0 + movu m0, [tlq+r3*2+32] + movu m1, [tlq+r3*2+34] + add r5d, dxd + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m7, m3 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+32*1], m0 + dec hd + jz .w32_end + add dstq, strideq + cmp r5d, maxbased + jb .w32_loop +.w32_end_loop: + mova [dstq+32*0], m6 + mova [dstq+32*1], m6 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + %assign stack_offset org_stack_offset + ALLOC_STACK -256, 10 + lea maxbased, [hq+63] + test angled, 0x400 + jnz .w64_main + vpbroadcastd m2, [pw_3] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + vpblendd m1, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m0, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m1, m2 + paddw m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pavgw m1, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + mov r3, rsp + paddw m0, m1 + lea r5d, [hq+32] + psrlw m0, 2 + mova [r3], m0 +.w64_filter_loop: + mova m0, [tlq+30] + paddw m1, m2, [tlq+28] + add tlq, 32 + paddw m0, [tlq+0] + pavgw m1, [tlq+4] + paddw m0, [tlq+2] + add r3, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r3], m0 + sub r5d, 16 + jg .w64_filter_loop + movu m0, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + punpckhwd m1, m0, m0 + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m0, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m1, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + pavgw m2, m3 + paddw m0, m1 + paddw m0, m2 + mov tlq, rsp + psrlw m0, 2 + mova [r3+32], m0 +.w64_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r5d, dxd + vpbroadcastd m7, [pw_m1024] ; -16 * 64 + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + paddw m8, m7, m7 ; -32 * 64 + psubw m3, m0 + paddw m9, m8, m7 ; -48 * 64 +.w64_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + psraw m1, m3, 15 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*0], m0 + movu m0, [tlq+r3*2+32] + movu m1, [tlq+r3*2+34] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m7, m3 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*1], m0 + movu m0, [tlq+r3*2+64] + movu m1, [tlq+r3*2+66] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m8, m3 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*2], m0 + movu m0, [tlq+r3*2+96] + movu m1, [tlq+r3*2+98] + add r5d, dxd + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m9, m3 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+32*3], m0 + dec hd + jz .w64_end + add dstq, strideq + cmp r5d, maxbased + jb .w64_loop +.w64_end_loop: + mova [dstq+32*0], m6 + mova [dstq+32*1], m6 + mova [dstq+32*2], m6 + mova [dstq+32*3], m6 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET + +cglobal ipred_z2_16bpc, 3, 12, 12, 352, dst, stride, tl, w, h, angle, dx, dy +%define base r9-z_filter_t0 + lea r9, [ipred_z2_16bpc_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea dxq, [dr_intra_derivative-90] + movsxd wq, [r9+wq*4] + mova m1, [tlq- 0] + movzx dyd, angleb + xor angled, 0x400 + mova m2, [tlq- 32] + mov r8, dxq + sub dxq, dyq + mova m3, [tlq- 64] + add wq, r9 + add r9, z_filter_t0-ipred_z2_16bpc_avx2_table + mova m4, [tlq- 96] + and dyd, ~1 + mova m5, [tlq-128] + and dxq, ~1 + movzx dyd, word [r8+dyq] ; angle - 90 + movzx dxd, word [dxq+270] ; 180 - angle + vpbroadcastd m11, [base+pw_62] + mova [rsp+128], m1 + mova [rsp+ 96], m2 + mova [rsp+ 64], m3 + neg dxd + mova [rsp+ 32], m4 + neg dyq + mova [rsp+ 0], m5 + jmp wq +.w4: + vbroadcasti128 m10, [base+z2_x_shuf] + vpbroadcastq m6, [base+z_base_inc+2] + lea r8d, [dxq+(65<<6)] ; xpos + mov r10d, (63-4)<<6 + test angled, 0x400 + jnz .w4_main ; !enable_intra_edge_filter + lea r3d, [hq+2] + add angled, 1022 + shl r3d, 6 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + movq xm0, [tlq+2] ; 1 2 3 4 + movq xm1, [tlq+0] ; 0 1 2 3 + pshuflw xm2, xm0, q3321 ; 2 3 4 4 + pshuflw xm3, xm1, q2100 ; 0 0 1 2 + vpbroadcastw xm4, r8m ; pixel_max + vbroadcasti128 m10, [base+z_upsample] + paddw xm1, xm0 + paddw xm2, xm3 + lea r8d, [r8+dxq+(1<<6)] + psubw xm2, xm1, xm2 + add dxd, dxd + psraw xm2, 3 + pxor xm3, xm3 + sub r10d, 3<<6 + paddw xm1, xm2 + paddw m6, m6 + pmaxsw xm1, xm3 + sub angled, 1075 ; angle - 53 + pavgw xm1, xm3 + lea r3d, [hq+3] + pminsw xm1, xm4 + xor angled, 0x7f ; 180 - angle + punpcklwd xm1, xm0 + movu [rsp+130], xm1 + call .filter_strength + jmp .w4_filter_left +ALIGN function_align +.filter_strength: + movd xm8, r3d + mov r3d, angled + movd xm7, angled + vpbroadcastb m8, xm8 + shr r3d, 8 ; is_sm << 1 + vpbroadcastb m7, xm7 + pcmpeqb m8, [base+z_filter_wh] + mova xm9, [r9+r3*8] + pand m0, m8, m7 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + ret +ALIGN function_align +.upsample_left: ; h4/h8 + mova xm0, [tlq-16] ; 8 7 6 5 4 3 2 1 + movu xm1, [tlq-14] ; 7 6 5 4 3 2 1 0 + vpbroadcastw xm4, r8m ; pixel_max + cmp hd, 8 + je .upsample_left_h8 + pshufhw xm2, xm0, q2100 ; _ _ _ _ 4 4 3 2 + pshufhw xm3, xm1, q3321 ; _ _ _ _ 2 1 0 0 + jmp .upsample_left_end +.upsample_left_h8: + pblendw xm2, xm0, [tlq-18], 0xfe ; 8 8 7 6 5 4 3 2 + pblendw xm3, xm1, [tlq-12], 0x7f ; 6 5 4 3 2 1 0 0 +.upsample_left_end: + paddw xm1, xm0 + paddw xm2, xm3 + psubw xm2, xm1, xm2 + add dyq, dyq + psraw xm2, 3 + pxor xm3, xm3 + paddw xm1, xm2 + pmaxsw xm1, xm3 + pavgw xm1, xm3 + pminsw xm1, xm4 + punpcklwd xm2, xm0, xm1 + punpckhwd xm0, xm1 + mova [rsp+ 96+gprsize], xm2 + mova [rsp+112+gprsize], xm0 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + sub angled, 1112 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w4_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*0] + psrldq xm0, xm1, 2 ; 1 2 3 4 + pshuflw xm2, xm1, q2100 ; 0 0 1 2 + pmullw xm4, xm0 + pshuflw xm3, xm0, q3321 ; 2 3 4 4 + paddw xm1, xm3 + pshuflw xm3, xm0, q3332 ; 3 4 4 4 + pmullw xm1, xm5 + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*2] + paddw xm2, xm3 + vpbroadcastd xm3, r6m ; max_width + pmullw xm2, xm5 + packssdw xm3, xm3 + paddw xm1, xm4 + paddw xm1, xm2 + psubw xm3, [base+pw_1to16] + pxor xm4, xm4 + psrlw xm1, 3 + pminsw xm3, xm11 ; clip to byte range since there's no variable word blend + pavgw xm1, xm4 + vpblendvb xm1, xm0, xm3 + movq [rsp+130], xm1 +.w4_no_filter_above: + lea r3d, [hq+2] + add angled, 973 ; angle + 883 + shl r3d, 6 + test r3d, angled + jz .w4_upsample_left ; angle <= 140 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm0, [base+pb_90] + psubb xm0, xm7 ; 180 - angle + pand xm0, xm8 ; reuse from previous filter_strength call + pcmpgtb xm0, xm9 + pmovmskb r3d, xm0 +.w4_filter_left: + test r3d, r3d + jz .w4_main + popcnt r3d, r3d + mova m0, [tlq-32] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + vpbroadcastd m5, r7m ; max_height + cmp r3d, 3 + je .w4_filter_left_s3 + vpbroadcastd m2, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pmullw m2, m0 + cmp hd, 8 + jl .w4_filter_left_h4 + movu m4, [tlq-34] + punpcklwd m1, m0, m0 + vpblendd m1, m4, 0xee ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + je .w4_filter_left_end + vpblendd m1, m4, 0x10 ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + jmp .w4_filter_left_end +.w4_upsample_left: + call .upsample_left + mov r11, -16 + vbroadcasti128 m9, [base+z_upsample] + jmp .w4_main_upsample_left +.w4_filter_left_s3: ; can only be h16 + movu m2, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m4, [base+pw_3] + paddw m1, m0, m2 + punpckhwd m2, m2 + vpblendd m2, [tlq-28], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + punpcklwd xm3, xm0, xm0 + paddw m2, m4 + vpblendd m4, m3, [tlq-34], 0xfe ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + vpblendd m3, [tlq-36], 0xfe ; 0 0 0 1 2 3 4 5 6 8 8 9 a b c d + paddw m1, m4 + pavgw m2, m3 + paddw m1, m2 + psrlw m1, 2 + jmp .w4_filter_left_end2 +.w4_filter_left_h4: + pshufhw m1, m0, q2100 ; _ _ _ _ _ _ _ _ _ _ _ _ c c d e +.w4_filter_left_end: + paddw m1, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m3 + paddw m1, m2 + pxor m2, m2 + psrlw m1, 3 + pavgw m1, m2 +.w4_filter_left_end2: + packssdw m5, m5 + psubw m5, [base+pw_16to1] + pminsw m5, m11 + vpblendvb m1, m0, m5 + mova [rsp+96], m1 +.w4_main: + vbroadcasti128 m9, [base+z2_x_shuf] + mov r11, -8 +.w4_main_upsample_left: + movd xm5, dyd + mova m4, [base+z2_y_shuf_h4] + mov r2d, r8d + movd xm0, dxd + vpbroadcastw m5, xm5 + rorx r5, dyq, 5 + lea r8d, [dyq*3] + pmullw m5, [base+z2_ymul] + rorx r9, dyq, 4 + sar dyd, 6 + vpbroadcastw m0, xm0 + sar r8d, 6 + pand m5, m11 ; frac_y + neg dyd + psllw m5, 9 + add r5d, dyd + add r8d, dyd + add r9d, dyd + paddw m7, m0, m0 + lea dyq, [rsp+dyq*2+126] + vpblendd m0, m7, 0xcc + add dyq, r11 + neg r5d + paddw m1, m0, m7 + neg r8d + vpblendd m0, m1, 0xf0 ; xpos0 xpos1 xpos2 xpos3 + neg r9d + paddw m7, m7 + paddw m6, m0 +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm1, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu xm3, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + vinserti128 m1, [rsp+r2*2], 1 + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + vinserti128 m3, [rsp+r3*2], 1 + pshufb m1, m10 ; a0 a1 a2 a3 A0 A1 A2 A3 + pshufb m3, m10 ; b0 b1 b2 b3 B0 B1 B2 B3 + pand m2, m11, m6 + punpcklqdq m0, m1, m3 + punpckhqdq m1, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w4_toponly + movu xm2, [dyq] + vinserti128 m2, [dyq+r8*2], 1 + movu xm3, [dyq+r5*2] + vinserti128 m3, [dyq+r9*2], 1 + pshufb m2, m9 + pshufb m3, m9 + punpckhwd m1, m2, m3 ; a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m2, m3 + psubw m2, m1 + pmulhrsw m2, m5 + psraw m3, m6, 15 ; base_x < topleft + paddw m1, m2 + vpermd m1, m4, m1 ; a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3 + vpblendvb m0, m1, m3 +.w4_toponly: + paddw m6, m7 ; xpos += dx + lea r3, [strideq*3] + add dyq, r11 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r2d, r10d + jge .w4_loop +.w4_leftonly_loop: + movu xm1, [dyq] + vinserti128 m1, [dyq+r8*2], 1 + movu xm2, [dyq+r5*2] + vinserti128 m2, [dyq+r9*2], 1 + add dyq, r11 + pshufb m1, m9 + pshufb m2, m9 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + psubw m1, m0 + pmulhrsw m1, m5 + paddw m0, m1 + vpermd m0, m4, m0 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + RET +.w8: + mov r10d, hd + test angled, 0x400 + jnz .w8_main + lea r3d, [angleq+126] + xor r8d, r8d + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + movu xm0, [tlq+2] ; 1 2 3 4 5 6 7 8 + mova xm1, [tlq+0] ; 0 1 2 3 4 5 6 7 + pblendw xm2, xm0, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 8 + pblendw xm3, xm1, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 + vpbroadcastw xm4, r8m ; pixel_max + paddw xm1, xm0 + paddw xm2, xm3 + not r8d + psubw xm2, xm1, xm2 + add dxd, dxd + psraw xm2, 3 + sub angled, 53 ; angle - 53 + pxor xm3, xm3 + paddw xm2, xm1 + lea r3d, [hq+7] + pmaxsw xm2, xm3 + xor angled, 0x7f ; 180 - angle + pavgw xm2, xm3 + pminsw xm2, xm4 + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 + movu [rsp+130], xm1 + movu [rsp+146], xm2 + call .filter_strength + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + sub angled, 90 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w8_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm6, [base+z_filter_k-4+r3*4+12*2] + movu xm0, [tlq+2] ; 1 2 3 4 5 6 7 8 x + pblendw xm2, xm1, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 x + pmullw xm4, xm0 + pblendw xm3, xm0, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 8 x + paddw xm1, xm3 + vpblendd xm3, [tlq+6], 0x07 ; 3 4 5 6 7 8 8 8 x + paddw xm2, xm3 + vpbroadcastd xm3, r6m ; max_width + pmullw xm1, xm5 + pmullw xm2, xm6 + packssdw xm3, xm3 + paddw xm1, xm4 + paddw xm1, xm2 + psubw xm3, [base+pw_1to16] + pxor xm4, xm4 + psrlw xm1, 3 + pminsw xm3, xm11 + pavgw xm1, xm4 + vpblendvb xm1, xm0, xm3 + movu [rsp+130], xm1 +.w8_no_filter_above: + lea r3d, [angleq-51] + mov r3b, hb + cmp r3d, 8 + jbe .w8_upsample_left ; angle > 140 && h <= 8 && !is_sm + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 +.w8_filter_left: + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + cmp r3d, 3 + jne .w8_filter_left_s12 + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m7, [base+pw_16] + cmp hd, 16 ; flags needed for later + jmp .filter_left_s3b +.w8_upsample_left: + call .upsample_left + vbroadcasti128 m7, [base+z2_y_shuf_us] + lea r11, [rsp+118] + mov r8, -8 + jmp .w8_main_upsample_left +.w16_filter_left_s12: + xor r8d, r8d +.w8_filter_left_s12: + mova m0, [tlq-32] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + vpbroadcastd m5, r7m ; max_height + vpbroadcastd m2, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pmullw m2, m0 + cmp hd, 8 + jl .w8_filter_left_h4 + movu m4, [tlq-34] + punpcklwd m1, m0, m0 + vpblendd m1, m4, 0xee ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + je .w8_filter_left_end + vpblendd m1, m4, 0x10 ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + jmp .w8_filter_left_end +.w8_filter_left_h4: + pshufhw m1, m0, q2100 ; _ _ _ _ _ _ _ _ _ _ _ _ c c d e +.w8_filter_left_end: + paddw m1, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m3 + paddw m1, m2 + pxor m2, m2 + psrlw m1, 3 + pavgw m1, m2 + packssdw m5, m5 + psubw m5, [base+pw_16to1] + pminsw m5, m11 + vpblendvb m1, m0, m5 + mova [rsp+96], m1 + test r8d, r8d + jz .w8_main +; upsample_main + vbroadcasti128 m10, [base+z_upsample] + vbroadcasti128 m7, [base+z2_y_shuf] + lea r5, [rsp+120] + movd xm1, dyd + vbroadcasti128 m4, [base+z_base_inc+2] + movd xm2, dxd + vpbroadcastw m1, xm1 + vpbroadcastw m2, xm2 + mov r7, dstq + paddw m4, m4 + pmullw m0, m1, [base+z2_ymul8] + paddw m5, m2, m2 + psllw xm1, 3 + vpblendd m2, m5, 0xf0 + lea r2d, [dxq+(66<<6)] ; xpos + paddw m4, m2 + pshufd m6, m0, q2020 + psraw xm0, 6 + pxor xm1, xm1 + psubw xm8, xm1, xm0 + pand m6, m11 + punpckhwd xm9, xm8, xm1 + psllw m6, 9 + punpcklwd xm8, xm1 +.w8_upsample_above_loop: + lea r3d, [r2+dxq] + shr r2d, 6 + movu xm1, [rsp+r2*2] + movu xm2, [rsp+r2*2+16] + lea r2d, [r3+dxq] + shr r3d, 6 + vinserti128 m1, [rsp+r3*2], 1 + vinserti128 m2, [rsp+r3*2+16], 1 + pshufb m1, m10 + pshufb m2, m10 + punpcklqdq m0, m1, m2 ; a0 b0 c0 d0 e0 f0 g0 h0 + punpckhqdq m1, m2 + pand m2, m11, m4 + psubw m1, m0 + psllw m2, 9 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w8_upsample_above_toponly + mova m1, m5 + vpgatherdq m3, [r5+xm9*2], m5 + mova m5, m1 + vpgatherdq m2, [r5+xm8*2], m1 + pshufb m3, m7 + pshufb m2, m7 + punpckldq m1, m2, m3 + punpckhdq m2, m3 + psubw m2, m1 + pmulhrsw m2, m6 + paddw m1, m2 + vpermq m1, m1, q3120 + psraw m2, m4, 15 + vpblendvb m0, m1, m2 +.w8_upsample_above_toponly: + paddw m4, m5 + sub r5, 4 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_ret + lea dstq, [dstq+strideq*2] + jmp .w8_upsample_above_loop +.w8_main: + vbroadcasti128 m7, [base+z2_y_shuf] + lea r11, [rsp+120] + mov r8, -4 +.w8_main_upsample_left: + movd xm1, dyd + vbroadcasti128 m4, [base+z_base_inc+2] + movd xm2, dxd + vpbroadcastw m1, xm1 + vpbroadcastw m2, xm2 + mov r7, dstq + pmullw m0, m1, [base+z2_ymul8] + paddw m5, m2, m2 + psllw xm1, 3 + vpblendd m2, m5, 0xf0 ; xpos0 xpos1 + lea r9d, [dxq+(65<<6)] ; xpos + paddw m4, m2 + movd [rsp+284], xm1 +.w8_loop0: + mov r2d, r9d + mova [rsp+288], m0 + mov r5, r11 + mova [rsp+320], m4 + pshufd m6, m0, q2020 + psraw xm0, 6 + pxor xm1, xm1 + psubw xm8, xm1, xm0 ; base_y + pand m6, m11 ; frac_y + punpckhwd xm9, xm8, xm1 ; base_y 2 3 6 7 + psllw m6, 9 + punpcklwd xm8, xm1 ; base_y 0 1 4 5 +.w8_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2*2] + movu xm1, [rsp+r2*2+2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vinserti128 m0, [rsp+r3*2], 1 + vinserti128 m1, [rsp+r3*2+2], 1 + pand m2, m11, m4 + psubw m1, m0 + psllw m2, 9 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w8_toponly + mova m1, m5 + vpgatherdq m3, [r5+xm9*2], m5 + mova m5, m1 + vpgatherdq m2, [r5+xm8*2], m1 + pshufb m3, m7 ; c0 d0 c1 d1 g0 h0 g1 h1 + pshufb m2, m7 ; a0 b0 a1 b1 e0 f0 e1 f1 + punpckldq m1, m2, m3 ; a0 b0 c0 d0 a1 b1 c1 d1 e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m2, m3 + psubw m2, m1 + pmulhrsw m2, m6 + paddw m1, m2 + vpermq m1, m1, q3120 + psraw m2, m4, 15 ; base_x < topleft + vpblendvb m0, m1, m2 +.w8_toponly: + paddw m4, m5 ; xpos += dx + add r5, r8 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r2d, (63-8)<<6 + jge .w8_loop +.w8_leftonly_loop: + mova m0, m5 + vpgatherdq m4, [r5+xm9*2], m5 + mova m5, m0 + vpgatherdq m3, [r5+xm8*2], m0 + add r5, r8 + pshufb m2, m4, m7 + pshufb m1, m3, m7 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + psubw m1, m0 + pmulhrsw m1, m6 + paddw m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_leftonly_loop +.w8_end: + sub r10d, 1<<8 + jl .w8_ret + vpbroadcastd m0, [rsp+284] + add r7, 16 + paddw m0, [rsp+288] ; base_y += 8*dy + add r9d, 8<<6 + vpbroadcastd m4, [pw_512] + movzx hd, r10b + paddw m4, [rsp+320] ; base_x += 8*64 + mov dstq, r7 + jmp .w8_loop0 +.w8_ret: + RET +.w16: + movd xm0, [tlq+32] + lea r10d, [hq+(1<<8)] + movd [rsp+160], xm0 + test angled, 0x400 + jnz .w8_main + lea r3d, [hq+15] + sub angled, 90 + call .filter_strength + test r3d, r3d + jz .w16_no_filter_above + popcnt r3d, r3d + vpbroadcastd m4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m5, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m6, [base+z_filter_k-4+r3*4+12*2] + movu m0, [tlq+2] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + punpcklwd xm2, xm1, xm1 + vpblendd m2, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + punpckhwd m3, m0, m0 + pmullw m4, m0 + vpblendd m3, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + paddw m1, m3 + vpblendd m3, [tlq+6], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g g g + paddw m2, m3 + vpbroadcastd m3, r6m ; max_width + pmullw m1, m5 + pmullw m2, m6 + packssdw m3, m3 + paddw m1, m4 + paddw m1, m2 + psubw m3, [base+pw_1to16] + pxor m4, m4 + psrlw m1, 3 + pminsw m3, m11 + pavgw m1, m4 + vpblendvb m1, m0, m3 + movu [rsp+130], m1 +.w16_no_filter_above: + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + cmp r3d, 3 + jne .w16_filter_left_s12 + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m7, [base+pw_16] + cmp hd, 4 + jne .filter_left_s3 + movq xm0, [tlq-8] ; 0 1 2 3 + movq xm1, [tlq-6] ; 1 2 3 4 + vpbroadcastd xm5, r7m ; max_height + movq xm4, [base+pw_16to1+24] ; 4to1 + pshuflw xm2, xm0, q2100 ; 0 0 1 2 + pshuflw xm3, xm1, q3321 ; 2 3 4 4 + paddw xm1, xm0 + paddw xm1, xm2 + pshuflw xm2, xm0, q1000 ; 0 0 0 1 + paddw xm3, xm6 + packssdw xm5, xm5 + pavgw xm2, xm3 + psubw xm5, xm4 + paddw xm1, xm2 + pminsw xm5, xm11 + psrlw xm1, 2 + vpblendvb xm1, xm0, xm5 + movq [rsp+120], xm1 + jmp .w8_main +.w32: + mova m2, [tlq+32] + movd xm0, [tlq+64] + lea r10d, [hq+(3<<8)] + mova [rsp+160], m2 + movd [rsp+192], xm0 + test angled, 0x400 + jnz .w8_main + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m0, r6m ; max_width + vpbroadcastd m7, [base+pw_16] + mov r3d, 32 + packssdw m0, m0 + psubw m0, [base+pw_1to16] + pminsw m8, m0, m11 + psubw m9, m8, m7 +.w32_filter_above: + movu m0, [tlq+2] + punpcklwd xm4, xm1, xm1 + paddw m2, m6, [tlq+6] + paddw m1, m0 + vpblendd m4, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m1, [tlq+4] + movu m3, [tlq+r3+2] + paddw m5, m6, [tlq+r3-2] + pavgw m2, m4 + punpckhwd m4, m3, m3 + paddw m1, m2 + vpblendd m2, m4, [tlq+r3+6], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m4, [tlq+r3+4], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + pavgw m2, m5 + paddw m5, m3, [tlq+r3] + paddw m4, m5 + psrlw m1, 2 + paddw m2, m4 + vpblendvb m1, m0, m8 + psrlw m2, 2 + vpblendvb m2, m3, m9 + movu [rsp+130], m1 + movu [rsp+r3+130], m2 +.filter_left_s3: + cmp hd, 16 + jl .filter_left_s3_h8 ; h8 +.filter_left_s3b: + mova m0, [tlq-32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + movu m2, [tlq-30] ; 3 4 5 6 7 8 9 a b c d e f g h i + vpbroadcastd m5, r7m ; max_height + paddw m1, m0, m2 + punpckhwd m2, m2 + mov r3d, hd + vpblendd m2, [tlq-28], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + packssdw m5, m5 + not r3 + psubw m5, [base+pw_16to1] + paddw m2, m6 + pminsw m8, m11, m5 + je .filter_left_s3_end ; h16 + paddw m1, [tlq-34] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m2, [tlq-36] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m2 + psrlw m1, 2 + vpblendvb m3, m1, m0, m8 + mova m0, [tlq-64] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m0, [tlq-62] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m2, m6, [tlq-60] ; 4 5 6 7 8 9 a b c d e f g h i j + psubw m8, m7 + mova [rsp+96], m3 + jnp .filter_left_s3_end ; h32 + mova m5, [tlq-96] + paddw m1, [tlq-66] + pavgw m2, [tlq-68] + paddw m1, m2 + paddw m4, m5, [tlq-94] + paddw m2, m6, [tlq-92] + psrlw m1, 2 + paddw m4, [tlq- 98] + pavgw m2, [tlq-100] + vpblendvb m3, m1, m0, m8 + mova m0, [tlq-128] + psubw m8, m7 + paddw m4, m2 + paddw m1, m0, [tlq-126] + paddw m2, m6, [tlq-124] + psrlw m4, 2 + mova [rsp+64], m3 + vpblendvb m4, m5, m8 + psubw m8, m7 + mova [rsp+32], m4 +.filter_left_s3_end: + punpcklwd xm3, xm0, xm0 + vpblendd m4, m3, [tlq+r3*2], 0xfe ; 2 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, [tlq+r3*2-2], 0xfe ; 2 2 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m4 + pavgw m2, m3 + paddw m1, m2 + psrlw m1, 2 + vpblendvb m1, m0, m8 + mova [rsp+r3*2+130], m1 + jmp .w8_main +.filter_left_s3_h8: + mova xm0, [tlq-16] ; 0 1 2 3 4 5 6 7 + movu xm3, [tlq-14] ; 1 2 3 4 5 6 7 8 + pblendw xm2, xm0, [tlq-18], 0xfe ; 0 0 1 2 3 4 5 6 + vpbroadcastd xm5, r7m ; max_height + paddw xm1, xm0, xm3 + pblendw xm3, [tlq-12], 0x7f ; 2 3 4 5 6 7 8 8 + paddw xm1, xm2 + vpblendd xm2, [tlq-20], 0x0e ; 0 0 0 1 2 3 4 5 + paddw xm3, xm6 + packssdw xm5, xm5 + pavgw xm2, xm3 + psubw xm5, [base+pw_16to1+16] ; 8to1 + paddw xm1, xm2 + pminsw xm5, xm11 + psrlw xm1, 2 + vpblendvb xm1, xm0, xm5 + mova [rsp+112], xm1 + jmp .w8_main +.w64: + mova m2, [tlq+ 32] + mova m3, [tlq+ 64] + mova m4, [tlq+ 96] + movd xm0, [tlq+128] + lea r10d, [hq+(7<<8)] + mova [rsp+160], m2 + mova [rsp+192], m3 + mova [rsp+224], m4 + movd [rsp+256], xm0 + test angled, 0x400 + jnz .w8_main + vpbroadcastd m6, [base+pw_3] + movu m0, [tlq+34] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m2, m6, [tlq+30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m5, m0, [tlq+32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m2, [tlq+38] ; 4 5 6 7 8 9 a b c d e f g h h h + paddw m5, [tlq+36] ; 3 4 5 6 7 8 9 a b c d e f g h h + movu m4, [tlq+66] + paddw m3, m6, [tlq+62] + paddw m7, m4, [tlq+64] + pavgw m3, [tlq+70] + paddw m7, [tlq+68] + paddw m2, m5 + vpbroadcastd m5, r6m ; max_width + mov r3d, 96 + packssdw m5, m5 + paddw m3, m7 + psubw m5, [base+pw_1to16] + psrlw m2, 2 + vpbroadcastd m7, [base+pw_16] + psrlw m3, 2 + pminsw m8, m11, m5 + psubw m9, m8, m7 + vpblendvb m2, m0, m9 + psubw m9, m7 + vpblendvb m3, m4, m9 + psubw m9, m7 + movu [rsp+162], m2 + movu [rsp+194], m3 + jmp .w32_filter_above + +cglobal ipred_z3_16bpc, 4, 9, 0, dst, stride, tl, w, h, angle, dy, org_w, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z3_16bpc_avx2_table] + tzcnt hd, hm + movifnidn angled, anglem + lea r7, [dr_intra_derivative+45*2-1] + sub tlq, 2 + movsxd hq, [r6+hq*4] + sub angled, 180 + add hq, r6 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + movzx dyd, word [r7+dyq] + vpbroadcastd m5, [pw_62] + mov org_wd, wd + jmp hq +.h4: + ALLOC_STACK -64, 7 + lea r7, [strideq*3] + cmp angleb, 40 + jae .h4_no_upsample + lea r4d, [angleq-1024] + sar r4d, 7 + add r4d, wd + jg .h4_no_upsample ; !enable_intra_edge_filter || w > 8 || (w == 8 && is_sm) + mova xm2, [tlq-14] ; 0 1 2 3 4 5 6 7 + pblendw xm1, xm2, [tlq-16], 0xfe ; 0 0 1 2 3 4 5 6 + vpblendd xm0, xm1, [tlq-18], 0x0e ; 0 0 0 1 2 3 4 5 + pshufd xm3, xm1, q0000 + paddw xm1, xm2 + paddw xm0, [tlq-12] ; 1 2 3 4 5 6 7 8 + vpbroadcastw xm4, r8m ; pixel_max + add dyd, dyd + psubw xm0, xm1, xm0 + mova [rsp+ 0], xm3 + movd xm3, dyd + psraw xm0, 3 + neg dyd + paddw xm1, xm0 + pxor xm0, xm0 + lea r2d, [dyq+(16<<6)+63] ; ypos + pmaxsw xm1, xm0 + pavgw xm1, xm0 + vpbroadcastw m3, xm3 + pminsw xm1, xm4 + punpckhwd xm0, xm1, xm2 + punpcklwd xm1, xm2 + paddw m2, m3, m3 + mova [rsp+32], xm0 + punpcklwd m3, m2 + mova [rsp+16], xm1 + paddw m4, m2, m2 + paddw m2, m3 + vpblendd m3, m2, 0xf0 ; ypos0 ypos1 ypos2 ypos3 +.h4_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 + movu xm1, [rsp+r2*2] + lea r2d, [r4+dyq] + shr r4d, 6 + movu xm2, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 + vinserti128 m1, [rsp+r2*2], 1 + lea r2d, [r4+dyq] + shr r4d, 6 + vinserti128 m2, [rsp+r4*2], 1 + psrld m0, m1, 16 + pblendw m0, m2, 0xaa ; a3 b3 a2 b2 a1 b1 a0 b0 c3 d3 c2 d2 c1 d1 c0 d0 + pslld m2, 16 + pblendw m1, m2, 0xaa + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m3, m4 + paddw m1, m0 + vextracti128 xm2, m1, 1 + punpckhdq xm0, xm1, xm2 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq xm1, xm2 ; a3 b3 c3 d3 a2 b2 c2 d2 + movhps [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movhps [dstq+strideq*2], xm1 + movq [dstq+r7 ], xm1 + add dstq, 8 + sub wd, 4 + jg .h4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; h4/h8/h16 +%define base r4-z_filter_t0 + lea r4, [z_filter_t0] + movd xm0, maxbased + movd xm1, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m1, xm1 + pcmpeqb m0, [base+z_filter_wh] + pand m0, m1 + mova xm1, [r4+angleq*8] + pcmpgtb m0, m1 + pmovmskb r5d, m0 + ret +.h4_no_upsample: + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea maxbased, [wq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + popcnt r5d, r5d + mova xm0, [tlq-14] ; 0 1 2 3 4 5 6 7 + movu xm3, [tlq-12] ; 1 2 3 4 5 6 7 8 + vpbroadcastd xm2, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd xm4, [base+z_filter_k-4+r5*4+12*0] + pmullw xm2, xm0 + pblendw xm0, [tlq-16], 0xfe ; 0 0 1 2 3 4 5 6 + paddw xm1, xm0, xm3 + movd [rsp+12], xm0 + pmullw xm1, xm4 + cmp r5d, 3 + jne .h4_filter_3tap + pblendw xm3, [tlq-10], 0x7f ; 2 3 4 5 6 7 8 8 + vpblendd xm0, [tlq-18], 0x0e ; 0 0 0 1 2 3 4 5 + movzx r4d, word [tlq-14] + movzx r2d, word [tlq-12] + inc maxbased + paddw xm1, xm2 + paddw xm0, xm3 + sub r2d, r4d + paddw xm2, xm0, xm0 + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+14], r2w +.h4_filter_3tap: + pxor xm0, xm0 + paddw xm1, xm2 + lea tlq, [rsp+30] + psrlw xm1, 3 + cmp wd, 8 + sbb maxbased, -1 + pavgw xm0, xm1 + mova [rsp+16], xm0 +.h4_main: + movd xm3, dyd + neg maxbaseq + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m3, xm3 + lea r4d, [maxbaseq+3*64] + neg dyq + movd xm2, r4d + sub tlq, 8 + lea r4, [dyq+63] ; ypos + punpcklwd m1, m1 + paddw m0, m3, m3 + vpbroadcastw m2, xm2 + punpcklwd m3, m0 + paddw m4, m0, m0 + paddw m0, m3 + psubw m2, m1 + vpblendd m3, m0, 0xf0 ; ypos0 ypos1 ypos2 ypos3 + or maxbased, 63 + paddw m3, m2 +.h4_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu xm1, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + movu xm2, [tlq+r5*2] + lea r5, [r4+dyq] + sar r4, 6 ; base2 + vinserti128 m1, [tlq+r4*2], 1 + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vinserti128 m2, [tlq+r5*2], 1 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + pand m2, m5, m3 + palignr m0, m1, 4 ; a3 b3 a2 b2 a1 b1 a0 b0 c3 d3 c2 d2 c1 d1 c0 d0 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 ; ypos < max_base_y + paddw m3, m4 + paddw m1, m0 + vpblendvb m1, m6, m1, m2 + vextracti128 xm2, m1, 1 + punpckhdq xm0, xm1, xm2 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq xm1, xm2 ; a3 b3 c3 d3 a2 b2 c2 d2 + movhps [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movhps [dstq+strideq*2], xm1 + movq [dstq+r7 ], xm1 + sub wd, 4 + jz .h4_end + add dstq, 8 + cmp r4d, maxbased + jg .h4_loop +.h4_end_loop: + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + movq [dstq+strideq*2], xm6 + movq [dstq+r7 ], xm6 + add dstq, 8 + sub wd, 4 + jg .h4_end_loop +.h4_end: + RET +.h8: + lea r4d, [angleq+216] + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 8 + mov r4b, wb + lea r7, [strideq*3] + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m2, [tlq-30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m2, [tlq-32] ; _ 0 1 2 3 4 5 6 7 8 9 a b c d e + movu m0, [tlq-34] ; _ _ 0 1 2 3 4 5 6 7 8 9 a b c d + cmp wd, 8 + je .h8_upsample_w8 + pshufhw xm3, xm2, q1000 + vpblendd m0, m3, 0x0f ; _ _ _ _ 4 4 4 5 6 7 8 9 a b c d +.h8_upsample_w8: + paddw m0, [tlq-28] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastw m4, r8m ; pixel_max + add dyd, dyd + psubw m0, m1, m0 + movd xm6, dyd + psraw m0, 3 + neg dyd + paddw m1, m0 + pxor m0, m0 + pmaxsw m1, m0 + lea r4d, [dyq+(16<<6)+63] ; ypos + pavgw m1, m0 + vpbroadcastw m6, xm6 + pminsw m1, m4 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + vextracti128 [rsp+48], m0, 1 + vextracti128 [rsp+32], m1, 1 + paddw m7, m6, m6 + mova [rsp+16], xm0 + mova [rsp+ 0], xm1 + punpcklwd m6, m7 ; ypos0 ypos1 +.h8_upsample_loop: + lea r2d, [r4+dyq] + shr r4d, 6 ; base0 + movu m1, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 ; base1 + movu m2, [rsp+r2*2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base2 + movu m3, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 ; base3 + movu m4, [rsp+r2*2] + psrld m0, m1, 16 + pblendw m0, m2, 0xaa ; a7 b7 a6 b6 a5 b5 a4 b4 a3 b3 a2 b2 a1 b1 a0 b0 + pslld m2, 16 + pblendw m1, m2, 0xaa + psrld m2, m3, 16 + pblendw m2, m4, 0xaa ; c7 d7 c6 d6 c5 d5 c4 d4 c3 d3 c2 d2 c1 d1 c0 d0 + pslld m4, 16 + pblendw m3, m4, 0xaa + pand m4, m5, m6 + paddw m6, m7 + psllw m4, 9 + psubw m1, m0 + pmulhrsw m1, m4 + pand m4, m5, m6 + psllw m4, 9 + psubw m3, m2 + pmulhrsw m3, m4 + paddw m6, m7 + lea r2, [dstq+strideq*4] + paddw m1, m0 + paddw m3, m2 + punpckhdq m0, m1, m3 ; a5 b5 c5 d5 a4 b4 c4 d4 a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq m1, m3 ; a7 b7 c7 d7 a6 b6 c6 d6 a3 b3 c3 d3 a2 b2 c2 d2 + vextracti128 xm2, m0, 1 + vextracti128 xm3, m1, 1 + movhps [r2 +strideq*0], xm0 + movq [r2 +strideq*1], xm0 + movhps [r2 +strideq*2], xm1 + movq [r2 +r7 ], xm1 + movhps [dstq+strideq*0], xm2 + movq [dstq+strideq*1], xm2 + movhps [dstq+strideq*2], xm3 + movq [dstq+r7 ], xm3 + add dstq, 8 + sub wd, 4 + jg .h8_upsample_loop + RET +.h8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(w+7, 15) + jmp .h8_main +.h8_no_upsample: + lea maxbased, [wq+7] + test angled, 0x400 + jnz .h8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h8_main + popcnt r5d, r5d + mova m0, [tlq-30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movu m3, [tlq-28] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m2, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + pmullw m2, m0 + cmp wd, 8 + jl .h8_filter_w4 + punpcklwd xm0, xm0 + vpblendd m1, m0, [tlq-32], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movd [rsp+28], xm0 + paddw m1, m3 + mov r4d, 16 + pmullw m1, m4 + cmovg maxbased, r4d + cmp r5d, 3 + jne .h8_filter_3tap + punpckhwd m3, m3 + vpblendd m0, [tlq-34], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m3, [tlq-26], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + movzx r4d, word [tlq-30] + movzx r2d, word [tlq-28] + inc maxbased + paddw m1, m2 + paddw m0, m3 + sub r2d, r4d + paddw m2, m0, m0 + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+30], r2w + jmp .h8_filter_3tap +.h8_filter_w4: + pshufhw xm1, xm0, q2100 + vinserti128 m1, [tlq-16], 1 ; _ _ _ _ 4 4 5 6 7 8 9 a b c d e + paddw m1, m3 + pmullw m1, m4 +.h8_filter_3tap: + pxor m0, m0 + paddw m1, m2 + lea tlq, [rsp+62] + psrlw m1, 3 + pavgw m0, m1 + mova [rsp+32], m0 +.h8_main: + movd xm4, dyd + neg maxbaseq + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m7, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + lea r4d, [maxbaseq+7*64] + neg dyq + movd xm2, r4d + sub tlq, 16 + lea r4, [dyq+63] + paddw m6, m4, m4 + vpbroadcastw m2, xm2 + vpblendd m4, m6, 0xf0 ; ypos0 ypos1 + psubw m2, m1 + or maxbased, 63 + paddw m4, m2 +.h8_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu xm0, [tlq+r4*2+2] + movu xm1, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + vinserti128 m0, [tlq+r5*2+2], 1 + vinserti128 m1, [tlq+r5*2], 1 + lea r5, [r4+dyq] + sar r4, 6 ; base2 + pand m3, m5, m4 + psllw m3, 9 + psubw m1, m0 + pmulhrsw m1, m3 + psraw m3, m4, 15 + paddw m4, m6 + paddw m0, m1 + movu xm1, [tlq+r4*2+2] + movu xm2, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vpblendvb m0, m7, m0, m3 + vinserti128 m1, [tlq+r5*2+2], 1 + vinserti128 m2, [tlq+r5*2], 1 + pand m3, m5, m4 + psllw m3, 9 + psubw m2, m1 + pmulhrsw m2, m3 + psraw m3, m4, 15 + paddw m4, m6 + lea r5, [dstq+strideq*4] + paddw m1, m2 + vpblendvb m1, m7, m1, m3 + punpckhwd m2, m0, m1 ; a3 c3 a2 c2 a1 c1 a0 c0 b3 d3 b2 d2 b1 d1 b0 d0 + vextracti128 xm3, m2, 1 + punpcklwd m0, m1 ; a7 c7 a6 c6 a5 c5 a4 c5 b7 d7 b6 d6 b5 d5 b4 d4 + punpckhwd xm1, xm2, xm3 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpcklwd xm2, xm3 ; a3 b3 c3 d3 a2 b2 c2 d2 + vextracti128 xm3, m0, 1 + movhps [dstq+strideq*0], xm1 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movq [dstq+r7 ], xm2 + punpckhwd xm1, xm0, xm3 ; a5 b5 c5 d5 a4 b4 c4 d4 + punpcklwd xm0, xm3 ; a7 b7 c7 d7 a6 b6 c6 d6 + movhps [r5 +strideq*0], xm1 + movq [r5 +strideq*1], xm1 + movhps [r5 +strideq*2], xm0 + movq [r5 +r7 ], xm0 + sub wd, 4 + jz .h8_end + add dstq, 8 + cmp r4d, maxbased + jg .h8_loop + lea r6, [strideq*5] + lea r2, [strideq+r7*2] ; stride*7 + test wd, 4 + jz .h8_end_loop + movq [dstq+strideq*0], xm7 + movq [dstq+strideq*1], xm7 + movq [dstq+strideq*2], xm7 + movq [dstq+r7 ], xm7 + movq [dstq+strideq*4], xm7 + movq [dstq+r6 ], xm7 + movq [dstq+r7*2 ], xm7 + movq [dstq+r2 ], xm7 + add dstq, 8 + sub wd, 4 + jz .h8_end +.h8_end_loop: + mova [dstq+strideq*0], xm7 + mova [dstq+strideq*1], xm7 + mova [dstq+strideq*2], xm7 + mova [dstq+r7 ], xm7 + mova [dstq+strideq*4], xm7 + mova [dstq+r6 ], xm7 + mova [dstq+r7*2 ], xm7 + mova [dstq+r2 ], xm7 + add dstq, 16 + sub wd, 8 + jg .h8_end_loop +.h8_end: + RET +.h16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(w+15, 31) + jmp .h16_main +ALIGN function_align +.h16: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 10 + lea maxbased, [wq+15] + lea r7, [strideq*3] + test angled, 0x400 + jnz .h16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h16_main ; filter_strength == 0 + popcnt r5d, r5d + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m1, m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m6, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pmullw m2, m6, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pmullw m1, m7 + paddw m1, m2 + cmp wd, 8 + jg .h16_filter_w16 + mova xm3, [tlq-46] ; 0 1 2 3 4 5 6 7 + pmullw xm6, xm3 + jl .h16_filter_w4 + pblendw xm3, [tlq-48], 0xfe ; 0 0 1 2 3 4 5 6 + cmp r5d, 3 + jne .h16_filter_w8_3tap + vpblendd xm4, xm3, [tlq-50], 0x0e ; 0 0 0 1 2 3 4 5 +.h16_filter_w8_5tap: + punpckhwd m0, m0 + vpblendd m0, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw xm4, [tlq-42] ; 2 3 4 5 6 7 8 9 + paddw m0, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw xm4, xm4 + paddw m0, m0 + paddw xm6, xm4 + paddw m1, m0 +.h16_filter_w8_3tap: + paddw xm3, [tlq-44] ; 1 2 3 4 5 6 7 8 + pmullw xm3, xm7 + pxor m0, m0 + paddw xm3, xm6 + psrlw xm3, 3 + pavgw xm3, xm0 + mova [rsp+48], xm3 + jmp .h16_filter_end +.h16_filter_w4: + pshufhw xm3, xm3, q2100 ; _ _ _ _ 4 4 5 6 + cmp r5d, 3 + jne .h16_filter_w8_3tap + pshufhw xm4, xm3, q2100 ; _ _ _ _ 4 4 4 5 + jmp .h16_filter_w8_5tap +.h16_filter_w16: + mova m3, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + pmullw m6, m3 + punpcklwd xm3, xm3 + vpblendd m4, m3, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m4, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + mov r4d, 32 + cmp wd, 16 + cmovg maxbased, r4d + movd [rsp+28], xm3 + pmullw m4, m7 + cmp r5d, 3 + jne .h16_filter_w16_3tap + punpckhwd m0, m0 + vpblendd m3, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m0, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m3, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movzx r4d, word [tlq-62] + movzx r2d, word [tlq-60] + or maxbased, 1 + paddw m3, m3 + sub r2d, r4d + paddw m0, m0 + lea r2d, [r2+r4*8+4] + paddw m4, m3 + shr r2d, 3 + paddw m1, m0 + mov [rsp+30], r2w +.h16_filter_w16_3tap: + pxor m0, m0 + paddw m4, m6 + psrlw m4, 3 + pavgw m4, m0 + mova [rsp+32], m4 +.h16_filter_end: + psrlw m1, 3 + lea tlq, [rsp+94] + pavgw m1, m0 + mova [rsp+64], m1 +.h16_main: + movd xm8, dyd + neg maxbaseq + vpbroadcastw m9, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m8, xm8 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + movd xm7, r4d + sub tlq, 32 + lea r4, [dyq+63] + vpbroadcastw m7, xm7 + or maxbased, 63 + psubw m7, [z_base_inc] +.h16_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu m0, [tlq+r4*2+2] + movu m2, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + movu m1, [tlq+r5*2+2] + movu m3, [tlq+r5*2] + lea r5, [r4+dyq] + sar r4, 6 ; base3 + pand m6, m5, m7 + psllw m6, 9 + psubw m2, m0 + pmulhrsw m2, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m0, m2 + movu m2, [tlq+r4*2+2] + movu m4, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vpblendvb m0, m9, m0, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m3, m1 + pmulhrsw m3, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m1, m3 + vpblendvb m1, m9, m1, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m4, m2 + pmulhrsw m4, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m2, m4 + movu m3, [tlq+r5*2+2] + movu m4, [tlq+r5*2] + vpblendvb m2, m9, m2, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m4, m3 + pmulhrsw m4, m6 + psraw m6, m7, 15 + paddw m7, m8 + lea r5, [dstq+strideq*4] + paddw m3, m4 + vpblendvb m3, m9, m3, m6 + punpckhwd m4, m0, m1 ; ab bb aa ba a9 b9 a8 b8 a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m0, m1 ; af bf ae be ad bd ac bc a7 b7 a6 b6 a5 b5 a4 b4 + punpckhwd m1, m2, m3 ; cb db ca da c9 d9 c8 d8 c3 d3 c2 d2 c1 d1 c0 d0 + punpcklwd m2, m3 ; cf df ce de cd dd cc dc c7 d7 c6 d6 c5 d5 c4 d4 + punpckhdq m3, m4, m1 ; a9 b9 c9 d9 a8 b8 c8 d8 a1 b1 c1 d1 a0 b0 c0 d0 + vextracti128 xm6, m3, 1 + punpckldq m4, m1 ; ab bb cb db aa ba ca da a3 b3 c3 d3 a2 b2 c2 d2 + punpckhdq m1, m0, m2 ; ad bd cd dd ac bc cc dc a5 b5 c5 d5 a4 b4 c4 d4 + punpckldq m0, m2 ; af bf cf df ae be ce de a7 b7 c7 d7 a6 b6 c6 d6 + vextracti128 xm2, m4, 1 + movhps [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + vextracti128 xm6, m1, 1 + movhps [dstq+strideq*2], xm2 + movq [dstq+r7 ], xm2 + vextracti128 xm2, m0, 1 + movhps [r5 +strideq*0], xm6 + movq [r5 +strideq*1], xm6 + movhps [r5 +strideq*2], xm2 + movq [r5 +r7 ], xm2 + lea r5, [dstq+strideq*8] + movhps [r5 +strideq*0], xm3 + movq [r5 +strideq*1], xm3 + movhps [r5 +strideq*2], xm4 + movq [r5 +r7 ], xm4 + lea r5, [r5+strideq*4] + movhps [r5 +strideq*0], xm1 + movq [r5 +strideq*1], xm1 + movhps [r5 +strideq*2], xm0 + movq [r5 +r7 ], xm0 + sub wd, 4 + jz .h16_end + add dstq, 8 + cmp r4d, maxbased + jg .h16_loop + mov hd, 4 +.h16_end_loop0: + mov r6d, wd + mov r2, dstq + test wb, 4 + jz .h16_end_loop + movq [dstq+strideq*0], xm9 + movq [dstq+strideq*1], xm9 + movq [dstq+strideq*2], xm9 + movq [dstq+r7 ], xm9 + and r6d, 120 + jz .h16_end_w4 + add dstq, 8 +.h16_end_loop: + mova [dstq+strideq*0], xm9 + mova [dstq+strideq*1], xm9 + mova [dstq+strideq*2], xm9 + mova [dstq+r7 ], xm9 + add dstq, 16 + sub r6d, 8 + jg .h16_end_loop +.h16_end_w4: + lea dstq, [r2+strideq*4] + dec hd + jg .h16_end_loop0 +.h16_end: + RET +.h32: + %assign stack_offset org_stack_offset + ALLOC_STACK -160, 9 + lea maxbased, [wq+31] + and maxbased, 31 + or maxbased, 32 ; imin(w+31, 63) + test angled, 0x400 + jnz .h32_main + vpbroadcastd m2, [pw_3] + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + punpckhwd m1, m0, m0 + vpblendd m1, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m0, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m2 + paddw m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m1, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + lea r4, [rsp+128] + paddw m0, m1 + lea r5d, [maxbaseq-31] + psrlw m0, 2 + mova [r4], m0 +.h32_filter_loop: + mova m0, [tlq-62] + paddw m1, m2, [tlq-66] + paddw m0, [tlq-64] + pavgw m1, [tlq-58] + paddw m0, [tlq-60] + sub tlq, 32 + sub r4, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r4], m0 + sub r5d, 16 + jg .h32_filter_loop + jl .h32_filter_h8 + mova m0, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + paddw m2, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m1, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movzx r5d, word [tlq-62] + movzx r2d, word [tlq-60] + pavgw m2, m3 + sub r2d, r5d + paddw m0, m1 + lea r2d, [r2+r5*8+4] + paddw m0, m2 + shr r2d, 3 + psrlw m0, 2 + mova [r4-32], m0 + mov [r4-36], r5w + mov [r4-34], r2w + lea tlq, [rsp+158] + mov r4d, 65 + cmp wd, 64 + cmove maxbased, r4d + jmp .h32_main +.h32_filter_h8: + mova xm0, [tlq-46] ; 0 1 2 3 4 5 6 7 + pblendw xm1, xm0, [tlq-48], 0xfe ; 0 0 1 2 3 4 5 6 + paddw xm2, [tlq-42] ; 2 3 4 5 6 7 8 9 + paddw xm0, [tlq-44] ; 1 2 3 4 5 6 7 8 + vpblendd xm3, xm1, [tlq-50], 0x0e ; 0 0 0 1 2 3 4 5 + lea tlq, [rsp+158] + pavgw xm2, xm3 + paddw xm0, xm1 + paddw xm0, xm2 + psrlw xm0, 2 + mova [r4-16], xm0 +.h32_main: + movd xm6, dyd + neg maxbaseq + vpbroadcastw m7, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m6, xm6 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + movd xm4, r4d + vpbroadcastd m8, [pw_m1024] + lea r4, [dyq+63] + vpbroadcastw m4, xm4 + or maxbased, 63 + psubw m4, [z_base_inc] +.h32_loop: + mov r5, r4 + sar r5, 6 + movu m1, [tlq+r5*2-64] + movu m0, [tlq+r5*2-62] + pand m3, m5, m4 + psllw m3, 9 + psubw m1, m0 + pmulhrsw m1, m3 + pcmpgtw m2, m8, m4 + paddw m0, m1 + vpblendvb m0, m7, m0, m2 + movu m2, [tlq+r5*2-32] + movu m1, [tlq+r5*2-30] + add r4, dyq + sub rsp, 64 + psubw m2, m1 + pmulhrsw m2, m3 + psraw m3, m4, 15 + paddw m4, m6 + mova [rsp+32*0], m0 + paddw m1, m2 + vpblendvb m1, m7, m1, m3 + mova [rsp+32*1], m1 + dec wd + jz .h32_transpose + cmp r4d, maxbased + jg .h32_loop +.h32_end_loop: + sub rsp, 64 + mova [rsp+32*0], m7 + mova [rsp+32*1], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + lea r3, [strideq*3] + lea r4, [strideq*5] + mov r8, dstq + lea r5, [strideq+r3*2] +.h32_transpose_loop0: + lea r6, [rsp+32] + lea r2, [r8+org_wq*2-16] +.h32_transpose_loop: + mova m0, [r6+64*7] + mova m1, [r6+64*6] + mova m2, [r6+64*5] + mova m3, [r6+64*4] + mova m4, [r6+64*3] + mova m5, [r6+64*2] + mova m6, [r6+64*1] + mova m7, [r6+64*0] + punpckhwd m8, m0, m1 ; a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m0, m1 ; a7 b7 a6 b6 a5 b5 a4 b4 + punpckhwd m1, m2, m3 ; c3 d3 c2 d2 c1 d1 c0 d0 + punpcklwd m2, m3 ; c7 d7 c6 d6 c5 d5 c4 d4 + punpckhwd m3, m4, m5 ; e3 f3 e2 f2 e1 f1 e0 f0 + punpcklwd m4, m5 ; e7 f7 e6 f6 e5 f5 e4 f4 + punpckhwd m5, m6, m7 ; g3 h3 g2 h2 g1 h1 g0 h0 + punpcklwd m6, m7 ; g7 h7 g6 h6 g5 h5 g4 h4 + lea dstq, [r2+strideq*8] + sub r6, 32 + punpckhdq m7, m8, m1 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq m8, m1 ; a3 b3 c3 d3 a2 b2 c2 d2 + punpckhdq m1, m3, m5 ; e1 f1 g1 h1 e0 f0 g0 h0 + punpckldq m3, m5 ; e3 f3 g3 h3 e2 f2 g2 h2 + punpckhqdq m5, m7, m1 ; 8 0 + vextracti128 [r2 +strideq*0], m5, 1 + punpcklqdq m7, m1 ; 9 1 + mova [dstq+strideq*0], xm5 + punpckhqdq m1, m8, m3 ; 10 2 + vextracti128 [r2 +strideq*1], m7, 1 + punpcklqdq m8, m3 ; 11 3 + mova [dstq+strideq*1], xm7 + punpckhdq m3, m0, m2 ; a5 b5 c5 d5 a4 b4 c4 d4 + vextracti128 [r2 +strideq*2], m1, 1 + punpckldq m0, m2 ; a7 b7 c7 d7 a6 b6 c6 d6 + mova [dstq+strideq*2], xm1 + punpckhdq m2, m4, m6 ; e5 f5 g5 h5 e4 f4 g4 h4 + vextracti128 [r2 +r3 ], m8, 1 + punpckldq m4, m6 ; e7 f7 g7 h7 e6 f6 g6 h6 + mova [dstq+r3 ], xm8 + punpckhqdq m6, m3, m2 ; 12 4 + vextracti128 [r2 +strideq*4], m6, 1 + punpcklqdq m3, m2 ; 13 5 + mova [dstq+strideq*4], xm6 + punpckhqdq m2, m0, m4 ; 14 6 + vextracti128 [r2 +r4 ], m3, 1 + punpcklqdq m0, m4 ; 15 7 + mova [dstq+r4 ], xm3 + vextracti128 [r2 +r3*2 ], m2, 1 + mova [dstq+r3*2 ], xm2 + vextracti128 [r2 +r5 ], m0, 1 + mova [dstq+r5 ], xm0 + lea r2, [dstq+strideq*8] + cmp r6, rsp + jae .h32_transpose_loop + add rsp, 64*8 + sub org_wd, 8 + jg .h32_transpose_loop0 +.h32_end: + RET +.h64: + %assign stack_offset org_stack_offset + ALLOC_STACK -256, 10 + lea maxbased, [wq+63] + test angled, 0x400 + jnz .h64_main + vpbroadcastd m2, [pw_3] + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + punpckhwd m1, m0, m0 + vpblendd m1, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m0, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m2 + paddw m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m1, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + lea r4, [rsp+224] + paddw m0, m1 + lea r5d, [wq+32] + psrlw m0, 2 + mova [r4], m0 +.h64_filter_loop: + mova m0, [tlq-62] + paddw m1, m2, [tlq-66] + paddw m0, [tlq-64] + pavgw m1, [tlq-58] + paddw m0, [tlq-60] + sub tlq, 32 + sub r4, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r4], m0 + sub r5d, 16 + jg .h64_filter_loop + mova m0, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + paddw m2, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m1, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + lea tlq, [rsp+254] + pavgw m2, m3 + paddw m0, m1 + paddw m0, m2 + psrlw m0, 2 + mova [r4-32], m0 +.h64_main: + neg maxbaseq + movd xm4, dyd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + vpbroadcastd m7, [pw_m1024] + movd xm3, r4d + lea r4, [dyq+63] + paddw m8, m7, m7 + vpbroadcastw m3, xm3 + or maxbased, 63 + paddw m9, m8, m7 + psubw m3, [z_base_inc] +.h64_loop: + mov r5, r4 + sar r5, 6 + movu m1, [tlq+r5*2-128] + movu m0, [tlq+r5*2-126] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + sub rsp, 128 + paddw m0, m1 + pcmpgtw m1, m9, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*0], m0 + movu m1, [tlq+r5*2-96] + movu m0, [tlq+r5*2-94] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m8, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*1], m0 + movu m1, [tlq+r5*2-64] + movu m0, [tlq+r5*2-62] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m7, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*2], m0 + movu m1, [tlq+r5*2-32] + movu m0, [tlq+r5*2-30] + psubw m1, m0 + pmulhrsw m1, m2 + add r4, dyq + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [rsp+32*3], m0 + dec wd + jz .h64_transpose + cmp r4d, maxbased + jg .h64_loop +.h64_end_loop: + sub rsp, 128 + mova [rsp+32*0], m6 + mova [rsp+32*1], m6 + mova [rsp+32*2], m6 + mova [rsp+32*3], m6 + dec wd + jg .h64_end_loop +.h64_transpose: + lea r2, [strideq*3] + lea r3, [strideq*5] + mov r5, dstq + lea r4, [strideq+r2*2] +.h64_transpose_loop0: + lea r6, [rsp+112] + lea dstq, [r5+org_wq*2-32] +.h64_transpose_loop: + mova xm0, [r6+128*15] + vinserti128 m0, [r6+128* 7], 1 + mova xm1, [r6+128*14] + vinserti128 m1, [r6+128* 6], 1 + mova xm2, [r6+128*13] + vinserti128 m2, [r6+128* 5], 1 + mova xm3, [r6+128*12] + vinserti128 m3, [r6+128* 4], 1 + mova xm4, [r6+128*11] + vinserti128 m4, [r6+128* 3], 1 + mova xm5, [r6+128*10] + vinserti128 m5, [r6+128* 2], 1 + mova xm6, [r6+128* 9] + vinserti128 m6, [r6+128* 1], 1 + mova xm7, [r6+128* 8] + vinserti128 m7, [r6+128* 0], 1 + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m6, m7 + punpcklwd m6, m7 + sub r6, 16 + punpckhdq m7, m8, m1 + punpckldq m8, m1 + punpckhdq m1, m3, m5 + punpckldq m3, m5 + punpckhqdq m5, m7, m1 + punpcklqdq m7, m1 + punpckhqdq m1, m8, m3 + punpcklqdq m8, m3 + punpckhdq m3, m0, m2 + mova [dstq+strideq*0], m5 + punpckldq m0, m2 + mova [dstq+strideq*1], m7 + punpckhdq m2, m4, m6 + mova [dstq+strideq*2], m1 + punpckldq m4, m6 + mova [dstq+r2 ], m8 + punpckhqdq m6, m3, m2 + mova [dstq+strideq*4], m6 + punpcklqdq m3, m2 + mova [dstq+r3 ], m3 + punpckhqdq m2, m0, m4 + mova [dstq+r2*2 ], m2 + punpcklqdq m0, m4 + mova [dstq+r4 ], m0 + lea dstq, [dstq+strideq*8] + cmp r6, rsp + jae .h64_transpose_loop + add rsp, 128*16 + sub org_wd, 16 + jg .h64_transpose_loop0 +.h64_end: + RET + +%macro FILTER_1BLK 5 ; dst, src, tmp, shuf, bdmax +%ifnum %4 + pshufb xm%2, xm%4 +%else + pshufb xm%2, %4 +%endif + vinserti128 m%2, xm%2, 1 + pshufd m%1, m%2, q0000 + pmaddwd m%1, m2 + pshufd m%3, m%2, q1111 + pmaddwd m%3, m3 + paddd m%1, m1 + paddd m%1, m%3 + pshufd m%3, m%2, q2222 + pmaddwd m%3, m4 + paddd m%1, m%3 + pshufd m%3, m%2, q3333 + pmaddwd m%3, m5 + paddd m%1, m%3 + psrad m%1, 4 + packusdw m%1, m%1 + pminsw m%1, m%5 +%endmacro + +%macro FILTER_2BLK 7 ; dst, src, tmp_dst, tmp_src, tmp, shuf, bdmax + pshufb m%2, m%6 + vpermq m%4, m%2, q3232 + vinserti128 m%2, xm%2, 1 + pshufd m%1, m%2, q0000 + pshufd m%3, m%4, q0000 + pmaddwd m%1, m2 + pmaddwd m%3, m2 + paddd m%1, m1 + paddd m%3, m1 + pshufd m%5, m%2, q1111 + pmaddwd m%5, m3 + paddd m%1, m%5 + pshufd m%5, m%4, q1111 + pmaddwd m%5, m3 + paddd m%3, m%5 + pshufd m%5, m%2, q2222 + pmaddwd m%5, m4 + paddd m%1, m%5 + pshufd m%5, m%4, q2222 + pmaddwd m%5, m4 + paddd m%3, m%5 + pshufd m%5, m%2, q3333 + pmaddwd m%5, m5 + paddd m%1, m%5 + pshufd m%5, m%4, q3333 + pmaddwd m%5, m5 + paddd m%3, m%5 + psrad m%1, 4 + psrad m%3, 4 + packusdw m%1, m%3 + pminsw m%1, m%7 +%endmacro + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. One redundant +; block is calculated for w8 and w16, two for w32. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 5 1 2 3 5 b c d f +; 2 2 3 2 4 5 7 2 4 5 7 c e f h +; 3 3 4 4 6 7 9 4 6 7 9 e g h j +; ___ 4 ___ 4 5 ___ 6 8 9 a ___ 6 8 9 a g i j k ___ +; 5 8 8 i + +cglobal ipred_filter_16bpc, 3, 9, 0, dst, stride, tl, w, h, filter +%assign org_stack_offset stack_offset +%define base r6-ipred_filter_16bpc_avx2_table + lea r6, [filter_intra_taps] + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + add filterq, r6 + lea r6, [ipred_filter_16bpc_avx2_table] + vbroadcasti128 m0, [tlq-6] + movsxd wq, [r6+wq*4] + vpbroadcastd m1, [base+pd_8] + pmovsxbw m2, [filterq+16*0] + pmovsxbw m3, [filterq+16*1] + pmovsxbw m4, [filterq+16*2] + pmovsxbw m5, [filterq+16*3] + add wq, r6 + mov hd, hm + jmp wq +.w4: + WIN64_SPILL_XMM 10 + mova xm8, [base+filter_shuf2] + vpbroadcastw m9, r8m ; bitdepth_max + lea r7, [6+hq*2] + sub tlq, r7 + jmp .w4_loop_start +.w4_loop: + pinsrq xm0, [tlq+hq*2], 0 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER_1BLK 6, 0, 7, 8, 9 + vextracti128 xm0, m6, 1 + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm0 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vbroadcasti128 m14, [base+filter_shuf3] + vpbroadcastw m15, r8m ; bitdepth_max + FILTER_1BLK 10, 0, 7, [base+filter_shuf2], 15 + vpermq m6, m10, q1302 ; ____ ____ | ____ 4321 + pslldq m8, m0, 4 + psrldq m7, m6, 2 + psrldq m0, m6, 10 + punpcklwd m7, m0 + vpblendd m8, m6, 0x33 ; _0__ 4321 | ____ 4321 + vpblendd m8, m7, 0x40 ; _056 4321 | ____ 4321 + vpblendd m8, [tlq-6], 0x30 ; _056 4321 | ____ 4321 + lea r7, [16+hq*2] + sub tlq, r7 + jmp .w8_loop_start +.w8_loop: + vpermq m8, m9, q1302 ; ____ 4321 | ____ 4321 + vpermq m6, m9, q2031 + psrldq m0, m6, 2 + psrldq m6, 10 + punpcklwd m6, m0 + vpblendd m8, m7, 0x80 ; _0__ 4321 | ____ 4321 + vpblendd m8, m6, 0x40 ; _056 4321 | ____ 4321 + mova m10, m9 +.w8_loop_start: + vpblendd m8, [tlq+hq*2], 0x0C ; _056 4321 | _056 4321 + call .main + vpblendd m10, m9, 0xCC + mova [dstq+strideq*0], xm10 + vextracti128 [dstq+strideq*1], m10, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + %assign stack_offset stack_offset - stack_size_padded + ALLOC_STACK 32, 16 + vpbroadcastw m15, r8m ; bitdepth_max + sub hd, 2 + TAIL_CALL .w16_main, 0 +.w16_main: + mova xm10, [base+filter_shuf2] + FILTER_1BLK 13, 0, 6, 10, 15 + vpermq m12, m13, q3120 + mova xm14, [base+filter_shuf3] + vinserti128 m14, [base+filter_shuf1], 1 + vpbroadcastq m0, [tlq+10] + vpblendd m0, [tlq-16], 0x4C ; ___0 4321 | _056 ____ + psrldq m6, m12, 8 + vpblendd m0, m6, 0x03 ; ___0 4321 | _056 4321 + punpcklwd m6, m12 + vpblendd m0, m6, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 12, 0, 6, 7, 8, 14, 15 + vpblendd m13, m12, 0xCC + vpermq m12, m12, q2031 ; 6___ 5___ + psrldq xm6, xm12, 2 + psrldq xm8, xm12, 12 + vpblendd xm6, xm8, 0x01 + pblendw xm6, [tlq+10], 0xF8 ; 4321 056_ + FILTER_1BLK 11, 6, 8, 10, 15 + vpermq m11, m11, q3120 + pshufd m9, m11, q1032 + movu m8, [tlq+6] ; __43 210_ | ____ ____ + pshufd m8, m8, q3021 ; __0_ 4321 | ____ ____ + pshufhw m8, m8, q3201 ; ___0 4321 | ____ ____ + vpblendd m9, m8, 0x70 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 + lea r7, [20+hq*2] + sub tlq, r7 + vpermq m6, m12, q0123 ; ____ 4321 | ____ 4321 + jmp .w16_loop_start +.w16_loop: + vpermq m13, m13, q3322 + vpermq m11, m9, q2020 + vpermq m9, m9, q1302 + vpermq m6, m12, q0123 + psrldq m7, 4 + vpblendd m13, m10, 0xCC + vpblendd m9, m7, 0x40 + mova m0, [rsp+8] + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 +.w16_loop_start: + mova m13, m12 + vpblendd m0, [tlq+hq*2], 0x0C + psrldq m7, m12, 8 + punpcklwd m7, m12 + vpblendd m0, m6, 0x33 ; ___0 4321 | _056 4321 + vpblendd m0, m7, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 10, 0, 6, 7, 8, 14, 15 + vpermq m12, m10, q2031 + mova [rsp+8], m0 + psrldq m8, m11, 8 + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 10 + psrldq xm0, xm13, 2 + punpcklwd m8, m11 + punpcklwd xm7, xm6 + vpblendd m8, m9, 0x73 ; 56_0 4321 | ____ 4321 + vpblendd m8, m7, 0x04 ; 56_0 4321 | __56 4321 + vpblendd m8, m0, 0x08 ; 56_0 4321 | _056 4321 + call .main + vpermq m8, m11, q3120 + vpblendd m6, m8, m9, 0xCC + mova [dstq+strideq*0+16], xm6 + vextracti128 [dstq+strideq*1+16], m6, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + vpermq m8, m9, q3120 + vextracti128 xm0, m8, 1 ; 4321 ____ + pshufd xm11, xm11, q1032 + vpblendd xm0, xm11, 0x02 ; 4321 0___ + psrldq xm6, xm8, 2 + psrldq xm7, xm8, 12 + pblendw xm0, xm6, 0x4 ; 4321 05__ + pblendw xm0, xm7, 0x2 ; 4321 056_ + FILTER_1BLK 6, 0, 7, [base+filter_shuf2], 15 + vpermq m12, m13, q1302 + vpblendd m12, m10, 0xCC + vpblendd m9, m6, 0xCC + mova [dstq+strideq*0+ 0], xm12 + mova [dstq+strideq*0+16], xm9 + vextracti128 [dstq+strideq*1+ 0], m12, 1 + vextracti128 [dstq+strideq*1+16], m9, 1 + ret +ALIGN function_align +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK 64, 16 + vpbroadcastw m15, r8m ; bitdepth_max + sub hd, 2 + lea r3, [dstq+32] + lea r5d, [hd*2+20] + call .w16_main + mov dstq, r3 + lea tlq, [tlq+r5+32] + sub r5d, 20 + shr r5d, 1 + sub r5d, 2 + lea r4, [dstq+strideq*2-2] +DEFINE_ARGS dst, stride, tl, stride3, left, h + lea stride3q, [strideq*3] + movu m8, [tlq-6] ; 4321 0___ + mova xm10, [base+filter_shuf2] + pinsrw xm0, xm8, [dstq+strideq*0-2], 2 + pinsrw xm0, xm0, [dstq+strideq*1-2], 1 ; 4321 056_ + pinsrw xm9, [leftq+strideq*0], 5 + pinsrw xm9, [leftq+strideq*1], 4 + FILTER_1BLK 13, 0, 6, 10, 15 + vpermq m12, m13, q3120 + mova xm14, [base+filter_shuf3] + vinserti128 m14, [base+filter_shuf1], 1 + psrldq m6, m12, 8 + punpcklwd m7, m6, m12 + vpblendd m0, m6, 0x03 ; ___0 ____ | _0__ 4321 + vpblendd m0, m7, 0x80 ; 56_0 ____ | _0__ 4321 + vpblendd m0, m8, 0x30 ; 56_0 4321 | _0__ 4321 + vpblendd m0, m9, 0x04 ; 56_0 4321 | _056 4321 + FILTER_2BLK 12, 0, 6, 7, 8, 14, 15 + vpblendd m13, m12, 0xCC + pinsrw xm9, [leftq+strideq*2], 3 + pinsrw xm9, [leftq+stride3q ], 2 + lea leftq, [leftq+strideq*4] + pinsrw xm9, [leftq+strideq*0], 1 + pinsrw xm9, [leftq+strideq*1], 0 + movq [rsp+32], xm9 + mov r7d, 1 + pslldq m8, m9, 4 + vpblendd m0, m8, 0x0C ; ___0 ____ | _056 ____ + vpermq m12, m12, q2031 ; 6___ 5___ + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 12 + vpblendd xm6, xm7, 0x01 ; ____ _56_ + pblendw xm6, [tlq+10], 0xF8 ; 4321 056_ + FILTER_1BLK 11, 6, 7, 10, 15 + vpermq m11, m11, q3120 + pshufd m9, m11, q1032 + vbroadcasti128 m8, [tlq+22] ; __43 210_ | ____ ____ + pshufd m8, m8, q3021 ; __0_ 4321 | ____ ____ + pshufhw m8, m8, q3201 ; ___0 4321 | ____ ____ + vpblendd m9, m8, 0x70 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 + vpermq m6, m12, q0123 ; ____ 4321 | ____ 4321 + jmp .w32_loop_start +.w32_loop_last: + mova m0, [rsp+0] + jmp .w32_loop +.w32_loop_left: + mova m0, [rsp+0] + vpblendd m0, [rsp+32+r7*4-12], 0x0C + dec r7d + jg .w32_loop + cmp hd, 2 + je .w32_loop + pinsrw xm6, [rsp+32], 6 + pinsrw xm6, [leftq+strideq*2], 5 + pinsrw xm6, [leftq+stride3q ], 4 + lea leftq, [leftq+strideq*4] + pinsrw xm6, [leftq+strideq*0], 3 + pinsrw xm6, [leftq+strideq*1], 2 + pinsrw xm6, [leftq+strideq*2], 1 + pinsrw xm6, [leftq+stride3q ], 0 + lea leftq, [leftq+strideq*4] + movu [rsp+36], xm6 + pinsrw xm6, [leftq+strideq*0], 1 + pinsrw xm6, [leftq+strideq*1], 0 + movd [rsp+32], xm6 + mov r7d, 4 +.w32_loop: + vpermq m13, m13, q3322 + vpermq m11, m9, q2020 + vpermq m9, m9, q1302 + vpermq m6, m12, q0123 + psrldq m7, 4 + vpblendd m13, m10, 0xCC + vpblendd m9, m7, 0x40 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 +.w32_loop_start: + mova m13, m12 + psrldq m7, m12, 8 + punpcklwd m7, m12 + vpblendd m0, m6, 0x33 ; ___0 4321 | _056 4321 + vpblendd m0, m7, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 10, 0, 6, 7, 8, 14, 15 + vpermq m12, m10, q2031 + mova [rsp+0], m0 + psrldq m8, m11, 8 + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 10 + psrldq xm0, xm13, 2 + punpcklwd m8, m11 + punpcklwd xm7, xm6 + vpblendd m8, m9, 0x73 ; 56_0 4321 | ____ 4321 + vpblendd m8, m7, 0x04 ; 56_0 4321 | __56 4321 + vpblendd m8, m0, 0x08 ; 56_0 4321 | _056 4321 + call .main + vpermq m8, m11, q3120 + vpblendd m6, m8, m9, 0xCC + mova [dstq+strideq*0+16], xm6 + vextracti128 [dstq+strideq*1+16], m6, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop_left + jz .w32_loop_last + vpermq m8, m9, q3120 + vextracti128 xm0, m8, 1 ; 4321 ____ + pshufd xm11, xm11, q1032 + vpblendd xm0, xm11, 0x02 ; 4321 0___ + psrldq xm6, xm8, 2 + psrldq xm7, xm8, 12 + pblendw xm0, xm6, 0x4 ; 4321 05__ + pblendw xm0, xm7, 0x2 ; 4321 056_ + FILTER_1BLK 6, 0, 7, [base+filter_shuf2], 15 + vpermq m12, m13, q1302 + vpblendd m12, m10, 0xCC + vpblendd m9, m6, 0xCC + mova [dstq+strideq*0+ 0], xm12 + mova [dstq+strideq*0+16], xm9 + vextracti128 [dstq+strideq*1+ 0], m12, 1 + vextracti128 [dstq+strideq*1+16], m9, 1 + RET +.main: + FILTER_2BLK 9, 8, 6, 7, 0, 14, 15 + ret + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +cglobal ipred_cfl_top_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + add tlq, 2 + movd xm4, wd + pxor m6, m6 + vpbroadcastw m7, r7m + pavgw xm4, xm6 + tzcnt wd, wd + movd xm5, wd + movu m0, [tlq] + lea t0, [ipred_cfl_left_16bpc_avx2_table] + movsxd r6, [t0+wq*4] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_avx2_table-ipred_cfl_left_16bpc_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +cglobal ipred_cfl_left_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + sub tlq, hq + movd xm4, hd + sub tlq, hq + pxor m6, m6 + vpbroadcastw m7, r7m + pavgw xm4, xm6 + tzcnt r6d, hd + movd xm5, r6d + movu m0, [tlq] + lea t0, [ipred_cfl_left_16bpc_avx2_table] + movsxd r6, [t0+r6*4] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_avx2_table-ipred_cfl_left_16bpc_avx2_table + tzcnt wd, wd + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + paddw m0, [tlq+32] +.h16: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h8: + psrldq xm1, xm0, 8 + paddw xm0, xm1 +.h4: + punpcklwd xm0, xm6 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + paddd xm0, xm4 + psrld xm0, xm5 + vpbroadcastw m0, xm0 + jmp wq + +cglobal ipred_cfl_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd xm4, t0d + tzcnt t0d, t0d + movd xm5, t0d + lea t0, [ipred_cfl_16bpc_avx2_table] + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + psrlw xm4, 1 + pxor m6, m6 + vpbroadcastw m7, r7m + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movq xm0, [tlq-8] + jmp wq +.w4: + movq xm1, [tlq+2] + paddw m0, m4 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrld m1, m0, 16 + paddw m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + lea r2d, [hq*2] + mov r6d, 0xAAAB6667 + shrx r6d, r6d, r2d + punpckhwd xm1, xm0, xm6 + punpcklwd xm0, xm6 + paddd xm0, xm1 + movd xm1, r6d + psrld xm0, 2 + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w4_end: + vpbroadcastw m0, xm0 +.s4: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + IPRED_CFL 4 + pmaxsw m4, m6 + pminsw m4, m7 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*2], xm5 + movhps [dstq+strideq*1], xm4 + movhps [dstq+r6 ], xm5 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + mova xm0, [tlq-16] + jmp wq +.w8: + vextracti128 xm1, m0, 1 + paddw xm0, [tlq+2] + paddw xm0, xm4 + paddw xm0, xm1 + psrld xm1, xm0, 16 + paddw xm0, xm1 + pblendw xm0, xm6, 0xAA + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w8_end: + vpbroadcastw m0, xm0 +.s8: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+strideq*0], xm4 + mova [dstq+strideq*2], xm5 + vextracti128 [dstq+strideq*1], m4, 1 + vextracti128 [dstq+r6 ], m5, 1 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova m0, [tlq-32] + jmp wq +.w16: + paddw m0, [tlq+2] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpckhwd xm1, xm0, xm6 + punpcklwd xm0, xm6 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+strideq*0], m4 + mova [dstq+strideq*1], m5 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-32] + jmp wq +.w32: + paddw m0, [tlq+ 2] + paddw m0, [tlq+34] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm6 + punpckhwd xm0, xm6 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x6667AAAB + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w32_end: + vpbroadcastw m0, xm0 +.s32: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+32*0], m4 + mova [dstq+32*1], m5 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + mov r6d, r7m + shr r6d, 11 + lea t0, [ipred_cfl_splat_16bpc_avx2_table] + tzcnt wd, wd + movifnidn hd, hm + movsxd wq, [t0+wq*4] + vpbroadcastd m0, [t0-ipred_cfl_splat_16bpc_avx2_table+pw_512+r6*4] + pxor m6, m6 + vpbroadcastw m7, r7m + add wq, t0 + movifnidn acq, acmp + jmp wq + +cglobal ipred_cfl_ac_420_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_2] + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + jg .w16 + je .w8 +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + mova xm0, [ypxq+strideq*2] + mova xm1, [ypxq+r3 ] + vinserti128 m0, [ypxq+strideq*0], 1 + vinserti128 m1, [ypxq+strideq*1], 1 + lea ypxq, [ypxq+strideq*4] + pmaddwd m0, m5 + pmaddwd m1, m5 + paddd m0, m1 + vextracti128 xm1, m0, 1 + paddd m4, m0 + packssdw xm1, xm0 + mova [acq], xm1 + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .dc + vpermq m1, m1, q1111 + pslld xm0, 2 +.w4_hpad_loop: + mova [acq], m1 + paddd m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .dc +.w8: + mov r5, acq + test wpadd, wpadd + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + vextracti128 xm1, m0, 1 + paddd m4, m0 + packssdw xm1, xm0, xm1 + mova [acq], xm1 + add acq, 16 + dec hd + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz .dc + vinserti128 m1, xm1, 1 + pslld m0, 2 + jmp .hpad +.w8_wpad1: + pmaddwd xm0, xm5, [ypxq+strideq*0] + pmaddwd xm3, xm5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd xm0, xm3 + pshufd xm3, xm0, q3333 + packssdw xm1, xm0, xm3 + paddd xm0, xm3 + paddd xm4, xm0 + mova [acq], xm1 + add acq, 16 + dec hd + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad: + mova m0, [ypxq+strideq*0+ 0] + mova m1, [ypxq+strideq*1+ 0] + cmp wpadd, 2 + jl .w16_wpad1 + je .w16_wpad2 + vpbroadcastd m2, [ypxq+strideq*0+12] + vpbroadcastd m3, [ypxq+strideq*1+12] + vpblendd m0, m2, 0xf0 + vpblendd m1, m3, 0xf0 + jmp .w16_wpad_end +.w16_wpad2: + vpbroadcastd m2, [ypxq+strideq*0+28] + vpbroadcastd m3, [ypxq+strideq*1+28] + jmp .w16_wpad_end +.w16_wpad1: + vpbroadcastd m2, [ypxq+strideq*0+44] + vpbroadcastd m3, [ypxq+strideq*1+44] + vinserti128 m2, [ypxq+strideq*0+32], 0 + vinserti128 m3, [ypxq+strideq*1+32], 0 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + REPX {pmaddwd x, m5}, m0, m1, m2, m3 + paddd m0, m1 + paddd m2, m3 + packssdw m1, m0, m2 + paddd m0, m2 + vpermq m1, m1, q3120 + paddd m4, m0 + mova [acq], m1 + add acq, 32 + dec hd + jg .w16_wpad + jmp .w16_hpad +.w16: + mov r5, acq + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmaddwd m0, m5, [ypxq+strideq*0+ 0] + pmaddwd m2, m5, [ypxq+strideq*0+32] + pmaddwd m1, m5, [ypxq+strideq*1+ 0] + pmaddwd m3, m5, [ypxq+strideq*1+32] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + paddd m2, m3 + packssdw m1, m0, m2 + paddd m0, m2 + vpermq m1, m1, q3120 + paddd m4, m0 + mova [acq], m1 + add acq, 32 + dec hd + jg .w16_loop +.w16_hpad: + add hpadd, hpadd + jz .dc + paddd m0, m0 +.hpad: + mova [acq+32*0], m1 + paddd m4, m0 + mova [acq+32*1], m1 + add acq, 32*2 + sub hpadd, 4 + jg .hpad +.dc: + vextracti128 xm1, m4, 1 + sub r5, acq ; -w*h*2 + tzcnt r1d, r5d + paddd xm4, xm1 + sub r1d, 2 + punpckhqdq xm1, xm4, xm4 + movd xm0, r1d + paddd xm1, xm4 + pshuflw xm4, xm1, q1032 + paddd xm1, xm4 + psrld xm1, xm0 + pxor xm0, xm0 + pavgw xm1, xm0 + vpbroadcastw m1, xm1 +.dc_loop: + mova m0, [acq+r5] + psubw m0, m1 + mova [acq+r5], m0 + add r5, 32 + jl .dc_loop + RET + +cglobal ipred_cfl_ac_422_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_4] + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + jg .w16 + je .w8 +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + mova xm0, [ypxq+strideq*0] + mova xm1, [ypxq+strideq*1] + vinserti128 m0, [ypxq+strideq*2], 1 + vinserti128 m1, [ypxq+r3 ], 1 + lea ypxq, [ypxq+strideq*4] + pmaddwd m0, m5 + pmaddwd m1, m5 + paddd m4, m0 + packssdw m0, m1 + paddd m4, m1 + mova [acq], m0 + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vextracti128 xm1, m1, 1 + vpermq m0, m0, q3333 + pslld xm1, 2 +.w4_hpad_loop: + mova [acq], m0 + paddd m4, m1 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w8: + mov r5, acq + test wpadd, wpadd + jnz .w8_wpad1 +.w8_loop: + pmaddwd m1, m5, [ypxq+strideq*0] + pmaddwd m0, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m4, m1 + packssdw m1, m0 + paddd m4, m0 + vpermq m2, m1, q3120 + mova [acq], m2 + add acq, 32 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vpermq m1, m1, q3131 + pslld m0, 2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w8_wpad1: + vpbroadcastd m1, [ypxq+strideq*0+12] + vpbroadcastd m0, [ypxq+strideq*1+12] + vinserti128 m1, [ypxq+strideq*0+ 0], 0 + vinserti128 m0, [ypxq+strideq*1+ 0], 0 + lea ypxq, [ypxq+strideq*2] + pmaddwd m1, m5 + pmaddwd m0, m5 + paddd m4, m1 + packssdw m1, m0 + paddd m4, m0 + vpermq m2, m1, q3120 + mova [acq], m2 + add acq, 32 + sub hd, 2 + jg .w8_wpad1 + jmp .w8_hpad +.w16: + mov r5, acq + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmaddwd m2, m5, [ypxq+strideq*0+ 0] + pmaddwd m1, m5, [ypxq+strideq*0+32] + pmaddwd m0, m5, [ypxq+strideq*1+ 0] + pmaddwd m3, m5, [ypxq+strideq*1+32] + lea ypxq, [ypxq+strideq*2] + paddd m4, m2 + packssdw m2, m1 + paddd m4, m1 + packssdw m1, m0, m3 + paddd m0, m3 + vpermq m2, m2, q3120 + paddd m4, m0 + vpermq m1, m1, q3120 + mova [acq+32*0], m2 + mova [acq+32*1], m1 + add acq, 32*2 + sub hd, 2 + jg .w16_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).w16_hpad +.w16_wpad: + mova m2, [ypxq+strideq*0+ 0] + mova m0, [ypxq+strideq*1+ 0] + cmp wpadd, 2 + jl .w16_wpad1 + je .w16_wpad2 + vpbroadcastd m1, [ypxq+strideq*0+12] + vpbroadcastd m3, [ypxq+strideq*1+12] + vpblendd m2, m1, 0xf0 + vpblendd m0, m3, 0xf0 + jmp .w16_wpad_end +.w16_wpad2: + vpbroadcastd m1, [ypxq+strideq*0+28] + vpbroadcastd m3, [ypxq+strideq*1+28] + jmp .w16_wpad_end +.w16_wpad1: + vpbroadcastd m1, [ypxq+strideq*0+44] + vpbroadcastd m3, [ypxq+strideq*1+44] + vinserti128 m1, [ypxq+strideq*0+32], 0 + vinserti128 m3, [ypxq+strideq*1+32], 0 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + REPX {pmaddwd x, m5}, m2, m0, m1, m3 + paddd m4, m2 + packssdw m2, m1 + paddd m4, m1 + packssdw m1, m0, m3 + paddd m0, m3 + vpermq m2, m2, q3120 + paddd m4, m0 + vpermq m1, m1, q3120 + mova [acq+32*0], m2 + mova [acq+32*1], m1 + add acq, 32*2 + sub hd, 2 + jg .w16_wpad + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).w16_hpad + +cglobal ipred_cfl_ac_444_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + lea r6, [ipred_cfl_ac_444_16bpc_avx2_table] + tzcnt wd, wm + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_1] + movsxd wq, [r6+wq*4] + shl hpadd, 2 + add wq, r6 + mov hd, hm + pxor m4, m4 + sub hd, hpadd + jmp wq +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + movq xm0, [ypxq+strideq*0] + movhps xm0, [ypxq+strideq*1] + vpbroadcastq m1, [ypxq+strideq*2] + vpbroadcastq m2, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + psllw m0, 3 + pmaddwd m1, m0, m5 + mova [acq], m0 + add acq, 32 + paddd m4, m1 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vpermq m0, m0, q3333 + paddd m1, m1 + mova [acq+32*0], m0 + vpermq m1, m1, q3333 + mova [acq+32*1], m0 + add acq, 32*2 + paddd m4, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w8: + lea r3, [strideq*3] + mov r5, acq +.w8_loop: + mova xm2, [ypxq+strideq*0] + vinserti128 m2, [ypxq+strideq*1], 1 + mova xm1, [ypxq+strideq*2] + vinserti128 m1, [ypxq+r3 ], 1 + lea ypxq, [ypxq+strideq*4] + psllw m2, 3 + psllw m1, 3 + mova [acq+32*0], m2 + pmaddwd m2, m5 + mova [acq+32*1], m1 + pmaddwd m0, m1, m5 + add acq, 32*2 + paddd m4, m2 + paddd m4, m0 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vperm2i128 m1, m1, 0x11 + pslld m0, 2 + pxor m2, m2 + vpblendd m0, m2, 0x0f + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w16_wpad2: + vpbroadcastw m3, [ypxq+strideq*0+14] + vpbroadcastw m0, [ypxq+strideq*1+14] + vpblendd m2, m3, 0xf0 + vpblendd m1, m0, 0xf0 + jmp .w16_wpad_end +.w16: + mov r5, acq +.w16_loop: + mova m2, [ypxq+strideq*0] + mova m1, [ypxq+strideq*1] + test wpadd, wpadd + jnz .w16_wpad2 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + psllw m2, 3 + psllw m1, 3 + mova [acq+32*0], m2 + pmaddwd m2, m5 + mova [acq+32*1], m1 + pmaddwd m0, m1, m5 + add acq, 32*2 + paddd m4, m2 + paddd m4, m0 + sub hd, 2 + jg .w16_loop + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + paddd m0, m0 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w32: + mov r5, acq + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + mova m0, [ypxq+ 0] + mova m1, [ypxq+32] + add ypxq, strideq + psllw m0, 3 + psllw m1, 3 + pmaddwd m2, m0, m5 + mova [acq+32*0], m0 + pmaddwd m3, m1, m5 + mova [acq+32*1], m1 + add acq, 32*2 + paddd m2, m3 + paddd m4, m2 + dec hd + jg .w32_loop +.w32_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + paddd m2, m2 +.w32_hpad_loop: + mova [acq+32*0], m0 + mova [acq+32*1], m1 + paddd m4, m2 + mova [acq+32*2], m0 + mova [acq+32*3], m1 + add acq, 32*4 + sub hpadd, 2 + jg .w32_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w32_wpad: + mova m0, [ypxq+ 0] + cmp wpadd, 4 + jl .w32_wpad2 + je .w32_wpad4 + vpbroadcastw m1, [ypxq+14] + vpblendd m0, m1, 0xf0 + jmp .w32_wpad_end +.w32_wpad4: + vpbroadcastw m1, [ypxq+30] + jmp .w32_wpad_end +.w32_wpad2: + vpbroadcastw m1, [ypxq+46] + vinserti128 m1, [ypxq+32], 0 +.w32_wpad_end: + add ypxq, strideq + psllw m0, 3 + psllw m1, 3 + pmaddwd m2, m0, m5 + mova [acq+32*0], m0 + pmaddwd m3, m1, m5 + mova [acq+32*1], m1 + add acq, 32*2 + paddd m2, m3 + paddd m4, m2 + dec hd + jg .w32_wpad + jmp .w32_hpad + +cglobal pal_pred_16bpc, 4, 6, 5, dst, stride, pal, idx, w, h + vbroadcasti128 m3, [palq] + lea r2, [pal_pred_16bpc_avx2_table] + tzcnt wd, wm + vbroadcasti128 m4, [pal_pred_shuf] + movifnidn hd, hm + movsxd wq, [r2+wq*4] + pshufb m3, m4 + punpckhqdq m4, m3, m3 + add wq, r2 +DEFINE_ARGS dst, stride, stride3, idx, w, h + lea stride3q, [strideq*3] + jmp wq +.w4: + mova xm2, [idxq] + add idxq, 16 + pshufb xm1, xm3, xm2 + pshufb xm2, xm4, xm2 + punpcklbw xm0, xm1, xm2 + punpckhbw xm1, xm2 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+strideq*1], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + movu m2, [idxq] ; only 16-byte alignment + add idxq, 32 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + vextracti128 [dstq+strideq*2], m0, 1 + vextracti128 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0+ 0], m0 + mova [dstq+strideq*0+32], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*1+ 0], m0 + mova [dstq+strideq*1+32], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+ 0], m0 + mova [dstq+32], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+64], m0 + mova [dstq+96], m1 + add dstq, strideq + dec hd + jg .w64 + RET + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,833 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +ipred_shuf: db 14, 15, 14, 15, 0, 1, 2, 3, 6, 7, 6, 7, 0, 1, 2, 3 + db 10, 11, 10, 11, 8, 9, 10, 11, 2, 3, 2, 3, 8, 9, 10, 11 + db 12, 13, 12, 13, 4, 5, 6, 7, 4, 5, 4, 5, 4, 5, 6, 7 + db 8, 9, 8, 9, 12, 13, 14, 15, 0, 1, 0, 1, 12, 13, 14, 15 +smooth_perm: db 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30 + db 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 81, 82, 85, 86, 89, 90, 93, 94 + db 97, 98,101,102,105,106,109,110,113,114,117,118,121,122,125,126 +pal_pred_perm: db 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39 + db 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47 + db 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55 + db 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63 +filter_permA: times 4 db 6, 7, 8, 9, 14, 15, 4, 5 + times 4 db 10, 11, 12, 13, 2, 3, -1, -1 +filter_permB: times 4 db 22, 23, 24, 25, 30, 31, 6, 7 + times 4 db 26, 27, 28, 29, 14, 15, -1, -1 +filter_permC: dd 8 ; dq 8, 10, 1, 11, 0, 9 +pw_1: times 2 dw 1 + dd 10 +filter_rnd: dd 32 + dd 1 + dd 8 + dd 11 +filter_shift: times 2 dw 6 + dd 0 + times 2 dw 4 + dd 9 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +JMP_TABLE ipred_paeth_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE pal_pred_16bpc, avx512icl, w4, w8, w16, w32, w64 + +cextern smooth_weights_1d_16bpc +cextern smooth_weights_2d_16bpc +cextern filter_intra_taps + +SECTION .text + +%macro PAETH 3 ; top, signed_ldiff, ldiff + paddw m0, m%2, m2 + psubw m1, m0, m3 ; tldiff + psubw m0, m%1 ; tdiff + pabsw m1, m1 + pabsw m0, m0 + pcmpgtw k1, m0, m1 + pminsw m0, m1 + pcmpgtw k2, m%3, m0 + vpblendmw m0{k1}, m%1, m3 + vpblendmw m0{k2}, m2, m0 +%endmacro + +INIT_ZMM avx512icl +cglobal ipred_paeth_16bpc, 3, 7, 10, dst, stride, tl, w, h +%define base r6-ipred_paeth_16bpc_avx512icl_table + lea r6, [ipred_paeth_16bpc_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastw m3, [tlq] ; topleft + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [tlq+2] ; top + movsldup m7, [base+ipred_shuf] + lea r6, [strideq*3] + psubw m5, m4, m3 + pabsw m6, m5 +.w4_loop: + sub tlq, 16 + vbroadcasti32x4 m2, [tlq] + pshufb m2, m7 ; left + PAETH 4, 5, 6 + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm8, ym0, 1 + vextracti32x4 xm9, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm8 + movq [dstq+r6 ], xm9 + sub hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm8 + movhps [dstq+r6 ], xm9 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.w4_end: + RET +.w8: + vbroadcasti32x4 m4, [tlq+2] + movsldup m7, [base+ipred_shuf] + lea r6, [strideq*3] + psubw m5, m4, m3 + pabsw m6, m5 +.w8_loop: + sub tlq, 8 + vpbroadcastq m2, [tlq] + pshufb m2, m7 + PAETH 4, 5, 6 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + vbroadcasti32x8 m4, [tlq+2] + movsldup m7, [base+ipred_shuf] + psubw m5, m4, m3 + pabsw m6, m5 +.w16_loop: + sub tlq, 4 + vpbroadcastd m2, [tlq] + pshufb m2, m7 + PAETH 4, 5, 6 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + movu m4, [tlq+2] + psubw m5, m4, m3 + pabsw m6, m5 +.w32_loop: + sub tlq, 2 + vpbroadcastw m2, [tlq] + PAETH 4, 5, 6 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +.w64: + movu m4, [tlq+ 2] + movu m7, [tlq+66] + psubw m5, m4, m3 + psubw m8, m7, m3 + pabsw m6, m5 + pabsw m9, m8 +.w64_loop: + sub tlq, 2 + vpbroadcastw m2, [tlq] + PAETH 4, 5, 6 + mova [dstq+64*0], m0 + PAETH 7, 8, 9 + mova [dstq+64*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_16bpc, 3, 7, 7, dst, stride, tl, w, h, weights, stride3 +%define base r6-$$ + lea r6, [$$] + tzcnt wd, wm + mov hd, hm + movsxd wq, [base+ipred_smooth_v_16bpc_avx512icl_table+wq*4] + lea weightsq, [base+smooth_weights_1d_16bpc+hq*4] + neg hq + vpbroadcastw m6, [tlq+hq*2] ; bottom + lea wq, [base+ipred_smooth_v_16bpc_avx512icl_table+wq] + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastq m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w4_loop: + vbroadcasti32x4 m3, [weightsq+hq*2] + pshufb m3, m4 + pmulhrsw m3, m5 + paddw m3, m6 + vextracti32x4 xm0, m3, 3 + vextracti32x4 xm1, ym3, 1 + vextracti32x4 xm2, m3, 2 + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + add hq, 8 + jg .end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jl .w4_loop +.end: + RET +.w8: + vbroadcasti32x4 m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w8_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m4 + pmulhrsw m0, m5 + paddw m0, m6 + vextracti32x4 [dstq+strideq*0], m0, 3 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + vbroadcasti32x8 m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w16_loop: + vpbroadcastd m0, [weightsq+hq*2+0] + vpbroadcastd m1, [weightsq+hq*2+4] + pshufb m0, m4 + pshufb m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + paddw m0, m6 + paddw m1, m6 + vextracti32x8 [dstq+strideq*0], m0, 1 + mova [dstq+strideq*1], ym0 + vextracti32x8 [dstq+strideq*2], m1, 1 + mova [dstq+stride3q ], ym1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + movu m5, [tlq+2] + psubw m5, m6 +.w32_loop: + vpbroadcastw m0, [weightsq+hq*2+0] + vpbroadcastw m1, [weightsq+hq*2+2] + vpbroadcastw m2, [weightsq+hq*2+4] + vpbroadcastw m3, [weightsq+hq*2+6] + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w32_loop + RET +.w64: + movu m4, [tlq+ 2] + movu m5, [tlq+66] + psubw m4, m6 + psubw m5, m6 +.w64_loop: + vpbroadcastw m1, [weightsq+hq*2+0] + vpbroadcastw m3, [weightsq+hq*2+2] + pmulhrsw m0, m4, m1 + pmulhrsw m1, m5 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m5 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + mova [dstq+strideq*1+64*0], m2 + mova [dstq+strideq*1+64*1], m3 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w64_loop + RET + +cglobal ipred_smooth_h_16bpc, 3, 7, 7, dst, stride, tl, w, h, stride3 + lea r6, [$$] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m6, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [base+ipred_smooth_h_16bpc_avx512icl_table+wq*4] + sub tlq, hq + lea stride3q, [strideq*3] + lea wq, [base+ipred_smooth_h_16bpc_avx512icl_table+wq] + jmp wq +.w4: + movsldup m4, [base+ipred_shuf] + vpbroadcastq m5, [base+smooth_weights_1d_16bpc+4*2] +.w4_loop: + vbroadcasti32x4 m0, [tlq+hq-16] ; left + pshufb m0, m4 + psubw m0, m6 ; left - right + pmulhrsw m0, m5 + paddw m0, m6 + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm2, ym0, 1 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + sub hd, 8*2 + jl .end + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.end: + RET +.w8: + movsldup m4, [base+ipred_shuf] + vbroadcasti32x4 m5, [base+smooth_weights_1d_16bpc+8*2] +.w8_loop: + vpbroadcastq m0, [tlq+hq-8] ; left + pshufb m0, m4 + psubw m0, m6 ; left - right + pmulhrsw m0, m5 + paddw m0, m6 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w8_loop + RET +.w16: + movsldup m4, [base+ipred_shuf] + vbroadcasti32x8 m5, [base+smooth_weights_1d_16bpc+16*2] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastd m1, [tlq+hq-8] + pshufb m0, m4 + pshufb m1, m4 + psubw m0, m6 + psubw m1, m6 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + paddw m0, m6 + paddw m1, m6 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w16_loop + RET +.w32: + movu m5, [base+smooth_weights_1d_16bpc+32*2] +.w32_loop: + vpbroadcastq m3, [tlq+hq-8] + punpcklwd m3, m3 + psubw m3, m6 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w32_loop + RET +.w64: + movu m4, [base+smooth_weights_1d_16bpc+64*2] + movu m5, [base+smooth_weights_1d_16bpc+64*3] +.w64_loop: + vpbroadcastw m1, [tlq+hq-2] + vpbroadcastw m3, [tlq+hq-4] + psubw m1, m6 + psubw m3, m6 + pmulhrsw m0, m4, m1 + pmulhrsw m1, m5 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m5 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + mova [dstq+strideq*1+64*0], m2 + mova [dstq+strideq*1+64*1], m3 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w64_loop + RET + +cglobal ipred_smooth_16bpc, 3, 7, 16, dst, stride, tl, w, h, v_weights, stride3 + lea r6, [$$] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m13, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [base+ipred_smooth_16bpc_avx512icl_table+wq*4] + mov r5d, 0x55555555 + sub tlq, hq + mova m14, [base+smooth_perm] + kmovd k1, r5d + vpbroadcastw m0, [tlq] ; bottom + mov r5, 0x3333333333333333 + pxor m15, m15 + lea wq, [base+ipred_smooth_16bpc_avx512icl_table+wq] + kmovq k2, r5 + lea v_weightsq, [base+smooth_weights_2d_16bpc+hq*2] + jmp wq +.w4: + vpbroadcastq m5, [tlq+hq+2] + movshdup m3, [base+ipred_shuf] + movsldup m4, [base+ipred_shuf] + vbroadcasti32x4 m6, [base+smooth_weights_2d_16bpc+4*4] + lea stride3q, [strideq*3] + punpcklwd m5, m0 ; top, bottom +.w4_loop: + vbroadcasti32x4 m0, [v_weightsq] + vpbroadcastq m2, [tlq+hq-8] + mova m1, m13 + pshufb m0, m3 + pmaddwd m0, m5 + pshufb m1{k2}, m2, m4 ; left, right + vpdpwssd m0, m1, m6 + vpermb m0, m14, m0 + pavgw ym0, ym15 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + add v_weightsq, 4*4 + sub hd, 4*2 + jg .w4_loop + RET +.w8: + vbroadcasti32x4 ym5, [tlq+hq+2] + movshdup m6, [base+ipred_shuf] + movsldup m7, [base+ipred_shuf] + pmovzxwd m5, ym5 + vbroadcasti32x8 m8, [base+smooth_weights_2d_16bpc+8*4] + lea stride3q, [strideq*3] + vpblendmw m5{k1}, m0, m5 ; top, bottom +.w8_loop: + vpbroadcastq m0, [v_weightsq+0] + vpbroadcastq m1, [v_weightsq+8] + vpbroadcastd m3, [tlq+hq-4] + vpbroadcastd m4, [tlq+hq-8] + pshufb m0, m6 + pmaddwd m0, m5 + pshufb m1, m6 + pmaddwd m1, m5 + mova m2, m13 + pshufb m2{k2}, m3, m7 ; left, right + mova m3, m13 + pshufb m3{k2}, m4, m7 + vpdpwssd m0, m2, m8 + vpdpwssd m1, m3, m8 + add v_weightsq, 4*4 + vpermt2b m0, m14, m1 + pavgw m0, m15 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w8_loop + RET +.w16: + pmovzxwd m5, [tlq+hq+2] + mova m6, [base+smooth_weights_2d_16bpc+16*4] + vpblendmw m5{k1}, m0, m5 ; top, bottom +.w16_loop: + vpbroadcastd m0, [v_weightsq+0] + vpbroadcastd m1, [v_weightsq+4] + pmaddwd m0, m5 + pmaddwd m1, m5 + mova m2, m13 + vpbroadcastw m2{k1}, [tlq+hq-2] ; left, right + mova m3, m13 + vpbroadcastw m3{k1}, [tlq+hq-4] + vpdpwssd m0, m2, m6 + vpdpwssd m1, m3, m6 + add v_weightsq, 2*4 + vpermt2b m0, m14, m1 + pavgw m0, m15 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w16_loop + RET +.w32: + pmovzxwd m5, [tlq+hq+ 2] + pmovzxwd m6, [tlq+hq+34] + mova m7, [base+smooth_weights_2d_16bpc+32*4] + mova m8, [base+smooth_weights_2d_16bpc+32*6] + vpblendmw m5{k1}, m0, m5 ; top, bottom + vpblendmw m6{k1}, m0, m6 +.w32_loop: + vpbroadcastd m2, [v_weightsq+0] + vpbroadcastd m3, [v_weightsq+4] + pmaddwd m0, m5, m2 + pmaddwd m2, m6 + pmaddwd m1, m5, m3 + pmaddwd m3, m6 + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-2] ; left, right + vpdpwssd m0, m4, m7 + vpdpwssd m2, m4, m8 + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-4] + vpdpwssd m1, m4, m7 + vpdpwssd m3, m4, m8 + add v_weightsq, 2*4 + vpermt2b m0, m14, m2 + vpermt2b m1, m14, m3 + pavgw m0, m15 + pavgw m1, m15 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w32_loop + RET +.w64: + pmovzxwd m5, [tlq+hq+ 2] + pmovzxwd m6, [tlq+hq+34] + pmovzxwd m7, [tlq+hq+66] + pmovzxwd m8, [tlq+hq+98] + mova m9, [base+smooth_weights_2d_16bpc+64*4] + vpblendmw m5{k1}, m0, m5 ; top, bottom + mova m10, [base+smooth_weights_2d_16bpc+64*5] + vpblendmw m6{k1}, m0, m6 + mova m11, [base+smooth_weights_2d_16bpc+64*6] + vpblendmw m7{k1}, m0, m7 + mova m12, [base+smooth_weights_2d_16bpc+64*7] + vpblendmw m8{k1}, m0, m8 +.w64_loop: + vpbroadcastd m3, [v_weightsq] + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-2] ; left, right + pmaddwd m0, m5, m3 + pmaddwd m2, m6, m3 + pmaddwd m1, m7, m3 + pmaddwd m3, m8 + vpdpwssd m0, m4, m9 + vpdpwssd m2, m4, m10 + vpdpwssd m1, m4, m11 + vpdpwssd m3, m4, m12 + add v_weightsq, 1*4 + vpermt2b m0, m14, m2 + vpermt2b m1, m14, m3 + pavgw m0, m15 + pavgw m1, m15 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + sub hd, 1*2 + jg .w64_loop + RET + +cglobal pal_pred_16bpc, 4, 7, 4, dst, stride, pal, idx, w, h, stride3 + lea r6, [pal_pred_16bpc_avx512icl_table] + tzcnt wd, wm + mova m2, [pal_pred_perm] + movsxd wq, [r6+wq*4] + mova xm3, [palq] + movifnidn hd, hm + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + pmovzxbw ym0, [idxq] + add idxq, 16 + vpermw ym0, ym0, ym3 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pmovzxbw m0, [idxq] + add idxq, 32 + vpermw m0, m0, m3 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + dec hd + jg .w64 + RET + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. +; w4 w8 w16 w32 +; 1 1 2 1 2 5 6 1 2 5 6 9 a d e +; 2 2 3 2 3 6 7 2 3 6 7 a b e f +; 3 3 4 3 4 7 8 3 4 7 8 b c f g +; 4 4 5 4 5 8 9 4 5 8 9 c d g h + +cglobal ipred_filter_16bpc, 4, 7, 14, dst, stride, tl, w, h, filter, top +%define base r6-$$ + lea r6, [$$] +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + movifnidn hd, hm + movu xm0, [tlq-6] + pmovsxbw m7, [base+filter_intra_taps+filterq+32*0] + pmovsxbw m8, [base+filter_intra_taps+filterq+32*1] + mov r5d, r8m ; bitdepth_max + movsldup m9, [base+filter_permA] + movshdup m10, [base+filter_permA] + shr r5d, 11 ; is_12bpc + jnz .12bpc + psllw m7, 2 ; upshift multipliers so that packusdw + psllw m8, 2 ; will perform clipping for free +.12bpc: + vpbroadcastd m5, [base+filter_rnd+r5*8] + vpbroadcastd m6, [base+filter_shift+r5*8] + sub wd, 8 + jl .w4 +.w8: + call .main4 + movsldup m11, [filter_permB] + lea r5d, [hq*2+2] + movshdup m12, [filter_permB] + lea topq, [tlq+2] + mova m13, [filter_permC] + sub hd, 4 + vinserti32x4 ym0, [topq], 1 ; a0 b0 t0 t1 + sub tlq, r5 +%if WIN64 + push r7 + push r8 +%endif + mov r7, dstq + mov r8d, hd +.w8_loop: + movlps xm4, xm0, [tlq+hq*2] + call .main8 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jge .w8_loop + test wd, wd + jz .end + mov r2d, 0x0d + kmovb k1, r2d + lea r2, [strideq*3] +.w16: + movd xmm0, [r7+strideq*1+12] + vpblendd xmm0, [topq+8], 0x0e ; t1 t2 + pinsrw xm4, xmm0, [r7+strideq*0+14], 2 + call .main8 + add r7, 16 + vinserti32x4 ym0, [topq+16], 1 ; a2 b2 t2 t3 + mov hd, r8d + mov dstq, r7 + add topq, 16 +.w16_loop: + movd xmm1, [dstq+strideq*2-4] + punpcklwd xm4, xmm1, xmm0 + movd xmm0, [dstq+r2-4] + shufps xm4{k1}, xmm0, xm0, q3210 + call .main8 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jge .w16_loop + sub wd, 8 + jg .w16 +.end: + vpermb m2, m11, m0 + mova ym1, ym5 + vpdpwssd m1, m2, m7 + vpermb m2, m12, m0 + vpdpwssd m1, m2, m8 +%if WIN64 + pop r8 + pop r7 +%endif + vextracti32x8 ym2, m1, 1 + paddd ym1, ym2 + packusdw ym1, ym1 + vpsrlvw ym1, ym6 + vpermt2q m0, m13, m1 + vextracti32x4 [dstq+strideq*0], m0, 2 + vextracti32x4 [dstq+strideq*1], ym0, 1 + RET +.w4_loop: + movlps xm0, [tlq-10] + lea dstq, [dstq+strideq*2] + sub tlq, 4 +.w4: + call .main4 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.main4: + vpermb m2, m9, m0 + mova ym1, ym5 + vpdpwssd m1, m2, m7 + vpermb m0, m10, m0 + vpdpwssd m1, m0, m8 + vextracti32x8 ym0, m1, 1 + paddd ym0, ym1 + vextracti32x4 xm1, ym0, 1 + packusdw xm0, xm1 ; clip + vpsrlvw xm0, xm6 + ret +ALIGN function_align +.main8: + vpermb m3, m11, m0 + mova ym2, ym5 + vpdpwssd m2, m3, m7 + vpermb m3, m9, m4 + mova ym1, ym5 + vpdpwssd m1, m3, m7 + vpermb m3, m12, m0 + vpdpwssd m2, m3, m8 + vpermb m3, m10, m4 + vpdpwssd m1, m3, m8 + vextracti32x8 ym4, m2, 1 + vextracti32x8 ym3, m1, 1 + paddd ym2, ym4 + paddd ym1, ym3 + packusdw ym1, ym2 ; clip + vpsrlvw ym1, ym6 + vpermt2q m0, m13, m1 ; c0 d0 b0 b1 a0 a1 + vextracti32x4 [dstq+strideq*0], m0, 2 + vextracti32x4 [dstq+strideq*1], ym0, 1 + ret + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4076 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA + +filter_shuf: db 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4, 5, 2, 3, -1, -1 +pal_pred_shuf: db 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 +z_base_inc_z2: dw 7*64, 6*64, 5*64, 4*64, 3*64, 2*64, 1*64, 0*64 +z_upsample: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_upsample_l: db -1, -1, -2, -1, -3, -1, -4, -1, 8, 9, 8, 9, 10, 11, 12, 13 + db 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 +z2_top_shufA: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +z2_top_shufB: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_left_shufA: db 14, 15, 12, 13, 10, 11, 8, 9, 12, 13, 10, 11, 8, 9, 6, 7 +z2_left_shufB: db 14, 15, 10, 11, 6, 7, 2, 3, 12, 13, 8, 9, 4, 5, 0, 1 +z_filt_wh16: db 19, 19, 19, 23, 23, 23, 31, 31, 31, 47, 47, 47, 79, 79, 79, -1 +z_filt_t_w48: db 55,127, 7,127, 15, 31, 39, 31,127, 39,127, 39, 7, 15, 31, 15 + db 39, 63, 3, 63, 3, 3, 19, 3, 47, 19, 47, 19, 3, 3, 3, 3 +z_filt_t_w16: db 15, 31, 7, 15, 31, 7, 3, 31, 3, 3, 3, 3, 3, 3, 0, 0 +z_filt_wh4: db 7, 7, 19, 7, +z_filt_wh8: db 19, 19, 11, 19, 11, 15, 15, 15, 23, 23, 23, 23, 39, 39, 39, 39 +ALIGN 8 +pb_2_3: times 4 db 2, 3 +z2_dy_offset: dw 96*64, 96*64, 95*64, 95*64 +z_filt_k: times 4 dw 8 + times 4 dw 6 + times 4 dw 4 + times 4 dw 5 +pw_m3584: times 4 dw -3584 +pw_m3072: times 4 dw -3072 +pw_m2560: times 4 dw -2560 +pw_m2048: times 4 dw -2048 +pw_m1536: times 4 dw -1536 +pw_m1024: times 4 dw -1024 +pw_m512: times 4 dw -512 +pw_1: times 4 dw 1 +pw_2: times 4 dw 2 +pw_3: times 4 dw 3 +pw_62: times 4 dw 62 +pw_256: times 4 dw 256 +pw_512: times 4 dw 512 +pw_2048: times 4 dw 2048 + +%define pw_4 (z_filt_k+8*2) +%define pw_8 (z_filt_k+8*0) +%define pw_m1to4 z2_upsample_l + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_16bpc_ssse3_table (ipred_dc_16bpc_ssse3_table + 10*4) +%define ipred_dc_128_16bpc_ssse3_table (ipred_dc_16bpc_ssse3_table + 15*4) +%define ipred_cfl_splat_16bpc_ssse3_table (ipred_cfl_16bpc_ssse3_table + 8*4) + +JMP_TABLE ipred_dc_left_16bpc, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_dc_16bpc, ssse3, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4, \ + s4-15*4, s8-15*4, s16c-15*4, s32c-15*4, s64-15*4 +JMP_TABLE ipred_h_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3_16bpc, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_cfl_16bpc, ssse3, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left_16bpc, ssse3, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_444_16bpc, ssse3, w4, w8, w16, w32 +JMP_TABLE pal_pred_16bpc, ssse3, w4, w8, w16, w32, w64 + +cextern smooth_weights_1d_16bpc +cextern smooth_weights_2d_16bpc +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_XMM ssse3 +cglobal ipred_dc_top_16bpc, 3, 7, 6, dst, stride, tl, w, h + LEA r5, ipred_dc_left_16bpc_ssse3_table + movd m4, wm + tzcnt wd, wm + add tlq, 2 + movifnidn hd, hm + pxor m3, m3 + pavgw m4, m3 + movd m5, wd + movu m0, [tlq] + movsxd r6, [r5+wq*4] + add r6, r5 + add r5, ipred_dc_128_16bpc_ssse3_table-ipred_dc_left_16bpc_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_left_16bpc_ssse3_table + mov hd, hm + movd m4, hm + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + pxor m3, m3 + sub tlq, hq + pavgw m4, m3 + movd m5, r6d + movu m0, [tlq] + movsxd r6, [r5+r6*4] + add r6, r5 + add r5, ipred_dc_128_16bpc_ssse3_table-ipred_dc_left_16bpc_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m2, [tlq+112] + movu m1, [tlq+ 96] + paddw m0, m2 + movu m2, [tlq+ 80] + paddw m1, m2 + movu m2, [tlq+ 64] + paddw m0, m2 + paddw m0, m1 +.h32: + movu m1, [tlq+ 48] + movu m2, [tlq+ 32] + paddw m1, m2 + paddw m0, m1 +.h16: + movu m1, [tlq+ 16] + paddw m0, m1 +.h8: + movhlps m1, m0 + paddw m0, m1 +.h4: + punpcklwd m0, m3 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + lea stride3q, [strideq*3] + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +cglobal ipred_dc_16bpc, 4, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd m4, r5d + tzcnt r5d, r5d + movd m5, r5d + LEA r5, ipred_dc_16bpc_ssse3_table + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pxor m3, m3 + psrlw m4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movq m0, [tlq-8] + jmp wq +.w4: + movq m1, [tlq+2] + paddw m1, m0 + punpckhwd m0, m3 + punpcklwd m1, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 + jmp .w4_end +.w4_mul: + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 16 + cmove r2d, r3d + psrld m0, 2 + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w4_end: + pshuflw m0, m0, q0000 +.s4: + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movq [dstq+strideq*2], m0 + movq [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +.h8: + mova m0, [tlq-16] + jmp wq +.w8: + movu m1, [tlq+2] + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 8 + je .w8_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 32 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +.h16: + mova m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w16: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + paddw m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 16 + je .w16_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + test hd, 8|32 + cmovz r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16c: + mova m1, m0 +.s16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*2+16*0], m0 + mova [dstq+strideq*2+16*1], m1 + mova [dstq+stride3q +16*0], m0 + mova [dstq+stride3q +16*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-48] + paddw m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w32: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + movu m2, [tlq+34] + paddw m0, m2 + movu m2, [tlq+50] + paddw m1, m2 + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 32 + je .w32_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 8 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32c: + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s32: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + mova [dstq+strideq*0+16*2], m2 + mova [dstq+strideq*0+16*3], m3 + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*3], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s32 + RET +.h64: + mova m0, [tlq-128] + mova m1, [tlq-112] + paddw m0, [tlq- 96] + paddw m1, [tlq- 80] + paddw m0, [tlq- 64] + paddw m1, [tlq- 48] + paddw m0, [tlq- 32] + paddw m1, [tlq- 16] + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 2] + movu m2, [tlq+ 18] + paddw m1, m2 + movu m2, [tlq+ 34] + paddw m0, m2 + movu m2, [tlq+ 50] + paddw m1, m2 + movu m2, [tlq+ 66] + paddw m0, m2 + movu m2, [tlq+ 82] + paddw m1, m2 + movu m2, [tlq+ 98] + paddw m0, m2 + movu m2, [tlq+114] + paddw m1, m2 + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 64 + je .w64_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 16 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w64_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m0 + mova [dstq+16*2], m0 + mova [dstq+16*3], m0 + mova [dstq+16*4], m0 + mova [dstq+16*5], m0 + mova [dstq+16*6], m0 + mova [dstq+16*7], m0 + add dstq, strideq + dec hd + jg .s64 + RET + +cglobal ipred_dc_128_16bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + mov r6d, r8m + LEA r5, ipred_dc_128_16bpc_ssse3_table + tzcnt wd, wm + shr r6d, 11 + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m0, [r5-ipred_dc_128_16bpc_ssse3_table+pw_512+r6*8] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_16bpc, 4, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_16bpc_ssse3_table + movifnidn hd, hm + movu m0, [tlq+ 2] + movu m1, [tlq+ 18] + movu m2, [tlq+ 34] + movu m3, [tlq+ 50] + cmp wd, 64 + je .w64 + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w64: + WIN64_SPILL_XMM 8 + movu m4, [tlq+ 66] + movu m5, [tlq+ 82] + movu m6, [tlq+ 98] + movu m7, [tlq+114] +.w64_loop: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + mova [dstq+16*4], m4 + mova [dstq+16*5], m5 + mova [dstq+16*6], m6 + mova [dstq+16*7], m7 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_h_16bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 +%define base r5-ipred_h_16bpc_ssse3_table + tzcnt wd, wm + LEA r5, ipred_h_16bpc_ssse3_table + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m2, [base+pw_256] + movddup m3, [base+pb_2_3] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + sub tlq, 8 + movq m3, [tlq] + pshuflw m0, m3, q3333 + pshuflw m1, m3, q2222 + pshuflw m2, m3, q1111 + pshuflw m3, m3, q0000 + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m1 + movq [dstq+strideq*2], m2 + movq [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + sub tlq, 8 + movq m3, [tlq] + punpcklwd m3, m3 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + sub tlq, 4 + movd m1, [tlq] + pshufb m0, m1, m3 + pshufb m1, m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m0 + mova [dstq+strideq*1+16*0], m1 + mova [dstq+strideq*1+16*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16 + RET +.w32: + sub tlq, 4 + movd m1, [tlq] + pshufb m0, m1, m3 + pshufb m1, m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m0 + mova [dstq+strideq*0+16*2], m0 + mova [dstq+strideq*0+16*3], m0 + mova [dstq+strideq*1+16*0], m1 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*1+16*2], m1 + mova [dstq+strideq*1+16*3], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + sub tlq, 2 + movd m0, [tlq] + pshufb m0, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m0 + mova [dstq+16*2], m0 + mova [dstq+16*3], m0 + mova [dstq+16*4], m0 + mova [dstq+16*5], m0 + mova [dstq+16*6], m0 + mova [dstq+16*7], m0 + add dstq, strideq + dec hd + jg .w64 + RET + +cglobal ipred_paeth_16bpc, 4, 6, 8, dst, stride, tl, w, h, left +%define base r5-ipred_paeth_16bpc_ssse3_table + movifnidn hd, hm + pshuflw m4, [tlq], q0000 + mov leftq, tlq + add hd, hd + punpcklqdq m4, m4 ; topleft + sub leftq, hq + and wd, ~7 + jnz .w8 + movddup m5, [tlq+2] ; top + psubw m6, m5, m4 + pabsw m7, m6 +.w4_loop: + movd m1, [leftq+hq-4] + punpcklwd m1, m1 + punpckldq m1, m1 ; left +%macro PAETH 0 + paddw m0, m6, m1 + psubw m2, m4, m0 ; tldiff + psubw m0, m5 ; tdiff + pabsw m2, m2 + pabsw m0, m0 + pminsw m2, m0 + pcmpeqw m0, m2 + pand m3, m5, m0 + pandn m0, m4 + por m0, m3 + pcmpgtw m3, m7, m2 + pand m0, m3 + pandn m3, m1 + por m0, m3 +%endmacro + PAETH + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2*2 + jg .w4_loop + RET +.w8: +%if ARCH_X86_32 + PUSH r6 + %define r7d hm + %assign regs_used 7 +%elif WIN64 + movaps r4m, m8 + PUSH r7 + %assign regs_used 8 +%endif +%if ARCH_X86_64 + movddup m8, [pw_256] +%endif + lea tlq, [tlq+wq*2+2] + neg wq + mov r7d, hd +.w8_loop0: + movu m5, [tlq+wq*2] + mov r6, dstq + add dstq, 16 + psubw m6, m5, m4 + pabsw m7, m6 +.w8_loop: + movd m1, [leftq+hq-2] +%if ARCH_X86_64 + pshufb m1, m8 +%else + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 +%endif + PAETH + mova [r6], m0 + add r6, strideq + sub hd, 1*2 + jg .w8_loop + mov hd, r7d + add wq, 8 + jl .w8_loop0 +%if WIN64 + movaps m8, r4m +%endif + RET + +%if ARCH_X86_64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 4 +%endif + +cglobal ipred_smooth_v_16bpc, 4, 6, 6, dst, stride, tl, w, h, weights + LEA weightsq, smooth_weights_1d_16bpc + mov hd, hm + lea weightsq, [weightsq+hq*4] + neg hq + movd m5, [tlq+hq*2] ; bottom + pshuflw m5, m5, q0000 + punpcklqdq m5, m5 + cmp wd, 4 + jne .w8 + movddup m4, [tlq+2] ; top + lea r3, [strideq*3] + psubw m4, m5 ; top - bottom +.w4_loop: + movq m1, [weightsq+hq*2] + punpcklwd m1, m1 + pshufd m0, m1, q1100 + punpckhdq m1, m1 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop + RET +.w8: +%if ARCH_X86_32 + PUSH r6 + %assign regs_used 7 + mov hm, hq + %define hq hm +%elif WIN64 + PUSH r7 + %assign regs_used 8 +%endif +.w8_loop0: + mov t0, hq + movu m4, [tlq+2] + add tlq, 16 + mov r6, dstq + add dstq, 16 + psubw m4, m5 +.w8_loop: + movq m3, [weightsq+t0*2] + punpcklwd m3, m3 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [r6+strideq*0], m0 + mova [r6+strideq*1], m1 + lea r6, [r6+strideq*2] + mova [r6+strideq*0], m2 + mova [r6+strideq*1], m3 + lea r6, [r6+strideq*2] + add t0, 4 + jl .w8_loop + sub wd, 8 + jg .w8_loop0 + RET + +cglobal ipred_smooth_h_16bpc, 3, 6, 6, dst, stride, tl, w, h, weights + LEA weightsq, smooth_weights_1d_16bpc + mov wd, wm + movifnidn hd, hm + movd m5, [tlq+wq*2] ; right + sub tlq, 8 + add hd, hd + pshuflw m5, m5, q0000 + sub tlq, hq + punpcklqdq m5, m5 + cmp wd, 4 + jne .w8 + movddup m4, [weightsq+4*2] + lea r3, [strideq*3] +.w4_loop: + movq m1, [tlq+hq] ; left + punpcklwd m1, m1 + psubw m1, m5 ; left - right + pshufd m0, m1, q3322 + punpckldq m1, m1 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movhps [dstq+strideq*2], m1 + movq [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w4_loop + RET +.w8: + lea weightsq, [weightsq+wq*4] + neg wq +%if ARCH_X86_32 + PUSH r6 + %assign regs_used 7 + %define hd hm +%elif WIN64 + PUSH r7 + %assign regs_used 8 +%endif +.w8_loop0: + mov t0d, hd + mova m4, [weightsq+wq*2] + mov r6, dstq + add dstq, 16 +.w8_loop: + movq m3, [tlq+t0*(1+ARCH_X86_32)] + punpcklwd m3, m3 + psubw m3, m5 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [r6+strideq*0], m0 + mova [r6+strideq*1], m1 + lea r6, [r6+strideq*2] + mova [r6+strideq*0], m2 + mova [r6+strideq*1], m3 + lea r6, [r6+strideq*2] + sub t0d, 4*(1+ARCH_X86_64) + jg .w8_loop + add wq, 8 + jl .w8_loop0 + RET + +%if ARCH_X86_64 +DECLARE_REG_TMP 10 +%else +DECLARE_REG_TMP 3 +%endif + +cglobal ipred_smooth_16bpc, 3, 7, 8, dst, stride, tl, w, h, \ + h_weights, v_weights, top + LEA h_weightsq, smooth_weights_2d_16bpc + mov wd, wm + mov hd, hm + movd m7, [tlq+wq*2] ; right + lea v_weightsq, [h_weightsq+hq*8] + neg hq + movd m6, [tlq+hq*2] ; bottom + pshuflw m7, m7, q0000 + pshuflw m6, m6, q0000 + cmp wd, 4 + jne .w8 + movq m4, [tlq+2] ; top + mova m5, [h_weightsq+4*4] + punpcklwd m4, m6 ; top, bottom + pxor m6, m6 +.w4_loop: + movq m1, [v_weightsq+hq*4] + sub tlq, 4 + movd m3, [tlq] ; left + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + pmaddwd m0, m4 + punpcklwd m3, m7 ; left, right + pmaddwd m1, m4 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m6 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w4_loop + RET +.w8: +%if ARCH_X86_32 + lea h_weightsq, [h_weightsq+wq*4] + mov t0, tlq + mov r1m, tlq + mov r2m, hq + %define m8 [h_weightsq+16*0] + %define m9 [h_weightsq+16*1] +%else +%if WIN64 + movaps r4m, m8 + movaps r6m, m9 + PUSH r7 + PUSH r8 +%endif + PUSH r9 + PUSH r10 + %assign regs_used 11 + lea h_weightsq, [h_weightsq+wq*8] + lea topq, [tlq+wq*2] + neg wq + mov r8, tlq + mov r9, hq +%endif + punpcklqdq m6, m6 +.w8_loop0: +%if ARCH_X86_32 + movu m5, [t0+2] + add t0, 16 + mov r0m, t0 +%else + movu m5, [topq+wq*2+2] + mova m8, [h_weightsq+wq*4+16*0] + mova m9, [h_weightsq+wq*4+16*1] +%endif + mov t0, dstq + add dstq, 16 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 +.w8_loop: + movd m1, [v_weightsq+hq*4] + sub tlq, 2 + movd m3, [tlq] ; left + pshufd m1, m1, q0000 + pmaddwd m0, m4, m1 + pshuflw m3, m3, q0000 + pmaddwd m1, m5 + punpcklwd m3, m7 ; left, right + pmaddwd m2, m8, m3 + pmaddwd m3, m9 + paddd m0, m2 + paddd m1, m3 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pxor m1, m1 + pavgw m0, m1 + mova [t0], m0 + add t0, strideq + inc hq + jl .w8_loop +%if ARCH_X86_32 + mov t0, r0m + mov tlq, r1m + add h_weightsq, 16*2 + mov hq, r2m + sub dword wm, 8 + jg .w8_loop0 +%else + mov tlq, r8 + mov hq, r9 + add wq, 8 + jl .w8_loop0 +%endif +%if WIN64 + movaps m8, r4m + movaps m9, r6m +%endif + RET + +%if ARCH_X86_64 +cglobal ipred_z1_16bpc, 3, 8, 8, 16*18, dst, stride, tl, w, h, angle, dx + %define base r7-$$ + %define bdmaxm r8m + lea r7, [$$] +%else +cglobal ipred_z1_16bpc, 3, 7, 8, -16*18, dst, stride, tl, w, h, angle, dx + %define base r1-$$ + %define stridemp [rsp+4*0] + %define bdmaxm [rsp+4*1] + mov r3, r8m + mov stridemp, r1 + mov bdmaxm, r3 + LEA r1, $$ +%endif + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + add tlq, 2 + movsxd wq, [base+ipred_z1_16bpc_ssse3_table+wq*4] + mov dxd, angled + movddup m0, [base+pw_256] + and dxd, 0x7e + movddup m7, [base+pw_62] + add angled, 165 ; ~90 + lea wq, [base+wq+ipred_z1_16bpc_ssse3_table] + movzx dxd, word [base+dr_intra_derivative+dxq] + xor angled, 0x4ff ; d = 90 - angle + jmp wq +.w4: + lea r3d, [angleq+88] + test r3d, 0x480 + jnz .w4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r3d, 9 + add r3d, hd + cmp r3d, 8 + jg .w4_no_upsample ; h > 8 || (w == h && is_sm) + movd m3, [tlq+14] + movu m2, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + movd m1, bdmaxm + pshufb m3, m0 + palignr m4, m3, m2, 4 ; 3 4 5 6 7 8 8 8 + paddw m4, [tlq- 2] ; 0 1 2 3 4 5 6 7 + add dxd, dxd + mova [rsp+32], m3 + palignr m3, m2, 2 ; 2 3 4 5 6 7 8 8 + pshufb m1, m0 + paddw m3, m2 ; -1 * a + 9 * b + 9 * c + -1 * d + psubw m5, m3, m4 ; = (b + c - a - d + (b + c) << 3 + 8) >> 4 + movd m4, dxd + psraw m5, 3 ; = ((b + c - a - d) >> 3 + b + c + 1) >> 1 + paddw m3, m5 + pxor m5, m5 + pmaxsw m3, m5 + mov r3d, dxd + pavgw m3, m5 + pshufb m4, m0 + pminsw m3, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + mova m3, [base+z_upsample] + movifnidn strideq, stridemp + mova [rsp+ 0], m1 + paddw m5, m4, m4 + mova [rsp+16], m2 + punpcklqdq m4, m5 ; xpos0 xpos1 +.w4_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu m1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + movu m2, [rsp+r2*2] + pshufb m1, m3 + pshufb m2, m3 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m7, m4 ; frac + psllw m2, 9 ; (a * (64 - frac) + b * frac + 32) >> 6 + psubw m1, m0 ; = a + (((b - a) * frac + 32) >> 6) + pmulhrsw m1, m2 ; = a + (((b - a) * (frac << 9) + 16384) >> 15) + paddw m4, m5 ; xpos += dx + paddw m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_upsample_loop + RET +.w4_no_upsample: + mov r3d, 7 ; max_base + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea r3d, [hq+3] + movd m1, r3d + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + pcmpeqb m1, [base+z_filt_wh4] + pand m1, m3 + pcmpgtb m1, [base+z_filt_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r3d, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x55555555 + movd m3, [tlq+r3*2] + shr r5d, 30 ; filter_strength + movd [rsp+12], m1 + pshuflw m3, m3, q0000 + mova [rsp+16*1], m2 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m3 + cmp hd, 8 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w4_main: + lea tlq, [tlq+r3*2] + movd m4, dxd + movddup m1, [base+z_base_inc] ; base_inc << 6 + movd m6, [tlq] ; top[max_base_x] + shl r3d, 6 + movd m3, r3d + pshufb m4, m0 + mov r5d, dxd ; xpos + pshufb m6, m0 + sub r5, r3 + pshufb m3, m0 + paddw m5, m4, m4 + psubw m3, m1 ; max_base_x + punpcklqdq m4, m5 ; xpos0 xpos1 + movifnidn strideq, stridemp +.w4_loop: + lea r3, [r5+dxq] + sar r5, 6 ; base0 + movq m0, [tlq+r5*2+0] + movq m1, [tlq+r5*2+2] + lea r5, [r3+dxq] + sar r3, 6 ; base1 + movhps m0, [tlq+r3*2+0] + movhps m1, [tlq+r3*2+2] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 ; xpos < max_base_x + paddw m4, m5 ; xpos += dx + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jz .w4_end + lea dstq, [dstq+strideq*2] + test r5d, r5d + jl .w4_loop +.w4_end_loop: + movq [dstq+strideq*0], m6 + movq [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_end_loop +.w4_end: + RET +.w8: + lea r3d, [angleq+88] + and r3d, ~0x7f + or r3d, hd + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + movu m1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + movu m5, [tlq+ 2] ; 2 3 4 5 6 7 8 9 + movu m3, [tlq+ 4] ; 3 4 5 6 7 8 9 a + paddw m5, m1 + paddw m3, [tlq- 2] ; 0 1 2 3 4 5 6 7 + psubw m2, m5, m3 + movu m6, [tlq+18] ; a b c d e f g _ + psraw m2, 3 + movu m3, [tlq+20] ; b c d e f g _ _ + paddw m5, m2 + movu m2, [tlq+16] ; 9 a b c d e f g + paddw m6, m2 + add dxd, dxd + cmp hd, 4 + jne .w8_upsample_h8 ; awkward single-pixel edge case + pshuflw m3, m3, q1110 ; b c c _ _ _ _ _ +.w8_upsample_h8: + paddw m3, [tlq+14] ; 8 9 a b c d e f + psubw m4, m6, m3 + movd m3, bdmaxm + psraw m4, 3 + mov r3d, dxd + paddw m6, m4 + pxor m4, m4 + pmaxsw m5, m4 + pmaxsw m6, m4 + pshufb m3, m0 + pavgw m5, m4 + pavgw m6, m4 + movd m4, dxd + pminsw m5, m3 + pminsw m6, m3 + mova m3, [base+z_upsample] + pshufb m4, m0 + movifnidn strideq, stridemp + punpcklwd m0, m1, m5 + mova [rsp+ 0], m0 + punpckhwd m1, m5 + mova [rsp+16], m1 + punpcklwd m0, m2, m6 + mova [rsp+32], m0 + punpckhwd m2, m6 + mova [rsp+48], m2 + mova m5, m4 +.w8_upsample_loop: + mov r2d, r3d + shr r2d, 6 + movu m1, [rsp+r2*2+ 0] + movu m2, [rsp+r2*2+16] + add r3d, dxd + pshufb m1, m3 + pshufb m2, m3 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w8_upsample_loop + RET +.w8_no_upsample: + lea r3d, [hq+7] + movd m1, r3d + and r3d, 7 + or r3d, 8 ; imin(h+7, 15) + test angled, 0x400 + jnz .w8_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movu m2, [base+z_filt_wh8] + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pcmpeqb m2, m1 + pand m2, m3 + pcmpgtb m2, m4 + pmovmskb r5d, m2 + test r5d, r5d + jz .w8_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x55555555 + movu m3, [tlq+16*1] + movd m4, [tlq+r3*2] + shr r5d, 30 ; filter_strength + movd [rsp+12], m1 + mova [rsp+16*1], m2 + pshuflw m4, m4, q0000 + mova [rsp+16*2], m3 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m4 + cmp hd, 16 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w8_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 + movifnidn strideq, stridemp +.w8_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+0] + movu m1, [tlq+r3*2+2] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m4, 15 ; xpos < max_base_x + paddw m4, m5 ; xpos += dx + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [dstq], m0 + dec hd + jz .w8_end + add dstq, strideq + add r5, dxq + jl .w8_loop +.w8_end_loop: + mova [dstq], m6 + add dstq, strideq + dec hd + jg .w8_end_loop +.w8_end: + RET +.w16: +%if ARCH_X86_32 + %define strideq r3 +%endif + lea r3d, [hq+15] + movd m1, r3d + and r3d, 15 + or r3d, 16 ; imin(h+15, 31) + test angled, 0x400 + jnz .w16_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m1, [base+z_filt_wh16] + pand m1, m3 + pcmpgtb m1, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w16_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x24924924 + movu m3, [tlq+16*1] + movu m4, [tlq+16*2] + shr r5d, 30 + movu m5, [tlq+16*3] + movd m6, [tlq+r3*2] + adc r5d, -1 ; filter_strength + movd [rsp+12], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + pshuflw m6, m6, q0000 + mova [rsp+16*3], m4 + mova [rsp+16*4], m5 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m6 + cmp hd, 32 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w16_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w16_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + movddup m3, [base+pw_m512] + paddw m1, m2 + psraw m2, m4, 15 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*0], m0 + por m1, m3 + mova [dstq+16*1], m1 + dec hd + jz .w16_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w16_loop +.w16_end_loop: + mova [dstq+16*0], m6 + mova [dstq+16*1], m6 + add dstq, strideq + dec hd + jg .w16_end_loop +.w16_end: + RET +.w32: + lea r3d, [hq+31] + and r3d, 31 + or r3d, 32 ; imin(h+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + call .filter_copy + lea r5d, [r3+2] + cmp hd, 64 + cmove r3d, r5d + call .filter_edge_s3 +.w32_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w32_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + psraw m2, m4, 15 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m512] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*0], m0 + por m1, m2 + mova [dstq+16*1], m1 + movu m0, [tlq+r3*2+32] + movu m2, [tlq+r3*2+34] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+48] + paddw m0, m2 + movu m2, [tlq+r3*2+50] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m1024] + movddup m3, [base+pw_m1536] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*2], m0 + por m1, m3 + mova [dstq+16*3], m1 + dec hd + jz .w32_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w32_loop +.w32_end_loop: + REPX {mova [dstq+16*x], m6}, 0, 1, 2, 3 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + lea r3d, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + call .filter_copy + call .filter_edge_s3 +.w64_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w64_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + psraw m2, m4, 15 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m512] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*0], m0 + por m1, m2 + mova [dstq+16*1], m1 + movu m0, [tlq+r3*2+32] + movu m2, [tlq+r3*2+34] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+48] + paddw m0, m2 + movu m2, [tlq+r3*2+50] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m1024] + pcmpgtw m2, m4 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m1536] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*2], m0 + por m1, m2 + mova [dstq+16*3], m1 + movu m0, [tlq+r3*2+64] + movu m2, [tlq+r3*2+66] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+80] + paddw m0, m2 + movu m2, [tlq+r3*2+82] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m2048] + pcmpgtw m2, m4 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m2560] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*4], m0 + por m1, m2 + mova [dstq+16*5], m1 + movu m0, [tlq+r3*2+96] + movu m2, [tlq+r3*2+98] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+112] + paddw m0, m2 + movu m2, [tlq+r3*2+114] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m3072] + movddup m3, [base+pw_m3584] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*6], m0 + por m1, m3 + mova [dstq+16*7], m1 + dec hd + jz .w64_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w64_loop +.w64_end_loop: + REPX {mova [dstq+16*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET +ALIGN function_align +.filter_copy: + pshuflw m2, [tlq-2], q0000 + pshuflw m3, [tlq+r3*2], q0000 + xor r5d, r5d + movd [rsp+gprsize+12], m2 +.filter_copy_loop: + movu m1, [tlq+r5*2+16*0] + movu m2, [tlq+r5*2+16*1] + add r5d, 16 + mova [rsp+r5*2+gprsize-16*1], m1 + mova [rsp+r5*2+gprsize-16*0], m2 + cmp r5d, r3d + jle .filter_copy_loop + lea tlq, [rsp+gprsize+16*1] + movq [tlq+r3*2+2], m3 + ret +.filter_edge: + cmp r5d, 3 + je .filter_edge_s3 + movddup m4, [base+z_filt_k+r5*8-8] + movddup m5, [base+z_filt_k+r5*8+8] + xor r5d, r5d + movddup m6, [base+pw_8] + movu m2, [tlq-2] + jmp .filter_edge_start +.filter_edge_loop: + movu m2, [tlq+r5*2-2] + mova [tlq+r5*2-16], m1 +.filter_edge_start: + pmullw m1, m4, [tlq+r5*2] + movu m3, [tlq+r5*2+2] + paddw m2, m3 + pmullw m2, m5 + add r5d, 8 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 4 + cmp r5d, r3d + jl .filter_edge_loop + mova [tlq+r5*2-16], m1 + ret +.filter_edge_s3: + movddup m5, [base+pw_3] + xor r5d, r5d + movu m2, [tlq-2] + movu m3, [tlq-4] + jmp .filter_edge_s3_start +.filter_edge_s3_loop: + movu m2, [tlq+r5*2-2] + movu m3, [tlq+r5*2-4] + mova [tlq+r5*2-16], m1 +.filter_edge_s3_start: + paddw m2, [tlq+r5*2+0] + paddw m3, m5 + movu m1, [tlq+r5*2+2] + movu m4, [tlq+r5*2+4] + add r5d, 8 + paddw m1, m2 + pavgw m3, m4 + paddw m1, m3 + psrlw m1, 2 + cmp r5d, r3d + jl .filter_edge_s3_loop + mova [tlq+r5*2-16], m1 + ret + +%if ARCH_X86_64 +cglobal ipred_z2_16bpc, 4, 12, 11, 16*24, dst, stride, tl, w, h, angle, dx, _, dy + %define base r7-$$ + %define maxwm r6m + %define maxhm r7m + %define bdmaxm r8m + lea r7, [$$] + mov hd, hm + movddup m8, [base+pw_62] + lea r9d, [wq-4] + shl r9d, 6 + mova m9, [base+z2_top_shufA] + or r9d, hd + mova m10, [base+z2_left_shufA] +%else +cglobal ipred_z2_16bpc, 4, 7, 8, -16*27, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define r9b byte [rsp+16*26+4*0] + %define r9d dword [rsp+16*26+4*0] + %define r10d dword [rsp+16*26+4*1] + %define r11d dword [rsp+16*26+4*2] + %define maxwm [rsp+16*2+4*0] + %define maxhm [rsp+16*2+4*1] + %define bdmaxm [rsp+16*2+4*2] + %define stridemp [rsp+16*26+4*3] + %define strideq r3 + %define dyd r4 + %define dyq r4 + mov stridemp, r1 + mov r1d, r6m + mov r4d, r7m + mov r5d, r8m + mov maxwm, r1d + mov maxhm, r4d + mov bdmaxm, r5d + LEA r1, $$ + lea hd, [wq-4] + mova m0, [base+z2_top_shufA] + shl hd, 6 + mova m1, [base+z2_left_shufA] + or hd, hm + mova [rsp+16*24], m0 + mov r9d, hd + mova [rsp+16*25], m1 +%endif + tzcnt wd, wd + movifnidn angled, anglem + mova m0, [tlq-16*8] + mova m1, [tlq-16*7] + mova m2, [tlq-16*6] + mova m3, [tlq-16*5] + movsxd wq, [base+ipred_z2_16bpc_ssse3_table+wq*4] +%if ARCH_X86_64 + movzx dxd, angleb +%else + movzx dxd, byte anglem +%endif + mova m4, [tlq-16*4] + mova m5, [tlq-16*3] + mova m6, [tlq-16*2] + mova m7, [tlq-16*1] + mova [rsp+16* 5], m0 + xor angled, 0x400 + mova [rsp+16* 6], m1 + mov dyd, dxd + mova [rsp+16* 7], m2 + neg dxq + mova [rsp+16* 8], m3 + and dyd, ~1 + mova [rsp+16* 9], m4 + and dxq, ~1 + mova [rsp+16*10], m5 + lea wq, [base+ipred_z2_16bpc_ssse3_table+wq] + mova [rsp+16*11], m6 + pxor m3, m3 + mova [rsp+16*12], m7 + movzx dyd, word [base+dr_intra_derivative+dyq-90] ; angle - 90 + movzx dxd, word [base+dr_intra_derivative+dxq+180] ; 180 - angle + movddup m0, [base+pw_256] ; 4<<6 + movd m4, [tlq] + movu m5, [tlq+16*0+2] + movu m6, [tlq+16*1+2] + movsldup m1, [base+z2_dy_offset] + pshufb m4, m0 + movq m7, [base+z_base_inc+2] + mov r11d, (112-4)<<6 + mova [rsp+16*13], m4 + neg dxd + mova [rsp+16*14], m5 + or dyd, 4<<16 + mova [rsp+16*15], m6 +%if ARCH_X86_64 + lea r10d, [dxq+(112<<6)] ; xpos +%else + mov [rsp+8*3], dyd + lea r4d, [dxq+(112<<6)] + mov r10d, r4d + movzx hd, r9b +%endif + movq [rsp+8*0], m1 + movq [rsp+8*1], m0 + movq [rsp+8*2], m7 + jmp wq +.w4: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+2] + add angled, 1022 + pshuflw m1, m5, q3333 + shl r3d, 6 + movq [rsp+16*14+8], m1 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + movd m2, r3d + movd m7, angled + shr angled, 8 ; is_sm << 1 + pshufb m2, m3 + pshufb m7, m3 + pcmpeqb m2, [base+z_filt_wh4] + pand m7, m2 + pcmpgtb m7, [base+z_filt_t_w48+angleq*8] + jmp .w8_filter_left +.upsample_above: ; w4/w8 + paddw m2, m5, [tlq] + movu m1, [rsp+gprsize+16*14+2] + movu m4, [rsp+gprsize+16*14-4] +%if ARCH_X86_64 + movd m6, r9m ; bdmax, offset due to call +%else + movd m6, [rsp+gprsize+16*2+4*2] +%endif + paddw m4, m1 + psubw m1, m2, m4 + pshufb m6, m0 + psraw m1, 3 + paddw m2, m1 + add dxd, dxd + pmaxsw m2, m3 + paddw m7, m7 + pavgw m2, m3 + pminsw m2, m6 +%if ARCH_X86_64 + mova m9, [base+z2_top_shufB] + lea r10d, [dxq+(113<<6)] + mov r11d, (112-7)<<6 +%else + mova m1, [base+z2_top_shufB] + lea r3d, [dxq+(113<<6)] + mov dword [rsp+gprsize+16*26+4*2], (112-7)<<6 + mov [rsp+gprsize+16*26+4*1], r3d + mova [rsp+gprsize+16*24], m1 +%endif + punpcklwd m1, m2, m5 + punpckhwd m2, m5 + movq [rsp+gprsize+8*2], m7 + mova [rsp+gprsize+16*14], m1 + mova [rsp+gprsize+16*15], m2 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + mov [rsp+16*4], angled + sub angled, 1112 ; angle - 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + mova m4, [base+z_filt_wh4] + movd m7, r3d + mova m5, [base+z_filt_t_w48+angleq*8] + mov r3d, 4 + call .w8_filter_top + mov angled, [rsp+16*4] + lea r3d, [hq+2] + sub angled, 139 + shl r3d, 6 + test r3d, angled + jnz .w8_filter_left ; angle <= 140 || h > 8 || (is_sm && h == 8) +.upsample_left: ; w4/w8 + mova m2, [tlq-16] + lea r3d, [hq-4] + movu m3, [tlq-14] + movu m4, [rsp+16*12+4] + pshufb m1, m2, [base+z2_upsample_l+r3*4] + movd m6, bdmaxm + pxor m5, m5 + paddw m3, m2 + paddw m4, m1 + psubw m1, m3, m4 + movshdup m4, [base+z2_dy_offset] + psraw m1, 3 + pshufb m6, m0 + paddw m3, m1 + pmaxsw m3, m5 + pavgw m3, m5 + pminsw m3, m6 +%if ARCH_X86_64 + mova m10, [base+z2_left_shufB] + add dyd, dyd +%else + mova m1, [base+z2_left_shufB] + shl dword [rsp+8*3], 1 + mova [rsp+16*25], m1 +%endif + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + movq [rsp+8*0], m4 + mova [rsp+16*12], m1 + mova [rsp+16*11], m2 +.w4_main: + movd m6, dxd +%if ARCH_X86_64 + movd m3, dyd +%else + movd m3, [rsp+8*3] +%endif + pshufb m6, m0 + movddup m0, [rsp+8*2] + paddw m7, m6, m6 + movq m5, [base+pw_m1to4] + pshuflw m4, m3, q0000 + punpcklqdq m6, m7 + pmullw m4, m5 + pshuflw m3, m3, q1111 + paddw m6, m0 + mov r2d, r10d + pshuflw m0, m4, q3333 + psubw m4, [rsp+8*0] + movq [rsp+8*3], m3 + movq [rsp+8*5], m0 ; dy*4 + mov r5, dstq +.w4_loop0: + mova [rsp+16*4], m6 + movq [rsp+8*4], m4 +%if ARCH_X86_64 + pand m0, m8, m4 +%else + movq m0, [base+pw_62] + pand m0, m4 +%endif + psraw m4, 6 + psllw m0, 9 ; frac_y << 9 + movq [rsp+8*7], m0 + pabsw m4, m4 + movq [rsp+8*6], m4 + movzx hd, r9b +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu m2, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu m1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movu m3, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movu m4, [rsp+r3*2] +%if ARCH_X86_64 + REPX {pshufb x, m9}, m2, m1, m3, m4 +%else + mova m0, [rsp+16*24] + REPX {pshufb x, m0}, m2, m1, m3, m4 +%endif + punpcklqdq m0, m2, m1 + punpckhqdq m2, m1 + punpcklqdq m1, m3, m4 + punpckhqdq m3, m4 +%if ARCH_X86_64 + pand m5, m8, m6 +%else + movddup m5, [base+pw_62] + pand m5, m6 +%endif + psllw m5, 9 + psubw m2, m0 + pmulhrsw m2, m5 + paddw m5, m6, m7 + psubw m3, m1 + paddw m0, m2 +%if ARCH_X86_64 + pand m2, m8, m5 +%else + movddup m2, [base+pw_62] + pand m2, m5 +%endif + psllw m2, 9 + pmulhrsw m3, m2 + paddw m1, m3 + cmp r3d, 111 ; topleft + jge .w4_toponly + mova [rsp+16*22], m0 + mova [rsp+16*23], m1 + movzx r3d, byte [rsp+8*6+0] ; base_y0 + movu m3, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+2] ; base_y1 + movu m2, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+4] ; base_y2 + movu m4, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+6] ; base_y3 + movu m0, [rsp+r3*2] +%if ARCH_X86_64 + REPX {pshufb x, m10}, m3, m2, m4, m0 +%else + mova m1, [rsp+16*25] + REPX {pshufb x, m1}, m3, m2, m4, m0 +%endif + punpcklwd m1, m3, m2 + punpckhwd m3, m2 ; 01 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 ; 23 + punpckldq m0, m1, m2 ; y0 d1 + punpckhdq m1, m2 ; y2 y3 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + movddup m4, [rsp+8*7] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + psraw m6, 15 ; base_x < topleft + psraw m4, m5, 15 + paddw m0, m2 + paddw m1, m3 + pand m0, m6 + pandn m6, [rsp+16*22] + pand m1, m4 + pandn m4, [rsp+16*23] + por m0, m6 + por m1, m4 +.w4_toponly: + movifnidn strideq, stridemp + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jz .w4_end + movq m4, [rsp+8*6] + paddsw m6, m5, m7 ; xpos += dx + movq m5, [rsp+8*3] + psubw m4, m5 + lea dstq, [dstq+strideq*2] + movq [rsp+8*6], m4 + cmp r2d, r11d + jge .w4_loop +.w4_leftonly_loop: + movzx r2d, byte [rsp+8*6+0] ; base_y0 + movu m3, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+2] ; base_y1 + movu m2, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+4] ; base_y2 + movu m6, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+6] ; base_y3 + movu m0, [rsp+r2*2] + psubw m4, m5 +%if ARCH_X86_64 + REPX {pshufb x, m10}, m3, m2, m6, m0 +%else + mova m1, [rsp+16*25] + REPX {pshufb x, m1}, m3, m2, m6, m0 +%endif + movq [rsp+8*6], m4 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m6, m0 + punpckhwd m6, m0 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m6 + punpckhdq m3, m6 + movddup m6, [rsp+8*7] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m6 + pmulhrsw m3, m6 + paddw m0, m2 + paddw m1, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + sub r9d, 1<<8 + jl .w4_ret + movq m4, [rsp+8*5] + add r5, 8 + mov dstq, r5 + paddw m4, [rsp+8*4] ; base_y += 4*dy + movzx r2d, word [rsp+8*1] + movddup m6, [rsp+8*1] + paddw m6, [rsp+16*4] ; base_x += (4 << upsample_above) + add r2d, r10d + mov r10d, r2d + jmp .w4_loop0 +.w4_ret: + RET +.w8: + test angled, 0x400 + jnz .w4_main + lea r3d, [angleq+126] + pshufhw m1, m5, q3333 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + movhps [rsp+16*15], m1 + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + call .upsample_above + sub angled, 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + movu m1, [base+z_filt_wh8] + movd m2, r3d + movd m7, angled + shr angled, 8 ; is_sm << 1 + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pshufb m2, m3 + pshufb m7, m3 + pcmpeqb m2, m1 + movq m1, [base+pw_512] + pand m7, m2 + pcmpgtb m7, m4 + movq [rsp+8*1], m1 ; 8<<6 + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + mov [rsp+16*4], angled + sub angled, 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m4, [base+z_filt_wh8] + movd m7, r3d + psrldq m5, [base+z_filt_t_w48+angleq*8], 4 + mov r3d, 8 + call .w8_filter_top + mov r3d, [rsp+16*4] + sub r3d, 141 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + cmp r3d, 8 + jbe .upsample_left ; angle > 140 && h <= 8 && !is_sm +.w8_filter_left: + pmovmskb r5d, m7 + test r5d, r5d + jz .w4_main + imul r5d, 0x55555555 + neg hq + mov r3, tlq + movd m1, [tlq+hq*2] + shr r5d, 30 ; filter_strength + lea tlq, [rsp+16*13-2] + pshuflw m1, m1, q0000 + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge + jmp .filter_left_end +.w8_filter_top: + REPX {pshufb x, m3}, m2, m1, m7 + pcmpeqb m2, m4 + pand m1, m2 + pand m7, m2 + pcmpgtb m1, m5 + pcmpgtb m7, m5 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_filter_top_end ; filter_strength == 0 + imul r5d, 0x55555555 + mov [dstq], tlq + lea tlq, [rsp+16*14+gprsize] + shr r5d, 30 ; filter_strength + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge +%if ARCH_X86_64 + mov r3d, r7m ; maxw, offset due to call +%else + mov r3d, [rsp+16*2+4*1] +%endif + mov tlq, [dstq] + cmp r3d, 8 + jge .w8_filter_top_end + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14+gprsize], m1 + movu [rsp+r3*2+16*15+gprsize], m2 +.w8_filter_top_end: + ret +.w16: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+15] + sub angled, 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movd m7, r3d + REPX {pshufb x, m3}, m2, m1, m7 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m2, [base+z_filt_wh16] + pand m1, m2 + pand m7, m2 + pcmpgtb m1, m4 + pcmpgtb m7, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w16_filter_left ; filter_strength == 0 + imul r5d, 0x24924924 + pshufhw m6, m6, q3333 + mov [dstq], tlq + lea tlq, [rsp+16*14] + shr r5d, 30 + movhps [tlq+16*2], m6 + adc r5d, -1 ; filter_strength + mov r3d, 16 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 16 + jge .w16_filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 +.w16_filter_left: + pmovmskb r5d, m7 + test r5d, r5d + jz .w4_main + imul r5d, 0x24924924 + neg hq + mov r3, tlq + movd m1, [tlq+hq*2] + shr r5d, 30 + lea tlq, [rsp+16*13-2] + pshuflw m1, m1, q0000 + adc r5d, -1 ; filter_strength + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge + jmp .filter_left_end +.w32: + movu m1, [tlq+16*2+2] + movu m2, [tlq+16*3+2] + mova [rsp+16*16], m1 + mova [rsp+16*17], m2 + test angled, 0x400 + jnz .w4_main + mov [dstq], tlq + lea tlq, [rsp+16*14] + pshufhw m2, m2, q3333 + mov r3d, 32 + movhps [tlq+16*4], m2 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge_s3 + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 32 + jge .filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 + cmp r3d, 16 + jge .filter_left + movu m1, [tlq+r3*2+16*2+2] + movu m2, [tlq+r3*2+16*3+2] + movu [rsp+r3*2+16*16], m1 + movu [rsp+r3*2+16*17], m2 +.filter_left: + neg hq + mov r3, tlq + pshuflw m1, [tlq+hq*2], q0000 + lea tlq, [rsp+16*13-2] + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge_s3 +.filter_left_end: + mov r2d, maxhm + cmp r2d, hd + jge .w4_main + neg r2 + movu m1, [r3+r2*2-16*1] + movu m2, [r3+r2*2-16*2] + movu [rsp+r2*2+16*12], m1 + movu [rsp+r2*2+16*11], m2 + cmp r2d, -48 + jle .w4_main + movu m1, [r3+r2*2-16*3] + movu m2, [r3+r2*2-16*4] + movu [rsp+r2*2+16*10], m1 + movu [rsp+r2*2+16* 9], m2 + cmp r2d, -32 + jle .w4_main + movu m1, [r3+r2*2-16*5] + movu m2, [r3+r2*2-16*6] + movu [rsp+r2*2+16* 8], m1 + movu [rsp+r2*2+16* 7], m2 + cmp r2d, -16 + jle .w4_main + movu m1, [r3+r2*2-16*7] + movu m2, [r3+r2*2-16*8] + movu [rsp+r2*2+16* 6], m1 + movu [rsp+r2*2+16* 5], m2 + jmp .w4_main +.w64: + movu m1, [tlq+16*2+2] + movu m2, [tlq+16*3+2] + movu m3, [tlq+16*4+2] + movu m4, [tlq+16*5+2] + movu m5, [tlq+16*6+2] + movu m6, [tlq+16*7+2] + mov [dstq], tlq + lea tlq, [rsp+16*14] + mova [tlq+16*2], m1 + mova [tlq+16*3], m2 + mova [tlq+16*4], m3 + mova [tlq+16*5], m4 + mova [tlq+16*6], m5 + mova [tlq+16*7], m6 + test angled, 0x400 + jnz .w4_main + pshufhw m6, m6, q3333 + mov r3d, 64 + movhps [tlq+16*8], m6 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge_s3 + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 64 + jge .filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 + cmp r3d, 48 + jge .filter_left + movu m1, [tlq+r3*2+16*2+2] + movu m2, [tlq+r3*2+16*3+2] + movu [rsp+r3*2+16*16], m1 + movu [rsp+r3*2+16*17], m2 + cmp r3d, 32 + jge .filter_left + movu m1, [tlq+r3*2+16*4+2] + movu m2, [tlq+r3*2+16*5+2] + movu [rsp+r3*2+16*18], m1 + movu [rsp+r3*2+16*19], m2 + cmp r3d, 16 + jge .filter_left + movu m1, [tlq+r3*2+16*6+2] + movu m2, [tlq+r3*2+16*7+2] + movu [rsp+r3*2+16*20], m1 + movu [rsp+r3*2+16*21], m2 + jmp .filter_left + +%if ARCH_X86_64 +cglobal ipred_z3_16bpc, 4, 9, 8, 16*18, dst, stride, tl, w, h, angle, dy, _, org_w + %define base r7-$$ + lea r7, [$$] + mov org_wd, wd +%else +cglobal ipred_z3_16bpc, 4, 7, 8, -16*18, dst, stride, tl, w, h, angle, dy + %define base r1-$$ + %define org_wd r5 + %define org_wq r5 + movd m6, r8m ; pixel_max + mov [dstq+4*0], strideq + LEA r1, $$ + mov [dstq+4*1], wd +%endif + tzcnt hd, hm + movifnidn angled, anglem + sub tlq, 2 + movsxd hq, [base+ipred_z3_16bpc_ssse3_table+hq*4] + sub angled, 180 + movddup m0, [base+pw_256] + mov dyd, angled + neg dyd + xor angled, 0x400 + movddup m7, [base+pw_62] + or dyq, ~0x7e + lea hq, [base+ipred_z3_16bpc_ssse3_table+hq] + movzx dyd, word [base+dr_intra_derivative+45*2-1+dyq] + jmp hq +.h4: + lea r4d, [angleq+88] + test r4d, 0x480 + jnz .h4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r4d, 9 + add r4d, wd + cmp r4d, 8 + jg .h4_no_upsample ; w > 8 || (w == 8 && is_sm) + mova m2, [tlq-14] ; 7 6 5 4 3 2 1 0 + movu m3, [tlq-12] ; 8 7 6 5 4 3 2 1 +%if ARCH_X86_64 + movd m6, r8m +%endif + pshufb m4, m2, m0 + mov tlq, rsp + palignr m1, m2, m4, 14 ; 8 8 7 6 5 4 3 2 + add dyd, dyd + palignr m5, m2, m4, 12 ; 8 8 8 7 6 5 4 3 + paddw m1, m2 + paddw m3, m5 + psubw m5, m1, m3 + mova m3, [base+z_upsample] + mova [tlq+ 0], m4 + movd m4, dyd + psraw m5, 3 + neg dyd + paddw m1, m5 + pxor m5, m5 + lea r5d, [dyq+(16<<6)+63] ; ypos + pmaxsw m1, m5 + pshufb m6, m0 + shl wd, 3 + pavgw m1, m5 + pshufb m4, m0 + pminsw m1, m6 + sub rsp, wq + punpckhwd m0, m1, m2 + paddw m5, m4, m4 + punpcklwd m1, m2 + mova [tlq+32], m0 + movsd m4, m5 + mova [tlq+16], m1 +.h4_upsample_loop: + lea r4d, [r5+dyq] + sar r5d, 6 + movu m2, [tlq+r5*2] + lea r5d, [r4+dyq] + sar r4d, 6 + movu m1, [tlq+r4*2] + pshufb m2, m3 + pshufb m1, m3 + punpckhqdq m0, m1, m2 + punpcklqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jg .h4_upsample_loop + or r3d, 4*2 + jmp .end_transpose +.h4_no_upsample: + mov r4d, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea r4d, [wq+3] + movd m1, r4d + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + pcmpeqb m1, [base+z_filt_wh4] + pand m1, m3 + pcmpgtb m1, [base+z_filt_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r4d, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + imul r5d, 0x55555555 + mova m2, [tlq-14] + neg r4 + movd m3, [tlq+r4*2] + shr r5d, 30 + movd [rsp+16*17], m1 + pshuflw m3, m3, q0000 + mova [rsp+16*16], m2 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m3 + cmp wd, 8 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h4_main: + movd m4, dyd + sub tlq, r4 + movddup m1, [base+z_base_inc_z2+8] ; base_inc << 6 + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m4, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] ; ypos + pshufb m3, m0 + shl wd, 3 + paddw m5, m4, m4 + sub rsp, wq + psubw m3, m1 ; max_base_y + movsd m4, m5 ; ypos1 ypos0 +.h4_loop: + lea r4, [r5+dyq] + sar r5, 6 + movddup m0, [tlq+r5*2-6] + movddup m1, [tlq+r5*2-8] + lea r5, [r4+dyq] + sar r4, 6 + movlps m0, [tlq+r4*2-6] + movlps m1, [tlq+r4*2-8] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 + paddw m4, m5 + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [rsp+wq-16], m0 + sub wd, 16 + jz .h4_transpose + test r5d, r5d + jg .h4_loop +.h4_end_loop: + mova [rsp+wq-16], m6 + sub wd, 16 + jg .h4_end_loop +.h4_transpose: + or r3d, 4*2 + jmp .end_transpose +.h8: + lea r4d, [angleq+88] + and r4d, ~0x7f + or r4d, wd + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m2, [tlq-30] ; g f e d c b a 9 + movu m1, [tlq-32] ; _ g f e d c b a + movu m3, [tlq-16] ; 9 8 7 6 5 4 3 2 + paddw m3, [tlq-14] ; 8 7 6 5 4 3 2 1 + pshufd m4, m2, q2100 ; _ _ g f e d c b + paddw m1, m2 + movu m5, [tlq-28] ; f e d c b a 9 8 + add dyd, dyd + cmp wd, 8 + je .h8_upsample_w8 + pshufhw m4, m2, q1000 ; _ _ _ _ c c c b +.h8_upsample_w8: + paddw m4, m5 + psubw m5, m1, m4 + movu m4, [tlq-18] ; a 9 8 7 6 5 4 3 + psraw m5, 3 + paddw m1, m5 + movu m5, [tlq-12] ; 7 6 5 4 3 2 1 0 +%if ARCH_X86_64 + movd m6, r8m ; pixel_max +%endif + paddw m4, m5 + shl wd, 4 + psubw m5, m3, m4 + movd m4, dyd + psraw m5, 3 + neg dyd + paddw m3, m5 + pshufb m6, m0 + mova m5, [tlq-14] + pshufb m4, m0 + pxor m0, m0 + pmaxsw m1, m0 + pmaxsw m3, m0 + mov tlq, rsp + pavgw m1, m0 + pavgw m3, m0 + sub rsp, wq + pminsw m1, m6 + pminsw m6, m3 + mova m3, [base+z_upsample] + lea r5d, [dyq+(16<<6)+63] ; ypos + punpcklwd m0, m1, m2 + mova [tlq+16*0], m0 + punpckhwd m1, m2 + mova [tlq+16*1], m1 + punpcklwd m0, m6, m5 + mova [tlq+16*2], m0 + punpckhwd m6, m5 + mova [tlq+16*3], m6 + mova m5, m4 +.h8_upsample_loop: + mov r4d, r5d + sar r4d, 6 + movu m1, [tlq+r4*2+16*0] + movu m2, [tlq+r4*2+16*1] + add r5d, dyd + pshufb m2, m3 + pshufb m1, m3 + punpckhqdq m0, m1, m2 + punpcklqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jg .h8_upsample_loop + or r3d, 8*2 + jmp .end_transpose +.h8_no_upsample: + lea r4d, [wq+7] + movd m1, r4d + and r4d, 7 + or r4d, 8 ; imin(w+7, 15) + test angled, 0x400 + jnz .h8_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movu m2, [base+z_filt_wh8] + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pcmpeqb m2, m1 + pand m2, m3 + pcmpgtb m2, m4 + pmovmskb r5d, m2 + test r5d, r5d + jz .h8_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + imul r5d, 0x55555555 + mova m2, [tlq-16*1+2] + neg r4 + mova m3, [tlq-16*2+2] + shr r5d, 30 + movd m4, [tlq+r4*2] + movd [rsp+16*17], m1 + mova [rsp+16*16], m2 + pshuflw m4, m4, q0000 + mova [rsp+16*15], m3 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m4 + cmp wd, 16 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h8_main: + sub tlq, r4 + movd m4, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m4, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + shl wd, 4 + mova m5, m4 + sub rsp, wq + psubw m3, [base+z_base_inc_z2] +.h8_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m1, [tlq+r4*2-16] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 + paddw m4, m5 + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [rsp+wq-16], m0 + sub wd, 8*2 + jz .h8_transpose + add r5, dyq + jg .h8_loop +.h8_end_loop: + mova [rsp+wq-16], m6 + sub wd, 8*2 + jg .h8_end_loop +.h8_transpose: + or r3d, 8*2 + jmp .end_transpose +.h16: + lea r4d, [wq+15] + movd m1, r4d + and r4d, 15 + or r4d, 16 ; imin(w+15, 31) + test angled, 0x400 + jnz .h16_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m1, [base+z_filt_wh16] + pand m1, m3 + pcmpgtb m1, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .h16_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + mova m2, [tlq-16*1+2] + imul r5d, 0x24924924 + mova m3, [tlq-16*2+2] + neg r4 + mova m4, [tlq-16*3+2] + shr r5d, 30 + mova m5, [tlq-16*4+2] + movd m6, [tlq+r4*2] + adc r5d, -1 ; filter_strength + movd [rsp+16*17], m1 + mova [rsp+16*16], m2 + mova [rsp+16*15], m3 + pshuflw m6, m6, q0000 + mova [rsp+16*14], m4 + mova [rsp+16*13], m5 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m6 + cmp wd, 32 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h16_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + shl wd, 5 + paddw m4, m5, [base+z_base_inc_z2] + sub rsp, wq + psubw m4, m3 +.h16_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m2, [tlq+r4*2-16] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r4*2-30] + paddw m0, m2 + movu m2, [tlq+r4*2-32] + psubw m2, m1 + pmulhrsw m2, m3 + movddup m3, [base+pw_m512] + paddw m1, m2 + psraw m2, m4, 15 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+wq-16*1], m0 + por m1, m3 + mova [rsp+wq-16*2], m1 + sub wd, 16*2 + jz .h16_transpose + add r5, dyq + jg .h16_loop +.h16_end_loop: + mova [rsp+wq-16*1], m6 + mova [rsp+wq-16*2], m6 + sub wd, 16*2 + jg .h16_end_loop +.h16_transpose: + or r3d, 16*2 + jmp .end_transpose +.h32: + lea r4d, [wq+31] + and r4d, 31 + or r4d, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + call .filter_copy + lea r5, [r4-2] + cmp wd, 64 + cmove r4, r5 + call .filter_edge_s3 +.h32_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + paddw m4, m5, [base+z_base_inc_z2] + psubw m4, m3 +.h32_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m3, [tlq+r4*2-16] + pand m2, m7, m4 + psllw m2, 9 + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-30] + paddw m0, m3 + movu m3, [tlq+r4*2-32] + psubw m3, m1 + pmulhrsw m3, m2 + sub rsp, 16*4 + paddw m1, m3 + psraw m3, m4, 15 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m512] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*3], m0 + por m1, m3 + mova [rsp+16*2], m1 + movu m0, [tlq+r4*2-46] + movu m3, [tlq+r4*2-48] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-62] + paddw m0, m3 + movu m3, [tlq+r4*2-64] + psubw m3, m1 + pmulhrsw m3, m2 + movddup m2, [base+pw_m1024] + paddw m1, m3 + movddup m3, [base+pw_m1536] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+16*1], m0 + por m1, m3 + mova [rsp+16*0], m1 + dec wd + jz .h32_transpose + add r5, dyq + jg .h32_loop +.h32_end_loop: + sub rsp, 16*4 + REPX {mova [rsp+16*x], m6}, 3, 2, 1, 0 + dec wd + jg .h32_end_loop +.h32_transpose: + or r3d, 32*2 + jmp .end_transpose +.h64: + lea r4d, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + call .filter_copy + call .filter_edge_s3 +.h64_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + paddw m4, m5, [base+z_base_inc_z2] + psubw m4, m3 +.h64_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2- 14] + movu m3, [tlq+r4*2- 16] + pand m2, m7, m4 + psllw m2, 9 + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 30] + paddw m0, m3 + movu m3, [tlq+r4*2- 32] + psubw m3, m1 + pmulhrsw m3, m2 + sub rsp, 16*8 + paddw m1, m3 + psraw m3, m4, 15 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m512] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*7], m0 + por m1, m3 + mova [rsp+16*6], m1 + movu m0, [tlq+r4*2- 46] + movu m3, [tlq+r4*2- 48] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 62] + paddw m0, m3 + movu m3, [tlq+r4*2- 64] + psubw m3, m1 + pmulhrsw m3, m2 + paddw m1, m3 + movddup m3, [base+pw_m1024] + pcmpgtw m3, m4 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m1536] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*5], m0 + por m1, m3 + mova [rsp+16*4], m1 + movu m0, [tlq+r4*2- 78] + movu m3, [tlq+r4*2- 80] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 94] + paddw m0, m3 + movu m3, [tlq+r4*2- 96] + psubw m3, m1 + pmulhrsw m3, m2 + paddw m1, m3 + movddup m3, [base+pw_m2048] + pcmpgtw m3, m4 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m2560] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*3], m0 + por m1, m3 + mova [rsp+16*2], m1 + movu m0, [tlq+r4*2-110] + movu m3, [tlq+r4*2-112] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-126] + paddw m0, m3 + movu m3, [tlq+r4*2-128] + psubw m3, m1 + pmulhrsw m3, m2 + movddup m2, [base+pw_m3072] + paddw m1, m3 + movddup m3, [base+pw_m3584] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+16*1], m0 + por m1, m3 + mova [rsp+16*0], m1 + dec wd + jz .h64_transpose + add r5, dyq + jg .h64_loop +.h64_end_loop: + sub rsp, 16*8 + REPX {mova [rsp+16*x], m6}, 7, 6, 5, 4, 3, 2, 1, 0 + dec wd + jg .h64_end_loop +.h64_transpose: + add r3d, 64*2 +.end_transpose: +%if ARCH_X86_64 + lea r7, [strideq*3] +%else + mov strideq, [dstq+4*0] + mov org_wd, [dstq+4*1] +%endif + lea r4d, [r3*3] +.end_transpose_loop: + lea r2, [rsp+r3-8] + lea r6, [dstq+org_wq*2-8] +.end_transpose_loop_y: + movq m0, [r2+r4 ] + movq m1, [r2+r3*2] + movq m2, [r2+r3*1] + movq m3, [r2+r3*0] + sub r2, 8 + punpcklwd m0, m1 + punpcklwd m2, m3 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + movhps [r6+strideq*0], m1 + movq [r6+strideq*1], m1 +%if ARCH_X86_64 + movhps [r6+strideq*2], m0 + movq [r6+r7 ], m0 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m0 + movq [r6+strideq*1], m0 + lea r6, [r6+strideq*2] +%endif + cmp r2, rsp + jae .end_transpose_loop_y + lea rsp, [rsp+r3*4] + sub org_wd, 4 + jg .end_transpose_loop + RET +.filter_copy: + neg r4 + pshuflw m2, [tlq+2], q0000 + xor r5d, r5d + pshuflw m3, [tlq+r4*2], q0000 + movq [rsp+gprsize+16*17], m2 +.filter_copy_loop: + mova m1, [tlq+r5*2-16*1+2] + mova m2, [tlq+r5*2-16*2+2] + sub r5, 16 + mova [rsp+r5*2+gprsize+16*18], m1 + mova [rsp+r5*2+gprsize+16*17], m2 + cmp r5d, r4d + jg .filter_copy_loop + lea tlq, [rsp+gprsize+16*17-2] + movq [tlq+r4*2-8], m3 + ret +.filter_edge: + cmp r5d, 3 + je .filter_edge_s3 + movddup m4, [base+z_filt_k+r5*8-8] + movddup m5, [base+z_filt_k+r5*8+8] + xor r5d, r5d + movddup m6, [base+pw_8] + movu m2, [tlq-12] + jmp .filter_edge_start +.filter_edge_loop: + movu m2, [tlq+r5*2-12] + mova [tlq+r5*2+2], m1 +.filter_edge_start: + pmullw m1, m4, [tlq+r5*2-14] + movu m3, [tlq+r5*2-16] + sub r5, 8 + paddw m2, m3 + pmullw m2, m5 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 4 + cmp r5d, r4d + jg .filter_edge_loop + mova [tlq+r5*2+2], m1 + neg r4d + ret +.filter_edge_s3: + movddup m5, [base+pw_3] + xor r5d, r5d + movu m2, [tlq-12] + movu m3, [tlq-10] + jmp .filter_edge_s3_start +.filter_edge_s3_loop: + movu m2, [tlq+r5*2-12] + movu m3, [tlq+r5*2-10] + mova [tlq+r5*2+2], m1 +.filter_edge_s3_start: + paddw m2, [tlq+r5*2-14] + paddw m3, m5 + movu m1, [tlq+r5*2-16] + movu m4, [tlq+r5*2-18] + sub r5, 8 + paddw m1, m2 + pavgw m3, m4 + paddw m1, m3 + psrlw m1, 2 + cmp r5d, r4d + jg .filter_edge_s3_loop + mova [tlq+r5*2+2], m1 + neg r4d + ret + +%if ARCH_X86_64 +cglobal ipred_filter_16bpc, 4, 7, 16, dst, stride, tl, w, h, filter +%else +cglobal ipred_filter_16bpc, 4, 7, 8, -16*8, dst, stride, tl, w, h, filter +%define m8 [esp+16*0] +%define m9 [esp+16*1] +%define m10 [esp+16*2] +%define m11 [esp+16*3] +%define m12 [esp+16*4] +%define m13 [esp+16*5] +%define m14 [esp+16*6] +%define m15 [esp+16*7] +%endif +%define base r6-$$ + movifnidn hd, hm + movd m6, r8m ; bitdepth_max +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + LEA r6, $$ + shl filterd, 6 + movu m0, [tlq-6] ; __ l1 l0 tl t0 t1 t2 t3 + mova m1, [base+filter_intra_taps+filterq+16*0] + mova m2, [base+filter_intra_taps+filterq+16*1] + mova m3, [base+filter_intra_taps+filterq+16*2] + mova m4, [base+filter_intra_taps+filterq+16*3] + pxor m5, m5 +%if ARCH_X86_64 + punpcklbw m8, m5, m1 ; place 8-bit coefficients in the upper + punpckhbw m9, m5, m1 ; half of each 16-bit word to avoid + punpcklbw m10, m5, m2 ; having to perform sign-extension. + punpckhbw m11, m5, m2 + punpcklbw m12, m5, m3 + punpckhbw m13, m5, m3 + punpcklbw m14, m5, m4 + punpckhbw m15, m5, m4 +%else + punpcklbw m7, m5, m1 + mova m8, m7 + punpckhbw m7, m5, m1 + mova m9, m7 + punpcklbw m7, m5, m2 + mova m10, m7 + punpckhbw m7, m5, m2 + mova m11, m7 + punpcklbw m7, m5, m3 + mova m12, m7 + punpckhbw m7, m5, m3 + mova m13, m7 + punpcklbw m7, m5, m4 + mova m14, m7 + punpckhbw m7, m5, m4 + mova m15, m7 +%endif + mova m7, [base+filter_shuf] + add hd, hd + mov r5, dstq + pshuflw m6, m6, q0000 + mov r6, tlq + punpcklqdq m6, m6 + sub tlq, hq +.left_loop: + pshufb m0, m7 ; tl t0 t1 t2 t3 l0 l1 __ + pshufd m1, m0, q0000 + pmaddwd m2, m8, m1 + pmaddwd m1, m9 + pshufd m4, m0, q1111 + pmaddwd m3, m10, m4 + pmaddwd m4, m11 + paddd m2, m3 + paddd m1, m4 + pshufd m4, m0, q2222 + pmaddwd m3, m12, m4 + pmaddwd m4, m13 + paddd m2, m3 + paddd m1, m4 + pshufd m3, m0, q3333 + pmaddwd m0, m14, m3 + pmaddwd m3, m15 + paddd m0, m2 + paddd m1, m3 + psrad m0, 11 ; x >> 3 + psrad m1, 11 + packssdw m0, m1 + pmaxsw m0, m5 + pavgw m0, m5 ; (x + 8) >> 4 + pminsw m0, m6 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movlps m0, [tlq+hq-10] + lea dstq, [dstq+strideq*2] + sub hd, 2*2 + jg .left_loop + sub wd, 4 + jz .end + sub tld, r6d ; -h*2 + sub r6, r5 ; tl-dst +.right_loop0: + add r5, 8 + mov hd, tld + movu m0, [r5+r6] ; tl t0 t1 t2 t3 __ __ __ + mov dstq, r5 +.right_loop: + pshufd m2, m0, q0000 + pmaddwd m1, m8, m2 + pmaddwd m2, m9 + pshufd m4, m0, q1111 + pmaddwd m3, m10, m4 + pmaddwd m4, m11 + pinsrw m0, [dstq+strideq*0-2], 5 + paddd m1, m3 + paddd m2, m4 + pshufd m0, m0, q2222 + movddup m4, [dstq+strideq*1-8] + pmaddwd m3, m12, m0 + pmaddwd m0, m13 + paddd m1, m3 + paddd m0, m2 + pshuflw m2, m4, q3333 + punpcklwd m2, m5 + pmaddwd m3, m14, m2 + pmaddwd m2, m15 + paddd m1, m3 + paddd m0, m2 + psrad m1, 11 + psrad m0, 11 + packssdw m0, m1 + pmaxsw m0, m5 + pavgw m0, m5 + pminsw m0, m6 + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + palignr m0, m4, 14 + lea dstq, [dstq+strideq*2] + add hd, 2*2 + jl .right_loop + sub wd, 4 + jg .right_loop0 +.end: + RET + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal ipred_cfl_top_16bpc, 4, 7, 8, dst, stride, tl, w, h, ac + LEA t0, ipred_cfl_left_16bpc_ssse3_table + movd m4, wd + tzcnt wd, wd + movifnidn hd, hm + add tlq, 2 + movsxd r6, [t0+wq*4] + movd m5, wd + jmp mangle(private_prefix %+ _ipred_cfl_left_16bpc_ssse3.start) + +cglobal ipred_cfl_left_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + LEA t0, ipred_cfl_left_16bpc_ssse3_table + tzcnt wd, wm + lea r6d, [hq*2] + movd m4, hd + sub tlq, r6 + tzcnt r6d, hd + movd m5, r6d + movsxd r6, [t0+r6*4] +.start: + movd m7, r7m + movu m0, [tlq] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_ssse3_table-ipred_cfl_left_16bpc_ssse3_table + movsxd wq, [t0+wq*4] + pxor m6, m6 + pshuflw m7, m7, q0000 + pcmpeqw m3, m3 + add wq, t0 + movifnidn acq, acmp + pavgw m4, m6 + punpcklqdq m7, m7 + jmp r6 +.h32: + movu m1, [tlq+48] + movu m2, [tlq+32] + paddw m0, m1 + paddw m0, m2 +.h16: + movu m1, [tlq+16] + paddw m0, m1 +.h8: + pshufd m1, m0, q1032 + paddw m0, m1 +.h4: + pmaddwd m0, m3 + psubd m4, m0 + pshuflw m0, m4, q1032 + paddd m0, m4 + psrld m0, m5 + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +%macro IPRED_CFL 2 ; dst, src + pabsw m%1, m%2 + pmulhrsw m%1, m2 + psignw m%2, m1 + psignw m%1, m%2 + paddw m%1, m0 + pmaxsw m%1, m6 + pminsw m%1, m7 +%endmacro + +cglobal ipred_cfl_16bpc, 4, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd m4, t0d + tzcnt t0d, t0d + movd m5, t0d + LEA t0, ipred_cfl_16bpc_ssse3_table + tzcnt wd, wd + movd m7, r7m + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + psrlw m4, 1 + pxor m6, m6 + pshuflw m7, m7, q0000 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + pcmpeqw m3, m3 + punpcklqdq m7, m7 + jmp r6 +.h4: + movq m0, [tlq-8] + jmp wq +.w4: + movq m1, [tlq+2] + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + cmp hd, 4 + jg .w4_mul + psrld m0, 3 + jmp .w4_end +.w4_mul: + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 16 + cmove r6d, r2d + movd m1, r6d + psrld m0, 2 + pmulhuw m0, m1 + psrlw m0, 1 +.w4_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s4: + movd m1, alpham + lea r6, [strideq*3] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + movq [dstq+strideq*0], m3 + movhps [dstq+strideq*1], m3 + movq [dstq+strideq*2], m4 + movhps [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4_loop + RET +.h8: + mova m0, [tlq-16] + jmp wq +.w8: + movu m1, [tlq+2] + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmove r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+strideq*0], m3 + mova [dstq+strideq*1], m4 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s8_loop + RET +.h16: + mova m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w16: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*0], m3 + mova [dstq+16*1], m4 + add dstq, strideq + dec hd + jg .s16_loop + RET +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-48] + paddw m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w32: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + movu m2, [tlq+34] + paddw m1, m2 + movu m2, [tlq+50] + paddw m1, m2 + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 32 + je .w32_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 8 + cmove r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*0], m3 + mova [dstq+16*1], m4 + mova m4, [acq+16*2] + mova m5, [acq+16*3] + add acq, 16*4 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*2], m3 + mova [dstq+16*3], m4 + add dstq, strideq + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac + tzcnt wd, wm + LEA t0, ipred_cfl_splat_16bpc_ssse3_table + mov r6d, r7m + movifnidn hd, hm + shr r6d, 11 + movd m7, r7m + movsxd wq, [t0+wq*4] + movddup m0, [t0-ipred_cfl_splat_16bpc_ssse3_table+pw_512+r6*8] + pshuflw m7, m7, q0000 + pxor m6, m6 + add wq, t0 + movifnidn acq, acmp + punpcklqdq m7, m7 + jmp wq + +cglobal ipred_cfl_ac_420_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm +%if ARCH_X86_32 && PIC + pcmpeqw m5, m5 + pabsw m5, m5 + paddw m5, m5 +%else + movddup m5, [pw_2] +%endif + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + mov r5, acq + jg .w16 + je .w8 + lea r3, [strideq*3] +.w4_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + pmaddwd m2, m5, [ypxq+strideq*2] + pmaddwd m3, m5, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + paddd m0, m1 + paddd m2, m3 + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .dc + punpckhqdq m0, m0 + pslld m2, 2 +.w4_hpad: + mova [acq+16*0], m0 + paddd m4, m2 + mova [acq+16*1], m0 + add acq, 16*2 + sub hpadd, 4 + jg .w4_hpad + jmp .dc +.w8: +%if ARCH_X86_32 + cmp dword wpadm, 0 +%else + test wpadd, wpadd +%endif + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m2, m5, [ypxq+strideq*1+16*0] + pmaddwd m1, m5, [ypxq+strideq*0+16*1] + pmaddwd m3, m5, [ypxq+strideq*1+16*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m2 + paddd m1, m3 + paddd m2, m0, m1 + packssdw m0, m1 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + dec hd + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz .dc + pslld m2, 2 + mova m1, m0 + jmp .hpad +.w8_wpad1: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + pshufd m1, m0, q3333 + paddd m2, m0, m1 + packssdw m0, m1 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + dec hd + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad3: + pshufd m3, m0, q3333 + mova m1, m3 + mova m2, m3 + jmp .w16_wpad_end +.w16_wpad2: + pshufd m1, m3, q3333 + mova m2, m1 + jmp .w16_wpad_end +.w16_wpad1: + pshufd m2, m1, q3333 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + WIN64_SPILL_XMM 7 +.w16_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m6, m5, [ypxq+strideq*1+16*0] + paddd m0, m6 + cmp wpadd, 2 + jg .w16_wpad3 + pmaddwd m3, m5, [ypxq+strideq*0+16*1] + pmaddwd m6, m5, [ypxq+strideq*1+16*1] + paddd m3, m6 + je .w16_wpad2 + pmaddwd m1, m5, [ypxq+strideq*0+16*2] + pmaddwd m6, m5, [ypxq+strideq*1+16*2] + paddd m1, m6 + jp .w16_wpad1 + pmaddwd m2, m5, [ypxq+strideq*0+16*3] + pmaddwd m6, m5, [ypxq+strideq*1+16*3] + paddd m2, m6 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + paddd m6, m0, m3 + packssdw m0, m3 + paddd m6, m1 + mova [acq+16*0], m0 + packssdw m1, m2 + paddd m2, m6 + mova [acq+16*1], m1 + add acq, 16*2 + paddd m4, m2 + dec hd + jg .w16_loop + WIN64_RESTORE_XMM + add hpadd, hpadd + jz .dc + paddd m2, m2 +.hpad: + mova [acq+16*0], m0 + mova [acq+16*1], m1 + paddd m4, m2 + mova [acq+16*2], m0 + mova [acq+16*3], m1 + add acq, 16*4 + sub hpadd, 4 + jg .hpad +.dc: + sub r5, acq ; -w*h*2 + pshufd m2, m4, q1032 + tzcnt r1d, r5d + paddd m2, m4 + sub r1d, 2 + pshufd m4, m2, q2301 + movd m0, r1d + paddd m2, m4 + psrld m2, m0 + pxor m0, m0 + pavgw m2, m0 + packssdw m2, m2 +.dc_loop: + mova m0, [acq+r5+16*0] + mova m1, [acq+r5+16*1] + psubw m0, m2 + psubw m1, m2 + mova [acq+r5+16*0], m0 + mova [acq+r5+16*1], m1 + add r5, 16*2 + jl .dc_loop + RET + +cglobal ipred_cfl_ac_422_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm +%if ARCH_X86_32 && PIC + pcmpeqw m5, m5 + pabsw m5, m5 + psllw m5, 2 +%else + movddup m5, [pw_4] +%endif + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + mov r5, acq + jg .w16 + je .w8 + lea r3, [strideq*3] +.w4_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m3, m5, [ypxq+strideq*1] + pmaddwd m1, m5, [ypxq+strideq*2] + pmaddwd m2, m5, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + paddd m4, m0 + packssdw m0, m3 + paddd m3, m1 + packssdw m1, m2 + paddd m4, m2 + paddd m4, m3 + mova [acq+16*0], m0 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + punpckhqdq m1, m1 + pslld m2, 3 + mova [acq+16*0], m1 + mova [acq+16*1], m1 + paddd m4, m2 + mova [acq+16*2], m1 + mova [acq+16*3], m1 + add acq, 16*4 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w8: +%if ARCH_X86_32 + cmp dword wpadm, 0 +%else + test wpadd, wpadd +%endif + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m2, m5, [ypxq+strideq*0+16*1] + pmaddwd m1, m5, [ypxq+strideq*1+16*0] + pmaddwd m3, m5, [ypxq+strideq*1+16*1] + lea ypxq, [ypxq+strideq*2] + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + mova [acq+16*0], m0 + paddd m2, m1, m3 + packssdw m1, m3 + paddd m4, m2 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + pslld m2, 2 + mova m0, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w8_wpad1: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + pshufd m2, m0, q3333 + pshufd m3, m1, q3333 + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + paddd m2, m1, m3 + packssdw m1, m3 + paddd m4, m2 + mova [acq+16*0], m0 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 2 + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad3: + pshufd m3, m0, q3333 + mova m1, m3 + mova m2, m3 + jmp .w16_wpad_end +.w16_wpad2: + pshufd m1, m3, q3333 + mova m2, m1 + jmp .w16_wpad_end +.w16_wpad1: + pshufd m2, m1, q3333 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + WIN64_SPILL_XMM 7 +.w16_loop: + pmaddwd m0, m5, [ypxq+16*0] + cmp wpadd, 2 + jg .w16_wpad3 + pmaddwd m3, m5, [ypxq+16*1] + je .w16_wpad2 + pmaddwd m1, m5, [ypxq+16*2] + jp .w16_wpad1 + pmaddwd m2, m5, [ypxq+16*3] +.w16_wpad_end: + add ypxq, strideq + paddd m6, m0, m3 + packssdw m0, m3 + mova [acq+16*0], m0 + paddd m6, m1 + packssdw m1, m2 + paddd m2, m6 + mova [acq+16*1], m1 + add acq, 16*2 + paddd m4, m2 + dec hd + jg .w16_loop + WIN64_RESTORE_XMM + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + paddd m2, m2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad + +cglobal ipred_cfl_ac_444_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h +%define base r6-ipred_cfl_ac_444_16bpc_ssse3_table + LEA r6, ipred_cfl_ac_444_16bpc_ssse3_table + tzcnt wd, wm + movifnidn hpadd, hpadm + pxor m4, m4 + movsxd wq, [r6+wq*4] + movddup m5, [base+pw_1] + add wq, r6 + mov hd, hm + shl hpadd, 2 + sub hd, hpadd + jmp wq +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + movq m0, [ypxq+strideq*0] + movhps m0, [ypxq+strideq*1] + movq m1, [ypxq+strideq*2] + movhps m1, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + psllw m0, 3 + psllw m1, 3 + mova [acq+16*0], m0 + pmaddwd m0, m5 + mova [acq+16*1], m1 + pmaddwd m2, m5, m1 + add acq, 16*2 + paddd m4, m0 + paddd m4, m2 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + punpckhqdq m1, m1 + mova [acq+16*0], m1 + pslld m2, 2 + mova [acq+16*1], m1 + punpckhqdq m2, m2 + mova [acq+16*2], m1 + paddd m4, m2 + mova [acq+16*3], m1 + add acq, 16*4 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w8: + mov r5, acq +.w8_loop: + mova m0, [ypxq+strideq*0] + mova m1, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + psllw m0, 3 + psllw m1, 3 + mova [acq+16*0], m0 + pmaddwd m0, m5 + mova [acq+16*1], m1 + pmaddwd m2, m5, m1 + add acq, 16*2 + paddd m4, m0 + paddd m4, m2 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + pslld m2, 2 + mova m0, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w16_wpad2: + pshufhw m3, m2, q3333 + pshufhw m1, m0, q3333 + punpckhqdq m3, m3 + punpckhqdq m1, m1 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + mov r5, acq +.w16_loop: + mova m2, [ypxq+strideq*0+16*0] + mova m0, [ypxq+strideq*1+16*0] + psllw m2, 3 + psllw m0, 3 + test wpadd, wpadd + jnz .w16_wpad2 + mova m3, [ypxq+strideq*0+16*1] + mova m1, [ypxq+strideq*1+16*1] + psllw m3, 3 + psllw m1, 3 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + mova [acq+16*0], m2 + pmaddwd m2, m5 + mova [acq+16*1], m3 + pmaddwd m3, m5 + paddd m4, m2 + pmaddwd m2, m5, m0 + mova [acq+16*2], m0 + paddd m4, m3 + pmaddwd m3, m5, m1 + mova [acq+16*3], m1 + add acq, 16*4 + paddd m2, m3 + paddd m4, m2 + sub hd, 2 + jg .w16_loop + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + paddd m2, m2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w32_wpad6: + pshufhw m1, m0, q3333 + punpckhqdq m1, m1 + mova m2, m1 + mova m3, m1 + jmp .w32_wpad_end +.w32_wpad4: + pshufhw m2, m1, q3333 + punpckhqdq m2, m2 + mova m3, m2 + jmp .w32_wpad_end +.w32_wpad2: + pshufhw m3, m2, q3333 + punpckhqdq m3, m3 + jmp .w32_wpad_end +.w32: + movifnidn wpadd, wpadm + mov r5, acq + WIN64_SPILL_XMM 8 +.w32_loop: + mova m0, [ypxq+16*0] + psllw m0, 3 + cmp wpadd, 4 + jg .w32_wpad6 + mova m1, [ypxq+16*1] + psllw m1, 3 + je .w32_wpad4 + mova m2, [ypxq+16*2] + psllw m2, 3 + jnp .w32_wpad2 + mova m3, [ypxq+16*3] + psllw m3, 3 +.w32_wpad_end: + add ypxq, strideq + pmaddwd m6, m5, m0 + mova [acq+16*0], m0 + pmaddwd m7, m5, m1 + mova [acq+16*1], m1 + paddd m6, m7 + pmaddwd m7, m5, m2 + mova [acq+16*2], m2 + paddd m6, m7 + pmaddwd m7, m5, m3 + mova [acq+16*3], m3 + add acq, 16*4 + paddd m6, m7 + paddd m4, m6 + dec hd + jg .w32_loop +%if WIN64 + mova m5, m6 + WIN64_RESTORE_XMM + SWAP 5, 6 +%endif + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w32_hpad_loop: + mova [acq+16*0], m0 + mova [acq+16*1], m1 + paddd m4, m6 + mova [acq+16*2], m2 + mova [acq+16*3], m3 + add acq, 16*4 + dec hpadd + jg .w32_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + +cglobal pal_pred_16bpc, 4, 5, 5, dst, stride, pal, idx, w, h +%define base r2-pal_pred_16bpc_ssse3_table +%if ARCH_X86_32 + %define hd r2d +%endif + mova m3, [palq] + LEA r2, pal_pred_16bpc_ssse3_table + tzcnt wd, wm + pshufb m3, [base+pal_pred_shuf] + movsxd wq, [r2+wq*4] + pshufd m4, m3, q1032 + add wq, r2 + movifnidn hd, hm + jmp wq +.w4: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4 + RET +.w8: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8 + RET +.w16: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16 + RET +.w32: + mova m0, [idxq+16*0] + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova m2, [idxq+16*1] + add idxq, 16*2 + mova [dstq+16*0], m0 + pshufb m0, m3, m2 + mova [dstq+16*1], m1 + pshufb m1, m4, m2 + punpcklbw m2, m0, m1 + punpckhbw m0, m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m0 + add dstq, strideq + dec hd + jg .w32 + RET +.w64: + mova m0, [idxq+16*0] + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova m2, [idxq+16*1] + mova [dstq+16*0], m0 + pshufb m0, m3, m2 + mova [dstq+16*1], m1 + pshufb m1, m4, m2 + punpcklbw m2, m0, m1 + punpckhbw m0, m1 + mova m1, [idxq+16*2] + mova [dstq+16*2], m2 + pshufb m2, m3, m1 + mova [dstq+16*3], m0 + pshufb m0, m4, m1 + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + mova m0, [idxq+16*3] + add idxq, 16*4 + mova [dstq+16*4], m1 + pshufb m1, m3, m0 + mova [dstq+16*5], m2 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + add dstq, strideq + dec hd + jg .w64 + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5387 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +; sm_weights[], but modified to precalculate x and 256-x with offsets to +; enable efficient use of pmaddubsw (which requires signed values) +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +pb_1to32: db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + db 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +pb_32to1: db 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17 +pb_16to1: db 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 +z_filter_wh: db 7, 7, 11, 11, 15, 15, 19, 19, 19, 23, 23, 23, 31, 31, 31, 39 + db 39, 39, 47, 47, 47, 63, 63, 63, 79, 79, 79, -1 +z_filter_k: db 0, 16, 0, 16, 0, 20, 0, 20, 8, 16, 8, 16 + db 32, 16, 32, 16, 24, 20, 24, 20, 16, 16, 16, 16 + db 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0 +z_filter_s: db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 + db 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15 + db 15, 15, 15, 15, 15, 15, 15, 15 ; should be in one cache line +pb_128: times 4 db 128 ; those are just placed here for alignment. +pb_36_m4: times 2 db 36, -4 +z3_shuf: db 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0 +z_filter_t0: db 55,127, 39,127, 39,127, 7, 15, 31, 7, 15, 31, 0, 3, 31, 0 +z_filter_t1: db 39, 63, 19, 47, 19, 47, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 +z_upsample1: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z_upsample2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8 +z2_upsample: db 7, 6, 15, 14, 5, 4, 13, 12, 3, 2, 11, 10, 1, 0, 9, 8 +z1_shuf_w4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +z2_shuf_h2: db 3, 2, 7, 6, 11, 10, 15, 14, 2, 1, 6, 5, 10, 9, 14, 13 +z2_shuf_h4: db 7, 6, 15, 14, 6, 5, 14, 13, 5, 4, 13, 12, 4, 3, 12, 11 +z3_shuf_w4: db 4, 3, 3, 2, 2, 1, 1, 0, 12, 11, 11, 10, 10, 9, 9, 8 +z_transpose4: db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 + dw 16*64, 17*64, 18*64, 19*64, 20*64, 21*64, 22*64, 23*64 +z2_base_inc: dw 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64, 8*64 + dw 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64, 16*64 +z2_ymul: dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +z2_y_shuf_h4: db 90, 90, 90, 90, 14, 14, 14, 14, 27, 27, 27, 27, 31, 31, 31, 31 ; 2, 6, 3, 7 + db 32, 32, 32, 32, 12, 12, 12, 12, 1, 0, 1, 0, 5, -1, -1, -1 ; 0, 4, 1, 5 +; vpermd indices in bits 4..6 of filter_shuf1: 0, 2, 6, 4, 1, 3, 7, 5 +filter_shuf1: db 10, 4, 10, 4, 37, 6, 5, 6,103, 9, 7, 9, 72, -1, 8, -1 + db 16, 4, 0, 4, 53, 6, 5, 6,119, 11, 7, 11, 95, -1, 15, -1 +filter_shuf2: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 2, 7, 2, 1, -1, 1, -1 +filter_shuf3: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 11, 7, 11; 15, -1, 15, -1 +pb_127_m127: times 2 db 127, -127 +ipred_v_shuf: db 0, 1, 0, 1, 4, 5, 4, 5, 8, 9, 8, 9, 12, 13, 12, 13 + db 2, 3, 2, 3, 6, 7, 6, 7, 10, 11, 10, 11, 14, 15, 14, 15 +ipred_h_shuf: db 7, 7, 7, 7, 3, 3, 3, 3, 5, 5, 5, 5, 1, 1, 1, 1 + db 6, 6, 6, 6, 2, 2, 2, 2, 4, 4, 4, 4; 0, 0, 0, 0 +pw_64: times 2 dw 64 + +cfl_ac_444_w16_pad1_shuffle: db 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1 + times 9 db 7, -1 +cfl_ac_w16_pad_shuffle: ; w=16, w_pad=1 + db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ; w=8, w_pad=1 as well as second half of previous one +cfl_ac_w8_pad1_shuffle: db 0, 1, 2, 3, 4, 5 + times 5 db 6, 7 + ; w=16,w_pad=2 + db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + times 8 db 14, 15 + ; w=16,w_pad=3 + db 0, 1, 2, 3, 4, 5 + times 13 db 6, 7 +pb_15to0: db 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +%define pb_0to15 cfl_ac_w16_pad_shuffle +%define pb_1 (ipred_h_shuf+12) +%define pb_2 (ipred_h_shuf+20) +%define pb_3 (ipred_h_shuf+ 4) +%define pb_4 (ipred_h_shuf+24) +%define pb_5 (ipred_h_shuf+ 8) +%define pb_7 (ipred_h_shuf+ 0) +%define pb_8 (z_upsample2 +12) +%define pb_12 (z2_y_shuf_h4+20) +%define pb_14 (z2_y_shuf_h4+ 4) +%define pb_15 (z_filter_s +32) +%define pb_27 (z2_y_shuf_h4+ 8) +%define pb_31 (z2_y_shuf_h4+12) +%define pb_32 (z2_y_shuf_h4+16) +%define pb_90 (z2_y_shuf_h4+ 0) +%define pw_1 (z2_y_shuf_h4+24) +%define pw_8 (z_filter_k +32) + +pw_62: times 2 dw 62 +pw_128: times 2 dw 128 +pw_255: times 2 dw 255 +pw_512: times 2 dw 512 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_avx2_table (ipred_dc_avx2_table + 10*4) +%define ipred_cfl_splat_avx2_table (ipred_cfl_avx2_table + 8*4) + +JMP_TABLE ipred_smooth, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_filter, avx2, w4, w8, w16, w32 +JMP_TABLE ipred_dc, avx2, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_h, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_cfl, avx2, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left, avx2, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_420, avx2, w16_pad1, w16_pad2, w16_pad3 +JMP_TABLE ipred_cfl_ac_422, avx2, w16_pad1, w16_pad2, w16_pad3 +JMP_TABLE ipred_cfl_ac_444, avx2, w32_pad1, w32_pad2, w32_pad3, w4, w8, w16, w32 +JMP_TABLE pal_pred, avx2, w4, w8, w16, w32, w64 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_YMM avx2 +cglobal ipred_dc_top_8bpc, 3, 7, 6, dst, stride, tl, w, h + lea r5, [ipred_dc_left_avx2_table] + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + shrx r6d, r6d, wd + movd xm3, r6d + movsxd r6, [r5+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_avx2_table-ipred_dc_left_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov r5d, 0x8000 + shrx r5d, r5d, r6d + movd xm3, r5d + lea r5, [ipred_dc_left_avx2_table] + movsxd r6, [r5+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_avx2_table-ipred_dc_left_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m1, [tlq+32] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h32: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddw xm0, xm1 +.h4: + pmaddwd xm0, xm2 + pmulhrsw xm0, xm3 + lea stride3q, [strideq*3] + vpbroadcastb m0, xm0 + mova m1, m0 + jmp wq + +cglobal ipred_dc_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm4, r5d + tzcnt r5d, r5d + movd xm5, r5d + lea r5, [ipred_dc_avx2_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pcmpeqd m3, m3 + psrlw xm4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd xm0, [tlq-4] + pmaddubsw xm0, xm3 + jmp wq +.w4: + movd xm1, [tlq+1] + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm1 + pmaddwd xm0, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddw xm0, xm1 + shrx r6d, r6d, r2d + psrlq xm1, xm0, 32 + paddw xm0, xm1 + movd xm1, r6d + psrlw xm0, 2 + pmulhuw xm0, xm1 +.w4_end: + vpbroadcastb xm0, xm0 +.s4: + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm0 + movd [dstq+strideq*2], xm0 + movd [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + movq xm0, [tlq-8] + pmaddubsw xm0, xm3 + jmp wq +.w8: + movq xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + punpckhqdq xm2, xm0, xm0 + paddw xm0, xm2 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w8_end: + vpbroadcastb xm0, xm0 +.s8: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova xm0, [tlq-16] + pmaddubsw xm0, xm3 + jmp wq +.w16: + movu xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w16_end: + vpbroadcastb xm0, xm0 +.s16: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w32_end: + vpbroadcastb m0, xm0 +.s32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-64] + mova m1, [tlq-32] + pmaddubsw m0, m3 + pmaddubsw m1, m3 + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 1] + movu m2, [tlq+33] + pmaddubsw m1, m3 + pmaddubsw m2, m3 + paddw m0, m1 + paddw m0, m2 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 64 + je .w64_end + mov r6d, 0x33345556 + shrx r6d, r6d, hd + movd xm1, r6d + pmulhuw xm0, xm1 +.w64_end: + vpbroadcastb m0, xm0 + mova m1, m0 +.s64: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m0 + mova [dstq+stride3q +32*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s64 + RET + +cglobal ipred_dc_128_8bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_avx2_table+pb_128] + mova m1, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_avx2_table] + tzcnt wd, wm + movu m0, [tlq+ 1] + movu m1, [tlq+33] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +%macro IPRED_H 2 ; w, store_type + vpbroadcastb m0, [tlq-1] + vpbroadcastb m1, [tlq-2] + vpbroadcastb m2, [tlq-3] + sub tlq, 4 + vpbroadcastb m3, [tlq+0] + mov%2 [dstq+strideq*0], m0 + mov%2 [dstq+strideq*1], m1 + mov%2 [dstq+strideq*2], m2 + mov%2 [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +ALIGN function_align +%endmacro + +INIT_XMM avx2 +cglobal ipred_h_8bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 + lea r5, [ipred_h_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + IPRED_H 4, d +.w8: + IPRED_H 8, q +.w16: + IPRED_H 16, a +INIT_YMM avx2 +.w32: + IPRED_H 32, a +.w64: + vpbroadcastb m0, [tlq-1] + vpbroadcastb m1, [tlq-2] + vpbroadcastb m2, [tlq-3] + sub tlq, 4 + vpbroadcastb m3, [tlq+0] + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m2 + mova [dstq+strideq*2+32*1], m2 + mova [dstq+stride3q +32*0], m3 + mova [dstq+stride3q +32*1], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64 + RET + +%macro PAETH 2 ; top, ldiff + pavgb m1, m%1, m3 ; Calculating tldiff normally requires + pxor m0, m%1, m3 ; 10-bit intermediates, but we can do it + pand m0, m4 ; in 8-bit with some tricks which avoids + psubusb m2, m5, m1 ; having to unpack everything to 16-bit. + psubb m1, m0 + psubusb m1, m5 + por m1, m2 + paddusb m1, m1 + por m1, m0 ; min(tldiff, 255) + psubusb m2, m5, m3 + psubusb m0, m3, m5 + por m2, m0 ; tdiff + pminub m2, m%2 + pcmpeqb m0, m%2, m2 ; ldiff <= tdiff + vpblendvb m0, m%1, m3, m0 + pminub m1, m2 + pcmpeqb m1, m2 ; ldiff <= tldiff || tdiff <= tldiff + vpblendvb m0, m5, m0, m1 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 6, 9, dst, stride, tl, w, h +%define base r5-ipred_paeth_avx2_table + lea r5, [ipred_paeth_avx2_table] + tzcnt wd, wm + vpbroadcastb m5, [tlq] ; topleft + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m4, [base+pb_1] + add wq, r5 + jmp wq +.w4: + vpbroadcastd m6, [tlq+1] ; top + mova m8, [base+ipred_h_shuf] + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + sub tlq, 8 + vpbroadcastq m3, [tlq] + pshufb m3, m8 ; left + PAETH 6, 7 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + vpbroadcastq m6, [tlq+1] + mova m8, [base+ipred_h_shuf] + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + sub tlq, 4 + vpbroadcastd m3, [tlq] + pshufb m3, m8 + PAETH 6, 7 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m6, [tlq+1] + mova xm8, xm4 ; lower half = 1, upper half = 0 + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + sub tlq, 2 + vpbroadcastd m3, [tlq] + pshufb m3, m8 + PAETH 6, 7 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w32_loop: + dec tlq + vpbroadcastb m3, [tlq] + PAETH 6, 7 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m6, [tlq+ 1] + movu m7, [tlq+33] +%if WIN64 + movaps r4m, xmm9 +%endif + psubusb m8, m5, m6 + psubusb m0, m6, m5 + psubusb m9, m5, m7 + psubusb m1, m7, m5 + por m8, m0 + por m9, m1 +.w64_loop: + dec tlq + vpbroadcastb m3, [tlq] + PAETH 6, 8 + mova [dstq+32*0], m0 + PAETH 7, 9 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop +%if WIN64 + movaps xmm9, r4m +%endif + RET + +%macro SMOOTH 6 ; src[1-2], mul[1-2], add[1-2] + ; w * a = (w - 128) * a + 128 * a + ; (256 - w) * b = (127 - w) * b + 129 * b + pmaddubsw m0, m%3, m%1 + pmaddubsw m1, m%4, m%2 + paddw m0, m%5 + paddw m1, m%6 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +cglobal ipred_smooth_v_8bpc, 3, 7, 0, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_avx2_table + lea r6, [ipred_smooth_v_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m0, [base+pb_127_m127] + vpbroadcastd m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + vpbroadcastb m5, [tlq+hq] ; bottom + add wq, r6 + jmp wq +.w4: + vpbroadcastd m2, [tlq+1] + punpcklbw m2, m5 ; top, bottom + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + punpckldq m4, m5, m5 + punpckhdq m5, m5 + pmaddubsw m3, m2, m0 + paddw m1, m2 ; 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; 128 * top + 129 * bottom + 128 +.w4_loop: + vbroadcasti128 m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 1 + pextrd [dstq+r3 ], xm1, 1 + cmp hd, -4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm1, 2 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + add hq, 8 + jl .w4_loop +.ret: + RET +ALIGN function_align +.w8: + vpbroadcastq m2, [tlq+1] + punpcklbw m2, m5 + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + pshufd m4, m5, q0000 + pshufd m5, m5, q1111 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 +.w8_loop: + vpbroadcastq m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +ALIGN function_align +.w16: + WIN64_SPILL_XMM 7 + vbroadcasti128 m3, [tlq+1] + mova m6, [base+ipred_v_shuf] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w16_loop: + vpbroadcastd m1, [weightsq+hq*2] + pshufb m1, m6 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w16_loop + RET +ALIGN function_align +.w32: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 6 + movu m3, [tlq+1] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w32_loop: + vpbroadcastw m1, [weightsq+hq*2] + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m0 + add dstq, strideq + inc hq + jl .w32_loop + RET +ALIGN function_align +.w64: + WIN64_SPILL_XMM 11 + movu m4, [tlq+ 1] + movu m8, [tlq+33] + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m7, m8, m5 + punpckhbw m8, m5 + pmaddubsw m5, m3, m0 + pmaddubsw m6, m4, m0 + pmaddubsw m9, m7, m0 + pmaddubsw m10, m8, m0 + paddw m2, m1, m3 + paddw m5, m2 + paddw m2, m1, m4 + paddw m6, m2 + paddw m0, m1, m7 + paddw m9, m0 + paddw m1, m8 + paddw m10, m1 +.w64_loop: + vpbroadcastw m2, [weightsq+hq*2] + SMOOTH 2, 2, 3, 4, 5, 6 + mova [dstq+32*0], m0 + SMOOTH 2, 2, 7, 8, 9, 10 + mova [dstq+32*1], m0 + add dstq, strideq + inc hq + jl .w64_loop + RET + +%macro SETUP_STACK_FRAME 3 ; stack_size, regs_used, xmm_regs_used + %assign stack_offset 0 + %assign stack_size_padded 0 + %assign regs_used %2 + %xdefine rstk rsp + SETUP_STACK_POINTER %1 + %if regs_used != %2 && WIN64 + PUSH r%2 + %endif + ALLOC_STACK %1, %3 +%endmacro + +cglobal ipred_smooth_h_8bpc, 3, 7, 0, dst, stride, tl, w, h +%define base r6-ipred_smooth_h_avx2_table + lea r6, [ipred_smooth_h_avx2_table] + mov wd, wm + vpbroadcastb m3, [tlq+wq] ; right + tzcnt wd, wd + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m4, [base+pb_127_m127] + vpbroadcastd m5, [base+pw_128] + add wq, r6 + jmp wq +.w4: + WIN64_SPILL_XMM 8 + vpbroadcastq m6, [base+smooth_weights+4*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 8 + sub tlq, hq + lea r3, [strideq*3] +.w4_loop: + vpbroadcastq m2, [tlq+hq] + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 8 + vbroadcasti128 m6, [base+smooth_weights+8*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq +.w8_loop: + vpbroadcastd m2, [tlq+hq] + pshufb m2, m7 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 + paddw m0, m1 + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + SETUP_STACK_FRAME 32*4, 7, 8 + lea r3, [rsp+64*2-4] + call .prep ; only worthwhile for for w16 and above + sub tlq, 2 + vpbroadcastd xm6, [base+pb_1] + mova xm7, [base+ipred_v_shuf+16] + vinserti128 m7, [base+ipred_v_shuf+ 0], 1 + vbroadcasti128 m4, [base+smooth_weights+16*2] + vbroadcasti128 m5, [base+smooth_weights+16*3] +.w16_loop: + vpbroadcastd m1, [tlq+hq] + vpbroadcastd m2, [r3+hq*2] + pshufb m1, m6 + punpcklbw m1, m3 + pshufb m2, m7 + SMOOTH 4, 5, 1, 1, 2, 2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + SETUP_STACK_FRAME 32*4, 7, 6 + lea r3, [rsp+64*2-2] + call .prep + dec tlq + mova xm4, [base+smooth_weights+16*4] + vinserti128 m4, [base+smooth_weights+16*6], 1 + mova xm5, [base+smooth_weights+16*5] + vinserti128 m5, [base+smooth_weights+16*7], 1 +.w32_loop: + vpbroadcastb m1, [tlq+hq] + punpcklbw m1, m3 + vpbroadcastw m2, [r3+hq*2] + SMOOTH 4, 5, 1, 1, 2, 2 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + SETUP_STACK_FRAME 32*4, 7, 9 + lea r3, [rsp+64*2-2] + call .prep + add r6, smooth_weights+16*15-ipred_smooth_h_avx2_table + dec tlq + mova xm5, [r6-16*7] + vinserti128 m5, [r6-16*5], 1 + mova xm6, [r6-16*6] + vinserti128 m6, [r6-16*4], 1 + mova xm7, [r6-16*3] + vinserti128 m7, [r6-16*1], 1 + mova xm8, [r6-16*2] + vinserti128 m8, [r6-16*0], 1 +.w64_loop: + vpbroadcastb m2, [tlq+hq] + punpcklbw m2, m3 + vpbroadcastw m4, [r3+hq*2] + SMOOTH 5, 6, 2, 2, 4, 4 + mova [dstq+32*0], m0 + SMOOTH 7, 8, 2, 2, 4, 4 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +ALIGN function_align +.prep: + vpermq m2, [tlq-32*1], q3120 + punpckhbw m1, m2, m3 + punpcklbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m1, m5 ; 1 * left + 256 * right + 128 + paddw m0, m1 ; 128 * left + 129 * right + 128 + pmaddubsw m1, m2, m4 + paddw m2, m5 + paddw m1, m2 + vpermq m2, [tlq-32*2], q3120 + mova [rsp+gprsize+32*3], m0 + mova [rsp+gprsize+32*2], m1 + punpckhbw m1, m2, m3 + punpcklbw m2, m3 + pmaddubsw m0, m1, m4 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m2, m5 + paddw m1, m2 + mova [rsp+gprsize+32*1], m0 + mova [rsp+gprsize+32*0], m1 + sub r3, hq + sub tlq, hq + sub r3, hq + ret + +%macro SMOOTH_2D_END 6 ; src[1-2], mul[1-2], add[1-2] + pmaddubsw m0, m%3, m%1 + pmaddubsw m1, m%4, m%2 +%ifnum %5 + paddw m0, m%5 +%else + paddw m0, %5 +%endif +%ifnum %6 + paddw m1, m%6 +%else + paddw m1, %6 +%endif + pavgw m0, m2 + pavgw m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +cglobal ipred_smooth_8bpc, 3, 7, 0, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_avx2_table + lea r6, [ipred_smooth_avx2_table] + mov wd, wm + vpbroadcastb m4, [tlq+wq] ; right + tzcnt wd, wd + mov hd, hm + mov r5, tlq + sub r5, hq + movsxd wq, [r6+wq*4] + vpbroadcastd m5, [base+pb_127_m127] + vpbroadcastb m0, [r5] ; bottom + vpbroadcastd m3, [base+pw_255] + add wq, r6 + lea v_weightsq, [base+smooth_weights+hq*2] + jmp wq +.w4: + WIN64_SPILL_XMM 12 + mova m10, [base+ipred_h_shuf] + vpbroadcastq m11, [base+smooth_weights+4*2] + mova m7, [base+ipred_v_shuf] + vpbroadcastd m8, [tlq+1] + sub tlq, 8 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m8, m0 ; top, bottom + pshufd m6, m7, q2200 + pshufd m7, m7, q3311 + pmaddubsw m9, m8, m5 + paddw m3, m8 ; 1 * top + 255 * bottom + 255 + paddw m9, m3 ; 128 * top + 129 * bottom + 255 +.w4_loop: + vpbroadcastq m1, [tlq+hq] + pshufb m1, m10 + punpcklbw m0, m1, m4 ; left, right + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 ; 127 * left - 127 * right + pmaddubsw m3, m1, m5 + paddw m2, m0 ; 128 * left + 129 * right + paddw m3, m1 + pmaddubsw m0, m11 + pmaddubsw m1, m11 + paddw m2, m0 + paddw m3, m1 + vbroadcasti128 m1, [v_weightsq] + add v_weightsq, 16 + pshufb m0, m1, m6 + pshufb m1, m7 + SMOOTH_2D_END 0, 1, 8, 8, 9, 9 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + mova m10, [base+ipred_h_shuf] + vbroadcasti128 m11, [base+smooth_weights+8*2] + mova m7, [base+ipred_v_shuf] + vpbroadcastq m8, [tlq+1] + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m8, m0 + pshufd m6, m7, q0000 + pshufd m7, m7, q1111 + pmaddubsw m9, m8, m5 + paddw m3, m8 + paddw m9, m3 +.w8_loop: + vpbroadcastd m1, [tlq+hq] + pshufb m1, m10 + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 + pmaddubsw m3, m1, m5 + paddw m2, m0 + paddw m3, m1 + pmaddubsw m0, m11 + pmaddubsw m1, m11 + paddw m2, m0 + paddw m3, m1 + vpbroadcastq m1, [v_weightsq] + add v_weightsq, 8 + pshufb m0, m1, m6 + pshufb m1, m7 + SMOOTH_2D_END 0, 1, 8, 8, 9, 9 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + SETUP_STACK_FRAME 32*4, 7, 14 + vbroadcasti128 m11, [tlq+1] + lea r3, [rsp+64*2-4] + punpcklbw m10, m11, m0 ; top, bottom + punpckhbw m11, m0 + call .prep_v + sub tlq, 2 + pmaddubsw m12, m10, m5 + pmaddubsw m13, m11, m5 + vpbroadcastd xm5, [base+pb_1] + mova m9, [base+ipred_v_shuf] + vbroadcasti128 m6, [base+smooth_weights+16*2] + vbroadcasti128 m7, [base+smooth_weights+16*3] + vperm2i128 m8, m9, m9, 0x01 + paddw m0, m10, m3 + paddw m3, m11 + paddw m12, m0 + paddw m13, m3 +.w16_loop: + vpbroadcastd m3, [tlq+hq] + vpbroadcastd m0, [r3+hq*2] + vpbroadcastd m1, [v_weightsq] + add v_weightsq, 4 + pshufb m3, m5 + punpcklbw m3, m4 ; left, right + pmaddubsw m2, m3, m6 + pmaddubsw m3, m7 + pshufb m0, m8 + pshufb m1, m9 + paddw m2, m0 + paddw m3, m0 + SMOOTH_2D_END 1, 1, 10, 11, 12, 13 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + SETUP_STACK_FRAME 32*4, 7, 11 + movu m8, [tlq+1] + lea r3, [rsp+64*2-2] + punpcklbw m7, m8, m0 + punpckhbw m8, m0 + call .prep_v + dec tlq + pmaddubsw m9, m7, m5 + pmaddubsw m10, m8, m5 + mova xm5, [base+smooth_weights+16*4] + vinserti128 m5, [base+smooth_weights+16*6], 1 + mova xm6, [base+smooth_weights+16*5] + vinserti128 m6, [base+smooth_weights+16*7], 1 + paddw m0, m7, m3 + paddw m3, m8 + paddw m9, m0 + paddw m10, m3 +.w32_loop: + vpbroadcastb m3, [tlq+hq] + punpcklbw m3, m4 + vpbroadcastw m0, [r3+hq*2] + vpbroadcastw m1, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m3, m5 + pmaddubsw m3, m6 + paddw m2, m0 + paddw m3, m0 + SMOOTH_2D_END 1, 1, 7, 8, 9, 10 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + SETUP_STACK_FRAME 32*8, 7, 16 + movu m13, [tlq+1 ] + movu m15, [tlq+33] + add r6, smooth_weights+16*15-ipred_smooth_avx2_table + lea r3, [rsp+64*2-2] + punpcklbw m12, m13, m0 + punpckhbw m13, m0 + punpcklbw m14, m15, m0 + punpckhbw m15, m0 + call .prep_v + dec tlq + pmaddubsw m0, m12, m5 + pmaddubsw m1, m13, m5 + pmaddubsw m2, m14, m5 + pmaddubsw m5, m15, m5 + mova xm8, [r6-16*7] + vinserti128 m8, [r6-16*5], 1 + mova xm9, [r6-16*6] + vinserti128 m9, [r6-16*4], 1 + mova xm10, [r6-16*3] + vinserti128 m10, [r6-16*1], 1 + mova xm11, [r6-16*2] + vinserti128 m11, [r6-16*0], 1 + lea r6, [rsp+32*4] + paddw m0, m3 + paddw m1, m3 + paddw m2, m3 + paddw m3, m5 + paddw m0, m12 + paddw m1, m13 + paddw m2, m14 + paddw m3, m15 + mova [r6+32*0], m0 + mova [r6+32*1], m1 + mova [r6+32*2], m2 + mova [r6+32*3], m3 +.w64_loop: + vpbroadcastb m5, [tlq+hq] + punpcklbw m5, m4 + vpbroadcastw m6, [r3+hq*2] + vpbroadcastw m7, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m5, m8 + pmaddubsw m3, m5, m9 + paddw m2, m6 + paddw m3, m6 + SMOOTH_2D_END 7, 7, 12, 13, [r6+32*0], [r6+32*1] + mova [dstq+32*0], m0 + pmaddubsw m2, m5, m10 + pmaddubsw m3, m5, m11 + paddw m2, m6 + paddw m3, m6 + SMOOTH_2D_END 7, 7, 14, 15, [r6+32*2], [r6+32*3] + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +ALIGN function_align +.prep_v: + vpermq m2, [tlq-32*1], q3120 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + pmaddubsw m0, m1, m5 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m2, m5 + paddw m1, m2 + vpermq m2, [tlq-32*2], q3120 + mova [rsp+gprsize+32*3], m0 + mova [rsp+gprsize+32*2], m1 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + pmaddubsw m0, m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m5 + paddw m1, m2 + mova [rsp+gprsize+32*1], m0 + mova [rsp+gprsize+32*0], m1 + sub r3, hq + sub tlq, hq + sub r3, hq + ret + +cglobal ipred_z1_8bpc, 3, 8, 0, dst, stride, tl, w, h, angle, dx, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z1_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea r7, [dr_intra_derivative] + inc tlq + movsxd wq, [r6+wq*4] + add wq, r6 + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + movzx dxd, word [r7+dxq] + xor angled, 0x4ff ; d = 90 - angle + vpbroadcastd m3, [pw_512] + vpbroadcastd m4, [pw_62] + vpbroadcastd m5, [pw_64] + jmp wq +.w4: + cmp angleb, 40 + jae .w4_no_upsample + lea r3d, [angleq-1024] + sar r3d, 7 + add r3d, hd + jg .w4_no_upsample ; !enable_intra_edge_filter || h > 8 || (h == 8 && is_sm) + ALLOC_STACK -32, 8 + mova xm1, [tlq-1] + pshufb xm0, xm1, [z_upsample1] + pshufb xm1, [z_upsample2] + vpbroadcastd xm2, [pb_36_m4] ; upshifted by 2 to be able to reuse + add dxd, dxd ; pw_512 (which is already in m3) + pmaddubsw xm0, xm2 ; for rounding instead of pw_2048 + pextrd [rsp+16], xm1, 3 ; top[max_base_x] + pmaddubsw xm1, xm2 + movd xm7, dxd + mov r3d, dxd ; xpos + vpbroadcastw m7, xm7 + paddw xm1, xm0 + movq xm0, [tlq] + pmulhrsw xm1, xm3 + pslldq m6, m7, 8 + paddw xm2, xm7, xm7 + lea r2, [strideq*3] + paddw m6, m7 + packuswb xm1, xm1 + paddw m6, m2 ; xpos2 xpos3 xpos0 xpos1 + punpcklbw xm0, xm1 + psllw m7, 2 + mova [rsp], xm0 +.w4_upsample_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + vpbroadcastq m1, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vpbroadcastq m2, [rsp+r5] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + movq xm0, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + movhps xm0, [rsp+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + paddw m6, m7 ; xpos += dx + pmulhrsw m0, m3 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r2 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; w4/w8/w16 + ; The C version uses a lot of branches, but we can do all the comparisons + ; in parallel and use popcnt to get the final filter strength value. +%define base r3-z_filter_t0 + lea r3, [z_filter_t0] + movd xm0, maxbased + movd xm2, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m2, xm2 + pcmpeqb m1, m0, [base+z_filter_wh] + pand m1, m2 + mova xm2, [r3+angleq*8] ; upper ymm half zero in both cases + pcmpgtb m1, m2 + pmovmskb r5d, m1 + ret +.w4_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -16, 11 + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea maxbased, [hq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m7, [base+pb_8] + vbroadcasti128 m2, [tlq-1] + pminub m1, m7, [base+z_filter_s] + vpbroadcastd m8, [base+z_filter_k-4+r5*4+12*0] + pminub m7, [base+z_filter_s+8] + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m10, [base+z_filter_k-4+r5*4+12*2] + pshufb m0, m2, m1 + shufps m1, m7, q2121 + pmaddubsw m0, m8 + pshufb m1, m2, m1 + pmaddubsw m1, m9 + pshufb m2, m7 + pmaddubsw m2, m10 + paddw m0, m1 + paddw m0, m2 + pmulhrsw m0, m3 + mov r3d, 9 + mov tlq, rsp + cmp hd, 4 + cmovne maxbased, r3d + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [tlq], xm0 +.w4_main: + movd xm6, dxd + vpbroadcastq m0, [z_base_inc] ; base_inc << 6 + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + mov r3d, dxd ; xpos + movd xm9, maxbased + vpbroadcastw m9, xm9 + vbroadcasti128 m8, [z1_shuf_w4] + psrlw m7, 8 ; top[max_base_x] + paddw m10, m6, m6 + psubw m9, m0 ; max_base_x + vpblendd m6, m10, 0xcc + mova xm0, xm10 + paddw m6, m0 ; xpos2 xpos3 xpos0 xpos1 + paddw m10, m10 +.w4_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + vpbroadcastq m1, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vpbroadcastq m2, [tlq+r5] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + movq xm0, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + movhps xm0, [tlq+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + pcmpgtw m1, m9, m6 ; base < max_base_x + pmulhrsw m0, m3 + paddw m6, m10 ; xpos += dx + lea r5, [dstq+strideq*2] + vpblendvb m0, m7, m0, m1 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [r5 +strideq*0], xm0 + pextrd [r5 +strideq*1], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r3d, maxbased + jb .w4_loop + packuswb xm7, xm7 + lea r6, [strideq*3] +.w4_end_loop: + movd [dstq+strideq*0], xm7 + movd [dstq+strideq*1], xm7 + movd [dstq+strideq*2], xm7 + movd [dstq+r6 ], xm7 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_end_loop +.w4_end: + RET +ALIGN function_align +.w8: + lea r3d, [angleq+216] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 8 + movu xm2, [z_filter_s+6] + mova xm0, [tlq-1] + movd xm6, hd + vinserti128 m0, [tlq+7], 1 + vpbroadcastb xm6, xm6 + vbroadcasti128 m1, [z_upsample1] + pminub xm6, xm2 + vpbroadcastd m7, [pb_36_m4] + vinserti128 m2, xm6, 1 + add dxd, dxd + pshufb m1, m0, m1 + pshufb m2, m0, m2 + movd xm6, dxd + pmaddubsw m1, m7 + pmaddubsw m2, m7 + vpbroadcastw m6, xm6 + mov r3d, dxd + psrldq m0, 1 + lea r2, [strideq*3] + paddw m7, m6, m6 + paddw m1, m2 + vpblendd m6, m7, 0xf0 + pmulhrsw m1, m3 + pslldq m2, m7, 8 + paddw m7, m7 + paddw m6, m2 + packuswb m1, m1 + punpcklbw m0, m1 + mova [rsp], m0 +.w8_upsample_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm0, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [rsp+r5], 1 + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + punpcklqdq m1, m2, m2 ; frac0 frac1 + pmaddubsw m0, m1 + movu xm1, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + vinserti128 m1, [rsp+r5], 1 + punpckhqdq m2, m2 ; frac2 frac3 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + paddw m6, m7 + pmulhrsw m1, m3 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r2 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_upsample_loop + RET +.w8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(h+7, 15) + jmp .w8_main +.w8_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 10 + lea maxbased, [hq+7] + test angled, 0x400 + jnz .w8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w8_main ; filter_strength == 0 + popcnt r5d, r5d + movu xm2, [tlq] + pminub xm1, xm0, [base+z_filter_s+14] + vinserti128 m2, [tlq-1], 1 + vinserti128 m1, [base+z_filter_s+ 0], 1 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pminub xm0, [base+z_filter_s+22] + vinserti128 m0, [base+z_filter_s+ 8], 1 + pshufb m6, m2, m1 + pmaddubsw m6, m7 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*1] + movzx r3d, byte [tlq+15] + shufps m1, m0, q2121 + pshufb m1, m2, m1 + pmaddubsw m1, m7 + paddw m1, m6 + sub r5d, 3 + jnz .w8_3tap + ; filter_strength == 3 uses a 5-tap filter instead of a 3-tap one, + ; which also results in an awkward edge case where out[w*2] is + ; slightly different from out[max_base_x] when h > w. + vpbroadcastd m7, [z_filter_k+4*8] + movzx r2d, byte [tlq+14] + pshufb m2, m0 + pmaddubsw m2, m7 + sub r2d, r3d + lea r2d, [r2+r3*8+4] + shr r2d, 3 ; (tlq[w*2-2] + tlq[w*2-1]*7 + 4) >> 3 + mov [rsp+16], r2b + paddw m1, m2 +.w8_3tap: + pmulhrsw m1, m3 + sar r5d, 1 + mov tlq, rsp + add r5d, 17 ; w*2 + (filter_strength == 3) + cmp hd, 16 + cmovns maxbased, r5d + mov [tlq+r5], r3b + vextracti128 xm0, m1, 1 + packuswb xm0, xm1 + mova [tlq], xm0 +.w8_main: + movd xm2, dxd + vbroadcasti128 m0, [z_base_inc] + vpbroadcastw m2, xm2 + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + psrlw m7, 8 + psubw m9, m0 + mov r3d, dxd + paddw m6, m2, m2 + vpblendd m2, m6, 0xf0 +.w8_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + pand m0, m4, m2 + psubw m1, m5, m0 + psllw m0, 8 + por m1, m0 + movu xm0, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [tlq+r5], 1 + pshufb m0, m8 + pmaddubsw m0, m1 + pcmpgtw m1, m9, m2 + paddw m2, m6 + pmulhrsw m0, m3 + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w8_loop + packuswb xm7, xm7 +.w8_end_loop: + movq [dstq+strideq*0], xm7 + movq [dstq+strideq*1], xm7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_end_loop +.w8_end: + RET +.w16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(h+15, 31) + jmp .w16_main +ALIGN function_align +.w16: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 12 + lea maxbased, [hq+15] + test angled, 0x400 + jnz .w16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w16_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m1, [base+pb_12] + vbroadcasti128 m6, [base+z_filter_s+8] + vinserti128 m2, m6, [base+z_filter_s], 0 + vinserti128 m6, [base+z_filter_s+16], 1 + mova xm10, [tlq-1] + vinserti128 m10, [tlq+3], 1 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*0] + vbroadcasti128 m7, [base+z_filter_s+14] + vinserti128 m8, m7, [base+z_filter_s+6], 0 + vinserti128 m7, [base+z_filter_s+22], 1 + psubw m0, m1 + movu xm11, [tlq+12] + vinserti128 m11, [tlq+16], 1 + pminub m8, m0 + pminub m7, m0 + pshufb m0, m10, m2 + shufps m2, m6, q2121 + pmaddubsw m0, m9 + pshufb m1, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m1, m9 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + movzx r3d, byte [tlq+31] + pshufb m2, m10, m2 + pmaddubsw m2, m9 + pshufb m8, m11, m8 + pmaddubsw m8, m9 + paddw m0, m2 + paddw m1, m8 + sub r5d, 3 + jnz .w16_3tap + vpbroadcastd m9, [z_filter_k+4*8] + movzx r2d, byte [tlq+30] + pshufb m10, m6 + pmaddubsw m10, m9 + pshufb m11, m7 + pmaddubsw m11, m9 + sub r2d, r3d + lea r2d, [r2+r3*8+4] + shr r2d, 3 + mov [rsp+32], r2b + paddw m0, m10 + paddw m1, m11 +.w16_3tap: + pmulhrsw m0, m3 + pmulhrsw m1, m3 + sar r5d, 1 + mov tlq, rsp + add r5d, 33 + cmp hd, 32 + cmovns maxbased, r5d + mov [tlq+r5], r3b + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [tlq], m0 +.w16_main: + movd xm6, dxd + vbroadcasti128 m0, [z_base_inc] + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + mov r3d, dxd + psubw m9, m0 + paddw m11, m6, m6 + psubw m10, m9, m3 ; 64*8 + vpblendd m6, m11, 0xf0 +.w16_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r3+0] + movu xm1, [tlq+r3+8] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [tlq+r5+0], 1 + vinserti128 m1, [tlq+r5+8], 1 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w16_loop +.w16_end_loop: + mova [dstq+strideq*0], xm7 + mova [dstq+strideq*1], xm7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_end_loop +.w16_end: + RET +ALIGN function_align +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 15 + lea r3d, [hq+31] + mov maxbased, 63 + cmp hd, 32 + cmovs maxbased, r3d + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + vbroadcasti128 m0, [pb_0to15] + sub r3d, 29 ; h+2 + movu xm13, [tlq+29] ; 32-39 + movd xm1, r3d + movu xm14, [tlq+37] ; 40-47 + sub r3d, 8 ; h-6 + vinserti128 m14, [tlq+51], 1 ; 56-63 + vpbroadcastb xm1, xm1 + mova xm11, [tlq- 1] ; 0- 7 + vinserti128 m11, [tlq+13], 1 ; 16-23 + movd xm2, r3d + movu xm12, [tlq+ 5] ; 8-15 + vinserti128 m12, [tlq+19], 1 ; 24-31 + pminub xm1, xm0 ; clip 32x8 + mova m7, [z_filter_s+0] + pshufb xm13, xm1 + vpbroadcastd m1, [pb_12] + vpbroadcastb xm2, xm2 + vinserti128 m13, [tlq+43], 1 ; 48-55 + vinserti128 m8, m7, [z_filter_s+4], 1 + vpblendd m2, m1, 0xf0 + vinserti128 m7, [z_filter_s+12], 0 + pminub m2, m0 ; clip 32x16 and 32x(32|64) + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m14, m2 + pshufb m0, m11, m8 + shufps m8, m7, q1021 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m8 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m8 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m8 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m7 + pmaddubsw m12, m9 + movzx r3d, byte [tlq+63] + movzx r2d, byte [tlq+62] + paddw m0, m11 + paddw m2, m12 + pshufb m13, m7 + pmaddubsw m13, m9 + pshufb m14, m7 + pmaddubsw m14, m9 + paddw m1, m13 + paddw m6, m14 + sub r2d, r3d + lea r2d, [r2+r3*8+4] ; edge case for 32x64 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + shr r2d, 3 + mov [rsp+64], r2b + mov tlq, rsp + mov [tlq+65], r3b + mov r3d, 65 + cmp hd, 64 + cmove maxbased, r3d + packuswb m0, m2 + packuswb m1, m6 + mova [tlq+ 0], m0 + mova [tlq+32], m1 +.w32_main: + movd xm6, dxd + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + mov r5d, dxd + psubw m9, [z_base_inc] + mova m11, m6 + psubw m10, m9, m3 ; 64*8 +.w32_loop: + mov r3d, r5d + shr r3d, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu m0, [tlq+r3+0] + movu m1, [tlq+r3+8] + add r5d, dxd + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [dstq], m0 + dec hd + jz .w32_end + add dstq, strideq + cmp r5d, maxbased + jb .w32_loop + test hb, 1 + jz .w32_end_loop + mova [dstq], m7 + add dstq, strideq + dec hd + jz .w32_end +.w32_end_loop: + mova [dstq+strideq*0], m7 + mova [dstq+strideq*1], m7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_end_loop +.w32_end: + RET +ALIGN function_align +.w64: + %assign stack_offset org_stack_offset + ALLOC_STACK -128, 16 + lea maxbased, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + mova xm11, [tlq- 1] ; 0- 7 + vinserti128 m11, [tlq+13], 1 ; 16-23 + movu xm12, [tlq+ 5] ; 8-15 + vinserti128 m12, [tlq+19], 1 ; 24-31 + mova m7, [z_filter_s+0] + vinserti128 m8, m7, [z_filter_s+4], 1 + vinserti128 m7, [z_filter_s+12], 0 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + movu xm13, [tlq+29] ; 32-39 + vinserti128 m13, [tlq+43], 1 ; 48-55 + movu xm14, [tlq+37] ; 40-47 + vinserti128 m14, [tlq+51], 1 ; 56-63 + pshufb m0, m11, m8 + shufps m8, m7, q1021 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + shufps m15, m8, m7, q2121 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m15 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m10, [z_filter_k+4*2+12*2] + pshufb m11, m15 + pmaddubsw m11, m10 + pshufb m12, m7 + pmaddubsw m12, m10 + pshufb m13, m7 + pmaddubsw m13, m10 + pshufb m14, m7 + pmaddubsw m14, m10 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + movu xm11, [tlq+ 61] ; 64- 71 + vinserti128 m11, [tlq+ 75], 1 ; 80- 87 + movu xm12, [tlq+ 69] ; 72- 79 + vinserti128 m12, [tlq+ 83], 1 ; 88- 95 + movu xm13, [tlq+ 93] ; 96-103 + vinserti128 m13, [tlq+107], 1 ; 112-119 + movu xm14, [tlq+101] ; 104-111 + vinserti128 m14, [tlq+115], 1 ; 120-127 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + lea r3d, [hq-20] + mov tlq, rsp + packuswb m0, m2 + packuswb m1, m6 + vpbroadcastd xm2, [pb_14] + vbroadcasti128 m6, [pb_0to15] + mova [tlq+32*0], m0 + mova [tlq+32*1], m1 + movd xm0, r3d + vpbroadcastd m1, [pb_12] + vpbroadcastb m0, xm0 + paddb m0, m2 + pminub m0, m6 ; clip 64x16 and 64x32 + pshufb m12, m0 + pminub m1, m6 ; clip 64x64 + pshufb m14, m1 + pshufb m0, m11, m7 + pmaddubsw m0, m10 + pshufb m2, m12, m7 + pmaddubsw m2, m10 + pshufb m1, m13, m7 + pmaddubsw m1, m10 + pshufb m6, m14, m7 + pmaddubsw m6, m10 + pshufb m7, m11, m15 + pmaddubsw m7, m9 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m0, m7 + pshufb m7, m13, m15 + pmaddubsw m7, m9 + paddw m2, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m1, m7 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m8 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + packuswb m0, m2 + packuswb m1, m6 + mova [tlq+32*2], m0 + mova [tlq+32*3], m1 +.w64_main: + movd xm12, dxd + vpbroadcastb m7, [tlq+maxbaseq] + lea r3d, [dxq-64] + shl maxbased, 6 + vpbroadcastw m12, xm12 + sub r3d, maxbased + vbroadcasti128 m8, [z_filter_s+2] + movd xm6, r3d + mov r5d, dxd + mova m10, [pb_1to32] + vpbroadcastd m11, [pb_32] + vpbroadcastw m6, xm6 +.w64_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3+ 0] + movu m1, [tlq+r3+ 8] + pand m2, m4, m6 + psubw m9, m5, m2 + psllw m2, 8 + por m9, m2 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + psraw m2, m6, 6 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packsswb m2, m2 + paddb m2, m10 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [dstq+ 0], m0 + movu m0, [tlq+r3+32] + movu m1, [tlq+r3+40] + add r5d, dxd + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + paddb m2, m11 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + paddw m6, m12 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [dstq+32], m0 + dec hd + jz .w64_end + add dstq, strideq + cmp r5d, maxbased + jb .w64_loop +.w64_end_loop: + mova [dstq+ 0], m7 + mova [dstq+32], m7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET + +cglobal ipred_z2_8bpc, 3, 10, 16, 224, dst, stride, tl, w, h, angle, dx, dy +%define base r9-z_filter_t0 + lea r9, [ipred_z2_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea dxq, [dr_intra_derivative-90] + movsxd wq, [r9+wq*4] + movzx dyd, angleb + xor angled, 0x400 + mov r8, dxq + sub dxq, dyq + add wq, r9 + add r9, z_filter_t0-ipred_z2_avx2_table + mova m2, [tlq-64] + mova m0, [tlq-32] + mova m1, [tlq] + and dyd, ~1 + and dxq, ~1 + movzx dyd, word [r8+dyq] ; angle - 90 + movzx dxd, word [dxq+270] ; 180 - angle + vpbroadcastd m13, [base+pw_512] + vpbroadcastd m14, [base+pw_62] + vpbroadcastd m15, [base+pw_64] + mova [rsp+ 0], m2 + mova [rsp+32], m0 + mova [rsp+64], m1 + neg dxd + neg dyd + jmp wq +.w4: + vpbroadcastq m6, [base+z2_base_inc] ; base_inc << 6 + vbroadcasti128 m10, [base+z1_shuf_w4] + vbroadcasti128 m11, [base+z2_shuf_h4] + lea r2d, [dxq+(65<<6)] ; xpos + movd xm5, dyd + mov r8d, (63-4)<<6 + mov dyq, -4 + pshuflw xm5, xm5, q0000 + pmullw xm5, [base+z2_ymul] + test angled, 0x400 + jnz .w4_main ; !enable_intra_edge_filter + lea r3d, [hq+2] + add angled, 1022 + shl r3d, 6 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm3, [base+pb_4] + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + call .filter_strength + jmp .w4_filter_left +ALIGN function_align +.filter_strength: + movd xm8, r3d + mov r3d, angled + movd xm7, angled + vpbroadcastb m8, xm8 + shr r3d, 8 ; is_sm << 1 + vpbroadcastb m7, xm7 + pcmpeqb m8, [base+z_filter_wh] + mova xm9, [r9+r3*8] + pand m0, m8, m7 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + ret +ALIGN function_align +.upsample_above: ; w4/w8 + pshufb xm2, xm1, [base+z_upsample1-2] + pminub xm3, [base+z_filter_s+4] + vpbroadcastd xm4, [base+pb_36_m4] + vbroadcasti128 m10, [base+pb_0to15] + pshufb xm3, xm1, xm3 + pmaddubsw xm2, xm4 + pmaddubsw xm3, xm4 + lea r2d, [r2+dxq+(1<<6)] + add dxd, dxd + paddw xm2, xm3 + pmulhrsw xm2, xm13 + sub r8d, 3<<6 + paddw m6, m6 + packuswb xm2, xm2 + punpcklbw xm1, xm2 + mova [rsp+gprsize+64], xm1 + ret +ALIGN function_align +.upsample_left: ; h4/h8 + mov r3d, hd + and r3d, 4 + movd xm2, [rsp+gprsize+64] + movddup xm0, [rsp+gprsize+56] + movd xm1, r3d + palignr xm2, xm0, 1 + vpbroadcastb xm1, xm1 + pshufb xm2, [base+z_filter_s+18] + vpbroadcastd xm3, [base+pb_36_m4] + pmaxub xm1, [base+z_upsample1-2] + pshufb xm1, xm0, xm1 + pmaddubsw xm2, xm3 + pmaddubsw xm1, xm3 + paddw xm5, xm5 + add dyq, dyq + paddw xm1, xm2 + pmulhrsw xm1, xm13 + vbroadcasti128 m11, [base+z2_upsample] + paddw xm5, xm15 + packuswb xm1, xm1 + punpcklbw xm0, xm1 + mova [rsp+gprsize+48], xm0 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + sub angled, 1112 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w4_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm2, [base+pb_4] + pminub xm2, [base+z_filter_s] + vpbroadcastd xm0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + pshufb xm3, xm1, xm2 ; 00 01 12 23 + pshufd xm2, xm2, q0321 + pmaddubsw xm0, xm3, xm0 + pshufb xm2, xm1, xm2 ; 12 23 34 44 + pmaddubsw xm2, xm4 + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*2] + punpckhqdq xm3, xm3 ; 34 44 44 44 + pmaddubsw xm3, xm4 + movd xm4, r6m ; max_width + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw xm0, xm2 + paddw xm0, xm3 + pmulhrsw xm0, xm13 + psubb xm4, [base+pb_1to32] + psrlq xm1, 8 + packuswb xm0, xm0 + vpblendvb xm0, xm1, xm4 + movd [rsp+65], xm0 +.w4_no_filter_above: + lea r3d, [hq+2] + add angled, 973 ; angle + 883 + shl r3d, 6 + test r3d, angled + jz .w4_upsample_left ; angle <= 140 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm0, [base+pb_90] + psubb xm0, xm7 ; 180 - angle + pand xm0, xm8 ; reuse from previous filter_strength call + pcmpgtb xm0, xm9 + pmovmskb r3d, xm0 +.w4_filter_left: + test r3d, r3d + jz .w4_main + popcnt r3d, r3d + mov r5d, 10 + cmp hd, 16 + movu xm2, [rsp+49] + vinserti128 m2, [rsp+43], 1 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + vinserti128 m3, m1, [z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 55 55 56 67 78 89 9a ab + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + vpbroadcastb m0, xm0 + pmaxub m0, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pshufb m0, m2, m0 + pmaddubsw m0, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*1] + pshufb m1, m2, m1 + pmaddubsw m1, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*2] + pshufb m2, m4 + pmaddubsw m2, m3 + movd xm4, r7m ; max_height + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + psubb xm4, [base+pb_16to1] + paddw m1, m0 + paddw m1, m2 + pmulhrsw m1, m13 + vextracti128 xm0, m1, 1 + packuswb xm0, xm1 + vpblendvb xm0, [rsp+48], xm4 + mova [rsp+48], xm0 + jmp .w4_main +.w4_upsample_left: + call .upsample_left +.w4_main: + movd xm0, dxd + mova m12, [base+z2_y_shuf_h4] + lea r5, [rsp+56] ; left-7 + vpbroadcastw m0, xm0 + lea r9, [strideq*3] + psraw xm1, xm5, 6 + pand xm5, xm14 ; frac_y + pxor xm2, xm2 + paddw m7, m0, m0 + psubw xm4, xm2, xm1 ; base_y + vpblendd m0, m7, 0xcc + mova xm1, xm7 + punpcklwd xm4, xm2 + paddw m0, m1 ; xpos2 xpos3 xpos0 xpos1 + psubw xm1, xm15, xm5 ; 64-frac_y + psllw xm5, 8 + paddw m7, m7 + paddw m6, m0 + por xm5, xm1 ; 64-frac_y, frac_y + vpbroadcastq m5, xm5 +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + vpbroadcastq m1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vpbroadcastq m2, [rsp+r3] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movq xm0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movhps xm0, [rsp+r3] + vpblendd m1, m2, 0xc0 + pand m2, m14, m6 ; frac_x + vpblendd m0, m1, 0xf0 + psubw m1, m15, m2 ; 64-frac_x + psllw m2, 8 + pshufb m0, m10 + por m1, m2 ; 64-frac_x, frac_x + pmaddubsw m0, m1 + cmp r3d, 64 + jge .w4_toponly + mova m1, m7 ; arbitrary negative value + vpgatherdq m3, [r5+xm4], m1 + pshufb m1, m3, m11 + vpermd m1, m12, m1 + pmaddubsw m1, m5 + psraw m2, m6, 15 ; base_x < topleft + vpblendvb m0, m1, m2 +.w4_toponly: + pmulhrsw m0, m13 + paddw m6, m7 ; xpos += dx + add r5, dyq + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r9 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r2d, r8d + jge .w4_loop +.w4_leftonly_loop: + mova m1, m7 + vpgatherdq m2, [r5+xm4], m1 + add r5, dyq + pshufb m0, m2, m11 + vpermd m0, m12, m0 + pmaddubsw m0, m5 + pmulhrsw m0, m13 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r9 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + RET +.w8: + vbroadcasti128 m6, [base+z2_base_inc] ; base_inc << 6 + movd xm5, dyd + vbroadcasti128 m10, [base+z_filter_s+2] + vbroadcasti128 m11, [base+z2_shuf_h4] + lea r2d, [dxq+(65<<6)] ; xpos + vpbroadcastw xm5, xm5 + mov r8d, (63-8)<<6 + mov dyq, -4 + pmullw xm5, [base+z2_ymul] + test angled, 0x400 + jnz .w8_main + lea r3d, [angleq+126] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + vpbroadcastd xm3, [base+pb_8] + movhps [rsp+80], xm1 + call .upsample_above + sub angled, 53 ; angle - 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + call .filter_strength + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + sub angled, 90 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w8_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm3, [base+pb_8] + pminub xm3, [base+z_filter_s+8] + vpbroadcastd xm0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + pshufb xm2, xm1, [base+z_filter_s] ; 00 01 12 23 34 45 56 67 + pmaddubsw xm0, xm2, xm0 + pshufb xm3, xm1, xm3 ; 34 45 56 67 78 88 88 88 + shufps xm2, xm3, q2121 ; 12 23 34 45 56 67 78 88 + pmaddubsw xm2, xm4 + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*2] + pmaddubsw xm3, xm4 + movd xm4, r6m ; max_width + pminuw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw xm0, xm2 + paddw xm0, xm3 + pmulhrsw xm0, xm13 + psubb xm4, [base+pb_1to32] + psrldq xm1, 1 + packuswb xm0, xm0 + vpblendvb xm0, xm1, xm4 + movq [rsp+65], xm0 +.w8_no_filter_above: + lea r3d, [angleq-51] + mov r3b, hb + cmp r3d, 8 + jbe .w8_upsample_left ; angle > 140 && h <= 8 && !is_sm + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 +.w8_filter_left: + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + vpbroadcastd m7, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m8, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m9, [base+z_filter_k-4+r3*4+12*2] + cmp hd, 32 + jne .w8_filter_left_h16 + movu xm2, [rsp+27] + vinserti128 m2, [rsp+35], 1 + vpbroadcastd xm0, [base+pb_5] + vbroadcasti128 m3, [base+z_filter_s+ 8] + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + pmaxub m3, m0 + pshufb m3, m2, m3 + pmaddubsw m3, m7 + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + paddw m3, m1 + paddw m3, m2 + pmulhrsw m3, m13 + jmp .w8_filter_left_top16 +.w8_filter_left_h16: + mov r5d, 10 + cmp hd, 16 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vpbroadcastb m0, xm0 +.w8_filter_left_top16: + vbroadcasti128 m1, [base+z_filter_s+12] + vinserti128 m2, m1, [base+z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 55 55 56 67 78 89 9a ab + vbroadcasti128 m4, [base+z_filter_s+16] + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + pmaxub m0, m2 + movu xm2, [rsp+49] + vinserti128 m2, [rsp+43], 1 + pshufb m0, m2, m0 + pmaddubsw m0, m7 + movd xm7, r7m ; max_height + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + pminsw xm7, xm15 + paddw m1, m0 + vpbroadcastb m7, xm7 + paddw m1, m2 + pmulhrsw m1, m13 + psubb m7, [base+pb_32to1] + packuswb m3, m1 + vpermq m3, m3, q1320 + vpblendvb m3, [rsp+32], m7 + mova [rsp+32], m3 + jmp .w8_main +.w8_upsample_left: + call .upsample_left +.w8_main: + movd xm3, dxd + lea r5, [rsp+56] ; left-7 + pshufd xm1, xm5, q3120 + pand xm5, xm14 + vpbroadcastw m3, xm3 + pxor xm0, xm0 + psubw xm2, xm15, xm5 + psraw xm1, 6 + lea r9, [strideq*3] + paddw m7, m3, m3 + psubw xm9, xm0, xm1 ; base_y + psllw xm5, 8 + punpcklwd xm8, xm9, xm0 ; base_y 0, 1, 4, 5 + vpblendd m3, m7, 0xf0 ; xpos0 xpos1 + por xm5, xm2 ; 64-frac_y, frac_y + punpckhwd xm9, xm0 ; base_y 2, 3, 6, 7 + paddw m6, m3 + vinserti128 m12, m5, xm5, 1 +.w8_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vinserti128 m0, [rsp+r3], 1 + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movu xm1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + vinserti128 m1, [rsp+r3], 1 + pand m2, m14, m6 + paddsw m4, m6, m7 + psubw m5, m15, m2 + psllw m2, 8 + pshufb m0, m10 + por m2, m5 + pmaddubsw m0, m2 + pand m2, m14, m4 + psubw m5, m15, m2 + psllw m2, 8 + pshufb m1, m10 + por m2, m5 + pmaddubsw m1, m2 + cmp r3d, 64 + jge .w8_toponly + mova m5, m7 + vpgatherdq m3, [r5+xm9], m7 + mova m7, m5 + vpgatherdq m2, [r5+xm8], m5 + pshufb m3, m11 + pshufb m2, m11 + punpckldq m5, m2, m3 ; a0 b0 c0 d0 a1 b1 c1 d1 e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m2, m3 ; a2 b2 c2 d2 a3 b3 c3 d3 e2 f2 g2 h2 e3 f3 g3 h3 + vpermq m5, m5, q3120 ; y0 y1 + vpermq m2, m2, q3120 ; y2 y3 + pmaddubsw m5, m12 + pmaddubsw m2, m12 + psraw m6, 15 ; base_x < topleft + vpblendvb m0, m5, m6 + psraw m3, m4, 15 + vpblendvb m1, m2, m3 +.w8_toponly: + pmulhrsw m0, m13 + pmulhrsw m1, m13 + paddw m6, m4, m7 ; xpos += dx + add r5, dyq + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r9 ], xm1 + sub hd, 4 + jz .w8_end + lea dstq, [dstq+strideq*4] + cmp r2d, r8d + jge .w8_loop +.w8_leftonly_loop: + mova m0, m7 + vpgatherdq m5, [r5+xm9], m7 + mova m7, m0 + vpgatherdq m3, [r5+xm8], m0 + add r5, dyq + pshufb m2, m5, m11 + pshufb m1, m3, m11 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 + pmaddubsw m0, m12 + pmaddubsw m1, m12 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r9 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_leftonly_loop +.w8_end: + RET +.w16: + mov r8d, hd + test angled, 0x400 + jnz .w16_main + lea r3d, [hq+15] + sub angled, 90 + call .filter_strength + test r3d, r3d + jz .w16_no_filter_above + popcnt r3d, r3d + vbroadcasti128 m6, [tlq+1] + mova xm2, [base+z_filter_s] + vinserti128 m2, [base+z_filter_s+14], 1 ; 00 01 12 23 34 45 56 67 67 78 89 9a ab bc cd de + movu xm3, [base+z_filter_s+8] + vinserti128 m3, [base+z_filter_s+22], 1 ; 34 45 56 67 78 89 9a ab ab bc cd de ef ff ff ff + vpblendd m1, m6, 0xf0 + vpbroadcastd m0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m5, [base+z_filter_k-4+r3*4+12*2] + pshufb m2, m1, m2 + pshufb m1, m3 + pmaddubsw m0, m2, m0 + shufps m2, m1, q2121 ; 12 23 34 45 56 67 78 89 89 9a ab bc cd de ef ff + pmaddubsw m2, m4 + pmaddubsw m1, m5 + movd xm4, r6m ; max_width + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw m0, m2 + paddw m0, m1 + pmulhrsw m0, m13 + psubb xm4, [base+pb_1to32] + vextracti128 xm2, m0, 1 + packuswb xm0, xm2 + vpblendvb xm0, xm6, xm4 + movu [rsp+65], xm0 +.w16_no_filter_above: + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + test r3d, r3d + jz .w16_main + popcnt r3d, r3d + vpbroadcastd m7, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m8, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m9, [base+z_filter_k-4+r3*4+12*2] +.w16_filter_left: + movd xm6, r7m ; max_height + pminsw xm6, xm15 + vpbroadcastb m6, xm6 + cmp hd, 32 + jl .w16_filter_left_h16 + vpbroadcastd xm0, [base+pb_5] + vbroadcasti128 m10, [base+z_filter_s+ 8] + vbroadcasti128 m11, [base+z_filter_s+12] + vbroadcasti128 m12, [base+z_filter_s+16] + je .w16_filter_left_h32 + movu m3, [tlq-69] + movu m5, [tlq-61] + pmaxub m1, m10, m0 + pshufb m1, m3, m1 + pmaddubsw m1, m7 + pshufb m2, m3, m11 + pmaddubsw m2, m8 + pshufb m3, m12 + pmaddubsw m3, m9 + paddw m1, m2 + pshufb m2, m5, m10 + pmaddubsw m2, m7 + pshufb m4, m5, m11 + pmaddubsw m4, m8 + pshufb m5, m12 + pmaddubsw m5, m9 + paddw m1, m3 + vpbroadcastd m3, [base+pb_32] + paddb m3, [base+pb_32to1] + paddw m2, m4 + paddw m2, m5 + pmulhrsw m1, m13 + pmulhrsw m2, m13 + psubb m3, m6, m3 + packuswb m1, m2 + vpblendvb m1, [tlq-64], m3 + mova [rsp], m1 + jmp .w16_filter_left_top32 +.w16_filter_left_h32: + pmaxub m10, m0 +.w16_filter_left_top32: + movu xm2, [tlq-37] + vinserti128 m2, [tlq-29], 1 + pshufb m3, m2, m10 + pshufb m1, m2, m11 + pshufb m2, m12 + pmaddubsw m3, m7 + pmaddubsw m1, m8 + pmaddubsw m2, m9 + paddw m3, m1 + paddw m3, m2 + pmulhrsw m3, m13 + jmp .w16_filter_left_top16 +.w16_filter_left_h16: + mov r5d, 10 + cmp hd, 16 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vpbroadcastb m0, xm0 +.w16_filter_left_top16: + movu xm2, [tlq-15] + vinserti128 m2, [tlq-21], 1 + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + vinserti128 m5, m1, [base+z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 34 45 56 67 78 89 9a ab + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + pmaxub m0, m5 + pshufb m0, m2, m0 + pmaddubsw m0, m7 + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + psubb m6, [base+pb_32to1] + paddw m1, m0 + paddw m1, m2 + pmulhrsw m1, m13 + packuswb m3, m1 + vpermq m3, m3, q1320 + vpblendvb m3, [tlq-32], m6 + mova [rsp+32], m3 +.w16_main: + movd xm1, dyd + vbroadcasti128 m10, [base+z_filter_s+2] + movd xm7, dxd + vbroadcasti128 m11, [base+z2_shuf_h2] + vpbroadcastw m1, xm1 + vpbroadcastw m7, xm7 + mov r7, dstq + pmullw m0, m1, [base+z2_ymul] + psllw xm1, 4 + paddw m6, m7, [base+z2_base_inc] + lea r9d, [dxq+(65<<6)] ; xpos + movd [rsp+156], xm1 +.w16_loop0: + mov r2d, r9d + mova [rsp+160], m0 + lea r5, [rsp+60] ; left-3 + mova [rsp+192], m6 + pxor m1, m1 + psraw m2, m0, 6 + pand m0, m14 + psubw m9, m1, m2 ; base_y + psubw m12, m15, m0 + punpcklwd m8, m9, m1 ; base_y 0, 1, 2, 3, 8, 9, 10, 11 + psllw m0, 8 + punpckhwd m9, m1 ; base_y 4, 5, 6, 7, 12, 13, 14, 15 + por m12, m0 ; 64-frac_y, frac_y +.w16_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2] + vinserti128 m0, [rsp+r2+8], 1 + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu xm1, [rsp+r3] + vinserti128 m1, [rsp+r3+8], 1 + pand m2, m14, m6 + paddsw m5, m6, m7 + psubw m3, m15, m2 + psllw m2, 8 + pshufb m0, m10 + por m2, m3 + pmaddubsw m0, m2 + pand m2, m14, m5 + psubw m3, m15, m2 + psllw m2, 8 + pshufb m1, m10 + por m2, m3 + pmaddubsw m1, m2 + cmp r3d, 64 + jge .w16_toponly + punpckhwd m2, m5, m5 ; mask out unnecessary loads + vpgatherdd m4, [r5+m9], m2 + punpcklwd m2, m5, m5 + vpgatherdd m3, [r5+m8], m2 + pshufb m4, m11 ; e0 f0 g0 h0 e1 f1 g1 h1 m0 n0 o0 p0 m1 n1 o1 p1 + pshufb m3, m11 ; a0 b0 c0 d0 a1 b1 c1 d1 i0 j0 k0 l0 i1 j1 k1 l1 + punpcklqdq m2, m3, m4 ; y0 + punpckhqdq m3, m4 ; y1 + pmaddubsw m2, m12 + pmaddubsw m3, m12 + psraw m6, 15 ; base_x < topleft + vpblendvb m0, m2, m6 + psraw m6, m5, 15 + vpblendvb m1, m3, m6 +.w16_toponly: + pmulhrsw m0, m13 + pmulhrsw m1, m13 + paddw m6, m5, m7 ; xpos += dx + sub r5, 2 + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r2d, (63-16)<<6 + jge .w16_loop +.w16_leftonly_loop: + mova m0, m7 + vpgatherdd m4, [r5+m9], m7 + mova m7, m0 + vpgatherdd m3, [r5+m8], m0 + sub r5, 2 + pshufb m2, m4, m11 + pshufb m1, m3, m11 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pmaddubsw m0, m12 + pmaddubsw m1, m12 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_leftonly_loop +.w16_end: + sub r8d, 1<<8 + jl .w16_ret + vpbroadcastd m0, [rsp+156] + paddw m0, [rsp+160] ; base_y += 16*dy + paddw m6, m13, [rsp+192] + add r7, 16 + add r9d, 16<<6 + movzx hd, r8b + mov dstq, r7 + paddw m6, m13 ; base_x += 16*64 + jmp .w16_loop0 +.w16_ret: + RET +.w32: + mova m2, [tlq+32] + lea r8d, [hq+(1<<8)] + mova [rsp+96], m2 + test angled, 0x400 + jnz .w16_main + vpbroadcastd m7, [base+z_filter_k+4*2+12*0] + vpbroadcastd m8, [base+z_filter_k+4*2+12*1] + vpbroadcastd m9, [base+z_filter_k+4*2+12*2] + mova xm5, [base+z_filter_s] + vinserti128 m5, [base+z_filter_s+10], 1 ; 00 01 12 23 34 45 56 67 45 56 67 78 89 9a ab bc + vinserti128 m1, [tlq+11], 1 + movu xm6, [base+z_filter_s+12] + vinserti128 m6, [base+z_filter_s+22], 1 ; 56 67 78 89 9a ab bc cd ab bc cd de ef ff ff ff + movu xm3, [tlq+ 6] + vinserti128 m3, [tlq+17], 1 + movd xm0, r6m ; max_width + pminsw xm0, xm15 + vpbroadcastb m10, xm0 +.w32_filter_above: + pshufb m0, m1, m5 + shufps m4, m5, m6, q1021 ; 12 23 34 45 56 67 78 89 67 78 89 9a ab bc cd de + pmaddubsw m0, m7 + pshufb m2, m1, m4 + shufps m5, m6, q2132 ; 34 45 56 67 78 89 9a ab 89 9a ab bc cd de ef ff + pmaddubsw m2, m8 + pshufb m1, m5 + pmaddubsw m1, m9 + paddw m0, m2 + paddw m0, m1 + pshufb m1, m3, m4 + pmaddubsw m1, m7 + pshufb m2, m3, m5 + pmaddubsw m2, m8 + pshufb m3, m6 + pmaddubsw m3, m9 + paddw m1, m2 + paddw m1, m3 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + psubb m10, [base+pb_1to32] + packuswb m0, m1 + vpblendvb m0, [tlq+1], m10 + movu [rsp+65], m0 + jmp .w16_filter_left +.w64: + mova m2, [tlq+32] + mov r3d, [tlq+64] + lea r8d, [hq+(3<<8)] + mova [rsp+ 96], m2 + mov [rsp+128], r3d + test angled, 0x400 + jnz .w16_main + vpbroadcastd m7, [base+z_filter_k+4*2+12*0] + vpbroadcastd m8, [base+z_filter_k+4*2+12*1] + vpbroadcastd m9, [base+z_filter_k+4*2+12*2] + movu xm6, [base+z_filter_s+ 4] + vinserti128 m6, [base+z_filter_s+10], 1 ; 12 23 34 45 56 67 78 89 45 56 67 78 89 9a ab bc + movu xm3, [tlq+30] + vinserti128 m3, [tlq+43], 1 + movu xm5, [base+z_filter_s+16] + vinserti128 m5, [base+z_filter_s+22], 1 ; 78 89 9a ab bc cd de ef ab bc cd de ef ff ff ff + pshufb m0, m3, m6 + shufps m4, m6, m5, q1021 ; 34 45 56 67 78 89 9a ab 67 78 89 9a ab bc cd de + pmaddubsw m0, m7 + pshufb m2, m3, m4 + shufps m6, m5, q2132 ; 56 67 78 89 9a ab bc cd 89 9a ab bc cd de ef ff + pmaddubsw m2, m8 + pshufb m3, m6 + pmaddubsw m3, m9 + paddw m0, m2 + paddw m0, m3 + movu xm2, [tlq+36] + vinserti128 m2, [tlq+49], 1 + pshufb m4, m2, m4 + pmaddubsw m4, m7 + pshufb m3, m2, m6 + pmaddubsw m3, m8 + pshufb m2, m5 + pmaddubsw m2, m9 + movd xm5, r6m ; max_width + pminsw xm5, xm15 + vpbroadcastb m10, xm5 + paddw m3, m4 + paddw m2, m3 + vpbroadcastd m3, [base+pb_32] + pmulhrsw m0, m13 + pmulhrsw m2, m13 + mova xm5, [base+z_filter_s] + vinserti128 m5, [base+z_filter_s+6], 1 + psubb m3, m10, m3 + psubb m3, [base+pb_1to32] + vinserti128 m1, [tlq+13], 1 + packuswb m0, m2 + vpblendvb m0, [tlq+33], m3 + movu xm3, [tlq+ 6] + vinserti128 m3, [tlq+19], 1 + movu [rsp+97], m0 + jmp .w32_filter_above + +cglobal ipred_z3_8bpc, 4, 9, 0, dst, stride, tl, w, h, angle, dy, org_w, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z3_avx2_table] + tzcnt hd, hm + movifnidn angled, anglem + lea r7, [dr_intra_derivative+45*2-1] + dec tlq + movsxd hq, [r6+hq*4] + sub angled, 180 + add hq, r6 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + movzx dyd, word [r7+dyq] + vpbroadcastd m3, [pw_512] + vpbroadcastd m4, [pw_62] + vpbroadcastd m5, [pw_64] + mov org_wd, wd + jmp hq +.h4: + lea r7, [strideq*3] + cmp angleb, 40 + jae .h4_no_upsample + lea r4d, [angleq-1024] + sar r4d, 7 + add r4d, wd + jg .h4_no_upsample ; !enable_intra_edge_filter || w > 8 || (w == 8 && is_sm) + ALLOC_STACK -32, 9 + movu xm8, [tlq-7] + pshufb xm0, xm8, [z_upsample1-4] + vpbroadcastb xm2, xm8 + pshufb xm1, xm8, [z_filter_s+2] + mova [rsp+16], xm2 ; top[max_base_y] + vpbroadcastd xm2, [pb_36_m4] + add dyd, dyd + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + movd xm7, dyd + mov r2d, dyd + vpbroadcastw m7, xm7 + paddw xm1, xm0 + pmulhrsw xm1, xm3 + pslldq m6, m7, 8 + paddw xm2, xm7, xm7 + paddw m6, m7 + packuswb xm1, xm1 + paddw m6, m2 + punpcklbw xm1, xm8 + mova xm8, [z_transpose4] + psllw m7, 2 + pshufb xm1, [pb_15to0] + mova [rsp], xm1 +.h4_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 + vpbroadcastq m1, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 + vpbroadcastq m2, [rsp+r4] + lea r4d, [r2+dyq] + shr r2d, 6 + movq xm0, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 + movhps xm0, [rsp+r4] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 + psllw m2, 8 + por m1, m2 + pmaddubsw m0, m1 + paddw m6, m7 + pmulhrsw m0, m3 + vextracti128 xm1, m0, 1 + packuswb xm1, xm0 + pshufb xm1, xm8 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r7 ], xm1, 3 + add dstq, 4 + sub wd, 4 + jg .h4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; h4/h8/h16 +%define base r4-z_filter_t0 + lea r4, [z_filter_t0] + movd xm0, maxbased + movd xm2, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m2, xm2 + pcmpeqb m1, m0, [base+z_filter_wh] + pand m1, m2 + mova xm2, [r4+angleq*8] + pcmpgtb m1, m2 + pmovmskb r5d, m1 + ret +.h4_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -16, 12 + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea maxbased, [wq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m7, [base+pb_7] + vbroadcasti128 m2, [tlq-14] + pmaxub m1, m7, [base+z_filter_s-4] + vpbroadcastd m8, [base+z_filter_k-4+r5*4+12*0] + pmaxub m7, [base+z_filter_s+4] + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m10, [base+z_filter_k-4+r5*4+12*2] + pshufb m0, m2, m1 + shufps m1, m7, q2121 + pmaddubsw m0, m8 + pshufb m1, m2, m1 + pmaddubsw m1, m9 + pshufb m2, m7 + pmaddubsw m2, m10 + paddw m0, m1 + paddw m0, m2 + pmulhrsw m0, m3 + mov r4d, 9 + lea tlq, [rsp+15] + cmp wd, 4 + cmovne maxbased, r4d + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [rsp], xm0 +.h4_main: + movd xm6, dyd + vpbroadcastq m0, [z_base_inc] ; base_inc << 6 + mov r4, tlq + sub tlq, 4 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] ; ypos + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf_w4] + add maxbased, 64 + vpbroadcastw m9, xm9 + psrlw m7, 8 ; top[max_base_y] + paddw m10, m6, m6 + psubw m9, m0 ; max_base_y + vpblendd m6, m10, 0xcc + mova xm0, xm10 + paddw m6, m0 ; ypos2 ypos3 ypos0 ypos1 + paddw m10, m10 + mova xm11, [z_transpose4] +.h4_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + vpbroadcastq m1, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + vpbroadcastq m2, [tlq+r5] + lea r5, [r4+dyq] + sar r4, 6 ; base2 + movq xm0, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + movhps xm0, [tlq+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + pcmpgtw m1, m9, m6 ; base < max_base_y + pmulhrsw m0, m3 + paddw m6, m10 ; ypos += dy + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + packuswb xm1, xm0 + pshufb xm1, xm11 ; transpose + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r7 ], xm1, 3 + sub wd, 4 + jz .h4_end + add dstq, 4 + cmp r4d, maxbased + jg .h4_loop + packuswb xm7, xm7 +.h4_end_loop: + movd [dstq+strideq*0], xm7 + movd [dstq+strideq*1], xm7 + movd [dstq+strideq*2], xm7 + movd [dstq+r7 ], xm7 + add dstq, 4 + sub wd, 4 + jg .h4_end_loop +.h4_end: + RET +ALIGN function_align +.h8: + lea r4d, [angleq+216] + mov r4b, wb + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 8 + and r4d, 4 + mova xm0, [tlq-15] + vinserti128 m0, [tlq- 9], 1 + movd xm1, r4d + movu xm2, [z_filter_s+2] + vinserti128 m2, [z_filter_s+6], 1 + vpbroadcastb xm1, xm1 ; w & 4 + vpbroadcastd m7, [pb_36_m4] + pmaxub xm1, [z_upsample1-4] ; clip 4x8 + vinserti128 m1, [z_upsample1], 1 + add dyd, dyd + pshufb m1, m0, m1 + pshufb m2, m0, m2 + vinserti128 m0, [tlq-7], 1 + movd xm6, dyd + pmaddubsw m1, m7 + pmaddubsw m2, m7 + vpbroadcastw m6, xm6 + mov r2d, dyd + lea r5, [strideq*3] + paddw m7, m6, m6 + paddw m1, m2 + vpblendd m6, m7, 0xf0 + pmulhrsw m1, m3 + pslldq m2, m7, 8 + paddw m7, m7 + paddw m6, m2 + vbroadcasti128 m2, [pb_15to0] + packuswb m1, m1 + punpcklbw m1, m0 + pshufb m1, m2 + vextracti128 [rsp+ 0], m1, 1 + mova [rsp+16], xm1 +.h8_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 ; base0 + movu xm0, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base1 + vinserti128 m0, [rsp+r4], 1 + lea r4d, [r2+dyq] + shr r2d, 6 ; base2 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + punpcklqdq m1, m2, m2 ; frac0 frac1 + pmaddubsw m0, m1 + movu xm1, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base3 + vinserti128 m1, [rsp+r4], 1 + punpckhqdq m2, m2 ; frac2 frac3 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + paddw m6, m7 + pmulhrsw m1, m3 + lea r4, [dstq+strideq*4] + psllw m1, 8 + por m0, m1 + vextracti128 xm1, m0, 1 + punpcklbw xm2, xm0, xm1 + punpckhbw xm0, xm1 + movd [dstq+strideq*0], xm2 + pextrd [dstq+strideq*1], xm2, 1 + pextrd [dstq+strideq*2], xm2, 2 + pextrd [dstq+r5 ], xm2, 3 + movd [r4 +strideq*0], xm0 + pextrd [r4 +strideq*1], xm0, 1 + pextrd [r4 +strideq*2], xm0, 2 + pextrd [r4 +r5 ], xm0, 3 + add dstq, 4 + sub wd, 4 + jg .h8_upsample_loop + RET +.h8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(w+7, 15) + jmp .h8_main +.h8_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 10 + lea maxbased, [wq+7] + test angled, 0x400 + jnz .h8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h8_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd xm6, [base+pb_15] + pcmpeqb xm1, xm1 + psubusb xm6, xm0 + psubb xm6, xm1 ; w == 4 ? 5 : 1 + movu xm2, [tlq-16] + pmaxub xm1, xm6, [base+z_filter_s] + vinserti128 m2, [tlq-14], 1 + vinserti128 m1, [base+z_filter_s+12], 1 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pmaxub xm6, [base+z_filter_s+ 8] + vinserti128 m6, [base+z_filter_s+20], 1 + pshufb m0, m2, m1 + pmaddubsw m0, m7 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*1] + movzx r4d, byte [tlq-15] + shufps m1, m6, q2121 + pshufb m1, m2, m1 + pmaddubsw m1, m7 + paddw m0, m1 + sub r5d, 3 + jnz .h8_3tap + vpbroadcastd m7, [z_filter_k+4*8] + movzx r2d, byte [tlq-14] + pshufb m2, m6 + pmaddubsw m2, m7 + sub r2d, r4d + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+15], r2b + paddw m0, m2 +.h8_3tap: + pmulhrsw m0, m3 + sar r5d, 1 + lea tlq, [rsp+31] + add r5d, 17 + cmp wd, 16 + cmovns maxbased, r5d + neg r5 + mov [tlq+r5], r4b + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [tlq-15], xm0 +.h8_main: + movd xm2, dyd + vbroadcasti128 m0, [z_base_inc] + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m2, xm2 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psrlw m7, 8 + psubw m9, m0 + paddw m6, m2, m2 + vpblendd m2, m6, 0x0f +.h8_loop: + lea r5, [r4+dyq] + sar r4, 6 + pand m0, m4, m2 + psubw m1, m5, m0 + psllw m0, 8 + por m1, m0 + vbroadcasti128 m0, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 + vinserti128 m0, [tlq+r5], 0 + sub rsp, 8*2 + pshufb m0, m8 + pmaddubsw m0, m1 + pcmpgtw m1, m9, m2 + paddw m2, m6 + pmulhrsw m0, m3 + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + psllw xm0, 8 + por xm0, xm1 ; interleave rows (partial transpose) + mova [rsp], xm0 + sub wd, 2 + jz .h8_transpose + cmp r4d, maxbased + jg .h8_loop + packuswb xm0, xm7, xm7 +.h8_end_loop: + sub rsp, 8*2 + mova [rsp], xm0 + sub wd, 2 + jg .h8_end_loop +.h8_transpose: + mova xm2, [rsp+16*1] + sub org_wd, 8 + lea r2, [strideq*3] + lea r6, [dstq+org_wq] + cmovns dstq, r6 + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 + lea r6, [dstq+strideq*4] + jge .h8_w8 + add rsp, 16*2 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r2 ], xm1, 3 + movd [r6 +strideq*0], xm2 + pextrd [r6 +strideq*1], xm2, 1 + pextrd [r6 +strideq*2], xm2, 2 + pextrd [r6 +r2 ], xm2, 3 + jmp .h8_end +.h8_w8_loop: + mova xm0, [rsp+16*0] + mova xm2, [rsp+16*1] + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 +.h8_w8: ; w8/w16/w32 + mova xm0, [rsp+16*2] + mova xm4, [rsp+16*3] + add rsp, 16*4 + punpcklwd xm3, xm4, xm0 + punpckhwd xm4, xm0 + punpckldq xm0, xm3, xm1 + punpckhdq xm3, xm1 + punpckldq xm1, xm4, xm2 + punpckhdq xm4, xm2 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm3 + movhps [dstq+r2 ], xm3 + movq [r6 +strideq*0], xm1 + movhps [r6 +strideq*1], xm1 + movq [r6 +strideq*2], xm4 + movhps [r6 +r2 ], xm4 + sub dstq, 8 + sub r6, 8 + sub org_wd, 8 + jge .h8_w8_loop +.h8_end: + RET +.h16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(w+15, 31) + jmp .h16_main +ALIGN function_align +.h16: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 12 + lea maxbased, [wq+15] + test angled, 0x400 + jnz .h16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h16_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m11, [base+pb_27] + vpbroadcastd m1, [base+pb_1] + vbroadcasti128 m6, [base+z_filter_s+12] + vinserti128 m2, m6, [base+z_filter_s+4], 0 + vinserti128 m6, [base+z_filter_s+20], 1 + movu xm10, [tlq-18] + vinserti128 m10, [tlq-14], 1 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*0] + vbroadcasti128 m7, [base+z_filter_s+8] + vinserti128 m8, m7, [base+z_filter_s+0], 0 + vinserti128 m7, [base+z_filter_s+16], 1 + psubusb m11, m0 + por m1, m11 + movu xm11, [tlq-32] + vinserti128 m11, [tlq-28], 1 + pmaxub m8, m1 + pmaxub m7, m1 + pshufb m0, m10, m2 + shufps m2, m6, q2121 + pmaddubsw m0, m9 + pshufb m1, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m1, m9 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + movzx r4d, byte [tlq-31] + pshufb m2, m10, m2 + pmaddubsw m2, m9 + pshufb m8, m11, m8 + pmaddubsw m8, m9 + paddw m0, m2 + paddw m1, m8 + sub r5d, 3 + jnz .h16_3tap + vpbroadcastd m9, [z_filter_k+4*8] + movzx r2d, byte [tlq-30] + pshufb m10, m6 + pmaddubsw m10, m9 + pshufb m11, m7 + pmaddubsw m11, m9 + sub r2d, r4d + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+31], r2b + paddw m0, m10 + paddw m1, m11 +.h16_3tap: + pmulhrsw m0, m3 + pmulhrsw m1, m3 + sar r5d, 1 + lea tlq, [rsp+63] + add r5d, 33 + cmp wd, 32 + cmovns maxbased, r5d + neg r5 + mov [tlq+r5], r4b + packuswb m0, m1 + vpermq m0, m0, q2031 + mova [tlq-31], m0 +.h16_main: + movd xm6, dyd + vbroadcasti128 m0, [z_base_inc] + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psubw m9, m0 + paddw m11, m6, m6 + psubw m10, m9, m3 ; 64*8 + vpblendd m6, m11, 0xf0 +.h16_loop: + lea r5, [r4+dyq] + sar r4, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r4-0] + movu xm1, [tlq+r4-8] + lea r4, [r5+dyq] + sar r5, 6 + vinserti128 m0, [tlq+r5-0], 1 + vinserti128 m1, [tlq+r5-8], 1 + sub rsp, 32 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + vpermq m0, m0, q3120 + mova [rsp], m0 + sub wd, 2 + jz .h16_transpose + cmp r4d, maxbased + jg .h16_loop + mova m0, m7 +.h16_end_loop: + sub rsp, 32 + mova [rsp], m7 + sub wd, 2 + jg .h16_end_loop +.h16_transpose: + mova m2, [rsp+32*1] + sub org_wd, 8 + lea r2, [strideq*3] + lea r6, [dstq+org_wq] + cmovns dstq, r6 + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + lea r3, [strideq*5] + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + lea r4, [strideq+r2*2] ; stride*7 + jge .h16_w8 + add rsp, 32*2 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + vextracti128 xm0, m0, 1 + movd [dstq+strideq*4], xm1 + pextrd [dstq+r3 ], xm1, 1 + pextrd [dstq+r2*2 ], xm1, 2 + pextrd [dstq+r4 ], xm1, 3 + lea dstq, [dstq+strideq*8] + vextracti128 xm1, m1, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + movd [dstq+strideq*4], xm1 + pextrd [dstq+r3 ], xm1, 1 + pextrd [dstq+r2*2 ], xm1, 2 + pextrd [dstq+r4 ], xm1, 3 + jmp .h16_end +.h16_w8_loop: + mova m0, [rsp+32*0] + mova m2, [rsp+32*1] + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 +.h16_w8: + mova m2, [rsp+32*2] + mova m4, [rsp+32*3] + lea r6, [dstq+strideq*8] + add rsp, 32*4 + punpcklbw m3, m4, m2 + punpckhbw m4, m2 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + punpckldq m4, m2, m0 + punpckhdq m2, m0 + punpckldq m0, m3, m1 + punpckhdq m3, m1 + movq [dstq+strideq*0], xm4 + movhps [dstq+strideq*1], xm4 + vextracti128 xm4, m4, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+r2 ], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*4], xm0 + movhps [dstq+r3 ], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+r2*2 ], xm3 + movhps [dstq+r4 ], xm3 + vextracti128 xm3, m3, 1 + movq [r6+strideq*0], xm4 + movhps [r6+strideq*1], xm4 + movq [r6+strideq*2], xm2 + movhps [r6+r2 ], xm2 + movq [r6+strideq*4], xm0 + movhps [r6+r3 ], xm0 + movq [r6+r2*2 ], xm3 + movhps [r6+r4 ], xm3 + sub dstq, 8 + sub org_wd, 8 + jge .h16_w8_loop +.h16_end: + RET +ALIGN function_align +.h32: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 15 + lea maxbased, [wq+31] + and maxbased, 31 + or maxbased, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + vbroadcasti128 m0, [pb_0to15] + mov r4d, 21 + mov r5d, 3 + movu xm11, [tlq-66] ; 56-63 + vinserti128 m11, [tlq-52], 1 ; 40-47 + sub r4d, wd ; 21-w + cmovns r5d, r4d + movu xm12, [tlq-58] ; 48-55 + vinserti128 m12, [tlq-44], 1 ; 32-39 + sub r4d, 8 ; 13-w + movd xm1, r5d + movu xm13, [tlq-34] ; 24-31 + vinserti128 m13, [tlq-20], 1 ; 8-15 + movd xm2, r4d + vpbroadcastb m1, xm1 + movu xm14, [tlq-28] ; 16-23 + vinserti128 m14, [tlq-14], 1 ; 0- 7 + vpbroadcastb m2, xm2 + pmaxsb m1, m0 ; clip 16x32 and (32|64)x32 + movu m7, [z_filter_s+4] + pshufb m11, m1 + vinserti128 m8, m7, [z_filter_s+8], 1 + vinserti128 m7, [z_filter_s+16], 0 + pmaxsb m2, m0 ; clip 8x32 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m12, m2 + pshufb m0, m11, m8 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + shufps m8, m7, q1021 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m8 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m8 + pmaddubsw m10, m9 + shufps m8, m7, q2121 + paddw m1, m10 + pshufb m10, m14, m8 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + movzx r4d, byte [tlq-63] + movzx r2d, byte [tlq-62] + paddw m0, m11 + paddw m2, m12 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m7 + pmaddubsw m14, m9 + paddw m1, m13 + paddw m6, m14 + sub r2d, r4d + lea r2d, [r2+r4*8+4] ; edge case for 64x32 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + shr r2d, 3 + mov [rsp+31], r2b + lea tlq, [rsp+95] + mov [tlq-65], r4b + mov r4d, 65 + cmp wd, 64 + cmove maxbased, r4d + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-63], m0 + mova [tlq-31], m1 +.h32_main: + movd xm6, dyd + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psubw m9, [z_base_inc] + mova m11, m6 + psubw m10, m9, m3 ; 64*8 +.h32_loop: + mov r5, r4 + sar r5, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r5- 0] + vinserti128 m0, [tlq+r5-16], 1 + movu xm1, [tlq+r5- 8] + vinserti128 m1, [tlq+r5-24], 1 + sub rsp, 32 + add r4, dyq + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [rsp], m0 + dec wd + jz .h32_transpose + cmp r4d, maxbased + jg .h32_loop +.h32_end_loop: + sub rsp, 32 + mova [rsp], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + lea dstq, [dstq+org_wq-8] + lea r2, [strideq*3] + lea r3, [strideq*5] + lea r4, [strideq+r2*2] ; stride*7 +.h32_w8_loop: + mova m7, [rsp+32*0] + mova m6, [rsp+32*1] + mova m5, [rsp+32*2] + mova m4, [rsp+32*3] + mova m3, [rsp+32*4] + mova m2, [rsp+32*5] + mova m1, [rsp+32*6] + mova m0, [rsp+32*7] + lea r6, [dstq+strideq*8] + add rsp, 32*8 + punpcklbw m8, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklwd m7, m8, m1 + punpckhwd m8, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpckldq m6, m7, m2 + punpckhdq m7, m2 + punpckldq m2, m8, m3 + punpckhdq m8, m3 + punpckldq m3, m1, m5 + punpckhdq m1, m5 + punpckldq m5, m0, m4 + punpckhdq m0, m4 + movq [dstq+strideq*0], xm6 + movhps [dstq+strideq*1], xm6 + vextracti128 xm6, m6, 1 + movq [dstq+strideq*2], xm7 + movhps [dstq+r2 ], xm7 + vextracti128 xm7, m7, 1 + movq [dstq+strideq*4], xm2 + movhps [dstq+r3 ], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+r2*2 ], xm8 + movhps [dstq+r4 ], xm8 + vextracti128 xm8, m8, 1 + movq [r6+strideq*0], xm3 + movhps [r6+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [r6+strideq*2], xm1 + movhps [r6+r2 ], xm1 + vextracti128 xm1, m1, 1 + movq [r6+strideq*4], xm5 + movhps [r6+r3 ], xm5 + vextracti128 xm5, m5, 1 + movq [r6+r2*2 ], xm0 + movhps [r6+r4 ], xm0 + lea r6, [r6+strideq*8] + vextracti128 xm0, m0, 1 + movq [r6+strideq*0], xm6 + movhps [r6+strideq*1], xm6 + movq [r6+strideq*2], xm7 + movhps [r6+r2 ], xm7 + movq [r6+strideq*4], xm2 + movhps [r6+r3 ], xm2 + movq [r6+r2*2 ], xm8 + movhps [r6+r4 ], xm8 + lea r6, [r6+strideq*8] + movq [r6+strideq*0], xm3 + movhps [r6+strideq*1], xm3 + movq [r6+strideq*2], xm1 + movhps [r6+r2 ], xm1 + movq [r6+strideq*4], xm5 + movhps [r6+r3 ], xm5 + movq [r6+r2*2 ], xm0 + movhps [r6+r4 ], xm0 + sub dstq, 8 + sub org_wd, 8 + jg .h32_w8_loop + RET +ALIGN function_align +.h64: + %assign stack_offset org_stack_offset + ALLOC_STACK -128, 16 + lea maxbased, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + mov r4d, 21 + vpbroadcastb xm11, [tlq-127] + vpblendd xm11, [tlq-130], 0x0e ; 120-127 + sub r4d, wd ; 21-w + mov r5d, 3 + vinserti128 m11, [tlq-116], 1 ; 104-111 + movu m7, [z_filter_s+4] + cmp wd, 32 + cmove r4d, r5d + vinserti128 m8, m7, [z_filter_s+8], 1 + vbroadcasti128 m6, [pb_0to15] + movd xm1, r4d + vpbroadcastd m9, [z_filter_k+4*2+12*0] + movu xm12, [tlq-122] ; 112-119 + vinserti128 m12, [tlq-108], 1 ; 96-103 + vpbroadcastb m1, xm1 + movu xm13, [tlq- 98] ; 88- 95 + vinserti128 m13, [tlq- 84], 1 ; 72- 79 + movu xm14, [tlq- 90] ; 80- 87 + vinserti128 m14, [tlq- 76], 1 ; 64- 71 + vinserti128 m7, [z_filter_s+16], 0 + pshufb m0, m11, m8 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pmaxsb m1, m6 ; clip (16|32)x64 + pshufb m13, m1 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + shufps m15, m8, m7, q1021 + pshufb m10, m11, m15 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m15 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + shufps m10, m8, m7, q2132 + pshufb m11, m10 + pmaddubsw m11, m9 + pshufb m12, m10 + pmaddubsw m12, m9 + pshufb m13, m10 + pmaddubsw m13, m9 + pshufb m14, m10 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + movu xm11, [tlq-66] ; 56-63 + vinserti128 m11, [tlq-52], 1 ; 40-47 + movu xm12, [tlq-58] ; 48-55 + vinserti128 m12, [tlq-44], 1 ; 32-39 + movu xm13, [tlq-34] ; 24-31 + vinserti128 m13, [tlq-20], 1 ; 8-15 + movu xm14, [tlq-28] ; 16-23 + vinserti128 m14, [tlq-14], 1 ; 0- 7 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + lea tlq, [rsp+127] + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-127], m0 + mova [tlq- 95], m1 + pshufb m0, m11, m10 + pmaddubsw m0, m9 + pshufb m2, m12, m10 + pmaddubsw m2, m9 + pshufb m1, m13, m10 + pmaddubsw m1, m9 + pshufb m6, m14, m7 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m7, m11, m15 + pmaddubsw m7, m9 + paddw m0, m7 + pshufb m7, m12, m15 + pmaddubsw m7, m9 + paddw m2, m7 + pshufb m7, m13, m15 + pmaddubsw m7, m9 + paddw m1, m7 + pshufb m7, m14, m10 + pmaddubsw m7, m9 + paddw m6, m7 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m15 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-63], m0 + mova [tlq-31], m1 +.h64_main: + movd xm12, dyd + neg maxbaseq + vbroadcasti128 m8, [z3_shuf] + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m12, xm12 + lea r5d, [dyq+maxbaseq-64] + neg dyq + or maxbased, 63 + lea r4, [dyq+63] + movd xm6, r5d + mova xm10, [pb_1to32+16] + vinserti128 m10, [pb_1to32], 1 + vpbroadcastd m11, [pb_32] + vpbroadcastw m6, xm6 +.h64_loop: + mov r5, r4 + sar r5, 6 + movu m0, [tlq+r5-24] + movu m1, [tlq+r5-32] + pand m2, m4, m6 + psubw m9, m5, m2 + psllw m2, 8 + por m9, m2 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + psraw m2, m6, 6 + sub rsp, 64 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packsswb m2, m2 + paddb m2, m10 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [rsp+32], m0 + movu m0, [tlq+r5-56] + movu m1, [tlq+r5-64] + add r4, dyq + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + paddb m2, m11 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + paddw m6, m12 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [rsp], m0 + dec wd + jz .h64_transpose + cmp r4d, maxbased + jg .h64_loop +.h64_end_loop: + sub rsp, 64 + mova [rsp+32], m7 + mova [rsp+ 0], m7 + dec wd + jg .h64_end_loop +.h64_transpose: + lea r2, [strideq*3] + lea r3, [strideq*5] + imul r5, strideq, -8 + lea dstq, [dstq+org_wq-16] + lea r4, [strideq+r2*2] ; stride*7 +.h64_transpose_loop0: + lea r6, [rsp+16*3] +.h64_transpose_loop: + mova xm0, [r6+64*15] + vinserti128 m0, [r6+64* 7], 1 + mova xm1, [r6+64*14] + vinserti128 m1, [r6+64* 6], 1 + mova xm2, [r6+64*13] + vinserti128 m2, [r6+64* 5], 1 + mova xm3, [r6+64*12] + vinserti128 m3, [r6+64* 4], 1 + mova xm4, [r6+64*11] + vinserti128 m4, [r6+64* 3], 1 + mova xm5, [r6+64*10] + vinserti128 m5, [r6+64* 2], 1 + mova xm6, [r6+64* 9] + vinserti128 m6, [r6+64* 1], 1 + mova xm7, [r6+64* 8] + vinserti128 m7, [r6+64* 0], 1 + sub r6, 16 + punpcklbw m8, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklwd m7, m8, m1 + punpckhwd m8, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpckldq m6, m7, m2 + punpckhdq m7, m2 + punpckldq m2, m8, m3 + punpckhdq m8, m3 + punpckldq m3, m1, m5 + punpckhdq m1, m5 + punpckldq m5, m0, m4 + punpckhdq m0, m4 + vpermq m6, m6, q3120 + vpermq m7, m7, q3120 + vpermq m2, m2, q3120 + vpermq m8, m8, q3120 + vpermq m3, m3, q3120 + vpermq m1, m1, q3120 + vpermq m5, m5, q3120 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm6 + vextracti128 [dstq+strideq*1], m6, 1 + mova [dstq+strideq*2], xm7 + vextracti128 [dstq+r2 ], m7, 1 + mova [dstq+strideq*4], xm2 + vextracti128 [dstq+r3 ], m2, 1 + mova [dstq+r2*2 ], xm8 + vextracti128 [dstq+r4 ], m8, 1 + sub dstq, r5 + mova [dstq+strideq*0], xm3 + vextracti128 [dstq+strideq*1], m3, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+r2 ], m1, 1 + mova [dstq+strideq*4], xm5 + vextracti128 [dstq+r3 ], m5, 1 + mova [dstq+r2*2 ], xm0 + vextracti128 [dstq+r4 ], m0, 1 + sub dstq, r5 + cmp r6, rsp + jae .h64_transpose_loop + add rsp, 64*16 + lea dstq, [dstq+r5*8-16] + sub org_wd, 16 + jg .h64_transpose_loop0 +.h64_end: + RET + +%macro FILTER_XMM 4 ; dst, src, tmp, shuf +%ifnum %4 + pshufb xm%2, xm%4 +%else + pshufb xm%2, %4 +%endif + pshufd xm%1, xm%2, q0000 ; p0 p1 + pmaddubsw xm%1, xm2 + pshufd xm%3, xm%2, q1111 ; p2 p3 + pmaddubsw xm%3, xm3 + paddw xm%1, xm1 + paddw xm%1, xm%3 + pshufd xm%3, xm%2, q2222 ; p4 p5 + pmaddubsw xm%3, xm4 + paddw xm%1, xm%3 + pshufd xm%3, xm%2, q3333 ; p6 __ + pmaddubsw xm%3, xm5 + paddw xm%1, xm%3 + psraw xm%1, 4 + packuswb xm%1, xm%1 +%endmacro + +%macro FILTER_YMM 4 ; dst, src, tmp, shuf + pshufb m%2, m%4 + pshufd m%1, m%2, q0000 + pmaddubsw m%1, m2 + pshufd m%3, m%2, q1111 + pmaddubsw m%3, m3 + paddw m%1, m1 + paddw m%1, m%3 + pshufd m%3, m%2, q2222 + pmaddubsw m%3, m4 + paddw m%1, m%3 + pshufd m%3, m%2, q3333 + pmaddubsw m%3, m5 + paddw m%1, m%3 + psraw m%1, 4 + vperm2i128 m%3, m%1, m%1, 0x01 + packuswb m%1, m%3 +%endmacro + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. One redundant +; block is calculated for w8 and w16, two for w32. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 5 1 2 3 5 b c d f +; 2 2 3 2 4 5 7 2 4 5 7 c e f h +; 3 3 4 4 6 7 9 4 6 7 9 e g h j +; ___ 4 ___ 4 5 ___ 6 8 9 a ___ 6 8 9 a g i j k ___ +; 5 8 8 i + +cglobal ipred_filter_8bpc, 3, 7, 0, dst, stride, tl, w, h, filter +%define base r6-ipred_filter_avx2_table + lea r6, [filter_intra_taps] + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + add filterq, r6 + lea r6, [ipred_filter_avx2_table] + movq xm0, [tlq-3] ; _ 6 5 0 1 2 3 4 + movsxd wq, [r6+wq*4] + vpbroadcastd m1, [base+pw_8] + vbroadcasti128 m2, [filterq+16*0] + vbroadcasti128 m3, [filterq+16*1] + vbroadcasti128 m4, [filterq+16*2] + vbroadcasti128 m5, [filterq+16*3] + add wq, r6 + mov hd, hm + jmp wq +.w4: + WIN64_SPILL_XMM 9 + mova xm8, [base+filter_shuf2] + sub tlq, 3 + sub tlq, hq + jmp .w4_loop_start +.w4_loop: + pinsrd xm0, xm6, [tlq+hq], 0 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER_XMM 6, 0, 7, 8 + movd [dstq+strideq*0], xm6 + pextrd [dstq+strideq*1], xm6, 1 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 10 + mova m8, [base+filter_shuf1] + FILTER_XMM 7, 0, 6, [base+filter_shuf2] + vpbroadcastd m0, [tlq+4] + vpbroadcastd m6, [tlq+5] + sub tlq, 4 + sub tlq, hq + vpbroadcastq m7, xm7 + vpblendd m7, m6, 0x20 +.w8_loop: + vpbroadcastd xm6, [tlq+hq] + palignr m6, m0, 12 + vpblendd m0, m6, m7, 0xeb ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm6, xm7 + call .main + vpblendd xm6, xm7, 0x0c + pshufd xm6, xm6, q3120 + movq [dstq+strideq*0], xm6 + movhps [dstq+strideq*1], xm6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + %assign xmm_regs_used 15 + %assign stack_size_padded 0x98 + SUB rsp, stack_size_padded +%endif + sub hd, 2 + TAIL_CALL .w16_main, 0 +.w16_main: +%if WIN64 + movaps [rsp+0xa8], xmm6 + movaps [rsp+0xb8], xmm7 + movaps [rsp+0x28], xmm8 + movaps [rsp+0x38], xmm9 + movaps [rsp+0x48], xmm10 + movaps [rsp+0x58], xmm11 + movaps [rsp+0x68], xmm12 + movaps [rsp+0x78], xmm13 + movaps [rsp+0x88], xmm14 +%endif + FILTER_XMM 12, 0, 7, [base+filter_shuf2] + vpbroadcastd m0, [tlq+5] + vpblendd m0, [tlq-12], 0x14 + mova m8, [base+filter_shuf1] + vpbroadcastq m7, xm12 + vpblendd m0, m7, 0xc2 ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + call .main ; c0 d0 a1 b1 a1 b1 c0 d0 + movlps xm9, xm7, [tlq+5] ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + vinserti128 m14, m8, [base+filter_shuf3], 0 + vpblendd xm12, xm7, 0x0c ; a0 b0 a1 b1 + FILTER_XMM 6, 9, 10, 14 + vpbroadcastq m6, xm6 ; a2 b2 __ __ __ __ a2 b2 + vpbroadcastd m9, [tlq+13] + vpbroadcastd m10, [tlq+12] + psrld m11, m8, 4 + vpblendd m6, m9, 0x20 ; top + sub tlq, 6 + sub tlq, hq +.w16_loop: + vpbroadcastd xm9, [tlq+hq] + palignr m9, m0, 12 + vpblendd m0, m9, m7, 0xe2 ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm13, xm7 + call .main ; e0 f0 c1 d1 c1 d1 e0 f0 + vpblendd m9, m12, m10, 0xf0 + vpblendd m12, m6, 0xc0 + pshufd m9, m9, q3333 + vpblendd m9, m6, 0xee + vpblendd m10, m9, m7, 0x0c ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_YMM 6, 10, 9, 14 ; c2 d2 a3 b3 a3 b3 c2 d2 + vpblendd m12, m6, 0x30 ; a0 b0 a1 b1 a3 b3 a2 b2 + vpermd m9, m11, m12 ; a0 a1 a2 a3 b0 b1 b2 b3 + vpblendd xm12, xm13, xm7, 0x0c ; c0 d0 c1 d1 + mova [dstq+strideq*0], xm9 + vextracti128 [dstq+strideq*1], m9, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + vpblendd xm7, xm6, xm10, 0x04 ; _ _ _ 5 _ _ _ 6 0 _ _ _ 1 2 3 4 + pshufd xm7, xm7, q1032 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_XMM 0, 7, 9, [base+filter_shuf1+16] + vpblendd xm6, xm0, 0x0c ; c2 d2 c3 d3 + shufps xm0, xm12, xm6, q2020 ; c0 c1 c2 c3 + shufps xm6, xm12, xm6, q3131 ; d0 d1 d2 d3 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm6 + ret +ALIGN function_align +.w32: + sub rsp, stack_size_padded + sub hd, 2 + lea r3, [dstq+16] + lea r5d, [hq-2] + call .w16_main + add tlq, r5 + mov dstq, r3 + lea r3, [strideq-4] + lea r4, [r3+strideq*2] + movq xm0, [tlq+21] + pinsrd xm0, [dstq-4], 2 + pinsrd xm0, [dstq+r3*1], 3 + FILTER_XMM 12, 0, 7, 14 ; a0 b0 a0 b0 + movq xm7, [dstq+r3*2] + pinsrd xm7, [dstq+r4], 2 + palignr xm7, xm0, 12 ; 0 _ _ _ _ _ _ _ _ _ _ 5 _ _ _ 6 + vpbroadcastd m0, [tlq+28] + vpbroadcastd m9, [tlq+29] + vbroadcasti128 m8, [base+filter_shuf1+16] + vpblendd m0, m9, 0x20 + vpblendd m0, m7, 0x0f + vpbroadcastq m7, xm12 + vpblendd m0, m7, 0xc2 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + call .main ; c0 d0 a1 b1 a1 b1 c0 d0 + add r3, 2 + lea r4, [r4+strideq*2] + movlps xm9, xm7, [tlq+29] ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + vpblendd xm12, xm7, 0x0c ; a0 b0 a1 b1 + FILTER_XMM 6, 9, 10, 14 + vpbroadcastq m6, xm6 ; a2 b2 __ __ __ __ a2 b2 + vpbroadcastd m9, [tlq+37] + vpbroadcastd m10, [tlq+36] + vpblendd m6, m9, 0x20 ; top +.w32_loop: + movq xm9, [dstq+r3*4] + pinsrd xm9, [dstq+r4], 2 +.w32_loop_last: + palignr m9, m0, 12 + vpblendd m0, m9, m7, 0xe2 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm13, xm7 ; c0 d0 + call .main ; e0 f0 c1 d1 c1 d1 e0 f0 + vpblendd m9, m12, m10, 0xf0 + vpblendd m12, m6, 0xc0 + pshufd m9, m9, q3333 + vpblendd m9, m6, 0xee + vpblendd m10, m9, m7, 0x0c ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_YMM 6, 10, 9, 14 ; c2 d2 a3 b3 a3 b3 c2 d2 + vpblendd m12, m6, 0x30 ; a0 b0 a1 b1 a3 b3 a2 b2 + vpermd m9, m11, m12 ; a0 a1 a2 a3 b0 b1 b2 b3 + vpblendd xm12, xm13, xm7, 0x0c ; c0 d0 c1 d1 + mova [dstq+strideq*0], xm9 + vextracti128 [dstq+strideq*1], m9, 1 + lea dstq, [dstq+strideq*2] + sub r5d, 2 + jg .w32_loop + jz .w32_loop_last + vpblendd xm7, xm6, xm10, 0x04 ; _ _ _ 5 _ _ _ 6 0 _ _ _ 1 2 3 4 + pshufd xm7, xm7, q1032 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_XMM 0, 7, 9, [base+filter_shuf1+16] + vpblendd xm6, xm0, 0x0c ; c2 d2 c3 d3 + shufps xm0, xm12, xm6, q2020 ; c0 c1 c2 c3 + shufps xm6, xm12, xm6, q3131 ; d0 d1 d2 d3 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm6 + RET +ALIGN function_align +.main: + FILTER_YMM 7, 0, 9, 8 + ret + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +cglobal ipred_cfl_top_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + lea t0, [ipred_cfl_left_avx2_table] + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + shrx r6d, r6d, wd + movd xm3, r6d + movsxd r6, [t0+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_avx2_table-ipred_cfl_left_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +cglobal ipred_cfl_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov t0d, 0x8000 + shrx t0d, t0d, r6d + movd xm3, t0d + lea t0, [ipred_cfl_left_avx2_table] + movsxd r6, [t0+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_avx2_table-ipred_cfl_left_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddw xm0, xm1 +.h4: + pmaddwd xm0, xm2 + pmulhrsw xm0, xm3 + vpbroadcastw m0, xm0 + jmp wq + +cglobal ipred_cfl_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd xm4, t0d + tzcnt t0d, t0d + movd xm5, t0d + lea t0, [ipred_cfl_avx2_table] + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + pcmpeqd m3, m3 + psrlw xm4, 1 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movd xm0, [tlq-4] + pmaddubsw xm0, xm3 + jmp wq +.w4: + movd xm1, [tlq+1] + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm1 + pmaddwd xm0, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddw xm0, xm1 + shrx r6d, r6d, r2d + psrlq xm1, xm0, 32 + paddw xm0, xm1 + movd xm1, r6d + psrlw xm0, 2 + pmulhuw xm0, xm1 +.w4_end: + vpbroadcastw m0, xm0 +.s4: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + IPRED_CFL 4 + packuswb m4, m4 + vextracti128 xm5, m4, 1 + movd [dstq+strideq*0], xm4 + pextrd [dstq+strideq*1], xm4, 1 + movd [dstq+strideq*2], xm5 + pextrd [dstq+r6 ], xm5, 1 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + movq xm0, [tlq-8] + pmaddubsw xm0, xm3 + jmp wq +.w8: + movq xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + punpckhqdq xm2, xm0, xm0 + paddw xm0, xm2 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w8_end: + vpbroadcastw m0, xm0 +.s8: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*1], xm5 + movhps [dstq+strideq*2], xm4 + movhps [dstq+r6 ], xm5 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova xm0, [tlq-16] + pmaddubsw xm0, xm3 + jmp wq +.w16: + movu xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vpermq m4, m4, q3120 + mova [dstq+strideq*0], xm4 + vextracti128 [dstq+strideq*1], m4, 1 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w32_end: + vpbroadcastw m0, xm0 +.s32: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vpermq m4, m4, q3120 + mova [dstq], m4 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + lea t0, [ipred_cfl_splat_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [t0+wq*4] + vpbroadcastd m0, [t0-ipred_cfl_splat_avx2_table+pw_128] + add wq, t0 + movifnidn acq, acmp + jmp wq + +cglobal ipred_cfl_ac_420_8bpc, 4, 9, 5, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + mov ac_bakq, acq + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + vpbroadcastd m2, [pb_2] + pxor m4, m4 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq xm0, [yq] + movq xm1, [yq+strideq] + movhps xm0, [yq+strideq*2] + movhps xm1, [yq+stride3q] + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + paddw xm0, xm1 + mova [acq], xm0 + paddw xm4, xm0 + lea yq, [yq+strideq*4] + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg + vpermq m0, m0, q1111 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova xm0, [yq] + mova xm1, [yq+strideq] + vinserti128 m0, [yq+strideq*2], 1 + vinserti128 m1, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg + jmp .w8_hpad +.w8_wpad: + vbroadcasti128 m3, [cfl_ac_w8_pad1_shuffle] +.w8_wpad_loop: + movq xm0, [yq] + movq xm1, [yq+strideq] + vinserti128 m0, [yq+strideq*2], 1 + vinserti128 m1, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufb m0, m3 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w8_hpad: + vpermq m0, m0, q3232 +.w8_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad_loop + jmp .calc_avg + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad_loop +.w16_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_420_avx2_table] + shl wpadd, 2 + mova m3, [iptrq+cfl_ac_w16_pad_shuffle- \ + ipred_cfl_ac_420_avx2_table+wpadq*8-32] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w16_pad3: + vpbroadcastq m0, [yq] + vpbroadcastq m1, [yq+strideq] + jmp .w16_wpad_end +.w16_pad2: + vbroadcasti128 m0, [yq] + vbroadcasti128 m1, [yq+strideq] + jmp .w16_wpad_end +.w16_pad1: + mova m0, [yq] + mova m1, [yq+strideq] + ; fall-through +.w16_wpad_end: + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufb m0, m3 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jz .w16_wpad_done + jmp iptrq +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w16_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + dec hpadd + jg .w16_hpad_loop + ; fall-through + +.calc_avg: + vpbroadcastd m2, [pw_1] + pmaddwd m0, m4, m2 + vextracti128 xm1, m0, 1 + tzcnt r1d, szd + paddd xm0, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal ipred_cfl_ac_422_8bpc, 4, 9, 6, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + mov ac_bakq, acq + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + vpbroadcastd m2, [pb_4] + pxor m4, m4 + pxor m5, m5 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq xm1, [yq] + movhps xm1, [yq+strideq] + movq xm0, [yq+strideq*2] + movhps xm0, [yq+stride3q] + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + mova [acq], xm1 + mova [acq+16], xm0 + paddw xm4, xm0 + paddw xm5, xm1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg + vpermq m0, m0, q1111 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova xm1, [yq] + vinserti128 m1, [yq+strideq], 1 + mova xm0, [yq+strideq*2] + vinserti128 m0, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg + jmp .w8_hpad +.w8_wpad: + vbroadcasti128 m3, [cfl_ac_w8_pad1_shuffle] +.w8_wpad_loop: + movq xm1, [yq] + vinserti128 m1, [yq+strideq], 1 + movq xm0, [yq+strideq*2] + vinserti128 m0, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pshufb m0, m3 + pshufb m1, m3 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w8_hpad: + vpermq m0, m0, q3232 +.w8_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad_loop + jmp .calc_avg + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m1, [yq] + mova m0, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad_loop +.w16_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_422_avx2_table] + shl wpadd, 2 + mova m3, [iptrq+cfl_ac_w16_pad_shuffle- \ + ipred_cfl_ac_422_avx2_table+wpadq*8-32] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w16_pad3: + vpbroadcastq m1, [yq] + vpbroadcastq m0, [yq+strideq] + jmp .w16_wpad_end +.w16_pad2: + vbroadcasti128 m1, [yq] + vbroadcasti128 m0, [yq+strideq] + jmp .w16_wpad_end +.w16_pad1: + mova m1, [yq] + mova m0, [yq+strideq] + ; fall-through +.w16_wpad_end: + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pshufb m0, m3 + pshufb m1, m3 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jz .w16_wpad_done + jmp iptrq +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w16_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + ; fall-through + +.calc_avg: + vpbroadcastd m2, [pw_1] + pmaddwd m5, m5, m2 + pmaddwd m0, m4, m2 + paddd m0, m5 + vextracti128 xm1, m0, 1 + tzcnt r1d, szd + paddd xm0, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal ipred_cfl_ac_444_8bpc, 4, 9, 6, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + vpbroadcastd m5, [pw_1] + tzcnt r8d, wd + lea r5, [ipred_cfl_ac_444_avx2_table] + movsxd r8, [r5+r8*4+12] + add r5, r8 + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak + mov ac_bakq, acq + jmp r5 + +.w4: + lea stride3q, [strideq*3] + pxor xm2, xm2 +.w4_loop: + movd xm1, [yq] + movd xm0, [yq+strideq*2] + pinsrd xm1, [yq+strideq], 1 + pinsrd xm0, [yq+stride3q], 1 + punpcklbw xm1, xm2 + punpcklbw xm0, xm2 + psllw xm1, 3 + psllw xm0, 3 + mova [acq], xm1 + mova [acq+16], xm0 + paddw xm1, xm0 + paddw xm4, xm1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_mul + pshufd xm0, xm0, q3232 + paddw xm1, xm0, xm0 +.w4_hpad_loop: + mova [acq], xm0 + mova [acq+16], xm0 + paddw xm4, xm1 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg_mul + +.w8: + lea stride3q, [strideq*3] + pxor m2, m2 +.w8_loop: + movq xm1, [yq] + movq xm0, [yq+strideq*2] + vinserti128 m1, [yq+strideq], 1 + vinserti128 m0, [yq+stride3q], 1 + punpcklbw m1, m2 + punpcklbw m0, m2 + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + paddw m4, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_mul + vpermq m0, m0, q3232 + paddw m1, m0, m0 +.w8_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddw m4, m1 + add acq, 64 + sub hpadd, 4 + jg .w8_hpad_loop + jmp .calc_avg_mul + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmovzxbw m1, [yq] + pmovzxbw m0, [yq+strideq] + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + pmaddwd m1, m5 + paddd m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad +.w16_wpad: + mova m3, [cfl_ac_444_w16_pad1_shuffle] +.w16_wpad_loop: + vpbroadcastq m1, [yq] + vpbroadcastq m0, [yq+strideq] + pshufb m1, m3 + pshufb m0, m3 + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + pmaddwd m1, m5 + paddd m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w16_hpad: + paddw m1, m0, m0 + pmaddwd m1, m5 +.w16_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddd m4, m1 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + jmp .calc_avg + +.w32: + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + pmovzxbw m1, [yq] + pmovzxbw m0, [yq+16] + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m2, m1, m0 + pmaddwd m2, m5 + paddd m4, m2 + add yq, strideq + add acq, 64 + dec hd + jg .w32_loop + test hpadd, hpadd + jz .calc_avg + jmp .w32_hpad_loop +.w32_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_444_avx2_table] + add wpadd, wpadd + mova m3, [iptrq+cfl_ac_444_w16_pad1_shuffle-ipred_cfl_ac_444_avx2_table] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w32_pad3: + vpbroadcastq m1, [yq] + pshufb m1, m3 + vpermq m0, m1, q3232 + jmp .w32_wpad_end +.w32_pad2: + pmovzxbw m1, [yq] + pshufhw m0, m1, q3333 + vpermq m0, m0, q3333 + jmp .w32_wpad_end +.w32_pad1: + pmovzxbw m1, [yq] + vpbroadcastq m0, [yq+16] + pshufb m0, m3 + ; fall-through +.w32_wpad_end: + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m2, m1, m0 + pmaddwd m2, m5 + paddd m4, m2 + add yq, strideq + add acq, 64 + dec hd + jz .w32_wpad_done + jmp iptrq +.w32_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w32_hpad_loop: + mova [acq], m1 + mova [acq+32], m0 + paddd m4, m2 + add acq, 64 + dec hpadd + jg .w32_hpad_loop + jmp .calc_avg + +.calc_avg_mul: + pmaddwd m4, m5 +.calc_avg: + vextracti128 xm1, m4, 1 + tzcnt r1d, szd + paddd xm0, xm4, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal pal_pred_8bpc, 4, 6, 5, dst, stride, pal, idx, w, h + vbroadcasti128 m4, [palq] + lea r2, [pal_pred_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r2+wq*4] + packuswb m4, m4 + add wq, r2 + lea r2, [strideq*3] + jmp wq +.w4: + pshufb xm0, xm4, [idxq] + add idxq, 16 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + pshufb xm0, xm4, [idxq+16*0] + pshufb xm1, xm4, [idxq+16*1] + add idxq, 16*2 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r2 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + add idxq, 32*2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+r2 ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +ALIGN function_align +.w32: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + pshufb m2, m4, [idxq+32*2] + pshufb m3, m4, [idxq+32*3] + add idxq, 32*4 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r2 ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +ALIGN function_align +.w64: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + pshufb m2, m4, [idxq+32*2] + pshufb m3, m4, [idxq+32*3] + add idxq, 32*4 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64 + RET + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1432 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +; dav1d_filter_intra_taps[], reordered for VNNI: p1 p2 p3 p4, p6 p5 p0 __ +filter_taps: db 10, 0, 0, 0, 2, 10, 0, 0, 1, 1, 10, 0, 1, 1, 2, 10 + db 6, 0, 0, 0, 2, 6, 0, 0, 2, 2, 6, 0, 1, 2, 2, 6 + db 0, 12, -6, 0, 0, 9, -5, 0, 0, 7, -3, 0, 0, 5, -3, 0 + db 12, 2, -4, 0, 9, 2, -3, 0, 7, 2, -3, 0, 5, 3, -3, 0 + db 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16 + db 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16 + db 0, 10,-10, 0, 0, 6, -6, 0, 0, 4, -4, 0, 0, 2, -2, 0 + db 10, 0,-10, 0, 6, 0, -6, 0, 4, 0, -4, 0, 2, 0, -2, 0 + db 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 8 + db 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4 + db 0, 16, -8, 0, 0, 16, -8, 0, 0, 16, -8, 0, 0, 16, -8, 0 + db 16, 0, -4, 0, 16, 0, -4, 0, 16, 0, -4, 0, 16, 0, -4, 0 + db 8, 0, 0, 0, 3, 8, 0, 0, 2, 3, 8, 0, 1, 2, 3, 8 + db 4, 0, 0, 0, 3, 4, 0, 0, 2, 3, 4, 0, 2, 2, 3, 4 + db 0, 10, -2, 0, 0, 6, -1, 0, 0, 4, -1, 0, 0, 2, 0, 0 + db 10, 3, -1, 0, 6, 4, -1, 0, 4, 4, -1, 0, 3, 3, -1, 0 + db 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 14 + db 12, 0, 0, 0, 1, 12, 0, 0, 0, 0, 12, 0, 0, 0, 1, 12 + db 0, 14,-12, 0, 0, 12,-10, 0, 0, 11, -9, 0, 0, 10, -8, 0 + db 14, 0,-10, 0, 12, 0, -9, 0, 11, 1, -8, 0, 9, 1, -7, 0 +filter_perm: db 0, 1, 2, 3, 24, 25, 26, 27, 4, 5, 6, 7, 28, 29, 30, 31 + db 15, 11, 7, 3, 15, 11, 7, 3, 15, 11, 7, 3, 15, 11, 7,131 + db 31, 27, 23, 19, 31, 27, 23, 19, 31, 27, 23, 19, 31, 27, 23,147 + db 47, 43, 39, 35, 47, 43, 39, 35, 47, 43, 39, 35, 47, 43, 39,163 +filter_end: dd 2, 3, 16, 17, -1, -1, 20, 21, 0, 6, 24, 30, 1, 7, 25, 31 +smooth_shuf: db 7, 7, 7, 7, 0, 1, 0, 1, 3, 3, 3, 3, 8, 9, 8, 9 + db 5, 5, 5, 5, 4, 5, 4, 5, 1, 1, 1, 1, 12, 13, 12, 13 + db 6, 6, 6, 6, 2, 3, 2, 3, 2, 2, 2, 2, 10, 11, 10, 11 + db 4, 4, 4, 4, 6, 7, 6, 7, 0, 0, 0, 0, 14, 15, 14, 15 +smooth_endA: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + db 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95 + db 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127 +smooth_endB: db 1, 3, 5, 7, 9, 11, 13, 15, 65, 67, 69, 71, 73, 75, 77, 79 + db 17, 19, 21, 23, 25, 27, 29, 31, 81, 83, 85, 87, 89, 91, 93, 95 + db 33, 35, 37, 39, 41, 43, 45, 47, 97, 99,101,103,105,107,109,111 + db 49, 51, 53, 55, 57, 59, 61, 63,113,115,117,119,121,123,125,127 +ipred_h_shuf: db 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4 + db 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 + +pb_127_m127: times 2 db 127, -127 +pb_128: times 4 db 128 +pw_128: times 2 dw 128 +pw_255: times 2 dw 255 + +%define pb_1 (ipred_h_shuf+24) +%define pb_2 (ipred_h_shuf+20) +%define pb_3 (ipred_h_shuf+16) +%define pd_8 (filter_taps+128) + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_8bpc_avx512icl_table (ipred_dc_8bpc_avx512icl_table + 10*4) + +JMP_TABLE ipred_h_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_dc_8bpc, avx512icl, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left_8bpc, avx512icl, h4, h8, h16, h32, h64 +JMP_TABLE pal_pred_8bpc, avx512icl, w4, w8, w16, w32, w64 + +SECTION .text + +INIT_ZMM avx512icl +cglobal ipred_dc_top_8bpc, 3, 7, 5, dst, stride, tl, w, h + lea r5, [ipred_dc_left_8bpc_avx512icl_table] + movd xm0, wm + tzcnt wd, wm + inc tlq + movifnidn hd, hm + movu ym1, [tlq] + movd xmm3, wd + movsxd r6, [r5+wq*4] + vpbroadcastd ym2, [r5-ipred_dc_left_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + vpdpbusd ym0, ym1, ym2 + add r6, r5 + add r5, ipred_dc_splat_8bpc_avx512icl_table-ipred_dc_left_8bpc_avx512icl_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_left_8bpc_avx512icl_table] + mov hd, hm + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movd xm0, hm + movu ym1, [tlq] + movd xmm3, r6d + movsxd r6, [r5+r6*4] + vpbroadcastd ym2, [r5-ipred_dc_left_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + vpdpbusd ym0, ym1, ym2 + add r6, r5 + add r5, ipred_dc_splat_8bpc_avx512icl_table-ipred_dc_left_8bpc_avx512icl_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu ym1, [tlq+32] ; unaligned when jumping here from dc_top + vpdpbusd ym0, ym1, ym2 +.h32: + vextracti32x4 xm1, ym0, 1 + paddd xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddd xm0, xm1 +.h4: + vpsrlvd xm0, xmm3 + lea stride3q, [strideq*3] + vpbroadcastb m0, xm0 + jmp wq + +cglobal ipred_dc_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm0, r5d + tzcnt r5d, r5d + movd xmm4, r5d + lea r5, [ipred_dc_8bpc_avx512icl_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + vpbroadcastd ym3, [r5-ipred_dc_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd xmm1, [tlq-4] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w4: + movd xmm1, [tlq+1] + vpdpbusd xm0, xmm1, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xmm0, xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xmm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddd xmm1, xm0 + shrx r6d, r6d, r2d + psrlq xmm0, xmm1, 32 + paddd xmm0, xmm1 + movd xmm1, r6d + psrld xmm0, 2 + pmulhuw xmm0, xmm1 +.w4_end: + vpbroadcastb xm0, xmm0 +.s4: + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm0 + movd [dstq+strideq*2], xm0 + movd [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +.h8: + movq xmm1, [tlq-8] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w8: + movq xmm1, [tlq+1] + vextracti32x4 xm2, ym0, 1 + vpdpbusd xm0, xmm1, xm3 + paddd xmm2, xm2, xm0 + punpckhqdq xmm0, xmm2, xmm2 + paddd xmm0, xmm2 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w8_end: + vpbroadcastb xm0, xmm0 +.s8: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +.h16: + mova xmm1, [tlq-16] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w16: + movu xmm1, [tlq+1] + vextracti32x4 xm2, ym0, 1 + vpdpbusd xm0, xmm1, xm3 + paddd xmm2, xm2, xm0 + punpckhqdq xmm0, xmm2, xmm2 + paddd xmm0, xmm2 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w16_end: + vpbroadcastb xm0, xmm0 +.s16: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +.h32: + mova ym1, [tlq-32] + vpdpbusd ym0, ym1, ym3 + jmp wq +.w32: + movu ym1, [tlq+1] + vpdpbusd ym0, ym1, ym3 + vextracti32x4 xm1, ym0, 1 + paddd xmm1, xm1, xm0 + punpckhqdq xmm0, xmm1, xmm1 + paddd xmm0, xmm1 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w32_end: + vpbroadcastb ym0, xmm0 +.s32: + mova [dstq+strideq*0], ym0 + mova [dstq+strideq*1], ym0 + mova [dstq+strideq*2], ym0 + mova [dstq+stride3q ], ym0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +.h64: + mova ym1, [tlq-64] + mova ym2, [tlq-32] + vpdpbusd ym0, ym1, ym3 + vpdpbusd ym0, ym2, ym3 + jmp wq +.w64: + movu ym1, [tlq+ 1] + movu ym2, [tlq+33] + vpdpbusd ym0, ym1, ym3 + vpdpbusd ym0, ym2, ym3 + vextracti32x4 xm1, ym0, 1 + paddd xmm1, xm1, xm0 + punpckhqdq xmm0, xmm1, xmm1 + paddd xmm0, xmm1 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 64 + je .w64_end + mov r6d, 0x33345556 + shrx r6d, r6d, hd + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w64_end: + vpbroadcastb m0, xmm0 +.s64: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s64 + RET + +cglobal ipred_dc_128_8bpc, 2, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_8bpc_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_8bpc_avx512icl_table+pb_128] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_8bpc_avx512icl_table] + tzcnt wd, wm + movu m0, [tlq+1] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_h_8bpc, 3, 7, 8, dst, stride, tl, w, h, stride3 +%define base r6-ipred_h_8bpc_avx512icl_table + lea r6, [ipred_h_8bpc_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea stride3q, [strideq*3] + sub tlq, hq + add wq, r6 + jmp wq +.w4: + mova xmm1, [base+ipred_h_shuf+16] +.w4_loop: + movd xmm0, [tlq+hq-4] + pshufb xmm0, xmm1 + movd [dstq+strideq*0], xmm0 + pextrd [dstq+strideq*1], xmm0, 1 + pextrd [dstq+strideq*2], xmm0, 2 + pextrd [dstq+stride3q ], xmm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +.w8: + movsldup xmm2, [base+ipred_h_shuf+16] + movshdup xmm3, [base+ipred_h_shuf+16] +.w8_loop: + movd xmm1, [tlq+hq-4] + pshufb xmm0, xmm1, xmm2 + pshufb xmm1, xmm3 + movq [dstq+strideq*0], xmm0 + movq [dstq+strideq*1], xmm1 + movhps [dstq+strideq*2], xmm0 + movhps [dstq+stride3q ], xmm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + movsldup m1, [base+smooth_shuf] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + pshufb m0, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpbroadcastd ym3, [base+pb_1] + vpord m2, m3, [base+pb_2] {1to16} +.w32_loop: + vpbroadcastd m1, [tlq+hq-4] + pshufb m0, m1, m2 + pshufb m1, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32_loop + RET +.w64: + vpbroadcastd m4, [base+pb_3] + vpbroadcastd m5, [base+pb_2] + vpbroadcastd m6, [base+pb_1] + pxor m7, m7 +.w64_loop: + vpbroadcastd m3, [tlq+hq-4] + pshufb m0, m3, m4 + pshufb m1, m3, m5 + pshufb m2, m3, m6 + pshufb m3, m7 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64_loop + RET + +%macro PAETH 0 + psubusb m1, m5, m4 + psubusb m0, m4, m5 + por m1, m0 ; tdiff + pavgb m2, m6, m4 + vpcmpub k1, m1, m7, 1 ; tdiff < ldiff + vpblendmb m0{k1}, m4, m6 + vpternlogd m4, m6, m8, 0x28 ; (m4 ^ m6) & m8 + psubusb m3, m5, m2 + psubb m2, m4 + psubusb m2, m5 + por m2, m3 + pminub m1, m7 + paddusb m2, m2 + por m2, m4 ; min(tldiff, 255) + vpcmpub k1, m2, m1, 1 ; tldiff < ldiff && tldiff < tdiff + vmovdqu8 m0{k1}, m5 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 7, 10, dst, stride, tl, w, h, top, stride3 + lea r6, [ipred_paeth_8bpc_avx512icl_table] + tzcnt wd, wm + vpbroadcastb m5, [tlq] ; topleft + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m8, [r6-ipred_paeth_8bpc_avx512icl_table+pb_1] + lea topq, [tlq+1] + sub tlq, hq + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +INIT_YMM avx512icl +.w4: + vpbroadcastd m6, [topq] + mova m9, [ipred_h_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + vpbroadcastq m4, [tlq+hq-8] + pshufb m4, m9 ; left + PAETH + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm0, 3 + sub hd, 8 + jl .w4_ret + vextracti32x4 xm0, m0, 1 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm0, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.w4_ret: + RET +INIT_ZMM avx512icl +.w8: + vpbroadcastq m6, [topq] + movsldup m9, [smooth_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + vpbroadcastq m4, [tlq+hq-8] + pshufb m4, m9 + PAETH + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm2, ym0, 1 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + sub hd, 8 + jl .w8_ret + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jg .w8_loop +.w8_ret: + RET +.w16: + vbroadcasti32x4 m6, [topq] + movsldup m9, [smooth_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + vpbroadcastd m4, [tlq+hq-4] + pshufb m4, m9 + PAETH + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + vbroadcasti32x8 m6, [topq] + mova ym9, ym8 + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w32_loop: + vpbroadcastd m4, [tlq+hq-2] + pshufb m4, m9 + PAETH + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + movu m6, [topq] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w64_loop: + vpbroadcastb m4, [tlq+hq-1] + PAETH + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_8bpc, 3, 7, 7, dst, stride, tl, w, h, weights, stride3 +%define base r6-ipred_smooth_v_8bpc_avx512icl_table + lea r6, [ipred_smooth_v_8bpc_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m0, [base+pb_127_m127] + vpbroadcastd m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + vpbroadcastb m4, [tlq+hq] ; bottom + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastd m2, [tlq+1] + movshdup m5, [smooth_shuf] + mova ym6, [smooth_endA] + punpcklbw m2, m4 ; top, bottom + pmaddubsw m3, m2, m0 + paddw m1, m2 ; 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; 128 * top + 129 * bottom + 128 +.w4_loop: + vbroadcasti32x4 m0, [weightsq+hq*2] + pshufb m0, m5 + pmaddubsw m0, m2, m0 + paddw m0, m3 + vpermb m0, m6, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + add hq, 8 + jg .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jl .w4_loop +.ret: + RET +.w8: + vpbroadcastq m2, [tlq+1] + movshdup m5, [smooth_shuf] + mova ym6, [smooth_endA] + punpcklbw m2, m4 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 +.w8_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m5 + pmaddubsw m0, m2, m0 + paddw m0, m3 + vpermb m0, m6, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + vbroadcasti32x4 m3, [tlq+1] + movshdup m6, [smooth_shuf] + mova m7, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w16_loop: + vpbroadcastq m1, [weightsq+hq*2] + pshufb m1, m6 + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m7, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + vbroadcasti32x8 m3, [tlq+1] + movshdup m6, [smooth_shuf] + mova m7, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w32_loop: + vpbroadcastd m1, [weightsq+hq*2] + pshufb m1, m6 + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m7, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + movu m3, [tlq+1] + mova m6, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w64_loop: + vpbroadcastw m1, [weightsq+hq*2] + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m6, m1 + mova [dstq], m0 + add dstq, strideq + inc hq + jl .w64_loop + RET + +cglobal ipred_smooth_h_8bpc, 4, 7, 11, dst, stride, tl, w, h, stride3 +%define base r5-ipred_smooth_h_8bpc_avx512icl_table + lea r5, [ipred_smooth_h_8bpc_avx512icl_table] + mov r6d, wd + tzcnt wd, wd + vpbroadcastb m4, [tlq+r6] ; right + mov hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m5, [base+pb_127_m127] + vpbroadcastd m6, [base+pw_128] + sub tlq, hq + add wq, r5 + vpmovb2m k1, m6 + lea stride3q, [strideq*3] + jmp wq +.w4: + movsldup m3, [smooth_shuf] + vpbroadcastq m7, [smooth_weights+4*2] + mova ym8, [smooth_endA] +.w4_loop: + vpbroadcastq m0, [tlq+hq-8] + mova m2, m4 + vpshufb m2{k1}, m0, m3 ; left, right + pmaddubsw m0, m2, m5 + pmaddubsw m1, m2, m7 + paddw m2, m6 + paddw m0, m2 + paddw m0, m1 + vpermb m0, m8, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + sub hd, 8 + jl .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.ret: + RET +.w8: + movsldup m3, [smooth_shuf] + vbroadcasti32x4 m7, [smooth_weights+8*2] + mova ym8, [smooth_endA] +.w8_loop: + vpbroadcastd m0, [tlq+hq-4] + mova m2, m4 + vpshufb m2{k1}, m0, m3 + pmaddubsw m0, m2, m5 + pmaddubsw m1, m2, m7 + paddw m2, m6 + paddw m0, m2 + paddw m0, m1 + vpermb m0, m8, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + movsldup m7, [smooth_shuf] + vbroadcasti32x4 m8, [smooth_weights+16*2] + vbroadcasti32x4 m9, [smooth_weights+16*3] + mova m10, [smooth_endB] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + mova m3, m4 + vpshufb m3{k1}, m0, m7 + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m8 + pmaddubsw m1, m3, m9 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m10, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + mova m10, [smooth_endA] + vpbroadcastd ym7, [pb_1] + vbroadcasti32x8 m8, [smooth_weights+32*2] + vbroadcasti32x8 m9, [smooth_weights+32*3] + vshufi32x4 m10, m10, q3120 +.w32_loop: + vpbroadcastd m0, [tlq+hq-2] + mova m3, m4 + vpshufb m3{k1}, m0, m7 + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m8 + pmaddubsw m1, m3, m9 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m10, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + mova m7, [smooth_weights+64*2] + mova m8, [smooth_weights+64*3] + mova m9, [smooth_endA] +.w64_loop: + mova m3, m4 + vpbroadcastb m3{k1}, [tlq+hq-1] + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m7 + pmaddubsw m1, m3, m8 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m9, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_8bpc, 4, 7, 16, dst, stride, tl, w, h, v_weights, stride3 +%define base r5-ipred_smooth_8bpc_avx512icl_table + lea r5, [ipred_smooth_8bpc_avx512icl_table] + mov r6d, wd + tzcnt wd, wd + mov hd, hm + vpbroadcastb m6, [tlq+r6] ; right + sub tlq, hq + movsxd wq, [r5+wq*4] + vpbroadcastd m7, [base+pb_127_m127] + vpbroadcastb m0, [tlq] ; bottom + vpbroadcastd m1, [base+pw_255] + add wq, r5 + lea v_weightsq, [base+smooth_weights+hq*2] + vpmovb2m k1, m1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastd m8, [tlq+hq+1] + movsldup m4, [smooth_shuf] + movshdup m5, [smooth_shuf] + vpbroadcastq m9, [smooth_weights+4*2] + mova ym11, [smooth_endA] + + punpcklbw m8, m0 ; top, bottom + pmaddubsw m10, m8, m7 + paddw m1, m8 ; 1 * top + 256 * bottom + 255 + paddw m10, m1 ; 128 * top + 129 * bottom + 255 +.w4_loop: + vpbroadcastq m1, [tlq+hq-8] + vbroadcasti32x4 m0, [v_weightsq] + add v_weightsq, 16 + mova m2, m6 + vpshufb m2{k1}, m1, m4 ; left, right + pmaddubsw m1, m2, m7 ; 127 * left - 127 * right + pshufb m0, m5 + pmaddubsw m0, m8, m0 + paddw m1, m2 ; 128 * left + 129 * right + pmaddubsw m2, m9 + paddw m0, m10 + paddw m1, m2 + pavgw m0, m1 + vpermb m0, m11, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + sub hd, 8 + jl .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.ret: + RET +.w8: + vpbroadcastq m8, [tlq+hq+1] + movsldup m4, [smooth_shuf] + movshdup m5, [smooth_shuf] + vbroadcasti32x4 m9, [smooth_weights+8*2] + mova ym11, [smooth_endA] + punpcklbw m8, m0 + pmaddubsw m10, m8, m7 + paddw m1, m8 + paddw m10, m1 +.w8_loop: + vpbroadcastd m1, [tlq+hq-4] + vpbroadcastq m0, [v_weightsq] + add v_weightsq, 8 + mova m2, m6 + vpshufb m2{k1}, m1, m4 + pmaddubsw m1, m2, m7 + pshufb m0, m5 + pmaddubsw m0, m8, m0 + paddw m1, m2 + pmaddubsw m2, m9 + paddw m0, m10 + paddw m1, m2 + pavgw m0, m1 + vpermb m0, m11, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + vbroadcasti32x4 m9, [tlq+hq+1] + movsldup m5, [smooth_shuf] + movshdup m10, [smooth_shuf] + vbroadcasti32x4 m11, [smooth_weights+16*2] + vbroadcasti32x4 m12, [smooth_weights+16*3] + mova m15, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m13, m8, m7 + pmaddubsw m14, m9, m7 + paddw m0, m1, m8 + paddw m1, m9 + paddw m13, m0 + paddw m14, m1 +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastq m1, [v_weightsq] + add v_weightsq, 8 + mova m4, m6 + vpshufb m4{k1}, m0, m5 + pmaddubsw m2, m4, m7 + pshufb m1, m10 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m11 + pmaddubsw m4, m12 + paddw m0, m13 + paddw m1, m14 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m15, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + vbroadcasti32x8 m9, [tlq+hq+1] + movshdup m10, [smooth_shuf] + mova m12, [smooth_weights+32*2] + vpbroadcastd ym5, [pb_1] + mova m15, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m13, m8, m7 + pmaddubsw m14, m9, m7 + vshufi32x4 m11, m12, m12, q2020 + vshufi32x4 m12, m12, q3131 + paddw m0, m1, m8 + paddw m1, m9 + paddw m13, m0 + paddw m14, m1 +.w32_loop: + vpbroadcastd m0, [tlq+hq-2] + vpbroadcastd m1, [v_weightsq] + add v_weightsq, 4 + mova m4, m6 + vpshufb m4{k1}, m0, m5 + pmaddubsw m2, m4, m7 + pshufb m1, m10 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m11 + pmaddubsw m4, m12 + paddw m0, m13 + paddw m1, m14 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m15, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + movu m9, [tlq+hq+1] + mova m11, [smooth_weights+64*2] + mova m2, [smooth_weights+64*3] + mova m14, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m12, m8, m7 + pmaddubsw m13, m9, m7 + vshufi32x4 m10, m11, m2, q2020 + vshufi32x4 m11, m2, q3131 + paddw m0, m1, m8 + paddw m1, m9 + paddw m12, m0 + paddw m13, m1 +.w64_loop: + mova m4, m6 + vpbroadcastb m4{k1}, [tlq+hq-1] + vpbroadcastw m1, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m4, m7 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m10 + pmaddubsw m4, m11 + paddw m0, m12 + paddw m1, m13 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m14, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal pal_pred_8bpc, 4, 7, 5, dst, stride, pal, idx, w, h, stride3 + lea r6, [pal_pred_8bpc_avx512icl_table] + tzcnt wd, wm + vbroadcasti32x4 m4, [palq] + movifnidn hd, hm + movsxd wq, [r6+wq*4] + packuswb m4, m4 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + pshufb xmm0, xm4, [idxq] + add idxq, 16 + movd [dstq+strideq*0], xmm0 + pextrd [dstq+strideq*1], xmm0, 1 + pextrd [dstq+strideq*2], xmm0, 2 + pextrd [dstq+stride3q ], xmm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pshufb xmm0, xm4, [idxq+16*0] + pshufb xmm1, xm4, [idxq+16*1] + add idxq, 16*2 + movq [dstq+strideq*0], xmm0 + movhps [dstq+strideq*1], xmm0 + movq [dstq+strideq*2], xmm1 + movhps [dstq+stride3q ], xmm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pshufb m0, m4, [idxq] + add idxq, 64 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + pshufb m0, m4, [idxq+64*0] + pshufb m1, m4, [idxq+64*1] + add idxq, 64*2 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +.w64: + pshufb m0, m4, [idxq+64*0] + pshufb m1, m4, [idxq+64*1] + pshufb m2, m4, [idxq+64*2] + pshufb m3, m4, [idxq+64*3] + add idxq, 64*4 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64 + RET + +; The ipred_filter code processes 4x2 blocks in the following order +; which increases parallelism compared to doing things row by row. +; Some redundant blocks are calculated for w > 4. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 4 1 2 3 4 9 a b c +; 2 2 3 2 3 4 5 2 3 4 5 a b c d +; 3 3 4 3 4 5 6 3 4 5 6 b c d e +; 4 4 5 4 5 6 7 4 5 6 7 c d e f +; 5 5 6 5 6 7 8 5 6 7 8 d e f g +; 6 6 7 6 7 8 9 6 7 8 9 e f g h +; 7 7 8 7 8 9 a 7 8 9 a f g h i +; ___ 8 ___ 8 9 ___ 8 9 a b ___ 8 9 a b g h i j ___ +; 9 9 a b h i j +; a b i j +; b j + +cglobal ipred_filter_8bpc, 4, 7, 14, dst, stride, tl, w, h, flt +%define base r6-filter_taps + lea r6, [filter_taps] +%ifidn fltd, fltm + movzx fltd, fltb +%else + movzx fltd, byte fltm +%endif + vpbroadcastd xmm2, [tlq+1] ; t0 t0 t0 t0 + movifnidn hd, hm + shl fltd, 6 + vpbroadcastd m6, [base+pd_8] + vpbroadcastd xmm3, [tlq-2] ; l1 l0 tl __ + vbroadcasti32x4 m7, [r6+fltq+16*0] ; p1 p2 p3 p4 + vbroadcasti32x4 m8, [r6+fltq+16*1] + vbroadcasti32x4 m9, [r6+fltq+16*2] ; p6 p5 p0 __ + vbroadcasti32x4 m10, [r6+fltq+16*3] + mova xmm0, xm6 + vpdpbusd xmm0, xmm2, xm7 + mova xmm1, xm6 + vpdpbusd xmm1, xmm2, xm8 + vpdpbusd xmm0, xmm3, xm9 + vpdpbusd xmm1, xmm3, xm10 + packssdw xmm0, xmm1 + cmp wd, 8 + jb .w4 + vpbroadcastd ym2, [tlq+5] + mova m11, [base+filter_perm] + mov r5, 0xffffffffffff000f + psrldq xmm2, 1 ; __ t0 + kmovq k1, r5 ; 0x000f + psraw xm5, xmm0, 4 + packuswb xmm2, xm5 ; __ t0 a0 b0 + pshufd ym2{k1}, ymm2, q3333 ; b0 b0 b0 b0 t1 t1 t1 t1 + je .w8 + kxnorb k3, k3, k3 ; 0x00ff + vpbroadcastd xm3, [tlq-4] + kandnq k2, k3, k1 ; 0xffffffffffff0000 + vpermb ym3{k2}, ym11, ymm2 ; l3 l2 l1 __ b3 a3 t3 __ + mova ym0, ym6 + vpdpbusd ym0, ym2, ym7 + mova ym1, ym6 + vpdpbusd ym1, ym2, ym8 + pshufb ym5{k2}, ym2, ym11 ; a0 b0 __ t0 + vpbroadcastd m2, [tlq+9] + vpdpbusd ym0, ym3, ym9 + vpdpbusd ym1, ym3, ym10 + vpbroadcastd xm3, [tlq-6] ; l5 l4 l3 __ + kunpckbw k4, k1, k3 ; 0x0fff + packssdw ym0, ym1 + psraw ym0, 4 ; a0 d0 a1 b1 + packuswb ym5, ym0 ; a0 b0 c0 d0 __ t1 a1 b1 + pshufd m2{k3}, m5, q3333 ; d0 d0 d0 d0 b1 b1 b1 b1 t2 t2 t2 t2 + vpermb m3{k2}, m11, m5 ; l5 l4 l3 __ d3 c3 b3 __ b7 a7 t7 __ + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + psrldq m0, m2, 1 ; __ d0 __ b0 __ t0 + vpbroadcastd m2, [tlq+13] + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + mova m12, [base+filter_end] + lea r5d, [hq-6] + mov r6, dstq + cmovp hd, r5d ; w == 16 ? h : h - 6 + packssdw m4, m1 + psraw m4, 4 ; e0 f0 c1 d1 a2 b2 + packuswb m0, m4 ; __ d0 e0 f0 __ b1 c1 d1 __ t2 a2 b2 + pshufd m2{k4}, m0, q3333 ; f0 f0 f0 f0 d1 d1 d1 d1 b2 b2 b2 b2 t3 t3 t3 t3 +.w16_loop: + vpbroadcastd xm3, [tlq-8] + vpermb m3{k2}, m11, m0 ; l7 l6 l5 __ f3 e3 d3 __ d7 c7 b7 __ bb ab tb __ + mova m1, m6 + vpdpbusd m1, m2, m7 + mova m0, m6 + vpdpbusd m0, m2, m8 + sub tlq, 2 + vpdpbusd m1, m3, m9 + vpdpbusd m0, m3, m10 + packssdw m1, m0 + mova m0, m4 + psraw m4, m1, 4 ; g0 h0 e1 f1 c2 d2 a3 b3 + packuswb m0, m4 ; e0 f0 g0 h0 c1 d1 e1 f1 a2 b2 c2 d2 __ __ a3 b3 + pshufd m2, m0, q3333 ; h0 h0 h0 h0 f1 f1 f1 f1 d2 d2 d2 d2 b3 b3 b3 b3 + vpermt2d m5, m12, m0 ; c0 d0 e0 f0 __ __ c1 d1 a0 a1 a2 a3 b0 b1 b2 b3 + vextracti32x4 [dstq+strideq*0], m5, 2 + vextracti32x4 [dstq+strideq*1], m5, 3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + cmp wd, 16 + je .ret + mova xm13, [filter_perm+16] + mova xmm3, [r6+strideq*0] + punpckhdq xmm3, [r6+strideq*1] + vpbroadcastd m2{k1}, [tlq+r5+17] ; t4 t4 t4 t4 f1 f1 f1 f1 d2 d2 d2 d2 b3 b3 b3 b3 + pinsrb xm3, xmm3, [tlq+r5+16], 7 + pshufb xm3, xm13 + vpermb m3{k2}, m11, m0 ; bf af tf __ h3 g3 f3 __ f7 e7 d7 __ db cb bb __ + mova m0, m6 + vpdpbusd m0, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kunpckbw k5, k3, k1 ; 0xff0f + lea r3, [strideq*3] + vpdpbusd m0, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m0, m1 + psraw m0, 4 ; a4 b4 g1 h1 e2 f2 c3 d3 + packuswb m4, m0 ; g0 h0 a4 b4 e1 f1 g1 h1 c2 d2 e2 f2 __ __ c3 d3 + vpblendmb m1{k3}, m4, m2 ; __ t4 a4 b4 e1 f1 g1 h1 c2 d2 e2 f2 __ __ c3 d3 + vpbroadcastd ym2, [tlq+r5+21] + pshufd m2{k5}, m4, q3333 ; b4 b4 b4 b4 t5 t5 t5 t5 f2 f2 f2 f2 d3 d3 d3 d3 + vpermt2d m5, m12, m4 ; e0 f0 g0 h0 __ __ e1 f1 c0 c1 c2 c3 d0 d1 d2 d3 + vextracti32x4 [dstq+strideq*0], m5, 2 + vextracti32x4 [dstq+strideq*1], m5, 3 + punpckhqdq xmm3, [r6+r3] + pinsrb xmm3, [r6+strideq*2+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; df cf bf __ bj aj tj __ h7 g7 f7 __ fb eb db __ + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kxnord k3, k3, k4 ; 0xfffff0ff + lea r4, [strideq*5] + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m4, m1 + psraw m4, 4 ; c4 d4 a5 b5 g2 h2 e3 f3 + packuswb m0, m4 ; a4 b4 c4 d4 g1 h1 a5 b5 e2 f2 g2 h2 __ __ e3 f3 + vpblendmw m1{k3}, m2, m0 ; a4 b4 c4 d4 __ t5 a5 b5 e2 f2 g2 h2 __ __ e3 f3 + vpbroadcastd m2, [tlq+r5+25] + pshufd m2{k3}, m0, q3333 ; d4 d4 d4 d4 b5 b5 b5 b5 t6 t6 t6 t6 f3 f3 f3 f3 + vpermt2d m5, m12, m0 ; g0 h0 a4 b4 __ __ g1 h1 e0 e1 e2 e3 f0 f1 f2 f3 + vextracti32x4 [dstq+strideq*2], m5, 2 + vextracti32x4 [dstq+r3 ], m5, 3 + punpckhqdq xmm3, [r6+r4] + pinsrb xmm3, [r6+strideq*4+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; ff ef df __ dj cj bj __ bn an tn __ hb hb fb __ + mova m0, m6 + vpdpbusd m0, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kunpckwd k1, k1, k2 ; 0x000f0000 + vpdpbusd m0, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m0, m1 + psraw m0, 4 ; e4 f4 c5 d5 a6 b6 g3 h3 + packuswb m4, m0 ; c4 d4 e4 f4 a5 b5 c5 d5 g2 h2 a6 b6 __ __ g3 h3 + vpblendmw m1{k1}, m4, m2 ; c4 d4 e4 f4 a5 b5 c5 d5 __ t6 a6 b6 __ __ g3 h3 + vpbroadcastd m2, [tlq+r5+29] + pshufd m2{k4}, m4, q3333 ; f4 f4 f4 f4 d5 d5 d5 d5 b6 b6 b6 b6 t7 t7 t7 t7 + vpermt2d m5, m12, m4 ; a4 b4 c4 d4 __ __ a5 b5 g0 g1 g2 g3 h0 h1 h2 h3 + vextracti32x4 [dstq+strideq*4], m5, 2 + vextracti32x4 [dstq+r4 ], m5, 3 + lea r0, [strideq+r3*2] +.w32_loop: + punpckhqdq xmm3, [r6+r0] + pinsrb xmm3, [r6+r3*2+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; hf gf ff __ fj ej dj __ dn cn bn __ br ar tr __ +.w32_loop_tail: + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m4, m1 + mova m1, m0 + psraw m0, m4, 4 ; g4 h4 e5 f5 c6 d6 a7 b7 + packuswb m1, m0 ; e4 f4 g4 h4 c5 d5 e5 f5 a6 b6 c6 d6 __ __ a7 b7 + pshufd m2, m1, q3333 ; h4 h4 h4 h4 f5 f5 f5 f5 d6 d6 d6 d6 b7 b7 b7 b7 + vpermt2d m5, m12, m1 ; c4 d4 e4 f4 __ __ c5 d5 a4 a5 a6 a7 b4 b5 b6 b7 + vextracti32x4 [r6+strideq*0+16], m5, 2 + vextracti32x4 [r6+strideq*1+16], m5, 3 + lea r6, [r6+strideq*2] + sub r5d, 2 + jg .w32_loop + vpermb m3, m11, m1 + cmp r5d, -6 + jg .w32_loop_tail +.ret: + RET +.w8: + vpermb ym3, ym11, ymm2 +.w8_loop: + vpbroadcastd ym3{k1}, [tlq-4] ; l3 l2 l1 __ b3 a3 t3 __ + mova ym0, ym6 + vpdpbusd ym0, ym2, ym7 + mova ym1, ym6 + vpdpbusd ym1, ym2, ym8 + sub tlq, 2 + vpdpbusd ym0, ym3, ym9 + vpdpbusd ym1, ym3, ym10 + mova ym3, ym5 + packssdw ym0, ym1 + psraw ym5, ym0, 4 ; c0 d0 a1 b1 + packuswb ym3, ym5 ; a0 b0 c0 d0 __ __ a1 b1 + pshufd ym2, ym3, q3333 ; d0 d0 d0 d0 b1 b1 b1 b1 + vpermb ym3, ym11, ym3 ; a0 a1 b0 b1 + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +.w4_loop: + vpbroadcastd xmm3, [tlq-4] ; l3 l2 l1 __ + mova xmm0, xm6 + vpdpbusd xmm0, xmm2, xm7 + mova xmm1, xm6 + vpdpbusd xmm1, xmm2, xm8 + sub tlq, 2 + vpdpbusd xmm0, xmm3, xm9 + vpdpbusd xmm1, xmm3, xm10 + packssdw xmm0, xmm1 +.w4: + psraw xmm0, 4 ; a0 b0 + packuswb xmm0, xmm0 + movd [dstq+strideq*0], xmm0 + pshufd xmm2, xmm0, q1111 ; b0 b0 b0 b0 + movd [dstq+strideq*1], xmm2 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/ipred_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5398 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA 16 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +; sm_weights[], but modified to precalculate x and 256-x with offsets to +; enable efficient use of pmaddubsw (which requires signed values) +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +ipred_v_shuf: db 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7 +ipred_h_shuf: db 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 +ipred_paeth_shuf: db 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 +z_upsample1: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z_upsample2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8 +z_transpose4: db 8, 12, 0, 4, 9, 13, 1, 5, 10, 14, 2, 6, 11, 15, 3, 7 +z3_shuf: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z3_shuf_h4: db 4, 3, 3, 2, 2, 1, 1, 0, 12, 11, 11, 10, 10, 9, 9, 8 +filter_shuf1: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 2, 7, 2, 1, -1, 1, -1 +filter_shuf2: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 11, 7, 11, 15, -1, 15, -1 +z_filter_wh4: db 7, 7, 19, 7, +z_filter_wh8: db 19, 19, 11, 19, 11, 15, 15, 15, 23, 23, 23, 23, 39, 39, 39, 39 +pd_32768: dd 32768 +z3_filter_k_tail: db 64, 0, 64, 0, 64, 0, 56, 8 +z1_shuf_w4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +pb_0to15: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +pb_15to0: db 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 +z3_base_inc: dw 7*64, 6*64, 5*64, 4*64, 3*64, 2*64, 1*64, 0*64 +z_filter_wh16: db 19, 19, 19, 23, 23, 23, 31, 31, 31, 47, 47, 47, 79, 79, 79, -1 +z_filter_t_w48: db 55,127, 7,127, 15, 31, 39, 31,127, 39,127, 39, 7, 15, 31, 15 + db 39, 63, 3, 63, 3, 3, 19, 3, 47, 19, 47, 19, 3, 3, 3, 3 +z_filter_t_w16: db 15, 31, 7, 15, 31, 7, 3, 31, 3, 3, 3, 3, 3, 3, 0, 0 +z_filter_s: db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 + db 7, 8, 8, 9, 9, 10, 10, 11 +z_filter_k_tail: db 0, 64, 0, 64, 8, 56, 0, 64 +z2_h_shuf: db 7, 6, 15, 14, 6, 5, 14, 13, 5, 4, 13, 12, 4, 3, 12, 11 +z2_upsample: db 7, 6, 15, 14, 5, 4, 13, 12, 3, 2, 11, 10, 1, 0, 9, 8 +z2_dy_offset: dw 88*64, 88*64, 87*64, 87*64 +pw_m1to4: dw -1, -2, -3, -4 +z_filter_k: times 4 db 0, 16 + times 4 db 0, 20 + times 4 db 8, 16 + times 4 db 32, 16 + times 4 db 24, 20 + times 4 db 16, 16 + times 4 db 0, 0 + times 4 db 0, 0 +pw_8: times 8 db 8, 0 +pb_3: times 16 db 3 +pb_16: times 16 db 16 +pw_62: times 8 dw 62 +pw_64: times 8 dw 64 +pw_256: times 8 dw 256 +pw_512: times 8 dw 512 +pw_m256: times 8 dw -256 +pb_2: times 8 db 2 +pb_4: times 8 db 4 +pb_8: times 8 db 8 +pb_128: times 8 db 128 +pb_m16: times 8 db -16 +pw_128: times 4 dw 128 +pw_255: times 4 dw 255 +pb_36_m4: times 4 db 36, -4 +pb_127_m127: times 4 db 127, -127 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_ssse3_table (ipred_dc_ssse3_table + 10*4) +%define ipred_cfl_splat_ssse3_table (ipred_cfl_ssse3_table + 8*4) + +JMP_TABLE ipred_h, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_dc, ssse3, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_smooth, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE pal_pred, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_cfl, ssse3, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left, ssse3, h4, h8, h16, h32 +JMP_TABLE ipred_filter, ssse3, w4, w8, w16, w32 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_h_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro IPRED_SET 3 ; width, stride, stride size pshuflw_imm8 + pshuflw m1, m0, %3 ; extend 8 byte for 2 pos + punpcklqdq m1, m1 + mova [dstq + %2], m1 +%if %1 > 16 + mova [dstq + 16 + %2], m1 +%endif +%if %1 > 32 + mova [dstq + 32 + %2], m1 + mova [dstq + 48 + %2], m1 +%endif +%endmacro + +%macro IPRED_H 1 ; width + sub tlq, 4 + movd m0, [tlq] ; get 4 bytes of topleft data + punpcklbw m0, m0 ; extend 2 byte +%if %1 == 4 + pshuflw m1, m0, q2233 + movd [dstq+strideq*0], m1 + psrlq m1, 32 + movd [dstq+strideq*1], m1 + pshuflw m0, m0, q0011 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+stride3q ], m0 + +%elif %1 == 8 + punpcklwd m0, m0 + punpckhdq m1, m0, m0 + punpckldq m0, m0 + movq [dstq+strideq*1], m1 + movhps [dstq+strideq*0], m1 + movq [dstq+stride3q ], m0 + movhps [dstq+strideq*2], m0 +%else + IPRED_SET %1, 0, q3333 + IPRED_SET %1, strideq, q2222 + IPRED_SET %1, strideq*2, q1111 + IPRED_SET %1, stride3q, q0000 +%endif + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +%endmacro + +INIT_XMM ssse3 +cglobal ipred_h_8bpc, 3, 6, 2, dst, stride, tl, w, h, stride3 + LEA r5, ipred_h_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + IPRED_H 4 +.w8: + IPRED_H 8 +.w16: + IPRED_H 16 +.w32: + IPRED_H 32 +.w64: + IPRED_H 64 + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_v_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_v_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_ssse3_table + tzcnt wd, wm + movu m0, [tlq+ 1] + movu m1, [tlq+17] + movu m2, [tlq+33] + movu m3, [tlq+49] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd m4, r5d + tzcnt r5d, r5d + movd m5, r5d + LEA r5, ipred_dc_ssse3_table + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+20] + pcmpeqd m3, m3 + psrlw m4, 1 ; dc = (width + height) >> 1; + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd m0, [tlq-4] + pmaddubsw m0, m3 + jmp wq +.w4: + movd m1, [tlq+1] + pmaddubsw m1, m3 + psubw m0, m4 + paddw m0, m1 + pmaddwd m0, m3 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 ; dc >>= ctz(width + height); + jmp .w4_end +.w4_mul: + punpckhqdq m1, m0, m0 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrlw m0, 2 + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8 + cmovz r6d, r2d + movd m5, r6d + pmulhuw m0, m5 +.w4_end: + pxor m1, m1 + pshufb m0, m1 +.s4: + movd [dstq+strideq*0], m0 + movd [dstq+strideq*1], m0 + movd [dstq+strideq*2], m0 + movd [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + movq m0, [tlq-8] + pmaddubsw m0, m3 + jmp wq +.w8: + movq m1, [tlq+1] + pmaddubsw m1, m3 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w8_end: + pxor m1, m1 + pshufb m0, m1 +.s8: + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movq [dstq+strideq*2], m0 + movq [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova m0, [tlq-16] + pmaddubsw m0, m3 + jmp wq +.w16: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w16_end: + pxor m1, m1 + pshufb m0, m1 +.s16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + mova m2, [tlq-16] + pmaddubsw m2, m3 + paddw m0, m2 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + movu m2, [tlq+17] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 64|16 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w32_end: + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 +.s32: + mova [dstq], m0 + mova [dstq+16], m1 + mova [dstq+strideq], m0 + mova [dstq+strideq+16], m1 + mova [dstq+strideq*2], m0 + mova [dstq+strideq*2+16], m1 + mova [dstq+stride3q], m0 + mova [dstq+stride3q+16], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-64] + mova m1, [tlq-48] + pmaddubsw m0, m3 + pmaddubsw m1, m3 + paddw m0, m1 + mova m1, [tlq-32] + pmaddubsw m1, m3 + paddw m0, m1 + mova m1, [tlq-16] + pmaddubsw m1, m3 + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 1] + movu m2, [tlq+17] + pmaddubsw m1, m3 + pmaddubsw m2, m3 + paddw m1, m2 + movu m2, [tlq+33] + pmaddubsw m2, m3 + paddw m1, m2 + movu m2, [tlq+49] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 64 + je .w64_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w64_end: + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s64: + mova [dstq], m0 + mova [dstq+16], m1 + mova [dstq+32], m2 + mova [dstq+48], m3 + mova [dstq+strideq], m0 + mova [dstq+strideq+16], m1 + mova [dstq+strideq+32], m2 + mova [dstq+strideq+48], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s64 + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_left_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_left_ssse3_table + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + movd m3, [r5-ipred_dc_left_ssse3_table+pd_32768] + movd m2, r6d + psrld m3, m2 + movsxd r6, [r5+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_ssse3_table-ipred_dc_left_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m1, [tlq+48] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 + movu m1, [tlq+32] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h32: + movu m1, [tlq+16] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h16: + pshufd m1, m0, q3232 ; psrlq m1, m0, 16 + paddw m0, m1 +.h8: + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 +.h4: + pmaddwd m0, m2 + pmulhrsw m0, m3 + lea stride3q, [strideq*3] + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 + mova m2, m0 + mova m3, m0 + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_128_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_128_8bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m0, [r5-ipred_dc_splat_ssse3_table+pb_128] + mova m1, m0 + mova m2, m0 + mova m3, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_top_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_top_8bpc, 3, 7, 6, dst, stride, tl, w, h + LEA r5, ipred_dc_left_ssse3_table + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + movd m3, [r5-ipred_dc_left_ssse3_table+pd_32768] + movd m2, wd + psrld m3, m2 + movsxd r6, [r5+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_ssse3_table-ipred_dc_left_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_v_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro SMOOTH 6 ; src[1-2], mul[1-2], add[1-2] + ; w * a = (w - 128) * a + 128 * a + ; (256 - w) * b = (127 - w) * b + 129 * b + ; => w * a + (256 - w) * b = [(w - 128) * a + (127 - w) * b] + [128 * a + 129 * b] + pmaddubsw m6, m%3, m%1 + pmaddubsw m0, m%4, m%2 ; (w - 128) * a + (127 - w) * b + paddw m6, m%5 + paddw m0, m%6 ; [(w - 128) * a + (127 - w) * b] + [128 * a + 129 * b + 128] + psrlw m6, 8 + psrlw m0, 8 + packuswb m6, m0 +%endmacro + +cglobal ipred_smooth_v_8bpc, 3, 7, 7, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_ssse3_table + LEA r6, ipred_smooth_v_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + movd m5, [tlq+hq] + pxor m2, m2 + pshufb m5, m2 + add wq, r6 + jmp wq +.w4: + movd m2, [tlq+1] + punpckldq m2, m2 + punpcklbw m2, m5 ; top, bottom + lea r3, [strideq*3] + mova m4, [base+ipred_v_shuf] + mova m5, m4 + punpckldq m4, m4 + punpckhdq m5, m5 + pmaddubsw m3, m2, m0 ; m3: 127 * top - 127 * bottom + paddw m1, m2 ; m1: 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; m3: 128 * top + 129 * bottom + 128 +.w4_loop: + movu m1, [weightsq+hq*2] + pshufb m0, m1, m4 ;m2, m3, m4 and m5 should be stable in loop + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + movd [dstq+strideq*0], m6 + pshuflw m1, m6, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m6, m6 + movd [dstq+strideq*2], m6 + psrlq m6, 32 + movd [dstq+r3 ], m6 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop + RET +ALIGN function_align +.w8: + movq m2, [tlq+1] + punpcklbw m2, m5 + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + pshufd m4, m5, q0000 + pshufd m5, m5, q1111 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 ; m3 is output for loop +.w8_loop: + movq m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + movq [dstq+strideq*0], m6 + movhps [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w8_loop + RET +ALIGN function_align +.w16: + movu m3, [tlq+1] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 ; m4 and m5 is output for loop +.w16_loop: + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add dstq, strideq + add hq, 1 + jl .w16_loop + RET +ALIGN function_align +.w32: +%if WIN64 + movaps [rsp+24], xmm7 + %define xmm_regs_used 8 +%endif + mova m7, m5 +.w32_loop_init: + mov r3d, 2 +.w32_loop: + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + movu m3, [tlq+1] + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add tlq, 16 + add dstq, 16 + dec r3d + jg .w32_loop + lea dstq, [dstq-32+strideq] + sub tlq, 32 + add hq, 1 + jl .w32_loop_init + RET +ALIGN function_align +.w64: +%if WIN64 + movaps [rsp+24], xmm7 + %define xmm_regs_used 8 +%endif + mova m7, m5 +.w64_loop_init: + mov r3d, 4 +.w64_loop: + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + movu m3, [tlq+1] + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add tlq, 16 + add dstq, 16 + dec r3d + jg .w64_loop + lea dstq, [dstq-64+strideq] + sub tlq, 64 + add hq, 1 + jl .w64_loop_init + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_h_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_smooth_h_8bpc, 3, 7, 8, dst, stride, tl, w, h +%define base r6-ipred_smooth_h_ssse3_table + LEA r6, ipred_smooth_h_ssse3_table + mov wd, wm + movd m3, [tlq+wq] + pxor m1, m1 + pshufb m3, m1 ; right + tzcnt wd, wd + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m4, [base+pb_127_m127] + movddup m5, [base+pw_128] + add wq, r6 + jmp wq +.w4: + movddup m6, [base+smooth_weights+4*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + sub tlq, hq + lea r3, [strideq*3] +.w4_loop: + movd m2, [tlq+hq] ; left + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r3 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova m6, [base+smooth_weights+8*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + sub tlq, hq + punpckldq m7, m7 +.w8_loop: + movd m2, [tlq+hq] ; left + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + mova m6, [base+smooth_weights+16*2] + mova m7, [base+smooth_weights+16*3] + sub tlq, 1 + sub tlq, hq +.w16_loop: + pxor m1, m1 + movd m2, [tlq+hq] ; left + pshufb m2, m1 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + lea dstq, [dstq+strideq] + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + sub tlq, 1 + sub tlq, hq + pxor m6, m6 +.w32_loop_init: + mov r5, 2 + lea r3, [base+smooth_weights+16*4] +.w32_loop: + mova m7, [r3] + add r3, 16 + movd m2, [tlq+hq] ; left + pshufb m2, m6 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m7 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + mova m7, [r3] + add r3, 16 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 16 + dec r5 + jg .w32_loop + lea dstq, [dstq-32+strideq] + sub hd, 1 + jg .w32_loop_init + RET +ALIGN function_align +.w64: + sub tlq, 1 + sub tlq, hq + pxor m6, m6 +.w64_loop_init: + mov r5, 4 + lea r3, [base+smooth_weights+16*8] +.w64_loop: + mova m7, [r3] + add r3, 16 + movd m2, [tlq+hq] ; left + pshufb m2, m6 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m7 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + mova m7, [r3] + add r3, 16 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 16 + dec r5 + jg .w64_loop + lea dstq, [dstq-64+strideq] + sub hd, 1 + jg .w64_loop_init + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro SMOOTH_2D_END 7 ; src[1-2], mul[1-2], add[1-2], m3 + pmaddubsw m6, m%3, m%1 + mova m0, m6 + pmaddubsw m6, m%4, m%2 + mova m1, m6 +%ifnum %5 + paddw m0, m%5 +%else + paddw m0, %5 +%endif +%ifnum %6 + paddw m1, m%6 +%else + paddw m1, %6 +%endif +%ifnum %7 +%else + mova m3, %7 +%endif + pavgw m0, m2 + pavgw m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +%macro SMOOTH_OUTPUT_16B 12 ; m1, [buffer1, buffer2, buffer3, buffer4,] [w1, w2,] m3, m7, [m0, m4, m5] + mova m1, [rsp+16*%1] ; top + punpckhbw m6, m1, m0 ; top, bottom + punpcklbw m1, m0 ; top, bottom + pmaddubsw m2, m1, m5 + mova [rsp+16*%2], m1 + paddw m1, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m1 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*%3], m2 + pmaddubsw m2, m6, m5 + mova [rsp+16*%4], m6 + paddw m6, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m6 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*%5], m2 + movd m1, [tlq+hq] ; left + pshufb m1, [base+pb_3] ; topleft[-(1 + y)] + punpcklbw m1, m4 ; left, right + pmaddubsw m2, m1, m5 ; 127 * left - 127 * right + paddw m2, m1 ; 128 * left + 129 * right + mova m3, m2 + pmaddubsw m0, m1, %6 ; weights_hor = &dav1d_sm_weights[width]; + pmaddubsw m1, %7 + paddw m2, m3, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + mova m7, [rsp+16*%9] + pshufb m1, m7 + mova [rsp+16*%8], m3 + mova m4, [rsp+16*%2] + mova m5, [rsp+16*%3] + mova m3, [rsp+16*%4] + mova m7, [rsp+16*%5] + SMOOTH_2D_END 1, 1, 4, 3, 5, 7, [rsp+16*%8] + mova [dstq], m0 + movddup m3, [base+pw_255] ; recovery + mova m0, [rsp+16*%10] ; recovery + mova m4, [rsp+16*%11] ; recovery + mova m5, [rsp+16*%12] ; recovery +%endmacro + +cglobal ipred_smooth_8bpc, 3, 7, 8, -13*16, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_ssse3_table + mov wd, wm + mov hd, hm + LEA r6, ipred_smooth_ssse3_table + movd m4, [tlq+wq] ; right + pxor m2, m2 + pshufb m4, m2 + tzcnt wd, wd + mov r5, tlq + sub r5, hq + movsxd wq, [r6+wq*4] + movddup m5, [base+pb_127_m127] + movd m0, [r5] + pshufb m0, m2 ; bottom + movddup m3, [base+pw_255] + add wq, r6 + lea v_weightsq, [base+smooth_weights+hq*2] ; weights_ver = &dav1d_sm_weights[height] + jmp wq +.w4: + mova m7, [base+ipred_v_shuf] + movd m1, [tlq+1] ; left + pshufd m1, m1, q0000 + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m1, m0 ; top, bottom + pshufd m6, m7, q1100 + pshufd m7, m7, q3322 + pmaddubsw m2, m1, m5 + paddw m3, m1 ; 1 * top + 255 * bottom + 255 + paddw m2, m3 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + movq m1, [base+smooth_weights+4*2] ; weights_hor = &dav1d_sm_weights[width]; + punpcklqdq m1, m1 + mova [rsp+16*2], m1 + mova [rsp+16*3], m4 + mova [rsp+16*4], m6 + mova [rsp+16*5], m5 +.w4_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+ipred_h_shuf] + punpcklbw m0, m1, m4 ; left, right + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 ; 127 * left - 127 * right + pmaddubsw m3, m1, m5 + paddw m2, m0 ; 128 * left + 129 * right + paddw m3, m1 + mova m4, [rsp+16*2] + pmaddubsw m0, m4 + pmaddubsw m1, m4 + paddw m2, m0 + paddw m3, m1 + movq m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 8 + pshufb m0, m1, m6 + pshufb m1, m7 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + SMOOTH_2D_END 0, 1, 4, 4, 5, 5, 3 + mova m4, [rsp+16*3] + mova m6, [rsp+16*4] + mova m5, [rsp+16*5] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r3 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova m7, [base+ipred_v_shuf] + movq m1, [tlq+1] ; left + punpcklqdq m1, m1 + sub tlq, 4 + sub tlq, hq + punpcklbw m1, m0 + pshufd m6, m7, q0000 + pshufd m7, m7, q1111 + pmaddubsw m2, m1, m5 + paddw m3, m1 + paddw m2, m3 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova m1, [base+smooth_weights+8*2] ; weights_hor = &dav1d_sm_weights[width]; + mova [rsp+16*2], m1 + mova [rsp+16*3], m4 + mova [rsp+16*4], m6 + mova [rsp+16*5], m5 +.w8_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+ipred_h_shuf] + pshufd m1, m1, q1100 + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 + pmaddubsw m3, m1, m5 + paddw m2, m0 + paddw m3, m1 + mova m4, [rsp+16*2] + pmaddubsw m0, m4 + pmaddubsw m1, m4 + paddw m2, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 4 + pshufb m0, m1, m6 + pshufb m1, m7 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + SMOOTH_2D_END 0, 1, 4, 4, 5, 5, 3 + mova m4, [rsp+16*3] + mova m6, [rsp+16*4] + mova m5, [rsp+16*5] + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + mova m7, [base+ipred_v_shuf] + movu m1, [tlq+1] ; left + sub tlq, 4 + sub tlq, hq + punpckhbw m6, m1, m0 ; top, bottom + punpcklbw m1, m0 ; top, bottom + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + pmaddubsw m2, m6, m5 + mova [rsp+16*5], m6 + paddw m6, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m6 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*6], m2 + pmaddubsw m2, m1, m5 + paddw m3, m1 ; 1 * top + 255 * bottom + 255 + mova [rsp+16*0], m1 + paddw m2, m3 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*1], m2 + mova [rsp+16*3], m4 + mova [rsp+16*4], m5 +.w16_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+pb_3] ; topleft[-(1 + y)] + punpcklbw m1, m4 ; left, right + pmaddubsw m2, m1, m5 ; 127 * left - 127 * right + paddw m2, m1 ; 128 * left + 129 * right + mova m0, m1 + mova m3, m2 + pmaddubsw m0, [base+smooth_weights+16*2] ; weights_hor = &dav1d_sm_weights[width]; + pmaddubsw m1, [base+smooth_weights+16*3] + paddw m2, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 2 + mova m7, [rsp+16*2] + pshufb m1, m7 + mova [rsp+16*7], m3 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + mova m3, [rsp+16*5] + mova m7, [rsp+16*6] + SMOOTH_2D_END 1, 1, 4, 3, 5, 7, [rsp+16*7] + mova m4, [rsp+16*3] + mova m5, [rsp+16*4] + mova [dstq], m0 + lea dstq, [dstq+strideq] + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m1, [tlq+1] ; top topleft[1 + x] + movu m2, [tlq+17] ; top + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + sub tlq, 4 + sub tlq, hq + mova m7, [base+ipred_v_shuf] + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + mova [rsp+16*3], m0 + mova [rsp+16*4], m4 + mova [rsp+16*5], m5 +.w32_loop: + SMOOTH_OUTPUT_16B 0, 6, 7, 8, 9, [base+smooth_weights+16*4], [base+smooth_weights+16*5], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 1, 6, 7, 8, 9, [base+smooth_weights+16*6], [base+smooth_weights+16*7], 10, 2, 3, 4, 5 + lea dstq, [dstq-16+strideq] + add v_weightsq, 2 + sub hd, 1 + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m1, [tlq+1] ; top topleft[1 + x] + movu m2, [tlq+17] ; top + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + movu m1, [tlq+33] ; top + movu m2, [tlq+49] ; top + mova [rsp+16*11], m1 + mova [rsp+16*12], m2 + sub tlq, 4 + sub tlq, hq + mova m7, [base+ipred_v_shuf] + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + mova [rsp+16*3], m0 + mova [rsp+16*4], m4 + mova [rsp+16*5], m5 +.w64_loop: + SMOOTH_OUTPUT_16B 0, 6, 7, 8, 9, [base+smooth_weights+16*8], [base+smooth_weights+16*9], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 1, 6, 7, 8, 9, [base+smooth_weights+16*10], [base+smooth_weights+16*11], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 11, 6, 7, 8, 9, [base+smooth_weights+16*12], [base+smooth_weights+16*13], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 12, 6, 7, 8, 9, [base+smooth_weights+16*14], [base+smooth_weights+16*15], 10, 2, 3, 4, 5 + lea dstq, [dstq-48+strideq] + add v_weightsq, 2 + sub hd, 1 + jg .w64_loop + RET + +%if ARCH_X86_64 +cglobal ipred_z1_8bpc, 3, 8, 11, 16*12, dst, stride, tl, w, h, angle, dx + %define base r7-$$ + lea r7, [$$] + mova m8, [base+pw_62] + mova m9, [base+pw_64] + mova m10, [base+pw_512] +%else +cglobal ipred_z1_8bpc, 3, 7, 8, -16*13, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define strideq r3 + %define stridemp dword [rsp+16*12] + mov stridemp, r1 + LEA r1, $$ +%endif + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + inc tlq + movsxd wq, [base+ipred_z1_ssse3_table+wq*4] + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + lea wq, [base+wq+ipred_z1_ssse3_table] + movzx dxd, word [base+dr_intra_derivative+dxq] + xor angled, 0x4ff ; d = 90 - angle + jmp wq +.w4: + lea r3d, [angleq+88] + test r3d, 0x480 + jnz .w4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r3d, 9 + add r3d, hd + cmp r3d, 8 + jg .w4_no_upsample ; h > 8 || (w == h && is_sm) + mova m1, [tlq-1] + pshufb m0, m1, [base+z_upsample1] + pshufb m1, [base+z_upsample2] + movddup m2, [base+pb_36_m4] + add dxd, dxd + pmaddubsw m0, m2 + pshufd m7, m1, q3333 + movd [rsp+16], m7 ; top[max_base_x] + pmaddubsw m1, m2 + movd m6, dxd + mov r5d, dxd ; xpos + pshufb m6, [base+pw_256] + paddw m1, m0 + movq m0, [tlq] + pmulhrsw m1, m10 + paddw m7, m6, m6 + punpcklqdq m6, m7 ; xpos0 xpos1 + packuswb m1, m1 + punpcklbw m0, m1 + movifnidn strideq, stridemp + mova [rsp], m0 +.w4_upsample_loop: + lea r2d, [r5+dxq] + shr r5d, 6 ; base0 + movq m0, [rsp+r5] + lea r5d, [r2+dxq] + shr r2d, 6 ; base1 + movhps m0, [rsp+r2] + pand m2, m8, m6 ; frac + psubw m1, m9, m2 ; 64-frac + psllw m2, 8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + paddw m6, m7 ; xpos += dx + pmulhrsw m0, m10 + packuswb m0, m0 + movd [dstq+strideq*0], m0 + pshuflw m0, m0, q1032 + movd [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_upsample_loop + RET +.w4_no_upsample: + mov r3d, 7 ; max_base + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea r3d, [hq+3] + movd m0, r3d + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + pcmpeqb m1, m0, [base+z_filter_wh4] + pand m1, m2 + pcmpgtb m1, [base+z_filter_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r3d, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + mova m3, [tlq-1] + imul r5d, 0x55555555 + movu m7, [base+z_filter_s+8] + shr r5d, 30 ; filter_strength + movddup m0, [base+pb_8] + pminub m7, m0 + pshufb m0, m3, [base+z_filter_s] + movddup m4, [base+z_filter_k-8+r5*8+24*0] + pshufb m3, m7 + movddup m5, [base+z_filter_k-8+r5*8+24*1] + shufps m2, m0, m3, q2121 + movddup m6, [base+z_filter_k-8+r5*8+24*2] + pmaddubsw m0, m4 + pmaddubsw m1, m2, m4 + pmaddubsw m2, m5 + paddd m5, m6 + pmaddubsw m4, m3, m5 + pmaddubsw m3, m6 + paddw m0, m2 + paddw m1, m4 + paddw m0, m3 + pshufd m1, m1, q3333 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + mov r5d, 9 + mov tlq, rsp + cmp hd, 4 + cmovne r3d, r5d + packuswb m0, m1 + mova [tlq], m0 +.w4_main: + add tlq, r3 + movd m5, dxd + movddup m0, [base+z_base_inc] ; base_inc << 6 + movd m7, [tlq] ; top[max_base_x] + shl r3d, 6 + movd m4, r3d + pshufb m5, [base+pw_256] + mov r5d, dxd ; xpos + pshufb m7, [base+pw_m256] + sub r5, r3 + pshufb m4, [base+pw_256] + mova m3, [base+z1_shuf_w4] + paddw m6, m5, m5 + psubw m4, m0 ; max_base_x + punpcklqdq m5, m6 ; xpos0 xpos1 +.w4_loop: + lea r3, [r5+dxq] + sar r5, 6 ; base0 + movq m0, [tlq+r5] + lea r5, [r3+dxq] + sar r3, 6 ; base1 + movhps m0, [tlq+r3] + pand m2, m8, m5 ; frac + psubw m1, m9, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m3 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + movifnidn strideq, stridemp + pcmpgtw m1, m4, m5 ; base < max_base_x + pmulhrsw m0, m10 + paddw m5, m6 ; xpos += dx + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movd [dstq+strideq*0], m0 + pshuflw m0, m0, q1032 + movd [dstq+strideq*1], m0 + sub hd, 2 + jz .w4_end + lea dstq, [dstq+strideq*2] + test r5d, r5d + jl .w4_loop + packuswb m7, m7 +.w4_end_loop: + movd [dstq+strideq*0], m7 + movd [dstq+strideq*1], m7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_end_loop +.w4_end: + RET +.w8: + lea r3d, [angleq+88] + and r3d, ~0x7f + or r3d, hd + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + mova m5, [base+z_upsample1] + movu m3, [base+z_filter_s+6] + movd m4, hd + mova m0, [tlq-1] + movu m1, [tlq+7] + pxor m7, m7 + pshufb m4, m7 + movddup m7, [base+pb_36_m4] + pminub m4, m3 + add dxd, dxd + pshufb m2, m0, m5 + pmaddubsw m2, m7 + pshufb m0, m3 + pmaddubsw m0, m7 + movd m6, dxd + pshufb m3, m1, m5 + pmaddubsw m3, m7 + pshufb m1, m4 + pmaddubsw m1, m7 + pshufb m6, [base+pw_256] + mov r5d, dxd + paddw m2, m0 + paddw m7, m6, m6 + paddw m3, m1 + punpcklqdq m6, m7 ; xpos0 xpos1 + movu m1, [tlq] + pmulhrsw m2, m10 + pmulhrsw m3, m10 + packuswb m2, m3 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + movifnidn strideq, stridemp + mova [rsp+16*0], m0 + mova [rsp+16*1], m1 +.w8_upsample_loop: + lea r2d, [r5+dxq] + shr r5d, 6 ; base0 + movu m0, [rsp+r5] + lea r5d, [r2+dxq] + shr r2d, 6 ; base1 + movu m1, [rsp+r2] + pand m2, m8, m6 + psubw m3, m9, m2 + psllw m2, 8 + por m3, m2 + punpcklqdq m2, m3, m3 ; frac0 + pmaddubsw m0, m2 + punpckhqdq m3, m3 ; frac1 + pmaddubsw m1, m3 + paddw m6, m7 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_upsample_loop + RET +.w8_no_upsample: + lea r3d, [hq+7] + movd m0, r3d + and r3d, 7 + or r3d, 8 ; imin(h+7, 15) + test angled, 0x400 + jnz .w8_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movu m1, [base+z_filter_wh8] + psrldq m3, [base+z_filter_t_w48+angleq*8], 4 + pcmpeqb m1, m0 + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_main ; filter_strength == 0 + movd m3, [tlq-1] + movu m0, [tlq+16*0] + imul r5d, 0x55555555 + movu m1, [tlq+16*1] + shr r5d, 30 ; filter_strength + movd m2, [tlq+r3] + lea tlq, [rsp+16*4] + sub r5, 3 + mova [tlq-16*1], m0 + pxor m7, m7 + mova [tlq+16*0], m1 + pshufb m3, m7 + pshufb m2, m7 + mova [tlq-16*2], m3 + movq [tlq+r3-15], m2 + call .filter_edge + sar r5d, 1 + add r5d, 17 + cmp hd, 8 + cmova r3d, r5d +.w8_main: + add tlq, r3 + movd m5, dxd + movd m7, [tlq] + shl r3d, 6 + movu m3, [base+z_filter_s+2] + movd m4, r3d + pshufb m5, [base+pw_256] + mov r5d, dxd + pshufb m7, [base+pw_m256] + sub r5, r3 + pshufb m4, [base+pw_256] + psubw m4, [base+z_base_inc] + mova m6, m5 +.w8_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3] + pand m1, m8, m5 + psubw m2, m9, m1 + psllw m1, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [dstq], m0 + dec hd + jz .w8_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w8_loop + packuswb m7, m7 +.w8_end_loop: + movq [dstq], m7 + add dstq, strideq + dec hd + jg .w8_end_loop +.w8_end: + RET +.w16: + lea r3d, [hq+15] + movd m0, r3d + and r3d, 15 + or r3d, 16 ; imin(h+15, 31) + test angled, 0x400 + jnz .w16_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m0, [base+z_filter_wh16] + pand m0, m2 + pcmpgtb m0, m3 + pmovmskb r5d, m0 + test r5d, r5d + jz .w16_main ; filter_strength == 0 + movd m4, [tlq-1] + movu m0, [tlq+16*0] + imul r5d, 0x24924924 + movu m1, [tlq+16*1] + shr r5d, 30 + movd m2, [tlq+30] + adc r5, -4 ; filter_strength-3 + movd m3, [tlq+r3] + lea tlq, [rsp+16*4] + mova [tlq-16*1], m0 + pxor m7, m7 + mova [tlq+16*0], m1 + pshufb m4, m7 + movd [rsp], m2 + pshufb m3, m7 + mova [tlq-16*2], m4 + movd [tlq+r3-16], m3 + call .filter_edge + cmp hd, 16 + jle .w16_main + pshuflw m0, [rsp], q0000 + sar r5, 1 + movd m1, [base+z_filter_k_tail+4+r5*4] + lea r3d, [r5+33] + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq+32], m0 +.w16_main: + add tlq, r3 + movd m5, dxd + movd m7, [tlq] + movd m4, r3d + shl r3d, 6 + pshufb m5, [base+pw_256] + pxor m6, m6 + pshufb m7, m6 + mov r5d, dxd + pshufb m4, m6 + sub r5, r3 + psubb m4, [base+pb_0to15] + mova m6, m5 +.w16_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+0] + pand m0, m8, m5 + movu m2, [tlq+r3+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m3, m5, 6 + packsswb m3, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + paddw m5, m6 + pcmpgtb m2, m4, m3 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq], m0 + dec hd + jz .w16_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w16_loop +.w16_end_loop: + mova [dstq], m7 + add dstq, strideq + dec hd + jg .w16_end_loop +.w16_end: + RET +.w32: + lea r3d, [hq+31] + and r3d, 31 + or r3d, 32 ; imin(h+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + movd m6, [tlq-1] + movu m0, [tlq+16*0] + movu m1, [tlq+16*1] + movu m2, [tlq+16*2] + movu m3, [tlq+16*3] + movd m4, [tlq+62] + movd m5, [tlq+r3] + lea tlq, [rsp+16*6] + mova [tlq-16*3], m0 + pxor m7, m7 + mova [tlq-16*2], m1 + pshufb m6, m7 + mova [tlq-16*1], m2 + xor r5d, r5d ; filter_strength = 3 + mova [tlq+16*0], m3 + movd [rsp], m4 + pshufb m5, m7 + mova [tlq-16*4], m6 + movd [tlq+r3-48], m5 + call .filter_edge + sub tlq, 16*2 + call .filter_edge + cmp hd, 32 + jle .w32_main + pshuflw m0, [rsp], q0000 + movd m1, [base+z_filter_k_tail+4] + add r3d, 2 + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq+64], m0 +.w32_main: + add tlq, r3 + movd m0, r3d + movd m7, [tlq] + shl r3d, 6 + movd m5, dxd + pxor m6, m6 + mov r5d, dxd + pshufb m0, m6 + pshufb m5, [base+pw_256] + sub r5, r3 + pshufb m7, m6 + psubb m0, [base+pb_0to15] + movddup m1, [base+pb_m16] + mova [rsp+16*0], m0 + paddb m0, m1 + mova [rsp+16*1], m0 + mova m6, m5 +.w32_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+16*0+0] + pand m0, m8, m5 + movu m2, [tlq+r3+16*0+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m4, m5, 6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m4, m4 + pcmpgtb m2, [rsp+16*0], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*1+0] + movu m2, [tlq+r3+16*1+1] + mova [dstq+16*0], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*1], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq+16*1], m0 + dec hd + jz .w32_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w32_loop +.w32_end_loop: + mova [dstq+16*0], m7 + mova [dstq+16*1], m7 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + lea r3d, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + movd m4, [tlq-1] + movu m0, [tlq+16*0] + movu m1, [tlq+16*1] + movu m2, [tlq+16*2] + movu m3, [tlq+16*3] + mova [rsp+16*3], m0 + pxor m7, m7 + mova [rsp+16*4], m1 + pshufb m4, m7 + mova [rsp+16*5], m2 + mova [rsp+16*6], m3 + mova [rsp+16*2], m4 + movu m0, [tlq+16*4] + movu m1, [tlq+16*5] + movu m2, [tlq+16*6] + movu m3, [tlq+16*7] + movd m4, [tlq+r3] + lea tlq, [rsp+16*10] + mova [tlq-16*3], m0 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*2], m1 + pshufb m4, m7 + mova [tlq-16*1], m2 + mova [tlq+16*0], m3 + movd [tlq+r3-16*7], m4 + cmp hd, 64 + jl .w64_filter96 ; skip one call if the last 32 bytes aren't used + call .filter_edge +.w64_filter96: + sub tlq, 16*2 + call .filter_edge + sub tlq, 16*2 + call .filter_edge + sub tlq, 16*2 + call .filter_edge +.w64_main: + add tlq, r3 + movd m0, r3d + movd m7, [tlq] + shl r3d, 6 + movd m5, dxd + pxor m6, m6 + mov r5d, dxd + pshufb m0, m6 + sub r5, r3 + pshufb m5, [base+pw_256] + pshufb m7, m6 + psubb m0, [base+pb_0to15] + movddup m1, [base+pb_m16] + mova [rsp+16*0], m0 + paddb m0, m1 + mova [rsp+16*1], m0 + paddb m0, m1 + mova [rsp+16*2], m0 + paddb m0, m1 + mova [rsp+16*3], m0 + mova m6, m5 +.w64_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+16*0+0] + pand m0, m8, m5 + movu m2, [tlq+r3+16*0+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m4, m5, 6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m4, m4 + pcmpgtb m2, [rsp+16*0], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*1+0] + movu m2, [tlq+r3+16*1+1] + mova [dstq+16*0], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*1], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*2+0] + movu m2, [tlq+r3+16*2+1] + mova [dstq+16*1], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*2], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*3+0] + movu m2, [tlq+r3+16*3+1] + mova [dstq+16*2], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*3], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq+16*3], m0 + dec hd + jz .w64_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w64_loop +.w64_end_loop: + mova [dstq+16*0], m7 + mova [dstq+16*1], m7 + mova [dstq+16*2], m7 + mova [dstq+16*3], m7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET +ALIGN function_align +.filter_edge: ; 32 pixels/iteration + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + movu m2, [tlq-18] + movu m1, [tlq-17] + movu m3, [tlq- 2] + movu m4, [tlq- 1] + punpcklbw m0, m2, m1 + pmaddubsw m0, m7 + punpckhbw m2, m1 + pmaddubsw m2, m7 + punpcklbw m1, m3, m4 + pmaddubsw m1, m7 + punpckhbw m3, m4 + pmaddubsw m3, m7 + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + mova m5, [tlq-16] + movu m6, [tlq-15] + punpcklbw m4, m5, m6 + pmaddubsw m4, m7 + punpckhbw m5, m6 + pmaddubsw m5, m7 + paddw m0, m4 + paddw m2, m5 + mova m5, [tlq+ 0] + movu m6, [tlq+ 1] + punpcklbw m4, m5, m6 + pmaddubsw m4, m7 + punpckhbw m5, m6 + pmaddubsw m5, m7 + paddw m1, m4 + paddw m3, m5 + test r5d, r5d + jnz .filter_end ; 3-tap + movddup m7, [base+z_filter_k+8*8] + movu m5, [tlq-14] + movu m6, [tlq+ 2] + punpcklbw m4, m5, m5 + pmaddubsw m4, m7 + punpckhbw m5, m5 + pmaddubsw m5, m7 + paddw m0, m4 + paddw m2, m5 + punpcklbw m5, m6, m6 + pmaddubsw m5, m7 + punpckhbw m6, m6 + pmaddubsw m6, m7 + paddw m1, m5 + paddw m3, m6 +.filter_end: +%if ARCH_X86_64 + REPX {pmulhrsw x, m10}, m0, m2, m1, m3 +%else + mova m4, m10 + REPX {pmulhrsw x, m4 }, m0, m2, m1, m3 +%endif + packuswb m0, m2 + packuswb m1, m3 + mova [tlq+16*0], m0 + mova [tlq+16*1], m1 + ret + +%if ARCH_X86_64 +cglobal ipred_z2_8bpc, 4, 12, 13, 16*16, dst, stride, tl, w, h, angle, dx, _, dy + %define base r7-$$ + %define maxwm r6m + %define maxhm r7m + lea r7, [$$] + mov hd, hm + mova m8, [base+pw_62] + mova m9, [base+pw_64] + lea r9d, [wq-4] + mova m10, [base+pw_512] + shl r9d, 6 + mova m11, [base+z1_shuf_w4] + or r9d, hd + mova m12, [base+z2_h_shuf] +%else +cglobal ipred_z2_8bpc, 4, 7, 8, -16*20, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define m11 [rsp+16*16] + %define m12 [rsp+16*17] + %define r9b byte [rsp+16*18+4*0] + %define r9d dword [rsp+16*18+4*0] + %define r10d dword [rsp+16*18+4*1] + %define r11d dword [rsp+16*18+4*2] + %define maxwm [rsp+16*18+4*3] + %define maxhm [rsp+16*19+4*0] + %define stridemp [rsp+16*19+4*1] + %define strideq r3 + %define dyd r4 + %define dyq r4 + mov stridemp, r1 + mov r1d, r6m + mov r4d, r7m + mov maxwm, r1d + mov maxhm, r4d + LEA r1, $$ + lea hd, [wq-4] + mova m0, [base+z1_shuf_w4] + shl hd, 6 + mova m1, [base+z2_h_shuf] + or hd, hm + mova m11, m0 + mov r9d, hd + mova m12, m1 +%endif + tzcnt wd, wd + movifnidn angled, anglem + movsxd wq, [base+ipred_z2_ssse3_table+wq*4] +%if ARCH_X86_64 + movzx dxd, angleb +%else + movzx dxd, byte anglem +%endif + xor angled, 0x400 + mova m0, [tlq-16*4] + mov dyd, dxd + mova m1, [tlq-16*3] + neg dxq + mova m2, [tlq-16*2] + and dyd, ~1 + mova m3, [tlq-16*1] + and dxq, ~1 + movd m4, [tlq] + movu m5, [tlq+16*0+1] + movu m6, [tlq+16*1+1] + movzx dyd, word [base+dr_intra_derivative+dyq-90] ; angle - 90 + movzx dxd, word [base+dr_intra_derivative+dxq+180] ; 180 - angle + mova [rsp+16*2], m0 + pxor m7, m7 + mova [rsp+16*3], m1 + pshufb m4, m7 + mova [rsp+16*4], m2 + lea wq, [base+ipred_z2_ssse3_table+wq] + mova [rsp+16*5], m3 + neg dxd + mova [rsp+16*6], m4 + or dyd, 4<<16 + mova [rsp+16*7], m4 + mova [rsp+16*8], m5 + mova [rsp+16*9], m6 + movq m0, [base+z_base_inc+2] + movsldup m1, [base+z2_dy_offset] + movq m2, [base+pw_256] ; 4<<6 + movq [rsp+16*14+8*0], m0 + movq [rsp+16*15+8*0], m1 + movq [rsp+16*15+8*1], m2 +%if ARCH_X86_64 + lea r10d, [dxq+(128<<6)] ; xpos +%else + mov [rsp+16*7+4*1], dyd + lea r4d, [dxq+(128<<6)] + mov r10d, r4d + movzx hd, r9b +%endif + mov r11d, (128-4)<<6 + jmp wq +.w4: + test angled, 0x400 + jnz .w4_main + movd m5, [tlq+4] + lea r3d, [hq+2] + add angled, 1022 + pshufb m5, m7 + shl r3d, 6 + movd [rsp+16*8+4], m5 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + movd m0, r3d + movd m6, angled + shr angled, 8 ; is_sm << 1 + pshufb m0, m7 + pshufb m6, m7 + pcmpeqb m0, [base+z_filter_wh4] + pand m6, m0 + pcmpgtb m6, [base+z_filter_t_w48+angleq*8] + jmp .w8_filter_left +.upsample_above: ; w4/w8 + movq m3, [rsp+gprsize+16*8-2] + movq m1, [rsp+gprsize+16*8-1] + movq m0, [rsp+gprsize+16*8+0] + movq m4, [rsp+gprsize+16*8+1] + movddup m5, [base+pb_36_m4] + punpcklbw m1, m3 + punpcklbw m2, m0, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 +%if ARCH_X86_64 + mova m11, [base+pb_0to15] + lea r10d, [r10+dxq+(1<<6)] + mov r11d, (128-7)<<6 +%else + mova m3, [base+pb_0to15] + mov r3d, [rsp+gprsize+16*18+4*1] + mov dword [rsp+gprsize+16*18+4*2], (128-7)<<6 + lea r3d, [r3+dxq+(1<<6)] + mov [rsp+gprsize+16*18+4*1], r3d + mova [rsp+gprsize+16*16], m3 +%endif + add dxd, dxd + paddw m1, m2 + pmulhrsw m1, m10 + movq m2, [rsp+gprsize+16*14] + paddw m2, m2 + movq [rsp+gprsize+16*14], m2 + packuswb m1, m1 + punpcklbw m1, m0 + mova [rsp+gprsize+16*8], m1 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + mov [rsp], angled + sub angled, 1112 ; angle - 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m3, [base+z_filter_wh4] + mova m4, [base+z_filter_t_w48+angleq*8] + call .w8_filter_top + mov angled, [rsp] + lea r3d, [hq+2] + sub angled, 139 + shl r3d, 6 + test r3d, angled + jnz .w8_filter_left ; angle <= 140 || h > 8 || (is_sm && h == 8) +.upsample_left: ; w4/w8 + neg hq + movd m0, [tlq+hq] + pshufb m0, m7 + movd [rsp+16*6+hq-4], m0 + movq m3, [rsp+16*5+7] + movq m0, [rsp+16*5+8] + movq m2, [rsp+16*5+9] + movq m4, [rsp+16*5+10] + movddup m5, [base+pb_36_m4] + punpcklbw m1, m0, m3 + punpcklbw m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + movshdup m3, [base+z2_dy_offset] +%if ARCH_X86_64 + mova m12, [base+z2_upsample] + add dyd, dyd +%else + mova m4, [base+z2_upsample] + shl dword [rsp+16*7+4*1], 1 + mova m12, m4 +%endif + paddw m1, m2 + pmulhrsw m1, m10 + movq [rsp+16*15], m3 + packuswb m1, m1 + punpcklbw m0, m1 + mova [rsp+16*5], m0 +.w4_main: + movd m6, dxd +%if ARCH_X86_64 + movd m3, dyd +%else + movd m3, [rsp+16*7+4*1] +%endif + movddup m0, [rsp+16*14+8*0] + pshufb m6, [base+pw_256] + paddw m7, m6, m6 + movq m5, [base+pw_m1to4] + pshuflw m4, m3, q0000 + punpcklqdq m6, m7 + pmullw m4, m5 + pshuflw m3, m3, q1111 + paddw m6, m0 + mov r2d, r10d + pshuflw m0, m4, q3333 + psubw m4, [rsp+16*15] + movq [rsp+16*6+8*1], m3 + movq [rsp+8*1], m0 ; dy*4 + mov r5, dstq +.w4_loop0: + mova [rsp+16*12], m6 + movq [rsp+8*0], m4 + pand m0, m4, m8 + psraw m4, 6 + psubw m1, m9, m0 + psllw m0, 8 + por m0, m1 ; 64-frac_y, frac_y + movq [rsp+8*3], m0 + pabsw m4, m4 + movq [rsp+8*2], m4 + movzx hd, r9b +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movq m0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movhps m0, [rsp+r3] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movq m1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movhps m1, [rsp+r3] + pand m2, m8, m6 + paddsw m5, m6, m7 + psubw m3, m9, m2 + psllw m2, 8 + pshufb m0, m11 + por m2, m3 + pmaddubsw m0, m2 + pand m2, m8, m5 + psubw m3, m9, m2 + psllw m2, 8 + pshufb m1, m11 + por m2, m3 + pmaddubsw m1, m2 + cmp r3d, 127 ; topleft + jge .w4_toponly + movzx r3d, byte [rsp+8*2+0] ; base_y0 + movq m3, [rsp+r3] + movzx r3d, byte [rsp+8*2+2] ; base_y1 + movhps m3, [rsp+r3] + movzx r3d, byte [rsp+8*2+4] ; base_y2 + movq m4, [rsp+r3] + movzx r3d, byte [rsp+8*2+6] ; base_y3 + movhps m4, [rsp+r3] + pshufb m3, m12 + pshufb m4, m12 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + movddup m4, [rsp+8*3] + pmaddubsw m2, m4 + pmaddubsw m3, m4 + psraw m6, 15 ; base_x < topleft + pand m2, m6 + pandn m6, m0 + por m0, m2, m6 + psraw m6, m5, 15 + pand m3, m6 + pandn m6, m1 + por m1, m3, m6 +.w4_toponly: + pmulhrsw m0, m10 + pmulhrsw m1, m10 + movifnidn strideq, stridemp + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + punpckhqdq m0, m0 + movd [dstq+strideq*0], m0 + psrlq m0, 32 + movd [dstq+strideq*1], m0 + sub hd, 4 + jz .w4_end + movq m4, [rsp+8*2] + movq m3, [rsp+16*6+8*1] + paddw m6, m5, m7 ; xpos += dx + psubw m4, m3 + movq [rsp+8*2], m4 + lea dstq, [dstq+strideq*2] + cmp r2d, r11d + jge .w4_loop + movddup m5, [rsp+8*3] +.w4_leftonly_loop: + movzx r2d, byte [rsp+8*2+0] ; base_y0 + movq m1, [rsp+r2] + movzx r2d, byte [rsp+8*2+2] ; base_y1 + movhps m1, [rsp+r2] + movzx r2d, byte [rsp+8*2+4] ; base_y2 + movq m2, [rsp+r2] + movzx r2d, byte [rsp+8*2+6] ; base_y3 + movhps m2, [rsp+r2] + psubw m4, m3 + pshufb m1, m12 + pshufb m2, m12 + movq [rsp+8*2], m4 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + punpckhqdq m0, m0 + movd [dstq+strideq*0], m0 + psrlq m0, 32 + movd [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + sub r9d, 1<<8 + jl .w4_ret + movq m4, [rsp+8*1] + add r5, 4 + mov dstq, r5 + paddw m4, [rsp+8*0] ; base_y += 4*dy + movzx r2d, word [rsp+16*15+8*1] + movddup m6, [rsp+16*15+8*1] + paddw m6, [rsp+16*12] ; base_x += (4 << upsample_above) + add r2d, r10d + mov r10d, r2d + jmp .w4_loop0 +.w4_ret: + RET +.w8: + test angled, 0x400 + jnz .w4_main + movd m5, [tlq+8] + lea r3d, [angleq+126] + pshufb m5, m7 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + movd [rsp+16*8+8], m5 + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + call .upsample_above + sub angled, 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + movu m1, [base+z_filter_wh8] + movd m0, r3d + movd m6, angled + shr angled, 8 ; is_sm << 1 + psrldq m2, [base+z_filter_t_w48+angleq*8], 4 + pshufb m0, m7 + pshufb m6, m7 + pcmpeqb m0, m1 + pand m6, m0 + pcmpgtb m6, m2 +%if ARCH_X86_64 + movq [rsp+16*15+8*1], m10 ; 8<<6 +%else + movq m0, m10 + movq [rsp+16*15+8*1], m0 +%endif + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + mov [rsp], angled + sub angled, 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m3, [base+z_filter_wh8] + psrldq m4, [base+z_filter_t_w48+angleq*8], 4 + call .w8_filter_top + mov r3d, [rsp] + sub r3d, 141 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + cmp r3d, 8 + jbe .upsample_left ; angle > 140 && h <= 8 && !is_sm +.w8_filter_left: + pmovmskb r5d, m6 + test r5d, r5d + jz .w4_main + imul r5d, 0x55555555 + mov r3, tlq + shr r5d, 30 + sub r5, 3 ; filter_strength-3 + jmp .filter_left +.w8_filter_top: + movd m6, r3d + REPX {pshufb x, m7}, m0, m1, m6 + pcmpeqb m0, m3 + pand m1, m0 + pand m6, m0 + pcmpgtb m1, m4 + pcmpgtb m6, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_filter_top_end ; filter_strength == 0 + imul r5d, 0x55555555 + movq m0, [rsp+gprsize+16*8-2] + shr r5d, 30 + movq m1, [rsp+gprsize+16*8-1] + sub r5, 3 ; filter_strength-3 + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + punpcklbw m0, m1 + pmaddubsw m0, m7 + movq m1, [rsp+gprsize+16*8+0] + movq m2, [rsp+gprsize+16*8+1] + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + punpcklbw m1, m2 + pmaddubsw m1, m7 + movq m2, [rsp+gprsize+16*8+2] + movddup m7, [base+z_filter_k+8*2+r5*8+24*2] + punpcklbw m2, m2 + pmaddubsw m2, m7 + paddw m0, m1 + paddw m0, m2 +%if ARCH_X86_64 + mov r3d, r7m ; maxw, offset due to call +%else + mov r3d, [rsp+gprsize+16*18+4*3] +%endif + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movq [rsp+gprsize+16*8], m0 + cmp r3d, 8 + jge .w8_filter_top_end + movq m0, [tlq+r3+1] + movq [rsp+gprsize+r3+16*8], m0 +.w8_filter_top_end: + ret +.w16: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+15] + sub angled, 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movd m6, r3d + REPX {pshufb x, m7}, m0, m1, m6 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m0, [base+z_filter_wh16] + pand m1, m0 + pand m6, m0 + pcmpgtb m1, m3 + pcmpgtb m6, m3 + pmovmskb r5d, m1 + mov r3, tlq + test r5d, r5d + jz .w16_filter_left ; filter_strength == 0 + imul r5d, 0x24924924 + pshufb m5, [base+z_filter_t_w16] ; tlq[16] + shr r5d, 30 + adc r5, -4 ; filter_strength-3 + movd [rsp+16*9], m5 + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + movu m1, [rsp+16*8-2] + movu m2, [rsp+16*8-1] + punpcklbw m0, m1, m2 + pmaddubsw m0, m7 + punpckhbw m1, m2 + pmaddubsw m1, m7 + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + mova m3, [rsp+16*8+0] + movu m4, [rsp+16*8+1] + punpcklbw m2, m3, m4 + pmaddubsw m2, m7 + punpckhbw m3, m4 + pmaddubsw m3, m7 + paddw m0, m2 + paddw m1, m3 + test r5d, r5d + jnz .w16_filter_end ; 3-tap + movddup m7, [base+z_filter_k+8*8] + movu m3, [rsp+16*8+2] + punpcklbw m2, m3, m3 + pmaddubsw m2, m7 + punpckhbw m3, m3 + pmaddubsw m3, m7 + paddw m0, m2 + paddw m1, m3 +.w16_filter_end: + mov r2d, maxwm + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*8], m0 + cmp r2d, 16 + jge .w16_filter_left + movu m0, [r3+r2+1] + movu [rsp+r2+16*8], m0 +.w16_filter_left: + pmovmskb r5d, m6 + test r5d, r5d + jz .w4_main + imul r5d, 0x24924924 + shr r5d, 30 + adc r5, -4 ; filter_strength-3 + jmp .filter_left +.w32: + test angled, 0x400 + jnz .w4_main + pshufb m6, [base+z_filter_t_w16] ; tlq[32] + mov r3, tlq + lea tlq, [rsp+16*9] + movd [tlq+16*1], m6 + xor r5d, r5d ; filter_strength = 3 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mov r2d, maxwm + mova [rsp+16*8], m0 + mova [rsp+16*9], m1 + cmp r2d, 32 + jge .filter_left + movu m0, [r3+r2+16*0+1] + movu m1, [r3+r2+16*1+1] + movu [rsp+r2+16*8], m0 + movu [rsp+r2+16*9], m1 + jmp .filter_left +.w64: + movu m0, [tlq+16*2+1] + movu m1, [tlq+16*3+1] + mova [rsp+16*10], m0 + mova [rsp+16*11], m1 + test angled, 0x400 + jnz .w4_main + pshufb m1, [base+z_filter_t_w16] ; tlq[64] + mov r3, tlq + lea tlq, [rsp+16*11] + movd [tlq+16*1], m1 + xor r5d, r5d ; filter_strength = 3 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mova m2, [tlq+16*2] + mova m3, [tlq+16*3] + mov r2d, maxwm + mova [rsp+16* 8], m0 + mova [rsp+16* 9], m1 + mova [rsp+16*10], m2 + mova [rsp+16*11], m3 + cmp r2d, 64 + jge .filter_left + movu m0, [r3+r2+16*0+1] + movu m1, [r3+r2+16*1+1] + movu [rsp+r2+16* 8], m0 + movu [rsp+r2+16* 9], m1 + cmp r2d, 32 + jge .filter_left + movu m0, [r3+r2+16*2+1] + movu m1, [r3+r2+16*3+1] + movu [rsp+r2+16*10], m0 + movu [rsp+r2+16*11], m1 +.filter_left: + neg hq + movd m0, [r3+hq] + pxor m1, m1 + pshufb m0, m1 + movd [rsp+16*6+hq-4], m0 + lea tlq, [rsp+16*5] + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + cmp hd, -32 + jge .filter_left_end + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mova [rsp+16*2], m0 + mova [rsp+16*3], m1 +.filter_left_end: + mov r2d, maxhm + mova m0, [rsp+16*5] + mova m1, [rsp+16*6] + mova m2, [rsp+16*7] + neg r2 + mova [rsp+16*4], m0 + mova [rsp+16*5], m1 + mova [rsp+16*6], m2 + cmp r2d, hd + jle .w4_main + movu m0, [r3+r2-16*2] + movu m1, [r3+r2-16*1] + movu [rsp+r2+16*4], m0 + movu [rsp+r2+16*5], m1 + cmp r2d, -32 + jle .w4_main + movu m0, [r3+r2-16*4] + movu m1, [r3+r2-16*3] + movu [rsp+r2+16*2], m0 + movu [rsp+r2+16*3], m1 + jmp .w4_main + +%if ARCH_X86_64 +cglobal ipred_z3_8bpc, 4, 9, 11, 16*10, dst, stride, tl, w, h, angle, dy, _, org_w + %define base r7-$$ + lea r7, [$$] + mova m8, [base+pw_62] + mova m9, [base+pw_64] + mova m10, [base+pw_512] + mov org_wd, wd +%else +cglobal ipred_z3_8bpc, 4, 7, 8, -16*10, dst, stride, tl, w, h, angle, dy + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define org_wd r5 + %define org_wq r5 + mov [dstq+strideq*0], strideq + mov [dstq+strideq*1], wd + LEA r1, $$ +%endif + tzcnt hd, hm + movifnidn angled, anglem + dec tlq + movsxd hq, [base+ipred_z3_ssse3_table+hq*4] + sub angled, 180 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + lea hq, [base+ipred_z3_ssse3_table+hq] + movzx dyd, word [base+dr_intra_derivative+45*2-1+dyq] + jmp hq +.h4: + lea r4d, [angleq+88] + test r4d, 0x480 + jnz .h4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r4d, 9 + add r4d, wd + cmp r4d, 8 + jg .h4_no_upsample ; w > 8 || (w == 8 && is_sm) + movu m3, [tlq-7] + movu m1, [base+z_upsample1-4] + movu m4, [base+z_filter_s+2] + pshufb m0, m3, m1 + pxor m1, m1 + pshufb m2, m3, m1 + pshufb m1, m3, m4 + mova [rsp+16], m2 ; top[max_base_y] + movddup m2, [base+pb_36_m4] + add dyd, dyd + pmaddubsw m0, m2 + pmaddubsw m1, m2 + movd m5, dyd + mov r5d, dyd + pshufb m5, [base+pw_256] + paddw m0, m1 + pmulhrsw m0, m10 + shl wd, 2 + mov tlq, rsp + sub rsp, wq + packuswb m0, m0 + punpcklbw m0, m3 + paddw m6, m5, m5 + punpcklqdq m5, m6 + pshufb m0, [base+pb_15to0] + mova [tlq], m0 +.h4_upsample_loop: + lea r4d, [r5+dyq] + shr r5d, 6 + movq m0, [tlq+r5] + lea r5d, [r4+dyq] + shr r4d, 6 + movhps m0, [tlq+r4] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + por m1, m2 + pmaddubsw m0, m1 + paddw m5, m6 + pmulhrsw m0, m10 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jg .h4_upsample_loop + jmp .h4_transpose +.h4_no_upsample: + mov r4d, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea r4d, [wq+3] + movd m0, r4d + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + pcmpeqb m1, m0, [base+z_filter_wh4] + pand m1, m2 + pcmpgtb m1, [base+z_filter_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r4d, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + movu m2, [tlq-7] + imul r5d, 0x55555555 + movu m3, [base+z_filter_s-2] + shr r5d, 30 ; filter_strength + mova m4, [base+z_upsample2] + movddup m5, [base+z_filter_k-8+r5*8+24*0] + movddup m6, [base+z_filter_k-8+r5*8+24*1] + movddup m7, [base+z_filter_k-8+r5*8+24*2] + pshufb m0, m2, m3 + shufps m3, m4, q2121 + pmaddubsw m1, m0, m5 + pmaddubsw m0, m6 + pshufb m5, m2, m3 + pmaddubsw m3, m5, m6 + pmaddubsw m5, m7 + pshufb m2, m4 + pmaddubsw m2, m7 + paddw m0, m1 + paddw m1, m3 + paddw m0, m5 + paddw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + lea r2d, [r4+2] + cmp wd, 4 + cmovne r4d, r2d + pshufd m0, m0, q0000 + lea tlq, [rsp+15] + packuswb m0, m1 + mova [rsp], m0 +.h4_main: + movd m5, dyd + movddup m0, [base+z_base_inc] ; base_inc << 6 + sub tlq, r4 + shl r4d, 6 + movd m7, [tlq] + movd m4, r4d + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, [base+pw_m256] + mova m3, [base+z3_shuf_h4] + lea r5, [dyq+r4+63] ; ypos + pshufb m4, [base+pw_256] + psubw m4, m0 ; max_base_y + shl wd, 2 + paddw m6, m5, m5 + sub rsp, wq + punpcklqdq m5, m6 +.h4_loop: + lea r4, [r5+dyq] + sar r5, 6 + movq m0, [tlq+r5-4] + lea r5, [r4+dyq] + sar r4, 6 + movhps m0, [tlq+r4-4] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jz .h4_transpose + test r5d, r5d + jg .h4_loop + packuswb m7, m7 +.h4_end_loop: + movq [rsp+wq-8], m7 + sub wd, 8 + jg .h4_end_loop +.h4_transpose: + mova m1, [base+z_transpose4] +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + lea r2, [strideq*3] + lea dstq, [dstq+org_wq-4] +.h4_transpose_loop: + mova m0, [rsp] + add rsp, 16 + pshufb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m2, m0, q1032 + movd [dstq+strideq*1], m2 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r2 ], m0 + sub dstq, 4 + sub org_wd, 4 + jg .h4_transpose_loop + RET +.h8: + lea r4d, [angleq+88] + and r4d, ~0x7f + or r4d, wd + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m4, [tlq-15] + and r4d, 4 + movu m3, [tlq- 9] + movd m1, r4d + movu m2, [base+z_filter_s+2] + pxor m0, m0 + movu m5, [base+z_filter_s+6] + movddup m7, [base+pb_36_m4] + pshufb m1, m0 ; w & 4 + movu m0, [base+z_upsample1-4] + pmaxub m1, m0 ; clip 4x8 + add dyd, dyd + pshufb m0, m4, m1 + pmaddubsw m0, m7 + pshufb m1, m4, m2 + pmaddubsw m1, m7 + pshufb m2, m3, [base+z_upsample1] + pmaddubsw m2, m7 + pshufb m3, m5 + pmaddubsw m3, m7 + movd m5, dyd + neg dyq + paddw m1, m0 + paddw m2, m3 + pmulhrsw m1, m10 + pmulhrsw m2, m10 + shl wd, 3 + lea tlq, [rsp+16] + pshufb m5, [base+pw_256] + sub rsp, wq + packuswb m1, m2 + lea r5, [dyq+63] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + mova [tlq-16*1], m0 + mova [tlq-16*0], m1 + paddw m6, m5, m5 + punpcklqdq m5, m6 +.h8_upsample_loop: + lea r4, [r5+dyq] + sar r5, 6 + movu m0, [tlq+r5] + lea r5, [r4+dyq] + sar r4, 6 + movu m1, [tlq+r4] + pand m3, m8, m5 + psubw m2, m9, m3 + psllw m2, 8 + por m3, m2 + pshufd m2, m3, q1010 + pmaddubsw m0, m2 + punpckhqdq m3, m3 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m1, m0 + mova [rsp+wq-16], m1 + sub wd, 16 + jg .h8_upsample_loop + jmp .h8_transpose +.h8_no_upsample: + lea r4d, [wq+7] + movd m0, r4d + and r4d, 7 + or r4d, 8 ; imin(w+7, 15) + test angled, 0x400 + jnz .h8_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movu m1, [base+z_filter_wh8] + psrldq m3, [base+z_filter_t_w48+angleq*8], 4 + pcmpeqb m1, m0 + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .h8_main ; filter_strength == 0 + mova m0, [tlq-15] + imul r5d, 0x55555555 + movd m1, [tlq+1] + neg r4 + movd m2, [tlq+r4] + shr r5d, 30 + pxor m7, m7 + lea tlq, [rsp+16*2] + sub r5, 3 ; filter_strength-3 + mova [tlq+16*0], m0 + pshufb m1, m7 + mova [tlq+16*1], m1 + pshufb m2, m7 + movq [tlq+r4+8], m2 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sar r5d, 1 + add tlq, 31 + add r5d, 17 + cmp wd, 8 + cmova r4d, r5d +.h8_main: + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m7, [tlq] + movd m4, r4d + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, [base+pw_m256] + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, [base+pw_256] + psubw m4, [base+z3_base_inc] + shl wd, 3 + mova m6, m5 + sub rsp, wq +.h8_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4-8] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jz .h8_transpose + add r5, dyq + jg .h8_loop + packuswb m7, m7 +.h8_end_loop: + movq [rsp+wq-8], m7 + sub wd, 8 + jg .h8_end_loop +.h8_transpose: +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + or r3d, 8 + cmp org_wd, 4 +%if ARCH_X86_64 + jne .end_transpose_main +%else + jne .end_transpose_loop +%endif + mova m1, [rsp+16*1] + mova m0, [rsp+16*0] + lea r2, [strideq*3] + add rsp, 16*2 + punpcklbw m2, m1, m0 + punpckhbw m1, m0 + punpckhbw m0, m1, m2 + punpcklbw m1, m2 +.write_4x8_end: + call .write_4x8 + RET +.write_4x8: + movd [dstq+r2 ], m0 + pshuflw m4, m0, q1032 + movd [dstq+strideq*2], m4 + punpckhqdq m0, m0 + movd [dstq+strideq*1], m0 + psrlq m0, 32 + movd [dstq+strideq*0], m0 + lea dstq, [dstq+strideq*4] + movd [dstq+r2 ], m1 + pshuflw m4, m1, q1032 + movd [dstq+strideq*2], m4 + punpckhqdq m1, m1 + movd [dstq+strideq*1], m1 + psrlq m1, 32 + movd [dstq+strideq*0], m1 + ret +.h16: + lea r4d, [wq+15] + movd m0, r4d + and r4d, 15 + or r4d, 16 ; imin(w+15, 31) + test angled, 0x400 + jnz .h16_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m1, m0, [base+z_filter_wh16] + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .h16_main ; filter_strength == 0 + mova m0, [tlq-16*2+1] + imul r5d, 0x24924924 + mova m1, [tlq-16*1+1] + neg r4 + movd m2, [tlq-16*0+1] + shr r5d, 30 + movd m3, [tlq+r4] + adc r5, -4 ; filter_strength-3 + pxor m7, m7 + lea tlq, [rsp+16*2] + mova [tlq-16*1], m0 + pshufb m2, m7 + mova [tlq+16*0], m1 + pshufb m3, m7 + mova [tlq+16*1], m2 + movq [tlq+r4+8], m3 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + add tlq, 31 + cmp wd, 16 + jle .h16_main + pshuflw m0, [tlq-47], q0000 + sar r5, 1 + movq m1, [base+z3_filter_k_tail+r5*4] + lea r4d, [r5+33] + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq-35], m0 +.h16_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + shl wd, 4 + mova m6, m5 + sub rsp, wq +.h16_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*2] + por m2, m1 + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + psrlw m2, m5, 6 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + pand m0, m1 + pandn m1, m7 + por m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jz .h16_transpose + add r5, dyq + jg .h16_loop +.h16_end_loop: + mova [rsp+wq-16], m7 + sub wd, 16 + jg .h16_end_loop +.h16_transpose: +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + or r3d, 16 + cmp org_wd, 4 +%if ARCH_X86_64 + jne .end_transpose_main +%else + jne .end_transpose_loop +%endif +.h16_transpose_w4: + mova m2, [rsp+16*3] + mova m4, [rsp+16*2] + mova m3, [rsp+16*1] + mova m0, [rsp+16*0] + lea r2, [strideq*3] + add rsp, 16*4 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + punpckhbw m4, m3, m0 + punpcklbw m3, m0 + punpckhwd m0, m1, m4 + punpcklwd m1, m4 + call .write_4x8 + lea dstq, [dstq+strideq*4] + punpckhwd m0, m2, m3 + punpcklwd m1, m2, m3 + jmp .write_4x8_end +.h32: + lea r4d, [wq+31] + and r4d, 31 + or r4d, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + mova m0, [tlq-16*4+1] + mova m1, [tlq-16*3+1] + mova m2, [tlq-16*2+1] + mova m3, [tlq-16*1+1] + movd m4, [tlq-16*0+1] + neg r4 + movd m5, [tlq+r4] + pxor m7, m7 + lea tlq, [rsp+16*4] + mova [tlq-16*3], m0 + mova [tlq-16*2], m1 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*1], m2 + pshufb m4, m7 + mova [tlq+16*0], m3 + pshufb m5, m7 + mova [tlq+16*1], m4 + movq [tlq+r4+8], m5 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + add tlq, 63 + cmp wd, 32 + jle .h32_main + pshuflw m0, [tlq-79], q0000 + movq m1, [base+z3_filter_k_tail] + add r4d, 2 + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq-67], m0 +.h32_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + mova m6, m5 +.h32_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*4] + por m2, m1 + movu m1, [tlq+r4-8*3] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + sub rsp, 32 + packuswb m0, m1 + mova [rsp+16*0], m0 + movu m0, [tlq+r4-8*2] + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + psrlw m2, m5, 6 + paddw m5, m6 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + pand m0, m1 + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + mova [rsp+16*1], m0 + pand m0, m1, [rsp+16*0] + pandn m1, m7 + por m0, m1 + mova [rsp+16*0], m0 + dec wd + jz .h32_transpose + add r5, dyq + jg .h32_loop +.h32_end_loop: + sub rsp, 32 + mova [rsp+16*1], m7 + mova [rsp+16*0], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + or r3d, 32 + jmp .end_transpose_main +.h64: + lea r4d, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + mova m0, [tlq-16*8+1] + mova m1, [tlq-16*7+1] + mova m2, [tlq-16*6+1] + mova m3, [tlq-16*5+1] + mova [rsp+16*1], m0 + mova [rsp+16*2], m1 + mova [rsp+16*3], m2 + mova [rsp+16*4], m3 + mova m0, [tlq-16*4+1] + mova m1, [tlq-16*3+1] + mova m2, [tlq-16*2+1] + mova m3, [tlq-16*1+1] + movd m4, [tlq-16*0+1] + neg r4 + movd m5, [tlq+r4] + pxor m7, m7 + lea tlq, [rsp+16*8] + mova [tlq-16*3], m0 + mova [tlq-16*2], m1 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*1], m2 + pshufb m4, m7 + mova [tlq+16*0], m3 + pshufb m5, m7 + mova [tlq+16*1], m4 + movq [tlq+r4+8], m5 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + cmp wd, 64 + jl .h64_filter96 ; skip one call if the last 32 bytes aren't used + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge +.h64_filter96: + add tlq, 127 +.h64_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + mova m6, m5 +.h64_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*8] + por m2, m1 + movu m1, [tlq+r4-8*7] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + sub rsp, 64 + packuswb m0, m1 + mova [rsp+16*0], m0 + movu m0, [tlq+r4-8*6] + movu m1, [tlq+r4-8*5] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*1], m0 + movu m0, [tlq+r4-8*4] + movu m1, [tlq+r4-8*3] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*2], m0 + movu m0, [tlq+r4-8*2] + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + psrlw m2, m5, 6 + paddw m5, m6 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + pand m0, m1 + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + mova [rsp+16*3], m0 + pand m0, m1, [rsp+16*2] + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + mova [rsp+16*2], m0 + pand m0, m1, [rsp+16*1] + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + mova [rsp+16*1], m0 + pand m0, m1, [rsp+16*0] + pandn m1, m7 + por m0, m1 + mova [rsp+16*0], m0 + dec wd + jz .h64_transpose + add r5, dyq + jg .h64_loop +.h64_end_loop: + sub rsp, 64 + mova [rsp+16*3], m7 + mova [rsp+16*2], m7 + mova [rsp+16*1], m7 + mova [rsp+16*0], m7 + dec wd + jg .h64_end_loop +.h64_transpose: + or r3d, 64 +.end_transpose_main: +%if ARCH_X86_64 + lea r5, [r3*3] + lea r7, [strideq*3] +%else + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif +.end_transpose_loop: + lea r4, [rsp+r3-8] + lea r6, [dstq+org_wq-8] +.end_transpose_loop_y: + movq m0, [r4+r3*1] + movq m4, [r4+r3*0] +%if ARCH_X86_64 + movq m1, [r4+r5 ] + movq m5, [r4+r3*2] + lea r2, [r4+r3*4] +%else + lea r2, [r4+r3*2] + movq m1, [r2+r3*1] + movq m5, [r2+r3*0] + lea r2, [r2+r3*2] +%endif + movq m2, [r2+r3*1] + movq m6, [r2+r3*0] +%if ARCH_X86_64 + movq m3, [r2+r5 ] + movq m7, [r2+r3*2] +%else + lea r2, [r2+r3*2] + movq m3, [r2+r3*1] + movq m7, [r2+r3*0] +%endif + sub r4, 8 + punpcklbw m0, m4 + punpcklbw m1, m5 + punpcklbw m2, m6 + punpcklbw m3, m7 + punpckhwd m4, m1, m0 + punpcklwd m1, m0 + punpckhwd m0, m3, m2 + punpcklwd m3, m2 + punpckhdq m2, m3, m1 + punpckldq m3, m1 + punpckldq m1, m0, m4 + punpckhdq m0, m4 + movhps [r6+strideq*0], m0 + movq [r6+strideq*1], m0 +%if ARCH_X86_64 + movhps [r6+strideq*2], m1 + movq [r6+r7 ], m1 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m1 + movq [r6+strideq*1], m1 + lea r6, [r6+strideq*2] +%endif + movhps [r6+strideq*0], m2 + movq [r6+strideq*1], m2 +%if ARCH_X86_64 + movhps [r6+strideq*2], m3 + movq [r6+r7 ], m3 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m3 + movq [r6+strideq*1], m3 + lea r6, [r6+strideq*2] +%endif + cmp r4, rsp + jae .end_transpose_loop_y + lea rsp, [rsp+r3*8] + sub org_wd, 8 + jg .end_transpose_loop + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_pal_pred_ssse3(pixel *dst, const ptrdiff_t stride, const uint16_t *const pal, +; const uint8_t *idx, const int w, const int h); +;--------------------------------------------------------------------------------------- +cglobal pal_pred_8bpc, 4, 6, 5, dst, stride, pal, idx, w, h + mova m4, [palq] + LEA r2, pal_pred_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r2+wq*4] + packuswb m4, m4 + add wq, r2 + lea r2, [strideq*3] + jmp wq +.w4: + pshufb m0, m4, [idxq] + add idxq, 16 + movd [dstq ], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq ], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r2 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + add idxq, 32 + movq [dstq ], m0 + movhps [dstq+strideq ], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r2 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+strideq ], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r2 ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +ALIGN function_align +.w32: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+16 ], m1 + mova [dstq+strideq ], m2 + mova [dstq+strideq+16], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +ALIGN function_align +.w64: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+16], m1 + mova [dstq+32], m2 + mova [dstq+48], m3 + add dstq, strideq + sub hd, 1 + jg .w64 + RET + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal ipred_cfl_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + movifnidn wd, wm + movifnidn hd, hm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd m4, t0d + tzcnt t0d, t0d + movd m5, t0d + LEA t0, ipred_cfl_ssse3_table + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+16] + pcmpeqd m3, m3 + psrlw m4, 1 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movd m0, [tlq-4] + pmaddubsw m0, m3 + jmp wq +.w4: + movd m1, [tlq+1] + pmaddubsw m1, m3 + psubw m0, m4 + paddw m0, m1 + pmaddwd m0, m3 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 ; dc >>= ctz(width + height); + jmp .w4_end +.w4_mul: + punpckhqdq m1, m0, m0 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + psrlw m0, 2 + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8 + cmovz r6d, r2d + movd m5, r6d + pmulhuw m0, m5 +.w4_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s4: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movd [dstq+strideq*0], m4 + pshuflw m4, m4, q1032 + movd [dstq+strideq*1], m4 + punpckhqdq m4, m4 + movd [dstq+strideq*2], m4 + psrlq m4, 32 + movd [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + movq m0, [tlq-8] + pmaddubsw m0, m3 + jmp wq +.w8: + movq m1, [tlq+1] + pmaddubsw m1, m3 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movq [dstq ], m4 + movhps [dstq+strideq ], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movq [dstq+strideq*2], m4 + movhps [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova m0, [tlq-16] + pmaddubsw m0, m3 + jmp wq +.w16: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq+strideq], m4 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + mova m2, [tlq-16] + pmaddubsw m2, m3 + paddw m0, m2 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + movu m2, [tlq+17] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 64|16 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq+16], m4 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_left_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov t0d, 0x8000 + movd m3, t0d + movd m2, r6d + psrld m3, m2 + LEA t0, ipred_cfl_left_ssse3_table + movsxd r6, [t0+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_ssse3_table-ipred_cfl_left_ssse3_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + movu m1, [tlq+16] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h16: + pshufd m1, m0, q3232 ; psrlq m1, m0, 16 + paddw m0, m1 +.h8: + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 +.h4: + pmaddwd m0, m2 + pmulhrsw m0, m3 + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_top_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_top_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + LEA t0, ipred_cfl_left_ssse3_table + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + movd m3, r6d + movd m2, wd + psrld m3, m2 + movsxd r6, [t0+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_ssse3_table-ipred_cfl_left_ssse3_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_128_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_128_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + tzcnt wd, wm + movifnidn hd, hm + LEA r6, ipred_cfl_splat_ssse3_table + movsxd wq, [r6+wq*4] + movddup m0, [r6-ipred_cfl_splat_ssse3_table+pw_128] + add wq, r6 + movifnidn acq, acmp + jmp wq + +%macro RELOAD_ACQ_32 1 + mov acq, ac_bakq ; restore acq +%endmacro + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_420_8bpc, 4, 8, 7, ac, y, stride, wpad, hpad, w, h, ac_bak +DECLARE_REG_TMP 7 + movddup m2, [pb_2] +%else +cglobal ipred_cfl_ac_420_8bpc, 4, 7, 7, ac, y, stride, wpad, hpad, w, h +DECLARE_REG_TMP 4 +%define ac_bakq acmp + mov t0d, 0x02020202 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m5, t0d + movifnidn hpadd, hpadm +%if ARCH_X86_64 + mov ac_bakq, acq +%endif + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq m0, [yq] + movq m1, [yq+strideq] + movhps m0, [yq+strideq*2] + movhps m1, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4_8 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop + jmp .calc_avg_4_8 +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + mova m0, [yq+strideq*2] + mova m1, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_4_8 + jmp .w8_hpad +.w8_wpad: ; wpadd=1 + movddup m0, [yq] + movddup m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufhw m0, m0, q3333 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 16 + sub hd, 1 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_4_8 +.w8_hpad: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 1 + jg .w8_hpad + jmp .calc_avg_4_8 +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + mova m6, [yq+16] + mova m1, [yq+strideq+16] + pmaddubsw m6, m2 + pmaddubsw m1, m2 + paddw m6, m1 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_loop + test hpadd, hpadd + jz .calc_avg16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movddup m0, [yq] + movddup m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufhw m0, m0, q3333 + mova [acq], m0 + paddw m4, m0 + mova m6, m0 + punpckhqdq m6, m0, m0 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + pshufhw m6, m0, q3333 + punpckhqdq m6, m6 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + movddup m6, [yq+16] + movddup m1, [yq+strideq+16] + pmaddubsw m6, m2 + pmaddubsw m1, m2 + paddw m6, m1 + pshufhw m6, m6, q3333 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg16 +.w16_hpad_loop: + mova [acq], m0 + paddw m4, m0 + mova [acq+16], m6 + paddw m4, m6 + add acq, 32 + dec hpadd + jg .w16_hpad_loop + jmp .calc_avg16 + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif +.calc_avg_4_8: + psrlw m2, 9 + pmaddwd m4, m2 + jmp .calc_avg +.calc_avg16: + psrld m0, m4, 16 + pslld m4, 16 + psrld m4, 16 + paddd m4, m0 +.calc_avg: + movd szd, m5 + psrad m5, 1 + tzcnt r1d, szd + paddd m4, m5 + movd m1, r1d + pshufd m0, m4, q2301 + paddd m0, m4 + pshufd m4, m0, q1032 + paddd m0, m4 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq +.sub_loop: + mova m1, [acq] + psubw m1, m0 ; ac[x] -= sum; + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_422_8bpc, 4, 8, 7, ac, y, stride, wpad, hpad, w, h, ac_bak + movddup m2, [pb_4] +%else +cglobal ipred_cfl_ac_422_8bpc, 4, 7, 7, ac, y, stride, wpad, hpad, w, h + mov t0d, 0x04040404 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m6, t0d + movifnidn hpadd, hpadm +%if ARCH_X86_64 + mov ac_bakq, acq +%endif + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + pxor m5, m5 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq m1, [yq] + movhps m1, [yq+strideq] + movq m0, [yq+strideq*2] + movhps m0, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop + jmp .calc_avg_4 +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova m1, [yq] + mova m0, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m0 + paddw m5, m1 + mova m1, [yq+strideq*2] + mova m0, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w8_hpad +.w8_wpad: + movddup m1, [yq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + movddup m0, [yq+strideq] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + sub hd, 2 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_8_16 +.w8_hpad: + mova [acq], m0 + paddw m4, m0 + mova [acq+16], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad + jmp .calc_avg_8_16 +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m1, [yq] + mova m0, [yq+16] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m0 + paddw m5, m1 + mova m1, [yq+strideq] + mova m0, [yq+strideq+16] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m0 + paddw m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movddup m1, [yq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movddup m1, [yq+strideq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq+32], m1 + paddw m4, m1 + punpckhqdq m0, m1, m1 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + mova m1, [yq] + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + pshufhw m1, m1, q3333 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + mova m1, [yq+strideq] + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + mova m0, m1 + pshufhw m0, m0, q3333 + punpckhqdq m0, m0 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m1, [yq] + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + movddup m0, [yq+16] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m5, m0 + mova m1, [yq+strideq] + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + movddup m0, [yq+strideq+16] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg_8_16 +.w16_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m1 + paddw m5, m0 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m1 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + jmp .calc_avg_8_16 + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif +.calc_avg_4: + psrlw m2, 10 + pmaddwd m5, m2 + pmaddwd m0, m4, m2 + jmp .calc_avg +.calc_avg_8_16: + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, m4 + psrld m0, 16 + pslld m4, 16 + psrld m4, 16 + paddd m0, m4 +.calc_avg: + paddd m5, m0 + movd szd, m6 + psrad m6, 1 + tzcnt r1d, szd ; const int log2sz = ctz(width) + ctz(height); + paddd m5, m6 + movd m1, r1d + pshufd m0, m5, q2301 + paddd m0, m5 + pshufd m5, m0, q1032 + paddd m0, m5 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq ; ac = ac_orig +.sub_loop: + mova m1, [acq] + psubw m1, m0 + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_444_8bpc, 4, 8, 7, -4*16, ac, y, stride, wpad, hpad, w, h, ac_bak + movddup m2, [pb_4] +%else +cglobal ipred_cfl_ac_444_8bpc, 4, 7, 7, -5*16, ac, y, stride, wpad, hpad, w, h +%define ac_bakq [rsp+16*4] + mov t0d, 0x04040404 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + movifnidn hpadd, hpadm + movd m0, hpadd + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m6, t0d + movd hpadd, m0 + mov ac_bakq, acq + shl hpadd, 2 + sub hd, hpadd + pxor m5, m5 + pxor m4, m4 + cmp wd, 16 + jg .w32 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movd m1, [yq] + movd m3, [yq+strideq] + punpckldq m1, m3 + punpcklbw m1, m1 + movd m0, [yq+strideq*2] + movd m3, [yq+stride3q] + punpckldq m0, m3 + punpcklbw m0, m0 + pmaddubsw m1, m2 + pmaddubsw m0, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m5, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop +.calc_avg_4: + psrlw m2, 10 + pmaddwd m5, m2 + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + movq m1, [yq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + movq m0, [yq+strideq] + punpcklbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + movq m1, [yq+strideq*2] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + movq m0, [yq+stride3q] + punpcklbw m0, m0 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w8_hpad +.w8_wpad: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + movd m0, [yq+strideq] + punpcklbw m0, m0 + punpcklqdq m0, m0 + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + sub hd, 2 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_8_16 +.w8_hpad: + mova [acq], m0 + paddw m5, m0 + mova [acq+16], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad + jmp .calc_avg_8_16 + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + mova m0, [yq+strideq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movd m1, [yq+strideq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhqdq m0, m1, m1 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + movq m1, [yq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + pshufhw m1, m1, q3333 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movq m1, [yq+strideq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + mova m0, m1 + pshufhw m0, m0, q3333 + punpckhqdq m0, m0 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + mova m0, [yq+strideq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg_8_16 +.w16_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m1 + paddw m5, m0 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m1 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop +.calc_avg_8_16: + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, m4 + psrld m0, 16 + pslld m4, 16 + psrld m4, 16 + paddd m0, m4 + paddd m5, m0 + jmp .calc_avg + +.w32: + pxor m0, m0 + mova [rsp ], m0 + mova [rsp+16], m0 + mova [rsp+32], m0 + mova [rsp+48], m0 + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m4, [yq+16] + mova m3, m4 + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + punpckhbw m4, m4 + pmaddubsw m4, m2 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_loop + test hpadd, hpadd + jz .calc_avg_32 + jmp .w32_hpad_loop +.w32_wpad: + cmp wpadd, 2 + jl .w32_pad1 + je .w32_pad2 + cmp wpadd, 4 + jl .w32_pad3 + je .w32_pad4 + cmp wpadd, 6 + jl .w32_pad5 + je .w32_pad6 +.w32_pad7: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + mova m0, m1 + punpckhqdq m0, m0 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad7 + jmp .w32_wpad_done +.w32_pad6: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + pshufhw m0, m1, q3333 + punpckhqdq m0, m0 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad6 + jmp .w32_wpad_done +.w32_pad5: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + mova m5, [rsp] + paddw m5, m1 + mova [rsp ], m5 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + punpckhqdq m3, m3 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad5 + jmp .w32_wpad_done +.w32_pad4: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + pshufhw m3, m3, q3333 + punpckhqdq m3, m3 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad4 + jmp .w32_wpad_done +.w32_pad3: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + movd m3, [yq+16] + punpcklbw m3, m3 + punpcklqdq m3, m3 + pshufhw m3, m3, q3333 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + punpckhqdq m4, m4 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad3 + jmp .w32_wpad_done +.w32_pad2: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, [yq+16] + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + pshufhw m4, m3, q3333 + punpckhqdq m4, m4 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad2 + jmp .w32_wpad_done +.w32_pad1: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m4, [yq+16] + mova m3, m4 + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + punpckhbw m4, m4 + punpcklqdq m4, m4 + pshufhw m4, m4, q3333 + pmaddubsw m4, m2 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad1 +.w32_wpad_done: + test hpadd, hpadd + jz .calc_avg_32 +.w32_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m1, [rsp] + mova [rsp ], m5 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova [acq+32], m3 + mova [acq+48], m4 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + add acq, 64 + sub hpadd, 1 + jg .w32_hpad_loop + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif + +.calc_avg_32: + mova m5, [rsp] + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, [rsp+16] + mova m3, m0 + psrld m0, 16 + pslld m3, 16 + psrld m3, 16 + paddd m0, m3 + paddd m5, m0 + mova m0, [rsp+32] + mova m3, m0 + psrld m0, 16 + pslld m3, 16 + psrld m3, 16 + paddd m0, m3 + mova m1, [rsp+48] + mova m3, m1 + psrld m1, 16 + pslld m3, 16 + psrld m3, 16 + paddd m1, m3 + paddd m1, m0 + paddd m5, m1 +.calc_avg: + movd szd, m6 + psrad m6, 1 + tzcnt r1d, szd ; const int log2sz = ctz(width) + ctz(height); + paddd m5, m6 + movd m1, r1d + pshufd m0, m5, q2301 + paddd m0, m5 + pshufd m5, m0, q1032 + paddd m0, m5 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq ; ac = ac_orig +.sub_loop: + mova m1, [acq] + psubw m1, m0 + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +; %1 simd register that hold the mask and will hold the result +; %2 simd register that holds the "true" values +; %3 location of the "false" values (simd register/memory) +%macro BLEND 3 ; mask, true, false + pand %2, %1 + pandn %1, %3 + por %1, %2 +%endmacro + +%macro PAETH 2 ; top, ldiff + pavgb m1, m%1, m3 + pxor m0, m%1, m3 + pand m0, m4 + psubusb m2, m5, m1 + psubb m1, m0 + psubusb m1, m5 + por m1, m2 + paddusb m1, m1 + por m1, m0 ; min(tldiff, 255) + psubusb m2, m5, m3 + psubusb m0, m3, m5 + por m2, m0 ; tdiff +%ifnum %2 + pminub m2, m%2 + pcmpeqb m0, m%2, m2 ; ldiff <= tdiff +%else + mova m0, %2 + pminub m2, m0 + pcmpeqb m0, m2 +%endif + pminub m1, m2 + pcmpeqb m1, m2 ; ldiff <= tldiff && tdiff <= tldiff + mova m2, m3 + BLEND m0, m2, m%1 + BLEND m1, m0, m5 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 6, 8, -7*16, dst, stride, tl, w, h +%define base r5-ipred_paeth_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + pxor m0, m0 + movd m5, [tlq] + pshufb m5, m0 + LEA r5, ipred_paeth_ssse3_table + movsxd wq, [r5+wq*4] + movddup m4, [base+ipred_paeth_shuf] + add wq, r5 + jmp wq +.w4: + movd m6, [tlq+1] ; top + pshufd m6, m6, q0000 + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + sub tlq, 4 + movd m3, [tlq] + mova m1, [base+ipred_h_shuf] + pshufb m3, m1 ; left + PAETH 6, 7 + movd [dstq ], m1 + pshuflw m0, m1, q1032 + movd [dstq+strideq ], m0 + punpckhqdq m1, m1 + movd [dstq+strideq*2], m1 + psrlq m1, 32 + movd [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + movddup m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + sub tlq, 2 + movd m3, [tlq] + pshufb m3, [base+ipred_paeth_shuf] + PAETH 6, 7 + movq [dstq ], m1 + movhps [dstq+strideq], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + sub tlq, 1 + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + PAETH 6, 7 + mova [dstq], m1 + add dstq, strideq + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp ], m6 + mova [rsp+16], m7 + movu m6, [tlq+17] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+32], m6 +.w32_loop: + dec tlq + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + mova m6, [rsp] + PAETH 6, [rsp+16] + mova [dstq ], m1 + mova m6, [rsp+32] + PAETH 6, 7 + mova [dstq+16], m1 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp ], m6 + mova [rsp+16], m7 + movu m6, [tlq+17] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+32], m6 + mova [rsp+48], m7 + movu m6, [tlq+33] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+64], m6 + mova [rsp+80], m7 + movu m6, [tlq+49] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+96], m6 +.w64_loop: + dec tlq + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + mova m6, [rsp] + PAETH 6, [rsp+16] + mova [dstq ], m1 + mova m6, [rsp+32] + PAETH 6, [rsp+48] + mova [dstq+16], m1 + mova m6, [rsp+64] + PAETH 6, [rsp+80] + mova [dstq+32], m1 + mova m6, [rsp+96] + PAETH 6, 7 + mova [dstq+48], m1 + add dstq, strideq + dec hd + jg .w64_loop + RET + + +%macro FILTER 4 ;dst, src, tmp, shuf +%ifnum %4 + pshufb m%2, m%4 +%else + pshufb m%2, %4 +%endif + pshufd m%1, m%2, q0000 ;p0 p1 + pmaddubsw m%1, m2 + pshufd m%3, m%2, q1111 ;p2 p3 + pmaddubsw m%3, m3 + paddw m%1, [base+pw_8] + paddw m%1, m%3 + pshufd m%3, m%2, q2222 ;p4 p5 + pmaddubsw m%3, m4 + paddw m%1, m%3 + pshufd m%3, m%2, q3333 ;p6 __ + pmaddubsw m%3, m5 + paddw m%1, m%3 + psraw m%1, 4 + packuswb m%1, m%1 +%endmacro + +cglobal ipred_filter_8bpc, 3, 7, 8, dst, stride, tl, w, h, filter +%define base r6-$$ + LEA r6, $$ + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + lea filterq, [base+filter_intra_taps+filterq] + movq m0, [tlq-3] ;_ 6 5 0 1 2 3 4 + movsxd wq, [base+ipred_filter_ssse3_table+wq*4] + mova m2, [filterq+16*0] + mova m3, [filterq+16*1] + mova m4, [filterq+16*2] + mova m5, [filterq+16*3] + lea wq, [base+ipred_filter_ssse3_table+wq] + mov hd, hm + jmp wq +.w4: + mova m1, [base+filter_shuf1] + sub tlq, 3 + sub tlq, hq + jmp .w4_loop_start +.w4_loop: + movd m0, [tlq+hq] + punpckldq m0, m6 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER 6, 0, 7, 1 + movd [dstq+strideq*0], m6 + pshuflw m6, m6, q1032 + movd [dstq+strideq*1], m6 + sub hd, 2 + jg .w4_loop + RET + +ALIGN function_align +.w8: + movq m6, [tlq+1] ;_ _ _ 0 1 2 3 4 + sub tlq, 5 + sub tlq, hq + +.w8_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER 0, 6, 1, [base+filter_shuf2] + + punpckldq m6, m7, m0 + movq [dstq+strideq*0], m6 + punpckhqdq m6, m6 + movq [dstq+strideq*1], m6 + + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET + +ALIGN function_align +.w16: + movu m6, [tlq+1] ;top row + sub tlq, 5 + sub tlq, hq + +.w16_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+4+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+8+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movd [dstq+12+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+strideq*1], m6 + + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET + +ALIGN function_align +.w32: + movu m6, [tlq+1] ;top row + lea filterq, [tlq+17] + sub tlq, 5 + sub tlq, hq + +.w32_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+4+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+8+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movu m1, [filterq] + punpckldq m0, m7, m1 ;_ _ _ 0 1 2 3 4 _ _ _ _ _ _ _ _ + punpcklqdq m0, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+12+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+strideq*1], m6 + + mova m6, m1 + + FILTER 7, 0, 6, [base+filter_shuf2] + punpcklqdq m0, m1, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+16+strideq*0], m7 + psrlq m7, 32 + palignr m7, m1, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+20+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+24+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movd [dstq+28+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+16+strideq*1], m6 + + mova m6, [dstq+strideq*1] + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + lea filterq, [dstq+16+strideq*1] + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5879 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +; dav1d_obmc_masks[] * -512 +const obmc_masks_avx2 + dw 0, 0, -9728, 0, -12800, -7168, -2560, 0 + dw -14336, -11264, -8192, -5632, -3584, -1536, 0, 0 + dw -15360, -13824, -12288, -10752, -9216, -7680, -6144, -5120 + dw -4096, -3072, -2048, -1536, 0, 0, 0, 0 + dw -15872, -14848, -14336, -13312, -12288, -11776, -10752, -10240 + dw -9728, -8704, -8192, -7168, -6656, -6144, -5632, -4608 + dw -4096, -3584, -3072, -2560, -2048, -2048, -1536, -1024 + dw 0, 0, 0, 0, 0, 0, 0, 0 + +deint_shuf: dd 0, 4, 1, 5, 2, 6, 3, 7 +subpel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +subpel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +subpel_h_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +subpel_s_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7 +rescale_mul2: dd 0, 1, 4, 5, 2, 3, 6, 7 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +wswap: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 +bdct_lb_q: times 8 db 0 + times 8 db 4 + times 8 db 8 + times 8 db 12 + +prep_mul: dw 16, 16, 4, 4 +put_bilin_h_rnd: dw 8, 8, 10, 10 +put_8tap_h_rnd: dd 34, 40 +s_8tap_h_rnd: dd 2, 8 +s_8tap_h_sh: dd 2, 4 +put_s_8tap_v_rnd: dd 512, 128 +put_s_8tap_v_sh: dd 10, 8 +prep_8tap_1d_rnd: dd 8 - (8192 << 4) +prep_8tap_2d_rnd: dd 32 - (8192 << 5) +warp8x8t_rnd: dd 16384 - (8192 << 15) +warp8x8_shift: dd 5, 3 +warp8x8_rnd: dw 4096, 4096, 16384, 16384 +bidir_rnd: dw -16400, -16400, -16388, -16388 +bidir_mul: dw 2048, 2048, 8192, 8192 + +%define pw_16 prep_mul +%define pd_512 put_s_8tap_v_rnd + +pw_2: times 2 dw 2 +pw_64: times 2 dw 64 +pw_2048: times 2 dw 2048 +pw_8192: times 2 dw 8192 +pw_27615: times 2 dw 27615 +pw_32766: times 2 dw 32766 +pw_m512: times 2 dw -512 +pd_32: dd 32 +pd_63: dd 63 +pd_64: dd 64 +pd_32768: dd 32768 +pd_65538: dd 65538 +pd_m524256: dd -524256 ; -8192 << 6 + 32 +pd_0x3ff: dd 0x3ff +pq_0x40000000: dq 0x40000000 + dd 0 + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx2, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx2, 2, 4, 8, 16, 32, 64, 128 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx2 mangle(private_prefix %+ _put_bilin_16bpc_avx2.put) +%xdefine prep_avx2 mangle(private_prefix %+ _prep_bilin_16bpc_avx2.prep) + +BASE_JMP_TABLE put, avx2, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx2, 4, 8, 16, 32, 64, 128 + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_16bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +HV_JMP_TABLE put, bilin, avx2, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx2, 7, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_16bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 + %%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 + %%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, avx2, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, avx2, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern resize_filter + +SECTION .text + +INIT_XMM avx2 +cglobal put_bilin_16bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + mov mxyd, r6m ; mx + lea r7, [put_avx2] +%if UNIX64 + DECLARE_REG_TMP 8 + %define org_w r8d + mov r8d, wd +%else + DECLARE_REG_TMP 7 + %define org_w wm +%endif + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +INIT_YMM avx2 +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*0+32*1], m1 + mova [dstq+dsq*1+32*0], m2 + mova [dstq+dsq*1+32*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + add srcq, ssq + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + movu m0, [srcq+32*4] + movu m1, [srcq+32*5] + movu m2, [srcq+32*6] + movu m3, [srcq+32*7] + add srcq, ssq + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + movd xm5, mxyd + mov mxyd, r7m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + mov r6d, r8m ; bitdepth_max + add wq, r7 + shr r6d, 11 + vpbroadcastd m3, [r7-put_avx2+put_bilin_h_rnd+r6*4] + jmp wq +.h_w2: + movq xm1, [srcq+ssq*0] + movhps xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw xm0, xm4, xm1 + psrlq xm1, 16 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 4 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + movq xm1, [srcq+ssq*0+2] + movhps xm1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw xm0, xm4 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 4 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti128 m0, [srcq+ssq*1], 1 + movu xm1, [srcq+ssq*0+2] + vinserti128 m1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + pmullw m0, m4, [srcq+ssq*0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+ssq*1] + pmullw m2, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m5, [srcq+32*0+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+32*1] + pmullw m2, m5, [srcq+32*1+2] + add srcq, ssq + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: +.h_w128: + movifnidn t0d, org_w +.h_w64_loop0: + mov r6d, t0d +.h_w64_loop: + pmullw m0, m4, [srcq+r6*2-32*1] + pmullw m1, m5, [srcq+r6*2-32*1+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+r6*2-32*2] + pmullw m2, m5, [srcq+r6*2-32*2+2] + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+r6*2-32*1], m0 + mova [dstq+r6*2-32*2], m1 + sub r6d, 32 + jg .h_w64_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w64_loop0 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + shl mxyd, 11 + movd xm5, mxyd + add wq, r7 + vpbroadcastw m5, xm5 + jmp wq +.v_w2: + movd xm0, [srcq+ssq*0] +.v_w2_loop: + movd xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq xm2, xm0, xm1 + movd xm0, [srcq+ssq*0] + punpckldq xm1, xm0 + psubw xm1, xm2 + pmulhrsw xm1, xm5 + paddw xm1, xm2 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xm0, [srcq+ssq*0] +.v_w4_loop: + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq xm2, xm0, xm1 + movq xm0, [srcq+ssq*0] + punpcklqdq xm1, xm0 + psubw xm1, xm2 + pmulhrsw xm1, xm5 + paddw xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu xm0, [srcq+ssq*0] +.v_w8_loop: + vbroadcasti128 m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m2, m0, m1, 0xf0 + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m1, m0, 0xf0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w32: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] +.v_w32_loop: + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + psubw m4, m2, m0 + pmulhrsw m4, m5 + paddw m4, m0 + movu m0, [srcq+ssq*0+32*0] + mova [dstq+dsq*0+32*0], m4 + psubw m4, m3, m1 + pmulhrsw m4, m5 + paddw m4, m1 + movu m1, [srcq+ssq*0+32*1] + mova [dstq+dsq*0+32*1], m4 + psubw m4, m0, m2 + pmulhrsw m4, m5 + paddw m4, m2 + mova [dstq+dsq*1+32*0], m4 + psubw m4, m1, m3 + pmulhrsw m4, m5 + paddw m4, m3 + mova [dstq+dsq*1+32*1], m4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w16: +.v_w64: +.v_w128: + movifnidn t0d, org_w + add t0d, t0d + mov r4, srcq + lea r6d, [hq+t0*8-256] + mov r7, dstq +.v_w16_loop0: + movu m0, [srcq+ssq*0] +.v_w16_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m5 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m5 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 + vpbroadcastd m3, [pw_2] + movd xm6, mxyd + vpbroadcastd m7, [pw_8192] + add wq, r7 + vpbroadcastw m6, xm6 + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + vpbroadcastd m7, [pw_2048] +.hv_12bpc: + jmp wq +.hv_w2: + vpbroadcastq xm1, [srcq+ssq*0] + pmullw xm0, xm4, xm1 + psrlq xm1, 16 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 +.hv_w2_loop: + movq xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm2, [srcq+ssq*0] + pmullw xm1, xm4, xm2 + psrlq xm2, 16 + pmullw xm2, xm5 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 ; 1 _ 2 _ + shufpd xm2, xm0, xm1, 0x01 ; 0 _ 1 _ + mova xm0, xm1 + psubw xm1, xm2 + paddw xm1, xm1 + pmulhw xm1, xm6 + paddw xm1, xm2 + pmulhrsw xm1, xm7 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + pmullw xm0, xm4, [srcq+ssq*0-8] + pmullw xm1, xm5, [srcq+ssq*0-6] + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 +.hv_w4_loop: + movq xm1, [srcq+ssq*1] + movq xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps xm1, [srcq+ssq*0] + movhps xm2, [srcq+ssq*0+2] + pmullw xm1, xm4 + pmullw xm2, xm5 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 ; 1 2 + shufpd xm2, xm0, xm1, 0x01 ; 0 1 + mova xm0, xm1 + psubw xm1, xm2 + paddw xm1, xm1 + pmulhw xm1, xm6 + paddw xm1, xm2 + pmulhrsw xm1, xm7 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xm0, xm4, [srcq+ssq*0] + pmullw xm1, xm5, [srcq+ssq*0+2] + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 + vinserti128 m0, xm0, 1 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti128 m1, [srcq+ssq*0], 1 + vinserti128 m2, [srcq+ssq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +.hv_w32: +.hv_w64: +.hv_w128: +%if UNIX64 + lea r6d, [r8*2-32] +%else + mov r6d, wm + lea r6d, [r6*2-32] +%endif + mov r4, srcq + lea r6d, [hq+r6*8] + mov r7, dstq +.hv_w16_loop0: + pmullw m0, m4, [srcq+ssq*0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w16_loop: + pmullw m1, m4, [srcq+ssq*1] + pmullw m2, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 + psubw m2, m1, m0 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m0 + pmulhrsw m2, m7 + mova [dstq+dsq*0], m2 + pmullw m0, m4, [srcq+ssq*0] + pmullw m2, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m1 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m1 + pmulhrsw m2, m7 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w16_loop0 + RET + +cglobal prep_bilin_16bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep_avx2] +%if UNIX64 + DECLARE_REG_TMP 7 + %define org_w r7d +%else + DECLARE_REG_TMP 6 + %define org_w r5m +%endif + mov org_w, wd + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [r6-prep_avx2+pw_8192] + add wq, r6 + shr r5d, 11 + vpbroadcastd m4, [r6-prep_avx2+prep_mul+r5*4] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + vpbroadcastq m1, [srcq+strideq*2] + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + pmullw m0, m4 + psubw m0, m5 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*2] + vinserti128 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m4, [srcq+strideq*2] + pmullw m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmullw m0, m4, [srcq+strideq*0+32*0] + pmullw m1, m4, [srcq+strideq*0+32*1] + pmullw m2, m4, [srcq+strideq*1+32*0] + pmullw m3, m4, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .prep_w32 + RET +.prep_w64: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m4, [srcq+32*1] + pmullw m2, m4, [srcq+32*2] + pmullw m3, m4, [srcq+32*3] + add srcq, strideq + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .prep_w64 + RET +.prep_w128: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m4, [srcq+32*1] + pmullw m2, m4, [srcq+32*2] + pmullw m3, m4, [srcq+32*3] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + pmullw m0, m4, [srcq+32*4] + pmullw m1, m4, [srcq+32*5] + pmullw m2, m4, [srcq+32*6] + pmullw m3, m4, [srcq+32*7] + add tmpq, 32*8 + add srcq, strideq + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .prep_w128 + RET +.h: + movd xm5, mxyd + mov mxyd, r6m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + vpbroadcastd m3, [pw_32766] + psubw m4, m5 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m4, 2 + psllw m5, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti128 m2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq m0, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + pmullw m0, m4 + vpblendd m1, m2, 0xcc + pmullw m1, m5 + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*0+2] + vinserti128 m1, [srcq+strideq*1+2], 1 + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m5, [srcq+strideq*0+2] + psubw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m1, m3 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 2 + jg .h_w16 + RET +.h_w32: +.h_w64: +.h_w128: + movifnidn t0d, org_w +.h_w32_loop0: + mov r3d, t0d +.h_w32_loop: + pmullw m0, m4, [srcq+r3*2-32*1] + pmullw m1, m5, [srcq+r3*2-32*1+2] + psubw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+r3*2-32*2] + pmullw m2, m5, [srcq+r3*2-32*2+2] + psubw m1, m3 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+r3*2-32*1], m0 + mova [tmpq+r3*2-32*2], m1 + sub r3d, 32 + jg .h_w32_loop + add srcq, strideq + lea tmpq, [tmpq+t0*2] + dec hd + jg .h_w32_loop0 + RET +.v: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + movd xm5, mxyd + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + vpbroadcastd m3, [pw_32766] + add wq, r6 + lea stride3q, [strideq*3] + psubw m4, m5 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m4, 2 + psllw m5, 2 +.v_12bpc: + jmp wq +.v_w4: + movq xm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq xm1, [srcq+strideq*1] + vpblendd m2, m0, 0x03 ; 0 2 2 2 + vpbroadcastq m0, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0xf0 ; 1 1 3 3 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m1, m2, 0x33 ; 0 1 2 3 + vpblendd m0, m2, 0x0c ; 4 2 4 4 + punpckhqdq m2, m1, m0 ; 1 2 3 4 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movu xm0, [srcq+strideq*0] +.v_w8_loop: + vbroadcasti128 m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m1, m0, m2, 0xf0 ; 0 1 + vbroadcasti128 m0, [srcq+strideq*0] + vpblendd m2, m0, 0xf0 ; 1 2 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5, m2 + psubw m0, m3 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m4 + mova [tmpq+32*0], m1 + pmullw m1, m5, m0 + psubw m2, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + PUSH r7 +%endif + movifnidn r7d, org_w + add r7d, r7d + mov r3, srcq + lea r6d, [hq+r7*8-256] + mov r5, tmpq +.v_w32_loop0: + movu m0, [srcq+strideq*0] +.v_w32_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5, m2 + psubw m0, m3 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m4 + mova [tmpq+r7*0], m1 + pmullw m1, m5, m0 + psubw m2, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+r7*1], m1 + lea tmpq, [tmpq+r7*2] + sub hd, 2 + jg .v_w32_loop + add r3, 32 + add r5, 32 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .v_w32_loop0 +%if WIN64 + POP r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + movd xm6, mxyd + add wq, r6 + lea stride3q, [strideq*3] + vpbroadcastw m6, xm6 + jmp wq +.hv_w4: + movu xm1, [srcq+strideq*0] +%if WIN64 + movaps [rsp+24], xmm7 +%endif + pmullw xm0, xm4, xm1 + psrldq xm1, 2 + pmullw xm1, xm5 + psubw xm0, xm3 + paddw xm0, xm1 + psraw xm0, 2 + vpbroadcastq m0, xm0 +.hv_w4_loop: + movu xm1, [srcq+strideq*1] + vinserti128 m1, [srcq+stride3q ], 1 + movu xm2, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vinserti128 m2, [srcq+strideq*0], 1 + punpcklqdq m7, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + pmullw m7, m4 + vpblendd m1, m2, 0xcc + pmullw m1, m5 + psubw m7, m3 + paddw m1, m7 + psraw m1, 2 ; 1 2 3 4 + vpblendd m0, m1, 0x3f + vpermq m2, m0, q2103 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop +%if WIN64 + movaps xmm7, [rsp+24] +%endif + RET +.hv_w8: + pmullw xm0, xm4, [srcq+strideq*0] + pmullw xm1, xm5, [srcq+strideq*0+2] + psubw xm0, xm3 + paddw xm0, xm1 + psraw xm0, 2 + vinserti128 m0, xm0, 1 +.hv_w8_loop: + movu xm1, [srcq+strideq*1] + movu xm2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + vinserti128 m1, [srcq+strideq*0], 1 + vinserti128 m2, [srcq+strideq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +.hv_w32: +.hv_w64: +.hv_w128: +%if WIN64 + PUSH r7 +%endif + movifnidn r7d, org_w + add r7d, r7d + mov r3, srcq + lea r6d, [hq+r7*8-256] + mov r5, tmpq +.hv_w16_loop0: + pmullw m0, m4, [srcq] + pmullw m1, m5, [srcq+2] + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 +.hv_w16_loop: + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+r7*0], m2 + pmullw m0, m4, [srcq+strideq*0] + pmullw m2, m5, [srcq+strideq*0+2] + psubw m0, m3 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+r7*1], m2 + lea tmpq, [tmpq+r7*2] + sub hd, 2 + jg .hv_w16_loop + add r3, 32 + add r5, 32 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .hv_w16_loop0 +%if WIN64 + POP r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_16bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my +%define base r8-put_avx2 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx2] + movifnidn wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 +%if WIN64 + pop r8 +%endif + jmp wq +.h_w2: + movzx mxd, mxb + sub srcq, 2 + mova xm2, [subpel_h_shuf2] + vpbroadcastd xm3, [base+subpel_filters+mxq*8+2] + pmovsxbw xm3, xm3 +.h_w2_loop: + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm2 + pshufb xm1, xm2 + pmaddwd xm0, xm3 + pmaddwd xm1, xm3 + phaddd xm0, xm1 + paddd xm0, xm4 + psrad xm0, 6 + packusdw xm0, xm0 + pminsw xm0, xm5 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xm3, [base+subpel_filters+mxq*8] + WIN64_SPILL_XMM 8 + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + pshufd xm3, xm3, q2211 + vpbroadcastq m2, xm3 + vpermq m3, m3, q1111 +.h_w4_loop: + movu xm1, [srcq+ssq*0] + vinserti128 m1, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m1, m6 ; 0 1 1 2 2 3 3 4 + pshufb m1, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m2 + pmaddwd m1, m3 + paddd m0, m4 + paddd m0, m1 + psrad m0, 6 + vextracti128 xm1, m0, 1 + packusdw xm0, xm1 + pminsw xm0, xm5 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + mov r7d, r8m + vpbroadcastw m5, r8m + shr r7d, 11 + vpbroadcastd m4, [base+put_8tap_h_rnd+r7*4] + cmp wd, 4 + je .h_w4 + jl .h_w2 + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 13 + shr mxd, 16 + sub srcq, 6 + vpbroadcastq m0, [base+subpel_filters+mxq*8] + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 8 + jg .h_w16 +.h_w8: +%macro PUT_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2] + pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m6 ; 0 1 1 2 2 3 3 4 + pmaddwd m%5, m9, m%4 ; abcd1 + pmaddwd m%1, m8 ; abcd0 + pshufb m%2, m7 ; 6 7 7 8 8 9 9 a + shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m%5, m4 + paddd m%1, m%5 + pmaddwd m%5, m11, m%2 ; abcd3 + paddd m%1, m%5 + pmaddwd m%5, m10, m%4 ; abcd2 + pshufb m%3, m7 ; a b b c c d d e + pmaddwd m%4, m8 ; efgh0 + paddd m%1, m%5 + pmaddwd m%5, m9, m%2 ; efgh1 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m11 ; efgh3 + pmaddwd m%2, m10 ; efgh2 + paddd m%4, m4 + paddd m%4, m%5 + paddd m%3, m%4 + paddd m%2, m%3 + psrad m%1, 6 + psrad m%2, 6 + packusdw m%1, m%2 + pminsw m%1, m5 +%endmacro + movu xm0, [srcq+ssq*0+ 0] + vinserti128 m0, [srcq+ssq*1+ 0], 1 + movu xm2, [srcq+ssq*0+16] + vinserti128 m2, [srcq+ssq*1+16], 1 + lea srcq, [srcq+ssq*2] + shufpd m1, m0, m2, 0x05 + PUT_8TAP_H 0, 1, 2, 3, 12 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mov r6d, wd +.h_w16_loop: + movu m0, [srcq+r6*2-32] + movu m1, [srcq+r6*2-24] + movu m2, [srcq+r6*2-16] + PUT_8TAP_H 0, 1, 2, 3, 12 + mova [dstq+r6*2-32], m0 + sub r6d, 16 + jg .h_w16_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w16 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m0, [base+subpel_filters+myq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastd m6, [pd_32] + vpbroadcastw m7, r8m + lea r6, [ssq*3] + sub srcq, r6 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 4 + jg .v_w8 + je .v_w4 +.v_w2: + movd xm2, [srcq+ssq*0] + pinsrd xm2, [srcq+ssq*1], 1 + pinsrd xm2, [srcq+ssq*2], 2 + pinsrd xm2, [srcq+r6 ], 3 ; 0 1 2 3 + lea srcq, [srcq+ssq*4] + movd xm3, [srcq+ssq*0] + vpbroadcastd xm1, [srcq+ssq*1] + vpbroadcastd xm0, [srcq+ssq*2] + add srcq, r6 + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklwd xm3, xm1 ; 45 56 + punpcklwd xm1, xm2, xm4 ; 01 12 + punpckhwd xm2, xm4 ; 23 34 +.v_w2_loop: + vpbroadcastd xm4, [srcq+ssq*0] + pmaddwd xm5, xm8, xm1 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm9 ; a1 b1 + paddd xm5, xm6 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm10 ; a2 b2 + paddd xm5, xm3 + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklwd xm3, xm4 ; 67 78 + pmaddwd xm4, xm11, xm3 ; a3 b3 + paddd xm5, xm4 + psrad xm5, 6 + packusdw xm5, xm5 + pminsw xm5, xm7 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xm1, [srcq+ssq*0] + vpbroadcastq m0, [srcq+ssq*1] + vpbroadcastq m2, [srcq+ssq*2] + vpbroadcastq m4, [srcq+r6 ] + lea srcq, [srcq+ssq*4] + vpbroadcastq m3, [srcq+ssq*0] + vpbroadcastq m5, [srcq+ssq*1] + vpblendd m1, m0, 0x30 + vpblendd m0, m2, 0x30 + punpcklwd m1, m0 ; 01 12 + vpbroadcastq m0, [srcq+ssq*2] + add srcq, r6 + vpblendd m2, m4, 0x30 + vpblendd m4, m3, 0x30 + punpcklwd m2, m4 ; 23 34 + vpblendd m3, m5, 0x30 + vpblendd m5, m0, 0x30 + punpcklwd m3, m5 ; 45 56 +.v_w4_loop: + vpbroadcastq m4, [srcq+ssq*0] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m6 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m4, m0, 0x30 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 6 + vextracti128 xm4, m5, 1 + packusdw xm5, xm4 + pminsw xm5, xm7 + movq [dstq+dsq*0], xm5 + movhps [dstq+dsq*1], xm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + shl wd, 5 + mov r7, srcq + mov r8, dstq + lea wd, [hq+wq-256] +.v_w8_loop0: + vbroadcasti128 m4, [srcq+ssq*0] + vbroadcasti128 m5, [srcq+ssq*1] + vbroadcasti128 m0, [srcq+r6 ] + vbroadcasti128 m6, [srcq+ssq*2] + lea srcq, [srcq+ssq*4] + vbroadcasti128 m1, [srcq+ssq*0] + vbroadcasti128 m2, [srcq+ssq*1] + vbroadcasti128 m3, [srcq+ssq*2] + add srcq, r6 + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklwd m3, m6, m0 ; 23 + punpckhwd m6, m0 ; 56 +.v_w8_loop: + vbroadcasti128 m14, [srcq+ssq*0] + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + vbroadcasti128 m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + paddd m13, m6 + shufpd m6, m0, m14, 0x0d + shufpd m0, m14, m5, 0x0c + punpcklwd m5, m6, m0 ; 67 + punpckhwd m6, m0 ; 78 + pmaddwd m14, m11, m5 ; a3 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 5 + psrad m13, 5 + packusdw m12, m13 + pxor m13, m13 + pavgw m12, m13 + pminsw m12, m7 + vpermq m12, m12, q3120 + mova [dstq+dsq*0], xm12 + vextracti128 [dstq+dsq*1], m12, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + add r7, 16 + add r8, 16 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .v_w8_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vpbroadcastw m15, r8m + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + vpbroadcastd m0, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m1, [base+subpel_filters+myq*8] + vpbroadcastd m6, [pd_512] + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m1, m1 + psraw m1, 8 ; sign-extend + test dword r8m, 0x800 + jz .hv_10bit + psraw m7, 2 + psllw m1, 2 +.hv_10bit: + pshufd m11, m1, q0000 + pshufd m12, m1, q1111 + pshufd m13, m1, q2222 + pshufd m14, m1, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 m9, [subpel_h_shuf2] + vbroadcasti128 m1, [srcq+r6 ] ; 3 3 + movu xm3, [srcq+ssq*2] + movu xm0, [srcq+ssq*0] + movu xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*4] + vinserti128 m3, [srcq+ssq*0], 1 ; 2 4 + vinserti128 m0, [srcq+ssq*1], 1 ; 0 5 + vinserti128 m2, [srcq+ssq*2], 1 ; 1 6 + add srcq, r6 + pshufb m1, m9 + pshufb m3, m9 + pshufb m0, m9 + pshufb m2, m9 + pmaddwd m1, m7 + pmaddwd m3, m7 + pmaddwd m0, m7 + pmaddwd m2, m7 + phaddd m1, m3 + phaddd m0, m2 + paddd m1, m6 + paddd m0, m6 + psrad m1, 10 + psrad m0, 10 + packssdw m1, m0 ; 3 2 0 1 + vextracti128 xm0, m1, 1 ; 3 4 5 6 + pshufd xm2, xm1, q1301 ; 2 3 1 2 + pshufd xm3, xm0, q2121 ; 4 5 4 5 + punpckhwd xm1, xm2 ; 01 12 + punpcklwd xm2, xm0 ; 23 34 + punpckhwd xm3, xm0 ; 45 56 +.hv_w2_loop: + movu xm4, [srcq+ssq*0] + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm4, xm9 + pshufb xm5, xm9 + pmaddwd xm4, xm7 + pmaddwd xm5, xm7 + phaddd xm4, xm5 + pmaddwd xm5, xm11, xm1 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm12 ; a1 b1 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm13 ; a2 b2 + paddd xm5, xm3 + paddd xm4, xm6 + psrad xm4, 10 + packssdw xm4, xm4 + palignr xm3, xm4, xm0, 12 + mova xm0, xm4 + punpcklwd xm3, xm0 ; 67 78 + pmaddwd xm4, xm14, xm3 ; a3 b3 + paddd xm5, xm6 + paddd xm5, xm4 + psrad xm5, 10 + packusdw xm5, xm5 + pminsw xm5, xm15 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + vbroadcasti128 m9, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + pshufd m8, m7, q1111 + pshufd m7, m7, q0000 + movu xm1, [srcq+ssq*0] + vinserti128 m1, [srcq+ssq*1], 1 ; 0 1 + vbroadcasti128 m0, [srcq+r6 ] + vinserti128 m2, m0, [srcq+ssq*2], 0 ; 2 3 + lea srcq, [srcq+ssq*4] + vinserti128 m0, [srcq+ssq*0], 1 ; 3 4 + movu xm3, [srcq+ssq*1] + vinserti128 m3, [srcq+ssq*2], 1 ; 5 6 + add srcq, r6 + pshufb m4, m1, m9 + pshufb m1, m10 + pmaddwd m4, m7 + pmaddwd m1, m8 + pshufb m5, m2, m9 + pshufb m2, m10 + pmaddwd m5, m7 + pmaddwd m2, m8 + paddd m4, m6 + paddd m1, m4 + pshufb m4, m0, m9 + pshufb m0, m10 + pmaddwd m4, m7 + pmaddwd m0, m8 + paddd m5, m6 + paddd m2, m5 + pshufb m5, m3, m9 + pshufb m3, m10 + pmaddwd m5, m7 + pmaddwd m3, m8 + paddd m4, m6 + paddd m4, m0 + paddd m5, m6 + paddd m5, m3 + vperm2i128 m0, m1, m2, 0x21 + psrld m1, 10 + psrld m2, 10 + vperm2i128 m3, m4, m5, 0x21 + pslld m4, 6 + pslld m5, 6 + pblendw m2, m4, 0xaa ; 23 34 + pslld m0, 6 + pblendw m1, m0, 0xaa ; 01 12 + psrld m3, 10 + pblendw m3, m5, 0xaa ; 45 56 + psrad m0, m5, 16 +.hv_w4_loop: + movu xm4, [srcq+ssq*0] + vinserti128 m4, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m6 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + pshufb m3, m4, m9 + pshufb m4, m10 + pmaddwd m3, m7 + pmaddwd m4, m8 + paddd m3, m6 + paddd m4, m3 + psrad m4, 10 + packssdw m0, m4 ; _ 7 6 8 + vpermq m3, m0, q1122 ; _ 6 _ 7 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m4, m5 + psrad m4, 10 + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, xm15 + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + vpbroadcastq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + pmovsxbw xm1, [base+subpel_filters+myq*8] + shl wd, 5 + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + pxor m0, m0 + punpcklbw m0, m2 + mov r7, srcq + mov r8, dstq + lea wd, [hq+wq-256] + test dword r8m, 0x800 + jz .hv_w8_10bit + psraw m0, 2 + psllw xm1, 2 +.hv_w8_10bit: + pshufd m11, m0, q0000 + pshufd m12, m0, q1111 + pshufd m13, m0, q2222 + pshufd m14, m0, q3333 +%if WIN64 + %define v_mul (rsp+stack_offset+40) ; r4m +%else + %define v_mul (rsp-24) ; red zone +%endif + mova [v_mul], xm1 +.hv_w8_loop0: +%macro PUT_8TAP_HV_H 3 ; dst/src+0, src+8, src+16 + pshufb m2, m%1, m9 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m8 ; 0 1 1 2 2 3 3 4 + pmaddwd m3, m12, m2 + pmaddwd m%1, m11 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + shufpd m2, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m3, m10 + paddd m%1, m3 + pmaddwd m3, m14, m%2 + paddd m%1, m3 + pmaddwd m3, m13, m2 + pshufb m%3, m9 ; a b b c c d d e + pmaddwd m2, m11 + paddd m%1, m3 + pmaddwd m3, m12, m%2 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m14 + pmaddwd m%2, m13 + paddd m2, m10 + paddd m2, m3 + paddd m%3, m2 + paddd m%2, m%3 + psrad m%1, 10 + psrad m%2, 10 + packssdw m%1, m%2 +%endmacro + movu xm4, [srcq+r6 *1+ 0] + vbroadcasti128 m8, [subpel_h_shufA] + movu xm6, [srcq+r6 *1+ 8] + vbroadcasti128 m9, [subpel_h_shufB] + movu xm0, [srcq+r6 *1+16] + vpbroadcastd m10, [pd_512] + movu xm5, [srcq+ssq*0+ 0] + vinserti128 m5, [srcq+ssq*4+ 0], 1 + movu xm1, [srcq+ssq*0+16] + vinserti128 m1, [srcq+ssq*4+16], 1 + shufpd m7, m5, m1, 0x05 + INIT_XMM avx2 + PUT_8TAP_HV_H 4, 6, 0 ; 3 + INIT_YMM avx2 + PUT_8TAP_HV_H 5, 7, 1 ; 0 4 + movu xm0, [srcq+ssq*2+ 0] + vinserti128 m0, [srcq+r6 *2+ 0], 1 + movu xm1, [srcq+ssq*2+16] + vinserti128 m1, [srcq+r6 *2+16], 1 + shufpd m7, m0, m1, 0x05 + PUT_8TAP_HV_H 0, 7, 1 ; 2 6 + movu xm6, [srcq+ssq*1+ 0] + movu xm1, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*4] + vinserti128 m6, [srcq+ssq*1+ 0], 1 + vinserti128 m1, [srcq+ssq*1+16], 1 + add srcq, r6 + shufpd m7, m6, m1, 0x05 + PUT_8TAP_HV_H 6, 7, 1 ; 1 5 + vpermq m4, m4, q1100 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + vpermq m7, m0, q3120 + punpcklwd m3, m7, m4 ; 23 + punpckhwd m4, m5 ; 34 + punpcklwd m1, m5, m6 ; 01 + punpckhwd m5, m6 ; 45 + punpcklwd m2, m6, m7 ; 12 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vpbroadcastd m9, [v_mul+4*0] + vpbroadcastd m7, [v_mul+4*1] + vpbroadcastd m10, [v_mul+4*2] + pmaddwd m8, m9, m1 ; a0 + pmaddwd m9, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m7 ; a1 + pmaddwd m4, m7 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m8, m5 + paddd m9, m6 + movu xm5, [srcq+ssq*0] + vinserti128 m5, [srcq+ssq*1], 1 + vbroadcasti128 m7, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + movu xm6, [srcq+ssq*0+16] + vinserti128 m6, [srcq+ssq*1+16], 1 + vextracti128 [dstq], m0, 1 + pshufb m0, m5, m7 ; 01 + pshufb m5, m10 ; 23 + pmaddwd m0, m11 + pmaddwd m5, m12 + paddd m0, m5 + pshufb m5, m6, m7 ; 89 + pshufb m6, m10 ; ab + pmaddwd m5, m13 + pmaddwd m6, m14 + paddd m6, m5 + movu xm5, [srcq+ssq*0+8] + vinserti128 m5, [srcq+ssq*1+8], 1 + lea srcq, [srcq+ssq*2] + pshufb m7, m5, m7 + pshufb m5, m10 + pmaddwd m10, m13, m7 + pmaddwd m7, m11 + paddd m0, m10 + vpbroadcastd m10, [pd_512] + paddd m6, m7 + pmaddwd m7, m14, m5 + pmaddwd m5, m12 + paddd m0, m7 + paddd m5, m6 + vbroadcasti128 m6, [dstq] + paddd m8, m10 + paddd m9, m10 + paddd m0, m10 + paddd m5, m10 + vpbroadcastd m10, [v_mul+4*3] + psrad m0, 10 + psrad m5, 10 + packssdw m0, m5 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m10, m5 ; a3 + pmaddwd m10, m6 ; b3 + paddd m7, m8 + paddd m9, m10 + psrad m7, 10 + psrad m9, 10 + packusdw m7, m9 + pminsw m7, m15 + vpermq m7, m7, q3120 + mova [dstq+dsq*0], xm7 + vextracti128 [dstq+dsq*1], m7, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + add r7, 16 + add r8, 16 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .hv_w8_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my +%define base r7-prep_avx2 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx2] + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov r6d, r7m ; bitdepth_max + movzx wd, word [r7+wq*2+table_offset(prep,)] + vpbroadcastd m5, [r7-prep_avx2+pw_8192] + shr r6d, 11 + add wq, r7 + vpbroadcastd m4, [base+prep_mul+r6*4] + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xm0, [base+subpel_filters+mxq*8] + vbroadcasti128 m3, [subpel_h_shufA] + vbroadcasti128 m4, [subpel_h_shufB] + WIN64_SPILL_XMM 8 + pshufd xm0, xm0, q2211 + test dword r7m, 0x800 + jnz .h_w4_12bpc + psllw xm0, 2 +.h_w4_12bpc: + vpbroadcastq m6, xm0 + vpermq m7, m0, q1111 +.h_w4_loop: + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti128 m2, [srcq+r6 ], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m1, m3 ; 0 1 1 2 2 3 3 4 + pshufb m1, m4 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m6 + pmaddwd m1, m7 + paddd m0, m5 + paddd m0, m1 + pshufb m1, m2, m3 + pshufb m2, m4 + pmaddwd m1, m6 + pmaddwd m2, m7 + paddd m1, m5 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [prep_8tap_1d_rnd] ; 8 - (8192 << 4) + lea r6, [strideq*3] + cmp wd, 4 + je .h_w4 + shr mxd, 16 + sub srcq, 6 + vpbroadcastq m0, [base+subpel_filters+mxq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + test dword r7m, 0x800 + jnz .h_12bpc + psllw m0, 2 +.h_12bpc: + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 8 + jg .h_w16 +.h_w8: +%macro PREP_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2] + pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m6 ; 0 1 1 2 2 3 3 4 + pmaddwd m%5, m9, m%4 ; abcd1 + pmaddwd m%1, m8 ; abcd0 + pshufb m%2, m7 ; 6 7 7 8 8 9 9 a + shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m%5, m5 + paddd m%1, m%5 + pmaddwd m%5, m11, m%2 ; abcd3 + paddd m%1, m%5 + pmaddwd m%5, m10, m%4 ; abcd2 + pshufb m%3, m7 ; a b b c c d d e + pmaddwd m%4, m8 ; efgh0 + paddd m%1, m%5 + pmaddwd m%5, m9, m%2 ; efgh1 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m11 ; efgh3 + pmaddwd m%2, m10 ; efgh2 + paddd m%4, m5 + paddd m%4, m%5 + paddd m%3, m%4 + paddd m%2, m%3 + psrad m%1, 4 + psrad m%2, 4 + packssdw m%1, m%2 +%endmacro + movu xm0, [srcq+strideq*0+ 0] + vinserti128 m0, [srcq+strideq*1+ 0], 1 + movu xm2, [srcq+strideq*0+16] + vinserti128 m2, [srcq+strideq*1+16], 1 + lea srcq, [srcq+strideq*2] + shufpd m1, m0, m2, 0x05 + PREP_8TAP_H 0, 1, 2, 3, 4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + add wd, wd +.h_w16_loop0: + mov r6d, wd +.h_w16_loop: + movu m0, [srcq+r6-32] + movu m1, [srcq+r6-24] + movu m2, [srcq+r6-16] + PREP_8TAP_H 0, 1, 2, 3, 4 + mova [tmpq+r6-32], m0 + sub r6d, 32 + jg .h_w16_loop + add srcq, strideq + add tmpq, wq + dec hd + jg .h_w16_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m0, [base+subpel_filters+myq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastd m7, [prep_8tap_1d_rnd] + lea r6, [strideq*3] + sub srcq, r6 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + test dword r7m, 0x800 + jnz .v_12bpc + psllw m0, 2 +.v_12bpc: + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 4 + jg .v_w8 +.v_w4: + movq xm1, [srcq+strideq*0] + vpbroadcastq m0, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m4, [srcq+r6 ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + vpblendd m1, m0, 0x30 + vpblendd m0, m2, 0x30 + punpcklwd m1, m0 ; 01 12 + vpbroadcastq m0, [srcq+strideq*2] + add srcq, r6 + vpblendd m2, m4, 0x30 + vpblendd m4, m3, 0x30 + punpcklwd m2, m4 ; 23 34 + vpblendd m3, m5, 0x30 + vpblendd m5, m0, 0x30 + punpcklwd m3, m5 ; 45 56 +.v_w4_loop: + vpbroadcastq m4, [srcq+strideq*0] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m7 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m4, m0, 0x30 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 4 + vextracti128 xm4, m5, 1 + packssdw xm5, xm4 + mova [tmpq], xm5 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: +%if WIN64 + push r8 +%endif + mov r8d, wd + shl wd, 5 + mov r5, srcq + mov r7, tmpq + lea wd, [hq+wq-256] +.v_w8_loop0: + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + vbroadcasti128 m0, [srcq+r6 ] + vbroadcasti128 m6, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m1, [srcq+strideq*0] + vbroadcasti128 m2, [srcq+strideq*1] + vbroadcasti128 m3, [srcq+strideq*2] + add srcq, r6 + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklwd m3, m6, m0 ; 23 + punpckhwd m6, m0 ; 56 +.v_w8_loop: + vbroadcasti128 m14, [srcq+strideq*0] + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m7 + paddd m13, m7 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + vbroadcasti128 m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + paddd m13, m6 + shufpd m6, m0, m14, 0x0d + shufpd m0, m14, m5, 0x0c + punpcklwd m5, m6, m0 ; 67 + punpckhwd m6, m0 ; 78 + pmaddwd m14, m11, m5 ; a3 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 4 + psrad m13, 4 + packssdw m12, m13 + vpermq m12, m12, q3120 + mova [tmpq+r8*0], xm12 + vextracti128 [tmpq+r8*2], m12, 1 + lea tmpq, [tmpq+r8*4] + sub hd, 2 + jg .v_w8_loop + add r5, 16 + add r7, 16 + movzx hd, wb + mov srcq, r5 + mov tmpq, r7 + sub wd, 1<<8 + jg .v_w8_loop0 +%if WIN64 + pop r8 +%endif + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vpbroadcastd m15, [prep_8tap_2d_rnd] + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + vpbroadcastd m0, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 2 + sub srcq, r6 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m1, m1 + psraw m7, 4 + psraw m1, 8 + test dword r7m, 0x800 + jz .hv_w4_10bit + psraw m7, 2 +.hv_w4_10bit: + pshufd m11, m1, q0000 + pshufd m12, m1, q1111 + pshufd m13, m1, q2222 + pshufd m14, m1, q3333 +.hv_w4: + vbroadcasti128 m9, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + pshufd m8, m7, q1111 + pshufd m7, m7, q0000 + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*1], 1 ; 0 1 + vbroadcasti128 m0, [srcq+r6 ] + vinserti128 m2, m0, [srcq+strideq*2], 0 ; 2 3 + lea srcq, [srcq+strideq*4] + vinserti128 m0, [srcq+strideq*0], 1 ; 3 4 + movu xm3, [srcq+strideq*1] + vinserti128 m3, [srcq+strideq*2], 1 ; 5 6 + add srcq, r6 + pshufb m4, m1, m9 + pshufb m1, m10 + pmaddwd m4, m7 + pmaddwd m1, m8 + pshufb m5, m2, m9 + pshufb m2, m10 + pmaddwd m5, m7 + pmaddwd m2, m8 + paddd m4, m15 + paddd m1, m4 + pshufb m4, m0, m9 + pshufb m0, m10 + pmaddwd m4, m7 + pmaddwd m0, m8 + paddd m5, m15 + paddd m2, m5 + pshufb m5, m3, m9 + pshufb m3, m10 + pmaddwd m5, m7 + pmaddwd m3, m8 + paddd m4, m15 + paddd m4, m0 + paddd m5, m15 + paddd m5, m3 + vperm2i128 m0, m1, m2, 0x21 + psrld m1, 6 + psrld m2, 6 + vperm2i128 m3, m4, m5, 0x21 + pslld m4, 10 + pslld m5, 10 + pblendw m2, m4, 0xaa ; 23 34 + pslld m0, 10 + pblendw m1, m0, 0xaa ; 01 12 + psrld m3, 6 + pblendw m3, m5, 0xaa ; 45 56 + psrad m0, m5, 16 +.hv_w4_loop: + movu xm4, [srcq+strideq*0] + vinserti128 m4, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m15 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + pshufb m3, m4, m9 + pshufb m4, m10 + pmaddwd m3, m7 + pmaddwd m4, m8 + paddd m3, m15 + paddd m4, m3 + psrad m4, 6 + packssdw m0, m4 ; _ 7 6 8 + vpermq m3, m0, q1122 ; _ 6 _ 7 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m4, m5 + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + vpbroadcastq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + pmovsxbw xm1, [base+subpel_filters+myq*8] +%if WIN64 + PUSH r8 +%endif + mov r8d, wd + shl wd, 5 + lea r6, [strideq*3] + sub srcq, 6 + sub srcq, r6 + mov r5, srcq + mov r7, tmpq + lea wd, [hq+wq-256] + pxor m0, m0 + punpcklbw m0, m2 + mova [v_mul], xm1 + psraw m0, 4 + test dword r7m, 0x800 + jz .hv_w8_10bit + psraw m0, 2 +.hv_w8_10bit: + pshufd m11, m0, q0000 + pshufd m12, m0, q1111 + pshufd m13, m0, q2222 + pshufd m14, m0, q3333 +.hv_w8_loop0: +%macro PREP_8TAP_HV_H 3 ; dst/src+0, src+8, src+16 + pshufb m2, m%1, m9 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m8 ; 0 1 1 2 2 3 3 4 + pmaddwd m3, m12, m2 + pmaddwd m%1, m11 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + shufpd m2, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m3, m15 + paddd m%1, m3 + pmaddwd m3, m14, m%2 + paddd m%1, m3 + pmaddwd m3, m13, m2 + pshufb m%3, m9 ; a b b c c d d e + pmaddwd m2, m11 + paddd m%1, m3 + pmaddwd m3, m12, m%2 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m14 + pmaddwd m%2, m13 + paddd m2, m15 + paddd m2, m3 + paddd m2, m%3 + paddd m2, m%2 + psrad m%1, 6 + psrad m2, 6 + packssdw m%1, m2 +%endmacro + movu xm4, [srcq+r6 + 0] + vbroadcasti128 m8, [subpel_h_shufA] + movu xm6, [srcq+r6 + 8] + vbroadcasti128 m9, [subpel_h_shufB] + movu xm0, [srcq+r6 +16] + movu xm5, [srcq+strideq*0+ 0] + vinserti128 m5, [srcq+strideq*4+ 0], 1 + movu xm1, [srcq+strideq*0+16] + vinserti128 m1, [srcq+strideq*4+16], 1 + shufpd m7, m5, m1, 0x05 + INIT_XMM avx2 + PREP_8TAP_HV_H 4, 6, 0 ; 3 + INIT_YMM avx2 + PREP_8TAP_HV_H 5, 7, 1 ; 0 4 + movu xm0, [srcq+strideq*2+ 0] + vinserti128 m0, [srcq+r6 *2+ 0], 1 + movu xm1, [srcq+strideq*2+16] + vinserti128 m1, [srcq+r6 *2+16], 1 + shufpd m7, m0, m1, 0x05 + PREP_8TAP_HV_H 0, 7, 1 ; 2 6 + movu xm6, [srcq+strideq*1+ 0] + movu xm1, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*4] + vinserti128 m6, [srcq+strideq*1+ 0], 1 + vinserti128 m1, [srcq+strideq*1+16], 1 + add srcq, r6 + shufpd m7, m6, m1, 0x05 + PREP_8TAP_HV_H 6, 7, 1 ; 1 5 + vpermq m4, m4, q1100 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + vpermq m7, m0, q3120 + punpcklwd m3, m7, m4 ; 23 + punpckhwd m4, m5 ; 34 + punpcklwd m1, m5, m6 ; 01 + punpckhwd m5, m6 ; 45 + punpcklwd m2, m6, m7 ; 12 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vpbroadcastd m9, [v_mul+4*0] + vpbroadcastd m7, [v_mul+4*1] + vpbroadcastd m10, [v_mul+4*2] + pmaddwd m8, m9, m1 ; a0 + pmaddwd m9, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m7 ; a1 + pmaddwd m4, m7 ; b1 + paddd m8, m15 + paddd m9, m15 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m8, m5 + paddd m9, m6 + movu xm5, [srcq+strideq*0] + vinserti128 m5, [srcq+strideq*1], 1 + vbroadcasti128 m7, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + movu xm6, [srcq+strideq*0+16] + vinserti128 m6, [srcq+strideq*1+16], 1 + vextracti128 [tmpq], m0, 1 + pshufb m0, m5, m7 ; 01 + pshufb m5, m10 ; 23 + pmaddwd m0, m11 + pmaddwd m5, m12 + paddd m0, m15 + paddd m0, m5 + pshufb m5, m6, m7 ; 89 + pshufb m6, m10 ; ab + pmaddwd m5, m13 + pmaddwd m6, m14 + paddd m5, m15 + paddd m6, m5 + movu xm5, [srcq+strideq*0+8] + vinserti128 m5, [srcq+strideq*1+8], 1 + lea srcq, [srcq+strideq*2] + pshufb m7, m5, m7 + pshufb m5, m10 + pmaddwd m10, m13, m7 + pmaddwd m7, m11 + paddd m0, m10 + paddd m6, m7 + pmaddwd m7, m14, m5 + pmaddwd m5, m12 + paddd m0, m7 + paddd m5, m6 + vbroadcasti128 m6, [tmpq] + vpbroadcastd m10, [v_mul+4*3] + psrad m0, 6 + psrad m5, 6 + packssdw m0, m5 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m10, m5 ; a3 + pmaddwd m10, m6 ; b3 + paddd m7, m8 + paddd m9, m10 + psrad m7, 6 + psrad m9, 6 + packssdw m7, m9 + vpermq m7, m7, q3120 + mova [tmpq+r8*0], xm7 + vextracti128 [tmpq+r8*2], m7, 1 + lea tmpq, [tmpq+r8*4] + sub hd, 2 + jg .hv_w8_loop + add r5, 16 + add r7, 16 + movzx hd, wb + mov srcq, r5 + mov tmpq, r7 + sub wd, 1<<8 + jg .hv_w8_loop0 +%if WIN64 + POP r8 +%endif + RET + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro REMAP_REG 2 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %xdefine r14_save r14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + %xdefine r14 r14_save + %undef r14_save + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%macro MC_8TAP_SCALED_H 8-9 0 ; dst, tmp[0-6], load_hrnd + movu xm%1, [srcq+ r4*2] + movu xm%2, [srcq+ r6*2] + movu xm%3, [srcq+ r7*2] + movu xm%4, [srcq+ r9*2] + vinserti128 m%1, [srcq+r10*2], 1 + vinserti128 m%2, [srcq+r11*2], 1 + vinserti128 m%3, [srcq+r13*2], 1 + vinserti128 m%4, [srcq+ rX*2], 1 + add srcq, ssq + movu xm%5, [srcq+ r4*2] + movu xm%6, [srcq+ r6*2] + movu xm%7, [srcq+ r7*2] + movu xm%8, [srcq+ r9*2] + vinserti128 m%5, [srcq+r10*2], 1 + vinserti128 m%6, [srcq+r11*2], 1 + vinserti128 m%7, [srcq+r13*2], 1 + vinserti128 m%8, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m%1, m12 + pmaddwd m%2, m13 + pmaddwd m%3, m14 + pmaddwd m%4, m15 + pmaddwd m%5, m12 + pmaddwd m%6, m13 + pmaddwd m%7, m14 + pmaddwd m%8, m15 + phaddd m%1, m%2 + %if %9 + mova m10, [rsp+0x00] + %endif + phaddd m%3, m%4 + phaddd m%5, m%6 + phaddd m%7, m%8 + phaddd m%1, m%3 + phaddd m%5, m%7 + paddd m%1, m10 + paddd m%5, m10 + psrad m%1, xm11 + psrad m%5, xm11 + packssdw m%1, m%5 +%endmacro + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isput 1 + %assign isprep 0 +cglobal put_8tap_scaled_16bpc, 4, 14, 16, 0xe0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %xdefine base_reg r12 + mov r7d, pxmaxm +%else + %assign isput 0 + %assign isprep 1 +cglobal prep_8tap_scaled_16bpc, 4, 14, 16, 0xe0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %define tmp_stridem qword [rsp+0xd0] + %xdefine base_reg r11 +%endif + lea base_reg, [%1_8tap_scaled_16bpc_avx2] +%define base base_reg-%1_8tap_scaled_16bpc_avx2 + tzcnt wd, wm + vpbroadcastd m8, dxm +%if isprep && UNIX64 + movd xm10, mxd + vpbroadcastd m10, xm10 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 + mov r6d, pxmaxm +%else + vpbroadcastd m10, mxm + %if isput + vpbroadcastw m11, pxmaxm + %else + mov r6d, pxmaxm + %endif +%endif + mov dyd, dym +%if isput + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %else + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %define dsm [rsp+0x98] + %define rX r1 + %define rXd r1d +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %else + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+0x98] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define rX r14 + %define rXd r14d +%endif + shr r7d, 11 + vpbroadcastd m6, [base+pd_0x3ff] + vpbroadcastd m12, [base+s_8tap_h_rnd+r7*4] + movd xm7, [base+s_8tap_h_sh+r7*4] +%if isput + vpbroadcastd m13, [base+put_s_8tap_v_rnd+r7*4] + pinsrd xm7, [base+put_s_8tap_v_sh+r7*4], 2 +%else + vpbroadcastd m13, [base+pd_m524256] +%endif + pxor m9, m9 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_avx2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0,1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd xm4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*2] + movu xm3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*0], 1 ; 0 4 + vinserti128 m1, [srcq+ssq*1], 1 ; 1 5 + vinserti128 m2, [srcq+ssq*2], 1 ; 2 6 + vinserti128 m3, [srcq+ss3q ], 1 ; 3 7 + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m10}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + phaddd m0, m1 + phaddd m2, m3 + paddd m0, m12 + paddd m2, m12 + psrad m0, xm7 + psrad m2, xm7 + packssdw m0, m2 ; 0 1 2 3 4 5 6 7 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 ; 1 2 3 4 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + pshufd xm4, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm4 ; 45 56 + punpckhwd xm4, xm1, xm4 ; 67 __ +.w2_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm14, r6q + pmovsxbw xm14, xm14 + pshufd xm8, xm14, q0000 + pshufd xm9, xm14, q1111 + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pshufd xm8, xm14, q2222 + pshufd xm14, xm14, q3333 + paddd xm5, xm6 + pmaddwd xm6, xm2, xm8 + pmaddwd xm8, xm4, xm14 + psrldq xm9, xm7, 8 + paddd xm5, xm6 + paddd xm5, xm13 + paddd xm5, xm8 + psrad xm5, xm9 + packusdw xm5, xm5 + pminsw xm5, xm11 + movd [dstq], xm5 + add dstq, dsq + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w2_loop + movu xm5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps xm3, xm0, q1032 ; 01 12 + shufps xm0, xm2, q1032 ; 23 34 + shufps xm2, xm4, q1032 ; 45 56 + pshufb xm5, xm10 + pmaddwd xm5, xm15 + phaddd xm5, xm5 + paddd xm5, xm12 + psrad xm5, xm7 + packssdw xm5, xm5 + palignr xm1, xm5, xm1, 12 + punpcklqdq xm1, xm1 ; 6 7 6 7 + punpcklwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +.w2_skip_line: + movu xm6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xm3, xm0 ; 01 12 + mova xm0, xm2 ; 23 34 + pshufb xm5, xm10 + pshufb xm6, xm10 + pmaddwd xm5, xm15 + pmaddwd xm6, xm15 + phaddd xm5, xm6 + paddd xm5, xm12 + psrad xm5, xm7 + packssdw xm5, xm5 ; 6 7 6 7 + palignr xm1, xm5, xm1, 8 ; 4 5 6 7 + pshufd xm5, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm5 ; 45 56 + punpckhwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +%endif +.w4: + mov myd, mym + mova [rsp+0x00], m12 +%if isput + mova [rsp+0x20], xm13 +%else + SWAP m11, m13 +%endif + mova [rsp+0x30], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m0, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + pcmpeqd m6, m9 + punpckldq m10, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pblendvb m14, m2, m10 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu xm7, [srcq+ssq*0] + movu xm9, [srcq+ssq*1] + movu xm8, [srcq+ssq*2] + movu xm10, [srcq+ss3q ] + movu xm1, [srcq+r4 ] + movu xm3, [srcq+r6 ] + movu xm2, [srcq+r11 ] + movu xm4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + vinserti128 m7, [srcq+ssq*0], 1 + vinserti128 m9, [srcq+ssq*1], 1 + vinserti128 m8, [srcq+ssq*2], 1 + vinserti128 m10, [srcq+ss3q ], 1 + vinserti128 m1, [srcq+r4 ], 1 + vinserti128 m3, [srcq+r6 ], 1 + vinserti128 m2, [srcq+r11 ], 1 + vinserti128 m4, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m0 + paddb m13, m0 + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m14}, m7, m9, m8, m10 + REPX {pshufb x, m13}, m1, m2, m3, m4 + REPX {pmaddwd x, m15}, m1, m2, m3, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x30] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 4 5 + packssdw m8, m10 ; 2 3 6 7 + vextracti128 xm9, m7, 1 ; 4 5 + vextracti128 xm3, m8, 1 ; 6 7 + shufps xm4, xm7, xm8, q1032 ; 1 2 + shufps xm5, xm8, xm9, q1032 ; 3 4 + shufps xm6, xm9, xm3, q1032 ; 5 6 + psrldq xm10, xm3, 8 ; 7 _ + punpcklwd xm0, xm7, xm4 ; 01 + punpckhwd xm7, xm4 ; 12 + punpcklwd xm1, xm8, xm5 ; 23 + punpckhwd xm8, xm5 ; 34 + punpcklwd xm2, xm9, xm6 ; 45 + punpckhwd xm9, xm6 ; 56 + punpcklwd xm3, xm10 ; 67 + mova [rsp+0x40], xm7 + mova [rsp+0x50], xm8 + mova [rsp+0x60], xm9 +.w4_loop: + and myd, 0x3ff + mov r11d, 64 << 24 + mov r13d, myd + shr r13d, 6 + lea r13d, [t1+r13] + cmovnz r11q, [base+subpel_filters+r13*8] + movq xm9, r11q + pmovsxbw xm9, xm9 + pshufd xm7, xm9, q0000 + pshufd xm8, xm9, q1111 + pmaddwd xm4, xm0, xm7 + pmaddwd xm5, xm1, xm8 + pshufd xm7, xm9, q2222 + pshufd xm9, xm9, q3333 + pmaddwd xm6, xm2, xm7 + pmaddwd xm8, xm3, xm9 +%if isput + mova xm7, [rsp+0x20] + movd xm9, [rsp+0x38] +%else + SWAP m7, m11 +%endif + paddd xm4, xm5 + paddd xm6, xm8 + paddd xm4, xm6 + paddd xm4, xm7 +%if isput + psrad xm4, xm9 + packusdw xm4, xm4 + pminuw xm4, xm11 + movq [dstq], xm4 + add dstq, dsq +%else + SWAP m11, m7 + psrad xm4, 6 + packssdw xm4, xm4 + movq [tmpq], xm4 + add tmpq, 8 +%endif + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + mova xm8, [rsp+0x00] + movd xm9, [rsp+0x30] + movu xm4, [srcq] + movu xm5, [srcq+r4] + test myd, 0x400 + jz .w4_skip_line + mova xm0, [rsp+0x40] + mova [rsp+0x40], xm1 + mova xm1, [rsp+0x50] + mova [rsp+0x50], xm2 + mova xm2, [rsp+0x60] + mova [rsp+0x60], xm3 + pshufb xm4, xm12 + pshufb xm5, xm13 + pmaddwd xm4, xm14 + pmaddwd xm5, xm15 + phaddd xm4, xm5 + paddd xm4, xm8 + psrad xm4, xm9 + packssdw xm4, xm4 + punpcklwd xm3, xm10, xm4 + mova xm10, xm4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu xm6, [srcq+ssq*1] + movu xm7, [srcq+r6] + movu m0, [rsp+0x50] + pshufb xm4, xm12 + pshufb xm6, xm12 + pshufb xm5, xm13 + pshufb xm7, xm13 + pmaddwd xm4, xm14 + pmaddwd xm6, xm14 + pmaddwd xm5, xm15 + pmaddwd xm7, xm15 + mova [rsp+0x40], m0 + phaddd xm4, xm5 + phaddd xm6, xm7 + paddd xm4, xm8 + paddd xm6, xm8 + psrad xm4, xm9 + psrad xm6, xm9 + packssdw xm4, xm6 + punpcklwd xm9, xm10, xm4 + mova [rsp+0x60], xm9 + psrldq xm10, xm4, 8 + mova xm0, xm1 + mova xm1, xm2 + mova xm2, xm3 + punpcklwd xm3, xm4, xm10 + lea srcq, [srcq+ssq*2] + jmp .w4_loop + SWAP m10, m13 +%if isprep + SWAP m13, m11 +%endif +.w8: + mov dword [rsp+0x80], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+0x80], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+0x80], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+0x80], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+0x80], 16 + movifprep tmp_stridem, 256 +.w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free +%if isput + movifnidn dsm, dsq + mova [rsp+0xb0], xm7 +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + shr t0d, 16 + sub srcq, 6 + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0x84], t0d + mov [rsp+0x88], srcq + mov [rsp+0x90], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + jmp .hloop +.hloop_prep: + dec dword [rsp+0x80] + jz .ret + add qword [rsp+0x90], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x40] + vpbroadcastd m15, [rsp+0x84] + pxor m9, m9 + mov srcq, [rsp+0x88] + mov r0q, [rsp+0x90] ; dstq / tmpq +.hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x40], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq [rsp+0xa0], xm1 + movq [rsp+0xa8], xm7 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x60], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x60] + vbroadcasti128 m9, [base+subpel_s_shuf8] + mov myd, mym + mov dyd, dym + pshufb m0, m9 ; 01a 01b + pshufb m1, m9 ; 23a 23b + pshufb m2, m9 ; 45a 45b + pshufb m3, m9 ; 67a 67b +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm9, r6q + punpcklqdq xm9, xm9 + pmovsxbw m9, xm9 + pshufd m8, m9, q0000 + pshufd m7, m9, q1111 + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m7 + pshufd m8, m9, q2222 + pshufd m9, m9, q3333 + pmaddwd m6, m2, m8 + pmaddwd m7, m3, m9 +%if isput + psrldq xm8, xm11, 8 +%endif + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, xm8 + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xb0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+0x60], myd + mov r4d, [rsp+0xa0] + mov r6d, [rsp+0xa4] + mov r7d, [rsp+0xa8] + mov r9d, [rsp+0xac] + jz .skip_line + vbroadcasti128 m9, [base+wswap] + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + mov myd, [rsp+0x60] + mov dyd, dym + pshufb m0, m9 + pshufb m1, m9 + pshufb m2, m9 + pshufb m3, m9 + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + phaddd m4, m6 + paddd m4, m10 + psrad m4, xm11 + pslld m4, 16 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .vloop +.skip_line: + mova m0, m1 + mova m1, m2 + mova m2, m3 + MC_8TAP_SCALED_H 3, 10, 4, 5, 6, 7, 8, 9, 1 + vbroadcasti128 m9, [base+subpel_s_shuf8] + mov myd, [rsp+0x60] + mov dyd, dym + pshufb m3, m9 + jmp .vloop + SWAP m1, m12, m10 + SWAP m7, m11 +.dy1: + movzx wd, word [base+%1_8tap_scaled_avx2_dy1_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy1_w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0-1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*2] + movu xm3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*1], 1 + vinserti128 m2, [srcq+ssq*2], 1 + add srcq, ss3q + movq xm6, r4q + pmovsxbw xm6, xm6 + pshufd xm8, xm6, q0000 + pshufd xm9, xm6, q1111 + pshufd xm14, xm6, q2222 + pshufd xm6, xm6, q3333 + REPX {pshufb x, m10}, m0, m1, m2 + pshufb xm3, xm10 + REPX {pmaddwd x, m15}, m0, m1, m2 + pmaddwd xm3, xm15 + phaddd m0, m1 + phaddd m2, m3 + paddd m0, m12 + paddd m2, m12 + psrad m0, xm7 + psrad m2, xm7 + packssdw m0, m2 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 + pshufd xm4, xm1, q2121 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + punpcklwd xm2, xm1, xm4 ; 45 56 +.dy1_w2_loop: + movu xm1, [srcq+ssq*0] + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm1, xm10 + pshufb xm5, xm10 + pmaddwd xm1, xm15 + pmaddwd xm5, xm15 + phaddd xm1, xm5 + pmaddwd xm5, xm3, xm8 + mova xm3, xm0 + pmaddwd xm0, xm9 + paddd xm1, xm12 + psrad xm1, xm7 + packssdw xm1, xm1 + paddd xm5, xm0 + mova xm0, xm2 + pmaddwd xm2, xm14 + paddd xm5, xm2 + palignr xm2, xm1, xm4, 12 + punpcklwd xm2, xm1 ; 67 78 + pmaddwd xm4, xm2, xm6 + paddd xm5, xm13 + paddd xm5, xm4 + mova xm4, xm1 + psrldq xm1, xm7, 8 + psrad xm5, xm1 + packusdw xm5, xm5 + pminsw xm5, xm11 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +.dy1_w4: + mov myd, mym +%if isput + mova [rsp+0x50], xm11 +%endif + mova [rsp+0x00], m12 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m4, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + pcmpeqd m6, m9 + punpckldq m10, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pblendvb m14, m2, m10 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*2] + lea r11, [r4+ssq*1] + lea r13, [r4+ss3q ] + movu xm0, [srcq+ssq*0] + movu xm7, [srcq+r4 ] + movu xm1, [srcq+ssq*2] + movu xm8, [srcq+r6 ] + vinserti128 m0, [srcq+ssq*1], 1 ; 0 1 + vinserti128 m7, [srcq+r11 ], 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 2 3 + vinserti128 m8, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + movu xm2, [srcq+ssq*0] + movu xm9, [srcq+r4 ] + movu xm3, [srcq+ssq*2] ; 6 _ + movu xm10, [srcq+r6 ] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + vinserti128 m9, [srcq+r11 ], 1 + lea srcq, [srcq+ss3q ] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m4 + paddb m13, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x40] + pshufb m0, m12 + pshufb m1, m12 + pmaddwd m0, m14 + pmaddwd m1, m14 + pshufb m7, m13 + pshufb m8, m13 + pmaddwd m7, m15 + pmaddwd m8, m15 + pshufb m2, m12 + pshufb xm3, xm12 + pmaddwd m2, m14 + pmaddwd xm3, xm14 + pshufb m9, m13 + pshufb xm10, xm13 + pmaddwd m9, m15 + pmaddwd xm10, xm15 + phaddd m0, m7 + phaddd m1, m8 + phaddd m2, m9 + phaddd xm3, xm10 + paddd m0, m5 + paddd m1, m5 + paddd m2, m5 + paddd xm3, xm5 + psrad m0, xm6 + psrad m1, xm6 + psrad m2, xm6 + psrad xm3, xm6 + vperm2i128 m4, m0, m1, 0x21 ; 1 2 + vperm2i128 m5, m1, m2, 0x21 ; 3 4 + vperm2i128 m6, m2, m3, 0x21 ; 5 6 + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + pslld m4, 16 + pslld m5, 16 + pslld m6, 16 + pblendw m0, m4, 0xaa ; 01 12 + pblendw m1, m5, 0xaa ; 23 34 + pblendw m2, m6, 0xaa ; 45 56 + movq xm10, r13q + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 +.dy1_w4_loop: + movu xm11, [srcq+ssq*0] + movu xm6, [srcq+r4 ] + vinserti128 m11, [srcq+ssq*1], 1 + vinserti128 m6, [srcq+r11 ], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pshufb m11, m12 + pshufb m6, m13 + pmaddwd m11, m14 + pmaddwd m6, m15 + paddd m4, [rsp+0x20] + phaddd m11, m6 + pmaddwd m6, m2, m9 + paddd m11, [rsp+0x00] + psrad m11, [rsp+0x40] + mova m0, m1 + mova m1, m2 + paddd m5, m6 + paddd m4, m5 + vinserti128 m2, m3, xm11, 1 + pslld m3, m11, 16 + pblendw m2, m3, 0xaa ; 67 78 + pmaddwd m5, m2, m10 + vextracti128 xm3, m11, 1 + paddd m4, m5 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0x50] + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET + SWAP m10, m13 +.dy1_w8: + mov dword [rsp+0xa0], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+0xa0], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+0xa0], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+0xa0], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+0xa0], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free + mov myd, mym +%if isput + %define dsm [rsp+0xb8] + movifnidn dsm, dsq + mova [rsp+0xc0], xm7 +%else + %if UNIX64 + %define hm [rsp+0xb8] + %endif +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm11 + shr t0d, 16 + sub srcq, 6 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0xa4], t0d + mov [rsp+0xa8], srcq + mov [rsp+0xb0], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+0xa0] + jz .ret + add qword [rsp+0xb0], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x60] + vpbroadcastd m15, [rsp+0xa4] + pxor m9, m9 + mov srcq, [rsp+0xa8] + mov r0q, [rsp+0xb0] ; dstq / tmpq + mova m10, [rsp+0x00] + mova xm11, [rsp+0x40] +.dy1_hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x60], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x80], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x80] + vbroadcasti128 m7, [base+subpel_s_shuf8] + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m10, [rsp+0x58] + vpbroadcastd m11, [rsp+0x5c] + pshufb m0, m7 ; 01a 01b + pshufb m1, m7 ; 23a 23b + pshufb m2, m7 ; 45a 45b + pshufb m3, m7 ; 67a 67b +.dy1_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xc0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep + vbroadcasti128 m7, [base+wswap] + pshufb m0, m7 + pshufb m1, m7 + pshufb m2, m7 + pshufb m3, m7 + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + phaddd m4, m6 + paddd m4, [rsp+0x00] + psrad m4, [rsp+0x40] + pslld m4, 16 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .dy1_vloop + SWAP m1, m12, m10 + SWAP m7, m11 +.dy2: + movzx wd, word [base+%1_8tap_scaled_avx2_dy2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy2_w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0-1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd xm4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*2] + movu xm2, [srcq+ssq*4] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*1], 1 ; 0 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 2 3 + lea srcq, [srcq+ssq*4] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m0, m10 + pshufb m1, m10 + pshufb m2, m10 + pmaddwd m0, m15 + pmaddwd m1, m15 + pmaddwd m2, m15 + movq xm6, r4q + pmovsxbw xm6, xm6 + phaddd m0, m1 + phaddd m1, m2 + paddd m0, m12 + paddd m1, m12 + psrad m0, xm7 + psrad m1, xm7 + packssdw m0, m1 ; 0 2 2 4 1 3 3 5 + vextracti128 xm1, m0, 1 + pshufd xm8, xm6, q0000 + pshufd xm9, xm6, q1111 + pshufd xm14, xm6, q2222 + pshufd xm6, xm6, q3333 + punpcklwd xm2, xm0, xm1 ; 01 23 + punpckhwd xm1, xm0, xm1 ; 23 45 +.dy2_w2_loop: + movu xm3, [srcq+ssq*0] + movu xm5, [srcq+ssq*2] + vinserti128 m3, [srcq+ssq*1], 1 ; 6 7 + vinserti128 m5, [srcq+ss3q ], 1 ; 8 9 + lea srcq, [srcq+ssq*4] + pmaddwd xm4, xm2, xm8 + pmaddwd xm1, xm9 + pshufb m3, m10 + pshufb m5, m10 + pmaddwd m3, m15 + pmaddwd m5, m15 + phaddd m3, m5 + paddd xm4, xm1 + paddd m3, m12 + psrad m3, xm7 + packssdw m3, m3 + pshufd m3, m3, q2100 + palignr m0, m3, m0, 12 ; 4 6 6 8 5 7 7 9 + vextracti128 xm1, m0, 1 + punpcklwd xm2, xm0, xm1 ; 45 67 + punpckhwd xm1, xm0, xm1 ; 67 89 + pmaddwd xm3, xm2, xm14 + pmaddwd xm5, xm1, xm6 + paddd xm4, xm13 + paddd xm4, xm3 + psrldq xm3, xm7, 8 + paddd xm4, xm5 + psrad xm4, xm3 + packusdw xm4, xm4 + pminsw xm4, xm11 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +.dy2_w4: + mov myd, mym +%if isput + mova [rsp+0x50], xm11 +%endif + mova [rsp+0x00], m12 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m4, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + pcmpeqd m6, m9 + punpckldq m11, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + movq xm10, r13q + pblendvb m14, m2, m11 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu xm0, [srcq+ssq*0] + movu xm7, [srcq+r4 ] + movu xm1, [srcq+ssq*1] + movu xm8, [srcq+r6 ] + vinserti128 m0, [srcq+ssq*2], 1 ; 0 2 + vinserti128 m7, [srcq+r11 ], 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 1 3 + vinserti128 m8, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + movu xm2, [srcq+ssq*0] + movu xm9, [srcq+r4 ] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + vinserti128 m9, [srcq+r6 ], 1 + lea srcq, [srcq+ssq*2] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m4 + paddb m13, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x40] + pshufb m0, m12 + pshufb m1, m12 + pshufb m2, m12 + pmaddwd m0, m14 + pmaddwd m1, m14 + pmaddwd m2, m14 + pshufb m7, m13 + pshufb m8, m13 + pshufb m9, m13 + pmaddwd m7, m15 + pmaddwd m8, m15 + pmaddwd m9, m15 + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + phaddd m0, m7 + phaddd m1, m8 + phaddd m2, m9 + paddd m0, m5 + paddd m1, m5 + paddd m2, m5 + psrad m0, xm6 + psrad m1, xm6 + psrad m2, xm6 + vperm2i128 m3, m0, m2, 0x21 ; 2 4 + vperm2i128 m2, m1, 0x13 ; 3 5 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + packssdw m0, m3 ; 0 2 2 4 + packssdw m1, m2 ; 1 3 3 5 + punpckhwd m2, m0, m1 ; 23 45 + punpcklwd m0, m1 ; 01 23 +.dy2_w4_loop: + movu xm1, [srcq+ssq*0] + movu xm6, [srcq+r4 ] + movu xm3, [srcq+ssq*1] + movu xm11, [srcq+r6 ] + vinserti128 m1, [srcq+ssq*2], 1 ; 6 8 + vinserti128 m6, [srcq+r11 ], 1 + vinserti128 m3, [srcq+ss3q ], 1 ; 7 9 + vinserti128 m11, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + pmaddwd m4, m0, m7 + pmaddwd m5, m2, m8 + pshufb m1, m12 + pshufb m3, m12 + pmaddwd m1, m14 + pmaddwd m3, m14 + mova m0, [rsp+0x00] + pshufb m6, m13 + pshufb m11, m13 + pmaddwd m6, m15 + pmaddwd m11, m15 + paddd m4, m5 + movd xm5, [rsp+0x40] + phaddd m1, m6 + phaddd m3, m11 + paddd m1, m0 + paddd m3, m0 + psrad m1, xm5 + psrad m3, xm5 + pslld m3, 16 + pblendw m1, m3, 0xaa ; 67 89 + vperm2i128 m0, m2, m1, 0x21 ; 45 67 + paddd m4, [rsp+0x20] + mova m2, m1 + pmaddwd m5, m0, m9 + pmaddwd m6, m2, m10 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0x50] + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET + SWAP m10, m13 +.dy2_w8: + mov dword [rsp+0xa0], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+0xa0], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+0xa0], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+0xa0], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+0xa0], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free + mov myd, mym +%if isput + movifnidn dsm, dsq + mova [rsp+0xc0], xm7 +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm11 + shr t0d, 16 + sub srcq, 6 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0xa4], t0d + mov [rsp+0xa8], srcq + mov [rsp+0xb0], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+0xa0] + jz .ret + add qword [rsp+0xb0], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x60] + vpbroadcastd m15, [rsp+0xa4] + pxor m9, m9 + mov srcq, [rsp+0xa8] + mov r0q, [rsp+0xb0] ; dstq / tmpq + mova m10, [rsp+0x00] + mova xm11, [rsp+0x40] +.dy2_hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x60], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x80], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x80] + vbroadcasti128 m7, [base+subpel_s_shuf8] + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m10, [rsp+0x58] + vpbroadcastd m11, [rsp+0x5c] + pshufb m0, m7 ; 01a 01b + pshufb m1, m7 ; 23a 23b + pshufb m2, m7 ; 45a 45b + pshufb m3, m7 ; 67a 67b +.dy2_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xc0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep + mova m0, m1 + mova m1, m2 + mova m2, m3 + movu xm3, [srcq+ r4*2] + movu xm4, [srcq+ r6*2] + movu xm5, [srcq+ r7*2] + movu xm6, [srcq+ r9*2] + vinserti128 m3, [srcq+r10*2], 1 + vinserti128 m4, [srcq+r11*2], 1 + vinserti128 m5, [srcq+r13*2], 1 + vinserti128 m6, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m3, m12 + pmaddwd m4, m13 + pmaddwd m5, m14 + pmaddwd m6, m15 + phaddd m3, m4 + phaddd m5, m6 + phaddd m3, m5 + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + mova m5, [rsp+0x00] + movd xm7, [rsp+0x40] + phaddd m4, m6 + paddd m3, m5 + paddd m4, m5 + psrad m3, xm7 + psrad m4, xm7 + pslld m4, 16 + pblendw m3, m4, 0xaa + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%undef isput +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_16bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, t0d + jmp mangle(private_prefix %+ _%1_8tap_scaled_16bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%else +DECLARE_REG_TMP 6, 8 +%endif + +%define PUT_8TAP_SCALED_FN FN put_8tap_scaled, +BILIN_SCALED_FN put +PUT_8TAP_SCALED_FN sharp, SHARP, SHARP +PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled, +BILIN_SCALED_FN prep +PREP_8TAP_SCALED_FN sharp, SHARP, SHARP +PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%macro WARP_V 5 ; dst, 01, 23, 45, 67 + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm8, [filterq+myq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 ; a e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; b f + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm9, [filterq+myq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 ; c g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + punpcklwd m8, m0 + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; d h + punpcklwd m0, m9, m0 + punpckldq m9, m8, m0 + punpckhdq m0, m8, m0 + punpcklbw m8, m11, m9 ; a0 a1 b0 b1 c0 c1 d0 d1 << 8 + punpckhbw m9, m11, m9 ; a2 a3 b2 b3 c2 c3 d2 d3 << 8 + pmaddwd m%2, m8 + pmaddwd m9, m%3 + punpcklbw m8, m11, m0 ; a4 a5 b4 b5 c4 c5 d4 d5 << 8 + punpckhbw m0, m11, m0 ; a6 a7 b6 b7 c6 c7 d6 d7 << 8 + pmaddwd m8, m%4 + pmaddwd m0, m%5 + paddd m9, m%2 + mova m%2, m%3 + paddd m0, m8 + mova m%3, m%4 + mova m%4, m%5 + paddd m%1, m0, m9 +%endmacro + +cglobal warp_affine_8x8t_16bpc, 4, 14, 16, tmp, ts + mov r6d, r7m + lea r9, [$$] + shr r6d, 11 + vpbroadcastd m13, [r9-$$+warp8x8_shift+r6*4] + vpbroadcastd m14, [warp8x8t_rnd] + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx2).main + jmp .start +.loop: + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx2).main2 + lea tmpq, [tmpq+tsq*4] +.start: + paddd m7, m14 + paddd m0, m14 + psrad m7, 15 + psrad m0, 15 + packssdw m7, m0 + vpermq m7, m7, q3120 + mova [tmpq+tsq*0], xm7 + vextracti128 [tmpq+tsq*2], m7, 1 + dec r4d + jg .loop +.end: + RET + +cglobal warp_affine_8x8_16bpc, 4, 14, 16, dst, ds, src, ss, abcd, mx, tmp2, \ + alpha, beta, filter, tmp1, delta, \ + my, gamma + mov r6d, r7m + lea filterq, [$$] + shr r6d, 11 + vpbroadcastd m13, [filterq-$$+warp8x8_shift+r6*4] + vpbroadcastd m14, [filterq-$$+warp8x8_rnd +r6*4] + vpbroadcastw m15, r7m ; pixel_max + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m7, 16 + psrad m0, 16 + packusdw m7, m0 + pmulhrsw m7, m14 + pminsw m7, m15 + vpermq m7, m7, q3120 + mova [dstq+dsq*0], xm7 + vextracti128 [dstq+dsq*1], m7, 1 + dec r4d + jg .loop +.end: + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov abcdq, r5m + mov mxd, r6m +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + vpbroadcastd m12, [pd_32768] + pxor m11, m11 + add filterq, mc_warp_filter-$$ + lea tmp1q, [ssq*3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + sub betad, tmp2d ; beta -= alpha*3 + mov myd, r7m + call .h + psrld m1, m0, 16 + call .h + pblendw m1, m0, 0xaa ; 01 + psrld m2, m0, 16 + call .h + pblendw m2, m0, 0xaa ; 12 + psrld m3, m0, 16 + call .h + pblendw m3, m0, 0xaa ; 23 + psrld m4, m0, 16 + call .h + pblendw m4, m0, 0xaa ; 34 + psrld m5, m0, 16 + call .h + pblendw m5, m0, 0xaa ; 45 + psrld m6, m0, 16 + call .h + pblendw m6, m0, 0xaa ; 56 + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + add myd, 512+(64<<10) + mov r4d, 4 + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 +.main2: + call .h + psrld m7, m6, 16 + pblendw m7, m0, 0xaa ; 67 + WARP_V 7, 1, 3, 5, 7 + call .h + psrld m10, m5, 16 + pblendw m10, m0, 0xaa ; 78 + WARP_V 0, 2, 4, 6, 10 + ret +ALIGN function_align +.h: + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + movu xm10, [srcq-6] + vinserti128 m10, [srcq+2], 1 + shr mxd, 10 ; 0 + shr tmp1d, 10 ; 4 + movq xm0, [filterq+mxq *8] + vinserti128 m0, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + movu xm8, [srcq-4] + vinserti128 m8, [srcq+4], 1 + shr tmp2d, 10 ; 1 + shr tmp1d, 10 ; 5 + movq xm9, [filterq+tmp2q*8] + vinserti128 m9, [filterq+tmp1q*8], 1 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 ; 2 + shr tmp1d, 10 ; 6 + punpcklbw m0, m11, m0 + pmaddwd m0, m10 + movu xm10, [srcq-2] + vinserti128 m10, [srcq+6], 1 + punpcklbw m9, m11, m9 + pmaddwd m9, m8 + movq xm8, [filterq+mxq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + phaddd m0, m9 ; 0 1 4 5 + movu xm9, [srcq+0] + vinserti128 m9, [srcq+8], 1 + shr tmp2d, 10 ; 3 + shr tmp1d, 10 ; 7 + punpcklbw m8, m11, m8 + pmaddwd m8, m10 + movq xm10, [filterq+tmp2q*8] + vinserti128 m10, [filterq+tmp1q*8], 1 + punpcklbw m10, m11, m10 + pmaddwd m9, m10 + add srcq, ssq + phaddd m8, m9 ; 2 3 6 7 + phaddd m0, m8 ; 0 1 2 3 4 5 6 7 + vpsllvd m0, m13 + paddd m0, m12 ; rounded 14-bit result in upper 16 bits of dword + ret + +%macro BIDIR_FN 0 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + movq [dstq ], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + cmp hd, 8 + je .ret + lea dstq, [dstq+strideq*4] + movq [dstq ], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.ret: + RET +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + cmp hd, 4 + jne .w8_loop_start + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 +.w8_loop_start: + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + dec hd + jg .w128_loop + RET +%endmacro + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal avg_16bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx2_table + lea r6, [avg_avx2_table] + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + vpbroadcastd m4, [base+bidir_rnd+t0*4] + vpbroadcastd m5, [base+bidir_mul+t0*4] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+32*0] + paddsw m0, [tmp2q+32*0] + mova m1, [tmp1q+32*1] + paddsw m1, [tmp2q+32*1] + mova m2, [tmp1q+32*2] + paddsw m2, [tmp2q+32*2] + mova m3, [tmp1q+32*3] + paddsw m3, [tmp2q+32*3] + add tmp1q, 32*4 + add tmp2q, 32*4 + pmaxsw m0, m4 + pmaxsw m1, m4 + pmaxsw m2, m4 + pmaxsw m3, m4 + psubsw m0, m4 + psubsw m1, m4 + psubsw m2, m4 + psubsw m3, m4 + pmulhw m0, m5 + pmulhw m1, m5 + pmulhw m2, m5 + pmulhw m3, m5 + ret + +cglobal w_avg_16bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, stride3 + lea r6, [w_avg_avx2_table] + tzcnt wd, wm + mov t0d, r6m ; weight + vpbroadcastw m8, r7m ; pixel_max + vpbroadcastd m7, [r6-w_avg_avx2_table+pd_65538] + movsxd wq, [r6+wq*4] + paddw m7, m8 + add wq, r6 + lea r6d, [t0-16] + shl t0d, 16 + sub t0d, r6d ; 16-weight, weight + pslld m7, 7 + rorx r6d, t0d, 30 ; << 2 + test dword r7m, 0x800 + cmovz r6d, t0d + movifnidn hd, hm + movd xm6, r6d + vpbroadcastd m6, xm6 + BIDIR_FN +ALIGN function_align +.main: + mova m4, [tmp1q+32*0] + mova m0, [tmp2q+32*0] + punpckhwd m5, m0, m4 + punpcklwd m0, m4 + mova m4, [tmp1q+32*1] + mova m1, [tmp2q+32*1] + pmaddwd m5, m6 + pmaddwd m0, m6 + paddd m5, m7 + paddd m0, m7 + psrad m5, 8 + psrad m0, 8 + packusdw m0, m5 + punpckhwd m5, m1, m4 + punpcklwd m1, m4 + mova m4, [tmp1q+32*2] + mova m2, [tmp2q+32*2] + pmaddwd m5, m6 + pmaddwd m1, m6 + paddd m5, m7 + paddd m1, m7 + psrad m5, 8 + psrad m1, 8 + packusdw m1, m5 + punpckhwd m5, m2, m4 + punpcklwd m2, m4 + mova m4, [tmp1q+32*3] + mova m3, [tmp2q+32*3] + add tmp1q, 32*4 + add tmp2q, 32*4 + pmaddwd m5, m6 + pmaddwd m2, m6 + paddd m5, m7 + paddd m2, m7 + psrad m5, 8 + psrad m2, 8 + packusdw m2, m5 + punpckhwd m5, m3, m4 + punpcklwd m3, m4 + pmaddwd m5, m6 + pmaddwd m3, m6 + paddd m5, m7 + paddd m3, m7 + psrad m5, 8 + psrad m3, 8 + packusdw m3, m5 + pminsw m0, m8 + pminsw m1, m8 + pminsw m2, m8 + pminsw m3, m8 + ret + +cglobal mask_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx2_table + lea r7, [mask_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_64] + vpbroadcastd m9, [base+bidir_rnd+r6*4] + vpbroadcastd m10, [base+bidir_mul+r6*4] + mov maskq, maskmp + add wq, r7 + BIDIR_FN +ALIGN function_align +.main: +%macro MASK 1 + pmovzxbw m5, [maskq+16*%1] + mova m%1, [tmp1q+32*%1] + mova m6, [tmp2q+32*%1] + punpckhwd m4, m%1, m6 + punpcklwd m%1, m6 + psubw m7, m8, m5 + punpckhwd m6, m5, m7 ; m, 64-m + punpcklwd m5, m7 + pmaddwd m4, m6 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m%1, m5 + psrad m4, 5 + psrad m%1, 5 + packssdw m%1, m4 + pmaxsw m%1, m9 + psubsw m%1, m9 + pmulhw m%1, m10 +%endmacro + MASK 0 + MASK 1 + MASK 2 + MASK 3 + add maskq, 16*4 + add tmp1q, 32*4 + add tmp2q, 32*4 + ret + +cglobal w_mask_420_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx2_table + lea r7, [w_mask_420_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd xm0, r7m ; sign + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+bidir_rnd+r6*4] + vpbroadcastd m13, [base+bidir_mul+r6*4] + movd xm14, [base+pw_2] + mov maskq, maskmp + psubw xm14, xm0 + vpbroadcastw m14, xm14 + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + phaddd m4, m5 + paddw m4, m14 + psrlw m4, 2 + packuswb m4, m4 + vextracti128 xm5, m4, 1 + punpcklwd xm4, xm5 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + mova [maskq], xm4 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8: + vperm2i128 m6, m4, m5, 0x21 + vpblendd m4, m5, 0xf0 + paddw m4, m14 + paddw m4, m6 + psrlw m4, 2 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + mova [maskq], xm4 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16: + punpcklqdq m6, m4, m5 + punpckhqdq m4, m5 + paddw m6, m14 + paddw m4, m6 + psrlw m4, 2 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + pshufd xm4, xm4, q3120 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + mova [maskq], xm4 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w32: + paddw m4, m14 + paddw m4, m5 + psrlw m15, m4, 2 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + call .main + mova m6, [deint_shuf] + paddw m4, m14 + paddw m4, m5 + psrlw m4, 2 + packuswb m15, m4 + vpermd m4, m6, m15 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m2 + mova [dstq+stride3q +32*1], m3 + mova [maskq], m4 + sub hd, 4 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w64: + paddw m4, m14 + paddw m15, m14, m5 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [maskq], m4 ; no available registers + call .main + paddw m4, [maskq] + mova m6, [deint_shuf] + paddw m5, m15 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 ; 0 2 4 6 1 3 5 7 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + mova [maskq], m4 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 64 +.w128: + paddw m4, m14 + paddw m5, m14 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [maskq+32*0], m4 + mova [dstq+strideq], m5 + call .main + paddw m4, m14 + paddw m15, m14, m5 + mova [dstq+strideq*0+32*4], m0 + mova [dstq+strideq*0+32*5], m1 + mova [dstq+strideq*0+32*6], m2 + mova [dstq+strideq*0+32*7], m3 + mova [maskq+32*1], m4 + call .main + paddw m4, [maskq+32*0] + paddw m5, [dstq+strideq] + mova m6, [deint_shuf] + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + mova [maskq+32*0], m4 + call .main + paddw m4, [maskq+32*1] + mova m6, [deint_shuf] + paddw m5, m15 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*4], m0 + mova [dstq+strideq*1+32*5], m1 + mova [dstq+strideq*1+32*6], m2 + mova [dstq+strideq*1+32*7], m3 + mova [maskq+32*1], m4 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: +%macro W_MASK 2-6 11, 12, 13 ; dst/src1, mask/src2, pw_64, rnd, mul + mova m%1, [tmp1q+32*%1] + mova m%2, [tmp2q+32*%1] + punpcklwd m8, m%2, m%1 + punpckhwd m9, m%2, m%1 + psubsw m%1, m%2 + pabsw m%1, m%1 + psubusw m7, m10, m%1 + psrlw m7, 10 ; 64-m + psubw m%2, m%3, m7 ; m + punpcklwd m%1, m7, m%2 + punpckhwd m7, m%2 + pmaddwd m%1, m8 + pmaddwd m7, m9 + psrad m%1, 5 + psrad m7, 5 + packssdw m%1, m7 + pmaxsw m%1, m%4 + psubsw m%1, m%4 + pmulhw m%1, m%5 +%endmacro + W_MASK 0, 4 + W_MASK 1, 5 + phaddw m4, m5 + W_MASK 2, 5 + W_MASK 3, 6 + phaddw m5, m6 + add tmp1q, 32*4 + add tmp2q, 32*4 + ret + +cglobal w_mask_422_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx2_table + lea r7, [w_mask_422_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + vpbroadcastb m14, r7m ; sign + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+bidir_rnd+r6*4] + vpbroadcastd m13, [base+bidir_mul+r6*4] + mova m15, [base+deint_shuf] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 4 + W_MASK 1, 5 + phaddw m4, m5 + W_MASK 2, 5 + W_MASK 3, 6 + phaddw m5, m6 + add tmp1q, 32*4 + add tmp2q, 32*4 + packuswb m4, m5 + pxor m5, m5 + psubb m4, m14 + pavgb m4, m5 + vpermd m4, m15, m4 + mova [maskq], m4 + add maskq, 32 + ret + +cglobal w_mask_444_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx2_table + lea r7, [w_mask_444_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] + vpbroadcastd m4, [base+pw_64] + vpbroadcastd m5, [base+bidir_rnd+r6*4] + vpbroadcastd m6, [base+bidir_mul+r6*4] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + call .main + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + call .main + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + call .main + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + call .main + mova [dstq+32*6], m0 + mova [dstq+32*7], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2, 4, 5, 6 + W_MASK 1, 3, 4, 5, 6 + packuswb m2, m3 + vpermq m2, m2, q3120 + add tmp1q, 32*2 + add tmp2q, 32*2 + mova [maskq], m2 + add maskq, 32 + ret + +; (a * (64 - m) + b * m + 32) >> 6 +; = (((b - a) * m + 32) >> 6) + a +; = (((b - a) * (m << 9) + 16384) >> 15) + a +; except m << 9 overflows int16_t when m == 64 (which is possible), +; but if we negate m it works out (-64 << 9 == -32768). +; = (((a - b) * (m * -512) + 16384) >> 15) + a +cglobal blend_16bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx2_table + lea r6, [blend_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + vpbroadcastd m6, [base+pw_m512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + pmovzxbw m3, [maskq] + movq xm0, [dstq+dsq*0] + movhps xm0, [dstq+dsq*1] + vpbroadcastq m1, [dstq+dsq*2] + vpbroadcastq m2, [dstq+r6 ] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + psubw m1, m0, [tmpq] + add maskq, 16 + add tmpq, 32 + pmullw m3, m6 + pmulhrsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + movq [dstq+dsq*2], xm1 + movhps [dstq+r6 ], xm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + mova xm1, [dstq+dsq*2] + vinserti128 m1, [dstq+r6 ], 1 + psubw m2, m0, [tmpq+32*0] + psubw m3, m1, [tmpq+32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + mova [dstq+dsq*2], xm1 + vextracti128 [dstq+r6 ], m1, 1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16 + RET +.w32: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova m0, [dstq+32*0] + psubw m2, m0, [tmpq+32*0] + mova m1, [dstq+32*1] + psubw m3, m1, [tmpq+32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .w32 + RET + +INIT_XMM avx2 +cglobal blend_v_16bpc, 3, 6, 6, dst, ds, tmp, w, h +%define base r5-blend_v_avx2_table + lea r5, [blend_v_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + vpbroadcastd m2, [base+obmc_masks_avx2+2*2] +.w2_loop: + movd m0, [dstq+dsq*0] + pinsrd m0, [dstq+dsq*1], 1 + movq m1, [tmpq] + add tmpq, 4*2 + psubw m1, m0, m1 + pmulhrsw m1, m2 + paddw m0, m1 + movd [dstq+dsq*0], m0 + pextrd [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + vpbroadcastq m2, [base+obmc_masks_avx2+4*2] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + psubw m1, m0, [tmpq] + add tmpq, 8*2 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +INIT_YMM avx2 +.w8: + vbroadcasti128 m2, [base+obmc_masks_avx2+8*2] +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + psubw m1, m0, [tmpq] + add tmpq, 16*2 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + mova m4, [base+obmc_masks_avx2+16*2] +.w16_loop: + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add tmpq, 32*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: +%if WIN64 + movaps [rsp+ 8], xmm6 + movaps [rsp+24], xmm7 +%endif + mova m6, [base+obmc_masks_avx2+32*2] + vbroadcasti128 m7, [base+obmc_masks_avx2+32*3] +.w32_loop: + mova m0, [dstq+dsq*0+32*0] + psubw m3, m0, [tmpq +32*0] + mova xm2, [dstq+dsq*0+32*1] + mova xm5, [tmpq +32*1] + mova m1, [dstq+dsq*1+32*0] + psubw m4, m1, [tmpq +32*2] + vinserti128 m2, [dstq+dsq*1+32*1], 1 + vinserti128 m5, [tmpq +32*3], 1 + add tmpq, 32*4 + psubw m5, m2, m5 + pmulhrsw m3, m6 + pmulhrsw m4, m6 + pmulhrsw m5, m7 + paddw m0, m3 + paddw m1, m4 + paddw m2, m5 + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*1+32*0], m1 + mova [dstq+dsq*0+32*1], xm2 + vextracti128 [dstq+dsq*1+32*1], m2, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop +%if WIN64 + movaps xmm6, [rsp+ 8] + movaps xmm7, [rsp+24] +%endif + RET + +%macro BLEND_H_ROW 2-3 0; dst_off, tmp_off, inc_tmp + mova m0, [dstq+32*(%1+0)] + psubw m2, m0, [tmpq+32*(%2+0)] + mova m1, [dstq+32*(%1+1)] + psubw m3, m1, [tmpq+32*(%2+1)] +%if %3 + add tmpq, 32*%3 +%endif + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+32*(%1+0)], m0 + mova [dstq+32*(%1+1)], m1 +%endmacro + +INIT_XMM avx2 +cglobal blend_h_16bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_h_avx2_table + lea r5, [blend_h_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea maskq, [base+obmc_masks_avx2+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + pinsrd m0, [dstq+dsq*1], 1 + movd m2, [maskq+hq*2] + movq m1, [tmpq] + add tmpq, 4*2 + punpcklwd m2, m2 + psubw m1, m0, m1 + pmulhrsw m1, m2 + paddw m0, m1 + movd [dstq+dsq*0], m0 + pextrd [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova m3, [blend_shuf] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + movd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 8*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +INIT_YMM avx2 +.w8: + vbroadcasti128 m3, [blend_shuf] + shufpd m3, m3, 0x0c +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + vpbroadcastd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 16*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +.w16: + vpbroadcastw m4, [maskq+hq*2] + vpbroadcastw m5, [maskq+hq*2+2] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add tmpq, 32*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16 + RET +.w32: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0, 2 + add dstq, dsq + inc hq + jl .w32 + RET +.w64: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 4 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 8 + BLEND_H_ROW 4, -4 + BLEND_H_ROW 6, -2 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal emu_edge_16bpc, 10, 13, 1, bw, bh, iw, ih, x, y, dst, dstride, src, sstride, \ + bottomext, rightext + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor r12d, r12d + lea r10, [ihq-1] + cmp yq, ihq + cmovs r10, yq + test yq, yq + cmovs r10, r12 + imul r10, sstrideq + add srcq, r10 + + ; ref += iclip(x, 0, iw - 1) + lea r10, [iwq-1] + cmp xq, iwq + cmovs r10, xq + test xq, xq + cmovs r10, r12 + lea srcq, [srcq+r10*2] + + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) + lea bottomextq, [yq+bhq] + sub bottomextq, ihq + lea r3, [bhq-1] + cmovs bottomextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, x, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, r12 + cmp bottomextq, bhq + cmovns bottomextq, r3 + cmp topextq, bhq + cmovg topextq, r3 + + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + lea rightextq, [xq+bwq] + sub rightextq, iwq + lea r2, [bwq-1] + cmovs rightextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, leftext, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, r12 + cmp rightextq, bwq + cmovns rightextq, r2 + cmp leftextq, bwq + cmovns leftextq, r2 + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, topext, \ + dst, dstride, src, sstride, bottomext, rightext + + ; center_h = bh - top_ext - bottom_ext + lea r3, [bottomextq+topextq] + sub centerhq, r3 + + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq + imul r2, dstrideq + add dstq, r2 + mov r9m, dstq + + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq + lea r3, [rightextq+leftextq] + sub centerwq, r3 + +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix +.v_loop_%3: +%if %1 + ; left extension + xor r3, r3 + vpbroadcastw m0, [srcq] +.left_loop_%3: + mova [dstq+r3*2], m0 + add r3, 16 + cmp r3, leftextq + jl .left_loop_%3 + + ; body + lea r12, [dstq+leftextq*2] +%endif + xor r3, r3 +.body_loop_%3: + movu m0, [srcq+r3*2] +%if %1 + movu [r12+r3*2], m0 +%else + movu [dstq+r3*2], m0 +%endif + add r3, 16 + cmp r3, centerwq + jl .body_loop_%3 + +%if %2 + ; right extension +%if %1 + lea r12, [r12+centerwq*2] +%else + lea r12, [dstq+centerwq*2] +%endif + xor r3, r3 + vpbroadcastw m0, [srcq+centerwq*2-2] +.right_loop_%3: + movu [r12+r3*2], m0 + add r3, 16 + cmp r3, rightextq + jl .right_loop_%3 + +%endif + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 +%endmacro + + test leftextq, leftextq + jnz .need_left_ext + test rightextq, rightextq + jnz .need_right_ext + v_loop 0, 0, 0 + jmp .body_done + +.need_left_ext: + test rightextq, rightextq + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: + ; bottom edge extension + test bottomextq, bottomextq + jz .top + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 +.bottom_x_loop: + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, bottomextq +.bottom_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .bottom_y_loop + add r1, 16 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end + mov srcq, r9m + mov dstq, dstm + xor r1, r1 +.top_x_loop: + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, topextq +.top_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .top_y_loop + add r1, 16 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +cglobal resize_16bpc, 6, 12, 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x, _, _, pxmax + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pd_64] + vpbroadcastw xm7, pxmaxm + pmaddwd m2, m5, [base+rescale_mul] ; dx*[0,1,2,3,4,5,6,7] + pslld m5, 3 ; dx*8 + pslld m6, 14 + paddd m8, m2 ; mx+[0..7]*dx +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + vpbroadcastd m10, [base+pd_63] + pxor m2, m2 + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + pand m9, m10 ; filter offset (masked) + ; load source pixels + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vextracti128 xm0, m0, 1 + movu xm10, [srcq+r8*2] + movu xm11, [srcq+r9*2] + movu xm12, [srcq+r10*2] + movu xm13, [srcq+r11*2] + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vinserti128 m10, [srcq+r8*2], 1 + vinserti128 m11, [srcq+r9*2], 1 + vinserti128 m12, [srcq+r10*2], 1 + vinserti128 m13, [srcq+r11*2], 1 + ptest m1, m1 + jz .filter + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vextracti128 xm1, m1, 1 + movu xm14, [base+resize_shuf+8+r8*2] + movu xm15, [base+resize_shuf+8+r9*2] + movu xm0, [base+resize_shuf+8+r10*2] + movu xm2, [base+resize_shuf+8+r11*2] + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vinserti128 m14, [base+resize_shuf+8+r8*2], 1 + vinserti128 m15, [base+resize_shuf+8+r9*2], 1 + vinserti128 m0, [base+resize_shuf+8+r10*2], 1 + vinserti128 m2, [base+resize_shuf+8+r11*2], 1 + pshufb m10, m14 + pshufb m11, m15 + pshufb m12, m0 + pshufb m13, m2 +.filter: + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vextracti128 xm9, m9, 1 + movq xm14, [base+resize_filter+r8*8] + movq xm15, [base+resize_filter+r9*8] + movq xm0, [base+resize_filter+r10*8] + movq xm2, [base+resize_filter+r11*8] + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + movhps xm14, [base+resize_filter+r8*8] + movhps xm15, [base+resize_filter+r9*8] + movhps xm0, [base+resize_filter+r10*8] + movhps xm2, [base+resize_filter+r11*8] + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pmovsxbw m0, xm0 + pmovsxbw m2, xm2 + pmaddwd m10, m14 + pmaddwd m11, m15 + pmaddwd m12, m0 + pmaddwd m13, m2 + phaddd m10, m11 + phaddd m12, m13 + phaddd m10, m12 + psubd m10, m3, m10 + psrad m10, 7 + vextracti128 xm0, m10, 1 + packusdw xm10, xm0 + pminsw xm10, xm7 + mova [dstq+xq*2], xm10 + paddd m4, m5 + add xd, 8 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4858 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +spel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 + db 32, 33, 34, 35, 34, 35, 36, 37, 36, 37, 38, 39, 38, 39, 40, 41 +spel_h_shufC: db 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 14, 15, 16, 17 + db 40, 41, 42, 43, 42, 43, 44, 45, 44, 45, 46, 47, 46, 47, 48, 49 + db 16, 17, 18, 19, 18, 19, 20, 21, 20, 21, 22, 23, 22, 23, 24, 25 + db 48, 49, 50, 51, 50, 51, 52, 53, 52, 53, 54, 55, 54, 55, 56, 57 +spel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 + db 36, 37, 38, 39, 38, 39, 40, 41, 40, 41, 42, 43, 42, 43, 44, 45 +spel_h_shufD: db 12, 13, 14, 15, 14, 15, 16, 17, 16, 17, 18, 19, 18, 19, 20, 21 + db 44, 45, 46, 47, 46, 47, 48, 49, 48, 49, 50, 51, 50, 51, 52, 53 + db 20, 21, 22, 23, 22, 23, 24, 25, 24, 25, 26, 27, 26, 27, 28, 29 + db 52, 53, 54, 55, 54, 55, 56, 57, 56, 57, 58, 59, 58, 59, 60, 61 +spel_v_shuf8: db 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 + db 16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39 + db 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 + db 24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47 +spel_v_shuf16: db 0, 1, 32, 33, 2, 3, 34, 35, 4, 5, 36, 37, 6, 7, 38, 39 + db 8, 9, 40, 41, 10, 11, 42, 43, 12, 13, 44, 45, 14, 15, 46, 47 + db 16, 17, 48, 49, 18, 19, 50, 51, 20, 21, 52, 53, 22, 23, 54, 55 + db 24, 25, 56, 57, 26, 27, 58, 59, 28, 29, 60, 61, 30, 31, 62, 63 +prep_endA: db 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30 + db 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 81, 82, 85, 86, 89, 90, 93, 94 + db 97, 98,101,102,105,106,109,110,113,114,117,118,121,122,125,126 +prep_endB: db 1, 2, 5, 6, 9, 10, 13, 14, 33, 34, 37, 38, 41, 42, 45, 46 + db 17, 18, 21, 22, 25, 26, 29, 30, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 97, 98,101,102,105,106,109,110 + db 81, 82, 85, 86, 89, 90, 93, 94,113,114,117,118,121,122,125,126 +prep_endC: db 1, 2, 5, 6, 9, 10, 13, 14, 65, 66, 69, 70, 73, 74, 77, 78 + db 17, 18, 21, 22, 25, 26, 29, 30, 81, 82, 85, 86, 89, 90, 93, 94 + db 33, 34, 37, 38, 41, 42, 45, 46, 97, 98,101,102,105,106,109,110 + db 49, 50, 53, 54, 57, 58, 61, 62,113,114,117,118,121,122,125,126 +spel_shuf4a: db 1, 2, 17, 18, 5, 6, 21, 22, 9, 10, 25, 26, 13, 14, 29, 30 + db 17, 18, 33, 34, 21, 22, 37, 38, 25, 26, 41, 42, 29, 30, 45, 46 +spel_shuf4b: db 18, 19, 33, 34, 22, 23, 37, 38, 26, 27, 41, 42, 30, 31, 45, 46 + db 33, 34, 49, 50, 37, 38, 53, 54, 41, 42, 57, 58, 45, 46, 61, 62 +spel_shuf8a: db 1, 2, 17, 18, 5, 6, 21, 22, 9, 10, 25, 26, 13, 14, 29, 30 + db 17, 18, 65, 66, 21, 22, 69, 70, 25, 26, 73, 74, 29, 30, 77, 78 + db 33, 34, 49, 50, 37, 38, 53, 54, 41, 42, 57, 58, 45, 46, 61, 62 + db 49, 50, 97, 98, 53, 54,101,102, 57, 58,105,106, 61, 62,109,110 +spel_shuf8b: db 18, 19, 65, 66, 22, 23, 69, 70, 26, 27, 73, 74, 30, 31, 77, 78 + db 65, 66, 81, 82, 69, 70, 85, 86, 73, 74, 89, 90, 77, 78, 93, 94 + db 50, 51, 97, 98, 54, 55,101,102, 58, 59,105,106, 62, 63,109,110 + db 97, 98,113,114,101,102,117,118,105,106,121,122,109,110,125,126 +spel_shuf16: db 1, 2, 33, 34, 5, 6, 37, 38, 9, 10, 41, 42, 13, 14, 45, 46 + db 17, 18, 49, 50, 21, 22, 53, 54, 25, 26, 57, 58, 29, 30, 61, 62 + db 65, 66, 97, 98, 69, 70,101,102, 73, 74,105,106, 77, 78,109,110 + db 81, 82,113,114, 85, 86,117,118, 89, 90,121,122, 93, 94,125,126 +spel_shuf32: db 1, 2, 65, 66, 5, 6, 69, 70, 9, 10, 73, 74, 13, 14, 77, 78 + db 17, 18, 81, 82, 21, 22, 85, 86, 25, 26, 89, 90, 29, 30, 93, 94 + db 33, 34, 97, 98, 37, 38,101,102, 41, 42,105,106, 45, 46,109,110 + db 49, 50,113,114, 53, 54,117,118, 57, 58,121,122, 61, 62,125,126 +spel_h_shuf2b: db 1, 2, 17, 18, 5, 6, 21, 22, 17, 18, 33, 34, 21, 22, 37, 38 + db 33, 34, 49, 50, 37, 38, 53, 54, 49, 50, 9, 10, 53, 54, 13, 14 + db 9, 10, 25, 26, 13, 14, 29, 30, 25, 26, 41, 42, 29, 30, 45, 46 +spel_shuf2: db 10, 11, 17, 18, 14, 15, 21, 22, 17, 18, 25, 26, 21, 22, 29, 30 +spel_h_shuf2a: db 0, 1, 2, 3, 2, 3, 4, 5, 16, 17, 18, 19, 18, 19, 20, 21 + db 4, 5, 6, 7, 6, 7, 8, 9, 20, 21, 22, 23, 22, 23, 24, 25 +w_mask_end42x: db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +w_mask_end444: db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 + db 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94 + db 96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126 +w_mask_shuf4: db 0, 2, 8, 10, 4, 6, 12, 14, 16, 18, 24, 26, 20, 22, 28, 30 + db 32, 34, 40, 42, 36, 38, 44, 46, 48, 50, 56, 58, 52, 54, 60, 62 + db 64, 66, 72, 74, 68, 70, 76, 78, 80, 82, 88, 90, 84, 86, 92, 94 + db 96, 98,104,106,100,102,108,110,112,114,120,122,116,118,124,126 +w_mask_shuf8: db 0, 2, 16, 18, 4, 6, 20, 22, 8, 10, 24, 26, 12, 14, 28, 30 + db 32, 34, 48, 50, 36, 38, 52, 54, 40, 42, 56, 58, 44, 46, 60, 62 + db 64, 66, 80, 82, 68, 70, 84, 86, 72, 74, 88, 90, 76, 78, 92, 94 + db 96, 98,112,114,100,102,116,118,104,106,120,122,108,110,124,126 +w_mask_shuf16: db 0, 2, 32, 34, 4, 6, 36, 38, 8, 10, 40, 42, 12, 14, 44, 46 + db 16, 18, 48, 50, 20, 22, 52, 54, 24, 26, 56, 58, 28, 30, 60, 62 + db 64, 66, 96, 98, 68, 70,100,102, 72, 74,104,106, 76, 78,108,110 + db 80, 82,112,114, 84, 86,116,118, 88, 90,120,122, 92, 94,124,126 +warp8x8_permA: db 0, 1, 2, 3, 32, 33, 34, 35, 2, 3, 4, 5, 34, 35, 36, 37 + db 4, 5, 6, 7, 36, 37, 38, 39, 6, 7, 8, 9, 38, 39, 40, 41 + db 8, 9, 10, 11, 40, 41, 42, 43, 10, 11, 12, 13, 42, 43, 44, 45 + db 12, 13, 14, 15, 44, 45, 46, 47, 14, 15, 16, 17, 46, 47, 48, 49 +warp8x8_permB: db 12, 13, 14, 15, 44, 45, 46, 47, 14, 15, 16, 17, 46, 47, 48, 49 + db 16, 17, 18, 19, 48, 49, 50, 51, 18, 19, 20, 21, 50, 51, 52, 53 + db 20, 21, 22, 23, 52, 53, 54, 55, 22, 23, 24, 25, 54, 55, 56, 57 + db 24, 25, 26, 27, 56, 57, 58, 59, 26, 27, 28, 29, 58, 59, 60, 61 +warp8x8_end: db 0, 1, 4, 5, 16, 17, 20, 21, 32, 33, 36, 37, 48, 49, 52, 53 + db 2, 3, 6, 7, 18, 19, 22, 23, 34, 35, 38, 39, 50, 51, 54, 55 + db 8, 9, 12, 13, 24, 25, 28, 29, 40, 41, 44, 45, 56, 57, 60, 61 + db 10, 11, 14, 15, 26, 27, 30, 31, 42, 43, 46, 47, 58, 59, 62, 63 +deint_q_shuf: ;dq 0, 2, 4, 6, 1, 3, 5, 7 +pd_0to7: dd 0, 1, 2, 3, 4, 5, 6, 7 + dd 1 +pw_2048: times 2 dw 2048 + dd 3 +pw_8192: times 2 dw 8192 +avg_shift: dw 5, 5, 3, 3 +pw_27615: times 2 dw 27615 +pw_32766: times 2 dw 32766 +warp8x8_permC: db -1, 0, -1, 1, -1, 8, -1, 9, -1, 4, -1, 5, -1, 12, -1, 13 +warp8x8_permD: db -1, 2, -1, 3, -1, 10, -1, 11, -1, 6, -1, 7, -1, 14, -1, 15 +warp_shift_h: db 11, 19, 11, 19, 43, 51, 43, 51, 13, 21, 13, 21, 45, 53, 45, 53 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +resize_permA: dd 0, 4, 8, 12, 1, 5, 9, 13, 16, 20, 24, 28, 17, 21, 25, 29 +resize_permB: dd 2, 6, 10, 14, 3, 7, 11, 15, 18, 22, 26, 30, 19, 23, 27, 31 +resize_permC: dq 0, 1, 4, 5, 8, 9, 12, 13 +resize_permD: dq 2, 3, 6, 7, 10, 11, 14, 15 +resize_permE: dq 0, 2, 4, 6 +resize_shufA: db -1, 0, -1, 1, -1, 4, -1, 5, -1, 8, -1, 9, -1, 12, -1, 13 +resize_shufB: db -1, 2, -1, 3, -1, 6, -1, 7, -1, 10, -1, 11, -1, 14, -1, 15 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 + +prep_hv_shift: dq 6, 4 +put_bilin_h_rnd: dw 8, 8, 10, 10 +prep_mul: dw 16, 16, 4, 4 +put_8tap_h_rnd: dd 34, 40 +prep_8tap_rnd: dd 128 - (8192 << 8) +warp_8x8_rnd_h: dd 512, 2048 +warp_8x8_rnd_v: dd 262144, 65536 +warp_8x8t_rnd_v: dd 16384 - (8192 << 15) +avg_round: dw -16400, -16400, -16388, -16388 +w_avg_round: dd 128 + (8192 << 4), 32 + (8192 << 4) +mask_round: dd 512 + (8192 << 6), 128 + (8192 << 6) +w_mask_round: dd 128, 64 +bidir_shift: dw 6, 6, 4, 4 + +pb_64: times 4 db 64 +pw_m512: times 2 dw -512 +pw_2: times 2 dw 2 +pw_64: times 2 dw 64 +pd_32: dd 32 +pd_63: dd 63 +pd_128: dd 128 +pd_640: dd 640 +pd_2176: dd 2176 +pd_16384: dd 16384 +pd_0_4: dd 0, 4 + +%define pw_16 prep_mul +%define pd_512 warp_8x8_rnd_h + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_16bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx512icl mangle(private_prefix %+ _put_bilin_16bpc_avx512icl.put) +%xdefine prep_avx512icl mangle(private_prefix %+ _prep_bilin_16bpc_avx512icl.prep) + +BIDIR_JMP_TABLE avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx512icl, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx512icl, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE put, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx512icl, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx512icl, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx512icl, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx512icl, 2, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx512icl, 2, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern obmc_masks_avx2 +cextern resize_filter + +SECTION .text + +%if WIN64 +DECLARE_REG_TMP 4 +%else +DECLARE_REG_TMP 8 +%endif + +INIT_ZMM avx512icl +cglobal put_bilin_16bpc, 4, 8, 13, dst, ds, src, ss, w, h, mxy + mov mxyd, r6m ; mx + lea r7, [put_avx512icl] + tzcnt t0d, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx t0d, word [r7+t0*2+table_offset(put,)] + add t0, r7 + jmp t0 +.put_w2: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu xmm0, [srcq+ssq*0] + movu xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], xmm0 + mova [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu ym0, [srcq+ssq*0] + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], ym0 + mova [dstq+dsq*1], ym1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+64*0], m0 + mova [dstq+dsq*0+64*1], m1 + mova [dstq+dsq*1+64*0], m2 + mova [dstq+dsq*1+64*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] + movu m2, [srcq+64*2] + movu m3, [srcq+64*3] + add srcq, ssq + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + vpbroadcastw m5, mxyd + mov mxyd, r7m ; my + vpbroadcastd m4, [pw_16] + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_h)] + mov r6d, r8m ; bitdepth_max + add t0, r7 + shr r6d, 11 + vpbroadcastd m6, [r7-put_avx512icl+put_bilin_h_rnd+r6*4] + jmp t0 +.h_w2: + movq xmm1, [srcq+ssq*0] + movhps xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw xmm0, xmm1, xm4 + psrlq xmm1, 16 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 4 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq xmm0, [srcq+ssq*0+0] + movhps xmm0, [srcq+ssq*1+0] + movq xmm1, [srcq+ssq*0+2] + movhps xmm1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw xmm0, xm4 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 4 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+ssq*0+0] + vinserti32x4 ym0, [srcq+ssq*1+0], 1 + movu xm1, [srcq+ssq*0+2] + vinserti32x4 ym1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw ym0, ym4 + pmullw ym1, ym5 + paddw ym0, ym6 + paddw ym0, ym1 + psrlw ym0, 4 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu ym0, [srcq+ssq*0+0] + vinserti32x8 m0, [srcq+ssq*1+0], 1 + movu ym1, [srcq+ssq*0+2] + vinserti32x8 m1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m6 + paddw m0, m1 + psrlw m0, 4 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m2, m5, [srcq+ssq*0+2] + pmullw m1, m4, [srcq+ssq*1+0] + pmullw m3, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m0, m6 + paddw m1, m6 + paddw m0, m2 + paddw m1, m3 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + pmullw m0, m4, [srcq+64*0+0] + pmullw m2, m5, [srcq+64*0+2] + pmullw m1, m4, [srcq+64*1+0] + pmullw m3, m5, [srcq+64*1+2] + add srcq, ssq + paddw m0, m6 + paddw m1, m6 + paddw m0, m2 + paddw m1, m3 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + pmullw m0, m4, [srcq+64*0+0] + pmullw m7, m5, [srcq+64*0+2] + pmullw m1, m4, [srcq+64*1+0] + pmullw m8, m5, [srcq+64*1+2] + pmullw m2, m4, [srcq+64*2+0] + pmullw m9, m5, [srcq+64*2+2] + pmullw m3, m4, [srcq+64*3+0] + pmullw m10, m5, [srcq+64*3+2] + add srcq, ssq + REPX {paddw x, m6}, m0, m1, m2, m3 + paddw m0, m7 + paddw m1, m8 + paddw m2, m9 + paddw m3, m10 + REPX {psrlw x, 4}, m0, m1, m2, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_v)] + shl mxyd, 11 + vpbroadcastw m8, mxyd + add t0, r7 + jmp t0 +.v_w2: + movd xmm0, [srcq+ssq*0] +.v_w2_loop: + movd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq xmm2, xmm0, xmm1 + movd xmm0, [srcq+ssq*0] + punpckldq xmm1, xmm0 + psubw xmm1, xmm2 + pmulhrsw xmm1, xm8 + paddw xmm1, xmm2 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xmm0, [srcq+ssq*0] +.v_w4_loop: + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq xmm2, xmm0, xmm1 + movq xmm0, [srcq+ssq*0] + punpcklqdq xmm1, xmm0 + psubw xmm1, xmm2 + pmulhrsw xmm1, xm8 + paddw xmm1, xmm2 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu xmm0, [srcq+ssq*0] +.v_w8_loop: + vbroadcasti128 ymm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd ymm2, ymm0, ymm1, 0xf0 + vbroadcasti128 ymm0, [srcq+ssq*0] + vpblendd ymm1, ymm0, 0xf0 + psubw ymm1, ymm2 + pmulhrsw ymm1, ym8 + paddw ymm1, ymm2 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + vzeroupper + RET +.v_w16: + movu ym0, [srcq+ssq*0] +.v_w16_loop: + movu ym3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw ym1, ym3, ym0 + pmulhrsw ym1, ym8 + paddw ym1, ym0 + movu ym0, [srcq+ssq*0] + psubw ym2, ym0, ym3 + pmulhrsw ym2, ym8 + paddw ym2, ym3 + mova [dstq+dsq*0], ym1 + mova [dstq+dsq*1], ym2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: + movu m0, [srcq+ssq*0] +.v_w32_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m8 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m8 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] +.v_w64_loop: + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + psubw m4, m2, m0 + pmulhrsw m4, m8 + paddw m4, m0 + movu m0, [srcq+ssq*0+64*0] + psubw m5, m3, m1 + pmulhrsw m5, m8 + paddw m5, m1 + movu m1, [srcq+ssq*0+64*1] + psubw m6, m0, m2 + pmulhrsw m6, m8 + psubw m7, m1, m3 + pmulhrsw m7, m8 + mova [dstq+dsq*0+64*0], m4 + mova [dstq+dsq*0+64*1], m5 + paddw m6, m2 + paddw m7, m3 + mova [dstq+dsq*1+64*0], m6 + mova [dstq+dsq*1+64*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*0+64*2] + movu m3, [srcq+ssq*0+64*3] +.v_w128_loop: + movu m4, [srcq+ssq*1+64*0] + movu m5, [srcq+ssq*1+64*1] + movu m6, [srcq+ssq*1+64*2] + movu m7, [srcq+ssq*1+64*3] + lea srcq, [srcq+ssq*2] + psubw m9, m4, m0 + pmulhrsw m9, m8 + paddw m9, m0 + movu m0, [srcq+ssq*0+64*0] + psubw m10, m5, m1 + pmulhrsw m10, m8 + paddw m10, m1 + movu m1, [srcq+ssq*0+64*1] + psubw m11, m6, m2 + pmulhrsw m11, m8 + paddw m11, m2 + movu m2, [srcq+ssq*0+64*2] + psubw m12, m7, m3 + pmulhrsw m12, m8 + paddw m12, m3 + movu m3, [srcq+ssq*0+64*3] + mova [dstq+dsq*0+64*0], m9 + psubw m9, m0, m4 + pmulhrsw m9, m8 + mova [dstq+dsq*0+64*1], m10 + psubw m10, m1, m5 + pmulhrsw m10, m8 + mova [dstq+dsq*0+64*2], m11 + psubw m11, m2, m6 + pmulhrsw m11, m8 + mova [dstq+dsq*0+64*3], m12 + psubw m12, m3, m7 + pmulhrsw m12, m8 + paddw m9, m4 + paddw m10, m5 + mova [dstq+dsq*1+64*0], m9 + mova [dstq+dsq*1+64*1], m10 + paddw m11, m6 + paddw m12, m7 + mova [dstq+dsq*1+64*2], m11 + mova [dstq+dsq*1+64*3], m12 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w128_loop + RET +.hv: + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_hv)] + shl mxyd, 11 + vpbroadcastd m6, [pw_2] + vpbroadcastw m7, mxyd + vpbroadcastd m8, [pw_8192] + add t0, r7 + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + vpbroadcastd m8, [pw_2048] +.hv_12bpc: + jmp t0 +.hv_w2: + vpbroadcastq xmm1, [srcq+ssq*0] + pmullw xmm0, xmm1, xm4 + psrlq xmm1, 16 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 +.hv_w2_loop: + movq xmm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm2, [srcq+ssq*0] + pmullw xmm1, xmm2, xm4 + psrlq xmm2, 16 + pmullw xmm2, xm5 + paddw xmm1, xm6 + paddw xmm1, xmm2 + psrlw xmm1, 2 ; 1 _ 2 _ + shufpd xmm2, xmm0, xmm1, 0x01 ; 0 _ 1 _ + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm7 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm8 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + pmullw xmm0, xm4, [srcq+ssq*0-8] + pmullw xmm1, xm5, [srcq+ssq*0-6] + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 +.hv_w4_loop: + movq xmm1, [srcq+ssq*1+0] + movq xmm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps xmm1, [srcq+ssq*0+0] + movhps xmm2, [srcq+ssq*0+2] + pmullw xmm1, xm4 + pmullw xmm2, xm5 + paddw xmm1, xm6 + paddw xmm1, xmm2 + psrlw xmm1, 2 ; 1 2 + shufpd xmm2, xmm0, xmm1, 0x01 ; 0 1 + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm7 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm8 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xmm0, xm4, [srcq+ssq*0+0] + pmullw xmm1, xm5, [srcq+ssq*0+2] + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 + vinserti32x4 ym0, xmm0, 1 +.hv_w8_loop: + movu xm1, [srcq+ssq*1+0] + movu xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym1, [srcq+ssq*0+0], 1 + vinserti32x4 ym2, [srcq+ssq*0+2], 1 + pmullw ym1, ym4 + pmullw ym2, ym5 + paddw ym1, ym6 + paddw ym1, ym2 + psrlw ym1, 2 ; 1 2 + vshufi32x4 ym2, ym0, ym1, 0x01 ; 0 1 + mova ym0, ym1 + psubw ym1, ym2 + paddw ym1, ym1 + pmulhw ym1, ym7 + paddw ym1, ym2 + pmulhrsw ym1, ym8 + mova [dstq+dsq*0], xm1 + vextracti32x4 [dstq+dsq*1], ym1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + pmullw ym0, ym4, [srcq+ssq*0+0] + pmullw ym1, ym5, [srcq+ssq*0+2] + paddw ym0, ym6 + paddw ym0, ym1 + psrlw ym0, 2 + vinserti32x8 m0, ym0, 1 +.hv_w16_loop: + movu ym1, [srcq+ssq*1+0] + movu ym2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti32x8 m1, [srcq+ssq*0+0], 1 + vinserti32x8 m2, [srcq+ssq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + vshufi32x4 m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m7 + paddw m1, m2 + pmulhrsw m1, m8 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: +.hv_w64: +.hv_w128: + movifnidn wd, wm + lea r6d, [hq+wq*8-256] + mov r4, srcq + mov r7, dstq +.hv_w32_loop0: + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m6 + paddw m0, m1 + psrlw m0, 2 +.hv_w32_loop: + pmullw m3, m4, [srcq+ssq*1+0] + pmullw m1, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m3, m6 + paddw m3, m1 + psrlw m3, 2 + psubw m1, m3, m0 + paddw m1, m1 + pmulhw m1, m7 + paddw m1, m0 + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m2, m5, [srcq+ssq*0+2] + paddw m0, m6 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m3 + paddw m2, m2 + pmulhw m2, m7 + paddw m2, m3 + pmulhrsw m1, m8 + pmulhrsw m2, m8 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + add r4, 64 + add r7, 64 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w32_loop0 + RET + +cglobal prep_bilin_16bpc, 3, 7, 16, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [r6-prep_avx512icl+pw_8192] + add wq, r6 + shr r5d, 11 + vpbroadcastd m4, [r6-prep_avx512icl+prep_mul+r5*4] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq xmm0, [srcq+strideq*0] + movhps xmm0, [srcq+strideq*1] + vpbroadcastq ymm1, [srcq+strideq*2] + vpbroadcastq ymm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm0, ymm1, 0x30 + vpblendd ymm0, ymm2, 0xc0 + pmullw ymm0, ym4 + psubw ymm0, ym5 + mova [tmpq], ymm0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + vzeroupper + RET +.prep_w8: + movu xm0, [srcq+strideq*0] + vinserti32x4 ym0, [srcq+strideq*1], 1 + vinserti32x4 m0, [srcq+strideq*2], 2 + vinserti32x4 m0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + psubw m0, m5 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + movu ym1, [srcq+strideq*2] + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m4, [srcq+strideq*2] + pmullw m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .prep_w32 + RET +.prep_w64: + pmullw m0, m4, [srcq+strideq*0+64*0] + pmullw m1, m4, [srcq+strideq*0+64*1] + pmullw m2, m4, [srcq+strideq*1+64*0] + pmullw m3, m4, [srcq+strideq*1+64*1] + lea srcq, [srcq+strideq*2] + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .prep_w64 + RET +.prep_w128: + pmullw m0, m4, [srcq+64*0] + pmullw m1, m4, [srcq+64*1] + pmullw m2, m4, [srcq+64*2] + pmullw m3, m4, [srcq+64*3] + add srcq, strideq + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + dec hd + jg .prep_w128 + RET +.h: + vpbroadcastw m5, mxyd + mov mxyd, r6m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastd m6, [pw_32766] + psubw m4, m5 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m4, 2 + psllw m5, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + movu xm1, [srcq+strideq*0] + vinserti32x4 ym1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti32x4 ym2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1, ym2 + psrldq ym1, 2 + psrldq ym2, 2 + pmullw ym0, ym4 + punpcklqdq ym1, ym2 + pmullw ym1, ym5 + psubw ym0, ym6 + paddw ym0, ym1 + psraw ym0, 2 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+strideq*0+0] + movu xm1, [srcq+strideq*0+2] + vinserti32x4 ym0, [srcq+strideq*1+0], 1 + vinserti32x4 ym1, [srcq+strideq*1+2], 1 + vinserti32x4 m0, [srcq+strideq*2+0], 2 + vinserti32x4 m1, [srcq+strideq*2+2], 2 + vinserti32x4 m0, [srcq+stride3q +0], 3 + vinserti32x4 m1, [srcq+stride3q +2], 3 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8 + RET +.h_w16: + movu ym0, [srcq+strideq*0+0] + vinserti32x8 m0, [srcq+strideq*1+0], 1 + movu ym1, [srcq+strideq*0+2] + vinserti32x8 m1, [srcq+strideq*1+2], 1 + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m2, m5, [srcq+strideq*0+2] + pmullw m1, m4, [srcq+strideq*1+0] + pmullw m3, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 2 + jg .h_w32 + RET +.h_w64: + pmullw m0, m4, [srcq+ 0] + pmullw m2, m5, [srcq+ 2] + pmullw m1, m4, [srcq+64] + pmullw m3, m5, [srcq+66] + add srcq, strideq + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + dec hd + jg .h_w64 + RET +.h_w128: + pmullw m0, m4, [srcq+ 0] + pmullw m7, m5, [srcq+ 2] + pmullw m1, m4, [srcq+ 64] + pmullw m8, m5, [srcq+ 66] + pmullw m2, m4, [srcq+128] + pmullw m9, m5, [srcq+130] + pmullw m3, m4, [srcq+192] + pmullw m10, m5, [srcq+194] + add srcq, strideq + REPX {psubw x, m6}, m0, m1, m2, m3 + paddw m0, m7 + paddw m1, m8 + paddw m2, m9 + paddw m3, m10 + REPX {psraw x, 2}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + vpbroadcastw m9, mxyd + vpbroadcastd m8, [pw_16] + vpbroadcastd m10, [pw_32766] + add wq, r6 + lea stride3q, [strideq*3] + psubw m8, m9 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m8, 2 + psllw m9, 2 +.v_12bpc: + jmp wq +.v_w4: + movq xmm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastq xmm2, [srcq+strideq*1] + vpbroadcastq ymm1, [srcq+strideq*2] + vpbroadcastq ymm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm2, ymm1, 0x30 + vpblendd ymm2, ymm3, 0xc0 + vpblendd ymm1, ymm2, ymm0, 0x03 ; 0 1 2 3 + movq xmm0, [srcq+strideq*0] + valignq ymm2, ymm0, ymm2, 1 ; 1 2 3 4 + pmullw ymm1, ym8 + pmullw ymm2, ym9 + psubw ymm1, ym10 + paddw ymm1, ymm2 + psraw ymm1, 2 + mova [tmpq], ymm1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + movu xm0, [srcq+strideq*0] +.v_w8_loop: + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vinserti32x4 m1, [srcq+strideq*2], 2 + vinserti32x4 m1, [srcq+stride3q ], 3 ; 0 1 2 3 + lea srcq, [srcq+strideq*4] + movu xm0, [srcq+strideq*0] + valignq m2, m0, m1, 2 ; 1 2 3 4 + pmullw m1, m8 + pmullw m2, m9 + psubw m1, m10 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + movu ym0, [srcq+strideq*0] +.v_w16_loop: + vinserti32x8 m1, m0, [srcq+strideq*1], 1 ; 0 1 + movu ym3, [srcq+strideq*2] + vinserti32x8 m2, m3, [srcq+stride3q ], 1 ; 2 3 + lea srcq, [srcq+strideq*4] + movu ym0, [srcq+strideq*0] + vshufi32x4 m3, m1, m3, q1032 ; 1 2 + vshufi32x4 m4, m2, m0, q1032 ; 3 4 + pmullw m1, m8 + pmullw m2, m8 + pmullw m3, m9 + pmullw m4, m9 + psubw m1, m10 + psubw m2, m10 + paddw m1, m3 + paddw m2, m4 + psraw m1, 2 + psraw m2, 2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + movu m0, [srcq+strideq*0] +.v_w32_loop: + movu m3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m1, m8, m0 + movu m0, [srcq+strideq*0] + pmullw m2, m8, m3 + pmullw m3, m9 + pmullw m4, m9, m0 + psubw m1, m10 + psubw m2, m10 + paddw m1, m3 + paddw m2, m4 + psraw m1, 2 + psraw m2, 2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] +.v_w64_loop: + add srcq, strideq + pmullw m2, m8, m0 + movu m0, [srcq+64*0] + pmullw m3, m8, m1 + movu m1, [srcq+64*1] + pmullw m4, m9, m0 + pmullw m5, m9, m1 + psubw m2, m10 + psubw m3, m10 + paddw m2, m4 + paddw m3, m5 + psraw m2, 2 + psraw m3, 2 + mova [tmpq+64*0], m2 + mova [tmpq+64*1], m3 + add tmpq, 64*2 + dec hd + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] + movu m2, [srcq+64*2] + movu m3, [srcq+64*3] +.v_w128_loop: + add srcq, strideq + pmullw m4, m8, m0 + movu m0, [srcq+64*0] + pmullw m5, m8, m1 + movu m1, [srcq+64*1] + pmullw m6, m8, m2 + movu m2, [srcq+64*2] + pmullw m7, m8, m3 + movu m3, [srcq+64*3] + pmullw m11, m9, m0 + pmullw m12, m9, m1 + pmullw m13, m9, m2 + pmullw m14, m9, m3 + REPX {psubw x, m10}, m4, m5, m6, m7 + paddw m4, m11 + paddw m5, m12 + paddw m6, m13 + paddw m7, m14 + REPX {psraw x, 2}, m4, m5, m6, m7 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m5 + mova [tmpq+64*2], m6 + mova [tmpq+64*3], m7 + add tmpq, 64*4 + dec hd + jg .v_w128_loop + RET +.hv: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + vpbroadcastw m7, mxyd + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + movq xmm0, [srcq+strideq*0+0] + movq xmm1, [srcq+strideq*0+2] + pmullw xmm0, xm4 + pmullw xmm1, xm5 + psubw xmm0, xm6 + paddw xmm0, xmm1 + psraw xmm0, 2 + vpbroadcastq ym0, xmm0 +.hv_w4_loop: + movu xm1, [srcq+strideq*1] + vinserti128 ym1, [srcq+stride3q ], 1 + movu xm2, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vinserti128 ym2, [srcq+strideq*0], 1 + punpcklqdq ym3, ym1, ym2 + psrldq ym1, 2 + psrldq ym2, 2 + pmullw ym3, ym4 + punpcklqdq ym1, ym2 + pmullw ym1, ym5 + psubw ym3, ym6 + paddw ym1, ym3 + psraw ym1, 2 ; 1 2 3 4 + valignq ym2, ym1, ym0, 3 ; 0 1 2 3 + mova ym0, ym1 + psubw ym1, ym2 + pmulhrsw ym1, ym7 + paddw ym1, ym2 + mova [tmpq], ym1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xm0, xm4, [srcq+strideq*0+0] + pmullw xm1, xm5, [srcq+strideq*0+2] + psubw xm0, xm6 + paddw xm0, xm1 + psraw xm0, 2 + vinserti32x4 m0, xm0, 3 +.hv_w8_loop: + movu xm1, [srcq+strideq*1+0] + movu xm2, [srcq+strideq*1+2] + vinserti32x4 ym1, [srcq+strideq*2+0], 1 + vinserti32x4 ym2, [srcq+strideq*2+2], 1 + vinserti32x4 m1, [srcq+stride3q +0], 2 + vinserti32x4 m2, [srcq+stride3q +2], 2 + lea srcq, [srcq+strideq*4] + vinserti32x4 m1, [srcq+strideq*0+0], 3 + vinserti32x4 m2, [srcq+strideq*0+2], 3 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m6 + paddw m1, m2 + psraw m1, 2 ; 1 2 3 4 + valignq m2, m1, m0, 6 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m7 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + pmullw ym0, ym4, [srcq+strideq*0+0] + pmullw ym1, ym5, [srcq+strideq*0+2] + psubw ym0, ym6 + paddw ym0, ym1 + psraw ym0, 2 + vinserti32x8 m0, ym0, 1 +.hv_w16_loop: + movu ym1, [srcq+strideq*1+0] + movu ym2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + vinserti32x8 m1, [srcq+strideq*0+0], 1 + vinserti32x8 m2, [srcq+strideq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m6 + paddw m1, m2 + psraw m1, 2 ; 1 2 + vshufi32x4 m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m7 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m1, m5, [srcq+strideq*0+2] + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 +.hv_w32_loop: + pmullw m3, m4, [srcq+strideq*1+0] + pmullw m1, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m3, m6 + paddw m3, m1 + psraw m3, 2 + psubw m1, m3, m0 + pmulhrsw m1, m7 + paddw m1, m0 + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m2, m5, [srcq+strideq*0+2] + psubw m0, m6 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m3 + pmulhrsw m2, m7 + paddw m2, m3 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + pmullw m0, m4, [srcq+ 0] + pmullw m2, m5, [srcq+ 2] + pmullw m1, m4, [srcq+64] + pmullw m3, m5, [srcq+66] + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 +.hv_w64_loop: + add srcq, strideq + pmullw m2, m4, [srcq+ 0] + pmullw m8, m5, [srcq+ 2] + pmullw m3, m4, [srcq+64] + pmullw m9, m5, [srcq+66] + psubw m2, m6 + psubw m3, m6 + paddw m2, m8 + paddw m3, m9 + psraw m2, 2 + psraw m3, 2 + psubw m8, m2, m0 + psubw m9, m3, m1 + pmulhrsw m8, m7 + pmulhrsw m9, m7 + paddw m8, m0 + mova m0, m2 + paddw m9, m1 + mova m1, m3 + mova [tmpq+64*0], m8 + mova [tmpq+64*1], m9 + add tmpq, 64*2 + dec hd + jg .hv_w64_loop + RET +.hv_w128: + pmullw m0, m4, [srcq+ 0] + pmullw m8, m5, [srcq+ 2] + pmullw m1, m4, [srcq+ 64] + pmullw m9, m5, [srcq+ 66] + pmullw m2, m4, [srcq+128] + pmullw m10, m5, [srcq+130] + pmullw m3, m4, [srcq+192] + pmullw m11, m5, [srcq+194] + REPX {psubw x, m6}, m0, m1, m2, m3 + paddw m0, m8 + paddw m1, m9 + paddw m2, m10 + paddw m3, m11 + REPX {psraw x, 2}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, strideq + pmullw m8, m4, [srcq+ 0] + pmullw m12, m5, [srcq+ 2] + pmullw m9, m4, [srcq+ 64] + pmullw m13, m5, [srcq+ 66] + pmullw m10, m4, [srcq+128] + pmullw m14, m5, [srcq+130] + pmullw m11, m4, [srcq+192] + pmullw m15, m5, [srcq+194] + REPX {psubw x, m6}, m8, m9, m10, m11 + paddw m8, m12 + paddw m9, m13 + paddw m10, m14 + paddw m11, m15 + REPX {psraw x, 2}, m8, m9, m10, m11 + psubw m12, m8, m0 + psubw m13, m9, m1 + psubw m14, m10, m2 + psubw m15, m11, m3 + REPX {pmulhrsw x, m7}, m12, m13, m14, m15 + paddw m12, m0 + mova m0, m8 + paddw m13, m1 + mova m1, m9 + mova [tmpq+64*0], m12 + mova [tmpq+64*1], m13 + paddw m14, m2 + mova m2, m10 + paddw m15, m3 + mova m3, m11 + mova [tmpq+64*2], m14 + mova [tmpq+64*3], m15 + add tmpq, 64*4 + dec hd + jg .hv_w128_loop + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro MC_8TAP_FN 4 ; prefix, type, type_h, type_v +cglobal %1_8tap_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8tap_16bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%define buf rsp+stack_offset+8 ; shadow space +%else +DECLARE_REG_TMP 7, 8 +%define buf rsp-40 ; red zone +%endif + +MC_8TAP_FN put, sharp, SHARP, SHARP +MC_8TAP_FN put, sharp_smooth, SHARP, SMOOTH +MC_8TAP_FN put, smooth_sharp, SMOOTH, SHARP +MC_8TAP_FN put, smooth, SMOOTH, SMOOTH +MC_8TAP_FN put, sharp_regular, SHARP, REGULAR +MC_8TAP_FN put, regular_sharp, REGULAR, SHARP +MC_8TAP_FN put, smooth_regular, SMOOTH, REGULAR +MC_8TAP_FN put, regular_smooth, REGULAR, SMOOTH +MC_8TAP_FN put, regular, REGULAR, REGULAR + +cglobal put_8tap_16bpc, 4, 9, 16, dst, ds, src, ss, w, h, mx, my +%define base r8-put_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx512icl] + movifnidn wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 +%if WIN64 + pop r8 +%endif + jmp wq +.h_w2: + movzx mxd, mxb + sub srcq, 2 + mova ym2, [spel_h_shuf2a] + pmovsxbw xmm4, [base+subpel_filters+mxq*8] + pshufd xmm3, xmm4, q1111 + pshufd xmm4, xmm4, q2222 +.h_w2_loop: + movu xm1, [srcq+ssq*0] + vinserti32x4 ym1, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova xmm0, xm8 + vpermb ym1, ym2, ym1 + vpdpwssd xmm0, xmm3, xm1 + vextracti32x4 xm1, ym1, 1 + vpdpwssd xmm0, xmm4, xm1 + psrad xmm0, 6 + packusdw xmm0, xmm0 + pminsw xmm0, xm9 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + vbroadcasti32x4 ym4, [spel_h_shufA] + vbroadcasti32x4 ym5, [spel_h_shufB] + pshufd xmm0, xmm0, q2211 + vpbroadcastq ym6, xmm0 + vpermq ym7, ymm0, q1111 +.h_w4_loop: + movu xm2, [srcq+ssq*0] + vinserti32x4 ym2, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova ym0, ym8 + pshufb ym1, ym2, ym4 + vpdpwssd ym0, ym6, ym1 + pshufb ym2, ym5 + vpdpwssd ym0, ym7, ym2 + psrad ym0, 6 + vextracti32x4 xm1, ym0, 1 + packusdw xm0, xm1 + pminsw xmm0, xm0, xm9 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + mov r7d, r8m + vpbroadcastw m9, r8m + shr r7d, 11 + vpbroadcastd m8, [base+put_8tap_h_rnd+r7*4] + cmp wd, 4 + je .h_w4 + jl .h_w2 + shr mxd, 16 + sub srcq, 6 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mova [buf], xmm0 + vpbroadcastd m10, xmm0 + vpbroadcastd m11, [buf+ 4] + vpbroadcastd m12, [buf+ 8] + vpbroadcastd m13, [buf+12] + sub wd, 16 + je .h_w16 + jg .h_w32 +.h_w8: + mova m4, [spel_h_shufA] + movu m5, [spel_h_shufB] + movu m6, [spel_h_shufC] + mova m7, [spel_h_shufD] +.h_w8_loop: + movu ym2, [srcq+ssq*0] + vinserti32x8 m2, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova m0, m8 + vpermb m1, m4, m2 + vpdpwssd m0, m10, m1 + vpermb m1, m5, m2 + vpdpwssd m0, m11, m1 + vpermb m1, m6, m2 + vpdpwssd m0, m12, m1 + vpermb m1, m7, m2 + vpdpwssd m0, m13, m1 + psrad m0, 6 + vextracti32x8 ym1, m0, 1 + packusdw ym0, ym1 + pminsw ym0, ym9 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8_loop + RET +.h_w16: + vbroadcasti32x4 m6, [spel_h_shufA] + vbroadcasti32x4 m7, [spel_h_shufB] +.h_w16_loop: + movu ym2, [srcq+ssq*0+ 0] + vinserti32x8 m2, [srcq+ssq*1+ 0], 1 + movu ym3, [srcq+ssq*0+16] + vinserti32x8 m3, [srcq+ssq*1+16], 1 + lea srcq, [srcq+ssq*2] + mova m0, m8 + mova m1, m8 + pshufb m4, m2, m6 + vpdpwssd m0, m10, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m12, m4 ; b2 + pshufb m4, m2, m7 + vpdpwssd m0, m11, m4 ; a1 + pshufb m4, m3, m7 + vpdpwssd m1, m13, m4 ; b3 + shufpd m2, m3, 0x55 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a2 + vpdpwssd m1, m10, m4 ; b0 + pshufb m2, m7 + vpdpwssd m0, m13, m2 ; a3 + vpdpwssd m1, m11, m2 ; b1 + psrad m0, 6 + psrad m1, 6 + packusdw m0, m1 + pminsw m0, m9 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + lea srcq, [srcq+wq*2] + vbroadcasti32x4 m6, [spel_h_shufA] + lea dstq, [dstq+wq*2] + vbroadcasti32x4 m7, [spel_h_shufB] + neg wq +.h_w32_loop0: + mov r6, wq +.h_w32_loop: + movu m2, [srcq+r6*2+ 0] + movu m3, [srcq+r6*2+ 8] + mova m0, m8 + mova m1, m8 + pshufb m4, m2, m6 + vpdpwssd m0, m10, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m10, m4 ; b0 + vpdpwssd m0, m12, m4 ; a2 + movu m4, [srcq+r6*2+16] + pshufb m3, m7 + vpdpwssd m1, m11, m3 ; b1 + vpdpwssd m0, m13, m3 ; a3 + pshufb m3, m4, m6 + vpdpwssd m1, m12, m3 ; b2 + pshufb m2, m7 + vpdpwssd m0, m11, m2 ; a1 + pshufb m4, m7 + vpdpwssd m1, m13, m4 ; b3 + psrad m0, 6 + psrad m1, 6 + packusdw m0, m1 + pminsw m0, m9 + mova [dstq+r6*2], m0 + add r6, 32 + jl .h_w32_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w32_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m10, [pd_32] + pmovsxbw xmm0, [base+subpel_filters+myq*8] + tzcnt r7d, wd + vpbroadcastw m11, r8m + lea r6, [ssq*3] + movzx r7d, word [r8+r7*2+table_offset(put, _8tap_v)] + sub srcq, r6 + mova [rsp+stack_offset+8], xmm0 + vpbroadcastd m12, xmm0 + add r7, r8 + vpbroadcastd m13, [rsp+stack_offset+12] + vpbroadcastd m14, [rsp+stack_offset+16] + vpbroadcastd m15, [rsp+stack_offset+20] + jmp r7 +.v_w2: + movd xmm2, [srcq+ssq*0] + pinsrd xmm2, [srcq+ssq*1], 1 + pinsrd xmm2, [srcq+ssq*2], 2 + add srcq, r6 + pinsrd xmm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, r6 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklwd xmm3, xmm1 ; 45 56 + punpcklwd xmm1, xmm2, xmm4 ; 01 12 + punpckhwd xmm2, xmm4 ; 23 34 +.v_w2_loop: + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xmm5, xm10 + vpdpwssd xmm5, xm12, xmm1 ; a0 b0 + mova xmm1, xmm2 + vpdpwssd xmm5, xm13, xmm2 ; a1 b1 + mova xmm2, xmm3 + vpdpwssd xmm5, xm14, xmm3 ; a2 b2 + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm0, 0x02 ; 7 8 + punpcklwd xmm3, xmm4 ; 67 78 + vpdpwssd xmm5, xm15, xmm3 ; a3 b3 + psrad xmm5, 6 + packusdw xmm5, xmm5 + pminsw xmm5, xm11 + movd [dstq+dsq*0], xmm5 + pextrd [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xmm1, [srcq+ssq*0] + vpbroadcastq ymm0, [srcq+ssq*1] + vpbroadcastq ymm2, [srcq+ssq*2] + add srcq, r6 + vpbroadcastq ymm4, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm5, [srcq+ssq*2] + add srcq, r6 + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklwd ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm4, 0x30 + vpblendd ymm4, ymm3, 0x30 + punpcklwd ymm2, ymm4 ; 23 34 + vpblendd ymm3, ymm5, 0x30 + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 45 56 +.v_w4_loop: + vpbroadcastq ymm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova ymm4, ym10 + vpdpwssd ymm4, ym12, ymm1 ; a0 b0 + mova ymm1, ymm2 + vpdpwssd ymm4, ym13, ymm2 ; a1 b1 + mova ymm2, ymm3 + vpdpwssd ymm4, ym14, ymm3 ; a2 b2 + vpblendd ymm3, ymm0, ymm5, 0x30 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 67 78 + vpdpwssd ymm4, ym15, ymm3 ; a3 b3 + psrad ymm4, 6 + vextracti128 xmm5, ymm4, 1 + packusdw xmm4, xmm5 + pminsw xmm4, xm11 + movq [dstq+dsq*0], xmm4 + movhps [dstq+dsq*1], xmm4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + vbroadcasti32x4 m2, [srcq+ssq*2] + vinserti32x4 m1, m2, [srcq+ssq*0], 0 + vinserti32x4 m1, [srcq+ssq*1], 1 ; 0 1 2 + add srcq, r6 + vinserti32x4 ym2, [srcq+ssq*0], 1 + vinserti32x4 m2, [srcq+ssq*1], 2 ; 2 3 4 + mova m6, [spel_v_shuf8] + movu xm0, [srcq+ssq*1] + vinserti32x4 ym0, [srcq+ssq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+ssq*0], 2 ; 4 5 6 + vpermb m1, m6, m1 ; 01 12 + vpermb m2, m6, m2 ; 23 34 + vpermb m3, m6, m0 ; 45 56 +.v_w8_loop: + vinserti32x4 m0, [srcq+ssq*1], 3 + lea srcq, [srcq+ssq*2] + movu xm5, [srcq+ssq*0] + mova m4, m10 + vpdpwssd m4, m12, m1 ; a0 b0 + mova m1, m2 + vshufi32x4 m0, m5, q1032 ; 6 7 8 + vpdpwssd m4, m13, m2 ; a1 b1 + mova m2, m3 + vpdpwssd m4, m14, m3 ; a2 b2 + vpermb m3, m6, m0 ; 67 78 + vpdpwssd m4, m15, m3 ; a3 b3 + psrad m4, 6 + vextracti32x8 ym5, m4, 1 + packusdw ym4, ym5 + pminsw ym4, ym11 + mova [dstq+dsq*0], xm4 + vextracti32x4 [dstq+dsq*1], ym4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti32x8 m1, [srcq+ssq*1] + vinserti32x8 m0, m1, [srcq+ssq*0], 0 + vinserti32x8 m1, [srcq+ssq*2], 1 + mova m8, [spel_v_shuf16] + add srcq, r6 + movu ym3, [srcq+ssq*0] + vinserti32x8 m3, [srcq+ssq*1], 1 + movu ym5, [srcq+ssq*2] + add srcq, r6 + vinserti32x8 m5, [srcq+ssq*0], 1 + vpermb m0, m8, m0 ; 01 + vpermb m1, m8, m1 ; 12 + vpermb m3, m8, m3 ; 34 + vpermb m5, m8, m5 ; 56 + mova m9, [deint_q_shuf] + vpshrdd m2, m1, m3, 16 ; 23 + vpshrdd m4, m3, m5, 16 ; 45 +.v_w16_loop: + mova m6, m10 + mova m7, m10 + vpdpwssd m6, m12, m0 ; a0 + mova m0, m2 + vpdpwssd m7, m12, m1 ; b0 + mova m1, m3 + vpdpwssd m6, m13, m2 ; a1 + mova m2, m4 + vpdpwssd m7, m13, m3 ; b1 + mova m3, m5 + vpdpwssd m6, m14, m4 ; a2 + mova m4, m5 + vpdpwssd m7, m14, m5 ; b2 + movu ym5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m5, [srcq+ssq*0], 1 + vpermb m5, m8, m5 ; 78 + vpshrdd m4, m5, 16 ; 67 + vpdpwssd m6, m15, m4 ; a3 + vpdpwssd m7, m15, m5 ; b3 + psrad m6, 6 + psrad m7, 6 + packusdw m6, m7 + pminsw m6, m11 + vpermq m6, m9, m6 + mova [dstq+dsq*0], ym6 + vextracti32x8 [dstq+dsq*1], m6, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + movaps [rsp+stack_offset+8], xmm6 +%endif + lea wd, [hq+wq*8-256] + mov r7, srcq + mov r8, dstq +.v_w32_loop0: + movu m16, [srcq+ssq*0] + movu m17, [srcq+ssq*1] + movu m18, [srcq+ssq*2] + add srcq, r6 + movu m19, [srcq+ssq*0] + movu m20, [srcq+ssq*1] + movu m21, [srcq+ssq*2] + add srcq, r6 + movu m22, [srcq+ssq*0] + punpcklwd m0, m16, m17 ; 01l + punpckhwd m16, m17 ; 01h + punpcklwd m1, m17, m18 ; 12l + punpckhwd m17, m18 ; 12h + punpcklwd m2, m18, m19 ; 23l + punpckhwd m18, m19 ; 23h + punpcklwd m3, m19, m20 ; 34l + punpckhwd m19, m20 ; 34h + punpcklwd m4, m20, m21 ; 45l + punpckhwd m20, m21 ; 45h + punpcklwd m5, m21, m22 ; 56l + punpckhwd m21, m22 ; 56h +.v_w32_loop: + mova m6, m10 + vpdpwssd m6, m12, m0 ; a0l + mova m8, m10 + vpdpwssd m8, m12, m16 ; a0h + mova m7, m10 + vpdpwssd m7, m12, m1 ; b0l + mova m9, m10 + vpdpwssd m9, m12, m17 ; b0h + mova m0, m2 + vpdpwssd m6, m13, m2 ; a1l + mova m16, m18 + vpdpwssd m8, m13, m18 ; a1h + mova m1, m3 + vpdpwssd m7, m13, m3 ; b1l + mova m17, m19 + vpdpwssd m9, m13, m19 ; b1h + mova m2, m4 + vpdpwssd m6, m14, m4 ; a2l + mova m18, m20 + vpdpwssd m8, m14, m20 ; a2h + mova m3, m5 + vpdpwssd m7, m14, m5 ; b2l + mova m19, m21 + vpdpwssd m9, m14, m21 ; b2h + movu m21, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m4, m22, m21 ; 67l + punpckhwd m20, m22, m21 ; 67h + movu m22, [srcq+ssq*0] + vpdpwssd m6, m15, m4 ; a3l + vpdpwssd m8, m15, m20 ; a3h + punpcklwd m5, m21, m22 ; 78l + punpckhwd m21, m22 ; 78h + vpdpwssd m7, m15, m5 ; b3l + vpdpwssd m9, m15, m21 ; b3h + REPX {psrad x, 6}, m6, m8, m7, m9 + packusdw m6, m8 + packusdw m7, m9 + pminsw m6, m11 + pminsw m7, m11 + mova [dstq+dsq*0], m6 + mova [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + add r7, 64 + add r8, 64 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .v_w32_loop0 +%if WIN64 + movaps xmm6, [rsp+stack_offset+8] +%endif + vzeroupper + RET +.hv: + vpbroadcastw m11, r8m + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 + test dword r8m, 0x800 + jnz .hv_12bit + vpbroadcastd m10, [pd_2176] + psllw xmm0, 6 + jmp .hv_main +.hv_12bit: + vpbroadcastd m10, [pd_640] + psllw xmm0, 4 + psllw xmm1, 2 +.hv_main: + mova [buf+ 0], xmm0 + mova [buf+16], xmm1 + vpbroadcastd m8, [buf+ 4] + vpbroadcastd m9, [buf+ 8] + vpbroadcastd ym12, xmm1 + vpbroadcastd ym13, [buf+20] + vpbroadcastd ym14, [buf+24] + vpbroadcastd ym15, [buf+28] + movu xm4, [srcq+ssq*0] + vinserti32x4 ym4, [srcq+ssq*1], 1 + vinserti32x4 m4, [srcq+ssq*2], 2 + add srcq, r6 + vinserti32x4 m4, [srcq+ssq*0], 3 ; 0 1 2 3 + movu xm0, [srcq+ssq*1] + vinserti32x4 ym0, [srcq+ssq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+ssq*0], 2 ; 4 5 6 + cmp wd, 4 + je .hv_w4 + vbroadcasti32x4 m2, [spel_h_shufA] + mova m3, [spel_h_shuf2b] + mova ym6, [spel_h_shuf2a] + mova xm7, [spel_shuf2] + mova m1, m10 + pshufb m4, m2 + pshufb m0, m2 + punpcklqdq m2, m4, m0 + vpdpwssd m1, m8, m2 ; 04 15 26 3_ + punpckhqdq m4, m0 + vpdpwssd m1, m9, m4 + vpermb m1, m3, m1 ; 01 12 + vextracti32x4 xm2, ym1, 1 ; 23 34 + vextracti32x4 xm3, m1, 2 ; 45 56 +.hv_w2_loop: + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym5, [srcq+ssq*0], 1 + mova xm4, xm10 + vpermb ym5, ym6, ym5 + pmaddwd xmm0, xm12, xm1 ; a0 b0 + vpdpwssd xm4, xm8, xm5 + vextracti32x4 xm5, ym5, 1 + mova xm1, xm2 + vpdpwssd xmm0, xm13, xm2 ; a1 b1 + vpdpwssd xm4, xm9, xm5 ; 7 8 + mova xm2, xm3 + vpdpwssd xmm0, xm14, xm3 ; a2 b2 + vpermt2b xm3, xm7, xm4 ; 67 78 + vpdpwssd xmm0, xm15, xm3 ; a3 b3 + psrad xmm0, 10 + packusdw xmm0, xmm0 + pminsw xmm0, xm11 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + vbroadcasti32x4 m19, [spel_h_shufA] + vbroadcasti32x4 m20, [spel_h_shufB] + mova ym6, [spel_shuf4a] + mova ym7, [spel_shuf4b] + mova m2, m10 + mova m3, m10 + pshufb m1, m4, m19 + vpdpwssd m2, m8, m1 + pshufb m1, m0, m19 + vpdpwssd m3, m8, m1 + pshufb m4, m20 + vpdpwssd m2, m9, m4 + pshufb m0, m20 + vpdpwssd m3, m9, m0 + vpermb m1, m6, m2 ; 01 12 + vshufi32x4 m2, m3, q1032 + vpermb m3, m6, m3 ; 45 56 + vpermb m2, m6, m2 ; 23 34 +.hv_w4_loop: + movu xm18, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 ym18, [srcq+ssq*0], 1 + mova ym4, ym10 + pshufb ym17, ym18, ym19 + pmaddwd ym16, ym12, ym1 ; a0 b0 + vpdpwssd ym4, ym8, ym17 + pshufb ym18, ym20 + mova ym1, ym2 + vpdpwssd ym16, ym13, ym2 ; a1 b1 + vpdpwssd ym4, ym9, ym18 ; 7 8 + mova ym2, ym3 + vpdpwssd ym16, ym14, ym3 ; a2 b2 + vpermt2b ym3, ym7, ym4 ; 67 78 + vpdpwssd ym16, ym15, ym3 ; a3 b3 + psrad ym16, 10 + vextracti128 xm17, ym16, 1 + packusdw xm16, xm17 + pminsw xm16, xm11 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + test dword r8m, 0x800 + jnz .hv_w8_12bit + vpbroadcastd m10, [pd_2176] + psllw xmm0, 6 + jmp .hv_w8_main +.hv_w8_12bit: + vpbroadcastd m10, [pd_640] + psllw xmm0, 4 + psllw xmm1, 2 +.hv_w8_main: + mova [buf+ 0], xmm0 + mova [buf+16], xmm1 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [buf+ 4] + vpbroadcastd m14, [buf+ 8] + vpbroadcastd m15, [buf+12] + vpbroadcastd m16, xmm1 + vpbroadcastd m17, [buf+20] + vpbroadcastd m18, [buf+24] + vpbroadcastd m19, [buf+28] + cmp wd, 16 + je .hv_w16 + jg .hv_w32 + mova m5, [spel_h_shufA] + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 ; 0 1 + movu ym9, [srcq+ssq*2] + add srcq, r6 + vinserti32x8 m9, [srcq+ssq*0], 1 ; 2 3 + movu ym20, [srcq+ssq*1] + vinserti32x8 m20, [srcq+ssq*2], 1 ; 4 5 + add srcq, r6 + movu ym21, [srcq+ssq*0] ; 6 + movu m6, [spel_h_shufB] + movu m7, [spel_h_shufC] + vpermb m8, m5, m0 + mova m1, m10 + vpdpwssd m1, m12, m8 ; a0 b0 + vpermb m8, m5, m9 + mova m2, m10 + vpdpwssd m2, m12, m8 ; c0 d0 + vpermb m8, m5, m20 + mova m3, m10 + vpdpwssd m3, m12, m8 ; e0 f0 + vpermb m8, m5, m21 + mova m4, m10 + vpdpwssd m4, m12, m8 ; g0 + vpermb m8, m6, m0 + vpdpwssd m1, m13, m8 ; a1 b1 + vpermb m8, m6, m9 + vpdpwssd m2, m13, m8 ; c1 d1 + vpermb m8, m6, m20 + vpdpwssd m3, m13, m8 ; e1 f1 + vpermb m8, m6, m21 + vpdpwssd m4, m13, m8 ; g1 + vpermb m8, m7, m0 + vpdpwssd m1, m14, m8 ; a2 b2 + vpermb m8, m7, m9 + vpdpwssd m2, m14, m8 ; c2 d2 + vpermb m8, m7, m20 + vpdpwssd m3, m14, m8 ; e2 f2 + vpermb m8, m7, m21 + vpdpwssd m4, m14, m8 ; g2 + mova m8, [spel_h_shufD] + vpermb m0, m8, m0 + vpdpwssd m1, m15, m0 ; a3 b3 + mova m0, [spel_shuf8a] + vpermb m9, m8, m9 + vpdpwssd m2, m15, m9 ; c3 d3 + mova m9, [spel_shuf8b] + vpermb m20, m8, m20 + vpdpwssd m3, m15, m20 ; e3 f3 + vpermb m21, m8, m21 + vpdpwssd m4, m15, m21 ; g3 + vpermt2b m1, m0, m2 ; 01 12 + vpermt2b m2, m0, m3 ; 23 34 + vpermt2b m3, m0, m4 ; 45 56 +.hv_w8_loop: + movu ym0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m0, [srcq+ssq*0], 1 + mova m4, m10 + vpermb m21, m5, m0 + vpdpwssd m4, m12, m21 ; h0 i0 + vpermb m21, m6, m0 + pmaddwd m20, m16, m1 ; A0 B0 + vpdpwssd m4, m13, m21 ; h1 i1 + vpermb m21, m7, m0 + mova m1, m2 + vpdpwssd m20, m17, m2 ; A1 B1 + vpdpwssd m4, m14, m21 ; h2 i2 + vpermb m21, m8, m0 + mova m2, m3 + vpdpwssd m20, m18, m3 ; A2 B2 + vpdpwssd m4, m15, m21 ; h3 i3 + vpermt2b m3, m9, m4 ; 67 78 + vpdpwssd m20, m19, m3 ; A3 B3 + psrad m20, 10 + vextracti32x8 ym21, m20, 1 + packusdw ym20, ym21 + pminsw ym20, ym11 + mova [dstq+dsq*0], xm20 + vextracti128 [dstq+dsq*1], ym20, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + vzeroupper + RET +.hv_w16: + WIN64_SPILL_XMM 26 + vbroadcasti32x8 m5, [srcq+ssq*0+ 8] + vinserti32x8 m4, m5, [srcq+ssq*0+ 0], 0 + vinserti32x8 m5, [srcq+ssq*0+16], 1 ; 0 + movu ym6, [srcq+ssq*1+ 0] + movu ym7, [srcq+ssq*1+16] + vinserti32x8 m6, [srcq+ssq*2+ 0], 1 + vinserti32x8 m7, [srcq+ssq*2+16], 1 ; 1 2 + add srcq, r6 + movu ym22, [srcq+ssq*0+ 0] + movu ym23, [srcq+ssq*0+16] + vinserti32x8 m22, [srcq+ssq*1+ 0], 1 + vinserti32x8 m23, [srcq+ssq*1+16], 1 ; 3 4 + movu ym24, [srcq+ssq*2+ 0] + movu ym25, [srcq+ssq*2+16] + add srcq, r6 + vinserti32x8 m24, [srcq+ssq*0+ 0], 1 + vinserti32x8 m25, [srcq+ssq*0+16], 1 ; 5 6 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m9, [spel_shuf16] + pshufb m0, m4, m20 + mova m1, m10 + vpdpwssd m1, m12, m0 ; a0 + pshufb m0, m6, m20 + mova m2, m10 + vpdpwssd m2, m12, m0 ; b0 + pshufb m0, m7, m20 + mova m3, m10 + vpdpwssd m3, m14, m0 ; c2 + pshufb m0, m4, m21 + vpdpwssd m1, m13, m0 ; a1 + pshufb m0, m6, m21 + vpdpwssd m2, m13, m0 ; b1 + pshufb m0, m7, m21 + vpdpwssd m3, m15, m0 ; c3 + pshufb m0, m5, m20 + vpdpwssd m1, m14, m0 ; a2 + shufpd m6, m7, 0x55 + pshufb m7, m6, m20 + vpdpwssd m2, m14, m7 ; b2 + vpdpwssd m3, m12, m7 ; c0 + pshufb m5, m21 + vpdpwssd m1, m15, m5 ; a3 + pshufb m6, m21 + vpdpwssd m2, m15, m6 ; b3 + vpdpwssd m3, m13, m6 ; c1 + pshufb m0, m22, m20 + mova m4, m10 + vpdpwssd m4, m12, m0 ; d0 + pshufb m0, m23, m20 + mova m5, m10 + vpdpwssd m5, m14, m0 ; e2 + pshufb m0, m24, m20 + mova m6, m10 + vpdpwssd m6, m12, m0 ; f0 + pshufb m0, m25, m20 + mova m7, m10 + vpdpwssd m7, m14, m0 ; g2 + pshufb m0, m22, m21 + vpdpwssd m4, m13, m0 ; d1 + pshufb m0, m23, m21 + vpdpwssd m5, m15, m0 ; e3 + pshufb m0, m24, m21 + vpdpwssd m6, m13, m0 ; f1 + pshufb m0, m25, m21 + vpdpwssd m7, m15, m0 ; g3 + shufpd m22, m23, 0x55 + pshufb m23, m22, m20 + vpdpwssd m4, m14, m23 ; d2 + vpdpwssd m5, m12, m23 ; e0 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m6, m14, m25 ; f2 + vpdpwssd m7, m12, m25 ; g0 + pshufb m22, m21 + vpdpwssd m4, m15, m22 ; d3 + vpdpwssd m5, m13, m22 ; e1 + pshufb m24, m21 + vpdpwssd m6, m15, m24 ; f3 + vpdpwssd m7, m13, m24 ; g1 + pslldq m1, 1 + vpermt2b m2, m9, m3 ; 12 + vpermt2b m4, m9, m5 ; 34 + vpermt2b m6, m9, m7 ; 56 + vpshrdd m1, m2, 16 ; 01 + vpshrdd m3, m2, m4, 16 ; 23 + vpshrdd m5, m4, m6, 16 ; 45 +.hv_w16_loop: + movu ym24, [srcq+ssq*1+ 0] + movu ym25, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*2] + vinserti32x8 m24, [srcq+ssq*0+ 0], 1 + vinserti32x8 m25, [srcq+ssq*0+16], 1 + mova m7, m10 + mova m8, m10 + pshufb m0, m24, m20 + vpdpwssd m7, m12, m0 ; h0 + pshufb m0, m25, m20 + vpdpwssd m8, m14, m0 ; i2 + pmaddwd m22, m16, m1 ; A0 + mova m1, m3 + pmaddwd m23, m16, m2 ; B0 + mova m2, m4 + pshufb m0, m24, m21 + vpdpwssd m7, m13, m0 ; h1 + pshufb m0, m25, m21 + vpdpwssd m8, m15, m0 ; i3 + vpdpwssd m22, m17, m3 ; A1 + mova m3, m5 + vpdpwssd m23, m17, m4 ; B1 + mova m4, m6 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m7, m14, m25 ; h2 + vpdpwssd m8, m12, m25 ; i0 + vpdpwssd m22, m18, m5 ; A2 + vpdpwssd m23, m18, m6 ; B2 + pshufb m24, m21 + vpdpwssd m7, m15, m24 ; h3 + vpdpwssd m8, m13, m24 ; i1 + vpermt2b m7, m9, m8 ; 78 + vpshrdd m5, m6, m7, 16 ; 67 + vpdpwssd m22, m19, m5 ; A3 + vpdpwssd m23, m19, m7 ; B3 + mova m6, m7 + psrad m22, 10 + psrad m23, 10 + vshufi32x4 m0, m22, m23, q3232 + vinserti32x8 m22, ym23, 1 + packusdw m22, m0 + pminsw m22, m11 + mova [dstq+dsq*0], ym22 + vextracti32x8 [dstq+dsq*1], m22, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 32 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m22, [spel_shuf32] + lea wd, [hq+wq*8-256] + mov r7, srcq + mov r8, dstq +.hv_w32_loop0: + movu m6, [srcq+ssq*0+ 0] + movu m7, [srcq+ssq*0+ 8] + movu m8, [srcq+ssq*0+16] + mova m0, m10 + mova m23, m10 + pshufb m9, m6, m20 + vpdpwssd m0, m12, m9 ; a0l + pshufb m9, m7, m20 + vpdpwssd m23, m12, m9 ; a0h + vpdpwssd m0, m14, m9 ; a2l + pshufb m7, m21 + vpdpwssd m23, m13, m7 ; a1h + vpdpwssd m0, m15, m7 ; a3l + pshufb m7, m8, m20 + vpdpwssd m23, m14, m7 ; a2h + pshufb m6, m21 + vpdpwssd m0, m13, m6 ; a1l + pshufb m8, m21 + vpdpwssd m23, m15, m8 ; a3h +%macro PUT_8TAP_HV_W32 5 ; dst_lo, dst_hi, stride_name, stride[1-2] + movu m6, [srcq+%3*%4+ 0] + movu m7, [srcq+%3*%4+ 8] + movu m8, [srcq+%3*%4+16] +%if %4 == 2 + add srcq, r6 +%endif + movu m29, [srcq+%3*%5+ 0] + movu m30, [srcq+%3*%5+ 8] + movu m31, [srcq+%3*%5+16] +%if %5 == 2 + add srcq, r6 +%endif + mova m%1, m10 + mova m9, m10 + pshufb m%2, m6, m20 + vpdpwssd m%1, m12, m%2 ; x0l + pshufb m%2, m29, m20 + vpdpwssd m9, m12, m%2 ; y0l + pshufb m6, m21 + vpdpwssd m%1, m13, m6 ; x1l + pshufb m29, m21 + vpdpwssd m9, m13, m29 ; y1l + pshufb m6, m7, m20 + mova m%2, m10 + vpdpwssd m%2, m12, m6 ; x0h + pshufb m29, m30, m20 + vpdpwssd m%1, m14, m6 ; y2l + mova m6, m10 + vpdpwssd m6, m12, m29 ; x0h + pshufb m7, m21 + vpdpwssd m9, m14, m29 ; y2l + pshufb m30, m21 + vpdpwssd m%2, m13, m7 ; x1h + vpdpwssd m%1, m15, m7 ; x3l + pshufb m7, m8, m20 + vpdpwssd m6, m13, m30 ; y1h + vpdpwssd m9, m15, m30 ; y3l + pshufb m30, m31, m20 + vpdpwssd m%2, m14, m7 ; x2h + pshufb m8, m21 + vpdpwssd m6, m14, m30 ; y2h + pshufb m31, m21 + vpdpwssd m%2, m15, m8 ; x3h + vpdpwssd m6, m15, m31 ; y3h +%if %1 == 1 + vpermt2b m0, m22, m%1 ; 01l + vpermt2b m23, m22, m%2 ; 01h +%endif + vpermt2b m%1, m22, m9 ; xyl + vpermt2b m%2, m22, m6 ; xyh +%endmacro + PUT_8TAP_HV_W32 1, 24, ssq, 1, 2 ; 12 + PUT_8TAP_HV_W32 3, 26, ssq, 0, 1 ; 34 + PUT_8TAP_HV_W32 5, 28, ssq, 2, 0 ; 56 + vpshrdd m2, m1, m3, 16 ; 23l + vpshrdd m25, m24, m26, 16 ; 23h + vpshrdd m4, m3, m5, 16 ; 45l + vpshrdd m27, m26, m28, 16 ; 45h +.hv_w32_loop: + movu m7, [srcq+ssq*1+ 0] + movu m9, [srcq+ssq*2+ 0] + movu m6, [srcq+ssq*1+ 8] + movu m8, [srcq+ssq*2+ 8] + mova m29, m10 + mova m31, m10 + pshufb m30, m7, m20 + vpdpwssd m29, m12, m30 ; h0l + pshufb m30, m9, m20 + vpdpwssd m31, m12, m30 ; i0l + pshufb m7, m21 + vpdpwssd m29, m13, m7 ; h1l + pshufb m9, m21 + vpdpwssd m31, m13, m9 ; i1l + pshufb m7, m6, m20 + vpdpwssd m29, m14, m7 ; h2l + pshufb m9, m8, m20 + vpdpwssd m31, m14, m9 ; i2l + pshufb m6, m21 + vpdpwssd m29, m15, m6 ; h3l + pshufb m8, m21 + vpdpwssd m31, m15, m8 ; i3l + mova m30, m10 + vpdpwssd m30, m12, m7 ; h0h + movu m7, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*2] + vpermt2b m29, m22, m31 ; 78l + mova m31, m10 + vpdpwssd m31, m12, m9 ; i0h + movu m9, [srcq+ssq*0+16] + vpdpwssd m30, m13, m6 ; h1h + pshufb m6, m7, m20 + vpdpwssd m31, m13, m8 ; i1h + pshufb m8, m9, m20 + vpdpwssd m30, m14, m6 ; h2h + pmaddwd m6, m16, m0 ; A0l + pshufb m7, m21 + vpdpwssd m31, m14, m8 ; i2h + pmaddwd m8, m16, m23 ; A0h + pshufb m9, m21 + vpdpwssd m30, m15, m7 ; h3h + pmaddwd m7, m16, m1 ; B0l + vpdpwssd m31, m15, m9 ; i3h + pmaddwd m9, m16, m24 ; B0h + mova m0, m2 + vpdpwssd m6, m17, m2 ; A1l + mova m23, m25 + vpdpwssd m8, m17, m25 ; A1h + mova m1, m3 + vpdpwssd m7, m17, m3 ; B1l + mova m24, m26 + vpdpwssd m9, m17, m26 ; B1h + vpermt2b m30, m22, m31 ; 78h + vpdpwssd m6, m18, m4 ; A2l + mova m2, m4 + vpdpwssd m8, m18, m27 ; A2h + mova m25, m27 + vpdpwssd m7, m18, m5 ; B2l + mova m3, m5 + vpdpwssd m9, m18, m28 ; B2h + mova m26, m28 + vpshrdd m4, m5, m29, 16 ; 67l + vpdpwssd m6, m19, m4 ; A3l + vpshrdd m27, m28, m30, 16 ; 67h + vpdpwssd m8, m19, m27 ; A3h + mova m5, m29 + vpdpwssd m7, m19, m29 ; B3l + mova m28, m30 + vpdpwssd m9, m19, m30 ; B3h + REPX {psrad x, 10}, m6, m8, m7, m9 + packusdw m6, m8 + packusdw m7, m9 + pminsw m6, m11 + pminsw m7, m11 + mova [dstq+dsq*0], m6 + mova [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + add r7, 64 + add r8, 64 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .hv_w32_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +MC_8TAP_FN prep, sharp, SHARP, SHARP +MC_8TAP_FN prep, sharp_smooth, SHARP, SMOOTH +MC_8TAP_FN prep, smooth_sharp, SMOOTH, SHARP +MC_8TAP_FN prep, smooth, SMOOTH, SMOOTH +MC_8TAP_FN prep, sharp_regular, SHARP, REGULAR +MC_8TAP_FN prep, regular_sharp, REGULAR, SHARP +MC_8TAP_FN prep, smooth_regular, SMOOTH, REGULAR +MC_8TAP_FN prep, regular_smooth, REGULAR, SMOOTH +MC_8TAP_FN prep, regular, REGULAR, REGULAR + +cglobal prep_8tap_16bpc, 3, 8, 16, tmp, src, stride, w, h, mx, my, stride3 +%define base r7-prep_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx512icl] + mov wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [pw_8192] + movzx wd, word [r7+wq*2+table_offset(prep,)] + shr r5d, 11 + vpbroadcastd m4, [r7-prep_avx512icl+prep_mul+r5*4] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mov r5d, r7m + vbroadcasti32x4 m4, [spel_h_shufA] + vbroadcasti32x4 m5, [spel_h_shufB] + shr r5d, 11 + mova ym9, [prep_endA] + psllw xmm0, [base+prep_hv_shift+r5*8] + mova [tmpq], xmm0 + vpbroadcastd m6, [tmpq+4] + vpbroadcastd m7, [tmpq+8] +.h_w4_loop: + movu xm2, [srcq+strideq*0] + vinserti32x4 ym2, [srcq+strideq*1], 1 + vinserti32x4 m2, [srcq+strideq*2], 2 + vinserti32x4 m2, [srcq+r6 ], 3 + lea srcq, [srcq+strideq*4] + mova m0, m10 + pshufb m1, m2, m4 + vpdpwssd m0, m6, m1 + pshufb m2, m5 + vpdpwssd m0, m7, m2 + vpermb m0, m9, m0 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m10, [prep_8tap_rnd] + lea r6, [strideq*3] + cmp wd, 4 + je .h_w4 + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mov r5d, r7m + sub srcq, 6 + shr r5d, 11 + psllw xmm0, [base+prep_hv_shift+r5*8] + mova [tmpq], xmm0 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + cmp wd, 16 + je .h_w16 + jg .h_w32 +.h_w8: + mova m6, [spel_h_shufA] + movu m7, [spel_h_shufB] + movu m8, [spel_h_shufC] + mova m9, [spel_h_shufD] + mova m11, [prep_endB] +.h_w8_loop: + movu ym4, [srcq+strideq*0] + vinserti32x8 m4, [srcq+strideq*1], 1 + movu ym5, [srcq+strideq*2] + vinserti32x8 m5, [srcq+r6 ], 1 + lea srcq, [srcq+strideq*4] + mova m0, m10 + mova m1, m10 + vpermb m2, m6, m4 + vpermb m3, m6, m5 + vpdpwssd m0, m12, m2 + vpdpwssd m1, m12, m3 + vpermb m2, m7, m4 + vpermb m3, m7, m5 + vpdpwssd m0, m13, m2 + vpdpwssd m1, m13, m3 + vpermb m2, m8, m4 + vpermb m3, m8, m5 + vpdpwssd m0, m14, m2 + vpdpwssd m1, m14, m3 + vpermb m2, m9, m4 + vpermb m3, m9, m5 + vpdpwssd m0, m15, m2 + vpdpwssd m1, m15, m3 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + vbroadcasti32x4 m6, [spel_h_shufA] + vbroadcasti32x4 m7, [spel_h_shufB] + mova m11, [prep_endC] +.h_w16_loop: + movu ym2, [srcq+strideq*0+ 0] + vinserti32x8 m2, [srcq+strideq*1+ 0], 1 + movu ym3, [srcq+strideq*0+16] + vinserti32x8 m3, [srcq+strideq*1+16], 1 + lea srcq, [srcq+strideq*2] + mova m0, m10 + mova m1, m10 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m14, m4 ; b2 + pshufb m4, m2, m7 + vpdpwssd m0, m13, m4 ; a1 + pshufb m4, m3, m7 + vpdpwssd m1, m15, m4 ; b3 + shufpd m2, m3, 0x55 + pshufb m4, m2, m6 + vpdpwssd m0, m14, m4 ; a2 + vpdpwssd m1, m12, m4 ; b0 + pshufb m2, m7 + vpdpwssd m0, m15, m2 ; a3 + vpdpwssd m1, m13, m2 ; b1 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + vbroadcasti32x4 m6, [spel_h_shufA] + lea srcq, [srcq+wq*2] + vbroadcasti32x4 m7, [spel_h_shufB] + neg wq + mova m11, [prep_endC] +.h_w32_loop0: + mov r6, wq +.h_w32_loop: + movu m2, [srcq+r6*2+ 0] + movu m3, [srcq+r6*2+ 8] + mova m0, m10 + mova m1, m10 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m12, m4 ; b0 + vpdpwssd m0, m14, m4 ; a2 + movu m4, [srcq+r6*2+16] + pshufb m3, m7 + vpdpwssd m1, m13, m3 ; b1 + vpdpwssd m0, m15, m3 ; a3 + pshufb m3, m4, m6 + vpdpwssd m1, m14, m3 ; b2 + pshufb m2, m7 + vpdpwssd m0, m13, m2 ; a1 + pshufb m4, m7 + vpdpwssd m1, m15, m4 ; b3 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + add r6, 32 + jl .h_w32_loop + add srcq, strideq + dec hd + jg .h_w32_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + mov r5d, r7m + vpbroadcastd m10, [prep_8tap_rnd] + pmovsxbw xmm0, [base+subpel_filters+myq*8] + tzcnt r6d, wd + shr r5d, 11 + movzx r6d, word [r7+r6*2+table_offset(prep, _8tap_v)] + psllw xmm0, [base+prep_hv_shift+r5*8] + add r7, r6 + lea r6, [strideq*3] + sub srcq, r6 + mova [tmpq], xmm0 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + jmp r7 +.v_w4: + movq xmm1, [srcq+strideq*0] + vpbroadcastq ymm0, [srcq+strideq*1] + vpbroadcastq ymm2, [srcq+strideq*2] + add srcq, r6 + vpbroadcastq ymm4, [srcq+strideq*0] + vpbroadcastq ymm3, [srcq+strideq*1] + vpbroadcastq ymm5, [srcq+strideq*2] + mova xm11, [prep_endA] + add srcq, r6 + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklwd ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+strideq*0] + vpblendd ymm2, ymm4, 0x30 + vpblendd ymm4, ymm3, 0x30 + punpcklwd ymm2, ymm4 ; 23 34 + vpblendd ymm3, ymm5, 0x30 + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 45 56 +.v_w4_loop: + vpbroadcastq ymm5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + mova ymm4, ym10 + vpdpwssd ymm4, ym12, ymm1 ; a0 b0 + mova ymm1, ymm2 + vpdpwssd ymm4, ym13, ymm2 ; a1 b1 + mova ymm2, ymm3 + vpdpwssd ymm4, ym14, ymm3 ; a2 b2 + vpblendd ymm3, ymm0, ymm5, 0x30 + vpbroadcastq ymm0, [srcq+strideq*0] + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 67 78 + vpdpwssd ymm4, ym15, ymm3 ; a3 b3 + vpermb ymm4, ym11, ymm4 + mova [tmpq], xmm4 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + vbroadcasti32x4 m2, [srcq+strideq*2] + vinserti32x4 m1, m2, [srcq+strideq*0], 0 + vinserti32x4 m1, [srcq+strideq*1], 1 ; 0 1 2 + add srcq, r6 + vinserti32x4 ym2, [srcq+strideq*0], 1 + vinserti32x4 m2, [srcq+strideq*1], 2 ; 2 3 4 + mova m6, [spel_v_shuf8] + movu xm0, [srcq+strideq*1] + vinserti32x4 ym0, [srcq+strideq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+strideq*0], 2 ; 4 5 6 + mova ym11, [prep_endB] + vpermb m1, m6, m1 ; 01 12 + vpermb m2, m6, m2 ; 23 34 + vpermb m3, m6, m0 ; 45 56 +.v_w8_loop: + vinserti32x4 m0, [srcq+strideq*1], 3 + lea srcq, [srcq+strideq*2] + movu xm5, [srcq+strideq*0] + mova m4, m10 + vpdpwssd m4, m12, m1 ; a0 b0 + mova m1, m2 + vshufi32x4 m0, m5, q1032 ; 6 7 8 + vpdpwssd m4, m13, m2 ; a1 b1 + mova m2, m3 + vpdpwssd m4, m14, m3 ; a2 b2 + vpermb m3, m6, m0 ; 67 78 + vpdpwssd m4, m15, m3 ; a3 b3 + vpermb m4, m11, m4 + mova [tmpq], ym4 + add tmpq, 32 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti32x8 m1, [srcq+strideq*1] + vinserti32x8 m0, m1, [srcq+strideq*0], 0 + vinserti32x8 m1, [srcq+strideq*2], 1 + mova m8, [spel_v_shuf16] + add srcq, r6 + movu ym3, [srcq+strideq*0] + vinserti32x8 m3, [srcq+strideq*1], 1 + movu ym5, [srcq+strideq*2] + add srcq, r6 + vinserti32x8 m5, [srcq+strideq*0], 1 + mova m11, [prep_endA] + vpermb m0, m8, m0 ; 01 + vpermb m1, m8, m1 ; 12 + vpermb m3, m8, m3 ; 34 + vpermb m5, m8, m5 ; 56 + vpshrdd m2, m1, m3, 16 ; 23 + vpshrdd m4, m3, m5, 16 ; 45 +.v_w16_loop: + mova m6, m10 + mova m7, m10 + vpdpwssd m6, m12, m0 ; a0 + mova m0, m2 + vpdpwssd m7, m12, m1 ; b0 + mova m1, m3 + vpdpwssd m6, m13, m2 ; a1 + mova m2, m4 + vpdpwssd m7, m13, m3 ; b1 + mova m3, m5 + vpdpwssd m6, m14, m4 ; a2 + mova m4, m5 + vpdpwssd m7, m14, m5 ; b2 + movu ym5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m5, [srcq+strideq*0], 1 + vpermb m5, m8, m5 ; 78 + vpshrdd m4, m5, 16 ; 67 + vpdpwssd m6, m15, m4 ; a3 + vpdpwssd m7, m15, m5 ; b3 + vpermt2b m6, m11, m7 + mova [tmpq], m6 + add tmpq, 64 + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + PUSH r8 + movaps [rsp+stack_offset+8], xmm6 +%endif + lea r5, [hq+wq*8-256] + mov r7, srcq + mov r8, tmpq +.v_w32_loop0: + movu m16, [srcq+strideq*0] + movu m17, [srcq+strideq*1] + movu m18, [srcq+strideq*2] + add srcq, r6 + movu m19, [srcq+strideq*0] + movu m20, [srcq+strideq*1] + movu m21, [srcq+strideq*2] + add srcq, r6 + movu m22, [srcq+strideq*0] + mova m11, [prep_endC] + punpcklwd m0, m16, m17 ; 01l + punpckhwd m16, m17 ; 01h + punpcklwd m1, m17, m18 ; 12l + punpckhwd m17, m18 ; 12h + punpcklwd m2, m18, m19 ; 23l + punpckhwd m18, m19 ; 23h + punpcklwd m3, m19, m20 ; 34l + punpckhwd m19, m20 ; 34h + punpcklwd m4, m20, m21 ; 45l + punpckhwd m20, m21 ; 45h + punpcklwd m5, m21, m22 ; 56l + punpckhwd m21, m22 ; 56h +.v_w32_loop: + mova m6, m10 + vpdpwssd m6, m12, m0 ; a0l + mova m8, m10 + vpdpwssd m8, m12, m16 ; a0h + mova m7, m10 + vpdpwssd m7, m12, m1 ; b0l + mova m9, m10 + vpdpwssd m9, m12, m17 ; b0h + mova m0, m2 + vpdpwssd m6, m13, m2 ; a1l + mova m16, m18 + vpdpwssd m8, m13, m18 ; a1h + mova m1, m3 + vpdpwssd m7, m13, m3 ; b1l + mova m17, m19 + vpdpwssd m9, m13, m19 ; b1h + mova m2, m4 + vpdpwssd m6, m14, m4 ; a2l + mova m18, m20 + vpdpwssd m8, m14, m20 ; a2h + mova m3, m5 + vpdpwssd m7, m14, m5 ; b2l + mova m19, m21 + vpdpwssd m9, m14, m21 ; b2h + movu m21, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklwd m4, m22, m21 ; 67l + punpckhwd m20, m22, m21 ; 67h + movu m22, [srcq+strideq*0] + vpdpwssd m6, m15, m4 ; a3l + vpdpwssd m8, m15, m20 ; a3h + punpcklwd m5, m21, m22 ; 78l + punpckhwd m21, m22 ; 78h + vpdpwssd m7, m15, m5 ; b3l + vpdpwssd m9, m15, m21 ; b3h + vpermt2b m6, m11, m8 + vpermt2b m7, m11, m9 + mova [tmpq+wq*0], m6 + mova [tmpq+wq*2], m7 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w32_loop + add r7, 64 + add r8, 64 + movzx hd, r5b + mov srcq, r7 + mov tmpq, r8 + sub r5d, 1<<8 + jg .v_w32_loop0 +%if WIN64 + movaps xmm6, [rsp+stack_offset+8] + POP r8 +%endif + vzeroupper + RET +.hv: + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + mov r5d, r7m + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 2 + shr r5d, 11 + sub srcq, r6 + psllw xmm0, [base+prep_hv_shift+r5*8] + psllw xmm1, 2 + vpbroadcastd m10, [prep_8tap_rnd] + vpbroadcastd ym11, [pd_128] + mova xm21, [prep_endA] + mova [tmpq+ 0], xmm0 + mova [tmpq+16], xmm1 + vpbroadcastd m8, [tmpq+ 4] + vpbroadcastd m9, [tmpq+ 8] + vpbroadcastd ym12, xmm1 + vpbroadcastd ym13, [tmpq+20] + vpbroadcastd ym14, [tmpq+24] + vpbroadcastd ym15, [tmpq+28] + movu xm4, [srcq+strideq*0] + vinserti32x4 ym4, [srcq+strideq*1], 1 + vinserti32x4 m4, [srcq+strideq*2], 2 + add srcq, r6 + vinserti32x4 m4, [srcq+strideq*0], 3 ; 0 1 2 3 + movu xm0, [srcq+strideq*1] + vinserti32x4 ym0, [srcq+strideq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+strideq*0], 2 ; 4 5 6 + vbroadcasti32x4 m19, [spel_h_shufA] + vbroadcasti32x4 m20, [spel_h_shufB] + mova ym6, [spel_shuf4a] + mova ym7, [spel_shuf4b] + mova m2, m10 + mova m3, m10 + pshufb m1, m4, m19 + vpdpwssd m2, m8, m1 + pshufb m1, m0, m19 + vpdpwssd m3, m8, m1 + pshufb m4, m20 + vpdpwssd m2, m9, m4 + pshufb m0, m20 + vpdpwssd m3, m9, m0 + vpermb m1, m6, m2 ; 01 12 + vshufi32x4 m2, m3, q1032 + vpermb m3, m6, m3 ; 45 56 + vpermb m2, m6, m2 ; 23 34 +.hv_w4_loop: + movu xm18, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti128 ym18, [srcq+strideq*0], 1 + mova ym16, ym11 + mova ym4, ym10 + pshufb ym17, ym18, ym19 + vpdpwssd ym16, ym12, ym1 ; a0 b0 + vpdpwssd ym4, ym8, ym17 + pshufb ym18, ym20 + mova ym1, ym2 + vpdpwssd ym16, ym13, ym2 ; a1 b1 + vpdpwssd ym4, ym9, ym18 ; 7 8 + mova ym2, ym3 + vpdpwssd ym16, ym14, ym3 ; a2 b2 + vpermt2b ym3, ym7, ym4 ; 67 78 + vpdpwssd ym16, ym15, ym3 ; a3 b3 + vpermb ym16, ym21, ym16 + mova [tmpq], xm16 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + mov r5d, r7m + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 6 + shr r5d, 11 + sub srcq, r6 + vpbroadcastd m10, [prep_8tap_rnd] + vpbroadcastd m11, [pd_128] + psllw xmm0, [base+prep_hv_shift+r5*8] + psllw xmm1, 2 + mova [tmpq+ 0], xmm0 + mova [tmpq+16], xmm1 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + vpbroadcastd m16, xmm1 + vpbroadcastd m17, [tmpq+20] + vpbroadcastd m18, [tmpq+24] + vpbroadcastd m19, [tmpq+28] + cmp wd, 16 + je .hv_w16 + jg .hv_w32 + WIN64_SPILL_XMM 23 + mova m5, [spel_h_shufA] + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 ; 0 1 + movu ym9, [srcq+strideq*2] + add srcq, r6 + vinserti32x8 m9, [srcq+strideq*0], 1 ; 2 3 + movu ym20, [srcq+strideq*1] + vinserti32x8 m20, [srcq+strideq*2], 1 ; 4 5 + add srcq, r6 + movu ym21, [srcq+strideq*0] ; 6 + movu m6, [spel_h_shufB] + movu m7, [spel_h_shufC] + mova ym22, [prep_endB] + vpermb m8, m5, m0 + mova m1, m10 + vpdpwssd m1, m12, m8 ; a0 b0 + vpermb m8, m5, m9 + mova m2, m10 + vpdpwssd m2, m12, m8 ; c0 d0 + vpermb m8, m5, m20 + mova m3, m10 + vpdpwssd m3, m12, m8 ; e0 f0 + vpermb m8, m5, m21 + mova m4, m10 + vpdpwssd m4, m12, m8 ; g0 + vpermb m8, m6, m0 + vpdpwssd m1, m13, m8 ; a1 b1 + vpermb m8, m6, m9 + vpdpwssd m2, m13, m8 ; c1 d1 + vpermb m8, m6, m20 + vpdpwssd m3, m13, m8 ; e1 f1 + vpermb m8, m6, m21 + vpdpwssd m4, m13, m8 ; g1 + vpermb m8, m7, m0 + vpdpwssd m1, m14, m8 ; a2 b2 + vpermb m8, m7, m9 + vpdpwssd m2, m14, m8 ; c2 d2 + vpermb m8, m7, m20 + vpdpwssd m3, m14, m8 ; e2 f2 + vpermb m8, m7, m21 + vpdpwssd m4, m14, m8 ; g2 + mova m8, [spel_h_shufD] + vpermb m0, m8, m0 + vpdpwssd m1, m15, m0 ; a3 b3 + mova m0, [spel_shuf8a] + vpermb m9, m8, m9 + vpdpwssd m2, m15, m9 ; c3 d3 + mova m9, [spel_shuf8b] + vpermb m20, m8, m20 + vpdpwssd m3, m15, m20 ; e3 f3 + vpermb m21, m8, m21 + vpdpwssd m4, m15, m21 ; g3 + vpermt2b m1, m0, m2 ; 01 12 + vpermt2b m2, m0, m3 ; 23 34 + vpermt2b m3, m0, m4 ; 45 56 +.hv_w8_loop: + movu ym0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m0, [srcq+strideq*0], 1 + mova m4, m10 + mova m20, m11 + vpermb m21, m5, m0 + vpdpwssd m4, m12, m21 ; h0 i0 + vpermb m21, m6, m0 + vpdpwssd m20, m16, m1 ; A0 B0 + vpdpwssd m4, m13, m21 ; h1 i1 + vpermb m21, m7, m0 + mova m1, m2 + vpdpwssd m20, m17, m2 ; A1 B1 + vpdpwssd m4, m14, m21 ; h2 i2 + vpermb m21, m8, m0 + mova m2, m3 + vpdpwssd m20, m18, m3 ; A2 B2 + vpdpwssd m4, m15, m21 ; h3 i3 + vpermt2b m3, m9, m4 ; 67 78 + vpdpwssd m20, m19, m3 ; A3 B3 + vpermb m20, m22, m20 + mova [tmpq], ym20 + add tmpq, 32 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 27 + vbroadcasti32x8 m5, [srcq+strideq*0+ 8] + vinserti32x8 m4, m5, [srcq+strideq*0+ 0], 0 + vinserti32x8 m5, [srcq+strideq*0+16], 1 ; 0 + movu ym6, [srcq+strideq*1+ 0] + movu ym7, [srcq+strideq*1+16] + vinserti32x8 m6, [srcq+strideq*2+ 0], 1 + vinserti32x8 m7, [srcq+strideq*2+16], 1 ; 1 2 + add srcq, r6 + movu ym22, [srcq+strideq*0+ 0] + movu ym23, [srcq+strideq*0+16] + vinserti32x8 m22, [srcq+strideq*1+ 0], 1 + vinserti32x8 m23, [srcq+strideq*1+16], 1 ; 3 4 + movu ym24, [srcq+strideq*2+ 0] + movu ym25, [srcq+strideq*2+16] + add srcq, r6 + vinserti32x8 m24, [srcq+strideq*0+ 0], 1 + vinserti32x8 m25, [srcq+strideq*0+16], 1 ; 5 6 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m9, [spel_shuf16] + mova m26, [prep_endB] + pshufb m0, m4, m20 + mova m1, m10 + vpdpwssd m1, m12, m0 ; a0 + pshufb m0, m6, m20 + mova m2, m10 + vpdpwssd m2, m12, m0 ; b0 + pshufb m0, m7, m20 + mova m3, m10 + vpdpwssd m3, m14, m0 ; c2 + pshufb m0, m4, m21 + vpdpwssd m1, m13, m0 ; a1 + pshufb m0, m6, m21 + vpdpwssd m2, m13, m0 ; b1 + pshufb m0, m7, m21 + vpdpwssd m3, m15, m0 ; c3 + pshufb m0, m5, m20 + vpdpwssd m1, m14, m0 ; a2 + shufpd m6, m7, 0x55 + pshufb m7, m6, m20 + vpdpwssd m2, m14, m7 ; b2 + vpdpwssd m3, m12, m7 ; c0 + pshufb m5, m21 + vpdpwssd m1, m15, m5 ; a3 + pshufb m6, m21 + vpdpwssd m2, m15, m6 ; b3 + vpdpwssd m3, m13, m6 ; c1 + pshufb m0, m22, m20 + mova m4, m10 + vpdpwssd m4, m12, m0 ; d0 + pshufb m0, m23, m20 + mova m5, m10 + vpdpwssd m5, m14, m0 ; e2 + pshufb m0, m24, m20 + mova m6, m10 + vpdpwssd m6, m12, m0 ; f0 + pshufb m0, m25, m20 + mova m7, m10 + vpdpwssd m7, m14, m0 ; g2 + pshufb m0, m22, m21 + vpdpwssd m4, m13, m0 ; d1 + pshufb m0, m23, m21 + vpdpwssd m5, m15, m0 ; e3 + pshufb m0, m24, m21 + vpdpwssd m6, m13, m0 ; f1 + pshufb m0, m25, m21 + vpdpwssd m7, m15, m0 ; g3 + shufpd m22, m23, 0x55 + pshufb m23, m22, m20 + vpdpwssd m4, m14, m23 ; d2 + vpdpwssd m5, m12, m23 ; e0 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m6, m14, m25 ; f2 + vpdpwssd m7, m12, m25 ; g0 + pshufb m22, m21 + vpdpwssd m4, m15, m22 ; d3 + vpdpwssd m5, m13, m22 ; e1 + pshufb m24, m21 + vpdpwssd m6, m15, m24 ; f3 + vpdpwssd m7, m13, m24 ; g1 + pslldq m1, 1 + vpermt2b m2, m9, m3 ; 12 + vpermt2b m4, m9, m5 ; 34 + vpermt2b m6, m9, m7 ; 56 + vpshrdd m1, m2, 16 ; 01 + vpshrdd m3, m2, m4, 16 ; 23 + vpshrdd m5, m4, m6, 16 ; 45 +.hv_w16_loop: + movu ym24, [srcq+strideq*1+ 0] + movu ym25, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*2] + vinserti32x8 m24, [srcq+strideq*0+ 0], 1 + vinserti32x8 m25, [srcq+strideq*0+16], 1 + mova m7, m10 + mova m8, m10 + pshufb m0, m24, m20 + vpdpwssd m7, m12, m0 ; h0 + mova m22, m11 + pshufb m0, m25, m20 + vpdpwssd m8, m14, m0 ; i2 + mova m23, m11 + vpdpwssd m22, m16, m1 ; A0 + mova m1, m3 + vpdpwssd m23, m16, m2 ; B0 + mova m2, m4 + pshufb m0, m24, m21 + vpdpwssd m7, m13, m0 ; h1 + pshufb m0, m25, m21 + vpdpwssd m8, m15, m0 ; i3 + vpdpwssd m22, m17, m3 ; A1 + mova m3, m5 + vpdpwssd m23, m17, m4 ; B1 + mova m4, m6 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m7, m14, m25 ; h2 + vpdpwssd m8, m12, m25 ; i0 + vpdpwssd m22, m18, m5 ; A2 + vpdpwssd m23, m18, m6 ; B2 + pshufb m24, m21 + vpdpwssd m7, m15, m24 ; h3 + vpdpwssd m8, m13, m24 ; i1 + vpermt2b m7, m9, m8 ; 78 + vpshrdd m5, m6, m7, 16 ; 67 + vpdpwssd m22, m19, m5 ; A3 + vpdpwssd m23, m19, m7 ; B3 + mova m6, m7 + vpermt2b m22, m26, m23 + mova [tmpq], m22 + add tmpq, 64 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + PUSH r8 + %assign regs_used regs_used + 1 + WIN64_SPILL_XMM 32 +%endif + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m22, [spel_shuf32] + lea r5d, [hq+wq*8-256] + mov r7, srcq + mov r8, tmpq +.hv_w32_loop0: + movu m6, [srcq+strideq*0+ 0] + movu m7, [srcq+strideq*0+ 8] + movu m8, [srcq+strideq*0+16] + mova m0, m10 + mova m23, m10 + pshufb m9, m6, m20 + vpdpwssd m0, m12, m9 ; a0l + pshufb m9, m7, m20 + vpdpwssd m23, m12, m9 ; a0h + vpdpwssd m0, m14, m9 ; a2l + pshufb m7, m21 + vpdpwssd m23, m13, m7 ; a1h + vpdpwssd m0, m15, m7 ; a3l + pshufb m7, m8, m20 + vpdpwssd m23, m14, m7 ; a2h + pshufb m6, m21 + vpdpwssd m0, m13, m6 ; a1l + pshufb m8, m21 + vpdpwssd m23, m15, m8 ; a3h + PUT_8TAP_HV_W32 1, 24, strideq, 1, 2 ; 12 + PUT_8TAP_HV_W32 3, 26, strideq, 0, 1 ; 34 + PUT_8TAP_HV_W32 5, 28, strideq, 2, 0 ; 56 + vpshrdd m2, m1, m3, 16 ; 23l + vpshrdd m25, m24, m26, 16 ; 23h + vpshrdd m4, m3, m5, 16 ; 45l + vpshrdd m27, m26, m28, 16 ; 45h +.hv_w32_loop: + movu m7, [srcq+strideq*1+ 0] + movu m9, [srcq+strideq*2+ 0] + movu m6, [srcq+strideq*1+ 8] + movu m8, [srcq+strideq*2+ 8] + mova m29, m10 + mova m31, m10 + pshufb m30, m7, m20 + vpdpwssd m29, m12, m30 ; h0l + pshufb m30, m9, m20 + vpdpwssd m31, m12, m30 ; i0l + pshufb m7, m21 + vpdpwssd m29, m13, m7 ; h1l + pshufb m9, m21 + vpdpwssd m31, m13, m9 ; i1l + pshufb m7, m6, m20 + vpdpwssd m29, m14, m7 ; h2l + pshufb m9, m8, m20 + vpdpwssd m31, m14, m9 ; i2l + pshufb m6, m21 + vpdpwssd m29, m15, m6 ; h3l + pshufb m8, m21 + vpdpwssd m31, m15, m8 ; i3l + mova m30, m10 + vpdpwssd m30, m12, m7 ; h0h + movu m7, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*2] + vpermt2b m29, m22, m31 ; 78l + mova m31, m10 + vpdpwssd m31, m12, m9 ; i0h + movu m9, [srcq+strideq*0+16] + vpdpwssd m30, m13, m6 ; h1h + pshufb m6, m7, m20 + vpdpwssd m31, m13, m8 ; i1h + pshufb m8, m9, m20 + vpdpwssd m30, m14, m6 ; h2h + mova m6, m11 + vpdpwssd m6, m16, m0 ; A0l + pshufb m7, m21 + vpdpwssd m31, m14, m8 ; i2h + mova m8, m11 + vpdpwssd m8, m16, m23 ; A0h + pshufb m9, m21 + vpdpwssd m30, m15, m7 ; h3h + mova m7, m11 + vpdpwssd m7, m16, m1 ; B0l + vpdpwssd m31, m15, m9 ; i3h + mova m9, m11 + vpdpwssd m9, m16, m24 ; B0h + mova m0, m2 + vpdpwssd m6, m17, m2 ; A1l + mova m23, m25 + vpdpwssd m8, m17, m25 ; A1h + mova m1, m3 + vpdpwssd m7, m17, m3 ; B1l + mova m24, m26 + vpdpwssd m9, m17, m26 ; B1h + vpermt2b m30, m22, m31 ; 78h + mova m31, [prep_endC] + vpdpwssd m6, m18, m4 ; A2l + mova m2, m4 + vpdpwssd m8, m18, m27 ; A2h + mova m25, m27 + vpdpwssd m7, m18, m5 ; B2l + mova m3, m5 + vpdpwssd m9, m18, m28 ; B2h + mova m26, m28 + vpshrdd m4, m5, m29, 16 ; 67l + vpdpwssd m6, m19, m4 ; A3l + vpshrdd m27, m28, m30, 16 ; 67h + vpdpwssd m8, m19, m27 ; A3h + mova m5, m29 + vpdpwssd m7, m19, m29 ; B3l + mova m28, m30 + vpdpwssd m9, m19, m30 ; B3h + vpermt2b m6, m31, m8 + vpermt2b m7, m31, m9 + mova [tmpq+wq*0], m6 + mova [tmpq+wq*2], m7 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w32_loop + add r7, 64 + add r8, 64 + movzx hd, r5b + mov srcq, r7 + mov tmpq, r8 + sub r5d, 1<<8 + jg .hv_w32_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal warp_affine_8x8t_16bpc, 4, 7, 22, tmp, ts +%define base r6-pd_0to7 + mov t0d, r7m + lea r6, [pd_0to7] + shr t0d, 11 + vpbroadcastd m8, [base+warp_8x8t_rnd_v] + vpbroadcastd m1, [base+warp_8x8_rnd_h+t0*4] + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main + psrad m14, m16, 15 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + psrad m16, 15 + packssdw m14, m16 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + psrad m15, m16, 15 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + add tsq, tsq + psrad m16, 15 + packssdw m15, m16 + jmp mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).end + +cglobal warp_affine_8x8_16bpc, 4, 7, 22, dst, ds, src, ss, abcd + mov t0d, r7m ; pixel_max + lea r6, [pd_0to7] + shr t0d, 11 + vpbroadcastd m1, [base+warp_8x8_rnd_h+t0*4] + vpbroadcastd m8, [base+warp_8x8_rnd_v+t0*4] + call .main + psrad m14, m16, 13 + call .main2 + psrad m16, 13 + packusdw m14, m16 + call .main2 + psrad m15, m16, 13 + call .main2 + vpbroadcastd m0, [base+bidir_shift+t0*4] + vpsrlvw m14, m0 + psrad m16, 13 + packusdw m15, m16 + vpsrlvw m15, m0 +.end: + mova m0, [base+warp8x8_end] + vpermb m16, m0, m14 + lea r2, [dsq*3] + mova [dstq+dsq*0], xm16 + vextracti128 [dstq+dsq*1], ym16, 1 + vextracti32x4 [dstq+dsq*2], m16, 2 + vextracti32x4 [dstq+r2 ], m16, 3 + vpermb m16, m0, m15 + lea dstq, [dstq+dsq*4] + mova [dstq+dsq*0], xm16 + vextracti128 [dstq+dsq*1], ym16, 1 + vextracti32x4 [dstq+dsq*2], m16, 2 + vextracti32x4 [dstq+r2 ], m16, 3 + RET +.main: + vpbroadcastd ym3, [base+pd_512] +%if WIN64 + mov abcdq, r5mp + vpaddd ym18, ym3, r6m {1to8} ; mx +%else + add r5d, 512 + vpbroadcastd ym18, r5d +%endif + vpaddd ym20, ym3, r7m {1to8} ; my + mova ym16, [base+pd_0to7] + vpbroadcastd ym19, [abcdq+4*0] ; alpha + vpbroadcastd ym21, [abcdq+4*1] ; gamma + lea r4, [ssq*3+6] + vpdpwssd ym18, ym19, ym16 ; tmx + vpdpwssd ym20, ym21, ym16 ; tmy + sub srcq, r4 + mova m10, [base+warp8x8_permA] + lea r4, [mc_warp_filter+64*8] + vbroadcasti32x4 m12, [base+warp8x8_permC] + kxnorb k1, k1, k1 + vbroadcasti32x4 m13, [base+warp8x8_permD] + movu ym5, [srcq+0] + vinserti32x8 m5, [srcq+8], 1 + psrad ym17, ym18, 10 + mova m11, [base+warp8x8_permB] + kmovb k2, k1 + vpgatherdq m3{k1}, [r4+ym17*8] ; filter_x0 + psrad ym19, 16 ; beta + psrad ym21, 16 ; delta + paddd ym18, ym19 + vpermb m4, m10, m5 + vpbroadcastq m9, [base+warp_shift_h+t0*8] + pshufd m3, m3, q3120 + paddd m7, m1, m1 + pshufb m2, m3, m12 + vpdpwssd m1, m4, m2 + vpermb m5, m11, m5 + vshufi32x4 m4, m5, q1021 + pshufb m3, m13 + vpdpwssd m1, m4, m3 + call .h + psllq m2, m1, 32 + paddd m1, m2 + vpmultishiftqb m1, m9, m1 + vpshrdq m1, m0, 48 ; 01 12 + call .h + vpshrdq m2, m1, m0, 48 ; 23 34 + call .h + vpshrdq m3, m2, m0, 48 ; 45 56 +.main2: + call .h + psrad ym6, ym20, 10 + kmovb k1, k2 + paddd ym17, ym20, ym21 ; my += delta + vpgatherdq m20{k2}, [r4+ym6*8] ; filter_y0 + psrad ym16, ym17, 10 + kmovb k2, k1 + vpgatherdq m6{k1}, [r4+ym16*8] ; filter_y1 + shufps m5, m20, m6, q2020 + mova m16, m8 + pshufb m4, m5, m12 + vpdpwssd m16, m1, m4 ; a0 b0 + pshufb m5, m13 + mova m1, m2 + vpdpwssd m16, m2, m5 ; a1 b1 + shufps m6, m20, m6, q3131 + paddd ym20, ym17, ym21 + pshufb m4, m6, m12 + mova m2, m3 + vpdpwssd m16, m3, m4 ; a2 b2 + vpshrdq m3, m0, 48 ; 67 78 + pshufb m6, m13 + vpdpwssd m16, m3, m6 ; a3 b3 + ret +ALIGN function_align +.h: + movu ym16, [srcq+ssq*1] + psrad ym6, ym18, 10 + lea srcq, [srcq+ssq*2] + vinserti32x8 m5, m16, [srcq+ssq*0], 1 + kmovb k1, k2 + paddd ym17, ym18, ym19 ; mx += beta + vpgatherdq m18{k2}, [r4+ym6*8] ; filter_x1 + psrad ym16, ym17, 10 + kmovb k2, k1 + vpgatherdq m6{k1}, [r4+ym16*8] ; filter_x2 + vpermb m4, m10, m5 + shufps m16, m18, m6, q2020 + shufps m6, m18, m6, q3131 + mova m0, m7 + pshufb m18, m16, m12 + vpdpwssd m0, m4, m18 ; a0 b0 + vpermb m5, m11, m5 + pshufb m18, m6, m13 + vpdpwssd m0, m5, m18 ; a3 b3 + paddd ym18, ym17, ym19 + vshufi32x4 m17, m4, m5, q1021 + pshufb m16, m13 + vpdpwssd m0, m17, m16 ; a1 b1 + vshufi32x4 m4, m5, q2132 + pshufb m6, m12 + vpdpwssd m0, m4, m6 ; a2 b2 + vpmultishiftqb m0, m9, m0 ; a a b b + ret + +%macro BIDIR_FN 0 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq ], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm0, ym1, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + vextracti32x4 xm0, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +%endmacro + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal avg_16bpc, 4, 7, 4, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx512icl_table + lea r6, [avg_avx512icl_table] + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + vpbroadcastd m2, [base+avg_round+t0*4] + vpbroadcastd m3, [base+avg_shift+t0*4] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+64*0] + paddsw m0, [tmp2q+64*0] + mova m1, [tmp1q+64*1] + paddsw m1, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + pmaxsw m0, m2 + pmaxsw m1, m2 + psubsw m0, m2 + psubsw m1, m2 + vpsrlvw m0, m3 + vpsrlvw m1, m3 + ret + +cglobal w_avg_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg_avx512icl_table + lea r6, [w_avg_avx512icl_table] + tzcnt wd, wm + mov t0d, r7m ; pixel_max + shr t0d, 11 + movsxd wq, [r6+wq*4] + vpbroadcastd m5, [base+w_avg_round+t0*4] + vpbroadcastd m7, [base+bidir_shift+t0*4] + add wq, r6 + mov r6d, r6m ; weight + lea t0d, [r6-16] + shl r6d, 16 + sub r6d, t0d ; 16-weight, weight + movifnidn hd, hm + vpbroadcastd m6, r6d + BIDIR_FN +ALIGN function_align +.main: + mova m3, [tmp1q+64*0] + mova m1, [tmp2q+64*0] + mova m0, [tmp1q+64*1] + mova m4, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + punpcklwd m2, m1, m3 + punpckhwd m1, m3 + punpcklwd m3, m4, m0 + punpckhwd m4, m0 + mova m0, m5 + vpdpwssd m0, m6, m2 + mova m2, m5 + vpdpwssd m2, m6, m1 + mova m1, m5 + vpdpwssd m1, m6, m3 + mova m3, m5 + vpdpwssd m3, m6, m4 + REPX {psrad x, 2}, m0, m2, m1, m3 + packusdw m0, m2 + packusdw m1, m3 + vpsrlvw m0, m7 + vpsrlvw m1, m7 + ret + +cglobal mask_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx512icl_table + lea r7, [mask_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_64] + vpbroadcastd m9, [base+mask_round+r6*4] + vpbroadcastd m10, [base+bidir_shift+r6*4] + mov maskq, maskmp + add wq, r7 + BIDIR_FN +ALIGN function_align +.main: + pmovzxbw m1, [maskq+32*0] + mova m4, [tmp1q+64*0] + mova m2, [tmp2q+64*0] + pmovzxbw m6, [maskq+32*1] + mova m5, [tmp1q+64*1] + mova m3, [tmp2q+64*1] + add maskq, 32*2 + add tmp1q, 64*2 + add tmp2q, 64*2 + punpcklwd m7, m4, m2 + punpckhwd m4, m2 + psubw m0, m8, m1 + punpcklwd m2, m1, m0 ; m, 64-m + punpckhwd m1, m0 + mova m0, m9 + vpdpwssd m0, m7, m2 + mova m2, m9 + vpdpwssd m2, m4, m1 ; tmp1 * m + tmp2 * (64-m) + punpcklwd m7, m5, m3 + punpckhwd m5, m3 + psubw m1, m8, m6 + punpcklwd m3, m6, m1 + punpckhwd m6, m1 + mova m1, m9 + vpdpwssd m1, m7, m3 + mova m3, m9 + vpdpwssd m3, m5, m6 + REPX {psrad x, 4}, m0, m2, m1, m3 + packusdw m0, m2 + packusdw m1, m3 + vpsrlvw m0, m10 + vpsrlvw m1, m10 + ret + +cglobal w_mask_420_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx512icl_table + lea r7, [w_mask_420_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+mask_round+r6*4] + vpbroadcastd m13, [base+bidir_shift+r6*4] + mov r6d, r7m ; sign + vpbroadcastd m14, [base+w_mask_round+r6*4] + mova ym15, [w_mask_end42x] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + mova m4, [w_mask_shuf4] + vpermt2b m2, m4, m3 + mova m3, m14 + vpdpbusd m3, m2, [pb_64] {1to16} + vpermb m3, m15, m3 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + mova [maskq], xm3 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8: + mova m8, [w_mask_shuf8] + vpbroadcastd m9, [pb_64] + jmp .w8_start +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8_start: + vpermt2b m2, m8, m3 + mova m3, m14 + vpdpbusd m3, m2, m9 + vpermb m3, m15, m3 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + mova [maskq], xm3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16: + mova m8, [w_mask_shuf16] + vpbroadcastd m9, [pb_64] + jmp .w16_start +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16_start: + vpermt2b m2, m8, m3 + mova m3, m14 + vpdpbusd m3, m2, m9 + vpermb m3, m15, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + mova [maskq], xm3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w32: + paddw m2, m3 + mova m8, m14 + vpdpwssd m8, m11, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + call .main + paddw m2, m3 + mova m3, m14 + vpdpwssd m3, m11, m2 + vpermt2b m8, m15, m3 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m1 + mova [maskq], ym8 + sub hd, 4 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w64: + mova m8, m2 + mova m9, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + call .main + paddw m8, m2 + paddw m9, m3 + mova m2, m14 + vpdpwssd m2, m11, m8 + mova m3, m14 + vpdpwssd m3, m11, m9 + vpermt2b m2, m15, m3 + mova [dstq+strideq*1+64*0], m0 + mova [dstq+strideq*1+64*1], m1 + mova [maskq], ym2 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 64 +.w128: + mova m16, m2 + mova m8, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + call .main + mova m17, m2 + mova m9, m3 + mova [dstq+strideq*0+64*2], m0 + mova [dstq+strideq*0+64*3], m1 + call .main + paddw m2, m16 + paddw m3, m8 + mova m16, m14 + vpdpwssd m16, m11, m2 + mova m8, m14 + vpdpwssd m8, m11, m3 + mova [dstq+strideq*1+64*0], m0 + mova [dstq+strideq*1+64*1], m1 + call .main + paddw m2, m17 + paddw m3, m9 + mova m17, m14 + vpdpwssd m17, m11, m2 + mova m9, m14 + vpdpwssd m9, m11, m3 + vpermt2b m16, m15, m8 + vpermt2b m17, m15, m9 + mova [dstq+strideq*1+64*2], m0 + mova [dstq+strideq*1+64*3], m1 + mova [maskq+32*0], ym16 + mova [maskq+32*1], ym17 + sub hd, 2 + jg .w128_loop + vzeroupper + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m10, m6 + psrlw m6, 10 ; 64-m + psubw m2, m11, m6 ; m + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m12 + vpdpwssd m0, m5, m1 + mova m1, m12 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m10, m5 + psrlw m5, 10 + psubw m3, m11, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m12 + vpdpwssd m1, m6, m4 + mova m4, m12 + vpdpwssd m4, m7, m5 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpsrlvw m0, m13 + vpsrlvw m1, m13 + ret + +cglobal w_mask_422_16bpc, 4, 8, 15, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx512icl_table + lea r7, [w_mask_422_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m9, [base+pw_64] + vpbroadcastd m10, [base+mask_round+r6*4] + vpbroadcastd m11, [base+bidir_shift+r6*4] + mov r6d, r7m ; sign + vpbroadcastd m12, [base+w_mask_round+r6*4] + mova ym13, [w_mask_end42x] + mov maskq, maskmp + add wq, r7 + paddw m14, m9, m9 ; pw_128 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m8, m6 + psrlw m6, 10 + psubw m2, m9, m6 + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m10 + vpdpwssd m0, m5, m1 + mova m1, m10 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m8, m5 + psrlw m5, 10 + psubw m3, m9, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m10 + vpdpwssd m1, m6, m4 + mova m4, m10 + vpdpwssd m4, m7, m5 + mova m5, m12 + vpdpwssd m5, m14, m2 + mova m2, m12 + vpdpwssd m2, m14, m3 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpermt2b m5, m13, m2 + vpsrlvw m0, m11 + vpsrlvw m1, m11 + mova [maskq], ym5 + add maskq, 32 + ret + +cglobal w_mask_444_16bpc, 4, 8, 13, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx512icl_table + lea r7, [w_mask_444_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m9, [base+pw_64] + vpbroadcastd m10, [base+mask_round+r6*4] + mova m11, [w_mask_end444] + vpbroadcastd m12, [base+bidir_shift+r6*4] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m8, m6 + psrlw m6, 10 + psubw m2, m9, m6 + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m10 + vpdpwssd m0, m5, m1 + mova m1, m10 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m8, m5 + psrlw m5, 10 + psubw m3, m9, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m10 + vpdpwssd m1, m6, m4 + mova m4, m10 + vpdpwssd m4, m7, m5 + vpermt2b m2, m11, m3 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpsrlvw m0, m12 + vpsrlvw m1, m12 + mova [maskq], m2 + add maskq, 64 + ret + +cglobal blend_16bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx512icl_table + lea r6, [blend_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + vpbroadcastd m6, [base+pw_m512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + pmovzxbw ym19, [maskq] + movq xm16, [dstq+dsq*0] + movhps xm16, [dstq+dsq*1] + vpbroadcastq ym17, [dstq+dsq*2] + vpbroadcastq ym18, [dstq+r6 ] + pmullw ym19, ym6 + vpblendd ym16, ym17, 0x30 + vpblendd ym16, ym18, 0xc0 + psubw ym17, ym16, [tmpq] + add maskq, 16 + add tmpq, 32 + pmulhrsw ym17, ym19 + paddw ym16, ym17 + vextracti128 xm17, ym16, 1 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + movq [dstq+dsq*2], xm17 + movhps [dstq+r6 ], xm17 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + vzeroupper + RET +.w8: + pmovzxbw m2, [maskq] + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + vinserti32x4 m0, [dstq+dsq*2], 2 + vinserti32x4 m0, [dstq+r6 ], 3 + pmullw m2, m6 + psubw m1, m0, [tmpq] + add maskq, 32 + add tmpq, 64 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + vextracti32x4 [dstq+dsq*2], m0, 2 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pmovzxbw m4, [maskq+32*0] + pmovzxbw m5, [maskq+32*1] + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + mova ym1, [dstq+dsq*2] + vinserti32x8 m1, [dstq+r6 ], 1 + pmullw m4, m6 + pmullw m5, m6 + psubw m2, m0, [tmpq+64*0] + psubw m3, m1, [tmpq+64*1] + add maskq, 32*2 + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + mova [dstq+dsq*2], ym1 + vextracti32x8 [dstq+r6 ], m1, 1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w16 + RET +.w32: + pmovzxbw m4, [maskq+32*0] + pmovzxbw m5, [maskq+32*1] + mova m0, [dstq+dsq*0] + mova m1, [dstq+dsq*1] + pmullw m4, m6 + pmullw m5, m6 + psubw m2, m0, [tmpq+ 64*0] + psubw m3, m1, [tmpq+ 64*1] + add maskq, 32*2 + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32 + RET + +cglobal blend_v_16bpc, 3, 6, 5, dst, ds, tmp, w, h + lea r5, [blend_v_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + vpbroadcastd xmm2, [obmc_masks_avx2+2*2] +.w2_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movq xmm1, [tmpq] + add tmpq, 4*2 + psubw xmm1, xmm0, xmm1 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + vpbroadcastq xmm2, [obmc_masks_avx2+4*2] +.w4_loop: + movq xmm0, [dstq+dsq*0] + movhps xmm0, [dstq+dsq*1] + psubw xmm1, xmm0, [tmpq] + add tmpq, 8*2 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + vbroadcasti32x4 ym2, [obmc_masks_avx2+8*2] +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + psubw ym1, ym0, [tmpq] + add tmpq, 16*2 + pmulhrsw ym1, ym2 + paddw ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + vbroadcasti32x8 m2, [obmc_masks_avx2+16*2] +.w16_loop: + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + psubw m1, m0, [tmpq] + add tmpq, 32*2 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + mova m4, [obmc_masks_avx2+32*2] +.w32_loop: + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 64*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop + RET + +cglobal blend_h_16bpc, 3, 7, 9, dst, ds, tmp, w, h, mask +%define base r6-$$ + lea r6, [$$] + tzcnt wd, wm + mov hd, hm + movsxd wq, [base+blend_h_avx512icl_table+wq*4] + lea maskq, [base+obmc_masks_avx2+hq*2] + lea hd, [hq*3] + lea wq, [base+blend_h_avx512icl_table+wq] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movq xmm1, [tmpq] + add tmpq, 4*2 + punpcklwd xmm2, xmm2 + psubw xmm1, xmm0, xmm1 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova xmm3, [blend_shuf] +.w4_loop: + movq xmm0, [dstq+dsq*0] + movhps xmm0, [dstq+dsq*1] + movd xmm2, [maskq+hq*2] + psubw xmm1, xmm0, [tmpq] + add tmpq, 8*2 + pshufb xmm2, xmm3 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + vbroadcasti32x4 ym3, [blend_shuf] + shufpd ym3, ym3, 0x0c +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + vpbroadcastd ym2, [maskq+hq*2] + psubw ym1, ym0, [tmpq] + add tmpq, 16*2 + pshufb ym2, ym3 + pmulhrsw ym1, ym2 + paddw ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +.w16: + vbroadcasti32x4 m3, [blend_shuf] + shufpd m3, m3, 0xf0 +.w16_loop: + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + vpbroadcastd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 32*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +.w32: + vpbroadcastw m4, [maskq+hq*2] + vpbroadcastw m5, [maskq+hq*2+2] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 64*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w32 + RET +.w64: + vpbroadcastw m4, [maskq+hq*2] + mova m0, [dstq+64*0] + psubw m2, m0, [tmpq+64*0] + mova m1, [dstq+64*1] + psubw m3, m1, [tmpq+64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m8, [maskq+hq*2] + mova m0, [dstq+64*0] + psubw m4, m0, [tmpq+64*0] + mova m1, [dstq+64*1] + psubw m5, m1, [tmpq+64*1] + mova m2, [dstq+64*2] + psubw m6, m2, [tmpq+64*2] + mova m3, [dstq+64*3] + psubw m7, m3, [tmpq+64*3] + add tmpq, 64*4 + REPX {pmulhrsw x, m8}, m4, m5, m6, m7 + paddw m0, m4 + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal resize_16bpc, 6, 12, 32, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + mov r6, ~0 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + kmovq k6, r6 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x, _, _, pxmax + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pd_16384] + vpbroadcastd m7, [base+pd_63] + mova m24, [base+resize_permA] + mova m25, [base+resize_permB] + mova m26, [base+resize_permC] + mova m27, [base+resize_permD] + vbroadcasti32x4 m28, [base+resize_shufA] + vbroadcasti32x4 m29, [base+resize_shufB] + mova m30, [base+resize_permE] + vpbroadcastw ym31, pxmaxm + vpdpwssd m8, m5, [base+rescale_mul] ; mx+dx*[0-15] + pslld m5, 4 ; dx*16 + pslld m6, 14 + pxor m2, m2 +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + vptestmd k5, m1, m1 + pand m9, m7 ; filter offset (masked) + ktestw k5, k5 + jz .load + vpbroadcastq m14, [base+pd_0_4] + vpermq m10, m0, q1100 + vpermq m11, m0, q3322 + vpermq m20, m1, q1100 + vpermq m21, m1, q3322 + punpckldq m10, m10 + punpckldq m11, m11 + punpckldq m20, m20 + punpckldq m21, m21 + paddd m10, m14 + paddd m11, m14 + paddd m20, m14 + paddd m21, m14 + vextracti32x8 ym12, m10, 1 + vextracti32x8 ym13, m11, 1 + vextracti32x8 ym22, m20, 1 + vextracti32x8 ym23, m21, 1 + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdq m16{k1}, [srcq+ym10*2] ; 0 1 2 3 + vpgatherdq m17{k2}, [srcq+ym11*2] ; 4 5 6 7 + vpgatherdq m18{k3}, [srcq+ym12*2] ; 8 9 A B + vpgatherdq m19{k4}, [srcq+ym13*2] ; C D E F + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdq m0{k1}, [base+resize_shuf+8+ym20*2] + vpgatherdq m1{k2}, [base+resize_shuf+8+ym21*2] + vpgatherdq m14{k3}, [base+resize_shuf+8+ym22*2] + vpgatherdq m15{k4}, [base+resize_shuf+8+ym23*2] + pshufb m16, m0 + pshufb m17, m1 + pshufb m18, m14 + pshufb m19, m15 + mova m20, m24 + mova m22, m24 + mova m21, m25 + mova m23, m25 + vpermi2d m20, m16, m17 ; 0-3a 0-3b 4-7a 4-7b + vpermi2d m21, m16, m17 ; 0-3c 0-3d 4-7c 4-7d + vpermi2d m22, m18, m19 ; 8-Ba 8-Bb C-Fa C-Fb + vpermi2d m23, m18, m19 ; 8-Bc 8-Bd C-Fc C-Fd + mova m15, m26 + mova m17, m26 + mova m16, m27 + mova m18, m27 + vpermi2q m15, m20, m22 ; 0-3a 4-7a 8-Ba C-Fa + vpermi2q m16, m20, m22 ; 0-3b 4-7b 8-Bb C-Fb + vpermi2q m17, m21, m23 ; 0-3c 4-7c 8-Bc C-Fc + vpermi2q m18, m21, m23 ; 0-3d 4-7d 8-Bd C-Fd + kmovq k1, k6 + kmovq k2, k6 + vpgatherdd m11{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m13{k2}, [base+resize_filter+m9*8+4] + pshufb m10, m11, m28 + pshufb m11, m11, m29 + pshufb m12, m13, m28 + pshufb m13, m13, m29 + jmp .filter +.load: + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdd m11{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m13{k2}, [base+resize_filter+m9*8+4] + pshufb m10, m11, m28 + pshufb m11, m11, m29 + pshufb m12, m13, m28 + pshufb m13, m13, m29 + vpgatherdd m15{k3}, [srcq+m0*2+ 0] + vpgatherdd m16{k4}, [srcq+m0*2+ 4] + kmovq k1, k6 + kmovq k2, k6 + vpgatherdd m17{k1}, [srcq+m0*2+ 8] + vpgatherdd m18{k2}, [srcq+m0*2+12] +.filter: + mova m14, m2 + vpdpwssd m14, m15, m10 + vpdpwssd m14, m16, m11 + vpdpwssd m14, m17, m12 + vpdpwssd m14, m18, m13 + psubd m14, m3, m14 + psrad m14, 15 + packusdw m14, m14 + vpermq m14, m30, m14 + pminsw ym14, ym31 + mova [dstq+xq*2], ym14 + paddd m4, m5 + add xd, 16 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8731 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA + +; dav1d_obmc_masks[] << 9 +obmc_masks: dw 0, 0, 9728, 0, 12800, 7168, 2560, 0 + dw 14336, 11264, 8192, 5632, 3584, 1536, 0, 0 + dw 15360, 13824, 12288, 10752, 9216, 7680, 6144, 5120 + dw 4096, 3072, 2048, 1536, 0, 0, 0, 0 + dw 15872, 14848, 14336, 13312, 12288, 11776, 10752, 10240 + dw 9728, 8704, 8192, 7168, 6656, 6144, 5632, 4608 + dw 4096, 3584, 3072, 2560, 2048, 2048, 1536, 1024 + +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +spel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +spel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +spel_h_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +spel_s_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 +spel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +unpckw: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +rescale_mul: dd 0, 1, 2, 3 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 +bdct_lb_q: times 8 db 0 + times 8 db 4 + times 8 db 8 + times 8 db 12 + +pw_2: times 8 dw 2 +pw_16: times 4 dw 16 +prep_mul: times 4 dw 16 + times 8 dw 4 +pw_64: times 8 dw 64 +pw_256: times 8 dw 256 +pw_2048: times 4 dw 2048 +bidir_mul: times 4 dw 2048 +pw_8192: times 8 dw 8192 +pw_27615: times 8 dw 27615 +pw_32766: times 8 dw 32766 +pw_m512: times 8 dw -512 +pd_63: times 4 dd 63 +pd_64: times 4 dd 64 +pd_512: times 4 dd 512 +pd_m524256: times 4 dd -524256 ; -8192 << 6 + 32 +pd_0x3ff: times 4 dd 0x3ff +pd_0x4000: times 4 dd 0x4000 +pq_0x400000: times 2 dq 0x400000 +pq_0x40000000: times 2 dq 0x40000000 +pd_65538: times 2 dd 65538 + +put_bilin_h_rnd: times 4 dw 8 + times 4 dw 10 +s_8tap_h_rnd: times 2 dd 2 + times 2 dd 8 +put_s_8tap_v_rnd: times 2 dd 512 + times 2 dd 128 +s_8tap_h_sh: dd 2, 4 +put_s_8tap_v_sh: dd 10, 8 +bidir_rnd: times 4 dw -16400 + times 4 dw -16388 +put_8tap_h_rnd: dd 34, 34, 40, 40 +prep_8tap_1d_rnd: times 2 dd 8 - (8192 << 4) +prep_8tap_2d_rnd: times 4 dd 32 - (8192 << 5) + +warp8x8_shift: dd 11, 13 +warp8x8_rnd1: dd 1024, 1024, 4096, 4096 +warp8x8_rnd2: times 4 dw 4096 + times 4 dw 16384 +warp8x8t_rnd: times 2 dd 16384 - (8192 << 15) + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, ssse3, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, ssse3, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, ssse3, 2, 4, 8, 16, 32, 64, 128 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_ssse3 mangle(private_prefix %+ _put_bilin_16bpc_ssse3.put) +%xdefine prep_ssse3 mangle(private_prefix %+ _prep_bilin_16bpc_ssse3.prep) + +BASE_JMP_TABLE put, ssse3, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, ssse3, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_16bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, ssse3, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, ssse3, 4, 8, 16, 32, 64, 128 + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern resize_filter + +SECTION .text + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +INIT_XMM ssse3 +cglobal put_bilin_16bpc, 4, 7, 0, dst, ds, src, ss, w, h, mxy +%define base t0-put_ssse3 + mov mxyd, r6m ; mx + LEA t0, put_ssse3 + movifnidn wd, wm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + tzcnt wd, wd + movzx wd, word [base+put_ssse3_table+wq*2] + add wq, t0 + movifnidn hd, hm + jmp wq +.put_w2: + mov r4d, [srcq+ssq*0] + mov r6d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4d + mov [dstq+dsq*1], r6d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq [dstq+dsq*0], m0 + movq [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0+16*0] + movu m1, [srcq+ssq*0+16*1] + movu m2, [srcq+ssq*1+16*0] + movu m3, [srcq+ssq*1+16*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+16*0], m0 + mova [dstq+dsq*0+16*1], m1 + mova [dstq+dsq*1+16*0], m2 + mova [dstq+dsq*1+16*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, ssq + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + add dstq, dsq + dec hd + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, ssq + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + add srcq, 16*8 + add dstq, 16*8 +.put_w128_loop: + movu m0, [srcq-16*8] + movu m1, [srcq-16*7] + movu m2, [srcq-16*6] + movu m3, [srcq-16*5] + mova [dstq-16*8], m0 + mova [dstq-16*7], m1 + mova [dstq-16*6], m2 + mova [dstq-16*5], m3 + movu m0, [srcq-16*4] + movu m1, [srcq-16*3] + movu m2, [srcq-16*2] + movu m3, [srcq-16*1] + mova [dstq-16*4], m0 + mova [dstq-16*3], m1 + mova [dstq-16*2], m2 + mova [dstq-16*1], m3 + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, ssq + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add dstq, dsq + dec hd + jg .put_w128_loop + RET +.h: + movd m5, mxyd + mov mxyd, r7m ; my + mova m4, [base+pw_16] + pshufb m5, [base+pw_256] + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + mov r6d, r8m ; bitdepth_max + shr r6d, 11 + movddup m3, [base+put_bilin_h_rnd+r6*8] + movifnidn hd, hm + sub wd, 8 + jg .h_w16 + je .h_w8 + cmp wd, -4 + je .h_w4 +.h_w2: + movq m1, [srcq+ssq*0] + movhps m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw m0, m4, m1 + psrlq m1, 16 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + movd [dstq+dsq*0], m0 + punpckhqdq m0, m0 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq m0, [srcq+ssq*0] + movhps m0, [srcq+ssq*1] + movq m1, [srcq+ssq*0+2] + movhps m1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + neg wq +.h_w16_loop0: + mov r6, wq +.h_w16_loop: + movu m0, [srcq+r6*2+ 0] + movu m1, [srcq+r6*2+ 2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + movu m1, [srcq+r6*2+16] + movu m2, [srcq+r6*2+18] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+r6*2+16*0], m0 + mova [dstq+r6*2+16*1], m1 + add r6, 16 + jl .h_w16_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w16_loop0 + RET +.v: + shl mxyd, 11 + movd m5, mxyd + pshufb m5, [base+pw_256] + movifnidn hd, hm + cmp wd, 4 + jg .v_w8 + je .v_w4 +.v_w2: + movd m0, [srcq+ssq*0] +.v_w2_loop: + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq m2, m0, m1 + movd m0, [srcq+ssq*0] + punpcklqdq m1, m0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + movd [dstq+dsq*0], m1 + punpckhqdq m1, m1 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq m0, [srcq+ssq*0] +.v_w4_loop: + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq m2, m0, m1 + movq m0, [srcq+ssq*0] + punpcklqdq m1, m0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: +%if ARCH_X86_64 +%if WIN64 + push r7 +%endif + shl wd, 5 + mov r7, srcq + lea r6d, [wq+hq-256] + mov r4, dstq +%else + mov r6, srcq +%endif +.v_w8_loop0: + movu m0, [srcq+ssq*0] +.v_w8_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m5 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m5 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop +%if ARCH_X86_64 + add r7, 16 + add r4, 16 + movzx hd, r6b + mov srcq, r7 + mov dstq, r4 + sub r6d, 1<<8 +%else + mov dstq, dstmp + add r6, 16 + mov hd, hm + add dstq, 16 + mov srcq, r6 + mov dstmp, dstq + sub wd, 8 +%endif + jg .v_w8_loop0 +%if WIN64 + pop r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 8 + shl mxyd, 11 + mova m3, [base+pw_2] + movd m6, mxyd + mova m7, [base+pw_8192] + pshufb m6, [base+pw_256] + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + mova m7, [base+pw_2048] +.hv_12bpc: + movifnidn hd, hm + cmp wd, 4 + jg .hv_w8 + je .hv_w4 +.hv_w2: + movddup m0, [srcq+ssq*0] + pshufhw m1, m0, q0321 + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w2_loop: + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps m2, [srcq+ssq*0] + pmullw m1, m4, m2 + psrlq m2, 16 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 _ 2 _ + shufpd m2, m0, m1, 0x01 ; 0 _ 1 _ + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + movd [dstq+dsq*0], m1 + punpckhqdq m1, m1 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + movddup m0, [srcq+ssq*0] + movddup m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w4_loop: + movq m1, [srcq+ssq*1] + movq m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps m1, [srcq+ssq*0] + movhps m2, [srcq+ssq*0+2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + shufpd m2, m0, m1, 0x01 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: +%if ARCH_X86_64 +%if WIN64 + push r7 +%endif + shl wd, 5 + lea r6d, [wq+hq-256] + mov r4, srcq + mov r7, dstq +%else + mov r6, srcq +%endif +.hv_w8_loop0: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w8_loop: + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 + psubw m2, m1, m0 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m0 + pmulhrsw m2, m7 + mova [dstq+dsq*0], m2 + movu m0, [srcq+ssq*0] + movu m2, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m2, m5 + paddw m0, m3 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m1 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m1 + pmulhrsw m2, m7 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop +%if ARCH_X86_64 + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 +%else + mov dstq, dstmp + add r6, 16 + mov hd, hm + add dstq, 16 + mov srcq, r6 + mov dstmp, dstq + sub wd, 8 +%endif + jg .hv_w8_loop0 +%if WIN64 + pop r7 +%endif + RET + +cglobal prep_bilin_16bpc, 4, 7, 0, tmp, src, stride, w, h, mxy, stride3 +%define base r6-prep_ssse3 + movifnidn mxyd, r5m ; mx + LEA r6, prep_ssse3 + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + tzcnt wd, wd + movzx wd, word [base+prep_ssse3_table+wq*2] + mov r5d, r7m ; bitdepth_max + mova m5, [base+pw_8192] + add wq, r6 + shr r5d, 11 + movddup m4, [base+prep_mul+r5*8] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*2] + movhps m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu m0, [srcq+strideq*0+16*0] + movu m1, [srcq+strideq*0+16*1] + movu m2, [srcq+strideq*1+16*0] + movu m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .prep_w16 + RET +.prep_w32: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + dec hd + jg .prep_w32 + RET +.prep_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*4], m0 + mova [tmpq+16*5], m1 + mova [tmpq+16*6], m2 + mova [tmpq+16*7], m3 + add tmpq, 16*8 + dec hd + jg .prep_w64 + RET +.prep_w128: + movu m0, [srcq+16* 0] + movu m1, [srcq+16* 1] + movu m2, [srcq+16* 2] + movu m3, [srcq+16* 3] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + movu m0, [srcq+16* 4] + movu m1, [srcq+16* 5] + movu m2, [srcq+16* 6] + movu m3, [srcq+16* 7] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*4], m0 + mova [tmpq+16*5], m1 + mova [tmpq+16*6], m2 + mova [tmpq+16*7], m3 + movu m0, [srcq+16* 8] + movu m1, [srcq+16* 9] + movu m2, [srcq+16*10] + movu m3, [srcq+16*11] + add tmpq, 16*16 + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq-16*8], m0 + mova [tmpq-16*7], m1 + mova [tmpq-16*6], m2 + mova [tmpq-16*5], m3 + movu m0, [srcq+16*12] + movu m1, [srcq+16*13] + movu m2, [srcq+16*14] + movu m3, [srcq+16*15] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq-16*4], m0 + mova [tmpq-16*3], m1 + mova [tmpq-16*2], m2 + mova [tmpq-16*1], m3 + dec hd + jg .prep_w128 + RET +.h: + movd m4, mxyd + mov mxyd, r6m ; my + mova m3, [base+pw_16] + pshufb m4, [base+pw_256] + mova m5, [base+pw_32766] + psubw m3, m4 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m3, 2 + psllw m4, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + sub wd, 8 + je .h_w8 + jg .h_w16 +.h_w4: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*0+2] + movhps m1, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 16 + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + lea srcq, [srcq+wq*2] + neg wq +.h_w16_loop0: + mov r6, wq +.h_w16_loop: + movu m0, [srcq+r6*2+ 0] + movu m1, [srcq+r6*2+ 2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + movu m1, [srcq+r6*2+16] + movu m2, [srcq+r6*2+18] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + add r6, 16 + jl .h_w16_loop + add srcq, strideq + dec hd + jg .h_w16_loop0 + RET +.v: + movd m4, mxyd + mova m3, [base+pw_16] + pshufb m4, [base+pw_256] + mova m5, [base+pw_32766] + psubw m3, m4 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m3, 2 + psllw m4, 2 +.v_12bpc: + cmp wd, 8 + je .v_w8 + jg .v_w16 +.v_w4: + movq m0, [srcq+strideq*0] +.v_w4_loop: + movq m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklqdq m1, m0, m2 ; 0 1 + movq m0, [srcq+strideq*0] + punpcklqdq m2, m0 ; 1 2 + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu m0, [srcq+strideq*0] +.v_w8_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4, m2 + psubw m0, m5 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m3 + mova [tmpq+16*0], m1 + pmullw m1, m4, m0 + psubw m2, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: +%if WIN64 + push r7 +%endif + mov r5, srcq +%if ARCH_X86_64 + lea r6d, [wq*4-32] + mov wd, wd + lea r6d, [hq+r6*8] + mov r7, tmpq +%else + mov r6d, wd +%endif +.v_w16_loop0: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4, m2 + psubw m0, m5 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m3 + mova [tmpq+wq*0], m1 + pmullw m1, m4, m0 + psubw m2, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+wq*2], m1 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w16_loop +%if ARCH_X86_64 + add r5, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 +%else + mov tmpq, tmpmp + add r5, 16 + mov hd, hm + add tmpq, 16 + mov srcq, r5 + mov tmpmp, tmpq + sub r6d, 8 +%endif + jg .v_w16_loop0 +%if WIN64 + pop r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 7 + shl mxyd, 11 + movd m6, mxyd + pshufb m6, [base+pw_256] + cmp wd, 8 + je .hv_w8 + jg .hv_w16 +.hv_w4: + movddup m0, [srcq+strideq*0] + movddup m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w4_loop: + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + movhps m1, [srcq+strideq*0] + movhps m2, [srcq+strideq*0+2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 ; 1 2 + shufpd m2, m0, m1, 0x01 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w8_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+16*0], m2 + movu m0, [srcq+strideq*0] + movu m2, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m2, m4 + psubw m0, m5 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +%if WIN64 + push r7 +%endif + mov r5, srcq +%if ARCH_X86_64 + lea r6d, [wq*4-32] + mov wd, wd + lea r6d, [hq+r6*8] + mov r7, tmpq +%else + mov r6d, wd +%endif +.hv_w16_loop0: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w16_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+wq*0], m2 + movu m0, [srcq+strideq*0] + movu m2, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m2, m4 + psubw m0, m5 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+wq*2], m2 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w16_loop +%if ARCH_X86_64 + add r5, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 +%else + mov tmpq, tmpmp + add r5, 16 + mov hd, hm + add tmpq, 16 + mov srcq, r5 + mov tmpmp, tmpq + sub r6d, 8 +%endif + jg .hv_w16_loop0 +%if WIN64 + pop r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_16bpc %+ SUFFIX) +%endif +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 1, 2, 6 +%elif WIN64 +DECLARE_REG_TMP 4, 5, 8 +%else +DECLARE_REG_TMP 7, 8, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +%if ARCH_X86_32 +cglobal put_8tap_16bpc, 0, 7, 8, dst, ds, src, ss, w, h, mx, my +%define mxb r0b +%define mxd r0 +%define mxq r0 +%define myb r1b +%define myd r1 +%define myq r1 +%define m8 [esp+16*0] +%define m9 [esp+16*1] +%define m10 [esp+16*2] +%define m11 [esp+16*3] +%define m12 [esp+16*4] +%define m13 [esp+16*5] +%define m14 [esp+16*6] +%define m15 [esp+16*7] +%else +cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my +%endif +%define base t2-put_ssse3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + LEA t2, put_ssse3 + movifnidn wd, wm + movifnidn srcq, srcmp + movifnidn ssq, ssmp + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [base+put_ssse3_table+wq*2] + movifnidn dstq, dstmp + movifnidn dsq, dsmp + add wq, t2 +%if WIN64 + pop r8 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + mov myd, r8m + movd m5, r8m + shr myd, 11 + movddup m4, [base+put_8tap_h_rnd+myq*8] + movifnidn dsq, dsmp + pshufb m5, [base+pw_256] + cmp wd, 4 + jg .h_w8 + movzx mxd, mxb + lea srcq, [srcq-2] + movq m3, [base+subpel_filters+mxq*8] + movifnidn dstq, dstmp + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + je .h_w4 +.h_w2: + mova m2, [base+spel_h_shuf2] + pshufd m3, m3, q2121 +.h_w2_loop: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m2 + pshufb m1, m2 + pmaddwd m0, m3 + pmaddwd m1, m3 + phaddd m0, m1 + paddd m0, m4 + psrad m0, 6 + packssdw m0, m0 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + movd [dstq+dsq*0], m0 + pshuflw m0, m0, q3232 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + WIN64_SPILL_XMM 8 + mova m6, [base+spel_h_shufA] + mova m7, [base+spel_h_shufB] + pshufd m2, m3, q1111 + pshufd m3, m3, q2222 +.h_w4_loop: + movu m1, [srcq] + add srcq, ssq + pshufb m0, m1, m6 ; 0 1 1 2 2 3 3 4 + pshufb m1, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m2 + pmaddwd m1, m3 + paddd m0, m4 + paddd m0, m1 + psrad m0, 6 + packssdw m0, m0 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + movq [dstq], m0 + add dstq, dsq + dec hd + jg .h_w4_loop + RET +.h_w8: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 +%endif + shr mxd, 16 + movq m3, [base+subpel_filters+mxq*8] + movifnidn dstq, dstmp + mova m6, [base+spel_h_shufA] + mova m7, [base+spel_h_shufB] +%if UNIX64 + mov wd, wd +%endif + lea srcq, [srcq+wq*2] + punpcklbw m3, m3 + lea dstq, [dstq+wq*2] + psraw m3, 8 + neg wq +%if ARCH_X86_32 + ALLOC_STACK -16*4 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif +.h_w8_loop0: + mov r6, wq +.h_w8_loop: + movu m0, [srcq+r6*2- 6] + movu m1, [srcq+r6*2+ 2] + pshufb m2, m0, m6 ; 0 1 1 2 2 3 3 4 + pshufb m0, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m2, m8 ; abcd0 + pmaddwd m0, m9 ; abcd1 + pshufb m3, m1, m6 ; 4 5 5 6 6 7 7 8 + pshufb m1, m7 ; 6 7 7 8 8 9 9 a + paddd m2, m4 + paddd m0, m2 + pmaddwd m2, m10, m3 ; abcd2 + pmaddwd m3, m8 ; efgh0 + paddd m0, m2 + pmaddwd m2, m11, m1 ; abcd3 + pmaddwd m1, m9 ; efgh1 + paddd m0, m2 + movu m2, [srcq+r6*2+10] + paddd m3, m4 + paddd m1, m3 + pshufb m3, m2, m6 ; 8 9 9 a a b b c + pshufb m2, m7 ; a b b c c d d e + pmaddwd m3, m10 ; efgh2 + pmaddwd m2, m11 ; efgh3 + paddd m1, m3 + paddd m1, m2 + psrad m0, 6 + psrad m1, 6 + packssdw m0, m1 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + mova [dstq+r6*2], m0 + add r6, 8 + jl .h_w8_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w8_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif +%if WIN64 + WIN64_SPILL_XMM 15 +%endif + movd m7, r8m + movifnidn dstq, dstmp + movifnidn dsq, dsmp + punpcklbw m3, m3 + pshufb m7, [base+pw_256] + psraw m3, 8 ; sign-extend +%if ARCH_X86_32 + ALLOC_STACK -16*7 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif + lea r6, [ssq*3] + sub srcq, r6 + cmp wd, 2 + jne .v_w4 +.v_w2: + movd m1, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + movd m2, [srcq+ssq*2] + add srcq, r6 + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m6, [srcq+ssq*2] + add srcq, r6 + movd m0, [srcq+ssq*0] + punpckldq m1, m4 ; 0 1 + punpckldq m4, m2 ; 1 2 + punpckldq m2, m5 ; 2 3 + punpckldq m5, m3 ; 3 4 + punpckldq m3, m6 ; 4 5 + punpckldq m6, m0 ; 5 6 + punpcklwd m1, m4 ; 01 12 + punpcklwd m2, m5 ; 23 34 + punpcklwd m3, m6 ; 45 56 + pxor m6, m6 +.v_w2_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + punpckldq m3, m0, m4 ; 6 7 + movd m0, [srcq+ssq*0] + punpckldq m4, m0 ; 7 8 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 5 + packssdw m5, m5 + pmaxsw m5, m6 + pavgw m5, m6 + pminsw m5, m7 + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q3232 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: +%if ARCH_X86_32 + shl wd, 14 +%if STACK_ALIGNMENT < 16 + mov [esp+4*29], srcq + mov [esp+4*30], dstq +%else + mov srcmp, srcq +%endif + lea wd, [wq+hq-(1<<16)] +%else + shl wd, 6 + mov r7, srcq + mov r8, dstq + lea wd, [wq+hq-(1<<8)] +%endif +.v_w4_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + movq m3, [srcq+ssq*2] + add srcq, r6 + movq m4, [srcq+ssq*0] + movq m5, [srcq+ssq*1] + movq m6, [srcq+ssq*2] + add srcq, r6 + movq m0, [srcq+ssq*0] + punpcklwd m1, m2 ; 01 + punpcklwd m2, m3 ; 12 + punpcklwd m3, m4 ; 23 + punpcklwd m4, m5 ; 34 + punpcklwd m5, m6 ; 45 + punpcklwd m6, m0 ; 56 +%if ARCH_X86_32 + jmp .v_w4_loop_start +.v_w4_loop: + mova m1, m12 + mova m2, m13 + mova m3, m14 +.v_w4_loop_start: + pmaddwd m1, m8 ; a0 + pmaddwd m2, m8 ; b0 + mova m12, m3 + mova m13, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m1, m3 + paddd m2, m4 + mova m14, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m1, m5 + paddd m2, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m3, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m1, m3 + pmaddwd m3, m11, m6 ; b3 + paddd m2, m3 + psrad m1, 5 + psrad m2, 5 + packssdw m1, m2 + pxor m2, m2 + pmaxsw m1, m2 + pavgw m1, m2 + pminsw m1, m7 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop +%if STACK_ALIGNMENT < 16 + mov srcq, [esp+4*29] + mov dstq, [esp+4*30] + movzx hd, ww + add srcq, 8 + add dstq, 8 + mov [esp+4*29], srcq + mov [esp+4*30], dstq +%else + mov srcq, srcmp + mov dstq, dstmp + movzx hd, ww + add srcq, 8 + add dstq, 8 + mov srcmp, srcq + mov dstmp, dstq +%endif + sub wd, 1<<16 +%else +.v_w4_loop: + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + paddd m13, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m14, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 5 + psrad m13, 5 + packssdw m12, m13 + pxor m13, m13 + pmaxsw m12, m13 + pavgw m12, m13 + pminsw m12, m7 + movq [dstq+dsq*0], m12 + movhps [dstq+dsq*1], m12 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + add r7, 8 + add r8, 8 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 +%endif + jg .v_w4_loop0 + RET +.hv: +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif +%if ARCH_X86_32 + movd m4, r8m + mova m6, [base+pd_512] + pshufb m4, [base+pw_256] +%else +%if WIN64 + ALLOC_STACK 16*6, 16 +%endif + movd m15, r8m + pshufb m15, [base+pw_256] +%endif + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + je .hv_w4 + movq m0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 + mov dstq, dstmp + mov dsq, dsmp + mova m5, [base+spel_h_shuf2] + ALLOC_STACK -16*8 +%else + mova m6, [base+pd_512] + mova m9, [base+spel_h_shuf2] +%endif + pshuflw m0, m0, q2121 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + test dword r8m, 0x800 + jz .hv_w2_10bpc + psraw m7, 2 + psllw m3, 2 +.hv_w2_10bpc: + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 +%if ARCH_X86_32 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m9, m5 + mova m11, m0 + mova m12, m1 + mova m13, m2 + mova m14, m3 + mova m15, m4 +%else + pshufd m11, m3, q0000 + pshufd m12, m3, q1111 + pshufd m13, m3, q2222 + pshufd m14, m3, q3333 +%endif + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + movu m1, [srcq+ssq*2] + add srcq, r6 + movu m4, [srcq+ssq*0] +%if ARCH_X86_32 + REPX {pshufb x, m5}, m2, m3, m1, m4 +%else + REPX {pshufb x, m9}, m2, m3, m1, m4 +%endif + REPX {pmaddwd x, m7}, m2, m3, m1, m4 + phaddd m2, m3 ; 0 1 + phaddd m1, m4 ; 2 3 + movu m3, [srcq+ssq*1] + movu m4, [srcq+ssq*2] + add srcq, r6 + movu m0, [srcq+ssq*0] +%if ARCH_X86_32 + REPX {pshufb x, m5}, m3, m4, m0 +%else + REPX {pshufb x, m9}, m3, m4, m0 +%endif + REPX {pmaddwd x, m7}, m3, m4, m0 + phaddd m3, m4 ; 4 5 + phaddd m0, m0 ; 6 6 + REPX {paddd x, m6}, m2, m1, m3, m0 + REPX {psrad x, 10}, m2, m1, m3, m0 + packssdw m2, m1 ; 0 1 2 3 + packssdw m3, m0 ; 4 5 6 _ + palignr m4, m3, m2, 4 ; 1 2 3 4 + pshufd m5, m3, q0321 ; 5 6 _ _ + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + punpcklwd m3, m5 ; 45 56 +.hv_w2_loop: + movu m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movu m5, [srcq+ssq*0] + pshufb m4, m9 + pshufb m5, m9 + pmaddwd m4, m7 + pmaddwd m5, m7 + phaddd m4, m5 + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + paddd m4, m6 + psrad m4, 10 ; 7 8 + packssdw m0, m4 + pshufd m3, m0, q2103 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m5, m6 + paddd m5, m4 + psrad m5, 10 + packssdw m5, m5 + pxor m4, m4 + pminsw m5, m15 + pmaxsw m5, m4 + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q3232 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w8: + shr mxd, 16 +.hv_w4: + movq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + mov dstq, dstmp + mov dsq, dsmp + mova m0, [base+spel_h_shufA] + mova m1, [base+spel_h_shufB] + ALLOC_STACK -16*15 + mova m8, m0 + mova m9, m1 + mova m14, m6 +%else + mova m8, [base+spel_h_shufA] + mova m9, [base+spel_h_shufB] +%endif + pxor m0, m0 + punpcklbw m0, m2 + punpcklbw m3, m3 + psraw m3, 8 + test dword r8m, 0x800 + jz .hv_w4_10bpc + psraw m0, 2 + psllw m3, 2 +.hv_w4_10bpc: + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 +%if ARCH_X86_32 + %define tmp esp+16*8 + shl wd, 14 +%if STACK_ALIGNMENT < 16 + mov [esp+4*61], srcq + mov [esp+4*62], dstq +%else + mov srcmp, srcq +%endif + mova [tmp+16*5], m4 + lea wd, [wq+hq-(1<<16)] + pshufd m1, m0, q0000 + pshufd m2, m0, q1111 + pshufd m5, m0, q2222 + pshufd m0, m0, q3333 + mova m10, m1 + mova m11, m2 + mova m12, m5 + mova m13, m0 +%else +%if WIN64 + %define tmp rsp +%else + %define tmp rsp-104 ; red zone +%endif + shl wd, 6 + mov r7, srcq + mov r8, dstq + lea wd, [wq+hq-(1<<8)] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 + mova [tmp+16*5], m15 +%endif + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [tmp+16*1], m0 + mova [tmp+16*2], m1 + mova [tmp+16*3], m2 + mova [tmp+16*4], m3 +%macro PUT_8TAP_HV_H 4-5 m14 ; dst/src+0, src+8, tmp, shift, [pd_512] + pshufb m%3, m%1, m8 ; 0 1 1 2 2 3 3 4 + pshufb m%1, m9 ; 2 3 3 4 4 5 5 6 + pmaddwd m%3, m10 + pmaddwd m%1, m11 + paddd m%3, %5 + paddd m%1, m%3 + pshufb m%3, m%2, m8 ; 4 5 5 6 6 7 7 8 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + pmaddwd m%3, m12 + pmaddwd m%2, m13 + paddd m%1, m%3 + paddd m%1, m%2 + psrad m%1, %4 +%endmacro +.hv_w4_loop0: +%if ARCH_X86_64 + mova m14, [pd_512] +%endif + movu m4, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + movu m5, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + movu m6, [srcq+ssq*2+0] + movu m3, [srcq+ssq*2+8] + add srcq, r6 + PUT_8TAP_HV_H 4, 1, 0, 10 + PUT_8TAP_HV_H 5, 2, 0, 10 + PUT_8TAP_HV_H 6, 3, 0, 10 + movu m7, [srcq+ssq*0+0] + movu m2, [srcq+ssq*0+8] + movu m1, [srcq+ssq*1+0] + movu m3, [srcq+ssq*1+8] + PUT_8TAP_HV_H 7, 2, 0, 10 + PUT_8TAP_HV_H 1, 3, 0, 10 + movu m2, [srcq+ssq*2+0] + movu m3, [srcq+ssq*2+8] + add srcq, r6 + PUT_8TAP_HV_H 2, 3, 0, 10 + packssdw m4, m7 ; 0 3 + packssdw m5, m1 ; 1 4 + movu m0, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 1, 3, 10 + packssdw m6, m2 ; 2 5 + packssdw m7, m0 ; 3 6 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +%if ARCH_X86_32 + jmp .hv_w4_loop_start +.hv_w4_loop: + mova m1, [tmp+16*6] + mova m2, m15 +.hv_w4_loop_start: + mova m7, [tmp+16*1] + pmaddwd m1, m7 ; a0 + pmaddwd m2, m7 ; b0 + mova m7, [tmp+16*2] + mova [tmp+16*6], m3 + pmaddwd m3, m7 ; a1 + mova m15, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m1, m3 + paddd m2, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m1, m5 + paddd m2, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 10 + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 10 + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m1, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m2, m7 ; b3 + psrad m1, 9 + psrad m2, 9 + packssdw m1, m2 + pxor m7, m7 + pmaxsw m1, m7 + pavgw m7, m1 + pminsw m7, [tmp+16*5] + movq [dstq+dsq*0], m7 + movhps [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop +%if STACK_ALIGNMENT < 16 + mov srcq, [esp+4*61] + mov dstq, [esp+4*62] + add srcq, 8 + add dstq, 8 + mov [esp+4*61], srcq + mov [esp+4*62], dstq +%else + mov srcq, srcmp + mov dstq, dstmp + add srcq, 8 + add dstq, 8 + mov srcmp, srcq + mov dstmp, dstq +%endif + movzx hd, ww + sub wd, 1<<16 +%else +.hv_w4_loop: + mova m15, [tmp+16*1] + pmaddwd m14, m15, m1 ; a0 + pmaddwd m15, m2 ; b0 + mova m7, [tmp+16*2] + mova m1, m3 + pmaddwd m3, m7 ; a1 + mova m2, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m14, m3 + paddd m15, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m14, m5 + paddd m15, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 10, [pd_512] + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 10, [pd_512] + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m14, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m15, m7 ; b3 + psrad m14, 9 + psrad m15, 9 + packssdw m14, m15 + pxor m7, m7 + pmaxsw m14, m7 + pavgw m7, m14 + pminsw m7, [tmp+16*5] + movq [dstq+dsq*0], m7 + movhps [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + add r7, 8 + add r8, 8 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 +%endif + jg .hv_w4_loop0 + RET +%undef tmp + +%if ARCH_X86_32 +DECLARE_REG_TMP 2, 1, 6, 4 +%elif WIN64 +DECLARE_REG_TMP 6, 4, 7, 4 +%else +DECLARE_REG_TMP 6, 7, 7, 8 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +%if ARCH_X86_32 +cglobal prep_8tap_16bpc, 0, 7, 8, tmp, src, ss, w, h, mx, my +%define mxb r0b +%define mxd r0 +%define mxq r0 +%define myb r2b +%define myd r2 +%define myq r2 +%else +cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, ss, w, h, mx, my +%endif +%define base t2-prep_ssse3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + LEA t2, prep_ssse3 + movifnidn wd, wm + movifnidn srcq, srcmp + test mxd, 0xf00 + jnz .h + movifnidn hd, hm + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov myd, r7m ; bitdepth_max + movzx wd, word [base+prep_ssse3_table+wq*2] + mova m5, [base+pw_8192] + shr myd, 11 + add wq, t2 + movddup m4, [base+prep_mul+myq*8] + movifnidn ssq, ssmp + movifnidn tmpq, tmpmp + lea r6, [ssq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + movifnidn ssq, r2mp + movifnidn hd, r4m + movddup m5, [base+prep_8tap_1d_rnd] + cmp wd, 4 + jne .h_w8 + movzx mxd, mxb + movq m0, [base+subpel_filters+mxq*8] + mova m3, [base+spel_h_shufA] + mova m4, [base+spel_h_shufB] + movifnidn tmpq, tmpmp + sub srcq, 2 + WIN64_SPILL_XMM 8 + punpcklbw m0, m0 + psraw m0, 8 + test dword r7m, 0x800 + jnz .h_w4_12bpc + psllw m0, 2 +.h_w4_12bpc: + pshufd m6, m0, q1111 + pshufd m7, m0, q2222 +.h_w4_loop: + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m1, m3 ; 0 1 1 2 2 3 3 4 + pshufb m1, m4 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m6 + pmaddwd m1, m7 + paddd m0, m5 + paddd m0, m1 + pshufb m1, m2, m3 + pshufb m2, m4 + pmaddwd m1, m6 + pmaddwd m2, m7 + paddd m1, m5 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq], m0 + add tmpq, 16 + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + WIN64_SPILL_XMM 11 + shr mxd, 16 + movq m2, [base+subpel_filters+mxq*8] + mova m4, [base+spel_h_shufA] + mova m6, [base+spel_h_shufB] + movifnidn tmpq, r0mp + add wd, wd + punpcklbw m2, m2 + add srcq, wq + psraw m2, 8 + add tmpq, wq + neg wq + test dword r7m, 0x800 + jnz .h_w8_12bpc + psllw m2, 2 +.h_w8_12bpc: + pshufd m7, m2, q0000 +%if ARCH_X86_32 + ALLOC_STACK -16*3 + pshufd m0, m2, q1111 + pshufd m1, m2, q2222 + pshufd m2, m2, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 +%else + pshufd m8, m2, q1111 + pshufd m9, m2, q2222 + pshufd m10, m2, q3333 +%endif +.h_w8_loop0: + mov r6, wq +.h_w8_loop: + movu m0, [srcq+r6- 6] + movu m1, [srcq+r6+ 2] + pshufb m2, m0, m4 ; 0 1 1 2 2 3 3 4 + pshufb m0, m6 ; 2 3 3 4 4 5 5 6 + pmaddwd m2, m7 ; abcd0 + pmaddwd m0, m8 ; abcd1 + pshufb m3, m1, m4 ; 4 5 5 6 6 7 7 8 + pshufb m1, m6 ; 6 7 7 8 8 9 9 a + paddd m2, m5 + paddd m0, m2 + pmaddwd m2, m9, m3 ; abcd2 + pmaddwd m3, m7 ; efgh0 + paddd m0, m2 + pmaddwd m2, m10, m1 ; abcd3 + pmaddwd m1, m8 ; efgh1 + paddd m0, m2 + movu m2, [srcq+r6+10] + paddd m3, m5 + paddd m1, m3 + pshufb m3, m2, m4 ; a b b c c d d e + pshufb m2, m6 ; 8 9 9 a a b b c + pmaddwd m3, m9 ; efgh2 + pmaddwd m2, m10 ; efgh3 + paddd m1, m3 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq+r6], m0 + add r6, 16 + jl .h_w8_loop + add srcq, ssq + sub tmpq, wq + dec hd + jg .h_w8_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + WIN64_SPILL_XMM 15 + movddup m7, [base+prep_8tap_1d_rnd] + movifnidn ssq, r2mp + movifnidn tmpq, r0mp + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + test dword r7m, 0x800 + jnz .v_12bpc + psllw m3, 2 +.v_12bpc: +%if ARCH_X86_32 + ALLOC_STACK -16*7 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif + lea r6, [ssq*3] + sub srcq, r6 + mov r6d, wd + shl wd, 6 + mov r5, srcq +%if ARCH_X86_64 + mov r7, tmpq +%elif STACK_ALIGNMENT < 16 + mov [esp+4*29], tmpq +%endif + lea wd, [wq+hq-(1<<8)] +.v_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m3, [srcq+ssq*0] + movq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m5, [srcq+ssq*0] + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m0, [srcq+ssq*0] + punpcklwd m1, m2 ; 01 + punpcklwd m2, m3 ; 12 + punpcklwd m3, m4 ; 23 + punpcklwd m4, m5 ; 34 + punpcklwd m5, m6 ; 45 + punpcklwd m6, m0 ; 56 +%if ARCH_X86_32 + jmp .v_loop_start +.v_loop: + mova m1, m12 + mova m2, m13 + mova m3, m14 +.v_loop_start: + pmaddwd m1, m8 ; a0 + pmaddwd m2, m8 ; b0 + mova m12, m3 + mova m13, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m1, m3 + paddd m2, m4 + mova m14, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m1, m5 + paddd m2, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m3, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m1, m7 + paddd m1, m3 + pmaddwd m3, m11, m6 ; b3 + paddd m2, m7 + paddd m2, m3 + psrad m1, 4 + psrad m2, 4 + packssdw m1, m2 + movq [tmpq+r6*0], m1 + movhps [tmpq+r6*2], m1 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .v_loop +%if STACK_ALIGNMENT < 16 + mov tmpq, [esp+4*29] + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov [esp+4*29], tmpq +%else + mov tmpq, tmpmp + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov tmpmp, tmpq +%endif +%else +.v_loop: + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + paddd m13, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m14, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m12, m7 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m7 + paddd m13, m14 + psrad m12, 4 + psrad m13, 4 + packssdw m12, m13 + movq [tmpq+r6*0], m12 + movhps [tmpq+r6*2], m12 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .v_loop + add r5, 8 + add r7, 8 + mov srcq, r5 + mov tmpq, r7 +%endif + movzx hd, wb + sub wd, 1<<8 + jg .v_loop0 + RET +.hv: +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + movzx t3d, mxb + shr mxd, 16 + cmp wd, 4 + cmove mxd, t3d + movifnidn hd, r4m + movq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 + mov ssq, r2mp + mov tmpq, r0mp + mova m0, [base+spel_h_shufA] + mova m1, [base+spel_h_shufB] + mova m4, [base+prep_8tap_2d_rnd] + ALLOC_STACK -16*14 + mova m8, m0 + mova m9, m1 + mova m14, m4 +%else +%if WIN64 + ALLOC_STACK 16*6, 16 +%endif + mova m8, [base+spel_h_shufA] + mova m9, [base+spel_h_shufB] +%endif + pxor m0, m0 + punpcklbw m0, m2 + punpcklbw m3, m3 + psraw m0, 4 + psraw m3, 8 + test dword r7m, 0x800 + jz .hv_10bpc + psraw m0, 2 +.hv_10bpc: + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + mov r6d, wd + shl wd, 6 + mov r5, srcq +%if ARCH_X86_32 + %define tmp esp+16*8 +%if STACK_ALIGNMENT < 16 + mov [esp+4*61], tmpq +%endif + pshufd m1, m0, q0000 + pshufd m2, m0, q1111 + pshufd m5, m0, q2222 + pshufd m0, m0, q3333 + mova m10, m1 + mova m11, m2 + mova m12, m5 + mova m13, m0 +%else +%if WIN64 + %define tmp rsp +%else + %define tmp rsp-88 ; red zone +%endif + mov r7, tmpq + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + lea wd, [wq+hq-(1<<8)] + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [tmp+16*1], m0 + mova [tmp+16*2], m1 + mova [tmp+16*3], m2 + mova [tmp+16*4], m3 +.hv_loop0: +%if ARCH_X86_64 + mova m14, [prep_8tap_2d_rnd] +%endif + movu m4, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + movu m5, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + movu m6, [srcq+ssq*0+0] + movu m3, [srcq+ssq*0+8] + PUT_8TAP_HV_H 4, 1, 0, 6 + PUT_8TAP_HV_H 5, 2, 0, 6 + PUT_8TAP_HV_H 6, 3, 0, 6 + movu m7, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + movu m1, [srcq+ssq*0+0] + movu m3, [srcq+ssq*0+8] + PUT_8TAP_HV_H 7, 2, 0, 6 + PUT_8TAP_HV_H 1, 3, 0, 6 + movu m2, [srcq+ssq*1+0] + movu m3, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 2, 3, 0, 6 + packssdw m4, m7 ; 0 3 + packssdw m5, m1 ; 1 4 + movu m0, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 1, 3, 6 + packssdw m6, m2 ; 2 5 + packssdw m7, m0 ; 3 6 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +%if ARCH_X86_32 + jmp .hv_loop_start +.hv_loop: + mova m1, [tmp+16*5] + mova m2, m15 +.hv_loop_start: + mova m7, [tmp+16*1] + pmaddwd m1, m7 ; a0 + pmaddwd m2, m7 ; b0 + mova m7, [tmp+16*2] + mova [tmp+16*5], m3 + pmaddwd m3, m7 ; a1 + mova m15, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m1, m14 + paddd m2, m14 + paddd m1, m3 + paddd m2, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m1, m5 + paddd m2, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 6 + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 6 + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m1, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m2, m7 ; b3 + psrad m1, 6 + psrad m2, 6 + packssdw m1, m2 + movq [tmpq+r6*0], m1 + movhps [tmpq+r6*2], m1 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .hv_loop +%if STACK_ALIGNMENT < 16 + mov tmpq, [esp+4*61] + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov [esp+4*61], tmpq +%else + mov tmpq, tmpmp + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov tmpmp, tmpq +%endif +%else +.hv_loop: + mova m15, [tmp+16*1] + mova m7, [prep_8tap_2d_rnd] + pmaddwd m14, m15, m1 ; a0 + pmaddwd m15, m2 ; b0 + paddd m14, m7 + paddd m15, m7 + mova m7, [tmp+16*2] + mova m1, m3 + pmaddwd m3, m7 ; a1 + mova m2, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m14, m3 + paddd m15, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m14, m5 + paddd m15, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 6, [prep_8tap_2d_rnd] + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 6, [prep_8tap_2d_rnd] + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m14, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m15, m7 ; b3 + psrad m14, 6 + psrad m15, 6 + packssdw m14, m15 + movq [tmpq+r6*0], m14 + movhps [tmpq+r6*2], m14 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .hv_loop + add r5, 8 + add r7, 8 + mov srcq, r5 + mov tmpq, r7 +%endif + movzx hd, wb + sub wd, 1<<8 + jg .hv_loop0 + RET +%undef tmp + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro SAVE_REG 1 + %xdefine r%1_save r%1 + %xdefine r%1q_save r%1q + %xdefine r%1d_save r%1d + %if ARCH_X86_32 + %define r%1m_save [rstk+stack_offset+(%1+1)*4] + %endif +%endmacro + +%macro LOAD_REG 1 + %xdefine r%1 r%1_save + %xdefine r%1q r%1q_save + %xdefine r%1d r%1d_save + %if ARCH_X86_32 + %define r%1m r%1m_save + %endif + %undef r%1d_save + %undef r%1q_save + %undef r%1_save +%endmacro + +%macro REMAP_REG 2-3 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d + %if ARCH_X86_32 + %if %3 == 0 + %xdefine r%1m r%2m + %else + %define r%1m [rstk+stack_offset+(%1+1)*4] + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %if ARCH_X86_64 + SAVE_REG 14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %else + SAVE_REG 5 + %assign %%i 5 + %rep 5 + %assign %%j %%i-1 + REMAP_REG %%i, %%j, 0 + %assign %%i %%i-1 + %endrep + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %if ARCH_X86_64 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + LOAD_REG 14 + %else + %rep 4 + %assign %%j %%i+1 + REMAP_REG %%i, %%j, 1 + %assign %%i %%i+1 + %endrep + LOAD_REG 5 + %endif + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%if ARCH_X86_32 + %macro MC_4TAP_SCALED_H 1 ; dst_mem + movu m7, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m5, [r4 +ssq*0] + movu m6, [r4 +ssq*1] + lea srcq, [srcq+ssq*2] + lea r4, [r4 +ssq*2] + REPX {pshufb x, m12}, m7, m2 + REPX {pmaddwd x, m13}, m7, m2 + REPX {pshufb x, m14}, m5, m6 + REPX {pmaddwd x, m15}, m5, m6 + phaddd m7, m5 + phaddd m2, m6 + mova m5, [esp+0x00] + movd m6, [esp+0x10] + paddd m7, m5 + paddd m2, m5 + psrad m7, m6 + psrad m2, m6 + packssdw m7, m2 + mova [stk+%1], m7 + %endmacro +%endif + +%if ARCH_X86_64 + %macro MC_8TAP_SCALED_H 8 ; dst, tmp[0-6] + movu m%1, [srcq+ r4*2] + movu m%2, [srcq+ r6*2] + movu m%3, [srcq+ r7*2] + movu m%4, [srcq+ r9*2] + movu m%5, [srcq+r10*2] + movu m%6, [srcq+r11*2] + movu m%7, [srcq+r13*2] + movu m%8, [srcq+ rX*2] + add srcq, ssq + pmaddwd m%1, [stk+0x10] + pmaddwd m%2, [stk+0x20] + pmaddwd m%3, [stk+0x30] + pmaddwd m%4, [stk+0x40] + pmaddwd m%5, [stk+0x50] + pmaddwd m%6, [stk+0x60] + pmaddwd m%7, [stk+0x70] + pmaddwd m%8, [stk+0x80] + phaddd m%1, m%2 + phaddd m%3, m%4 + phaddd m%5, m%6 + phaddd m%7, m%8 + phaddd m%1, m%3 + phaddd m%5, m%7 + paddd m%1, hround + paddd m%5, hround + psrad m%1, m12 + psrad m%5, m12 + packssdw m%1, m%5 + %endmacro +%else + %macro MC_8TAP_SCALED_H 2-3 1 ; weights_mem_start, h_mem, load_fh_offsets + %if %3 == 1 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + %endif + movu m0, [srcq+r0*2] + movu m1, [srcq+rX*2] + movu m2, [srcq+r4*2] + movu m3, [srcq+r5*2] + mov r0, [stk+16] + mov rX, [stk+20] + mov r4, [stk+24] + mov r5, [stk+28] + pmaddwd m0, [stk+%1+0x00] + pmaddwd m1, [stk+%1+0x10] + pmaddwd m2, [stk+%1+0x20] + pmaddwd m3, [stk+%1+0x30] + phaddd m0, m1 + phaddd m2, m3 + movu m4, [srcq+r0*2] + movu m5, [srcq+rX*2] + movu m6, [srcq+r4*2] + movu m7, [srcq+r5*2] + add srcq, ssq + pmaddwd m4, [stk+%1+0xa0] + pmaddwd m5, [stk+%1+0xb0] + pmaddwd m6, [stk+%1+0xc0] + pmaddwd m7, [stk+%1+0xd0] + phaddd m4, m5 + phaddd m6, m7 + phaddd m0, m2 + phaddd m4, m6 + paddd m0, hround + paddd m4, hround + psrad m0, m12 + psrad m4, m12 + packssdw m0, m4 + %if %2 != 0 + mova [stk+%2], m0 + %endif + %endmacro +%endif + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isput 1 + %assign isprep 0 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_16bpc, 2, 15, 16, 0x1c0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal put_8tap_scaled_16bpc, 2, 14, 16, 0x1c0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_16bpc, 0, 7, 8, 0x200, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal put_8tap_scaled_16bpc, 0, 7, 8, -0x200-0x30, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %endif + %xdefine base_reg r12 +%else ; prep + %assign isput 0 + %assign isprep 1 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_16bpc, 2, 15, 16, 0x1c0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %xdefine tmp_stridem r14q + %else +cglobal prep_8tap_scaled_16bpc, 2, 14, 16, 0x1c0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %define tmp_stridem qword [stk+0x138] + %endif + %xdefine base_reg r11 + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_16bpc, 0, 7, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal prep_8tap_scaled_16bpc, 0, 6, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %define tmp_stridem dword [stk+0x138] + %endif +%endif +%if ARCH_X86_32 + mov [esp+0x1f0], t0d + mov [esp+0x1f4], t1d + %if isput && required_stack_alignment > STACK_ALIGNMENT + mov dstd, dstm + mov dsd, dsm + mov srcd, srcm + mov ssd, ssm + mov hd, hm + mov r4, mxm + %define r0m [esp+0x200] + %define dsm [esp+0x204] + %define dsmp dsm + %define r1m dsm + %define r2m [esp+0x208] + %define ssm [esp+0x20c] + %define r3m ssm + %define hm [esp+0x210] + %define mxm [esp+0x214] + mov r0m, dstd + mov dsm, dsd + mov r2m, srcd + mov ssm, ssd + mov hm, hd + mov r0, mym + mov r1, dxm + mov r2, dym + %define mym [esp+0x218] + %define dxm [esp+0x21c] + %define dym [esp+0x220] + mov mxm, r4 + mov mym, r0 + mov dxm, r1 + mov dym, r2 + tzcnt wd, wm + %endif + %if isput + mov r3, pxmaxm + %define pxmaxm r3 + %else + mov r2, pxmaxm + %endif + %if isprep && required_stack_alignment > STACK_ALIGNMENT + %xdefine base_reg r5 + %else + %xdefine base_reg r6 + %endif +%endif + LEA base_reg, %1_8tap_scaled_16bpc_ssse3 +%xdefine base base_reg-%1_8tap_scaled_16bpc_ssse3 +%if ARCH_X86_64 || isprep || required_stack_alignment <= STACK_ALIGNMENT + tzcnt wd, wm +%endif +%if ARCH_X86_64 + %if isput + mov r7d, pxmaxm + %endif +%else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 +%endif + movd m8, dxm + movd m14, mxm +%if isput + movd m15, pxmaxm +%endif + pshufd m8, m8, q0000 + pshufd m14, m14, q0000 +%if isput + pshuflw m15, m15, q0000 + punpcklqdq m15, m15 +%endif +%if isprep + %if UNIX64 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 + %endif + %if ARCH_X86_64 + mov r6d, pxmaxm + %endif +%endif +%if ARCH_X86_64 + mov dyd, dym +%endif +%if isput + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %elif ARCH_X86_64 + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %else + %endif + %if ARCH_X86_64 + %if required_stack_alignment > STACK_ALIGNMENT + %define dsm [rsp+0x138] + %define rX r1 + %define rXd r1d + %else + %define dsm dsq + %define rX r14 + %define rXd r14d + %endif + %else + %define rX r1 + %endif +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %elif ARCH_X86_64 + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %xdefine hm r7m + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %if ARCH_X86_64 + %define rX r14 + %define rXd r14d + %else + %define rX r3 + %endif +%endif +%if ARCH_X86_64 + shr r7d, 11 + mova m10, [base+pd_0x3ff] + movddup m11, [base+s_8tap_h_rnd+r7*8] + movd m12, [base+s_8tap_h_sh+r7*4] + %if isput + movddup m13, [base+put_s_8tap_v_rnd+r7*8] + movd m7, [base+put_s_8tap_v_sh+r7*4] + %define pxmaxm [rsp] + mova pxmaxm, m15 + punpcklqdq m12, m7 + %endif + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q +%else + %define m10 [base+pd_0x3ff] + %define m11 [esp+0x00] + %define m12 [esp+0x10] + shr r3, 11 + movddup m1, [base+s_8tap_h_rnd+r3*8] + movd m2, [base+s_8tap_h_sh+r3*4] + %if isput + %define m13 [esp+0x20] + %define pxmaxm [esp+0x30] + %define stk esp+0x40 + movddup m5, [base+put_s_8tap_v_rnd+r3*8] + movd m6, [base+put_s_8tap_v_sh+r3*4] + mova pxmaxm, m15 + punpcklqdq m2, m6 + mova m13, m5 + %else + %define m13 [base+pd_m524256] + %endif + mov ssd, ssm + mova m11, m1 + mova m12, m2 + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + mov r1, [esp+0x1f4] + lea r0, [ssd*3] + movzx r2, r1b + shr r1, 16 + cmp dword hm, 6 + cmovs r1, r2 + mov [esp+0x1f4], r1 + %if isprep + mov r1, r1m + %endif + mov r2, r2m + sub srcq, r0 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define ss3q r0 + %define myd r4 + %define dyd dword dym + %define hd dword hm +%endif + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_ssse3_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + movzx r4, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r4 + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6, m7 + REPX {pmaddwd x, m15}, m4, m5, m6, m7 + phaddd m0, m1 + phaddd m2, m3 + phaddd m4, m5 + phaddd m6, m7 + REPX {paddd x, m11}, m0, m2, m4, m6 + REPX {psrad x, m12}, m0, m2, m4, m6 + packssdw m0, m2 ; 0 1 2 3 + packssdw m4, m6 ; 4 5 6 7 + SWAP m1, m4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m2, m3 + movu m1, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m14}, m1, m7, m6, m3 + REPX {pmaddwd x, m15}, m1, m7, m6, m3 + phaddd m1, m7 + phaddd m6, m3 + REPX {paddd x, m11}, m0, m2, m1, m6 + REPX {psrad x, m12}, m0, m2, m1, m6 + packssdw m0, m2 + packssdw m1, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + %endif + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mov myd, mym + mov r0, r0m + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif +.w2_loop: + and myd, 0x3ff + %if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m10, r6q + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pmaddwd m5, m3, m7 + pmaddwd m6, m0, m8 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddwd m7, m2, m9 + pmaddwd m8, m4, m10 + paddd m5, m6 + paddd m7, m8 + %else + mov r1, [esp+0x1f4] + xor r3, r3 + mov r5, myd + shr r5, 6 + lea r1, [r1+r5] + mov r5, 64 << 24 + cmovnz r3, [base+subpel_filters+r1*8+4] + cmovnz r5, [base+subpel_filters+r1*8+0] + movd m6, r3 + movd m7, r5 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m5, m7, q0000 + pshufd m6, m7, q1111 + pmaddwd m3, m5 + pmaddwd m0, m6 + pshufd m5, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m2, m5 + pmaddwd m4, m7 + paddd m3, m0 + paddd m2, m4 + SWAP m5, m3 + SWAP m7, m2 + %define m8 m3 + %endif + paddd m5, m13 + pshufd m6, m12, q1032 + pxor m8, m8 + paddd m5, m7 + psrad m5, m6 + packssdw m5, m5 + pmaxsw m5, m8 + pminsw m5, pxmaxm + movd [dstq], m5 + add dstq, dsmp + dec hd + jz .ret + %if ARCH_X86_64 + add myd, dyd + %else + add myd, dym + %endif + test myd, ~0x3ff + %if ARCH_X86_32 + SWAP m3, m5 + SWAP m2, m7 + mova m3, [stk+0x20] + mova m0, [stk+0x30] + mova m2, [stk+0x40] + mova m4, [stk+0x50] + %endif + jz .w2_loop + %if ARCH_X86_32 + mov r3, r3m + %endif + movu m5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps m3, m0, q1032 ; 01 12 + shufps m0, m2, q1032 ; 23 34 + shufps m2, m4, q1032 ; 45 56 + pshufb m5, m14 + pmaddwd m5, m15 + phaddd m5, m5 + paddd m5, m11 + psrad m5, m12 + packssdw m5, m5 + palignr m4, m5, m1, 12 + punpcklqdq m1, m4, m4 ; 6 7 6 7 + punpcklwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif + jmp .w2_loop +.w2_skip_line: + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m3, m0 ; 01 12 + mova m0, m2 ; 23 34 + pshufb m5, m14 + pshufb m6, m14 + pmaddwd m5, m15 + pmaddwd m6, m15 + phaddd m5, m6 + paddd m5, m11 + psrad m5, m12 + packssdw m5, m5 ; 6 7 6 7 + punpckhqdq m1, m5 ; 4 5 6 7 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif + jmp .w2_loop +%endif +INIT_XMM ssse3 +.w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + movzx r4, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%else + %define m9 [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd rX, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + movifprep r3, r3m + SWAP m4, m7 + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x20], m13 + mova [stk+0x30], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + movu m1, [srcq+r4 ] + movu m3, [srcq+r6 ] + movu m2, [srcq+r11 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m13}, m7, m9, m8, m10 + REPX {pshufb x, m14}, m1, m2, m3, m4 + REPX {pmaddwd x, m15}, m1, m2, m3, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m4, [srcq+ss3q ] + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 + packssdw m8, m10 ; 2 3 + movu m0, [srcq+r4 ] + movu m9, [srcq+r6 ] + movu m10, [srcq+r11 ] + movu m11, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m1, m2, m3, m4 + REPX {pmaddwd x, m13}, m1, m2, m3, m4 + REPX {pshufb x, m14}, m0, m9, m10, m11 + REPX {pmaddwd x, m15}, m0, m9, m10, m11 + phaddd m1, m0 + phaddd m2, m9 + phaddd m3, m10 + phaddd m4, m11 + REPX {paddd x, m5}, m1, m2, m3, m4 + REPX {psrad x, xm6}, m1, m2, m3, m4 + packssdw m1, m2 ; 4 5 + packssdw m3, m4 ; 6 7 + SWAP m9, m1 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + pshufd m10, m3, q1032 ; 7 _ + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + punpcklwd m3, m10 ; 67 + mova [rsp+0x40], m7 + mova [rsp+0x50], m8 + mova [rsp+0x60], m9 +%else + mova [stk+0x00], m12 + mova [stk+0x10], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x40 ; 0 1 + MC_4TAP_SCALED_H 0x50 ; 2 3 + MC_4TAP_SCALED_H 0x60 ; 4 5 + MC_4TAP_SCALED_H 0x70 ; 6 7 + mova m4, [stk+0x40] + mova m5, [stk+0x50] + mova m6, [stk+0x60] + mova m7, [stk+0x70] + mov [stk+0xc0], r4 + shufps m1, m4, m5, q1032 ; 1 2 + shufps m2, m5, m6, q1032 ; 3 4 + shufps m3, m6, m7, q1032 ; 5 6 + pshufd m0, m7, q1032 ; 7 _ + mova [stk+0xb0], m0 + punpcklwd m0, m4, m1 ; 01 + punpckhwd m4, m1 ; 12 + punpcklwd m1, m5, m2 ; 23 + punpckhwd m5, m2 ; 34 + punpcklwd m2, m6, m3 ; 45 + punpckhwd m6, m3 ; 56 + punpcklwd m3, m7, [stk+0xb0] ; 67 + mov myd, mym + mov r0, r0m + mova [stk+0x40], m0 ; 01 + mova [stk+0x50], m1 ; 23 + mova [stk+0x60], m2 ; 45 + mova [stk+0x70], m3 ; 67 + mova [stk+0x80], m4 ; 12 + mova [stk+0x90], m5 ; 34 + mova [stk+0xa0], m6 ; 56 + %define m12 [stk+0x00] + %define m14 [stk+0x10] + %define m13 [stk+0x20] + %define m15 [stk+0x30] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%endif +.w4_loop: + and myd, 0x3ff +%if ARCH_X86_64 + mov r11d, 64 << 24 + mov r13d, myd + shr r13d, 6 + lea r13d, [t1+r13] + cmovnz r11q, [base+subpel_filters+r13*8] + movq m9, r11q + punpcklbw m9, m9 + psraw m9, 8 + pshufd m7, m9, q0000 + pshufd m8, m9, q1111 + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pshufd m7, m9, q2222 + pshufd m9, m9, q3333 + pmaddwd m6, m2, m7 + pmaddwd m8, m3, m9 + %if isput + movd m9, [rsp+0x28] + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif + paddd m4, m5 + paddd m6, m8 + paddd m4, m6 + paddd m4, vrnd_mem +%else + mov mym, myd + mov r5, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m0, m4 + pmaddwd m1, m5 + pmaddwd m2, m6 + pmaddwd m3, m7 + %if isput + movd m4, [esp+0x18] + %endif + paddd m0, m1 + paddd m2, m3 + paddd m0, vrnd_mem + paddd m0, m2 + SWAP m4, m0 + %define m9 m0 +%endif +%if isput + pxor m5, m5 + psrad m4, m9 + packssdw m4, m4 + pmaxsw m4, m5 + pminsw m4, pxmaxm + movq [dstq], m4 + add dstq, dsmp +%else + psrad m4, 6 + packssdw m4, m4 + movq [tmpq], m4 + add tmpq, 8 +%endif + dec hd + jz .ret +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + mova m8, [rsp+0x10] + movd m9, [rsp+0x20] + movu m4, [srcq] + movu m5, [srcq+r4] + test myd, 0x400 + jz .w4_skip_line + mova m0, [rsp+0x40] + mova [rsp+0x40], m1 + mova m1, [rsp+0x50] + mova [rsp+0x50], m2 + mova m2, [rsp+0x60] + mova [rsp+0x60], m3 + pshufb m4, m12 + pshufb m5, m14 + pmaddwd m4, m13 + pmaddwd m5, m15 + phaddd m4, m5 + paddd m4, m8 + psrad m4, m9 + packssdw m4, m4 + punpcklwd m3, m10, m4 + mova m10, m4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu m6, [srcq+ssq*1] + movu m7, [srcq+r6] + mova m0, [rsp+0x50] + mova m11, [rsp+0x60] + pshufb m4, m12 + pshufb m6, m12 + pshufb m5, m14 + pshufb m7, m14 + pmaddwd m4, m13 + pmaddwd m6, m13 + pmaddwd m5, m15 + pmaddwd m7, m15 + mova [rsp+0x40], m0 + mova [rsp+0x50], m11 + phaddd m4, m5 + phaddd m6, m7 + paddd m4, m8 + paddd m6, m8 + psrad m4, m9 + psrad m6, m9 + packssdw m4, m6 + punpcklwd m9, m10, m4 + mova [rsp+0x60], m9 + pshufd m10, m4, q1032 + mova m0, m1 + mova m1, m2 + mova m2, m3 + punpcklwd m3, m4, m10 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +%else + SWAP m0, m4 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + jnz .w4_next_line + mova m0, [stk+0x40] + mova m1, [stk+0x50] + mova m2, [stk+0x60] + mova m3, [stk+0x70] + jmp .w4_loop +.w4_next_line: + mov r5, [stk+0xc0] + movu m4, [srcq] + movu m5, [r5] + test myd, 0x400 + jz .w4_skip_line + add [stk+0xc0], ssq + mova m0, [stk+0x80] + mova m3, [stk+0x50] + mova [stk+0x40], m0 + mova [stk+0x80], m3 + mova m1, [stk+0x90] + mova m6, [stk+0x60] + mova [stk+0x50], m1 + mova [stk+0x90], m6 + mova m2, [stk+0xa0] + mova m7, [stk+0x70] + mova [stk+0x60], m2 + mova [stk+0xa0], m7 + pshufb m4, m12 + pshufb m5, m14 + pmaddwd m4, m13 + pmaddwd m5, m15 + phaddd m4, m5 + paddd m4, hrnd_mem + psrad m4, hsh_mem + packssdw m4, m4 + punpcklwd m3, [stk+0xb0], m4 + mova [stk+0xb0], m4 + mova [stk+0x70], m3 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu m6, [srcq+ssq*1] + movu m7, [r5 +ssq*1] + lea r5, [r5 +ssq*2] + mov [stk+0xc0], r5 + mova m0, [stk+0x50] + mova m1, [stk+0x60] + mova m2, [stk+0x70] + mova m3, [stk+0x90] + pshufb m4, m12 + pshufb m6, m12 + pshufb m5, m14 + pshufb m7, m14 + pmaddwd m4, m13 + pmaddwd m6, m13 + pmaddwd m5, m15 + pmaddwd m7, m15 + mova [stk+0x40], m0 + mova [stk+0x50], m1 + mova [stk+0x60], m2 + mova [stk+0x80], m3 + phaddd m4, m5 + phaddd m6, m7 + mova m5, [stk+0xa0] + mova m7, [stk+0xb0] + paddd m4, hrnd_mem + paddd m6, hrnd_mem + psrad m4, hsh_mem + psrad m6, hsh_mem + packssdw m4, m6 + punpcklwd m7, m4 + pshufd m6, m4, q1032 + mova [stk+0x90], m5 + mova [stk+0xa0], m7 + mova [stk+0xb0], m6 + punpcklwd m3, m4, m6 + mova [stk+0x70], m3 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +%endif +INIT_XMM ssse3 +%if ARCH_X86_64 + %define stk rsp+0x20 +%endif +.w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.w_start: +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + %define hround m11 + shr t0d, 16 + movd m15, t0d + %if isprep + mova m13, [base+pd_m524256] + %endif +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq ssm + %endif + mov r4, [esp+0x1f0] + shr r4, 16 + movd m15, r4 + mov r0, r0m + mov myd, mym +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + mov r5, hm + mov [stk+0x0f4], myd + mov [stk+0x134], r5 +%endif + jmp .hloop +.hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov myd, [stk+0x0f4] + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov mym, myd + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + mov myd, mym + mov dyd, dym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m5, m11, q0000 + pshufd m7, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m4, m5, m0 + pmaddwd m5, m5, m1 + pmaddwd m6, m7, m2 + pmaddwd m7, m7, m3 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m10 + pmaddwd m7, [stk+0xa0], m10 + pmaddwd m8, [stk+0xb0], m11 + pmaddwd m9, [stk+0xc0], m11 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov myd, mym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.vloop: + mov r0, r0m + mov r5, [esp+0x1f4] + and myd, 0x3ff + mov mym, myd + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [stk+0x140], myd + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + jz .skip_line + mova m14, [base+unpckw] + movu m8, [srcq+r10*2] + movu m9, [srcq+r11*2] + movu m10, [srcq+r13*2] + movu m11, [srcq+ rX*2] + movu m4, [srcq+ r4*2] + movu m5, [srcq+ r6*2] + movu m6, [srcq+ r7*2] + movu m7, [srcq+ r9*2] + add srcq, ssq + mov myd, [stk+0x140] + mov dyd, dym + pshufd m15, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m15 ; 3a 2a + pshufb m3, m15 ; 3b 2b + pmaddwd m8, [stk+0x50] + pmaddwd m9, [stk+0x60] + pmaddwd m10, [stk+0x70] + pmaddwd m11, [stk+0x80] + pmaddwd m4, [stk+0x10] + pmaddwd m5, [stk+0x20] + pmaddwd m6, [stk+0x30] + pmaddwd m7, [stk+0x40] + phaddd m8, m9 + phaddd m10, m11 + mova m11, hround + phaddd m4, m5 + phaddd m6, m7 + phaddd m8, m10 + phaddd m4, m6 + paddd m4, m11 + paddd m8, m11 + psrad m4, m12 + psrad m8, m12 + packssdw m4, m8 + pshufb m5, [stk+0x90], m14 ; 4a 5a + pshufb m6, [stk+0xa0], m14 ; 4b 5b + pshufb m7, [stk+0xb0], m15 ; 7a 6a + pshufb m8, [stk+0xc0], m15 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + punpckhwd m5, m7 ; 56a + punpckhwd m6, m8 ; 56b + punpcklwd m7, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m8, m4 ; 78b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m8 + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 10, 11 + MC_8TAP_SCALED_H 8, 5, 6, 7, 9, 0, 10, 11 + mov myd, [stk+0x140] + mov dyd, dym + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [stk+0x90] ; 23a + mova m3, [stk+0xa0] ; 23b + mova m5, [stk+0xb0] ; 45a + mova m6, [stk+0xc0] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m4 +%else + mov r0m, r0 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + mov mym, myd + jnz .next_line + mova m0, [stk+0x20] + mova m1, [stk+0x30] + mova m2, [stk+0x40] + mova m3, [stk+0x50] + jmp .vloop +.next_line: + test myd, 0x400 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + jz .skip_line + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + mova m7, [base+unpckw] + pshufd m4, m7, q1032 + pshufb m0, [stk+0x20], m7 ; 0a 1a + pshufb m1, [stk+0x30], m7 ; 0b 1b + pshufb m2, [stk+0x40], m4 ; 3a 2a + pshufb m3, [stk+0x50], m4 ; 3b 2b + pshufb m5, [stk+0x60], m7 ; 4a 5a + pshufb m6, [stk+0x70], m7 ; 4b 5b + pshufb m7, [stk+0x80], m4 ; 7a 6a + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + punpckhwd m5, m7 ; 56a + mova [stk+0x60], m5 + pshufb m5, [stk+0x90], m4 ; 7b 6b + punpcklwd m7, [stk+0xe0] ; 78a + punpckhwd m6, m5 ; 56b + mova [stk+0x70], m6 + movq m6, [stk+0xe8] + mova [stk+0x80], m7 + punpcklwd m5, m6 + mov myd, mym + mova [stk+0x90], m5 + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + MC_8TAP_SCALED_H 0xa0, 0 ; 9 + mova m7, [stk+0xe0] + mova m2, [stk+0x60] ; 23a + mova m3, [stk+0x70] ; 23b + mova m4, [stk+0x80] ; 45a + mova m5, [stk+0x90] ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova m0, [stk+0x40] ; 01a + mova m1, [stk+0x50] ; 01b + mov myd, mym + mova [stk+0x40], m2 + mova [stk+0x50], m3 + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova [stk+0x20], m0 + mova [stk+0x30], m1 +%endif + jmp .vloop +INIT_XMM ssse3 +.dy1: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy1_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy1_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + %define m11 [esp+0x00] + %define m12 [esp+0x10] + %define m13 [esp+0x20] + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 + mov r1, r1m + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + mov [stk+0x20], r3 + mov r3, r3m + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6 + REPX {pmaddwd x, m15}, m4, m5, m6 + phaddd m0, m1 + phaddd m2, m3 + phaddd m4, m5 + phaddd m6, m6 + REPX {paddd x, m11}, m0, m2, m4, m6 + REPX {psrad x, m12}, m0, m2, m4, m6 + packssdw m0, m2 ; 0 1 2 3 + packssdw m4, m6 ; 4 5 6 + SWAP m1, m4 + movq m10, r4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m2, m3 + movu m1, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + REPX {pshufb x, m14}, m1, m7, m6 + REPX {pmaddwd x, m15}, m1, m7, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + phaddd m1, m7 + phaddd m6, m6 + REPX {paddd x, m11}, m0, m2, m1, m6 + REPX {psrad x, m12}, m0, m2, m1, m6 + packssdw m0, m2 + packssdw m1, m6 + %define m8 m6 + %define m9 m4 + %define m10 m5 + movd m10, r4 + movd m9, [stk+0x20] + punpckldq m10, m9 + %endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + %if ARCH_X86_32 + mova [stk+0x50], m7 + mova [stk+0x60], m8 + mova [stk+0x70], m9 + mova [stk+0x80], m10 + %define m7 [stk+0x50] + %define m8 [stk+0x60] + %define m9 [stk+0x70] + %define m10 [stk+0x80] + %endif + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m4, m1, q2121 ; 5 6 5 6 + punpcklwd m2, m1, m4 ; 45 56 + %if ARCH_X86_32 + mov r0, r0m + %endif +.dy1_w2_loop: + movu m1, [srcq+ssq*0] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m3, m7 + mova m3, m0 + pmaddwd m0, m8 + pshufb m1, m14 + pshufb m6, m14 + pmaddwd m1, m15 + pmaddwd m6, m15 + phaddd m1, m6 + paddd m1, m11 + psrad m1, m12 + packssdw m1, m1 + paddd m5, m0 + mova m0, m2 + pmaddwd m2, m9 + paddd m5, m2 + palignr m2, m1, m4, 12 + punpcklwd m2, m1 ; 67 78 + pmaddwd m4, m2, m10 + paddd m5, m13 + paddd m5, m4 + pxor m6, m6 + mova m4, m1 + pshufd m1, m12, q1032 + psrad m5, m1 + packssdw m5, m5 + pmaxsw m5, m6 + pminsw m5, pxmaxm + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q1032 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy1_w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %define vrnd_mem [rsp+0x30] + %define stk rsp+0x40 + %else + %define vrnd_mem [base+pd_m524256] + %define stk rsp+0x30 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m9 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd rX, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + SWAP m4, m7 + %if isprep + mov r3, r3m + %endif + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x40], m13 + mova [stk+0x50], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + movu m1, [srcq+r4 ] + movu m3, [srcq+r6 ] + movu m2, [srcq+r11 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m13}, m7, m9, m8, m10 + REPX {pshufb x, m14}, m1, m3, m2, m4 + REPX {pmaddwd x, m15}, m1, m3, m2, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 + packssdw m8, m10 ; 2 3 + movu m0, [srcq+r4 ] + movu m9, [srcq+r6 ] + movu m10, [srcq+r11 ] + add srcq, ss3q + REPX {pshufb x, m12}, m1, m2, m3 + REPX {pmaddwd x, m13}, m1, m2, m3 + REPX {pshufb x, m14}, m0, m9, m10 + REPX {pmaddwd x, m15}, m0, m9, m10 + phaddd m1, m0 + phaddd m2, m9 + phaddd m3, m10 + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + REPX {paddd x, m5}, m1, m2, m3 + REPX {psrad x, xm6}, m1, m2, m3 + packssdw m1, m2 ; 4 5 + packssdw m3, m3 ; 6 6 + SWAP m9, m1 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + movq m10, r13 + mova [stk+0x00], m1 + mova [stk+0x10], m8 + mova [stk+0x20], m2 + mova [stk+0x30], m9 + mova [stk+0x40], m3 + %define hrnd_mem [rsp+0x10] + %define hsh_mem [rsp+0x20] + %define vsh_mem [rsp+0x28] + %if isput + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%else + mova [stk+0x20], m12 + mova [stk+0x30], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x60 ; 0 1 + MC_4TAP_SCALED_H 0x70 ; 2 3 + MC_4TAP_SCALED_H 0x80 ; 4 5 + movu m7, [srcq] + movu m2, [r4] + add srcq, ssq + add r4, ssq + mov [stk+0xb0], r4 + pshufb m7, m12 + pshufb m2, m14 + pmaddwd m7, m13 + pmaddwd m2, m15 + phaddd m7, m2 + paddd m7, [esp+0x00] + psrad m7, [esp+0x10] + packssdw m7, m7 ; 6 6 + mova m4, [stk+0x60] + mova m5, [stk+0x70] + mova m6, [stk+0x80] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + shufps m1, m4, m5, q1032 ; 1 2 + shufps m2, m5, m6, q1032 ; 3 4 + shufps m3, m6, m7, q1032 ; 5 6 + mova [stk+0xa0], m7 + punpcklwd m0, m4, m1 ; 01 + punpckhwd m4, m1 ; 12 + punpcklwd m1, m5, m2 ; 23 + punpckhwd m5, m2 ; 34 + punpcklwd m2, m6, m3 ; 45 + punpckhwd m6, m3 ; 56 + movd m7, r4 + movd m3, r5 + mov r0, r0m + %if isput + mov r1, r1m + %endif + mov r4, [stk+0xb0] + mova [stk+0xc0], m4 ; 12 + mova [stk+0x60], m1 ; 23 + mova [stk+0x70], m2 ; 45 + mova [stk+0x80], m5 ; 34 + mova [stk+0x90], m6 ; 56 + %define m12 [stk+0x20] + %define m14 [stk+0x30] + %define m13 [stk+0x40] + %define m15 [stk+0x50] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %define vsh_mem [esp+0x18] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif + %define m10 m7 + punpckldq m10, m3 +%endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m3, m10, q0000 + pshufd m4, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_32 + %xdefine m8 m3 + %xdefine m9 m6 + %xdefine m11 m5 + %xdefine m6 m4 + mova [stk+0x100], m3 + mova [stk+0x110], m4 + mova [stk+0x120], m5 + mova [stk+0x130], m10 + %define m3 [stk+0x100] + %define m4 [stk+0x110] + %define m5 [stk+0x120] + %define m10 [stk+0x130] + mova m7, [stk+0xc0] + mova m8, [stk+0x80] +%endif +.dy1_w4_loop: + movu m11, [srcq+ssq*0] + movu m6, [srcq+ssq*1] + pmaddwd m0, m3 + pmaddwd m7, m3 + pmaddwd m1, m4 + pmaddwd m8, m4 + pmaddwd m2, m5 + pmaddwd m9, m5 + paddd m1, m0 + paddd m8, m7 +%if ARCH_X86_64 + movu m0, [srcq+r4] + movu m7, [srcq+r6] +%else + movu m0, [r4+ssq*0] + movu m7, [r4+ssq*1] + lea r4, [r4+ssq*2] +%endif + lea srcq, [srcq+ssq*2] + paddd m1, m2 + paddd m8, m9 + pshufb m11, m12 + pshufb m6, m12 + pmaddwd m11, m13 + pmaddwd m6, m13 + pshufb m0, m14 + pshufb m7, m14 + pmaddwd m0, m15 + pmaddwd m7, m15 + phaddd m11, m0 + phaddd m6, m7 + paddd m11, hrnd_mem + paddd m6, hrnd_mem + psrad m11, hsh_mem + psrad m6, hsh_mem + packssdw m11, m6 ; 7 8 +%if ARCH_X86_64 + shufps m9, [stk+0x40], m11, q1032 ; 6 7 + mova m0, [stk+0x00] + mova [stk+0x40], m11 +%else + shufps m9, [stk+0xa0], m11, q1032 ; 6 7 + mova m0, [stk+0x60] + mova [stk+0xa0], m11 +%endif + punpcklwd m2, m9, m11 ; 67 + punpckhwd m9, m11 ; 78 + pmaddwd m6, m2, m10 + pmaddwd m7, m9, m10 +%if isput + movd m11, vsh_mem +%endif + paddd m1, vrnd_mem + paddd m8, vrnd_mem + paddd m1, m6 + paddd m8, m7 +%if ARCH_X86_64 + mova m7, [stk+0x10] +%else + mova m7, [stk+0x80] +%endif +%if isput + psrad m1, m11 + psrad m8, m11 +%else + psrad m1, 6 + psrad m8, 6 +%endif + packssdw m1, m8 +%if ARCH_X86_64 + mova m8, [stk+0x30] +%else + mova m8, [stk+0x90] +%endif +%if isput + pxor m6, m6 + pmaxsw m1, m6 + pminsw m1, pxmaxm + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m1 + add tmpq, 16 +%endif +%if ARCH_X86_64 + mova m1, [stk+0x20] + mova [stk+0x10], m8 + mova [stk+0x00], m1 + mova [stk+0x20], m2 + mova [stk+0x30], m9 +%else + mova m1, [stk+0x70] + mova [stk+0x80], m8 + mova [stk+0x60], m1 + mova [stk+0x70], m2 + mova [stk+0x90], m9 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET ; why not jz .ret? +INIT_XMM ssse3 +.dy1_w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %define hround m11 + %if isput + mova [rsp+0x30], m13 + %else + mova m13, [base+pd_m524256] + %endif + shr t0d, 16 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + SWAP m3, m5 +%endif + punpcklbw m3, m3 + psraw m3, 8 + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 +%if ARCH_X86_64 + mova [stk+0x140], m0 + mova [stk+0x150], m1 + mova [stk+0x160], m2 + mova [stk+0x170], m3 + %if UNIX64 + mov hm, hd + %endif +%else + mova [stk+0x180], m0 + mova [stk+0x190], m1 + mova [stk+0x1a0], m2 + mova [stk+0x1b0], m3 + SWAP m5, m3 + mov r5, hm + mov [stk+0x134], r5 +%endif + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy1_hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova m10, [stk+0x140] + mova m11, [stk+0x150] + mova m14, [stk+0x160] + mova m15, [stk+0x170] + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] + %define shift [rsp+0x20] + %if isput + %define vround [rsp+0x30] + %else + %define vround [base+pd_m524256] + %endif +.dy1_vloop: + pmaddwd m4, m0, m10 + pmaddwd m5, m1, m10 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m11 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m14 + pmaddwd m7, [stk+0xa0], m14 + pmaddwd m8, [stk+0xb0], m15 + pmaddwd m9, [stk+0xc0], m15 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov r0, r0m + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.dy1_vloop: + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep +%if ARCH_X86_64 + movu m8, [srcq+r10*2] + movu m9, [srcq+r11*2] + movu m12, [srcq+r13*2] + movu m13, [srcq+ rX*2] + movu m4, [srcq+ r4*2] + movu m5, [srcq+ r6*2] + movu m6, [srcq+ r7*2] + movu m7, [srcq+ r9*2] + add srcq, ssq + pmaddwd m8, [stk+0x50] + pmaddwd m9, [stk+0x60] + pmaddwd m12, [stk+0x70] + pmaddwd m13, [stk+0x80] + pmaddwd m4, [stk+0x10] + pmaddwd m5, [stk+0x20] + pmaddwd m6, [stk+0x30] + pmaddwd m7, [stk+0x40] + phaddd m8, m9 + phaddd m12, m13 + mova m9, [base+unpckw] + mova m13, hround + phaddd m4, m5 + phaddd m6, m7 + phaddd m8, m12 + phaddd m4, m6 + pshufd m5, m9, q1032 + pshufb m0, m9 ; 0a 1a + pshufb m1, m9 ; 0b 1b + pshufb m2, m5 ; 3a 2a + pshufb m3, m5 ; 3b 2b + mova m12, shift + paddd m4, m13 + paddd m8, m13 + psrad m4, m12 + psrad m8, m12 + packssdw m4, m8 + pshufb m6, [stk+0x90], m9 ; 4a 5a + pshufb m7, [stk+0xa0], m9 ; 4b 5b + pshufb m8, [stk+0xb0], m5 ; 7a 6a + pshufb m13, [stk+0xc0], m5 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m6 ; 34a + punpcklwd m3, m7 ; 34b + punpckhwd m6, m8 ; 56a + punpckhwd m7, m13 ; 56b + punpcklwd m8, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m13, m4 ; 78b + mova [stk+0x90], m6 + mova [stk+0xa0], m7 + mova [stk+0xb0], m8 + mova [stk+0xc0], m13 + mova m13, vround +%else + mov r0m, r0 + mov r3, r3m + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + mova m7, [base+unpckw] + pshufd m4, m7, q1032 + pshufb m0, [stk+0x20], m7 ; 0a 1a + pshufb m1, [stk+0x30], m7 ; 0b 1b + pshufb m2, [stk+0x40], m4 ; 3a 2a + pshufb m3, [stk+0x50], m4 ; 3b 2b + pshufb m5, [stk+0x60], m7 ; 4a 5a + pshufb m6, [stk+0x70], m7 ; 4b 5b + pshufb m7, [stk+0x80], m4 ; 7a 6a + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + punpckhwd m5, m7 ; 56a + mova [stk+0x60], m5 + pshufb m5, [stk+0x90], m4 ; 7b 6b + punpcklwd m7, [stk+0xe0] ; 78a + mova m4, [stk+0x180] + punpckhwd m6, m5 ; 56b + mova [stk+0x70], m6 + movq m6, [stk+0xe8] + mova [stk+0x80], m7 + mova m7, [stk+0x1b0] + punpcklwd m5, m6 + mova m6, [stk+0x1a0] + mova [stk+0x90], m5 + mova m5, [stk+0x190] + mov r0, r0m +%endif + jmp .dy1_vloop +INIT_XMM ssse3 +%if ARCH_X86_64 + %define stk rsp+0x20 +%endif +.dy2: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy2_w2: + %if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m13 + %define vrnd_mem [rsp+0x10] + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + %define m11 [esp+0x00] + %define m12 [esp+0x10] + %define vrnd_mem [esp+0x20] + mov r1, r1m + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*2] + movu m2, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*1] + movu m5, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + mov [stk+0x20], r3 + mov r3, r3m + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2 + REPX {pmaddwd x, m15}, m0, m1, m2 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6 + REPX {pmaddwd x, m15}, m4, m5, m6 + phaddd m0, m1 + phaddd m1, m2 + phaddd m4, m5 + phaddd m5, m6 + REPX {paddd x, m11}, m0, m1, m4, m5 + REPX {psrad x, m12}, m0, m1, m4, m5 + packssdw m0, m1 ; 0 2 2 4 + packssdw m4, m5 ; 1 3 3 5 + SWAP m2, m4 + movq m10, r4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m1, m2 + movu m2, [srcq+ssq*1] + movu m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + REPX {pshufb x, m14}, m2, m7, m6 + REPX {pmaddwd x, m15}, m2, m7, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + phaddd m2, m7 + phaddd m7, m6 + REPX {paddd x, m11}, m0, m1, m2, m7 + REPX {psrad x, m12}, m0, m1, m2, m7 + packssdw m0, m1 + packssdw m2, m7 + %define m8 m6 + %define m9 m4 + %define m10 m5 + movd m10, r4 + movd m9, [stk+0x20] + punpckldq m10, m9 + %endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + %if ARCH_X86_32 + mova [stk+0x50], m7 + mova [stk+0x60], m8 + mova [stk+0x70], m9 + mova [stk+0x80], m10 + %xdefine m13 m7 + %define m7 [stk+0x50] + %define m8 [stk+0x60] + %define m9 [stk+0x70] + %define m10 [stk+0x80] + %endif + punpcklwd m1, m0, m2 ; 01 23 + punpckhwd m3, m0, m2 ; 23 45 + %if ARCH_X86_32 + mov r4, r0m + %define dstq r4 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + %endif +.dy2_w2_loop: + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m13, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd m3, m8 + REPX {pshufb x, m14}, m4, m5, m6, m13 + REPX {pmaddwd x, m15}, m4, m5, m6, m13 + phaddd m4, m5 + phaddd m6, m13 + pmaddwd m5, m1, m7 + paddd m4, m11 + paddd m6, m11 + psrad m4, m12 + psrad m6, m12 + packssdw m4, m6 ; 6 7 8 9 + paddd m5, m3 + pshufd m3, m4, q2200 + pshufd m4, m4, q3311 + palignr m3, m0, 12 ; 4 6 6 8 + palignr m4, m2, 12 ; 5 7 7 9 + mova m0, m3 + mova m2, m4 + punpcklwd m1, m3, m4 + punpckhwd m3, m4 + pmaddwd m6, m1, m9 + pmaddwd m4, m3, m10 + paddd m5, vrnd_mem + paddd m6, m4 + paddd m5, m6 + pshufd m4, m12, q1032 + pxor m6, m6 + psrad m5, m4 + packssdw m5, m5 + pmaxsw m5, m6 + pminsw m5, pxmaxm + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q1032 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy2_w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %define vrnd_mem [rsp+0x30] + %define stk rsp+0x40 + %else + %define vrnd_mem [base+pd_m524256] + %define stk rsp+0x30 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m9 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r1, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r3, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + SWAP m4, m7 + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x40], m13 + mova [stk+0x50], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m1, [srcq+ssq*0] + movu m8, [srcq+ssq*2] + movu m9, [srcq+ssq*1] + movu m10, [srcq+ss3q ] + movu m7, [srcq+r4 ] + movu m2, [srcq+r11 ] + movu m3, [srcq+r6 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m1, m9, m8, m10 + REPX {pmaddwd x, m13}, m1, m9, m8, m10 + REPX {pshufb x, m14}, m7, m3, m2, m4 + REPX {pmaddwd x, m15}, m7, m3, m2, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m1, m7 + phaddd m8, m2 + phaddd m9, m3 + phaddd m10, m4 + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + REPX {paddd x, m5}, m1, m9, m8, m10 + REPX {psrad x, xm6}, m1, m9, m8, m10 + packssdw m1, m8 ; 0 2 + packssdw m9, m10 ; 1 3 + movu m0, [srcq+r4 ] + movu m8, [srcq+r6 ] + lea srcq, [srcq+ssq*2] + REPX {pshufb x, m12}, m2, m3 + REPX {pmaddwd x, m13}, m2, m3 + REPX {pshufb x, m14}, m0, m8 + REPX {pmaddwd x, m15}, m0, m8 + phaddd m2, m0 + phaddd m3, m8 + shr myd, 6 + mov r9d, 64 << 24 + lea myd, [t1+myq] + cmovnz r9q, [base+subpel_filters+myq*8] + REPX {paddd x, m5}, m2, m3 + REPX {psrad x, xm6}, m2, m3 + packssdw m2, m3 ; 4 5 + pshufd m3, m2, q1032 ; 5 _ + punpcklwd m0, m1, m9 ; 01 + punpckhwd m1, m9 ; 23 + punpcklwd m2, m3 ; 45 + movq m10, r9 + %define hrnd_mem [rsp+0x10] + %define hsh_mem [rsp+0x20] + %define vsh_mem [rsp+0x28] + %if isput + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%else + mova [stk+0x20], m12 + mova [stk+0x30], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x60 ; 0 1 + MC_4TAP_SCALED_H 0x70 ; 2 3 + MC_4TAP_SCALED_H 0x80 ; 4 5 + mov [stk+0xe0], r4 + mova m3, [base+spel_s_shuf8] + mova m0, [stk+0x60] + mova m1, [stk+0x70] + mova m2, [stk+0x80] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + pshufb m0, m3 ; 01 + pshufb m1, m3 ; 23 + pshufb m2, m3 ; 45 + movd m7, r4 + movd m4, r5 + mov r5, r0m + %if isput + mov r1, r1m + %endif + mov r4, [stk+0xe0] + %define dstq r5 + %define tmpq r5 + %define m12 [stk+0x20] + %define m14 [stk+0x30] + %define m13 [stk+0x40] + %define m15 [stk+0x50] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %define vsh_mem [esp+0x18] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif + %define m10 m7 + punpckldq m10, m4 +%endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m3, m10, q0000 + pshufd m4, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_32 + %xdefine m8 m3 + %xdefine m9 m6 + %xdefine m11 m5 + %xdefine m6 m4 + mova [stk+0x100], m3 + mova [stk+0x110], m4 + mova [stk+0x120], m5 + mova [stk+0x130], m10 + %define m3 [stk+0x100] + %define m4 [stk+0x110] + %define m5 [stk+0x120] + %define m10 [stk+0x130] +%endif +.dy2_w4_loop: + pmaddwd m8, m0, m3 + pmaddwd m9, m1, m3 + mova m0, m2 + pmaddwd m1, m4 + pmaddwd m11, m2, m4 + paddd m8, vrnd_mem + paddd m9, vrnd_mem + pmaddwd m2, m5 + paddd m8, m1 + paddd m9, m11 + paddd m8, m2 + movu m6, [srcq+ssq*0] + movu m1, [srcq+ssq*2] +%if ARCH_X86_64 + movu m11, [srcq+r4 ] + movu m2, [srcq+r11] +%else + movu m11, [r4+ssq*0] + movu m2, [r4+ssq*2] +%endif + pshufb m6, m12 + pshufb m1, m12 + pmaddwd m6, m13 + pmaddwd m1, m13 + pshufb m11, m14 + pshufb m2, m14 + pmaddwd m11, m15 + pmaddwd m2, m15 + phaddd m6, m11 + phaddd m1, m2 + paddd m6, hrnd_mem + paddd m1, hrnd_mem + psrad m6, hsh_mem + psrad m1, hsh_mem + movu m7, [srcq+ssq*1] + movu m11, [srcq+ss3q ] + packssdw m6, m1 ; 6 8 +%if ARCH_X86_64 + movu m2, [srcq+r6 ] + movu m1, [srcq+r13] +%else + movu m2, [r4+ssq*1] + movu m1, [r4+ss3q ] +%endif + pshufb m7, m12 + pshufb m11, m12 + pmaddwd m7, m13 + pmaddwd m11, m13 + pshufb m2, m14 + pshufb m1, m14 + pmaddwd m2, m15 + pmaddwd m1, m15 + phaddd m7, m2 + phaddd m11, m1 + paddd m7, hrnd_mem + paddd m11, hrnd_mem + psrad m7, hsh_mem + psrad m11, hsh_mem + packssdw m7, m11 ; 7 9 +%if ARCH_X86_32 + lea r4, [r4+ssq*4] +%endif + lea srcq, [srcq+ssq*4] + punpcklwd m1, m6, m7 ; 67 + punpckhwd m6, m7 ; 89 + mova m2, m6 + pmaddwd m11, m1, m5 + pmaddwd m7, m1, m10 + pmaddwd m6, m10 + paddd m9, m11 +%if isput + movd m11, vsh_mem +%endif + paddd m8, m7 + paddd m9, m6 +%if isput + psrad m8, m11 + psrad m9, m11 + packssdw m8, m9 + pxor m7, m7 + pmaxsw m8, m7 + pminsw m8, pxmaxm + movq [dstq+dsq*0], m8 + movhps [dstq+dsq*1], m8 + lea dstq, [dstq+dsq*2] +%else + psrad m8, 6 + psrad m9, 6 + packssdw m8, m9 + mova [tmpq], m8 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET ; why not jz .ret? +INIT_XMM ssse3 +.dy2_w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %define hround m11 + %if isput + mova [rsp+0x30], m13 + %else + mova m13, [base+pd_m524256] + %endif + shr t0d, 16 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %xdefine m15 m3 + %if isput + %define dstq r0 + %else + %define tmpq r0 + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + SWAP m3, m5 +%endif + punpcklbw m3, m3 + psraw m3, 8 + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 +%if ARCH_X86_64 + mova [stk+0x140], m0 + mova [stk+0x150], m1 + mova [stk+0x160], m2 + mova [stk+0x170], m3 + %if UNIX64 + mov hm, hd + %endif +%else + mova [stk+0x180], m0 + mova [stk+0x190], m1 + mova [stk+0x1a0], m2 + mova [stk+0x1b0], m3 + SWAP m5, m3 + mov r5, hm + mov [stk+0x134], r5 +%endif + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy2_hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova m10, [stk+0x140] + mova m11, [stk+0x150] + mova m14, [stk+0x160] + mova m15, [stk+0x170] + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] + %define shift [rsp+0x20] + %if isput + %define vround [rsp+0x30] + %else + %define vround [base+pd_m524256] + %endif +.dy2_vloop: + pmaddwd m4, m0, m10 + pmaddwd m5, m1, m10 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m11 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m14 + pmaddwd m7, [stk+0xa0], m14 + pmaddwd m8, [stk+0xb0], m15 + pmaddwd m9, [stk+0xc0], m15 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov r0, r0m + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.dy2_vloop: + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep +%if ARCH_X86_64 + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 0, 1 + mova [stk+0xd0], m4 + MC_8TAP_SCALED_H 8, 5, 6, 7, 9, 4, 0, 1 + mova m4, [stk+0xd0] + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [stk+0x90] ; 23a + mova m3, [stk+0xa0] ; 23b + mova m5, [stk+0xb0] ; 45a + mova m6, [stk+0xc0] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m4 +%else + mov r0m, r0 + mov r3, r3m + MC_8TAP_SCALED_H 0xa0, 0xe0 ; 8 + MC_8TAP_SCALED_H 0xa0, 0 ; 9 + mova m7, [stk+0xe0] + mova m2, [stk+0x60] ; 23a + mova m3, [stk+0x70] ; 23b + mova m4, [stk+0x80] ; 45a + mova m5, [stk+0x90] ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova m0, [stk+0x40] ; 01a + mova m1, [stk+0x50] ; 01b + mova [stk+0x40], m2 + mova [stk+0x50], m3 + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mov r0, r0m +%endif + jmp .dy2_vloop +INIT_XMM ssse3 +.ret: + MC_8TAP_SCALED_RET 0 +%if ARCH_X86_32 && !isprep && required_stack_alignment > STACK_ALIGNMENT + %define r0m [rstk+stack_offset+ 4] + %define r1m [rstk+stack_offset+ 8] + %define r2m [rstk+stack_offset+12] + %define r3m [rstk+stack_offset+16] +%endif +%undef isput +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_16bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, (5*15 << 16) | 5*15 + jmp mangle(private_prefix %+ _%1_8tap_scaled_16bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 8 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN put +FN put_8tap_scaled, sharp, SHARP, SHARP +FN put_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN put_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN put_8tap_scaled, smooth, SMOOTH, SMOOTH +FN put_8tap_scaled, sharp_regular, SHARP, REGULAR +FN put_8tap_scaled, regular_sharp, REGULAR, SHARP +FN put_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN put_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN put_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 7 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN prep +FN prep_8tap_scaled, sharp, SHARP, SHARP +FN prep_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN prep_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN prep_8tap_scaled, smooth, SMOOTH, SMOOTH +FN prep_8tap_scaled, sharp_regular, SHARP, REGULAR +FN prep_8tap_scaled, regular_sharp, REGULAR, SHARP +FN prep_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN prep_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN prep_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%if ARCH_X86_64 +DECLARE_REG_TMP 6 +%else +DECLARE_REG_TMP 2 +%endif + +%if ARCH_X86_64 +; warp8x8t spills one less xmm register than warp8x8 on WIN64, compensate that +; by allocating 16 bytes more stack space so that stack offsets match up. +%if WIN64 && STACK_ALIGNMENT == 16 +%assign stksz 16*14 +%else +%assign stksz 16*13 +%endif +cglobal warp_affine_8x8t_16bpc, 4, 13, 9, stksz, dst, ds, src, ss, delta, \ + mx, tmp, alpha, beta, \ + filter, my, gamma, cnt +%assign stack_size_padded_8x8t stack_size_padded +%else +cglobal warp_affine_8x8t_16bpc, 0, 7, 8, -16*17, alpha, gamma, src, tmp, \ + filter, mx, my +%define m8 [esp+16*13] +%define m9 [esp+16*14] +%define cntd dword [esp+4*63] +%define dstq tmpq +%define dsq 0 +%if STACK_ALIGNMENT < 16 +%define dstm [esp+4*65] +%define dsm [esp+4*66] +%else +%define dstm r0m +%define dsm r1m +%endif +%endif +%define base filterq-$$ + mov t0d, r7m + LEA filterq, $$ + shr t0d, 11 +%if ARCH_X86_64 + movddup m8, [base+warp8x8t_rnd] +%else + movddup m1, [base+warp8x8t_rnd] + mov r1, r1m + add r1, r1 + mova m8, m1 + mov r1m, r1 ; ds *= 2 +%endif + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main + jmp .start +.loop: +%if ARCH_X86_64 + lea dstq, [dstq+dsq*4] +%else + add dstq, dsm + mov dstm, dstq +%endif + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main2 +.start: +%if ARCH_X86_32 + mov dstq, dstm +%endif + paddd m1, m8 + paddd m2, m8 + psrad m1, 15 + psrad m2, 15 + packssdw m1, m2 + mova [dstq+dsq*0], m1 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main3 +%if ARCH_X86_32 + mov dstq, dstm + add dstq, dsm +%endif + paddd m1, m8 + paddd m2, m8 + psrad m1, 15 + psrad m2, 15 + packssdw m1, m2 + mova [dstq+dsq*2], m1 + dec cntd + jg .loop + RET + +%if ARCH_X86_64 +cglobal warp_affine_8x8_16bpc, 4, 13, 10, 16*13, dst, ds, src, ss, delta, \ + mx, tmp, alpha, beta, \ + filter, my, gamma, cnt +ASSERT stack_size_padded == stack_size_padded_8x8t +%else +cglobal warp_affine_8x8_16bpc, 0, 7, 8, -16*17, alpha, gamma, src, tmp, \ + filter, mx, my +%endif + mov t0d, r7m + LEA filterq, $$ + shr t0d, 11 +%if ARCH_X86_64 + movddup m8, [base+warp8x8_rnd2+t0*8] + movd m9, r7m ; pixel_max + pshufb m9, [base+pw_256] +%else + movddup m1, [base+warp8x8_rnd2+t0*8] + movd m2, r7m ; pixel_max + pshufb m2, [base+pw_256] + mova m8, m1 + mova m9, m2 +%endif + call .main + jmp .start +.loop: +%if ARCH_X86_64 + lea dstq, [dstq+dsq*2] +%else + add dstq, dsm + mov dstm, dstq +%endif + call .main2 +.start: +%if ARCH_X86_32 + mov dstq, dstm +%endif + psrad m1, 16 + psrad m2, 16 + packssdw m1, m2 + pmaxsw m1, m6 + pmulhrsw m1, m8 + pminsw m1, m9 + mova [dstq+dsq*0], m1 + call .main3 +%if ARCH_X86_32 + mov dstq, dstm + add dstq, dsm +%endif + psrad m1, 16 + psrad m2, 16 + packssdw m1, m2 + pmaxsw m1, m6 + pmulhrsw m1, m8 + pminsw m1, m9 + mova [dstq+dsq*1], m1 + dec cntd + jg .loop + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov deltaq, r5m + mov mxd, r6m +%endif + movd m0, [base+warp8x8_shift+t0*4] + movddup m7, [base+warp8x8_rnd1+t0*8] + add filterq, mc_warp_filter-$$ +%if ARCH_X86_64 + movsx alphad, word [deltaq+2*0] + movsx betad, word [deltaq+2*1] + movsx gammad, word [deltaq+2*2] + movsx deltad, word [deltaq+2*3] + lea tmpq, [ssq*3] + add mxd, 512+(64<<10) + sub srcq, tmpq ; src -= ss*3 + imul tmpd, alphad, -7 + mov myd, r7m + add betad, tmpd ; beta -= alpha*7 + imul tmpd, gammad, -7 + add myd, 512+(64<<10) + mov cntd, 4 + add deltad, tmpd ; delta -= gamma*7 +%else +%if STACK_ALIGNMENT < 16 + %assign stack_offset stack_offset - gprsize +%endif + mov r3d, r5m ; abcd +%if STACK_ALIGNMENT < 16 + mov r0, r1m ; dst + mov r1, r2m ; ds + mov [esp+gprsize+4*65], r0 + mov [esp+gprsize+4*66], r1 +%endif + movsx alphad, word [r3+2*0] + movsx r2d, word [r3+2*1] + movsx gammad, word [r3+2*2] + movsx r3d, word [r3+2*3] + imul r5d, alphad, -7 + add r2d, r5d ; beta -= alpha*7 + imul r5d, gammad, -7 + mov [esp+gprsize+4*60], r2d + add r3d, r5d ; delta -= gamma*7 + mov [esp+gprsize+4*61], r3d + mov r3d, r4m ; ss + mov srcq, r3m + mov mxd, r6m + mov myd, r7m + mov dword [esp+gprsize+4*63], 4 ; cnt + mov [esp+gprsize+4*62], r3 + lea r3, [r3*3] + add mxd, 512+(64<<10) + add myd, 512+(64<<10) + sub srcq, r3 ; src -= ss*3 +%if STACK_ALIGNMENT < 16 + %assign stack_offset stack_offset + gprsize +%endif +%endif + mova [rsp+gprsize], m0 + pxor m6, m6 + call .h + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 01 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 1], m1 + mova [rsp+gprsize+16* 4], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 12 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 7], m1 + mova [rsp+gprsize+16*10], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 23 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 2], m1 + mova [rsp+gprsize+16* 5], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 34 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 8], m1 + mova [rsp+gprsize+16*11], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 45 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 3], m1 + mova [rsp+gprsize+16* 6], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 56 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 9], m1 + mova [rsp+gprsize+16*12], m5 + mova m5, m0 +.main2: + call .h +%macro WARP_V 6 ; 01l, 23l, 45l, 01h, 23h, 45h + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m4, [filterq+myq*8] ; a + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m2, [filterq+tmpq*8] ; b + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m3, [filterq+myq*8] ; c + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m1, [filterq+tmpq*8] ; d + lea tmpd, [myq+gammaq] + shr myd, 10 + punpcklwd m4, m2 + punpcklwd m3, m1 + punpckldq m2, m4, m3 + punpckhdq m4, m3 + punpcklbw m1, m6, m2 ; a0 a1 b0 b1 c0 c1 d0 d1 << 8 + pmaddwd m1, [rsp+gprsize+16*%1] + punpckhbw m3, m6, m2 ; a2 a3 b2 b3 c2 c3 d2 d3 << 8 + mova m2, [rsp+gprsize+16*%2] + pmaddwd m3, m2 + mova [rsp+gprsize+16*%1], m2 + paddd m1, m3 + punpcklbw m3, m6, m4 ; a4 a5 b4 b5 c4 c5 d4 d5 << 8 + mova m2, [rsp+gprsize+16*%3] + pmaddwd m3, m2 + mova [rsp+gprsize+16*%2], m2 + paddd m1, m3 + punpcklwd m3, m5, m0 ; 67 + punpckhbw m2, m6, m4 ; a6 a7 b6 b7 c6 c7 d6 d7 << 8 + pmaddwd m2, m3 + mova [rsp+gprsize+16*%3], m3 + paddd m1, m2 + movq m4, [filterq+myq*8] ; e + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] ; f + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m2, [filterq+myq*8] ; g +%if ARCH_X86_64 + lea myd, [tmpq+deltaq] ; my += delta +%else + mov myd, [esp+gprsize+4*61] + add myd, tmpd +%endif + shr tmpd, 10 + punpcklwd m4, m3 + movq m3, [filterq+tmpq*8] ; h + punpcklwd m2, m3 + punpckldq m3, m4, m2 + punpckhdq m4, m2 + punpcklbw m2, m6, m3 ; e0 e1 f0 f1 g0 g1 h0 h1 << 8 + pmaddwd m2, [rsp+gprsize+16*%4] + punpckhbw m6, m3 ; e2 e3 f2 f3 g2 g3 h2 h3 << 8 + mova m3, [rsp+gprsize+16*%5] + pmaddwd m6, m3 + mova [rsp+gprsize+16*%4], m3 + pxor m3, m3 + paddd m2, m6 + punpcklbw m3, m4 ; e4 e5 f4 f5 g4 g5 h4 h5 << 8 + mova m6, [rsp+gprsize+16*%6] + pmaddwd m3, m6 + mova [rsp+gprsize+16*%5], m6 + punpckhwd m5, m0 + pxor m6, m6 + paddd m2, m3 + punpckhbw m3, m6, m4 ; e6 e7 f6 f7 g6 g7 h6 h7 << 8 + pmaddwd m3, m5 + mova [rsp+gprsize+16*%6], m5 + mova m5, m0 + paddd m2, m3 +%endmacro + WARP_V 1, 2, 3, 4, 5, 6 + ret +.main3: + call .h + WARP_V 7, 8, 9, 10, 11, 12 + ret +ALIGN function_align +.h: + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + punpcklbw m0, m6, m3 + movu m3, [srcq-6] + pmaddwd m0, m3 ; 0 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m2, m6, m3 + movu m3, [srcq-4] + pmaddwd m2, m3 ; 1 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m0, m2 ; 0 1 + punpcklbw m2, m6, m3 + movu m3, [srcq-2] + pmaddwd m2, m3 ; 2 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m1, m6, m3 + movu m3, [srcq+0] + pmaddwd m1, m3 ; 3 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m2, m1 ; 2 3 + punpcklbw m1, m6, m3 + movu m3, [srcq+2] + pmaddwd m1, m3 ; 4 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + phaddd m0, m2 ; 0 1 2 3 + punpcklbw m2, m6, m3 + movu m3, [srcq+4] + pmaddwd m2, m3 ; 5 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m1, m2 ; 4 5 + punpcklbw m2, m6, m3 + movu m3, [srcq+6] + pmaddwd m2, m3 ; 6 +%if ARCH_X86_64 + lea mxd, [tmpq+betaq] ; mx += beta +%else + mov mxd, [esp+gprsize*2+4*60] + add mxd, tmpd +%endif + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m4, m6, m3 + movu m3, [srcq+8] +%if ARCH_X86_64 + add srcq, ssq +%else + add srcq, [esp+gprsize*2+4*62] +%endif + pmaddwd m3, m4 ; 7 + phaddd m2, m3 ; 6 7 + phaddd m1, m2 ; 4 5 6 7 + paddd m0, m7 + paddd m1, m7 + psrad m0, [rsp+gprsize*2] + psrad m1, [rsp+gprsize*2] + packssdw m0, m1 + ret + +%macro BIDIR_FN 0 + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.ret: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jne .w8_loop + RET +.w16_loop: + call .main + add dstq, strideq +.w16: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + dec hd + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal avg_16bpc, 4, 7, 4, dst, stride, tmp1, tmp2, w, h +%define base r6-avg_ssse3_table + LEA r6, avg_ssse3_table + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + movddup m2, [base+bidir_rnd+t0*8] + movddup m3, [base+bidir_mul+t0*8] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+16*0] + paddsw m0, [tmp2q+16*0] + mova m1, [tmp1q+16*1] + paddsw m1, [tmp2q+16*1] + add tmp1q, 16*2 + add tmp2q, 16*2 + pmaxsw m0, m2 + pmaxsw m1, m2 + psubsw m0, m2 + psubsw m1, m2 + pmulhw m0, m3 + pmulhw m1, m3 + ret + +cglobal w_avg_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, h +%define base r6-w_avg_ssse3_table + LEA r6, w_avg_ssse3_table + tzcnt wd, wm + mov t0d, r6m ; weight + movd m6, r7m ; pixel_max + movddup m5, [base+pd_65538] + movsxd wq, [r6+wq*4] + pshufb m6, [base+pw_256] + add wq, r6 + lea r6d, [t0-16] + shl t0d, 16 + sub t0d, r6d ; 16-weight, weight + paddw m5, m6 + mov r6d, t0d + shl t0d, 2 + test dword r7m, 0x800 + cmovnz r6d, t0d + movifnidn hd, hm + movd m4, r6d + pslld m5, 7 + pxor m7, m7 + pshufd m4, m4, q0000 + BIDIR_FN +ALIGN function_align +.main: + mova m2, [tmp1q+16*0] + mova m0, [tmp2q+16*0] + punpckhwd m3, m0, m2 + punpcklwd m0, m2 + mova m2, [tmp1q+16*1] + mova m1, [tmp2q+16*1] + add tmp1q, 16*2 + add tmp2q, 16*2 + pmaddwd m3, m4 + pmaddwd m0, m4 + paddd m3, m5 + paddd m0, m5 + psrad m3, 8 + psrad m0, 8 + packssdw m0, m3 + punpckhwd m3, m1, m2 + punpcklwd m1, m2 + pmaddwd m3, m4 + pmaddwd m1, m4 + paddd m3, m5 + paddd m1, m5 + psrad m3, 8 + psrad m1, 8 + packssdw m1, m3 + pminsw m0, m6 + pminsw m1, m6 + pmaxsw m0, m7 + pmaxsw m1, m7 + ret + +%if ARCH_X86_64 +cglobal mask_16bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%else +cglobal mask_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, mask +%define hd dword r5m +%define m8 [base+pw_64] +%endif +%define base r6-mask_ssse3_table + LEA r6, mask_ssse3_table + tzcnt wd, wm + mov t0d, r7m ; pixel_max + shr t0d, 11 + movsxd wq, [r6+wq*4] + movddup m6, [base+bidir_rnd+t0*8] + movddup m7, [base+bidir_mul+t0*8] +%if ARCH_X86_64 + mova m8, [base+pw_64] + movifnidn hd, hm +%endif + add wq, r6 + mov maskq, r6mp + BIDIR_FN +ALIGN function_align +.main: + movq m3, [maskq+8*0] + mova m0, [tmp1q+16*0] + mova m4, [tmp2q+16*0] + pxor m5, m5 + punpcklbw m3, m5 + punpckhwd m2, m0, m4 + punpcklwd m0, m4 + psubw m1, m8, m3 + punpckhwd m4, m3, m1 ; m, 64-m + punpcklwd m3, m1 + pmaddwd m2, m4 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m0, m3 + movq m3, [maskq+8*1] + mova m1, [tmp1q+16*1] + mova m4, [tmp2q+16*1] + add maskq, 8*2 + add tmp1q, 16*2 + add tmp2q, 16*2 + psrad m2, 5 + psrad m0, 5 + packssdw m0, m2 + punpcklbw m3, m5 + punpckhwd m2, m1, m4 + punpcklwd m1, m4 + psubw m5, m8, m3 + punpckhwd m4, m3, m5 ; m, 64-m + punpcklwd m3, m5 + pmaddwd m2, m4 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m1, m3 + psrad m2, 5 + psrad m1, 5 + packssdw m1, m2 + pmaxsw m0, m6 + pmaxsw m1, m6 + psubsw m0, m6 + psubsw m1, m6 + pmulhw m0, m7 + pmulhw m1, m7 + ret + +cglobal w_mask_420_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_420_ssse3_table + LEA t0, w_mask_420_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd m0, r7m ; sign + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m4, [base+bidir_mul+r6*8] + ALLOC_STACK -16*4 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + mova [rsp+16*3], m4 + %define m8 [rsp+gprsize+16*0] + %define m9 [rsp+gprsize+16*1] + %define m10 [rsp+gprsize+16*2] + %define m11 [rsp+gprsize+16*3] +%endif + movd m7, [base+pw_2] + psubw m7, m0 + pshufb m7, [base+pw_256] + add wq, t0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 4 +.w4: + movq [dstq+strideq*0], m0 + phaddw m2, m3 + movhps [dstq+strideq*1], m0 + phaddd m2, m2 + lea dstq, [dstq+strideq*2] + paddw m2, m7 + movq [dstq+strideq*0], m1 + psrlw m2, 2 + movhps [dstq+strideq*1], m1 + packuswb m2, m2 + movd [maskq], m2 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 4 +.w8: + mova [dstq+strideq*0], m0 + paddw m2, m3 + phaddw m2, m2 + mova [dstq+strideq*1], m1 + paddw m2, m7 + psrlw m2, 2 + packuswb m2, m2 + movd [maskq], m2 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 8 +.w16: + mova [dstq+strideq*1+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*1], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + paddw m2, [dstq+strideq*1+16*0] + paddw m3, [dstq+strideq*1+16*1] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*1], m1 + paddw m2, m7 + psrlw m2, 2 + packuswb m2, m2 + movq [maskq], m2 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16 +.w32: + mova [dstq+strideq*1+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*1], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*0+16*2], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m1 + call .main + paddw m2, [dstq+strideq*1+16*0] + paddw m3, [dstq+strideq*1+16*1] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*1], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*2] + paddw m2, [dstq+strideq*1+16*3] + mova [dstq+strideq*1+16*2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*3], m1 + packuswb m3, m2 + mova [maskq], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16*2 +.w64: + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*2], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*2], m0 + mova [dstq+strideq*1+16*4], m3 + mova [dstq+strideq*0+16*3], m1 + call .main + mova [dstq+strideq*1+16*5], m2 + mova [dstq+strideq*0+16*4], m0 + mova [dstq+strideq*1+16*6], m3 + mova [dstq+strideq*0+16*5], m1 + call .main + mova [dstq+strideq*0+16*6], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*7], m2 + mova [dstq+strideq*0+16*7], m1 + call .main + paddw m2, [dstq+strideq*1+16*1] + paddw m3, [dstq+strideq*1+16*2] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*1], m1 + call .main + paddw m2, [dstq+strideq*1+16*3] + paddw m3, [dstq+strideq*1+16*4] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*2] + mova [dstq+strideq*1+16*2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*3], m1 + packuswb m3, m2 + mova [maskq+16*0], m3 + call .main + paddw m2, [dstq+strideq*1+16*5] + paddw m3, [dstq+strideq*1+16*6] + mova [dstq+strideq*1+16*4], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*6], m2 + mova [dstq+strideq*1+16*5], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*6] + paddw m2, [dstq+strideq*1+16*7] + mova [dstq+strideq*1+16*6], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*7], m1 + packuswb m3, m2 + mova [maskq+16*1], m3 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16*4 +.w128: + mova [dstq+strideq*1+16* 1], m2 + mova [dstq+strideq*0+16* 0], m0 + mova [dstq+strideq*1+16* 2], m3 + mova [dstq+strideq*0+16* 1], m1 + call .main + mova [dstq+strideq*1+16* 3], m2 + mova [dstq+strideq*0+16* 2], m0 + mova [dstq+strideq*1+16* 4], m3 + mova [dstq+strideq*0+16* 3], m1 + call .main + mova [dstq+strideq*1+16* 5], m2 + mova [dstq+strideq*0+16* 4], m0 + mova [dstq+strideq*1+16* 6], m3 + mova [dstq+strideq*0+16* 5], m1 + call .main + mova [dstq+strideq*1+16* 7], m2 + mova [dstq+strideq*0+16* 6], m0 + mova [dstq+strideq*1+16* 8], m3 + mova [dstq+strideq*0+16* 7], m1 + call .main + mova [dstq+strideq*1+16* 9], m2 + mova [dstq+strideq*0+16* 8], m0 + mova [dstq+strideq*1+16*10], m3 + mova [dstq+strideq*0+16* 9], m1 + call .main + mova [dstq+strideq*1+16*11], m2 + mova [dstq+strideq*0+16*10], m0 + mova [dstq+strideq*1+16*12], m3 + mova [dstq+strideq*0+16*11], m1 + call .main + mova [dstq+strideq*1+16*13], m2 + mova [dstq+strideq*0+16*12], m0 + mova [dstq+strideq*1+16*14], m3 + mova [dstq+strideq*0+16*13], m1 + call .main + mova [dstq+strideq*0+16*14], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*15], m2 + mova [dstq+strideq*0+16*15], m1 + call .main + paddw m2, [dstq+strideq*1+16* 1] + paddw m3, [dstq+strideq*1+16* 2] + mova [dstq+strideq*1+16* 0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16* 2], m2 + mova [dstq+strideq*1+16* 1], m1 + call .main + paddw m2, [dstq+strideq*1+16* 3] + paddw m3, [dstq+strideq*1+16* 4] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16* 2] + mova [dstq+strideq*1+16* 2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16* 3], m1 + packuswb m3, m2 + mova [maskq+16*0], m3 + call .main + paddw m2, [dstq+strideq*1+16* 5] + paddw m3, [dstq+strideq*1+16* 6] + mova [dstq+strideq*1+16* 4], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16* 6], m2 + mova [dstq+strideq*1+16* 5], m1 + call .main + paddw m2, [dstq+strideq*1+16* 7] + paddw m3, [dstq+strideq*1+16* 8] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16* 6] + mova [dstq+strideq*1+16* 6], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16* 7], m1 + packuswb m3, m2 + mova [maskq+16*1], m3 + call .main + paddw m2, [dstq+strideq*1+16* 9] + paddw m3, [dstq+strideq*1+16*10] + mova [dstq+strideq*1+16* 8], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*10], m2 + mova [dstq+strideq*1+16* 9], m1 + call .main + paddw m2, [dstq+strideq*1+16*11] + paddw m3, [dstq+strideq*1+16*12] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*10] + mova [dstq+strideq*1+16*10], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*11], m1 + packuswb m3, m2 + mova [maskq+16*2], m3 + call .main + paddw m2, [dstq+strideq*1+16*13] + paddw m3, [dstq+strideq*1+16*14] + mova [dstq+strideq*1+16*12], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*14], m2 + mova [dstq+strideq*1+16*13], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*14] + paddw m2, [dstq+strideq*1+16*15] + mova [dstq+strideq*1+16*14], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*15], m1 + packuswb m3, m2 + mova [maskq+16*3], m3 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: +%macro W_MASK 2 ; dst/tmp_offset, mask + mova m%1, [tmp1q+16*%1] + mova m%2, [tmp2q+16*%1] + punpcklwd m4, m%2, m%1 + punpckhwd m5, m%2, m%1 + psubsw m%1, m%2 + pabsw m%1, m%1 + psubusw m6, m8, m%1 + psrlw m6, 10 ; 64-m + psubw m%2, m9, m6 ; m + punpcklwd m%1, m6, m%2 + punpckhwd m6, m%2 + pmaddwd m%1, m4 + pmaddwd m6, m5 + psrad m%1, 5 + psrad m6, 5 + packssdw m%1, m6 + pmaxsw m%1, m10 + psubsw m%1, m10 + pmulhw m%1, m11 +%endmacro + W_MASK 0, 2 + W_MASK 1, 3 + add tmp1q, 16*2 + add tmp2q, 16*2 + ret + +cglobal w_mask_422_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_422_ssse3_table + LEA t0, w_mask_422_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd m7, r7m ; sign + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m4, [base+bidir_mul+r6*8] + ALLOC_STACK -16*4 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + mova [rsp+16*3], m4 +%endif + pxor m0, m0 + add wq, t0 + pshufb m7, m0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2 + W_MASK 1, 3 + phaddw m2, m3 + add tmp1q, 16*2 + add tmp2q, 16*2 + packuswb m2, m2 + pxor m3, m3 + psubb m2, m7 + pavgb m2, m3 + movq [maskq], m2 + add maskq, 8 + ret + +cglobal w_mask_444_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_444_ssse3_table + LEA t0, w_mask_444_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m7, [base+bidir_mul+r6*8] + ALLOC_STACK -16*3 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + %define m11 m7 +%endif + add wq, t0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2 + W_MASK 1, 3 + packuswb m2, m3 + add tmp1q, 16*2 + add tmp2q, 16*2 + mova [maskq], m2 + add maskq, 16 + ret + +; (a * (64 - m) + b * m + 32) >> 6 +; = (((b - a) * m + 32) >> 6) + a +; = (((b - a) * (m << 9) + 16384) >> 15) + a +; except m << 9 overflows int16_t when m == 64 (which is possible), +; but if we negate m it works out (-64 << 9 == -32768). +; = (((a - b) * (m * -512) + 16384) >> 15) + a +cglobal blend_16bpc, 3, 7, 8, dst, stride, tmp, w, h, mask, stride3 +%define base r6-blend_ssse3_table + LEA r6, blend_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + mova m7, [base+pw_m512] + add wq, r6 + lea stride3q, [strideq*3] + pxor m6, m6 + jmp wq +.w4: + mova m5, [maskq] + movq m0, [dstq+strideq*0] + movhps m0, [dstq+strideq*1] + movq m1, [dstq+strideq*2] + movhps m1, [dstq+stride3q ] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+stride3q ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + mova m5, [maskq] + mova m0, [dstq+strideq*0] + mova m1, [dstq+strideq*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8 + RET +.w16: + mova m5, [maskq] + mova m0, [dstq+16*0] + mova m1, [dstq+16*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16 + RET +.w32: + mova m5, [maskq+16*0] + mova m0, [dstq+16*0] + mova m1, [dstq+16*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova m5, [maskq+16*1] + mova m0, [dstq+16*2] + mova m1, [dstq+16*3] + psubw m2, m0, [tmpq+16*2] + psubw m3, m1, [tmpq+16*3] + add maskq, 32 + add tmpq, 64 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + add dstq, strideq + dec hd + jg .w32 + RET + +cglobal blend_v_16bpc, 3, 6, 6, dst, stride, tmp, w, h +%define base r5-blend_v_ssse3_table + LEA r5, blend_v_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + movd m4, [base+obmc_masks+2*2] +.w2_loop: + movd m0, [dstq+strideq*0] + movd m2, [tmpq+4*0] + movd m1, [dstq+strideq*1] + movd m3, [tmpq+4*1] + add tmpq, 4*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + movd [dstq+strideq*0], m0 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + movddup m2, [base+obmc_masks+4*2] +.w4_loop: + movq m0, [dstq+strideq*0] + movhps m0, [dstq+strideq*1] + mova m1, [tmpq] + add tmpq, 8*2 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova m4, [base+obmc_masks+8*2] +.w8_loop: + mova m0, [dstq+strideq*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+strideq*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + mova m4, [base+obmc_masks+16*2] + movq m5, [base+obmc_masks+16*3] +.w16_loop: + mova m0, [dstq+16*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+16*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16_loop + RET +.w32: +%if WIN64 + movaps [rsp+8], m6 +%endif + mova m4, [base+obmc_masks+16*4] + mova m5, [base+obmc_masks+16*5] + mova m6, [base+obmc_masks+16*6] +.w32_loop: + mova m0, [dstq+16*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+16*1] + mova m3, [tmpq+16*1] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + mova m2, [dstq+16*2] + paddw m1, m3 + mova m3, [tmpq+16*2] + add tmpq, 16*4 + psubw m3, m2 + pmulhrsw m3, m6 + paddw m2, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + add dstq, strideq + dec hd + jg .w32_loop +%if WIN64 + movaps m6, [rsp+8] +%endif + RET + +%macro BLEND_H_ROW 2-3 0; dst_off, tmp_off, inc_tmp + mova m0, [dstq+16*(%1+0)] + mova m2, [tmpq+16*(%2+0)] + mova m1, [dstq+16*(%1+1)] + mova m3, [tmpq+16*(%2+1)] +%if %3 + add tmpq, 16*%3 +%endif + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*(%1+0)], m0 + mova [dstq+16*(%1+1)], m1 +%endmacro + +cglobal blend_h_16bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base r6-blend_h_ssse3_table + LEA r6, blend_h_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m4, [base+blend_shuf] + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + add wq, r6 + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + movd m2, [dstq+dsq*1] + movd m3, [maskq+hq*2] + movq m1, [tmpq] + add tmpq, 4*2 + punpckldq m0, m2 + punpcklwd m3, m3 + psubw m1, m0 + pmulhrsw m1, m3 + paddw m0, m1 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova m3, [base+blend_shuf] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + movd m2, [maskq+hq*2] + mova m1, [tmpq] + add tmpq, 8*2 + psubw m1, m0 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + movddup m5, [base+blend_shuf+8] +%if WIN64 + movaps [rsp+ 8], m6 + movaps [rsp+24], m7 +%endif +.w8_loop: + movd m7, [maskq+hq*2] + mova m0, [dstq+dsq*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+dsq*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + pshufb m6, m7, m4 + psubw m2, m0 + pshufb m7, m5 + psubw m3, m1 + pmulhrsw m2, m6 + pmulhrsw m3, m7 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop +%if WIN64 + movaps m6, [rsp+ 8] + movaps m7, [rsp+24] +%endif + RET +.w16: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0, 2 + add dstq, dsq + inc hq + jl .w16 + RET +.w32: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 4 + add dstq, dsq + inc hq + jl .w32 + RET +.w64: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2 + BLEND_H_ROW 4, 4 + BLEND_H_ROW 6, 6, 8 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2 + BLEND_H_ROW 4, 4 + BLEND_H_ROW 6, 6, 16 + BLEND_H_ROW 8, -8 + BLEND_H_ROW 10, -6 + BLEND_H_ROW 12, -4 + BLEND_H_ROW 14, -2 + add dstq, dsq + inc hq + jl .w128 + RET + +; emu_edge args: +; const intptr_t bw, const intptr_t bh, const intptr_t iw, const intptr_t ih, +; const intptr_t x, const intptr_t y, pixel *dst, const ptrdiff_t dst_stride, +; const pixel *ref, const ptrdiff_t ref_stride +; +; bw, bh total filled size +; iw, ih, copied block -> fill bottom, right +; x, y, offset in bw/bh -> fill top, left +cglobal emu_edge_16bpc, 10, 13, 1, bw, bh, iw, ih, x, \ + y, dst, dstride, src, sstride, \ + bottomext, rightext, blk + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + +%if ARCH_X86_64 + %define reg_zero r12q + %define reg_tmp r10 + %define reg_src srcq + %define reg_bottomext bottomextq + %define reg_rightext rightextq + %define reg_blkm r9m +%else + %define reg_zero r6 + %define reg_tmp r0 + %define reg_src r1 + %define reg_bottomext r0 + %define reg_rightext r1 + %define reg_blkm r2m +%endif + ; + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor reg_zero, reg_zero + lea reg_tmp, [ihq-1] + cmp yq, ihq + cmovs reg_tmp, yq + test yq, yq + cmovs reg_tmp, reg_zero +%if ARCH_X86_64 + imul reg_tmp, sstrideq + add srcq, reg_tmp +%else + imul reg_tmp, sstridem + mov reg_src, srcm + add reg_src, reg_tmp +%endif + ; + ; ref += iclip(x, 0, iw - 1) + lea reg_tmp, [iwq-1] + cmp xq, iwq + cmovs reg_tmp, xq + test xq, xq + cmovs reg_tmp, reg_zero + lea reg_src, [reg_src+reg_tmp*2] +%if ARCH_X86_32 + mov srcm, reg_src +%endif + ; + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) +%if ARCH_X86_32 + mov r1, r1m ; restore bh +%endif + lea reg_bottomext, [yq+bhq] + sub reg_bottomext, ihq + lea r3, [bhq-1] + cmovs reg_bottomext, reg_zero + ; + + DEFINE_ARGS bw, bh, iw, ih, x, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, reg_zero + cmp reg_bottomext, bhq + cmovns reg_bottomext, r3 + cmp topextq, bhq + cmovg topextq, r3 + %if ARCH_X86_32 + mov r4m, reg_bottomext + ; + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + mov r0, r0m ; restore bw + %endif + lea reg_rightext, [xq+bwq] + sub reg_rightext, iwq + lea r2, [bwq-1] + cmovs reg_rightext, reg_zero + + DEFINE_ARGS bw, bh, iw, ih, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, reg_zero + cmp reg_rightext, bwq + cmovns reg_rightext, r2 + %if ARCH_X86_32 + mov r3m, r1 + %endif + cmp leftextq, bwq + cmovns leftextq, r2 + +%undef reg_zero +%undef reg_tmp +%undef reg_src +%undef reg_bottomext +%undef reg_rightext + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; center_h = bh - top_ext - bottom_ext +%if ARCH_X86_64 + lea r3, [bottomextq+topextq] + sub centerhq, r3 +%else + mov r1, centerhm ; restore r1 + sub centerhq, topextq + sub centerhq, r4m + mov r1m, centerhq +%endif + ; + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq +%if ARCH_X86_64 + imul r2, dstrideq +%else + mov r6, r6m ; restore dstq + imul r2, dstridem +%endif + add dstq, r2 + mov reg_blkm, dstq ; save pointer for ext + ; + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq +%if ARCH_X86_64 + lea r3, [rightextq+leftextq] + sub centerwq, r3 +%else + sub centerwq, r3m + sub centerwq, leftextq +%endif + +; vloop Macro +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix + %if ARCH_X86_64 + %define reg_tmp r12 + %else + %define reg_tmp r0 + %endif +.v_loop_%3: + %if ARCH_X86_32 + mov r0, r0m + mov r1, r1m + %endif +%if %1 + ; left extension + %if ARCH_X86_64 + movd m0, [srcq] + %else + mov r3, srcm + movd m0, [r3] + %endif + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + xor r3, r3 +.left_loop_%3: + mova [dstq+r3*2], m0 + add r3, mmsize/2 + cmp r3, leftextq + jl .left_loop_%3 + ; body + lea reg_tmp, [dstq+leftextq*2] +%endif + xor r3, r3 +.body_loop_%3: + %if ARCH_X86_64 + movu m0, [srcq+r3*2] + %else + mov r1, srcm + movu m0, [r1+r3*2] + %endif +%if %1 + movu [reg_tmp+r3*2], m0 +%else + movu [dstq+r3*2], m0 +%endif + add r3, mmsize/2 + cmp r3, centerwq + jl .body_loop_%3 +%if %2 + ; right extension +%if %1 + lea reg_tmp, [reg_tmp+centerwq*2] +%else + lea reg_tmp, [dstq+centerwq*2] +%endif + %if ARCH_X86_64 + movd m0, [srcq+centerwq*2-2] + %else + mov r3, srcm + movd m0, [r3+centerwq*2-2] + %endif + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + xor r3, r3 +.right_loop_%3: + movu [reg_tmp+r3*2], m0 + add r3, mmsize/2 + %if ARCH_X86_64 + cmp r3, rightextq + %else + cmp r3, r3m + %endif + jl .right_loop_%3 +%endif + %if ARCH_X86_64 + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 + %else + add dstq, dstridem + mov r0, sstridem + add srcm, r0 + sub dword centerhm, 1 + jg .v_loop_%3 + mov r0, r0m ; restore r0 + %endif +%endmacro ; vloop MACRO + + test leftextq, leftextq + jnz .need_left_ext + %if ARCH_X86_64 + test rightextq, rightextq + jnz .need_right_ext + %else + cmp leftextq, r3m ; leftextq == 0 + jne .need_right_ext + %endif + v_loop 0, 0, 0 + jmp .body_done + + ;left right extensions +.need_left_ext: + %if ARCH_X86_64 + test rightextq, rightextq + %else + mov r3, r3m + test r3, r3 + %endif + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: +; r0 ; bw +; r1 ;; x loop +; r4 ;; y loop +; r5 ; topextq +; r6 ;dstq +; r7 ;dstrideq +; r8 ; srcq +%if ARCH_X86_64 + %define reg_dstride dstrideq +%else + %define reg_dstride r2 +%endif + ; + ; bottom edge extension + %if ARCH_X86_64 + test bottomextq, bottomextq + jz .top + %else + xor r1, r1 + cmp r1, r4m + je .top + %endif + ; + %if ARCH_X86_64 + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 + %else + mov r3, dstq + mov reg_dstride, dstridem + sub r3, reg_dstride + mov srcm, r3 + %endif + ; +.bottom_x_loop: + %if ARCH_X86_64 + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, bottomextq + %else + mov r3, srcm + mova m0, [r3+r1*2] + lea r3, [dstq+r1*2] + mov r4, r4m + %endif + ; +.bottom_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .bottom_y_loop + add r1, mmsize/2 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end +%if ARCH_X86_64 + mov srcq, reg_blkm +%else + mov r3, reg_blkm + mov reg_dstride, dstridem +%endif + mov dstq, dstm + xor r1, r1 + ; +.top_x_loop: +%if ARCH_X86_64 + mova m0, [srcq+r1*2] +%else + mov r3, reg_blkm + mova m0, [r3+r1*2] +%endif + lea r3, [dstq+r1*2] + mov r4, topextq + ; +.top_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .top_y_loop + add r1, mmsize/2 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +%undef reg_dstride +%undef reg_blkm +%undef reg_tmp + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +%if ARCH_X86_64 +cglobal resize_16bpc, 0, 12, 16, 1*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%elif STACK_ALIGNMENT >= 16 +cglobal resize_16bpc, 0, 7, 8, 6*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%else +cglobal resize_16bpc, 0, 6, 8, 6*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%endif + movifnidn dstq, dstmp + movifnidn srcq, srcmp +%if STACK_ALIGNMENT >= 16 + movifnidn dst_wd, dst_wm +%endif +%if ARCH_X86_64 + movifnidn hd, hm +%endif + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + movd m4, pxmaxm + movd m7, dxm + movd m6, mx0m + movd m5, src_wm + punpcklwd m4, m4 + pshufd m4, m4, q0000 + pshufd m7, m7, q0000 + pshufd m6, m6, q0000 + pshufd m5, m5, q0000 + mova [rsp+16*3*ARCH_X86_32], m4 +%if ARCH_X86_64 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ + %define base r7-$$ +%else + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, x + %define hd dword r5m + %if STACK_ALIGNMENT >= 16 + LEA r6, $$ + %define base r6-$$ + %else + LEA r4, $$ + %define base r4-$$ + %endif +%endif +%if ARCH_X86_64 + mova m12, [base+pd_64] + mova m11, [base+pd_63] +%else + %define m12 [base+pd_64] + %define m11 [base+pd_63] +%endif + pmaddwd m4, m7, [base+rescale_mul] ; dx*[0,1,2,3] + pslld m7, 2 ; dx*4 + pslld m5, 14 + paddd m6, m4 ; mx+[0..3]*dx + SCRATCH 7, 15, 0 + SCRATCH 6, 14, 1 + SCRATCH 5, 13, 2 + pxor m1, m1 +.loop_y: + xor xd, xd + mova m0, m14 ; per-line working version of mx +.loop_x: + pcmpgtd m1, m0 + pandn m1, m0 + psrad m2, m0, 8 ; filter offset (unmasked) + pcmpgtd m3, m13, m1 + pand m1, m3 + pandn m3, m13 + por m1, m3 + psubd m3, m0, m1 ; pshufb offset + psrad m1, 14 ; clipped src_x offset + psrad m3, 14 ; pshufb edge_emu offset + pand m2, m11 ; filter offset (masked) + ; load source pixels +%if ARCH_X86_64 + movd r8d, m1 + pshuflw m1, m1, q3232 + movd r9d, m1 + punpckhqdq m1, m1 + movd r10d, m1 + psrlq m1, 32 + movd r11d, m1 + movu m4, [srcq+r8*2] + movu m5, [srcq+r9*2] + movu m6, [srcq+r10*2] + movu m7, [srcq+r11*2] + ; if no emulation is required, we don't need to shuffle or emulate edges + packssdw m3, m3 + movq r11, m3 + test r11, r11 + jz .filter + movsx r8, r11w + sar r11, 16 + movsx r9, r11w + sar r11, 16 + movsx r10, r11w + sar r11, 16 + movu m1, [base+resize_shuf+8+r8*2] + movu m3, [base+resize_shuf+8+r9*2] + movu m8, [base+resize_shuf+8+r10*2] + movu m9, [base+resize_shuf+8+r11*2] + pshufb m4, m1 + pshufb m5, m3 + pshufb m6, m8 + pshufb m7, m9 +.filter: + movd r8d, m2 + pshuflw m2, m2, q3232 + movd r9d, m2 + punpckhqdq m2, m2 + movd r10d, m2 + psrlq m2, 32 + movd r11d, m2 + movq m8, [base+resize_filter+r8*8] + movq m2, [base+resize_filter+r9*8] + pxor m9, m9 + punpcklbw m1, m9, m8 + punpcklbw m3, m9, m2 + psraw m1, 8 + psraw m3, 8 + movq m10, [base+resize_filter+r10*8] + movq m2, [base+resize_filter+r11*8] + punpcklbw m8, m9, m10 + punpcklbw m9, m2 + psraw m8, 8 + psraw m9, 8 + pmaddwd m4, m1 + pmaddwd m5, m3 + pmaddwd m6, m8 + pmaddwd m7, m9 + phaddd m4, m5 +%else + movd r3, m1 + pshuflw m1, m1, q3232 + movd r1, m1 + punpckhqdq m1, m1 + movu m4, [srcq+r3*2] + movu m5, [srcq+r1*2] + movd r3, m1 + psrlq m1, 32 + movd r1, m1 + movu m6, [srcq+r3*2] + movu m7, [srcq+r1*2] + ; if no emulation is required, we don't need to shuffle or emulate edges + pxor m1, m1 + pcmpeqb m1, m3 + pmovmskb r3d, m1 + cmp r3d, 0xffff + je .filter + movd r3, m3 + movu m1, [base+resize_shuf+8+r3*2] + pshuflw m3, m3, q3232 + movd r1, m3 + pshufb m4, m1 + movu m1, [base+resize_shuf+8+r1*2] + punpckhqdq m3, m3 + movd r3, m3 + pshufb m5, m1 + movu m1, [base+resize_shuf+8+r3*2] + psrlq m3, 32 + movd r1, m3 + pshufb m6, m1 + movu m1, [base+resize_shuf+8+r1*2] + pshufb m7, m1 +.filter: + mova [esp+4*16], m6 + mova [esp+5*16], m7 + movd r3, m2 + pshuflw m2, m2, q3232 + movd r1, m2 + movq m6, [base+resize_filter+r3*8] + movq m7, [base+resize_filter+r1*8] + pxor m3, m3 + punpcklbw m1, m3, m6 + punpcklbw m3, m7 + psraw m1, 8 + psraw m3, 8 + pmaddwd m4, m1 + pmaddwd m5, m3 + punpckhqdq m2, m2 + movd r3, m2 + psrlq m2, 32 + movd r1, m2 + phaddd m4, m5 + movq m2, [base+resize_filter+r3*8] + movq m5, [base+resize_filter+r1*8] + mova m6, [esp+4*16] + mova m7, [esp+5*16] + pxor m3, m3 + punpcklbw m1, m3, m2 + punpcklbw m3, m5 + psraw m1, 8 + psraw m3, 8 + pmaddwd m6, m1 + pmaddwd m7, m3 +%endif + phaddd m6, m7 + phaddd m4, m6 + pxor m1, m1 + psubd m2, m12, m4 + psrad m2, 7 + packssdw m2, m2 + pmaxsw m2, m1 + pminsw m2, [rsp+16*3*ARCH_X86_32] + movq [dstq+xq*2], m2 + paddd m0, m15 + add xd, 4 +%if STACK_ALIGNMENT >= 16 + cmp xd, dst_wd +%else + cmp xd, dst_wm +%endif + jl .loop_x + add dstq, dst_stridemp + add srcq, src_stridemp + dec hd + jg .loop_y + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5669 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018-2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +; dav1d_obmc_masks[] with 64-x interleaved +obmc_masks: db 0, 0, 0, 0 + ; 2 + db 45, 19, 64, 0 + ; 4 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + db 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0 + +warp_8x8_shufA: db 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 8 + db 4, 6, 8, 10, 5, 7, 9, 11, 5, 7, 9, 11, 6, 8, 10, 12 +warp_8x8_shufB: db 2, 4, 6, 8, 3, 5, 7, 9, 3, 5, 7, 9, 4, 6, 8, 10 + db 6, 8, 10, 12, 7, 9, 11, 13, 7, 9, 11, 13, 8, 10, 12, 14 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_v_shuf4: db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 +subpel_s_shuf2: db 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +bilin_h_shuf8: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7 +deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +pb_8x0_8x8: db 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 +bdct_lb_dw: db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12 +wswap: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 + +wm_420_sign: dd 0x01020102, 0x01010101 +wm_422_sign: dd 0x80808080, 0x7f7f7f7f + +pb_64: times 4 db 64 +pw_m256: times 2 dw -256 +pw_15: times 2 dw 15 +pw_32: times 2 dw 32 +pw_34: times 2 dw 34 +pw_258: times 2 dw 258 +pw_512: times 2 dw 512 +pw_1024: times 2 dw 1024 +pw_2048: times 2 dw 2048 +pw_6903: times 2 dw 6903 +pw_8192: times 2 dw 8192 +pd_32: dd 32 +pd_63: dd 63 +pd_512: dd 512 +pd_32768: dd 32768 +pd_0x3ff: dd 0x3ff +pd_0x4000: dd 0x4000 +pq_0x40000000: dq 0x40000000 + +cextern mc_subpel_filters +cextern mc_warp_filter2 +cextern resize_filter + +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx2 mangle(private_prefix %+ _put_bilin_8bpc_avx2.put) +%xdefine prep_avx2 mangle(private_prefix %+ _prep_bilin_8bpc_avx2.prep) + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +BASE_JMP_TABLE put, avx2, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx2, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx2, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx2, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx2, 1, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE put_8tap_scaled, avx2, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx2, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx2, 2, 4, 8, 16, 32, 32, 32 + +SECTION .text + +INIT_XMM avx2 +cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + lea r7, [put_avx2] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + movzx r6d, word [srcq+ssq*0] + movzx r7d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6w + mov [dstq+dsq*1], r7w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +INIT_YMM avx2 +.put_w32: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*0+32*1], m1 + mova [dstq+dsq*1+32*0], m2 + mova [dstq+dsq*1+32*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + add srcq, ssq + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 255 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 + movd xm5, mxyd + mov mxyd, r7m ; my + vpbroadcastw m5, xm5 + test mxyd, mxyd + jnz .hv + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + vpbroadcastd m3, [pw_2048] + add wq, r7 + jmp wq +.h_w2: + movd xm0, [srcq+ssq*0] + pinsrd xm0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 + pmulhrsw xm0, xm3 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + mova xm4, [bilin_h_shuf4] +.h_w4_loop: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 + pmulhrsw xm0, xm3 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pshufb xm1, xm4 + pmaddubsw xm0, xm5 + pmaddubsw xm1, xm5 + pmulhrsw xm0, xm3 + pmulhrsw xm1, xm3 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*1+8*0], 1 + movu xm1, [srcq+ssq*0+8*1] + vinserti128 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movu m1, [srcq+8*4] + movu m2, [srcq+8*5] + add srcq, ssq + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + packuswb m1, m2 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + mov r6, -32*3 +.h_w128_loop: + movu m0, [srcq+r6+32*3+8*0] + movu m1, [srcq+r6+32*3+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+32*3], m0 + add r6, 32 + jle .h_w128_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 255 + vpbroadcastd m5, [pw_2048] + add mxyd, 16 + add wq, r7 + movd xm4, mxyd + vpbroadcastw m4, xm4 + jmp wq +.v_w2: + movd xm0, [srcq+ssq*0] +.v_w2_loop: + pinsrw xm1, xm0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pinsrw xm0, xm1, [srcq+ssq*0], 0 ; 2 1 + pshuflw xm1, xm1, q2301 ; 1 0 + punpcklbw xm1, xm0 + pmaddubsw xm1, xm4 + pmulhrsw xm1, xm5 + packuswb xm1, xm1 + pextrw [dstq+dsq*0], xm1, 1 + pextrw [dstq+dsq*1], xm1, 0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xm0, [srcq+ssq*0] +.v_w4_loop: + vpbroadcastd xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm1, xm2, xm0, 0x01 ; 0 1 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm2, xm0, 0x02 ; 1 2 + punpcklbw xm1, xm2 + pmaddubsw xm1, xm4 + pmulhrsw xm1, xm5 + packuswb xm1, xm1 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xm0, [srcq+ssq*0] +.v_w8_loop: + movq xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw xm1, xm0, xm2 + movq xm0, [srcq+ssq*0] + punpcklbw xm2, xm0 + pmaddubsw xm1, xm4 + pmaddubsw xm2, xm4 + pmulhrsw xm1, xm5 + pmulhrsw xm2, xm5 + packuswb xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu xm0, [srcq+ssq*0] +.v_w16_loop: + vbroadcasti128 m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m2, m3, m0, 0x0f ; 0 1 + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m3, m0, 0xf0 ; 1 2 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +%macro PUT_BILIN_V_W32 0 + movu m0, [srcq+ssq*0] +%%loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m1, m0, m3 + punpckhbw m2, m0, m3 + movu m0, [srcq+ssq*0] + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + pmaddubsw m2, m4 + pmaddubsw m3, m4 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + packuswb m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg %%loop +%endmacro + PUT_BILIN_V_W32 + RET +.v_w64: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] +.v_w64_loop: + add srcq, ssq + movu m3, [srcq+32*0] + punpcklbw m2, m0, m3 + punpckhbw m0, m3 + pmaddubsw m2, m4 + pmaddubsw m0, m4 + pmulhrsw m2, m5 + pmulhrsw m0, m5 + packuswb m2, m0 + mova m0, m3 + movu m3, [srcq+32*1] + mova [dstq+32*0], m2 + punpcklbw m2, m1, m3 + punpckhbw m1, m3 + pmaddubsw m2, m4 + pmaddubsw m1, m4 + pmulhrsw m2, m5 + pmulhrsw m1, m5 + packuswb m2, m1 + mova m1, m3 + mova [dstq+32*1], m2 + add dstq, dsq + dec hd + jg .v_w64_loop + RET +.v_w128: + lea r6d, [hq+(3<<8)] + mov r4, srcq + mov r7, dstq +.v_w128_loop: + PUT_BILIN_V_W32 + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + vpbroadcastd m7, [pw_15] + movd xm6, mxyd + add wq, r7 + paddb m5, m5 + vpbroadcastw m6, xm6 + jmp wq +.hv_w2: + vpbroadcastd xm0, [srcq+ssq*0] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 +.hv_w2_loop: + movd xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pinsrd xm1, [srcq+ssq*0], 1 + pshufb xm1, xm4 + pmaddubsw xm1, xm5 ; 1 _ 2 _ + shufps xm2, xm0, xm1, q1032 ; 0 _ 1 _ + mova xm0, xm1 + psubw xm1, xm2 + pmulhw xm1, xm6 + pavgw xm2, xm7 + paddw xm1, xm2 + psrlw xm1, 4 + packuswb xm1, xm1 + pextrw [dstq+dsq*0], xm1, 0 + pextrw [dstq+dsq*1], xm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova xm4, [bilin_h_shuf4] + movddup xm0, [srcq+ssq*0] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 +.hv_w4_loop: + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm1, [srcq+ssq*0] + pshufb xm1, xm4 + pmaddubsw xm1, xm5 ; 1 2 + shufps xm2, xm0, xm1, q1032 ; 0 1 + mova xm0, xm1 + psubw xm1, xm2 + pmulhw xm1, xm6 + pavgw xm2, xm7 + paddw xm1, xm2 + psrlw xm1, 4 + packuswb xm1, xm1 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 m0, [srcq+ssq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 m1, [srcq+ssq*0], 1 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhw m1, m6 + pavgw m2, m7 + paddw m1, m2 + psrlw m1, 4 + vextracti128 xm2, m1, 1 + packuswb xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + movu m0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w16_loop: + movu xm2, [srcq+ssq*1+8*0] + vinserti128 m2, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + movu xm3, [srcq+ssq*0+8*0] + vinserti128 m3, [srcq+ssq*0+8*1], 1 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + psubw m1, m2, m0 + pmulhw m1, m6 + pavgw m0, m7 + paddw m1, m0 + pmaddubsw m0, m3, m5 + psubw m3, m0, m2 + pmulhw m3, m6 + pavgw m2, m7 + paddw m3, m2 + psrlw m1, 4 + psrlw m3, 4 + packuswb m1, m3 + vpermq m1, m1, q3120 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w128: + lea r6d, [hq+(3<<16)] + jmp .hv_w32_start +.hv_w64: + lea r6d, [hq+(1<<16)] +.hv_w32_start: + mov r4, srcq + mov r7, dstq +.hv_w32: +%if WIN64 + movaps r4m, xmm8 +%endif +.hv_w32_loop0: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w32_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m8, m2, m0 + pmulhw m8, m6 + pavgw m0, m7 + paddw m8, m0 + mova m0, m2 + psubw m2, m3, m1 + pmulhw m2, m6 + pavgw m1, m7 + paddw m2, m1 + mova m1, m3 + psrlw m8, 4 + psrlw m2, 4 + packuswb m8, m2 + mova [dstq], m8 + add dstq, dsq + dec hd + jg .hv_w32_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<16 + jg .hv_w32_loop0 +%if WIN64 + movaps xmm8, r4m +%endif + RET + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep%+SUFFIX] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd xm0, [srcq+strideq*0] + pinsrd xm0, [srcq+strideq*1], 1 + pinsrd xm0, [srcq+strideq*2], 2 + pinsrd xm0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmovzxbw m0, xm0 + psllw m0, 4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + movq xm1, [srcq+strideq*2] + movhps xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmovzxbw m0, xm0 + pmovzxbw m1, xm1 + psllw m0, 4 + psllw m1, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + pmovzxbw m0, [srcq+strideq*0] + pmovzxbw m1, [srcq+strideq*1] + pmovzxbw m2, [srcq+strideq*2] + pmovzxbw m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmovzxbw m0, [srcq+strideq*0+16*0] + pmovzxbw m1, [srcq+strideq*0+16*1] + pmovzxbw m2, [srcq+strideq*1+16*0] + pmovzxbw m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .prep_w32 + RET +.prep_w64: + pmovzxbw m0, [srcq+16*0] + pmovzxbw m1, [srcq+16*1] + pmovzxbw m2, [srcq+16*2] + pmovzxbw m3, [srcq+16*3] + add srcq, strideq + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .prep_w64 + RET +.prep_w128: + pmovzxbw m0, [srcq+16*0] + pmovzxbw m1, [srcq+16*1] + pmovzxbw m2, [srcq+16*2] + pmovzxbw m3, [srcq+16*3] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + pmovzxbw m0, [srcq+16*4] + pmovzxbw m1, [srcq+16*5] + pmovzxbw m2, [srcq+16*6] + pmovzxbw m3, [srcq+16*7] + add tmpq, 32*8 + add srcq, strideq + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .prep_w128 + RET +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] + imul mxyd, 255 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 + movd xm5, mxyd + mov mxyd, r6m ; my + vpbroadcastw m5, xm5 + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + vbroadcasti128 m4, [bilin_h_shuf4] +.h_w4_loop: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + movq xm1, [srcq+strideq*2] + movhps xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 m0, xm1, 1 + pshufb m0, m4 + pmaddubsw m0, m5 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: +.h_w8_loop: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*2] + vinserti128 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: +.h_w16_loop: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + movu xm2, [srcq+strideq*2+8*0] + vinserti128 m2, [srcq+strideq*2+8*1], 1 + movu xm3, [srcq+stride3q +8*0] + vinserti128 m3, [srcq+stride3q +8*1], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: +.h_w32_loop: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + movu xm1, [srcq+strideq*0+8*2] + vinserti128 m1, [srcq+strideq*0+8*3], 1 + movu xm2, [srcq+strideq*1+8*0] + vinserti128 m2, [srcq+strideq*1+8*1], 1 + movu xm3, [srcq+strideq*1+8*2] + vinserti128 m3, [srcq+strideq*1+8*3], 1 + lea srcq, [srcq+strideq*2] + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .h_w32_loop + RET +.h_w64: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + movu xm2, [srcq+8*4] + vinserti128 m2, [srcq+8*5], 1 + movu xm3, [srcq+8*6] + vinserti128 m3, [srcq+8*7], 1 + add srcq, strideq + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .h_w64 + RET +.h_w128: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + movu xm2, [srcq+8*4] + vinserti128 m2, [srcq+8*5], 1 + movu xm3, [srcq+8*6] + vinserti128 m3, [srcq+8*7], 1 + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + movu xm0, [srcq+8* 8] + vinserti128 m0, [srcq+8* 9], 1 + movu xm1, [srcq+8*10] + vinserti128 m1, [srcq+8*11], 1 + movu xm2, [srcq+8*12] + vinserti128 m2, [srcq+8*13], 1 + movu xm3, [srcq+8*14] + vinserti128 m3, [srcq+8*15], 1 + add tmpq, 32*8 + add srcq, strideq + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .h_w128 + RET +.v: + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + imul mxyd, 255 + add mxyd, 16 + add wq, r6 + lea stride3q, [strideq*3] + movd xm6, mxyd + vpbroadcastw m6, xm6 + jmp wq +.v_w4: + movd xm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastd m1, [srcq+strideq*2] + vpbroadcastd xm2, [srcq+strideq*1] + vpbroadcastd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0x05 ; 0 2 2 2 + vpbroadcastd m0, [srcq+strideq*0] + vpblendd m3, m2, 0x0f ; 1 1 3 3 + vpblendd m2, m1, m0, 0xa0 ; 0 2 2 4 + vpblendd m1, m3, 0xaa ; 0 1 2 3 + vpblendd m2, m3, 0x55 ; 1 2 3 4 + punpcklbw m1, m2 + pmaddubsw m1, m6 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq xm0, [srcq+strideq*0] +.v_w8_loop: + vpbroadcastq m1, [srcq+strideq*2] + vpbroadcastq m2, [srcq+strideq*1] + vpbroadcastq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0x03 ; 0 2 2 2 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m2, m3, 0xcc ; 1 3 1 3 + vpblendd m3, m2, m1, 0xf0 ; 1 3 2 2 + vpblendd m2, m1, 0x0f ; 0 2 1 3 + vpblendd m3, m0, 0xc0 ; 1 3 2 4 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m6 + pmaddubsw m2, m6 + mova [tmpq+32*0], m1 + mova [tmpq+32*1], m2 + add tmpq, 32*2 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti128 m0, [srcq+strideq*0] +.v_w16_loop: + vbroadcasti128 m1, [srcq+strideq*1] + vbroadcasti128 m2, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + shufpd m4, m0, m2, 0x0c ; 0 2 + vbroadcasti128 m0, [srcq+strideq*0] + shufpd m1, m3, 0x0c ; 1 3 + shufpd m2, m0, 0x0c ; 2 4 + punpcklbw m3, m4, m1 + punpcklbw m5, m1, m2 + punpckhbw m4, m1 + punpckhbw m1, m2 + pmaddubsw m3, m6 + pmaddubsw m5, m6 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+32*0], m3 + mova [tmpq+32*1], m5 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m1 + add tmpq, 32*4 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + vpermq m0, [srcq+strideq*0], q3120 +.v_w32_loop: + vpermq m1, [srcq+strideq*1], q3120 + vpermq m2, [srcq+strideq*2], q3120 + vpermq m3, [srcq+stride3q ], q3120 + lea srcq, [srcq+strideq*4] + punpcklbw m4, m0, m1 + punpckhbw m5, m0, m1 + vpermq m0, [srcq+strideq*0], q3120 + pmaddubsw m4, m6 + pmaddubsw m5, m6 + mova [tmpq+32*0], m4 + mova [tmpq+32*1], m5 + punpcklbw m4, m1, m2 + punpckhbw m1, m2 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + punpcklbw m5, m2, m3 + punpckhbw m2, m3 + pmaddubsw m5, m6 + pmaddubsw m2, m6 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m1 + add tmpq, 32*8 + punpcklbw m1, m3, m0 + punpckhbw m3, m0 + pmaddubsw m1, m6 + pmaddubsw m3, m6 + mova [tmpq-32*4], m5 + mova [tmpq-32*3], m2 + mova [tmpq-32*2], m1 + mova [tmpq-32*1], m3 + sub hd, 4 + jg .v_w32_loop + RET +.v_w64: + vpermq m0, [srcq+strideq*0+32*0], q3120 + vpermq m1, [srcq+strideq*0+32*1], q3120 +.v_w64_loop: + vpermq m2, [srcq+strideq*1+32*0], q3120 + vpermq m3, [srcq+strideq*1+32*1], q3120 + lea srcq, [srcq+strideq*2] + punpcklbw m4, m0, m2 + punpckhbw m0, m2 + pmaddubsw m4, m6 + pmaddubsw m0, m6 + mova [tmpq+32*0], m4 + mova [tmpq+32*1], m0 + punpcklbw m4, m1, m3 + punpckhbw m5, m1, m3 + vpermq m0, [srcq+strideq*0+32*0], q3120 + vpermq m1, [srcq+strideq*0+32*1], q3120 + pmaddubsw m4, m6 + pmaddubsw m5, m6 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m5 + add tmpq, 32*8 + punpcklbw m4, m2, m0 + punpckhbw m2, m0 + punpcklbw m5, m3, m1 + punpckhbw m3, m1 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + pmaddubsw m5, m6 + pmaddubsw m3, m6 + mova [tmpq-32*4], m4 + mova [tmpq-32*3], m2 + mova [tmpq-32*2], m5 + mova [tmpq-32*1], m3 + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + lea r6d, [hq+(3<<8)] + mov r3, srcq + mov r5, tmpq +.v_w128_loop0: + vpermq m0, [srcq+strideq*0], q3120 +.v_w128_loop: + vpermq m1, [srcq+strideq*1], q3120 + lea srcq, [srcq+strideq*2] + punpcklbw m2, m0, m1 + punpckhbw m3, m0, m1 + vpermq m0, [srcq+strideq*0], q3120 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + punpcklbw m4, m1, m0 + punpckhbw m1, m0 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+32*0], m2 + mova [tmpq+32*1], m3 + mova [tmpq+32*8], m4 + mova [tmpq+32*9], m1 + add tmpq, 32*16 + sub hd, 2 + jg .v_w128_loop + add r3, 32 + add r5, 64 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .v_w128_loop0 + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + movd xm6, mxyd + vpbroadcastw m6, xm6 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + vbroadcasti128 m4, [bilin_h_shuf4] + vpbroadcastq m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w4_loop: + movq xm1, [srcq+strideq*1] + movhps xm1, [srcq+strideq*2] + movq xm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + movhps xm2, [srcq+strideq*0] + vinserti128 m1, xm2, 1 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 3 4 + vpblendd m2, m1, m0, 0xc0 + vpermq m2, m2, q2103 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xm1, [srcq+strideq*1] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 m2, [srcq+strideq*0], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 ; 1 2 + vperm2i128 m3, m0, m1, 0x21 ; 0 1 + pmaddubsw m0, m2, m5 ; 3 4 + vperm2i128 m2, m1, m0, 0x21 ; 2 3 + psubw m1, m3 + pmulhrsw m1, m6 + paddw m1, m3 + psubw m3, m0, m2 + pmulhrsw m3, m6 + paddw m3, m2 + mova [tmpq+32*0], m1 + mova [tmpq+32*1], m3 + add tmpq, 32*2 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w16_loop: + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + movu xm2, [srcq+strideq*0+8*0] + vinserti128 m2, [srcq+strideq*0+8*1], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+32*0], m3 + mova [tmpq+32*1], m2 + add tmpq, 32*2 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w32_loop: + add srcq, strideq + movu xm2, [srcq+8*0] + vinserti128 m2, [srcq+8*1], 1 + pshufb m2, m4 + pmaddubsw m2, m5 + psubw m3, m2, m0 + pmulhrsw m3, m6 + paddw m3, m0 + mova m0, m2 + movu xm2, [srcq+8*2] + vinserti128 m2, [srcq+8*3], 1 + pshufb m2, m4 + pmaddubsw m2, m5 + mova [tmpq+32*0], m3 + psubw m3, m2, m1 + pmulhrsw m3, m6 + paddw m3, m1 + mova m1, m2 + mova [tmpq+32*1], m3 + add tmpq, 32*2 + dec hd + jg .hv_w32_loop + RET +.hv_w128: + lea r3d, [hq+(7<<8)] + mov r6d, 256 + jmp .hv_w64_start +.hv_w64: + lea r3d, [hq+(3<<8)] + mov r6d, 128 +.hv_w64_start: +%if WIN64 + PUSH r7 +%endif + mov r5, srcq + mov r7, tmpq +.hv_w64_loop0: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w64_loop: + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + movu xm2, [srcq+strideq*0+8*0] + vinserti128 m2, [srcq+strideq*0+8*1], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+r6*0], m3 + mova [tmpq+r6*1], m2 + lea tmpq, [tmpq+r6*2] + sub hd, 2 + jg .hv_w64_loop + add r5, 16 + add r7, 32 + movzx hd, r3b + mov srcq, r5 + mov tmpq, r7 + sub r3d, 1<<8 + jg .hv_w64_loop0 +%if WIN64 + POP r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; fn, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx2] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 + lea r6, [ssq*3] + lea r7, [dsq*3] +%if WIN64 + pop r8 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [pw_34] ; 2 + (8 << 2) + WIN64_SPILL_XMM 11 + cmp wd, 4 + jl .h_w2 + vbroadcasti128 m6, [subpel_h_shufA] + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m7, [subpel_h_shufB] + vbroadcasti128 m8, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)] + vpbroadcastd m9, [r8+mxq*8+subpel_filters-put_avx2+0] + vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+4] + add wq, r8 + jmp wq +.h_w2: + movzx mxd, mxb + dec srcq + mova xm4, [subpel_h_shuf4] + vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2] +.h_w2_loop: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm3 + phaddw xm0, xm0 + paddw xm0, xm5 + psraw xm0, 6 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2] +.h_w4_loop: + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm6 + pshufb xm1, xm6 + pmaddubsw xm0, xm3 + pmaddubsw xm1, xm3 + phaddw xm0, xm1 + paddw xm0, xm5 + psraw xm0, 6 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: +%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3] + pshufb m%2, m%1, m7 + pshufb m%3, m%1, m8 + pshufb m%1, m6 + pmaddubsw m%4, m%2, m9 + pmaddubsw m%2, m10 + pmaddubsw m%3, m10 + pmaddubsw m%1, m9 + paddw m%3, m%4 + paddw m%1, m%2 + phaddw m%1, m%3 + paddw m%1, m5 + psraw m%1, 6 +%endmacro + movu xm0, [srcq+ssq*0] + vinserti128 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 1, 2, 3 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*1+8*0], 1 + movu xm1, [srcq+ssq*0+8*1] + vinserti128 m1, [srcq+ssq*1+8*1], 1 + PUT_8TAP_H 0, 2, 3, 4 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 1, 2, 3, 4 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + xor r6d, r6d + jmp .h_start +.h_w64: + mov r6, -32*1 + jmp .h_start +.h_w128: + mov r6, -32*3 +.h_start: + sub srcq, r6 + sub dstq, r6 + mov r4, r6 +.h_loop: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 2, 3, 4 + packuswb m0, m1 + mova [dstq+r6], m0 + add r6, 32 + jle .h_loop + add srcq, ssq + add dstq, dsq + mov r6, r4 + dec hd + jg .h_loop + RET +.v: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + tzcnt r6d, wd + movzx r6d, word [r8+r6*2+table_offset(put, _8tap_v)] + vpbroadcastd m7, [pw_512] + lea myq, [r8+myq*8+subpel_filters-put_avx2] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + add r6, r8 + lea ss3q, [ssq*3] + sub srcq, ss3q + jmp r6 +.v_w2: + movd xm2, [srcq+ssq*0] + pinsrw xm2, [srcq+ssq*1], 2 + pinsrw xm2, [srcq+ssq*2], 4 + add srcq, ss3q + pinsrw xm2, [srcq+ssq*0], 6 ; 0 1 2 3 + movd xm3, [srcq+ssq*1] + vpbroadcastd xm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklbw xm3, xm1 ; 45 56 + punpcklbw xm1, xm2, xm4 ; 01 12 + punpckhbw xm2, xm4 ; 23 34 +.v_w2_loop: + pmaddubsw xm5, xm1, xm8 ; a0 b0 + mova xm1, xm2 + pmaddubsw xm2, xm9 ; a1 b1 + paddw xm5, xm2 + mova xm2, xm3 + pmaddubsw xm3, xm10 ; a2 b2 + paddw xm5, xm3 + vpbroadcastd xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklbw xm3, xm4 ; 67 78 + pmaddubsw xm4, xm3, xm11 ; a3 b3 + paddw xm5, xm4 + pmulhrsw xm5, xm7 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xm2, [srcq+ssq*0] + pinsrd xm2, [srcq+ssq*1], 1 + pinsrd xm2, [srcq+ssq*2], 2 + add srcq, ss3q + pinsrd xm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xm3, [srcq+ssq*1] + vpbroadcastd xm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklbw xm3, xm1 ; 45 56 + punpcklbw xm1, xm2, xm4 ; 01 12 + punpckhbw xm2, xm4 ; 23 34 +.v_w4_loop: + pmaddubsw xm5, xm1, xm8 ; a0 b0 + mova xm1, xm2 + pmaddubsw xm2, xm9 ; a1 b1 + paddw xm5, xm2 + mova xm2, xm3 + pmaddubsw xm3, xm10 ; a2 b2 + paddw xm5, xm3 + vpbroadcastd xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklbw xm3, xm4 ; 67 78 + pmaddubsw xm4, xm3, xm11 ; a3 b3 + paddw xm5, xm4 + pmulhrsw xm5, xm7 + packuswb xm5, xm5 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xm1, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + vpbroadcastq m2, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m5, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpbroadcastq m6, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m0, [srcq+ssq*0] + vpblendd m1, m4, 0x30 + vpblendd m4, m2, 0x30 + punpcklbw m1, m4 ; 01 12 + vpblendd m2, m5, 0x30 + vpblendd m5, m3, 0x30 + punpcklbw m2, m5 ; 23 34 + vpblendd m3, m6, 0x30 + vpblendd m6, m0, 0x30 + punpcklbw m3, m6 ; 45 56 +.v_w8_loop: + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, m8 ; a0 b0 + mova m1, m2 + pmaddubsw m2, m9 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, m10 ; a2 b2 + paddw m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+ssq*0] + vpblendd m4, m0, 0x30 + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, m11 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + vextracti128 xm4, m5, 1 + packuswb xm5, xm4 + movq [dstq+dsq*0], xm5 + movhps [dstq+dsq*1], xm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: +.v_w32: +.v_w64: +.v_w128: + lea r6d, [wq*8-128] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*2] +.v_w16_loop0: + vbroadcasti128 m4, [srcq+ssq*0] + vbroadcasti128 m5, [srcq+ssq*1] + vbroadcasti128 m6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m0, [srcq+ssq*0] + vbroadcasti128 m1, [srcq+ssq*1] + vbroadcasti128 m2, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m3, [srcq+ssq*0] + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklbw m1, m4, m5 ; 01 + punpckhbw m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklbw m2, m5, m6 ; 12 + punpckhbw m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklbw m3, m6, m0 ; 23 + punpckhbw m6, m0 ; 56 +.v_w16_loop: + vbroadcasti128 m12, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti128 m13, [srcq+ssq*0] + pmaddubsw m14, m1, m8 ; a0 + pmaddubsw m15, m2, m8 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, m9 ; a1 + pmaddubsw m4, m9 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, m10 ; a2 + pmaddubsw m6, m10 ; b2 + paddw m14, m5 + paddw m15, m6 + shufpd m6, m0, m12, 0x0d + shufpd m0, m12, m13, 0x0c + punpcklbw m5, m6, m0 ; 67 + punpckhbw m6, m0 ; 78 + pmaddubsw m12, m5, m11 ; a3 + pmaddubsw m13, m6, m11 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + packuswb m14, m15 + vpermq m14, m14, q3120 + mova [dstq+dsq*0], xm14 + vextracti128 [dstq+dsq*1], m14, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + dec srcq + vpbroadcastd m7, [r8+mxq*8+subpel_filters-put_avx2+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastq m0, [r8+myq*8+subpel_filters-put_avx2] + lea ss3q, [ssq*3] + sub srcq, ss3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m8, [pw_8192] + vpbroadcastd m9, [pd_512] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 m6, [subpel_h_shuf4] + movq xm2, [srcq+ssq*0] + movhps xm2, [srcq+ssq*1] + movq xm0, [srcq+ssq*2] + add srcq, ss3q + movhps xm0, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpbroadcastq m4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m1, [srcq+ssq*0] + vpblendd m2, m3, 0x30 + vpblendd m0, m1, 0x30 + vpblendd m2, m4, 0xc0 + pshufb m2, m6 + pshufb m0, m6 + pmaddubsw m2, m7 + pmaddubsw m0, m7 + phaddw m2, m0 + pmulhrsw m2, m8 + vextracti128 xm3, m2, 1 + palignr xm4, xm3, xm2, 4 + punpcklwd xm1, xm2, xm4 ; 01 12 + punpckhwd xm2, xm4 ; 23 34 + pshufd xm0, xm3, q2121 + punpcklwd xm3, xm0 ; 45 56 +.hv_w2_loop: + movq xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm4, [srcq+ssq*0] + pshufb xm4, xm6 + pmaddubsw xm4, xm7 + pmaddwd xm5, xm1, xm10 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm11 ; a1 b1 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm12 ; a2 b2 + phaddw xm4, xm4 + pmulhrsw xm4, xm8 + paddd xm5, xm3 + palignr xm3, xm4, xm0, 12 + mova xm0, xm4 + punpcklwd xm3, xm0 ; 67 78 + pmaddwd xm4, xm3, xm13 ; a3 b3 + paddd xm5, xm9 + paddd xm5, xm4 + psrad xm5, 10 + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova m6, [subpel_h_shuf4] + vpbroadcastq m2, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + vpbroadcastq m0, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m5, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpblendd m2, m4, 0xcc ; 0 1 + vpbroadcastq m4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m1, [srcq+ssq*0] + vpblendd m0, m5, 0xcc ; 2 3 + vpblendd m3, m4, 0xcc ; 4 5 + pshufb m2, m6 + pshufb m0, m6 + pshufb m3, m6 + pshufb m1, m6 + pmaddubsw m2, m7 + pmaddubsw m0, m7 + pmaddubsw m3, m7 + pmaddubsw m1, m7 + phaddw m2, m0 + phaddw m3, m1 + pmulhrsw m2, m8 + pmulhrsw m3, m8 + palignr m4, m3, m2, 4 + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + pshufd m0, m3, q2121 + punpcklwd m3, m0 ; 45 56 +.hv_w4_loop: + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m1, m10 ; a0 b0 + mova m1, m2 + pmaddwd m2, m11 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m12 ; a2 b2 + paddd m5, m3 + vpbroadcastq m3, [srcq+ssq*0] + vpblendd m4, m3, 0xcc ; 7 8 + pshufb m4, m6 + pmaddubsw m4, m7 + phaddw m4, m4 + pmulhrsw m4, m8 + palignr m3, m4, m0, 12 + mova m0, m4 + punpcklwd m3, m0 ; 67 78 + pmaddwd m4, m3, m13 ; a3 b3 + paddd m5, m9 + paddd m5, m4 + psrad m5, 10 + vextracti128 xm4, m5, 1 + packssdw xm5, xm4 + packuswb xm5, xm5 + pshuflw xm5, xm5, q3120 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+0] + vpbroadcastd m11, [r8+mxq*8+subpel_filters-put_avx2+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastq m0, [r8+myq*8+subpel_filters-put_avx2] + lea ss3q, [ssq*3] + sub srcq, ss3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + lea r6d, [wq*8-64] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*4] +.hv_w8_loop0: + vbroadcasti128 m7, [subpel_h_shufA] + movu xm4, [srcq+ssq*0] + vbroadcasti128 m8, [subpel_h_shufB] + movu xm5, [srcq+ssq*1] + vbroadcasti128 m9, [subpel_h_shufC] + movu xm6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m4, m0, 0xf0 ; 0 3 + vinserti128 m5, [srcq+ssq*1], 1 ; 1 4 + vinserti128 m6, [srcq+ssq*2], 1 ; 2 5 + add srcq, ss3q + vinserti128 m0, [srcq+ssq*0], 1 ; 3 6 +%macro HV_H_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3] + pshufb %3, %1, %6 + pshufb %4, %1, %7 + pshufb %1, %5 + pmaddubsw %2, %3, m10 + pmaddubsw %4, m11 + pmaddubsw %3, m11 + pmaddubsw %1, m10 + paddw %2, %4 + paddw %1, %3 + phaddw %1, %2 +%endmacro + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 + vpbroadcastd m7, [pw_8192] + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + pmulhrsw m0, m7 + pmulhrsw m4, m7 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + vpermq m7, m0, q3120 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vextracti128 r6m, m0, 1 ; not enough registers + movu xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 m0, [srcq+ssq*0], 1 ; 7 8 + pmaddwd m8, m1, m12 ; a0 + pmaddwd m9, m2, m12 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m13 ; a1 + pmaddwd m4, m13 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m14 ; a2 + pmaddwd m6, m14 ; b2 + paddd m8, m5 + paddd m9, m6 + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + vbroadcasti128 m5, [subpel_h_shufA] + HV_H_W8 m0, m5, m6, m7, m5, m6, m7 + vpbroadcastd m5, [pw_8192] + vpbroadcastd m7, [pd_512] + vbroadcasti128 m6, r6m + pmulhrsw m0, m5 + paddd m8, m7 + paddd m9, m7 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, m15 ; a3 + paddd m8, m7 + pmaddwd m7, m6, m15 ; b3 + paddd m7, m9 + psrad m8, 10 + psrad m7, 10 + packssdw m8, m7 + vextracti128 xm7, m8, 1 + packuswb xm8, xm7 + pshufd xm7, xm8, q3120 + movq [dstq+dsq*0], xm7 + movhps [dstq+dsq*1], xm7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + add r4, 8 + add r7, 8 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w8_loop0 + RET + +%macro PREP_8TAP_H 0 + pshufb m1, m0, m5 + pshufb m2, m0, m6 + pshufb m3, m0, m7 + pmaddubsw m1, m8 + pmaddubsw m0, m2, m8 + pmaddubsw m2, m9 + pmaddubsw m3, m9 + paddw m1, m2 + paddw m0, m3 + phaddw m0, m1, m0 + pmulhrsw m0, m4 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep%+SUFFIX] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r7+wq*2+table_offset(prep,)] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m4, [pw_8192] + vbroadcasti128 m5, [subpel_h_shufA] + WIN64_SPILL_XMM 10 + cmp wd, 4 + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)] + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0] + vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4] + add wq, r7 + jmp wq +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m6, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2] + lea stride3q, [strideq*3] +.h_w4_loop: + movq xm0, [srcq+strideq*0] + vpbroadcastq m2, [srcq+strideq*2] + movq xm1, [srcq+strideq*1] + vpblendd m0, m2, 0xf0 + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m2, 0xf0 + pshufb m0, m5 + pshufb m1, m5 + pmaddubsw m0, m6 + pmaddubsw m1, m6 + phaddw m0, m1 + pmulhrsw m0, m4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + PREP_8TAP_H + mova [tmpq+32*0], m0 + movu xm0, [srcq+strideq*1+8*0] + vinserti128 m0, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + mova [tmpq+32*1], m0 + add tmpq, 32*2 + sub hd, 2 + jg .h_w16 + RET +.h_w32: + xor r6d, r6d + jmp .h_start +.h_w64: + mov r6, -32*1 + jmp .h_start +.h_w128: + mov r6, -32*3 +.h_start: + sub srcq, r6 + mov r5, r6 +.h_loop: + movu xm0, [srcq+r6+8*0] + vinserti128 m0, [srcq+r6+8*1], 1 + PREP_8TAP_H + mova [tmpq+32*0], m0 + movu xm0, [srcq+r6+8*2] + vinserti128 m0, [srcq+r6+8*3], 1 + PREP_8TAP_H + mova [tmpq+32*1], m0 + add tmpq, 32*2 + add r6, 32 + jle .h_loop + add srcq, strideq + mov r6, r5 + dec hd + jg .h_loop + RET +.v: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + movzx mxd, myb ; Select 4-tap/8-tap filter multipliers. + shr myd, 16 ; Note that the code is 8-tap only, having + cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4 + cmove myd, mxd ; had a negligible effect on performance. + ; TODO: Would a 6-tap code path be worth it? + lea myq, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + vpbroadcastd m7, [pw_8192] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + cmp wd, 8 + jg .v_w16 + je .v_w8 +.v_w4: + movd xm0, [srcq+strideq*0] + vpbroadcastd m1, [srcq+strideq*2] + vpbroadcastd xm2, [srcq+strideq*1] + add srcq, stride3q + vpbroadcastd m3, [srcq+strideq*0] + vpblendd m1, m0, 0x01 ; 0 2 2 _ 2 _ _ _ + vpblendd m3, m2, 0x03 ; 1 1 3 3 3 3 _ _ + vpbroadcastd m0, [srcq+strideq*1] + vpbroadcastd m2, [srcq+strideq*2] + vpblendd m1, m0, 0x68 ; 0 2 2 4 2 4 4 _ + vpbroadcastd m0, [srcq+stride3q ] + vbroadcasti128 m5, [deint_shuf4] + vpblendd m3, m2, 0xc0 ; 1 1 3 3 3 3 5 5 + vpblendd m2, m3, m1, 0x55 ; 0 1 2 3 2 3 4 5 + vpblendd m3, m1, 0xaa ; 1 2 3 4 3 4 5 _ + punpcklbw m1, m2, m3 ; 01 12 23 34 + vpblendd m3, m0, 0x80 ; 1 2 3 4 3 4 5 6 + punpckhbw m2, m3 ; 23 34 45 56 +.v_w4_loop: + lea srcq, [srcq+strideq*4] + pinsrd xm0, [srcq+strideq*0], 1 + vpbroadcastd m3, [srcq+strideq*1] + vpbroadcastd m4, [srcq+strideq*2] + vpblendd m3, m0, 0x03 ; 6 7 8 _ 8 _ _ _ + vpbroadcastd m0, [srcq+stride3q ] + vpblendd m3, m4, 0x20 ; 6 7 8 _ 8 9 _ _ + vpblendd m3, m0, 0x40 ; 6 7 8 _ 8 9 a _ + pshufb m3, m5 ; 67 78 89 9a + pmaddubsw m4, m1, m8 + vperm2i128 m1, m2, m3, 0x21 ; 45 56 67 78 + pmaddubsw m2, m9 + paddw m4, m2 + mova m2, m3 + pmaddubsw m3, m11 + paddw m3, m4 + pmaddubsw m4, m1, m10 + paddw m3, m4 + pmulhrsw m3, m7 + mova [tmpq], m3 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq xm1, [srcq+strideq*0] + vpbroadcastq m4, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m5, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m6, [srcq+strideq*1] + vpbroadcastq m0, [srcq+strideq*2] + vpblendd m1, m4, 0x30 + vpblendd m4, m2, 0x30 + punpcklbw m1, m4 ; 01 12 + vpblendd m2, m5, 0x30 + vpblendd m5, m3, 0x30 + punpcklbw m2, m5 ; 23 34 + vpblendd m3, m6, 0x30 + vpblendd m6, m0, 0x30 + punpcklbw m3, m6 ; 45 56 +.v_w8_loop: + vpbroadcastq m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmaddubsw m5, m2, m9 ; a1 + pmaddubsw m6, m2, m8 ; b0 + vpblendd m2, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m4, m0, 0x30 + punpcklbw m2, m4 ; 67 78 + pmaddubsw m1, m8 ; a0 + pmaddubsw m4, m3, m9 ; b1 + paddw m5, m1 + mova m1, m3 + pmaddubsw m3, m10 ; a2 + paddw m6, m4 + paddw m5, m3 + vpbroadcastq m4, [srcq+strideq*1] + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*2] + vpblendd m4, m0, 0x30 + punpcklbw m3, m4 ; 89 9a + pmaddubsw m4, m2, m11 ; a3 + paddw m5, m4 + pmaddubsw m4, m2, m10 ; b2 + paddw m6, m4 + pmaddubsw m4, m3, m11 ; b3 + paddw m6, m4 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + mova [tmpq+32*0], m5 + mova [tmpq+32*1], m6 + add tmpq, 32*2 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + add wd, wd + mov r5, srcq + mov r7, tmpq + lea r6d, [hq+wq*8-256] +.v_w16_loop0: + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m0, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*0] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m1, [srcq+strideq*0] + vbroadcasti128 m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+strideq*0] + shufpd m4, m4, m0, 0x0c + shufpd m5, m5, m1, 0x0c + punpcklbw m1, m4, m5 ; 01 + punpckhbw m4, m5 ; 34 + shufpd m6, m6, m2, 0x0c + punpcklbw m2, m5, m6 ; 12 + punpckhbw m5, m6 ; 45 + shufpd m0, m0, m3, 0x0c + punpcklbw m3, m6, m0 ; 23 + punpckhbw m6, m0 ; 56 +.v_w16_loop: + vbroadcasti128 m12, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m13, [srcq+strideq*0] + pmaddubsw m14, m1, m8 ; a0 + pmaddubsw m15, m2, m8 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, m9 ; a1 + pmaddubsw m4, m9 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, m10 ; a2 + pmaddubsw m6, m10 ; b2 + paddw m14, m5 + paddw m15, m6 + shufpd m6, m0, m12, 0x0d + shufpd m0, m12, m13, 0x0c + punpcklbw m5, m6, m0 ; 67 + punpckhbw m6, m0 ; 78 + pmaddubsw m12, m5, m11 ; a3 + pmaddubsw m13, m6, m11 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + mova [tmpq+wq*0], m14 + mova [tmpq+wq*1], m15 + lea tmpq, [tmpq+wq*2] + sub hd, 2 + jg .v_w16_loop + add r5, 16 + add r7, 32 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + %assign stack_size_padded 0 + WIN64_SPILL_XMM 16 + cmp wd, 4 + je .hv_w4 + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0] + vpbroadcastd m11, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + jmp .hv_w8 +.hv_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + mova m7, [subpel_h_shuf4] + pmovzxbd m9, [deint_shuf4] + vpbroadcastd m10, [pw_8192] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m11, [pd_32] + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + vpbroadcastq m2, [srcq+strideq*0] + vpbroadcastq m4, [srcq+strideq*1] + vpbroadcastq m0, [srcq+strideq*2] + vpbroadcastq m5, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m6, [srcq+strideq*1] + vpbroadcastq m1, [srcq+strideq*2] + vpblendd m2, m4, 0xcc ; 0 1 + vpblendd m0, m5, 0xcc ; 2 3 + vpblendd m3, m6, 0xcc ; 4 5 + pshufb m2, m7 ; 00 01 10 11 02 03 12 13 + pshufb m0, m7 ; 20 21 30 31 22 23 32 33 + pshufb m3, m7 ; 40 41 50 51 42 43 52 53 + pshufb m1, m7 ; 60 61 60 61 62 63 62 63 + pmaddubsw m2, m8 + pmaddubsw m0, m8 + pmaddubsw m3, m8 + pmaddubsw m1, m8 + phaddw m2, m0 ; 0a 1a 2a 3a 0b 1b 2b 3b + phaddw m3, m1 ; 4a 5a 6a __ 4b 5b 6b __ + pmulhrsw m2, m10 + pmulhrsw m3, m10 + palignr m4, m3, m2, 4 ; 1a 2a 3a 4a 1b 2b 3b 4b + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + pshufd m0, m3, q2121 + punpcklwd m3, m0 ; 45 56 +.hv_w4_loop: + pmaddwd m5, m1, m12 ; a0 b0 + pmaddwd m6, m2, m12 ; c0 d0 + pmaddwd m2, m13 ; a1 b1 + pmaddwd m4, m3, m13 ; c1 d1 + mova m1, m3 + pmaddwd m3, m14 ; a2 b2 + paddd m5, m2 + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + paddd m6, m4 + vpbroadcastq m4, [srcq+strideq*0] + paddd m5, m3 + vpbroadcastq m3, [srcq+strideq*1] + vpblendd m2, m4, 0xcc + vpbroadcastq m4, [srcq+strideq*2] + vpblendd m3, m4, 0xcc + pshufb m2, m7 + pshufb m3, m7 + pmaddubsw m2, m8 + pmaddubsw m3, m8 + phaddw m2, m3 + pmulhrsw m2, m10 + palignr m3, m2, m0, 12 + mova m0, m2 + punpcklwd m2, m3, m0 ; 67 78 + punpckhwd m3, m0 ; 89 9a + pmaddwd m4, m2, m14 ; c2 d2 + paddd m6, m11 + paddd m5, m11 + paddd m6, m4 + pmaddwd m4, m2, m15 ; a3 b3 + paddd m5, m4 + pmaddwd m4, m3, m15 ; c3 d3 + paddd m6, m4 + psrad m5, 6 + psrad m6, 6 + packssdw m5, m6 + vpermd m5, m9, m5 + mova [tmpq], m5 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + lea r6d, [wq*8-64] + mov r5, srcq + mov r7, tmpq + lea r6d, [hq+r6*4] +.hv_w8_loop0: + vbroadcasti128 m7, [subpel_h_shufA] + movu xm4, [srcq+strideq*0] + vbroadcasti128 m8, [subpel_h_shufB] + movu xm5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m9, [subpel_h_shufC] + movu xm6, [srcq+strideq*0] + vbroadcasti128 m0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m4, m0, 0xf0 ; 0 3 + vinserti128 m5, [srcq+strideq*0], 1 ; 1 4 + vinserti128 m6, [srcq+strideq*1], 1 ; 2 5 + lea srcq, [srcq+strideq*2] + vinserti128 m0, [srcq+strideq*0], 1 ; 3 6 + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 + vpbroadcastd m7, [pw_8192] + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + pmulhrsw m0, m7 + pmulhrsw m4, m7 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + vpermq m7, m0, q3120 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vextracti128 [tmpq], m0, 1 ; not enough registers + movu xm0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti128 m0, [srcq+strideq*0], 1 ; 7 8 + pmaddwd m8, m1, m12 ; a0 + pmaddwd m9, m2, m12 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m13 ; a1 + pmaddwd m4, m13 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m14 ; a2 + pmaddwd m6, m14 ; b2 + paddd m8, m5 + paddd m9, m6 + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + vbroadcasti128 m5, [subpel_h_shufA] + HV_H_W8 m0, m5, m6, m7, m5, m6, m7 + vpbroadcastd m5, [pw_8192] + vpbroadcastd m7, [pd_32] + vbroadcasti128 m6, [tmpq] + pmulhrsw m0, m5 + paddd m8, m7 + paddd m9, m7 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, m15 ; a3 + paddd m8, m7 + pmaddwd m7, m6, m15 ; b3 + paddd m7, m9 + psrad m8, 6 + psrad m7, 6 + packssdw m8, m7 + vpermq m7, m8, q3120 + mova [tmpq+wq*0], xm7 + vextracti128 [tmpq+wq*2], m7, 1 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w8_loop + add r5, 8 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .hv_w8_loop0 + RET + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro REMAP_REG 2 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %xdefine r14_save r14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + %xdefine r14 r14_save + %undef r14_save + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%macro MC_8TAP_SCALED_H 8 ; dst, tmp[0-6] + movq xm%1, [srcq+ r4] + movq xm%2, [srcq+ r6] + movhps xm%1, [srcq+ r7] + movhps xm%2, [srcq+ r9] + vinserti128 m%1, [srcq+r10], 1 + vinserti128 m%2, [srcq+r11], 1 + vpbroadcastq m%5, [srcq+r13] + vpbroadcastq m%6, [srcq+ rX] + add srcq, ssq + movq xm%3, [srcq+ r4] + movq xm%4, [srcq+ r6] + movhps xm%3, [srcq+ r7] + movhps xm%4, [srcq+ r9] + vinserti128 m%3, [srcq+r10], 1 + vinserti128 m%4, [srcq+r11], 1 + vpbroadcastq m%7, [srcq+r13] + vpbroadcastq m%8, [srcq+ rX] + add srcq, ssq + vpblendd m%1, m%5, 0xc0 + vpblendd m%2, m%6, 0xc0 + vpblendd m%3, m%7, 0xc0 + vpblendd m%4, m%8, 0xc0 + pmaddubsw m%1, m15 + pmaddubsw m%2, m10 + pmaddubsw m%3, m15 + pmaddubsw m%4, m10 + phaddw m%1, m%2 + phaddw m%3, m%4 + phaddw m%1, m%3 + pmulhrsw m%1, m12 +%endmacro + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isprep 0 +cglobal put_8tap_scaled_8bpc, 4, 14, 16, 128, dst, ds, src, ss, w, h, mx, my, dx, dy + %xdefine base_reg r12 + %define rndshift 10 +%else + %assign isprep 1 +cglobal prep_8tap_scaled_8bpc, 4, 14, 16, 128, tmp, src, ss, w, h, mx, my, dx, dy + %define tmp_stridem qword [rsp+120] + %xdefine base_reg r11 + %define rndshift 6 +%endif + lea base_reg, [%1_8tap_scaled_8bpc_avx2] +%define base base_reg-%1_8tap_scaled_8bpc_avx2 + tzcnt wd, wm + vpbroadcastd m8, dxm +%if isprep && UNIX64 + movd xm14, mxd + vpbroadcastd m14, xm14 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 +%else + vpbroadcastd m14, mxm +%endif + mov dyd, dym +%ifidn %1, put + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %else + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %define dsm [rsp+112] + %define rX r1 + %define rXd r1d +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %else + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+112] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define rX r14 + %define rXd r14d +%endif + vpbroadcastd m10, [base+pd_0x3ff] + vpbroadcastd m12, [base+pw_8192] +%ifidn %1, put + vpbroadcastd m13, [base+pd_512] +%else + vpbroadcastd m13, [base+pd_32] +%endif + pxor m9, m9 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_avx2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0,1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*2] + movhps xm0, [srcq+ssq*1] + movhps xm1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*2], 1 + vpbroadcastq m2, [srcq+ssq*1] + vpbroadcastq m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + vpblendd m15, m7, 0xaa + vpblendd m0, m2, 0xc0 ; 0 1 4 5 + vpblendd m1, m3, 0xc0 ; 2 3 6 7 + pblendvb m15, m11, m8 + pshufb m0, m14 + pshufb m1, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + phaddw m0, m1 + pmulhrsw m0, m12 ; 0 1 2 3 4 5 6 7 + vextracti128 xm1, m0, 1 ; 4 5 6 7 + palignr xm2, xm1, xm0, 4 ; 1 2 3 4 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + pshufd xm4, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm4 ; 45 56 + punpckhwd xm4, xm1, xm4 ; 67 __ +.w2_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm11, r6q + pmovsxbw xm11, xm11 + pshufd xm8, xm11, q0000 + pshufd xm9, xm11, q1111 + pshufd xm10, xm11, q2222 + pshufd xm11, xm11, q3333 + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pmaddwd xm7, xm2, xm10 + pmaddwd xm8, xm4, xm11 + paddd xm5, xm6 + paddd xm7, xm8 + paddd xm5, xm13 + paddd xm5, xm7 + psrad xm5, 10 + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq], xm5, 0 + add dstq, dsq + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w2_loop + movq xm5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps xm3, xm0, q1032 ; 01 12 + shufps xm0, xm2, q1032 ; 23 34 + shufps xm2, xm4, q1032 ; 45 56 + pshufb xm5, xm14 + pmaddubsw xm5, xm15 + phaddw xm5, xm5 + pmulhrsw xm5, xm12 + palignr xm1, xm5, xm1, 12 + punpcklqdq xm1, xm1 ; 6 7 6 7 + punpcklwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +.w2_skip_line: + movhps xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xm3, xm0 ; 01 12 + mova xm0, xm2 ; 23 34 + pshufb xm5, xm14 + pmaddubsw xm5, xm15 + phaddw xm5, xm5 + pmulhrsw xm5, xm12 ; 6 7 6 7 + palignr xm1, xm5, xm1, 8 ; 4 5 6 7 + pshufd xm5, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm5 ; 45 56 + punpckhwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +%endif +.w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd xm15, xm0 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pinsrd xm15, [base+subpel_filters+r6*8+2], 1 + pcmpeqd m0, m9 + psrld m14, 10 + movu xm7, [srcq+ssq*0] + movu xm9, [srcq+ssq*1] + pinsrd xm15, [base+subpel_filters+r11*8+2], 2 + movu xm8, [srcq+ssq*2] + movu xm10, [srcq+ss3q ] + pinsrd xm15, [base+subpel_filters+r13*8+2], 3 + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m7, [srcq+ssq*0], 1 + vinserti128 m9, [srcq+ssq*1], 1 + vinserti128 m15, xm15, 1 + vinserti128 m8, [srcq+ssq*2], 1 + vinserti128 m10, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + pblendvb m15, m11, m0 + pshufb m7, m14 + pshufb m9, m14 + pshufb m8, m14 + pshufb m10, m14 + pmaddubsw m7, m15 + pmaddubsw m9, m15 + pmaddubsw m8, m15 + pmaddubsw m10, m15 + phaddw m7, m9 + phaddw m8, m10 + pmulhrsw m7, m12 ; 0 1 4 5 + pmulhrsw m8, m12 ; 2 3 6 7 + vextracti128 xm9, m7, 1 ; 4 5 + vextracti128 xm3, m8, 1 ; 6 7 + shufps xm4, xm7, xm8, q1032 ; 1 2 + shufps xm5, xm8, xm9, q1032 ; 3 4 + shufps xm6, xm9, xm3, q1032 ; 5 6 + psrldq xm11, xm3, 8 ; 7 _ + punpcklwd xm0, xm7, xm4 ; 01 + punpckhwd xm7, xm4 ; 12 + punpcklwd xm1, xm8, xm5 ; 23 + punpckhwd xm8, xm5 ; 34 + punpcklwd xm2, xm9, xm6 ; 45 + punpckhwd xm9, xm6 ; 56 + punpcklwd xm3, xm11 ; 67 + mova [rsp+0x00], xm7 + mova [rsp+0x10], xm8 + mova [rsp+0x20], xm9 +.w4_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm10, r6q + pmovsxbw xm10, xm10 + pshufd xm7, xm10, q0000 + pshufd xm8, xm10, q1111 + pshufd xm9, xm10, q2222 + pshufd xm10, xm10, q3333 + pmaddwd xm4, xm0, xm7 + pmaddwd xm5, xm1, xm8 + pmaddwd xm6, xm2, xm9 + pmaddwd xm7, xm3, xm10 + paddd xm4, xm5 + paddd xm6, xm7 + paddd xm4, xm13 + paddd xm4, xm6 + psrad xm4, rndshift + packssdw xm4, xm4 +%ifidn %1, put + packuswb xm4, xm4 + movd [dstq], xm4 + add dstq, dsq +%else + movq [tmpq], xm4 + add tmpq, 8 +%endif + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + movu xm4, [srcq] + test myd, 0x400 + jz .w4_skip_line + mova xm0, [rsp+0x00] + mova [rsp+0x00], xm1 + mova xm1, [rsp+0x10] + mova [rsp+0x10], xm2 + mova xm2, [rsp+0x20] + mova [rsp+0x20], xm3 + pshufb xm4, xm14 + pmaddubsw xm4, xm15 + phaddw xm4, xm4 + pmulhrsw xm4, xm12 + punpcklwd xm3, xm11, xm4 + mova xm11, xm4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu xm5, [srcq+ssq*1] + movu m6, [rsp+0x10] + pshufb xm4, xm14 + pshufb xm5, xm14 + pmaddubsw xm4, xm15 + pmaddubsw xm5, xm15 + movu [rsp+0x00], m6 + phaddw xm4, xm5 + pmulhrsw xm4, xm12 + punpcklwd xm9, xm11, xm4 + mova [rsp+0x20], xm9 + psrldq xm11, xm4, 8 + mova xm0, xm1 + mova xm1, xm2 + mova xm2, xm3 + punpcklwd xm3, xm4, xm11 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +.w8: + mov dword [rsp+48], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+48], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+48], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+48], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+48], 16 + movifprep tmp_stridem, 256 +.w_start: +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+72], t0d + mov [rsp+56], srcq + mov [rsp+64], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + jmp .hloop +.hloop_prep: + dec dword [rsp+48] + jz .ret + add qword [rsp+64], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp+16] + vpbroadcastd m15, [rsp+72] + pxor m9, m9 + mov srcq, [rsp+56] + mov r0q, [rsp+64] ; dstq / tmpq +.hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp+16], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + mova [rsp], xm14 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + mov myd, mym + mov dyd, dym + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + vbroadcasti128 m14, [base+wswap] +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm11, r6q + punpcklqdq xm11, xm11 + pmovsxbw m11, xm11 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pshufd m8, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m6, m2, m8 + pmaddwd m7, m3, m11 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+52], myd + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + jz .skip_line + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + add srcq, ssq + mov myd, [rsp+52] + mov dyd, dym + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, m10 + phaddw m4, m5 + pslld m5, m4, 16 + paddw m4, m5 + pmulhrsw m4, m12 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .vloop +.skip_line: + mova m0, m1 + mova m1, m2 + mova m2, m3 + vpbroadcastq m7, [srcq+r13] + vpbroadcastq m8, [srcq+ rX] + movq xm3, [srcq+ r4] + movq xm4, [srcq+ r6] + movhps xm3, [srcq+ r7] + movhps xm4, [srcq+ r9] + vinserti128 m3, [srcq+r10], 1 + vinserti128 m4, [srcq+r11], 1 + add srcq, ssq + movq xm5, [srcq+ r4] + movq xm6, [srcq+ r6] + movhps xm5, [srcq+ r7] + movhps xm6, [srcq+ r9] + vinserti128 m5, [srcq+r10], 1 + vinserti128 m6, [srcq+r11], 1 + vpbroadcastq m9, [srcq+r13] + vpbroadcastq m11, [srcq+ rX] + add srcq, ssq + mov myd, [rsp+52] + mov dyd, dym + vpblendd m3, m7, 0xc0 + vpblendd m4, m8, 0xc0 + vpblendd m5, m9, 0xc0 + vpblendd m6, m11, 0xc0 + pmaddubsw m3, m15 + pmaddubsw m4, m10 + pmaddubsw m5, m15 + pmaddubsw m6, m10 + phaddw m3, m4 + phaddw m5, m6 + psrld m4, m3, 16 + pslld m6, m5, 16 + paddw m3, m4 + paddw m5, m6 + pblendw m3, m5, 0xaa + pmulhrsw m3, m12 + jmp .vloop +.dy1: + movzx wd, word [base+%1_8tap_scaled_avx2_dy1_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy1_w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0-1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*2] + movhps xm0, [srcq+ssq*1] + movhps xm1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*2], 1 + vpbroadcastq m2, [srcq+ssq*1] + add srcq, ss3q + movq xm10, r4q + pmovsxbw xm10, xm10 + vpblendd m15, m7, 0xaa + pblendvb m15, m11, m8 + pshufd xm8, xm10, q0000 + pshufd xm9, xm10, q1111 + pshufd xm11, xm10, q3333 + pshufd xm10, xm10, q2222 + vpblendd m0, m2, 0xc0 + pshufb m1, m14 + pshufb m0, m14 + pmaddubsw m1, m15 + pmaddubsw m0, m15 + phaddw m0, m1 + pmulhrsw m0, m12 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 + pshufd xm4, xm1, q2121 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + punpcklwd xm2, xm1, xm4 ; 45 56 +.dy1_w2_loop: + movq xm1, [srcq+ssq*0] + movhps xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pmaddwd xm7, xm2, xm10 + mova xm3, xm0 + mova xm0, xm2 + paddd xm5, xm13 + paddd xm6, xm7 + pshufb xm1, xm14 + pmaddubsw xm1, xm15 + phaddw xm1, xm1 + pmulhrsw xm1, xm12 + palignr xm7, xm1, xm4, 12 + punpcklwd xm2, xm7, xm1 ; 67 78 + pmaddwd xm7, xm2, xm11 + mova xm4, xm1 + paddd xm5, xm6 + paddd xm5, xm7 + psrad xm5, rndshift + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +.dy1_w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + vpermq m8, m8, q3120 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r11d, xm15, 1 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + movu xm2, [srcq+ssq*0] + movu xm3, [srcq+ssq*2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pcmpeqd m8, m9 + psrld m14, 10 + pinsrd xm15, [base+subpel_filters+r11*8+2], 1 + vpblendd m7, [base+subpel_filters+r13*8+2-20], 0x20 + vinserti128 m2, [srcq+ssq*1], 1 + vinserti128 m3, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movu xm4, [srcq+ssq*0] + movu xm5, [srcq+ssq*2] + vinserti128 m4, [srcq+ssq*1], 1 + add srcq, ss3q + vpblendd m15, m7, 0x30 + punpcklqdq m15, m15 + pblendvb m15, m11, m8 + movq xm10, r4q + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + pshufb m2, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb xm5, xm14 + vpermq m2, m2, q3120 + vpermq m3, m3, q3120 + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m2, m3 + phaddw m4, m5 + pmulhrsw m2, m12 + pmulhrsw m4, m12 + palignr m5, m4, m2, 4 + pshufd m3, m4, q2121 + punpcklwd m0, m2, m5 ; 01 12 + punpckhwd m1, m2, m5 ; 23 34 + punpcklwd m2, m4, m3 ; 45 56 +.dy1_w4_loop: + movu xm11, [srcq+ssq*0] + vinserti128 m11, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + mova m0, m1 + mova m1, m2 + paddd m4, m13 + paddd m5, m6 + pshufb m11, m14 + vpermq m11, m11, q3120 + pmaddubsw m11, m15 + phaddw m11, m11 + pmulhrsw m11, m12 + palignr m6, m11, m3, 12 + punpcklwd m2, m6, m11 ; 67 78 + mova m3, m11 + pmaddwd m6, m2, m10 + paddd m4, m5 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + pshuflw xm4, xm4, q3120 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] +%else + pshufd xm4, xm4, q3120 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET +.dy1_w8: + mov dword [rsp+72], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+72], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+72], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+72], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+72], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+76], t0d + mov [rsp+80], srcq + mov [rsp+88], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+96], xm0 + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+72] + jz .ret + add qword [rsp+88], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp+32] + vpbroadcastd m15, [rsp+76] + pxor m9, m9 + mov srcq, [rsp+80] + mov r0q, [rsp+88] ; dstq / tmpq +.dy1_hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp+32], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + movq [rsp+64], xm14 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + movu [rsp], m10 + vpbroadcastd m8, [rsp+0x60] + vpbroadcastd m9, [rsp+0x64] + vpbroadcastd m10, [rsp+0x68] + vpbroadcastd m11, [rsp+0x6c] + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + vbroadcasti128 m14, [base+wswap] +.dy1_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + add srcq, ssq + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, [rsp] + phaddw m4, m5 + pslld m5, m4, 16 + paddw m4, m5 + pmulhrsw m4, m12 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .dy1_vloop +.dy2: + movzx wd, word [base+%1_8tap_scaled_avx2_dy2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy2_w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0-1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + vpbroadcastq m2, [srcq+ssq*1] + movhps xm0, [srcq+ssq*2] + vpbroadcastq m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vpblendd m15, m7, 0xaa + pblendvb m15, m11, m8 + movhps xm1, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + vpblendd m0, m2, 0x30 + vpblendd m1, m4, 0xc0 + vpblendd m0, m3, 0xc0 + pshufb m0, m14 + pshufb m1, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + movq xm11, r4q + pmovsxbw xm11, xm11 + phaddw m0, m1 + pmulhrsw m0, m12 ; 0 2 _ 4 1 3 _ 5 + pshufd xm8, xm11, q0000 + pshufd xm9, xm11, q1111 + pshufd xm10, xm11, q2222 + pshufd xm11, xm11, q3333 + pshufd m2, m0, q3110 ; 0 2 2 4 1 3 3 5 + vextracti128 xm1, m2, 1 + punpcklwd xm3, xm2, xm1 ; 01 23 + punpckhwd xm2, xm1 ; 23 45 +.dy2_w2_loop: + movq xm6, [srcq+ssq*0] + vpbroadcastq m7, [srcq+ssq*1] + movhps xm6, [srcq+ssq*2] + vpbroadcastq m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd xm4, xm3, xm8 + pmaddwd xm5, xm2, xm9 + vpblendd m6, m7, 0x30 + vpblendd m6, m1, 0xc0 + pshufb m6, m14 + pmaddubsw m6, m15 + phaddw m6, m6 + pmulhrsw m6, m12 + palignr m0, m6, m0, 8 + pshufd m2, m0, q3221 + vextracti128 xm1, m2, 1 + punpcklwd xm3, xm2, xm1 ; 45 67 + punpckhwd xm2, xm1 ; 67 89 + pmaddwd xm6, xm3, xm10 + pmaddwd xm7, xm2, xm11 + paddd xm4, xm5 + paddd xm4, xm13 + paddd xm6, xm7 + paddd xm4, xm6 + psrad xm4, rndshift + packssdw xm4, xm4 + packuswb xm4, xm4 + pextrw [dstq+dsq*0], xm4, 0 + pextrw [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +.dy2_w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pinsrd xm15, [base+subpel_filters+r6*8+2], 1 + pcmpeqd m8, m9 + psrld m14, 10 + movu xm0, [srcq+ssq*0] + movu xm2, [srcq+ssq*2] + pinsrd xm15, [base+subpel_filters+r11*8+2], 2 + movu xm1, [srcq+ssq*1] + movu xm3, [srcq+ss3q ] + pinsrd xm15, [base+subpel_filters+r13*8+2], 3 + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + vinserti128 m15, xm15, 1 + pshufb m14, m5 + paddb m14, m6 + vinserti128 m2, [srcq+ssq*0], 1 + vinserti128 m3, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pblendvb m15, m11, m8 + pshufb xm0, xm14 + pshufb m2, m14 + pshufb xm1, xm14 + pshufb m3, m14 + pmaddubsw xm0, xm15 + pmaddubsw m2, m15 + pmaddubsw xm1, xm15 + pmaddubsw m3, m15 + movq xm11, r4q + punpcklqdq xm11, xm11 + pmovsxbw m11, xm11 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 2 _ 4 + pmulhrsw m1, m12 ; 1 3 _ 5 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + punpcklwd xm2, xm0, xm1 + punpckhwd m1, m0, m1 ; 23 45 + vinserti128 m0, m2, xm1, 1 ; 01 23 +.dy2_w4_loop: + movu xm6, [srcq+ssq*0] + movu xm7, [srcq+ssq*1] + vinserti128 m6, [srcq+ssq*2], 1 + vinserti128 m7, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pshufb m6, m14 + pshufb m7, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + psrld m2, m6, 16 + pslld m3, m7, 16 + paddw m6, m2 + paddw m7, m3 + pblendw m6, m7, 0xaa ; 67 89 + pmulhrsw m6, m12 + paddd m4, m5 + vperm2i128 m0, m1, m6, 0x21 ; 45 67 + mova m1, m6 + pmaddwd m6, m0, m10 + pmaddwd m7, m1, m11 + paddd m4, m13 + paddd m6, m7 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET +.dy2_w8: + mov dword [rsp+40], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+40], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+40], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+40], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+40], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+64], t0d + mov [rsp+48], srcq + mov [rsp+56], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+40] + jz .ret + add qword [rsp+56], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp] + vpbroadcastd m15, [rsp+64] + pxor m9, m9 + mov srcq, [rsp+48] + mov r0q, [rsp+56] ; dstq / tmpq +.dy2_hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m11, [rsp+0x58] + vpbroadcastd m4, [rsp+0x5c] + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + SWAP m14, m4 +.dy2_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m14 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep + mova m0, m1 + mova m1, m2 + mova m2, m3 + movq xm3, [srcq+ r4] + movq xm4, [srcq+ r6] + movhps xm3, [srcq+ r7] + movhps xm4, [srcq+ r9] + vinserti128 m3, [srcq+r10], 1 + vinserti128 m4, [srcq+r11], 1 + vpbroadcastq m5, [srcq+r13] + vpbroadcastq m6, [srcq+ rX] + add srcq, ssq + vpblendd m3, m5, 0xc0 + vpblendd m4, m6, 0xc0 + pmaddubsw m3, m15 + pmaddubsw m4, m10 + phaddw m3, m4 + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + add srcq, ssq + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, m10 + phaddw m4, m5 + psrld m5, m3, 16 + pslld m6, m4, 16 + paddw m3, m5 + paddw m4, m6 + pblendw m3, m4, 0xaa + pmulhrsw m3, m12 + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_8bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, t0d + jmp mangle(private_prefix %+ _%1_8tap_scaled_8bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%else +DECLARE_REG_TMP 6, 8 +%endif + +%define PUT_8TAP_SCALED_FN FN put_8tap_scaled, +%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled, + +BILIN_SCALED_FN put +PUT_8TAP_SCALED_FN sharp, SHARP, SHARP +PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +BILIN_SCALED_FN prep +PREP_8TAP_SCALED_FN sharp, SHARP, SHARP +PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%macro WARP_V 5 ; dst, 02, 46, 13, 57 + ; Can be done using gathers, but that's terribly slow on many CPU:s + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm8, [filterq+myq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 ; a e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; b f + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm9, [filterq+myq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 ; c g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + shr tmp2d, 10 + shr tmp1d, 10 + punpcklwd m8, m0 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; d h + punpcklwd m0, m9, m0 + punpckldq m9, m8, m0 + punpckhdq m0, m8, m0 + punpcklbw m8, m11, m9 ; a0 a2 b0 b2 c0 c2 d0 d2 << 8 + punpckhbw m9, m11, m9 ; a4 a6 b4 b6 c4 c6 d4 d6 << 8 + pmaddwd m%2, m8 + pmaddwd m9, m%3 + punpcklbw m8, m11, m0 ; a1 a3 b1 b3 c1 c3 d1 d3 << 8 + punpckhbw m0, m11, m0 ; a5 a7 b5 b7 c5 c7 d5 d7 << 8 + pmaddwd m8, m%4 + pmaddwd m0, m%5 + paddd m%2, m9 + paddd m0, m8 + paddd m%1, m0, m%2 +%endmacro + +cglobal warp_affine_8x8t_8bpc, 0, 14, 0, tmp, ts +%if WIN64 + sub rsp, 0xa0 +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).main +.loop: + psrad m7, 13 + psrad m0, 13 + packssdw m7, m0 + pmulhrsw m7, m14 ; (x + (1 << 6)) >> 7 + vpermq m7, m7, q3120 + mova [tmpq+tsq*0], xm7 + vextracti128 [tmpq+tsq*2], m7, 1 + dec r4d + jz mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).end + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).main2 + lea tmpq, [tmpq+tsq*4] + jmp .loop + +cglobal warp_affine_8x8_8bpc, 0, 14, 0, dst, ds, src, ss, abcd, mx, tmp2, alpha, \ + beta, filter, tmp1, delta, my, gamma +%if WIN64 + sub rsp, 0xa0 + %assign xmm_regs_used 16 + %assign stack_size_padded 0xa0 + %assign stack_offset stack_offset+stack_size_padded +%endif + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m7, 18 + psrad m0, 18 + packusdw m7, m0 + pavgw m7, m11 ; (x + (1 << 10)) >> 11 + vextracti128 xm0, m7, 1 + packuswb xm7, xm0 + pshufd xm7, xm7, q3120 + movq [dstq+dsq*0], xm7 + movhps [dstq+dsq*1], xm7 + dec r4d + jg .loop +.end: + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov abcdq, r5m + mov mxd, r6m + movaps [rsp+stack_offset+0x10], xmm6 + movaps [rsp+stack_offset+0x20], xmm7 + movaps [rsp+0x28], xmm8 + movaps [rsp+0x38], xmm9 + movaps [rsp+0x48], xmm10 + movaps [rsp+0x58], xmm11 + movaps [rsp+0x68], xmm12 + movaps [rsp+0x78], xmm13 + movaps [rsp+0x88], xmm14 + movaps [rsp+0x98], xmm15 +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + mova m12, [warp_8x8_shufA] + mova m13, [warp_8x8_shufB] + vpbroadcastd m14, [pw_8192] + vpbroadcastd m15, [pd_32768] + pxor m11, m11 + lea filterq, [mc_warp_filter2] + lea tmp1q, [ssq*3+3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + 3 + sub betad, tmp2d ; beta -= alpha*3 + mov myd, r7m + call .h + psrld m1, m0, 16 + call .h + psrld m4, m0, 16 + call .h + pblendw m1, m0, 0xaa ; 02 + call .h + pblendw m4, m0, 0xaa ; 13 + call .h + psrld m2, m1, 16 + pblendw m2, m0, 0xaa ; 24 + call .h + psrld m5, m4, 16 + pblendw m5, m0, 0xaa ; 35 + call .h + psrld m3, m2, 16 + pblendw m3, m0, 0xaa ; 46 + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + add myd, 512+(64<<10) + mov r4d, 4 + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 +.main2: + call .h + psrld m6, m5, 16 + pblendw m6, m0, 0xaa ; 57 + WARP_V 7, 1, 3, 4, 6 + call .h + mova m1, m2 + mova m2, m3 + psrld m3, 16 + pblendw m3, m0, 0xaa ; 68 + WARP_V 0, 4, 6, 1, 3 + mova m4, m5 + mova m5, m6 + ret +ALIGN function_align +.h: + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + vbroadcasti128 m10, [srcq] + shr mxd, 10 + shr tmp1d, 10 + movq xm8, [filterq+mxq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 + shr tmp1d, 10 + movq xm9, [filterq+mxq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + punpcklqdq m8, m0 ; 0 1 4 5 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 + punpcklqdq m9, m0 ; 2 3 6 7 + pshufb m0, m10, m12 + pmaddubsw m0, m8 + pshufb m10, m13 + pmaddubsw m10, m9 + add srcq, ssq + phaddw m0, m10 + pmaddwd m0, m14 ; 17-bit intermediate, upshifted by 13 + paddd m0, m15 ; rounded 14-bit result in upper 16 bits of dword + ret + +%macro BIDIR_FN 1 ; op + %1 0 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + cmp hd, 8 + je .ret + %1 2 + lea dstq, [dstq+strideq*4] + vextracti128 xm1, m0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.ret: + RET +.w8_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*4] +.w8: + vextracti128 xm1, m0, 1 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq*4] +.w16: + vpermq m0, m0, q3120 + mova [dstq ], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq*2] +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + %1_INC_PTR 4 + %1 0 + add dstq, strideq +.w64: + vpermq m0, m0, q3120 + mova [dstq], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+32], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + %1 0 + add dstq, strideq +.w128: + vpermq m0, m0, q3120 + mova [dstq+0*32], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+1*32], m0 + %1_INC_PTR 8 + %1 -4 + vpermq m0, m0, q3120 + mova [dstq+2*32], m0 + %1 -2 + vpermq m0, m0, q3120 + mova [dstq+3*32], m0 + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + mova m0, [tmp1q+(%1+0)*32] + paddw m0, [tmp2q+(%1+0)*32] + mova m1, [tmp1q+(%1+1)*32] + paddw m1, [tmp2q+(%1+1)*32] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + packuswb m0, m1 +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*32 + add tmp2q, %1*32 +%endmacro + +cglobal avg_8bpc, 4, 7, 3, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg %+ SUFFIX %+ _table + lea r6, [avg %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m2, [base+pw_1024] + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m0, [tmp1q+(%1+0)*32] + psubw m2, m0, [tmp2q+(%1+0)*32] + mova m1, [tmp1q+(%1+1)*32] + psubw m3, m1, [tmp2q+(%1+1)*32] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg %+ SUFFIX %+ _table + lea r6, [w_avg %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + vpbroadcastw m4, r6m ; weight + movsxd wq, dword [r6+wq*4] + vpbroadcastd m5, [base+pw_2048] + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + pxor m0, m0 + mov tmp1q, tmp2q + psubw m4, m0, m4 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 + vpermq m3, [maskq+%1*16], q3120 + mova m0, [tmp2q+(%1+0)*32] + psubw m1, m0, [tmp1q+(%1+0)*32] + psubb m3, m4, m3 + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 + punpcklbw m2, m4, m3 ; -m << 9 + pmulhw m1, m2 + paddw m0, m1 + mova m1, [tmp2q+(%1+1)*32] + psubw m2, m1, [tmp1q+(%1+1)*32] + paddw m2, m2 + punpckhbw m3, m4, m3 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*16 + add tmp2q, %1*32 + add tmp1q, %1*32 +%endmacro + +cglobal mask_8bpc, 4, 8, 6, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask %+ SUFFIX %+ _table + lea r7, [mask %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + vpbroadcastd m5, [base+pw_2048] + pxor m4, m4 + add wq, r7 + BIDIR_FN MASK + +%macro W_MASK 4-5 0 ; dst, mask, tmp_offset[1-2], 4:4:4 + mova m%1, [tmp1q+32*%3] + mova m1, [tmp2q+32*%3] + psubw m1, m%1 + pabsw m%2, m1 + psubusw m%2, m6, m%2 + psrlw m%2, 8 ; 64 - m + psllw m2, m%2, 10 + pmulhw m1, m2 + paddw m%1, m1 + mova m1, [tmp1q+32*%4] + mova m2, [tmp2q+32*%4] + psubw m2, m1 + pabsw m3, m2 + psubusw m3, m6, m3 + psrlw m3, 8 +%if %5 + packuswb m%2, m3 + psubb m%2, m5, m%2 + vpermq m%2, m%2, q3120 +%else + phaddw m%2, m3 +%endif + psllw m3, 10 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m%1, m7 + pmulhrsw m1, m7 + packuswb m%1, m1 +%endmacro + +cglobal blend_8bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx2_table + lea r6, [blend_avx2_table] + tzcnt wd, wm + movifnidn maskq, maskmp + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m4, [base+pb_64] + vpbroadcastd m5, [base+pw_512] + sub tmpq, maskq + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + vpbroadcastd xm1, [dstq+dsq*2] + pinsrd xm1, [dstq+r6 ], 3 + mova xm6, [maskq] + psubb xm3, xm4, xm6 + punpcklbw xm2, xm3, xm6 + punpckhbw xm3, xm6 + mova xm6, [maskq+tmpq] + add maskq, 4*4 + punpcklbw xm0, xm6 + punpckhbw xm1, xm6 + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm3 + pmulhrsw xm0, xm5 + pmulhrsw xm1, xm5 + packuswb xm0, xm1 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + pextrd [dstq+dsq*2], xm0, 2 + pextrd [dstq+r6 ], xm0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + movq xm1, [dstq+dsq*0] + movhps xm1, [dstq+dsq*1] + vpbroadcastq m2, [dstq+dsq*2] + vpbroadcastq m3, [dstq+r6 ] + mova m0, [maskq] + mova m6, [maskq+tmpq] + add maskq, 8*4 + vpblendd m1, m2, 0x30 + vpblendd m1, m3, 0xc0 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + movq [dstq+dsq*2], xm1 + movhps [dstq+r6 ], xm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + mova m0, [maskq] + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + mova m6, [maskq+tmpq] + add maskq, 16*2 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16 + RET +ALIGN function_align +.w32: + mova m0, [maskq] + mova m1, [dstq] + mova m6, [maskq+tmpq] + add maskq, 32 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_avx2_table + lea r5, [blend_v_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_avx2_table + jmp wq +.w2: + vpbroadcastd xm2, [maskq+2*2] +.w2_s0_loop: + movd xm0, [dstq+dsq*0] + pinsrw xm0, [dstq+dsq*1], 1 + movd xm1, [tmpq] + add tmpq, 2*2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_s0_loop + RET +ALIGN function_align +.w4: + vpbroadcastq xm2, [maskq+4*2] +.w4_loop: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + movq xm1, [tmpq] + add tmpq, 4*2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova xm3, [maskq+8*2] +.w8_loop: + movq xm0, [dstq+dsq*0] + vpbroadcastq xm1, [dstq+dsq*1] + mova xm2, [tmpq] + add tmpq, 8*2 + punpcklbw xm0, xm2 + punpckhbw xm1, xm2 + pmaddubsw xm0, xm3 + pmaddubsw xm1, xm3 + pmulhrsw xm0, xm5 + pmulhrsw xm1, xm5 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m3, [maskq+16*2] + vbroadcasti128 m4, [maskq+16*3] +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + mova m2, [tmpq] + add tmpq, 16*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + mova xm3, [maskq+16*4] + vinserti128 m3, [maskq+16*6], 1 + mova xm4, [maskq+16*5] + vinserti128 m4, [maskq+16*7], 1 +.w32_loop: + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .w32_loop + RET + +cglobal blend_h_8bpc, 4, 7, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_h_avx2_table + lea r5, [blend_h_avx2_table] + mov r6d, wd + tzcnt wd, wd + mov hd, hm + movsxd wq, dword [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xm0, [dstq+dsq*0] + pinsrw xm0, [dstq+dsq*1], 1 + movd xm2, [maskq+hq*2] + movd xm1, [tmpq] + add tmpq, 2*2 + punpcklwd xm2, xm2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +ALIGN function_align +.w4: + mova xm3, [blend_shuf] +.w4_loop: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + movd xm2, [maskq+hq*2] + movq xm1, [tmpq] + add tmpq, 4*2 + pshufb xm2, xm3 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +ALIGN function_align +.w8: + vbroadcasti128 m4, [blend_shuf] + shufpd m4, m4, 0x03 +.w8_loop: + vpbroadcastq m1, [dstq+dsq*0] + movq xm0, [dstq+dsq*1] + vpblendd m0, m1, 0x30 + vpbroadcastd m3, [maskq+hq*2] + movq xm1, [tmpq+8*1] + vinserti128 m1, [tmpq+8*0], 1 + add tmpq, 8*2 + pshufb m3, m4 + punpcklbw m0, m1 + pmaddubsw m0, m3 + pmulhrsw m0, m5 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movhps [dstq+dsq*0], xm0 + movq [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m4, [blend_shuf] + shufpd m4, m4, 0x0c +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + vpbroadcastd m3, [maskq+hq*2] + mova m2, [tmpq] + add tmpq, 16*2 + pshufb m3, m4 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +ALIGN function_align +.w32: ; w32/w64/w128 + sub dsq, r6 +.w32_loop0: + vpbroadcastw m3, [maskq+hq*2] + mov wd, r6d +.w32_loop: + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 32 + sub wd, 32 + jg .w32_loop + add dstq, dsq + inc hq + jl .w32_loop0 + RET + +cglobal emu_edge_8bpc, 10, 13, 1, bw, bh, iw, ih, x, y, dst, dstride, src, sstride, \ + bottomext, rightext + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor r12d, r12d + lea r10, [ihq-1] + cmp yq, ihq + cmovs r10, yq + test yq, yq + cmovs r10, r12 + imul r10, sstrideq + add srcq, r10 + + ; ref += iclip(x, 0, iw - 1) + lea r10, [iwq-1] + cmp xq, iwq + cmovs r10, xq + test xq, xq + cmovs r10, r12 + add srcq, r10 + + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) + lea bottomextq, [yq+bhq] + sub bottomextq, ihq + lea r3, [bhq-1] + cmovs bottomextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, x, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, r12 + cmp bottomextq, bhq + cmovns bottomextq, r3 + cmp topextq, bhq + cmovg topextq, r3 + + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + lea rightextq, [xq+bwq] + sub rightextq, iwq + lea r2, [bwq-1] + cmovs rightextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, leftext, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, r12 + cmp rightextq, bwq + cmovns rightextq, r2 + cmp leftextq, bwq + cmovns leftextq, r2 + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, topext, \ + dst, dstride, src, sstride, bottomext, rightext + + ; center_h = bh - top_ext - bottom_ext + lea r3, [bottomextq+topextq] + sub centerhq, r3 + + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq + imul r2, dstrideq + add dstq, r2 + mov r9m, dstq + + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq + lea r3, [rightextq+leftextq] + sub centerwq, r3 + +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix +.v_loop_%3: +%if %1 + ; left extension + xor r3, r3 + vpbroadcastb m0, [srcq] +.left_loop_%3: + mova [dstq+r3], m0 + add r3, 32 + cmp r3, leftextq + jl .left_loop_%3 + + ; body + lea r12, [dstq+leftextq] +%endif + xor r3, r3 +.body_loop_%3: + movu m0, [srcq+r3] +%if %1 + movu [r12+r3], m0 +%else + movu [dstq+r3], m0 +%endif + add r3, 32 + cmp r3, centerwq + jl .body_loop_%3 + +%if %2 + ; right extension +%if %1 + add r12, centerwq +%else + lea r12, [dstq+centerwq] +%endif + xor r3, r3 + vpbroadcastb m0, [srcq+centerwq-1] +.right_loop_%3: + movu [r12+r3], m0 + add r3, 32 + cmp r3, rightextq + jl .right_loop_%3 + +%endif + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 +%endmacro + + test leftextq, leftextq + jnz .need_left_ext + test rightextq, rightextq + jnz .need_right_ext + v_loop 0, 0, 0 + jmp .body_done + +.need_left_ext: + test rightextq, rightextq + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: + ; bottom edge extension + test bottomextq, bottomextq + jz .top + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 +.bottom_x_loop: + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, bottomextq +.bottom_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .bottom_y_loop + add r1, 32 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end + mov srcq, r9m + mov dstq, dstm + xor r1, r1 +.top_x_loop: + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, topextq +.top_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .top_y_loop + add r1, 32 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +cglobal resize_8bpc, 6, 12, 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ + + vpbroadcastd xm3, [base+pw_m256] + vpbroadcastd m7, [base+pd_63] + vbroadcasti128 m15, [base+pb_8x0_8x8] + pmaddwd m2, m5, [base+rescale_mul] ; dx*[0,1,2,3,4,5,6,7] + pslld m5, 3 ; dx*8 + pslld m6, 14 + paddd m8, m2 ; mx+[0..7]*dx + pxor m2, m2 + + ; m2 = 0, m3 = pmulhrsw constant for x=(x+64)>>7 + ; m8 = mx+[0..7]*dx, m5 = dx*8, m6 = src_w, m7 = 0x3f, m15=0,8 + +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx + +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + pand m9, m7 ; filter offset (masked) + + ; load source pixels - this ugly code is vpgatherdq emulation since + ; directly using vpgatherdq on Haswell is quite a bit slower :( + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vextracti128 xm0, m0, 1 + movq xm12, [srcq+r8] + movq xm13, [srcq+r10] + movhps xm12, [srcq+r9] + movhps xm13, [srcq+r11] + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vinserti128 m12, [srcq+r8], 1 + vinserti128 m13, [srcq+r10], 1 + vpbroadcastq m10, [srcq+r9] + vpbroadcastq m11, [srcq+r11] + vpblendd m12, m10, 11000000b + vpblendd m13, m11, 11000000b + + ; if no emulation is required, we don't need to shuffle or emulate edges + ; this also saves 2 quasi-vpgatherdqs + vptest m1, m1 + jz .filter + + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vextracti128 xm1, m1, 1 + movq xm14, [base+resize_shuf+4+r8] + movq xm0, [base+resize_shuf+4+r10] + movhps xm14, [base+resize_shuf+4+r9] + movhps xm0, [base+resize_shuf+4+r11] + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vinserti128 m14, [base+resize_shuf+4+r8], 1 + vinserti128 m0, [base+resize_shuf+4+r10], 1 + vpbroadcastq m10, [base+resize_shuf+4+r9] + vpbroadcastq m11, [base+resize_shuf+4+r11] + vpblendd m14, m10, 11000000b + vpblendd m0, m11, 11000000b + + paddb m14, m15 + paddb m0, m15 + pshufb m12, m14 + pshufb m13, m0 + +.filter: + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vextracti128 xm9, m9, 1 + movq xm10, [base+resize_filter+r8*8] + movq xm11, [base+resize_filter+r10*8] + movhps xm10, [base+resize_filter+r9*8] + movhps xm11, [base+resize_filter+r11*8] + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vinserti128 m10, [base+resize_filter+r8*8], 1 + vinserti128 m11, [base+resize_filter+r10*8], 1 + vpbroadcastq m14, [base+resize_filter+r9*8] + vpbroadcastq m1, [base+resize_filter+r11*8] + vpblendd m10, m14, 11000000b + vpblendd m11, m1, 11000000b + + pmaddubsw m12, m10 + pmaddubsw m13, m11 + phaddw m12, m13 + vextracti128 xm13, m12, 1 + phaddsw xm12, xm13 + pmulhrsw xm12, xm3 ; x=(x+64)>>7 + packuswb xm12, xm12 + movq [dstq+xq], xm12 + + paddd m4, m5 + add xd, 8 + cmp xd, dst_wd + jl .loop_x + + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +cglobal w_mask_420_8bpc, 4, 8, 14, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx2_table + lea r7, [w_mask_420_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + pmovzxbd m9, [base+deint_shuf4] + vpbroadcastd m8, [base+wm_420_sign+r6*4] ; 258 - sign + add wq, r7 + W_MASK 0, 4, 0, 1 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + jg .w4_h16 +.w4_end: + vextracti128 xm0, m4, 1 + vpblendd xm1, xm4, xm0, 0x05 + vpblendd xm4, xm0, 0x0a + pshufd xm1, xm1, q2301 + psubw xm4, xm8, xm4 + psubw xm4, xm1 + psrlw xm4, 2 + packuswb xm4, xm4 + movq [maskq], xm4 + RET +.w4_h16: + W_MASK 0, 5, 2, 3 + lea dstq, [dstq+strideq*4] + phaddd m4, m5 + vextracti128 xm1, m0, 1 + psubw m4, m8, m4 + psrlw m4, 2 + vpermd m4, m9, m4 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq], xm4 + RET +.w8_loop: + add tmp1q, 2*32 + add tmp2q, 2*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 8 +.w8: + vextracti128 xm2, m4, 1 + vextracti128 xm1, m0, 1 + psubw xm4, xm8, xm4 + psubw xm4, xm2 + psrlw xm4, 2 + packuswb xm4, xm4 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + movq [maskq], xm4 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + W_MASK 0, 5, 2, 3 + punpckhqdq m1, m4, m5 + punpcklqdq m4, m5 + psubw m1, m8, m1 + psubw m1, m4 + psrlw m1, 2 + vpermq m0, m0, q3120 + packuswb m1, m1 + vpermd m1, m9, m1 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + mova [maskq], xm1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*2] + add maskq, 16 +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + W_MASK 0, 5, 2, 3 + psubw m4, m8, m4 + psubw m4, m5 + psrlw m4, 2 + vpermq m0, m0, q3120 + packuswb m4, m4 + vpermd m4, m9, m4 + mova [dstq+strideq*1], m0 + mova [maskq], xm4 + sub hd, 2 + jg .w32_loop + RET +.w64_loop_even: + psubw m10, m8, m4 + psubw m11, m8, m5 + dec hd +.w64_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + add dstq, strideq +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + test hd, 1 + jz .w64_loop_even + psubw m4, m10, m4 + psubw m5, m11, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq], m4 + add maskq, 32 + dec hd + jg .w64_loop + RET +.w128_loop_even: + psubw m12, m8, m4 + psubw m13, m8, m5 + dec hd +.w128_loop: + W_MASK 0, 4, 0, 1 + add dstq, strideq +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + add tmp1q, 8*32 + add tmp2q, 8*32 + test hd, 1 + jz .w128_even + psubw m4, m10, m4 + psubw m5, m11, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq+32*0], m4 + jmp .w128_odd +.w128_even: + psubw m10, m8, m4 + psubw m11, m8, m5 +.w128_odd: + W_MASK 0, 4, -4, -3 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + W_MASK 0, 5, -2, -1 + vpermq m0, m0, q3120 + mova [dstq+32*3], m0 + test hd, 1 + jz .w128_loop_even + psubw m4, m12, m4 + psubw m5, m13, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq+32*1], m4 + add maskq, 64 + dec hd + jg .w128_loop + RET + +cglobal w_mask_422_8bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx2_table + lea r7, [w_mask_422_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + pxor m9, m9 + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + pmovzxbd m10, [base+deint_shuf4] + vpbroadcastd m8, [base+wm_422_sign+r6*4] ; 128 - sign + add wq, r7 + mov maskq, maskmp + W_MASK 0, 4, 0, 1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + jg .w4_h16 +.w4_end: + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + psubb xm5, xm8, xm4 + pavgb xm5, xm9 + pshufd xm5, xm5, q3120 + mova [maskq], xm5 + RET +.w4_h16: + W_MASK 0, 5, 2, 3 + lea dstq, [dstq+strideq*4] + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermd m5, m10, m5 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq], m5 + RET +.w8_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8: + vextracti128 xm5, m4, 1 + vextracti128 xm1, m0, 1 + packuswb xm4, xm5 + psubb xm5, xm8, xm4 + pavgb xm5, xm9 + pshufd xm5, xm5, q3120 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + mova [maskq], xm5 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + mova [maskq], m5 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+strideq*1], m0 + mova [maskq], m5 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + add dstq, strideq + add maskq, 32 +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*1], m0 + mova [maskq], m5 + dec hd + jg .w64_loop + RET +.w128_loop: + add tmp1q, 32*8 + add tmp2q, 32*8 + W_MASK 0, 4, 0, 1 + add dstq, strideq + add maskq, 32*2 +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*1], m0 + mova [maskq+32*0], m5 + W_MASK 0, 4, 4, 5 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + W_MASK 0, 5, 6, 7 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*3], m0 + mova [maskq+32*1], m5 + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 8, 8, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx2_table + lea r7, [w_mask_444_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m5, [base+pb_64] + vpbroadcastd m7, [base+pw_2048] + add wq, r7 + W_MASK 0, 4, 0, 1, 1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + mova [maskq+32*0], m4 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + je .w4_end + W_MASK 0, 4, 2, 3, 1 + lea dstq, [dstq+strideq*4] + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq+32*1], m4 +.w4_end: + RET +.w8_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w8: + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + mova [maskq], m4 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [maskq], m4 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32 +.w32: + vpermq m0, m0, q3120 + mova [dstq], m0 + mova [maskq], m4 + dec hd + jg .w32_loop + RET +.w64_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32*2 +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + mova [maskq+32*0], m4 + W_MASK 0, 4, 2, 3, 1 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + mova [maskq+32*1], m4 + dec hd + jg .w64_loop + RET +.w128_loop: + add tmp1q, 32*8 + add tmp2q, 32*8 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32*4 +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + mova [maskq+32*0], m4 + W_MASK 0, 4, 2, 3, 1 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + mova [maskq+32*1], m4 + W_MASK 0, 4, 4, 5, 1 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + mova [maskq+32*2], m4 + W_MASK 0, 4, 6, 7, 1 + vpermq m0, m0, q3120 + mova [dstq+32*3], m0 + mova [maskq+32*3], m4 + dec hd + jg .w128_loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4538 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +obmc_masks: +pw_512: times 2 dw 512 + ; 2 + db 45, 19, 64, 0 + ; 4 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + db 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0 + +warp_8x8_permA: db 4, 5, 6, 7, 16, 17, 18, 19, 5, 6, 7, 8, 17, 18, 19, 20 + db 6, 7, 8, 9, 18, 19, 20, 21, 7, 8, 9, 10, 19, 20, 21, 22 + db 8, 9, 10, 11, 20, 21, 22, 23, 9, 10, 11, 12, 21, 22, 23, 24 + db 10, 11, 12, 13, 22, 23, 24, 25, 11, 12, 13, 14, 23, 24, 25, 26 +warp_8x8_permB: db 0, 1, 2, 3, 20, 21, 22, 23, 1, 2, 3, 4, 21, 22, 23, 24 + db 2, 3, 4, 5, 22, 23, 24, 25, 3, 4, 5, 6, 23, 24, 25, 26 + db 4, 5, 6, 7, 24, 25, 26, 27, 5, 6, 7, 8, 25, 26, 27, 28 + db 6, 7, 8, 9, 26, 27, 28, 29, 7, 8, 9, 10, 27, 28, 29, 30 +warp_8x8_permC: db -1, 0, -1, 1, -1, 8, -1, 9, -1, 4, -1, 5, -1, 12, -1, 13 +warp_8x8_permD: db -1, 2, -1, 3, -1, 10, -1, 11, -1, 6, -1, 7, -1, 14, -1, 15 +pd_0to7: dd 0, 1, 2, 3, 4, 5, 6, 7 +warp_8x8_hpack: db 3, 11, 3, 11, 35, 43, 35, 43 +pd_16384: dd 16384 +pd_262144: dd 262144 +warp_8x8_end: db 0, 4, 16, 20, 32, 36, 48, 52, 2, 6, 18, 22, 34, 38, 50, 54 +warp_8x8t_end: db 2, 3, 10, 11, 18, 19, 26, 27, 34, 35, 42, 43, 50, 51, 58, 59 + db 6, 7, 14, 15, 22, 23, 30, 31, 38, 39, 46, 47, 54, 55, 62, 63 +bidir_sctr_w4: dd 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +wm_420_perm4: db 1, 3, 9, 11, 5, 7, 13, 15, 17, 19, 25, 27, 21, 23, 29, 31 + db 33, 35, 41, 43, 37, 39, 45, 47, 49, 51, 57, 59, 53, 55, 61, 63 + db 0, 2, 8, 10, 4, 6, 12, 14, 16, 18, 24, 26, 20, 22, 28, 30 + db 32, 34, 40, 42, 36, 38, 44, 46, 48, 50, 56, 58, 52, 54, 60, 62 +wm_420_perm8: db 1, 3, 17, 19, 5, 7, 21, 23, 9, 11, 25, 27, 13, 15, 29, 31 + db 33, 35, 49, 51, 37, 39, 53, 55, 41, 43, 57, 59, 45, 47, 61, 63 + db 0, 2, 16, 18, 4, 6, 20, 22, 8, 10, 24, 26, 12, 14, 28, 30 + db 32, 34, 48, 50, 36, 38, 52, 54, 40, 42, 56, 58, 44, 46, 60, 62 +wm_420_perm16: db 1, 3, 33, 35, 5, 7, 37, 39, 9, 11, 41, 43, 13, 15, 45, 47 + db 17, 19, 49, 51, 21, 23, 53, 55, 25, 27, 57, 59, 29, 31, 61, 63 + db 0, 2, 32, 34, 4, 6, 36, 38, 8, 10, 40, 42, 12, 14, 44, 46 + db 16, 18, 48, 50, 20, 22, 52, 54, 24, 26, 56, 58, 28, 30, 60, 62 +wm_420_mask: db 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63 + db 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127 + db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +wm_422_mask: db 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62 + db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 66, 70, 74, 78, 82, 86, 90, 94, 98,102,106,110,114,118,122,126 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +wm_444_mask: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 +bilin_h_perm16: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 + db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15 + db 33, 32, 34, 33, 35, 34, 36, 35, 37, 36, 38, 37, 39, 38, 40, 39 + db 41, 40, 42, 41, 43, 42, 44, 43, 45, 44, 46, 45, 47, 46, 48, 47 +bilin_h_perm32: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 + db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15 + db 17, 16, 18, 17, 19, 18, 20, 19, 21, 20, 22, 21, 23, 22, 24, 23 + db 25, 24, 26, 25, 27, 26, 28, 27, 29, 28, 30, 29, 31, 30, 32, 31 +bilin_v_perm8: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7 + db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23 + db 32, 80, 33, 81, 34, 82, 35, 83, 36, 84, 37, 85, 38, 86, 39, 87 + db 64, 32, 65, 33, 66, 34, 67, 35, 68, 36, 69, 37, 70, 38, 71, 39 +bilin_v_perm16: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7 + db 24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15 + db 64, 16, 65, 17, 66, 18, 67, 19, 68, 20, 69, 21, 70, 22, 71, 23 + db 72, 24, 73, 25, 74, 26, 75, 27, 76, 28, 77, 29, 78, 30, 79, 31 +bilin_v_perm32: db 64, 0, 65, 1, 66, 2, 67, 3, 68, 4, 69, 5, 70, 6, 71, 7 + db 72, 8, 73, 9, 74, 10, 75, 11, 76, 12, 77, 13, 78, 14, 79, 15 + db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23 + db 88, 24, 89, 25, 90, 26, 91, 27, 92, 28, 93, 29, 94, 30, 95, 31 +bilin_v_perm64: dq 0, 4, 1, 5, 2, 6, 3, 7 +spel_h_perm16a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 + db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38 + db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46 +spel_h_perm16b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 + db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18 + db 36, 37, 38, 39, 37, 38, 39, 40, 38, 39, 40, 41, 39, 40, 41, 42 + db 44, 45, 46, 47, 45, 46, 47, 48, 46, 47, 48, 49, 47, 48, 49, 50 +spel_h_perm16c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46 + db 48, 49, 50, 51, 49, 50, 51, 52, 50, 51, 52, 53, 51, 52, 53, 54 +spel_h_perm32a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 + db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30 +spel_h_perm32b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 + db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18 + db 20, 21, 22, 23, 21, 22, 23, 24, 22, 23, 24, 25, 23, 24, 25, 26 + db 28, 29, 30, 31, 29, 30, 31, 32, 30, 31, 32, 33, 31, 32, 33, 34 +spel_h_perm32c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30 + db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38 +spel_v_perm16: db 32, 0, 33, 1, 34, 2, 35, 3, 36, 4, 37, 5, 38, 6, 39, 7 + db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 + db 40, 16, 41, 17, 42, 18, 43, 19, 44, 20, 45, 21, 46, 22, 47, 23 + db 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31 +spel_v_perm32: db 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39 + db 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47 + db 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55 + db 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63 +spel_hv_perm4a: db 8, 9, 16, 17, 10, 11, 18, 19, 12, 13, 20, 21, 14, 15, 22, 23 + db 16, 17, 24, 25, 18, 19, 26, 27, 20, 21, 28, 29, 22, 23, 30, 31 +spel_hv_perm4b: db 24, 25, 32, 33, 26, 27, 34, 35, 28, 29, 36, 37, 30, 31, 38, 39 + db 32, 33, 40, 41, 34, 35, 42, 43, 36, 37, 44, 45, 38, 39, 46, 47 +spel_hv_perm4c: db 40, 41, 48, 49, 42, 43, 50, 51, 44, 45, 52, 53, 46, 47, 54, 55 + db 48, 49, 56, 57, 50, 51, 58, 59, 52, 53, 60, 61, 54, 55, 62, 63 +spel_hv_perm4d: db 18, 19, 0, 1, 22, 23, 4, 5, 26, 27, 8, 9, 30, 31, 12, 13 + db 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29 +spel_hv_perm8a: db 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 + db 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 + db 16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39 + db 24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47 +spel_hv_perm8b: db 32, 33, 48, 49, 34, 35, 50, 51, 36, 37, 52, 53, 38, 39, 54, 55 + db 40, 41, 56, 57, 42, 43, 58, 59, 44, 45, 60, 61, 46, 47, 62, 63 + db 48, 49, 64, 65, 50, 51, 66, 67, 52, 53, 68, 69, 54, 55, 70, 71 + db 56, 57, 72, 73, 58, 59, 74, 75, 60, 61, 76, 77, 62, 63, 78, 79 +spel_hv_perm8c: db 34, 35, 0, 1, 38, 39, 4, 5, 42, 43, 8, 9, 46, 47, 12, 13 + db 50, 51, 16, 17, 54, 55, 20, 21, 58, 59, 24, 25, 62, 63, 28, 29 + db 0, 1, 32, 33, 4, 5, 36, 37, 8, 9, 40, 41, 12, 13, 44, 45 + db 16, 17, 48, 49, 20, 21, 52, 53, 24, 25, 56, 57, 28, 29, 60, 61 +spel_hv_end16: db 1, 3, 17, 19, 5, 7, 21, 23, 33, 35, 49, 51, 37, 39, 53, 55 + db 9, 11, 25, 27, 13, 15, 29, 31, 41, 43, 57, 59, 45, 47, 61, 63 +spel_hv_perm16a:db 0, 1, 2, 3, 32, 33, 34, 35, 1, 2, 3, 4, 33, 34, 35, 36 + db 2, 3, 4, 5, 34, 35, 36, 37, 3, 4, 5, 6, 35, 36, 37, 38 +spel_hv_perm16c:db 8, 9, 10, 11, 40, 41, 42, 43, 9, 10, 11, 12, 41, 42, 43, 44 + db 10, 11, 12, 13, 42, 43, 44, 45, 11, 12, 13, 14, 43, 44, 45, 46 + db 16, 17, 18, 19, 48, 49, 50, 51, 17, 18, 19, 20, 49, 50, 51, 52 + db 18, 19, 20, 21, 50, 51, 52, 53, 19, 20, 21, 22, 51, 52, 53, 54 +spel_hv_perm16b:db 4, 5, 6, 7, 36, 37, 38, 39, 5, 6, 7, 8, 37, 38, 39, 40 + db 6, 7, 8, 9, 38, 39, 40, 41, 7, 8, 9, 10, 39, 40, 41, 42 + db 12, 13, 14, 15, 44, 45, 46, 47, 13, 14, 15, 16, 45, 46, 47, 48 + db 14, 15, 16, 17, 46, 47, 48, 49, 15, 16, 17, 18, 47, 48, 49, 50 +spel_hv_perm16d:db 0, 1, 2, 3, 1, 2, 3, 4, 4, 5, 6, 7, 5, 6, 7, 8 + db 2, 3, 4, 5, 3, 4, 5, 6, 6, 7, 8, 9, 7, 8, 9, 10 + db 8, 9, 10, 11, 9, 10, 11, 12, 12, 13, 14, 15, 13, 14, 15, 16 + db 10, 11, 12, 13, 11, 12, 13, 14, 14, 15, 16, 17, 15, 16, 17, 18 +spel_hv_perm16e:db 4, 5, 6, 7, 5, 6, 7, 8, 8, 9, 10, 11, 9, 10, 11, 12 + db 6, 7, 8, 9, 7, 8, 9, 10, 10, 11, 12, 13, 11, 12, 13, 14 + db 12, 13, 14, 15, 13, 14, 15, 16, 16, 17, 18, 19, 17, 18, 19, 20 + db 14, 15, 16, 17, 15, 16, 17, 18, 18, 19, 20, 21, 19, 20, 21, 22 +spel_hv_end: db 1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, 49, 51, 53, 55 +deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +bilin_h_shuf4: db 1, 0, 2, 1, 3, 2, 4, 3, 9, 8, 10, 9, 11, 10, 12, 11 +bilin_h_shuf8: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 +resize_permA: dd 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 +resize_permB: dd 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 +resize_permC: dd 0, 4, 8, 12 +pb_02461357: db 0, 2, 4, 6, 1, 3, 5, 7 + +wm_420_perm64: dq 0xfedcba9876543210 +wm_sign: dd 0x40804080, 0xc0c0c0c0, 0x40404040 + +pb_8x0_8x8: times 8 db 0 + times 8 db 8 +pb_127: times 4 db 127 +pw_m128 times 2 dw -128 +pw_m256: times 2 dw -256 +pw_1024: times 2 dw 1024 +pw_2048: times 2 dw 2048 +pw_6903: times 2 dw 6903 +pw_8192: times 2 dw 8192 +pd_32: dd 32 +pd_34: dd 34 +pd_63: dd 63 +pd_512: dd 512 +pd_32768: dd 32768 + +%define pb_m64 (wm_sign+4) +%define pb_64 (wm_sign+8) +%define pd_2 (pd_0to7+8) + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) +cextern mc_warp_filter +cextern resize_filter + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx512icl mangle(private_prefix %+ _put_bilin_8bpc_avx512icl.put) +%xdefine prep_avx512icl mangle(private_prefix %+ _prep_bilin_8bpc_avx512icl.prep) + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +BASE_JMP_TABLE put, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx512icl, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx512icl, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx512icl, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx512icl, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx512icl, 7, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx512icl, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx512icl, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx512icl, 2, 4, 8, 16, 32, 64, 128 + +SECTION .text + +%macro WRAP_YMM 1+ +INIT_YMM cpuname + %1 +INIT_ZMM cpuname +%endmacro + +INIT_ZMM avx512icl +cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + lea r7, [put_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + movzx r6d, word [srcq+ssq*0] + movzx r7d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6w + mov [dstq+dsq*1], r7w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu xmm0, [srcq+ssq*0] + movu xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], xmm0 + mova [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu ym0, [srcq+ssq*0] + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], ym0 + mova [dstq+dsq*1], ym1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+64*0], m0 + mova [dstq+dsq*0+64*1], m1 + mova [dstq+dsq*1+64*0], m2 + mova [dstq+dsq*1+64*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 0xff01 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 << 8 + vpbroadcastw m5, mxyd + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .hv + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + vpbroadcastd m3, [pw_2048] + add wq, r7 + jmp wq +.h_w2: + movd xmm0, [srcq+ssq*0] + pinsrd xmm0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb xmm0, xm4 + pmaddubsw xmm0, xm5 + pmulhrsw xmm0, xm3 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + mova xmm4, [bilin_h_shuf4] +.h_w4_loop: + movq xmm0, [srcq+ssq*0] + movhps xmm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xmm4 + pmaddubsw xmm0, xm5 + pmulhrsw xmm0, xm3 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti32x4 ym0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 + pmulhrsw ym0, ym3 + vpmovuswb xm0, ym0 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mova m4, [bilin_h_perm16] +.h_w16_loop: + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + vpermb m0, m4, m0 + pmaddubsw m0, m5 + pmulhrsw m0, m3 + vpmovuswb ym0, m0 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + movu ym0, [srcq+ssq*0+8*0] + vinserti32x8 m0, [srcq+ssq*1+8*0], 1 + movu ym1, [srcq+ssq*0+8*1] + vinserti32x8 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + add srcq, ssq + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + movu m0, [srcq+8*0] + movu m2, [srcq+8*1] + movu m1, [srcq+8*8] + movu m6, [srcq+8*9] + add srcq, ssq + REPX {pshufb x, m4}, m0, m2, m1, m6 + REPX {pmaddubsw x, m5}, m0, m2, m1, m6 + REPX {pmulhrsw x, m3}, m0, m2, m1, m6 + packuswb m0, m2 + packuswb m1, m6 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 0xff01 + vpbroadcastd m5, [pw_2048] + add mxyd, 16 << 8 + add wq, r7 + vpbroadcastw m4, mxyd + jmp wq +.v_w2: + movd xmm0, [srcq+ssq*0] +.v_w2_loop: + pinsrw xmm1, xmm0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pinsrw xmm0, xmm1, [srcq+ssq*0], 0 ; 2 1 + pshuflw xmm1, xmm1, q2301 ; 1 0 + punpcklbw xmm1, xmm0, xmm1 + pmaddubsw xmm1, xm4 + pmulhrsw xmm1, xm5 + packuswb xmm1, xmm1 + pextrw [dstq+dsq*0], xmm1, 1 + pextrw [dstq+dsq*1], xmm1, 0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xmm0, [srcq+ssq*0] +.v_w4_loop: + vpbroadcastd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xmm2, xmm1, xmm0, 0x01 ; 0 1 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm1, xmm0, 0x02 ; 1 2 + punpcklbw xmm1, xmm2 + pmaddubsw xmm1, xm4 + pmulhrsw xmm1, xm5 + packuswb xmm1, xmm1 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xmm0, [srcq+ssq*0] +.v_w8_loop: + movq xmm3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw xmm1, xmm3, xmm0 + movq xmm0, [srcq+ssq*0] + punpcklbw xmm2, xmm0, xmm3 + pmaddubsw xmm1, xm4 + pmaddubsw xmm2, xm4 + pmulhrsw xmm1, xm5 + pmulhrsw xmm2, xm5 + packuswb xmm1, xmm2 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu xmm0, [srcq+ssq*0] +.v_w16_loop: + vbroadcasti128 ymm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd ymm3, ymm2, ymm0, 0x0f ; 0 1 + vbroadcasti128 ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm2, ymm0, 0xf0 ; 1 2 + punpcklbw ymm1, ymm2, ymm3 + punpckhbw ymm2, ymm3 + pmaddubsw ymm1, ym4 + pmaddubsw ymm2, ym4 + pmulhrsw ymm1, ym5 + pmulhrsw ymm2, ym5 + packuswb ymm1, ymm2 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + vzeroupper + RET +.v_w32: + movu ym0, [srcq+ssq*0] + kxnorb k1, k1, k1 +.v_w32_loop: + vbroadcasti32x8 m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendmd m3{k1}, m2, m0 ; 0 1 + vbroadcasti32x8 m0, [srcq+ssq*0] + vpblendmd m2{k1}, m0, m2 ; 1 2 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+ssq*0] +.v_w64_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m1, m3, m0 + punpckhbw m6, m3, m0 + movu m0, [srcq+ssq*0] + pmaddubsw m1, m4 + pmaddubsw m6, m4 + punpcklbw m2, m0, m3 + punpckhbw m7, m0, m3 + pmaddubsw m2, m4 + pmaddubsw m7, m4 + REPX {pmulhrsw x, m5}, m1, m6, m2, m7 + packuswb m1, m6 + packuswb m2, m7 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] +.v_w128_loop: + add srcq, ssq + movu m2, [srcq+64*0] + movu m3, [srcq+64*1] + punpcklbw m6, m2, m0 + pmaddubsw m6, m4 + punpckhbw m0, m2, m0 + pmaddubsw m0, m4 + punpcklbw m7, m3, m1 + pmaddubsw m7, m4 + punpckhbw m1, m3, m1 + pmaddubsw m1, m4 + REPX {pmulhrsw x, m5}, m6, m0, m7, m1 + packuswb m6, m0 + mova m0, m2 + packuswb m7, m1 + mova m1, m3 + mova [dstq+64*0], m6 + mova [dstq+64*1], m7 + add dstq, dsq + dec hd + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + vpbroadcastd m7, [pw_2048] + add wq, r7 + vpbroadcastw m6, mxyd + jmp wq +.hv_w2: + vpbroadcastd xmm0, [srcq+ssq*0] + pshufb xmm0, xm4 + pmaddubsw xmm0, xm5 +.hv_w2_loop: + movd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pinsrd xmm1, [srcq+ssq*0], 1 + pshufb xmm1, xm4 + pmaddubsw xmm1, xm5 ; 1 _ 2 _ + shufps xmm2, xmm0, xmm1, q1032 ; 0 _ 1 _ + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm6 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm7 + packuswb xmm1, xmm1 + pextrw [dstq+dsq*0], xmm1, 0 + pextrw [dstq+dsq*1], xmm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova xmm4, [bilin_h_shuf4] + movddup xmm0, [srcq+ssq*0] + pshufb xmm0, xmm4 + pmaddubsw xmm0, xm5 +.hv_w4_loop: + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm1, [srcq+ssq*0] + pshufb xmm1, xmm4 + pmaddubsw xmm1, xm5 ; 1 2 + shufps xmm2, xmm0, xmm1, q1032 ; 0 1 + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm6 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm7 + packuswb xmm1, xmm1 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 ym0, [srcq+ssq*0] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 ym1, [srcq+ssq*0], 1 + pshufb ym1, ym4 + pmaddubsw ym1, ym5 ; 1 2 + valignq ym2, ym1, ym0, 2 + mova ym0, ym1 + psubw ym1, ym2 + paddw ym1, ym1 + pmulhw ym1, ym6 + paddw ym1, ym2 + pmulhrsw ym1, ym7 + vpmovuswb xm1, ym1 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + vbroadcasti32x8 m0, [srcq+ssq*0] + mova m4, [bilin_h_perm16] + vpermb m0, m4, m0 + pmaddubsw m0, m5 +.hv_w16_loop: + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m1, [srcq+ssq*0], 1 + vpermb m1, m4, m1 + pmaddubsw m1, m5 ; 1 2 + valignq m2, m1, m0, 4 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + vpmovuswb ym1, m1 + mova [dstq+dsq*0], xm1 + vextracti32x4 [dstq+dsq*1], ym1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+ssq*0] + pmovzxbq m8, [pb_02461357] + pmaddubsw m0, m5 +.hv_w32_loop: + vpermb m2, m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpermb m3, m4, [srcq+ssq*0] + pmaddubsw m2, m5 + psubw m1, m2, m0 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m0 + pmaddubsw m0, m3, m5 + psubw m3, m0, m2 + paddw m3, m3 + pmulhw m3, m6 + paddw m3, m2 + pmulhrsw m1, m7 + pmulhrsw m3, m7 + packuswb m1, m3 + vpermq m1, m8, m1 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w64_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m8, m2, m0 + psubw m9, m3, m1 + paddw m8, m8 + pmulhw m8, m6 + paddw m9, m9 + pmulhw m9, m6 + paddw m8, m0 + pmulhrsw m8, m7 + paddw m9, m1 + pmulhrsw m9, m7 + mova m0, m2 + mova m1, m3 + packuswb m8, m9 + mova [dstq], m8 + add dstq, dsq + dec hd + jg .hv_w64_loop + RET +.hv_w128: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + movu m2, [srcq+8*8] + movu m3, [srcq+8*9] + REPX {pshufb x, m4}, m0, m1, m2, m3 + REPX {pmaddubsw x, m5}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, ssq + movu m8, [srcq+8*0] + movu m9, [srcq+8*1] + movu m10, [srcq+8*8] + movu m11, [srcq+8*9] + REPX {pshufb x, m4}, m8, m9, m10, m11 + REPX {pmaddubsw x, m5}, m8, m9, m10, m11 + psubw m12, m8, m0 + psubw m13, m9, m1 + psubw m14, m10, m2 + psubw m15, m11, m3 + paddw m12, m12 + pmulhw m12, m6 + paddw m13, m13 + pmulhw m13, m6 + paddw m14, m14 + pmulhw m14, m6 + paddw m15, m15 + pmulhw m15, m6 + paddw m12, m0 + pmulhrsw m12, m7 + paddw m13, m1 + pmulhrsw m13, m7 + paddw m14, m2 + pmulhrsw m14, m7 + paddw m15, m3 + pmulhrsw m15, m7 + mova m0, m8 + mova m1, m9 + mova m2, m10 + mova m3, m11 + packuswb m12, m13 + packuswb m14, m15 + mova [dstq+64*0], m12 + mova [dstq+64*1], m14 + add dstq, dsq + dec hd + jg .hv_w128_loop + RET + +DECLARE_REG_TMP 3, 5, 6 + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea t2, [prep_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [t2+wq*2+table_offset(prep,)] + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd xmm0, [srcq+strideq*0] + pinsrd xmm0, [srcq+strideq*1], 1 + pinsrd xmm0, [srcq+strideq*2], 2 + pinsrd xmm0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmovzxbw ym0, xmm0 + psllw ym0, 4 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq xmm0, [srcq+strideq*0] + movq xmm1, [srcq+strideq*1] + vinserti128 ym0, ymm0, [srcq+strideq*2], 1 + vinserti128 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1 + pmovzxbw m0, ym0 + psllw m0, 4 + mova [tmpq], m0 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu xmm0, [srcq+strideq*0] + vinserti128 ym0, ymm0, [srcq+strideq*1], 1 + movu xmm1, [srcq+strideq*2] + vinserti128 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmovzxbw m0, ym0 + pmovzxbw m1, ym1 + psllw m0, 4 + psllw m1, 4 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmovzxbw m0, [srcq+strideq*0] + pmovzxbw m1, [srcq+strideq*1] + pmovzxbw m2, [srcq+strideq*2] + pmovzxbw m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .prep_w32 + RET +.prep_w64: + pmovzxbw m0, [srcq+strideq*0+32*0] + pmovzxbw m1, [srcq+strideq*0+32*1] + pmovzxbw m2, [srcq+strideq*1+32*0] + pmovzxbw m3, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .prep_w64 + RET +.prep_w128: + pmovzxbw m0, [srcq+32*0] + pmovzxbw m1, [srcq+32*1] + pmovzxbw m2, [srcq+32*2] + pmovzxbw m3, [srcq+32*3] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + add srcq, strideq + dec hd + jg .prep_w128 + RET +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] + imul mxyd, 0xff01 + add mxyd, 16 << 8 + vpbroadcastw m5, mxyd + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .hv + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_h)] + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + vbroadcasti32x4 ym4, [bilin_h_shuf4] +.h_w4_loop: + movq xmm0, [srcq+strideq*0] + movq xmm1, [srcq+strideq*1] + vinserti32x4 ym0, ymm0, [srcq+strideq*2], 1 + vinserti32x4 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1 + pshufb ym0, ym4 + pmaddubsw ym0, ym5 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + vbroadcasti32x4 m4, [bilin_h_shuf8] +.h_w8_loop: + movu xmm0, [srcq+strideq*0] + vinserti32x4 ym0, ymm0, [srcq+strideq*1], 1 + vinserti32x4 m0, [srcq+strideq*2], 2 + vinserti32x4 m0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pmaddubsw m0, m5 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + mova m4, [bilin_h_perm16] +.h_w16_loop: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + movu ym1, [srcq+strideq*2] + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vpermb m0, m4, m0 + vpermb m1, m4, m1 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: + mova m4, [bilin_h_perm32] +.h_w32_loop: + vpermb m0, m4, [srcq+strideq*0] + vpermb m1, m4, [srcq+strideq*1] + vpermb m2, m4, [srcq+strideq*2] + vpermb m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .h_w32_loop + RET +.h_w64: + mova m4, [bilin_h_perm32] +.h_w64_loop: + vpermb m0, m4, [srcq+strideq*0+32*0] + vpermb m1, m4, [srcq+strideq*0+32*1] + vpermb m2, m4, [srcq+strideq*1+32*0] + vpermb m3, m4, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .h_w64_loop + RET +.h_w128: + mova m4, [bilin_h_perm32] +.h_w128_loop: + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + vpermb m2, m4, [srcq+32*2] + vpermb m3, m4, [srcq+32*3] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + add srcq, strideq + dec hd + jg .h_w128_loop + RET +.v: + WIN64_SPILL_XMM 7 + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_v)] + imul mxyd, 0xff01 + add mxyd, 16 << 8 + add wq, t2 + lea stride3q, [strideq*3] + vpbroadcastw m6, mxyd + jmp wq +.v_w4: + vpbroadcastd xm0, [srcq+strideq*0] + mov r3d, 0x29 + vbroadcasti32x4 ym3, [bilin_v_shuf4] + kmovb k1, r3d +.v_w4_loop: + vpblendmd xm1{k1}, xm0, [srcq+strideq*1] {1to4} ; __01 ____ + vpbroadcastd ym2, [srcq+strideq*2] + vpbroadcastd ym2{k1}, [srcq+stride3q ] ; __2_ 23__ + lea srcq, [srcq+strideq*4] + vpbroadcastd ym0, [srcq+strideq*0] + punpckhqdq ym2{k1}, ym1, ym0 ; 012_ 234_ + pshufb ym2, ym3 + pmaddubsw ym2, ym6 + mova [tmpq], ym2 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + mova m5, [bilin_v_perm8] + vbroadcasti32x4 ym0, [srcq+strideq*0] +.v_w8_loop: + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vpbroadcastq ym0, [srcq+strideq*2] + vinserti32x4 m1, [srcq+stride3q ], 2 + lea srcq, [srcq+strideq*4] + vinserti32x4 ym0, [srcq+strideq*0], 0 + vpermt2b m1, m5, m0 + pmaddubsw m1, m6 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + mova m5, [bilin_v_perm16] + movu xm0, [srcq+strideq*0] +.v_w16_loop: + movu xm2, [srcq+strideq*2] + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vpermt2b m1, m5, m2 + vinserti32x4 ym2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + movu xm0, [srcq+strideq*0] + vpermt2b m2, m5, m0 + pmaddubsw m1, m6 + pmaddubsw m2, m6 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + mova m5, [bilin_v_perm32] + movu ym0, [srcq+strideq*0] +.v_w32_loop: + movu ym2, [srcq+strideq*1] + movu ym3, [srcq+strideq*2] + movu ym4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpermt2b m0, m5, m2 + vpermt2b m2, m5, m3 + vpermt2b m3, m5, m4 + pmaddubsw m1, m0, m6 + movu ym0, [srcq+strideq*0] + vpermt2b m4, m5, m0 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + pmaddubsw m4, m6 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + mova [tmpq+64*2], m3 + mova [tmpq+64*3], m4 + add tmpq, 64*4 + sub hd, 4 + jg .v_w32_loop + RET +.v_w64: + mova m5, [bilin_v_perm64] + vpermq m0, m5, [srcq+strideq*0] +.v_w64_loop: + vpermq m1, m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m1, m0 + punpckhbw m2, m1, m0 + vpermq m0, m5, [srcq+strideq*0] + punpcklbw m3, m0, m1 + punpckhbw m1, m0, m1 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + pmaddubsw m1, m6 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m2 + mova [tmpq+64*2], m3 + mova [tmpq+64*3], m1 + add tmpq, 64*4 + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + mova m5, [bilin_v_perm64] + vpermq m0, m5, [srcq+strideq*0+ 0] + vpermq m1, m5, [srcq+strideq*0+64] +.v_w128_loop: + vpermq m2, m5, [srcq+strideq*1+ 0] + vpermq m3, m5, [srcq+strideq*1+64] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m2, m0 + punpckhbw m0, m2, m0 + pmaddubsw m4, m6 + pmaddubsw m0, m6 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m0 + punpcklbw m4, m3, m1 + punpckhbw m1, m3, m1 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+64*2], m4 + mova [tmpq+64*3], m1 + vpermq m0, m5, [srcq+strideq*0+ 0] + vpermq m1, m5, [srcq+strideq*0+64] + punpcklbw m4, m0, m2 + punpckhbw m2, m0, m2 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + mova [tmpq+64*4], m4 + mova [tmpq+64*5], m2 + punpcklbw m4, m1, m3 + punpckhbw m3, m1, m3 + pmaddubsw m4, m6 + pmaddubsw m3, m6 + mova [tmpq+64*6], m4 + mova [tmpq+64*7], m3 + add tmpq, 64*8 + sub hd, 2 + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 7 + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + vpbroadcastw m6, mxyd + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + vbroadcasti32x4 ym4, [bilin_h_shuf4] + vpbroadcastq ym0, [srcq+strideq*0] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 +.hv_w4_loop: + movq xmm1, [srcq+strideq*1] + movq xmm2, [srcq+strideq*2] + vinserti32x4 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vinserti32x4 ym2, ymm2, [srcq+strideq*0], 1 + punpcklqdq ym1, ym2 + pshufb ym1, ym4 + pmaddubsw ym1, ym5 ; 1 2 3 4 + valignq ym2, ym1, ym0, 3 ; 0 1 2 3 + mova ym0, ym1 + psubw ym1, ym2 + pmulhrsw ym1, ym6 + paddw ym1, ym2 + mova [tmpq], ym1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti32x4 m4, [bilin_h_shuf8] + vbroadcasti32x4 m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xmm1, [srcq+strideq*1] + vinserti128 ym1, ymm1, [srcq+strideq*2], 1 + vinserti128 m1, [srcq+stride3q ], 2 + lea srcq, [srcq+strideq*4] + vinserti128 m1, [srcq+strideq*0], 3 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 3 4 + valignq m2, m1, m0, 6 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + mova m4, [bilin_h_perm16] + vbroadcasti32x8 m0, [srcq+strideq*0] + vpermb m0, m4, m0 + pmaddubsw m0, m5 +.hv_w16_loop: + movu ym1, [srcq+strideq*1] + vinserti32x8 m1, [srcq+strideq*2], 1 + movu ym2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti32x8 m2, [srcq+strideq*0], 1 + vpermb m1, m4, m1 + vpermb m2, m4, m2 + pmaddubsw m1, m5 ; 1 2 + vshufi32x4 m3, m0, m1, q1032 ; 0 1 + pmaddubsw m0, m2, m5 ; 3 4 + vshufi32x4 m2, m1, m0, q1032 ; 2 3 + psubw m1, m3 + pmulhrsw m1, m6 + paddw m1, m3 + psubw m3, m0, m2 + pmulhrsw m3, m6 + paddw m3, m2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m3 + add tmpq, 64*2 + sub hd, 4 + jg .hv_w16_loop + RET +.hv_w32: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+strideq*0] + pmaddubsw m0, m5 +.hv_w32_loop: + vpermb m1, m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermb m2, m4, [srcq+strideq*0] + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+64*0], m3 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w64_loop: + add srcq, strideq + vpermb m2, m4, [srcq+32*0] + vpermb m3, m4, [srcq+32*1] + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m7, m2, m0 + psubw m8, m3, m1 + pmulhrsw m7, m6 + pmulhrsw m8, m6 + paddw m7, m0 + mova m0, m2 + paddw m8, m1 + mova m1, m3 + mova [tmpq+64*0], m7 + mova [tmpq+64*1], m8 + add tmpq, 64*2 + dec hd + jg .hv_w64_loop + RET +.hv_w128: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + vpermb m2, m4, [srcq+32*2] + vpermb m3, m4, [srcq+32*3] + REPX {pmaddubsw x, m5}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, strideq + vpermb m7, m4, [srcq+32*0] + vpermb m8, m4, [srcq+32*1] + vpermb m9, m4, [srcq+32*2] + vpermb m10, m4, [srcq+32*3] + REPX {pmaddubsw x, m5}, m7, m8, m9, m10 + psubw m11, m7, m0 + psubw m12, m8, m1 + psubw m13, m9, m2 + psubw m14, m10, m3 + REPX {pmulhrsw x, m6}, m11, m12, m13, m14 + paddw m11, m0 + mova m0, m7 + paddw m12, m1 + mova m1, m8 + paddw m13, m2 + mova m2, m9 + paddw m14, m3 + mova m3, m10 + mova [tmpq+64*0], m11 + mova [tmpq+64*1], m12 + mova [tmpq+64*2], m13 + mova [tmpq+64*3], m14 + add tmpq, 64*4 + dec hd + jg .hv_w128_loop + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; fn, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%macro PUT_8TAP_H 4-5 0 ; dst/src, tmp[1-3], vpermb +%if %5 + vpermb m%2, m6, m%1 + vpermb m%3, m7, m%1 + vpermb m%4, m8, m%1 +%else +%if %2 < %4 ; reuse a previous value if possible + pshufb m%2, m%1, m6 +%endif + pshufb m%3, m%1, m7 + pshufb m%4, m%1, m8 +%endif + mova m%1, m5 + vpdpbusd m%1, m%2, m9 + mova m%2, m5 + vpdpbusd m%2, m%3, m9 + vpdpbusd m%1, m%3, m10 + vpdpbusd m%2, m%4, m10 + packusdw m%1, m%2 + psrlw m%1, 6 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, + +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 +%define base r8-put_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx512icl] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 + lea r6, [ssq*3] + lea r7, [dsq*3] +%if WIN64 + pop r8 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [pd_34] ; 2 + (8 << 2) + WIN64_SPILL_XMM 11 + cmp wd, 4 + jl .h_w2 + vbroadcasti128 m6, [subpel_h_shufA] + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m7, [subpel_h_shufB] + vbroadcasti128 m8, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)] + vpbroadcastd m9, [base+mxq*8+subpel_filters+0] + vpbroadcastd m10, [base+mxq*8+subpel_filters+4] + add wq, r8 + jmp wq +.h_w2: + movzx mxd, mxb + dec srcq + mova xmm4, [subpel_h_shuf4] + vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2] +.h_w2_loop: + movq xmm0, [srcq+ssq*0] + movhps xmm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xmm4 + mova xmm1, xm5 + vpdpbusd xmm1, xmm0, xmm3 + packssdw xmm0, xmm1, xmm1 + psraw xmm0, 6 + packuswb xmm0, xm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2] +.h_w4_loop: + movq xmm0, [srcq+ssq*0] + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xm6 + pshufb xmm1, xm6 + mova xmm2, xm5 + vpdpbusd xmm2, xmm0, xmm3 + mova xmm0, xm5 + vpdpbusd xmm0, xmm1, xmm3 + packssdw xmm0, xmm2, xmm0 + psraw xmm0, 6 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti32x4 ym0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + WRAP_YMM PUT_8TAP_H 0, 1, 2, 3 + vpmovuswb xm0, ym0 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mova m6, [spel_h_perm16a] + mova m7, [spel_h_perm16b] + mova m8, [spel_h_perm16c] +.h_w16_loop: + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 1, 2, 3, 1 + vpmovuswb ym0, m0 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + movu ym0, [srcq+ssq*0+8*0] + vinserti32x8 m0, [srcq+ssq*1+8*0], 1 + movu ym1, [srcq+ssq*0+8*1] + vinserti32x8 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 4, 3, 2 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 4, 3, 2 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + movu m0, [srcq+8*0] + movu m2, [srcq+8*1] + movu m1, [srcq+8*8] + movu m3, [srcq+8*9] + add srcq, ssq + PUT_8TAP_H 0, 4, 11, 12 + PUT_8TAP_H 2, 12, 11, 4 + PUT_8TAP_H 1, 4, 11, 12 + PUT_8TAP_H 3, 12, 11, 4 + packuswb m0, m2 + packuswb m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + tzcnt r6d, wd + movzx r6d, word [r8+r6*2+table_offset(put, _8tap_v)] + vpbroadcastd m7, [pw_512] + lea myq, [base+subpel_filters+myq*8] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + add r6, r8 + lea ss3q, [ssq*3] + sub srcq, ss3q + jmp r6 +.v_w2: + movd xmm2, [srcq+ssq*0] + pinsrw xmm2, [srcq+ssq*1], 2 + pinsrw xmm2, [srcq+ssq*2], 4 + add srcq, ss3q + pinsrw xmm2, [srcq+ssq*0], 6 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklbw xmm3, xmm1 ; 45 56 + punpcklbw xmm1, xmm2, xmm4 ; 01 12 + punpckhbw xmm2, xmm4 ; 23 34 +.v_w2_loop: + pmaddubsw xmm5, xmm1, xm8 ; a0 b0 + mova xmm1, xmm2 + pmaddubsw xmm2, xm9 ; a1 b1 + paddw xmm5, xmm2 + mova xmm2, xmm3 + pmaddubsw xmm3, xm10 ; a2 b2 + paddw xmm5, xmm3 + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm4, xmm0, 0x02 ; 7 8 + punpcklbw xmm3, xmm4 ; 67 78 + pmaddubsw xmm4, xmm3, xm11 ; a3 b3 + paddw xmm5, xmm4 + pmulhrsw xmm5, xm7 + packuswb xmm5, xmm5 + pextrw [dstq+dsq*0], xmm5, 0 + pextrw [dstq+dsq*1], xmm5, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xmm2, [srcq+ssq*0] + pinsrd xmm2, [srcq+ssq*1], 1 + pinsrd xmm2, [srcq+ssq*2], 2 + add srcq, ss3q + pinsrd xmm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklbw xmm3, xmm1 ; 45 56 + punpcklbw xmm1, xmm2, xmm4 ; 01 12 + punpckhbw xmm2, xmm4 ; 23 34 +.v_w4_loop: + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw xmm5, xmm1, xm8 ; a0 b0 + mova xmm1, xmm2 + pmaddubsw xmm2, xm9 ; a1 b1 + paddw xmm5, xmm2 + mova xmm2, xmm3 + pmaddubsw xmm3, xm10 ; a2 b2 + paddw xmm5, xmm3 + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm4, xmm0, 0x02 ; 7 8 + punpcklbw xmm3, xmm4 ; 67 78 + pmaddubsw xmm4, xmm3, xm11 ; a3 b3 + paddw xmm5, xmm4 + pmulhrsw xmm5, xm7 + packuswb xmm5, xmm5 + movd [dstq+dsq*0], xmm5 + pextrd [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xmm1, [srcq+ssq*0] + vpbroadcastq ymm0, [srcq+ssq*1] + vpbroadcastq ymm2, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq ymm5, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm4, [srcq+ssq*2] + add srcq, ss3q + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklbw ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm5, 0x30 + vpblendd ymm5, ymm3, 0x30 + punpcklbw ymm2, ymm5 ; 23 34 + vpblendd ymm3, ymm4, 0x30 + vpblendd ymm4, ymm0, 0x30 + punpcklbw ymm3, ymm4 ; 45 56 +.v_w8_loop: + vpbroadcastq ymm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw ymm5, ymm1, ym8 ; a0 b0 + mova ymm1, ymm2 + pmaddubsw ymm2, ym9 ; a1 b1 + paddw ymm5, ymm2 + mova ymm2, ymm3 + pmaddubsw ymm3, ym10 ; a2 b2 + paddw ymm5, ymm3 + vpblendd ymm3, ymm0, ymm4, 0x30 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm4, ymm4, ymm0, 0x30 + punpcklbw ymm3, ymm4 ; 67 78 + pmaddubsw ymm4, ymm3, ym11 ; a3 b3 + paddw ymm5, ymm4 + pmulhrsw ymm5, ym7 + vextracti128 xmm4, ymm5, 1 + packuswb xmm5, xmm4 + movq [dstq+dsq*0], xmm5 + movhps [dstq+dsq*1], xmm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + vzeroupper + RET +.v_w16: + mova m12, [spel_v_perm16] + vbroadcasti32x4 m1, [srcq+ssq*0] + vbroadcasti32x4 ym4, [srcq+ssq*1] + mov r6d, 0x0f + vbroadcasti32x4 m2, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti32x4 ym5, [srcq+ssq*0] + kmovb k1, r6d + vbroadcasti32x4 m3, [srcq+ssq*1] + vbroadcasti32x4 ym6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti32x4 m0, [srcq+ssq*0] + vshufpd m1{k1}, m4, m2, 0xcc + vshufpd m2{k1}, m5, m3, 0xcc + vshufpd m3{k1}, m6, m0, 0xcc + vpermb m1, m12, m1 ; 01 12 + vpermb m2, m12, m2 ; 23 34 + vpermb m3, m12, m3 ; 45 56 +.v_w16_loop: + pmaddubsw m4, m1, m8 ; a0 b0 + mova m1, m2 + pmaddubsw m5, m2, m9 ; a1 b1 + mova m2, m3 + pmaddubsw m6, m3, m10 ; a2 b2 + mova m3, m0 + paddw m4, m5 + vbroadcasti32x4 ym5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti32x4 m0, [srcq+ssq*0] + vshufpd m3{k1}, m5, m0, 0xcc + vpermb m3, m12, m3 ; 67 78 + pmaddubsw m5, m3, m11 ; a3 b3 + paddw m4, m6 + paddw m4, m5 + pmulhrsw m4, m7 + vextracti32x8 ym5, m4, 1 + packuswb ym4, ym5 + mova [dstq+dsq*0], xm4 + vextracti32x4 [dstq+dsq*1], ym4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: + mova m12, [spel_v_perm32] + pmovzxbq m14, [pb_02461357] + vpshrdw m13, m12, m12, 8 + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + vpermb m1, m12, m0 ; 01 + vinserti32x8 m0, [srcq+ssq*2], 0 + add srcq, ss3q + vpermb m2, m13, m0 ; 12 + vinserti32x8 m0, [srcq+ssq*0], 1 + vpermb m3, m12, m0 ; 23 + vinserti32x8 m0, [srcq+ssq*1], 0 + vpermb m4, m13, m0 ; 34 + vinserti32x8 m0, [srcq+ssq*2], 1 + add srcq, ss3q + vpermb m5, m12, m0 ; 45 + vinserti32x8 m0, [srcq+ssq*0], 0 + vpermb m6, m13, m0 ; 56 +.v_w32_loop: + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddubsw m15, m1, m8 + mova m1, m3 + pmaddubsw m16, m2, m8 + mova m2, m4 + pmaddubsw m17, m3, m9 + mova m3, m5 + pmaddubsw m18, m4, m9 + mova m4, m6 + pmaddubsw m19, m5, m10 + vpermb m5, m12, m0 ; 67 + vinserti32x8 m0, [srcq+ssq*0], 0 + pmaddubsw m20, m6, m10 + vpermb m6, m13, m0 ; 78 + paddw m15, m17 + pmaddubsw m17, m5, m11 + paddw m16, m18 + pmaddubsw m18, m6, m11 + paddw m15, m19 + paddw m16, m20 + paddw m15, m17 + paddw m16, m18 + pmulhrsw m15, m7 + pmulhrsw m16, m7 + packuswb m15, m16 + vpermq m15, m14, m15 + mova [dstq+dsq*0], ym15 + vextracti32x8 [dstq+dsq*1], m15, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + vzeroupper + RET +.v_w64: +.v_w128: + lea r6d, [hq+wq*4-256] + mov r4, srcq + mov r7, dstq +.v_loop0: + movu m2, [srcq+ssq*0] + movu m4, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + movu m13, [srcq+ssq*0] + movu m15, [srcq+ssq*1] + movu m17, [srcq+ssq*2] + add srcq, ss3q + movu m0, [srcq+ssq*0] + punpcklbw m1, m2, m4 ; 01l + punpckhbw m2, m4 ; 01h + punpcklbw m3, m4, m6 ; 12l + punpckhbw m4, m6 ; 12h + punpcklbw m5, m6, m13 ; 23l + punpckhbw m6, m13 ; 23h + punpcklbw m12, m13, m15 ; 34l + punpckhbw m13, m15 ; 34h + punpcklbw m14, m15, m17 ; 45l + punpckhbw m15, m17 ; 45h + punpcklbw m16, m17, m0 ; 56l + punpckhbw m17, m0 ; 56h +.v_loop: + pmaddubsw m18, m1, m8 ; a0l + mova m1, m5 + pmaddubsw m19, m2, m8 ; a0h + mova m2, m6 + pmaddubsw m20, m3, m8 ; b0l + mova m3, m12 + pmaddubsw m21, m4, m8 ; b0h + mova m4, m13 + pmaddubsw m5, m9 ; a1l + pmaddubsw m6, m9 ; a1h + pmaddubsw m12, m9 ; b1l + pmaddubsw m13, m9 ; b1h + paddw m18, m5 + mova m5, m14 + pmaddubsw m14, m10 ; a2l + paddw m19, m6 + mova m6, m15 + pmaddubsw m15, m10 ; a2h + paddw m20, m12 + mova m12, m16 + pmaddubsw m16, m10 ; b2l + paddw m21, m13 + mova m13, m17 + pmaddubsw m17, m10 ; b2h + paddw m18, m14 + paddw m19, m15 + paddw m20, m16 + paddw m21, m17 + movu m17, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m14, m0, m17 ; 67l + punpckhbw m15, m0, m17 ; 67h + pmaddubsw m16, m14, m11 ; a3l + pmaddubsw m0, m15, m11 ; a3h + paddw m18, m16 + paddw m19, m0 + movu m0, [srcq+ssq*0] + punpcklbw m16, m17, m0 ; 78l + punpckhbw m17, m0 ; 78h + pmulhrsw m18, m7 + pmulhrsw m19, m7 + packuswb m18, m19 + mova [dstq+dsq*0], m18 + pmaddubsw m18, m16, m11 ; b3l + pmaddubsw m19, m17, m11 ; b3h + paddw m18, m20 + paddw m19, m21 + pmulhrsw m18, m7 + pmulhrsw m19, m7 + packuswb m18, m19 + mova [dstq+dsq*1], m18 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_loop + add r4, 64 + add r7, 64 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 256 + jg .v_loop0 + vzeroupper + RET +.hv: + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + dec srcq + vpbroadcastd m7, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m8, [pd_2] + vpbroadcastq ym0, [base+subpel_filters+myq*8] + lea ss3q, [ssq*3] + vpbroadcastd ym9, [pd_32768] + mov r6, srcq + punpcklbw ym0, ym8, ym0 + sub r6, ss3q + psraw ym0, 2 ; << 6 + mova xm14, [spel_hv_end] + pshufd ym10, ym0, q0000 + pshufd ym11, ym0, q1111 + pshufd ym12, ym0, q2222 + pshufd ym13, ym0, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 ym6, [subpel_h_shuf4] + movq xmm2, [r6+ssq*0] + movhps xmm2, [r6+ssq*1] + movq xmm0, [r6+ssq*2] + movhps xmm0, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq ymm1, [srcq+ssq*0] + vpblendd ymm2, ymm3, 0x30 + vpblendd ymm0, ymm1, 0x30 ; 2 3 6 _ + vpblendd ymm2, ymm4, 0xc0 ; 0 1 4 5 + pshufb ymm2, ym6 + pshufb ymm0, ym6 + mova ymm1, ym8 + vpdpbusd ymm1, ymm2, ym7 + mova ymm2, ym8 + vpdpbusd ymm2, ymm0, ym7 + packssdw ymm2, ymm1, ymm2 + psraw ymm2, 2 + vextracti128 xmm3, ymm2, 1 + palignr xmm4, xmm3, xmm2, 4 + punpcklwd xmm1, xmm2, xmm4 ; 01 12 + punpckhwd xmm2, xmm4 ; 23 34 + pshufd xmm0, xmm3, q2121 + punpcklwd xmm3, xmm0 ; 45 56 +.hv_w2_loop: + movq xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm4, [srcq+ssq*0] + mova xmm5, xm9 + vpdpwssd xmm5, xmm1, xm10 ; a0 b0 + mova xmm1, xmm2 + vpdpwssd xmm5, xmm2, xm11 ; a1 b1 + pshufb xmm4, xm6 + mova xmm2, xmm3 + vpdpwssd xmm5, xmm3, xm12 ; a2 b2 + mova xmm3, xm8 + vpdpbusd xmm3, xmm4, xm7 + packssdw xmm4, xmm3, xmm3 + psraw xmm4, 2 + palignr xmm3, xmm4, xmm0, 12 + mova xmm0, xmm4 + punpcklwd xmm3, xmm4 ; 67 78 + vpdpwssd xmm5, xmm3, xm13 ; a3 b3 + packuswb xmm5, xmm5 + pshufb xmm5, xm14 + pextrw [dstq+dsq*0], xmm5, 0 + pextrw [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + vzeroupper + RET +.hv_w4: + movq xmm1, [r6+ssq*0] + vpbroadcastq ym2, [r6+ssq*1] + vinserti32x4 ym1, ymm1, [r6+ssq*2], 1 + vinserti32x4 m2, [srcq+ssq*0], 2 + vinserti32x4 m1, [srcq+ssq*1], 2 + vinserti32x4 m2, [srcq+ssq*2], 3 ; _ 1 3 5 + vbroadcasti32x4 m6, [subpel_h_shufA] + add srcq, ss3q + vinserti32x4 m1, [srcq+ssq*0], 3 ; 0 2 4 6 + pshufb m2, m6 + pshufb m1, m6 + mova m0, m8 + vpdpbusd m0, m2, m7 + mova m4, m8 + vpdpbusd m4, m1, m7 + mova ym1, [spel_hv_perm4a] + mova ym2, [spel_hv_perm4b] + mova ym3, [spel_hv_perm4c] + packssdw m0, m4 + psraw m0, 2 ; _ 0 1 2 3 4 5 6 + mov r6d, 0x5555 + vpermb ym1, ym1, ym0 ; 01 12 + vpermb m2, m2, m0 ; 23 34 + vpermb m3, m3, m0 ; 45 56 + kmovw k1, r6d + mova ym15, [spel_hv_perm4d] +.hv_w4_loop: + movq xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym4, ymm4, [srcq+ssq*0], 1 + mova ym5, ym9 + vpdpwssd ym5, ym1, ym10 ; a0 b0 + mova ym1, ym2 + pshufb ym4, ym6 + mova ym0, ym8 + vpdpbusd ym0, ym4, ym7 + vpdpwssd ym5, ym2, ym11 ; a1 b1 + mova ym2, ym3 + vpdpwssd ym5, ym3, ym12 ; a2 b2 + vpsraw ym3{k1}, ym0, 2 ; 7 8 + vpermb ym3, ym15, ym3 ; 67 78 + vpdpwssd ym5, ym3, ym13 ; a3 b3 + packuswb ym5, ym5 + vpermb ym5, ym14, ym5 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [base+subpel_filters+mxq*8+0] + vpbroadcastd m11, [base+subpel_filters+mxq*8+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m8, [pd_2] + vpbroadcastq m0, [base+subpel_filters+myq*8] + vpbroadcastd m9, [pd_32768] + punpcklbw m0, m8, m0 + lea ss3q, [ssq*3] + psraw m0, 2 ; << 6 + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + cmp wd, 8 + jne .hv_w16 + mov r6, srcq + sub r6, ss3q + movu xmm1, [r6+ssq*0] + vinserti128 ymm1, [r6+ssq*1], 1 + movu xmm2, [srcq+ssq*1] + vinserti32x4 m6, zmm1, [r6+ssq*2], 2 + vinserti128 ymm2, [srcq+ssq*2], 1 + vinserti32x4 m6, [srcq+ssq*0], 3 ; 0 1 2 3 + add srcq, ss3q + vbroadcasti32x4 m4, [subpel_h_shufA] + vinserti32x4 m0, zmm2, [srcq+ssq*0], 2 ; 4 5 6 _ + vbroadcasti32x4 m7, [subpel_h_shufB] + vbroadcasti32x4 m17, [subpel_h_shufC] + pshufb m1, m6, m4 ; 0 1 2 3 0123 + mova m2, m8 + vpdpbusd m2, m1, m10 + pshufb m5, m6, m7 ; 0 1 2 3 4567 + mova m1, m8 + vpdpbusd m1, m5, m10 + pshufb m4, m0, m4 ; 4 5 6 _ 0123 + mova m3, m8 + vpdpbusd m3, m4, m10 + pshufb m7, m0, m7 ; 4 5 6 _ 4567 + mova m4, m8 + vpdpbusd m4, m7, m10 + pshufb m6, m17 + vpdpbusd m2, m5, m11 + vpdpbusd m1, m6, m11 + pshufb m6, m0, m17 + vpdpbusd m3, m7, m11 + vpdpbusd m4, m6, m11 + mova m5, [spel_hv_perm8a] + mova m0, [spel_hv_perm8b] + mov r6, 0x55555555ff00 + packssdw m2, m1 + packssdw m3, m4 + mova m18, [spel_hv_perm8c] + psraw m2, 2 ; 0 1 2 3 + psraw m3, 2 ; 4 5 6 _ + vpermb m1, m5, m2 ; 01 12 + vbroadcasti32x8 m6, [subpel_h_shufA] + kmovq k1, r6 + vpermt2b m2, m0, m3 ; 23 34 + vbroadcasti32x8 m7, [subpel_h_shufB] + kshiftrq k2, k1, 16 + mova xm16, [spel_hv_end] + vpermb m3, m5, m3 ; 45 56 +.hv_w8_loop: + vbroadcasti32x4 ym4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti32x4 m4{k1}, [srcq+ssq*0] + mova m0, m9 + vpdpwssd m0, m1, m12 ; a0 b0 + pshufb m1, m4, m6 ; 7 8 0123 4567 + mova m5, m8 + vpdpbusd m5, m1, m10 + pshufb m4, m7 ; 7 8 4567 89ab + vpdpwssd m0, m2, m13 ; a1 b1 + mova m1, m2 + vpdpbusd m5, m4, m11 + mova m2, m3 + vpdpwssd m0, m3, m14 ; a2 b2 + psraw m3{k2}, m5, 2 ; 75 86 + vpermb m3, m18, m3 ; 67 78 + vpdpwssd m0, m3, m15 ; a3 b3 + packuswb m0, m0 + vpermb zmm1, m16, m0 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + vzeroupper + RET +.hv_w16: + movu m7, [spel_hv_perm16a] + sub srcq, ss3q + mova m20, [spel_hv_perm16b] + lea r6d, [wq*2-32] + mova m21, [spel_hv_perm16c] + mov r4, srcq + mov r7, dstq + mova ym16, [spel_hv_end16] + lea r6d, [hq+r6*8] +.hv_w16_loop0: + movu ym17, [srcq+ssq*0] + vinserti32x8 m17, [srcq+ssq*1], 1 ; 0 1 + movu ym18, [srcq+ssq*2] + add srcq, ss3q + vinserti32x8 m18, [srcq+ssq*0], 1 ; 2 3 + movu ym19, [srcq+ssq*1] + vinserti32x8 m19, [srcq+ssq*2], 1 ; 4 5 + add srcq, ss3q + vpermb m2, m7, m17 ; 0 1 0123 89ab + vpermb m0, m20, m17 ; 0 1 4567 cdef + vpermb m4, m7, m18 ; 2 3 0123 89ab + mova m1, m8 + vpdpbusd m1, m2, m10 + vpermb m5, m20, m18 ; 2 3 4567 cdef + mova m2, m8 + vpdpbusd m2, m0, m10 + vpermb m17, m21, m17 ; 0 1 89ab ghij + mova m3, m8 + vpdpbusd m3, m4, m10 + vpermb m6, m7, m19 ; 4 5 0123 89ab + mova m4, m8 + vpdpbusd m4, m5, m10 + vpermb m18, m21, m18 ; 2 3 89ab ghij + vpdpbusd m1, m0, m11 + movu ym0, [srcq+ssq*0] ; 6 + vpdpbusd m2, m17, m11 + vpermb m17, m20, m19 ; 4 5 4567 cdef + vpdpbusd m3, m5, m11 + mova m5, m8 + vpdpbusd m5, m6, m10 + mova m6, m8 + vpdpbusd m6, m17, m10 + vpdpbusd m4, m18, m11 + mova m18, [spel_hv_perm16d] + vpermb m18, m18, m0 ; 6 0145 2367 89cd abef + vpdpbusd m5, m17, m11 + vpermb m19, m21, m19 ; 4 5 89ab ghij + mova m17, m8 + vpdpbusd m17, m18, m10 + mova m18, [spel_hv_perm16e] + vpermb m0, m18, m0 ; 6 4589 67ab cdgh efij + packssdw m1, m2 ; 01 + vpdpbusd m6, m19, m11 + packssdw m3, m4 ; 23 + vpdpbusd m17, m0, m11 + psraw m1, 2 + packssdw m5, m6 ; 45 + psraw m3, 2 + vpshrdd m2, m1, m3, 16 ; 12 + psraw m5, 2 + vpshrdd m4, m3, m5, 16 ; 34 + psraw m17, 2 + vpshrdd m6, m5, m17, 16 ; 56 +.hv_w16_loop: + movu ym18, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m18, [srcq+ssq*0], 1 + mova m0, m9 + vpdpwssd m0, m1, m12 ; a0 + vpermb m1, m7, m18 ; 7 8 0123 89ab + mova m17, m9 + vpdpwssd m17, m2, m12 ; b0 + vpermb m2, m20, m18 ; 7 8 4567 cdef + mova m19, m8 + vpdpbusd m19, m1, m10 + vpermb m18, m21, m18 + mova m1, m8 + vpdpbusd m1, m2, m10 + vpdpwssd m0, m3, m13 ; a1 + vpdpwssd m17, m4, m13 ; b1 + vpdpbusd m19, m2, m11 + mova m2, m4 + vpdpbusd m1, m18, m11 + mova m4, m6 + vpdpwssd m0, m5, m14 ; a2 + vpdpwssd m17, m6, m14 ; b2 + packssdw m19, m1 + mova m1, m3 + mova m3, m5 + psraw m6, m19, 2 ; 7 8 + vpshrdd m5, m4, m6, 16 ; 6 7 + vpdpwssd m17, m6, m15 ; b3 + vpdpwssd m0, m5, m15 ; a3 + packuswb m0, m17 + vpermb zmm1, m16, m0 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w16_loop0 + vzeroupper + RET + +%macro PREP_8TAP_H 0 + vpermb m10, m5, m0 + vpermb m11, m5, m1 + vpermb m12, m6, m0 + vpermb m13, m6, m1 + vpermb m14, m7, m0 + vpermb m15, m7, m1 + mova m0, m4 + vpdpbusd m0, m10, m8 + mova m2, m4 + vpdpbusd m2, m12, m8 + mova m1, m4 + vpdpbusd m1, m11, m8 + mova m3, m4 + vpdpbusd m3, m13, m8 + vpdpbusd m0, m12, m9 + vpdpbusd m2, m14, m9 + vpdpbusd m1, m13, m9 + vpdpbusd m3, m15, m9 + packssdw m0, m2 + packssdw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, + +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx512icl] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r7+wq*2+table_offset(prep,)] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m4, [pd_2] + WIN64_SPILL_XMM 10 + cmp wd, 4 + je .h_w4 + tzcnt wd, wd + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)] + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+0] + vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep_avx512icl+4] + add wq, r7 + jmp wq +.h_w4: + movzx mxd, mxb + vbroadcasti128 ym5, [subpel_h_shufA] + mov r3d, 0x4 + dec srcq + vpbroadcastd ym6, [r7+mxq*8+subpel_filters-prep_avx512icl+2] + kmovb k1, r3d + lea stride3q, [strideq*3] +.h_w4_loop: + movq xm2, [srcq+strideq*0] + movq xm3, [srcq+strideq*1] + vpbroadcastq ym2{k1}, [srcq+strideq*2] + vpbroadcastq ym3{k1}, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pshufb ym2, ym5 + pshufb ym3, ym5 + mova ym0, ym4 + vpdpbusd ym0, ym2, ym6 + mova ym1, ym4 + vpdpbusd ym1, ym3, ym6 + packssdw ym0, ym1 + psraw ym0, 2 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + vbroadcasti128 m5, [subpel_h_shufA] + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + lea stride3q, [strideq*3] +.h_w8_loop: + movu xmm3, [srcq+strideq*0] + vinserti128 ym3, ymm3, [srcq+strideq*1], 1 + vinserti128 m3, [srcq+strideq*2], 2 + vinserti128 m3, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pshufb m1, m3, m5 + pshufb m2, m3, m6 + mova m0, m4 + vpdpbusd m0, m1, m8 + mova m1, m4 + vpdpbusd m1, m2, m8 + pshufb m3, m7 + vpdpbusd m0, m2, m9 + vpdpbusd m1, m3, m9 + packssdw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + mova m5, [spel_h_perm16a] + mova m6, [spel_h_perm16b] + mova m7, [spel_h_perm16c] + lea stride3q, [strideq*3] +.h_w16_loop: + movu ym0, [srcq+strideq*0] + movu ym1, [srcq+strideq*2] + vinserti32x8 m0, [srcq+strideq*1], 1 + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + PREP_8TAP_H + add tmpq, 64*2 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: + mova m5, [spel_h_perm32a] + mova m6, [spel_h_perm32b] + mova m7, [spel_h_perm32c] +.h_w32_loop: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + add tmpq, 64*2 + sub hd, 2 + jg .h_w32_loop + RET +.h_w64: + xor r6d, r6d + jmp .h_start +.h_w128: + mov r6, -64*1 +.h_start: + mova m5, [spel_h_perm32a] + mova m6, [spel_h_perm32b] + mova m7, [spel_h_perm32c] + sub srcq, r6 + mov r5, r6 +.h_loop: + movu m0, [srcq+r6+32*0] + movu m1, [srcq+r6+32*1] + PREP_8TAP_H + add tmpq, 64*2 + add r6, 64 + jle .h_loop + add srcq, strideq + mov r6, r5 + dec hd + jg .h_loop + RET +.v: + movzx mxd, myb ; Select 4-tap/8-tap filter multipliers. + shr myd, 16 ; Note that the code is 8-tap only, having + tzcnt wd, wd + cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4 + cmove myd, mxd ; had a negligible effect on performance. + ; TODO: Would a 6-tap code path be worth it? + lea myq, [r7+myq*8+subpel_filters-prep_avx512icl] + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_v)] + add wq, r7 + lea stride3q, [strideq*3] + sub srcq, stride3q + vpbroadcastd m7, [pw_8192] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + jmp wq +.v_w4: + movd xmm0, [srcq+strideq*0] + vpbroadcastd ymm1, [srcq+strideq*2] + vpbroadcastd xmm2, [srcq+strideq*1] + vpbroadcastd ymm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm1, ymm0, 0x01 ; 0 2 2 _ 2 _ _ _ + vpblendd ymm3, ymm2, 0x03 ; 1 1 3 3 3 3 _ _ + vpbroadcastd ymm0, [srcq+strideq*0] + vpbroadcastd ymm2, [srcq+strideq*1] + vpblendd ymm1, ymm0, 0x68 ; 0 2 2 4 2 4 4 _ + vpbroadcastd ymm0, [srcq+strideq*2] + vbroadcasti128 ymm5, [deint_shuf4] + vpblendd ymm3, ymm2, 0xc0 ; 1 1 3 3 3 3 5 5 + vpblendd ymm2, ymm3, ymm1, 0x55 ; 0 1 2 3 2 3 4 5 + vpblendd ymm3, ymm1, 0xaa ; 1 2 3 4 3 4 5 _ + punpcklbw ymm1, ymm2, ymm3 ; 01 12 23 34 + vpblendd ymm3, ymm0, 0x80 ; 1 2 3 4 3 4 5 6 + punpckhbw ymm2, ymm3 ; 23 34 45 56 +.v_w4_loop: + pinsrd xmm0, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vpbroadcastd ymm3, [srcq+strideq*0] + vpbroadcastd ymm4, [srcq+strideq*1] + vpblendd ymm3, ymm4, 0x20 ; _ _ 8 _ 8 9 _ _ + vpblendd ymm3, ymm0, 0x03 ; 6 7 8 _ 8 9 _ _ + vpbroadcastd ymm0, [srcq+strideq*2] + vpblendd ymm3, ymm0, 0x40 ; 6 7 8 _ 8 9 a _ + pshufb ymm3, ymm5 ; 67 78 89 9a + pmaddubsw ymm4, ymm1, ym8 + vperm2i128 ymm1, ymm2, ymm3, 0x21 ; 45 56 67 78 + pmaddubsw ymm2, ym9 + paddw ymm4, ymm2 + mova ymm2, ymm3 + pmaddubsw ymm3, ym11 + paddw ymm3, ymm4 + pmaddubsw ymm4, ymm1, ym10 + paddw ymm3, ymm4 + pmulhrsw ymm3, ym7 + mova [tmpq], ymm3 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + mov r3d, 0xf044 + kmovw k1, r3d + kshiftrw k2, k1, 8 + movq xm0, [srcq+strideq*0] + vpbroadcastq ym1, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m4, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + vpbroadcastq m6, [srcq+strideq*2] + vmovdqa64 ym0{k1}, ym1 + vmovdqa64 ym1{k1}, ym2 + vmovdqa64 m2{k1}, m3 + vmovdqa64 m3{k1}, m4 + vmovdqa64 m4{k1}, m5 + vmovdqa64 m5{k1}, m6 + punpcklbw ym0, ym1 ; 01 12 __ __ + punpcklbw m2, m3 ; 23 34 23 34 + punpcklbw m4, m5 ; 45 56 45 56 + vmovdqa64 m0{k2}, m2 ; 01 12 23 34 + vmovdqa64 m2{k2}, m4 ; 23 34 45 56 +.v_w8_loop: + vpbroadcastq m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + pmaddubsw m14, m0, m8 + pmaddubsw m15, m2, m9 + vpblendmq m0{k1}, m6, m1 + vpblendmq m2{k1}, m1, m3 + vpbroadcastq m6, [srcq+strideq*2] + paddw m14, m15 + punpcklbw m2, m0, m2 ; 67 78 67 78 + vpblendmq m12{k1}, m3, m5 + vpblendmq m13{k1}, m5, m6 + vpblendmq m0{k2}, m4, m2 ; 45 56 67 78 + punpcklbw m4, m12, m13 ; 89 9a 89 9a + vmovdqa64 m2{k2}, m4 ; 67 78 89 9a + pmaddubsw m12, m0, m10 + pmaddubsw m13, m2, m11 + paddw m14, m12 + paddw m14, m13 + pmulhrsw m14, m7 + mova [tmpq], m14 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + mov r3d, 0xf0 + kmovb k1, r3d + vbroadcasti128 m0, [srcq+strideq*0] + vbroadcasti128 m1, [srcq+strideq*1] + vbroadcasti128 m2, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*2] + vmovdqa64 m0{k1}, m1 + vmovdqa64 m1{k1}, m2 + vmovdqa64 m2{k1}, m3 + vmovdqa64 m3{k1}, m4 + vmovdqa64 m4{k1}, m5 + vmovdqa64 m5{k1}, m6 + shufpd m0, m2, 0xcc ; 0a_2a 0b_2b 1a_3a 1b_3b + shufpd m1, m3, 0xcc ; 1a_3a 1b_3b 2a_4a 2b_4b + shufpd m4, m4, 0x44 ; 4a_-- 4b_-- 5a_-- 5b_-- + shufpd m5, m5, 0x44 ; 5a_-- 5b_-- 6a_-- 6b_-- + punpckhbw m2, m0, m1 ; 23a 23b 34a 34b + punpcklbw m0, m1 ; 01a 01b 12a 12b + punpcklbw m4, m5 ; 45a 45b 56a 56b +.v_w16_loop: + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m5, [srcq+strideq*0] + vpblendmq m1{k1}, m6, m3 + vmovdqa64 m3{k1}, m5 + pmaddubsw m12, m0, m8 + pmaddubsw m13, m2, m8 + pmaddubsw m14, m2, m9 + pmaddubsw m15, m4, m9 + pmaddubsw m0, m4, m10 + vbroadcasti128 m2, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*2] + paddw m12, m14 + paddw m13, m15 + paddw m12, m0 + vmovdqa64 m5{k1}, m2 + vmovdqa64 m2{k1}, m6 + mova m0, m4 + shufpd m1, m5, 0xcc ; 6a_8a 6b_8b 7a_9a 7b_9b + shufpd m3, m2, 0xcc ; 7a_9a 7b_9b 8a_Aa 8b_Ab + punpcklbw m2, m1, m3 ; 67a 67b 78a 78b + punpckhbw m4, m1, m3 ; 89a 89b 9Aa 9Ab + pmaddubsw m14, m2, m10 + pmaddubsw m15, m2, m11 + paddw m13, m14 + paddw m12, m15 + pmaddubsw m14, m4, m11 + paddw m13, m14 + pmulhrsw m12, m7 + pmulhrsw m13, m7 + mova [tmpq+ 0], m12 + mova [tmpq+64], m13 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + mova m18, [bilin_v_perm64] + movu ym0, [srcq+strideq*0] + movu ym1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym2, [srcq+strideq*0] + movu ym3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym4, [srcq+strideq*0] + movu ym5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym6, [srcq+strideq*0] + vpermq m0, m18, m0 + vpermq m1, m18, m1 + vpermq m2, m18, m2 + vpermq m3, m18, m3 + vpermq m4, m18, m4 + vpermq m5, m18, m5 + vpermq m6, m18, m6 + punpcklbw m0, m1 + punpcklbw m1, m2 + punpcklbw m2, m3 + punpcklbw m3, m4 + punpcklbw m4, m5 + punpcklbw m5, m6 +.v_w32_loop: + movu ym12, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym13, [srcq+strideq*0] + pmaddubsw m14, m0, m8 + pmaddubsw m16, m2, m9 + pmaddubsw m15, m1, m8 + pmaddubsw m17, m3, m9 + mova m0, m2 + mova m1, m3 + vpermq m12, m18, m12 + vpermq m13, m18, m13 + paddw m14, m16 + paddw m15, m17 + pmaddubsw m16, m4, m10 + pmaddubsw m17, m5, m10 + punpcklbw m6, m12 + punpcklbw m12, m13 + mova m2, m4 + mova m3, m5 + paddw m14, m16 + paddw m15, m17 + pmaddubsw m16, m6, m11 + pmaddubsw m17, m12, m11 + mova m4, m6 + mova m5, m12 + paddw m14, m16 + paddw m15, m17 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + mova m6, m13 + mova [tmpq+ 0], m14 + mova [tmpq+64], m15 + add tmpq, 64*2 + sub hd, 2 + jg .v_w32_loop + vzeroupper + RET +.v_w64: + mov wd, 64 + jmp .v_start +.v_w128: + mov wd, 128 +.v_start: + WIN64_SPILL_XMM 27 + mova m26, [bilin_v_perm64] + lea r6d, [hq+wq*2] + mov r5, srcq + mov r7, tmpq +.v_loop0: + vpermq m0, m26, [srcq+strideq*0] + vpermq m1, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m2, m26, [srcq+strideq*0] + vpermq m3, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m4, m26, [srcq+strideq*0] + vpermq m5, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m6, m26, [srcq+strideq*0] + punpckhbw m12, m0, m1 + punpcklbw m0, m1 + punpckhbw m13, m1, m2 + punpcklbw m1, m2 + punpckhbw m14, m2, m3 + punpcklbw m2, m3 + punpckhbw m15, m3, m4 + punpcklbw m3, m4 + punpckhbw m16, m4, m5 + punpcklbw m4, m5 + punpckhbw m17, m5, m6 + punpcklbw m5, m6 +.v_loop: + vpermq m18, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m19, m26, [srcq+strideq*0] + pmaddubsw m20, m0, m8 + pmaddubsw m21, m12, m8 + pmaddubsw m22, m1, m8 + pmaddubsw m23, m13, m8 + mova m0, m2 + mova m12, m14 + mova m1, m3 + mova m13, m15 + pmaddubsw m2, m9 + pmaddubsw m14, m9 + pmaddubsw m3, m9 + pmaddubsw m15, m9 + punpckhbw m24, m6, m18 + punpcklbw m6, m18 + paddw m20, m2 + paddw m21, m14 + paddw m22, m3 + paddw m23, m15 + mova m2, m4 + mova m14, m16 + mova m3, m5 + mova m15, m17 + pmaddubsw m4, m10 + pmaddubsw m16, m10 + pmaddubsw m5, m10 + pmaddubsw m17, m10 + punpckhbw m25, m18, m19 + punpcklbw m18, m19 + paddw m20, m4 + paddw m21, m16 + paddw m22, m5 + paddw m23, m17 + mova m4, m6 + mova m16, m24 + mova m5, m18 + mova m17, m25 + pmaddubsw m6, m11 + pmaddubsw m24, m11 + pmaddubsw m18, m11 + pmaddubsw m25, m11 + paddw m20, m6 + paddw m21, m24 + paddw m22, m18 + paddw m23, m25 + pmulhrsw m20, m7 + pmulhrsw m21, m7 + pmulhrsw m22, m7 + pmulhrsw m23, m7 + mova m6, m19 + mova [tmpq+wq*0+ 0], m20 + mova [tmpq+wq*0+64], m21 + mova [tmpq+wq*2+ 0], m22 + mova [tmpq+wq*2+64], m23 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_loop + add r5, 64 + add r7, 128 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .v_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + %assign stack_size_padded 0 + WIN64_SPILL_XMM 16 + cmp wd, 4 + je .hv_w4 + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r7+mxq*8+subpel_filters-prep_avx512icl+0] + vpbroadcastd m11, [r7+mxq*8+subpel_filters-prep_avx512icl+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + tzcnt wd, wd + vpbroadcastd m8, [pd_2] + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_hv)] + vpbroadcastd m9, [pd_32] + add wq, r7 + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl] + lea stride3q, [strideq*3] + sub srcq, stride3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + jmp wq +.hv_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl] + lea stride3q, [strideq*3] + sub srcq, stride3q + mov r3d, 0x04 + kmovb k1, r3d + kshiftlb k2, k1, 2 + kshiftlb k3, k1, 4 + vpbroadcastd m10, [pd_2] + vbroadcasti128 m16, [subpel_h_shufA] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m11, [pd_32] + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + movq xm3, [srcq+strideq*0] + vpbroadcastq ym2, [srcq+strideq*1] + vpbroadcastq ym3{k1}, [srcq+strideq*2] + vpbroadcastq m2{k2}, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3{k2}, [srcq+strideq*0] + vpbroadcastq m2{k3}, [srcq+strideq*1] + vpbroadcastq m3{k3}, [srcq+strideq*2] + mova m17, [spel_hv_perm4a] + movu m18, [spel_hv_perm4b] + mova m0, m10 + mova m1, m10 + pshufb m2, m16 + pshufb m3, m16 + vpdpbusd m0, m2, m8 + vpdpbusd m1, m3, m8 + packssdw m0, m1 ; _ 0 1 2 3 4 5 6 + psraw m0, 2 + vpermb m1, m17, m0 ; 01 12 23 34 + vpermb m2, m18, m0 ; 23 34 45 56 +.hv_w4_loop: + movq xm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + movq xm4, [srcq+strideq*0] + vpbroadcastq ym3{k1}, [srcq+strideq*1] + vpbroadcastq ym4{k1}, [srcq+strideq*2] + mova ym5, ym10 + mova ym6, ym10 + pshufb ym3, ym16 + pshufb ym4, ym16 + vpdpbusd ym5, ym3, ym8 + vpdpbusd ym6, ym4, ym8 + mova m7, m11 + packssdw ym5, ym6 ; 7 8 9 a _ _ _ _ + psraw ym5, 2 + valignq m0, m5, m0, 4 ; _ 4 5 6 7 8 9 a + vpdpwssd m7, m1, m12 + vpdpwssd m7, m2, m13 + vpermb m1, m17, m0 ; 45 56 67 78 + vpermb m2, m18, m0 ; 67 78 89 9a + vpdpwssd m7, m1, m14 + vpdpwssd m7, m2, m15 + psrad m7, 6 + vpmovdw [tmpq], m7 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + WIN64_SPILL_XMM 24 + vbroadcasti128 m16, [subpel_h_shufA] + vbroadcasti128 m17, [subpel_h_shufB] + vbroadcasti128 m18, [subpel_h_shufC] + vinserti128 ym0, [srcq+strideq*0], 1 + vinserti128 m0, [srcq+strideq*1], 2 + vinserti128 m0, [srcq+strideq*2], 3 + movu xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 ym1, [srcq+strideq*0], 1 + vinserti128 m1, [srcq+strideq*1], 2 + vinserti128 m1, [srcq+strideq*2], 3 + mova m2, m8 + mova m4, m8 + mova m3, m8 + mova m5, m8 + pshufb m20, m0, m16 + pshufb m21, m0, m17 + pshufb m22, m0, m18 + pshufb m23, m1, m16 + pshufb m6, m1, m17 + pshufb m7, m1, m18 + vpdpbusd m2, m20, m10 + vpdpbusd m4, m21, m10 + vpdpbusd m2, m21, m11 + vpdpbusd m4, m22, m11 + vpdpbusd m3, m23, m10 + vpdpbusd m5, m6, m10 + vpdpbusd m3, m6, m11 + vpdpbusd m5, m7, m11 + packssdw m2, m4 + packssdw m3, m5 + psraw m2, 2 ; _ 0 1 2 + psraw m3, 2 ; 3 4 5 6 + valignq m0, m3, m2, 2 ; 0 1 2 3 + valignq m1, m3, m2, 4 ; 1 2 3 4 + valignq m2, m3, m2, 6 ; 2 3 4 5 + punpcklwd m4, m0, m1 ; 01a 12a 23a 34a + punpckhwd m5, m0, m1 ; 01b 12b 23b 34b + punpcklwd m6, m2, m3 ; 23a 34a 45a 56a + punpckhwd m7, m2, m3 ; 23b 34b 45b 56b +.hv_w8_loop: + movu xm19, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 ym19, [srcq+strideq*0], 1 + vinserti128 m19, [srcq+strideq*1], 2 + vinserti128 m19, [srcq+strideq*2], 3 + mova m20, m9 + mova m21, m9 + mova m22, m8 + mova m23, m8 + vpdpwssd m20, m4, m12 + vpdpwssd m21, m5, m12 + vpdpwssd m20, m6, m13 + vpdpwssd m21, m7, m13 + pshufb m0, m19, m16 + pshufb m1, m19, m17 + pshufb m2, m19, m18 + vpdpbusd m22, m0, m10 + vpdpbusd m23, m1, m10 + vpdpbusd m22, m1, m11 + vpdpbusd m23, m2, m11 + packssdw m22, m23 + psraw m22, 2 ; 7 8 9 A + valignq m0, m22, m3, 2 ; 4 5 6 7 + valignq m1, m22, m3, 4 ; 5 6 7 8 + valignq m2, m22, m3, 6 ; 6 7 8 9 + mova m3, m22 + punpcklwd m4, m0, m1 ; 45a 56a 67a 78a + punpckhwd m5, m0, m1 ; 45b 56b 67b 78b + punpcklwd m6, m2, m3 ; 67a 78a 89a 9Aa + punpckhwd m7, m2, m3 ; 67b 78b 89b 9Ab + vpdpwssd m20, m4, m14 + vpdpwssd m21, m5, m14 + vpdpwssd m20, m6, m15 + vpdpwssd m21, m7, m15 + psrad m20, 6 + psrad m21, 6 + packssdw m20, m21 + mova [tmpq], m20 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + mov wd, 16*2 + jmp .hv_start +.hv_w32: + mov wd, 32*2 + jmp .hv_start +.hv_w64: + mov wd, 64*2 + jmp .hv_start +.hv_w128: + mov wd, 128*2 +.hv_start: + WIN64_SPILL_XMM 31 + mova m16, [spel_h_perm16a] + mova m17, [spel_h_perm16b] + mova m18, [spel_h_perm16c] + lea r6d, [hq+wq*8-256] + mov r5, srcq + mov r7, tmpq +.hv_loop0: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym1, [srcq+strideq*0] + vinserti32x8 m1, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym2, [srcq+strideq*0] + vinserti32x8 m2, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym3, [srcq+strideq*0] + mova m4, m8 + mova m5, m8 + mova m6, m8 + mova m7, m8 + vpermb m19, m16, m0 + vpermb m20, m17, m0 + vpermb m21, m18, m0 + vpermb m22, m16, m1 + vpermb m23, m17, m1 + vpermb m24, m18, m1 + vpermb m25, m16, m2 + vpermb m26, m17, m2 + vpermb m27, m18, m2 + vpermb ym28, ym16, ym3 + vpermb ym29, ym17, ym3 + vpermb ym30, ym18, ym3 + mova m0, m8 + mova m1, m8 + mova ym2, ym8 + mova ym3, ym8 + vpdpbusd m4, m19, m10 + vpdpbusd m5, m20, m10 + vpdpbusd m6, m22, m10 + vpdpbusd m7, m23, m10 + vpdpbusd m0, m25, m10 + vpdpbusd m1, m26, m10 + vpdpbusd ym2, ym28, ym10 + vpdpbusd ym3, ym29, ym10 + vpdpbusd m4, m20, m11 + vpdpbusd m5, m21, m11 + vpdpbusd m6, m23, m11 + vpdpbusd m7, m24, m11 + vpdpbusd m0, m26, m11 + vpdpbusd m1, m27, m11 + vpdpbusd ym2, ym29, ym11 + vpdpbusd ym3, ym30, ym11 + packssdw m4, m5 + packssdw m6, m7 + packssdw m0, m1 + packssdw ym2, ym3 + psraw m4, 2 ; 0a 0b 1a 1b + psraw m6, 2 ; 2a 2b 3a 3b + psraw m0, 2 ; 4a 4b 5a 5b + psraw ym2, 2 ; 6a 6b __ __ + vshufi32x4 m5, m4, m6, q1032 ; 1a 1b 2a 2b + vshufi32x4 m7, m6, m0, q1032 ; 3a 3b 4a 4b + vshufi32x4 m1, m0, m2, q1032 ; 5a 5b 6a 6b + punpcklwd m2, m4, m5 ; 01a 01c 12a 12c + punpckhwd m3, m4, m5 ; 01b 01d 12b 12d + punpcklwd m4, m6, m7 ; 23a 23c 34a 34c + punpckhwd m5, m6, m7 ; 23b 23d 34b 34d + punpcklwd m6, m0, m1 ; 45a 45c 56a 56c + punpckhwd m7, m0, m1 ; 45b 45d 56b 56d +.hv_loop: + movu ym19, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m19, [srcq+strideq*0], 1 + mova m20, m9 + mova m21, m9 + mova m22, m8 + mova m23, m8 + vpdpwssd m20, m2, m12 + vpdpwssd m21, m3, m12 + vpdpwssd m20, m4, m13 + vpdpwssd m21, m5, m13 + vpermb m24, m16, m19 + vpermb m25, m17, m19 + vpermb m26, m18, m19 + vpdpbusd m22, m24, m10 + vpdpbusd m23, m25, m10 + vpdpbusd m22, m25, m11 + vpdpbusd m23, m26, m11 + packssdw m22, m23 + psraw m22, 2 ; 7a 7b 8a 8b + vshufi32x4 m0, m1, m22, q1032 ; 6a 6b 7a 7b + mova m2, m4 + mova m3, m5 + mova m1, m22 + mova m4, m6 + mova m5, m7 + punpcklwd m6, m0, m1 ; 67a 67c 78a 78c + punpckhwd m7, m0, m1 ; 67b 67d 78b 78d + vpdpwssd m20, m4, m14 + vpdpwssd m21, m5, m14 + vpdpwssd m20, m6, m15 + vpdpwssd m21, m7, m15 + psrad m20, 6 + psrad m21, 6 + packssdw m20, m21 + mova [tmpq+wq*0], ym20 + vextracti32x8 [tmpq+wq*1], m20, 1 + lea tmpq, [tmpq+wq*2] + sub hd, 2 + jg .hv_loop + add r5, 16 + add r7, 32 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .hv_loop0 + RET + +cglobal warp_affine_8x8t_8bpc, 4, 7, 22, tmp, ts + vpbroadcastd m9, [pd_16384] + mova ym15, [warp_8x8t_end] + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx512icl).main + jmp .start +.loop: + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx512icl).main2 + lea tmpq, [tmpq+tsq*4] +.start: + paddd m16, m16 + vpermb m16, m15, m16 + mova [tmpq+tsq*0], xm16 + vextracti128 [tmpq+tsq*2], ym16, 1 + sub r6d, 0x1800 + jg .loop + RET + +cglobal warp_affine_8x8_8bpc, 4, 7, 22, dst, ds, src, ss, abcd, filter + vpbroadcastd m9, [pd_262144] + mova xm15, [warp_8x8_end] + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m16, 19 + packuswb m16, m16 + vpermb m16, m15, m16 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + sub r6d, 0x1800 + jg .loop + RET +ALIGN function_align +.main: + vpbroadcastd m1, [pd_512] +%if WIN64 + mov abcdq, r5mp + vpaddd ym18, ym1, r6m {1to8} ; mx +%else + add r5d, 512 + vpbroadcastd ym18, r5d +%endif + vpaddd ym20, ym1, r7m {1to8} ; my + mova ym16, [pd_0to7] + vpbroadcastd ym19, [abcdq+4*0] + vpbroadcastd ym21, [abcdq+4*1] + lea r4, [ssq*3+3] + mova m10, [warp_8x8_permA] + mov r6d, 0x5555 + mova m11, [warp_8x8_permB] + lea filterq, [mc_warp_filter+64*8] + vpbroadcastq m12, [warp_8x8_hpack] + sub srcq, r4 ; src -= src_stride*3 + 3 + vbroadcasti32x4 m13, [warp_8x8_permC] + kxnorb k2, k2, k2 + vbroadcasti32x4 m14, [warp_8x8_permD] + vpdpwssd ym18, ym19, ym16 ; alpha + vpdpwssd ym20, ym21, ym16 ; gamma + vbroadcasti32x4 m0, [srcq] + psrad ym19, 16 ; beta + psrad ym21, 16 ; delta + kmovw k1, r6d + psrad ym16, ym18, 10 + kmovb k3, k2 + paddd ym18, ym19 + vpgatherdq m2{k2}, [filterq+ym16*8] ; filter_x0 + psrld m1, 8 ; pd_2 + pshufb m0, m11 + paddd m8, m1, m1 ; pd_4 + vpdpbusd m1, m0, m2 + call .h + psllq m2, m1, 45 + pslld m1, 13 + paddd m1, m2 + vpshrdq m1, m0, 48 ; 01 12 + call .h + vpshrdq m2, m1, m0, 48 ; 23 34 + call .h + vpshrdq m3, m2, m0, 48 ; 45 56 +.main2: + call .h + psrad ym17, ym20, 10 + kmovb k2, k3 + paddd ym20, ym21 + vpgatherdq m7{k3}, [filterq+ym17*8] ; filter_y0 + psrad ym16, ym20, 10 + kmovb k3, k2 + paddd ym20, ym21 + vpgatherdq m17{k2}, [filterq+ym16*8] ; filter_y1 + shufps m5, m7, m17, q2020 ; a0 a1 a2 a3 b0 b1 b2 b3 A0 A1 A2 A3 B0 B1 B2 B3 + mova m16, m9 + pshufb m4, m5, m13 ; a0 a1 A0 A1 b0 b1 B0 B1 + vpdpwssd m16, m1, m4 + pshufb m5, m14 ; a2 a3 A2 A3 b2 b3 B2 B3 + mova m1, m2 + vpdpwssd m16, m2, m5 + shufps m5, m7, m17, q3131 ; a4 a5 a6 a7 b4 b5 b6 b7 A4 A5 A6 A7 B4 B5 B6 B7 + mova m2, m3 + pshufb m4, m5, m13 ; a4 a5 A4 A5 b4 b5 B4 B5 + vpdpwssd m16, m3, m4 + vpshrdq m3, m0, 48 ; 67 78 + pshufb m5, m14 ; a6 a7 A6 A7 b6 b7 B6 B7 + vpdpwssd m16, m3, m5 + ret +ALIGN function_align +.h: + movu xm5, [srcq+ssq*1] + psrad ym16, ym18, 10 + lea srcq, [srcq+ssq*2] + vinserti32x4 ym5, [srcq+ssq*0], 1 + kmovb k2, k3 + paddd ym18, ym19 + vpgatherdq m6{k3}, [filterq+ym16*8] ; filter_x1 + psrad ym17, ym18, 10 + kmovb k3, k2 + paddd ym18, ym19 + vpgatherdq m16{k2}, [filterq+ym17*8] ; filter_x2 + mova m0, m8 + vpermb m4, m10, m5 ; a4 b0 a5 b1 a6 b2 a7 b3 a8 b4 a9 b5 aa b6 ab b7 + vpshldq m17, m16, m6, 32 ; a4 a5 a6 a7 b0 b1 b2 b3 + vpdpbusd m0, m4, m17 + vpermb m5, m11, m5 ; a0 b4 a1 b5 a2 b6 a3 b7 a4 b8 a5 b9 a6 ba a7 bb + vmovdqa32 m16{k1}, m6 ; a0 a1 a2 a3 b4 b5 b6 b7 + vpdpbusd m0, m5, m16 + vpmultishiftqb m0, m12, m0 ; 1 1 2 2 (>> 3) + ret + +%macro BIDIR_FN 1 ; op + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM %1 0 + vextracti32x4 xm1, ym0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_ret + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_ret: + RET +.w4_h16: + vpbroadcastd m7, strided + pmulld m7, [bidir_sctr_w4] + %1 0 + kxnorw k1, k1, k1 + vpscatterdd [dstq+m7]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM %1 0 + vextracti32x4 xm1, ym0, 1 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + %1_INC_PTR 2 + lea dstq, [dstq+strideq*4] +.w8_h8: + %1 0 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq ], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 2 + lea dstq, [dstq+strideq*4] +.w16: + %1 0 + vpermq m0, m0, q3120 + mova [dstq ], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m7, [pb_02461357] +.w32_loop: + %1 0 + %1_INC_PTR 2 + vpermq m0, m7, m0 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m7, [pb_02461357] +.w64_loop: + %1 0 + %1_INC_PTR 2 + vpermq m0, m7, m0 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m7, [pb_02461357] +.w128_loop: + %1 0 + vpermq m6, m7, m0 + %1 2 + mova [dstq+64*0], m6 + %1_INC_PTR 4 + vpermq m6, m7, m0 + mova [dstq+64*1], m6 + add dstq, strideq + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + mova m0, [tmp1q+(%1+0)*mmsize] + paddw m0, [tmp2q+(%1+0)*mmsize] + mova m1, [tmp1q+(%1+1)*mmsize] + paddw m1, [tmp2q+(%1+1)*mmsize] + pmulhrsw m0, m4 + pmulhrsw m1, m4 + packuswb m0, m1 +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +cglobal avg_8bpc, 4, 7, 5, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx512icl_table + lea r6, [avg_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m4, [base+pw_1024] + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m0, [tmp1q+(%1+0)*mmsize] + psubw m2, m0, [tmp2q+(%1+0)*mmsize] + mova m1, [tmp1q+(%1+1)*mmsize] + psubw m3, m1, [tmp2q+(%1+1)*mmsize] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg_avx512icl_table + lea r6, [w_avg_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + vpbroadcastw m4, r6m ; weight + movsxd wq, dword [r6+wq*4] + vpbroadcastd m5, [base+pw_2048] + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + pxor m0, m0 + mov tmp1q, tmp2q + psubw m4, m0, m4 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 +%if mmsize == 64 + vpermq m3, m8, [maskq+%1*32] +%else + vpermq m3, [maskq+%1*16], q3120 +%endif + mova m0, [tmp2q+(%1+0)*mmsize] + psubw m1, m0, [tmp1q+(%1+0)*mmsize] + psubb m3, m4, m3 + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 + punpcklbw m2, m4, m3 ; -m << 9 + pmulhw m1, m2 + paddw m0, m1 + mova m1, [tmp2q+(%1+1)*mmsize] + psubw m2, m1, [tmp1q+(%1+1)*mmsize] + paddw m2, m2 + punpckhbw m3, m4, m3 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*32 + add tmp2q, %1*64 + add tmp1q, %1*64 +%endmacro + +cglobal mask_8bpc, 4, 8, 6, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx512icl_table + lea r7, [mask_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + pxor m4, m4 + mova m8, [base+bilin_v_perm64] + vpbroadcastd m5, [base+pw_2048] + add wq, r7 + BIDIR_FN MASK + +%macro W_MASK 4-5 0 ; dst, mask, tmp_offset[1-2], 4:4:4 + mova m%1, [tmp1q+mmsize*%3] + mova m1, [tmp2q+mmsize*%3] + psubw m1, m%1 + pabsw m%2, m1 + psubusw m%2, m6, m%2 + psrlw m%2, 8 ; 64 - m + psllw m2, m%2, 10 + pmulhw m1, m2 + paddw m%1, m1 + mova m1, [tmp1q+mmsize*%4] + mova m2, [tmp2q+mmsize*%4] + psubw m2, m1 + pabsw m3, m2 + psubusw m3, m6, m3 + vpshldw m%2, m3, 8 + psllw m3, m%2, 10 +%if %5 + psubb m%2, m5, m%2 +%endif + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m%1, m7 + pmulhrsw m1, m7 + packuswb m%1, m1 +%endmacro + +cglobal w_mask_420_8bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx512icl_table + lea r7, [w_mask_420_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + vpbroadcastd m9, [base+pb_m64] ; -1 << 6 + mova ym10, [base+wm_420_mask+32] + vpbroadcastd m8, [base+wm_sign+r6*8] ; (258 - sign) << 6 + add wq, r7 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + mova m5, [wm_420_perm4] + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1 + vinserti128 ym5, [wm_420_perm4+32], 1 + vpermb ym4, ym5, ym4 + vpdpbusd ym8, ym4, ym9 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + vpermb ym8, ym10, ym8 + movq [maskq], xm8 + RET +.w4_h16: + vpbroadcastd m11, strided + pmulld m11, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + vpdpbusd m8, m4, m9 + kxnorw k1, k1, k1 + vpermb m8, m10, m8 + mova [maskq], xm8 + vpscatterdd [dstq+m11]{k1}, m0 + RET +.w8: + mova m5, [wm_420_perm8] + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1 + vinserti128 ym5, [wm_420_perm8+32], 1 + vpermb ym4, ym5, ym4 + vpdpbusd ym8, ym4, ym9 + vpermb m8, m10, m8 + mova [maskq], xm8 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 16 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + mova m1, m8 + vpdpbusd m1, m4, m9 + vpermb m1, m10, m1 + mova [maskq], xm1 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16: + mova m5, [wm_420_perm16] +.w16_loop: + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + mova m1, m8 + vpdpbusd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m0, q3120 + mova [maskq], xm1 + add maskq, 16 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m5, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpbusd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + mova [maskq], xm1 + add maskq, 16 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m12, [wm_420_perm64] ; 0, 2, 4, 6, 8, 10, 12, 14 + psrlq m13, m12, 4 ; 1, 3, 5, 7, 9, 11, 13, 15 +.w64_loop: + W_MASK 0, 4, 0, 2 + W_MASK 11, 5, 1, 3 + mova m2, m8 + vpdpbusd m2, m4, m9 + mova m3, m8 + vpdpbusd m3, m5, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermt2b m2, m10, m3 + mova m1, m0 + vpermt2q m0, m12, m11 + vpermt2q m1, m13, m11 + mova [maskq], ym2 + add maskq, 32 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64_loop + RET +.w128: + pmovzxbq m14, [wm_420_perm64] + mova m10, [wm_420_mask] + psrlq m15, m14, 4 +.w128_loop: + W_MASK 0, 12, 0, 4 + W_MASK 11, 13, 1, 5 + mova m4, m8 + vpdpbusd m4, m12, m9 + mova m5, m8 + vpdpbusd m5, m13, m9 + mova m1, m0 + vpermt2q m0, m14, m11 + vpermt2q m1, m15, m11 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*1+64*0], m1 + W_MASK 0, 12, 2, 6 + W_MASK 11, 13, 3, 7 + vprold m4, 16 + vprold m5, 16 + vpdpbusd m4, m12, m9 + vpdpbusd m5, m13, m9 + add tmp1q, 512 + add tmp2q, 512 + vpermt2b m4, m10, m5 + mova m1, m0 + vpermt2q m0, m14, m11 + vpermt2q m1, m15, m11 + mova [maskq], m4 + add maskq, 64 + mova [dstq+strideq*0+64*1], m0 + mova [dstq+strideq*1+64*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w128_loop + RET + +cglobal w_mask_422_8bpc, 4, 8, 14, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx512icl_table + lea r7, [w_mask_422_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + vpbroadcastd m9, [base+pw_m128] + mova m10, [base+wm_422_mask] + vpbroadcastd m11, [base+pb_127] + add wq, r7 + vpbroadcastd m8, [base+wm_sign+4+r6*4] + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1 + movhps xm10, [wm_422_mask+16] + vpdpwssd ym8, ym4, ym9 + vpermb ym8, ym10, ym8 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + pand xm8, xm11 + mova [maskq], xm8 + RET +.w4_h16: + vpbroadcastd m5, strided + pmulld m5, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1 + vpdpwssd m8, m4, m9 + kxnorw k1, k1, k1 + vpermb m8, m10, m8 + pand ym8, ym11 + mova [maskq], ym8 + vpscatterdd [dstq+m5]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1 + movhps xm10, [wm_422_mask+16] + vpdpwssd ym8, ym4, ym9 + vpermb ym8, ym10, ym8 + pand xm8, xm11 + mova [maskq], xm8 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 32 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + vpermb m1, m10, m1 + pand ym1, ym11 + mova [maskq], ym1 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 32 + lea dstq, [dstq+strideq*4] +.w16: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + vpermb m1, m10, m1 + vpermq m0, m0, q3120 + pand ym1, ym11 + mova [maskq], ym1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m5, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + pand ym1, ym11 + mova [maskq], ym1 + add maskq, 32 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m5, [pb_02461357] +.w64_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + pand ym1, ym11 + mova [maskq], ym1 + add maskq, 32 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m13, [pb_02461357] +.w128_loop: + W_MASK 0, 4, 0, 1 + W_MASK 12, 5, 2, 3 + mova m2, m8 + vpdpwssd m2, m4, m9 + mova m3, m8 + vpdpwssd m3, m5, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermt2b m2, m10, m3 + vpermq m0, m13, m0 + vpermq m1, m13, m12 + pand m2, m11 + mova [maskq], m2 + add maskq, 64 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 8, 12, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx512icl_table + lea r7, [w_mask_444_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m5, [base+pb_64] + vpbroadcastd m7, [base+pw_2048] + mova m8, [base+wm_444_mask] + add wq, r7 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1, 1 + vinserti128 ym8, [wm_444_mask+32], 1 + vpermb ym4, ym8, ym4 + mova [maskq], ym4 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + RET +.w4_h16: + vpbroadcastd m9, strided + pmulld m9, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + kxnorw k1, k1, k1 + mova [maskq], m4 + vpscatterdd [dstq+m9]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1, 1 + vinserti128 ym8, [wm_444_mask+32], 1 + vpermb ym4, ym8, ym4 + mova [maskq], ym4 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 64 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + mova [maskq], m4 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 64 + lea dstq, [dstq+strideq*4] +.w16: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + vpermq m0, m0, q3120 + mova [maskq], m4 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m9, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + add tmp1q, 128 + add tmp2q, 128 + vpermq m0, m9, m0 + mova [maskq], m4 + add maskq, 64 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m9, [pb_02461357] +.w64_loop: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + add tmp1q, 128 + add tmp2q, 128 + vpermq m0, m9, m0 + mova [maskq], m4 + add maskq, 64 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m11, [pb_02461357] +.w128_loop: + W_MASK 0, 4, 0, 1, 1 + W_MASK 10, 9, 2, 3, 1 + vpermb m4, m8, m4 + vpermb m9, m8, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermq m0, m11, m0 + vpermq m10, m11, m10 + mova [maskq+64*0], m4 + mova [maskq+64*1], m9 + add maskq, 128 + mova [dstq+64*0], m0 + mova [dstq+64*1], m10 + add dstq, strideq + dec hd + jg .w128_loop + RET + +cglobal blend_8bpc, 3, 7, 8, dst, ds, tmp, w, h, mask +%define base r6-blend_avx512icl_table + lea r6, [blend_avx512icl_table] + tzcnt wd, wm + movifnidn maskq, maskmp + movifnidn hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m6, [base+pb_64] + vpbroadcastd m7, [base+pw_512] + sub tmpq, maskq + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + vpbroadcastd xmm1, [dstq+dsq*2] + pinsrd xmm1, [dstq+r6 ], 3 + mova xmm4, [maskq] + mova xmm5, [maskq+tmpq] + add maskq, 4*4 + psubb xmm3, xm6, xmm4 + punpcklbw xmm0, xmm5 + punpcklbw xmm2, xmm3, xmm4 + punpckhbw xmm1, xmm5 + punpckhbw xmm3, xmm4 + pmaddubsw xmm0, xmm2 + pmaddubsw xmm1, xmm3 + pmulhrsw xmm0, xm7 + pmulhrsw xmm1, xm7 + packuswb xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + pextrd [dstq+dsq*2], xmm0, 2 + pextrd [dstq+r6 ], xmm0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +.w8: + movq xmm0, [dstq+dsq*0] + vpbroadcastq xmm1, [dstq+dsq*1] + vpbroadcastq ymm2, [dstq+dsq*2] + vpbroadcastq ymm3, [dstq+r6 ] + mova ymm4, [maskq] + mova ymm5, [maskq+tmpq] + add maskq, 8*4 + vpblendd ymm0, ymm2, 0x30 + vpblendd ymm1, ymm3, 0xc0 + psubb ymm3, ym6, ymm4 + punpcklbw ymm0, ymm5 + punpcklbw ymm2, ymm3, ymm4 + punpckhbw ymm1, ymm5 + punpckhbw ymm3, ymm4 + pmaddubsw ymm0, ymm2 + pmaddubsw ymm1, ymm3 + pmulhrsw ymm0, ym7 + pmulhrsw ymm1, ym7 + packuswb ymm0, ymm1 + vextracti128 xmm1, ymm0, 1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + movq [dstq+dsq*2], xmm1 + movhps [dstq+r6 ], xmm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + vzeroupper + RET +.w16: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + vinserti32x4 m1, [dstq+dsq*2], 2 + mova m4, [maskq] + vinserti32x4 m1, [dstq+r6 ], 3 + mova m5, [maskq+tmpq] + add maskq, 16*4 + psubb m3, m6, m4 + punpcklbw m0, m1, m5 + punpcklbw m2, m3, m4 + punpckhbw m1, m5 + punpckhbw m3, m4 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + vextracti32x4 [dstq+dsq*2], m0, 2 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w16 + RET +.w32: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + mova m4, [maskq] + mova m5, [maskq+tmpq] + add maskq, 32*2 + psubb m3, m6, m4 + punpcklbw m0, m1, m5 + punpcklbw m2, m3, m4 + punpckhbw m1, m5 + punpckhbw m3, m4 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_avx512icl_table + lea r5, [blend_v_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_avx512icl_table + jmp wq +.w2: + vpbroadcastd xmm2, [maskq+2*2] +.w2_s0_loop: + movd xmm0, [dstq+dsq*0] + pinsrw xmm0, [dstq+dsq*1], 1 + movd xmm1, [tmpq] + add tmpq, 2*2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_s0_loop + RET +.w4: + vpbroadcastq xmm2, [maskq+4*2] +.w4_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movq xmm1, [tmpq] + add tmpq, 4*2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova xmm3, [maskq+8*2] +.w8_loop: + movq xmm0, [dstq+dsq*0] + vpbroadcastq xmm1, [dstq+dsq*1] + mova xmm2, [tmpq] + add tmpq, 8*2 + punpcklbw xmm0, xmm2 + punpckhbw xmm1, xmm2 + pmaddubsw xmm0, xmm3 + pmaddubsw xmm1, xmm3 + pmulhrsw xmm0, xm5 + pmulhrsw xmm1, xm5 + packuswb xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + vbroadcasti32x4 ym3, [maskq+16*2] + vbroadcasti32x4 ym4, [maskq+16*3] +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + mova ym2, [tmpq] + add tmpq, 16*2 + punpcklbw ym0, ym1, ym2 + punpckhbw ym1, ym2 + pmaddubsw ym0, ym3 + pmaddubsw ym1, ym4 + pmulhrsw ym0, ym5 + pmulhrsw ym1, ym5 + packuswb ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + mova m4, [maskq+32*2] + vshufi32x4 m3, m4, m4, q2020 + vshufi32x4 m4, m4, q3131 +.w32_loop: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + mova m2, [tmpq] + add tmpq, 32*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop + RET + +cglobal blend_h_8bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base r6-blend_h_avx512icl_table + lea r6, [blend_h_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea maskq, [base+obmc_masks+hq*2] + vpbroadcastd m5, [base+pw_512] + lea hd, [hq*3] + add wq, r6 + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xmm0, [dstq+dsq*0] + pinsrw xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movd xmm1, [tmpq] + add tmpq, 2*2 + punpcklwd xmm2, xmm2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova xmm3, [blend_shuf] +.w4_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movq xmm1, [tmpq] + add tmpq, 4*2 + pshufb xmm2, xmm3 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + vbroadcasti128 ymm4, [blend_shuf] + shufpd ymm4, ymm4, 0x03 +.w8_loop: + vpbroadcastq ymm1, [dstq+dsq*0] + movq xmm0, [dstq+dsq*1] + vpblendd ymm0, ymm1, 0x30 + vpbroadcastd ymm3, [maskq+hq*2] + movq xmm1, [tmpq+8*1] + vinserti128 ymm1, [tmpq+8*0], 1 + add tmpq, 8*2 + pshufb ymm3, ymm4 + punpcklbw ymm0, ymm1 + pmaddubsw ymm0, ymm3 + pmulhrsw ymm0, ym5 + vextracti128 xmm1, ymm0, 1 + packuswb xmm0, xmm1 + movhps [dstq+dsq*0], xmm0 + movq [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + vzeroupper + RET +.w16: + vbroadcasti32x4 ym4, [blend_shuf] + shufpd ym4, ym4, 0x0c +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + vpbroadcastd ym3, [maskq+hq*2] + mova ym2, [tmpq] + add tmpq, 16*2 + pshufb ym3, ym4 + punpcklbw ym0, ym1, ym2 + punpckhbw ym1, ym2 + pmaddubsw ym0, ym3 + pmaddubsw ym1, ym3 + pmulhrsw ym0, ym5 + pmulhrsw ym1, ym5 + packuswb ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +.w32: + vbroadcasti32x4 m4, [blend_shuf] + shufpd m4, m4, 0xf0 +.w32_loop: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + vpbroadcastd m3, [maskq+hq*2] + mova m2, [tmpq] + add tmpq, 32*2 + pshufb m3, m4 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + vpbroadcastw m3, [maskq+hq*2] + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m6, [maskq+hq*2] + mova m2, [dstq+64*0] + mova m1, [tmpq+64*0] + mova m3, [dstq+64*1] + mova m4, [tmpq+64*1] + add tmpq, 64*2 + punpcklbw m0, m2, m1 + punpckhbw m2, m1 + pmaddubsw m0, m6 + pmaddubsw m2, m6 + punpcklbw m1, m3, m4 + punpckhbw m3, m4 + pmaddubsw m1, m6 + pmaddubsw m3, m6 + REPX {pmulhrsw x, m5}, m0, m2, m1, m3 + packuswb m0, m2 + packuswb m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal resize_8bpc, 6, 12, 19, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + mov r6, ~0 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + kmovq k3, r6 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pw_m256] + vpbroadcastd m7, [base+pd_63] + vbroadcasti32x4 m15, [base+pb_8x0_8x8] + vpdpwssd m8, m5, [base+rescale_mul] ; mx+dx*[0-15] + pslld m5, 4 ; dx*16 + pslld m6, 14 + pxor m2, m2 + mova m16, [base+resize_permA] + mova m17, [base+resize_permB] + mova xm18, [base+resize_permC] +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + vptestmd k4, m1, m1 + pand m9, m7 ; filter offset (masked) + ktestw k4, k4 + jz .load + vextracti32x8 ym12, m0, 1 + vextracti32x8 ym13, m1, 1 + kmovq k1, k3 + kmovq k2, k3 + vpgatherdq m10{k1}, [srcq+ym0] + vpgatherdq m11{k2}, [srcq+ym12] + kmovq k1, k3 + kmovq k2, k3 + vpgatherdq m14{k1}, [base+resize_shuf+4+ym1] + vpgatherdq m0{k2}, [base+resize_shuf+4+ym13] + mova m12, m16 + mova m13, m17 + paddb m14, m15 + paddb m0, m15 + pshufb m10, m14 + pshufb m11, m0 + vpermi2d m12, m10, m11 + vpermi2d m13, m10, m11 + jmp .filter +.load: + kmovq k1, k3 + kmovq k2, k3 + vpgatherdd m12{k1}, [srcq+m0+0] + vpgatherdd m13{k2}, [srcq+m0+4] +.filter: + kmovq k1, k3 + kmovq k2, k3 + vpgatherdd m10{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m11{k2}, [base+resize_filter+m9*8+4] + mova m14, m2 + vpdpbusd m14, m12, m10 + vpdpbusd m14, m13, m11 + packssdw m14, m14 + pmulhrsw m14, m3 + packuswb m14, m14 + vpermd m14, m18, m14 + mova [dstq+xq], xm14 + paddd m4, m5 + add xd, 16 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/mc_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9599 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; Copyright © 2018, VideoLabs +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA 16 + +; dav1d_obmc_masks[] with 64-x interleaved +obmc_masks: db 0, 0, 0, 0 + ; 2 @4 + db 45, 19, 64, 0 + ; 4 @8 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 @16 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 @32 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 @64 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + +warp_8x8_shufA: db 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 8 +warp_8x8_shufB: db 4, 6, 8, 10, 5, 7, 9, 11, 5, 7, 9, 11, 6, 8, 10, 12 +warp_8x8_shufC: db 2, 4, 6, 8, 3, 5, 7, 9, 3, 5, 7, 9, 4, 6, 8, 10 +warp_8x8_shufD: db 6, 8, 10, 12, 7, 9, 11, 13, 7, 9, 11, 13, 8, 10, 12, 14 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_s_shuf2: db 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +bilin_h_shuf8: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +unpckw: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +rescale_mul: dd 0, 1, 2, 3 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 + +wm_420_sign: times 4 dw 258 + times 4 dw 257 +wm_422_sign: times 8 db 128 + times 8 db 127 + +pb_8x0_8x8: times 8 db 0 + times 8 db 8 +bdct_lb_dw: times 4 db 0 + times 4 db 4 + times 4 db 8 + times 4 db 12 + +pb_64: times 16 db 64 +pw_m256: times 8 dw -256 +pw_1: times 8 dw 1 +pw_2: times 8 dw 2 +pw_8: times 8 dw 8 +pw_15: times 8 dw 15 +pw_26: times 8 dw 26 +pw_34: times 8 dw 34 +pw_512: times 8 dw 512 +pw_1024: times 8 dw 1024 +pw_2048: times 8 dw 2048 +pw_6903: times 8 dw 6903 +pw_8192: times 8 dw 8192 +pd_32: times 4 dd 32 +pd_63: times 4 dd 63 +pd_512: times 4 dd 512 +pd_16384: times 4 dd 16484 +pd_32768: times 4 dd 32768 +pd_262144:times 4 dd 262144 +pd_0x3ff: times 4 dd 0x3ff +pd_0x4000:times 4 dd 0x4000 +pq_0x40000000: times 2 dq 0x40000000 + +const mc_warp_filter2 ; dav1d_mc_warp_filter[] reordered for pmaddubsw usage + ; [-1, 0) + db 0, 127, 0, 0, 0, 1, 0, 0, 0, 127, 0, 0, -1, 2, 0, 0 + db 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, 0 + db 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, 0 + db 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, 0 + db 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, 0 + db 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, 0 + db 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, 0 + db 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, 0 + db 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, 0 + db 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, 0 + db 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, 0 + db 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, 0 + db 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, 0 + db 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, 0 + db 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, 0 + db 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, 0 + db 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, 0 + db 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, 0 + db 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, 0 + db 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, 0 + db 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, 0 + db 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, 0 + db 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, 0 + db 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, 0 + db 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, 0 + db 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, 0 + db 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, 0 + db 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, 0 + db 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, 0 + db 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, 0 + db 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, 0 + db 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, 0 + ; [0, 1) + db 0, 0, 1, 0, 0, 127, 0, 0, 0, -1, 2, 0, 0, 127, 0, 0 + db 0, -3, 4, 1, 1, 127, -2, 0, 0, -5, 6, 1, 1, 127, -2, 0 + db 0, -6, 8, 1, 2, 126, -3, 0, -1, -7, 11, 2, 2, 126, -4, -1 + db -1, -8, 13, 2, 3, 125, -5, -1, -1, -10, 16, 3, 3, 124, -6, -1 + db -1, -11, 18, 3, 4, 123, -7, -1, -1, -12, 20, 3, 4, 122, -7, -1 + db -1, -13, 23, 3, 4, 121, -8, -1, -2, -14, 25, 4, 5, 120, -9, -1 + db -1, -15, 27, 4, 5, 119, -10, -1, -1, -16, 30, 4, 5, 118, -11, -1 + db -2, -17, 33, 5, 6, 116, -12, -1, -2, -17, 35, 5, 6, 114, -12, -1 + db -2, -18, 38, 5, 6, 113, -13, -1, -2, -19, 41, 6, 7, 111, -14, -2 + db -2, -19, 43, 6, 7, 110, -15, -2, -2, -20, 46, 6, 7, 108, -15, -2 + db -2, -20, 49, 6, 7, 106, -16, -2, -2, -21, 51, 7, 7, 104, -16, -2 + db -2, -21, 54, 7, 7, 102, -17, -2, -2, -21, 56, 7, 8, 100, -18, -2 + db -2, -22, 59, 7, 8, 98, -18, -2, -2, -22, 62, 7, 8, 96, -19, -2 + db -2, -22, 64, 7, 8, 94, -19, -2, -2, -22, 67, 8, 8, 91, -20, -2 + db -2, -22, 69, 8, 8, 89, -20, -2, -2, -22, 72, 8, 8, 87, -21, -2 + db -2, -21, 74, 8, 8, 84, -21, -2, -2, -22, 77, 8, 8, 82, -21, -2 + db -2, -21, 79, 8, 8, 79, -21, -2, -2, -21, 82, 8, 8, 77, -22, -2 + db -2, -21, 84, 8, 8, 74, -21, -2, -2, -21, 87, 8, 8, 72, -22, -2 + db -2, -20, 89, 8, 8, 69, -22, -2, -2, -20, 91, 8, 8, 67, -22, -2 + db -2, -19, 94, 8, 7, 64, -22, -2, -2, -19, 96, 8, 7, 62, -22, -2 + db -2, -18, 98, 8, 7, 59, -22, -2, -2, -18, 100, 8, 7, 56, -21, -2 + db -2, -17, 102, 7, 7, 54, -21, -2, -2, -16, 104, 7, 7, 51, -21, -2 + db -2, -16, 106, 7, 6, 49, -20, -2, -2, -15, 108, 7, 6, 46, -20, -2 + db -2, -15, 110, 7, 6, 43, -19, -2, -2, -14, 111, 7, 6, 41, -19, -2 + db -1, -13, 113, 6, 5, 38, -18, -2, -1, -12, 114, 6, 5, 35, -17, -2 + db -1, -12, 116, 6, 5, 33, -17, -2, -1, -11, 118, 5, 4, 30, -16, -1 + db -1, -10, 119, 5, 4, 27, -15, -1, -1, -9, 120, 5, 4, 25, -14, -2 + db -1, -8, 121, 4, 3, 23, -13, -1, -1, -7, 122, 4, 3, 20, -12, -1 + db -1, -7, 123, 4, 3, 18, -11, -1, -1, -6, 124, 3, 3, 16, -10, -1 + db -1, -5, 125, 3, 2, 13, -8, -1, -1, -4, 126, 2, 2, 11, -7, -1 + db 0, -3, 126, 2, 1, 8, -6, 0, 0, -2, 127, 1, 1, 6, -5, 0 + db 0, -2, 127, 1, 1, 4, -3, 0, 0, 0, 127, 0, 0, 2, -1, 0 + ; [1, 2) + db 0, 0, 127, 0, 0, 1, 0, 0, 0, 0, 127, 0, 0, -1, 2, 0 + db 0, 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1 + db 0, 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1 + db 0, 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1 + db 0, 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1 + db 0, 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2 + db 0, 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2 + db 0, 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2 + db 0, 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3 + db 0, 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3 + db 0, 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3 + db 0, 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4 + db 0, 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4 + db 0, 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4 + db 0, 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4 + db 0, 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4 + db 0, 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4 + db 0, 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4 + db 0, 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4 + db 0, 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4 + db 0, 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4 + db 0, 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4 + db 0, 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4 + db 0, 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3 + db 0, 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3 + db 0, 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3 + db 0, 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2 + db 0, 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2 + db 0, 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2 + db 0, 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1 + db 0, 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1 + db 0, 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0 + db 0, 0, 2, -1, 0, 0, 127, 0 + +pw_258: times 2 dw 258 + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +%macro BIDIR_JMP_TABLE 2-* + ;evaluated at definition time (in loop below) + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + ; dynamically generated label + %%table: + %rep %0 - 2 ; repeat for num args + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, ssse3, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, ssse3, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, ssse3, 2, 4, 8, 16, 16, 16, 16 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine prep_sse2 mangle(private_prefix %+ _prep_bilin_8bpc_sse2.prep) +%xdefine put_ssse3 mangle(private_prefix %+ _put_bilin_8bpc_ssse3.put) +%xdefine prep_ssse3 mangle(private_prefix %+ _prep_bilin_8bpc_ssse3.prep) + +BASE_JMP_TABLE put, ssse3, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, ssse3, 4, 8, 16, 32, 64, 128 + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +HV_JMP_TABLE prep, 8tap, sse2, 1, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, sse2, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, ssse3, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, ssse3, 1, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, ssse3, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, ssse3, 7, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, ssse3, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, ssse3, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +SECTION .text + +INIT_XMM ssse3 + +%if ARCH_X86_32 + DECLARE_REG_TMP 1 + %define base t0-put_ssse3 +%else + DECLARE_REG_TMP 7 + %define base 0 +%endif + +%macro RESTORE_DSQ_32 1 + %if ARCH_X86_32 + mov %1, dsm ; restore dsq + %endif +%endmacro + +cglobal put_bilin_8bpc, 1, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + LEA t0, put_ssse3 + movifnidn srcq, srcmp + movifnidn ssq, ssmp + tzcnt wd, wm + mov hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [t0+wq*2+table_offset(put,)] + add wq, t0 + RESTORE_DSQ_32 t0 + jmp wq +.put_w2: + movzx r4d, word [srcq+ssq*0] + movzx r6d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4w + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r4d, [srcq+ssq*0] + mov r6d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4d + mov [dstq+dsq*1], r6d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq [dstq+dsq*0], m0 + movq [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0+16*0] + movu m1, [srcq+ssq*0+16*1] + movu m2, [srcq+ssq*1+16*0] + movu m3, [srcq+ssq*1+16*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+16*0], m0 + mova [dstq+dsq*0+16*1], m1 + mova [dstq+dsq*1+16*0], m2 + mova [dstq+dsq*1+16*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, ssq + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add srcq, ssq + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 0x00ff00ff + mova m4, [base+bilin_h_shuf8] + mova m0, [base+bilin_h_shuf4] + add mxyd, 0x00100010 + movd m5, mxyd + mov mxyd, r7m ; my + pshufd m5, m5, q0000 + test mxyd, mxyd + jnz .hv + movzx wd, word [t0+wq*2+table_offset(put, _bilin_h)] + mova m3, [base+pw_2048] + add wq, t0 + movifnidn dsq, dsmp + jmp wq +.h_w2: + pshufd m4, m4, q3120 ; m4 = {1, 0, 2, 1, 5, 4, 6, 5} +.h_w2_loop: + movd m0, [srcq+ssq*0] + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq m0, m1 + pshufb m0, m4 + pmaddubsw m0, m5 + pmulhrsw m0, m3 + packuswb m0, m0 + movd r6d, m0 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movq m4, [srcq+ssq*0] + movhps m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m4, m0 + pmaddubsw m4, m5 + pmulhrsw m4, m3 + packuswb m4, m4 + movd [dstq+dsq*0], m4 + psrlq m4, 32 + movd [dstq+dsq*1], m4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w16 + RET +.h_w32: + movu m0, [srcq+mmsize*0+8*0] + movu m1, [srcq+mmsize*0+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movu m1, [srcq+mmsize*1+8*0] + movu m2, [srcq+mmsize*1+8*1] + add srcq, ssq + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + packuswb m1, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: + mov r6, -16*3 +.h_w64_loop: + movu m0, [srcq+r6+16*3+8*0] + movu m1, [srcq+r6+16*3+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+16*3], m0 + add r6, 16 + jle .h_w64_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + mov r6, -16*7 +.h_w128_loop: + movu m0, [srcq+r6+16*7+8*0] + movu m1, [srcq+r6+16*7+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+16*7], m0 + add r6, 16 + jle .h_w128_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [t0+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 0x00ff00ff + mova m5, [base+pw_2048] + add mxyd, 0x00100010 + add wq, t0 + movd m4, mxyd + pshufd m4, m4, q0000 + movifnidn dsq, dsmp + jmp wq +.v_w2: + movd m0, [srcq+ssq*0] +.v_w2_loop: + pinsrw m0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pshuflw m1, m0, q2301 + pinsrw m0, [srcq+ssq*0], 0 ; 2 1 + punpcklbw m1, m0 + pmaddubsw m1, m4 + pmulhrsw m1, m5 + packuswb m1, m1 + movd r6d, m1 + mov [dstq+dsq*1], r6w + shr r6d, 16 + mov [dstq+dsq*0], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd m0, [srcq+ssq*0] +.v_w4_loop: + movd m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + movd m0, [srcq+ssq*0] + punpckldq m1, m2 ; 0 1 + punpckldq m2, m0 ; 1 2 + punpcklbw m1, m2 + pmaddubsw m1, m4 + pmulhrsw m1, m5 + packuswb m1, m1 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + ; + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq m0, [srcq+ssq*0] +.v_w8_loop: + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + movq m0, [srcq+ssq*0] + punpcklbw m1, m2 + punpcklbw m2, m0 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +%macro PUT_BILIN_V_W16 0 + movu m0, [srcq+ssq*0] +%%loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + mova m2, m0 + movu m0, [srcq+ssq*0] + punpcklbw m1, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + pmaddubsw m2, m4 + pmaddubsw m3, m4 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + packuswb m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg %%loop +%endmacro +.v_w16: + PUT_BILIN_V_W16 + RET +.v_w128: + lea r6d, [hq+(7<<16)] + jmp .v_w16gt +.v_w64: + lea r6d, [hq+(3<<16)] + jmp .v_w16gt +.v_w32: + lea r6d, [hq+(1<<16)] +.v_w16gt: + mov r4, srcq +%if ARCH_X86_64 + mov r7, dstq +%endif +.v_w16gt_loop: + PUT_BILIN_V_W16 +%if ARCH_X86_64 + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%else + mov dstq, dstmp + add r4, 16 + movzx hd, r6w + add dstq, 16 + mov srcq, r4 + mov dstmp, dstq +%endif + sub r6d, 1<<16 + jg .v_w16gt + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [t0+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + mova m7, [base+pw_15] + movd m6, mxyd + add wq, t0 + pshuflw m6, m6, q0000 + paddb m5, m5 + punpcklqdq m6, m6 + jmp wq +.hv_w2: + RESTORE_DSQ_32 t0 + movd m0, [srcq+ssq*0] + punpckldq m0, m0 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w2_loop: + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + punpckldq m1, m2 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 _ 2 _ + shufps m2, m0, m1, q1032 ; 0 _ 1 _ + mova m0, m1 + psubw m1, m2 ; 2 * (src[x + src_stride] - src[x]) + pmulhw m1, m6 ; (my * (src[x + src_stride] - src[x]) >> 4 + pavgw m2, m7 ; src[x] + 8 + paddw m1, m2 ; src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8 + psrlw m1, 4 + packuswb m1, m1 +%if ARCH_X86_64 + movq r6, m1 +%else + pshuflw m1, m1, q2020 + movd r6d, m1 +%endif + mov [dstq+dsq*0], r6w + shr r6, gprsize*4 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova m4, [base+bilin_h_shuf4] + movddup m0, [srcq+ssq*0] + movifnidn dsq, dsmp + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w4_loop: + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps m1, [srcq+ssq*0] + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 + shufps m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhw m1, m6 + pavgw m2, m7 + paddw m1, m2 + psrlw m1, 4 + packuswb m1, m1 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+ssq*0] + movifnidn dsq, dsmp + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m2, m4 + pmaddubsw m2, m5 + psubw m1, m2, m0 + pmulhw m1, m6 + pavgw m0, m7 + paddw m1, m0 + movu m0, [srcq+ssq*0] + pshufb m0, m4 + pmaddubsw m0, m5 + psubw m3, m0, m2 + pmulhw m3, m6 + pavgw m2, m7 + paddw m3, m2 + psrlw m1, 4 + psrlw m3, 4 + packuswb m1, m3 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w128: + lea r6d, [hq+(7<<16)] + jmp .hv_w16_start +.hv_w64: + lea r6d, [hq+(3<<16)] + jmp .hv_w16_start +.hv_w32: + lea r6d, [hq+(1<<16)] +.hv_w16_start: + mov r4, srcq +%if ARCH_X86_32 + %define m8 [dstq] +%else + mov r7, dstq +%endif +.hv_w16: + movifnidn dsq, dsmp +%if WIN64 + movaps r4m, m8 +%endif +.hv_w16_loop0: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w16_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova m8, m2 + psubw m2, m0 + pmulhw m2, m6 + pavgw m0, m7 + paddw m2, m0 + mova m0, m3 + psubw m3, m1 + pmulhw m3, m6 + pavgw m1, m7 + paddw m3, m1 + mova m1, m0 + mova m0, m8 + psrlw m2, 4 + psrlw m3, 4 + packuswb m2, m3 + mova [dstq], m2 + add dstq, dsmp + dec hd + jg .hv_w16_loop +%if ARCH_X86_32 + mov dstq, dstm + add r4, 16 + movzx hd, r6w + add dstq, 16 + mov srcq, r4 + mov dstm, dstq +%else + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%endif + sub r6d, 1<<16 + jg .hv_w16_loop0 +%if WIN64 + movaps m8, r4m +%endif + RET + +%macro PSHUFB_BILIN_H8 2 ; dst, src + %if cpuflag(ssse3) + pshufb %1, %2 + %else + psrldq %2, %1, 1 + punpcklbw %1, %2 + %endif +%endmacro + +%macro PSHUFB_BILIN_H4 3 ; dst, src, tmp + %if cpuflag(ssse3) + pshufb %1, %2 + %else + psrldq %2, %1, 1 + punpckhbw %3, %1, %2 + punpcklbw %1, %2 + punpcklqdq %1, %3 + %endif +%endmacro + +%macro PMADDUBSW 5 ; dst/src1, src2, zero, tmp, reset_zero + %if cpuflag(ssse3) + pmaddubsw %1, %2 + %else + %if %5 == 1 + pxor %3, %3 + %endif + punpckhbw %4, %1, %3 + punpcklbw %1, %1, %3 + pmaddwd %4, %2 + pmaddwd %1, %2 + packssdw %1, %4 + %endif +%endmacro + +%macro PMULHRSW 5 ; dst, src, tmp, rndval, shift + %if cpuflag(ssse3) + pmulhrsw %1, %2 + %else + punpckhwd %3, %1, %4 + punpcklwd %1, %4 + pmaddwd %3, %2 + pmaddwd %1, %2 + psrad %3, %5 + psrad %1, %5 + packssdw %1, %3 + %endif +%endmacro + +%macro PREP_BILIN 0 +%if ARCH_X86_32 + %define base r6-prep%+SUFFIX +%else + %define base 0 +%endif + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + LEA r6, prep%+SUFFIX + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: +%if notcpuflag(ssse3) + add r6, prep_ssse3 - prep_sse2 + jmp prep_ssse3 +%else + movzx wd, word [r6+wq*2+table_offset(prep,)] + pxor m4, m4 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd m0, [srcq+strideq*0] + movd m1, [srcq+strideq*1] + movd m2, [srcq+strideq*2] + movd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpckldq m0, m1 + punpckldq m2, m3 + punpcklbw m0, m4 + punpcklbw m2, m4 + psllw m0, 4 + psllw m2, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq m0, [srcq+strideq*0] + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*2] + movq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu m1, [srcq+strideq*0] + movu m3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .prep_w16 + RET +.prep_w128: + mov r3, -128 + jmp .prep_w32_start +.prep_w64: + mov r3, -64 + jmp .prep_w32_start +.prep_w32: + mov r3, -32 +.prep_w32_start: + sub srcq, r3 +.prep_w32_vloop: + mov r6, r3 +.prep_w32_hloop: + movu m1, [srcq+r6+16*0] + movu m3, [srcq+r6+16*1] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + add r6, 32 + jl .prep_w32_hloop + add srcq, strideq + dec hd + jg .prep_w32_vloop + RET +%endif +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] +%if cpuflag(ssse3) + imul mxyd, 0x00ff00ff + mova m4, [base+bilin_h_shuf8] + add mxyd, 0x00100010 +%else + imul mxyd, 0xffff + add mxyd, 16 +%endif + movd m5, mxyd + mov mxyd, r6m ; my + pshufd m5, m5, q0000 + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] +%if notcpuflag(ssse3) + WIN64_SPILL_XMM 8 + pxor m6, m6 +%endif + add wq, r6 + jmp wq +.h_w4: +%if cpuflag(ssse3) + mova m4, [base+bilin_h_shuf4] +%endif + lea stride3q, [strideq*3] +.h_w4_loop: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*2] + movhps m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + PSHUFB_BILIN_H4 m0, m4, m2 + PMADDUBSW m0, m5, m6, m2, 0 + PSHUFB_BILIN_H4 m1, m4, m2 + PMADDUBSW m1, m5, m6, m2, 0 + mova [tmpq+0 ], m0 + mova [tmpq+16], m1 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + lea stride3q, [strideq*3] +.h_w8_loop: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + movu m0, [srcq+strideq*0+8*0] + movu m1, [srcq+strideq*0+8*1] + movu m2, [srcq+strideq*1+8*0] + movu m3, [srcq+strideq*1+8*1] + lea srcq, [srcq+strideq*2] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .h_w16 + RET +.h_w128: + mov r3, -128 + jmp .h_w32_start +.h_w64: + mov r3, -64 + jmp .h_w32_start +.h_w32: + mov r3, -32 +.h_w32_start: + sub srcq, r3 +.h_w32_vloop: + mov r6, r3 +.h_w32_hloop: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + movu m2, [srcq+r6+8*2] + movu m3, [srcq+r6+8*3] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + add r6, 32 + jl .h_w32_hloop + add srcq, strideq + dec hd + jg .h_w32_vloop + RET +.v: +%if notcpuflag(ssse3) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 8 +%endif + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] +%if cpuflag(ssse3) + imul mxyd, 0x00ff00ff + add mxyd, 0x00100010 +%else + imul mxyd, 0xffff + pxor m6, m6 + add mxyd, 16 +%endif + add wq, r6 + lea stride3q, [strideq*3] + movd m5, mxyd + pshufd m5, m5, q0000 + jmp wq +.v_w4: + movd m0, [srcq+strideq*0] +.v_w4_loop: + movd m1, [srcq+strideq*1] + movd m2, [srcq+strideq*2] + movd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpckldq m0, m1 + punpckldq m1, m2 + punpcklbw m0, m1 ; 01 12 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + movd m0, [srcq+strideq*0] + punpckldq m2, m3 + punpckldq m3, m0 + punpcklbw m2, m3 ; 23 34 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq m0, [srcq+strideq*0] +.v_w8_loop: + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*2] + movq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m0, m1 ; 01 + punpcklbw m1, m2 ; 12 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + movq m0, [srcq+strideq*0] + punpcklbw m2, m3 ; 23 + punpcklbw m3, m0 ; 34 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*1], m1 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m4, m0, m1 + punpckhbw m0, m1 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + punpcklbw m4, m1, m2 + punpckhbw m1, m2 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*1], m0 + movu m0, [srcq+strideq*0] + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + punpcklbw m4, m2, m3 + punpckhbw m2, m3 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*3], m1 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*4], m4 + punpcklbw m4, m3, m0 + punpckhbw m3, m0 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*5], m2 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*6], m4 + mova [tmpq+16*7], m3 + add tmpq, 16*8 + sub hd, 4 + jg .v_w16_loop + RET +.v_w128: + lea r3d, [hq+(3<<8)] + mov r6d, 256 + jmp .v_w32_start +.v_w64: + lea r3d, [hq+(1<<8)] + mov r6d, 128 + jmp .v_w32_start +.v_w32: + xor r3d, r3d + mov r6d, 64 +.v_w32_start: +%if ARCH_X86_64 + %if WIN64 + PUSH r7 + %endif + mov r7, tmpq +%endif + mov r5, srcq +.v_w32_hloop: + movu m0, [srcq+strideq*0+16*0] + movu m1, [srcq+strideq*0+16*1] +.v_w32_vloop: + movu m2, [srcq+strideq*1+16*0] + movu m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m0, m2 + punpckhbw m0, m2 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + mova [tmpq+16*1], m0 + movu m0, [srcq+strideq*0+16*0] + punpcklbw m4, m1, m3 + punpckhbw m1, m3 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + mova [tmpq+16*3], m1 + movu m1, [srcq+strideq*0+16*1] + add tmpq, r6 + punpcklbw m4, m2, m0 + punpckhbw m2, m0 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + mova [tmpq+16*1], m2 + punpcklbw m4, m3, m1 + punpckhbw m3, m1 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + mova [tmpq+16*3], m3 + add tmpq, r6 + sub hd, 2 + jg .v_w32_vloop + add r5, 32 + movzx hd, r3b + mov srcq, r5 +%if ARCH_X86_64 + add r7, 16*4 + mov tmpq, r7 +%else + mov tmpq, tmpmp + add tmpq, 16*4 + mov tmpmp, tmpq +%endif + sub r3d, 1<<8 + jg .v_w32_hloop +%if WIN64 + POP r7 +%endif + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] +%assign stack_offset stack_offset - stack_size_padded +%if cpuflag(ssse3) + imul mxyd, 0x08000800 + WIN64_SPILL_XMM 8 +%else + or mxyd, 1<<16 + WIN64_SPILL_XMM 9 + %if ARCH_X86_64 + mova m8, [base+pw_8] + %else + %define m8 [base+pw_8] + %endif + pxor m7, m7 +%endif + movd m6, mxyd + add wq, r6 + pshufd m6, m6, q0000 + jmp wq +.hv_w4: +%if cpuflag(ssse3) + mova m4, [base+bilin_h_shuf4] + movddup m0, [srcq+strideq*0] +%else + movhps m0, [srcq+strideq*0] +%endif + lea r3, [strideq*3] + PSHUFB_BILIN_H4 m0, m4, m3 + PMADDUBSW m0, m5, m7, m4, 0 ; _ 0 +.hv_w4_loop: + movq m1, [srcq+strideq*1] + movhps m1, [srcq+strideq*2] + movq m2, [srcq+r3 ] + lea srcq, [srcq+strideq*4] + movhps m2, [srcq+strideq*0] + PSHUFB_BILIN_H4 m1, m4, m3 + PSHUFB_BILIN_H4 m2, m4, m3 + PMADDUBSW m1, m5, m7, m4, 0 ; 1 2 + PMADDUBSW m2, m5, m7, m4, 0 ; 3 4 + shufpd m0, m1, 0x01 ; 0 1 + shufpd m3, m1, m2, 0x01 ; 2 3 + psubw m1, m0 + PMULHRSW m1, m6, m4, m8, 4 + paddw m1, m0 + mova m0, m2 + psubw m2, m3 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m3 + mova [tmpq+16*0], m1 + mova [tmpq+16*1], m2 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+strideq*0] + PSHUFB_BILIN_H8 m0, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 0 +.hv_w8_loop: + movu m1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu m2, [srcq+strideq*0] + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PMADDUBSW m1, m5, m7, m4, 0 ; 1 + PMADDUBSW m2, m5, m7, m4, 0 ; 2 + psubw m3, m1, m0 + PMULHRSW m3, m6, m4, m8, 4 + paddw m3, m0 + mova m0, m2 + psubw m2, m1 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m1 + mova [tmpq+16*0], m3 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w128: + lea r3d, [hq+(7<<8)] + mov r5d, 256 + jmp .hv_w16_start +.hv_w64: + lea r3d, [hq+(3<<8)] + mov r5d, 128 + jmp .hv_w16_start +.hv_w32: + lea r3d, [hq+(1<<8)] + mov r5d, 64 + jmp .hv_w16_start +.hv_w16: + xor r3d, r3d + mov r5d, 32 +.hv_w16_start: +%if ARCH_X86_64 || cpuflag(ssse3) + mov r6, srcq +%endif +%if ARCH_X86_64 + %if WIN64 + PUSH r7 + %endif + mov r7, tmpq +%endif +.hv_w16_hloop: + movu m0, [srcq+strideq*0+8*0] + movu m1, [srcq+strideq*0+8*1] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 0a + PMADDUBSW m1, m5, m7, m4, 0 ; 0b +.hv_w16_vloop: + movu m2, [srcq+strideq*1+8*0] + PSHUFB_BILIN_H8 m2, m4 + PMADDUBSW m2, m5, m7, m4, 0 ; 1a + psubw m3, m2, m0 + PMULHRSW m3, m6, m4, m8, 4 + paddw m3, m0 + mova [tmpq+16*0], m3 + movu m3, [srcq+strideq*1+8*1] + lea srcq, [srcq+strideq*2] + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m3, m5, m7, m4, 0 ; 1b + psubw m0, m3, m1 + PMULHRSW m0, m6, m4, m8, 4 + paddw m0, m1 + mova [tmpq+16*1], m0 + add tmpq, r5 + movu m0, [srcq+strideq*0+8*0] + PSHUFB_BILIN_H8 m0, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 2a + psubw m1, m0, m2 + PMULHRSW m1, m6, m4, m8, 4 + paddw m1, m2 + mova [tmpq+16*0], m1 + movu m1, [srcq+strideq*0+8*1] + PSHUFB_BILIN_H8 m1, m4 + PMADDUBSW m1, m5, m7, m4, 0 ; 2b + psubw m2, m1, m3 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m3 + mova [tmpq+16*1], m2 + add tmpq, r5 + sub hd, 2 + jg .hv_w16_vloop + movzx hd, r3b +%if ARCH_X86_64 + add r6, 16 + add r7, 2*16 + mov srcq, r6 + mov tmpq, r7 +%elif cpuflag(ssse3) + mov tmpq, tmpm + add r6, 16 + add tmpq, 2*16 + mov srcq, r6 + mov tmpm, tmpq +%else + mov srcq, srcm + mov tmpq, tmpm + add srcq, 16 + add tmpq, 2*16 + mov srcm, srcq + mov tmpm, tmpq +%endif + sub r3d, 1<<8 + jg .hv_w16_hloop +%if WIN64 + POP r7 +%endif + RET +%endmacro + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 1, 2 +%elif WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +FN put_8tap, sharp, SHARP, SHARP +FN put_8tap, sharp_smooth, SHARP, SMOOTH +FN put_8tap, smooth_sharp, SMOOTH, SHARP +FN put_8tap, smooth, SMOOTH, SMOOTH +FN put_8tap, sharp_regular, SHARP, REGULAR +FN put_8tap, regular_sharp, REGULAR, SHARP +FN put_8tap, smooth_regular, SMOOTH, REGULAR +FN put_8tap, regular_smooth, REGULAR, SMOOTH +FN put_8tap, regular, REGULAR, REGULAR + +%if ARCH_X86_32 + %define base_reg r1 + %define base base_reg-put_ssse3 +%else + %define base_reg r8 + %define base 0 +%endif + +cglobal put_8tap_8bpc, 1, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 +%assign org_stack_offset stack_offset + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h +%if ARCH_X86_64 + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v +%else + imul ssd, mym, 0x010101 + add ssd, t1d ; 8tap_v, my, 4tap_v + mov srcq, srcm +%endif + mov wd, wm + movifnidn hd, hm + LEA base_reg, put_ssse3 + test mxd, 0xf00 + jnz .h +%if ARCH_X86_32 + test ssd, 0xf00 +%else + test myd, 0xf00 +%endif + jnz .v + tzcnt wd, wd + movzx wd, word [base_reg+wq*2+table_offset(put,)] + add wq, base_reg +; put_bilin mangling jump +%assign stack_offset org_stack_offset + movifnidn dsq, dsmp + movifnidn ssq, ssmp +%if WIN64 + pop r8 +%endif + lea r6, [ssq*3] + jmp wq +.h: +%if ARCH_X86_32 + test ssd, 0xf00 +%else + test myd, 0xf00 +%endif + jnz .hv + movifnidn ssq, ssmp + WIN64_SPILL_XMM 12 + cmp wd, 4 + jl .h_w2 + je .h_w4 + tzcnt wd, wd +%if ARCH_X86_64 + mova m10, [base+subpel_h_shufA] + mova m11, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] +%endif + shr mxd, 16 + sub srcq, 3 + movzx wd, word [base_reg+wq*2+table_offset(put, _8tap_h)] + movq m6, [base_reg+mxq*8+subpel_filters-put_ssse3] + mova m7, [base+pw_34] ; 2 + (8 << 2) + pshufd m5, m6, q0000 + pshufd m6, m6, q1111 + add wq, base_reg + jmp wq +.h_w2: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + mova m4, [base+subpel_h_shuf4] + movd m3, [base_reg+mxq*8+subpel_filters-put_ssse3+2] + mova m5, [base+pw_34] ; 2 + (8 << 2) + pshufd m3, m3, q0000 + movifnidn dsq, dsmp +.h_w2_loop: + movq m0, [srcq+ssq*0] + movhps m0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pmaddubsw m0, m3 + phaddw m0, m0 + paddw m0, m5 ; pw34 + psraw m0, 6 + packuswb m0, m0 + movd r6d, m0 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m3, [base_reg+mxq*8+subpel_filters-put_ssse3+2] + mova m6, [base+subpel_h_shufA] + mova m5, [base+pw_34] ; 2 + (8 << 2) + pshufd m3, m3, q0000 + movifnidn dsq, dsmp +.h_w4_loop: + movq m0, [srcq+ssq*0] ; 1 + movq m1, [srcq+ssq*1] ; 2 + lea srcq, [srcq+ssq*2] + pshufb m0, m6 ; subpel_h_shufA + pshufb m1, m6 ; subpel_h_shufA + pmaddubsw m0, m3 ; subpel_filters + pmaddubsw m1, m3 ; subpel_filters + phaddw m0, m1 + paddw m0, m5 ; pw34 + psraw m0, 6 + packuswb m0, m0 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3] + %if ARCH_X86_32 + pshufb %2, %1, [base+subpel_h_shufB] + pshufb %3, %1, [base+subpel_h_shufC] + pshufb %1, [base+subpel_h_shufA] + %else + pshufb %2, %1, m11; subpel_h_shufB + pshufb %3, %1, m9 ; subpel_h_shufC + pshufb %1, m10 ; subpel_h_shufA + %endif + pmaddubsw %4, %2, m5 ; subpel +0 B0 + pmaddubsw %2, m6 ; subpel +4 B4 + pmaddubsw %3, m6 ; C4 + pmaddubsw %1, m5 ; A0 + paddw %3, %4 ; C4+B0 + paddw %1, %2 ; A0+B4 + phaddw %1, %3 + paddw %1, m7 ; pw34 + psraw %1, 6 +%endmacro +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + PUT_8TAP_H m0, m2, m3, m4 + PUT_8TAP_H m1, m2, m3, m4 + packuswb m0, m1 +%if ARCH_X86_32 + movq [dstq], m0 + add dstq, dsm + movhps [dstq], m0 + add dstq, dsm +%else + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] +%endif + sub hd, 2 + jg .h_w8 + RET +.h_w128: + mov r4, -16*7 + jmp .h_w16_start +.h_w64: + mov r4, -16*3 + jmp .h_w16_start +.h_w32: + mov r4, -16*1 + jmp .h_w16_start +.h_w16: + xor r4d, r4d +.h_w16_start: + sub srcq, r4 + sub dstq, r4 +.h_w16_loop_v: + mov r6, r4 +.h_w16_loop_h: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + PUT_8TAP_H m0, m2, m3, m4 + PUT_8TAP_H m1, m2, m3, m4 + packuswb m0, m1 + mova [dstq+r6], m0 + add r6, 16 + jle .h_w16_loop_h + add srcq, ssq + add dstq, dsmp + dec hd + jg .h_w16_loop_v + RET +.v: +%if ARCH_X86_32 + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m0, [base_reg+ssq*8+subpel_filters-put_ssse3] +%else + %assign stack_offset org_stack_offset + WIN64_SPILL_XMM 16 + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-put_ssse3] +%endif + tzcnt r6d, wd + movzx r6d, word [base_reg+r6*2+table_offset(put, _8tap_v)] + punpcklwd m0, m0 + mova m7, [base+pw_512] + add r6, base_reg +%if ARCH_X86_32 + %define subpel0 [rsp+mmsize*0] + %define subpel1 [rsp+mmsize*1] + %define subpel2 [rsp+mmsize*2] + %define subpel3 [rsp+mmsize*3] +%assign regs_used 2 ; use r1 (ds) as tmp for stack alignment if needed + ALLOC_STACK -16*4 +%assign regs_used 7 + pshufd m1, m0, q0000 + mova subpel0, m1 + pshufd m1, m0, q1111 + mova subpel1, m1 + pshufd m1, m0, q2222 + mova subpel2, m1 + pshufd m1, m0, q3333 + mova subpel3, m1 + mov ssq, [rstk+stack_offset+gprsize*4] + lea ssq, [ssq*3] + sub srcq, ssq + mov ssq, [rstk+stack_offset+gprsize*4] + mov dsq, [rstk+stack_offset+gprsize*2] +%else + %define subpel0 m8 + %define subpel1 m9 + %define subpel2 m10 + %define subpel3 m11 + lea ss3q, [ssq*3] + pshufd m8, m0, q0000 + sub srcq, ss3q + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 +%endif + jmp r6 +.v_w2: + movd m1, [srcq+ssq*0] + movd m0, [srcq+ssq*1] +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + movd m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m3, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] +%else + movd m2, [srcq+ssq*2] + add srcq, ss3q + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m4, [srcq+ssq*2] + add srcq, ss3q +%endif + punpcklwd m1, m0 ; 0 1 + punpcklwd m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+ssq*0] + punpcklwd m2, m5 ; 2 3 + punpcklwd m5, m3 ; 3 4 + punpcklwd m3, m4 ; 4 5 + punpcklwd m4, m0 ; 5 6 + punpcklbw m2, m5 ; 23 34 + punpcklbw m3, m4 ; 45 56 +.v_w2_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, subpel0 ; a0 b0 + mova m1, m2 + pmaddubsw m2, subpel1 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, subpel2 ; a2 b2 + paddw m5, m3 + punpcklwd m3, m0, m4 ; 6 7 + movd m0, [srcq+ssq*0] + punpcklwd m4, m0 ; 7 8 + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, subpel3 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + packuswb m5, m5 + movd r6d, m5 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: +%if ARCH_X86_32 +.v_w8: +.v_w16: +.v_w32: +.v_w64: +.v_w128: + shl wd, 14 +%if STACK_ALIGNMENT < 16 + %define dstm [rsp+mmsize*4+gprsize] + mov dstm, dstq +%endif + lea r6d, [hq+wq-(1<<16)] + mov r4, srcq +.v_w4_loop0: +%endif + movd m1, [srcq+ssq*0] + movd m0, [srcq+ssq*1] +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + movd m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m3, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] +%else + movd m2, [srcq+ssq*2] + add srcq, ss3q + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m4, [srcq+ssq*2] + add srcq, ss3q +%endif + punpckldq m1, m0 ; 0 1 + punpckldq m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+ssq*0] + punpckldq m2, m5 ; 2 3 + punpckldq m5, m3 ; 3 4 + punpckldq m3, m4 ; 4 5 + punpckldq m4, m0 ; 5 6 + punpcklbw m2, m5 ; 23 34 + punpcklbw m3, m4 ; 45 56 +.v_w4_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, subpel0 ; a0 b0 + mova m1, m2 + pmaddubsw m2, subpel1 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, subpel2 ; a2 b2 + paddw m5, m3 + punpckldq m3, m0, m4 ; 6 7 _ _ + movd m0, [srcq+ssq*0] + punpckldq m4, m0 ; 7 8 _ _ + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, subpel3 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + packuswb m5, m5 + movd [dstq+dsq*0], m5 + psrlq m5, 32 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop +%if ARCH_X86_32 + mov dstq, dstm + add r4, 4 + movzx hd, r6w + add dstq, 4 + mov srcq, r4 + mov dstm, dstq + sub r6d, 1<<16 + jg .v_w4_loop0 +%endif + RET +%if ARCH_X86_64 +.v_w8: +.v_w16: +.v_w32: +.v_w64: +.v_w128: + lea r6d, [wq*8-64] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*4] +.v_w8_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + movq m3, [srcq+ssq*2] + add srcq, ss3q + movq m4, [srcq+ssq*0] + movq m5, [srcq+ssq*1] + movq m6, [srcq+ssq*2] + add srcq, ss3q + movq m0, [srcq+ssq*0] + punpcklbw m1, m2 ; 01 + punpcklbw m2, m3 ; 12 + punpcklbw m3, m4 ; 23 + punpcklbw m4, m5 ; 34 + punpcklbw m5, m6 ; 45 + punpcklbw m6, m0 ; 56 +.v_w8_loop: + movq m13, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m14, m1, subpel0 ; a0 + mova m1, m3 + pmaddubsw m15, m2, subpel0 ; b0 + mova m2, m4 + pmaddubsw m3, subpel1 ; a1 + mova m12, m0 + pmaddubsw m4, subpel1 ; b1 + movq m0, [srcq+ssq*0] + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + pmaddubsw m5, subpel2 ; a2 + mova m4, m6 + pmaddubsw m6, subpel2 ; b2 + punpcklbw m12, m13 ; 67 + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + pmaddubsw m12, subpel3 ; a3 + paddw m15, m6 + mova m6, m13 + pmaddubsw m13, subpel3 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + packuswb m14, m15 + movq [dstq+dsq*0], m14 + movhps [dstq+dsq*1], m14 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + add r4, 8 + add r7, 8 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w8_loop0 + RET +%endif ;ARCH_X86_64 +%undef subpel0 +%undef subpel1 +%undef subpel2 +%undef subpel3 +.hv: + %assign stack_offset org_stack_offset + cmp wd, 4 + jg .hv_w8 +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m1, [base_reg+mxq*8+subpel_filters-put_ssse3+2] +%if ARCH_X86_32 + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m0, [base_reg+ssq*8+subpel_filters-put_ssse3] + mov ssq, ssmp + lea r6, [ssq*3] + sub srcq, r6 + %define base_reg r6 + mov r6, r1; use as new base + %assign regs_used 2 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + mov dsq, [rstk+stack_offset+gprsize*2] + %define subpelv0 [rsp+mmsize*0] + %define subpelv1 [rsp+mmsize*1] + %define subpelv2 [rsp+mmsize*2] + %define subpelv3 [rsp+mmsize*3] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m6, m0, q0000 + mova subpelv0, m6 + pshufd m6, m0, q1111 + mova subpelv1, m6 + pshufd m6, m0, q2222 + mova subpelv2, m6 + pshufd m6, m0, q3333 + mova subpelv3, m6 +%else + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-put_ssse3] + ALLOC_STACK mmsize*14, 14 + lea ss3q, [ssq*3] + sub srcq, ss3q + %define subpelv0 m10 + %define subpelv1 m11 + %define subpelv2 m12 + %define subpelv3 m13 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + mova m8, [base+pw_8192] + mova m9, [base+pd_512] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + pshufd m7, m1, q0000 + cmp wd, 4 + je .hv_w4 +.hv_w2: + mova m6, [base+subpel_h_shuf4] + movq m2, [srcq+ssq*0] ; 0 + movhps m2, [srcq+ssq*1] ; 0 _ 1 +%if ARCH_X86_32 + %define w8192reg [base+pw_8192] + %define d512reg [base+pd_512] + lea srcq, [srcq+ssq*2] + movq m0, [srcq+ssq*0] ; 2 + movhps m0, [srcq+ssq*1] ; 2 _ 3 + lea srcq, [srcq+ssq*2] +%else + %define w8192reg m8 + %define d512reg m9 + movq m0, [srcq+ssq*2] ; 2 + add srcq, ss3q + movhps m0, [srcq+ssq*0] ; 2 _ 3 +%endif + pshufb m2, m6 ; 0 ~ 1 ~ + pshufb m0, m6 ; 2 ~ 3 ~ + pmaddubsw m2, m7 ; subpel_filters + pmaddubsw m0, m7 ; subpel_filters + phaddw m2, m0 ; 0 1 2 3 + pmulhrsw m2, w8192reg +%if ARCH_X86_32 + movq m3, [srcq+ssq*0] ; 4 + movhps m3, [srcq+ssq*1] ; 4 _ 5 + lea srcq, [srcq+ssq*2] +%else + movq m3, [srcq+ssq*1] ; 4 + movhps m3, [srcq+ssq*2] ; 4 _ 5 + add srcq, ss3q +%endif + movq m0, [srcq+ssq*0] ; 6 + pshufb m3, m6 ; 4 ~ 5 ~ + pshufb m0, m6 ; 6 ~ + pmaddubsw m3, m7 ; subpel_filters + pmaddubsw m0, m7 ; subpel_filters + phaddw m3, m0 ; 4 5 6 _ + pmulhrsw m3, w8192reg + palignr m4, m3, m2, 4; V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 0 1 1 2 + punpckhwd m2, m4 ; V 23 34 2 3 3 4 + pshufd m0, m3, q2121; V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 4 5 5 6 +.hv_w2_loop: + movq m4, [srcq+ssq*1] ; V 7 + lea srcq, [srcq+ssq*2] ; V + movhps m4, [srcq+ssq*0] ; V 7 8 + pshufb m4, m6 + pmaddubsw m4, m7 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 ; V + pmaddwd m2, subpelv1 ; V a1 b1 + paddd m5, m2 ; V + mova m2, m3 ; V + pmaddwd m3, subpelv2 ; a2 b2 + phaddw m4, m4 + pmulhrsw m4, w8192reg + paddd m5, m3 ; V + palignr m3, m4, m0, 12 + mova m0, m4 + punpcklwd m3, m0 ; V 67 78 + pmaddwd m4, m3, subpelv3 ; V a3 b3 + paddd m5, d512reg + paddd m5, m4 + psrad m5, 10 + packssdw m5, m5 + packuswb m5, m5 + movd r4d, m5 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +%undef w8192reg +%undef d512reg +.hv_w4: +%define hv4_line_0_0 4 +%define hv4_line_0_1 5 +%define hv4_line_0_2 6 +%define hv4_line_0_3 7 +%define hv4_line_0_4 8 +%define hv4_line_0_5 9 +%define hv4_line_1_0 10 +%define hv4_line_1_1 11 +%define hv4_line_1_2 12 +%define hv4_line_1_3 13 +%macro SAVELINE_W4 3 + mova [rsp+mmsize*hv4_line_%3_%2], %1 +%endmacro +%macro RESTORELINE_W4 3 + mova %1, [rsp+mmsize*hv4_line_%3_%2] +%endmacro +%if ARCH_X86_32 + %define w8192reg [base+pw_8192] + %define d512reg [base+pd_512] +%else + %define w8192reg m8 + %define d512reg m9 +%endif + ; lower shuffle 0 1 2 3 4 + mova m6, [base+subpel_h_shuf4] + movq m5, [srcq+ssq*0] ; 0 _ _ _ + movhps m5, [srcq+ssq*1] ; 0 _ 1 _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movq m4, [srcq+ssq*0] ; 2 _ _ _ + movhps m4, [srcq+ssq*1] ; 2 _ 3 _ + lea srcq, [srcq+ssq*2] +%else + movq m4, [srcq+ssq*2] ; 2 _ _ _ + movhps m4, [srcq+ss3q ] ; 2 _ 3 _ + lea srcq, [srcq+ssq*4] +%endif + pshufb m2, m5, m6 ;H subpel_h_shuf4 0 ~ 1 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 2 ~ 3 ~ + pmaddubsw m2, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m2, m0 ;H 0 1 2 3 + pmulhrsw m2, w8192reg ;H pw_8192 + SAVELINE_W4 m2, 2, 0 + ; upper shuffle 2 3 4 5 6 + mova m6, [base+subpel_h_shuf4+16] + pshufb m2, m5, m6 ;H subpel_h_shuf4 0 ~ 1 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 2 ~ 3 ~ + pmaddubsw m2, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m2, m0 ;H 0 1 2 3 + pmulhrsw m2, w8192reg ;H pw_8192 + ; + ; lower shuffle + mova m6, [base+subpel_h_shuf4] + movq m5, [srcq+ssq*0] ; 4 _ _ _ + movhps m5, [srcq+ssq*1] ; 4 _ 5 _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movq m4, [srcq+ssq*0] ; 6 _ _ _ + add srcq, ssq +%else + movq m4, [srcq+ssq*2] ; 6 _ _ _ + add srcq, ss3q +%endif + pshufb m3, m5, m6 ;H subpel_h_shuf4 4 ~ 5 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 6 ~ 6 ~ + pmaddubsw m3, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m3, m0 ;H 4 5 6 7 + pmulhrsw m3, w8192reg ;H pw_8192 + SAVELINE_W4 m3, 3, 0 + ; upper shuffle + mova m6, [base+subpel_h_shuf4+16] + pshufb m3, m5, m6 ;H subpel_h_shuf4 4 ~ 5 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 6 ~ 6 ~ + pmaddubsw m3, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m3, m0 ;H 4 5 6 7 + pmulhrsw m3, w8192reg ;H pw_8192 + ;process high + palignr m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + ;process low + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + palignr m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 +.hv_w4_loop: + ;process low + pmaddwd m5, m1, subpelv0 ; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 + mova m6, [base+subpel_h_shuf4] + movq m4, [srcq+ssq*0] ; 7 + movhps m4, [srcq+ssq*1] ; 7 _ 8 _ + pshufb m4, m6 ;H subpel_h_shuf4 7 ~ 8 ~ + pmaddubsw m4, m7 ;H subpel_filters + phaddw m4, m4 ;H 7 8 7 8 + pmulhrsw m4, w8192reg ;H pw_8192 + palignr m3, m4, m0, 12 ; 6 7 8 7 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 + paddd m5, d512reg ; pd_512 + paddd m5, m4 + psrad m5, 10 + SAVELINE_W4 m0, 0, 0 + SAVELINE_W4 m1, 1, 0 + SAVELINE_W4 m2, 2, 0 + SAVELINE_W4 m3, 3, 0 + SAVELINE_W4 m5, 5, 0 + ;process high + RESTORELINE_W4 m0, 0, 1 + RESTORELINE_W4 m1, 1, 1 + RESTORELINE_W4 m2, 2, 1 + RESTORELINE_W4 m3, 3, 1 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 + mova m6, [base+subpel_h_shuf4+16] + movq m4, [srcq+ssq*0] ; 7 + movhps m4, [srcq+ssq*1] ; 7 _ 8 _ + lea srcq, [srcq+ssq*2] + pshufb m4, m6 ;H subpel_h_shuf4 7 ~ 8 ~ + pmaddubsw m4, m7 ;H subpel_filters + phaddw m4, m4 ;H 7 8 7 8 + pmulhrsw m4, w8192reg ;H pw_8192 + palignr m3, m4, m0, 12 ; 6 7 8 7 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 + paddd m5, d512reg ; pd_512 + paddd m5, m4 + psrad m4, m5, 10 + RESTORELINE_W4 m5, 5, 0 + packssdw m5, m4 ; d -> w + packuswb m5, m5 ; w -> b + pshuflw m5, m5, q3120 + movd [dstq+dsq*0], m5 + psrlq m5, 32 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + RESTORELINE_W4 m0, 0, 0 + RESTORELINE_W4 m1, 1, 0 + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + jg .hv_w4_loop + RET +%undef subpelv0 +%undef subpelv1 +%undef subpelv2 +%undef subpelv3 +.hv_w8: + %assign stack_offset org_stack_offset +%define hv8_line_1 0 +%define hv8_line_2 1 +%define hv8_line_3 2 +%define hv8_line_4 3 +%define hv8_line_6 4 +%macro SAVELINE_W8 2 + mova [rsp+hv8_line_%1*mmsize], %2 +%endmacro +%macro RESTORELINE_W8 2 + mova %2, [rsp+hv8_line_%1*mmsize] +%endmacro + shr mxd, 16 + sub srcq, 3 +%if ARCH_X86_32 + %define base_reg r1 + %define subpelh0 [rsp+mmsize*5] + %define subpelh1 [rsp+mmsize*6] + %define subpelv0 [rsp+mmsize*7] + %define subpelv1 [rsp+mmsize*8] + %define subpelv2 [rsp+mmsize*9] + %define subpelv3 [rsp+mmsize*10] + %define accuv0 [rsp+mmsize*11] + %define accuv1 [rsp+mmsize*12] + movq m1, [base_reg+mxq*8+subpel_filters-put_ssse3] + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m5, [base_reg+ssq*8+subpel_filters-put_ssse3] + mov ssq, ssmp + ALLOC_STACK -mmsize*13 +%if STACK_ALIGNMENT < 16 + %define dstm [rsp+mmsize*13+gprsize*1] + %define dsm [rsp+mmsize*13+gprsize*2] + mov r6, [rstk+stack_offset+gprsize*2] + mov dsm, r6 +%endif + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + punpcklbw m5, m5 + psraw m5, 8 ; sign-extend + pshufd m2, m5, q0000 + pshufd m3, m5, q1111 + pshufd m4, m5, q2222 + pshufd m5, m5, q3333 + mova subpelh0, m0 + mova subpelh1, m1 + mova subpelv0, m2 + mova subpelv1, m3 + mova subpelv2, m4 + mova subpelv3, m5 + lea r6, [ssq*3] + mov dstm, dstq + sub srcq, r6 +%else + ALLOC_STACK 16*5, 16 + %define subpelh0 m10 + %define subpelh1 m11 + %define subpelv0 m12 + %define subpelv1 m13 + %define subpelv2 m14 + %define subpelv3 m15 + %define accuv0 m8 + %define accuv1 m9 + movq m0, [base_reg+mxq*8+subpel_filters-put_ssse3] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m1, [base_reg+myq*8+subpel_filters-put_ssse3] + pshufd subpelh0, m0, q0000 + pshufd subpelh1, m0, q1111 + punpcklbw m1, m1 + psraw m1, 8 ; sign-extend + pshufd subpelv0, m1, q0000 + pshufd subpelv1, m1, q1111 + pshufd subpelv2, m1, q2222 + pshufd subpelv3, m1, q3333 + lea ss3q, [ssq*3] + mov r7, dstq + sub srcq, ss3q +%endif + shl wd, 14 + lea r6d, [hq+wq-(1<<16)] + mov r4, srcq +.hv_w8_loop0: + movu m4, [srcq+ssq*0] ; 0 = _ _ + movu m5, [srcq+ssq*1] ; 1 = _ _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] +%endif +%macro HV_H_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3] + %if ARCH_X86_32 + pshufb %3, %1, [base+subpel_h_shufB] + pshufb %4, %1, [base+subpel_h_shufC] + pshufb %1, [base+subpel_h_shufA] + %else + pshufb %3, %1, %6 ; subpel_h_shufB + pshufb %4, %1, %7 ; subpel_h_shufC + pshufb %1, %5 ; subpel_h_shufA + %endif + pmaddubsw %2, %3, subpelh0 ; subpel +0 C0 + pmaddubsw %4, subpelh1; subpel +4 B4 + pmaddubsw %3, subpelh1; C4 + pmaddubsw %1, subpelh0; A0 + paddw %2, %4 ; C0+B4 + paddw %1, %3 ; A0+C4 + phaddw %1, %2 +%endmacro +%if ARCH_X86_64 + mova m7, [base+subpel_h_shufA] + mova m8, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] +%endif + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 ; 0 ~ ~ ~ + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 ; 1 ~ ~ ~ +%if ARCH_X86_32 + movu m6, [srcq+ssq*0] ; 2 = _ _ + movu m0, [srcq+ssq*1] ; 3 = _ _ + lea srcq, [srcq+ssq*2] +%else + movu m6, [srcq+ssq*2] ; 2 = _ _ + add srcq, ss3q + movu m0, [srcq+ssq*0] ; 3 = _ _ +%endif + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 ; 2 ~ ~ ~ + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 ; 3 ~ ~ ~ + mova m7, [base+pw_8192] + pmulhrsw m4, m7 ; H pw_8192 + pmulhrsw m5, m7 ; H pw_8192 + pmulhrsw m6, m7 ; H pw_8192 + pmulhrsw m0, m7 ; H pw_8192 + punpcklwd m1, m4, m5 ; 0 1 ~ + punpcklwd m2, m5, m6 ; 1 2 ~ + punpcklwd m3, m6, m0 ; 2 3 ~ + SAVELINE_W8 1, m1 + SAVELINE_W8 2, m2 + SAVELINE_W8 3, m3 + mova m7, [base+subpel_h_shufA] +%if ARCH_X86_32 + movu m4, [srcq+ssq*0] ; 4 = _ _ + movu m5, [srcq+ssq*1] ; 5 = _ _ + lea srcq, [srcq+ssq*2] +%else + movu m4, [srcq+ssq*1] ; 4 = _ _ + movu m5, [srcq+ssq*2] ; 5 = _ _ + add srcq, ss3q +%endif + movu m6, [srcq+ssq*0] ; 6 = _ _ + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 ; 4 ~ ~ ~ + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 ; 5 ~ ~ ~ + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 ; 6 ~ ~ ~ + mova m7, [base+pw_8192] + pmulhrsw m1, m4, m7 ; H pw_8192 4 ~ + pmulhrsw m2, m5, m7 ; H pw_8192 5 ~ + pmulhrsw m3, m6, m7 ; H pw_8192 6 ~ + punpcklwd m4, m0, m1 ; 3 4 ~ + punpcklwd m5, m1, m2 ; 4 5 ~ + punpcklwd m6, m2, m3 ; 5 6 ~ + SAVELINE_W8 6, m3 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 +.hv_w8_loop: + ; m8 accu for V a + ; m9 accu for V b + SAVELINE_W8 1, m3 + SAVELINE_W8 2, m4 + SAVELINE_W8 3, m5 + SAVELINE_W8 4, m6 +%if ARCH_X86_32 + pmaddwd m0, m1, subpelv0 ; a0 + pmaddwd m7, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m0, m3 + paddd m7, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m0, m5 + paddd m7, m6 + mova m5, [base+pd_512] + paddd m0, m5 ; pd_512 + paddd m7, m5 ; pd_512 + mova accuv0, m0 + mova accuv1, m7 +%else + pmaddwd m8, m1, subpelv0 ; a0 + pmaddwd m9, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m8, m3 + paddd m9, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m8, m5 + paddd m9, m6 + mova m7, [base+pd_512] + paddd m8, m7 ; pd_512 + paddd m9, m7 ; pd_512 + mova m7, [base+subpel_h_shufB] + mova m6, [base+subpel_h_shufC] + mova m5, [base+subpel_h_shufA] +%endif + movu m0, [srcq+ssq*1] ; 7 + movu m4, [srcq+ssq*2] ; 8 + lea srcq, [srcq+ssq*2] + HV_H_W8 m0, m1, m2, m3, m5, m7, m6 + HV_H_W8 m4, m1, m2, m3, m5, m7, m6 + mova m5, [base+pw_8192] + pmulhrsw m0, m5 ; H pw_8192 + pmulhrsw m4, m5 ; H pw_8192 + RESTORELINE_W8 6, m6 + punpcklwd m5, m6, m0 ; 6 7 ~ + punpcklwd m6, m0, m4 ; 7 8 ~ + pmaddwd m1, m5, subpelv3 ; a3 + paddd m2, m1, accuv0 + pmaddwd m1, m6, subpelv3 ; b3 + paddd m1, m1, accuv1 ; H + V + psrad m2, 10 + psrad m1, 10 + packssdw m2, m1 ; d -> w + packuswb m2, m1 ; w -> b + movd [dstq+dsq*0], m2 + psrlq m2, 32 +%if ARCH_X86_32 + add dstq, dsm + movd [dstq+dsq*0], m2 + add dstq, dsm +%else + movd [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] +%endif + sub hd, 2 + jle .hv_w8_outer + SAVELINE_W8 6, m4 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 + RESTORELINE_W8 4, m4 + jmp .hv_w8_loop +.hv_w8_outer: +%if ARCH_X86_32 + mov dstq, dstm + add r4, 4 + movzx hd, r6w + add dstq, 4 + mov srcq, r4 + mov dstm, dstq +%else + add r4, 4 + add r7, 4 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%endif + sub r6d, 1<<16 + jg .hv_w8_loop0 + RET + +%macro PSHUFB_SUBPEL_H_4 5 ; dst/src1, src2/mask, tmp1, tmp2, reset_mask + %if cpuflag(ssse3) + pshufb %1, %2 + %else + %if %5 == 1 + pcmpeqd %2, %2 + psrlq %2, 32 + %endif + psrldq %3, %1, 1 + pshufd %3, %3, q2301 + pand %1, %2 + pandn %4, %2, %3 + por %1, %4 + %endif +%endmacro + +%macro PSHUFB_SUBPEL_H_4a 6 ; dst, src1, src2/mask, tmp1, tmp2, reset_mask + %ifnidn %1, %2 + mova %1, %2 + %endif + PSHUFB_SUBPEL_H_4 %1, %3, %4, %5, %6 +%endmacro + +%macro PSHUFB_SUBPEL_H_4b 6 ; dst, src1, src2/mask, tmp1, tmp2, reset_mask + %if notcpuflag(ssse3) + psrlq %1, %2, 16 + %elifnidn %1, %2 + mova %1, %2 + %endif + PSHUFB_SUBPEL_H_4 %1, %3, %4, %5, %6 +%endmacro + +%macro PALIGNR 4-5 ; dst, src1, src2, shift[, tmp] + %if cpuflag(ssse3) + palignr %1, %2, %3, %4 + %else + %if %0 == 4 + %assign %%i regnumof%+%1 + 1 + %define %%tmp m %+ %%i + %else + %define %%tmp %5 + %endif + psrldq %1, %3, %4 + pslldq %%tmp, %2, 16-%4 + por %1, %%tmp + %endif +%endmacro + +%macro PHADDW 4 ; dst, src, pw_1/tmp, load_pw_1 + %if cpuflag(ssse3) + phaddw %1, %2 + %elifnidn %1, %2 + %if %4 == 1 + mova %3, [base+pw_1] + %endif + pmaddwd %1, %3 + pmaddwd %2, %3 + packssdw %1, %2 + %else + %if %4 == 1 + pmaddwd %1, [base+pw_1] + %else + pmaddwd %1, %3 + %endif + packssdw %1, %1 + %endif +%endmacro + +%macro PMULHRSW_POW2 4 ; dst, src1, src2, shift + %if cpuflag(ssse3) + pmulhrsw %1, %2, %3 + %else + paddw %1, %2, %3 + psraw %1, %4 + %endif +%endmacro + +%macro PMULHRSW_8192 3 ; dst, src1, src2 + PMULHRSW_POW2 %1, %2, %3, 2 +%endmacro + +%macro PREP_8TAP_H_LOAD4 5 ; dst, src_memloc, tmp[1-2] + movd %1, [%2+0] + movd %3, [%2+1] + movd %4, [%2+2] + movd %5, [%2+3] + punpckldq %1, %3 + punpckldq %4, %5 + punpcklqdq %1, %4 +%endmacro + +%macro PREP_8TAP_H_LOAD 2 ; dst0, src_memloc + %if cpuflag(ssse3) + movu m%1, [%2] + pshufb m2, m%1, m11 ; subpel_h_shufB + pshufb m3, m%1, m9 ; subpel_h_shufC + pshufb m%1, m10 ; subpel_h_shufA + %else + %if ARCH_X86_64 + SWAP m12, m5 + SWAP m13, m6 + SWAP m14, m7 + %define %%mx0 m%+%%i + %define %%mx1 m%+%%j + %assign %%i 0 + %rep 12 + movd %%mx0, [%2+%%i] + %assign %%i %%i+1 + %endrep + %assign %%i 0 + %rep 6 + %assign %%j %%i+1 + punpckldq %%mx0, %%mx1 + %assign %%i %%i+2 + %endrep + %assign %%i 0 + %rep 3 + %assign %%j %%i+2 + punpcklqdq %%mx0, %%mx1 + %assign %%i %%i+4 + %endrep + SWAP m%1, m0 + SWAP m2, m4 + SWAP m3, m8 + SWAP m5, m12 + SWAP m6, m13 + SWAP m7, m14 + %else + PREP_8TAP_H_LOAD4 m0, %2+0, m1, m4, m7 + PREP_8TAP_H_LOAD4 m2, %2+4, m1, m4, m7 + PREP_8TAP_H_LOAD4 m3, %2+8, m1, m4, m7 + SWAP m%1, m0 + %endif + %endif +%endmacro + +%macro PREP_8TAP_H 2 ; dst, src_memloc + PREP_8TAP_H_LOAD %1, %2 + %if ARCH_X86_64 && notcpuflag(ssse3) + SWAP m8, m1 + SWAP m9, m7 + %endif + %xdefine mX m%+%1 + %assign %%i regnumof%+mX + %define mX m%+%%i + mova m4, m2 + PMADDUBSW m4, m5, m1, m7, 1 ; subpel +0 B0 + PMADDUBSW m2, m6, m1, m7, 0 ; subpel +4 B4 + PMADDUBSW m3, m6, m1, m7, 0 ; subpel +4 C4 + PMADDUBSW mX, m5, m1, m7, 0 ; subpel +0 A0 + %undef mX + %if ARCH_X86_64 && notcpuflag(ssse3) + SWAP m1, m8 + SWAP m7, m9 + %endif + paddw m3, m4 + paddw m%1, m2 + PHADDW m%1, m3, m15, ARCH_X86_32 + %if ARCH_X86_64 || cpuflag(ssse3) + PMULHRSW_8192 m%1, m%1, m7 + %else + PMULHRSW_8192 m%1, m%1, [base+pw_2] + %endif +%endmacro + +%macro PREP_8TAP_HV 4 ; dst, src_memloc, tmp[1-2] + %if cpuflag(ssse3) + movu %1, [%2] + pshufb m2, %1, shufB + pshufb m3, %1, shufC + pshufb %1, shufA + %else + PREP_8TAP_H_LOAD4 %1, %2+0, m1, %3, %4 + PREP_8TAP_H_LOAD4 m2, %2+4, m1, %3, %4 + PREP_8TAP_H_LOAD4 m3, %2+8, m1, %3, %4 + %endif + mova m1, m2 + PMADDUBSW m1, subpelh0, %3, %4, 1 ; subpel +0 C0 + PMADDUBSW m3, subpelh1, %3, %4, 0 ; subpel +4 B4 + PMADDUBSW m2, subpelh1, %3, %4, 0 ; C4 + PMADDUBSW %1, subpelh0, %3, %4, 0 ; A0 + paddw m1, m3 ; C0+B4 + paddw %1, m2 ; A0+C4 + PHADDW %1, m1, %3, 1 +%endmacro + +%macro PREP_8TAP 0 +%if ARCH_X86_32 + DECLARE_REG_TMP 1, 2 +%elif WIN64 + DECLARE_REG_TMP 6, 4 +%else + DECLARE_REG_TMP 6, 7 +%endif + +FN prep_8tap, sharp, SHARP, SHARP +FN prep_8tap, sharp_smooth, SHARP, SMOOTH +FN prep_8tap, smooth_sharp, SMOOTH, SHARP +FN prep_8tap, smooth, SMOOTH, SMOOTH +FN prep_8tap, sharp_regular, SHARP, REGULAR +FN prep_8tap, regular_sharp, REGULAR, SHARP +FN prep_8tap, smooth_regular, SMOOTH, REGULAR +FN prep_8tap, regular_smooth, REGULAR, SMOOTH +FN prep_8tap, regular, REGULAR, REGULAR + +%if ARCH_X86_32 + %define base_reg r2 + %define base base_reg-prep%+SUFFIX +%else + %define base_reg r7 + %define base 0 +%endif +cglobal prep_8tap_8bpc, 1, 9, 0, tmp, src, stride, w, h, mx, my, stride3 +%assign org_stack_offset stack_offset + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + mov wd, wm + movifnidn srcd, srcm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + LEA base_reg, prep_ssse3 + tzcnt wd, wd + movzx wd, word [base_reg-prep_ssse3+prep_ssse3_table+wq*2] + pxor m4, m4 + add wq, base_reg + movifnidn strided, stridem + lea r6, [strideq*3] + %assign stack_offset org_stack_offset +%if WIN64 + pop r8 + pop r7 +%endif + jmp wq +.h: + LEA base_reg, prep%+SUFFIX + test myd, 0xf00 + jnz .hv +%if cpuflag(ssse3) + WIN64_SPILL_XMM 12 +%else + WIN64_SPILL_XMM 16 +%endif +%if ARCH_X86_32 + %define strideq r6 + mov strideq, stridem +%endif + cmp wd, 4 + je .h_w4 + tzcnt wd, wd +%if cpuflag(ssse3) + %if ARCH_X86_64 + mova m10, [base+subpel_h_shufA] + mova m11, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] + %else + %define m10 [base+subpel_h_shufA] + %define m11 [base+subpel_h_shufB] + %define m9 [base+subpel_h_shufC] + %endif +%endif + shr mxd, 16 + sub srcq, 3 + movzx wd, word [base_reg+wq*2+table_offset(prep, _8tap_h)] + movq m6, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] +%if cpuflag(ssse3) + mova m7, [base+pw_8192] + pshufd m5, m6, q0000 + pshufd m6, m6, q1111 +%else + punpcklbw m6, m6 + psraw m6, 8 + %if ARCH_X86_64 + mova m7, [pw_2] + mova m15, [pw_1] + %else + %define m15 m4 + %endif + pshufd m5, m6, q1010 + punpckhqdq m6, m6 +%endif + add wq, base_reg + jmp wq +.h_w4: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m4, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX+2] +%if cpuflag(ssse3) + mova m6, [base+pw_8192] + mova m5, [base+subpel_h_shufA] + pshufd m4, m4, q0000 +%else + mova m6, [base+pw_2] + %if ARCH_X86_64 + mova m14, [pw_1] + %else + %define m14 m7 + %endif + punpcklbw m4, m4 + psraw m4, 8 + punpcklqdq m4, m4 +%endif +%if ARCH_X86_64 + lea stride3q, [strideq*3] +%endif +.h_w4_loop: +%if cpuflag(ssse3) + movq m0, [srcq+strideq*0] ; 0 + movq m1, [srcq+strideq*1] ; 1 + %if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m2, [srcq+strideq*0] ; 2 + movq m3, [srcq+strideq*1] ; 3 + lea srcq, [srcq+strideq*2] + %else + movq m2, [srcq+strideq*2] ; 2 + movq m3, [srcq+stride3q ] ; 3 + lea srcq, [srcq+strideq*4] + %endif + pshufb m0, m5 + pshufb m1, m5 + pshufb m2, m5 + pshufb m3, m5 +%elif ARCH_X86_64 + movd m0, [srcq+strideq*0+0] + movd m12, [srcq+strideq*0+1] + movd m1, [srcq+strideq*1+0] + movd m5, [srcq+strideq*1+1] + movd m2, [srcq+strideq*2+0] + movd m13, [srcq+strideq*2+1] + movd m3, [srcq+stride3q +0] + movd m7, [srcq+stride3q +1] + punpckldq m0, m12 + punpckldq m1, m5 + punpckldq m2, m13 + punpckldq m3, m7 + movd m12, [srcq+strideq*0+2] + movd m8, [srcq+strideq*0+3] + movd m5, [srcq+strideq*1+2] + movd m9, [srcq+strideq*1+3] + movd m13, [srcq+strideq*2+2] + movd m10, [srcq+strideq*2+3] + movd m7, [srcq+stride3q +2] + movd m11, [srcq+stride3q +3] + lea srcq, [srcq+strideq*4] + punpckldq m12, m8 + punpckldq m5, m9 + punpckldq m13, m10 + punpckldq m7, m11 + punpcklqdq m0, m12 ; 0 + punpcklqdq m1, m5 ; 1 + punpcklqdq m2, m13 ; 2 + punpcklqdq m3, m7 ; 3 +%else + movd m0, [srcq+strideq*0+0] + movd m1, [srcq+strideq*0+1] + movd m2, [srcq+strideq*0+2] + movd m3, [srcq+strideq*0+3] + punpckldq m0, m1 + punpckldq m2, m3 + punpcklqdq m0, m2 ; 0 + movd m1, [srcq+strideq*1+0] + movd m2, [srcq+strideq*1+1] + movd m3, [srcq+strideq*1+2] + movd m7, [srcq+strideq*1+3] + lea srcq, [srcq+strideq*2] + punpckldq m1, m2 + punpckldq m3, m7 + punpcklqdq m1, m3 ; 1 + movd m2, [srcq+strideq*0+0] + movd m3, [srcq+strideq*0+1] + movd m7, [srcq+strideq*0+2] + movd m5, [srcq+strideq*0+3] + punpckldq m2, m3 + punpckldq m7, m5 + punpcklqdq m2, m7 ; 2 + movd m3, [srcq+strideq*1+0] + movd m7, [srcq+strideq*1+1] + punpckldq m3, m7 + movd m7, [srcq+strideq*1+2] + movd m5, [srcq+strideq*1+3] + lea srcq, [srcq+strideq*2] + punpckldq m7, m5 + punpcklqdq m3, m7 ; 3 +%endif + PMADDUBSW m0, m4, m5, m7, 1 ; subpel_filters + 2 + PMADDUBSW m1, m4, m5, m7, 0 + PMADDUBSW m2, m4, m5, m7, 0 + PMADDUBSW m3, m4, m5, m7, 0 + PHADDW m0, m1, m14, ARCH_X86_32 + PHADDW m2, m3, m14, 0 + PMULHRSW_8192 m0, m0, m6 + PMULHRSW_8192 m2, m2, m6 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m2 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: +%if cpuflag(ssse3) + PREP_8TAP_H 0, srcq+strideq*0 + PREP_8TAP_H 1, srcq+strideq*1 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + lea srcq, [srcq+strideq*2] + add tmpq, 32 + sub hd, 2 +%else + PREP_8TAP_H 0, srcq + mova [tmpq], m0 + add srcq, strideq + add tmpq, 16 + dec hd +%endif + jg .h_w8 + RET +.h_w16: + mov r3, -16*1 + jmp .h_start +.h_w32: + mov r3, -16*2 + jmp .h_start +.h_w64: + mov r3, -16*4 + jmp .h_start +.h_w128: + mov r3, -16*8 +.h_start: + sub srcq, r3 + mov r5, r3 +.h_loop: +%if cpuflag(ssse3) + PREP_8TAP_H 0, srcq+r3+8*0 + PREP_8TAP_H 1, srcq+r3+8*1 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 32 + add r3, 16 +%else + PREP_8TAP_H 0, srcq+r3 + mova [tmpq], m0 + add tmpq, 16 + add r3, 8 +%endif + jl .h_loop + add srcq, strideq + mov r3, r5 + dec hd + jg .h_loop + RET +.v: + LEA base_reg, prep%+SUFFIX +%if ARCH_X86_32 + mov mxd, myd + and mxd, 0x7f +%else + %assign stack_offset org_stack_offset + WIN64_SPILL_XMM 16 + movzx mxd, myb +%endif + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] +%if cpuflag(ssse3) + mova m2, [base+pw_512] + mova m7, [base+pw_8192] + punpcklwd m0, m0 +%else + punpcklbw m0, m0 + psraw m0, 8 +%endif +%if ARCH_X86_32 + %define subpel0 [rsp+mmsize*0] + %define subpel1 [rsp+mmsize*1] + %define subpel2 [rsp+mmsize*2] + %define subpel3 [rsp+mmsize*3] +%assign regs_used 6 ; use r5 (mx) as tmp for stack alignment if needed + %if cpuflag(ssse3) + ALLOC_STACK -mmsize*4 + %else + ALLOC_STACK -mmsize*5 + %endif +%assign regs_used 7 + mov strideq, [rstk+stack_offset+gprsize*3] + pshufd m1, m0, q0000 + mova subpel0, m1 + pshufd m1, m0, q1111 + mova subpel1, m1 + lea r5, [strideq*3] + pshufd m1, m0, q2222 + mova subpel2, m1 + pshufd m1, m0, q3333 + mova subpel3, m1 + sub srcq, r5 +%else + %define subpel0 m8 + %define subpel1 m9 + %define subpel2 m10 + %define subpel3 m11 + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + lea stride3q, [strideq*3] + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + sub srcq, stride3q + cmp wd, 8 + jns .v_w8 +%endif +.v_w4: +%if notcpuflag(ssse3) + pxor m6, m6 + %if ARCH_X86_64 + mova m7, [base+pw_2] + %endif +%endif +%if ARCH_X86_32 + %if STACK_ALIGNMENT < mmsize + %define srcm [esp+stack_size+gprsize*1] + %define tmpm [esp+stack_size+gprsize*2] + %endif + mov tmpm, tmpq + mov srcm, srcq + lea r5d, [wq - 4] ; horizontal loop + shl r5d, (16 - 2) ; (wq / 4) << 16 + mov r5w, hw +.v_w4_loop0: +%endif + movd m1, [srcq+strideq*0] + movd m0, [srcq+strideq*1] +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movd m2, [srcq+strideq*0] + movd m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movd m3, [srcq+strideq*0] + movd m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] +%else + movd m2, [srcq+strideq*2] + add srcq, stride3q + movd m4, [srcq+strideq*0] + movd m3, [srcq+strideq*1] + movd m5, [srcq+strideq*2] + add srcq, stride3q +%endif + punpckldq m1, m0 ; 0 1 + punpckldq m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+strideq*0] + punpckldq m2, m4 ; 2 3 + punpckldq m4, m3 ; 3 4 + punpckldq m3, m5 ; 4 5 + punpckldq m5, m0 ; 5 6 + punpcklbw m2, m4 ; 23 34 + punpcklbw m3, m5 ; 45 56 +.v_w4_loop: +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel0 + %define subpel0 m7 +%endif + mova m5, m1 + PMADDUBSW m5, subpel0, m6, m4, 0 ; a0 b0 +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel1 + %define subpel1 m7 +%endif + mova m1, m2 + PMADDUBSW m2, subpel1, m6, m4, 0 ; a1 b1 + paddw m5, m2 +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel2 + %define subpel2 m7 +%endif + mova m2, m3 + PMADDUBSW m3, subpel2, m6, m4, 0 ; a2 b2 + movd m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + paddw m5, m3 + punpckldq m3, m0, m4 ; 6 7 _ _ + movd m0, [srcq+strideq*0] + punpckldq m4, m0 ; 7 8 _ _ + punpcklbw m3, m4 ; 67 78 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m12, m0 + %else + mova [esp+mmsize*4], m0 + mova m7, subpel3 + %define subpel3 m7 + %endif +%endif + mova m4, m3 + PMADDUBSW m4, subpel3, m6, m0, 0 ; a3 b3 + paddw m5, m4 +%if ARCH_X86_64 || cpuflag(ssse3) + %if notcpuflag(ssse3) + SWAP m0, m12 + %endif + PMULHRSW_8192 m5, m5, m7 +%else + mova m0, [esp+mmsize*4] + PMULHRSW_8192 m5, m5, [base+pw_2] +%endif + movq [tmpq+wq*0], m5 + movhps [tmpq+wq*2], m5 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w4_loop +%if ARCH_X86_32 + mov srcq, srcm + mov tmpq, tmpm + movzx hd, r5w + add srcq, 4 + add tmpq, 8 + mov srcm, srcq + mov tmpm, tmpq + sub r5d, 1<<16 ; horizontal-- + jg .v_w4_loop0 +%endif + RET +%if ARCH_X86_64 +.v_w8: + lea r6d, [wq*8-64] + mov r5, srcq + mov r8, tmpq + lea r6d, [hq+r6*4] +.v_w8_loop0: + movq m1, [srcq+strideq*0] + movq m2, [srcq+strideq*1] + movq m3, [srcq+strideq*2] + add srcq, stride3q + movq m4, [srcq+strideq*0] + movq m5, [srcq+strideq*1] + movq m6, [srcq+strideq*2] + add srcq, stride3q + movq m0, [srcq+strideq*0] + punpcklbw m1, m2 ; 01 + punpcklbw m2, m3 ; 12 + punpcklbw m3, m4 ; 23 + punpcklbw m4, m5 ; 34 + punpcklbw m5, m6 ; 45 + punpcklbw m6, m0 ; 56 +.v_w8_loop: + movq m13, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] +%if cpuflag(ssse3) + pmaddubsw m14, m1, subpel0 ; a0 + pmaddubsw m15, m2, subpel0 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, subpel1 ; a1 + pmaddubsw m4, subpel1 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, subpel2 ; a2 + pmaddubsw m6, subpel2 ; b2 + punpcklbw m12, m0, m13 ; 67 + movq m0, [srcq+strideq*0] + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + pmaddubsw m12, subpel3 ; a3 + paddw m15, m6 + mova m6, m13 + pmaddubsw m13, subpel3 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 +%else + mova m14, m1 + PMADDUBSW m14, subpel0, m7, m12, 1 ; a0 + mova m15, m2 + PMADDUBSW m15, subpel0, m7, m12, 0 ; b0 + mova m1, m3 + PMADDUBSW m3, subpel1, m7, m12, 0 ; a1 + mova m2, m4 + PMADDUBSW m4, subpel1, m7, m12, 0 ; b1 + paddw m14, m3 + mova m3, m5 + PMADDUBSW m5, subpel2, m7, m12, 0 ; a2 + paddw m15, m4 + mova m4, m6 + PMADDUBSW m6, subpel2, m7, m12, 0 ; b2 + paddw m15, m6 + punpcklbw m12, m0, m13 ; 67 + movq m0, [srcq+strideq*0] + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + PMADDUBSW m12, subpel3, m7, m6, 0 ; a3 + paddw m14, m12 + mova m6, m13 + PMADDUBSW m13, subpel3, m7, m12, 0 ; b3 + paddw m15, m13 + PMULHRSW_8192 m14, m14, [base+pw_2] + PMULHRSW_8192 m15, m15, [base+pw_2] +%endif + movu [tmpq+wq*0], m14 + movu [tmpq+wq*2], m15 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w8_loop + add r5, 8 + add r8, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r8 + sub r6d, 1<<8 + jg .v_w8_loop0 + RET +%endif ;ARCH_X86_64 +%undef subpel0 +%undef subpel1 +%undef subpel2 +%undef subpel3 +.hv: + %assign stack_offset org_stack_offset + cmp wd, 4 + jg .hv_w8 + and mxd, 0x7f + movd m1, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX+2] +%if ARCH_X86_32 + mov mxd, myd + shr myd, 16 + and mxd, 0x7f + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + mov strideq, stridem + %assign regs_used 6 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + lea r5, [strideq*3+1] + sub srcq, r5 + %define subpelv0 [rsp+mmsize*0] + %define subpelv1 [rsp+mmsize*1] + %define subpelv2 [rsp+mmsize*2] + %define subpelv3 [rsp+mmsize*3] + punpcklbw m0, m0 + psraw m0, 8 + pshufd m6, m0, q0000 + mova subpelv0, m6 + pshufd m6, m0, q1111 + mova subpelv1, m6 + pshufd m6, m0, q2222 + mova subpelv2, m6 + pshufd m6, m0, q3333 + mova subpelv3, m6 +%else + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + %if cpuflag(ssse3) + ALLOC_STACK mmsize*14, 14 + %else + ALLOC_STACK mmsize*14, 16 + %endif + lea stride3q, [strideq*3] + sub srcq, stride3q + dec srcq + %define subpelv0 m10 + %define subpelv1 m11 + %define subpelv2 m12 + %define subpelv3 m13 + punpcklbw m0, m0 + psraw m0, 8 + %if cpuflag(ssse3) + mova m8, [base+pw_8192] + %else + mova m8, [base+pw_2] + %endif + mova m9, [base+pd_32] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + pshufd m7, m1, q0000 +%if notcpuflag(ssse3) + punpcklbw m7, m7 + psraw m7, 8 +%endif +%define hv4_line_0_0 4 +%define hv4_line_0_1 5 +%define hv4_line_0_2 6 +%define hv4_line_0_3 7 +%define hv4_line_0_4 8 +%define hv4_line_0_5 9 +%define hv4_line_1_0 10 +%define hv4_line_1_1 11 +%define hv4_line_1_2 12 +%define hv4_line_1_3 13 +%if ARCH_X86_32 + %if cpuflag(ssse3) + %define w8192reg [base+pw_8192] + %else + %define w8192reg [base+pw_2] + %endif + %define d32reg [base+pd_32] +%else + %define w8192reg m8 + %define d32reg m9 +%endif + ; lower shuffle 0 1 2 3 4 +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%else + %if ARCH_X86_64 + mova m15, [pw_1] + %else + %define m15 m1 + %endif +%endif + movq m5, [srcq+strideq*0] ; 0 _ _ _ + movhps m5, [srcq+strideq*1] ; 0 _ 1 _ +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m4, [srcq+strideq*0] ; 2 _ _ _ + movhps m4, [srcq+strideq*1] ; 2 _ 3 _ + lea srcq, [srcq+strideq*2] +%else + movq m4, [srcq+strideq*2] ; 2 _ _ _ + movhps m4, [srcq+stride3q ] ; 2 _ 3 _ + lea srcq, [srcq+strideq*4] +%endif + PSHUFB_SUBPEL_H_4a m2, m5, m6, m1, m3, 1 ;H subpel_h_shuf4 0~1~ + PSHUFB_SUBPEL_H_4a m0, m4, m6, m1, m3, 0 ;H subpel_h_shuf4 2~3~ + PMADDUBSW m2, m7, m1, m3, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m3, 0 ;H subpel_filters + PHADDW m2, m0, m15, ARCH_X86_32 ;H 0 1 2 3 + PMULHRSW_8192 m2, m2, w8192reg + SAVELINE_W4 m2, 2, 0 + ; upper shuffle 2 3 4 5 6 +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + PSHUFB_SUBPEL_H_4b m2, m5, m6, m1, m3, 0 ;H subpel_h_shuf4 0~1~ + PSHUFB_SUBPEL_H_4b m0, m4, m6, m1, m3, 0 ;H subpel_h_shuf4 2~3~ + PMADDUBSW m2, m7, m1, m3, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m3, 0 ;H subpel_filters + PHADDW m2, m0, m15, ARCH_X86_32 ;H 0 1 2 3 + PMULHRSW_8192 m2, m2, w8192reg +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m2 + %else + mova [esp+mmsize*4], m2 + %endif +%endif + ; lower shuffle +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%endif + movq m5, [srcq+strideq*0] ; 4 _ _ _ + movhps m5, [srcq+strideq*1] ; 4 _ 5 _ +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m4, [srcq+strideq*0] ; 6 _ _ _ + add srcq, strideq +%else + movq m4, [srcq+strideq*2] ; 6 _ _ _ + add srcq, stride3q +%endif + PSHUFB_SUBPEL_H_4a m3, m5, m6, m1, m2, 0 ;H subpel_h_shuf4 4~5~ + PSHUFB_SUBPEL_H_4a m0, m4, m6, m1, m2, 0 ;H subpel_h_shuf4 6~6~ + PMADDUBSW m3, m7, m1, m2, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m2, 0 ;H subpel_filters + PHADDW m3, m0, m15, ARCH_X86_32 ;H 4 5 6 7 + PMULHRSW_8192 m3, m3, w8192reg + SAVELINE_W4 m3, 3, 0 + ; upper shuffle +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + PSHUFB_SUBPEL_H_4b m3, m5, m6, m1, m2, 0 ;H subpel_h_shuf4 4~5~ + PSHUFB_SUBPEL_H_4b m0, m4, m6, m1, m2, 0 ;H subpel_h_shuf4 6~6~ + PMADDUBSW m3, m7, m1, m2, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m2, 0 ;H subpel_filters + PHADDW m3, m0, m15, ARCH_X86_32 ;H 4 5 6 7 + PMULHRSW_8192 m3, m3, w8192reg +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m2, m14 + %else + mova m2, [esp+mmsize*4] + %endif +%endif + ;process high + PALIGNR m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + ;process low + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + PALIGNR m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 +.hv_w4_loop: + ;process low + pmaddwd m5, m1, subpelv0 ; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m5 + %else + mova [esp+mmsize*4], m5 + %define m15 m3 + %endif +%endif +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%endif + movq m4, [srcq+strideq*0] ; 7 + movhps m4, [srcq+strideq*1] ; 7 _ 8 _ + PSHUFB_SUBPEL_H_4a m4, m4, m6, m3, m5, 0 ; H subpel_h_shuf4 7~8~ + PMADDUBSW m4, m7, m3, m5, 1 ; H subpel_filters + PHADDW m4, m4, m15, ARCH_X86_32 ; H 7878 + PMULHRSW_8192 m4, m4, w8192reg + PALIGNR m3, m4, m0, 12, m5 ; 6787 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m5, m14 + %else + mova m5, [esp+mmsize*4] + %endif +%endif + paddd m5, d32reg ; pd_32 + paddd m5, m4 + psrad m5, 6 + SAVELINE_W4 m0, 0, 0 + SAVELINE_W4 m1, 1, 0 + SAVELINE_W4 m2, 2, 0 + SAVELINE_W4 m3, 3, 0 + SAVELINE_W4 m5, 5, 0 + ;process high + RESTORELINE_W4 m0, 0, 1 + RESTORELINE_W4 m1, 1, 1 + RESTORELINE_W4 m2, 2, 1 + RESTORELINE_W4 m3, 3, 1 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m5 + %else + mova [esp+0xA0], m5 + %endif +%endif +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + movq m4, [srcq+strideq*0] ; 7 + movhps m4, [srcq+strideq*1] ; 7 _ 8 _ + PSHUFB_SUBPEL_H_4b m4, m4, m6, m3, m5, 0 ; H subpel_h_shuf4 7~8~ + PMADDUBSW m4, m7, m3, m5, 1 ; H subpel_filters + PHADDW m4, m4, m15, ARCH_X86_32 ; H 7878 + PMULHRSW_8192 m4, m4, w8192reg + PALIGNR m3, m4, m0, 12, m5 ; 6787 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m5, m14 + %else + mova m5, [esp+0xA0] + %endif +%endif + paddd m5, d32reg ; pd_32 + paddd m5, m4 + psrad m4, m5, 6 + RESTORELINE_W4 m5, 5, 0 + packssdw m5, m4 + pshufd m5, m5, q3120 + movu [tmpq], m5 + lea srcq, [srcq+strideq*2] + add tmpq, 16 + sub hd, 2 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + RESTORELINE_W4 m0, 0, 0 + RESTORELINE_W4 m1, 1, 0 + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + jg .hv_w4_loop + RET +%undef subpelv0 +%undef subpelv1 +%undef subpelv2 +%undef subpelv3 +.hv_w8: + %assign stack_offset org_stack_offset +%define hv8_line_1 0 +%define hv8_line_2 1 +%define hv8_line_3 2 +%define hv8_line_4 3 +%define hv8_line_6 4 + shr mxd, 16 +%if ARCH_X86_32 + %define subpelh0 [rsp+mmsize*5] + %define subpelh1 [rsp+mmsize*6] + %define subpelv0 [rsp+mmsize*7] + %define subpelv1 [rsp+mmsize*8] + %define subpelv2 [rsp+mmsize*9] + %define subpelv3 [rsp+mmsize*10] + %define accuv0 [rsp+mmsize*11] + %define accuv1 [rsp+mmsize*12] + movq m1, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] + mov mxd, myd + shr myd, 16 + and mxd, 0x7f + cmp hd, 6 + cmovs myd, mxd + movq m5, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + mov strideq, stridem + %assign regs_used 6 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + %if STACK_ALIGNMENT < mmsize + %define tmpm [rsp+mmsize*13+gprsize*1] + %define srcm [rsp+mmsize*13+gprsize*2] + %define stridem [rsp+mmsize*13+gprsize*3] + mov tmpm, tmpq + mov stridem, strideq + %endif + %if cpuflag(ssse3) + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + %else + punpcklbw m1, m1 + psraw m1, 8 + pshufd m0, m1, q1010 + punpckhqdq m1, m1 + %endif + punpcklbw m5, m5 + psraw m5, 8 + pshufd m2, m5, q0000 + pshufd m3, m5, q1111 + pshufd m4, m5, q2222 + pshufd m5, m5, q3333 + mova subpelh0, m0 + mova subpelh1, m1 + mova subpelv0, m2 + mova subpelv1, m3 + mova subpelv2, m4 + mova subpelv3, m5 + lea r5, [strideq*3+3] + sub srcq, r5 + mov srcm, srcq +%else + ALLOC_STACK mmsize*5, 16 + %define subpelh0 m10 + %define subpelh1 m11 + %define subpelv0 m12 + %define subpelv1 m13 + %define subpelv2 m14 + %define subpelv3 m15 + %define accuv0 m8 + %define accuv1 m9 + movq m0, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m1, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + %if cpuflag(ssse3) + pshufd subpelh0, m0, q0000 + pshufd subpelh1, m0, q1111 + %else + punpcklbw m0, m0 + psraw m0, 8 + pshufd subpelh0, m0, q1010 + pshufd subpelh1, m0, q3232 + mova m7, [base+pw_2] + %endif + punpcklbw m1, m1 + psraw m1, 8 + pshufd subpelv0, m1, q0000 + pshufd subpelv1, m1, q1111 + pshufd subpelv2, m1, q2222 + pshufd subpelv3, m1, q3333 + lea stride3q, [strideq*3] + sub srcq, 3 + sub srcq, stride3q + mov r6, srcq + mov r8, tmpq +%endif + lea r5d, [wq-4] + shl r5d, 14 + add r5d, hd +.hv_w8_loop0: +%if cpuflag(ssse3) + %if ARCH_X86_64 + mova m7, [base+subpel_h_shufA] + mova m8, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] + %define shufA m7 + %define shufB m8 + %define shufC m9 + %else + %define shufA [base+subpel_h_shufA] + %define shufB [base+subpel_h_shufB] + %define shufC [base+subpel_h_shufC] + %endif +%endif + PREP_8TAP_HV m4, srcq+strideq*0, m7, m0 + PREP_8TAP_HV m5, srcq+strideq*1, m7, m0 +%if ARCH_X86_64 + PREP_8TAP_HV m6, srcq+strideq*2, m7, m0 + add srcq, stride3q + PREP_8TAP_HV m0, srcq+strideq*0, m7, m9 +%else + lea srcq, [srcq+strideq*2] + %if notcpuflag(ssse3) + mova [esp], m4 + %endif + PREP_8TAP_HV m6, srcq+strideq*0, m7, m4 + PREP_8TAP_HV m0, srcq+strideq*1, m7, m4 + lea srcq, [srcq+strideq*2] +%endif +%if cpuflag(ssse3) + mova m7, [base+pw_8192] +%else + mova m7, [base+pw_2] + %if ARCH_X86_32 + mova m4, [esp] + %endif +%endif + PMULHRSW_8192 m4, m4, m7 + PMULHRSW_8192 m5, m5, m7 + PMULHRSW_8192 m6, m6, m7 + PMULHRSW_8192 m0, m0, m7 + punpcklwd m1, m4, m5 ; 01 + punpcklwd m2, m5, m6 ; 12 + punpcklwd m3, m6, m0 ; 23 + SAVELINE_W8 1, m1 + SAVELINE_W8 2, m2 + SAVELINE_W8 3, m3 +%if cpuflag(ssse3) + mova m7, [base+subpel_h_shufA] +%endif +%if ARCH_X86_64 + PREP_8TAP_HV m4, srcq+strideq*1, m8, m9 + PREP_8TAP_HV m5, srcq+strideq*2, m8, m9 + add srcq, stride3q + PREP_8TAP_HV m6, srcq+strideq*0, m8, m9 +%else + %if notcpuflag(ssse3) + mova [esp+0x30], m0 + %endif + PREP_8TAP_HV m4, srcq+strideq*0, m7, m0 + PREP_8TAP_HV m5, srcq+strideq*1, m7, m0 + lea srcq, [srcq+strideq*2] + PREP_8TAP_HV m6, srcq+strideq*0, m7, m0 +%endif +%if cpuflag(ssse3) + mova m7, [base+pw_8192] +%elif ARCH_X86_32 + mova m0, [esp+0x30] + mova m7, [base+pw_2] +%endif + PMULHRSW_8192 m1, m4, m7 + PMULHRSW_8192 m2, m5, m7 + PMULHRSW_8192 m3, m6, m7 + punpcklwd m4, m0, m1 ; 34 + punpcklwd m5, m1, m2 ; 45 + punpcklwd m6, m2, m3 ; 56 + SAVELINE_W8 6, m3 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 +.hv_w8_loop: + SAVELINE_W8 1, m3 + SAVELINE_W8 2, m4 + SAVELINE_W8 3, m5 + SAVELINE_W8 4, m6 +%if ARCH_X86_32 + pmaddwd m0, m1, subpelv0 ; a0 + pmaddwd m7, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m0, m3 + paddd m7, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m0, m5 + paddd m7, m6 + mova m5, [base+pd_32] + paddd m0, m5 + paddd m7, m5 + mova accuv0, m0 + mova accuv1, m7 +%else + pmaddwd accuv0, m1, subpelv0 ; a0 + pmaddwd accuv1, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd accuv0, m3 + paddd accuv1, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd accuv0, m5 + paddd accuv1, m6 + mova m7, [base+pd_32] + paddd accuv0, m7 + paddd accuv1, m7 + %if cpuflag(ssse3) + mova m7, [base+subpel_h_shufB] + mova m6, [base+subpel_h_shufC] + mova m5, [base+subpel_h_shufA] + %define shufA m5 + %define shufB m7 + %define shufC m6 + %endif +%endif + PREP_8TAP_HV m0, srcq+strideq*1, m5, m6 + lea srcq, [srcq+strideq*2] + PREP_8TAP_HV m4, srcq+strideq*0, m5, m6 +%if cpuflag(ssse3) + mova m5, [base+pw_8192] +%else + mova m5, [base+pw_2] +%endif + PMULHRSW_8192 m0, m0, m5 + PMULHRSW_8192 m4, m4, m5 + RESTORELINE_W8 6, m6 + punpcklwd m5, m6, m0 ; 67 + punpcklwd m6, m0, m4 ; 78 + pmaddwd m1, m5, subpelv3 ; a3 + paddd m2, m1, accuv0 + pmaddwd m1, m6, subpelv3 ; b3 + paddd m1, m1, accuv1 + psrad m2, 6 + psrad m1, 6 + packssdw m2, m1 + movq [tmpq+wq*0], m2 + movhps [tmpq+wq*2], m2 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jle .hv_w8_outer + SAVELINE_W8 6, m4 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 + RESTORELINE_W8 4, m4 + jmp .hv_w8_loop +.hv_w8_outer: +%if ARCH_X86_32 + mov srcq, srcm + mov tmpq, tmpm + movzx hd, r5w + add srcq, 4 + add tmpq, 8 + mov srcm, srcq + mov tmpm, tmpq +%else + add r6, 4 + add r8, 8 + movzx hd, r5b + mov srcq, r6 + mov tmpq, r8 +%endif + sub r5d, 1<<16 + jg .hv_w8_loop0 + RET +%endmacro + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro SAVE_REG 1 + %xdefine r%1_save r%1 + %xdefine r%1q_save r%1q + %xdefine r%1d_save r%1d + %if ARCH_X86_32 + %define r%1m_save [rstk+stack_offset+(%1+1)*4] + %endif +%endmacro + +%macro LOAD_REG 1 + %xdefine r%1 r%1_save + %xdefine r%1q r%1q_save + %xdefine r%1d r%1d_save + %if ARCH_X86_32 + %define r%1m r%1m_save + %endif + %undef r%1d_save + %undef r%1q_save + %undef r%1_save +%endmacro + +%macro REMAP_REG 2-3 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d + %if ARCH_X86_32 + %if %3 == 0 + %xdefine r%1m r%2m + %else + %define r%1m [rstk+stack_offset+(%1+1)*4] + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %if ARCH_X86_64 + SAVE_REG 14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %else + SAVE_REG 5 + %assign %%i 5 + %rep 5 + %assign %%j %%i-1 + REMAP_REG %%i, %%j, 0 + %assign %%i %%i-1 + %endrep + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %if ARCH_X86_64 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + LOAD_REG 14 + %else + %rep 4 + %assign %%j %%i+1 + REMAP_REG %%i, %%j, 1 + %assign %%i %%i+1 + %endrep + LOAD_REG 5 + %endif + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%if ARCH_X86_64 + %macro MC_8TAP_SCALED_H 12 ; dst[0-1], tmp[0-5], weights[0-3] + SWAP m%2, m%5 + movq m%1, [srcq+ r4] + movq m%2, [srcq+ r6] + movhps m%1, [srcq+ r7] + movhps m%2, [srcq+ r9] + movq m%3, [srcq+r10] + movq m%4, [srcq+r11] + movhps m%3, [srcq+r13] + movhps m%4, [srcq+ rX] + add srcq, ssq + movq m%5, [srcq+ r4] + movq m%6, [srcq+ r6] + movhps m%5, [srcq+ r7] + movhps m%6, [srcq+ r9] + movq m%7, [srcq+r10] + movq m%8, [srcq+r11] + movhps m%7, [srcq+r13] + movhps m%8, [srcq+ rX] + add srcq, ssq + pmaddubsw m%1, m%9 + pmaddubsw m%5, m%9 + pmaddubsw m%2, m%10 + pmaddubsw m%6, m%10 + pmaddubsw m%3, m%11 + pmaddubsw m%7, m%11 + pmaddubsw m%4, m%12 + pmaddubsw m%8, m%12 + phaddw m%1, m%2 + phaddw m%5, m%6 + phaddw m%3, m%4 + phaddw m%7, m%8 + phaddw m%1, m%3 + phaddw m%5, m%7 + pmulhrsw m%1, m12 + pmulhrsw m%5, m12 + SWAP m%2, m%5 + %endmacro +%else + %macro MC_8TAP_SCALED_H 2-3 1 ; weights_mem_start, h_mem_start, load_fh_offsets + %if %3 == 1 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + %endif + movq m0, [srcq+r0] + movq m1, [srcq+rX] + movhps m0, [srcq+r4] + movhps m1, [srcq+r5] + add srcq, ssq + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + sub srcq, ssq + movq m2, [srcq+r0] + movq m3, [srcq+rX] + movhps m2, [srcq+r4] + movhps m3, [srcq+r5] + add srcq, ssq + movq m6, [srcq+r0] + movq m7, [srcq+rX] + movhps m6, [srcq+r4] + movhps m7, [srcq+r5] + add srcq, ssq + pmaddubsw m0, [esp+%1+ 0] + pmaddubsw m4, [esp+%1+ 0] + pmaddubsw m1, [esp+%1+16] + pmaddubsw m5, [esp+%1+16] + pmaddubsw m2, [esp+%1+32] + pmaddubsw m6, [esp+%1+32] + pmaddubsw m3, [esp+%1+48] + pmaddubsw m7, [esp+%1+48] + phaddw m0, m1 + phaddw m4, m5 + phaddw m2, m3 + phaddw m6, m7 + phaddw m0, m2 + phaddw m4, m6 + pmulhrsw m0, m12 + pmulhrsw m4, m12 + %if %2 != 0 + mova [esp+%2+ 0], m0 + mova [esp+%2+16], m4 + %endif + %endmacro +%endif + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isprep 0 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_8bpc, 2, 15, 16, 0x180, dst, ds, src, ss, w, h, mx, my, dx, dy + %else +cglobal put_8tap_scaled_8bpc, 2, 14, 16, 0x180, dst, ds, src, ss, w, h, mx, my, dx, dy + %endif + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_8bpc, 0, 7, 8, 0x200, dst, ds, src, ss, w, h, mx, my, dx, dy + %else +cglobal put_8tap_scaled_8bpc, 0, 7, 8, -0x200-0x20, dst, ds, src, ss, w, h, mx, my, dx, dy + %endif + %endif + %xdefine base_reg r12 + %define rndshift 10 +%else ; prep + %assign isprep 1 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_8bpc, 2, 15, 16, 0x180, tmp, src, ss, w, h, mx, my, dx, dy + %xdefine tmp_stridem r14q + %else +cglobal prep_8tap_scaled_8bpc, 2, 14, 16, 0x180, tmp, src, ss, w, h, mx, my, dx, dy + %define tmp_stridem qword [rsp+0x138] + %endif + %xdefine base_reg r11 + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_8bpc, 0, 7, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy + %else +cglobal prep_8tap_scaled_8bpc, 0, 6, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy + %endif + %define tmp_stridem dword [esp+0x138] + %endif + %define rndshift 6 +%endif +%if ARCH_X86_32 + mov [esp+0x1f0], t0d + mov [esp+0x1f4], t1d + %if !isprep && required_stack_alignment > STACK_ALIGNMENT + mov dstd, dstm + mov dsd, dsm + mov srcd, srcm + mov ssd, ssm + mov hd, hm + mov r4, mxm + %define r0m [esp+0x200] + %define dsm [esp+0x204] + %define dsmp dsm + %define r1m dsm + %define r2m [esp+0x208] + %define ssm [esp+0x20c] + %define r3m ssm + %define hm [esp+0x210] + %define mxm [esp+0x214] + mov r0m, dstd + mov dsm, dsd + mov r2m, srcd + mov ssm, ssd + mov hm, hd + mov r0, mym + mov r1, dxm + mov r2, dym + %define mym [esp+0x218] + %define dxm [esp+0x09c] + %define dym [esp+0x21c] + mov mxm, r4 + mov mym, r0 + mov dxm, r1 + mov dym, r2 + tzcnt wd, wm + %endif + %if isprep && required_stack_alignment > STACK_ALIGNMENT + %xdefine base_reg r5 + %else + %xdefine base_reg r6 + %endif + mov ssd, ssm +%endif + LEA base_reg, %1_8tap_scaled_8bpc_ssse3 +%xdefine base base_reg-%1_8tap_scaled_8bpc_ssse3 +%if ARCH_X86_64 || isprep || required_stack_alignment <= STACK_ALIGNMENT + tzcnt wd, wm +%endif +%if ARCH_X86_32 + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 +%endif + movd m8, dxm + movd m14, mxm + pshufd m8, m8, q0000 + pshufd m14, m14, q0000 +%if isprep && UNIX64 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 +%endif +%if ARCH_X86_64 + mov dyd, dym +%endif +%ifidn %1, put + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %elif ARCH_X86_64 + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %if ARCH_X86_64 + %if required_stack_alignment > STACK_ALIGNMENT + %define dsm [rsp+0x138] + %define rX r1 + %define rXd r1d + %else + %define dsm dsq + %define rX r14 + %define rXd r14d + %endif + %else + %define rX r1 + %endif +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %elif ARCH_X86_64 + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+0x94] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %if ARCH_X86_64 + %define rX r14 + %define rXd r14d + %else + %define rX r3 + %endif +%endif +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m12, [base+pw_8192] + %ifidn %1, put + mova m13, [base+pd_512] + %else + mova m13, [base+pd_32] + %endif +%else + %define m10 [base+pd_0x3ff] + %define m12 [base+pw_8192] + %ifidn %1, put + %define m13 [base+pd_512] + %else + %define m13 [base+pd_32] + %endif +%endif + pxor m9, m9 +%if ARCH_X86_64 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q +%else + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + mov r1, [esp+0x1f4] + lea r0, [ssq*3] + movzx r2, r1b + shr r1, 16 + cmp dword hm, 6 + cmovs r1, r2 + mov [esp+0x1f4], r1 + mov r1, r1m + mov r2, r2m + sub srcq, r0 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define ss3q r0 + %define myd r4 + %define dyd dword dym + %define hd dword hm +%endif + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_ssse3_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %else + %define m11 [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [rsp+0x180], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m2, [srcq+ssq*2] + movhps m0, [srcq+ssq*1] + movhps m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + %endif + movq m1, [srcq+ssq*0] + movq m3, [srcq+ssq*2] + movhps m1, [srcq+ssq*1] + movhps m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %else + pand m7, m8, m11 + pandn m8, m15 + %define m8 m6 + %define m15 m5 + por m15, m7 + mova [rsp+0x190], m15 + %endif + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 1 2 3 + pmulhrsw m1, m12 ; 4 5 6 7 + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mov myd, mym + mov r0, r0m + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif +.w2_loop: + and myd, 0x3ff + %if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m5, m3, m8 + pmaddwd m6, m0, m9 + pmaddwd m7, m2, m10 + pmaddwd m8, m4, m11 + paddd m5, m6 + paddd m7, m8 + %else + mov mym, myd + mov r1, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r1, [r1+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r1*8+0] + cmovnz r3, [base+subpel_filters+r1*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m5, m7, q0000 + pshufd m6, m7, q1111 + pmaddwd m3, m5 + pmaddwd m0, m6 + pshufd m5, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m2, m5 + pmaddwd m4, m7 + paddd m3, m0 + paddd m2, m4 + SWAP m5, m3 + SWAP m7, m2 + %endif + paddd m5, m13 + paddd m5, m7 + psrad m5, 10 + packssdw m5, m5 + packuswb m5, m5 + %if ARCH_X86_64 + pextrw r6d, m5, 0 + mov [dstq], r6w + add dstq, dsq + dec hd + jz .ret + add myd, dyd + %else + pextrw r3d, m5, 0 + mov [dstq], r3w + add dstq, dsm + dec hd + jz .ret + mov myd, mym + add myd, dym + %endif + test myd, ~0x3ff + %if ARCH_X86_32 + SWAP m3, m5 + SWAP m2, m7 + mova m3, [rsp+0x1a0] + mova m0, [rsp+0x1b0] + mova m2, [rsp+0x1c0] + mova m4, [rsp+0x1d0] + %define m14 [esp+0x180] + %define m15 [esp+0x190] + %endif + jz .w2_loop + %if ARCH_X86_32 + mov r3, r3m + %endif + movq m5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps m3, m0, q1032 ; 01 12 + shufps m0, m2, q1032 ; 23 34 + shufps m2, m4, q1032 ; 45 56 + pshufb m5, m14 + pmaddubsw m5, m15 + phaddw m5, m5 + pmulhrsw m5, m12 + palignr m4, m5, m1, 12 + punpcklqdq m1, m4, m4 ; 6 7 6 7 + punpcklwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif + jmp .w2_loop +.w2_skip_line: + movhps m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m3, m0 ; 01 12 + mova m0, m2 ; 23 34 + pshufb m5, m14 + pmaddubsw m5, m15 + phaddw m5, m5 + pmulhrsw m5, m12 ; 6 7 6 7 + palignr m4, m5, m1, 8 ; 4 5 6 7 + pshufd m5, m4, q0321 ; 5 6 7 _ + mova m1, m4 + punpcklwd m2, m4, m5 ; 45 56 + punpckhwd m4, m5 ; 67 __ + %if ARCH_X86_32 + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif + jmp .w2_loop +%endif +INIT_XMM ssse3 +.w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%else + %define m11 [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd rX, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + movifprep r3, r3m + SWAP m4, m7 + %define m15 m1 +%endif + mova m5, [base+bdct_lb_dw] + movq m6, [base+subpel_s_shuf2] + psrld m14, 10 + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 + punpcklqdq m6, m6 + pshufb m14, m5 + paddb m14, m6 +%if ARCH_X86_64 + pcmpeqd m0, m9 + pand m11, m0 +%else + mova [esp+0x180], m14 + SWAP m7, m4 + pxor m3, m3 + pcmpeqd m0, m3 + pand m2, m11, m0 + %define m11 m2 +%endif + pandn m0, m15 +%if ARCH_X86_64 + SWAP m15, m0 +%else + %define m15 m0 +%endif + por m15, m11 +%if ARCH_X86_64 + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m2, [srcq+ssq*0] + movu m4, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m5, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m7, m14 + pshufb m9, m14 + pshufb m8, m14 + pshufb m10, m14 + pshufb m2, m14 + pshufb m4, m14 + pshufb m3, m14 + pshufb m5, m14 + pmaddubsw m7, m15 + pmaddubsw m9, m15 + pmaddubsw m8, m15 + pmaddubsw m10, m15 + pmaddubsw m2, m15 + pmaddubsw m4, m15 + pmaddubsw m3, m15 + pmaddubsw m5, m15 + phaddw m7, m9 + phaddw m8, m10 + phaddw m9, m2, m4 + phaddw m3, m5 + pmulhrsw m7, m12 ; 0 1 + pmulhrsw m8, m12 ; 2 3 + pmulhrsw m9, m12 ; 4 5 + pmulhrsw m3, m12 ; 6 7 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + psrldq m11, m3, 8 ; 7 _ + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + punpcklwd m3, m11 ; 67 + mova [rsp+0x00], m7 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 +%else + mova [esp+0x190], m15 + lea ss3q, [ssq*3] + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + movu m7, [srcq+ssq*2] + movu m6, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m2, m14 + pshufb m3, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + phaddw m2, m3 + phaddw m7, m6 + movu m1, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m6, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m1, m14 + pshufb m5, m14 + pshufb m3, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m5, m15 + pmaddubsw m3, m15 + pmaddubsw m6, m15 + phaddw m1, m5 + phaddw m3, m6 + pmulhrsw m2, m12 + pmulhrsw m7, m12 + pmulhrsw m1, m12 + pmulhrsw m3, m12 + shufps m4, m2, m7, q1032 ; 1 2 + shufps m5, m7, m1, q1032 ; 3 4 + shufps m6, m1, m3, q1032 ; 5 6 + psrldq m0, m3, 8 ; 7 _ + mova [esp+0x1a0], m0 + %define m11 [esp+0x1a0] + punpcklwd m0, m2, m4 ; 01 + punpckhwd m2, m4 ; 12 + punpcklwd m4, m7, m5 ; 23 + punpckhwd m7, m5 ; 34 + punpcklwd m5, m1, m6 ; 45 + punpckhwd m1, m6 ; 56 + punpcklwd m3, [esp+0x1a0] ; 67 + mov myd, mym + mov r0, r0m + mova [esp+0x1b0], m0 ; 01 + mova [esp+0x1c0], m4 ; 23 + mova [esp+0x1d0], m5 ; 45 + mova [esp+0x1e0], m3 ; 67 + mova [rsp+0x00], m2 ; 12 + mova [rsp+0x10], m7 ; 34 + mova [rsp+0x20], m1 ; 56 + SWAP m1, m4 + SWAP m2, m5 +%endif +.w4_loop: + and myd, 0x3ff +%if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m10, r6q + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m10 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 +%else + mov mym, myd + mov r5, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m0, m4 + pmaddwd m1, m5 + pmaddwd m2, m6 + pmaddwd m3, m7 + paddd m0, m1 + paddd m2, m3 + paddd m0, m13 + paddd m0, m2 + SWAP m4, m0 +%endif + psrad m4, rndshift + packssdw m4, m4 +%ifidn %1, put + packuswb m4, m4 + movd [dstq], m4 + add dstq, dsmp +%else + movq [tmpq], m4 + add tmpq, 8 +%endif + dec hd + jz .ret +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .w4_loop +%else + SWAP m0, m4 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + jnz .w4_next_line + mova m0, [esp+0x1b0] + mova m1, [esp+0x1c0] + mova m2, [esp+0x1d0] + mova m3, [esp+0x1e0] + jmp .w4_loop +.w4_next_line: + %define m14 [esp+0x180] + %define m15 [esp+0x190] +%endif + movu m4, [srcq] + test myd, 0x400 + jz .w4_skip_line +%if ARCH_X86_64 + mova m0, [rsp+0x00] + mova [rsp+0x00], m1 + mova m1, [rsp+0x10] + mova [rsp+0x10], m2 + mova m2, [rsp+0x20] + mova [rsp+0x20], m3 +%else + mova m5, [esp+0x1c0] + mova m0, [rsp+0x000] + mova [rsp+0x00], m5 + mova [esp+0x1b0], m0 + mova m6, [esp+0x1d0] + mova m1, [rsp+0x010] + mova [rsp+0x10], m6 + mova [esp+0x1c0], m1 + mova m7, [esp+0x1e0] + mova m2, [rsp+0x020] + mova [rsp+0x20], m7 + mova [esp+0x1d0], m2 +%endif + pshufb m4, m14 + pmaddubsw m4, m15 + phaddw m4, m4 + pmulhrsw m4, m12 + punpcklwd m3, m11, m4 +%if ARCH_X86_32 + mova [esp+0x1e0], m3 +%endif + mova m11, m4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: +%if ARCH_X86_32 + mova m0, [esp+0x1c0] + mova m1, [esp+0x1d0] + mova m2, [esp+0x1e0] +%endif + movu m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m6, [rsp+0x10] + mova m7, [rsp+0x20] + pshufb m4, m14 + pshufb m5, m14 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m4, m5 + pmulhrsw m4, m12 + punpcklwd m5, m11, m4 + mova [rsp+0x00], m6 + mova [rsp+0x10], m7 + mova [rsp+0x20], m5 +%if ARCH_X86_64 + psrldq m11, m4, 8 + mova m0, m1 + mova m1, m2 + mova m2, m3 + punpcklwd m3, m4, m11 +%else + psrldq m6, m4, 8 + punpcklwd m3, m4, m6 + mova [esp+0x1a0], m6 + mova [esp+0x1b0], m0 + mova [esp+0x1c0], m1 + mova [esp+0x1d0], m2 + mova [esp+0x1e0], m3 +%endif + jmp .w4_loop +INIT_XMM ssse3 +.w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.w_start: +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq ssm + %endif + mov r4, [esp+0x1f0] + shr r4, 16 + movd m15, r4 + mov r0, r0m + mov myd, mym +%endif + sub srcq, 3 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + mov r5, hm + mov [esp+0x094], myd + mov [esp+0x134], r5 +%endif + jmp .hloop +.hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [esp+0x130], 8*(isprep+1) + mov myd, [esp+0x094] + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + pxor m9, m9 + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov mym, myd + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.hloop: +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m11, m4 + pand m8, m11, m6 + pand m15, m11, m14 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m11, m5 + mova [rsp+0x10], m7 + mova [rsp+0x20], m8 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10, 7, 8, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10, 7, 8, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10, 7, 8, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 9, 10, 7, 8, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m9, [rsp+0x80] + mov myd, mym + mov dyd, dym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 + SWAP m14, m8 +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m5, m11, q0000 + pshufd m7, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m4, m5, m0 + pmaddwd m5, m5, m1 + pmaddwd m6, m7, m2 + pmaddwd m7, m7, m3 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 + pmaddwd m8, [rsp+0x70], m11 + pmaddwd m9, [rsp+0x80], m11 + paddd m4, m6 + paddd m5, m7 + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x140, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x160 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x180 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 6-7 + mova m5, [esp+0x180] + mova m6, [esp+0x190] + mova m7, [esp+0x1a0] + mova m0, [esp+0x1b0] + mov myd, mym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x180], m4 + mova [esp+0x190], m5 + mova [esp+0x1a0], m6 + mova [esp+0x1b0], m7 + mova m1, [esp+0x140] + mova m2, [esp+0x150] + mova m3, [esp+0x160] + mova m4, [esp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova [esp+0x160], m2 + mova [esp+0x170], m3 +.vloop: + mov r0, r0m + mov r5, [esp+0x1f4] + and myd, 0x3ff + mov mym, myd + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [esp+0x180], m6 + pmaddwd m3, [esp+0x190], m6 + pmaddwd m4, [esp+0x1a0], m7 + pmaddwd m5, [esp+0x1b0], m7 + paddd m0, m2 + paddd m1, m3 + paddd m0, m13 + paddd m1, m13 + paddd m4, m0 + paddd m5, m1 +%endif + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+0x140], myd + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + jz .skip_line + mova m14, [base+unpckw] + movq m6, [srcq+r10] + movq m7, [srcq+r11] + movhps m6, [srcq+r13] + movhps m7, [srcq+ rX] + movq m4, [srcq+ r4] + movq m5, [srcq+ r6] + movhps m4, [srcq+ r7] + movhps m5, [srcq+ r9] + add srcq, ssq + mov myd, [rsp+0x140] + mov dyd, dym + pshufd m9, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m9 ; 3a 2a + pshufb m3, m9 ; 3b 2b + pmaddubsw m6, [rsp+0x30] + pmaddubsw m7, [rsp+0x40] + pmaddubsw m4, [rsp+0x10] + pmaddubsw m5, [rsp+0x20] + phaddw m6, m7 + phaddw m4, m5 + phaddw m4, m6 + pmulhrsw m4, m12 + pshufb m5, [rsp+0x50], m14 ; 4a 5a + pshufb m6, [rsp+0x60], m14 ; 4b 5b + pshufb m7, [rsp+0x70], m9 ; 7a 6a + pshufb m8, [rsp+0x80], m9 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + punpckhwd m5, m7 ; 56a + punpckhwd m6, m8 ; 56b + punpcklwd m7, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m8, m4 ; 78b + mova [rsp+0x50], m5 + mova [rsp+0x60], m6 + mova [rsp+0x70], m7 + mova [rsp+0x80], m8 + jmp .vloop +.skip_line: + mova m0, [rsp+0x10] + mova m1, [rsp+0x20] + mova m14, [rsp+0x30] + mova m15, [rsp+0x40] + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 10, 11, 0, 1, 14, 15 + mov myd, [rsp+0x140] + mov dyd, dym + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [rsp+0x50] ; 23a + mova m3, [rsp+0x60] ; 23b + mova m5, [rsp+0x70] ; 45a + mova m6, [rsp+0x80] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [rsp+0x50], m5 + mova [rsp+0x60], m6 + mova [rsp+0x70], m7 + mova [rsp+0x80], m4 +%else + mov r0m, r0 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + mov mym, myd + jnz .next_line + mova m0, [esp+0x140] + mova m1, [esp+0x150] + mova m2, [esp+0x160] + mova m3, [esp+0x170] + jmp .vloop +.next_line: + test myd, 0x400 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + jz .skip_line + mova m6, [base+unpckw] + mova m0, [esp+0x140] + mova m1, [esp+0x150] + mova m7, [esp+0x180] + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + pshufb m0, m6 ; 0a 1a + pshufb m1, m6 ; 0b 1b + pshufb m7, m6 ; 4a 5a + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + movq m3, [srcq+r0] + movq m2, [srcq+rX] + movhps m3, [srcq+r4] + movhps m2, [srcq+r5] + add srcq, ssq + pmaddubsw m4, [esp+0x20] + pmaddubsw m5, [esp+0x30] + pmaddubsw m3, [esp+0x40] + pmaddubsw m2, [esp+0x50] + phaddw m4, m5 + phaddw m3, m2 + mova m5, [esp+0x190] + mova m2, [esp+0x160] + phaddw m4, m3 + mova m3, [esp+0x170] + pmulhrsw m4, m12 ; 8a 8b + mov myd, mym + pshufb m5, m6 ; 4b 5b + pshufd m6, m6, q1032 + pshufb m2, m6 ; 3a 2a + pshufb m3, m6 ; 3b 2b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova m0, [esp+0x1a0] + mova m1, [esp+0x1b0] + punpcklwd m2, m7 ; 34a + punpcklwd m3, m5 ; 34b + mova [esp+0x160], m2 + mova [esp+0x170], m3 + pshufb m0, m6 ; 7a 6a + pshufb m1, m6 ; 7b 6b + punpckhwd m7, m0 ; 56a + punpckhwd m5, m1 ; 56b + punpcklwd m0, m4 + punpckhqdq m4, m4 + punpcklwd m1, m4 + mova [esp+0x180], m7 + mova [esp+0x190], m5 + mova [esp+0x1a0], m0 + mova [esp+0x1b0], m1 + mova m0, [esp+0x140] + mova m1, [esp+0x150] + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 0x20, 0x1c0, 0 + mov myd, mym + mova m0, [esp+0x160] + mova m1, [esp+0x170] + mova m2, [esp+0x180] + mova m3, [esp+0x190] + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova m4, [esp+0x1a0] + mova m5, [esp+0x1b0] + mova [esp+0x160], m2 + mova [esp+0x170], m3 + mova m6, [esp+0x1c0] + mova m7, [esp+0x1d0] + mova [esp+0x180], m4 + mova [esp+0x190], m5 + punpcklwd m4, m6, m7 + punpckhwd m6, m7 + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m6 +%endif + jmp .vloop +INIT_XMM ssse3 +.dy1: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy1_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy1_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + movzx r5, byte [esp+0x1f0] + dec srcd + movd m15, r5 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %else + %define m11 [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [esp+0x00], m14 + %define m14 [esp+0x00] + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m2, [srcq+ssq*2] + movhps m0, [srcq+ssq*1] + movhps m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movq m10, r4 + %else + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + %define m10 m4 + movd m10, r4 + movd m3, r3 + mov r3, r3m + punpckldq m10, m3 + %endif + movq m1, [srcq+ssq*0] + movq m3, [srcq+ssq*2] + movhps m1, [srcq+ssq*1] + add srcq, ss3q + punpcklbw m10, m10 + psraw m10, 8 + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + %else + pand m7, m11, m8 + %define m11 m7 + %endif + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %if ARCH_X86_64 + pshufd m8, m10, q0000 + pshufd m9, m10, q1111 + pshufd m11, m10, q3333 + pshufd m10, m10, q2222 + %else + mova [esp+0x10], m15 + %define m15 [esp+0x10] + mov r0, r0m + pshufd m5, m4, q0000 + pshufd m6, m4, q1111 + pshufd m7, m4, q2222 + pshufd m4, m4, q3333 + %define m8 [esp+0x20] + %define m9 [esp+0x30] + %define m10 [esp+0x40] + %define m11 [esp+0x50] + mova m8, m5 + mova m9, m6 + mova m10, m7 + mova m11, m4 + %endif + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + palignr m2, m1, m0, 4 + pshufd m4, m1, q2121 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + punpcklwd m2, m1, m4 ; 45 56 +.dy1_w2_loop: + movq m1, [srcq+ssq*0] + movhps m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m3, m8 + pmaddwd m6, m0, m9 + pmaddwd m7, m2, m10 + mova m3, m0 + mova m0, m2 + paddd m5, m13 + paddd m6, m7 + pshufb m1, m14 + pmaddubsw m1, m15 + phaddw m1, m1 + pmulhrsw m1, m12 + palignr m7, m1, m4, 12 + punpcklwd m2, m7, m1 ; 67 78 + pmaddwd m7, m2, m11 + mova m4, m1 + paddd m5, m6 + paddd m5, m7 + psrad m5, rndshift + packssdw m5, m5 + packuswb m5, m5 + movd r4d, m5 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy1_w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] +%else + movd r1, m15 + movd r3, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + %define m15 m5 + SWAP m4, m7 + movd m15, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m4, [base+subpel_filters+r5*8+2] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif +%endif + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 + movq m6, [base+subpel_s_shuf2] +%if ARCH_X86_64 + pcmpeqd m8, m9 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpcklqdq m6, m6 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m7, [srcq+ssq*2] + add srcq, ss3q + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + paddb m14, m6 + movq m10, r4q + punpcklbw m10, m10 + psraw m10, 8 + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb m5, m14 + pshufb m7, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + pmaddubsw m7, m15 + phaddw m0, m1 + phaddw m2, m3 + phaddw m4, m5 + phaddw m6, m7, m7 + pmulhrsw m0, m12 ; 0 1 + pmulhrsw m2, m12 ; 2 3 + pmulhrsw m4, m12 ; 4 5 + pmulhrsw m6, m12 ; 6 _ + shufps m1, m0, m2, q1032 ; 1 2 + shufps m3, m2, m4, q1032 ; 3 4 + shufps m5, m4, m6, q1032 ; 5 6 + punpcklwd m7, m0, m1 ; 01 + punpckhwd m0, m1 ; 12 + punpcklwd m8, m2, m3 ; 23 + punpckhwd m2, m3 ; 34 + punpcklwd m9, m4, m5 ; 45 + punpckhwd m4, m5 ; 56 +%else + pxor m3, m3 + pcmpeqd m8, m3 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + add srcq, ss3q + punpcklqdq m6, m6 + SWAP m4, m7 + pand m7, m11, m8 + pandn m8, m15 + SWAP m5, m0 + por m15, m7 + paddb m14, m6 + movu m0, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m0, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + mova [esp+0x00], m14 + mova [esp+0x10], m15 + pmaddubsw m0, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + phaddw m1, m2 + movu m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + mov r0, r0m + phaddw m3, m0 + pshufb m2, m14 + pmaddubsw m2, m15 + %define m14 [esp+0x00] + %define m15 [esp+0x10] + phaddw m7, m6 + phaddw m2, m2 + movd m6, r4 + movd m0, r5 + punpckldq m6, m0 + punpcklbw m6, m6 + psraw m6, 8 + mova [esp+0x20], m6 + pmulhrsw m1, m12 ; 0 1 + pmulhrsw m3, m12 ; 2 3 + pmulhrsw m7, m12 ; 4 5 + pmulhrsw m2, m12 ; 6 _ + shufps m0, m1, m3, q1032 ; 1 2 + shufps m4, m3, m7, q1032 ; 3 4 + shufps m5, m7, m2, q1032 ; 5 6 + punpcklwd m6, m1, m0 ; 01 + punpckhwd m1, m0 ; 12 + mova [esp+0x30], m1 + punpcklwd m1, m3, m4 ; 23 + punpckhwd m3, m4 ; 34 + mova [esp+0x40], m3 + punpcklwd m3, m7, m5 ; 45 + punpckhwd m7, m5 ; 56 + mova [esp+0x50], m7 + mova [esp+0x60], m2 + mova m0, [esp+0x20] + %xdefine m8 m1 + %xdefine m9 m3 + %xdefine m10 m0 + SWAP m7, m6 + SWAP m1, m4 + SWAP m3, m2 +%endif + pshufd m1, m10, q0000 + pshufd m3, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_64 + mova [rsp+0x00], m8 + mova [rsp+0x10], m2 + mova [rsp+0x20], m9 + mova [rsp+0x30], m4 +%else + mova [esp+0x70], m8 + mova [esp+0x80], m9 + mova [esp+0x90], m1 + mova [esp+0xa0], m3 + mova [esp+0xb0], m5 + mova [esp+0xc0], m10 + %ifidn %1, put + mov dsd, dsm + %endif + %define m11 m6 +%endif +.dy1_w4_loop: +%if ARCH_X86_64 + movu m11, [srcq+ssq*0] + pmaddwd m7, m1 + pmaddwd m8, m3 + pmaddwd m0, m1 + pmaddwd m2, m3 + pmaddwd m9, m5 + pmaddwd m4, m5 + paddd m7, m8 + paddd m0, m2 + movu m8, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m11, m14 + pmaddubsw m11, m15 + paddd m7, m13 + paddd m0, m13 + paddd m7, m9 + paddd m0, m4 + pshufb m8, m14 + pmaddubsw m8, m15 + phaddw m11, m8 + mova m8, [rsp+0x20] + pmulhrsw m11, m12 + punpcklwd m9, m6, m11 ; 67 + psrldq m6, m11, 8 + punpcklwd m4, m11, m6 ; 78 + pmaddwd m2, m9, m10 + pmaddwd m11, m4, m10 + paddd m7, m2 + mova m2, [rsp+0x30] + paddd m0, m11 +%else + SWAP m7, m6 + SWAP m1, m4 + SWAP m3, m2 + movu m5, [srcq+ssq*0] + mova m0, [esp+0x30] + mova m2, [esp+0x40] + mova m4, [esp+0x50] + pmaddwd m6, [esp+0x90] + pmaddwd m1, [esp+0xa0] + pmaddwd m0, [esp+0x90] + pmaddwd m2, [esp+0xa0] + pmaddwd m3, [esp+0xb0] + pmaddwd m4, [esp+0xb0] + paddd m6, m1 + paddd m0, m2 + movu m7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m5, m14 + pmaddubsw m5, m15 + paddd m6, m13 + paddd m0, m13 + paddd m6, m3 + paddd m0, m4 + pshufb m7, m14 + pmaddubsw m7, m15 + phaddw m5, m7 + mova m7, [rsp+0x80] + pmulhrsw m5, m12 + punpcklwd m3, [esp+0x60], m5 ; 67 + psrldq m1, m5, 8 + punpcklwd m4, m5, m1 ; 78 + pmaddwd m2, m3, [esp+0xc0] + pmaddwd m5, m4, [esp+0xc0] + mova [esp+0x60], m1 + paddd m6, m2 + mova m2, [esp+0x50] + paddd m0, m5 + SWAP m7, m6 +%endif + psrad m7, rndshift + psrad m0, rndshift + packssdw m7, m0 +%if ARCH_X86_64 + mova m0, [rsp+0x10] +%else + mova m0, [esp+0x40] +%define m11 m5 +%endif +%ifidn %1, put + packuswb m7, m7 + psrldq m11, m7, 4 + movd [dstq+dsq*0], m7 + movd [dstq+dsq*1], m11 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m7 + add tmpq, 16 +%endif + sub hd, 2 + jz .ret +%if ARCH_X86_64 + mova m7, [rsp+0x00] + mova [rsp+0x00], m8 + mova [rsp+0x10], m2 + mova [rsp+0x20], m9 + mova [rsp+0x30], m4 +%else + mova m7, [esp+0x70] ; 01 + mova m1, [esp+0x80] ; 23 + mova m2, [esp+0x50] ; 34 + mova [esp+0x30], m0 + mova [esp+0x70], m1 + mova [esp+0x40], m2 + mova [esp+0x80], m3 + mova [esp+0x50], m4 +%endif + jmp .dy1_w4_loop +INIT_XMM ssse3 +.dy1_w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define m8 m0 + %define m9 m1 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + sub srcq, 3 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q + punpcklbw m3, m3 + psraw m3, 8 +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + punpcklbw m5, m5 + psraw m5, 8 + SWAP m3, m5 +%endif + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [rsp+0x140], m0 + mova [rsp+0x150], m1 + mova [rsp+0x160], m2 + mova [rsp+0x170], m3 +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + SWAP m5, m3 + mov r5, hm + mov [esp+0x134], r5 +%endif + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [rsp+0x130], 8*(isprep+1) + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%else + %define m10 [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy1_hloop: + pxor m9, m9 +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m8, m11, m4 + pand m9, m11, m6 + pand m15, m11, m7 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m7, m2 + pandn m5, m3 + por m8, m4 + por m9, m6 + por m15, m7 + por m11, m5 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 10, 8, 9, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 7, 10, 8, 9, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m15, [rsp+0x80] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + SWAP m14, m8 + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m15; 23a + punpckhwd m3, m15 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 + mova m14, [base+unpckw] +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x60, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x180 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1c0 ; 6-7 + mova m5, [esp+0x1a0] + mova m6, [esp+0x1b0] + mova m7, [esp+0x1c0] + mova m0, [esp+0x1d0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 + mova [esp+0x1d0], m7 + mova m1, [esp+0x060] + mova m2, [esp+0x070] + mova m3, [esp+0x180] + mova m4, [esp+0x190] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x060], m0 + mova [esp+0x070], m1 + mova [esp+0x180], m2 + mova [esp+0x190], m3 + %define m8 [esp+0x140] + %define m9 [esp+0x150] + %define m10 [esp+0x160] + %define m11 [esp+0x170] +%endif +.dy1_vloop: +%if ARCH_X86_32 + mov r0, r0m +%endif + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m9 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 +%else + pmaddwd m6, [rsp+0x1a0], m10 + pmaddwd m7, [rsp+0x1b0], m10 +%endif + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x70], m11 + pmaddwd m7, [rsp+0x80], m11 +%else + pmaddwd m6, [rsp+0x1c0], m11 + pmaddwd m7, [rsp+0x1d0], m11 +%endif + paddd m4, m6 + paddd m5, m7 + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif +%if ARCH_X86_32 + mov r0m, r0 +%endif + dec hd + jz .dy1_hloop_prep +%if ARCH_X86_64 + movq m4, [srcq+ r4] + movq m5, [srcq+ r6] + movhps m4, [srcq+ r7] + movhps m5, [srcq+ r9] + movq m6, [srcq+r10] + movq m7, [srcq+r11] + movhps m6, [srcq+r13] + movhps m7, [srcq+ rX] + add srcq, ssq + pshufd m15, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m15 ; 3a 2a + pshufb m3, m15 ; 3b 2b + pmaddubsw m4, [rsp+0x10] + pmaddubsw m5, [rsp+0x20] + pmaddubsw m6, [rsp+0x30] + pmaddubsw m7, [rsp+0x40] + phaddw m4, m5 + phaddw m6, m7 + phaddw m4, m6 + pmulhrsw m4, m12 + pshufb m5, [rsp+0x70], m15 ; 7a 6a + pshufb m7, [rsp+0x80], m15 ; 7b 6b + pshufb m6, [rsp+0x50], m14 ; 4a 5a + pshufb m15, [rsp+0x60], m14 ; 4b 5b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m6 ; 34a + punpcklwd m3, m15 ; 34b + punpckhwd m6, m5 ; 56a + punpckhwd m15, m7 ; 56b + punpcklwd m5, m4 ; 78a + psrldq m4, 8 + punpcklwd m7, m4 ; 78b + mova [rsp+0x50], m6 + mova [rsp+0x60], m15 + mova [rsp+0x70], m5 + mova [rsp+0x80], m7 +%else + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova m6, [base+unpckw] + mova m0, [esp+0x060] + mova m1, [esp+0x070] + mova m7, [esp+0x1a0] + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + pshufb m0, m6 ; 0a 1a + pshufb m1, m6 ; 0b 1b + pshufb m7, m6 ; 4a 5a + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + movq m3, [srcq+r0] + movq m2, [srcq+rX] + movhps m3, [srcq+r4] + movhps m2, [srcq+r5] + add srcq, ssq + pmaddubsw m4, [esp+0x20] + pmaddubsw m5, [esp+0x30] + pmaddubsw m3, [esp+0x40] + pmaddubsw m2, [esp+0x50] + phaddw m4, m5 + phaddw m3, m2 + mova m5, [esp+0x1b0] + mova m2, [esp+0x180] + phaddw m4, m3 + mova m3, [esp+0x190] + pmulhrsw m4, m12 ; 8a 8b + pshufb m5, m6 ; 4b 5b + pshufd m6, m6, q1032 + pshufb m2, m6 ; 3a 2a + pshufb m3, m6 ; 3b 2b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + mova [esp+0x60], m0 + mova [esp+0x70], m1 + mova m0, [esp+0x1c0] + mova m1, [esp+0x1d0] + punpcklwd m2, m7 ; 34a + punpcklwd m3, m5 ; 34b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + pshufb m0, m6 ; 7a 6a + pshufb m1, m6 ; 7b 6b + punpckhwd m7, m0 ; 56a + punpckhwd m5, m1 ; 56b + punpcklwd m0, m4 + punpckhqdq m4, m4 + punpcklwd m1, m4 + mova [esp+0x1a0], m7 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m0 + mova [esp+0x1d0], m1 + mova m0, [esp+0x60] + mova m1, [esp+0x70] +%endif + jmp .dy1_vloop +INIT_XMM ssse3 +.dy2: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy2_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + movzx r5, byte [esp+0x1f0] + dec srcd + movd m15, r5 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [esp+0x00], m14 + %define m14 [esp+0x00] + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + movhps m0, [srcq+ssq*2] + movhps m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movq m10, r4q + %else + mov myd, mym + mov r3, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r3, r3m + %define m10 m4 + movd m10, r4 + movd m3, r5 + punpckldq m10, m3 + %endif + movq m3, [srcq+ssq*0] + movhps m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m10, m10 + psraw m10, 8 + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + %else + pand m7, m11, m8 + %define m11 m7 + %endif + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %if ARCH_X86_64 + pshufd m8, m10, q0000 + pshufd m9, m10, q1111 + pshufd m11, m10, q3333 + pshufd m10, m10, q2222 + %else + mova [esp+0x10], m15 + %define m15 [esp+0x10] + mov r5, r0m + %define dstq r5 + mov dsd, dsm + pshufd m5, m4, q0000 + pshufd m6, m4, q1111 + pshufd m7, m4, q2222 + pshufd m4, m4, q3333 + %define m8 [esp+0x20] + %define m9 [esp+0x30] + %define m10 [esp+0x40] + %define m11 [esp+0x50] + mova m8, m5 + mova m9, m6 + mova m10, m7 + mova m11, m4 + %endif + pshufb m0, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + pslldq m2, m3, 8 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 2 _ 4 + pmulhrsw m1, m12 ; 1 3 _ 5 + pshufd m2, m0, q3110 ; 0 2 2 4 + pshufd m1, m1, q3110 ; 1 3 3 5 + punpcklwd m3, m2, m1 ; 01 23 + punpckhwd m2, m1 ; 23 45 +.dy2_w2_loop: + movq m6, [srcq+ssq*0] + movq m7, [srcq+ssq*1] + movhps m6, [srcq+ssq*2] + movhps m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd m4, m3, m8 + pmaddwd m5, m2, m9 + pshufb m6, m14 + pshufb m7, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + phaddw m6, m7 + pmulhrsw m6, m12 + psrldq m7, m6, 8 + palignr m6, m0, 8 + palignr m7, m1, 8 + mova m0, m6 + mova m1, m7 + pshufd m6, m6, q3221 + pshufd m7, m7, q3221 + punpcklwd m3, m6, m7 ; 45 67 + punpckhwd m2, m6, m7 ; 67 89 + pmaddwd m6, m3, m10 + pmaddwd m7, m2, m11 + paddd m4, m5 + paddd m4, m13 + paddd m6, m7 + paddd m4, m6 + psrad m4, rndshift + packssdw m4, m4 + packuswb m4, m4 + movd r4d, m4 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy2_w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %define dstq r0 + %if isprep + %define ssq r3 + %endif + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] + movq m6, [base+subpel_s_shuf2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] +%else + movd r1, m15 + movd r3, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + %define m15 m5 + SWAP m4, m7 + movd m15, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m4, [base+subpel_filters+r5*8+2] + movq m6, [base+subpel_s_shuf2] + mov myd, mym + mov r3, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif +%endif + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 +%if ARCH_X86_64 + pcmpeqd m8, m9 + psrld m14, 10 + movu m0, [srcq+ssq*0] + movu m2, [srcq+ssq*2] + movu m1, [srcq+ssq*1] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpcklqdq m6, m6 + pshufb m14, [base+bdct_lb_dw] + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + paddb m14, m6 + movq m11, r4q + punpcklbw m11, m11 + psraw m11, 8 + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb m5, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m0, m2 + phaddw m1, m3 + phaddw m4, m5 + pmulhrsw m0, m12 ; 0 2 + pmulhrsw m1, m12 ; 1 3 + pmulhrsw m4, m12 ; 4 5 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 +%else + pxor m3, m3 + pcmpeqd m8, m3 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ssq*1] + add srcq, ss3q + punpcklqdq m6, m6 + SWAP m4, m7 + pand m7, m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m7 + paddb m14, m6 + movu m0, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m0, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + mova [esp+0x00], m14 + mova [esp+0x10], m15 + pmaddubsw m0, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + %define m14 [esp+0x00] + %define m15 [esp+0x10] + phaddw m1, m2 + phaddw m3, m0 + phaddw m7, m6 + %ifidn %1, put + mov dsd, dsm + %define dstq r5 + %else + %define tmpq r5 + %endif + movd m6, r4 + movd m0, r5 + punpckldq m6, m0 + punpcklbw m6, m6 + psraw m6, 8 + mov r5, r0m + pmulhrsw m1, m12 ; 0 2 + pmulhrsw m3, m12 ; 1 3 + pmulhrsw m7, m12 ; 4 5 + SWAP m0, m1, m3 + SWAP m4, m7 + pshufd m2, m6, q0000 + pshufd m3, m6, q1111 + pshufd m7, m6, q2222 + pshufd m6, m6, q3333 + mova [esp+0x30], m2 + mova [esp+0x40], m3 + mova [esp+0x50], m7 + mova [esp+0x60], m6 + %define m8 [esp+0x30] + %define m9 [esp+0x40] + %define m10 [esp+0x50] + %define m11 [esp+0x60] +%endif + psrldq m5, m4, 8 ; 5 _ + punpckhwd m2, m0, m1 ; 23 + punpcklwd m0, m1 ; 01 + punpcklwd m4, m5 ; 45 +.dy2_w4_loop: + pmaddwd m0, m8 ; a0 + pmaddwd m5, m2, m8 ; b0 + pmaddwd m2, m9 ; a1 + pmaddwd m7, m4, m9 ; b1 + pmaddwd m3, m4, m10 ; a2 + paddd m0, m13 + paddd m5, m13 + paddd m0, m2 + paddd m5, m7 + paddd m0, m3 + movu m6, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m6, m14 + pshufb m7, m14 + pshufb m3, m14 + pshufb m1, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + pmaddubsw m3, m15 + pmaddubsw m1, m15 + phaddw m6, m7 + phaddw m3, m1 + pmulhrsw m6, m12 ; 6 7 + pmulhrsw m3, m12 ; 8 9 + psrldq m7, m6, 8 + psrldq m1, m3, 8 + punpcklwd m6, m7 ; 67 + punpcklwd m3, m1 ; 89 + mova m2, m6 + pmaddwd m1, m6, m10 ; b2 + pmaddwd m6, m11 ; a3 + pmaddwd m7, m3, m11 ; b3 + paddd m5, m1 + paddd m0, m6 + paddd m5, m7 + psrad m0, rndshift + psrad m5, rndshift + packssdw m0, m5 +%ifidn %1, put + packuswb m0, m0 + psrldq m1, m0, 4 + movd [dstq+dsq*0], m0 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m0 + add tmpq, 16 +%endif + mova m0, m4 + mova m4, m3 + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET +INIT_XMM ssse3 +.dy2_w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %define m9 m1 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define tmpq r0 + %define ssq ssm + %else + %define dstq r0 + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + sub srcq, 3 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q + punpcklbw m3, m3 + psraw m3, 8 +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + punpcklbw m5, m5 + psraw m5, 8 + SWAP m3, m5 +%endif + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [rsp+0x140], m0 + mova [rsp+0x150], m1 + mova [rsp+0x160], m2 + mova [rsp+0x170], m3 +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + SWAP m5, m3 + mov r5, hm + mov [esp+0x134], r5 +%endif + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [rsp+0x130], 8*(isprep+1) + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%else + %define m10 [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy2_hloop: + pxor m9, m9 +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m8, m11, m4 + pand m9, m11, m6 + pand m15, m11, m7 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m7, m2 + pandn m5, m3 + por m8, m4 + por m9, m6 + por m15, m7 + por m11, m5 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 10, 8, 9, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 7, 10, 8, 9, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m15, [rsp+0x80] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + SWAP m14, m8 + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m15; 23a + punpckhwd m3, m15 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x60, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x180 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1c0 ; 6-7 + mova m5, [esp+0x1a0] + mova m6, [esp+0x1b0] + mova m7, [esp+0x1c0] + mova m0, [esp+0x1d0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 + mova [esp+0x1d0], m7 + mova m1, [esp+0x060] + mova m2, [esp+0x070] + mova m3, [esp+0x180] + mova m4, [esp+0x190] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + %define m8 [esp+0x140] + %define m9 [esp+0x150] + %define m10 [esp+0x160] + %define m11 [esp+0x170] +%endif +.dy2_vloop: +%if ARCH_X86_32 + mov r0, r0m +%endif + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m9 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 +%else + pmaddwd m6, [esp+0x1a0], m10 + pmaddwd m7, [esp+0x1b0], m10 +%endif + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x70], m11 + pmaddwd m7, [rsp+0x80], m11 +%else + pmaddwd m6, [esp+0x1c0], m11 + pmaddwd m7, [esp+0x1d0], m11 +%endif + paddd m4, m6 + paddd m5, m7 + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif +%if ARCH_X86_32 + mov r0m, r0 +%endif + dec hd + jz .dy2_hloop_prep +%if ARCH_X86_64 + mova m8, [rsp+0x10] + mova m9, [rsp+0x20] + mova m10, [rsp+0x30] + mova m11, [rsp+0x40] + mova m0, m2 ; 01a + mova m1, m3 ; 01b + MC_8TAP_SCALED_H 2, 6, 3, 4, 5, 7, 14, 15, 8, 9, 10, 11 + mova m3, [rsp+0x50] ; 23a + mova m4, [rsp+0x60] ; 23b + mova m5, [rsp+0x70] ; 45a + mova m7, [rsp+0x80] ; 45b + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m14, m2, m6 ; 67a + punpckhwd m2, m6 ; 67b + mova [rsp+0x50], m5 + mova [rsp+0x60], m7 + mova [rsp+0x70], m14 + mova [rsp+0x80], m2 + mova m2, m3 + mova m3, m4 +%else + MC_8TAP_SCALED_H 0x20, 0 + punpcklwd m6, m0, m4 + punpckhwd m7, m0, m4 + mova m0, [esp+0x180] ; 01a + mova m1, [esp+0x190] ; 01b + mova m2, [rsp+0x1a0] ; 23a + mova m3, [esp+0x1b0] ; 23b + mova m4, [esp+0x1c0] ; 45a + mova m5, [esp+0x1d0] ; 45b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 ; 67a + mova [esp+0x1d0], m7 ; 67b +%endif + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%if ARCH_X86_32 && !isprep && required_stack_alignment > STACK_ALIGNMENT + %define r0m [rstk+stack_offset+ 4] + %define r1m [rstk+stack_offset+ 8] + %define r2m [rstk+stack_offset+12] + %define r3m [rstk+stack_offset+16] +%endif +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_8bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, (5*15 << 16) | 5*15 + jmp mangle(private_prefix %+ _%1_8tap_scaled_8bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 8 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN put +FN put_8tap_scaled, sharp, SHARP, SHARP +FN put_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN put_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN put_8tap_scaled, smooth, SMOOTH, SMOOTH +FN put_8tap_scaled, sharp_regular, SHARP, REGULAR +FN put_8tap_scaled, regular_sharp, REGULAR, SHARP +FN put_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN put_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN put_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 7 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN prep +FN prep_8tap_scaled, sharp, SHARP, SHARP +FN prep_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN prep_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN prep_8tap_scaled, smooth, SMOOTH, SMOOTH +FN prep_8tap_scaled, sharp_regular, SHARP, REGULAR +FN prep_8tap_scaled, regular_sharp, REGULAR, SHARP +FN prep_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN prep_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN prep_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%if ARCH_X86_32 + %macro SAVE_ALPHA_BETA 0 + mov alpham, alphad + mov betam, betad + %endmacro + + %macro SAVE_DELTA_GAMMA 0 + mov deltam, deltad + mov gammam, gammad + %endmacro + + %macro LOAD_ALPHA_BETA_MX 0 + mov mym, myd + mov alphad, alpham + mov betad, betam + mov mxd, mxm + %endmacro + + %macro LOAD_DELTA_GAMMA_MY 0 + mov mxm, mxd + mov deltad, deltam + mov gammad, gammam + mov myd, mym + %endmacro + + %define PIC_reg r2 + %define PIC_base_offset $$ + %define PIC_sym(sym) (PIC_reg+(sym)-PIC_base_offset) +%else + %define SAVE_ALPHA_BETA + %define SAVE_DELTA_GAMMA + %define PIC_sym(sym) sym +%endif + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < required_stack_alignment + %assign copy_args 8*4 + %else + %assign copy_args 0 + %endif +%endif + +%macro RELOC_ARGS 0 + %if copy_args + mov r0, r0m + mov r1, r1m + mov r2, r2m + mov r3, r3m + mov r5, r5m + mov dstm, r0 + mov dsm, r1 + mov srcm, r2 + mov ssm, r3 + mov mxm, r5 + mov r0, r6m + mov mym, r0 + %endif +%endmacro + +%macro BLENDHWDW 2 ; blend high words from dwords, src1, src2 + %if cpuflag(sse4) + pblendw %1, %2, 0xAA + %else + pand %2, m10 + por %1, %2 + %endif +%endmacro + +%macro WARP_V 10 ; dst0, dst1, 0, 2, 4, 6, 1, 3, 5, 7 + %if ARCH_X86_32 + %define m8 m4 + %define m9 m5 + %define m14 m6 + %define m15 m7 + %define m11 m7 + %endif + %if notcpuflag(ssse3) || ARCH_X86_32 + pxor m11, m11 + %endif + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq m2, [filterq+myq *8] ; a + movq m8, [filterq+tmp1q*8] ; e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq m3, [filterq+tmp2q*8] ; b + movq m0, [filterq+tmp1q*8] ; f + punpcklwd m2, m3 + punpcklwd m8, m0 + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq m0, [filterq+myq *8] ; c + movq m9, [filterq+tmp1q*8] ; g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + shr tmp2d, 10 + shr tmp1d, 10 + movq m3, [filterq+tmp2q*8] ; d + movq m1, [filterq+tmp1q*8] ; h + punpcklwd m0, m3 + punpcklwd m9, m1 + punpckldq m1, m2, m0 + punpckhdq m2, m0 + punpcklbw m0, m11, m1 ; a0 a2 b0 b2 c0 c2 d0 d2 << 8 + punpckhbw m3, m11, m1 ; a4 a6 b4 b6 c4 c6 d4 d6 << 8 + punpcklbw m1, m11, m2 ; a1 a3 b1 b3 c1 c3 d1 d3 << 8 + punpckhbw m14, m11, m2 ; a5 a7 b5 b7 c5 c7 d5 d7 << 8 + pmaddwd m0, %3 + pmaddwd m3, %5 + pmaddwd m1, %7 + pmaddwd m14, %9 + paddd m0, m3 + paddd m1, m14 + paddd m0, m1 + mova %1, m0 + %if ARCH_X86_64 + SWAP m3, m14 + %endif + punpckldq m0, m8, m9 + punpckhdq m8, m9 + punpcklbw m1, m11, m0 ; e0 e2 f0 f2 g0 g2 h0 h2 << 8 + punpckhbw m14, m11, m0 ; e4 e6 f4 f6 g4 g6 h4 h6 << 8 + punpcklbw m2, m11, m8 ; e1 e3 f1 f3 g1 g3 h1 h3 << 8 + punpckhbw m15, m11, m8 ; e5 e7 f5 f7 g5 g7 h5 h7 << 8 + pmaddwd m1, %4 + pmaddwd m14, %6 + pmaddwd m2, %8 + pmaddwd m15, %10 + paddd m1, m14 + paddd m2, m15 + paddd m1, m2 + mova %2, m1 + %if ARCH_X86_64 + SWAP m14, m3 + %endif +%endmacro + +%if ARCH_X86_64 + %define counterd r4d +%else + %if copy_args == 0 + %define counterd dword r4m + %else + %define counterd dword [esp+stack_size-4*7] + %endif +%endif + +%macro WARP_AFFINE_8X8T 0 +%if ARCH_X86_64 +cglobal warp_affine_8x8t_8bpc, 6, 14, 16, 0x90, tmp, ts +%else +cglobal warp_affine_8x8t_8bpc, 0, 7, 16, -0x130-copy_args, tmp, ts + %if copy_args + %define tmpm [esp+stack_size-4*1] + %define tsm [esp+stack_size-4*2] + %endif +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).main +.loop: +%if ARCH_X86_32 + %define m12 m4 + %define m13 m5 + %define m14 m6 + %define m15 m7 + mova m12, [esp+0xC0] + mova m13, [esp+0xD0] + mova m14, [esp+0xE0] + mova m15, [esp+0xF0] +%endif +%if cpuflag(ssse3) + psrad m12, 13 + psrad m13, 13 + psrad m14, 13 + psrad m15, 13 + packssdw m12, m13 + packssdw m14, m15 + mova m13, [PIC_sym(pw_8192)] + pmulhrsw m12, m13 ; (x + (1 << 6)) >> 7 + pmulhrsw m14, m13 +%else + %if ARCH_X86_32 + %define m10 m0 + %endif + mova m10, [PIC_sym(pd_16384)] + paddd m12, m10 + paddd m13, m10 + paddd m14, m10 + paddd m15, m10 + psrad m12, 15 + psrad m13, 15 + psrad m14, 15 + psrad m15, 15 + packssdw m12, m13 + packssdw m14, m15 +%endif + mova [tmpq+tsq*0], m12 + mova [tmpq+tsq*2], m14 + dec counterd + jz mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).end +%if ARCH_X86_32 + mov tmpm, tmpd + mov r0, [esp+0x100] + mov r1, [esp+0x104] +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).main2 + lea tmpq, [tmpq+tsq*4] + jmp .loop +%endmacro + +%macro WARP_AFFINE_8X8 0 +%if ARCH_X86_64 +cglobal warp_affine_8x8_8bpc, 6, 14, 16, 0x90, \ + dst, ds, src, ss, abcd, mx, tmp2, alpha, beta, \ + filter, tmp1, delta, my, gamma +%else +cglobal warp_affine_8x8_8bpc, 0, 7, 16, -0x130-copy_args, \ + dst, ds, src, ss, abcd, mx, tmp2, alpha, beta, \ + filter, tmp1, delta, my, gamma + %define alphaq r0 + %define alphad r0 + %define alpham [esp+gprsize+0x100] + %define betaq r1 + %define betad r1 + %define betam [esp+gprsize+0x104] + %define deltaq r0 + %define deltad r0 + %define deltam [esp+gprsize+0x108] + %define gammaq r1 + %define gammad r1 + %define gammam [esp+gprsize+0x10C] + %define filterq r3 + %define tmp1q r4 + %define tmp1d r4 + %define tmp1m [esp+gprsize+0x110] + %define myq r5 + %define myd r5 + %define mym r6m + %if copy_args + %define dstm [esp+stack_size-4*1] + %define dsm [esp+stack_size-4*2] + %define srcm [esp+stack_size-4*3] + %define ssm [esp+stack_size-4*4] + %define mxm [esp+stack_size-4*5] + %define mym [esp+stack_size-4*6] + %endif +%endif + call .main + jmp .start +.loop: +%if ARCH_X86_32 + mov dstm, dstd + mov alphad, [esp+0x100] + mov betad, [esp+0x104] +%endif + call .main2 + lea dstq, [dstq+dsq*2] +.start: +%if notcpuflag(sse4) + %if cpuflag(ssse3) + %define roundval pw_8192 + %else + %define roundval pd_262144 + %endif + %if ARCH_X86_64 + mova m10, [PIC_sym(roundval)] + %else + %define m10 [PIC_sym(roundval)] + %endif +%endif +%if ARCH_X86_32 + %define m12 m5 + %define m13 m6 + mova m12, [esp+0xC0] + mova m13, [esp+0xD0] +%endif +%if cpuflag(sse4) + %if ARCH_X86_32 + %define m11 m4 + pxor m11, m11 + %endif + psrad m12, 18 + psrad m13, 18 + packusdw m12, m13 + pavgw m12, m11 ; (x + (1 << 10)) >> 11 +%else + %if cpuflag(ssse3) + psrad m12, 17 + psrad m13, 17 + packssdw m12, m13 + pmulhrsw m12, m10 + %else + paddd m12, m10 + paddd m13, m10 + psrad m12, 19 + psrad m13, 19 + packssdw m12, m13 + %endif +%endif +%if ARCH_X86_32 + %define m14 m6 + %define m15 m7 + mova m14, [esp+0xE0] + mova m15, [esp+0xF0] +%endif +%if cpuflag(sse4) + psrad m14, 18 + psrad m15, 18 + packusdw m14, m15 + pavgw m14, m11 ; (x + (1 << 10)) >> 11 +%else + %if cpuflag(ssse3) + psrad m14, 17 + psrad m15, 17 + packssdw m14, m15 + pmulhrsw m14, m10 + %else + paddd m14, m10 + paddd m15, m10 + psrad m14, 19 + psrad m15, 19 + packssdw m14, m15 + %endif +%endif + packuswb m12, m14 + movq [dstq+dsq*0], m12 + movhps [dstq+dsq*1], m12 + dec counterd + jg .loop +.end: + RET +ALIGN function_align +.main: +%assign stack_offset stack_offset+gprsize +%if ARCH_X86_32 + %assign stack_size stack_size+4 + %if copy_args + %assign stack_offset stack_offset-4 + %endif + RELOC_ARGS + LEA PIC_reg, $$ + %define PIC_mem [esp+gprsize+0x114] + mov abcdd, abcdm + %if copy_args == 0 + mov ssd, ssm + mov mxd, mxm + %endif + mov PIC_mem, PIC_reg + mov srcd, srcm +%endif + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 + SAVE_DELTA_GAMMA +%if ARCH_X86_32 + mov abcdd, abcdm +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + lea tmp1q, [ssq*3+3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + 3 +%if ARCH_X86_32 + mov srcm, srcd + mov PIC_reg, PIC_mem +%endif + sub betad, tmp2d ; beta -= alpha*3 + lea filterq, [PIC_sym(mc_warp_filter2)] +%if ARCH_X86_64 + mov myd, r6m + %if cpuflag(ssse3) + pxor m11, m11 + %endif +%endif + call .h + psrld m2, m0, 16 + psrld m3, m1, 16 +%if ARCH_X86_32 + %if notcpuflag(ssse3) + mova [esp+gprsize+0x00], m2 + %endif + mova [esp+gprsize+0x10], m3 +%endif + call .h + psrld m4, m0, 16 + psrld m5, m1, 16 +%if ARCH_X86_32 + mova [esp+gprsize+0x20], m4 + mova [esp+gprsize+0x30], m5 +%endif + call .h +%if ARCH_X86_64 + %define blendmask [rsp+gprsize+0x80] +%else + %if notcpuflag(ssse3) + mova m2, [esp+gprsize+0x00] + %endif + mova m3, [esp+gprsize+0x10] + %define blendmask [esp+gprsize+0x120] + %define m10 m7 +%endif + pcmpeqd m10, m10 + pslld m10, 16 + mova blendmask, m10 + BLENDHWDW m2, m0 ; 0 + BLENDHWDW m3, m1 ; 2 + mova [rsp+gprsize+0x00], m2 + mova [rsp+gprsize+0x10], m3 + call .h +%if ARCH_X86_32 + mova m4, [esp+gprsize+0x20] + mova m5, [esp+gprsize+0x30] +%endif + mova m10, blendmask + BLENDHWDW m4, m0 ; 1 + BLENDHWDW m5, m1 ; 3 + mova [rsp+gprsize+0x20], m4 + mova [rsp+gprsize+0x30], m5 + call .h +%if ARCH_X86_32 + %if notcpuflag(ssse3) + mova m2, [esp+gprsize+0x00] + %endif + mova m3, [esp+gprsize+0x10] + %define m10 m5 +%endif + psrld m6, m2, 16 + psrld m7, m3, 16 + mova m10, blendmask + BLENDHWDW m6, m0 ; 2 + BLENDHWDW m7, m1 ; 4 + mova [rsp+gprsize+0x40], m6 + mova [rsp+gprsize+0x50], m7 + call .h +%if ARCH_X86_32 + mova m4, [esp+gprsize+0x20] + mova m5, [esp+gprsize+0x30] +%endif + psrld m2, m4, 16 + psrld m3, m5, 16 + mova m10, blendmask + BLENDHWDW m2, m0 ; 3 + BLENDHWDW m3, m1 ; 5 + mova [rsp+gprsize+0x60], m2 + mova [rsp+gprsize+0x70], m3 + call .h +%if ARCH_X86_32 + mova m6, [esp+gprsize+0x40] + mova m7, [esp+gprsize+0x50] + %define m10 m7 +%endif + psrld m4, m6, 16 + psrld m5, m7, 16 + mova m10, blendmask + BLENDHWDW m4, m0 ; 4 + BLENDHWDW m5, m1 ; 6 +%if ARCH_X86_64 + add myd, 512+(64<<10) + mova m6, m2 + mova m7, m3 +%else + mova [esp+gprsize+0x80], m4 + mova [esp+gprsize+0x90], m5 + add dword mym, 512+(64<<10) +%endif + mov counterd, 4 + SAVE_ALPHA_BETA +.main2: + call .h +%if ARCH_X86_32 + mova m6, [esp+gprsize+0x60] + mova m7, [esp+gprsize+0x70] + %define m10 m5 +%endif + psrld m6, 16 + psrld m7, 16 + mova m10, blendmask + BLENDHWDW m6, m0 ; 5 + BLENDHWDW m7, m1 ; 7 +%if ARCH_X86_64 + WARP_V m12, m13, [rsp+gprsize+0x00], [rsp+gprsize+0x10], \ + m4, m5, \ + [rsp+gprsize+0x20], [rsp+gprsize+0x30], \ + m6, m7 +%else + mova [esp+gprsize+0xA0], m6 + mova [esp+gprsize+0xB0], m7 + LOAD_DELTA_GAMMA_MY + WARP_V [esp+gprsize+0xC0], [esp+gprsize+0xD0], \ + [esp+gprsize+0x00], [esp+gprsize+0x10], \ + [esp+gprsize+0x80], [esp+gprsize+0x90], \ + [esp+gprsize+0x20], [esp+gprsize+0x30], \ + [esp+gprsize+0xA0], [esp+gprsize+0xB0] + LOAD_ALPHA_BETA_MX +%endif + call .h + mova m2, [rsp+gprsize+0x40] + mova m3, [rsp+gprsize+0x50] +%if ARCH_X86_32 + mova m4, [rsp+gprsize+0x80] + mova m5, [rsp+gprsize+0x90] + %define m10 m7 +%endif + mova [rsp+gprsize+0x00], m2 + mova [rsp+gprsize+0x10], m3 + mova [rsp+gprsize+0x40], m4 + mova [rsp+gprsize+0x50], m5 + psrld m4, 16 + psrld m5, 16 + mova m10, blendmask + BLENDHWDW m4, m0 ; 6 + BLENDHWDW m5, m1 ; 8 +%if ARCH_X86_64 + WARP_V m14, m15, [rsp+gprsize+0x20], [rsp+gprsize+0x30], \ + m6, m7, \ + [rsp+gprsize+0x00], [rsp+gprsize+0x10], \ + m4, m5 +%else + mova [esp+gprsize+0x80], m4 + mova [esp+gprsize+0x90], m5 + LOAD_DELTA_GAMMA_MY + WARP_V [esp+gprsize+0xE0], [esp+gprsize+0xF0], \ + [esp+gprsize+0x20], [esp+gprsize+0x30], \ + [esp+gprsize+0xA0], [esp+gprsize+0xB0], \ + [esp+gprsize+0x00], [esp+gprsize+0x10], \ + [esp+gprsize+0x80], [esp+gprsize+0x90] + mov mym, myd + mov dstd, dstm + mov dsd, dsm + mov mxd, mxm +%endif + mova m2, [rsp+gprsize+0x60] + mova m3, [rsp+gprsize+0x70] +%if ARCH_X86_32 + mova m6, [esp+gprsize+0xA0] + mova m7, [esp+gprsize+0xB0] +%endif + mova [rsp+gprsize+0x20], m2 + mova [rsp+gprsize+0x30], m3 + mova [rsp+gprsize+0x60], m6 + mova [rsp+gprsize+0x70], m7 + ret +ALIGN function_align +.h: +%if ARCH_X86_32 + %define m8 m3 + %define m9 m4 + %define m10 m5 + %define m14 m6 + %define m15 m7 +%endif + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] +%if ARCH_X86_32 + %assign stack_offset stack_offset+4 + %assign stack_size stack_size+4 + %define PIC_mem [esp+gprsize*2+0x114] + mov PIC_mem, PIC_reg + mov srcd, srcm +%endif + movu m10, [srcq] +%if ARCH_X86_32 + add srcd, ssm + mov srcm, srcd + mov PIC_reg, PIC_mem +%else + add srcq, ssq +%endif + shr mxd, 10 + shr tmp1d, 10 + movq m1, [filterq+mxq *8] ; 0 X + movq m8, [filterq+tmp1q*8] ; 4 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movhps m1, [filterq+tmp2q*8] ; 0 1 + movhps m8, [filterq+tmp1q*8] ; 4 5 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 + shr tmp1d, 10 +%if cpuflag(ssse3) + movq m14, [filterq+mxq *8] ; 2 X + movq m9, [filterq+tmp1q*8] ; 6 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + movhps m14, [filterq+tmp2q*8] ; 2 3 + movhps m9, [filterq+tmp1q*8] ; 6 7 + pshufb m0, m10, [PIC_sym(warp_8x8_shufA)] + pmaddubsw m0, m1 + pshufb m1, m10, [PIC_sym(warp_8x8_shufB)] + pmaddubsw m1, m8 + pshufb m15, m10, [PIC_sym(warp_8x8_shufC)] + pmaddubsw m15, m14 + pshufb m10, m10, [PIC_sym(warp_8x8_shufD)] + pmaddubsw m10, m9 + phaddw m0, m15 + phaddw m1, m10 +%else + %if ARCH_X86_32 + %define m11 m2 + %endif + pcmpeqw m0, m0 + psrlw m14, m0, 8 + psrlw m15, m10, 8 ; 01 03 05 07 09 11 13 15 + pand m14, m10 ; 00 02 04 06 08 10 12 14 + packuswb m14, m15 ; 00 02 04 06 08 10 12 14 01 03 05 07 09 11 13 15 + psrldq m9, m0, 4 + pshufd m0, m14, q0220 + pand m0, m9 + psrldq m14, 1 ; 02 04 06 08 10 12 14 01 03 05 07 09 11 13 15 __ + pslldq m15, m14, 12 + por m0, m15 ; shufA + psrlw m15, m0, 8 + psraw m11, m1, 8 + psllw m0, 8 + psllw m1, 8 + psrlw m0, 8 + psraw m1, 8 + pmullw m15, m11 + pmullw m0, m1 + paddw m0, m15 ; pmaddubsw m0, m1 + pshufd m15, m14, q0220 + pand m15, m9 + psrldq m14, 1 ; 04 06 08 10 12 14 01 03 05 07 09 11 13 15 __ __ + pslldq m1, m14, 12 + por m15, m1 ; shufC + pshufd m1, m14, q0220 + pand m1, m9 + psrldq m14, 1 ; 06 08 10 12 14 01 03 05 07 09 11 13 15 __ __ __ + pslldq m11, m14, 12 + por m1, m11 ; shufB + pshufd m10, m14, q0220 + pand m10, m9 + psrldq m14, 1 ; 08 10 12 14 01 03 05 07 09 11 13 15 __ __ __ __ + pslldq m14, m14, 12 + por m10, m14 ; shufD + psrlw m9, m1, 8 + psraw m11, m8, 8 + psllw m1, 8 + psllw m8, 8 + psrlw m1, 8 + psraw m8, 8 + pmullw m9, m11 + pmullw m1, m8 + paddw m1, m9 ; pmaddubsw m1, m8 + movq m14, [filterq+mxq *8] ; 2 X + movq m9, [filterq+tmp1q*8] ; 6 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + movhps m14, [filterq+tmp2q*8] ; 2 3 + movhps m9, [filterq+tmp1q*8] ; 6 7 + psrlw m8, m15, 8 + psraw m11, m14, 8 + psllw m15, 8 + psllw m14, 8 + psrlw m15, 8 + psraw m14, 8 + pmullw m8, m11 + pmullw m15, m14 + paddw m15, m8 ; pmaddubsw m15, m14 + psrlw m8, m10, 8 + psraw m11, m9, 8 + psllw m10, 8 + psllw m9, 8 + psrlw m10, 8 + psraw m9, 8 + pmullw m8, m11 + pmullw m10, m9 + paddw m10, m8 ; pmaddubsw m10, m9 + pslld m8, m0, 16 + pslld m9, m1, 16 + pslld m14, m15, 16 + pslld m11, m10, 16 + paddw m0, m8 + paddw m1, m9 + paddw m15, m14 + paddw m10, m11 + psrad m0, 16 + psrad m1, 16 + psrad m15, 16 + psrad m10, 16 + packssdw m0, m15 ; phaddw m0, m15 + packssdw m1, m10 ; phaddw m1, m10 +%endif + mova m14, [PIC_sym(pw_8192)] + mova m9, [PIC_sym(pd_32768)] + pmaddwd m0, m14 ; 17-bit intermediate, upshifted by 13 + pmaddwd m1, m14 + paddd m0, m9 ; rounded 14-bit result in upper 16 bits of dword + paddd m1, m9 + ret +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%macro BIDIR_FN 1 ; op + %1 0 + lea stride3q, [strideq*3] + jmp wq +.w4_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*4] +.w4: ; tile 4x + movd [dstq ], m0 ; copy dw[0] + pshuflw m1, m0, q1032 ; swap dw[1] and dw[0] + movd [dstq+strideq*1], m1 ; copy dw[1] + punpckhqdq m0, m0 ; swap dw[3,2] with dw[1,0] + movd [dstq+strideq*2], m0 ; dw[2] + psrlq m0, 32 ; shift right in dw[3] + movd [dstq+stride3q ], m0 ; copy + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*2] +.w8: + movq [dstq ], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq] +.w16: + mova [dstq ], m0 + dec hd + jg .w16_loop + RET +.w32_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq] +.w32: + mova [dstq ], m0 + %1 2 + mova [dstq + 16 ], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + %1_INC_PTR 8 + %1 0 + add dstq, strideq +.w64: + %assign i 0 + %rep 4 + mova [dstq + i*16 ], m0 + %assign i i+1 + %if i < 4 + %1 2*i + %endif + %endrep + dec hd + jg .w64_loop + RET +.w128_loop: + %1_INC_PTR 16 + %1 0 + add dstq, strideq +.w128: + %assign i 0 + %rep 8 + mova [dstq + i*16 ], m0 + %assign i i+1 + %if i < 8 + %1 2*i + %endif + %endrep + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + ; writes AVG of tmp1 tmp2 uint16 coeffs into uint8 pixel + mova m0, [tmp1q+(%1+0)*mmsize] ; load 8 coef(2bytes) from tmp1 + paddw m0, [tmp2q+(%1+0)*mmsize] ; load/add 8 coef(2bytes) tmp2 + mova m1, [tmp1q+(%1+1)*mmsize] + paddw m1, [tmp2q+(%1+1)*mmsize] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + packuswb m0, m1 ; pack/trunc 16 bits from m0 & m1 to 8 bit +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +cglobal avg_8bpc, 4, 7, 3, dst, stride, tmp1, tmp2, w, h, stride3 + LEA r6, avg_ssse3_table + tzcnt wd, wm ; leading zeros + movifnidn hd, hm ; move h(stack) to h(register) if not already that register + movsxd wq, dword [r6+wq*4] ; push table entry matching the tile width (tzcnt) in widen reg + mova m2, [pw_1024+r6-avg_ssse3_table] ; fill m2 with shift/align + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m2, [tmp1q+(%1+0)*mmsize] + mova m0, m2 + psubw m2, [tmp2q+(%1+0)*mmsize] + mova m3, [tmp1q+(%1+1)*mmsize] + mova m1, m3 + psubw m3, [tmp2q+(%1+1)*mmsize] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 + LEA r6, w_avg_ssse3_table + tzcnt wd, wm + movd m4, r6m + movifnidn hd, hm + pxor m0, m0 + movsxd wq, dword [r6+wq*4] + mova m5, [pw_2048+r6-w_avg_ssse3_table] + pshufb m4, m0 + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + psubw m0, m4 + mov tmp1q, tmp2q + mova m4, m0 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 + mova m3, [maskq+(%1+0)*(mmsize/2)] + mova m0, [tmp2q+(%1+0)*mmsize] ; b + psubw m1, m0, [tmp1q+(%1+0)*mmsize] ; b - a + mova m6, m3 ; m + psubb m3, m4, m6 ; -m + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 ; -m << 1 + punpcklbw m2, m4, m3 ; -m << 9 (<< 8 when ext as uint16) + pmulhw m1, m2 ; (-m * (b - a)) << 10 + paddw m0, m1 ; + b + mova m1, [tmp2q+(%1+1)*mmsize] ; b + psubw m2, m1, [tmp1q+(%1+1)*mmsize] ; b - a + paddw m2, m2 ; (b - a) << 1 + mova m6, m3 ; (-m << 1) + punpckhbw m3, m4, m6 ; (-m << 9) + pmulhw m2, m3 ; (-m << 9) + paddw m1, m2 ; (-m * (b - a)) << 10 + pmulhrsw m0, m5 ; round + pmulhrsw m1, m5 ; round + packuswb m0, m1 ; interleave 16 -> 8 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*mmsize/2 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +%if ARCH_X86_64 +cglobal mask_8bpc, 4, 8, 7, dst, stride, tmp1, tmp2, w, h, mask, stride3 + movifnidn hd, hm +%else +cglobal mask_8bpc, 4, 7, 7, dst, stride, tmp1, tmp2, w, mask, stride3 +%define hd dword r5m +%endif +%define base r6-mask_ssse3_table + LEA r6, mask_ssse3_table + tzcnt wd, wm + movsxd wq, dword [r6+wq*4] + pxor m4, m4 + mova m5, [base+pw_2048] + add wq, r6 + mov maskq, r6m + BIDIR_FN MASK +%undef hd + +%macro W_MASK_420_END 1-* +%rep %0 + call .main + paddw m2, [maskq+16*%1] + mova [maskq+16*%1], m2 + mova [dstq+strideq*1+16*(2*%1+0)], m0 + call .main + psubw m3, m7, m2 + psubw m1, m7, [maskq+16*%1] + psubw m3, [dstq+strideq*1+16*(2*%1+1)] + psrlw m1, 2 + psrlw m3, 2 + packuswb m1, m3 + mova [maskq+16*%1], m1 + mova [dstq+strideq*1+16*(2*%1+1)], m0 + %rotate 1 +%endrep +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal w_mask_420_8bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_420_ssse3_table + LEA t0, w_mask_420_ssse3_table + tzcnt wd, wm + mov r6d, r7m ; sign + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_2048] + movddup m7, [base+wm_420_sign+r6*8] ; 258 - sign + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + movifnidn hd, hm +%else + %define m8 [base+pw_6903] + %define hd dword hm +%endif + mov maskq, maskmp + call .main + jmp wq +.w4_loop: + call .main + add maskq, 4 + lea dstq, [dstq+strideq*2] +.w4: + pshufd m3, m2, q2020 + pshufd m2, m2, q3131 + psubw m1, m7, m3 + psubw m1, m2 + psrlw m1, 2 + packuswb m1, m1 + movd [maskq], m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + add maskq, 4 + lea dstq, [dstq+strideq*2] +.w8: + movhlps m3, m2 + psubw m1, m7, m2 + psubw m1, m3 + psrlw m1, 2 + packuswb m1, m1 + movd [maskq], m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + add maskq, 8 + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*1], m2 + mova [dstq+strideq*0], m0 + call .main + psubw m1, m7, [dstq+strideq*1] + psubw m1, m2 + psrlw m1, 2 + packuswb m1, m1 + movq [maskq], m1 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w32: + mova [maskq], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + W_MASK_420_END 0 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add maskq, 16*2 + lea dstq, [dstq+strideq*2] +.w64: + mova [maskq+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + call .main + mova [maskq+16*1], m2 + mova [dstq+strideq*0+16*2], m0 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m0 + W_MASK_420_END 0, 1 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + add maskq, 16*4 + lea dstq, [dstq+strideq*2] +.w128: + mova [maskq+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + call .main + mova [maskq+16*1], m2 + mova [dstq+strideq*0+16*2], m0 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m0 + call .main + mova [maskq+16*2], m2 + mova [dstq+strideq*0+16*4], m0 + call .main + mova [dstq+strideq*1+16*5], m2 + mova [dstq+strideq*0+16*5], m0 + call .main + mova [maskq+16*3], m2 + mova [dstq+strideq*0+16*6], m0 + call .main + mova [dstq+strideq*1+16*7], m2 + mova [dstq+strideq*0+16*7], m0 + W_MASK_420_END 0, 1, 2, 3 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: + mova m0, [tmp1q +16*0] + mova m3, [tmp1q+tmp2q+16*0] + mova m1, [tmp1q +16*1] + mova m4, [tmp1q+tmp2q+16*1] + add tmp1q, 16*2 + psubw m3, m0 + psubw m4, m1 + pabsw m5, m3 + psubusw m2, m8, m5 + psrlw m2, 8 ; 64 - m + psllw m5, m2, 10 + pmulhw m3, m5 + pabsw m5, m4 + paddw m0, m3 + psubusw m3, m8, m5 + psrlw m3, 8 + phaddw m2, m3 + psllw m3, 10 + pmulhw m4, m3 + paddw m1, m4 + pmulhrsw m0, m6 + pmulhrsw m1, m6 + packuswb m0, m1 + ret + +%macro W_MASK_422_BACKUP 1 ; mask_offset +%if ARCH_X86_64 + mova m10, m2 +%else + mova [maskq+16*%1], m2 +%endif +%endmacro + +%macro W_MASK_422_END 1 ; mask_offset +%if ARCH_X86_64 + packuswb m10, m2 + psubb m1, m7, m10 + pavgb m1, m9 +%else + mova m3, [maskq+16*%1] + packuswb m3, m2 + pxor m2, m2 + psubb m1, m7, m3 + pavgb m1, m2 +%endif + mova [maskq+16*%1], m1 +%endmacro + +cglobal w_mask_422_8bpc, 4, 7, 11, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_422_ssse3_table + LEA t0, w_mask_422_ssse3_table + tzcnt wd, wm + mov r6d, r7m ; sign + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_2048] + movddup m7, [base+wm_422_sign+r6*8] ; 128 - sign + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pw_6903] + pxor m9, m9 + movifnidn hd, hm +%else + add t0, w_mask_420_ssse3_table-w_mask_422_ssse3_table + %define hd dword hm +%endif + mov maskq, maskmp + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + jmp wq +.w4_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 8 + lea dstq, [dstq+strideq*2] +.w4: + packuswb m2, m2 + psubb m1, m7, m2 +%if ARCH_X86_64 + pavgb m1, m9 +%else + pxor m2, m2 + pavgb m1, m2 +%endif + movq [maskq], m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w8: + W_MASK_422_BACKUP 0 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + lea dstq, [dstq+strideq*2] + W_MASK_422_END 0 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w16: + W_MASK_422_BACKUP 0 + mova [dstq+strideq*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + add dstq, strideq +.w32: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16*2 + add dstq, strideq +.w64: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 1 + mova [dstq+16*2], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 1 + mova [dstq+16*3], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16*4 + add dstq, strideq +.w128: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 1 + mova [dstq+16*2], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 1 + mova [dstq+16*3], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 2 + mova [dstq+16*4], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 2 + mova [dstq+16*5], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 3 + mova [dstq+16*6], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 3 + mova [dstq+16*7], m0 + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_444_ssse3_table + LEA t0, w_mask_444_ssse3_table + tzcnt wd, wm + mov maskq, maskmp + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_6903] + mova m7, [base+pw_2048] + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pb_64] + movifnidn hd, hm +%else + %define m8 [base+pb_64] + %define hd dword hm +%endif + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0], m0 + call .main + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + call .main + mova [dstq+16*2], m0 + call .main + mova [dstq+16*3], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + call .main + mova [dstq+16*2], m0 + call .main + mova [dstq+16*3], m0 + call .main + mova [dstq+16*4], m0 + call .main + mova [dstq+16*5], m0 + call .main + mova [dstq+16*6], m0 + call .main + mova [dstq+16*7], m0 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m0, [tmp1q +16*0] + mova m3, [tmp1q+tmp2q+16*0] + mova m1, [tmp1q +16*1] + mova m4, [tmp1q+tmp2q+16*1] + add tmp1q, 16*2 + psubw m3, m0 + psubw m4, m1 + pabsw m5, m3 + psubusw m2, m6, m5 + psrlw m2, 8 ; 64 - m + psllw m5, m2, 10 + pmulhw m3, m5 + pabsw m5, m4 + paddw m0, m3 + psubusw m3, m6, m5 + psrlw m3, 8 + packuswb m2, m3 + psllw m3, 10 + pmulhw m4, m3 + psubb m3, m8, m2 + paddw m1, m4 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + mova [maskq], m3 + add maskq, 16 + packuswb m0, m1 + ret + +%macro BLEND_64M 4; a, b, mask1, mask2 + punpcklbw m0, %1, %2; {b;a}[7..0] + punpckhbw %1, %2 ; {b;a}[15..8] + pmaddubsw m0, %3 ; {b*m[0] + (64-m[0])*a}[7..0] u16 + pmaddubsw %1, %4 ; {b*m[1] + (64-m[1])*a}[15..8] u16 + pmulhrsw m0, m5 ; {((b*m[0] + (64-m[0])*a) + 1) / 32}[7..0] u16 + pmulhrsw %1, m5 ; {((b*m[1] + (64-m[0])*a) + 1) / 32}[15..8] u16 + packuswb m0, %1 ; {blendpx}[15..0] u8 +%endmacro + +%macro BLEND 2; a, b + psubb m3, m4, m0 ; m3 = (64 - m) + punpcklbw m2, m3, m0 ; {m;(64-m)}[7..0] + punpckhbw m3, m0 ; {m;(64-m)}[15..8] + BLEND_64M %1, %2, m2, m3 +%endmacro + +cglobal blend_8bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_ssse3_table + LEA r6, blend_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movifnidn maskq, maskmp + movsxd wq, dword [r6+wq*4] + mova m4, [base+pb_64] + mova m5, [base+pw_512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movq m0, [maskq]; m + movd m1, [dstq+dsq*0] ; a + movd m6, [dstq+dsq*1] + punpckldq m1, m6 + movq m6, [tmpq] ; b + psubb m3, m4, m0 ; m3 = (64 - m) + punpcklbw m2, m3, m0 ; {m;(64-m)}[7..0] + punpcklbw m1, m6 ; {b;a}[7..0] + pmaddubsw m1, m2 ; {b*m[0] + (64-m[0])*a}[7..0] u16 + pmulhrsw m1, m5 ; {((b*m[0] + (64-m[0])*a) + 1) / 32}[7..0] u16 + packuswb m1, m0 ; {blendpx}[15..0] u8 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + add maskq, 8 + add tmpq, 8 + lea dstq, [dstq+dsq*2] ; dst_stride * 2 + sub hd, 2 + jg .w4 + RET +.w8: + mova m0, [maskq]; m + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m6, [tmpq] ; b + BLEND m1, m6 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + add maskq, 16 + add tmpq, 16 + lea dstq, [dstq+dsq*2] ; dst_stride * 2 + sub hd, 2 + jg .w8 + RET +.w16: + mova m0, [maskq]; m + mova m1, [dstq] ; a + mova m6, [tmpq] ; b + BLEND m1, m6 + mova [dstq], m0 + add maskq, 16 + add tmpq, 16 + add dstq, dsq ; dst_stride + dec hd + jg .w16 + RET +.w32: + %assign i 0 + %rep 2 + mova m0, [maskq+16*i]; m + mova m1, [dstq+16*i] ; a + mova m6, [tmpq+16*i] ; b + BLEND m1, m6 + mova [dstq+i*16], m0 + %assign i i+1 + %endrep + add maskq, 32 + add tmpq, 32 + add dstq, dsq ; dst_stride + dec hd + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_ssse3_table + LEA r5, blend_v_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r5+wq*4] + mova m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_ssse3_table + jmp wq +.w2: + movd m3, [maskq+4] + punpckldq m3, m3 + ; 2 mask blend is provided for 4 pixels / 2 lines +.w2_loop: + movd m1, [dstq+dsq*0] ; a {..;a;a} + pinsrw m1, [dstq+dsq*1], 1 + movd m2, [tmpq] ; b + punpcklbw m0, m1, m2; {b;a}[7..0] + pmaddubsw m0, m3 ; {b*m + (64-m)*a}[7..0] u16 + pmulhrsw m0, m5 ; {((b*m + (64-m)*a) + 1) / 32}[7..0] u16 + packuswb m0, m1 ; {blendpx}[8..0] u8 + movd r3d, m0 + mov [dstq+dsq*0], r3w + shr r3d, 16 + mov [dstq+dsq*1], r3w + add tmpq, 2*2 + lea dstq, [dstq + dsq * 2] + sub hd, 2 + jg .w2_loop + RET +.w4: + movddup m3, [maskq+8] + ; 4 mask blend is provided for 8 pixels / 2 lines +.w4_loop: + movd m1, [dstq+dsq*0] ; a + movd m2, [dstq+dsq*1] ; + punpckldq m1, m2 + movq m2, [tmpq] ; b + punpcklbw m1, m2 ; {b;a}[7..0] + pmaddubsw m1, m3 ; {b*m + (64-m)*a}[7..0] u16 + pmulhrsw m1, m5 ; {((b*m + (64-m)*a) + 1) / 32}[7..0] u16 + packuswb m1, m1 ; {blendpx}[8..0] u8 + movd [dstq], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + add tmpq, 2*4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova m3, [maskq+16] + ; 8 mask blend is provided for 16 pixels +.w8_loop: + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m2, [tmpq]; b + BLEND_64M m1, m2, m3, m3 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + add tmpq, 16 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + ; 16 mask blend is provided for 32 pixels + mova m3, [maskq+32] ; obmc_masks_16[0] (64-m[0]) + mova m4, [maskq+48] ; obmc_masks_16[1] (64-m[1]) +.w16_loop: + mova m1, [dstq] ; a + mova m2, [tmpq] ; b + BLEND_64M m1, m2, m3, m4 + mova [dstq], m0 + add tmpq, 16 + add dstq, dsq + dec hd + jg .w16_loop + RET +.w32: +%if WIN64 + mova [rsp+8], xmm6 +%endif + mova m3, [maskq+64] ; obmc_masks_32[0] (64-m[0]) + mova m4, [maskq+80] ; obmc_masks_32[1] (64-m[1]) + mova m6, [maskq+96] ; obmc_masks_32[2] (64-m[2]) + ; 16 mask blend is provided for 64 pixels +.w32_loop: + mova m1, [dstq+16*0] ; a + mova m2, [tmpq+16*0] ; b + BLEND_64M m1, m2, m3, m4 + movq m1, [dstq+16*1] ; a + punpcklbw m1, [tmpq+16*1] ; b + pmaddubsw m1, m6 + pmulhrsw m1, m5 + packuswb m1, m1 + mova [dstq+16*0], m0 + movq [dstq+16*1], m1 + add tmpq, 32 + add dstq, dsq + dec hd + jg .w32_loop +%if WIN64 + mova xmm6, [rsp+8] +%endif + RET + +cglobal blend_h_8bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base t0-blend_h_ssse3_table +%if ARCH_X86_32 + ; We need to keep the PIC pointer for w4, reload wd from stack instead + DECLARE_REG_TMP 6 +%else + DECLARE_REG_TMP 5 + mov r6d, wd +%endif + LEA t0, blend_h_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, dword [t0+wq*4] + mova m5, [base+pw_512] + add wq, t0 + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + pinsrw m0, [dstq+dsq*1], 1 + movd m2, [maskq+hq*2] + movd m1, [tmpq] + punpcklwd m2, m2 + punpcklbw m0, m1 + pmaddubsw m0, m2 + pmulhrsw m0, m5 + packuswb m0, m0 + movd r3d, m0 + mov [dstq+dsq*0], r3w + shr r3d, 16 + mov [dstq+dsq*1], r3w + lea dstq, [dstq+dsq*2] + add tmpq, 2*2 + add hq, 2 + jl .w2 + RET +.w4: +%if ARCH_X86_32 + mova m3, [base+blend_shuf] +%else + mova m3, [blend_shuf] +%endif +.w4_loop: + movd m0, [dstq+dsq*0] + movd m2, [dstq+dsq*1] + punpckldq m0, m2 ; a + movq m1, [tmpq] ; b + movq m2, [maskq+hq*2] ; m + pshufb m2, m3 + punpcklbw m0, m1 + pmaddubsw m0, m2 + pmulhrsw m0, m5 + packuswb m0, m0 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add tmpq, 4*2 + add hq, 2 + jl .w4_loop + RET +.w8: + movd m4, [maskq+hq*2] + punpcklwd m4, m4 + pshufd m3, m4, q0000 + pshufd m4, m4, q1111 + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m2, [tmpq] + BLEND_64M m1, m2, m3, m4 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add tmpq, 8*2 + add hq, 2 + jl .w8 + RET +; w16/w32/w64/w128 +.w16: +%if ARCH_X86_32 + mov r6d, wm +%endif + sub dsq, r6 +.w16_loop0: + movd m3, [maskq+hq*2] + pshuflw m3, m3, q0000 + punpcklqdq m3, m3 + mov wd, r6d +.w16_loop: + mova m1, [dstq] ; a + mova m2, [tmpq] ; b + BLEND_64M m1, m2, m3, m3 + mova [dstq], m0 + add dstq, 16 + add tmpq, 16 + sub wd, 16 + jg .w16_loop + add dstq, dsq + inc hq + jl .w16_loop0 + RET + +; emu_edge args: +; const intptr_t bw, const intptr_t bh, const intptr_t iw, const intptr_t ih, +; const intptr_t x, const intptr_t y, pixel *dst, const ptrdiff_t dst_stride, +; const pixel *ref, const ptrdiff_t ref_stride +; +; bw, bh total filled size +; iw, ih, copied block -> fill bottom, right +; x, y, offset in bw/bh -> fill top, left +cglobal emu_edge_8bpc, 10, 13, 2, bw, bh, iw, ih, x, \ + y, dst, dstride, src, sstride, \ + bottomext, rightext, blk + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + pxor m1, m1 + +%if ARCH_X86_64 + %define reg_zero r12q + %define reg_tmp r10 + %define reg_src srcq + %define reg_bottomext bottomextq + %define reg_rightext rightextq + %define reg_blkm r9m +%else + %define reg_zero r6 + %define reg_tmp r0 + %define reg_src r1 + %define reg_bottomext r0 + %define reg_rightext r1 + %define reg_blkm r2m +%endif + ; + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor reg_zero, reg_zero + lea reg_tmp, [ihq-1] + cmp yq, ihq + cmovs reg_tmp, yq + test yq, yq + cmovs reg_tmp, reg_zero +%if ARCH_X86_64 + imul reg_tmp, sstrideq + add srcq, reg_tmp +%else + imul reg_tmp, sstridem + mov reg_src, srcm + add reg_src, reg_tmp +%endif + ; + ; ref += iclip(x, 0, iw - 1) + lea reg_tmp, [iwq-1] + cmp xq, iwq + cmovs reg_tmp, xq + test xq, xq + cmovs reg_tmp, reg_zero + add reg_src, reg_tmp +%if ARCH_X86_32 + mov srcm, reg_src +%endif + ; + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) +%if ARCH_X86_32 + mov r1, r1m ; restore bh +%endif + lea reg_bottomext, [yq+bhq] + sub reg_bottomext, ihq + lea r3, [bhq-1] + cmovs reg_bottomext, reg_zero + ; + + DEFINE_ARGS bw, bh, iw, ih, x, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, reg_zero + cmp reg_bottomext, bhq + cmovns reg_bottomext, r3 + cmp topextq, bhq + cmovg topextq, r3 + %if ARCH_X86_32 + mov r4m, reg_bottomext + ; + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + mov r0, r0m ; restore bw + %endif + lea reg_rightext, [xq+bwq] + sub reg_rightext, iwq + lea r2, [bwq-1] + cmovs reg_rightext, reg_zero + + DEFINE_ARGS bw, bh, iw, ih, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, reg_zero + cmp reg_rightext, bwq + cmovns reg_rightext, r2 + %if ARCH_X86_32 + mov r3m, r1 + %endif + cmp leftextq, bwq + cmovns leftextq, r2 + +%undef reg_zero +%undef reg_tmp +%undef reg_src +%undef reg_bottomext +%undef reg_rightext + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; center_h = bh - top_ext - bottom_ext +%if ARCH_X86_64 + lea r3, [bottomextq+topextq] + sub centerhq, r3 +%else + mov r1, centerhm ; restore r1 + sub centerhq, topextq + sub centerhq, r4m + mov r1m, centerhq +%endif + ; + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq +%if ARCH_X86_64 + imul r2, dstrideq +%else + mov r6, r6m ; restore dstq + imul r2, dstridem +%endif + add dstq, r2 + mov reg_blkm, dstq ; save pointer for ext + ; + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq +%if ARCH_X86_64 + lea r3, [rightextq+leftextq] + sub centerwq, r3 +%else + sub centerwq, r3m + sub centerwq, leftextq +%endif + +; vloop Macro +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix + %if ARCH_X86_64 + %define reg_tmp r12 + %else + %define reg_tmp r0 + %endif +.v_loop_%3: + %if ARCH_X86_32 + mov r0, r0m + mov r1, r1m + %endif +%if %1 + ; left extension + %if ARCH_X86_64 + movd m0, [srcq] + %else + mov r3, srcm + movd m0, [r3] + %endif + pshufb m0, m1 + xor r3, r3 +.left_loop_%3: + mova [dstq+r3], m0 + add r3, mmsize + cmp r3, leftextq + jl .left_loop_%3 + ; body + lea reg_tmp, [dstq+leftextq] +%endif + xor r3, r3 +.body_loop_%3: + %if ARCH_X86_64 + movu m0, [srcq+r3] + %else + mov r1, srcm + movu m0, [r1+r3] + %endif +%if %1 + movu [reg_tmp+r3], m0 +%else + movu [dstq+r3], m0 +%endif + add r3, mmsize + cmp r3, centerwq + jl .body_loop_%3 +%if %2 + ; right extension +%if %1 + add reg_tmp, centerwq +%else + lea reg_tmp, [dstq+centerwq] +%endif + %if ARCH_X86_64 + movd m0, [srcq+centerwq-1] + %else + mov r3, srcm + movd m0, [r3+centerwq-1] + %endif + pshufb m0, m1 + xor r3, r3 +.right_loop_%3: + movu [reg_tmp+r3], m0 + add r3, mmsize + %if ARCH_X86_64 + cmp r3, rightextq + %else + cmp r3, r3m + %endif + jl .right_loop_%3 +%endif + %if ARCH_X86_64 + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 + %else + add dstq, dstridem + mov r0, sstridem + add srcm, r0 + sub dword centerhm, 1 + jg .v_loop_%3 + mov r0, r0m ; restore r0 + %endif +%endmacro ; vloop MACRO + + test leftextq, leftextq + jnz .need_left_ext + %if ARCH_X86_64 + test rightextq, rightextq + jnz .need_right_ext + %else + cmp leftextq, r3m ; leftextq == 0 + jne .need_right_ext + %endif + v_loop 0, 0, 0 + jmp .body_done + + ;left right extensions +.need_left_ext: + %if ARCH_X86_64 + test rightextq, rightextq + %else + mov r3, r3m + test r3, r3 + %endif + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: +; r0 ; bw +; r1 ;; x loop +; r4 ;; y loop +; r5 ; topextq +; r6 ;dstq +; r7 ;dstrideq +; r8 ; srcq +%if ARCH_X86_64 + %define reg_dstride dstrideq +%else + %define reg_dstride r2 +%endif + ; + ; bottom edge extension + %if ARCH_X86_64 + test bottomextq, bottomextq + jz .top + %else + xor r1, r1 + cmp r1, r4m + je .top + %endif + ; + %if ARCH_X86_64 + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 + %else + mov r3, dstq + mov reg_dstride, dstridem + sub r3, reg_dstride + mov srcm, r3 + %endif + ; +.bottom_x_loop: + %if ARCH_X86_64 + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, bottomextq + %else + mov r3, srcm + mova m0, [r3+r1] + lea r3, [dstq+r1] + mov r4, r4m + %endif + ; +.bottom_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .bottom_y_loop + add r1, mmsize + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end +%if ARCH_X86_64 + mov srcq, reg_blkm +%else + mov r3, reg_blkm + mov reg_dstride, dstridem +%endif + mov dstq, dstm + xor r1, r1 + ; +.top_x_loop: +%if ARCH_X86_64 + mova m0, [srcq+r1] +%else + mov r3, reg_blkm + mova m0, [r3+r1] +%endif + lea r3, [dstq+r1] + mov r4, topextq + ; +.top_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .top_y_loop + add r1, mmsize + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +%undef reg_dstride +%undef reg_blkm +%undef reg_tmp + +cextern resize_filter + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +%if ARCH_X86_64 +cglobal resize_8bpc, 0, 12, 14, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%elif STACK_ALIGNMENT >= 16 +cglobal resize_8bpc, 0, 7, 8, 3 * 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%else +cglobal resize_8bpc, 0, 6, 8, 3 * 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%endif + movifnidn dstq, dstmp + movifnidn srcq, srcmp +%if STACK_ALIGNMENT >= 16 + movifnidn dst_wd, dst_wm +%endif +%if ARCH_X86_64 + movifnidn hd, hm +%endif + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + movd m7, dxm + movd m6, mx0m + movd m5, src_wm + pshufd m7, m7, q0000 + pshufd m6, m6, q0000 + pshufd m5, m5, q0000 + +%if ARCH_X86_64 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ +%else + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, x +%define hd dword r5m +%if STACK_ALIGNMENT >= 16 + LEA r6, $$ +%define base r6-$$ +%else + LEA r4, $$ +%define base r4-$$ +%endif +%endif + +%if ARCH_X86_64 + mova m10, [base+pw_m256] + mova m9, [base+pd_63] + mova m8, [base+pb_8x0_8x8] +%else +%define m10 [base+pw_m256] +%define m9 [base+pd_63] +%define m8 [base+pb_8x0_8x8] +%endif + pmaddwd m4, m7, [base+rescale_mul] ; dx*[0,1,2,3] + pslld m7, 2 ; dx*4 + pslld m5, 14 + paddd m6, m4 ; mx+[0..3]*dx + SCRATCH 7, 13, 0 + SCRATCH 6, 12, 1 + SCRATCH 5, 11, 2 + + ; m10 = pmulhrsw constant for x=(x+64)>>7 + ; m12 = mx+[0..3]*dx, m13 = dx*4, m11 = src_w, m9 = 0x3f, m8=0,8 + +.loop_y: + xor xd, xd + mova m0, m12 ; per-line working version of mx + +.loop_x: + pxor m1, m1 + pcmpgtd m1, m0 + pandn m1, m0 + psrad m2, m0, 8 ; filter offset (unmasked) + pcmpgtd m3, m11, m1 + pand m1, m3 + pandn m3, m11 + por m1, m3 + psubd m3, m0, m1 ; pshufb offset + psrad m1, 14 ; clipped src_x offset + psrad m3, 14 ; pshufb edge_emu offset + pand m2, m9 ; filter offset (masked) + + ; load source pixels +%if ARCH_X86_64 + movd r8d, m1 + pshuflw m1, m1, q3232 + movd r9d, m1 + punpckhqdq m1, m1 + movd r10d, m1 + psrlq m1, 32 + movd r11d, m1 + movq m4, [srcq+r8] + movq m5, [srcq+r10] + movhps m4, [srcq+r9] + movhps m5, [srcq+r11] +%else + movd r3d, m1 + pshufd m1, m1, q3312 + movd r1d, m1 + pshuflw m1, m1, q3232 + movq m4, [srcq+r3] + movq m5, [srcq+r1] + movd r3d, m1 + punpckhqdq m1, m1 + movd r1d, m1 + movhps m4, [srcq+r3] + movhps m5, [srcq+r1] +%endif + + ; if no emulation is required, we don't need to shuffle or emulate edges + ; this also saves 2 quasi-vpgatherdqs + pxor m6, m6 + pcmpeqb m6, m3 +%if ARCH_X86_64 + pmovmskb r8d, m6 + cmp r8d, 0xffff +%else + pmovmskb r3d, m6 + cmp r3d, 0xffff +%endif + je .filter + +%if ARCH_X86_64 + movd r8d, m3 + pshuflw m3, m3, q3232 + movd r9d, m3 + punpckhqdq m3, m3 + movd r10d, m3 + psrlq m3, 32 + movd r11d, m3 + movsxd r8, r8d + movsxd r9, r9d + movsxd r10, r10d + movsxd r11, r11d + movq m6, [base+resize_shuf+4+r8] + movq m7, [base+resize_shuf+4+r10] + movhps m6, [base+resize_shuf+4+r9] + movhps m7, [base+resize_shuf+4+r11] +%else + movd r3d, m3 + pshufd m3, m3, q3312 + movd r1d, m3 + pshuflw m3, m3, q3232 + movq m6, [base+resize_shuf+4+r3] + movq m7, [base+resize_shuf+4+r1] + movd r3d, m3 + punpckhqdq m3, m3 + movd r1d, m3 + movhps m6, [base+resize_shuf+4+r3] + movhps m7, [base+resize_shuf+4+r1] +%endif + + paddb m6, m8 + paddb m7, m8 + pshufb m4, m6 + pshufb m5, m7 + +.filter: +%if ARCH_X86_64 + movd r8d, m2 + pshuflw m2, m2, q3232 + movd r9d, m2 + punpckhqdq m2, m2 + movd r10d, m2 + psrlq m2, 32 + movd r11d, m2 + movq m6, [base+resize_filter+r8*8] + movq m7, [base+resize_filter+r10*8] + movhps m6, [base+resize_filter+r9*8] + movhps m7, [base+resize_filter+r11*8] +%else + movd r3d, m2 + pshufd m2, m2, q3312 + movd r1d, m2 + pshuflw m2, m2, q3232 + movq m6, [base+resize_filter+r3*8] + movq m7, [base+resize_filter+r1*8] + movd r3d, m2 + punpckhqdq m2, m2 + movd r1d, m2 + movhps m6, [base+resize_filter+r3*8] + movhps m7, [base+resize_filter+r1*8] +%endif + + pmaddubsw m4, m6 + pmaddubsw m5, m7 + phaddw m4, m5 + phaddsw m4, m4 + pmulhrsw m4, m10 ; x=(x+64)>>7 + packuswb m4, m4 + movd [dstq+xq], m4 + + paddd m0, m13 + add xd, 4 +%if STACK_ALIGNMENT >= 16 + cmp xd, dst_wd +%else + cmp xd, dst_wm +%endif + jl .loop_x + + add dstq, dst_stridemp + add srcq, src_stridemp + dec hd + jg .loop_y + RET + +INIT_XMM ssse3 +PREP_BILIN +PREP_8TAP +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T + +INIT_XMM sse4 +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T + +INIT_XMM sse2 +PREP_BILIN +PREP_8TAP +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_avx.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_avx.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_avx.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_avx.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,204 @@ +; +; Copyright (c) 2016, Alliance for Open Media. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. +; + +; + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION .text + +%macro SAD_FN 4 +%if %4 == 0 +%if %3 == 5 +cglobal sad%1x%2, 4, %3, 5, src, src_stride, ref, ref_stride, n_rows +%else ; %3 == 7 +cglobal sad%1x%2, 4, %3, 6, src, src_stride, ref, ref_stride, \ + src_stride3, ref_stride3, n_rows +%endif ; %3 == 5/7 +%else ; avg +%if %3 == 5 +cglobal sad%1x%2_avg, 5, 1 + %3, 5, src, src_stride, ref, ref_stride, \ + second_pred, n_rows +%else ; %3 == 7 +cglobal sad%1x%2_avg, 5, ARCH_X86_64 + %3, 6, src, src_stride, \ + ref, ref_stride, \ + second_pred, \ + src_stride3, ref_stride3 +%if ARCH_X86_64 +%define n_rowsd r7d +%else ; x86-32 +%define n_rowsd dword r0m +%endif ; x86-32/64 +%endif ; %3 == 5/7 +%endif ; avg/sad + movsxdifnidn src_strideq, src_strided + movsxdifnidn ref_strideq, ref_strided +%if %3 == 7 + lea src_stride3q, [src_strideq*3] + lea ref_stride3q, [ref_strideq*3] +%endif ; %3 == 7 +%endmacro + +; unsigned int aom_sad128x128_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD128XN 1-2 0 + SAD_FN 128, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+32] + movu m3, [refq+64] + movu m4, [refq+96] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + vpsadbw m1, [srcq] + vpsadbw m2, [srcq+32] + vpsadbw m3, [srcq+64] + vpsadbw m4, [srcq+96] + + add refq, ref_strideq + add srcq, src_strideq + + vpaddd m1, m2 + vpaddd m3, m4 + vpaddd m0, m1 + vpaddd m0, m3 + + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + + RET +%endmacro + +INIT_YMM avx2 +SAD128XN 128 ; sad128x128_avx2 +SAD128XN 128, 1 ; sad128x128_avg_avx2 +SAD128XN 64 ; sad128x64_avx2 +SAD128XN 64, 1 ; sad128x64_avg_avx2 + + +; unsigned int aom_sad64x64_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD64XN 1-2 0 + SAD_FN 64, %1, 5, %2 + mov n_rowsd, %1/2 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+32] + movu m3, [refq+ref_strideq] + movu m4, [refq+ref_strideq+32] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + vpsadbw m1, [srcq] + vpsadbw m2, [srcq+32] + vpsadbw m3, [srcq+src_strideq] + vpsadbw m4, [srcq+src_strideq+32] + + vpaddd m1, m2 + vpaddd m3, m4 + lea refq, [refq+ref_strideq*2] + vpaddd m0, m1 + lea srcq, [srcq+src_strideq*2] + vpaddd m0, m3 + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + RET +%endmacro + +INIT_YMM avx2 +SAD64XN 128 ; sad64x128_avx2 +SAD64XN 128, 1 ; sad64x128_avg_avx2 +SAD64XN 64 ; sad64x64_avx2 +SAD64XN 32 ; sad64x32_avx2 +SAD64XN 64, 1 ; sad64x64_avg_avx2 +SAD64XN 32, 1 ; sad64x32_avg_avx2 +SAD64XN 16 ; sad64x16_avx2 +SAD64XN 16, 1 ; sad64x16_avg_avx2 + + +; unsigned int aom_sad32x32_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD32XN 1-2 0 + SAD_FN 32, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+ref_strideq] + movu m3, [refq+ref_strideq*2] + movu m4, [refq+ref_stride3q] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+src_strideq] + psadbw m3, [srcq+src_strideq*2] + psadbw m4, [srcq+src_stride3q] + + vpaddd m1, m2 + vpaddd m3, m4 + lea refq, [refq+ref_strideq*4] + vpaddd m0, m1 + lea srcq, [srcq+src_strideq*4] + vpaddd m0, m3 + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + RET +%endmacro + +INIT_YMM avx2 +SAD32XN 64 ; sad32x64_avx2 +SAD32XN 32 ; sad32x32_avx2 +SAD32XN 16 ; sad32x16_avx2 +SAD32XN 64, 1 ; sad32x64_avg_avx2 +SAD32XN 32, 1 ; sad32x32_avg_avx2 +SAD32XN 16, 1 ; sad32x16_avg_avx2 +SAD32XN 8 ; sad_32x8_avx2 +SAD32XN 8, 1 ; sad_32x8_avg_avx2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_plane.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_plane.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_plane.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_plane.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +; Copyright (c) 2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA + +align 32 +mask_lut: db \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, \ +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, + +%macro JMP_TABLE 3-* + %xdefine %%func mangle(private_prefix %+ _%1_%2) + %xdefine %%table %1_%2_table + %%table: + %rep %0 - 2 + dd (%%func %+ .%3) - (%%table) + %rotate 1 + %endrep +%endmacro + +JMP_TABLE sad_plane_8bpc, avx2, vec0, vec1, vec2, vec3 +JMP_TABLE sad_plane_8bpc, sse2, vec0, vec1, vec2, vec3 + +%use ifunc + +SECTION .text + +%macro SAD_PLANE_FN 0 +cglobal sad_plane_8bpc, 5, 9, 9, p1, p2, stride, width, rows, \ + resid_simd, resid, width_unrll, tmp0 + mov resid_simdq, widthq + mov residd, widthd + and residd, mmsize - 1 + and resid_simdq, -(mmsize) + and widthq, -(4*mmsize) + ; LUT row size is always 32 regardless of mmsize (because the + ; start of the rows would be the same, so we reuse the same LUT) + shl residd, ilog2(32) + pxor xm0, xm0 + pxor xm1, xm1 + pxor xm2, xm2 + pxor xm3, xm3 + ; load mask from lookup table into m8 + lea tmp0q, [mask_lut] + mova m8, [tmp0q + residq] + + DEFINE_ARGS p1, p2, stride, width, rows, \ + resid_simd, resid, width_unrll, skip_ptr + + sub resid_simdq, widthq + ; need to divide by mmsize to load skip pointer + shr resid_simdq, ilog2(mmsize) +%if mmsize == 32 + %define jmp_table sad_plane_8bpc_avx2_table +%elif mmsize == 16 + %define jmp_table sad_plane_8bpc_sse2_table +%endif + lea r6, [jmp_table] + movsxd skip_ptrq, [r6 + 4*resid_simdq] + add skip_ptrq, r6 + + ; shift back (for residual to load correct number of bytes) + shl resid_simdq, ilog2(mmsize) + ; set pointer to point after end of width of first row + add p1q, widthq + add p2q, widthq + mov width_unrllq, widthq + neg widthq +.loop_row: + test widthq, widthq + jz .skip +.loop: + mova m4, [p1q + widthq + 0*mmsize] + mova m5, [p1q + widthq + 1*mmsize] + mova m6, [p1q + widthq + 2*mmsize] + mova m7, [p1q + widthq + 3*mmsize] + + psadbw m4, m4, [p2q + widthq + 0*mmsize] + psadbw m5, m5, [p2q + widthq + 1*mmsize] + psadbw m6, m6, [p2q + widthq + 2*mmsize] + psadbw m7, m7, [p2q + widthq + 3*mmsize] + + paddq m0, m4 + paddq m1, m5 + paddq m2, m6 + paddq m3, m7 + + add widthq, 4*mmsize + jnz .loop +.skip: + jmp skip_ptrq +.vec3: + mova m6, [p1q + 2*mmsize] + psadbw m6, m6, [p2q + 2*mmsize] + paddq m2, m6 +.vec2: + mova m5, [p1q + 1*mmsize] + psadbw m5, m5, [p2q + 1*mmsize] + paddq m1, m5 +.vec1: + mova m4, [p1q + 0*mmsize] + psadbw m4, m4, [p2q + 0*mmsize] + paddq m0, m4 +.vec0: + ; skip residual element add if necessary + test residd, residd + jz .next_row + ; load residual elements and mask out elements past the width + pand m4, m8, [p1q + resid_simdq] + pand m5, m8, [p2q + resid_simdq] + psadbw m4, m4, m5 + paddq m2, m4 +.next_row: + ; width is 0 after the unrolled loop, so subtracting is basically a mov + neg + sub widthq, width_unrllq + ; since we started with p1+width, adding stride will get the + ; pointer at the end of the next row + add p1q, strideq + add p2q, strideq + dec rowsd + jnz .loop_row + ; final horizontal reduction + paddq m2, m3 + paddq m0, m1 + paddq m0, m2 +%if mmsize == 32 + vextracti128 xm1, ym0, 1 + paddq xm0, xm1 +%endif + pshufd xm1, xm0, q0032 + paddq xm0, xm1 + movq rax, xm0 + RET +%endmacro + +INIT_XMM sse2 +SAD_PLANE_FN + +INIT_YMM avx2 +SAD_PLANE_FN + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_sse2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_sse2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_sse2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/sad_sse2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,354 @@ +; +; Copyright (c) 2016, Alliance for Open Media. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. +; + +; + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION .text + +%macro SAD_FN 4 +%if %4 == 0 +%if %3 == 5 +cglobal sad%1x%2, 4, %3, 5, src, src_stride, ref, ref_stride, n_rows +%else ; %3 == 7 +cglobal sad%1x%2, 4, %3, 6, src, src_stride, ref, ref_stride, \ + src_stride3, ref_stride3, n_rows +%endif ; %3 == 5/7 +%else ; avg +%if %3 == 5 +cglobal sad%1x%2_avg, 5, 1 + %3, 5, src, src_stride, ref, ref_stride, \ + second_pred, n_rows +%else ; %3 == 7 +cglobal sad%1x%2_avg, 5, ARCH_X86_64 + %3, 6, src, src_stride, \ + ref, ref_stride, \ + second_pred, \ + src_stride3, ref_stride3 +%if ARCH_X86_64 +%define n_rowsd r7d +%else ; x86-32 +%define n_rowsd dword r0m +%endif ; x86-32/64 +%endif ; %3 == 5/7 +%endif ; avg/sad + movsxdifnidn src_strideq, src_strided + movsxdifnidn ref_strideq, ref_strided +%if %3 == 7 + lea src_stride3q, [src_strideq*3] + lea ref_stride3q, [ref_strideq*3] +%endif ; %3 == 7 +%endmacro + +; unsigned int aom_sad128x128_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD128XN 1-2 0 + SAD_FN 128, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+32] + movu m4, [refq+48] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+32] + psadbw m4, [srcq+48] + + paddd m1, m2 + paddd m3, m4 + paddd m0, m1 + paddd m0, m3 + + movu m1, [refq+64] + movu m2, [refq+80] + movu m3, [refq+96] + movu m4, [refq+112] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*4] + pavgb m2, [second_predq+mmsize*5] + pavgb m3, [second_predq+mmsize*6] + pavgb m4, [second_predq+mmsize*7] + lea second_predq, [second_predq+mmsize*8] +%endif + psadbw m1, [srcq+64] + psadbw m2, [srcq+80] + psadbw m3, [srcq+96] + psadbw m4, [srcq+112] + + add refq, ref_strideq + add srcq, src_strideq + + paddd m1, m2 + paddd m3, m4 + paddd m0, m1 + paddd m0, m3 + + sub n_rowsd, 1 + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD128XN 128 ; sad128x128_sse2 +SAD128XN 128, 1 ; sad128x128_avg_sse2 +SAD128XN 64 ; sad128x64_sse2 +SAD128XN 64, 1 ; sad128x64_avg_sse2 + + +; unsigned int aom_sad64x64_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD64XN 1-2 0 + SAD_FN 64, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+32] + movu m4, [refq+48] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+32] + psadbw m4, [srcq+48] + paddd m1, m2 + paddd m3, m4 + add refq, ref_strideq + paddd m0, m1 + add srcq, src_strideq + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD64XN 128 ; sad64x128_sse2 +SAD64XN 128, 1 ; sad64x128_avg_sse2 +SAD64XN 64 ; sad64x64_sse2 +SAD64XN 32 ; sad64x32_sse2 +SAD64XN 64, 1 ; sad64x64_avg_sse2 +SAD64XN 32, 1 ; sad64x32_avg_sse2 +SAD64XN 16 ; sad64x16_sse2 +SAD64XN 16, 1 ; sad64x16_avg_sse2 + +; unsigned int aom_sad32x32_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD32XN 1-2 0 + SAD_FN 32, %1, 5, %2 + mov n_rowsd, %1/2 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+ref_strideq] + movu m4, [refq+ref_strideq+16] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+src_strideq] + psadbw m4, [srcq+src_strideq+16] + paddd m1, m2 + paddd m3, m4 + lea refq, [refq+ref_strideq*2] + paddd m0, m1 + lea srcq, [srcq+src_strideq*2] + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD32XN 64 ; sad32x64_sse2 +SAD32XN 32 ; sad32x32_sse2 +SAD32XN 16 ; sad32x16_sse2 +SAD32XN 64, 1 ; sad32x64_avg_sse2 +SAD32XN 32, 1 ; sad32x32_avg_sse2 +SAD32XN 16, 1 ; sad32x16_avg_sse2 +SAD32XN 8 ; sad_32x8_sse2 +SAD32XN 8, 1 ; sad_32x8_avg_sse2 + +; unsigned int aom_sad16x{8,16}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD16XN 1-2 0 + SAD_FN 16, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+ref_strideq] + movu m3, [refq+ref_strideq*2] + movu m4, [refq+ref_stride3q] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+src_strideq] + psadbw m3, [srcq+src_strideq*2] + psadbw m4, [srcq+src_stride3q] + paddd m1, m2 + paddd m3, m4 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD16XN 32 ; sad16x32_sse2 +SAD16XN 16 ; sad16x16_sse2 +SAD16XN 8 ; sad16x8_sse2 +SAD16XN 32, 1 ; sad16x32_avg_sse2 +SAD16XN 16, 1 ; sad16x16_avg_sse2 +SAD16XN 8, 1 ; sad16x8_avg_sse2 +SAD16XN 4 ; sad_16x4_sse2 +SAD16XN 4, 1 ; sad_16x4_avg_sse2 +SAD16XN 64 ; sad_16x64_sse2 +SAD16XN 64, 1 ; sad_16x64_avg_sse2 + +; unsigned int aom_sad8x{8,16}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD8XN 1-2 0 + SAD_FN 8, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movh m1, [refq] + movhps m1, [refq+ref_strideq] + movh m2, [refq+ref_strideq*2] + movhps m2, [refq+ref_stride3q] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + lea second_predq, [second_predq+mmsize*2] +%endif + movh m3, [srcq] + movhps m3, [srcq+src_strideq] + movh m4, [srcq+src_strideq*2] + movhps m4, [srcq+src_stride3q] + psadbw m1, m3 + psadbw m2, m4 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + paddd m0, m2 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD8XN 16 ; sad8x16_sse2 +SAD8XN 8 ; sad8x8_sse2 +SAD8XN 4 ; sad8x4_sse2 +SAD8XN 16, 1 ; sad8x16_avg_sse2 +SAD8XN 8, 1 ; sad8x8_avg_sse2 +SAD8XN 4, 1 ; sad8x4_avg_sse2 +SAD8XN 32 ; sad_8x32_sse2 +SAD8XN 32, 1 ; sad_8x32_avg_sse2 + +; unsigned int aom_sad4x{4, 8}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD4XN 1-2 0 + SAD_FN 4, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movd m1, [refq] + movd m2, [refq+ref_strideq] + movd m3, [refq+ref_strideq*2] + movd m4, [refq+ref_stride3q] + punpckldq m1, m2 + punpckldq m3, m4 + movlhps m1, m3 +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + lea second_predq, [second_predq+mmsize*1] +%endif + movd m2, [srcq] + movd m5, [srcq+src_strideq] + movd m4, [srcq+src_strideq*2] + movd m3, [srcq+src_stride3q] + punpckldq m2, m5 + punpckldq m4, m3 + movlhps m2, m4 + psadbw m1, m2 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD4XN 8 ; sad4x8_sse +SAD4XN 4 ; sad4x4_sse +SAD4XN 8, 1 ; sad4x8_avg_sse +SAD4XN 4, 1 ; sad4x4_avg_sse +SAD4XN 16 ; sad_4x16_sse2 +SAD4XN 16, 1 ; sad_4x16_avg_sse2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,979 @@ +; Copyright (c) 2019, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 +maddubsw_hsub: times 16 db 1, -1 + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +; Perform 4x4 hadamard transform on input with 2 rows per register. +; Rows 0 and 2 are in m0 and rows 1 and 3 are in m1. +; A second set of packed input can also be taken in m2 and m3. +; Ends with sums in every other entry (i.e. already reduced horizontally). +%macro HADAMARD_4x4_PACKED 1 +%if %1 == 1 + %define tmp m2 + ; 2->0, 1->2, 0->2 + %define ROTATE SWAP 2, 1, 0 +%elif %1 == 2 + %define tmp m4 + ; 4->0, 3->2, 2->3, 1->2, 0->1 + %define ROTATE SWAP 4, 3, 2, 1, 0 +%endif + ; m0 d2 c2 b2 a2 d0 c0 b0 a0 + ; m1 d3 c3 b3 a3 d1 c1 b1 a1 + + ; Stage 1 + ; m0 d2+d3 c2+c3 b2+b3 a2+a3 d0+d1 c0+c1 b0+b1 a0+a1 + ; m1 d2-d3 c2-c3 b2-b3 a2-a3 d0-d1 c0-c1 b0-b1 a0-a1 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; Stage 2 + ; m0 d0-d1 d0+d1 c0-c1 c0+c1 b0-b1 b0+b1 a0-a1 a0+a1 + ; m1 d2-d3 d2+d3 c2-c3 c2+c3 b2-b3 b2+b3 a2-a3 a2+a3 + punpcklwd tmp, m0, m1 + punpckhwd m0, m1 +%if %1 == 2 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 +%endif + ROTATE + + ; m0 d0-d1+d2-d3 d0+d1+d2+d3 c0-c1+c2-c3 c0+c1+c2+c3 + ; b0-b1+b2-b3 b0+b1+b2+b3 a0-a1+a2-a3 a0+a1+a2+a3 + ; m1 d0-d2-d2+d3 d0+d1-d2-d3 c0-c1-c2+c3 c0+c1-c2-c3 + ; b0-b1-b2+b3 b0+b1-b2-b3 a0-a1-a2-a3 a0+a1-a2-a3 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; m0 s2 s0 r2 r0 q2 q0 p2 p0 + ; m1 s3 s1 r3 r1 q3 q1 p3 p1 + + ; Stage 1 + ; m0 q3 q1 q2 q0 p3 p1 p2 p0 + ; m1 s3 s1 s2 s0 r3 r1 r2 r0 + punpckldq tmp, m0, m1 + punpckhdq m0, m1 +%if %1 == 2 + punpckldq m1, m2, m3 + punpckhdq m2, m3 +%endif + ROTATE + + ; m0 q3+s3 q1+s1 q2+s2 q0+s0 p3+r3 p1+r1 p2+r2 p0+r0 + ; m1 q3-s3 q1-s1 q2-s2 q0-s0 p3-r3 p1-r1 p2-r2 p0-r0 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; Stage 2 + ; m0 p3-r3 p1-r1 p2-r2 p0-r0 p3+r3 p1+r1 p2+r2 p0+r0 + ; m1 q3-s3 q1-s1 q2-s2 q0-s0 q3+s3 q1+s1 q2+s2 q0+s0 + punpcklqdq tmp, m0, m1 + punpckhqdq m0, m1 +%if %1 == 2 + punpcklqdq m1, m2, m3 + punpckhqdq m2, m3 +%endif + ROTATE + + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw tmp, m0, m1 + pmaxsw m0, m1 + ; m1 is free + ; 0x7FFF + pcmpeqb m1, m1 + psrlw m1, 1 + + paddsw tmp, m1 + psubw m0, tmp +%if %1 == 2 + paddw tmp, m2, m3 + pmaxsw m2, m3 + paddsw tmp, m1 + psubw m2, tmp + + paddw m0, m2 +%endif +%endmacro + +; Load diffs of 4 entries for 2 rows +%macro LOAD_PACK_DIFF_Dx2 7 + movd m%1, %2 + movd m%6, %4 + punpckldq m%1, m%6 + pmovzxbw m%1, m%1 + movd m%6, %3 + movd m%7, %5 + punpckldq m%6, m%7 + pmovzxbw m%6, m%6 + psubw m%1, m%6 +%endmacro + +; Can only use 128-bit vectors +%macro SATD_4x4_FN 0 +cglobal satd_4x4, 4, 6, 4, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + + ; Load rows 0 and 2 to m0 and 1 and 3 to m1 + LOAD_PACK_DIFF_Dx2 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + 2, 3 + LOAD_PACK_DIFF_Dx2 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + 2, 3 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + pshufd m1, m0, q3232 + paddw m0, m1 + pshuflw m1, m0, q3232 + paddw m0, m1 + pshuflw m1, m0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw m0, m1 + movd eax, m0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 4 + RET +%endmacro + +INIT_XMM sse4 +SATD_4x4_FN + +INIT_XMM avx2 +SATD_4x4_FN + +; Load diffs of 8 entries for 2 row +; Each set of 4 columns share an 128-bit lane +%macro LOAD_PACK_DIFF_Qx2 7 + movq xm%1, %2 + movq xm%6, %4 + punpckldq xm%1, xm%6 + pmovzxbw m%1, xm%1 + movq xm%6, %3 + movq xm%7, %5 + punpckldq xm%6, xm%7 + pmovzxbw m%6, xm%6 + psubw m%1, m%6 +%endmacro + +INIT_YMM avx2 +cglobal satd_8x4, 4, 6, 4, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + ; Load rows 0 and 2 to m0 and 1 and 3 to m1 + ; Each set of 4 columns share 128-bit lanes + LOAD_PACK_DIFF_Qx2 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + 2, 3 + LOAD_PACK_DIFF_Qx2 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + 2, 3 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 8 + RET + +; Load diffs of 4 entries for 4 rows +; Each set of two rows share 128-bit lanes +%macro LOAD_PACK_DIFF_Dx4 12 + movd xm%1, %2 + movd xm%10, %4 + punpckldq xm%1, xm%10 + movd xm%10, %6 + movd xm%11, %8 + punpckldq xm%10, xm%11 + punpcklqdq xm%1, xm%10 + pmovzxbw m%1, xm%1 + movd xm%10, %3 + movd xm%11, %5 + punpckldq xm%10, xm%11 + movd xm%11, %7 + movd xm%12, %9 + punpckldq xm%11, xm%12 + punpcklqdq xm%10, xm%11 + pmovzxbw m%10, xm%10 + psubw m%1, m%10 +%endmacro + +INIT_YMM avx2 +cglobal satd_4x8, 4, 8, 5, src, src_stride, dst, dst_stride, \ + src4, dst4, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src4q, [srcq+src_strideq*4] + lea dst4q, [dstq+dst_strideq*4] + ; Load rows 0, 2, 4 and 6 to m0 and 1, 3, 5 and 7 to m1. + ; Lanes split the low and high rows of m0 and m1. + LOAD_PACK_DIFF_Dx4 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 2, 3, 4 + LOAD_PACK_DIFF_Dx4 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 2, 3, 4 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation. + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + sub ax, 8 + RET + +; Rudimentary fast hadamard transform +; Two Hadamard transforms share an 128-bit lane. +%macro HADAMARD_4x4 0 + ; 4->0, 3->2, 2->3, 1->2, 0->1 + %define ROTATE SWAP 4, 3, 2, 1, 0 + + ; Stage 1 + paddw m0, m1, m2 + psubw m1, m2 + paddw m2, m3, m4 + psubw m3, m4 + ROTATE + + ; Stage 2 + paddw m0, m1, m3 + psubw m1, m3 + paddw m3, m2, m4 + psubw m2, m4 + SWAP 3, 2, 1 + ROTATE + + ; Transpose + ; Since two transforms share an 128-bit lane, unpacking results in a single + ; transform's values on each register. This has to be resolved later. + ; A and B indicate different 4x4 transforms. + + ; Start + ; m1 B (a3 a2 a1 a0) A (a3 a2 a1 a0) + ; m2 B (b3 b2 b1 b0) A (b3 b2 b1 b0) + ; m3 B (c3 c2 c1 c0) A (c3 c2 c1 c0) + ; m4 B (d3 d2 d1 d0) A (d3 d2 d1 d0) + + ; Stage 1 + ; m1 A (b3 a3 b2 a2 b1 a1 b0 a0) + ; m2 B (b3 a3 b2 a2 b1 a1 b0 a0) + ; m3 A (d3 c3 d2 c2 d1 c1 d0 c0) + ; m4 B (d3 c3 d2 c2 d1 c1 d0 c0) + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + punpcklwd m2, m3, m4 + punpckhwd m3, m4 + ROTATE + + ; m1 A (d3 c3 b3 a3 d2 c2 b2 a2) + ; m2 A (d1 c1 b1 a1 d0 c0 b0 a0) + ; m3 B (d3 c3 b3 a3 d2 c2 b2 a2) + ; m4 B (d1 c1 b1 a1 d0 c0 b0 a0) + punpckldq m0, m1, m3 + punpckhdq m1, m3 + punpckldq m3, m2, m4 + punpckhdq m2, m4 + SWAP 3, 2, 1 + ROTATE + + ; Make the transforms share 128-bit lanes again. + ; m1 B (d0 c0 b0 a0) A (d0 c0 b0 a0) + ; m2 B (d1 c1 b1 a1) A (d1 c1 b1 a1) + ; m3 B (d2 c2 b2 a2) A (d2 c2 b2 a2) + ; m4 B (d3 c3 b3 a3) A (d3 c3 b3 a3) + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + ROTATE + + ; Stage 1 + paddw m0, m1, m2 + psubw m1, m2 + paddw m2, m3, m4 + psubw m3, m4 + ROTATE + + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw m0, m1, m3 + pmaxsw m1, m3 + ; m2 is free + ; 0x7FFF + pcmpeqb m3, m3 + psrlw m3, 1 + + paddsw m0, m3 + psubw m1, m0 + + paddw m0, m2, m4 + pmaxsw m2, m4 + paddsw m0, m3 + psubw m2, m0 + + paddw m1, m2 + SWAP 1, 0 +%endmacro + +; Load diffs of 16 entries for 1 row +%macro LOAD_DIFF_DQ 4 + movu xm%1, %2 + movu xm%4, %3 + vpmovzxbw m%1, xm%1 + vpmovzxbw m%4, xm%4 + psubw m%1, m%4 +%endmacro + +INIT_YMM avx2 +cglobal satd_16x4, 4, 6, 5, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_4x4 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + ; Avoids overflow in this case + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 16 + RET + +INIT_YMM avx2 +cglobal satd_4x16, 4, 8, 7, src, src_stride, dst, dst_stride, \ + src4, dst4, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src4q, [srcq+src_strideq*4] + lea dst4q, [dstq+dst_strideq*4] + LOAD_PACK_DIFF_Dx4 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 4, 5, 6 + LOAD_PACK_DIFF_Dx4 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 4, 5, 6 + lea srcq, [srcq+src_strideq*8] + lea dstq, [dstq+dst_strideq*8] + lea src4q, [src4q+src_strideq*8] + lea dst4q, [dst4q+dst_strideq*8] + LOAD_PACK_DIFF_Dx4 2, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 4, 5, 6 + LOAD_PACK_DIFF_Dx4 3, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 4, 5, 6 + HADAMARD_4x4_PACKED 2 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 16 + RET + +; On x86-64 we can transpose in-place without spilling registers. +; By clever choices of the order to apply the butterflies and the order of +; their outputs, we can take the rows in order and output the columns in order +; without any extra operations and using just one temporary register. +%macro TRANSPOSE8x8 9 + punpckhwd m%9, m%5, m%6 + punpcklwd m%5, m%6 + ; m%6 is free + punpckhwd m%6, m%1, m%2 + punpcklwd m%1, m%2 + ; m%2 is free + punpckhwd m%2, m%7, m%8 + punpcklwd m%7, m%8 + ; m%8 is free + punpckhwd m%8, m%3, m%4 + punpcklwd m%3, m%4 + ; m%4 is free + punpckhdq m%4, m%1, m%3 + punpckldq m%1, m%3 + ; m%3 is free + punpckldq m%3, m%5, m%7 + punpckhdq m%5, m%7 + ; m%7 is free + punpckhdq m%7, m%6, m%8 + punpckldq m%6, m%8 + ; m%8 is free + punpckldq m%8, m%9, m%2 + punpckhdq m%9, m%2 + ; m%2 is free + punpckhqdq m%2, m%1, m%3 + punpcklqdq m%1, m%3 + ; m%3 is free + punpcklqdq m%3, m%4, m%5 + punpckhqdq m%4, m%5 + ; m%5 is free + punpcklqdq m%5, m%6, m%8 + punpckhqdq m%6, m%8 + ; m%8 is free + punpckhqdq m%8, m%7, m%9 + punpcklqdq m%7, m%9 +%endmacro + +; Load diff of 8 entries for 1 row +%macro LOAD_DIFF_Q 4 + movq %1, %2 + movq %4, %3 + punpcklbw %1, %4 + pmaddubsw %1, hsub +%endmacro + +%macro HADAMARD_8_STAGE_1 9 + paddw m%9, m%1, m%2 + psubw m%1, m%2 + paddw m%2, m%3, m%4 + psubw m%3, m%4 + paddw m%4, m%5, m%6 + psubw m%5, m%6 + paddw m%6, m%7, m%8 + psubw m%7, m%8 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +%macro HADAMARD_8_STAGE_2 9 + paddw m%9, m%1, m%3 ; 0 + psubw m%1, m%3 ; 2 + paddw m%3, m%2, m%4 ; 1 + psubw m%2, m%4 ; 3 + SWAP %3, %2, %1 + paddw m%4, m%5, m%7 ; 4 + psubw m%5, m%7 ; 6 + paddw m%7, m%6, m%8 ; 5 + psubw m%6, m%8 ; 7 + SWAP %7, %6, %5 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +%macro HADAMARD_8_STAGE_3 9 + paddw m%9, m%1, m%5 ; 0 + psubw m%1, m%5 ; 4 + paddw m%5, m%2, m%6 ; 1 + psubw m%2, m%6 ; 5 + paddw m%6, m%3, m%7 ; 2 + psubw m%3, m%7 ; 6 + paddw m%7, m%4, m%8 ; 3 + psubw m%4, m%8 ; 7 + SWAP %5, %2, %6, %3, %7, %4, %1 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +; Rudimentary fast hadamard transform +%macro HADAMARD_8x8 0 + HADAMARD_8_STAGE_1 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_2 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_3 1, 2, 3, 4, 5, 6, 7, 8, 0 + + TRANSPOSE8x8 1, 2, 3, 4, 5, 6, 7, 8, 0 + + HADAMARD_8_STAGE_1 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_2 1, 2, 3, 4, 5, 6, 7, 8, 0 + + ; Stage 3 + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw m0, m1, m5 + pmaxsw m1, m5 + ; m1 is free + ; 0x7FFF + pcmpeqb m5, m5 + psrlw m5, 1 + + paddsw m0, m5 + psubw m1, m0 + + paddw m0, m2, m6 + pmaxsw m2, m6 + paddsw m0, m5 + psubw m2, m0 + + paddw m0, m3, m7 + pmaxsw m3, m7 + paddsw m0, m5 + psubw m3, m0 + + paddw m0, m4, m8 + pmaxsw m4, m8 + paddsw m0, m5 + psubw m4, m0 + + paddw m1, m2 + paddw m3, m4 + + paddw m1, m3 + SWAP 1, 0 +%endmacro + +; Only works with 128 bit vectors +%macro SATD_8x8_FN 0 +cglobal satd_8x8, 4, 6, 10, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_Q m1, [srcq], [dstq], m2 + LOAD_DIFF_Q m2, [srcq+src_strideq*1], [dstq+dst_strideq*1], m3 + LOAD_DIFF_Q m3, [srcq+src_strideq*2], [dstq+dst_strideq*2], m4 + LOAD_DIFF_Q m4, [srcq+src_stride3q], [dstq+dst_stride3q], m5 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_Q m5, [srcq], [dstq], m6 + LOAD_DIFF_Q m6, [srcq+src_strideq*1], [dstq+dst_strideq*1], m7 + LOAD_DIFF_Q m7, [srcq+src_strideq*2], [dstq+dst_strideq*2], m8 + LOAD_DIFF_Q m8, [srcq+src_stride3q], [dstq+dst_stride3q], m9 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + pshufd m1, m0, q3232 + paddd m0, m1 + pshuflw m1, m0, q3232 + paddd m0, m1 + movd eax, m0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 32-2 + shr eax, 2 + RET +%endmacro + +INIT_XMM ssse3 +SATD_8x8_FN + +INIT_XMM avx2 +SATD_8x8_FN + +INIT_YMM avx2 +cglobal satd_16x8, 4, 6, 9, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + ; Load rows into m1-m8 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_DQ 5, [srcq], [dstq], 0 + LOAD_DIFF_DQ 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 8, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 64-2 + shr eax, 2 + RET + +%macro LOAD_DIFF_Qx2 7 + movq xm%1, %2 + movq xm%6, %3 + punpcklbw xm%1, xm%6 + movq xm%6, %4 + movq xm%7, %5 + punpcklbw xm%6, xm%7 + vinserti128 m%1, xm%6, 1 + pmaddubsw m%1, hsub +%endmacro + +INIT_YMM avx2 +cglobal satd_8x16, 4, 8, 11, src, src_stride, dst, dst_stride, \ + src8, dst8, src_stride3, dst_stride3 + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + lea src8q, [srcq+src_strideq*8] + lea dst8q, [dstq+dst_strideq*8] + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_Qx2 1, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 4, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + lea src8q, [src8q+src_strideq*4] + lea dst8q, [dst8q+dst_strideq*4] + LOAD_DIFF_Qx2 5, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 8, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 64-2 + shr eax, 2 + RET + +; Less optimized, boilerplate implementations + +INIT_YMM avx2 +cglobal satd_8x32, 4, 9, 13, src, src_stride, dst, dst_stride, \ + src8, dst8, src_stride3, dst_stride3, cnt + ; ones for converting to 32-bit with pmaddwd + pcmpeqw m11, m11 + pabsw m11, m11 + ; sum + pxor m12, m12 + mov cntd, 1 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src8q, [srcq+src_strideq*8] + lea dst8q, [dstq+dst_strideq*8] +.loop: + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + LOAD_DIFF_Qx2 1, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 4, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + lea src8q, [src8q+src_strideq*4] + lea dst8q, [dst8q+dst_strideq*4] + LOAD_DIFF_Qx2 5, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 8, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pmaddwd m0, m11 + paddd m12, m0 + + lea srcq, [srcq+src_stride3q*4] + lea dstq, [dstq+dst_stride3q*4] + lea src8q, [src8q+src_stride3q*4] + lea dst8q, [dst8q+dst_stride3q*4] + dec cntd + jge .loop + + vextracti128 xm0, m12, 1 + paddd xm0, xm12 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 128-2 + shr eax, 2 + RET + +INIT_YMM avx2 +cglobal satd_16x8_internal, 0, 0, 0, \ + dummy1, src_stride, dummy2, dst_stride, \ + src_stride3, dst_stride3, src, dst + %define hadd m9 + %define sum m10 + ; Load rows into m1-m8 + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_DQ 5, [srcq], [dstq], 0 + LOAD_DIFF_DQ 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 8, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_8x8 + + pmaddwd m0, hadd + paddd sum, m0 + ret + +%macro SATD_NXM 2 +%if %1 > 16 +%if %2 > 8 +cglobal satd_%1x%2, 4, 10, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + w, h +%else +cglobal satd_%1x%2, 4, 9, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + w +%endif +%else ; %2 > 8 +cglobal satd_%1x%2, 4, 9, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + h +%endif + ; ones for converting to 32-bit with pmaddwd + pcmpeqw m9, m9 + pabsw m9, m9 + ; sum + pxor m10, m10 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] +%if %2 > 8 + mov hd, %2/8 - 1 +.looph: +%endif +%if %1 > 16 + mov wd, %1/16 - 1 +.loopv: +%endif + mov call_srcq, srcq + mov call_dstq, dstq + call m(satd_16x8_internal) +%if %1 > 16 + add srcq, 16 + add dstq, 16 + dec wd + jge .loopv + sub srcq, %1 + sub dstq, %1 +%endif +%if %2 > 8 + lea srcq, [srcq+src_strideq*8] + lea dstq, [dstq+dst_strideq*8] + dec hd + jge .looph +%endif + + ; Reduce horizontally + vextracti128 xm0, m10, 1 + paddd xm0, xm10 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, %1*%2/2 - 2 + shr eax, 2 + RET +%endmacro + +INIT_YMM avx2 +SATD_NXM 16, 16 +SATD_NXM 32, 32 +SATD_NXM 64, 64 +SATD_NXM 128, 128 + +SATD_NXM 16, 32 +SATD_NXM 32, 16 +SATD_NXM 32, 64 +SATD_NXM 64, 32 +SATD_NXM 64, 128 +SATD_NXM 128, 64 + +SATD_NXM 32, 8 +SATD_NXM 16, 64 +SATD_NXM 64, 16 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/satd16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1129 @@ +; Copyright (c) 2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +align 32 +pw_1x16: times 16 dw 1 + +SECTION .text + +%macro NORMALIZE4PT 0 + add eax, 2 + shr eax, 2 +%endmacro + +%macro NORMALIZE8PT 0 + add eax, 4 + shr eax, 3 +%endmacro + +; Add and subtract registers +; +; Takes m0 and m1 as both input and output. +; Requires m2 as a free register. +; +; If we start with this permutation: +; +; m0 0 1 2 3 4 5 6 7 +; m1 8 9 10 11 12 13 14 15 +; +; Then the output will be as such: +; +; m0 [0+8][1+9][2+10][3+11] [4+12][5+13][6+14][7+15] +; m1 [0-8][1-9][2-10][3-11] [4-12][5-13][6-14][7-15] +%macro BUTTERFLY 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + ; use alternate registers 3,4,5 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 32 + %define V ym + %elif VEC_SIZE == 16 + %define V xm + %endif + + ; Use m2 as a temporary register, then swap + ; so that m0 and m1 contain the output. + %if BIT_PRECISION == 16 + paddw V%+ 2, V%+ 0, V%+ 1 + psubw V%+ 0, V%+ 1 + %elif BIT_PRECISION == 32 + paddd ym2, ym0, ym1 + psubd ym0, ym1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + + SWAP 2, 1, 0 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +; Interleave packed rows together (in m0 and m1). +; m2 should contain a free register. +; +; Macro argument takes size in bits of each element (where one +; element is the difference between two original source pixels). +; +; If we start with this permutation: +; +; m0 0 1 2 3 4 5 6 7 +; m1 8 9 10 11 12 13 14 15 +; +; Then, after INTERLEAVE, this will be the permutation: +; +; m0 0 8 1 9 2 10 3 11 +; m1 4 12 5 13 6 14 7 15 +%macro INTERLEAVE 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + %if BIT_PRECISION == 16 + punpcklwd V%+ 2, V%+ 0, V%+ 1 + punpckhwd V%+ 0, V%+ 1 + SWAP 2, 1, 0 + %elif BIT_PRECISION == 32 + punpckldq ym2, ym0, ym1 + punpckhdq ym0, ym1 + ; AVX2 shuffles operate over 128-bit halves of the full ymm register + ; in parallel, so these shuffles are required to fix up the permutation. + vperm2i128 ym1, ym2, ym0, 0x20 + vperm2i128 ym0, ym2, ym0, 0x31 + SWAP 0, 1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +; Interleave pairs of 2 elements (in m0 and m1) +; m2 should contain a free register. +%macro INTERLEAVE_PAIRS 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + %if BIT_PRECISION == 16 + punpckldq V%+ 2, V%+ 0, V%+ 1 + punpckhdq V%+ 0, V%+ 1 + %elif BIT_PRECISION == 32 + punpcklqdq ym2, ym0, ym1 + punpckhqdq ym0, ym1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + SWAP 2, 1, 0 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +%macro HADAMARD_4X4_PACKED 2 + %define BIT_PRECISION %1 + ; Register size to use (in bytes) + %define VEC_SIZE %2 + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + ; Starting registers: + + ; m0 0 1 2 3 + ; m1 4 5 6 7 + ; m2 8 9 10 11 + ; m3 12 13 14 15 + + ; Where each number represents an index of the + ; original block of differences. + + ; Pack rows 0,2 and 1,3 into m0 and m1 + %if BIT_PRECISION == 16 + %if VEC_SIZE == 16 + ; In this case, each row only has 64 bits, so we use + ; punpcklqdq only. The high 64 bits are always 0. + punpcklqdq xm0, xm2 + punpcklqdq xm1, xm3 + %elif VEC_SIZE == 32 + ; The upper 128 bits of all input registers are zeroed + punpcklqdq m4, m0, m2 + punpcklqdq m5, m1, m3 + punpckhqdq m0, m0, m2 + punpckhqdq m1, m1, m3 + vinserti128 m0, m4, xm0, 1 + vinserti128 m1, m5, xm1, 1 + %endif + %elif BIT_PRECISION == 32 + vinserti128 ym0, ym0, xm2, 1 + vinserti128 ym1, ym1, xm3, 1 + %else + %error Invalid bit precision (expected 16 or 32) + %endif + + ; Now that we've packed rows 0-2 and 1-3 together, + ; this is our permutation: + + ; m0 0 1 2 3 8 9 10 11 + ; m1 4 5 6 7 12 13 14 15 + + ; For a 8x4 transform (with 16-bit coefficients), this pattern is + ; extended for each 128-bit half but for the second block, and thus + ; all comments also apply to the upper 128-bits for the 8x4 transform. + + BUTTERFLY %1, %2, 0 + + ; m0 [0+4][1+5][2+6][3+7] [8+12][9+13][10+14][11+15] + ; m1 [0-4][1-5][2-6][3-7] [8-12][9-13][10-14][11-15] + + INTERLEAVE %1, %2, 0 + + ; m0 [ 0+4][ 0-4][ 1+5][ 1-5] [2 + 6][2 - 6][3 + 7][3 - 7] + ; m1 [8+12][8-12][9+13][9-13] [10+14][10-14][11+15][11-15] + + BUTTERFLY %1, %2, 0 + + ; m0 [0+4+8+12][0-4+8-12][1+5+9+13][1-5+9-13] [2+6+10+14][2-6+10-14][3+7+11+15][3-7+11-15] + ; m1 [0+4-8-12][0-4-8+12][1+5-9-13][1-5-9+13] [2+6-10-14][2-6-10+14][3+7-11-15][3-7-11+15] + + ; for one row: + ; [0+1+2+3][0-1+2-3][0+1-2-3][0-1-2+3] + ; For the vertical transform, these are packed into a new column. + + INTERLEAVE_PAIRS %1, %2, 0 + + ; p0 p1 p2 p3 + ; m0 [0+4+ 8+12][0-4+ 8-12][0+4- 8-12][0-4- 8+12] [1+5+ 9+13][1-5+ 9-13][1+5- 9-13][1-5- 9+13] + ; m1 [2+6+10+14][2-6+10-14][2+6-10-14][2-6-10+14] [3+7+11+15][3-7+11-15][3+7-11-15][3-7-11+15] + + ; According to this grid: + + ; p0 q0 r0 s0 + ; p1 q1 r1 s1 + ; p2 q2 r2 s2 + ; p3 q3 r3 s3 + + ; Horizontal transform; since the output is transposed from the original order, + ; we can do the same steps as the vertical transform and the result will be the same. + BUTTERFLY %1, %2, 0 + INTERLEAVE %1, %2, 0 + BUTTERFLY %1, %2, 0 + + ; Finished horizontal transform except for the last step (interleaving pairs), + ; which we skip, because after this we add up the absolute value of the + ; coefficients, which is a commutative operation (order does not matter). +%endmacro + +; Horizontal sum of mm register +; +; Inputs: +; %1 = Element size in bits (16 or 32) +; %2 = Size of input register in bytes (16 or 32) +; You can e.g. pass 16 for this argument if you +; only want to sum up the bottom 128-bits of a +; ymm register. +; %3 = Input register number +; %4 = Temporary register number +; %5 = Output register (e.g., eax) +%macro HSUM 5 + %define E_SIZE %1 + %define REG_SIZE %2 + %define INPUT %3 + %define TMP %4 + %define OUTPUT %5 + + %if REG_SIZE == 16 + %define V xm + %elif REG_SIZE == 32 + %define V ym + %else + %error Invalid register size (expected 16 or 32) + %endif + + %if E_SIZE == 16 + ; Add adjacent pairs of 16-bit elements to produce 32-bit results, + ; then proceed with 32-bit sum + pmaddwd V%+INPUT, [pw_1x16] + %endif + + %if mmsize == 32 && REG_SIZE == 32 + ; Add upper half of ymm to xmm + vextracti128 xm%+TMP, ym%+INPUT, 1 + paddd xm%+INPUT, xm%+TMP + %endif + + ; Reduce 32-bit results + pshufd xm%+TMP, xm%+INPUT, q2323 + paddd xm%+INPUT, xm%+TMP + pshufd xm%+TMP, xm%+INPUT, q1111 + paddd xm%+INPUT, xm%+TMP + movd OUTPUT, xm%+INPUT +%endmacro + +; given m0-7, do butterfly as follows: +; (m0, m1) = butterfly(m0, m1) +; (m2, m3) = butterfly(m2, m3) +; (m4, m5) = butterfly(m4, m5) +; (m6, m7) = butterfly(m6, m7) +%macro BUTTERFLY_8X8 0 + ; m8 is free + paddd m8, m0, m1 + psubd m0, m1 + SWAP 8, 1, 0 + + ; m8 is free + paddd m8, m2, m3 + psubd m2, m3 + SWAP 8, 3, 2 + + paddd m8, m4, m5 + psubd m4, m5 + SWAP 8, 5, 4 + + paddd m8, m6, m7 + psubd m6, m7 + SWAP 8, 7, 6 +%endmacro + +%macro HADAMARD_8X8_VERTICAL 0 + BUTTERFLY_8X8 + ; m0-7 contain a0-7 + + SWAP 2, 1 + SWAP 6, 5 + + BUTTERFLY_8X8 + + SWAP 1, 4 + SWAP 3, 6 + + BUTTERFLY_8X8 + + SWAP 2, 1 + SWAP 2, 4 + SWAP 3, 6 + SWAP 5, 6 +%endmacro + +; Transpose rows m0-7. +; Output is also contained in m0-7. +; +; Uses m8, m10-15 as temporary registers (i.e. m9 is left unchanged.) +%macro TRANSPOSE8X8D 0 + SWAP 9, 0 + SWAP 10, 1 + SWAP 11, 2 + SWAP 12, 3 + SWAP 13, 4 + SWAP 14, 5 + SWAP 15, 6 + SWAP 2, 7 + + punpckldq m6, m9, m10 + punpckldq m1, m11, m12 + punpckhdq m8, m9, m10 + punpckldq m4, m13, m14 + punpckldq m9, m15, m2 + vshufps m3, m6, m1, 0x4e + vpblendd m10, m6, m3, 0xcc + vshufps m6, m4, m9, 0x4e + punpckhdq m7, m11, m12 + vpblendd m11, m4, m6, 0xcc + vpblendd m12, m3, m1, 0xcc + vperm2i128 m3, m10, m11, 0x20 + punpckhdq m5, m13, m14 + vpblendd m13, m6, m9, 0xcc + punpckhdq m4, m15, m2 + vperm2i128 m2, m12, m13, 0x20 + vshufps m14, m8, m7, 0x4e + vpblendd m15, m14, m7, 0xcc + vshufps m7, m5, m4, 0x4e + vpblendd m8, m8, m14, 0xcc + vpblendd m5, m5, m7, 0xcc + vperm2i128 m6, m8, m5, 0x20 + vpblendd m4, m7, m4, 0xcc + vperm2i128 m7, m15, m4, 0x20 + vperm2i128 m1, m10, m11, 0x31 + vperm2i128 m9, m12, m13, 0x31 + vperm2i128 m5, m8, m5, 0x31 + vperm2i128 m4, m15, m4, 0x31 + + SWAP 0, 9 + + ; Output order is as follows: + ; 3 2 6 7 1 0 5 4 + + ; sort rows + SWAP 3, 0 + ; 0 2 6 7 1 3 5 4 + SWAP 1, 2 + ; 0 1 6 7 2 3 5 4 + SWAP 6, 2 + ; 0 1 2 7 6 3 5 4 + SWAP 7, 3 + ; 0 1 2 3 6 7 5 4 + SWAP 6, 4 + ; 0 1 2 3 4 7 5 6 + SWAP 7, 5 + ; 0 1 2 3 4 5 7 6 + SWAP 6, 7 + ; 0 1 2 3 4 5 6 7 +%endmacro + +; m0-7 as input; add coefficients to ymm9. +INIT_YMM avx2 +cglobal satd_8x8_hbd_internal, 0, 0, 0, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + HADAMARD_8X8_VERTICAL + + TRANSPOSE8X8D + + HADAMARD_8X8_VERTICAL + + REPX {pabsd x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + + ; Add m0-7 + paddd m0, m4 + paddd m1, m5 + paddd m2, m6 + paddd m3, m7 + + paddd m0, m2 + paddd m1, m3 + + paddd m0, m1 + paddd ymm9, m0 + ret + +%macro LOAD_DIFF_8X8 0 + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + movu xm4, [srcq + 0*src_strideq] + movu xm5, [srcq + 1*src_strideq] + movu xm6, [srcq + 2*src_strideq] + movu xm7, [srcq + src_stride3q ] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + + pmovsxwd m0, xm0 + pmovsxwd m1, xm1 + pmovsxwd m2, xm2 + pmovsxwd m3, xm3 + pmovsxwd m4, xm4 + pmovsxwd m5, xm5 + pmovsxwd m6, xm6 + pmovsxwd m7, xm7 +%endmacro + +INIT_YMM avx2 +cglobal satd_8x8_hbd, 5, 7, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + LOAD_DIFF_8X8 + + ; m0-7 contain rows of 8x8 block to transform + ; with 32-bit coefficients + + HADAMARD_8X8_VERTICAL + + TRANSPOSE8X8D + + HADAMARD_8X8_VERTICAL + + REPX {pabsd x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + + ; Add m0-7 + paddd m0, m4 + paddd m1, m5 + paddd m2, m6 + paddd m3, m7 + + paddd m0, m2 + paddd m1, m3 + + paddd m0, m1 + + HSUM 32, 32, 0, 1, eax + NORMALIZE8PT + RET + +INIT_YMM avx2 +cglobal satd_4x4_hbd, 5, 7, 8, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + + ; src -= dst + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + + HADAMARD_4X4_PACKED 16, 16 + + ; Sum up absolute value of transform coefficients + pabsw xm0, xm0 + pabsw xm1, xm1 + paddw xm0, xm1 + HSUM 16, 16, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + ; this gives a nicer disassembly + RESET_MM_PERMUTATION + + ; Load src rows + pmovzxwd xm0, [srcq + 0*src_strideq] + pmovzxwd xm1, [srcq + 1*src_strideq] + pmovzxwd xm2, [srcq + 2*src_strideq] + pmovzxwd xm3, [srcq + src_stride3q ] + + ; Load dst rows + pmovzxwd xm4, [dstq + 0*dst_strideq] + pmovzxwd xm5, [dstq + 1*dst_strideq] + pmovzxwd xm6, [dstq + 2*dst_strideq] + pmovzxwd xm7, [dstq + dst_stride3q ] + + ; src -= dst + psubd xm0, xm4 + psubd xm1, xm5 + psubd xm2, xm6 + psubd xm3, xm7 + + HADAMARD_4X4_PACKED 32, 32 + + pabsd m0, m0 + pabsd m1, m1 + paddd m0, m1 + HSUM 32, 32, 0, 1, eax + NORMALIZE4PT + RET + +; 32-bit input rows are in m0-3; result is in m0. +; Uses m0-5 as temporary registers. +%macro HADAMARD_8X4_12BPC 0 + vperm2i128 m4, m0, m2, 0x31 + vperm2i128 m5, m1, m3, 0x31 + vinserti128 m0, m0, xm2, 1 + vinserti128 m1, m1, xm3, 1 + + ; Swap so m3,m4 are used as inputs. + SWAP 3, 4, 5 + + ; instead of using HADAMARD_4X4_PACKED twice, we interleave + ; 2 transforms operating over different registers for more + ; opportunity for instruction level parallelism. + + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE 32, 32, 0 + INTERLEAVE 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE_PAIRS 32, 32, 0 + INTERLEAVE_PAIRS 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE 32, 32, 0 + INTERLEAVE 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + + pabsd m0, m0 + pabsd m1, m1 + pabsd m3, m3 + pabsd m4, m4 + + paddd m0, m1 + paddd m3, m4 + paddd m0, m3 +%endmacro + +INIT_YMM avx2 +cglobal satd_16x4_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movu m0, [srcq + 0*src_strideq] + movu m1, [srcq + 1*src_strideq] + movu m2, [srcq + 2*src_strideq] + movu m3, [srcq + src_stride3q ] + + ; src -= dst + psubw m0, [dstq + 0*dst_strideq] + psubw m1, [dstq + 1*dst_strideq] + psubw m2, [dstq + 2*dst_strideq] + psubw m3, [dstq + dst_stride3q ] + +.10bpc_main: + + ; Original permutation + ; m0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + ; m1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + ; m2 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 + ; m3 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + + ; Two registers perform 2 4x4 transforms in parallel + + punpcklqdq m4, m0, m2 + punpcklqdq m5, m1, m3 + + punpckhqdq m0, m0, m2 + punpckhqdq m1, m1, m3 + + SWAP 4, 3 + SWAP 5, 4 + + ; New permutation + ; m0 0 1 2 3 32 33 34 35 8 9 10 11 40 41 42 43 + ; m1 16 17 18 19 48 49 50 51 24 25 26 27 56 57 58 59 + ; m3 4 5 6 7 36 37 38 39 12 13 14 15 44 45 46 47 + ; m4 20 21 22 23 52 53 54 55 28 29 30 31 60 61 62 63 + + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE 16, 32, 0 + INTERLEAVE 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE_PAIRS 16, 32, 0 + INTERLEAVE_PAIRS 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE 16, 32, 0 + INTERLEAVE 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + + pabsw m0, m0 + pabsw m1, m1 + pabsw m3, m3 + pabsw m4, m4 + + paddw m0, m1 + paddw m3, m4 + paddw m0, m3 + + HSUM 16, 32, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + RESET_MM_PERMUTATION + + mov bdmaxd, 2 + pxor m6, m6 +.12bpc_loop: + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + + pmovsxwd m0, xm0 + pmovsxwd m1, xm1 + pmovsxwd m2, xm2 + pmovsxwd m3, xm3 + + add srcq, 16 + add dstq, 16 + + HADAMARD_8X4_12BPC + paddd m6, m0 + dec bdmaxd + jnz .12bpc_loop + + HSUM 32, 32, 6, 1, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_4x16_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; BLOCK 1 + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; BLOCK 2 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + ; BLOCK 3 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; BLOCK 4 + movq xm8, [srcq + 0*src_strideq] + movq xm9, [srcq + 1*src_strideq] + movq xm10, [srcq + 2*src_strideq] + movq xm11, [srcq + src_stride3q ] + + psubw xm8, [dstq + 0*dst_strideq] + psubw xm9, [dstq + 1*dst_strideq] + psubw xm10, [dstq + 2*dst_strideq] + psubw xm11, [dstq + dst_stride3q ] + + vinserti128 m4, m4, xm8, 1 + vinserti128 m5, m5, xm9, 1 + vinserti128 m6, m6, xm10, 1 + vinserti128 m7, m7, xm11, 1 + + punpcklqdq m0, m0, m4 + punpcklqdq m1, m1, m5 + punpcklqdq m2, m2, m6 + punpcklqdq m3, m3, m7 + + jmp m(satd_16x4_hbd).10bpc_main + +.12bpc: + mov bdmaxd, 2 + pxor m8, m8 + +.12bpc_loop: + ; BLOCK 1 + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + pmovsxwd xm0, xm0 + pmovsxwd xm1, xm1 + pmovsxwd xm2, xm2 + pmovsxwd xm3, xm3 + + ; BLOCK 2 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + pmovsxwd xm4, xm4 + pmovsxwd xm5, xm5 + pmovsxwd xm6, xm6 + pmovsxwd xm7, xm7 + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + HADAMARD_8X4_12BPC + paddd m8, m0 + dec bdmaxd + jnz .12bpc_loop + + HSUM 32, 32, 8, 0, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_8x4_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + + ; src -= dst + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + +.10bpc_main: + HADAMARD_4X4_PACKED 16, 32 + + pabsw m0, m0 + pabsw m1, m1 + paddw m0, m1 + HSUM 16, 32, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + RESET_MM_PERMUTATION + + pmovzxwd m0, [srcq + 0*src_strideq] + pmovzxwd m1, [srcq + 1*src_strideq] + pmovzxwd m2, [srcq + 2*src_strideq] + pmovzxwd m3, [srcq + src_stride3q ] + + pmovzxwd m4, [dstq + 0*dst_strideq] + pmovzxwd m5, [dstq + 1*dst_strideq] + pmovzxwd m6, [dstq + 2*dst_strideq] + pmovzxwd m7, [dstq + dst_stride3q ] + + ; src -= dst + psubd m0, m4 + psubd m1, m5 + psubd m2, m6 + psubd m3, m7 + +.12bpc_main: + HADAMARD_8X4_12BPC + HSUM 32, 32, 0, 1, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_4x8_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + + ; This loads past the number of elements we are technically supposed + ; to read, however, this should still be safe, since at least one + ; valid element is in the memory address. + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + + punpcklqdq xm0, xm0, xm4 + punpcklqdq xm1, xm1, xm5 + punpcklqdq xm2, xm2, xm6 + punpcklqdq xm3, xm3, xm7 + + ; Jump to HADAMARD_4X4_PACKED in 8x4 satd, this saves us some binary size + ; by deduplicating the shared code. + jmp m(satd_8x4_hbd).10bpc_main + ; No return; we return in the other function. + +.12bpc: + RESET_MM_PERMUTATION + + pmovzxwd xm0, [srcq + 0*src_strideq] + pmovzxwd xm1, [srcq + 1*src_strideq] + pmovzxwd xm2, [srcq + 2*src_strideq] + pmovzxwd xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + pmovzxwd xm4, [dstq + 0*dst_strideq] + pmovzxwd xm5, [dstq + 1*dst_strideq] + pmovzxwd xm6, [dstq + 2*dst_strideq] + pmovzxwd xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; src -= dst + psubd xm0, xm4 + psubd xm1, xm5 + psubd xm2, xm6 + psubd xm3, xm7 + + pmovzxwd xm4, [srcq + 0*src_strideq] + pmovzxwd xm5, [srcq + 1*src_strideq] + pmovzxwd xm6, [srcq + 2*src_strideq] + pmovzxwd xm7, [srcq + src_stride3q ] + + pmovzxwd xm8, [dstq + 0*dst_strideq] + pmovzxwd xm9, [dstq + 1*dst_strideq] + pmovzxwd xm10, [dstq + 2*dst_strideq] + pmovzxwd xm11, [dstq + dst_stride3q ] + + ; src -= dst (second block) + psubd xm4, xm8 + psubd xm5, xm9 + psubd xm6, xm10 + psubd xm7, xm11 + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + ; Jump to HADAMARD_4X4_PACKED in 8x4 satd, this saves us some binary size + ; by deduplicating the shared code. + jmp m(satd_8x4_hbd).12bpc_main + ; No return; we return in the other function. + + +; , +%macro SATD_NXM 2 + +INIT_YMM avx2 +cglobal satd_%1x%2_hbd, 5, 10, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3, nsrc_stride4, ndst_stride4, rows + lea nsrc_stride4q, [4*src_strideq] + lea ndst_stride4q, [4*dst_strideq] + + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + neg nsrc_stride4q + neg ndst_stride4q + + pxor m9, m9 + + ; Height contains the number of rows. + mov rowsd, %2/8 +.outer: + mov bdmaxd, %1/8 + +; Loop over blocks in same row. +.loop: + LOAD_DIFF_8X8 + + ; Fix up pointers and go to next block in same row. + lea srcq, [srcq + nsrc_stride4q + 16] + lea dstq, [dstq + ndst_stride4q + 16] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + lea srcq, [srcq + 8*src_strideq - (%1*16)/8] + lea dstq, [dstq + 8*dst_strideq - (%1*16)/8] + + dec rowsd + jnz .outer + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +%macro SATD_NX8 1 +INIT_YMM avx2 +cglobal satd_%1x8_hbd, 5, 9, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3, nsrc_stride4, ndst_stride4 + lea nsrc_stride4q, [4*src_strideq] + lea ndst_stride4q, [4*dst_strideq] + + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + neg nsrc_stride4q + neg ndst_stride4q + + pxor m9, m9 + mov bdmaxd, %1/8 + +.loop: + LOAD_DIFF_8X8 + + lea srcq, [srcq + nsrc_stride4q + 16] + lea dstq, [dstq + ndst_stride4q + 16] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +%macro SATD_8XM 1 +INIT_YMM avx2 +cglobal satd_8x%1_hbd, 5, 7, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + pxor m9, m9 + mov bdmaxd, %1/8 + +.loop: + LOAD_DIFF_8X8 + + lea srcq, [srcq + 4*src_strideq] + lea dstq, [dstq + 4*dst_strideq] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +SATD_NXM 16, 16 +SATD_NXM 32, 32 +SATD_NXM 64, 64 +SATD_NXM 128, 128 +SATD_NXM 16, 32 +SATD_NXM 16, 64 +SATD_NXM 32, 16 +SATD_NXM 32, 64 +SATD_NXM 64, 16 +SATD_NXM 64, 32 +SATD_NXM 64, 128 +SATD_NXM 128, 64 +SATD_NX8 16 +SATD_NX8 32 +SATD_8XM 16 +SATD_8XM 32 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/tables.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/tables.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/tables.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/tables.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,563 @@ +; Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "src/asm/x86/x86inc.asm" + +SECTION_RODATA 16 + +align 8, db 0 +const mc_subpel_filters, db 0, 1, -3, 63, 4, -1, 0, 0, ; REGULAR + db 0, 1, -5, 61, 9, -2, 0, 0, + db 0, 1, -6, 58, 14, -4, 1, 0, + db 0, 1, -7, 55, 19, -5, 1, 0, + db 0, 1, -7, 51, 24, -6, 1, 0, + db 0, 1, -8, 47, 29, -6, 1, 0, + db 0, 1, -7, 42, 33, -6, 1, 0, + db 0, 1, -7, 38, 38, -7, 1, 0, + db 0, 1, -6, 33, 42, -7, 1, 0, + db 0, 1, -6, 29, 47, -8, 1, 0, + db 0, 1, -6, 24, 51, -7, 1, 0, + db 0, 1, -5, 19, 55, -7, 1, 0, + db 0, 1, -4, 14, 58, -6, 1, 0, + db 0, 0, -2, 9, 61, -5, 1, 0, + db 0, 0, -1, 4, 63, -3, 1, 0, + db 0, 1, 14, 31, 17, 1, 0, 0, ; SMOOTH + db 0, 0, 13, 31, 18, 2, 0, 0, + db 0, 0, 11, 31, 20, 2, 0, 0, + db 0, 0, 10, 30, 21, 3, 0, 0, + db 0, 0, 9, 29, 22, 4, 0, 0, + db 0, 0, 8, 28, 23, 5, 0, 0, + db 0, -1, 8, 27, 24, 6, 0, 0, + db 0, -1, 7, 26, 26, 7, -1, 0, + db 0, 0, 6, 24, 27, 8, -1, 0, + db 0, 0, 5, 23, 28, 8, 0, 0, + db 0, 0, 4, 22, 29, 9, 0, 0, + db 0, 0, 3, 21, 30, 10, 0, 0, + db 0, 0, 2, 20, 31, 11, 0, 0, + db 0, 0, 2, 18, 31, 13, 0, 0, + db 0, 0, 1, 17, 31, 14, 1, 0, + db -1, 1, -3, 63, 4, -1, 1, 0, ; SHARP + db -1, 3, -6, 62, 8, -3, 2, -1, + db -1, 4, -9, 60, 13, -5, 3, -1, + db -2, 5, -11, 58, 19, -7, 3, -1, + db -2, 5, -11, 54, 24, -9, 4, -1, + db -2, 5, -12, 50, 30, -10, 4, -1, + db -2, 5, -12, 45, 35, -11, 5, -1, + db -2, 6, -12, 40, 40, -12, 6, -2, + db -1, 5, -11, 35, 45, -12, 5, -2, + db -1, 4, -10, 30, 50, -12, 5, -2, + db -1, 4, -9, 24, 54, -11, 5, -2, + db -1, 3, -7, 19, 58, -11, 5, -2, + db -1, 3, -5, 13, 60, -9, 4, -1, + db -1, 2, -3, 8, 62, -6, 3, -1, + db 0, 1, -1, 4, 63, -3, 1, -1, + db 0, 0, -2, 63, 4, -1, 0, 0, ; REGULAR 4 + db 0, 0, -4, 61, 9, -2, 0, 0, + db 0, 0, -5, 58, 14, -3, 0, 0, + db 0, 0, -6, 55, 19, -4, 0, 0, + db 0, 0, -6, 51, 24, -5, 0, 0, + db 0, 0, -7, 47, 29, -5, 0, 0, + db 0, 0, -6, 42, 33, -5, 0, 0, + db 0, 0, -6, 38, 38, -6, 0, 0, + db 0, 0, -5, 33, 42, -6, 0, 0, + db 0, 0, -5, 29, 47, -7, 0, 0, + db 0, 0, -5, 24, 51, -6, 0, 0, + db 0, 0, -4, 19, 55, -6, 0, 0, + db 0, 0, -3, 14, 58, -5, 0, 0, + db 0, 0, -2, 9, 61, -4, 0, 0, + db 0, 0, -1, 4, 63, -2, 0, 0, + db 0, 0, 15, 31, 17, 1, 0, 0, ; SMOOTH 4 + db 0, 0, 13, 31, 18, 2, 0, 0, + db 0, 0, 11, 31, 20, 2, 0, 0, + db 0, 0, 10, 30, 21, 3, 0, 0, + db 0, 0, 9, 29, 22, 4, 0, 0, + db 0, 0, 8, 28, 23, 5, 0, 0, + db 0, 0, 7, 27, 24, 6, 0, 0, + db 0, 0, 6, 26, 26, 6, 0, 0, + db 0, 0, 6, 24, 27, 7, 0, 0, + db 0, 0, 5, 23, 28, 8, 0, 0, + db 0, 0, 4, 22, 29, 9, 0, 0, + db 0, 0, 3, 21, 30, 10, 0, 0, + db 0, 0, 2, 20, 31, 11, 0, 0, + db 0, 0, 2, 18, 31, 13, 0, 0, + db 0, 0, 1, 17, 31, 15, 0, 0, + ; Bilin scaled being very rarely used, add a new table entry + ; and use the put/prep_8tap_scaled code, thus acting as a + ; scaled bilinear filter. + db 0, 0, 0, 60, 4, 0, 0, 0, + db 0, 0, 0, 56, 8, 0, 0, 0, + db 0, 0, 0, 52, 12, 0, 0, 0, + db 0, 0, 0, 48, 16, 0, 0, 0, + db 0, 0, 0, 44, 20, 0, 0, 0, + db 0, 0, 0, 40, 24, 0, 0, 0, + db 0, 0, 0, 36, 28, 0, 0, 0, + db 0, 0, 0, 32, 32, 0, 0, 0, + db 0, 0, 0, 28, 36, 0, 0, 0, + db 0, 0, 0, 24, 40, 0, 0, 0, + db 0, 0, 0, 20, 44, 0, 0, 0, + db 0, 0, 0, 16, 48, 0, 0, 0, + db 0, 0, 0, 12, 52, 0, 0, 0, + db 0, 0, 0, 8, 56, 0, 0, 0, + db 0, 0, 0, 4, 60, 0, 0, 0 + +align 64, db 0 +const filter_intra_taps, db -6, 10, -5, 2, -3, 1, -3, 1, ; 0 + db -4, 6, -3, 2, -3, 2, -3, 1, + db 0, 0, 10, 0, 1, 10, 1, 2, + db 0, 0, 6, 0, 2, 6, 2, 2, + db 0, 12, 0, 9, 0, 7, 10, 5, + db 0, 2, 0, 2, 0, 2, 6, 3, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 12, 0, 9, 0, 7, 0, 5, 0, + db -10, 16, -6, 0, -4, 0, -2, 0, ; 1 + db -10, 16, -6, 0, -4, 0, -2, 0, + db 0, 0, 16, 0, 0, 16, 0, 0, + db 0, 0, 16, 0, 0, 16, 0, 0, + db 0, 10, 0, 6, 0, 4, 16, 2, + db 0, 0, 0, 0, 0, 0, 16, 0, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 10, 0, 6, 0, 4, 0, 2, 0, + db -8, 8, -8, 0, -8, 0, -8, 0, ; 2 + db -4, 4, -4, 0, -4, 0, -4, 0, + db 0, 0, 8, 0, 0, 8, 0, 0, + db 0, 0, 4, 0, 0, 4, 0, 0, + db 0, 16, 0, 16, 0, 16, 8, 16, + db 0, 0, 0, 0, 0, 0, 4, 0, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 16, 0, 16, 0, 16, 0, 16, 0, + db -2, 8, -1, 3, -1, 2, 0, 1, ; 3 + db -1, 4, -1, 3, -1, 2, -1, 2, + db 0, 0, 8, 0, 3, 8, 2, 3, + db 0, 0, 4, 0, 3, 4, 2, 3, + db 0, 10, 0, 6, 0, 4, 8, 2, + db 0, 3, 0, 4, 0, 4, 4, 3, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 10, 0, 6, 0, 4, 0, 3, 0, + db -12, 14, -10, 0, -9, 0, -8, 0, ; 4 + db -10, 12, -9, 1, -8, 0, -7, 0, + db 0, 0, 14, 0, 0, 14, 0, 0, + db 0, 0, 12, 0, 0, 12, 0, 1, + db 0, 14, 0, 12, 0, 11, 14, 10, + db 0, 0, 0, 0, 0, 1, 12, 1, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 14, 0, 12, 0, 11, 0, 9, 0 + +align 64, db 0 +const sgr_x_by_x, db 255, 128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17, + db 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9, + db 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, + db 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, + db 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, + db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 0 + +align 8, db 0 +const mc_warp_filter, db 0, 127, 0, 0, 0, 1, 0, 0, 0, 127, 0, 0, -1, 2, 0, 0, ; [-1, 0) + db 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, 0, + db 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, 0, + db 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, 0, + db 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, 0, + db 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, 0, + db 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, 0, + db 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, 0, + db 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, 0, + db 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, 0, + db 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, 0, + db 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, 0, + db 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, 0, + db 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, 0, + db 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, 0, + db 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, 0, + db 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, 0, + db 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, 0, + db 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, 0, + db 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, 0, + db 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, 0, + db 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, 0, + db 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, 0, + db 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, 0, + db 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, 0, + db 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, 0, + db 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, 0, + db 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, 0, + db 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, 0, + db 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, 0, + db 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, 0, + db 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, 0, + db 0, 0, 1, 0, 0, 127, 0, 0, 0, -1, 2, 0, 0, 127, 0, 0, ; [0, 1) + db 0, -3, 4, 1, 1, 127, -2, 0, 0, -5, 6, 1, 1, 127, -2, 0, + db 0, -6, 8, 1, 2, 126, -3, 0, -1, -7, 11, 2, 2, 126, -4, -1, + db -1, -8, 13, 2, 3, 125, -5, -1, -1, -10, 16, 3, 3, 124, -6, -1, + db -1, -11, 18, 3, 4, 123, -7, -1, -1, -12, 20, 3, 4, 122, -7, -1, + db -1, -13, 23, 3, 4, 121, -8, -1, -2, -14, 25, 4, 5, 120, -9, -1, + db -1, -15, 27, 4, 5, 119, -10, -1, -1, -16, 30, 4, 5, 118, -11, -1, + db -2, -17, 33, 5, 6, 116, -12, -1, -2, -17, 35, 5, 6, 114, -12, -1, + db -2, -18, 38, 5, 6, 113, -13, -1, -2, -19, 41, 6, 7, 111, -14, -2, + db -2, -19, 43, 6, 7, 110, -15, -2, -2, -20, 46, 6, 7, 108, -15, -2, + db -2, -20, 49, 6, 7, 106, -16, -2, -2, -21, 51, 7, 7, 104, -16, -2, + db -2, -21, 54, 7, 7, 102, -17, -2, -2, -21, 56, 7, 8, 100, -18, -2, + db -2, -22, 59, 7, 8, 98, -18, -2, -2, -22, 62, 7, 8, 96, -19, -2, + db -2, -22, 64, 7, 8, 94, -19, -2, -2, -22, 67, 8, 8, 91, -20, -2, + db -2, -22, 69, 8, 8, 89, -20, -2, -2, -22, 72, 8, 8, 87, -21, -2, + db -2, -21, 74, 8, 8, 84, -21, -2, -2, -22, 77, 8, 8, 82, -21, -2, + db -2, -21, 79, 8, 8, 79, -21, -2, -2, -21, 82, 8, 8, 77, -22, -2, + db -2, -21, 84, 8, 8, 74, -21, -2, -2, -21, 87, 8, 8, 72, -22, -2, + db -2, -20, 89, 8, 8, 69, -22, -2, -2, -20, 91, 8, 8, 67, -22, -2, + db -2, -19, 94, 8, 7, 64, -22, -2, -2, -19, 96, 8, 7, 62, -22, -2, + db -2, -18, 98, 8, 7, 59, -22, -2, -2, -18, 100, 8, 7, 56, -21, -2, + db -2, -17, 102, 7, 7, 54, -21, -2, -2, -16, 104, 7, 7, 51, -21, -2, + db -2, -16, 106, 7, 6, 49, -20, -2, -2, -15, 108, 7, 6, 46, -20, -2, + db -2, -15, 110, 7, 6, 43, -19, -2, -2, -14, 111, 7, 6, 41, -19, -2, + db -1, -13, 113, 6, 5, 38, -18, -2, -1, -12, 114, 6, 5, 35, -17, -2, + db -1, -12, 116, 6, 5, 33, -17, -2, -1, -11, 118, 5, 4, 30, -16, -1, + db -1, -10, 119, 5, 4, 27, -15, -1, -1, -9, 120, 5, 4, 25, -14, -2, + db -1, -8, 121, 4, 3, 23, -13, -1, -1, -7, 122, 4, 3, 20, -12, -1, + db -1, -7, 123, 4, 3, 18, -11, -1, -1, -6, 124, 3, 3, 16, -10, -1, + db -1, -5, 125, 3, 2, 13, -8, -1, -1, -4, 126, 2, 2, 11, -7, -1, + db 0, -3, 126, 2, 1, 8, -6, 0, 0, -2, 127, 1, 1, 6, -5, 0, + db 0, -2, 127, 1, 1, 4, -3, 0, 0, 0, 127, 0, 0, 2, -1, 0, + db 0, 0, 127, 0, 0, 1, 0, 0, 0, 0, 127, 0, 0, -1, 2, 0, ; [1, 2) + db 0, 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, + db 0, 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, + db 0, 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, + db 0, 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, + db 0, 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, + db 0, 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, + db 0, 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, + db 0, 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, + db 0, 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, + db 0, 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, + db 0, 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, + db 0, 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, + db 0, 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, + db 0, 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, + db 0, 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, + db 0, 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, + db 0, 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, + db 0, 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, + db 0, 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, + db 0, 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, + db 0, 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, + db 0, 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, + db 0, 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, + db 0, 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, + db 0, 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, + db 0, 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, + db 0, 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, + db 0, 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, + db 0, 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, + db 0, 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, + db 0, 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, + db 0, 0, 2, -1, 0, 0, 127, 0 ; dummy (replicate row index 191) + +; Values that are 0 will never be used +align 2, db 0 +const dr_intra_derivative, dw 0, ; Angles: + dw 1023, 0, ; 3, 93, 183 + dw 547, ; 6, 96, 186 + dw 372, 0, 0, ; 9, 99, 189 + dw 273, ; 14, 104, 194 + dw 215, 0, ; 17, 107, 197 + dw 178, ; 20, 110, 200 + dw 151, 0, ; 23, 113, 203 (113 & 203 are base angles) + dw 132, ; 26, 116, 206 + dw 116, 0, ; 29, 119, 209 + dw 102, 0, ; 32, 122, 212 + dw 90, ; 36, 126, 216 + dw 80, 0, ; 39, 129, 219 + dw 71, ; 42, 132, 222 + dw 64, 0, ; 45, 135, 225 (45 & 135 are base angles) + dw 57, ; 48, 138, 228 + dw 51, 0, ; 51, 141, 231 + dw 45, 0, ; 54, 144, 234 + dw 40, ; 58, 148, 238 + dw 35, 0, ; 61, 151, 241 + dw 31, ; 64, 154, 244 + dw 27, 0, ; 67, 157, 247 (67 & 157 are base angles) + dw 23, ; 70, 160, 250 + dw 19, 0, ; 73, 163, 253 + dw 15, 0, ; 76, 166, 256 + dw 11, 0, ; 81, 171, 261 + dw 7, ; 84, 174, 264 + dw 3 ; 87, 177, 267 + +; Taken from the spec. Range is [-2048, 2047], mean is 0 and stddev is 512 +align 2, db 0 +const gaussian_sequence, dw 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820, + dw 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800, + dw 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588, + dw -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368, + dw 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4, + dw 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396, + dw 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740, + dw 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292, + dw 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532, + dw 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704, + dw 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96, + dw -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244, + dw 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136, + dw 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676, + dw -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400, + dw -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844, + dw -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96, + dw -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356, + dw 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280, + dw 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808, + dw 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228, + dw -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136, + dw -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264, + dw -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388, + dw 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500, + dw 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384, + dw 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220, + dw -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148, + dw 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572, + dw -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516, + dw 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916, + dw -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492, + dw 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560, + dw -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108, + dw -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516, + dw -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88, + dw -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196, + dw -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864, + dw 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920, + dw 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564, + dw -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876, + dw -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244, + dw 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184, + dw 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364, + dw -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72, + dw 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24, + dw 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4, + dw -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120, + dw 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108, + dw -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296, + dw 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336, + dw -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164, + dw -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264, + dw 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536, + dw -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296, + dw -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696, + dw 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204, + dw 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212, + dw -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40, + dw 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384, + dw 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8, + dw 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704, + dw -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348, + dw -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592, + dw -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420, + dw 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220, + dw -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208, + dw -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544, + dw -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288, + dw -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240, + dw -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132, + dw 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16, + dw -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044, + dw -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732, + dw 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460, + dw -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52, + dw -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104, + dw -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460, + dw 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716, + dw -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960, + dw 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476, + dw 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692, + dw 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352, + dw -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144, + dw -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44, + dw 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356, + dw 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452, + dw -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552, + dw -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264, + dw -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448, + dw -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588, + dw 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464, + dw 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216, + dw 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132, + dw 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412, + dw 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48, + dw 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196, + dw 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48, + dw -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292, + dw 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32, + dw -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012, + dw -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120, + dw -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56, + dw 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416, + dw -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404, + dw -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92, + dw 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904, + dw 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728, + dw 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584, + dw 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48, + dw 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180, + dw 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528, + dw 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364, + dw -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260, + dw -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324, + dw -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64, + dw 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120, + dw -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168, + dw -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888, + dw 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588, + dw -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484, + dw 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580, + dw 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392, + dw 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80, + dw -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688, + dw 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4, + dw -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300, + dw 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444, + dw 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192, + dw 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160, + dw 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188, + dw -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404, + dw -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400, + dw 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92, + dw -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824, + dw 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620, + dw 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720, + dw 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620, + dw -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508, + dw -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736, + dw 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836, + dw 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180, + dw 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140, + dw -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32, + dw -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916, + dw 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368, + dw -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380, + dw -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572, + dw -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864, + dw 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908, + dw -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84, + dw 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396, + dw -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360, + dw 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928, + dw -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288, + dw 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196, + dw 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504, + dw 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272, + dw 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344, + dw -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208, + dw -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156, + dw -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240, + dw -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432, + dw 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244, + dw 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584, + dw 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24, + dw 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300, + dw -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416, + dw 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380, + dw -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384, + dw 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88, + dw 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876, + dw -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320, + dw -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88, + dw -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196, + dw -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120, + dw 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664, + dw -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0, + dw -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264, + dw -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288, + dw -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56, + dw 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148, + dw 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156, + dw -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144, + dw -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148, + dw 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944, + dw 428, -484 + +align 8, db 0 +const resize_filter, db 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 1, -128, -2, 1, 0, 0, + db 0, -1, 3, -127, -4, 2, -1, 0, 0, -1, 4, -127, -6, 3, -1, 0, + db 0, -2, 6, -126, -8, 3, -1, 0, 0, -2, 7, -125, -11, 4, -1, 0, + db 1, -2, 8, -125, -13, 5, -2, 0, 1, -3, 9, -124, -15, 6, -2, 0, + db 1, -3, 10, -123, -18, 6, -2, 1, 1, -3, 11, -122, -20, 7, -3, 1, + db 1, -4, 12, -121, -22, 8, -3, 1, 1, -4, 13, -120, -25, 9, -3, 1, + db 1, -4, 14, -118, -28, 9, -3, 1, 1, -4, 15, -117, -30, 10, -4, 1, + db 1, -5, 16, -116, -32, 11, -4, 1, 1, -5, 16, -114, -35, 12, -4, 1, + db 1, -5, 17, -112, -38, 12, -4, 1, 1, -5, 18, -111, -40, 13, -5, 1, + db 1, -5, 18, -109, -43, 14, -5, 1, 1, -6, 19, -107, -45, 14, -5, 1, + db 1, -6, 19, -105, -48, 15, -5, 1, 1, -6, 19, -103, -51, 16, -5, 1, + db 1, -6, 20, -101, -53, 16, -6, 1, 1, -6, 20, -99, -56, 17, -6, 1, + db 1, -6, 20, -97, -58, 17, -6, 1, 1, -6, 20, -95, -61, 18, -6, 1, + db 2, -7, 20, -93, -64, 18, -6, 2, 2, -7, 20, -91, -66, 19, -6, 1, + db 2, -7, 20, -88, -69, 19, -6, 1, 2, -7, 20, -86, -71, 19, -6, 1, + db 2, -7, 20, -84, -74, 20, -7, 2, 2, -7, 20, -81, -76, 20, -7, 1, + db 2, -7, 20, -79, -79, 20, -7, 2, 1, -7, 20, -76, -81, 20, -7, 2, + db 2, -7, 20, -74, -84, 20, -7, 2, 1, -6, 19, -71, -86, 20, -7, 2, + db 1, -6, 19, -69, -88, 20, -7, 2, 1, -6, 19, -66, -91, 20, -7, 2, + db 2, -6, 18, -64, -93, 20, -7, 2, 1, -6, 18, -61, -95, 20, -6, 1, + db 1, -6, 17, -58, -97, 20, -6, 1, 1, -6, 17, -56, -99, 20, -6, 1, + db 1, -6, 16, -53, -101, 20, -6, 1, 1, -5, 16, -51, -103, 19, -6, 1, + db 1, -5, 15, -48, -105, 19, -6, 1, 1, -5, 14, -45, -107, 19, -6, 1, + db 1, -5, 14, -43, -109, 18, -5, 1, 1, -5, 13, -40, -111, 18, -5, 1, + db 1, -4, 12, -38, -112, 17, -5, 1, 1, -4, 12, -35, -114, 16, -5, 1, + db 1, -4, 11, -32, -116, 16, -5, 1, 1, -4, 10, -30, -117, 15, -4, 1, + db 1, -3, 9, -28, -118, 14, -4, 1, 1, -3, 9, -25, -120, 13, -4, 1, + db 1, -3, 8, -22, -121, 12, -4, 1, 1, -3, 7, -20, -122, 11, -3, 1, + db 1, -2, 6, -18, -123, 10, -3, 1, 0, -2, 6, -15, -124, 9, -3, 1, + db 0, -2, 5, -13, -125, 8, -2, 1, 0, -1, 4, -11, -125, 7, -2, 0, + db 0, -1, 3, -8, -126, 6, -2, 0, 0, -1, 3, -6, -127, 4, -1, 0, + db 0, -1, 2, -4, -127, 3, -1, 0, 0, 0, 1, -2, -128, 1, 0, 0, + +align 16, db 0 ; Unused +const obmc_masks, db 0, 0, + ; 2 + db 19, 0, + ; 4 + db 25, 14, 5, 0, + ; 8 + db 28, 22, 16, 11, 7, 3, 0, 0, + ; 16 + db 30, 27, 24, 21, 18, 15, 12, 10, 8, 6, 4, 3, 0, 0, 0, 0, + ; 32 + db 31, 29, 28, 26, 24, 23, 21, 20, 19, 17, 16, 14, 13, 12, 11, 9, + db 8, 7, 6, 5, 4, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/x86inc.asm clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/x86inc.asm --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/x86inc.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/asm/x86/x86inc.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1902 @@ +;***************************************************************************** +;* x86inc.asm: x86 abstraction layer +;***************************************************************************** +;* Copyright (C) 2005-2022 x264 project +;* +;* Authors: Loren Merritt +;* Henrik Gramner +;* Anton Mitrofanov +;* Fiona Glaser +;* +;* Permission to use, copy, modify, and/or distribute this software for any +;* purpose with or without fee is hereby granted, provided that the above +;* copyright notice and this permission notice appear in all copies. +;* +;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +;***************************************************************************** + +; This is a header file for the x86inc.asm assembly language, which uses +; NASM/YASM syntax combined with a large number of macros to provide easy +; abstraction between different calling conventions (x86_32, win64, linux64). +; It also has various other useful features to simplify writing the kind of +; DSP functions that are most often used. + +%ifndef private_prefix + %error private_prefix not defined +%endif + +%ifndef public_prefix + %define public_prefix private_prefix +%endif + +%ifndef STACK_ALIGNMENT + %if ARCH_X86_64 + %define STACK_ALIGNMENT 16 + %else + %define STACK_ALIGNMENT 4 + %endif +%endif + +%define WIN64 0 +%define UNIX64 0 +%if ARCH_X86_64 + %ifidn __OUTPUT_FORMAT__,win32 + %define WIN64 1 + %elifidn __OUTPUT_FORMAT__,win64 + %define WIN64 1 + %elifidn __OUTPUT_FORMAT__,x64 + %define WIN64 1 + %else + %define UNIX64 1 + %endif +%endif + +%define FORMAT_ELF 0 +%define FORMAT_MACHO 0 +%ifidn __OUTPUT_FORMAT__,elf + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf32 + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf64 + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,macho + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho32 + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho64 + %define FORMAT_MACHO 1 +%endif + +%ifdef PREFIX + %define mangle(x) _ %+ x +%else + %define mangle(x) x +%endif + +; Use VEX-encoding even in non-AVX functions +%ifndef FORCE_VEX_ENCODING + %define FORCE_VEX_ENCODING 0 +%endif + +%macro SECTION_RODATA 0-1 16 + %ifidn __OUTPUT_FORMAT__,win32 + SECTION .rdata align=%1 + %elif WIN64 + SECTION .rdata align=%1 + %else + SECTION .rodata align=%1 + %endif +%endmacro + +%if ARCH_X86_64 + %define PIC 1 ; always use PIC on x86-64 + default rel +%elifidn __OUTPUT_FORMAT__,win32 + %define PIC 0 ; PIC isn't used on 32-bit Windows +%elifndef PIC + %define PIC 0 +%endif + +%define HAVE_PRIVATE_EXTERN 1 +%ifdef __NASM_VER__ + %use smartalign + %if __NASM_VERSION_ID__ < 0x020e0000 ; 2.14 + %define HAVE_PRIVATE_EXTERN 0 + %endif +%endif + +; Macros to eliminate most code duplication between x86_32 and x86_64: +; Currently this works only for leaf functions which load all their arguments +; into registers at the start, and make no other use of the stack. Luckily that +; covers most use cases. + +; PROLOGUE: +; %1 = number of arguments. loads them from stack if needed. +; %2 = number of registers used. pushes callee-saved regs if needed. +; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed. +; %4 = (optional) stack size to be allocated. The stack will be aligned before +; allocating the specified stack size. If the required stack alignment is +; larger than the known stack alignment the stack will be manually aligned +; and an extra register will be allocated to hold the original stack +; pointer (to not invalidate r0m etc.). To prevent the use of an extra +; register as stack pointer, request a negative stack size. +; %4+/%5+ = list of names to define to registers +; PROLOGUE can also be invoked by adding the same options to cglobal + +; e.g. +; cglobal foo, 2,3,7,0x40, dst, src, tmp +; declares a function (foo) that automatically loads two arguments (dst and +; src) into registers, uses one additional register (tmp) plus 7 vector +; registers (m0-m6) and allocates 0x40 bytes of stack space. + +; TODO Some functions can use some args directly from the stack. If they're the +; last args then you can just not declare them, but if they're in the middle +; we need more flexible macro. + +; RET: +; Pops anything that was pushed by PROLOGUE, and returns. + +; REP_RET: +; Use this instead of RET if it's a branch target. + +; registers: +; rN and rNq are the native-size register holding function argument N +; rNd, rNw, rNb are dword, word, and byte size +; rNh is the high 8 bits of the word size +; rNm is the original location of arg N (a register or on the stack), dword +; rNmp is native size + +%macro DECLARE_REG 2-3 + %define r%1q %2 + %define r%1d %2d + %define r%1w %2w + %define r%1b %2b + %define r%1h %2h + %define %2q %2 + %if %0 == 2 + %define r%1m %2d + %define r%1mp %2 + %elif ARCH_X86_64 ; memory + %define r%1m [rstk + stack_offset + %3] + %define r%1mp qword r %+ %1 %+ m + %else + %define r%1m [rstk + stack_offset + %3] + %define r%1mp dword r %+ %1 %+ m + %endif + %define r%1 %2 +%endmacro + +%macro DECLARE_REG_SIZE 3 + %define r%1q r%1 + %define e%1q r%1 + %define r%1d e%1 + %define e%1d e%1 + %define r%1w %1 + %define e%1w %1 + %define r%1h %3 + %define e%1h %3 + %define r%1b %2 + %define e%1b %2 + %if ARCH_X86_64 == 0 + %define r%1 e%1 + %endif +%endmacro + +DECLARE_REG_SIZE ax, al, ah +DECLARE_REG_SIZE bx, bl, bh +DECLARE_REG_SIZE cx, cl, ch +DECLARE_REG_SIZE dx, dl, dh +DECLARE_REG_SIZE si, sil, null +DECLARE_REG_SIZE di, dil, null +DECLARE_REG_SIZE bp, bpl, null + +; t# defines for when per-arch register allocation is more complex than just function arguments + +%macro DECLARE_REG_TMP 1-* + %assign %%i 0 + %rep %0 + CAT_XDEFINE t, %%i, r%1 + %assign %%i %%i+1 + %rotate 1 + %endrep +%endmacro + +%macro DECLARE_REG_TMP_SIZE 0-* + %rep %0 + %define t%1q t%1 %+ q + %define t%1d t%1 %+ d + %define t%1w t%1 %+ w + %define t%1h t%1 %+ h + %define t%1b t%1 %+ b + %rotate 1 + %endrep +%endmacro + +DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 + +%if ARCH_X86_64 + %define gprsize 8 +%else + %define gprsize 4 +%endif + +%macro LEA 2 +%if ARCH_X86_64 + lea %1, [%2] +%elif PIC + call $+5 ; special-cased to not affect the RSB on most CPU:s + pop %1 + add %1, (%2)-$+1 +%else + mov %1, %2 +%endif +%endmacro + +; Repeats an instruction/operation for multiple arguments. +; Example usage: "REPX {psrlw x, 8}, m0, m1, m2, m3" +%macro REPX 2-* ; operation, args + %xdefine %%f(x) %1 + %rep %0 - 1 + %rotate 1 + %%f(%1) + %endrep +%endmacro + +%macro PUSH 1 + push %1 + %ifidn rstk, rsp + %assign stack_offset stack_offset+gprsize + %endif +%endmacro + +%macro POP 1 + pop %1 + %ifidn rstk, rsp + %assign stack_offset stack_offset-gprsize + %endif +%endmacro + +%macro PUSH_IF_USED 1-* + %rep %0 + %if %1 < regs_used + PUSH r%1 + %endif + %rotate 1 + %endrep +%endmacro + +%macro POP_IF_USED 1-* + %rep %0 + %if %1 < regs_used + pop r%1 + %endif + %rotate 1 + %endrep +%endmacro + +%macro LOAD_IF_USED 1-* + %rep %0 + %if %1 < num_args + mov r%1, r %+ %1 %+ mp + %endif + %rotate 1 + %endrep +%endmacro + +%macro SUB 2 + sub %1, %2 + %ifidn %1, rstk + %assign stack_offset stack_offset+(%2) + %endif +%endmacro + +%macro ADD 2 + add %1, %2 + %ifidn %1, rstk + %assign stack_offset stack_offset-(%2) + %endif +%endmacro + +%macro movifnidn 2 + %ifnidn %1, %2 + mov %1, %2 + %endif +%endmacro + +%if ARCH_X86_64 == 0 + %define movsxd movifnidn +%endif + +%macro movsxdifnidn 2 + %ifnidn %1, %2 + movsxd %1, %2 + %endif +%endmacro + +%macro ASSERT 1 + %if (%1) == 0 + %error assertion ``%1'' failed + %endif +%endmacro + +%macro DEFINE_ARGS 0-* + %ifdef n_arg_names + %assign %%i 0 + %rep n_arg_names + CAT_UNDEF arg_name %+ %%i, q + CAT_UNDEF arg_name %+ %%i, d + CAT_UNDEF arg_name %+ %%i, w + CAT_UNDEF arg_name %+ %%i, h + CAT_UNDEF arg_name %+ %%i, b + CAT_UNDEF arg_name %+ %%i, m + CAT_UNDEF arg_name %+ %%i, mp + CAT_UNDEF arg_name, %%i + %assign %%i %%i+1 + %endrep + %endif + + %xdefine %%stack_offset stack_offset + %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine + %assign %%i 0 + %rep %0 + %xdefine %1q r %+ %%i %+ q + %xdefine %1d r %+ %%i %+ d + %xdefine %1w r %+ %%i %+ w + %xdefine %1h r %+ %%i %+ h + %xdefine %1b r %+ %%i %+ b + %xdefine %1m r %+ %%i %+ m + %xdefine %1mp r %+ %%i %+ mp + CAT_XDEFINE arg_name, %%i, %1 + %assign %%i %%i+1 + %rotate 1 + %endrep + %xdefine stack_offset %%stack_offset + %assign n_arg_names %0 +%endmacro + +%define required_stack_alignment ((mmsize + 15) & ~15) +%define vzeroupper_required (mmsize > 16 && (ARCH_X86_64 == 0 || xmm_regs_used > 16 || notcpuflag(avx512))) +%define high_mm_regs (16*cpuflag(avx512)) + +; Large stack allocations on Windows need to use stack probing in order +; to guarantee that all stack memory is committed before accessing it. +; This is done by ensuring that the guard page(s) at the end of the +; currently committed pages are touched prior to any pages beyond that. +%if WIN64 + %assign STACK_PROBE_SIZE 8192 +%elifidn __OUTPUT_FORMAT__, win32 + %assign STACK_PROBE_SIZE 4096 +%else + %assign STACK_PROBE_SIZE 0 +%endif + +%macro PROBE_STACK 1 ; stack_size + %if STACK_PROBE_SIZE + %assign %%i STACK_PROBE_SIZE + %rep %1 / STACK_PROBE_SIZE + mov eax, [rsp-%%i] + %assign %%i %%i+STACK_PROBE_SIZE + %endrep + %endif +%endmacro + +%macro ALLOC_STACK 0-2 0, 0 ; stack_size, n_xmm_regs (for win64 only) + %ifnum %1 + %if %1 != 0 + %assign %%pad 0 + %assign stack_size %1 + %if stack_size < 0 + %assign stack_size -stack_size + %endif + %if WIN64 + %assign %%pad %%pad + 32 ; shadow space + %if mmsize != 8 + %assign xmm_regs_used %2 + %if xmm_regs_used > 8 + %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers + %endif + %endif + %endif + %if required_stack_alignment <= STACK_ALIGNMENT + ; maintain the current stack alignment + %assign stack_size_padded stack_size + %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + PROBE_STACK stack_size_padded + SUB rsp, stack_size_padded + %else + %assign %%reg_num (regs_used - 1) + %xdefine rstk r %+ %%reg_num + ; align stack, and save original stack location directly above + ; it, i.e. in [rsp+stack_size_padded], so we can restore the + ; stack in a single instruction (i.e. mov rsp, rstk or mov + ; rsp, [rsp+stack_size_padded]) + %if %1 < 0 ; need to store rsp on stack + %xdefine rstkm [rsp + stack_size + %%pad] + %assign %%pad %%pad + gprsize + %else ; can keep rsp in rstk during whole function + %xdefine rstkm rstk + %endif + %assign stack_size_padded stack_size + ((%%pad + required_stack_alignment-1) & ~(required_stack_alignment-1)) + PROBE_STACK stack_size_padded + mov rstk, rsp + and rsp, ~(required_stack_alignment-1) + sub rsp, stack_size_padded + movifnidn rstkm, rstk + %endif + WIN64_PUSH_XMM + %endif + %endif +%endmacro + +%macro SETUP_STACK_POINTER 0-1 0 + %ifnum %1 + %if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT + %if %1 > 0 + ; Reserve an additional register for storing the original stack pointer, but avoid using + ; eax/rax for this purpose since it can potentially get overwritten as a return value. + %assign regs_used (regs_used + 1) + %if ARCH_X86_64 && regs_used == 7 + %assign regs_used 8 + %elif ARCH_X86_64 == 0 && regs_used == 1 + %assign regs_used 2 + %endif + %endif + %if ARCH_X86_64 && regs_used < 5 + UNIX64 * 3 + ; Ensure that we don't clobber any registers containing arguments. For UNIX64 we also preserve r6 (rax) + ; since it's used as a hidden argument in vararg functions to specify the number of vector registers used. + %assign regs_used 5 + UNIX64 * 3 + %endif + %endif + %endif +%endmacro + +%if WIN64 ; Windows x64 ;================================================= + +DECLARE_REG 0, rcx +DECLARE_REG 1, rdx +DECLARE_REG 2, R8 +DECLARE_REG 3, R9 +DECLARE_REG 4, R10, 40 +DECLARE_REG 5, R11, 48 +DECLARE_REG 6, rax, 56 +DECLARE_REG 7, rdi, 64 +DECLARE_REG 8, rsi, 72 +DECLARE_REG 9, rbx, 80 +DECLARE_REG 10, rbp, 88 +DECLARE_REG 11, R14, 96 +DECLARE_REG 12, R15, 104 +DECLARE_REG 13, R12, 112 +DECLARE_REG 14, R13, 120 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + ASSERT regs_used >= num_args + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 15 + PUSH_IF_USED 7, 8, 9, 10, 11, 12, 13, 14 + ALLOC_STACK %4, %3 + %if mmsize != 8 && stack_size == 0 + WIN64_SPILL_XMM %3 + %endif + LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%macro WIN64_PUSH_XMM 0 + ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated. + %if xmm_regs_used > 6 + high_mm_regs + movaps [rstk + stack_offset + 8], xmm6 + %endif + %if xmm_regs_used > 7 + high_mm_regs + movaps [rstk + stack_offset + 24], xmm7 + %endif + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + %assign %%i 8 + %rep %%xmm_regs_on_stack + movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i + %assign %%i %%i+1 + %endrep + %endif +%endmacro + +%macro WIN64_SPILL_XMM 1 + %assign xmm_regs_used %1 + ASSERT xmm_regs_used <= 16 + high_mm_regs + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. + %assign %%pad %%xmm_regs_on_stack*16 + 32 + %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + SUB rsp, stack_size_padded + %endif + WIN64_PUSH_XMM +%endmacro + +%macro WIN64_RESTORE_XMM_INTERNAL 0 + %assign %%pad_size 0 + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + %assign %%i xmm_regs_used - high_mm_regs + %rep %%xmm_regs_on_stack + %assign %%i %%i-1 + movaps xmm %+ %%i, [rsp + (%%i-8)*16 + stack_size + 32] + %endrep + %endif + %if stack_size_padded > 0 + %if stack_size > 0 && required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %assign %%pad_size stack_size_padded + %endif + %endif + %if xmm_regs_used > 7 + high_mm_regs + movaps xmm7, [rsp + stack_offset - %%pad_size + 24] + %endif + %if xmm_regs_used > 6 + high_mm_regs + movaps xmm6, [rsp + stack_offset - %%pad_size + 8] + %endif +%endmacro + +%macro WIN64_RESTORE_XMM 0 + WIN64_RESTORE_XMM_INTERNAL + %assign stack_offset (stack_offset-stack_size_padded) + %assign stack_size_padded 0 + %assign xmm_regs_used 0 +%endmacro + +%define has_epilogue regs_used > 7 || stack_size > 0 || vzeroupper_required || xmm_regs_used > 6+high_mm_regs + +%macro RET 0 + WIN64_RESTORE_XMM_INTERNAL + POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%elif ARCH_X86_64 ; *nix x64 ;============================================= + +DECLARE_REG 0, rdi +DECLARE_REG 1, rsi +DECLARE_REG 2, rdx +DECLARE_REG 3, rcx +DECLARE_REG 4, R8 +DECLARE_REG 5, R9 +DECLARE_REG 6, rax, 8 +DECLARE_REG 7, R10, 16 +DECLARE_REG 8, R11, 24 +DECLARE_REG 9, rbx, 32 +DECLARE_REG 10, rbp, 40 +DECLARE_REG 11, R14, 48 +DECLARE_REG 12, R15, 56 +DECLARE_REG 13, R12, 64 +DECLARE_REG 14, R13, 72 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + %assign xmm_regs_used %3 + ASSERT regs_used >= num_args + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 15 + PUSH_IF_USED 9, 10, 11, 12, 13, 14 + ALLOC_STACK %4 + LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%define has_epilogue regs_used > 9 || stack_size > 0 || vzeroupper_required + +%macro RET 0 + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif + POP_IF_USED 14, 13, 12, 11, 10, 9 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%else ; X86_32 ;============================================================== + +DECLARE_REG 0, eax, 4 +DECLARE_REG 1, ecx, 8 +DECLARE_REG 2, edx, 12 +DECLARE_REG 3, ebx, 16 +DECLARE_REG 4, esi, 20 +DECLARE_REG 5, edi, 24 +DECLARE_REG 6, ebp, 28 +%define rsp esp + +%macro DECLARE_ARG 1-* + %rep %0 + %define r%1m [rstk + stack_offset + 4*%1 + 4] + %define r%1mp dword r%1m + %rotate 1 + %endrep +%endmacro + +DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + ASSERT regs_used >= num_args + %if num_args > 7 + %assign num_args 7 + %endif + %if regs_used > 7 + %assign regs_used 7 + %endif + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 7 + PUSH_IF_USED 3, 4, 5, 6 + ALLOC_STACK %4 + LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%define has_epilogue regs_used > 3 || stack_size > 0 || vzeroupper_required + +%macro RET 0 + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif + POP_IF_USED 6, 5, 4, 3 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%endif ;====================================================================== + +%if WIN64 == 0 + %macro WIN64_SPILL_XMM 1 + %assign xmm_regs_used %1 + %endmacro + %macro WIN64_RESTORE_XMM 0 + %assign xmm_regs_used 0 + %endmacro + %macro WIN64_PUSH_XMM 0 + %endmacro +%endif + +; On AMD cpus <=K10, an ordinary ret is slow if it immediately follows either +; a branch or a branch target. So switch to a 2-byte form of ret in that case. +; We can automatically detect "follows a branch", but not a branch target. +; (SSSE3 is a sufficient condition to know that your cpu doesn't have this problem.) +%macro REP_RET 0 + %if has_epilogue || cpuflag(ssse3) + RET + %else + rep ret + %endif + annotate_function_size +%endmacro + +%define last_branch_adr $$ +%macro AUTO_REP_RET 0 + %if notcpuflag(ssse3) + times ((last_branch_adr-$)>>31)+1 rep ; times 1 iff $ == last_branch_adr. + %endif + ret + annotate_function_size +%endmacro + +%macro BRANCH_INSTR 0-* + %rep %0 + %macro %1 1-2 %1 + %2 %1 + %if notcpuflag(ssse3) + %%branch_instr equ $ + %xdefine last_branch_adr %%branch_instr + %endif + %endmacro + %rotate 1 + %endrep +%endmacro + +BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, jna, jnae, jb, jbe, jnb, jnbe, jc, jnc, js, jns, jo, jno, jp, jnp + +%macro TAIL_CALL 1-2 1 ; callee, is_nonadjacent + %if has_epilogue + call %1 + RET + %elif %2 + jmp %1 + %endif + annotate_function_size +%endmacro + +;============================================================================= +; arch-independent part +;============================================================================= + +%assign function_align 16 + +; Begin a function. +; Applies any symbol mangling needed for C linkage, and sets up a define such that +; subsequent uses of the function name automatically refer to the mangled version. +; Appends cpuflags to the function name if cpuflags has been specified. +; The "" empty default parameter is a workaround for nasm, which fails if SUFFIX +; is empty and we call cglobal_internal with just %1 %+ SUFFIX (without %2). +%macro cglobal 1-2+ "" ; name, [PROLOGUE args] + cglobal_internal 1, %1 %+ SUFFIX, %2 +%endmacro +%macro cvisible 1-2+ "" ; name, [PROLOGUE args] + cglobal_internal 0, %1 %+ SUFFIX, %2 +%endmacro +%macro cglobal_internal 2-3+ + annotate_function_size + %ifndef cglobaled_%2 + %if %1 + %xdefine %2 mangle(private_prefix %+ _ %+ %2) + %else + %xdefine %2 mangle(public_prefix %+ _ %+ %2) + %endif + %xdefine %2.skip_prologue %2 %+ .skip_prologue + CAT_XDEFINE cglobaled_, %2, 1 + %endif + %xdefine current_function %2 + %xdefine current_function_section __SECT__ + %if FORMAT_ELF + %if %1 + global %2:function hidden + %else + global %2:function + %endif + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN && %1 + global %2:private_extern + %else + global %2 + %endif + align function_align + %2: + RESET_MM_PERMUTATION ; needed for x86-64, also makes disassembly somewhat nicer + %xdefine rstk rsp ; copy of the original stack pointer, used when greater alignment than the known stack alignment is required + %assign stack_offset 0 ; stack pointer offset relative to the return address + %assign stack_size 0 ; amount of stack space that can be freely used inside a function + %assign stack_size_padded 0 ; total amount of allocated stack space, including space for callee-saved xmm registers on WIN64 and alignment padding + %assign xmm_regs_used 0 ; number of XMM registers requested, used for dealing with callee-saved registers on WIN64 and vzeroupper + %ifnidn %3, "" + PROLOGUE %3 + %endif +%endmacro + +; Create a global symbol from a local label with the correct name mangling and type +%macro cglobal_label 1 + %if FORMAT_ELF + global current_function %+ %1:function hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global current_function %+ %1:private_extern + %else + global current_function %+ %1 + %endif + %1: +%endmacro + +%macro cextern 1 + %xdefine %1 mangle(private_prefix %+ _ %+ %1) + CAT_XDEFINE cglobaled_, %1, 1 + extern %1 +%endmacro + +; like cextern, but without the prefix +%macro cextern_naked 1 + %ifdef PREFIX + %xdefine %1 mangle(%1) + %endif + CAT_XDEFINE cglobaled_, %1, 1 + extern %1 +%endmacro + +%macro const 1-2+ + %xdefine %1 mangle(private_prefix %+ _ %+ %1) + %if FORMAT_ELF + global %1:data hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global %1:private_extern + %else + global %1 + %endif + %1: %2 +%endmacro + +; This is needed for ELF, otherwise the GNU linker assumes the stack is executable by default. +%if FORMAT_ELF + [SECTION .note.GNU-stack noalloc noexec nowrite progbits] +%endif + +; Tell debuggers how large the function was. +; This may be invoked multiple times per function; we rely on later instances overriding earlier ones. +; This is invoked by RET and similar macros, and also cglobal does it for the previous function, +; but if the last function in a source file doesn't use any of the standard macros for its epilogue, +; then its size might be unspecified. +%macro annotate_function_size 0 + %ifdef __YASM_VER__ + %ifdef current_function + %if FORMAT_ELF + current_function_section + %%ecf equ $ + size current_function %%ecf - current_function + __SECT__ + %endif + %endif + %endif +%endmacro + +; cpuflags + +%assign cpuflags_mmx (1<<0) +%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx +%assign cpuflags_3dnow (1<<2) | cpuflags_mmx +%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow +%assign cpuflags_sse (1<<4) | cpuflags_mmx2 +%assign cpuflags_sse2 (1<<5) | cpuflags_sse +%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 +%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 +%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 +%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 +%assign cpuflags_sse4 (1<<10) | cpuflags_ssse3 +%assign cpuflags_sse42 (1<<11) | cpuflags_sse4 +%assign cpuflags_aesni (1<<12) | cpuflags_sse42 +%assign cpuflags_gfni (1<<13) | cpuflags_sse42 +%assign cpuflags_avx (1<<14) | cpuflags_sse42 +%assign cpuflags_xop (1<<15) | cpuflags_avx +%assign cpuflags_fma4 (1<<16) | cpuflags_avx +%assign cpuflags_fma3 (1<<17) | cpuflags_avx +%assign cpuflags_bmi1 (1<<18) | cpuflags_avx|cpuflags_lzcnt +%assign cpuflags_bmi2 (1<<19) | cpuflags_bmi1 +%assign cpuflags_avx2 (1<<20) | cpuflags_fma3|cpuflags_bmi2 +%assign cpuflags_avx512 (1<<21) | cpuflags_avx2 ; F, CD, BW, DQ, VL +%assign cpuflags_avx512icl (1<<22) | cpuflags_avx512|cpuflags_gfni ; VNNI, IFMA, VBMI, VBMI2, VPOPCNTDQ, BITALG, VAES, VPCLMULQDQ + +%assign cpuflags_cache32 (1<<23) +%assign cpuflags_cache64 (1<<24) +%assign cpuflags_aligned (1<<25) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<26) + +; Returns a boolean value expressing whether or not the specified cpuflag is enabled. +%define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) +%define notcpuflag(x) (cpuflag(x) ^ 1) + +; Takes an arbitrary number of cpuflags from the above list. +; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu. +; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co. +%macro INIT_CPUFLAGS 0-* + %xdefine SUFFIX + %undef cpuname + %assign cpuflags 0 + + %if %0 >= 1 + %rep %0 + %ifdef cpuname + %xdefine cpuname cpuname %+ _%1 + %else + %xdefine cpuname %1 + %endif + %assign cpuflags cpuflags | cpuflags_%1 + %rotate 1 + %endrep + %xdefine SUFFIX _ %+ cpuname + + %if cpuflag(avx) + %assign avx_enabled 1 + %endif + %if (mmsize == 16 && notcpuflag(sse2)) || (mmsize == 32 && notcpuflag(avx2)) + %define mova movaps + %define movu movups + %define movnta movntps + %endif + %if cpuflag(aligned) + %define movu mova + %elif cpuflag(sse3) && notcpuflag(ssse3) + %define movu lddqu + %endif + %endif + + %if ARCH_X86_64 || cpuflag(sse2) + %ifdef __NASM_VER__ + ALIGNMODE p6 + %else + CPU amdnop + %endif + %else + %ifdef __NASM_VER__ + ALIGNMODE nop + %else + CPU basicnop + %endif + %endif +%endmacro + +; Merge mmx, sse*, and avx* +; m# is a simd register of the currently selected size +; xm# is the corresponding xmm register if mmsize >= 16, otherwise the same as m# +; ym# is the corresponding ymm register if mmsize >= 32, otherwise the same as m# +; zm# is the corresponding zmm register if mmsize >= 64, otherwise the same as m# +; (All 4 remain in sync through SWAP.) + +%macro CAT_XDEFINE 3 + %xdefine %1%2 %3 +%endmacro + +%macro CAT_UNDEF 2 + %undef %1%2 +%endmacro + +%macro DEFINE_MMREGS 1 ; mmtype + %assign %%prev_mmregs 0 + %ifdef num_mmregs + %assign %%prev_mmregs num_mmregs + %endif + + %assign num_mmregs 8 + %if ARCH_X86_64 && mmsize >= 16 + %assign num_mmregs 16 + %if cpuflag(avx512) || mmsize == 64 + %assign num_mmregs 32 + %endif + %endif + + %assign %%i 0 + %rep num_mmregs + CAT_XDEFINE m, %%i, %1 %+ %%i + CAT_XDEFINE nn%1, %%i, %%i + %assign %%i %%i+1 + %endrep + %if %%prev_mmregs > num_mmregs + %rep %%prev_mmregs - num_mmregs + CAT_UNDEF m, %%i + CAT_UNDEF nn %+ mmtype, %%i + %assign %%i %%i+1 + %endrep + %endif + %xdefine mmtype %1 +%endmacro + +; Prefer registers 16-31 over 0-15 to avoid having to use vzeroupper +%macro AVX512_MM_PERMUTATION 0-1 0 ; start_reg + %if ARCH_X86_64 && cpuflag(avx512) + %assign %%i %1 + %rep 16-%1 + %assign %%i_high %%i+16 + SWAP %%i, %%i_high + %assign %%i %%i+1 + %endrep + %endif +%endmacro + +%macro INIT_MMX 0-1+ + %assign avx_enabled 0 + %define RESET_MM_PERMUTATION INIT_MMX %1 + %define mmsize 8 + %define mova movq + %define movu movq + %define movh movd + %define movnta movntq + INIT_CPUFLAGS %1 + DEFINE_MMREGS mm +%endmacro + +%macro INIT_XMM 0-1+ + %assign avx_enabled FORCE_VEX_ENCODING + %define RESET_MM_PERMUTATION INIT_XMM %1 + %define mmsize 16 + %define mova movdqa + %define movu movdqu + %define movh movq + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS xmm + %if WIN64 + AVX512_MM_PERMUTATION 6 ; Swap callee-saved registers with volatile registers + %endif + %xdefine bcstd 1to4 + %xdefine bcstq 1to2 +%endmacro + +%macro INIT_YMM 0-1+ + %assign avx_enabled 1 + %define RESET_MM_PERMUTATION INIT_YMM %1 + %define mmsize 32 + %define mova movdqa + %define movu movdqu + %undef movh + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS ymm + AVX512_MM_PERMUTATION + %xdefine bcstd 1to8 + %xdefine bcstq 1to4 +%endmacro + +%macro INIT_ZMM 0-1+ + %assign avx_enabled 1 + %define RESET_MM_PERMUTATION INIT_ZMM %1 + %define mmsize 64 + %define mova movdqa + %define movu movdqu + %undef movh + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS zmm + AVX512_MM_PERMUTATION + %xdefine bcstd 1to16 + %xdefine bcstq 1to8 +%endmacro + +INIT_XMM + +%macro DECLARE_MMCAST 1 + %define mmmm%1 mm%1 + %define mmxmm%1 mm%1 + %define mmymm%1 mm%1 + %define mmzmm%1 mm%1 + %define xmmmm%1 mm%1 + %define xmmxmm%1 xmm%1 + %define xmmymm%1 xmm%1 + %define xmmzmm%1 xmm%1 + %define ymmmm%1 mm%1 + %define ymmxmm%1 xmm%1 + %define ymmymm%1 ymm%1 + %define ymmzmm%1 ymm%1 + %define zmmmm%1 mm%1 + %define zmmxmm%1 xmm%1 + %define zmmymm%1 ymm%1 + %define zmmzmm%1 zmm%1 + %define xm%1 xmm %+ m%1 + %define ym%1 ymm %+ m%1 + %define zm%1 zmm %+ m%1 +%endmacro + +%assign i 0 +%rep 32 + DECLARE_MMCAST i + %assign i i+1 +%endrep + +; I often want to use macros that permute their arguments. e.g. there's no +; efficient way to implement butterfly or transpose or dct without swapping some +; arguments. +; +; I would like to not have to manually keep track of the permutations: +; If I insert a permutation in the middle of a function, it should automatically +; change everything that follows. For more complex macros I may also have multiple +; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations. +; +; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that +; permutes its arguments. It's equivalent to exchanging the contents of the +; registers, except that this way you exchange the register names instead, so it +; doesn't cost any cycles. + +%macro PERMUTE 2-* ; takes a list of pairs to swap + %rep %0/2 + %xdefine %%tmp%2 m%2 + %rotate 2 + %endrep + %rep %0/2 + %xdefine m%1 %%tmp%2 + CAT_XDEFINE nn, m%1, %1 + %rotate 2 + %endrep +%endmacro + +%macro SWAP 2+ ; swaps a single chain (sometimes more concise than pairs) + %ifnum %1 ; SWAP 0, 1, ... + SWAP_INTERNAL_NUM %1, %2 + %else ; SWAP m0, m1, ... + SWAP_INTERNAL_NAME %1, %2 + %endif +%endmacro + +%macro SWAP_INTERNAL_NUM 2-* + %rep %0-1 + %xdefine %%tmp m%1 + %xdefine m%1 m%2 + %xdefine m%2 %%tmp + CAT_XDEFINE nn, m%1, %1 + CAT_XDEFINE nn, m%2, %2 + %rotate 1 + %endrep +%endmacro + +%macro SWAP_INTERNAL_NAME 2-* + %xdefine %%args nn %+ %1 + %rep %0-1 + %xdefine %%args %%args, nn %+ %2 + %rotate 1 + %endrep + SWAP_INTERNAL_NUM %%args +%endmacro + +; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later +; calls to that function will automatically load the permutation, so values can +; be returned in mmregs. +%macro SAVE_MM_PERMUTATION 0-1 + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif + %assign %%i 0 + %rep num_mmregs + %xdefine %%tmp m %+ %%i + CAT_XDEFINE %%f, %%i, regnumof %+ %%tmp + %assign %%i %%i+1 + %endrep +%endmacro + +%macro LOAD_MM_PERMUTATION 0-1 ; name to load from + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif + %xdefine %%tmp %%f %+ 0 + %ifnum %%tmp + DEFINE_MMREGS mmtype + %assign %%i 0 + %rep num_mmregs + %xdefine %%tmp %%f %+ %%i + CAT_XDEFINE %%m, %%i, m %+ %%tmp + %assign %%i %%i+1 + %endrep + %rep num_mmregs + %assign %%i %%i-1 + CAT_XDEFINE m, %%i, %%m %+ %%i + CAT_XDEFINE nn, m %+ %%i, %%i + %endrep + %endif +%endmacro + +; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't +%macro call 1 + %ifid %1 + call_internal %1 %+ SUFFIX, %1 + %else + call %1 + %endif +%endmacro +%macro call_internal 2 + %xdefine %%i %2 + %ifndef cglobaled_%2 + %ifdef cglobaled_%1 + %xdefine %%i %1 + %endif + %endif + call %%i + LOAD_MM_PERMUTATION %%i +%endmacro + +; Substitutions that reduce instruction size but are functionally equivalent +%macro add 2 + %ifnum %2 + %if %2==128 + sub %1, -128 + %else + add %1, %2 + %endif + %else + add %1, %2 + %endif +%endmacro + +%macro sub 2 + %ifnum %2 + %if %2==128 + add %1, -128 + %else + sub %1, %2 + %endif + %else + sub %1, %2 + %endif +%endmacro + +;============================================================================= +; AVX abstraction layer +;============================================================================= + +%assign i 0 +%rep 32 + %if i < 8 + CAT_XDEFINE sizeofmm, i, 8 + CAT_XDEFINE regnumofmm, i, i + %endif + CAT_XDEFINE sizeofxmm, i, 16 + CAT_XDEFINE sizeofymm, i, 32 + CAT_XDEFINE sizeofzmm, i, 64 + CAT_XDEFINE regnumofxmm, i, i + CAT_XDEFINE regnumofymm, i, i + CAT_XDEFINE regnumofzmm, i, i + %assign i i+1 +%endrep +%undef i + +%macro CHECK_AVX_INSTR_EMU 3-* + %xdefine %%opcode %1 + %xdefine %%dst %2 + %rep %0-2 + %ifidn %%dst, %3 + %error non-avx emulation of ``%%opcode'' is not supported + %endif + %rotate 1 + %endrep +%endmacro + +;%1 == instruction +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +;%6+: operands +%macro RUN_AVX_INSTR 6-9+ + %ifnum sizeof%7 + %assign __sizeofreg sizeof%7 + %elifnum sizeof%6 + %assign __sizeofreg sizeof%6 + %else + %assign __sizeofreg mmsize + %endif + %assign __emulate_avx 0 + %if avx_enabled && __sizeofreg >= 16 + %xdefine __instr v%1 + %else + %xdefine __instr %1 + %if %0 >= 8+%4 + %assign __emulate_avx 1 + %endif + %endif + %ifnidn %2, fnord + %ifdef cpuname + %if notcpuflag(%2) + %error use of ``%1'' %2 instruction in cpuname function: current_function + %elif %3 == 0 && __sizeofreg == 16 && notcpuflag(sse2) + %error use of ``%1'' sse2 instruction in cpuname function: current_function + %elif %3 == 0 && __sizeofreg == 32 && notcpuflag(avx2) + %error use of ``%1'' avx2 instruction in cpuname function: current_function + %elif __sizeofreg == 16 && notcpuflag(sse) + %error use of ``%1'' sse instruction in cpuname function: current_function + %elif __sizeofreg == 32 && notcpuflag(avx) + %error use of ``%1'' avx instruction in cpuname function: current_function + %elif __sizeofreg == 64 && notcpuflag(avx512) + %error use of ``%1'' avx512 instruction in cpuname function: current_function + %elifidn %1, pextrw ; special case because the base instruction is mmx2, + %ifnid %6 ; but sse4 is required for memory operands + %if notcpuflag(sse4) + %error use of ``%1'' sse4 instruction in cpuname function: current_function + %endif + %endif + %endif + %endif + %endif + + %if __emulate_avx + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 && %4 == 0 + %ifnidn %6, %7 + %ifidn %6, %8 + %xdefine __src1 %8 + %xdefine __src2 %7 + %elifnnum sizeof%8 + ; 3-operand AVX instructions with a memory arg can only have it in src2, + ; whereas SSE emulation prefers to have it in src1 (i.e. the mov). + ; So, if the instruction is commutative with a memory arg, swap them. + %xdefine __src1 %8 + %xdefine __src2 %7 + %endif + %endif + %endif + %ifnidn %6, __src1 + %if %0 >= 9 + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, __src2, %9 + %else + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, __src2 + %endif + %if __sizeofreg == 8 + MOVQ %6, __src1 + %elif %3 + MOVAPS %6, __src1 + %else + MOVDQA %6, __src1 + %endif + %endif + %if %0 >= 9 + %1 %6, __src2, %9 + %else + %1 %6, __src2 + %endif + %elif %0 >= 9 + %if avx_enabled && __sizeofreg >= 16 && %4 == 1 + %ifnnum regnumof%7 + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8, %9 + %else + __instr %6, %7, %8, %9 + %endif + %else + __instr %6, %7, %8, %9 + %endif + %elif %0 == 8 + %if avx_enabled && __sizeofreg >= 16 && %4 == 0 + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 + %ifnum regnumof%7 + %ifnum regnumof%8 + %if regnumof%7 < 8 && regnumof%8 >= 8 && regnumof%8 < 16 && sizeof%8 <= 32 + ; Most VEX-encoded instructions require an additional byte to encode when + ; src2 is a high register (e.g. m8..15). If the instruction is commutative + ; we can swap src1 and src2 when doing so reduces the instruction length. + %xdefine __src1 %8 + %xdefine __src2 %7 + %endif + %endif + %elifnum regnumof%8 ; put memory operands in src2 when possible + %xdefine __src1 %8 + %xdefine __src2 %7 + %else + %assign __emulate_avx 1 + %endif + %elifnnum regnumof%7 + ; EVEX allows imm8 shift instructions to be used with memory operands, + ; but VEX does not. This handles those special cases. + %ifnnum %8 + %assign __emulate_avx 1 + %elif notcpuflag(avx512) + %assign __emulate_avx 1 + %endif + %endif + %if __emulate_avx ; a separate load is required + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8 + %else + __instr %6, __src1, __src2 + %endif + %else + __instr %6, %7, %8 + %endif + %elif %0 == 7 + %if avx_enabled && __sizeofreg >= 16 && %5 + %xdefine __src1 %6 + %xdefine __src2 %7 + %ifnum regnumof%6 + %ifnum regnumof%7 + %if regnumof%6 < 8 && regnumof%7 >= 8 && regnumof%7 < 16 && sizeof%7 <= 32 + %xdefine __src1 %7 + %xdefine __src2 %6 + %endif + %endif + %endif + __instr %6, __src1, __src2 + %else + __instr %6, %7 + %endif + %else + __instr %6 + %endif +%endmacro + +;%1 == instruction +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +%macro AVX_INSTR 1-5 fnord, 0, 255, 0 + %macro %1 1-10 fnord, fnord, fnord, fnord, %1, %2, %3, %4, %5 + %ifidn %2, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1 + %elifidn %3, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2 + %elifidn %4, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3 + %elifidn %5, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4 + %else + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4, %5 + %endif + %endmacro +%endmacro + +; Instructions with both VEX/EVEX and legacy encodings +; Non-destructive instructions are written without parameters +AVX_INSTR addpd, sse2, 1, 0, 1 +AVX_INSTR addps, sse, 1, 0, 1 +AVX_INSTR addsd, sse2, 1, 0, 0 +AVX_INSTR addss, sse, 1, 0, 0 +AVX_INSTR addsubpd, sse3, 1, 0, 0 +AVX_INSTR addsubps, sse3, 1, 0, 0 +AVX_INSTR aesdec, aesni, 0, 0, 0 +AVX_INSTR aesdeclast, aesni, 0, 0, 0 +AVX_INSTR aesenc, aesni, 0, 0, 0 +AVX_INSTR aesenclast, aesni, 0, 0, 0 +AVX_INSTR aesimc, aesni +AVX_INSTR aeskeygenassist, aesni +AVX_INSTR andnpd, sse2, 1, 0, 0 +AVX_INSTR andnps, sse, 1, 0, 0 +AVX_INSTR andpd, sse2, 1, 0, 1 +AVX_INSTR andps, sse, 1, 0, 1 +AVX_INSTR blendpd, sse4, 1, 1, 0 +AVX_INSTR blendps, sse4, 1, 1, 0 +AVX_INSTR blendvpd, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR blendvps, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR cmpeqpd, sse2, 1, 0, 1 +AVX_INSTR cmpeqps, sse, 1, 0, 1 +AVX_INSTR cmpeqsd, sse2, 1, 0, 0 +AVX_INSTR cmpeqss, sse, 1, 0, 0 +AVX_INSTR cmplepd, sse2, 1, 0, 0 +AVX_INSTR cmpleps, sse, 1, 0, 0 +AVX_INSTR cmplesd, sse2, 1, 0, 0 +AVX_INSTR cmpless, sse, 1, 0, 0 +AVX_INSTR cmpltpd, sse2, 1, 0, 0 +AVX_INSTR cmpltps, sse, 1, 0, 0 +AVX_INSTR cmpltsd, sse2, 1, 0, 0 +AVX_INSTR cmpltss, sse, 1, 0, 0 +AVX_INSTR cmpneqpd, sse2, 1, 0, 1 +AVX_INSTR cmpneqps, sse, 1, 0, 1 +AVX_INSTR cmpneqsd, sse2, 1, 0, 0 +AVX_INSTR cmpneqss, sse, 1, 0, 0 +AVX_INSTR cmpnlepd, sse2, 1, 0, 0 +AVX_INSTR cmpnleps, sse, 1, 0, 0 +AVX_INSTR cmpnlesd, sse2, 1, 0, 0 +AVX_INSTR cmpnless, sse, 1, 0, 0 +AVX_INSTR cmpnltpd, sse2, 1, 0, 0 +AVX_INSTR cmpnltps, sse, 1, 0, 0 +AVX_INSTR cmpnltsd, sse2, 1, 0, 0 +AVX_INSTR cmpnltss, sse, 1, 0, 0 +AVX_INSTR cmpordpd, sse2 1, 0, 1 +AVX_INSTR cmpordps, sse 1, 0, 1 +AVX_INSTR cmpordsd, sse2 1, 0, 0 +AVX_INSTR cmpordss, sse 1, 0, 0 +AVX_INSTR cmppd, sse2, 1, 1, 0 +AVX_INSTR cmpps, sse, 1, 1, 0 +AVX_INSTR cmpsd, sse2, 1, 1, 0 +AVX_INSTR cmpss, sse, 1, 1, 0 +AVX_INSTR cmpunordpd, sse2, 1, 0, 1 +AVX_INSTR cmpunordps, sse, 1, 0, 1 +AVX_INSTR cmpunordsd, sse2, 1, 0, 0 +AVX_INSTR cmpunordss, sse, 1, 0, 0 +AVX_INSTR comisd, sse2, 1 +AVX_INSTR comiss, sse, 1 +AVX_INSTR cvtdq2pd, sse2, 1 +AVX_INSTR cvtdq2ps, sse2, 1 +AVX_INSTR cvtpd2dq, sse2, 1 +AVX_INSTR cvtpd2ps, sse2, 1 +AVX_INSTR cvtps2dq, sse2, 1 +AVX_INSTR cvtps2pd, sse2, 1 +AVX_INSTR cvtsd2si, sse2, 1 +AVX_INSTR cvtsd2ss, sse2, 1, 0, 0 +AVX_INSTR cvtsi2sd, sse2, 1, 0, 0 +AVX_INSTR cvtsi2ss, sse, 1, 0, 0 +AVX_INSTR cvtss2sd, sse2, 1, 0, 0 +AVX_INSTR cvtss2si, sse, 1 +AVX_INSTR cvttpd2dq, sse2, 1 +AVX_INSTR cvttps2dq, sse2, 1 +AVX_INSTR cvttsd2si, sse2, 1 +AVX_INSTR cvttss2si, sse, 1 +AVX_INSTR divpd, sse2, 1, 0, 0 +AVX_INSTR divps, sse, 1, 0, 0 +AVX_INSTR divsd, sse2, 1, 0, 0 +AVX_INSTR divss, sse, 1, 0, 0 +AVX_INSTR dppd, sse4, 1, 1, 0 +AVX_INSTR dpps, sse4, 1, 1, 0 +AVX_INSTR extractps, sse4, 1 +AVX_INSTR gf2p8affineinvqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8affineqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8mulb, gfni, 0, 0, 0 +AVX_INSTR haddpd, sse3, 1, 0, 0 +AVX_INSTR haddps, sse3, 1, 0, 0 +AVX_INSTR hsubpd, sse3, 1, 0, 0 +AVX_INSTR hsubps, sse3, 1, 0, 0 +AVX_INSTR insertps, sse4, 1, 1, 0 +AVX_INSTR lddqu, sse3 +AVX_INSTR ldmxcsr, sse, 1 +AVX_INSTR maskmovdqu, sse2 +AVX_INSTR maxpd, sse2, 1, 0, 1 +AVX_INSTR maxps, sse, 1, 0, 1 +AVX_INSTR maxsd, sse2, 1, 0, 0 +AVX_INSTR maxss, sse, 1, 0, 0 +AVX_INSTR minpd, sse2, 1, 0, 1 +AVX_INSTR minps, sse, 1, 0, 1 +AVX_INSTR minsd, sse2, 1, 0, 0 +AVX_INSTR minss, sse, 1, 0, 0 +AVX_INSTR movapd, sse2, 1 +AVX_INSTR movaps, sse, 1 +AVX_INSTR movd, mmx +AVX_INSTR movddup, sse3, 1 +AVX_INSTR movdqa, sse2 +AVX_INSTR movdqu, sse2 +AVX_INSTR movhlps, sse, 1, 0, 0 +AVX_INSTR movhpd, sse2, 1, 0, 0 +AVX_INSTR movhps, sse, 1, 0, 0 +AVX_INSTR movlhps, sse, 1, 0, 0 +AVX_INSTR movlpd, sse2, 1, 0, 0 +AVX_INSTR movlps, sse, 1, 0, 0 +AVX_INSTR movmskpd, sse2, 1 +AVX_INSTR movmskps, sse, 1 +AVX_INSTR movntdq, sse2 +AVX_INSTR movntdqa, sse4 +AVX_INSTR movntpd, sse2, 1 +AVX_INSTR movntps, sse, 1 +AVX_INSTR movq, mmx +AVX_INSTR movsd, sse2, 1, 0, 0 +AVX_INSTR movshdup, sse3, 1 +AVX_INSTR movsldup, sse3, 1 +AVX_INSTR movss, sse, 1, 0, 0 +AVX_INSTR movupd, sse2, 1 +AVX_INSTR movups, sse, 1 +AVX_INSTR mpsadbw, sse4, 0, 1, 0 +AVX_INSTR mulpd, sse2, 1, 0, 1 +AVX_INSTR mulps, sse, 1, 0, 1 +AVX_INSTR mulsd, sse2, 1, 0, 0 +AVX_INSTR mulss, sse, 1, 0, 0 +AVX_INSTR orpd, sse2, 1, 0, 1 +AVX_INSTR orps, sse, 1, 0, 1 +AVX_INSTR pabsb, ssse3 +AVX_INSTR pabsd, ssse3 +AVX_INSTR pabsw, ssse3 +AVX_INSTR packssdw, mmx, 0, 0, 0 +AVX_INSTR packsswb, mmx, 0, 0, 0 +AVX_INSTR packusdw, sse4, 0, 0, 0 +AVX_INSTR packuswb, mmx, 0, 0, 0 +AVX_INSTR paddb, mmx, 0, 0, 1 +AVX_INSTR paddd, mmx, 0, 0, 1 +AVX_INSTR paddq, sse2, 0, 0, 1 +AVX_INSTR paddsb, mmx, 0, 0, 1 +AVX_INSTR paddsw, mmx, 0, 0, 1 +AVX_INSTR paddusb, mmx, 0, 0, 1 +AVX_INSTR paddusw, mmx, 0, 0, 1 +AVX_INSTR paddw, mmx, 0, 0, 1 +AVX_INSTR palignr, ssse3, 0, 1, 0 +AVX_INSTR pand, mmx, 0, 0, 1 +AVX_INSTR pandn, mmx, 0, 0, 0 +AVX_INSTR pavgb, mmx2, 0, 0, 1 +AVX_INSTR pavgw, mmx2, 0, 0, 1 +AVX_INSTR pblendvb, sse4, 0, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR pblendw, sse4, 0, 1, 0 +AVX_INSTR pclmulhqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmulhqlqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqlqdq, fnord, 0, 0, 0 +AVX_INSTR pclmulqdq, fnord, 0, 1, 0 +AVX_INSTR pcmpeqb, mmx, 0, 0, 1 +AVX_INSTR pcmpeqd, mmx, 0, 0, 1 +AVX_INSTR pcmpeqq, sse4, 0, 0, 1 +AVX_INSTR pcmpeqw, mmx, 0, 0, 1 +AVX_INSTR pcmpestri, sse42 +AVX_INSTR pcmpestrm, sse42 +AVX_INSTR pcmpgtb, mmx, 0, 0, 0 +AVX_INSTR pcmpgtd, mmx, 0, 0, 0 +AVX_INSTR pcmpgtq, sse42, 0, 0, 0 +AVX_INSTR pcmpgtw, mmx, 0, 0, 0 +AVX_INSTR pcmpistri, sse42 +AVX_INSTR pcmpistrm, sse42 +AVX_INSTR pextrb, sse4 +AVX_INSTR pextrd, sse4 +AVX_INSTR pextrq, sse4 +AVX_INSTR pextrw, mmx2 +AVX_INSTR phaddd, ssse3, 0, 0, 0 +AVX_INSTR phaddsw, ssse3, 0, 0, 0 +AVX_INSTR phaddw, ssse3, 0, 0, 0 +AVX_INSTR phminposuw, sse4 +AVX_INSTR phsubd, ssse3, 0, 0, 0 +AVX_INSTR phsubsw, ssse3, 0, 0, 0 +AVX_INSTR phsubw, ssse3, 0, 0, 0 +AVX_INSTR pinsrb, sse4, 0, 1, 0 +AVX_INSTR pinsrd, sse4, 0, 1, 0 +AVX_INSTR pinsrq, sse4, 0, 1, 0 +AVX_INSTR pinsrw, mmx2, 0, 1, 0 +AVX_INSTR pmaddubsw, ssse3, 0, 0, 0 +AVX_INSTR pmaddwd, mmx, 0, 0, 1 +AVX_INSTR pmaxsb, sse4, 0, 0, 1 +AVX_INSTR pmaxsd, sse4, 0, 0, 1 +AVX_INSTR pmaxsw, mmx2, 0, 0, 1 +AVX_INSTR pmaxub, mmx2, 0, 0, 1 +AVX_INSTR pmaxud, sse4, 0, 0, 1 +AVX_INSTR pmaxuw, sse4, 0, 0, 1 +AVX_INSTR pminsb, sse4, 0, 0, 1 +AVX_INSTR pminsd, sse4, 0, 0, 1 +AVX_INSTR pminsw, mmx2, 0, 0, 1 +AVX_INSTR pminub, mmx2, 0, 0, 1 +AVX_INSTR pminud, sse4, 0, 0, 1 +AVX_INSTR pminuw, sse4, 0, 0, 1 +AVX_INSTR pmovmskb, mmx2 +AVX_INSTR pmovsxbd, sse4 +AVX_INSTR pmovsxbq, sse4 +AVX_INSTR pmovsxbw, sse4 +AVX_INSTR pmovsxdq, sse4 +AVX_INSTR pmovsxwd, sse4 +AVX_INSTR pmovsxwq, sse4 +AVX_INSTR pmovzxbd, sse4 +AVX_INSTR pmovzxbq, sse4 +AVX_INSTR pmovzxbw, sse4 +AVX_INSTR pmovzxdq, sse4 +AVX_INSTR pmovzxwd, sse4 +AVX_INSTR pmovzxwq, sse4 +AVX_INSTR pmuldq, sse4, 0, 0, 1 +AVX_INSTR pmulhrsw, ssse3, 0, 0, 1 +AVX_INSTR pmulhuw, mmx2, 0, 0, 1 +AVX_INSTR pmulhw, mmx, 0, 0, 1 +AVX_INSTR pmulld, sse4, 0, 0, 1 +AVX_INSTR pmullw, mmx, 0, 0, 1 +AVX_INSTR pmuludq, sse2, 0, 0, 1 +AVX_INSTR por, mmx, 0, 0, 1 +AVX_INSTR psadbw, mmx2, 0, 0, 1 +AVX_INSTR pshufb, ssse3, 0, 0, 0 +AVX_INSTR pshufd, sse2 +AVX_INSTR pshufhw, sse2 +AVX_INSTR pshuflw, sse2 +AVX_INSTR psignb, ssse3, 0, 0, 0 +AVX_INSTR psignd, ssse3, 0, 0, 0 +AVX_INSTR psignw, ssse3, 0, 0, 0 +AVX_INSTR pslld, mmx, 0, 0, 0 +AVX_INSTR pslldq, sse2, 0, 0, 0 +AVX_INSTR psllq, mmx, 0, 0, 0 +AVX_INSTR psllw, mmx, 0, 0, 0 +AVX_INSTR psrad, mmx, 0, 0, 0 +AVX_INSTR psraw, mmx, 0, 0, 0 +AVX_INSTR psrld, mmx, 0, 0, 0 +AVX_INSTR psrldq, sse2, 0, 0, 0 +AVX_INSTR psrlq, mmx, 0, 0, 0 +AVX_INSTR psrlw, mmx, 0, 0, 0 +AVX_INSTR psubb, mmx, 0, 0, 0 +AVX_INSTR psubd, mmx, 0, 0, 0 +AVX_INSTR psubq, sse2, 0, 0, 0 +AVX_INSTR psubsb, mmx, 0, 0, 0 +AVX_INSTR psubsw, mmx, 0, 0, 0 +AVX_INSTR psubusb, mmx, 0, 0, 0 +AVX_INSTR psubusw, mmx, 0, 0, 0 +AVX_INSTR psubw, mmx, 0, 0, 0 +AVX_INSTR ptest, sse4 +AVX_INSTR punpckhbw, mmx, 0, 0, 0 +AVX_INSTR punpckhdq, mmx, 0, 0, 0 +AVX_INSTR punpckhqdq, sse2, 0, 0, 0 +AVX_INSTR punpckhwd, mmx, 0, 0, 0 +AVX_INSTR punpcklbw, mmx, 0, 0, 0 +AVX_INSTR punpckldq, mmx, 0, 0, 0 +AVX_INSTR punpcklqdq, sse2, 0, 0, 0 +AVX_INSTR punpcklwd, mmx, 0, 0, 0 +AVX_INSTR pxor, mmx, 0, 0, 1 +AVX_INSTR rcpps, sse, 1 +AVX_INSTR rcpss, sse, 1, 0, 0 +AVX_INSTR roundpd, sse4, 1 +AVX_INSTR roundps, sse4, 1 +AVX_INSTR roundsd, sse4, 1, 1, 0 +AVX_INSTR roundss, sse4, 1, 1, 0 +AVX_INSTR rsqrtps, sse, 1 +AVX_INSTR rsqrtss, sse, 1, 0, 0 +AVX_INSTR shufpd, sse2, 1, 1, 0 +AVX_INSTR shufps, sse, 1, 1, 0 +AVX_INSTR sqrtpd, sse2, 1 +AVX_INSTR sqrtps, sse, 1 +AVX_INSTR sqrtsd, sse2, 1, 0, 0 +AVX_INSTR sqrtss, sse, 1, 0, 0 +AVX_INSTR stmxcsr, sse, 1 +AVX_INSTR subpd, sse2, 1, 0, 0 +AVX_INSTR subps, sse, 1, 0, 0 +AVX_INSTR subsd, sse2, 1, 0, 0 +AVX_INSTR subss, sse, 1, 0, 0 +AVX_INSTR ucomisd, sse2, 1 +AVX_INSTR ucomiss, sse, 1 +AVX_INSTR unpckhpd, sse2, 1, 0, 0 +AVX_INSTR unpckhps, sse, 1, 0, 0 +AVX_INSTR unpcklpd, sse2, 1, 0, 0 +AVX_INSTR unpcklps, sse, 1, 0, 0 +AVX_INSTR xorpd, sse2, 1, 0, 1 +AVX_INSTR xorps, sse, 1, 0, 1 + +; 3DNow instructions, for sharing code between AVX, SSE and 3DN +AVX_INSTR pfadd, 3dnow, 1, 0, 1 +AVX_INSTR pfmul, 3dnow, 1, 0, 1 +AVX_INSTR pfsub, 3dnow, 1, 0, 0 + +;%1 == instruction +;%2 == minimal instruction set +%macro GPR_INSTR 2 + %macro %1 2-5 fnord, %1, %2 + %ifdef cpuname + %if notcpuflag(%5) + %error use of ``%4'' %5 instruction in cpuname function: current_function + %endif + %endif + %ifidn %3, fnord + %4 %1, %2 + %else + %4 %1, %2, %3 + %endif + %endmacro +%endmacro + +GPR_INSTR andn, bmi1 +GPR_INSTR bextr, bmi1 +GPR_INSTR blsi, bmi1 +GPR_INSTR blsmsk, bmi1 +GPR_INSTR blsr, bmi1 +GPR_INSTR bzhi, bmi2 +GPR_INSTR mulx, bmi2 +GPR_INSTR pdep, bmi2 +GPR_INSTR pext, bmi2 +GPR_INSTR popcnt, sse42 +GPR_INSTR rorx, bmi2 +GPR_INSTR sarx, bmi2 +GPR_INSTR shlx, bmi2 +GPR_INSTR shrx, bmi2 + +; base-4 constants for shuffles +%assign i 0 +%rep 256 + %assign j ((i>>6)&3)*1000 + ((i>>4)&3)*100 + ((i>>2)&3)*10 + (i&3) + %if j < 10 + CAT_XDEFINE q000, j, i + %elif j < 100 + CAT_XDEFINE q00, j, i + %elif j < 1000 + CAT_XDEFINE q0, j, i + %else + CAT_XDEFINE q, j, i + %endif + %assign i i+1 +%endrep +%undef i +%undef j + +%macro FMA_INSTR 3 + %macro %1 4-7 %1, %2, %3 + %if cpuflag(xop) + v%5 %1, %2, %3, %4 + %elifnidn %1, %4 + %6 %1, %2, %3 + %7 %1, %4 + %else + %error non-xop emulation of ``%5 %1, %2, %3, %4'' is not supported + %endif + %endmacro +%endmacro + +FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation +FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation +FMA_INSTR pmacsww, pmullw, paddw +FMA_INSTR pmadcswd, pmaddwd, paddd + +; Macros for consolidating FMA3 and FMA4 using 4-operand (dst, src1, src2, src3) syntax. +; FMA3 is only possible if dst is the same as one of the src registers. +; Either src2 or src3 can be a memory operand. +%macro FMA4_INSTR 2-* + %push fma4_instr + %xdefine %$prefix %1 + %rep %0 - 1 + %macro %$prefix%2 4-6 %$prefix, %2 + %if notcpuflag(fma3) && notcpuflag(fma4) + %error use of ``%5%6'' fma instruction in cpuname function: current_function + %elif cpuflag(fma4) + v%5%6 %1, %2, %3, %4 + %elifidn %1, %2 + ; If %3 or %4 is a memory operand it needs to be encoded as the last operand. + %ifnum sizeof%3 + v%{5}213%6 %2, %3, %4 + %else + v%{5}132%6 %2, %4, %3 + %endif + %elifidn %1, %3 + v%{5}213%6 %3, %2, %4 + %elifidn %1, %4 + v%{5}231%6 %4, %2, %3 + %else + %error fma3 emulation of ``%5%6 %1, %2, %3, %4'' is not supported + %endif + %endmacro + %rotate 1 + %endrep + %pop +%endmacro + +FMA4_INSTR fmadd, pd, ps, sd, ss +FMA4_INSTR fmaddsub, pd, ps +FMA4_INSTR fmsub, pd, ps, sd, ss +FMA4_INSTR fmsubadd, pd, ps +FMA4_INSTR fnmadd, pd, ps, sd, ss +FMA4_INSTR fnmsub, pd, ps, sd, ss + +; Macros for converting VEX instructions to equivalent EVEX ones. +%macro EVEX_INSTR 2-3 0 ; vex, evex, prefer_evex + %macro %1 2-7 fnord, fnord, %1, %2, %3 + %ifidn %3, fnord + %define %%args %1, %2 + %elifidn %4, fnord + %define %%args %1, %2, %3 + %else + %define %%args %1, %2, %3, %4 + %endif + %assign %%evex_required cpuflag(avx512) & %7 + %ifnum regnumof%1 + %if regnumof%1 >= 16 || sizeof%1 > 32 + %assign %%evex_required 1 + %endif + %endif + %ifnum regnumof%2 + %if regnumof%2 >= 16 || sizeof%2 > 32 + %assign %%evex_required 1 + %endif + %endif + %ifnum regnumof%3 + %if regnumof%3 >= 16 || sizeof%3 > 32 + %assign %%evex_required 1 + %endif + %endif + %if %%evex_required + %6 %%args + %else + %5 %%args ; Prefer VEX over EVEX due to shorter instruction length + %endif + %endmacro +%endmacro + +EVEX_INSTR vbroadcastf128, vbroadcastf32x4 +EVEX_INSTR vbroadcasti128, vbroadcasti32x4 +EVEX_INSTR vextractf128, vextractf32x4 +EVEX_INSTR vextracti128, vextracti32x4 +EVEX_INSTR vinsertf128, vinsertf32x4 +EVEX_INSTR vinserti128, vinserti32x4 +EVEX_INSTR vmovdqa, vmovdqa32 +EVEX_INSTR vmovdqu, vmovdqu32 +EVEX_INSTR vpand, vpandd +EVEX_INSTR vpandn, vpandnd +EVEX_INSTR vpor, vpord +EVEX_INSTR vpxor, vpxord +EVEX_INSTR vrcpps, vrcp14ps, 1 ; EVEX versions have higher precision +EVEX_INSTR vrcpss, vrcp14ss, 1 +EVEX_INSTR vrsqrtps, vrsqrt14ps, 1 +EVEX_INSTR vrsqrtss, vrsqrt14ss, 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/cpu.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/cpu.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/cpu.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/cpu.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,309 @@ +#[cfg(asm_neon)] +pub use neon::*; +#[cfg(not(any(asm_x86_64, asm_neon)))] +pub use rust::*; +#[cfg(asm_x86_64)] +pub use x86::*; + +#[cfg(not(any(asm_x86_64, asm_neon)))] +mod rust { + use arg_enum_proc_macro::ArgEnum; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum, Default)] + #[allow(clippy::upper_case_acronyms)] + + pub enum CpuFeatureLevel { + #[default] + RUST, + } + + impl CpuFeatureLevel { + #[cfg(test)] + #[allow(unused)] + #[inline] + pub const fn all() -> &'static [Self] { + use CpuFeatureLevel::*; + &[RUST] + } + } +} + +#[cfg(asm_x86_64)] +#[macro_use] +mod x86 { + use std::{env, str::FromStr}; + + use arg_enum_proc_macro::ArgEnum; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum)] + #[allow(clippy::upper_case_acronyms)] + pub enum CpuFeatureLevel { + RUST, + SSE2, + SSSE3, + #[arg_enum(alias = "sse4.1")] + SSE4_1, + AVX2, + AVX512, + #[arg_enum(alias = "avx512vpclmulqdq")] + AVX512ICL, + } + + impl CpuFeatureLevel { + #[cfg(test)] + pub const fn all() -> &'static [Self] { + &[ + CpuFeatureLevel::RUST, + CpuFeatureLevel::SSE2, + CpuFeatureLevel::SSSE3, + CpuFeatureLevel::SSE4_1, + CpuFeatureLevel::AVX2, + CpuFeatureLevel::AVX512, + CpuFeatureLevel::AVX512ICL, + ] + } + + #[inline] + pub const fn len() -> usize { + CpuFeatureLevel::AVX512ICL as usize + 1 + } + + #[inline] + pub const fn as_index(self) -> usize { + self as usize + } + } + + impl Default for CpuFeatureLevel { + #[inline] + fn default() -> CpuFeatureLevel { + fn avx512_detected() -> bool { + is_x86_feature_detected!("avx512bw") + && is_x86_feature_detected!("avx512cd") + && is_x86_feature_detected!("avx512dq") + && is_x86_feature_detected!("avx512f") + && is_x86_feature_detected!("avx512vl") + } + #[allow(deprecated)] // Until MSRV >= 1.69.0 + fn avx512icl_detected() -> bool { + // Per dav1d, these are the flags needed. + avx512_detected() + && is_x86_feature_detected!("avx512vnni") + && is_x86_feature_detected!("avx512ifma") + && is_x86_feature_detected!("avx512vbmi") + && is_x86_feature_detected!("avx512vbmi2") + && is_x86_feature_detected!("avx512vpopcntdq") + && is_x86_feature_detected!("avx512bitalg") + && is_x86_feature_detected!("avx512gfni") + && is_x86_feature_detected!("avx512vaes") + && is_x86_feature_detected!("avx512vpclmulqdq") + } + + let detected: CpuFeatureLevel = if avx512icl_detected() { + CpuFeatureLevel::AVX512ICL + } else if avx512_detected() { + CpuFeatureLevel::AVX512 + } else if is_x86_feature_detected!("avx2") { + CpuFeatureLevel::AVX2 + } else if is_x86_feature_detected!("sse4.1") { + CpuFeatureLevel::SSE4_1 + } else if is_x86_feature_detected!("ssse3") { + CpuFeatureLevel::SSSE3 + } else if is_x86_feature_detected!("sse2") { + CpuFeatureLevel::SSE2 + } else { + CpuFeatureLevel::RUST + }; + let manual: CpuFeatureLevel = match env::var("CPU_TARGET") { + Ok(feature) => CpuFeatureLevel::from_str(&feature).unwrap_or(detected), + Err(_e) => detected, + }; + if manual > detected { + detected + } else { + manual + } + } + } + + // Create a static lookup table for CPUFeatureLevel enums + // Note: keys are CpuFeatureLevels without any prefix (no CpuFeatureLevel::) + macro_rules! cpu_function_lookup_table { + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + static $name: [$type; crate::cpu::CpuFeatureLevel::len()] = { + use crate::cpu::CpuFeatureLevel; + #[allow(unused_mut)] + let mut out: [$type; CpuFeatureLevel::len()] = [$empty; CpuFeatureLevel::len()]; + + // Can't use out[0][.] == $empty in static as of rust 1.40 + #[allow(unused_mut)] + let mut set: [bool; CpuFeatureLevel::len()] = [false; CpuFeatureLevel::len()]; + + #[allow(unused_imports)] + use CpuFeatureLevel::*; + $( + out[$key as usize] = $value; + set[$key as usize] = true; + )* + cpu_function_lookup_table!(waterfall_cpu_features(out, set, [SSE2, SSSE3, SSE4_1, AVX2, AVX512, AVX512ICL])); + out + }; + }; + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + $pub cpu_function_lookup_table!($name: [$type], default: $empty, [$(($key, $value)),*]); + }; + + // Fill empty output functions with the existent functions they support. + // cpus should be in order of lowest cpu level to highest + // Used like an internal function + // Put in here to avoid adding more public macros + (waterfall_cpu_features($out:ident, $set:ident, [$($cpu:ident),*])) => { + // Use an array to emulate if statements (not supported in static as of + // rust 1.40). Setting best[0] (false) and best[1] (true) is equivalent to + // doing nothing and overriding our value respectively. + #[allow(unused_assignments)] + let mut best = [$out[0], $out[0]]; + $( + // If the current entry has a function, update out best function. + best[$set[$cpu as usize] as usize] = $out[$cpu as usize]; + // Update our current entry. Does nothing if it already had a function. + $out[$cpu as usize] = best[1]; + )* + }; + + // use $name_$key as our values + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + pastey::item!{ + cpu_function_lookup_table!( + $pub, $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + pastey::item!{ + cpu_function_lookup_table!( + $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + } +} + +#[cfg(asm_neon)] +#[macro_use] +mod neon { + use std::{env, str::FromStr}; + + use arg_enum_proc_macro::ArgEnum; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum)] + #[allow(clippy::upper_case_acronyms)] + pub enum CpuFeatureLevel { + RUST, + NEON, + } + + impl CpuFeatureLevel { + #[cfg(test)] + #[inline] + pub const fn all() -> &'static [Self] { + use CpuFeatureLevel::*; + &[RUST, NEON] + } + + #[inline] + pub const fn len() -> usize { + CpuFeatureLevel::NEON as usize + 1 + } + + #[inline] + pub fn as_index(self) -> usize { + self as usize + } + } + + impl Default for CpuFeatureLevel { + #[inline] + fn default() -> CpuFeatureLevel { + let detected = CpuFeatureLevel::NEON; + let manual: CpuFeatureLevel = match env::var("CPU_TARGET") { + Ok(feature) => CpuFeatureLevel::from_str(&feature).unwrap_or(detected), + Err(_e) => detected, + }; + if manual > detected { + detected + } else { + manual + } + } + } + + // Create a static lookup table for CPUFeatureLevel enums + // Note: keys are CpuFeatureLevels without any prefix (no CpuFeatureLevel::) + macro_rules! cpu_function_lookup_table { + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + static $name: [$type; crate::cpu::CpuFeatureLevel::len()] = { + use crate::cpu::CpuFeatureLevel; + #[allow(unused_mut)] + let mut out: [$type; CpuFeatureLevel::len()] = [$empty; CpuFeatureLevel::len()]; + + // Can't use out[0][.] == $empty in static as of rust 1.40 + #[allow(unused_mut)] + let mut set: [bool; CpuFeatureLevel::len()] = [false; CpuFeatureLevel::len()]; + + #[allow(unused_imports)] + use CpuFeatureLevel::*; + $( + out[$key as usize] = $value; + set[$key as usize] = true; + )* + cpu_function_lookup_table!(waterfall_cpu_features(out, set, [NEON])); + out + }; + }; + + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + $pub cpu_function_lookup_table!($name: [$type], default: $empty, [$(($key, $value)),*]); + }; + // Fill empty output functions with the existent functions they support. + // cpus should be in order of lowest cpu level to highest + // Used like an internal function + // Put in here to avoid adding more public macros + (waterfall_cpu_features($out:ident, $set:ident, [$($cpu:ident),*])) => { + // Use an array to emulate if statements (not supported in static as of + // rust 1.40). Setting best[0] (false) and best[1] (true) is equivalent to + // doing nothing and overriding our value respectively. + #[allow(unused_assignments)] + let mut best = [$out[0], $out[0]]; + $( + // If the current entry has a function, update out best function. + best[$set[$cpu as usize] as usize] = $out[$cpu as usize]; + // Update our current entry. Does nothing if it already had a function. + $out[$cpu as usize] = best[1]; + )* + }; + + + // use $name_$key as our values + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + pastey::item!{ + cpu_function_lookup_table!( + $pub, $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + pastey::item!{ + cpu_function_lookup_table!( + $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/block.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/block.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/block.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/block.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,286 @@ +use std::{ + fmt, + fmt::Display, + ops::{Index, IndexMut}, +}; + +use thiserror::Error; +use v_frame::plane::PlaneOffset; + +use crate::data::{ + plane::PlaneBlockOffset, + superblock::{MI_SIZE_LOG2, SB_SIZE_LOG2}, +}; + +pub const MAX_TX_SIZE: usize = 64; +pub const BLOCK_TO_PLANE_SHIFT: usize = MI_SIZE_LOG2; +pub const MIB_SIZE_LOG2: usize = SB_SIZE_LOG2 - MI_SIZE_LOG2; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(test, derive(Default))] +#[allow(non_camel_case_types)] +pub enum BlockSize { + BLOCK_4X4, + BLOCK_4X8, + BLOCK_8X4, + BLOCK_8X8, + BLOCK_8X16, + BLOCK_16X8, + BLOCK_16X16, + BLOCK_16X32, + BLOCK_32X16, + BLOCK_32X32, + BLOCK_32X64, + BLOCK_64X32, + #[cfg_attr(test, default)] + BLOCK_64X64, + BLOCK_64X128, + BLOCK_128X64, + BLOCK_128X128, + BLOCK_4X16, + BLOCK_16X4, + BLOCK_8X32, + BLOCK_32X8, + BLOCK_16X64, + BLOCK_64X16, +} + +impl BlockSize { + /// # Errors + /// + /// - Returns `InvalidBlockSize` if the given `w` and `h` do not produce a + /// valid block size. + pub fn from_width_and_height_opt(w: usize, h: usize) -> Result { + use crate::data::block::BlockSize::*; + + match (w, h) { + (4, 4) => Ok(BLOCK_4X4), + (4, 8) => Ok(BLOCK_4X8), + (4, 16) => Ok(BLOCK_4X16), + (8, 4) => Ok(BLOCK_8X4), + (8, 8) => Ok(BLOCK_8X8), + (8, 16) => Ok(BLOCK_8X16), + (8, 32) => Ok(BLOCK_8X32), + (16, 4) => Ok(BLOCK_16X4), + (16, 8) => Ok(BLOCK_16X8), + (16, 16) => Ok(BLOCK_16X16), + (16, 32) => Ok(BLOCK_16X32), + (16, 64) => Ok(BLOCK_16X64), + (32, 8) => Ok(BLOCK_32X8), + (32, 16) => Ok(BLOCK_32X16), + (32, 32) => Ok(BLOCK_32X32), + (32, 64) => Ok(BLOCK_32X64), + (64, 16) => Ok(BLOCK_64X16), + (64, 32) => Ok(BLOCK_64X32), + (64, 64) => Ok(BLOCK_64X64), + (64, 128) => Ok(BLOCK_64X128), + (128, 64) => Ok(BLOCK_128X64), + (128, 128) => Ok(BLOCK_128X128), + _ => Err(InvalidBlockSize), + } + } + + /// # Panics + /// + /// - If the given `w` and `h` do not produce a valid block size. + pub fn from_width_and_height(w: usize, h: usize) -> BlockSize { + Self::from_width_and_height_opt(w, h).unwrap() + } + + pub const fn width(self) -> usize { + 1 << self.width_log2() + } + + pub const fn width_log2(self) -> usize { + use crate::data::block::BlockSize::*; + + match self { + BLOCK_4X4 | BLOCK_4X8 | BLOCK_4X16 => 2, + BLOCK_8X4 | BLOCK_8X8 | BLOCK_8X16 | BLOCK_8X32 => 3, + BLOCK_16X4 | BLOCK_16X8 | BLOCK_16X16 | BLOCK_16X32 | BLOCK_16X64 => 4, + BLOCK_32X8 | BLOCK_32X16 | BLOCK_32X32 | BLOCK_32X64 => 5, + BLOCK_64X16 | BLOCK_64X32 | BLOCK_64X64 | BLOCK_64X128 => 6, + BLOCK_128X64 | BLOCK_128X128 => 7, + } + } + + pub const fn height(self) -> usize { + 1 << self.height_log2() + } + + pub const fn height_log2(self) -> usize { + use crate::data::block::BlockSize::*; + + match self { + BLOCK_4X4 | BLOCK_8X4 | BLOCK_16X4 => 2, + BLOCK_4X8 | BLOCK_8X8 | BLOCK_16X8 | BLOCK_32X8 => 3, + BLOCK_4X16 | BLOCK_8X16 | BLOCK_16X16 | BLOCK_32X16 | BLOCK_64X16 => 4, + BLOCK_8X32 | BLOCK_16X32 | BLOCK_32X32 | BLOCK_64X32 => 5, + BLOCK_16X64 | BLOCK_32X64 | BLOCK_64X64 | BLOCK_128X64 => 6, + BLOCK_64X128 | BLOCK_128X128 => 7, + } + } + + pub const fn tx_size(self) -> TxSize { + use crate::data::block::{BlockSize::*, TxSize::*}; + + match self { + BLOCK_4X4 => TX_4X4, + BLOCK_4X8 => TX_4X8, + BLOCK_8X4 => TX_8X4, + BLOCK_8X8 => TX_8X8, + BLOCK_8X16 => TX_8X16, + BLOCK_16X8 => TX_16X8, + BLOCK_16X16 => TX_16X16, + BLOCK_16X32 => TX_16X32, + BLOCK_32X16 => TX_32X16, + BLOCK_32X32 => TX_32X32, + BLOCK_32X64 => TX_32X64, + BLOCK_64X32 => TX_64X32, + BLOCK_4X16 => TX_4X16, + BLOCK_16X4 => TX_16X4, + BLOCK_8X32 => TX_8X32, + BLOCK_32X8 => TX_32X8, + BLOCK_16X64 => TX_16X64, + BLOCK_64X16 => TX_64X16, + _ => TX_64X64, + } + } +} + +#[derive(Debug, Copy, Clone, Error, Eq, PartialEq)] +pub struct InvalidBlockSize; + +impl Display for InvalidBlockSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid block size") + } +} + +/// Transform Size +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)] +#[allow(non_camel_case_types)] +pub enum TxSize { + TX_4X4, + TX_8X8, + TX_16X16, + TX_32X32, + TX_64X64, + + TX_4X8, + TX_8X4, + TX_8X16, + TX_16X8, + TX_16X32, + TX_32X16, + TX_32X64, + TX_64X32, + + TX_4X16, + TX_16X4, + TX_8X32, + TX_32X8, + TX_16X64, + TX_64X16, +} + +impl TxSize { + pub const fn width(self) -> usize { + 1 << self.width_log2() + } + + pub const fn width_log2(self) -> usize { + use crate::data::block::TxSize::*; + match self { + TX_4X4 | TX_4X8 | TX_4X16 => 2, + TX_8X8 | TX_8X4 | TX_8X16 | TX_8X32 => 3, + TX_16X16 | TX_16X8 | TX_16X32 | TX_16X4 | TX_16X64 => 4, + TX_32X32 | TX_32X16 | TX_32X64 | TX_32X8 => 5, + TX_64X64 | TX_64X32 | TX_64X16 => 6, + } + } + + pub const fn height(self) -> usize { + 1 << self.height_log2() + } + + pub const fn height_log2(self) -> usize { + use crate::data::block::TxSize::*; + match self { + TX_4X4 | TX_8X4 | TX_16X4 => 2, + TX_8X8 | TX_4X8 | TX_16X8 | TX_32X8 => 3, + TX_16X16 | TX_8X16 | TX_32X16 | TX_4X16 | TX_64X16 => 4, + TX_32X32 | TX_16X32 | TX_64X32 | TX_8X32 => 5, + TX_64X64 | TX_32X64 | TX_16X64 => 6, + } + } +} + +/// Absolute offset in blocks, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct BlockOffset { + pub x: usize, + pub y: usize, +} + +impl BlockOffset { + /// Convert to plane offset without decimation. + pub const fn to_luma_plane_offset(self) -> PlaneOffset { + PlaneOffset { + x: (self.x as isize) << BLOCK_TO_PLANE_SHIFT, + y: (self.y as isize) << BLOCK_TO_PLANE_SHIFT, + } + } + + pub fn with_offset(self, col_offset: isize, row_offset: isize) -> BlockOffset { + let x = self.x as isize + col_offset; + let y = self.y as isize + row_offset; + debug_assert!(x >= 0); + debug_assert!(y >= 0); + + BlockOffset { + x: x as usize, + y: y as usize, + } + } +} + +#[derive(Clone)] +pub struct FrameBlocks { + blocks: Box<[Block]>, + pub cols: usize, +} + +impl Index for FrameBlocks { + type Output = [Block]; + + fn index(&self, index: usize) -> &Self::Output { + &self.blocks[index * self.cols..(index + 1) * self.cols] + } +} + +impl IndexMut for FrameBlocks { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.blocks[index * self.cols..(index + 1) * self.cols] + } +} + +// for convenience, also index by BlockOffset + +impl Index for FrameBlocks { + type Output = Block; + + fn index(&self, bo: PlaneBlockOffset) -> &Self::Output { + &self[bo.0.y][bo.0.x] + } +} + +impl IndexMut for FrameBlocks { + fn index_mut(&mut self, bo: PlaneBlockOffset) -> &mut Self::Output { + &mut self[bo.0.y][bo.0.x] + } +} + +#[derive(Copy, Clone, Default)] +pub struct Block {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/frame.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/frame.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/frame.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/frame.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,174 @@ +use std::sync::Arc; + +use v_frame::{frame::Frame, math::Fixed, pixel::Pixel, plane::Plane}; + +use crate::data::motion::{RefMEStats, ReferenceFramesSet}; + +pub const MAX_PLANES: usize = 3; + +pub const ALLOWED_REF_FRAMES: &[RefType] = &[RefType::LAST_FRAME]; +pub const INTER_REFS_PER_FRAME: usize = 7; + +#[derive(Debug, Clone)] +pub struct FrameState { + pub input: Arc>, + pub input_hres: Arc>, // half-resolution version of input luma + pub input_qres: Arc>, // quarter-resolution version of input luma + pub frame_me_stats: RefMEStats, +} + +impl FrameState { + /// Similar to [`FrameState::new_with_frame`], but takes an `me_stats` + /// and `rec` to enable reusing the same underlying allocations to create + /// a `FrameState` + /// + /// This function primarily exists for [`estimate_inter_costs`], and so + /// it does not create hres or qres versions of `frame` as downscaling is + /// somewhat expensive and are not needed for [`estimate_inter_costs`]. + pub fn new_with_frame_and_me_stats_and_rec(frame: Arc>, me_stats: RefMEStats) -> Self { + let hres = Plane::new(0, 0, 0, 0, 0, 0); + let qres = Plane::new(0, 0, 0, 0, 0, 0); + + Self { + input: frame, + input_hres: Arc::new(hres), + input_qres: Arc::new(qres), + frame_me_stats: me_stats, + // enc_stats: Default::default(), + } + } +} + +// LAST_FRAME through ALTREF_FRAME correspond to slots 0-6. +#[allow(non_camel_case_types)] +#[allow(dead_code)] +#[derive(PartialEq, Eq, PartialOrd, Copy, Clone, Debug)] +pub enum RefType { + INTRA_FRAME = 0, + LAST_FRAME = 1, + LAST2_FRAME = 2, + LAST3_FRAME = 3, + GOLDEN_FRAME = 4, + BWDREF_FRAME = 5, + ALTREF2_FRAME = 6, + ALTREF_FRAME = 7, + NONE_FRAME = 8, +} + +impl RefType { + /// convert to a ref list index, 0-6 (`INTER_REFS_PER_FRAME`) + /// + /// # Panics + /// + /// - If the ref type is a None or Intra frame + pub fn to_index(self) -> usize { + use self::RefType::*; + + match self { + NONE_FRAME => { + panic!("Tried to get slot of NONE_FRAME"); + } + INTRA_FRAME => { + panic!("Tried to get slot of INTRA_FRAME"); + } + _ => (self as usize) - 1, + } + } +} + +// Frame Invariants are invariant inside a frame +#[allow(dead_code)] +#[derive(Debug, Clone)] +pub struct FrameInvariants { + pub w_in_b: usize, + pub h_in_b: usize, + pub ref_frames: [u8; INTER_REFS_PER_FRAME], + pub rec_buffer: ReferenceFramesSet, +} + +impl FrameInvariants { + pub fn new(width: usize, height: usize) -> Self { + let w_in_b = 2 * width.align_power_of_two_and_shift(3); // MiCols, ((width+7)/8)<<3 >> MI_SIZE_LOG2 + let h_in_b = 2 * height.align_power_of_two_and_shift(3); // MiRows, ((height+7)/8)<<3 >> MI_SIZE_LOG2 + + Self { + w_in_b, + h_in_b, + ref_frames: [0; INTER_REFS_PER_FRAME], + rec_buffer: ReferenceFramesSet::new(), + } + } + + pub fn new_key_frame(width: usize, height: usize) -> Self { + Self::new(width, height) + } + + /// Returns the created `FrameInvariants`, or `None` if this should be + /// a placeholder frame. + pub(crate) fn new_inter_frame( + previous_coded_fi: &Self, + output_frameno_in_gop: u64, + ) -> Option { + let mut fi = previous_coded_fi.clone(); + let idx_in_group_output = get_idx_in_group_output(output_frameno_in_gop); + let order_hint = get_order_hint(output_frameno_in_gop, idx_in_group_output); + + // this is the slot that the current frame is going to be saved into + let slot_idx = get_slot_idx(0, order_hint); + + // level 0 has no forward references + // default to last P frame + // + // calculations done relative to the slot_idx for this frame. + // the last four frames can be found by subtracting from the current + // + // add 4 to prevent underflow + // TODO: maybe use order_hint here like in get_slot_idx? + // this is the previous P frame + fi.ref_frames = [(slot_idx + 4 - 1) as u8 % 4; INTER_REFS_PER_FRAME]; + + Some(fi) + } +} + +// All the stuff below is ripped from InterCfg but assumes +// reordering and multiref are off, so pyramid depth is always 0 +const fn get_slot_idx(level: u64, order_hint: u32) -> u32 { + // Frames with level == 0 are stored in slots 0..4, and frames with higher + // values of level in slots 4..8 + if level == 0 { + order_hint & 3 + } else { + // This only works with pyramid_depth <= 4. + 3 + level as u32 + } +} + +/// Get the index of an output frame in its re-ordering group given the output +/// frame number of the frame in the current keyframe gop. +/// When re-ordering is disabled, this always returns 0. +fn get_idx_in_group_output(output_frameno_in_gop: u64) -> u64 { + // The first frame in the GOP should be a keyframe and is not re-ordered, + // so we should not be calling this function on it. + debug_assert!(output_frameno_in_gop > 0); + + output_frameno_in_gop - 1 +} + +/// Get the order-hint of an output frame given the output frame number of the +/// frame in the current keyframe gop and the index of that output frame +/// in its re-ordering gorup. +fn get_order_hint(output_frameno_in_gop: u64, idx_in_group_output: u64) -> u32 { + // The first frame in the GOP should be a keyframe, but currently this + // function only handles inter frames. + // We could return 0 for keyframes if keyframe support is needed. + debug_assert!(output_frameno_in_gop > 0); + + // Which P-frame group in the current gop is this output frame in? + // Subtract 1 because the first frame in the gop is always a keyframe. + let group_idx = output_frameno_in_gop - 1; + // Get the offset to the corresponding input frame. + let offset = idx_in_group_output + 1; + // Construct the final order hint relative to the start of the group. + (group_idx + offset) as u32 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/hadamard.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/hadamard.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/hadamard.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/hadamard.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,82 @@ +pub unsafe fn hadamard4x4(data: &mut [i32]) { + hadamard2d::<{ 4 * 4 }, 4, 4>(&mut *(data.as_mut_ptr() as *mut [i32; 16])); +} + +// SAFETY: The length of data must be 64. +pub unsafe fn hadamard8x8(data: &mut [i32]) { + hadamard2d::<{ 8 * 8 }, 8, 8>(&mut *(data.as_mut_ptr() as *mut [i32; 64])); +} + +fn hadamard2d(data: &mut [i32; LEN]) { + // Vertical transform. + let vert_func = if H == 4 { + hadamard4_1d:: + } else { + hadamard8_1d:: + }; + vert_func(data); + + // Horizontal transform. + let horz_func = if W == 4 { + hadamard4_1d:: + } else { + hadamard8_1d:: + }; + horz_func(data); +} + +#[allow(clippy::erasing_op)] +#[allow(clippy::identity_op)] +fn hadamard4_1d( + data: &mut [i32; LEN], +) { + for i in 0..N { + let sub: &mut [i32] = &mut data[i * STRIDE0..]; + let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]); + let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]); + let (b0, b2) = butterfly(a0, a2); + let (b1, b3) = butterfly(a1, a3); + sub[0 * STRIDE1] = b0; + sub[1 * STRIDE1] = b1; + sub[2 * STRIDE1] = b2; + sub[3 * STRIDE1] = b3; + } +} + +#[allow(clippy::erasing_op)] +#[allow(clippy::identity_op)] +fn hadamard8_1d( + data: &mut [i32; LEN], +) { + for i in 0..N { + let sub: &mut [i32] = &mut data[i * STRIDE0..]; + + let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]); + let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]); + let (a4, a5) = butterfly(sub[4 * STRIDE1], sub[5 * STRIDE1]); + let (a6, a7) = butterfly(sub[6 * STRIDE1], sub[7 * STRIDE1]); + + let (b0, b2) = butterfly(a0, a2); + let (b1, b3) = butterfly(a1, a3); + let (b4, b6) = butterfly(a4, a6); + let (b5, b7) = butterfly(a5, a7); + + let (c0, c4) = butterfly(b0, b4); + let (c1, c5) = butterfly(b1, b5); + let (c2, c6) = butterfly(b2, b6); + let (c3, c7) = butterfly(b3, b7); + + sub[0 * STRIDE1] = c0; + sub[1 * STRIDE1] = c1; + sub[2 * STRIDE1] = c2; + sub[3 * STRIDE1] = c3; + sub[4 * STRIDE1] = c4; + sub[5 * STRIDE1] = c5; + sub[6 * STRIDE1] = c6; + sub[7 * STRIDE1] = c7; + } +} + +const fn butterfly(a: i32, b: i32) -> (i32, i32) { + ((a + b), (a - b)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_neon.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,187 @@ +use v_frame::{ + pixel::{Pixel, PixelType}, + plane::PlaneSlice, +}; + +use crate::{ + cpu::CpuFeatureLevel, + data::{ + mc::{FilterMode, FilterMode::*}, + plane::PlaneRegionMut, + }, +}; + +#[allow(clippy::too_many_arguments)] +pub fn put_8tap_internal( + dst: &mut PlaneRegionMut<'_, T>, + src: PlaneSlice<'_, T>, + width: usize, + height: usize, + col_frac: i32, + row_frac: i32, + bit_depth: usize, + cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + super::rust::put_8tap_internal(dst, src, width, height, col_frac, row_frac, bit_depth, cpu); + }; + + unsafe { + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + + match T::type_enum() { + PixelType::U8 => match PUT_FNS[cpu.as_index()] + [get_2d_mode_idx(FilterMode::REGULAR, FilterMode::REGULAR)] + { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(dst), + }, + PixelType::U16 if bit_depth > 8 => { + match PUT_HBD_FNS[cpu.as_index()] + [get_2d_mode_idx(FilterMode::REGULAR, FilterMode::REGULAR)] + { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + } + } + _ => call_rust(dst), + } + } +} + +// gets an index that can be mapped to a function for a pair of filter modes +const fn get_2d_mode_idx(mode_x: FilterMode, mode_y: FilterMode) -> usize { + (mode_x as usize + 4 * (mode_y as usize)) & 15 +} + +type PutFn = unsafe extern "C" fn( + dst: *mut u8, + dst_stride: isize, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PutHBDFn = unsafe extern "C" fn( + dst: *mut u16, + dst_stride: isize, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +macro_rules! decl_mc_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern "C" { + $( + fn $func_name( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, + ); + )* + } + + static PUT_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } + } + +decl_mc_fns!( + (REGULAR, REGULAR, avsc_put_8tap_regular_8bpc_neon), + (REGULAR, SMOOTH, avsc_put_8tap_regular_smooth_8bpc_neon), + (REGULAR, SHARP, avsc_put_8tap_regular_sharp_8bpc_neon), + (SMOOTH, REGULAR, avsc_put_8tap_smooth_regular_8bpc_neon), + (SMOOTH, SMOOTH, avsc_put_8tap_smooth_8bpc_neon), + (SMOOTH, SHARP, avsc_put_8tap_smooth_sharp_8bpc_neon), + (SHARP, REGULAR, avsc_put_8tap_sharp_regular_8bpc_neon), + (SHARP, SMOOTH, avsc_put_8tap_sharp_smooth_8bpc_neon), + (SHARP, SHARP, avsc_put_8tap_sharp_8bpc_neon), + (BILINEAR, BILINEAR, avsc_put_bilin_8bpc_neon) +); + +cpu_function_lookup_table!( + PUT_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); + +macro_rules! decl_mc_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern "C" { + $( + fn $func_name( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PUT_HBD_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } + } + +decl_mc_hbd_fns!( + (REGULAR, REGULAR, avsc_put_8tap_regular_16bpc_neon), + (REGULAR, SMOOTH, avsc_put_8tap_regular_smooth_16bpc_neon), + (REGULAR, SHARP, avsc_put_8tap_regular_sharp_16bpc_neon), + (SMOOTH, REGULAR, avsc_put_8tap_smooth_regular_16bpc_neon), + (SMOOTH, SMOOTH, avsc_put_8tap_smooth_16bpc_neon), + (SMOOTH, SHARP, avsc_put_8tap_smooth_sharp_16bpc_neon), + (SHARP, REGULAR, avsc_put_8tap_sharp_regular_16bpc_neon), + (SHARP, SMOOTH, avsc_put_8tap_sharp_smooth_16bpc_neon), + (SHARP, SHARP, avsc_put_8tap_sharp_16bpc_neon), + (BILINEAR, BILINEAR, avsc_put_bilin_16bpc_neon) +); + +cpu_function_lookup_table!( + PUT_HBD_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_x86.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_x86.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_x86.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc/simd_x86.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,225 @@ +use v_frame::{ + pixel::{Pixel, PixelType}, + plane::PlaneSlice, +}; + +use crate::{ + cpu::CpuFeatureLevel, + data::{ + mc::{FilterMode, FilterMode::*}, + plane::PlaneRegionMut, + }, +}; + +#[allow(clippy::too_many_arguments)] +pub fn put_8tap_internal( + dst: &mut PlaneRegionMut<'_, T>, + src: PlaneSlice<'_, T>, + width: usize, + height: usize, + col_frac: i32, + row_frac: i32, + bit_depth: usize, + cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + super::rust::put_8tap_internal(dst, src, width, height, col_frac, row_frac, bit_depth, cpu); + }; + + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + unsafe { + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + + match T::type_enum() { + PixelType::U8 => match PUT_FNS[cpu.as_index()][get_2d_mode_idx(REGULAR, REGULAR)] { + Some(func) => func( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(dst), + }, + PixelType::U16 => { + match PUT_HBD_FNS[cpu.as_index()][get_2d_mode_idx(REGULAR, REGULAR)] { + Some(func) => func( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + } + } + } + } +} + +type PutFn = unsafe extern "C" fn( + dst: *mut u8, + dst_stride: isize, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PutHBDFn = unsafe extern "C" fn( + dst: *mut u16, + dst_stride: isize, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +// gets an index that can be mapped to a function for a pair of filter modes +const fn get_2d_mode_idx(mode_x: FilterMode, mode_y: FilterMode) -> usize { + (mode_x as usize + 4 * (mode_y as usize)) & 15 +} + +macro_rules! decl_mc_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + pastey::item! { + extern "C" { + $( + fn [<$func_name _ssse3>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx2>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx512icl>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + )* + } + + static PUT_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PUT_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + + static PUT_FNS_AVX512ICL: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx512icl>]); + )* + out + }; + } + } + } + +decl_mc_fns!( + (REGULAR, REGULAR, avsc_put_8tap_regular_8bpc), + (REGULAR, SMOOTH, avsc_put_8tap_regular_smooth_8bpc), + (REGULAR, SHARP, avsc_put_8tap_regular_sharp_8bpc), + (SMOOTH, REGULAR, avsc_put_8tap_smooth_regular_8bpc), + (SMOOTH, SMOOTH, avsc_put_8tap_smooth_8bpc), + (SMOOTH, SHARP, avsc_put_8tap_smooth_sharp_8bpc), + (SHARP, REGULAR, avsc_put_8tap_sharp_regular_8bpc), + (SHARP, SMOOTH, avsc_put_8tap_sharp_smooth_8bpc), + (SHARP, SHARP, avsc_put_8tap_sharp_8bpc), + (BILINEAR, BILINEAR, avsc_put_bilin_8bpc) +); + +cpu_function_lookup_table!( + PUT_FNS: [[Option; 16]], + default: [None; 16], + [SSSE3, AVX2, AVX512ICL] +); + +macro_rules! decl_mc_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + pastey::item! { + extern "C" { + $( + fn [<$func_name _ssse3>]( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + + fn [<$func_name _avx2>]( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PUT_HBD_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PUT_HBD_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + } + } + } + +decl_mc_hbd_fns!( + (REGULAR, REGULAR, avsc_put_8tap_regular_16bpc), + (REGULAR, SMOOTH, avsc_put_8tap_regular_smooth_16bpc), + (REGULAR, SHARP, avsc_put_8tap_regular_sharp_16bpc), + (SMOOTH, REGULAR, avsc_put_8tap_smooth_regular_16bpc), + (SMOOTH, SMOOTH, avsc_put_8tap_smooth_16bpc), + (SMOOTH, SHARP, avsc_put_8tap_smooth_sharp_16bpc), + (SHARP, REGULAR, avsc_put_8tap_sharp_regular_16bpc), + (SHARP, SMOOTH, avsc_put_8tap_sharp_smooth_16bpc), + (SHARP, SHARP, avsc_put_8tap_sharp_16bpc), + (BILINEAR, BILINEAR, avsc_put_bilin_16bpc) +); + +cpu_function_lookup_table!( + PUT_HBD_FNS: [[Option; 16]], + default: [None; 16], + [SSSE3, AVX2] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,307 @@ +#[cfg(asm_neon)] +mod simd_neon; +#[cfg(asm_x86_64)] +mod simd_x86; + +use v_frame::{pixel::Pixel, plane::PlaneSlice}; + +#[cfg(not(any(asm_x86_64, asm_neon)))] +use self::rust::*; +#[cfg(asm_neon)] +use self::simd_neon::*; +#[cfg(asm_x86_64)] +use self::simd_x86::*; +use crate::{cpu::CpuFeatureLevel, data::plane::PlaneRegionMut}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +#[allow(clippy::upper_case_acronyms)] +#[allow(dead_code)] +pub enum FilterMode { + REGULAR = 0, + SMOOTH = 1, + SHARP = 2, + BILINEAR = 3, + SWITCHABLE = 4, +} + +pub const SUBPEL_FILTER_SIZE: usize = 8; + +const SUBPEL_FILTERS: [[[i32; SUBPEL_FILTER_SIZE]; 16]; 6] = [ + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 2, -6, 126, 8, -2, 0, 0], + [0, 2, -10, 122, 18, -4, 0, 0], + [0, 2, -12, 116, 28, -8, 2, 0], + [0, 2, -14, 110, 38, -10, 2, 0], + [0, 2, -14, 102, 48, -12, 2, 0], + [0, 2, -16, 94, 58, -12, 2, 0], + [0, 2, -14, 84, 66, -12, 2, 0], + [0, 2, -14, 76, 76, -14, 2, 0], + [0, 2, -12, 66, 84, -14, 2, 0], + [0, 2, -12, 58, 94, -16, 2, 0], + [0, 2, -12, 48, 102, -14, 2, 0], + [0, 2, -10, 38, 110, -14, 2, 0], + [0, 2, -8, 28, 116, -12, 2, 0], + [0, 0, -4, 18, 122, -10, 2, 0], + [0, 0, -2, 8, 126, -6, 2, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 2, 28, 62, 34, 2, 0, 0], + [0, 0, 26, 62, 36, 4, 0, 0], + [0, 0, 22, 62, 40, 4, 0, 0], + [0, 0, 20, 60, 42, 6, 0, 0], + [0, 0, 18, 58, 44, 8, 0, 0], + [0, 0, 16, 56, 46, 10, 0, 0], + [0, -2, 16, 54, 48, 12, 0, 0], + [0, -2, 14, 52, 52, 14, -2, 0], + [0, 0, 12, 48, 54, 16, -2, 0], + [0, 0, 10, 46, 56, 16, 0, 0], + [0, 0, 8, 44, 58, 18, 0, 0], + [0, 0, 6, 42, 60, 20, 0, 0], + [0, 0, 4, 40, 62, 22, 0, 0], + [0, 0, 4, 36, 62, 26, 0, 0], + [0, 0, 2, 34, 62, 28, 2, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [-2, 2, -6, 126, 8, -2, 2, 0], + [-2, 6, -12, 124, 16, -6, 4, -2], + [-2, 8, -18, 120, 26, -10, 6, -2], + [-4, 10, -22, 116, 38, -14, 6, -2], + [-4, 10, -22, 108, 48, -18, 8, -2], + [-4, 10, -24, 100, 60, -20, 8, -2], + [-4, 10, -24, 90, 70, -22, 10, -2], + [-4, 12, -24, 80, 80, -24, 12, -4], + [-2, 10, -22, 70, 90, -24, 10, -4], + [-2, 8, -20, 60, 100, -24, 10, -4], + [-2, 8, -18, 48, 108, -22, 10, -4], + [-2, 6, -14, 38, 116, -22, 10, -4], + [-2, 6, -10, 26, 120, -18, 8, -2], + [-2, 4, -6, 16, 124, -12, 6, -2], + [0, 2, -2, 8, 126, -6, 2, -2], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, 0, 120, 8, 0, 0, 0], + [0, 0, 0, 112, 16, 0, 0, 0], + [0, 0, 0, 104, 24, 0, 0, 0], + [0, 0, 0, 96, 32, 0, 0, 0], + [0, 0, 0, 88, 40, 0, 0, 0], + [0, 0, 0, 80, 48, 0, 0, 0], + [0, 0, 0, 72, 56, 0, 0, 0], + [0, 0, 0, 64, 64, 0, 0, 0], + [0, 0, 0, 56, 72, 0, 0, 0], + [0, 0, 0, 48, 80, 0, 0, 0], + [0, 0, 0, 40, 88, 0, 0, 0], + [0, 0, 0, 32, 96, 0, 0, 0], + [0, 0, 0, 24, 104, 0, 0, 0], + [0, 0, 0, 16, 112, 0, 0, 0], + [0, 0, 0, 8, 120, 0, 0, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, -4, 126, 8, -2, 0, 0], + [0, 0, -8, 122, 18, -4, 0, 0], + [0, 0, -10, 116, 28, -6, 0, 0], + [0, 0, -12, 110, 38, -8, 0, 0], + [0, 0, -12, 102, 48, -10, 0, 0], + [0, 0, -14, 94, 58, -10, 0, 0], + [0, 0, -12, 84, 66, -10, 0, 0], + [0, 0, -12, 76, 76, -12, 0, 0], + [0, 0, -10, 66, 84, -12, 0, 0], + [0, 0, -10, 58, 94, -14, 0, 0], + [0, 0, -10, 48, 102, -12, 0, 0], + [0, 0, -8, 38, 110, -12, 0, 0], + [0, 0, -6, 28, 116, -10, 0, 0], + [0, 0, -4, 18, 122, -8, 0, 0], + [0, 0, -2, 8, 126, -4, 0, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, 30, 62, 34, 2, 0, 0], + [0, 0, 26, 62, 36, 4, 0, 0], + [0, 0, 22, 62, 40, 4, 0, 0], + [0, 0, 20, 60, 42, 6, 0, 0], + [0, 0, 18, 58, 44, 8, 0, 0], + [0, 0, 16, 56, 46, 10, 0, 0], + [0, 0, 14, 54, 48, 12, 0, 0], + [0, 0, 12, 52, 52, 12, 0, 0], + [0, 0, 12, 48, 54, 14, 0, 0], + [0, 0, 10, 46, 56, 16, 0, 0], + [0, 0, 8, 44, 58, 18, 0, 0], + [0, 0, 6, 42, 60, 20, 0, 0], + [0, 0, 4, 40, 62, 22, 0, 0], + [0, 0, 4, 36, 62, 26, 0, 0], + [0, 0, 2, 34, 62, 30, 0, 0], + ], +]; + +mod rust { + use num_traits::AsPrimitive; + use v_frame::{math::round_shift, pixel::Pixel, plane::PlaneSlice}; + + use crate::{ + cpu::CpuFeatureLevel, + data::{ + mc::{FilterMode, SUBPEL_FILTERS, SUBPEL_FILTER_SIZE}, + plane::PlaneRegionMut, + }, + }; + + #[cfg_attr( + all(asm_x86_64, any(target_feature = "ssse3", target_feature = "avx2")), + cold + )] + #[cfg_attr(asm_neon, cold)] + #[allow(clippy::too_many_arguments)] + pub fn put_8tap_internal( + dst: &mut PlaneRegionMut<'_, T>, + src: PlaneSlice<'_, T>, + width: usize, + height: usize, + col_frac: i32, + row_frac: i32, + bit_depth: usize, + _cpu: CpuFeatureLevel, + ) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + let ref_stride = src.plane.cfg.stride; + let y_filter = get_filter(row_frac, height); + let x_filter = get_filter(col_frac, width); + let max_sample_val = (1 << bit_depth) - 1; + let intermediate_bits = 4 - if bit_depth == 12 { 2 } else { 0 }; + match (col_frac, row_frac) { + (0, 0) => { + for r in 0..height { + let src_slice = &src[r]; + let dst_slice = &mut dst[r]; + dst_slice[..width].copy_from_slice(&src_slice[..width]); + } + } + (0, _) => { + let offset_slice = src.go_up(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + let dst_slice = &mut dst[r]; + for c in 0..width { + dst_slice[c] = T::cast_from( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter(src_slice[c..].as_ptr(), ref_stride, y_filter) + }, + 7, + ) + .clamp(0, max_sample_val), + ); + } + } + } + (_, 0) => { + let offset_slice = src.go_left(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + let dst_slice = &mut dst[r]; + for c in 0..width { + dst_slice[c] = T::cast_from( + round_shift( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ), + intermediate_bits, + ) + .clamp(0, max_sample_val), + ); + } + } + } + (_, _) => { + let mut intermediate: [i16; 8 * (128 + 7)] = [0; 8 * (128 + 7)]; + + let offset_slice = src.go_left(3).go_up(3); + for cg in (0..width).step_by(8) { + for r in 0..height + 7 { + let src_slice = &offset_slice[r]; + for c in cg..(cg + 8).min(width) { + intermediate[8 * r + (c - cg)] = round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ) as i16; + } + } + + for r in 0..height { + let dst_slice = &mut dst[r]; + for c in cg..(cg + 8).min(width) { + dst_slice[c] = T::cast_from( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter( + intermediate[8 * r + c - cg..].as_ptr(), + 8, + y_filter, + ) + }, + 7 + intermediate_bits, + ) + .clamp(0, max_sample_val), + ); + } + } + } + } + } + } + + fn get_filter(frac: i32, length: usize) -> [i32; SUBPEL_FILTER_SIZE] { + const MODE: FilterMode = FilterMode::REGULAR; + + let filter_idx = if MODE == FilterMode::BILINEAR || length > 4 { + MODE as usize + } else { + (MODE as usize).min(1) + 4 + }; + SUBPEL_FILTERS[filter_idx][frac as usize] + } + + unsafe fn run_filter>( + src: *const T, + stride: usize, + filter: [i32; 8], + ) -> i32 { + filter + .iter() + .enumerate() + .map(|(i, f)| { + let p = src.add(i * stride); + f * (*p).as_() + }) + .sum::() + } +} + +#[allow(clippy::too_many_arguments)] +pub fn put_8tap( + dst: &mut PlaneRegionMut<'_, T>, + src: PlaneSlice<'_, T>, + width: usize, + height: usize, + col_frac: i32, + row_frac: i32, + bit_depth: usize, + cpu: CpuFeatureLevel, +) { + put_8tap_internal(dst, src, width, height, col_frac, row_frac, bit_depth, cpu); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +use std::mem::MaybeUninit; + +pub(crate) mod block; +pub(crate) mod frame; +pub(crate) mod hadamard; +pub(crate) mod mc; +pub(crate) mod motion; +pub(crate) mod plane; +pub(crate) mod prediction; +pub(crate) mod sad; +pub(crate) mod satd; +pub(crate) mod superblock; +pub(crate) mod tile; + +/// Assume all the elements are initialized. +pub unsafe fn slice_assume_init_mut(slice: &'_ mut [MaybeUninit]) -> &'_ mut [T] { + &mut *(slice as *mut [MaybeUninit] as *mut [T]) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/motion.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/motion.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/motion.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/motion.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,320 @@ +use std::{ + marker::PhantomData, + ops, + ops::{Index, IndexMut}, + slice, + sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; + +use arrayvec::ArrayVec; +use v_frame::{frame::Frame, pixel::Pixel, plane::Plane}; + +const MV_IN_USE_BITS: usize = 14; +pub const MV_UPP: i32 = 1 << MV_IN_USE_BITS; +pub const MV_LOW: i32 = -(1 << MV_IN_USE_BITS); + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct MotionVector { + pub row: i16, + pub col: i16, +} + +impl MotionVector { + pub const fn quantize_to_fullpel(self) -> Self { + Self { + row: (self.row / 8) * 8, + col: (self.col / 8) * 8, + } + } +} + +impl ops::Mul for MotionVector { + type Output = MotionVector; + + fn mul(self, rhs: i16) -> MotionVector { + MotionVector { + row: self.row * rhs, + col: self.col * rhs, + } + } +} + +impl ops::Mul for MotionVector { + type Output = MotionVector; + + fn mul(self, rhs: u16) -> MotionVector { + MotionVector { + row: self.row * rhs as i16, + col: self.col * rhs as i16, + } + } +} + +impl ops::Shr for MotionVector { + type Output = MotionVector; + + fn shr(self, rhs: u8) -> MotionVector { + MotionVector { + row: self.row >> rhs, + col: self.col >> rhs, + } + } +} + +impl ops::Shl for MotionVector { + type Output = MotionVector; + + fn shl(self, rhs: u8) -> MotionVector { + MotionVector { + row: self.row << rhs, + col: self.col << rhs, + } + } +} + +impl ops::Add for MotionVector { + type Output = MotionVector; + + fn add(self, rhs: MotionVector) -> MotionVector { + MotionVector { + row: self.row + rhs.row, + col: self.col + rhs.col, + } + } +} + +#[derive(Debug, Copy, Clone, Default)] +pub struct MEStats { + pub mv: MotionVector, + /// SAD value on the scale of a 128x128 block + pub normalized_sad: u32, +} + +#[derive(Debug, Clone)] +pub struct FrameMEStats { + stats: Box<[MEStats]>, + pub cols: usize, + pub rows: usize, +} + +pub const REF_FRAMES_LOG2: usize = 3; +pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2; +pub type RefMEStats = Arc>; +pub type ReadGuardMEStats<'a> = RwLockReadGuard<'a, [FrameMEStats; REF_FRAMES]>; +pub type WriteGuardMEStats<'a> = RwLockWriteGuard<'a, [FrameMEStats; REF_FRAMES]>; + +impl FrameMEStats { + pub fn new(cols: usize, rows: usize) -> Self { + Self { + // dynamic allocation: once per frame + stats: vec![MEStats::default(); cols * rows].into_boxed_slice(), + cols, + rows, + } + } + + pub fn new_arc_array(cols: usize, rows: usize) -> RefMEStats { + Arc::new(RwLock::new([ + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + ])) + } +} + +impl Index for FrameMEStats { + type Output = [MEStats]; + + fn index(&self, index: usize) -> &Self::Output { + &self.stats[index * self.cols..(index + 1) * self.cols] + } +} + +impl IndexMut for FrameMEStats { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.stats[index * self.cols..(index + 1) * self.cols] + } +} + +/// Tiled view of `FrameMEStats` +#[derive(Debug)] +pub struct TileMEStats<'a> { + data: *const MEStats, + // expressed in mi blocks + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameMEStats` + stride: usize, + phantom: PhantomData<&'a MotionVector>, +} + +/// Mutable tiled view of `FrameMEStats` +#[derive(Debug)] +pub struct TileMEStatsMut<'a> { + data: *mut MEStats, + // expressed in mi blocks + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameMEStats` + stride: usize, + phantom: PhantomData<&'a mut MotionVector>, +} + +// common impl for TileMotionVectors and TileMotionVectorsMut +macro_rules! tile_me_stats_common { + // $name: TileMEStats or TileMEStatsMut + // $opt_mut: nothing or mut + ($name:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + /// # Panics + /// + /// - If the requested dimensions are larger than the frame MV size + #[allow(dead_code)] + pub fn new( + frame_mvs: &'a $($opt_mut)? FrameMEStats, + x: usize, + y: usize, + cols: usize, + rows: usize, + ) -> Self { + assert!(x + cols <= frame_mvs.cols); + assert!(y + rows <= frame_mvs.rows); + Self { + data: & $($opt_mut)? frame_mvs[y][x], + x, + y, + cols, + rows, + stride: frame_mvs.cols, + phantom: PhantomData, + } + } + + #[allow(dead_code)] + pub const fn x(&self) -> usize { + self.x + } + + #[allow(dead_code)] + pub const fn y(&self) -> usize { + self.y + } + + #[allow(dead_code)] + pub const fn cols(&self) -> usize { + self.cols + } + + #[allow(dead_code)] + pub const fn rows(&self) -> usize { + self.rows + } + } + + unsafe impl Send for $name<'_> {} + unsafe impl Sync for $name<'_> {} + + impl Index for $name<'_> { + type Output = [MEStats]; + + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts(ptr, self.cols) + } + } + } + } +} + +tile_me_stats_common!(TileMEStats); +tile_me_stats_common!(TileMEStatsMut, mut); + +impl TileMEStatsMut<'_> { + pub const fn as_const(&self) -> TileMEStats<'_> { + TileMEStats { + data: self.data, + x: self.x, + y: self.y, + cols: self.cols, + rows: self.rows, + stride: self.stride, + phantom: PhantomData, + } + } +} + +impl IndexMut for TileMEStatsMut<'_> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts_mut(ptr, self.cols) + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[allow(clippy::upper_case_acronyms)] +pub enum MVSamplingMode { + INIT, + CORNER { right: bool, bottom: bool }, +} + +#[derive(Debug, Clone)] +pub struct ReferenceFrame { + pub frame: Arc>, + pub input_hres: Arc>, + pub input_qres: Arc>, + pub frame_me_stats: RefMEStats, +} + +#[derive(Debug, Clone, Default)] +pub struct ReferenceFramesSet { + pub frames: [Option>>; REF_FRAMES], +} + +impl ReferenceFramesSet { + pub fn new() -> Self { + Self { + frames: Default::default(), + // deblock: Default::default() + } + } +} + +pub struct MotionEstimationSubsets { + pub min_sad: u32, + pub median: Option, + pub subset_b: ArrayVec, + pub subset_c: ArrayVec, +} + +impl MotionEstimationSubsets { + pub fn all_mvs(&self) -> ArrayVec { + let mut all = ArrayVec::new(); + if let Some(median) = self.median { + all.push(median); + } + + all.extend(self.subset_b.iter().copied()); + all.extend(self.subset_c.iter().copied()); + + all + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/plane.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/plane.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/plane.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/plane.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,547 @@ +use std::{ + iter::FusedIterator, + marker::PhantomData, + ops::{Index, IndexMut}, + slice, +}; + +use v_frame::{ + pixel::Pixel, + plane::{Plane, PlaneConfig, PlaneOffset}, +}; + +use super::block::{BlockOffset, BLOCK_TO_PLANE_SHIFT}; + +/// Bounded region of a plane +/// +/// This allows giving access to a rectangular area of a plane without +/// giving access to the whole plane. +#[derive(Debug)] +pub struct PlaneRegion<'a, T: Pixel> { + data: *const T, // points to (plane_cfg.x, plane_cfg.y) + pub plane_cfg: &'a PlaneConfig, + // private to guarantee borrowing rules + rect: Rect, + phantom: PhantomData<&'a T>, +} + +/// Mutable bounded region of a plane +/// +/// This allows to give mutable access to a rectangular area of the plane +/// without giving access to the whole plane. +#[derive(Debug)] +pub struct PlaneRegionMut<'a, T: Pixel> { + data: *mut T, // points to (plane_cfg.x, plane_cfg.y) + pub plane_cfg: &'a PlaneConfig, + rect: Rect, + phantom: PhantomData<&'a mut T>, +} + +// common impl for PlaneRegion and PlaneRegionMut +macro_rules! plane_region_common { + // $name: PlaneRegion or PlaneRegionMut + // $as_ptr: as_ptr or as_mut_ptr + // $opt_mut: nothing or mut + ($name:ident, $as_ptr:ident $(,$opt_mut:tt)?) => { + impl<'a, T: Pixel> $name<'a, T> { + #[cold] + pub fn empty(plane_cfg : &'a PlaneConfig) -> Self { + return Self { + // SAFETY: This is actually pretty unsafe. + // This means we need to ensure that no other method on this struct + // can access data if the dimensions are 0. + data: std::ptr::null_mut::(), + plane_cfg, + rect: Rect::default(), + phantom: PhantomData, + } + } + + /// # Panics + /// + /// - If the configured dimensions are invalid + pub fn from_slice(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { + if cfg.width == 0 || cfg.height == 0 { + return Self::empty(&cfg); + } + assert!(rect.x >= -(cfg.xorigin as isize)); + assert!(rect.y >= -(cfg.yorigin as isize)); + assert!(cfg.xorigin as isize + rect.x + rect.width as isize <= cfg.stride as isize); + assert!(cfg.yorigin as isize + rect.y + rect.height as isize <= cfg.alloc_height as isize); + + // SAFETY: The above asserts ensure we do not go OOB. + unsafe { Self::from_slice_unsafe(data, cfg, rect)} + } + + unsafe fn from_slice_unsafe(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { + let origin = (cfg.yorigin as isize + rect.y) * cfg.stride as isize + cfg.xorigin as isize + rect.x; + Self { + data: data.$as_ptr().offset(origin), + plane_cfg: cfg, + rect, + phantom: PhantomData, + } + } + + pub fn new(plane: &'a $($opt_mut)? Plane, rect: Rect) -> Self { + Self::from_slice(& $($opt_mut)? plane.data, &plane.cfg, rect) + } + + #[allow(dead_code)] + pub fn new_from_plane(plane: &'a $($opt_mut)? Plane) -> Self { + let rect = Rect { + x: 0, + y: 0, + width: plane.cfg.stride - plane.cfg.xorigin, + height: plane.cfg.alloc_height - plane.cfg.yorigin, + }; + + // SAFETY: Area::StartingAt{}.to_rect is guaranteed to be the entire plane + unsafe { Self::from_slice_unsafe(& $($opt_mut)? plane.data, &plane.cfg, rect) } + } + + #[allow(dead_code)] + pub fn data_ptr(&self) -> *const T { + self.data + } + + pub fn rect(&self) -> &Rect { + &self.rect + } + + #[allow(dead_code)] + pub fn rows_iter(&self) -> PlaneRegionRowsIter<'_, T> { + PlaneRegionRowsIter { + data: self.data, + stride: self.plane_cfg.stride, + width: self.rect.width, + remaining: self.rect.height, + phantom: PhantomData, + } + } + + #[allow(dead_code)] + pub fn vert_windows(&self, h: usize) -> VertWindows<'_, T> { + VertWindows { + data: self.data, + plane_cfg: self.plane_cfg, + remaining: (self.rect.height as isize - h as isize + 1).max(0) as usize, + output_rect: Rect { + x: self.rect.x, + y: self.rect.y, + width: self.rect.width, + height: h + } + } + } + + #[allow(dead_code)] + pub fn horz_windows(&self, w: usize) -> HorzWindows<'_, T> { + HorzWindows { + data: self.data, + plane_cfg: self.plane_cfg, + remaining: (self.rect.width as isize - w as isize + 1).max(0) as usize, + output_rect: Rect { + x: self.rect.x, + y: self.rect.y, + width: w, + height: self.rect.height + } + } + } + + /// Return a view to a subregion of the plane + /// + /// The subregion must be included in (i.e. must not exceed) this region. + /// + /// It is described by an `Area`, relative to this region. + /// + /// # Panics + /// + /// - If the requested dimensions are larger than the plane region size + /// + /// # Example + /// + /// ``` ignore + /// # use rav1e::tiling::*; + /// # fn f(region: &PlaneRegion<'_, u16>) { + /// // a subregion from (10, 8) to the end of the region + /// let subregion = region.subregion(Area::StartingAt { x: 10, y: 8 }); + /// # } + /// ``` + /// + /// ``` ignore + /// # use rav1e::context::*; + /// # use rav1e::tiling::*; + /// # fn f(region: &PlaneRegion<'_, u16>) { + /// // a subregion from the top-left of block (2, 3) having size (64, 64) + /// let bo = BlockOffset { x: 2, y: 3 }; + /// let subregion = region.subregion(Area::BlockRect { bo, width: 64, height: 64 }); + /// # } + /// ``` + #[allow(dead_code)] + pub fn subregion(&self, area: Area) -> PlaneRegion<'_, T> { + if self.data.is_null() { + return PlaneRegion::empty(&self.plane_cfg); + } + let rect = area.to_rect( + self.plane_cfg.xdec, + self.plane_cfg.ydec, + self.rect.width, + self.rect.height, + ); + assert!(rect.x >= 0 && rect.x as usize <= self.rect.width); + assert!(rect.y >= 0 && rect.y as usize <= self.rect.height); + // SAFETY: The above asserts ensure we do not go outside the original rectangle. + let data = unsafe { + self.data.add(rect.y as usize * self.plane_cfg.stride + rect.x as usize) + }; + let absolute_rect = Rect { + x: self.rect.x + rect.x, + y: self.rect.y + rect.y, + width: rect.width, + height: rect.height, + }; + PlaneRegion { + data, + plane_cfg: &self.plane_cfg, + rect: absolute_rect, + phantom: PhantomData, + } + } + } + + unsafe impl Send for $name<'_, T> {} + unsafe impl Sync for $name<'_, T> {} + + impl Index for $name<'_, T> { + type Output = [T]; + + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rect.height); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.plane_cfg.stride); + slice::from_raw_parts(ptr, self.rect.width) + } + } + } + } +} + +plane_region_common!(PlaneRegion, as_ptr); +plane_region_common!(PlaneRegionMut, as_mut_ptr, mut); + +impl PlaneRegionMut<'_, T> { + pub fn data_ptr_mut(&mut self) -> *mut T { + self.data + } + + pub fn rows_iter_mut(&mut self) -> PlaneRegionRowsIterMut<'_, T> { + PlaneRegionRowsIterMut { + data: self.data, + stride: self.plane_cfg.stride, + width: self.rect.width, + remaining: self.rect.height, + phantom: PhantomData, + } + } + + pub fn as_const(&self) -> PlaneRegion<'_, T> { + PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.rect, + phantom: PhantomData, + } + } +} + +impl IndexMut for PlaneRegionMut<'_, T> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rect.height); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.plane_cfg.stride); + slice::from_raw_parts_mut(ptr, self.rect.width) + } + } +} + +/// Iterator over plane region rows +pub struct PlaneRegionRowsIter<'a, T: Pixel> { + data: *const T, + stride: usize, + width: usize, + remaining: usize, + phantom: PhantomData<&'a T>, +} + +impl<'a, T: Pixel> Iterator for PlaneRegionRowsIter<'a, T> { + type Item = &'a [T]; + + fn next(&mut self) -> Option { + if self.remaining > 0 { + // SAFETY: We verified that we have enough data left to not go OOB, + // assuming that `self.stride` and `self.width` are set correctly. + let row = unsafe { + let ptr = self.data; + self.data = self.data.add(self.stride); + slice::from_raw_parts(ptr, self.width) + }; + self.remaining -= 1; + Some(row) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } +} + +/// Mutable iterator over plane region rows +pub struct PlaneRegionRowsIterMut<'a, T: Pixel> { + data: *mut T, + stride: usize, + width: usize, + remaining: usize, + phantom: PhantomData<&'a mut T>, +} + +impl<'a, T: Pixel> Iterator for PlaneRegionRowsIterMut<'a, T> { + type Item = &'a mut [T]; + + fn next(&mut self) -> Option { + if self.remaining > 0 { + // SAFETY: We verified that we have enough data left to not go OOB, + // assuming that `self.stride` and `self.width` are set correctly. + let row = unsafe { + let ptr = self.data; + self.data = self.data.add(self.stride); + slice::from_raw_parts_mut(ptr, self.width) + }; + self.remaining -= 1; + Some(row) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } +} + +impl ExactSizeIterator for PlaneRegionRowsIter<'_, T> { +} +impl FusedIterator for PlaneRegionRowsIter<'_, T> { +} +impl ExactSizeIterator for PlaneRegionRowsIterMut<'_, T> { +} +impl FusedIterator for PlaneRegionRowsIterMut<'_, T> { +} + +pub struct VertWindows<'a, T: Pixel> { + data: *const T, + plane_cfg: &'a PlaneConfig, + remaining: usize, + output_rect: Rect, +} + +pub struct HorzWindows<'a, T: Pixel> { + data: *const T, + plane_cfg: &'a PlaneConfig, + remaining: usize, + output_rect: Rect, +} + +impl<'a, T: Pixel> Iterator for VertWindows<'a, T> { + type Item = PlaneRegion<'a, T>; + + fn next(&mut self) -> Option { + self.nth(0) + } + + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } + + fn nth(&mut self, n: usize) -> Option { + if self.remaining > n { + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(self.plane_cfg.stride * n) }; + self.output_rect.y += n as isize; + let output = PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.output_rect, + phantom: PhantomData, + }; + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(self.plane_cfg.stride) }; + self.output_rect.y += 1; + self.remaining -= n + 1; + Some(output) + } else { + None + } + } +} + +impl<'a, T: Pixel> Iterator for HorzWindows<'a, T> { + type Item = PlaneRegion<'a, T>; + + fn next(&mut self) -> Option { + self.nth(0) + } + + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } + + fn nth(&mut self, n: usize) -> Option { + if self.remaining > n { + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(n) }; + self.output_rect.x += n as isize; + let output = PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.output_rect, + phantom: PhantomData, + }; + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(1) }; + self.output_rect.x += 1; + self.remaining -= n + 1; + Some(output) + } else { + None + } + } +} + +impl ExactSizeIterator for VertWindows<'_, T> { +} +impl FusedIterator for VertWindows<'_, T> { +} +impl ExactSizeIterator for HorzWindows<'_, T> { +} +impl FusedIterator for HorzWindows<'_, T> { +} + +/// Rectangle of a plane region, in pixels +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub struct Rect { + // coordinates relative to the plane origin (xorigin, yorigin) + pub x: isize, + pub y: isize, + pub width: usize, + pub height: usize, +} + +// Structure to describe a rectangle area in several ways +// +// To retrieve a subregion from a region, we need to provide the subregion +// bounds, relative to its parent region. The subregion must always be included +// in its parent region. +// +// For that purpose, we could just use a rectangle (x, y, width, height), but +// this would be too cumbersome to use in practice. For example, we often need +// to pass a subregion from an offset, using the same bottom-right corner as +// its parent, or to pass a subregion expressed in block offset instead of +// pixel offset. +// +// Area provides a flexible way to describe a subregion. +#[derive(Debug, Clone, Copy)] +pub enum Area { + /// A well-defined rectangle + Rect(Rect), + /// A rectangle starting at offset (x, y) and ending at the bottom-right + /// corner of the parent + StartingAt { x: isize, y: isize }, + /// a rectangle starting at given block offset until the bottom-right corner + /// of the parent + BlockStartingAt { bo: BlockOffset }, +} + +impl Area { + /// Convert to a rectangle of pixels. + /// For a `BlockRect` and `BlockStartingAt`, for subsampled chroma planes, + /// the returned rect will be aligned to a 4x4 chroma block. + /// This is necessary for `compute_distortion` and `rdo_cfl_alpha` as + /// the subsampled chroma block covers multiple luma blocks. + pub const fn to_rect( + self, + xdec: usize, + ydec: usize, + parent_width: usize, + parent_height: usize, + ) -> Rect { + match self { + Area::Rect(rect) => rect, + Area::StartingAt { x, y } => Rect { + x, + y, + width: (parent_width as isize - x) as usize, + height: (parent_height as isize - y) as usize, + }, + Area::BlockStartingAt { bo } => { + let x = (bo.x >> xdec << BLOCK_TO_PLANE_SHIFT) as isize; + let y = (bo.y >> ydec << BLOCK_TO_PLANE_SHIFT) as isize; + Rect { + x, + y, + width: (parent_width as isize - x) as usize, + height: (parent_height as isize - y) as usize, + } + } + } + } +} + +pub trait AsRegion { + fn as_region(&self) -> PlaneRegion<'_, T>; + fn region(&self, area: Area) -> PlaneRegion<'_, T>; + fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T>; +} + +impl AsRegion for Plane { + fn as_region(&self) -> PlaneRegion<'_, T> { + PlaneRegion::new_from_plane(self) + } + + fn region(&self, area: Area) -> PlaneRegion<'_, T> { + let rect = area.to_rect( + self.cfg.xdec, + self.cfg.ydec, + self.cfg.stride - self.cfg.xorigin, + self.cfg.alloc_height - self.cfg.yorigin, + ); + PlaneRegion::new(self, rect) + } + + fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T> { + let rect = area.to_rect( + self.cfg.xdec, + self.cfg.ydec, + self.cfg.stride - self.cfg.xorigin, + self.cfg.alloc_height - self.cfg.yorigin, + ); + PlaneRegionMut::new(self, rect) + } +} + +/// Absolute offset in blocks inside a plane, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PlaneBlockOffset(pub BlockOffset); + +impl PlaneBlockOffset { + /// Convert to plane offset without decimation. + pub const fn to_luma_plane_offset(self) -> PlaneOffset { + self.0.to_luma_plane_offset() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/prediction.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/prediction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/prediction.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/prediction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,148 @@ +use v_frame::{ + pixel::Pixel, + plane::{Plane, PlaneConfig, PlaneOffset, PlaneSlice}, +}; + +use crate::{ + cpu::CpuFeatureLevel, + data::{ + frame::{FrameInvariants, RefType}, + mc::put_8tap, + motion::MotionVector, + plane::PlaneRegionMut, + tile::TileRect, + }, +}; + +// There are more modes than in the spec because every allowed +// drl index for NEAR modes is considered its own mode. +#[allow(non_camel_case_types)] +#[allow(clippy::upper_case_acronyms)] +#[allow(dead_code)] +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default)] +pub enum PredictionMode { + #[default] + DC_PRED, // Average of above and left pixels + V_PRED, // Vertical + H_PRED, // Horizontal + D45_PRED, // Directional 45 degree + D135_PRED, // Directional 135 degree + D113_PRED, // Directional 113 degree + D157_PRED, // Directional 157 degree + D203_PRED, // Directional 203 degree + D67_PRED, // Directional 67 degree + SMOOTH_PRED, // Combination of horizontal and vertical interpolation + SMOOTH_V_PRED, + SMOOTH_H_PRED, + PAETH_PRED, + UV_CFL_PRED, + NEARESTMV, + NEAR0MV, + NEAR1MV, + NEAR2MV, + GLOBALMV, + NEWMV, + // Compound ref compound modes + NEAREST_NEARESTMV, + NEAR_NEAR0MV, + NEAR_NEAR1MV, + NEAR_NEAR2MV, + NEAREST_NEWMV, + NEW_NEARESTMV, + NEAR_NEW0MV, + NEAR_NEW1MV, + NEAR_NEW2MV, + NEW_NEAR0MV, + NEW_NEAR1MV, + NEW_NEAR2MV, + GLOBAL_GLOBALMV, + NEW_NEWMV, +} + +impl PredictionMode { + pub fn is_intra(self) -> bool { + self < PredictionMode::NEARESTMV + } + + /// Inter prediction with a single reference (i.e. not compound mode) + /// + /// # Panics + /// + /// - If called on an intra `PredictionMode` + #[allow(clippy::too_many_arguments)] + pub fn predict_inter_single( + self, + fi: &FrameInvariants, + tile_rect: TileRect, + p: usize, + po: PlaneOffset, + dst: &mut PlaneRegionMut<'_, T>, + width: usize, + height: usize, + ref_frame: RefType, + mv: MotionVector, + bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, + ) { + assert!(!self.is_intra()); + let frame_po = tile_rect.to_frame_plane_offset(po); + + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] { + let (row_frac, col_frac, src) = + PredictionMode::get_mv_params(&rec.frame.planes[p], frame_po, mv); + put_8tap( + dst, + src, + width, + height, + col_frac, + row_frac, + bit_depth, + cpu_feature_level, + ); + } + } + + // Used by inter prediction to extract the fractional component of a mv and + // obtain the correct PlaneSlice to operate on. + fn get_mv_params( + rec_plane: &Plane, + po: PlaneOffset, + mv: MotionVector, + ) -> (i32, i32, PlaneSlice) { + let &PlaneConfig { xdec, ydec, .. } = &rec_plane.cfg; + let row_offset = mv.row as i32 >> (3 + ydec); + let col_offset = mv.col as i32 >> (3 + xdec); + let row_frac = ((mv.row as i32) << (1 - ydec)) & 0xf; + let col_frac = ((mv.col as i32) << (1 - xdec)) & 0xf; + let qo = PlaneOffset { + x: po.x + col_offset as isize - 3, + y: po.y + row_offset as isize - 3, + }; + ( + row_frac, + col_frac, + rec_plane.slice(qo).clamp().subslice(3, 3), + ) + } +} + +#[derive(Copy, Clone, Debug)] +#[allow(clippy::upper_case_acronyms)] +pub enum PredictionVariant { + NONE, + LEFT, + TOP, + BOTH, +} + +impl PredictionVariant { + pub const fn new(x: usize, y: usize) -> Self { + match (x, y) { + (0, 0) => PredictionVariant::NONE, + (_, 0) => PredictionVariant::LEFT, + (0, _) => PredictionVariant::TOP, + _ => PredictionVariant::BOTH, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/sad/simd_x86.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad/simd_x86.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/sad/simd_x86.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad/simd_x86.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +use v_frame::{ + pixel::{Pixel, PixelType}, + plane::Plane, +}; + +use crate::CpuFeatureLevel; + +macro_rules! decl_sad_plane_fn { + ($($f:ident),+) => { + extern "C" { + $( + fn $f( + src: *const u8, dst: *const u8, stride: libc::size_t, + width: libc::size_t, rows: libc::size_t + ) -> u64; + )* + } + }; + } + +decl_sad_plane_fn!(avsc_sad_plane_8bpc_sse2, avsc_sad_plane_8bpc_avx2); + +pub(super) fn sad_plane_internal( + src: &Plane, + dst: &Plane, + cpu: CpuFeatureLevel, +) -> u64 { + use std::mem; + + assert_eq!(src.cfg.width, dst.cfg.width); + assert_eq!(src.cfg.stride, dst.cfg.stride); + assert_eq!(src.cfg.height, dst.cfg.height); + assert!(src.cfg.width <= src.cfg.stride); + + match T::type_enum() { + PixelType::U8 => { + // helper macro to reduce boilerplate + macro_rules! call_asm { + ($func:ident, $src:expr, $dst:expr, $cpu:expr) => { + // SAFETY: Calls Assembly code. + unsafe { + let result = $func( + mem::transmute::<*const T, *const u8>(src.data_origin().as_ptr()), + mem::transmute::<*const T, *const u8>(dst.data_origin().as_ptr()), + src.cfg.stride, + src.cfg.width, + src.cfg.height, + ); + + result + } + }; + } + + if cpu >= CpuFeatureLevel::AVX2 { + call_asm!(avsc_sad_plane_8bpc_avx2, src, dst, cpu) + } else if cpu >= CpuFeatureLevel::SSE2 { + call_asm!(avsc_sad_plane_8bpc_sse2, src, dst, cpu) + } else { + super::rust::sad_plane_internal(src, dst, cpu) + } + } + PixelType::U16 => super::rust::sad_plane_internal(src, dst, cpu), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/sad.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/sad.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/sad.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +#[cfg(asm_x86_64)] +mod simd_x86; + +use rust::get_sad_internal; +#[cfg(not(asm_x86_64))] +use rust::*; +#[cfg(asm_x86_64)] +use simd_x86::*; +use v_frame::{pixel::Pixel, plane::Plane}; + +use super::plane::PlaneRegion; +use crate::cpu::CpuFeatureLevel; + +mod rust { + use v_frame::{ + pixel::{CastFromPrimitive, Pixel}, + plane::Plane, + }; + + use crate::{ + data::plane::{Area, PlaneRegion, Rect}, + CpuFeatureLevel, + }; + + pub(super) fn sad_plane_internal( + src: &Plane, + dst: &Plane, + _cpu: CpuFeatureLevel, + ) -> u64 { + assert_eq!(src.cfg.width, dst.cfg.width); + assert_eq!(src.cfg.height, dst.cfg.height); + + src.rows_iter() + .zip(dst.rows_iter()) + .map(|(src, dst)| { + src.iter() + .zip(dst.iter()) + .map(|(&p1, &p2)| i32::cast_from(p1).abs_diff(i32::cast_from(p2))) + .sum::() as u64 + }) + .sum() + } + + pub fn get_sad_internal( + plane_org: &PlaneRegion<'_, T>, + plane_ref: &PlaneRegion<'_, T>, + w: usize, + h: usize, + _bit_depth: usize, + _cpu: CpuFeatureLevel, + ) -> u32 { + debug_assert!(w <= 128 && h <= 128); + let plane_org = plane_org.subregion(Area::Rect(Rect { + x: 0, + y: 0, + width: w, + height: h, + })); + let plane_ref = plane_ref.subregion(Area::Rect(Rect { + x: 0, + y: 0, + width: w, + height: h, + })); + + plane_org + .rows_iter() + .zip(plane_ref.rows_iter()) + .map(|(src, dst)| { + src.iter() + .zip(dst) + .map(|(&p1, &p2)| i32::cast_from(p1).abs_diff(i32::cast_from(p2))) + .sum::() + }) + .sum() + } +} + +/// Compute the sum of absolute differences (SADs) on 2 rows of pixels +/// +/// This differs from other SAD functions in that it operates over a row +/// (or line) of unknown length rather than a `PlaneRegion`. +pub(crate) fn sad_plane(src: &Plane, dst: &Plane, cpu: CpuFeatureLevel) -> u64 { + sad_plane_internal(src, dst, cpu) +} + +pub(crate) fn get_sad( + plane_org: &PlaneRegion<'_, T>, + plane_ref: &PlaneRegion<'_, T>, + w: usize, + h: usize, + bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u32 { + get_sad_internal(plane_org, plane_ref, w, h, bit_depth, cpu) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_neon.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,200 @@ +use v_frame::pixel::{Pixel, PixelType}; + +use super::{to_index, DIST_FNS_LENGTH}; +use crate::{ + cpu::CpuFeatureLevel, + data::{block::BlockSize, plane::PlaneRegion}, +}; + +type SatdFn = unsafe extern "C" fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, +) -> u32; +type SatdHbdFn = unsafe extern "C" fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, +) -> u32; + +macro_rules! declare_asm_dist_fn { + ($(($name: ident, $T: ident)),+) => ( + $( + extern "C" { fn $name ( + src: *const $T, src_stride: isize, dst: *const $T, dst_stride: isize + ) -> u32; } + )+ + ) + } + +declare_asm_dist_fn![ + // SATD + (avsc_satd4x4_neon, u8), + (avsc_satd4x8_neon, u8), + (avsc_satd4x16_neon, u8), + (avsc_satd8x4_neon, u8), + (avsc_satd8x8_neon, u8), + (avsc_satd8x16_neon, u8), + (avsc_satd8x32_neon, u8), + (avsc_satd16x4_neon, u8), + (avsc_satd16x8_neon, u8), + (avsc_satd16x16_neon, u8), + (avsc_satd16x32_neon, u8), + (avsc_satd16x64_neon, u8), + (avsc_satd32x8_neon, u8), + (avsc_satd32x16_neon, u8), + (avsc_satd32x32_neon, u8), + (avsc_satd32x64_neon, u8), + (avsc_satd64x16_neon, u8), + (avsc_satd64x32_neon, u8), + (avsc_satd64x64_neon, u8), + (avsc_satd64x128_neon, u8), + (avsc_satd128x64_neon, u8), + (avsc_satd128x128_neon, u8), + // SATD HBD + (avsc_satd4x4_hbd_neon, u16), + (avsc_satd4x8_hbd_neon, u16), + (avsc_satd4x16_hbd_neon, u16), + (avsc_satd8x4_hbd_neon, u16), + (avsc_satd8x8_hbd_neon, u16), + (avsc_satd8x16_hbd_neon, u16), + (avsc_satd8x32_hbd_neon, u16), + (avsc_satd16x4_hbd_neon, u16), + (avsc_satd16x8_hbd_neon, u16), + (avsc_satd16x16_hbd_neon, u16), + (avsc_satd16x32_hbd_neon, u16), + (avsc_satd16x64_hbd_neon, u16), + (avsc_satd32x8_hbd_neon, u16), + (avsc_satd32x16_hbd_neon, u16), + (avsc_satd32x32_hbd_neon, u16), + (avsc_satd32x64_hbd_neon, u16), + (avsc_satd64x16_hbd_neon, u16), + (avsc_satd64x32_hbd_neon, u16), + (avsc_satd64x64_hbd_neon, u16), + (avsc_satd64x128_hbd_neon, u16), + (avsc_satd128x64_hbd_neon, u16), + (avsc_satd128x128_hbd_neon, u16) +]; + +static SATD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use crate::data::block::BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(avsc_satd4x4_neon); + out[BLOCK_4X8 as usize] = Some(avsc_satd4x8_neon); + out[BLOCK_4X16 as usize] = Some(avsc_satd4x16_neon); + out[BLOCK_8X4 as usize] = Some(avsc_satd8x4_neon); + out[BLOCK_16X4 as usize] = Some(avsc_satd16x4_neon); + + out[BLOCK_8X8 as usize] = Some(avsc_satd8x8_neon); + out[BLOCK_8X16 as usize] = Some(avsc_satd8x16_neon); + out[BLOCK_8X32 as usize] = Some(avsc_satd8x32_neon); + out[BLOCK_16X8 as usize] = Some(avsc_satd16x8_neon); + out[BLOCK_16X16 as usize] = Some(avsc_satd16x16_neon); + out[BLOCK_16X32 as usize] = Some(avsc_satd16x32_neon); + out[BLOCK_16X64 as usize] = Some(avsc_satd16x64_neon); + out[BLOCK_32X8 as usize] = Some(avsc_satd32x8_neon); + out[BLOCK_32X16 as usize] = Some(avsc_satd32x16_neon); + out[BLOCK_32X32 as usize] = Some(avsc_satd32x32_neon); + out[BLOCK_32X64 as usize] = Some(avsc_satd32x64_neon); + out[BLOCK_64X16 as usize] = Some(avsc_satd64x16_neon); + out[BLOCK_64X32 as usize] = Some(avsc_satd64x32_neon); + out[BLOCK_64X64 as usize] = Some(avsc_satd64x64_neon); + out[BLOCK_64X128 as usize] = Some(avsc_satd64x128_neon); + out[BLOCK_128X64 as usize] = Some(avsc_satd128x64_neon); + out[BLOCK_128X128 as usize] = Some(avsc_satd128x128_neon); + + out +}; + +static SATD_HBD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use crate::data::block::BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(avsc_satd4x4_hbd_neon); + out[BLOCK_4X8 as usize] = Some(avsc_satd4x8_hbd_neon); + out[BLOCK_4X16 as usize] = Some(avsc_satd4x16_hbd_neon); + out[BLOCK_8X4 as usize] = Some(avsc_satd8x4_hbd_neon); + out[BLOCK_16X4 as usize] = Some(avsc_satd16x4_hbd_neon); + + out[BLOCK_8X8 as usize] = Some(avsc_satd8x8_hbd_neon); + out[BLOCK_8X16 as usize] = Some(avsc_satd8x16_hbd_neon); + out[BLOCK_8X32 as usize] = Some(avsc_satd8x32_hbd_neon); + out[BLOCK_16X8 as usize] = Some(avsc_satd16x8_hbd_neon); + out[BLOCK_16X16 as usize] = Some(avsc_satd16x16_hbd_neon); + out[BLOCK_16X32 as usize] = Some(avsc_satd16x32_hbd_neon); + out[BLOCK_16X64 as usize] = Some(avsc_satd16x64_hbd_neon); + out[BLOCK_32X8 as usize] = Some(avsc_satd32x8_hbd_neon); + out[BLOCK_32X16 as usize] = Some(avsc_satd32x16_hbd_neon); + out[BLOCK_32X32 as usize] = Some(avsc_satd32x32_hbd_neon); + out[BLOCK_32X64 as usize] = Some(avsc_satd32x64_hbd_neon); + out[BLOCK_64X16 as usize] = Some(avsc_satd64x16_hbd_neon); + out[BLOCK_64X32 as usize] = Some(avsc_satd64x32_hbd_neon); + out[BLOCK_64X64 as usize] = Some(avsc_satd64x64_hbd_neon); + out[BLOCK_64X128 as usize] = Some(avsc_satd64x128_hbd_neon); + out[BLOCK_128X64 as usize] = Some(avsc_satd128x64_hbd_neon); + out[BLOCK_128X128 as usize] = Some(avsc_satd128x128_hbd_neon); + + out +}; + +cpu_function_lookup_table!( + SATD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +cpu_function_lookup_table!( + SATD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +pub(super) fn get_satd_internal( + src: &PlaneRegion<'_, T>, + dst: &PlaneRegion<'_, T>, + w: usize, + h: usize, + bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { super::rust::get_satd_internal(src, dst, w, h, bit_depth, cpu) }; + + match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SATD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SATD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_x86.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_x86.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_x86.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/simd_x86.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,242 @@ +use v_frame::pixel::{Pixel, PixelType}; + +use super::{to_index, DIST_FNS_LENGTH}; +use crate::{ + cpu::CpuFeatureLevel, + data::{block::BlockSize, plane::PlaneRegion}, +}; + +type SatdFn = unsafe extern "C" fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, +) -> u32; + +type SatdHBDFn = unsafe extern "C" fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, + bdmax: u32, +) -> u32; + +macro_rules! declare_asm_dist_fn { + ($(($name: ident, $T: ident)),+) => ( + $( + extern "C" { fn $name ( + src: *const $T, src_stride: isize, dst: *const $T, dst_stride: isize + ) -> u32; } + )+ + ) + } + +macro_rules! declare_asm_satd_hbd_fn { + ($($name: ident),+) => ( + $( + extern "C" { pub(crate) fn $name ( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, bdmax: u32 + ) -> u32; } + )+ + ) + } + +declare_asm_dist_fn![ + // SSSE3 + (avsc_satd_8x8_ssse3, u8), + // SSE4 + (avsc_satd_4x4_sse4, u8), + // AVX + (avsc_satd_4x4_avx2, u8), + (avsc_satd_8x8_avx2, u8), + (avsc_satd_16x16_avx2, u8), + (avsc_satd_32x32_avx2, u8), + (avsc_satd_64x64_avx2, u8), + (avsc_satd_128x128_avx2, u8), + (avsc_satd_4x8_avx2, u8), + (avsc_satd_8x4_avx2, u8), + (avsc_satd_8x16_avx2, u8), + (avsc_satd_16x8_avx2, u8), + (avsc_satd_16x32_avx2, u8), + (avsc_satd_32x16_avx2, u8), + (avsc_satd_32x64_avx2, u8), + (avsc_satd_64x32_avx2, u8), + (avsc_satd_64x128_avx2, u8), + (avsc_satd_128x64_avx2, u8), + (avsc_satd_4x16_avx2, u8), + (avsc_satd_16x4_avx2, u8), + (avsc_satd_8x32_avx2, u8), + (avsc_satd_32x8_avx2, u8), + (avsc_satd_16x64_avx2, u8), + (avsc_satd_64x16_avx2, u8) +]; + +declare_asm_satd_hbd_fn![ + avsc_satd_4x4_hbd_avx2, + avsc_satd_8x4_hbd_avx2, + avsc_satd_4x8_hbd_avx2, + avsc_satd_8x8_hbd_avx2, + avsc_satd_16x8_hbd_avx2, + avsc_satd_16x16_hbd_avx2, + avsc_satd_32x32_hbd_avx2, + avsc_satd_64x64_hbd_avx2, + avsc_satd_128x128_hbd_avx2, + avsc_satd_16x32_hbd_avx2, + avsc_satd_16x64_hbd_avx2, + avsc_satd_32x16_hbd_avx2, + avsc_satd_32x64_hbd_avx2, + avsc_satd_64x16_hbd_avx2, + avsc_satd_64x32_hbd_avx2, + avsc_satd_64x128_hbd_avx2, + avsc_satd_128x64_hbd_avx2, + avsc_satd_32x8_hbd_avx2, + avsc_satd_8x16_hbd_avx2, + avsc_satd_8x32_hbd_avx2, + avsc_satd_16x4_hbd_avx2, + avsc_satd_4x16_hbd_avx2 +]; + +static SATD_FNS_SSSE3: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_8X8 as usize] = Some(avsc_satd_8x8_ssse3); + + out +}; + +static SATD_FNS_SSE4_1: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(avsc_satd_4x4_sse4); + out[BLOCK_8X8 as usize] = Some(avsc_satd_8x8_ssse3); + + out +}; + +static SATD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(avsc_satd_4x4_avx2); + out[BLOCK_8X8 as usize] = Some(avsc_satd_8x8_avx2); + out[BLOCK_16X16 as usize] = Some(avsc_satd_16x16_avx2); + out[BLOCK_32X32 as usize] = Some(avsc_satd_32x32_avx2); + out[BLOCK_64X64 as usize] = Some(avsc_satd_64x64_avx2); + out[BLOCK_128X128 as usize] = Some(avsc_satd_128x128_avx2); + + out[BLOCK_4X8 as usize] = Some(avsc_satd_4x8_avx2); + out[BLOCK_8X4 as usize] = Some(avsc_satd_8x4_avx2); + out[BLOCK_8X16 as usize] = Some(avsc_satd_8x16_avx2); + out[BLOCK_16X8 as usize] = Some(avsc_satd_16x8_avx2); + out[BLOCK_16X32 as usize] = Some(avsc_satd_16x32_avx2); + out[BLOCK_32X16 as usize] = Some(avsc_satd_32x16_avx2); + out[BLOCK_32X64 as usize] = Some(avsc_satd_32x64_avx2); + out[BLOCK_64X32 as usize] = Some(avsc_satd_64x32_avx2); + out[BLOCK_64X128 as usize] = Some(avsc_satd_64x128_avx2); + out[BLOCK_128X64 as usize] = Some(avsc_satd_128x64_avx2); + + out[BLOCK_4X16 as usize] = Some(avsc_satd_4x16_avx2); + out[BLOCK_16X4 as usize] = Some(avsc_satd_16x4_avx2); + out[BLOCK_8X32 as usize] = Some(avsc_satd_8x32_avx2); + out[BLOCK_32X8 as usize] = Some(avsc_satd_32x8_avx2); + out[BLOCK_16X64 as usize] = Some(avsc_satd_16x64_avx2); + out[BLOCK_64X16 as usize] = Some(avsc_satd_64x16_avx2); + + out +}; + +cpu_function_lookup_table!( + SATD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSSE3, SSE4_1, AVX2] +); + +static SATD_HBD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(avsc_satd_4x4_hbd_avx2); + out[BLOCK_8X8 as usize] = Some(avsc_satd_8x8_hbd_avx2); + out[BLOCK_16X16 as usize] = Some(avsc_satd_16x16_hbd_avx2); + out[BLOCK_32X32 as usize] = Some(avsc_satd_32x32_hbd_avx2); + out[BLOCK_64X64 as usize] = Some(avsc_satd_64x64_hbd_avx2); + out[BLOCK_128X128 as usize] = Some(avsc_satd_128x128_hbd_avx2); + + out[BLOCK_4X8 as usize] = Some(avsc_satd_4x8_hbd_avx2); + out[BLOCK_8X4 as usize] = Some(avsc_satd_8x4_hbd_avx2); + out[BLOCK_8X16 as usize] = Some(avsc_satd_8x16_hbd_avx2); + out[BLOCK_16X8 as usize] = Some(avsc_satd_16x8_hbd_avx2); + out[BLOCK_16X32 as usize] = Some(avsc_satd_16x32_hbd_avx2); + out[BLOCK_32X16 as usize] = Some(avsc_satd_32x16_hbd_avx2); + out[BLOCK_32X64 as usize] = Some(avsc_satd_32x64_hbd_avx2); + out[BLOCK_64X32 as usize] = Some(avsc_satd_64x32_hbd_avx2); + out[BLOCK_64X128 as usize] = Some(avsc_satd_64x128_hbd_avx2); + out[BLOCK_128X64 as usize] = Some(avsc_satd_128x64_hbd_avx2); + + out[BLOCK_4X16 as usize] = Some(avsc_satd_4x16_hbd_avx2); + out[BLOCK_16X4 as usize] = Some(avsc_satd_16x4_hbd_avx2); + out[BLOCK_8X32 as usize] = Some(avsc_satd_8x32_hbd_avx2); + out[BLOCK_32X8 as usize] = Some(avsc_satd_32x8_hbd_avx2); + out[BLOCK_16X64 as usize] = Some(avsc_satd_16x64_hbd_avx2); + out[BLOCK_64X16 as usize] = Some(avsc_satd_64x16_hbd_avx2); + + out +}; + +cpu_function_lookup_table!( + SATD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [AVX2] +); + +pub(super) fn get_satd_internal( + src: &PlaneRegion<'_, T>, + dst: &PlaneRegion<'_, T>, + w: usize, + h: usize, + bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { super::rust::get_satd_internal(dst, src, w, h, bit_depth, cpu) }; + + match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SATD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SATD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + (1 << bit_depth) - 1, + ) + }, + None => call_rust(), + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +use v_frame::{pixel::Pixel, plane::Plane}; + +use crate::{ + data::{ + plane::{Area, AsRegion}, + satd::get_satd, + }, + CpuFeatureLevel, +}; + +// Generate plane data for get_sad_same() +fn setup_planes() -> (Plane, Plane) { + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + // Make the test pattern robust to data alignment + let xpad_off = (input_plane.cfg.xorigin - input_plane.cfg.xpad) as i32 - 8i32; + + for (i, row) in input_plane + .data + .chunks_mut(input_plane.cfg.stride) + .enumerate() + { + for (j, pixel) in row.iter_mut().enumerate() { + let val = ((j + i) as i32 - xpad_off) & 255i32; + assert!(val >= u8::MIN.into() && val <= u8::MAX.into()); + *pixel = T::cast_from(val); + } + } + + for (i, row) in rec_plane.data.chunks_mut(rec_plane.cfg.stride).enumerate() { + for (j, pixel) in row.iter_mut().enumerate() { + let val = (j as i32 - i as i32 - xpad_off) & 255i32; + assert!(val >= u8::MIN.into() && val <= u8::MAX.into()); + *pixel = T::cast_from(val); + } + } + + (input_plane, rec_plane) +} + +fn get_satd_same_inner() { + let blocks: Vec<(usize, usize, u32)> = vec![ + (4, 4, 1408), + (4, 8, 2016), + (8, 4, 1816), + (8, 8, 3984), + (8, 16, 5136), + (16, 8, 4864), + (16, 16, 9984), + (16, 32, 13824), + (32, 16, 13760), + (32, 32, 27952), + (32, 64, 37168), + (64, 32, 45104), + (64, 64, 84176), + (64, 128, 127920), + (128, 64, 173680), + (128, 128, 321456), + (4, 16, 3136), + (16, 4, 2632), + (8, 32, 7056), + (32, 8, 6624), + (16, 64, 18432), + (64, 16, 21312), + ]; + + let bit_depth: usize = 8; + let (input_plane, rec_plane) = setup_planes::(); + + for (w, h, distortion) in blocks { + let area = Area::StartingAt { x: 32, y: 40 }; + + let input_region = input_plane.region(area); + let rec_region = rec_plane.region(area); + + assert_eq!( + distortion, + get_satd( + &input_region, + &rec_region, + w, + h, + bit_depth, + CpuFeatureLevel::default() + ) + ); + } +} + +#[test] +fn get_satd_same_u8() { + get_satd_same_inner::(); +} + +#[test] +fn get_satd_same_u16() { + get_satd_same_inner::(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/satd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/satd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,127 @@ +#[cfg(asm_neon)] +mod simd_neon; +#[cfg(asm_x86_64)] +mod simd_x86; +#[cfg(test)] +mod tests; + +#[cfg(not(any(asm_x86_64, asm_neon)))] +use rust::*; +#[cfg(asm_neon)] +use simd_neon::*; +#[cfg(asm_x86_64)] +use simd_x86::*; +use v_frame::pixel::Pixel; + +use super::{block::BlockSize, plane::PlaneRegion}; +use crate::cpu::CpuFeatureLevel; + +mod rust { + use v_frame::{ + math::msb, + pixel::{CastFromPrimitive, Pixel}, + }; + + use crate::{ + cpu::CpuFeatureLevel, + data::{ + hadamard::{hadamard4x4, hadamard8x8}, + plane::{Area, PlaneRegion, Rect}, + sad::get_sad, + }, + }; + + /// Sum of absolute transformed differences over a block. + /// w and h can be at most 128, the size of the largest block. + /// Use the sum of 4x4 and 8x8 hadamard transforms for the transform, but + /// revert to sad on edges when these transforms do not fit into w and h. + /// 4x4 transforms instead of 8x8 transforms when width or height < 8. + #[cfg_attr(all(asm_x86_64, target_feature = "avx2"), cold)] + #[cfg_attr(asm_neon, cold)] + pub(super) fn get_satd_internal( + plane_org: &PlaneRegion<'_, T>, + plane_ref: &PlaneRegion<'_, T>, + w: usize, + h: usize, + bit_depth: usize, + cpu: CpuFeatureLevel, + ) -> u32 { + assert!(w <= 128 && h <= 128); + assert!(plane_org.rect().width >= w && plane_org.rect().height >= h); + assert!(plane_ref.rect().width >= w && plane_ref.rect().height >= h); + + // Size of hadamard transform should be 4x4 or 8x8 + // 4x* and *x4 use 4x4 and all other use 8x8 + let size: usize = w.min(h).min(8); + let tx2d = if size == 4 { hadamard4x4 } else { hadamard8x8 }; + + let mut sum: u64 = 0; + + // Loop over chunks the size of the chosen transform + for chunk_y in (0..h).step_by(size) { + let chunk_h = (h - chunk_y).min(size); + for chunk_x in (0..w).step_by(size) { + let chunk_w = (w - chunk_x).min(size); + let chunk_area = Area::Rect(Rect { + x: chunk_x as isize, + y: chunk_y as isize, + width: chunk_w, + height: chunk_h, + }); + let chunk_org = plane_org.subregion(chunk_area); + let chunk_ref = plane_ref.subregion(chunk_area); + + // Revert to sad on edge blocks (frame edges) + if chunk_w != size || chunk_h != size { + sum += get_sad(&chunk_org, &chunk_ref, chunk_w, chunk_h, bit_depth, cpu) as u64; + continue; + } + + let buf: &mut [i32] = &mut [0; 8 * 8][..size * size]; + + // Move the difference of the transforms to a buffer + for (row_diff, (row_org, row_ref)) in buf + .chunks_mut(size) + .zip(chunk_org.rows_iter().zip(chunk_ref.rows_iter())) + { + for (diff, (a, b)) in + row_diff.iter_mut().zip(row_org.iter().zip(row_ref.iter())) + { + *diff = i32::cast_from(*a) - i32::cast_from(*b); + } + } + + // Perform the hadamard transform on the differences + // SAFETY: A sufficient number elements exist for the size of the transform. + unsafe { + tx2d(buf); + } + + // Sum the absolute values of the transformed differences + sum += buf.iter().map(|a| a.unsigned_abs() as u64).sum::(); + } + } + + // Normalize the results + let ln = msb(size as i32) as u64; + ((sum + (1 << ln >> 1)) >> ln) as u32 + } +} + +// BlockSize::BLOCK_SIZES.next_power_of_two() +const DIST_FNS_LENGTH: usize = 32; + +const fn to_index(bsize: BlockSize) -> usize { + bsize as usize & (DIST_FNS_LENGTH - 1) +} + +pub(crate) fn get_satd( + src: &PlaneRegion<'_, T>, + dst: &PlaneRegion<'_, T>, + w: usize, + h: usize, + bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u32 { + get_satd_internal(src, dst, w, h, bit_depth, cpu) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/superblock.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/superblock.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/superblock.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/superblock.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +use crate::data::{ + block::{BlockOffset, MIB_SIZE_LOG2}, + tile::TileBlockOffset, +}; + +pub const MAX_SB_SIZE_LOG2: usize = 7; +pub const SUPERBLOCK_TO_BLOCK_SHIFT: usize = MIB_SIZE_LOG2; +pub const SB_SIZE_LOG2: usize = 6; +pub const SB_SIZE: usize = 1 << SB_SIZE_LOG2; +pub const MI_SIZE_LOG2: usize = 2; +pub const MI_SIZE: usize = 1 << MI_SIZE_LOG2; + +/// Absolute offset in superblocks inside a tile, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TileSuperBlockOffset(pub SuperBlockOffset); + +impl TileSuperBlockOffset { + /// Offset of a block inside the current superblock. + pub const fn block_offset(self, block_x: usize, block_y: usize) -> TileBlockOffset { + TileBlockOffset(self.0.block_offset(block_x, block_y)) + } +} + +/// Absolute offset in superblocks inside a plane, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PlaneSuperBlockOffset(pub SuperBlockOffset); + +/// Absolute offset in superblocks, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SuperBlockOffset { + pub x: usize, + pub y: usize, +} + +impl SuperBlockOffset { + /// Offset of a block inside the current superblock. + const fn block_offset(self, block_x: usize, block_y: usize) -> BlockOffset { + BlockOffset { + x: (self.x << SUPERBLOCK_TO_BLOCK_SHIFT) + block_x, + y: (self.y << SUPERBLOCK_TO_BLOCK_SHIFT) + block_y, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/tile.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/tile.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/data/tile.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/data/tile.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,420 @@ +use std::iter::FusedIterator; + +use v_frame::{ + frame::Frame, + math::Fixed, + pixel::Pixel, + plane::{Plane, PlaneOffset}, +}; + +use crate::data::{ + block::BlockOffset, + frame::{FrameState, MAX_PLANES}, + motion::{FrameMEStats, TileMEStatsMut, WriteGuardMEStats}, + plane::{PlaneBlockOffset, PlaneRegion, Rect}, + superblock::{PlaneSuperBlockOffset, SuperBlockOffset, MI_SIZE, MI_SIZE_LOG2, SB_SIZE_LOG2}, +}; + +pub const MAX_TILE_WIDTH: usize = 4096; +pub const MAX_TILE_AREA: usize = 4096 * 2304; +pub const MAX_TILE_COLS: usize = 64; +pub const MAX_TILE_ROWS: usize = 64; +pub const MAX_TILE_RATE: f64 = 4096f64 * 2176f64 * 60f64 * 1.1; + +/// Tiled view of a frame +#[derive(Debug)] +pub struct Tile<'a, T: Pixel> { + pub planes: [PlaneRegion<'a, T>; MAX_PLANES], +} + +// common impl for Tile and TileMut +macro_rules! tile_common { + // $name: Tile or TileMut + // $pr_type: PlaneRegion or PlaneRegionMut + // $iter: iter or iter_mut + //opt_mut: nothing or mut + ($name:ident, $pr_type:ident, $iter:ident $(,$opt_mut:tt)?) => { + impl<'a, T: Pixel> $name<'a, T> { + + pub fn new( + frame: &'a $($opt_mut)? Frame, + luma_rect: TileRect, + ) -> Self { + let mut planes_iter = frame.planes.$iter(); + Self { + planes: [ + { + let plane = planes_iter.next().unwrap(); + $pr_type::new(plane, luma_rect.into()) + }, + { + let plane = planes_iter.next().unwrap(); + let rect = luma_rect.decimated(plane.cfg.xdec, plane.cfg.ydec); + $pr_type::new(plane, rect.into()) + }, + { + let plane = planes_iter.next().unwrap(); + let rect = luma_rect.decimated(plane.cfg.xdec, plane.cfg.ydec); + $pr_type::new(plane, rect.into()) + }, + ], + } + } + } + } +} + +tile_common!(Tile, PlaneRegion, iter); + +/// Rectangle of a tile, in pixels +/// +/// This is similar to Rect, but with unsigned (x, y) for convenience. +#[derive(Debug, Clone, Copy)] +pub struct TileRect { + pub x: usize, + pub y: usize, + pub width: usize, + pub height: usize, +} + +impl TileRect { + pub const fn decimated(self, xdec: usize, ydec: usize) -> Self { + Self { + x: self.x >> xdec, + y: self.y >> ydec, + width: self.width >> xdec, + height: self.height >> ydec, + } + } + + pub const fn to_frame_plane_offset(self, tile_po: PlaneOffset) -> PlaneOffset { + PlaneOffset { + x: self.x as isize + tile_po.x, + y: self.y as isize + tile_po.y, + } + } +} + +impl From for Rect { + fn from(tile_rect: TileRect) -> Rect { + Rect { + x: tile_rect.x as isize, + y: tile_rect.y as isize, + width: tile_rect.width, + height: tile_rect.height, + } + } +} + +/// Tiled view of `FrameState` +/// +/// Contrary to `PlaneRegionMut` and `TileMut`, there is no const version: +/// - in practice, we don't need it; +/// - it would require to instantiate a const version of every of its inner +/// tiled views recursively. +/// +/// # `TileState` fields +/// +/// The way the `FrameState` fields are mapped depend on how they are accessed +/// tile-wise and frame-wise. +/// +/// Some fields (like `qc`) are only used during tile-encoding, so they are only +/// stored in `TileState`. +/// +/// Some other fields (like `input` or `segmentation`) are not written +/// tile-wise, so they just reference the matching field in `FrameState`. +/// +/// Some others (like `rec`) are written tile-wise, but must be accessible +/// frame-wise once the tile views vanish (e.g. for deblocking). +#[derive(Debug)] +pub struct TileStateMut<'a, T: Pixel> { + pub sbo: PlaneSuperBlockOffset, + pub sb_width: usize, + pub sb_height: usize, + pub mi_width: usize, + pub mi_height: usize, + pub width: usize, + pub height: usize, + pub input_tile: Tile<'a, T>, // the current tile + pub input_hres: &'a Plane, + pub input_qres: &'a Plane, + pub me_stats: Vec>, +} + +impl<'a, T: Pixel> TileStateMut<'a, T> { + pub fn new( + fs: &'a mut FrameState, + sbo: PlaneSuperBlockOffset, + width: usize, + height: usize, + frame_me_stats: &'a mut [FrameMEStats], + ) -> Self { + debug_assert!( + width % MI_SIZE == 0, + "Tile width must be a multiple of MI_SIZE" + ); + debug_assert!( + height % MI_SIZE == 0, + "Tile width must be a multiple of MI_SIZE" + ); + + let sb_rounded_width = width.align_power_of_two(SB_SIZE_LOG2); + let sb_rounded_height = height.align_power_of_two(SB_SIZE_LOG2); + + let luma_rect = TileRect { + x: sbo.0.x << SB_SIZE_LOG2, + y: sbo.0.y << SB_SIZE_LOG2, + width: sb_rounded_width, + height: sb_rounded_height, + }; + let sb_width = width.align_power_of_two_and_shift(SB_SIZE_LOG2); + let sb_height = height.align_power_of_two_and_shift(SB_SIZE_LOG2); + + Self { + sbo, + sb_width, + sb_height, + mi_width: width >> MI_SIZE_LOG2, + mi_height: height >> MI_SIZE_LOG2, + width, + height, + input_tile: Tile::new(&fs.input, luma_rect), + input_hres: &fs.input_hres, + input_qres: &fs.input_qres, + me_stats: frame_me_stats + .iter_mut() + .map(|fmvs| { + TileMEStatsMut::new( + fmvs, + sbo.0.x << (SB_SIZE_LOG2 - MI_SIZE_LOG2), + sbo.0.y << (SB_SIZE_LOG2 - MI_SIZE_LOG2), + width >> MI_SIZE_LOG2, + height >> MI_SIZE_LOG2, + ) + }) + .collect(), + } + } + + pub fn to_frame_block_offset(&self, tile_bo: TileBlockOffset) -> PlaneBlockOffset { + let bx = self.sbo.0.x << (SB_SIZE_LOG2 - MI_SIZE_LOG2); + let by = self.sbo.0.y << (SB_SIZE_LOG2 - MI_SIZE_LOG2); + PlaneBlockOffset(BlockOffset { + x: bx + tile_bo.0.x, + y: by + tile_bo.0.y, + }) + } +} + +/// Absolute offset in blocks inside a tile, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct TileBlockOffset(pub BlockOffset); + +impl TileBlockOffset { + /// Convert to plane offset without decimation. + pub const fn to_luma_plane_offset(self) -> PlaneOffset { + self.0.to_luma_plane_offset() + } + + pub fn with_offset(self, col_offset: isize, row_offset: isize) -> TileBlockOffset { + Self(self.0.with_offset(col_offset, row_offset)) + } +} + +/// Tiling information +/// +/// This stores everything necessary to split a frame into tiles, and write +/// headers fields into the bitstream. +/// +/// The method `tile_iter_mut()` actually provides tiled views of `FrameState` +/// and `FrameBlocks`. +#[derive(Debug, Clone, Copy)] +pub struct TilingInfo { + pub frame_width: usize, + pub frame_height: usize, + pub tile_width_sb: usize, + pub tile_height_sb: usize, + pub cols: usize, // number of columns of tiles within the whole frame + pub rows: usize, // number of rows of tiles within the whole frame +} + +impl TilingInfo { + /// # Panics + /// + /// Panics if the resulting tile sizes would be too large. + pub fn from_target_tiles( + frame_width: usize, + frame_height: usize, + frame_rate: f64, + tile_cols_log2: usize, + tile_rows_log2: usize, + is_422_p: bool, + ) -> Self { + // + + // Frame::new() aligns to the next multiple of 8 + let frame_width = frame_width.align_power_of_two(3); + let frame_height = frame_height.align_power_of_two(3); + let frame_width_sb = frame_width.align_power_of_two_and_shift(SB_SIZE_LOG2); + let frame_height_sb = frame_height.align_power_of_two_and_shift(SB_SIZE_LOG2); + let sb_cols = frame_width.align_power_of_two_and_shift(SB_SIZE_LOG2); + let sb_rows = frame_height.align_power_of_two_and_shift(SB_SIZE_LOG2); + + // these are bitstream-defined values and must not be changed + let max_tile_width_sb = MAX_TILE_WIDTH >> SB_SIZE_LOG2; + let max_tile_area_sb = MAX_TILE_AREA >> (2 * SB_SIZE_LOG2); + let min_tile_cols_log2 = Self::tile_log2(max_tile_width_sb, sb_cols).unwrap(); + let max_tile_cols_log2 = Self::tile_log2(1, sb_cols.min(MAX_TILE_COLS)).unwrap(); + let max_tile_rows_log2 = Self::tile_log2(1, sb_rows.min(MAX_TILE_ROWS)).unwrap(); + let min_tiles_log2 = + min_tile_cols_log2.max(Self::tile_log2(max_tile_area_sb, sb_cols * sb_rows).unwrap()); + + // Implements restriction in Annex A of the spec. + // Unlike the other restrictions, this one does not change + // the header coding of the tile rows/cols. + let min_tiles_ratelimit_log2 = min_tiles_log2.max( + ((frame_width * frame_height) as f64 * frame_rate / MAX_TILE_RATE) + .ceil() + .log2() + .ceil() as usize, + ); + + let tile_cols_log2 = tile_cols_log2.clamp(min_tile_cols_log2, max_tile_cols_log2); + let tile_width_sb_pre = sb_cols.align_power_of_two_and_shift(tile_cols_log2); + + // If this is 4:2:2, our UV horizontal is subsampled but not our + // vertical. Loop Restoration Units must be square, so they + // will always have an even number of horizontal superblocks. For + // tiles and LRUs to align, tile_width_sb must be even in 4:2:2 + // video. + + // This is only relevant when doing loop restoration RDO inline + // with block/superblock encoding, that is, where tiles are + // relevant. If (when) we introduce optionally delaying loop-filter + // encode to after the partitioning loop, we won't need to make + // any 4:2:2 adjustment. + + let tile_width_sb = if is_422_p { + (tile_width_sb_pre + 1) >> 1 << 1 + } else { + tile_width_sb_pre + }; + + let cols = frame_width_sb.div_ceil(tile_width_sb); + + // Adjust tile_cols_log2 in case of rounding tile_width_sb to even. + let tile_cols_log2 = Self::tile_log2(1, cols).unwrap(); + assert!(tile_cols_log2 >= min_tile_cols_log2); + + let min_tile_rows_log2 = min_tiles_log2.saturating_sub(tile_cols_log2); + let min_tile_rows_ratelimit_log2 = min_tiles_ratelimit_log2.saturating_sub(tile_cols_log2); + let tile_rows_log2 = tile_rows_log2 + .max(min_tile_rows_log2) + .clamp(min_tile_rows_ratelimit_log2, max_tile_rows_log2); + let tile_height_sb = sb_rows.align_power_of_two_and_shift(tile_rows_log2); + + let rows = frame_height_sb.div_ceil(tile_height_sb); + + Self { + frame_width, + frame_height, + tile_width_sb, + tile_height_sb, + cols, + rows, + } + } + + /// Return the smallest value for `k` such that `blkSize << k` is greater + /// than or equal to `target`. + /// + /// + pub fn tile_log2(blk_size: usize, target: usize) -> Option { + let mut k = 0; + while (blk_size.checked_shl(k)?) < target { + k += 1; + } + Some(k as usize) + } + + /// Split frame-level structures into tiles + /// + /// Provide mutable tiled views of frame-level structures. + pub fn tile_iter_mut<'a, T: Pixel>( + &self, + fs: &'a mut FrameState, + ) -> TileContextIterMut<'a, T> { + let afs = fs as *mut _; + let frame_me_stats = fs.frame_me_stats.write().expect("poisoned lock"); + TileContextIterMut { + ti: *self, + fs: afs, + next: 0, + frame_me_stats, + } + } +} + +/// Iterator over tiled views +pub struct TileContextIterMut<'a, T: Pixel> { + ti: TilingInfo, + fs: *mut FrameState, + frame_me_stats: WriteGuardMEStats<'a>, + next: usize, +} + +impl<'a, T: Pixel> Iterator for TileContextIterMut<'a, T> { + type Item = TileContextMut<'a, T>; + + fn next(&mut self) -> Option { + if self.next < self.ti.rows * self.ti.cols { + let tile_col = self.next % self.ti.cols; + let tile_row = self.next / self.ti.cols; + let ctx = TileContextMut { + ts: { + // SAFETY: Multiple tiles mutably access this struct. + // The dimensions must be configured correctly to ensure + // the tiles do not overlap. + let fs = unsafe { &mut *self.fs }; + // SAFETY: ditto + let frame_me_stats = unsafe { + let len = self.frame_me_stats.len(); + let ptr = self.frame_me_stats.as_mut_ptr(); + std::slice::from_raw_parts_mut(ptr, len) + }; + let sbo = PlaneSuperBlockOffset(SuperBlockOffset { + x: tile_col * self.ti.tile_width_sb, + y: tile_row * self.ti.tile_height_sb, + }); + let x = sbo.0.x << SB_SIZE_LOG2; + let y = sbo.0.y << SB_SIZE_LOG2; + let tile_width = self.ti.tile_width_sb << SB_SIZE_LOG2; + let tile_height = self.ti.tile_height_sb << SB_SIZE_LOG2; + let width = tile_width.min(self.ti.frame_width - x); + let height = tile_height.min(self.ti.frame_height - y); + TileStateMut::new(fs, sbo, width, height, frame_me_stats) + }, + }; + self.next += 1; + Some(ctx) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.ti.cols * self.ti.rows - self.next; + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for TileContextIterMut<'_, T> { +} +impl FusedIterator for TileContextIterMut<'_, T> { +} + +/// Container for all tiled views +pub struct TileContextMut<'a, T: Pixel> { + pub ts: TileStateMut<'a, T>, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +use std::io::Read; + +use num_rational::Rational32; +use v_frame::{ + frame::Frame, + pixel::{ChromaSampling, Pixel}, +}; + +#[cfg(feature = "ffmpeg")] +use crate::ffmpeg::FfmpegDecoder; +#[cfg(feature = "vapoursynth")] +use crate::vapoursynth::VapoursynthDecoder; + +pub enum Decoder { + Y4m(y4m::Decoder), + #[cfg(feature = "vapoursynth")] + Vapoursynth(VapoursynthDecoder), + #[cfg(feature = "ffmpeg")] + Ffmpeg(FfmpegDecoder), +} + +impl Decoder { + /// # Errors + /// + /// - If using a Vapoursynth script that contains an unsupported video + /// format. + #[inline] + pub fn get_video_details(&self) -> anyhow::Result { + match self { + Decoder::Y4m(dec) => Ok(crate::y4m::get_video_details(dec)), + #[cfg(feature = "vapoursynth")] + Decoder::Vapoursynth(dec) => dec.get_video_details(), + #[cfg(feature = "ffmpeg")] + Decoder::Ffmpeg(dec) => Ok(dec.video_details), + } + } + + /// # Errors + /// + /// - If a frame cannot be read. + #[inline] + pub fn read_video_frame( + &mut self, + video_details: &VideoDetails, + ) -> anyhow::Result> { + match self { + Decoder::Y4m(dec) => crate::y4m::read_video_frame::(dec, video_details), + #[cfg(feature = "vapoursynth")] + Decoder::Vapoursynth(dec) => dec.read_video_frame::(video_details), + #[cfg(feature = "ffmpeg")] + Decoder::Ffmpeg(dec) => dec.read_video_frame::(), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct VideoDetails { + pub width: usize, + pub height: usize, + pub bit_depth: usize, + pub chroma_sampling: ChromaSampling, + pub time_base: Rational32, +} + +impl Default for VideoDetails { + #[inline] + fn default() -> Self { + VideoDetails { + width: 640, + height: 480, + bit_depth: 8, + chroma_sampling: ChromaSampling::Cs420, + time_base: Rational32::new(1, 30), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/ffmpeg.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/ffmpeg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/ffmpeg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/ffmpeg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,194 @@ +extern crate ffmpeg_the_third as ffmpeg; + +use std::path::Path; + +use anyhow::bail; +use ffmpeg::{ + codec::{decoder, packet}, + format, + format::context, + frame, + media::Type, +}; +use ffmpeg_the_third::threading; +use num_rational::Rational32; +use v_frame::{ + frame::Frame, + pixel::{ChromaSampling, Pixel}, +}; + +use crate::decoder::VideoDetails; + +/// An interface that is used for decoding a video stream using ffmpeg +/// +/// There have been desync issue reported with this decoder +/// on some video files. Use at your own risk! +pub struct FfmpegDecoder { + input_ctx: context::Input, + decoder: decoder::Video, + pub video_details: VideoDetails, + frameno: usize, + stream_index: usize, + end_of_stream: bool, + eof_sent: bool, +} + +impl FfmpegDecoder { + /// Initialize a new ffmpeg decoder for a given input file + /// + /// # Errors + /// + /// - If ffmpeg is not available or not working on the system + /// - If the source contains no video + /// - If the source has an unsupported pixel format + #[inline] + pub fn new>(input: P) -> anyhow::Result { + ffmpeg::init()?; + + let input_ctx = format::input(&input)?; + let input = input_ctx + .streams() + .best(Type::Video) + .ok_or_else(|| anyhow::anyhow!("Could not find video stream"))?; + let stream_index = input.index(); + let mut context = ffmpeg::codec::context::Context::from_parameters(input.parameters())?; + context.set_threading(threading::Config::kind(threading::Type::Frame)); + let mut decoder = context.decoder().video()?; + decoder.set_parameters(input.parameters())?; + + let frame_rate = input.avg_frame_rate(); + Ok(Self { + video_details: VideoDetails { + width: decoder.width() as usize, + height: decoder.height() as usize, + bit_depth: match decoder.format() { + format::pixel::Pixel::YUV420P + | format::pixel::Pixel::YUV422P + | format::pixel::Pixel::YUV444P + | format::pixel::Pixel::YUVJ420P + | format::pixel::Pixel::YUVJ422P + | format::pixel::Pixel::YUVJ444P => 8, + format::pixel::Pixel::YUV420P10LE + | format::pixel::Pixel::YUV422P10LE + | format::pixel::Pixel::YUV444P10LE => 10, + format::pixel::Pixel::YUV420P12LE + | format::pixel::Pixel::YUV422P12LE + | format::pixel::Pixel::YUV444P12LE => 12, + _ => { + bail!("Unsupported pixel format {:?}", decoder.format()); + } + }, + chroma_sampling: match decoder.format() { + format::pixel::Pixel::YUV420P + | format::pixel::Pixel::YUVJ420P + | format::pixel::Pixel::YUV420P10LE + | format::pixel::Pixel::YUV420P12LE => ChromaSampling::Cs420, + format::pixel::Pixel::YUV422P + | format::pixel::Pixel::YUVJ422P + | format::pixel::Pixel::YUV422P10LE + | format::pixel::Pixel::YUV422P12LE => ChromaSampling::Cs422, + format::pixel::Pixel::YUV444P + | format::pixel::Pixel::YUVJ444P + | format::pixel::Pixel::YUV444P10LE + | format::pixel::Pixel::YUV444P12LE => ChromaSampling::Cs444, + _ => { + bail!("Unsupported pixel format {:?}", decoder.format()); + } + }, + time_base: Rational32::new(frame_rate.denominator(), frame_rate.numerator()), + }, + decoder, + input_ctx, + frameno: 0, + stream_index, + end_of_stream: false, + eof_sent: false, + }) + } + + fn decode_frame(&self, decoded: &frame::Video) -> Frame { + const SB_SIZE_LOG2: usize = 6; + const SB_SIZE: usize = 1 << SB_SIZE_LOG2; + const SUBPEL_FILTER_SIZE: usize = 8; + const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE; + const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN; + + let mut f: Frame = Frame::new_with_padding( + self.video_details.width, + self.video_details.height, + self.video_details.chroma_sampling, + LUMA_PADDING, + ); + let width = self.video_details.width; + let height = self.video_details.height; + let bit_depth = self.video_details.bit_depth; + let bytes = if bit_depth > 8 { 2 } else { 1 }; + let (chroma_width, _) = self + .video_details + .chroma_sampling + .get_chroma_dimensions(width, height); + f.planes[0].copy_from_raw_u8(decoded.data(0), width * bytes, bytes); + f.planes[1].copy_from_raw_u8(decoded.data(1), chroma_width * bytes, bytes); + f.planes[2].copy_from_raw_u8(decoded.data(2), chroma_width * bytes, bytes); + f + } + + /// # Errors + /// + /// - If there are no frames remaining + #[inline] + pub fn read_video_frame(&mut self) -> anyhow::Result> { + // For some reason there's a crap ton of work needed to get ffmpeg to do + // something simple, because each codec has it's own stupid way of doing + // things and they don't all decode the same way. + // + // Maybe ffmpeg could have made a simple, singular interface that does this for + // us, but noooooo. + // + // Reference: https://ffmpeg.org/doxygen/trunk/api-h264-test_8c_source.html#l00110 + loop { + // This iterator is actually really stupid... it doesn't reset itself after each + // `new`. But that solves our lifetime hell issues, ironically. + let packet = self + .input_ctx + .packets() + .next() + .and_then(Result::ok) + .map(|(_, packet)| packet); + + let mut packet = if let Some(packet) = packet { + packet + } else { + self.end_of_stream = true; + packet::Packet::empty() + }; + + if self.end_of_stream && !self.eof_sent { + let _ = self.decoder.send_eof(); + self.eof_sent = true; + } + + if self.end_of_stream || packet.stream() == self.stream_index { + let mut decoded = frame::Video::new( + self.decoder.format(), + self.video_details.width as u32, + self.video_details.height as u32, + ); + packet.set_pts(Some(self.frameno as i64)); + packet.set_dts(Some(self.frameno as i64)); + + if !self.end_of_stream { + let _ = self.decoder.send_packet(&packet); + } + + if self.decoder.receive_frame(&mut decoded).is_ok() { + let f = self.decode_frame(&decoded); + self.frameno += 1; + return Ok(f); + } else if self.end_of_stream { + bail!("No frames left"); + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,216 @@ +// Documentation lints +// FIXME: add docs and turn this to warn +#![allow(missing_docs)] +#![warn(clippy::doc_link_with_quotes)] +#![warn(clippy::doc_markdown)] +#![warn(clippy::missing_errors_doc)] +#![warn(clippy::missing_panics_doc)] + +pub mod decoder; + +mod analyze; +#[macro_use] +mod cpu; +mod data; +#[cfg(feature = "ffmpeg")] +pub mod ffmpeg; +#[cfg(feature = "vapoursynth")] +pub mod vapoursynth; +mod y4m; + +use std::{ + collections::{BTreeMap, BTreeSet}, + io::Read, + sync::Arc, + time::Instant, +}; + +pub use ::y4m::Decoder as Y4mDecoder; +use decoder::Decoder; +pub use num_rational::Rational32; +use v_frame::pixel::Pixel; + +pub use crate::{analyze::SceneChangeDetector, cpu::CpuFeatureLevel}; + +/// Options determining how to run scene change detection. +#[derive(Debug, Clone, Copy)] +pub struct DetectionOptions { + /// The speed of detection algorithm to use. + /// Slower algorithms are more accurate/better for use in encoders. + pub analysis_speed: SceneDetectionSpeed, + /// Enabling this will utilize heuristics to avoid scenecuts + /// that are too close to each other. + /// This is generally useful if you want scenecut detection + /// for use in an encoder. + /// If you want a raw list of scene changes, you should disable this. + pub detect_flashes: bool, + /// The minimum distance between two scene changes. + pub min_scenecut_distance: Option, + /// The maximum distance between two scene changes. + pub max_scenecut_distance: Option, + /// The distance to look ahead in the video + /// for scene flash detection. + /// + /// Not used if `detect_flashes` is `false`. + pub lookahead_distance: usize, +} + +impl Default for DetectionOptions { + #[inline] + fn default() -> Self { + DetectionOptions { + analysis_speed: SceneDetectionSpeed::Standard, + detect_flashes: true, + lookahead_distance: 5, + min_scenecut_distance: None, + max_scenecut_distance: None, + } + } +} + +/// Results from a scene change detection pass. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize))] +pub struct DetectionResults { + /// The 0-indexed frame numbers where scene changes were detected. + pub scene_changes: Vec, + /// The total number of frames read. + pub frame_count: usize, + /// Average speed (FPS) + pub speed: f64, +} + +/// # Errors +/// +/// - If using a Vapoursynth script that contains an unsupported video format. +#[inline] +pub fn new_detector( + dec: &mut Decoder, + opts: DetectionOptions, +) -> anyhow::Result> { + let video_details = dec.get_video_details()?; + + Ok(SceneChangeDetector::new( + (video_details.width, video_details.height), + video_details.bit_depth, + video_details.time_base.recip(), + video_details.chroma_sampling, + if opts.detect_flashes { + opts.lookahead_distance + } else { + 1 + }, + opts.analysis_speed, + opts.min_scenecut_distance.map_or(0, |val| val), + opts.max_scenecut_distance + .map_or_else(|| u32::MAX as usize, |val| val), + CpuFeatureLevel::default(), + )) +} + +/// Runs through a y4m video clip, +/// detecting where scene changes occur. +/// This is adjustable based on the `opts` parameters. +/// +/// This is the preferred, simplified interface +/// for analyzing a whole clip for scene changes. +/// +/// # Arguments +/// +/// - `progress_callback`: An optional callback that will fire after each frame +/// is analyzed. Arguments passed in will be, in order, the number of frames +/// analyzed, and the number of keyframes detected. This is generally useful +/// for displaying progress, etc. +/// +/// # Errors +/// +/// - If using a Vapoursynth script that contains an unsupported video format. +/// +/// # Panics +/// +/// - If `opts.lookahead_distance` is 0. +#[inline] +pub fn detect_scene_changes( + dec: &mut Decoder, + opts: DetectionOptions, + frame_limit: Option, + progress_callback: Option<&dyn Fn(usize, usize)>, +) -> anyhow::Result { + assert!(opts.lookahead_distance >= 1); + + let mut detector = new_detector::(dec, opts)?; + let video_details = dec.get_video_details()?; + let mut frame_queue = BTreeMap::new(); + let mut keyframes = BTreeSet::new(); + keyframes.insert(0); + + let start_time = Instant::now(); + let mut frameno = 0; + loop { + let mut next_input_frameno = frame_queue.keys().last().copied().map_or(0, |key| key + 1); + while next_input_frameno + < (frameno + opts.lookahead_distance + 1).min(frame_limit.unwrap_or(usize::MAX)) + { + let frame = dec.read_video_frame(&video_details); + if let Ok(frame) = frame { + frame_queue.insert(next_input_frameno, Arc::new(frame)); + next_input_frameno += 1; + } else { + // End of input + break; + } + } + + // The frame_queue should start at whatever the previous frame was + let frame_set = frame_queue + .values() + .take(opts.lookahead_distance + 2) + .collect::>(); + if frame_set.len() < 2 { + // End of video + break; + } + if frameno == 0 + || detector.analyze_next_frame( + &frame_set, + frameno, + *keyframes + .iter() + .last() + .expect("at least 1 keyframe should exist"), + ) + { + keyframes.insert(frameno); + }; + + if frameno > 0 { + frame_queue.remove(&(frameno - 1)); + } + + frameno += 1; + if let Some(progress_fn) = progress_callback { + progress_fn(frameno, keyframes.len()); + } + if let Some(frame_limit) = frame_limit { + if frameno == frame_limit { + break; + } + } + } + Ok(DetectionResults { + scene_changes: keyframes.into_iter().collect(), + frame_count: frameno, + speed: frameno as f64 / start_time.elapsed().as_secs_f64(), + }) +} + +#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Eq)] +pub enum SceneDetectionSpeed { + /// Fastest scene detection using pixel-wise comparison + Fast, + /// Scene detection using frame costs and motion vectors + Standard, + /// Do not perform scenecut detection, only place keyframes at fixed + /// intervals + None, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/main.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/main.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/main.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,135 @@ +use std::{ + fs::File, + io::{self, BufReader, Read, Write}, +}; + +use anyhow::Result; +use av_scenechange::{ + decoder::Decoder, + detect_scene_changes, + DetectionOptions, + SceneDetectionSpeed, +}; +use clap::Parser; + +#[derive(Parser, Debug)] +struct Args { + /// Sets the input file to use + #[clap(value_parser)] + pub input: String, + + /// Optional file to write results to + #[clap(long, short, value_parser)] + pub output: Option, + + /// Speed level for scene-change detection, 0: best quality, 1: fastest mode + #[clap(long, short, value_parser, default_value_t = 0)] + pub speed: u8, + + /// Do not detect short scene flashes and exclude them as scene cuts + #[clap(long)] + pub no_flash_detection: bool, + + /// Sets a minimum interval between two consecutive scenecuts + #[clap(long, value_parser)] + pub min_scenecut: Option, + + /// Sets a maximum interval between two consecutive scenecuts, + /// after which a scenecut will be forced + #[clap(long, value_parser)] + pub max_scenecut: Option, +} + +fn main() -> Result<()> { + init_logger(); + + #[cfg(feature = "tracing")] + let (chrome_layer, _guard) = tracing_chrome::ChromeLayerBuilder::new().build(); + + #[cfg(feature = "tracing")] + { + use tracing_subscriber::layer::SubscriberExt; + tracing::subscriber::set_global_default(tracing_subscriber::registry().with(chrome_layer)) + .expect("Could not initialize tracing subscriber"); + } + + let matches = Args::parse(); + let input = match matches.input.as_str() { + "-" => Box::new(io::stdin()) as Box, + f => Box::new(File::open(f)?) as Box, + }; + let mut reader = BufReader::new(input); + + let mut opts = DetectionOptions { + detect_flashes: !matches.no_flash_detection, + min_scenecut_distance: matches.min_scenecut, + max_scenecut_distance: matches.max_scenecut, + ..DetectionOptions::default() + }; + + opts.analysis_speed = match matches.speed { + 0 => SceneDetectionSpeed::Standard, + 1 => SceneDetectionSpeed::Fast, + _ => panic!("Speed mode must be in range [0; 1]"), + }; + + let mut dec = Decoder::Y4m(y4m::Decoder::new(&mut reader)?); + let bit_depth = dec.get_video_details()?.bit_depth; + let results = if bit_depth == 8 { + detect_scene_changes::<_, u8>(&mut dec, opts, None, None)? + } else { + detect_scene_changes::<_, u16>(&mut dec, opts, None, None)? + }; + print!("{}", serde_json::to_string(&results)?); + + if let Some(output_file) = matches.output { + let mut file = File::create(output_file)?; + + let output = serde_json::to_string_pretty(&results)?; + file.write_all(&output.into_bytes())?; + } + + Ok(()) +} + +#[cfg(not(feature = "devel"))] +const fn init_logger() { + // Do nothing +} + +#[cfg(feature = "devel")] +fn init_logger() { + use std::str::FromStr; + fn level_colored(l: log::Level) -> console::StyledObject<&'static str> { + use console::style; + use log::Level; + match l { + Level::Trace => style("??").dim(), + Level::Debug => style("? ").dim(), + Level::Info => style("> ").green(), + Level::Warn => style("! ").yellow(), + Level::Error => style("!!").red(), + } + } + + let level = std::env::var("LOG") + .ok() + .and_then(|l| log::LevelFilter::from_str(&l).ok()) + .unwrap_or(log::LevelFilter::Warn); + + fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "{level} {message}", + level = level_colored(record.level()), + message = message, + )); + }) + // set the default log level. to filter out verbose log messages from dependencies, set + // this to Warn and overwrite the log level for your crate. + .level(level) + // output to stdout + .chain(std::io::stderr()) + .apply() + .unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/vapoursynth.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/vapoursynth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/vapoursynth.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/vapoursynth.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,200 @@ +use std::{mem::size_of, path::Path, slice}; + +use anyhow::{bail, ensure}; +use num_rational::Rational32; +use v_frame::{ + frame::Frame, + pixel::{ChromaSampling, Pixel}, +}; +use vapoursynth::{ + video_info::{Property, VideoInfo}, + vsscript::{Environment, EvalFlags}, +}; + +use crate::decoder::VideoDetails; + +const OUTPUT_INDEX: i32 = 0; + +pub struct VapoursynthDecoder { + env: Environment, + frames_read: usize, + total_frames: usize, +} + +impl VapoursynthDecoder { + /// # Errors + /// + /// - If sourcing an invalid Vapoursynth script. + /// - If using a Vapoursynth script that contains an unsupported video + /// format. + #[inline] + pub fn new(source: &Path) -> anyhow::Result { + let env = Environment::from_file(source, EvalFlags::SetWorkingDir)?; + let total_frames = { + let (node, _) = env.get_output(OUTPUT_INDEX)?; + get_num_frames(node.info())? + }; + Ok(Self { + env, + frames_read: 0, + total_frames, + }) + } + + /// # Errors + /// + /// - If sourcing an invalid Vapoursynth script. + /// - If using a Vapoursynth script that contains an unsupported video + /// format. + #[inline] + pub fn get_video_details(&self) -> anyhow::Result { + let (node, _) = self.env.get_output(OUTPUT_INDEX)?; + let info = node.info(); + let (width, height) = get_resolution(info)?; + Ok(VideoDetails { + width, + height, + bit_depth: get_bit_depth(info)?, + chroma_sampling: get_chroma_sampling(info)?, + time_base: get_time_base(info)?, + }) + } + + /// # Errors + /// + /// - If sourcing an invalid Vapoursynth script. + /// - If using a Vapoursynth script that contains an unsupported video + /// format. + /// - If a frame cannot be read. + #[allow(clippy::transmute_ptr_to_ptr)] + #[inline] + pub fn read_video_frame(&mut self, cfg: &VideoDetails) -> anyhow::Result> { + const SB_SIZE_LOG2: usize = 6; + const SB_SIZE: usize = 1 << SB_SIZE_LOG2; + const SUBPEL_FILTER_SIZE: usize = 8; + const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE; + const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN; + + if self.frames_read >= self.total_frames { + bail!("No frames left"); + } + + let (node, _) = self.env.get_output(OUTPUT_INDEX)?; + let vs_frame = node.get_frame(self.frames_read)?; + self.frames_read += 1; + + let bytes = size_of::(); + let mut f: Frame = + Frame::new_with_padding(cfg.width, cfg.height, cfg.chroma_sampling, LUMA_PADDING); + + // SAFETY: We are using the stride to compute the length of the data slice + unsafe { + f.planes[0].copy_from_raw_u8( + slice::from_raw_parts( + vs_frame.data_ptr(0), + vs_frame.stride(0) * vs_frame.height(0), + ), + vs_frame.stride(0), + bytes, + ); + f.planes[1].copy_from_raw_u8( + slice::from_raw_parts( + vs_frame.data_ptr(1), + vs_frame.stride(1) * vs_frame.height(1), + ), + vs_frame.stride(1), + bytes, + ); + f.planes[2].copy_from_raw_u8( + slice::from_raw_parts( + vs_frame.data_ptr(2), + vs_frame.stride(2) * vs_frame.height(2), + ), + vs_frame.stride(2), + bytes, + ); + } + Ok(f) + } +} + +/// Get the number of frames from a Vapoursynth `VideoInfo` struct. +fn get_num_frames(info: VideoInfo) -> anyhow::Result { + let num_frames = { + if Property::Variable == info.format { + bail!("Cannot output clips with varying format"); + } + if Property::Variable == info.resolution { + bail!("Cannot output clips with varying dimensions"); + } + if Property::Variable == info.framerate { + bail!("Cannot output clips with varying framerate"); + } + + info.num_frames + }; + + ensure!(num_frames != 0, "vapoursynth reported 0 frames"); + + Ok(num_frames) +} + +/// Get the bit depth from a Vapoursynth `VideoInfo` struct. +fn get_bit_depth(info: VideoInfo) -> anyhow::Result { + let bits_per_sample = { + match info.format { + Property::Variable => { + bail!("Cannot output clips with variable format"); + } + Property::Constant(x) => x.bits_per_sample(), + } + }; + + Ok(bits_per_sample as usize) +} + +/// Get the resolution from a Vapoursynth `VideoInfo` struct. +fn get_resolution(info: VideoInfo) -> anyhow::Result<(usize, usize)> { + let resolution = { + match info.resolution { + Property::Variable => { + bail!("Cannot output clips with variable resolution"); + } + Property::Constant(x) => x, + } + }; + + Ok((resolution.width, resolution.height)) +} + +/// Get the time base (inverse of frame rate) from a Vapoursynth `VideoInfo` +/// struct. +fn get_time_base(info: VideoInfo) -> anyhow::Result { + match info.framerate { + Property::Variable => bail!("Cannot output clips with varying framerate"), + Property::Constant(fps) => Ok(Rational32::new( + fps.denominator as i32, + fps.numerator as i32, + )), + } +} + +/// Get the chroma sampling from a Vapoursynth `VideoInfo` struct. +fn get_chroma_sampling(info: VideoInfo) -> anyhow::Result { + match info.format { + Property::Variable => bail!("Variable pixel format not supported"), + Property::Constant(x) => match x.color_family() { + vapoursynth::format::ColorFamily::YUV => { + let ss = (x.sub_sampling_w(), x.sub_sampling_h()); + match ss { + (1, 1) => Ok(ChromaSampling::Cs420), + (1, 0) => Ok(ChromaSampling::Cs422), + (0, 0) => Ok(ChromaSampling::Cs444), + _ => bail!("Unrecognized chroma subsampling"), + } + } + vapoursynth::format::ColorFamily::Gray => Ok(ChromaSampling::Cs400), + _ => bail!("Currently only YUV input is supported"), + }, + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/y4m.rs clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/y4m.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av-scenechange/src/y4m.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av-scenechange/src/y4m.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +use std::io::Read; + +use num_rational::Rational32; +use v_frame::{ + frame::Frame, + pixel::{ChromaSampling, Pixel}, +}; + +use crate::decoder::VideoDetails; + +pub fn get_video_details(dec: &y4m::Decoder) -> VideoDetails { + let width = dec.get_width(); + let height = dec.get_height(); + let color_space = dec.get_colorspace(); + let bit_depth = color_space.get_bit_depth(); + let chroma_sampling = map_y4m_color_space(color_space); + let framerate = dec.get_framerate(); + let time_base = Rational32::new(framerate.den as i32, framerate.num as i32); + + VideoDetails { + width, + height, + bit_depth, + chroma_sampling, + time_base, + } +} + +const fn map_y4m_color_space(color_space: y4m::Colorspace) -> ChromaSampling { + use y4m::Colorspace::{ + C420jpeg, + C420mpeg2, + C420p10, + C420p12, + C420paldv, + C422p10, + C422p12, + C444p10, + C444p12, + Cmono, + Cmono12, + C420, + C422, + C444, + }; + use ChromaSampling::{Cs400, Cs420, Cs422, Cs444}; + match color_space { + Cmono | Cmono12 => Cs400, + C420jpeg | C420paldv => Cs420, + C420mpeg2 => Cs420, + C420 | C420p10 | C420p12 => Cs420, + C422 | C422p10 | C422p12 => Cs422, + C444 | C444p10 | C444p12 => Cs444, + _ => unimplemented!(), + } +} + +pub fn read_video_frame( + dec: &mut y4m::Decoder, + cfg: &VideoDetails, +) -> anyhow::Result> { + const SB_SIZE_LOG2: usize = 6; + const SB_SIZE: usize = 1 << SB_SIZE_LOG2; + const SUBPEL_FILTER_SIZE: usize = 8; + const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE; + const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN; + + let bytes = dec.get_bytes_per_sample(); + dec.read_frame() + .map(|frame| { + let mut f: Frame = + Frame::new_with_padding(cfg.width, cfg.height, cfg.chroma_sampling, LUMA_PADDING); + + let (chroma_width, _) = cfg + .chroma_sampling + .get_chroma_dimensions(cfg.width, cfg.height); + + f.planes[0].copy_from_raw_u8(frame.get_y_plane(), cfg.width * bytes, bytes); + f.planes[1].copy_from_raw_u8(frame.get_u_plane(), chroma_width * bytes, bytes); + f.planes[2].copy_from_raw_u8(frame.get_v_plane(), chroma_width * bytes, bytes); + f + }) + .map_err(|e| e.into()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"0dd57e61abc29ca7e03c694a23b61d2d36c03b63cc2c47533ea94bd5cfc8db08",".github/workflows/av1-grain-compact.yml":"852ca2909b16677a8aa7e12c3d6f0df95978ff8cba1beeb3e98595476f8b095b",".github/workflows/av1-grain-macos.yml":"6aebeccfc90150ed6cf32447a77c3652822111d4731643895b744a194e0f7b2e",".github/workflows/av1-grain-ubuntu.yml":"95238751495ab062b786af9c61d9cb1d13e32666a5397918d924d54e9dabefd3",".github/workflows/av1-grain-windows.yml":"9bd9d4540d7b0fa94974955812aca5a3f2e12f1f5629b18b18bf4296c0ee7684",".github/workflows/dependabot.yml":"9d2c6a298f45fc16d85fee33d60c349d55efee5a1fff8dda3b8733cce6f6bb2a","CHANGELOG.md":"654123144c912afacf2ac11964b99f7e60291ead867679650cf5ea97cfc9fa89","Cargo.lock":"f00776c122f50abc739259e5cb6ec28bc51c95c6f5a345244ab689b965c84b36","Cargo.toml":"8be55ff324ad76d2cbb2468d8106ad12d16d28a0fd590a6f33921acc226475f9","Cargo.toml.orig":"0fcba2e8fe066da1a90613094b2885decc11c2b00da94d8fd4830b9672ac65f5","LICENSE":"acc9e236b0011c638714a16f5634fa5bcd3be111182e237c3049db700c3521e2","README.md":"50eb5d2b97462b9ccac9a12472c6bb2e312c6587125668511fca0d7c8c89f14c","rustfmt.toml":"17a87f7e0a78a8ef0c7d2e70cd276bee9ced3e7b633cea40296c72a0618ea431","src/create.rs":"72bdd25ea1197a7aeca71ca1b1b3be69eb0d81acb3ab26a96a6ea1ecb3c83957","src/diff.rs":"7ae8114c61147be4dfd563d8e19892ee0ef0b4e722e0fcb3ef9c8a502fe87520","src/diff/ffmpeg.rs":"0ce324b0de9a284d51a31b207f5a2fb580ef66104badd97cb41f4dbb387287bf","src/diff/solver.rs":"2217acce0a4282e85d4ca54e2505fe4b394e9fbd79230870b58062edd5051018","src/diff/solver/util.rs":"3557e37ed1b4d050a8c61dd0640622fc51a54bcafd5baf6fe86cda84348530e8","src/diff/vapoursynth.rs":"ae4df187a3b81acafe207f61d5f9aa51ae92dd74a22d1ec6e55f29a2e22c752a","src/estimate.rs":"501f5c1775fc7bc329ae11d3c3a7e6dccee733990cb90e424457be4b82808ac6","src/lib.rs":"51f1a75abfb7c749c21a2e5761bdb8c256d6f0442034a12bc741668bfcf9b87c","src/parse.rs":"163d1ff719e8a0a93de699d809be920c141263cdf60e5e7d804f7ebb1b721be8","src/util.rs":"a756baba43f6e61494bf90aa140ea90a6d4c265bce089429139d66a772604a01"},"package":"8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4cff686adc70186b59f3d035079cca93c191d88c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-compact.yml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-compact.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-compact.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-compact.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +name: av1-grain-compact + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build-test: + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + + - name: Run rustfmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check --verbose + + - name: Run cargo clippy + uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-targets --tests --benches -- -D warnings + + - name: Build + run: cargo build --verbose --tests --benches + + - name: Run tests + run: cargo test --verbose + + - name: Generate docs + run: cargo doc --no-deps diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-macos.yml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-macos.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-macos.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-macos.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +#FIXME +# - valgrind cannot be installed on macos, only on linux +# - rust-code-analysis is not tested on macos, so no static analysis + +name: av1-grain-macos + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build-test: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + + - name: Run rustfmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check --verbose + + - name: Run cargo clippy + uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-targets --tests --benches -- -D warnings + + - name: Build + run: cargo build --verbose --tests --benches + + - name: Run tests + run: cargo test --verbose + + - name: Generate docs + run: cargo doc --no-deps diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-ubuntu.yml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-ubuntu.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-ubuntu.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-ubuntu.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,185 @@ +name: av1-grain-ubuntu + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + + - name: Run rustfmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check --verbose + + - name: Run cargo clippy + uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-targets --tests --benches -- -D warnings + + - name: Build + run: cargo build --verbose --tests --benches + + - name: Run tests + run: cargo test --verbose + + - name: Install cargo-msrv + uses: taiki-e/install-action@v2 + with: + tool: cargo-msrv + + - name: Validate minimum Rust version + run: | + cargo msrv verify + + - name: Generate docs + run: cargo doc --no-deps + + code-coverage: + needs: [build-test] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@v2 + with: + tool: cargo-llvm-cov + + - name: Generate code coverage + run: cargo llvm-cov --lcov --output-path lcov.log + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.log + fail_ci_if_error: true + + memory-and-threads-dynamic-analysis: + needs: [build-test] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Install valgrind + run: | + sudo apt-get install valgrind + + # FIXME Use binaries + - name: Install cargo-valgrind + run: | + cargo install cargo-valgrind + + # Usage of the `help` command as base command, please replace it + # with the effective command that valgrind has to analyze + - name: Run cargo-valgrind + run: | + cargo valgrind run -- --help + + undefined-behaviour-fuzzy-dynamic-analysis: + needs: [build-test] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Cache produced data + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-ci-${{ hashFiles('**/Cargo.toml') }} + + - name: Install Rust nightly and miri + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: miri + override: true + + # FIXME Use binaries + - name: Install cargo-fuzz + run: | + cargo install cargo-fuzz --force + + - name: Run miri + env: + # -Zrandomize-layout makes sure not to rely on the layout of anything + # that might change + RUSTFLAGS: -Zrandomize-layout + # -Zmiri-strict-provenance enables strict provenance checking in Miri. + # This means that casting an integer to a pointer will stop execution + # because the provenance of the pointer cannot be determined. + # -Zmiri-symbolic-alignment-check makes the alignment check more strict. + MIRIFLAGS: > + -Zmiri-strict-provenance + -Zmiri-symbolic-alignment-check + run: cargo miri test + + # FIXME Create a template with a dummy series of fuzzy tests + - name: Init cargo-fuzz + run: cargo fuzz init + + - name: Run cargo-fuzz + run: cargo fuzz build + + static-code-analysis: + needs: [build-test] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install rust-code-analysis + env: + RCA_LINK: https://github.com/mozilla/rust-code-analysis/releases/download + RCA_VERSION: v0.0.23 + run: | + mkdir -p $HOME/.local/bin + curl -L "$RCA_LINK/$RCA_VERSION/rust-code-analysis-linux-cli-x86_64.tar.gz" | + tar xz -C $HOME/.local/bin + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Run rust-code-analysis + run: | + mkdir $HOME/rca-json + # FIXME: Update rca version to analyze the entire directory of a repo + rust-code-analysis-cli --metrics -O json --pr -o "$HOME/rca-json" -p src/ + + - name: Upload rust-code-analysis json + uses: actions/upload-artifact@v4 + with: + name: rca-json-ubuntu + path: ~/rca-json diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-windows.yml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-windows.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-windows.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/av1-grain-windows.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +# FIXME +# - Code coverage on Windows does not work because there are problems +# with grcov paths +# - valgrind cannot be installed on Windows, only on linux +# - cargo-fuzz and AddressSanitizer are not supported on Windows + +name: av1-grain-windows + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build-test: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + + - name: Run rustfmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check --verbose + + - name: Run cargo clippy + uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-targets --tests --benches -- -D warnings + + - name: Build + run: cargo build --verbose --tests --benches + + - name: Run tests + run: cargo test --verbose + + - name: Generate docs + run: cargo doc --no-deps + + static-code-analysis: + needs: [build-test] + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install rust-code-analysis + env: + RCA_LINK: https://github.com/mozilla/rust-code-analysis/releases/download + RCA_VERSION: v0.0.23 + run: | + mkdir -p $HOME/bin + curl -LO "$Env:RCA_LINK/$env:RCA_VERSION/rust-code-analysis-win-cli-x86_64.zip" + 7z e -y "rust-code-analysis-win-cli-x86_64.zip" -o"$HOME/bin" + echo "$HOME/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Run rust-code-analysis + run: | + mkdir $HOME/rca-json + # FIXME: Update rca version to analyze the entire directory of a repo + rust-code-analysis-cli --metrics -O json --pr -o "$HOME/rca-json" -p src/ + + - name: Upload rust-code-analysis json + uses: actions/upload-artifact@v4 + with: + name: rca-json-windows + path: ~/rca-json diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/.github/workflows/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/.github/workflows/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + commit-message: + prefix: "chore" + include: "scope" + labels: + - "dependencies" + - "rust" + groups: + rust-dependencies: + patterns: + - "*" + update-types: + - "minor" + - "patch" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +# CHANGELOG + + + +## Version 0.2.5 + +- Bump `nom` dependency to 8.0 + +## Version 0.2.4 + +- Fix a compilation issue with `--no-default-features` + +## Version 0.2.3 + +- Many speed optimizations to diff + +## Version 0.2.2 + +- Fix issue where `NoiseModel` may fail in certain circumstances. +- Considerably speed up `NoiseModel` calculations. + +## Version 0.2.1 + +- Bump `v_frame` to 0.3 +- Fix a clippy warning + +## Version 0.2.0 + +- [Breaking] Change the name of `generate_grain_params` to `generate_photon_noise_params`. This was done to support the future `generate_film_grain_params` feature. +- [Feature] Add the `diff` module which contains the `DiffGenerator` struct. This takes in a series of source frames and denoised frames and generates a grain table based on the difference. This feature is enabled by default. + +## Version 0.1.4 + +- Fix a bug that prevented `generate_luma_noise_points` from generating any luma noise points. + - ALL previous versions have been yanked because of the severity of this bug. Please update to this one. + +## Version 0.1.3 + +- Be more consistent in using `anyhow::Result` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,398 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av1-grain" +version = "0.2.5" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "quickcheck", + "quickcheck_macros", + "serde", + "v_frame", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger", + "log", + "rand", +] + +[[package]] +name = "quickcheck_macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f71ee38b42f8459a88d3362be6f9b841ad2d5421844f61eb1c59c11bff3ac14a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,199 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.80.1" +name = "av1-grain" +version = "0.2.5" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Helpers for generating and parsing AV1 film grain data" +homepage = "https://github.com/rust-av/av1-grain" +documentation = "https://docs.rs/av1-grain" +readme = "README.md" +license = "BSD-2-Clause" +repository = "https://github.com/rust-av/av1-grain" + +[features] +create = [] +default = [ + "create", + "parse", + "diff", + "estimate", +] +diff = [ + "num-rational", + "v_frame", +] +estimate = ["v_frame"] +parse = ["nom"] +serialize = [ + "serde", + "arrayvec/serde", +] +unstable = [] + +[lib] +name = "av1_grain" +path = "src/lib.rs" + +[dependencies.anyhow] +version = "1.0.58" + +[dependencies.arrayvec] +version = "0.7.2" + +[dependencies.log] +version = "0.4.17" + +[dependencies.nom] +version = "8.0.0" +optional = true + +[dependencies.num-rational] +version = "0.4.1" +optional = true + +[dependencies.serde] +version = "1.0.140" +features = ["derive"] +optional = true + +[dependencies.v_frame] +version = "0.3.0" +optional = true + +[dev-dependencies.quickcheck] +version = "1.0.3" + +[dev-dependencies.quickcheck_macros] +version = "1.0.0" + +[lints.clippy] +case_sensitive_file_extension_comparisons = "warn" +cfg_not_test = "deny" +checked_conversions = "warn" +clear_with_drain = "warn" +clone_on_ref_ptr = "warn" +cloned_instead_of_copied = "warn" +collection_is_never_read = "warn" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "deny" +enum_glob_use = "warn" +equatable_if_let = "warn" +expl_impl_clone_on_copy = "deny" +filetype_is_file = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +format_collect = "warn" +format_push_string = "warn" +future_not_send = "warn" +if_then_some_else_none = "warn" +ignore_without_reason = "warn" +implicit_clone = "warn" +imprecise_flops = "warn" +inconsistent_struct_constructor = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" +inline_always = "warn" +invalid_upcast_comparisons = "warn" +iter_filter_is_ok = "warn" +iter_filter_is_some = "warn" +iter_on_empty_collections = "warn" +iter_on_single_items = "warn" +iter_with_drain = "warn" +large_futures = "warn" +large_include_file = "warn" +large_stack_arrays = "warn" +large_stack_frames = "warn" +large_types_passed_by_value = "warn" +linkedlist = "deny" +macro_use_imports = "warn" +manual_assert = "warn" +manual_instant_elapsed = "warn" +manual_is_power_of_two = "warn" +manual_is_variant_and = "warn" +manual_let_else = "warn" +manual_midpoint = "warn" +manual_string_new = "warn" +map_unwrap_or = "warn" +map_with_unused_argument_over_ranges = "warn" +match_bool = "warn" +maybe_infinite_iter = "warn" +mem_forget = "warn" +mismatching_type_param_order = "warn" +missing_inline_in_public_items = "warn" +mixed_read_write_in_expression = "warn" +mut_mut = "warn" +mutex_atomic = "warn" +mutex_integer = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_collect = "warn" +needless_continue = "warn" +needless_pass_by_ref_mut = "warn" +needless_pass_by_value = "warn" +non_send_fields_in_send_ty = "deny" +non_std_lazy_statics = "warn" +non_zero_suggestions = "warn" +option_as_ref_cloned = "warn" +option_if_let_else = "warn" +or_fun_call = "warn" +path_buf_push_overwrite = "warn" +pathbuf_init_then_push = "warn" +precedence_bits = "warn" +range_minus_one = "warn" +range_plus_one = "warn" +rc_buffer = "warn" +rc_mutex = "warn" +read_zero_byte_vec = "warn" +redundant_clone = "warn" +redundant_test_prefix = "warn" +ref_option = "warn" +ref_option_ref = "warn" +semicolon_if_nothing_returned = "warn" +set_contains_or_insert = "warn" +significant_drop_in_scrutinee = "deny" +stable_sort_primitive = "warn" +str_split_at_newline = "warn" +string_lit_chars_any = "warn" +string_slice = "warn" +suboptimal_flops = "warn" +suspicious_operation_groupings = "warn" +suspicious_xor_used_as_pow = "warn" +tests_outside_test_module = "warn" +transmute_ptr_to_ptr = "warn" +transmute_undefined_repr = "warn" +trivial_regex = "warn" +trivially_copy_pass_by_ref = "warn" +undocumented_unsafe_blocks = "warn" +uninlined_format_args = "allow" +unnecessary_box_returns = "warn" +unnecessary_debug_formatting = "warn" +unnecessary_join = "warn" +unused_async = "warn" +unused_peekable = "warn" +unused_rounding = "warn" +unwrap_used = "warn" +verbose_bit_mask = "warn" +verbose_file_reads = "warn" +zero_sized_map_values = "warn" + +[profile.release] +lto = "thin" +codegen-units = 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,156 @@ +[package] +name = "av1-grain" +version = "0.2.5" +edition = "2021" +rust-version = "1.80.1" +license = "BSD-2-Clause" +description = "Helpers for generating and parsing AV1 film grain data" +readme = "README.md" +repository = "https://github.com/rust-av/av1-grain" +homepage = "https://github.com/rust-av/av1-grain" +documentation = "https://docs.rs/av1-grain" + +[dependencies] +anyhow = "1.0.58" +arrayvec = "0.7.2" +log = "0.4.17" +nom = { version = "8.0.0", optional = true } +num-rational = { version = "0.4.1", optional = true } +serde = { version = "1.0.140", optional = true, features = ["derive"] } +v_frame = { version = "0.3.0", optional = true } + +[dev-dependencies] +quickcheck = "1.0.3" +quickcheck_macros = "1.0.0" + +[features] +default = ["create", "parse", "diff", "estimate"] +unstable = [] +create = [] +diff = ["num-rational", "v_frame"] +estimate = ["v_frame"] +parse = ["nom"] +serialize = ["serde", "arrayvec/serde"] + +[profile.release] +codegen-units = 1 +lto = "thin" + +[lints.clippy] +# Performance +clear_with_drain = "warn" +format_collect = "warn" +format_push_string = "warn" +imprecise_flops = "warn" +inefficient_to_string = "warn" +inline_always = "warn" +iter_with_drain = "warn" +large_include_file = "warn" +large_types_passed_by_value = "warn" +linkedlist = "deny" +missing_inline_in_public_items = "warn" +mutex_atomic = "warn" +mutex_integer = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_collect = "warn" +needless_pass_by_value = "warn" +non_std_lazy_statics = "warn" +non_zero_suggestions = "warn" +or_fun_call = "warn" +rc_buffer = "warn" +redundant_clone = "warn" +ref_option = "warn" +set_contains_or_insert = "warn" +stable_sort_primitive = "warn" +string_lit_chars_any = "warn" +suboptimal_flops = "warn" +trivial_regex = "warn" +trivially_copy_pass_by_ref = "warn" +unnecessary_box_returns = "warn" +unnecessary_join = "warn" +unused_async = "warn" +verbose_file_reads = "warn" +# Readability/Code Intention +# Disabled because of a lint difference between stable and nightly +# allow_attributes = "warn" +checked_conversions = "warn" +clone_on_ref_ptr = "warn" +cloned_instead_of_copied = "warn" +enum_glob_use = "warn" +equatable_if_let = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +if_then_some_else_none = "warn" +implicit_clone = "warn" +inconsistent_struct_constructor = "warn" +invalid_upcast_comparisons = "warn" +iter_filter_is_ok = "warn" +iter_filter_is_some = "warn" +iter_on_empty_collections = "warn" +iter_on_single_items = "warn" +macro_use_imports = "warn" +manual_assert = "warn" +manual_instant_elapsed = "warn" +manual_is_power_of_two = "warn" +manual_is_variant_and = "warn" +manual_let_else = "warn" +manual_string_new = "warn" +map_unwrap_or = "warn" +map_with_unused_argument_over_ranges = "warn" +match_bool = "warn" +needless_continue = "warn" +needless_pass_by_ref_mut = "warn" +option_as_ref_cloned = "warn" +option_if_let_else = "warn" +pathbuf_init_then_push = "warn" +precedence_bits = "warn" +range_minus_one = "warn" +range_plus_one = "warn" +redundant_test_prefix = "warn" +ref_option_ref = "warn" +# Disabled due to https://github.com/rust-lang/rust-clippy/issues/14697 +# self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +tests_outside_test_module = "warn" +transmute_ptr_to_ptr = "warn" +unused_peekable = "warn" +unused_rounding = "warn" +verbose_bit_mask = "warn" +zero_sized_map_values = "warn" +# Correctness/Safety +case_sensitive_file_extension_comparisons = "warn" +cfg_not_test = "deny" +collection_is_never_read = "warn" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "deny" +expl_impl_clone_on_copy = "deny" +filetype_is_file = "warn" +future_not_send = "warn" +ignore_without_reason = "warn" +infinite_loop = "warn" +large_futures = "warn" +large_stack_arrays = "warn" +large_stack_frames = "warn" +manual_midpoint = "warn" +maybe_infinite_iter = "warn" +mem_forget = "warn" +mismatching_type_param_order = "warn" +mixed_read_write_in_expression = "warn" +mut_mut = "warn" +non_send_fields_in_send_ty = "deny" +path_buf_push_overwrite = "warn" +rc_mutex = "warn" +read_zero_byte_vec = "warn" +significant_drop_in_scrutinee = "deny" +str_split_at_newline = "warn" +string_slice = "warn" +suspicious_operation_groupings = "warn" +suspicious_xor_used_as_pow = "warn" +transmute_undefined_repr = "warn" +undocumented_unsafe_blocks = "warn" +unnecessary_debug_formatting = "warn" +unwrap_used = "warn" +# Annoyances +uninlined_format_args = "allow" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2022-2022, the rav1e contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/README.md clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +# av1-grain + +[![docs.rs](https://img.shields.io/docsrs/av1-grain?style=for-the-badge)](https://docs.rs/av1-grain) +[![Crates.io](https://img.shields.io/crates/v/av1-grain?style=for-the-badge)](https://crates.io/crates/av1-grain) +[![LICENSE](https://img.shields.io/crates/l/av1-grain?style=for-the-badge)](https://github.com/rust-av/av1-grain/blob/main/LICENSE) + +This crate contains helper functions for parsing and generating AV1 film grain data. + +This code was originally created for use in rav1e. +It has been moved to this crate so it can be shared with other +AV1 crates that need to deal with film grain. + +## Examples + +The `generate_photon_noise_params` and `write_grain_table` APIs live behind the +`create` feature. Enable it in your project to produce plain-text photon noise tables +compatible with `svt-av1`, `aomenc`, and similar encoders: + +```rust +use av1_grain::{ + generate_photon_noise_params, write_grain_table, NoiseGenArgs, TransferFunction, +}; + +fn main() -> anyhow::Result<()> { + // This would apply to the entire video--we can use `u64::MAX` as the end timestamp for simplicity. + let segment = generate_photon_noise_params( + 0, + u64::MAX, + NoiseGenArgs { + // This setting can range from 100-6400 to adjust the noise strength + iso_setting: 800, + width: 1920, + height: 1080, + transfer_function: TransferFunction::BT1886, + chroma_grain: true, + random_seed: None, + }, + ); + + write_grain_table("example.tbl", &[segment])?; + Ok(()) +} +``` + +Running this program generates a photon noise table covering the entire video +(`start_time` 0 to `end_time` `u64::MAX`) and stores it in `example.tbl`. The +file extension is arbitrary; `.tbl` is a common choice. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +edition = "2021" +use_field_init_shorthand = true +use_try_shorthand = true + +# Unstable features--for future stabilization +# imports_layout = "HorizontalVertical" +# imports_granularity = "Crate" +# group_imports = "StdExternalCrate" +# format_strings = true +# format_macro_matchers = true +# format_macro_bodies = true +# hex_literal_case = "Lower" +# normalize_comments = true +# normalize_doc_attributes = true +# overflow_delimited_expr = true +# reorder_impl_items = true +# wrap_comments = true +# format_code_in_doc_comments = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/create.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/create.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/create.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/create.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,467 @@ +// Copyright (c) 2022-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +// The original work for this formula was implmented in aomenc, and this is +// an adaptation of that work: +// https://aomedia.googlesource.com/aom/+/refs/heads/main/examples/photon_noise_table.c + +// This implementation creates a film grain table, for use in stills and videos, +// representing the noise that one would get by shooting with a digital camera +// at a given light level. Much of the noise in digital images is photon shot +// noise, which is due to the characteristics of photon arrival and grows in +// standard deviation as the square root of the expected number of photons +// captured. +// https://www.photonstophotos.net/Emil%20Martinec/noise.html#shotnoise +// +// The proxy used by this implementation for the amount of light captured +// is the ISO value such that the focal plane exposure at the time of capture +// would have been mapped by a 35mm camera to the output lightness observed +// in the image. That is, if one were to shoot on a 35mm camera (36×24mm sensor) +// at the nominal exposure for that ISO setting, the resulting image should +// contain noise of the same order of magnitude as generated by this +// implementation. +// +// The (mostly) square-root relationship between light intensity and noise +// amplitude holds in linear light, but AV1 streams are most often encoded +// non-linearly, and the film grain is applied to those non-linear values. +// Therefore, this implementation must account for the non-linearity, and this +// is controlled by the transfer function parameter, which specifies the tone +// response curve that will be used when encoding the actual image. The default +// for this implementation is BT.1886, which is approximately similar to an +// encoding gamma of 1/2.8 (i.e. a decoding gamma of 2.8) though not quite +// identical. +// +// As alluded to above, the implementation assumes that the image is taken from +// the entirety of a 36×24mm (“35mm format”) sensor. If that assumption does not +// hold, then a “35mm-equivalent ISO value” that can be passed to the +// implementation can be obtained by multiplying the true ISO value by the ratio +// of 36×24mm to the area that was actually used. For formats that approximately +// share the same aspect ratio, this is often expressed as the square of the +// “equivalence ratio” which is the ratio of their diagonals. For example, APS-C +// (often ~24×16mm) is said to have an equivalence ratio of 1.5 relative to the +// 35mm format, and therefore ISO 1000 on APS-C and ISO 1000×1.5² = 2250 on 35mm +// produce an image of the same lightness from the same amount of light spread +// onto their respective surface areas (resulting in different focal plane +// exposures), and those images will thus have similar amounts of noise if the +// cameras are of similar technology. https://doi.org/10.1117/1.OE.57.11.110801 +// +// The implementation needs to know the resolution of the images to which its +// grain tables will be applied so that it can know how the light on the sensor +// was shared between its pixels. As a general rule, while a higher pixel count +// will lead to more noise per pixel, when the final image is viewed at the same +// physical size, that noise will tend to “average out” to the same amount over +// a given area, since there will be more pixels in it which, in aggregate, will +// have received essentially as much light. Put differently, the amount of noise +// depends on the scale at which it is measured, and the decision for this +// implementation was to make that scale relative to the image instead of its +// constituent samples. For more on this, see: +// +// https://www.photonstophotos.net/Emil%20Martinec/noise-p3.html#pixelsize +// https://www.dpreview.com/articles/5365920428/the-effect-of-pixel-and-sensor-sizes-on-noise/2 +// https://www.dpreview.com/videos/7940373140/dpreview-tv-why-lower-resolution-sensors-are-not-better-in-low-light + +use std::{ + fs::File, + io::{BufWriter, Write}, + path::Path, +}; + +use arrayvec::ArrayVec; + +use crate::{GrainTableSegment, ScalingPoints, DEFAULT_GRAIN_SEED, NUM_Y_POINTS}; + +const PQ_M1: f32 = 2610. / 16384.; +const PQ_M2: f32 = 128. * 2523. / 4096.; +const PQ_C1: f32 = 3424. / 4096.; +const PQ_C2: f32 = 32. * 2413. / 4096.; +const PQ_C3: f32 = 32. * 2392. / 4096.; + +const BT1886_WHITEPOINT: f32 = 203.; +const BT1886_BLACKPOINT: f32 = 0.1; +const BT1886_GAMMA: f32 = 2.4; + +// BT.1886 formula from https://en.wikipedia.org/wiki/ITU-R_BT.1886. +// +// TODO: the inverses, alpha, and beta should all be constants +// once floats in const fns are stabilized and `powf` is const. +// Until then, `inline(always)` gets us close enough. + +fn bt1886_inv_whitepoint() -> f32 { + BT1886_WHITEPOINT.powf(1.0 / BT1886_GAMMA) +} + +fn bt1886_inv_blackpoint() -> f32 { + BT1886_BLACKPOINT.powf(1.0 / BT1886_GAMMA) +} + +/// The variable for user gain: +/// `α = (Lw^(1/λ) - Lb^(1/λ)) ^ λ` +fn bt1886_alpha() -> f32 { + (bt1886_inv_whitepoint() - bt1886_inv_blackpoint()).powf(BT1886_GAMMA) +} + +/// The variable for user black level lift: +/// `β = Lb^(1/λ) / (Lw^(1/λ) - Lb^(1/λ))` +fn bt1886_beta() -> f32 { + bt1886_inv_blackpoint() / (bt1886_inv_whitepoint() - bt1886_inv_blackpoint()) +} + +/// Settings and video data defining how to generate the film grain params. +#[derive(Debug, Clone, Copy)] +pub struct NoiseGenArgs { + pub iso_setting: u32, + pub width: u32, + pub height: u32, + pub transfer_function: TransferFunction, + pub chroma_grain: bool, + pub random_seed: Option, +} + +/// Generates a set of photon noise parameters for a segment of video +/// given a set of `args`. +#[must_use] +#[inline] +pub fn generate_photon_noise_params( + start_time: u64, + end_time: u64, + args: NoiseGenArgs, +) -> GrainTableSegment { + GrainTableSegment { + start_time, + end_time, + scaling_points_y: generate_luma_noise_points(args), + scaling_points_cb: ArrayVec::new(), + scaling_points_cr: ArrayVec::new(), + scaling_shift: 8, + ar_coeff_lag: 0, + ar_coeffs_y: ArrayVec::new(), + ar_coeffs_cb: ArrayVec::try_from([0].as_slice()) + .expect("Cannot fail creation from const array"), + ar_coeffs_cr: ArrayVec::try_from([0].as_slice()) + .expect("Cannot fail creation from const array"), + ar_coeff_shift: 6, + cb_mult: 0, + cb_luma_mult: 0, + cb_offset: 0, + cr_mult: 0, + cr_luma_mult: 0, + cr_offset: 0, + overlap_flag: true, + chroma_scaling_from_luma: args.chroma_grain, + grain_scale_shift: 0, + random_seed: args.random_seed.unwrap_or(DEFAULT_GRAIN_SEED), + } +} + +/// Generates a set of film grain parameters for a segment of video +/// given a set of `args`. +/// +/// # Panics +/// - This is not yet implemented, so it will always panic +#[must_use] +#[inline] +#[cfg(feature = "unstable")] +pub fn generate_film_grain_params( + start_time: u64, + end_time: u64, + args: NoiseGenArgs, +) -> GrainTableSegment { + todo!("SCIENCE"); + // GrainTableSegment { + // start_time, + // end_time, + // scaling_points_y: generate_luma_noise_points(args), + // scaling_points_cb: ArrayVec::new(), + // scaling_points_cr: ArrayVec::new(), + // scaling_shift: 8, + // ar_coeff_lag: 0, + // ar_coeffs_y: ArrayVec::new(), + // ar_coeffs_cb: ArrayVec::try_from([0].as_slice()) + // .expect("Cannot fail creation from const array"), + // ar_coeffs_cr: ArrayVec::try_from([0].as_slice()) + // .expect("Cannot fail creation from const array"), + // ar_coeff_shift: 6, + // cb_mult: 0, + // cb_luma_mult: 0, + // cb_offset: 0, + // cr_mult: 0, + // cr_luma_mult: 0, + // cr_offset: 0, + // overlap_flag: true, + // chroma_scaling_from_luma: args.chroma_grain, + // grain_scale_shift: 0, + // random_seed: args.random_seed.unwrap_or(DEFAULT_GRAIN_SEED), + // } +} + +/// Write a set of generated film grain params to a table file, +/// using the standard film grain table format supported by +/// aomenc, rav1e, and svt-av1. +/// +/// # Errors +/// +/// - If the output file cannot be written to +#[inline] +pub fn write_grain_table>( + filename: P, + params: &[GrainTableSegment], +) -> anyhow::Result<()> { + let mut file = BufWriter::new(File::create(filename)?); + writeln!(&mut file, "filmgrn1")?; + for segment in params { + write_film_grain_segment(segment, &mut file)?; + } + file.flush()?; + + Ok(()) +} + +fn write_film_grain_segment( + params: &GrainTableSegment, + output: &mut BufWriter, +) -> anyhow::Result<()> { + writeln!( + output, + "E {} {} 1 {} 1", + params.start_time, params.end_time, params.random_seed, + )?; + writeln!( + output, + "\tp {} {} {} {} {} {} {} {} {} {} {} {}", + params.ar_coeff_lag, + params.ar_coeff_shift, + params.grain_scale_shift, + params.scaling_shift, + u8::from(params.chroma_scaling_from_luma), + u8::from(params.overlap_flag), + params.cb_mult, + params.cb_luma_mult, + params.cb_offset, + params.cr_mult, + params.cr_luma_mult, + params.cr_offset + )?; + + write!(output, "\tsY {} ", params.scaling_points_y.len())?; + for point in ¶ms.scaling_points_y { + write!(output, " {} {}", point[0], point[1])?; + } + writeln!(output)?; + + write!(output, "\tsCb {}", params.scaling_points_cb.len())?; + for point in ¶ms.scaling_points_cb { + write!(output, " {} {}", point[0], point[1])?; + } + writeln!(output)?; + + write!(output, "\tsCr {}", params.scaling_points_cr.len())?; + for point in ¶ms.scaling_points_cr { + write!(output, " {} {}", point[0], point[1])?; + } + writeln!(output)?; + + write!(output, "\tcY")?; + for coeff in ¶ms.ar_coeffs_y { + write!(output, " {}", *coeff)?; + } + writeln!(output)?; + + write!(output, "\tcCb")?; + for coeff in ¶ms.ar_coeffs_cb { + write!(output, " {}", *coeff)?; + } + writeln!(output)?; + + write!(output, "\tcCr")?; + for coeff in ¶ms.ar_coeffs_cr { + write!(output, " {}", *coeff)?; + } + writeln!(output)?; + + Ok(()) +} + +#[allow(clippy::upper_case_acronyms)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TransferFunction { + /// For SDR content + BT1886, + /// For HDR content + SMPTE2084, +} + +impl TransferFunction { + #[must_use] + #[inline] + pub fn to_linear(self, x: f32) -> f32 { + match self { + TransferFunction::BT1886 => { + // The screen luminance in cd/m^2: + // L = α * (x + β)^λ + let luma = bt1886_alpha() * (x + bt1886_beta()).powf(BT1886_GAMMA); + + // Normalize to between 0.0 and 1.0 + luma / BT1886_WHITEPOINT + } + TransferFunction::SMPTE2084 => { + let pq_pow_inv_m2 = x.powf(1. / PQ_M2); + (0_f32.max(pq_pow_inv_m2 - PQ_C1) / PQ_C3.mul_add(-pq_pow_inv_m2, PQ_C2)) + .powf(1. / PQ_M1) + } + } + } + + #[allow(clippy::wrong_self_convention)] + #[must_use] + #[inline] + pub fn from_linear(self, x: f32) -> f32 { + match self { + TransferFunction::BT1886 => { + // Scale to a raw cd/m^2 value + let luma = x * BT1886_WHITEPOINT; + + // The inverse of the `to_linear` formula: + // `(L / α)^(1 / λ) - β = x` + (luma / bt1886_alpha()).powf(1.0 / BT1886_GAMMA) - bt1886_beta() + } + TransferFunction::SMPTE2084 => { + if x < f32::EPSILON { + return 0.0; + } + let linear_pow_m1 = x.powf(PQ_M1); + (PQ_C2.mul_add(linear_pow_m1, PQ_C1) / PQ_C3.mul_add(linear_pow_m1, 1.)).powf(PQ_M2) + } + } + } + + #[inline] + #[must_use] + pub fn mid_tone(self) -> f32 { + self.to_linear(0.5) + } +} + +fn generate_luma_noise_points(args: NoiseGenArgs) -> ScalingPoints { + // Assumes a daylight-like spectrum. + // https://www.strollswithmydog.com/effective-quantum-efficiency-of-sensor/#:~:text=11%2C260%20photons/um%5E2/lx-s + const PHOTONS_PER_SQ_MICRON_PER_LUX_SECOND: f32 = 11260.; + + // Order of magnitude for cameras in the 2010-2020 decade, taking the CFA into + // account. + const EFFECTIVE_QUANTUM_EFFICIENCY: f32 = 0.2; + + // Also reasonable values for current cameras. The read noise is typically + // higher than this at low ISO settings but it matters less there. + const PHOTO_RESPONSE_NON_UNIFORMITY: f32 = 0.005; + const INPUT_REFERRED_READ_NOISE: f32 = 1.5; + + // Assumes a 35mm sensor (36mm × 24mm). + const SENSOR_AREA: f32 = 36_000. * 24_000.; + + // Focal plane exposure for a mid-tone (typically a 18% reflectance card), in + // lx·s. + let mid_tone_exposure = 10. / args.iso_setting as f32; + + let pixel_area_microns = SENSOR_AREA / (args.width * args.height) as f32; + + let mid_tone_electrons_per_pixel = EFFECTIVE_QUANTUM_EFFICIENCY + * PHOTONS_PER_SQ_MICRON_PER_LUX_SECOND + * mid_tone_exposure + * pixel_area_microns; + let max_electrons_per_pixel = mid_tone_electrons_per_pixel / args.transfer_function.mid_tone(); + + let mut scaling_points = ScalingPoints::default(); + for i in 0..NUM_Y_POINTS { + let x = i as f32 / (NUM_Y_POINTS as f32 - 1.); + let linear = args.transfer_function.to_linear(x); + let electrons_per_pixel = max_electrons_per_pixel * linear; + + // Quadrature sum of the relevant sources of noise, in electrons rms. Photon + // shot noise is sqrt(electrons) so we can skip the square root and the + // squaring. + // https://en.wikipedia.org/wiki/Addition_in_quadrature + // https://doi.org/10.1117/3.725073 + let noise_in_electrons = (PHOTO_RESPONSE_NON_UNIFORMITY + * PHOTO_RESPONSE_NON_UNIFORMITY + * electrons_per_pixel) + .mul_add( + electrons_per_pixel, + INPUT_REFERRED_READ_NOISE.mul_add(INPUT_REFERRED_READ_NOISE, electrons_per_pixel), + ) + .sqrt(); + let linear_noise = noise_in_electrons / max_electrons_per_pixel; + let linear_range_start = 0_f32.max(2.0f32.mul_add(-linear_noise, linear)); + let linear_range_end = 1_f32.min(2_f32.mul_add(linear_noise, linear)); + let tf_slope = (args.transfer_function.from_linear(linear_range_end) + - args.transfer_function.from_linear(linear_range_start)) + / (linear_range_end - linear_range_start); + let encoded_noise = linear_noise * tf_slope; + + let x = (255. * x).round() as u8; + let encoded_noise = 255_f32.min((255. * 7.88 * encoded_noise).round()) as u8; + + scaling_points.push([x, encoded_noise]); + } + + scaling_points +} + +#[cfg(test)] +mod tests { + use quickcheck::TestResult; + use quickcheck_macros::quickcheck; + + use super::*; + + #[quickcheck] + fn bt1886_to_linear_within_range(x: f32) -> TestResult { + if !(0.0..=1.0).contains(&x) || x.is_nan() { + return TestResult::discard(); + } + + let tx = TransferFunction::BT1886; + let res = tx.to_linear(x); + TestResult::from_bool((0.0..=1.0).contains(&res)) + } + + #[quickcheck] + fn bt1886_to_linear_reverts_correctly(x: f32) -> TestResult { + if !(0.0..=1.0).contains(&x) || x.is_nan() { + return TestResult::discard(); + } + + let tx = TransferFunction::BT1886; + let res = tx.to_linear(x); + let res = tx.from_linear(res); + TestResult::from_bool((x - res).abs() < f32::EPSILON) + } + + #[quickcheck] + fn smpte2084_to_linear_within_range(x: f32) -> TestResult { + if !(0.0..=1.0).contains(&x) || x.is_nan() { + return TestResult::discard(); + } + + let tx = TransferFunction::SMPTE2084; + let res = tx.to_linear(x); + TestResult::from_bool((0.0..=1.0).contains(&res)) + } + + #[quickcheck] + fn smpte2084_to_linear_reverts_correctly(x: f32) -> TestResult { + if !(0.0..=1.0).contains(&x) || x.is_nan() { + return TestResult::discard(); + } + + let tx = TransferFunction::SMPTE2084; + let res = tx.to_linear(x); + let res = tx.from_linear(res); + TestResult::from_bool((x - res).abs() < f32::EPSILON) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/ffmpeg.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/ffmpeg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/ffmpeg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/ffmpeg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,276 @@ +use std::{path::Path, ptr::addr_of_mut}; + +use anyhow::{bail, ensure, Result}; +use arrayvec::ArrayVec; +use ffmpeg_next::{ + codec::context::Context, + decoder, + format::{context::Input, input, Pixel}, + media::Type as MediaType, + Error::StreamNotFound, +}; +use num_rational::Rational64; +use v_frame::{frame::Frame, plane::Plane}; + +use super::{ColorFormat, PixelFormat, VideoSource}; + +pub(super) struct FfmpegSource { + input: Input, + decoder: decoder::Video, + next_frameno: usize, +} + +impl FfmpegSource { + pub(super) fn open(source: &Path) -> Result { + let input = input(&source)?; + let video_stream = input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + let decoder = Context::from_parameters(video_stream.parameters())? + .decoder() + .video()?; + + Ok(FfmpegSource { + input, + decoder, + next_frameno: 0, + }) + } +} + +impl VideoSource for FfmpegSource { + fn read_frame(&mut self, frameno: usize) -> Result>> { + ensure!( + frameno == self.next_frameno, + "Frame number mismatch in read_frame, ffmpeg decoder is desynced from av1-grain" + ); + + loop { + // SAFETY: This is a really bad Rust interface from ffmpeg_next. + // We don't let the frame escape unless it's initialized successfully. + unsafe { + let mut frame = ffmpeg_next::util::frame::Frame::empty(); + if self.decoder.receive_frame(&mut frame).is_ok() { + self.next_frameno += 1; + return Ok(Some(ffmpeg_frame_to_v_frame(&mut frame))); + } + }; + + let video_stream = self + .input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + let video_stream_index = video_stream.index(); + + let packet = self + .input + .packets() + .find(|&(ref stream, _)| stream.index() == video_stream_index); + if packet.is_none() { + return Ok(None); + } + + let (_, packet) = packet.unwrap(); + self.decoder.send_packet(&packet)?; + } + } + + fn get_frame_count(&mut self) -> Result { + let video_stream = self + .input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + let video_stream_index = video_stream.index(); + + let num_frames = self + .input + .packets() + .filter(|&(ref stream, _)| stream.index() == video_stream_index) + .count(); + self.input.seek(0, 0..1)?; + + ensure!(num_frames > 0, "ffmpeg reported 0 frames"); + + Ok(num_frames) + } + + fn get_frame_rate(&mut self) -> Result { + let video_stream = self + .input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + let rate = video_stream.avg_frame_rate(); + Ok(Rational64::new(i64::from(rate.0), i64::from(rate.1))) + } + + fn get_resolution(&mut self) -> Result<(u32, u32)> { + let video_stream = self + .input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + + let decoder = Context::from_parameters(video_stream.parameters())? + .decoder() + .video()?; + + Ok((decoder.width(), decoder.height())) + } + + fn get_pixel_format(&mut self) -> Result { + let video_stream = self + .input + .streams() + .best(MediaType::Video) + .ok_or(StreamNotFound)?; + + let decoder = Context::from_parameters(video_stream.parameters())? + .decoder() + .video()?; + + ColorFormat::try_from(decoder.format()) + } +} + +impl TryFrom for ColorFormat { + type Error = anyhow::Error; + + fn try_from(format: Pixel) -> Result { + Ok(match format { + Pixel::YUV420P | Pixel::YUVJ420P => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 8, + }, + Pixel::YUV422P | Pixel::YUVJ422P => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 8, + }, + Pixel::YUV444P | Pixel::YUVJ444P => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 8, + }, + Pixel::YUV420P9 | Pixel::YUV420P9BE | Pixel::YUV420P9LE => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 9, + }, + Pixel::YUV422P9 | Pixel::YUV422P9BE | Pixel::YUV422P9LE => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 9, + }, + Pixel::YUV444P9 | Pixel::YUV444P9BE | Pixel::YUV444P9LE => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 9, + }, + Pixel::YUV420P10 | Pixel::YUV420P10BE | Pixel::YUV420P10LE => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 10, + }, + Pixel::YUV422P10 | Pixel::YUV422P10BE | Pixel::YUV422P10LE => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 10, + }, + Pixel::YUV444P10 | Pixel::YUV444P10BE | Pixel::YUV444P10LE => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 10, + }, + Pixel::YUV420P12 | Pixel::YUV420P12BE | Pixel::YUV420P12LE => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 12, + }, + Pixel::YUV422P12 | Pixel::YUV422P12BE | Pixel::YUV422P12LE => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 12, + }, + Pixel::YUV444P12 | Pixel::YUV444P12BE | Pixel::YUV444P12LE => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 12, + }, + Pixel::YUV420P14 | Pixel::YUV420P14BE | Pixel::YUV420P14LE => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 14, + }, + Pixel::YUV422P14 | Pixel::YUV422P14BE | Pixel::YUV422P14LE => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 14, + }, + Pixel::YUV444P14 | Pixel::YUV444P14BE | Pixel::YUV444P14LE => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 14, + }, + Pixel::YUV420P16 | Pixel::YUV420P16LE | Pixel::YUV420P16BE => ColorFormat { + pixel_format: PixelFormat::YUV420, + bit_depth: 16, + }, + Pixel::YUV422P16 | Pixel::YUV422P16LE | Pixel::YUV422P16BE => ColorFormat { + pixel_format: PixelFormat::YUV422, + bit_depth: 16, + }, + Pixel::YUV444P16 | Pixel::YUV444P16LE | Pixel::YUV444P16BE => ColorFormat { + pixel_format: PixelFormat::YUV444, + bit_depth: 16, + }, + Pixel::GRAY8 => ColorFormat { + pixel_format: PixelFormat::YUV400, + bit_depth: 8, + }, + Pixel::GRAY16BE | Pixel::GRAY16LE | Pixel::GRAY16 => ColorFormat { + pixel_format: PixelFormat::YUV400, + bit_depth: 16, + }, + _ => bail!("Only YUV clips are supported"), + }) + } +} + +fn ffmpeg_frame_to_v_frame(ff_frame: &mut ffmpeg_next::util::frame::Frame) -> Frame { + // SAFETY: We know this pointer is initialized + let in_frame = unsafe { ffmpeg_next::util::frame::video::Video::wrap(ff_frame.as_mut_ptr()) }; + let mut planes = [ + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + ]; + let format = + ColorFormat::try_from(in_frame.format()).expect("Color format has already been checked"); + for p in 0..in_frame.planes() { + let mut plane: Plane = Plane::new( + in_frame.plane_width(p) as usize, + in_frame.plane_height(p) as usize, + if p > 0 { + format.pixel_format.subsampling().0 + } else { + 0 + }, + if p > 0 { + format.pixel_format.subsampling().1 + } else { + 0 + }, + 0usize, + 0usize, + ); + + let in_data = in_frame.data(p); + + if format.bit_depth == 8 { + assert!(plane.data.len() == in_data.len()); + plane.data_origin_mut().copy_from_slice(in_data); + } else { + assert!(plane.data.len() * 2 == in_data.len()); + in_data + .chunks_exact(2) + .zip(plane.data_origin_mut().iter_mut()) + .for_each(|(i, o)| { + let i = u16::from_le_bytes([i[0], i[1]]); + *o = (i >> (format.bit_depth - 8)) as u8; + }); + } + + planes[p] = plane; + } + Frame { planes } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/solver/util.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/solver/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver/util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,234 @@ +use std::ptr; + +use v_frame::plane::Plane; + +use crate::diff::BLOCK_SIZE; + +/// Solves Ax = b, where x and b are column vectors of size nx1 and A is nxn +#[allow(clippy::many_single_char_names)] +pub(super) fn linsolve( + n: usize, + a: &mut [f64], + stride: usize, + b: &mut [f64], + x: &mut [f64], +) -> bool { + // SAFETY: We need to ensure that `n` doesn't exceed the bounds of these arrays. + // But this is a crate-private function, so we control all input. + unsafe { + // Forward elimination + for k in 0..(n - 1) { + // Bring the largest magnitude to the diagonal position + ((k + 1)..n).rev().for_each(|i| { + if a.get_unchecked((i - 1) * stride + k).abs() + < a.get_unchecked(i * stride + k).abs() + { + (0..n).for_each(|j| { + swap_unchecked(a, i * stride + j, (i - 1) * stride + j); + }); + swap_unchecked(b, i, i - 1); + } + }); + + for i in k..(n - 1) { + if a.get_unchecked(k * stride + k).abs() < f64::EPSILON { + return false; + } + let c = *a.get_unchecked((i + 1) * stride + k) / *a.get_unchecked(k * stride + k); + (0..n).for_each(|j| { + let a2_val = *a.get_unchecked(k * stride + j); + let a_val = a.get_unchecked_mut((i + 1) * stride + j); + *a_val = c.mul_add(-a2_val, *a_val); + }); + let b2_val = *b.get_unchecked(k); + let b_val = b.get_unchecked_mut(i + 1); + *b_val = c.mul_add(-b2_val, *b_val); + } + } + + // Backward substitution + for i in (0..n).rev() { + if a.get_unchecked(i * stride + i).abs() < f64::EPSILON { + return false; + } + let mut c = 0.0f64; + for j in (i + 1)..n { + c = a + .get_unchecked(i * stride + j) + .mul_add(*x.get_unchecked(j), c); + } + *x.get_unchecked_mut(i) = (*b.get_unchecked(i) - c) / *a.get_unchecked(i * stride + i); + } + } + + true +} + +// TODO: This is unstable upstream. Once it's stable upstream, use that. +unsafe fn swap_unchecked(slice: &mut [T], a: usize, b: usize) { + let ptr = slice.as_mut_ptr(); + // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` + unsafe { + ptr::swap(ptr.add(a), ptr.add(b)); + } +} + +pub(super) fn multiply_mat( + m1: &[f64], + m2: &[f64], + res: &mut [f64], + m1_rows: usize, + inner_dim: usize, + m2_cols: usize, +) { + assert!(res.len() >= m1_rows * m2_cols); + assert!(m1.len() >= m1_rows * inner_dim); + assert!(m2.len() >= m2_cols * inner_dim); + let mut idx = 0; + for row in 0..m1_rows { + for col in 0..m2_cols { + let mut sum = 0f64; + for inner in 0..inner_dim { + // SAFETY: We do the bounds checks once at the top to improve performance. + unsafe { + sum += m1.get_unchecked(row * inner_dim + inner) + * m2.get_unchecked(inner * m2_cols + col); + } + } + // SAFETY: We do the bounds checks once at the top to improve performance. + unsafe { + *res.get_unchecked_mut(idx) = sum; + } + idx += 1; + } + } +} + +#[must_use] +pub(super) fn normalized_cross_correlation(a: &[f64], b: &[f64], n: usize) -> f64 { + let mut c = 0f64; + let mut a_len = 0f64; + let mut b_len = 0f64; + for (a, b) in a.iter().zip(b.iter()).take(n) { + a_len = (*a).mul_add(*a, a_len); + b_len = (*b).mul_add(*b, b_len); + c = (*a).mul_add(*b, c); + } + c / (a_len.sqrt() * b_len.sqrt()) +} + +#[allow(clippy::too_many_arguments)] +pub(super) fn extract_ar_row( + coords: &[[isize; 2]], + num_coords: usize, + source_origin: &[u8], + denoised_origin: &[u8], + stride: usize, + dec: (usize, usize), + alt_source_origin: Option<&[u8]>, + alt_denoised_origin: Option<&[u8]>, + alt_stride: usize, + x: usize, + y: usize, + buffer: &mut [f64], +) -> f64 { + debug_assert!(buffer.len() > num_coords); + debug_assert!(coords.len() >= num_coords); + + // SAFETY: We know the indexes we provide do not overflow the data bounds + unsafe { + for i in 0..num_coords { + let x_i = x as isize + coords.get_unchecked(i)[0]; + let y_i = y as isize + coords.get_unchecked(i)[1]; + debug_assert!(x_i >= 0); + debug_assert!(y_i >= 0); + let index = y_i as usize * stride + x_i as usize; + *buffer.get_unchecked_mut(i) = f64::from(*source_origin.get_unchecked(index)) + - f64::from(*denoised_origin.get_unchecked(index)); + } + let val = f64::from(*source_origin.get_unchecked(y * stride + x)) + - f64::from(*denoised_origin.get_unchecked(y * stride + x)); + + if let Some(alt_source_origin) = alt_source_origin { + if let Some(alt_denoised_origin) = alt_denoised_origin { + let mut source_sum = 0u64; + let mut denoised_sum = 0u64; + let mut num_samples = 0usize; + + for dy_i in 0..(1 << dec.1) { + let y_up = (y << dec.1) + dy_i; + for dx_i in 0..(1 << dec.0) { + let x_up = (x << dec.0) + dx_i; + let index = y_up * alt_stride + x_up; + source_sum += u64::from(*alt_source_origin.get_unchecked(index)); + denoised_sum += u64::from(*alt_denoised_origin.get_unchecked(index)); + num_samples += 1; + } + } + *buffer.get_unchecked_mut(num_coords) = + (source_sum as f64 - denoised_sum as f64) / num_samples as f64; + } + } + + val + } +} + +#[must_use] +pub(super) fn get_block_mean( + source: &Plane, + frame_dims: (usize, usize), + x_o: usize, + y_o: usize, +) -> f64 { + let max_h = (frame_dims.1 - y_o).min(BLOCK_SIZE); + let max_w = (frame_dims.0 - x_o).min(BLOCK_SIZE); + + let data_origin = source.data_origin(); + let mut block_sum = 0u64; + for y in 0..max_h { + for x in 0..max_w { + let index = (y_o + y) * source.cfg.stride + x_o + x; + // SAFETY: We know the index cannot exceed the dimensions of the plane data + unsafe { + block_sum += u64::from(*data_origin.get_unchecked(index)); + } + } + } + + block_sum as f64 / (max_w * max_h) as f64 +} + +#[must_use] +pub(super) fn get_noise_var( + source: &Plane, + denoised: &Plane, + frame_dims: (usize, usize), + x_o: usize, + y_o: usize, + block_w: usize, + block_h: usize, +) -> f64 { + let max_h = (frame_dims.1 - y_o).min(block_h); + let max_w = (frame_dims.0 - x_o).min(block_w); + + let source_origin = source.data_origin(); + let denoised_origin = denoised.data_origin(); + let mut noise_var_sum = 0u64; + let mut noise_sum = 0i64; + for y in 0..max_h { + for x in 0..max_w { + let index = (y_o + y) * source.cfg.stride + x_o + x; + // SAFETY: We know the index cannot exceed the dimensions of the plane data + unsafe { + let noise = i64::from(*source_origin.get_unchecked(index)) + - i64::from(*denoised_origin.get_unchecked(index)); + noise_sum += noise; + noise_var_sum += noise.pow(2) as u64; + } + } + } + + let noise_mean = noise_sum as f64 / (max_w * max_h) as f64; + noise_mean.mul_add(-noise_mean, noise_var_sum as f64 / (max_w * max_h) as f64) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/solver.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/solver.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/solver.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1159 @@ +mod util; + +use std::ops::{Add, AddAssign}; + +use anyhow::anyhow; +use arrayvec::ArrayVec; +use v_frame::{frame::Frame, math::clamp, plane::Plane}; + +use self::util::{extract_ar_row, get_block_mean, get_noise_var, linsolve, multiply_mat}; +use super::{NoiseStatus, BLOCK_SIZE, BLOCK_SIZE_SQUARED}; +use crate::{ + diff::solver::util::normalized_cross_correlation, GrainTableSegment, DEFAULT_GRAIN_SEED, + NUM_UV_COEFFS, NUM_UV_POINTS, NUM_Y_COEFFS, NUM_Y_POINTS, +}; + +const LOW_POLY_NUM_PARAMS: usize = 3; +const NOISE_MODEL_LAG: usize = 3; +const BLOCK_NORMALIZATION: f64 = 255.0f64; + +#[derive(Debug, Clone)] +pub(super) struct FlatBlockFinder { + a: Box<[f64]>, + a_t_a_inv: [f64; LOW_POLY_NUM_PARAMS * LOW_POLY_NUM_PARAMS], +} + +impl FlatBlockFinder { + #[must_use] + pub fn new() -> Self { + let mut eqns = EquationSystem::new(LOW_POLY_NUM_PARAMS); + let mut a_t_a_inv = [0.0f64; LOW_POLY_NUM_PARAMS * LOW_POLY_NUM_PARAMS]; + let mut a = vec![0.0f64; LOW_POLY_NUM_PARAMS * BLOCK_SIZE_SQUARED]; + + let bs_half = (BLOCK_SIZE / 2) as f64; + (0..BLOCK_SIZE).for_each(|y| { + let yd = (y as f64 - bs_half) / bs_half; + (0..BLOCK_SIZE).for_each(|x| { + let xd = (x as f64 - bs_half) / bs_half; + let coords = [yd, xd, 1.0f64]; + let row = y * BLOCK_SIZE + x; + a[LOW_POLY_NUM_PARAMS * row] = yd; + a[LOW_POLY_NUM_PARAMS * row + 1] = xd; + a[LOW_POLY_NUM_PARAMS * row + 2] = 1.0f64; + + (0..LOW_POLY_NUM_PARAMS).for_each(|i| { + (0..LOW_POLY_NUM_PARAMS).for_each(|j| { + eqns.a[LOW_POLY_NUM_PARAMS * i + j] += coords[i] * coords[j]; + }); + }); + }); + }); + + // Lazy inverse using existing equation solver. + (0..LOW_POLY_NUM_PARAMS).for_each(|i| { + eqns.b.fill(0.0f64); + eqns.b[i] = 1.0f64; + eqns.solve(); + + (0..LOW_POLY_NUM_PARAMS).for_each(|j| { + a_t_a_inv[j * LOW_POLY_NUM_PARAMS + i] = eqns.x[j]; + }); + }); + + FlatBlockFinder { + a: a.into_boxed_slice(), + a_t_a_inv, + } + } + + // The gradient-based features used in this code are based on: + // A. Kokaram, D. Kelly, H. Denman and A. Crawford, "Measuring noise + // correlation for improved video denoising," 2012 19th, ICIP. + // The thresholds are more lenient to allow for correct grain modeling + // in extreme cases. + #[must_use] + #[allow(clippy::too_many_lines)] + pub fn run(&self, plane: &Plane) -> (Vec, usize) { + const TRACE_THRESHOLD: f64 = 0.15f64 / BLOCK_SIZE_SQUARED as f64; + const RATIO_THRESHOLD: f64 = 1.25f64; + const NORM_THRESHOLD: f64 = 0.08f64 / BLOCK_SIZE_SQUARED as f64; + const VAR_THRESHOLD: f64 = 0.005f64 / BLOCK_SIZE_SQUARED as f64; + + // The following weights are used to combine the above features to give + // a sigmoid score for flatness. If the input was normalized to [0,100] + // the magnitude of these values would be close to 1 (e.g., weights + // corresponding to variance would be a factor of 10000x smaller). + const VAR_WEIGHT: f64 = -6682f64; + const RATIO_WEIGHT: f64 = -0.2056f64; + const TRACE_WEIGHT: f64 = 13087f64; + const NORM_WEIGHT: f64 = -12434f64; + const OFFSET: f64 = 2.5694f64; + + let num_blocks_w = plane.cfg.width.div_ceil(BLOCK_SIZE); + let num_blocks_h = plane.cfg.height.div_ceil(BLOCK_SIZE); + let num_blocks = num_blocks_w * num_blocks_h; + let mut flat_blocks = vec![0u8; num_blocks]; + let mut num_flat = 0; + let mut plane_result = [0.0f64; BLOCK_SIZE_SQUARED]; + let mut block_result = [0.0f64; BLOCK_SIZE_SQUARED]; + let mut scores = vec![IndexAndScore::default(); num_blocks]; + + for by in 0..num_blocks_h { + for bx in 0..num_blocks_w { + // Compute gradient covariance matrix. + let mut gxx = 0f64; + let mut gxy = 0f64; + let mut gyy = 0f64; + let mut var = 0f64; + let mut mean = 0f64; + + self.extract_block( + plane, + bx * BLOCK_SIZE, + by * BLOCK_SIZE, + &mut plane_result, + &mut block_result, + ); + for yi in 1..(BLOCK_SIZE - 1) { + for xi in 1..(BLOCK_SIZE - 1) { + // SAFETY: We know the size of `block_result` and that we cannot exceed the bounds of it + unsafe { + let result_ptr = block_result.as_ptr().add(yi * BLOCK_SIZE + xi); + + let gx = (*result_ptr.add(1) - *result_ptr.sub(1)) / 2f64; + let gy = + (*result_ptr.add(BLOCK_SIZE) - *result_ptr.sub(BLOCK_SIZE)) / 2f64; + gxx += gx * gx; + gxy += gx * gy; + gyy += gy * gy; + + let block_val = *result_ptr; + mean += block_val; + var += block_val * block_val; + } + } + } + let block_size_norm_factor = (BLOCK_SIZE - 2).pow(2) as f64; + mean /= block_size_norm_factor; + + // Normalize gradients by block_size. + gxx /= block_size_norm_factor; + gxy /= block_size_norm_factor; + gyy /= block_size_norm_factor; + var = mean.mul_add(-mean, var / block_size_norm_factor); + + let trace = gxx + gyy; + let det = gxx.mul_add(gyy, -gxy.powi(2)); + let e_sub = (trace.mul_add(trace, -4f64 * det)).max(0.).sqrt(); + let e1 = (trace + e_sub) / 2.0f64; + let e2 = (trace - e_sub) / 2.0f64; + // Spectral norm + let norm = e1; + let ratio = e1 / e2.max(1.0e-6_f64); + let is_flat = trace < TRACE_THRESHOLD + && ratio < RATIO_THRESHOLD + && norm < NORM_THRESHOLD + && var > VAR_THRESHOLD; + + let sum_weights = NORM_WEIGHT.mul_add( + norm, + TRACE_WEIGHT.mul_add( + trace, + VAR_WEIGHT.mul_add(var, RATIO_WEIGHT.mul_add(ratio, OFFSET)), + ), + ); + // clamp the value to [-25.0, 100.0] to prevent overflow + let sum_weights = clamp(sum_weights, -25.0f64, 100.0f64); + let score = (1.0f64 / (1.0f64 + (-sum_weights).exp())) as f32; + // SAFETY: We know the size of `flat_blocks` and `scores` and that we cannot exceed the bounds of it + unsafe { + let index = by * num_blocks_w + bx; + *flat_blocks.get_unchecked_mut(index) = if is_flat { 255 } else { 0 }; + *scores.get_unchecked_mut(index) = IndexAndScore { + score: if var > VAR_THRESHOLD { score } else { 0f32 }, + index, + }; + } + if is_flat { + num_flat += 1; + } + } + } + + scores.sort_unstable_by(|a, b| a.score.partial_cmp(&b.score).expect("Shouldn't be NaN")); + // SAFETY: We know the size of `flat_blocks` and `scores` and that we cannot exceed the bounds of it + unsafe { + let top_nth_percentile = num_blocks * 90 / 100; + let score_threshold = scores.get_unchecked(top_nth_percentile).score; + for score in &scores { + if score.score >= score_threshold { + let block_ref = flat_blocks.get_unchecked_mut(score.index); + if *block_ref == 0 { + num_flat += 1; + } + *block_ref |= 1; + } + } + } + + (flat_blocks, num_flat) + } + + fn extract_block( + &self, + plane: &Plane, + offset_x: usize, + offset_y: usize, + plane_result: &mut [f64; BLOCK_SIZE_SQUARED], + block_result: &mut [f64; BLOCK_SIZE_SQUARED], + ) { + let mut plane_coords = [0f64; LOW_POLY_NUM_PARAMS]; + let mut a_t_a_inv_b = [0f64; LOW_POLY_NUM_PARAMS]; + let plane_origin = plane.data_origin(); + + for yi in 0..BLOCK_SIZE { + let y = clamp(offset_y + yi, 0, plane.cfg.height - 1); + for xi in 0..BLOCK_SIZE { + let x = clamp(offset_x + xi, 0, plane.cfg.width - 1); + // SAFETY: We know the bounds of the plane data and `block_result` + // and do not exceed them. + unsafe { + *block_result.get_unchecked_mut(yi * BLOCK_SIZE + xi) = + f64::from(*plane_origin.get_unchecked(y * plane.cfg.stride + x)) + / BLOCK_NORMALIZATION; + } + } + } + + multiply_mat( + block_result, + &self.a, + &mut a_t_a_inv_b, + 1, + BLOCK_SIZE_SQUARED, + LOW_POLY_NUM_PARAMS, + ); + multiply_mat( + &self.a_t_a_inv, + &a_t_a_inv_b, + &mut plane_coords, + LOW_POLY_NUM_PARAMS, + LOW_POLY_NUM_PARAMS, + 1, + ); + multiply_mat( + &self.a, + &plane_coords, + plane_result, + BLOCK_SIZE_SQUARED, + LOW_POLY_NUM_PARAMS, + 1, + ); + + for (block_res, plane_res) in block_result.iter_mut().zip(plane_result.iter()) { + *block_res -= *plane_res; + } + } +} + +#[derive(Debug, Clone, Copy, Default)] +struct IndexAndScore { + pub index: usize, + pub score: f32, +} + +/// Wrapper of data required to represent linear system of eqns and soln. +#[derive(Debug, Clone)] +struct EquationSystem { + a: Vec, + b: Vec, + x: Vec, + n: usize, +} + +impl EquationSystem { + #[must_use] + pub fn new(n: usize) -> Self { + Self { + a: vec![0.0f64; n * n], + b: vec![0.0f64; n], + x: vec![0.0f64; n], + n, + } + } + + pub fn solve(&mut self) -> bool { + let n = self.n; + let mut a = self.a.clone(); + let mut b = self.b.clone(); + + linsolve(n, &mut a, self.n, &mut b, &mut self.x) + } + + pub fn set_chroma_coefficient_fallback_solution(&mut self) { + const TOLERANCE: f64 = 1.0e-6f64; + let last = self.n - 1; + // Set all of the AR coefficients to zero, but try to solve for correlation + // with the luma channel + self.x.fill(0f64); + if self.a[last * self.n + last].abs() > TOLERANCE { + self.x[last] = self.b[last] / self.a[last * self.n + last]; + } + } + + pub fn copy_from(&mut self, other: &Self) { + assert_eq!(self.n, other.n); + self.a.copy_from_slice(&other.a); + self.x.copy_from_slice(&other.x); + self.b.copy_from_slice(&other.b); + } + + pub fn clear(&mut self) { + self.a.fill(0f64); + self.b.fill(0f64); + self.x.fill(0f64); + } +} + +impl Add<&EquationSystem> for EquationSystem { + type Output = EquationSystem; + + fn add(self, addend: &EquationSystem) -> Self::Output { + let mut dest = self.clone(); + let n = self.n; + for i in 0..n { + for j in 0..n { + dest.a[i * n + j] += addend.a[i * n + j]; + } + dest.b[i] += addend.b[i]; + } + dest + } +} + +impl AddAssign<&EquationSystem> for EquationSystem { + fn add_assign(&mut self, rhs: &EquationSystem) { + *self = self.clone() + rhs; + } +} + +/// Representation of a piecewise linear curve +/// +/// Holds n points as (x, y) pairs, that store the curve. +struct NoiseStrengthLut { + points: Vec<[f64; 2]>, +} + +impl NoiseStrengthLut { + #[must_use] + pub fn new(num_bins: usize) -> Self { + assert!(num_bins > 0); + Self { + points: vec![[0f64; 2]; num_bins], + } + } +} + +#[derive(Debug, Clone)] +pub(super) struct NoiseModel { + combined_state: [NoiseModelState; 3], + latest_state: [NoiseModelState; 3], + n: usize, + coords: Vec<[isize; 2]>, +} + +impl NoiseModel { + #[must_use] + pub fn new() -> Self { + let n = Self::num_coeffs(); + let combined_state = [ + NoiseModelState::new(n), + NoiseModelState::new(n + 1), + NoiseModelState::new(n + 1), + ]; + let latest_state = [ + NoiseModelState::new(n), + NoiseModelState::new(n + 1), + NoiseModelState::new(n + 1), + ]; + let mut coords = Vec::new(); + + let neg_lag = -(NOISE_MODEL_LAG as isize); + for y in neg_lag..=0 { + let max_x = if y == 0 { + -1isize + } else { + NOISE_MODEL_LAG as isize + }; + for x in neg_lag..=max_x { + coords.push([x, y]); + } + } + assert!(n == coords.len()); + + Self { + combined_state, + latest_state, + n, + coords, + } + } + + pub fn update( + &mut self, + source: &Frame, + denoised: &Frame, + flat_blocks: &[u8], + ) -> NoiseStatus { + let num_blocks_w = source.planes[0].cfg.width.div_ceil(BLOCK_SIZE); + let num_blocks_h = source.planes[0].cfg.height.div_ceil(BLOCK_SIZE); + let mut y_model_different = false; + + // Clear the latest equation system + for i in 0..3 { + self.latest_state[i].eqns.clear(); + self.latest_state[i].num_observations = 0; + self.latest_state[i].strength_solver.clear(); + } + + // Check that we have enough flat blocks + let num_blocks = flat_blocks.iter().filter(|b| **b > 0).count(); + if num_blocks <= 1 { + return NoiseStatus::Error(anyhow!("Not enough flat blocks to update noise estimate")); + } + + let frame_dims = (source.planes[0].cfg.width, source.planes[0].cfg.height); + for channel in 0..3 { + if source.planes[channel].data.is_empty() { + // Monochrome source + break; + } + let is_chroma = channel > 0; + let alt_source = (channel > 0).then(|| &source.planes[0]); + let alt_denoised = (channel > 0).then(|| &denoised.planes[0]); + self.add_block_observations( + channel, + &source.planes[channel], + &denoised.planes[channel], + alt_source, + alt_denoised, + frame_dims, + flat_blocks, + num_blocks_w, + num_blocks_h, + ); + if !self.latest_state[channel].ar_equation_system_solve(is_chroma) { + if is_chroma { + self.latest_state[channel] + .eqns + .set_chroma_coefficient_fallback_solution(); + } else { + return NoiseStatus::Error(anyhow!( + "Solving latest noise equation system failed on plane {}", + channel + )); + } + } + self.add_noise_std_observations( + channel, + &source.planes[channel], + &denoised.planes[channel], + alt_source, + frame_dims, + flat_blocks, + num_blocks_w, + num_blocks_h, + ); + if !self.latest_state[channel].strength_solver.solve() { + return NoiseStatus::Error(anyhow!( + "Failed to solve strength solver for latest state" + )); + } + + // Check noise characteristics and return if error + if channel == 0 + && self.combined_state[channel].strength_solver.num_equations > 0 + && self.is_different() + { + y_model_different = true; + } + + if y_model_different { + continue; + } + + self.combined_state[channel].num_observations += + self.latest_state[channel].num_observations; + self.combined_state[channel].eqns += &self.latest_state[channel].eqns; + if !self.combined_state[channel].ar_equation_system_solve(is_chroma) { + if is_chroma { + self.combined_state[channel] + .eqns + .set_chroma_coefficient_fallback_solution(); + } else { + return NoiseStatus::Error(anyhow!( + "Solving combined noise equation system failed on plane {}", + channel + )); + } + } + + self.combined_state[channel].strength_solver += + &self.latest_state[channel].strength_solver; + + if !self.combined_state[channel].strength_solver.solve() { + return NoiseStatus::Error(anyhow!( + "Failed to solve strength solver for combined state" + )); + }; + } + + if y_model_different { + return NoiseStatus::DifferentType; + } + + NoiseStatus::Ok + } + + #[allow(clippy::too_many_lines)] + #[must_use] + pub fn get_grain_parameters(&self, start_ts: u64, end_ts: u64) -> GrainTableSegment { + // Both the domain and the range of the scaling functions in the film_grain + // are normalized to 8-bit (e.g., they are implicitly scaled during grain + // synthesis). + let scaling_points_y = self.combined_state[0] + .strength_solver + .fit_piecewise(NUM_Y_POINTS) + .points; + let scaling_points_cb = self.combined_state[1] + .strength_solver + .fit_piecewise(NUM_UV_POINTS) + .points; + let scaling_points_cr = self.combined_state[2] + .strength_solver + .fit_piecewise(NUM_UV_POINTS) + .points; + + let mut max_scaling_value: f64 = 1.0e-4f64; + for p in scaling_points_y + .iter() + .chain(scaling_points_cb.iter()) + .chain(scaling_points_cr.iter()) + .map(|p| p[1]) + { + if p > max_scaling_value { + max_scaling_value = p; + } + } + + // Scaling_shift values are in the range [8,11] + let max_scaling_value_log2 = + clamp((max_scaling_value.log2() + 1f64).floor() as u8, 2u8, 5u8); + let scale_factor = f64::from(1u32 << (8u8 - max_scaling_value_log2)); + let map_scaling_point = |p: [f64; 2]| { + [ + (p[0] + 0.5f64) as u8, + clamp(scale_factor.mul_add(p[1], 0.5f64) as i32, 0i32, 255i32) as u8, + ] + }; + + let scaling_points_y: ArrayVec<_, NUM_Y_POINTS> = scaling_points_y + .into_iter() + .map(map_scaling_point) + .collect(); + let scaling_points_cb: ArrayVec<_, NUM_UV_POINTS> = scaling_points_cb + .into_iter() + .map(map_scaling_point) + .collect(); + let scaling_points_cr: ArrayVec<_, NUM_UV_POINTS> = scaling_points_cr + .into_iter() + .map(map_scaling_point) + .collect(); + + // Convert the ar_coeffs into 8-bit values + let n_coeff = self.combined_state[0].eqns.n; + let mut max_coeff = 1.0e-4f64; + let mut min_coeff = 1.0e-4f64; + let mut y_corr = [0f64; 2]; + let mut avg_luma_strength = 0f64; + for c in 0..3 { + let eqns = &self.combined_state[c].eqns; + for i in 0..n_coeff { + if eqns.x[i] > max_coeff { + max_coeff = eqns.x[i]; + } + if eqns.x[i] < min_coeff { + min_coeff = eqns.x[i]; + } + } + + // Since the correlation between luma/chroma was computed in an already + // scaled space, we adjust it in the un-scaled space. + let solver = &self.combined_state[c].strength_solver; + // Compute a weighted average of the strength for the channel. + let mut average_strength = 0f64; + let mut total_weight = 0f64; + for i in 0..solver.eqns.n { + let mut w = 0f64; + for j in 0..solver.eqns.n { + w += solver.eqns.a[i * solver.eqns.n + j]; + } + w = w.sqrt(); + average_strength += solver.eqns.x[i] * w; + total_weight += w; + } + if total_weight.abs() < f64::EPSILON { + average_strength = 1f64; + } else { + average_strength /= total_weight; + } + if c == 0 { + avg_luma_strength = average_strength; + } else { + y_corr[c - 1] = avg_luma_strength * eqns.x[n_coeff] / average_strength; + max_coeff = max_coeff.max(y_corr[c - 1]); + min_coeff = min_coeff.min(y_corr[c - 1]); + } + } + + // Shift value: AR coeffs range (values 6-9) + // 6: [-2, 2), 7: [-1, 1), 8: [-0.5, 0.5), 9: [-0.25, 0.25) + let ar_coeff_shift = clamp( + 7i32 - (1.0f64 + max_coeff.log2().floor()).max((-min_coeff).log2().ceil()) as i32, + 6i32, + 9i32, + ) as u8; + let scale_ar_coeff = f64::from(1u16 << ar_coeff_shift); + let ar_coeffs_y = self.get_ar_coeffs_y(n_coeff, scale_ar_coeff); + let ar_coeffs_cb = self.get_ar_coeffs_uv(1, n_coeff, scale_ar_coeff, y_corr); + let ar_coeffs_cr = self.get_ar_coeffs_uv(2, n_coeff, scale_ar_coeff, y_corr); + + GrainTableSegment { + random_seed: if start_ts == 0 { DEFAULT_GRAIN_SEED } else { 0 }, + start_time: start_ts, + end_time: end_ts, + ar_coeff_lag: NOISE_MODEL_LAG as u8, + scaling_points_y, + scaling_points_cb, + scaling_points_cr, + scaling_shift: 5 + (8 - max_scaling_value_log2), + ar_coeff_shift, + ar_coeffs_y, + ar_coeffs_cb, + ar_coeffs_cr, + // At the moment, the noise modeling code assumes that the chroma scaling + // functions are a function of luma. + cb_mult: 128, + cb_luma_mult: 192, + cb_offset: 256, + cr_mult: 128, + cr_luma_mult: 192, + cr_offset: 256, + chroma_scaling_from_luma: false, + grain_scale_shift: 0, + overlap_flag: true, + } + } + + pub fn save_latest(&mut self) { + for c in 0..3 { + let latest_state = &self.latest_state[c]; + let combined_state = &mut self.combined_state[c]; + combined_state.eqns.copy_from(&latest_state.eqns); + combined_state + .strength_solver + .eqns + .copy_from(&latest_state.strength_solver.eqns); + combined_state.strength_solver.num_equations = + latest_state.strength_solver.num_equations; + combined_state.num_observations = latest_state.num_observations; + combined_state.ar_gain = latest_state.ar_gain; + } + } + + #[must_use] + const fn num_coeffs() -> usize { + let n = 2 * NOISE_MODEL_LAG + 1; + (n * n) / 2 + } + + #[must_use] + fn get_ar_coeffs_y(&self, n_coeff: usize, scale_ar_coeff: f64) -> ArrayVec { + assert!(n_coeff <= NUM_Y_COEFFS); + let mut coeffs = ArrayVec::new(); + let eqns = &self.combined_state[0].eqns; + for i in 0..n_coeff { + coeffs.push(clamp((scale_ar_coeff * eqns.x[i]).round() as i32, -128i32, 127i32) as i8); + } + coeffs + } + + #[must_use] + fn get_ar_coeffs_uv( + &self, + channel: usize, + n_coeff: usize, + scale_ar_coeff: f64, + y_corr: [f64; 2], + ) -> ArrayVec { + assert!(n_coeff <= NUM_Y_COEFFS); + let mut coeffs = ArrayVec::new(); + let eqns = &self.combined_state[channel].eqns; + for i in 0..n_coeff { + coeffs.push(clamp((scale_ar_coeff * eqns.x[i]).round() as i32, -128i32, 127i32) as i8); + } + coeffs.push(clamp( + (scale_ar_coeff * y_corr[channel - 1]).round() as i32, + -128i32, + 127i32, + ) as i8); + coeffs + } + + // Return true if the noise estimate appears to be different from the combined + // (multi-frame) estimate. The difference is measured by checking whether the + // AR coefficients have diverged (using a threshold on normalized cross + // correlation), or whether the noise strength has changed. + #[must_use] + fn is_different(&self) -> bool { + const COEFF_THRESHOLD: f64 = 0.9f64; + const STRENGTH_THRESHOLD: f64 = 0.005f64; + + let latest = &self.latest_state[0]; + let combined = &self.combined_state[0]; + let corr = normalized_cross_correlation(&latest.eqns.x, &combined.eqns.x, combined.eqns.n); + if corr < COEFF_THRESHOLD { + return true; + } + + let dx = 1.0f64 / latest.strength_solver.num_bins as f64; + let latest_eqns = &latest.strength_solver.eqns; + let combined_eqns = &combined.strength_solver.eqns; + let mut diff = 0.0f64; + let mut total_weight = 0.0f64; + for j in 0..latest_eqns.n { + let mut weight = 0.0f64; + for i in 0..latest_eqns.n { + weight += latest_eqns.a[i * latest_eqns.n + j]; + } + weight = weight.sqrt(); + diff += weight * (latest_eqns.x[j] - combined_eqns.x[j]).abs(); + total_weight += weight; + } + + diff * dx / total_weight > STRENGTH_THRESHOLD + } + + #[allow(clippy::too_many_arguments)] + fn add_block_observations( + &mut self, + channel: usize, + source: &Plane, + denoised: &Plane, + alt_source: Option<&Plane>, + alt_denoised: Option<&Plane>, + frame_dims: (usize, usize), + flat_blocks: &[u8], + num_blocks_w: usize, + num_blocks_h: usize, + ) { + let num_coords = self.n; + let state = &mut self.latest_state[channel]; + let a = &mut state.eqns.a; + let b = &mut state.eqns.b; + let mut buffer = vec![0f64; num_coords + 1].into_boxed_slice(); + let n = state.eqns.n; + let block_w = BLOCK_SIZE >> source.cfg.xdec; + let block_h = BLOCK_SIZE >> source.cfg.ydec; + + let dec = (source.cfg.xdec, source.cfg.ydec); + let stride = source.cfg.stride; + let source_origin = source.data_origin(); + let denoised_origin = denoised.data_origin(); + let alt_stride = alt_source.map_or(0, |s| s.cfg.stride); + let alt_source_origin = alt_source.map(|s| s.data_origin()); + let alt_denoised_origin = alt_denoised.map(|s| s.data_origin()); + + for by in 0..num_blocks_h { + let y_o = by * block_h; + for bx in 0..num_blocks_w { + // SAFETY: We know the indexes we provide do not overflow the data bounds + unsafe { + let flat_block_ptr = flat_blocks.as_ptr().add(by * num_blocks_w + bx); + let x_o = bx * block_w; + if *flat_block_ptr == 0 { + continue; + } + let y_start = if by > 0 && *flat_block_ptr.sub(num_blocks_w) > 0 { + 0 + } else { + NOISE_MODEL_LAG + }; + let x_start = if bx > 0 && *flat_block_ptr.sub(1) > 0 { + 0 + } else { + NOISE_MODEL_LAG + }; + let y_end = ((frame_dims.1 >> dec.1) - by * block_h).min(block_h); + let x_end = ((frame_dims.0 >> dec.0) - bx * block_w - NOISE_MODEL_LAG).min( + if bx + 1 < num_blocks_w && *flat_block_ptr.add(1) > 0 { + block_w + } else { + block_w - NOISE_MODEL_LAG + }, + ); + for y in y_start..y_end { + for x in x_start..x_end { + let val = extract_ar_row( + &self.coords, + num_coords, + source_origin, + denoised_origin, + stride, + dec, + alt_source_origin, + alt_denoised_origin, + alt_stride, + x + x_o, + y + y_o, + &mut buffer, + ); + for i in 0..n { + for j in 0..n { + *a.get_unchecked_mut(i * n + j) += (*buffer.get_unchecked(i) + * *buffer.get_unchecked(j)) + / BLOCK_NORMALIZATION.powi(2); + } + *b.get_unchecked_mut(i) += + (*buffer.get_unchecked(i) * val) / BLOCK_NORMALIZATION.powi(2); + } + state.num_observations += 1; + } + } + } + } + } + } + + #[allow(clippy::too_many_arguments)] + fn add_noise_std_observations( + &mut self, + channel: usize, + source: &Plane, + denoised: &Plane, + alt_source: Option<&Plane>, + frame_dims: (usize, usize), + flat_blocks: &[u8], + num_blocks_w: usize, + num_blocks_h: usize, + ) { + let coeffs = &self.latest_state[channel].eqns.x; + let num_coords = self.n; + let luma_gain = self.latest_state[0].ar_gain; + let noise_gain = self.latest_state[channel].ar_gain; + let block_w = BLOCK_SIZE >> source.cfg.xdec; + let block_h = BLOCK_SIZE >> source.cfg.ydec; + + for by in 0..num_blocks_h { + let y_o = by * block_h; + for bx in 0..num_blocks_w { + let x_o = bx * block_w; + if flat_blocks[by * num_blocks_w + bx] == 0 { + continue; + } + let num_samples_h = ((frame_dims.1 >> source.cfg.ydec) - by * block_h).min(block_h); + let num_samples_w = ((frame_dims.0 >> source.cfg.xdec) - bx * block_w).min(block_w); + // Make sure that we have a reasonable amount of samples to consider the + // block + if num_samples_w * num_samples_h > BLOCK_SIZE { + let block_mean = get_block_mean( + alt_source.unwrap_or(source), + frame_dims, + x_o << source.cfg.xdec, + y_o << source.cfg.ydec, + ); + let noise_var = get_noise_var( + source, + denoised, + ( + frame_dims.0 >> source.cfg.xdec, + frame_dims.1 >> source.cfg.ydec, + ), + x_o, + y_o, + block_w, + block_h, + ); + // We want to remove the part of the noise that came from being + // correlated with luma. Note that the noise solver for luma must + // have already been run. + let luma_strength = if channel > 0 { + luma_gain * self.latest_state[0].strength_solver.get_value(block_mean) + } else { + 0f64 + }; + let corr = if channel > 0 { + coeffs[num_coords] + } else { + 0f64 + }; + // Chroma noise: + // N(0, noise_var) = N(0, uncorr_var) + corr * N(0, luma_strength^2) + // The uncorrelated component: + // uncorr_var = noise_var - (corr * luma_strength)^2 + // But don't allow fully correlated noise (hence the max), since the + // synthesis cannot model it. + let uncorr_std = (noise_var / 16f64) + .max((corr * luma_strength).mul_add(-(corr * luma_strength), noise_var)) + .sqrt(); + let adjusted_strength = uncorr_std / noise_gain; + self.latest_state[channel] + .strength_solver + .add_measurement(block_mean, adjusted_strength); + } + } + } + } +} + +#[derive(Debug, Clone)] +struct NoiseModelState { + eqns: EquationSystem, + ar_gain: f64, + num_observations: usize, + strength_solver: StrengthSolver, +} + +impl NoiseModelState { + #[must_use] + pub fn new(n: usize) -> Self { + const NUM_BINS: usize = 20; + + Self { + eqns: EquationSystem::new(n), + ar_gain: 1.0f64, + num_observations: 0usize, + strength_solver: StrengthSolver::new(NUM_BINS), + } + } + + pub fn ar_equation_system_solve(&mut self, is_chroma: bool) -> bool { + let ret = self.eqns.solve(); + self.ar_gain = 1.0f64; + if !ret { + return ret; + } + + // Update the AR gain from the equation system as it will be used to fit + // the noise strength as a function of intensity. In the Yule-Walker + // equations, the diagonal should be the variance of the correlated noise. + // In the case of the least squares estimate, there will be some variability + // in the diagonal. So use the mean of the diagonal as the estimate of + // overall variance (this works for least squares or Yule-Walker formulation). + let mut var = 0f64; + let n_adjusted = self.eqns.n - usize::from(is_chroma); + for i in 0..n_adjusted { + var += self.eqns.a[i * self.eqns.n + i] / self.num_observations as f64; + } + var /= n_adjusted as f64; + + // Keep track of E(Y^2) = + E(X^2) + // In the case that we are using chroma and have an estimate of correlation + // with luma we adjust that estimate slightly to remove the correlated bits by + // subtracting out the last column of a scaled by our correlation estimate + // from b. E(y^2) = + let mut sum_covar = 0f64; + for i in 0..n_adjusted { + let mut bi = self.eqns.b[i]; + if is_chroma { + bi -= self.eqns.a[i * self.eqns.n + n_adjusted] * self.eqns.x[n_adjusted]; + } + sum_covar += (bi * self.eqns.x[i]) / self.num_observations as f64; + } + + // Now, get an estimate of the variance of uncorrelated noise signal and use + // it to determine the gain of the AR filter. + let noise_var = (var - sum_covar).max(1e-6f64); + self.ar_gain = 1f64.max((var / noise_var).max(1e-6f64).sqrt()); + ret + } +} + +#[derive(Debug, Clone)] +struct StrengthSolver { + eqns: EquationSystem, + num_bins: usize, + num_equations: usize, + total: f64, +} + +impl StrengthSolver { + #[must_use] + pub fn new(num_bins: usize) -> Self { + Self { + eqns: EquationSystem::new(num_bins), + num_bins, + num_equations: 0usize, + total: 0f64, + } + } + + pub fn add_measurement(&mut self, block_mean: f64, noise_std: f64) { + let bin = self.get_bin_index(block_mean); + let bin_i0 = bin.floor() as usize; + let bin_i1 = (self.num_bins - 1).min(bin_i0 + 1); + let a = bin - bin_i0 as f64; + let n = self.num_bins; + let eqns = &mut self.eqns; + eqns.a[bin_i0 * n + bin_i0] += (1f64 - a).powi(2); + eqns.a[bin_i1 * n + bin_i0] += a * (1f64 - a); + eqns.a[bin_i1 * n + bin_i1] += a.powi(2); + eqns.a[bin_i0 * n + bin_i1] += (1f64 - a) * a; + eqns.b[bin_i0] += (1f64 - a) * noise_std; + eqns.b[bin_i1] += a * noise_std; + self.total += noise_std; + self.num_equations += 1; + } + + pub fn solve(&mut self) -> bool { + // Add regularization proportional to the number of constraints + let n = self.num_bins; + let alpha = 2f64 * self.num_equations as f64 / n as f64; + + // Do this in a non-destructive manner so it is not confusing to the caller + let old_a = self.eqns.a.clone(); + for i in 0..n { + let i_lo = i.saturating_sub(1); + let i_hi = (n - 1).min(i + 1); + self.eqns.a[i * n + i_lo] -= alpha; + self.eqns.a[i * n + i] += 2f64 * alpha; + self.eqns.a[i * n + i_hi] -= alpha; + } + + // Small regularization to give average noise strength + let mean = self.total / self.num_equations as f64; + for i in 0..n { + self.eqns.a[i * n + i] += 1f64 / 8192f64; + self.eqns.b[i] += mean / 8192f64; + } + let result = self.eqns.solve(); + self.eqns.a = old_a; + result + } + + #[must_use] + pub fn fit_piecewise(&self, max_output_points: usize) -> NoiseStrengthLut { + const TOLERANCE: f64 = 0.00625f64; + + let mut lut = NoiseStrengthLut::new(self.num_bins); + for i in 0..self.num_bins { + lut.points[i][0] = self.get_center(i); + lut.points[i][1] = self.eqns.x[i]; + } + + let mut residual = vec![0.0f64; self.num_bins]; + self.update_piecewise_linear_residual(&lut, &mut residual, 0, self.num_bins); + + // Greedily remove points if there are too many or if it doesn't hurt local + // approximation (never remove the end points) + while lut.points.len() > 2 { + let mut min_index = 1usize; + for j in 1..(lut.points.len() - 1) { + if residual[j] < residual[min_index] { + min_index = j; + } + } + let dx = lut.points[min_index + 1][0] - lut.points[min_index - 1][0]; + let avg_residual = residual[min_index] / dx; + if lut.points.len() <= max_output_points && avg_residual > TOLERANCE { + break; + } + + lut.points.remove(min_index); + self.update_piecewise_linear_residual( + &lut, + &mut residual, + min_index - 1, + min_index + 1, + ); + } + + lut + } + + #[must_use] + pub fn get_value(&self, x: f64) -> f64 { + let bin = self.get_bin_index(x); + let bin_i0 = bin.floor() as usize; + let bin_i1 = (self.num_bins - 1).min(bin_i0 + 1); + let a = bin - bin_i0 as f64; + (1f64 - a).mul_add(self.eqns.x[bin_i0], a * self.eqns.x[bin_i1]) + } + + pub fn clear(&mut self) { + self.eqns.clear(); + self.num_equations = 0; + self.total = 0f64; + } + + #[must_use] + fn get_bin_index(&self, value: f64) -> f64 { + let max = 255f64; + let val = clamp(value, 0f64, max); + (self.num_bins - 1) as f64 * val / max + } + + fn update_piecewise_linear_residual( + &self, + lut: &NoiseStrengthLut, + residual: &mut [f64], + start: usize, + end: usize, + ) { + let dx = 255f64 / self.num_bins as f64; + #[allow(clippy::needless_range_loop)] + for i in start.max(1)..end.min(lut.points.len() - 1) { + let lower = 0usize.max(self.get_bin_index(lut.points[i - 1][0]).floor() as usize); + let upper = + (self.num_bins - 1).min(self.get_bin_index(lut.points[i + 1][0]).ceil() as usize); + let mut r = 0f64; + for j in lower..=upper { + let x = self.get_center(j); + if x < lut.points[i - 1][0] || x >= lut.points[i + 1][0] { + continue; + } + + let y = self.eqns.x[j]; + let a = (x - lut.points[i - 1][0]) / (lut.points[i + 1][0] - lut.points[i - 1][0]); + let estimate_y = lut.points[i - 1][1].mul_add(1f64 - a, lut.points[i + 1][1] * a); + r += (y - estimate_y).abs(); + } + residual[i] = r * dx; + } + } + + #[must_use] + fn get_center(&self, i: usize) -> f64 { + let range = 255f64; + let n = self.num_bins; + i as f64 / (n - 1) as f64 * range + } +} + +impl Add<&StrengthSolver> for StrengthSolver { + type Output = StrengthSolver; + + fn add(self, addend: &StrengthSolver) -> Self::Output { + let mut dest = self; + dest.eqns += &addend.eqns; + dest.num_equations += addend.num_equations; + dest.total += addend.total; + dest + } +} + +impl AddAssign<&StrengthSolver> for StrengthSolver { + fn add_assign(&mut self, rhs: &StrengthSolver) { + *self = self.clone() + rhs; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/vapoursynth.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/vapoursynth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff/vapoursynth.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff/vapoursynth.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,180 @@ +use std::path::Path; + +use anyhow::{bail, ensure, Result}; +use num_rational::Rational64; +use v_frame::{frame::Frame, plane::Plane}; +use vapoursynth::{ + format::Format, + prelude::{ColorFamily, Environment, EvalFlags, FrameRef, Property}, + video_info::VideoInfo, +}; + +use super::{ColorFormat, PixelFormat, VideoSource}; + +const OUTPUT_INDEX: i32 = 0i32; + +pub(super) struct VapoursynthSource { + env: Environment, +} + +impl VapoursynthSource { + pub(super) fn open(source: &Path) -> Result { + let mut env = Environment::new()?; + env.eval_file(source, EvalFlags::SetWorkingDir)?; + + Ok(VapoursynthSource { env }) + } +} + +impl VideoSource for VapoursynthSource { + fn read_frame(&mut self, frameno: usize) -> Result>> { + let (node, _) = self.env.get_output(OUTPUT_INDEX)?; + Ok(node + .get_frame(frameno) + .map(|frame| Some(vs_frame_to_v_frame(&frame)))?) + } + + fn get_frame_count(&mut self) -> Result { + let info = vs_get_clip_info(&mut self.env)?; + + let num_frames = { + if Property::Variable == info.format { + bail!("Cannot handle clips with varying format"); + } + if Property::Variable == info.resolution { + bail!("Cannot handle clips with varying dimensions"); + } + if Property::Variable == info.framerate { + bail!("Cannot handle clips with varying framerate"); + } + + info.num_frames + }; + + ensure!(num_frames > 0, "vapoursynth reported 0 frames"); + + Ok(num_frames) + } + + fn get_frame_rate(&mut self) -> Result { + let info = vs_get_clip_info(&mut self.env)?; + + match info.framerate { + Property::Variable => bail!("Cannot output clips with varying framerate"), + Property::Constant(fps) => Ok(Rational64::new( + fps.numerator as i64, + fps.denominator as i64, + )), + } + } + + fn get_resolution(&mut self) -> Result<(u32, u32)> { + let info = vs_get_clip_info(&mut self.env)?; + + let resolution = { + match info.resolution { + Property::Variable => { + bail!("Cannot output clips with variable resolution"); + } + Property::Constant(x) => x, + } + }; + + Ok((resolution.width as u32, resolution.height as u32)) + } + + fn get_pixel_format(&mut self) -> Result { + let info = vs_get_clip_info(&mut self.env)?; + + ColorFormat::try_from(info.format) + } +} + +impl TryFrom>> for ColorFormat { + type Error = anyhow::Error; + + fn try_from(format: Property) -> Result { + match format { + Property::Variable => bail!("Variable pixel format not supported"), + Property::Constant(x) => ColorFormat::try_from(x), + } + } +} + +impl TryFrom> for ColorFormat { + type Error = anyhow::Error; + + fn try_from(format: Format) -> Result { + Ok(match format.color_family() { + ColorFamily::Gray => ColorFormat { + pixel_format: PixelFormat::YUV400, + bit_depth: format.bits_per_sample(), + }, + ColorFamily::YUV => ColorFormat { + pixel_format: match format.sub_sampling_h() + format.sub_sampling_w() { + 0 => PixelFormat::YUV444, + 1 => PixelFormat::YUV422, + 2 => PixelFormat::YUV420, + _ => unreachable!(), + }, + bit_depth: format.bits_per_sample(), + }, + _ => bail!("Only YUV clips are supported"), + }) + } +} + +fn vs_get_clip_info(env: &mut Environment) -> Result { + // Get the output node. + let (node, _) = env.get_output(OUTPUT_INDEX)?; + + Ok(node.info()) +} + +fn vs_frame_to_v_frame(in_frame: &FrameRef) -> Frame { + let mut planes = [ + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + ]; + let format = + ColorFormat::try_from(in_frame.format()).expect("Color format has already been checked"); + for p in 0..format.pixel_format.planes() { + let xdec = if p > 0 { + format.pixel_format.subsampling().0 + } else { + 0 + }; + let ydec = if p > 0 { + format.pixel_format.subsampling().1 + } else { + 0 + }; + let mut plane: Plane = Plane::new( + in_frame.width(p) as usize >> xdec, + in_frame.height(p) as usize >> ydec, + xdec, + ydec, + 0usize, + 0usize, + ); + + if format.bit_depth == 8 { + let in_data: &[u8] = in_frame.plane(p).unwrap(); + assert!(plane.data.len() == in_data.len()); + plane.data_origin_mut().copy_from_slice(in_data); + } else { + let in_data: &[u16] = in_frame.plane(p).unwrap(); + assert!(plane.data.len() == in_data.len()); + in_data + .iter() + .zip(plane.data_origin_mut().iter_mut()) + .for_each(|(i, o)| { + *o = (i >> (format.bit_depth - 8)) as u8; + }); + } + + planes[p] = plane; + } + Frame { planes } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/diff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/diff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +use anyhow::{ensure, Result}; +use num_rational::Rational64; +use v_frame::{frame::Frame, pixel::Pixel}; + +use self::solver::{FlatBlockFinder, NoiseModel}; +use crate::{util::frame_into_u8, GrainTableSegment}; + +mod solver; + +const BLOCK_SIZE: usize = 32; +const BLOCK_SIZE_SQUARED: usize = BLOCK_SIZE * BLOCK_SIZE; + +pub struct DiffGenerator { + fps: Rational64, + source_bit_depth: usize, + denoised_bit_depth: usize, + frame_count: usize, + prev_timestamp: u64, + flat_block_finder: FlatBlockFinder, + noise_model: NoiseModel, + grain_table: Vec, +} + +impl DiffGenerator { + #[must_use] + #[inline] + pub fn new(fps: Rational64, source_bit_depth: usize, denoised_bit_depth: usize) -> Self { + Self { + frame_count: 0, + fps, + flat_block_finder: FlatBlockFinder::new(), + noise_model: NoiseModel::new(), + grain_table: Vec::new(), + prev_timestamp: 0, + source_bit_depth, + denoised_bit_depth, + } + } + + /// Processes the next frame and adds the results to the state of this + /// `DiffGenerator`. + /// + /// # Errors + /// - If the frames do not have the same resolution + /// - If the frames do not have the same chroma subsampling + #[inline] + pub fn diff_frame( + &mut self, + source: &Frame, + denoised: &Frame, + ) -> Result<()> { + self.diff_frame_internal( + &frame_into_u8(source, self.source_bit_depth), + &frame_into_u8(denoised, self.denoised_bit_depth), + ) + } + + /// Finalize the state of this `DiffGenerator` and return the resulting + /// grain table segments. + #[must_use] + #[inline] + pub fn finish(mut self) -> Vec { + log::debug!("Updating final parameters"); + self.grain_table.push( + self.noise_model + .get_grain_parameters(self.prev_timestamp, i64::MAX as u64), + ); + + self.grain_table + } + + fn diff_frame_internal(&mut self, source: &Frame, denoised: &Frame) -> Result<()> { + verify_dimensions_match(source, denoised)?; + + let (flat_blocks, num_flat_blocks) = self.flat_block_finder.run(&source.planes[0]); + log::debug!("Num flat blocks: {num_flat_blocks}"); + + log::debug!("Updating noise model"); + let status = self.noise_model.update(source, denoised, &flat_blocks); + + if status == NoiseStatus::DifferentType { + let cur_timestamp = self.frame_count as u64 * 10_000_000u64 * *self.fps.denom() as u64 + / *self.fps.numer() as u64; + log::debug!( + "Updating parameters for times {} to {}", + self.prev_timestamp, + cur_timestamp + ); + self.grain_table.push( + self.noise_model + .get_grain_parameters(self.prev_timestamp, cur_timestamp), + ); + self.noise_model.save_latest(); + self.prev_timestamp = cur_timestamp; + } + log::debug!("Noise model updated for frame {}", self.frame_count); + self.frame_count += 1; + + Ok(()) + } +} + +#[derive(Debug)] +enum NoiseStatus { + Ok, + DifferentType, + #[allow(dead_code)] + Error(anyhow::Error), +} + +impl PartialEq for NoiseStatus { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (&Self::Error(_), &Self::Error(_)) => true, + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} + +fn verify_dimensions_match(source: &Frame, denoised: &Frame) -> Result<()> { + let res_1 = (source.planes[0].cfg.width, source.planes[0].cfg.height); + let res_2 = (denoised.planes[0].cfg.width, denoised.planes[0].cfg.height); + ensure!( + res_1 == res_2, + "Luma resolutions were not equal, {}x{} != {}x{}", + res_1.0, + res_1.1, + res_2.0, + res_2.1 + ); + + let res_1 = (source.planes[1].cfg.width, source.planes[1].cfg.height); + let res_2 = (denoised.planes[1].cfg.width, denoised.planes[1].cfg.height); + ensure!( + res_1 == res_2, + "Chroma resolutions were not equal, {}x{} != {}x{}", + res_1.0, + res_1.1, + res_2.0, + res_2.1 + ); + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/estimate.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/estimate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/estimate.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/estimate.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,71 @@ +use std::{f64::consts::PI, mem::size_of}; + +use v_frame::{ + plane::Plane, + prelude::{CastFromPrimitive, Pixel}, +}; + +/// Estimates the amount of noise within a plane. +/// Returns `None` if a reliable estimate cannot be obtained +/// due to too few smooth pixels. +/// +/// Ranges seem to be approximately: +/// +/// - `0.0..0.5` = no noticeable noise +/// - `0.5..1.0` = light noise, probably photon-noise-esque +/// +/// # Panics +/// - If called with a `bit_depth` not between `8..=16` +#[must_use] +pub fn estimate_plane_noise(plane: &Plane, bit_depth: usize) -> Option { + const EDGE_THRESHOLD: u16 = 50; + + if size_of::() == 1 { + assert_eq!(bit_depth, 8); + } else if size_of::() == 2 { + assert!(bit_depth > 8 && bit_depth <= 16); + } else { + unimplemented!("Bit depths greater than 16 are not currently supported"); + } + + let width = plane.cfg.width; + let height = plane.cfg.height; + let stride = plane.cfg.stride; + + let mut accum = 0u64; + let mut count = 0u64; + for i in 1..(height - 1) { + for j in 1..(width - 1) { + // Setup a small 3x3 matrix. + let center_idx = (i * stride + j) as isize; + let mut mat = [[0i16; 3]; 3]; + for ii in -1isize..=1isize { + for jj in -1isize..=1isize { + let idx = (center_idx + ii * stride as isize + jj) as usize; + mat[(ii + 1) as usize][(jj + 1) as usize] = if size_of::() == 1 { + i16::cast_from(plane.data_origin()[idx]) + } else { + (u16::cast_from(plane.data_origin()[idx]) >> (bit_depth - 8usize)) as i16 + }; + } + } + + // Compute sobel gradients + let g_x = + (mat[0][0] - mat[0][2]) + (mat[2][0] - mat[2][2]) + 2 * (mat[1][0] - mat[1][2]); + let g_y = + (mat[0][0] - mat[2][0]) + (mat[0][2] - mat[2][2]) + 2 * (mat[0][1] - mat[2][1]); + let g_a = (g_x.abs() + g_y.abs()) as u16; + // Accumulate Laplacian + if g_a < EDGE_THRESHOLD { + // Only count smooth pixels + let v = 4 * mat[1][1] - 2 * (mat[0][1] + mat[2][1] + mat[1][0] + mat[1][2]) + + (mat[0][0] + mat[0][2] + mat[2][0] + mat[2][2]); + accum += u64::from(v.unsigned_abs()); + count += 1; + } + } + } + + (count >= 16).then(|| accum as f64 / (6u64 * count) as f64 * (PI / 2f64).sqrt()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,114 @@ +// Copyright (c) 2022-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(feature = "create")] +mod create; +#[cfg(feature = "diff")] +mod diff; +#[cfg(all(feature = "estimate", feature = "unstable"))] +mod estimate; +#[cfg(feature = "parse")] +mod parse; +mod util; + +use arrayvec::ArrayVec; +#[cfg(feature = "create")] +pub use create::*; +#[cfg(feature = "diff")] +pub use diff::*; +#[cfg(all(feature = "estimate", feature = "unstable"))] +pub use estimate::*; +#[cfg(feature = "parse")] +pub use parse::*; +#[cfg(any(feature = "diff", feature = "estimate"))] +pub use v_frame; + +/// The max number of luma scaling points for grain synthesis +pub const NUM_Y_POINTS: usize = 14; +/// The max number of scaling points per chroma plane for grain synthesis +pub const NUM_UV_POINTS: usize = 10; +/// The max number of luma coefficients for grain synthesis +pub const NUM_Y_COEFFS: usize = 24; +/// The max number of coefficients per chroma plane for grain synthesis +pub const NUM_UV_COEFFS: usize = 25; + +/// A randomly generated u16 to be used as a starting random seed +/// for grain synthesis. The idea behind using a constant random seed +/// is so that encodes are deterministic and reproducible. +pub const DEFAULT_GRAIN_SEED: u16 = 10956; + +pub type ScalingPoints = ArrayVec<[u8; 2], NUM_Y_POINTS>; + +/// Specifies parameters for enabling decoder-side grain synthesis for +/// a segment of video from `start_time` to `end_time`. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] +pub struct GrainTableSegment { + /// The beginning timestamp of this segment, in 10,000,000ths of a second. + pub start_time: u64, + /// The ending timestamp of this segment, not inclusive, in 10,000,000ths of + /// a second. + pub end_time: u64, + + /// Values for the cutoffs and scale factors for luma scaling points + pub scaling_points_y: ArrayVec<[u8; 2], NUM_Y_POINTS>, + /// Values for the cutoffs and scale factors for Cb scaling points + pub scaling_points_cb: ArrayVec<[u8; 2], NUM_UV_POINTS>, + /// Values for the cutoffs and scale factors for Cr scaling points + pub scaling_points_cr: ArrayVec<[u8; 2], NUM_UV_POINTS>, + + /// Determines the range and quantization step of the standard deviation + /// of film grain. + /// + /// Accepts values between `8..=11`. + pub scaling_shift: u8, + + /// A factor specifying how many AR coefficients are provided, + /// based on the forumla `coeffs_len = (2 * ar_coeff_lag * (ar_coeff_lag + + /// 1))`. + /// + /// Accepts values between `0..=3`. + pub ar_coeff_lag: u8, + /// Values for the AR coefficients for luma scaling points + pub ar_coeffs_y: ArrayVec, + /// Values for the AR coefficients for Cb scaling points + pub ar_coeffs_cb: ArrayVec, + /// Values for the AR coefficients for Cr scaling points + pub ar_coeffs_cr: ArrayVec, + /// Shift value: Specifies the range of acceptable AR coefficients + /// 6: [-2, 2) + /// 7: [-1, 1) + /// 8: [-0.5, 0.5) + /// 9: [-0.25, 0.25) + pub ar_coeff_shift: u8, + /// Multiplier to the grain strength of the Cb plane + pub cb_mult: u8, + /// Multiplier to the grain strength of the Cb plane inherited from the luma + /// plane + pub cb_luma_mult: u8, + /// A base value for the Cb plane grain + pub cb_offset: u16, + /// Multiplier to the grain strength of the Cr plane + pub cr_mult: u8, + /// Multiplier to the grain strength of the Cr plane inherited from the luma + /// plane + pub cr_luma_mult: u8, + /// A base value for the Cr plane grain + pub cr_offset: u16, + + /// Whether film grain blocks should overlap or not + pub overlap_flag: bool, + /// Scale chroma grain from luma instead of providing chroma scaling points + pub chroma_scaling_from_luma: bool, + /// Specifies how much the Gaussian random numbers should be scaled down + /// during the grain synthesis process. + pub grain_scale_shift: u8, + /// Random seed used for generating grain + pub random_seed: u16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/parse.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/parse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/parse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/parse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,797 @@ +// Copyright (c) 2022-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use arrayvec::ArrayVec; +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{char, digit1, line_ending, multispace0, multispace1, space0, space1}, + combinator::{eof, map_res, opt, recognize}, + error::{Error as NomError, ErrorKind, FromExternalError, ParseError}, + multi::{many1, separated_list0, separated_list1}, + sequence::{delimited, preceded}, + AsChar, Compare, Err as NomErr, IResult, Input, Parser, +}; + +use crate::{GrainTableSegment, NUM_UV_COEFFS, NUM_UV_POINTS, NUM_Y_COEFFS, NUM_Y_POINTS}; + +/// This file has the implementation details of the grain table. +/// +/// The file format is an ascii representation for readability and +/// editability. Array parameters are separated from the non-array +/// parameters and prefixed with a few characters to make for easy +/// localization with a parameter set. Each entry is prefixed with "E" +/// and the other parameters are only specified if "apply-grain" is +/// non-zero. +/// +/// ```text +/// filmgrn1 +/// E +/// p ... +/// sY ... +/// sCb ... +/// sCr ... +/// cY .... +/// cCb .... +/// cCr .... +/// E ... +/// ``` +/// +/// # Errors +/// +/// - If the file cannot be opened +/// - If the file does not contain a properly formatted film grain table +#[inline] +pub fn parse_grain_table(input: &str) -> anyhow::Result> { + let (input, _) = grain_table_header(input).map_err(|e| anyhow::anyhow!(e.to_string()))?; + let (_, segments) = many1(grain_table_segment) + .parse(input) + .map_err(|e| anyhow::anyhow!(e.to_string()))?; + Ok(segments.into_iter().flatten().collect()) +} + +fn grain_table_header(input: &str) -> IResult<&str, ()> { + let (input, _) = delimited(multispace0, tag("filmgrn1"), line_ending).parse(input)?; + Ok((input, ())) +} + +fn line, F>(parser: F) -> impl Parser +where + I: Input + Clone + Compare<&'static str>, + ::Item: AsChar + Clone, + F: Parser, +{ + delimited(multispace0, parser, alt((line_ending, eof))) +} + +fn grain_table_segment(input: &str) -> IResult<&str, Option> { + let (input, e_params) = e_params(input)?; + if !e_params.apply { + // I'm not sure *why* there's even an option to generate a film grain config + // that doesn't apply film grain. But, well, I didn't make this format. + return Ok((input, None)); + } + + let (input, p_params) = p_params(input)?; + let (input, s_y_params) = s_y_params(input)?; + let (input, s_cb_params) = s_cb_params(input)?; + let (input, s_cr_params) = s_cr_params(input)?; + let coeff_count = (2 * p_params.ar_coeff_lag * (p_params.ar_coeff_lag + 1)) as usize; + let (input, c_y_params) = c_y_params(input, coeff_count)?; + let (input, c_cb_params) = c_cb_params(input, coeff_count)?; + let (input, c_cr_params) = c_cr_params(input, coeff_count)?; + + Ok(( + input, + Some(GrainTableSegment { + start_time: e_params.start, + end_time: e_params.end, + scaling_points_y: s_y_params, + scaling_points_cb: s_cb_params, + scaling_points_cr: s_cr_params, + scaling_shift: p_params.scaling_shift, + ar_coeff_lag: p_params.ar_coeff_lag, + ar_coeffs_y: c_y_params, + ar_coeffs_cb: c_cb_params, + ar_coeffs_cr: c_cr_params, + ar_coeff_shift: p_params.ar_coeff_shift, + cb_mult: p_params.cb_mult, + cb_luma_mult: p_params.cb_luma_mult, + cb_offset: p_params.cb_offset, + cr_mult: p_params.cr_mult, + cr_luma_mult: p_params.cr_luma_mult, + cr_offset: p_params.cr_offset, + overlap_flag: p_params.overlap_flag, + chroma_scaling_from_luma: p_params.chroma_scaling_from_luma, + grain_scale_shift: p_params.grain_scale_shift, + random_seed: e_params.seed, + }), + )) +} + +#[derive(Debug, Clone, Copy)] +struct EParams { + pub start: u64, + pub end: u64, + pub apply: bool, + pub seed: u16, +} + +fn e_params(input: &str) -> IResult<&str, EParams> { + let (input, params) = map_res( + line(preceded( + tag("E"), + preceded(space1, separated_list1(space1, digit1)), + )), + |items: Vec<&str>| { + if items.len() != 5 { + return Err(NomErr::>::Failure( + NomError::from_external_error( + input, + ErrorKind::Verify, + "Expected 5 values on E line", + ), + )); + } + let parsed = EParams { + start: items[0].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse start_time", + )) + })?, + end: items[1].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse end_time", + )) + })?, + apply: items[2].parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse apply_grain", + )) + })? > 0, + seed: items[3].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse random_seed", + )) + })?, + }; + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + if params.end < params.start { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + "Start time must be before end time", + ))); + } + + Ok((input, params)) +} + +#[derive(Debug, Clone, Copy)] +struct PParams { + ar_coeff_lag: u8, + ar_coeff_shift: u8, + grain_scale_shift: u8, + scaling_shift: u8, + chroma_scaling_from_luma: bool, + overlap_flag: bool, + cb_mult: u8, + cb_luma_mult: u8, + cb_offset: u16, + cr_mult: u8, + cr_luma_mult: u8, + cr_offset: u16, +} + +#[allow(clippy::too_many_lines)] +fn p_params(input: &str) -> IResult<&str, PParams> { + let (input, params) = map_res( + line(preceded( + tag("p"), + preceded(space1, separated_list1(space1, digit1)), + )), + |items: Vec<&str>| { + if items.len() != 12 { + return Err(NomErr::>::Failure( + NomError::from_external_error( + input, + ErrorKind::Verify, + "Expected 12 values on p line", + ), + )); + } + + let parsed = PParams { + ar_coeff_lag: items[0].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse ar_coeff_lag", + )) + })?, + ar_coeff_shift: items[1].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse ar_coeff_shift", + )) + })?, + grain_scale_shift: items[2].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse grain_scale_shift", + )) + })?, + scaling_shift: items[3].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse scaling_shift", + )) + })?, + chroma_scaling_from_luma: items[4].parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse chroma_scaling_from_luma", + )) + })? > 0, + overlap_flag: items[5].parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse overlap_flag", + )) + })? > 0, + cb_mult: items[6].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cb_mult", + )) + })?, + cb_luma_mult: items[7].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cb_luma_mult", + )) + })?, + cb_offset: items[8].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cb_offset", + )) + })?, + cr_mult: items[9].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cr_mult", + )) + })?, + cr_luma_mult: items[10].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cr_luma_mult", + )) + })?, + cr_offset: items[11].parse().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse cr_offset", + )) + })?, + }; + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + if params.scaling_shift < 8 || params.scaling_shift > 11 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + "scaling_shift must be between 8 and 11", + ))); + } + if params.ar_coeff_lag > 3 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + "ar_coeff_lag must be between 0 and 3", + ))); + } + if params.ar_coeff_shift < 6 || params.ar_coeff_shift > 9 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + "ar_coeff_shift must be between 6 and 9", + ))); + } + + Ok((input, params)) +} + +fn s_y_params(input: &str) -> IResult<&str, ArrayVec<[u8; 2], NUM_Y_POINTS>> { + let (input, values) = map_res( + line(preceded( + tag("sY"), + preceded(space1, separated_list1(space1, digit1)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Y-plane points", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + let len = values[0] as usize; + if values.len() != len * 2 + 1 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!( + "Expected {} Y-plane points, got {}", + len * 2, + values.len() - 1 + ), + ))); + } + + Ok(( + input, + values[1..] + .chunks_exact(2) + .map(|chunk| [chunk[0], chunk[1]]) + .collect(), + )) +} + +fn s_cb_params(input: &str) -> IResult<&str, ArrayVec<[u8; 2], NUM_UV_POINTS>> { + let (input, values) = map_res( + line(preceded( + tag("sCb"), + preceded(space1, separated_list1(space1, digit1)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Cb-plane points", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + let len = values[0] as usize; + if values.len() != len * 2 + 1 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!( + "Expected {} Cb-plane points, got {}", + len * 2, + values.len() - 1 + ), + ))); + } + + Ok(( + input, + values[1..] + .chunks_exact(2) + .map(|chunk| [chunk[0], chunk[1]]) + .collect(), + )) +} + +fn s_cr_params(input: &str) -> IResult<&str, ArrayVec<[u8; 2], NUM_UV_POINTS>> { + let (input, values) = map_res( + line(preceded( + tag("sCr"), + preceded(space1, separated_list1(space1, digit1)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Cr-plane points", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + let len = values[0] as usize; + if values.len() != len * 2 + 1 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!( + "Expected {} Cr-plane points, got {}", + len * 2, + values.len() - 1 + ), + ))); + } + + Ok(( + input, + values[1..] + .chunks_exact(2) + .map(|chunk| [chunk[0], chunk[1]]) + .collect(), + )) +} + +fn integer(input: &str) -> IResult<&str, &str> { + recognize(preceded(opt(char('-')), digit1)).parse(input) +} + +fn c_y_params(input: &str, count: usize) -> IResult<&str, ArrayVec> { + let (input, values) = map_res( + line(preceded( + tag("cY"), + preceded(space0, separated_list0(multispace1, integer)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Y-plane coeffs", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + if values.len() != count { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!("Expected {} Y-plane coeffs, got {}", count, values.len()), + ))); + } + + Ok((input, values.into_iter().collect())) +} + +fn c_cb_params(input: &str, count: usize) -> IResult<&str, ArrayVec> { + let (input, values) = map_res( + line(preceded( + tag("cCb"), + preceded(space1, separated_list1(multispace1, integer)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Cb-plane coeffs", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + if values.len() != count + 1 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!( + "Expected {} Cb-plane coeffs, got {}", + count + 1, + values.len() + ), + ))); + } + + Ok((input, values.into_iter().collect())) +} + +fn c_cr_params(input: &str, count: usize) -> IResult<&str, ArrayVec> { + let (input, values) = map_res( + line(preceded( + tag("cCr"), + preceded(space1, separated_list1(multispace1, integer)), + )), + |items: Vec<&str>| { + let mut parsed = Vec::with_capacity(items.len()); + for item in items { + parsed.push(item.parse::().map_err(|_e| { + NomErr::>::Failure(NomError::from_external_error( + input, + ErrorKind::Digit, + "Failed to parse Cr-plane coeffs", + )) + })?); + } + Ok::<_, NomErr>>(parsed) + }, + ) + .parse(input)?; + + if values.len() != count + 1 { + return Err(NomErr::Failure(NomError::from_external_error( + input, + ErrorKind::Verify, + format!( + "Expected {} Cr-plane coeffs, got {}", + count + 1, + values.len() + ), + ))); + } + + Ok((input, values.into_iter().collect())) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_luma_only_table() { + // This is the luma-only table format generated by + // both aomenc's photon noise utility and by av1an. + let input = r#"filmgrn1 +E 0 9223372036854775807 1 7391 1 + p 0 6 0 8 0 1 0 0 0 0 0 0 + sY 14 0 20 20 5 39 4 59 3 78 3 98 3 118 3 137 3 157 3 177 3 196 3 216 4 235 4 255 4 + sCb 0 + sCr 0 + cY + cCb 0 + cCr 0 +"#; + let expected = GrainTableSegment { + start_time: 0, + end_time: 9_223_372_036_854_775_807, + scaling_points_y: ArrayVec::from([ + [0, 20], + [20, 5], + [39, 4], + [59, 3], + [78, 3], + [98, 3], + [118, 3], + [137, 3], + [157, 3], + [177, 3], + [196, 3], + [216, 4], + [235, 4], + [255, 4], + ]), + scaling_points_cb: ArrayVec::new(), + scaling_points_cr: ArrayVec::new(), + scaling_shift: 8, + ar_coeff_lag: 0, + ar_coeffs_y: ArrayVec::new(), + ar_coeffs_cb: ArrayVec::try_from([0].as_slice()).expect("Arrayvec has capacity"), + ar_coeffs_cr: ArrayVec::try_from([0].as_slice()).expect("Arrayvec has capacity"), + ar_coeff_shift: 6, + cb_mult: 0, + cb_luma_mult: 0, + cb_offset: 0, + cr_mult: 0, + cr_luma_mult: 0, + cr_offset: 0, + overlap_flag: true, + chroma_scaling_from_luma: false, + grain_scale_shift: 0, + random_seed: 7391, + }; + let output = parse_grain_table(input).expect("Test failed"); + assert_eq!(vec![expected], output); + } + + #[test] + fn parse_luma_chroma_table() { + // This is the luma+chroma table format generated by + // both aomenc's photon noise utility and by av1an. + let input = r#"filmgrn1 +E 0 9223372036854775807 1 7391 1 + p 0 6 0 8 0 1 128 192 256 128 192 256 + sY 14 0 0 20 4 39 3 59 3 78 3 98 3 118 4 137 4 157 4 177 4 196 4 216 5 235 5 255 5 + sCb 10 0 0 28 0 57 0 85 0 113 0 142 0 170 0 198 0 227 0 255 1 + sCr 10 0 0 28 0 57 0 85 0 113 0 142 0 170 0 198 0 227 0 255 1 + cY + cCb 0 + cCr 0 +"#; + let expected = GrainTableSegment { + start_time: 0, + end_time: 9_223_372_036_854_775_807, + scaling_points_y: ArrayVec::from([ + [0, 0], + [20, 4], + [39, 3], + [59, 3], + [78, 3], + [98, 3], + [118, 4], + [137, 4], + [157, 4], + [177, 4], + [196, 4], + [216, 5], + [235, 5], + [255, 5], + ]), + scaling_points_cb: ArrayVec::from([ + [0, 0], + [28, 0], + [57, 0], + [85, 0], + [113, 0], + [142, 0], + [170, 0], + [198, 0], + [227, 0], + [255, 1], + ]), + scaling_points_cr: ArrayVec::from([ + [0, 0], + [28, 0], + [57, 0], + [85, 0], + [113, 0], + [142, 0], + [170, 0], + [198, 0], + [227, 0], + [255, 1], + ]), + scaling_shift: 8, + ar_coeff_lag: 0, + ar_coeffs_y: ArrayVec::new(), + ar_coeffs_cb: ArrayVec::try_from([0].as_slice()).expect("Arrayvec has capacity"), + ar_coeffs_cr: ArrayVec::try_from([0].as_slice()).expect("Arrayvec has capacity"), + ar_coeff_shift: 6, + cb_mult: 128, + cb_luma_mult: 192, + cb_offset: 256, + cr_mult: 128, + cr_luma_mult: 192, + cr_offset: 256, + overlap_flag: true, + chroma_scaling_from_luma: false, + grain_scale_shift: 0, + random_seed: 7391, + }; + let output = parse_grain_table(input).expect("Test failed"); + assert_eq!(vec![expected], output); + } + + #[test] + fn parse_complex_table() { + let input = r#"filmgrn1 +E 0 417083 1 7391 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 6 0 53 13 53 40 64 94 49 121 46 255 46 + sCb 2 0 14 255 13 + sCr 2 0 12 255 14 + cY 1 -4 1 4 8 3 -2 -6 9 14 -27 -25 -2 4 5 15 -80 94 28 -3 -2 6 -47 121 + cCb -3 1 -4 6 -1 2 -2 1 11 -10 -2 -16 -1 3 -2 -14 -26 65 19 -3 -5 2 -6 75 -1 + cCr 0 0 -4 8 -1 0 1 2 -1 -9 4 -7 -5 -2 -5 -14 0 45 18 3 -3 4 8 49 5 +E 417083 7090416 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 4 0 46 40 54 108 39 255 38 + sCb 2 0 14 255 14 + sCr 2 0 12 255 14 + cY 1 -4 1 5 8 4 -2 -6 9 13 -28 -28 -5 5 5 13 -76 91 32 -1 -3 7 -50 124 + cCb -2 1 -3 3 -2 1 -1 2 8 -10 0 -12 -2 2 -1 -14 -20 61 18 -1 -4 -2 -1 70 -1 + cCr 0 0 -3 6 -1 -1 0 1 -2 -8 6 -4 -5 -2 -6 -12 4 41 17 4 -2 3 13 44 5 +E 7090416 7507500 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 4 0 54 40 64 108 46 255 44 + sCb 2 0 14 255 13 + sCr 2 0 12 255 14 + cY 1 -4 2 3 7 3 -2 -6 9 14 -26 -25 -3 5 6 15 -81 95 27 -3 -3 5 -46 121 + cCb -2 1 -4 4 -2 1 -1 2 9 -12 3 -13 -1 2 -2 -16 -26 66 17 -2 -5 -1 1 73 0 + cCr 1 -1 -5 8 -1 -1 1 1 -3 -9 9 -5 -6 -2 -7 -14 1 44 17 3 -3 5 15 46 4 +E 7507500 10010000 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 4 0 49 40 59 108 43 255 41 + sCb 2 0 14 255 14 + sCr 2 0 13 255 15 + cY 1 -4 0 6 8 3 -2 -5 8 14 -29 -26 -3 4 3 15 -76 92 29 -2 -3 8 -49 121 + cCb -3 0 -3 6 0 1 -2 1 10 -9 -4 -15 -1 2 -1 -13 -22 62 20 -3 -4 2 -7 73 -1 + cCr -1 0 -3 6 0 0 0 2 0 -9 2 -7 -5 -1 -4 -14 0 45 19 2 -2 3 7 50 4 +E 10010000 13346666 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 6 0 33 27 39 40 53 54 55 108 52 255 52 + sCb 2 0 16 255 14 + sCr 2 0 11 255 12 + cY 1 -4 1 5 9 4 -2 -7 12 11 -27 -30 -5 5 6 10 -73 89 35 -1 -3 6 -49 124 + cCb -2 0 -2 1 -2 1 -2 0 9 -9 -2 -14 -1 2 0 -11 -26 65 18 -2 -4 -2 -8 75 -5 + cCr 0 0 -4 5 -2 0 1 3 -1 -9 6 -5 -5 -1 -6 -14 1 43 18 4 -3 3 13 49 3 +E 13346666 16683333 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 6 0 36 27 42 40 58 54 60 108 57 255 57 + sCb 2 0 15 255 14 + sCr 4 0 11 40 17 94 13 255 13 + cY 1 -4 1 5 8 3 -2 -6 10 12 -27 -27 -4 4 5 12 -73 90 32 -2 -3 6 -47 121 + cCb -2 0 -3 4 -1 1 -2 0 10 -9 -2 -14 1 3 -1 -10 -24 62 16 -2 -4 0 -6 72 -7 + cCr 0 0 -3 6 -1 0 1 3 1 -9 3 -7 -5 -1 -5 -14 -2 46 19 2 -3 3 7 54 3 +E 16683333 17100416 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 7 0 41 13 41 27 49 40 66 54 68 108 65 255 65 + sCb 2 0 18 255 14 + sCr 4 0 11 40 18 67 14 255 13 + cY 0 -3 1 4 7 3 -2 -5 7 13 -27 -23 -3 4 5 15 -79 94 26 -3 -2 5 -45 120 + cCb -1 -2 -1 1 0 0 -3 -2 12 -6 -3 -15 3 2 2 -8 -42 75 12 -3 -4 -2 -8 82 -3 + cCr 0 0 -5 7 -2 0 1 3 0 -11 6 -7 -5 -1 -6 -15 -5 48 18 2 -3 3 10 55 2 +E 17100416 20020000 1 0 1 + p 3 7 0 11 0 1 128 192 256 128 192 256 + sY 6 0 37 27 44 40 61 54 63 108 60 255 60 + sCb 2 0 14 255 14 + sCr 4 0 11 40 18 94 13 255 13 + cY 1 -3 0 6 7 2 -1 -5 7 13 -28 -25 -2 3 3 13 -73 91 29 -2 -2 7 -47 119 + cCb -2 -1 -3 4 0 1 -2 -1 11 -7 -6 -15 1 2 -1 -9 -25 63 16 -3 -4 2 -11 73 -8 + cCr -1 1 -2 6 0 1 0 2 3 -9 -2 -10 -4 0 -3 -14 -6 50 20 0 -3 3 -1 59 3 +E 20020000 9223372036854775807 1 0 1 + p 3 6 0 11 0 1 128 192 256 128 192 256 + sY 6 0 32 27 37 40 50 54 52 121 49 255 49 + sCb 4 0 21 40 23 81 17 255 15 + sCr 2 0 11 255 12 + cY 1 -3 1 2 5 3 -2 -6 8 6 -12 -18 -2 3 5 7 -42 44 21 -3 -1 4 -29 67 + cCb -1 0 1 0 -1 0 -1 0 5 -4 -3 -9 1 1 2 -4 -21 39 10 -2 -3 -2 -7 44 1 + cCr 1 0 -3 2 -3 -1 0 1 -1 -4 5 -2 -1 -1 -5 -6 3 20 10 4 -2 0 9 23 -1"#; + let output = parse_grain_table(input); + assert!(output.is_ok()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/util.rs clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/av1-grain/src/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/av1-grain/src/util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ +#[cfg(feature = "diff")] +use std::{borrow::Cow, mem::size_of}; + +#[cfg(feature = "diff")] +use v_frame::{ + frame::Frame, + prelude::{CastFromPrimitive, ChromaSampling, Pixel}, +}; + +#[cfg(feature = "diff")] +pub fn frame_into_u8(frame: &Frame, bit_depth: usize) -> Cow<'_, Frame> { + if size_of::() == 1 { + assert_eq!(bit_depth, 8); + // SAFETY: We know from the size check that this must be a `Frame` + Cow::Borrowed(unsafe { &*(frame as *const Frame).cast::>() }) + } else if size_of::() == 2 { + assert!(bit_depth > 8 && bit_depth <= 16); + let mut u8_frame: Frame = Frame::new_with_padding( + frame.planes[0].cfg.width, + frame.planes[0].cfg.height, + match frame.planes[1].cfg.xdec + frame.planes[1].cfg.ydec { + 0 => ChromaSampling::Cs444, + 1 => ChromaSampling::Cs422, + 2 => ChromaSampling::Cs420, + _ => unreachable!(), + }, + frame.planes[0].cfg.xpad, + ); + for i in 0..3 { + let out_plane = &mut u8_frame.planes[i]; + for (i, o) in frame.planes[i] + .data_origin() + .iter() + .zip(out_plane.data_origin_mut().iter_mut()) + { + *o = (u16::cast_from(*i) >> (bit_depth - 8usize)) as u8; + } + } + Cow::Owned(u8_frame) + } else { + unimplemented!("Bit depths greater than 16 are not currently supported"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"38e2dc5ed8ed505d563ff3f34dae78feace84aac2ffbe84a27d3e0e4889497c8","Cargo.lock":"08ca7fd7d3bd8de658d89ef64ca04596cdc80253eae38d13ad9417c0c15e696a","Cargo.toml":"f5773cbcc189f9b76bcea4502e2ded6eb7648987e5874a023154e8a756199a62","Cargo.toml.orig":"f5e8f36855de478049bcb5040f23e01dd888361368a3b2933128abec5c12d7e3","LICENSE":"04556ac17ea72a59b51986f9ce00ed6508b714fcdb432e4e76d8bb311c858b69","README.md":"c445640a24c30df40f0e684c8b3f18be99bc640f9126941fbed2627e4dbf65bf","src/boxes.rs":"5da4eda3e81904dae3c90ec1a6a092e6be46123d236858fda738f99fb2e749d6","src/constants.rs":"5f103dea3cb4a420c43bc716daeb4ef7f046e117b9b2ba6ca3566943197fc757","src/lib.rs":"4869f1166a57de04532d16bbd6335d16c9988fbac44eb067e1b1ab8e543be92c","src/writer.rs":"5bffe54e9b0c3cf8562950397d1b24d79efb44af5c3484a5589f136da6fc9070"},"package":"47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f4f4f96e28d0bd8da9e085ec90220708cc49bbbd" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,203 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "avif-parse" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f85ce2a7cd14ac0a30dc29a115de22466aeb8a029410f9f1e4f283443c959d1" +dependencies = [ + "arrayvec", + "bitreader", + "byteorder", + "fallible_collections 0.5.1", + "leb128", + "log", +] + +[[package]] +name = "avif-serialize" +version = "0.8.6" +dependencies = [ + "arrayvec", + "avif-parse", + "mp4parse", +] + +[[package]] +name = "bitreader" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "886559b1e163d56c765bc3a985febb4eee8009f625244511d8ee3c432e08c066" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "fallible_collections" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "fallible_collections" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3e85d14d419ba3e1db925519461c0d17a49bdd2d67ea6316fa965ca7acdf74" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "mp4parse" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63a35203d3c6ce92d5251c77520acb2e57108c88728695aa883f70023624c570" +dependencies = [ + "bitreader", + "byteorder", + "fallible_collections 0.4.9", + "log", + "num-traits", + "static_assertions", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.80" +name = "avif-serialize" +version = "0.8.6" +authors = ["Kornel Lesiński "] +build = false +include = [ + "src/*.rs", + "Cargo.toml", + "README.md", + "LICENSE", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Minimal writer for AVIF header structure (MPEG/HEIF/MIAF/ISO-BMFF)" +homepage = "https://lib.rs/avif-serialize" +readme = "README.md" +keywords = [ + "avif", + "heif", + "bmff", + "av1", + "mux", +] +categories = [ + "multimedia::images", + "encoding", +] +license = "BSD-3-Clause" +repository = "https://github.com/kornelski/avif-serialize" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] + +[badges.maintenance] +status = "passively-maintained" + +[lib] +name = "avif_serialize" +path = "src/lib.rs" + +[dependencies.arrayvec] +version = "0.7.6" + +[dev-dependencies.avif-parse] +version = "1.4.0" + +[dev-dependencies.mp4parse] +version = "0.17" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "avif-serialize" +version = "0.8.6" +authors = ["Kornel Lesiński "] +edition = "2021" +license = "BSD-3-Clause" +description = "Minimal writer for AVIF header structure (MPEG/HEIF/MIAF/ISO-BMFF)" +readme = "README.md" +categories = ["multimedia::images", "encoding"] +keywords = ["avif", "heif", "bmff", "av1", "mux"] +repository = "https://github.com/kornelski/avif-serialize" +homepage = "https://lib.rs/avif-serialize" +include = ["src/*.rs", "Cargo.toml", "README.md", "LICENSE"] +rust-version = "1.80" + +[dependencies] +arrayvec = "0.7.6" + +[dev-dependencies] +mp4parse = "0.17" +avif-parse = "1.4.0" + +[badges] +maintenance = { status = "passively-maintained" } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, Cloudflare, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/README.md clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +# AVIF image serializer (muxer) + +Minimal writer for AVIF header structure. This is lean, safe-Rust alternative to [libavif](https://lib.rs/libavif). +It creates the jungle of MPEG/HEIF/MIAF/ISO-BMFF "boxes" as appropriate for AVIF files. Supports alpha channel embedding. + +Compatible with decoders in Chrome 85+, libavif v0.8.1, and Firefox 92. It's used in [cavif](https://lib.rs/cavif) and other encoders. + +Together with [rav1e](https://lib.rs/rav1e), it allows pure-Rust AVIF image encoding. + +## Requirements + +* [Latest stable](https://rustup.rs) version of Rust. + +## Usage + +1. Compress pixels using an AV1 encoder, such as [rav1e](https://lib.rs/rav1e). [libaom](https://lib.rs/libaom-sys) works too. + +2. Call `avif_serialize::serialize_to_vec(av1_data, None, width, height, 8)` + +See [`ravif` crate sources](https://github.com/kornelski/cavif-rs) for example usage. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/boxes.rs clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/boxes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/boxes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/boxes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,654 @@ +use crate::constants::{ColorPrimaries, MatrixCoefficients, TransferCharacteristics}; +use crate::writer::{Writer, WriterBackend, IO}; +use arrayvec::ArrayVec; +use std::io::Write; +use std::num::NonZeroU32; +use std::{fmt, io}; + +pub trait MpegBox { + fn len(&self) -> usize; + fn write(&self, w: &mut Writer) -> Result<(), B::Error>; +} + +#[derive(Copy, Clone)] +pub struct FourCC(pub [u8; 4]); + +impl fmt::Debug for FourCC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match std::str::from_utf8(&self.0) { + Ok(s) => s.fmt(f), + Err(_) => self.0.fmt(f), + } + } +} + +#[derive(Debug, Clone)] +pub struct AvifFile<'data> { + pub ftyp: FtypBox, + pub meta: MetaBox<'data>, + pub mdat: MdatBox, +} + +impl AvifFile<'_> { + /// Where the primary data starts inside the `mdat` box, for `iloc`'s offset + fn mdat_payload_start_offset(&self) -> u32 { + (self.ftyp.len() + self.meta.len() + + BASIC_BOX_SIZE) as u32 // mdat head + } + + /// `iloc` is mostly unnecssary, high risk of out-of-buffer accesses in parsers that don't pay attention, + /// and also awkward to serialize, because its content depends on its own serialized byte size. + fn fix_iloc_positions(&mut self) { + let start_offset = self.mdat_payload_start_offset(); + self.meta.iloc.absolute_offset_start = NonZeroU32::new(start_offset); + } + + fn write_header(&mut self, out: &mut Vec) -> io::Result<()> { + if self.meta.iprp.ipco.ispe().map_or(true, |b| b.width == 0 || b.height == 0) { + return Err(io::Error::new(io::ErrorKind::InvalidInput, "missing width/height")); + } + + self.fix_iloc_positions(); + + out.try_reserve_exact(self.ftyp.len() + self.meta.len())?; + let mut w = Writer::new(out); + self.ftyp.write(&mut w).map_err(|_| io::ErrorKind::OutOfMemory)?; + self.meta.write(&mut w).map_err(|_| io::ErrorKind::OutOfMemory)?; + Ok(()) + } + + pub fn file_size(&self) -> usize { + self.ftyp.len() + self.meta.len() + self.mdat.len(&self.meta.iloc) + } + + pub fn write_to_vec(&mut self, out: &mut Vec) -> io::Result<()> { + let expected_file_size = self.file_size(); + out.try_reserve_exact(expected_file_size)?; + let initial = out.len(); + self.write_header(out)?; + + let _ = self.mdat.write(&mut Writer::new(out), &self.meta.iloc); + let written = out.len() - initial; + debug_assert_eq!(expected_file_size, written); + Ok(()) + } + + pub fn write(&mut self, mut out: W) -> io::Result<()> { + let mut tmp = Vec::new(); + + self.write_header(&mut tmp)?; + out.write_all(&tmp)?; + drop(tmp); + + self.mdat.write(&mut Writer::new(&mut IO(out)), &self.meta.iloc) + } +} + +const BASIC_BOX_SIZE: usize = 8; +const FULL_BOX_SIZE: usize = BASIC_BOX_SIZE + 4; + +#[derive(Debug, Clone)] +pub struct FtypBox { + pub major_brand: FourCC, + pub minor_version: u32, + pub compatible_brands: ArrayVec, +} + +/// File Type box (chunk) +impl MpegBox for FtypBox { + #[inline(always)] + fn len(&self) -> usize { + BASIC_BOX_SIZE + + 4 // brand + + 4 // ver + + 4 * self.compatible_brands.len() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), *b"ftyp")?; + b.push(&self.major_brand.0)?; + b.u32(self.minor_version)?; + for cb in &self.compatible_brands { + b.push(&cb.0)?; + } + Ok(()) + } +} + +/// Metadata box +#[derive(Debug, Clone)] +pub struct MetaBox<'data> { + pub hdlr: HdlrBox, + pub iloc: IlocBox<'data>, + pub iinf: IinfBox, + pub pitm: PitmBox, + pub iprp: IprpBox, + pub iref: IrefBox, +} + +impl MpegBox for MetaBox<'_> { + #[inline] + fn len(&self) -> usize { + FULL_BOX_SIZE + + self.hdlr.len() + + self.pitm.len() + + self.iloc.len() + + self.iinf.len() + + self.iprp.len() + + if !self.iref.is_empty() { self.iref.len() } else { 0 } + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"meta", 0)?; + self.hdlr.write(&mut b)?; + self.pitm.write(&mut b)?; + self.iloc.write(&mut b)?; + self.iinf.write(&mut b)?; + if !self.iref.is_empty() { + self.iref.write(&mut b)?; + } + self.iprp.write(&mut b) + } +} + +/// Item Info box +#[derive(Debug, Clone)] +pub struct IinfBox { + pub items: ArrayVec, +} + +impl MpegBox for IinfBox { + #[inline] + fn len(&self) -> usize { + FULL_BOX_SIZE + + 2 // num items u16 + + self.items.iter().map(|item| item.len()).sum::() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"iinf", 0)?; + b.u16(self.items.len() as _)?; + for infe in &self.items { + infe.write(&mut b)?; + } + Ok(()) + } +} + +/// Item Info Entry box +#[derive(Debug, Copy, Clone)] +pub struct InfeBox { + pub id: u16, + pub typ: FourCC, + pub name: &'static str, +} + +impl MpegBox for InfeBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + + 2 // id + + 2 // item_protection_index + + 4 // type + + self.name.len() + 1 // nul-terminated + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"infe", 2)?; + b.u16(self.id)?; + b.u16(0)?; + b.push(&self.typ.0)?; + b.push(self.name.as_bytes())?; + b.u8(0) + } +} + +#[derive(Debug, Clone)] +pub struct HdlrBox { +} + +impl MpegBox for HdlrBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + 4 + 4 + 13 + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + // because an image format needs to be told it's an image format, + // and it does it the way classic MacOS used to, because Quicktime. + let mut b = w.full_box(self.len(), *b"hdlr", 0)?; + b.u32(0)?; // old MacOS file type handler + b.push(b"pict")?; // MacOS Quicktime subtype + b.u32(0)?; // Firefox 92 wants all 0 here + b.u32(0)?; // Reserved + b.u32(0)?; // Reserved + b.u8(0)?; // Pascal string for component name + Ok(()) + } +} + +/// Item properties + associations +#[derive(Debug, Clone)] +pub struct IprpBox { + pub ipco: IpcoBox, + pub ipma: IpmaBox, +} + +impl MpegBox for IprpBox { + #[inline(always)] + fn len(&self) -> usize { + BASIC_BOX_SIZE + + self.ipco.len() + + self.ipma.len() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), *b"iprp")?; + self.ipco.write(&mut b)?; + self.ipma.write(&mut b) + } +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum IpcoProp { + Av1C(Av1CBox), + Pixi(PixiBox), + Ispe(IspeBox), + AuxC(AuxCBox), + Colr(ColrBox), +} + +impl IpcoProp { + pub fn len(&self) -> usize { + match self { + Self::Av1C(p) => p.len(), + Self::Pixi(p) => p.len(), + Self::Ispe(p) => p.len(), + Self::AuxC(p) => p.len(), + Self::Colr(p) => p.len(), + } + } + + pub fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + match self { + Self::Av1C(p) => p.write(w), + Self::Pixi(p) => p.write(w), + Self::Ispe(p) => p.write(w), + Self::AuxC(p) => p.write(w), + Self::Colr(p) => p.write(w), + } + } +} + +/// Item Property Container box +#[derive(Debug, Clone)] +pub struct IpcoBox { + props: ArrayVec, +} + +impl IpcoBox { + pub fn new() -> Self { + Self { props: ArrayVec::new() } + } + + #[must_use] + pub fn push(&mut self, prop: IpcoProp) -> Option { + self.props.try_push(prop).ok()?; + Some(self.props.len() as u8) // the spec wants them off by one + } + + pub(crate) fn ispe(&self) -> Option<&IspeBox> { + self.props.iter().find_map(|b| match b { + IpcoProp::Ispe(i) => Some(i), + _ => None, + }) + } +} + +impl MpegBox for IpcoBox { + #[inline] + fn len(&self) -> usize { + BASIC_BOX_SIZE + + self.props.iter().map(|a| a.len()).sum::() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), *b"ipco")?; + for p in &self.props { + p.write(&mut b)?; + } + Ok(()) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct AuxCBox { + pub urn: &'static str, +} + +impl AuxCBox { + pub fn len(&self) -> usize { + FULL_BOX_SIZE + self.urn.len() + 1 + } + + pub fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"auxC", 0)?; + b.push(self.urn.as_bytes())?; + b.u8(0) + } +} + +/// Pixies, I guess. +#[derive(Debug, Copy, Clone)] +pub struct PixiBox { + pub depth: u8, + pub channels: u8, +} + +impl PixiBox { + pub fn len(self) -> usize { + FULL_BOX_SIZE + + 1 + self.channels as usize + } + + pub fn write(self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"pixi", 0)?; + b.u8(self.channels)?; + for _ in 0..self.channels { + b.u8(self.depth)?; + } + Ok(()) + } +} + +/// This is HEVC-specific and not for AVIF, but Chrome wants it :( +#[derive(Debug, Copy, Clone)] +pub struct IspeBox { + pub width: u32, + pub height: u32, +} + +impl MpegBox for IspeBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + 4 + 4 + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"ispe", 0)?; + b.u32(self.width)?; + b.u32(self.height) + } +} + +/// Property→image associations +#[derive(Debug, Clone)] +pub struct IpmaEntry { + pub item_id: u16, + pub prop_ids: ArrayVec, +} + +#[derive(Debug, Clone)] +pub struct IpmaBox { + pub entries: ArrayVec, +} + +impl MpegBox for IpmaBox { + #[inline] + fn len(&self) -> usize { + FULL_BOX_SIZE + 4 + self.entries.iter().map(|e| 2 + 1 + e.prop_ids.len()).sum::() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"ipma", 0)?; + b.u32(self.entries.len() as _)?; // entry count + + for e in &self.entries { + b.u16(e.item_id)?; + b.u8(e.prop_ids.len() as u8)?; // assoc count + for &p in &e.prop_ids { + b.u8(p)?; + } + } + Ok(()) + } +} + +/// Item Reference box +#[derive(Debug, Copy, Clone)] +pub struct IrefEntryBox { + pub from_id: u16, + pub to_id: u16, + pub typ: FourCC, +} + +impl MpegBox for IrefEntryBox { + #[inline(always)] + fn len(&self) -> usize { + BASIC_BOX_SIZE + + 2 // from + + 2 // refcount + + 2 // to + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), self.typ.0)?; + b.u16(self.from_id)?; + b.u16(1)?; + b.u16(self.to_id) + } +} + +#[derive(Debug, Clone)] +pub struct IrefBox { + pub entries: ArrayVec, +} + +impl IrefBox { + pub fn is_empty(&self) -> bool { + self.entries.is_empty() + } +} + +impl MpegBox for IrefBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + self.entries.iter().map(|e| e.len()).sum::() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"iref", 0)?; + for entry in &self.entries { + entry.write(&mut b)?; + } + Ok(()) + } +} + +/// Auxiliary item (alpha or depth map) +#[derive(Debug, Copy, Clone)] +#[allow(unused)] +pub struct AuxlBox {} + +impl MpegBox for AuxlBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + w.full_box(self.len(), *b"auxl", 0)?; + Ok(()) + } +} + +/// ColourInformationBox +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct ColrBox { + pub color_primaries: ColorPrimaries, + pub transfer_characteristics: TransferCharacteristics, + pub matrix_coefficients: MatrixCoefficients, + pub full_range_flag: bool, // u1 + u7 +} + +impl Default for ColrBox { + fn default() -> Self { + Self { + color_primaries: ColorPrimaries::Bt709, + transfer_characteristics: TransferCharacteristics::Srgb, + matrix_coefficients: MatrixCoefficients::Bt601, + full_range_flag: true, + } + } +} + +impl MpegBox for ColrBox { + #[inline(always)] + fn len(&self) -> usize { + BASIC_BOX_SIZE + 4 + 2 + 2 + 2 + 1 + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), *b"colr")?; + b.u32(u32::from_be_bytes(*b"nclx"))?; + b.u16(self.color_primaries as u16)?; + b.u16(self.transfer_characteristics as u16)?; + b.u16(self.matrix_coefficients as u16)?; + b.u8(if self.full_range_flag { 1 << 7 } else { 0 }) + } +} +#[derive(Debug, Copy, Clone)] +pub struct Av1CBox { + pub seq_profile: u8, + pub seq_level_idx_0: u8, + pub seq_tier_0: bool, + pub high_bitdepth: bool, + pub twelve_bit: bool, + pub monochrome: bool, + pub chroma_subsampling_x: bool, + pub chroma_subsampling_y: bool, + pub chroma_sample_position: u8, +} + +impl MpegBox for Av1CBox { + #[inline(always)] + fn len(&self) -> usize { + BASIC_BOX_SIZE + 4 + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(), *b"av1C")?; + let flags1 = + u8::from(self.seq_tier_0) << 7 | + u8::from(self.high_bitdepth) << 6 | + u8::from(self.twelve_bit) << 5 | + u8::from(self.monochrome) << 4 | + u8::from(self.chroma_subsampling_x) << 3 | + u8::from(self.chroma_subsampling_y) << 2 | + self.chroma_sample_position; + + b.push(&[ + 0x81, // marker and version + (self.seq_profile << 5) | self.seq_level_idx_0, // x2d == 45 + flags1, + 0, + ]) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct PitmBox(pub u16); + +impl MpegBox for PitmBox { + #[inline(always)] + fn len(&self) -> usize { + FULL_BOX_SIZE + 2 + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"pitm", 0)?; + b.u16(self.0) + } +} + +#[derive(Debug, Clone)] +pub struct IlocBox<'data> { + /// update before writing + pub absolute_offset_start: Option, + pub items: ArrayVec, 3>, +} + +#[derive(Debug, Clone)] +pub struct IlocItem<'data> { + pub id: u16, + pub extents: [IlocExtent<'data>; 1], +} + +#[derive(Debug, Copy, Clone)] +pub struct IlocExtent<'data> { + /// offset and len will be calculated when writing + pub data: &'data [u8], +} + +impl MpegBox for IlocBox<'_> { + #[inline(always)] + #[allow(unused_parens)] + fn len(&self) -> usize { + FULL_BOX_SIZE + + 1 // offset_size, length_size + + 1 // base_offset_size, reserved + + 2 // num items + + self.items.iter().map(|i| ( // for each item + 2 // id + + 2 // dat ref idx + + 0 // base_offset_size + + 2 // extent count + + i.extents.len() * ( // for each extent + 4 // extent_offset + + 4 // extent_len + ) + )).sum::() + } + + fn write(&self, w: &mut Writer) -> Result<(), B::Error> { + let mut b = w.full_box(self.len(), *b"iloc", 0)?; + b.push(&[4 << 4 | 4, 0])?; // offset and length are 4 bytes + + b.u16(self.items.len() as _)?; // num items + let mut next_start = if let Some(ok) = self.absolute_offset_start { ok.get() } else { + debug_assert!(false); + !0 + }; + for item in &self.items { + b.u16(item.id)?; + b.u16(0)?; + b.u16(item.extents.len() as _)?; // num extents + for ex in &item.extents { + let len = ex.data.len() as u32; + b.u32(next_start)?; + next_start += len; + b.u32(len)?; + } + } + Ok(()) + } +} + +#[derive(Debug, Clone)] +pub struct MdatBox; + +impl MdatBox { + #[inline(always)] + fn len(&self, chunks: &IlocBox) -> usize { + BASIC_BOX_SIZE + chunks.items.iter().flat_map(|c| &c.extents).map(|d| d.data.len()).sum::() + } + + fn write(&self, w: &mut Writer, chunks: &IlocBox) -> Result<(), B::Error> { + let mut b = w.basic_box(self.len(chunks), *b"mdat")?; + for ch in chunks.items.iter().flat_map(|c| &c.extents) { + b.push(ch.data)?; + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/constants.rs clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/constants.rs --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/constants.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/constants.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +/// `Bt709` works for sRGB images. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ColorPrimaries { + /// Rec.709 and sRGB + Bt709 = 1, + Unspecified = 2, + /// ITU-R BT601-6 525 + Bt601 = 6, + /// ITU-R BT2020 + Bt2020 = 9, + /// SMPTE ST 431-2. NB: "P3" images use DisplayP3 instead. + DciP3 = 11, + /// SMPTE ST 432-1 + DisplayP3 = 12, +} + +/// This controls how color data is interpreted (gamma). +/// +/// If you don't know what to do with these, pick `Srgb`. +/// +/// Reasonable options include `Bt709` (HDTV), `Bt2020_10` (Wide Gamut), `Smpte2084`, `Hlg` (HDR). +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum TransferCharacteristics { + /// Rec.709. May be appropriate for conversions from video. + Bt709 = 1, + /// Don't use this for color channels. + Unspecified = 2, + /// Don't use this. Analog NTSC TV. BT.470 System M (historical) + #[deprecated(note = "This is obsolete. Please don't proliferate legacy baggage.")] + #[doc(hidden)] + Bt470M = 4, + /// Don't use this. Analog PAL TV. BT.470 System B, G (historical) + #[deprecated(note = "This is obsolete. Please don't proliferate legacy baggage.")] + #[doc(hidden)] + Bt470BG = 5, + /// ITU-R BT601-6 525. Not recommended, unless you're converting from unlabelled low-res video clips. + /// See `Bt709` and `Srgb`. + Bt601 = 6, + /// Don't use this. SMPTE 240 M. It's just a worse Rec.709. + Smpte240 = 7, + /// "Linear transfer characteristics" + Linear = 8, + /// "Logarithmic transfer characteristic (100:1 range)" + Log = 9, + /// "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + LogSqrt = 10, + /// IEC 61966-2-4 + Iec61966 = 11, + /// Don't use this. Obsoleted BT.1361 extended color gamut system (historical) + #[deprecated(note = "This is obsolete. Please don't proliferate legacy baggage.")] + #[doc(hidden)] + Bt1361 = 12, + /// sRGB. This is the safe choice for encoding "standard" RGB images, especially 8-bit inputs. + Srgb = 13, + /// ITU-R BT2020 for 10-bit system. Reasonable for encoding wide gamut. + Bt2020_10 = 14, + /// ITU-R BT2020 for 12-bit system + Bt2020_12 = 15, + /// SMPTE ST 2084, ITU BT.2100 PQ + Smpte2084 = 16, + /// SMPTE ST 428. Not recommended. Overkill for images. Use `Bt2020_10` instead. + Smpte428 = 17, + /// BT.2100 HLG (Hybrid Log Gamma), ARIB STD-B67 + Hlg = 18, +} + +/// This is the format of color channels. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum MatrixCoefficients { + /// GBR (sRGB). This isn't actually good for most RGB images. Use `Bt709` for lossy and `Ycgco` for lossless. + Rgb = 0, + /// ITU-R BT1361 + Bt709 = 1, + Unspecified = 2, + /// ITU-R BT601-6 525. This matches luma in JPEG's YCbCr when used with sRGB transfer characteristics, but is a bit off for chroma. + Bt601 = 6, + Ycgco = 8, + /// ITU-R BT2020 non-constant luminance system + Bt2020Ncl = 9, + /// ITU-R BT2020 constant luminance system + Bt2020Cl = 10, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,507 @@ +//! # AVIF image serializer (muxer) +//! +//! ## Usage +//! +//! 1. Compress pixels using an AV1 encoder, such as [rav1e](https://lib.rs/rav1e). [libaom](https://lib.rs/libaom-sys) works too. +//! +//! 2. Call `avif_serialize::serialize_to_vec(av1_data, None, width, height, 8)` +//! +//! See [cavif](https://github.com/kornelski/cavif-rs) for a complete implementation. + +mod boxes; +pub mod constants; +mod writer; + +use crate::boxes::*; +use arrayvec::ArrayVec; +use std::io; + +/// Config for the serialization (allows setting advanced image properties). +/// +/// See [`Aviffy::new`]. +pub struct Aviffy { + premultiplied_alpha: bool, + colr: ColrBox, + min_seq_profile: u8, + chroma_subsampling: (bool, bool), + monochrome: bool, + width: u32, + height: u32, + bit_depth: u8, + exif: Option>, +} + +/// Makes an AVIF file given encoded AV1 data (create the data with [`rav1e`](https://lib.rs/rav1e)) +/// +/// `color_av1_data` is already-encoded AV1 image data for the color channels (YUV, RGB, etc.). +/// [You can parse this information out of AV1 payload with `avif-parse`](https://docs.rs/avif-parse/latest/avif_parse/struct.AV1Metadata.html). +/// +/// The color image should have been encoded without chroma subsampling AKA YUV444 (`Cs444` in `rav1e`) +/// AV1 handles full-res color so effortlessly, you should never need chroma subsampling ever again. +/// +/// Optional `alpha_av1_data` is a monochrome image (`rav1e` calls it "YUV400"/`Cs400`) representing transparency. +/// Alpha adds a lot of header bloat, so don't specify it unless it's necessary. +/// +/// `width`/`height` is image size in pixels. It must of course match the size of encoded image data. +/// `depth_bits` should be 8, 10 or 12, depending on how the image was encoded. +/// +/// Color and alpha must have the same dimensions and depth. +/// +/// Data is written (streamed) to `into_output`. +pub fn serialize(into_output: W, color_av1_data: &[u8], alpha_av1_data: Option<&[u8]>, width: u32, height: u32, depth_bits: u8) -> io::Result<()> { + Aviffy::new() + .set_width(width) + .set_height(height) + .set_bit_depth(depth_bits) + .write_slice(into_output, color_av1_data, alpha_av1_data) +} + +impl Aviffy { + /// You will have to set image properties to match the AV1 bitstream. + /// + /// [You can get this information out of the AV1 payload with `avif-parse`](https://docs.rs/avif-parse/latest/avif_parse/struct.AV1Metadata.html). + #[inline] + #[must_use] + pub fn new() -> Self { + Self { + premultiplied_alpha: false, + min_seq_profile: 1, + chroma_subsampling: (false, false), + monochrome: false, + width: 0, + height: 0, + bit_depth: 0, + colr: ColrBox::default(), + exif: None, + } + } + + /// If set, must match the AV1 color payload, and will result in `colr` box added to AVIF. + /// Defaults to BT.601, because that's what Safari assumes when `colr` is missing. + /// Other browsers are smart enough to read this from the AV1 payload instead. + #[inline] + pub fn set_matrix_coefficients(&mut self, matrix_coefficients: constants::MatrixCoefficients) -> &mut Self { + self.colr.matrix_coefficients = matrix_coefficients; + self + } + + #[doc(hidden)] + pub fn matrix_coefficients(&mut self, matrix_coefficients: constants::MatrixCoefficients) -> &mut Self { + self.set_matrix_coefficients(matrix_coefficients) + } + + /// If set, must match the AV1 color payload, and will result in `colr` box added to AVIF. + /// Defaults to sRGB. + #[inline] + pub fn set_transfer_characteristics(&mut self, transfer_characteristics: constants::TransferCharacteristics) -> &mut Self { + self.colr.transfer_characteristics = transfer_characteristics; + self + } + + #[doc(hidden)] + pub fn transfer_characteristics(&mut self, transfer_characteristics: constants::TransferCharacteristics) -> &mut Self { + self.set_transfer_characteristics(transfer_characteristics) + } + + /// If set, must match the AV1 color payload, and will result in `colr` box added to AVIF. + /// Defaults to sRGB/Rec.709. + #[inline] + pub fn set_color_primaries(&mut self, color_primaries: constants::ColorPrimaries) -> &mut Self { + self.colr.color_primaries = color_primaries; + self + } + + #[doc(hidden)] + pub fn color_primaries(&mut self, color_primaries: constants::ColorPrimaries) -> &mut Self { + self.set_color_primaries(color_primaries) + } + + /// If set, must match the AV1 color payload, and will result in `colr` box added to AVIF. + /// Defaults to full. + #[inline] + pub fn set_full_color_range(&mut self, full_range: bool) -> &mut Self { + self.colr.full_range_flag = full_range; + self + } + + #[doc(hidden)] + pub fn full_color_range(&mut self, full_range: bool) -> &mut Self { + self.set_full_color_range(full_range) + } + + /// Makes an AVIF file given encoded AV1 data (create the data with [`rav1e`](https://lib.rs/rav1e)) + /// + /// `color_av1_data` is already-encoded AV1 image data for the color channels (YUV, RGB, etc.). + /// The color image should have been encoded without chroma subsampling AKA YUV444 (`Cs444` in `rav1e`) + /// AV1 handles full-res color so effortlessly, you should never need chroma subsampling ever again. + /// + /// Optional `alpha_av1_data` is a monochrome image (`rav1e` calls it "YUV400"/`Cs400`) representing transparency. + /// Alpha adds a lot of header bloat, so don't specify it unless it's necessary. + /// + /// `width`/`height` is image size in pixels. It must of course match the size of encoded image data. + /// `depth_bits` should be 8, 10 or 12, depending on how the image has been encoded in AV1. + /// + /// Color and alpha must have the same dimensions and depth. + /// + /// Data is written (streamed) to `into_output`. + #[inline] + pub fn write(&self, into_output: W, color_av1_data: &[u8], alpha_av1_data: Option<&[u8]>, width: u32, height: u32, depth_bits: u8) -> io::Result<()> { + self.make_boxes(color_av1_data, alpha_av1_data, width, height, depth_bits)?.write(into_output) + } + + /// See [`Self::write`] + #[inline] + pub fn write_slice(&self, into_output: W, color_av1_data: &[u8], alpha_av1_data: Option<&[u8]>) -> io::Result<()> { + self.make_boxes(color_av1_data, alpha_av1_data, self.width, self.height, self.bit_depth)?.write(into_output) + } + + fn make_boxes<'data>(&'data self, color_av1_data: &'data [u8], alpha_av1_data: Option<&'data [u8]>, width: u32, height: u32, depth_bits: u8) -> io::Result> { + if ![8, 10, 12].contains(&depth_bits) { + return Err(io::Error::new(io::ErrorKind::InvalidInput, "depth must be 8/10/12")); + } + + let mut image_items = ArrayVec::new(); + let mut iloc_items = ArrayVec::new(); + let mut ipma_entries = ArrayVec::new(); + let mut irefs = ArrayVec::new(); + let mut ipco = IpcoBox::new(); + let color_image_id = 1; + let alpha_image_id = 2; + let exif_id = 3; + const ESSENTIAL_BIT: u8 = 0x80; + let color_depth_bits = depth_bits; + let alpha_depth_bits = depth_bits; // Sadly, the spec requires these to match. + + image_items.push(InfeBox { + id: color_image_id, + typ: FourCC(*b"av01"), + name: "", + }); + + let ispe_prop = ipco.push(IpcoProp::Ispe(IspeBox { width, height })).ok_or(io::ErrorKind::InvalidInput)?; + + // This is redundant, but Chrome wants it, and checks that it matches :( + let av1c_color_prop = ipco.push(IpcoProp::Av1C(Av1CBox { + seq_profile: self.min_seq_profile.max(if color_depth_bits >= 12 { 2 } else { 0 }), + seq_level_idx_0: 31, + seq_tier_0: false, + high_bitdepth: color_depth_bits >= 10, + twelve_bit: color_depth_bits >= 12, + monochrome: self.monochrome, + chroma_subsampling_x: self.chroma_subsampling.0, + chroma_subsampling_y: self.chroma_subsampling.1, + chroma_sample_position: 0, + })).ok_or(io::ErrorKind::InvalidInput)?; + + // Useless bloat + let pixi_3 = ipco.push(IpcoProp::Pixi(PixiBox { + channels: 3, + depth: color_depth_bits, + })).ok_or(io::ErrorKind::InvalidInput)?; + + let mut ipma = IpmaEntry { + item_id: color_image_id, + prop_ids: from_array([ispe_prop, av1c_color_prop | ESSENTIAL_BIT, pixi_3]), + }; + + // Redundant info, already in AV1 + if self.colr != ColrBox::default() { + let colr_color_prop = ipco.push(IpcoProp::Colr(self.colr)).ok_or(io::ErrorKind::InvalidInput)?; + ipma.prop_ids.push(colr_color_prop); + } + ipma_entries.push(ipma); + + if let Some(exif_data) = self.exif.as_deref() { + image_items.push(InfeBox { + id: exif_id, + typ: FourCC(*b"Exif"), + name: "", + }); + + iloc_items.push(IlocItem { + id: exif_id, + extents: [IlocExtent { data: exif_data }], + }); + + irefs.push(IrefEntryBox { + from_id: exif_id, + to_id: color_image_id, + typ: FourCC(*b"cdsc"), + }); + } + + if let Some(alpha_data) = alpha_av1_data { + image_items.push(InfeBox { + id: alpha_image_id, + typ: FourCC(*b"av01"), + name: "", + }); + + irefs.push(IrefEntryBox { + from_id: alpha_image_id, + to_id: color_image_id, + typ: FourCC(*b"auxl"), + }); + + if self.premultiplied_alpha { + irefs.push(IrefEntryBox { + from_id: color_image_id, + to_id: alpha_image_id, + typ: FourCC(*b"prem"), + }); + } + + let av1c_alpha_prop = ipco.push(boxes::IpcoProp::Av1C(Av1CBox { + seq_profile: if alpha_depth_bits >= 12 { 2 } else { 0 }, + seq_level_idx_0: 31, + seq_tier_0: false, + high_bitdepth: alpha_depth_bits >= 10, + twelve_bit: alpha_depth_bits >= 12, + monochrome: true, + chroma_subsampling_x: true, + chroma_subsampling_y: true, + chroma_sample_position: 0, + })).ok_or(io::ErrorKind::InvalidInput)?; + + // So pointless + let pixi_1 = ipco.push(IpcoProp::Pixi(PixiBox { + channels: 1, + depth: alpha_depth_bits, + })).ok_or(io::ErrorKind::InvalidInput)?; + + // that's a silly way to add 1 bit of information, isn't it? + let auxc_prop = ipco.push(IpcoProp::AuxC(AuxCBox { + urn: "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha", + })).ok_or(io::ErrorKind::InvalidInput)?; + + ipma_entries.push(IpmaEntry { + item_id: alpha_image_id, + prop_ids: from_array([ispe_prop, av1c_alpha_prop | ESSENTIAL_BIT, auxc_prop, pixi_1]), + }); + + // Use interleaved color and alpha, with alpha first. + // Makes it possible to display partial image. + iloc_items.push(IlocItem { + id: alpha_image_id, + extents: [IlocExtent { data: alpha_data }], + }); + } + iloc_items.push(IlocItem { + id: color_image_id, + extents: [IlocExtent { data: color_av1_data }], + }); + + Ok(AvifFile { + ftyp: FtypBox { + major_brand: FourCC(*b"avif"), + minor_version: 0, + compatible_brands: [FourCC(*b"mif1"), FourCC(*b"miaf")].into(), + }, + meta: MetaBox { + hdlr: HdlrBox {}, + iinf: IinfBox { items: image_items }, + pitm: PitmBox(color_image_id), + iloc: IlocBox { + absolute_offset_start: None, + items: iloc_items, + }, + iprp: IprpBox { + ipco, + // It's not enough to define these properties, + // they must be assigned to the image + ipma: IpmaBox { entries: ipma_entries }, + }, + iref: IrefBox { entries: irefs }, + }, + // Here's the actual data. If HEIF wasn't such a kitchen sink, this + // would have been the only data this file needs. + mdat: MdatBox, + }) + } + + /// Panics if the input arguments were invalid. Use [`Self::write`] to handle the errors. + #[must_use] + #[track_caller] + pub fn to_vec(&self, color_av1_data: &[u8], alpha_av1_data: Option<&[u8]>, width: u32, height: u32, depth_bits: u8) -> Vec { + let mut file = self.make_boxes(color_av1_data, alpha_av1_data, width, height, depth_bits).unwrap(); + let mut out = Vec::new(); + file.write_to_vec(&mut out).unwrap(); + out + } + + /// `(false, false)` is 4:4:4 + /// `(true, true)` is 4:2:0 + /// + /// `chroma_sample_position` is always 0. Don't use chroma subsampling with AVIF. + #[inline] + pub fn set_chroma_subsampling(&mut self, subsampled_xy: (bool, bool)) -> &mut Self { + self.chroma_subsampling = subsampled_xy; + self + } + + /// Set whether the image is monochrome (grayscale). + /// This is used to set the `monochrome` flag in the AV1 sequence header. + #[inline] + pub fn set_monochrome(&mut self, monochrome: bool) -> &mut Self { + self.monochrome = monochrome; + self + } + + /// Set exif metadata to be included in the AVIF file as a separate item. + #[inline] + pub fn set_exif(&mut self, exif: Vec) -> &mut Self { + self.exif = Some(exif); + self + } + + /// Sets minimum required + /// + /// Higher bit depth may increase this + #[inline] + pub fn set_seq_profile(&mut self, seq_profile: u8) -> &mut Self { + self.min_seq_profile = seq_profile; + self + } + + #[inline] + pub fn set_width(&mut self, width: u32) -> &mut Self { + self.width = width; + self + } + + #[inline] + pub fn set_height(&mut self, height: u32) -> &mut Self { + self.height = height; + self + } + + /// 8, 10 or 12. + #[inline] + pub fn set_bit_depth(&mut self, bit_depth: u8) -> &mut Self { + self.bit_depth = bit_depth; + self + } + + /// Set whether image's colorspace uses premultiplied alpha, i.e. RGB channels were multiplied by their alpha value, + /// so that transparent areas are all black. Image decoders will be instructed to undo the premultiplication. + /// + /// Premultiplied alpha images usually compress better and tolerate heavier compression, but + /// may not be supported correctly by less capable AVIF decoders. + /// + /// This just sets the configuration property. The pixel data must have already been processed before compression. + /// If a decoder displays semitransparent colors too dark, it doesn't support premultiplied alpha. + /// If a decoder displays semitransparent colors too bright, you didn't premultiply the colors before encoding. + /// + /// If you're not using premultiplied alpha, consider bleeding RGB colors into transparent areas, + /// otherwise there may be unwanted outlines around edges of transparency. + #[inline] + pub fn set_premultiplied_alpha(&mut self, is_premultiplied: bool) -> &mut Self { + self.premultiplied_alpha = is_premultiplied; + self + } + + #[doc(hidden)] + pub fn premultiplied_alpha(&mut self, is_premultiplied: bool) -> &mut Self { + self.set_premultiplied_alpha(is_premultiplied) + } +} + +#[inline(always)] +fn from_array(array: [T; L1]) -> ArrayVec { + assert!(L1 <= L2); + let mut tmp = ArrayVec::new_const(); + let _ = tmp.try_extend_from_slice(&array); + tmp +} + +/// See [`serialize`] for description. This one makes a `Vec` instead of using `io::Write`. +#[must_use] +#[track_caller] +pub fn serialize_to_vec(color_av1_data: &[u8], alpha_av1_data: Option<&[u8]>, width: u32, height: u32, depth_bits: u8) -> Vec { + Aviffy::new().to_vec(color_av1_data, alpha_av1_data, width, height, depth_bits) +} + +#[test] +fn test_roundtrip_parse_mp4() { + let test_img = b"av12356abc"; + let avif = serialize_to_vec(test_img, None, 10, 20, 8); + + let ctx = mp4parse::read_avif(&mut avif.as_slice(), mp4parse::ParseStrictness::Normal).unwrap(); + + assert_eq!(&test_img[..], ctx.primary_item_coded_data().unwrap()); +} + +#[test] +fn test_roundtrip_parse_mp4_alpha() { + let test_img = b"av12356abc"; + let test_a = b"alpha"; + let avif = serialize_to_vec(test_img, Some(test_a), 10, 20, 8); + + let ctx = mp4parse::read_avif(&mut avif.as_slice(), mp4parse::ParseStrictness::Normal).unwrap(); + + assert_eq!(&test_img[..], ctx.primary_item_coded_data().unwrap()); + assert_eq!(&test_a[..], ctx.alpha_item_coded_data().unwrap()); +} + +#[test] +fn test_roundtrip_parse_exif() { + let test_img = b"av12356abc"; + let test_a = b"alpha"; + let avif = Aviffy::new() + .set_exif(b"lol".to_vec()) + .to_vec(test_img, Some(test_a), 10, 20, 8); + + let ctx = mp4parse::read_avif(&mut avif.as_slice(), mp4parse::ParseStrictness::Normal).unwrap(); + + assert_eq!(&test_img[..], ctx.primary_item_coded_data().unwrap()); + assert_eq!(&test_a[..], ctx.alpha_item_coded_data().unwrap()); +} + +#[test] +fn test_roundtrip_parse_avif() { + let test_img = [1, 2, 3, 4, 5, 6]; + let test_alpha = [77, 88, 99]; + let avif = serialize_to_vec(&test_img, Some(&test_alpha), 10, 20, 8); + + let ctx = avif_parse::read_avif(&mut avif.as_slice()).unwrap(); + + assert_eq!(&test_img[..], ctx.primary_item.as_slice()); + assert_eq!(&test_alpha[..], ctx.alpha_item.as_deref().unwrap()); +} + +#[test] +fn test_roundtrip_parse_avif_colr() { + let test_img = [1, 2, 3, 4, 5, 6]; + let test_alpha = [77, 88, 99]; + let avif = Aviffy::new() + .matrix_coefficients(constants::MatrixCoefficients::Bt709) + .to_vec(&test_img, Some(&test_alpha), 10, 20, 8); + + let ctx = avif_parse::read_avif(&mut avif.as_slice()).unwrap(); + + assert_eq!(&test_img[..], ctx.primary_item.as_slice()); + assert_eq!(&test_alpha[..], ctx.alpha_item.as_deref().unwrap()); +} + +#[test] +fn premultiplied_flag() { + let test_img = [1,2,3,4]; + let test_alpha = [55,66,77,88,99]; + let avif = Aviffy::new().premultiplied_alpha(true).to_vec(&test_img, Some(&test_alpha), 5, 5, 8); + + let ctx = avif_parse::read_avif(&mut avif.as_slice()).unwrap(); + + assert!(ctx.premultiplied_alpha); + assert_eq!(&test_img[..], ctx.primary_item.as_slice()); + assert_eq!(&test_alpha[..], ctx.alpha_item.as_deref().unwrap()); +} + +#[test] +fn size_required() { + assert!(Aviffy::new().set_bit_depth(10).write_slice(&mut vec![], &[], None).is_err()); +} + +#[test] +fn depth_required() { + assert!(Aviffy::new().set_width(1).set_height(1).write_slice(&mut vec![], &[], None).is_err()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/avif-serialize/src/writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/avif-serialize/src/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,143 @@ +use std::convert::TryFrom; +use std::io; + +pub struct OOM; + +pub trait WriterBackend { + type Error; + fn reserve(&mut self, size: usize) -> Result<(), Self::Error>; + fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> Result<(), Self::Error>; +} + +/// `io::Write` generates bloated code (with backtrace for every byte written), +/// so small boxes are written infallibly. +impl WriterBackend for Vec { + type Error = OOM; + + #[inline] + fn reserve(&mut self, size: usize) -> Result<(), Self::Error> { + self.try_reserve(size).map_err(|_| OOM) + } + + #[inline(always)] + fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> Result<(), Self::Error> { + let has_capacity = self.capacity() - self.len() >= data.len(); + debug_assert!(has_capacity); + if has_capacity { + self.extend_from_slice(data); + Ok(()) + } else { + Err(OOM) + } + } +} + +pub struct IO(pub W); + +impl WriterBackend for IO { + type Error = io::Error; + + #[inline] + fn reserve(&mut self, _size: usize) -> io::Result<()> { + Ok(()) + } + + #[inline(always)] + fn extend_from_slice_in_capacity(&mut self, data: &[u8]) -> io::Result<()> { + self.0.write_all(data) + } +} + +pub struct Writer<'p, 'w, B> { + out: &'w mut B, + #[cfg(debug_assertions)] + parent: Option<&'p mut usize>, + #[cfg(not(debug_assertions))] + parent: std::marker::PhantomData<&'p mut usize>, + #[cfg(debug_assertions)] + left: usize, +} + +impl<'w, B> Writer<'static, 'w, B> { + #[inline] + pub fn new(out: &'w mut B) -> Self { + Self { + parent: Default::default(), + #[cfg(debug_assertions)] + left: 0, + out, + } + } +} + +impl Writer<'_, '_, B> { + #[inline(always)] + pub fn full_box(&mut self, len: usize, typ: [u8; 4], version: u8) -> Result, B::Error> { + let mut b = self.basic_box(len, typ)?; + b.push(&[version, 0, 0, 0])?; + Ok(b) + } + + #[inline] + pub fn basic_box(&mut self, len: usize, typ: [u8; 4]) -> Result, B::Error> { + let mut b = Writer { + out: self.out, + parent: Default::default(), + #[cfg(debug_assertions)] + left: len, + }; + #[cfg(debug_assertions)] + if self.left > 0 { + self.left -= len; + b.parent = Some(&mut self.left); + } else { + debug_assert!(self.parent.is_none()); + } + b.out.reserve(len)?; + + if let Ok(len) = u32::try_from(len) { + b.u32(len)?; + } else { + debug_assert!(false, "constants for box size don't include this"); + b.u32(1)?; + b.u64(len as u64)?; + } + b.push(&typ)?; + Ok(b) + } + + #[inline(always)] + pub fn push(&mut self, data: &[u8]) -> Result<(), B::Error> { + #[cfg(debug_assertions)] { + self.left -= data.len(); + } + self.out.extend_from_slice_in_capacity(data) + } + + #[inline(always)] + pub fn u8(&mut self, val: u8) -> Result<(), B::Error> { + self.push(std::slice::from_ref(&val)) + } + + #[inline(always)] + pub fn u16(&mut self, val: u16) -> Result<(), B::Error> { + self.push(&val.to_be_bytes()) + } + + #[inline(always)] + pub fn u32(&mut self, val: u32) -> Result<(), B::Error> { + self.push(&val.to_be_bytes()) + } + + #[inline(always)] + pub fn u64(&mut self, val: u64) -> Result<(), B::Error> { + self.push(&val.to_be_bytes()) + } +} + +#[cfg(debug_assertions)] +impl Drop for Writer<'_, '_, B> { + fn drop(&mut self) { + assert_eq!(self.left, 0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/base64/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/base64/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"36372e08a5cf4b713529f222928466b4d9bdc4116896bb9f121022c3b66502f1","Cargo.toml":"a261c28ccafada2884a75cab0e4e67326bafe720d58c937dc235521105982165","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"df01f5b4317d601e7de86743f9818aec9196abf9e298f5e47679b7a966ecd945","RELEASE-NOTES.md":"208162655e96cdf04949b6c0a53f24985095c8b188d7ea2c1017a23ce45e25eb","benches/benchmarks.rs":"da4a49294a7fcaf718f2b062a52ed669ca096abce6c57b4025efdd24825048c2","clippy.toml":"b26be4d15ed059985ce6994f11817fd7562046f46e460a0dc64dbb71cfc246d1","examples/base64.rs":"b75ead2199a9b4389c69fe6f1ae988176a263b8fc84e7a4fea1d7e5a41592078","icon_CLion.svg":"cffa044ba75cb998ee3306991dc4a3755ec2f39ab95ddd4b74bc21988389020f","src/alphabet.rs":"3461a34bd63c10cfe232deb5dd42e2ec2dfb5decd508caf31ec2a1826ad68131","src/chunked_encoder.rs":"edfdbb9a4329b80fb2c769ada81e234e00839e0fa85faaa70bacf40ce12e951c","src/decode.rs":"666ca75ccd975f0548d37312d2843ca4703b83697a044839bbefeba8f4f7874a","src/display.rs":"31bf3e19274a0b80dd8948a81ea535944f756ef5b88736124c940f5fe1e8c71c","src/encode.rs":"44ddcc162f3fe9817b6e857dda0a3b9197b90a657e5f71c44aacabf5431ccf7d","src/engine/general_purpose/decode.rs":"ba8a76d333ab96dd07b3f84bd6d405d690d2d17e84bd0878f05245a82dc16853","src/engine/general_purpose/decode_suffix.rs":"71ceb066b73e8cc833916e2cedbf0a01b07c2f16e30b2b2f63aff1c823874b51","src/engine/general_purpose/mod.rs":"9f49375fc03166a491acf464daa7a9e6540fdc2cca407da9a248e15640952c20","src/engine/mod.rs":"15210115e5f99e0d252a1240922deb1516778e318564f92a9d880a82fd82a55e","src/engine/naive.rs":"dc166010633e8de0fbff31e2f05d128506f3e0f34a6358c1a825b59a8ea1af0d","src/engine/tests.rs":"37bee2de07343bf5d37720f29cda291e8562f2363704e0ad91862d5991568d22","src/lib.rs":"3f964521aea13dbe49438ffed630a55471401da4c55c40506969697b649237f0","src/prelude.rs":"c1587138e5301ac797c5c362cb3638649b33f79c20c16db6f38ad44330540752","src/read/decoder.rs":"cc87daa4c52a23d1275352bccf07468baf2b60e90b2ac14f89a94254697cb83c","src/read/decoder_tests.rs":"edeee377e70095532be1625d0148de2273b739e9069a05e616d3e67877d92f1d","src/read/mod.rs":"e0b714eda02d16b1ffa6f78fd09b2f963e01c881b1f7c17b39db4e904be5e746","src/tests.rs":"90cb9f8a1ccb7c4ddc4f8618208e0031fc97e0df0e5aa466d6a5cf45d25967d8","src/write/encoder.rs":"c889c853249220fe2ddaeb77ee6e2ee2945f7db88cd6658ef89ff71b81255ea8","src/write/encoder_string_writer.rs":"0326c9d120369b9bbc35697b5b9b141bed24283374c93d5af1052eb042e47799","src/write/encoder_tests.rs":"28695a485b17cf5db73656aae5d90127f726e02c6d70efd83e5ab53a4cc17b38","src/write/mod.rs":"73cd98dadc9d712b3fefd9449d97e825e097397441b90588e0051e4d3b0911b9","tests/encode.rs":"5309f4538b1df611436f7bfba7409c725161b6f841b1bbf8d9890ae185de7d88","tests/tests.rs":"78efcf0dc4bb6ae52f7a91fcad89e44e4dce578224c36b4e6c1c306459be8500"},"package":"9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"0de73044240d0bc885d3c92760af40309e1c4c2ca92d266b4968dbbaad993a54",".circleci/config.yml":"8d2384265f87ea7aa923db02824c628d118e98bc178252f3984d42bc86cbd20e",".github/ISSUE_TEMPLATE/general-purpose-issue.md":"9e89c069e50dc24a09ece40bd6d02618ab044b2b53d2e5221defd6c884c96964","Cargo.lock":"36372e08a5cf4b713529f222928466b4d9bdc4116896bb9f121022c3b66502f1","Cargo.toml":"a261c28ccafada2884a75cab0e4e67326bafe720d58c937dc235521105982165","Cargo.toml.orig":"b17fbd0a764669ee9b09d7545708853285337f0ed293cf3ce42f68a42746efc4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"df01f5b4317d601e7de86743f9818aec9196abf9e298f5e47679b7a966ecd945","RELEASE-NOTES.md":"208162655e96cdf04949b6c0a53f24985095c8b188d7ea2c1017a23ce45e25eb","benches/benchmarks.rs":"da4a49294a7fcaf718f2b062a52ed669ca096abce6c57b4025efdd24825048c2","clippy.toml":"b26be4d15ed059985ce6994f11817fd7562046f46e460a0dc64dbb71cfc246d1","examples/base64.rs":"b75ead2199a9b4389c69fe6f1ae988176a263b8fc84e7a4fea1d7e5a41592078","icon_CLion.svg":"cffa044ba75cb998ee3306991dc4a3755ec2f39ab95ddd4b74bc21988389020f","src/alphabet.rs":"3461a34bd63c10cfe232deb5dd42e2ec2dfb5decd508caf31ec2a1826ad68131","src/chunked_encoder.rs":"edfdbb9a4329b80fb2c769ada81e234e00839e0fa85faaa70bacf40ce12e951c","src/decode.rs":"666ca75ccd975f0548d37312d2843ca4703b83697a044839bbefeba8f4f7874a","src/display.rs":"31bf3e19274a0b80dd8948a81ea535944f756ef5b88736124c940f5fe1e8c71c","src/encode.rs":"44ddcc162f3fe9817b6e857dda0a3b9197b90a657e5f71c44aacabf5431ccf7d","src/engine/general_purpose/decode.rs":"ba8a76d333ab96dd07b3f84bd6d405d690d2d17e84bd0878f05245a82dc16853","src/engine/general_purpose/decode_suffix.rs":"71ceb066b73e8cc833916e2cedbf0a01b07c2f16e30b2b2f63aff1c823874b51","src/engine/general_purpose/mod.rs":"9f49375fc03166a491acf464daa7a9e6540fdc2cca407da9a248e15640952c20","src/engine/mod.rs":"15210115e5f99e0d252a1240922deb1516778e318564f92a9d880a82fd82a55e","src/engine/naive.rs":"dc166010633e8de0fbff31e2f05d128506f3e0f34a6358c1a825b59a8ea1af0d","src/engine/tests.rs":"37bee2de07343bf5d37720f29cda291e8562f2363704e0ad91862d5991568d22","src/lib.rs":"3f964521aea13dbe49438ffed630a55471401da4c55c40506969697b649237f0","src/prelude.rs":"c1587138e5301ac797c5c362cb3638649b33f79c20c16db6f38ad44330540752","src/read/decoder.rs":"cc87daa4c52a23d1275352bccf07468baf2b60e90b2ac14f89a94254697cb83c","src/read/decoder_tests.rs":"edeee377e70095532be1625d0148de2273b739e9069a05e616d3e67877d92f1d","src/read/mod.rs":"e0b714eda02d16b1ffa6f78fd09b2f963e01c881b1f7c17b39db4e904be5e746","src/tests.rs":"90cb9f8a1ccb7c4ddc4f8618208e0031fc97e0df0e5aa466d6a5cf45d25967d8","src/write/encoder.rs":"c889c853249220fe2ddaeb77ee6e2ee2945f7db88cd6658ef89ff71b81255ea8","src/write/encoder_string_writer.rs":"0326c9d120369b9bbc35697b5b9b141bed24283374c93d5af1052eb042e47799","src/write/encoder_tests.rs":"28695a485b17cf5db73656aae5d90127f726e02c6d70efd83e5ab53a4cc17b38","src/write/mod.rs":"73cd98dadc9d712b3fefd9449d97e825e097397441b90588e0051e4d3b0911b9","tests/encode.rs":"5309f4538b1df611436f7bfba7409c725161b6f841b1bbf8d9890ae185de7d88","tests/tests.rs":"78efcf0dc4bb6ae52f7a91fcad89e44e4dce578224c36b4e6c1c306459be8500"},"package":"9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/base64/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/base64/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/base64/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9652c787730e58515ce7b44fcafd2430ab424628" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/base64/.circleci/config.yml clamav-1.4.6+dfsg/.cargo/vendor/base64/.circleci/config.yml --- clamav-1.4.3+dfsg/.cargo/vendor/base64/.circleci/config.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/base64/.circleci/config.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,135 @@ +version: '2.1' + +workflows: + version: 2 + build: + jobs: + - build: + matrix: + parameters: + rust_img: [ + # Yes, a single-parameter axis, but means it can be referred to as a cache parameter easily without + # duplicating the magic version number throughout this file. + # The default rust images (not -slim or -alpine) are based on buildpack-deps. Hopefully this will + # be easier on the CI hosts since presumably those fat lower layers will already be cached, and + # therefore faster than a minimal, customized alpine. + # MSRV + 'rust:1.48.0' + ] + # a hacky scheme to work around CircleCI's inability to deal with mutable docker tags, forcing us to + # get a nightly or stable toolchain via rustup instead of a mutable docker tag + toolchain_override: [ + '__msrv__', # won't add any other toolchains, just uses what's in the docker image + '1.65.0', # minimum needed to build dev-dependencies + 'stable', + 'beta', + 'nightly' + ] + +jobs: + build: + parameters: + rust_img: + type: string + toolchain_override: + type: string + docker: + - image: << parameters.rust_img >> + steps: + - checkout + - restore_cache: + key: project-cache-v5-<< parameters.rust_img >>-<< parameters.toolchain_override >>-{{ checksum "Cargo.toml" }} + - run: + name: Setup toolchain + command: | + if [[ '<< parameters.toolchain_override >>' != '__msrv__' ]] + then + rustup toolchain add '<< parameters.toolchain_override >>' + rustup default '<< parameters.toolchain_override >>' + fi + - run: + name: Log rustc version + command: rustc --version + - run: + name: Build main target + # update first to select dependencies appropriate for this toolchain + command: | + cargo update + cargo build + - run: + name: Check formatting + command: | + rustup component add rustfmt + cargo fmt -- --check + - run: + name: Check clippy lints + # we only care about stable clippy -- nightly clippy is a bit wild + command: | + if [[ '<< parameters.toolchain_override >>' == 'stable' ]] + then + rustup component add clippy + cargo clippy --all-targets + fi + - run: + name: Build all targets + command: | + if [[ '<< parameters.toolchain_override >>' != '__msrv__' ]] + then + cargo build --all-targets + fi + - run: + name: Build without default features + command: | + cargo build --no-default-features + if [[ '<< parameters.toolchain_override >>' != '__msrv__' ]] + then + cargo build --no-default-features --all-targets + fi + - run: + name: Build with only alloc + command: | + cargo build --no-default-features --features alloc + if [[ '<< parameters.toolchain_override >>' != '__msrv__' ]] + then + cargo build --no-default-features --features alloc --all-targets + fi + - run: + name: Add arm toolchain + command: rustup target add thumbv6m-none-eabi + - run: + name: Build ARM without default features (no_std) + command: cargo build --target thumbv6m-none-eabi --no-default-features + - run: + name: Build ARM with only alloc feature + command: cargo build --target thumbv6m-none-eabi --no-default-features --features alloc + - run: + # dev dependencies can't build on 1.48.0 + name: Run tests + command: | + if [[ '<< parameters.toolchain_override >>' != '__msrv__' ]] + then + cargo test --no-default-features + cargo test + fi + - run: + name: Build docs + command: cargo doc --verbose + - run: + name: Confirm fuzzers can run + # TERM=dumb prevents cargo fuzz list from printing with color + environment: + TERM: dumb + command: | + if [[ '<< parameters.toolchain_override >>' = 'nightly' ]] + then + cargo install cargo-fuzz + cargo fuzz list | xargs -I FUZZER cargo fuzz run FUZZER -- -max_total_time=1 + fi + + - save_cache: + key: project-cache-v5-<< parameters.rust_img >>-<< parameters.toolchain_override >>-{{ checksum "Cargo.toml" }} + paths: + # rust docker img doesn't use $HOME/[.cargo,.rustup] + - /usr/local/cargo + - /usr/local/rustup + - ./target diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/base64/.github/ISSUE_TEMPLATE/general-purpose-issue.md clamav-1.4.6+dfsg/.cargo/vendor/base64/.github/ISSUE_TEMPLATE/general-purpose-issue.md --- clamav-1.4.3+dfsg/.cargo/vendor/base64/.github/ISSUE_TEMPLATE/general-purpose-issue.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/base64/.github/ISSUE_TEMPLATE/general-purpose-issue.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +--- +name: General purpose issue +about: General purpose issue +title: Default issue +labels: '' +assignees: '' + +--- + +# Before you file an issue + +- Did you read the docs? +- Did you read the README? + +# The problem + +- + +# How I, the issue filer, am going to help solve it + +- diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/base64/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/base64/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/base64/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/base64/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +[package] +name = "base64" +version = "0.21.7" +authors = ["Alice Maz ", "Marshall Pierce "] +description = "encodes and decodes base64 as bytes or utf8" +repository = "https://github.com/marshallpierce/rust-base64" +documentation = "https://docs.rs/base64" +readme = "README.md" +keywords = ["base64", "utf8", "encode", "decode", "no_std"] +categories = ["encoding"] +license = "MIT OR Apache-2.0" +edition = "2018" +# dev-dependencies require 1.65, but the main code doesn't +# This option was added in 1.56, keep it for when we bump MSRV. +rust-version = "1.48.0" + +[[bench]] +name = "benchmarks" +harness = false +required-features = ["std"] + +[[example]] +name = "base64" +required-features = ["std"] + +[[test]] +name = "tests" +required-features = ["alloc"] + +[[test]] +name = "encode" +required-features = ["alloc"] + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] + +[dev-dependencies] +criterion = "0.4.0" +rand = { version = "0.8.5", features = ["small_rng"] } +# Latest is 4.4.13 but specifies MSRV in Cargo.toml which means we can't depend +# on it (even though we won't compile it in MSRV CI). +clap = { version = "3.2.25", features = ["derive"] } +strum = { version = "0.25", features = ["derive"] } +# test fixtures for engine tests +rstest = "0.13.0" +rstest_reuse = "0.6.0" +once_cell = "1" + +[features] +default = ["std"] +alloc = [] +std = ["alloc"] + +[profile.bench] +# Useful for better disassembly when using `perf record` and `perf annotate` +debug = true + +[profile.test] +# Faster tests save much more than the increase in compilation time +opt-level = 3 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bindgen/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bindgen/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"1c290771bddd3cde261935e253cd7574b648d1b321a0f3466d429eca3a3cce64","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","build.rs":"4a9c4ac3759572e17de312a9d3f4ced3b6fd3c71811729e5a8d06bfbd1ac8f82","callbacks.rs":"985f5e3b19b870ec90baa89187b5049514fc5a259bc74fd6fb2ee857c52c11ff","clang.rs":"ee5130a029688f0eadc854c9873824330b6539e2eae597e2198b51e4e8f124a5","codegen/bitfield_unit.rs":"fddeaeab5859f4e82081865595b7705f5c0774d997df95fa5c655b81b9cae125","codegen/bitfield_unit_tests.rs":"9df86490de5e9d66ccea583dcb686dd440375dc1a3c3cf89a89d5de3883bf28a","codegen/dyngen.rs":"6d8bed53c6de66bc658b3186041c2b75549f49b0f0363ff18b87c8dcf2f5a05b","codegen/error.rs":"fa02274debd9064f35a627c43407e4e47ca89f2becfb1c233a500440d6c73e00","codegen/helpers.rs":"cf9e60d18d17d624f3559b6dd65e75630a16e6c1b71666f7c9656e51053d10f8","codegen/impl_debug.rs":"80df6136327b1ca8c7d1c2961290b5ab00b85b49b22c02f26a590bc68fb230af","codegen/impl_partialeq.rs":"db739d7ba6f5ba4033d6bf62c276f35217c20eab27230cf07dadf59e8b2f71bb","codegen/mod.rs":"89156a1926556d7c46b0266aabbb7c4e5a4a93fe1e5fc088f86acd3b14203f17","codegen/postprocessing/merge_extern_blocks.rs":"284457a3c75e945217bab4e5a4280fef0fcc03c31e12cc5010aab87f34c0b6c7","codegen/postprocessing/mod.rs":"160a6d6701cabf2514e23570df1bd1b648c909cc27b7c583f21d98fe0c16722e","codegen/postprocessing/sort_semantically.rs":"f465d1e8cc119082eb79c164b5cd780a370821e8bf56585b287dd3b51fc4a542","codegen/serialize.rs":"bb99633ab6a6764b84dac86a873fa64c90aa4979f26e75fbeff9af365b3fefa8","codegen/struct_layout.rs":"5685fc6caa24ac2779fbb885064043898830c00c92819e8c0e4fd9564c641c4d","deps.rs":"5ee2332fdb10325f3b0a0c6d9ba94e13eb631ef39e955fa958afc3625bdb5448","diagnostics.rs":"dc40cd5e9710922422c5c9420e2351f5d976e7a1d7275e4f4ce742cad9eb53f8","extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","features.rs":"6c17e37bdd14355c9c3f93b67e539bf001ea113a9efe287527e9021d785b5bda","ir/analysis/derive.rs":"cba290e9c4ba271e90524149ad3b874f37843bfdfab12d513cc85d2665447fd5","ir/analysis/has_destructor.rs":"e7e95c3b0989b6375cd3eabaac85a36ecc2915a1fd3700c7d26fe04e8dc83ba3","ir/analysis/has_float.rs":"a56b97bf913f132c2c63dc202b45c692c416a8c9fdc6b2baeee30362fb0d4405","ir/analysis/has_type_param_in_array.rs":"788ebb4ba2cf46a22f1e4ff3005d51f38d414b72e95355f7ff4125521e2d9525","ir/analysis/has_vtable.rs":"83efa40ae89147170eabdff1387e60aba574ca4cd4cdef22692753594f09d6c6","ir/analysis/mod.rs":"ed161d9f60306ad42af2ae70ff0eb686a36e2fb30eb94918b5e5f19af80e1db7","ir/analysis/sizedness.rs":"f0a9302f3c6ad694d76cfab11dbaf5392ecaf7f04bc7b211a5a003776b963896","ir/analysis/template_params.rs":"8f73a640cdd3b8e4e05fd5818eec8d36ba240ff131e8b785da3270c1335827a1","ir/annotations.rs":"eaacb6508b02d7d494bcaa50b9ba7acbe15f90f22130d3a24e2573909c08776f","ir/comment.rs":"4c9c20b5a3da086211e92adec0822831dbc0b7ebee98fee313edcae9ae8d55ec","ir/comp.rs":"fb32715ed8fc14bee51c344a41c1f7a8a802d4a6dceb2775034ea33a88670df7","ir/context.rs":"8b9f502e85ed563b46fc11eacb2e2140c19e7527dce4e31831cc9a571fbf87ff","ir/derive.rs":"c21e470bb0091f20bfa366110880d48984fc3cf7071fdf36eccfa64f3eca231c","ir/dot.rs":"75bdfd83d9e754ba726f6a5529ba1d9ff46f5bf49bf237452985eb008fed0854","ir/enum_ty.rs":"f4bfa6d18ba4977fb66f5d5e4a7674eded93b761404d91cdd6fdd50029db455a","ir/function.rs":"4cb04fbf40e8e8d4128c6182c84f21026b99446daf29ccba0871bedb275a5f81","ir/int.rs":"601736f0ad0949e40684a9ce89bafbfefa71743df6ee6c342e44888a0f141ae0","ir/item.rs":"5c0d0d2a7a327ac0c6ba1aadcef710b6d399c24bee3fbbd1ab6386e871c44033","ir/item_kind.rs":"33e21104b0bb824a696a52cd520567ae56158010a1df14777e68ac5f8ad7e8fa","ir/layout.rs":"e704c9c8cd1532f9890a1c6b43e3b6e691565b6acc2a9ce07486a4674497f511","ir/mod.rs":"a3b98b1732111a980a795c72eaf1e09101e842ef2de76b4f2d4a7857f8d4cee4","ir/module.rs":"f82f380274e9adbab8017bc5e484a23d945e2cb7a97ce17c9cd2a2cfc505bb54","ir/objc.rs":"0f55ff60db706241634ed8396108ec84ecbec80e0cf28f68ab580c868e0e0cb4","ir/template.rs":"3f59efa9670ca90215d4374be869c9dbecb98a8d1041e7c6e4ab69a62bb982c2","ir/traversal.rs":"a4ec73d3533d4b93386153baf6a2ca846ee51228c76ed51105229d3ddcd74466","ir/ty.rs":"7e479d601229619cf39073fc3570f4211666cc042a60ab27c810bdde0e5d5690","ir/var.rs":"40d18226706de0ee5f002d0b5617dbcba35de0605edd531c75e3a76d000f0f4f","lib.rs":"ef2927a0a84d50b6bea44d9e95f69d2dc9fc7bc75aff8fc3a5edd2919613a81c","log_stubs.rs":"9f974e041e35c8c7e29985d27ae5cd0858d68f8676d1dc005c6388d7d011707f","options/as_args.rs":"3b3547e08f0cb72fa042cde417bbc8760166d11dc0db4812e7a280c93074d2f5","options/helpers.rs":"f4a7681e29b2dcc3be9249478c499d685b9e29d4f4ca4ae8bff7a91668cd8f15","options/mod.rs":"f06194a21bf5b4a7039d1be80e5b0b3e4a310f48084a6e2b7abbb1539d0c2004","parse.rs":"fce3616e0464aa7414888e5d00d4df18c83bb3034a1c807d36a07a3c586e475a","regex_set.rs":"8b38dce6b4b34712f7eafcb2817024de18fccf0cead0c175de34f78ea4027545","time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a7f662e37488d6acc5b23048b3b8b1928c72b16b2d5ffc0435b88fbafe750b8b","Cargo.toml":"1c290771bddd3cde261935e253cd7574b648d1b321a0f3466d429eca3a3cce64","Cargo.toml.orig":"e423b71169c7d3277c0b992a0327d9f77c629db50921863ec81072361f28a208","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","build.rs":"4a9c4ac3759572e17de312a9d3f4ced3b6fd3c71811729e5a8d06bfbd1ac8f82","callbacks.rs":"985f5e3b19b870ec90baa89187b5049514fc5a259bc74fd6fb2ee857c52c11ff","clang.rs":"ee5130a029688f0eadc854c9873824330b6539e2eae597e2198b51e4e8f124a5","codegen/bitfield_unit.rs":"fddeaeab5859f4e82081865595b7705f5c0774d997df95fa5c655b81b9cae125","codegen/bitfield_unit_tests.rs":"9df86490de5e9d66ccea583dcb686dd440375dc1a3c3cf89a89d5de3883bf28a","codegen/dyngen.rs":"6d8bed53c6de66bc658b3186041c2b75549f49b0f0363ff18b87c8dcf2f5a05b","codegen/error.rs":"fa02274debd9064f35a627c43407e4e47ca89f2becfb1c233a500440d6c73e00","codegen/helpers.rs":"cf9e60d18d17d624f3559b6dd65e75630a16e6c1b71666f7c9656e51053d10f8","codegen/impl_debug.rs":"80df6136327b1ca8c7d1c2961290b5ab00b85b49b22c02f26a590bc68fb230af","codegen/impl_partialeq.rs":"db739d7ba6f5ba4033d6bf62c276f35217c20eab27230cf07dadf59e8b2f71bb","codegen/mod.rs":"89156a1926556d7c46b0266aabbb7c4e5a4a93fe1e5fc088f86acd3b14203f17","codegen/postprocessing/merge_extern_blocks.rs":"284457a3c75e945217bab4e5a4280fef0fcc03c31e12cc5010aab87f34c0b6c7","codegen/postprocessing/mod.rs":"160a6d6701cabf2514e23570df1bd1b648c909cc27b7c583f21d98fe0c16722e","codegen/postprocessing/sort_semantically.rs":"f465d1e8cc119082eb79c164b5cd780a370821e8bf56585b287dd3b51fc4a542","codegen/serialize.rs":"bb99633ab6a6764b84dac86a873fa64c90aa4979f26e75fbeff9af365b3fefa8","codegen/struct_layout.rs":"5685fc6caa24ac2779fbb885064043898830c00c92819e8c0e4fd9564c641c4d","deps.rs":"5ee2332fdb10325f3b0a0c6d9ba94e13eb631ef39e955fa958afc3625bdb5448","diagnostics.rs":"dc40cd5e9710922422c5c9420e2351f5d976e7a1d7275e4f4ce742cad9eb53f8","extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","features.rs":"6c17e37bdd14355c9c3f93b67e539bf001ea113a9efe287527e9021d785b5bda","ir/analysis/derive.rs":"cba290e9c4ba271e90524149ad3b874f37843bfdfab12d513cc85d2665447fd5","ir/analysis/has_destructor.rs":"e7e95c3b0989b6375cd3eabaac85a36ecc2915a1fd3700c7d26fe04e8dc83ba3","ir/analysis/has_float.rs":"a56b97bf913f132c2c63dc202b45c692c416a8c9fdc6b2baeee30362fb0d4405","ir/analysis/has_type_param_in_array.rs":"788ebb4ba2cf46a22f1e4ff3005d51f38d414b72e95355f7ff4125521e2d9525","ir/analysis/has_vtable.rs":"83efa40ae89147170eabdff1387e60aba574ca4cd4cdef22692753594f09d6c6","ir/analysis/mod.rs":"ed161d9f60306ad42af2ae70ff0eb686a36e2fb30eb94918b5e5f19af80e1db7","ir/analysis/sizedness.rs":"f0a9302f3c6ad694d76cfab11dbaf5392ecaf7f04bc7b211a5a003776b963896","ir/analysis/template_params.rs":"8f73a640cdd3b8e4e05fd5818eec8d36ba240ff131e8b785da3270c1335827a1","ir/annotations.rs":"eaacb6508b02d7d494bcaa50b9ba7acbe15f90f22130d3a24e2573909c08776f","ir/comment.rs":"4c9c20b5a3da086211e92adec0822831dbc0b7ebee98fee313edcae9ae8d55ec","ir/comp.rs":"fb32715ed8fc14bee51c344a41c1f7a8a802d4a6dceb2775034ea33a88670df7","ir/context.rs":"8b9f502e85ed563b46fc11eacb2e2140c19e7527dce4e31831cc9a571fbf87ff","ir/derive.rs":"c21e470bb0091f20bfa366110880d48984fc3cf7071fdf36eccfa64f3eca231c","ir/dot.rs":"75bdfd83d9e754ba726f6a5529ba1d9ff46f5bf49bf237452985eb008fed0854","ir/enum_ty.rs":"f4bfa6d18ba4977fb66f5d5e4a7674eded93b761404d91cdd6fdd50029db455a","ir/function.rs":"4cb04fbf40e8e8d4128c6182c84f21026b99446daf29ccba0871bedb275a5f81","ir/int.rs":"601736f0ad0949e40684a9ce89bafbfefa71743df6ee6c342e44888a0f141ae0","ir/item.rs":"5c0d0d2a7a327ac0c6ba1aadcef710b6d399c24bee3fbbd1ab6386e871c44033","ir/item_kind.rs":"33e21104b0bb824a696a52cd520567ae56158010a1df14777e68ac5f8ad7e8fa","ir/layout.rs":"e704c9c8cd1532f9890a1c6b43e3b6e691565b6acc2a9ce07486a4674497f511","ir/mod.rs":"a3b98b1732111a980a795c72eaf1e09101e842ef2de76b4f2d4a7857f8d4cee4","ir/module.rs":"f82f380274e9adbab8017bc5e484a23d945e2cb7a97ce17c9cd2a2cfc505bb54","ir/objc.rs":"0f55ff60db706241634ed8396108ec84ecbec80e0cf28f68ab580c868e0e0cb4","ir/template.rs":"3f59efa9670ca90215d4374be869c9dbecb98a8d1041e7c6e4ab69a62bb982c2","ir/traversal.rs":"a4ec73d3533d4b93386153baf6a2ca846ee51228c76ed51105229d3ddcd74466","ir/ty.rs":"7e479d601229619cf39073fc3570f4211666cc042a60ab27c810bdde0e5d5690","ir/var.rs":"40d18226706de0ee5f002d0b5617dbcba35de0605edd531c75e3a76d000f0f4f","lib.rs":"ef2927a0a84d50b6bea44d9e95f69d2dc9fc7bc75aff8fc3a5edd2919613a81c","log_stubs.rs":"9f974e041e35c8c7e29985d27ae5cd0858d68f8676d1dc005c6388d7d011707f","options/as_args.rs":"3b3547e08f0cb72fa042cde417bbc8760166d11dc0db4812e7a280c93074d2f5","options/helpers.rs":"f4a7681e29b2dcc3be9249478c499d685b9e29d4f4ca4ae8bff7a91668cd8f15","options/mod.rs":"f06194a21bf5b4a7039d1be80e5b0b3e4a310f48084a6e2b7abbb1539d0c2004","parse.rs":"fce3616e0464aa7414888e5d00d4df18c83bb3034a1c807d36a07a3c586e475a","regex_set.rs":"8b38dce6b4b34712f7eafcb2817024de18fccf0cead0c175de34f78ea4027545","time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bindgen/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bindgen/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bindgen/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7d243056d335fdc4537f7bca73c06d01aae24ddc" + }, + "path_in_vcs": "bindgen" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bindgen/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bindgen/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bindgen/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bindgen/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,59 @@ +[package] +authors = [ + "Jyun-Yan You ", + "Emilio Cobos Álvarez ", + "Nick Fitzgerald ", + "The Servo project developers", +] +description = "Automatically generates Rust FFI bindings to C and C++ libraries." +keywords = ["bindings", "ffi", "code-generation"] +categories = ["external-ffi-bindings", "development-tools::ffi"] +license = "BSD-3-Clause" +name = "bindgen" +readme = "../README.md" +repository = "https://github.com/rust-lang/rust-bindgen" +documentation = "https://docs.rs/bindgen" +homepage = "https://rust-lang.github.io/rust-bindgen/" +version = "0.65.1" +edition = "2018" +build = "build.rs" +# If you change this, also update README.md and msrv in .github/workflows/bindgen.yml +rust-version = "1.60.0" + +[lib] +name = "bindgen" +path = "lib.rs" + +[dependencies] +bitflags = "1.0.3" +cexpr = "0.6" +clang-sys = { version = "1", features = ["clang_6_0"] } +lazycell = "1" +lazy_static = "1" +peeking_take_while = "0.1.2" +quote = { version = "1", default-features = false } +syn = { version = "2.0", features = ["full", "extra-traits", "visit-mut"]} +regex = { version = "1.5", default-features = false , features = ["std", "unicode"] } +which = { version = "4.2.1", optional = true, default-features = false } +prettyplease = { version = "0.2.0" } +annotate-snippets = { version = "0.9.1", features = ["color"], optional = true } +shlex = "1" +rustc-hash = "1.0.1" +proc-macro2 = { version = "1", default-features = false } +log = { version = "0.4", optional = true } + +[features] +default = ["logging", "runtime", "which-rustfmt"] +logging = ["log"] +static = ["clang-sys/static"] +runtime = ["clang-sys/runtime"] +# Dynamically discover a `rustfmt` binary using the `which` crate +which-rustfmt = ["which"] +__cli = [] +experimental = ["annotate-snippets"] + +# These features only exist for CI testing -- don't use them if you're not hacking +# on bindgen! +testing_only_extra_assertions = [] +testing_only_libclang_9 = [] +testing_only_libclang_5 = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"6f7d3d5dff7f17d2bb671db4e3c1fc6033a9b3da3a27629cde59ecc384c485dd","Changelog.md":"ca67beb56c4ba8883fac47549e186e2694a38db6ceb6c5c845e521f4d70bda65","LICENSE-APACHE":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE-MIT":"2346961b4509d62a2f1c9327f84c64958593d84d9c3d87dd8fee45e3de1a9a58","README.md":"4a3b4f8d241e81c48d88a34a69711ad735c43eed075b583785fb5ceeef8b9a15","benches/bench.rs":"eff75a64946ca8d4c543ee4998c476e49a46bc55f9b0bede1ce5d7f8bc979a62","src/lib.rs":"f1885b7f9c4dd52011108ea13c18d24010eda205238b474231f0fedbd8b4df05","src/tests.rs":"4fd22cd4e3ddf7776dea357d203235dccef72b5fe7d8d497e492b3909ceb7621"},"package":"dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"7a90a09fd987deb67f9fadaba2650dace335aead56c6adbcc285e7c05fc5d6e6",".travis.yml":"328397015a42353120dd4bfa414d19ee3677f061444b983fe13993ee20def928","Cargo.toml":"6f7d3d5dff7f17d2bb671db4e3c1fc6033a9b3da3a27629cde59ecc384c485dd","Cargo.toml.orig":"f7b9402f1816487b028e4f11f20c4d4d8880b150d7384e70d7bb275f4445c139","Changelog.md":"ca67beb56c4ba8883fac47549e186e2694a38db6ceb6c5c845e521f4d70bda65","LICENSE-APACHE":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE-MIT":"2346961b4509d62a2f1c9327f84c64958593d84d9c3d87dd8fee45e3de1a9a58","README.md":"4a3b4f8d241e81c48d88a34a69711ad735c43eed075b583785fb5ceeef8b9a15","benches/bench.rs":"eff75a64946ca8d4c543ee4998c476e49a46bc55f9b0bede1ce5d7f8bc979a62","src/lib.rs":"f1885b7f9c4dd52011108ea13c18d24010eda205238b474231f0fedbd8b4df05","src/tests.rs":"4fd22cd4e3ddf7776dea357d203235dccef72b5fe7d8d497e492b3909ceb7621"},"package":"dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9a5f9ed6216537947ca82ec2d3ecf3dcbf157cec" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bit_field/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bit_field/.travis.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +language: rust +rust: + - stable + - beta + - nightly + +cache: cargo + +sudo: false + +script: + - cargo build --verbose --all + - cargo test --verbose --all + - if [ "${TRAVIS_RUST_VERSION}" = "nightly" ]; then + cargo bench --verbose --all; + fi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bit_field/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bit_field/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bit_field/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bit_field/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "bit_field" +version = "0.10.2" +authors = ["Philipp Oppermann "] +license = "Apache-2.0/MIT" + +description = "Simple bit field trait providing get_bit, get_bits, set_bit, and set_bits methods for Rust's integral types." +keywords = ["no_std"] +repository = "https://github.com/phil-opp/rust-bit-field" +documentation = "https://docs.rs/bit_field" + +[dependencies] + +[package.metadata.release] +dev-version = false +pre-release-replacements = [ + { file = "Changelog.md", search = "## Unreleased", replace = "## Unreleased\n\n# {{version}} – {{date}}", exactly = 1 }, +] +pre-release-commit-message = "Release version {{version}}" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"cb81297fc686539a786805dfef959e6f7c9b5fd55e451150cea68bcacc73ee8c","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","CONTRIBUTING.md":"6c9f96eacb20af877ae2d16f024904f3038b93448a8488e9dbcac0df7f6439a5","Cargo.lock":"04c2a120060e71f281a3a3f26f9be8dbc5a80102204f1f982ae0e2089557e646","Cargo.toml":"ed18e06a8a26ae38abea369bb062b6e6c1b714913ee9e64c060151f5ec966f5b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"e37efef64c50b073d5afcb6d2d43649cec6bf26d4022f32b5d77665bcb4c9049","SECURITY.md":"68704c8128fa2e776ed7cbda741fbf61ad52f998a96350ee7ee4dbf64c6573bc","benches/parse.rs":"f1390d62322c6880d65bd931e183d49b313f287879a6bfaa36b1cb1921090b51","examples/custom_bits_type.rs":"e53b32051adc5d97860e0b48c8f3a301a041d73b4939c0d7caa5f0cfcc0b9739","examples/custom_derive.rs":"29dd7b845345a103ca31e91b579aeb01fb74935b8223c29184eb42223edadb65","examples/fmt.rs":"87ba37a1fb8528570c74ea26d8e8948e1179c3d867b928bea1080880258e0a99","examples/macro_free.rs":"69e7f284b53b5214d51228a686e87f127b52a3b74711e45537ebfa5583a180e5","examples/serde.rs":"08b21b35d5c10fdca132fe0f36c8067bb44f559e96617a9257ab6316a20cbc75","spec.md":"fcdd939df30c59b0643be09027df664b71cbea9b9989185441482c5576160fed","src/example_generated.rs":"d018caf059f6ffc4c2403b771a6d76679fa5af03c329a91bd9252957df695e7f","src/external.rs":"734d3f470e6a669297d2df421ce3976fe613d8aa9c071d5ce6fe3ca890e5b815","src/external/arbitrary.rs":"fa8c9187028b9bc54856977b0914676f62101010e7a9450abd577fd78c89552f","src/external/bytemuck.rs":"3afcef382122867040fddd5e4153d633d1ed5596fe5d7dfac66a8e61c2513df5","src/external/serde.rs":"4a09db12534a20fe554a08dc5f1c8124b379292d41fa75628abcd2ca21587573","src/internal.rs":"645b13af0c7302258df61239073a4b8203d09f27b6c17f8a6f1f8c3e427f5334","src/iter.rs":"dbaa6437c1c044f689185ce3fafe43df8796bed19bbdd2c20334a52de5eeee73","src/lib.rs":"c7ade9eb151425815a8fc5afc558951a256d14143be36c4442bcae477571783b","src/parser.rs":"4e788b29f5d0542c409a8b43c703bcb4a6c2a57c181cadd17f565f0abb39681e","src/public.rs":"d151f7db62fefdb6cd2cad1038a785f02d1ce32eaab4c4cc84376283699182cc","src/tests.rs":"b120c27ff0c67a819527de9d8171f1f4c5d37ba4009c54abeb869c70e6035f14","src/tests/all.rs":"e99a865cd4271a524c2fe95503e96d851b35990570aed6fb2e9dac7a14da31b6","src/tests/bits.rs":"3840c34b2ea5d1802404b9ce5bcc1d3fa6ccd8dfba2e29e6d07c605f817d90df","src/tests/complement.rs":"d0e6d4c3daf49e0a7438c9f1c1ac91fad1b37f258c03593f6cd6a695ee626f5e","src/tests/contains.rs":"58bb3cb8c86550e775d11134da1d4aca85c83f943ea454e3a5f222772c674a24","src/tests/difference.rs":"d0d2b96bb52658b8ac019210da74ca75a53e76622f668855142ea6e97c28cb0e","src/tests/empty.rs":"817d6e93ced7cb7576ff0e334aa1a44703f3f96871ff2c6bdcb8f207e6551f67","src/tests/eq.rs":"b816767680a029e9c163e37af074dd4e604c4a3e4936f829f0ca3774fd5f0e37","src/tests/extend.rs":"5fabb9fd0254c64da019149c24063fceff72da3eb4ad73b57c1cc4c04b008364","src/tests/flags.rs":"2f48d3a25db1cf66fe98c9959abc70875deb9f7b38b2c278dc70c46e0d4ec277","src/tests/fmt.rs":"a2d4148491f3202f030f63633eee941b741e3be29a68cf376f008dbe5cb11e5c","src/tests/from_bits.rs":"d94c65b88bf89961d0cfc1b3152a7f1acc285bae160a1628438effda11b8e2c1","src/tests/from_bits_retain.rs":"980591dfaf91e940f42d9a1ce890f237514dd59d458fc264abcf9ceabbc40677","src/tests/from_bits_truncate.rs":"d3406b5e107ebb6449b98a59eee6cc5d84f947d4aaee1ee7e80dc7202de179f0","src/tests/from_name.rs":"f4a055d1f3c86decef70ef8f3020cef5c4e229718c20b3d59d5a3abc3a8b1298","src/tests/insert.rs":"3fab5da800a6fc0654dfb5f859f95da65a507eb9fda8695083c2712266dff0b9","src/tests/intersection.rs":"baf1454c9e4eba552264870a556ee0032d9f2bb8cac361833d571235e0b52221","src/tests/intersects.rs":"c55e36179fd8bc636f04ea9bbce346dcaafe57915d13f1df28c5b83117dbd08e","src/tests/is_all.rs":"b2f11faa7c954bd85c8fb39999e0c37d983cf7895152bc13c7ddde106aa33b6d","src/tests/is_empty.rs":"11f21323cdca7ff92dd89e09de667dba69e8dce88e2d3e27ea68ace91d15d070","src/tests/iter.rs":"4ba121932b527e787b82745405c7c65c1084c242e2dda3290d475ec160d265e4","src/tests/parser.rs":"fa2fb8dedcf16601af609a5e21d9c5840c7f96a1e3a587f7f2ea3dc8387f7628","src/tests/remove.rs":"6e75f8508d2dc1a2cba89ef691f4387a665a4fd13853bb1dd0fd80c783b89947","src/tests/symmetric_difference.rs":"0a89f084f9de1dd5b1932fe72c3b10a3c93cbaa16832b3a31b6a85e3bbd3ba6e","src/tests/union.rs":"88f398ee4600bb1e59bf6d02d1f6ff33f5f853eab5a6c700bd8a683c6ee4651a","src/traits.rs":"b79d008daec546136fae4497966fc85a33663d86ea2d9213fd23b412d4d77b66"},"package":"cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5ba2676c4a8061bebcfd17a6a98df15bc401ec2d781ec47a12ea4661324dd460","CHANGELOG.md":"cb81297fc686539a786805dfef959e6f7c9b5fd55e451150cea68bcacc73ee8c","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","CONTRIBUTING.md":"6c9f96eacb20af877ae2d16f024904f3038b93448a8488e9dbcac0df7f6439a5","Cargo.lock":"04c2a120060e71f281a3a3f26f9be8dbc5a80102204f1f982ae0e2089557e646","Cargo.toml":"ed18e06a8a26ae38abea369bb062b6e6c1b714913ee9e64c060151f5ec966f5b","Cargo.toml.orig":"722550c1a91ed45c03e43daa05545b851844e6999653093ab29891bf16ac99e3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"e37efef64c50b073d5afcb6d2d43649cec6bf26d4022f32b5d77665bcb4c9049","SECURITY.md":"68704c8128fa2e776ed7cbda741fbf61ad52f998a96350ee7ee4dbf64c6573bc","benches/parse.rs":"f1390d62322c6880d65bd931e183d49b313f287879a6bfaa36b1cb1921090b51","examples/custom_bits_type.rs":"e53b32051adc5d97860e0b48c8f3a301a041d73b4939c0d7caa5f0cfcc0b9739","examples/custom_derive.rs":"29dd7b845345a103ca31e91b579aeb01fb74935b8223c29184eb42223edadb65","examples/fmt.rs":"87ba37a1fb8528570c74ea26d8e8948e1179c3d867b928bea1080880258e0a99","examples/macro_free.rs":"69e7f284b53b5214d51228a686e87f127b52a3b74711e45537ebfa5583a180e5","examples/serde.rs":"08b21b35d5c10fdca132fe0f36c8067bb44f559e96617a9257ab6316a20cbc75","spec.md":"fcdd939df30c59b0643be09027df664b71cbea9b9989185441482c5576160fed","src/example_generated.rs":"d018caf059f6ffc4c2403b771a6d76679fa5af03c329a91bd9252957df695e7f","src/external.rs":"734d3f470e6a669297d2df421ce3976fe613d8aa9c071d5ce6fe3ca890e5b815","src/external/arbitrary.rs":"fa8c9187028b9bc54856977b0914676f62101010e7a9450abd577fd78c89552f","src/external/bytemuck.rs":"3afcef382122867040fddd5e4153d633d1ed5596fe5d7dfac66a8e61c2513df5","src/external/serde.rs":"4a09db12534a20fe554a08dc5f1c8124b379292d41fa75628abcd2ca21587573","src/internal.rs":"645b13af0c7302258df61239073a4b8203d09f27b6c17f8a6f1f8c3e427f5334","src/iter.rs":"dbaa6437c1c044f689185ce3fafe43df8796bed19bbdd2c20334a52de5eeee73","src/lib.rs":"c7ade9eb151425815a8fc5afc558951a256d14143be36c4442bcae477571783b","src/parser.rs":"4e788b29f5d0542c409a8b43c703bcb4a6c2a57c181cadd17f565f0abb39681e","src/public.rs":"d151f7db62fefdb6cd2cad1038a785f02d1ce32eaab4c4cc84376283699182cc","src/tests.rs":"b120c27ff0c67a819527de9d8171f1f4c5d37ba4009c54abeb869c70e6035f14","src/tests/all.rs":"e99a865cd4271a524c2fe95503e96d851b35990570aed6fb2e9dac7a14da31b6","src/tests/bits.rs":"3840c34b2ea5d1802404b9ce5bcc1d3fa6ccd8dfba2e29e6d07c605f817d90df","src/tests/complement.rs":"d0e6d4c3daf49e0a7438c9f1c1ac91fad1b37f258c03593f6cd6a695ee626f5e","src/tests/contains.rs":"58bb3cb8c86550e775d11134da1d4aca85c83f943ea454e3a5f222772c674a24","src/tests/difference.rs":"d0d2b96bb52658b8ac019210da74ca75a53e76622f668855142ea6e97c28cb0e","src/tests/empty.rs":"817d6e93ced7cb7576ff0e334aa1a44703f3f96871ff2c6bdcb8f207e6551f67","src/tests/eq.rs":"b816767680a029e9c163e37af074dd4e604c4a3e4936f829f0ca3774fd5f0e37","src/tests/extend.rs":"5fabb9fd0254c64da019149c24063fceff72da3eb4ad73b57c1cc4c04b008364","src/tests/flags.rs":"2f48d3a25db1cf66fe98c9959abc70875deb9f7b38b2c278dc70c46e0d4ec277","src/tests/fmt.rs":"a2d4148491f3202f030f63633eee941b741e3be29a68cf376f008dbe5cb11e5c","src/tests/from_bits.rs":"d94c65b88bf89961d0cfc1b3152a7f1acc285bae160a1628438effda11b8e2c1","src/tests/from_bits_retain.rs":"980591dfaf91e940f42d9a1ce890f237514dd59d458fc264abcf9ceabbc40677","src/tests/from_bits_truncate.rs":"d3406b5e107ebb6449b98a59eee6cc5d84f947d4aaee1ee7e80dc7202de179f0","src/tests/from_name.rs":"f4a055d1f3c86decef70ef8f3020cef5c4e229718c20b3d59d5a3abc3a8b1298","src/tests/insert.rs":"3fab5da800a6fc0654dfb5f859f95da65a507eb9fda8695083c2712266dff0b9","src/tests/intersection.rs":"baf1454c9e4eba552264870a556ee0032d9f2bb8cac361833d571235e0b52221","src/tests/intersects.rs":"c55e36179fd8bc636f04ea9bbce346dcaafe57915d13f1df28c5b83117dbd08e","src/tests/is_all.rs":"b2f11faa7c954bd85c8fb39999e0c37d983cf7895152bc13c7ddde106aa33b6d","src/tests/is_empty.rs":"11f21323cdca7ff92dd89e09de667dba69e8dce88e2d3e27ea68ace91d15d070","src/tests/iter.rs":"4ba121932b527e787b82745405c7c65c1084c242e2dda3290d475ec160d265e4","src/tests/parser.rs":"fa2fb8dedcf16601af609a5e21d9c5840c7f96a1e3a587f7f2ea3dc8387f7628","src/tests/remove.rs":"6e75f8508d2dc1a2cba89ef691f4387a665a4fd13853bb1dd0fd80c783b89947","src/tests/symmetric_difference.rs":"0a89f084f9de1dd5b1932fe72c3b10a3c93cbaa16832b3a31b6a85e3bbd3ba6e","src/tests/union.rs":"88f398ee4600bb1e59bf6d02d1f6ff33f5f853eab5a6c700bd8a683c6ee4651a","src/traits.rs":"b79d008daec546136fae4497966fc85a33663d86ea2d9213fd23b412d4d77b66"},"package":"cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e5ff0ca84b6aa5c9989c924ebe02527959bb7d02" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bitflags/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ +[package] +name = "bitflags" +# NB: When modifying, also modify the number in readme (for breaking changes) +version = "2.5.0" +edition = "2021" +rust-version = "1.56.0" +authors = ["The Rust Project Developers"] +license = "MIT OR Apache-2.0" +keywords = ["bit", "bitmask", "bitflags", "flags"] +readme = "README.md" +repository = "https://github.com/bitflags/bitflags" +homepage = "https://github.com/bitflags/bitflags" +documentation = "https://docs.rs/bitflags" +categories = ["no-std"] +description = """ +A macro to generate structures which behave like bitflags. +""" +exclude = ["/tests", "/.github"] + +[dependencies] +serde = { version = "1.0", optional = true, default-features = false } +arbitrary = { version = "1.0", optional = true } +bytemuck = { version = "1.0", optional = true } +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +compiler_builtins = { version = "0.1.2", optional = true } + +[dev-dependencies] +trybuild = "1.0" +rustversion = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +serde_test = "1.0" +zerocopy = "0.6" +arbitrary = { version = "1.0", features = ["derive"] } +bytemuck = { version = "1.0", features = ["derive"] } + +[features] +std = [] +example_generated = [] +rustc-dep-of-std = ["core", "compiler_builtins"] + +[package.metadata.docs.rs] +features = ["example_generated"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"d362fc1fccaaf4d421bcf0fe8b80ddb4f625dade0c1ee52d08bd0b95509a49d1","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"87aced7532a7974eb37ab5fe6037f0abafc36d6b2d74891ecd2bf2f14f50d11e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"baa8604f8afb34fd93b9c79729daafb884dedcaf34023e4af8ad037d916061fd","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"e6477688535ee326d27238aeedc9cb4320ac35b9d17a4deda09e0587b0ccdbd4","tests/basic.rs":"146f1cbf6279bc609242cd3349f29cb21b41294f5e4921875f5ec95bd83529a2","tests/compile-fail/impls/copy.rs":"b791371237ddc75a7c04d2130e03b462c9c00a80dca08bd45aa97433d9c0d13a","tests/compile-fail/impls/copy.stderr.beta":"77d83484ce221d4b6ff2f7de843929a452d779fcfff428122710dd8218c298e3","tests/compile-fail/impls/eq.rs":"0cee8b9e07d537890e0189710293b53972d0fab63c09366f33c391065afafa99","tests/compile-fail/impls/eq.stderr.beta":"381fc6143d45ce76d7cecc47aa59cb69fe5e79c0b60a4a85d5c6163b400b3cc7","tests/compile-fail/non_integer_base/all_defined.rs":"95e14cad9e94560262f2862c3c01865ac30369b69da1001b0e7285cb55e6cb75","tests/compile-fail/non_integer_base/all_defined.stderr.beta":"1760739a276690903bb03844025587d37939f5dfcbfab309db3c86f32bdbf748","tests/compile-fail/non_integer_base/all_missing.rs":"b3d9da619d23213731ba2581aa7999c796c3c79aaf4f0ee6b11ceec08a11537f","tests/compile-fail/non_integer_base/all_missing.stderr.beta":"37e102290d3867e175b21976be798939f294efb17580d5b51e7b17b590d55132","tests/compile-fail/visibility/private_field.rs":"38e4d3fe6471829360d12c8d09b097f6a21aa93fb51eac3b215d96bdae23316b","tests/compile-fail/visibility/private_field.stderr.beta":"5aa24a3ebb39326f31927721c5017b8beb66c3e501fb865a3fa814c9763bfa0f","tests/compile-fail/visibility/private_flags.rs":"2ce4235802aa4e9c96c4e77d9e31d8401ef58dcda4741325184f0764ab1fe393","tests/compile-fail/visibility/private_flags.stderr.beta":"f3eb9f7baf2689258f3519ff7ee5c6ec3c237264ebcfe63f40c40f2023e5022f","tests/compile-fail/visibility/pub_const.rs":"8f813a97ac518c5ea8ac65b184101912452384afaf7b8d6c5e62f8370eca3c0a","tests/compile-fail/visibility/pub_const.stderr.beta":"823976ae1794d7f5372e2ec9aabba497e7bb88004722904c38da342ed98e8962","tests/compile-pass/impls/convert.rs":"88fe80bfb9cd5779f0e1d92c9ec02a8b6bb67e334c07f2309e9c0ba5ef776eb0","tests/compile-pass/impls/default.rs":"c508f9a461691f44b45142fa5ad599f02326e1de4c0cbca6c0593f4652eba109","tests/compile-pass/impls/inherent_methods.rs":"ecc26388e9a394bfa7a5bb69a5d621ab3d4d1e53f28f657bb8e78fe79f437913","tests/compile-pass/redefinition/core.rs":"ff5b6e72f87acc6ebb12405d3c0f6e3fa62e669933656a454bb63b30ea44179c","tests/compile-pass/redefinition/stringify.rs":"1edbce42b900c14425d7ffa14e83e165ebe452d7dccd8c0a8a821bdec64f5c93","tests/compile-pass/repr/c.rs":"6fda17f7c2edfcd155314579e83d0fc8a16209e400f1f9a5ca77bd9a799041f2","tests/compile-pass/repr/transparent.rs":"6cdc87a2137d8a4e0c8ce9b6cba83c82255f8ea125951bf614418685600489ce","tests/compile-pass/visibility/bits_field.rs":"1f3e5ba5a047440066a9f6bf7b7af33f5b06f6b1da3dd9af6886168199a7ea0a","tests/compile-pass/visibility/pub_in.rs":"e95312ff60966d42ec4bc00225507895a9b8ec24056ce6a9edd9145be35d730f","tests/compile.rs":"f27c67a7dd183ca30efea1b6e0880e3469a6dd63b92b1fd711c082df182c9eec"},"package":"bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5386b6ede1417ea7b388580bcc0f40cd12a88b54c9f5fa324aba53d5b2177a53",".github/workflows/rust.yml":"01a64da62e40322f547eca8b38e92a4b0cd47bbbdc580d806cfbfc42cc85d07d","CHANGELOG.md":"d362fc1fccaaf4d421bcf0fe8b80ddb4f625dade0c1ee52d08bd0b95509a49d1","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"87aced7532a7974eb37ab5fe6037f0abafc36d6b2d74891ecd2bf2f14f50d11e","Cargo.toml.orig":"b4f5eefea5453292bbe9a91f618666eb346fac484f940bbc53fe927b8c2e0071","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"baa8604f8afb34fd93b9c79729daafb884dedcaf34023e4af8ad037d916061fd","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"e6477688535ee326d27238aeedc9cb4320ac35b9d17a4deda09e0587b0ccdbd4","tests/basic.rs":"146f1cbf6279bc609242cd3349f29cb21b41294f5e4921875f5ec95bd83529a2","tests/compile-fail/.gitignore":"5ff0d69b1ee1a840a51ebb0aca613aa8b2eb66e1d7be02d5d2e757b09fc8645b","tests/compile-fail/impls/copy.rs":"b791371237ddc75a7c04d2130e03b462c9c00a80dca08bd45aa97433d9c0d13a","tests/compile-fail/impls/copy.stderr.beta":"77d83484ce221d4b6ff2f7de843929a452d779fcfff428122710dd8218c298e3","tests/compile-fail/impls/eq.rs":"0cee8b9e07d537890e0189710293b53972d0fab63c09366f33c391065afafa99","tests/compile-fail/impls/eq.stderr.beta":"381fc6143d45ce76d7cecc47aa59cb69fe5e79c0b60a4a85d5c6163b400b3cc7","tests/compile-fail/non_integer_base/all_defined.rs":"95e14cad9e94560262f2862c3c01865ac30369b69da1001b0e7285cb55e6cb75","tests/compile-fail/non_integer_base/all_defined.stderr.beta":"1760739a276690903bb03844025587d37939f5dfcbfab309db3c86f32bdbf748","tests/compile-fail/non_integer_base/all_missing.rs":"b3d9da619d23213731ba2581aa7999c796c3c79aaf4f0ee6b11ceec08a11537f","tests/compile-fail/non_integer_base/all_missing.stderr.beta":"37e102290d3867e175b21976be798939f294efb17580d5b51e7b17b590d55132","tests/compile-fail/visibility/private_field.rs":"38e4d3fe6471829360d12c8d09b097f6a21aa93fb51eac3b215d96bdae23316b","tests/compile-fail/visibility/private_field.stderr.beta":"5aa24a3ebb39326f31927721c5017b8beb66c3e501fb865a3fa814c9763bfa0f","tests/compile-fail/visibility/private_flags.rs":"2ce4235802aa4e9c96c4e77d9e31d8401ef58dcda4741325184f0764ab1fe393","tests/compile-fail/visibility/private_flags.stderr.beta":"f3eb9f7baf2689258f3519ff7ee5c6ec3c237264ebcfe63f40c40f2023e5022f","tests/compile-fail/visibility/pub_const.rs":"8f813a97ac518c5ea8ac65b184101912452384afaf7b8d6c5e62f8370eca3c0a","tests/compile-fail/visibility/pub_const.stderr.beta":"823976ae1794d7f5372e2ec9aabba497e7bb88004722904c38da342ed98e8962","tests/compile-pass/impls/convert.rs":"88fe80bfb9cd5779f0e1d92c9ec02a8b6bb67e334c07f2309e9c0ba5ef776eb0","tests/compile-pass/impls/default.rs":"c508f9a461691f44b45142fa5ad599f02326e1de4c0cbca6c0593f4652eba109","tests/compile-pass/impls/inherent_methods.rs":"ecc26388e9a394bfa7a5bb69a5d621ab3d4d1e53f28f657bb8e78fe79f437913","tests/compile-pass/redefinition/core.rs":"ff5b6e72f87acc6ebb12405d3c0f6e3fa62e669933656a454bb63b30ea44179c","tests/compile-pass/redefinition/stringify.rs":"1edbce42b900c14425d7ffa14e83e165ebe452d7dccd8c0a8a821bdec64f5c93","tests/compile-pass/repr/c.rs":"6fda17f7c2edfcd155314579e83d0fc8a16209e400f1f9a5ca77bd9a799041f2","tests/compile-pass/repr/transparent.rs":"6cdc87a2137d8a4e0c8ce9b6cba83c82255f8ea125951bf614418685600489ce","tests/compile-pass/visibility/bits_field.rs":"1f3e5ba5a047440066a9f6bf7b7af33f5b06f6b1da3dd9af6886168199a7ea0a","tests/compile-pass/visibility/pub_in.rs":"e95312ff60966d42ec4bc00225507895a9b8ec24056ce6a9edd9145be35d730f","tests/compile.rs":"f27c67a7dd183ca30efea1b6e0880e3469a6dd63b92b1fd711c082df182c9eec"},"package":"bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "ed185cfb1c447c1b4bd6ac021c9ec3bb02c9e2f2" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/.github/workflows/rust.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,56 @@ +name: Rust + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + check: + name: Test + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + rust: + - stable + - beta + - nightly + - 1.46.0 + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + + - name: Default features + uses: actions-rs/cargo@v1 + with: + command: test + args: --features example_generated + + embedded: + name: Build (embedded) + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + target: thumbv6m-none-eabi + override: true + + - name: Default features + uses: actions-rs/cargo@v1 + with: + command: build + args: -Z avoid-dev-deps --features example_generated --target thumbv6m-none-eabi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/Cargo.toml.orig 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,39 @@ +[package] +name = "bitflags" +# NB: When modifying, also modify: +# 1. html_root_url in lib.rs +# 2. number in readme (for breaking changes) +version = "1.3.2" +edition = "2018" +authors = ["The Rust Project Developers"] +license = "MIT/Apache-2.0" +keywords = ["bit", "bitmask", "bitflags", "flags"] +readme = "README.md" +repository = "https://github.com/bitflags/bitflags" +homepage = "https://github.com/bitflags/bitflags" +documentation = "https://docs.rs/bitflags" +categories = ["no-std"] +description = """ +A macro to generate structures which behave like bitflags. +""" +exclude = ["bors.toml"] + +[dependencies] +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +compiler_builtins = { version = '0.1.2', optional = true } + +[dev-dependencies] +trybuild = "1.0" +rustversion = "1.0" +walkdir = "2.3" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" + +[features] +default = [] +example_generated = [] +rustc-dep-of-std = ["core", "compiler_builtins"] + +[package.metadata.docs.rs] +features = ["example_generated"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/tests/compile-fail/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/tests/compile-fail/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/bitflags-1.3.2/tests/compile-fail/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitflags-1.3.2/tests/compile-fail/.gitignore 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1 @@ +*.stderr diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"985c642ac6692653ff92b0b1661257169b44a3d7efe211b62bb09791c2fdbec4",".github/workflows/ci.yml":"c0b5ba40e5dd5d1dbe0343816c4673e8a7b3a35d8bf147470cc4c1e25ccf01be","CHANGES.md":"e17e841b3818f8276d67319329e2258fb758e5268a2af2304a02b6c2bbd5b740","Cargo.lock":"ca661ba02616034c3fd5a7c1165bbd78b91680d0a6134f307fec6f386fdfac8d","Cargo.toml":"c05e1a3159627e662951a5cfcce8fbadef1c912501eeeb6c824cee67770bba3f","Cargo.toml.orig":"c551d042fcd5cc01fcfeddad3ae421eb921dae73583b8f7635fcc9fb637a56c2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7a65c85c057a5538fdd8215b7aa2f3e0353f3b07c3e00bb409070b2b81375895","README.md":"7339cae960d3d15dcb23879afbc9b0d3c63c429f3cb0c2600663771133e52de2","examples/data/metadata-only.flac":"13d62b422a7db33198c9658bf671d2dee1db12ef6d0a7492525af01c6d697126","examples/flac-metadata-read.rs":"0f5d66967e46e88786f18dfe2ffa6be7e47734e6291da29d44e0b472b01467ce","examples/flac-metadata-write.rs":"c82f4c3406b1a1194d5da8116e93aa004252e44caf66ed53aae0ce5f987acf5e","src/byte_io.rs":"a777b7e21d0dcd39b3338c567969d566ae8bfe441cc672a9bf002c4f057e2c95","src/huffman.rs":"fd064d85afc265bed1cf172fa63f1a150ceb7af0386c5cf3c95be0fcd02fa7ce","src/lib.rs":"1ca6d01d744402e56df0a1c69ae1117d3e15c9a6856680774a0dea9163e8ed15","src/read.rs":"a75abb462d3f188437e1028c17a218ecc570f42d50f9b609b15b912536d9b909","src/write.rs":"d81250744ddbbf98bc94be34fa2a5dc03deddff9e4738cd663cdffa6b4dedfff","tests/huffman.rs":"5a7bdf0ad7d0039244e621f51951effb983f97d8aca236fb8e802a7efebe1822","tests/random-3be.bin":"85d55037586a21fbaabbfd4ca4f9d396f3bd7ce4e1a6f394f06b70937137081a","tests/random-3le.bin":"85a6b0845b9e409e6bd30628ab3ca0092ec9ab7d870ad71b4274a4214be63643","tests/random.bin":"33910ffdefd3d5dbb09ebcd2d6e9bdd159aec82ed919154192f1e36f61cc2e88","tests/read.rs":"eaeeb3099539157d83d22ca6b65906e4faed0c919a80aeafbbbe295d3b4bdc27","tests/read_seek.rs":"a2a2da8e07bbc845bde858f618bbb3919693ddfa34f21ace9d38db6f630b7cca","tests/roundtrip.rs":"f0b7bf5c27cfed504104315669a211ecc9495f52ed62a0ad31b629ac7175bf19","tests/write.rs":"929a8fec093802e3385fdb4a45e3dd1b6712714bbc2b7ffcf50ad6e7e2a0f4a4"},"package":"60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "63e05b218f27217b0d83384efa6d4e12e419c953" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +name: Rust CI + +on: + push: + pull_request: + +jobs: + build: + name: Build & Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: clippy + + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@main + + - name: Run tests + run: cargo test + + - name: Check (no_std) + run: cargo check --no-default-features + + - name: Check (no_std, alloc) + run: cargo check --no-default-features --features alloc + + - name: Run clippy + run: cargo clippy + + - name: Install cargo-msrv + run: cargo binstall --no-confirm cargo-msrv + + - name: Verify MSRV + run: cargo msrv verify diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/CHANGES.md clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/CHANGES.md --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/CHANGES.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/CHANGES.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +# 4.9.0 + +- Further extend VBR integer support + +# 4.8.0 + +- Add io::Seek support to ByteReader + +# 4.7.0 + +- Add support for LLVM-style variable bit rate integers + +# 4.6.0 + +- Add no alloc support + +# 4.5.0 + +- Implement new `CheckedSignedFixed` type alias +- Implement `FixedSignedBitCount` for use by `CheckedSignedFixed` + +# 4.4.0 + +- Implement new `CheckedUnsignedFixed` type alias +- Implement `FixedBitCount` for use by `CheckedUnsignedFixed` + +# 4.3.0 + +- Add `bytes` method to ToByteStream traits with default implementations + +# 4.2.0 + +- Add `Checked` API for avoiding redundant validation during writes +- Add `BitCount`-related helper methods to optimize unary writes + +# 4.1.0 + +- Implement `FromBitStreamUsing` convenience trait +- Implement `FromByteStreamUsing` convenience trait +- Implement `ToBitStreamUsing` convenience trait +- Implement `ToByteStreamUsing` convenience trait + +# 4.0.0 + +- Implement `SignedBitCount` for signed integer types. +- Remove endianness requirement for `BitCounter` +- Optimize `BitRecorder` implementation to be much faster +- Optimize read/write_bytes to be much faster for un-aligned bytes +- Seal `Endianness` traits from further downstream implementation + +# 3.2.0 + +- Implement `Integer` for `bool` and arrays of `Integer` types. +- Add a `read_const` method to `BitRead` for consisency with `BitWrite::write_const`. +- Widen unknown `BitCount` values to handle more edge cases. + +# 3.1.0 + +- Implement `Integer` for the unsigned `NonZero` types. +- Add byte alignment convenience methods. +- Fix `BitCount.checked_sub` for consistency with `checked_add`. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitstream-io" +version = "4.9.0" +dependencies = [ + "core2", +] + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,87 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.83" +name = "bitstream-io" +version = "4.9.0" +authors = ["Brian Langenberger "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Library for reading/writing un-aligned values from/to streams in big-endian and little-endian formats." +homepage = "https://github.com/tuffy/bitstream-io" +documentation = "https://docs.rs/bitstream-io/" +readme = "README.md" +keywords = [ + "bitstream", + "endian", + "big-endian", + "little-endian", + "binary", +] +license = "MIT/Apache-2.0" +repository = "https://github.com/tuffy/bitstream-io" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +alloc = ["core2/alloc"] +default = ["std"] +std = [ + "core2/std", + "alloc", +] + +[lib] +name = "bitstream_io" +path = "src/lib.rs" + +[[example]] +name = "flac-metadata-read" +path = "examples/flac-metadata-read.rs" + +[[example]] +name = "flac-metadata-write" +path = "examples/flac-metadata-write.rs" + +[[test]] +name = "huffman" +path = "tests/huffman.rs" + +[[test]] +name = "read" +path = "tests/read.rs" + +[[test]] +name = "read_seek" +path = "tests/read_seek.rs" + +[[test]] +name = "roundtrip" +path = "tests/roundtrip.rs" + +[[test]] +name = "write" +path = "tests/write.rs" + +[dependencies.core2] +version = "0.4" +default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +[package] +name = "bitstream-io" +description = "Library for reading/writing un-aligned values from/to streams in big-endian and little-endian formats." +keywords = ["bitstream", "endian", "big-endian", "little-endian", "binary"] +version = "4.9.0" +authors = ["Brian Langenberger "] +license = "MIT/Apache-2.0" +documentation = "https://docs.rs/bitstream-io/" +homepage = "https://github.com/tuffy/bitstream-io" +repository = "https://github.com/tuffy/bitstream-io" +edition = "2018" +rust-version = "1.83" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +core2 = { version = "0.4", default-features = false } + +[features] +std = ["core2/std", "alloc"] +alloc = ["core2/alloc"] +default = ["std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2017 Brian Langenberger + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/README.md clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +bitstream-io +============ + +A Rust library for reading or writing binary values to or from streams +which may not be aligned at a whole byte. + +This library is intended to be flexible enough to wrap +around any stream which implements the `Read` or `Write` traits. +It also supports a wide array of integer data types as +containers for those binary values. + +## Minimum Compiler Version + +Beginning with version 2.4, the minimum compiler version has been +updated to Rust 1.79 in order to support compile-time assertion +in `const` blocks, which can be used to check for a class +of errors at compile-time rather than runtime. Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/examples/data/metadata-only.flac and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/data/metadata-only.flac differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-read.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-read.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,148 @@ +//! Reading the initial STREAMINFO block from a FLAC file, +//! as documented in its +//! [specification](https://xiph.org/flac/format.html#stream). +//! + +extern crate bitstream_io; + +use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStream}; +use std::num::NonZero; + +#[derive(Debug, PartialEq, Eq)] +struct BlockHeader { + last_block: bool, // 1 bit + block_type: u8, // 7 bits + block_size: u32, // 24 bits +} + +impl FromBitStream for BlockHeader { + type Error = std::io::Error; + + fn from_reader(r: &mut R) -> std::io::Result { + Ok(Self { + last_block: r.read_bit()?, + block_type: r.read::<7, _>()?, + block_size: r.read::<24, _>()?, + }) + } +} + +#[derive(Debug, PartialEq, Eq)] +struct Streaminfo { + minimum_block_size: u16, // 16 bits + maximum_block_size: u16, // 16 bits + minimum_frame_size: u32, // 24 bits + maximum_frame_size: u32, // 24 bits + sample_rate: u32, // 20 bits + channels: NonZero, // 3 bits + bits_per_sample: NonZero, // 5 bits + total_samples: u64, // 36 bits + md5: [u8; 16], // 16 bytes +} + +impl FromBitStream for Streaminfo { + type Error = std::io::Error; + + fn from_reader(r: &mut R) -> std::io::Result { + Ok(Self { + minimum_block_size: r.read_to()?, + maximum_block_size: r.read_to()?, + minimum_frame_size: r.read::<24, _>()?, + maximum_frame_size: r.read::<24, _>()?, + sample_rate: r.read::<20, _>()?, + channels: r.read::<3, _>()?, + bits_per_sample: r.read::<5, _>()?, + total_samples: r.read::<36, _>()?, + md5: r.read_to()?, + }) + } +} + +#[derive(Debug, PartialEq, Eq)] +struct VorbisComment { + vendor: String, + comment: Vec, +} + +impl FromBitStream for VorbisComment { + type Error = Box; + + fn from_reader(r: &mut R) -> Result { + use bitstream_io::LE; + + fn read_entry( + r: &mut R, + ) -> Result> { + use std::convert::TryInto; + let size = r.read_as_to::()?.try_into()?; + Ok(String::from_utf8(r.read_to_vec(size)?)?) + } + + Ok(Self { + vendor: read_entry(r)?, + comment: (0..r.read_as_to::()?) + .map(|_| read_entry(r)) + .collect::, _>>()?, + }) + } +} + +fn main() { + // test FLAC file data + let flac = include_bytes!("data/metadata-only.flac"); + + let mut reader = BitReader::endian(flac.as_slice(), BigEndian); + + // stream marker + assert_eq!(&reader.read_to::<[u8; 4]>().unwrap(), b"fLaC"); + + // metadata block header + assert_eq!( + reader.parse::().unwrap(), + BlockHeader { + last_block: false, + block_type: 0, + block_size: 34 + } + ); + + // STREAMINFO block + assert_eq!( + dbg!(reader.parse::().unwrap()), + Streaminfo { + minimum_block_size: 4096, + maximum_block_size: 4096, + minimum_frame_size: 1542, + maximum_frame_size: 8546, + sample_rate: 44100, + channels: NonZero::new(2).unwrap(), + bits_per_sample: NonZero::new(16).unwrap(), + total_samples: 304844, + md5: *b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92", + } + ); + + // metadata block header + assert_eq!( + dbg!(reader.parse::().unwrap()), + BlockHeader { + last_block: false, + block_type: 4, + block_size: 122 + } + ); + + // VORBIS_COMMENT block + assert_eq!( + dbg!(reader.parse::().unwrap()), + VorbisComment { + vendor: "reference libFLAC 1.1.4 20070213".to_string(), + comment: vec![ + "title=2ch 44100 16bit".to_string(), + "album=Test Album".to_string(), + "artist=Assorted".to_string(), + "tracknumber=1".to_string(), + ], + } + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-write.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-write.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/examples/flac-metadata-write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +extern crate bitstream_io; + +// Writing the initial STREAMINFO block to a FLAC file, +// as documented in its +// [specification](https://xiph.org/flac/format.html#stream). + +use bitstream_io::{ + BigEndian, BitWrite, BitWriter, ByteWrite, ByteWriter, LittleEndian, ToBitStream, +}; +use std::convert::TryInto; +use std::num::NonZero; + +#[derive(Debug, PartialEq, Eq)] +struct BlockHeader { + last_block: bool, // 1 bit + block_type: u8, // 7 bits + block_size: u32, // 24 bits +} + +impl ToBitStream for BlockHeader { + type Error = std::io::Error; + + fn to_writer(&self, w: &mut W) -> std::io::Result<()> { + w.write_bit(self.last_block)?; + w.write::<7, _>(self.block_type)?; + w.write::<24, _>(self.block_size) + } +} + +#[derive(Debug, PartialEq, Eq)] +struct Streaminfo { + minimum_block_size: u16, // 16 bits + maximum_block_size: u16, // 16 bits + minimum_frame_size: u32, // 24 bits + maximum_frame_size: u32, // 24 bits + sample_rate: u32, // 20 bits + channels: NonZero, // 3 bits + bits_per_sample: NonZero, // 5 bits + total_samples: u64, // 36 bits + md5: [u8; 16], // 16 bytes +} + +impl ToBitStream for Streaminfo { + type Error = std::io::Error; + + fn to_writer(&self, w: &mut W) -> std::io::Result<()> { + w.write_from(self.minimum_block_size)?; + w.write_from(self.maximum_block_size)?; + w.write::<24, _>(self.minimum_frame_size)?; + w.write::<24, _>(self.maximum_frame_size)?; + w.write::<20, _>(self.sample_rate)?; + w.write::<3, _>(self.channels)?; + w.write::<5, _>(self.bits_per_sample)?; + w.write::<36, _>(self.total_samples)?; + w.write_bytes(&self.md5) + } +} + +#[derive(Debug, PartialEq, Eq)] +struct VorbisComment { + vendor: String, + comment: Vec, +} + +impl VorbisComment { + fn len(&self) -> usize { + 4 + self.vendor.len() + 4 + self.comment.iter().map(|c| 4 + c.len()).sum::() + } + + fn write(&self, w: &mut ByteWriter) -> std::io::Result<()> { + use std::convert::TryInto; + + fn write_entry( + w: &mut ByteWriter, + s: &str, + ) -> std::io::Result<()> { + w.write::(s.len().try_into().unwrap())?; + w.write_bytes(s.as_bytes()) + } + + write_entry(w, &self.vendor)?; + w.write::(self.comment.len().try_into().unwrap())?; + self.comment.iter().try_for_each(|s| write_entry(w, s)) + } +} + +fn main() { + let mut flac: Vec = Vec::new(); + + let mut writer = BitWriter::endian(&mut flac, BigEndian); + + // stream marker + writer.write_bytes(b"fLaC").unwrap(); + + // metadata block header + writer + .build(&BlockHeader { + last_block: false, + block_type: 0, + block_size: 34, + }) + .unwrap(); + + // STREAMINFO block + writer + .build(&Streaminfo { + minimum_block_size: 4096, + maximum_block_size: 4096, + minimum_frame_size: 1542, + maximum_frame_size: 8546, + sample_rate: 44100, + channels: NonZero::new(2).unwrap(), + bits_per_sample: NonZero::new(16).unwrap(), + total_samples: 304844, + md5: *b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92", + }) + .unwrap(); + + let comment = VorbisComment { + vendor: "reference libFLAC 1.1.4 20070213".to_string(), + comment: vec![ + "title=2ch 44100 16bit".to_string(), + "album=Test Album".to_string(), + "artist=Assorted".to_string(), + "tracknumber=1".to_string(), + ], + }; + + // metadata block header + writer + .build(&BlockHeader { + last_block: false, + block_type: 4, + block_size: comment.len().try_into().unwrap(), + }) + .unwrap(); + + // VORBIS_COMMENT block (little endian) + comment + .write(&mut ByteWriter::new(writer.writer().unwrap())) + .unwrap(); + + assert_eq!(flac, include_bytes!("data/metadata-only.flac")); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/byte_io.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/byte_io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/byte_io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/byte_io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +pub trait ByteSource: Sized { + type Error: Sized; + + #[inline(always)] + fn read_byte(&mut self) -> Result { + let mut byte = 0; + self.read_bytes(core::slice::from_mut(&mut byte)) + .map(|()| byte) + } + + fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>; + + fn skip_bytes(&mut self, bytes: u32) -> Result<(), Self::Error> { + fn skip_chunks( + reader: &mut R, + mut bytes: usize, + ) -> Result<(), R::Error> + where + R: ByteSource, + { + let mut buf = [0; SIZE]; + while bytes > 0 { + let to_read = bytes.min(SIZE); + reader.read_bytes(&mut buf[0..to_read])?; + bytes -= to_read; + } + Ok(()) + } + + match bytes { + 0..256 => skip_chunks::<8, Self>(self, bytes as usize), + 256..1024 => skip_chunks::<256, Self>(self, bytes as usize), + 1024..4096 => skip_chunks::<1024, Self>(self, bytes as usize), + _ => skip_chunks::<4096, Self>(self, bytes as usize), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/huffman.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits and implementations for reading or writing Huffman codes +//! from or to a stream. + +#![warn(missing_docs)] + +/// A trait for building a final value from individual bits +/// +/// Though similar to the [`crate::read::FromBitStream`] trait, +/// this is intended to parse short symbols from a stream of bits +/// while `FromBitStream` is meant for parsing larger structs from +/// a whole reader. +/// For example, one might have several [`FromBits`] implementations +/// in a single program that all generate `i32` symbols from bits, +/// but implementing `FromBitStream` multiple times for `i32` +/// isn't possible (or practical). +pub trait FromBits { + /// Our returned symbol type + type Symbol; + + /// Given a fallable bit generator, return our output type + /// + /// # Errors + /// + /// Passes along any error from the bit generator + fn from_bits(next: F) -> Result + where + F: FnMut() -> Result; +} + +/// For building individual bits from a final value +/// +/// Though similar to the [`crate::write::ToBitStream`] trait, +/// this is intended to generate a stream of bits from short symbols +/// while `ToBitStream` is meant for writing larger structs to +/// a whole writer. +/// For example, one might have several [`ToBits`] implementations +/// in a single program that all write `i32` symbols to bits, +/// but implementing `ToBitStream` multiple times for `i32` +/// isn't possible (or practical). +pub trait ToBits { + /// The type we accept to output + type Symbol; + + /// Given a value to generate, write out bits as needed. + /// + /// Outputs nothing if the symbol isn't defined. + /// + /// # Errors + /// + /// Passes along any error from the bit generator + fn to_bits(value: Self::Symbol, write: F) -> Result<(), E> + where + F: FnMut(bool) -> Result<(), E>; +} + +/// Defines a new Huffman tree for reading and writing +/// +/// Its syntax is: `define_huffman_tree!(name : type = nodes)` +/// where `name` is some identifier to identify the tree in the +/// macro's current scope, `type` is the tree's output +/// type (which should implement `Copy` and `Eq`), and `nodes` is either a +/// final leaf value or a `[bit_0, bit_1]` pair where `bit_0` is +/// the tree visited on a `0` bit, and `bit_1` is the tree visited +/// on a `1` bit. +/// +/// # Example +/// +/// ``` +/// use bitstream_io::{define_huffman_tree, huffman::FromBits}; +/// define_huffman_tree!(TreeName : &'static str = ["bit 0", ["bit 1->0", "bit 1->1"]]); +/// let mut bits = [true, false].iter().copied(); +/// assert_eq!(TreeName::from_bits(|| bits.next().ok_or(())).unwrap(), "bit 1->0"); +/// ``` +#[macro_export] +macro_rules! define_huffman_tree { + ($name:ident : $type:ty = $nodes:tt) => { + #[derive(Copy, Clone, Debug)] + struct $name; + + impl $crate::huffman::FromBits for $name { + type Symbol = $type; + + fn from_bits(mut next: F) -> Result + where + F: FnMut() -> Result, + { + $crate::compile_read_tree_nodes!(next, $nodes) + } + } + + impl $crate::huffman::ToBits for $name { + type Symbol = $type; + + fn to_bits(value: Self::Symbol, mut write: F) -> Result<(), E> + where + F: FnMut(bool) -> Result<(), E> + { + $crate::compile_write_tree_nodes!(value ; write ; $nodes ; ); + Ok(()) + } + } + }; +} + +/// A helper macro for compiling individual Huffman tree nodes +#[macro_export] +macro_rules! compile_read_tree_nodes { + ($next:ident , [$bit_0:tt, $bit_1:tt]) => { + if $next()? { + $crate::compile_read_tree_nodes!($next, $bit_1) + } else { + $crate::compile_read_tree_nodes!($next, $bit_0) + } + }; + ($next:ident , $final:tt) => { + Ok($final) + }; +} + +/// A helper macro for compiling individual Huffman tree nodes +#[macro_export] +macro_rules! compile_write_tree_nodes { + ($value:ident ; $write:ident ; [$bit_0:tt, $bit_1:tt] ; ) => { + $crate::compile_write_tree_nodes!($value ; $write ; $bit_0 ; false); + $crate::compile_write_tree_nodes!($value ; $write ; $bit_1 ; true); + }; + ($value:ident ; $write:ident ; [$bit_0:tt, $bit_1:tt] ; $($bits:tt),*) => { + $crate::compile_write_tree_nodes!($value ; $write ; $bit_0 ; $($bits),* , false); + $crate::compile_write_tree_nodes!($value ; $write ; $bit_1 ; $($bits),* , true); + }; + ($value:ident ; $write:ident ; $final:tt ; $( $bits:tt),* ) => { + if $value == $final { + $( $write($bits)?; )* + return Ok(()); + } + }; +} + +/// A limited unary reader which stops at the given maximum. +/// +/// Counts non-`STOP_BIT` values (which must be 0 or 1) +/// until `STOP_BIT`, or until `MAXIMUM` is reached. +/// Returns the number of non-`STOP_BIT` bits, or `None` if +/// maximum is reached beforehand. +/// +/// # Examples +/// ``` +/// use bitstream_io::{BitReader, BitRead, BigEndian, huffman::LimitedUnary}; +/// +/// let data: &[u8] = &[0b001_00000, 0b1111_1111]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // get 2 bits until the next 1 bit +/// assert_eq!(r.read_huffman::>().unwrap(), Some(2)); +/// // but 5 bits in a row is our maximum +/// assert_eq!(r.read_huffman::>().unwrap(), None); +/// // the remaining 8 bits are ok to be read +/// assert_eq!(r.read::<8, u8>().unwrap(), 0b1111_1111); +/// ``` +/// +/// ``` +/// use bitstream_io::{BitWriter, BitWrite, BigEndian, huffman::LimitedUnary}; +/// +/// let mut w = BitWriter::endian(vec![], BigEndian); +/// // writes 2 as a regular unary value which stops at the 1 bit +/// w.write_huffman::>(Some(2)).unwrap(); +/// // writing values beyond the maximum does nothing +/// w.write_huffman::>(Some(10)).unwrap(); +/// // writes 5, 0 bits (which is our maximum) +/// w.write_huffman::>(None).unwrap(); +/// // write some 1 bits to pad out the stream +/// w.write::<8, u8>(0b1111_1111); +/// +/// assert_eq!(w.into_writer(), &[0b001_00000, 0b1111_1111]); +/// ``` +#[derive(Copy, Clone, Debug)] +pub struct LimitedUnary; + +impl FromBits for LimitedUnary { + type Symbol = Option; + + fn from_bits(mut next: F) -> Result + where + F: FnMut() -> Result, + { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + let mut bits = 0; + while bits < MAXIMUM { + if next()? + != match STOP_BIT { + 0 => false, + 1 => true, + _ => unreachable!(), + } + { + bits += 1; + } else { + return Ok(Some(bits)); + } + } + Ok(None) + } +} + +impl ToBits for LimitedUnary { + type Symbol = Option; + + fn to_bits(value: Option, mut write: F) -> Result<(), E> + where + F: FnMut(bool) -> Result<(), E>, + { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + match value { + Some(bits) if bits < MAXIMUM => { + (0..bits).try_for_each(|_| { + write(match STOP_BIT { + 0 => true, + 1 => false, + _ => unreachable!(), + }) + })?; + write(match STOP_BIT { + 0 => false, + 1 => true, + _ => unreachable!(), + }) + } + Some(_) => { + /*more bits than MAXIMUM, so output nothing*/ + Ok(()) + } + None => (0..MAXIMUM).try_for_each(|_| { + write(match STOP_BIT { + 0 => true, + 1 => false, + _ => unreachable!(), + }) + }), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3762 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits and helpers for bitstream handling functionality +//! +//! Bitstream readers are for reading signed and unsigned integer +//! values from a stream whose sizes may not be whole bytes. +//! Bitstream writers are for writing signed and unsigned integer +//! values to a stream, also potentially un-aligned at a whole byte. +//! +//! Both big-endian and little-endian streams are supported. +//! +//! The only requirement for wrapped reader streams is that they must +//! implement the [`io::Read`] trait, and the only requirement +//! for writer streams is that they must implement the [`io::Write`] trait. +//! +//! In addition, reader streams do not consume any more bytes +//! from the underlying reader than necessary, buffering only a +//! single partial byte as needed. +//! Writer streams also write out all whole bytes as they are accumulated. +//! +//! Readers and writers are also designed to work with integer +//! types of any possible size. +//! Many of Rust's built-in integer types are supported by default. + +//! # Minimum Compiler Version +//! +//! Beginning with version 2.4, the minimum compiler version has been +//! updated to Rust 1.79. +//! +//! The issue is that reading an excessive number of +//! bits to a type which is too small to hold them, +//! or writing an excessive number of bits from too small of a type, +//! are always errors: +//! ``` +//! use std::io::{Read, Cursor}; +//! use bitstream_io::{BigEndian, BitReader, BitRead}; +//! let data = [0; 10]; +//! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); +//! let x: Result = r.read_var(64); // reading 64 bits to u32 always fails at runtime +//! assert!(x.is_err()); +//! ``` +//! but those errors will not be caught until the program runs, +//! which is less than ideal for the common case in which +//! the number of bits is already known at compile-time. +//! +//! But starting with Rust 1.79, we can now have read and write methods +//! which take a constant number of bits and can validate the number of bits +//! are small enough for the type being read/written at compile-time: +//! ```rust,compile_fail +//! use std::io::{Read, Cursor}; +//! use bitstream_io::{BigEndian, BitReader, BitRead}; +//! let data = [0; 10]; +//! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); +//! let x: Result = r.read::<64, _>(); // doesn't compile at all +//! ``` +//! Since catching potential bugs at compile-time is preferable +//! to encountering errors at runtime, this will hopefully be +//! an improvement in the long run. + +//! # Changes From 3.X.X +//! +//! Version 4.0.0 features significant optimizations to the [`BitRecorder`] +//! and deprecates the [`BitCounter`] in favor of [`BitsWritten`], +//! which no longer requires specifying an endianness. +//! +//! In addition, the [`BitRead::read_bytes`] and [`BitWrite::write_bytes`] +//! methods are significantly optimized in the case of non-aligned +//! reads and writes. +//! +//! Finally, the [`Endianness`] traits have been sealed so as not +//! to be implemented by other packages. Given that other endianness +//! types are extremely rare in file formats and end users should not +//! have to implement this trait themselves, this should not be a +//! concern. +//! +//! # Changes From 2.X.X +//! +//! Version 3.0.0 has made many breaking changes to the [`BitRead`] and +//! [`BitWrite`] traits. +//! +//! The [`BitRead::read`] method takes a constant number of bits, +//! and the [`BitRead::read_var`] method takes a variable number of bits +//! (reversing the older [`BitRead2::read_in`] and [`BitRead2::read`] +//! calling methods to emphasize using the constant-based one, +//! which can do more validation at compile-time). +//! A new [`BitRead2`] trait uses the older calling convention +//! for compatibility with existing code and is available +//! for anything implementing [`BitRead`]. +//! +//! In addition, the main reading methods return primitive types which +//! implement a new [`Integer`] trait, +//! which delegates to [`BitRead::read_unsigned`] +//! or [`BitRead::read_signed`] depending on whether the output +//! is an unsigned or signed type. +//! +//! [`BitWrite::write`] and [`BitWrite::write_var`] work +//! similarly to the reader's `read` methods, taking anything +//! that implements [`Integer`] and writing an unsigned or +//! signed value to [`BitWrite::write_unsigned`] or +//! [`BitWrite::write_signed`] as appropriate. +//! +//! And as with reading, a [`BitWrite2`] trait is offered +//! for compatibility. +//! +//! In addition, the Huffman code handling has been rewritten +//! to use a small amount of macro magic to write +//! code to read and write symbols at compile-time. +//! This is significantly faster than the older version +//! and can no longer fail to compile at runtime. +//! +//! Lastly, there's a new [`BitCount`] struct which wraps a humble +//! `u32` but encodes the maximum possible number of bits +//! at the type level. +//! This is intended for file formats which encode the number +//! of bits to be read in the format itself. +//! For example, FLAC's predictor coefficient precision +//! is a 4 bit value which indicates how large each predictor +//! coefficient is in bits +//! (each coefficient might be an `i32` type). +//! By keeping track of the maximum value at compile time +//! (4 bits' worth, in this case), we can eliminate +//! any need to check that coefficients aren't too large +//! for an `i32` at runtime. +//! This is accomplished by using [`BitRead::read_count`] to +//! read a [`BitCount`] and then reading final values with +//! that number of bits using [`BitRead::read_counted`]. + +//! # Migrating From Pre 1.0.0 +//! +//! There are now [`BitRead`] and [`BitWrite`] traits for bitstream +//! reading and writing (analogous to the standard library's +//! `Read` and `Write` traits) which you will also need to import. +//! The upside to this approach is that library consumers +//! can now make functions and methods generic over any sort +//! of bit reader or bit writer, regardless of the underlying +//! stream byte source or endianness. + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn(missing_docs)] +#![forbid(unsafe_code)] +#![no_std] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +#[cfg(not(feature = "std"))] +use core2::io; + +use core::convert::TryInto; +use core::num::NonZero; +use core::ops::{ + BitAnd, BitOr, BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, +}; +use core::{fmt::Debug, marker::PhantomData, mem}; +#[cfg(feature = "std")] +use std::io; + +pub mod huffman; +pub mod read; +pub mod write; +pub use read::{ + BitRead, BitRead2, BitReader, ByteRead, ByteReader, FromBitStream, FromBitStreamUsing, + FromBitStreamWith, FromByteStream, FromByteStreamUsing, FromByteStreamWith, +}; +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +#[cfg(feature = "alloc")] +pub use write::BitRecorder; +pub use write::{ + BitWrite, BitWrite2, BitWriter, BitsWritten, ByteWrite, ByteWriter, ToBitStream, + ToBitStreamUsing, ToBitStreamWith, ToByteStream, ToByteStreamUsing, ToByteStreamWith, +}; + +#[allow(deprecated)] +pub use write::BitCounter; + +/// A trait intended for simple fixed-length primitives (such as ints and floats) +/// which allows them to be read and written to streams of +/// different endiannesses verbatim. +pub trait Primitive { + /// The raw byte representation of this numeric type + type Bytes: AsRef<[u8]> + AsMut<[u8]>; + + /// An empty buffer of this type's size + fn buffer() -> Self::Bytes; + + /// Our value in big-endian bytes + fn to_be_bytes(self) -> Self::Bytes; + + /// Our value in little-endian bytes + fn to_le_bytes(self) -> Self::Bytes; + + /// Convert big-endian bytes to our value + fn from_be_bytes(bytes: Self::Bytes) -> Self; + + /// Convert little-endian bytes to our value + fn from_le_bytes(bytes: Self::Bytes) -> Self; +} + +macro_rules! define_primitive_numeric { + ($t:ty) => { + impl Primitive for $t { + type Bytes = [u8; mem::size_of::<$t>()]; + + #[inline(always)] + fn buffer() -> Self::Bytes { + [0; mem::size_of::<$t>()] + } + #[inline(always)] + fn to_be_bytes(self) -> Self::Bytes { + self.to_be_bytes() + } + #[inline(always)] + fn to_le_bytes(self) -> Self::Bytes { + self.to_le_bytes() + } + #[inline(always)] + fn from_be_bytes(bytes: Self::Bytes) -> Self { + <$t>::from_be_bytes(bytes) + } + #[inline(always)] + fn from_le_bytes(bytes: Self::Bytes) -> Self { + <$t>::from_le_bytes(bytes) + } + } + }; +} + +impl Primitive for [u8; N] { + type Bytes = [u8; N]; + + #[inline(always)] + fn buffer() -> Self::Bytes { + [0; N] + } + + #[inline(always)] + fn to_be_bytes(self) -> Self::Bytes { + self + } + + #[inline(always)] + fn to_le_bytes(self) -> Self::Bytes { + self + } + + #[inline(always)] + fn from_be_bytes(bytes: Self::Bytes) -> Self { + bytes + } + + #[inline(always)] + fn from_le_bytes(bytes: Self::Bytes) -> Self { + bytes + } +} + +/// This trait is for integer types which can be read or written +/// to a bit stream as a partial amount of bits. +/// +/// It unifies signed and unsigned integer types by delegating +/// reads and writes to the signed and unsigned reading +/// and writing methods as appropriate. +pub trait Integer { + /// Reads a value of ourself from the stream + /// with the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the given number of bits + /// is larger than our type. + fn read(reader: &mut R) -> io::Result + where + Self: Sized; + + /// Reads a value of ourself from the stream + /// with the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if our type is too small + /// to hold the requested number of bits. + fn read_var(reader: &mut R, bits: BitCount) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized; + + /// Writes ourself to the stream using the given const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if our value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the given number of bits + /// is larger than our type. + fn write(self, writer: &mut W) -> io::Result<()>; + + /// Writes ourself to the stream using the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if our value is too small + /// to hold the given number of bits. + /// Returns an error if our value is too large + /// to fit the given number of bits. + fn write_var( + self, + writer: &mut W, + bits: BitCount, + ) -> io::Result<()>; +} + +/// This trait is for integer types which can be read or written +/// to a bit stream as variable-width integers. +/// +/// It unifies signed and unsigned integer types by delegating +/// reads and write to the signed and unsigned vbr reading and +/// writing methods as appropriate. +pub trait VBRInteger: Integer { + /// Reads a value of ourself from the stream using a variable width integer. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized; + + /// Writes ourself to the stream using a variable width integer. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()>; +} + +/// Reading and writing booleans as `Integer` requires the number of bits to be 1. +/// +/// This is more useful when combined with the fixed array target +/// for reading blocks of bit flags. +/// +/// # Example +/// ``` +/// use bitstream_io::{BitReader, BitRead, BigEndian}; +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct Flags { +/// a: bool, +/// b: bool, +/// c: bool, +/// d: bool, +/// } +/// +/// let data: &[u8] = &[0b1011_0000]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // note the number of bits must be 1 per read +/// // while the quantity of flags is indicated by the array length +/// let flags = r.read::<1, [bool; 4]>().map(|[a, b, c, d]| Flags { a, b, c, d }).unwrap(); +/// assert_eq!(flags, Flags { a: true, b: false, c: true, d: true }); +/// ``` +impl Integer for bool { + #[inline(always)] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + const { + assert!(BITS == 1, "booleans require exactly 1 bit"); + } + + reader.read_bit() + } + + fn read_var( + reader: &mut R, + BitCount { bits }: BitCount, + ) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + if bits == 1 { + reader.read_bit() + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "booleans require exactly 1 bit", + )) + } + } + + #[inline(always)] + fn write(self, writer: &mut W) -> io::Result<()> { + const { + assert!(BITS == 1, "booleans require exactly 1 bit"); + } + + writer.write_bit(self) + } + + fn write_var( + self, + writer: &mut W, + BitCount { bits }: BitCount, + ) -> io::Result<()> { + if bits == 1 { + writer.write_bit(self) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "booleans require exactly 1 bit", + )) + } + } +} + +impl Integer for [I; SIZE] { + #[inline] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + let mut a = [I::default(); SIZE]; + + a.iter_mut().try_for_each(|v| { + *v = reader.read::()?; + Ok::<(), io::Error>(()) + })?; + + Ok(a) + } + + #[inline] + fn read_var(reader: &mut R, count: BitCount) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + let mut a = [I::default(); SIZE]; + + a.iter_mut().try_for_each(|v| { + *v = reader.read_counted(count)?; + Ok::<(), io::Error>(()) + })?; + + Ok(a) + } + + #[inline] + fn write(self, writer: &mut W) -> io::Result<()> { + IntoIterator::into_iter(self).try_for_each(|v| writer.write::(v)) + } + + #[inline] + fn write_var( + self, + writer: &mut W, + count: BitCount, + ) -> io::Result<()> { + IntoIterator::into_iter(self).try_for_each(|v| writer.write_counted(count, v)) + } +} + +impl VBRInteger for [I; SIZE] { + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + let mut a = [I::default(); SIZE]; + + a.iter_mut().try_for_each(|v| { + I::read_vbr::(reader).map(|item| { + *v = item; + }) + })?; + + Ok(a) + } + + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()> { + IntoIterator::into_iter(self).try_for_each(|v| I::write_vbr::(v, writer)) + } +} + +/// This trait extends many common integer types (both unsigned and signed) +/// with a few trivial methods so that they can be used +/// with the bitstream handling traits. +pub trait Numeric: + Primitive + + Sized + + Copy + + Default + + Debug + + PartialOrd + + Shl + + ShlAssign + + Shr + + ShrAssign + + Rem + + RemAssign + + BitAnd + + BitOr + + BitOrAssign + + BitXor + + Not + + Sub +{ + /// Size of type in bits + const BITS_SIZE: u32; + + /// The value of 0 in this type + const ZERO: Self; + + /// The value of 1 in this type + const ONE: Self; + + /// Returns a `u8` value in this type + fn from_u8(u: u8) -> Self; + + /// Assuming 0 <= value < 256, returns this value as a `u8` type + fn to_u8(self) -> u8; +} + +macro_rules! define_numeric { + ($t:ty) => { + define_primitive_numeric!($t); + + impl Numeric for $t { + const BITS_SIZE: u32 = mem::size_of::<$t>() as u32 * 8; + + const ZERO: Self = 0; + + const ONE: Self = 1; + + #[inline(always)] + fn from_u8(u: u8) -> Self { + u as $t + } + #[inline(always)] + fn to_u8(self) -> u8 { + self as u8 + } + } + }; +} + +/// This trait extends many common unsigned integer types +/// so that they can be used with the bitstream handling traits. +pub trait UnsignedInteger: Numeric { + /// This type's most-significant bit + const MSB_BIT: Self; + + /// This type's least significant bit + const LSB_BIT: Self; + + /// This type with all bits set + const ALL: Self; + + /// The signed variant of ourself + type Signed: SignedInteger; + + /// Given a twos-complement value, + /// return this value is a non-negative signed number. + /// The location of the sign bit depends on the stream's endianness + /// and is not stored in the result. + /// + /// # Example + /// ``` + /// use bitstream_io::UnsignedInteger; + /// assert_eq!(0b00000001u8.as_non_negative(), 1i8); + /// ``` + fn as_non_negative(self) -> Self::Signed; + + /// Given a two-complement positive value and certain number of bits, + /// returns this value as a negative signed number. + /// The location of the sign bit depends on the stream's endianness + /// and is not stored in the result. + /// + /// # Example + /// ``` + /// use bitstream_io::UnsignedInteger; + /// assert_eq!(0b01111111u8.as_negative(8), -1i8); + /// ``` + fn as_negative(self, bits: u32) -> Self::Signed; + + /// Given a two-complement positive value and certain number of bits, + /// returns this value as a negative number. + /// + /// # Example + /// ``` + /// use bitstream_io::UnsignedInteger; + /// assert_eq!(0b01111111u8.as_negative_fixed::<8>(), -1i8); + /// ``` + fn as_negative_fixed(self) -> Self::Signed; + + /// Checked shift left + fn checked_shl(self, rhs: u32) -> Option; + + /// Checked shift right + fn checked_shr(self, rhs: u32) -> Option; + + /// Shift left up to our length in bits + /// + /// If rhs equals our length in bits, returns default + fn shl_default(self, rhs: u32) -> Self { + self.checked_shl(rhs).unwrap_or(Self::ZERO) + } + + /// Shift left up to our length in bits + /// + /// If rhs equals our length in bits, returns zero + fn shr_default(self, rhs: u32) -> Self { + self.checked_shr(rhs).unwrap_or(Self::ZERO) + } +} + +macro_rules! define_unsigned_integer { + ($t:ty, $s:ty) => { + define_numeric!($t); + + impl UnsignedInteger for $t { + type Signed = $s; + + const MSB_BIT: Self = 1 << (Self::BITS_SIZE - 1); + + const LSB_BIT: Self = 1; + + const ALL: Self = <$t>::MAX; + + #[inline(always)] + fn as_non_negative(self) -> Self::Signed { + self as $s + } + #[inline(always)] + fn as_negative(self, bits: u32) -> Self::Signed { + (self as $s) + (-1 << (bits - 1)) + } + #[inline(always)] + fn as_negative_fixed(self) -> Self::Signed { + (self as $s) + (-1 << (BITS - 1)) + } + #[inline(always)] + fn checked_shl(self, rhs: u32) -> Option { + self.checked_shl(rhs) + } + #[inline(always)] + fn checked_shr(self, rhs: u32) -> Option { + self.checked_shr(rhs) + } + // TODO - enable these in the future + // #[inline(always)] + // fn shl_default(self, rhs: u32) -> Self { + // self.unbounded_shl(rhs) + // } + // #[inline(always)] + // fn shr_default(self, rhs: u32) -> Self { + // self.unbounded_shr(rhs) + // } + } + + impl Integer for $t { + #[inline(always)] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + reader.read_unsigned::() + } + + #[inline(always)] + fn read_var(reader: &mut R, bits: BitCount) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + reader.read_unsigned_counted::(bits) + } + + #[inline(always)] + fn write( + self, + writer: &mut W, + ) -> io::Result<()> { + writer.write_unsigned::(self) + } + + #[inline(always)] + fn write_var( + self, + writer: &mut W, + bits: BitCount, + ) -> io::Result<()> { + writer.write_unsigned_counted(bits, self) + } + } + + impl VBRInteger for $t { + #[inline(always)] + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + reader.read_unsigned_vbr::() + } + + #[inline(always)] + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()> { + writer.write_unsigned_vbr::(self) + } + } + + /// Unsigned NonZero types increment their value by 1 + /// when being read and decrement it by 1 + /// when being written. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// use core::num::NonZero; + /// + /// let data: &[u8] = &[0b001_00000]; + /// // reading a regular u8 in 3 bits yields 1 + /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, u8>().unwrap(), 1); + /// // reading a NonZero in 3 bits of the same data yields 2 + /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, NonZero>().unwrap().get(), 2); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// use core::num::NonZero; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing 1 as a regular u8 in 3 bits + /// w.write::<3, u8>(1).unwrap(); + /// w.byte_align(); + /// assert_eq!(w.into_writer(), &[0b001_00000]); + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing 1 as a NonZero in 3 bits + /// w.write::<3, NonZero>(NonZero::new(1).unwrap()).unwrap(); + /// w.byte_align(); + /// assert_eq!(w.into_writer(), &[0b000_00000]); + /// ``` + impl Integer for NonZero<$t> { + #[inline] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + const { + assert!( + BITS < <$t>::BITS_SIZE, + "BITS must be less than the type's size in bits" + ); + } + + <$t as Integer>::read::(reader).map(|u| NonZero::new(u + 1).unwrap()) + } + + #[inline] + fn read_var( + reader: &mut R, + count @ BitCount { bits }: BitCount, + ) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE { + <$t as Integer>::read_var::(reader, count) + .map(|u| NonZero::new(u + 1).unwrap()) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "bit count must be less than the type's size in bits", + )) + } + } + + #[inline] + fn write( + self, + writer: &mut W, + ) -> io::Result<()> { + const { + assert!( + BITS < <$t>::BITS_SIZE, + "BITS must be less than the type's size in bits" + ); + } + + <$t as Integer>::write::(self.get() - 1, writer) + } + + #[inline] + fn write_var( + self, + writer: &mut W, + count @ BitCount { bits }: BitCount, + ) -> io::Result<()> { + if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE { + <$t as Integer>::write_var::(self.get() - 1, writer, count) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "bit count must be less than the type's size in bits", + )) + } + } + } + + impl VBRInteger for NonZero<$t> { + #[inline] + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + <$t as VBRInteger>::read_vbr::(reader) + .map(|u| NonZero::new(u + 1).unwrap()) + } + + #[inline] + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()> { + <$t as VBRInteger>::write_vbr::(self.get() - 1, writer) + } + } + + impl Integer for Option> { + #[inline] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + <$t as Integer>::read::(reader).map(NonZero::new) + } + + #[inline] + fn read_var(reader: &mut R, count: BitCount) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + <$t as Integer>::read_var::(reader, count).map(NonZero::new) + } + + #[inline] + fn write( + self, + writer: &mut W, + ) -> io::Result<()> { + <$t as Integer>::write::(self.map(|n| n.get()).unwrap_or(0), writer) + } + + #[inline] + fn write_var( + self, + writer: &mut W, + count: BitCount, + ) -> io::Result<()> { + <$t as Integer>::write_var::( + self.map(|n| n.get()).unwrap_or(0), + writer, + count, + ) + } + } + + impl VBRInteger for Option> { + #[inline(always)] + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + <$t as VBRInteger>::read_vbr::(reader).map(NonZero::new) + } + + #[inline] + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()> { + <$t as VBRInteger>::write_vbr::( + self.map(|n| n.get()).unwrap_or(0), + writer, + ) + } + } + }; +} + +/// This trait extends many common signed integer types +/// so that they can be used with the bitstream handling traits. +/// +/// This trait was formerly named `SignedNumeric` in 2.X.X code. +/// If backwards-compatibility is needed one can +/// import `SignedInteger` as `SignedNumeric`. +pub trait SignedInteger: Numeric { + /// The unsigned variant of ourself + type Unsigned: UnsignedInteger; + + /// Returns true if this value is negative + /// + /// # Example + /// ``` + /// use bitstream_io::SignedInteger; + /// assert!(!1i8.is_negative()); + /// assert!((-1i8).is_negative()); + /// ``` + fn is_negative(self) -> bool; + + /// Returns ourself as a non-negative value. + /// The location of the sign bit depends on the stream's endianness + /// and is not stored in the result. + /// + /// # Example + /// ``` + /// use bitstream_io::SignedInteger; + /// assert_eq!(1i8.as_non_negative(), 0b00000001u8); + /// ``` + fn as_non_negative(self) -> Self::Unsigned; + + /// Given a negative value and a certain number of bits, + /// returns this value as a twos-complement positive number. + /// The location of the sign bit depends on the stream's endianness + /// and is not stored in the result. + /// + /// # Example + /// ``` + /// use bitstream_io::SignedInteger; + /// assert_eq!((-1i8).as_negative(8), 0b01111111u8); + /// ``` + fn as_negative(self, bits: u32) -> Self::Unsigned; + + /// Given a negative value and a certain number of bits, + /// returns this value as a twos-complement positive number. + /// + /// # Example + /// ``` + /// use bitstream_io::SignedInteger; + /// assert_eq!((-1i8).as_negative_fixed::<8>(), 0b01111111u8); + /// ``` + fn as_negative_fixed(self) -> Self::Unsigned; +} + +macro_rules! define_signed_integer { + ($t:ty, $u:ty) => { + define_numeric!($t); + + impl SignedInteger for $t { + type Unsigned = $u; + + #[inline(always)] + fn is_negative(self) -> bool { + self.is_negative() + } + fn as_non_negative(self) -> Self::Unsigned { + self as $u + } + fn as_negative(self, bits: u32) -> Self::Unsigned { + (self - (-1 << (bits - 1))) as $u + } + fn as_negative_fixed(self) -> Self::Unsigned { + (self - (-1 << (BITS - 1))) as $u + } + } + + impl Integer for $t { + #[inline(always)] + fn read(reader: &mut R) -> io::Result + where + Self: Sized, + { + reader.read_signed::() + } + + #[inline(always)] + fn read_var(reader: &mut R, bits: BitCount) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + reader.read_signed_counted::(bits) + } + + #[inline(always)] + fn write( + self, + writer: &mut W, + ) -> io::Result<()> { + writer.write_signed::(self) + } + + #[inline(always)] + fn write_var( + self, + writer: &mut W, + bits: BitCount, + ) -> io::Result<()> { + writer.write_signed_counted::(bits, self) + } + } + + impl VBRInteger for $t { + #[inline(always)] + fn read_vbr(reader: &mut R) -> io::Result + where + R: BitRead + ?Sized, + Self: Sized, + { + reader.read_signed_vbr::() + } + + #[inline(always)] + fn write_vbr( + self, + writer: &mut W, + ) -> io::Result<()> { + writer.write_signed_vbr::(self) + } + } + }; +} + +define_unsigned_integer!(u8, i8); +define_unsigned_integer!(u16, i16); +define_unsigned_integer!(u32, i32); +define_unsigned_integer!(u64, i64); +define_unsigned_integer!(u128, i128); + +define_signed_integer!(i8, u8); +define_signed_integer!(i16, u16); +define_signed_integer!(i32, u32); +define_signed_integer!(i64, u64); +define_signed_integer!(i128, u128); + +define_primitive_numeric!(f32); +define_primitive_numeric!(f64); + +mod private { + use crate::{ + io, BitCount, BitRead, BitWrite, CheckedSigned, CheckedUnsigned, Primitive, SignedBitCount, + SignedInteger, UnsignedInteger, + }; + + #[test] + fn test_checked_signed() { + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<8>(), -128i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<8>(), 127i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), -64i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), 63i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), -32i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), 31i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), -16i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), 15i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), -8i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), 7i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), -4i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), 3i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), -2i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), 1i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), -1i8).is_ok()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), 0i8).is_ok()); + + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), -65i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), 64i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), -33i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), 32i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), -17i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), 16i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), -9i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), 8i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), -5i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), 4i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), -3i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), 2i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), -2i8).is_err()); + assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), 1i8).is_err()); + } + + pub trait Endianness: Sized { + /// Pops the next bit from the queue, + /// repleneshing it from the given reader if necessary + fn pop_bit_refill( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read; + + /// Pops the next unary value from the source until + /// `STOP_BIT` is encountered, replenishing it from the given + /// closure if necessary. + /// + /// `STOP_BIT` must be 0 or 1. + fn pop_unary( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read; + + /// Pushes the next bit into the queue, + /// and returns `Some` value if the queue is full. + fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option; + + /// For performing bulk reads from a bit source to an output type. + fn read_bits( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + count: BitCount, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger; + + /// For performing bulk reads from a bit source to an output type. + fn read_bits_fixed( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger; + + /// For performing a checked write to a bit sink + fn write_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + value: CheckedUnsigned, + ) -> io::Result<()> + where + W: io::Write, + U: UnsignedInteger; + + /// For performing a checked signed write to a bit sink + fn write_signed_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + value: CheckedSigned, + ) -> io::Result<()> + where + W: io::Write, + S: SignedInteger; + + /// Reads signed value from reader in this endianness + fn read_signed_counted( + r: &mut R, + bits: SignedBitCount, + ) -> io::Result + where + R: BitRead, + S: SignedInteger; + + /// Reads whole set of bytes to output buffer + fn read_bytes( + reader: &mut R, + queue_value: &mut u8, + queue_bits: u32, + buf: &mut [u8], + ) -> io::Result<()> + where + R: io::Read; + + /// Writes whole set of bytes to output buffer + fn write_bytes( + writer: &mut W, + queue_value: &mut u8, + queue_bits: u32, + buf: &[u8], + ) -> io::Result<()> + where + W: io::Write; + + /// Converts a primitive's byte buffer to a primitive + fn bytes_to_primitive(buf: P::Bytes) -> P; + + /// Converts a primitive to a primitive's byte buffer + fn primitive_to_bytes(p: P) -> P::Bytes; + + /// Reads convertable numeric value from reader in this endianness + #[deprecated(since = "4.0.0")] + fn read_primitive(r: &mut R) -> io::Result + where + R: BitRead, + V: Primitive; + + /// Writes convertable numeric value to writer in this endianness + #[deprecated(since = "4.0.0")] + fn write_primitive(w: &mut W, value: V) -> io::Result<()> + where + W: BitWrite, + V: Primitive; + } + + pub trait Checkable { + fn write_endian( + self, + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result<()> + where + E: Endianness, + W: io::Write; + } +} + +/// A stream's endianness, or byte order, for determining +/// how bits should be read. +/// +/// It comes in `BigEndian` and `LittleEndian` varieties +/// (which may be shortened to `BE` and `LE`) +/// and is not something programmers should implement directly. +pub trait Endianness: private::Endianness {} + +#[inline(always)] +fn read_byte(mut reader: R) -> io::Result +where + R: io::Read, +{ + let mut byte = 0; + reader + .read_exact(core::slice::from_mut(&mut byte)) + .map(|()| byte) +} + +#[inline(always)] +fn write_byte(mut writer: W, byte: u8) -> io::Result<()> +where + W: io::Write, +{ + writer.write_all(core::slice::from_ref(&byte)) +} + +/// A number of bits to be consumed or written, with a known maximum +/// +/// Although [`BitRead::read`] and [`BitWrite::write`] should be +/// preferred when the number of bits is fixed and known at compile-time - +/// because they can validate the bit count is less than or equal +/// to the type's size in bits at compile-time - +/// there are many instances where bit count is dynamic and +/// determined by the file format itself. +/// But when using [`BitRead::read_var`] or [`BitWrite::write_var`] +/// we must pessimistically assume any number of bits as an argument +/// and validate that the number of bits is not larger than the +/// type being read or written on every call. +/// +/// ``` +/// use bitstream_io::{BitRead, BitReader, BigEndian}; +/// +/// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // our bit count is a 3 bit value +/// let count = r.read::<3, u32>().unwrap(); +/// // that count indicates we need to read 4 bits (0b100) +/// assert_eq!(count, 4); +/// // read the first 4-bit value +/// assert_eq!(r.read_var::(count).unwrap(), 0b0001); +/// // read the second 4-bit value +/// assert_eq!(r.read_var::(count).unwrap(), 0b1111); +/// // read the third 4-bit value +/// assert_eq!(r.read_var::(count).unwrap(), 0b0110); +/// ``` +/// +/// In the preceding example, even though we know `count` is a +/// 3 bit value whose maximum value will never be greater than 7, +/// the subsequent `read_var` calls have no way to know that. +/// They must assume `count` could be 9, or `u32::MAX` or any other `u32` value +/// and validate the count is not larger than the `u8` types we're reading. +/// +/// But we can convert our example to use the `BitCount` type: +/// +/// ``` +/// use bitstream_io::{BitRead, BitReader, BigEndian, BitCount}; +/// +/// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // our bit count is a 3 bit value with a maximum value of 7 +/// let count = r.read_count::<0b111>().unwrap(); +/// // that count indicates we need to read 4 bits (0b100) +/// assert_eq!(count, BitCount::<7>::new::<4>()); +/// // read the first 4-bit value +/// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b0001); +/// // read the second 4-bit value +/// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b1111); +/// // read the third 4-bit value +/// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b0110); +/// ``` +/// +/// Because the [`BitRead::read_counted`] methods know at compile-time +/// that the bit count will be larger than 7, that check can be eliminated +/// simply by taking advantage of information we already know. +/// +/// Leveraging the `BitCount` type also allows us to reason about +/// bit counts in a more formal way, and use checked permutation methods +/// to modify them while ensuring they remain constrained by +/// the file format's requirements. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct BitCount { + // The amount of bits may be less than or equal to the maximum, + // but never more. + bits: u32, +} + +impl BitCount { + /// Builds a bit count from a constant number + /// of bits, which must not be greater than `MAX`. + /// + /// Intended to be used for defining constants. + /// + /// Use `TryFrom` to conditionally build + /// counts from values at runtime. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; + /// let data: &[u8] = &[0b111_00000]; + /// let mut r = BitReader::endian(data, BigEndian); + /// // reading 3 bits from a stream out of a maximum of 8 + /// // doesn't require checking that the bit count is larger + /// // than a u8 at runtime because specifying the maximum of 8 + /// // guarantees our bit count will not be larger than 8 + /// assert_eq!(r.read_counted::<8, u8>(BitCount::new::<3>()).unwrap(), 0b111); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::BitCount; + /// // trying to build a count of 10 with a maximum of 8 + /// // fails to compile at all + /// let count = BitCount::<8>::new::<10>(); + /// ``` + pub const fn new() -> Self { + const { + assert!(BITS <= MAX, "BITS must be <= MAX"); + } + + Self { bits: BITS } + } + + /// Add a number of bits to our count, + /// returning a new count with a new maximum. + /// + /// Returns `None` if the new count goes above our new maximum. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// let count = BitCount::<2>::new::<1>(); + /// // adding 2 to 1 and increasing the max to 3 yields a new count of 3 + /// assert_eq!(count.checked_add::<3>(2), Some(BitCount::<3>::new::<3>())); + /// // adding 2 to 1 without increasing the max yields None + /// assert_eq!(count.checked_add::<2>(2), None); + /// ``` + #[inline] + pub const fn checked_add(self, bits: u32) -> Option> { + match self.bits.checked_add(bits) { + Some(bits) if bits <= NEW_MAX => Some(BitCount { bits }), + _ => None, + } + } + + /// Subtracts a number of bits from our count, + /// returning a new count with a new maximum. + /// + /// Returns `None` if the new count goes below 0 + /// or below our new maximum. + /// + /// # Example + /// ``` + /// use bitstream_io::BitCount; + /// let count = BitCount::<5>::new::<5>(); + /// // subtracting 1 from 5 yields a new count of 4 + /// assert_eq!(count.checked_sub::<5>(1), Some(BitCount::<5>::new::<4>())); + /// // subtracting 6 from 5 yields None + /// assert!(count.checked_sub::<5>(6).is_none()); + /// // subtracting 1 with a new maximum of 3 also yields None + /// // because 4 is larger than the maximum of 3 + /// assert!(count.checked_sub::<3>(1).is_none()); + /// ``` + #[inline] + pub const fn checked_sub(self, bits: u32) -> Option> { + match self.bits.checked_sub(bits) { + Some(bits) if bits <= NEW_MAX => Some(BitCount { bits }), + _ => None, + } + } + + /// Attempt to convert our count to a count with a new + /// bit count and new maximum. + /// + /// Returns `Some(count)` if the updated number of bits + /// is less than or equal to the new maximum. + /// Returns `None` if not. + /// + /// # Examples + /// ``` + /// use bitstream_io::BitCount; + /// + /// let count = BitCount::<5>::new::<5>(); + /// // muliplying 5 bits by 2 with a new max of 10 is ok + /// assert_eq!( + /// count.try_map::<10, _>(|i| i.checked_mul(2)), + /// Some(BitCount::<10>::new::<10>()), + /// ); + /// + /// // multiplying 5 bits by 3 with a new max of 10 overflows + /// assert_eq!(count.try_map::<10, _>(|i| i.checked_mul(3)), None); + /// ``` + #[inline] + pub fn try_map(self, f: F) -> Option> + where + F: FnOnce(u32) -> Option, + { + f(self.bits) + .filter(|bits| *bits <= NEW_MAX) + .map(|bits| BitCount { bits }) + } + + /// Returns our maximum bit count + /// + /// # Example + /// ``` + /// use bitstream_io::BitCount; + /// + /// let count = BitCount::<10>::new::<5>(); + /// assert_eq!(count.max(), 10); + /// ``` + #[inline(always)] + pub const fn max(&self) -> u32 { + MAX + } + + /// Returns signed count if our bit count is greater than 0 + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitCount, SignedBitCount}; + /// + /// let count = BitCount::<10>::new::<5>(); + /// assert_eq!(count.signed_count(), Some(SignedBitCount::<10>::new::<5>())); + /// + /// let count = BitCount::<10>::new::<0>(); + /// assert_eq!(count.signed_count(), None); + /// ``` + #[inline(always)] + pub const fn signed_count(&self) -> Option> { + match self.bits.checked_sub(1) { + Some(bits) => Some(SignedBitCount { + bits: *self, + unsigned: BitCount { bits }, + }), + None => None, + } + } + + /// Masks off the least-significant bits for the given type + /// + /// Returns closure that takes a value and returns a + /// pair of the most-significant and least-significant + /// bits. Because the least-significant bits cannot + /// be larger than this bit count, that value is + /// returned as a [`Checked`] type. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// // create a bit count of 3 + /// let count = BitCount::<8>::new::<3>(); + /// + /// // create a mask suitable for u8 types + /// let mask = count.mask_lsb::(); + /// + /// let (msb, lsb) = mask(0b11011_110); + /// assert_eq!(msb, 0b11011); // the most-significant bits + /// assert_eq!(lsb.into_value(), 0b110); // the least-significant bits + /// + /// let (msb, lsb) = mask(0b01100_010); + /// assert_eq!(msb, 0b01100); // the most-significant bits + /// assert_eq!(lsb.into_value(), 0b010); // the least-significant bits + /// + /// let (msb, lsb) = mask(0b00000_111); + /// assert_eq!(msb, 0b00000); // the most-significant bits + /// assert_eq!(lsb.into_value(), 0b111); // the least-significant bits + /// ``` + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// // a mask with a bit count of 0 puts everything in msb + /// let mask = BitCount::<8>::new::<0>().mask_lsb::(); + /// + /// let (msb, lsb) = mask(0b11111111); + /// assert_eq!(msb, 0b11111111); + /// assert_eq!(lsb.into_value(), 0); + /// + /// // a mask with a bit count larger than the type + /// // is restricted to that type's size, if possible + /// let mask = BitCount::<16>::new::<9>().mask_lsb::(); + /// + /// let (msb, lsb) = mask(0b11111111); + /// assert_eq!(msb, 0); + /// assert_eq!(lsb.into_value(), 0b11111111); + /// ``` + pub fn mask_lsb(self) -> impl Fn(U) -> (U, CheckedUnsigned) { + use core::convert::TryFrom; + + let (mask, shift, count) = match U::BITS_SIZE.checked_sub(self.bits) { + Some(mask_bits) => (U::ALL.shr_default(mask_bits), self.bits, self), + None => ( + U::ALL, + U::BITS_SIZE, + BitCount::try_from(U::BITS_SIZE).expect("bit count too small for type"), + ), + }; + + move |v| { + ( + v.shr_default(shift), + Checked { + value: v & mask, + count, + }, + ) + } + } + + /// Returns this bit count's range for the given unsigned type + /// + /// # Example + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// assert_eq!(BitCount::<9>::new::<0>().range::(), 0..=0); + /// assert_eq!(BitCount::<9>::new::<1>().range::(), 0..=0b1); + /// assert_eq!(BitCount::<9>::new::<2>().range::(), 0..=0b11); + /// assert_eq!(BitCount::<9>::new::<3>().range::(), 0..=0b111); + /// assert_eq!(BitCount::<9>::new::<4>().range::(), 0..=0b1111); + /// assert_eq!(BitCount::<9>::new::<5>().range::(), 0..=0b11111); + /// assert_eq!(BitCount::<9>::new::<6>().range::(), 0..=0b111111); + /// assert_eq!(BitCount::<9>::new::<7>().range::(), 0..=0b1111111); + /// assert_eq!(BitCount::<9>::new::<8>().range::(), 0..=0b11111111); + /// // a count that exceeds the type's size is + /// // naturally restricted to that type's maximum range + /// assert_eq!(BitCount::<9>::new::<9>().range::(), 0..=0b11111111); + /// ``` + #[inline] + pub fn range(&self) -> core::ops::RangeInclusive { + match U::ONE.checked_shl(self.bits) { + Some(top) => U::ZERO..=(top - U::ONE), + None => U::ZERO..=U::ALL, + } + } + + /// Returns minimum value between ourself and bit count + /// + /// # Example + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// let count = BitCount::<8>::new::<7>(); + /// assert_eq!(count.min(6), BitCount::new::<6>()); + /// assert_eq!(count.min(8), BitCount::new::<7>()); + /// ``` + #[inline(always)] + pub fn min(self, bits: u32) -> Self { + // the minimum of ourself and another bit count + // can never exceed our maximum bit count + Self { + bits: self.bits.min(bits), + } + } + + /// Returns the minimum value of an unsigned int in this bit count + /// + /// # Example + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// assert_eq!(BitCount::<8>::new::<0>().none::().into_value(), 0b0); + /// assert_eq!(BitCount::<8>::new::<1>().none::().into_value(), 0b0); + /// assert_eq!(BitCount::<8>::new::<2>().none::().into_value(), 0b00); + /// assert_eq!(BitCount::<8>::new::<3>().none::().into_value(), 0b000); + /// assert_eq!(BitCount::<8>::new::<4>().none::().into_value(), 0b0000); + /// assert_eq!(BitCount::<8>::new::<5>().none::().into_value(), 0b00000); + /// assert_eq!(BitCount::<8>::new::<6>().none::().into_value(), 0b000000); + /// assert_eq!(BitCount::<8>::new::<7>().none::().into_value(), 0b0000000); + /// assert_eq!(BitCount::<8>::new::<8>().none::().into_value(), 0b00000000); + /// ``` + #[inline(always)] + pub fn none(self) -> CheckedUnsigned { + CheckedUnsigned { + value: U::ZERO, + count: self, + } + } + + /// Returns the maximum value of an unsigned int in this bit count + /// + /// # Example + /// + /// ``` + /// use bitstream_io::BitCount; + /// + /// assert_eq!(BitCount::<8>::new::<0>().all::().into_value(), 0b0); + /// assert_eq!(BitCount::<8>::new::<1>().all::().into_value(), 0b1); + /// assert_eq!(BitCount::<8>::new::<2>().all::().into_value(), 0b11); + /// assert_eq!(BitCount::<8>::new::<3>().all::().into_value(), 0b111); + /// assert_eq!(BitCount::<8>::new::<4>().all::().into_value(), 0b1111); + /// assert_eq!(BitCount::<8>::new::<5>().all::().into_value(), 0b11111); + /// assert_eq!(BitCount::<8>::new::<6>().all::().into_value(), 0b111111); + /// assert_eq!(BitCount::<8>::new::<7>().all::().into_value(), 0b1111111); + /// assert_eq!(BitCount::<8>::new::<8>().all::().into_value(), 0b11111111); + /// ``` + #[inline(always)] + pub fn all(self) -> CheckedUnsigned { + CheckedUnsigned { + value: match U::ONE.checked_shl(self.bits) { + Some(top) => top - U::ONE, + None => U::ALL, + }, + count: self, + } + } +} + +impl core::convert::TryFrom for BitCount { + type Error = u32; + + /// Attempts to convert a `u32` bit count to a `BitCount` + /// + /// Attempting a bit maximum bit count larger than the + /// largest supported type is a compile-time error + /// + /// # Examples + /// ``` + /// use bitstream_io::BitCount; + /// use std::convert::TryInto; + /// + /// assert_eq!(8u32.try_into(), Ok(BitCount::<8>::new::<8>())); + /// assert_eq!(9u32.try_into(), Err::, _>(9)); + /// ``` + fn try_from(bits: u32) -> Result { + (bits <= MAX).then_some(Self { bits }).ok_or(bits) + } +} + +impl core::fmt::Display for BitCount { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Display::fmt(&self.bits, f) + } +} + +impl BitCount<{ u32::MAX }> { + /// Builds a bit count where the maximum bits is unknown. + /// + /// # Example + /// ``` + /// use bitstream_io::BitCount; + /// assert_eq!(BitCount::unknown(5), BitCount::<{ u32::MAX }>::new::<5>()); + /// ``` + pub const fn unknown(bits: u32) -> Self { + Self { bits } + } +} + +#[test] +fn test_unknown_bitcount() { + let count = BitCount::unknown(u32::MAX); + assert!(u32::from(count) <= count.max()); +} + +impl From> for u32 { + #[inline(always)] + fn from(BitCount { bits }: BitCount) -> u32 { + bits + } +} + +/// A number of bits to be read or written for signed integers, with a known maximum +/// +/// This is closely related to the [`BitCount`] type, but further constrained +/// to have a minimum value of 1 - because signed values require at least +/// 1 bit for the sign. +/// +/// Let's start with a basic example: +/// +/// ``` +/// use bitstream_io::{BitRead, BitReader, BigEndian}; +/// +/// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // our bit count is a 3 bit value +/// let count = r.read::<3, u32>().unwrap(); +/// // that count indicates we need to read 4 bits (0b100) +/// assert_eq!(count, 4); +/// // read the first 4-bit signed value +/// assert_eq!(r.read_var::(count).unwrap(), 1); +/// // read the second 4-bit signed value +/// assert_eq!(r.read_var::(count).unwrap(), -1); +/// // read the third 4-bit signed value +/// assert_eq!(r.read_var::(count).unwrap(), 6); +/// ``` +/// +/// In the preceding example, even though we know `count` is a +/// 3 bit value whose maximum value will never be greater than 7, +/// the subsequent `read_var` calls have no way to know that. +/// They must assume `count` could be 9, or `u32::MAX` or any other `u32` value +/// and validate the count is not larger than the `i8` types we're reading +/// while also greater than 0 because `i8` requires a sign bit. +/// +/// But we can convert our example to use the `SignedBitCount` type: +/// ``` +/// use bitstream_io::{BitRead, BitReader, BigEndian, SignedBitCount}; +/// +/// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; +/// let mut r = BitReader::endian(data, BigEndian); +/// // our bit count is a 3 bit value with a maximum value of 7 +/// let count = r.read_count::<0b111>().unwrap(); +/// // convert that count to a signed bit count, +/// // which guarantees its value is greater than 0 +/// let count = count.signed_count().unwrap(); +/// // that count indicates we need to read 4 bits (0b100) +/// assert_eq!(count, SignedBitCount::<7>::new::<4>()); +/// // read the first 4-bit value +/// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), 1); +/// // read the second 4-bit value +/// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), -1); +/// // read the third 4-bit value +/// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), 6); +/// ``` +/// +/// Because the [`BitRead::read_signed_counted`] methods know at compile-time +/// that the bit count will be larger than 7, that check can be eliminated +/// simply by taking advantage of information we already know. +/// +/// Leveraging the `SignedBitCount` type also allows us to reason about +/// bit counts in a more formal way, and use checked permutation methods +/// to modify them while ensuring they remain constrained by +/// the file format's requirements. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct SignedBitCount { + // the whole original bit count + bits: BitCount, + // a bit count with one bit removed for the sign + unsigned: BitCount, +} + +impl SignedBitCount { + /// Builds a signed bit count from a constant number + /// of bits, which must be greater than 0 and + /// not be greater than `MAX`. + /// + /// Intended to be used for defining constants. + /// + /// Use `TryFrom` to conditionally build + /// counts from values at runtime. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, SignedBitCount}; + /// let data: &[u8] = &[0b111_00000]; + /// let mut r = BitReader::endian(data, BigEndian); + /// // reading 3 bits from a stream out of a maximum of 8 + /// // doesn't require checking that the bit count is larger + /// // than a u8 at runtime because specifying the maximum of 8 + /// // guarantees our bit count will not be larger than 8 + /// assert_eq!(r.read_signed_counted::<8, i8>(SignedBitCount::new::<3>()).unwrap(), -1); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::SignedBitCount; + /// // trying to build a count of 10 with a maximum of 8 + /// // fails to compile at all + /// let count = SignedBitCount::<8>::new::<10>(); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::SignedBitCount; + /// // trying to build a count of 0 also fails to compile + /// let count = SignedBitCount::<8>::new::<0>(); + /// ``` + pub const fn new() -> Self { + const { + assert!(BITS > 0, "BITS must be > 0"); + } + + Self { + bits: BitCount::new::(), + unsigned: BitCount { bits: BITS - 1 }, + } + } + + /// Add a number of bits to our count, + /// returning a new count with a new maximum. + /// + /// Returns `None` if the new count goes above our new maximum. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::SignedBitCount; + /// + /// let count = SignedBitCount::<2>::new::<1>(); + /// // adding 2 to 1 and increasing the max to 3 yields a new count of 3 + /// assert_eq!(count.checked_add::<3>(2), Some(SignedBitCount::<3>::new::<3>())); + /// // adding 2 to 1 without increasing the max yields None + /// assert_eq!(count.checked_add::<2>(2), None); + /// ``` + #[inline] + pub const fn checked_add( + self, + bits: u32, + ) -> Option> { + match self.bits.checked_add(bits) { + Some(bits_new) => match self.unsigned.checked_add(bits) { + Some(unsigned) => Some(SignedBitCount { + bits: bits_new, + unsigned, + }), + None => None, + }, + None => None, + } + } + + /// Subtracts a number of bits from our count, + /// returning a new count with a new maximum. + /// + /// Returns `None` if the new count goes below 1 + /// or below our new maximum. + /// + /// # Example + /// ``` + /// use bitstream_io::SignedBitCount; + /// let count = SignedBitCount::<5>::new::<5>(); + /// // subtracting 1 from 5 yields a new count of 4 + /// assert_eq!(count.checked_sub::<5>(1), Some(SignedBitCount::<5>::new::<4>())); + /// // subtracting 6 from 5 yields None + /// assert!(count.checked_sub::<5>(6).is_none()); + /// // subtracting 1 with a new maximum of 3 also yields None + /// // because 4 is larger than the maximum of 3 + /// assert!(count.checked_sub::<3>(1).is_none()); + /// // subtracting 5 from 5 also yields None + /// // because SignedBitCount always requires 1 bit for the sign + /// assert!(count.checked_sub::<5>(5).is_none()); + /// ``` + #[inline] + pub const fn checked_sub( + self, + bits: u32, + ) -> Option> { + match self.bits.checked_sub(bits) { + Some(bits_new) => match self.unsigned.checked_sub(bits) { + Some(unsigned) => Some(SignedBitCount { + bits: bits_new, + unsigned, + }), + None => None, + }, + None => None, + } + } + + /// Attempt to convert our count to a count with a new + /// bit count and new maximum. + /// + /// Returns `Some(count)` if the updated number of bits + /// is less than or equal to the new maximum + /// and greater than 0. + /// Returns `None` if not. + /// + /// # Examples + /// ``` + /// use bitstream_io::SignedBitCount; + /// + /// let count = SignedBitCount::<5>::new::<5>(); + /// // muliplying 5 bits by 2 with a new max of 10 is ok + /// assert_eq!( + /// count.try_map::<10, _>(|i| i.checked_mul(2)), + /// Some(SignedBitCount::<10>::new::<10>()), + /// ); + /// + /// // multiplying 5 bits by 3 with a new max of 10 overflows + /// assert_eq!(count.try_map::<10, _>(|i| i.checked_mul(3)), None); + /// + /// // multiplying 5 bits by 0 results in 0 bits, + /// // which isn't value for a SignedBitCount + /// assert_eq!(count.try_map::<10, _>(|i| Some(i * 0)), None); + /// ``` + #[inline] + pub fn try_map(self, f: F) -> Option> + where + F: FnOnce(u32) -> Option, + { + self.bits.try_map(f).and_then(|b| b.signed_count()) + } + + /// Returns our maximum bit count + /// + /// # Example + /// ``` + /// use bitstream_io::SignedBitCount; + /// + /// let count = SignedBitCount::<10>::new::<5>(); + /// assert_eq!(count.max(), 10); + /// ``` + #[inline(always)] + pub const fn max(&self) -> u32 { + MAX + } + + /// Returns regular unsigned bit count + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitCount, SignedBitCount}; + /// + /// let signed_count = SignedBitCount::<10>::new::<5>(); + /// assert_eq!(signed_count.count(), BitCount::<10>::new::<5>()); + /// ``` + #[inline(always)] + pub const fn count(&self) -> BitCount { + self.bits + } + + /// Returns this bit count's range for the given signed type + /// + /// # Example + /// + /// ``` + /// use bitstream_io::SignedBitCount; + /// + /// assert_eq!(SignedBitCount::<9>::new::<1>().range::(), -1..=0); + /// assert_eq!(SignedBitCount::<9>::new::<2>().range::(), -2..=1); + /// assert_eq!(SignedBitCount::<9>::new::<3>().range::(), -4..=3); + /// assert_eq!(SignedBitCount::<9>::new::<4>().range::(), -8..=7); + /// assert_eq!(SignedBitCount::<9>::new::<5>().range::(), -16..=15); + /// assert_eq!(SignedBitCount::<9>::new::<6>().range::(), -32..=31); + /// assert_eq!(SignedBitCount::<9>::new::<7>().range::(), -64..=63); + /// assert_eq!(SignedBitCount::<9>::new::<8>().range::(), -128..=127); + /// // a count that exceeds the type's size is + /// // naturally restricted to that type's maximum range + /// assert_eq!(SignedBitCount::<9>::new::<9>().range::(), -128..=127); + /// ``` + pub fn range(&self) -> core::ops::RangeInclusive { + // a bit of a hack to get around the somewhat restrictive + // SignedInteger trait I've created for myself + + if self.bits.bits < S::BITS_SIZE { + (!S::ZERO << self.unsigned.bits)..=((S::ONE << self.unsigned.bits) - S::ONE) + } else { + S::Unsigned::ZERO.as_negative(S::BITS_SIZE)..=(S::Unsigned::ALL >> 1).as_non_negative() + } + } +} + +impl core::fmt::Display for SignedBitCount { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Display::fmt(&self.bits, f) + } +} + +impl core::convert::TryFrom> for SignedBitCount { + type Error = (); + + #[inline] + fn try_from(count: BitCount) -> Result { + count.signed_count().ok_or(()) + } +} + +impl core::convert::TryFrom for SignedBitCount { + type Error = u32; + + #[inline] + fn try_from(count: u32) -> Result { + BitCount::::try_from(count).and_then(|b| b.signed_count().ok_or(count)) + } +} + +impl From> for u32 { + #[inline(always)] + fn from( + SignedBitCount { + bits: BitCount { bits }, + .. + }: SignedBitCount, + ) -> u32 { + bits + } +} + +/// An error when converting a value to a [`Checked`] struct +#[derive(Copy, Clone, Debug)] +pub enum CheckedError { + /// Excessive bits for type + ExcessiveBits, + /// Excessive value for bits + ExcessiveValue, +} + +impl core::error::Error for CheckedError {} + +impl core::fmt::Display for CheckedError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + match self { + Self::ExcessiveBits => core::fmt::Display::fmt("excessive bits for type written", f), + Self::ExcessiveValue => core::fmt::Display::fmt("excessive value for bits written", f), + } + } +} + +impl From for io::Error { + #[inline] + fn from(error: CheckedError) -> Self { + match error { + CheckedError::ExcessiveBits => io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type written", + ), + CheckedError::ExcessiveValue => io::Error::new( + io::ErrorKind::InvalidInput, + "excessive value for bits written", + ), + } + } +} + +/// A type for eliminating redundant validation when writing +/// +/// Normally, when writing a value, not only must the number of bits +/// must be checked against the type being written +/// (e.g. writing 9 bits from a `u8` is always an error), +/// but the value must also be checked against the number of bits +/// (e.g. writing a value of 2 in 1 bit is always an error). +/// +/// But when the value's range can be checked in advance, +/// the write-time check can be skipped through the use +/// of the [`BitWrite::write_checked`] method. +#[derive(Copy, Clone, Debug)] +pub struct Checked { + count: C, + value: T, +} + +impl Checked { + /// Returns our bit count and value + #[inline] + pub fn into_count_value(self) -> (C, T) { + (self.count, self.value) + } + + /// Returns our value + #[inline] + pub fn into_value(self) -> T { + self.value + } +} + +impl AsRef for Checked { + fn as_ref(&self) -> &T { + &self.value + } +} + +/// An unsigned type with a verified value +pub type CheckedUnsigned = Checked, T>; + +impl Checkable for CheckedUnsigned { + #[inline] + fn write(&self, writer: &mut W) -> io::Result<()> { + // a naive default implementation + writer.write_unsigned_counted(self.count, self.value) + } + + #[inline] + fn written_bits(&self) -> u32 { + self.count.bits + } +} + +impl CheckablePrimitive for CheckedUnsigned { + type CountType = BitCount; + + #[inline] + fn read(reader: &mut R, count: Self::CountType) -> io::Result { + reader + .read_unsigned_counted(count) + .map(|value| Self { value, count }) + } +} + +impl private::Checkable for CheckedUnsigned { + fn write_endian( + self, + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result<()> + where + E: private::Endianness, + W: io::Write, + { + E::write_bits_checked(writer, queue_value, queue_bits, self) + } +} + +impl CheckedUnsigned { + /// Returns our value if it fits in the given number of bits + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitCount, CheckedUnsigned, CheckedError}; + /// + /// // a value of 7 fits into a 3 bit count + /// assert!(CheckedUnsigned::<8, u8>::new(3, 0b111).is_ok()); + /// + /// // a value of 8 does not fit into a 3 bit count + /// assert!(matches!( + /// CheckedUnsigned::<8, u8>::new(3, 0b1000), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// + /// // a bit count of 9 is too large for u8 + /// assert!(matches!( + /// CheckedUnsigned::<9, _>::new(9, 1u8), + /// Err(CheckedError::ExcessiveBits), + /// )); + /// ``` + #[inline] + pub fn new(count: impl TryInto>, value: U) -> Result { + let count @ BitCount { bits } = + count.try_into().map_err(|_| CheckedError::ExcessiveBits)?; + + if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { + if bits == 0 { + Ok(Self { + count, + value: U::ZERO, + }) + } else if value <= U::ALL >> (U::BITS_SIZE - bits) { + Ok(Self { count, value }) + } else { + Err(CheckedError::ExcessiveValue) + } + } else { + Err(CheckedError::ExcessiveBits) + } + } + + /// Returns our value if it fits in the given number of const bits + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{CheckedUnsigned, CheckedError}; + /// + /// // a value of 7 fits into a 3 bit count + /// assert!(CheckedUnsigned::<8, u8>::new_fixed::<3>(0b111).is_ok()); + /// + /// // a value of 8 does not fit into a 3 bit count + /// assert!(matches!( + /// CheckedUnsigned::<8, u8>::new_fixed::<3>(0b1000), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// ``` + /// + /// ```compile_fail + /// use bitstream_io::{BitCount, CheckedUnsigned}; + /// + /// // a bit count of 9 is too large for u8 + /// + /// // because this is checked at compile-time, + /// // it does not compile at all + /// let c = CheckedUnsigned::<16, u8>::new_fixed::<9>(1); + /// ``` + pub fn new_fixed(value: U) -> Result { + const { + assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); + } + + if BITS == 0 { + Ok(Self { + count: BitCount::new::<0>(), + value: U::ZERO, + }) + } else if BITS == U::BITS_SIZE || value <= (U::ALL >> (U::BITS_SIZE - BITS)) { + Ok(Self { + // whether BITS is larger than MAX is checked here + count: BitCount::new::(), + value, + }) + } else { + Err(CheckedError::ExcessiveValue) + } + } +} + +/// A fixed number of bits to be consumed or written +/// +/// Analagous to [`BitCount`], this is a zero-sized type +/// whose value is fixed at compile-time and cannot be changed. +/// +/// # Example +/// +/// ``` +/// use bitstream_io::{ +/// BigEndian, BitRead, BitReader, BitWrite, BitWriter, CheckedUnsignedFixed, FixedBitCount, +/// }; +/// +/// type FourBits = CheckedUnsignedFixed<4, u8>; +/// +/// let input: &[u8] = &[0b0001_1111, 0b0110_1001]; +/// let mut r = BitReader::endian(input, BigEndian); +/// +/// // read 4, 4-bit values +/// let v1 = r.read_checked::(FixedBitCount).unwrap(); +/// let v2 = r.read_checked::(FixedBitCount).unwrap(); +/// let v3 = r.read_checked::(FixedBitCount).unwrap(); +/// let v4 = r.read_checked::(FixedBitCount).unwrap(); +/// +/// assert_eq!(v1.into_value(), 0b0001); +/// assert_eq!(v2.into_value(), 0b1111); +/// assert_eq!(v3.into_value(), 0b0110); +/// assert_eq!(v4.into_value(), 0b1001); +/// +/// // write those same values back to disk +/// let mut w = BitWriter::endian(vec![], BigEndian); +/// w.write_checked(v1).unwrap(); +/// w.write_checked(v2).unwrap(); +/// w.write_checked(v3).unwrap(); +/// w.write_checked(v4).unwrap(); +/// +/// // ensure they're the same +/// assert_eq!(w.into_writer().as_slice(), input); +/// ``` +#[derive(Copy, Clone, Debug)] +pub struct FixedBitCount; + +impl From> for BitCount { + fn from(_count: FixedBitCount) -> Self { + BitCount::new::() + } +} + +impl core::convert::TryFrom> + for FixedBitCount +{ + type Error = BitCount; + + fn try_from(count: BitCount) -> Result { + (count.bits == BITS).then_some(FixedBitCount).ok_or(count) + } +} + +/// An unsigned type with a verified value for a fixed number of bits +pub type CheckedUnsignedFixed = Checked, T>; + +impl CheckedUnsignedFixed { + /// Returns our checked value if it fits in the given number of const bits + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{CheckedUnsignedFixed, CheckedError}; + /// + /// // a value of 7 fits into a maximum of 3 bits + /// assert!(CheckedUnsignedFixed::<3, u8>::new_fixed(0b111).is_ok()); + /// + /// // a value of 8 does not fit into a maximum of 3 bits + /// assert!(matches!( + /// CheckedUnsignedFixed::<3, u8>::new_fixed(0b1000), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// ``` + /// + /// ```compile_fail + /// use bitstream_io::CheckedUnsignedFixed; + /// + /// // a bit count of 9 is too large for u8 + /// + /// // because this is checked at compile-time, + /// // it does not compile at all + /// let c = CheckedUnsignedFixed::<9, u8>::new_fixed(1); + /// ``` + pub fn new_fixed(value: U) -> Result { + const { + assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); + } + + if BITS == 0 { + Ok(Self { + count: FixedBitCount, + value: U::ZERO, + }) + } else if BITS == U::BITS_SIZE || value <= (U::ALL >> (U::BITS_SIZE - BITS)) { + Ok(Self { + count: FixedBitCount, + value, + }) + } else { + Err(CheckedError::ExcessiveValue) + } + } +} + +impl Checkable for CheckedUnsignedFixed { + #[inline] + fn write(&self, writer: &mut W) -> io::Result<()> { + // a naive default implementation + writer.write_unsigned::(self.value) + } + + #[inline] + fn written_bits(&self) -> u32 { + BITS + } +} + +impl private::Checkable for CheckedUnsignedFixed { + fn write_endian( + self, + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result<()> + where + E: private::Endianness, + W: io::Write, + { + E::write_bits_checked( + writer, + queue_value, + queue_bits, + Checked { + value: self.value, + count: self.count.into(), + }, + ) + } +} + +impl CheckablePrimitive for CheckedUnsignedFixed { + type CountType = FixedBitCount; + + fn read(reader: &mut R, count: FixedBitCount) -> io::Result { + Ok(Self { + value: reader.read_unsigned::()?, + count, + }) + } +} + +/// A signed type with a verified value +pub type CheckedSigned = Checked, T>; + +impl Checkable for CheckedSigned { + #[inline] + fn write(&self, writer: &mut W) -> io::Result<()> { + // a naive default implementation + writer.write_signed_counted(self.count, self.value) + } + + #[inline] + fn written_bits(&self) -> u32 { + self.count.bits.into() + } +} + +impl CheckablePrimitive for CheckedSigned { + type CountType = SignedBitCount; + + #[inline] + fn read(reader: &mut R, count: Self::CountType) -> io::Result { + reader + .read_signed_counted(count) + .map(|value| Self { value, count }) + } +} + +impl private::Checkable for CheckedSigned { + #[inline] + fn write_endian( + self, + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result<()> + where + E: private::Endianness, + W: io::Write, + { + E::write_signed_bits_checked(writer, queue_value, queue_bits, self) + } +} + +impl CheckedSigned { + /// Returns our value if it fits in the given number of bits + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{SignedBitCount, CheckedSigned, CheckedError}; + /// + /// // a value of 3 fits into a 3 bit count + /// assert!(CheckedSigned::<8, _>::new(3, 3i8).is_ok()); + /// + /// // a value of 4 does not fit into a 3 bit count + /// assert!(matches!( + /// CheckedSigned::<8, _>::new(3, 4i8), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// + /// // a bit count of 9 is too large for i8 + /// assert!(matches!( + /// CheckedSigned::<9, _>::new(9, 1i8), + /// Err(CheckedError::ExcessiveBits), + /// )); + /// ``` + #[inline] + pub fn new(count: impl TryInto>, value: S) -> Result { + let count @ SignedBitCount { + bits: BitCount { bits }, + unsigned: BitCount { + bits: unsigned_bits, + }, + } = count.try_into().map_err(|_| CheckedError::ExcessiveBits)?; + + if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { + if bits == S::BITS_SIZE + || (((S::ZERO - S::ONE) << unsigned_bits) <= value + && value < (S::ONE << unsigned_bits)) + { + Ok(Self { count, value }) + } else { + Err(CheckedError::ExcessiveValue) + } + } else { + Err(CheckedError::ExcessiveBits) + } + } + + /// Returns our value if it fits in the given number of const bits + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{CheckedSigned, CheckedError}; + /// + /// // a value of 3 fits into a 3 bit count + /// assert!(CheckedSigned::<8, i8>::new_fixed::<3>(3).is_ok()); + /// + /// // a value of 4 does not fit into a 3 bit count + /// assert!(matches!( + /// CheckedSigned::<8, i8>::new_fixed::<3>(4), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// ``` + /// + /// ```compile_fail + /// use bitstream_io::{BitCount, CheckedSigned}; + /// + /// // a bit count of 9 is too large for i8 + /// + /// // because this is checked at compile-time, + /// // it does not compile at all + /// let c = CheckedSigned::<16, i8>::new_fixed::<9>(1); + /// ``` + pub fn new_fixed(value: S) -> Result { + const { + assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); + } + + if BITS == S::BITS_SIZE + || (((S::ZERO - S::ONE) << (BITS - 1)) <= value && value < (S::ONE << (BITS - 1))) + { + Ok(Self { + count: SignedBitCount::new::(), + value, + }) + } else { + Err(CheckedError::ExcessiveValue) + } + } +} + +/// A fixed number of bits to be consumed or written +/// +/// Analagous to [`SignedBitCount`], this is a zero-sized type +/// whose value is fixed at compile-time and cannot be changed. +/// +/// # Example +/// +/// ``` +/// use bitstream_io::{ +/// BigEndian, BitRead, BitReader, BitWrite, BitWriter, +/// CheckedSignedFixed, FixedSignedBitCount, +/// }; +/// +/// type FourBits = CheckedSignedFixed<4, i8>; +/// +/// let input: &[u8] = &[0b0001_1111, 0b0110_1001]; +/// let mut r = BitReader::endian(input, BigEndian); +/// +/// // read 4, 4-bit values +/// let v1 = r.read_checked::(FixedSignedBitCount).unwrap(); +/// let v2 = r.read_checked::(FixedSignedBitCount).unwrap(); +/// let v3 = r.read_checked::(FixedSignedBitCount).unwrap(); +/// let v4 = r.read_checked::(FixedSignedBitCount).unwrap(); +/// +/// assert_eq!(v1.into_value(), 1); +/// assert_eq!(v2.into_value(), -1); +/// assert_eq!(v3.into_value(), 6); +/// assert_eq!(v4.into_value(), -7); +/// +/// // write those same values back to disk +/// let mut w = BitWriter::endian(vec![], BigEndian); +/// w.write_checked(v1).unwrap(); +/// w.write_checked(v2).unwrap(); +/// w.write_checked(v3).unwrap(); +/// w.write_checked(v4).unwrap(); +/// +/// // ensure they're the same +/// assert_eq!(w.into_writer().as_slice(), input); +/// ``` +#[derive(Copy, Clone, Debug)] +pub struct FixedSignedBitCount; + +impl From> for SignedBitCount { + fn from(_count: FixedSignedBitCount) -> Self { + SignedBitCount::new::() + } +} + +impl core::convert::TryFrom> + for FixedSignedBitCount +{ + type Error = SignedBitCount; + + fn try_from(count: SignedBitCount) -> Result { + (count.bits.bits == BITS) + .then_some(FixedSignedBitCount) + .ok_or(count) + } +} + +/// A signed type with a verified value for a fixed number of bits +pub type CheckedSignedFixed = Checked, T>; + +impl CheckedSignedFixed { + /// Returns our checked value if it fits in the given number of const bits + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{SignedBitCount, CheckedSignedFixed, CheckedError}; + /// + /// // a value of 3 fits into a 3 bit count + /// assert!(CheckedSignedFixed::<3, _>::new_fixed(3i8).is_ok()); + /// + /// // a value of 4 does not fit into a 3 bit count + /// assert!(matches!( + /// CheckedSignedFixed::<3, _>::new_fixed(4i8), + /// Err(CheckedError::ExcessiveValue), + /// )); + /// ``` + /// + /// ```compile_fail + /// use bitstream_io::CheckedSignedFixed; + /// + /// // a bit count of 9 is too large for i8 + /// + /// // because this is checked at compile-time, + /// // it does not compile at all + /// let c = CheckedSignedFixed::<9, _>::new_fixed(1i8); + /// ``` + pub fn new_fixed(value: S) -> Result { + const { + assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); + } + + if BITS == S::BITS_SIZE + || (((S::ZERO - S::ONE) << (BITS - 1)) <= value && value < (S::ONE << (BITS - 1))) + { + Ok(Self { + count: FixedSignedBitCount, + value, + }) + } else { + Err(CheckedError::ExcessiveValue) + } + } +} +impl Checkable for CheckedSignedFixed { + #[inline] + fn write(&self, writer: &mut W) -> io::Result<()> { + // a naive default implementation + writer.write_signed::(self.value) + } + + #[inline] + fn written_bits(&self) -> u32 { + BITS + } +} + +impl private::Checkable for CheckedSignedFixed { + #[inline] + fn write_endian( + self, + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result<()> + where + E: private::Endianness, + W: io::Write, + { + E::write_signed_bits_checked( + writer, + queue_value, + queue_bits, + CheckedSigned { + value: self.value, + count: self.count.into(), + }, + ) + } +} + +impl CheckablePrimitive for CheckedSignedFixed { + type CountType = FixedSignedBitCount; + + fn read( + reader: &mut R, + count: FixedSignedBitCount, + ) -> io::Result { + Ok(Self { + value: reader.read_signed::()?, + count, + }) + } +} + +/// A trait for writable types whose values can be validated +/// +/// Ordinarily, when writing a value to a stream with a given +/// number of bits, the value must be validated to ensure +/// it will fit within that number of bits. +/// +/// # Example 1 +/// +/// ``` +/// use bitstream_io::{BitWrite, BitWriter, BigEndian}; +/// +/// let mut w = BitWriter::endian(vec![], BigEndian); +/// +/// // writing a value of 2 in 1 bit is always an error +/// // which is checked here at write-time +/// assert!(w.write::<1, u8>(2).is_err()); +/// ``` +/// +/// But if the value can be checked beforehand, +/// it doesn't need to be checked at write-time. +/// +/// # Example 2 +/// +/// ``` +/// use bitstream_io::{BitWrite, BitWriter, BigEndian, CheckedUnsigned}; +/// +/// let mut w = BitWriter::endian(vec![], BigEndian); +/// +/// // writing a value of 1 in 1 bit is ok +/// // and we're checking that validity at this stage +/// let value = CheckedUnsigned::<1, u8>::new_fixed::<1>(1).unwrap(); +/// +/// // because we've pre-validated the value beforehand, +/// // it doesn't need to be checked again here +/// // (though the write itself may still fail) +/// assert!(w.write_checked(value).is_ok()); +/// ``` +/// +pub trait Checkable: private::Checkable + Sized { + /// Write our value to the given stream + fn write(&self, writer: &mut W) -> io::Result<()>; + + /// The number of written bits + fn written_bits(&self) -> u32; +} + +/// A trait for readable types whose bit counts can be saved +/// +/// Because the intent of reading checkable values is +/// to avoid validating their values when being written, +/// implementing the [`Checkable`] trait is required. +pub trait CheckablePrimitive: Checkable { + /// Our bit count type for reading + type CountType; + + /// Reads our value from the given stream + fn read(reader: &mut R, count: Self::CountType) -> io::Result; +} + +/// Big-endian, or most significant bits first +#[derive(Copy, Clone, Debug)] +pub struct BigEndian; + +/// Big-endian, or most significant bits first +pub type BE = BigEndian; + +impl BigEndian { + // checked in the sense that we've verified + // the output type is large enough to hold the + // requested number of bits + #[inline] + fn read_bits_checked( + reader: &mut R, + queue: &mut u8, + queue_bits: &mut u32, + BitCount { bits }: BitCount, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + // reads a whole value with the given number of + // bytes in our endianness, where the number of bytes + // must be less than or equal to the type's size in bytes + #[inline(always)] + fn read_bytes(reader: &mut R, bytes: usize) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + let mut buf = U::buffer(); + reader + .read_exact(&mut buf.as_mut()[(mem::size_of::() - bytes)..]) + .map(|()| U::from_be_bytes(buf)) + } + + if bits <= *queue_bits { + // all bits in queue, so no byte needed + let value = queue.shr_default(u8::BITS_SIZE - bits); + *queue = queue.shl_default(bits); + *queue_bits -= bits; + Ok(U::from_u8(value)) + } else { + // at least one byte needed + + // bits needed beyond what's in the queue + let needed_bits = bits - *queue_bits; + + match (needed_bits / 8, needed_bits % 8) { + (0, needed) => { + // only one additional byte needed, + // which we share between our returned value + // and the bit queue + let next_byte = read_byte(reader)?; + + Ok(U::from_u8( + mem::replace(queue, next_byte.shl_default(needed)).shr_default( + u8::BITS_SIZE - mem::replace(queue_bits, u8::BITS_SIZE - needed), + ), + ) + .shl_default(needed) + | U::from_u8(next_byte.shr_default(u8::BITS_SIZE - needed))) + } + (bytes, 0) => { + // exact number of bytes needed beyond what's + // available in the queue + // so read a whole value from the reader + // and prepend what's left of our queue onto it + + Ok(U::from_u8( + mem::take(queue).shr_default(u8::BITS_SIZE - mem::take(queue_bits)), + ) + .shl_default(needed_bits) + | read_bytes(reader, bytes as usize)?) + } + (bytes, needed) => { + // read a whole value from the reader + // prepend what's in the queue at the front of it + // *and* append a partial byte at the end of it + // while also updating the queue and its bit count + + let whole: U = read_bytes(reader, bytes as usize)?; + let next_byte = read_byte(reader)?; + + Ok(U::from_u8( + mem::replace(queue, next_byte.shl_default(needed)).shr_default( + u8::BITS_SIZE - mem::replace(queue_bits, u8::BITS_SIZE - needed), + ), + ) + .shl_default(needed_bits) + | whole.shl_default(needed) + | U::from_u8(next_byte.shr_default(u8::BITS_SIZE - needed))) + } + } + } + } +} + +impl Endianness for BigEndian {} + +impl private::Endianness for BigEndian { + #[inline] + fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option { + *queue_value = (*queue_value << 1) | u8::from(bit); + *queue_bits = (*queue_bits + 1) % 8; + (*queue_bits == 0).then(|| mem::take(queue_value)) + } + + #[inline] + fn read_bits( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + count @ BitCount { bits }: BitCount, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { + Self::read_bits_checked::(reader, queue_value, queue_bits, count) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type read", + )) + } + } + + #[inline] + fn read_bits_fixed( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + const { + assert!(BITS <= U::BITS_SIZE, "excessive bits for type read"); + } + + Self::read_bits_checked::( + reader, + queue_value, + queue_bits, + BitCount::new::(), + ) + } + + // checked in the sense that we've verified + // the input type is large enough to hold the + // requested number of bits and that the value is + // not too large for those bits + #[inline] + fn write_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + CheckedUnsigned { + count: BitCount { bits }, + value, + }: CheckedUnsigned, + ) -> io::Result<()> + where + W: io::Write, + U: UnsignedInteger, + { + fn write_bytes(writer: &mut W, bytes: usize, value: U) -> io::Result<()> + where + W: io::Write, + U: UnsignedInteger, + { + let buf = U::to_be_bytes(value); + writer.write_all(&buf.as_ref()[(mem::size_of::() - bytes)..]) + } + + // the amount of available bits in the queue + let available_bits = u8::BITS_SIZE - *queue_bits; + + if bits < available_bits { + // all bits fit in queue, so no write needed + *queue_value = queue_value.shl_default(bits) | U::to_u8(value); + *queue_bits += bits; + Ok(()) + } else { + // at least one byte needs to be written + + // bits beyond what can fit in the queue + let excess_bits = bits - available_bits; + + match (excess_bits / 8, excess_bits % 8) { + (0, excess) => { + // only one byte to be written, + // while the excess bits are shared + // between the written byte and the bit queue + + *queue_bits = excess; + + write_byte( + writer, + mem::replace( + queue_value, + U::to_u8(value & U::ALL.shr_default(U::BITS_SIZE - excess)), + ) + .shl_default(available_bits) + | U::to_u8(value.shr_default(excess)), + ) + } + (bytes, 0) => { + // no excess bytes beyond what can fit the queue + // so write a whole byte and + // the remainder of the whole value + + *queue_bits = 0; + + write_byte( + writer.by_ref(), + mem::take(queue_value).shl_default(available_bits) + | U::to_u8(value.shr_default(bytes * 8)), + )?; + + write_bytes(writer, bytes as usize, value) + } + (bytes, excess) => { + // write what's in the queue along + // with the head of our whole value, + // write the middle section of our whole value, + // while also replacing the queue with + // the tail of our whole value + + *queue_bits = excess; + + write_byte( + writer.by_ref(), + mem::replace( + queue_value, + U::to_u8(value & U::ALL.shr_default(U::BITS_SIZE - excess)), + ) + .shl_default(available_bits) + | U::to_u8(value.shr_default(excess + bytes * 8)), + )?; + + write_bytes(writer, bytes as usize, value.shr_default(excess)) + } + } + } + } + + fn write_signed_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + value: CheckedSigned, + ) -> io::Result<()> + where + W: io::Write, + S: SignedInteger, + { + let ( + SignedBitCount { + bits: BitCount { bits }, + unsigned, + }, + value, + ) = value.into_count_value(); + + if let Some(b) = Self::push_bit_flush(queue_value, queue_bits, value.is_negative()) { + write_byte(writer.by_ref(), b)?; + } + Self::write_bits_checked( + writer, + queue_value, + queue_bits, + Checked { + value: if value.is_negative() { + value.as_negative(bits) + } else { + value.as_non_negative() + }, + count: unsigned, + }, + ) + } + + #[inline] + fn pop_bit_refill( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + { + Ok(if *queue_bits == 0 { + let value = read_byte(reader)?; + let msb = value & u8::MSB_BIT; + *queue_value = value << 1; + *queue_bits = u8::BITS_SIZE - 1; + msb + } else { + let msb = *queue_value & u8::MSB_BIT; + *queue_value <<= 1; + *queue_bits -= 1; + msb + } != 0) + } + + #[inline] + fn pop_unary( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + match STOP_BIT { + 0 => find_unary( + reader, + queue_value, + queue_bits, + |v| v.leading_ones(), + |q| *q, + |v, b| v.checked_shl(b), + ), + 1 => find_unary( + reader, + queue_value, + queue_bits, + |v| v.leading_zeros(), + |_| u8::BITS_SIZE, + |v, b| v.checked_shl(b), + ), + _ => unreachable!(), + } + } + + #[inline] + fn read_signed_counted( + r: &mut R, + SignedBitCount { + bits: BitCount { bits }, + unsigned, + }: SignedBitCount, + ) -> io::Result + where + R: BitRead, + S: SignedInteger, + { + if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { + let is_negative = r.read_bit()?; + let unsigned = r.read_unsigned_counted::(unsigned)?; + Ok(if is_negative { + unsigned.as_negative(bits) + } else { + unsigned.as_non_negative() + }) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type read", + )) + } + } + + fn read_bytes( + reader: &mut R, + queue_value: &mut u8, + queue_bits: u32, + buf: &mut [u8], + ) -> io::Result<()> + where + R: io::Read, + { + if queue_bits == 0 { + reader.read_exact(buf) + } else { + let mut input_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; + + for output_chunk in buf.chunks_mut(CHUNK_SIZE) { + let input_chunk = &mut input_chunk[0..output_chunk.len()]; + reader.read_exact(input_chunk)?; + + // shift down each byte in our input to eventually + // accomodate the contents of the bit queue + // and make that our output + output_chunk + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o = i >> queue_bits; + }); + + // include leftover bits from the next byte + // shifted to the top + output_chunk[1..] + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o |= *i << (u8::BITS_SIZE - queue_bits); + }); + + // finally, prepend the queue's contents + // to the first byte in the chunk + // while replacing those contents + // with the final byte of the input + output_chunk[0] |= mem::replace( + queue_value, + input_chunk.last().unwrap() << (u8::BITS_SIZE - queue_bits), + ); + } + + Ok(()) + } + } + + fn write_bytes( + writer: &mut W, + queue_value: &mut u8, + queue_bits: u32, + buf: &[u8], + ) -> io::Result<()> + where + W: io::Write, + { + if queue_bits == 0 { + writer.write_all(buf) + } else { + let mut output_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; + + for input_chunk in buf.chunks(CHUNK_SIZE) { + let output_chunk = &mut output_chunk[0..input_chunk.len()]; + + output_chunk + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o = i >> queue_bits; + }); + + output_chunk[1..] + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o |= *i << (u8::BITS_SIZE - queue_bits); + }); + + output_chunk[0] |= mem::replace( + queue_value, + input_chunk.last().unwrap() & (u8::ALL >> (u8::BITS_SIZE - queue_bits)), + ) << (u8::BITS_SIZE - queue_bits); + + writer.write_all(output_chunk)?; + } + + Ok(()) + } + } + + #[inline(always)] + fn bytes_to_primitive(buf: P::Bytes) -> P { + P::from_be_bytes(buf) + } + + #[inline(always)] + fn primitive_to_bytes(p: P) -> P::Bytes { + p.to_be_bytes() + } + + #[inline] + fn read_primitive(r: &mut R) -> io::Result + where + R: BitRead, + V: Primitive, + { + let mut buffer = V::buffer(); + r.read_bytes(buffer.as_mut())?; + Ok(V::from_be_bytes(buffer)) + } + + #[inline] + fn write_primitive(w: &mut W, value: V) -> io::Result<()> + where + W: BitWrite, + V: Primitive, + { + w.write_bytes(value.to_be_bytes().as_ref()) + } +} + +/// Little-endian, or least significant bits first +#[derive(Copy, Clone, Debug)] +pub struct LittleEndian; + +/// Little-endian, or least significant bits first +pub type LE = LittleEndian; + +impl LittleEndian { + // checked in the sense that we've verified + // the output type is large enough to hold the + // requested number of bits + #[inline] + fn read_bits_checked( + reader: &mut R, + queue: &mut u8, + queue_bits: &mut u32, + BitCount { bits }: BitCount, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + // reads a whole value with the given number of + // bytes in our endianness, where the number of bytes + // must be less than or equal to the type's size in bytes + #[inline(always)] + fn read_bytes(reader: &mut R, bytes: usize) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + let mut buf = U::buffer(); + reader + .read_exact(&mut buf.as_mut()[0..bytes]) + .map(|()| U::from_le_bytes(buf)) + } + + if bits <= *queue_bits { + // all bits in queue, so no byte needed + let value = *queue & u8::ALL.shr_default(u8::BITS_SIZE - bits); + *queue = queue.shr_default(bits); + *queue_bits -= bits; + Ok(U::from_u8(value)) + } else { + // at least one byte needed + + // bits needed beyond what's in the queue + let needed_bits = bits - *queue_bits; + + match (needed_bits / 8, needed_bits % 8) { + (0, needed) => { + // only one additional byte needed, + // which we share between our returned value + // and the bit queue + let next_byte = read_byte(reader)?; + + Ok( + U::from_u8(mem::replace(queue, next_byte.shr_default(needed))) + | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed))) + << mem::replace(queue_bits, u8::BITS_SIZE - needed)), + ) + } + (bytes, 0) => { + // exact number of bytes needed beyond what's + // available in the queue + + // so read a whole value from the reader + // and prepend what's left of our queue onto it + + Ok(U::from_u8(mem::take(queue)) + | (read_bytes::(reader, bytes as usize)? << mem::take(queue_bits))) + } + (bytes, needed) => { + // read a whole value from the reader + // prepend what's in the queue at the front of it + // *and* append a partial byte at the end of it + // while also updating the queue and its bit count + + let whole: U = read_bytes(reader, bytes as usize)?; + let next_byte = read_byte(reader)?; + + Ok( + U::from_u8(mem::replace(queue, next_byte.shr_default(needed))) + | (whole << *queue_bits) + | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed))) + << (mem::replace(queue_bits, u8::BITS_SIZE - needed) + bytes * 8)), + ) + } + } + } + } +} + +impl Endianness for LittleEndian {} + +impl private::Endianness for LittleEndian { + #[inline] + fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option { + *queue_value |= u8::from(bit) << *queue_bits; + *queue_bits = (*queue_bits + 1) % 8; + (*queue_bits == 0).then(|| mem::take(queue_value)) + } + + #[inline] + fn read_bits( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + count @ BitCount { bits }: BitCount, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { + Self::read_bits_checked::(reader, queue_value, queue_bits, count) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type read", + )) + } + } + + #[inline] + fn read_bits_fixed( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + U: UnsignedInteger, + { + const { + assert!(BITS <= U::BITS_SIZE, "excessive bits for type read"); + } + + Self::read_bits_checked::( + reader, + queue_value, + queue_bits, + BitCount::new::(), + ) + } + + // checked in the sense that we've verified + // the input type is large enough to hold the + // requested number of bits and that the value is + // not too large for those bits + #[inline] + fn write_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + CheckedUnsigned { + count: BitCount { bits }, + value, + }: CheckedUnsigned, + ) -> io::Result<()> + where + W: io::Write, + U: UnsignedInteger, + { + fn write_bytes(writer: &mut W, bytes: usize, value: U) -> io::Result<()> + where + W: io::Write, + U: UnsignedInteger, + { + let buf = U::to_le_bytes(value); + writer.write_all(&buf.as_ref()[0..bytes]) + } + + // the amount of available bits in the queue + let available_bits = u8::BITS_SIZE - *queue_bits; + + if bits < available_bits { + // all bits fit in queue, so no write needed + *queue_value |= U::to_u8(value.shl_default(*queue_bits)); + *queue_bits += bits; + Ok(()) + } else { + // at least one byte needs to be written + + // bits beyond what can fit in the queue + let excess_bits = bits - available_bits; + + match (excess_bits / 8, excess_bits % 8) { + (0, excess) => { + // only one byte to be written, + // while the excess bits are shared + // between the written byte and the bit queue + + write_byte( + writer, + mem::replace(queue_value, U::to_u8(value.shr_default(available_bits))) + | U::to_u8( + (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL), + ), + ) + } + (bytes, 0) => { + // no excess bytes beyond what can fit the queue + // so write a whole byte and + // the remainder of the whole value + + write_byte( + writer.by_ref(), + mem::take(queue_value) + | U::to_u8((value << mem::take(queue_bits)) & U::from_u8(u8::ALL)), + )?; + + write_bytes(writer, bytes as usize, value >> available_bits) + } + (bytes, excess) => { + // write what's in the queue along + // with the head of our whole value, + // write the middle section of our whole value, + // while also replacing the queue with + // the tail of our whole value + + write_byte( + writer.by_ref(), + mem::replace( + queue_value, + U::to_u8(value.shr_default(available_bits + bytes * 8)), + ) | U::to_u8( + (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL), + ), + )?; + + write_bytes(writer, bytes as usize, value >> available_bits) + } + } + } + } + + fn write_signed_bits_checked( + writer: &mut W, + queue_value: &mut u8, + queue_bits: &mut u32, + value: CheckedSigned, + ) -> io::Result<()> + where + W: io::Write, + S: SignedInteger, + { + // little-endian + let ( + SignedBitCount { + bits: BitCount { bits }, + unsigned, + }, + value, + ) = value.into_count_value(); + + Self::write_bits_checked( + writer.by_ref(), + queue_value, + queue_bits, + Checked { + value: if value.is_negative() { + value.as_negative(bits) + } else { + value.as_non_negative() + }, + count: unsigned, + }, + )?; + match Self::push_bit_flush(queue_value, queue_bits, value.is_negative()) { + Some(b) => write_byte(writer, b), + None => Ok(()), + } + } + + #[inline] + fn pop_bit_refill( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + { + Ok(if *queue_bits == 0 { + let value = read_byte(reader)?; + let lsb = value & u8::LSB_BIT; + *queue_value = value >> 1; + *queue_bits = u8::BITS_SIZE - 1; + lsb + } else { + let lsb = *queue_value & u8::LSB_BIT; + *queue_value >>= 1; + *queue_bits -= 1; + lsb + } != 0) + } + + #[inline] + fn pop_unary( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + ) -> io::Result + where + R: io::Read, + { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + match STOP_BIT { + 0 => find_unary( + reader, + queue_value, + queue_bits, + |v| v.trailing_ones(), + |q| *q, + |v, b| v.checked_shr(b), + ), + 1 => find_unary( + reader, + queue_value, + queue_bits, + |v| v.trailing_zeros(), + |_| u8::BITS_SIZE, + |v, b| v.checked_shr(b), + ), + _ => unreachable!(), + } + } + + #[inline] + fn read_signed_counted( + r: &mut R, + SignedBitCount { + bits: BitCount { bits }, + unsigned, + }: SignedBitCount, + ) -> io::Result + where + R: BitRead, + S: SignedInteger, + { + if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { + let unsigned = r.read_unsigned_counted::(unsigned)?; + let is_negative = r.read_bit()?; + Ok(if is_negative { + unsigned.as_negative(bits) + } else { + unsigned.as_non_negative() + }) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type read", + )) + } + } + + fn read_bytes( + reader: &mut R, + queue_value: &mut u8, + queue_bits: u32, + buf: &mut [u8], + ) -> io::Result<()> + where + R: io::Read, + { + if queue_bits == 0 { + reader.read_exact(buf) + } else { + let mut input_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; + + for output_chunk in buf.chunks_mut(CHUNK_SIZE) { + let input_chunk = &mut input_chunk[0..output_chunk.len()]; + reader.read_exact(input_chunk)?; + + output_chunk + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o = i << queue_bits; + }); + + output_chunk[1..] + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o |= i >> (u8::BITS_SIZE - queue_bits); + }); + + output_chunk[0] |= mem::replace( + queue_value, + input_chunk.last().unwrap() >> (u8::BITS_SIZE - queue_bits), + ); + } + + Ok(()) + } + } + + fn write_bytes( + writer: &mut W, + queue_value: &mut u8, + queue_bits: u32, + buf: &[u8], + ) -> io::Result<()> + where + W: io::Write, + { + if queue_bits == 0 { + writer.write_all(buf) + } else { + let mut output_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; + + for input_chunk in buf.chunks(CHUNK_SIZE) { + let output_chunk = &mut output_chunk[0..input_chunk.len()]; + + output_chunk + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o = i << queue_bits; + }); + + output_chunk[1..] + .iter_mut() + .zip(input_chunk.iter()) + .for_each(|(o, i)| { + *o |= i >> (u8::BITS_SIZE - queue_bits); + }); + + output_chunk[0] |= mem::replace( + queue_value, + input_chunk.last().unwrap() >> (u8::BITS_SIZE - queue_bits), + ); + + writer.write_all(output_chunk)?; + } + + Ok(()) + } + } + + #[inline(always)] + fn bytes_to_primitive(buf: P::Bytes) -> P { + P::from_le_bytes(buf) + } + + #[inline(always)] + fn primitive_to_bytes(p: P) -> P::Bytes { + p.to_le_bytes() + } + + #[inline] + fn read_primitive(r: &mut R) -> io::Result + where + R: BitRead, + V: Primitive, + { + let mut buffer = V::buffer(); + r.read_bytes(buffer.as_mut())?; + Ok(V::from_le_bytes(buffer)) + } + + #[inline] + fn write_primitive(w: &mut W, value: V) -> io::Result<()> + where + W: BitWrite, + V: Primitive, + { + w.write_bytes(value.to_le_bytes().as_ref()) + } +} + +#[inline] +fn find_unary( + reader: &mut R, + queue_value: &mut u8, + queue_bits: &mut u32, + leading_bits: impl Fn(u8) -> u32, + max_bits: impl Fn(&mut u32) -> u32, + checked_shift: impl Fn(u8, u32) -> Option, +) -> io::Result +where + R: io::Read, +{ + let mut acc = 0; + + loop { + match leading_bits(*queue_value) { + bits if bits == max_bits(queue_bits) => { + // all bits exhausted + // fetch another byte and keep going + acc += *queue_bits; + *queue_value = read_byte(reader.by_ref())?; + *queue_bits = u8::BITS_SIZE; + } + bits => match checked_shift(*queue_value, bits + 1) { + Some(value) => { + // fetch part of source byte + *queue_value = value; + *queue_bits -= bits + 1; + break Ok(acc + bits); + } + None => { + // fetch all of source byte + *queue_value = 0; + *queue_bits = 0; + break Ok(acc + bits); + } + }, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/read.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/read.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2508 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits and implementations for reading bits from a stream. + +#![warn(missing_docs)] + +#[cfg(not(feature = "std"))] +use core2::io; + +#[cfg(feature = "alloc")] +use alloc::{vec, vec::Vec}; +#[cfg(feature = "std")] +use std::io; + +use super::{ + BitCount, CheckablePrimitive, Endianness, Integer, PhantomData, Primitive, SignedBitCount, + SignedInteger, UnsignedInteger, VBRInteger, +}; + +use core::convert::TryInto; + +/// An error returned if performing VBR read overflows +#[derive(Copy, Clone, Debug)] +pub(crate) struct VariableWidthOverflow; + +impl core::fmt::Display for VariableWidthOverflow { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + "variable bit rate overflowed".fmt(f) + } +} + +impl core::error::Error for VariableWidthOverflow {} + +impl From for io::Error { + fn from(VariableWidthOverflow: VariableWidthOverflow) -> Self { + io::Error::new( + #[cfg(feature = "std")] + { + io::ErrorKind::StorageFull + }, + #[cfg(not(feature = "std"))] + { + io::ErrorKind::Other + }, + "variable bit rate overflow", + ) + } +} + +/// A trait for anything that can read a variable number of +/// potentially un-aligned values from an input stream +pub trait BitRead { + /// Reads a single bit from the stream. + /// `true` indicates 1, `false` indicates 0 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b1000_1110]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert!(r.read_bit().is_err()); // no more bits to read + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, LittleEndian}; + /// + /// let bytes: &[u8] = &[0b1000_1110]; + /// let mut r = BitReader::endian(bytes, LittleEndian); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert!(r.read_bit().is_err()); // no more bits to read + /// ``` + fn read_bit(&mut self) -> io::Result { + self.read_unsigned::<1, u8>().map(|b| b == 1) + } + + /// Reads a signed or unsigned value from the stream with + /// the given constant number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0001_1111, 0b1011_11_00]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading unsigned value is ok + /// assert_eq!(r.read::<4, u8>().unwrap(), 1); + /// // reading signed value is also ok + /// assert_eq!(r.read::<4, i8>().unwrap(), -1); + /// // reading an array of bits is ok too + /// assert_eq!(r.read::<1, [bool; 4]>().unwrap(), [true, false, true, true]); + /// // reading an array of any Integer type is ok + /// assert_eq!(r.read::<2, [u8; 2]>().unwrap(), [0b11, 0b00]); + /// // reading more bytes than we have is an error + /// assert!(r.read::<4, u8>().is_err()); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0001_1111, 0, 0]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading 9 bits to a u8 is a compile-time error + /// r.read::<9, u8>(); + /// ``` + #[inline] + fn read(&mut self) -> io::Result + where + I: Integer, + { + I::read::(self) + } + + /// Reads a signed or unsigned value from the stream with + /// the given variable number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// let bytes: &[u8] = &[0b0001_1111]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading unsigned value is ok + /// assert_eq!(r.read_var::(4).unwrap(), 1); + /// // reading signed value is also ok + /// assert_eq!(r.read_var::(4).unwrap(), -1); + /// // reading more bytes than we have is an error + /// assert!(r.read_var::(4).is_err()); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// let bytes: &[u8] = &[0, 0, 0, 0, 0]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading 9 bits to a u8 is a runtime error + /// // no matter how much data is left + /// assert!(r.read_var::(9).is_err()); + /// ``` + #[inline] + fn read_var(&mut self, bits: u32) -> io::Result + where + I: Integer + Sized, + { + I::read_var(self, BitCount::unknown(bits)) + } + + /// Given a desired maximum value for a bit count, + /// reads the necessary bits to fill up to that amount. + /// + /// For example, if the maximum bit count is 15 - or `0b1111` - + /// reads a 4-bit unsigned value from the stream and returns a [`BitCount`] + /// which can be used in subsequent reads. + /// + /// Note that `MAX` must be greater than 0, and `MAX + 1` must be + /// an exact power of two. + /// + /// # Errors + /// + /// Passes along an I/O error from the underlying stream. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// + /// let bytes: &[u8] = &[0b100_11110]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// let count = r.read::<3, u32>().unwrap(); + /// assert_eq!(count, 4); // reads 0b100 - or 4 + /// // may need to verify count is not larger than u8 at runtime + /// assert_eq!(r.read_var::(count).unwrap(), 0b1111); + /// ``` + /// + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead, BitCount}; + /// + /// let bytes: &[u8] = &[0b100_11110]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// let count = r.read_count::<0b111>().unwrap(); + /// assert_eq!(count, BitCount::new::<4>()); // reads 0b100 - or 4 + /// // maximum size of bit count is known to be 7 at compile-time, + /// // so no runtime check needed to know 7 bits is not larger than a u8 + /// assert_eq!(r.read_counted::<0b111, u8>(count).unwrap(), 0b1111); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// + /// let bytes: &[u8] = &[0b100_11110]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // maximum bit count is 6 (0b110), so we need to read 3 bits + /// // but no idea what to do if a value of 7 (0b111) is read, + /// // so this does not compile at all + /// let count = r.read_count::<0b110>(); + /// ``` + fn read_count(&mut self) -> io::Result> { + const { + assert!(MAX > 0, "MAX value must be > 0"); + assert!( + MAX == u32::MAX || (MAX + 1).is_power_of_two(), + "MAX should fill some whole number of bits ('0b111', '0b1111', etc.)" + ) + } + + self.read_unsigned_var(if MAX < u32::MAX { + (MAX + 1).ilog2() + } else { + 32 + }) + .map(|bits| BitCount { bits }) + } + + /// Reads a signed or unsigned value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; + /// + /// let bytes: &[u8] = &[0b1111_0000]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading 4 bits with a maximum of 4 will fit into a u8 + /// // so no runtime check needed + /// assert_eq!(r.read_counted::<4, u8>(BitCount::new::<4>()).unwrap(), 0b1111); + /// // reading 4 bits with a maximum of 64 might not fit into a u8 + /// // so we need to verify this at runtime + /// assert_eq!(r.read_counted::<64, u8>(BitCount::new::<4>()).unwrap(), 0b0000); + /// ``` + #[inline(always)] + fn read_counted(&mut self, bits: BitCount) -> io::Result + where + I: Integer + Sized, + { + I::read_var(self, bits) + } + + /// Reads an unsigned value from the stream with + /// the given constant number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b1_01_10111]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert_eq!(reader.read_unsigned::<1, u8>().unwrap(), 0b1); + /// assert_eq!(reader.read_unsigned::<2, u8>().unwrap(), 0b01); + /// assert_eq!(reader.read_unsigned::<5, u8>().unwrap(), 0b10111); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b10110_11_1]; + /// let mut reader = BitReader::endian(data, LittleEndian); + /// assert_eq!(reader.read_unsigned::<1, u8>().unwrap(), 0b1); + /// assert_eq!(reader.read_unsigned::<2, u8>().unwrap(), 0b11); + /// assert_eq!(reader.read_unsigned::<5, u8>().unwrap(), 0b10110); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0, 0, 0, 0, 0]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// // doesn't compile at all + /// reader.read_unsigned::<9, u8>(); // can't read 9 bits to u8 + /// ``` + fn read_unsigned(&mut self) -> io::Result + where + U: UnsignedInteger, + { + self.read_unsigned_var(BITS) + } + + /// Reads an unsigned value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b1_01_10111]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert_eq!(reader.read_unsigned_var::(1).unwrap(), 0b1); + /// assert_eq!(reader.read_unsigned_var::(2).unwrap(), 0b01); + /// assert_eq!(reader.read_unsigned_var::(5).unwrap(), 0b10111); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b10110_11_1]; + /// let mut reader = BitReader::endian(data, LittleEndian); + /// assert_eq!(reader.read_unsigned_var::(1).unwrap(), 0b1); + /// assert_eq!(reader.read_unsigned_var::(2).unwrap(), 0b11); + /// assert_eq!(reader.read_unsigned_var::(5).unwrap(), 0b10110); + /// ``` + /// + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0, 0, 0, 0, 0]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert!(reader.read_unsigned_var::(9).is_err()); // can't read 9 bits to u8 + /// assert!(reader.read_unsigned_var::(17).is_err()); // can't read 17 bits to u16 + /// assert!(reader.read_unsigned_var::(33).is_err()); // can't read 33 bits to u32 + /// assert!(reader.read_unsigned_var::(65).is_err()); // can't read 65 bits to u64 + /// ``` + #[inline(always)] + fn read_unsigned_var(&mut self, bits: u32) -> io::Result + where + U: UnsignedInteger, + { + self.read_unsigned_counted(BitCount::unknown(bits)) + } + + /// Reads an unsigned value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; + /// + /// let bytes: &[u8] = &[0b1111_0000]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading 4 bits with a maximum of 4 will fit into a u8 + /// // so no runtime check needed + /// assert_eq!(r.read_unsigned_counted::<4, u8>(BitCount::new::<4>()).unwrap(), 0b1111); + /// // reading 4 bits with a maximum of 64 might not fit into a u8 + /// // so we need to verify this at runtime + /// assert_eq!(r.read_unsigned_counted::<64, u8>(BitCount::new::<4>()).unwrap(), 0b0000); + /// ``` + fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result + where + U: UnsignedInteger; + + /// Reads a twos-complement signed value from the stream with + /// the given constant number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the number of bits is 0, + /// since one bit is always needed for the sign. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// + /// let data: &[u8] = &[0b1011_0111]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), -5); + /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), 7); + /// assert!(reader.read_signed::<4, i8>().is_err()); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// + /// let data: &[u8] = &[0b1011_0111]; + /// let mut reader = BitReader::endian(data, LittleEndian); + /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), 7); + /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), -5); + /// assert!(reader.read_signed::<4, i8>().is_err()); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// + /// let data: &[u8] = &[0, 0, 0, 0, 0]; + /// let mut reader = BitReader::endian(data, LittleEndian); + /// // reading 9 bits to an i8 is a compile-time error + /// reader.read_signed::<9, i8>(); + /// ``` + fn read_signed(&mut self) -> io::Result + where + S: SignedInteger, + { + self.read_signed_var(BITS) + } + + /// Reads a twos-complement signed value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the number of bits is 0, + /// since one bit is always needed for the sign. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b1011_0111]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert_eq!(reader.read_signed_var::(4).unwrap(), -5); + /// assert_eq!(reader.read_signed_var::(4).unwrap(), 7); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0b1011_0111]; + /// let mut reader = BitReader::endian(data, LittleEndian); + /// assert_eq!(reader.read_signed_var::(4).unwrap(), 7); + /// assert_eq!(reader.read_signed_var::(4).unwrap(), -5); + /// ``` + /// + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + /// let mut r = BitReader::endian(data, BigEndian); + /// assert!(r.read_signed_var::(9).is_err()); // can't read 9 bits to i8 + /// assert!(r.read_signed_var::(17).is_err()); // can't read 17 bits to i16 + /// assert!(r.read_signed_var::(33).is_err()); // can't read 33 bits to i32 + /// assert!(r.read_signed_var::(65).is_err()); // can't read 65 bits to i64 + /// ``` + fn read_signed_var(&mut self, bits: u32) -> io::Result + where + S: SignedInteger, + { + self.read_signed_counted(BitCount::unknown(bits)) + } + + /// Reads a twos-complement signed value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the number of bits is 0, + /// since one bit is always needed for the sign. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; + /// + /// let bytes: &[u8] = &[0b0001_1111]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // reading 4 bits with a maximum of 4 will fit into an i8 + /// // so no runtime check needed + /// assert_eq!(r.read_signed_counted::<4, i8>(BitCount::new::<4>()).unwrap(), 1); + /// // reading 4 bits with a maximum of 64 might not fit into an i8 + /// // so we need to verify this at runtime + /// assert_eq!(r.read_signed_counted::<64, i8>(BitCount::new::<4>()).unwrap(), -1); + /// ``` + fn read_signed_counted( + &mut self, + bits: impl TryInto>, + ) -> io::Result + where + S: SignedInteger; + + /// Reads the given constant value from the stream with the + /// given number of bits. + /// + /// Due to current limitations of constant paramters, + /// this is limited to `u32` values. + /// + /// If the constant read from the stream doesn't match the expected + /// value, returns the generated error from the closure. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream, + /// converted to the mismatch error. Returns the generated + /// error if the read value doesn't match the expected constant. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// enum Error { + /// Mismatch, + /// Io, + /// } + /// + /// impl From for Error { + /// fn from(_err: std::io::Error) -> Self { + /// Self::Io + /// } + /// } + /// + /// let data: &[u8] = &[0b1000_1011, 0b0000_0001]; + /// let mut r = BitReader::endian(data, BigEndian); + /// assert!(r.read_const::<4, 0b1000, _>(Error::Mismatch).is_ok()); + /// assert!(r.read_const::<4, 0b1011, _>(Error::Mismatch).is_ok()); + /// // 0b1000 doesn't match 0b0000 + /// assert!(matches!(r.read_const::<4, 0b1000, _>(Error::Mismatch), Err(Error::Mismatch))); + /// // 0b1011 doesn't match 0b0001 + /// assert!(matches!(r.read_const::<4, 0b1011, _>(Error::Mismatch), Err(Error::Mismatch))); + /// // run out of bits to check + /// assert!(matches!(r.read_const::<4, 0b0000, _>(Error::Mismatch), Err(Error::Io))); + /// ``` + #[inline] + fn read_const(&mut self, err: E) -> Result<(), E> + where + E: From, + { + use super::Numeric; + + const { + assert!( + BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), + "excessive value for bits read" + ); + } + + (self.read::()? == VALUE) + .then_some(()) + .ok_or(err) + } + + /// Reads whole value from the stream whose size in bits is equal + /// to its type's size. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_to::().unwrap(), 0x12_34_56_78); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_to::<[u8; 4]>().unwrap(), [0x12, 0x34, 0x56, 0x78]); + /// ``` + fn read_to(&mut self) -> io::Result + where + V: Primitive; + + /// Reads whole value from the stream whose size in bits is equal + /// to its type's size in an endianness that may be different + /// from the stream's endianness. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, LittleEndian}; + /// + /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_as_to::().unwrap(), 0x78_56_34_12); + /// ``` + fn read_as_to(&mut self) -> io::Result + where + F: Endianness, + V: Primitive; + + /// Skips the given number of bits in the stream. + /// Since this method does not need an accumulator, + /// it may be slightly faster than reading to an empty variable. + /// In addition, since there is no accumulator, + /// there is no upper limit on the number of bits + /// which may be skipped. + /// These bits are still read from the stream, however, + /// and are never skipped via a `seek` method. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b1_00000_10]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert!(r.skip(5).is_ok()); + /// assert_eq!(r.read_bit().unwrap(), true); + /// assert_eq!(r.read_bit().unwrap(), false); + /// assert!(r.read_bit().is_err()); + /// ``` + fn skip(&mut self, bits: u32) -> io::Result<()> { + (0..bits).try_for_each(|_| self.read_bit().map(|_| ())) + } + + /// Completely fills the given buffer with whole bytes. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03, 0x04]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// let mut buf = [0; 3]; + /// assert_eq!(r.read::<8, u8>().unwrap(), 0x00); + /// assert!(r.read_bytes(&mut buf).is_ok()); + /// assert_eq!(&buf, &[0x01, 0x02, 0x03]); + /// assert_eq!(r.read::<8, u8>().unwrap(), 0x04); + /// ``` + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + for b in buf.iter_mut() { + *b = self.read_unsigned::<8, _>()?; + } + Ok(()) + } + + /// Completely fills a whole buffer with bytes and returns it. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[inline(always)] + #[deprecated(since = "1.8.0", note = "use read_to() method instead")] + fn read_to_bytes(&mut self) -> io::Result<[u8; SIZE]> { + self.read_to() + } + + /// Completely fills a vector of bytes and returns it. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03, 0x04]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// let mut buf = [0; 3]; + /// assert_eq!(r.read::<8, u8>().unwrap(), 0x00); + /// assert_eq!(r.read_to_vec(3).unwrap().as_slice(), &[0x01, 0x02, 0x03]); + /// assert_eq!(r.read::<8, u8>().unwrap(), 0x04); + /// ``` + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn read_to_vec(&mut self, bytes: usize) -> io::Result> { + read_to_vec(|buf| self.read_bytes(buf), bytes) + } + + /// Counts the number of bits in the stream until `STOP_BIT` + /// and returns the amount read. + /// `STOP_BIT` must be 0 or 1. + /// Because this field is variably-sized and may be large, + /// its output is always a `u32` type. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// May panic if the number of bits exceeds `u32`. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0_10_11111, 0b10_000000]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // read 1 bits until stop bit of 0, big-endian order + /// assert_eq!(r.read_unary::<0>().unwrap(), 0); + /// assert_eq!(r.read_unary::<0>().unwrap(), 1); + /// assert_eq!(r.read_unary::<0>().unwrap(), 6); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b1_01_00000, 0b01_000000]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// // read 0 bits until stop bit of 1, big-endian order + /// assert_eq!(r.read_unary::<1>().unwrap(), 0); + /// assert_eq!(r.read_unary::<1>().unwrap(), 1); + /// assert_eq!(r.read_unary::<1>().unwrap(), 6); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, LittleEndian}; + /// + /// let bytes: &[u8] = &[0b11111_01_0, 0b000000_01]; + /// let mut r = BitReader::endian(bytes, LittleEndian); + /// // read 1 bits until stop bit of 0, little-endian order + /// assert_eq!(r.read_unary::<0>().unwrap(), 0); + /// assert_eq!(r.read_unary::<0>().unwrap(), 1); + /// assert_eq!(r.read_unary::<0>().unwrap(), 6); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, LittleEndian}; + /// + /// let bytes: &[u8] = &[0b00000_10_1, 0b111111_10]; + /// let mut r = BitReader::endian(bytes, LittleEndian); + /// // read 0 bits until stop bit of 1, little-endian order + /// assert_eq!(r.read_unary::<1>().unwrap(), 0); + /// assert_eq!(r.read_unary::<1>().unwrap(), 1); + /// assert_eq!(r.read_unary::<1>().unwrap(), 6); + /// ``` + fn read_unary(&mut self) -> io::Result { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + // a simple implementation which works anywhere + let mut unary = 0; + while self.read::<1, u8>()? != STOP_BIT { + unary += 1; + } + Ok(unary) + } + + /// Reads to a checked value that is known to fit a given number of bits + /// + /// # Example + /// ``` + /// use bitstream_io::{ + /// BitRead, BitReader, BigEndian, Checked, CheckedUnsigned, CheckedSigned, + /// BitCount, SignedBitCount, BitWrite, BitWriter, + /// }; + /// + /// let data: &[u8] = &[0b1001_1111]; + /// let mut r = BitReader::endian(data, BigEndian); + /// + /// let bit_count = BitCount::<4>::new::<4>(); + /// let checked_u8 = r.read_checked::>(bit_count).unwrap(); + /// assert_eq!(checked_u8.into_value(), 0b1001); + /// + /// let bit_count = SignedBitCount::<4>::new::<4>(); + /// let checked_i8 = r.read_checked::>(bit_count).unwrap(); + /// assert_eq!(checked_i8.into_value(), -1); + /// + /// // note that checked values already know their bit count + /// // so none is required when writing them to a stream + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// w.write_checked(checked_u8).unwrap(); + /// w.write_checked(checked_i8).unwrap(); + /// assert_eq!(w.into_writer().as_slice(), data); + /// ``` + #[inline] + fn read_checked(&mut self, count: C::CountType) -> io::Result + where + C: CheckablePrimitive, + { + C::read(self, count) + } + + /// Parses and returns complex type + fn parse(&mut self) -> Result { + F::from_reader(self) + } + + /// Parses and returns complex type with context + fn parse_with<'a, F: FromBitStreamWith<'a>>( + &mut self, + context: &F::Context, + ) -> Result { + F::from_reader(self, context) + } + + /// Parses and returns complex type with owned context + fn parse_using(&mut self, context: F::Context) -> Result { + F::from_reader(self, context) + } + + /// Returns true if the stream is aligned at a whole byte. + /// + /// # Example + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data = [0]; + /// let mut reader = BitReader::endian(data.as_slice(), BigEndian); + /// assert_eq!(reader.byte_aligned(), true); + /// assert!(reader.skip(1).is_ok()); + /// assert_eq!(reader.byte_aligned(), false); + /// assert!(reader.skip(7).is_ok()); + /// assert_eq!(reader.byte_aligned(), true); + /// ``` + fn byte_aligned(&self) -> bool; + + /// Throws away all unread bit values until the next whole byte. + /// Does nothing if the stream is already aligned. + /// + /// # Example + /// ``` + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data: &[u8] = &[0x00, 0xFF]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// assert_eq!(reader.read::<4, u8>().unwrap(), 0); + /// reader.byte_align(); + /// assert_eq!(reader.read::<8, u8>().unwrap(), 0xFF); + /// ``` + fn byte_align(&mut self); + + /// Given a compiled Huffman tree, reads bits from the stream + /// until the next symbol is encountered. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian, define_huffman_tree, huffman::FromBits}; + /// + /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); + /// // 'a' is 0 + /// // 'b' is 1 -> 0 + /// // 'c' is 1 -> 1 -> 0 + /// // 'd' is 1 -> 1 -> 1 + /// + /// let data: &[u8] = &[0b0_10_110_11, 0b1_0000000]; + /// let mut r = BitReader::endian(data, BigEndian); + /// assert_eq!(r.read_huffman::().unwrap(), 'a'); + /// assert_eq!(r.read_huffman::().unwrap(), 'b'); + /// assert_eq!(r.read_huffman::().unwrap(), 'c'); + /// assert_eq!(r.read_huffman::().unwrap(), 'd'); + /// ``` + #[inline] + fn read_huffman(&mut self) -> io::Result + where + T: crate::huffman::FromBits, + { + T::from_bits(|| self.read_bit()) + } + + /// Reads a number using a variable using a variable width integer. + /// This optimises the case when the number is small. + /// + /// The integer is mapped to an unsigned value using zigzag encoding. + /// For an integer X: + /// - if X >= 0 -> 2X + /// - else -> -2X + 1 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the data read would overflow the size of the result + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0111_1100, 0b1100_0001]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_unsigned_vbr::<4, u32>().unwrap(), 7); + /// assert_eq!(r.read_unsigned_vbr::<4, u32>().unwrap(), 100); + /// ``` + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b1111_1111, 0b0011_1000, 0b1000_0100, 0b1000_1000, 0b1000_0000]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 255); // Tries to read <011><111><111> + /// assert!(r.read_unsigned_vbr::<4, u8>().is_err()); // Tries to read a value of <100><000><000> + /// assert!(r.read_unsigned_vbr::<4, u8>().is_err()); // Tries to read a value of <000><000><000><000> + /// ``` + fn read_unsigned_vbr(&mut self) -> io::Result { + const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) }; + let payload_bits = FIELD_SIZE - 1; + let mut value = U::ZERO; + let mut shift = 0u32; + loop { + let (data, continuation) = self.read_unsigned::().map(|item| { + ( + item & ((U::ONE << payload_bits) - U::ONE), + (item >> payload_bits) != U::ZERO, + ) + })?; + let shifted = data << shift; + value |= shifted; + if !continuation { + if (data << shift) >> shift == data { + break Ok(value); + } else { + break Err(VariableWidthOverflow {}.into()); + } + } + shift += payload_bits; + if shift >= U::BITS_SIZE { + break Err(VariableWidthOverflow {}.into()); + } + } + } + + /// Reads a number using a variable using a variable width integer. + /// This optimises the case when the number is small. + /// + /// The integer is mapped to an unsigned value using zigzag encoding. + /// For an integer X: + /// - if X >= 0 -> 2X + /// - else -> -2X + 1 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the data read would overflow the size of the result + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0110_1011, 0b1100_0001]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_signed_vbr::<4, i32>().unwrap(), 3); + /// assert_eq!(r.read_signed_vbr::<4, i32>().unwrap(), -50); + /// ``` + fn read_signed_vbr(&mut self) -> io::Result { + self.read_unsigned_vbr::() + .map(|zig_zag| { + let shifted = zig_zag >> 1; + let complimented = zig_zag & ::ONE; + let neg = I::ZERO - complimented.as_non_negative(); + shifted.as_non_negative() ^ neg + }) + } + + /// Reads a signed or unsigned variable width integer from the stream. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the data read would overflow the size of the result + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// let bytes: &[u8] = &[0b0110_1011, 0b1100_0001]; + /// let mut r = BitReader::endian(bytes, BigEndian); + /// assert_eq!(r.read_vbr::<4, u32>().unwrap(), 6); + /// assert_eq!(r.read_vbr::<4, i32>().unwrap(), -50); + /// ``` + #[inline] + fn read_vbr(&mut self) -> io::Result { + I::read_vbr::(self) + } + + /// Creates a "by reference" adaptor for this `BitRead` + /// + /// The returned adapter also implements `BitRead` + /// and will borrow the current reader. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitReader, BitRead, BigEndian}; + /// + /// fn parse(r: R) { + /// // perform some parsing + /// } + /// + /// let data: &[u8] = &[0]; + /// let mut reader = BitReader::endian(data, BigEndian); + /// // performing parsing by reference + /// parse(reader.by_ref()); + /// // original owned reader still available + /// assert_eq!(reader.read::<8, u8>().unwrap(), 0); + /// ``` + #[inline] + fn by_ref(&mut self) -> &mut Self { + self + } +} + +impl BitRead for &mut R { + #[inline] + fn read_bit(&mut self) -> io::Result { + (**self).read_bit() + } + + #[inline] + fn read(&mut self) -> io::Result + where + I: Integer, + { + (**self).read::() + } + + #[inline] + fn read_var(&mut self, bits: u32) -> io::Result + where + I: Integer + Sized, + { + (**self).read_var(bits) + } + + #[inline] + fn read_count(&mut self) -> io::Result> { + (**self).read_count::() + } + + #[inline] + fn read_counted(&mut self, bits: BitCount) -> io::Result + where + I: Integer + Sized, + { + (**self).read_counted::(bits) + } + + #[inline] + fn read_unsigned(&mut self) -> io::Result + where + U: UnsignedInteger, + { + (**self).read_unsigned::() + } + + #[inline] + fn read_unsigned_var(&mut self, bits: u32) -> io::Result + where + U: UnsignedInteger, + { + (**self).read_unsigned_var(bits) + } + + #[inline] + fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result + where + U: UnsignedInteger, + { + (**self).read_unsigned_counted::(bits) + } + + #[inline] + fn read_signed(&mut self) -> io::Result + where + S: SignedInteger, + { + (**self).read_signed::() + } + + #[inline] + fn read_signed_var(&mut self, bits: u32) -> io::Result + where + S: SignedInteger, + { + (**self).read_signed_var(bits) + } + + #[inline] + fn read_signed_counted( + &mut self, + bits: impl TryInto>, + ) -> io::Result + where + S: SignedInteger, + { + (**self).read_signed_counted::(bits) + } + + #[inline] + fn read_to(&mut self) -> io::Result + where + V: Primitive, + { + (**self).read_to::() + } + + #[inline] + fn read_as_to(&mut self) -> io::Result + where + F: Endianness, + V: Primitive, + { + (**self).read_as_to::() + } + + #[inline] + fn skip(&mut self, bits: u32) -> io::Result<()> { + (**self).skip(bits) + } + + #[inline] + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + (**self).read_bytes(buf) + } + + #[inline] + #[cfg(feature = "alloc")] + fn read_to_vec(&mut self, bytes: usize) -> io::Result> { + (**self).read_to_vec(bytes) + } + + #[inline] + fn read_unary(&mut self) -> io::Result { + (**self).read_unary::() + } + + #[inline] + fn parse(&mut self) -> Result { + (**self).parse::() + } + + #[inline] + fn parse_with<'a, F: FromBitStreamWith<'a>>( + &mut self, + context: &F::Context, + ) -> Result { + (**self).parse_with::(context) + } + + #[inline] + fn byte_aligned(&self) -> bool { + (**self).byte_aligned() + } + + #[inline] + fn byte_align(&mut self) { + (**self).byte_align() + } + + #[inline] + fn read_huffman(&mut self) -> io::Result + where + T: crate::huffman::FromBits, + { + (**self).read_huffman::() + } +} + +/// A compatibility trait for older code implementing [`BitRead`] +/// +/// This is a trait largely compatible with older code +/// from the 2.X.X version, +/// which one can use with a named import as needed. +/// +/// New code should prefer the regular [`BitRead`] trait. +/// +/// # Example +/// ``` +/// use bitstream_io::BitRead2 as BitRead; +/// use bitstream_io::{BitReader, BigEndian}; +/// let byte = &[0b1111_0000]; +/// let mut reader = BitReader::endian(byte.as_slice(), BigEndian); +/// assert_eq!(reader.read::(4).unwrap(), 0b1111); +/// assert_eq!(reader.read_in::<4, u8>().unwrap(), 0b0000); +/// ``` +pub trait BitRead2 { + /// Reads a single bit from the stream. + /// `true` indicates 1, `false` indicates 0 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_bit(&mut self) -> io::Result; + + /// Reads an unsigned value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + fn read(&mut self, bits: u32) -> io::Result + where + I: Integer + Sized; + + /// Reads an unsigned value from the stream with + /// the given constant number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + fn read_in(&mut self) -> io::Result + where + I: Integer, + { + self.read(BITS) + } + + /// Reads a twos-complement signed value from the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the number of bits is 0, + /// since one bit is always needed for the sign. + /// Also returns an error if the output type is too small + /// to hold the requested number of bits. + fn read_signed(&mut self, bits: u32) -> io::Result + where + S: SignedInteger; + + /// Reads a twos-complement signed value from the stream with + /// the given constant number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the number of bits is 0, + /// since one bit is always needed for the sign. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + fn read_signed_in(&mut self) -> io::Result + where + S: SignedInteger, + { + self.read_signed(BITS) + } + + /// Reads whole value from the stream whose size in bits is equal + /// to its type's size. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_to(&mut self) -> io::Result + where + V: Primitive; + + /// Reads whole value from the stream whose size in bits is equal + /// to its type's size in an endianness that may be different + /// from the stream's endianness. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_as_to(&mut self) -> io::Result + where + F: Endianness, + V: Primitive; + + /// Skips the given number of bits in the stream. + /// Since this method does not need an accumulator, + /// it may be slightly faster than reading to an empty variable. + /// In addition, since there is no accumulator, + /// there is no upper limit on the number of bits + /// which may be skipped. + /// These bits are still read from the stream, however, + /// and are never skipped via a `seek` method. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn skip(&mut self, bits: u32) -> io::Result<()>; + + /// Completely fills the given buffer with whole bytes. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + for b in buf.iter_mut() { + *b = self.read_in::<8, _>()?; + } + Ok(()) + } + + /// Completely fills a whole buffer with bytes and returns it. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[inline(always)] + #[deprecated(since = "1.8.0", note = "use read_to() method instead")] + fn read_to_bytes(&mut self) -> io::Result<[u8; SIZE]> { + self.read_to() + } + + /// Completely fills a vector of bytes and returns it. + /// If the stream is already byte-aligned, it will map + /// to a faster `read_exact` call. Otherwise it will read + /// bytes individually in 8-bit increments. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn read_to_vec(&mut self, bytes: usize) -> io::Result> { + read_to_vec(|buf| self.read_bytes(buf), bytes) + } + + /// Counts the number of 1 bits in the stream until the next + /// 0 bit and returns the amount read. + /// Because this field is variably-sized and may be large, + /// its output is always a `u32` type. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_unary0(&mut self) -> io::Result { + let mut unary = 0; + while self.read_bit()? { + unary += 1; + } + Ok(unary) + } + + /// Counts the number of 0 bits in the stream until the next + /// 1 bit and returns the amount read. + /// Because this field is variably-sized and may be large, + /// its output is always a `u32` type. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_unary1(&mut self) -> io::Result { + let mut unary = 0; + while !(self.read_bit()?) { + unary += 1; + } + Ok(unary) + } + + /// Parses and returns complex type + fn parse(&mut self) -> Result + where + Self: BitRead, + { + F::from_reader(self) + } + + /// Parses and returns complex type with context + fn parse_with<'a, F: FromBitStreamWith<'a>>( + &mut self, + context: &F::Context, + ) -> Result + where + Self: BitRead, + { + F::from_reader(self, context) + } + + /// Returns true if the stream is aligned at a whole byte. + fn byte_aligned(&self) -> bool; + + /// Throws away all unread bit values until the next whole byte. + /// Does nothing if the stream is already aligned. + fn byte_align(&mut self); + + /// Given a compiled Huffman tree, reads bits from the stream + /// until the next symbol is encountered. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[inline] + fn read_huffman(&mut self) -> io::Result + where + T: crate::huffman::FromBits, + { + T::from_bits(|| self.read_bit()) + } +} + +impl BitRead2 for R { + #[inline(always)] + fn read_bit(&mut self) -> io::Result { + BitRead::read_bit(self) + } + + #[inline(always)] + fn read(&mut self, bits: u32) -> io::Result + where + I: Integer + Sized, + { + self.read_var(bits) + } + + #[inline(always)] + fn read_in(&mut self) -> io::Result + where + I: Integer, + { + BitRead::read::(self) + } + + #[inline(always)] + fn read_signed(&mut self, bits: u32) -> io::Result + where + S: SignedInteger, + { + self.read_signed_var(bits) + } + + #[inline(always)] + fn read_signed_in(&mut self) -> io::Result + where + S: SignedInteger, + { + BitRead::read_signed::(self) + } + + #[inline(always)] + fn read_to(&mut self) -> io::Result + where + V: Primitive, + { + BitRead::read_to::(self) + } + + #[inline(always)] + fn read_as_to(&mut self) -> io::Result + where + F: Endianness, + V: Primitive, + { + BitRead::read_as_to::(self) + } + + #[inline(always)] + fn skip(&mut self, bits: u32) -> io::Result<()> { + BitRead::skip(self, bits) + } + + #[inline(always)] + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + BitRead::read_bytes(self, buf) + } + + #[inline(always)] + fn read_unary0(&mut self) -> io::Result { + self.read_unary::<0>() + } + + #[inline(always)] + fn read_unary1(&mut self) -> io::Result { + self.read_unary::<1>() + } + + #[inline(always)] + fn byte_aligned(&self) -> bool { + BitRead::byte_aligned(self) + } + + #[inline(always)] + fn byte_align(&mut self) { + BitRead::byte_align(self) + } +} + +/// For reading non-aligned bits from a stream of bytes in a given endianness. +/// +/// This will read exactly as many whole bytes needed to return +/// the requested number of bits. It may cache up to a single partial byte +/// but no more. +#[derive(Clone, Debug)] +pub struct BitReader { + // our underlying reader + reader: R, + // our partial byte + value: u8, + // the number of bits in our partial byte + bits: u32, + // a container for our endiannness + phantom: PhantomData, +} + +impl BitReader { + /// Wraps a BitReader around something that implements `Read` + pub fn new(reader: R) -> BitReader { + BitReader { + reader, + value: 0, + bits: 0, + phantom: PhantomData, + } + } + + /// Wraps a BitReader around something that implements `Read` + /// with the given endianness. + pub fn endian(reader: R, _endian: E) -> BitReader { + BitReader { + reader, + value: 0, + bits: 0, + phantom: PhantomData, + } + } + + /// Unwraps internal reader and disposes of BitReader. + /// + /// # Warning + /// + /// Any unread partial bits are discarded. + #[inline] + pub fn into_reader(self) -> R { + self.reader + } +} + +impl BitReader { + /// If stream is byte-aligned, provides mutable reference + /// to internal reader. Otherwise returns `None` + #[inline] + pub fn reader(&mut self) -> Option<&mut R> { + if BitRead::byte_aligned(self) { + Some(&mut self.reader) + } else { + None + } + } + + /// Returns byte-aligned mutable reference to internal reader. + /// + /// Bytes aligns stream if it is not already aligned. + #[inline] + pub fn aligned_reader(&mut self) -> &mut R { + BitRead::byte_align(self); + &mut self.reader + } + + /// Converts `BitReader` to `ByteReader` in the same endianness. + /// + /// # Warning + /// + /// Any unread partial bits are discarded. + #[inline] + pub fn into_bytereader(self) -> ByteReader { + ByteReader::new(self.into_reader()) + } + + /// If stream is byte-aligned, provides temporary `ByteReader` + /// in the same endianness. Otherwise returns `None` + /// + /// # Warning + /// + /// Any reader bits left over when `ByteReader` is dropped are lost. + #[inline] + pub fn bytereader(&mut self) -> Option> { + self.reader().map(ByteReader::new) + } +} + +impl BitRead for BitReader { + #[inline(always)] + fn read_bit(&mut self) -> io::Result { + let Self { + value, + bits, + reader, + .. + } = self; + E::pop_bit_refill(reader, value, bits) + } + + #[inline(always)] + fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result + where + U: UnsignedInteger, + { + let Self { + value: queue_value, + bits: queue_bits, + reader, + .. + } = self; + E::read_bits(reader, queue_value, queue_bits, bits) + } + + #[inline] + fn read_unsigned(&mut self) -> io::Result + where + U: UnsignedInteger, + { + let Self { + value, + bits, + reader, + .. + } = self; + E::read_bits_fixed::(reader, value, bits) + } + + #[inline(always)] + fn read_signed_counted( + &mut self, + bits: impl TryInto>, + ) -> io::Result + where + S: SignedInteger, + { + E::read_signed_counted( + self, + bits.try_into().map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "signed reads need at least 1 bit for sign", + ) + })?, + ) + } + + #[inline] + fn read_signed(&mut self) -> io::Result + where + S: SignedInteger, + { + let count = const { + assert!(BITS <= S::BITS_SIZE, "excessive bits for type read"); + let count = BitCount::::new::().signed_count(); + assert!(count.is_some(), "signed reads need at least 1 bit for sign"); + count.unwrap() + }; + + E::read_signed_counted(self, count) + } + + #[inline] + fn read_to(&mut self) -> io::Result + where + V: Primitive, + { + let mut buffer = V::buffer(); + E::read_bytes::<8, _>( + &mut self.reader, + &mut self.value, + self.bits, + buffer.as_mut(), + )?; + Ok(E::bytes_to_primitive(buffer)) + } + + #[inline] + fn read_as_to(&mut self) -> io::Result + where + F: Endianness, + V: Primitive, + { + let mut buffer = V::buffer(); + F::read_bytes::<8, _>( + &mut self.reader, + &mut self.value, + self.bits, + buffer.as_mut(), + )?; + Ok(F::bytes_to_primitive(buffer)) + } + + /// # Examples + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data = [0b10110111]; + /// let mut reader = BitReader::endian(data.as_slice(), BigEndian); + /// assert!(reader.skip(3).is_ok()); + /// assert_eq!(reader.read::<5, u8>().unwrap(), 0b10111); + /// ``` + /// + /// ``` + /// use std::io::Read; + /// use bitstream_io::{LittleEndian, BitReader, BitRead}; + /// let data = [0b10110111]; + /// let mut reader = BitReader::endian(data.as_slice(), LittleEndian); + /// assert!(reader.skip(3).is_ok()); + /// assert_eq!(reader.read::<5, u8>().unwrap(), 0b10110); + /// ``` + fn skip(&mut self, mut bits: u32) -> io::Result<()> { + if BitRead::byte_aligned(self) && bits % 8 == 0 { + skip_aligned(self.reader.by_ref(), bits / 8) + } else { + loop { + match bits { + 0 => break Ok(()), + bits @ 1..64 => break self.read_var(bits).map(|_: u64| ()), + _ => { + let _ = BitRead::read::<64, u64>(self)?; + bits -= 64; + } + } + } + } + } + + /// # Example + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data = b"foobar"; + /// let mut reader = BitReader::endian(data.as_slice(), BigEndian); + /// assert!(reader.skip(24).is_ok()); + /// let mut buf = [0;3]; + /// assert!(reader.read_bytes(&mut buf).is_ok()); + /// assert_eq!(&buf, b"bar"); + /// ``` + #[inline] + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + E::read_bytes::<1024, _>(&mut self.reader, &mut self.value, self.bits, buf) + } + + fn read_unary(&mut self) -> io::Result { + let Self { + value, + bits, + reader, + .. + } = self; + E::pop_unary::(reader, value, bits) + } + + #[inline] + fn byte_aligned(&self) -> bool { + self.bits == 0 + } + + #[inline] + fn byte_align(&mut self) { + self.value = 0; + self.bits = 0; + } +} + +impl BitReader +where + E: Endianness, + R: io::Read + io::Seek, +{ + /// # Example + /// ``` + /// use std::io::{Read, Cursor, SeekFrom}; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data = [0x00, 0xFF]; + /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); + /// assert_eq!(reader.position_in_bits().unwrap(), 0); + /// + /// let pos = reader.seek_bits(SeekFrom::Start(5)).unwrap(); + /// assert!(pos == 5 && 5 == reader.position_in_bits().unwrap()); + /// + /// let pos = reader.seek_bits(SeekFrom::Current(-2)).unwrap(); + /// assert!(pos == 3 && 3 == reader.position_in_bits().unwrap()); + /// + /// let pos = reader.seek_bits(SeekFrom::End(5)).unwrap(); + /// assert!(pos == 11 && 11 == reader.position_in_bits().unwrap()); + /// ``` + pub fn seek_bits(&mut self, from: io::SeekFrom) -> io::Result { + match from { + io::SeekFrom::Start(from_start_pos) => { + let (bytes, bits) = (from_start_pos / 8, (from_start_pos % 8) as u32); + BitRead::byte_align(self); + self.reader.seek(io::SeekFrom::Start(bytes))?; + BitRead::skip(self, bits)?; + Ok(from_start_pos) + } + io::SeekFrom::End(from_end_pos) => { + let reader_end = self.reader.seek(io::SeekFrom::End(0))?; + let new_pos = (reader_end * 8) as i64 - from_end_pos; + assert!(new_pos >= 0, "The final position should be greater than 0"); + self.seek_bits(io::SeekFrom::Start(new_pos as u64)) + } + io::SeekFrom::Current(offset) => { + let new_pos = self.position_in_bits()? as i64 + offset; + assert!(new_pos >= 0, "The final position should be greater than 0"); + self.seek_bits(io::SeekFrom::Start(new_pos as u64)) + } + } + } + + /// # Example + /// ``` + /// use std::fs::read; + /// use std::io::{Read, Cursor, SeekFrom}; + /// use bitstream_io::{BigEndian, BitReader, BitRead}; + /// let data = [0x00, 0xFF]; + /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); + /// assert_eq!(reader.position_in_bits().unwrap(), 0); + /// + /// let _: i32 = reader.read_signed::<5, _>().unwrap(); + /// assert_eq!(reader.position_in_bits().unwrap(), 5); + /// + /// reader.read_bit().unwrap(); + /// assert_eq!(reader.position_in_bits().unwrap(), 6); + /// ``` + #[inline] + #[allow(clippy::seek_from_current)] + pub fn position_in_bits(&mut self) -> io::Result { + // core2 doesn't have `seek_from_current` + let bytes = self.reader.seek(io::SeekFrom::Current(0))?; + Ok(bytes * 8 - (self.bits as u64)) + } +} + +fn skip_aligned(reader: R, bytes: u32) -> io::Result<()> +where + R: io::Read, +{ + fn skip_chunks(mut reader: R, mut bytes: usize) -> io::Result<()> + where + R: io::Read, + { + let mut buf = [0; SIZE]; + while bytes > 0 { + let to_read = bytes.min(SIZE); + reader.read_exact(&mut buf[0..to_read])?; + bytes -= to_read; + } + Ok(()) + } + + match bytes { + 0..256 => skip_chunks::<8, R>(reader, bytes as usize), + 256..1024 => skip_chunks::<256, R>(reader, bytes as usize), + 1024..4096 => skip_chunks::<1024, R>(reader, bytes as usize), + _ => skip_chunks::<4096, R>(reader, bytes as usize), + } +} + +/// A trait for anything that can read aligned values from an input stream +pub trait ByteRead { + /// Reads whole numeric value from stream + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, ByteReader, ByteRead}; + /// let data = [0b00000000, 0b11111111]; + /// let mut reader = ByteReader::endian(data.as_slice(), BigEndian); + /// assert_eq!(reader.read::().unwrap(), 0b0000000011111111); + /// ``` + /// + /// ``` + /// use std::io::Read; + /// use bitstream_io::{LittleEndian, ByteReader, ByteRead}; + /// let data = [0b00000000, 0b11111111]; + /// let mut reader = ByteReader::endian(data.as_slice(), LittleEndian); + /// assert_eq!(reader.read::().unwrap(), 0b1111111100000000); + /// ``` + fn read(&mut self) -> Result + where + V: Primitive; + + /// Reads whole numeric value from stream in a potentially different endianness + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; + /// let data = [0b00000000, 0b11111111]; + /// let mut reader = ByteReader::endian(data.as_slice(), BigEndian); + /// assert_eq!(reader.read_as::().unwrap(), 0b1111111100000000); + /// ``` + /// + /// ``` + /// use std::io::Read; + /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; + /// let data = [0b00000000, 0b11111111]; + /// let mut reader = ByteReader::endian(data.as_slice(), LittleEndian); + /// assert_eq!(reader.read_as::().unwrap(), 0b0000000011111111); + /// ``` + fn read_as(&mut self) -> Result + where + F: Endianness, + V: Primitive; + + /// Completely fills the given buffer with whole bytes. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + for b in buf.iter_mut() { + *b = self.read()?; + } + Ok(()) + } + + /// Completely fills a whole buffer with bytes and returns it. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[inline(always)] + #[deprecated(since = "1.8.0", note = "use read() method instead")] + fn read_to_bytes(&mut self) -> io::Result<[u8; SIZE]> { + self.read() + } + + /// Completely fills a vector of bytes and returns it. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn read_to_vec(&mut self, bytes: usize) -> io::Result> { + read_to_vec(|buf| self.read_bytes(buf), bytes) + } + + /// Skips the given number of bytes in the stream. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn skip(&mut self, bytes: u32) -> io::Result<()>; + + /// Parses and returns complex type + fn parse(&mut self) -> Result { + F::from_reader(self) + } + + /// Parses and returns complex type with context + fn parse_with<'a, F: FromByteStreamWith<'a>>( + &mut self, + context: &F::Context, + ) -> Result { + F::from_reader(self, context) + } + + /// Parses and returns complex type with owned context + fn parse_using(&mut self, context: F::Context) -> Result { + F::from_reader(self, context) + } + + /// Returns mutable reference to underlying reader + fn reader_ref(&mut self) -> &mut dyn io::Read; +} + +/// For reading aligned bytes from a stream of bytes in a given endianness. +/// +/// This only reads aligned values and maintains no internal state. +#[derive(Debug)] +pub struct ByteReader { + phantom: PhantomData, + reader: R, +} + +impl ByteReader { + /// Wraps a ByteReader around something that implements `Read` + pub fn new(reader: R) -> ByteReader { + ByteReader { + phantom: PhantomData, + reader, + } + } + + /// Wraps a ByteReader around something that implements `Read` + /// with the given endianness. + pub fn endian(reader: R, _endian: E) -> ByteReader { + ByteReader { + phantom: PhantomData, + reader, + } + } + + /// Unwraps internal reader and disposes of `ByteReader`. + #[inline] + pub fn into_reader(self) -> R { + self.reader + } + + /// Provides mutable reference to internal reader + #[inline] + pub fn reader(&mut self) -> &mut R { + &mut self.reader + } + + /// Converts `ByteReader` to `BitReader` in the same endianness. + #[inline] + pub fn into_bitreader(self) -> BitReader { + BitReader::new(self.into_reader()) + } + + /// Provides temporary `BitReader` in the same endianness. + /// + /// # Warning + /// + /// Any unread bits left over when `BitReader` is dropped are lost. + #[inline] + pub fn bitreader(&mut self) -> BitReader<&mut R, E> { + BitReader::new(self.reader()) + } +} + +impl ByteRead for ByteReader { + #[inline] + fn read(&mut self) -> Result + where + V: Primitive, + { + let mut buf = V::buffer(); + self.read_bytes(buf.as_mut())?; + Ok(E::bytes_to_primitive(buf)) + } + + #[inline] + fn read_as(&mut self) -> Result + where + F: Endianness, + V: Primitive, + { + let mut buf = V::buffer(); + self.read_bytes(buf.as_mut())?; + Ok(F::bytes_to_primitive(buf)) + } + + #[inline] + fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.reader.read_exact(buf) + } + + #[inline] + fn skip(&mut self, bytes: u32) -> io::Result<()> { + skip_aligned(&mut self.reader, bytes) + } + + #[inline] + fn reader_ref(&mut self) -> &mut dyn io::Read { + &mut self.reader + } +} + +impl io::Seek for ByteReader { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + self.reader().seek(pos) + } +} + +/// Implemented by complex types that don't require any additional context +/// to parse themselves from a reader. Analogous to [`std::str::FromStr`]. +/// +/// # Example +/// ``` +/// use std::io::Read; +/// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStream}; +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct BlockHeader { +/// last_block: bool, +/// block_type: u8, +/// block_size: u32, +/// } +/// +/// impl FromBitStream for BlockHeader { +/// type Error = std::io::Error; +/// +/// fn from_reader(r: &mut R) -> std::io::Result { +/// Ok(Self { +/// last_block: r.read_bit()?, +/// block_type: r.read::<7, _>()?, +/// block_size: r.read::<24, _>()?, +/// }) +/// } +/// } +/// +/// let mut reader = BitReader::endian(b"\x04\x00\x00\x7A".as_slice(), BigEndian); +/// assert_eq!( +/// reader.parse::().unwrap(), +/// BlockHeader { last_block: false, block_type: 4, block_size: 122 } +/// ); +/// ``` +pub trait FromBitStream { + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader + fn from_reader(r: &mut R) -> Result + where + Self: Sized; +} + +/// Implemented by complex types that require some immutable context +/// to parse themselves from a reader. +/// +/// # Example +/// ``` +/// use std::io::Read; +/// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStreamWith}; +/// +/// #[derive(Default)] +/// struct Streaminfo { +/// minimum_block_size: u16, +/// maximum_block_size: u16, +/// minimum_frame_size: u32, +/// maximum_frame_size: u32, +/// sample_rate: u32, +/// channels: u8, +/// bits_per_sample: u8, +/// total_samples: u64, +/// md5: [u8; 16], +/// } +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct FrameHeader { +/// variable_block_size: bool, +/// block_size: u32, +/// sample_rate: u32, +/// channel_assignment: u8, +/// sample_size: u8, +/// frame_number: u64, +/// crc8: u8, +/// } +/// +/// impl FromBitStreamWith<'_> for FrameHeader { +/// type Context = Streaminfo; +/// +/// type Error = FrameHeaderError; +/// +/// fn from_reader( +/// r: &mut R, +/// streaminfo: &Streaminfo, +/// ) -> Result { +/// if r.read::<14, u16>()? != 0b11111111111110 { +/// return Err(FrameHeaderError::InvalidSync); +/// } +/// +/// if r.read_bit()? != false { +/// return Err(FrameHeaderError::InvalidReservedBit); +/// } +/// +/// let variable_block_size = r.read_bit()?; +/// +/// let block_size_bits = r.read::<4, u8>()?; +/// +/// let sample_rate_bits = r.read::<4, u8>()?; +/// +/// let channel_assignment = r.read::<4, u8>()?; +/// +/// let sample_size = match r.read::<3, u8>()? { +/// 0b000 => streaminfo.bits_per_sample, +/// 0b001 => 8, +/// 0b010 => 12, +/// 0b011 => return Err(FrameHeaderError::InvalidSampleSize), +/// 0b100 => 16, +/// 0b101 => 20, +/// 0b110 => 24, +/// 0b111 => 32, +/// _ => unreachable!(), +/// }; +/// +/// if r.read_bit()? != false { +/// return Err(FrameHeaderError::InvalidReservedBit); +/// } +/// +/// let frame_number = read_utf8(r)?; +/// +/// Ok(FrameHeader { +/// variable_block_size, +/// block_size: match block_size_bits { +/// 0b0000 => return Err(FrameHeaderError::InvalidBlockSize), +/// 0b0001 => 192, +/// n @ 0b010..=0b0101 => 576 * (1 << (n - 2)), +/// 0b0110 => r.read::<8, u32>()? + 1, +/// 0b0111 => r.read::<16, u32>()? + 1, +/// n @ 0b1000..=0b1111 => 256 * (1 << (n - 8)), +/// _ => unreachable!(), +/// }, +/// sample_rate: match sample_rate_bits { +/// 0b0000 => streaminfo.sample_rate, +/// 0b0001 => 88200, +/// 0b0010 => 176400, +/// 0b0011 => 192000, +/// 0b0100 => 8000, +/// 0b0101 => 16000, +/// 0b0110 => 22050, +/// 0b0111 => 24000, +/// 0b1000 => 32000, +/// 0b1001 => 44100, +/// 0b1010 => 48000, +/// 0b1011 => 96000, +/// 0b1100 => r.read::<8, u32>()? * 1000, +/// 0b1101 => r.read::<16, u32>()?, +/// 0b1110 => r.read::<16, u32>()? * 10, +/// 0b1111 => return Err(FrameHeaderError::InvalidSampleRate), +/// _ => unreachable!(), +/// }, +/// channel_assignment, +/// sample_size, +/// frame_number, +/// crc8: r.read::<8, _>()? +/// }) +/// } +/// } +/// +/// #[derive(Debug)] +/// enum FrameHeaderError { +/// Io(std::io::Error), +/// InvalidSync, +/// InvalidReservedBit, +/// InvalidSampleSize, +/// InvalidBlockSize, +/// InvalidSampleRate, +/// } +/// +/// impl From for FrameHeaderError { +/// fn from(err: std::io::Error) -> Self { +/// Self::Io(err) +/// } +/// } +/// +/// fn read_utf8(r: &mut R) -> Result { +/// r.read::<8, _>() // left unimplimented in this example +/// } +/// +/// let mut reader = BitReader::endian(b"\xFF\xF8\xC9\x18\x00\xC2".as_slice(), BigEndian); +/// assert_eq!( +/// reader.parse_with::(&Streaminfo::default()).unwrap(), +/// FrameHeader { +/// variable_block_size: false, +/// block_size: 4096, +/// sample_rate: 44100, +/// channel_assignment: 1, +/// sample_size: 16, +/// frame_number: 0, +/// crc8: 0xC2, +/// } +/// ); +/// ``` +/// +/// # Example with lifetime-contrained `Context` +/// +/// In some cases, the `Context` can depend on a reference to another `struct`. +/// +/// ``` +/// use std::io::Read; +/// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStreamWith}; +/// +/// #[derive(Default)] +/// struct ModeParameters { +/// size_len: u8, +/// index_len: u8, +/// index_delta_len: u8, +/// // ... +/// } +/// +/// struct AuHeaderParseContext<'a> { +/// params: &'a ModeParameters, +/// base_index: Option, +/// } +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct AuHeader { +/// size: u32, +/// index: u32, +/// // ... +/// } +/// +/// impl<'a> FromBitStreamWith<'a> for AuHeader { +/// type Context = AuHeaderParseContext<'a>; +/// +/// type Error = AuHeaderError; +/// +/// fn from_reader( +/// r: &mut R, +/// ctx: &AuHeaderParseContext<'a>, +/// ) -> Result { +/// let size = r.read_var::(ctx.params.size_len as u32)?; +/// let index = match ctx.base_index { +/// None => r.read_var::(ctx.params.index_len as u32)?, +/// Some(base_index) => { +/// base_index +/// + 1 +/// + r.read_var::(ctx.params.index_delta_len as u32)? +/// } +/// }; +/// +/// Ok(AuHeader { +/// size, +/// index, +/// // ... +/// }) +/// } +/// } +/// +/// #[derive(Debug)] +/// enum AuHeaderError { +/// Io(std::io::Error), +/// } +/// +/// impl From for AuHeaderError { +/// fn from(err: std::io::Error) -> Self { +/// Self::Io(err) +/// } +/// } +/// +/// let mut reader = BitReader::endian(b"\xFF\xEA\xFF\x10".as_slice(), BigEndian); +/// +/// let mode_params = ModeParameters { +/// size_len: 10, +/// index_len: 6, +/// index_delta_len: 2, +/// // ... +/// }; +/// +/// let mut ctx = AuHeaderParseContext { +/// params: &mode_params, +/// base_index: None, +/// }; +/// +/// let header1 = reader.parse_with::(&ctx).unwrap(); +/// assert_eq!( +/// header1, +/// AuHeader { +/// size: 1023, +/// index: 42, +/// } +/// ); +/// +/// ctx.base_index = Some(header1.index); +/// +/// assert_eq!( +/// reader.parse_with::(&ctx).unwrap(), +/// AuHeader { +/// size: 1020, +/// index: 44, +/// } +/// ); +/// ``` +pub trait FromBitStreamWith<'a> { + /// Some context to use when parsing + type Context: 'a; + + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader with the given context + fn from_reader( + r: &mut R, + context: &Self::Context, + ) -> Result + where + Self: Sized; +} + +/// Implemented by complex types that consume some immutable context +/// to parse themselves from a reader. +/// +/// Like [`FromBitStreamWith`], but consumes its context +/// rather than taking a shared reference to it. +pub trait FromBitStreamUsing { + /// Some context to consume when parsing + type Context; + + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader with the given context + fn from_reader( + r: &mut R, + context: Self::Context, + ) -> Result + where + Self: Sized; +} + +/// Implemented by complex types that don't require any additional context +/// to parse themselves from a reader. Analagous to `FromStr`. +pub trait FromByteStream { + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader + fn from_reader(r: &mut R) -> Result + where + Self: Sized; +} + +/// Implemented by complex types that require some additional context +/// to parse themselves from a reader. Analagous to `FromStr`. +pub trait FromByteStreamWith<'a> { + /// Some context to use when parsing + type Context: 'a; + + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader + fn from_reader( + r: &mut R, + context: &Self::Context, + ) -> Result + where + Self: Sized; +} + +/// Implemented by complex types that consume some additional context +/// to parse themselves from a reader. +/// +/// Like [`FromByteStreamWith`], but consumes the context. +pub trait FromByteStreamUsing { + /// Some context to use when parsing + type Context; + + /// Error generated during parsing, such as `io::Error` + type Error; + + /// Parse Self from reader + fn from_reader( + r: &mut R, + context: Self::Context, + ) -> Result + where + Self: Sized; +} + +#[cfg(feature = "alloc")] +fn read_to_vec( + mut read: impl FnMut(&mut [u8]) -> io::Result<()>, + bytes: usize, +) -> io::Result> { + const MAX_CHUNK: usize = 4096; + + match bytes { + 0 => Ok(Vec::new()), + bytes if bytes <= MAX_CHUNK => { + let mut buf = vec![0; bytes]; + read(&mut buf)?; + Ok(buf) + } + mut bytes => { + let mut whole = Vec::with_capacity(MAX_CHUNK); + let mut chunk: [u8; MAX_CHUNK] = [0; MAX_CHUNK]; + while bytes > 0 { + let chunk_size = bytes.min(MAX_CHUNK); + let chunk = &mut chunk[0..chunk_size]; + read(chunk)?; + whole.extend_from_slice(chunk); + bytes -= chunk_size; + } + Ok(whole) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/write.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/src/write.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/src/write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3033 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits and implementations for writing bits to a stream. + +#![warn(missing_docs)] + +#[cfg(not(feature = "std"))] +use core2::io; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::{ + convert::{From, TryFrom, TryInto}, + fmt, +}; +#[cfg(feature = "std")] +use std::io; + +use super::{ + BitCount, Checkable, CheckedSigned, CheckedUnsigned, Endianness, Integer, Numeric, PhantomData, + Primitive, SignedBitCount, SignedInteger, UnsignedInteger, VBRInteger, +}; + +#[cfg(feature = "alloc")] +pub use bit_recorder::BitRecorder; + +/// For writing bit values to an underlying stream in a given endianness. +/// +/// Because this only writes whole bytes to the underlying stream, +/// it is important that output is byte-aligned before the bitstream +/// writer's lifetime ends. +/// **Partial bytes will be lost** if the writer is disposed of +/// before they can be written. +pub struct BitWriter { + // our underlying writer + writer: W, + // our partial byte + value: u8, + // the number of bits in our partial byte + bits: u32, + // a container for our endianness + phantom: PhantomData, +} + +impl BitWriter { + /// Wraps a BitWriter around something that implements `Write` + pub fn new(writer: W) -> BitWriter { + BitWriter { + writer, + value: 0, + bits: 0, + phantom: PhantomData, + } + } + + /// Wraps a BitWriter around something that implements `Write` + /// with the given endianness. + pub fn endian(writer: W, _endian: E) -> BitWriter { + BitWriter { + writer, + value: 0, + bits: 0, + phantom: PhantomData, + } + } + + /// Unwraps internal writer and disposes of BitWriter. + /// + /// # Warning + /// + /// Any unwritten partial bits are discarded. + #[inline] + pub fn into_writer(self) -> W { + self.writer + } + + /// If stream is byte-aligned, provides mutable reference + /// to internal writer. Otherwise returns `None` + #[inline] + pub fn writer(&mut self) -> Option<&mut W> { + if BitWrite::byte_aligned(self) { + Some(&mut self.writer) + } else { + None + } + } + + /// Returns byte-aligned mutable reference to internal writer. + /// + /// Bytes aligns stream if it is not already aligned. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + #[inline] + pub fn aligned_writer(&mut self) -> io::Result<&mut W> { + BitWrite::byte_align(self)?; + Ok(&mut self.writer) + } + + /// Converts `BitWriter` to `ByteWriter` in the same endianness. + /// + /// # Warning + /// + /// Any written partial bits are discarded. + #[inline] + pub fn into_bytewriter(self) -> ByteWriter { + ByteWriter::new(self.into_writer()) + } + + /// If stream is byte-aligned, provides temporary `ByteWriter` + /// in the same endianness. Otherwise returns `None` + /// + /// # Warning + /// + /// Any unwritten bits left over when `ByteWriter` is dropped are lost. + #[inline] + pub fn bytewriter(&mut self) -> Option> { + self.writer().map(ByteWriter::new) + } + + /// Flushes output stream to disk, if necessary. + /// Any partial bytes are not flushed. + /// + /// # Errors + /// + /// Passes along any errors from the underlying stream. + #[inline(always)] + pub fn flush(&mut self) -> io::Result<()> { + self.writer.flush() + } +} + +/// A trait for anything that can write a variable number of +/// potentially un-aligned values to an output stream +pub trait BitWrite { + /// Writes a single bit to the stream. + /// `true` indicates 1, `false` indicates 0 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert_eq!(w.into_writer(), &[0b1000_1110]); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, LittleEndian}; + /// + /// let mut w = BitWriter::endian(vec![], LittleEndian); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(false).is_ok()); + /// assert!(w.write_bit(true).is_ok()); + /// assert_eq!(w.into_writer(), &[0b1000_1110]); + /// ``` + #[inline] + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + self.write_unsigned::<1, u8>(u8::from(bit)) + } + + /// Writes a signed or unsigned value to the stream using the given + /// const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing unsigned value is ok + /// assert!(w.write::<4, u8>(1).is_ok()); + /// // writing signed value is ok + /// assert!(w.write::<4, i8>(-1).is_ok()); + /// // writing an array of bits is ok too + /// assert!(w.write::<1, [bool; 4]>([true, false, true, true]).is_ok()); + /// // writing an array of any Integer type is ok + /// assert!(w.write::<2, [u8; 2]>([0b11, 0b00]).is_ok()); + /// // trying to write a value larger than 4 bits in 4 bits is an error + /// assert!(w.write::<4, u8>(u8::MAX).is_err()); + /// + /// assert_eq!(w.into_writer(), &[0b0001_1111, 0b1011_11_00]); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // trying to write 9 bits from a u8 is a compile-time error + /// w.write::<9, u8>(1); + /// ``` + #[inline] + fn write(&mut self, value: I) -> io::Result<()> + where + I: Integer, + { + Integer::write::(value, self) + } + + /// Writes a signed or unsigned value to the stream using the given + /// number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing unsigned value is ok + /// assert!(w.write_var::(4, 1).is_ok()); + /// // writing signed value is also ok + /// assert!(w.write_var::(4, -1).is_ok()); + /// assert_eq!(w.into_writer(), &[0b0001_1111]); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing a value larger than 4 bits in 4 bits is a runtime error + /// assert!(w.write_var::(4, u8::MAX).is_err()); + /// // writing 9 bits from a u8 is also a runtime error + /// assert!(w.write_var::(9, 0).is_err()); + /// ``` + #[inline] + fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> + where + I: Integer, + { + self.write_counted(BitCount::unknown(bits), value) + } + + /// Writes an unsigned value to the stream using the given + /// const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// writer.write_unsigned::<1, u8>(0b1).unwrap(); + /// writer.write_unsigned::<2, u8>(0b01).unwrap(); + /// writer.write_unsigned::<5, u8>(0b10111).unwrap(); + /// assert_eq!(writer.into_writer(), [0b1_01_10111]); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// writer.write_unsigned::<1, u8>(0b1).unwrap(); + /// writer.write_unsigned::<2, u8>(0b11).unwrap(); + /// writer.write_unsigned::<5, u8>(0b10110).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110_11_1]); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// // trying to write 9 bits from a u8 is a compile-time error + /// writer.write_unsigned::<9, u8>(1); + /// ``` + /// + /// ``` + /// use std::io::{Write, sink}; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut w = BitWriter::endian(sink(), BigEndian); + /// assert!(w.write_unsigned::<1, u8>(2).is_err()); // can't write 2 in 1 bit + /// assert!(w.write_unsigned::<2, u8>(4).is_err()); // can't write 4 in 2 bits + /// assert!(w.write_unsigned::<3, u8>(8).is_err()); // can't write 8 in 3 bits + /// assert!(w.write_unsigned::<4, u8>(16).is_err()); // can't write 16 in 4 bits + /// ``` + #[inline] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + self.write_unsigned_var(BITS, value) + } + + /// Writes an unsigned value to the stream using the given + /// number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// writer.write_unsigned_var::(1, 0b1).unwrap(); + /// writer.write_unsigned_var::(2, 0b01).unwrap(); + /// writer.write_unsigned_var::(5, 0b10111).unwrap(); + /// assert_eq!(writer.into_writer(), [0b1_01_10111]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// writer.write_unsigned_var::(1, 0b1).unwrap(); + /// writer.write_unsigned_var::(2, 0b11).unwrap(); + /// writer.write_unsigned_var::(5, 0b10110).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110_11_1]); + /// ``` + /// + /// ``` + /// use std::io::{Write, sink}; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut w = BitWriter::endian(sink(), BigEndian); + /// assert!(w.write_unsigned_var::(9, 0).is_err()); // can't write u8 in 9 bits + /// assert!(w.write_unsigned_var::(17, 0).is_err()); // can't write u16 in 17 bits + /// assert!(w.write_unsigned_var::(33, 0).is_err()); // can't write u32 in 33 bits + /// assert!(w.write_unsigned_var::(65, 0).is_err()); // can't write u64 in 65 bits + /// assert!(w.write_unsigned_var::(1, 2).is_err()); // can't write 2 in 1 bit + /// assert!(w.write_unsigned_var::(2, 4).is_err()); // can't write 4 in 2 bits + /// assert!(w.write_unsigned_var::(3, 8).is_err()); // can't write 8 in 3 bits + /// assert!(w.write_unsigned_var::(4, 16).is_err()); // can't write 16 in 4 bits + /// ``` + fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + self.write_unsigned_counted(BitCount::unknown(bits), value) + } + + /// Writes a twos-complement signed value to the stream + /// with the given const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the number of bits is 0, + /// since one bit is always needed for the sign. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// writer.write_signed::<4, i8>(-5).unwrap(); + /// writer.write_signed::<4, i8>(7).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110111]); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// writer.write_signed::<4, i8>(7).unwrap(); + /// writer.write_signed::<4, i8>(-5).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110111]); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// // writing a value too large for 4 bits in 4 bits is a runtime error + /// assert!(writer.write_signed::<4, i8>(i8::MAX).is_err()); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// // writing 9 bits from an i8 is a compile-time error + /// assert!(writer.write_signed::<9, i8>(1).is_err()); + /// ``` + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + self.write_signed_var(BITS, value) + } + + /// Writes a twos-complement signed value to the stream + /// with the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the number of bits is 0, + /// since one bit is always needed for the sign. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// writer.write_signed_var(4, -5).unwrap(); + /// writer.write_signed_var(4, 7).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110111]); + /// ``` + /// + /// ``` + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// + /// let mut writer = BitWriter::endian(vec![], LittleEndian); + /// writer.write_signed_var(4, 7).unwrap(); + /// writer.write_signed_var(4, -5).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10110111]); + /// ``` + #[inline(always)] + fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> + where + S: SignedInteger, + { + self.write_signed_counted(BitCount::unknown(bits), value) + } + + /// Writes the given bit count to the stream + /// with the necessary maximum number of bits. + /// + /// For example, if the maximum bit count is 15 - or `0b1111` - + /// writes the bit count to the stream as a 4-bit unsigned value + /// which can be used in subsequent writes. + /// + /// Note that `MAX` must be greater than 0. + /// Unlike the bit reader, the bit count need not be an exact + /// power of two when writing. Any bits higher than the + /// bit count can reach are simply left 0. + /// + /// # Errors + /// + /// Passes along an I/O error from the underlying stream. + /// + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// let count = 4; + /// w.write::<3, u32>(count).unwrap(); + /// // may need to verify count is not larger than u8 at runtime + /// w.write_var::(count, 0b1111).unwrap(); + /// w.byte_align().unwrap(); + /// assert_eq!(w.into_writer(), &[0b100_11110]); + /// ``` + /// + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitCount}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // a bit count of 4, with a maximum of 7 (0b111) + /// let count: BitCount<0b111> = BitCount::new::<4>(); + /// w.write_count(count).unwrap(); + /// // maximum size of count is known to be 7 bits at compile-time + /// // so no need to check that 7 bits is larger than a u8 at runtime + /// w.write_counted::<0b111, u8>(count, 0b1111).unwrap(); + /// w.byte_align().unwrap(); + /// assert_eq!(w.into_writer(), &[0b100_11110]); + /// ``` + /// + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitCount}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // a bit count of 4, with a maximum of 6 (0b110) + /// let count: BitCount<0b110> = BitCount::new::<4>(); + /// w.write_count(count).unwrap(); + /// w.write_counted::<0b110, u8>(count, 0b1111).unwrap(); + /// w.byte_align().unwrap(); + /// // bit count is written in 3 bits + /// // while actual value is written in 4 bits + /// assert_eq!(w.into_writer(), &[0b100_11110]); + /// ``` + fn write_count(&mut self, BitCount { bits }: BitCount) -> io::Result<()> { + const { + assert!(MAX > 0, "MAX value must be > 0"); + } + + self.write_unsigned_var( + if MAX == u32::MAX { + 32 + } else if (MAX + 1).is_power_of_two() { + (MAX + 1).ilog2() + } else { + (MAX + 1).ilog2() + 1 + }, + bits, + ) + } + + /// Writes a signed or unsigned value to the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing 4 bits with a maximum of 8 will fit into a u8 + /// // so we only need check the value fits into 4 bits + /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok()); + /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err()); + /// // writing 4 bits with a maximum of 64 might not fit into a u8 + /// // so need to verify this at runtime + /// assert!(w.write_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok()); + /// assert_eq!(w.into_writer(), &[0b1111_0000]); + /// ``` + fn write_counted(&mut self, bits: BitCount, value: I) -> io::Result<()> + where + I: Integer + Sized, + { + I::write_var::(value, self, bits) + } + + /// Writes a signed value to the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing 4 bits with a maximum of 8 will fit into a u8 + /// // so we only need check the value fits into 4 bits + /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok()); + /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err()); + /// // writing 4 bits with a maximum of 64 might not fit into a u8 + /// // so need to verify this at runtime + /// assert!(w.write_unsigned_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok()); + /// assert_eq!(w.into_writer(), &[0b1111_0000]); + /// ``` + fn write_unsigned_counted( + &mut self, + bits: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger; + + /// Writes an unsigned value to the stream with + /// the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // writing 4 bits with a maximum of 8 will fit into an i8 + /// // so we only need check the value fits into 4 bits + /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111).is_ok()); + /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111 + 1).is_err()); + /// // writing 4 bits with a maximum of 64 might not fit into a i8 + /// // so need to verify this at runtime + /// assert!(w.write_signed_counted::<64, i8>(BitCount::new::<4>(), 0b0000).is_ok()); + /// assert_eq!(w.into_writer(), &[0b0111_0000]); + /// ``` + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger; + + /// Writes the given constant value to the stream with + /// the given number of bits. + /// + /// Due to current limitations of constant parameters, + /// this is limited to `u32` values. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// A compile-time error occurs if the number of bits is larger + /// than 32 or if the value is too large too fit the + /// requested number of bits. + /// + /// # Examples + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_const::<4, 0b1000>().is_ok()); + /// assert!(w.write_const::<4, 0b1011>().is_ok()); + /// assert_eq!(w.into_writer(), &[0b1000_1011]); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // trying to write a 5 bit value in 4 bits is a compile-time error + /// w.write_const::<4, 0b11111>(); + /// ``` + /// + /// ```rust,compile_fail + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// // trying to write a 33 bit value is also a compile-time error + /// w.write_const::<33, 1>(); + /// ``` + #[inline] + fn write_const(&mut self) -> io::Result<()> { + const { + assert!( + BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), + "excessive value for bits written" + ); + } + + self.write::(VALUE) + } + + /// Writes whole value to the stream whose size in bits + /// is equal to its type's size. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_from::(0x12_34_56_78).is_ok()); + /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]); + /// ``` + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_from::<[u8; 4]>([0x12, 0x34, 0x56, 0x78]).is_ok()); + /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]); + /// ``` + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive; + + /// Writes whole value to the stream whose size in bits + /// is equal to its type's size in an endianness that may + /// be different from the stream's endianness. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian, LittleEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_as_from::(0x12_34_56_78).is_ok()); + /// assert_eq!(w.into_writer(), &[0x78, 0x56, 0x34, 0x12]); + /// ``` + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive; + + /// Pads the stream by writing 0 over the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// let mut w = BitWriter::endian(vec![], BigEndian); + /// assert!(w.write_bit(true).is_ok()); + /// assert!(w.pad(7).is_ok()); + /// assert_eq!(w.into_writer(), &[0b1_0000000]); + /// ``` + fn pad(&mut self, mut bits: u32) -> io::Result<()> { + loop { + match bits { + 0 => break Ok(()), + bits @ 1..64 => break self.write_var(bits, 0u64), + _ => { + self.write::<64, u64>(0)?; + bits -= 64; + } + } + } + } + + /// Writes the entirety of a byte buffer to the stream. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_var(8, 0x66u8).unwrap(); + /// writer.write_var(8, 0x6Fu8).unwrap(); + /// writer.write_var(8, 0x6Fu8).unwrap(); + /// writer.write_bytes(b"bar").unwrap(); + /// assert_eq!(writer.into_writer(), b"foobar"); + /// ``` + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + buf.iter().try_for_each(|b| self.write_unsigned::<8, _>(*b)) + } + + /// Writes `value` number of non `STOP_BIT` bits to the stream + /// and then writes a `STOP_BIT`. This field is variably-sized. + /// `STOP_BIT` must be 0 or 1. + /// + /// # Errors + /// + /// Passes along any I/O error from the underyling stream. + /// + /// # Examples + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_unary::<0>(0).unwrap(); + /// writer.write_unary::<0>(3).unwrap(); + /// writer.write_unary::<0>(10).unwrap(); + /// assert_eq!(writer.into_writer(), [0b01110111, 0b11111110]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); + /// writer.write_unary::<0>(0).unwrap(); + /// writer.write_unary::<0>(3).unwrap(); + /// writer.write_unary::<0>(10).unwrap(); + /// assert_eq!(writer.into_writer(), [0b11101110, 0b01111111]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_unary::<1>(0).unwrap(); + /// writer.write_unary::<1>(3).unwrap(); + /// writer.write_unary::<1>(10).unwrap(); + /// assert_eq!(writer.into_writer(), [0b10001000, 0b00000001]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); + /// writer.write_unary::<1>(0).unwrap(); + /// writer.write_unary::<1>(3).unwrap(); + /// writer.write_unary::<1>(10).unwrap(); + /// assert_eq!(writer.into_writer(), [0b00010001, 0b10000000]); + /// ``` + fn write_unary(&mut self, mut value: u32) -> io::Result<()> { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + const MAX: BitCount<32> = BitCount::new::<32>(); + + match STOP_BIT { + 0 => { + while value > 0 { + let to_write = MAX.min(value); + self.write_checked(to_write.all::())?; + value -= u32::from(to_write); + } + self.write_bit(false) + } + 1 => { + while value > 0 { + let to_write = MAX.min(value); + self.write_checked(to_write.none::())?; + value -= u32::from(to_write); + } + self.write_bit(true) + } + _ => unreachable!(), + } + } + + /// Writes checked value that is known to fit a given number of bits + fn write_checked(&mut self, value: C) -> io::Result<()> { + // a naive default implementation + value.write(self) + } + + /// Builds and writes complex type + fn build(&mut self, build: &T) -> Result<(), T::Error> { + build.to_writer(self) + } + + /// Builds and writes complex type with context + fn build_with<'a, T: ToBitStreamWith<'a>>( + &mut self, + build: &T, + context: &T::Context, + ) -> Result<(), T::Error> { + build.to_writer(self, context) + } + + /// Builds and writes complex type with owned context + fn build_using( + &mut self, + build: &T, + context: T::Context, + ) -> Result<(), T::Error> { + build.to_writer(self, context) + } + + /// Returns true if the stream is aligned at a whole byte. + /// + /// # Example + /// ``` + /// use std::io::{Write, sink}; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(sink(), BigEndian); + /// assert_eq!(writer.byte_aligned(), true); + /// writer.write_var(1, 0u8).unwrap(); + /// assert_eq!(writer.byte_aligned(), false); + /// writer.write_var(7, 0u8).unwrap(); + /// assert_eq!(writer.byte_aligned(), true); + /// ``` + fn byte_aligned(&self) -> bool; + + /// Pads the stream with 0 bits until it is aligned at a whole byte. + /// Does nothing if the stream is already aligned. + /// + /// # Errors + /// + /// Passes along any I/O error from the underyling stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_var(1, 0u8).unwrap(); + /// writer.byte_align().unwrap(); + /// writer.write_var(8, 0xFFu8).unwrap(); + /// assert_eq!(writer.into_writer(), [0x00, 0xFF]); + /// ``` + fn byte_align(&mut self) -> io::Result<()> { + while !BitWrite::byte_aligned(self) { + self.write_bit(false)?; + } + Ok(()) + } + + /// Given a symbol, writes its representation to the output stream as bits. + /// Generates no output if the symbol isn't defined in the Huffman tree. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// use bitstream_io::define_huffman_tree; + /// + /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); + /// // 'a' is 0 + /// // 'b' is 1 -> 0 + /// // 'c' is 1 -> 1 -> 0 + /// // 'd' is 1 -> 1 -> 1 + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// writer.write_huffman::('b').unwrap(); + /// writer.write_huffman::('c').unwrap(); + /// writer.write_huffman::('d').unwrap(); + /// assert_eq!(writer.into_writer(), [0b10_110_111]); + /// ``` + fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> + where + T: crate::huffman::ToBits, + { + T::to_bits(value, |b| self.write_bit(b)) + } + + /// Writes a number using a variable using a variable width integer. + /// This optimises the case when the number is small. + /// + /// Given a 4-bit VBR field, any 3-bit value (0 through 7) is encoded directly, with the high bit set to zero. + /// Values larger than N-1 bits emit their bits in a series of N-1 bit chunks, where all but the last set the high bit. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_unsigned_vbr::<4,_>(7u32); + /// writer.write_unsigned_vbr::<4,_>(100u32); + /// assert_eq!(writer.into_writer(), [0b0111_1100, 0b1100_0001]); + /// ``` + fn write_unsigned_vbr( + &mut self, + value: U, + ) -> io::Result<()> { + const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) }; + let payload_bits = FIELD_SIZE - 1; + let continuation_bit = U::ONE.shl(payload_bits); + let payload_mask = continuation_bit.sub(U::ONE); + let mut value = value; + + loop { + let payload = value & payload_mask; + value >>= payload_bits; + if value != U::ZERO { + self.write_unsigned::(payload | continuation_bit)?; + } else { + self.write_unsigned::(payload)?; + break; + } + } + Ok(()) + } + + /// Writes a number using a variable using a variable width integer. + /// This optimises the case when the number is small. + /// + /// The integer is mapped to an unsigned value using zigzag encoding. + /// For an integer X: + /// - if X >= 0 -> 2X + /// - else -> -2X + 1 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_signed_vbr::<4,_>(3); + /// writer.write_signed_vbr::<4,_>(-50); + /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]); + /// ``` + #[inline] + fn write_signed_vbr( + &mut self, + value: I, + ) -> io::Result<()> { + let zig_zag = value.shl(1).bitxor(value.shr(I::BITS_SIZE - 1)); + self.write_unsigned_vbr::(zig_zag.as_non_negative()) + } + + /// Writes a signed or unsigned variable width integer to the stream + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_vbr::<4,_>(6u32); + /// writer.write_vbr::<4,_>(-50i32); + /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]); + /// ``` + #[inline] + fn write_vbr(&mut self, value: I) -> io::Result<()> { + I::write_vbr::(value, self) + } + + /// Creates a "by reference" adaptor for this `BitWrite` + /// + /// The returned adapter also implements `BitWrite` + /// and will borrow the current reader. + /// + /// # Example + /// ``` + /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; + /// + /// fn build(w: W) { + /// // perform some building + /// } + /// + /// let mut writer = BitWriter::endian(vec![], BigEndian); + /// // performing building by reference + /// build(writer.by_ref()); + /// // original owned writer still available + /// writer.write::<8, u8>(0).unwrap(); + /// assert_eq!(writer.into_writer(), &[0]); + /// ``` + #[inline] + fn by_ref(&mut self) -> &mut Self { + self + } +} + +impl BitWrite for &mut W { + #[inline] + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + (**self).write_bit(bit) + } + + #[inline] + fn write(&mut self, value: I) -> io::Result<()> + where + I: Integer, + { + (**self).write::(value) + } + + #[inline] + fn write_const(&mut self) -> io::Result<()> { + (**self).write_const::() + } + + #[inline] + fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> + where + I: Integer, + { + (**self).write_var(bits, value) + } + + #[inline] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + (**self).write_unsigned::(value) + } + + #[inline] + fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + (**self).write_unsigned_var(bits, value) + } + + #[inline] + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + (**self).write_signed::(value) + } + + #[inline(always)] + fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> + where + S: SignedInteger, + { + (**self).write_signed_var(bits, value) + } + + #[inline] + fn write_count(&mut self, count: BitCount) -> io::Result<()> { + (**self).write_count::(count) + } + + #[inline] + fn write_counted(&mut self, bits: BitCount, value: I) -> io::Result<()> + where + I: Integer + Sized, + { + (**self).write_counted::(bits, value) + } + + #[inline] + fn write_unsigned_counted( + &mut self, + bits: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger, + { + (**self).write_unsigned_counted::(bits, value) + } + + #[inline] + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger, + { + (**self).write_signed_counted::(bits, value) + } + + #[inline] + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + (**self).write_from::(value) + } + + #[inline] + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + (**self).write_as_from::(value) + } + + #[inline] + fn pad(&mut self, bits: u32) -> io::Result<()> { + (**self).pad(bits) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_bytes(buf) + } + + #[inline] + fn write_unary(&mut self, value: u32) -> io::Result<()> { + (**self).write_unary::(value) + } + + #[inline] + fn write_checked(&mut self, value: C) -> io::Result<()> { + (**self).write_checked(value) + } + + #[inline] + fn build(&mut self, build: &T) -> Result<(), T::Error> { + (**self).build(build) + } + + #[inline] + fn build_with<'a, T: ToBitStreamWith<'a>>( + &mut self, + build: &T, + context: &T::Context, + ) -> Result<(), T::Error> { + (**self).build_with(build, context) + } + + #[inline] + fn byte_aligned(&self) -> bool { + (**self).byte_aligned() + } + + #[inline] + fn byte_align(&mut self) -> io::Result<()> { + (**self).byte_align() + } + + #[inline] + fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> + where + T: crate::huffman::ToBits, + { + (**self).write_huffman::(value) + } +} + +/// A compatibility trait for older code implementing [`BitWrite`] +/// +/// This is a trait largely compatible with older code +/// from the 2.X.X version, +/// which one can use with a named import as needed. +/// +/// New code should prefer the regular [`BitWrite`] trait. +/// +/// # Example +/// ``` +/// use bitstream_io::BitWrite2 as BitWrite; +/// use bitstream_io::{BitWriter, BigEndian}; +/// let mut byte = vec![]; +/// let mut writer = BitWriter::endian(byte, BigEndian); +/// writer.write::(4, 0b1111).unwrap(); +/// writer.write_out::<4, u8>(0b0000).unwrap(); +/// assert_eq!(writer.into_writer(), [0b1111_0000]); +/// ``` +pub trait BitWrite2 { + /// Writes a single bit to the stream. + /// `true` indicates 1, `false` indicates 0 + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + self.write_unsigned_out::<1, u8>(u8::from(bit)) + } + + /// Writes a signed or unsigned value to the stream using the given + /// number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the value is too large + /// to fit the given number of bits. + fn write(&mut self, bits: u32, value: I) -> io::Result<()> + where + I: Integer; + + /// Writes a signed or unsigned value to the stream using the given + /// const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + fn write_out(&mut self, value: I) -> io::Result<()> + where + I: Integer; + + /// Writes an unsigned value to the stream using the given + /// number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the value is too large + /// to fit the given number of bits. + fn write_unsigned(&mut self, bits: u32, value: U) -> io::Result<()> + where + U: UnsignedInteger; + + /// Writes an unsigned value to the stream using the given + /// const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + #[inline] + fn write_unsigned_out(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + self.write_unsigned(BITS, value) + } + + /// Writes a twos-complement signed value to the stream + /// with the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the input type is too small + /// to hold the given number of bits. + /// Returns an error if the number of bits is 0, + /// since one bit is always needed for the sign. + /// Returns an error if the value is too large + /// to fit the given number of bits. + fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> + where + S: SignedInteger; + + /// Writes a twos-complement signed value to the stream + /// with the given const number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// Returns an error if the value is too large + /// to fit the given number of bits. + /// A compile-time error occurs if the number of bits is 0, + /// since one bit is always needed for the sign. + /// A compile-time error occurs if the given number of bits + /// is larger than the output type. + fn write_signed_out(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + self.write_signed(BITS, value) + } + + /// Writes whole value to the stream whose size in bits + /// is equal to its type's size. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive; + + /// Writes whole value to the stream whose size in bits + /// is equal to its type's size in an endianness that may + /// be different from the stream's endianness. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive; + + /// Pads the stream by writing 0 over the given number of bits. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn pad(&mut self, mut bits: u32) -> io::Result<()> { + loop { + match bits { + 0 => break Ok(()), + bits @ 1..64 => break self.write(bits, 0u64), + _ => { + self.write_out::<64, u64>(0)?; + bits -= 64; + } + } + } + } + + /// Writes the entirety of a byte buffer to the stream. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_var(8, 0x66u8).unwrap(); + /// writer.write_var(8, 0x6Fu8).unwrap(); + /// writer.write_var(8, 0x6Fu8).unwrap(); + /// writer.write_bytes(b"bar").unwrap(); + /// assert_eq!(writer.into_writer(), b"foobar"); + /// ``` + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + buf.iter() + .try_for_each(|b| self.write_unsigned_out::<8, _>(*b)) + } + + /// Writes `value` number of 1 bits to the stream + /// and then writes a 0 bit. This field is variably-sized. + /// + /// # Errors + /// + /// Passes along any I/O error from the underyling stream. + fn write_unary0(&mut self, value: u32) -> io::Result<()>; + + /// Writes `value` number of 0 bits to the stream + /// and then writes a 1 bit. This field is variably-sized. + /// + /// # Errors + /// + /// Passes along any I/O error from the underyling stream. + fn write_unary1(&mut self, value: u32) -> io::Result<()>; + + /// Builds and writes complex type + fn build(&mut self, build: &T) -> Result<(), T::Error> + where + Self: BitWrite, + { + build.to_writer(self) + } + + /// Builds and writes complex type with context + fn build_with<'a, T: ToBitStreamWith<'a>>( + &mut self, + build: &T, + context: &T::Context, + ) -> Result<(), T::Error> + where + Self: BitWrite, + { + build.to_writer(self, context) + } + + /// Returns true if the stream is aligned at a whole byte. + fn byte_aligned(&self) -> bool; + + /// Pads the stream with 0 bits until it is aligned at a whole byte. + /// Does nothing if the stream is already aligned. + /// + /// # Errors + /// + /// Passes along any I/O error from the underyling stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_var(1, 0u8).unwrap(); + /// writer.byte_align().unwrap(); + /// writer.write_var(8, 0xFFu8).unwrap(); + /// assert_eq!(writer.into_writer(), [0x00, 0xFF]); + /// ``` + fn byte_align(&mut self) -> io::Result<()> { + while !self.byte_aligned() { + self.write_bit(false)?; + } + Ok(()) + } + + /// Given a symbol, writes its representation to the output stream as bits. + /// Generates no output if the symbol isn't defined in the Huffman tree. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite2}; + /// use bitstream_io::define_huffman_tree; + /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// writer.write_huffman::('b').unwrap(); + /// writer.write_huffman::('c').unwrap(); + /// writer.write_huffman::('d').unwrap(); + /// assert_eq!(writer.into_writer(), [0b10_110_111]); + /// ``` + fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> + where + T: crate::huffman::ToBits, + { + T::to_bits(value, |b| self.write_bit(b)) + } +} + +impl BitWrite2 for W { + #[inline] + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + BitWrite::write_bit(self, bit) + } + + #[inline] + fn write(&mut self, bits: u32, value: I) -> io::Result<()> + where + I: Integer, + { + BitWrite::write_var(self, bits, value) + } + + #[inline] + fn write_out(&mut self, value: I) -> io::Result<()> + where + I: Integer, + { + BitWrite::write::(self, value) + } + + #[inline] + fn write_unsigned(&mut self, bits: u32, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + BitWrite::write_unsigned_var::(self, bits, value) + } + + #[inline] + fn write_unsigned_out(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + BitWrite::write_unsigned::(self, value) + } + + #[inline] + fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> + where + S: SignedInteger, + { + BitWrite::write_signed_var::(self, bits, value) + } + + #[inline] + fn write_signed_out(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + BitWrite::write_signed::(self, value) + } + + #[inline] + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + BitWrite::write_from(self, value) + } + + #[inline] + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + BitWrite::write_as_from::(self, value) + } + + #[inline] + fn pad(&mut self, bits: u32) -> io::Result<()> { + BitWrite::pad(self, bits) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + BitWrite::write_bytes(self, buf) + } + + #[inline] + fn write_unary0(&mut self, value: u32) -> io::Result<()> { + BitWrite::write_unary::<0>(self, value) + } + + #[inline] + fn write_unary1(&mut self, value: u32) -> io::Result<()> { + BitWrite::write_unary::<1>(self, value) + } + + #[inline] + fn byte_aligned(&self) -> bool { + BitWrite::byte_aligned(self) + } + + #[inline] + fn byte_align(&mut self) -> io::Result<()> { + BitWrite::byte_align(self) + } +} + +impl BitWrite for BitWriter { + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + match E::push_bit_flush(&mut self.value, &mut self.bits, bit) { + None => Ok(()), + Some(byte) => write_byte(&mut self.writer, byte), + } + } + + #[inline(always)] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + let Self { + value: queue_value, + bits: queue_bits, + writer, + .. + } = self; + + E::write_bits_checked( + writer, + queue_value, + queue_bits, + CheckedUnsigned::::new_fixed::(value)?, + ) + } + + fn write_unsigned_counted( + &mut self, + count: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger, + { + let Self { + value: queue_value, + bits: queue_bits, + writer, + .. + } = self; + + E::write_bits_checked( + writer, + queue_value, + queue_bits, + CheckedUnsigned::new(count, value)?, + ) + } + + #[inline(always)] + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger, + { + E::write_signed_bits_checked( + &mut self.writer, + &mut self.value, + &mut self.bits, + CheckedSigned::new( + bits.try_into().map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "signed writes need at least 1 bit for sign", + ) + })?, + value, + )?, + ) + } + + #[inline] + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + E::write_signed_bits_checked( + &mut self.writer, + &mut self.value, + &mut self.bits, + CheckedSigned::::new_fixed::(value)?, + ) + } + + #[inline] + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + E::write_bytes::<8, _>( + &mut self.writer, + &mut self.value, + self.bits, + E::primitive_to_bytes(value).as_ref(), + ) + } + + #[inline] + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + F::write_bytes::<8, _>( + &mut self.writer, + &mut self.value, + self.bits, + F::primitive_to_bytes(value).as_ref(), + ) + } + + #[inline] + fn write_checked(&mut self, value: C) -> io::Result<()> { + value.write_endian::(&mut self.writer, &mut self.value, &mut self.bits) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + E::write_bytes::<1024, _>(&mut self.writer, &mut self.value, self.bits, buf) + } + + #[inline(always)] + fn byte_aligned(&self) -> bool { + self.bits == 0 + } +} + +/// An error returned if performing math operations would overflow +#[derive(Copy, Clone, Debug)] +pub struct Overflowed; + +impl fmt::Display for Overflowed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "overflow occured in counter".fmt(f) + } +} + +impl core::error::Error for Overflowed {} + +impl From for io::Error { + fn from(Overflowed: Overflowed) -> Self { + io::Error::new( + #[cfg(feature = "std")] + { + io::ErrorKind::StorageFull + }, + #[cfg(not(feature = "std"))] + { + io::ErrorKind::Other + }, + "bitstream accumulator overflow", + ) + } +} + +/// A common trait for integer types for performing math operations +/// which may check for overflow. +pub trait Counter: Default + Sized + From + TryFrom + TryFrom { + /// add rhs to self, returning `Overflowed` if the result is too large + fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed>; + + /// multiply self by rhs, returning `Overflowed` if the result is too large + fn checked_mul(self, rhs: Self) -> Result; + + /// returns `true` if the number if bits written is divisible by 8 + fn byte_aligned(&self) -> bool; +} + +macro_rules! define_counter { + ($t:ty) => { + impl Counter for $t { + fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed> { + *self = <$t>::checked_add(*self, rhs).ok_or(Overflowed)?; + Ok(()) + } + + fn checked_mul(self, rhs: Self) -> Result { + <$t>::checked_mul(self, rhs).ok_or(Overflowed) + } + + fn byte_aligned(&self) -> bool { + self % 8 == 0 + } + } + }; +} + +define_counter!(u8); +define_counter!(u16); +define_counter!(u32); +define_counter!(u64); +define_counter!(u128); + +/// For counting the number of bits written but generating no output. +/// +/// # Example +/// ``` +/// use bitstream_io::{BigEndian, BitWrite, BitsWritten}; +/// let mut writer: BitsWritten = BitsWritten::new(); +/// writer.write_var(1, 0b1u8).unwrap(); +/// writer.write_var(2, 0b01u8).unwrap(); +/// writer.write_var(5, 0b10111u8).unwrap(); +/// assert_eq!(writer.written(), 8); +/// ``` +#[derive(Default)] +pub struct BitsWritten { + bits: N, +} + +impl BitsWritten { + /// Creates new empty BitsWritten value + #[inline] + pub fn new() -> Self { + Self { bits: N::default() } + } +} + +impl BitsWritten { + /// Returns number of bits written + #[inline] + pub fn written(&self) -> N { + self.bits + } +} + +impl BitsWritten { + /// Returns number of bits written + #[inline] + pub fn into_written(self) -> N { + self.bits + } +} + +impl BitWrite for BitsWritten { + #[inline] + fn write_bit(&mut self, _bit: bool) -> io::Result<()> { + self.bits.checked_add_assign(1u8.into())?; + Ok(()) + } + + #[inline] + fn write_const(&mut self) -> io::Result<()> { + const { + assert!( + BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), + "excessive value for bits written" + ); + } + + self.bits + .checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?; + Ok(()) + } + + #[inline] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + const { + assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); + } + + if BITS == 0 { + Ok(()) + } else if value <= (U::ALL >> (U::BITS_SIZE - BITS)) { + self.bits + .checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?; + Ok(()) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive value for bits written", + )) + } + } + + #[inline] + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + let SignedBitCount { + bits: BitCount { bits }, + unsigned, + } = const { + assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); + let count = BitCount::::new::().signed_count(); + assert!( + count.is_some(), + "signed writes need at least 1 bit for sign" + ); + count.unwrap() + }; + + // doesn't matter which side the sign is on + // so long as it's added to the bit count + self.bits.checked_add_assign(1u8.into())?; + + self.write_unsigned_counted( + unsigned, + if value.is_negative() { + value.as_negative(bits) + } else { + value.as_non_negative() + }, + ) + } + + #[inline] + fn write_unsigned_counted( + &mut self, + BitCount { bits }: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger, + { + if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { + if bits == 0 { + Ok(()) + } else if value <= U::ALL >> (U::BITS_SIZE - bits) { + self.bits + .checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?; + Ok(()) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive value for bits written", + )) + } + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type written", + )) + } + } + + #[inline] + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger, + { + let SignedBitCount { + bits: BitCount { bits }, + unsigned, + } = bits.try_into().map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "signed writes need at least 1 bit for sign", + ) + })?; + + if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { + // doesn't matter which side the sign is on + // so long as it's added to the bit count + self.bits.checked_add_assign(1u8.into())?; + + self.write_unsigned_counted( + unsigned, + if value.is_negative() { + value.as_negative(bits) + } else { + value.as_non_negative() + }, + ) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "excessive bits for type written", + )) + } + } + + #[inline] + fn write_from(&mut self, _: V) -> io::Result<()> + where + V: Primitive, + { + self.bits.checked_add_assign( + N::try_from(core::mem::size_of::()) + .map_err(|_| Overflowed)? + .checked_mul(8u8.into())?, + )?; + Ok(()) + } + + #[inline] + fn write_as_from(&mut self, _: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + self.bits.checked_add_assign( + N::try_from(core::mem::size_of::()) + .map_err(|_| Overflowed)? + .checked_mul(8u8.into())?, + )?; + Ok(()) + } + + #[inline] + fn pad(&mut self, bits: u32) -> io::Result<()> { + self.bits + .checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?; + Ok(()) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + self.bits.checked_add_assign( + N::try_from(buf.len()) + .map_err(|_| Overflowed)? + .checked_mul(8u8.into())?, + )?; + Ok(()) + } + + fn write_unary(&mut self, value: u32) -> io::Result<()> { + const { + assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); + } + + self.bits + .checked_add_assign(value.try_into().map_err(|_| Overflowed)?)?; + self.bits.checked_add_assign(1u8.into())?; + Ok(()) + } + + fn write_checked(&mut self, value: C) -> io::Result<()> { + Ok(self + .bits + .checked_add_assign(value.written_bits().try_into().map_err(|_| Overflowed)?)?) + } + + #[inline] + fn byte_aligned(&self) -> bool { + self.bits.byte_aligned() + } +} + +/// For counting the number of bits written but generating no output. +/// +/// # Example +/// ``` +/// use bitstream_io::{BigEndian, BitWrite, BitCounter}; +/// let mut writer: BitCounter = BitCounter::new(); +/// writer.write_var(1, 0b1u8).unwrap(); +/// writer.write_var(2, 0b01u8).unwrap(); +/// writer.write_var(5, 0b10111u8).unwrap(); +/// assert_eq!(writer.written(), 8); +/// ``` +#[derive(Default)] +#[deprecated(since = "4.0.0", note = "use of BitsWritten is preferred")] +pub struct BitCounter { + bits: BitsWritten, + phantom: PhantomData, +} + +#[allow(deprecated)] +impl BitCounter { + /// Creates new counter + #[inline] + pub fn new() -> Self { + BitCounter { + bits: BitsWritten::new(), + phantom: PhantomData, + } + } +} + +#[allow(deprecated)] +impl BitCounter { + /// Returns number of bits written + #[inline] + pub fn written(&self) -> N { + self.bits.written() + } +} + +#[allow(deprecated)] +impl BitCounter { + /// Returns number of bits written + #[inline] + pub fn into_written(self) -> N { + self.bits.into_written() + } +} + +#[allow(deprecated)] +impl BitWrite for BitCounter +where + E: Endianness, + N: Counter, +{ + #[inline] + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + BitWrite::write_bit(&mut self.bits, bit) + } + + #[inline] + fn write_const(&mut self) -> io::Result<()> { + BitWrite::write_const::(&mut self.bits) + } + + #[inline] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + BitWrite::write_unsigned::(&mut self.bits, value) + } + + #[inline] + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + BitWrite::write_signed::(&mut self.bits, value) + } + + #[inline] + fn write_unsigned_counted( + &mut self, + count: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger, + { + BitWrite::write_unsigned_counted::(&mut self.bits, count, value) + } + + #[inline] + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger, + { + BitWrite::write_signed_counted::(&mut self.bits, bits, value) + } + + #[inline] + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + BitWrite::write_from(&mut self.bits, value) + } + + #[inline] + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + BitWrite::write_as_from::(&mut self.bits, value) + } + + #[inline] + fn pad(&mut self, bits: u32) -> io::Result<()> { + BitWrite::pad(&mut self.bits, bits) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + BitWrite::write_bytes(&mut self.bits, buf) + } + + fn write_unary(&mut self, value: u32) -> io::Result<()> { + BitWrite::write_unary::(&mut self.bits, value) + } + + #[inline] + fn byte_aligned(&self) -> bool { + BitWrite::byte_aligned(&self.bits) + } +} + +#[cfg(feature = "alloc")] +mod bit_recorder { + use super::*; + + /// For recording writes in order to play them back on another writer + /// # Example + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitRecorder}; + /// let mut recorder: BitRecorder = BitRecorder::new(); + /// recorder.write_var(1, 0b1u8).unwrap(); + /// recorder.write_var(2, 0b01u8).unwrap(); + /// recorder.write_var(5, 0b10111u8).unwrap(); + /// assert_eq!(recorder.written(), 8); + /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); + /// recorder.playback(&mut writer); + /// assert_eq!(writer.into_writer(), [0b10110111]); + /// ``` + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + pub struct BitRecorder { + writer: BitWriter, E>, + phantom: PhantomData, + } + + impl BitRecorder { + /// Creates new recorder + #[inline] + pub fn new() -> Self { + BitRecorder { + writer: BitWriter::new(Vec::new()), + phantom: PhantomData, + } + } + + /// Creates new recorder sized for the given number of bytes + #[inline] + pub fn with_capacity(bytes: usize) -> Self { + BitRecorder { + writer: BitWriter::new(Vec::with_capacity(bytes)), + phantom: PhantomData, + } + } + + /// Creates new recorder with the given endianness + #[inline] + pub fn endian(endian: E) -> Self { + BitRecorder { + writer: BitWriter::endian(Vec::new(), endian), + phantom: PhantomData, + } + } + + /// Returns number of bits written + /// + /// # Panics + /// + /// Panics if the number of bits written is + /// larger than the maximum supported by the counter type. + /// Use [`BitRecorder::written_checked`] for a non-panicking + /// alternative. + #[inline] + pub fn written(&self) -> N { + self.written_checked().unwrap() + } + + /// Returns number of bits written + /// + /// # Errors + /// + /// Returns an error if the number of bits written overflows + /// our counter type. + #[inline] + pub fn written_checked(&self) -> Result { + let mut written = N::try_from(self.writer.writer.len()) + .map_err(|_| Overflowed)? + .checked_mul(8u8.into())?; + + written.checked_add_assign(N::try_from(self.writer.bits).map_err(|_| Overflowed)?)?; + + Ok(written) + } + + /// Plays recorded writes to the given writer + #[inline] + pub fn playback(&self, writer: &mut W) -> io::Result<()> { + writer.write_bytes(self.writer.writer.as_slice())?; + writer.write_var(self.writer.bits, self.writer.value)?; + Ok(()) + } + + /// Clears recorder, removing all values + #[inline] + pub fn clear(&mut self) { + self.writer = BitWriter::new({ + let mut v = core::mem::take(&mut self.writer.writer); + v.clear(); + v + }); + } + } + + impl Default for BitRecorder { + #[inline] + fn default() -> Self { + Self::new() + } + } + + impl BitWrite for BitRecorder + where + E: Endianness, + N: Counter, + { + #[inline] + fn write_bit(&mut self, bit: bool) -> io::Result<()> { + BitWrite::write_bit(&mut self.writer, bit) + } + + #[inline] + fn write(&mut self, value: I) -> io::Result<()> + where + I: Integer, + { + BitWrite::write::(&mut self.writer, value) + } + + #[inline] + fn write_const(&mut self) -> io::Result<()> { + self.writer.write_const::() + } + + #[inline] + fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> + where + I: Integer, + { + self.writer.write_var(bits, value) + } + + #[inline] + fn write_unsigned(&mut self, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + BitWrite::write_unsigned::(&mut self.writer, value) + } + + #[inline] + fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> + where + U: UnsignedInteger, + { + self.writer.write_unsigned_var(bits, value) + } + + #[inline] + fn write_signed(&mut self, value: S) -> io::Result<()> + where + S: SignedInteger, + { + BitWrite::write_signed::(&mut self.writer, value) + } + + #[inline(always)] + fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> + where + S: SignedInteger, + { + self.writer.write_signed_var(bits, value) + } + + #[inline] + fn write_count(&mut self, count: BitCount) -> io::Result<()> { + self.writer.write_count::(count) + } + + #[inline] + fn write_counted( + &mut self, + bits: BitCount, + value: I, + ) -> io::Result<()> + where + I: Integer + Sized, + { + self.writer.write_counted::(bits, value) + } + + #[inline] + fn write_unsigned_counted( + &mut self, + bits: BitCount, + value: U, + ) -> io::Result<()> + where + U: UnsignedInteger, + { + self.writer.write_unsigned_counted::(bits, value) + } + + #[inline] + fn write_signed_counted( + &mut self, + bits: impl TryInto>, + value: S, + ) -> io::Result<()> + where + S: SignedInteger, + { + self.writer.write_signed_counted::(bits, value) + } + + #[inline] + fn write_from(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + BitWrite::write_from::(&mut self.writer, value) + } + + #[inline] + fn write_as_from(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + BitWrite::write_as_from::(&mut self.writer, value) + } + + #[inline] + fn pad(&mut self, bits: u32) -> io::Result<()> { + BitWrite::pad(&mut self.writer, bits) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + BitWrite::write_bytes(&mut self.writer, buf) + } + + #[inline] + fn write_unary(&mut self, value: u32) -> io::Result<()> { + self.writer.write_unary::(value) + } + + #[inline] + fn build(&mut self, build: &T) -> Result<(), T::Error> { + BitWrite::build(&mut self.writer, build) + } + + #[inline] + fn build_with<'a, T: ToBitStreamWith<'a>>( + &mut self, + build: &T, + context: &T::Context, + ) -> Result<(), T::Error> { + BitWrite::build_with(&mut self.writer, build, context) + } + + #[inline] + fn byte_aligned(&self) -> bool { + BitWrite::byte_aligned(&self.writer) + } + + #[inline] + fn byte_align(&mut self) -> io::Result<()> { + BitWrite::byte_align(&mut self.writer) + } + + #[inline] + fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> + where + T: crate::huffman::ToBits, + { + BitWrite::write_huffman::(&mut self.writer, value) + } + } + + impl BitRecorder { + /// Returns shortest option between ourself and candidate + /// + /// Executes fallible closure on emptied candidate recorder, + /// compares the lengths of ourself and the candidate, + /// and returns the shorter of the two. + /// + /// If the new candidate is shorter, we swap ourself and + /// the candidate so any recorder capacity can be reused. + /// + /// # Example + /// + /// ``` + /// use bitstream_io::{BitRecorder, BitWrite, BigEndian}; + /// + /// let mut best = BitRecorder::::new(); + /// let mut candidate = BitRecorder::new(); + /// + /// // write an 8 bit value to our initial candidate + /// best.write::<8, u8>(0); + /// assert_eq!(best.written(), 8); + /// + /// // try another candidate which writes 4 bits + /// best = best.best(&mut candidate, |w| { + /// w.write::<4, u8>(0) + /// }).unwrap(); + /// + /// // which becomes our new best candidate + /// assert_eq!(best.written(), 4); + /// + /// // finally, try a not-so-best candidate + /// // which writes 10 bits + /// best = best.best(&mut candidate, |w| { + /// w.write::<10, u16>(0) + /// }).unwrap(); + /// + /// // so our best candidate remains 4 bits + /// assert_eq!(best.written(), 4); + /// ``` + pub fn best( + mut self, + candidate: &mut Self, + f: impl FnOnce(&mut Self) -> Result<(), F>, + ) -> Result { + candidate.clear(); + + f(candidate)?; + + if candidate.written() < self.written() { + core::mem::swap(&mut self, candidate); + } + + Ok(self) + } + } +} + +#[inline] +fn write_byte(mut writer: W, byte: u8) -> io::Result<()> +where + W: io::Write, +{ + writer.write_all(core::slice::from_ref(&byte)) +} + +/// For writing aligned bytes to a stream of bytes in a given endianness. +/// +/// This only writes aligned values and maintains no internal state. +pub struct ByteWriter { + phantom: PhantomData, + writer: W, +} + +impl ByteWriter { + /// Wraps a ByteWriter around something that implements `Write` + pub fn new(writer: W) -> ByteWriter { + ByteWriter { + phantom: PhantomData, + writer, + } + } + + /// Wraps a BitWriter around something that implements `Write` + /// with the given endianness. + pub fn endian(writer: W, _endian: E) -> ByteWriter { + ByteWriter { + phantom: PhantomData, + writer, + } + } + + /// Unwraps internal writer and disposes of `ByteWriter`. + /// Any unwritten partial bits are discarded. + #[inline] + pub fn into_writer(self) -> W { + self.writer + } + + /// Provides mutable reference to internal writer. + #[inline] + pub fn writer(&mut self) -> &mut W { + &mut self.writer + } + + /// Converts `ByteWriter` to `BitWriter` in the same endianness. + #[inline] + pub fn into_bitwriter(self) -> BitWriter { + BitWriter::new(self.into_writer()) + } + + /// Provides temporary `BitWriter` in the same endianness. + /// + /// # Warning + /// + /// Any unwritten bits left over when `BitWriter` is dropped are lost. + #[inline] + pub fn bitwriter(&mut self) -> BitWriter<&mut W, E> { + BitWriter::new(self.writer()) + } +} + +/// A trait for anything that can write aligned values to an output stream +pub trait ByteWrite { + /// Writes whole numeric value to stream + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// # Examples + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite}; + /// let mut writer = ByteWriter::endian(Vec::new(), BigEndian); + /// writer.write(0b0000000011111111u16).unwrap(); + /// assert_eq!(writer.into_writer(), [0b00000000, 0b11111111]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{LittleEndian, ByteWriter, ByteWrite}; + /// let mut writer = ByteWriter::endian(Vec::new(), LittleEndian); + /// writer.write(0b0000000011111111u16).unwrap(); + /// assert_eq!(writer.into_writer(), [0b11111111, 0b00000000]); + /// ``` + fn write(&mut self, value: V) -> io::Result<()> + where + V: Primitive; + + /// Writes whole numeric value to stream in a potentially different endianness + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + /// + /// # Examples + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite, LittleEndian}; + /// let mut writer = ByteWriter::endian(Vec::new(), BigEndian); + /// writer.write_as::(0b0000000011111111).unwrap(); + /// assert_eq!(writer.into_writer(), [0b11111111, 0b00000000]); + /// ``` + /// + /// ``` + /// use std::io::Write; + /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite, LittleEndian}; + /// let mut writer = ByteWriter::endian(Vec::new(), LittleEndian); + /// writer.write_as::(0b0000000011111111).unwrap(); + /// assert_eq!(writer.into_writer(), [0b00000000, 0b11111111]); + /// ``` + fn write_as(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive; + + /// Writes the entirety of a byte buffer to the stream. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()>; + + /// Pads the stream by writing 0 over the given number of bytes. + /// + /// # Errors + /// + /// Passes along any I/O error from the underlying stream. + fn pad(&mut self, bytes: u32) -> io::Result<()>; + + /// Builds and writes complex type + fn build(&mut self, build: &T) -> Result<(), T::Error> { + build.to_writer(self) + } + + /// Builds and writes complex type with context + fn build_with<'a, T: ToByteStreamWith<'a>>( + &mut self, + build: &T, + context: &T::Context, + ) -> Result<(), T::Error> { + build.to_writer(self, context) + } + + /// Builds and writes complex type with owned context + fn build_using( + &mut self, + build: &T, + context: T::Context, + ) -> Result<(), T::Error> { + build.to_writer(self, context) + } + + /// Returns mutable reference to underlying writer + fn writer_ref(&mut self) -> &mut dyn io::Write; +} + +impl ByteWrite for ByteWriter { + #[inline] + fn write(&mut self, value: V) -> io::Result<()> + where + V: Primitive, + { + self.writer.write_all(E::primitive_to_bytes(value).as_ref()) + } + + #[inline] + fn write_as(&mut self, value: V) -> io::Result<()> + where + F: Endianness, + V: Primitive, + { + self.writer.write_all(F::primitive_to_bytes(value).as_ref()) + } + + #[inline] + fn pad(&mut self, mut bytes: u32) -> io::Result<()> { + let buf = [0u8; 8]; + + while bytes > 0 { + let to_write = bytes.min(8); + self.write_bytes(&buf[0..to_write as usize])?; + bytes -= to_write; + } + Ok(()) + } + + #[inline] + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + self.writer.write_all(buf) + } + + #[inline] + fn writer_ref(&mut self) -> &mut dyn io::Write { + &mut self.writer + } +} + +/// Implemented by complex types that don't require any additional context +/// to build themselves to a writer +/// +/// # Example +/// ``` +/// use std::io::Read; +/// use bitstream_io::{BigEndian, BitWrite, BitWriter, ToBitStream}; +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct BlockHeader { +/// last_block: bool, +/// block_type: u8, +/// block_size: u32, +/// } +/// +/// impl ToBitStream for BlockHeader { +/// type Error = std::io::Error; +/// +/// fn to_writer(&self, w: &mut W) -> std::io::Result<()> { +/// w.write_bit(self.last_block)?; +/// w.write::<7, _>(self.block_type)?; +/// w.write::<24, _>(self.block_size) +/// } +/// } +/// +/// let mut data = Vec::new(); +/// let mut writer = BitWriter::endian(&mut data, BigEndian); +/// writer.build(&BlockHeader { last_block: false, block_type: 4, block_size: 122 }).unwrap(); +/// assert_eq!(data, b"\x04\x00\x00\x7A"); +/// ``` +pub trait ToBitStream { + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer(&self, w: &mut W) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bits, if possible + fn bits(&self) -> Result + where + Self: Sized, + { + let mut c: BitsWritten = BitsWritten::default(); + self.to_writer(&mut c)?; + Ok(c.into_written()) + } + + /// Returns total length of self, if possible + #[deprecated(since = "4.0.0", note = "use of bits() is preferred")] + #[inline] + fn bits_len(&self) -> Result + where + Self: Sized, + { + self.bits() + } +} + +/// Implemented by complex types that require additional context +/// to build themselves to a writer +pub trait ToBitStreamWith<'a> { + /// Some context to use when writing + type Context: 'a; + + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer( + &self, + w: &mut W, + context: &Self::Context, + ) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bits, if possible + fn bits(&self, context: &Self::Context) -> Result + where + Self: Sized, + { + let mut c: BitsWritten = BitsWritten::default(); + self.to_writer(&mut c, context)?; + Ok(c.into_written()) + } + + /// Returns total length of self, if possible + #[deprecated(since = "4.0.0", note = "use of len() is preferred")] + #[inline] + fn bits_len(&self, context: &Self::Context) -> Result + where + Self: Sized, + { + self.bits(context) + } +} + +/// Implemented by complex types that consume additional context +/// to build themselves to a writer +pub trait ToBitStreamUsing { + /// Some context to consume when writing + type Context; + + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer( + &self, + w: &mut W, + context: Self::Context, + ) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bits, if possible + fn bits(&self, context: Self::Context) -> Result + where + Self: Sized, + { + let mut c: BitsWritten = BitsWritten::default(); + self.to_writer(&mut c, context)?; + Ok(c.into_written()) + } +} + +/// Implemented by complex types that don't require any additional context +/// to build themselves to a writer +pub trait ToByteStream { + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer(&self, w: &mut W) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bytes, if possible + fn bytes(&self) -> Result + where + Self: Sized, + { + let mut counter = ByteCount::default(); + self.to_writer(&mut counter)?; + Ok(counter.writer.count) + } +} + +/// Implemented by complex types that require additional context +/// to build themselves to a writer +pub trait ToByteStreamWith<'a> { + /// Some context to use when writing + type Context: 'a; + + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer( + &self, + w: &mut W, + context: &Self::Context, + ) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bytes, if possible + fn bytes(&self, context: &Self::Context) -> Result + where + Self: Sized, + { + let mut counter = ByteCount::default(); + self.to_writer(&mut counter, context)?; + Ok(counter.writer.count) + } +} + +/// Implemented by complex types that consume additional context +/// to build themselves to a writer +pub trait ToByteStreamUsing { + /// Some context to consume when writing + type Context; + + /// Error generated during building, such as `io::Error` + type Error; + + /// Generate self to writer + fn to_writer( + &self, + w: &mut W, + context: Self::Context, + ) -> Result<(), Self::Error> + where + Self: Sized; + + /// Returns length of self in bytes, if possible + fn bytes(&self, context: Self::Context) -> Result + where + Self: Sized, + { + let mut counter = ByteCount::default(); + self.to_writer(&mut counter, context)?; + Ok(counter.writer.count) + } +} + +#[derive(Default)] +struct ByteCounterWriter { + count: C, +} + +impl io::Write for ByteCounterWriter { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.count + .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?; + + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + // nothing to do + Ok(()) + } +} + +#[derive(Default)] +struct ByteCount { + writer: ByteCounterWriter, +} + +impl ByteWrite for ByteCount { + fn write(&mut self, _value: V) -> io::Result<()> { + self.writer.count.checked_add_assign( + V::buffer() + .as_ref() + .len() + .try_into() + .map_err(|_| Overflowed)?, + )?; + + Ok(()) + } + + fn write_as(&mut self, _value: V) -> io::Result<()> { + self.writer.count.checked_add_assign( + V::buffer() + .as_ref() + .len() + .try_into() + .map_err(|_| Overflowed)?, + )?; + + Ok(()) + } + + fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { + self.writer + .count + .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?; + + Ok(()) + } + + fn pad(&mut self, bytes: u32) -> io::Result<()> { + self.writer + .count + .checked_add_assign(bytes.try_into().map_err(|_| Overflowed)?)?; + + Ok(()) + } + + fn writer_ref(&mut self) -> &mut dyn io::Write { + &mut self.writer + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/huffman.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +#[test] +fn test_huffman_values() { + use bitstream_io::{define_huffman_tree, BigEndian, BitRead, BitReader}; + + let data = [0b10110001, 0b11101101]; + + define_huffman_tree!(Tree1 : i32 = [0, [1, [2, 5]]]); + define_huffman_tree!(Tree2 : &'static str = ["foo", ["bar", ["baz", "kelp"]]]); + + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 5); + + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read_huffman::().unwrap(), "bar"); + assert_eq!(r.read_huffman::().unwrap(), "baz"); + assert_eq!(r.read_huffman::().unwrap(), "foo"); + assert_eq!(r.read_huffman::().unwrap(), "foo"); + assert_eq!(r.read_huffman::().unwrap(), "kelp"); +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/random-3be.bin and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random-3be.bin differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/random-3le.bin and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random-3le.bin differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/random.bin clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random.bin --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/random.bin 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/random.bin 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +x^㍀¦´ÎMt±íÃoi�úŸ~3’J+Ûxm×v�M¢vË^ýÁxk.Oˈ¬¾¿`þ¨kq�œ��rÇÿϙ|ûGGÝí~lòµ�{P4Hg'~\Úó#ú µʼ„Õ>TÓ"r[ushHikT!TœËu�•ìx6 \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/read.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/read.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1043 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io; + +#[test] +fn test_reader_be() { + use bitstream_io::{BigEndian, BitRead, BitReader}; + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // reading individual bits + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + + // reading unsigned values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.byte_aligned()); + assert_eq!(r.read_var::(2).unwrap(), 2); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(3).unwrap(), 6); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(5).unwrap(), 7); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(3).unwrap(), 5); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(19).unwrap(), 0x53BC1); + assert!(r.byte_aligned()); + assert!(r.read_var::(1).is_err()); + + // reading const unsigned values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.byte_aligned()); + assert_eq!(r.read::<2, u32>().unwrap(), 2); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<3, u32>().unwrap(), 6); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<5, u32>().unwrap(), 7); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<3, u32>().unwrap(), 5); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<19, u32>().unwrap(), 0x53BC1); + assert!(r.byte_aligned()); + assert!(r.read::<1, u32>().is_err()); + + // 16-bit values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read::<1, u8>().unwrap(), 1); + assert_eq!(r.read::<14, u16>().unwrap(), 0b0110_0011_1101_10); + assert_eq!(r.read::<16, u16>().unwrap(), 0b1001_1101_1110_0000); + assert_eq!(r.read::<1, u8>().unwrap(), 1); + + // skipping bits + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_var::(2).unwrap(), 2); + assert!(r.skip(3).is_ok()); + assert_eq!(r.read_var::(5).unwrap(), 7); + assert!(r.skip(3).is_ok()); + assert_eq!(r.read_var::(19).unwrap(), 0x53BC1); + + // reading signed values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_signed_var::(2).unwrap(), -2); + assert_eq!(r.read_signed_var::(3).unwrap(), -2); + assert_eq!(r.read_signed_var::(5).unwrap(), 7); + assert_eq!(r.read_signed_var::(3).unwrap(), -3); + assert_eq!(r.read_signed_var::(19).unwrap(), -181311); + + // reading const signed values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_signed::<2, i32>().unwrap(), -2); + assert_eq!(r.read_signed::<3, i32>().unwrap(), -2); + assert_eq!(r.read_signed::<5, i32>().unwrap(), 7); + assert_eq!(r.read_signed::<3, i32>().unwrap(), -3); + assert_eq!(r.read_signed::<19, i32>().unwrap(), -181311); + + // reading unary 0 values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_unary::<0>().unwrap(), 1); + assert_eq!(r.read_unary::<0>().unwrap(), 2); + assert_eq!(r.read_unary::<0>().unwrap(), 0); + assert_eq!(r.read_unary::<0>().unwrap(), 0); + assert_eq!(r.read_unary::<0>().unwrap(), 4); + + // reading unary 1 values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + assert_eq!(r.read_unary::<1>().unwrap(), 1); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + assert_eq!(r.read_unary::<1>().unwrap(), 3); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + + // reading unsigned vbr + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 11); + assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 238); + assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 99); + assert!(r.read_unsigned_vbr::<4, u8>().is_err()); + + // reading signed vbr + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), -6); + assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), 119); + assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), -50); + assert!(r.read_signed_vbr::<4, i8>().is_err()); + + // byte aligning + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert_eq!(r.read_var::(3).unwrap(), 5); + r.byte_align(); + assert_eq!(r.read_var::(3).unwrap(), 7); + r.byte_align(); + r.byte_align(); + assert_eq!(r.read_var::(8).unwrap(), 59); + r.byte_align(); + assert_eq!(r.read_var::(4).unwrap(), 12); + + // reading bytes, aligned + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + let mut sub_data = [0; 2]; + assert!(r.read_bytes(&mut sub_data).is_ok()); + assert_eq!(&sub_data, b"\xB1\xED"); + + // reading bytes, un-aligned + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + let mut sub_data = [0; 2]; + assert_eq!(r.read_var::(4).unwrap(), 11); + assert!(r.read_bytes(&mut sub_data).is_ok()); + assert_eq!(&sub_data, b"\x1E\xD3"); +} + +#[test] +fn test_edge_cases_be() { + use bitstream_io::{BigEndian, BitRead, BitReader}; + + let data: Vec = vec![ + 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 127, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, + 255, 255, 255, + ]; + + // 0 bit reads + let mut r = BitReader::endian([255; 1].as_slice(), BigEndian); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(8).unwrap(), 255); + + let mut r = BitReader::endian([255; 1].as_slice(), BigEndian); + assert_eq!(r.read::<0, u8>().unwrap(), 0); + assert_eq!(r.read::<0, u16>().unwrap(), 0); + assert_eq!(r.read::<0, u32>().unwrap(), 0); + assert_eq!(r.read::<0, u64>().unwrap(), 0); + assert_eq!(r.read::<8, u8>().unwrap(), 255); + + let mut r = BitReader::endian([255; 1].as_slice(), BigEndian); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + + // unsigned 32 and 64-bit values + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read_var::(32).unwrap(), 0); + assert_eq!(r.read_var::(32).unwrap(), 4294967295); + assert_eq!(r.read_var::(32).unwrap(), 2147483648); + assert_eq!(r.read_var::(32).unwrap(), 2147483647); + assert_eq!(r.read_var::(64).unwrap(), 0); + assert_eq!(r.read_var::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); + assert_eq!(r.read_var::(64).unwrap(), 9223372036854775808); + assert_eq!(r.read_var::(64).unwrap(), 9223372036854775807); + + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read::<32, u32>().unwrap(), 0); + assert_eq!(r.read::<32, u32>().unwrap(), 4294967295); + assert_eq!(r.read::<32, u32>().unwrap(), 2147483648); + assert_eq!(r.read::<32, u32>().unwrap(), 2147483647); + assert_eq!(r.read::<64, u64>().unwrap(), 0); + assert_eq!(r.read::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); + assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775808); + assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775807); + + // signed 32 and 64-bit values + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read_signed_var::(32).unwrap(), 0); + assert_eq!(r.read_signed_var::(32).unwrap(), -1); + assert_eq!(r.read_signed_var::(32).unwrap(), -2147483648); + assert_eq!(r.read_signed_var::(32).unwrap(), 2147483647); + assert_eq!(r.read_signed_var::(64).unwrap(), 0); + assert_eq!(r.read_signed_var::(64).unwrap(), -1); + assert_eq!(r.read_signed_var::(64).unwrap(), -9223372036854775808); + assert_eq!(r.read_signed_var::(64).unwrap(), 9223372036854775807); + + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read_signed::<32, i32>().unwrap(), 0); + assert_eq!(r.read_signed::<32, i32>().unwrap(), -1); + assert_eq!(r.read_signed::<32, i32>().unwrap(), -2147483648); + assert_eq!(r.read_signed::<32, i32>().unwrap(), 2147483647); + assert_eq!(r.read_signed::<64, i64>().unwrap(), 0); + assert_eq!(r.read_signed::<64, i64>().unwrap(), -1); + assert_eq!(r.read_signed::<64, i64>().unwrap(), -9223372036854775808); + assert_eq!(r.read_signed::<64, i64>().unwrap(), 9223372036854775807); +} + +#[test] +fn test_reader_huffman_be() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BigEndian, BitRead, BitReader}; + + define_huffman_tree!(SomeTree : i32 = [[[4, 3], 2], [1, 0]]); + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 4); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 4); + assert_eq!(r.read_huffman::().unwrap(), 2); +} + +#[test] +fn test_read_chunks_be() { + use bitstream_io::{BigEndian, BitRead, BitReader}; + + let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; + let mut chunk: [u8; 2] = [0; 2]; + + // test non-aligned chunk reading + let mut r = BitReader::endian(data, BigEndian); + assert_eq!(r.read::<2, u8>().unwrap(), 0b10); + r.read_bytes(&mut chunk).unwrap(); + assert_eq!(&chunk, &[0b11_0001_11, 0b10_1101_00]); + assert_eq!(r.read::<14, u16>().unwrap(), 0b11_1011_1100_0001); + + // test the smallest chunk + let mut chunk = 0; + let mut r = BitReader::endian(data, BigEndian); + assert_eq!(r.read::<2, u8>().unwrap(), 0b10); + r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); + assert_eq!(chunk, 0b11_0001_11); + r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); + assert_eq!(chunk, 0b10_1101_00); + assert_eq!(r.read::<14, u16>().unwrap(), 0b11_1011_1100_0001); + + // test a larger chunk + let data = include_bytes!("random.bin"); + let mut chunk: [u8; 127] = [0; 127]; + + let mut r = BitReader::endian(data.as_slice(), BigEndian); + assert_eq!(r.read::<3, u8>().unwrap(), 0b000); + r.read_bytes(&mut chunk).unwrap(); + assert_eq!( + chunk.as_slice(), + include_bytes!("random-3be.bin").as_slice() + ); + assert_eq!(r.read::<5, u8>().unwrap(), 0b10110); +} + +#[test] +fn test_reader_le() { + use bitstream_io::{BitRead, BitReader, LittleEndian}; + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // reading individual bits + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), false); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_bit().unwrap(), true); + + // reading unsigned values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.byte_aligned()); + assert_eq!(r.read_var::(2).unwrap(), 1); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(3).unwrap(), 4); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(5).unwrap(), 13); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(3).unwrap(), 3); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(19).unwrap(), 0x609DF); + assert!(r.byte_aligned()); + assert!(r.read_var::(1).is_err()); + + // reading const unsigned values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.byte_aligned()); + assert_eq!(r.read::<2, u32>().unwrap(), 1); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<3, u32>().unwrap(), 4); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<5, u32>().unwrap(), 13); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<3, u32>().unwrap(), 3); + assert!(!r.byte_aligned()); + assert_eq!(r.read::<19, u32>().unwrap(), 0x609DF); + assert!(r.byte_aligned()); + assert!(r.read::<1, u32>().is_err()); + + // 16-bit values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read::<1, u8>().unwrap(), 1); + assert_eq!(r.read::<14, u16>().unwrap(), 0b1101_1011_0110_00); + assert_eq!(r.read::<16, u16>().unwrap(), 0b1000_0010_0111_0111); + assert_eq!(r.read::<1, u8>().unwrap(), 1); + + // skipping bits + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_var::(2).unwrap(), 1); + assert!(r.skip(3).is_ok()); + assert_eq!(r.read_var::(5).unwrap(), 13); + assert!(r.skip(3).is_ok()); + assert_eq!(r.read_var::(19).unwrap(), 0x609DF); + + // reading signed values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_signed_var::(2).unwrap(), 1); + assert_eq!(r.read_signed_var::(3).unwrap(), -4); + assert_eq!(r.read_signed_var::(5).unwrap(), 13); + assert_eq!(r.read_signed_var::(3).unwrap(), 3); + assert_eq!(r.read_signed_var::(19).unwrap(), -128545); + + // reading const signed values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_signed::<2, i32>().unwrap(), 1); + assert_eq!(r.read_signed::<3, i32>().unwrap(), -4); + assert_eq!(r.read_signed::<5, i32>().unwrap(), 13); + assert_eq!(r.read_signed::<3, i32>().unwrap(), 3); + assert_eq!(r.read_signed::<19, i32>().unwrap(), -128545); + + // reading unary 0 values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_unary::<0>().unwrap(), 1); + assert_eq!(r.read_unary::<0>().unwrap(), 0); + assert_eq!(r.read_unary::<0>().unwrap(), 0); + assert_eq!(r.read_unary::<0>().unwrap(), 2); + assert_eq!(r.read_unary::<0>().unwrap(), 2); + + // reading unary 1 values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + assert_eq!(r.read_unary::<1>().unwrap(), 3); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + assert_eq!(r.read_unary::<1>().unwrap(), 1); + assert_eq!(r.read_unary::<1>().unwrap(), 0); + + // byte aligning + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert_eq!(r.read_var::(3).unwrap(), 1); + r.byte_align(); + assert_eq!(r.read_var::(3).unwrap(), 5); + r.byte_align(); + r.byte_align(); + assert_eq!(r.read_var::(8).unwrap(), 59); + r.byte_align(); + assert_eq!(r.read_var::(4).unwrap(), 1); + + // reading bytes, aligned + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + let mut sub_data = [0; 2]; + assert!(r.read_bytes(&mut sub_data).is_ok()); + assert_eq!(&sub_data, b"\xB1\xED"); + + // reading bytes, un-aligned + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + let mut sub_data = [0; 2]; + assert_eq!(r.read_var::(4).unwrap(), 1); + assert!(r.read_bytes(&mut sub_data).is_ok()); + assert_eq!(&sub_data, b"\xDB\xBE"); +} + +#[test] +fn test_edge_cases_le() { + use bitstream_io::{BitRead, BitReader, LittleEndian}; + + let data: Vec = vec![ + 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 128, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, + 255, 255, 127, + ]; + + // 0 bit reads + let mut r = BitReader::endian([255; 1].as_slice(), LittleEndian); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(0).unwrap(), 0); + assert_eq!(r.read_var::(8).unwrap(), 255); + + let mut r = BitReader::endian([255; 1].as_slice(), LittleEndian); + assert_eq!(r.read::<0, u8>().unwrap(), 0); + assert_eq!(r.read::<0, u16>().unwrap(), 0); + assert_eq!(r.read::<0, u32>().unwrap(), 0); + assert_eq!(r.read::<0, u64>().unwrap(), 0); + assert_eq!(r.read::<8, u8>().unwrap(), 255); + + let mut r = BitReader::endian([255; 1].as_slice(), LittleEndian); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + assert!(r.read_signed_var::(0).is_err()); + + // unsigned 32 and 64-bit values + let mut r = BitReader::endian(data.as_slice(), LittleEndian); + assert_eq!(r.read_var::(32).unwrap(), 0); + assert_eq!(r.read_var::(32).unwrap(), 4294967295); + assert_eq!(r.read_var::(32).unwrap(), 2147483648); + assert_eq!(r.read_var::(32).unwrap(), 2147483647); + assert_eq!(r.read_var::(64).unwrap(), 0); + assert_eq!(r.read_var::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); + assert_eq!(r.read_var::(64).unwrap(), 9223372036854775808); + assert_eq!(r.read_var::(64).unwrap(), 9223372036854775807); + + let mut r = BitReader::endian(data.as_slice(), LittleEndian); + assert_eq!(r.read::<32, u32>().unwrap(), 0); + assert_eq!(r.read::<32, u32>().unwrap(), 4294967295); + assert_eq!(r.read::<32, u32>().unwrap(), 2147483648); + assert_eq!(r.read::<32, u32>().unwrap(), 2147483647); + assert_eq!(r.read::<64, u64>().unwrap(), 0); + assert_eq!(r.read::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); + assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775808); + assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775807); + + let mut r = BitReader::endian(data.as_slice(), LittleEndian); + assert_eq!(r.read_signed_var::(32).unwrap(), 0); + assert_eq!(r.read_signed_var::(32).unwrap(), -1); + assert_eq!(r.read_signed_var::(32).unwrap(), -2147483648); + assert_eq!(r.read_signed_var::(32).unwrap(), 2147483647); + assert_eq!(r.read_signed_var::(64).unwrap(), 0); + assert_eq!(r.read_signed_var::(64).unwrap(), -1); + assert_eq!(r.read_signed_var::(64).unwrap(), -9223372036854775808); + assert_eq!(r.read_signed_var::(64).unwrap(), 9223372036854775807); + + let mut r = BitReader::endian(data.as_slice(), LittleEndian); + assert_eq!(r.read_signed::<32, i32>().unwrap(), 0); + assert_eq!(r.read_signed::<32, i32>().unwrap(), -1); + assert_eq!(r.read_signed::<32, i32>().unwrap(), -2147483648); + assert_eq!(r.read_signed::<32, i32>().unwrap(), 2147483647); + assert_eq!(r.read_signed::<64, i64>().unwrap(), 0); + assert_eq!(r.read_signed::<64, i64>().unwrap(), -1); + assert_eq!(r.read_signed::<64, i64>().unwrap(), -9223372036854775808); + assert_eq!(r.read_signed::<64, i64>().unwrap(), 9223372036854775807); +} + +#[test] +fn test_reader_huffman_le() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BitRead, BitReader, LittleEndian}; + + define_huffman_tree!(SomeTree : i32 = [[[4, 3], 2], [1, 0]]); + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 3); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 0); + assert_eq!(r.read_huffman::().unwrap(), 1); + assert_eq!(r.read_huffman::().unwrap(), 2); + assert_eq!(r.read_huffman::().unwrap(), 4); + assert_eq!(r.read_huffman::().unwrap(), 3); +} + +#[test] +fn test_read_chunks_le() { + use bitstream_io::{BitRead, BitReader, LittleEndian}; + + let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; + let mut chunk: [u8; 2] = [0; 2]; + + // test non-aligned chunk reading + let mut r = BitReader::endian(data, LittleEndian); + assert_eq!(r.read::<2, u8>().unwrap(), 0b01); + r.read_bytes(&mut chunk).unwrap(); + assert_eq!(&chunk, &[0b01_1011_00, 0b11_1110_11]); + assert_eq!(r.read::<14, u16>().unwrap(), 0b1100_0001_0011_10); + + // test the smallest chunk + let mut chunk = 0; + let mut r = BitReader::endian(data, LittleEndian); + assert_eq!(r.read::<2, u8>().unwrap(), 0b01); + r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); + assert_eq!(chunk, 0b01_1011_00); + r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); + assert_eq!(chunk, 0b11_1110_11); + assert_eq!(r.read::<14, u16>().unwrap(), 0b1100_0001_0011_10); + + // test a larger chunk + let data = include_bytes!("random.bin"); + let mut chunk: [u8; 127] = [0; 127]; + + let mut r = BitReader::endian(data.as_slice(), LittleEndian); + assert_eq!(r.read::<3, u8>().unwrap(), 0b010); + r.read_bytes(&mut chunk).unwrap(); + assert_eq!( + chunk.as_slice(), + include_bytes!("random-3le.bin").as_slice() + ); + assert_eq!(r.read::<5, u8>().unwrap(), 0b00110); +} + +#[test] +fn test_reader_io_errors_be() { + use bitstream_io::{BigEndian, BitRead, BitReader}; + use io::ErrorKind; + + let actual_data: [u8; 1] = [0xB1]; + + // individual bits + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert_eq!(r.read_bit().unwrap_err().kind(), ErrorKind::UnexpectedEof); + + // skipping bits + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_var::(7).is_ok()); + assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); + + // signed values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_signed_var::(2).is_ok()); + assert!(r.read_signed_var::(3).is_ok()); + assert_eq!( + r.read_signed_var::(5).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_signed::<2, i32>().is_ok()); + assert!(r.read_signed::<3, i32>().is_ok()); + assert_eq!( + r.read_signed::<5, i32>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // unary 0 values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert_eq!( + r.read_unary::<0>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // unary 1 values + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert_eq!( + r.read_unary::<1>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // reading bytes, aligned + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + let mut sub_data = [0; 2]; + assert_eq!( + r.read_bytes(&mut sub_data).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // reading bytes, un-aligned + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + let mut sub_data = [0; 2]; + assert!(r.read_var::(4).is_ok()); + assert_eq!( + r.read_bytes(&mut sub_data).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); +} + +#[test] +fn test_reader_io_errors_le() { + use bitstream_io::{BitRead, BitReader, LittleEndian}; + use io::ErrorKind; + + let actual_data: [u8; 1] = [0xB1]; + + // individual bits + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert!(r.read_bit().is_ok()); + assert_eq!(r.read_bit().unwrap_err().kind(), ErrorKind::UnexpectedEof); + + // skipping bits + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_var::(7).is_ok()); + assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); + + // signed values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_signed_var::(2).is_ok()); + assert!(r.read_signed_var::(3).is_ok()); + assert_eq!( + r.read_signed_var::(5).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_signed::<2, i32>().is_ok()); + assert!(r.read_signed::<3, i32>().is_ok()); + assert_eq!( + r.read_signed::<5, i32>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // unary 0 values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert!(r.read_unary::<0>().is_ok()); + assert_eq!( + r.read_unary::<0>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // unary 1 values + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert!(r.read_unary::<1>().is_ok()); + assert_eq!( + r.read_unary::<1>().unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // reading bytes, aligned + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + let mut sub_data = [0; 2]; + assert_eq!( + r.read_bytes(&mut sub_data).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); + + // reading bytes, un-aligned + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + let mut sub_data = [0; 2]; + assert!(r.read_var::(4).is_ok()); + assert_eq!( + r.read_bytes(&mut sub_data).unwrap_err().kind(), + ErrorKind::UnexpectedEof + ); +} + +#[test] +fn test_reader_bits_errors() { + use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; + use io::ErrorKind; + let actual_data = [0u8; 10]; + + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + + assert_eq!( + r.read_var::(9).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(17).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(33).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(65).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + assert_eq!( + r.read_signed_var::(9).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(17).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(33).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(65).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + + assert_eq!( + r.read_var::(9).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(17).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(33).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_var::(65).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + assert_eq!( + r.read_signed_var::(9).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(17).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(33).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + r.read_signed_var::(65).unwrap_err().kind(), + ErrorKind::InvalidInput + ); +} + +#[test] +fn test_clone() { + use bitstream_io::{BigEndian, BitRead, BitReader}; + + // Reading unsigned examples, cloning while unaligned. + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + assert!(r.byte_aligned()); + assert_eq!(r.read_var::(4).unwrap(), 0xB); + let mut r2 = r.clone(); + assert!(!r.byte_aligned()); + assert_eq!(r.read_var::(4).unwrap(), 0x1); + assert_eq!(r.read_var::(8).unwrap(), 0xED); + assert!(!r2.byte_aligned()); + assert_eq!(r2.read_var::(4).unwrap(), 0x1); + assert_eq!(r2.read_var::(8).unwrap(), 0xED); + + // Can still instantiate a BitReader when the backing std::io::Read is + // !Clone. + struct NotCloneRead<'a>(&'a [u8]); + impl<'a> io::Read for NotCloneRead<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + } + let _r = BitReader::endian(NotCloneRead(&actual_data[..]), BigEndian); +} + +#[test] +fn test_read_bytes() { + use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); + let read_data: [u8; 4] = r.read_to().unwrap(); + assert_eq!(actual_data, read_data); + + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); + let read_data: [u8; 4] = r.read_to().unwrap(); + assert_eq!(actual_data, read_data); +} + +#[test] +fn test_large_reads() { + use bitstream_io::{BigEndian, BitRead, BitReader, ByteRead, ByteReader, LittleEndian}; + + for size in [0, 1, 4096, 4097, 10000] { + let input = (0..255).cycle().take(size).collect::>(); + assert_eq!(input.len(), size); + + let mut r = BitReader::endian(input.as_slice(), BigEndian); + let output = r.read_to_vec(size).unwrap(); + assert_eq!(input, output); + + let mut r = BitReader::endian(input.as_slice(), LittleEndian); + let output = r.read_to_vec(size).unwrap(); + assert_eq!(input, output); + + let mut r = ByteReader::endian(input.as_slice(), BigEndian); + let output = r.read_to_vec(size).unwrap(); + assert_eq!(input, output); + + let mut r = ByteReader::endian(input.as_slice(), LittleEndian); + let output = r.read_to_vec(size).unwrap(); + assert_eq!(input, output); + } + + let input: [u8; 5] = [0, 0, 0, 0, 0]; + + let mut r = BitReader::endian(input.as_slice(), BigEndian); + assert!(r.read_to_vec(usize::MAX).is_err()); + + let mut r = BitReader::endian(input.as_slice(), LittleEndian); + assert!(r.read_to_vec(usize::MAX).is_err()); + + let mut r = ByteReader::endian(input.as_slice(), BigEndian); + assert!(r.read_to_vec(usize::MAX).is_err()); + + let mut r = ByteReader::endian(input.as_slice(), LittleEndian); + assert!(r.read_to_vec(usize::MAX).is_err()); +} + +#[test] +fn test_bitcount_read() { + use bitstream_io::{BigEndian, BitCount, BitRead, BitReader}; + + // 1 bit count - reading 1 bit + let bytes = &[0b1_1_000000]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b1>().unwrap(); + assert_eq!(count, BitCount::new::<1>()); + assert_eq!(reader.read_counted::<1, u8>(count).unwrap(), 0b1); + + // 2 bits count - reading 3 bits + let bytes = &[0b11_111_000]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b11>().unwrap(); + assert_eq!(count, BitCount::new::<0b11>()); + assert_eq!(reader.read_counted::<0b11, u8>(count).unwrap(), 0b111); + + // 3 bits count - reading 7 bits + let bytes = &[0b111_11111, 0b11_000000]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b111>().unwrap(); + assert_eq!(count, BitCount::new::<0b111>()); + assert_eq!(reader.read_counted::<0b111, u8>(count).unwrap(), 0b11111_11); + + // 4 bits count - reading 15 bits + let bytes = &[0b1111_1111, 0b11111111, 0b111_00000]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b1111>().unwrap(); + assert_eq!(count, BitCount::new::<0b1111>()); + assert_eq!( + reader.read_counted::<0b1111, u16>(count).unwrap(), + 0b1111_11111111_111 + ); + + // 5 bits count - reading 31 bits + let bytes = &[0b11111_111, 0b11111111, 0b11111111, 0b11111111, 0b1111_0000]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b11111>().unwrap(); + assert_eq!(count, BitCount::new::<0b11111>()); + assert_eq!( + reader.read_counted::<0b11111, u32>(count).unwrap(), + 0b111_11111111_11111111_11111111_1111, + ); + + // 6 bits count - reading 63 bits + let bytes = &[ + 0b111111_11, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111_000, + ]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b111111>().unwrap(); + assert_eq!(count, BitCount::new::<0b111111>()); + assert_eq!( + reader.read_counted::<0b111111, u64>(count).unwrap(), + 0b11_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111, + ); + + // 7 bits count - reading 127 bits + let bytes = &[ + 0b1111111_1, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b111111_00, + ]; + let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); + let count = reader.read_count::<0b1111111>().unwrap(); + assert_eq!(count, BitCount::new::<0b1111111>()); + assert_eq!( + reader.read_counted::<0b1111111, u128>(count).unwrap(), + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + ); + + // We have to stop here because no primitive type gets any larger. + // So while BitCount technically extends out to 32 bits, + // it's not practical to get anywhere near that. +} + +#[test] +fn test_nonzero_reads() { + use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; + use core::num::NonZero; + + let data: &[u8] = &[0b001_00000, 0]; + + assert_eq!( + BitReader::endian(data, BigEndian).read::<3, u8>().unwrap(), + 1, + ); + assert_eq!( + BitReader::endian(data, BigEndian) + .read::<3, NonZero>() + .unwrap() + .get(), + 2, + ); + assert_eq!( + BitReader::endian(data, BigEndian) + .read_var::(3) + .unwrap(), + 1, + ); + assert_eq!( + BitReader::endian(data, BigEndian) + .read_var::>(3) + .unwrap() + .get(), + 2, + ); + assert!(BitReader::endian(data, BigEndian) + .read_var::>(8) + .is_err()); + + let data: &[u8] = &[0b00000_001, 0]; + + assert_eq!( + BitReader::endian(data, LittleEndian) + .read::<3, u8>() + .unwrap(), + 1, + ); + assert_eq!( + BitReader::endian(data, LittleEndian) + .read::<3, NonZero>() + .unwrap() + .get(), + 2, + ); + assert_eq!( + BitReader::endian(data, LittleEndian) + .read_var::(3) + .unwrap(), + 1, + ); + assert_eq!( + BitReader::endian(data, LittleEndian) + .read_var::>(3) + .unwrap() + .get(), + 2, + ); + assert!(BitReader::endian(data, LittleEndian) + .read_var::>(8) + .is_err()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/read_seek.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read_seek.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/read_seek.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/read_seek.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,133 @@ +use bitstream_io::{BigEndian, BitRead, BitReader, Endianness, LittleEndian}; +use std::io::{self, Cursor, SeekFrom}; + +#[test] +fn test_reader_pos_be() -> io::Result<()> { + test_reader_pos::() +} + +#[test] +fn test_reader_pos_le() -> io::Result<()> { + test_reader_pos::() +} + +fn test_reader_pos() -> io::Result<()> { + let actual_data: [u8; 7] = [ + 0b1000_1110, + 0b1000_1110, + 0b1000_1110, + 0b1000_1110, + 0b1000_1110, + 0b1000_1110, + 0b1000_1110, + ]; + let mut r: BitReader<_, E> = BitReader::new(Cursor::new(&actual_data)); + + assert_eq!(r.position_in_bits()?, 0); + r.read_bit()?; + r.read_bit()?; + assert_eq!(r.position_in_bits()?, 2); + let _: u32 = r.read_var(5)?; + assert_eq!(r.position_in_bits()?, 7); + let _: u32 = r.read_var(4)?; + assert_eq!(r.position_in_bits()?, 11); + let mut buf = [0u8; 2]; + r.read_bytes(&mut buf)?; + assert_eq!(r.position_in_bits()?, 27); + r.read_bit()?; + r.read_bit()?; + r.read_bit()?; + r.read_bit()?; + r.read_bit()?; + r.read_bit()?; + r.read_bit()?; + let _: i32 = r.read_signed_var(9)?; + assert_eq!(r.position_in_bits()?, 43); + let _: i32 = r.read_signed_var(5)?; + assert_eq!(r.position_in_bits()?, 48); + + Ok(()) +} + +#[test] +pub fn test_reader_seek_start() -> io::Result<()> { + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); + + r.seek_bits(SeekFrom::Start(0))?; + assert_eq!(r.position_in_bits()?, 0); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.position_in_bits()?, 8); + + r.seek_bits(SeekFrom::Start(2))?; + assert_eq!(r.position_in_bits()?, 2); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.position_in_bits()?, 8); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.position_in_bits()?, 10); + + r.seek_bits(SeekFrom::Start(7))?; + assert_eq!(r.position_in_bits()?, 7); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + + Ok(()) +} + +#[test] +pub fn test_reader_seek_current() -> io::Result<()> { + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); + + r.seek_bits(SeekFrom::Current(2))?; + assert_eq!(r.position_in_bits()?, 2); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + let _: i32 = r.read_signed_var(11)?; + assert_eq!(r.position_in_bits()?, 17); + + r.seek_bits(SeekFrom::Current(-3))?; + assert_eq!(r.position_in_bits()?, 14); + r.skip(10)?; + assert_eq!(r.position_in_bits()?, 24); + r.seek_bits(SeekFrom::Current(0))?; + assert_eq!(r.position_in_bits()?, 24); + + Ok(()) +} + +#[test] +pub fn test_reader_seek_end() -> io::Result<()> { + let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); + + r.seek_bits(SeekFrom::End(7))?; + assert_eq!(r.position_in_bits()?, 25); + assert_eq!(r.read_bit()?, true); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.read_bit()?, false); + assert_eq!(r.position_in_bits()?, 29); + r.seek_bits(SeekFrom::End(0))?; + assert_eq!(r.position_in_bits()?, 32); + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/roundtrip.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/roundtrip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/roundtrip.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/roundtrip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,484 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use bitstream_io::{ + BigEndian, BitRead, BitReader, BitWrite, BitWriter, Endianness, Integer, LittleEndian, + Primitive, +}; + +fn roundtrip() { + /*unsigned values*/ + for bits in 1..17 { + let max = 1 << bits; + let mut output: Vec = Vec::with_capacity(max); + { + let mut writer = BitWriter::<_, E>::new(&mut output); + for value in 0..max { + writer.write_var(bits, value as u32).unwrap(); + } + writer.byte_align().unwrap(); + } + { + let mut reader = BitReader::<_, E>::new(output.as_slice()); + for value in 0..max { + assert_eq!(reader.read_var::(bits).unwrap(), value as u32); + } + } + } + + /*signed values*/ + for bits in 2..17 { + let min = -1i32 << (bits - 1); + let max = 1i32 << (bits - 1); + let mut output: Vec = Vec::with_capacity(max as usize); + { + let mut writer = BitWriter::<_, E>::new(&mut output); + for value in min..max { + writer.write_signed_var(bits, value as i32).unwrap(); + } + writer.byte_align().unwrap(); + } + { + let mut reader = BitReader::<_, E>::new(output.as_slice()); + for value in min..max { + assert_eq!(reader.read_signed_var::(bits).unwrap(), value as i32); + } + } + } +} + +#[test] +fn test_rountrip_be() { + roundtrip::(); +} + +#[test] +fn test_roundtrip_le() { + roundtrip::(); +} + +fn wide_roundtrip(start: I, end: I, increment: I) +where + E: Endianness, + I: Integer + + Copy + + std::fmt::Debug + + std::ops::AddAssign + + std::cmp::PartialEq + + std::cmp::PartialOrd, +{ + let mut w = BitWriter::, E>::new(vec![]); + // add an extra bit to check non byte-aligned values + w.write_bit(true).unwrap(); + let mut v = start; + while v < end { + w.write::(v).unwrap(); + v += increment; + } + w.byte_align().unwrap(); + + let vec = w.into_writer(); + let mut r = BitReader::<_, E>::new(vec.as_slice()); + assert_eq!(r.read_bit().unwrap(), true); + let mut v = start; + while v < end { + assert_eq!(r.read::().unwrap(), v); + v += increment; + } +} + +#[test] +fn test_roundtrip_u7_be() { + wide_roundtrip::<7, BigEndian, u8>(u8::MIN, u8::MAX / 2, 1); +} + +#[test] +fn test_roundtrip_u7_le() { + wide_roundtrip::<7, LittleEndian, u8>(u8::MIN, u8::MAX / 2, 1); +} + +#[test] +fn test_roundtrip_u8_be() { + wide_roundtrip::<8, BigEndian, u8>(u8::MIN, u8::MAX, 1); +} + +#[test] +fn test_roundtrip_u8_le() { + wide_roundtrip::<8, LittleEndian, u8>(u8::MIN, u8::MAX, 1); +} + +#[test] +fn test_roundtrip_i8_be() { + wide_roundtrip::<8, BigEndian, i8>(i8::MIN, i8::MAX, 1); +} + +#[test] +fn test_roundtrip_i8_le() { + wide_roundtrip::<8, LittleEndian, i8>(i8::MIN, i8::MAX, 1); +} + +#[test] +fn test_roundtrip_u9_be() { + wide_roundtrip::<9, BigEndian, u16>(u16::MIN, u8::MAX as u16 * 2, 1); +} + +#[test] +fn test_roundtrip_u9_le() { + wide_roundtrip::<9, LittleEndian, u16>(u16::MIN, u8::MAX as u16 * 2, 1); +} + +#[test] +fn test_roundtrip_u15_be() { + wide_roundtrip::<15, BigEndian, u16>(u16::MIN, u16::MAX / 2, 1); +} + +#[test] +fn test_roundtrip_u15_le() { + wide_roundtrip::<15, LittleEndian, u16>(u16::MIN, u16::MAX / 2, 1); +} + +#[test] +fn test_roundtrip_u16_be() { + wide_roundtrip::<16, BigEndian, u16>(u16::MIN, u16::MAX, 1); +} + +#[test] +fn test_roundtrip_u16_le() { + wide_roundtrip::<16, LittleEndian, u16>(u16::MIN, u16::MAX, 1); +} + +#[test] +fn test_roundtrip_i16_be() { + wide_roundtrip::<16, BigEndian, i16>(i16::MIN, i16::MAX, 1); +} + +#[test] +fn test_roundtrip_i16_le() { + wide_roundtrip::<16, LittleEndian, i16>(i16::MIN, i16::MAX, 1); +} + +#[test] +fn test_roundtrip_u32_be() { + wide_roundtrip::<32, BigEndian, u32>(u32::MIN, u32::MAX - 65536, 65536); +} + +#[test] +fn test_roundtrip_u32_le() { + wide_roundtrip::<32, LittleEndian, u32>(u32::MIN, u32::MAX - 65536, 65536); +} + +#[test] +fn test_roundtrip_i32_be() { + wide_roundtrip::<32, BigEndian, i32>(i32::MIN, i32::MAX - 65536, 65536); +} + +#[test] +fn test_roundtrip_i32_le() { + wide_roundtrip::<32, LittleEndian, i32>(i32::MIN, i32::MAX - 65536, 65536); +} + +#[test] +fn test_roundtrip_u64_be() { + wide_roundtrip::<64, BigEndian, u64>(u64::MIN, u64::MAX - u64::MAX / 65536, u64::MAX / 65536); +} + +#[test] +fn test_roundtrip_u64_le() { + wide_roundtrip::<64, LittleEndian, u64>( + u64::MIN, + u64::MAX - u64::MAX / 65536, + u64::MAX / 65536, + ); +} + +#[test] +fn test_roundtrip_i64_be() { + wide_roundtrip::<64, BigEndian, i64>(i64::MIN, i64::MAX - i64::MAX / 65536, i64::MAX / 65536); +} + +#[test] +fn test_roundtrip_i64_le() { + wide_roundtrip::<64, LittleEndian, i64>( + i64::MIN, + i64::MAX - i64::MAX / 65536, + i64::MAX / 65536, + ); +} + +#[test] +fn test_roundtrip_u128_be() { + wide_roundtrip::<128, BigEndian, u128>( + u128::MIN, + u128::MAX - u128::MAX / 65536, + u128::MAX / 65536, + ); +} + +#[test] +fn test_roundtrip_u128_le() { + wide_roundtrip::<128, LittleEndian, u128>( + u128::MIN, + u128::MAX - u128::MAX / 65536, + u128::MAX / 65536, + ); +} + +#[test] +fn test_roundtrip_i128_be() { + wide_roundtrip::<128, BigEndian, i128>( + i128::MIN, + i128::MAX - i128::MAX / 65536, + i128::MAX / 65536, + ); +} + +#[test] +fn test_roundtrip_i128_le() { + wide_roundtrip::<128, LittleEndian, i128>( + i128::MIN, + i128::MAX - i128::MAX / 65536, + i128::MAX / 65536, + ); +} + +fn unary() { + let mut output: Vec = Vec::new(); + { + let mut writer = BitWriter::<_, E>::new(&mut output); + for value in 0..1024 { + writer.write_unary::<0>(value).unwrap(); + } + writer.byte_align().unwrap(); + } + { + let mut c = output.as_slice(); + let mut reader = BitReader::<_, E>::new(&mut c); + for value in 0..1024 { + assert_eq!(reader.read_unary::<0>().unwrap(), value); + } + } + + let mut output: Vec = Vec::new(); + { + let mut writer = BitWriter::<_, E>::new(&mut output); + for value in 0..1024 { + writer.write_unary::<1>(value).unwrap(); + } + writer.byte_align().unwrap(); + } + { + let mut c = output.as_slice(); + let mut reader = BitReader::<_, E>::new(&mut c); + for value in 0..1024 { + assert_eq!(reader.read_unary::<1>().unwrap(), value); + } + } +} + +#[test] +fn test_unary_roundtrip_be() { + unary::() +} + +#[test] +fn test_unary_roundtrip_le() { + unary::() +} + +fn float() +where + E: Endianness, + P: Primitive + From + core::fmt::Debug + core::cmp::PartialEq, +{ + let mut output: Vec = Vec::new(); + { + let mut writer = BitWriter::<_, E>::new(&mut output); + // these values should all be exact in floating-point + for value in 0..1024 { + writer.write_from(P::from(value)).unwrap(); + } + writer.byte_align().unwrap(); + } + { + let mut c = output.as_slice(); + let mut reader = BitReader::<_, E>::new(&mut c); + for value in 0..1024 { + assert_eq!(reader.read_to::

().unwrap(), P::from(value)); + } + } +} + +#[test] +fn test_f32_roundtrip_be() { + float::() +} + +#[test] +fn test_f64_roundtrip_be() { + float::() +} + +#[test] +fn test_f32_roundtrip_le() { + float::() +} + +#[test] +fn test_f64_roundtrip_le() { + float::() +} + +#[test] +fn test_auto_signedness() { + use bitstream_io::{ + BigEndian, BitRead, BitReader, BitWrite, BitWriter, Endianness, Integer, LittleEndian, + SignedInteger, UnsignedInteger, + }; + + macro_rules! define_roundtrip { + ($n:ident, $i:ident, $w:ident, $r:ident) => { + fn $n( + mut start: I, + end: I, + bits: u32, + ) { + let mut w: BitWriter<_, E> = BitWriter::new(Vec::new()); + w.write_bit(true).unwrap(); + let mut i = start; + while i < end { + w.$w(bits, i).unwrap(); + i += I::ONE; + } + w.$w(bits, end).unwrap(); + + w.byte_align().unwrap(); + + let v = w.into_writer(); + let mut r: BitReader<_, E> = BitReader::new(v.as_slice()); + assert_eq!(r.read_bit().unwrap(), true); + while start < end { + assert_eq!(r.$r::(bits).unwrap(), start); + start += I::ONE; + } + assert_eq!(r.$r::(bits).unwrap(), end); + } + }; + } + + define_roundtrip!( + test_writer_unsigned, + UnsignedInteger, + write_var, + read_unsigned_var + ); + test_writer_unsigned::<_, BigEndian>(u8::MIN, u8::MAX, 8); + test_writer_unsigned::<_, LittleEndian>(u8::MIN, u8::MAX, 8); + + define_roundtrip!( + test_writer_signed, + SignedInteger, + write_var, + read_signed_var + ); + test_writer_signed::<_, BigEndian>(i8::MIN, i8::MAX, 8); + test_writer_signed::<_, LittleEndian>(i8::MIN, i8::MAX, 8); + + define_roundtrip!( + test_reader_unsigned, + UnsignedInteger, + write_unsigned_var, + read_var + ); + test_reader_unsigned::<_, BigEndian>(u8::MIN, u8::MAX, 8); + test_reader_unsigned::<_, LittleEndian>(u8::MIN, u8::MAX, 8); + + define_roundtrip!( + test_reader_signed, + SignedInteger, + write_signed_var, + read_var + ); + test_reader_signed::<_, BigEndian>(i8::MIN, i8::MAX, 8); + test_reader_signed::<_, LittleEndian>(i8::MIN, i8::MAX, 8); +} + +#[test] +fn test_bit_count() { + use bitstream_io::{BigEndian, BitRead, BitReader, BitWrite, BitWriter}; + + let data: &[u8] = &[0b1111_0000]; + + // read a count from a 4-bit field + let count = BitReader::endian(data, BigEndian) + .read_count::<0b1111>() + .unwrap(); + assert_eq!(u32::from(count), 0b1111); + + // increment it by 1 + let count = count.try_map::<16, _>(|i| i.checked_add(1)).unwrap(); + assert_eq!(u32::from(count), 0b1111 + 1); + + // decrement it by 1 + let count = count.try_map::<0b1111, _>(|i| i.checked_sub(1)).unwrap(); + assert_eq!(u32::from(count), 0b1111); + + // write the count back to disk + let mut w = BitWriter::endian(vec![], BigEndian); + w.write_count::<0b1111>(count).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), data); +} + +fn test_primitives() { + use bitstream_io::{BitRead, BitReader, BitWrite, BitWriter}; + + // try a lot of primitive values, shifted by 1 bit + let mut w = BitWriter::, E>::new(vec![]); + w.write_bit(true).unwrap(); + w.write_from::(u8::MAX - 10).unwrap(); + w.write_from::(u16::MAX - 10).unwrap(); + w.write_from::(u32::MAX - 10).unwrap(); + w.write_from::(u64::MAX - 10).unwrap(); + w.write_from::(u128::MAX - 10).unwrap(); + w.write_from::(i8::MAX - 10).unwrap(); + w.write_from::(i16::MAX - 10).unwrap(); + w.write_from::(i32::MAX - 10).unwrap(); + w.write_from::(i64::MAX - 10).unwrap(); + w.write_from::(i128::MAX - 10).unwrap(); + w.write_from::(1.0).unwrap(); + w.write_from::(2.0).unwrap(); + w.write_from::<[u8; 3]>([9, 8, 7]).unwrap(); + w.byte_align().unwrap(); + + let v = w.into_writer(); + let mut r = BitReader::<&[u8], E>::new(v.as_slice()); + assert_eq!(r.read_bit().unwrap(), true); + assert_eq!(r.read_to::().unwrap(), u8::MAX - 10); + assert_eq!(r.read_to::().unwrap(), u16::MAX - 10); + assert_eq!(r.read_to::().unwrap(), u32::MAX - 10); + assert_eq!(r.read_to::().unwrap(), u64::MAX - 10); + assert_eq!(r.read_to::().unwrap(), u128::MAX - 10); + assert_eq!(r.read_to::().unwrap(), i8::MAX - 10); + assert_eq!(r.read_to::().unwrap(), i16::MAX - 10); + assert_eq!(r.read_to::().unwrap(), i32::MAX - 10); + assert_eq!(r.read_to::().unwrap(), i64::MAX - 10); + assert_eq!(r.read_to::().unwrap(), i128::MAX - 10); + assert_eq!(r.read_to::().unwrap(), 1.0); + assert_eq!(r.read_to::().unwrap(), 2.0); + assert_eq!(r.read_to::<[u8; 3]>().unwrap(), [9, 8, 7]); +} + +#[test] +fn test_primitives_be() { + test_primitives::() +} + +#[test] +fn test_primitives_le() { + test_primitives::() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/write.rs clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bitstream-io/tests/write.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bitstream-io/tests/write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2116 @@ +// Copyright 2017 Brian Langenberger +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use bitstream_io::{BigEndian, BitWrite, BitWriter}; +use std::io; + +#[test] +fn test_writer_be() { + use bitstream_io::{BigEndian, BitWrite, BitWriter}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // writing individual bits + let mut w = BitWriter::endian(Vec::with_capacity(2), BigEndian); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data[0..2]); + + // writing unsigned values + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + assert!(w.byte_aligned()); + w.write_var(2, 2u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 6u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 7u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 5u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x53BC1u32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + assert!(w.byte_aligned()); + w.write::<2, u32>(2).unwrap(); + assert!(!w.byte_aligned()); + w.write::<3, u32>(6).unwrap(); + assert!(!w.byte_aligned()); + w.write::<5, u32>(7).unwrap(); + assert!(!w.byte_aligned()); + w.write::<3, u32>(5).unwrap(); + assert!(!w.byte_aligned()); + w.write::<19, u32>(0x53BC1).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + assert!(w.byte_aligned()); + w.write::<1, u8>(1).unwrap(); + assert!(!w.byte_aligned()); + w.write::<14, u16>(0b0110_0011_1101_10).unwrap(); + assert!(!w.byte_aligned()); + w.write::<16, u16>(0b1001_1101_1110_0000).unwrap(); + assert!(!w.byte_aligned()); + w.write::<1, u8>(1).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing signed values + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_signed_var(2, -2).unwrap(); + w.write_signed_var(3, -2).unwrap(); + w.write_signed_var(5, 7).unwrap(); + w.write_signed_var(3, -3).unwrap(); + w.write_signed_var(19, -181311).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_signed::<2, i32>(-2).unwrap(); + w.write_signed::<3, i32>(-2).unwrap(); + w.write_signed::<5, i32>(7).unwrap(); + w.write_signed::<3, i32>(-3).unwrap(); + w.write_signed::<19, i32>(-181311).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing unary 0 values + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(1, 1u32).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing unary 1 values + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(5).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing unsigned vbr + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_unsigned_vbr::<4, _>(11u8).unwrap(); // 001 011 -> <1>011 <0>001 + w.write_unsigned_vbr::<4, _>(238u8).unwrap(); // 011 101 110 -> <1>110 <1>101 <0>011 + w.write_unsigned_vbr::<4, _>(99u8).unwrap(); // 001 100 011 -> <1>011 <1>100 <0>001 + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing signed vbr + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_signed_vbr::<4, _>(-6i16).unwrap(); // 001 011 -> <1>011 <0>001 + w.write_signed_vbr::<4, _>(119i16).unwrap(); // 011 101 110 -> <1>110 <1>101 <0>011 + w.write_signed_vbr::<4, _>(-50i16).unwrap(); // 001 100 011 -> <1>011 <1>100 <0>001 + assert_eq!(w.into_writer().as_slice(), &final_data); + + // byte aligning + let aligned_data = [0xA0, 0xE0, 0x3B, 0xC0]; + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer().as_slice(), &aligned_data); + + // writing bytes, aligned + let final_data = [0xB1, 0xED]; + let mut w = BitWriter::endian(Vec::with_capacity(2), BigEndian); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing bytes, un-aligned + let final_data = [0xBB, 0x1E, 0xD0]; + let mut w = BitWriter::endian(Vec::with_capacity(3), BigEndian); + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_writer_edge_cases_be() { + use bitstream_io::{BigEndian, BitWrite, BitWriter}; + + // 0 bit writes + let mut w = BitWriter::endian(Vec::new(), BigEndian); + w.write_var(0, 0u8).unwrap(); + w.write_var(0, 0u16).unwrap(); + w.write_var(0, 0u32).unwrap(); + w.write_var(0, 0u64).unwrap(); + assert!(w.into_writer().is_empty()); + + let mut w = BitWriter::endian(Vec::new(), BigEndian); + assert!(w.write_signed_var(0, 0i8).is_err()); + assert!(w.write_signed_var(0, 0i16).is_err()); + assert!(w.write_signed_var(0, 0i32).is_err()); + assert!(w.write_signed_var(0, 0i64).is_err()); + assert!(w.into_writer().is_empty()); + + let final_data: Vec = vec![ + 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 127, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, + 255, 255, 255, + ]; + + // unsigned 32 and 64-bit values + let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); + w.write_var(32, 0u32).unwrap(); + w.write_var(32, 4294967295u32).unwrap(); + w.write_var(32, 2147483648u32).unwrap(); + w.write_var(32, 2147483647u32).unwrap(); + w.write_var(64, 0u64).unwrap(); + w.write_var(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); + w.write_var(64, 9223372036854775808u64).unwrap(); + w.write_var(64, 9223372036854775807u64).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); + w.write::<32, u32>(0).unwrap(); + w.write::<32, u32>(4294967295).unwrap(); + w.write::<32, u32>(2147483648).unwrap(); + w.write::<32, u32>(2147483647).unwrap(); + w.write::<64, u64>(0).unwrap(); + w.write::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); + w.write::<64, u64>(9223372036854775808).unwrap(); + w.write::<64, u64>(9223372036854775807).unwrap(); + assert_eq!(w.into_writer(), final_data); + + // signed 32 and 64-bit values + let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); + w.write_signed_var(32, 0i32).unwrap(); + w.write_signed_var(32, -1i32).unwrap(); + w.write_signed_var(32, -2147483648i32).unwrap(); + w.write_signed_var(32, 2147483647i32).unwrap(); + w.write_signed_var(64, 0i64).unwrap(); + w.write_signed_var(64, -1i64).unwrap(); + w.write_signed_var(64, -9223372036854775808i64).unwrap(); + w.write_signed_var(64, 9223372036854775807i64).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); + w.write_signed::<32, i32>(0).unwrap(); + w.write_signed::<32, i32>(-1).unwrap(); + w.write_signed::<32, i32>(-2147483648).unwrap(); + w.write_signed::<32, i32>(2147483647).unwrap(); + w.write_signed::<64, i64>(0).unwrap(); + w.write_signed::<64, i64>(-1).unwrap(); + w.write_signed::<64, i64>(-9223372036854775808).unwrap(); + w.write_signed::<64, i64>(9223372036854775807).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(8, core::i8::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i8::MAX.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(8, core::i8::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i8::MIN.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(16, core::i16::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i16::MAX.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(16, core::i16::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i16::MIN.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(32, core::i32::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i32::MAX.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(32, core::i32::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i32::MIN.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(64, core::i64::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i64::MAX.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(64, core::i64::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i64::MIN.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(128, core::i128::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i128::MAX.to_be_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, BigEndian) + .write_signed_var(128, core::i128::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i128::MIN.to_be_bytes()); +} + +#[test] +fn test_writer_huffman_be() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BigEndian, BitWrite, BitWriter}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); + + let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(2).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_write_chunks_be() { + use bitstream_io::{BigEndian, BitWrite, BitWriter}; + + let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; + + // test non-aligned chunk writing + let mut w = BitWriter::endian(vec![], BigEndian); + w.write::<2, u8>(0b10).unwrap(); + w.write_bytes(&[0b11_0001_11, 0b10_1101_00]).unwrap(); + w.write::<14, u16>(0b11_1011_1100_0001).unwrap(); + assert_eq!(w.into_writer().as_slice(), data); + + // test the smallest chunk + let mut w = BitWriter::endian(vec![], BigEndian); + w.write::<2, u8>(0b10).unwrap(); + w.write_bytes(core::slice::from_ref(&0b11_0001_11)).unwrap(); + w.write_bytes(core::slice::from_ref(&0b10_1101_00)).unwrap(); + w.write::<14, u16>(0b11_1011_1100_0001).unwrap(); + assert_eq!(w.into_writer().as_slice(), data); + + // test a larger chunk + let mut w = BitWriter::endian(vec![], BigEndian); + w.write::<3, u8>(0b000).unwrap(); + w.write_bytes(include_bytes!("random-3be.bin").as_slice()) + .unwrap(); + w.write::<5, u8>(0b10110).unwrap(); + assert_eq!( + w.into_writer().as_slice(), + include_bytes!("random.bin").as_slice() + ); +} + +#[test] +fn test_writer_le() { + use bitstream_io::{BitWrite, BitWriter, LittleEndian}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // writing individual bits + let mut w = BitWriter::endian(Vec::with_capacity(2), LittleEndian); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data[0..2]); + + // writing unsigned values + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + assert!(w.byte_aligned()); + w.write_var(2, 1u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 4u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 13u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 3u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x609DFu32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + assert!(w.byte_aligned()); + w.write::<2, u32>(1).unwrap(); + assert!(!w.byte_aligned()); + w.write::<3, u32>(4).unwrap(); + assert!(!w.byte_aligned()); + w.write::<5, u32>(13).unwrap(); + assert!(!w.byte_aligned()); + w.write::<3, u32>(3).unwrap(); + assert!(!w.byte_aligned()); + w.write::<19, u32>(0x609DF).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + assert!(w.byte_aligned()); + w.write::<1, u8>(1).unwrap(); + assert!(!w.byte_aligned()); + w.write::<14, u16>(0b1101_1011_0110_00).unwrap(); + assert!(!w.byte_aligned()); + w.write::<16, u16>(0b1000_0010_0111_0111).unwrap(); + assert!(!w.byte_aligned()); + w.write::<1, u8>(1).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing signed values + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_signed_var(2, 1).unwrap(); + w.write_signed_var(3, -4).unwrap(); + w.write_signed_var(5, 13).unwrap(); + w.write_signed_var(3, 3).unwrap(); + w.write_signed_var(19, -128545).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_signed::<2, i32>(1).unwrap(); + w.write_signed::<3, i32>(-4).unwrap(); + w.write_signed::<5, i32>(13).unwrap(); + w.write_signed::<3, i32>(3).unwrap(); + w.write_signed::<19, i32>(-128545).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing unary 0 values + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(5).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(2, 3u32).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing unary 1 values + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(5).unwrap(); + w.write_unary::<1>(0).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // byte aligning + let aligned_data = [0x05, 0x07, 0x3B, 0x0C]; + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer().as_slice(), &aligned_data); + + // writing bytes, aligned + let final_data = [0xB1, 0xED]; + let mut w = BitWriter::endian(Vec::with_capacity(2), LittleEndian); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); + + // writing bytes, un-aligned + let final_data = [0x1B, 0xDB, 0x0E]; + let mut w = BitWriter::endian(Vec::with_capacity(3), LittleEndian); + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_writer_edge_cases_le() { + use bitstream_io::{BitWrite, BitWriter, LittleEndian}; + + // 0 bit writes + let mut w = BitWriter::endian(Vec::new(), LittleEndian); + w.write_var(0, 0u8).unwrap(); + w.write_var(0, 0u16).unwrap(); + w.write_var(0, 0u32).unwrap(); + w.write_var(0, 0u64).unwrap(); + assert!(w.into_writer().is_empty()); + + let mut w = BitWriter::endian(Vec::new(), LittleEndian); + assert!(w.write_signed_var(0, 0i8).is_err()); + assert!(w.write_signed_var(0, 0i16).is_err()); + assert!(w.write_signed_var(0, 0i32).is_err()); + assert!(w.write_signed_var(0, 0i64).is_err()); + assert!(w.into_writer().is_empty()); + + let final_data: Vec = vec![ + 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 128, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, + 255, 255, 127, + ]; + + // unsigned 32 and 64-bit values + let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); + w.write_var(32, 0u32).unwrap(); + w.write_var(32, 4294967295u32).unwrap(); + w.write_var(32, 2147483648u32).unwrap(); + w.write_var(32, 2147483647u32).unwrap(); + w.write_var(64, 0u64).unwrap(); + w.write_var(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); + w.write_var(64, 9223372036854775808u64).unwrap(); + w.write_var(64, 9223372036854775807u64).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); + w.write::<32, u32>(0).unwrap(); + w.write::<32, u32>(4294967295).unwrap(); + w.write::<32, u32>(2147483648).unwrap(); + w.write::<32, u32>(2147483647).unwrap(); + w.write::<64, u64>(0).unwrap(); + w.write::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); + w.write::<64, u64>(9223372036854775808).unwrap(); + w.write::<64, u64>(9223372036854775807).unwrap(); + assert_eq!(w.into_writer(), final_data); + + // signed 32 and 64-bit values + let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); + w.write_signed_var(32, 0i32).unwrap(); + w.write_signed_var(32, -1i32).unwrap(); + w.write_signed_var(32, -2147483648i32).unwrap(); + w.write_signed_var(32, 2147483647i32).unwrap(); + w.write_signed_var(64, 0i64).unwrap(); + w.write_signed_var(64, -1i64).unwrap(); + w.write_signed_var(64, -9223372036854775808i64).unwrap(); + w.write_signed_var(64, 9223372036854775807i64).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); + w.write_signed::<32, i32>(0).unwrap(); + w.write_signed::<32, i32>(-1).unwrap(); + w.write_signed::<32, i32>(-2147483648).unwrap(); + w.write_signed::<32, i32>(2147483647).unwrap(); + w.write_signed::<64, i64>(0).unwrap(); + w.write_signed::<64, i64>(-1).unwrap(); + w.write_signed::<64, i64>(-9223372036854775808).unwrap(); + w.write_signed::<64, i64>(9223372036854775807).unwrap(); + assert_eq!(w.into_writer(), final_data); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(8, core::i8::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i8::MAX.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(8, core::i8::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i8::MIN.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(16, core::i16::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i16::MAX.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(16, core::i16::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i16::MIN.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(32, core::i32::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i32::MAX.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(32, core::i32::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i32::MIN.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(64, core::i64::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i64::MAX.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(64, core::i64::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i64::MIN.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(128, core::i128::MAX) + .unwrap(); + } + assert_eq!(bytes, core::i128::MAX.to_le_bytes()); + + let mut bytes = Vec::new(); + { + BitWriter::endian(&mut bytes, LittleEndian) + .write_signed_var(128, core::i128::MIN) + .unwrap(); + } + assert_eq!(bytes, core::i128::MIN.to_le_bytes()); +} + +#[test] +fn test_writer_huffman_le() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BitWrite, BitWriter, LittleEndian}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + define_huffman_tree!(TreeName : i32= [[[4, 3], 2], [1, 0]]); + + let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.write_huffman::(1).unwrap(); + w.write_huffman::(3).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(3).unwrap(); + w.write_var(1, 1u8).unwrap(); + assert_eq!(w.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_write_chunks_le() { + use bitstream_io::{BitWrite, BitWriter, LittleEndian}; + + let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; + + // test non-aligned chunk writing + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write::<2, u8>(0b01).unwrap(); + w.write_bytes(&[0b01_1011_00, 0b11_1110_11]).unwrap(); + w.write::<14, u16>(0b1100_0001_0011_10).unwrap(); + assert_eq!(w.into_writer().as_slice(), data); + + // test the smallest chunk + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write::<2, u8>(0b01).unwrap(); + w.write_bytes(core::slice::from_ref(&0b01_1011_00)).unwrap(); + w.write_bytes(core::slice::from_ref(&0b11_1110_11)).unwrap(); + w.write::<14, u16>(0b1100_0001_0011_10).unwrap(); + assert_eq!(w.into_writer().as_slice(), data); + + // test a larger chunk + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write::<3, u8>(0b010).unwrap(); + w.write_bytes(include_bytes!("random-3le.bin").as_slice()) + .unwrap(); + w.write::<5, u8>(0b00110).unwrap(); + assert_eq!( + w.into_writer().as_slice(), + include_bytes!("random.bin").as_slice() + ); +} + +struct LimitedWriter { + can_write: usize, +} + +impl LimitedWriter { + fn new(max_bytes: usize) -> LimitedWriter { + LimitedWriter { + can_write: max_bytes, + } + } +} + +impl io::Write for LimitedWriter { + fn write(&mut self, buf: &[u8]) -> Result { + let to_write = buf.len().min(self.can_write); + self.can_write -= to_write; + Ok(to_write) + } + + fn flush(&mut self) -> Result<(), io::Error> { + Ok(()) + } +} + +#[test] +fn test_writer_io_errors_be() { + use bitstream_io::{BigEndian, BitWrite, BitWriter}; + use io::ErrorKind; + + // individual bits + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert_eq!(w.write_bit(true).unwrap_err().kind(), ErrorKind::WriteZero); + + // unsigned values + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_var(2, 2u32).is_ok()); + assert!(w.write_var(3, 6u32).is_ok()); + assert!(w.write_var(5, 7u32).is_ok()); + assert!(w.write_var(3, 5u32).is_ok()); + assert_eq!( + w.write_var(19, 0x53BC1u32).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // signed values + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_signed_var(2, -2).is_ok()); + assert!(w.write_signed_var(3, -2).is_ok()); + assert!(w.write_signed_var(5, 7).is_ok()); + assert!(w.write_signed_var(3, -3).is_ok()); + assert_eq!( + w.write_signed_var(19, -181311).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // unary 0 values + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_unary::<0>(1).is_ok()); + assert!(w.write_unary::<0>(2).is_ok()); + assert!(w.write_unary::<0>(0).is_ok()); + assert!(w.write_unary::<0>(0).is_ok()); + assert!(w.write_unary::<0>(4).is_ok()); + assert!(w.write_unary::<0>(2).is_ok()); + assert_eq!( + w.write_unary::<0>(1).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // unary 1 values + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(1).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(3).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(1).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert_eq!( + w.write_unary::<1>(1).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // byte aligning + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_var::(9, 0b111111111).is_ok()); + assert_eq!(w.byte_align().unwrap_err().kind(), ErrorKind::WriteZero); + + // aligned bytes + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert_eq!( + w.write_bytes(b"\xB1\xED").unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // un-aligned bytes + let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); + assert!(w.write_var(4, 11u8).is_ok()); + assert_eq!( + w.write_bytes(b"\xB1\xED").unwrap_err().kind(), + ErrorKind::WriteZero + ); +} + +#[test] +fn test_writer_io_errors_le() { + use bitstream_io::{BitWrite, BitWriter, LittleEndian}; + use io::ErrorKind; + + // individual bits + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(false).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert!(w.write_bit(true).is_ok()); + assert_eq!(w.write_bit(true).unwrap_err().kind(), ErrorKind::WriteZero); + + // unsigned values + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_var(2, 1u32).is_ok()); + assert!(w.write_var(3, 4u32).is_ok()); + assert!(w.write_var(5, 13u32).is_ok()); + assert!(w.write_var(3, 3u32).is_ok()); + assert_eq!( + w.write_var(19, 0x609DFu32).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // signed values + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_signed_var(2, 1).is_ok()); + assert!(w.write_signed_var(3, -4).is_ok()); + assert!(w.write_signed_var(5, 13).is_ok()); + assert!(w.write_signed_var(3, 3).is_ok()); + assert_eq!( + w.write_signed_var(19, -128545).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // unary 0 values + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_unary::<0>(1).is_ok()); + assert!(w.write_unary::<0>(0).is_ok()); + assert!(w.write_unary::<0>(0).is_ok()); + assert!(w.write_unary::<0>(2).is_ok()); + assert!(w.write_unary::<0>(2).is_ok()); + assert!(w.write_unary::<0>(2).is_ok()); + assert_eq!( + w.write_unary::<0>(5).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // unary 1 values + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(3).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(1).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(1).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert!(w.write_unary::<1>(1).is_ok()); + assert!(w.write_unary::<1>(0).is_ok()); + assert_eq!( + w.write_unary::<1>(1).unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // byte aligning + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_var::(9, 0b111111111).is_ok()); + assert_eq!(w.byte_align().unwrap_err().kind(), ErrorKind::WriteZero); + + // aligned bytes + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert_eq!( + w.write_bytes(b"\xB1\xED").unwrap_err().kind(), + ErrorKind::WriteZero + ); + + // un-aligned bytes + let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); + assert!(w.write_var(4, 11u8).is_ok()); + assert_eq!( + w.write_bytes(b"\xB1\xED").unwrap_err().kind(), + ErrorKind::WriteZero + ); +} + +#[test] +fn test_writer_bits_errors() { + use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; + use io::{sink, ErrorKind}; + + let mut w = BitWriter::endian(sink(), BigEndian); + assert_eq!( + w.write_var(9, 0u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(17, 0u16).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(33, 0u32).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(65, 0u64).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + assert_eq!( + w.write_var(1, 0b10u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(2, 0b100u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(3, 0b1000u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + for bits in 1..8 { + let val = 1u8 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 8..16 { + let val = 1u16 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 16..32 { + let val = 1u32 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 32..64 { + let val = 1u64 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + + assert_eq!( + w.write_signed_var(9, 0i8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(17, 0i16).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(33, 0i32).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(65, 0i64).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + let mut w = BitWriter::endian(sink(), LittleEndian); + assert_eq!( + w.write_var(9, 0u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(17, 0u16).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(33, 0u32).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(65, 0u64).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + assert_eq!( + w.write_var(1, 0b10u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(2, 0b100u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_var(3, 0b1000u8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + + for bits in 1..8 { + let val = 1u8 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 8..16 { + let val = 1u16 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 16..32 { + let val = 1u32 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + for bits in 32..64 { + let val = 1u64 << bits; + assert_eq!( + w.write_var(bits, val).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + } + + assert_eq!( + w.write_signed_var(9, 0i8).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(17, 0i16).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(33, 0i32).unwrap_err().kind(), + ErrorKind::InvalidInput + ); + assert_eq!( + w.write_signed_var(65, 0i64).unwrap_err().kind(), + ErrorKind::InvalidInput + ); +} + +#[test] +fn test_counter_be() { + use bitstream_io::{BitWrite, BitsWritten}; + + // writing individual bits + let mut w: BitsWritten = BitsWritten::new(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.written(), 16); + + // writing unsigned values + let mut w: BitsWritten = BitsWritten::new(); + assert!(w.byte_aligned()); + w.write_var(2, 2u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 6u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 7u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 5u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x53BC1u32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.written(), 32); + + // writing signed values + let mut w: BitsWritten = BitsWritten::new(); + w.write_signed_var(2, -2).unwrap(); + w.write_signed_var(3, -2).unwrap(); + w.write_signed_var(5, 7).unwrap(); + w.write_signed_var(3, -3).unwrap(); + w.write_signed_var(19, -181311).unwrap(); + assert_eq!(w.written(), 32); + + // writing unary 0 values + let mut w: BitsWritten = BitsWritten::new(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(1, 1u32).unwrap(); + assert_eq!(w.written(), 32); + + // writing unary 1 values + let mut w: BitsWritten = BitsWritten::new(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(5).unwrap(); + assert_eq!(w.written(), 32); + + // byte aligning + let mut w: BitsWritten = BitsWritten::new(); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 32); + + // writing bytes, aligned + let mut w: BitsWritten = BitsWritten::new(); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.written(), 16); + + // writing bytes, un-aligned + let mut w: BitsWritten = BitsWritten::new(); + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 24); +} + +#[test] +fn test_counter_huffman_be() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BitWrite, BitsWritten}; + + define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); + + let mut w: BitsWritten = BitsWritten::new(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(2).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 32); +} + +#[test] +fn test_counter_le() { + use bitstream_io::{BitWrite, BitsWritten}; + + // writing individual bits + let mut w: BitsWritten = BitsWritten::new(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.written(), 16); + + // writing unsigned values + let mut w: BitsWritten = BitsWritten::new(); + assert!(w.byte_aligned()); + w.write_var(2, 1u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 4u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 13u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 3u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x609DFu32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.written(), 32); + + // writing signed values + let mut w: BitsWritten = BitsWritten::new(); + w.write_signed_var(2, 1).unwrap(); + w.write_signed_var(3, -4).unwrap(); + w.write_signed_var(5, 13).unwrap(); + w.write_signed_var(3, 3).unwrap(); + w.write_signed_var(19, -128545).unwrap(); + assert_eq!(w.written(), 32); + + // writing unary 0 values + let mut w: BitsWritten = BitsWritten::new(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(5).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(2, 3u32).unwrap(); + assert_eq!(w.written(), 32); + + // writing unary 1 values + let mut w: BitsWritten = BitsWritten::new(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(5).unwrap(); + w.write_unary::<1>(0).unwrap(); + assert_eq!(w.written(), 32); + + // byte aligning + let mut w: BitsWritten = BitsWritten::new(); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 32); + + // writing bytes, aligned + let mut w: BitsWritten = BitsWritten::new(); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.written(), 16); + + // writing bytes, un-aligned + let mut w: BitsWritten = BitsWritten::new(); + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 24); +} + +#[test] +fn test_counter_huffman_le() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BitWrite, BitsWritten}; + + define_huffman_tree!(TreeName : i32= [[[4, 3], 2], [1, 0]]); + + let mut w: BitsWritten = BitsWritten::new(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(3).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(3).unwrap(); + w.write::<1, u8>(1).unwrap(); + assert_eq!(w.written(), 32); +} + +#[test] +fn test_recorder_be() { + use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; + + // partial writes + let mut w: BitRecorder = BitRecorder::new(); + w.write_bit(true).unwrap(); + + let mut w2 = BitWriter::endian(vec![], BigEndian); + w.playback(&mut w2).unwrap(); + w2.byte_align().unwrap(); + + let mut w3 = BitWriter::endian(vec![], BigEndian); + w3.write_bit(true).unwrap(); + w3.byte_align().unwrap(); + + assert_eq!(w2.into_writer(), w3.into_writer()); + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // writing individual bits + let mut w: BitRecorder = BitRecorder::new(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.written(), 16); + let mut w2 = BitWriter::endian(Vec::with_capacity(2), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data[0..2]); + + // writing unsigned values + let mut w: BitRecorder = BitRecorder::new(); + assert!(w.byte_aligned()); + w.write_var(2, 2u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 6u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 7u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 5u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x53BC1u32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing signed values + let mut w: BitRecorder = BitRecorder::new(); + w.write_signed_var(2, -2).unwrap(); + w.write_signed_var(3, -2).unwrap(); + w.write_signed_var(5, 7).unwrap(); + w.write_signed_var(3, -3).unwrap(); + w.write_signed_var(19, -181311).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing unary 0 values + let mut w: BitRecorder = BitRecorder::new(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(4).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(1, 1u32).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing unary 1 values + let mut w: BitRecorder = BitRecorder::new(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(5).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // byte aligning + let aligned_data = [0xA0, 0xE0, 0x3B, 0xC0]; + let mut w: BitRecorder = BitRecorder::new(); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &aligned_data); + + // writing bytes, aligned + let final_data = [0xB1, 0xED]; + let mut w: BitRecorder = BitRecorder::new(); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.written(), 16); + let mut w2 = BitWriter::endian(Vec::with_capacity(2), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing bytes, un-aligned + let mut w: BitRecorder = BitRecorder::new(); + let final_data = [0xBB, 0x1E, 0xD0]; + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + let mut w2 = BitWriter::endian(Vec::with_capacity(3), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_recorder_huffman_be() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); + + let mut w: BitRecorder = BitRecorder::new(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(2).unwrap(); + w.byte_align().unwrap(); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_recorder_le() { + use bitstream_io::{BitRecorder, BitWrite, BitWriter, LittleEndian}; + + // partial writes + let mut w: BitRecorder = BitRecorder::new(); + w.write_bit(true).unwrap(); + + let mut w2 = BitWriter::endian(vec![], LittleEndian); + w.playback(&mut w2).unwrap(); + w2.byte_align().unwrap(); + + let mut w3 = BitWriter::endian(vec![], LittleEndian); + w3.write_bit(true).unwrap(); + w3.byte_align().unwrap(); + + assert_eq!(w2.into_writer(), w3.into_writer()); + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + // writing individual bits + let mut w: BitRecorder = BitRecorder::new(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(false).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + w.write_bit(true).unwrap(); + assert_eq!(w.written(), 16); + let mut w2 = BitWriter::endian(Vec::with_capacity(2), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data[0..2]); + + // writing unsigned values + let mut w: BitRecorder = BitRecorder::new(); + assert!(w.byte_aligned()); + w.write_var(2, 1u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 4u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(5, 13u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(3, 3u32).unwrap(); + assert!(!w.byte_aligned()); + w.write_var(19, 0x609DFu32).unwrap(); + assert!(w.byte_aligned()); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing signed values + let mut w: BitRecorder = BitRecorder::new(); + w.write_signed_var(2, 1).unwrap(); + w.write_signed_var(3, -4).unwrap(); + w.write_signed_var(5, 13).unwrap(); + w.write_signed_var(3, 3).unwrap(); + w.write_signed_var(19, -128545).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing unary 0 values + let mut w: BitRecorder = BitRecorder::new(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(2).unwrap(); + w.write_unary::<0>(5).unwrap(); + w.write_unary::<0>(3).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(1).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_unary::<0>(0).unwrap(); + w.write_var(2, 3u32).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing unary 1 values + let mut w: BitRecorder = BitRecorder::new(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(3).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(1).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(0).unwrap(); + w.write_unary::<1>(2).unwrap(); + w.write_unary::<1>(5).unwrap(); + w.write_unary::<1>(0).unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // byte aligning + let aligned_data = [0x05, 0x07, 0x3B, 0x0C]; + let mut w: BitRecorder = BitRecorder::new(); + w.write_var(3, 5u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(3, 7u32).unwrap(); + w.byte_align().unwrap(); + w.byte_align().unwrap(); + w.write_var(8, 59u32).unwrap(); + w.byte_align().unwrap(); + w.write_var(4, 12u32).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 32); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &aligned_data); + + // writing bytes, aligned + let final_data = [0xB1, 0xED]; + let mut w: BitRecorder = BitRecorder::new(); + w.write_bytes(b"\xB1\xED").unwrap(); + assert_eq!(w.written(), 16); + let mut w2 = BitWriter::endian(Vec::with_capacity(2), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); + + // writing bytes, un-aligned + let final_data = [0x1B, 0xDB, 0x0E]; + let mut w: BitRecorder = BitRecorder::new(); + w.write_var(4, 11u32).unwrap(); + w.write_bytes(b"\xB1\xED").unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.written(), 24); + let mut w2 = BitWriter::endian(Vec::with_capacity(3), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_recorder_huffman_le() { + use bitstream_io::define_huffman_tree; + use bitstream_io::{BitRecorder, BitWrite, BitWriter, LittleEndian}; + + let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; + + define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); + + let mut w: BitRecorder = BitRecorder::new(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(3).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(0).unwrap(); + w.write_huffman::(1).unwrap(); + w.write_huffman::(2).unwrap(); + w.write_huffman::(4).unwrap(); + w.write_huffman::(3).unwrap(); + w.write::<1, u8>(1).unwrap(); + let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); + w.playback(&mut w2).unwrap(); + assert_eq!(w2.into_writer().as_slice(), &final_data); +} + +#[test] +fn test_pad() { + use bitstream_io::{BigEndian, Endianness, LittleEndian}; + + fn test_pad_endian() { + use bitstream_io::BitWriter; + + let mut plain: BitWriter<_, E> = BitWriter::new(Vec::new()); + let mut padded: BitWriter<_, E> = BitWriter::new(Vec::new()); + + for bits in 1..64 { + plain.write_bit(true).unwrap(); + plain.write_var(bits, 0u64).unwrap(); + + padded.write_bit(true).unwrap(); + padded.pad(bits).unwrap(); + } + // plain.write_from([0u8; 1024]).unwrap(); + // plain.write_bit(true).unwrap(); + + // padded.pad(1024 * 8).unwrap(); + // padded.write_bit(true).unwrap(); + + plain.byte_align().unwrap(); + padded.byte_align().unwrap(); + + assert_eq!(plain.into_writer(), padded.into_writer()); + } + + test_pad_endian::(); + test_pad_endian::(); +} + +#[test] +fn test_counter_overflow() { + use bitstream_io::BitsWritten; + + // overflow u8 with many small writes + let mut counter: BitsWritten = BitsWritten::new(); + for _ in 0..255 { + assert!(counter.write_bit(false).is_ok()); + } + assert!(counter.write_bit(false).is_err()); + + // overflow u8 with one big write + let mut counter: BitsWritten = BitsWritten::new(); + assert!(counter.write_from([0u8; 31]).is_ok()); + + let mut counter: BitsWritten = BitsWritten::new(); + assert!(counter.write_from([0u8; 32]).is_err()); +} + +#[test] +fn test_negative_write() { + let mut bit_writer = BitWriter::endian(Vec::new(), BigEndian); + assert!(bit_writer.write_bit(false).is_ok()); + assert!(bit_writer.write_var(8, -1i8).is_ok()); + assert!(bit_writer.write_var(7, 0u8).is_ok()); + if let Some(writer) = bit_writer.writer() { + assert_eq!(writer[0] >> 7, 0); + } else { + panic!("writer() returned None"); + } +} + +#[test] +fn test_bitcount_write() { + use bitstream_io::{BigEndian, BitCount, BitWrite, BitWriter}; + + // 1 bit count - writing 1 bit + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b1>::new::<1>(); + writer.write_count(count).unwrap(); + writer.write_counted::<1, u8>(count, 0b1).unwrap(); + writer.byte_align().unwrap(); + assert_eq!(writer.into_writer(), &[0b1_1_000000]); + + // 2 bit count - writing 3 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b11>::new::<0b11>(); + writer.write_count(count).unwrap(); + writer.write_counted::<0b11, u8>(count, 0b111).unwrap(); + writer.byte_align().unwrap(); + assert_eq!(writer.into_writer(), &[0b11_111_000]); + + // 3 bit count - writing 7 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b111>::new::<0b111>(); + writer.write_count(count).unwrap(); + writer + .write_counted::<0b111, u8>(count, 0b11111_11) + .unwrap(); + writer.byte_align().unwrap(); + assert_eq!(writer.into_writer(), &[0b111_11111, 0b11_000000]); + + // 4 bit count - writing 15 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b1111>::new::<0b1111>(); + writer.write_count(count).unwrap(); + writer + .write_counted::<0b1111, u16>(count, 0b1111_11111111_111) + .unwrap(); + writer.byte_align().unwrap(); + assert_eq!( + writer.into_writer(), + &[0b1111_1111, 0b11111111, 0b111_00000] + ); + + // 5 bits count - writing 31 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b11111>::new::<0b11111>(); + writer.write_count(count).unwrap(); + writer + .write_counted::<0b11111, u32>(count, 0b111_11111111_11111111_11111111_1111) + .unwrap(); + writer.byte_align().unwrap(); + assert_eq!( + writer.into_writer(), + &[0b11111_111, 0b11111111, 0b11111111, 0b11111111, 0b1111_0000] + ); + + // 6 bits count - writing 63 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b111111>::new::<0b111111>(); + writer.write_count(count).unwrap(); + writer + .write_counted::<0b111111, u64>( + count, + 0b11_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111, + ) + .unwrap(); + writer.byte_align().unwrap(); + assert_eq!( + writer.into_writer(), + &[ + 0b111111_11, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111_000 + ] + ); + + // 7 bits count - writing 127 bits + let bytes = vec![]; + let mut writer = BitWriter::endian(bytes, BigEndian); + let count = BitCount::<0b1111111>::new::<0b1111111>(); + writer.write_count(count).unwrap(); + writer + .write_counted::<0b1111111, u128>(count, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + .unwrap(); + writer.byte_align().unwrap(); + assert_eq!( + writer.into_writer(), + &[ + 0b1111111_1, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b111111_00, + ] + ); +} + +#[test] +fn test_nonzero_writes() { + use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; + use core::num::NonZero; + + let mut w = BitWriter::endian(vec![], BigEndian); + w.write::<3, u8>(1).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b001_00000]); + + let mut w = BitWriter::endian(vec![], BigEndian); + w.write::<3, NonZero>(NonZero::new(2).unwrap()).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b001_00000]); + + let mut w = BitWriter::endian(vec![], BigEndian); + w.write_var::(3, 1).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b001_00000]); + + let mut w = BitWriter::endian(vec![], BigEndian); + w.write_var::>(3, NonZero::new(2).unwrap()) + .unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b001_00000]); + + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write::<3, u8>(1).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b00000_001]); + + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write::<3, NonZero>(NonZero::new(2).unwrap()).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b00000_001]); + + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write_var::(3, 1).unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b00000_001]); + + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write_var::>(3, NonZero::new(2).unwrap()) + .unwrap(); + w.byte_align().unwrap(); + assert_eq!(w.into_writer(), &[0b00000_001]); +} + +#[test] +fn test_const_writes() { + use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; + + let mut w = BitWriter::endian(vec![], BigEndian); + w.write_const::<0, 0b0>().unwrap(); + w.write_const::<1, 0b1>().unwrap(); + w.write_const::<2, 0b10>().unwrap(); + w.write_const::<3, 0b100>().unwrap(); + w.write_const::<4, 0b1000>().unwrap(); + w.write_const::<5, 0b10000>().unwrap(); + w.write_const::<6, 0b100000>().unwrap(); + w.write_const::<7, 0b1000000>().unwrap(); + w.write_const::<8, 0b10000000>().unwrap(); + w.write_const::<9, 0b100000000>().unwrap(); + w.write_const::<10, 0b1000000000>().unwrap(); + w.byte_align().unwrap(); + + assert_eq!( + w.into_writer(), + &[ + 0b1_10_100_10, + 0b00_100001, + 0b00000_100, + 0b0000_1000, + 0b0000_1000, + 0b00000_100, + 0b00000000 + ] + ); + + let mut w = BitWriter::endian(vec![], LittleEndian); + w.write_const::<0, 0b0>().unwrap(); + w.write_const::<1, 0b1>().unwrap(); + w.write_const::<2, 0b10>().unwrap(); + w.write_const::<3, 0b100>().unwrap(); + w.write_const::<4, 0b1000>().unwrap(); + w.write_const::<5, 0b10000>().unwrap(); + w.write_const::<6, 0b100000>().unwrap(); + w.write_const::<7, 0b1000000>().unwrap(); + w.write_const::<8, 0b10000000>().unwrap(); + w.write_const::<9, 0b100000000>().unwrap(); + w.write_const::<10, 0b1000000000>().unwrap(); + w.byte_align().unwrap(); + + assert_eq!( + w.into_writer(), + &[ + 0b00_100_10_1, + 0b0_10000_10, + 0b000_10000, + 0b0000_1000, + 0b0000_1000, + 0b000_10000, + 0b0_1000000 + ] + ); +} + +#[test] +fn test_byte_count() { + use bitstream_io::{ByteWrite, ToByteStream}; + + #[derive(Default)] + struct Builder { + a: u8, + b: u16, + c: u32, + d: u64, + e: u128, + } + + impl ToByteStream for Builder { + type Error = io::Error; + + fn to_writer(&self, w: &mut W) -> io::Result<()> { + w.write(self.a)?; + w.write(self.b)?; + w.write(self.c)?; + w.write(self.d)?; + w.write(self.e)?; + Ok(()) + } + } + + assert_eq!( + Builder::default().bytes::().unwrap(), + 1 + 2 + 4 + 8 + 16 + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"aa53da4c09163e6c269f9536ade5363ae62549295b4f4a85bdf923540f6442e1","Cargo.toml":"c76e4bd298cd6223882238449e31939d75613e82757ca87e249df843decf5f9a","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"d5c22aa3118d240e877ad41c5d9fa232f9c77d757d4aac0c2f943afc0a95e0ef","README.md":"9bf3545872bdad2fb41557be5cefc21a48f0c7804f8124e24b67760429036472","src/lib.rs":"b437252d389042d894b1ef17859b043e827d2bd2a1bca4b5311c67dff565274d","src/sealed.rs":"9327ee3e567ae779b83c2b7f4f3ff56fcb2117163e023e7b0e37759e7e8d1f5c","tests/mod.rs":"a42403629557eea432a8797f2d81a4ab65de15ce9a2db933496c53f05669e1d7"},"package":"3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"83f3846b9d1b0a039b5ca05f910516a6b6f1039e04f5eaadf915456b1259ef71","CHANGELOG.md":"aa53da4c09163e6c269f9536ade5363ae62549295b4f4a85bdf923540f6442e1","Cargo.toml":"c76e4bd298cd6223882238449e31939d75613e82757ca87e249df843decf5f9a","Cargo.toml.orig":"fa80221c48c162058fb829ff845746f7db0ffbc274067b5850bc3d50a437495f","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"d5c22aa3118d240e877ad41c5d9fa232f9c77d757d4aac0c2f943afc0a95e0ef","README.md":"9bf3545872bdad2fb41557be5cefc21a48f0c7804f8124e24b67760429036472","src/lib.rs":"b437252d389042d894b1ef17859b043e827d2bd2a1bca4b5311c67dff565274d","src/sealed.rs":"9327ee3e567ae779b83c2b7f4f3ff56fcb2117163e023e7b0e37759e7e8d1f5c","tests/mod.rs":"a42403629557eea432a8797f2d81a4ab65de15ce9a2db933496c53f05669e1d7"},"package":"3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6d35952d3d3b124bc1049ad6fb406b42b1ce4bfe" + }, + "path_in_vcs": "block-buffer" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/block-buffer/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/block-buffer/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +[package] +name = "block-buffer" +version = "0.10.4" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +description = "Buffer type for block processing of data" +documentation = "https://docs.rs/block-buffer" +repository = "https://github.com/RustCrypto/utils" +keywords = ["block", "buffer"] +categories = ["cryptography", "no-std"] +edition = "2018" +readme = "README.md" + +[dependencies] +generic-array = "0.14" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/built/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"6e7d5ad543571293268f47fd277c58997c30f4b96487bd5ed24cbc9c958acd30",".devcontainer/devcontainer.json":"3e5eeaf177492d5d3b5a9f103f2da822f65e9954234a329317573eece1087f0d",".github/workflows/check.yml":"111a9416d5bb84e71f59c3e5b720da1300d09ea3d62b606267b3b6d0e86e91f7","CHANGELOG.md":"7a1a6a40d495ce50014420d9ec34ad4ddc99c89c68f342b837a4b48b4d87bedc","Cargo.lock":"ee20ddb7ef292d5c0b20e2b445c3bb086530ad4953173e5a17603feae0bea362","Cargo.toml":"592076cd2e69e6c827c07fccd6e48a457f7fc36170a45d3ae8f1184e85b6a6bf","Cargo.toml.orig":"29d0474a143c6d6580e8092eb5cf07c65559d93843f941a55321efdd83866a5c","LICENSE":"09ae9a35173439c76fdbc953b5988d815715dc9bdc6191b88e9a393190bb62c4","README.md":"796f28c703d40dc7424e0020bd6c72fbe61d6888b2fc95494f3d510b1ba7b5a7","src/dependencies.rs":"d63a9b971a2a0c1d0e96f62a05124eb3128ceeaed87f45b9984c78fb9e7cda50","src/environment.rs":"b28daa64ccecb1c0df4ca2a98b155f07f2a230c941f54e555a4d9f5c232836ed","src/git.rs":"61058b541d3ac4b23c8634c48cc139023915df56e694c826538c6cfcec16d03a","src/krono.rs":"f1546f8661181880b677c7d5d3d3b44f40ae188c8aca9f01b3e3a763ac065fd3","src/lib.rs":"05f741e93053cda2ec5e17a0d633771c12445277d7b59872adb63b327ee85b54","src/util.rs":"c52de94737df8612ffdd49617e31cff1d1b05de6983c91a077854ca4bcd149b2","tests/testbox_tests.rs":"76005cbe889a23f2623e24d6fa6e81c2fe25c5136efd0368acbe12dd986f9aaa"},"package":"f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/built/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "2d84b2362c9cde5e0054be103190de0cbc065d85" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/.devcontainer/devcontainer.json clamav-1.4.6+dfsg/.cargo/vendor/built/.devcontainer/devcontainer.json --- clamav-1.4.3+dfsg/.cargo/vendor/built/.devcontainer/devcontainer.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/.devcontainer/devcontainer.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "image": "mcr.microsoft.com/devcontainers/universal:2", + "features": { + "ghcr.io/devcontainers/features/rust:1": {} + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/.github/workflows/check.yml clamav-1.4.6+dfsg/.cargo/vendor/built/.github/workflows/check.yml --- clamav-1.4.3+dfsg/.cargo/vendor/built/.github/workflows/check.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/.github/workflows/check.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +name: Clippy, Format & Test + +on: [pull_request, push, workflow_dispatch] + +jobs: + fmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo fmt --all -- --check + - run: cargo fmt --manifest-path=example_project/Cargo.toml --all -- --check + + check: + name: cargo check + runs-on: ubuntu-latest + strategy: + matrix: + toolchain: [stable, "1.81"] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.toolchain }} + - run: cargo check --no-default-features + - run: cargo check --no-default-features --features cargo-lock + - run: cargo check --no-default-features --features dependency-tree + - run: cargo check --no-default-features --features git2 + - run: cargo check --no-default-features --features semver + - run: cargo check --no-default-features --features chrono + - run: cargo check --all-features + - run: cargo check --manifest-path=example_project/Cargo.toml + + semver_crate: + name: cargo check of internal crate + runs-on: ubuntu-latest + strategy: + matrix: + toolchain: [stable, "1.83"] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.toolchain }} + - run: cargo check --manifest-path=semver_check/Cargo.toml + + clippy: + name: cargo clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - run: cargo clippy --all --tests -- -D warnings + - run: cargo clippy --all-features --all --tests -- -D warnings + - run: cargo clippy --manifest-path=example_project/Cargo.toml --all --tests -- --warn clippy::pedantic -D warnings + + test: + name: cargo test + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + toolchain: [stable, nightly] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + targets: x86_64-unknown-none + toolchain: ${{ matrix.toolchain }} + - if: matrix.toolchain == 'nightly' + run: echo "RUSTFLAGS=-Zfmt-debug=none" >> $GITHUB_ENV + - run: cargo test --no-default-features + - run: cargo test --all-features + - run: cargo test -- --ignored nostd_testbox + - run: cargo run --manifest-path=example_project/Cargo.toml + + semver: + name: Semver check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: sudo apt update && sudo apt install -y cmake + - uses: obi1kenobi/cargo-semver-checks-action@v2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/built/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/built/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,129 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.8.0] +- Add override-variables +- Bump MSRV to 1.81 (due to dependencies) + +## [0.7.7] +- Fix `NUM_JOB` to 1 if `SOURCE_DATE_EPOCH` is set, in order to better support reproducible builds +- Set MSRV to 1.74 (due to dependencies) + +## [0.7.6] +- Do not depend on `fmt::Debug`-output (`fmt-debug=none`) +- Bump `git2` to 0.20 +- Use `static`- instead of `const`-items throughout + +## [0.7.5] - 2024-10-17 +### Changed +- Bump `cargo-lock` to 10.0 + +## [0.7.4] - 2024-07-07 +### Added +- Honor `SOURCE_DATE_EPOCH` in `BUILT_TIME_UTC` + +### Changed +- Bump `git2` to 0.19 + +## [0.7.3] - 2024-05-21 +### Added +- Search for lockfile in manifest's parent directory (crates in workspaces) + +## [0.7.2] - 2024-04-09 +### Changed +- Fixed hard error in case `rustdoc` is missing + +## [0.7.1] - 2023-10-14 +### Changed +- Fixed `no_std` builds + +## [0.7.0] - 2023-08-09 +### Changed +- The `Options`-type has been removed in favor of controlling `built`'s behavior by means of feature-flags. +- `cargo-lock` is now an optional dependency +- Bump `git2` to 0.18 + +## [0.6.1] - 2023-06-19 +### Changed +- Bump `git2` to 0.17 +- Bump `cargo-lock` to 9.0 + +### Added +- `FEATURES_LOWERCASE` and `FEATURES_LOWERCASE_STR` + +## [0.6.0] - 2023-02-09 +### Changed +- Identical re-release after yanking 0.5.3, due to semver failure + +## [0.5.3] - 2023-02-08 +### Changed +- Bump `git2` to 0.16, mitigating GHSA-8643-3wh5-rmjq + +### Added +- Add `GIT_COMMIT_HASH_SHORT` + +## [0.5.2] - 2022-12-03 +### Changed +- Removed unused transitive dependency on `time` +- Bump `cargo-lock` to 8.0 +- Bump `git2` to 0.15 +- Fix unescaped quotes in literals + +### Added +- Added GitHub Actions to the list of detected CI platforms + +## [0.5.1] - 2021-05-27 +### Changed +- Bump `cargo-lock` to 7.0 +- Bump `semver` to 1.0 + +## [0.5.0] - 2021-05-01 +### Fixed +- Fix possibly wrong `CFG_` values in cross-compilation scenarios +- Fix handling of backspaces in doc-attributes + +### Changed +- Switch deprecated `tempdir` to `tempfile` +- Add `#allow(dead_code)` to generated code +- Bump `cargo-lock` to 6.0 +- Bump `semver` to 0.11 +- Publicly re-export dependencies + +## [0.4.4] - 2020-12-01 +### Added +- Added `PKG_LICENSE` and `PKG_REPOSITORY` + +## [0.4.3] - 2020-08-19 +### Fixed +- Fix handling of unescaped special characters + +## [0.4.2] - 2020-05-27 +### Added +- Add `GIT_DIRTY` +- Add `GIT_COMMIT_HASH` and `GIT_HEAD_REF` + +### Changed +- Bump `semver` to 0.10 + +[unreleased]: https://github.com/lukaslueg/built/compare/0.8.0...master +[0.8.0]: https://github.com/lukaslueg/built/compare/0.7.7...0.8.0 +[0.7.7]: https://github.com/lukaslueg/built/compare/0.7.6...0.7.7 +[0.7.6]: https://github.com/lukaslueg/built/compare/0.7.5...0.7.6 +[0.7.5]: https://github.com/lukaslueg/built/compare/0.7.4...0.7.5 +[0.7.4]: https://github.com/lukaslueg/built/compare/0.7.3...0.7.4 +[0.7.3]: https://github.com/lukaslueg/built/compare/0.7.2...0.7.3 +[0.7.2]: https://github.com/lukaslueg/built/compare/0.7.1...0.7.2 +[0.7.1]: https://github.com/lukaslueg/built/compare/0.7.0...0.7.1 +[0.7.0]: https://github.com/lukaslueg/built/compare/0.6.1...0.7.0 +[0.6.1]: https://github.com/lukaslueg/built/compare/0.6.0...0.6.1 +[0.6.0]: https://github.com/lukaslueg/built/compare/0.5.3...0.6.0 +[0.5.3]: https://github.com/lukaslueg/built/compare/0.5.2...0.5.3 +[0.5.2]: https://github.com/lukaslueg/built/compare/0.5.1...0.5.2 +[0.5.1]: https://github.com/lukaslueg/built/compare/0.5.0...0.5.1 +[0.5.0]: https://github.com/lukaslueg/built/compare/0.4.4...0.5.0 +[0.4.4]: https://github.com/lukaslueg/built/compare/0.4.3...0.4.4 +[0.4.3]: https://github.com/lukaslueg/built/compare/0.4.2...0.4.3 +[0.4.2]: https://github.com/lukaslueg/built/compare/0.4.1...0.4.2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,974 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "built" +version = "0.8.0" +dependencies = [ + "cargo-lock", + "chrono", + "git2", + "semver", + "tempfile", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "cargo-lock" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06acb4f71407ba205a07cb453211e0e6a67b21904e47f6ba1f9589e38f2e454" +dependencies = [ + "petgraph", + "semver", + "serde", + "toml", + "url", +] + +[[package]] +name = "cc" +version = "1.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-link", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "git2" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5220b8ba44c68a9a7f7a7659e864dd73692e417ef0211bea133c7b74e031eeb9" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "url", +] + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libgit2-sys" +version = "0.18.1+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tempfile" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "toml" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e27d6ad3dac991091e4d35de9ba2d2d00647c5d0fc26c5496dee55984ae111b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.81" +name = "built" +version = "0.8.0" +authors = ["Lukas Lueg "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Provides a crate with information from the time it was built." +documentation = "https://docs.rs/built" +readme = "README.md" +keywords = [ + "cargo", + "build", +] +license = "MIT" +repository = "https://github.com/lukaslueg/built" + +[package.metadata.docs.rs] +features = [ + "cargo-lock", + "chrono", + "dependency-tree", + "git2", + "semver", +] + +[features] +dependency-tree = ["cargo-lock/dependency-tree"] + +[lib] +name = "built" +path = "src/lib.rs" + +[[test]] +name = "testbox_tests" +path = "tests/testbox_tests.rs" + +[dependencies.cargo-lock] +version = "10.0" +optional = true +default-features = false + +[dependencies.chrono] +version = "0.4" +features = ["clock"] +optional = true +default-features = false + +[dependencies.git2] +version = "0.20" +features = [] +optional = true +default-features = false + +[dependencies.semver] +version = "1.0" +optional = true + +[dev-dependencies.tempfile] +version = "3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/built/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +[package] +name = "built" +version = "0.8.0" +description = "Provides a crate with information from the time it was built." +repository = "https://github.com/lukaslueg/built" +documentation = "https://docs.rs/built" +authors = ["Lukas Lueg "] +license = "MIT" +readme = "README.md" +keywords = ["cargo", "build"] +edition = "2021" +rust-version = "1.81" + +[dependencies] +cargo-lock = { version = "10.0", optional = true, default-features = false } +semver = { version = "1.0", optional = true } +chrono = { version = "0.4", optional = true, default-features = false, features = ["clock"] } +git2 = { version = "0.20", optional = true, default-features = false, features = [] } + +[dev-dependencies] +tempfile = "3" + +[features] +dependency-tree = [ "cargo-lock/dependency-tree" ] + +[package.metadata.docs.rs] +features = [ "cargo-lock", "chrono", "dependency-tree", "git2", "semver" ] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/built/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/built/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-2023 Lukas Lueg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/README.md clamav-1.4.6+dfsg/.cargo/vendor/built/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/built/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,73 @@ +```built``` provides a crate with information from the time it was built. + +[![Crates.io Version](https://img.shields.io/crates/v/built.svg)](https://crates.io/crates/built) +[![Docs](https://docs.rs/built/badge.svg)](https://docs.rs/built) +[![Clippy, Format & Test](https://github.com/lukaslueg/built/actions/workflows/check.yml/badge.svg)](https://github.com/lukaslueg/built/actions/workflows/check.yml) +[![Downloads](https://img.shields.io/crates/d/built)](https://crates.io/crates/built) + +`built` is used as a build-time dependency to collect various information +about the build-environment, serialize this information into Rust-code and +provide that to the crate. The information collected by `built` include: + +* Various metadata like version, authors, homepage etc. as set by `Cargo.toml` +* The tag or commit id if the crate was being compiled from within a Git repository. +* The values of `CARGO_CFG_*` build script environment variables, like `CARGO_CFG_TARGET_OS` and `CARGO_CFG_TARGET_ARCH`. +* The features the crate was compiled with. +* The various dependencies, dependencies of dependencies and their versions Cargo ultimately chose to compile. +* The presence of a CI-platform like `Github Actions`, `Travis CI` and `AppVeyor`. +* The compiler and it's version; the documentation-generator and it's version. + +See [the example](https://github.com/lukaslueg/built/tree/master/example_project) or the [docs](https://docs.rs/built) for more information. + +### MSRV + +`built-0.8` itself currently requires Rust 1.81 with all features enabled. + +--- + +```rust,ignore +// In build.rs + +fn main() { + built::write_built_file().expect("Failed to acquire build-time information") +} +``` + +```rust,ignore +// In lib.rs or main.rs + +// Include the generated-file as a separate module +pub mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +println!( + "This is version {}, built for {} by {}.", + built_info::PKG_VERSION, + built_info::TARGET, + built_info::RUSTC_VERSION +); + +match built_info::CI_PLATFORM { + None => print!("It seems I've not been built on a continuous integration platform,"), + Some(ci) => print!("I've been built on CI-platform {},", ci), +} + +if built::util::detect_ci().is_some() { + println!(" but I'm currently executing on one!"); +} else { + println!(" and I'm currently not executing on one!"); +} + +//.... +``` + +> This is version 0.1.0, built for x86_64-unknown-linux-gnu by rustc 1.77.2 (25ef9e3d8 2024-04-09). +> +> I was built from git `0.7.2-3-g4014a2e`, commit 4014a2eb4e8575bec9a1f17ae7b92d8956ecd1fd, short_commit 4014a2e; the working directory was "clean". The branch was `refs/heads/master`. +> +> I was built for a x86_64-CPU, which is a little-endian architecture. I was compiled to run on linux (a unix-breed) and my runtime should be gnu. +> +> It seems I've not been built on a continuous integration platform, and I'm currently not executing on one! +> +> I was built with profile "debug", features "" on 2024-04-14 14:28:31 +00:00 (38 seconds ago) using `built 0.7.2` (with help from `android-tzdata 0.1.1, android_system_properties 0.1.5, autocfg 1.2.0, bitflags 2.5.0, bumpalo 3.16.0, cargo-lock 9.0.0, cc 1.0.94, cfg-if 1.0.0, chrono 0.4.37, core-foundation-sys 0.8.6, equivalent 1.0.1, fixedbitset 0.4.2, form_urlencoded 1.2.1, git2 0.18.3, hashbrown 0.14.3, iana-time-zone 0.1.60, iana-time-zone-haiku 0.1.2, idna 0.5.0, indexmap 2.2.6, jobserver 0.1.30, js-sys 0.3.69, libc 0.2.153, libgit2-sys 0.16.2+1.7.2, libz-sys 1.1.16, log 0.4.21, memchr 2.7.2, num-traits 0.2.18, once_cell 1.19.0, percent-encoding 2.3.1, petgraph 0.6.4, pkg-config 0.3.30, proc-macro2 1.0.79, quote 1.0.36, semver 1.0.22, serde 1.0.197, serde_derive 1.0.197, serde_spanned 0.6.5, syn 2.0.58, tinyvec 1.6.0, tinyvec_macros 0.1.1, toml 0.7.8, toml_datetime 0.6.5, toml_edit 0.19.15, unicode-bidi 0.3.15, unicode-ident 1.0.12, unicode-normalization 0.1.23, url 2.5.0, vcpkg 0.2.15, wasm-bindgen 0.2.92, wasm-bindgen-backend 0.2.92, wasm-bindgen-macro 0.2.92, wasm-bindgen-macro-support 0.2.92, wasm-bindgen-shared 0.2.92, windows-core 0.52.0, windows-targets 0.52.5, windows_aarch64_gnullvm 0.52.5, windows_aarch64_msvc 0.52.5, windows_i686_gnu 0.52.5, windows_i686_gnullvm 0.52.5, windows_i686_msvc 0.52.5, windows_x86_64_gnu 0.52.5, windows_x86_64_gnullvm 0.52.5, windows_x86_64_msvc 0.52.5, winnow 0.5.40`). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/dependencies.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/dependencies.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/dependencies.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/dependencies.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,276 @@ +use crate::util::TupleArrayDisplay; +use crate::{write_str_variable, write_variable}; +use std::{collections, fs, io, path}; + +fn package_names<'a, I>(packages: I) -> Vec<(String, String)> +where + I: IntoIterator, +{ + let mut res = packages + .into_iter() + .map(|package| (package.name.to_string(), package.version.to_string())) + .collect::>() + .into_iter() + .collect::>(); + res.sort_unstable(); + res +} + +fn find_lockfile(base: &path::Path) -> io::Result { + base.ancestors() + .find_map(|p| { + let lockfile = p.join("Cargo.lock"); + lockfile.exists().then(|| lockfile.to_owned()) + }) + .ok_or(io::Error::other("Cargo.lock not found")) +} + +#[cfg(feature = "dependency-tree")] +struct Dependencies { + deps: Vec<(String, String)>, + direct_deps: Vec<(String, String)>, + indirect_deps: Vec<(String, String)>, +} + +#[cfg(feature = "dependency-tree")] +impl Dependencies { + fn new(lockfile: &cargo_lock::Lockfile) -> Self { + use cargo_lock::dependency::graph::EdgeDirection; + + let tree = lockfile + .dependency_tree() + .expect("properly formed lockfile"); + let graph = tree.graph(); + + let root_pkg_idx = graph + .externals(EdgeDirection::Incoming) + .collect::>(); + let deps = package_names(graph.node_indices().filter_map(|idx| { + if root_pkg_idx.contains(&idx) { + None + } else { + Some(&graph[idx]) + } + })); + let direct_deps_idx = root_pkg_idx + .iter() + .flat_map(|idx| graph.neighbors_directed(*idx, EdgeDirection::Outgoing)) + .collect::>(); + let direct_deps = package_names(direct_deps_idx.iter().map(|dep_idx| &graph[*dep_idx])); + let indirect_deps = package_names(graph.node_indices().filter_map(|idx| { + if root_pkg_idx.contains(&idx) | direct_deps_idx.contains(&idx) { + None + } else { + Some(&graph[idx]) + } + })); + + Self { + deps, + direct_deps, + indirect_deps, + } + } +} + +#[cfg(feature = "dependency-tree")] +pub fn write_dependencies(manifest_location: &path::Path, mut w: &fs::File) -> io::Result<()> { + use io::{Read, Write}; + + let mut lock_buf = String::new(); + fs::File::open(find_lockfile(manifest_location)?)?.read_to_string(&mut lock_buf)?; + let lockfile = lock_buf.parse().expect("Failed to parse lockfile"); + + let dependencies = Dependencies::new(&lockfile); + + write_variable!( + w, + "DEPENDENCIES", + format_args!("[(&str, &str); {}]", dependencies.deps.len()), + TupleArrayDisplay(&dependencies.deps), + "An array of effective dependencies as documented by `Cargo.lock`." + ); + write_str_variable!( + w, + "DEPENDENCIES_STR", + dependencies + .deps + .iter() + .map(|(n, v)| format!("{n} {v}")) + .collect::>() + .join(", "), + "The effective dependencies as a comma-separated string." + ); + + write_variable!( + w, + "DIRECT_DEPENDENCIES", + format_args!("[(&str, &str); {}]", dependencies.direct_deps.len()), + TupleArrayDisplay(&dependencies.direct_deps), + "An array of direct dependencies as documented by `Cargo.lock`." + ); + write_str_variable!( + w, + "DIRECT_DEPENDENCIES_STR", + dependencies + .direct_deps + .iter() + .map(|(n, v)| format!("{n} {v}")) + .collect::>() + .join(", "), + "The direct dependencies as a comma-separated string." + ); + + write_variable!( + w, + "INDIRECT_DEPENDENCIES", + format_args!("[(&str, &str); {}]", dependencies.indirect_deps.len()), + TupleArrayDisplay(&dependencies.indirect_deps), + "An array of indirect dependencies as documented by `Cargo.lock`." + ); + write_str_variable!( + w, + "INDIRECT_DEPENDENCIES_STR", + dependencies + .indirect_deps + .iter() + .map(|(n, v)| format!("{n} {v}")) + .collect::>() + .join(", "), + "The indirect dependencies as a comma-separated string." + ); + + Ok(()) +} + +#[cfg(not(feature = "dependency-tree"))] +pub fn write_dependencies(manifest_location: &path::Path, mut w: &fs::File) -> io::Result<()> { + use io::{Read, Write}; + + let mut lock_buf = String::new(); + fs::File::open(find_lockfile(manifest_location)?)?.read_to_string(&mut lock_buf)?; + let lockfile: cargo_lock::Lockfile = lock_buf.parse().expect("Failed to parse lockfile"); + + let deps = package_names(&lockfile.packages); + + write_variable!( + w, + "DEPENDENCIES", + format_args!("[(&str, &str); {}]", deps.len()), + TupleArrayDisplay(&deps), + "An array of effective dependencies as documented by `Cargo.lock`." + ); + write_str_variable!( + w, + "DEPENDENCIES_STR", + deps.iter() + .map(|(n, v)| format!("{n} {v}")) + .collect::>() + .join(", "), + "The effective dependencies as a comma-separated string." + ); + + Ok(()) +} + +#[cfg(test)] +mod tests { + static LOCK_TOML_BUFFER: &str = r#" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "foo" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7dbb6acfeff1d490fba693a402456f76b344fea77a5e7cae43b5970c3332b8f" + +[[package]] +name = "foobar" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c0d152c1d2a9673211b9f3c02a4786715ce730dbd5f94f2f895fc0bb9eed63" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "dummy" +version = "0.1.0" +dependencies = [ + "foo", + "foobar", + "nom", +] +"#; + + #[test] + fn parse_deps() { + let lockfile: cargo_lock::Lockfile = + LOCK_TOML_BUFFER.parse().expect("Failed to parse lockfile"); + let deps = super::package_names(&lockfile.packages); + assert_eq!( + deps, + [ + ("dummy".to_owned(), "0.1.0".to_owned()), + ("foo".to_owned(), "0.0.0".to_owned()), + ("foobar".to_owned(), "0.0.0".to_owned()), + ("memchr".to_owned(), "2.6.3".to_owned()), + ("minimal-lexical".to_owned(), "0.2.1".to_owned()), + ("nom".to_owned(), "7.1.3".to_owned()), + ] + ); + } + + #[test] + #[cfg(feature = "dependency-tree")] + fn direct_deps() { + let lockfile = LOCK_TOML_BUFFER.parse().expect("Failed to parse lockfile"); + let dependencies = super::Dependencies::new(&lockfile); + assert_eq!( + dependencies.deps, + [ + ("foo".to_owned(), "0.0.0".to_owned()), + ("foobar".to_owned(), "0.0.0".to_owned()), + ("memchr".to_owned(), "2.6.3".to_owned()), + ("minimal-lexical".to_owned(), "0.2.1".to_owned()), + ("nom".to_owned(), "7.1.3".to_owned()), + ] + ); + assert_eq!( + dependencies.direct_deps, + [ + ("foo".to_owned(), "0.0.0".to_owned()), + ("foobar".to_owned(), "0.0.0".to_owned()), + ("nom".to_owned(), "7.1.3".to_owned()), + ] + ); + assert_eq!( + dependencies.indirect_deps, + [ + ("memchr".to_owned(), "2.6.3".to_owned()), + ("minimal-lexical".to_owned(), "0.2.1".to_owned()), + ] + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/environment.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/environment.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/environment.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/environment.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,527 @@ +use crate::util::{self, ArrayDisplay}; +use crate::{fmt_option_str, write_str_variable, write_variable}; +use std::{cell, collections, env, ffi, fmt, fs, io, process}; + +const BUILT_OVERRIDE_PREFIX: &str = "BUILT_OVERRIDE_"; + +#[derive(Debug, Default)] +enum EnvironmentValue { + #[default] + Unused, + Queried, + Used, +} + +impl EnvironmentValue { + fn upgrade_to_queried(&mut self) { + if matches!(self, EnvironmentValue::Unused) { + *self = EnvironmentValue::Queried; + } + } + + fn upgrade_to_used(&mut self) { + *self = EnvironmentValue::Used; + } + + pub fn is_unused(&self) -> bool { + matches!(self, EnvironmentValue::Unused) + } + + pub fn is_used(&self) -> bool { + matches!(self, EnvironmentValue::Used) + } +} + +pub struct EnvironmentMap { + map: collections::HashMap)>, + override_prefix: String, +} + +fn get_version_from_cmd(executable: &ffi::OsStr) -> io::Result { + let output = process::Command::new(executable).arg("-V").output()?; + let mut v = String::from_utf8(output.stdout).unwrap(); + v.pop(); // remove newline + Ok(v) +} + +impl EnvironmentMap { + pub fn new() -> Self { + let map = env::vars_os() + .filter_map(|(k, v)| match (k.into_string(), v.into_string()) { + (Ok(k), Ok(v)) => Some((k, (v, cell::RefCell::default()))), + _ => None, + }) + .collect::>(); + let override_prefix = format!("{}{}_", BUILT_OVERRIDE_PREFIX, map["CARGO_PKG_NAME"].0); + Self { + map, + override_prefix, + } + } + + fn override_key(&self, key: &str) -> String { + let mut prefixed_key = self.override_prefix.clone(); + prefixed_key.push_str(key); + prefixed_key + } + + pub fn get(&self, key: &str) -> Option<&str> { + self.map.get(key).map(|v| { + v.1.borrow_mut().upgrade_to_queried(); + v.0.as_str() + }) + } + + pub fn contains_key(&self, key: &str) -> bool { + self.get(key).is_some() + } + + pub fn filter_map_keys(&self, mut f: F) -> impl Iterator + where + F: FnMut(&str) -> Option<&str>, + { + self.map.iter().filter_map(move |v| match f(v.0.as_str()) { + Some(w) => { + v.1 .1.borrow_mut().upgrade_to_queried(); + Some(w) + } + None => None, + }) + } + + pub fn get_override_var<'a, T>(&'a self, key: &str) -> Option + where + T: util::ParseFromEnv<'a>, + { + self.map.get(&self.override_key(key)).map(|v| { + v.1.borrow_mut().upgrade_to_queried(); + match T::parse_from_env(v.0.as_str()) { + Ok(t) => { + v.1.borrow_mut().upgrade_to_used(); + t + } + Err(e) => { + panic!("Failed to parse `{key}`=`{0}`: {e:?}", v.0); + } + } + }) + } + + pub fn unused_override_vars(&self) -> impl Iterator { + self.map.iter().filter_map(|(k, v)| { + if k.starts_with(&self.override_prefix) && v.1.borrow().is_unused() { + Some(k.as_str()) + } else { + None + } + }) + } + + pub fn used_override_vars(&self) -> impl Iterator { + self.map.iter().filter_map(|(k, v)| { + if v.1.borrow().is_used() { + Some(k.strip_prefix(&self.override_prefix).unwrap()) + } else { + None + } + }) + } + + pub fn write_ci(&self, mut w: &fs::File) -> io::Result<()> { + use io::Write; + + let ci = match self.get_override_var("CI_PLATFORM") { + Some(v) => v, + None => self.detect_ci().map(|ci| ci.to_string()), + }; + write_variable!( + w, + "CI_PLATFORM", + "Option<&str>", + fmt_option_str(ci), + "The Continuous Integration platform detected during compilation." + ); + Ok(()) + } + + pub fn write_env(&self, mut w: &fs::File) -> io::Result<()> { + use io::Write; + macro_rules! write_env_str { + ($(($name:ident, $env_name:expr, $doc:expr)),*) => {$( + let v = match self.get_override_var(stringify!($name)) { + Some(v) => v, + None => self.get($env_name).expect(stringify!(Missing expected environment variable $env_name)), + }; + write_str_variable!( + w, + stringify!($name), + v, + $doc + ); + )*} + } + + write_env_str!( + (PKG_VERSION, "CARGO_PKG_VERSION", "The full version."), + ( + PKG_VERSION_MAJOR, + "CARGO_PKG_VERSION_MAJOR", + "The major version." + ), + ( + PKG_VERSION_MINOR, + "CARGO_PKG_VERSION_MINOR", + "The minor version." + ), + ( + PKG_VERSION_PATCH, + "CARGO_PKG_VERSION_PATCH", + "The patch version." + ), + ( + PKG_VERSION_PRE, + "CARGO_PKG_VERSION_PRE", + "The pre-release version." + ), + ( + PKG_AUTHORS, + "CARGO_PKG_AUTHORS", + "A colon-separated list of authors." + ), + (PKG_NAME, "CARGO_PKG_NAME", "The name of the package."), + (PKG_DESCRIPTION, "CARGO_PKG_DESCRIPTION", "The description."), + (PKG_HOMEPAGE, "CARGO_PKG_HOMEPAGE", "The homepage."), + (PKG_LICENSE, "CARGO_PKG_LICENSE", "The license."), + ( + PKG_REPOSITORY, + "CARGO_PKG_REPOSITORY", + "The source repository as advertised in Cargo.toml." + ), + ( + TARGET, + "TARGET", + "The target triple that was being compiled for." + ), + (HOST, "HOST", "The host triple of the rust compiler."), + ( + PROFILE, + "PROFILE", + "`release` for release builds, `debug` for other builds." + ), + (RUSTC, "RUSTC", "The compiler that cargo resolved to use."), + ( + RUSTDOC, + "RUSTDOC", + "The documentation generator that cargo resolved to use." + ) + ); + + write_str_variable!( + w, + "OPT_LEVEL", + self.get_override_var("OPT_LEVEL") + .unwrap_or_else(|| env::var("OPT_LEVEL").unwrap()), + "Value of OPT_LEVEL for the profile used during compilation." + ); + + write_variable!( + w, + "NUM_JOBS", + "u32", + self.get_override_var("NUM_JOBS").unwrap_or_else(|| { + if env::var(crate::SOURCE_DATE_EPOCH).is_ok() { + 1u32 + } else { + env::var("NUM_JOBS").unwrap().parse().unwrap() + } + }), + "The parallelism that was specified during compilation." + ); + + write_variable!( + w, + "DEBUG", + "bool", + self.get_override_var("DEBUG") + .unwrap_or_else(|| env::var("DEBUG").unwrap() == "true"), + "Value of DEBUG for the profile used during compilation." + ); + Ok(()) + } + + pub fn write_features(&self, mut w: &fs::File) -> io::Result<()> { + use io::Write; + + let mut features = self.get_override_var("FEATURES").unwrap_or_else(|| { + self.filter_map_keys(|k| k.strip_prefix("CARGO_FEATURE_")) + .map(|f| f.to_owned()) + .collect::>() + }); + features.sort_unstable(); + + write_variable!( + w, + "FEATURES", + format_args!("[&str; {}]", features.len()), + ArrayDisplay(&features, |t, f| write!(f, "\"{}\"", t.escape_default())), + "The features that were enabled during compilation." + ); + let features_str = features.join(", "); + write_str_variable!( + w, + "FEATURES_STR", + features_str, + "The features as a comma-separated string." + ); + + let mut lowercase_features = features + .iter() + .map(|name| name.to_lowercase()) + .collect::>(); + lowercase_features.sort_unstable(); + + write_variable!( + w, + "FEATURES_LOWERCASE", + format_args!("[&str; {}]", lowercase_features.len()), + ArrayDisplay(&lowercase_features, |val, fmt| write!( + fmt, + "\"{}\"", + val.escape_default() + )), + "The features as above, as lowercase strings." + ); + let lowercase_features_str = lowercase_features.join(", "); + write_str_variable!( + w, + "FEATURES_LOWERCASE_STR", + lowercase_features_str, + "The feature-string as above, from lowercase strings." + ); + + Ok(()) + } + + pub fn write_cfg(&self, mut w: &fs::File) -> io::Result<()> { + use io::Write; + + write_str_variable!( + w, + "CFG_TARGET_ARCH", + self.get_override_var("CFG_TARGET_ARCH") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_ARCH").unwrap()), + "The target architecture, given by `CARGO_CFG_TARGET_ARCH`." + ); + + write_str_variable!( + w, + "CFG_ENDIAN", + self.get_override_var("CFG_ENDIAN") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_ENDIAN").unwrap()), + "The endianness, given by `CARGO_CFG_TARGET_ENDIAN`." + ); + + write_str_variable!( + w, + "CFG_ENV", + self.get_override_var("CFG_ENV") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_ENV").unwrap()), + "The toolchain-environment, given by `CARGO_CFG_TARGET_ENV`." + ); + + write_str_variable!( + w, + "CFG_FAMILY", + self.get_override_var("CFG_FAMILY") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_FAMILY").unwrap_or_default()), + "The OS-family, given by `CARGO_CFG_TARGET_FAMILY`." + ); + + write_str_variable!( + w, + "CFG_OS", + self.get_override_var("CFG_OS") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_OS").unwrap()), + "The operating system, given by `CARGO_CFG_TARGET_OS`." + ); + + write_str_variable!( + w, + "CFG_POINTER_WIDTH", + self.get_override_var("CFG_POINTER_WIDTH") + .unwrap_or_else(|| self.get("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap()), + "The pointer width, given by `CARGO_CFG_TARGET_POINTER_WIDTH`." + ); + + Ok(()) + } + + pub fn write_compiler_version(&self, mut w: &fs::File) -> io::Result<()> { + use std::io::Write; + + let rustc; + let rustc_version; + match self.get_override_var("RUSTC") { + Some(v) => { + rustc = v; + rustc_version = self + .get_override_var("RUSTC_VERSION") + .expect("RUSTC_VERSION must be overridden if RUSTC is") + } + None => { + rustc = self.get("RUSTC").unwrap(); + rustc_version = get_version_from_cmd(rustc.as_ref())?; + } + } + + let rustdoc; + let rustdoc_version; + match self.get_override_var("RUSTDOC") { + Some(v) => { + rustdoc = v; + rustdoc_version = self.get_override_var("RUSTDOC_VERSION").unwrap_or_default(); + } + None => { + rustdoc = self.get("RUSTDOC").unwrap(); + rustdoc_version = get_version_from_cmd(rustdoc.as_ref()).unwrap_or_default(); + } + } + + write_str_variable!( + w, + "RUSTC_VERSION", + rustc_version, + format_args!("The output of `{rustc} -V`") + ); + + write_str_variable!( + w, + "RUSTDOC_VERSION", + rustdoc_version, + format_args!( + "The output of `{rustdoc} -V`; empty string if `{rustdoc} -V` failed to execute" + ) + ); + Ok(()) + } + + pub fn detect_ci(&self) -> Option { + macro_rules! detect { + ($(($k:expr, $v:expr, $i:ident)),*) => {$( + if self.get($k).map_or(false, |v| v == $v) { + return Some(CIPlatform::$i); + } + )*}; + ($(($k:expr, $i:ident)),*) => {$( + if self.contains_key($k) { + return Some(CIPlatform::$i); + } + )*}; + ($($k:expr),*) => {$( + if self.contains_key($k) { + return Some(CIPlatform::Generic); + } + )*}; + } + // Variable names collected by watson/ci-info + detect!( + ("TRAVIS", Travis), + ("CIRCLECI", Circle), + ("GITLAB_CI", GitLab), + ("APPVEYOR", AppVeyor), + ("DRONE", Drone), + ("MAGNUM", Magnum), + ("SEMAPHORE", Semaphore), + ("JENKINS_URL", Jenkins), + ("bamboo_planKey", Bamboo), + ("TF_BUILD", TFS), + ("TEAMCITY_VERSION", TeamCity), + ("BUILDKITE", Buildkite), + ("HUDSON_URL", Hudson), + ("GO_PIPELINE_LABEL", GoCD), + ("BITBUCKET_COMMIT", BitBucket), + ("GITHUB_ACTIONS", GitHubActions) + ); + + if self.contains_key("TASK_ID") && self.contains_key("RUN_ID") { + return Some(CIPlatform::TaskCluster); + } + + detect!(("CI_NAME", "codeship", Codeship)); + + detect!( + "CI", // Could be Travis, Circle, GitLab, AppVeyor or CodeShip + "CONTINUOUS_INTEGRATION", // Probably Travis + "BUILD_NUMBER" // Jenkins, TeamCity + ); + None + } +} + +/// Various Continuous Integration platforms whose presence can be detected. +pub enum CIPlatform { + /// + Travis, + /// + Circle, + /// + GitLab, + /// + AppVeyor, + /// + Codeship, + /// + Drone, + /// + Magnum, + /// + Semaphore, + /// + Jenkins, + /// + Bamboo, + /// + TFS, + /// + TeamCity, + /// + Buildkite, + /// + Hudson, + /// + TaskCluster, + /// + GoCD, + /// + BitBucket, + /// + GitHubActions, + /// Unspecific + Generic, +} + +impl fmt::Display for CIPlatform { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match *self { + CIPlatform::Travis => "Travis CI", + CIPlatform::Circle => "CircleCI", + CIPlatform::GitLab => "GitLab", + CIPlatform::AppVeyor => "AppVeyor", + CIPlatform::Codeship => "CodeShip", + CIPlatform::Drone => "Drone", + CIPlatform::Magnum => "Magnum", + CIPlatform::Semaphore => "Semaphore", + CIPlatform::Jenkins => "Jenkins", + CIPlatform::Bamboo => "Bamboo", + CIPlatform::TFS => "Team Foundation Server", + CIPlatform::TeamCity => "TeamCity", + CIPlatform::Buildkite => "Buildkite", + CIPlatform::Hudson => "Hudson", + CIPlatform::TaskCluster => "TaskCluster", + CIPlatform::GoCD => "GoCD", + CIPlatform::BitBucket => "BitBucket", + CIPlatform::GitHubActions => "GitHub Actions", + CIPlatform::Generic => "Generic CI", + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/git.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/git.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/git.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/git.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,332 @@ +use crate::{environment, fmt_option_str, write_variable}; +use std::{fs, io, path}; + +pub fn write_git_version( + manifest_location: &path::Path, + envmap: &environment::EnvironmentMap, + mut w: &fs::File, +) -> io::Result<()> { + use io::Write; + + // CIs will do shallow clones of repositories, causing libgit2 to error + // out. We try to detect if we are running on a CI and ignore the + // error. + let (mut tag, mut dirty) = ( + envmap.get_override_var("GIT_VERSION"), + envmap.get_override_var("GIT_DIRTY"), + ); + if tag.is_none() || dirty.is_none() { + if let Some((git_tag, git_dirty)) = get_repo_description(manifest_location).ok().flatten() { + if tag.is_none() { + tag = Some(git_tag); + } + if dirty.is_none() { + dirty = Some(git_dirty); + } + }; + } + write_variable!( + w, + "GIT_VERSION", + "Option<&str>", + fmt_option_str(tag), + "If the crate was compiled from within a git-repository, \ + `GIT_VERSION` contains HEAD's tag. The short commit id is used if HEAD is not tagged." + ); + write_variable!( + w, + "GIT_DIRTY", + "Option", + match dirty { + Some(true) => "Some(true)", + Some(false) => "Some(false)", + None => "None", + }, + "If the repository had dirty/staged files." + ); + + let (mut branch, mut commit, mut commit_short) = ( + envmap.get_override_var("GIT_HEAD_REF"), + envmap.get_override_var::("GIT_COMMIT_HASH"), + envmap.get_override_var("GIT_COMMIT_HASH_SHORT"), + ); + if branch.is_none() || commit.is_none() || commit_short.is_none() { + if let Some((git_branch, git_commit, git_commit_short)) = + get_repo_head(manifest_location).ok().flatten() + { + if branch.is_none() { + branch = git_branch; + } + if commit.is_none() { + commit = Some(git_commit); + } + if commit_short.is_none() { + commit_short = Some(git_commit_short); + } + } + } + if let (Some(h), None) = (&commit, &commit_short) { + commit_short = Some(h.chars().take(8).collect()) + } + + let doc = "If the crate was compiled from within a git-repository, `GIT_HEAD_REF` \ + contains full name to the reference pointed to by HEAD \ + (e.g.: `refs/heads/master`). If HEAD is detached or the branch name is not \ + valid UTF-8 `None` will be stored.\n"; + write_variable!( + w, + "GIT_HEAD_REF", + "Option<&str>", + fmt_option_str(branch), + doc + ); + + write_variable!( + w, + "GIT_COMMIT_HASH", + "Option<&str>", + fmt_option_str(commit), + "If the crate was compiled from within a git-repository, `GIT_COMMIT_HASH` \ + contains HEAD's full commit SHA-1 hash." + ); + + write_variable!( + w, + "GIT_COMMIT_HASH_SHORT", + "Option<&str>", + fmt_option_str(commit_short), + "If the crate was compiled from within a git-repository, `GIT_COMMIT_HASH_SHORT` \ + contains HEAD's short commit SHA-1 hash." + ); + + Ok(()) +} + +/// Retrieves the git-tag or hash describing the exact version and a boolean +/// that indicates if the repository currently has dirty/staged files. +/// +/// If a valid git-repo can't be discovered at or above the given path, +/// `Ok(None)` is returned instead of an `Err`-value. +/// +/// # Errors +/// Errors from `git2` are returned if the repository does exists at all. +#[cfg(feature = "git2")] +pub fn get_repo_description(root: &std::path::Path) -> Result, git2::Error> { + match git2::Repository::discover(root) { + Ok(repo) => { + let mut desc_opt = git2::DescribeOptions::new(); + desc_opt.describe_tags().show_commit_oid_as_fallback(true); + let tag = repo + .describe(&desc_opt) + .and_then(|desc| desc.format(None))?; + let mut st_opt = git2::StatusOptions::new(); + st_opt.include_ignored(false); + st_opt.include_untracked(false); + let dirty = repo + .statuses(Some(&mut st_opt))? + .iter() + .any(|status| !matches!(status.status(), git2::Status::CURRENT)); + Ok(Some((tag, dirty))) + } + Err(ref e) + if e.class() == git2::ErrorClass::Repository + && e.code() == git2::ErrorCode::NotFound => + { + Ok(None) + } + Err(e) => Err(e), + } +} + +/// Retrieves the branch name and hash of HEAD. +/// +/// The returned value is a tuple of head's reference-name, long-hash and short-hash. The +/// branch name will be `None` if the head is detached, or it's not valid UTF-8. +/// +/// If a valid git-repo can't be discovered at or above the given path, +/// `Ok(None)` is returned instead of an `Err`-value. +/// +/// # Errors +/// Errors from `git2` are returned if the repository does exists at all. +#[cfg(feature = "git2")] +pub fn get_repo_head( + root: &std::path::Path, +) -> Result, String, String)>, git2::Error> { + match git2::Repository::discover(root) { + Ok(repo) => { + // Supposed to be the reference pointed to by HEAD, but it's HEAD + // itself, if detached + let head_ref = repo.head()?; + let branch = { + // Check whether `head` is really the pointed to reference and + // not HEAD itself. + if repo.head_detached()? { + None + } else { + head_ref.name() + } + }; + let head = head_ref.peel_to_commit()?; + let commit = head.id(); + let commit_short = head.into_object().short_id()?; + Ok(Some(( + branch.map(ToString::to_string), + format!("{commit}"), + commit_short.as_str().unwrap_or_default().to_string(), + ))) + } + Err(ref e) + if e.class() == git2::ErrorClass::Repository + && e.code() == git2::ErrorCode::NotFound => + { + Ok(None) + } + Err(e) => Err(e), + } +} + +#[cfg(test)] +mod tests { + #[test] + fn parse_git_repo() { + use std::fs; + use std::path; + + let repo_root = tempfile::tempdir().unwrap(); + assert_eq!(super::get_repo_description(repo_root.as_ref()), Ok(None)); + + let repo = git2::Repository::init_opts( + &repo_root, + git2::RepositoryInitOptions::new() + .external_template(false) + .mkdir(false) + .no_reinit(true) + .mkpath(false), + ) + .unwrap(); + + let cruft_file = repo_root.path().join("cruftfile"); + std::fs::write(&cruft_file, "Who? Me?").unwrap(); + + let project_root = repo_root.path().join("project_root"); + fs::create_dir(&project_root).unwrap(); + + let sig = git2::Signature::now("foo", "bar").unwrap(); + let mut idx = repo.index().unwrap(); + idx.add_path(path::Path::new("cruftfile")).unwrap(); + idx.write().unwrap(); + let commit_oid = repo + .commit( + Some("HEAD"), + &sig, + &sig, + "Testing testing 1 2 3", + &repo.find_tree(idx.write_tree().unwrap()).unwrap(), + &[], + ) + .unwrap(); + + let binding = repo + .find_commit(commit_oid) + .unwrap() + .into_object() + .short_id() + .unwrap(); + + let commit_oid_short = binding.as_str().unwrap(); + + let commit_hash = commit_oid.to_string(); + let commit_hash_short = commit_oid_short.to_string(); + + assert!(commit_hash.starts_with(&commit_hash_short)); + + // The commit, the commit-id is something and the repo is not dirty + let (tag, dirty) = super::get_repo_description(&project_root).unwrap().unwrap(); + assert!(!tag.is_empty()); + assert!(!dirty); + + // Tag the commit, it should be retrieved + repo.tag( + "foobar", + &repo + .find_object(commit_oid, Some(git2::ObjectType::Commit)) + .unwrap(), + &sig, + "Tagged foobar", + false, + ) + .unwrap(); + + let (tag, dirty) = super::get_repo_description(&project_root).unwrap().unwrap(); + assert_eq!(tag, "foobar"); + assert!(!dirty); + + // Make some dirt + std::fs::write(cruft_file, "now dirty").unwrap(); + let (tag, dirty) = super::get_repo_description(&project_root).unwrap().unwrap(); + assert_eq!(tag, "foobar"); + assert!(dirty); + + let branch_short_name = "baz"; + let branch_name = "refs/heads/baz"; + let commit = repo.find_commit(commit_oid).unwrap(); + repo.branch(branch_short_name, &commit, true).unwrap(); + repo.set_head(branch_name).unwrap(); + + assert_eq!( + super::get_repo_head(&project_root), + Ok(Some(( + Some(branch_name.to_owned()), + commit_hash, + commit_hash_short + ))) + ); + } + + #[test] + fn detached_head_repo() { + let repo_root = tempfile::tempdir().unwrap(); + let repo = git2::Repository::init_opts( + &repo_root, + git2::RepositoryInitOptions::new() + .external_template(false) + .mkdir(false) + .no_reinit(true) + .mkpath(false), + ) + .unwrap(); + let sig = git2::Signature::now("foo", "bar").unwrap(); + let commit_oid = repo + .commit( + Some("HEAD"), + &sig, + &sig, + "Testing", + &repo + .find_tree(repo.index().unwrap().write_tree().unwrap()) + .unwrap(), + &[], + ) + .unwrap(); + + let binding = repo + .find_commit(commit_oid) + .unwrap() + .into_object() + .short_id() + .unwrap(); + + let commit_oid_short = binding.as_str().unwrap(); + + let commit_hash = commit_oid.to_string(); + let commit_hash_short = commit_oid_short.to_string(); + + assert!(commit_hash.starts_with(&commit_hash_short)); + + repo.set_head_detached(commit_oid).unwrap(); + assert_eq!( + super::get_repo_head(repo_root.as_ref()), + Ok(Some((None, commit_hash, commit_hash_short))) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/krono.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/krono.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/krono.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/krono.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +use crate::{environment, util, write_str_variable, write_variable}; +use std::{fs, io}; + +impl<'a> util::ParseFromEnv<'a> for chrono::DateTime { + type Err = chrono::ParseError; + + fn parse_from_env(s: &'a str) -> Result { + Ok(chrono::DateTime::parse_from_rfc2822(s)?.with_timezone(&chrono::offset::Utc)) + } +} + +/// Parse a time-string as formatted by `built`. +/// +/// ``` +/// use chrono::Datelike; +/// +/// pub mod build_info { +/// pub static BUILT_TIME_UTC: &'static str = "Tue, 14 Feb 2017 05:21:41 GMT"; +/// } +/// +/// assert_eq!(built::util::strptime(&build_info::BUILT_TIME_UTC).year(), 2017); +/// ``` +/// +/// # Panics +/// If the string can't be parsed. This should never happen with input provided +/// by `built`. +#[must_use] +pub fn strptime(s: &str) -> chrono::DateTime { + chrono::DateTime::parse_from_rfc2822(s) + .unwrap() + .with_timezone(&chrono::offset::Utc) +} + +fn get_source_date_epoch_from_env() -> Option> { + match std::env::var(crate::SOURCE_DATE_EPOCH) { + Ok(val) => { + let ts = match val.parse::() { + Ok(ts) => ts, + Err(_) => { + eprintln!("SOURCE_DATE_EPOCH defined, but not a i64"); + return None; + } + }; + match chrono::DateTime::from_timestamp(ts, 0) { + Some(now) => Some(now), + None => { + eprintln!("SOURCE_DATE_EPOCH can't be represented as a UTC-time"); + None + } + } + } + Err(_) => None, + } +} + +pub fn write_time(mut w: &fs::File, envmap: &environment::EnvironmentMap) -> io::Result<()> { + use io::Write; + + let now = match envmap.get_override_var("BUILT_TIME_UTC") { + Some(v) => v, + None => get_source_date_epoch_from_env().unwrap_or_else(chrono::offset::Utc::now), + }; + write_str_variable!( + w, + "BUILT_TIME_UTC", + now.to_rfc2822(), + "The build time in RFC2822, UTC." + ); + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,526 @@ +// MIT License +// +// Copyright (c) Lukas Lueg +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +#![allow(clippy::needless_doctest_main)] + +//! Provides a crate with information from the time it was built. +//! +//! `built` is used as a build-time dependency to collect various information +//! about the build-environment, serialize this information into Rust-code and +//! provide that to the crate. The information collected by `built` include: +//! +//! * Various metadata like version, authors, homepage etc. as set by `Cargo.toml` +//! * The tag or commit id if the crate was being compiled from within a Git repository. +//! * The values of `CARGO_CFG_*` build script environment variables, like `CARGO_CFG_TARGET_OS` and `CARGO_CFG_TARGET_ARCH`. +//! * The features the crate was compiled with. +//! * The various dependencies, dependencies of dependencies and their versions Cargo ultimately chose to compile. +//! * The presence of a CI-platform like `Github Actions`, `Travis CI` and `AppVeyor`. +//! * The compiler and it's version; the documentation-generator and it's version. +//! +//! `built` does not add any further runtime-dependencies to a crate; all information +//! is serialized as types from `stdlib`. One can include `built` as a +//! runtime-dependency and use it's convenience functions. +//! +//! To add `built` to a crate, add it as a build-time dependency, use a build-script +//! to collect and serialize the build-time information, and `include!` the generated code. +//! +//! Add this to `Cargo.toml`: +//! +//! ```toml +//! [package] +//! build = "build.rs" +//! +//! [build-dependencies] +//! built = "0.7" +//! ``` +//! +//! Add or modify a build-script. In `build.rs`: +//! +//! ```rust,no_run +//! fn main() { +//! built::write_built_file().expect("Failed to acquire build-time information"); +//! } +//! ``` +//! +//! The build-script will by default write a file named `built.rs` into Cargo's output +//! directory. It can be picked up in `main.rs` (or anywhere else) like this: +//! +//! ```rust,ignore +//! // Use of a mod or pub mod is not actually necessary. +//! pub mod built_info { +//! // The file has been placed there by the build script. +//! include!(concat!(env!("OUT_DIR"), "/built.rs")); +//! } +//! ``` +//! +//! ...and then used somewhere in the crate's code: +//! +//! ```rust +//! # mod built_info { +//! # pub static PKG_VERSION_PRE: &str = ""; +//! # pub static CI_PLATFORM: Option<&str> = None; +//! # pub static GIT_VERSION: Option<&str> = None; +//! # pub static DEPENDENCIES: [(&str, &str); 0] = []; +//! # pub static BUILT_TIME_UTC: &str = "Tue, 14 Feb 2017 05:21:41 GMT"; +//! # } +//! # +//! # enum LogLevel { TRACE, ERROR }; +//! /// Determine if current version is a pre-release or was built from a git-repo +//! fn release_is_unstable() -> bool { +//! return !built_info::PKG_VERSION_PRE.is_empty() || built_info::GIT_VERSION.is_some() +//! } +//! +//! /// Default log-level, enhanced on CI +//! fn default_log_level() -> LogLevel { +//! if built_info::CI_PLATFORM.is_some() { +//! LogLevel::TRACE +//! } else { +//! LogLevel::ERROR +//! } +//! } +//! +//! /// The time this crate was built +//! #[cfg(feature = "chrono")] +//! fn built_time() -> built::chrono::DateTime { +//! built::util::strptime(built_info::BUILT_TIME_UTC) +//! .with_timezone(&built::chrono::offset::Local) +//! } +//! +//! /// If another crate pulls in a dependency we don't like, print a warning +//! #[cfg(feature = "semver")] +//! fn check_sane_dependencies() { +//! if built::util::parse_versions(&built_info::DEPENDENCIES) +//! .any(|(name, ver)| name == "DeleteAllMyFiles" +//! && ver < built::semver::Version::parse("1.1.4").unwrap()) { +//! eprintln!("DeleteAllMyFiles < 1.1.4 may not delete all your files. Beware!"); +//! } +//! } +//! ``` +//! +//! +//! ## Overrides +//! +//! Most values otherwise detected by `built` can be manually set using environment variables. The +//! primary use-case for this is to allow automated build-systems and package-managers to enforce +//! certain values, e.g. to hide the presence of a CI-platform and/or allow for reproducible +//! builds. +//! +//! The values set via the environment take precedence over what `built` would otherwise detect. +//! There is no mechanism to ensure that values derived from override-variables are sensible, +//! besides enforcing the correct type. +//! +//! Override-variables are prefixed by `BUILT_OVERRIDE_{PKG_NAME}_`, where `{PKG_NAME}` is the name +//! of the package as reported by `cargo`. For example, if the package is named "mypkg", and the value +//! to be overridden is named "CI_PLATFORM", then the override variable is named +//! "BUILT_OVERRIDE_mypkg_CI_PLATFORM". Remember that more than one package in a dependency-graph +//! might use `built` internally, so you might have to override multiple instances of the same +//! value. +//! Unused override variables result in a warning at compile time, albeit cargo only reports those +//! for path-specific (e.g. local) packages. +//! +//! An override-variable's text-presentation must parse to the value's respective type: +//! * Strings are used as-is. +//! * Integers and `bool` must parse via their `std::str::FromStr`-implementation. +//! * `std::option::Option` parses the string `BUILT_OVERRIDE_NONE` as `Option::None`; every other value +//! must parse as `T`. For example, `BUILT_OVERRIDE_mypkg_CI_PLATFORM=BUILT_OVERRIDE_NONE` forces +//! `CI_PLATFORM.is_none()`. +//! * List-like values are parsed as comma-separated values. +//! +//! If an override-variable can't be parsed, the build-process will abort with a `panic!()`. +//! +//! Notice that values that were overridden are recorded in `OVERRIDE_VARIABLES_USED`. +//! +//! Please refer to the respective item's documentation for more information on overrides. +//! +//! ## Feature flags +//! The information that `built` collects and makes available in `built.rs` depends +//! on the features that were enabled on the build-time dependency. +//! +//! ### _Always available_ +//! The following information is available regardless of feature-flags. +//! +//! ``` +//! /// The Continuous Integration platform detected during compilation. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CI_PLATFORM`. +//! pub static CI_PLATFORM: Option<&str> = None; +//! +//! /// The full version. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_VERSION`. +//! pub static PKG_VERSION: &str = "0.1.0"; +//! /// The major version. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_MAJOR`. +//! pub static PKG_VERSION_MAJOR: &str = "0"; +//! /// The minor version. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_MINOR`. +//! pub static PKG_VERSION_MINOR: &str = "1"; +//! /// "The patch version. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_PATCH`. +//! pub static PKG_VERSION_PATCH: &str = "0"; +//! /// "The pre-release version. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_PRE`. +//! pub static PKG_VERSION_PRE: &str = ""; +//! +//! /// "A colon-separated list of authors. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_AUTHORS`. +//! pub static PKG_AUTHORS: &str = "Lukas Lueg "; +//! +//! /// The name of the package. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_NAME`. +//! pub static PKG_NAME: &str = "example_project"; +//! /// "The description. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_DESCRIPTION`. +//! pub static PKG_DESCRIPTION: &str = ""; +//! /// "The homepage. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_HOMEPAGE`. +//! pub static PKG_HOMEPAGE: &str = ""; +//! /// "The license. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_LICENSE`. +//! pub static PKG_LICENSE: &str = "MIT"; +//! /// The source repository as advertised in Cargo.toml. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_REPOSITORY`. +//! pub static PKG_REPOSITORY: &str = ""; +//! +//! /// The target triple that was being compiled for. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_TARGET`. +//! pub static TARGET: &str = "x86_64-unknown-linux-gnu"; +//! /// The host triple of the rust compiler. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_HOST`. +//! pub static HOST: &str = "x86_64-unknown-linux-gnu"; +//! /// `release` for release builds, `debug` for other builds. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PROFILE`. +//! pub static PROFILE: &str = "debug"; +//! +//! /// The compiler that cargo resolved to use. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTC`; notice that +//! /// if `RUSTC` is overridden, `RUSTC_VERSION` *must* also be overridden. +//! pub static RUSTC: &str = "rustc"; +//! /// The documentation-generator that cargo resolved to use. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTDOC`; notice that if `RUSTDOC` +//! /// is overridden, `RUSTDOC_VERSION` *must* also be overridden. +//! pub static RUSTDOC: &str = "rustdoc"; +//! /// The output of `rustc -V` +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTC_VERSION`. +//! pub static RUSTC_VERSION: &str = "rustc 1.43.1 (8d69840ab 2020-05-04)"; +//! /// The output of `rustdoc -V` +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTDOC_VERSION`. +//! pub static RUSTDOC_VERSION: &str = "rustdoc 1.43.1 (8d69840ab 2020-05-04)"; +//! +//! /// Value of OPT_LEVEL for the profile used during compilation. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_OPT_LEVEL`. +//! pub static OPT_LEVEL: &str = "0"; +//! /// The parallelism that was specified during compilation. +//! /// If `SOURCE_DATE_EPOCH` is set, `NUM_JOBS` is forced to `1`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_NUM_JOBS`. +//! pub static NUM_JOBS: u32 = 8; +//! /// "Value of DEBUG for the profile used during compilation. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_NUM_DEBUG`. +//! pub static DEBUG: bool = true; +//! +//! /// The features that were enabled during compilation. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_FEATURES`. +//! pub static FEATURES: [&str; 0] = []; +//! /// The features as a comma-separated string. +//! pub static FEATURES_STR: &str = ""; +//! /// The features as above, as lowercase strings. +//! pub static FEATURES_LOWERCASE: [&str; 0] = []; +//! /// The feature-string as above, from lowercase strings. +//! pub static FEATURES_LOWERCASE_STR: &str = ""; +//! +//! /// The target architecture, given by `CARGO_CFG_TARGET_ARCH`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_TARGET_ARCH`. +//! pub static CFG_TARGET_ARCH: &str = "x86_64"; +//! /// The endianness, given by `CARGO_CFG_TARGET_ENDIAN`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_ENDIAN`. +//! pub static CFG_ENDIAN: &str = "little"; +//! /// The toolchain-environment, given by `CARGO_CFG_TARGET_ENV`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_ENV`. +//! pub static CFG_ENV: &str = "gnu"; +//! /// The OS-family, given by `CARGO_CFG_TARGET_FAMILY`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_FAMILY`. +//! pub static CFG_FAMILY: &str = "unix"; +//! /// The operating system, given by `CARGO_CFG_TARGET_OS`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_OS`. +//! pub static CFG_OS: &str = "linux"; +//! /// The pointer width, given by `CARGO_CFG_TARGET_POINTER_WIDTH`. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_POINTER_WIDTH`. +//! pub static CFG_POINTER_WIDTH: &str = "64"; +//! +//! /// The override-variables that were used during compilation. +//! pub static OVERRIDE_VARIABLES_USED: [&str; 0] = []; +//! ``` +//! +//! ### `cargo-lock` +//! Parses `Cargo.lock`and generates representations of dependencies and their versions. +//! +//! For this to work, `Cargo.lock` needs to actually be there; this is (usually) +//! only true for executables and not for libraries. Cargo will only create a +//! `Cargo.lock` for the top-level crate in a dependency-tree. In case +//! of a library, the top-level crate will decide which crate/version +//! combination to compile and there will be no `Cargo.lock` while the library +//! gets compiled as a dependency. +//! +//! Parsing `Cargo.lock` instead of `Cargo.toml` allows to serialize the +//! precise versions Cargo chose to compile. One can't, however, distinguish +//! `build-dependencies`, `dev-dependencies` and `dependencies`. Furthermore, +//! some dependencies never show up if Cargo had not been forced to +//! actually use them (e.g. `dev-dependencies` with `cargo test` never +//! having been executed). +//! +//! Note that if the `dependency-tree`-feature is not active, the list of dependencies +//! contains the root-package(s) as well. +//! +//! ``` +//! /// An array of effective dependencies as documented by `Cargo.lock`. +//! pub static DEPENDENCIES: [(&str, &str); 37] = [("autocfg", "1.0.0"), ("bitflags", "1.2.1"), ("built", "0.4.1"), ("cargo-lock", "4.0.1"), ("cc", "1.0.54"), ("cfg-if", "0.1.10"), ("chrono", "0.4.11"), ("example_project", "0.1.0"), ("git2", "0.13.6"), ("idna", "0.2.0"), ("jobserver", "0.1.21"), ("libc", "0.2.71"), ("libgit2-sys", "0.12.6+1.0.0"), ("libz-sys", "1.0.25"), ("log", "0.4.8"), ("matches", "0.1.8"), ("num-integer", "0.1.42"), ("num-traits", "0.2.11"), ("percent-encoding", "2.1.0"), ("pkg-config", "0.3.17"), ("proc-macro2", "1.0.17"), ("quote", "1.0.6"), ("semver", "1.0.0"), ("serde", "1.0.110"), ("serde_derive", "1.0.110"), ("smallvec", "1.4.0"), ("syn", "1.0.25"), ("time", "0.1.43"), ("toml", "0.5.6"), ("unicode-bidi", "0.3.4"), ("unicode-normalization", "0.1.12"), ("unicode-xid", "0.2.0"), ("url", "2.1.1"), ("vcpkg", "0.2.8"), ("winapi", "0.3.8"), ("winapi-i686-pc-windows-gnu", "0.4.0"), ("winapi-x86_64-pc-windows-gnu", "0.4.0")]; +//! /// The effective dependencies as a comma-separated string. +//! pub static DEPENDENCIES_STR: &str = "autocfg 1.0.0, bitflags 1.2.1, built 0.4.1, cargo-lock 4.0.1, cc 1.0.54, cfg-if 0.1.10, chrono 0.4.11, example_project 0.1.0, git2 0.13.6, idna 0.2.0, jobserver 0.1.21, libc 0.2.71, libgit2-sys 0.12.6+1.0.0, libz-sys 1.0.25, log 0.4.8, matches 0.1.8, num-integer 0.1.42, num-traits 0.2.11, percent-encoding 2.1.0, pkg-config 0.3.17, proc-macro2 1.0.17, quote 1.0.6, semver 1.0.0, serde 1.0.110, serde_derive 1.0.110, smallvec 1.4.0, syn 1.0.25, time 0.1.43, toml 0.5.6, unicode-bidi 0.3.4, unicode-normalization 0.1.12, unicode-xid 0.2.0, url 2.1.1, vcpkg 0.2.8, winapi 0.3.8, winapi-i686-pc-windows-gnu 0.4.0, winapi-x86_64-pc-windows-gnu 0.4.0"; +//! ``` +//! +//! ### `dependency-tree` (implies `cargo-lock`) +//! Solve the dependency-graph in `Cargo.lock` to discern direct and indirect +//! dependencies. +//! +//! "Direct" dependencies are those which the root-package(s) depends on. +//! "Indirect" dependencies are those which are not direct dependencies. +//! +//! ``` +//! /// An array of direct dependencies as documented by `Cargo.lock`. +//! pub static DIRECT_DEPENDENCIES: [(&str, &str); 1] = [("built", "0.6.1")]; +//! /// The direct dependencies as a comma-separated string. +//! pub static DIRECT_DEPENDENCIES_STR: &str = r"built 0.6.1"; +//! +//! /// An array of indirect dependencies as documented by `Cargo.lock`. +//! pub static INDIRECT_DEPENDENCIES: [(&str, &str); 64] = [("android-tzdata", "0.1.1"), ("android_system_properties", "0.1.5"), ("autocfg", "1.1.0"), ("bitflags", "2.4.0"), ("bumpalo", "3.13.0"), ("cargo-lock", "9.0.0"), ("cc", "1.0.83"), ("cfg-if", "1.0.0"), ("chrono", "0.4.29"), ("core-foundation-sys", "0.8.4"), ("equivalent", "1.0.1"), ("example_project", "0.1.0"), ("fixedbitset", "0.4.2"), ("form_urlencoded", "1.2.0"), ("git2", "0.18.0"), ("hashbrown", "0.14.0"), ("iana-time-zone", "0.1.57"), ("iana-time-zone-haiku", "0.1.2"), ("idna", "0.4.0"), ("indexmap", "2.0.0"), ("jobserver", "0.1.26"), ("js-sys", "0.3.64"), ("libc", "0.2.147"), ("libgit2-sys", "0.16.1+1.7.1"), ("libz-sys", "1.1.12"), ("log", "0.4.20"), ("memchr", "2.6.3"), ("num-traits", "0.2.16"), ("once_cell", "1.18.0"), ("percent-encoding", "2.3.0"), ("petgraph", "0.6.4"), ("pkg-config", "0.3.27"), ("proc-macro2", "1.0.66"), ("quote", "1.0.33"), ("semver", "1.0.18"), ("serde", "1.0.188"), ("serde_derive", "1.0.188"), ("serde_spanned", "0.6.3"), ("syn", "2.0.31"), ("tinyvec", "1.6.0"), ("tinyvec_macros", "0.1.1"), ("toml", "0.7.6"), ("toml_datetime", "0.6.3"), ("toml_edit", "0.19.14"), ("unicode-bidi", "0.3.13"), ("unicode-ident", "1.0.11"), ("unicode-normalization", "0.1.22"), ("url", "2.4.1"), ("vcpkg", "0.2.15"), ("wasm-bindgen", "0.2.87"), ("wasm-bindgen-backend", "0.2.87"), ("wasm-bindgen-macro", "0.2.87"), ("wasm-bindgen-macro-support", "0.2.87"), ("wasm-bindgen-shared", "0.2.87"), ("windows", "0.48.0"), ("windows-targets", "0.48.5"), ("windows_aarch64_gnullvm", "0.48.5"), ("windows_aarch64_msvc", "0.48.5"), ("windows_i686_gnu", "0.48.5"), ("windows_i686_msvc", "0.48.5"), ("windows_x86_64_gnu", "0.48.5"), ("windows_x86_64_gnullvm", "0.48.5"), ("windows_x86_64_msvc", "0.48.5"), ("winnow", "0.5.15")]; +//! /// The indirect dependencies as a comma-separated string. +//! pub static INDIRECT_DEPENDENCIES_STR: &str = r"android-tzdata 0.1.1, android_system_properties 0.1.5, autocfg 1.1.0, bitflags 2.4.0, bumpalo 3.13.0, cargo-lock 9.0.0, cc 1.0.83, cfg-if 1.0.0, chrono 0.4.29, core-foundation-sys 0.8.4, equivalent 1.0.1, example_project 0.1.0, fixedbitset 0.4.2, form_urlencoded 1.2.0, git2 0.18.0, hashbrown 0.14.0, iana-time-zone 0.1.57, iana-time-zone-haiku 0.1.2, idna 0.4.0, indexmap 2.0.0, jobserver 0.1.26, js-sys 0.3.64, libc 0.2.147, libgit2-sys 0.16.1+1.7.1, libz-sys 1.1.12, log 0.4.20, memchr 2.6.3, num-traits 0.2.16, once_cell 1.18.0, percent-encoding 2.3.0, petgraph 0.6.4, pkg-config 0.3.27, proc-macro2 1.0.66, quote 1.0.33, semver 1.0.18, serde 1.0.188, serde_derive 1.0.188, serde_spanned 0.6.3, syn 2.0.31, tinyvec 1.6.0, tinyvec_macros 0.1.1, toml 0.7.6, toml_datetime 0.6.3, toml_edit 0.19.14, unicode-bidi 0.3.13, unicode-ident 1.0.11, unicode-normalization 0.1.22, url 2.4.1, vcpkg 0.2.15, wasm-bindgen 0.2.87, wasm-bindgen-backend 0.2.87, wasm-bindgen-macro 0.2.87, wasm-bindgen-macro-support 0.2.87, wasm-bindgen-shared 0.2.87, windows 0.48.0, windows-targets 0.48.5, windows_aarch64_gnullvm 0.48.5, windows_aarch64_msvc 0.48.5, windows_i686_gnu 0.48.5, windows_i686_msvc 0.48.5, windows_x86_64_gnu 0.48.5, windows_x86_64_gnullvm 0.48.5, windows_x86_64_msvc 0.48.5, winnow 0.5.15"; +//! ``` +//! +//! ### `git2` +//! Try to open the git-repository at `manifest_location` and retrieve `HEAD` +//! tag or commit id. +//! +//! Notice that `GIT_HEAD_REF` is `None` if `HEAD` is detached or not valid UTF-8. +//! +//! Continuous Integration platforms like `Travis` and `AppVeyor` will +//! do shallow clones, causing `libgit2` to be unable to get a meaningful +//! result. `GIT_VERSION` and `GIT_DIRTY` will therefore always be `None` if +//! a CI-platform is detected. +//! ``` +//! /// If the crate was compiled from within a git-repository, +//! /// `GIT_VERSION` contains HEAD's tag. The short commit id is used +//! /// if HEAD is not tagged. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_VERSION`. +//! pub static GIT_VERSION: Option<&str> = Some("0.4.1-10-gca2af4f"); +//! +//! /// If the repository had dirty/staged files. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_DIRTY`. +//! pub static GIT_DIRTY: Option = Some(true); +//! +//! /// If the crate was compiled from within a git-repository, +//! /// `GIT_HEAD_REF` contains full name to the reference pointed to by +//! /// HEAD (e.g.: `refs/heads/master`). If HEAD is detached or the branch +//! /// name is not valid UTF-8 `None` will be stored. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_HEAD_REF`. +//! pub static GIT_HEAD_REF: Option<&str> = Some("refs/heads/master"); +//! +//! /// If the crate was compiled from within a git-repository, +//! /// `GIT_COMMIT_HASH` contains HEAD's full commit SHA-1 hash. +//! /// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_GIT_COMMIT_HASH`. +//! pub static GIT_COMMIT_HASH: Option<&str> = Some("ca2af4f11bb8f4f6421c4cccf428bf4862573daf"); +//! +//! /// If the crate was compiled from within a git-repository, +//! /// `GIT_COMMIT_HASH_SHORT` contains HEAD's short commit SHA-1 hash. +//! /// Can be overriden using `BUILT_OVERRIDE_{pkg_name}_GIT_COMMIT_HASH_SHORT`. +//! pub static GIT_COMMIT_HASH_SHORT: Option<&str> = Some("ca2af4f"); +//! ``` +//! +//! ### `chrono` +//! +//! The build-time is recorded as `BUILT_TIME_UTC`. If `built` is included as a runtime-dependency, +//! it can parse the string-representation into a `time:Tm` with the help of +//! `built::util::strptime()`. +//! +//! `built` honors the environment variable `SOURCE_DATE_EPOCH`. If the variable is defined and +//! parses to a valid UTC timestamp, that build-time is used instead of the current local time. +//! The variable is silently ignored if defined but but does not parse to a valid UTC timestamp. +//! +//! ``` +//! /// The built-time in RFC2822, UTC +//! /// Can be overridden with`BUILT_OVERRIDE_BUILT_TIME_UTC`; the override takes precedence +//! /// over `SOURCE_DATE_EPOCH`; it *must* parse via `chrono::DateTime::parse_from_rfc2822()`. +//! pub static BUILT_TIME_UTC: &str = "Wed, 27 May 2020 18:12:39 +0000"; +//! ``` + +#[cfg(feature = "cargo-lock")] +mod dependencies; +mod environment; +#[cfg(feature = "git2")] +mod git; +#[cfg(feature = "chrono")] +mod krono; +pub mod util; + +use std::{env, fmt, fs, io, io::Write, path}; + +#[cfg(feature = "semver")] +pub use semver; + +#[cfg(feature = "chrono")] +pub use chrono; + +pub use environment::CIPlatform; + +#[doc = include_str!("../README.md")] +#[allow(dead_code)] +type _READMETEST = (); + +/// If `SOURCE_DATE_EPOCH` is defined, it's value is used instead of +/// `chrono::..::now()` as `BUILT_TIME_UTC`. +/// The presence of `SOURCE_DATE_EPOCH` also soft-indicates that a +/// reproducible build is desired, which we may or may not be able +/// to honor. +const SOURCE_DATE_EPOCH: &str = "SOURCE_DATE_EPOCH"; + +macro_rules! write_variable { + ($writer:expr, $name:expr, $datatype:expr, $value:expr, $doc:expr) => { + writeln!( + $writer, + "#[allow(clippy::needless_raw_string_hashes)]\n#[doc=r#\"{}\"#]\n#[allow(dead_code)]\npub static {}: {} = {};", + $doc, $name, $datatype, $value + )?; + }; +} +pub(crate) use write_variable; + +macro_rules! write_str_variable { + ($writer:expr, $name:expr, $value:expr, $doc:expr) => { + write_variable!( + $writer, + $name, + "&str", + format_args!("\"{}\"", $value.escape_default()), + $doc + ); + }; +} +pub(crate) use write_str_variable; + +pub(crate) fn fmt_option_str(o: Option) -> String { + match o { + Some(s) => format!("Some(\"{s}\")"), + None => "None".to_owned(), + } +} + +/// Writes rust-code describing the crate at `manifest_location` to a new file named `dst`. +/// +/// # Errors +/// The function returns an error if the file at `dst` already exists or can't +/// be written to. This should not be a concern if the filename points to +/// `OUR_DIR`. +pub fn write_built_file_with_opts( + #[cfg(any(feature = "cargo-lock", feature = "git2"))] manifest_location: Option<&path::Path>, + dst: &path::Path, +) -> io::Result<()> { + let mut built_file = fs::File::create(dst)?; + built_file.write_all( + r#"// +// EVERYTHING BELOW THIS POINT WAS AUTO-GENERATED DURING COMPILATION. DO NOT MODIFY. +// +"# + .as_ref(), + )?; + + let envmap = environment::EnvironmentMap::new(); + envmap.write_ci(&built_file)?; + envmap.write_env(&built_file)?; + envmap.write_features(&built_file)?; + envmap.write_compiler_version(&built_file)?; + envmap.write_cfg(&built_file)?; + + #[cfg(feature = "git2")] + { + if let Some(manifest_location) = manifest_location { + git::write_git_version(manifest_location, &envmap, &built_file)?; + } + } + + #[cfg(feature = "cargo-lock")] + if let Some(manifest_location) = manifest_location { + dependencies::write_dependencies(manifest_location, &built_file)?; + } + + #[cfg(feature = "chrono")] + krono::write_time(&built_file, &envmap)?; + + let mut used_override_vars = envmap.used_override_vars().collect::>(); + used_override_vars.sort_unstable(); + write_variable!( + built_file, + "OVERRIDE_VARIABLES_USED", + format_args!("[&str; {}]", used_override_vars.len()), + util::ArrayDisplay(&used_override_vars, |t, f| write!( + f, + "\"{}\"", + t.escape_default() + )), + "The override-variables that were used during compilation." + ); + + built_file.write_all( + r#"// +// EVERYTHING ABOVE THIS POINT WAS AUTO-GENERATED DURING COMPILATION. DO NOT MODIFY. +// +"# + .as_ref(), + )?; + + let unused_override_vars = envmap.unused_override_vars().collect::>().join(", "); + if !unused_override_vars.is_empty() { + println!("cargo::warning=At least one environment variable looks like an override-variable but was ignored by built: `{unused_override_vars}`. Typo?"); + } + + Ok(()) +} + +/// A shorthand for calling `write_built_file_with_opts()` with `CARGO_MANIFEST_DIR` and +/// `[OUT_DIR]/built.rs`. +/// +/// # Errors +/// Same as `write_built_file_with_opts()`. +/// +/// # Panics +/// If `CARGO_MANIFEST_DIR` or `OUT_DIR` are not set. +pub fn write_built_file() -> io::Result<()> { + let dst = path::Path::new(&env::var("OUT_DIR").expect("OUT_DIR not set")).join("built.rs"); + write_built_file_with_opts( + #[cfg(any(feature = "cargo-lock", feature = "git2"))] + Some( + env::var("CARGO_MANIFEST_DIR") + .expect("CARGO_MANIFEST_DIR") + .as_ref(), + ), + &dst, + )?; + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/src/util.rs clamav-1.4.6+dfsg/.cargo/vendor/built/src/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/src/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/src/util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,219 @@ +//! Various convenience functions for `built` at runtime. + +use std::fmt; +use std::fmt::Write; + +#[cfg(feature = "git2")] +pub use crate::git::{get_repo_description, get_repo_head}; + +#[cfg(feature = "chrono")] +pub use crate::krono::strptime; + +/// Parses version-strings with `semver::Version::parse()`. +/// +/// This function is only available if `built` was compiled with the +/// `semver` feature. +/// +/// The function takes a reference to an array of names and version numbers as +/// serialized by `built` and returns an iterator over the unchanged names +/// and parsed version numbers. +/// +/// ``` +/// pub mod build_info { +/// pub static DEPENDENCIES: [(&'static str, &'static str); 1] = [("built", "0.1.0")]; +/// } +/// +/// let deps = build_info::DEPENDENCIES; +/// assert!(built::util::parse_versions(&deps) +/// .any(|(name, ver)| name == "built" && +/// ver >= semver::Version::parse("0.1.0").unwrap())); +/// ``` +/// +/// # Panics +/// If a version can't be parsed by `semver::Version::parse()`. This should never +/// happen with version strings provided by Cargo and `built`. +#[cfg(feature = "semver")] +pub fn parse_versions<'a, T>( + name_and_versions: T, +) -> impl Iterator +where + T: IntoIterator, +{ + fn parse_version<'a>(t: &'a (&'a str, &'a str)) -> (&'a str, semver::Version) { + (t.0, t.1.parse().unwrap()) + } + name_and_versions.into_iter().map(parse_version) +} + +/// Detect execution on various Continuous Integration platforms. +/// +/// CI-platforms are detected by the presence of known environment variables. +/// This allows to detect specific CI-platform (like `GitLab`); various +/// generic environment variables are also checked, which may result in +/// `CIPlatform::Generic`. +/// +/// Since some platforms have fairly generic environment variables to begin with +/// (e.g. `TASK_ID`), this function may have false positives. +#[must_use] +pub fn detect_ci() -> Option { + crate::environment::EnvironmentMap::new().detect_ci() +} + +pub(crate) trait ParseFromEnv<'a> +where + Self: Sized, +{ + type Err: std::fmt::Debug; + + fn parse_from_env(s: &'a str) -> Result; +} + +impl<'a> ParseFromEnv<'a> for &'a str { + type Err = std::convert::Infallible; + + fn parse_from_env(s: &'a str) -> Result { + Ok(s) + } +} + +macro_rules! parsefromenv_impl { + ($tie:ty) => { + impl ParseFromEnv<'_> for $tie { + type Err = ::Err; + + fn parse_from_env(s: &str) -> Result { + s.parse() + } + } + }; + ($($tie:ty),+) => { + $( + parsefromenv_impl!($tie); + )+ + }; +} +parsefromenv_impl!(i64, i32, i16, i8, u64, u32, u16, u8, bool, String); + +impl<'a, T> ParseFromEnv<'a> for Vec +where + T: ParseFromEnv<'a>, +{ + type Err = >::Err; + + fn parse_from_env(s: &'a str) -> Result { + s.split(',') + .map(|chunk| T::parse_from_env(chunk.trim())) + .collect() + } +} + +impl<'a, T> ParseFromEnv<'a> for Option +where + T: ParseFromEnv<'a>, +{ + type Err = >::Err; + + fn parse_from_env(s: &'a str) -> Result { + if s == "BUILT_OVERRIDE_NONE" { + Ok(None) + } else { + Ok(Some(T::parse_from_env(s)?)) + } + } +} + +pub(crate) struct ArrayDisplay<'a, T, F>(pub &'a [T], pub F) +where + F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result; + +impl fmt::Display for ArrayDisplay<'_, T, F> +where + F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_char('[')?; + for (i, v) in self.0.iter().enumerate() { + if i != 0 { + f.write_str(", ")?; + } + (self.1)(v, f)?; + } + f.write_char(']') + } +} + +#[cfg(feature = "cargo-lock")] +pub(crate) struct TupleArrayDisplay<'a, T>(pub &'a [(T, T)]); + +#[cfg(feature = "cargo-lock")] +impl fmt::Display for TupleArrayDisplay<'_, T> +where + T: AsRef, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + ArrayDisplay(self.0, |(a, b), fmt| write!( + fmt, + r#"("{}", "{}")"#, + a.as_ref().escape_default(), + b.as_ref().escape_default() + )) + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_env() { + assert_eq!(String::parse_from_env("foo"), Ok("foo".to_owned())); + assert_eq!(<&str>::parse_from_env("foo"), Ok("foo")); + + assert_eq!(i64::parse_from_env("123"), Ok(123)); + assert_eq!(i32::parse_from_env("123"), Ok(123)); + assert_eq!(i16::parse_from_env("123"), Ok(123)); + assert_eq!(i8::parse_from_env("123"), Ok(123)); + assert_eq!(u64::parse_from_env("123"), Ok(123)); + assert_eq!(u32::parse_from_env("123"), Ok(123)); + assert_eq!(u16::parse_from_env("123"), Ok(123)); + assert_eq!(u8::parse_from_env("123"), Ok(123)); + + assert_eq!(i8::parse_from_env("-123"), Ok(-123)); + assert!(u8::parse_from_env("-123").is_err()); + assert!(i32::parse_from_env("foo").is_err()); + assert!(i32::parse_from_env("").is_err()); + + assert_eq!(bool::parse_from_env("true"), Ok(true)); + assert_eq!(bool::parse_from_env("false"), Ok(false)); + assert!(bool::parse_from_env("").is_err()); + assert!(bool::parse_from_env("foo").is_err()); + + assert!(Option::::parse_from_env("").is_err()); + assert_eq!(Option::<&str>::parse_from_env(""), Ok(Some(""))); + assert_eq!( + Option::parse_from_env("BUILT_OVERRIDE_NONE"), + Ok(Option::::None) + ); + assert_eq!(Option::parse_from_env("123"), Ok(Some(123u8))); + assert_eq!(Option::::parse_from_env("true"), Ok(Some(true))); + assert!(Option::::parse_from_env("123").is_err()); + + assert_eq!( + Vec::<&str>::parse_from_env("foo, b a r , foo"), + Ok(vec!["foo", "b a r", "foo"]) + ); + assert_eq!( + Vec::::parse_from_env("123,456,789"), + Ok(vec![123, 456, 789]) + ); + + assert_eq!( + Option::parse_from_env("123,456"), + Ok(Some(vec![123u32, 456u32])) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/built/tests/testbox_tests.rs clamav-1.4.6+dfsg/.cargo/vendor/built/tests/testbox_tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/built/tests/testbox_tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/built/tests/testbox_tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,906 @@ +use std::{ + collections, env, ffi, fs, + io::{self, Write}, + path, process, +}; + +struct Project { + root: tempfile::TempDir, + files: Vec<(path::PathBuf, Vec)>, + env: collections::HashMap, +} + +impl Project { + fn new() -> Project { + Project { + root: tempfile::tempdir().unwrap(), + files: Default::default(), + env: Default::default(), + } + } + + fn add_file, C: Into>>( + &mut self, + name: N, + content: C, + ) -> &mut Self { + self.files.push((name.into(), content.into())); + self + } + + fn set_env(&mut self, k: K, v: V) -> &mut Self + where + K: Into, + V: Into, + { + self.env.insert(k.into(), v.into()); + self + } + + fn bootstrap(&mut self) -> &mut Self { + let built_root = get_built_root(); + let features = if cfg!(feature = "git2") { + r#"["git2"]"# + } else { + "[]" + }; + + self.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "testbox" +version = "0.0.1" +build = "build.rs" + +[build-dependencies] +built = {{ path = "{}", features = {} }}"#, + built_root.display().to_string().escape_default(), + &features, + ), + ) + .add_file( + "build.rs", + r#" +fn main() { + built::write_built_file().expect("writing failed"); +}"#, + ); + self + } + + /// Hold on to the tempdir, it will be removed when dropped! + fn create(self) -> io::Result { + fs::DirBuilder::new() + .create(self.root.path().join("src")) + .unwrap(); + for (name, content) in self.files { + let fname = self.root.path().join(name); + assert!(fname.is_absolute()); + fs::create_dir_all(fname.parent().unwrap()).unwrap(); + let mut file = fs::File::create(fname)?; + file.write_all(&content)?; + } + Ok(self.root) + } + + fn create_and_run(mut self, extra_args: &[&str]) -> (String, String) { + let env = std::mem::take(&mut self.env); + let root = self.create().expect("Creating the project failed"); + Self::run(root.as_ref(), extra_args, env) + } + + fn create_and_build(self, extra_args: &[&str]) { + let root = self.create().expect("Creating the project failed"); + Self::build(root.as_ref(), extra_args); + } + + fn run(root: &std::path::Path, extra_args: &[&str], env: I) -> (String, String) + where + I: IntoIterator, + K: AsRef, + V: AsRef, + { + let cargo_result = process::Command::new("cargo") + .current_dir(root) + .arg("run") + .args(extra_args) + .envs(env) + .output() + .expect("cargo failed"); + let stderr = String::from_utf8_lossy(&cargo_result.stderr); + let stdout = String::from_utf8_lossy(&cargo_result.stdout); + assert!( + cargo_result.status.success(), + "cargo failed with {}", + stderr + ); + assert!(stdout.contains("builttestsuccess")); + (stderr.into_owned(), stdout.into_owned()) + } + + fn build(root: &std::path::Path, extra_args: &[&str]) { + let cargo_result = process::Command::new("cargo") + .current_dir(root) + .arg("build") + .args(extra_args) + .output() + .expect("cargo failed"); + assert!( + cargo_result.status.success(), + "cargo failed with {}", + String::from_utf8_lossy(&cargo_result.stderr) + ); + } + + #[cfg(feature = "git2")] + fn init_git(&self) -> git2::Repository { + git2::Repository::init_opts( + &self.root, + git2::RepositoryInitOptions::new() + .external_template(false) + .mkdir(false) + .no_reinit(true) + .mkpath(false), + ) + .expect("git-init failed") + } +} + +/// Tries to find built's Cargo.toml, panics if it ends up in / +fn get_built_root() -> path::PathBuf { + env::current_exe() + .map(|path| { + let mut path = path; + loop { + if path.join("Cargo.toml").exists() { + break; + } + path = path::PathBuf::from(path.parent().unwrap()); + } + path + }) + .unwrap() +} + +#[test] +#[ignore = "requires target x86_64-unknown-none"] +fn nostd_testbox() { + let mut p = Project::new(); + + let built_root = get_built_root(); + + p.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "nostd_testbox" +version = "1.2.3-rc1" +authors = ["Joe", "Bob"] +build = "build.rs" +description = "xobtset" +homepage = "localhost" +repository = "https://dev.example.com/sources/testbox/" +license = "MIT" + +[build-dependencies] +built = {{ path = "{}", default_features=false }} + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + +[features] +default = ["SuperAwesome", "MegaAwesome"] +SuperAwesome = [] +MegaAwesome = []"#, + built_root.display().to_string().escape_default(), + ), + ) + .add_file( + "build.rs", + r#" +fn main() { + built::write_built_file().unwrap(); +}"#, + ) + .add_file( + "src/main.rs", + r#" +#![no_main] +#![no_std] + +use core::panic::PanicInfo; + +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop {} +} + +#[no_mangle] +pub unsafe extern "C" fn main() -> ! { + loop {} +} +"#, + ); + + p.create_and_build(&["--target", "x86_64-unknown-none"]); +} + +#[test] +fn unused_override() { + let mut p = Project::new(); + p.bootstrap() + .add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + println!("builttestsuccess"); +} +"#, + ) + .set_env("BUILT_OVERRIDE_testbox_FOO", "BAR") + .set_env("BUILT_OVERRIDE_testbox1_FOO", "BAR"); + let (stderr, _) = p.create_and_run(&[]); + assert!(stderr.contains("but was ignored by built: `BUILT_OVERRIDE_testbox_FOO`.")); + assert!(!stderr.contains("but was ignored by built: `BUILT_OVERRIDE_testbox1_FOO`.")); +} + +#[test] +fn minimal_testbox() { + let mut p = Project::new(); + + let built_root = get_built_root(); + + p.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "minimal_testbox" +version = "1.2.3-rc1" +authors = ["Joe", "Bob"] +build = "build.rs" +description = "xobtset" +homepage = "localhost" +repository = "https://dev.example.com/sources/testbox/" +license = "MIT" + +[dependencies] +built = {{ path = "{built_root}", default_features=false }} + +[build-dependencies] +built = {{ path = "{built_root}", default_features=false }} + +[features] +default = ["SuperAwesome", "MegaAwesome"] +SuperAwesome = [] +MegaAwesome = []"#, + built_root = built_root.display().to_string().escape_default() + ), + ); + + p.add_file( + "build.rs", + r#" + +fn main() { + built::write_built_file().unwrap(); +}"#, + ); + + p.add_file( + "src/main.rs", + r#" +//! The minimal testbox. + +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::PKG_VERSION, "1.2.3-rc1"); + assert_eq!(built_info::PKG_VERSION_MAJOR, "1"); + assert_eq!(built_info::PKG_VERSION_MINOR, "2"); + assert_eq!(built_info::PKG_VERSION_PATCH, "3"); + assert_eq!(built_info::PKG_VERSION_PRE, "rc1"); + assert_eq!(built_info::PKG_AUTHORS, "Joe:Bob"); + assert_eq!(built_info::PKG_NAME, "minimal_testbox"); + assert_eq!(built_info::PKG_DESCRIPTION, "xobtset"); + assert_eq!(built_info::PKG_HOMEPAGE, "localhost"); + assert_eq!(built_info::PKG_LICENSE, "MIT"); + assert_eq!(built_info::PKG_REPOSITORY, "https://dev.example.com/sources/testbox/"); + assert!(built_info::NUM_JOBS > 0); + assert!(built_info::OPT_LEVEL == "0"); + assert!(built_info::DEBUG); + assert_eq!(built_info::PROFILE, "debug"); + assert_eq!(built_info::FEATURES, + ["DEFAULT", "MEGAAWESOME", "SUPERAWESOME"]); + assert_eq!(built_info::FEATURES_STR, + "DEFAULT, MEGAAWESOME, SUPERAWESOME"); + assert_eq!(built_info::FEATURES_LOWERCASE, + ["default", "megaawesome", "superawesome"]); + assert_eq!(built_info::FEATURES_LOWERCASE_STR, + "default, megaawesome, superawesome"); + assert_ne!(built_info::RUSTC_VERSION, ""); + assert_ne!(built_info::RUSTDOC_VERSION, ""); + assert_ne!(built_info::HOST, ""); + assert_ne!(built_info::TARGET, ""); + assert_ne!(built_info::RUSTC, ""); + assert_ne!(built_info::RUSTDOC, ""); + assert_ne!(built_info::CFG_TARGET_ARCH, ""); + assert_ne!(built_info::CFG_ENDIAN, ""); + assert_ne!(built_info::CFG_FAMILY, ""); + assert_ne!(built_info::CFG_OS, ""); + assert_ne!(built_info::CFG_POINTER_WIDTH, ""); + // For CFG_ENV, empty string is a possible value. + let _: &'static str = built_info::CFG_ENV; + println!("builttestsuccess"); +}"#, + ); + + p.create_and_run(&[]); +} + +#[test] +fn simple_workspace() { + let mut p = Project::new(); + let built_root = get_built_root(); + + p.add_file("Cargo.toml", "[workspace]\nmembers = ['foobar']"); + p.add_file( + "foobar/Cargo.toml", + format!( + r#"[package] +name = "foobar" +version = "5.6.7" +build = "build.rs" + +[build-dependencies] +built = {{ path = "{}" }}"#, + built_root.display().to_string().escape_default() + ), + ); + p.add_file( + "foobar/build.rs", + "fn main() { built::write_built_file().unwrap(); }", + ); + p.add_file( + "foobar/src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} +fn main() { + assert_eq!(built_info::PKG_VERSION, "5.6.7"); + println!("builttestsuccess"); +} +"#, + ); + p.create_and_run(&[]); +} + +#[test] +#[cfg(all( + feature = "cargo-lock", + feature = "dependency-tree", + feature = "git2", + feature = "chrono", + feature = "semver" +))] +fn full_testbox() { + let mut p = Project::new(); + + let built_root = get_built_root(); + + p.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "testbox" +version = "1.2.3-rc1" +authors = ["Joe", "Bob", "Harry:Potter"] +build = "build.rs" +description = "xobtset" +homepage = "localhost" +repository = "https://dev.example.com/sources/testbox/" +license = "MIT" + +[dependencies] +built = {{ path = "{built_root}", features=["cargo-lock", "dependency-tree", "git2", "chrono", "semver"] }} + +[build-dependencies] +built = {{ path = "{built_root}", features=["cargo-lock", "dependency-tree", "git2", "chrono", "semver"] }} + +[features] +default = ["SuperAwesome", "MegaAwesome"] +SuperAwesome = [] +MegaAwesome = []"#, + built_root = built_root.display().to_string().escape_default() + ), + ) + .add_file( + "build.rs", + r#" +fn main() { + built::write_built_file().unwrap(); +}"#, + ) + .set_env("CONTINUOUS_INTEGRATION", "1") + .add_file( + "src/main.rs", + r#" +//! The testbox. + +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::GIT_VERSION, None); + assert_eq!(built_info::GIT_DIRTY, None); + assert_eq!(built_info::GIT_COMMIT_HASH, None); + assert_eq!(built_info::GIT_COMMIT_HASH_SHORT, None); + assert_eq!(built_info::GIT_HEAD_REF, None); + assert!(built_info::CI_PLATFORM.is_some()); + assert_eq!(built_info::PKG_VERSION, "1.2.3-rc1"); + assert_eq!(built_info::PKG_VERSION_MAJOR, "1"); + assert_eq!(built_info::PKG_VERSION_MINOR, "2"); + assert_eq!(built_info::PKG_VERSION_PATCH, "3"); + assert_eq!(built_info::PKG_VERSION_PRE, "rc1"); + assert_eq!(built_info::PKG_AUTHORS, "Joe:Bob:Harry:Potter"); + assert_eq!(built_info::PKG_NAME, "testbox"); + assert_eq!(built_info::PKG_DESCRIPTION, "xobtset"); + assert_eq!(built_info::PKG_HOMEPAGE, "localhost"); + assert_eq!(built_info::PKG_LICENSE, "MIT"); + assert_eq!(built_info::PKG_REPOSITORY, "https://dev.example.com/sources/testbox/"); + assert!(built_info::NUM_JOBS > 0); + assert!(built_info::OPT_LEVEL == "0"); + assert!(built_info::DEBUG); + assert_eq!(built_info::PROFILE, "debug"); + assert_eq!(built_info::FEATURES, + ["DEFAULT", "MEGAAWESOME", "SUPERAWESOME"]); + assert_eq!(built_info::FEATURES_STR, + "DEFAULT, MEGAAWESOME, SUPERAWESOME"); + assert_eq!(built_info::FEATURES_LOWERCASE, + ["default", "megaawesome", "superawesome"]); + assert_eq!(built_info::FEATURES_LOWERCASE_STR, + "default, megaawesome, superawesome"); + assert_ne!(built_info::RUSTC_VERSION, ""); + assert_ne!(built_info::RUSTDOC_VERSION, ""); + assert_ne!(built_info::DEPENDENCIES_STR, ""); + assert_ne!(built_info::DIRECT_DEPENDENCIES_STR, ""); + assert_ne!(built_info::INDIRECT_DEPENDENCIES_STR, ""); + assert_ne!(built_info::HOST, ""); + assert_ne!(built_info::TARGET, ""); + assert_ne!(built_info::RUSTC, ""); + assert_ne!(built_info::RUSTDOC, ""); + assert_ne!(built_info::CFG_TARGET_ARCH, ""); + assert_ne!(built_info::CFG_ENDIAN, ""); + assert_ne!(built_info::CFG_FAMILY, ""); + assert_ne!(built_info::CFG_OS, ""); + assert_ne!(built_info::CFG_POINTER_WIDTH, ""); + // For CFG_ENV, empty string is a possible value. + let _: &'static str = built_info::CFG_ENV; + + assert!(built::util::parse_versions(built_info::DEPENDENCIES.iter()) + .any(|(name, ver)| name == "toml" && ver >= built::semver::Version::parse("0.1.0").unwrap())); + + assert_eq!(built_info::DIRECT_DEPENDENCIES.len(), 1); + assert_eq!(built_info::DIRECT_DEPENDENCIES[0].0, "built"); + + assert!((built::chrono::offset::Utc::now() - built::util::strptime(built_info::BUILT_TIME_UTC)).num_days() <= 1); + + assert!(built_info::OVERRIDE_VARIABLES_USED.is_empty()); + + println!("builttestsuccess"); +}"#, + ); + p.create_and_run(&[]); +} + +#[test] +#[cfg(all(feature = "git2", feature = "chrono", feature = "semver"))] +fn overridden_testbox() { + let mut p = Project::new(); + + let built_root = get_built_root(); + + p.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "testbox" +version = "1.2.3-rc1" +authors = ["Joe", "Bob", "Harry:Potter"] +build = "build.rs" +description = "xobtset" +homepage = "localhost" +repository = "https://dev.example.com/sources/testbox/" +license = "MIT" + +[dependencies] +built = {{ path = "{built_root}", features=["git2", "chrono", "semver"] }} + +[build-dependencies] +built = {{ path = "{built_root}", features=["git2", "chrono", "semver"] }} + +[features] +default = ["SuperAwesome", "MegaAwesome"] +SuperAwesome = [] +MegaAwesome = []"#, + built_root = built_root.display().to_string().escape_default() + ), + ) + .add_file( + "build.rs", + r#" +fn main() { + built::write_built_file().unwrap(); +}"#, + ) + .set_env("BUILT_OVERRIDE_testbox_GIT_VERSION", "GIT_VERSION1") + .set_env("BUILT_OVERRIDE_testbox_GIT_DIRTY", "false") + .set_env("BUILT_OVERRIDE_testbox_GIT_COMMIT_HASH", "1234567890") + .set_env("BUILT_OVERRIDE_testbox_GIT_HEAD_REF", "GIT_REF") + .set_env("BUILT_OVERRIDE_testbox_CI_PLATFORM", "TESTBOXCI") + .set_env("BUILT_OVERRIDE_testbox_PKG_VERSION", "1.2.3.4") + .set_env("BUILT_OVERRIDE_testbox_PKG_VERSION_MAJOR", "abc") + .set_env("BUILT_OVERRIDE_testbox_PKG_VERSION_MINOR", "def") + .set_env("BUILT_OVERRIDE_testbox_PKG_VERSION_PATCH", "ghi") + .set_env("BUILT_OVERRIDE_testbox_PKG_VERSION_PRE", "jkl") + .set_env("BUILT_OVERRIDE_testbox_PKG_AUTHORS", "The council") + .set_env("BUILT_OVERRIDE_testbox_PKG_NAME", "OVERRIDEBOX") + .set_env("BUILT_OVERRIDE_testbox_PKG_DESCRIPTION", "TEST") + .set_env("BUILT_OVERRIDE_testbox_PKG_HOMEPAGE", "foreignhost") + .set_env("BUILT_OVERRIDE_testbox_PKG_LICENSE", "MITv2") + .set_env("BUILT_OVERRIDE_testbox_PKG_REPOSITORY", "8.8.8.8") + .set_env("BUILT_OVERRIDE_testbox_NUM_JOBS", "999") + .set_env( + "BUILT_OVERRIDE_testbox_OPT_LEVEL", + "not_too_fast_not_too_slow", + ) + .set_env("BUILT_OVERRIDE_testbox_DEBUG", "false") + .set_env("BUILT_OVERRIDE_testbox_PROFILE", "MEDIUM") + .set_env( + "BUILT_OVERRIDE_testbox_FEATURES", + "cup_holder,Stereo Sound, dynamic range", + ) + .set_env("BUILT_OVERRIDE_testbox_RUSTC", "overridec") + .set_env("BUILT_OVERRIDE_testbox_RUSTC_VERSION", "overridec v1") + .set_env("BUILT_OVERRIDE_testbox_RUSTDOC", "overridedoc") + .set_env("BUILT_OVERRIDE_testbox_RUSTDOC_VERSION", "overridedoc v1") + .set_env("BUILT_OVERRIDE_testbox_HOST", "overridehost") + .set_env("BUILT_OVERRIDE_testbox_TARGET", "potato") + .set_env("BUILT_OVERRIDE_testbox_CFG_TARGET_ARCH", "potatoes") + .set_env("BUILT_OVERRIDE_testbox_CFG_ENDIAN", "random") + .set_env("BUILT_OVERRIDE_testbox_CFG_FAMILY", "v0") + .set_env("BUILT_OVERRIDE_testbox_CFG_OS", "none") + .set_env("BUILT_OVERRIDE_testbox_CFG_POINTER_WIDTH", "63.9998") + .set_env("BUILT_OVERRIDE_testbox_CFG_ENV", "calm") + .set_env( + "BUILT_OVERRIDE_testbox_BUILT_TIME_UTC", + "Sat, 25 May 2024 12:15:59 +0000", + ) + .add_file( + "src/main.rs", + r#" +//! The testbox. + +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::GIT_VERSION, Some("GIT_VERSION1")); + assert_eq!(built_info::GIT_DIRTY, Some(false)); + assert_eq!(built_info::GIT_COMMIT_HASH, Some("1234567890")); + assert_eq!(built_info::GIT_COMMIT_HASH_SHORT, Some("12345678")); + assert_eq!(built_info::GIT_HEAD_REF, Some("GIT_REF")); + assert_eq!(built_info::CI_PLATFORM, Some("TESTBOXCI")); + assert_eq!(built_info::PKG_VERSION, "1.2.3.4"); + assert_eq!(built_info::PKG_VERSION_MAJOR, "abc"); + assert_eq!(built_info::PKG_VERSION_MINOR, "def"); + assert_eq!(built_info::PKG_VERSION_PATCH, "ghi"); + assert_eq!(built_info::PKG_VERSION_PRE, "jkl"); + assert_eq!(built_info::PKG_AUTHORS, "The council"); + assert_eq!(built_info::PKG_NAME, "OVERRIDEBOX"); + assert_eq!(built_info::PKG_DESCRIPTION, "TEST"); + assert_eq!(built_info::PKG_HOMEPAGE, "foreignhost"); + assert_eq!(built_info::PKG_LICENSE, "MITv2"); + assert_eq!(built_info::PKG_REPOSITORY, "8.8.8.8"); + assert_eq!(built_info::NUM_JOBS, 999); + assert_eq!(built_info::OPT_LEVEL, "not_too_fast_not_too_slow"); + assert!(!built_info::DEBUG); + assert_eq!(built_info::PROFILE, "MEDIUM"); + assert_eq!(built_info::FEATURES, + ["Stereo Sound", "cup_holder", "dynamic range"]); + assert_eq!(built_info::FEATURES_STR, + "Stereo Sound, cup_holder, dynamic range"); + assert_eq!(built_info::FEATURES_LOWERCASE, + ["cup_holder", "dynamic range", "stereo sound"]); + assert_eq!(built_info::FEATURES_LOWERCASE_STR, + "cup_holder, dynamic range, stereo sound"); + assert_eq!(built_info::RUSTC, "overridec"); + assert_eq!(built_info::RUSTC_VERSION, "overridec v1"); + assert_eq!(built_info::RUSTDOC, "overridedoc"); + assert_eq!(built_info::RUSTDOC_VERSION, "overridedoc v1"); + assert_eq!(built_info::HOST, "overridehost"); + assert_eq!(built_info::TARGET, "potato"); + assert_eq!(built_info::CFG_TARGET_ARCH, "potatoes"); + assert_eq!(built_info::CFG_ENDIAN, "random"); + assert_eq!(built_info::CFG_FAMILY, "v0"); + assert_eq!(built_info::CFG_OS, "none"); + assert_eq!(built_info::CFG_POINTER_WIDTH, "63.9998"); + assert_eq!(built_info::CFG_ENV, "calm"); + + assert_eq!(built::util::strptime(built_info::BUILT_TIME_UTC).to_rfc2822(), + "Sat, 25 May 2024 12:15:59 +0000"); + assert_eq!(built_info::OVERRIDE_VARIABLES_USED, [ + "BUILT_TIME_UTC", + "CFG_ENDIAN", + "CFG_ENV", + "CFG_FAMILY", + "CFG_OS", + "CFG_POINTER_WIDTH", + "CFG_TARGET_ARCH", + "CI_PLATFORM", + "DEBUG", + "FEATURES", + "GIT_COMMIT_HASH", + "GIT_DIRTY", + "GIT_HEAD_REF", + "GIT_VERSION", + "HOST", + "NUM_JOBS", + "OPT_LEVEL", + "PKG_AUTHORS", + "PKG_DESCRIPTION", + "PKG_HOMEPAGE", + "PKG_LICENSE", + "PKG_NAME", + "PKG_REPOSITORY", + "PKG_VERSION", + "PKG_VERSION_MAJOR", + "PKG_VERSION_MINOR", + "PKG_VERSION_PATCH", + "PKG_VERSION_PRE", + "PROFILE", + "RUSTC", + "RUSTC_VERSION", + "RUSTDOC", + "RUSTDOC_VERSION", + "TARGET", + ]); + println!("builttestsuccess"); +}"#, + ); + p.create_and_run(&[]); +} + +#[test] +#[cfg(feature = "chrono")] +fn source_date_epoch() { + let mut p = Project::new(); + let built_root = get_built_root(); + + p.add_file( + "Cargo.toml", + format!( + r#" +[package] +name = "testbox" +version = "1.2.3-rc1" +authors = ["Joe", "Bob", "Harry:Potter"] +build = "build.rs" +description = "xobtset" + +[dependencies] +built = {{ path = "{built_root}", features=["chrono"] }} + +[build-dependencies] +built = {{ path = "{built_root}", features=["chrono"] }}"#, + built_root = built_root.display().to_string().escape_default() + ), + ) + .add_file( + "build.rs", + r#" +fn main() { + built::write_built_file().unwrap(); +}"#, + ) + .add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built::util::strptime(built_info::BUILT_TIME_UTC).to_rfc2822(), + "Sat, 25 May 2024 12:15:59 +0000"); + assert_eq!(built_info::NUM_JOBS, 1); + println!("builttestsuccess"); +}"#, + ) + .set_env("SOURCE_DATE_EPOCH", "1716639359"); + p.create_and_run(&[]); +} + +#[test] +#[cfg(feature = "git2")] +fn git_no_git() { + // `root` isn't even a git-repo + let mut p = Project::new(); + p.bootstrap().add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::GIT_DIRTY, None); + println!("builttestsuccess"); +} +"#, + ); + + p.create_and_run(&[]); +} + +#[test] +#[cfg(feature = "git2")] +fn clean_then_dirty_git() { + let mut p = Project::new(); + p.bootstrap().add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::GIT_DIRTY, Some(false)); + println!("builttestsuccess"); +} +"#, + ); + let repo = p.init_git(); + let root = p.create().expect("Creating the project failed"); + + let sig = git2::Signature::now("foo", "bar").unwrap(); + + let mut idx = repo.index().unwrap(); + for p in &["src/main.rs", "build.rs"] { + idx.add_path(path::Path::new(p)).unwrap(); + } + idx.write().unwrap(); + repo.commit( + Some("HEAD"), + &sig, + &sig, + "Testing testing 1 2 3", + &repo.find_tree(idx.write_tree().unwrap()).unwrap(), + &[], + ) + .unwrap(); + Project::run( + root.as_ref(), + &[], + std::iter::empty::<(ffi::OsString, ffi::OsString)>(), + ); + + let mut f = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(root.path().join("src/main.rs")) + .unwrap(); + f.write_all( + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + assert_eq!(built_info::GIT_DIRTY, Some(true)); + assert!(built_info::GIT_COMMIT_HASH.is_some()); + assert!(built_info::GIT_COMMIT_HASH_SHORT.is_some()); + assert!(built_info::GIT_COMMIT_HASH.unwrap().starts_with(built_info::GIT_COMMIT_HASH_SHORT.unwrap())); + println!("builttestsuccess"); +} +"# + .as_bytes(), + ) + .unwrap(); + + Project::run( + root.as_ref(), + &[], + std::iter::empty::<(ffi::OsString, ffi::OsString)>(), + ); +} + +#[test] +#[cfg(feature = "git2")] +fn empty_git() { + // Issue #7, git can be there and still fail + let mut p = Project::new(); + p.bootstrap().add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + println!("builttestsuccess"); +} +"#, + ); + p.init_git(); + p.create_and_run(&[]); +} + +#[cfg(target_os = "windows")] +#[test] +fn absolute_paths() { + // Issue #35. Usually binaries we refer to are simply executables names but sometimes they are + // absolute paths, containing backslashes, and everything gets sad on this devilish platform. + + let mut p = Project::new(); + p.bootstrap().add_file( + "src/main.rs", + r#" +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +fn main() { + println!("builttestsuccess"); +} +"#, + ); + + let rustc_exe_buf = String::from_utf8( + process::Command::new("where") + .arg("rustc") + .output() + .expect("Unable to locate absolute path to rustc using `where`") + .stdout, + ) + .unwrap(); + let rustc_exe = rustc_exe_buf.split("\r\n").next().unwrap(); + + // There should at least be `C:\` + assert!(rustc_exe.contains('\\')); + + let root = p.create().expect("Creating the project failed"); + let cargo_result = process::Command::new("cargo") + .current_dir(&root) + .arg("run") + .env("RUSTC", &rustc_exe) + .output() + .expect("cargo failed"); + if !cargo_result.status.success() { + panic!( + "cargo failed with {}", + String::from_utf8_lossy(&cargo_result.stderr) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"4c72465c63386f9730cf82d7f83626f5f42f74df56d4b82f78777502e93872c1","Cargo.toml":"7bfc46e880d0b4b257569b37193ed3eaabd683518b1f5982170f355a3fbd0c4e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"65f94e99ddaf4f5d1782a6dae23f35d4293a9a01444a13135a6887017d353cee","README.md":"85ca165cde63d8c13d0c16e247c3dbbb5b5fb7814f87c52356d70f5776ccb25a","src/alloc.rs":"3a9645d9e8db1f2a8549ee928cafa5263a828f25c88ce4d2b07996ecc14bfa81","src/boxed.rs":"2e78edaff0d5ecaa6b093654685b0707fb9754ff0b1e0353e13db483a8640a5b","src/collections/collect_in.rs":"0588a4ff3967a4323abb4218bbd615af4b123639ab4fae9130c6590c258b3d15","src/collections/mod.rs":"d58dc46eb4f9fcdde574f09bc5b8646f53e42d49c169561d98e0c23e5b36848a","src/collections/raw_vec.rs":"a37069763ff1434bb12356318d0a00cc25a273f0c2fc0bfea35615785808d1c6","src/collections/str/lossy.rs":"c5d62b16e01071e2a574ae41ef6693ad12f1e6c786c5d38f7a13ebd6cb23c088","src/collections/str/mod.rs":"d82a8bd417fbf52a589d89a16ea2a0ac4f6ac920c3976ab1f5b6ac0c8493c4f2","src/collections/string.rs":"39b2a94b552a82066fa4996d65d1dea4073e2a6724b5c237d530ec46e16bc222","src/collections/vec.rs":"c75bb568bcd39b018a8b9b96f9fcac0af32414404ebb116789b35bfa3cd8dfbc","src/lib.rs":"c71735f5eac817d378fa47d9013056cb9feb55d15eb8247e50607bfb4ea4cdbd"},"package":"79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5ad972c19c89185e868d470020e5a2ddef314c8ce37d139be662d3019158e0e4","CHANGELOG.md":"4c72465c63386f9730cf82d7f83626f5f42f74df56d4b82f78777502e93872c1","Cargo.toml":"7bfc46e880d0b4b257569b37193ed3eaabd683518b1f5982170f355a3fbd0c4e","Cargo.toml.orig":"f4fa84a8c6a3346970506e7f3d854c0acfe15ddb542e8ac138e3e72c7c8d64a4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"65f94e99ddaf4f5d1782a6dae23f35d4293a9a01444a13135a6887017d353cee","README.md":"85ca165cde63d8c13d0c16e247c3dbbb5b5fb7814f87c52356d70f5776ccb25a","src/alloc.rs":"3a9645d9e8db1f2a8549ee928cafa5263a828f25c88ce4d2b07996ecc14bfa81","src/boxed.rs":"2e78edaff0d5ecaa6b093654685b0707fb9754ff0b1e0353e13db483a8640a5b","src/collections/collect_in.rs":"0588a4ff3967a4323abb4218bbd615af4b123639ab4fae9130c6590c258b3d15","src/collections/mod.rs":"d58dc46eb4f9fcdde574f09bc5b8646f53e42d49c169561d98e0c23e5b36848a","src/collections/raw_vec.rs":"a37069763ff1434bb12356318d0a00cc25a273f0c2fc0bfea35615785808d1c6","src/collections/str/lossy.rs":"c5d62b16e01071e2a574ae41ef6693ad12f1e6c786c5d38f7a13ebd6cb23c088","src/collections/str/mod.rs":"d82a8bd417fbf52a589d89a16ea2a0ac4f6ac920c3976ab1f5b6ac0c8493c4f2","src/collections/string.rs":"39b2a94b552a82066fa4996d65d1dea4073e2a6724b5c237d530ec46e16bc222","src/collections/vec.rs":"c75bb568bcd39b018a8b9b96f9fcac0af32414404ebb116789b35bfa3cd8dfbc","src/lib.rs":"c71735f5eac817d378fa47d9013056cb9feb55d15eb8247e50607bfb4ea4cdbd"},"package":"79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4eeab8847c85d5cde135ca21ae14a54e56b05224" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bumpalo/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bumpalo/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,58 @@ +[package] +authors = ["Nick Fitzgerald "] +categories = ["memory-management", "rust-patterns", "no-std"] +description = "A fast bump allocation arena for Rust." +documentation = "https://docs.rs/bumpalo" +edition = "2021" +license = "MIT OR Apache-2.0" +name = "bumpalo" +readme = "README.md" +repository = "https://github.com/fitzgen/bumpalo" +version = "3.16.0" +exclude = ["/.github/*", "/benches", "/tests", "valgrind.supp", "bumpalo.png"] +rust-version = "1.73.0" + +[package.metadata.docs.rs] +all-features = true + +[lib] +path = "src/lib.rs" +bench = false + +[[bench]] +name = "benches" +path = "benches/benches.rs" +harness = false +required-features = ["collections"] + +[[test]] +name = "try_alloc" +path = "tests/try_alloc.rs" +harness = false + +[dependencies] +# This dependency provides a version of the unstable nightly Rust `Allocator` +# trait on stable Rust. Enabling this feature means that `bumpalo` will +# implement its `Allocator` trait. +allocator-api2 = { version = "0.2.8", default-features = false, optional = true } + +# This dependency is here to allow integration with Serde, if the `serde` feature is enabled +serde = { version = "1.0.171", optional = true } + +[dev-dependencies] +quickcheck = "1.0.3" +criterion = "0.3.6" +rand = "0.8.5" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" + +[features] +default = [] +collections = [] +boxed = [] +allocator_api = [] +std = [] +serde = ["dep:serde"] + +# [profile.bench] +# debug = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo/config.toml clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo/config.toml --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo/config.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo/config.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +[alias] + +# The list of features should be the same as the one under `[package.metadata.docs.rs]` +nightly_docs = "doc --no-deps -F nightly_docs,derive,extern_crate_alloc,extern_crate_std,zeroable_maybe_uninit,zeroable_atomics,min_const_generics,wasm_simd,must_cast" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo-checksum.json 2025-06-17 01:41:32.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"97a0b8234556120873b15b5bf6ac70930f5fe38900bbcc70ba6283467a52b1f8","LICENSE-APACHE":"870e20c217d15bcfcbe53d7c5867cd8fac44a4ca0b41fc1eb843557e16063eba","LICENSE-MIT":"0b2d108c9c686a74ac312990ee8377902756a2a081a7af3b0f9d68abf0a8f1a1","LICENSE-ZLIB":"682b4c81b85e83ce6cc6e1ace38fdd97aeb4de0e972bd2b44aa0916c54af8c96","README.md":"167493de1f1ad16d13c778494ae344cd71306622c89d19002eaf7f4185c1f728","changelog.md":"bc6a75f248b44c5f9e97f99ed133b8bc6eeeb6aa1f1436442d1f6a6a3b53d6b5","rustfmt.toml":"f4c215534437936f924c937dbb1677f614761589300d6b389f3b518b3eb551b8","src/allocation.rs":"be0c1075015d32698722183523dae7d9cd679f93f6692e733dd6a361214404c9","src/anybitpattern.rs":"172bcc22ba7b38a9a36e34d0aa5efc8716bba77569a3c142f16f8103046f1d45","src/checked.rs":"35f69278bf0106ce2855bff48ae3aeb125a54c3ee4afb123cbfe135d518e68c0","src/contiguous.rs":"bb340c0f20a06aa725bb625edcb493146ba64980fd1fd9e450654aa37384c564","src/internal.rs":"2b5b4fdc1a5d14462dd604ca1f4f23116f40639d7d8b4c1a7189ce276edd8272","src/lib.rs":"752aa0122fa8e3d80dfc48d0bf694aebbbccf7a3686ca2376aca7bb60ed627c3","src/must.rs":"fed78b2a4dac5ef6758bab53a4f3bcabd8da071854bcc07dc70a255b327ec64c","src/no_uninit.rs":"4ab2f5ed29bff0b33630661154eb548f3e55581bfcf576a90397b7f8d5323201","src/offset_of.rs":"2afd190ef0462b30ade786fe813a91e7bf41cc2fa99a1d79002cbafab5964f37","src/pod.rs":"b010341e374a7c26f84286178c435f6df2e9d80f47306cb1dc29fdb0bc4d8e0f","src/pod_in_option.rs":"73bbe1d69f32d909695ce26d131aa2d81eaa31e2b4532256ebfe1a6ba68675c1","src/transparent.rs":"5e555d6d83f5fe215ce2dbc949e87977aa92ab8d6f7a9be8479f63fdeda2359f","src/zeroable.rs":"f44c0dbfe27661e39c17379e9a3a6ad458b8ca004c1fbf3d352a18aed3f093b1","src/zeroable_in_option.rs":"f74799ac3eee50116ec63a0ae4d3e351e0ab7ac807d01b4b59027bf6a68d6de6","tests/array_tests.rs":"98ca7a0dcd93e65f70d4db19643e707cafae5a249561ab151998cedb89b2e036","tests/cast_slice_tests.rs":"1869416e833757f603765afbf48152a6d32a100316529eb494b48fca6c5a8899","tests/checked_tests.rs":"27965acf20e46482b09ee56aaa2536868821be651a3b95052f40e554ecde9917","tests/derive.rs":"93b5ab70ecdd726811af9dee1702e23e964b8ceac59f727889f6a2678ad90d65","tests/doc_tests.rs":"f20708319fde62d8957909d51ee976fce394ad0891ebc4bbcf336ab026a34092","tests/offset_of_tests.rs":"fb5f91e17f984050969f8b06f1de58b5c1e80802c5deb992d3188f5ec274690f","tests/std_tests.rs":"967d4fb4cae24a374633c9b68f1ff65f86ba4c8a0e980adfe69dcaf60a9049c2","tests/transparent.rs":"ecef6e0987e28121b480942e58ce4534f13fe35667bde7f5c6e04e590b02f6a3","tests/wrapper_forgets.rs":"c6330546f6aa696245625056e7323b3916e3fb1a9fbecefe9c9e62d3726812d9"},"package":"ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"} \ No newline at end of file +{"files":{".cargo/config.toml":"a29a2d9e9b58f555a0e10be1a6bbd64af0a2018b21e4261b0a9d4106b2f0a379",".cargo_vcs_info.json":"d456b3b5eeb3534d792ba6db470f4f6b9e061c4784c393500689bbbfe2e2469f",".github/FUNDING.yml":"b22c687bd479be811728338b63c503855e21f62dbd00ca10cc081bbf4d8e833b",".github/workflows/rust.yml":"58dbeeffb200623ca4071c2cf929f8ac872213222f972d8edd089997b3cd73bc","Cargo.toml":"97a0b8234556120873b15b5bf6ac70930f5fe38900bbcc70ba6283467a52b1f8","Cargo.toml.orig":"f18061ca303b27eff7edf69c58103d5eee0e1393e6b70140322dcfbfba9e70c0","LICENSE-APACHE":"870e20c217d15bcfcbe53d7c5867cd8fac44a4ca0b41fc1eb843557e16063eba","LICENSE-MIT":"0b2d108c9c686a74ac312990ee8377902756a2a081a7af3b0f9d68abf0a8f1a1","LICENSE-ZLIB":"682b4c81b85e83ce6cc6e1ace38fdd97aeb4de0e972bd2b44aa0916c54af8c96","README.md":"167493de1f1ad16d13c778494ae344cd71306622c89d19002eaf7f4185c1f728","changelog.md":"bc6a75f248b44c5f9e97f99ed133b8bc6eeeb6aa1f1436442d1f6a6a3b53d6b5","rustfmt.toml":"f4c215534437936f924c937dbb1677f614761589300d6b389f3b518b3eb551b8","src/allocation.rs":"be0c1075015d32698722183523dae7d9cd679f93f6692e733dd6a361214404c9","src/anybitpattern.rs":"172bcc22ba7b38a9a36e34d0aa5efc8716bba77569a3c142f16f8103046f1d45","src/checked.rs":"35f69278bf0106ce2855bff48ae3aeb125a54c3ee4afb123cbfe135d518e68c0","src/contiguous.rs":"bb340c0f20a06aa725bb625edcb493146ba64980fd1fd9e450654aa37384c564","src/internal.rs":"2b5b4fdc1a5d14462dd604ca1f4f23116f40639d7d8b4c1a7189ce276edd8272","src/lib.rs":"752aa0122fa8e3d80dfc48d0bf694aebbbccf7a3686ca2376aca7bb60ed627c3","src/must.rs":"fed78b2a4dac5ef6758bab53a4f3bcabd8da071854bcc07dc70a255b327ec64c","src/no_uninit.rs":"4ab2f5ed29bff0b33630661154eb548f3e55581bfcf576a90397b7f8d5323201","src/offset_of.rs":"2afd190ef0462b30ade786fe813a91e7bf41cc2fa99a1d79002cbafab5964f37","src/pod.rs":"b010341e374a7c26f84286178c435f6df2e9d80f47306cb1dc29fdb0bc4d8e0f","src/pod_in_option.rs":"73bbe1d69f32d909695ce26d131aa2d81eaa31e2b4532256ebfe1a6ba68675c1","src/transparent.rs":"5e555d6d83f5fe215ce2dbc949e87977aa92ab8d6f7a9be8479f63fdeda2359f","src/zeroable.rs":"f44c0dbfe27661e39c17379e9a3a6ad458b8ca004c1fbf3d352a18aed3f093b1","src/zeroable_in_option.rs":"f74799ac3eee50116ec63a0ae4d3e351e0ab7ac807d01b4b59027bf6a68d6de6","tests/array_tests.rs":"98ca7a0dcd93e65f70d4db19643e707cafae5a249561ab151998cedb89b2e036","tests/cast_slice_tests.rs":"1869416e833757f603765afbf48152a6d32a100316529eb494b48fca6c5a8899","tests/checked_tests.rs":"27965acf20e46482b09ee56aaa2536868821be651a3b95052f40e554ecde9917","tests/derive.rs":"93b5ab70ecdd726811af9dee1702e23e964b8ceac59f727889f6a2678ad90d65","tests/doc_tests.rs":"f20708319fde62d8957909d51ee976fce394ad0891ebc4bbcf336ab026a34092","tests/offset_of_tests.rs":"fb5f91e17f984050969f8b06f1de58b5c1e80802c5deb992d3188f5ec274690f","tests/std_tests.rs":"967d4fb4cae24a374633c9b68f1ff65f86ba4c8a0e980adfe69dcaf60a9049c2","tests/transparent.rs":"ecef6e0987e28121b480942e58ce4534f13fe35667bde7f5c6e04e590b02f6a3","tests/wrapper_forgets.rs":"c6330546f6aa696245625056e7323b3916e3fb1a9fbecefe9c9e62d3726812d9"},"package":"ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "621848fcf09ac42000e3b9c548f17f252c7e399c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [Lokathor] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,111 @@ +name: Rust + +on: + push: {} + pull_request: {} + +env: + RUST_BACKTRACE: 1 + +jobs: + test: + name: Test Rust ${{ matrix.rust }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + # it's a little tempting to use `matrix` to do a cartesian product with + # our `--feature` config here, but doing so will be very slow, as the + # free tier only supports up to 20 job runners at a time. + include: + # versions (all on linux-x86_64) + - { rust: 1.34.0, os: ubuntu-latest } + - { rust: stable, os: ubuntu-latest } + - { rust: beta, os: ubuntu-latest } + - { rust: nightly, os: ubuntu-latest } + # non-linux platforms (ones which don't require `cross`) + - { rust: stable, os: macos-latest } + - { rust: stable, os: windows-latest } + - { rust: stable-x86_64-gnu, os: windows-latest } + - { rust: stable-i686-msvc, os: windows-latest } + - { rust: stable-i686-gnu, os: windows-latest } + steps: + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - uses: actions/checkout@v3 + - run: cargo test --verbose + - run: cargo test --verbose --no-default-features + - run: cargo test --verbose + - run: cargo test --verbose --all-features + if: matrix.rust == 'nightly' + - run: cargo test --verbose --manifest-path=derive/Cargo.toml --all-features + if: matrix.rust == 'nightly' + + cross-test: + name: Test on ${{ matrix.target }} with cross + runs-on: ubuntu-latest + strategy: + matrix: + # we once had mips runners for Big-endian coverage but those got demoted to tier 3. + target: [i686-unknown-linux-gnu] + steps: + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: nightly + - uses: actions/checkout@v3 + - run: cargo install cross + - run: cross test --verbose --target=${{ matrix.target }} --no-default-features + - run: cross test --verbose --target=${{ matrix.target }} + - run: cross test --verbose --target=${{ matrix.target }} --all-features + if: matrix.rust == 'nightly' + - run: cross test --verbose --target=${{ matrix.target }} --manifest-path=derive/Cargo.toml --all-features + if: matrix.rust == 'nightly' + + miri-test: + name: Test with miri + runs-on: ubuntu-latest + steps: + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: nightly + components: miri + - uses: actions/checkout@v3 + # Note(Lokathor): We got some cached json errors, and so we cargo clean for this run. + - run: rm -fr target + - run: cargo miri test --verbose --no-default-features + - run: cargo miri test --verbose --all-features + - run: cd derive && rm -fr target && cargo miri test --verbose --all-features + + sanitizer-test: + name: Test with -Zsanitizer=${{ matrix.sanitizer }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sanitizer: [address, memory, leak] + steps: + - uses: actions/checkout@v3 + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: nightly + components: rust-src + - name: Test with sanitizer + env: + RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + RUSTDOCFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + ASAN_OPTIONS: detect_stack_use_after_return=1 + # Asan's leak detection occasionally complains about some small leaks if + # backtraces are captured. + RUST_BACKTRACE: 0 + # We don't run `derive`'s unit tests here the way we do elsewhere (for + # example, in `miri-test` above), as at the moment we can't easily build + # the `proc_macro` runtime with sanitizers on. IIUC doing this would + # require a custom rustc build, and... lol nope. + # + # This would mean only part of the code running under the sanitizer would + # actually include the sanitizer's checks, which is a recipe for false + # positives, so we just skip it, the generated code is what we care + # about anyway. + run: | + cargo test -Zbuild-std --verbose --target=x86_64-unknown-linux-gnu --no-default-features + cargo test -Zbuild-std --verbose --target=x86_64-unknown-linux-gnu --all-features diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bytemuck/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytemuck/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,116 @@ +[package] +name = "bytemuck" +description = "A crate for mucking around with piles of bytes." +version = "1.21.0" +authors = ["Lokathor "] +repository = "https://github.com/Lokathor/bytemuck" +readme = "README.md" +keywords = ["transmute", "bytes", "casting"] +categories = ["encoding", "no-std"] +edition = "2018" +license = "Zlib OR Apache-2.0 OR MIT" +exclude = ["/pedantic.bat"] + +[features] +# In v2 we'll fix these names to be more "normal". + +# Enable deriving the various `bytemuck` traits. +derive = ["bytemuck_derive"] +# Enable features requiring items from `extern crate alloc`. +extern_crate_alloc = [] +# Enable features requiring items from `extern crate std`. +extern_crate_std = ["extern_crate_alloc"] +# Implement `Zeroable` for `MaybeUninit`. +zeroable_maybe_uninit = [] +# Implement `Zeroable` for `std::sync::atomic` types. +zeroable_atomics = [] + +# All MSRV notes below are GUIDELINES and future versions may require even more +# MSRV on any feature. + +# MSRV 1.36: Use `align_offset` method instead of casting to `usize` to check +# alignment of pointers, this *may* improve codegen in some cases (but it has +# never been formally benchmarked!) +align_offset = [] + +min_const_generics = [] # MSRV 1.51: support arrays via min_const_generics + +wasm_simd = [] # MSRV 1.54.0: support wasm simd types +aarch64_simd = [] # MSRV 1.59.0: support aarch64 simd types +avx512_simd = [] # MSRV 1.72.0: support avx512 simd types + +must_cast = [] # MSRV 1.64.0: support the `must` module. +must_cast_extra = ["must_cast"] # MSRV 1.83.0: support mutable references in const + +# Adds `TransparentWrapper` impls for stdlib types newer than bytemuck's base MSRV. +# Current MSRV 1.74.0: `core::num::Saturating`. +# MSRV may increase if impls are added for newer types. +transparentwrapper_extra = [] + +const_zeroed = [] # MSRV 1.75.0: support const `zeroed()` + +# MSRV 1.82.0: support `zeroed_*rc*` when combined with `extern_crate_alloc` +alloc_uninit = [] + +# Do not use if you can avoid it, because this is **unsound**!!!! +unsound_ptr_pod_impl = [] + +# MSRV 1.46.0: adds the `#[track_caller]` attribute to functions which may panic +track_caller = [] + +# Enables all features that are both sound and supported on the latest stable +# version of Rust, with the exception of `extern_crate_alloc` and +# `extern_crate_std`. +# Note: Enabling this feature opts out of any MSRV guarantees! +latest_stable_rust = [ + # Keep this list sorted. + "aarch64_simd", + "avx512_simd", + "align_offset", + "alloc_uninit", + "const_zeroed", + "derive", + "min_const_generics", + "must_cast", + "must_cast_extra", + "track_caller", + "transparentwrapper_extra", + "wasm_simd", + "zeroable_atomics", + "zeroable_maybe_uninit", +] + +# ALL FEATURES BELOW THIS ARE NOT SEMVER SUPPORTED! TEMPORARY ONLY! + +# Enable support for `std::simd` types. +nightly_portable_simd = [] +# Enable support for unstable `std::arch` types (such as the AVX512 types). +nightly_stdsimd = [] +# Enable `f16` and `f128` +nightly_float = [] + +# Improved documentation using the nightly toolchain +nightly_docs = [] + +[dependencies] +bytemuck_derive = { version = "1.4", path = "derive", optional = true } + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(target_arch, values("spirv"))'] } + +[package.metadata.docs.rs] +# Note(Lokathor): Don't use all-features or it would use `unsound_ptr_pod_impl` too. +features = [ + "nightly_docs", + "latest_stable_rust", + "extern_crate_alloc", + "extern_crate_std", +] + +[package.metadata.playground] +# Note(Lokathor): Don't use all-features or it would use `unsound_ptr_pod_impl` too. +features = [ + "latest_stable_rust", + "extern_crate_alloc", + "extern_crate_std", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo-checksum.json 2026-08-06 21:12:23.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"c1cb69be6db5933c4bb4ebb6591e0fe3e7b97d491face3abcf947383c218bb31","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"94ba374cb26f3c68fb83da2e5e7dce85920fc4fb827620b06b39d71a9d0e1e18","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"2f2d64924c35b7203e3e3f3d136fcb714281762d145ca3513246da5547b1d014","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"8b114080042d3292ec8de425904e4114b7f532fe3add0d807521e6cc166a17ea","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"ab3394c385b32457795931440cfb8dbca70ba5d9e1a428fcf651f7ccb2d6c34f"},"package":"1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"22f6dd88c6eafeaed5cf136324470cac49d811de2b72b731170f3624f31e39bf",".github/workflows/ci.yml":"a9ff175a9ff8e3d874351f433a4d73f59cb67601bec47c97c5fa587dc5edf60b","CHANGELOG.md":"c1cb69be6db5933c4bb4ebb6591e0fe3e7b97d491face3abcf947383c218bb31","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"94ba374cb26f3c68fb83da2e5e7dce85920fc4fb827620b06b39d71a9d0e1e18","Cargo.toml.orig":"9d03fe1393b5f6308f0368c7a37efb8516b64d4521569be5c8a0432cbc8f36a2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"2f2d64924c35b7203e3e3f3d136fcb714281762d145ca3513246da5547b1d014","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"8b114080042d3292ec8de425904e4114b7f532fe3add0d807521e6cc166a17ea","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"ab3394c385b32457795931440cfb8dbca70ba5d9e1a428fcf651f7ccb2d6c34f"},"package":"1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ec068eefa042d494475db125c4b034bd8e9e34dd" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +name: ci +on: + pull_request: + branches: + - master + push: + branches: + - master + schedule: + - cron: '00 01 * * *' + +# The section is needed to drop write-all permissions that are granted on +# `schedule` event. By specifying any permission explicitly all others are set +# to none. By using the principle of least privilege the damage a compromised +# workflow can do (because of an injection or compromised third party tool or +# action) is restricted. Currently the worklow doesn't need any additional +# permission except for pulling the code. Adding labels to issues, commenting +# on pull-requests, etc. may need additional permissions: +# +# Syntax for this section: +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions +# +# Reference for how to assign permissions on a job-by-job basis: +# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs +# +# Reference for available permissions that we can enable if needed: +# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token +permissions: + # to fetch code (actions/checkout) + contents: read + +jobs: + test: + name: test + env: + # For some builds, we use cross to test on 32-bit and big-endian + # systems. + CARGO: cargo + # When CARGO is set to CROSS, TARGET is set to `--target matrix.target`. + # Note that we only use cross on Linux, so setting a target on a + # different OS will just use normal cargo. + TARGET: + # Bump this as appropriate. We pin to a version to make sure CI + # continues to work as cross releases in the past have broken things + # in subtle ways. + CROSS_VERSION: v0.2.5 + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - build: pinned + os: ubuntu-latest + rust: 1.60.0 + - build: stable + os: ubuntu-latest + rust: stable + - build: beta + os: ubuntu-latest + rust: beta + - build: nightly + os: ubuntu-latest + rust: nightly + - build: macos + os: macos-latest + rust: stable + - build: win-msvc + os: windows-latest + rust: stable + - build: win-gnu + os: windows-latest + rust: stable-x86_64-gnu + - build: stable-x86 + os: ubuntu-latest + rust: stable + target: i686-unknown-linux-gnu + - build: stable-aarch64 + os: ubuntu-latest + rust: stable + target: aarch64-unknown-linux-gnu + - build: stable-powerpc64 + os: ubuntu-latest + rust: stable + target: powerpc64-unknown-linux-gnu + - build: stable-s390x + os: ubuntu-latest + rust: stable + target: s390x-unknown-linux-gnu + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - name: Use Cross + if: matrix.os == 'ubuntu-latest' && matrix.target != '' + run: | + # In the past, new releases of 'cross' have broken CI. So for now, we + # pin it. We also use their pre-compiled binary releases because cross + # has over 100 dependencies and takes a bit to compile. + dir="$RUNNER_TEMP/cross-download" + mkdir "$dir" + echo "$dir" >> $GITHUB_PATH + cd "$dir" + curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz" + tar xf cross-x86_64-unknown-linux-musl.tar.gz + echo "CARGO=cross" >> $GITHUB_ENV + echo "TARGET=--target ${{ matrix.target }}" >> $GITHUB_ENV + - name: Show command used for Cargo + run: | + echo "cargo command is: ${{ env.CARGO }}" + echo "target flag is: ${{ env.TARGET }}" + - name: Show CPU info for debugging + if: matrix.os == 'ubuntu-latest' + run: lscpu + - name: Build + run: ${{ env.CARGO }} build --verbose $TARGET + - name: Build (no default) + run: ${{ env.CARGO }} build --verbose $TARGET --no-default-features + - name: Build docs + run: ${{ env.CARGO }} doc --verbose $TARGET + + # Our dev dependencies evolve more rapidly than we'd like, so only run + # tests when we aren't pinning the Rust version. + - name: Tests + if: matrix.build != 'pinned' + run: ${{ env.CARGO }} test --verbose $TARGET + + - name: Tests (no default, lib only) + if: matrix.build != 'pinned' + run: ${{ env.CARGO }} test --verbose --no-default-features --lib $TARGET + + - name: Tests (i128) + if: matrix.build != 'pinned' + run: ${{ env.CARGO }} test --verbose --features i128 $TARGET + + - name: Tests (no default, lib only, i128) + if: matrix.build != 'pinned' + run: ${{ env.CARGO }} test --verbose --no-default-features --features i128 --lib $TARGET + + - name: Compile benchmarks + if: matrix.build == 'nightly' + run: cargo bench --verbose --no-run $TARGET + + - name: Compile benchmarks (no default) + if: matrix.build == 'nightly' + run: cargo bench --verbose --no-run --no-default-features $TARGET + + - name: Compile benchmarks (i128) + if: matrix.build == 'nightly' + run: cargo bench --verbose --no-run --features i128 $TARGET + + - name: Compile benchmarks (no default, i128) + if: matrix.build == 'nightly' + run: cargo bench --verbose --no-run --no-default-features --features i128 $TARGET + + miri: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + # We use nightly here so that we can use miri I guess? + toolchain: nightly + components: miri + - name: Run full test suite + run: cargo miri test --verbose + + rustfmt: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - name: Check formatting + run: cargo fmt -- --check diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/byteorder/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +name = "byteorder" +version = "1.5.0" #:version +authors = ["Andrew Gallant "] +description = "Library for reading/writing numbers in big-endian and little-endian." +documentation = "https://docs.rs/byteorder" +homepage = "https://github.com/BurntSushi/byteorder" +repository = "https://github.com/BurntSushi/byteorder" +readme = "README.md" +categories = ["encoding", "parsing", "no-std"] +keywords = ["byte", "endian", "big-endian", "little-endian", "binary"] +license = "Unlicense OR MIT" +edition = "2021" +rust-version = "1.60" + +[lib] +name = "byteorder" +bench = false + +[dev-dependencies] +quickcheck = { version = "0.9.2", default-features = false } +rand = "0.7" + +[features] +default = ["std"] +std = [] + +# This feature is no longer used and is DEPRECATED. This crate now +# automatically enables i128 support for Rust compilers that support it. The +# feature will be removed if and when a new major version is released. +i128 = [] + +[profile.bench] +opt-level = 3 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"6f4f945547751f55214188b47a54755879ba8c4ddb74ba8aea0c573d29aadfb3","Cargo.toml":"86ad0165e3fa2ad3ef17783be36336461747077416ee2279cc47a85cbfe9b786","Cargo.toml.orig":"b00ac42c0bf7483741251f313f2dbbb782f95df86426094344685c676bb62b5c","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"d1ef59814b8c766c156a2b43d9bdfc9e1e65727360b54576a2041c96645383ac","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","src/io.rs":"09963cd6169270907475bb0fe8615718a1287aa3a8c0b653a77ba5b4acae0281","src/lib.rs":"bf73dc14b78c0e331d13e58872baf93d1f7fb11bbd750e95bd5c4419867834ed"},"package":"8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7d44da06a48fe10d7e23efd9a932d18a7a2def63" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "byteorder-lite" +version = "0.1.0" +include = [ + "README.md", + "LICENSE-MIT", + "UNLICENSE", + "src/*", +] +description = "Library for reading/writing numbers in big-endian and little-endian." +homepage = "https://github.com/image-rs/byteorder-lite" +documentation = "https://docs.rs/byteorder-lite" +readme = "README.md" +keywords = [ + "byte", + "endian", + "big-endian", + "little-endian", + "binary", +] +categories = [ + "encoding", + "parsing", + "no-std", +] +license = "Unlicense OR MIT" +repository = "https://github.com/image-rs/byteorder-lite" + +[profile.bench] +opt-level = 3 + +[lib] +bench = false + +[dev-dependencies.quickcheck] +version = "0.9.2" +default-features = false + +[dev-dependencies.rand] +version = "0.7" + +[features] +default = ["std"] +std = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "byteorder-lite" +version = "0.1.0" +description = "Library for reading/writing numbers in big-endian and little-endian." +documentation = "https://docs.rs/byteorder-lite" +homepage = "https://github.com/image-rs/byteorder-lite" +repository = "https://github.com/image-rs/byteorder-lite" +readme = "README.md" +categories = ["encoding", "parsing", "no-std"] +keywords = ["byte", "endian", "big-endian", "little-endian", "binary"] +license = "Unlicense OR MIT" +edition = "2021" +rust-version = "1.60" +include = ["README.md", "LICENSE-MIT", "UNLICENSE", "src/*"] + +[lib] +bench = false + +[dev-dependencies] +quickcheck = { version = "0.9.2", default-features = false } +rand = "0.7" + +[features] +default = ["std"] +std = [] + +[profile.bench] +opt-level = 3 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/README.md clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +# byteorder-lite + +[![crates.io](https://img.shields.io/crates/v/byteorder-lite.svg)](https://crates.io/crates/byteorder-lite) +[![Documentation](https://docs.rs/byteorder-lite/badge.svg)](https://docs.rs/byteorder-lite) +[![Build Status](https://github.com/image-rs/byteorder-lite/workflows/ci/badge.svg)](https://github.com/image-rs/byteorder-lite/actions) + +This crate is a fork of the `byteorder` crate which sets +`#![forbid(unsafe_code)]`. It includes all traits and most methods from the +original crate, but the `ReadBytesExt::read_*_into` family of methods had to be +removed because they currently cannot be implemented without unsafe code. + +`byteorder-lite` is not affiliated with the main `byteorder` crate. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/UNLICENSE clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/UNLICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/UNLICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/UNLICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/src/io.rs clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/src/io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1066 @@ +use std::io::{self, Result}; + +use crate::ByteOrder; + +/// Extends [`Read`] with methods for reading numbers. (For `std::io`.) +/// +/// Most of the methods defined here have an unconstrained type parameter that +/// must be explicitly instantiated. Typically, it is instantiated with either +/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate. +/// +/// # Examples +/// +/// Read unsigned 16 bit big-endian integers from a [`Read`]: +/// +/// ```rust +/// use std::io::Cursor; +/// use byteorder_lite::{BigEndian, ReadBytesExt}; +/// +/// let mut rdr = Cursor::new(vec![2, 5, 3, 0]); +/// assert_eq!(517, rdr.read_u16::().unwrap()); +/// assert_eq!(768, rdr.read_u16::().unwrap()); +/// ``` +/// +/// [`BigEndian`]: enum.BigEndian.html +/// [`LittleEndian`]: enum.LittleEndian.html +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +pub trait ReadBytesExt: io::Read { + /// Reads an unsigned 8 bit integer from the underlying reader. + /// + /// Note that since this reads a single byte, no byte order conversions + /// are used. It is included for completeness. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read unsigned 8 bit integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::ReadBytesExt; + /// + /// let mut rdr = Cursor::new(vec![2, 5]); + /// assert_eq!(2, rdr.read_u8().unwrap()); + /// assert_eq!(5, rdr.read_u8().unwrap()); + /// ``` + #[inline] + fn read_u8(&mut self) -> Result { + let mut buf = [0; 1]; + self.read_exact(&mut buf)?; + Ok(buf[0]) + } + + /// Reads a signed 8 bit integer from the underlying reader. + /// + /// Note that since this reads a single byte, no byte order conversions + /// are used. It is included for completeness. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read signed 8 bit integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::ReadBytesExt; + /// + /// let mut rdr = Cursor::new(vec![0x02, 0xfb]); + /// assert_eq!(2, rdr.read_i8().unwrap()); + /// assert_eq!(-5, rdr.read_i8().unwrap()); + /// ``` + #[inline] + fn read_i8(&mut self) -> Result { + let mut buf = [0; 1]; + self.read_exact(&mut buf)?; + Ok(buf[0] as i8) + } + + /// Reads an unsigned 16 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read unsigned 16 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![2, 5, 3, 0]); + /// assert_eq!(517, rdr.read_u16::().unwrap()); + /// assert_eq!(768, rdr.read_u16::().unwrap()); + /// ``` + #[inline] + fn read_u16(&mut self) -> Result { + let mut buf = [0; 2]; + self.read_exact(&mut buf)?; + Ok(T::read_u16(&buf)) + } + + /// Reads a signed 16 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read signed 16 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]); + /// assert_eq!(193, rdr.read_i16::().unwrap()); + /// assert_eq!(-132, rdr.read_i16::().unwrap()); + /// ``` + #[inline] + fn read_i16(&mut self) -> Result { + let mut buf = [0; 2]; + self.read_exact(&mut buf)?; + Ok(T::read_i16(&buf)) + } + + /// Reads an unsigned 24 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read unsigned 24 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x00, 0x01, 0x0b]); + /// assert_eq!(267, rdr.read_u24::().unwrap()); + /// ``` + #[inline] + fn read_u24(&mut self) -> Result { + let mut buf = [0; 3]; + self.read_exact(&mut buf)?; + Ok(T::read_u24(&buf)) + } + + /// Reads a signed 24 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read signed 24 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0xff, 0x7a, 0x33]); + /// assert_eq!(-34253, rdr.read_i24::().unwrap()); + /// ``` + #[inline] + fn read_i24(&mut self) -> Result { + let mut buf = [0; 3]; + self.read_exact(&mut buf)?; + Ok(T::read_i24(&buf)) + } + + /// Reads an unsigned 32 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read unsigned 32 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]); + /// assert_eq!(267, rdr.read_u32::().unwrap()); + /// ``` + #[inline] + fn read_u32(&mut self) -> Result { + let mut buf = [0; 4]; + self.read_exact(&mut buf)?; + Ok(T::read_u32(&buf)) + } + + /// Reads a signed 32 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read signed 32 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]); + /// assert_eq!(-34253, rdr.read_i32::().unwrap()); + /// ``` + #[inline] + fn read_i32(&mut self) -> Result { + let mut buf = [0; 4]; + self.read_exact(&mut buf)?; + Ok(T::read_i32(&buf)) + } + + /// Reads an unsigned 48 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read unsigned 48 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0xb6, 0x71, 0x6b, 0xdc, 0x2b, 0x31]); + /// assert_eq!(200598257150769, rdr.read_u48::().unwrap()); + /// ``` + #[inline] + fn read_u48(&mut self) -> Result { + let mut buf = [0; 6]; + self.read_exact(&mut buf)?; + Ok(T::read_u48(&buf)) + } + + /// Reads a signed 48 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read signed 48 bit big-endian integers from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x9d, 0x71, 0xab, 0xe7, 0x97, 0x8f]); + /// assert_eq!(-108363435763825, rdr.read_i48::().unwrap()); + /// ``` + #[inline] + fn read_i48(&mut self) -> Result { + let mut buf = [0; 6]; + self.read_exact(&mut buf)?; + Ok(T::read_i48(&buf)) + } + + /// Reads an unsigned 64 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read an unsigned 64 bit big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83]); + /// assert_eq!(918733457491587, rdr.read_u64::().unwrap()); + /// ``` + #[inline] + fn read_u64(&mut self) -> Result { + let mut buf = [0; 8]; + self.read_exact(&mut buf)?; + Ok(T::read_u64(&buf)) + } + + /// Reads a signed 64 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read a signed 64 bit big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]); + /// assert_eq!(i64::min_value(), rdr.read_i64::().unwrap()); + /// ``` + #[inline] + fn read_i64(&mut self) -> Result { + let mut buf = [0; 8]; + self.read_exact(&mut buf)?; + Ok(T::read_i64(&buf)) + } + + /// Reads an unsigned 128 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read an unsigned 128 bit big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![ + /// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83, + /// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83 + /// ]); + /// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::().unwrap()); + /// ``` + #[inline] + fn read_u128(&mut self) -> Result { + let mut buf = [0; 16]; + self.read_exact(&mut buf)?; + Ok(T::read_u128(&buf)) + } + + /// Reads a signed 128 bit integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read a signed 128 bit big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// assert_eq!(i128::min_value(), rdr.read_i128::().unwrap()); + /// ``` + #[inline] + fn read_i128(&mut self) -> Result { + let mut buf = [0; 16]; + self.read_exact(&mut buf)?; + Ok(T::read_i128(&buf)) + } + + /// Reads an unsigned n-bytes integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read an unsigned n-byte big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x80, 0x74, 0xfa]); + /// assert_eq!(8418554, rdr.read_uint::(3).unwrap()); + #[inline] + fn read_uint(&mut self, nbytes: usize) -> Result { + let mut buf = [0; 8]; + self.read_exact(&mut buf[..nbytes])?; + Ok(T::read_uint(&buf[..nbytes], nbytes)) + } + + /// Reads a signed n-bytes integer from the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read an unsigned n-byte big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0xc1, 0xff, 0x7c]); + /// assert_eq!(-4063364, rdr.read_int::(3).unwrap()); + #[inline] + fn read_int(&mut self, nbytes: usize) -> Result { + let mut buf = [0; 8]; + self.read_exact(&mut buf[..nbytes])?; + Ok(T::read_int(&buf[..nbytes], nbytes)) + } + + /// Reads an unsigned n-bytes integer from the underlying reader. + #[inline] + fn read_uint128(&mut self, nbytes: usize) -> Result { + let mut buf = [0; 16]; + self.read_exact(&mut buf[..nbytes])?; + Ok(T::read_uint128(&buf[..nbytes], nbytes)) + } + + /// Reads a signed n-bytes integer from the underlying reader. + #[inline] + fn read_int128(&mut self, nbytes: usize) -> Result { + let mut buf = [0; 16]; + self.read_exact(&mut buf[..nbytes])?; + Ok(T::read_int128(&buf[..nbytes], nbytes)) + } + + /// Reads a IEEE754 single-precision (4 bytes) floating point number from + /// the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read a big-endian single-precision floating point number from a `Read`: + /// + /// ```rust + /// use std::f32; + /// use std::io::Cursor; + /// + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![ + /// 0x40, 0x49, 0x0f, 0xdb, + /// ]); + /// assert_eq!(f32::consts::PI, rdr.read_f32::().unwrap()); + /// ``` + #[inline] + fn read_f32(&mut self) -> Result { + let mut buf = [0; 4]; + self.read_exact(&mut buf)?; + Ok(T::read_f32(&buf)) + } + + /// Reads a IEEE754 double-precision (8 bytes) floating point number from + /// the underlying reader. + /// + /// # Errors + /// + /// This method returns the same errors as [`Read::read_exact`]. + /// + /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact + /// + /// # Examples + /// + /// Read a big-endian double-precision floating point number from a `Read`: + /// + /// ```rust + /// use std::f64; + /// use std::io::Cursor; + /// + /// use byteorder_lite::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![ + /// 0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18, + /// ]); + /// assert_eq!(f64::consts::PI, rdr.read_f64::().unwrap()); + /// ``` + #[inline] + fn read_f64(&mut self) -> Result { + let mut buf = [0; 8]; + self.read_exact(&mut buf)?; + Ok(T::read_f64(&buf)) + } +} + +/// All types that implement `Read` get methods defined in `ReadBytesExt` +/// for free. +impl ReadBytesExt for R {} + +/// Extends [`Write`] with methods for writing numbers. (For `std::io`.) +/// +/// Most of the methods defined here have an unconstrained type parameter that +/// must be explicitly instantiated. Typically, it is instantiated with either +/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate. +/// +/// # Examples +/// +/// Write unsigned 16 bit big-endian integers to a [`Write`]: +/// +/// ```rust +/// use byteorder_lite::{BigEndian, WriteBytesExt}; +/// +/// let mut wtr = vec![]; +/// wtr.write_u16::(517).unwrap(); +/// wtr.write_u16::(768).unwrap(); +/// assert_eq!(wtr, vec![2, 5, 3, 0]); +/// ``` +/// +/// [`BigEndian`]: enum.BigEndian.html +/// [`LittleEndian`]: enum.LittleEndian.html +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +pub trait WriteBytesExt: io::Write { + /// Writes an unsigned 8 bit integer to the underlying writer. + /// + /// Note that since this writes a single byte, no byte order conversions + /// are used. It is included for completeness. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 8 bit integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::WriteBytesExt; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u8(2).unwrap(); + /// wtr.write_u8(5).unwrap(); + /// assert_eq!(wtr, b"\x02\x05"); + /// ``` + #[inline] + fn write_u8(&mut self, n: u8) -> Result<()> { + self.write_all(&[n]) + } + + /// Writes a signed 8 bit integer to the underlying writer. + /// + /// Note that since this writes a single byte, no byte order conversions + /// are used. It is included for completeness. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 8 bit integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::WriteBytesExt; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i8(2).unwrap(); + /// wtr.write_i8(-5).unwrap(); + /// assert_eq!(wtr, b"\x02\xfb"); + /// ``` + #[inline] + fn write_i8(&mut self, n: i8) -> Result<()> { + self.write_all(&[n as u8]) + } + + /// Writes an unsigned 16 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 16 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u16::(517).unwrap(); + /// wtr.write_u16::(768).unwrap(); + /// assert_eq!(wtr, b"\x02\x05\x03\x00"); + /// ``` + #[inline] + fn write_u16(&mut self, n: u16) -> Result<()> { + let mut buf = [0; 2]; + T::write_u16(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 16 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 16 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i16::(193).unwrap(); + /// wtr.write_i16::(-132).unwrap(); + /// assert_eq!(wtr, b"\x00\xc1\xff\x7c"); + /// ``` + #[inline] + fn write_i16(&mut self, n: i16) -> Result<()> { + let mut buf = [0; 2]; + T::write_i16(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 24 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 24 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u24::(267).unwrap(); + /// wtr.write_u24::(120111).unwrap(); + /// assert_eq!(wtr, b"\x00\x01\x0b\x01\xd5\x2f"); + /// ``` + #[inline] + fn write_u24(&mut self, n: u32) -> Result<()> { + let mut buf = [0; 3]; + T::write_u24(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 24 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 24 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i24::(-34253).unwrap(); + /// wtr.write_i24::(120111).unwrap(); + /// assert_eq!(wtr, b"\xff\x7a\x33\x01\xd5\x2f"); + /// ``` + #[inline] + fn write_i24(&mut self, n: i32) -> Result<()> { + let mut buf = [0; 3]; + T::write_i24(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 32 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 32 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u32::(267).unwrap(); + /// wtr.write_u32::(1205419366).unwrap(); + /// assert_eq!(wtr, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66"); + /// ``` + #[inline] + fn write_u32(&mut self, n: u32) -> Result<()> { + let mut buf = [0; 4]; + T::write_u32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 32 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 32 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i32::(-34253).unwrap(); + /// wtr.write_i32::(1205419366).unwrap(); + /// assert_eq!(wtr, b"\xff\xff\x7a\x33\x47\xd9\x3d\x66"); + /// ``` + #[inline] + fn write_i32(&mut self, n: i32) -> Result<()> { + let mut buf = [0; 4]; + T::write_i32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 48 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 48 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u48::(52360336390828).unwrap(); + /// wtr.write_u48::(541).unwrap(); + /// assert_eq!(wtr, b"\x2f\x9f\x17\x40\x3a\xac\x00\x00\x00\x00\x02\x1d"); + /// ``` + #[inline] + fn write_u48(&mut self, n: u64) -> Result<()> { + let mut buf = [0; 6]; + T::write_u48(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 48 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 48 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i48::(-108363435763825).unwrap(); + /// wtr.write_i48::(77).unwrap(); + /// assert_eq!(wtr, b"\x9d\x71\xab\xe7\x97\x8f\x00\x00\x00\x00\x00\x4d"); + /// ``` + #[inline] + fn write_i48(&mut self, n: i64) -> Result<()> { + let mut buf = [0; 6]; + T::write_i48(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 64 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write unsigned 64 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_u64::(918733457491587).unwrap(); + /// wtr.write_u64::(143).unwrap(); + /// assert_eq!(wtr, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f"); + /// ``` + #[inline] + fn write_u64(&mut self, n: u64) -> Result<()> { + let mut buf = [0; 8]; + T::write_u64(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 64 bit integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write signed 64 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_i64::(i64::min_value()).unwrap(); + /// wtr.write_i64::(i64::max_value()).unwrap(); + /// assert_eq!(wtr, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff"); + /// ``` + #[inline] + fn write_i64(&mut self, n: i64) -> Result<()> { + let mut buf = [0; 8]; + T::write_i64(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 128 bit integer to the underlying writer. + #[inline] + fn write_u128(&mut self, n: u128) -> Result<()> { + let mut buf = [0; 16]; + T::write_u128(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 128 bit integer to the underlying writer. + #[inline] + fn write_i128(&mut self, n: i128) -> Result<()> { + let mut buf = [0; 16]; + T::write_i128(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned n-bytes integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Panics + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 8`, this method panics. + /// + /// # Examples + /// + /// Write unsigned 40 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_uint::(312550384361, 5).unwrap(); + /// wtr.write_uint::(43, 5).unwrap(); + /// assert_eq!(wtr, b"\x48\xc5\x74\x62\xe9\x00\x00\x00\x00\x2b"); + /// ``` + #[inline] + fn write_uint( + &mut self, + n: u64, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 8]; + T::write_uint(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes a signed n-bytes integer to the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Panics + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 8`, this method panics. + /// + /// # Examples + /// + /// Write signed 56 bit big-endian integers to a `Write`: + /// + /// ```rust + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_int::(-3548172039376767, 7).unwrap(); + /// wtr.write_int::(43, 7).unwrap(); + /// assert_eq!(wtr, b"\xf3\x64\xf4\xd1\xfd\xb0\x81\x00\x00\x00\x00\x00\x00\x2b"); + /// ``` + #[inline] + fn write_int( + &mut self, + n: i64, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 8]; + T::write_int(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes an unsigned n-bytes integer to the underlying writer. + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 16`, this method panics. + #[inline] + fn write_uint128( + &mut self, + n: u128, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 16]; + T::write_uint128(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes a signed n-bytes integer to the underlying writer. + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 16`, this method panics. + #[inline] + fn write_int128( + &mut self, + n: i128, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 16]; + T::write_int128(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes a IEEE754 single-precision (4 bytes) floating point number to + /// the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write a big-endian single-precision floating point number to a `Write`: + /// + /// ```rust + /// use std::f32; + /// + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_f32::(f32::consts::PI).unwrap(); + /// assert_eq!(wtr, b"\x40\x49\x0f\xdb"); + /// ``` + #[inline] + fn write_f32(&mut self, n: f32) -> Result<()> { + let mut buf = [0; 4]; + T::write_f32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a IEEE754 double-precision (8 bytes) floating point number to + /// the underlying writer. + /// + /// # Errors + /// + /// This method returns the same errors as [`Write::write_all`]. + /// + /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all + /// + /// # Examples + /// + /// Write a big-endian double-precision floating point number to a `Write`: + /// + /// ```rust + /// use std::f64; + /// + /// use byteorder_lite::{BigEndian, WriteBytesExt}; + /// + /// let mut wtr = Vec::new(); + /// wtr.write_f64::(f64::consts::PI).unwrap(); + /// assert_eq!(wtr, b"\x40\x09\x21\xfb\x54\x44\x2d\x18"); + /// ``` + #[inline] + fn write_f64(&mut self, n: f64) -> Result<()> { + let mut buf = [0; 8]; + T::write_f64(&mut buf, n); + self.write_all(&buf) + } +} + +/// All types that implement `Write` get methods defined in `WriteBytesExt` +/// for free. +impl WriteBytesExt for W {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/byteorder-lite/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/byteorder-lite/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3983 @@ +/*! + +This crate is a fork of the [`byteorder`] crate which sets +`#![forbid(unsafe_code)]`. It includes all traits and most methods from the +original crate, but the `ReadBytesExt::read_*_into` family of methods had to be +removed because they currently cannot be implemented without unsafe code. + +The organization of the crate is pretty simple. A trait, [`ByteOrder`], specifies +byte conversion methods for each type of number in Rust (sans numbers that have +a platform dependent size like `usize` and `isize`). Two types, [`BigEndian`] +and [`LittleEndian`] implement these methods. Finally, [`ReadBytesExt`] and +[`WriteBytesExt`] provide convenience methods available to all types that +implement [`Read`] and [`Write`]. + +An alias, [`NetworkEndian`], for [`BigEndian`] is provided to help improve +code clarity. + +An additional alias, [`NativeEndian`], is provided for the endianness of the +local platform. This is convenient when serializing data for use and +conversions are not desired. + +# Examples + +Read unsigned 16 bit big-endian integers from a [`Read`] type: + +```rust +use std::io::Cursor; +use byteorder_lite::{BigEndian, ReadBytesExt}; + +let mut rdr = Cursor::new(vec![2, 5, 3, 0]); +// Note that we use type parameters to indicate which kind of byte order +// we want! +assert_eq!(517, rdr.read_u16::().unwrap()); +assert_eq!(768, rdr.read_u16::().unwrap()); +``` + +Write unsigned 16 bit little-endian integers to a [`Write`] type: + +```rust +use byteorder_lite::{LittleEndian, WriteBytesExt}; + +let mut wtr = vec![]; +wtr.write_u16::(517).unwrap(); +wtr.write_u16::(768).unwrap(); +assert_eq!(wtr, vec![5, 2, 0, 3]); +``` + +# Optional Features + +This crate can also be used without the standard library. + +# Alternatives + +The standard numeric types provide built-in methods like `to_le_bytes` and +`from_le_bytes`, which support some of the same use cases. + +[`byteorder`]: https://crates.io/crates/byteorder +[`ByteOrder`]: trait.ByteOrder.html +[`BigEndian`]: enum.BigEndian.html +[`LittleEndian`]: enum.LittleEndian.html +[`ReadBytesExt`]: trait.ReadBytesExt.html +[`WriteBytesExt`]: trait.WriteBytesExt.html +[`NetworkEndian`]: type.NetworkEndian.html +[`NativeEndian`]: type.NativeEndian.html +[`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +*/ + +#![forbid(unsafe_code)] +#![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +// When testing under miri, we disable tests that take too long. But this +// provokes lots of dead code warnings. So we just squash them. +#![cfg_attr(miri, allow(dead_code, unused_macros))] + +use core::{fmt::Debug, hash::Hash}; + +#[cfg(feature = "std")] +pub use crate::io::{ReadBytesExt, WriteBytesExt}; + +#[cfg(feature = "std")] +mod io; + +#[inline] +fn extend_sign(val: u64, nbytes: usize) -> i64 { + let shift = (8 - nbytes) * 8; + (val << shift) as i64 >> shift +} + +#[inline] +fn extend_sign128(val: u128, nbytes: usize) -> i128 { + let shift = (16 - nbytes) * 8; + (val << shift) as i128 >> shift +} + +#[inline] +fn unextend_sign(val: i64, nbytes: usize) -> u64 { + let shift = (8 - nbytes) * 8; + (val << shift) as u64 >> shift +} + +#[inline] +fn unextend_sign128(val: i128, nbytes: usize) -> u128 { + let shift = (16 - nbytes) * 8; + (val << shift) as u128 >> shift +} + +#[inline] +fn pack_size(n: u64) -> usize { + (8 - ((n | 1).leading_zeros() >> 3)) as usize +} + +#[inline] +fn pack_size128(n: u128) -> usize { + (16 - ((n | 1).leading_zeros() >> 3)) as usize +} + +mod private { + /// Sealed stops crates other than byteorder from implementing any traits + /// that use it. + pub trait Sealed {} + impl Sealed for super::LittleEndian {} + impl Sealed for super::BigEndian {} +} + +/// `ByteOrder` describes types that can serialize integers as bytes. +/// +/// Note that `Self` does not appear anywhere in this trait's definition! +/// Therefore, in order to use it, you'll need to use syntax like +/// `T::read_u16(&[0, 1])` where `T` implements `ByteOrder`. +/// +/// This crate provides two types that implement `ByteOrder`: [`BigEndian`] +/// and [`LittleEndian`]. +/// This trait is sealed and cannot be implemented for callers to avoid +/// breaking backwards compatibility when adding new derived traits. +/// +/// # Examples +/// +/// Write and read `u32` numbers in little endian order: +/// +/// ```rust +/// use byteorder_lite::{ByteOrder, LittleEndian}; +/// +/// let mut buf = [0; 4]; +/// LittleEndian::write_u32(&mut buf, 1_000_000); +/// assert_eq!(1_000_000, LittleEndian::read_u32(&buf)); +/// ``` +/// +/// Write and read `i16` numbers in big endian order: +/// +/// ```rust +/// use byteorder_lite::{ByteOrder, BigEndian}; +/// +/// let mut buf = [0; 2]; +/// BigEndian::write_i16(&mut buf, -5_000); +/// assert_eq!(-5_000, BigEndian::read_i16(&buf)); +/// ``` +/// +/// [`BigEndian`]: enum.BigEndian.html +/// [`LittleEndian`]: enum.LittleEndian.html +pub trait ByteOrder: + Clone + + Copy + + Debug + + Default + + Eq + + Hash + + Ord + + PartialEq + + PartialOrd + + private::Sealed +{ + /// Reads an unsigned 16 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + fn read_u16(buf: &[u8]) -> u16; + + /// Reads an unsigned 24 bit integer from `buf`, stored in u32. + /// + /// # Panics + /// + /// Panics when `buf.len() < 3`. + /// + /// # Examples + /// + /// Write and read 24 bit `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_u24(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u24(&buf)); + /// ``` + fn read_u24(buf: &[u8]) -> u32 { + Self::read_uint(buf, 3) as u32 + } + + /// Reads an unsigned 32 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 4]; + /// LittleEndian::write_u32(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u32(&buf)); + /// ``` + fn read_u32(buf: &[u8]) -> u32; + + /// Reads an unsigned 48 bit integer from `buf`, stored in u64. + /// + /// # Panics + /// + /// Panics when `buf.len() < 6`. + /// + /// # Examples + /// + /// Write and read 48 bit `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 6]; + /// LittleEndian::write_u48(&mut buf, 1_000_000_000_000); + /// assert_eq!(1_000_000_000_000, LittleEndian::read_u48(&buf)); + /// ``` + fn read_u48(buf: &[u8]) -> u64 { + Self::read_uint(buf, 6) as u64 + } + + /// Reads an unsigned 64 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 8]; + /// LittleEndian::write_u64(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u64(&buf)); + /// ``` + fn read_u64(buf: &[u8]) -> u64; + + /// Reads an unsigned 128 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + /// + /// # Examples + /// + /// Write and read `u128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 16]; + /// LittleEndian::write_u128(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf)); + /// ``` + fn read_u128(buf: &[u8]) -> u128; + + /// Reads an unsigned n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 8` or + /// `buf.len() < nbytes` + /// + /// # Examples + /// + /// Write and read an n-byte number in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_uint(&mut buf, 1_000_000, 3); + /// assert_eq!(1_000_000, LittleEndian::read_uint(&buf, 3)); + /// ``` + fn read_uint(buf: &[u8], nbytes: usize) -> u64; + + /// Reads an unsigned n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 16` or + /// `buf.len() < nbytes` + /// + /// # Examples + /// + /// Write and read an n-byte number in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3); + /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3)); + /// ``` + fn read_uint128(buf: &[u8], nbytes: usize) -> u128; + + /// Writes an unsigned 16 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + /// + /// # Examples + /// + /// Write and read `u16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 2]; + /// LittleEndian::write_u16(&mut buf, 1_000); + /// assert_eq!(1_000, LittleEndian::read_u16(&buf)); + /// ``` + fn write_u16(buf: &mut [u8], n: u16); + + /// Writes an unsigned 24 bit integer `n` to `buf`, stored in u32. + /// + /// # Panics + /// + /// Panics when `buf.len() < 3`. + /// + /// # Examples + /// + /// Write and read 24 bit `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_u24(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u24(&buf)); + /// ``` + fn write_u24(buf: &mut [u8], n: u32) { + Self::write_uint(buf, n as u64, 3) + } + + /// Writes an unsigned 32 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 4]; + /// LittleEndian::write_u32(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u32(&buf)); + /// ``` + fn write_u32(buf: &mut [u8], n: u32); + + /// Writes an unsigned 48 bit integer `n` to `buf`, stored in u64. + /// + /// # Panics + /// + /// Panics when `buf.len() < 6`. + /// + /// # Examples + /// + /// Write and read 48 bit `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 6]; + /// LittleEndian::write_u48(&mut buf, 1_000_000_000_000); + /// assert_eq!(1_000_000_000_000, LittleEndian::read_u48(&buf)); + /// ``` + fn write_u48(buf: &mut [u8], n: u64) { + Self::write_uint(buf, n as u64, 6) + } + + /// Writes an unsigned 64 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 8]; + /// LittleEndian::write_u64(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u64(&buf)); + /// ``` + fn write_u64(buf: &mut [u8], n: u64); + + /// Writes an unsigned 128 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + /// + /// # Examples + /// + /// Write and read `u128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 16]; + /// LittleEndian::write_u128(&mut buf, 1_000_000); + /// assert_eq!(1_000_000, LittleEndian::read_u128(&buf)); + /// ``` + fn write_u128(buf: &mut [u8], n: u128); + + /// Writes an unsigned integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then + /// this method panics. + /// + /// # Examples + /// + /// Write and read an n-byte number in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_uint(&mut buf, 1_000_000, 3); + /// assert_eq!(1_000_000, LittleEndian::read_uint(&buf, 3)); + /// ``` + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize); + + /// Writes an unsigned integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 16`, then + /// this method panics. + /// + /// # Examples + /// + /// Write and read an n-byte number in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_uint128(&mut buf, 1_000_000, 3); + /// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3)); + /// ``` + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize); + + /// Reads a signed 16 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + /// + /// # Examples + /// + /// Write and read `i16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 2]; + /// LittleEndian::write_i16(&mut buf, -1_000); + /// assert_eq!(-1_000, LittleEndian::read_i16(&buf)); + /// ``` + #[inline] + fn read_i16(buf: &[u8]) -> i16 { + Self::read_u16(buf) as i16 + } + + /// Reads a signed 24 bit integer from `buf`, stored in i32. + /// + /// # Panics + /// + /// Panics when `buf.len() < 3`. + /// + /// # Examples + /// + /// Write and read 24 bit `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_i24(&mut buf, -1_000_000); + /// assert_eq!(-1_000_000, LittleEndian::read_i24(&buf)); + /// ``` + #[inline] + fn read_i24(buf: &[u8]) -> i32 { + Self::read_int(buf, 3) as i32 + } + + /// Reads a signed 32 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 4]; + /// LittleEndian::write_i32(&mut buf, -1_000_000); + /// assert_eq!(-1_000_000, LittleEndian::read_i32(&buf)); + /// ``` + #[inline] + fn read_i32(buf: &[u8]) -> i32 { + Self::read_u32(buf) as i32 + } + + /// Reads a signed 48 bit integer from `buf`, stored in i64. + /// + /// # Panics + /// + /// Panics when `buf.len() < 6`. + /// + /// # Examples + /// + /// Write and read 48 bit `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 6]; + /// LittleEndian::write_i48(&mut buf, -1_000_000_000_000); + /// assert_eq!(-1_000_000_000_000, LittleEndian::read_i48(&buf)); + /// ``` + #[inline] + fn read_i48(buf: &[u8]) -> i64 { + Self::read_int(buf, 6) as i64 + } + + /// Reads a signed 64 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 8]; + /// LittleEndian::write_i64(&mut buf, -1_000_000_000); + /// assert_eq!(-1_000_000_000, LittleEndian::read_i64(&buf)); + /// ``` + #[inline] + fn read_i64(buf: &[u8]) -> i64 { + Self::read_u64(buf) as i64 + } + + /// Reads a signed 128 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + /// + /// # Examples + /// + /// Write and read `i128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 16]; + /// LittleEndian::write_i128(&mut buf, -1_000_000_000); + /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf)); + /// ``` + #[inline] + fn read_i128(buf: &[u8]) -> i128 { + Self::read_u128(buf) as i128 + } + + /// Reads a signed n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 8` or + /// `buf.len() < nbytes` + /// + /// # Examples + /// + /// Write and read n-length signed numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_int(&mut buf, -1_000, 3); + /// assert_eq!(-1_000, LittleEndian::read_int(&buf, 3)); + /// ``` + #[inline] + fn read_int(buf: &[u8], nbytes: usize) -> i64 { + extend_sign(Self::read_uint(buf, nbytes), nbytes) + } + + /// Reads a signed n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 16` or + /// `buf.len() < nbytes` + /// + /// # Examples + /// + /// Write and read n-length signed numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_int128(&mut buf, -1_000, 3); + /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3)); + /// ``` + #[inline] + fn read_int128(buf: &[u8], nbytes: usize) -> i128 { + extend_sign128(Self::read_uint128(buf, nbytes), nbytes) + } + + /// Reads a IEEE754 single-precision (4 bytes) floating point number. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let e = 2.71828; + /// let mut buf = [0; 4]; + /// LittleEndian::write_f32(&mut buf, e); + /// assert_eq!(e, LittleEndian::read_f32(&buf)); + /// ``` + #[inline] + fn read_f32(buf: &[u8]) -> f32 { + f32::from_bits(Self::read_u32(buf)) + } + + /// Reads a IEEE754 double-precision (8 bytes) floating point number. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let phi = 1.6180339887; + /// let mut buf = [0; 8]; + /// LittleEndian::write_f64(&mut buf, phi); + /// assert_eq!(phi, LittleEndian::read_f64(&buf)); + /// ``` + #[inline] + fn read_f64(buf: &[u8]) -> f64 { + f64::from_bits(Self::read_u64(buf)) + } + + /// Writes a signed 16 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + /// + /// # Examples + /// + /// Write and read `i16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 2]; + /// LittleEndian::write_i16(&mut buf, -1_000); + /// assert_eq!(-1_000, LittleEndian::read_i16(&buf)); + /// ``` + #[inline] + fn write_i16(buf: &mut [u8], n: i16) { + Self::write_u16(buf, n as u16) + } + + /// Writes a signed 24 bit integer `n` to `buf`, stored in i32. + /// + /// # Panics + /// + /// Panics when `buf.len() < 3`. + /// + /// # Examples + /// + /// Write and read 24 bit `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_i24(&mut buf, -1_000_000); + /// assert_eq!(-1_000_000, LittleEndian::read_i24(&buf)); + /// ``` + #[inline] + fn write_i24(buf: &mut [u8], n: i32) { + Self::write_int(buf, n as i64, 3) + } + + /// Writes a signed 32 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 4]; + /// LittleEndian::write_i32(&mut buf, -1_000_000); + /// assert_eq!(-1_000_000, LittleEndian::read_i32(&buf)); + /// ``` + #[inline] + fn write_i32(buf: &mut [u8], n: i32) { + Self::write_u32(buf, n as u32) + } + + /// Writes a signed 48 bit integer `n` to `buf`, stored in i64. + /// + /// # Panics + /// + /// Panics when `buf.len() < 6`. + /// + /// # Examples + /// + /// Write and read 48 bit `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 6]; + /// LittleEndian::write_i48(&mut buf, -1_000_000_000_000); + /// assert_eq!(-1_000_000_000_000, LittleEndian::read_i48(&buf)); + /// ``` + #[inline] + fn write_i48(buf: &mut [u8], n: i64) { + Self::write_int(buf, n as i64, 6) + } + + /// Writes a signed 64 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 8]; + /// LittleEndian::write_i64(&mut buf, -1_000_000_000); + /// assert_eq!(-1_000_000_000, LittleEndian::read_i64(&buf)); + /// ``` + #[inline] + fn write_i64(buf: &mut [u8], n: i64) { + Self::write_u64(buf, n as u64) + } + + /// Writes a signed 128 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + /// + /// # Examples + /// + /// Write and read n-byte `i128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 16]; + /// LittleEndian::write_i128(&mut buf, -1_000_000_000); + /// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf)); + /// ``` + #[inline] + fn write_i128(buf: &mut [u8], n: i128) { + Self::write_u128(buf, n as u128) + } + + /// Writes a signed integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then + /// this method panics. + /// + /// # Examples + /// + /// Write and read an n-byte number in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_int(&mut buf, -1_000, 3); + /// assert_eq!(-1_000, LittleEndian::read_int(&buf, 3)); + /// ``` + #[inline] + fn write_int(buf: &mut [u8], n: i64, nbytes: usize) { + Self::write_uint(buf, unextend_sign(n, nbytes), nbytes) + } + + /// Writes a signed integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 16`, then + /// this method panics. + /// + /// # Examples + /// + /// Write and read n-length signed numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut buf = [0; 3]; + /// LittleEndian::write_int128(&mut buf, -1_000, 3); + /// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3)); + /// ``` + #[inline] + fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) { + Self::write_uint128(buf, unextend_sign128(n, nbytes), nbytes) + } + + /// Writes a IEEE754 single-precision (4 bytes) floating point number. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let e = 2.71828; + /// let mut buf = [0; 4]; + /// LittleEndian::write_f32(&mut buf, e); + /// assert_eq!(e, LittleEndian::read_f32(&buf)); + /// ``` + #[inline] + fn write_f32(buf: &mut [u8], n: f32) { + Self::write_u32(buf, n.to_bits()) + } + + /// Writes a IEEE754 double-precision (8 bytes) floating point number. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let phi = 1.6180339887; + /// let mut buf = [0; 8]; + /// LittleEndian::write_f64(&mut buf, phi); + /// assert_eq!(phi, LittleEndian::read_f64(&buf)); + /// ``` + #[inline] + fn write_f64(buf: &mut [u8], n: f64) { + Self::write_u64(buf, n.to_bits()) + } + + /// Reads unsigned 16 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 2*dst.len()`. + /// + /// # Examples + /// + /// Write and read `u16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 8]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u16_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u16_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_u16_into(src: &[u8], dst: &mut [u16]); + + /// Reads unsigned 32 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_u32_into(src: &[u8], dst: &mut [u32]); + + /// Reads unsigned 64 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_u64_into(src: &[u8], dst: &mut [u64]); + + /// Reads unsigned 128 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 16*dst.len()`. + /// + /// # Examples + /// + /// Write and read `u128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 64]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u128_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u128_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_u128_into(src: &[u8], dst: &mut [u128]); + + /// Reads signed 16 bit integers from `src` to `dst`. + /// + /// # Panics + /// + /// Panics when `buf.len() != 2*dst.len()`. + /// + /// # Examples + /// + /// Write and read `i16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 8]; + /// let numbers_given = [1, 2, 0x0f, 0xee]; + /// LittleEndian::write_i16_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i16_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_i16_into(src: &[u8], dst: &mut [i16]); + + /// Reads signed 32 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_i32_into(src: &[u8], dst: &mut [i32]); + + /// Reads signed 64 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_i64_into(src: &[u8], dst: &mut [i64]); + + /// Reads signed 128 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 16*dst.len()`. + /// + /// # Examples + /// + /// Write and read `i128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 64]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i128_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i128_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_i128_into(src: &[u8], dst: &mut [i128]); + + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; + /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_f32_into(src: &[u8], dst: &mut [f32]); + + /// **DEPRECATED**. + /// + /// This method is deprecated. Use `read_f32_into` instead. + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; + /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + #[inline] + #[deprecated(since = "1.3.0", note = "please use `read_f32_into` instead")] + fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) { + Self::read_f32_into(src, dst); + } + + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; + /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn read_f64_into(src: &[u8], dst: &mut [f64]); + + /// **DEPRECATED**. + /// + /// This method is deprecated. Use `read_f64_into` instead. + /// + /// Reads IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; + /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + #[inline] + #[deprecated(since = "1.3.0", note = "please use `read_f64_into` instead")] + fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) { + Self::read_f64_into(src, dst); + } + + /// Writes unsigned 16 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 2*src.len()`. + /// + /// # Examples + /// + /// Write and read `u16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 8]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u16_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u16_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_u16_into(src: &[u16], dst: &mut [u8]); + + /// Writes unsigned 32 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 4*src.len()`. + /// + /// # Examples + /// + /// Write and read `u32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_u32_into(src: &[u32], dst: &mut [u8]); + + /// Writes unsigned 64 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 8*src.len()`. + /// + /// # Examples + /// + /// Write and read `u64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_u64_into(src: &[u64], dst: &mut [u8]); + + /// Writes unsigned 128 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 16*src.len()`. + /// + /// # Examples + /// + /// Write and read `u128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 64]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_u128_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_u128_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_u128_into(src: &[u128], dst: &mut [u8]); + + /// Writes signed 8 bit integers from `src` into `dst`. + /// + /// Note that since each `i8` is a single byte, no byte order conversions + /// are used. This method is included because it provides a safe, simple + /// way for the caller to write from a `&[i8]` buffer. (Without this + /// method, the caller would have to either use `unsafe` code or convert + /// each byte to `u8` individually.) + /// + /// # Panics + /// + /// Panics when `buf.len() != src.len()`. + /// + /// # Examples + /// + /// Write and read `i8` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian, ReadBytesExt}; + /// + /// let mut bytes = [0; 4]; + /// let numbers_given = [1, 2, 0xf, 0xe]; + /// LittleEndian::write_i8_into(&numbers_given, &mut bytes); + /// ``` + fn write_i8_into(src: &[i8], dst: &mut [u8]) { + assert_eq!(src.len(), dst.len()); + for (d, s) in dst.iter_mut().zip(src.iter()) { + *d = *s as u8; + } + } + + /// Writes signed 16 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `buf.len() != 2*src.len()`. + /// + /// # Examples + /// + /// Write and read `i16` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 8]; + /// let numbers_given = [1, 2, 0x0f, 0xee]; + /// LittleEndian::write_i16_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i16_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_i16_into(src: &[i16], dst: &mut [u8]); + + /// Writes signed 32 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 4*src.len()`. + /// + /// # Examples + /// + /// Write and read `i32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_i32_into(src: &[i32], dst: &mut [u8]); + + /// Writes signed 64 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 8*src.len()`. + /// + /// # Examples + /// + /// Write and read `i64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_i64_into(src: &[i64], dst: &mut [u8]); + + /// Writes signed 128 bit integers from `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `dst.len() != 16*src.len()`. + /// + /// # Examples + /// + /// Write and read `i128` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 64]; + /// let numbers_given = [1, 2, 0xf00f, 0xffee]; + /// LittleEndian::write_i128_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0; 4]; + /// LittleEndian::read_i128_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_i128_into(src: &[i128], dst: &mut [u8]); + + /// Writes IEEE754 single-precision (4 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 4*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f32` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 16]; + /// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19]; + /// LittleEndian::write_f32_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f32_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_f32_into(src: &[f32], dst: &mut [u8]); + + /// Writes IEEE754 double-precision (8 bytes) floating point numbers from + /// `src` into `dst`. + /// + /// # Panics + /// + /// Panics when `src.len() != 8*dst.len()`. + /// + /// # Examples + /// + /// Write and read `f64` numbers in little endian order: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, LittleEndian}; + /// + /// let mut bytes = [0; 32]; + /// let numbers_given = [1.0, 2.0, 31.312e211, -11.32e91]; + /// LittleEndian::write_f64_into(&numbers_given, &mut bytes); + /// + /// let mut numbers_got = [0.0; 4]; + /// LittleEndian::read_f64_into(&bytes, &mut numbers_got); + /// assert_eq!(numbers_given, numbers_got); + /// ``` + fn write_f64_into(src: &[f64], dst: &mut [u8]); + + /// Converts the given slice of unsigned 16 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_u16(&mut numbers); + /// assert_eq!(numbers, [5u16.to_be(), 65000u16.to_be()]); + /// ``` + fn from_slice_u16(numbers: &mut [u16]); + + /// Converts the given slice of unsigned 32 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_u32(&mut numbers); + /// assert_eq!(numbers, [5u32.to_be(), 65000u32.to_be()]); + /// ``` + fn from_slice_u32(numbers: &mut [u32]); + + /// Converts the given slice of unsigned 64 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_u64(&mut numbers); + /// assert_eq!(numbers, [5u64.to_be(), 65000u64.to_be()]); + /// ``` + fn from_slice_u64(numbers: &mut [u64]); + + /// Converts the given slice of unsigned 128 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_u128(&mut numbers); + /// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]); + /// ``` + fn from_slice_u128(numbers: &mut [u128]); + + /// Converts the given slice of signed 16 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 6500]; + /// BigEndian::from_slice_i16(&mut numbers); + /// assert_eq!(numbers, [5i16.to_be(), 6500i16.to_be()]); + /// ``` + fn from_slice_i16(src: &mut [i16]); + + /// Converts the given slice of signed 32 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_i32(&mut numbers); + /// assert_eq!(numbers, [5i32.to_be(), 65000i32.to_be()]); + /// ``` + fn from_slice_i32(src: &mut [i32]); + + /// Converts the given slice of signed 64 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_i64(&mut numbers); + /// assert_eq!(numbers, [5i64.to_be(), 65000i64.to_be()]); + /// ``` + fn from_slice_i64(src: &mut [i64]); + + /// Converts the given slice of signed 128 bit integers to a particular + /// endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + /// + /// # Examples + /// + /// Convert the host platform's endianness to big-endian: + /// + /// ```rust + /// use byteorder_lite::{ByteOrder, BigEndian}; + /// + /// let mut numbers = [5, 65000]; + /// BigEndian::from_slice_i128(&mut numbers); + /// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]); + /// ``` + fn from_slice_i128(src: &mut [i128]); + + /// Converts the given slice of IEEE754 single-precision (4 bytes) floating + /// point numbers to a particular endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + fn from_slice_f32(numbers: &mut [f32]); + + /// Converts the given slice of IEEE754 double-precision (8 bytes) floating + /// point numbers to a particular endianness. + /// + /// If the endianness matches the endianness of the host platform, then + /// this is a no-op. + fn from_slice_f64(numbers: &mut [f64]); +} + +/// Defines big-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +/// +/// # Examples +/// +/// Write and read `u32` numbers in big endian order: +/// +/// ```rust +/// use byteorder_lite::{ByteOrder, BigEndian}; +/// +/// let mut buf = [0; 4]; +/// BigEndian::write_u32(&mut buf, 1_000_000); +/// assert_eq!(1_000_000, BigEndian::read_u32(&buf)); +/// ``` +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum BigEndian {} + +impl Default for BigEndian { + fn default() -> BigEndian { + panic!("BigEndian default") + } +} + +/// A type alias for [`BigEndian`]. +/// +/// [`BigEndian`]: enum.BigEndian.html +pub type BE = BigEndian; + +/// Defines little-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +/// +/// # Examples +/// +/// Write and read `u32` numbers in little endian order: +/// +/// ```rust +/// use byteorder_lite::{ByteOrder, LittleEndian}; +/// +/// let mut buf = [0; 4]; +/// LittleEndian::write_u32(&mut buf, 1_000_000); +/// assert_eq!(1_000_000, LittleEndian::read_u32(&buf)); +/// ``` +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum LittleEndian {} + +impl Default for LittleEndian { + fn default() -> LittleEndian { + panic!("LittleEndian default") + } +} + +/// A type alias for [`LittleEndian`]. +/// +/// [`LittleEndian`]: enum.LittleEndian.html +pub type LE = LittleEndian; + +/// Defines network byte order serialization. +/// +/// Network byte order is defined by [RFC 1700][1] to be big-endian, and is +/// referred to in several protocol specifications. This type is an alias of +/// [`BigEndian`]. +/// +/// [1]: https://tools.ietf.org/html/rfc1700 +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +/// +/// # Examples +/// +/// Write and read `i16` numbers in big endian order: +/// +/// ```rust +/// use byteorder_lite::{ByteOrder, NetworkEndian, BigEndian}; +/// +/// let mut buf = [0; 2]; +/// BigEndian::write_i16(&mut buf, -5_000); +/// assert_eq!(-5_000, NetworkEndian::read_i16(&buf)); +/// ``` +/// +/// [`BigEndian`]: enum.BigEndian.html +pub type NetworkEndian = BigEndian; + +/// Defines system native-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +/// +/// On this platform, this is an alias for [`LittleEndian`]. +/// +/// [`LittleEndian`]: enum.LittleEndian.html +#[cfg(target_endian = "little")] +pub type NativeEndian = LittleEndian; + +/// Defines system native-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +/// +/// On this platform, this is an alias for [`BigEndian`]. +/// +/// [`BigEndian`]: enum.BigEndian.html +#[cfg(target_endian = "big")] +pub type NativeEndian = BigEndian; + +/// Copies a &[u8] $src into a &mut [$ty] $dst for the endianness given by +/// $from_bytes (must be either from_be_bytes or from_le_bytes). +/// +/// Panics if $src.len() != $dst.len() * size_of::<$ty>(). +macro_rules! read_slice { + ($src:expr, $dst:expr, $ty:ty, $from_bytes:ident) => {{ + const SIZE: usize = core::mem::size_of::<$ty>(); + // Check types: + let src: &[u8] = $src; + let dst: &mut [$ty] = $dst; + assert_eq!(src.len(), dst.len() * SIZE); + for (src, dst) in src.chunks_exact(SIZE).zip(dst.iter_mut()) { + *dst = <$ty>::$from_bytes(src.try_into().unwrap()); + } + }}; +} + +/// Copies a &[$ty] $src into a &mut [u8] $dst for the endianness given by +/// $from_bytes (must be either from_be_bytes or from_le_bytes). +/// +/// Panics if $src.len() * size_of::<$ty>() != $dst.len(). +macro_rules! write_slice { + ($src:expr, $dst:expr, $ty:ty, $to_bytes:ident) => {{ + const SIZE: usize = core::mem::size_of::<$ty>(); + // Check types: + let src: &[$ty] = $src; + let dst: &mut [u8] = $dst; + assert_eq!(src.len() * SIZE, dst.len()); + for (src, dst) in src.iter().zip(dst.chunks_exact_mut(SIZE)) { + dst.copy_from_slice(&src.$to_bytes()); + } + }}; +} + +impl ByteOrder for BigEndian { + #[inline] + fn read_u16(buf: &[u8]) -> u16 { + u16::from_be_bytes(buf[..2].try_into().unwrap()) + } + + #[inline] + fn read_u32(buf: &[u8]) -> u32 { + u32::from_be_bytes(buf[..4].try_into().unwrap()) + } + + #[inline] + fn read_u64(buf: &[u8]) -> u64 { + u64::from_be_bytes(buf[..8].try_into().unwrap()) + } + + #[inline] + fn read_u128(buf: &[u8]) -> u128 { + u128::from_be_bytes(buf[..16].try_into().unwrap()) + } + + #[inline] + fn read_uint(buf: &[u8], nbytes: usize) -> u64 { + let mut out = [0; 8]; + assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len()); + let start = out.len() - nbytes; + out[start..].copy_from_slice(&buf[..nbytes]); + u64::from_be_bytes(out) + } + + #[inline] + fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { + let mut out = [0; 16]; + assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len()); + let start = out.len() - nbytes; + out[start..].copy_from_slice(&buf[..nbytes]); + u128::from_be_bytes(out) + } + + #[inline] + fn write_u16(buf: &mut [u8], n: u16) { + buf[..2].copy_from_slice(&n.to_be_bytes()); + } + + #[inline] + fn write_u32(buf: &mut [u8], n: u32) { + buf[..4].copy_from_slice(&n.to_be_bytes()); + } + + #[inline] + fn write_u64(buf: &mut [u8], n: u64) { + buf[..8].copy_from_slice(&n.to_be_bytes()); + } + + #[inline] + fn write_u128(buf: &mut [u8], n: u128) { + buf[..16].copy_from_slice(&n.to_be_bytes()); + } + + #[inline] + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { + assert!(pack_size(n) <= nbytes && nbytes <= 8); + assert!(nbytes <= buf.len()); + + buf[..nbytes].copy_from_slice(&n.to_be_bytes()[(8 - nbytes)..]); + } + + #[inline] + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { + assert!(pack_size128(n) <= nbytes && nbytes <= 16); + assert!(nbytes <= buf.len()); + + buf[..nbytes].copy_from_slice(&n.to_be_bytes()[(16 - nbytes)..]); + } + + #[inline] + fn read_u16_into(src: &[u8], dst: &mut [u16]) { + read_slice!(src, dst, u16, from_be_bytes); + } + + #[inline] + fn read_u32_into(src: &[u8], dst: &mut [u32]) { + read_slice!(src, dst, u32, from_be_bytes); + } + + #[inline] + fn read_u64_into(src: &[u8], dst: &mut [u64]) { + read_slice!(src, dst, u64, from_be_bytes); + } + + #[inline] + fn read_u128_into(src: &[u8], dst: &mut [u128]) { + read_slice!(src, dst, u128, from_be_bytes); + } + + #[inline] + fn read_i16_into(src: &[u8], dst: &mut [i16]) { + read_slice!(src, dst, i16, from_be_bytes); + } + + #[inline] + fn read_i32_into(src: &[u8], dst: &mut [i32]) { + read_slice!(src, dst, i32, from_be_bytes); + } + + #[inline] + fn read_i64_into(src: &[u8], dst: &mut [i64]) { + read_slice!(src, dst, i64, from_be_bytes); + } + + #[inline] + fn read_i128_into(src: &[u8], dst: &mut [i128]) { + read_slice!(src, dst, i128, from_be_bytes); + } + + #[inline] + fn read_f32_into(src: &[u8], dst: &mut [f32]) { + read_slice!(src, dst, f32, from_be_bytes); + } + + #[inline] + fn read_f64_into(src: &[u8], dst: &mut [f64]) { + read_slice!(src, dst, f64, from_be_bytes); + } + + #[inline] + fn write_u16_into(src: &[u16], dst: &mut [u8]) { + write_slice!(src, dst, u16, to_be_bytes); + } + + #[inline] + fn write_u32_into(src: &[u32], dst: &mut [u8]) { + write_slice!(src, dst, u32, to_be_bytes); + } + + #[inline] + fn write_u64_into(src: &[u64], dst: &mut [u8]) { + write_slice!(src, dst, u64, to_be_bytes); + } + + #[inline] + fn write_u128_into(src: &[u128], dst: &mut [u8]) { + write_slice!(src, dst, u128, to_be_bytes); + } + + #[inline] + fn write_i16_into(src: &[i16], dst: &mut [u8]) { + write_slice!(src, dst, i16, to_be_bytes); + } + + #[inline] + fn write_i32_into(src: &[i32], dst: &mut [u8]) { + write_slice!(src, dst, i32, to_be_bytes); + } + + #[inline] + fn write_i64_into(src: &[i64], dst: &mut [u8]) { + write_slice!(src, dst, i64, to_be_bytes); + } + + #[inline] + fn write_i128_into(src: &[i128], dst: &mut [u8]) { + write_slice!(src, dst, i128, to_be_bytes); + } + + #[inline] + fn write_f32_into(src: &[f32], dst: &mut [u8]) { + write_slice!(src, dst, f32, to_be_bytes); + } + + #[inline] + fn write_f64_into(src: &[f64], dst: &mut [u8]) { + write_slice!(src, dst, f64, to_be_bytes); + } + + #[inline] + fn from_slice_u16(numbers: &mut [u16]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_u32(numbers: &mut [u32]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_u64(numbers: &mut [u64]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_u128(numbers: &mut [u128]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_i16(numbers: &mut [i16]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_i32(numbers: &mut [i32]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_i64(numbers: &mut [i64]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_i128(numbers: &mut [i128]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = n.to_be(); + } + } + } + + #[inline] + fn from_slice_f32(numbers: &mut [f32]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = f32::from_bits(n.to_bits().to_be()); + } + } + } + + #[inline] + fn from_slice_f64(numbers: &mut [f64]) { + if cfg!(target_endian = "little") { + for n in numbers { + *n = f64::from_bits(n.to_bits().to_be()); + } + } + } +} + +impl ByteOrder for LittleEndian { + #[inline] + fn read_u16(buf: &[u8]) -> u16 { + u16::from_le_bytes(buf[..2].try_into().unwrap()) + } + + #[inline] + fn read_u32(buf: &[u8]) -> u32 { + u32::from_le_bytes(buf[..4].try_into().unwrap()) + } + + #[inline] + fn read_u64(buf: &[u8]) -> u64 { + u64::from_le_bytes(buf[..8].try_into().unwrap()) + } + + #[inline] + fn read_u128(buf: &[u8]) -> u128 { + u128::from_le_bytes(buf[..16].try_into().unwrap()) + } + + #[inline] + fn read_uint(buf: &[u8], nbytes: usize) -> u64 { + let mut out = [0; 8]; + assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len()); + out[..nbytes].copy_from_slice(&buf[..nbytes]); + u64::from_le_bytes(out) + } + + #[inline] + fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { + let mut out = [0; 16]; + assert!(1 <= nbytes && nbytes <= out.len() && nbytes <= buf.len()); + out[..nbytes].copy_from_slice(&buf[..nbytes]); + u128::from_le_bytes(out) + } + + #[inline] + fn write_u16(buf: &mut [u8], n: u16) { + buf[..2].copy_from_slice(&n.to_le_bytes()); + } + + #[inline] + fn write_u32(buf: &mut [u8], n: u32) { + buf[..4].copy_from_slice(&n.to_le_bytes()); + } + + #[inline] + fn write_u64(buf: &mut [u8], n: u64) { + buf[..8].copy_from_slice(&n.to_le_bytes()); + } + + #[inline] + fn write_u128(buf: &mut [u8], n: u128) { + buf[..16].copy_from_slice(&n.to_le_bytes()); + } + + #[inline] + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { + assert!(pack_size(n) <= nbytes && nbytes <= 8); + assert!(nbytes <= buf.len()); + + buf[..nbytes].copy_from_slice(&n.to_le_bytes()[..nbytes]); + } + + #[inline] + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { + assert!(pack_size128(n) <= nbytes && nbytes <= 16); + assert!(nbytes <= buf.len()); + + buf[..nbytes].copy_from_slice(&n.to_le_bytes()[..nbytes]); + } + + #[inline] + fn read_u16_into(src: &[u8], dst: &mut [u16]) { + read_slice!(src, dst, u16, from_le_bytes); + } + + #[inline] + fn read_u32_into(src: &[u8], dst: &mut [u32]) { + read_slice!(src, dst, u32, from_le_bytes); + } + + #[inline] + fn read_u64_into(src: &[u8], dst: &mut [u64]) { + read_slice!(src, dst, u64, from_le_bytes); + } + + #[inline] + fn read_u128_into(src: &[u8], dst: &mut [u128]) { + read_slice!(src, dst, u128, from_le_bytes); + } + + #[inline] + fn read_i16_into(src: &[u8], dst: &mut [i16]) { + read_slice!(src, dst, i16, from_le_bytes); + } + + #[inline] + fn read_i32_into(src: &[u8], dst: &mut [i32]) { + read_slice!(src, dst, i32, from_le_bytes); + } + + #[inline] + fn read_i64_into(src: &[u8], dst: &mut [i64]) { + read_slice!(src, dst, i64, from_le_bytes); + } + + #[inline] + fn read_i128_into(src: &[u8], dst: &mut [i128]) { + read_slice!(src, dst, i128, from_le_bytes); + } + + #[inline] + fn read_f32_into(src: &[u8], dst: &mut [f32]) { + read_slice!(src, dst, f32, from_le_bytes); + } + + #[inline] + fn read_f64_into(src: &[u8], dst: &mut [f64]) { + read_slice!(src, dst, f64, from_le_bytes); + } + + #[inline] + fn write_u16_into(src: &[u16], dst: &mut [u8]) { + write_slice!(src, dst, u16, to_le_bytes); + } + + #[inline] + fn write_u32_into(src: &[u32], dst: &mut [u8]) { + write_slice!(src, dst, u32, to_le_bytes); + } + + #[inline] + fn write_u64_into(src: &[u64], dst: &mut [u8]) { + write_slice!(src, dst, u64, to_le_bytes); + } + + #[inline] + fn write_u128_into(src: &[u128], dst: &mut [u8]) { + write_slice!(src, dst, u128, to_le_bytes); + } + + #[inline] + fn write_i16_into(src: &[i16], dst: &mut [u8]) { + write_slice!(src, dst, i16, to_le_bytes); + } + + #[inline] + fn write_i32_into(src: &[i32], dst: &mut [u8]) { + write_slice!(src, dst, i32, to_le_bytes); + } + + #[inline] + fn write_i64_into(src: &[i64], dst: &mut [u8]) { + write_slice!(src, dst, i64, to_le_bytes); + } + + #[inline] + fn write_i128_into(src: &[i128], dst: &mut [u8]) { + write_slice!(src, dst, i128, to_le_bytes); + } + + #[inline] + fn write_f32_into(src: &[f32], dst: &mut [u8]) { + write_slice!(src, dst, f32, to_le_bytes); + } + + #[inline] + fn write_f64_into(src: &[f64], dst: &mut [u8]) { + write_slice!(src, dst, f64, to_le_bytes); + } + + #[inline] + fn from_slice_u16(numbers: &mut [u16]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_u32(numbers: &mut [u32]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_u64(numbers: &mut [u64]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_u128(numbers: &mut [u128]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_i16(numbers: &mut [i16]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_i32(numbers: &mut [i32]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_i64(numbers: &mut [i64]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_i128(numbers: &mut [i128]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = n.to_le(); + } + } + } + + #[inline] + fn from_slice_f32(numbers: &mut [f32]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = f32::from_bits(n.to_bits().to_le()); + } + } + } + + #[inline] + fn from_slice_f64(numbers: &mut [f64]) { + if cfg!(target_endian = "big") { + for n in numbers { + *n = f64::from_bits(n.to_bits().to_le()); + } + } + } +} + +#[cfg(test)] +mod test { + use quickcheck::{Arbitrary, Gen, QuickCheck, StdGen, Testable}; + use rand::{thread_rng, Rng}; + + pub const U24_MAX: u32 = 16_777_215; + pub const I24_MAX: i32 = 8_388_607; + pub const U48_MAX: u64 = 281_474_976_710_655; + pub const I48_MAX: i64 = 140_737_488_355_327; + + pub const U64_MAX: u64 = ::core::u64::MAX; + pub const I64_MAX: u64 = ::core::i64::MAX as u64; + + macro_rules! calc_max { + ($max:expr, $bytes:expr) => { + calc_max!($max, $bytes, 8) + }; + ($max:expr, $bytes:expr, $maxbytes:expr) => { + ($max - 1) >> (8 * ($maxbytes - $bytes)) + }; + } + + #[derive(Clone, Debug)] + pub struct Wi128(pub T); + + impl Wi128 { + pub fn clone(&self) -> T { + self.0.clone() + } + } + + impl PartialEq for Wi128 { + fn eq(&self, other: &T) -> bool { + self.0.eq(other) + } + } + + impl Arbitrary for Wi128 { + fn arbitrary(gen: &mut G) -> Wi128 { + let max = calc_max!(::core::u128::MAX, gen.size(), 16); + let output = (gen.gen::() as u128) + | ((gen.gen::() as u128) << 64); + Wi128(output & (max - 1)) + } + } + + impl Arbitrary for Wi128 { + fn arbitrary(gen: &mut G) -> Wi128 { + let max = calc_max!(::core::i128::MAX, gen.size(), 16); + let output = (gen.gen::() as i128) + | ((gen.gen::() as i128) << 64); + Wi128(output & (max - 1)) + } + } + + pub fn qc_sized(f: A, size: u64) { + QuickCheck::new() + .gen(StdGen::new(thread_rng(), size as usize)) + .tests(1_00) + .max_tests(10_000) + .quickcheck(f); + } + + macro_rules! qc_byte_order { + ($name:ident, $ty_int:ty, $max:expr, + $bytes:expr, $read:ident, $write:ident) => { + #[cfg(not(miri))] + mod $name { + #[allow(unused_imports)] + use super::{qc_sized, Wi128}; + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + + #[test] + fn big_endian() { + fn prop(n: $ty_int) -> bool { + let mut buf = [0; 16]; + BigEndian::$write(&mut buf, n.clone(), $bytes); + n == BigEndian::$read(&buf[..$bytes], $bytes) + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + + #[test] + fn little_endian() { + fn prop(n: $ty_int) -> bool { + let mut buf = [0; 16]; + LittleEndian::$write(&mut buf, n.clone(), $bytes); + n == LittleEndian::$read(&buf[..$bytes], $bytes) + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + + #[test] + fn native_endian() { + fn prop(n: $ty_int) -> bool { + let mut buf = [0; 16]; + NativeEndian::$write(&mut buf, n.clone(), $bytes); + n == NativeEndian::$read(&buf[..$bytes], $bytes) + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + } + }; + ($name:ident, $ty_int:ty, $max:expr, + $read:ident, $write:ident) => { + #[cfg(not(miri))] + mod $name { + #[allow(unused_imports)] + use super::{qc_sized, Wi128}; + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + use core::mem::size_of; + + #[test] + fn big_endian() { + fn prop(n: $ty_int) -> bool { + let bytes = size_of::<$ty_int>(); + let mut buf = [0; 16]; + BigEndian::$write(&mut buf[16 - bytes..], n.clone()); + n == BigEndian::$read(&buf[16 - bytes..]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn little_endian() { + fn prop(n: $ty_int) -> bool { + let bytes = size_of::<$ty_int>(); + let mut buf = [0; 16]; + LittleEndian::$write(&mut buf[..bytes], n.clone()); + n == LittleEndian::$read(&buf[..bytes]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn native_endian() { + fn prop(n: $ty_int) -> bool { + let bytes = size_of::<$ty_int>(); + let mut buf = [0; 16]; + NativeEndian::$write(&mut buf[..bytes], n.clone()); + n == NativeEndian::$read(&buf[..bytes]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + } + }; + } + + qc_byte_order!( + prop_u16, + u16, + ::core::u16::MAX as u64, + read_u16, + write_u16 + ); + qc_byte_order!( + prop_i16, + i16, + ::core::i16::MAX as u64, + read_i16, + write_i16 + ); + qc_byte_order!( + prop_u24, + u32, + crate::test::U24_MAX as u64, + read_u24, + write_u24 + ); + qc_byte_order!( + prop_i24, + i32, + crate::test::I24_MAX as u64, + read_i24, + write_i24 + ); + qc_byte_order!( + prop_u32, + u32, + ::core::u32::MAX as u64, + read_u32, + write_u32 + ); + qc_byte_order!( + prop_i32, + i32, + ::core::i32::MAX as u64, + read_i32, + write_i32 + ); + qc_byte_order!( + prop_u48, + u64, + crate::test::U48_MAX as u64, + read_u48, + write_u48 + ); + qc_byte_order!( + prop_i48, + i64, + crate::test::I48_MAX as u64, + read_i48, + write_i48 + ); + qc_byte_order!( + prop_u64, + u64, + ::core::u64::MAX as u64, + read_u64, + write_u64 + ); + qc_byte_order!( + prop_i64, + i64, + ::core::i64::MAX as u64, + read_i64, + write_i64 + ); + qc_byte_order!( + prop_f32, + f32, + ::core::u64::MAX as u64, + read_f32, + write_f32 + ); + qc_byte_order!( + prop_f64, + f64, + ::core::i64::MAX as u64, + read_f64, + write_f64 + ); + + qc_byte_order!(prop_u128, Wi128, 16 + 1, read_u128, write_u128); + qc_byte_order!(prop_i128, Wi128, 16 + 1, read_i128, write_i128); + + qc_byte_order!( + prop_uint_1, + u64, + calc_max!(super::U64_MAX, 1), + 1, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_2, + u64, + calc_max!(super::U64_MAX, 2), + 2, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_3, + u64, + calc_max!(super::U64_MAX, 3), + 3, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_4, + u64, + calc_max!(super::U64_MAX, 4), + 4, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_5, + u64, + calc_max!(super::U64_MAX, 5), + 5, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_6, + u64, + calc_max!(super::U64_MAX, 6), + 6, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_7, + u64, + calc_max!(super::U64_MAX, 7), + 7, + read_uint, + write_uint + ); + qc_byte_order!( + prop_uint_8, + u64, + calc_max!(super::U64_MAX, 8), + 8, + read_uint, + write_uint + ); + + qc_byte_order!( + prop_uint128_1, + Wi128, + 1, + 1, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_2, + Wi128, + 2, + 2, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_3, + Wi128, + 3, + 3, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_4, + Wi128, + 4, + 4, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_5, + Wi128, + 5, + 5, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_6, + Wi128, + 6, + 6, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_7, + Wi128, + 7, + 7, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_8, + Wi128, + 8, + 8, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_9, + Wi128, + 9, + 9, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_10, + Wi128, + 10, + 10, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_11, + Wi128, + 11, + 11, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_12, + Wi128, + 12, + 12, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_13, + Wi128, + 13, + 13, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_14, + Wi128, + 14, + 14, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_15, + Wi128, + 15, + 15, + read_uint128, + write_uint128 + ); + qc_byte_order!( + prop_uint128_16, + Wi128, + 16, + 16, + read_uint128, + write_uint128 + ); + + qc_byte_order!( + prop_int_1, + i64, + calc_max!(super::I64_MAX, 1), + 1, + read_int, + write_int + ); + qc_byte_order!( + prop_int_2, + i64, + calc_max!(super::I64_MAX, 2), + 2, + read_int, + write_int + ); + qc_byte_order!( + prop_int_3, + i64, + calc_max!(super::I64_MAX, 3), + 3, + read_int, + write_int + ); + qc_byte_order!( + prop_int_4, + i64, + calc_max!(super::I64_MAX, 4), + 4, + read_int, + write_int + ); + qc_byte_order!( + prop_int_5, + i64, + calc_max!(super::I64_MAX, 5), + 5, + read_int, + write_int + ); + qc_byte_order!( + prop_int_6, + i64, + calc_max!(super::I64_MAX, 6), + 6, + read_int, + write_int + ); + qc_byte_order!( + prop_int_7, + i64, + calc_max!(super::I64_MAX, 7), + 7, + read_int, + write_int + ); + qc_byte_order!( + prop_int_8, + i64, + calc_max!(super::I64_MAX, 8), + 8, + read_int, + write_int + ); + + qc_byte_order!( + prop_int128_1, + Wi128, + 1, + 1, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_2, + Wi128, + 2, + 2, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_3, + Wi128, + 3, + 3, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_4, + Wi128, + 4, + 4, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_5, + Wi128, + 5, + 5, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_6, + Wi128, + 6, + 6, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_7, + Wi128, + 7, + 7, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_8, + Wi128, + 8, + 8, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_9, + Wi128, + 9, + 9, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_10, + Wi128, + 10, + 10, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_11, + Wi128, + 11, + 11, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_12, + Wi128, + 12, + 12, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_13, + Wi128, + 13, + 13, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_14, + Wi128, + 14, + 14, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_15, + Wi128, + 15, + 15, + read_int128, + write_int128 + ); + qc_byte_order!( + prop_int128_16, + Wi128, + 16, + 16, + read_int128, + write_int128 + ); + + // Test that all of the byte conversion functions panic when given a + // buffer that is too small. + // + // These tests are critical to ensure safety, otherwise we might end up + // with a buffer overflow. + macro_rules! too_small { + ($name:ident, $maximally_small:expr, $zero:expr, + $read:ident, $write:ident) => { + mod $name { + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + + #[test] + #[should_panic] + fn read_big_endian() { + let buf = [0; $maximally_small]; + BigEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn read_little_endian() { + let buf = [0; $maximally_small]; + LittleEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn read_native_endian() { + let buf = [0; $maximally_small]; + NativeEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn write_big_endian() { + let mut buf = [0; $maximally_small]; + BigEndian::$write(&mut buf, $zero); + } + + #[test] + #[should_panic] + fn write_little_endian() { + let mut buf = [0; $maximally_small]; + LittleEndian::$write(&mut buf, $zero); + } + + #[test] + #[should_panic] + fn write_native_endian() { + let mut buf = [0; $maximally_small]; + NativeEndian::$write(&mut buf, $zero); + } + } + }; + ($name:ident, $maximally_small:expr, $read:ident) => { + mod $name { + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + + #[test] + #[should_panic] + fn read_big_endian() { + let buf = [0; $maximally_small]; + BigEndian::$read(&buf, $maximally_small + 1); + } + + #[test] + #[should_panic] + fn read_little_endian() { + let buf = [0; $maximally_small]; + LittleEndian::$read(&buf, $maximally_small + 1); + } + + #[test] + #[should_panic] + fn read_native_endian() { + let buf = [0; $maximally_small]; + NativeEndian::$read(&buf, $maximally_small + 1); + } + } + }; + } + + too_small!(small_u16, 1, 0, read_u16, write_u16); + too_small!(small_i16, 1, 0, read_i16, write_i16); + too_small!(small_u32, 3, 0, read_u32, write_u32); + too_small!(small_i32, 3, 0, read_i32, write_i32); + too_small!(small_u64, 7, 0, read_u64, write_u64); + too_small!(small_i64, 7, 0, read_i64, write_i64); + too_small!(small_f32, 3, 0.0, read_f32, write_f32); + too_small!(small_f64, 7, 0.0, read_f64, write_f64); + too_small!(small_u128, 15, 0, read_u128, write_u128); + too_small!(small_i128, 15, 0, read_i128, write_i128); + + too_small!(small_uint_1, 1, read_uint); + too_small!(small_uint_2, 2, read_uint); + too_small!(small_uint_3, 3, read_uint); + too_small!(small_uint_4, 4, read_uint); + too_small!(small_uint_5, 5, read_uint); + too_small!(small_uint_6, 6, read_uint); + too_small!(small_uint_7, 7, read_uint); + + too_small!(small_uint128_1, 1, read_uint128); + too_small!(small_uint128_2, 2, read_uint128); + too_small!(small_uint128_3, 3, read_uint128); + too_small!(small_uint128_4, 4, read_uint128); + too_small!(small_uint128_5, 5, read_uint128); + too_small!(small_uint128_6, 6, read_uint128); + too_small!(small_uint128_7, 7, read_uint128); + too_small!(small_uint128_8, 8, read_uint128); + too_small!(small_uint128_9, 9, read_uint128); + too_small!(small_uint128_10, 10, read_uint128); + too_small!(small_uint128_11, 11, read_uint128); + too_small!(small_uint128_12, 12, read_uint128); + too_small!(small_uint128_13, 13, read_uint128); + too_small!(small_uint128_14, 14, read_uint128); + too_small!(small_uint128_15, 15, read_uint128); + + too_small!(small_int_1, 1, read_int); + too_small!(small_int_2, 2, read_int); + too_small!(small_int_3, 3, read_int); + too_small!(small_int_4, 4, read_int); + too_small!(small_int_5, 5, read_int); + too_small!(small_int_6, 6, read_int); + too_small!(small_int_7, 7, read_int); + + too_small!(small_int128_1, 1, read_int128); + too_small!(small_int128_2, 2, read_int128); + too_small!(small_int128_3, 3, read_int128); + too_small!(small_int128_4, 4, read_int128); + too_small!(small_int128_5, 5, read_int128); + too_small!(small_int128_6, 6, read_int128); + too_small!(small_int128_7, 7, read_int128); + too_small!(small_int128_8, 8, read_int128); + too_small!(small_int128_9, 9, read_int128); + too_small!(small_int128_10, 10, read_int128); + too_small!(small_int128_11, 11, read_int128); + too_small!(small_int128_12, 12, read_int128); + too_small!(small_int128_13, 13, read_int128); + too_small!(small_int128_14, 14, read_int128); + too_small!(small_int128_15, 15, read_int128); + + // Test that reading/writing slices enforces the correct lengths. + macro_rules! slice_lengths { + ($name:ident, $read:ident, $write:ident, + $num_bytes:expr, $numbers:expr) => { + mod $name { + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + + #[test] + #[should_panic] + fn read_big_endian() { + let bytes = [0; $num_bytes]; + let mut numbers = $numbers; + BigEndian::$read(&bytes, &mut numbers); + } + + #[test] + #[should_panic] + fn read_little_endian() { + let bytes = [0; $num_bytes]; + let mut numbers = $numbers; + LittleEndian::$read(&bytes, &mut numbers); + } + + #[test] + #[should_panic] + fn read_native_endian() { + let bytes = [0; $num_bytes]; + let mut numbers = $numbers; + NativeEndian::$read(&bytes, &mut numbers); + } + + #[test] + #[should_panic] + fn write_big_endian() { + let mut bytes = [0; $num_bytes]; + let numbers = $numbers; + BigEndian::$write(&numbers, &mut bytes); + } + + #[test] + #[should_panic] + fn write_little_endian() { + let mut bytes = [0; $num_bytes]; + let numbers = $numbers; + LittleEndian::$write(&numbers, &mut bytes); + } + + #[test] + #[should_panic] + fn write_native_endian() { + let mut bytes = [0; $num_bytes]; + let numbers = $numbers; + NativeEndian::$write(&numbers, &mut bytes); + } + } + }; + } + + slice_lengths!( + slice_len_too_small_u16, + read_u16_into, + write_u16_into, + 3, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_u16, + read_u16_into, + write_u16_into, + 5, + [0, 0] + ); + slice_lengths!( + slice_len_too_small_i16, + read_i16_into, + write_i16_into, + 3, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_i16, + read_i16_into, + write_i16_into, + 5, + [0, 0] + ); + + slice_lengths!( + slice_len_too_small_u32, + read_u32_into, + write_u32_into, + 7, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_u32, + read_u32_into, + write_u32_into, + 9, + [0, 0] + ); + slice_lengths!( + slice_len_too_small_i32, + read_i32_into, + write_i32_into, + 7, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_i32, + read_i32_into, + write_i32_into, + 9, + [0, 0] + ); + + slice_lengths!( + slice_len_too_small_u64, + read_u64_into, + write_u64_into, + 15, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_u64, + read_u64_into, + write_u64_into, + 17, + [0, 0] + ); + slice_lengths!( + slice_len_too_small_i64, + read_i64_into, + write_i64_into, + 15, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_i64, + read_i64_into, + write_i64_into, + 17, + [0, 0] + ); + + slice_lengths!( + slice_len_too_small_u128, + read_u128_into, + write_u128_into, + 31, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_u128, + read_u128_into, + write_u128_into, + 33, + [0, 0] + ); + slice_lengths!( + slice_len_too_small_i128, + read_i128_into, + write_i128_into, + 31, + [0, 0] + ); + slice_lengths!( + slice_len_too_big_i128, + read_i128_into, + write_i128_into, + 33, + [0, 0] + ); + + #[test] + fn uint_bigger_buffer() { + use crate::{ByteOrder, LittleEndian}; + let n = LittleEndian::read_uint(&[1, 2, 3, 4, 5, 6, 7, 8], 5); + assert_eq!(n, 0x05_0403_0201); + } + + #[test] + fn regression173_array_impl() { + use crate::{BigEndian, ByteOrder, LittleEndian}; + + let xs = [0; 100]; + + let x = BigEndian::read_u16(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_u32(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_u64(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_u128(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_i16(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_i32(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_i64(&xs); + assert_eq!(x, 0); + let x = BigEndian::read_i128(&xs); + assert_eq!(x, 0); + + let x = LittleEndian::read_u16(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_u32(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_u64(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_u128(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_i16(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_i32(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_i64(&xs); + assert_eq!(x, 0); + let x = LittleEndian::read_i128(&xs); + assert_eq!(x, 0); + } +} + +#[cfg(test)] +#[cfg(feature = "std")] +mod stdtests { + extern crate quickcheck; + extern crate rand; + + use self::quickcheck::{QuickCheck, StdGen, Testable}; + use self::rand::thread_rng; + + fn qc_unsized(f: A) { + QuickCheck::new() + .gen(StdGen::new(thread_rng(), 16)) + .tests(1_00) + .max_tests(10_000) + .quickcheck(f); + } + + macro_rules! calc_max { + ($max:expr, $bytes:expr) => { + ($max - 1) >> (8 * (8 - $bytes)) + }; + } + + macro_rules! qc_bytes_ext { + ($name:ident, $ty_int:ty, $max:expr, + $bytes:expr, $read:ident, $write:ident) => { + #[cfg(not(miri))] + mod $name { + #[allow(unused_imports)] + use crate::test::{qc_sized, Wi128}; + use crate::{ + BigEndian, LittleEndian, NativeEndian, ReadBytesExt, + WriteBytesExt, + }; + use std::io::Cursor; + + #[test] + fn big_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let offset = wtr.len() - $bytes; + let mut rdr = Cursor::new(&mut wtr[offset..]); + n == rdr.$read::($bytes).unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + + #[test] + fn little_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::($bytes).unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + + #[test] + fn native_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let offset = if cfg!(target_endian = "big") { + wtr.len() - $bytes + } else { + 0 + }; + let mut rdr = Cursor::new(&mut wtr[offset..]); + n == rdr.$read::($bytes).unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max); + } + } + }; + ($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => { + #[cfg(not(miri))] + mod $name { + #[allow(unused_imports)] + use crate::test::{qc_sized, Wi128}; + use crate::{ + BigEndian, LittleEndian, NativeEndian, ReadBytesExt, + WriteBytesExt, + }; + use std::io::Cursor; + + #[test] + fn big_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn little_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn native_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::(n.clone()).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + } + }; + } + + qc_bytes_ext!( + prop_ext_u16, + u16, + ::std::u16::MAX as u64, + read_u16, + write_u16 + ); + qc_bytes_ext!( + prop_ext_i16, + i16, + ::std::i16::MAX as u64, + read_i16, + write_i16 + ); + qc_bytes_ext!( + prop_ext_u32, + u32, + ::std::u32::MAX as u64, + read_u32, + write_u32 + ); + qc_bytes_ext!( + prop_ext_i32, + i32, + ::std::i32::MAX as u64, + read_i32, + write_i32 + ); + qc_bytes_ext!( + prop_ext_u64, + u64, + ::std::u64::MAX as u64, + read_u64, + write_u64 + ); + qc_bytes_ext!( + prop_ext_i64, + i64, + ::std::i64::MAX as u64, + read_i64, + write_i64 + ); + qc_bytes_ext!( + prop_ext_f32, + f32, + ::std::u64::MAX as u64, + read_f32, + write_f32 + ); + qc_bytes_ext!( + prop_ext_f64, + f64, + ::std::i64::MAX as u64, + read_f64, + write_f64 + ); + + qc_bytes_ext!(prop_ext_u128, Wi128, 16 + 1, read_u128, write_u128); + qc_bytes_ext!(prop_ext_i128, Wi128, 16 + 1, read_i128, write_i128); + + qc_bytes_ext!( + prop_ext_uint_1, + u64, + calc_max!(crate::test::U64_MAX, 1), + 1, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_2, + u64, + calc_max!(crate::test::U64_MAX, 2), + 2, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_3, + u64, + calc_max!(crate::test::U64_MAX, 3), + 3, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_4, + u64, + calc_max!(crate::test::U64_MAX, 4), + 4, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_5, + u64, + calc_max!(crate::test::U64_MAX, 5), + 5, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_6, + u64, + calc_max!(crate::test::U64_MAX, 6), + 6, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_7, + u64, + calc_max!(crate::test::U64_MAX, 7), + 7, + read_uint, + write_u64 + ); + qc_bytes_ext!( + prop_ext_uint_8, + u64, + calc_max!(crate::test::U64_MAX, 8), + 8, + read_uint, + write_u64 + ); + + qc_bytes_ext!( + prop_ext_uint128_1, + Wi128, + 1, + 1, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_2, + Wi128, + 2, + 2, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_3, + Wi128, + 3, + 3, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_4, + Wi128, + 4, + 4, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_5, + Wi128, + 5, + 5, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_6, + Wi128, + 6, + 6, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_7, + Wi128, + 7, + 7, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_8, + Wi128, + 8, + 8, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_9, + Wi128, + 9, + 9, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_10, + Wi128, + 10, + 10, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_11, + Wi128, + 11, + 11, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_12, + Wi128, + 12, + 12, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_13, + Wi128, + 13, + 13, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_14, + Wi128, + 14, + 14, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_15, + Wi128, + 15, + 15, + read_uint128, + write_u128 + ); + qc_bytes_ext!( + prop_ext_uint128_16, + Wi128, + 16, + 16, + read_uint128, + write_u128 + ); + + qc_bytes_ext!( + prop_ext_int_1, + i64, + calc_max!(crate::test::I64_MAX, 1), + 1, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_2, + i64, + calc_max!(crate::test::I64_MAX, 2), + 2, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_3, + i64, + calc_max!(crate::test::I64_MAX, 3), + 3, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_4, + i64, + calc_max!(crate::test::I64_MAX, 4), + 4, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_5, + i64, + calc_max!(crate::test::I64_MAX, 5), + 5, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_6, + i64, + calc_max!(crate::test::I64_MAX, 6), + 6, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_7, + i64, + calc_max!(crate::test::I64_MAX, 1), + 7, + read_int, + write_i64 + ); + qc_bytes_ext!( + prop_ext_int_8, + i64, + calc_max!(crate::test::I64_MAX, 8), + 8, + read_int, + write_i64 + ); + + qc_bytes_ext!( + prop_ext_int128_1, + Wi128, + 1, + 1, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_2, + Wi128, + 2, + 2, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_3, + Wi128, + 3, + 3, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_4, + Wi128, + 4, + 4, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_5, + Wi128, + 5, + 5, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_6, + Wi128, + 6, + 6, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_7, + Wi128, + 7, + 7, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_8, + Wi128, + 8, + 8, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_9, + Wi128, + 9, + 9, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_10, + Wi128, + 10, + 10, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_11, + Wi128, + 11, + 11, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_12, + Wi128, + 12, + 12, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_13, + Wi128, + 13, + 13, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_14, + Wi128, + 14, + 14, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_15, + Wi128, + 15, + 15, + read_int128, + write_i128 + ); + qc_bytes_ext!( + prop_ext_int128_16, + Wi128, + 16, + 16, + read_int128, + write_i128 + ); + + // Test slice serialization/deserialization. + macro_rules! qc_slice { + ($name:ident, $ty_int:ty, $read:ident, $write:ident, $zero:expr) => { + #[cfg(not(miri))] + mod $name { + use super::qc_unsized; + #[allow(unused_imports)] + use crate::test::Wi128; + use crate::{ + BigEndian, ByteOrder, LittleEndian, NativeEndian, + }; + use core::mem::size_of; + + #[test] + fn big_endian() { + fn prop(numbers: Vec<$ty_int>) -> bool { + let numbers: Vec<_> = + numbers.into_iter().map(|x| x.clone()).collect(); + let num_bytes = size_of::<$ty_int>() * numbers.len(); + let mut bytes = vec![0; num_bytes]; + + BigEndian::$write(&numbers, &mut bytes); + + let mut got = vec![$zero; numbers.len()]; + BigEndian::$read(&bytes, &mut got); + + numbers == got + } + qc_unsized(prop as fn(_) -> bool); + } + + #[test] + fn little_endian() { + fn prop(numbers: Vec<$ty_int>) -> bool { + let numbers: Vec<_> = + numbers.into_iter().map(|x| x.clone()).collect(); + let num_bytes = size_of::<$ty_int>() * numbers.len(); + let mut bytes = vec![0; num_bytes]; + + LittleEndian::$write(&numbers, &mut bytes); + + let mut got = vec![$zero; numbers.len()]; + LittleEndian::$read(&bytes, &mut got); + + numbers == got + } + qc_unsized(prop as fn(_) -> bool); + } + + #[test] + fn native_endian() { + fn prop(numbers: Vec<$ty_int>) -> bool { + let numbers: Vec<_> = + numbers.into_iter().map(|x| x.clone()).collect(); + let num_bytes = size_of::<$ty_int>() * numbers.len(); + let mut bytes = vec![0; num_bytes]; + + NativeEndian::$write(&numbers, &mut bytes); + + let mut got = vec![$zero; numbers.len()]; + NativeEndian::$read(&bytes, &mut got); + + numbers == got + } + qc_unsized(prop as fn(_) -> bool); + } + } + }; + } + + qc_slice!(prop_slice_u16, u16, read_u16_into, write_u16_into, 0); + qc_slice!(prop_slice_i16, i16, read_i16_into, write_i16_into, 0); + qc_slice!(prop_slice_u32, u32, read_u32_into, write_u32_into, 0); + qc_slice!(prop_slice_i32, i32, read_i32_into, write_i32_into, 0); + qc_slice!(prop_slice_u64, u64, read_u64_into, write_u64_into, 0); + qc_slice!(prop_slice_i64, i64, read_i64_into, write_i64_into, 0); + qc_slice!( + prop_slice_u128, + Wi128, + read_u128_into, + write_u128_into, + 0 + ); + qc_slice!( + prop_slice_i128, + Wi128, + read_i128_into, + write_i128_into, + 0 + ); + + qc_slice!(prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0); + qc_slice!(prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"a0692ff3c8c5693b4fdf96a44e3cb157fa1ffb7c07fe4d4123f6ff395540645c","Cargo.toml":"0064c85dbced0ad6704403b042ba5c437c82222852c6c78b063199092b49998b","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"c1b2b54999d4829f9f64fb41cbdf05a72d565be0dd078a8633d34631147498a1","SECURITY.md":"a3335079977c2f13bad59e323fdc1056bdae5adfe55f18d15ac2c930d741828c","benches/buf.rs":"72e6b6120b52d568da068f17c66a793d65602e400c595778581b63092e41d8dc","benches/bytes.rs":"7084e564f8568f52c9fdb76a06e58701aa7f0c776209d29a0f60c38a19748203","benches/bytes_mut.rs":"1326fe6224b26826228e02b4133151e756f38152c2d9cfe66adf83af76c3ec98","ci/miri.sh":"13b2db3432fcdf9e2db6ef9e6ec20d063c0ce63542981a6f77e09306e1e2198e","ci/test-stable.sh":"b21b9265d8d65c1f3d50c64e40d41c66a870d897325119d1f78d601727bbb562","ci/tsan.sh":"466b86b19225dd26c756cf2252cb1973f87a145642c99364b462ed7ceb55c7dd","clippy.toml":"8522f448dfa3b33ac334ce47d233ebb6b58e8ae115e45107a64fc1b4510fe560","src/buf/buf_impl.rs":"5ef03026b2eac1a6ce8d85df7b135f6f69c11fdb73c76ac449e8e7734c5aef07","src/buf/buf_mut.rs":"20bfb57681d1f0cb7c7610e12b9a06233235ba6f20100f7eb2f23a5f4cf0de90","src/buf/chain.rs":"c933958f04c4ecd39a18db34c04ea51cc601180d43ee6924fed2fb44b96fe8c7","src/buf/iter.rs":"d4dca5b7f9b1cb441f22ac1862e28b10086721879163a810955aefb5cd7f3e58","src/buf/limit.rs":"e005ba140b70f68654877c96b981a220477e415ff5c92438c1b0cb9bc866d872","src/buf/mod.rs":"3f60295316d44b510b942abb31a0d975ae488bd4b52c87f5252d73f88f82715a","src/buf/reader.rs":"cda8bc221a1de06c7395d5c6e80f8a5924198eafbc2decc0909082ce8781d789","src/buf/take.rs":"ce7f4644986797dae3e6bdaa8f65c8ff0a9b0d4b80f749c735ed4777b96dcb2c","src/buf/uninit_slice.rs":"52629b93ff7a08db45fc69395580b34fa3609fd9309ea01f86e58488b02b08a3","src/buf/vec_deque.rs":"8d552c26ac6ce28a471f74c388e4749432e86b1d8f5a9759b9fc32a2549d395f","src/buf/writer.rs":"b137608cb40944a5c3e061a73087c5a48e50048dae002d0334a23cf4d3547065","src/bytes.rs":"140ea293c520a0a6c80f7f3aa7ce9a6d33782f6be19a416929450b3fbfcba107","src/bytes_mut.rs":"76e6a2e68ffa433b694671f673aa16dc2d4a414e73d1037fd8f3d801251901ce","src/fmt/debug.rs":"4d217b8f43e489925bb6904010df617efc63b50a3cc1ab126eec54b43b66eb3e","src/fmt/hex.rs":"54c05ab7d95d7381e499079d63773fabd2672f3c4929b56b02ab87d4495902b5","src/fmt/mod.rs":"b38222dcfff70eb3ffb6ce305b95f3fcfd9fa68cca85693eb2ed01d3da7ddb88","src/lib.rs":"226bb979808d8dcc8ff1643029b74a672b1779d6b7153a9e180777b77906191f","src/loom.rs":"eb3f577d8cce39a84155c241c4dc308f024631f02085833f7fe9f0ea817bcea9","src/serde.rs":"3ecd7e828cd4c2b7db93c807cb1548fad209e674df493edf7cda69a7b04d405d","tests/test_buf.rs":"827a965d3635eed132317248172add380679a3aaa0a26752bb77ea6ff8a458d5","tests/test_buf_mut.rs":"3e6a12a4f546dbf1a0e1346ab2b7ff707fdaf01a06b21714ca64b141484a76c3","tests/test_bytes.rs":"778b718447d04401033e8319b30a34ed9b5a264d79677afe3b301d6bebf1b419","tests/test_bytes_odd_alloc.rs":"ad5df84a35038359413199762c65017989d905e6e965a7b863beaa9962a7e1e8","tests/test_bytes_vec_alloc.rs":"dd7e3c3a71abcfdcad7e3b2f52a6bd106ad6ea0d4bc634372e81dae097233cf0","tests/test_chain.rs":"e9f094539bb42b3135f50033c44122a6b44cf0f953e51e8b488f43243f1e7f10","tests/test_debug.rs":"13299107172809e8cbbd823964ac9450cd0d6b6de79f2e6a2e0f44b9225a0593","tests/test_iter.rs":"665e1837c1294d7695ffa352a666ce8673fb46fa603164556524e87d5517a6cb","tests/test_reader.rs":"bf83669d4e0960dad6aa47b46a9a454814fab626eb83572aba914c3d71618f43","tests/test_serde.rs":"2691f891796ba259de0ecf926de05c514f4912cc5fcd3e6a1591efbcd23ed4d0","tests/test_take.rs":"db01bf6855097f318336e90d12c0725a92cee426d330e477a6bd1d32dac34a27"},"package":"325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ad8751616b31c5b1fe757ac9d68493b513d526a9c914583440dca32ee1a27e25",".github/workflows/ci.yml":"1e635153dbcbee2afb3fd51a83340439f07f223b179e7cde28a68a8ee7385008","CHANGELOG.md":"98b59d530d4ee459b9183c8601aad783bdc5f5ce01c68f2df7f29438f47fe871","Cargo.lock":"3db4c23f448167dc361d799583456431062a6e3fbedf2ceb075adfa263da9c6c","Cargo.toml":"ebdcb7f4b82227b25a075ca774a6021037502d6305d77fee8e01b157c84ffdaa","Cargo.toml.orig":"3a4815f3f9939b85f08ea5785f083f5153234de58e4125c64be33fe91459075f","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"275ac7bc295e3cc659d28f05261645ac5bd6286476afe2ee3c1ed719f7b6df02","SECURITY.md":"a3335079977c2f13bad59e323fdc1056bdae5adfe55f18d15ac2c930d741828c","benches/buf.rs":"72e6b6120b52d568da068f17c66a793d65602e400c595778581b63092e41d8dc","benches/bytes.rs":"7084e564f8568f52c9fdb76a06e58701aa7f0c776209d29a0f60c38a19748203","benches/bytes_mut.rs":"1326fe6224b26826228e02b4133151e756f38152c2d9cfe66adf83af76c3ec98","ci/miri.sh":"e74475e7aec647a490a1f491b5dac6a60e3c03926a7c7e1898fa3e7c626415c7","ci/panic-abort.sh":"aec2e5427117e533d7a9721a926eb6a9d72f264510066baf2c501357df2d936f","ci/test-stable.sh":"fb751f06f314f728c489b7a7854701f632e24de8d0540ea8cf3449c6a853ac3c","ci/tsan.sh":"466b86b19225dd26c756cf2252cb1973f87a145642c99364b462ed7ceb55c7dd","clippy.toml":"583b79f56f20c85fb7820fcfa97985e03a4b41da31c8bbe6c03b721d3df5e800","src/buf/buf_impl.rs":"a14aa7e5e7fac1d4d1a3617d616af0b478a9a31235b773bcec11255c8c78446e","src/buf/buf_mut.rs":"c76d0a846cf6e2c42af7acf0bbedc49a30ce3b9185392835c6a6f8b06a128b9e","src/buf/chain.rs":"27ff0a6fce049c51a24d45003b9741b655c28330b48af23ad1514587760b0c93","src/buf/iter.rs":"d4dca5b7f9b1cb441f22ac1862e28b10086721879163a810955aefb5cd7f3e58","src/buf/limit.rs":"e005ba140b70f68654877c96b981a220477e415ff5c92438c1b0cb9bc866d872","src/buf/mod.rs":"3f60295316d44b510b942abb31a0d975ae488bd4b52c87f5252d73f88f82715a","src/buf/reader.rs":"cda8bc221a1de06c7395d5c6e80f8a5924198eafbc2decc0909082ce8781d789","src/buf/take.rs":"443766677fae38b398271693ed6134c7cc14949cdb9fce299c44dd55ecf84fb3","src/buf/uninit_slice.rs":"52629b93ff7a08db45fc69395580b34fa3609fd9309ea01f86e58488b02b08a3","src/buf/vec_deque.rs":"baac165527d1bdfc3bb259380bb4722e70c3f11e8a901e8bab6e4f951b060711","src/buf/writer.rs":"b137608cb40944a5c3e061a73087c5a48e50048dae002d0334a23cf4d3547065","src/bytes.rs":"54568a31252a7cc4f1dcee26d2d34dc6e0af9c9d8bf09522b694c3bd6a2a04bc","src/bytes_mut.rs":"aa9ce99a8c58100341f3fd33ee33c821fa89ebc3b7e98190ebe66f7632b4f6c2","src/fmt/debug.rs":"4d217b8f43e489925bb6904010df617efc63b50a3cc1ab126eec54b43b66eb3e","src/fmt/hex.rs":"54c05ab7d95d7381e499079d63773fabd2672f3c4929b56b02ab87d4495902b5","src/fmt/mod.rs":"b38222dcfff70eb3ffb6ce305b95f3fcfd9fa68cca85693eb2ed01d3da7ddb88","src/lib.rs":"037b377f32c52ea6cf5ebd0135ff80a6f8c4b25e663aa5a9786c6310c2f91e46","src/loom.rs":"7c89f9f5f900d5b9b7c43d08d467957933eba90d5dcff1b38cf9a7e48494a577","src/serde.rs":"3ecd7e828cd4c2b7db93c807cb1548fad209e674df493edf7cda69a7b04d405d","tests/test_buf.rs":"c55dc7ab1a7392c2467a079dc77223fbec35ff54e9eda9b05cc1d4e22cb36626","tests/test_buf_mut.rs":"1f28f3d125e98b81a813a414a89a8c9b5d45369b10dda187a68614ff285c820e","tests/test_bytes.rs":"57f461b6a05cfe58dff0c5d5eb46277557274eb4bedfecb9aa5d295963e0c9f4","tests/test_bytes_odd_alloc.rs":"ad5df84a35038359413199762c65017989d905e6e965a7b863beaa9962a7e1e8","tests/test_bytes_vec_alloc.rs":"5a0e77cab12b32374b2822df8d9a6479afe68b55c1cba1511ebf4199be532caa","tests/test_chain.rs":"1784287560d45e0225b2cd9d24498264031c36f42cebb7e92108e11641d1cce0","tests/test_debug.rs":"13299107172809e8cbbd823964ac9450cd0d6b6de79f2e6a2e0f44b9225a0593","tests/test_iter.rs":"665e1837c1294d7695ffa352a666ce8673fb46fa603164556524e87d5517a6cb","tests/test_limit.rs":"6c5801f1e94f0abb2b4994aa1ade8e36464f26bf9e13e3dcac02d0f2f6f08ed5","tests/test_reader.rs":"050b872d89376b3b83841839b4334066d8357b01aaf3783a180aac25a5550f3d","tests/test_serde.rs":"2691f891796ba259de0ecf926de05c514f4912cc5fcd3e6a1591efbcd23ed4d0","tests/test_take.rs":"fb34700a8ed75b3c6937a4dee0bffadb64f7c7f735bd9faa8730eb96a9e9b651"},"package":"1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "417dccdeff249e0c011327de7d92e0d6fbe7cc43" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/bytes/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,211 @@ +name: CI + +on: + pull_request: + branches: + - master + push: + branches: + - master + schedule: + - cron: '0 2 * * 0' + +env: + RUSTFLAGS: -Dwarnings + RUST_BACKTRACE: 1 + nightly: nightly-2024-09-15 + +defaults: + run: + shell: bash + +jobs: + # Check formatting + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update stable + - name: Check formatting + run: cargo fmt --all --check + + # TODO + # # Apply clippy lints + # clippy: + # name: clippy + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - name: Apply clippy lints + # run: cargo clippy --all-features + + # This represents the minimum Rust version supported by + # Bytes. Updating this should be done in a dedicated PR. + # + # Tests are not run as tests may require newer versions of + # rust. + minrust: + name: minrust + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install cargo-hack + uses: taiki-e/install-action@cargo-hack + - name: Check + run: cargo hack check --feature-powerset --optional-deps --rust-version + + # Stable + stable: + name: stable + strategy: + matrix: + os: + - ubuntu-latest + - ubuntu-22.04-arm # TODO: update to 24.04 when https://github.com/rust-lang/rust/issues/135867 solved + - macos-latest + - windows-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Install Rust + # --no-self-update is necessary because the windows environment cannot self-update rustup.exe. + run: rustup update stable --no-self-update + - name: Install cargo-hack + uses: taiki-e/install-action@cargo-hack + - name: Test + run: ci/test-stable.sh test + + # Nightly + nightly: + name: nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Install cargo-hack + uses: taiki-e/install-action@cargo-hack + - name: Test + run: ci/test-stable.sh test + + panic-abort: + name: panic=abort tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Run tests with -Cpanic=abort + run: ci/panic-abort.sh + + # Run tests on some extra platforms + cross: + name: cross + strategy: + matrix: + include: + - target: i686-unknown-linux-gnu + os: ubuntu-latest + - target: armv7-unknown-linux-gnueabihf + os: ubuntu-22.04-arm # TODO: update to 24.04 when https://github.com/rust-lang/rust/issues/135867 solved + - target: powerpc-unknown-linux-gnu + os: ubuntu-latest + - target: powerpc64-unknown-linux-gnu + os: ubuntu-latest + - target: wasm32-wasip1 + os: ubuntu-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update stable + - uses: taiki-e/setup-cross-toolchain-action@v1 + with: + target: ${{ matrix.target }} + - name: Test + run: cargo test --target ${{ matrix.target }} + + # Build for no_std environment. + no-std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update stable + - name: Install cargo-hack + uses: taiki-e/install-action@cargo-hack + # thumbv6m-none-eabi supports atomic, but not atomic CAS. + # thumbv7m-none-eabi supports atomic CAS. + - run: rustup target add thumbv6m-none-eabi thumbv7m-none-eabi + # * --optional-deps is needed for serde feature + # * --no-dev-deps is needed to avoid https://github.com/rust-lang/cargo/issues/4866 + - run: cargo hack build --target thumbv7m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps + # A sound way to provide atomic CAS on platforms without native atomic CAS is system-dependent. + # portable-atomic provides major ways via cfgs and accepts user-defined implementations via critical-section feature. + - run: cargo hack build --target thumbv6m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps --features extra-platforms,extra-platforms/critical-section + + # Sanitizers + tsan: + name: tsan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Install rust-src + run: rustup component add rust-src + - name: ASAN / TSAN + run: ci/tsan.sh + + miri: + name: miri + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Miri + run: ci/miri.sh + + # Loom + loom: + name: loom + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Loom tests + run: RUSTFLAGS="--cfg loom -Dwarnings" cargo test --lib + + publish_docs: + name: Publish Documentation + needs: + - rustfmt + # - clippy + - stable + - nightly + - minrust + - cross + - tsan + - miri + - loom + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Build documentation + run: cargo doc --no-deps --all-features + env: + RUSTDOCFLAGS: --cfg docsrs + - name: Publish documentation + run: | + cd target/doc + git init + git add . + git -c user.name='ci' -c user.email='ci' commit -m 'Deploy Bytes API documentation' + git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages + if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' && github.repository == 'tokio-rs/bytes' diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/bytes/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,46 @@ +# 1.11.1 (February 3rd, 2026) + +- Fix integer overflow in `BytesMut::reserve` + +# 1.11.0 (November 14th, 2025) + +- Bump MSRV to 1.57 (#788) + +### Fixed + +- fix: `BytesMut` only reuse if src has remaining (#803) +- Specialize `BytesMut::put::` (#793) +- Reserve capacity in `BytesMut::put` (#794) +- Change `BytesMut::remaining_mut` to use `isize::MAX` instead of `usize::MAX` (#795) + +### Internal changes + +- Guarantee address in `slice()` for empty slices. (#780) +- Rename `Vtable::to_*` -> `Vtable::into_*` (#776) +- Fix latest clippy warnings (#787) +- Ignore `BytesMut::freeze` doctest on wasm (#790) +- Move `drop_fn` of `from_owner` into vtable (#801) + +# 1.10.1 (March 5th, 2025) + +### Fixed + +- Fix memory leak when using `to_vec` with `Bytes::from_owner` (#773) + +# 1.10.0 (February 3rd, 2025) + +### Added + +- Add feature to support platforms without atomic CAS (#467) +- `try_get_*` methods for `Buf` trait (#753) +- Implement `Buf::chunks_vectored` for `Take` (#617) +- Implement `Buf::chunks_vectored` for `VecDeque` (#708) + +### Fixed + +- Remove incorrect guarantee for `chunks_vectored` (#754) +- Ensure that tests pass under `panic=abort` (#749) + # 1.9.0 (November 27, 2024) ### Added diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,444 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "bytes" +version = "1.11.1" +dependencies = [ + "loom", + "portable-atomic", + "serde", + "serde_test", +] + +[[package]] +name = "cc" +version = "1.2.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_test" +version = "1.0.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +dependencies = [ + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -10,15 +10,16 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" -rust-version = "1.39" +edition = "2021" +rust-version = "1.57" name = "bytes" -version = "1.9.0" +version = "1.11.1" authors = [ "Carl Lerche ", "Sean McArthur ", ] build = false +autolib = false autobins = false autoexamples = false autotests = false @@ -43,6 +44,10 @@ "docsrs", ] +[features] +default = ["std"] +std = [] + [lib] name = "bytes" path = "src/lib.rs" @@ -80,6 +85,10 @@ path = "tests/test_iter.rs" [[test]] +name = "test_limit" +path = "tests/test_limit.rs" + +[[test]] name = "test_reader" path = "tests/test_reader.rs" @@ -103,6 +112,13 @@ name = "bytes_mut" path = "benches/bytes_mut.rs" +[dependencies.extra-platforms] +version = "1.3" +features = ["require-cas"] +optional = true +default-features = false +package = "portable-atomic" + [dependencies.serde] version = "1.0.60" features = ["alloc"] @@ -112,9 +128,10 @@ [dev-dependencies.serde_test] version = "1.0" -[features] -default = ["std"] -std = [] - [target."cfg(loom)".dev-dependencies.loom] version = "0.7" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(loom)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +[package] + +name = "bytes" +# When releasing to crates.io: +# - Update CHANGELOG.md. +# - Create "v1.x.y" git tag. +version = "1.11.1" +edition = "2021" +rust-version = "1.57" +license = "MIT" +authors = [ + "Carl Lerche ", + "Sean McArthur ", +] +description = "Types and traits for working with bytes" +repository = "https://github.com/tokio-rs/bytes" +readme = "README.md" +keywords = ["buffers", "zero-copy", "io"] +categories = ["network-programming", "data-structures"] + +[features] +default = ["std"] +std = [] + +[dependencies] +serde = { version = "1.0.60", optional = true, default-features = false, features = ["alloc"] } +# Use portable-atomic crate to support platforms without atomic CAS. +# See "no_std support" section in readme for more information. +# +# Enable require-cas feature to provide a better error message if the end user forgets to use the cfg or feature. +extra-platforms = { package = "portable-atomic", version = "1.3", optional = true, default-features = false, features = ["require-cas"] } + +[dev-dependencies] +serde_test = "1.0" + +[target.'cfg(loom)'.dev-dependencies] +loom = "0.7" + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(loom)', +] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/README.md clamav-1.4.6+dfsg/.cargo/vendor/bytes/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -27,6 +27,21 @@ use bytes::{Bytes, BytesMut, Buf, BufMut}; ``` +## no_std support + +To use `bytes` with no_std environment, disable the (enabled by default) `std` feature. + +```toml +[dependencies] +bytes = { version = "1", default-features = false } +``` + +To use `bytes` with no_std environment without atomic CAS, such as thumbv6m, you also need to enable +the `extra-platforms` feature. See the [documentation for the `portable-atomic` +crate](https://docs.rs/portable-atomic) for more information. + +The MSRV when `extra-platforms` feature is enabled depends on the MSRV of `portable-atomic`. + ## Serde support Serde support is optional and disabled by default. To enable use the feature `serde`. @@ -36,6 +51,8 @@ bytes = { version = "1", features = ["serde"] } ``` +The MSRV when `serde` feature is enabled depends on the MSRV of `serde`. + ## Building documentation When building the `bytes` documentation the `docsrs` option should be used, otherwise diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/miri.sh clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/miri.sh --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/miri.sh 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/miri.sh 2006-07-24 01:21:28.000000000 +0000 @@ -8,3 +8,6 @@ cargo miri test cargo miri test --target mips64-unknown-linux-gnuabi64 + +# run with wrapping integer overflow instead of panic +cargo miri test --release diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/panic-abort.sh clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/panic-abort.sh --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/panic-abort.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/panic-abort.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +#!/bin/bash + +set -ex +RUSTFLAGS="$RUSTFLAGS -Cpanic=abort -Zpanic-abort-tests" cargo test --all-features --test '*' diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/test-stable.sh clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/test-stable.sh --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/ci/test-stable.sh 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/ci/test-stable.sh 2006-07-24 01:21:28.000000000 +0000 @@ -16,7 +16,10 @@ cargo check --benches # Check minimal versions - cargo clean - cargo update -Zminimal-versions + # Remove dev-dependencies from Cargo.toml to prevent the next `cargo update` + # from determining minimal versions based on dev-dependencies. + cargo hack --remove-dev-deps --workspace + # Update Cargo.lock to minimal version dependencies. + cargo update -Z minimal-versions cargo check --all-features fi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/bytes/clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/clippy.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/clippy.toml 2006-07-24 01:21:28.000000000 +0000 @@ -1 +1 @@ -msrv = "1.39" +msrv = "1.57" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/buf_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/buf_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,19 +3,22 @@ use crate::buf::{take, Chain, Take}; #[cfg(feature = "std")] use crate::{min_u64_usize, saturating_sub_usize_u64}; -use crate::{panic_advance, panic_does_not_fit}; +use crate::{panic_advance, panic_does_not_fit, TryGetError}; #[cfg(feature = "std")] use std::io::IoSlice; use alloc::boxed::Box; -macro_rules! buf_get_impl { +macro_rules! buf_try_get_impl { ($this:ident, $typ:tt::$conv:tt) => {{ const SIZE: usize = core::mem::size_of::<$typ>(); if $this.remaining() < SIZE { - panic_advance(SIZE, $this.remaining()); + return Err(TryGetError { + requested: SIZE, + available: $this.remaining(), + }); } // try to convert directly from the bytes @@ -29,12 +32,12 @@ if let Some(ret) = ret { // if the direct conversion was possible, advance and return $this.advance(SIZE); - return ret; + return Ok(ret); } else { // if not we copy the bytes in a temp buffer then convert let mut buf = [0; SIZE]; $this.copy_to_slice(&mut buf); // (do the advance) - return $typ::$conv(buf); + return Ok($typ::$conv(buf)); } }}; (le => $this:ident, $typ:tt, $len_to_read:expr) => {{ @@ -49,8 +52,8 @@ None => panic_does_not_fit(SIZE, $len_to_read), }; - $this.copy_to_slice(subslice); - return $typ::from_le_bytes(buf); + $this.try_copy_to_slice(subslice)?; + return Ok($typ::from_le_bytes(buf)); }}; (be => $this:ident, $typ:tt, $len_to_read:expr) => {{ const SIZE: usize = core::mem::size_of::<$typ>(); @@ -61,8 +64,23 @@ }; let mut buf = [0; SIZE]; - $this.copy_to_slice(&mut buf[slice_at..]); - return $typ::from_be_bytes(buf); + $this.try_copy_to_slice(&mut buf[slice_at..])?; + return Ok($typ::from_be_bytes(buf)); + }}; +} + +macro_rules! buf_get_impl { + ($this:ident, $typ:tt::$conv:tt) => {{ + return (|| buf_try_get_impl!($this, $typ::$conv))() + .unwrap_or_else(|error| panic_advance(&error)); + }}; + (le => $this:ident, $typ:tt, $len_to_read:expr) => {{ + return (|| buf_try_get_impl!(le => $this, $typ, $len_to_read))() + .unwrap_or_else(|error| panic_advance(&error)); + }}; + (be => $this:ident, $typ:tt, $len_to_read:expr) => {{ + return (|| buf_try_get_impl!(be => $this, $typ, $len_to_read))() + .unwrap_or_else(|error| panic_advance(&error)); }}; } @@ -164,12 +182,12 @@ /// fetching more than one slice at once. `dst` is a slice of `IoSlice` /// references, enabling the slice to be directly used with [`writev`] /// without any further conversion. The sum of the lengths of all the - /// buffers in `dst` will be less than or equal to `Buf::remaining()`. + /// buffers written to `dst` will be less than or equal to `Buf::remaining()`. /// /// The entries in `dst` will be overwritten, but the data **contained** by - /// the slices **will not** be modified. If `chunk_vectored` does not fill every - /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices - /// in `self. + /// the slices **will not** be modified. The return value is the number of + /// slices written to `dst`. If `Buf::remaining()` is non-zero, then this + /// writes at least one non-empty slice to `dst`. /// /// This is a lower level function. Most operations are done with other /// functions. @@ -273,20 +291,9 @@ /// # Panics /// /// This function panics if `self.remaining() < dst.len()`. - fn copy_to_slice(&mut self, mut dst: &mut [u8]) { - if self.remaining() < dst.len() { - panic_advance(dst.len(), self.remaining()); - } - - while !dst.is_empty() { - let src = self.chunk(); - let cnt = usize::min(src.len(), dst.len()); - - dst[..cnt].copy_from_slice(&src[..cnt]); - dst = &mut dst[cnt..]; - - self.advance(cnt); - } + fn copy_to_slice(&mut self, dst: &mut [u8]) { + self.try_copy_to_slice(dst) + .unwrap_or_else(|error| panic_advance(&error)); } /// Gets an unsigned 8 bit integer from `self`. @@ -307,7 +314,10 @@ /// This function panics if there is no more remaining data in `self`. fn get_u8(&mut self) -> u8 { if self.remaining() < 1 { - panic_advance(1, 0); + panic_advance(&TryGetError { + requested: 1, + available: 0, + }) } let ret = self.chunk()[0]; self.advance(1); @@ -332,7 +342,10 @@ /// This function panics if there is no more remaining data in `self`. fn get_i8(&mut self) -> i8 { if self.remaining() < 1 { - panic_advance(1, 0); + panic_advance(&TryGetError { + requested: 1, + available: 0, + }); } let ret = self.chunk()[0] as i8; self.advance(1); @@ -858,7 +871,8 @@ /// /// # Panics /// - /// This function panics if there is not enough remaining data in `self`. + /// This function panics if there is not enough remaining data in `self`, or + /// if `nbytes` is greater than 8. fn get_uint(&mut self, nbytes: usize) -> u64 { buf_get_impl!(be => self, u64, nbytes); } @@ -878,7 +892,8 @@ /// /// # Panics /// - /// This function panics if there is not enough remaining data in `self`. + /// This function panics if there is not enough remaining data in `self`, or + /// if `nbytes` is greater than 8. fn get_uint_le(&mut self, nbytes: usize) -> u64 { buf_get_impl!(le => self, u64, nbytes); } @@ -1113,6 +1128,1214 @@ f64::from_bits(self.get_u64_ne()) } + /// Copies bytes from `self` into `dst`. + /// + /// The cursor is advanced by the number of bytes copied. `self` must have + /// enough remaining bytes to fill `dst`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// let mut dst = [0; 5]; + /// + /// assert_eq!(Ok(()), buf.try_copy_to_slice(&mut dst)); + /// assert_eq!(&b"hello"[..], &dst); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"hello world"[..]; + /// let mut dst = [0; 12]; + /// + /// assert_eq!(Err(TryGetError{requested: 12, available: 11}), buf.try_copy_to_slice(&mut dst)); + /// assert_eq!(11, buf.remaining()); + /// ``` + fn try_copy_to_slice(&mut self, mut dst: &mut [u8]) -> Result<(), TryGetError> { + if self.remaining() < dst.len() { + return Err(TryGetError { + requested: dst.len(), + available: self.remaining(), + }); + } + + while !dst.is_empty() { + let src = self.chunk(); + let cnt = usize::min(src.len(), dst.len()); + + dst[..cnt].copy_from_slice(&src[..cnt]); + dst = &mut dst[cnt..]; + + self.advance(cnt); + } + Ok(()) + } + + /// Gets an unsigned 8 bit integer from `self`. + /// + /// The current position is advanced by 1. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(Ok(0x08_u8), buf.try_get_u8()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b""[..]; + /// assert_eq!(Err(TryGetError{requested: 1, available: 0}), buf.try_get_u8()); + /// ``` + fn try_get_u8(&mut self) -> Result { + if self.remaining() < 1 { + return Err(TryGetError { + requested: 1, + available: self.remaining(), + }); + } + let ret = self.chunk()[0]; + self.advance(1); + Ok(ret) + } + + /// Gets a signed 8 bit integer from `self`. + /// + /// The current position is advanced by 1. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(Ok(0x08_i8), buf.try_get_i8()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b""[..]; + /// assert_eq!(Err(TryGetError{requested: 1, available: 0}), buf.try_get_i8()); + /// ``` + fn try_get_i8(&mut self) -> Result { + if self.remaining() < 1 { + return Err(TryGetError { + requested: 1, + available: self.remaining(), + }); + } + let ret = self.chunk()[0] as i8; + self.advance(1); + Ok(ret) + } + + /// Gets an unsigned 16 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(Ok(0x0809_u16), buf.try_get_u16()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_u16()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_u16(&mut self) -> Result { + buf_try_get_impl!(self, u16::from_be_bytes) + } + + /// Gets an unsigned 16 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(Ok(0x0809_u16), buf.try_get_u16_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_u16_le()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_u16_le(&mut self) -> Result { + buf_try_get_impl!(self, u16::from_le_bytes) + } + + /// Gets an unsigned 16 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x08\x09 hello", + /// false => b"\x09\x08 hello", + /// }; + /// assert_eq!(Ok(0x0809_u16), buf.try_get_u16_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_u16_ne()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_u16_ne(&mut self) -> Result { + buf_try_get_impl!(self, u16::from_ne_bytes) + } + + /// Gets a signed 16 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(Ok(0x0809_i16), buf.try_get_i16()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_i16()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_i16(&mut self) -> Result { + buf_try_get_impl!(self, i16::from_be_bytes) + } + + /// Gets an signed 16 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(Ok(0x0809_i16), buf.try_get_i16_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_i16_le()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_i16_le(&mut self) -> Result { + buf_try_get_impl!(self, i16::from_le_bytes) + } + + /// Gets a signed 16 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x08\x09 hello", + /// false => b"\x09\x08 hello", + /// }; + /// assert_eq!(Ok(0x0809_i16), buf.try_get_i16_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08"[..]; + /// assert_eq!(Err(TryGetError{requested: 2, available: 1}), buf.try_get_i16_ne()); + /// assert_eq!(1, buf.remaining()); + /// ``` + fn try_get_i16_ne(&mut self) -> Result { + buf_try_get_impl!(self, i16::from_ne_bytes) + } + + /// Gets an unsigned 32 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(Ok(0x0809A0A1), buf.try_get_u32()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_u32()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_u32(&mut self) -> Result { + buf_try_get_impl!(self, u32::from_be_bytes) + } + + /// Gets an unsigned 32 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(Ok(0x0809A0A1_u32), buf.try_get_u32_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_u32_le()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_u32_le(&mut self) -> Result { + buf_try_get_impl!(self, u32::from_le_bytes) + } + + /// Gets an unsigned 32 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x08\x09\xA0\xA1 hello", + /// false => b"\xA1\xA0\x09\x08 hello", + /// }; + /// assert_eq!(Ok(0x0809A0A1_u32), buf.try_get_u32_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_u32_ne()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_u32_ne(&mut self) -> Result { + buf_try_get_impl!(self, u32::from_ne_bytes) + } + + /// Gets a signed 32 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(Ok(0x0809A0A1_i32), buf.try_get_i32()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_i32()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_i32(&mut self) -> Result { + buf_try_get_impl!(self, i32::from_be_bytes) + } + + /// Gets a signed 32 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(Ok(0x0809A0A1_i32), buf.try_get_i32_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_i32_le()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_i32_le(&mut self) -> Result { + buf_try_get_impl!(self, i32::from_le_bytes) + } + + /// Gets a signed 32 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x08\x09\xA0\xA1 hello", + /// false => b"\xA1\xA0\x09\x08 hello", + /// }; + /// assert_eq!(Ok(0x0809A0A1_i32), buf.try_get_i32_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_i32_ne()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_i32_ne(&mut self) -> Result { + buf_try_get_impl!(self, i32::from_ne_bytes) + } + + /// Gets an unsigned 64 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(Ok(0x0102030405060708_u64), buf.try_get_u64()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_u64()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_u64(&mut self) -> Result { + buf_try_get_impl!(self, u64::from_be_bytes) + } + + /// Gets an unsigned 64 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x0102030405060708_u64), buf.try_get_u64_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_u64_le()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_u64_le(&mut self) -> Result { + buf_try_get_impl!(self, u64::from_le_bytes) + } + + /// Gets an unsigned 64 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03\x04\x05\x06\x07\x08 hello", + /// false => b"\x08\x07\x06\x05\x04\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x0102030405060708_u64), buf.try_get_u64_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_u64_ne()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_u64_ne(&mut self) -> Result { + buf_try_get_impl!(self, u64::from_ne_bytes) + } + + /// Gets a signed 64 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(Ok(0x0102030405060708_i64), buf.try_get_i64()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_i64()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_i64(&mut self) -> Result { + buf_try_get_impl!(self, i64::from_be_bytes) + } + + /// Gets a signed 64 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x0102030405060708_i64), buf.try_get_i64_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_i64_le()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_i64_le(&mut self) -> Result { + buf_try_get_impl!(self, i64::from_le_bytes) + } + + /// Gets a signed 64 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03\x04\x05\x06\x07\x08 hello", + /// false => b"\x08\x07\x06\x05\x04\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x0102030405060708_i64), buf.try_get_i64_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_i64_ne()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_i64_ne(&mut self) -> Result { + buf_try_get_impl!(self, i64::from_ne_bytes) + } + + /// Gets an unsigned 128 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(Ok(0x01020304050607080910111213141516_u128), buf.try_get_u128()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_u128()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_u128(&mut self) -> Result { + buf_try_get_impl!(self, u128::from_be_bytes) + } + + /// Gets an unsigned 128 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x01020304050607080910111213141516_u128), buf.try_get_u128_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_u128_le()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_u128_le(&mut self) -> Result { + buf_try_get_impl!(self, u128::from_le_bytes) + } + + /// Gets an unsigned 128 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello", + /// false => b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x01020304050607080910111213141516_u128), buf.try_get_u128_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_u128_ne()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_u128_ne(&mut self) -> Result { + buf_try_get_impl!(self, u128::from_ne_bytes) + } + + /// Gets a signed 128 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(Ok(0x01020304050607080910111213141516_i128), buf.try_get_i128()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_i128()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_i128(&mut self) -> Result { + buf_try_get_impl!(self, i128::from_be_bytes) + } + + /// Gets a signed 128 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x01020304050607080910111213141516_i128), buf.try_get_i128_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_i128_le()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_i128_le(&mut self) -> Result { + buf_try_get_impl!(self, i128::from_le_bytes) + } + + /// Gets a signed 128 bit integer from `self` in native-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello", + /// false => b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x01020304050607080910111213141516_i128), buf.try_get_i128_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15"[..]; + /// assert_eq!(Err(TryGetError{requested: 16, available: 15}), buf.try_get_i128_ne()); + /// assert_eq!(15, buf.remaining()); + /// ``` + fn try_get_i128_ne(&mut self) -> Result { + buf_try_get_impl!(self, i128::from_ne_bytes) + } + + /// Gets an unsigned n-byte integer from `self` in big-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(Ok(0x010203_u64), buf.try_get_uint(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_uint(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` > 8. + fn try_get_uint(&mut self, nbytes: usize) -> Result { + buf_try_get_impl!(be => self, u64, nbytes); + } + + /// Gets an unsigned n-byte integer from `self` in little-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x010203_u64), buf.try_get_uint_le(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_uint_le(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` > 8. + fn try_get_uint_le(&mut self, nbytes: usize) -> Result { + buf_try_get_impl!(le => self, u64, nbytes); + } + + /// Gets an unsigned n-byte integer from `self` in native-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03 hello", + /// false => b"\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x010203_u64), buf.try_get_uint_ne(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03", + /// false => b"\x03\x02\x01", + /// }; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_uint_ne(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` is greater than 8. + fn try_get_uint_ne(&mut self, nbytes: usize) -> Result { + if cfg!(target_endian = "big") { + self.try_get_uint(nbytes) + } else { + self.try_get_uint_le(nbytes) + } + } + + /// Gets a signed n-byte integer from `self` in big-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(Ok(0x010203_i64), buf.try_get_int(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_int(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` is greater than 8. + fn try_get_int(&mut self, nbytes: usize) -> Result { + buf_try_get_impl!(be => self, i64, nbytes); + } + + /// Gets a signed n-byte integer from `self` in little-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(Ok(0x010203_i64), buf.try_get_int_le(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_int_le(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` is greater than 8. + fn try_get_int_le(&mut self, nbytes: usize) -> Result { + buf_try_get_impl!(le => self, i64, nbytes); + } + + /// Gets a signed n-byte integer from `self` in native-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03 hello", + /// false => b"\x03\x02\x01 hello", + /// }; + /// assert_eq!(Ok(0x010203_i64), buf.try_get_int_ne(3)); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x01\x02\x03", + /// false => b"\x03\x02\x01", + /// }; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_int_ne(4)); + /// assert_eq!(3, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `nbytes` is greater than 8. + fn try_get_int_ne(&mut self, nbytes: usize) -> Result { + if cfg!(target_endian = "big") { + self.try_get_int(nbytes) + } else { + self.try_get_int_le(nbytes) + } + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\x99\x99\x9A hello"[..]; + /// assert_eq!(1.2f32, buf.get_f32()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\x99\x99"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_f32()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_f32(&mut self) -> Result { + Ok(f32::from_bits(self.try_get_u32()?)) + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x9A\x99\x99\x3F hello"[..]; + /// assert_eq!(1.2f32, buf.get_f32_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\x99\x99"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_f32_le()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_f32_le(&mut self) -> Result { + Ok(f32::from_bits(self.try_get_u32_le()?)) + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in native-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x3F\x99\x99\x9A hello", + /// false => b"\x9A\x99\x99\x3F hello", + /// }; + /// assert_eq!(1.2f32, buf.get_f32_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\x99\x99"[..]; + /// assert_eq!(Err(TryGetError{requested: 4, available: 3}), buf.try_get_f32_ne()); + /// assert_eq!(3, buf.remaining()); + /// ``` + fn try_get_f32_ne(&mut self) -> Result { + Ok(f32::from_bits(self.try_get_u32_ne()?)) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello"[..]; + /// assert_eq!(1.2f64, buf.get_f64()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_f64()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_f64(&mut self) -> Result { + Ok(f64::from_bits(self.try_get_u64()?)) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello"[..]; + /// assert_eq!(1.2f64, buf.get_f64_le()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_f64_le()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_f64_le(&mut self) -> Result { + Ok(f64::from_bits(self.try_get_u64_le()?)) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in native-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// Returns `Err(TryGetError)` when there are not enough + /// remaining bytes to read the value. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = match cfg!(target_endian = "big") { + /// true => b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello", + /// false => b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello", + /// }; + /// assert_eq!(1.2f64, buf.get_f64_ne()); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33"[..]; + /// assert_eq!(Err(TryGetError{requested: 8, available: 7}), buf.try_get_f64_ne()); + /// assert_eq!(7, buf.remaining()); + /// ``` + fn try_get_f64_ne(&mut self) -> Result { + Ok(f64::from_bits(self.try_get_u64_ne()?)) + } + /// Consumes `len` bytes inside self and returns new instance of `Bytes` /// with this data. /// @@ -1136,7 +2359,10 @@ use super::BufMut; if self.remaining() < len { - panic_advance(len, self.remaining()); + panic_advance(&TryGetError { + requested: len, + available: self.remaining(), + }); } let mut ret = crate::BytesMut::with_capacity(len); @@ -1361,6 +2587,36 @@ } #[inline] + fn get_u128(&mut self) -> u128 { + (**self).get_u128() + } + + #[inline] + fn get_u128_le(&mut self) -> u128 { + (**self).get_u128_le() + } + + #[inline] + fn get_u128_ne(&mut self) -> u128 { + (**self).get_u128_ne() + } + + #[inline] + fn get_i128(&mut self) -> i128 { + (**self).get_i128() + } + + #[inline] + fn get_i128_le(&mut self) -> i128 { + (**self).get_i128_le() + } + + #[inline] + fn get_i128_ne(&mut self) -> i128 { + (**self).get_i128_ne() + } + + #[inline] fn get_uint(&mut self, nbytes: usize) -> u64 { (**self).get_uint(nbytes) } @@ -1391,6 +2647,231 @@ } #[inline] + fn get_f32(&mut self) -> f32 { + (**self).get_f32() + } + + #[inline] + fn get_f32_le(&mut self) -> f32 { + (**self).get_f32_le() + } + + #[inline] + fn get_f32_ne(&mut self) -> f32 { + (**self).get_f32_ne() + } + + #[inline] + fn get_f64(&mut self) -> f64 { + (**self).get_f64() + } + + #[inline] + fn get_f64_le(&mut self) -> f64 { + (**self).get_f64_le() + } + + #[inline] + fn get_f64_ne(&mut self) -> f64 { + (**self).get_f64_ne() + } + + #[inline] + fn try_copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), TryGetError> { + (**self).try_copy_to_slice(dst) + } + + #[inline] + fn try_get_u8(&mut self) -> Result { + (**self).try_get_u8() + } + + #[inline] + fn try_get_i8(&mut self) -> Result { + (**self).try_get_i8() + } + + #[inline] + fn try_get_u16(&mut self) -> Result { + (**self).try_get_u16() + } + + #[inline] + fn try_get_u16_le(&mut self) -> Result { + (**self).try_get_u16_le() + } + + #[inline] + fn try_get_u16_ne(&mut self) -> Result { + (**self).try_get_u16_ne() + } + + #[inline] + fn try_get_i16(&mut self) -> Result { + (**self).try_get_i16() + } + + #[inline] + fn try_get_i16_le(&mut self) -> Result { + (**self).try_get_i16_le() + } + + #[inline] + fn try_get_i16_ne(&mut self) -> Result { + (**self).try_get_i16_ne() + } + + #[inline] + fn try_get_u32(&mut self) -> Result { + (**self).try_get_u32() + } + + #[inline] + fn try_get_u32_le(&mut self) -> Result { + (**self).try_get_u32_le() + } + + #[inline] + fn try_get_u32_ne(&mut self) -> Result { + (**self).try_get_u32_ne() + } + + #[inline] + fn try_get_i32(&mut self) -> Result { + (**self).try_get_i32() + } + + #[inline] + fn try_get_i32_le(&mut self) -> Result { + (**self).try_get_i32_le() + } + + #[inline] + fn try_get_i32_ne(&mut self) -> Result { + (**self).try_get_i32_ne() + } + + #[inline] + fn try_get_u64(&mut self) -> Result { + (**self).try_get_u64() + } + + #[inline] + fn try_get_u64_le(&mut self) -> Result { + (**self).try_get_u64_le() + } + + #[inline] + fn try_get_u64_ne(&mut self) -> Result { + (**self).try_get_u64_ne() + } + + #[inline] + fn try_get_i64(&mut self) -> Result { + (**self).try_get_i64() + } + + #[inline] + fn try_get_i64_le(&mut self) -> Result { + (**self).try_get_i64_le() + } + + #[inline] + fn try_get_i64_ne(&mut self) -> Result { + (**self).try_get_i64_ne() + } + + #[inline] + fn try_get_u128(&mut self) -> Result { + (**self).try_get_u128() + } + + #[inline] + fn try_get_u128_le(&mut self) -> Result { + (**self).try_get_u128_le() + } + + #[inline] + fn try_get_u128_ne(&mut self) -> Result { + (**self).try_get_u128_ne() + } + + #[inline] + fn try_get_i128(&mut self) -> Result { + (**self).try_get_i128() + } + + #[inline] + fn try_get_i128_le(&mut self) -> Result { + (**self).try_get_i128_le() + } + + #[inline] + fn try_get_i128_ne(&mut self) -> Result { + (**self).try_get_i128_ne() + } + + #[inline] + fn try_get_uint(&mut self, nbytes: usize) -> Result { + (**self).try_get_uint(nbytes) + } + + #[inline] + fn try_get_uint_le(&mut self, nbytes: usize) -> Result { + (**self).try_get_uint_le(nbytes) + } + + #[inline] + fn try_get_uint_ne(&mut self, nbytes: usize) -> Result { + (**self).try_get_uint_ne(nbytes) + } + + #[inline] + fn try_get_int(&mut self, nbytes: usize) -> Result { + (**self).try_get_int(nbytes) + } + + #[inline] + fn try_get_int_le(&mut self, nbytes: usize) -> Result { + (**self).try_get_int_le(nbytes) + } + + #[inline] + fn try_get_int_ne(&mut self, nbytes: usize) -> Result { + (**self).try_get_int_ne(nbytes) + } + + #[inline] + fn try_get_f32(&mut self) -> Result { + (**self).try_get_f32() + } + + #[inline] + fn try_get_f32_le(&mut self) -> Result { + (**self).try_get_f32_le() + } + + #[inline] + fn try_get_f32_ne(&mut self) -> Result { + (**self).try_get_f32_ne() + } + + #[inline] + fn try_get_f64(&mut self) -> Result { + (**self).try_get_f64() + } + + #[inline] + fn try_get_f64_le(&mut self) -> Result { + (**self).try_get_f64_le() + } + + #[inline] + fn try_get_f64_ne(&mut self) -> Result { + (**self).try_get_f64_ne() + } + + #[inline] fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { (**self).copy_to_bytes(len) } @@ -1419,7 +2900,10 @@ #[inline] fn advance(&mut self, cnt: usize) { if self.len() < cnt { - panic_advance(cnt, self.len()); + panic_advance(&TryGetError { + requested: cnt, + available: self.len(), + }); } *self = &self[cnt..]; @@ -1428,7 +2912,10 @@ #[inline] fn copy_to_slice(&mut self, dst: &mut [u8]) { if self.len() < dst.len() { - panic_advance(dst.len(), self.len()); + panic_advance(&TryGetError { + requested: dst.len(), + available: self.len(), + }); } dst.copy_from_slice(&self[..dst.len()]); @@ -1458,7 +2945,10 @@ // We intentionally allow `cnt == 0` here even if `pos > len`. let max_cnt = saturating_sub_usize_u64(len, pos); if cnt > max_cnt { - panic_advance(cnt, max_cnt); + panic_advance(&TryGetError { + requested: cnt, + available: max_cnt, + }); } // This will not overflow because either `cnt == 0` or the sum is not diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/buf_mut.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_mut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/buf_mut.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/buf_mut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,9 @@ use crate::buf::{limit, Chain, Limit, UninitSlice}; #[cfg(feature = "std")] use crate::buf::{writer, Writer}; -use crate::{panic_advance, panic_does_not_fit}; +use crate::{panic_advance, panic_does_not_fit, TryGetError}; -use core::{mem, ptr, usize}; +use core::{mem, ptr}; use alloc::{boxed::Box, vec::Vec}; @@ -204,7 +204,10 @@ Self: Sized, { if self.remaining_mut() < src.remaining() { - panic_advance(src.remaining(), self.remaining_mut()); + panic_advance(&TryGetError { + requested: src.remaining(), + available: self.remaining_mut(), + }); } while src.has_remaining() { @@ -242,7 +245,10 @@ #[inline] fn put_slice(&mut self, mut src: &[u8]) { if self.remaining_mut() < src.len() { - panic_advance(src.len(), self.remaining_mut()); + panic_advance(&TryGetError { + requested: src.len(), + available: self.remaining_mut(), + }); } while !src.is_empty() { @@ -285,7 +291,10 @@ #[inline] fn put_bytes(&mut self, val: u8, mut cnt: usize) { if self.remaining_mut() < cnt { - panic_advance(cnt, self.remaining_mut()); + panic_advance(&TryGetError { + requested: cnt, + available: self.remaining_mut(), + }) } while cnt > 0 { @@ -1487,18 +1496,24 @@ #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { if self.len() < cnt { - panic_advance(cnt, self.len()); + panic_advance(&TryGetError { + requested: cnt, + available: self.len(), + }); } // Lifetime dance taken from `impl Write for &mut [u8]`. - let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); + let (_, b) = core::mem::take(self).split_at_mut(cnt); *self = b; } #[inline] fn put_slice(&mut self, src: &[u8]) { if self.len() < src.len() { - panic_advance(src.len(), self.len()); + panic_advance(&TryGetError { + requested: src.len(), + available: self.len(), + }); } self[..src.len()].copy_from_slice(src); @@ -1509,7 +1524,10 @@ #[inline] fn put_bytes(&mut self, val: u8, cnt: usize) { if self.len() < cnt { - panic_advance(cnt, self.len()); + panic_advance(&TryGetError { + requested: cnt, + available: self.len(), + }); } // SAFETY: We just checked that the pointer is valid for `cnt` bytes. @@ -1534,18 +1552,24 @@ #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { if self.len() < cnt { - panic_advance(cnt, self.len()); + panic_advance(&TryGetError { + requested: cnt, + available: self.len(), + }); } // Lifetime dance taken from `impl Write for &mut [u8]`. - let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); + let (_, b) = core::mem::take(self).split_at_mut(cnt); *self = b; } #[inline] fn put_slice(&mut self, src: &[u8]) { if self.len() < src.len() { - panic_advance(src.len(), self.len()); + panic_advance(&TryGetError { + requested: src.len(), + available: self.len(), + }); } // SAFETY: We just checked that the pointer is valid for `src.len()` bytes. @@ -1558,7 +1582,10 @@ #[inline] fn put_bytes(&mut self, val: u8, cnt: usize) { if self.len() < cnt { - panic_advance(cnt, self.len()); + panic_advance(&TryGetError { + requested: cnt, + available: self.len(), + }); } // SAFETY: We just checked that the pointer is valid for `cnt` bytes. @@ -1573,7 +1600,7 @@ #[inline] fn remaining_mut(&self) -> usize { // A vector can never have more than isize::MAX bytes - core::isize::MAX as usize - self.len() + isize::MAX as usize - self.len() } #[inline] @@ -1582,7 +1609,10 @@ let remaining = self.capacity() - len; if remaining < cnt { - panic_advance(cnt, remaining); + panic_advance(&TryGetError { + requested: cnt, + available: remaining, + }); } // Addition will not overflow since the sum is at most the capacity. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/chain.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/chain.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/chain.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/chain.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ use crate::buf::{IntoIter, UninitSlice}; -use crate::{Buf, BufMut, Bytes}; +use crate::{Buf, BufMut}; #[cfg(feature = "std")] use std::io::IoSlice; @@ -169,7 +169,7 @@ n } - fn copy_to_bytes(&mut self, len: usize) -> Bytes { + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { let a_rem = self.a.remaining(); if a_rem >= len { self.a.copy_to_bytes(len) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/take.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/take.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/take.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/take.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,10 @@ -use crate::{Buf, Bytes}; +use crate::Buf; use core::cmp; +#[cfg(feature = "std")] +use std::io::IoSlice; + /// A `Buf` adapter which limits the bytes read from an underlying buffer. /// /// This struct is generally created by calling `take()` on `Buf`. See @@ -145,11 +148,40 @@ self.limit -= cnt; } - fn copy_to_bytes(&mut self, len: usize) -> Bytes { + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { assert!(len <= self.remaining(), "`len` greater than remaining"); let r = self.inner.copy_to_bytes(len); self.limit -= len; r } + + #[cfg(feature = "std")] + fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { + if self.limit == 0 { + return 0; + } + + const LEN: usize = 16; + let mut slices: [IoSlice<'a>; LEN] = [IoSlice::new(&[]); LEN]; + + let cnt = self + .inner + .chunks_vectored(&mut slices[..dst.len().min(LEN)]); + let mut limit = self.limit; + for (i, (dst, slice)) in dst[..cnt].iter_mut().zip(slices.iter()).enumerate() { + if let Some(buf) = slice.get(..limit) { + // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV. + let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(buf) }; + *dst = IoSlice::new(buf); + return i + 1; + } else { + // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV. + let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(slice) }; + *dst = IoSlice::new(buf); + limit -= slice.len(); + } + } + cnt + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/vec_deque.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/vec_deque.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/buf/vec_deque.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/buf/vec_deque.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,6 @@ use alloc::collections::VecDeque; +#[cfg(feature = "std")] +use std::io; use super::Buf; @@ -16,6 +18,22 @@ } } + #[cfg(feature = "std")] + fn chunks_vectored<'a>(&'a self, dst: &mut [io::IoSlice<'a>]) -> usize { + if self.is_empty() || dst.is_empty() { + return 0; + } + + let (s1, s2) = self.as_slices(); + dst[0] = io::IoSlice::new(s1); + if s2.is_empty() || dst.len() == 1 { + return 1; + } + + dst[1] = io::IoSlice::new(s2); + 2 + } + fn advance(&mut self, cnt: usize) { self.drain(..cnt); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/bytes.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,7 @@ -use core::iter::FromIterator; use core::mem::{self, ManuallyDrop}; use core::ops::{Deref, RangeBounds}; use core::ptr::NonNull; -use core::{cmp, fmt, hash, ptr, slice, usize}; +use core::{cmp, fmt, hash, ptr, slice}; use alloc::{ alloc::{dealloc, Layout}, @@ -16,7 +15,7 @@ #[allow(unused)] use crate::loom::sync::atomic::AtomicMut; use crate::loom::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; -use crate::{offset_from, Buf, BytesMut}; +use crate::{Buf, BytesMut}; /// A cheaply cloneable and sliceable chunk of contiguous memory. /// @@ -112,9 +111,9 @@ pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes, /// fn(data, ptr, len) /// - /// takes `Bytes` to value - pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec, - pub to_mut: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> BytesMut, + /// `into_*` consumes the `Bytes`, returning the respective value. + pub into_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec, + pub into_mut: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> BytesMut, /// fn(data) pub is_unique: unsafe fn(&AtomicPtr<()>) -> bool, /// fn(data, ptr, len) @@ -268,10 +267,7 @@ // and: https://github.com/tokio-rs/bytes/pull/742/#discussion_r1813316032 let owned = Box::into_raw(Box::new(Owned { - lifetime: OwnedLifetime { - ref_cnt: AtomicUsize::new(1), - drop: owned_box_and_drop::, - }, + ref_cnt: AtomicUsize::new(1), owner, })); @@ -279,7 +275,7 @@ ptr: NonNull::dangling().as_ptr(), len: 0, data: AtomicPtr::new(owned.cast()), - vtable: &OWNED_VTABLE, + vtable: &Owned::::VTABLE, }; let buf = unsafe { &*owned }.owner.as_ref(); @@ -401,7 +397,7 @@ ); if end == begin { - return Bytes::new(); + return Bytes::new_empty_with_ptr(self.ptr.wrapping_add(begin)); } let mut ret = self.clone(); @@ -790,7 +786,7 @@ impl PartialOrd for Bytes { fn partial_cmp(&self, other: &Bytes) -> Option { - self.as_slice().partial_cmp(other.as_slice()) + Some(self.cmp(other)) } } @@ -1045,7 +1041,7 @@ /// ``` fn from(bytes: Bytes) -> Self { let bytes = ManuallyDrop::new(bytes); - unsafe { (bytes.vtable.to_mut)(&bytes.data, bytes.ptr, bytes.len) } + unsafe { (bytes.vtable.into_mut)(&bytes.data, bytes.ptr, bytes.len) } } } @@ -1058,7 +1054,7 @@ impl From for Vec { fn from(bytes: Bytes) -> Vec { let bytes = ManuallyDrop::new(bytes); - unsafe { (bytes.vtable.to_vec)(&bytes.data, bytes.ptr, bytes.len) } + unsafe { (bytes.vtable.into_vec)(&bytes.data, bytes.ptr, bytes.len) } } } @@ -1077,8 +1073,8 @@ const STATIC_VTABLE: Vtable = Vtable { clone: static_clone, - to_vec: static_to_vec, - to_mut: static_to_mut, + into_vec: static_to_vec, + into_mut: static_to_mut, is_unique: static_is_unique, drop: static_drop, }; @@ -1109,94 +1105,88 @@ // ===== impl OwnedVtable ===== #[repr(C)] -struct OwnedLifetime { - ref_cnt: AtomicUsize, - drop: unsafe fn(*mut ()), -} - -#[repr(C)] struct Owned { - lifetime: OwnedLifetime, + ref_cnt: AtomicUsize, owner: T, } -unsafe fn owned_box_and_drop(ptr: *mut ()) { - let b: Box> = Box::from_raw(ptr as _); - drop(b); +impl Owned { + const VTABLE: Vtable = Vtable { + clone: owned_clone::, + into_vec: owned_to_vec::, + into_mut: owned_to_mut::, + is_unique: owned_is_unique, + drop: owned_drop::, + }; } -unsafe fn owned_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes { +unsafe fn owned_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes { let owned = data.load(Ordering::Relaxed); - let ref_cnt = &(*owned.cast::()).ref_cnt; - let old_cnt = ref_cnt.fetch_add(1, Ordering::Relaxed); + let old_cnt = (*owned.cast::()).fetch_add(1, Ordering::Relaxed); if old_cnt > usize::MAX >> 1 { - crate::abort() + crate::abort(); } Bytes { ptr, len, data: AtomicPtr::new(owned as _), - vtable: &OWNED_VTABLE, + vtable: &Owned::::VTABLE, } } -unsafe fn owned_to_vec(_data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec { +unsafe fn owned_to_vec(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec { let slice = slice::from_raw_parts(ptr, len); - slice.to_vec() + let vec = slice.to_vec(); + owned_drop_impl::(data.load(Ordering::Relaxed)); + vec } -unsafe fn owned_to_mut(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> BytesMut { - let bytes_mut = BytesMut::from_vec(owned_to_vec(data, ptr, len)); - owned_drop_impl(data.load(Ordering::Relaxed)); - bytes_mut +unsafe fn owned_to_mut(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> BytesMut { + BytesMut::from_vec(owned_to_vec::(data, ptr, len)) } unsafe fn owned_is_unique(_data: &AtomicPtr<()>) -> bool { false } -unsafe fn owned_drop_impl(owned: *mut ()) { - let lifetime = owned.cast::(); - let ref_cnt = &(*lifetime).ref_cnt; +unsafe fn owned_drop_impl(owned: *mut ()) { + { + let ref_cnt = &*owned.cast::(); - let old_cnt = ref_cnt.fetch_sub(1, Ordering::Release); - if old_cnt != 1 { - return; + let old_cnt = ref_cnt.fetch_sub(1, Ordering::Release); + debug_assert!( + old_cnt > 0 && old_cnt <= usize::MAX >> 1, + "expected non-zero refcount and no underflow" + ); + if old_cnt != 1 { + return; + } + ref_cnt.load(Ordering::Acquire); } - ref_cnt.load(Ordering::Acquire); - let drop_fn = &(*lifetime).drop; - drop_fn(owned) + drop(Box::>::from_raw(owned.cast())); } -unsafe fn owned_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) { +unsafe fn owned_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) { let owned = data.load(Ordering::Relaxed); - owned_drop_impl(owned); + owned_drop_impl::(owned); } -static OWNED_VTABLE: Vtable = Vtable { - clone: owned_clone, - to_vec: owned_to_vec, - to_mut: owned_to_mut, - is_unique: owned_is_unique, - drop: owned_drop, -}; - // ===== impl PromotableVtable ===== static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable { clone: promotable_even_clone, - to_vec: promotable_even_to_vec, - to_mut: promotable_even_to_mut, + into_vec: promotable_even_to_vec, + into_mut: promotable_even_to_mut, is_unique: promotable_is_unique, drop: promotable_even_drop, }; static PROMOTABLE_ODD_VTABLE: Vtable = Vtable { clone: promotable_odd_clone, - to_vec: promotable_odd_to_vec, - to_mut: promotable_odd_to_mut, + into_vec: promotable_odd_to_vec, + into_mut: promotable_odd_to_mut, is_unique: promotable_is_unique, drop: promotable_odd_drop, }; @@ -1231,7 +1221,7 @@ let buf = f(shared); - let cap = offset_from(ptr, buf) + len; + let cap = ptr.offset_from(buf) as usize + len; // Copy back buffer ptr::copy(ptr, buf, len); @@ -1259,7 +1249,7 @@ debug_assert_eq!(kind, KIND_VEC); let buf = f(shared); - let off = offset_from(ptr, buf); + let off = ptr.offset_from(buf) as usize; let cap = off + len; let v = Vec::from_raw_parts(buf, cap, cap); @@ -1344,7 +1334,7 @@ } unsafe fn free_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) { - let cap = offset_from(offset, buf) + len; + let cap = offset.offset_from(buf) as usize + len; dealloc(buf, Layout::from_size_align(cap, 1).unwrap()) } @@ -1371,8 +1361,8 @@ static SHARED_VTABLE: Vtable = Vtable { clone: shared_clone, - to_vec: shared_to_vec, - to_mut: shared_to_mut, + into_vec: shared_to_vec, + into_mut: shared_to_mut, is_unique: shared_is_unique, drop: shared_drop, }; @@ -1440,7 +1430,7 @@ let cap = shared.cap; // Rebuild Vec - let off = offset_from(ptr, buf); + let off = ptr.offset_from(buf) as usize; let v = Vec::from_raw_parts(buf, len + off, cap); let mut b = BytesMut::from_vec(v); @@ -1506,7 +1496,7 @@ // vector. let shared = Box::new(Shared { buf, - cap: offset_from(offset, buf) + len, + cap: offset.offset_from(buf) as usize + len, // Initialize refcount to 2. One for this reference, and one // for the new clone that will be returned from // `shallow_clone`. @@ -1533,7 +1523,7 @@ // pointed to by `actual` will be visible. match atom.compare_exchange(ptr as _, shared as _, Ordering::AcqRel, Ordering::Acquire) { Ok(actual) => { - debug_assert!(actual as usize == ptr as usize); + debug_assert!(core::ptr::eq(actual, ptr)); // The upgrade was successful, the new handle can be // returned. Bytes { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/bytes_mut.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes_mut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/bytes_mut.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/bytes_mut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,7 @@ -use core::iter::FromIterator; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::ptr::{self, NonNull}; -use core::{cmp, fmt, hash, isize, slice, usize}; +use core::{cmp, fmt, hash, slice}; use alloc::{ borrow::{Borrow, BorrowMut}, @@ -17,7 +16,7 @@ #[allow(unused)] use crate::loom::sync::atomic::AtomicMut; use crate::loom::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; -use crate::{offset_from, Buf, BufMut, Bytes}; +use crate::{Buf, BufMut, Bytes, TryGetError}; /// A unique reference to a contiguous slice of memory. /// @@ -226,7 +225,7 @@ /// /// # Examples /// - /// ``` + /// ```ignore-wasm /// use bytes::{BytesMut, BufMut}; /// use std::thread; /// @@ -694,11 +693,17 @@ let v_capacity = v.capacity(); let ptr = v.as_mut_ptr(); - let offset = offset_from(self.ptr.as_ptr(), ptr); + let offset = self.ptr.as_ptr().offset_from(ptr) as usize; + + let new_cap_plus_offset = match new_cap.checked_add(offset) { + Some(new_cap_plus_offset) => new_cap_plus_offset, + None if !allocate => return false, + None => panic!("overflow"), + }; // Compare the condition in the `kind == KIND_VEC` case above // for more details. - if v_capacity >= new_cap + offset { + if v_capacity >= new_cap_plus_offset { self.cap = new_cap; // no copy is necessary } else if v_capacity >= new_cap && offset >= len { @@ -714,14 +719,12 @@ if !allocate { return false; } - // calculate offset - let off = (self.ptr.as_ptr() as usize) - (v.as_ptr() as usize); // new_cap is calculated in terms of `BytesMut`, not the underlying // `Vec`, so it does not take the offset into account. // // Thus we have to manually add it here. - new_cap = new_cap.checked_add(off).expect("overflow"); + new_cap = new_cap_plus_offset; // The vector capacity is not sufficient. The reserve request is // asking for more than the initial buffer capacity. Allocate more @@ -743,13 +746,13 @@ // the unused capacity of the vector is copied over to the new // allocation, so we need to ensure that we don't have any data we // care about in the unused capacity before calling `reserve`. - debug_assert!(off + len <= v.capacity()); - v.set_len(off + len); + debug_assert!(offset + len <= v.capacity()); + v.set_len(offset + len); v.reserve(new_cap - v.len()); // Update the info - self.ptr = vptr(v.as_mut_ptr().add(off)); - self.cap = v.capacity() - off; + self.ptr = vptr(v.as_mut_ptr().add(offset)); + self.cap = v.capacity() - offset; } return true; @@ -780,7 +783,7 @@ self.ptr = vptr(v.as_mut_ptr()); self.cap = v.capacity(); debug_assert_eq!(self.len, v.len()); - return true; + true } /// Attempts to cheaply reclaim already allocated capacity for at least `additional` more @@ -986,7 +989,7 @@ // new start and updating the `len` field to reflect the new length // of the view. self.ptr = vptr(self.ptr.as_ptr().add(count)); - self.len = self.len.checked_sub(count).unwrap_or(0); + self.len = self.len.saturating_sub(count); self.cap -= count; } @@ -1171,14 +1174,18 @@ unsafe impl BufMut for BytesMut { #[inline] fn remaining_mut(&self) -> usize { - usize::MAX - self.len() + // Max allocation size is isize::MAX. + isize::MAX as usize - self.len() } #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { let remaining = self.cap - self.len(); if cnt > remaining { - super::panic_advance(cnt, remaining); + super::panic_advance(&TryGetError { + requested: cnt, + available: remaining, + }); } // Addition won't overflow since it is at most `self.cap`. self.len = self.len() + cnt; @@ -1199,11 +1206,27 @@ where Self: Sized, { - while src.has_remaining() { - let s = src.chunk(); - let l = s.len(); - self.extend_from_slice(s); - src.advance(l); + if !src.has_remaining() { + // prevent calling `copy_to_bytes`->`put`->`copy_to_bytes` infintely when src is empty + return; + } else if self.capacity() == 0 { + // When capacity is zero, try reusing allocation of `src`. + let src_copy = src.copy_to_bytes(src.remaining()); + drop(src); + match src_copy.try_into_mut() { + Ok(bytes_mut) => *self = bytes_mut, + Err(bytes) => self.extend_from_slice(&bytes), + } + } else { + // In case the src isn't contiguous, reserve upfront. + self.reserve(src.remaining()); + + while src.has_remaining() { + let s = src.chunk(); + let l = s.len(); + self.extend_from_slice(s); + src.advance(l); + } } } @@ -1281,7 +1304,7 @@ impl PartialOrd for BytesMut { fn partial_cmp(&self, other: &BytesMut) -> Option { - self.as_slice().partial_cmp(other.as_slice()) + Some(self.cmp(other)) } } @@ -1716,10 +1739,10 @@ rebuild_vec(bytes.ptr.as_ptr(), bytes.len, bytes.cap, off) } } else { - let shared = bytes.data as *mut Shared; + let shared = bytes.data; if unsafe { (*shared).is_unique() } { - let vec = mem::replace(unsafe { &mut (*shared).vec }, Vec::new()); + let vec = core::mem::take(unsafe { &mut (*shared).vec }); unsafe { release_shared(shared) }; @@ -1773,8 +1796,8 @@ static SHARED_VTABLE: Vtable = Vtable { clone: shared_v_clone, - to_vec: shared_v_to_vec, - to_mut: shared_v_to_mut, + into_vec: shared_v_to_vec, + into_mut: shared_v_to_mut, is_unique: shared_v_is_unique, drop: shared_v_drop, }; @@ -1794,7 +1817,7 @@ let shared = &mut *shared; // Drop shared - let mut vec = mem::replace(&mut shared.vec, Vec::new()); + let mut vec = core::mem::take(&mut shared.vec); release_shared(shared); // Copy back buffer @@ -1820,7 +1843,7 @@ let v = &mut shared.vec; let v_capacity = v.capacity(); let v_ptr = v.as_mut_ptr(); - let offset = offset_from(ptr as *mut u8, v_ptr); + let offset = ptr.offset_from(v_ptr) as usize; let cap = v_capacity - offset; let ptr = vptr(ptr as *mut u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,3 @@ -#![allow(unknown_lints, unexpected_cfgs)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] #![doc(test( no_crate_inject, @@ -115,7 +114,6 @@ #[inline(always)] #[cfg(feature = "std")] fn saturating_sub_usize_u64(a: usize, b: u64) -> usize { - use core::convert::TryFrom; match usize::try_from(b) { Ok(b) => a.saturating_sub(b), Err(_) => 0, @@ -125,19 +123,53 @@ #[inline(always)] #[cfg(feature = "std")] fn min_u64_usize(a: u64, b: usize) -> usize { - use core::convert::TryFrom; match usize::try_from(a) { Ok(a) => usize::min(a, b), Err(_) => b, } } +/// Error type for the `try_get_` methods of [`Buf`]. +/// Indicates that there were not enough remaining +/// bytes in the buffer while attempting +/// to get a value from a [`Buf`] with one +/// of the `try_get_` methods. +#[derive(Debug, PartialEq, Eq)] +pub struct TryGetError { + /// The number of bytes necessary to get the value + pub requested: usize, + + /// The number of bytes available in the buffer + pub available: usize, +} + +impl core::fmt::Display for TryGetError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + write!( + f, + "Not enough bytes remaining in buffer to read value (requested {} but only {} available)", + self.requested, + self.available + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryGetError {} + +#[cfg(feature = "std")] +impl From for std::io::Error { + fn from(error: TryGetError) -> Self { + std::io::Error::new(std::io::ErrorKind::Other, error) + } +} + /// Panic with a nice error message. #[cold] -fn panic_advance(idx: usize, len: usize) -> ! { +fn panic_advance(error_info: &TryGetError) -> ! { panic!( "advance out of bounds: the len is {} but advancing by {}", - len, idx + error_info.available, error_info.requested ); } @@ -148,18 +180,3 @@ size, nbytes ); } - -/// Precondition: dst >= original -/// -/// The following line is equivalent to: -/// -/// ```rust,ignore -/// self.ptr.as_ptr().offset_from(ptr) as usize; -/// ``` -/// -/// But due to min rust is 1.39 and it is only stabilized -/// in 1.47, we cannot use it. -#[inline] -fn offset_from(dst: *const u8, original: *const u8) -> usize { - dst as usize - original as usize -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/loom.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/loom.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/src/loom.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/src/loom.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,10 @@ #[cfg(not(all(test, loom)))] pub(crate) mod sync { pub(crate) mod atomic { + #[cfg(not(feature = "extra-platforms"))] pub(crate) use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; + #[cfg(feature = "extra-platforms")] + pub(crate) use extra_platforms::{AtomicPtr, AtomicUsize, Ordering}; pub(crate) trait AtomicMut { fn with_mut(&mut self, f: F) -> R diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_buf.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_buf.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,88 +1,410 @@ #![warn(rust_2018_idioms)] -use bytes::Buf; +use ::bytes::{Buf, Bytes, BytesMut}; +use core::{cmp, mem}; +use std::collections::VecDeque; #[cfg(feature = "std")] use std::io::IoSlice; -#[test] -fn test_fresh_cursor_vec() { - let mut buf = &b"hello"[..]; +// A random 64-byte ascii string, with the first 8 bytes altered to +// give valid representations of f32 and f64 (making them easier to compare) +// and negative signed numbers when interpreting as big endian +// (testing Sign Extension for `Buf::get_int' and `Buf::get_int_ne`). +const INPUT: &[u8] = b"\xffFqrjrDqPhvTc45vvq33f6bJrUtyHESuTeklWKgYd64xgzxJwvAkpYYnpNJyZSRn"; + +macro_rules! e { + ($big_endian_val:expr, $little_endian_val:expr) => { + if cfg!(target_endian = "big") { + $big_endian_val + } else { + $little_endian_val + } + }; +} + +macro_rules! buf_tests { + ($make_input:ident) => { + buf_tests!($make_input, true); + }; + ($make_input:ident, $checks_vectored_is_complete:expr) => { + use super::*; + + #[test] + fn empty_state() { + let buf = $make_input(&[]); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert!(buf.chunk().is_empty()); + } + + #[test] + fn fresh_state() { + let buf = $make_input(INPUT); + assert_eq!(buf.remaining(), 64); + assert!(buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64); + assert!(INPUT.starts_with(chunk)); + } + + #[test] + fn advance() { + let mut buf = $make_input(INPUT); + buf.advance(8); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } + + #[test] + fn advance_to_end() { + let mut buf = $make_input(INPUT); + buf.advance(64); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.is_empty()); + } + + #[test] + #[should_panic] + fn advance_past_end() { + let mut buf = $make_input(INPUT); + buf.advance(65); + } + + #[test] + #[cfg(feature = "std")] + fn chunks_vectored_empty() { + let buf = $make_input(&[]); + let mut bufs = [IoSlice::new(&[]); 16]; + + let n = buf.chunks_vectored(&mut bufs); + assert_eq!(n, 0); + assert!(bufs.iter().all(|buf| buf.is_empty())); + } + + #[test] + #[cfg(feature = "std")] + fn chunks_vectored_is_complete() { + let buf = $make_input(INPUT); + let mut bufs = [IoSlice::new(&[]); 16]; + + let n = buf.chunks_vectored(&mut bufs); + assert!(n > 0); + assert!(n <= 16); + + let bufs_concat = bufs[..n] + .iter() + .flat_map(|b| b.iter().copied()) + .collect::>(); + if $checks_vectored_is_complete { + assert_eq!(bufs_concat, INPUT); + } else { + // If this panics then `buf` implements `chunks_vectored`. + // Remove the `false` argument from `buf_tests!` for that type. + assert!(bufs_concat.len() < INPUT.len()); + assert!(INPUT.starts_with(&bufs_concat)); + } + + for i in n..16 { + assert!(bufs[i].is_empty()); + } + } + + #[test] + fn copy_to_slice() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 8]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..8]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } - assert_eq!(buf.remaining(), 5); - assert_eq!(buf.chunk(), b"hello"); + #[test] + fn copy_to_slice_big() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 56]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 64 - 56); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..56]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 56); + assert!(INPUT[56..].starts_with(chunk)); + } + + #[test] + fn copy_to_slice_to_end() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 64]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert_eq!(chunk, INPUT); + + assert!(buf.chunk().is_empty()); + } + + #[test] + #[should_panic] + fn copy_to_slice_overflow() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 65]; + buf.copy_to_slice(&mut chunk); + } + + #[test] + fn copy_to_bytes() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(8); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..8]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } + + #[test] + fn copy_to_bytes_big() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(56); + assert_eq!(buf.remaining(), 64 - 56); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..56]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 56); + assert!(INPUT[56..].starts_with(chunk)); + } + + #[test] + fn copy_to_bytes_to_end() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(64); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert_eq!(chunk, INPUT); + + assert!(buf.chunk().is_empty()); + } + + #[test] + #[should_panic] + fn copy_to_bytes_overflow() { + let mut buf = $make_input(INPUT); - buf.advance(2); + let _ = buf.copy_to_bytes(65); + } + + buf_tests!(number $make_input, get_u8, get_u8_overflow, u8, get_u8, 0xff); + buf_tests!(number $make_input, get_i8, get_i8_overflow, i8, get_i8, 0xffu8 as i8); + buf_tests!(number $make_input, get_u16_be, get_u16_be_overflow, u16, get_u16, 0xff46); + buf_tests!(number $make_input, get_u16_le, get_u16_le_overflow, u16, get_u16_le, 0x46ff); + buf_tests!(number $make_input, get_u16_ne, get_u16_ne_overflow, u16, get_u16_ne, e!(0xff46, 0x46ff)); + buf_tests!(number $make_input, get_i16_be, get_i16_be_overflow, i16, get_i16, 0xff46u16 as i16); + buf_tests!(number $make_input, get_i16_le, get_i16_le_overflow, i16, get_i16_le, 0x46ff); + buf_tests!(number $make_input, get_i16_ne, get_i16_ne_overflow, i16, get_i16_ne, e!(0xff46u16 as i16, 0x46ff)); + buf_tests!(number $make_input, get_u32_be, get_u32_be_overflow, u32, get_u32, 0xff467172); + buf_tests!(number $make_input, get_u32_le, get_u32_le_overflow, u32, get_u32_le, 0x727146ff); + buf_tests!(number $make_input, get_u32_ne, get_u32_ne_overflow, u32, get_u32_ne, e!(0xff467172, 0x727146ff)); + buf_tests!(number $make_input, get_i32_be, get_i32_be_overflow, i32, get_i32, 0xff467172u32 as i32); + buf_tests!(number $make_input, get_i32_le, get_i32_le_overflow, i32, get_i32_le, 0x727146ff); + buf_tests!(number $make_input, get_i32_ne, get_i32_ne_overflow, i32, get_i32_ne, e!(0xff467172u32 as i32, 0x727146ff)); + buf_tests!(number $make_input, get_u64_be, get_u64_be_overflow, u64, get_u64, 0xff4671726a724471); + buf_tests!(number $make_input, get_u64_le, get_u64_le_overflow, u64, get_u64_le, 0x7144726a727146ff); + buf_tests!(number $make_input, get_u64_ne, get_u64_ne_overflow, u64, get_u64_ne, e!(0xff4671726a724471, 0x7144726a727146ff)); + buf_tests!(number $make_input, get_i64_be, get_i64_be_overflow, i64, get_i64, 0xff4671726a724471u64 as i64); + buf_tests!(number $make_input, get_i64_le, get_i64_le_overflow, i64, get_i64_le, 0x7144726a727146ff); + buf_tests!(number $make_input, get_i64_ne, get_i64_ne_overflow, i64, get_i64_ne, e!(0xff4671726a724471u64 as i64, 0x7144726a727146ff)); + buf_tests!(number $make_input, get_u128_be, get_u128_be_overflow, u128, get_u128, 0xff4671726a7244715068765463343576); + buf_tests!(number $make_input, get_u128_le, get_u128_le_overflow, u128, get_u128_le, 0x76353463547668507144726a727146ff); + buf_tests!(number $make_input, get_u128_ne, get_u128_ne_overflow, u128, get_u128_ne, e!(0xff4671726a7244715068765463343576, 0x76353463547668507144726a727146ff)); + buf_tests!(number $make_input, get_i128_be, get_i128_be_overflow, i128, get_i128, 0xff4671726a7244715068765463343576u128 as i128); + buf_tests!(number $make_input, get_i128_le, get_i128_le_overflow, i128, get_i128_le, 0x76353463547668507144726a727146ff); + buf_tests!(number $make_input, get_i128_ne, get_i128_ne_overflow, i128, get_i128_ne, e!(0xff4671726a7244715068765463343576u128 as i128, 0x76353463547668507144726a727146ff)); + buf_tests!(number $make_input, get_f32_be, get_f32_be_overflow, f32, get_f32, f32::from_bits(0xff467172)); + buf_tests!(number $make_input, get_f32_le, get_f32_le_overflow, f32, get_f32_le, f32::from_bits(0x727146ff)); + buf_tests!(number $make_input, get_f32_ne, get_f32_ne_overflow, f32, get_f32_ne, f32::from_bits(e!(0xff467172, 0x727146ff))); + buf_tests!(number $make_input, get_f64_be, get_f64_be_overflow, f64, get_f64, f64::from_bits(0xff4671726a724471)); + buf_tests!(number $make_input, get_f64_le, get_f64_le_overflow, f64, get_f64_le, f64::from_bits(0x7144726a727146ff)); + buf_tests!(number $make_input, get_f64_ne, get_f64_ne_overflow, f64, get_f64_ne, f64::from_bits(e!(0xff4671726a724471, 0x7144726a727146ff))); + + buf_tests!(var_number $make_input, get_uint_be, get_uint_be_overflow, u64, get_uint, 3, 0xff4671); + buf_tests!(var_number $make_input, get_uint_le, get_uint_le_overflow, u64, get_uint_le, 3, 0x7146ff); + buf_tests!(var_number $make_input, get_uint_ne, get_uint_ne_overflow, u64, get_uint_ne, 3, e!(0xff4671, 0x7146ff)); + buf_tests!(var_number $make_input, get_int_be, get_int_be_overflow, i64, get_int, 3, 0xffffffffffff4671u64 as i64); + buf_tests!(var_number $make_input, get_int_le, get_int_le_overflow, i64, get_int_le, 3, 0x7146ff); + buf_tests!(var_number $make_input, get_int_ne, get_int_ne_overflow, i64, get_int_ne, 3, e!(0xffffffffffff4671u64 as i64, 0x7146ff)); + }; + (number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $value:expr) => { + #[test] + fn $ok_name() { + let mut buf = $make_input(INPUT); + + let value = buf.$method(); + assert_eq!(buf.remaining(), 64 - mem::size_of::<$number>()); + assert!(buf.has_remaining()); + assert_eq!(value, $value); + } - assert_eq!(buf.remaining(), 3); - assert_eq!(buf.chunk(), b"llo"); + #[test] + #[should_panic] + fn $panic_name() { + let mut buf = $make_input(&[]); - buf.advance(3); + let _ = buf.$method(); + } + }; + (var_number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $len:expr, $value:expr) => { + #[test] + fn $ok_name() { + let mut buf = $make_input(INPUT); + + let value = buf.$method($len); + assert_eq!(buf.remaining(), 64 - $len); + assert!(buf.has_remaining()); + assert_eq!(value, $value); + } - assert_eq!(buf.remaining(), 0); - assert_eq!(buf.chunk(), b""); + #[test] + #[should_panic] + fn $panic_name() { + let mut buf = $make_input(&[]); + + let _ = buf.$method($len); + } + }; } -#[test] -fn test_get_u8() { - let mut buf = &b"\x21zomg"[..]; - assert_eq!(0x21, buf.get_u8()); +mod u8_slice { + fn make_input(buf: &'static [u8]) -> &'static [u8] { + buf + } + + buf_tests!(make_input); } -#[test] -fn test_get_u16() { - let mut buf = &b"\x21\x54zomg"[..]; - assert_eq!(0x2154, buf.get_u16()); - let mut buf = &b"\x21\x54zomg"[..]; - assert_eq!(0x5421, buf.get_u16_le()); +mod bytes { + fn make_input(buf: &'static [u8]) -> impl Buf { + Bytes::from_static(buf) + } + + buf_tests!(make_input); } -#[test] -fn test_get_int() { - let mut buf = &b"\xd6zomg"[..]; - assert_eq!(-42, buf.get_int(1)); - let mut buf = &b"\xd6zomg"[..]; - assert_eq!(-42, buf.get_int_le(1)); - - let mut buf = &b"\xfe\x1d\xc0zomg"[..]; - assert_eq!(0xffffffffffc01dfeu64 as i64, buf.get_int_le(3)); - let mut buf = &b"\xfe\x1d\xc0zomg"[..]; - assert_eq!(0xfffffffffffe1dc0u64 as i64, buf.get_int(3)); +mod bytes_mut { + fn make_input(buf: &'static [u8]) -> impl Buf { + BytesMut::from(buf) + } + + buf_tests!(make_input); } -#[test] -#[should_panic] -fn test_get_u16_buffer_underflow() { - let mut buf = &b"\x21"[..]; - buf.get_u16(); +mod vec_deque { + fn make_input(buf: &'static [u8]) -> impl Buf { + let mut deque = VecDeque::new(); + + if !buf.is_empty() { + // Construct |b|some bytes|a| `VecDeque` + let mid = buf.len() / 2; + let (a, b) = buf.split_at(mid); + + deque.reserve_exact(buf.len() + 1); + + let extra_space = deque.capacity() - b.len() - 1; + deque.resize(extra_space, 0); + + deque.extend(a); + deque.drain(..extra_space); + deque.extend(b); + + let (a, b) = deque.as_slices(); + assert!( + !a.is_empty(), + "could not setup test - attempt to create discontiguous VecDeque failed" + ); + assert!( + !b.is_empty(), + "could not setup test - attempt to create discontiguous VecDeque failed" + ); + } + + deque + } + + buf_tests!(make_input, true); } #[cfg(feature = "std")] -#[test] -fn test_bufs_vec() { - let buf = &b"hello world"[..]; +mod cursor { + use std::io::Cursor; - let b1: &[u8] = &mut []; - let b2: &[u8] = &mut []; + fn make_input(buf: &'static [u8]) -> impl Buf { + Cursor::new(buf) + } - let mut dst = [IoSlice::new(b1), IoSlice::new(b2)]; + buf_tests!(make_input); +} - assert_eq!(1, buf.chunks_vectored(&mut dst[..])); +mod box_bytes { + fn make_input(buf: &'static [u8]) -> impl Buf { + Box::new(Bytes::from_static(buf)) + } + + buf_tests!(make_input); } -#[test] -fn test_vec_deque() { - use std::collections::VecDeque; +mod chain_u8_slice { + fn make_input(buf: &'static [u8]) -> impl Buf { + let (a, b) = buf.split_at(buf.len() / 2); + Buf::chain(a, b) + } + + buf_tests!(make_input); +} - let mut buffer: VecDeque = VecDeque::new(); - buffer.extend(b"hello world"); - assert_eq!(11, buffer.remaining()); - assert_eq!(b"hello world", buffer.chunk()); - buffer.advance(6); - assert_eq!(b"world", buffer.chunk()); - buffer.extend(b" piece"); - let mut out = [0; 11]; - buffer.copy_to_slice(&mut out); - assert_eq!(b"world piece", &out[..]); +mod chain_small_big_u8_slice { + fn make_input(buf: &'static [u8]) -> impl Buf { + let mid = cmp::min(1, buf.len()); + let (a, b) = buf.split_at(mid); + Buf::chain(a, b) + } + + buf_tests!(make_input); +} + +mod chain_limited_slices { + fn make_input(buf: &'static [u8]) -> impl Buf { + let buf3 = &buf[cmp::min(buf.len(), 3)..]; + let a = Buf::take(buf3, 0); + let b = Buf::take(buf, 3); + let c = Buf::take(buf3, usize::MAX); + let d = buf; + Buf::take(Buf::chain(Buf::chain(a, b), Buf::chain(c, d)), buf.len()) + } + + buf_tests!(make_input, true); } #[allow(unused_allocation)] // This is intentional. @@ -115,20 +437,3 @@ assert_eq!((Box::new(Special) as Box).get_u8(), b'x'); assert_eq!(Box::new(Special).get_u8(), b'x'); } - -#[test] -fn copy_to_bytes_less() { - let mut buf = &b"hello world"[..]; - - let bytes = buf.copy_to_bytes(5); - assert_eq!(bytes, &b"hello"[..]); - assert_eq!(buf, &b" world"[..]) -} - -#[test] -#[should_panic] -fn copy_to_bytes_overflow() { - let mut buf = &b"hello world"[..]; - - let _bytes = buf.copy_to_bytes(12); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_buf_mut.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf_mut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_buf_mut.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_buf_mut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,7 +4,6 @@ use bytes::{BufMut, BytesMut}; use core::fmt::Write; use core::mem::MaybeUninit; -use core::usize; #[test] fn test_vec_as_mut_buf() { @@ -274,3 +273,12 @@ let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; slice.copy_from_slice(b"abcd"); } + +/// Test if with zero capacity BytesMut does not infinitely recurse in put from Buf +#[test] +fn test_bytes_mut_reuse() { + let mut buf = BytesMut::new(); + buf.put(&[] as &[u8]); + let mut buf = BytesMut::new(); + buf.put(&[1u8, 2, 3] as &[u8]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_bytes.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,7 +5,6 @@ use std::sync::Arc; use std::panic::{self, AssertUnwindSafe}; -use std::usize; const LONG: &[u8] = b"mary had a little lamb, little lamb, little lamb"; const SHORT: &[u8] = b"hello world"; @@ -82,7 +81,6 @@ #[test] fn fmt_write() { use std::fmt::Write; - use std::iter::FromIterator; let s = String::from_iter((0..10).map(|_| "abcdefg")); let mut a = BytesMut::with_capacity(64); @@ -158,6 +156,13 @@ } #[test] +#[should_panic] +fn slice_start_greater_than_end() { + let a = Bytes::from(&b"hello world"[..]); + a.slice(5..3); +} + +#[test] fn split_off() { let mut hello = Bytes::from(&b"helloworld"[..]); let world = hello.split_off(5); @@ -180,6 +185,13 @@ } #[test] +#[should_panic = "split_off out of bounds"] +fn bytes_mut_split_off_oob() { + let mut hello = BytesMut::from(&b"helloworld"[..]); + let _ = hello.split_off(44); +} + +#[test] fn split_off_uninitialized() { let mut bytes = BytesMut::with_capacity(1024); let other = bytes.split_off(128); @@ -291,6 +303,7 @@ } #[test] +#[cfg_attr(not(panic = "unwind"), ignore)] fn split_off_to_at_gt_len() { fn make_bytes() -> Bytes { let mut bytes = BytesMut::with_capacity(100); @@ -724,9 +737,19 @@ } #[test] +#[should_panic] +fn mut_advance_past_len() { + let mut a = BytesMut::from("hello world"); + unsafe { + a.advance_mut(20); + } +} + +#[test] // Only run these tests on little endian systems. CI uses qemu for testing // big endian... and qemu doesn't really support threading all that well. #[cfg(any(miri, target_endian = "little"))] +#[cfg(not(target_family = "wasm"))] // wasm without experimental threads proposal doesn't support threads fn stress() { // Tests promoting a buffer from a vec -> shared in a concurrent situation use std::sync::{Arc, Barrier}; @@ -1404,6 +1427,26 @@ } #[test] +fn slice_empty_addr() { + let buf = Bytes::from(vec![0; 1024]); + + let ptr_start = buf.as_ptr(); + let ptr_end = ptr_start.wrapping_add(1024); + + let empty_end = buf.slice(1024..); + assert_eq!(empty_end.len(), 0); + assert_eq!(empty_end.as_ptr(), ptr_end); + + let empty_start = buf.slice(..0); + assert_eq!(empty_start.len(), 0); + assert_eq!(empty_start.as_ptr(), ptr_start); + + // Is miri happy about the provenance? + let _ = &empty_end[..]; + let _ = &empty_start[..]; +} + +#[test] fn split_off_empty_addr() { let mut buf = Bytes::from(vec![0; 1024]); @@ -1618,6 +1661,20 @@ } #[test] +fn owned_into_vec() { + let drop_counter = SharedAtomicCounter::new(); + let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let owner = OwnedTester::new(buf, drop_counter.clone()); + let b1 = Bytes::from_owner(owner); + + let v1: Vec = b1.into(); + assert_eq!(&v1[..], &buf[..]); + // into() vec will copy out of the owner and drop it + assert_eq!(drop_counter.get(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore)] fn owned_safe_drop_on_as_ref_panic() { let buf: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let drop_counter = SharedAtomicCounter::new(); @@ -1631,3 +1688,35 @@ assert!(result.is_err()); assert_eq!(drop_counter.get(), 1); } + +/// Test `BytesMut::put` reuses allocation of `Bytes`. +#[test] +fn bytes_mut_put_bytes_specialization() { + let mut vec = Vec::with_capacity(1234); + vec.push(10); + let capacity = vec.capacity(); + assert!(capacity >= 1234); + + // Make `Bytes` backed by `Vec`. + let bytes = Bytes::from(vec); + let mut bytes_mut = BytesMut::new(); + bytes_mut.put(bytes); + + // Check contents is correct. + assert_eq!(&[10], bytes_mut.as_ref()); + // If allocation is reused, capacity should be equal to original vec capacity. + assert_eq!(bytes_mut.capacity(), capacity); +} + +#[test] +#[should_panic] +fn bytes_mut_reserve_overflow() { + let mut a = BytesMut::from(&b"hello world"[..]); + let mut b = a.split_off(5); + // Ensure b becomes the unique owner of the backing storage + drop(a); + // Trigger overflow in new_cap + offset inside reserve + b.reserve(usize::MAX - 6); + // This call relies on the corrupted cap and may cause UB & HBO + b.put_u8(b'h'); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_bytes_vec_alloc.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes_vec_alloc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_bytes_vec_alloc.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_bytes_vec_alloc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +#![cfg(not(miri))] use std::alloc::{GlobalAlloc, Layout, System}; use std::ptr::null_mut; use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; @@ -7,7 +8,7 @@ #[global_allocator] static LEDGER: Ledger = Ledger::new(); -const LEDGER_LENGTH: usize = 2048; +const LEDGER_LENGTH: usize = 1024 * 1024; struct Ledger { alloc_table: [(AtomicPtr, AtomicUsize); LEDGER_LENGTH], @@ -31,9 +32,11 @@ .is_ok() { entry_size.store(size, Ordering::SeqCst); - break; + return; } } + + panic!("Ledger ran out of space."); } fn remove(&self, ptr: *mut u8) -> usize { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_chain.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_chain.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_chain.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_chain.rs 2006-07-24 01:21:28.000000000 +0000 @@ -135,7 +135,7 @@ #[test] fn chain_growing_buffer() { - let mut buff = [' ' as u8; 10]; + let mut buff = [b' '; 10]; let mut vec = b"wassup".to_vec(); let mut chained = (&mut buff[..]).chain_mut(&mut vec).chain_mut(Vec::new()); // Required for potential overflow because remaining_mut for Vec is isize::MAX - vec.len(), but for chain_mut is usize::MAX diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_limit.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_limit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_limit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_limit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +#![warn(rust_2018_idioms)] + +use bytes::{buf::Limit, BufMut}; + +#[test] +fn long_limit() { + let buf = &mut [0u8; 10]; + let limit = buf.limit(100); + assert_eq!(10, limit.remaining_mut()); + assert_eq!(&[0u8; 10], &limit.get_ref()[..]); +} + +#[test] +fn limit_get_mut() { + let buf = &mut [0u8; 128]; + let mut limit = buf.limit(10); + assert_eq!(10, limit.remaining_mut()); + assert_eq!(&mut [0u8; 128], &limit.get_mut()[..]); +} + +#[test] +fn limit_set_limit() { + let buf = &mut [0u8; 128]; + let mut limit = buf.limit(10); + assert_eq!(10, Limit::limit(&limit)); + limit.set_limit(5); + assert_eq!(5, Limit::limit(&limit)); +} + +#[test] +fn limit_chunk_mut() { + let buf = &mut [0u8; 20]; + let mut limit = buf.limit(10); + assert_eq!(10, limit.chunk_mut().len()); + + let buf = &mut [0u8; 10]; + let mut limit = buf.limit(20); + assert_eq!(10, limit.chunk_mut().len()); +} + +#[test] +#[should_panic = "advance out of bounds"] +fn limit_advance_mut_panic_1() { + let buf = &mut [0u8; 10]; + let mut limit = buf.limit(100); + unsafe { + limit.advance_mut(50); + } +} + +#[test] +#[should_panic = "cnt <= self.limit"] +fn limit_advance_mut_panic_2() { + let buf = &mut [0u8; 100]; + let mut limit = buf.limit(10); + unsafe { + limit.advance_mut(50); + } +} + +#[test] +fn limit_advance_mut() { + let buf = &mut [0u8; 100]; + let mut limit = buf.limit(10); + unsafe { + limit.advance_mut(5); + } + assert_eq!(5, limit.remaining_mut()); + assert_eq!(5, limit.chunk_mut().len()); +} + +#[test] +fn limit_into_inner() { + let buf_arr = *b"hello world"; + let buf: &mut [u8] = &mut buf_arr.clone(); + let mut limit = buf.limit(4); + let mut dst = vec![]; + + unsafe { + limit.advance_mut(2); + } + + let buf = limit.into_inner(); + dst.put(&buf[..]); + assert_eq!(*dst, b"llo world"[..]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_reader.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_reader.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -27,3 +27,12 @@ reader.read_line(&mut line).unwrap(); assert_eq!("world", &line); } + +#[test] +fn get_mut() { + let buf = &b"hello world"[..]; + let mut reader = buf.reader(); + let buf_mut = reader.get_mut(); + assert_eq!(11, buf_mut.remaining()); + assert_eq!(b"hello world", buf_mut); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_take.rs clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_take.rs --- clamav-1.4.3+dfsg/.cargo/vendor/bytes/tests/test_take.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bytes/tests/test_take.rs 2006-07-24 01:21:28.000000000 +0000 @@ -30,3 +30,55 @@ let abcd = Bytes::copy_from_slice(b"abcd"); abcd.take(2).copy_to_bytes(3); } + +#[cfg(feature = "std")] +#[test] +fn take_chunks_vectored() { + fn chain() -> impl Buf { + Bytes::from([1, 2, 3].to_vec()).chain(Bytes::from([4, 5, 6].to_vec())) + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(0); + assert_eq!(take.chunks_vectored(&mut dst), 0); + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(1); + assert_eq!(take.chunks_vectored(&mut dst), 1); + assert_eq!(&*dst[0], &[1]); + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(3); + assert_eq!(take.chunks_vectored(&mut dst), 1); + assert_eq!(&*dst[0], &[1, 2, 3]); + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(4); + assert_eq!(take.chunks_vectored(&mut dst), 2); + assert_eq!(&*dst[0], &[1, 2, 3]); + assert_eq!(&*dst[1], &[4]); + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(6); + assert_eq!(take.chunks_vectored(&mut dst), 2); + assert_eq!(&*dst[0], &[1, 2, 3]); + assert_eq!(&*dst[1], &[4, 5, 6]); + } + + { + let mut dst = [std::io::IoSlice::new(&[]); 2]; + let take = chain().take(7); + assert_eq!(take.chunks_vectored(&mut dst), 2); + assert_eq!(&*dst[0], &[1, 2, 3]); + assert_eq!(&*dst[1], &[4, 5, 6]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"d2a01821d2be5fe6a7a9857b4a764100043d6c15068176f7f0828067bba9644f","Cargo.toml":"8fdd1ba07d7f158008e96be6e415536522c901f0c7edddfa2c6b47ca3936b5f1","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"a45da9aad6e4c77faac5b8be230daf2e2cab653b66e95b0f21e353116fed2da9","README.md":"8af5e3ccbbf1c71cfabc0d66f47054401e12329d029ece8022fd8d4095c027d9","benches/decoder_reader.rs":"8ddf69eeb536edb35c0c75c258e25c2199e5995479555a3085469fd59f60a937","rustfmt.toml":"f6a927ac8e2b02f7b803d5b50b262b79c85071765a13fa824ec24415da5b984c","src/bitreader.rs":"f4ef954a7bab20fff7d6cc052befa15d49b3e2fbbb3fdcf830413b23fc891f9e","src/block/bwt.rs":"8925c622a817db4dab8766a16deccbff1ced8ecb75100cbcc232fa4f48f0d7d8","src/block/error.rs":"ba3d9d734193168c031b74149341764fa47ff7384842f41cf277cb17a0498b43","src/block/mod.rs":"74f4316752c066f3d8cb91a2b05cccc2ac2208073aba88fc93e08df4073dd194","src/crc.rs":"5c4131175ea1577debcf87dad78fcea0644c4e0f45d4c080aab3703d33946b4f","src/decoder/error.rs":"76d97c3946f787f4284d3ee6a1efe5b0156b4e7bb880f1e3b374f9b7b41e22a9","src/decoder/mod.rs":"e503fe4cedeec78583333b85c5b5ecc564258f7d753e3a174a778ca3447562c3","src/decoder/reader.rs":"d7bda72190fc3cc5e65e7d2c50d4de7dc84823fbdf66ba691f851c2beef6503f","src/header/error.rs":"bf4e10e2a510be54aaac74dbcaa885d4d2dc1f6c40de6da6bebc90f184bdd54b","src/header/mod.rs":"3fdd8e79714d103a4c5972133e27da44bf87809456ff31c17ec3d584ece83ebc","src/huffman.rs":"70eaf4c1294280bae889c7f0f2f514e1d41444a52132d7241558d47cb157342e","src/lib.rs":"d35f0f27eaad7d68afe1230911b97e095f1666fbca0b40c9bf6f46b8ff00b7b0","src/move_to_front.rs":"69e05eae97e9ce1074f2e9a59a0e174b9c08a7fa60f36cbb4d9006056a89717e","tests/decode_reader.rs":"94e17380a5c6005b4e08a9e52868d6ff15790e6849fa1b4edc74cb0317355a46","tests/samplefiles/sample1.bz2":"d4b442283e085497c528c0122c7ec64bf12aac422b3faff57b97de3378b7a7a4","tests/samplefiles/sample1.ref":"af423164ec87f495f7d450fee9bdd418c12114cd305de2384fd20b91ba7994c2","tests/samplefiles/sample2.bz2":"c74d44033766ea66171f51bd2ce6e3ad9ce4e0749e03ee4bee3074ab2a4b9c7f","tests/samplefiles/sample2.ref":"316ad6713f2c05413e0b9eac132840d092674e7de4138251d3552f98671fcf9a","tests/samplefiles/sample3.bz2":"fc60721da6329daa4bfe5ef3b32d2de0bebac626ce8522ae033dc3a9296c7779","tests/samplefiles/sample3.ref":"6be9c2bd214924b18db0d57b9a14d6f4eeb0b276cd3a980aed91521cca3199dd"},"package":"beeb59e7e4c811ab37cc73680c798c7a5da77fc9989c62b09138e31ee740f735"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"da50a80c5ab7059d3c36cb850a152e6313c9d6fa01018b53351f2af1cd33c405",".github/workflows/ci.yml":"4eaba2ee9cee0adc97b9fb5e17930e5abf4e6a9ce1943a67946cac97e6d29bea","CHANGELOG.md":"d2a01821d2be5fe6a7a9857b4a764100043d6c15068176f7f0828067bba9644f","Cargo.toml":"8fdd1ba07d7f158008e96be6e415536522c901f0c7edddfa2c6b47ca3936b5f1","Cargo.toml.orig":"6f0d29a121ed8e4d9367516d3ef202e9963f0bf95bb61a76a3bd118c6c01924a","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"a45da9aad6e4c77faac5b8be230daf2e2cab653b66e95b0f21e353116fed2da9","README.md":"8af5e3ccbbf1c71cfabc0d66f47054401e12329d029ece8022fd8d4095c027d9","benches/decoder_reader.rs":"8ddf69eeb536edb35c0c75c258e25c2199e5995479555a3085469fd59f60a937","rustfmt.toml":"f6a927ac8e2b02f7b803d5b50b262b79c85071765a13fa824ec24415da5b984c","src/bitreader.rs":"f4ef954a7bab20fff7d6cc052befa15d49b3e2fbbb3fdcf830413b23fc891f9e","src/block/bwt.rs":"8925c622a817db4dab8766a16deccbff1ced8ecb75100cbcc232fa4f48f0d7d8","src/block/error.rs":"ba3d9d734193168c031b74149341764fa47ff7384842f41cf277cb17a0498b43","src/block/mod.rs":"74f4316752c066f3d8cb91a2b05cccc2ac2208073aba88fc93e08df4073dd194","src/crc.rs":"5c4131175ea1577debcf87dad78fcea0644c4e0f45d4c080aab3703d33946b4f","src/decoder/error.rs":"76d97c3946f787f4284d3ee6a1efe5b0156b4e7bb880f1e3b374f9b7b41e22a9","src/decoder/mod.rs":"e503fe4cedeec78583333b85c5b5ecc564258f7d753e3a174a778ca3447562c3","src/decoder/reader.rs":"d7bda72190fc3cc5e65e7d2c50d4de7dc84823fbdf66ba691f851c2beef6503f","src/header/error.rs":"bf4e10e2a510be54aaac74dbcaa885d4d2dc1f6c40de6da6bebc90f184bdd54b","src/header/mod.rs":"3fdd8e79714d103a4c5972133e27da44bf87809456ff31c17ec3d584ece83ebc","src/huffman.rs":"70eaf4c1294280bae889c7f0f2f514e1d41444a52132d7241558d47cb157342e","src/lib.rs":"d35f0f27eaad7d68afe1230911b97e095f1666fbca0b40c9bf6f46b8ff00b7b0","src/move_to_front.rs":"69e05eae97e9ce1074f2e9a59a0e174b9c08a7fa60f36cbb4d9006056a89717e","tests/decode_reader.rs":"94e17380a5c6005b4e08a9e52868d6ff15790e6849fa1b4edc74cb0317355a46","tests/samplefiles/sample1.bz2":"d4b442283e085497c528c0122c7ec64bf12aac422b3faff57b97de3378b7a7a4","tests/samplefiles/sample1.ref":"af423164ec87f495f7d450fee9bdd418c12114cd305de2384fd20b91ba7994c2","tests/samplefiles/sample2.bz2":"c74d44033766ea66171f51bd2ce6e3ad9ce4e0749e03ee4bee3074ab2a4b9c7f","tests/samplefiles/sample2.ref":"316ad6713f2c05413e0b9eac132840d092674e7de4138251d3552f98671fcf9a","tests/samplefiles/sample3.bz2":"fc60721da6329daa4bfe5ef3b32d2de0bebac626ce8522ae033dc3a9296c7779","tests/samplefiles/sample3.ref":"6be9c2bd214924b18db0d57b9a14d6f4eeb0b276cd3a980aed91521cca3199dd"},"package":"beeb59e7e4c811ab37cc73680c798c7a5da77fc9989c62b09138e31ee740f735"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "359904e0132d10acfe0896b878efbf4b137a3e0a" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/.github/workflows/ci.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,96 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +env: + RUST_BACKTRACE: full + +jobs: + rustfmt: + name: rustfmt / linux / stable + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install rust + run: | + rustup default nightly-2021-02-16 + rustup component add rustfmt + + - name: cargo fmt -- --check + run: | + cargo fmt -- --check + + clippy: + name: clippy / linux / stable + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install rust + run: | + rustup update --no-self-update stable + rustup component add clippy + + - name: cargo clippy + run: | + cargo clippy --features rustc_1_40 --all-targets + + test: + name: test / ${{ matrix.name }} + runs-on: ubuntu-latest + + strategy: + matrix: + include: + - name: linux / stable + rust: stable + - name: linux / beta + rust: beta + - name: linux / nightly + rust: nightly + - name: linux / 1.37.0 + rust: 1.37.0 + - name: linux / 1.34.2 + rust: 1.34.2 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install rust + run: | + rustup default ${{ matrix.rust }} + rustup update --no-self-update ${{ matrix.rust }} + + - name: Remove unused dev-dependencies for benches + run: | + sed -i '/criterion/d' Cargo.toml + sed -i '/bzip2 =/d' Cargo.toml + + - name: Test + run: | + cargo test ${{ matrix.args }} + + - name: Test (with rustc 1.37 optimizations) + if: matrix.rust != '1.34.2' + run: | + cargo test --features rustc_1_37 + + - name: Test (with rustc 1.40 optimizations) + if: matrix.rust != '1.37.0' && matrix.rust != '1.34.2' + run: | + cargo test --features rustc_1_40 + + - name: Test (with rustc nightly optimizations) + if: matrix.rust == 'nightly' + run: | + cargo test --features nightly diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/bzip2-rs/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/bzip2-rs/Cargo.toml.orig 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,36 @@ +[package] +name = "bzip2-rs" +version = "0.1.2" +authors = ["Paolo Barbolini "] +description = "Pure Rust bzip2 decompressor" +license = "MIT/Apache-2.0" +categories = ["compression"] +keywords = ["bzip2"] +repository = "https://github.com/paolobarbolini/bzip2-rs" +readme = "README.md" +edition = "2018" + +[dependencies] +crc32fast = "1.2.1" +tinyvec = "1.1" + +[dev-dependencies] +pretty_assertions = "0.6" + +# bench +criterion = "0.3.4" +bzip2 = "0.4.1" + +[features] +default = [] +rustc_1_37 = [] +# soft deprecated: we don't need this tinyvec feature +rustc_1_40 = ["rustc_1_37", "tinyvec/rustc_1_40"] +# deprecated: the nightly_const_generics tinyvec feature also requires +# `array_map` to be stabilized. This should have been called nightly +rustc_1_51 = [] +nightly = ["rustc_1_40", "tinyvec/nightly_const_generics", "crc32fast/nightly"] + +[[bench]] +harness = false +name = "decoder_reader" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGES":"3cf7a0bffff309f8fa7f20aa4618f83a8c2b48c9202495169a13eab9e289d1bf","Cargo.lock":"ea22103f506e5cedde42425feed40fd6b7f71a327c93349894fdc4ab70acdf83","Cargo.toml":"25f65d822446d3827a7c53e250428f92af07faa66c8b185f1c72ade89e0aa1e3","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"eaedddd66de11155f17ca657825d92a0dc4243aebf98f846c15b31cd27b27b99","build.rs":"f0fa57ad2c0dca5855cc2636a2e95acbadb52fa887609216022bdf71ed996dec","contributing.md":"bfa8eb84ebea06077ba25e7157b10a6676c5da8ff850116f36205f9a004848b9","docs.md":"3bbbefd04f4b7b86d37cb4217c404f1df43957b275f34235adf4d42be74ce661","internals.md":"62721f9a63729769c947ddb8270df3445f148fcba545e1152bc4f545cc32398b","rust-toolchain.toml":"2ce1c1fe5e79a52424c9d88d99f5a2c95dcf5b4f4a82431bb9e5710cfb39e184","src/bindgen/bindings.rs":"817f045c8093c584f14143cbf00d5f8d3b1e5e638ecfefd0a67160d49b48b83a","src/bindgen/bitflags.rs":"7a2f75eff0f25da53e83f49d82744f6a7fa36f73d85dd9cdf883ba1c76346e8f","src/bindgen/builder.rs":"80a05adbbbc4d2be57098622361739c801db898b7e6a7f401952e669ee268807","src/bindgen/cargo/cargo.rs":"3483dd68c914cd529fca840a7a44a2bff446264b44428d1578ef3e54450500b0","src/bindgen/cargo/cargo_expand.rs":"20e8b924ecc4e7a74dcef963e3b2e6b644535aeb1d0ef848638aa6da786d6a39","src/bindgen/cargo/cargo_lock.rs":"0426ce5ed7ed2a4c76ea119f9f9bb841c9a55ceb3554e93c3e0909b68c04bb82","src/bindgen/cargo/cargo_metadata.rs":"dd8ed657bf9099685024f1ca0def236e61b00a4ef2dd646d5d4797a0597b439d","src/bindgen/cargo/cargo_toml.rs":"a28f4cc8b9c938ec7fe99b1f235795e191e0baa1961299cb6c1155c7bbdbdfa0","src/bindgen/cargo/mod.rs":"a938c1070207d9d13304b1fe2f19680d2a409337fad1fad3770c676a6cc74373","src/bindgen/cdecl.rs":"0c95ea2ce3db89c6f97c4d67aef3616becc8e8aceeefcfca2ea884014d1b358a","src/bindgen/config.rs":"d644b915168ab0681f14408d1bd9efa834f085110dfd04e7ce487cfe07da24f5","src/bindgen/declarationtyperesolver.rs":"a0b975320ab5c6f6c342ae32828309e131f1bf0f094ff0e533070123b06417cf","src/bindgen/dependencies.rs":"0916e1db9b2aab59ae60623bbf79d1eee1c59cac0711f03fc442ed893e60cc16","src/bindgen/error.rs":"0d5de9016166d8dce14ed8249990a280f709b28459c74cf3717ffd2399fc476c","src/bindgen/ir/annotation.rs":"a9286669bda682c05bcd2b3374c1bef48259db1df165b18ff2ad5c1ed64a166b","src/bindgen/ir/cfg.rs":"67c00ad73694ed3270adff19312174514247145ce4ab7929ddb8263ef4c451bb","src/bindgen/ir/constant.rs":"3fc8753c0b72fdff3468eb0af3f4911ec8c2fea63bb1d5028acdbc8dbcef91d1","src/bindgen/ir/documentation.rs":"49281cd443232483c524491bac2543f148b554a886ba7abcd29ef8a86c80aca3","src/bindgen/ir/enumeration.rs":"d702f37337ed21b01edcf38e0513489124517cd5c34a8aaf0ae947b6b0f86ae8","src/bindgen/ir/field.rs":"3f582301c827405415e84ef6c9f59ab3d7fdc61d81f4dce56fccb0b3c4f3667c","src/bindgen/ir/function.rs":"efc94223df2401a057329659e83e5535b26ec6f79e147083857dfd29a376bc27","src/bindgen/ir/generic_path.rs":"682c043bd5e76e073991609dd76d261100f37d12b3f1c8144a8d68766552921e","src/bindgen/ir/global.rs":"5ec1b6bcbc3c3fa54ce237b63069ad6bd4bd738c9fb5d8caf94eb69824602ca2","src/bindgen/ir/item.rs":"3da475bec94f09ab0d8e734bb88be311caeb7a0dbf13dce94f26f97028872c8f","src/bindgen/ir/mod.rs":"67ae2b67ef6fafee72f68f38bf874b05a6816d60d8c63211abf802414459be5b","src/bindgen/ir/opaque.rs":"1bcb7677ea08cedad17c75a5c65747c71641803cc378a71d734afd36eb428c9a","src/bindgen/ir/path.rs":"a107230f403b7c139ea722e8c20156d12c609e141a6f279e19d5c5a0280d08af","src/bindgen/ir/repr.rs":"347005917a75cb49fa8bbc22c2191a2291d79343d7f42940690907d3a4fb6a6c","src/bindgen/ir/structure.rs":"7fc949d434e5ef2f6848fd23ce4e73866570c3238fd6a87cb9128c7b21eed73c","src/bindgen/ir/ty.rs":"f447f37314d3a6fdd7888a159118d00f2ea338d3f4c9a851f144df0bd89b0bcf","src/bindgen/ir/typedef.rs":"aeb873bbbf5615557e23d43bdee306aaa2b3f7aa0f2a6cf44fc69c23211009c3","src/bindgen/ir/union.rs":"cb8137c8ead799e8276303c6cbae4877013ccff57db8c245e457b6bae522ce82","src/bindgen/library.rs":"5c4d6094b01f020e6e5594c0431e8b26bca1c492c3f888ad1261ade4c1b326e7","src/bindgen/mangle.rs":"95a8ef747e275c87001f07a95924d4f78b304b9a38b8302b52b90705a3845515","src/bindgen/mod.rs":"40c7ea333a83de98e420e39dc86d4067dccf82d5ac0ccbdad3da9a2ed63e3c3a","src/bindgen/monomorph.rs":"30126ba80ed9921e43e4929a1b79d5b4ef54b3d4ce0bb60dbcdce777d60b23e3","src/bindgen/parser.rs":"474f4e8f15c28cfc2cb941662cbb7d4304a406df24f87990b7f4fc16dcca7b4f","src/bindgen/rename.rs":"7d981a720fe54bab916ba8328ecfc129e5eabd90e4b9a806071912661fa40a4f","src/bindgen/reserved.rs":"7024f1cc80f787d768151bac15ed4e6f1b55fcb64c699e3a05b398ed9acbe4ea","src/bindgen/utilities.rs":"ed53d73b3b402347309f04e4f0a020e981924d1581e7594321f5382a9c0d6ee8","src/bindgen/writer.rs":"fb4a9a6f46506918a33fa149ab22b83b685af60a3a072db54659c46d831a5163","src/lib.rs":"0c313bbe7f3bef625b2d2b345ec188e16db34c4222fc3e230b12b5863838b4a4","src/logging.rs":"61a51d7c22d4c34c3ec058e15ea45b9c5519addcf3e6841a56cd56e599b5cf1b","src/main.rs":"1655d7bb6270f2c97e2da1856e4b0d078bec633a374f75e87924e3f7d1424b4c","template.toml":"f2cedfbe9823e5e303b6aec81e8078aaa95ee7fd04610d10c4156ee0e248cfbf","tests/depfile.rs":"beed7e1f4cbb7c451cd7bf1357914053d390cc884ac5a78beb8f2ba4d8f56c82","tests/depfile/Readme.md":"2b81cc10632a3a883ade804ac8a495ea915263b1c67705267746725b37dec07f","tests/depfile/cbindgen_test.cmake":"8d83fe959e3fdc3af2c60426348798c33fd9e4bdb1098826968c3686c7cca878","tests/expectations/alias.both.c":"612bfc7278636a7c9c94d64406b528b492ee83e49a82411ed0c30630f9f34029","tests/expectations/alias.both.compat.c":"5f22c9d89182bffcbfed3662d5fbff9877049b045dfb8e6b81e6f5c01f974980","tests/expectations/alias.c":"cf3c496e8e65c6ab14469a38420f9afd147160d432e6a2ed11c716c908b2cb5f","tests/expectations/alias.compat.c":"a56deac9f43efb1f68aed20f6b436687289f9037e2a21810669f640a7f8b6e12","tests/expectations/alias.cpp":"259c612fc5149b0e3ae7a353eff451413b54c4d912e69567d32849cd26697eb7","tests/expectations/alias.pyx":"f65869ad2181650669f3c8c3445e5bdf0de6313a5b53d8982fb9cdcf08e9f8f2","tests/expectations/alias.tag.c":"73136d2f5b0b948d12a87935ada9d64f2ba9f03f40f6daffd692a3062d93b6c4","tests/expectations/alias.tag.compat.c":"1291aa2a7a7e68f16c17cbf2e0dbdae5b09670d6f436841f2246c5f0c8bdf76f","tests/expectations/alias.tag.pyx":"6b648bd4bde9cefb8441bcb9f28b9769cb4a5299d8caac49180ffcc276ff5ec3","tests/expectations/annotation.both.c":"0a54b323f9c40a345f535d79c89d245259443d5afe72e16165e3996f33588b70","tests/expectations/annotation.both.compat.c":"c15c9aee10d474ac8f998c4e0914f6f0c13526b3aaf6837de16b2e193a336c0f","tests/expectations/annotation.c":"3edc90fd9773ff57b0a6a39edbc8eb5ed594a0b080d89ce1a20dcb7a5ebfcfcc","tests/expectations/annotation.compat.c":"1bbcfa9ccbe11adaaceb63e3118b2186931967361e25e5b5895ec71fe6634823","tests/expectations/annotation.cpp":"4781e0146707823823c39bb16f167cfba0e2120c6e76869a2e0f89cb1700ad66","tests/expectations/annotation.pyx":"0fad8e0ecd818515b2860c2a7aaba8e42010f7dbeaeec82a6766cbb1506fdadd","tests/expectations/annotation.tag.c":"55408b8b93b950b6e174abd940d011d2ed927ef8350b3dc456c48d0b7fdfce0d","tests/expectations/annotation.tag.compat.c":"3af0b1343b9148330f0226c6caec2961449df5702e66801853c6129d9cc5c7a1","tests/expectations/annotation.tag.pyx":"993e26032085458117e39de0e827c7c5015c9eebd0e6b2b6d076370000fd913e","tests/expectations/array.both.c":"51200233fe3a252492a9d96c069bbcbd3e89ed8a1b180d3d3b6d1af3f41126b1","tests/expectations/array.both.compat.c":"beedb600de83fe8688a10c1521ff7fdd61566114de723fb02f0a83f9aa0dab46","tests/expectations/array.c":"954225a346d838028d5b2d7c68f7b3c35f44d763341f3f425e04236426f9a209","tests/expectations/array.compat.c":"2c4940d3194c3813ac46d246d201d791dcec0865908e2921d77525a37610af75","tests/expectations/array.cpp":"37152d5dbf71e280afdbbcff347ee7e53cc1eb426f1f0dbf94520f72b1695b1e","tests/expectations/array.pyx":"68c523e03f09764d120f2044f1cfb35a48a52be49746153f8e819cff4fa74167","tests/expectations/array.tag.c":"957cdc7253d9524b5f1527e2d3b6120f706f9b390b6e6dc37f46d4e7ee766ac1","tests/expectations/array.tag.compat.c":"725bf3feca7a14fe77cfea5b18991179459ec4e2e57e7957a09eb93cf7ce15bf","tests/expectations/array.tag.pyx":"dbfcbdeb3e580a13e8c85235876b176ce9324599cc69f399cbca5f1090225c47","tests/expectations/asserted_cast.both.c":"e7be7cccbbc4c6bed203e16def79792ec212d28f93a6178fcca8bd5e5608aa93","tests/expectations/asserted_cast.both.compat.c":"9e49646e982dcd65464536634553c02a8c11a486198b346de14004d265fa55fa","tests/expectations/asserted_cast.c":"acf929fa2bc9be077666de04f4d10fc0d4224749a7a092021c5e8046711c71c7","tests/expectations/asserted_cast.compat.c":"4c2ec364d80064ae887913bb2bb27e47857ab8b332c3042a4d585737952af623","tests/expectations/asserted_cast.cpp":"b4df513687321770538b9da13674d7f9a6249bdf91ec61049d756d40c84d967d","tests/expectations/asserted_cast.pyx":"9f9a81a26b2c5351493b37b875a1d93376c90a87a682d03b015b264bf533f08c","tests/expectations/asserted_cast.tag.c":"15b0b83adea966408e574421171bbbbf9cf85b7605e3e0e240af41f2bfab2ca9","tests/expectations/asserted_cast.tag.compat.c":"7e8f488d0613133a3fbae959cfd7c1d3a018ab8d762923aa073dc21ff8ab7b74","tests/expectations/asserted_cast.tag.pyx":"4dd8b290c45b4fbb21c044ed29df04816273493af3777114d312d4183fcfc67f","tests/expectations/assoc_const_conflict.compat.c":"bb2c53ac57d1b53f5e2ec0c0140d3d309d9e92158953f46b04708f3d86d93b67","tests/expectations/assoc_const_conflict.cpp":"440c42309e090c11c54259d0b49cc02eba856d11bd22b61e5387514ce7e432a4","tests/expectations/assoc_const_conflict.pyx":"84d5b4e58002f6062acce657f6a065f6782f4cab35e12f537ce44e82c84333e7","tests/expectations/assoc_constant.both.c":"7331702e91f98099690443a149bda315eb2ff4e49371351593fdd559458e75f9","tests/expectations/assoc_constant.both.compat.c":"81ebecdf6d838244b3464a8d9c1b4ed6caeb7ab43c17170e5faff006d60e2fcc","tests/expectations/assoc_constant.c":"bc24ec8a76c6bbecdb42593051ec1c87286ed5afe6ae5207dd978191b506f8d6","tests/expectations/assoc_constant.compat.c":"d7c4e031ccdb61b2ff04c99a755ffdcb9fb090c7a976c1739596a30852f85340","tests/expectations/assoc_constant.cpp":"d9d1a1724c6967e9534601a966279cecd0358999db241e17db5221af7427578d","tests/expectations/assoc_constant.pyx":"8bd9db9c6bfa3e007105de578edfc2dc236f61d6c290cc460a447aad2f4454cc","tests/expectations/assoc_constant.tag.c":"7a2669d2332623ef8e9bd605203f09dabe905c568f5f0162153e2e77ec7ae6fd","tests/expectations/assoc_constant.tag.compat.c":"d71d82758c132208ba453e876cc6e2e7f5afb1b537fbe588dab6cdce62a8ac9c","tests/expectations/assoc_constant.tag.pyx":"641a6a40d67f91dd4ce9a6f14b6f39e925e343dd2e3b3c6dd15ffa7da457022e","tests/expectations/associated_constant_panic.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/associated_constant_panic.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/associated_constant_panic.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/associated_in_body.both.c":"64073eb290a508f2d90544c9ec4eef700cb81450940c84c428987193648be911","tests/expectations/associated_in_body.both.compat.c":"0ddc87d364827469f0e1508cd7b79641c4d9e4cec86505df7d2b0c6ae5ec0361","tests/expectations/associated_in_body.c":"61e8d63bce9dcf0266ccdaf7806a1d599a652488a402ea0b18cc2ecf39e1a179","tests/expectations/associated_in_body.compat.c":"b66dbaae1a4e36580ce0b6dba97cf9d9faf51b99c66fe80ab0183853ac682749","tests/expectations/associated_in_body.cpp":"1a9d135f8f0bcd5c891f9c1d62b16b79197fe347d712106b07748032544ab57e","tests/expectations/associated_in_body.pyx":"c7178a28201a6934f367d1906d7a49635a29824193b9e866c69464ce9a5a0daa","tests/expectations/associated_in_body.tag.c":"17c4c60744b692853f56e3e2907a9d64dc3cf1177f23aa867705c26f5c4f1548","tests/expectations/associated_in_body.tag.compat.c":"5b1064ec35ce9cb901f74244440624feb16c0dd5a019c61c7c27301d46fc0cce","tests/expectations/associated_in_body.tag.pyx":"cea0d58bef114ee79d82451e413c470b40b16500ebe44b8745dd8cf15d949c00","tests/expectations/bitfield.both.c":"684e0e0e909797238ad7e47b41dc3c9cc854c072724b9bcdc745bd2aa246c102","tests/expectations/bitfield.both.compat.c":"a4e4503e6e6a8ff59aacaeb641c37c78a692e1ace60fb8a2e069143211d5ce95","tests/expectations/bitfield.c":"45df0bd7774d3d63f745a34880e189c18a26a840ca4ec7f350777a07ccadb0fb","tests/expectations/bitfield.compat.c":"8e13a28fcce8570a47179dea123be18174af1a7ad73743a238bcb7997e3caf03","tests/expectations/bitfield.cpp":"29496ff002d05ead46c3138bff1de7d0ef6ae3fb1861d78699659a00227b2b2b","tests/expectations/bitfield.pyx":"b3209227b52c338dc12d5e1c9f4915be54fbabb8f04bc3d7eeed359faf298654","tests/expectations/bitfield.tag.c":"570212e779377fdc803539aeeca8a3ccb639c53341cdf044684e374bac4d1e9c","tests/expectations/bitfield.tag.compat.c":"1c40246f2a4e43be091ae835e02a72421d74e1f4f2d13ca7a18e051ef61c08e7","tests/expectations/bitfield.tag.pyx":"89580c6294bf5aa09afa748b708d2c221b0473fc4431f5fdbc6565bca086ceb5","tests/expectations/bitflags.both.c":"e2109e0ab8f9384ce0b3bd9e631f8354fd4a39a649f65ba2af08ba04da6ec0b5","tests/expectations/bitflags.both.compat.c":"c04a4f3ac1b8c62ce55d24a768829e505814c9891feda19cb7055d2f7f40fc38","tests/expectations/bitflags.c":"5d60a7fbfc6c2040cbfc7f07c0af7d30f57bfe400d09f7ed79658fbb19da6e0a","tests/expectations/bitflags.compat.c":"8ca16f80c7e4c4a57313c0797436f0bd98a8f6a2d2bb06ba108dda36e17f61dd","tests/expectations/bitflags.cpp":"583ed57057def6bda93a2ed561e42b5dfdd5625d22601864b8840ad351f2dc7d","tests/expectations/bitflags.pyx":"c6ac88988cdf42f94b5859911600b16812b1222500ea104a8bbe0a5bd1c659a8","tests/expectations/bitflags.tag.c":"13ae1d889b9082b5addedb079e9cd198dbe35cac614a1e42c326fdb57ed08bf0","tests/expectations/bitflags.tag.compat.c":"207d34358a4a978824f9dc663c5a2b3fd5a056280d8b0dc378bb0d4cbb1efac4","tests/expectations/bitflags.tag.pyx":"2bff6611e1abd58056d2582246877bea38479c648367a9a2e5e14f9573dff5aa","tests/expectations/body.both.c":"b5b4b17c7545bb60b6b113750b6211ea012fbaf323a9f7c0a6f22bd502b10eba","tests/expectations/body.both.compat.c":"ab2ae390bff1c669024c0f57dafb6c39223124eb7fee5f774a26a24b7b745643","tests/expectations/body.c":"83e6548451a14b54b482fcf15765097c5fe67296f211ff0d13487b440fa3f205","tests/expectations/body.compat.c":"4b231ba3e4a9a5d5d15c905dbf7825af4afd00f1f418154d76aef0c8e820625d","tests/expectations/body.cpp":"8f033a0b3afaae1d37745734718539549951e9c60d66a12fbb09e974a09c2704","tests/expectations/body.pyx":"f80e234950b3f1fb08a22b49541f483b855e1fcaec5b826249aab46c22a0945b","tests/expectations/body.tag.c":"c93242bff38924582159b58214ab5aac7b24345139081037cc437fb8a58002a9","tests/expectations/body.tag.compat.c":"b6f862490b2d3d030eb6cb8246e44bae069010a7df448ff3978a75de1c726d37","tests/expectations/body.tag.pyx":"ab304c830a1938e7ae60af8e9f728ee6ba6be38877bee4061bfaff27fab45de3","tests/expectations/box.both.c":"033db62bcb5592eeef95df3ca03d02918716a13fc4799d5e1ab20b42174323b3","tests/expectations/box.both.compat.c":"0d8ba9b1d689008368bb237771f994254c59d4abccb4606fe92dba4ce398abda","tests/expectations/box.c":"59a66035f60097cb270b6a46726b16f6930b57735723f7741c47695405e1c5f1","tests/expectations/box.compat.c":"3bc047168d70c56805845c3453d1f5fc608dc8f220e18e1ac433fe7a764f3989","tests/expectations/box.cpp":"5ac330bbf91df9cf320d6e95a9cf7d156e1c2e8dbd9580b8d1d86e2b96825836","tests/expectations/box.pyx":"d64f95840104d9b0b4eeeae748201d223f0b27abdc1864f57e149909ce8b2d54","tests/expectations/box.tag.c":"b1f5a20002ba352099ed429040529ad5a2bc96ded7d6cd75785cf9aaf44fe309","tests/expectations/box.tag.compat.c":"aeeca7f7466eca2360bc8b34aa7b8f932f3763761943ffb910eb7114bcbefe71","tests/expectations/box.tag.pyx":"4407c8277cea35090db1a46485892fd286f408b89255bbda28c7bc5a4c6397f9","tests/expectations/cdecl.c":"e49da32919797ea6d6ce3f4fd7a967ad33ef1dfa3f323f15181cca5f9a1fc98e","tests/expectations/cdecl.compat.c":"80ca597ab6be6a89310ed2120e62192b6c957cce02770218e11eebfdaa730282","tests/expectations/cdecl.cpp":"3242efce31ba876da3554e8ecaf3f7e89fae84537452d778d65dc1b1e4f31620","tests/expectations/cdecl.pyx":"91dc1444087738b3d108c19378391b92eea1660810829f3f3e02544c12e3a7c0","tests/expectations/cell.both.c":"40742fe09737aee76007e9fa879b9ac9c913f634cd1736e64adc1e246d3caa77","tests/expectations/cell.both.compat.c":"7fe548aa4cc0b4a05c2c482e70e11680a70ad55cb4e850ea3253e4194582e66a","tests/expectations/cell.c":"4018a58ca84d08753a690c93da2f520de98764b738ee30cc6fd06c890fafab2a","tests/expectations/cell.compat.c":"f2e80372856f6589327e56d3173ded3c8fc69ce714ae773865d96c04310c7632","tests/expectations/cell.cpp":"fcfe5b2f9d546cfaa5654135b1b8c0202ea23070d758a0ab7c74c4cf84df59d2","tests/expectations/cell.pyx":"2e359ca33d41e2e4c8586070c8484d20c07f5899e7a644df11d7bbf6149a6bef","tests/expectations/cell.tag.c":"87d4eb265f6c2313033cba74aa83c63010e0ef5f0d7de4cbfeab42429c379449","tests/expectations/cell.tag.compat.c":"77eecb7243f1dae0261e8c2fd2ba988eac4c0f455bff18ed7dcccc643205e838","tests/expectations/cell.tag.pyx":"6350674fd920f0b2e2eeaa5d4acc031a3945132f06fbb9e58ae5fbc85e03cd3e","tests/expectations/cfg.both.c":"7aeb06484d7d48fcb804f0c2490363271c68c46f88021a80f6b4915d03d59652","tests/expectations/cfg.both.compat.c":"af8d86fd3169f728e278e36639dd5a63ae574a0fcef074f1c21d2ecc35567697","tests/expectations/cfg.c":"9c6e2458b9b3e3c850dbb5c91598d0e9e6ecaeec776dedb3c308e2b922da09f4","tests/expectations/cfg.compat.c":"0980c724257983a39b37d4b8a4860cfef8619db7efbd06868f732f25ab7c157d","tests/expectations/cfg.cpp":"06fc52674e19706211b1f8386e1763d9a1f20d2f72453eafb9eaad3c85279a69","tests/expectations/cfg.pyx":"9abda332fb51d0f2e38f6e08d79e9f6dd28468d2415af1c90ebede91ca04c16f","tests/expectations/cfg.tag.c":"ad78b20b4f24ad6bbb1a7872c7ee4f0442407ed67fba3a69f24caaa807eb291c","tests/expectations/cfg.tag.compat.c":"f5fb90cf6ac7823e7c558bbb45e8e0626c6f26bb4ae2305fb8aee45c26534ccb","tests/expectations/cfg.tag.pyx":"132b50acb9af10a52f21d3623a1368bd2e8e3462843969bd1cec90aaf7ec0033","tests/expectations/cfg_2.both.c":"b93e3faf89cef94e5190bffe0535cdbdd39ecc1848ad5ed21b12a1d602e8980b","tests/expectations/cfg_2.both.compat.c":"1a22e353b9cad1331c2a34eac2f6c3c8aafb850242f6b1a8989690d9f4d6827e","tests/expectations/cfg_2.c":"50ed9a839309444b5b7569e7a5e3a29fa331ab2b11c5cc1169a174b1ed787dfb","tests/expectations/cfg_2.compat.c":"102606e339afdfe5aba1712c5af7a343b39b97b118e6b5013aeca0fffc2bbd8b","tests/expectations/cfg_2.cpp":"06523409a17cfdf1f55562859d3ca2b5afa6775370246d6b1f34d52ca21b9c0f","tests/expectations/cfg_2.pyx":"64cafab8f478bec98d24f61262cfa9fcf7350fee9ef02e36541d72906fe256cf","tests/expectations/cfg_2.tag.c":"a2199043d58396b92007347dcf8e228ff2ddbf66360349300264305cfb2c324c","tests/expectations/cfg_2.tag.compat.c":"2475f0db5d5fd92306596f95b67ce0b35dcd8b0811f92d06c6a043cff6bf3b51","tests/expectations/cfg_2.tag.pyx":"46d11bbad61c3776d5a5691f8a792314759dc5193291c339c92f9774432a031f","tests/expectations/cfg_field.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/cfg_field.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/cfg_field.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/char.both.c":"3a120740886f111014128581320eaadc537b30717b946cb110004a7fd1c56b35","tests/expectations/char.both.compat.c":"96c4dd607cd73faee95d956ac87922c3ac809fd9d68ced25f6da91b761638af2","tests/expectations/char.c":"2365acd2244ddc250304b59a830ea27ca485f834628de95d419de0a91efc2965","tests/expectations/char.compat.c":"13a7c3b21783a5b815af46548021c9c93a74e476b8060aa4e8357bcb7f221936","tests/expectations/char.cpp":"7612cd7d981224c74d0829253a2da2dab788a02773be4c0b2634505c0f59b0db","tests/expectations/char.pyx":"9521eb16f9d0491dd39ccc10b6ef3ea9a582e0903482f692cd2dbd19603fefde","tests/expectations/char.tag.c":"8aeeab4c3c0b28c9cbc6177a20bd5d85e98454b5c871885efb8b1d9da9a79aa2","tests/expectations/char.tag.compat.c":"f7fc5f73c50ae5f2f4348f4c8cda4fca318891339254f37a6a58762a94c1bba9","tests/expectations/char.tag.pyx":"565200395f89d5d2572815bd38dfdc4d5f6787bd0ef23aa293a7451ccb5b5755","tests/expectations/const_conflict.compat.c":"bb2c53ac57d1b53f5e2ec0c0140d3d309d9e92158953f46b04708f3d86d93b67","tests/expectations/const_conflict.cpp":"440c42309e090c11c54259d0b49cc02eba856d11bd22b61e5387514ce7e432a4","tests/expectations/const_conflict.pyx":"84d5b4e58002f6062acce657f6a065f6782f4cab35e12f537ce44e82c84333e7","tests/expectations/const_generics.both.c":"0b8df13162108de95889c5cb93e8d6e41e8e93728c0780fafdd143d815e64c91","tests/expectations/const_generics.both.compat.c":"2cb5e46155fe47fb1031627006e6d76ffea0e290afe295ed6cf1c3008a33243b","tests/expectations/const_generics.c":"1716cd634d1a7492324ff4f9b250e27d50976121a10c680e4686f8190e5d49ed","tests/expectations/const_generics.compat.c":"c33873b08bd0bbf583771e54919e1d4409bb9b44b367bfc38e45321deefed44d","tests/expectations/const_generics.cpp":"0ea0b84bbf5972698d7f84d06425c47bf61182207dead1a41c3b37541fdcebef","tests/expectations/const_generics.pyx":"17a3b2d36f061392e3f31d4a59d99ffb65b92f21c2806aecb44be7fd9dbd6e80","tests/expectations/const_generics.tag.c":"5cb1b9e1ee1a1271b3e5ce8e5083cc4b2374a2623d119540e015f23bbcde9fc1","tests/expectations/const_generics.tag.compat.c":"11518acb3877ff50d341abee03c3cc6da81f2c0322415c5132de2a24a420ec46","tests/expectations/const_generics.tag.pyx":"8fc7eff13aeb16ab2ce169bd142acd64e5b72b7ca08d2815efbce992bc869db9","tests/expectations/const_generics_arrayvec.both.c":"26ae374121029c59e6972cacec466435bccd7c5c1e5643704982d9f3bd82a156","tests/expectations/const_generics_arrayvec.both.compat.c":"6b429649f99d07ef4de05fcab298c4a77eab14c83b47da9f54126a2fd915d4f3","tests/expectations/const_generics_arrayvec.c":"389b0e3f3558d8d2f3553c604fe389490c48bf4c9f4583c09960c49c1860c3bd","tests/expectations/const_generics_arrayvec.compat.c":"895ff714acab3b8a26e89714e9016e6bd24c9fc1deed13c4963f6495e3521f2a","tests/expectations/const_generics_arrayvec.cpp":"70ccc080eec6b913bfe4901e40bb15e9fb27569b9f909a5faba734e50b01dd2c","tests/expectations/const_generics_arrayvec.pyx":"0abcf0f834698bdb5ed68ce77fbc24a53d371be4b4bdc73afebd321a00ffd6c5","tests/expectations/const_generics_arrayvec.tag.c":"afadc3c9ac58cb8864e9fb4e3f93294d5af68e76866c5ee5a0b5bd09dd841349","tests/expectations/const_generics_arrayvec.tag.compat.c":"cace3169b7bdbbfbd07a7c176de4b853aafb30c70a2f9de545a04d7016c042fa","tests/expectations/const_generics_arrayvec.tag.pyx":"80c0cbb038d5a59378c0a2095d15d60e98fb69d25befb36a11e6c8a0734be87f","tests/expectations/const_generics_bool.both.c":"cffc68aaab6384e661e2918bad8afe80a98e64b323a00b58d7a60c4e7e373806","tests/expectations/const_generics_bool.both.compat.c":"8a9a5ca67d85cc18a2ff5747bab3fc27af3d45ed0b15876129119290f84a776e","tests/expectations/const_generics_bool.c":"576fddca98f1366e0e7ad9904265ddf1df8774c091f9bbba52d98de7584b4107","tests/expectations/const_generics_bool.compat.c":"2a795fd4d18c0a14747d1079bb7b6268cf238b7195ef15600506edd3fa423111","tests/expectations/const_generics_bool.cpp":"b515522d50277cd573377871c34bbe90cbbc50a0405944cc724367488eea4c45","tests/expectations/const_generics_bool.pyx":"f86e3582bae096db1a42a4832dca53bbd32a19c35f70380aa5bf51f28da39b73","tests/expectations/const_generics_bool.tag.c":"d468a61f92045aeecfb8e1a4d2afe306069b86b24e2d86056a49546aaeff901d","tests/expectations/const_generics_bool.tag.compat.c":"28f5a25f5a56809d221fa3e94b919084617a0daca18244f766428cc6ad29e7f6","tests/expectations/const_generics_bool.tag.pyx":"987a33d986b409befe581784bc8a2d2f616245291e05e72f3adc37d29cfbca36","tests/expectations/const_generics_byte.both.c":"3dfe00700ca408e4f1baa7053620511b49d0cb73dc01b1451f42cb1acd782cd5","tests/expectations/const_generics_byte.both.compat.c":"761848e8c69f54869dd8fc49bfb464fd9d14be937e71f92cd2c7752a37e8acb7","tests/expectations/const_generics_byte.c":"b510fbc557762a6ae270293c4905df86b9c6930d8ec09b18e95fd712dcf95cfe","tests/expectations/const_generics_byte.compat.c":"363cb9bec3f998cdafd8124e26bc19e4e62c87e3ab20c7f1f34a19b0f5fad9c5","tests/expectations/const_generics_byte.cpp":"47f6a05dad514ccb2848bfb125b49567ffe29d971a1f03582d50d89d5ad14050","tests/expectations/const_generics_byte.pyx":"f3fa4be5d6756bc54af31b8029c86ed3372204f3569d95bdc8a5dbebc171a851","tests/expectations/const_generics_byte.tag.c":"6d593dbf6d779c6de9d888ae3e26c088e3c3fc4cf48ca5956ed7f42044b07b0d","tests/expectations/const_generics_byte.tag.compat.c":"f984b7735576a6feb1a5b7b52f6b7d7672375d2f87386bbfe596210fcd26642e","tests/expectations/const_generics_byte.tag.pyx":"477173eed61ffd33731a13c553ef48468172e9f814dc3839513222c9b7f3ed21","tests/expectations/const_generics_char.both.c":"7c2289524849937ccf1250e8846d9625eb5e1be4d72749fb2e924855985d1327","tests/expectations/const_generics_char.both.compat.c":"ad0602c33225385d0f644d0e3de9466ff0f023de644e3a9e24108a45405e254b","tests/expectations/const_generics_char.c":"7b272f23ef1845e2a9804c979fd6d223a026a78645704ffe9dcacf0794c83f2e","tests/expectations/const_generics_char.compat.c":"016055fc5fedfd638340bf902dceccd4f477dcc1297476528d4dce909a791cb0","tests/expectations/const_generics_char.cpp":"830d9d84ad904715cb708ed482e5973beeaba18d68e8bd69a3bce231ab385e74","tests/expectations/const_generics_char.pyx":"085bd0e5835ad6745ec592f0084a984899d9bc1539af8d9a99256e6146ded5c1","tests/expectations/const_generics_char.tag.c":"224d76c50dc8b0a667cfafe9f3594e6492ab010729bca4d02db2f5f7a9e01f76","tests/expectations/const_generics_char.tag.compat.c":"2c9bdd92f8988203e26d41fc7855d08dec0b01c517565b27a1a7aebd3012575d","tests/expectations/const_generics_char.tag.pyx":"ca3981c77afe488d789f51d9d35a548143bc2284a18b08545374bbcfc4e65b54","tests/expectations/const_generics_constant.both.c":"f5f0f2c5f31bc0f6b1ecbe8d36c0dd20680122a52ed88c8a4f40bfedc0dbb2fd","tests/expectations/const_generics_constant.both.compat.c":"2ad6d03c4ce769af51875e51d413cbb5c6107a036ce386c6a51e1ec18f6f218e","tests/expectations/const_generics_constant.c":"187e99eebe98218cf6398e27ad6dc9aa0cdfeb664f123454905ff9d015b95cbe","tests/expectations/const_generics_constant.compat.c":"b14b2167e6c5e067065b1da0079e4e0caec000626da0926a0cea9f083e12556d","tests/expectations/const_generics_constant.cpp":"5d38b085ce11c7354eafc6b3aec72affd1e8093b2ae7e8edf2c13a31a61b714a","tests/expectations/const_generics_constant.pyx":"a098babec8b10c4cae3f8c97e2ec625ebf7dc14561b1251dc92c69c42c87edf0","tests/expectations/const_generics_constant.tag.c":"31c0e515df992991f74633675694b92aa420f30a05f482746010bd4cc1c79087","tests/expectations/const_generics_constant.tag.compat.c":"6aba92e6e60cc1146b869747bf9aba4a0a19f20f43118d8d4ce5d92e643db326","tests/expectations/const_generics_constant.tag.pyx":"e5ce1ddfdff4e6776879aa1f8d606f6e2c9a469465dc56d250a434e9ddda73ed","tests/expectations/const_generics_thru.both.c":"9199534a9b676c45bf00da22c8065d4c95771cd4d36bc64ef8fb3b16251648f9","tests/expectations/const_generics_thru.both.compat.c":"05afaea3eacf926f12f5ef0ac8f1effc759b1dea9f3016f59d7298748ad337d2","tests/expectations/const_generics_thru.c":"a18b0349afb33d020f12ea22a1b22d4175ef3115ef3dc9a4d8a43919130e9ec8","tests/expectations/const_generics_thru.compat.c":"b67ba7cd9330b9040d9dd129d829f39a9c42d9b7c8b234f570c2b2b62c833aca","tests/expectations/const_generics_thru.cpp":"fcfdc43f14bcff84e2fce8c6d4477636268be21a1e013d3164cc7aba29ea3f3f","tests/expectations/const_generics_thru.pyx":"59171efe6927fe45ee5ad4fc2fc437e6f80438dcc97dc192f0510c3f2fd891db","tests/expectations/const_generics_thru.tag.c":"1535d2d6d01dfa94ab4baf35be71540cc6319b6eb03074ec414b186443972015","tests/expectations/const_generics_thru.tag.compat.c":"450bc656d7d5ddef25b85203cd0cfcb80aee20e30df7eb552c4ca8ed4c312bc2","tests/expectations/const_generics_thru.tag.pyx":"fe4d631f466bf0fefbb77f50d2c18d73271b1cb20c4b711ea880900683106c2a","tests/expectations/const_transparent.compat.c":"a722d38646474b075c37c7b34d2a1dc824df82e804e4e41957cd1f339e2fba4f","tests/expectations/const_transparent.cpp":"6c9b46b989a08e8045735301456f207471b03547bd83c4c654c3cdbfdc9e1ce8","tests/expectations/const_transparent.pyx":"721caf7ea1e2a7d5ebca1670134cfb42f6a16969e192a52f9db815f10073010f","tests/expectations/constant.both.c":"deed4e341fa8b41884bff5af299df73c59e40cd4e8a63a77dd42619cf28e9d38","tests/expectations/constant.both.compat.c":"e8462d4ce6efe917e166263d3625059493a71c3c90e9a2b48bdb9710112ecd22","tests/expectations/constant.c":"129d9124d4c99e28f3bbbea1d527023582b118fffc74000f75eaa5f5c442a204","tests/expectations/constant.compat.c":"4b5a76782d75be1fbe5a06f776bfe3394d7959f368bebdfda7e1458ea72f1303","tests/expectations/constant.cpp":"352ef18aa9c1b431d1ce099606ed6295d1145d89afc4670a0f0ba90bad218ff4","tests/expectations/constant.pyx":"1c0e93bb36fe3eddac86263ad00296d7e65ef27207435dad6497c92be23ba101","tests/expectations/constant.tag.c":"acd58a2ca6c5c0991a9d7c47b39ff967bc92ef1fba415ac58b05cee1a5ec83f6","tests/expectations/constant.tag.compat.c":"2ad53667d23ddef7899a3119e2f28ff91f1adc0afe52236723a40da4993bf05f","tests/expectations/constant.tag.pyx":"9d33c799f8032cc515487e60c25c24b980ce94b30a90aa0fabd067f3caa8b1f7","tests/expectations/constant_big.compat.c":"eba7da537ec9ac4f2c772a398fdd7b5385dcef75698899cf58d85013dd03c2bb","tests/expectations/constant_big.cpp":"ad4e09aac8611e1c0e9235f6912a0a7c6bfbc82d858c9005525c6e381921427a","tests/expectations/constant_big.pyx":"2e31bd9e3f0df266ca8e2ae0edca7f0dae59e328f83b7c8914aec4ce163623ec","tests/expectations/constant_constexpr.both.compat.c":"8b498a1a11e995d17cdc1b9d74d2cec3051af5601d195adee1954b5675457a5e","tests/expectations/constant_constexpr.compat.c":"7f540ae608e3240cccc763f53e5ffcf279a3ab5f737f055e6ba1be6708ffa905","tests/expectations/constant_constexpr.cpp":"0b691506eeaa5729c2a8d8a31420591cdb7d45f2d8767e61b60ee90e516518e6","tests/expectations/constant_constexpr.pyx":"500df1da145ac960629956a3b7a2d93a1cfd8526a900e2985643dbe5c892638f","tests/expectations/constant_constexpr.tag.compat.c":"097adc133ca25bde9ebad4a63fe77d26759fa14ba015127a160d9c0f869caab3","tests/expectations/constant_constexpr.tag.pyx":"8e2fb6f28152d22ea29830021add535b0313353f93c65cb012655c3d4316fa8b","tests/expectations/constant_sort_name.c":"733b9a46e8b9e33cb8696d13e74ba7b8023735c8fd8dfe73b3cf39d027dffb38","tests/expectations/constant_sort_name.compat.c":"82bd07c1f56913bca006c3859f222feada9ce53a53444702c5c61fd96943ec49","tests/expectations/constant_sort_name.cpp":"fbccd8e8d4d4f8461dbc20251d4138e16f7a06745b04a0421537fd94a3292be1","tests/expectations/constant_sort_name.pyx":"676a0026c90d31ca7339b4124f79e2da27198723b62410396b04984e72268070","tests/expectations/constant_sort_none.c":"7839492e03ffac12c0b2f5a15bd4b32aaeb20d0c50440fc392fa2cff9b585f83","tests/expectations/constant_sort_none.compat.c":"3b59ec576d09ae51f0db0f8c34bb9787972cd8441ae718117568f9220c4f0cc9","tests/expectations/constant_sort_none.cpp":"707da6714a41880e7062c3ccf4088fed204572cd612cf9411a208e847566e348","tests/expectations/constant_sort_none.pyx":"da6f1f7ca130359c87ad502e3e1367b20a6f0b936dd036a5caa53181bc51c099","tests/expectations/constant_user_defined_type.both.compat.c":"c6c7e161438bc7d4eac09336b05950bba88ffb0ddfe39691ad288fd8db6825a8","tests/expectations/constant_user_defined_type.compat.c":"a723546e5f6a7bfe3caf8f8f687f8b7c457cc57defffb9082db07a91eecbe3be","tests/expectations/constant_user_defined_type.cpp":"1181a923e46ae423dcbff4d0308befb67b5274855ad75087b6ef5e61e7c70139","tests/expectations/constant_user_defined_type.pyx":"14f8acfe6db6e732931eaa3f5f8a4e9daebb425d64710fac1b72ee0b358a145d","tests/expectations/constant_user_defined_type.tag.compat.c":"0466a87dd60eb403f4f376639464e4b9400dd00938bd5166e131aa1715ff9e89","tests/expectations/constant_user_defined_type.tag.pyx":"b903a4e223c02cdee43ce21facc1958af978afa9e7e7f45f82414de77169a405","tests/expectations/custom_header.c":"30083b9d26f8f022945e85fae85ed3608a47e105217b0595ff64d103093bf3d6","tests/expectations/custom_header.compat.c":"4ac0644b644b1dcdd667a5e981ace55e21e0064ab83f27c59ff7fb0eab9f4861","tests/expectations/custom_header.cpp":"16875359466b19aff8885d62d20e499abf68675a2ae7741e2bd9c0956f87d9f1","tests/expectations/custom_header.pyx":"0540db55e6c4955d2841048feb2c4791e498bc06bac5d884cc33473cc642a316","tests/expectations/cython_options.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/cython_options.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/cython_options.pyx":"03c9cf870f9e143f0a49f10dc8c7a7cbecef2f524f041ba650790ee00940139d","tests/expectations/decl_name_conflicting.both.c":"9efc49c435bb6fb7ef52b331d1957fc7e965e49b31f3934a19b9847ab01e661e","tests/expectations/decl_name_conflicting.both.compat.c":"7837b1477436fa876cab383a253de885989b8debee61eeda124bf3bfcc0f5328","tests/expectations/decl_name_conflicting.c":"98a84351d4fce32d41467d3e54a90828faab5c3bb438e4039fc5f96e021a9c00","tests/expectations/decl_name_conflicting.compat.c":"d17848bb72edd047c20c3a1d291cc1c1e6b68867ac42f77e2cdadcef7edcb0a7","tests/expectations/decl_name_conflicting.cpp":"44a51f5fab3e1f87c2d92535a2d36657bc21c317b53bd93a35720949abd453f2","tests/expectations/decl_name_conflicting.pyx":"6b1c840be79f4f89486978c7a133877274bdb712ccee9af963041780d2b54b56","tests/expectations/decl_name_conflicting.tag.c":"55d25744b93c9cd59f9fb22aff48a981fce1fa994b0c279e0b2f6e73569bfd3b","tests/expectations/decl_name_conflicting.tag.compat.c":"e430a6eb17a1a0fbd52431f1806082f4baba20cfa9c7d654fd499b8bdd7bb885","tests/expectations/decl_name_conflicting.tag.pyx":"edafee5ca19add0925a0bb4eaa4ea7efed8d0b9c2a64b0c97653714c8cf9dd88","tests/expectations/dep_v2.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/dep_v2.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/dep_v2.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/dep_v2.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/dep_v2.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/dep_v2.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/dep_v2.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/dep_v2.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/dep_v2.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/derive_eq.both.c":"0a42ce7794512473d32b7ff91f789b188af91c3c69ee6b6a9d86e82327129bd1","tests/expectations/derive_eq.both.compat.c":"d628768393c2420530d2628ced1e4447e583f9f386756fdd547f9c92df264852","tests/expectations/derive_eq.c":"7b914984a98209889a6f9f4314f1347c4128deb26cef8f7b5b678206d5752bcf","tests/expectations/derive_eq.compat.c":"be14695942908f4d976b1ff606c567347f4ddf3fca40f62c4e1926231eb0ce10","tests/expectations/derive_eq.cpp":"21d619eeb9fa71fdcd35cdc4a29348b340860d7c7474b5b0231845b071b8cb59","tests/expectations/derive_eq.pyx":"102c2505a974086507785589249f4349f0de5493c5672340e59dcf25bbb4fa7e","tests/expectations/derive_eq.tag.c":"7a28b8245621034532bd5af2c018bb0b62effb8b62a1076df143209121c42317","tests/expectations/derive_eq.tag.compat.c":"38dd43a0e5543dd566537512767131c41cfa6ae56c17ca8e14aee32076e879fc","tests/expectations/derive_eq.tag.pyx":"73aa8f84cae7e397fda4c1cfe6503b1df5e4ba820b64bd57311d2464214491bc","tests/expectations/derive_ostream.both.c":"0c225a59b20e6cd10b82d1e3fb4bd158e2f8ed6ad664953974cb80fcafc3fc76","tests/expectations/derive_ostream.both.compat.c":"1a7d96d572abd7fef9375e9ffe0e55f0a290a2ea15db1b1a9dac287632a73cee","tests/expectations/derive_ostream.c":"a6e8faff52219d4f055fb2fc193109e64af7413433dd49521c62a8914fe078da","tests/expectations/derive_ostream.compat.c":"74794d970127e90872aef5cf21be225e64e1e20b0d0509eb7191f3d8c422e4f4","tests/expectations/derive_ostream.cpp":"bd9ad020c82e15b445bb40b58e458f05262c706dcc19e20f40d224d53c79faf8","tests/expectations/derive_ostream.pyx":"714d0f4bc3f6ddcda46a01d827769cf9c5a81e8d47a5311de1904319750cc06f","tests/expectations/derive_ostream.tag.c":"834713a0931d81ddc6e88d5988d46b87004aca955e37e2cb156621740cb6ece2","tests/expectations/derive_ostream.tag.compat.c":"83e5c3c4c12b52f073ce71485c42d01b280c01596226ec602c384038425b31aa","tests/expectations/derive_ostream.tag.pyx":"2a8b513eba477ee274aafffc34a4878806f1a6000b054fa427d3aaf03ffabab8","tests/expectations/destructor_and_copy_ctor.both.c":"e846eacbf7f762b32982531b6490b94ed6c2c7ad998bf7c898c676d435f7b0f5","tests/expectations/destructor_and_copy_ctor.both.compat.c":"f6dfd8d30add21605134458c1e59ffac0e01903afd378928bcb6e01f721d3b64","tests/expectations/destructor_and_copy_ctor.c":"c4097f05b1c764d8c038225c407b145d8e1660b1d1a155a17afa04a2009e365c","tests/expectations/destructor_and_copy_ctor.compat.c":"645f95a9ade1397eac35b678f1c212ca4d933807a9083952d1d58c2c0fb736f1","tests/expectations/destructor_and_copy_ctor.cpp":"5e2842b4831b25c278dbef666a3a051411c79ea137245e67a25c2ed8850ea1b8","tests/expectations/destructor_and_copy_ctor.pyx":"db1dab0bc08747a35178cd0e8c37fad8f98886bd6e0b82b43b84cf49b2ed42b4","tests/expectations/destructor_and_copy_ctor.tag.c":"025a21e8f3974098ec52fdbc331f38c0c9643041597c3756a3bd40d4691092b9","tests/expectations/destructor_and_copy_ctor.tag.compat.c":"3b8bc3684ba0d2474208f4b28cb2be5eb1f551bab5c498dcdb7a353f0e537d0e","tests/expectations/destructor_and_copy_ctor.tag.pyx":"38c2803307cefc9fc6f8c85564397ec8d35241348a75b70abaa561dd65e62bac","tests/expectations/display_list.both.c":"a515bb0077634f77f023ef62f2ede36cf8326fe4da5bdcd2e800692c234e6ce6","tests/expectations/display_list.both.compat.c":"a1b785b368ef3b4b813cb8a3ec95089b8dbf772414dfefee585fb633cd2faa8e","tests/expectations/display_list.c":"f3df45922f23a2ec455b36341dad5c59e3d6453aeb9a7354c0ea55b04b79ba93","tests/expectations/display_list.compat.c":"18ebf21569cb7862816cd218f8b9926e5a725d9b032d46523eb4480bae9ceb0d","tests/expectations/display_list.cpp":"b94d2065a6ea07ae0c121cebb4f510d6d72cb2dfe7b8a2001d094bbb6301fa23","tests/expectations/display_list.pyx":"ae55fc18e44a7bad123f3a100ee25178c31b45786d43eb76cf8e71afa83050e8","tests/expectations/display_list.tag.c":"886bd29c8d6b482f52e0d51c22b8d4381eb6ecf9ad6d249d0cc4843bfdbd663e","tests/expectations/display_list.tag.compat.c":"0a017a5f3d9fe253e392b44a19d1bac49a21b05d9de1029f4f7d908c819a611f","tests/expectations/display_list.tag.pyx":"6f0f242efa62500f225f4dffe5201ca8169ea345248f0c4f313edf73dd41e348","tests/expectations/doclength_short.c":"14a5f31a6e6af5ce3e01de42950b759a94a9c7ca86d822009e36b7beca77c55d","tests/expectations/doclength_short.compat.c":"5196290e2ecb33d7bea2f20b6aa22c126ccd420e001b52458dba4efc4683af65","tests/expectations/doclength_short.cpp":"7e223faf3cf18072b2b3fed19d48a56fd983b5fcd2e4bf79a894294d330cb830","tests/expectations/doclength_short.pyx":"29a356be42cb9d14454ad9d820d7fc50fc692d4fb8fde0a828659cbc97ba833e","tests/expectations/docstyle_auto.c":"34e1474c79b8a974c1e4b91a444272d954a50d7a2e74c46368a1f94ea1a59113","tests/expectations/docstyle_auto.compat.c":"e907be610c1c2fe09af9a355155df95226aa45b129d6ad5fcc4d7358793499bc","tests/expectations/docstyle_auto.cpp":"85f23dbbb3e5cf03ca1c9bedfd559b4253dd6795d8c3597773ce2dff3ac30714","tests/expectations/docstyle_auto.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/docstyle_c99.c":"dcb114c8aa34bd0a15cca9e7076b24700c3660741ecdcc41e7ddcc44bfff9434","tests/expectations/docstyle_c99.compat.c":"fe9814379b9c8795bf8ecfb1308397e5e0dbe9bd81cc9ac820b90ac89191c39f","tests/expectations/docstyle_c99.cpp":"2391bfb6d1de7679f5a6dcc5c2a1fa8b57d6a2af98058ddc6558153f64904a57","tests/expectations/docstyle_c99.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/docstyle_doxy.c":"34e1474c79b8a974c1e4b91a444272d954a50d7a2e74c46368a1f94ea1a59113","tests/expectations/docstyle_doxy.compat.c":"e907be610c1c2fe09af9a355155df95226aa45b129d6ad5fcc4d7358793499bc","tests/expectations/docstyle_doxy.cpp":"0277cd56e2bfb397cbbc9ab58ab9e91ae27cf7388ce6c081140420a05ca7fd24","tests/expectations/docstyle_doxy.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/documentation.c":"268e799c5b13dabb6796b9e233d623adf89d3d69a26c9d25d661a182a2de2a73","tests/expectations/documentation.compat.c":"b9987f70233cc3952f82b2553b2e016e85b54037b767009c1b96c9cbf9d80830","tests/expectations/documentation.cpp":"d34d4e1fbad6275e999d733083f922070bd2537e87e9024e5624da03c52eb7d6","tests/expectations/documentation.pyx":"f87ad48322fc1ebeb72589f9c88c1fa3c98da99deeb4080b62b651caac20a5d6","tests/expectations/documentation_attr.c":"7c353cf10b129591b74fc1a3492b2ae45e80877e5c00ed225e83f892a495bd73","tests/expectations/documentation_attr.compat.c":"17f61b4a39cb3f8668713ea7d50e74e57e5021e326cedd95e3f67a29d1c4d2a4","tests/expectations/documentation_attr.cpp":"044c5e034beafc6275c6a3779fedcc6570795c4033819ba065a584b339ef5e46","tests/expectations/documentation_attr.pyx":"dbdea07c97a1b0e1937c009228825efbbbb12f5a4fcd85ae6fc9912ea039204c","tests/expectations/enum.both.c":"640e36792377ef29dc2ebd6761003f951e77409aa55f2ec7738b2a18bf41facc","tests/expectations/enum.both.compat.c":"09fc4d23136543bc3ca2b10622408b24f2ba1b37cdd27cb6b2d2dc0a9ab33d6f","tests/expectations/enum.c":"d5e57784fd64677a2152fb78935beb013615366876ee9fed05bbec85e84e968d","tests/expectations/enum.compat.c":"638e52ac76133c9bbe0ad4536cac2032bc0764ff8d73f433f5120bb419c4147c","tests/expectations/enum.cpp":"e71881b5bba8a2ac80fd5562344caceebc85b5cb99ceddff4627f20cf5c15a7d","tests/expectations/enum.pyx":"655890d52693af0df6236c7fa6b01687d11eea6982f5983c46707596e3608bb5","tests/expectations/enum.tag.c":"e1ab4025b5a7796af61b88b82ecee89e0cf3293f64904c9c44da4e0a72831b4c","tests/expectations/enum.tag.compat.c":"5d01ac0feb90336268578c5d590cc1b7f4331e5566682c0ad1a66f4115204255","tests/expectations/enum.tag.pyx":"4cef4a8578e4a2225a16206f8f1acea6751f20dded407f3bc589e6eb4a13abb6","tests/expectations/enum_discriminant.c":"6f24cbb16f768c5ffb22c7e37a316aa874a903c96d2ce18c9210ec0501224d74","tests/expectations/enum_discriminant.compat.c":"35ce86b5d0a7ceb4ddee1c13ae33265206a9f5e37d830b97878ee01f16b680ae","tests/expectations/enum_discriminant.cpp":"5385c9f16a5971734309f177adc5c9715963812092944a07f1764088ca26a220","tests/expectations/enum_discriminant.pyx":"f0f9441256929c7b92c1219c6062609d423fbdf24d3fb9ed9fa04fa78b1c9bda","tests/expectations/enum_self.both.c":"d75e33232219c5ac92e7192590725aa5f808f39a2ae6510366ce23485bba2e1a","tests/expectations/enum_self.both.compat.c":"5b90d1664411cbee379141e4bd49b3747c8738abfd90f48fcd1cde20736b59b3","tests/expectations/enum_self.c":"268553d06c168f0c0f9df14d4b1825c25fe627909b99bcf4e388eaafe2c516dc","tests/expectations/enum_self.compat.c":"185abf491a7577b844ff38e67c3cdd8e33f8371b3d69cf290d3bd8455ce33bad","tests/expectations/enum_self.cpp":"9fd2c124a9498f995a00b9f237e9e99ae9b0c14777698d25e30fb105a4bb25db","tests/expectations/enum_self.pyx":"4c0da57ac648729c2b148d76b63e823880a120b2438b93429fef518524d564fe","tests/expectations/enum_self.tag.c":"0473c73442d1fe1348d552e8c51c548cffc0d61178cf2c6329fb5abcb854bed1","tests/expectations/enum_self.tag.compat.c":"8db08e1d671641c094c51ee0c488a5864b5f6a8f294d30958d66a13817078ab1","tests/expectations/enum_self.tag.pyx":"a581d08f6e2bffce62c72bc627d94545d722f1a959a032516342b1f8eef51508","tests/expectations/euclid.both.c":"a78b580e52876b49f32529ae67754975c1c33172c8bfba830cc147d3c755fb5d","tests/expectations/euclid.both.compat.c":"c6e5ee01e4dc8ffba597457db2ad5a7865f2778a334bfa468903681f5a8f340b","tests/expectations/euclid.c":"360eb8124beef4803470e58fe0d0546b64b5ee91ba7f3237de30e8b3c389122e","tests/expectations/euclid.compat.c":"4cc5da9fe161f55353c581702ca815e49c249f18d23c5f6b2b06e8ffd8a50afd","tests/expectations/euclid.cpp":"e2d7b4e83aae20151e2c1dbb96121abf4fc2fa6122485dd148dd99b7aeb97ba2","tests/expectations/euclid.pyx":"0353d7e1413cb86bb255c4b4516a7f430f6721ed2d67261b25383c17352e893f","tests/expectations/euclid.tag.c":"3a3bd68906ca709c4d7eefdea0021cf9117a83dd87a2bd9200b0b41cba68ba20","tests/expectations/euclid.tag.compat.c":"891ae3746e246a2e814a02f6670a025347fc792e956c242782cba4b8abb53f9b","tests/expectations/euclid.tag.pyx":"4a8efd3be848dfdb1e4beda0133d083b759e2dea791711c52f466ef746292c83","tests/expectations/exclude_generic_monomorph.both.c":"b63eac0e7048c67d47e7f75993684c098ecc86356fadff0038eeb4f4f8f86fcb","tests/expectations/exclude_generic_monomorph.both.compat.c":"c6a8435506c81517b4ea8b2653723e41ce72cd4c831ea8b439cfed774043a9a0","tests/expectations/exclude_generic_monomorph.c":"41924ac09f9b3abaac47c46f7781485a83518e37548f103a19af9460a7b7b6da","tests/expectations/exclude_generic_monomorph.compat.c":"5e8839568a14640b635689c9d88824d2a63332e254bd87a437cf71ad96b5c419","tests/expectations/exclude_generic_monomorph.cpp":"b63eac0e7048c67d47e7f75993684c098ecc86356fadff0038eeb4f4f8f86fcb","tests/expectations/exclude_generic_monomorph.pyx":"c0ff87a1730876e78bd564dfa001e3115d6722c3051e938f5141d1d66f5bc465","tests/expectations/exclude_generic_monomorph.tag.c":"3e6e6f27f680af301472ff2e4d0dfdb7eec5d8714968b99a6bb30841580f4f74","tests/expectations/exclude_generic_monomorph.tag.compat.c":"2f0a9feb2d9c4eb5a14089a06682416d685122dc8b75d0b3ec427d6a23363c80","tests/expectations/exclude_generic_monomorph.tag.pyx":"6b30a5d86eca17eb132334bcde1f8a7d9a91bd9316187587ee905d73a3ef1da6","tests/expectations/expand.both.c":"977cda0bf7dbf4fb408dd7f013bc24143e17dd10987f42f2ddc9b758857b96d1","tests/expectations/expand.both.compat.c":"bae04494dca07e7c56bdc60212ff99c009930db00c95c3910d64d5260769bcd0","tests/expectations/expand.c":"fc69383c93f639f92996e4b91f296084510abe22f10b831ca628d7d11182620d","tests/expectations/expand.compat.c":"786956948cba335e44d4ec08f6cbce6aa85cec2605554ac88903ae1fc06ec2bc","tests/expectations/expand.cpp":"38f85893eaca630049af26274b6cdfd4ba9f9ad162bdce9e8f82be6f2572005a","tests/expectations/expand.pyx":"1eb4669255dd12dea709aedef09b49053ba96c83e5225afe30c07cb55a21e801","tests/expectations/expand.tag.c":"c14c175f9672e03913b278c6f2346c3ed655ff66a67889b9f9f22e923dd293ca","tests/expectations/expand.tag.compat.c":"972f420b8703a1a2f9e72e7af8ed1dab832240faabe6c2af9a72e47f000fbe58","tests/expectations/expand.tag.pyx":"a5fbf6408df5bd3ddd87bfcaf0ac7cdcd0717b42802a9a0815012d14588b1b58","tests/expectations/expand_default_features.both.c":"84118df0f668e17a54ef8a081622bffbfcff9c64856ef135ac492a90d1029579","tests/expectations/expand_default_features.both.compat.c":"4a3e098f40d2062fd1aa35a4231ce597de7e3d805eda74e4463a409f9febd585","tests/expectations/expand_default_features.c":"6bb6ecbe2d0e4c904d260fba76a4893a0284e5a794305e704886d36c7e63f595","tests/expectations/expand_default_features.compat.c":"5c4ca68e2bb67ba37949f3e87f5da85cef61a869891a239e39fcb7dc35120ba2","tests/expectations/expand_default_features.cpp":"7abea90e45ecf0ef2ab3d254e59eaea7044fcf95188e4dbdf2780c410b22919a","tests/expectations/expand_default_features.pyx":"1183233f2774df3087a3691d8c315428791a2a1fef2902250aab7c4574bacf56","tests/expectations/expand_default_features.tag.c":"7da60b618c40a23089c8f7c26c196da98a59720acf25683f32a838c52f8a8b10","tests/expectations/expand_default_features.tag.compat.c":"fa7654d64a8de65c26a109d4f4389c9fe32489bbb9dbfbb3e4c51541e3555e49","tests/expectations/expand_default_features.tag.pyx":"e509ee84cda4f78b8fd871a6a30ab0932fd00db0733fdf03883d025d1d2a9466","tests/expectations/expand_dep.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/expand_dep.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/expand_dep.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/expand_dep.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/expand_dep.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/expand_dep.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/expand_dep.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/expand_dep.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/expand_dep.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/expand_dep_v2.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/expand_dep_v2.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/expand_dep_v2.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/expand_dep_v2.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/expand_dep_v2.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/expand_dep_v2.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/expand_dep_v2.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/expand_dep_v2.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/expand_dep_v2.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/expand_features.both.c":"b953f3e1c597a42bea863a9baf59de77c2d7aebf00a25c7bf03bd842a5470a92","tests/expectations/expand_features.both.compat.c":"69ab55195aa57c3f15491027e098d45b15de039b48b87e07727414f9357cd8af","tests/expectations/expand_features.c":"928314408a433b8e03ce4ec9d99a29be51de11a2a646bf00d5efaf4e8f42ef5b","tests/expectations/expand_features.compat.c":"4086173d7c9973d4ef51e4a729e69fbc96d196e9c4b483c1015581ea16961833","tests/expectations/expand_features.cpp":"71761f1030231dd7d6628f4c4055f85720186680c0ed32055df93096575703bd","tests/expectations/expand_features.pyx":"b4c443321c0f86ddf508b8bb1308f75cc5239975893aa47074e252f4d34acd11","tests/expectations/expand_features.tag.c":"307babc64b5f3821d90cce8dd7b344a665ecf5b76b76c2bf606001798f39d46a","tests/expectations/expand_features.tag.compat.c":"9316e9411d1a8be5414c0d2db09d1c582fd172661a69ecb2cf5a30731aeeb496","tests/expectations/expand_features.tag.pyx":"2654ffa0041ae74a6a80494fda866a967d2535d79f1d03224a175373f8b4cf22","tests/expectations/expand_no_default_features.both.c":"977cda0bf7dbf4fb408dd7f013bc24143e17dd10987f42f2ddc9b758857b96d1","tests/expectations/expand_no_default_features.both.compat.c":"bae04494dca07e7c56bdc60212ff99c009930db00c95c3910d64d5260769bcd0","tests/expectations/expand_no_default_features.c":"fc69383c93f639f92996e4b91f296084510abe22f10b831ca628d7d11182620d","tests/expectations/expand_no_default_features.compat.c":"786956948cba335e44d4ec08f6cbce6aa85cec2605554ac88903ae1fc06ec2bc","tests/expectations/expand_no_default_features.cpp":"38f85893eaca630049af26274b6cdfd4ba9f9ad162bdce9e8f82be6f2572005a","tests/expectations/expand_no_default_features.pyx":"1eb4669255dd12dea709aedef09b49053ba96c83e5225afe30c07cb55a21e801","tests/expectations/expand_no_default_features.tag.c":"c14c175f9672e03913b278c6f2346c3ed655ff66a67889b9f9f22e923dd293ca","tests/expectations/expand_no_default_features.tag.compat.c":"972f420b8703a1a2f9e72e7af8ed1dab832240faabe6c2af9a72e47f000fbe58","tests/expectations/expand_no_default_features.tag.pyx":"a5fbf6408df5bd3ddd87bfcaf0ac7cdcd0717b42802a9a0815012d14588b1b58","tests/expectations/export_name.c":"4c0452bf3c2901a1006efd759360882df316c2938d141906c89ad60b15b477ad","tests/expectations/export_name.compat.c":"5a2182e239b75ef0e4970431523f4ca5e3c17d43178ab1126b0833385666e37f","tests/expectations/export_name.cpp":"212eb614a342bdd626c83b790ffdfe30d985cdec4e2ff14fd38ccec4f55137c8","tests/expectations/export_name.pyx":"e10cb6efef0c0d2c7f91d9226db21ed1111464f6474acc1076390cc4ca36e8c0","tests/expectations/extern.both.c":"5864f0aaa3669aff76a2a44fdb88de8ffebf2b22a1d32997686149d6c4401b84","tests/expectations/extern.both.compat.c":"957495a1a26dac601525b832456856813542be2014f344f2aa84a546c57fc7c9","tests/expectations/extern.c":"e541f754570d2a1ce3ecf242de3b41f0437db6cbf4fb7e8505fca0ebc2088950","tests/expectations/extern.compat.c":"0d2e98ee37e668f056cf62884084ddf3b505f4a193626f098c5de20ac501d504","tests/expectations/extern.cpp":"2c9e359108649bd0f34ca83382ff77fd9c278dff4e9f9dc763012c0e1769f05c","tests/expectations/extern.pyx":"419351cf630b00068f523b6bd463ba2a74e8babd14335fc08442ff9acce71efe","tests/expectations/extern.tag.c":"1d6e6afbf9765a48cebf170bd31751ff7372d7665ea646bf2605e5df12c7e43d","tests/expectations/extern.tag.compat.c":"a9e47795357fbe2f04a952033d33d2d7bc54a47654f40c21c5c1c824137690ee","tests/expectations/extern.tag.pyx":"585a09dcfe77d89ef0cbd5e4420f1caa07f3862aa67af293347c6f92336e4183","tests/expectations/extern_2.c":"a81c41efe618612fc4b9a22d937397ce7a76ae966a28b33e56a10725cf2700ea","tests/expectations/extern_2.compat.c":"124174ff9745e397b646830ed9660faeb05910bcb340b73c925a4f8f3f656a14","tests/expectations/extern_2.cpp":"739b9b9e58af72a281402c050d6358ddf001076a64ca861a2c3a95a66cb80d96","tests/expectations/extern_2.pyx":"0c1a9e29feecbc385005b9eef2c5a5398b74d5906fc09d2127b18e9722f6308d","tests/expectations/external_workspace_child.both.c":"0c518b620f1b2bc24d789d725083cfe6f9064630b8f386123c237d9e73fa38b8","tests/expectations/external_workspace_child.both.compat.c":"1fe5756ea6f2668069d92e7cda051ba1ca0ff547fa49fcc559d07fcf33d1c8f4","tests/expectations/external_workspace_child.c":"9d9aeb31e5388158b6abf8686d4109771159d98ef83e93658d3c2e556dd69174","tests/expectations/external_workspace_child.compat.c":"3681fcbc89d3f7b91a1cb4b67bf6b64b0d08cd7722c9a6f908b0e16da9015077","tests/expectations/external_workspace_child.cpp":"32ab68edd8b25b7de5553236f624e23a25206aa3524bd52dcbbb423a8bc38611","tests/expectations/external_workspace_child.pyx":"d67d610ac34dc895c1bb1a82007f798aa71a2bd0f309026acd40bbee182835f8","tests/expectations/external_workspace_child.tag.c":"be776d880e923d640da889c22551dbc6dcacf6f80b1b8a07284bc8fcd726151b","tests/expectations/external_workspace_child.tag.compat.c":"08b1d7e35fba239e73e08a56fe2a5ec80133b46774e4047ae2eabb56e027a4ad","tests/expectations/external_workspace_child.tag.pyx":"a6bee518d269e44054cb0935a8b704f942e43d84e69e5dabf9f07f1bfff733bc","tests/expectations/fns.both.c":"c1405054701813792db17fec4156ce2940713751aea6eb1f3e2b49eb14a78876","tests/expectations/fns.both.compat.c":"4601c5ed7d383db6490afcc49927d0e94121e6ac4c0e534f4c5317c9b4b14bdc","tests/expectations/fns.c":"7c5803639ebaa0935c3fbe7aa1ed66cbf3566ee44005d14f58161ad66e9f1b28","tests/expectations/fns.compat.c":"ca3f73199d1cf506d63b746fa45edfdb8d650d2a268c64740efcbed14352ec70","tests/expectations/fns.cpp":"2f4f1079779feeb468d995aecc51b8a3cab2af8525c24f28f3b852685f7dcfe9","tests/expectations/fns.pyx":"862c85224357db387d97f90c1822b52d918839aaa2818358fbb0fec4c3dde14a","tests/expectations/fns.tag.c":"9472ed474690bd8aece9893720ef7cb0c36d9a08511b077d9ddfedfe4204b45e","tests/expectations/fns.tag.compat.c":"cf0de02321c40c8426bd6298d7f62c21d2bb96ed9985184aaa91d4f50a8716fd","tests/expectations/fns.tag.pyx":"212a5f846b1eef6999481bc82b1abd54df8d245d771c7261690c276a6394556a","tests/expectations/forward_declaration.both.c":"ec4bdaa4367767cccee63afcac538bb34eed644ea2300c46400747416d271889","tests/expectations/forward_declaration.both.compat.c":"98ddc3144866860b7b421b3cf13fcea8b96c129c2ff238a35bde75567dbabf0f","tests/expectations/forward_declaration.c":"fa1c91cefc98346e34cd76cebd754bca1a7472594291ad910eda7e3f2c70bd61","tests/expectations/forward_declaration.compat.c":"19679d72b140a9e8984be0ba72ad2db52ecb1e577e0bc9d8410c5367991da723","tests/expectations/forward_declaration.cpp":"982e68a79e1fac4c4cdef1ff45c357ff3d343d7983866be3d21bab3291225a89","tests/expectations/forward_declaration.pyx":"ad727c468b1103aeb5f96b0d81325416f0f3aa4366b9ebfbef861e769957eea9","tests/expectations/forward_declaration.tag.c":"795e52d2101989fea9a35e2f6f6c2f4eaf8a09edd0a1e404687bf6e26907c9ba","tests/expectations/forward_declaration.tag.compat.c":"34a675955746042a4c658f7bf7bf679f4a88fc40387f9063bb7f5922c3edf236","tests/expectations/forward_declaration.tag.pyx":"ef8ba87a36122681ba479728147c82100c42a83754ef6a577df3122f6278e5ef","tests/expectations/function_args.c":"90545731d4f875305f4255721917fe99fe2b72a9800c0e0a1f5ce216c3bdfd93","tests/expectations/function_args.compat.c":"f8afecff6f47cb348f8899248cc12282614b052d50c3d20494f9f65c418c7ee4","tests/expectations/function_args.cpp":"929d057fe83dcf946ebc2abc915484e31c8bcfd48e5d572b1de90ec044129532","tests/expectations/function_args.pyx":"5e9da75f1c1047376424977fdf8c577bedea7e0248f9d45b468d75724e3baa62","tests/expectations/function_noreturn.both.c":"2c557b8e7145bb6da3802ff0bb0e0afc53c49b38552f0ea8800441bcec639e93","tests/expectations/function_noreturn.both.compat.c":"8078d88dd3ea314d5604b3db0295bc94482b7229ce1e4f49f5015035c498f62a","tests/expectations/function_noreturn.c":"1cbeaef6928599ebfa2c7cf7da18227bb06a8143547908bcdb2818018a3e28da","tests/expectations/function_noreturn.compat.c":"2c4a2afec60facdbaaf2818213a7513d3b41a2e97a9876b90a7c8ee816e223c2","tests/expectations/function_noreturn.cpp":"5d03d79185e3328364be4013fd39bcfe015f0c8c30ec82336c421128cfa6ddd5","tests/expectations/function_noreturn.pyx":"f61b56c865940ded65a51ebf2322e7eebb7c571e0541efa188e49959f7e74692","tests/expectations/function_noreturn.tag.c":"747bfdbe489c7011549a2ec37a1849874aa823273df8f83943446359bb28a2e7","tests/expectations/function_noreturn.tag.compat.c":"da06fdaf673696586f386b2ad310597f2cac57caaa5cd5aed334a9dc260771c2","tests/expectations/function_noreturn.tag.pyx":"f5dacca236dd2a72949c38163cdbaf6b125a27bcb3580d2a203afdbb20d491f1","tests/expectations/function_ptr.c":"445561ce58f52f9732681e4baf9f26fa936c3fff919da6fb8adc0185f651f7e2","tests/expectations/function_ptr.compat.c":"43ea17b6fc6e5b56dc1b83e538f89e69fe0154e99b32b5cd2227456d48d9b8c0","tests/expectations/function_ptr.cpp":"f7346f3f163964e020f9259582105a80cedbb42f5184b4ebaf9988ea778d39d8","tests/expectations/function_ptr.pyx":"5c3a893a6619867ddd428ce35f42207af76576b7aa18649368d383117cb5a0dd","tests/expectations/function_sort_name.c":"8c6f66d028092f8ad11acf8d9bfd934e17ef2ae25c26d3012c9655a54f379b45","tests/expectations/function_sort_name.compat.c":"7d8e577d35f4590a8d733ea072e68410784e9870295607ae8872c71239994a2c","tests/expectations/function_sort_name.cpp":"2924b7b6d6b49a93dd1f1a850643b7458da50fe7ea20ea057e3a9f4a27d051d1","tests/expectations/function_sort_name.pyx":"5a94077258293fd28418e4141328aeab509ebbd1f2bdd084aa9802ea84994bc4","tests/expectations/function_sort_none.c":"cb76985dc63027d0d85bb6cfb32e5a77f9c3a46a97059068643186f27a88d9ce","tests/expectations/function_sort_none.compat.c":"3aa6b8e43a5cbcceb35ced688fdf0dac71bd63f0dff1cb7d0ecea72749fcb017","tests/expectations/function_sort_none.cpp":"6b07b4a14d97230660b18a6a63258e3571124c935b4a8391ab377d48c8e9d2f8","tests/expectations/function_sort_none.pyx":"c4b01d34e21c584097a1726c17884dd148315e5924c3353d799c7ee3b39cc939","tests/expectations/generic_pointer.both.c":"883597ae24580f0700dce70e121fbc6258bedaaec1412883ada64f3663433fa6","tests/expectations/generic_pointer.both.compat.c":"ee1c7f3319a4f6d5dc57a8ba1c07299b469c20030828ca24e2553b2d830c8ae1","tests/expectations/generic_pointer.c":"9ec3e744a8f953038b2bc748b34b0e9f682dd473ad46f06ea28bb6d282db9281","tests/expectations/generic_pointer.compat.c":"0c7db5c531555f960346011f526ca77268093718e707dd1d628f833a7678714f","tests/expectations/generic_pointer.cpp":"d4772de13c5e44f85aef9d9014d4e6b180d9749553895fdc559a96316dfcd0c8","tests/expectations/generic_pointer.pyx":"2f961cb4f9635a7ad83b3cb41787dfb336a1e7eea2003ee158e18a30c98e21b9","tests/expectations/generic_pointer.tag.c":"6f7946fdf4f71603a67134fb7e15764d8c723575c969e0976091a6912fbde974","tests/expectations/generic_pointer.tag.compat.c":"7e03767bd8435010e1e92d6f6a7436d1376d78738199a7b1e484efd7e0543804","tests/expectations/generic_pointer.tag.pyx":"69e4baa3e9aaec93c0dca6b7002c0b939ca9043893f33dd1756248e9a9a2dcef","tests/expectations/global_attr.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/global_attr.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/global_attr.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/global_variable.c":"e438559eb15269367b740790ee27a8bcf63a65f58153cfa9da90a173480b7842","tests/expectations/global_variable.compat.c":"7da3dbaa9810ec68996038c3170e308c86d038f2c6a7424f08153a002b84e737","tests/expectations/global_variable.cpp":"3b3506a61523642fab2ec283f14aeaa315117284f1566581f368f9d6d94c819e","tests/expectations/global_variable.pyx":"f9362bd82ec80bc8578ee363b0fed388091f90a61242d0a2853f8c18b846c142","tests/expectations/ignore.c":"8629579fd8d0e5df30b4a6e8258fe62efaeb58365f906e253684b1bd9530654c","tests/expectations/ignore.compat.c":"513d4638f5b6331b88782b7b9803d2eb30e058661ecce6e0f0aeab79b5edfd7a","tests/expectations/ignore.cpp":"8def6cc5a4e93ea3dbdb196769bfaaea3f2502cfdee4e256ef5ae86d25896145","tests/expectations/ignore.pyx":"deaa02f33d1bfe7d637420038e93bc63ffef82e93902bfccd43fd28daa4dd764","tests/expectations/include.compat.c":"f6a8f36949826da8fdd47af14b92afca3a27d334a2057bbd5dea3c3db6a8d8ad","tests/expectations/include.cpp":"52590989caf74c26b42591460528979ce10569e35457f93bcc9ca07af686e6bc","tests/expectations/include.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/include_guard.c":"5d9bc0cf8c54aec379f38ce9ee64a8ced7c710e86b947e6516745586d8d51e65","tests/expectations/include_guard.compat.c":"7ed0680e9547628b3c3edd867fa31bab7bdae7bb38ba68e8c643b676de876b1b","tests/expectations/include_guard.cpp":"09174bac4cc923d3a3b91ef4e1205dbc244af756b8dd40382e0c7b7044ee0ed1","tests/expectations/include_guard.pyx":"2dfb2777f23cfd907d3de10774c020dec80fb510b8d850a2725f133afb5fa038","tests/expectations/include_item.both.compat.c":"0d64fd9ae4b4dba8553cb80512e360fcc06cd4fe03a851a865e4b96a8582ac7c","tests/expectations/include_item.compat.c":"35a80c1690f6b418e3e6163174fce69bc667f578eb6a077107ac7bc87298a987","tests/expectations/include_item.cpp":"b9a3d9d3c40c993223e93e9e0ce8f9c5d173832b1c8d4e09054d6ba559fe80fa","tests/expectations/include_item.pyx":"a0448dd076125dd3483575edcd3f441ae0e5d3ce8b77742f48664ad2406e451e","tests/expectations/include_item.tag.compat.c":"c3e805ff7c80652cd250e0f91c158e25062b9331f9f106b77a7e08147e70d346","tests/expectations/include_item.tag.pyx":"b85cec40d10b7384c5277d5bfaa9dc789a38f56f9bde5d8186d3805055406193","tests/expectations/include_specific.compat.c":"3c762fa6241403b00500f12542bd195f10c680c5b1801c76357b8c38193eeb97","tests/expectations/include_specific.cpp":"3c762fa6241403b00500f12542bd195f10c680c5b1801c76357b8c38193eeb97","tests/expectations/include_specific.pyx":"da3b3299f457f3aba4adfa25e21b9270ddfe6f324d29128add8bb6474bc7cc86","tests/expectations/infinite-recursion-typedef-monomorph.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/infinite-recursion-typedef-monomorph.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/infinite-recursion-typedef-monomorph.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/infinite_recursion_typedef_monomorph.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/infinite_recursion_typedef_monomorph.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/infinite_recursion_typedef_monomorph.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/inner_mod.both.c":"d848b62ec77f2cc5b0e21446cffa0429d2759fe55dfbc98604ac12466c43d542","tests/expectations/inner_mod.both.compat.c":"f6a4661c96309cfb53f860a6766a36760b0c501a4e603834f113a2b0cc980e73","tests/expectations/inner_mod.c":"acdad2892c84bba42f5e45ae3295ea095dba9786d566672acfddd8e388ffde70","tests/expectations/inner_mod.compat.c":"fb9a16a48c294e56d60cdb50e9522d8119152e5ca34862857ee7643694e3ed84","tests/expectations/inner_mod.cpp":"e27ee433a0764f92010e476b4f311b3c8e7723e22bc4f3cf2f473ad6fe516ae3","tests/expectations/inner_mod.pyx":"ac755298e5255b926962fc068e2a70899d40bf6065cf46db8e57ceb56b0538d0","tests/expectations/inner_mod.tag.c":"e5b15746228630dbcd16bbd1467375d0954f981de85ba4230ee09bfa7f509a4e","tests/expectations/inner_mod.tag.compat.c":"6e3c7a559af8d84eb504d94aec8694c18d2c8d9acf32cc525e748c86db7d0c97","tests/expectations/inner_mod.tag.pyx":"7dc7732308c5c67801aee1dd627df1a3c530b544057638362870138cab2efaf7","tests/expectations/item_types.c":"ab7fb01375066294949a2dc99a55cd1cde72bfd8510aea21fe89db256200ed42","tests/expectations/item_types.compat.c":"0c68a303f170b7f412fd8ed4196d0c688a995c9f3a0b35b0bf857acecf9cfa36","tests/expectations/item_types.cpp":"19f55fe8f8416342e916344276ebf10a975e57b9a787c1b42bb9b0a374a587c6","tests/expectations/item_types.pyx":"c067270e98479b2c336bc0b520c57c480b7b4448b21f0fb1a8b342d1953a79c3","tests/expectations/item_types_renamed.c":"fbb007a71b1e2567d4068dbceb46b4e284e64fc0f425b67b84bf9f319f947435","tests/expectations/item_types_renamed.compat.c":"a15917d285d40d7edad8b53ff9df83a5f417212c9d6bb8e120c68401afaa127b","tests/expectations/item_types_renamed.cpp":"b60fce152b506ad6e3f964638390212e06b7e3a9853f62943d05e12ae44c9766","tests/expectations/item_types_renamed.pyx":"a0e219b8f7a33b0843aad617bb42a987a41ba4d1edcb399d07c7c29e1137c1c1","tests/expectations/layout.both.compat.c":"0a3f11507f4c77e6568d37f85b72cb7e22e3ae25c19edcdf3faefa4029a3a79b","tests/expectations/layout.compat.c":"f3aaea6884993faf3dc4cb8433deb6eea361e8188e4a944ec44cfee418c1c30b","tests/expectations/layout.cpp":"0ba0d01dae0403e9d4f7c86241027ea34cd7f67b0fa4d5f48a4e993f42688369","tests/expectations/layout.pyx":"7031dcbdd850c1465afe36222ca0918b2f424022d549eff7c30a818cc1873a02","tests/expectations/layout.tag.compat.c":"a4fc428e701015b316d1d5f45af9ccfe4f93119737dbc70440bb5135775455f5","tests/expectations/layout.tag.pyx":"c44b62c85bab18e65ced0ef68549b92861191624dec0a13ac8743a3d11ef8fcc","tests/expectations/layout_aligned_opaque.both.compat.c":"f3ee88baa5bafe2038a33db94e5088d91f16a99a127a0a20fe5820d0fa2b309e","tests/expectations/layout_aligned_opaque.compat.c":"c6def8e3570b4c33ad597d699f5c668f3f6765240f8a79f1fbb506a2f29d5aed","tests/expectations/layout_aligned_opaque.cpp":"bd1ec25eb3f52444263012c836c1a312831ae9987cf092569b9f77f5087f7fa3","tests/expectations/layout_aligned_opaque.pyx":"19b00e1ddad32eccf8f092254a386af4a379510849f3f7f1401fd8e44d86a58f","tests/expectations/layout_aligned_opaque.tag.compat.c":"b1c7d1fefd46489aef9c7d9a1ac9d2813daddb42950ae1e251c5f36db56ea087","tests/expectations/layout_aligned_opaque.tag.pyx":"b4907b7045b946226178bab261d98a573f574b00a92b35374bb855525e4c5d8c","tests/expectations/layout_packed_opaque.both.compat.c":"ceb4ae333479c72559158a62d2dca064c6982d765ce99d979ccbddb48231e464","tests/expectations/layout_packed_opaque.compat.c":"eff44ed7ce409947708c246aa3b535f10b42bfd39a591d94afe8ab4d404a5350","tests/expectations/layout_packed_opaque.cpp":"31e40feebac3001adf6ab13e121108a60da2b2924c7ba673f0ff56cd29ceed84","tests/expectations/layout_packed_opaque.pyx":"5ac79bebcde01e802f8b945305db80a5b6e1a9a7637cc5277befc67a458544fd","tests/expectations/layout_packed_opaque.tag.compat.c":"e0a6f08d233d4f53d5302b728a723dc0b1c4684b47c50c7e28732fb895d6223f","tests/expectations/layout_packed_opaque.tag.pyx":"7767f5e23c99d5109516f7fbd81218210d6e3d321a1465f13cfc87b82489045c","tests/expectations/lifetime_arg.both.c":"b5f69000140f7afdbd7da95c5378da6dadd036c3692643488ebeb32409ce02ad","tests/expectations/lifetime_arg.both.compat.c":"0224425b0f7633b5b651c67a4f3ddb047c803ce8a55322a9ab2d2b74df13bb42","tests/expectations/lifetime_arg.c":"1219d3d3e02b7b9600bc861cf7f8268bd2e24705819e14c5a90cb236fe633b72","tests/expectations/lifetime_arg.compat.c":"bb23c5d46ef6ecc103674cec94cbfd4b41e087b46c5479edd9e2f26db575ed84","tests/expectations/lifetime_arg.cpp":"e6db96ee06a83ba33f1767a1741b656637574895edf496f1fadb109538d7eeca","tests/expectations/lifetime_arg.pyx":"36bc1ca71ee8eba07ed117326f565c50f38dc08a8b8e130be449a652baed630a","tests/expectations/lifetime_arg.tag.c":"54fc3164b2ec51a555fc98685ade1f4b46026cf5108ea238b7fef94059490264","tests/expectations/lifetime_arg.tag.compat.c":"b5e98c37d9e22e9c4b692f560872926977058aaa7a93634d45adbe4eee65df18","tests/expectations/lifetime_arg.tag.pyx":"41fa3947bcbd19b38f2eef40440535fc02e4351982c03991028131cb8b34243a","tests/expectations/linestyle_cr.both.c":"66018159ecc88a3da9e13953b5fd529ccdbceab9f9f4e6f1abd1f0596e3396a0","tests/expectations/linestyle_cr.both.compat.c":"3d849ad69d3d8673de20fbe25d350d3d89d2b03598057159572dcdad1e53fb01","tests/expectations/linestyle_cr.c":"c47b79a70178b4dec21195bf3ecff48bceff5203a3621f2709a4163713c4777e","tests/expectations/linestyle_cr.compat.c":"9963c2f0101fda33df235e71816d6959662c1374d4ce1395ada0a54160528b04","tests/expectations/linestyle_cr.cpp":"a1f4477d1de11feff1bd6383075f1e66143766563b162e02b630377d391cea60","tests/expectations/linestyle_cr.pyx":"401015e4f3d27c133f67bf2089c1d173d3e5dc8de063e726551fe738dc215e56","tests/expectations/linestyle_cr.tag.c":"b50a6e683e09e118df9d736d8c41558fe9449cd7ea286880af587c1c8cfebf9f","tests/expectations/linestyle_cr.tag.compat.c":"476b857e2ea70bcc0a38791988f8e366ec651eb9293407741a7daff78b0a6c72","tests/expectations/linestyle_cr.tag.pyx":"cd32abba2b2f8a866b251cf424ed3211d091cf59b762c09ca59aaf5100710c16","tests/expectations/linestyle_crlf.both.c":"755a99b1e933766ea9801a1ce117c2f997b0fa6b2c5137912fb65a22cf0335bd","tests/expectations/linestyle_crlf.both.compat.c":"9ea5a984f8c6948762c4fe9a2fc636c21007df7653b1fd0092251fdc417c67f6","tests/expectations/linestyle_crlf.c":"8e5c12fba506818fb7843e9955d23cd400d185a550b0232361740e6ed899c733","tests/expectations/linestyle_crlf.compat.c":"a95bed74fc25acfbd9385e75d9047f1b49b813cd06cf342a0542b3ddcbe99ace","tests/expectations/linestyle_crlf.cpp":"12f0ea9dce436788bb0e63078085fa2a07caa8af17ecbe65da58c65cdc3cb47f","tests/expectations/linestyle_crlf.pyx":"7650edb5a4f2b1137f44a61bcc7b08ab946a80f8f7a6e626949e6a4ac02b370d","tests/expectations/linestyle_crlf.tag.c":"6b420ef3c54620e8eeb287a0c4df434521d9448dc56b464ecac8ccbe95c07ca6","tests/expectations/linestyle_crlf.tag.compat.c":"f46844a888c93b7068a4fa19351aaa6e4b6b16edf1f9a2e02650e6ec89e3813f","tests/expectations/linestyle_crlf.tag.pyx":"4d3251841193e79a33b97cf932c04b1cf68f0e7effaa3d8c1590291589e752d1","tests/expectations/linestyle_lf.both.c":"ffec23096e4d365160f926c800be026e7e7638ccfd38963d3a93eb1c2a7c0fec","tests/expectations/linestyle_lf.both.compat.c":"2221088f3b4fe1b7683bcbb2ea3e96723e1764b3ad3bc83cf58626839fb291ba","tests/expectations/linestyle_lf.c":"8ceccd798cd6034abac6b31b3f6cd5d4c1911bdb6da3a46235d4a12c30dff29b","tests/expectations/linestyle_lf.compat.c":"24d70a7beaffa4dd1e22f6c3b8fb76ab72acbffa7806e41c0b7057dffab969a7","tests/expectations/linestyle_lf.cpp":"abee092cf4bcebc00fd7f242ac1f9aa28b80f589f7c9bfc34a6ed1c07e82267b","tests/expectations/linestyle_lf.pyx":"a6e7f087939ecbaf9dcd548e8ffb1b19e74cbf2206c95d07f3390a0588191b37","tests/expectations/linestyle_lf.tag.c":"9b87b10e928fda7709575f3a6ae449c00e111aca5082e45e4765883cae39e1b9","tests/expectations/linestyle_lf.tag.compat.c":"f4ad723de21bdc3a88122f0582a32b6bfc16a5f5618b638331e1fb836f2d5b00","tests/expectations/linestyle_lf.tag.pyx":"575ee9f32e8490cb8d5c3146dcba935e45d865a5be633d8a69747ef77b87c204","tests/expectations/literal_target.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/literal_target.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/literal_target.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/mangle.both.c":"88d970e66abcf79d61bd52cd47e514bfa4fd859894323df5bf2f083f80ac4e0d","tests/expectations/mangle.both.compat.c":"13b5ef25d4a47707e62de9d924eb77d30d269b7128f86ed80b9657a98667a50c","tests/expectations/mangle.c":"8a7feb1d905a5155570d0b445014697ef7c0add1307e030e4fcfa36f4251acbe","tests/expectations/mangle.compat.c":"2fd8fc643ee24c15263f6160a5dd050e35475b375b48922f959402a091ed341a","tests/expectations/mangle.cpp":"537fdc0ca1cf479dafab28e40bd8dbf6b1afd0eaa57b59e6aa01116879b4ea8f","tests/expectations/mangle.pyx":"10fba6e4c29fc836547c2da6cfc55a1061d085f8bff910ff6fce2b620b82941e","tests/expectations/mangle.tag.c":"092c8bd77ee925c301dbe36ed66f849da9f6fa4b12a33283114c6b02fad192b8","tests/expectations/mangle.tag.compat.c":"18cbe572bbbe5177bb299a077b2f16178fca41826b2bd9255d200127d21329cd","tests/expectations/mangle.tag.pyx":"ed46ed2725f9770377f07c01d87726b5b098e8384ce3fd116125303a638f9dea","tests/expectations/manuallydrop.both.c":"a498841bc0733dc2292c5939947851612b901a02fc2c2ad9bc60636450b47240","tests/expectations/manuallydrop.both.compat.c":"b14fa50b138e98752152e6650ba872198bc358c0af8cb830e247e6e6f12e6fae","tests/expectations/manuallydrop.c":"21927680697b6127e2168576055dff8d69d2d253debd7b9455c6aa0863d8c74d","tests/expectations/manuallydrop.compat.c":"9c7a87ea0e2d19b615e5ec8cf7d37c95eb9dc146330adb0f9c4af1585e3d0e39","tests/expectations/manuallydrop.cpp":"21ece2b6da294f6059f55fd56fc06967ecde5a038967ccb8681d65bfb371ab85","tests/expectations/manuallydrop.pyx":"a5bce0fcb482fd981592b2aa38f692ab2a9c7fefef4840ce8da82a5253958b9f","tests/expectations/manuallydrop.tag.c":"4870a7484b157d3df0d418f4de16dd69ed635d974fe85b0ce0bb4c455884ba2e","tests/expectations/manuallydrop.tag.compat.c":"e4bfeebbd0d403e2dadc92b4cf0686d8356efa578ebafd62ffa43347794613eb","tests/expectations/manuallydrop.tag.pyx":"49058f688f67beb2a54c9baf9c3c4bf174c59397d21559abf4a8fa2fa3a800e4","tests/expectations/maybeuninit.both.c":"a63ba08c83ed7a82627964e29f5490e6dfd9f5c0440817a1bcca82d4c8f6ec5d","tests/expectations/maybeuninit.both.compat.c":"a51540ed9db1f7c8c4274010b25a35f231ad8204958c57cd2631aed2ab326a90","tests/expectations/maybeuninit.c":"1c62b5405efae8f1155597b56e3cedc974d538f44ec2629465ff37d1c357956b","tests/expectations/maybeuninit.compat.c":"4587d6a224c958219bf9a57d0673d1543068c6741713a7a0a85ae9b7be1efb4f","tests/expectations/maybeuninit.cpp":"aca6865910f5ccaca1188fc1ca0d071ba59a77e4ff1f45e686e49137d3f55e66","tests/expectations/maybeuninit.pyx":"89445e1baa2f02ce48d82ffc257aa8570d2f920f40d5b516c68512d96a3d6ff8","tests/expectations/maybeuninit.tag.c":"a262317d95f08c3f818f18177218ee10b3d372c43f6171da7aece01259d64069","tests/expectations/maybeuninit.tag.compat.c":"6626c55f78f27349c24b9ae1972f0b3463e77e02145223963bd9d93068cdc5cd","tests/expectations/maybeuninit.tag.pyx":"8ccbfb67f0dabb18d9af5ec6afc77e7c8ef33c71fdd5fe01ef9b99f9e9d7975f","tests/expectations/mod_2015.both.c":"4d42dc63bf6733f16e0b7db00b0067bad9a4e9e66ec1784bf3fbd195cb0ad9ec","tests/expectations/mod_2015.both.compat.c":"29a4abcfab680f6d5d9d49f47024cc933a921ba705fcac4ea6ad15ddb7a225c9","tests/expectations/mod_2015.c":"93ffb87f08257b4872003cee883183b6d4ede3e22e8c886341c919a7710c3589","tests/expectations/mod_2015.compat.c":"db3427f121357249d187be57b97b616ac65f9c9b785ac3f72f15e33c39093e27","tests/expectations/mod_2015.cpp":"6e9011a8513c99b756d5c793e28a416d652f374a177935711a164abf1f924f6a","tests/expectations/mod_2015.pyx":"603b9887af457653c7357c13bf11570270f6a43f4c40ee2cb27200739bb3af9e","tests/expectations/mod_2015.tag.c":"ffbf8e8fbe6d80000235a6535fb21ae30482142eb1c531c3bf1be75b4c60e354","tests/expectations/mod_2015.tag.compat.c":"90c690aa404e56f5081d96b43cd221ac8e666092bdec798036c7cc37d2929091","tests/expectations/mod_2015.tag.pyx":"c88d0e2d99ff83f5e40ae941edfc3393b195aa7037c867863439f256cc2c0e39","tests/expectations/mod_2018.both.c":"5be9bc903ebcc592c98c584ee20c466772f1f33112e25ce685882a1bacb2c9f9","tests/expectations/mod_2018.both.compat.c":"611b8d84e32416d3add4563d7a25c02de906ed74631efb63ff779df5caac72ea","tests/expectations/mod_2018.c":"1e16affa30b8d51ec6caa6d7153a126f74a6f953625ca40a9bc384da4e2575ae","tests/expectations/mod_2018.compat.c":"44dceb2e36932503d3cb90745479b415f222d04482c1b39cf31ddd6034aaeb77","tests/expectations/mod_2018.cpp":"640252162e835da73383acb704b01ad4f9286b1d68d8c1387de55c564ca7eafc","tests/expectations/mod_2018.pyx":"370fde411356d674dcbf6bae3dc375720f3704d3639a5602b8552d337f452869","tests/expectations/mod_2018.tag.c":"7e47259ead3a180919f3c960308c5f3233a8a48d0d921ca4236a5e064ceb75b9","tests/expectations/mod_2018.tag.compat.c":"9db156388ba66c6f218d99aa870b1908982106271c85e08889e03ee106775557","tests/expectations/mod_2018.tag.pyx":"cb159adc7388df316dedf0a1f7c67fa116235c7fc56befefe0ec206449db3088","tests/expectations/mod_attr.both.c":"e470259bbea62c1304c3b860d803d5c731a0de48351d71b5964e469c9b1630a5","tests/expectations/mod_attr.both.compat.c":"1df6dab72e8053d5556489e14774d3565ddb9815629169623b53c4b100c942f2","tests/expectations/mod_attr.c":"36b7399b5feddc4f4624706a8efb859f0690f1bd790979ae00963a53c399b486","tests/expectations/mod_attr.compat.c":"421356a463fcc7b8009f6e9f7fcb231735138cd8b00994db220d4fba7033dd0a","tests/expectations/mod_attr.cpp":"ce54146b0300eb463aabd53a598a13ea200d75739b1f747afb64dcad72568bd0","tests/expectations/mod_attr.pyx":"efcbf28926b8dba7527ca7a3959ee170f21b95469610087b5a7a1f59d836a717","tests/expectations/mod_attr.tag.c":"26fb16ec5661935512120ea53a2f0a750c232b285181692342bc3b29c1626ded","tests/expectations/mod_attr.tag.compat.c":"9738e2d7525db7ca32eb01153bacef69a46e185ceb18045bf23462c9fd8ac9d0","tests/expectations/mod_attr.tag.pyx":"25d56fef07810075ac8e3613509aeb14e54101d1e6cb8f7930bf51dfcf53a7b6","tests/expectations/mod_path.both.c":"1d7ba633ee3311f1b1dac786a36977558fd1cc42a5fc108a0045de1cbb58c142","tests/expectations/mod_path.both.compat.c":"50705d130b54224f6781d8fe1783036be0162b50194018b3d30033796821c56b","tests/expectations/mod_path.c":"358500d2996dd971630376eef9816379576625619b3516e5d3de5cc74bbefc6f","tests/expectations/mod_path.compat.c":"cd2604b2ffed7bfa17327ed654370e058b913afaaa9461454ab6da6bfd4a6b6d","tests/expectations/mod_path.cpp":"ce490dfba7b336456bd443001c848c71c6c7160fcab5a8615ec825cb6c8634ce","tests/expectations/mod_path.pyx":"23c7cd14eb5294331834dbb6645e4545cbf887b90458a8be24c9f927496710b4","tests/expectations/mod_path.tag.c":"8c849f6a71fd73720b23141b0498400800dd1282bb47930855e2f12c80544777","tests/expectations/mod_path.tag.compat.c":"c6ba516c29bf70a7234f85acaeaa98fa5720eb386f0b0c03e042262c476e0eb6","tests/expectations/mod_path.tag.pyx":"8e8d99e0a9c29e8cc85efef7d5439d0f6e3d62c9102f955cd9794b7d432e8321","tests/expectations/monomorph_1.both.c":"10d69c5368f5995d614425992d794936ebbd46fe15fd8a50ff9c0cae0792b49f","tests/expectations/monomorph_1.both.compat.c":"a48fca0cc1856a58ae7db2893abbb9879c70248561b81d9c75dfe252be3e27ee","tests/expectations/monomorph_1.c":"56f782e0e7ed4af20b54b9c1a1fa32ccbb421f74953827e77e4a34374a1f99f9","tests/expectations/monomorph_1.compat.c":"2481def545a3d016b1480752266b5a1460e30f972bc532ac55fad28329fc8eae","tests/expectations/monomorph_1.cpp":"76c9f60394d2b33f784e8ea47d4a45247ded703cab9d3d9b92e7c3eafb99bd2d","tests/expectations/monomorph_1.pyx":"19b26eee97461802d415845e86e8b13905d5019c406bbc01a2c9f0c95040741a","tests/expectations/monomorph_1.tag.c":"bdc4017baf04090f62c8b18d75824bdff0fb48f0b6ba2013eb8a594d5859702e","tests/expectations/monomorph_1.tag.compat.c":"e03f90337eca949628d86dd393c17ef1bbac240561edeec1f6365b71bd7035b1","tests/expectations/monomorph_1.tag.pyx":"d116bc45b720243a572769bc08a65d8df36d52be82c3e306e5c60e56799f9a39","tests/expectations/monomorph_2.both.c":"27440ed92ed1cb717dca92703ee85a0bf1b16122fe99f2e2bf4320b05c8fbd0b","tests/expectations/monomorph_2.both.compat.c":"fb4754a776aaa49155c538e90dd8de978cea7cfc63e9ca846d2ed7b46b66e1f5","tests/expectations/monomorph_2.c":"ad18b5898aa40134b766636adb7963140d9592028b409252709489c07321ed69","tests/expectations/monomorph_2.compat.c":"7392c90cfed6097d93892eaca523b90fa57336cd9489fd64e7e15e85f7600076","tests/expectations/monomorph_2.cpp":"95889ebbb57c509e6ea8d8b79e692b9d2ee3ba4343b1492cfbcf0b6eed185f26","tests/expectations/monomorph_2.pyx":"be1027e30cfe3b0038061cd8662384e23f70ce442fd9692e8f099c1f963a5989","tests/expectations/monomorph_2.tag.c":"b8be9d57b0021ad9fcaa7b905511aa14a412299ac9ff6680f273a3e999e86cfd","tests/expectations/monomorph_2.tag.compat.c":"ea568e6dde68ec79d95488c8f2682495d6135f40266e901642cff45295668a5c","tests/expectations/monomorph_2.tag.pyx":"726ca00603356eb5b2f13e4ab4dbefd478954e9127960e4d623c2b003c446fcf","tests/expectations/monomorph_3.both.c":"1db37a701a9843a87ab9dc5b3170a70d2a3e9dfc2ee1d5131ea28738f6eb03f8","tests/expectations/monomorph_3.both.compat.c":"f3339fa5db4d59b08e5b6b1ca2f047a422249e71ccbba54cf3d4cefb6608063c","tests/expectations/monomorph_3.c":"6f5150caf205ed2c4ce1f894ccc41036c336ec6171aaf1c5ea6b4995474a53a0","tests/expectations/monomorph_3.compat.c":"261747e051bd071b480bd46841e2598d7c829d62fe4397a1602a6a1f77c833c4","tests/expectations/monomorph_3.cpp":"fbe1c063e47cc1e0b216053db1c1355e0698af8c83b6cb8fedb2f5063194508d","tests/expectations/monomorph_3.pyx":"c4668d54b54e532c5c1486a73769bdb497d552db3818105e2549122e8d08a175","tests/expectations/monomorph_3.tag.c":"0267e4ea206bac3ebaaef30f7dee4f2243cf7f5ffa0e0748f194d3e1fa5635e5","tests/expectations/monomorph_3.tag.compat.c":"3264f932beb090697bad43ecf82018719de18254460fadd7dd6a4c14b29871aa","tests/expectations/monomorph_3.tag.pyx":"106f50decd972650f25c3db07ed0279e4c6674a9ef22e4e5c5dd2f6a01def21f","tests/expectations/must_use.both.c":"95461e91bfd356405c9f320e0448c63a53f3a683ae21d83ef4bbf111bb7d06d9","tests/expectations/must_use.both.compat.c":"ccd7c9c85eb89e86f12e17e62f5f8182d2323d349f053a0f11ed0473fa012f4a","tests/expectations/must_use.c":"488e06c3e6cb76fcf734c807dfe7464d929e581d04c0f968a393c6681caeff70","tests/expectations/must_use.compat.c":"723ef05fd1ecbfa6280683415f11e1f1557048ceed13fdf3bdef6ff285ccca90","tests/expectations/must_use.cpp":"78ef60a4d6c588f97bbf88f81cad3884c45f0b0bfe27af161e220ec48c76a963","tests/expectations/must_use.pyx":"c7530439e1ca8e593be4449d5c85e3ab1649a6a3728cf18b2dd306dfa9fb5538","tests/expectations/must_use.tag.c":"8436ea338277f4b1d1923aab72de491a1b1e4f0104a480913c404fabab4e15b8","tests/expectations/must_use.tag.compat.c":"59ed65a024c04bb8bbea47f172acc4c2c0626e0f480cf3013f848a0c481fc799","tests/expectations/must_use.tag.pyx":"84f2013e619d7447308af15e1f75a3d86abe63a9494a4c3c1673a29de5ba3791","tests/expectations/namespace_constant.both.c":"e49631bb7ef1c78d3a699417b0fdb496f7411de836413baee26873dec16e6ce1","tests/expectations/namespace_constant.both.compat.c":"5fde7d256fb56db4dab0918960faf228c24c53cce2e5660f43296c7d2eae6b7f","tests/expectations/namespace_constant.c":"f86295772c831a2e12da48314a18829301a43c476c62953c14ccaac4a85f0a48","tests/expectations/namespace_constant.compat.c":"bb1230c6476d773c14ddc0027a8b713b364d5f7dee03861e2999ba3968e8bc1c","tests/expectations/namespace_constant.cpp":"4923d9ef69010e9d515c5de5661dc5b91fd1c6531de5744abc75d6c4cfd69dd8","tests/expectations/namespace_constant.pyx":"2501710bd9698215badfe51ae410b870cdd6c415cba39ea9f434385d86e18090","tests/expectations/namespace_constant.tag.c":"1e3f5dc75e6c49f6ac9a223abf7fd35743465d7376116eb435c31befbd58674a","tests/expectations/namespace_constant.tag.compat.c":"5e45fe7f4600288ad2a5e545f873fff0d43e95c561e03c5afe5b596d0d144306","tests/expectations/namespace_constant.tag.pyx":"665c3b9423175a1233f1fe0cd466fd4d73d59f813fd3079899b62b2015e6902c","tests/expectations/namespaces_constant.both.c":"e49631bb7ef1c78d3a699417b0fdb496f7411de836413baee26873dec16e6ce1","tests/expectations/namespaces_constant.both.compat.c":"129a4b4f393636afc87e42d7f498e5fca2e921c77407fc4cf79da1d54da0fdac","tests/expectations/namespaces_constant.c":"f86295772c831a2e12da48314a18829301a43c476c62953c14ccaac4a85f0a48","tests/expectations/namespaces_constant.compat.c":"1e446aa818a096bb981340f14470e11ced8cf9dc061fc887d99046c53ccb761b","tests/expectations/namespaces_constant.cpp":"ec82f0a6cbb28fb99e849791db08d50335ce19f6a5e981b7a7482f0a999eb7f6","tests/expectations/namespaces_constant.pyx":"2501710bd9698215badfe51ae410b870cdd6c415cba39ea9f434385d86e18090","tests/expectations/namespaces_constant.tag.c":"1e3f5dc75e6c49f6ac9a223abf7fd35743465d7376116eb435c31befbd58674a","tests/expectations/namespaces_constant.tag.compat.c":"c6771d0b00159fde06de09d6074537cfd19d86f0ea70af8bc5c003dcbca2e96a","tests/expectations/namespaces_constant.tag.pyx":"665c3b9423175a1233f1fe0cd466fd4d73d59f813fd3079899b62b2015e6902c","tests/expectations/nested_import.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/nested_import.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/nested_import.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/no_includes.c":"7a291fbd7336e914b26137ad41ec8bd4b32339d54165147533cdb64b60fb92ef","tests/expectations/no_includes.compat.c":"9aa00142d44fcb11d131f63d3962c7c9a81aec881f0da8fef1f90cbd8378ea5b","tests/expectations/no_includes.cpp":"ccc81037551361d758874141fb95165c57473faf66e500830ad4b40fbe00e906","tests/expectations/no_includes.pyx":"2dfb2777f23cfd907d3de10774c020dec80fb510b8d850a2725f133afb5fa038","tests/expectations/nonnull.both.c":"bc89aae611a1bdf1ba1a2e073e6ef6bdc1e4c2649dbe53becc82764b5ae9ab02","tests/expectations/nonnull.both.compat.c":"d1f99b090cc1d952e3515d46680564948a5fbd2f58d11f5b23ac0f382c209df0","tests/expectations/nonnull.c":"e46f7cc997ce798dfdfc78d64ed71e9157d2b69f3b122c2caf09fe412560aab3","tests/expectations/nonnull.compat.c":"b453816610023cc1f27b8d44261c3fb927f1fff9e4b67e58658b1c89c02e71df","tests/expectations/nonnull.cpp":"fba2388c683faa872f7e6087be9a632c6400cff41d12f92736836abfa1a5af71","tests/expectations/nonnull.pyx":"97eb98c1cd54c2957df9845008eff32b782b2f32f84cd1a0214b8a9a131763dc","tests/expectations/nonnull.tag.c":"9968d2607a64b8f21efe2c9d255da6ff8c606eca82e241b1426a31e5a5650af0","tests/expectations/nonnull.tag.compat.c":"32a9bdf793c01fc90b414e14f7255114402340c5b79f0c2092ce5a0e14c0c622","tests/expectations/nonnull.tag.pyx":"30f8c77d14ae34ea152e697936ab2dbc3a8b5feb9a1fd8711c6a9c8967fd657b","tests/expectations/nonnull_attribute.both.c":"2b46102c86d19bcaed20026b879d429d1d55f785624cc7c80af2debe3b3ff46e","tests/expectations/nonnull_attribute.both.compat.c":"9f08d028de8a199057b5b837b26a5510959a7bea4ebf9b0ea8dd98896162b7fe","tests/expectations/nonnull_attribute.c":"661d8728beda90b65721fc48541b1e532e01011b8ce4d1479da227ca9dbbd5b3","tests/expectations/nonnull_attribute.compat.c":"39d76bd914641c3e8fc8d5c803290901872b7f35069acb57b92a367cfdce2b71","tests/expectations/nonnull_attribute.cpp":"0f6bb96180c6352bccf834ff30122c85578b3b0a9c28264d45704bf894431e92","tests/expectations/nonnull_attribute.pyx":"1602314d618d995a29b1cd864aa30f4827512bae8adaafbe8ae4754b193e4924","tests/expectations/nonnull_attribute.tag.c":"c53457574ee33cbb888c851ee016821ec3213b5ef360831fabd70d781e7fb292","tests/expectations/nonnull_attribute.tag.compat.c":"45a99a1efc18db8faee7f396e4e4025ca20dfcd9d7e35be532e77c2e7ac08780","tests/expectations/nonnull_attribute.tag.pyx":"d4083a527238f5786acfbdbb0b7ecf19621787a726ecedaa6649e76d1fc33165","tests/expectations/nonzero.both.c":"de3b7de2c7b04cc7ffef576238569efbe68878e2a5a0e8a61f846e6273c57c5b","tests/expectations/nonzero.both.compat.c":"3a387b8b306029152bdaf7a3cd50c8a2e7d660ade5f564a35d36821d4cf86694","tests/expectations/nonzero.c":"d383fbd9f7fed933bad88d90a5b668c7ec12c3659d4dcd4849e8acec45a40777","tests/expectations/nonzero.compat.c":"450edf13cea98960d7baa192f2024026f799f0d6bdf9a6b9761a69583be3409f","tests/expectations/nonzero.cpp":"b256e4467c238cf428345d6910f7fc9efbf5717c98fe58161ef623f73f568f39","tests/expectations/nonzero.pyx":"a0dcd9361bdb3dabe367da5e9da818aede4f0519478204a3ba18cb300a22c9ed","tests/expectations/nonzero.tag.c":"083f047fcf9db6970f30f64f78b93d4875aecc94f5b1fa66ece2e90c5073133e","tests/expectations/nonzero.tag.compat.c":"2110e5eeda0a97dbc98254408de095dacad2a1a3c5a19eacbdf2fecc314e3ac5","tests/expectations/nonzero.tag.pyx":"6843118de0204e84271957bf9bd90349261991ff3391706b7386ab38166ddc70","tests/expectations/opaque.both.c":"b30710454b62658d4918ce7201bc48574daf3e48559d70535532282c953e4a6d","tests/expectations/opaque.both.compat.c":"e8c8f7b4606c65a4569b04bacb2573ccc78e3199c75d55ac4857e258e26a1024","tests/expectations/opaque.c":"8e59e82e0dcc94a546b057b8798d4dc4741a0c400d407c062a3f275f6002c101","tests/expectations/opaque.compat.c":"ae35afdbe3cf3e068ab031a63265f4b94d205b1bb2c3a27c1554c90a3ef06591","tests/expectations/opaque.cpp":"1f6d6d69806dbc0df22f9817f7826f81a103fa7e144f4bb4c15f81ff8884f8db","tests/expectations/opaque.pyx":"621874f934c702e4ac17a23e1d35e59269300033dbc9304aa780badbc1531bb5","tests/expectations/opaque.tag.c":"23759de134ada5d93d0628de216317cbd7dc81dd2628742cb32971ec98311f90","tests/expectations/opaque.tag.compat.c":"4a49cfe48f53d84457e5892597d61fb278a66b3d21a94f7de12032c431e3d66e","tests/expectations/opaque.tag.pyx":"4015405e384c38acb9f7f592c566aa36d6200adf862c14b691eeeb79d95031fc","tests/expectations/pin.both.c":"ca5f471174d398194cea1dcbc6cc4a92917b0dc4c40a4e4783d6cbc25ffea7b0","tests/expectations/pin.both.compat.c":"20bef811ce72a83dbf46f0610ce5522cd83b4f01dad56200bc312e457c4cc72d","tests/expectations/pin.c":"ee1df686f63a00e47e4b2d70400ebca00d87365a5e5420046a8eed2cc98b908b","tests/expectations/pin.compat.c":"bae78af72ef3493fa81916ffdde6931302ef690447e67ec74bc7cd39c8a47f3e","tests/expectations/pin.cpp":"2696ff27dc5d3029a6822662efc61af37b692d208147397da3ef6ceee982d208","tests/expectations/pin.pyx":"a316d36d8f682ed493ed3569a8a760cd2387c1254d1d591f69344f17b623cf37","tests/expectations/pin.tag.c":"295dc9beb12444d0acf573defa070de3cde6277c97586f6293f5fca0575299de","tests/expectations/pin.tag.compat.c":"fe4686b3f3bf3cc7e0917e6826a8d4cf9c0f23ee034d4e6b3487b5f9fdb2bdbc","tests/expectations/pin.tag.pyx":"25c42afbb22d7582506a15b558b7ae192736966d2c2ad1ab3516b8b03679415a","tests/expectations/pragma_once.c":"95e7271709e92cc423fffba8cd534b6cd9c5d4754d5cc6dcbfe9a539f44e2c75","tests/expectations/pragma_once.compat.c":"906e661e80125cb01c762351e5bcb7981428aaf3304b6ab20c6d6932468656d3","tests/expectations/pragma_once.cpp":"d1892017945637ca6801719e8cd5002ec64e456d3b2d3b2c04eb337af069ab4f","tests/expectations/pragma_once.pyx":"3a86c97c4392932f53b8a0f6ebb436ab37c67cfa31e569322fc953b38aa34de1","tests/expectations/prefix.both.c":"6b2b07a2ffc19523144d86f31bb19cb696573091037cbdd077b9dd71ba530ccb","tests/expectations/prefix.both.compat.c":"62404d5616108de3a2acaeb43b2ae6b46286f58411cba8a0be8bf64768b0b822","tests/expectations/prefix.c":"46b860a97e645cd5bd80256dffefa934fa79c18159476bccb45adb757cce441a","tests/expectations/prefix.compat.c":"781e5cb6e1384cd9be9b72db829cf551b3b5c4ffdc17c12774db01389973bd84","tests/expectations/prefix.cpp":"fa42c2896e01eb387a6cc246d9ea4b352dc5e8a064b2b901887c4931fed5e500","tests/expectations/prefix.pyx":"2628e42be93e502b761838b826a62fe447cdaf8e5b9e5c7936fa32190ddf3359","tests/expectations/prefix.tag.c":"89007bd5e6f08452bb8754b2393017e04b1ace8d138cfc25904df019eaf4b08b","tests/expectations/prefix.tag.compat.c":"1859b9de1d0bce6191d5b460b0ad97153e9a696d960556a589f0ce52b2c4aacb","tests/expectations/prefix.tag.pyx":"28c6ef6d967e4922956299a34f9f956187a551a9af227938e1536a08f8b1379b","tests/expectations/prefixed_struct_literal.both.c":"9559f5424ca4828af65d221bbdd30793289b997dac8ee6352414276cf731785b","tests/expectations/prefixed_struct_literal.both.compat.c":"08b628769f3f69e4344023118fccd0f65f5d73b1a2dbed1e8cf56945eee1c6be","tests/expectations/prefixed_struct_literal.c":"99a2da6d8da7278015d9a58df331562fd81813453856d302e3675a62e9bb271d","tests/expectations/prefixed_struct_literal.compat.c":"2c9a529e318c2772d804348938406ac2482ddad4792a08fe4e929487668f543a","tests/expectations/prefixed_struct_literal.cpp":"c7c1646ee95fe973e6b08f3e1af0cf6802997d455259928d1315cbf266324a45","tests/expectations/prefixed_struct_literal.pyx":"def6e2fa920533665063b601c53bc104deeac1354463585cfa90fdb71a73a2bd","tests/expectations/prefixed_struct_literal.tag.c":"b68b97ac636ad4d9d87f42135b06fb7aee7c7a5fbff99d82eda74c1ebb5809e0","tests/expectations/prefixed_struct_literal.tag.compat.c":"ed20719d7f7639122f43c8b3aff649c88724c773903dd3db20272fe1bce9ebf5","tests/expectations/prefixed_struct_literal.tag.pyx":"b7ba0af6fa6e76b3dda926ec70325c5c7dbea07059c284d990310e5c63a0e1d3","tests/expectations/prefixed_struct_literal_deep.both.c":"32753f1450ab56384e15112615099cbf7e05062ccd2dc59fc3a729fd884e6469","tests/expectations/prefixed_struct_literal_deep.both.compat.c":"2c421ab89a10c32592af85876da4a71172c24e36ca2db6e5f3a5723866ebb0c5","tests/expectations/prefixed_struct_literal_deep.c":"997e66ee545f1a392e2cdf14f92fe3ea5fbfa5ff9fddb545c14b1346baf55802","tests/expectations/prefixed_struct_literal_deep.compat.c":"6afaeb3c4aca7f73957c55c9b6d153de0f6c410227d9004f2664db291e56d760","tests/expectations/prefixed_struct_literal_deep.cpp":"4e459f43d6e9656fa9bf674a721b743132a8cc42b3e35b0bc1718d532113d184","tests/expectations/prefixed_struct_literal_deep.pyx":"7ed0799231747875564eb43e78b18e0f803279b625c9bd845e8bf5ab9452e5cd","tests/expectations/prefixed_struct_literal_deep.tag.c":"dc18b95c737546333a0c116cfecc677556584a38d1f2e60a237d751c1e34661c","tests/expectations/prefixed_struct_literal_deep.tag.compat.c":"bc01145cd2692ad37659eea40f4097faa88602cbd8cb8a410bc971976f68c84e","tests/expectations/prefixed_struct_literal_deep.tag.pyx":"26498cb3a8152a1a50a12ed2d9c706959d6b90d39afc14158f4cd9d462474b84","tests/expectations/ptrs_as_arrays.c":"f23c55ffda78e07d22ad04db76dd3b49c2658eb919e709caa904820a510c8b17","tests/expectations/ptrs_as_arrays.compat.c":"dd7d3fc890b675c397f28ef905a5114047d0cbec79a1acadab5e61f9522fdb02","tests/expectations/ptrs_as_arrays.cpp":"ccc94fdc2e5418fb1c6e5a530caaab68459943d42d6586df46ea5c9aacc0676b","tests/expectations/ptrs_as_arrays.pyx":"3eb5550015d66109f9caf8d19f9498c8948b86aa3a950d0465145dd0618843ea","tests/expectations/raw_ident.both.c":"91ee9b892383769b89d80473183e570eea10bd2e50e95ec0ad77ba0446424fed","tests/expectations/raw_ident.both.compat.c":"0bc56b066457e8d8455ed36b58d714daa7739b4e9ca960d81cca5dd89f671814","tests/expectations/raw_ident.c":"b8e7d10a721b94645908abee01ca61b9450c7f6033800f9fa941ea589290cd4b","tests/expectations/raw_ident.compat.c":"3ad77d90cd04d55f00e1ace8ce91bfe51152adf19c9459cb9553d9376713e3a1","tests/expectations/raw_ident.cpp":"b8d1a964670429e5d3bab54df5b59a6b13c85bf1cc4ba3b44a7368262b2b6e7d","tests/expectations/raw_ident.pyx":"c13215aea9c776fd86a25e7d850170ae9d2f7d66f41c5a061503375732f52642","tests/expectations/raw_ident.tag.c":"7f8a8163ff099d62098af621f25e26c30e5e9a94b006004596f1ba33a08b569d","tests/expectations/raw_ident.tag.compat.c":"fc4f13d7a81c2c2643b60abec8b7e01218a5e20a7e77427feaa5413c00261682","tests/expectations/raw_ident.tag.pyx":"5f9809b9d80930479bf9807b1e5b897ec6a39a58845cf027e8563bd03e901b9c","tests/expectations/raw_lines.c":"026afd7d10e04be3dbb480078a3e9c9c827ae3f97e688f17d7428fffec2b0264","tests/expectations/raw_lines.compat.c":"3f8f40efb683163f6d9451de6eeb454cfc05f17e7af74edca359dd08ef57b3c0","tests/expectations/raw_lines.cpp":"921d9cde3bc1c797b93a5b329e0d34160e53559b3c52effc83d4c8f1507cbfb3","tests/expectations/raw_lines.pyx":"4af0f1e258276f5da540c0405e8f8a5e5d8904d658736d0c1ba83fdd3b4ccfdb","tests/expectations/rename.both.c":"77faa1f85cdc9b812e4803c75248a6494ed75d16ecd24624c1149f9c81069bda","tests/expectations/rename.both.compat.c":"c9518f693ca9df5ee1abdd18c9945acb1b74ffb3b150a82772d6b01ae6a9b7ce","tests/expectations/rename.c":"8263595d6613ae047750f23e842ee77ff503f6408a557049ffdbfc16286be38b","tests/expectations/rename.compat.c":"1756807a3c51e53a3da260cdbfc91450bd54c8b22fd27e79ce673b0713114260","tests/expectations/rename.cpp":"f4ee5fd92554a846e81f27355a25bb660429c6bb985ee7a883cf5b8fa32eb658","tests/expectations/rename.pyx":"2142172189e88fe19ca0d44560ec218af5557841c7214585b429be62ab245fb8","tests/expectations/rename.tag.c":"60018fdaae3750e2c60c368fe9a195027ba6ccae03a12533bbaeeb04a96d02dc","tests/expectations/rename.tag.compat.c":"61bbb70212dc73046e6be1a09250f1ba8163506ef53b4f5274abf383c7b9f8ee","tests/expectations/rename.tag.pyx":"d13f5ea7f6266966171ff07211e172e8da9b79315ccc5e87ddc53a6df7d668e2","tests/expectations/rename_case.c":"b7c67bf7fcdadb3a44f3e717f2d22131dd5d9935aabc22f28c5119f45d5ecdbe","tests/expectations/rename_case.compat.c":"307903360c05d387a1107b4c83639b86baeccf25a6590b271cede87319905613","tests/expectations/rename_case.cpp":"2e1c0dd0bd817ba7f0a099b6c49ce4a6d682408f6d0ba78163949f1b8c1e30ce","tests/expectations/rename_case.pyx":"8af444e46fef91aa30015e166b88a819e9b7e9040dc85681b6f9f8d95c1ffecb","tests/expectations/rename_crate.both.c":"0b18c131a60be4411fbaec9e05e1295c5ef7b6481435458e6626888929ef64ee","tests/expectations/rename_crate.both.compat.c":"584989132f23548fcb4efefc50a1d486c61a1096d979bbcc226b7d88048a7284","tests/expectations/rename_crate.c":"bfa98a6eb12d66ff783f4ccfc95e9f387241f4651fd4972d35c714aa11790a55","tests/expectations/rename_crate.compat.c":"620bd8a3177b1b85eef545054a2c0da7734acdc6cdf0de006550a5bf0b1f1463","tests/expectations/rename_crate.cpp":"bcd672b04df587cfdbff965a26c4036cefe4a32a0b0bc43f8afe12da6925062a","tests/expectations/rename_crate.pyx":"704067e5ed8c2a73a38d118b6c9de4d16fc16047b82e0ef5d20410aff3ceb51a","tests/expectations/rename_crate.tag.c":"2b7ca2afb0e0f30e8f9aba9f023879d34683d11da534263f40544c13df63fa6f","tests/expectations/rename_crate.tag.compat.c":"3d1a5aa501d0a5fe5fd729599edb1e1aa312b25dc7c5131f4dac351e31b8a283","tests/expectations/rename_crate.tag.pyx":"1f76217c43716d5a0c75c94ec2f5324ab4f65377897a727e2b82f14b4b27f823","tests/expectations/renaming_overrides_prefixing.both.c":"77c7dd26dc089205d7bad2f5ddaf80486425abf35c4dff952dc5e555ea1237d8","tests/expectations/renaming_overrides_prefixing.both.compat.c":"6220291f381b1503f344d4f5b2ffaae4a5bddb5385e8bc9ff71219f78fd5008e","tests/expectations/renaming_overrides_prefixing.c":"9c75ec110a52903b63e3174a636f0bd75c6d3daf03d041eaac1c3853d15cdac4","tests/expectations/renaming_overrides_prefixing.compat.c":"329934f453884687b371a9859a67f85270b56c6ff374a78cb03745b2cef7c4a6","tests/expectations/renaming_overrides_prefixing.cpp":"1b50bb928516eb1fddf1345dca133645fe271533ff7b0ddb106ce66ec1ffef62","tests/expectations/renaming_overrides_prefixing.pyx":"f739ece019f92a094a2a8ad937c16508f2b261dc8552a6eb0962bef9df69e7d9","tests/expectations/renaming_overrides_prefixing.tag.c":"8dde2e5380b0ecd415c4552aa95e272fbdcc4843bfaadce8845339d04ece4aa3","tests/expectations/renaming_overrides_prefixing.tag.compat.c":"b24513fd3120d796273599deebd8c81c2a40bf08b5ad095b1b6a63c3528a83ae","tests/expectations/renaming_overrides_prefixing.tag.pyx":"47fc898306bc851614103a77648ac89e083cfcbab345df711ccb92baf0750fd4","tests/expectations/reserved.both.c":"8f140f38d0872e5b17351bdb25e5b005ece1af0dd25252ce3c2db9291a459a8c","tests/expectations/reserved.both.compat.c":"089e8e487072489faf686ff79a66542dce5ffb62a70932cc420454e718dc08cf","tests/expectations/reserved.c":"e91ad65c8cb095fd5e391d0e0115714b94fbd5e52a2604861106832ed9e3c0ef","tests/expectations/reserved.compat.c":"ca3b08af39c9dc0b4402f4aa1bf27402b43916429953d8b5c59a489ae62512d6","tests/expectations/reserved.cpp":"a7ac3e2f0a699f5d0192e97812c68793e57a8b5ce07af48b6a9c2ff2a1680b0d","tests/expectations/reserved.pyx":"dcb0d2468b20d98ad1fd7d2ce295247849b492567b2361e75f6e01f935a9f1fd","tests/expectations/reserved.tag.c":"fa21c2123137ae01bb37f1458616922c4dc6ac62c05339f73142702808f1d2f9","tests/expectations/reserved.tag.compat.c":"2ee9b63889ba7a3262829b1a073da665bcafc8fdace7b4c2ed8c750403b597a9","tests/expectations/reserved.tag.pyx":"1c11e2d3b0137af92e64ea65f19c6eb3bc6d42f4da98f118a176ee9bfe5b1626","tests/expectations/sentinel.both.c":"87c249eda8e73ac37b586b6961e2cc0a0b970b793720c0a1552df9edd0fcc2f2","tests/expectations/sentinel.both.compat.c":"bc69a1dde5d2ed402211f979fc5a247b21638641a0869c556d44d6130b7a6845","tests/expectations/sentinel.c":"8c5bf6bd0b04574ed173f0f50f16e4191188a4f8401e05d6724f0eec33d35017","tests/expectations/sentinel.compat.c":"5bbc747d69716b12ed9f4cf3e64ea7b486d5473c86cc9ef4c03485e75437ec8c","tests/expectations/sentinel.cpp":"5c2d05019f8f65de0028ef870737fca9abb7ea177ba0d4dbb68fa5d9f1d1bcaf","tests/expectations/sentinel.pyx":"5d3282346d2c0ff7dfd596d0a7dedcc97d3df153c97c620f9db1584065c9593e","tests/expectations/sentinel.tag.c":"d50caaf5d902934525366f50ff8c85d370039baca0e5cadbbc13982ed7a98456","tests/expectations/sentinel.tag.compat.c":"a1772a029c21095e6431d907e6be39c710bd90cddaaa5612379f02fd026e930d","tests/expectations/sentinel.tag.pyx":"2d695cc04fd973c71b3b028cb783b02d224134ba23ea2691f8b5050b36a4189c","tests/expectations/simplify_option_ptr.both.c":"cc7e41a657e11bc440047bd245c47741b2277689745dd6cef8fb5c7c100c8541","tests/expectations/simplify_option_ptr.both.compat.c":"38a6eda3b72f869b92046bf0fe5de111686edd5651920a0effcac56715768d65","tests/expectations/simplify_option_ptr.c":"5f10f8757f3ed36f74ec3686e60b3b9dea13e961265e53ddd3c99659a9e4ed0a","tests/expectations/simplify_option_ptr.compat.c":"a40f97d0f10003a1e03ebd3d835acb349fbb384517307abbdaf0062578f972f7","tests/expectations/simplify_option_ptr.cpp":"5ffc251e522dacd0a128a607c45a9f93645d7b6b7c00770b4f2831c74efa6bbc","tests/expectations/simplify_option_ptr.pyx":"00936d6685c699b7214ce2024af110cd619015d992147967d2f579d32990e131","tests/expectations/simplify_option_ptr.tag.c":"6b1a96aa61709e545e3629fbb546886fc7ceeab17bbc96f8db50f3c6545929b5","tests/expectations/simplify_option_ptr.tag.compat.c":"9ba3eb34cd2c4fd2dd95c730c5dd4f79d5f188b24b66355488042d6a68274ac1","tests/expectations/simplify_option_ptr.tag.pyx":"519743231de069eab84c3bc4e8ec31a5f009ee34846d9135a9c1df6eaf3eae65","tests/expectations/size_types.c":"76501f91182f958bb08ebd6bb357646e36cfd7bc332fd166789a8a1fbf4cf397","tests/expectations/size_types.compat.c":"0857b5a4ca7bc32f8fdcf84b07e5c9d317a80b469525b61f12bf6f0f6a2e7e69","tests/expectations/size_types.cpp":"79e269afa154855faa3a96a2baf7f3a505fe2d1dacc07d04fcc35060e3c30d0e","tests/expectations/size_types.pyx":"71c927fec8165010be1ab8cfa4add0c86c3b420086a026967071cbb7eb3a91a3","tests/expectations/static.both.c":"6fc6ac1197c8e0bdf393bdd4f99d018057c832f611dd1b37dfbc985f6354bd3c","tests/expectations/static.both.compat.c":"d28d355eae17260fffb96c7903aa2dbdafb4f1ad12cd83a2cd7ec944f12c570b","tests/expectations/static.c":"4a84a7b7c6388ec65e0855c02780f253844256e9b8c9d2c8f9c19a1e67cc729f","tests/expectations/static.compat.c":"298387148c4c870854dbbe81c996575bce7306e640661c3c636a2e811f736dcc","tests/expectations/static.cpp":"a9054d752eaef1e6bd8edb169fbdddfd20f6f0627103ded58ad52d2e316f2a3a","tests/expectations/static.pyx":"7515602ece87657fbc5477cdb75fab6477332aa6964200b5c309fc4158bd7b6c","tests/expectations/static.tag.c":"67cd9094682d5878babe355e6f0036153008eff9a190abcff80d05e4fb3111f8","tests/expectations/static.tag.compat.c":"c132f2e64fd645e415ea99b546c97bca613348c0d4275681ff5079bd55d7b7f5","tests/expectations/static.tag.pyx":"d842f816824dd6bc1337b50bb653cfd44a9348abd6da1c2cc8e04c2773807924","tests/expectations/std_lib.both.c":"8ef283c43e91a9c77174df7af5d3999353e1daac3b0afdea17dbd132a6df22c5","tests/expectations/std_lib.both.compat.c":"997390aad31bdbe204e5aea068ee467de8bc2ed365991d8b514830282f60fba3","tests/expectations/std_lib.c":"8b8f89b986ef595c3cf7ae7604825ab30365406c1fb435fb0a7bfe1ab05f4297","tests/expectations/std_lib.compat.c":"93ce746242cdfe562bf0374584e0a913de41a718cca98ae54adcda44cf5d7a5d","tests/expectations/std_lib.cpp":"2ae1e7c56d054114d49ad95932d436f390bd89b37f763685fe91dee9617376ae","tests/expectations/std_lib.pyx":"b5f57cc4fe57d5132a8d98f1a4f19547e467cf8331870fb65573183f2d0b7730","tests/expectations/std_lib.tag.c":"0e1d6b0d0e41071718034e5940b01da5e45cb17c2f99db7552335c0720b86907","tests/expectations/std_lib.tag.compat.c":"2ee4070a5512b9fe7409c1b3444cda9ac3d7ba28fd17582fa0a461950a76ece6","tests/expectations/std_lib.tag.pyx":"1c8011a2edaa0128e4e90ed3e7ca1bfd0ffbd90d49c097b9f36c755938d08b45","tests/expectations/struct.both.c":"44788c37c8bcb017282501700e2211908547c973b1d67321f31c4c78edbdb7f8","tests/expectations/struct.both.compat.c":"7b06998839a1850750cfb320e1befc3f33537d49add9778e86bdcf575d03bb9c","tests/expectations/struct.c":"3f3a24f56a43dd92290367ed37d3e64562def9f91b1ada89347adb2a686a4e5b","tests/expectations/struct.compat.c":"72027b56ec38931f962b0abea91e94cc179b3588d7d7b4c738013a39c249e3a7","tests/expectations/struct.cpp":"24223fcecc97e832fe70bfc10ed515c4f3da7a4f9bc3517df93ba97ac604e313","tests/expectations/struct.pyx":"d266e1195a387510a1cf49c3d680301dc6d0988e207fd9031cee0dc343dab26b","tests/expectations/struct.tag.c":"98033bb2596a3852351de170e1139499ae39eb5f414c6624353709e4c602fc6f","tests/expectations/struct.tag.compat.c":"5e3b361a41f6a3540c10f632873483a2b295dd8bed5a2701fe498b20aba24704","tests/expectations/struct.tag.pyx":"8a7213ad4f7a3b5edb6bf341ffcf52804512ed5b9d75cbb8f7f453492b86dc60","tests/expectations/struct_literal.both.c":"dbdaba2b639e54e19512901ae9130e8524d8034005876398742dd90c312df1d8","tests/expectations/struct_literal.both.compat.c":"4e0814176a6e17bacf1f63a849c8f8fe7785b40ed3e38e4cf018fc3aaabe0129","tests/expectations/struct_literal.c":"8e120681c9d50cc290853a0373a75318c5b1d690b1480d6850e6cc2b7e621b3e","tests/expectations/struct_literal.compat.c":"433b9d0ca518190fad88709e67286ab35d6f6ed8cacf382a51252c15514fbee9","tests/expectations/struct_literal.cpp":"4890a434488271d0fb620385c7ab5ce5bda6878514ac0e62c432253e477f74f2","tests/expectations/struct_literal.pyx":"40a9b091b89403cab2295f72e5d003e1b4885f7e7104ec291a1f9f29e9b8f753","tests/expectations/struct_literal.tag.c":"41ab9ca8945eb6dc011925445882ddece4ea9bd8448277a5ad72d1cf71169a71","tests/expectations/struct_literal.tag.compat.c":"7a0e315ff9cdcd41e42ba103c6bfc2c220a6f1ce1b575980de4d4b6c5d52d5a8","tests/expectations/struct_literal.tag.pyx":"b369847669050e0b4f59aa8b05cbcf59813f02b6bfc9b7272d4862edb9eeaa97","tests/expectations/struct_literal_order.both.c":"31b61ab03512aee2f152073dea8423f322ee25e0754eb18dcd42d5b5ae3f54d7","tests/expectations/struct_literal_order.both.compat.c":"850873c0f1eddfcbe23ec803aab2f52b7128171b2db8a838142928144494a4a4","tests/expectations/struct_literal_order.c":"ab4e19c8e18c302e4bdae2e7e6d8d9b3e302286bb271d68eb2146db9e618f283","tests/expectations/struct_literal_order.compat.c":"489aab1f32445f2f32ac56cdc108d16a21357f6b269fea48bebb239c88b52982","tests/expectations/struct_literal_order.cpp":"41d552bf043993e89a7f3cee1222038a5f3ac44b317a05b9cbaf8e7bde9e2fe0","tests/expectations/struct_literal_order.pyx":"103a67d3a52029b6e5971665571c2c8c996a7163404fc0e891ee9f4003c693df","tests/expectations/struct_literal_order.tag.c":"818bec81379d034429fa870fac46e9878b0744e6c4f992904f638781e308f79f","tests/expectations/struct_literal_order.tag.compat.c":"2b59847145b19e5c4059474cc83c26b7fb543ef26cc91c7555043c86a00e056f","tests/expectations/struct_literal_order.tag.pyx":"9dd53c9b81932ac80aa8107577d62ef4241fe206977735ead3f9cf55a9663bfd","tests/expectations/struct_self.both.c":"2a187365237828051a485326d209fa72930b976bc82e580d74081eea028401e4","tests/expectations/struct_self.both.compat.c":"52fb23dcee0f333c981b9a40ad1a222b947b99f7db8feff437c6da775a5894b7","tests/expectations/struct_self.c":"1937ed40437d089404ea04e85df65343f4048830485b91680c44ecdd41f26cc7","tests/expectations/struct_self.compat.c":"8fb27c7eaeab15fbf369edb806a9342ad5d65c4be8dd88a411b10a290725f11e","tests/expectations/struct_self.cpp":"59c4b69ba609084b14f97b7ab545d601aedf9ed4429e5682155f791fdc212614","tests/expectations/struct_self.pyx":"4c8ef74ae6e2c77beee59c4ec671129bddeb7eecb8b43670be71160fdf0b8881","tests/expectations/struct_self.tag.c":"de2462cc5788b3a858b096fbb99cea9d13b9646b7cc8c65247d9492418f1cbaf","tests/expectations/struct_self.tag.compat.c":"c93763dd177ba56e5dceb21295c0eb8f66be05e5413edc91019240cfe840f53c","tests/expectations/struct_self.tag.pyx":"386321c5d2f4dcb7a714cdf7bda34076f9f90a706a9b2e58ce8bd1794c89bd41","tests/expectations/style_crash.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/style_crash.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/style_crash.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/swift_name.both.c":"5dffffc5326d4ef841b68d8ade7c410c6b20851b604beeb8bc95354c2c4ec10a","tests/expectations/swift_name.both.compat.c":"554721f3f10201d18e7df09790086f9097b36fe5513e809b98446c782f73f1b3","tests/expectations/swift_name.c":"03b1398b9daf9b0acce73f85240b2085820d644d9d067363a53dcff95e892a5d","tests/expectations/swift_name.compat.c":"bf0cce62d4daec8e2408cc329d2bd8f70b9d8825ba3f278baa3e14f9f589069d","tests/expectations/swift_name.cpp":"f50a92ca45571eea3300a8f85074345289c3e3a4c4702195254150e7073aca00","tests/expectations/swift_name.pyx":"55346ca8f01e944a91aba0a22b7d8a92cc4a11677042b37e69e245db65a97cfc","tests/expectations/swift_name.tag.c":"155c5c6272d9671d4c2db0b1068aa7ed339c75ccfc349966a65364326ae4df07","tests/expectations/swift_name.tag.compat.c":"9b42f24733598f827941287ec9a551ed125b5016cbf902a14d7c05b5e54adf72","tests/expectations/swift_name.tag.pyx":"140ed42417c2f7d0f6796b563fc6b99db508fa3e106664fd367146213c6c2492","tests/expectations/transform_op.both.c":"c2d396ab17fc51293bc915a17ba6a0c165de4a50a7aca5a2a964648fef0a95c7","tests/expectations/transform_op.both.compat.c":"7ff5109437176e0dbc4f394291e56951d01da7dc8b471abb7f6cf87fd970dfac","tests/expectations/transform_op.c":"5c71a776ddf337608673a9f4f700dca411fd8da784b03d8baba8adcc60104c2a","tests/expectations/transform_op.compat.c":"0b70a18c01c7c5b9d4205ffbe8c04744adcfa0117c5bfdb97f1376ec8f63763c","tests/expectations/transform_op.cpp":"63446b46079c175bf99f2d475e360fd0d4e4f5ce2556fdf03b4331441494a47a","tests/expectations/transform_op.pyx":"c07b1ac344959537668a4482b5724a7247b20b5a7b62ba8b1b8180c8fda4a4e6","tests/expectations/transform_op.tag.c":"dd27004c7302cfd344582142679e81a2c4924432133771ac1b3511da71bb50ca","tests/expectations/transform_op.tag.compat.c":"42fe132b57f0b35710c8ae362f4927895b64d1012277af892d82095a43922774","tests/expectations/transform_op.tag.pyx":"b46395357b465bc95543089ce30d7074569780ad247dd03788dfb6ff9d13b399","tests/expectations/transparent.both.c":"c1ed47b4f14670faad177efcfd9c2bb74851201444da5a6ccf70a65132cba916","tests/expectations/transparent.both.compat.c":"23af96040634abd598e2196026cc0a23eb1a7f7b54bb4c2d7c28e0d74252377d","tests/expectations/transparent.c":"031e1800e40b6bd59b649a05b303df6fdb57255e7e7190c39c511a7b27a7bfdf","tests/expectations/transparent.compat.c":"685184af63abd732b4ca35d59d5de8a56150241f372c07204237c8b364379fdf","tests/expectations/transparent.cpp":"8915b4103154722b749a211a7f89e76cc6f9822cffcae49aa4d18764c39ee678","tests/expectations/transparent.pyx":"825c4b65506bdf5355b36f4d9c90737c86bc6d29272b7f9f5d2e5656effcc630","tests/expectations/transparent.tag.c":"6c5b0b107f05f345bc81c030233e63d38a7a82f5a5be719cc6029976892c6851","tests/expectations/transparent.tag.compat.c":"2c5cac22393daae1c514c17f242099f48d4149b9b8d495b697b0c2eeca34b60a","tests/expectations/transparent.tag.pyx":"2a39efdf6e611d81f6fbf67d658158e1bde85e8ad70f9ab93ff4336090ff84a8","tests/expectations/typedef.both.c":"79d5c5fb08e8e6929576ae536c3d7141607ed7a363a1ebec5dd82ce1f0f9cbe5","tests/expectations/typedef.both.compat.c":"88c51043226253b4ca3812c4b27998ceadeaa6637d8db6b34b4b05c93fae0528","tests/expectations/typedef.c":"e83d84aa0bfc55d54f16fb98cdd17e07258f129fbebf5523aee55ebced1d4b02","tests/expectations/typedef.compat.c":"32fd05db2b98796097ca252436bccb8270474ca61de4d007d5248697da092443","tests/expectations/typedef.cpp":"e208f1a81abee51bff3ed49f62f814c630e2303c61fcec26ee013516003858d6","tests/expectations/typedef.pyx":"79e655032a2811193bf8fa6278fc4d21d9ff93617b508df9c6964cc44b017a3b","tests/expectations/typedef.tag.c":"4af487e5e1b6e74f17ed8445c6e3a69f96307cc2f904d7e9b212846112575862","tests/expectations/typedef.tag.compat.c":"5cf3831cf49ab69a1900ff58fea5488bb2ebdb75d9829d5d2d6258d332970383","tests/expectations/typedef.tag.pyx":"89f9e5ee4e2919f80a7f615ccf995d87ddc3e794e3921c50c87b68511864dcf6","tests/expectations/union.both.c":"976ca72778588d6ed517b25f7315ade9f4d96a4261b303ecff40e8a0d7ada15d","tests/expectations/union.both.compat.c":"0590d866fa3d6fa7131cbfb2c6cad13ede12a10607e86705dd49550d53626aeb","tests/expectations/union.c":"966eac07c65ea6a6b5c22e90e55d06d931ae539662f862de3ba8be7039c04ad3","tests/expectations/union.compat.c":"0a7acc07e93f11677b2d6db5527bdff0bdb0cfa2dbd7a1e0190b3958143e50d3","tests/expectations/union.cpp":"848e43bd7086bd94c136f347fe2209adbad074527d2c9d07dc26d0ee0bbfa177","tests/expectations/union.pyx":"577352939826b36cd714b1f4ac244ec4c6030f9bcfd99aeb52b555e2f5a0b691","tests/expectations/union.tag.c":"fbc4da207f1ba8f3c26a014ed5ef015c6c46a442b65129ad363be2f12e6dc963","tests/expectations/union.tag.compat.c":"96ea2eb155962801870ad8bac885ac3b0350cc0d7d363d8e0b0ee713a6f3c466","tests/expectations/union.tag.pyx":"cbd531379c08e3b4e2b148f087fbfdd18e97f570fcfa8cf89b68b769c12557ed","tests/expectations/union_self.both.c":"f6aceb8b80c8467c6c83549874de4ad41aff41f8898c0e7fcdfe1e01a1609fc5","tests/expectations/union_self.both.compat.c":"5090bda547f554f35673ef355e0c89bf863bd79a3fa98ba98dbbc27a10dd3722","tests/expectations/union_self.c":"e51ee5773a115e0dc23e4706a07be90dc606d8ceda653aa01f8950f83b67c8b1","tests/expectations/union_self.compat.c":"963d78273f7e213f0223153b87c73d348c1a234df0b7fb215d8b239b4db6501e","tests/expectations/union_self.cpp":"7ff87eb2163420bc3d7deca616b96a53225bea94d30b24d955ebf0240b773dae","tests/expectations/union_self.pyx":"194a0d6d5b7b338722fe966b55a3b09aee375e857942f1d218bb9586d08a282a","tests/expectations/union_self.tag.c":"eb6db9deec2228df7e761ef5ebcc2a44c9bf642db635bfaf9fdefb74ac848c18","tests/expectations/union_self.tag.compat.c":"c233507a1b1e6dc09136a1f586a84bca9f67cd2d0cb750936e449b8145dbb16d","tests/expectations/union_self.tag.pyx":"a9c50823695c5d7d3be5d9448cf498602c0aa138f89868a6499783ae26281ee5","tests/expectations/using_namespaces.c":"fb2d6c8baed0b32ac1c5e69864e57f73f0a5c2ab8a6b37a5e763352ae43fddeb","tests/expectations/using_namespaces.compat.c":"417a45ea1ff78f2eac7f84c617d72377117cf31388df070ae6dcb70a412f33e5","tests/expectations/using_namespaces.cpp":"033d493d0d18d4f21abd489ba9618d49bfb0f7049f26ab5963f388c52f39467c","tests/expectations/using_namespaces.pyx":"3a86c97c4392932f53b8a0f6ebb436ab37c67cfa31e569322fc953b38aa34de1","tests/expectations/va_list.c":"4fc02312093bbce794f0ac0955d9adc14b63f91bb26cd8b5413806748b7fc06b","tests/expectations/va_list.compat.c":"5ad4f390682d3d840e2fae38731fccb9a20325b41e5814e3a507896568ffb60b","tests/expectations/va_list.cpp":"c095ef88de58863535d4e6268696c3016512da1f3a970f0f93d5c0d593caa48f","tests/expectations/va_list.pyx":"c39d0b93112d3f05dea5221722ef0ba1eb15ae4c2947f9e0eaa10fbbcbd6f6f7","tests/expectations/workspace.both.c":"7f468e3471a1c21fb19950107c32cbb1f61a55bbfc7217038a6b155868eab0c8","tests/expectations/workspace.both.compat.c":"f3cac1a0847e3bb118de25320846fca47cb08986a048a18e97edae0c17050648","tests/expectations/workspace.c":"f0b6aa5ec14968a880ffbf21662f901aa3955c46c401d87e872dd283ba504069","tests/expectations/workspace.compat.c":"6f040c52cb58257efb5c43098e413e751395aadd69b320ab9155da3c3cbc5000","tests/expectations/workspace.cpp":"9ef7811351c107141b697a481552bceb9c9992b8862af9129ae9411fffb65d30","tests/expectations/workspace.pyx":"5c341cf4f8c6f3269c92e9d681937f2036ea11f2dfc76ce506139ba5f9d1ecfa","tests/expectations/workspace.tag.c":"ed26bcdb8568eb62f2cc09e6112cc012165e6faa2b52c283b8c28dfcf560cd23","tests/expectations/workspace.tag.compat.c":"f842aaeb2648812733f436d312038bab8c875534171efa5c82a88b87253968c0","tests/expectations/workspace.tag.pyx":"aefa3818c4a23869e8119abd4103af623e277a73c971034d851fdc48b3fe489f","tests/expectations/zst.both.c":"70959f28c197126cc3372a62af96f92d4283bde7ed9172f7096ca8df51a384ed","tests/expectations/zst.both.compat.c":"b1fcea6def407219f5e91e5d0486846f75e2eb75c416c6dc8469d2c6db21fc50","tests/expectations/zst.c":"cd78682cbac3d5c71ed372841329d7a5e6584664a3b35c90095a605a53939c7c","tests/expectations/zst.compat.c":"dddf99765cb5f85713c2ff8b45248a8638e834c70011bcdf468871705a5087dc","tests/expectations/zst.cpp":"8c4253887a47a0998f0007d082d73b89e728bddf438102c6268f2b6c706987ab","tests/expectations/zst.pyx":"4ea80e7e218c5529c28c1fd9a5e5802753baa5cafb07edd0c31cdea9bf2b1c22","tests/expectations/zst.tag.c":"b98b24d5fb3dab63d078d9248cb5000ba57601a27eeae7f724ab6ff393669bd6","tests/expectations/zst.tag.compat.c":"2775e2adcb08da84d3be81a4c19cefc4c9f67985a27f4aac8603bc6af5abf9cd","tests/expectations/zst.tag.pyx":"94dc49969fe20556c13f5815ab3d2de7950751067c25c85f189cd7a79569df5d","tests/rust/alias.rs":"cfa45dce533ac0669cb5f8a5facd80b1308e5b38af26082361ca1fad683dfb01","tests/rust/annotation.rs":"2ec88922528b315bda1515e9167b5f771ac958b8e16db487b1427f6b4576283d","tests/rust/array.rs":"f3f321ecbb21331abec66eb8da2200550bee1a116e4a5c1389c4404114388e67","tests/rust/array.toml":"7935a7d9b5fabba3f500058ce7b3c0cd79449283e6a353a3d1658e55709500ee","tests/rust/asserted_cast.rs":"5207c37aae5b929bf28195c619fcc23f6887be6d763205b201c1411d1f58d321","tests/rust/asserted_cast.toml":"49d996a324f26d749e4e9a03a2ef1e30421e6716b652d24e6bb3fb753b00139b","tests/rust/assoc_const_conflict.rs":"dd5bce15a9b1198f06b06c7ddfa9244ee69e102baf487608db0521cec65de2b4","tests/rust/assoc_constant.rs":"3fd9391aeb6610ffb03e1cba5725dbd581a30071c7d5440c8f97845cdb3c8534","tests/rust/associated_constant_panic.rs":"761b5d70dc78a3b08713e8ec804022ee9e81284e8e968c2e7921f911f926c0a0","tests/rust/associated_in_body.rs":"0d51663ad3d686649f36435b47aad3e25d284d8d95b31cc797367fa950be8297","tests/rust/associated_in_body.toml":"584f72f042ae5c820f17054d3e5b49ed523ba51707adbe5b032bdd0031b9a26c","tests/rust/bitflags.rs":"b4dc7a4af20d1281f3965c2a295797aed00e1ced041c9a238b1667fea7dfb46f","tests/rust/bitflags.toml":"2d501b38c02c7cac4669d3905c8cb6f559c01bdda5e8d4b7a4fd3f8aeebf730f","tests/rust/body.rs":"986d2f7b8d9b4c4b76374c31bd7924d842249f9273dd15596fa00088ade2d86e","tests/rust/body.toml":"cfa734400fa079e137a3705c686c35eba1380b2f8dca9480b10e1930a292a9f6","tests/rust/box.rs":"03434d85fab066ed38fa39c372bd3be89af96913021c0190770da5f961e48bf8","tests/rust/box.toml":"78361b0fa8d7b0dea35cbe78badcbc5ff72bee8b8f69c451b3b305fcc41dfde0","tests/rust/cdecl.rs":"49d928c33231e9df3c0232aa913defd771c16c540617bda8c238cf8497436f16","tests/rust/cell.rs":"455a5ab03499d3bfc4c1f6662a29bcde0dcc8b09aac0058ab3a142192c87a9ae","tests/rust/cfg.rs":"dc612c646079401aa9ef8bb03040ee8f8d412683877959bd8a581d9953794d68","tests/rust/cfg.toml":"4af74309b7723df209b4880575e952a40af7a9a9acc7ab6e63ac052bc11ce106","tests/rust/cfg_2.rs":"16c59cd70008418750bcfca47c14a87a348b34c81fccc06115b68b0933b8dc64","tests/rust/cfg_2.toml":"49e149901948f7a1f2ed5cfc6d415b799d51848de235b2be153e7ef922d544ff","tests/rust/cfg_field.rs":"904aec8f65fc8ff7a33ec9aa474891e87770de411ed1603c1cf3f5e14c0703f9","tests/rust/char.rs":"8d266ad0518c6d864ad117f438963b51995fbe1825e415c35abd1c305b626364","tests/rust/const_conflict.rs":"6027453be28b17c20eebb6ea450b91b1e781b41fca08b97725b0eb7393120b47","tests/rust/const_generics.rs":"68b3c832da04d17dca8dbb589ba50009d8e89eb39618e9cd67ca4fb1f09e8a60","tests/rust/const_generics_arrayvec.rs":"f65ebcdc766371561e2ba947103b5cf3404568f763548b81cb3efaa5d93d9747","tests/rust/const_generics_bool.rs":"38ec457a423990bc7feec4346ea503e79fd57b6abab4ff4b1a9f8fd290c86d51","tests/rust/const_generics_byte.rs":"2e74c4a5ef57b2adb9e1e0041db1eb73bff2f4c4a0b3f748e70c6efb2c1eb4fc","tests/rust/const_generics_char.rs":"dec6117d9e91c2aaf8ab6358ddfd438a47cb936879bbd06eafa688398e9422af","tests/rust/const_generics_constant.rs":"380ba5515154eb4eccc9e13928c92522bd251c7b339d96c4ca4ab8dc7bdc25b1","tests/rust/const_generics_thru.rs":"087668e5c83236fd63c3acd5726c452818b13d6c6a2bc941e0704789d27e1929","tests/rust/const_transparent.rs":"7b3b029268345c373b4cd341c0be1bf6fc61d0ba9752f1f298e873f0b2638a71","tests/rust/constant.rs":"73eb998b1de5c6b48b73981e47b87e40a86bea6766d5ab31aa2f3f54d1e86071","tests/rust/constant_big.rs":"ef57342d59c7252cbfb5668689b82f44a9905d111cf5495dba655c2497edfa15","tests/rust/constant_constexpr.rs":"d5a974e8a2309975e069a59e8621d898aab8d52da8aa0d776d9571764508c99c","tests/rust/constant_constexpr.toml":"578ab8fcb0bf020b2486557e49ca473327d60452f75ae1602a6bb8e98c85be4e","tests/rust/constant_sort_name.rs":"b0fc655ea110af97dc80266dea84aaca098fb03224caa818c0adadcd48061b7d","tests/rust/constant_sort_name.toml":"739bdfbc7a1edaf7173011220ad822d8929ceed0985cc68700a478ae9f5caa26","tests/rust/constant_sort_none.rs":"b0fc655ea110af97dc80266dea84aaca098fb03224caa818c0adadcd48061b7d","tests/rust/constant_user_defined_type.rs":"49911c1eb1b69771a020a705fa6ea538d2a1e26d1181a8fd6c1cfc11e16affd2","tests/rust/custom_header.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/custom_header.toml":"4ca71bdad8db36ed78e0cb6342a33a4023f3f535a48141c43905750ffa688f96","tests/rust/cython_options.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/cython_options.toml":"425bef8aafe10ec59986426f8147abcc56e534b12b950fba7ab2a3db50bf56a6","tests/rust/decl_name_conflicting.rs":"14c5ff6339754ca440d144fa2c97081d61ffc004bb634fb0ae586e87921384ac","tests/rust/derive_ostream.rs":"d815d16ba4913a40e4893fcf16193ff90abf352556191eb98d91ecb356ff0fc7","tests/rust/destructor_and_copy_ctor.rs":"8eb882982e9eb3d08a1157c89ae6962a55624f3e5ebf878757aa9f31a9eaedaf","tests/rust/destructor_and_copy_ctor.toml":"b1e73400004d05354122f6aa57352eee27c3f543c08f5b689802e47dca5d6a2b","tests/rust/display_list.rs":"b4c8388b49c0d62ecc2ea3b2b43474b7ef672e196cb9c456f9f0dd317cc315a2","tests/rust/doclength_short.rs":"19839d89d5a0526bb7eae81b335c94d980e0aeb9d4d51706463d5543427d99fb","tests/rust/doclength_short.toml":"8ca95480bca52ac337cb4410936d71e73271d79acba998d29068c3f6855c4a58","tests/rust/docstyle_auto.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_auto.toml":"1609736841750b13dffd4ccd31820b5212913c19cc2767bca90672825a055614","tests/rust/docstyle_c99.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_c99.toml":"434839317738bc8ec8bb7b71cd3286b1cc473854929daebff35bd8748b056fa8","tests/rust/docstyle_doxy.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_doxy.toml":"041f3902d904ca4756bc35352b1885781b67314a5a35f4c894bfc4aa3e0185e1","tests/rust/documentation.rs":"3c3451092feeb8f6283a968a7cbfcdbba23a6004327761e0fe8d4073a3ba19de","tests/rust/documentation_attr.rs":"7df25a9c3e7fd97cc916c324536d30816132c927c325b8623e24321806d879cf","tests/rust/enum.rs":"0d3d219b4e1418558b99c63fbe10c2879cacbfe69d0e465940d9ecb3b44f5112","tests/rust/enum.toml":"c67604d307b23aac28b02a34f9bbf451f2b169ac157d845e65ff3734adcf0576","tests/rust/enum_discriminant.rs":"2415b502bfa695c84ea672fc24fa6842ddc4c06ea55de261fa035b30ded94a3a","tests/rust/enum_discriminant.toml":"7a4b4d6adaf4d7fbaf6135b4cc859a86ff9e62b184c44cedd48bda4e79d0df27","tests/rust/enum_self.rs":"07523f250ad30b00cdea0325e55b93e066090a42f2d37cf07d185a81385ac3d4","tests/rust/euclid.rs":"d93d138d31e1cd90ffaec25d44feb2305dc702f45db04733b1ea79c0f164fea2","tests/rust/exclude_generic_monomorph.rs":"4b6299729923ae1e36e4ee3ecf766cc2825b46a25d0ed2033641cffb7c3b35ad","tests/rust/exclude_generic_monomorph.toml":"fad039feb18394d4d05d597a95118f4c3eff754b684397d54260e6e772c0d996","tests/rust/export_name.rs":"bb35cd7d9ab197774684aec596560859315ded1bb29ed161907960423d838ba3","tests/rust/extern.rs":"fb8c0e2b06186b4fbcce4f059289bc9c775ea42d3e36f935d407a2882f32c9d7","tests/rust/extern_2.rs":"6299ea10095ef94e3285844029c067349f07fa78c6d891b3e7402f85db36bcf0","tests/rust/fns.rs":"7c8da1440a30830b395bac08d50a0a41c91f01be00b57b8821b6e40159d5d487","tests/rust/forward_declaration.rs":"3e8616a472d97bff7239f42c7991e4893a2b7ef8730f6833b767c0d37a4cf7d2","tests/rust/forward_declaration.toml":"f4e9df03133b937507a034bbec10e680969fe47a57bbbb65701d19fbbddb5190","tests/rust/function_args.rs":"81ecd18c5919a3508f3bb6f04aecf4f91ed9db27da6d4b54a17fbe1d9b626643","tests/rust/function_noreturn.rs":"d797d6511c800d02a9030ce3b8ed4a88a14b5866d21dbf505a9d23b7223f50e4","tests/rust/function_noreturn.toml":"3e0549ffddce990d0fe3e3860bff8f2e39434658578505105afdc6b37d1133b3","tests/rust/function_ptr.rs":"eece7bd1bcdbef8b9c2e875dc11eb59d82a1293ace228b4a2d7ba07354bd1758","tests/rust/function_sort_name.rs":"a816564c64059e90587172feabe824726eb58050729f43237603bcb5dbf3694f","tests/rust/function_sort_name.toml":"1dcd75d52b46fc43de0e5c7b3dc300338c68e8ac0becb5b375821820c43a369a","tests/rust/function_sort_none.rs":"a816564c64059e90587172feabe824726eb58050729f43237603bcb5dbf3694f","tests/rust/generic_pointer.rs":"620d093fb1606a81d1afff60d1359bf76461214382b968e951dc12d1070af5be","tests/rust/global_attr.rs":"279e4ce58c67101d8d03f002a918bc89fd4b819a44b43a9e1259fa6529d02692","tests/rust/global_variable.rs":"0d4f12d6b688bfc5a9e134d94bd5391213bc24793aca59b5f9f3f3a8e4b9c7d8","tests/rust/ignore.rs":"abe57db0bc568385ba20e379a30f928d8c5a3f851b8910fa15d05ccacd1c3a74","tests/rust/include.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/include.toml":"0c0530f9ae070027bfb23f539458782938401d028ea1b7b457dadc6b9eb0ee19","tests/rust/include_guard.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/include_guard.toml":"4f92729aeec3544b88bee8854e9b608c3fe5cf523eedee86bfd818a657d6ef9c","tests/rust/include_item.rs":"b59b9e35174bf2156e7d4d3d686b0fb6eb3976abd1e5c270693e3987b8ff9e4e","tests/rust/include_item.toml":"a8a25d0f3949303c1b2ac75ab142bd2a3418d54e335008f64ffe0c08a4f8fce2","tests/rust/include_specific.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/include_specific.toml":"579522a1f980d6a2b950d2cb0abe527c2c87b7d8147946ccacec0eadc6a7b2c7","tests/rust/infinite_recursion_typedef_monomorph.rs":"69f3a37eb5d08dd25cc90838666d116a07fdbe3bb7bd24e911abe36215476cb5","tests/rust/inner_mod.rs":"84d975ad14c8057f7cfc21d2a0dffdde043fef5e97e50bfb76abec61af617271","tests/rust/item_types.rs":"507a1de52bc29698edac28f08b0cec008604579689b9ef3cd832eb56ee359482","tests/rust/item_types.toml":"92ff09b39cb560124161667fa469e58bb5b369aef7b59e7668a84c8b7986c09f","tests/rust/item_types_renamed.rs":"507a1de52bc29698edac28f08b0cec008604579689b9ef3cd832eb56ee359482","tests/rust/item_types_renamed.toml":"68ff8b74b6dda04323ce09fe90260a5b6f203c9e7a75d77e021ffc973447a1cb","tests/rust/layout.rs":"79cc422e9976fdbe44272a185d0e233f96fd15e86af092a0dc9ded5517e9178e","tests/rust/layout.toml":"b4fb6c69305f20776a22f40a3d2368280fd908426ad68572ab59a0ef0711974d","tests/rust/layout_aligned_opaque.rs":"2b4af2cf9a2308a1b0407f389e680f5a3a5b81cc7121d4164aaf6c10de8b5315","tests/rust/layout_aligned_opaque.toml":"2ea5eb9208f53a0246f458fffe093d0a557ea5bac8a3910bf80efbdb56fbaf1e","tests/rust/layout_packed_opaque.rs":"fdb022462224bf6679111ed2dc4b294352d235a3ccb53a21cecc0418624370f0","tests/rust/layout_packed_opaque.toml":"b2f2d4cb9061267ded116cdd461a7ae2d3f156f99d007ad8d137f60588a19c84","tests/rust/lifetime_arg.rs":"33c5066b198b82e1bb6044a3ed913447cda9e52ac43c893a239c2d4ab0a98a54","tests/rust/linestyle_cr.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_cr.toml":"24724f1514e7f79178fbebe757fa24f84ba1b996cb37e1d4de35394a2eee88e9","tests/rust/linestyle_crlf.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_crlf.toml":"a315db1b1b4fcb6b5de44b8cd88f560161a99c166ec38470f9a7c7c0a9b0f02a","tests/rust/linestyle_lf.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_lf.toml":"9ac0b95d322c535fd3d13cca88e1a41c07f76bb82c073a6c201702085cfe136e","tests/rust/mangle.rs":"b764fb75e43856f76295b7eacbb5ff4b8d73772d1dfde730606769dd7890b427","tests/rust/mangle.toml":"9251c18d50b2c1f57afc70979f70cf54fa4d96b2b8abc3b7bf02ec1e74846875","tests/rust/manuallydrop.rs":"c6262ebd269697737c3e169db8344dd58bd51c049fe3a0ac65d3dfb25a8fbbf7","tests/rust/manuallydrop.toml":"ad2c9b4a190521a243dd37c27f9894e93dd274c2782d6651229ea09a6ff63745","tests/rust/maybeuninit.rs":"fde78e4074fe0eb6ed75f1416b5fbeafe5931c4df3edcd1e51c31e4f38a5c517","tests/rust/maybeuninit.toml":"d2322c437c261ffe1ca9bda7cca7cc78e9d6681a04f32c0aad7ad95852fb3574","tests/rust/monomorph_1.rs":"4daa3c42f7a1bf0bb7dd6ed605f554db4dc6f8dbfcff999939e218195563f1f2","tests/rust/monomorph_2.rs":"eab2dc18f375594f16e00b401c9c8f4f98c770d61807c3323080ec811bcc0230","tests/rust/monomorph_3.rs":"e1a03e6f9c37a64183adc89ba978bccead47deab61e563f02a1a66520782154e","tests/rust/must_use.rs":"fa6d2c1474f4dc07b5b2defc463ff0976e9ca25eb93b691745174fe1fbde11b2","tests/rust/must_use.toml":"4c4c13940de3a610e25d319682ed53a10c26a0450f3ccf14b90e730d701822b5","tests/rust/namespace_constant.rs":"d280b65bdcf529b456570a01f0306b4e9ffc0aa22200fd8b54e9e5433f6c5ab2","tests/rust/namespace_constant.toml":"493e814e3ade6f1fc4d34140c73d0ecdf00f1e4864f7719516d799eecc9eb2dd","tests/rust/namespaces_constant.rs":"d280b65bdcf529b456570a01f0306b4e9ffc0aa22200fd8b54e9e5433f6c5ab2","tests/rust/namespaces_constant.toml":"6b5a58b167b9890c186ad92c9f9164b9f3204a86d706a7be688d51f8a666e9de","tests/rust/nested_import.rs":"35a8343efe9117b3ca460b2d8e9a4a0813d58f622ab776cbe18527814d7105c5","tests/rust/no_includes.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/no_includes.toml":"504215785a725906418431f044ff10cd2ea2db7261ff990a3f278dae17c05e58","tests/rust/nonnull.rs":"dda4baa922a142eb7ef283a5fb672fed6492552adbcc82106e78d482a8abc39b","tests/rust/nonnull_attribute.rs":"9479791492ee3c9e0838e3b7d207ff3338d0c7867ea9f5f7d42c4224cf1f515d","tests/rust/nonnull_attribute.toml":"d41f84191d8e843f2d87facc3e4aea13b2d4a02099e3e1fa9b583c4d1b855c91","tests/rust/nonzero.rs":"2a3f41a681cdffb9f9d10eb2b56b9359c961c1bf48881e16573b1b34232307a6","tests/rust/nonzero.toml":"7838caaf3c460e73d5e055001b2d52c560084701dadc9ce8447563a6726e39ad","tests/rust/opaque.rs":"d22d57adccab8cecb28d4573a42de30e76bb32e836843012b720a4828c35b227","tests/rust/opaque.toml":"4c9bdee2ba996a05d3148a6f12ad7a64c6f651c3e00b199b7e5d5a9f35ce7140","tests/rust/pin.rs":"dd7db5d6dc0c0bf40828f8b45d9995bcc3de5b8e06ba5b91c64b451e9af0e500","tests/rust/pin.toml":"8d790949c59791b57d0a085c4c3bdf777728297082a87982f6303200f2c16bf0","tests/rust/pragma_once.skip_warning_as_error.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/pragma_once.skip_warning_as_error.toml":"bf1d35fcffe74f6689f53712cf7e079693f0a92c6e77403b5f9a5b0fcb0cb96c","tests/rust/prefix.rs":"773f2824b4771b8ceefb44e4ebe0b1d991acb0f297960fda543ea7a657854876","tests/rust/prefix.toml":"c6ab6c4cd09d12cbb04ace74dacb51ca5c89b6f0d77f2d95e918f22a9f27c0e3","tests/rust/prefixed_struct_literal.rs":"ce1843b02706788c31f8fb5889674ecc17f7940254cdf1e37ca47846b18e56d8","tests/rust/prefixed_struct_literal.toml":"d74eb710eb1f3bd05a723e54a6897170491ba0ae9bcf26acd1a3fe00e3a4ec14","tests/rust/prefixed_struct_literal_deep.rs":"fdee21e3739e9cf93ce1886d20e83db7597f3bb0d0c60c0fa5cab0e3b8beb1e6","tests/rust/prefixed_struct_literal_deep.toml":"d74eb710eb1f3bd05a723e54a6897170491ba0ae9bcf26acd1a3fe00e3a4ec14","tests/rust/ptrs_as_arrays.rs":"264ddc525e4286ec480caa1e011c3edc846eff16d2cb5f061295be55a86a3844","tests/rust/raw_ident.rs":"4d83ee8fdf4cc572d944baac267fd30318039441f17d6682d4457f2252e61217","tests/rust/raw_lines.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/raw_lines.toml":"18d6b74ac6571b81a58c8a36e9e23c594537cbb63e79df73ffffb54da39ee87f","tests/rust/rename.rs":"9a310fa1c402c996047927342a94bd50f36697d124cb3214f91de31bb7fc31c1","tests/rust/rename.toml":"42523c11649292309fb8a226e2153768c5e44af1cf586d53fdd44a64bf59be40","tests/rust/rename_case.rs":"59f8788ed6118d353a37f5014f9604a8a970065be2e79db7d8ace663f449499f","tests/rust/renaming_overrides_prefixing.rs":"f1fcaf9d1f7a11f749e819524d73171986f76543204dbe8e5781097b1df6de4e","tests/rust/renaming_overrides_prefixing.toml":"ce65e3488f3e8c1ab5a4b6a191f1555b83156619bf332286d40005be260cad33","tests/rust/reserved.rs":"5a802dd88ef94f129d93a895ed1e81531100e8cf82d8fc5a9aa55afcd50e3458","tests/rust/sentinel.rs":"a982a4067401d8257f0d45d7832895eec5c8a352ff8fca5fc49a4149599d89bd","tests/rust/sentinel.toml":"93812028777748e46ee6b023b3f41864718862d47a862a92c0073b84e03f22f3","tests/rust/simplify_option_ptr.rs":"ab17ae61577f15ef1fbb8e4c6cdff97a52ff001b27bbaebe8955764375db1fe9","tests/rust/size_types.rs":"314dc9b48853b286c6dd2e40dc355411a4310b5039f1aeeb39f573f3f891becf","tests/rust/size_types.toml":"2a6c8e75eac5a680c34b78599c04c41379dbe0ce6d1ff6f6291685fb156ad6bf","tests/rust/static.rs":"2241389aaf3d3cf4db7dcc16071b2a2abab28669b11ba4f2a66fa85339688fda","tests/rust/std_lib.rs":"c1c8f383f01608f7f7c6a104fe470c8afd25be0ceb2194a702905fe9aa82d74d","tests/rust/struct.rs":"ff89af75f5766eed5c02a7272919204793ef96cebb63cd9ecd934699f232656a","tests/rust/struct_literal.rs":"d459e815498b0457f1d5bdb9ecec1a375985e2d57442ddfa29d5335e4cf8ff23","tests/rust/struct_literal_order.rs":"b3b4ee077bf7362a8b1af37ae5dba8bfa3c0d13a25e6f49a201eb857c1024c68","tests/rust/struct_self.rs":"7f0ca8785ff6d25be86af271229a42958d6308efe1da71421b5e505a3626c267","tests/rust/style_crash.rs":"8c4c716638c58260ecced5a58bfb035f6e42375a2d221028c2fe0d99203e6b44","tests/rust/swift_name.rs":"4852f0d6547ed54e6f2b1de9a977a743a025ad8da16297818bc24af7b17199a6","tests/rust/swift_name.toml":"1542a5b0409fa024ec7c81190887633dedb186c14d37b053c25f0609fd99b381","tests/rust/transform_op.rs":"103e3ccf7f34077ff2e61107242fd957cf0c59ba659537b12facee18b22d08af","tests/rust/transform_op.toml":"6129b6b8ea9a289eb64ecb5123929ed31d09f1374dc59341e1fa6d22842e55df","tests/rust/transparent.rs":"42e2adeea38fb1418a011ac6dd8fbd97958f8a91bf6c6faebb687dab468fd3e2","tests/rust/typedef.rs":"8e2c8c9dd0014040187fbc656a1a7921e4faabb7c10ba00f7d68fdbe05c1219d","tests/rust/union.rs":"4e697db4b97ef737c06f9997f341505b306abcb6145a6b767b8203f72ceeaff9","tests/rust/union_self.rs":"bec8ef669782564e9710598816aa7266e2ab33321b9c2f7c7b4fe8c683386afe","tests/rust/using_namespaces.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/using_namespaces.toml":"2f96d6173b28f152bfdc8b8692972eab1d549d340283607b6f5ee13a02242335","tests/rust/va_list.rs":"d35aa437a1f624ae4ed8530e48ee0e15ffe5997ca5b79e06412d6f0eed133ed6","tests/rust/zst.rs":"cb77d9fad1476d0e7237a7504be7d9631310e697eb72f20a100a098e433de6d4","tests/testing-helpers.h":"78e624dfd94adf25fc2bfc69be5ea18dfffa049f146345e7881350e77fb9be7d","tests/tests.rs":"130dda708010a86905f6b042e4993e96c815ff60104a3c59d078588694d11a85"},"package":"faeaa693e5a727975a79211b8f35c0cb09b031fdb6eaa4a788bc6713d01488ca"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a0e21569cb159cfe3abe3ad63c54035e9e72736a1b620be3f3f4c390889f4cf2",".clippy.toml":"a6a5a8a0900c286e725fe59862957d9f062698faa0bab4364a6372ccbdceff89",".github/workflows/cbindgen.yml":"9324d2c99d0ac5fee1119ca297b5b5cd7a6aa080fa9dfd3474b095b0a2e38002",".github/workflows/deploy.yml":"44e66de170026fb13d96e373ed2c4d7eadfc20fe738fd344eb24e0f354d071b5","CHANGES":"3cf7a0bffff309f8fa7f20aa4618f83a8c2b48c9202495169a13eab9e289d1bf","Cargo.lock":"ea22103f506e5cedde42425feed40fd6b7f71a327c93349894fdc4ab70acdf83","Cargo.toml":"25f65d822446d3827a7c53e250428f92af07faa66c8b185f1c72ade89e0aa1e3","Cargo.toml.orig":"11ff61203a266f1a9b255c27d92cb06cfd201ea5f1dcdd564566ba261bde7453","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"eaedddd66de11155f17ca657825d92a0dc4243aebf98f846c15b31cd27b27b99","build.rs":"f0fa57ad2c0dca5855cc2636a2e95acbadb52fa887609216022bdf71ed996dec","contributing.md":"bfa8eb84ebea06077ba25e7157b10a6676c5da8ff850116f36205f9a004848b9","docs.md":"3bbbefd04f4b7b86d37cb4217c404f1df43957b275f34235adf4d42be74ce661","internals.md":"62721f9a63729769c947ddb8270df3445f148fcba545e1152bc4f545cc32398b","rust-toolchain.toml":"2ce1c1fe5e79a52424c9d88d99f5a2c95dcf5b4f4a82431bb9e5710cfb39e184","src/bindgen/bindings.rs":"817f045c8093c584f14143cbf00d5f8d3b1e5e638ecfefd0a67160d49b48b83a","src/bindgen/bitflags.rs":"7a2f75eff0f25da53e83f49d82744f6a7fa36f73d85dd9cdf883ba1c76346e8f","src/bindgen/builder.rs":"80a05adbbbc4d2be57098622361739c801db898b7e6a7f401952e669ee268807","src/bindgen/cargo/cargo.rs":"3483dd68c914cd529fca840a7a44a2bff446264b44428d1578ef3e54450500b0","src/bindgen/cargo/cargo_expand.rs":"20e8b924ecc4e7a74dcef963e3b2e6b644535aeb1d0ef848638aa6da786d6a39","src/bindgen/cargo/cargo_lock.rs":"0426ce5ed7ed2a4c76ea119f9f9bb841c9a55ceb3554e93c3e0909b68c04bb82","src/bindgen/cargo/cargo_metadata.rs":"dd8ed657bf9099685024f1ca0def236e61b00a4ef2dd646d5d4797a0597b439d","src/bindgen/cargo/cargo_toml.rs":"a28f4cc8b9c938ec7fe99b1f235795e191e0baa1961299cb6c1155c7bbdbdfa0","src/bindgen/cargo/mod.rs":"a938c1070207d9d13304b1fe2f19680d2a409337fad1fad3770c676a6cc74373","src/bindgen/cdecl.rs":"0c95ea2ce3db89c6f97c4d67aef3616becc8e8aceeefcfca2ea884014d1b358a","src/bindgen/config.rs":"d644b915168ab0681f14408d1bd9efa834f085110dfd04e7ce487cfe07da24f5","src/bindgen/declarationtyperesolver.rs":"a0b975320ab5c6f6c342ae32828309e131f1bf0f094ff0e533070123b06417cf","src/bindgen/dependencies.rs":"0916e1db9b2aab59ae60623bbf79d1eee1c59cac0711f03fc442ed893e60cc16","src/bindgen/error.rs":"0d5de9016166d8dce14ed8249990a280f709b28459c74cf3717ffd2399fc476c","src/bindgen/ir/annotation.rs":"a9286669bda682c05bcd2b3374c1bef48259db1df165b18ff2ad5c1ed64a166b","src/bindgen/ir/cfg.rs":"67c00ad73694ed3270adff19312174514247145ce4ab7929ddb8263ef4c451bb","src/bindgen/ir/constant.rs":"3fc8753c0b72fdff3468eb0af3f4911ec8c2fea63bb1d5028acdbc8dbcef91d1","src/bindgen/ir/documentation.rs":"49281cd443232483c524491bac2543f148b554a886ba7abcd29ef8a86c80aca3","src/bindgen/ir/enumeration.rs":"d702f37337ed21b01edcf38e0513489124517cd5c34a8aaf0ae947b6b0f86ae8","src/bindgen/ir/field.rs":"3f582301c827405415e84ef6c9f59ab3d7fdc61d81f4dce56fccb0b3c4f3667c","src/bindgen/ir/function.rs":"efc94223df2401a057329659e83e5535b26ec6f79e147083857dfd29a376bc27","src/bindgen/ir/generic_path.rs":"682c043bd5e76e073991609dd76d261100f37d12b3f1c8144a8d68766552921e","src/bindgen/ir/global.rs":"5ec1b6bcbc3c3fa54ce237b63069ad6bd4bd738c9fb5d8caf94eb69824602ca2","src/bindgen/ir/item.rs":"3da475bec94f09ab0d8e734bb88be311caeb7a0dbf13dce94f26f97028872c8f","src/bindgen/ir/mod.rs":"67ae2b67ef6fafee72f68f38bf874b05a6816d60d8c63211abf802414459be5b","src/bindgen/ir/opaque.rs":"1bcb7677ea08cedad17c75a5c65747c71641803cc378a71d734afd36eb428c9a","src/bindgen/ir/path.rs":"a107230f403b7c139ea722e8c20156d12c609e141a6f279e19d5c5a0280d08af","src/bindgen/ir/repr.rs":"347005917a75cb49fa8bbc22c2191a2291d79343d7f42940690907d3a4fb6a6c","src/bindgen/ir/structure.rs":"7fc949d434e5ef2f6848fd23ce4e73866570c3238fd6a87cb9128c7b21eed73c","src/bindgen/ir/ty.rs":"f447f37314d3a6fdd7888a159118d00f2ea338d3f4c9a851f144df0bd89b0bcf","src/bindgen/ir/typedef.rs":"aeb873bbbf5615557e23d43bdee306aaa2b3f7aa0f2a6cf44fc69c23211009c3","src/bindgen/ir/union.rs":"cb8137c8ead799e8276303c6cbae4877013ccff57db8c245e457b6bae522ce82","src/bindgen/library.rs":"5c4d6094b01f020e6e5594c0431e8b26bca1c492c3f888ad1261ade4c1b326e7","src/bindgen/mangle.rs":"95a8ef747e275c87001f07a95924d4f78b304b9a38b8302b52b90705a3845515","src/bindgen/mod.rs":"40c7ea333a83de98e420e39dc86d4067dccf82d5ac0ccbdad3da9a2ed63e3c3a","src/bindgen/monomorph.rs":"30126ba80ed9921e43e4929a1b79d5b4ef54b3d4ce0bb60dbcdce777d60b23e3","src/bindgen/parser.rs":"474f4e8f15c28cfc2cb941662cbb7d4304a406df24f87990b7f4fc16dcca7b4f","src/bindgen/rename.rs":"7d981a720fe54bab916ba8328ecfc129e5eabd90e4b9a806071912661fa40a4f","src/bindgen/reserved.rs":"7024f1cc80f787d768151bac15ed4e6f1b55fcb64c699e3a05b398ed9acbe4ea","src/bindgen/utilities.rs":"ed53d73b3b402347309f04e4f0a020e981924d1581e7594321f5382a9c0d6ee8","src/bindgen/writer.rs":"fb4a9a6f46506918a33fa149ab22b83b685af60a3a072db54659c46d831a5163","src/lib.rs":"0c313bbe7f3bef625b2d2b345ec188e16db34c4222fc3e230b12b5863838b4a4","src/logging.rs":"61a51d7c22d4c34c3ec058e15ea45b9c5519addcf3e6841a56cd56e599b5cf1b","src/main.rs":"1655d7bb6270f2c97e2da1856e4b0d078bec633a374f75e87924e3f7d1424b4c","template.toml":"f2cedfbe9823e5e303b6aec81e8078aaa95ee7fd04610d10c4156ee0e248cfbf","tests/depfile.rs":"beed7e1f4cbb7c451cd7bf1357914053d390cc884ac5a78beb8f2ba4d8f56c82","tests/depfile/Readme.md":"2b81cc10632a3a883ade804ac8a495ea915263b1c67705267746725b37dec07f","tests/depfile/cbindgen_test.cmake":"8d83fe959e3fdc3af2c60426348798c33fd9e4bdb1098826968c3686c7cca878","tests/expectations/alias.both.c":"612bfc7278636a7c9c94d64406b528b492ee83e49a82411ed0c30630f9f34029","tests/expectations/alias.both.compat.c":"5f22c9d89182bffcbfed3662d5fbff9877049b045dfb8e6b81e6f5c01f974980","tests/expectations/alias.c":"cf3c496e8e65c6ab14469a38420f9afd147160d432e6a2ed11c716c908b2cb5f","tests/expectations/alias.compat.c":"a56deac9f43efb1f68aed20f6b436687289f9037e2a21810669f640a7f8b6e12","tests/expectations/alias.cpp":"259c612fc5149b0e3ae7a353eff451413b54c4d912e69567d32849cd26697eb7","tests/expectations/alias.pyx":"f65869ad2181650669f3c8c3445e5bdf0de6313a5b53d8982fb9cdcf08e9f8f2","tests/expectations/alias.tag.c":"73136d2f5b0b948d12a87935ada9d64f2ba9f03f40f6daffd692a3062d93b6c4","tests/expectations/alias.tag.compat.c":"1291aa2a7a7e68f16c17cbf2e0dbdae5b09670d6f436841f2246c5f0c8bdf76f","tests/expectations/alias.tag.pyx":"6b648bd4bde9cefb8441bcb9f28b9769cb4a5299d8caac49180ffcc276ff5ec3","tests/expectations/annotation.both.c":"0a54b323f9c40a345f535d79c89d245259443d5afe72e16165e3996f33588b70","tests/expectations/annotation.both.compat.c":"c15c9aee10d474ac8f998c4e0914f6f0c13526b3aaf6837de16b2e193a336c0f","tests/expectations/annotation.c":"3edc90fd9773ff57b0a6a39edbc8eb5ed594a0b080d89ce1a20dcb7a5ebfcfcc","tests/expectations/annotation.compat.c":"1bbcfa9ccbe11adaaceb63e3118b2186931967361e25e5b5895ec71fe6634823","tests/expectations/annotation.cpp":"4781e0146707823823c39bb16f167cfba0e2120c6e76869a2e0f89cb1700ad66","tests/expectations/annotation.pyx":"0fad8e0ecd818515b2860c2a7aaba8e42010f7dbeaeec82a6766cbb1506fdadd","tests/expectations/annotation.tag.c":"55408b8b93b950b6e174abd940d011d2ed927ef8350b3dc456c48d0b7fdfce0d","tests/expectations/annotation.tag.compat.c":"3af0b1343b9148330f0226c6caec2961449df5702e66801853c6129d9cc5c7a1","tests/expectations/annotation.tag.pyx":"993e26032085458117e39de0e827c7c5015c9eebd0e6b2b6d076370000fd913e","tests/expectations/array.both.c":"51200233fe3a252492a9d96c069bbcbd3e89ed8a1b180d3d3b6d1af3f41126b1","tests/expectations/array.both.compat.c":"beedb600de83fe8688a10c1521ff7fdd61566114de723fb02f0a83f9aa0dab46","tests/expectations/array.c":"954225a346d838028d5b2d7c68f7b3c35f44d763341f3f425e04236426f9a209","tests/expectations/array.compat.c":"2c4940d3194c3813ac46d246d201d791dcec0865908e2921d77525a37610af75","tests/expectations/array.cpp":"37152d5dbf71e280afdbbcff347ee7e53cc1eb426f1f0dbf94520f72b1695b1e","tests/expectations/array.pyx":"68c523e03f09764d120f2044f1cfb35a48a52be49746153f8e819cff4fa74167","tests/expectations/array.tag.c":"957cdc7253d9524b5f1527e2d3b6120f706f9b390b6e6dc37f46d4e7ee766ac1","tests/expectations/array.tag.compat.c":"725bf3feca7a14fe77cfea5b18991179459ec4e2e57e7957a09eb93cf7ce15bf","tests/expectations/array.tag.pyx":"dbfcbdeb3e580a13e8c85235876b176ce9324599cc69f399cbca5f1090225c47","tests/expectations/asserted_cast.both.c":"e7be7cccbbc4c6bed203e16def79792ec212d28f93a6178fcca8bd5e5608aa93","tests/expectations/asserted_cast.both.compat.c":"9e49646e982dcd65464536634553c02a8c11a486198b346de14004d265fa55fa","tests/expectations/asserted_cast.c":"acf929fa2bc9be077666de04f4d10fc0d4224749a7a092021c5e8046711c71c7","tests/expectations/asserted_cast.compat.c":"4c2ec364d80064ae887913bb2bb27e47857ab8b332c3042a4d585737952af623","tests/expectations/asserted_cast.cpp":"b4df513687321770538b9da13674d7f9a6249bdf91ec61049d756d40c84d967d","tests/expectations/asserted_cast.pyx":"9f9a81a26b2c5351493b37b875a1d93376c90a87a682d03b015b264bf533f08c","tests/expectations/asserted_cast.tag.c":"15b0b83adea966408e574421171bbbbf9cf85b7605e3e0e240af41f2bfab2ca9","tests/expectations/asserted_cast.tag.compat.c":"7e8f488d0613133a3fbae959cfd7c1d3a018ab8d762923aa073dc21ff8ab7b74","tests/expectations/asserted_cast.tag.pyx":"4dd8b290c45b4fbb21c044ed29df04816273493af3777114d312d4183fcfc67f","tests/expectations/assoc_const_conflict.compat.c":"bb2c53ac57d1b53f5e2ec0c0140d3d309d9e92158953f46b04708f3d86d93b67","tests/expectations/assoc_const_conflict.cpp":"440c42309e090c11c54259d0b49cc02eba856d11bd22b61e5387514ce7e432a4","tests/expectations/assoc_const_conflict.pyx":"84d5b4e58002f6062acce657f6a065f6782f4cab35e12f537ce44e82c84333e7","tests/expectations/assoc_constant.both.c":"7331702e91f98099690443a149bda315eb2ff4e49371351593fdd559458e75f9","tests/expectations/assoc_constant.both.compat.c":"81ebecdf6d838244b3464a8d9c1b4ed6caeb7ab43c17170e5faff006d60e2fcc","tests/expectations/assoc_constant.c":"bc24ec8a76c6bbecdb42593051ec1c87286ed5afe6ae5207dd978191b506f8d6","tests/expectations/assoc_constant.compat.c":"d7c4e031ccdb61b2ff04c99a755ffdcb9fb090c7a976c1739596a30852f85340","tests/expectations/assoc_constant.cpp":"d9d1a1724c6967e9534601a966279cecd0358999db241e17db5221af7427578d","tests/expectations/assoc_constant.pyx":"8bd9db9c6bfa3e007105de578edfc2dc236f61d6c290cc460a447aad2f4454cc","tests/expectations/assoc_constant.tag.c":"7a2669d2332623ef8e9bd605203f09dabe905c568f5f0162153e2e77ec7ae6fd","tests/expectations/assoc_constant.tag.compat.c":"d71d82758c132208ba453e876cc6e2e7f5afb1b537fbe588dab6cdce62a8ac9c","tests/expectations/assoc_constant.tag.pyx":"641a6a40d67f91dd4ce9a6f14b6f39e925e343dd2e3b3c6dd15ffa7da457022e","tests/expectations/associated_constant_panic.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/associated_constant_panic.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/associated_constant_panic.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/associated_in_body.both.c":"64073eb290a508f2d90544c9ec4eef700cb81450940c84c428987193648be911","tests/expectations/associated_in_body.both.compat.c":"0ddc87d364827469f0e1508cd7b79641c4d9e4cec86505df7d2b0c6ae5ec0361","tests/expectations/associated_in_body.c":"61e8d63bce9dcf0266ccdaf7806a1d599a652488a402ea0b18cc2ecf39e1a179","tests/expectations/associated_in_body.compat.c":"b66dbaae1a4e36580ce0b6dba97cf9d9faf51b99c66fe80ab0183853ac682749","tests/expectations/associated_in_body.cpp":"1a9d135f8f0bcd5c891f9c1d62b16b79197fe347d712106b07748032544ab57e","tests/expectations/associated_in_body.pyx":"c7178a28201a6934f367d1906d7a49635a29824193b9e866c69464ce9a5a0daa","tests/expectations/associated_in_body.tag.c":"17c4c60744b692853f56e3e2907a9d64dc3cf1177f23aa867705c26f5c4f1548","tests/expectations/associated_in_body.tag.compat.c":"5b1064ec35ce9cb901f74244440624feb16c0dd5a019c61c7c27301d46fc0cce","tests/expectations/associated_in_body.tag.pyx":"cea0d58bef114ee79d82451e413c470b40b16500ebe44b8745dd8cf15d949c00","tests/expectations/bitfield.both.c":"684e0e0e909797238ad7e47b41dc3c9cc854c072724b9bcdc745bd2aa246c102","tests/expectations/bitfield.both.compat.c":"a4e4503e6e6a8ff59aacaeb641c37c78a692e1ace60fb8a2e069143211d5ce95","tests/expectations/bitfield.c":"45df0bd7774d3d63f745a34880e189c18a26a840ca4ec7f350777a07ccadb0fb","tests/expectations/bitfield.compat.c":"8e13a28fcce8570a47179dea123be18174af1a7ad73743a238bcb7997e3caf03","tests/expectations/bitfield.cpp":"29496ff002d05ead46c3138bff1de7d0ef6ae3fb1861d78699659a00227b2b2b","tests/expectations/bitfield.pyx":"b3209227b52c338dc12d5e1c9f4915be54fbabb8f04bc3d7eeed359faf298654","tests/expectations/bitfield.tag.c":"570212e779377fdc803539aeeca8a3ccb639c53341cdf044684e374bac4d1e9c","tests/expectations/bitfield.tag.compat.c":"1c40246f2a4e43be091ae835e02a72421d74e1f4f2d13ca7a18e051ef61c08e7","tests/expectations/bitfield.tag.pyx":"89580c6294bf5aa09afa748b708d2c221b0473fc4431f5fdbc6565bca086ceb5","tests/expectations/bitflags.both.c":"e2109e0ab8f9384ce0b3bd9e631f8354fd4a39a649f65ba2af08ba04da6ec0b5","tests/expectations/bitflags.both.compat.c":"c04a4f3ac1b8c62ce55d24a768829e505814c9891feda19cb7055d2f7f40fc38","tests/expectations/bitflags.c":"5d60a7fbfc6c2040cbfc7f07c0af7d30f57bfe400d09f7ed79658fbb19da6e0a","tests/expectations/bitflags.compat.c":"8ca16f80c7e4c4a57313c0797436f0bd98a8f6a2d2bb06ba108dda36e17f61dd","tests/expectations/bitflags.cpp":"583ed57057def6bda93a2ed561e42b5dfdd5625d22601864b8840ad351f2dc7d","tests/expectations/bitflags.pyx":"c6ac88988cdf42f94b5859911600b16812b1222500ea104a8bbe0a5bd1c659a8","tests/expectations/bitflags.tag.c":"13ae1d889b9082b5addedb079e9cd198dbe35cac614a1e42c326fdb57ed08bf0","tests/expectations/bitflags.tag.compat.c":"207d34358a4a978824f9dc663c5a2b3fd5a056280d8b0dc378bb0d4cbb1efac4","tests/expectations/bitflags.tag.pyx":"2bff6611e1abd58056d2582246877bea38479c648367a9a2e5e14f9573dff5aa","tests/expectations/body.both.c":"b5b4b17c7545bb60b6b113750b6211ea012fbaf323a9f7c0a6f22bd502b10eba","tests/expectations/body.both.compat.c":"ab2ae390bff1c669024c0f57dafb6c39223124eb7fee5f774a26a24b7b745643","tests/expectations/body.c":"83e6548451a14b54b482fcf15765097c5fe67296f211ff0d13487b440fa3f205","tests/expectations/body.compat.c":"4b231ba3e4a9a5d5d15c905dbf7825af4afd00f1f418154d76aef0c8e820625d","tests/expectations/body.cpp":"8f033a0b3afaae1d37745734718539549951e9c60d66a12fbb09e974a09c2704","tests/expectations/body.pyx":"f80e234950b3f1fb08a22b49541f483b855e1fcaec5b826249aab46c22a0945b","tests/expectations/body.tag.c":"c93242bff38924582159b58214ab5aac7b24345139081037cc437fb8a58002a9","tests/expectations/body.tag.compat.c":"b6f862490b2d3d030eb6cb8246e44bae069010a7df448ff3978a75de1c726d37","tests/expectations/body.tag.pyx":"ab304c830a1938e7ae60af8e9f728ee6ba6be38877bee4061bfaff27fab45de3","tests/expectations/box.both.c":"033db62bcb5592eeef95df3ca03d02918716a13fc4799d5e1ab20b42174323b3","tests/expectations/box.both.compat.c":"0d8ba9b1d689008368bb237771f994254c59d4abccb4606fe92dba4ce398abda","tests/expectations/box.c":"59a66035f60097cb270b6a46726b16f6930b57735723f7741c47695405e1c5f1","tests/expectations/box.compat.c":"3bc047168d70c56805845c3453d1f5fc608dc8f220e18e1ac433fe7a764f3989","tests/expectations/box.cpp":"5ac330bbf91df9cf320d6e95a9cf7d156e1c2e8dbd9580b8d1d86e2b96825836","tests/expectations/box.pyx":"d64f95840104d9b0b4eeeae748201d223f0b27abdc1864f57e149909ce8b2d54","tests/expectations/box.tag.c":"b1f5a20002ba352099ed429040529ad5a2bc96ded7d6cd75785cf9aaf44fe309","tests/expectations/box.tag.compat.c":"aeeca7f7466eca2360bc8b34aa7b8f932f3763761943ffb910eb7114bcbefe71","tests/expectations/box.tag.pyx":"4407c8277cea35090db1a46485892fd286f408b89255bbda28c7bc5a4c6397f9","tests/expectations/cdecl.c":"e49da32919797ea6d6ce3f4fd7a967ad33ef1dfa3f323f15181cca5f9a1fc98e","tests/expectations/cdecl.compat.c":"80ca597ab6be6a89310ed2120e62192b6c957cce02770218e11eebfdaa730282","tests/expectations/cdecl.cpp":"3242efce31ba876da3554e8ecaf3f7e89fae84537452d778d65dc1b1e4f31620","tests/expectations/cdecl.pyx":"91dc1444087738b3d108c19378391b92eea1660810829f3f3e02544c12e3a7c0","tests/expectations/cell.both.c":"40742fe09737aee76007e9fa879b9ac9c913f634cd1736e64adc1e246d3caa77","tests/expectations/cell.both.compat.c":"7fe548aa4cc0b4a05c2c482e70e11680a70ad55cb4e850ea3253e4194582e66a","tests/expectations/cell.c":"4018a58ca84d08753a690c93da2f520de98764b738ee30cc6fd06c890fafab2a","tests/expectations/cell.compat.c":"f2e80372856f6589327e56d3173ded3c8fc69ce714ae773865d96c04310c7632","tests/expectations/cell.cpp":"fcfe5b2f9d546cfaa5654135b1b8c0202ea23070d758a0ab7c74c4cf84df59d2","tests/expectations/cell.pyx":"2e359ca33d41e2e4c8586070c8484d20c07f5899e7a644df11d7bbf6149a6bef","tests/expectations/cell.tag.c":"87d4eb265f6c2313033cba74aa83c63010e0ef5f0d7de4cbfeab42429c379449","tests/expectations/cell.tag.compat.c":"77eecb7243f1dae0261e8c2fd2ba988eac4c0f455bff18ed7dcccc643205e838","tests/expectations/cell.tag.pyx":"6350674fd920f0b2e2eeaa5d4acc031a3945132f06fbb9e58ae5fbc85e03cd3e","tests/expectations/cfg.both.c":"7aeb06484d7d48fcb804f0c2490363271c68c46f88021a80f6b4915d03d59652","tests/expectations/cfg.both.compat.c":"af8d86fd3169f728e278e36639dd5a63ae574a0fcef074f1c21d2ecc35567697","tests/expectations/cfg.c":"9c6e2458b9b3e3c850dbb5c91598d0e9e6ecaeec776dedb3c308e2b922da09f4","tests/expectations/cfg.compat.c":"0980c724257983a39b37d4b8a4860cfef8619db7efbd06868f732f25ab7c157d","tests/expectations/cfg.cpp":"06fc52674e19706211b1f8386e1763d9a1f20d2f72453eafb9eaad3c85279a69","tests/expectations/cfg.pyx":"9abda332fb51d0f2e38f6e08d79e9f6dd28468d2415af1c90ebede91ca04c16f","tests/expectations/cfg.tag.c":"ad78b20b4f24ad6bbb1a7872c7ee4f0442407ed67fba3a69f24caaa807eb291c","tests/expectations/cfg.tag.compat.c":"f5fb90cf6ac7823e7c558bbb45e8e0626c6f26bb4ae2305fb8aee45c26534ccb","tests/expectations/cfg.tag.pyx":"132b50acb9af10a52f21d3623a1368bd2e8e3462843969bd1cec90aaf7ec0033","tests/expectations/cfg_2.both.c":"b93e3faf89cef94e5190bffe0535cdbdd39ecc1848ad5ed21b12a1d602e8980b","tests/expectations/cfg_2.both.compat.c":"1a22e353b9cad1331c2a34eac2f6c3c8aafb850242f6b1a8989690d9f4d6827e","tests/expectations/cfg_2.c":"50ed9a839309444b5b7569e7a5e3a29fa331ab2b11c5cc1169a174b1ed787dfb","tests/expectations/cfg_2.compat.c":"102606e339afdfe5aba1712c5af7a343b39b97b118e6b5013aeca0fffc2bbd8b","tests/expectations/cfg_2.cpp":"06523409a17cfdf1f55562859d3ca2b5afa6775370246d6b1f34d52ca21b9c0f","tests/expectations/cfg_2.pyx":"64cafab8f478bec98d24f61262cfa9fcf7350fee9ef02e36541d72906fe256cf","tests/expectations/cfg_2.tag.c":"a2199043d58396b92007347dcf8e228ff2ddbf66360349300264305cfb2c324c","tests/expectations/cfg_2.tag.compat.c":"2475f0db5d5fd92306596f95b67ce0b35dcd8b0811f92d06c6a043cff6bf3b51","tests/expectations/cfg_2.tag.pyx":"46d11bbad61c3776d5a5691f8a792314759dc5193291c339c92f9774432a031f","tests/expectations/cfg_field.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/cfg_field.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/cfg_field.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/char.both.c":"3a120740886f111014128581320eaadc537b30717b946cb110004a7fd1c56b35","tests/expectations/char.both.compat.c":"96c4dd607cd73faee95d956ac87922c3ac809fd9d68ced25f6da91b761638af2","tests/expectations/char.c":"2365acd2244ddc250304b59a830ea27ca485f834628de95d419de0a91efc2965","tests/expectations/char.compat.c":"13a7c3b21783a5b815af46548021c9c93a74e476b8060aa4e8357bcb7f221936","tests/expectations/char.cpp":"7612cd7d981224c74d0829253a2da2dab788a02773be4c0b2634505c0f59b0db","tests/expectations/char.pyx":"9521eb16f9d0491dd39ccc10b6ef3ea9a582e0903482f692cd2dbd19603fefde","tests/expectations/char.tag.c":"8aeeab4c3c0b28c9cbc6177a20bd5d85e98454b5c871885efb8b1d9da9a79aa2","tests/expectations/char.tag.compat.c":"f7fc5f73c50ae5f2f4348f4c8cda4fca318891339254f37a6a58762a94c1bba9","tests/expectations/char.tag.pyx":"565200395f89d5d2572815bd38dfdc4d5f6787bd0ef23aa293a7451ccb5b5755","tests/expectations/const_conflict.compat.c":"bb2c53ac57d1b53f5e2ec0c0140d3d309d9e92158953f46b04708f3d86d93b67","tests/expectations/const_conflict.cpp":"440c42309e090c11c54259d0b49cc02eba856d11bd22b61e5387514ce7e432a4","tests/expectations/const_conflict.pyx":"84d5b4e58002f6062acce657f6a065f6782f4cab35e12f537ce44e82c84333e7","tests/expectations/const_generics.both.c":"0b8df13162108de95889c5cb93e8d6e41e8e93728c0780fafdd143d815e64c91","tests/expectations/const_generics.both.compat.c":"2cb5e46155fe47fb1031627006e6d76ffea0e290afe295ed6cf1c3008a33243b","tests/expectations/const_generics.c":"1716cd634d1a7492324ff4f9b250e27d50976121a10c680e4686f8190e5d49ed","tests/expectations/const_generics.compat.c":"c33873b08bd0bbf583771e54919e1d4409bb9b44b367bfc38e45321deefed44d","tests/expectations/const_generics.cpp":"0ea0b84bbf5972698d7f84d06425c47bf61182207dead1a41c3b37541fdcebef","tests/expectations/const_generics.pyx":"17a3b2d36f061392e3f31d4a59d99ffb65b92f21c2806aecb44be7fd9dbd6e80","tests/expectations/const_generics.tag.c":"5cb1b9e1ee1a1271b3e5ce8e5083cc4b2374a2623d119540e015f23bbcde9fc1","tests/expectations/const_generics.tag.compat.c":"11518acb3877ff50d341abee03c3cc6da81f2c0322415c5132de2a24a420ec46","tests/expectations/const_generics.tag.pyx":"8fc7eff13aeb16ab2ce169bd142acd64e5b72b7ca08d2815efbce992bc869db9","tests/expectations/const_generics_arrayvec.both.c":"26ae374121029c59e6972cacec466435bccd7c5c1e5643704982d9f3bd82a156","tests/expectations/const_generics_arrayvec.both.compat.c":"6b429649f99d07ef4de05fcab298c4a77eab14c83b47da9f54126a2fd915d4f3","tests/expectations/const_generics_arrayvec.c":"389b0e3f3558d8d2f3553c604fe389490c48bf4c9f4583c09960c49c1860c3bd","tests/expectations/const_generics_arrayvec.compat.c":"895ff714acab3b8a26e89714e9016e6bd24c9fc1deed13c4963f6495e3521f2a","tests/expectations/const_generics_arrayvec.cpp":"70ccc080eec6b913bfe4901e40bb15e9fb27569b9f909a5faba734e50b01dd2c","tests/expectations/const_generics_arrayvec.pyx":"0abcf0f834698bdb5ed68ce77fbc24a53d371be4b4bdc73afebd321a00ffd6c5","tests/expectations/const_generics_arrayvec.tag.c":"afadc3c9ac58cb8864e9fb4e3f93294d5af68e76866c5ee5a0b5bd09dd841349","tests/expectations/const_generics_arrayvec.tag.compat.c":"cace3169b7bdbbfbd07a7c176de4b853aafb30c70a2f9de545a04d7016c042fa","tests/expectations/const_generics_arrayvec.tag.pyx":"80c0cbb038d5a59378c0a2095d15d60e98fb69d25befb36a11e6c8a0734be87f","tests/expectations/const_generics_bool.both.c":"cffc68aaab6384e661e2918bad8afe80a98e64b323a00b58d7a60c4e7e373806","tests/expectations/const_generics_bool.both.compat.c":"8a9a5ca67d85cc18a2ff5747bab3fc27af3d45ed0b15876129119290f84a776e","tests/expectations/const_generics_bool.c":"576fddca98f1366e0e7ad9904265ddf1df8774c091f9bbba52d98de7584b4107","tests/expectations/const_generics_bool.compat.c":"2a795fd4d18c0a14747d1079bb7b6268cf238b7195ef15600506edd3fa423111","tests/expectations/const_generics_bool.cpp":"b515522d50277cd573377871c34bbe90cbbc50a0405944cc724367488eea4c45","tests/expectations/const_generics_bool.pyx":"f86e3582bae096db1a42a4832dca53bbd32a19c35f70380aa5bf51f28da39b73","tests/expectations/const_generics_bool.tag.c":"d468a61f92045aeecfb8e1a4d2afe306069b86b24e2d86056a49546aaeff901d","tests/expectations/const_generics_bool.tag.compat.c":"28f5a25f5a56809d221fa3e94b919084617a0daca18244f766428cc6ad29e7f6","tests/expectations/const_generics_bool.tag.pyx":"987a33d986b409befe581784bc8a2d2f616245291e05e72f3adc37d29cfbca36","tests/expectations/const_generics_byte.both.c":"3dfe00700ca408e4f1baa7053620511b49d0cb73dc01b1451f42cb1acd782cd5","tests/expectations/const_generics_byte.both.compat.c":"761848e8c69f54869dd8fc49bfb464fd9d14be937e71f92cd2c7752a37e8acb7","tests/expectations/const_generics_byte.c":"b510fbc557762a6ae270293c4905df86b9c6930d8ec09b18e95fd712dcf95cfe","tests/expectations/const_generics_byte.compat.c":"363cb9bec3f998cdafd8124e26bc19e4e62c87e3ab20c7f1f34a19b0f5fad9c5","tests/expectations/const_generics_byte.cpp":"47f6a05dad514ccb2848bfb125b49567ffe29d971a1f03582d50d89d5ad14050","tests/expectations/const_generics_byte.pyx":"f3fa4be5d6756bc54af31b8029c86ed3372204f3569d95bdc8a5dbebc171a851","tests/expectations/const_generics_byte.tag.c":"6d593dbf6d779c6de9d888ae3e26c088e3c3fc4cf48ca5956ed7f42044b07b0d","tests/expectations/const_generics_byte.tag.compat.c":"f984b7735576a6feb1a5b7b52f6b7d7672375d2f87386bbfe596210fcd26642e","tests/expectations/const_generics_byte.tag.pyx":"477173eed61ffd33731a13c553ef48468172e9f814dc3839513222c9b7f3ed21","tests/expectations/const_generics_char.both.c":"7c2289524849937ccf1250e8846d9625eb5e1be4d72749fb2e924855985d1327","tests/expectations/const_generics_char.both.compat.c":"ad0602c33225385d0f644d0e3de9466ff0f023de644e3a9e24108a45405e254b","tests/expectations/const_generics_char.c":"7b272f23ef1845e2a9804c979fd6d223a026a78645704ffe9dcacf0794c83f2e","tests/expectations/const_generics_char.compat.c":"016055fc5fedfd638340bf902dceccd4f477dcc1297476528d4dce909a791cb0","tests/expectations/const_generics_char.cpp":"830d9d84ad904715cb708ed482e5973beeaba18d68e8bd69a3bce231ab385e74","tests/expectations/const_generics_char.pyx":"085bd0e5835ad6745ec592f0084a984899d9bc1539af8d9a99256e6146ded5c1","tests/expectations/const_generics_char.tag.c":"224d76c50dc8b0a667cfafe9f3594e6492ab010729bca4d02db2f5f7a9e01f76","tests/expectations/const_generics_char.tag.compat.c":"2c9bdd92f8988203e26d41fc7855d08dec0b01c517565b27a1a7aebd3012575d","tests/expectations/const_generics_char.tag.pyx":"ca3981c77afe488d789f51d9d35a548143bc2284a18b08545374bbcfc4e65b54","tests/expectations/const_generics_constant.both.c":"f5f0f2c5f31bc0f6b1ecbe8d36c0dd20680122a52ed88c8a4f40bfedc0dbb2fd","tests/expectations/const_generics_constant.both.compat.c":"2ad6d03c4ce769af51875e51d413cbb5c6107a036ce386c6a51e1ec18f6f218e","tests/expectations/const_generics_constant.c":"187e99eebe98218cf6398e27ad6dc9aa0cdfeb664f123454905ff9d015b95cbe","tests/expectations/const_generics_constant.compat.c":"b14b2167e6c5e067065b1da0079e4e0caec000626da0926a0cea9f083e12556d","tests/expectations/const_generics_constant.cpp":"5d38b085ce11c7354eafc6b3aec72affd1e8093b2ae7e8edf2c13a31a61b714a","tests/expectations/const_generics_constant.pyx":"a098babec8b10c4cae3f8c97e2ec625ebf7dc14561b1251dc92c69c42c87edf0","tests/expectations/const_generics_constant.tag.c":"31c0e515df992991f74633675694b92aa420f30a05f482746010bd4cc1c79087","tests/expectations/const_generics_constant.tag.compat.c":"6aba92e6e60cc1146b869747bf9aba4a0a19f20f43118d8d4ce5d92e643db326","tests/expectations/const_generics_constant.tag.pyx":"e5ce1ddfdff4e6776879aa1f8d606f6e2c9a469465dc56d250a434e9ddda73ed","tests/expectations/const_generics_thru.both.c":"9199534a9b676c45bf00da22c8065d4c95771cd4d36bc64ef8fb3b16251648f9","tests/expectations/const_generics_thru.both.compat.c":"05afaea3eacf926f12f5ef0ac8f1effc759b1dea9f3016f59d7298748ad337d2","tests/expectations/const_generics_thru.c":"a18b0349afb33d020f12ea22a1b22d4175ef3115ef3dc9a4d8a43919130e9ec8","tests/expectations/const_generics_thru.compat.c":"b67ba7cd9330b9040d9dd129d829f39a9c42d9b7c8b234f570c2b2b62c833aca","tests/expectations/const_generics_thru.cpp":"fcfdc43f14bcff84e2fce8c6d4477636268be21a1e013d3164cc7aba29ea3f3f","tests/expectations/const_generics_thru.pyx":"59171efe6927fe45ee5ad4fc2fc437e6f80438dcc97dc192f0510c3f2fd891db","tests/expectations/const_generics_thru.tag.c":"1535d2d6d01dfa94ab4baf35be71540cc6319b6eb03074ec414b186443972015","tests/expectations/const_generics_thru.tag.compat.c":"450bc656d7d5ddef25b85203cd0cfcb80aee20e30df7eb552c4ca8ed4c312bc2","tests/expectations/const_generics_thru.tag.pyx":"fe4d631f466bf0fefbb77f50d2c18d73271b1cb20c4b711ea880900683106c2a","tests/expectations/const_transparent.compat.c":"a722d38646474b075c37c7b34d2a1dc824df82e804e4e41957cd1f339e2fba4f","tests/expectations/const_transparent.cpp":"6c9b46b989a08e8045735301456f207471b03547bd83c4c654c3cdbfdc9e1ce8","tests/expectations/const_transparent.pyx":"721caf7ea1e2a7d5ebca1670134cfb42f6a16969e192a52f9db815f10073010f","tests/expectations/constant.both.c":"deed4e341fa8b41884bff5af299df73c59e40cd4e8a63a77dd42619cf28e9d38","tests/expectations/constant.both.compat.c":"e8462d4ce6efe917e166263d3625059493a71c3c90e9a2b48bdb9710112ecd22","tests/expectations/constant.c":"129d9124d4c99e28f3bbbea1d527023582b118fffc74000f75eaa5f5c442a204","tests/expectations/constant.compat.c":"4b5a76782d75be1fbe5a06f776bfe3394d7959f368bebdfda7e1458ea72f1303","tests/expectations/constant.cpp":"352ef18aa9c1b431d1ce099606ed6295d1145d89afc4670a0f0ba90bad218ff4","tests/expectations/constant.pyx":"1c0e93bb36fe3eddac86263ad00296d7e65ef27207435dad6497c92be23ba101","tests/expectations/constant.tag.c":"acd58a2ca6c5c0991a9d7c47b39ff967bc92ef1fba415ac58b05cee1a5ec83f6","tests/expectations/constant.tag.compat.c":"2ad53667d23ddef7899a3119e2f28ff91f1adc0afe52236723a40da4993bf05f","tests/expectations/constant.tag.pyx":"9d33c799f8032cc515487e60c25c24b980ce94b30a90aa0fabd067f3caa8b1f7","tests/expectations/constant_big.compat.c":"eba7da537ec9ac4f2c772a398fdd7b5385dcef75698899cf58d85013dd03c2bb","tests/expectations/constant_big.cpp":"ad4e09aac8611e1c0e9235f6912a0a7c6bfbc82d858c9005525c6e381921427a","tests/expectations/constant_big.pyx":"2e31bd9e3f0df266ca8e2ae0edca7f0dae59e328f83b7c8914aec4ce163623ec","tests/expectations/constant_constexpr.both.compat.c":"8b498a1a11e995d17cdc1b9d74d2cec3051af5601d195adee1954b5675457a5e","tests/expectations/constant_constexpr.compat.c":"7f540ae608e3240cccc763f53e5ffcf279a3ab5f737f055e6ba1be6708ffa905","tests/expectations/constant_constexpr.cpp":"0b691506eeaa5729c2a8d8a31420591cdb7d45f2d8767e61b60ee90e516518e6","tests/expectations/constant_constexpr.pyx":"500df1da145ac960629956a3b7a2d93a1cfd8526a900e2985643dbe5c892638f","tests/expectations/constant_constexpr.tag.compat.c":"097adc133ca25bde9ebad4a63fe77d26759fa14ba015127a160d9c0f869caab3","tests/expectations/constant_constexpr.tag.pyx":"8e2fb6f28152d22ea29830021add535b0313353f93c65cb012655c3d4316fa8b","tests/expectations/constant_sort_name.c":"733b9a46e8b9e33cb8696d13e74ba7b8023735c8fd8dfe73b3cf39d027dffb38","tests/expectations/constant_sort_name.compat.c":"82bd07c1f56913bca006c3859f222feada9ce53a53444702c5c61fd96943ec49","tests/expectations/constant_sort_name.cpp":"fbccd8e8d4d4f8461dbc20251d4138e16f7a06745b04a0421537fd94a3292be1","tests/expectations/constant_sort_name.pyx":"676a0026c90d31ca7339b4124f79e2da27198723b62410396b04984e72268070","tests/expectations/constant_sort_none.c":"7839492e03ffac12c0b2f5a15bd4b32aaeb20d0c50440fc392fa2cff9b585f83","tests/expectations/constant_sort_none.compat.c":"3b59ec576d09ae51f0db0f8c34bb9787972cd8441ae718117568f9220c4f0cc9","tests/expectations/constant_sort_none.cpp":"707da6714a41880e7062c3ccf4088fed204572cd612cf9411a208e847566e348","tests/expectations/constant_sort_none.pyx":"da6f1f7ca130359c87ad502e3e1367b20a6f0b936dd036a5caa53181bc51c099","tests/expectations/constant_user_defined_type.both.compat.c":"c6c7e161438bc7d4eac09336b05950bba88ffb0ddfe39691ad288fd8db6825a8","tests/expectations/constant_user_defined_type.compat.c":"a723546e5f6a7bfe3caf8f8f687f8b7c457cc57defffb9082db07a91eecbe3be","tests/expectations/constant_user_defined_type.cpp":"1181a923e46ae423dcbff4d0308befb67b5274855ad75087b6ef5e61e7c70139","tests/expectations/constant_user_defined_type.pyx":"14f8acfe6db6e732931eaa3f5f8a4e9daebb425d64710fac1b72ee0b358a145d","tests/expectations/constant_user_defined_type.tag.compat.c":"0466a87dd60eb403f4f376639464e4b9400dd00938bd5166e131aa1715ff9e89","tests/expectations/constant_user_defined_type.tag.pyx":"b903a4e223c02cdee43ce21facc1958af978afa9e7e7f45f82414de77169a405","tests/expectations/custom_header.c":"30083b9d26f8f022945e85fae85ed3608a47e105217b0595ff64d103093bf3d6","tests/expectations/custom_header.compat.c":"4ac0644b644b1dcdd667a5e981ace55e21e0064ab83f27c59ff7fb0eab9f4861","tests/expectations/custom_header.cpp":"16875359466b19aff8885d62d20e499abf68675a2ae7741e2bd9c0956f87d9f1","tests/expectations/custom_header.pyx":"0540db55e6c4955d2841048feb2c4791e498bc06bac5d884cc33473cc642a316","tests/expectations/cython_options.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/cython_options.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/cython_options.pyx":"03c9cf870f9e143f0a49f10dc8c7a7cbecef2f524f041ba650790ee00940139d","tests/expectations/decl_name_conflicting.both.c":"9efc49c435bb6fb7ef52b331d1957fc7e965e49b31f3934a19b9847ab01e661e","tests/expectations/decl_name_conflicting.both.compat.c":"7837b1477436fa876cab383a253de885989b8debee61eeda124bf3bfcc0f5328","tests/expectations/decl_name_conflicting.c":"98a84351d4fce32d41467d3e54a90828faab5c3bb438e4039fc5f96e021a9c00","tests/expectations/decl_name_conflicting.compat.c":"d17848bb72edd047c20c3a1d291cc1c1e6b68867ac42f77e2cdadcef7edcb0a7","tests/expectations/decl_name_conflicting.cpp":"44a51f5fab3e1f87c2d92535a2d36657bc21c317b53bd93a35720949abd453f2","tests/expectations/decl_name_conflicting.pyx":"6b1c840be79f4f89486978c7a133877274bdb712ccee9af963041780d2b54b56","tests/expectations/decl_name_conflicting.tag.c":"55d25744b93c9cd59f9fb22aff48a981fce1fa994b0c279e0b2f6e73569bfd3b","tests/expectations/decl_name_conflicting.tag.compat.c":"e430a6eb17a1a0fbd52431f1806082f4baba20cfa9c7d654fd499b8bdd7bb885","tests/expectations/decl_name_conflicting.tag.pyx":"edafee5ca19add0925a0bb4eaa4ea7efed8d0b9c2a64b0c97653714c8cf9dd88","tests/expectations/dep_v2.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/dep_v2.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/dep_v2.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/dep_v2.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/dep_v2.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/dep_v2.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/dep_v2.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/dep_v2.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/dep_v2.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/derive_eq.both.c":"0a42ce7794512473d32b7ff91f789b188af91c3c69ee6b6a9d86e82327129bd1","tests/expectations/derive_eq.both.compat.c":"d628768393c2420530d2628ced1e4447e583f9f386756fdd547f9c92df264852","tests/expectations/derive_eq.c":"7b914984a98209889a6f9f4314f1347c4128deb26cef8f7b5b678206d5752bcf","tests/expectations/derive_eq.compat.c":"be14695942908f4d976b1ff606c567347f4ddf3fca40f62c4e1926231eb0ce10","tests/expectations/derive_eq.cpp":"21d619eeb9fa71fdcd35cdc4a29348b340860d7c7474b5b0231845b071b8cb59","tests/expectations/derive_eq.pyx":"102c2505a974086507785589249f4349f0de5493c5672340e59dcf25bbb4fa7e","tests/expectations/derive_eq.tag.c":"7a28b8245621034532bd5af2c018bb0b62effb8b62a1076df143209121c42317","tests/expectations/derive_eq.tag.compat.c":"38dd43a0e5543dd566537512767131c41cfa6ae56c17ca8e14aee32076e879fc","tests/expectations/derive_eq.tag.pyx":"73aa8f84cae7e397fda4c1cfe6503b1df5e4ba820b64bd57311d2464214491bc","tests/expectations/derive_ostream.both.c":"0c225a59b20e6cd10b82d1e3fb4bd158e2f8ed6ad664953974cb80fcafc3fc76","tests/expectations/derive_ostream.both.compat.c":"1a7d96d572abd7fef9375e9ffe0e55f0a290a2ea15db1b1a9dac287632a73cee","tests/expectations/derive_ostream.c":"a6e8faff52219d4f055fb2fc193109e64af7413433dd49521c62a8914fe078da","tests/expectations/derive_ostream.compat.c":"74794d970127e90872aef5cf21be225e64e1e20b0d0509eb7191f3d8c422e4f4","tests/expectations/derive_ostream.cpp":"bd9ad020c82e15b445bb40b58e458f05262c706dcc19e20f40d224d53c79faf8","tests/expectations/derive_ostream.pyx":"714d0f4bc3f6ddcda46a01d827769cf9c5a81e8d47a5311de1904319750cc06f","tests/expectations/derive_ostream.tag.c":"834713a0931d81ddc6e88d5988d46b87004aca955e37e2cb156621740cb6ece2","tests/expectations/derive_ostream.tag.compat.c":"83e5c3c4c12b52f073ce71485c42d01b280c01596226ec602c384038425b31aa","tests/expectations/derive_ostream.tag.pyx":"2a8b513eba477ee274aafffc34a4878806f1a6000b054fa427d3aaf03ffabab8","tests/expectations/destructor_and_copy_ctor.both.c":"e846eacbf7f762b32982531b6490b94ed6c2c7ad998bf7c898c676d435f7b0f5","tests/expectations/destructor_and_copy_ctor.both.compat.c":"f6dfd8d30add21605134458c1e59ffac0e01903afd378928bcb6e01f721d3b64","tests/expectations/destructor_and_copy_ctor.c":"c4097f05b1c764d8c038225c407b145d8e1660b1d1a155a17afa04a2009e365c","tests/expectations/destructor_and_copy_ctor.compat.c":"645f95a9ade1397eac35b678f1c212ca4d933807a9083952d1d58c2c0fb736f1","tests/expectations/destructor_and_copy_ctor.cpp":"5e2842b4831b25c278dbef666a3a051411c79ea137245e67a25c2ed8850ea1b8","tests/expectations/destructor_and_copy_ctor.pyx":"db1dab0bc08747a35178cd0e8c37fad8f98886bd6e0b82b43b84cf49b2ed42b4","tests/expectations/destructor_and_copy_ctor.tag.c":"025a21e8f3974098ec52fdbc331f38c0c9643041597c3756a3bd40d4691092b9","tests/expectations/destructor_and_copy_ctor.tag.compat.c":"3b8bc3684ba0d2474208f4b28cb2be5eb1f551bab5c498dcdb7a353f0e537d0e","tests/expectations/destructor_and_copy_ctor.tag.pyx":"38c2803307cefc9fc6f8c85564397ec8d35241348a75b70abaa561dd65e62bac","tests/expectations/display_list.both.c":"a515bb0077634f77f023ef62f2ede36cf8326fe4da5bdcd2e800692c234e6ce6","tests/expectations/display_list.both.compat.c":"a1b785b368ef3b4b813cb8a3ec95089b8dbf772414dfefee585fb633cd2faa8e","tests/expectations/display_list.c":"f3df45922f23a2ec455b36341dad5c59e3d6453aeb9a7354c0ea55b04b79ba93","tests/expectations/display_list.compat.c":"18ebf21569cb7862816cd218f8b9926e5a725d9b032d46523eb4480bae9ceb0d","tests/expectations/display_list.cpp":"b94d2065a6ea07ae0c121cebb4f510d6d72cb2dfe7b8a2001d094bbb6301fa23","tests/expectations/display_list.pyx":"ae55fc18e44a7bad123f3a100ee25178c31b45786d43eb76cf8e71afa83050e8","tests/expectations/display_list.tag.c":"886bd29c8d6b482f52e0d51c22b8d4381eb6ecf9ad6d249d0cc4843bfdbd663e","tests/expectations/display_list.tag.compat.c":"0a017a5f3d9fe253e392b44a19d1bac49a21b05d9de1029f4f7d908c819a611f","tests/expectations/display_list.tag.pyx":"6f0f242efa62500f225f4dffe5201ca8169ea345248f0c4f313edf73dd41e348","tests/expectations/doclength_short.c":"14a5f31a6e6af5ce3e01de42950b759a94a9c7ca86d822009e36b7beca77c55d","tests/expectations/doclength_short.compat.c":"5196290e2ecb33d7bea2f20b6aa22c126ccd420e001b52458dba4efc4683af65","tests/expectations/doclength_short.cpp":"7e223faf3cf18072b2b3fed19d48a56fd983b5fcd2e4bf79a894294d330cb830","tests/expectations/doclength_short.pyx":"29a356be42cb9d14454ad9d820d7fc50fc692d4fb8fde0a828659cbc97ba833e","tests/expectations/docstyle_auto.c":"34e1474c79b8a974c1e4b91a444272d954a50d7a2e74c46368a1f94ea1a59113","tests/expectations/docstyle_auto.compat.c":"e907be610c1c2fe09af9a355155df95226aa45b129d6ad5fcc4d7358793499bc","tests/expectations/docstyle_auto.cpp":"85f23dbbb3e5cf03ca1c9bedfd559b4253dd6795d8c3597773ce2dff3ac30714","tests/expectations/docstyle_auto.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/docstyle_c99.c":"dcb114c8aa34bd0a15cca9e7076b24700c3660741ecdcc41e7ddcc44bfff9434","tests/expectations/docstyle_c99.compat.c":"fe9814379b9c8795bf8ecfb1308397e5e0dbe9bd81cc9ac820b90ac89191c39f","tests/expectations/docstyle_c99.cpp":"2391bfb6d1de7679f5a6dcc5c2a1fa8b57d6a2af98058ddc6558153f64904a57","tests/expectations/docstyle_c99.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/docstyle_doxy.c":"34e1474c79b8a974c1e4b91a444272d954a50d7a2e74c46368a1f94ea1a59113","tests/expectations/docstyle_doxy.compat.c":"e907be610c1c2fe09af9a355155df95226aa45b129d6ad5fcc4d7358793499bc","tests/expectations/docstyle_doxy.cpp":"0277cd56e2bfb397cbbc9ab58ab9e91ae27cf7388ce6c081140420a05ca7fd24","tests/expectations/docstyle_doxy.pyx":"0b1bd6021b476900ff9a7bec7f1d06b8cd5de8085f50920b59c173e5c9c693c8","tests/expectations/documentation.c":"268e799c5b13dabb6796b9e233d623adf89d3d69a26c9d25d661a182a2de2a73","tests/expectations/documentation.compat.c":"b9987f70233cc3952f82b2553b2e016e85b54037b767009c1b96c9cbf9d80830","tests/expectations/documentation.cpp":"d34d4e1fbad6275e999d733083f922070bd2537e87e9024e5624da03c52eb7d6","tests/expectations/documentation.pyx":"f87ad48322fc1ebeb72589f9c88c1fa3c98da99deeb4080b62b651caac20a5d6","tests/expectations/documentation_attr.c":"7c353cf10b129591b74fc1a3492b2ae45e80877e5c00ed225e83f892a495bd73","tests/expectations/documentation_attr.compat.c":"17f61b4a39cb3f8668713ea7d50e74e57e5021e326cedd95e3f67a29d1c4d2a4","tests/expectations/documentation_attr.cpp":"044c5e034beafc6275c6a3779fedcc6570795c4033819ba065a584b339ef5e46","tests/expectations/documentation_attr.pyx":"dbdea07c97a1b0e1937c009228825efbbbb12f5a4fcd85ae6fc9912ea039204c","tests/expectations/enum.both.c":"640e36792377ef29dc2ebd6761003f951e77409aa55f2ec7738b2a18bf41facc","tests/expectations/enum.both.compat.c":"09fc4d23136543bc3ca2b10622408b24f2ba1b37cdd27cb6b2d2dc0a9ab33d6f","tests/expectations/enum.c":"d5e57784fd64677a2152fb78935beb013615366876ee9fed05bbec85e84e968d","tests/expectations/enum.compat.c":"638e52ac76133c9bbe0ad4536cac2032bc0764ff8d73f433f5120bb419c4147c","tests/expectations/enum.cpp":"e71881b5bba8a2ac80fd5562344caceebc85b5cb99ceddff4627f20cf5c15a7d","tests/expectations/enum.pyx":"655890d52693af0df6236c7fa6b01687d11eea6982f5983c46707596e3608bb5","tests/expectations/enum.tag.c":"e1ab4025b5a7796af61b88b82ecee89e0cf3293f64904c9c44da4e0a72831b4c","tests/expectations/enum.tag.compat.c":"5d01ac0feb90336268578c5d590cc1b7f4331e5566682c0ad1a66f4115204255","tests/expectations/enum.tag.pyx":"4cef4a8578e4a2225a16206f8f1acea6751f20dded407f3bc589e6eb4a13abb6","tests/expectations/enum_discriminant.c":"6f24cbb16f768c5ffb22c7e37a316aa874a903c96d2ce18c9210ec0501224d74","tests/expectations/enum_discriminant.compat.c":"35ce86b5d0a7ceb4ddee1c13ae33265206a9f5e37d830b97878ee01f16b680ae","tests/expectations/enum_discriminant.cpp":"5385c9f16a5971734309f177adc5c9715963812092944a07f1764088ca26a220","tests/expectations/enum_discriminant.pyx":"f0f9441256929c7b92c1219c6062609d423fbdf24d3fb9ed9fa04fa78b1c9bda","tests/expectations/enum_self.both.c":"d75e33232219c5ac92e7192590725aa5f808f39a2ae6510366ce23485bba2e1a","tests/expectations/enum_self.both.compat.c":"5b90d1664411cbee379141e4bd49b3747c8738abfd90f48fcd1cde20736b59b3","tests/expectations/enum_self.c":"268553d06c168f0c0f9df14d4b1825c25fe627909b99bcf4e388eaafe2c516dc","tests/expectations/enum_self.compat.c":"185abf491a7577b844ff38e67c3cdd8e33f8371b3d69cf290d3bd8455ce33bad","tests/expectations/enum_self.cpp":"9fd2c124a9498f995a00b9f237e9e99ae9b0c14777698d25e30fb105a4bb25db","tests/expectations/enum_self.pyx":"4c0da57ac648729c2b148d76b63e823880a120b2438b93429fef518524d564fe","tests/expectations/enum_self.tag.c":"0473c73442d1fe1348d552e8c51c548cffc0d61178cf2c6329fb5abcb854bed1","tests/expectations/enum_self.tag.compat.c":"8db08e1d671641c094c51ee0c488a5864b5f6a8f294d30958d66a13817078ab1","tests/expectations/enum_self.tag.pyx":"a581d08f6e2bffce62c72bc627d94545d722f1a959a032516342b1f8eef51508","tests/expectations/euclid.both.c":"a78b580e52876b49f32529ae67754975c1c33172c8bfba830cc147d3c755fb5d","tests/expectations/euclid.both.compat.c":"c6e5ee01e4dc8ffba597457db2ad5a7865f2778a334bfa468903681f5a8f340b","tests/expectations/euclid.c":"360eb8124beef4803470e58fe0d0546b64b5ee91ba7f3237de30e8b3c389122e","tests/expectations/euclid.compat.c":"4cc5da9fe161f55353c581702ca815e49c249f18d23c5f6b2b06e8ffd8a50afd","tests/expectations/euclid.cpp":"e2d7b4e83aae20151e2c1dbb96121abf4fc2fa6122485dd148dd99b7aeb97ba2","tests/expectations/euclid.pyx":"0353d7e1413cb86bb255c4b4516a7f430f6721ed2d67261b25383c17352e893f","tests/expectations/euclid.tag.c":"3a3bd68906ca709c4d7eefdea0021cf9117a83dd87a2bd9200b0b41cba68ba20","tests/expectations/euclid.tag.compat.c":"891ae3746e246a2e814a02f6670a025347fc792e956c242782cba4b8abb53f9b","tests/expectations/euclid.tag.pyx":"4a8efd3be848dfdb1e4beda0133d083b759e2dea791711c52f466ef746292c83","tests/expectations/exclude_generic_monomorph.both.c":"b63eac0e7048c67d47e7f75993684c098ecc86356fadff0038eeb4f4f8f86fcb","tests/expectations/exclude_generic_monomorph.both.compat.c":"c6a8435506c81517b4ea8b2653723e41ce72cd4c831ea8b439cfed774043a9a0","tests/expectations/exclude_generic_monomorph.c":"41924ac09f9b3abaac47c46f7781485a83518e37548f103a19af9460a7b7b6da","tests/expectations/exclude_generic_monomorph.compat.c":"5e8839568a14640b635689c9d88824d2a63332e254bd87a437cf71ad96b5c419","tests/expectations/exclude_generic_monomorph.cpp":"b63eac0e7048c67d47e7f75993684c098ecc86356fadff0038eeb4f4f8f86fcb","tests/expectations/exclude_generic_monomorph.pyx":"c0ff87a1730876e78bd564dfa001e3115d6722c3051e938f5141d1d66f5bc465","tests/expectations/exclude_generic_monomorph.tag.c":"3e6e6f27f680af301472ff2e4d0dfdb7eec5d8714968b99a6bb30841580f4f74","tests/expectations/exclude_generic_monomorph.tag.compat.c":"2f0a9feb2d9c4eb5a14089a06682416d685122dc8b75d0b3ec427d6a23363c80","tests/expectations/exclude_generic_monomorph.tag.pyx":"6b30a5d86eca17eb132334bcde1f8a7d9a91bd9316187587ee905d73a3ef1da6","tests/expectations/expand.both.c":"977cda0bf7dbf4fb408dd7f013bc24143e17dd10987f42f2ddc9b758857b96d1","tests/expectations/expand.both.compat.c":"bae04494dca07e7c56bdc60212ff99c009930db00c95c3910d64d5260769bcd0","tests/expectations/expand.c":"fc69383c93f639f92996e4b91f296084510abe22f10b831ca628d7d11182620d","tests/expectations/expand.compat.c":"786956948cba335e44d4ec08f6cbce6aa85cec2605554ac88903ae1fc06ec2bc","tests/expectations/expand.cpp":"38f85893eaca630049af26274b6cdfd4ba9f9ad162bdce9e8f82be6f2572005a","tests/expectations/expand.pyx":"1eb4669255dd12dea709aedef09b49053ba96c83e5225afe30c07cb55a21e801","tests/expectations/expand.tag.c":"c14c175f9672e03913b278c6f2346c3ed655ff66a67889b9f9f22e923dd293ca","tests/expectations/expand.tag.compat.c":"972f420b8703a1a2f9e72e7af8ed1dab832240faabe6c2af9a72e47f000fbe58","tests/expectations/expand.tag.pyx":"a5fbf6408df5bd3ddd87bfcaf0ac7cdcd0717b42802a9a0815012d14588b1b58","tests/expectations/expand_default_features.both.c":"84118df0f668e17a54ef8a081622bffbfcff9c64856ef135ac492a90d1029579","tests/expectations/expand_default_features.both.compat.c":"4a3e098f40d2062fd1aa35a4231ce597de7e3d805eda74e4463a409f9febd585","tests/expectations/expand_default_features.c":"6bb6ecbe2d0e4c904d260fba76a4893a0284e5a794305e704886d36c7e63f595","tests/expectations/expand_default_features.compat.c":"5c4ca68e2bb67ba37949f3e87f5da85cef61a869891a239e39fcb7dc35120ba2","tests/expectations/expand_default_features.cpp":"7abea90e45ecf0ef2ab3d254e59eaea7044fcf95188e4dbdf2780c410b22919a","tests/expectations/expand_default_features.pyx":"1183233f2774df3087a3691d8c315428791a2a1fef2902250aab7c4574bacf56","tests/expectations/expand_default_features.tag.c":"7da60b618c40a23089c8f7c26c196da98a59720acf25683f32a838c52f8a8b10","tests/expectations/expand_default_features.tag.compat.c":"fa7654d64a8de65c26a109d4f4389c9fe32489bbb9dbfbb3e4c51541e3555e49","tests/expectations/expand_default_features.tag.pyx":"e509ee84cda4f78b8fd871a6a30ab0932fd00db0733fdf03883d025d1d2a9466","tests/expectations/expand_dep.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/expand_dep.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/expand_dep.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/expand_dep.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/expand_dep.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/expand_dep.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/expand_dep.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/expand_dep.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/expand_dep.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/expand_dep_v2.both.c":"9a1572f80eefff757c5fb0177780671190a92f2dc7702a932406de53705b095c","tests/expectations/expand_dep_v2.both.compat.c":"c0b4f0a494024e66e04aad69cdd5022d694fc263a0628dc12bddd43cf8fc65e1","tests/expectations/expand_dep_v2.c":"20edfb69d065d63425aec974c97a23530585ac0f86334e2a565af8b110589d3e","tests/expectations/expand_dep_v2.compat.c":"127844afc3e5e33ae47db25be10938b5a3861780361ed3d22e10f834014f5fef","tests/expectations/expand_dep_v2.cpp":"b4884a3cf2e3d0d66b810831920b46579efe08a9d26b666bc9879c66f0c15ee2","tests/expectations/expand_dep_v2.pyx":"84f008b65e42343001b5719f67a1e3c8d39e5207a656ad068ee41acc372e8a20","tests/expectations/expand_dep_v2.tag.c":"889c38974bf7c2902f7213a35112d743c4ed0b68310d3aa9906efd9f916b93fa","tests/expectations/expand_dep_v2.tag.compat.c":"d925948a283703f6b336e1b6c8e3f15e0f84d92547ac832bc101cbdb511503d8","tests/expectations/expand_dep_v2.tag.pyx":"7a22343bead8edbb687caf42eca9720b69b7c3d96e5d4ec14e71d283aaabd512","tests/expectations/expand_features.both.c":"b953f3e1c597a42bea863a9baf59de77c2d7aebf00a25c7bf03bd842a5470a92","tests/expectations/expand_features.both.compat.c":"69ab55195aa57c3f15491027e098d45b15de039b48b87e07727414f9357cd8af","tests/expectations/expand_features.c":"928314408a433b8e03ce4ec9d99a29be51de11a2a646bf00d5efaf4e8f42ef5b","tests/expectations/expand_features.compat.c":"4086173d7c9973d4ef51e4a729e69fbc96d196e9c4b483c1015581ea16961833","tests/expectations/expand_features.cpp":"71761f1030231dd7d6628f4c4055f85720186680c0ed32055df93096575703bd","tests/expectations/expand_features.pyx":"b4c443321c0f86ddf508b8bb1308f75cc5239975893aa47074e252f4d34acd11","tests/expectations/expand_features.tag.c":"307babc64b5f3821d90cce8dd7b344a665ecf5b76b76c2bf606001798f39d46a","tests/expectations/expand_features.tag.compat.c":"9316e9411d1a8be5414c0d2db09d1c582fd172661a69ecb2cf5a30731aeeb496","tests/expectations/expand_features.tag.pyx":"2654ffa0041ae74a6a80494fda866a967d2535d79f1d03224a175373f8b4cf22","tests/expectations/expand_no_default_features.both.c":"977cda0bf7dbf4fb408dd7f013bc24143e17dd10987f42f2ddc9b758857b96d1","tests/expectations/expand_no_default_features.both.compat.c":"bae04494dca07e7c56bdc60212ff99c009930db00c95c3910d64d5260769bcd0","tests/expectations/expand_no_default_features.c":"fc69383c93f639f92996e4b91f296084510abe22f10b831ca628d7d11182620d","tests/expectations/expand_no_default_features.compat.c":"786956948cba335e44d4ec08f6cbce6aa85cec2605554ac88903ae1fc06ec2bc","tests/expectations/expand_no_default_features.cpp":"38f85893eaca630049af26274b6cdfd4ba9f9ad162bdce9e8f82be6f2572005a","tests/expectations/expand_no_default_features.pyx":"1eb4669255dd12dea709aedef09b49053ba96c83e5225afe30c07cb55a21e801","tests/expectations/expand_no_default_features.tag.c":"c14c175f9672e03913b278c6f2346c3ed655ff66a67889b9f9f22e923dd293ca","tests/expectations/expand_no_default_features.tag.compat.c":"972f420b8703a1a2f9e72e7af8ed1dab832240faabe6c2af9a72e47f000fbe58","tests/expectations/expand_no_default_features.tag.pyx":"a5fbf6408df5bd3ddd87bfcaf0ac7cdcd0717b42802a9a0815012d14588b1b58","tests/expectations/export_name.c":"4c0452bf3c2901a1006efd759360882df316c2938d141906c89ad60b15b477ad","tests/expectations/export_name.compat.c":"5a2182e239b75ef0e4970431523f4ca5e3c17d43178ab1126b0833385666e37f","tests/expectations/export_name.cpp":"212eb614a342bdd626c83b790ffdfe30d985cdec4e2ff14fd38ccec4f55137c8","tests/expectations/export_name.pyx":"e10cb6efef0c0d2c7f91d9226db21ed1111464f6474acc1076390cc4ca36e8c0","tests/expectations/extern.both.c":"5864f0aaa3669aff76a2a44fdb88de8ffebf2b22a1d32997686149d6c4401b84","tests/expectations/extern.both.compat.c":"957495a1a26dac601525b832456856813542be2014f344f2aa84a546c57fc7c9","tests/expectations/extern.c":"e541f754570d2a1ce3ecf242de3b41f0437db6cbf4fb7e8505fca0ebc2088950","tests/expectations/extern.compat.c":"0d2e98ee37e668f056cf62884084ddf3b505f4a193626f098c5de20ac501d504","tests/expectations/extern.cpp":"2c9e359108649bd0f34ca83382ff77fd9c278dff4e9f9dc763012c0e1769f05c","tests/expectations/extern.pyx":"419351cf630b00068f523b6bd463ba2a74e8babd14335fc08442ff9acce71efe","tests/expectations/extern.tag.c":"1d6e6afbf9765a48cebf170bd31751ff7372d7665ea646bf2605e5df12c7e43d","tests/expectations/extern.tag.compat.c":"a9e47795357fbe2f04a952033d33d2d7bc54a47654f40c21c5c1c824137690ee","tests/expectations/extern.tag.pyx":"585a09dcfe77d89ef0cbd5e4420f1caa07f3862aa67af293347c6f92336e4183","tests/expectations/extern_2.c":"a81c41efe618612fc4b9a22d937397ce7a76ae966a28b33e56a10725cf2700ea","tests/expectations/extern_2.compat.c":"124174ff9745e397b646830ed9660faeb05910bcb340b73c925a4f8f3f656a14","tests/expectations/extern_2.cpp":"739b9b9e58af72a281402c050d6358ddf001076a64ca861a2c3a95a66cb80d96","tests/expectations/extern_2.pyx":"0c1a9e29feecbc385005b9eef2c5a5398b74d5906fc09d2127b18e9722f6308d","tests/expectations/external_workspace_child.both.c":"0c518b620f1b2bc24d789d725083cfe6f9064630b8f386123c237d9e73fa38b8","tests/expectations/external_workspace_child.both.compat.c":"1fe5756ea6f2668069d92e7cda051ba1ca0ff547fa49fcc559d07fcf33d1c8f4","tests/expectations/external_workspace_child.c":"9d9aeb31e5388158b6abf8686d4109771159d98ef83e93658d3c2e556dd69174","tests/expectations/external_workspace_child.compat.c":"3681fcbc89d3f7b91a1cb4b67bf6b64b0d08cd7722c9a6f908b0e16da9015077","tests/expectations/external_workspace_child.cpp":"32ab68edd8b25b7de5553236f624e23a25206aa3524bd52dcbbb423a8bc38611","tests/expectations/external_workspace_child.pyx":"d67d610ac34dc895c1bb1a82007f798aa71a2bd0f309026acd40bbee182835f8","tests/expectations/external_workspace_child.tag.c":"be776d880e923d640da889c22551dbc6dcacf6f80b1b8a07284bc8fcd726151b","tests/expectations/external_workspace_child.tag.compat.c":"08b1d7e35fba239e73e08a56fe2a5ec80133b46774e4047ae2eabb56e027a4ad","tests/expectations/external_workspace_child.tag.pyx":"a6bee518d269e44054cb0935a8b704f942e43d84e69e5dabf9f07f1bfff733bc","tests/expectations/fns.both.c":"c1405054701813792db17fec4156ce2940713751aea6eb1f3e2b49eb14a78876","tests/expectations/fns.both.compat.c":"4601c5ed7d383db6490afcc49927d0e94121e6ac4c0e534f4c5317c9b4b14bdc","tests/expectations/fns.c":"7c5803639ebaa0935c3fbe7aa1ed66cbf3566ee44005d14f58161ad66e9f1b28","tests/expectations/fns.compat.c":"ca3f73199d1cf506d63b746fa45edfdb8d650d2a268c64740efcbed14352ec70","tests/expectations/fns.cpp":"2f4f1079779feeb468d995aecc51b8a3cab2af8525c24f28f3b852685f7dcfe9","tests/expectations/fns.pyx":"862c85224357db387d97f90c1822b52d918839aaa2818358fbb0fec4c3dde14a","tests/expectations/fns.tag.c":"9472ed474690bd8aece9893720ef7cb0c36d9a08511b077d9ddfedfe4204b45e","tests/expectations/fns.tag.compat.c":"cf0de02321c40c8426bd6298d7f62c21d2bb96ed9985184aaa91d4f50a8716fd","tests/expectations/fns.tag.pyx":"212a5f846b1eef6999481bc82b1abd54df8d245d771c7261690c276a6394556a","tests/expectations/forward_declaration.both.c":"ec4bdaa4367767cccee63afcac538bb34eed644ea2300c46400747416d271889","tests/expectations/forward_declaration.both.compat.c":"98ddc3144866860b7b421b3cf13fcea8b96c129c2ff238a35bde75567dbabf0f","tests/expectations/forward_declaration.c":"fa1c91cefc98346e34cd76cebd754bca1a7472594291ad910eda7e3f2c70bd61","tests/expectations/forward_declaration.compat.c":"19679d72b140a9e8984be0ba72ad2db52ecb1e577e0bc9d8410c5367991da723","tests/expectations/forward_declaration.cpp":"982e68a79e1fac4c4cdef1ff45c357ff3d343d7983866be3d21bab3291225a89","tests/expectations/forward_declaration.pyx":"ad727c468b1103aeb5f96b0d81325416f0f3aa4366b9ebfbef861e769957eea9","tests/expectations/forward_declaration.tag.c":"795e52d2101989fea9a35e2f6f6c2f4eaf8a09edd0a1e404687bf6e26907c9ba","tests/expectations/forward_declaration.tag.compat.c":"34a675955746042a4c658f7bf7bf679f4a88fc40387f9063bb7f5922c3edf236","tests/expectations/forward_declaration.tag.pyx":"ef8ba87a36122681ba479728147c82100c42a83754ef6a577df3122f6278e5ef","tests/expectations/function_args.c":"90545731d4f875305f4255721917fe99fe2b72a9800c0e0a1f5ce216c3bdfd93","tests/expectations/function_args.compat.c":"f8afecff6f47cb348f8899248cc12282614b052d50c3d20494f9f65c418c7ee4","tests/expectations/function_args.cpp":"929d057fe83dcf946ebc2abc915484e31c8bcfd48e5d572b1de90ec044129532","tests/expectations/function_args.pyx":"5e9da75f1c1047376424977fdf8c577bedea7e0248f9d45b468d75724e3baa62","tests/expectations/function_noreturn.both.c":"2c557b8e7145bb6da3802ff0bb0e0afc53c49b38552f0ea8800441bcec639e93","tests/expectations/function_noreturn.both.compat.c":"8078d88dd3ea314d5604b3db0295bc94482b7229ce1e4f49f5015035c498f62a","tests/expectations/function_noreturn.c":"1cbeaef6928599ebfa2c7cf7da18227bb06a8143547908bcdb2818018a3e28da","tests/expectations/function_noreturn.compat.c":"2c4a2afec60facdbaaf2818213a7513d3b41a2e97a9876b90a7c8ee816e223c2","tests/expectations/function_noreturn.cpp":"5d03d79185e3328364be4013fd39bcfe015f0c8c30ec82336c421128cfa6ddd5","tests/expectations/function_noreturn.pyx":"f61b56c865940ded65a51ebf2322e7eebb7c571e0541efa188e49959f7e74692","tests/expectations/function_noreturn.tag.c":"747bfdbe489c7011549a2ec37a1849874aa823273df8f83943446359bb28a2e7","tests/expectations/function_noreturn.tag.compat.c":"da06fdaf673696586f386b2ad310597f2cac57caaa5cd5aed334a9dc260771c2","tests/expectations/function_noreturn.tag.pyx":"f5dacca236dd2a72949c38163cdbaf6b125a27bcb3580d2a203afdbb20d491f1","tests/expectations/function_ptr.c":"445561ce58f52f9732681e4baf9f26fa936c3fff919da6fb8adc0185f651f7e2","tests/expectations/function_ptr.compat.c":"43ea17b6fc6e5b56dc1b83e538f89e69fe0154e99b32b5cd2227456d48d9b8c0","tests/expectations/function_ptr.cpp":"f7346f3f163964e020f9259582105a80cedbb42f5184b4ebaf9988ea778d39d8","tests/expectations/function_ptr.pyx":"5c3a893a6619867ddd428ce35f42207af76576b7aa18649368d383117cb5a0dd","tests/expectations/function_sort_name.c":"8c6f66d028092f8ad11acf8d9bfd934e17ef2ae25c26d3012c9655a54f379b45","tests/expectations/function_sort_name.compat.c":"7d8e577d35f4590a8d733ea072e68410784e9870295607ae8872c71239994a2c","tests/expectations/function_sort_name.cpp":"2924b7b6d6b49a93dd1f1a850643b7458da50fe7ea20ea057e3a9f4a27d051d1","tests/expectations/function_sort_name.pyx":"5a94077258293fd28418e4141328aeab509ebbd1f2bdd084aa9802ea84994bc4","tests/expectations/function_sort_none.c":"cb76985dc63027d0d85bb6cfb32e5a77f9c3a46a97059068643186f27a88d9ce","tests/expectations/function_sort_none.compat.c":"3aa6b8e43a5cbcceb35ced688fdf0dac71bd63f0dff1cb7d0ecea72749fcb017","tests/expectations/function_sort_none.cpp":"6b07b4a14d97230660b18a6a63258e3571124c935b4a8391ab377d48c8e9d2f8","tests/expectations/function_sort_none.pyx":"c4b01d34e21c584097a1726c17884dd148315e5924c3353d799c7ee3b39cc939","tests/expectations/generic_pointer.both.c":"883597ae24580f0700dce70e121fbc6258bedaaec1412883ada64f3663433fa6","tests/expectations/generic_pointer.both.compat.c":"ee1c7f3319a4f6d5dc57a8ba1c07299b469c20030828ca24e2553b2d830c8ae1","tests/expectations/generic_pointer.c":"9ec3e744a8f953038b2bc748b34b0e9f682dd473ad46f06ea28bb6d282db9281","tests/expectations/generic_pointer.compat.c":"0c7db5c531555f960346011f526ca77268093718e707dd1d628f833a7678714f","tests/expectations/generic_pointer.cpp":"d4772de13c5e44f85aef9d9014d4e6b180d9749553895fdc559a96316dfcd0c8","tests/expectations/generic_pointer.pyx":"2f961cb4f9635a7ad83b3cb41787dfb336a1e7eea2003ee158e18a30c98e21b9","tests/expectations/generic_pointer.tag.c":"6f7946fdf4f71603a67134fb7e15764d8c723575c969e0976091a6912fbde974","tests/expectations/generic_pointer.tag.compat.c":"7e03767bd8435010e1e92d6f6a7436d1376d78738199a7b1e484efd7e0543804","tests/expectations/generic_pointer.tag.pyx":"69e4baa3e9aaec93c0dca6b7002c0b939ca9043893f33dd1756248e9a9a2dcef","tests/expectations/global_attr.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/global_attr.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/global_attr.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/global_variable.c":"e438559eb15269367b740790ee27a8bcf63a65f58153cfa9da90a173480b7842","tests/expectations/global_variable.compat.c":"7da3dbaa9810ec68996038c3170e308c86d038f2c6a7424f08153a002b84e737","tests/expectations/global_variable.cpp":"3b3506a61523642fab2ec283f14aeaa315117284f1566581f368f9d6d94c819e","tests/expectations/global_variable.pyx":"f9362bd82ec80bc8578ee363b0fed388091f90a61242d0a2853f8c18b846c142","tests/expectations/ignore.c":"8629579fd8d0e5df30b4a6e8258fe62efaeb58365f906e253684b1bd9530654c","tests/expectations/ignore.compat.c":"513d4638f5b6331b88782b7b9803d2eb30e058661ecce6e0f0aeab79b5edfd7a","tests/expectations/ignore.cpp":"8def6cc5a4e93ea3dbdb196769bfaaea3f2502cfdee4e256ef5ae86d25896145","tests/expectations/ignore.pyx":"deaa02f33d1bfe7d637420038e93bc63ffef82e93902bfccd43fd28daa4dd764","tests/expectations/include.compat.c":"f6a8f36949826da8fdd47af14b92afca3a27d334a2057bbd5dea3c3db6a8d8ad","tests/expectations/include.cpp":"52590989caf74c26b42591460528979ce10569e35457f93bcc9ca07af686e6bc","tests/expectations/include.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/include_guard.c":"5d9bc0cf8c54aec379f38ce9ee64a8ced7c710e86b947e6516745586d8d51e65","tests/expectations/include_guard.compat.c":"7ed0680e9547628b3c3edd867fa31bab7bdae7bb38ba68e8c643b676de876b1b","tests/expectations/include_guard.cpp":"09174bac4cc923d3a3b91ef4e1205dbc244af756b8dd40382e0c7b7044ee0ed1","tests/expectations/include_guard.pyx":"2dfb2777f23cfd907d3de10774c020dec80fb510b8d850a2725f133afb5fa038","tests/expectations/include_item.both.compat.c":"0d64fd9ae4b4dba8553cb80512e360fcc06cd4fe03a851a865e4b96a8582ac7c","tests/expectations/include_item.compat.c":"35a80c1690f6b418e3e6163174fce69bc667f578eb6a077107ac7bc87298a987","tests/expectations/include_item.cpp":"b9a3d9d3c40c993223e93e9e0ce8f9c5d173832b1c8d4e09054d6ba559fe80fa","tests/expectations/include_item.pyx":"a0448dd076125dd3483575edcd3f441ae0e5d3ce8b77742f48664ad2406e451e","tests/expectations/include_item.tag.compat.c":"c3e805ff7c80652cd250e0f91c158e25062b9331f9f106b77a7e08147e70d346","tests/expectations/include_item.tag.pyx":"b85cec40d10b7384c5277d5bfaa9dc789a38f56f9bde5d8186d3805055406193","tests/expectations/include_specific.compat.c":"3c762fa6241403b00500f12542bd195f10c680c5b1801c76357b8c38193eeb97","tests/expectations/include_specific.cpp":"3c762fa6241403b00500f12542bd195f10c680c5b1801c76357b8c38193eeb97","tests/expectations/include_specific.pyx":"da3b3299f457f3aba4adfa25e21b9270ddfe6f324d29128add8bb6474bc7cc86","tests/expectations/infinite-recursion-typedef-monomorph.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/infinite-recursion-typedef-monomorph.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/infinite-recursion-typedef-monomorph.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/infinite_recursion_typedef_monomorph.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/infinite_recursion_typedef_monomorph.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/infinite_recursion_typedef_monomorph.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/inner_mod.both.c":"d848b62ec77f2cc5b0e21446cffa0429d2759fe55dfbc98604ac12466c43d542","tests/expectations/inner_mod.both.compat.c":"f6a4661c96309cfb53f860a6766a36760b0c501a4e603834f113a2b0cc980e73","tests/expectations/inner_mod.c":"acdad2892c84bba42f5e45ae3295ea095dba9786d566672acfddd8e388ffde70","tests/expectations/inner_mod.compat.c":"fb9a16a48c294e56d60cdb50e9522d8119152e5ca34862857ee7643694e3ed84","tests/expectations/inner_mod.cpp":"e27ee433a0764f92010e476b4f311b3c8e7723e22bc4f3cf2f473ad6fe516ae3","tests/expectations/inner_mod.pyx":"ac755298e5255b926962fc068e2a70899d40bf6065cf46db8e57ceb56b0538d0","tests/expectations/inner_mod.tag.c":"e5b15746228630dbcd16bbd1467375d0954f981de85ba4230ee09bfa7f509a4e","tests/expectations/inner_mod.tag.compat.c":"6e3c7a559af8d84eb504d94aec8694c18d2c8d9acf32cc525e748c86db7d0c97","tests/expectations/inner_mod.tag.pyx":"7dc7732308c5c67801aee1dd627df1a3c530b544057638362870138cab2efaf7","tests/expectations/item_types.c":"ab7fb01375066294949a2dc99a55cd1cde72bfd8510aea21fe89db256200ed42","tests/expectations/item_types.compat.c":"0c68a303f170b7f412fd8ed4196d0c688a995c9f3a0b35b0bf857acecf9cfa36","tests/expectations/item_types.cpp":"19f55fe8f8416342e916344276ebf10a975e57b9a787c1b42bb9b0a374a587c6","tests/expectations/item_types.pyx":"c067270e98479b2c336bc0b520c57c480b7b4448b21f0fb1a8b342d1953a79c3","tests/expectations/item_types_renamed.c":"fbb007a71b1e2567d4068dbceb46b4e284e64fc0f425b67b84bf9f319f947435","tests/expectations/item_types_renamed.compat.c":"a15917d285d40d7edad8b53ff9df83a5f417212c9d6bb8e120c68401afaa127b","tests/expectations/item_types_renamed.cpp":"b60fce152b506ad6e3f964638390212e06b7e3a9853f62943d05e12ae44c9766","tests/expectations/item_types_renamed.pyx":"a0e219b8f7a33b0843aad617bb42a987a41ba4d1edcb399d07c7c29e1137c1c1","tests/expectations/layout.both.compat.c":"0a3f11507f4c77e6568d37f85b72cb7e22e3ae25c19edcdf3faefa4029a3a79b","tests/expectations/layout.compat.c":"f3aaea6884993faf3dc4cb8433deb6eea361e8188e4a944ec44cfee418c1c30b","tests/expectations/layout.cpp":"0ba0d01dae0403e9d4f7c86241027ea34cd7f67b0fa4d5f48a4e993f42688369","tests/expectations/layout.pyx":"7031dcbdd850c1465afe36222ca0918b2f424022d549eff7c30a818cc1873a02","tests/expectations/layout.tag.compat.c":"a4fc428e701015b316d1d5f45af9ccfe4f93119737dbc70440bb5135775455f5","tests/expectations/layout.tag.pyx":"c44b62c85bab18e65ced0ef68549b92861191624dec0a13ac8743a3d11ef8fcc","tests/expectations/layout_aligned_opaque.both.compat.c":"f3ee88baa5bafe2038a33db94e5088d91f16a99a127a0a20fe5820d0fa2b309e","tests/expectations/layout_aligned_opaque.compat.c":"c6def8e3570b4c33ad597d699f5c668f3f6765240f8a79f1fbb506a2f29d5aed","tests/expectations/layout_aligned_opaque.cpp":"bd1ec25eb3f52444263012c836c1a312831ae9987cf092569b9f77f5087f7fa3","tests/expectations/layout_aligned_opaque.pyx":"19b00e1ddad32eccf8f092254a386af4a379510849f3f7f1401fd8e44d86a58f","tests/expectations/layout_aligned_opaque.tag.compat.c":"b1c7d1fefd46489aef9c7d9a1ac9d2813daddb42950ae1e251c5f36db56ea087","tests/expectations/layout_aligned_opaque.tag.pyx":"b4907b7045b946226178bab261d98a573f574b00a92b35374bb855525e4c5d8c","tests/expectations/layout_packed_opaque.both.compat.c":"ceb4ae333479c72559158a62d2dca064c6982d765ce99d979ccbddb48231e464","tests/expectations/layout_packed_opaque.compat.c":"eff44ed7ce409947708c246aa3b535f10b42bfd39a591d94afe8ab4d404a5350","tests/expectations/layout_packed_opaque.cpp":"31e40feebac3001adf6ab13e121108a60da2b2924c7ba673f0ff56cd29ceed84","tests/expectations/layout_packed_opaque.pyx":"5ac79bebcde01e802f8b945305db80a5b6e1a9a7637cc5277befc67a458544fd","tests/expectations/layout_packed_opaque.tag.compat.c":"e0a6f08d233d4f53d5302b728a723dc0b1c4684b47c50c7e28732fb895d6223f","tests/expectations/layout_packed_opaque.tag.pyx":"7767f5e23c99d5109516f7fbd81218210d6e3d321a1465f13cfc87b82489045c","tests/expectations/lifetime_arg.both.c":"b5f69000140f7afdbd7da95c5378da6dadd036c3692643488ebeb32409ce02ad","tests/expectations/lifetime_arg.both.compat.c":"0224425b0f7633b5b651c67a4f3ddb047c803ce8a55322a9ab2d2b74df13bb42","tests/expectations/lifetime_arg.c":"1219d3d3e02b7b9600bc861cf7f8268bd2e24705819e14c5a90cb236fe633b72","tests/expectations/lifetime_arg.compat.c":"bb23c5d46ef6ecc103674cec94cbfd4b41e087b46c5479edd9e2f26db575ed84","tests/expectations/lifetime_arg.cpp":"e6db96ee06a83ba33f1767a1741b656637574895edf496f1fadb109538d7eeca","tests/expectations/lifetime_arg.pyx":"36bc1ca71ee8eba07ed117326f565c50f38dc08a8b8e130be449a652baed630a","tests/expectations/lifetime_arg.tag.c":"54fc3164b2ec51a555fc98685ade1f4b46026cf5108ea238b7fef94059490264","tests/expectations/lifetime_arg.tag.compat.c":"b5e98c37d9e22e9c4b692f560872926977058aaa7a93634d45adbe4eee65df18","tests/expectations/lifetime_arg.tag.pyx":"41fa3947bcbd19b38f2eef40440535fc02e4351982c03991028131cb8b34243a","tests/expectations/linestyle_cr.both.c":"66018159ecc88a3da9e13953b5fd529ccdbceab9f9f4e6f1abd1f0596e3396a0","tests/expectations/linestyle_cr.both.compat.c":"3d849ad69d3d8673de20fbe25d350d3d89d2b03598057159572dcdad1e53fb01","tests/expectations/linestyle_cr.c":"c47b79a70178b4dec21195bf3ecff48bceff5203a3621f2709a4163713c4777e","tests/expectations/linestyle_cr.compat.c":"9963c2f0101fda33df235e71816d6959662c1374d4ce1395ada0a54160528b04","tests/expectations/linestyle_cr.cpp":"a1f4477d1de11feff1bd6383075f1e66143766563b162e02b630377d391cea60","tests/expectations/linestyle_cr.pyx":"401015e4f3d27c133f67bf2089c1d173d3e5dc8de063e726551fe738dc215e56","tests/expectations/linestyle_cr.tag.c":"b50a6e683e09e118df9d736d8c41558fe9449cd7ea286880af587c1c8cfebf9f","tests/expectations/linestyle_cr.tag.compat.c":"476b857e2ea70bcc0a38791988f8e366ec651eb9293407741a7daff78b0a6c72","tests/expectations/linestyle_cr.tag.pyx":"cd32abba2b2f8a866b251cf424ed3211d091cf59b762c09ca59aaf5100710c16","tests/expectations/linestyle_crlf.both.c":"755a99b1e933766ea9801a1ce117c2f997b0fa6b2c5137912fb65a22cf0335bd","tests/expectations/linestyle_crlf.both.compat.c":"9ea5a984f8c6948762c4fe9a2fc636c21007df7653b1fd0092251fdc417c67f6","tests/expectations/linestyle_crlf.c":"8e5c12fba506818fb7843e9955d23cd400d185a550b0232361740e6ed899c733","tests/expectations/linestyle_crlf.compat.c":"a95bed74fc25acfbd9385e75d9047f1b49b813cd06cf342a0542b3ddcbe99ace","tests/expectations/linestyle_crlf.cpp":"12f0ea9dce436788bb0e63078085fa2a07caa8af17ecbe65da58c65cdc3cb47f","tests/expectations/linestyle_crlf.pyx":"7650edb5a4f2b1137f44a61bcc7b08ab946a80f8f7a6e626949e6a4ac02b370d","tests/expectations/linestyle_crlf.tag.c":"6b420ef3c54620e8eeb287a0c4df434521d9448dc56b464ecac8ccbe95c07ca6","tests/expectations/linestyle_crlf.tag.compat.c":"f46844a888c93b7068a4fa19351aaa6e4b6b16edf1f9a2e02650e6ec89e3813f","tests/expectations/linestyle_crlf.tag.pyx":"4d3251841193e79a33b97cf932c04b1cf68f0e7effaa3d8c1590291589e752d1","tests/expectations/linestyle_lf.both.c":"ffec23096e4d365160f926c800be026e7e7638ccfd38963d3a93eb1c2a7c0fec","tests/expectations/linestyle_lf.both.compat.c":"2221088f3b4fe1b7683bcbb2ea3e96723e1764b3ad3bc83cf58626839fb291ba","tests/expectations/linestyle_lf.c":"8ceccd798cd6034abac6b31b3f6cd5d4c1911bdb6da3a46235d4a12c30dff29b","tests/expectations/linestyle_lf.compat.c":"24d70a7beaffa4dd1e22f6c3b8fb76ab72acbffa7806e41c0b7057dffab969a7","tests/expectations/linestyle_lf.cpp":"abee092cf4bcebc00fd7f242ac1f9aa28b80f589f7c9bfc34a6ed1c07e82267b","tests/expectations/linestyle_lf.pyx":"a6e7f087939ecbaf9dcd548e8ffb1b19e74cbf2206c95d07f3390a0588191b37","tests/expectations/linestyle_lf.tag.c":"9b87b10e928fda7709575f3a6ae449c00e111aca5082e45e4765883cae39e1b9","tests/expectations/linestyle_lf.tag.compat.c":"f4ad723de21bdc3a88122f0582a32b6bfc16a5f5618b638331e1fb836f2d5b00","tests/expectations/linestyle_lf.tag.pyx":"575ee9f32e8490cb8d5c3146dcba935e45d865a5be633d8a69747ef77b87c204","tests/expectations/literal_target.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/literal_target.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/literal_target.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/mangle.both.c":"88d970e66abcf79d61bd52cd47e514bfa4fd859894323df5bf2f083f80ac4e0d","tests/expectations/mangle.both.compat.c":"13b5ef25d4a47707e62de9d924eb77d30d269b7128f86ed80b9657a98667a50c","tests/expectations/mangle.c":"8a7feb1d905a5155570d0b445014697ef7c0add1307e030e4fcfa36f4251acbe","tests/expectations/mangle.compat.c":"2fd8fc643ee24c15263f6160a5dd050e35475b375b48922f959402a091ed341a","tests/expectations/mangle.cpp":"537fdc0ca1cf479dafab28e40bd8dbf6b1afd0eaa57b59e6aa01116879b4ea8f","tests/expectations/mangle.pyx":"10fba6e4c29fc836547c2da6cfc55a1061d085f8bff910ff6fce2b620b82941e","tests/expectations/mangle.tag.c":"092c8bd77ee925c301dbe36ed66f849da9f6fa4b12a33283114c6b02fad192b8","tests/expectations/mangle.tag.compat.c":"18cbe572bbbe5177bb299a077b2f16178fca41826b2bd9255d200127d21329cd","tests/expectations/mangle.tag.pyx":"ed46ed2725f9770377f07c01d87726b5b098e8384ce3fd116125303a638f9dea","tests/expectations/manuallydrop.both.c":"a498841bc0733dc2292c5939947851612b901a02fc2c2ad9bc60636450b47240","tests/expectations/manuallydrop.both.compat.c":"b14fa50b138e98752152e6650ba872198bc358c0af8cb830e247e6e6f12e6fae","tests/expectations/manuallydrop.c":"21927680697b6127e2168576055dff8d69d2d253debd7b9455c6aa0863d8c74d","tests/expectations/manuallydrop.compat.c":"9c7a87ea0e2d19b615e5ec8cf7d37c95eb9dc146330adb0f9c4af1585e3d0e39","tests/expectations/manuallydrop.cpp":"21ece2b6da294f6059f55fd56fc06967ecde5a038967ccb8681d65bfb371ab85","tests/expectations/manuallydrop.pyx":"a5bce0fcb482fd981592b2aa38f692ab2a9c7fefef4840ce8da82a5253958b9f","tests/expectations/manuallydrop.tag.c":"4870a7484b157d3df0d418f4de16dd69ed635d974fe85b0ce0bb4c455884ba2e","tests/expectations/manuallydrop.tag.compat.c":"e4bfeebbd0d403e2dadc92b4cf0686d8356efa578ebafd62ffa43347794613eb","tests/expectations/manuallydrop.tag.pyx":"49058f688f67beb2a54c9baf9c3c4bf174c59397d21559abf4a8fa2fa3a800e4","tests/expectations/maybeuninit.both.c":"a63ba08c83ed7a82627964e29f5490e6dfd9f5c0440817a1bcca82d4c8f6ec5d","tests/expectations/maybeuninit.both.compat.c":"a51540ed9db1f7c8c4274010b25a35f231ad8204958c57cd2631aed2ab326a90","tests/expectations/maybeuninit.c":"1c62b5405efae8f1155597b56e3cedc974d538f44ec2629465ff37d1c357956b","tests/expectations/maybeuninit.compat.c":"4587d6a224c958219bf9a57d0673d1543068c6741713a7a0a85ae9b7be1efb4f","tests/expectations/maybeuninit.cpp":"aca6865910f5ccaca1188fc1ca0d071ba59a77e4ff1f45e686e49137d3f55e66","tests/expectations/maybeuninit.pyx":"89445e1baa2f02ce48d82ffc257aa8570d2f920f40d5b516c68512d96a3d6ff8","tests/expectations/maybeuninit.tag.c":"a262317d95f08c3f818f18177218ee10b3d372c43f6171da7aece01259d64069","tests/expectations/maybeuninit.tag.compat.c":"6626c55f78f27349c24b9ae1972f0b3463e77e02145223963bd9d93068cdc5cd","tests/expectations/maybeuninit.tag.pyx":"8ccbfb67f0dabb18d9af5ec6afc77e7c8ef33c71fdd5fe01ef9b99f9e9d7975f","tests/expectations/mod_2015.both.c":"4d42dc63bf6733f16e0b7db00b0067bad9a4e9e66ec1784bf3fbd195cb0ad9ec","tests/expectations/mod_2015.both.compat.c":"29a4abcfab680f6d5d9d49f47024cc933a921ba705fcac4ea6ad15ddb7a225c9","tests/expectations/mod_2015.c":"93ffb87f08257b4872003cee883183b6d4ede3e22e8c886341c919a7710c3589","tests/expectations/mod_2015.compat.c":"db3427f121357249d187be57b97b616ac65f9c9b785ac3f72f15e33c39093e27","tests/expectations/mod_2015.cpp":"6e9011a8513c99b756d5c793e28a416d652f374a177935711a164abf1f924f6a","tests/expectations/mod_2015.pyx":"603b9887af457653c7357c13bf11570270f6a43f4c40ee2cb27200739bb3af9e","tests/expectations/mod_2015.tag.c":"ffbf8e8fbe6d80000235a6535fb21ae30482142eb1c531c3bf1be75b4c60e354","tests/expectations/mod_2015.tag.compat.c":"90c690aa404e56f5081d96b43cd221ac8e666092bdec798036c7cc37d2929091","tests/expectations/mod_2015.tag.pyx":"c88d0e2d99ff83f5e40ae941edfc3393b195aa7037c867863439f256cc2c0e39","tests/expectations/mod_2018.both.c":"5be9bc903ebcc592c98c584ee20c466772f1f33112e25ce685882a1bacb2c9f9","tests/expectations/mod_2018.both.compat.c":"611b8d84e32416d3add4563d7a25c02de906ed74631efb63ff779df5caac72ea","tests/expectations/mod_2018.c":"1e16affa30b8d51ec6caa6d7153a126f74a6f953625ca40a9bc384da4e2575ae","tests/expectations/mod_2018.compat.c":"44dceb2e36932503d3cb90745479b415f222d04482c1b39cf31ddd6034aaeb77","tests/expectations/mod_2018.cpp":"640252162e835da73383acb704b01ad4f9286b1d68d8c1387de55c564ca7eafc","tests/expectations/mod_2018.pyx":"370fde411356d674dcbf6bae3dc375720f3704d3639a5602b8552d337f452869","tests/expectations/mod_2018.tag.c":"7e47259ead3a180919f3c960308c5f3233a8a48d0d921ca4236a5e064ceb75b9","tests/expectations/mod_2018.tag.compat.c":"9db156388ba66c6f218d99aa870b1908982106271c85e08889e03ee106775557","tests/expectations/mod_2018.tag.pyx":"cb159adc7388df316dedf0a1f7c67fa116235c7fc56befefe0ec206449db3088","tests/expectations/mod_attr.both.c":"e470259bbea62c1304c3b860d803d5c731a0de48351d71b5964e469c9b1630a5","tests/expectations/mod_attr.both.compat.c":"1df6dab72e8053d5556489e14774d3565ddb9815629169623b53c4b100c942f2","tests/expectations/mod_attr.c":"36b7399b5feddc4f4624706a8efb859f0690f1bd790979ae00963a53c399b486","tests/expectations/mod_attr.compat.c":"421356a463fcc7b8009f6e9f7fcb231735138cd8b00994db220d4fba7033dd0a","tests/expectations/mod_attr.cpp":"ce54146b0300eb463aabd53a598a13ea200d75739b1f747afb64dcad72568bd0","tests/expectations/mod_attr.pyx":"efcbf28926b8dba7527ca7a3959ee170f21b95469610087b5a7a1f59d836a717","tests/expectations/mod_attr.tag.c":"26fb16ec5661935512120ea53a2f0a750c232b285181692342bc3b29c1626ded","tests/expectations/mod_attr.tag.compat.c":"9738e2d7525db7ca32eb01153bacef69a46e185ceb18045bf23462c9fd8ac9d0","tests/expectations/mod_attr.tag.pyx":"25d56fef07810075ac8e3613509aeb14e54101d1e6cb8f7930bf51dfcf53a7b6","tests/expectations/mod_path.both.c":"1d7ba633ee3311f1b1dac786a36977558fd1cc42a5fc108a0045de1cbb58c142","tests/expectations/mod_path.both.compat.c":"50705d130b54224f6781d8fe1783036be0162b50194018b3d30033796821c56b","tests/expectations/mod_path.c":"358500d2996dd971630376eef9816379576625619b3516e5d3de5cc74bbefc6f","tests/expectations/mod_path.compat.c":"cd2604b2ffed7bfa17327ed654370e058b913afaaa9461454ab6da6bfd4a6b6d","tests/expectations/mod_path.cpp":"ce490dfba7b336456bd443001c848c71c6c7160fcab5a8615ec825cb6c8634ce","tests/expectations/mod_path.pyx":"23c7cd14eb5294331834dbb6645e4545cbf887b90458a8be24c9f927496710b4","tests/expectations/mod_path.tag.c":"8c849f6a71fd73720b23141b0498400800dd1282bb47930855e2f12c80544777","tests/expectations/mod_path.tag.compat.c":"c6ba516c29bf70a7234f85acaeaa98fa5720eb386f0b0c03e042262c476e0eb6","tests/expectations/mod_path.tag.pyx":"8e8d99e0a9c29e8cc85efef7d5439d0f6e3d62c9102f955cd9794b7d432e8321","tests/expectations/monomorph_1.both.c":"10d69c5368f5995d614425992d794936ebbd46fe15fd8a50ff9c0cae0792b49f","tests/expectations/monomorph_1.both.compat.c":"a48fca0cc1856a58ae7db2893abbb9879c70248561b81d9c75dfe252be3e27ee","tests/expectations/monomorph_1.c":"56f782e0e7ed4af20b54b9c1a1fa32ccbb421f74953827e77e4a34374a1f99f9","tests/expectations/monomorph_1.compat.c":"2481def545a3d016b1480752266b5a1460e30f972bc532ac55fad28329fc8eae","tests/expectations/monomorph_1.cpp":"76c9f60394d2b33f784e8ea47d4a45247ded703cab9d3d9b92e7c3eafb99bd2d","tests/expectations/monomorph_1.pyx":"19b26eee97461802d415845e86e8b13905d5019c406bbc01a2c9f0c95040741a","tests/expectations/monomorph_1.tag.c":"bdc4017baf04090f62c8b18d75824bdff0fb48f0b6ba2013eb8a594d5859702e","tests/expectations/monomorph_1.tag.compat.c":"e03f90337eca949628d86dd393c17ef1bbac240561edeec1f6365b71bd7035b1","tests/expectations/monomorph_1.tag.pyx":"d116bc45b720243a572769bc08a65d8df36d52be82c3e306e5c60e56799f9a39","tests/expectations/monomorph_2.both.c":"27440ed92ed1cb717dca92703ee85a0bf1b16122fe99f2e2bf4320b05c8fbd0b","tests/expectations/monomorph_2.both.compat.c":"fb4754a776aaa49155c538e90dd8de978cea7cfc63e9ca846d2ed7b46b66e1f5","tests/expectations/monomorph_2.c":"ad18b5898aa40134b766636adb7963140d9592028b409252709489c07321ed69","tests/expectations/monomorph_2.compat.c":"7392c90cfed6097d93892eaca523b90fa57336cd9489fd64e7e15e85f7600076","tests/expectations/monomorph_2.cpp":"95889ebbb57c509e6ea8d8b79e692b9d2ee3ba4343b1492cfbcf0b6eed185f26","tests/expectations/monomorph_2.pyx":"be1027e30cfe3b0038061cd8662384e23f70ce442fd9692e8f099c1f963a5989","tests/expectations/monomorph_2.tag.c":"b8be9d57b0021ad9fcaa7b905511aa14a412299ac9ff6680f273a3e999e86cfd","tests/expectations/monomorph_2.tag.compat.c":"ea568e6dde68ec79d95488c8f2682495d6135f40266e901642cff45295668a5c","tests/expectations/monomorph_2.tag.pyx":"726ca00603356eb5b2f13e4ab4dbefd478954e9127960e4d623c2b003c446fcf","tests/expectations/monomorph_3.both.c":"1db37a701a9843a87ab9dc5b3170a70d2a3e9dfc2ee1d5131ea28738f6eb03f8","tests/expectations/monomorph_3.both.compat.c":"f3339fa5db4d59b08e5b6b1ca2f047a422249e71ccbba54cf3d4cefb6608063c","tests/expectations/monomorph_3.c":"6f5150caf205ed2c4ce1f894ccc41036c336ec6171aaf1c5ea6b4995474a53a0","tests/expectations/monomorph_3.compat.c":"261747e051bd071b480bd46841e2598d7c829d62fe4397a1602a6a1f77c833c4","tests/expectations/monomorph_3.cpp":"fbe1c063e47cc1e0b216053db1c1355e0698af8c83b6cb8fedb2f5063194508d","tests/expectations/monomorph_3.pyx":"c4668d54b54e532c5c1486a73769bdb497d552db3818105e2549122e8d08a175","tests/expectations/monomorph_3.tag.c":"0267e4ea206bac3ebaaef30f7dee4f2243cf7f5ffa0e0748f194d3e1fa5635e5","tests/expectations/monomorph_3.tag.compat.c":"3264f932beb090697bad43ecf82018719de18254460fadd7dd6a4c14b29871aa","tests/expectations/monomorph_3.tag.pyx":"106f50decd972650f25c3db07ed0279e4c6674a9ef22e4e5c5dd2f6a01def21f","tests/expectations/must_use.both.c":"95461e91bfd356405c9f320e0448c63a53f3a683ae21d83ef4bbf111bb7d06d9","tests/expectations/must_use.both.compat.c":"ccd7c9c85eb89e86f12e17e62f5f8182d2323d349f053a0f11ed0473fa012f4a","tests/expectations/must_use.c":"488e06c3e6cb76fcf734c807dfe7464d929e581d04c0f968a393c6681caeff70","tests/expectations/must_use.compat.c":"723ef05fd1ecbfa6280683415f11e1f1557048ceed13fdf3bdef6ff285ccca90","tests/expectations/must_use.cpp":"78ef60a4d6c588f97bbf88f81cad3884c45f0b0bfe27af161e220ec48c76a963","tests/expectations/must_use.pyx":"c7530439e1ca8e593be4449d5c85e3ab1649a6a3728cf18b2dd306dfa9fb5538","tests/expectations/must_use.tag.c":"8436ea338277f4b1d1923aab72de491a1b1e4f0104a480913c404fabab4e15b8","tests/expectations/must_use.tag.compat.c":"59ed65a024c04bb8bbea47f172acc4c2c0626e0f480cf3013f848a0c481fc799","tests/expectations/must_use.tag.pyx":"84f2013e619d7447308af15e1f75a3d86abe63a9494a4c3c1673a29de5ba3791","tests/expectations/namespace_constant.both.c":"e49631bb7ef1c78d3a699417b0fdb496f7411de836413baee26873dec16e6ce1","tests/expectations/namespace_constant.both.compat.c":"5fde7d256fb56db4dab0918960faf228c24c53cce2e5660f43296c7d2eae6b7f","tests/expectations/namespace_constant.c":"f86295772c831a2e12da48314a18829301a43c476c62953c14ccaac4a85f0a48","tests/expectations/namespace_constant.compat.c":"bb1230c6476d773c14ddc0027a8b713b364d5f7dee03861e2999ba3968e8bc1c","tests/expectations/namespace_constant.cpp":"4923d9ef69010e9d515c5de5661dc5b91fd1c6531de5744abc75d6c4cfd69dd8","tests/expectations/namespace_constant.pyx":"2501710bd9698215badfe51ae410b870cdd6c415cba39ea9f434385d86e18090","tests/expectations/namespace_constant.tag.c":"1e3f5dc75e6c49f6ac9a223abf7fd35743465d7376116eb435c31befbd58674a","tests/expectations/namespace_constant.tag.compat.c":"5e45fe7f4600288ad2a5e545f873fff0d43e95c561e03c5afe5b596d0d144306","tests/expectations/namespace_constant.tag.pyx":"665c3b9423175a1233f1fe0cd466fd4d73d59f813fd3079899b62b2015e6902c","tests/expectations/namespaces_constant.both.c":"e49631bb7ef1c78d3a699417b0fdb496f7411de836413baee26873dec16e6ce1","tests/expectations/namespaces_constant.both.compat.c":"129a4b4f393636afc87e42d7f498e5fca2e921c77407fc4cf79da1d54da0fdac","tests/expectations/namespaces_constant.c":"f86295772c831a2e12da48314a18829301a43c476c62953c14ccaac4a85f0a48","tests/expectations/namespaces_constant.compat.c":"1e446aa818a096bb981340f14470e11ced8cf9dc061fc887d99046c53ccb761b","tests/expectations/namespaces_constant.cpp":"ec82f0a6cbb28fb99e849791db08d50335ce19f6a5e981b7a7482f0a999eb7f6","tests/expectations/namespaces_constant.pyx":"2501710bd9698215badfe51ae410b870cdd6c415cba39ea9f434385d86e18090","tests/expectations/namespaces_constant.tag.c":"1e3f5dc75e6c49f6ac9a223abf7fd35743465d7376116eb435c31befbd58674a","tests/expectations/namespaces_constant.tag.compat.c":"c6771d0b00159fde06de09d6074537cfd19d86f0ea70af8bc5c003dcbca2e96a","tests/expectations/namespaces_constant.tag.pyx":"665c3b9423175a1233f1fe0cd466fd4d73d59f813fd3079899b62b2015e6902c","tests/expectations/nested_import.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/nested_import.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/nested_import.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/no_includes.c":"7a291fbd7336e914b26137ad41ec8bd4b32339d54165147533cdb64b60fb92ef","tests/expectations/no_includes.compat.c":"9aa00142d44fcb11d131f63d3962c7c9a81aec881f0da8fef1f90cbd8378ea5b","tests/expectations/no_includes.cpp":"ccc81037551361d758874141fb95165c57473faf66e500830ad4b40fbe00e906","tests/expectations/no_includes.pyx":"2dfb2777f23cfd907d3de10774c020dec80fb510b8d850a2725f133afb5fa038","tests/expectations/nonnull.both.c":"bc89aae611a1bdf1ba1a2e073e6ef6bdc1e4c2649dbe53becc82764b5ae9ab02","tests/expectations/nonnull.both.compat.c":"d1f99b090cc1d952e3515d46680564948a5fbd2f58d11f5b23ac0f382c209df0","tests/expectations/nonnull.c":"e46f7cc997ce798dfdfc78d64ed71e9157d2b69f3b122c2caf09fe412560aab3","tests/expectations/nonnull.compat.c":"b453816610023cc1f27b8d44261c3fb927f1fff9e4b67e58658b1c89c02e71df","tests/expectations/nonnull.cpp":"fba2388c683faa872f7e6087be9a632c6400cff41d12f92736836abfa1a5af71","tests/expectations/nonnull.pyx":"97eb98c1cd54c2957df9845008eff32b782b2f32f84cd1a0214b8a9a131763dc","tests/expectations/nonnull.tag.c":"9968d2607a64b8f21efe2c9d255da6ff8c606eca82e241b1426a31e5a5650af0","tests/expectations/nonnull.tag.compat.c":"32a9bdf793c01fc90b414e14f7255114402340c5b79f0c2092ce5a0e14c0c622","tests/expectations/nonnull.tag.pyx":"30f8c77d14ae34ea152e697936ab2dbc3a8b5feb9a1fd8711c6a9c8967fd657b","tests/expectations/nonnull_attribute.both.c":"2b46102c86d19bcaed20026b879d429d1d55f785624cc7c80af2debe3b3ff46e","tests/expectations/nonnull_attribute.both.compat.c":"9f08d028de8a199057b5b837b26a5510959a7bea4ebf9b0ea8dd98896162b7fe","tests/expectations/nonnull_attribute.c":"661d8728beda90b65721fc48541b1e532e01011b8ce4d1479da227ca9dbbd5b3","tests/expectations/nonnull_attribute.compat.c":"39d76bd914641c3e8fc8d5c803290901872b7f35069acb57b92a367cfdce2b71","tests/expectations/nonnull_attribute.cpp":"0f6bb96180c6352bccf834ff30122c85578b3b0a9c28264d45704bf894431e92","tests/expectations/nonnull_attribute.pyx":"1602314d618d995a29b1cd864aa30f4827512bae8adaafbe8ae4754b193e4924","tests/expectations/nonnull_attribute.tag.c":"c53457574ee33cbb888c851ee016821ec3213b5ef360831fabd70d781e7fb292","tests/expectations/nonnull_attribute.tag.compat.c":"45a99a1efc18db8faee7f396e4e4025ca20dfcd9d7e35be532e77c2e7ac08780","tests/expectations/nonnull_attribute.tag.pyx":"d4083a527238f5786acfbdbb0b7ecf19621787a726ecedaa6649e76d1fc33165","tests/expectations/nonzero.both.c":"de3b7de2c7b04cc7ffef576238569efbe68878e2a5a0e8a61f846e6273c57c5b","tests/expectations/nonzero.both.compat.c":"3a387b8b306029152bdaf7a3cd50c8a2e7d660ade5f564a35d36821d4cf86694","tests/expectations/nonzero.c":"d383fbd9f7fed933bad88d90a5b668c7ec12c3659d4dcd4849e8acec45a40777","tests/expectations/nonzero.compat.c":"450edf13cea98960d7baa192f2024026f799f0d6bdf9a6b9761a69583be3409f","tests/expectations/nonzero.cpp":"b256e4467c238cf428345d6910f7fc9efbf5717c98fe58161ef623f73f568f39","tests/expectations/nonzero.pyx":"a0dcd9361bdb3dabe367da5e9da818aede4f0519478204a3ba18cb300a22c9ed","tests/expectations/nonzero.tag.c":"083f047fcf9db6970f30f64f78b93d4875aecc94f5b1fa66ece2e90c5073133e","tests/expectations/nonzero.tag.compat.c":"2110e5eeda0a97dbc98254408de095dacad2a1a3c5a19eacbdf2fecc314e3ac5","tests/expectations/nonzero.tag.pyx":"6843118de0204e84271957bf9bd90349261991ff3391706b7386ab38166ddc70","tests/expectations/opaque.both.c":"b30710454b62658d4918ce7201bc48574daf3e48559d70535532282c953e4a6d","tests/expectations/opaque.both.compat.c":"e8c8f7b4606c65a4569b04bacb2573ccc78e3199c75d55ac4857e258e26a1024","tests/expectations/opaque.c":"8e59e82e0dcc94a546b057b8798d4dc4741a0c400d407c062a3f275f6002c101","tests/expectations/opaque.compat.c":"ae35afdbe3cf3e068ab031a63265f4b94d205b1bb2c3a27c1554c90a3ef06591","tests/expectations/opaque.cpp":"1f6d6d69806dbc0df22f9817f7826f81a103fa7e144f4bb4c15f81ff8884f8db","tests/expectations/opaque.pyx":"621874f934c702e4ac17a23e1d35e59269300033dbc9304aa780badbc1531bb5","tests/expectations/opaque.tag.c":"23759de134ada5d93d0628de216317cbd7dc81dd2628742cb32971ec98311f90","tests/expectations/opaque.tag.compat.c":"4a49cfe48f53d84457e5892597d61fb278a66b3d21a94f7de12032c431e3d66e","tests/expectations/opaque.tag.pyx":"4015405e384c38acb9f7f592c566aa36d6200adf862c14b691eeeb79d95031fc","tests/expectations/pin.both.c":"ca5f471174d398194cea1dcbc6cc4a92917b0dc4c40a4e4783d6cbc25ffea7b0","tests/expectations/pin.both.compat.c":"20bef811ce72a83dbf46f0610ce5522cd83b4f01dad56200bc312e457c4cc72d","tests/expectations/pin.c":"ee1df686f63a00e47e4b2d70400ebca00d87365a5e5420046a8eed2cc98b908b","tests/expectations/pin.compat.c":"bae78af72ef3493fa81916ffdde6931302ef690447e67ec74bc7cd39c8a47f3e","tests/expectations/pin.cpp":"2696ff27dc5d3029a6822662efc61af37b692d208147397da3ef6ceee982d208","tests/expectations/pin.pyx":"a316d36d8f682ed493ed3569a8a760cd2387c1254d1d591f69344f17b623cf37","tests/expectations/pin.tag.c":"295dc9beb12444d0acf573defa070de3cde6277c97586f6293f5fca0575299de","tests/expectations/pin.tag.compat.c":"fe4686b3f3bf3cc7e0917e6826a8d4cf9c0f23ee034d4e6b3487b5f9fdb2bdbc","tests/expectations/pin.tag.pyx":"25c42afbb22d7582506a15b558b7ae192736966d2c2ad1ab3516b8b03679415a","tests/expectations/pragma_once.c":"95e7271709e92cc423fffba8cd534b6cd9c5d4754d5cc6dcbfe9a539f44e2c75","tests/expectations/pragma_once.compat.c":"906e661e80125cb01c762351e5bcb7981428aaf3304b6ab20c6d6932468656d3","tests/expectations/pragma_once.cpp":"d1892017945637ca6801719e8cd5002ec64e456d3b2d3b2c04eb337af069ab4f","tests/expectations/pragma_once.pyx":"3a86c97c4392932f53b8a0f6ebb436ab37c67cfa31e569322fc953b38aa34de1","tests/expectations/prefix.both.c":"6b2b07a2ffc19523144d86f31bb19cb696573091037cbdd077b9dd71ba530ccb","tests/expectations/prefix.both.compat.c":"62404d5616108de3a2acaeb43b2ae6b46286f58411cba8a0be8bf64768b0b822","tests/expectations/prefix.c":"46b860a97e645cd5bd80256dffefa934fa79c18159476bccb45adb757cce441a","tests/expectations/prefix.compat.c":"781e5cb6e1384cd9be9b72db829cf551b3b5c4ffdc17c12774db01389973bd84","tests/expectations/prefix.cpp":"fa42c2896e01eb387a6cc246d9ea4b352dc5e8a064b2b901887c4931fed5e500","tests/expectations/prefix.pyx":"2628e42be93e502b761838b826a62fe447cdaf8e5b9e5c7936fa32190ddf3359","tests/expectations/prefix.tag.c":"89007bd5e6f08452bb8754b2393017e04b1ace8d138cfc25904df019eaf4b08b","tests/expectations/prefix.tag.compat.c":"1859b9de1d0bce6191d5b460b0ad97153e9a696d960556a589f0ce52b2c4aacb","tests/expectations/prefix.tag.pyx":"28c6ef6d967e4922956299a34f9f956187a551a9af227938e1536a08f8b1379b","tests/expectations/prefixed_struct_literal.both.c":"9559f5424ca4828af65d221bbdd30793289b997dac8ee6352414276cf731785b","tests/expectations/prefixed_struct_literal.both.compat.c":"08b628769f3f69e4344023118fccd0f65f5d73b1a2dbed1e8cf56945eee1c6be","tests/expectations/prefixed_struct_literal.c":"99a2da6d8da7278015d9a58df331562fd81813453856d302e3675a62e9bb271d","tests/expectations/prefixed_struct_literal.compat.c":"2c9a529e318c2772d804348938406ac2482ddad4792a08fe4e929487668f543a","tests/expectations/prefixed_struct_literal.cpp":"c7c1646ee95fe973e6b08f3e1af0cf6802997d455259928d1315cbf266324a45","tests/expectations/prefixed_struct_literal.pyx":"def6e2fa920533665063b601c53bc104deeac1354463585cfa90fdb71a73a2bd","tests/expectations/prefixed_struct_literal.tag.c":"b68b97ac636ad4d9d87f42135b06fb7aee7c7a5fbff99d82eda74c1ebb5809e0","tests/expectations/prefixed_struct_literal.tag.compat.c":"ed20719d7f7639122f43c8b3aff649c88724c773903dd3db20272fe1bce9ebf5","tests/expectations/prefixed_struct_literal.tag.pyx":"b7ba0af6fa6e76b3dda926ec70325c5c7dbea07059c284d990310e5c63a0e1d3","tests/expectations/prefixed_struct_literal_deep.both.c":"32753f1450ab56384e15112615099cbf7e05062ccd2dc59fc3a729fd884e6469","tests/expectations/prefixed_struct_literal_deep.both.compat.c":"2c421ab89a10c32592af85876da4a71172c24e36ca2db6e5f3a5723866ebb0c5","tests/expectations/prefixed_struct_literal_deep.c":"997e66ee545f1a392e2cdf14f92fe3ea5fbfa5ff9fddb545c14b1346baf55802","tests/expectations/prefixed_struct_literal_deep.compat.c":"6afaeb3c4aca7f73957c55c9b6d153de0f6c410227d9004f2664db291e56d760","tests/expectations/prefixed_struct_literal_deep.cpp":"4e459f43d6e9656fa9bf674a721b743132a8cc42b3e35b0bc1718d532113d184","tests/expectations/prefixed_struct_literal_deep.pyx":"7ed0799231747875564eb43e78b18e0f803279b625c9bd845e8bf5ab9452e5cd","tests/expectations/prefixed_struct_literal_deep.tag.c":"dc18b95c737546333a0c116cfecc677556584a38d1f2e60a237d751c1e34661c","tests/expectations/prefixed_struct_literal_deep.tag.compat.c":"bc01145cd2692ad37659eea40f4097faa88602cbd8cb8a410bc971976f68c84e","tests/expectations/prefixed_struct_literal_deep.tag.pyx":"26498cb3a8152a1a50a12ed2d9c706959d6b90d39afc14158f4cd9d462474b84","tests/expectations/ptrs_as_arrays.c":"f23c55ffda78e07d22ad04db76dd3b49c2658eb919e709caa904820a510c8b17","tests/expectations/ptrs_as_arrays.compat.c":"dd7d3fc890b675c397f28ef905a5114047d0cbec79a1acadab5e61f9522fdb02","tests/expectations/ptrs_as_arrays.cpp":"ccc94fdc2e5418fb1c6e5a530caaab68459943d42d6586df46ea5c9aacc0676b","tests/expectations/ptrs_as_arrays.pyx":"3eb5550015d66109f9caf8d19f9498c8948b86aa3a950d0465145dd0618843ea","tests/expectations/raw_ident.both.c":"91ee9b892383769b89d80473183e570eea10bd2e50e95ec0ad77ba0446424fed","tests/expectations/raw_ident.both.compat.c":"0bc56b066457e8d8455ed36b58d714daa7739b4e9ca960d81cca5dd89f671814","tests/expectations/raw_ident.c":"b8e7d10a721b94645908abee01ca61b9450c7f6033800f9fa941ea589290cd4b","tests/expectations/raw_ident.compat.c":"3ad77d90cd04d55f00e1ace8ce91bfe51152adf19c9459cb9553d9376713e3a1","tests/expectations/raw_ident.cpp":"b8d1a964670429e5d3bab54df5b59a6b13c85bf1cc4ba3b44a7368262b2b6e7d","tests/expectations/raw_ident.pyx":"c13215aea9c776fd86a25e7d850170ae9d2f7d66f41c5a061503375732f52642","tests/expectations/raw_ident.tag.c":"7f8a8163ff099d62098af621f25e26c30e5e9a94b006004596f1ba33a08b569d","tests/expectations/raw_ident.tag.compat.c":"fc4f13d7a81c2c2643b60abec8b7e01218a5e20a7e77427feaa5413c00261682","tests/expectations/raw_ident.tag.pyx":"5f9809b9d80930479bf9807b1e5b897ec6a39a58845cf027e8563bd03e901b9c","tests/expectations/raw_lines.c":"026afd7d10e04be3dbb480078a3e9c9c827ae3f97e688f17d7428fffec2b0264","tests/expectations/raw_lines.compat.c":"3f8f40efb683163f6d9451de6eeb454cfc05f17e7af74edca359dd08ef57b3c0","tests/expectations/raw_lines.cpp":"921d9cde3bc1c797b93a5b329e0d34160e53559b3c52effc83d4c8f1507cbfb3","tests/expectations/raw_lines.pyx":"4af0f1e258276f5da540c0405e8f8a5e5d8904d658736d0c1ba83fdd3b4ccfdb","tests/expectations/rename.both.c":"77faa1f85cdc9b812e4803c75248a6494ed75d16ecd24624c1149f9c81069bda","tests/expectations/rename.both.compat.c":"c9518f693ca9df5ee1abdd18c9945acb1b74ffb3b150a82772d6b01ae6a9b7ce","tests/expectations/rename.c":"8263595d6613ae047750f23e842ee77ff503f6408a557049ffdbfc16286be38b","tests/expectations/rename.compat.c":"1756807a3c51e53a3da260cdbfc91450bd54c8b22fd27e79ce673b0713114260","tests/expectations/rename.cpp":"f4ee5fd92554a846e81f27355a25bb660429c6bb985ee7a883cf5b8fa32eb658","tests/expectations/rename.pyx":"2142172189e88fe19ca0d44560ec218af5557841c7214585b429be62ab245fb8","tests/expectations/rename.tag.c":"60018fdaae3750e2c60c368fe9a195027ba6ccae03a12533bbaeeb04a96d02dc","tests/expectations/rename.tag.compat.c":"61bbb70212dc73046e6be1a09250f1ba8163506ef53b4f5274abf383c7b9f8ee","tests/expectations/rename.tag.pyx":"d13f5ea7f6266966171ff07211e172e8da9b79315ccc5e87ddc53a6df7d668e2","tests/expectations/rename_case.c":"b7c67bf7fcdadb3a44f3e717f2d22131dd5d9935aabc22f28c5119f45d5ecdbe","tests/expectations/rename_case.compat.c":"307903360c05d387a1107b4c83639b86baeccf25a6590b271cede87319905613","tests/expectations/rename_case.cpp":"2e1c0dd0bd817ba7f0a099b6c49ce4a6d682408f6d0ba78163949f1b8c1e30ce","tests/expectations/rename_case.pyx":"8af444e46fef91aa30015e166b88a819e9b7e9040dc85681b6f9f8d95c1ffecb","tests/expectations/rename_crate.both.c":"0b18c131a60be4411fbaec9e05e1295c5ef7b6481435458e6626888929ef64ee","tests/expectations/rename_crate.both.compat.c":"584989132f23548fcb4efefc50a1d486c61a1096d979bbcc226b7d88048a7284","tests/expectations/rename_crate.c":"bfa98a6eb12d66ff783f4ccfc95e9f387241f4651fd4972d35c714aa11790a55","tests/expectations/rename_crate.compat.c":"620bd8a3177b1b85eef545054a2c0da7734acdc6cdf0de006550a5bf0b1f1463","tests/expectations/rename_crate.cpp":"bcd672b04df587cfdbff965a26c4036cefe4a32a0b0bc43f8afe12da6925062a","tests/expectations/rename_crate.pyx":"704067e5ed8c2a73a38d118b6c9de4d16fc16047b82e0ef5d20410aff3ceb51a","tests/expectations/rename_crate.tag.c":"2b7ca2afb0e0f30e8f9aba9f023879d34683d11da534263f40544c13df63fa6f","tests/expectations/rename_crate.tag.compat.c":"3d1a5aa501d0a5fe5fd729599edb1e1aa312b25dc7c5131f4dac351e31b8a283","tests/expectations/rename_crate.tag.pyx":"1f76217c43716d5a0c75c94ec2f5324ab4f65377897a727e2b82f14b4b27f823","tests/expectations/renaming_overrides_prefixing.both.c":"77c7dd26dc089205d7bad2f5ddaf80486425abf35c4dff952dc5e555ea1237d8","tests/expectations/renaming_overrides_prefixing.both.compat.c":"6220291f381b1503f344d4f5b2ffaae4a5bddb5385e8bc9ff71219f78fd5008e","tests/expectations/renaming_overrides_prefixing.c":"9c75ec110a52903b63e3174a636f0bd75c6d3daf03d041eaac1c3853d15cdac4","tests/expectations/renaming_overrides_prefixing.compat.c":"329934f453884687b371a9859a67f85270b56c6ff374a78cb03745b2cef7c4a6","tests/expectations/renaming_overrides_prefixing.cpp":"1b50bb928516eb1fddf1345dca133645fe271533ff7b0ddb106ce66ec1ffef62","tests/expectations/renaming_overrides_prefixing.pyx":"f739ece019f92a094a2a8ad937c16508f2b261dc8552a6eb0962bef9df69e7d9","tests/expectations/renaming_overrides_prefixing.tag.c":"8dde2e5380b0ecd415c4552aa95e272fbdcc4843bfaadce8845339d04ece4aa3","tests/expectations/renaming_overrides_prefixing.tag.compat.c":"b24513fd3120d796273599deebd8c81c2a40bf08b5ad095b1b6a63c3528a83ae","tests/expectations/renaming_overrides_prefixing.tag.pyx":"47fc898306bc851614103a77648ac89e083cfcbab345df711ccb92baf0750fd4","tests/expectations/reserved.both.c":"8f140f38d0872e5b17351bdb25e5b005ece1af0dd25252ce3c2db9291a459a8c","tests/expectations/reserved.both.compat.c":"089e8e487072489faf686ff79a66542dce5ffb62a70932cc420454e718dc08cf","tests/expectations/reserved.c":"e91ad65c8cb095fd5e391d0e0115714b94fbd5e52a2604861106832ed9e3c0ef","tests/expectations/reserved.compat.c":"ca3b08af39c9dc0b4402f4aa1bf27402b43916429953d8b5c59a489ae62512d6","tests/expectations/reserved.cpp":"a7ac3e2f0a699f5d0192e97812c68793e57a8b5ce07af48b6a9c2ff2a1680b0d","tests/expectations/reserved.pyx":"dcb0d2468b20d98ad1fd7d2ce295247849b492567b2361e75f6e01f935a9f1fd","tests/expectations/reserved.tag.c":"fa21c2123137ae01bb37f1458616922c4dc6ac62c05339f73142702808f1d2f9","tests/expectations/reserved.tag.compat.c":"2ee9b63889ba7a3262829b1a073da665bcafc8fdace7b4c2ed8c750403b597a9","tests/expectations/reserved.tag.pyx":"1c11e2d3b0137af92e64ea65f19c6eb3bc6d42f4da98f118a176ee9bfe5b1626","tests/expectations/sentinel.both.c":"87c249eda8e73ac37b586b6961e2cc0a0b970b793720c0a1552df9edd0fcc2f2","tests/expectations/sentinel.both.compat.c":"bc69a1dde5d2ed402211f979fc5a247b21638641a0869c556d44d6130b7a6845","tests/expectations/sentinel.c":"8c5bf6bd0b04574ed173f0f50f16e4191188a4f8401e05d6724f0eec33d35017","tests/expectations/sentinel.compat.c":"5bbc747d69716b12ed9f4cf3e64ea7b486d5473c86cc9ef4c03485e75437ec8c","tests/expectations/sentinel.cpp":"5c2d05019f8f65de0028ef870737fca9abb7ea177ba0d4dbb68fa5d9f1d1bcaf","tests/expectations/sentinel.pyx":"5d3282346d2c0ff7dfd596d0a7dedcc97d3df153c97c620f9db1584065c9593e","tests/expectations/sentinel.tag.c":"d50caaf5d902934525366f50ff8c85d370039baca0e5cadbbc13982ed7a98456","tests/expectations/sentinel.tag.compat.c":"a1772a029c21095e6431d907e6be39c710bd90cddaaa5612379f02fd026e930d","tests/expectations/sentinel.tag.pyx":"2d695cc04fd973c71b3b028cb783b02d224134ba23ea2691f8b5050b36a4189c","tests/expectations/simplify_option_ptr.both.c":"cc7e41a657e11bc440047bd245c47741b2277689745dd6cef8fb5c7c100c8541","tests/expectations/simplify_option_ptr.both.compat.c":"38a6eda3b72f869b92046bf0fe5de111686edd5651920a0effcac56715768d65","tests/expectations/simplify_option_ptr.c":"5f10f8757f3ed36f74ec3686e60b3b9dea13e961265e53ddd3c99659a9e4ed0a","tests/expectations/simplify_option_ptr.compat.c":"a40f97d0f10003a1e03ebd3d835acb349fbb384517307abbdaf0062578f972f7","tests/expectations/simplify_option_ptr.cpp":"5ffc251e522dacd0a128a607c45a9f93645d7b6b7c00770b4f2831c74efa6bbc","tests/expectations/simplify_option_ptr.pyx":"00936d6685c699b7214ce2024af110cd619015d992147967d2f579d32990e131","tests/expectations/simplify_option_ptr.tag.c":"6b1a96aa61709e545e3629fbb546886fc7ceeab17bbc96f8db50f3c6545929b5","tests/expectations/simplify_option_ptr.tag.compat.c":"9ba3eb34cd2c4fd2dd95c730c5dd4f79d5f188b24b66355488042d6a68274ac1","tests/expectations/simplify_option_ptr.tag.pyx":"519743231de069eab84c3bc4e8ec31a5f009ee34846d9135a9c1df6eaf3eae65","tests/expectations/size_types.c":"76501f91182f958bb08ebd6bb357646e36cfd7bc332fd166789a8a1fbf4cf397","tests/expectations/size_types.compat.c":"0857b5a4ca7bc32f8fdcf84b07e5c9d317a80b469525b61f12bf6f0f6a2e7e69","tests/expectations/size_types.cpp":"79e269afa154855faa3a96a2baf7f3a505fe2d1dacc07d04fcc35060e3c30d0e","tests/expectations/size_types.pyx":"71c927fec8165010be1ab8cfa4add0c86c3b420086a026967071cbb7eb3a91a3","tests/expectations/static.both.c":"6fc6ac1197c8e0bdf393bdd4f99d018057c832f611dd1b37dfbc985f6354bd3c","tests/expectations/static.both.compat.c":"d28d355eae17260fffb96c7903aa2dbdafb4f1ad12cd83a2cd7ec944f12c570b","tests/expectations/static.c":"4a84a7b7c6388ec65e0855c02780f253844256e9b8c9d2c8f9c19a1e67cc729f","tests/expectations/static.compat.c":"298387148c4c870854dbbe81c996575bce7306e640661c3c636a2e811f736dcc","tests/expectations/static.cpp":"a9054d752eaef1e6bd8edb169fbdddfd20f6f0627103ded58ad52d2e316f2a3a","tests/expectations/static.pyx":"7515602ece87657fbc5477cdb75fab6477332aa6964200b5c309fc4158bd7b6c","tests/expectations/static.tag.c":"67cd9094682d5878babe355e6f0036153008eff9a190abcff80d05e4fb3111f8","tests/expectations/static.tag.compat.c":"c132f2e64fd645e415ea99b546c97bca613348c0d4275681ff5079bd55d7b7f5","tests/expectations/static.tag.pyx":"d842f816824dd6bc1337b50bb653cfd44a9348abd6da1c2cc8e04c2773807924","tests/expectations/std_lib.both.c":"8ef283c43e91a9c77174df7af5d3999353e1daac3b0afdea17dbd132a6df22c5","tests/expectations/std_lib.both.compat.c":"997390aad31bdbe204e5aea068ee467de8bc2ed365991d8b514830282f60fba3","tests/expectations/std_lib.c":"8b8f89b986ef595c3cf7ae7604825ab30365406c1fb435fb0a7bfe1ab05f4297","tests/expectations/std_lib.compat.c":"93ce746242cdfe562bf0374584e0a913de41a718cca98ae54adcda44cf5d7a5d","tests/expectations/std_lib.cpp":"2ae1e7c56d054114d49ad95932d436f390bd89b37f763685fe91dee9617376ae","tests/expectations/std_lib.pyx":"b5f57cc4fe57d5132a8d98f1a4f19547e467cf8331870fb65573183f2d0b7730","tests/expectations/std_lib.tag.c":"0e1d6b0d0e41071718034e5940b01da5e45cb17c2f99db7552335c0720b86907","tests/expectations/std_lib.tag.compat.c":"2ee4070a5512b9fe7409c1b3444cda9ac3d7ba28fd17582fa0a461950a76ece6","tests/expectations/std_lib.tag.pyx":"1c8011a2edaa0128e4e90ed3e7ca1bfd0ffbd90d49c097b9f36c755938d08b45","tests/expectations/struct.both.c":"44788c37c8bcb017282501700e2211908547c973b1d67321f31c4c78edbdb7f8","tests/expectations/struct.both.compat.c":"7b06998839a1850750cfb320e1befc3f33537d49add9778e86bdcf575d03bb9c","tests/expectations/struct.c":"3f3a24f56a43dd92290367ed37d3e64562def9f91b1ada89347adb2a686a4e5b","tests/expectations/struct.compat.c":"72027b56ec38931f962b0abea91e94cc179b3588d7d7b4c738013a39c249e3a7","tests/expectations/struct.cpp":"24223fcecc97e832fe70bfc10ed515c4f3da7a4f9bc3517df93ba97ac604e313","tests/expectations/struct.pyx":"d266e1195a387510a1cf49c3d680301dc6d0988e207fd9031cee0dc343dab26b","tests/expectations/struct.tag.c":"98033bb2596a3852351de170e1139499ae39eb5f414c6624353709e4c602fc6f","tests/expectations/struct.tag.compat.c":"5e3b361a41f6a3540c10f632873483a2b295dd8bed5a2701fe498b20aba24704","tests/expectations/struct.tag.pyx":"8a7213ad4f7a3b5edb6bf341ffcf52804512ed5b9d75cbb8f7f453492b86dc60","tests/expectations/struct_literal.both.c":"dbdaba2b639e54e19512901ae9130e8524d8034005876398742dd90c312df1d8","tests/expectations/struct_literal.both.compat.c":"4e0814176a6e17bacf1f63a849c8f8fe7785b40ed3e38e4cf018fc3aaabe0129","tests/expectations/struct_literal.c":"8e120681c9d50cc290853a0373a75318c5b1d690b1480d6850e6cc2b7e621b3e","tests/expectations/struct_literal.compat.c":"433b9d0ca518190fad88709e67286ab35d6f6ed8cacf382a51252c15514fbee9","tests/expectations/struct_literal.cpp":"4890a434488271d0fb620385c7ab5ce5bda6878514ac0e62c432253e477f74f2","tests/expectations/struct_literal.pyx":"40a9b091b89403cab2295f72e5d003e1b4885f7e7104ec291a1f9f29e9b8f753","tests/expectations/struct_literal.tag.c":"41ab9ca8945eb6dc011925445882ddece4ea9bd8448277a5ad72d1cf71169a71","tests/expectations/struct_literal.tag.compat.c":"7a0e315ff9cdcd41e42ba103c6bfc2c220a6f1ce1b575980de4d4b6c5d52d5a8","tests/expectations/struct_literal.tag.pyx":"b369847669050e0b4f59aa8b05cbcf59813f02b6bfc9b7272d4862edb9eeaa97","tests/expectations/struct_literal_order.both.c":"31b61ab03512aee2f152073dea8423f322ee25e0754eb18dcd42d5b5ae3f54d7","tests/expectations/struct_literal_order.both.compat.c":"850873c0f1eddfcbe23ec803aab2f52b7128171b2db8a838142928144494a4a4","tests/expectations/struct_literal_order.c":"ab4e19c8e18c302e4bdae2e7e6d8d9b3e302286bb271d68eb2146db9e618f283","tests/expectations/struct_literal_order.compat.c":"489aab1f32445f2f32ac56cdc108d16a21357f6b269fea48bebb239c88b52982","tests/expectations/struct_literal_order.cpp":"41d552bf043993e89a7f3cee1222038a5f3ac44b317a05b9cbaf8e7bde9e2fe0","tests/expectations/struct_literal_order.pyx":"103a67d3a52029b6e5971665571c2c8c996a7163404fc0e891ee9f4003c693df","tests/expectations/struct_literal_order.tag.c":"818bec81379d034429fa870fac46e9878b0744e6c4f992904f638781e308f79f","tests/expectations/struct_literal_order.tag.compat.c":"2b59847145b19e5c4059474cc83c26b7fb543ef26cc91c7555043c86a00e056f","tests/expectations/struct_literal_order.tag.pyx":"9dd53c9b81932ac80aa8107577d62ef4241fe206977735ead3f9cf55a9663bfd","tests/expectations/struct_self.both.c":"2a187365237828051a485326d209fa72930b976bc82e580d74081eea028401e4","tests/expectations/struct_self.both.compat.c":"52fb23dcee0f333c981b9a40ad1a222b947b99f7db8feff437c6da775a5894b7","tests/expectations/struct_self.c":"1937ed40437d089404ea04e85df65343f4048830485b91680c44ecdd41f26cc7","tests/expectations/struct_self.compat.c":"8fb27c7eaeab15fbf369edb806a9342ad5d65c4be8dd88a411b10a290725f11e","tests/expectations/struct_self.cpp":"59c4b69ba609084b14f97b7ab545d601aedf9ed4429e5682155f791fdc212614","tests/expectations/struct_self.pyx":"4c8ef74ae6e2c77beee59c4ec671129bddeb7eecb8b43670be71160fdf0b8881","tests/expectations/struct_self.tag.c":"de2462cc5788b3a858b096fbb99cea9d13b9646b7cc8c65247d9492418f1cbaf","tests/expectations/struct_self.tag.compat.c":"c93763dd177ba56e5dceb21295c0eb8f66be05e5413edc91019240cfe840f53c","tests/expectations/struct_self.tag.pyx":"386321c5d2f4dcb7a714cdf7bda34076f9f90a706a9b2e58ce8bd1794c89bd41","tests/expectations/style_crash.compat.c":"cb16feeb6243454a636876fa5a6e046595e73f112eaa59dac9381732696d6452","tests/expectations/style_crash.cpp":"ce08b96a75048e41a1b1eeb07f188b4ae7759210996ec85060ad255fcaf360a3","tests/expectations/style_crash.pyx":"aa2a91d9d06f5ea56f74e813a887dcaec06903befbe5f4cd78c4cb8b53dcb0cf","tests/expectations/swift_name.both.c":"5dffffc5326d4ef841b68d8ade7c410c6b20851b604beeb8bc95354c2c4ec10a","tests/expectations/swift_name.both.compat.c":"554721f3f10201d18e7df09790086f9097b36fe5513e809b98446c782f73f1b3","tests/expectations/swift_name.c":"03b1398b9daf9b0acce73f85240b2085820d644d9d067363a53dcff95e892a5d","tests/expectations/swift_name.compat.c":"bf0cce62d4daec8e2408cc329d2bd8f70b9d8825ba3f278baa3e14f9f589069d","tests/expectations/swift_name.cpp":"f50a92ca45571eea3300a8f85074345289c3e3a4c4702195254150e7073aca00","tests/expectations/swift_name.pyx":"55346ca8f01e944a91aba0a22b7d8a92cc4a11677042b37e69e245db65a97cfc","tests/expectations/swift_name.tag.c":"155c5c6272d9671d4c2db0b1068aa7ed339c75ccfc349966a65364326ae4df07","tests/expectations/swift_name.tag.compat.c":"9b42f24733598f827941287ec9a551ed125b5016cbf902a14d7c05b5e54adf72","tests/expectations/swift_name.tag.pyx":"140ed42417c2f7d0f6796b563fc6b99db508fa3e106664fd367146213c6c2492","tests/expectations/transform_op.both.c":"c2d396ab17fc51293bc915a17ba6a0c165de4a50a7aca5a2a964648fef0a95c7","tests/expectations/transform_op.both.compat.c":"7ff5109437176e0dbc4f394291e56951d01da7dc8b471abb7f6cf87fd970dfac","tests/expectations/transform_op.c":"5c71a776ddf337608673a9f4f700dca411fd8da784b03d8baba8adcc60104c2a","tests/expectations/transform_op.compat.c":"0b70a18c01c7c5b9d4205ffbe8c04744adcfa0117c5bfdb97f1376ec8f63763c","tests/expectations/transform_op.cpp":"63446b46079c175bf99f2d475e360fd0d4e4f5ce2556fdf03b4331441494a47a","tests/expectations/transform_op.pyx":"c07b1ac344959537668a4482b5724a7247b20b5a7b62ba8b1b8180c8fda4a4e6","tests/expectations/transform_op.tag.c":"dd27004c7302cfd344582142679e81a2c4924432133771ac1b3511da71bb50ca","tests/expectations/transform_op.tag.compat.c":"42fe132b57f0b35710c8ae362f4927895b64d1012277af892d82095a43922774","tests/expectations/transform_op.tag.pyx":"b46395357b465bc95543089ce30d7074569780ad247dd03788dfb6ff9d13b399","tests/expectations/transparent.both.c":"c1ed47b4f14670faad177efcfd9c2bb74851201444da5a6ccf70a65132cba916","tests/expectations/transparent.both.compat.c":"23af96040634abd598e2196026cc0a23eb1a7f7b54bb4c2d7c28e0d74252377d","tests/expectations/transparent.c":"031e1800e40b6bd59b649a05b303df6fdb57255e7e7190c39c511a7b27a7bfdf","tests/expectations/transparent.compat.c":"685184af63abd732b4ca35d59d5de8a56150241f372c07204237c8b364379fdf","tests/expectations/transparent.cpp":"8915b4103154722b749a211a7f89e76cc6f9822cffcae49aa4d18764c39ee678","tests/expectations/transparent.pyx":"825c4b65506bdf5355b36f4d9c90737c86bc6d29272b7f9f5d2e5656effcc630","tests/expectations/transparent.tag.c":"6c5b0b107f05f345bc81c030233e63d38a7a82f5a5be719cc6029976892c6851","tests/expectations/transparent.tag.compat.c":"2c5cac22393daae1c514c17f242099f48d4149b9b8d495b697b0c2eeca34b60a","tests/expectations/transparent.tag.pyx":"2a39efdf6e611d81f6fbf67d658158e1bde85e8ad70f9ab93ff4336090ff84a8","tests/expectations/typedef.both.c":"79d5c5fb08e8e6929576ae536c3d7141607ed7a363a1ebec5dd82ce1f0f9cbe5","tests/expectations/typedef.both.compat.c":"88c51043226253b4ca3812c4b27998ceadeaa6637d8db6b34b4b05c93fae0528","tests/expectations/typedef.c":"e83d84aa0bfc55d54f16fb98cdd17e07258f129fbebf5523aee55ebced1d4b02","tests/expectations/typedef.compat.c":"32fd05db2b98796097ca252436bccb8270474ca61de4d007d5248697da092443","tests/expectations/typedef.cpp":"e208f1a81abee51bff3ed49f62f814c630e2303c61fcec26ee013516003858d6","tests/expectations/typedef.pyx":"79e655032a2811193bf8fa6278fc4d21d9ff93617b508df9c6964cc44b017a3b","tests/expectations/typedef.tag.c":"4af487e5e1b6e74f17ed8445c6e3a69f96307cc2f904d7e9b212846112575862","tests/expectations/typedef.tag.compat.c":"5cf3831cf49ab69a1900ff58fea5488bb2ebdb75d9829d5d2d6258d332970383","tests/expectations/typedef.tag.pyx":"89f9e5ee4e2919f80a7f615ccf995d87ddc3e794e3921c50c87b68511864dcf6","tests/expectations/union.both.c":"976ca72778588d6ed517b25f7315ade9f4d96a4261b303ecff40e8a0d7ada15d","tests/expectations/union.both.compat.c":"0590d866fa3d6fa7131cbfb2c6cad13ede12a10607e86705dd49550d53626aeb","tests/expectations/union.c":"966eac07c65ea6a6b5c22e90e55d06d931ae539662f862de3ba8be7039c04ad3","tests/expectations/union.compat.c":"0a7acc07e93f11677b2d6db5527bdff0bdb0cfa2dbd7a1e0190b3958143e50d3","tests/expectations/union.cpp":"848e43bd7086bd94c136f347fe2209adbad074527d2c9d07dc26d0ee0bbfa177","tests/expectations/union.pyx":"577352939826b36cd714b1f4ac244ec4c6030f9bcfd99aeb52b555e2f5a0b691","tests/expectations/union.tag.c":"fbc4da207f1ba8f3c26a014ed5ef015c6c46a442b65129ad363be2f12e6dc963","tests/expectations/union.tag.compat.c":"96ea2eb155962801870ad8bac885ac3b0350cc0d7d363d8e0b0ee713a6f3c466","tests/expectations/union.tag.pyx":"cbd531379c08e3b4e2b148f087fbfdd18e97f570fcfa8cf89b68b769c12557ed","tests/expectations/union_self.both.c":"f6aceb8b80c8467c6c83549874de4ad41aff41f8898c0e7fcdfe1e01a1609fc5","tests/expectations/union_self.both.compat.c":"5090bda547f554f35673ef355e0c89bf863bd79a3fa98ba98dbbc27a10dd3722","tests/expectations/union_self.c":"e51ee5773a115e0dc23e4706a07be90dc606d8ceda653aa01f8950f83b67c8b1","tests/expectations/union_self.compat.c":"963d78273f7e213f0223153b87c73d348c1a234df0b7fb215d8b239b4db6501e","tests/expectations/union_self.cpp":"7ff87eb2163420bc3d7deca616b96a53225bea94d30b24d955ebf0240b773dae","tests/expectations/union_self.pyx":"194a0d6d5b7b338722fe966b55a3b09aee375e857942f1d218bb9586d08a282a","tests/expectations/union_self.tag.c":"eb6db9deec2228df7e761ef5ebcc2a44c9bf642db635bfaf9fdefb74ac848c18","tests/expectations/union_self.tag.compat.c":"c233507a1b1e6dc09136a1f586a84bca9f67cd2d0cb750936e449b8145dbb16d","tests/expectations/union_self.tag.pyx":"a9c50823695c5d7d3be5d9448cf498602c0aa138f89868a6499783ae26281ee5","tests/expectations/using_namespaces.c":"fb2d6c8baed0b32ac1c5e69864e57f73f0a5c2ab8a6b37a5e763352ae43fddeb","tests/expectations/using_namespaces.compat.c":"417a45ea1ff78f2eac7f84c617d72377117cf31388df070ae6dcb70a412f33e5","tests/expectations/using_namespaces.cpp":"033d493d0d18d4f21abd489ba9618d49bfb0f7049f26ab5963f388c52f39467c","tests/expectations/using_namespaces.pyx":"3a86c97c4392932f53b8a0f6ebb436ab37c67cfa31e569322fc953b38aa34de1","tests/expectations/va_list.c":"4fc02312093bbce794f0ac0955d9adc14b63f91bb26cd8b5413806748b7fc06b","tests/expectations/va_list.compat.c":"5ad4f390682d3d840e2fae38731fccb9a20325b41e5814e3a507896568ffb60b","tests/expectations/va_list.cpp":"c095ef88de58863535d4e6268696c3016512da1f3a970f0f93d5c0d593caa48f","tests/expectations/va_list.pyx":"c39d0b93112d3f05dea5221722ef0ba1eb15ae4c2947f9e0eaa10fbbcbd6f6f7","tests/expectations/workspace.both.c":"7f468e3471a1c21fb19950107c32cbb1f61a55bbfc7217038a6b155868eab0c8","tests/expectations/workspace.both.compat.c":"f3cac1a0847e3bb118de25320846fca47cb08986a048a18e97edae0c17050648","tests/expectations/workspace.c":"f0b6aa5ec14968a880ffbf21662f901aa3955c46c401d87e872dd283ba504069","tests/expectations/workspace.compat.c":"6f040c52cb58257efb5c43098e413e751395aadd69b320ab9155da3c3cbc5000","tests/expectations/workspace.cpp":"9ef7811351c107141b697a481552bceb9c9992b8862af9129ae9411fffb65d30","tests/expectations/workspace.pyx":"5c341cf4f8c6f3269c92e9d681937f2036ea11f2dfc76ce506139ba5f9d1ecfa","tests/expectations/workspace.tag.c":"ed26bcdb8568eb62f2cc09e6112cc012165e6faa2b52c283b8c28dfcf560cd23","tests/expectations/workspace.tag.compat.c":"f842aaeb2648812733f436d312038bab8c875534171efa5c82a88b87253968c0","tests/expectations/workspace.tag.pyx":"aefa3818c4a23869e8119abd4103af623e277a73c971034d851fdc48b3fe489f","tests/expectations/zst.both.c":"70959f28c197126cc3372a62af96f92d4283bde7ed9172f7096ca8df51a384ed","tests/expectations/zst.both.compat.c":"b1fcea6def407219f5e91e5d0486846f75e2eb75c416c6dc8469d2c6db21fc50","tests/expectations/zst.c":"cd78682cbac3d5c71ed372841329d7a5e6584664a3b35c90095a605a53939c7c","tests/expectations/zst.compat.c":"dddf99765cb5f85713c2ff8b45248a8638e834c70011bcdf468871705a5087dc","tests/expectations/zst.cpp":"8c4253887a47a0998f0007d082d73b89e728bddf438102c6268f2b6c706987ab","tests/expectations/zst.pyx":"4ea80e7e218c5529c28c1fd9a5e5802753baa5cafb07edd0c31cdea9bf2b1c22","tests/expectations/zst.tag.c":"b98b24d5fb3dab63d078d9248cb5000ba57601a27eeae7f724ab6ff393669bd6","tests/expectations/zst.tag.compat.c":"2775e2adcb08da84d3be81a4c19cefc4c9f67985a27f4aac8603bc6af5abf9cd","tests/expectations/zst.tag.pyx":"94dc49969fe20556c13f5815ab3d2de7950751067c25c85f189cd7a79569df5d","tests/rust/alias.rs":"cfa45dce533ac0669cb5f8a5facd80b1308e5b38af26082361ca1fad683dfb01","tests/rust/annotation.rs":"2ec88922528b315bda1515e9167b5f771ac958b8e16db487b1427f6b4576283d","tests/rust/array.rs":"f3f321ecbb21331abec66eb8da2200550bee1a116e4a5c1389c4404114388e67","tests/rust/array.toml":"7935a7d9b5fabba3f500058ce7b3c0cd79449283e6a353a3d1658e55709500ee","tests/rust/asserted_cast.rs":"5207c37aae5b929bf28195c619fcc23f6887be6d763205b201c1411d1f58d321","tests/rust/asserted_cast.toml":"49d996a324f26d749e4e9a03a2ef1e30421e6716b652d24e6bb3fb753b00139b","tests/rust/assoc_const_conflict.rs":"dd5bce15a9b1198f06b06c7ddfa9244ee69e102baf487608db0521cec65de2b4","tests/rust/assoc_constant.rs":"3fd9391aeb6610ffb03e1cba5725dbd581a30071c7d5440c8f97845cdb3c8534","tests/rust/associated_constant_panic.rs":"761b5d70dc78a3b08713e8ec804022ee9e81284e8e968c2e7921f911f926c0a0","tests/rust/associated_in_body.rs":"0d51663ad3d686649f36435b47aad3e25d284d8d95b31cc797367fa950be8297","tests/rust/associated_in_body.toml":"584f72f042ae5c820f17054d3e5b49ed523ba51707adbe5b032bdd0031b9a26c","tests/rust/bitflags.rs":"b4dc7a4af20d1281f3965c2a295797aed00e1ced041c9a238b1667fea7dfb46f","tests/rust/bitflags.toml":"2d501b38c02c7cac4669d3905c8cb6f559c01bdda5e8d4b7a4fd3f8aeebf730f","tests/rust/body.rs":"986d2f7b8d9b4c4b76374c31bd7924d842249f9273dd15596fa00088ade2d86e","tests/rust/body.toml":"cfa734400fa079e137a3705c686c35eba1380b2f8dca9480b10e1930a292a9f6","tests/rust/box.rs":"03434d85fab066ed38fa39c372bd3be89af96913021c0190770da5f961e48bf8","tests/rust/box.toml":"78361b0fa8d7b0dea35cbe78badcbc5ff72bee8b8f69c451b3b305fcc41dfde0","tests/rust/cdecl.rs":"49d928c33231e9df3c0232aa913defd771c16c540617bda8c238cf8497436f16","tests/rust/cell.rs":"455a5ab03499d3bfc4c1f6662a29bcde0dcc8b09aac0058ab3a142192c87a9ae","tests/rust/cfg.rs":"dc612c646079401aa9ef8bb03040ee8f8d412683877959bd8a581d9953794d68","tests/rust/cfg.toml":"4af74309b7723df209b4880575e952a40af7a9a9acc7ab6e63ac052bc11ce106","tests/rust/cfg_2.rs":"16c59cd70008418750bcfca47c14a87a348b34c81fccc06115b68b0933b8dc64","tests/rust/cfg_2.toml":"49e149901948f7a1f2ed5cfc6d415b799d51848de235b2be153e7ef922d544ff","tests/rust/cfg_field.rs":"904aec8f65fc8ff7a33ec9aa474891e87770de411ed1603c1cf3f5e14c0703f9","tests/rust/char.rs":"8d266ad0518c6d864ad117f438963b51995fbe1825e415c35abd1c305b626364","tests/rust/const_conflict.rs":"6027453be28b17c20eebb6ea450b91b1e781b41fca08b97725b0eb7393120b47","tests/rust/const_generics.rs":"68b3c832da04d17dca8dbb589ba50009d8e89eb39618e9cd67ca4fb1f09e8a60","tests/rust/const_generics_arrayvec.rs":"f65ebcdc766371561e2ba947103b5cf3404568f763548b81cb3efaa5d93d9747","tests/rust/const_generics_bool.rs":"38ec457a423990bc7feec4346ea503e79fd57b6abab4ff4b1a9f8fd290c86d51","tests/rust/const_generics_byte.rs":"2e74c4a5ef57b2adb9e1e0041db1eb73bff2f4c4a0b3f748e70c6efb2c1eb4fc","tests/rust/const_generics_char.rs":"dec6117d9e91c2aaf8ab6358ddfd438a47cb936879bbd06eafa688398e9422af","tests/rust/const_generics_constant.rs":"380ba5515154eb4eccc9e13928c92522bd251c7b339d96c4ca4ab8dc7bdc25b1","tests/rust/const_generics_thru.rs":"087668e5c83236fd63c3acd5726c452818b13d6c6a2bc941e0704789d27e1929","tests/rust/const_transparent.rs":"7b3b029268345c373b4cd341c0be1bf6fc61d0ba9752f1f298e873f0b2638a71","tests/rust/constant.rs":"73eb998b1de5c6b48b73981e47b87e40a86bea6766d5ab31aa2f3f54d1e86071","tests/rust/constant_big.rs":"ef57342d59c7252cbfb5668689b82f44a9905d111cf5495dba655c2497edfa15","tests/rust/constant_constexpr.rs":"d5a974e8a2309975e069a59e8621d898aab8d52da8aa0d776d9571764508c99c","tests/rust/constant_constexpr.toml":"578ab8fcb0bf020b2486557e49ca473327d60452f75ae1602a6bb8e98c85be4e","tests/rust/constant_sort_name.rs":"b0fc655ea110af97dc80266dea84aaca098fb03224caa818c0adadcd48061b7d","tests/rust/constant_sort_name.toml":"739bdfbc7a1edaf7173011220ad822d8929ceed0985cc68700a478ae9f5caa26","tests/rust/constant_sort_none.rs":"b0fc655ea110af97dc80266dea84aaca098fb03224caa818c0adadcd48061b7d","tests/rust/constant_user_defined_type.rs":"49911c1eb1b69771a020a705fa6ea538d2a1e26d1181a8fd6c1cfc11e16affd2","tests/rust/custom_header.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/custom_header.toml":"4ca71bdad8db36ed78e0cb6342a33a4023f3f535a48141c43905750ffa688f96","tests/rust/cython_options.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/cython_options.toml":"425bef8aafe10ec59986426f8147abcc56e534b12b950fba7ab2a3db50bf56a6","tests/rust/decl_name_conflicting.rs":"14c5ff6339754ca440d144fa2c97081d61ffc004bb634fb0ae586e87921384ac","tests/rust/derive_ostream.rs":"d815d16ba4913a40e4893fcf16193ff90abf352556191eb98d91ecb356ff0fc7","tests/rust/destructor_and_copy_ctor.rs":"8eb882982e9eb3d08a1157c89ae6962a55624f3e5ebf878757aa9f31a9eaedaf","tests/rust/destructor_and_copy_ctor.toml":"b1e73400004d05354122f6aa57352eee27c3f543c08f5b689802e47dca5d6a2b","tests/rust/display_list.rs":"b4c8388b49c0d62ecc2ea3b2b43474b7ef672e196cb9c456f9f0dd317cc315a2","tests/rust/doclength_short.rs":"19839d89d5a0526bb7eae81b335c94d980e0aeb9d4d51706463d5543427d99fb","tests/rust/doclength_short.toml":"8ca95480bca52ac337cb4410936d71e73271d79acba998d29068c3f6855c4a58","tests/rust/docstyle_auto.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_auto.toml":"1609736841750b13dffd4ccd31820b5212913c19cc2767bca90672825a055614","tests/rust/docstyle_c99.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_c99.toml":"434839317738bc8ec8bb7b71cd3286b1cc473854929daebff35bd8748b056fa8","tests/rust/docstyle_doxy.rs":"44f9d1d22a4a44930e69fef2603b6a0fdad5767a0ba17e0fce89927597d5b4f7","tests/rust/docstyle_doxy.toml":"041f3902d904ca4756bc35352b1885781b67314a5a35f4c894bfc4aa3e0185e1","tests/rust/documentation.rs":"3c3451092feeb8f6283a968a7cbfcdbba23a6004327761e0fe8d4073a3ba19de","tests/rust/documentation_attr.rs":"7df25a9c3e7fd97cc916c324536d30816132c927c325b8623e24321806d879cf","tests/rust/enum.rs":"0d3d219b4e1418558b99c63fbe10c2879cacbfe69d0e465940d9ecb3b44f5112","tests/rust/enum.toml":"c67604d307b23aac28b02a34f9bbf451f2b169ac157d845e65ff3734adcf0576","tests/rust/enum_discriminant.rs":"2415b502bfa695c84ea672fc24fa6842ddc4c06ea55de261fa035b30ded94a3a","tests/rust/enum_discriminant.toml":"7a4b4d6adaf4d7fbaf6135b4cc859a86ff9e62b184c44cedd48bda4e79d0df27","tests/rust/enum_self.rs":"07523f250ad30b00cdea0325e55b93e066090a42f2d37cf07d185a81385ac3d4","tests/rust/euclid.rs":"d93d138d31e1cd90ffaec25d44feb2305dc702f45db04733b1ea79c0f164fea2","tests/rust/exclude_generic_monomorph.rs":"4b6299729923ae1e36e4ee3ecf766cc2825b46a25d0ed2033641cffb7c3b35ad","tests/rust/exclude_generic_monomorph.toml":"fad039feb18394d4d05d597a95118f4c3eff754b684397d54260e6e772c0d996","tests/rust/export_name.rs":"bb35cd7d9ab197774684aec596560859315ded1bb29ed161907960423d838ba3","tests/rust/extern.rs":"fb8c0e2b06186b4fbcce4f059289bc9c775ea42d3e36f935d407a2882f32c9d7","tests/rust/extern_2.rs":"6299ea10095ef94e3285844029c067349f07fa78c6d891b3e7402f85db36bcf0","tests/rust/fns.rs":"7c8da1440a30830b395bac08d50a0a41c91f01be00b57b8821b6e40159d5d487","tests/rust/forward_declaration.rs":"3e8616a472d97bff7239f42c7991e4893a2b7ef8730f6833b767c0d37a4cf7d2","tests/rust/forward_declaration.toml":"f4e9df03133b937507a034bbec10e680969fe47a57bbbb65701d19fbbddb5190","tests/rust/function_args.rs":"81ecd18c5919a3508f3bb6f04aecf4f91ed9db27da6d4b54a17fbe1d9b626643","tests/rust/function_noreturn.rs":"d797d6511c800d02a9030ce3b8ed4a88a14b5866d21dbf505a9d23b7223f50e4","tests/rust/function_noreturn.toml":"3e0549ffddce990d0fe3e3860bff8f2e39434658578505105afdc6b37d1133b3","tests/rust/function_ptr.rs":"eece7bd1bcdbef8b9c2e875dc11eb59d82a1293ace228b4a2d7ba07354bd1758","tests/rust/function_sort_name.rs":"a816564c64059e90587172feabe824726eb58050729f43237603bcb5dbf3694f","tests/rust/function_sort_name.toml":"1dcd75d52b46fc43de0e5c7b3dc300338c68e8ac0becb5b375821820c43a369a","tests/rust/function_sort_none.rs":"a816564c64059e90587172feabe824726eb58050729f43237603bcb5dbf3694f","tests/rust/generic_pointer.rs":"620d093fb1606a81d1afff60d1359bf76461214382b968e951dc12d1070af5be","tests/rust/global_attr.rs":"279e4ce58c67101d8d03f002a918bc89fd4b819a44b43a9e1259fa6529d02692","tests/rust/global_variable.rs":"0d4f12d6b688bfc5a9e134d94bd5391213bc24793aca59b5f9f3f3a8e4b9c7d8","tests/rust/ignore.rs":"abe57db0bc568385ba20e379a30f928d8c5a3f851b8910fa15d05ccacd1c3a74","tests/rust/include.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/include.toml":"0c0530f9ae070027bfb23f539458782938401d028ea1b7b457dadc6b9eb0ee19","tests/rust/include_guard.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/include_guard.toml":"4f92729aeec3544b88bee8854e9b608c3fe5cf523eedee86bfd818a657d6ef9c","tests/rust/include_item.rs":"b59b9e35174bf2156e7d4d3d686b0fb6eb3976abd1e5c270693e3987b8ff9e4e","tests/rust/include_item.toml":"a8a25d0f3949303c1b2ac75ab142bd2a3418d54e335008f64ffe0c08a4f8fce2","tests/rust/include_specific.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/rust/include_specific.toml":"579522a1f980d6a2b950d2cb0abe527c2c87b7d8147946ccacec0eadc6a7b2c7","tests/rust/infinite_recursion_typedef_monomorph.rs":"69f3a37eb5d08dd25cc90838666d116a07fdbe3bb7bd24e911abe36215476cb5","tests/rust/inner_mod.rs":"84d975ad14c8057f7cfc21d2a0dffdde043fef5e97e50bfb76abec61af617271","tests/rust/item_types.rs":"507a1de52bc29698edac28f08b0cec008604579689b9ef3cd832eb56ee359482","tests/rust/item_types.toml":"92ff09b39cb560124161667fa469e58bb5b369aef7b59e7668a84c8b7986c09f","tests/rust/item_types_renamed.rs":"507a1de52bc29698edac28f08b0cec008604579689b9ef3cd832eb56ee359482","tests/rust/item_types_renamed.toml":"68ff8b74b6dda04323ce09fe90260a5b6f203c9e7a75d77e021ffc973447a1cb","tests/rust/layout.rs":"79cc422e9976fdbe44272a185d0e233f96fd15e86af092a0dc9ded5517e9178e","tests/rust/layout.toml":"b4fb6c69305f20776a22f40a3d2368280fd908426ad68572ab59a0ef0711974d","tests/rust/layout_aligned_opaque.rs":"2b4af2cf9a2308a1b0407f389e680f5a3a5b81cc7121d4164aaf6c10de8b5315","tests/rust/layout_aligned_opaque.toml":"2ea5eb9208f53a0246f458fffe093d0a557ea5bac8a3910bf80efbdb56fbaf1e","tests/rust/layout_packed_opaque.rs":"fdb022462224bf6679111ed2dc4b294352d235a3ccb53a21cecc0418624370f0","tests/rust/layout_packed_opaque.toml":"b2f2d4cb9061267ded116cdd461a7ae2d3f156f99d007ad8d137f60588a19c84","tests/rust/lifetime_arg.rs":"33c5066b198b82e1bb6044a3ed913447cda9e52ac43c893a239c2d4ab0a98a54","tests/rust/linestyle_cr.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_cr.toml":"24724f1514e7f79178fbebe757fa24f84ba1b996cb37e1d4de35394a2eee88e9","tests/rust/linestyle_crlf.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_crlf.toml":"a315db1b1b4fcb6b5de44b8cd88f560161a99c166ec38470f9a7c7c0a9b0f02a","tests/rust/linestyle_lf.rs":"734eb068f66bf32f85ba9f0dcc1973a85b56eb0a0561daea0a26272e238c4eaa","tests/rust/linestyle_lf.toml":"9ac0b95d322c535fd3d13cca88e1a41c07f76bb82c073a6c201702085cfe136e","tests/rust/mangle.rs":"b764fb75e43856f76295b7eacbb5ff4b8d73772d1dfde730606769dd7890b427","tests/rust/mangle.toml":"9251c18d50b2c1f57afc70979f70cf54fa4d96b2b8abc3b7bf02ec1e74846875","tests/rust/manuallydrop.rs":"c6262ebd269697737c3e169db8344dd58bd51c049fe3a0ac65d3dfb25a8fbbf7","tests/rust/manuallydrop.toml":"ad2c9b4a190521a243dd37c27f9894e93dd274c2782d6651229ea09a6ff63745","tests/rust/maybeuninit.rs":"fde78e4074fe0eb6ed75f1416b5fbeafe5931c4df3edcd1e51c31e4f38a5c517","tests/rust/maybeuninit.toml":"d2322c437c261ffe1ca9bda7cca7cc78e9d6681a04f32c0aad7ad95852fb3574","tests/rust/monomorph_1.rs":"4daa3c42f7a1bf0bb7dd6ed605f554db4dc6f8dbfcff999939e218195563f1f2","tests/rust/monomorph_2.rs":"eab2dc18f375594f16e00b401c9c8f4f98c770d61807c3323080ec811bcc0230","tests/rust/monomorph_3.rs":"e1a03e6f9c37a64183adc89ba978bccead47deab61e563f02a1a66520782154e","tests/rust/must_use.rs":"fa6d2c1474f4dc07b5b2defc463ff0976e9ca25eb93b691745174fe1fbde11b2","tests/rust/must_use.toml":"4c4c13940de3a610e25d319682ed53a10c26a0450f3ccf14b90e730d701822b5","tests/rust/namespace_constant.rs":"d280b65bdcf529b456570a01f0306b4e9ffc0aa22200fd8b54e9e5433f6c5ab2","tests/rust/namespace_constant.toml":"493e814e3ade6f1fc4d34140c73d0ecdf00f1e4864f7719516d799eecc9eb2dd","tests/rust/namespaces_constant.rs":"d280b65bdcf529b456570a01f0306b4e9ffc0aa22200fd8b54e9e5433f6c5ab2","tests/rust/namespaces_constant.toml":"6b5a58b167b9890c186ad92c9f9164b9f3204a86d706a7be688d51f8a666e9de","tests/rust/nested_import.rs":"35a8343efe9117b3ca460b2d8e9a4a0813d58f622ab776cbe18527814d7105c5","tests/rust/no_includes.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/no_includes.toml":"504215785a725906418431f044ff10cd2ea2db7261ff990a3f278dae17c05e58","tests/rust/nonnull.rs":"dda4baa922a142eb7ef283a5fb672fed6492552adbcc82106e78d482a8abc39b","tests/rust/nonnull_attribute.rs":"9479791492ee3c9e0838e3b7d207ff3338d0c7867ea9f5f7d42c4224cf1f515d","tests/rust/nonnull_attribute.toml":"d41f84191d8e843f2d87facc3e4aea13b2d4a02099e3e1fa9b583c4d1b855c91","tests/rust/nonzero.rs":"2a3f41a681cdffb9f9d10eb2b56b9359c961c1bf48881e16573b1b34232307a6","tests/rust/nonzero.toml":"7838caaf3c460e73d5e055001b2d52c560084701dadc9ce8447563a6726e39ad","tests/rust/opaque.rs":"d22d57adccab8cecb28d4573a42de30e76bb32e836843012b720a4828c35b227","tests/rust/opaque.toml":"4c9bdee2ba996a05d3148a6f12ad7a64c6f651c3e00b199b7e5d5a9f35ce7140","tests/rust/pin.rs":"dd7db5d6dc0c0bf40828f8b45d9995bcc3de5b8e06ba5b91c64b451e9af0e500","tests/rust/pin.toml":"8d790949c59791b57d0a085c4c3bdf777728297082a87982f6303200f2c16bf0","tests/rust/pragma_once.skip_warning_as_error.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/pragma_once.skip_warning_as_error.toml":"bf1d35fcffe74f6689f53712cf7e079693f0a92c6e77403b5f9a5b0fcb0cb96c","tests/rust/prefix.rs":"773f2824b4771b8ceefb44e4ebe0b1d991acb0f297960fda543ea7a657854876","tests/rust/prefix.toml":"c6ab6c4cd09d12cbb04ace74dacb51ca5c89b6f0d77f2d95e918f22a9f27c0e3","tests/rust/prefixed_struct_literal.rs":"ce1843b02706788c31f8fb5889674ecc17f7940254cdf1e37ca47846b18e56d8","tests/rust/prefixed_struct_literal.toml":"d74eb710eb1f3bd05a723e54a6897170491ba0ae9bcf26acd1a3fe00e3a4ec14","tests/rust/prefixed_struct_literal_deep.rs":"fdee21e3739e9cf93ce1886d20e83db7597f3bb0d0c60c0fa5cab0e3b8beb1e6","tests/rust/prefixed_struct_literal_deep.toml":"d74eb710eb1f3bd05a723e54a6897170491ba0ae9bcf26acd1a3fe00e3a4ec14","tests/rust/ptrs_as_arrays.rs":"264ddc525e4286ec480caa1e011c3edc846eff16d2cb5f061295be55a86a3844","tests/rust/raw_ident.rs":"4d83ee8fdf4cc572d944baac267fd30318039441f17d6682d4457f2252e61217","tests/rust/raw_lines.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/raw_lines.toml":"18d6b74ac6571b81a58c8a36e9e23c594537cbb63e79df73ffffb54da39ee87f","tests/rust/rename.rs":"9a310fa1c402c996047927342a94bd50f36697d124cb3214f91de31bb7fc31c1","tests/rust/rename.toml":"42523c11649292309fb8a226e2153768c5e44af1cf586d53fdd44a64bf59be40","tests/rust/rename_case.rs":"59f8788ed6118d353a37f5014f9604a8a970065be2e79db7d8ace663f449499f","tests/rust/renaming_overrides_prefixing.rs":"f1fcaf9d1f7a11f749e819524d73171986f76543204dbe8e5781097b1df6de4e","tests/rust/renaming_overrides_prefixing.toml":"ce65e3488f3e8c1ab5a4b6a191f1555b83156619bf332286d40005be260cad33","tests/rust/reserved.rs":"5a802dd88ef94f129d93a895ed1e81531100e8cf82d8fc5a9aa55afcd50e3458","tests/rust/sentinel.rs":"a982a4067401d8257f0d45d7832895eec5c8a352ff8fca5fc49a4149599d89bd","tests/rust/sentinel.toml":"93812028777748e46ee6b023b3f41864718862d47a862a92c0073b84e03f22f3","tests/rust/simplify_option_ptr.rs":"ab17ae61577f15ef1fbb8e4c6cdff97a52ff001b27bbaebe8955764375db1fe9","tests/rust/size_types.rs":"314dc9b48853b286c6dd2e40dc355411a4310b5039f1aeeb39f573f3f891becf","tests/rust/size_types.toml":"2a6c8e75eac5a680c34b78599c04c41379dbe0ce6d1ff6f6291685fb156ad6bf","tests/rust/static.rs":"2241389aaf3d3cf4db7dcc16071b2a2abab28669b11ba4f2a66fa85339688fda","tests/rust/std_lib.rs":"c1c8f383f01608f7f7c6a104fe470c8afd25be0ceb2194a702905fe9aa82d74d","tests/rust/struct.rs":"ff89af75f5766eed5c02a7272919204793ef96cebb63cd9ecd934699f232656a","tests/rust/struct_literal.rs":"d459e815498b0457f1d5bdb9ecec1a375985e2d57442ddfa29d5335e4cf8ff23","tests/rust/struct_literal_order.rs":"b3b4ee077bf7362a8b1af37ae5dba8bfa3c0d13a25e6f49a201eb857c1024c68","tests/rust/struct_self.rs":"7f0ca8785ff6d25be86af271229a42958d6308efe1da71421b5e505a3626c267","tests/rust/style_crash.rs":"8c4c716638c58260ecced5a58bfb035f6e42375a2d221028c2fe0d99203e6b44","tests/rust/swift_name.rs":"4852f0d6547ed54e6f2b1de9a977a743a025ad8da16297818bc24af7b17199a6","tests/rust/swift_name.toml":"1542a5b0409fa024ec7c81190887633dedb186c14d37b053c25f0609fd99b381","tests/rust/transform_op.rs":"103e3ccf7f34077ff2e61107242fd957cf0c59ba659537b12facee18b22d08af","tests/rust/transform_op.toml":"6129b6b8ea9a289eb64ecb5123929ed31d09f1374dc59341e1fa6d22842e55df","tests/rust/transparent.rs":"42e2adeea38fb1418a011ac6dd8fbd97958f8a91bf6c6faebb687dab468fd3e2","tests/rust/typedef.rs":"8e2c8c9dd0014040187fbc656a1a7921e4faabb7c10ba00f7d68fdbe05c1219d","tests/rust/union.rs":"4e697db4b97ef737c06f9997f341505b306abcb6145a6b767b8203f72ceeaff9","tests/rust/union_self.rs":"bec8ef669782564e9710598816aa7266e2ab33321b9c2f7c7b4fe8c683386afe","tests/rust/using_namespaces.rs":"6bb8d24e0a54594a9db16c3f19416f81945dfd570d9dc4eb64f75b25535c7cb6","tests/rust/using_namespaces.toml":"2f96d6173b28f152bfdc8b8692972eab1d549d340283607b6f5ee13a02242335","tests/rust/va_list.rs":"d35aa437a1f624ae4ed8530e48ee0e15ffe5997ca5b79e06412d6f0eed133ed6","tests/rust/zst.rs":"cb77d9fad1476d0e7237a7504be7d9631310e697eb72f20a100a098e433de6d4","tests/testing-helpers.h":"78e624dfd94adf25fc2bfc69be5ea18dfffa049f146345e7881350e77fb9be7d","tests/tests.rs":"130dda708010a86905f6b042e4993e96c815ff60104a3c59d078588694d11a85"},"package":"faeaa693e5a727975a79211b8f35c0cb09b031fdb6eaa4a788bc6713d01488ca"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "dd9a550152cd162a3aa01757a55dd22fc56d0d8a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.clippy.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.clippy.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +# Specify the minimum supported Rust version +msrv = "1.57.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.github/workflows/cbindgen.yml clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/cbindgen.yml --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.github/workflows/cbindgen.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/cbindgen.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,87 @@ +name: cbindgen + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + rustfmt-clippy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install stable + uses: dtolnay/rust-toolchain@stable + with: + components: "clippy, rustfmt" + + - name: Run rustfmt + run: | + cargo +stable fmt --check + + - name: Run clippy + run: | + cargo +stable clippy --workspace -- -D warnings + + - name: Install minimum supported Rust version + id: msrv + uses: dtolnay/rust-toolchain@1.64 + + - name: Build with minimum supported Rust version + run: | + cargo +${{steps.msrv.outputs.name}} test nonexistent-test --verbose + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install stable Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.8' + + - name: Install Cython + run: | + python -m pip install --upgrade pip wheel + pip install Cython==0.29.* + + - name: Build + run: | + cargo +stable build --verbose + + - name: Build no-default-features + run: | + cargo +stable build --verbose --no-default-features + + - name: Test package + env: + CBINDGEN_TEST_VERIFY: 1 + run: | + cargo +stable package --verbose + (cd target/package/cbindgen-$(cargo +stable run -- --version | cut -d ' ' -f 2) && cargo +stable test --verbose) + + - name: Install nightly Rust + uses: dtolnay/rust-toolchain@nightly + + - name: Test + env: + CBINDGEN_TEST_VERIFY: 1 + run: | + cargo +nightly test --verbose + + - name: Test minimal-versions + run: | + cargo +nightly update -Zminimal-versions + cargo +nightly test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.github/workflows/deploy.yml clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/deploy.yml --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/.github/workflows/deploy.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/.github/workflows/deploy.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +name: deploy + +on: + push: + tags: + - 'v*.*.*' + +jobs: + + linux-binaries: + permissions: + # Grant the GITHUB_TOKEN additional permissions necessary for creating a release. + # We only run this action for tags, so any code has already been reviewed by + # someone with permissions to create a tag. + contents: write + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v3 + + - name: Install stable + uses: dtolnay/rust-toolchain@stable + + - name: semver + run: | + cargo +stable install cargo-semver-checks --locked + cargo semver-checks check-release + + - name: Build cbindgen + run: | + cargo +stable build --release + + - name: Strip cbindgen + run: | + strip target/release/cbindgen + + - name: Handle release data and files + id: tagName + run: | + VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) + echo "::set-output name=version::$VERSION" + # Steps to extract the last release notes from CHANGES: + # 1. Remove the first three lines + # 2. Stop at the next heading level + # 3. Remove the last line + # 4. Deindent the bullet points to avoid a markdown code block + tail -n +3 CHANGES | sed '/^##/q' | + sed '$ d' | awk '{$1=$1};1' > CHANGES.txt + + - name: Create a release + run: | + TAG=${{ steps.tagName.outputs.version }} + gh release create ${TAG} --title "${TAG}" --notes-file "CHANGES.txt" --draft 'target/release/cbindgen#cbindgen-ubuntu20.04' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/cbindgen/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cbindgen/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +[package] +name = "cbindgen" +version = "0.25.0" +authors = [ + "Emilio Cobos Álvarez ", + "Jeff Muizelaar ", + "Kartikaya Gupta ", + "Ryan Hunt " +] +license = "MPL-2.0" +description = "A tool for generating C bindings to Rust code." +keywords = ["bindings", "ffi", "code-generation"] +categories = ["external-ffi-bindings", "development-tools::ffi"] +repository = "https://github.com/eqrion/cbindgen" +edition = "2018" +rust-version = "1.64" +exclude = [ + "tests/profile.rs", # Test relies in a sub-crate, see https://github.com/rust-lang/cargo/issues/9017 +] + +[dependencies] +clap = { version = "3.1", optional = true } +indexmap = "1" +log = "0.4" +serde = { version = "1.0.103", default-features = false, features = ["derive"] } +serde_json = "1.0" +tempfile = "3" +toml = "0.5" +proc-macro2 = "1.0.60" +quote = "1" +heck = "0.4" + +[dependencies.syn] +version = "1.0.88" +default-features = false +features = ["clone-impls", "extra-traits", "full", "parsing", "printing"] + +[dev-dependencies] +serial_test = "0.5.0" + +[features] +default = ["clap"] + +[[bin]] +name = "cbindgen" +path = "src/main.rs" +doc = false +required-features = ["clap"] + +[lib] +name = "cbindgen" +path = "src/lib.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/cc/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"0b6441ff8659e7a6784411cacb180eb9f1d7281c3f34643bc8288db47d2b08b3","Cargo.toml":"5c15212a19ab7432d834b92cc7f6af9461c860fbaf2a756cda9b6f40d7b0e845","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f1ddbede208a5b78333a25dac0a7598e678e9b601a7d99a791069bddaf180dfe","src/command_helpers.rs":"15afbc35930a5a53f00d74a8910cff35caeb5511c26642cffe5630377aced901","src/detect_compiler_family.c":"72903b91d7a28f49b39e7d730f4c9c4bb39fb901948fa1279cd08abf392f5a29","src/lib.rs":"d805931c886be881ed685c3f75b104e96068c4a7e51f48c9a304b3fdebcfdcda","src/parallel/async_executor.rs":"4ce24435fff6b6555b43fee042c16bd65d4150d0346567f246b9190d85b45983","src/parallel/job_token.rs":"352a0295c965c684904329d334f3b9889db3a9c3f201701f8db44e4d00e00515","src/parallel/mod.rs":"bd9c1334d17d138c281961c690b8d8118a2d6295a7d6cd7296826255436fa063","src/parallel/stderr.rs":"a2d18ba3f2e04deb9047ece9ab7ca5452d9a76b515afbe20a76307e31597f34b","src/target_info.rs":"342be00f6215e161d8163e272a2945bb9f52f171648e15e11d46800a73186955","src/tempfile.rs":"47a58e904ac07da6682004b5b615dc83250b253a8d3e8ba1b9bcaf6cdf4fd142","src/tool.rs":"b48a7a0efbeb24dc4ccdb4326583ef074e69c670330681a5be9d5c19492e5f96","src/windows/com.rs":"be1564756c9f3ef1398eafeed7b54ba610caba28e8f6258d28a997737ebf9535","src/windows/find_tools.rs":"06aaf9d6247f407cb6077c68d0c9469f64a098eda2222059e7400588e7e05f6a","src/windows/mod.rs":"42f1ad7fee35a17686b003e6aa520d3d1940d47d2f531d626e9ae0c48ba49005","src/windows/registry.rs":"c521b72c825e8095843e73482ffa810ed066ad8bb9f86e6db0c5c143c171aba1","src/windows/setup_config.rs":"754439cbab492afd44c9755abcbec1a41c9b2c358131cee2df13c0e996dbbec8","src/windows/vs_instances.rs":"76e3cee74b5fd38ddaf533bba11fe401667c50dda5f9d064099840893eaa7587","src/windows/winapi.rs":"250d51c1826d1a2329e9889dd9f058cfce253dbf2a678b076147c6cdb5db046c","src/windows/windows_sys.rs":"5a440eb39d8a0c176b66177e8753186797793bc5d7896292c408fb44c12dfed3"},"package":"099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"fbf36888a5d2453eb1f96be1cf826e9e70c0e84fbf14c85dd954e367f3cf8e28","Cargo.lock":"0b6441ff8659e7a6784411cacb180eb9f1d7281c3f34643bc8288db47d2b08b3","Cargo.toml":"5c15212a19ab7432d834b92cc7f6af9461c860fbaf2a756cda9b6f40d7b0e845","Cargo.toml.orig":"e900e320993e006e8c07276bf7b433c156e41c498b54a2d28a29dc48201ab88c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f1ddbede208a5b78333a25dac0a7598e678e9b601a7d99a791069bddaf180dfe","src/command_helpers.rs":"15afbc35930a5a53f00d74a8910cff35caeb5511c26642cffe5630377aced901","src/detect_compiler_family.c":"72903b91d7a28f49b39e7d730f4c9c4bb39fb901948fa1279cd08abf392f5a29","src/lib.rs":"d805931c886be881ed685c3f75b104e96068c4a7e51f48c9a304b3fdebcfdcda","src/parallel/async_executor.rs":"4ce24435fff6b6555b43fee042c16bd65d4150d0346567f246b9190d85b45983","src/parallel/job_token.rs":"352a0295c965c684904329d334f3b9889db3a9c3f201701f8db44e4d00e00515","src/parallel/mod.rs":"bd9c1334d17d138c281961c690b8d8118a2d6295a7d6cd7296826255436fa063","src/parallel/stderr.rs":"a2d18ba3f2e04deb9047ece9ab7ca5452d9a76b515afbe20a76307e31597f34b","src/target_info.rs":"342be00f6215e161d8163e272a2945bb9f52f171648e15e11d46800a73186955","src/tempfile.rs":"47a58e904ac07da6682004b5b615dc83250b253a8d3e8ba1b9bcaf6cdf4fd142","src/tool.rs":"b48a7a0efbeb24dc4ccdb4326583ef074e69c670330681a5be9d5c19492e5f96","src/windows/com.rs":"be1564756c9f3ef1398eafeed7b54ba610caba28e8f6258d28a997737ebf9535","src/windows/find_tools.rs":"06aaf9d6247f407cb6077c68d0c9469f64a098eda2222059e7400588e7e05f6a","src/windows/mod.rs":"42f1ad7fee35a17686b003e6aa520d3d1940d47d2f531d626e9ae0c48ba49005","src/windows/registry.rs":"c521b72c825e8095843e73482ffa810ed066ad8bb9f86e6db0c5c143c171aba1","src/windows/setup_config.rs":"754439cbab492afd44c9755abcbec1a41c9b2c358131cee2df13c0e996dbbec8","src/windows/vs_instances.rs":"76e3cee74b5fd38ddaf533bba11fe401667c50dda5f9d064099840893eaa7587","src/windows/winapi.rs":"250d51c1826d1a2329e9889dd9f058cfce253dbf2a678b076147c6cdb5db046c","src/windows/windows_sys.rs":"5a440eb39d8a0c176b66177e8753186797793bc5d7896292c408fb44c12dfed3"},"package":"099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/cc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9866310fa3d285b01bbe501f0a1f4f9354d2fbb4" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/cc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/cc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cc/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +[package] +name = "cc" +version = "1.0.97" +authors = ["Alex Crichton "] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/cc-rs" +homepage = "https://github.com/rust-lang/cc-rs" +documentation = "https://docs.rs/cc" +description = """ +A build-time dependency for Cargo build scripts to assist in invoking the native +C compiler to compile native C code into a static archive to be linked into Rust +code. +""" +keywords = ["build-dependencies"] +readme = "README.md" +categories = ["development-tools::build-utils"] +# The binary target is only used by tests. +exclude = ["/.github", "tests", "src/bin"] +edition = "2018" +rust-version = "1.63" + +[dependencies] +jobserver = { version = "0.1.30", default-features = false, optional = true } +once_cell = { version = "1.19", optional = true } + +[target.'cfg(unix)'.dependencies] +# Don't turn on the feature "std" for this, see https://github.com/rust-lang/cargo/issues/4866 +# which is still an issue with `resolver = "1"`. +libc = { version = "0.2.62", default-features = false, optional = true } + +[features] +parallel = ["libc", "jobserver", "once_cell"] + +[dev-dependencies] +tempfile = "3" + +[workspace] +members = [ + "dev-tools/cc-test", + "dev-tools/gen-target-info", + "dev-tools/gen-windows-sys-binding", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"3300e6f2f5fc184c613a78251df3d1333530c9b54193e137b75c88f6db5a6fa6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","rustfmt.toml":"d8e7f616455a670ba75e3e94bf6f88f4c168c481664d12501820c7dfff5c3cc2","src/expr.rs":"dad9327dac3af9d2f5818937aac91000e02d835dc600da6185c06e9e12047b1e","src/lib.rs":"ff218b9b734ab2eaef813a6ee3a907cb5cd71d483dfaa28d44926824a5b6d804","src/literal.rs":"6fdefc0357b8a14444df21b05c90556861dc0466e63a57669786f3ef3a3dc1c3","src/token.rs":"cd1ba6315b0137de9a0711670dd1840ac76c41f3b88dcd1a93ad77e1800c703f","tests/clang.rs":"5bb9807f35f760065d15cb9dfb7d8b79c2f734aef7ba5fe3737154155ed8ee73","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"7b8023ba468ec76b184912692bc40e8fbcdd92ad86ec5a7c0dbcb02f2b8d961d","tests/input/strings.h":"2dd11bc066f34e8cb1916a28353e9e9a3a21cd406651b2f94fc47e89c95d9cba","tests/input/test_llvm_bug_9069.h":"8d9ae1d1eadc8f6d5c14296f984547fe894d0f2ce5cd6d7aa8caad40a56bc5e1"},"package":"6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f5fa050aba66bc280e9163f1c2e309f87dfb3a0dc4a511b1379d767dc42bf4d1",".github/workflows/ci.yml":"ed1d33f83f25e920c5ecaec59f51fd9209fcf1da912cbff4e5a6d7da6b737922","Cargo.toml":"3300e6f2f5fc184c613a78251df3d1333530c9b54193e137b75c88f6db5a6fa6","Cargo.toml.orig":"cb6c93b8f4c1b681296427608ca2e7c6772ba3a6b824df6d968ed027afb1d851","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","rustfmt.toml":"d8e7f616455a670ba75e3e94bf6f88f4c168c481664d12501820c7dfff5c3cc2","src/expr.rs":"dad9327dac3af9d2f5818937aac91000e02d835dc600da6185c06e9e12047b1e","src/lib.rs":"ff218b9b734ab2eaef813a6ee3a907cb5cd71d483dfaa28d44926824a5b6d804","src/literal.rs":"6fdefc0357b8a14444df21b05c90556861dc0466e63a57669786f3ef3a3dc1c3","src/token.rs":"cd1ba6315b0137de9a0711670dd1840ac76c41f3b88dcd1a93ad77e1800c703f","tests/clang.rs":"5bb9807f35f760065d15cb9dfb7d8b79c2f734aef7ba5fe3737154155ed8ee73","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"7b8023ba468ec76b184912692bc40e8fbcdd92ad86ec5a7c0dbcb02f2b8d961d","tests/input/strings.h":"2dd11bc066f34e8cb1916a28353e9e9a3a21cd406651b2f94fc47e89c95d9cba","tests/input/test_llvm_bug_9069.h":"8d9ae1d1eadc8f6d5c14296f984547fe894d0f2ce5cd6d7aa8caad40a56bc5e1"},"package":"6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "c7ccdfbc37b508cfda1171ab4f89afaeb72e82f3" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/cexpr/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cexpr/.github/workflows/ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,31 @@ +name: CI +on: + push: + branches: + - master + pull_request: + branches: + - master + + +jobs: + build_and_test: + name: Build and Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "11.0" + directory: ${{ runner.temp }}/llvm-11.0 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - uses: actions-rs/cargo@v1 + with: + command: test + args: --verbose --all diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cexpr/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/cexpr/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/cexpr/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cexpr/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "cexpr" +version = "0.6.0" +edition = "2018" +authors = ["Jethro Beekman "] +license = "Apache-2.0/MIT" +description = "A C expression parser and evaluator" +documentation = "https://docs.rs/cexpr/" +repository = "https://github.com/jethrogb/rust-cexpr" +keywords = ["C","expression","parser"] + +[badges] +travis-ci = { repository = "jethrogb/rust-cexpr" } + +[dependencies] +nom = { version = "7", default-features = false, features = ["std"] } + +[dev-dependencies] +clang-sys = ">= 0.13.0, < 0.29.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"5b2a8f6e5256957c029cf3a8912d51438e7faa5891c5c102c312f6d4599c1f00","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"2406e83ee174e30aa67f8ab266836fa78545012b196395aff37c152321e2c713","src/lib.rs":"54b0f108b0dc48a077c52c0bcd22b64ef4de083e5e2b7d405e50ae4d78224f1b","tests/xcrate.rs":"c0734dae6e63beafcd60bf53546115a2320735b51035c9e2387fdf9301580934"},"package":"baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"adc7a2b67bc53600a229c2892d592977aa4939434fb93f53b2e98799173a675c",".github/workflows/main.yml":"27a418e9130e6462907cf246c5b71c9d51bc684873219c561011928dd829d445","Cargo.toml":"5b2a8f6e5256957c029cf3a8912d51438e7faa5891c5c102c312f6d4599c1f00","Cargo.toml.orig":"90923641c7cd59e9f3df14ab37d39523d4a6e59cf02d7a6aae79abcaca07e3b9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"2406e83ee174e30aa67f8ab266836fa78545012b196395aff37c152321e2c713","src/lib.rs":"54b0f108b0dc48a077c52c0bcd22b64ef4de083e5e2b7d405e50ae4d78224f1b","tests/xcrate.rs":"c0734dae6e63beafcd60bf53546115a2320735b51035c9e2387fdf9301580934"},"package":"baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "e60fa1efeab0ec6e90c50d93ec526e1410459c23" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/.github/workflows/main.yml 2020-10-06 18:43:06.000000000 +0000 @@ -0,0 +1,56 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable, beta, nightly] + steps: + - uses: actions/checkout@master + - name: Install Rust Stable + run: | + rustup self update + rustup update ${{ matrix.rust }} + rustup default ${{ matrix.rust }} + rustc -vV + - name: Run tests + run: cargo test + + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust Stable + run: | + rustup update stable + rustup default stable + rustup component add rustfmt + - name: Run rustfmt + run: cargo fmt -- --check + + publish_docs: + name: Publish Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust Stable + run: | + rustup update stable + rustup default stable + - name: Build documentation + run: cargo doc --no-deps + - name: Publish documentation + run: | + cd target/doc + git init + git remote add origin https://x-access-token:${{ secrets.github_token }}@github.com/${{ github.repository }} + git fetch origin + git reset --hard "origin/gh-pages^" -- + git add . + git -c user.name='ci' -c user.email='ci' commit -m init + git push -f -q origin HEAD:gh-pages + if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/cfg-if/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cfg-if/Cargo.toml.orig 2020-10-06 18:43:25.000000000 +0000 @@ -0,0 +1,25 @@ +[package] +name = "cfg-if" +version = "1.0.0" +authors = ["Alex Crichton "] +license = "MIT/Apache-2.0" +readme = "README.md" +repository = "https://github.com/alexcrichton/cfg-if" +homepage = "https://github.com/alexcrichton/cfg-if" +documentation = "https://docs.rs/cfg-if" +description = """ +A macro to ergonomically define an item depending on a large number of #[cfg] +parameters. Structured like an if-else chain, the first matching branch is the +item that gets emitted. +""" +edition = "2018" + +[badges] +travis-ci = { repository = "alexcrichton/cfg-if" } + +[dependencies] +core = { version = "1.0.0", optional = true, package = 'rustc-std-workspace-core' } +compiler_builtins = { version = '0.1.2', optional = true } + +[features] +rustc-dep-of-std = ['core', 'compiler_builtins'] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/chrono/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/chrono/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CITATION.cff":"e64b28c9c9202b791045a241c45f001695b017a2d5ce5a2aa8877e0b1cd14196","Cargo.toml":"07e2702b3c79570e297d8bf2a2d9f332e99cd98ab9036a279bf7403be133135b","LICENSE.txt":"46610329ff0b38effb9cb05979ff1ef761e465fed96b2eaca39e439d00129fd7","src/date.rs":"10f03590ccab03c3efc076ef55bf218f1e93fdd5f85e4440f46b7590373619b1","src/datetime/mod.rs":"8e9a40d33c29ca94d01a7d473be97df71c304c435dc367931f0cd5a3a7090c60","src/datetime/serde.rs":"0a4c17c9549f3c55ad44e109812c20d9223d22110e4c476af41f24bb75fd9edf","src/datetime/tests.rs":"396c4fccb3b6f20eacfb44629f84dff048327689920d7fb702f8620bf62ccaef","src/format/formatting.rs":"0aec20482093fc3511dcd6d16f481de0edba433dc716e8fb9bdab7fd1dd538c3","src/format/locales.rs":"c35aef701aa077e1b056c9eb7a561241a178207d2f6f748e1b00ee2afcfd8740","src/format/mod.rs":"3ae0b0bcebd503090585746a010b49039850201fec34f8bff9d42fbf7b30e570","src/format/parse.rs":"0b057428e5000b55cf78b6ea26deb48fc4aab96271c9c3878894481a4f88f5f6","src/format/parsed.rs":"8f708e8eb1ef6d2b726fbea7dafb949de32c3604f850757b1d376fa49c85bf39","src/format/scan.rs":"be6c765c1916e601eb6274302c619e394aa52d54c5441f26d2fbd9fbf2a08a0a","src/format/strftime.rs":"6773256fcfe83de3d2445f3fe758b9def6c64900b9fddbda0bc60d9e857c6028","src/lib.rs":"ec723fe8444bcf92c93232fe9b20fbb41cc319879a6bbacde438bfee4f06d0d7","src/month.rs":"7f538afb7e317388b4abb6248a75b2979eaf3e7672becb2b8fc4debcbf10810f","src/naive/date/mod.rs":"c84f1253184b9945d008cf6177f4d825e287e3240136c8af9ec190780411339b","src/naive/date/tests.rs":"fceb4b6ce5de7b402ab9de0876a760487e5904329e24493737645489fc875df4","src/naive/datetime/mod.rs":"aead7ff43214156fbdd9fb6b129318f7edf997a76f109cc4cefd4779855e6494","src/naive/datetime/serde.rs":"383ad8fc47fbc80d2cb605659a476d6ae16fbd9095c9b6851321fe61a42a3d83","src/naive/datetime/tests.rs":"26c0c64db8f4aa2d0f06fcc26458e2d66978af40fc827be8bc2bb7f61d6278fe","src/naive/internals.rs":"7b9fc479602a085a31f81c197f0f4f07be035237555e64b9574edf32ad771678","src/naive/isoweek.rs":"3f586d8de01f2d324ab1dcf94cf50cbfe5071ce71c4849b0e936524d29869776","src/naive/mod.rs":"4fe2fed98d9f253b930bc335ae167dbe34687a0c54311f3aa4c7014fcf930456","src/naive/time/mod.rs":"f17fd2d76de3b44c6eb12a413fe20b44e5bdfdc9b2d10cc4153aac5b03914dbe","src/naive/time/serde.rs":"eee49254c4f76655a620dbdee6a9e99597784561c4e763484a93a9d766aa1274","src/naive/time/tests.rs":"70143375785969ed348fcc1ceab50b670d239209191b938823dd7b25a97ced40","src/offset/fixed.rs":"7a8e7bbe33a67b0dc7614fa2eb7f79a0396360dcaf9967a9f9e5bddb82b7b421","src/offset/local/mod.rs":"6222d8e2fdcd8a97ce64a4eec531288f5739d07066bd1795c872d7e449eb3647","src/offset/local/tz_info/mod.rs":"c8096637c04687ea396e444c25fdf0008e2b9975ab3c173a41dd63ac213c7877","src/offset/local/tz_info/parser.rs":"4e2f34a6e760833392bc7da038721fb5e266eebb8e4b327a8140e2d8504de4ec","src/offset/local/tz_info/rule.rs":"214b7d146ac02fad0ad598f180af7d27c962d74b2c3f43c261a7bb6d95eeeb43","src/offset/local/tz_info/timezone.rs":"c25c0cfda1dcb4847639bf5b2469fd38e0f01f2cb230b05d6e5e9c5b6082f5db","src/offset/local/unix.rs":"01bd00821db763098e7730dd54e9c951aad112bba75aa01a9f8efb9397310d36","src/offset/local/win_bindings.rs":"01c65d6dd603f2b937641cbf80c03cd0c2a2378d3a9c90202f463876f545d20a","src/offset/local/win_bindings.txt":"3bbbcb90060f20414a9cb2396bfb1d0efc9608dbeabdb08637fe99ea25f473fd","src/offset/local/windows.rs":"4d8a15958c4ac1a8cc238016065e27377dbbebc1702d6d7da87f93bb278b6f7a","src/offset/mod.rs":"c97d570dcbcebcd508be332359f581a2799099b503eab10aebf5350cc1fc1eec","src/offset/utc.rs":"4b5449427cebf609cb5bbcc07ae70faeb3eab4f742d5a6a521e9118227d6eb2d","src/round.rs":"b1e0a0a2b34ffa354139152e6710a23586f93cfae89c8738b517b943ec6e38ab","src/time_delta.rs":"0806728d0b31209474c1bcae3d1feb8c542cebd88f5de945850bb47d39f47977","src/traits.rs":"1f295008518b45534697049d5ba491100a9cd6e615034d5b3eb068eb1d46bdfb","src/weekday.rs":"035dbe51b0a707d949b4335939026d15507dcd529b6498d5853c815e45e78672","tests/dateutils.rs":"66617fa13727a60fac86a61bed4f0510e0b622a95f052307105ec7d6520c5acb","tests/wasm.rs":"252f16aeeaacbf26ca268b9a5e53aee3560cd1f071142a7a16d1509a02758a17","tests/win_bindings.rs":"b23c8d95c724ecf55879229cb20db6bf85d8f76a87221d1e67cb07bb71d29836"},"package":"a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"55ae9e1241c02132d053fef6b207694e68a3093b769612c9082815734bec9ba7","CITATION.cff":"e64b28c9c9202b791045a241c45f001695b017a2d5ce5a2aa8877e0b1cd14196","Cargo.toml":"07e2702b3c79570e297d8bf2a2d9f332e99cd98ab9036a279bf7403be133135b","Cargo.toml.orig":"6db09283886c69d1927ec4e62418c3df46df3692b63ba08ab6d4def5ffe6e85b","LICENSE.txt":"46610329ff0b38effb9cb05979ff1ef761e465fed96b2eaca39e439d00129fd7","README.md":"753bad996509fbc16b2e2e6c42315fc0e96366990807fd15d6d647067b7fa3ab","src/date.rs":"10f03590ccab03c3efc076ef55bf218f1e93fdd5f85e4440f46b7590373619b1","src/datetime/mod.rs":"8e9a40d33c29ca94d01a7d473be97df71c304c435dc367931f0cd5a3a7090c60","src/datetime/serde.rs":"0a4c17c9549f3c55ad44e109812c20d9223d22110e4c476af41f24bb75fd9edf","src/datetime/tests.rs":"396c4fccb3b6f20eacfb44629f84dff048327689920d7fb702f8620bf62ccaef","src/format/formatting.rs":"0aec20482093fc3511dcd6d16f481de0edba433dc716e8fb9bdab7fd1dd538c3","src/format/locales.rs":"c35aef701aa077e1b056c9eb7a561241a178207d2f6f748e1b00ee2afcfd8740","src/format/mod.rs":"3ae0b0bcebd503090585746a010b49039850201fec34f8bff9d42fbf7b30e570","src/format/parse.rs":"0b057428e5000b55cf78b6ea26deb48fc4aab96271c9c3878894481a4f88f5f6","src/format/parsed.rs":"8f708e8eb1ef6d2b726fbea7dafb949de32c3604f850757b1d376fa49c85bf39","src/format/scan.rs":"be6c765c1916e601eb6274302c619e394aa52d54c5441f26d2fbd9fbf2a08a0a","src/format/strftime.rs":"6773256fcfe83de3d2445f3fe758b9def6c64900b9fddbda0bc60d9e857c6028","src/lib.rs":"ec723fe8444bcf92c93232fe9b20fbb41cc319879a6bbacde438bfee4f06d0d7","src/month.rs":"7f538afb7e317388b4abb6248a75b2979eaf3e7672becb2b8fc4debcbf10810f","src/naive/date/mod.rs":"c84f1253184b9945d008cf6177f4d825e287e3240136c8af9ec190780411339b","src/naive/date/tests.rs":"fceb4b6ce5de7b402ab9de0876a760487e5904329e24493737645489fc875df4","src/naive/datetime/mod.rs":"aead7ff43214156fbdd9fb6b129318f7edf997a76f109cc4cefd4779855e6494","src/naive/datetime/serde.rs":"383ad8fc47fbc80d2cb605659a476d6ae16fbd9095c9b6851321fe61a42a3d83","src/naive/datetime/tests.rs":"26c0c64db8f4aa2d0f06fcc26458e2d66978af40fc827be8bc2bb7f61d6278fe","src/naive/internals.rs":"7b9fc479602a085a31f81c197f0f4f07be035237555e64b9574edf32ad771678","src/naive/isoweek.rs":"3f586d8de01f2d324ab1dcf94cf50cbfe5071ce71c4849b0e936524d29869776","src/naive/mod.rs":"4fe2fed98d9f253b930bc335ae167dbe34687a0c54311f3aa4c7014fcf930456","src/naive/time/mod.rs":"f17fd2d76de3b44c6eb12a413fe20b44e5bdfdc9b2d10cc4153aac5b03914dbe","src/naive/time/serde.rs":"eee49254c4f76655a620dbdee6a9e99597784561c4e763484a93a9d766aa1274","src/naive/time/tests.rs":"70143375785969ed348fcc1ceab50b670d239209191b938823dd7b25a97ced40","src/offset/fixed.rs":"7a8e7bbe33a67b0dc7614fa2eb7f79a0396360dcaf9967a9f9e5bddb82b7b421","src/offset/local/mod.rs":"6222d8e2fdcd8a97ce64a4eec531288f5739d07066bd1795c872d7e449eb3647","src/offset/local/tz_info/mod.rs":"c8096637c04687ea396e444c25fdf0008e2b9975ab3c173a41dd63ac213c7877","src/offset/local/tz_info/parser.rs":"4e2f34a6e760833392bc7da038721fb5e266eebb8e4b327a8140e2d8504de4ec","src/offset/local/tz_info/rule.rs":"214b7d146ac02fad0ad598f180af7d27c962d74b2c3f43c261a7bb6d95eeeb43","src/offset/local/tz_info/timezone.rs":"c25c0cfda1dcb4847639bf5b2469fd38e0f01f2cb230b05d6e5e9c5b6082f5db","src/offset/local/unix.rs":"01bd00821db763098e7730dd54e9c951aad112bba75aa01a9f8efb9397310d36","src/offset/local/win_bindings.rs":"01c65d6dd603f2b937641cbf80c03cd0c2a2378d3a9c90202f463876f545d20a","src/offset/local/win_bindings.txt":"3bbbcb90060f20414a9cb2396bfb1d0efc9608dbeabdb08637fe99ea25f473fd","src/offset/local/windows.rs":"4d8a15958c4ac1a8cc238016065e27377dbbebc1702d6d7da87f93bb278b6f7a","src/offset/mod.rs":"c97d570dcbcebcd508be332359f581a2799099b503eab10aebf5350cc1fc1eec","src/offset/utc.rs":"4b5449427cebf609cb5bbcc07ae70faeb3eab4f742d5a6a521e9118227d6eb2d","src/round.rs":"b1e0a0a2b34ffa354139152e6710a23586f93cfae89c8738b517b943ec6e38ab","src/time_delta.rs":"0806728d0b31209474c1bcae3d1feb8c542cebd88f5de945850bb47d39f47977","src/traits.rs":"1f295008518b45534697049d5ba491100a9cd6e615034d5b3eb068eb1d46bdfb","src/weekday.rs":"035dbe51b0a707d949b4335939026d15507dcd529b6498d5853c815e45e78672","tests/dateutils.rs":"66617fa13727a60fac86a61bed4f0510e0b622a95f052307105ec7d6520c5acb","tests/wasm.rs":"252f16aeeaacbf26ca268b9a5e53aee3560cd1f071142a7a16d1509a02758a17","tests/win_bindings.rs":"b23c8d95c724ecf55879229cb20db6bf85d8f76a87221d1e67cb07bb71d29836"},"package":"a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/chrono/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/chrono/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/chrono/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "352a35203a140e2352e5a5be62ba8dfd03b616e1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/chrono/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/chrono/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/chrono/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/chrono/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,76 @@ +[package] +name = "chrono" +version = "0.4.38" +description = "Date and time library for Rust" +homepage = "https://github.com/chronotope/chrono" +documentation = "https://docs.rs/chrono/" +repository = "https://github.com/chronotope/chrono" +keywords = ["date", "time", "calendar"] +categories = ["date-and-time"] +readme = "README.md" +license = "MIT OR Apache-2.0" +include = ["src/*", "tests/*.rs", "LICENSE.txt", "CITATION.cff"] +edition = "2021" +rust-version = "1.61.0" + +[lib] +name = "chrono" + +[features] +# Don't forget to adjust `ALL_NON_EXCLUSIVE_FEATURES` in CI scripts when adding a feature or an optional dependency. +default = ["clock", "std", "oldtime", "wasmbind"] +alloc = [] +libc = [] +winapi = ["windows-targets"] +std = ["alloc"] +clock = ["winapi", "iana-time-zone", "android-tzdata", "now"] +now = ["std"] +oldtime = [] +wasmbind = ["wasm-bindgen", "js-sys"] +unstable-locales = ["pure-rust-locales"] +# Note that rkyv-16, rkyv-32, and rkyv-64 are mutually exclusive. +rkyv = ["dep:rkyv", "rkyv/size_32"] +rkyv-16 = ["dep:rkyv", "rkyv?/size_16"] +rkyv-32 = ["dep:rkyv", "rkyv?/size_32"] +rkyv-64 = ["dep:rkyv", "rkyv?/size_64"] +rkyv-validation = ["rkyv?/validation"] +# Features for internal use only: +__internal_bench = [] + +[dependencies] +num-traits = { version = "0.2", default-features = false } +serde = { version = "1.0.99", default-features = false, optional = true } +pure-rust-locales = { version = "0.8", optional = true } +rkyv = { version = "0.7.43", optional = true, default-features = false } +arbitrary = { version = "1.0.0", features = ["derive"], optional = true } + +[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] +wasm-bindgen = { version = "0.2", optional = true } +js-sys = { version = "0.3", optional = true } # contains FFI bindings for the JS Date API + +[target.'cfg(windows)'.dependencies] +windows-targets = { version = "0.52", optional = true } + +[target.'cfg(windows)'.dev-dependencies] +windows-bindgen = { version = "0.56" } # The MSRV of its windows-metatada dependency is 1.70 + +[target.'cfg(unix)'.dependencies] +iana-time-zone = { version = "0.1.45", optional = true, features = ["fallback"] } + +[target.'cfg(target_os = "android")'.dependencies] +android-tzdata = { version = "0.1.1", optional = true } + +[dev-dependencies] +serde_json = { version = "1" } +serde_derive = { version = "1", default-features = false } +bincode = { version = "1.3.0" } + +[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dev-dependencies] +wasm-bindgen-test = "0.3" + +[package.metadata.docs.rs] +features = ["arbitrary", "rkyv", "serde", "unstable-locales"] +rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.playground] +features = ["serde"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/chrono/README.md clamav-1.4.6+dfsg/.cargo/vendor/chrono/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/chrono/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/chrono/README.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,92 @@ +[Chrono][docsrs]: Timezone-aware date and time handling +======================================== + +[![Chrono GitHub Actions][gh-image]][gh-checks] +[![Chrono on crates.io][cratesio-image]][cratesio] +[![Chrono on docs.rs][docsrs-image]][docsrs] +[![Chat][discord-image]][discord] +[![codecov.io][codecov-img]][codecov-link] + +[gh-image]: https://github.com/chronotope/chrono/actions/workflows/test.yml/badge.svg?branch=main +[gh-checks]: https://github.com/chronotope/chrono/actions/workflows/test.yml?query=branch%3Amain +[cratesio-image]: https://img.shields.io/crates/v/chrono.svg +[cratesio]: https://crates.io/crates/chrono +[docsrs-image]: https://docs.rs/chrono/badge.svg +[docsrs]: https://docs.rs/chrono +[discord-image]: https://img.shields.io/discord/976380008299917365?logo=discord +[discord]: https://discord.gg/sXpav4PS7M +[codecov-img]: https://img.shields.io/codecov/c/github/chronotope/chrono?logo=codecov +[codecov-link]: https://codecov.io/gh/chronotope/chrono + +Chrono aims to provide all functionality needed to do correct operations on dates and times in the +[proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar): + +* The [`DateTime`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) type is timezone-aware + by default, with separate timezone-naive types. +* Operations that may produce an invalid or ambiguous date and time return `Option` or + [`MappedLocalTime`](https://docs.rs/chrono/latest/chrono/offset/enum.MappedLocalTime.html). +* Configurable parsing and formatting with an `strftime` inspired date and time formatting syntax. +* The [`Local`](https://docs.rs/chrono/latest/chrono/offset/struct.Local.html) timezone works with + the current timezone of the OS. +* Types and operations are implemented to be reasonably efficient. + +Timezone data is not shipped with chrono by default to limit binary sizes. Use the companion crate +[Chrono-TZ](https://crates.io/crates/chrono-tz) or [`tzfile`](https://crates.io/crates/tzfile) for +full timezone support. + +## Documentation + +See [docs.rs](https://docs.rs/chrono/latest/chrono/) for the API reference. + +## Limitations + +* Only the proleptic Gregorian calendar (i.e. extended to support older dates) is supported. +* Date types are limited to about +/- 262,000 years from the common epoch. +* Time types are limited to nanosecond accuracy. +* Leap seconds can be represented, but Chrono does not fully support them. + See [Leap Second Handling](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html#leap-second-handling). + +## Crate features + +Default features: + +* `alloc`: Enable features that depend on allocation (primarily string formatting). +* `std`: Enables functionality that depends on the standard library. This is a superset of `alloc` + and adds interoperation with standard library types and traits. +* `clock`: Enables reading the local timezone (`Local`). This is a superset of `now`. +* `now`: Enables reading the system time (`now`). +* `wasmbind`: Interface with the JS Date API for the `wasm32` target. + +Optional features: + +* `serde`: Enable serialization/deserialization via [serde]. +* `rkyv`: Deprecated, use the `rkyv-*` features. +* `rkyv-16`: Enable serialization/deserialization via [rkyv], using 16-bit integers for integral `*size` types. +* `rkyv-32`: Enable serialization/deserialization via [rkyv], using 32-bit integers for integral `*size` types. +* `rkyv-64`: Enable serialization/deserialization via [rkyv], using 64-bit integers for integral `*size` types. +* `rkyv-validation`: Enable rkyv validation support using `bytecheck`. +* `arbitrary`: Construct arbitrary instances of a type with the Arbitrary crate. +* `unstable-locales`: Enable localization. This adds various methods with a `_localized` suffix. + The implementation and API may change or even be removed in a patch release. Feedback welcome. +* `oldtime`: This feature no longer has any effect; it used to offer compatibility with the `time` 0.1 crate. + +Note: The `rkyv{,-16,-32,-64}` features are mutually exclusive. + +[serde]: https://github.com/serde-rs/serde +[rkyv]: https://github.com/rkyv/rkyv + +## Rust version requirements + +The Minimum Supported Rust Version (MSRV) is currently **Rust 1.61.0**. + +The MSRV is explicitly tested in CI. It may be bumped in minor releases, but this is not done +lightly. + +## License + +This project is licensed under either of + +* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +* [MIT License](https://opensource.org/licenses/MIT) + +at your option. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"7a177945b551a62c30b9183f8edaac38216fbeb3fb7f8760e5f2a69916140086","Cargo.toml":"9d896747d0d657eeb8913dc254439b06f77025399c654026db5d58bf655837f6","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"d75bc7b6e957818c2c9c78107eade13c48bd1e9f6a5eca3b04644b21938b0157","build.rs":"f344874bf25f8ec6f852c55edaf262789fc6b883489afb47fa3d7da83f95ad1c","build/common.rs":"0b23893c737a9b60d8d400b5101bf3bcc632e0833d948590c42d189a1f69aeb0","build/dynamic.rs":"79014d1f9c7a197affb018d60218458e8878ccc80e61fc2e5d61b2f291ebbb4b","build/macros.rs":"eac7bffaac5f70728764065145eb1541b0a133c900356a0bcf55f0d89966c84e","build/static.rs":"b3000f872b139b3f3230f49e98a183d05ac18be661192bb5cada896eca853aca","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"3c0fc0c0e3cabc3b81732b5ac784b36f69dfb72abcecc3bf4e5a08c72d9c8ad0","src/link.rs":"13b236714d68483fbcec9df2ee1ae63db21e87176881c2d53a9157a2b38240eb","src/support.rs":"5398f8c35cceae64ca941b9a26ed28f29d34a1301958399d636e599dcfd0d64f","tests/build.rs":"66ed85f6e1baf9fac5c50e486fa43413e40c3f16ce9f503c9bba53e300682a9a","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"a39e48b2ab3347692f461609e296456850cff870514fa3df8232341318015568"},"package":"67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"6b70c3dc854f7ba844ccf7ee5dfe0fbe23ecb0fd115436f39ae81be3febc21a1",".github/workflows/ci.yml":"08aad65ace219eef655543eaec68fcecfb07cc33d78b4f39182a35f1c740ef31",".github/workflows/ssh.yml":"fd321443e7c8a7654a6eaa18e4a76960e660276368bbe3d80f8aab86c1dc1c59","CHANGELOG.md":"7a177945b551a62c30b9183f8edaac38216fbeb3fb7f8760e5f2a69916140086","Cargo.toml":"9d896747d0d657eeb8913dc254439b06f77025399c654026db5d58bf655837f6","Cargo.toml.orig":"3c1ca4aa7254c0235f34810244df85012e6e0b1daee06a2218abf8181ed3bd49","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"d75bc7b6e957818c2c9c78107eade13c48bd1e9f6a5eca3b04644b21938b0157","build.rs":"f344874bf25f8ec6f852c55edaf262789fc6b883489afb47fa3d7da83f95ad1c","build/common.rs":"0b23893c737a9b60d8d400b5101bf3bcc632e0833d948590c42d189a1f69aeb0","build/dynamic.rs":"79014d1f9c7a197affb018d60218458e8878ccc80e61fc2e5d61b2f291ebbb4b","build/macros.rs":"eac7bffaac5f70728764065145eb1541b0a133c900356a0bcf55f0d89966c84e","build/static.rs":"b3000f872b139b3f3230f49e98a183d05ac18be661192bb5cada896eca853aca","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"3c0fc0c0e3cabc3b81732b5ac784b36f69dfb72abcecc3bf4e5a08c72d9c8ad0","src/link.rs":"13b236714d68483fbcec9df2ee1ae63db21e87176881c2d53a9157a2b38240eb","src/support.rs":"5398f8c35cceae64ca941b9a26ed28f29d34a1301958399d636e599dcfd0d64f","tests/build.rs":"66ed85f6e1baf9fac5c50e486fa43413e40c3f16ce9f503c9bba53e300682a9a","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"a39e48b2ab3347692f461609e296456850cff870514fa3df8232341318015568"},"package":"67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "b1854129fa7ae4b6d521feed5eca3eb6816c9342" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + ci: + name: CI + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + clang: [["14.0", "clang_14_0"]] + rust: ["1.51.0"] + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + # LLVM and Clang + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: ${{ matrix.clang[0] }} + directory: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }} + # Rust + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + # Test + - name: Cargo Test (Dynamic) + uses: actions-rs/cargo@v1 + with: + command: test + args: --verbose --features ${{ matrix.clang[1] }} -- --nocapture + - name: Cargo Test (Runtime) + uses: actions-rs/cargo@v1 + with: + command: test + args: --verbose --features "${{ matrix.clang[1] }} runtime" -- --nocapture + - name: Cargo Run (bindgen-test) + uses: actions-rs/cargo@v1 + with: + command: run + args: --manifest-path bindgen-test/Cargo.toml diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.github/workflows/ssh.yml clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ssh.yml --- clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/.github/workflows/ssh.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/.github/workflows/ssh.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +name: SSH + +on: + workflow_dispatch: + inputs: + os: + description: "Operating System" + required: true + default: "ubuntu-latest" + +jobs: + ssh: + name: SSH + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + clang: [["13.0", "clang_13_0"]] + rust: ["1.51.0"] + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + if: github.event.inputs.os == matrix.os + # LLVM and Clang + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + if: github.event.inputs.os == matrix.os + with: + version: ${{ matrix.clang[0] }} + directory: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }} + # Rust + - name: Install Rust + uses: actions-rs/toolchain@v1 + if: github.event.inputs.os == matrix.os + with: + toolchain: ${{ matrix.rust }} + # SSH + - name: Enable SSH + uses: mxschmitt/action-tmate@v3 + if: github.event.inputs.os == matrix.os diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/clang-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/clang-sys/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +[package] + +name = "clang-sys" +authors = ["Kyle Mayes "] + +version = "1.7.0" + +readme = "README.md" +license = "Apache-2.0" + +description = "Rust bindings for libclang." + +documentation = "https://docs.rs/clang-sys" +repository = "https://github.com/KyleMayes/clang-sys" + +links = "clang" +build = "build.rs" + +[features] + +clang_3_5 = [] +clang_3_6 = ["clang_3_5"] +clang_3_7 = ["clang_3_6"] +clang_3_8 = ["clang_3_7"] +clang_3_9 = ["clang_3_8"] +clang_4_0 = ["clang_3_9"] +clang_5_0 = ["clang_4_0"] +clang_6_0 = ["clang_5_0"] +clang_7_0 = ["clang_6_0"] +clang_8_0 = ["clang_7_0"] +clang_9_0 = ["clang_8_0"] +clang_10_0 = ["clang_9_0"] +clang_11_0 = ["clang_10_0"] +clang_12_0 = ["clang_11_0"] +clang_13_0 = ["clang_12_0"] +clang_14_0 = ["clang_13_0"] +clang_15_0 = ["clang_14_0"] +clang_16_0 = ["clang_15_0"] +clang_17_0 = ["clang_16_0"] + +runtime = ["libloading"] +static = [] + +[dependencies] + +glob = "0.3" +libc = { version = "0.2.39", default-features = false } +libloading = { version = "0.8", optional = true } + +[build-dependencies] + +glob = "0.3" + +[dev-dependencies] + +glob = "0.3" +serial_test = "1" +tempfile = "3" + +[package.metadata.docs.rs] + +features = ["clang_17_0", "runtime"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"0647ef6e3629446892fb530dc6f49977a3a81c4d943d0028b697ffa0d98565ad","Cargo.toml":"4ec438714084877d63c79e99191599a3694839c74842f81ca69de836a5889c75","LICENSE":"592dc80f1a865d20d61a2006a2d29ce34a2bc28cd7e868ab300fdeed6da154ca","README.md":"af03438f3b349f8e32ae2cf77c026948bd6493e7631ddd908ee0d225385c7894","src/lib.rs":"17a7ed7a6c994b475976558f3492c8890d089c1ee19f4ea3cd246c28145c895a","src/math.rs":"1fef0855d7d7defb8af69a033a2ce7e5f64367f48ba673cb4ce8e85e2006a124"},"package":"3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e4c6e8ce6d9a7aa2db6ce95040c7d8aec8b2134c80d91c15da9f93b7e257524f",".github/workflows/rust.yml":"43b7308a5519f1c3d5bcdce5789928bf197ba7afcd93683e41aa42520f0704b1","CHANGELOG.md":"0647ef6e3629446892fb530dc6f49977a3a81c4d943d0028b697ffa0d98565ad","Cargo.toml":"4ec438714084877d63c79e99191599a3694839c74842f81ca69de836a5889c75","Cargo.toml.orig":"9ed70895de29435768e4c70392dc0fe715e9aa9c3ba6e3e9cab7e9ef126cd202","LICENSE":"592dc80f1a865d20d61a2006a2d29ce34a2bc28cd7e868ab300fdeed6da154ca","README.md":"af03438f3b349f8e32ae2cf77c026948bd6493e7631ddd908ee0d225385c7894","src/lib.rs":"17a7ed7a6c994b475976558f3492c8890d089c1ee19f4ea3cd246c28145c895a","src/math.rs":"1fef0855d7d7defb8af69a033a2ce7e5f64367f48ba673cb4ce8e85e2006a124"},"package":"3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "6c302d2d1540496584476d513dd75b815f14e7a1" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/color_quant/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/color_quant/.github/workflows/rust.yml 2020-10-09 17:13:54.000000000 +0000 @@ -0,0 +1,38 @@ +name: Rust CI +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: ["1.34.2", stable, beta, nightly] + command: [build, test] + steps: + - uses: actions/checkout@v2 + - run: rustup default ${{ matrix.rust }} + - name: build + run: > + cargo build --verbose + - name: test + if: ${{ matrix.rust != '1.34.2' }} + run: > + cargo test --tests --benches + # TODO: add criterion benchmarks? + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt + - name: Run rustfmt check + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/color_quant/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/color_quant/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/color_quant/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/color_quant/Cargo.toml.orig 2020-10-09 19:01:02.000000000 +0000 @@ -0,0 +1,8 @@ +[package] +name = "color_quant" +license = "MIT" +version = "1.1.0" +authors = ["nwin "] +readme = "README.md" +description = "Color quantization library to reduce n colors to 256 colors." +repository = "https://github.com/image-rs/color_quant.git" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"f8b5e9fa6c6bbfad4e3c0acfbad03f05cbd98073e664e3ad2fe16a56dd492aa1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"4d469ca3f6aceb42dfaf7b26aa9ef14a8ebce05e02d0beda985fa32f2ec48963","src/attributed_string.rs":"7042f3fbf6904efecb15f01ce2e96eecf84973e0fef9be4c10d14944b0f90a24","src/bag.rs":"dec9ff467ac713526c3be8148ae41b21ab8840f393733bb53c77224ef089787c","src/base.rs":"5d0dee358519712e881e2edbea0ca6d3539958ed1ff3d70aa136af7e25292f22","src/binary_heap.rs":"0565125dbdb1fa578888e00f5b195ab91f0bf65881eabcd39de99ca811d756de","src/bit_vector.rs":"dcdaa573d90b25bdc6b98f2330110e8591b7c329601643dcc6aa23b1b9ec7210","src/bundle.rs":"83ac9d7c45f06161767588c465eed086a773714734da0614d98d000326df3603","src/calendar.rs":"b73796956e50d92f0479479e84246712804537d694e4cdd01d5440e5fbcbd333","src/characterset.rs":"ba60f78884cd860e151df35c1953bcd6eae46d9f27c36584b66e508e2301a7a8","src/data.rs":"fe4e2effbfd9348575507d06aa53cd583808c908f9e03ac1a076b077230c9c01","src/date.rs":"971d681f6eeefa3764d8a43e53cbf7c937c419331207c7bb003a25c9b0b0722f","src/date_formatter.rs":"05e84ac3cf4c0daae2e939a9bedddfd10dd5309ea1536bf8241de41971d11f8a","src/dictionary.rs":"ac23d99208131049c82c13b37a99b4fd129224d1dafcd65ff2f9de200d73e9d1","src/error.rs":"b523faa8c498e1115c72e71a10e7a3bf8bcc01588cb02e70dc9fd45cbdaa35f6","src/file_security.rs":"542c5d8eef22424479abcb448601611d85c9cc96e41cd6cd6de5ea3efe1213a6","src/filedescriptor.rs":"706eebde408713cc49bbab078e86fe51e95fe29b167420bbcbb573847dcf29e2","src/lib.rs":"8ae5082d92ebf6b1a53332211b87986aa7228534f5e341b62100e522b7fcadec","src/locale.rs":"372190a9cb5659fba0b92598c5dcbdaa3f90b29b3440ddcfe77931e85c1f96d9","src/mach_port.rs":"e52c2ce794e82ebeeb0cba170902409f18626b7d9e29d6dcd333e9c13411408a","src/messageport.rs":"d8e342f0eabe47f6f4746fdbf996bf9008b4b5f1fa24e0bc4ecd73b2de81b234","src/notification_center.rs":"0ab30523bc4ac799016970c9c59594cbb3afeda054705c15d0979eb07abb7c7d","src/number.rs":"28b10c9d2361cac18549ef66839f595e98490096e756e9a7f25536b6ceb1f687","src/number_formatter.rs":"024fbd3b2ecaecf19cfdb463e0f0096d1fa28bc4ce636659e53459d1b01af658","src/plugin.rs":"0904b1b4b882e626d5d63ac91c540dfdf65f5f4428cf38c9def6acfc7ed84cd3","src/preferences.rs":"49d8ac0c669a01678fa0dc26d6cb13bc72004c8422e525bf3e26f01feb5a3693","src/propertylist.rs":"f7f12cb8c67098e5b96cb8a63b4a947549a2cbf7a6523ce314141b4f8cc202c4","src/runloop.rs":"8fa6e5e74a013f8101d5a4f6616818573adc7ed197e28b799dca4c3a1cedaac9","src/set.rs":"0e619ec75a6b975be6b6d59ed3b01c803dd635020288b178db949b1c45442d17","src/socket.rs":"b67737b8c04142fa4d198c19f0867fd653837e529bf2665e78750c94f469a793","src/stream.rs":"f9b1099191010a96ce0aadcc22385732710dfc1521873096a9db67ad80472e36","src/string.rs":"fa46e7b7865709494bb05c9c7c6006f165fafa956ab41f053af0e4b41904efa4","src/string_tokenizer.rs":"0da4ae1a841591871602f21cc1c9b51289a0514a255b269e4b61afdeb0097c10","src/timezone.rs":"f584ea76627f12f33eba25d7ea054c2d2c10a2d96474fce12858ccb4bdf688c1","src/tree.rs":"50d513ea1801797c549218c51f5ebf77be4cf80901b12ce3ba0a223c602995d4","src/url.rs":"cb08b0bd24708e6572711f4f82b88370e811aabf4f58f22c34f0f873a44c7486","src/url_enumerator.rs":"bd531f31f6c62b2849d5ccbc82bfc3ae3866c4cdd6768b6c2fe380f24c290540","src/user_notification.rs":"e86b052817028847e62121752e7d58f8ed6f8ad15f5ef947c1fa93bbd0fcbf26","src/uuid.rs":"48af493dc6c8b00d804d6ae92a2fd71eabdae8a2be0500baaa55ce56345c350a","src/xml_node.rs":"c7894a4d08f695ba75d539b3c8d6cc3a90544000786fe3f9cd9c02ad7541213b","src/xml_parser.rs":"ac8a3d2c71ec8ec80603ce5ef214147c0e93bed211c1559a47f14fc31cb0bbaf"},"package":"06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"abb57076b7b146aaa3508d3aeef56380579a57196346c9e413c34958fcf4c1bc","Cargo.toml":"f8b5e9fa6c6bbfad4e3c0acfbad03f05cbd98073e664e3ad2fe16a56dd492aa1","Cargo.toml.orig":"055e4c3d8e2b83f0e5cdc325954c10a043adaad7bb738a2a974af99712b94f6c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"4d469ca3f6aceb42dfaf7b26aa9ef14a8ebce05e02d0beda985fa32f2ec48963","src/attributed_string.rs":"7042f3fbf6904efecb15f01ce2e96eecf84973e0fef9be4c10d14944b0f90a24","src/bag.rs":"dec9ff467ac713526c3be8148ae41b21ab8840f393733bb53c77224ef089787c","src/base.rs":"5d0dee358519712e881e2edbea0ca6d3539958ed1ff3d70aa136af7e25292f22","src/binary_heap.rs":"0565125dbdb1fa578888e00f5b195ab91f0bf65881eabcd39de99ca811d756de","src/bit_vector.rs":"dcdaa573d90b25bdc6b98f2330110e8591b7c329601643dcc6aa23b1b9ec7210","src/bundle.rs":"83ac9d7c45f06161767588c465eed086a773714734da0614d98d000326df3603","src/calendar.rs":"b73796956e50d92f0479479e84246712804537d694e4cdd01d5440e5fbcbd333","src/characterset.rs":"ba60f78884cd860e151df35c1953bcd6eae46d9f27c36584b66e508e2301a7a8","src/data.rs":"fe4e2effbfd9348575507d06aa53cd583808c908f9e03ac1a076b077230c9c01","src/date.rs":"971d681f6eeefa3764d8a43e53cbf7c937c419331207c7bb003a25c9b0b0722f","src/date_formatter.rs":"05e84ac3cf4c0daae2e939a9bedddfd10dd5309ea1536bf8241de41971d11f8a","src/dictionary.rs":"ac23d99208131049c82c13b37a99b4fd129224d1dafcd65ff2f9de200d73e9d1","src/error.rs":"b523faa8c498e1115c72e71a10e7a3bf8bcc01588cb02e70dc9fd45cbdaa35f6","src/file_security.rs":"542c5d8eef22424479abcb448601611d85c9cc96e41cd6cd6de5ea3efe1213a6","src/filedescriptor.rs":"706eebde408713cc49bbab078e86fe51e95fe29b167420bbcbb573847dcf29e2","src/lib.rs":"8ae5082d92ebf6b1a53332211b87986aa7228534f5e341b62100e522b7fcadec","src/locale.rs":"372190a9cb5659fba0b92598c5dcbdaa3f90b29b3440ddcfe77931e85c1f96d9","src/mach_port.rs":"e52c2ce794e82ebeeb0cba170902409f18626b7d9e29d6dcd333e9c13411408a","src/messageport.rs":"d8e342f0eabe47f6f4746fdbf996bf9008b4b5f1fa24e0bc4ecd73b2de81b234","src/notification_center.rs":"0ab30523bc4ac799016970c9c59594cbb3afeda054705c15d0979eb07abb7c7d","src/number.rs":"28b10c9d2361cac18549ef66839f595e98490096e756e9a7f25536b6ceb1f687","src/number_formatter.rs":"024fbd3b2ecaecf19cfdb463e0f0096d1fa28bc4ce636659e53459d1b01af658","src/plugin.rs":"0904b1b4b882e626d5d63ac91c540dfdf65f5f4428cf38c9def6acfc7ed84cd3","src/preferences.rs":"49d8ac0c669a01678fa0dc26d6cb13bc72004c8422e525bf3e26f01feb5a3693","src/propertylist.rs":"f7f12cb8c67098e5b96cb8a63b4a947549a2cbf7a6523ce314141b4f8cc202c4","src/runloop.rs":"8fa6e5e74a013f8101d5a4f6616818573adc7ed197e28b799dca4c3a1cedaac9","src/set.rs":"0e619ec75a6b975be6b6d59ed3b01c803dd635020288b178db949b1c45442d17","src/socket.rs":"b67737b8c04142fa4d198c19f0867fd653837e529bf2665e78750c94f469a793","src/stream.rs":"f9b1099191010a96ce0aadcc22385732710dfc1521873096a9db67ad80472e36","src/string.rs":"fa46e7b7865709494bb05c9c7c6006f165fafa956ab41f053af0e4b41904efa4","src/string_tokenizer.rs":"0da4ae1a841591871602f21cc1c9b51289a0514a255b269e4b61afdeb0097c10","src/timezone.rs":"f584ea76627f12f33eba25d7ea054c2d2c10a2d96474fce12858ccb4bdf688c1","src/tree.rs":"50d513ea1801797c549218c51f5ebf77be4cf80901b12ce3ba0a223c602995d4","src/url.rs":"cb08b0bd24708e6572711f4f82b88370e811aabf4f58f22c34f0f873a44c7486","src/url_enumerator.rs":"bd531f31f6c62b2849d5ccbc82bfc3ae3866c4cdd6768b6c2fe380f24c290540","src/user_notification.rs":"e86b052817028847e62121752e7d58f8ed6f8ad15f5ef947c1fa93bbd0fcbf26","src/uuid.rs":"48af493dc6c8b00d804d6ae92a2fd71eabdae8a2be0500baaa55ce56345c350a","src/xml_node.rs":"c7894a4d08f695ba75d539b3c8d6cc3a90544000786fe3f9cd9c02ad7541213b","src/xml_parser.rs":"ac8a3d2c71ec8ec80603ce5ef214147c0e93bed211c1559a47f14fc31cb0bbaf"},"package":"06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "64dd01a6a951ccc12bb707a5882549d4e80b8249" + }, + "path_in_vcs": "core-foundation-sys" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/core-foundation-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core-foundation-sys/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[package] +name = "core-foundation-sys" +description = "Bindings to Core Foundation for macOS" +homepage = "https://github.com/servo/core-foundation-rs" +repository = "https://github.com/servo/core-foundation-rs" +version = "0.8.6" +authors = ["The Servo Project Developers"] +license = "MIT OR Apache-2.0" +edition = "2018" + +[dependencies] + +[features] +default = ["link"] +mac_os_10_7_support = [] # backwards compatibility +mac_os_10_8_features = [] # enables new features +# Disable to manually link. Enabled by default. +link = [] + +[package.metadata.docs.rs] +all-features = true +default-target = "x86_64-apple-darwin" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/core2/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"97e582bdafd724e30842db3636818e46685c3865345a84649a0746f9f2aead48",".github/workflows/ci.yml":"8f1149869431189d5dd545186a6b32062ed6bc69f88179ef7f86c4451166f2c1","Cargo.toml":"9d15d78383cea0be698c50194e817b837db639df535df793a8f77603565b14be","Cargo.toml.orig":"2606318d338a48be74faab8f1cd7b06255619ea65f9c498ff90e8d24cdd6bb4c","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f21c3bfdc47749b5912eb55f0661b2b8fd9696b3e09e7d97a1fc78fb52c3eb1b","README.md":"12f750bbe4b2e2193b7b020ba1435c69cb5edafc7e4c7c5578f4e0cc750405f7","src/error.rs":"87b6be698ca7871b3cee5ef7c0b5dfa88f0b49dfc4884bf37434cf4abf26de7e","src/io/buffered.rs":"195943a51da57f4df57d43400c904215cad12c7626531a78b56e30df229a039f","src/io/cursor.rs":"aafa4fd118bfe1b5fc0fcde33ae979c5837ba65bbebf1091bea9634d192df4df","src/io/error.rs":"5a1dcd55cb76f28d506daf8436ce96e60b7da87cc5154e8f90d97c748a0d4e4e","src/io/impls.rs":"bdeee214b35b792e26b0568a525b32c5f30090577d404cdbd589dac5a99759e6","src/io/mod.rs":"bfacd06c96e78b901c2c8c508fbfa6400eef6aedc8a391afea75f6054451e597","src/io/traits.rs":"2dfa00f4431853ca3fad18b953bded7b2ff9a89011d872b9848c93164f34c4d5","src/io/util.rs":"6647763b5db5c0e60e7927e3c439fcd5edd74af159b4696f1f84b8a2dd39b27b","src/lib.rs":"c65760822761904ce833a0a91aceb58b6ea509a5c385c7b06fec1e887db68a71","tests/tests.rs":"26ab2060fca5bb3d4b2a84b9acc45b3b0a17294ddeed433eab0639e0dd88ca30"},"package":"b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/core2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "545e84bcb0f235b12e21351e0c69767958efe2a7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/core2/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/core2/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/.github/workflows/ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,91 @@ +name: CI +on: [push, pull_request] + +jobs: + test-nightly: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + rust: [nightly] + steps: + - uses: actions/checkout@v2 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - name: Run tests (no_std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --tests --no-default-features --features nightly + - name: Run tests (std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --tests --no-default-features --features std,nightly + - name: Run tests (alloc) + uses: actions-rs/cargo@v1 + with: + command: test + args: --tests --no-default-features --features alloc,nightly + test-stable: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + rust: [stable] + steps: + - uses: actions/checkout@v2 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - name: Run tests (no_std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features + - name: Run tests (std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features std + - name: Run tests (alloc) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features alloc + test-msrv: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + rust: [1.47] + steps: + - uses: actions/checkout@v2 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - name: Run tests (no_std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features + - name: Run tests (std) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features std + - name: Run tests (alloc) + uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features alloc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/core2/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "core2" +version = "0.4.0" +authors = ["Brendan Molloy "] +description = "The bare essentials of std::io for use in no_std. Alloc support is optional." +categories = ["no-std"] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/bbqsrc/core2" +[package.metadata.docs.rs] +features = ["nightly"] +[dependencies.memchr] +version = "2" +default-features = false + +[features] +alloc = [] +default = ["std"] +nightly = [] +std = ["alloc"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/core2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,21 @@ +[package] +name = "core2" +version = "0.4.0" +authors = ["Brendan Molloy "] +description = "The bare essentials of std::io for use in no_std. Alloc support is optional." +license = "Apache-2.0 OR MIT" +edition = "2018" +repository = "https://github.com/bbqsrc/core2" +categories = ["no-std"] + +[dependencies] +memchr = { version = "2", default-features = false } + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] +nightly = [] + +[package.metadata.docs.rs] +features = ["nightly"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/core2/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-APACHE 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + http://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. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/core2/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/LICENSE-MIT 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,19 @@ +Copyright (c) 2020-2021 Brendan Molloy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/README.md clamav-1.4.6+dfsg/.cargo/vendor/core2/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/core2/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/README.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,66 @@ +# core2 + +[![Actions Status](https://github.com/bbqsrc/core2/workflows/CI/badge.svg)](https://github.com/bbqsrc/core2/actions) +[![Documentation](https://docs.rs/core2/badge.svg)](https://docs.rs/core2) +![Minimum Supported Rust Version (MSRV)](https://img.shields.io/badge/rust-v1.47.0+-blue) + +Ever wanted a `Cursor` or the `Error` trait in `no_std`? Well now you can have it. A 'fork' of Rust's `std` modules for `no_std` environments, with the added benefit of optionally taking advantage of `alloc`. + +The goal of this crate is to provide a stable interface for building I/O and error trait functionality in +`no_std` environments. The current code corresponds to the most recent stable API of Rust 1.47.0. +It is also a goal to achieve a true alloc-less experience, with opt-in alloc support. + +This crate works on `stable` with some limitations in functionality, and `nightly` without limitations by adding +the relevant feature flag. + +This crate is `std` by default -- use no default features to get `no_std` mode. + +## Usage + +```toml +[dependencies] +core2 = "0.3" +``` + +Add the crate, use the things you would usually want from `std::io`, but instead from `core2::io`, and +use `core2::error::Error` in place of `std::error::Error`. + +### Features + +- **std**: enables `std` pass-throughs for the polyfilled types, but allows accessing the new types +- **alloc**: enable aspects of the `Read` and `Write` traits that require `alloc` support (WIP) +- **nightly**: enables **nightly**-only features, such as `BufReader` and `BufWriter` with const generic buffers. + +### Differences to `std::io` + +- No `std::io::Error`, so we have our own copy without any `Os` error functions +- `IoSlice` and the `*_vectored` family of functions are not implemented. +- `BufReader` and `BufWriter` have a different signature, as they now use a const generic bounded array for the internal buffer. (Requires **nightly** feature) + +Other than items perhaps being entirely missing or certain functions unavailable on some traits, no function signatures have been changed. + +### Limitations + +- Using the buffer types currently requires **nightly** due to the use of const generics. +- Using `copy` or the buffer types with `std` support currently requires **nightly** due to the `initializer` API. + +## Where is it used? + +All of the below are works in progress, but should help with demonstrating how to use this crate. + +- [thiserror_core2](https://github.com/bbqsrc/thiserror-core2): fork of `thiserror` using the `core2::error::Error` trait. + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +--- + +Almost all of the code in this repository is a copy of the [Rust language codebase](https://github.com/rust-lang/rust) with minor modifications. + +For attributions, see https://thanks.rust-lang.org/. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/error.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,473 @@ +//! Traits for working with Errors. + +// A note about crates and the facade: +// +// Originally, the `Error` trait was defined in libcore, and the impls +// were scattered about. However, coherence objected to this +// arrangement, because to create the blanket impls for `Box` required +// knowing that `&str: !Error`, and we have no means to deal with that +// sort of conflict just now. Therefore, for the time being, we have +// moved the `Error` trait into libstd. As we evolve a sol'n to the +// coherence challenge (e.g., specialization, neg impls, etc) we can +// reconsider what crate these items belong in. + +#[allow(deprecated)] +use core::alloc::LayoutErr; + +use core::any::TypeId; +use core::fmt::{Debug, Display}; + +#[cfg(feature = "alloc")] +use alloc::{string::String, borrow::Cow, boxed::Box}; + +/// `Error` is a trait representing the basic expectations for error values, +/// i.e., values of type `E` in [`Result`]. Errors must describe +/// themselves through the [`Display`] and [`Debug`] traits, and may provide +/// cause chain information: +/// +/// [`Error::source()`] is generally used when errors cross +/// "abstraction boundaries". If one module must report an error that is caused +/// by an error from a lower-level module, it can allow accessing that error +/// via [`Error::source()`]. This makes it possible for the high-level +/// module to provide its own errors while also revealing some of the +/// implementation for debugging via `source` chains. +/// +/// [`Result`]: Result +pub trait Error: Debug + Display { + /// The lower-level source of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct SuperError { + /// side: SuperErrorSideKick, + /// } + /// + /// impl fmt::Display for SuperError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperError is here!") + /// } + /// } + /// + /// impl Error for SuperError { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// Some(&self.side) + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SuperErrorSideKick; + /// + /// impl fmt::Display for SuperErrorSideKick { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperErrorSideKick is here!") + /// } + /// } + /// + /// impl Error for SuperErrorSideKick {} + /// + /// fn get_super_error() -> Result<(), SuperError> { + /// Err(SuperError { side: SuperErrorSideKick }) + /// } + /// + /// fn main() { + /// match get_super_error() { + /// Err(e) => { + /// println!("Error: {}", e); + /// println!("Caused by: {}", e.source().unwrap()); + /// } + /// _ => println!("No error"), + /// } + /// } + /// ``` + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } + + /// Gets the `TypeId` of `self`. + #[doc(hidden)] + fn type_id(&self, _: private::Internal) -> TypeId + where + Self: 'static, + { + TypeId::of::() + } +} + +mod private { + // This is a hack to prevent `type_id` from being overridden by `Error` + // implementations, since that can enable unsound downcasting. + #[derive(Debug)] + pub struct Internal; +} + +#[cfg(feature = "alloc")] +impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(feature = "alloc")] +impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of + /// dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(feature = "alloc")] +impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: String) -> Box { + struct StringError(String); + + impl Error for StringError {} + + impl Display for StringError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Display::fmt(&self.0, f) + } + } + + // Purposefully skip printing "StringError(..)" + impl Debug for StringError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Debug::fmt(&self.0, f) + } + } + + Box::new(StringError(err)) + } +} + +#[cfg(feature = "alloc")] +impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; + err2 + } +} + +#[cfg(feature = "alloc")] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(feature = "alloc")] +impl From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(feature = "alloc")] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(feature = "alloc")] +impl<'a> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'a, str>) -> Box { + From::from(String::from(err)) + } +} + +// #[unstable(feature = "never_type", issue = "35121")] +#[cfg(feature = "nightly")] +impl Error for ! {} + +#[allow(deprecated)] +impl Error for LayoutErr {} + +impl Error for core::str::ParseBoolError {} + +impl Error for core::str::Utf8Error {} + +impl Error for core::num::ParseIntError {} + +impl Error for core::num::TryFromIntError {} + +impl Error for core::array::TryFromSliceError {} + +impl Error for core::num::ParseFloatError {} + +#[cfg(feature = "alloc")] +impl Error for alloc::string::FromUtf8Error {} + +#[cfg(feature = "alloc")] +impl Error for alloc::string::FromUtf16Error {} + + +#[cfg(feature = "alloc")] +impl Error for Box { + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } +} + +// Copied from `any.rs`. +impl dyn Error + 'static { + /// Returns `true` if the boxed type is the same as `T` + #[inline] + pub fn is(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = TypeId::of::(); + + // Get `TypeId` of the type in the trait object. + let boxed = self.type_id(private::Internal); + + // Compare both `TypeId`s on equality. + t == boxed + } + + /// Returns some reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + unsafe { Some(&*(self as *const dyn Error as *const T)) } + } else { + None + } + } + + /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } + } else { + None + } + } +} + +impl dyn Error + 'static + Send { + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +impl dyn Error + 'static + Send + Sync { + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +#[cfg(feature = "alloc")] +impl dyn Error { + #[inline] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + if self.is::() { + unsafe { + let raw: *mut dyn Error = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +#[cfg(feature = "alloc")] +impl dyn Error + Send { + #[inline] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send` marker. + core::mem::transmute::, Box>(s) + }) + } +} + +#[cfg(feature = "alloc")] +impl dyn Error + Send + Sync { + #[inline] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send + Sync` marker. + core::mem::transmute::, Box>(s) + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/buffered.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/buffered.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/buffered.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/buffered.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,1111 @@ +//! Buffering wrappers for I/O traits + +use crate::io::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write}; +use core::{cmp, fmt}; + +/// The `BufReader` struct adds buffering to any reader. +/// +/// It can be excessively inefficient to work directly with a [`Read`] instance. +/// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`] +/// results in a system call. A `BufReader` performs large, infrequent reads on +/// the underlying [`Read`] and maintains an in-memory buffer of the results. +/// +/// `BufReader` can improve the speed of programs that make *small* and +/// *repeated* read calls to the same file or network socket. It does not +/// help when reading very large amounts at once, or reading just one or a few +/// times. It also provides no advantage when reading from a source that is +/// already in memory, like a [`Vec`]``. +/// +/// When the `BufReader` is dropped, the contents of its buffer will be +/// discarded. Creating multiple instances of a `BufReader` on the same +/// stream can cause data loss. Reading from the underlying reader after +/// unwrapping the `BufReader` with [`BufReader::into_inner`] can also cause +/// data loss. +/// +/// [`TcpStream::read`]: Read::read +/// [`TcpStream`]: crate::net::TcpStream +/// +/// # Examples +/// +/// ```no_run +/// use std::prelude::*; +/// use core2::io::BufReader; +/// use std::fs::File; +/// +/// fn main() -> core::result::Result<()> { +/// let f = File::open("log.txt")?; +/// let mut reader = BufReader::new(f); +/// +/// let mut line = String::new(); +/// let len = reader.read_line(&mut line)?; +/// println!("First line is {} bytes long", len); +/// Ok(()) +/// } +/// ``` +pub struct BufReader { + inner: R, + buf: [u8; S], + pos: usize, + cap: usize, +} + +impl BufReader { + /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufReader; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::new(f); + /// Ok(()) + /// } + /// ``` + pub fn new(inner: R) -> BufReader { + BufReader { + inner, + buf: [0; S], + pos: 0, + cap: 0, + } + } +} + +impl BufReader { + /// Gets a reference to the underlying reader. + /// + /// It is inadvisable to directly read from the underlying reader. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufReader; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); + /// + /// let f2 = reader.get_ref(); + /// Ok(()) + /// } + /// ``` + pub fn get_ref(&self) -> &R { + &self.inner + } + + /// Gets a mutable reference to the underlying reader. + /// + /// It is inadvisable to directly read from the underlying reader. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufReader; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); + /// + /// let f2 = reader.get_mut(); + /// Ok(()) + /// } + /// ``` + pub fn get_mut(&mut self) -> &mut R { + &mut self.inner + } + + /// Returns a reference to the internally buffered data. + /// + /// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty. + /// + /// [`fill_buf`]: BufRead::fill_buf + /// + /// # Examples + /// + /// ```no_run + /// use std::{BufReader, BufRead}; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// assert!(reader.buffer().is_empty()); + /// + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.buffer().is_empty()); + /// } + /// Ok(()) + /// } + /// ``` + pub fn buffer(&self) -> &[u8] { + &self.buf[self.pos..self.cap] + } + + /// Returns the number of bytes the internal buffer can hold at once. + /// + /// # Examples + /// + /// ```no_run + /// use std::{BufReader, BufRead}; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// + /// let capacity = reader.capacity(); + /// let buffer = reader.fill_buf()?; + /// assert!(buffer.len() <= capacity); + /// Ok(()) + /// } + /// ``` + pub fn capacity(&self) -> usize { + S + } + + /// Unwraps this `BufReader`, returning the underlying reader. + /// + /// Note that any leftover data in the internal buffer is lost. Therefore, + /// a following read from the underlying reader may lead to data loss. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufReader; + /// use std::fs::File; + /// + /// fn main() -> core::result::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); + /// + /// let f2 = reader.into_inner(); + /// Ok(()) + /// } + /// ``` + pub fn into_inner(self) -> R { + self.inner + } + + /// Invalidates all data in the internal buffer. + #[inline] + fn discard_buffer(&mut self) { + self.pos = 0; + self.cap = 0; + } +} + +impl Read for BufReader { + fn read(&mut self, buf: &mut [u8]) -> Result { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= S { + self.discard_buffer(); + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) + } +} + +impl BufRead for BufReader { + fn fill_buf(&mut self) -> Result<&[u8]> { + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + // Branch using `>=` instead of the more correct `==` + // to tell the compiler that the pos..cap slice is always valid. + if self.pos >= self.cap { + debug_assert!(self.pos == self.cap); + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) + } + + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); + } +} + +impl fmt::Debug for BufReader +where + R: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("BufReader") + .field("reader", &self.inner) + .field("buffer", &format_args!("{}/{}", self.cap - self.pos, S)) + .finish() + } +} + +impl Seek for BufReader { + /// Seek to an offset, in bytes, in the underlying reader. + /// + /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the + /// position the underlying reader would be at if the `BufReader` had no + /// internal buffer. + /// + /// Seeking always discards the internal buffer, even if the seek position + /// would otherwise fall within it. This guarantees that calling + /// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader + /// at the same position. + /// + /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`]. + /// + /// See [`std::Seek`] for more details. + /// + /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)` + /// where `n` minus the internal buffer length overflows an `i64`, two + /// seeks will be performed instead of one. If the second seek returns + /// [`Err`], the underlying reader will be left at the same position it would + /// have if you called `seek` with [`SeekFrom::Current`]`(0)`. + /// + /// [`std::Seek`]: Seek + fn seek(&mut self, pos: SeekFrom) -> Result { + let result: u64; + if let SeekFrom::Current(n) = pos { + let remainder = (self.cap - self.pos) as i64; + // it should be safe to assume that remainder fits within an i64 as the alternative + // means we managed to allocate 8 exbibytes and that's absurd. + // But it's not out of the realm of possibility for some weird underlying reader to + // support seeking by i64::MIN so we need to handle underflow when subtracting + // remainder. + if let Some(offset) = n.checked_sub(remainder) { + result = self.inner.seek(SeekFrom::Current(offset))?; + } else { + // seek backwards by our remainder, and then by the offset + self.inner.seek(SeekFrom::Current(-remainder))?; + self.discard_buffer(); + result = self.inner.seek(SeekFrom::Current(n))?; + } + } else { + // Seeking with Start/End doesn't care about our buffer length. + result = self.inner.seek(pos)?; + } + self.discard_buffer(); + Ok(result) + } +} + +/// Wraps a writer and buffers its output. +/// +/// It can be excessively inefficient to work directly with something that +/// implements [`Write`]. For example, every call to +/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A +/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying +/// writer in large, infrequent batches. +/// +/// `BufWriter` can improve the speed of programs that make *small* and +/// *repeated* write calls to the same file or network socket. It does not +/// help when writing very large amounts at once, or writing just one or a few +/// times. It also provides no advantage when writing to a destination that is +/// in memory, like a [`Vec`]`. +/// +/// It is critical to call [`flush`] before `BufWriter` is dropped. Though +/// dropping will attempt to flush the contents of the buffer, any errors +/// that happen in the process of dropping will be ignored. Calling [`flush`] +/// ensures that the buffer is empty and thus dropping will not even attempt +/// file operations. +/// +/// # Examples +/// +/// Let's write the numbers one through ten to a [`TcpStream`]: +/// +/// ```no_run +/// use std::prelude::*; +/// use std::net::TcpStream; +/// +/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); +/// +/// for i in 0..10 { +/// stream.write(&[i+1]).unwrap(); +/// } +/// ``` +/// +/// Because we're not buffering, we write each one in turn, incurring the +/// overhead of a system call per byte written. We can fix this with a +/// `BufWriter`: +/// +/// ```no_run +/// use std::prelude::*; +/// use core2::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// for i in 0..10 { +/// stream.write(&[i+1]).unwrap(); +/// } +/// stream.flush().unwrap(); +/// ``` +/// +/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped +/// together by the buffer and will all be written out in one system call when +/// the `stream` is flushed. +/// +/// [`TcpStream::write`]: Write::write +/// [`TcpStream`]: crate::net::TcpStream +/// [`flush`]: Write::flush +pub struct BufWriter { + inner: Option, + buf: [u8; S], + len: usize, + // #30888: If the inner writer panics in a call to write, we don't want to + // write the buffered data a second time in BufWriter's destructor. This + // flag tells the Drop impl if it should skip the flush. + panicked: bool, +} + +/// An error returned by [`BufWriter::into_inner`] which combines an error that +/// happened while writing out the buffer, and the buffered writer object +/// which may be used to recover from the condition. +/// +/// # Examples +/// +/// ```no_run +/// use core2::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// // do stuff with the stream +/// +/// // we want to get our `TcpStream` back, so let's try: +/// +/// let stream = match stream.into_inner() { +/// Ok(s) => s, +/// Err(e) => { +/// // Here, e is an IntoInnerError +/// panic!("An error occurred"); +/// } +/// }; +/// ``` +#[derive(Debug)] +pub struct IntoInnerError(W, Error); + +impl BufWriter +where + W: Write, +{ + /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// ``` + pub fn new(inner: W) -> BufWriter { + BufWriter { + inner: Some(inner), + buf: [0; S], + len: 0, + panicked: false, + } + } + + /// Send data in our local buffer into the inner writer, looping as + /// necessary until either it's all been sent or an error occurs. + /// + /// Because all the data in the buffer has been reported to our owner as + /// "successfully written" (by returning nonzero success values from + /// `write`), any 0-length writes from `inner` must be reported as i/o + /// errors from this method. + fn flush_buf(&mut self) -> Result<()> { + /// Helper struct to ensure the buffer is updated after all the writes + /// are complete. It tracks the number of written bytes and drains them + /// all from the front of the buffer when dropped. + struct BufGuard<'a, const S: usize> { + buffer: &'a mut [u8; S], + written: usize, + } + + impl<'a, const S: usize> BufGuard<'a, S> { + fn new(buffer: &'a mut [u8; S]) -> Self { + Self { buffer, written: 0 } + } + + /// The unwritten part of the buffer + fn remaining(&self) -> &[u8] { + &self.buffer[self.written..] + } + + /// Flag some bytes as removed from the front of the buffer + fn consume(&mut self, amt: usize) { + self.written += amt; + } + + /// true if all of the bytes have been written + fn done(&self) -> bool { + self.written >= self.buffer.len() + } + } + + impl Drop for BufGuard<'_, S> { + fn drop(&mut self) { + if self.written > 0 { + let mut new_buf = [0; S]; + new_buf.copy_from_slice(&self.buffer[self.written..]); + *self.buffer = new_buf; + } + } + } + + let mut guard = BufGuard::new(&mut self.buf); + let inner = self.inner.as_mut().unwrap(); + while !guard.done() { + self.panicked = true; + let r = inner.write(guard.remaining()); + self.panicked = false; + + match r { + Ok(0) => { + return Err(Error::new( + ErrorKind::WriteZero, + "failed to write the buffered data", + )); + } + Ok(n) => guard.consume(n), + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } + + /// Buffer some data without flushing it, regardless of the size of the + /// data. Writes as much as possible without exceeding capacity. Returns + /// the number of bytes written. + fn write_to_buf(&mut self, buf: &[u8]) -> usize { + let available = S - self.len; + let amt_to_buffer = available.min(buf.len()); + (&mut self.buf[available..]).copy_from_slice(&buf[..amt_to_buffer]); + self.len += amt_to_buffer; + amt_to_buffer + } + + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_ref(); + /// ``` + pub fn get_ref(&self) -> &W { + self.inner.as_ref().unwrap() + } + + /// Gets a mutable reference to the underlying writer. + /// + /// It is inadvisable to directly write to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_mut(); + /// ``` + pub fn get_mut(&mut self) -> &mut W { + self.inner.as_mut().unwrap() + } + + /// Returns a reference to the internally buffered data. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // See how many bytes are currently buffered + /// let bytes_buffered = buf_writer.buffer().len(); + /// ``` + pub fn buffer(&self) -> &[u8] { + &self.buf + } + + /// Returns the number of bytes the internal buffer can hold without flushing. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // Check the capacity of the inner buffer + /// let capacity = buf_writer.capacity(); + /// // Calculate how many bytes can be written without flushing + /// let without_flush = capacity - buf_writer.buffer().len(); + /// ``` + pub fn capacity(&self) -> usize { + S + } + + /// Unwraps this `BufWriter`, returning the underlying writer. + /// + /// The buffer is written out before returning the writer. + /// + /// # Errors + /// + /// An [`Err`] will be returned if an error occurs while flushing the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // unwrap the TcpStream and flush the buffer + /// let stream = buffer.into_inner().unwrap(); + /// ``` + pub fn into_inner(mut self) -> core::result::Result>> { + match self.flush_buf() { + Err(e) => Err(IntoInnerError(self, e)), + Ok(()) => Ok(self.inner.take().unwrap()), + } + } +} + +impl Write for BufWriter { + fn write(&mut self, buf: &[u8]) -> Result { + if self.len + buf.len() > S { + self.flush_buf()?; + } + // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919 + if buf.len() >= S { + self.panicked = true; + let r = self.get_mut().write(buf); + self.panicked = false; + r + } else { + self.buf.copy_from_slice(buf); + Ok(buf.len()) + } + } + + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + // Normally, `write_all` just calls `write` in a loop. We can do better + // by calling `self.get_mut().write_all()` directly, which avoids + // round trips through the buffer in the event of a series of partial + // writes in some circumstances. + if self.len + buf.len() > S { + self.flush_buf()?; + } + // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919 + if buf.len() >= S { + self.panicked = true; + let r = self.get_mut().write_all(buf); + self.panicked = false; + r + } else { + self.buf.copy_from_slice(buf); + Ok(()) + } + } + + fn flush(&mut self) -> Result<()> { + self.flush_buf().and_then(|()| self.get_mut().flush()) + } +} + +impl fmt::Debug for BufWriter +where + W: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("BufWriter") + .field("writer", &self.inner.as_ref().unwrap()) + .field("buffer", &format_args!("{}/{}", self.buf.len(), S)) + .finish() + } +} + +impl Seek for BufWriter { + /// Seek to the offset, in bytes, in the underlying writer. + /// + /// Seeking always writes out the internal buffer before seeking. + fn seek(&mut self, pos: SeekFrom) -> Result { + self.flush_buf()?; + self.get_mut().seek(pos) + } +} + +impl Drop for BufWriter { + fn drop(&mut self) { + if self.inner.is_some() && !self.panicked { + // dtors should not panic, so we ignore a failed flush + let _r = self.flush_buf(); + } + } +} + +impl IntoInnerError { + /// Returns the error which caused the call to [`BufWriter::into_inner()`] + /// to fail. + /// + /// This error was returned when attempting to write the internal buffer. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is an IntoInnerError, let's log the inner error. + /// // + /// // We'll just 'log' to stdout for this example. + /// println!("{}", e.error()); + /// + /// panic!("An unexpected error occurred."); + /// } + /// }; + /// ``` + pub fn error(&self) -> &Error { + &self.1 + } + + /// Returns the buffered writer instance which generated the error. + /// + /// The returned object can be used for error recovery, such as + /// re-inspecting the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use core2::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is an IntoInnerError, let's re-examine the buffer: + /// let buffer = e.into_inner(); + /// + /// // do stuff to try to recover + /// + /// // afterwards, let's just return the stream + /// buffer.into_inner().unwrap() + /// } + /// }; + /// ``` + pub fn into_inner(self) -> W { + self.0 + } +} + +impl From> for Error { + fn from(iie: IntoInnerError) -> Error { + iie.1 + } +} + +impl fmt::Display for IntoInnerError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.error().fmt(f) + } +} + +/// Private helper struct for implementing the line-buffered writing logic. +/// This shim temporarily wraps a BufWriter, and uses its internals to +/// implement a line-buffered writer (specifically by using the internal +/// methods like write_to_buf and flush_buf). In this way, a more +/// efficient abstraction can be created than one that only had access to +/// `write` and `flush`, without needlessly duplicating a lot of the +/// implementation details of BufWriter. This also allows existing +/// `BufWriters` to be temporarily given line-buffering logic; this is what +/// enables Stdout to be alternately in line-buffered or block-buffered mode. +#[derive(Debug)] +pub(super) struct LineWriterShim<'a, W: Write, const S: usize> { + buffer: &'a mut BufWriter, +} + +impl<'a, W: Write, const S: usize> LineWriterShim<'a, W, S> { + pub fn new(buffer: &'a mut BufWriter) -> Self { + Self { buffer } + } + + /// Get a mutable reference to the inner writer (that is, the writer + /// wrapped by the BufWriter). Be careful with this writer, as writes to + /// it will bypass the buffer. + fn inner_mut(&mut self) -> &mut W { + self.buffer.get_mut() + } + + /// Get the content currently buffered in self.buffer + fn buffered(&self) -> &[u8] { + self.buffer.buffer() + } + + /// Flush the buffer iff the last byte is a newline (indicating that an + /// earlier write only succeeded partially, and we want to retry flushing + /// the buffered line before continuing with a subsequent write) + fn flush_if_completed_line(&mut self) -> Result<()> { + match self.buffered().last().copied() { + Some(b'\n') => self.buffer.flush_buf(), + _ => Ok(()), + } + } +} + +impl<'a, W: Write, const S: usize> Write for LineWriterShim<'a, W, S> { + /// Write some data into this BufReader with line buffering. This means + /// that, if any newlines are present in the data, the data up to the last + /// newline is sent directly to the underlying writer, and data after it + /// is buffered. Returns the number of bytes written. + /// + /// This function operates on a "best effort basis"; in keeping with the + /// convention of `Write::write`, it makes at most one attempt to write + /// new data to the underlying writer. If that write only reports a partial + /// success, the remaining data will be buffered. + /// + /// Because this function attempts to send completed lines to the underlying + /// writer, it will also flush the existing buffer if it ends with a + /// newline, even if the incoming data does not contain any newlines. + fn write(&mut self, buf: &[u8]) -> Result { + let newline_idx = match memchr::memrchr(b'\n', buf) { + // If there are no new newlines (that is, if this write is less than + // one line), just do a regular buffered write (which may flush if + // we exceed the inner buffer's size) + None => { + self.flush_if_completed_line()?; + return self.buffer.write(buf); + } + // Otherwise, arrange for the lines to be written directly to the + // inner writer. + Some(newline_idx) => newline_idx + 1, + }; + + // Flush existing content to prepare for our write. We have to do this + // before attempting to write `buf` in order to maintain consistency; + // if we add `buf` to the buffer then try to flush it all at once, + // we're obligated to return Ok(), which would mean suppressing any + // errors that occur during flush. + self.buffer.flush_buf()?; + + // This is what we're going to try to write directly to the inner + // writer. The rest will be buffered, if nothing goes wrong. + let lines = &buf[..newline_idx]; + + // Write `lines` directly to the inner writer. In keeping with the + // `write` convention, make at most one attempt to add new (unbuffered) + // data. Because this write doesn't touch the BufWriter state directly, + // and the buffer is known to be empty, we don't need to worry about + // self.buffer.panicked here. + let flushed = self.inner_mut().write(lines)?; + + // If buffer returns Ok(0), propagate that to the caller without + // doing additional buffering; otherwise we're just guaranteeing + // an "ErrorKind::WriteZero" later. + if flushed == 0 { + return Ok(0); + } + + // Now that the write has succeeded, buffer the rest (or as much of + // the rest as possible). If there were any unwritten newlines, we + // only buffer out to the last unwritten newline that fits in the + // buffer; this helps prevent flushing partial lines on subsequent + // calls to LineWriterShim::write. + + // Handle the cases in order of most-common to least-common, under + // the presumption that most writes succeed in totality, and that most + // writes are smaller than the buffer. + // - Is this a partial line (ie, no newlines left in the unwritten tail) + // - If not, does the data out to the last unwritten newline fit in + // the buffer? + // - If not, scan for the last newline that *does* fit in the buffer + let tail = if flushed >= newline_idx { + &buf[flushed..] + } else if newline_idx - flushed <= self.buffer.capacity() { + &buf[flushed..newline_idx] + } else { + let scan_area = &buf[flushed..]; + let scan_area = &scan_area[..self.buffer.capacity()]; + match memchr::memrchr(b'\n', scan_area) { + Some(newline_idx) => &scan_area[..newline_idx + 1], + None => scan_area, + } + }; + + let buffered = self.buffer.write_to_buf(tail); + Ok(flushed + buffered) + } + + fn flush(&mut self) -> Result<()> { + self.buffer.flush() + } + + /// Write some data into this BufReader with line buffering. This means + /// that, if any newlines are present in the data, the data up to the last + /// newline is sent directly to the underlying writer, and data after it + /// is buffered. + /// + /// Because this function attempts to send completed lines to the underlying + /// writer, it will also flush the existing buffer if it contains any + /// newlines, even if the incoming data does not contain any newlines. + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + match memchr::memrchr(b'\n', buf) { + // If there are no new newlines (that is, if this write is less than + // one line), just do a regular buffered write (which may flush if + // we exceed the inner buffer's size) + None => { + self.flush_if_completed_line()?; + self.buffer.write_all(buf) + } + Some(newline_idx) => { + let (lines, tail) = buf.split_at(newline_idx + 1); + + if self.buffered().is_empty() { + self.inner_mut().write_all(lines)?; + } else { + // If there is any buffered data, we add the incoming lines + // to that buffer before flushing, which saves us at least + // one write call. We can't really do this with `write`, + // since we can't do this *and* not suppress errors *and* + // report a consistent state to the caller in a return + // value, but here in write_all it's fine. + self.buffer.write_all(lines)?; + self.buffer.flush_buf()?; + } + + self.buffer.write_all(tail) + } + } + } +} + +/// Wraps a writer and buffers output to it, flushing whenever a newline +/// (`0x0a`, `'\n'`) is detected. +/// +/// The [`BufWriter`] struct wraps a writer and buffers its output. +/// But it only does this batched write when it goes out of scope, or when the +/// internal buffer is full. Sometimes, you'd prefer to write each line as it's +/// completed, rather than the entire buffer at once. Enter `LineWriter`. It +/// does exactly that. +/// +/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the +/// `LineWriter` goes out of scope or when its internal buffer is full. +/// +/// If there's still a partial line in the buffer when the `LineWriter` is +/// dropped, it will flush those contents. +/// +/// # Examples +/// +/// We can use `LineWriter` to write one line at a time, significantly +/// reducing the number of actual writes to the file. +/// +/// ```no_run +/// use std::fs::{self, File}; +/// use std::prelude::*; +/// use core2::io::LineWriter; +/// +/// fn main() -> core::result::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh +/// Somewhere ages and ages hence: +/// Two roads diverged in a wood, and I - +/// I took the one less traveled by, +/// And that has made all the difference."; +/// +/// let file = File::create("poem.txt")?; +/// let mut file = LineWriter::new(file); +/// +/// file.write_all(b"I shall be telling this with a sigh")?; +/// +/// // No bytes are written until a newline is encountered (or +/// // the internal buffer is filled). +/// assert_eq!(fs::read_to_string("poem.txt")?, ""); +/// file.write_all(b"\n")?; +/// assert_eq!( +/// fs::read_to_string("poem.txt")?, +/// "I shall be telling this with a sigh\n", +/// ); +/// +/// // Write the rest of the poem. +/// file.write_all(b"Somewhere ages and ages hence: +/// Two roads diverged in a wood, and I - +/// I took the one less traveled by, +/// And that has made all the difference.")?; +/// +/// // The last line of the poem doesn't end in a newline, so +/// // we have to flush or drop the `LineWriter` to finish +/// // writing. +/// file.flush()?; +/// +/// // Confirm the whole poem was written. +/// assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]); +/// Ok(()) +/// } +/// ``` +pub struct LineWriter { + inner: BufWriter, +} + +impl LineWriter { + /// Creates a new `LineWriter`. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use core2::io::LineWriter; + /// + /// fn main() -> core::result::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// Ok(()) + /// } + /// ``` + pub fn new(inner: W) -> LineWriter { + LineWriter { + inner: BufWriter::new(inner), + } + } + + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use core2::io::LineWriter; + /// + /// fn main() -> core::result::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// + /// let reference = file.get_ref(); + /// Ok(()) + /// } + /// ``` + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Gets a mutable reference to the underlying writer. + /// + /// Caution must be taken when calling methods on the mutable reference + /// returned as extra writes could corrupt the output stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use core2::io::LineWriter; + /// + /// fn main() -> core::result::Result<()> { + /// let file = File::create("poem.txt")?; + /// let mut file = LineWriter::new(file); + /// + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// Ok(()) + /// } + /// ``` + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Unwraps this `LineWriter`, returning the underlying writer. + /// + /// The internal buffer is written out before returning the writer. + /// + /// # Errors + /// + /// An [`Err`] will be returned if an error occurs while flushing the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use core2::io::LineWriter; + /// + /// fn main() -> core::result::Result<()> { + /// let file = File::create("poem.txt")?; + /// + /// let writer: LineWriter = LineWriter::new(file); + /// + /// let file: File = writer.into_inner()?; + /// Ok(()) + /// } + /// ``` + pub fn into_inner(self) -> core::result::Result>> { + self.inner + .into_inner() + .map_err(|IntoInnerError(buf, e)| IntoInnerError(LineWriter { inner: buf }, e)) + } +} + +impl Write for LineWriter { + fn write(&mut self, buf: &[u8]) -> Result { + LineWriterShim::new(&mut self.inner).write(buf) + } + + fn flush(&mut self) -> Result<()> { + self.inner.flush() + } + + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + LineWriterShim::new(&mut self.inner).write_all(buf) + } + + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { + LineWriterShim::new(&mut self.inner).write_fmt(fmt) + } +} + +impl fmt::Debug for LineWriter +where + W: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("LineWriter") + .field("writer", &self.inner.inner) + .field("buffer", &format_args!("{}/{}", self.inner.len, S)) + .finish() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/cursor.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/cursor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/cursor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/cursor.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,272 @@ +use super::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write}; +use core::cmp; + +/// A `Cursor` wraps an in-memory buffer and provides it with a +/// [`Seek`] implementation. +/// +/// `Cursor`s are used with in-memory buffers, anything implementing +/// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`], +/// allowing these buffers to be used anywhere you might use a reader or writer +/// that does actual I/O. +/// +/// The standard library implements some I/O traits on various types which +/// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and +/// `Cursor<`[`&[u8]`][bytes]`>`. +/// +/// # Examples +/// +/// We may want to write bytes to a [`File`] in our production +/// code, but use an in-memory buffer in our tests. We can do this with +/// `Cursor`: +/// +/// [bytes]: crate::slice +/// [`File`]: crate::fs::File +/// +/// ``` +/// use std::io::prelude::*; +/// use core2::io::{self, Seek, SeekFrom, Write}; +/// use std::fs::File; +/// +/// // a library function we've written +/// fn write_ten_bytes_at_end(writer: &mut W) -> io::Result<()> { +/// writer.seek(SeekFrom::End(-10))?; +/// +/// for i in 0..10 { +/// writer.write(&[i])?; +/// } +/// +/// // all went well +/// Ok(()) +/// } +/// +/// # #[cfg(feature = "std")] +/// # fn foo() -> io::Result<()> { +/// // Here's some code that uses this library function. +/// // +/// // We might want to use a BufReader here for efficiency, but let's +/// // keep this example focused. +/// let mut file = File::create("foo.txt").map_err(|e| io::Error::from(e))?; +/// +/// write_ten_bytes_at_end(&mut file)?; +/// # Ok(()) +/// # } +/// +/// // now let's write a test +/// #[test] +/// fn test_writes_bytes() { +/// // setting up a real File is much slower than an in-memory buffer, +/// // let's use a cursor instead +/// use core2::io::Cursor; +/// let mut buff = Cursor::new(vec![0; 15]); +/// +/// write_ten_bytes_at_end(&mut buff).unwrap(); +/// +/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +/// } +/// ``` +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Cursor { + inner: T, + pos: u64, +} + +impl Cursor { + /// Creates a new cursor wrapping the provided underlying in-memory buffer. + /// + /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`]) + /// is not empty. So writing to cursor starts with overwriting [`Vec`] + /// content, not with appending to it. + /// + /// # Examples + /// + /// ``` + /// use core2::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// ``` + pub fn new(inner: T) -> Cursor { + Cursor { pos: 0, inner } + } + + /// Consumes this cursor, returning the underlying value. + /// + /// # Examples + /// + /// ``` + /// use core2::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let vec = buff.into_inner(); + /// ``` + pub fn into_inner(self) -> T { + self.inner + } + + /// Gets a reference to the underlying value in this cursor. + /// + /// # Examples + /// + /// ``` + /// use core2::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_ref(); + /// ``` + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying value in this cursor. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying value as it may corrupt this cursor's position. + /// + /// # Examples + /// + /// ``` + /// use core2::io::Cursor; + /// + /// let mut buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_mut(); + /// ``` + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Returns the current position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Cursor, Seek, SeekFrom}; + /// use std::io::prelude::*; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.seek(SeekFrom::Current(2)).unwrap(); + /// assert_eq!(buff.position(), 2); + /// + /// buff.seek(SeekFrom::Current(-1)).unwrap(); + /// assert_eq!(buff.position(), 1); + /// ``` + pub fn position(&self) -> u64 { + self.pos + } + + /// Sets the position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use core2::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.set_position(2); + /// assert_eq!(buff.position(), 2); + /// + /// buff.set_position(4); + /// assert_eq!(buff.position(), 4); + /// ``` + pub fn set_position(&mut self, pos: u64) { + self.pos = pos; + } +} + +impl Seek for Cursor +where + T: AsRef<[u8]>, +{ + fn seek(&mut self, style: SeekFrom) -> Result { + let (base_pos, offset) = match style { + SeekFrom::Start(n) => { + self.pos = n; + return Ok(n); + } + SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), + SeekFrom::Current(n) => (self.pos, n), + }; + let new_pos = if offset >= 0 { + base_pos.checked_add(offset as u64) + } else { + base_pos.checked_sub((offset.wrapping_neg()) as u64) + }; + match new_pos { + Some(n) => { + self.pos = n; + Ok(self.pos) + } + None => Err(Error::new( + ErrorKind::InvalidInput, + "invalid seek to a negative or overflowing position", + )), + } + } +} + +impl Read for Cursor +where + T: AsRef<[u8]>, +{ + fn read(&mut self, buf: &mut [u8]) -> Result { + let n = Read::read(&mut self.fill_buf()?, buf)?; + self.pos += n as u64; + Ok(n) + } + + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + let n = buf.len(); + Read::read_exact(&mut self.fill_buf()?, buf)?; + self.pos += n as u64; + Ok(()) + } +} + +impl BufRead for Cursor +where + T: AsRef<[u8]>, +{ + fn fill_buf(&mut self) -> Result<&[u8]> { + let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); + Ok(&self.inner.as_ref()[(amt as usize)..]) + } + fn consume(&mut self, amt: usize) { + self.pos += amt as u64; + } +} + +// Non-resizing write implementation +#[inline] +fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> Result { + let pos = cmp::min(*pos_mut, slice.len() as u64); + let amt = (&mut slice[(pos as usize)..]).write(buf)?; + *pos_mut += amt as u64; + Ok(amt) +} + +impl Write for Cursor<&mut [u8]> { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + slice_write(&mut self.pos, self.inner, buf) + } + + #[inline] + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/error.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/error.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,458 @@ +use core::{convert::From, fmt, result}; + +/// A specialized [`Result`] type for I/O operations. +/// +/// This type is broadly used across [`std::io`] for any operation which may +/// produce an error. +/// +/// This typedef is generally used to avoid writing out [`io::Error`] directly and +/// is otherwise a direct mapping to [`Result`]. +/// +/// While usual Rust style is to import types directly, aliases of [`Result`] +/// often are not, to make it easier to distinguish between them. [`Result`] is +/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias +/// will generally use `io::Result` instead of shadowing the [prelude]'s import +/// of [`std::result::Result`][`Result`]. +/// +/// [`std::io`]: crate::io +/// [`io::Error`]: Error +/// [`Result`]: crate::result::Result +/// [prelude]: crate::prelude +/// +/// # Examples +/// +/// A convenience function that bubbles an `io::Result` to its caller: +/// +/// ``` +/// use core2::io; +/// +/// #[cfg(feature = "std")] +/// fn get_string() -> io::Result { +/// let mut buffer = String::new(); +/// +/// std::io::stdin().read_line(&mut buffer).map_err(|e| io::Error::from(e))?; +/// +/// Ok(buffer) +/// } +/// ``` +pub type Result = result::Result; + +/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and +/// associated traits. +/// +/// Errors mostly originate from the underlying OS, but custom instances of +/// `Error` can be created with crafted error messages and a particular value of +/// [`ErrorKind`]. +/// +/// [`Read`]: crate::io::Read +/// [`Write`]: crate::io::Write +/// [`Seek`]: crate::io::Seek +pub struct Error { + repr: Repr, +} + +impl crate::error::Error for Error {} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.repr, f) + } +} + +enum Repr { + Simple(ErrorKind), + Custom(Custom), +} + +#[derive(Debug)] +struct Custom { + kind: ErrorKind, + error: &'static str, +} + +/// A list specifying general categories of I/O error. +/// +/// This list is intended to grow over time and it is not recommended to +/// exhaustively match against it. +/// +/// It is used with the [`io::Error`] type. +/// +/// [`io::Error`]: Error +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +// #[allow(deprecated)] +#[non_exhaustive] +pub enum ErrorKind { + /// An entity was not found, often a file. + NotFound, + /// The operation lacked the necessary privileges to complete. + PermissionDenied, + /// The connection was refused by the remote server. + ConnectionRefused, + /// The connection was reset by the remote server. + ConnectionReset, + /// The connection was aborted (terminated) by the remote server. + ConnectionAborted, + /// The network operation failed because it was not connected yet. + NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + AddrNotAvailable, + /// The operation failed because a pipe was closed. + BrokenPipe, + /// An entity already exists, often a file. + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + WouldBlock, + /// A parameter was incorrect. + InvalidInput, + /// Data not valid for the operation were encountered. + /// + /// Unlike [`InvalidInput`], this typically means that the operation + /// parameters were valid, however the error was caused by malformed + /// input data. + /// + /// For example, a function that reads a file into a string will error with + /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: ErrorKind::InvalidInput + InvalidData, + /// The I/O operation's timeout expired, causing it to be canceled. + TimedOut, + /// An error returned when an operation could not be completed because a + /// call to [`write`] returned [`Ok(0)`]. + /// + /// This typically means that an operation could only succeed if it wrote a + /// particular number of bytes but only a smaller number of bytes could be + /// written. + /// + /// [`write`]: crate::io::Write::write + /// [`Ok(0)`]: Ok + WriteZero, + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + Interrupted, + /// Any I/O error not part of this list. + /// + /// Errors that are `Other` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Other` and to expect any additional characteristics, + /// e.g., a specific [`Error::raw_os_error`] return value. + Other, + + /// An error returned when an operation could not be completed because an + /// "end of file" was reached prematurely. + /// + /// This typically means that an operation could only succeed if it read a + /// particular number of bytes but only a smaller number of bytes could be + /// read. + UnexpectedEof, + + /// Any I/O error from the standard library that's not part of this list. + /// + /// Errors that are `Uncategorized` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Uncategorized`; use a wildcard match (`_`) instead. + #[doc(hidden)] + Uncategorized, +} + +impl ErrorKind { + pub(crate) fn as_str(&self) -> &'static str { + match *self { + ErrorKind::NotFound => "entity not found", + ErrorKind::PermissionDenied => "permission denied", + ErrorKind::ConnectionRefused => "connection refused", + ErrorKind::ConnectionReset => "connection reset", + ErrorKind::ConnectionAborted => "connection aborted", + ErrorKind::NotConnected => "not connected", + ErrorKind::AddrInUse => "address in use", + ErrorKind::AddrNotAvailable => "address not available", + ErrorKind::BrokenPipe => "broken pipe", + ErrorKind::AlreadyExists => "entity already exists", + ErrorKind::WouldBlock => "operation would block", + ErrorKind::InvalidInput => "invalid input parameter", + ErrorKind::InvalidData => "invalid data", + ErrorKind::TimedOut => "timed out", + ErrorKind::WriteZero => "write zero", + ErrorKind::Interrupted => "operation interrupted", + ErrorKind::Other => "other os error", + ErrorKind::UnexpectedEof => "unexpected end of file", + ErrorKind::Uncategorized => "uncategorized", + } + } +} + +#[cfg(feature = "std")] +impl From for ErrorKind { + /// Converts an [`std::io::ErrorKind`] into an [`ErrorKind`]. + /// + /// This conversion allocates a new error with a simple representation of error kind. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// let not_found = ErrorKind::from(std::io::ErrorKind::NotFound); + /// let err: Error = not_found.into(); + /// assert_eq!("entity not found", format!("{}", err)); + /// ``` + fn from(k: std::io::ErrorKind) -> Self { + match k { + std::io::ErrorKind::NotFound => ErrorKind::NotFound, + std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied, + std::io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused, + std::io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset, + std::io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted, + std::io::ErrorKind::NotConnected => ErrorKind::NotConnected, + std::io::ErrorKind::AddrInUse => ErrorKind::AddrInUse, + std::io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable, + std::io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe, + std::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists, + std::io::ErrorKind::WouldBlock => ErrorKind::WouldBlock, + std::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput, + std::io::ErrorKind::InvalidData => ErrorKind::InvalidData, + std::io::ErrorKind::TimedOut => ErrorKind::TimedOut, + std::io::ErrorKind::WriteZero => ErrorKind::WriteZero, + std::io::ErrorKind::Interrupted => ErrorKind::Interrupted, + std::io::ErrorKind::Other => ErrorKind::Other, + std::io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof, + _ => ErrorKind::Uncategorized, + } + } +} + +/// Intended for use for errors not exposed to the user, where allocating onto +/// the heap (for normal construction via Error::new) is too costly. +impl From for Error { + /// Converts an [`ErrorKind`] into an [`Error`]. + /// + /// This conversion allocates a new error with a simple representation of error kind. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// let not_found = ErrorKind::NotFound; + /// let error = Error::from(not_found); + /// assert_eq!("entity not found", format!("{}", error)); + /// ``` + #[inline] + fn from(kind: ErrorKind) -> Error { + Error { + repr: Repr::Simple(kind), + } + } +} + +#[cfg(feature = "std")] +impl From for Error { + /// Converts an [`std::io::ErrorKind`] into an [`Error`]. + /// + /// This conversion allocates a new error with a simple representation of error kind. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// let not_found = std::io::Error::from(std::io::ErrorKind::NotFound); + /// let error = Error::from(not_found); + /// assert_eq!("entity not found", format!("{}", error)); + /// ``` + #[inline] + fn from(err: std::io::Error) -> Self { + Self::from(ErrorKind::from(err.kind())) + } +} + +impl Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error.into_inner().unwrap()); + /// ``` + pub fn new(kind: ErrorKind, error: &'static str) -> Error { + Self::_new(kind, error.into()) + } + + fn _new(kind: ErrorKind, error: &'static str) -> Error { + Error { + repr: Repr::Custom(Custom { kind, error }), + } + } + + /// Returns a reference to the inner error wrapped by this error (if any). + /// + /// If this [`Error`] was constructed via [`new`] then this function will + /// return [`Some`], otherwise it will return [`None`]. + /// + /// [`new`]: Error::new + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// fn print_error(err: &Error) { + /// if let Some(inner_err) = err.get_ref() { + /// println!("Inner error: {:?}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// #[cfg(feature = "std")] + /// fn emit_error() { + /// // Will print "No inner error". + /// print_error(&Error::from(std::io::Error::last_os_error())); + /// // Will print "Inner error: ...". + /// print_error(&Error::new(ErrorKind::Other, "oh no!")); + /// } + /// + /// #[cfg(not(feature = "std"))] + /// fn emit_error() { + /// // Will print "No inner error". + /// print_error(&ErrorKind::Other.into()); + /// // Will print "Inner error: ...". + /// print_error(&Error::new(ErrorKind::Other, "oh no!")); + /// } + /// + /// fn main() { + /// emit_error(); + /// } + /// ``` + pub fn get_ref(&self) -> Option<&&'static str> { + match self.repr { + Repr::Simple(..) => None, + Repr::Custom(ref c) => Some(&c.error), + } + } + + /// Consumes the `Error`, returning its inner error (if any). + /// + /// If this [`Error`] was constructed via [`new`] then this function will + /// return [`Some`], otherwise it will return [`None`]. + /// + /// [`new`]: Error::new + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// if let Some(inner_err) = err.into_inner() { + /// println!("Inner error: {}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// #[cfg(feature = "std")] + /// fn emit_error() { + /// // Will print "No inner error". + /// print_error(std::io::Error::last_os_error().into()); + /// // Will print "Inner error: ...". + /// print_error(Error::new(ErrorKind::Other, "oh no!")); + /// } + /// + /// #[cfg(not(feature = "std"))] + /// fn emit_error() { + /// // Will print "No inner error". + /// print_error(ErrorKind::Other.into()); + /// // Will print "Inner error: ...". + /// print_error(Error::new(ErrorKind::Other, "oh no!")); + /// } + /// + /// fn main() { + /// emit_error(); + /// } + /// ``` + pub fn into_inner(self) -> Option<&'static str> { + match self.repr { + Repr::Simple(..) => None, + Repr::Custom(c) => Some(c.error), + } + } + + /// Returns the corresponding [`ErrorKind`] for this error. + /// + /// # Examples + /// + /// ``` + /// use core2::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// println!("{:?}", err.kind()); + /// } + /// + /// #[cfg(feature = "std")] + /// fn emit_error() { + /// // Will print "Other". + /// print_error(std::io::Error::last_os_error().into()); + /// // Will print "AddrInUse". + /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); + /// } + /// + /// #[cfg(not(feature = "std"))] + /// fn emit_error() { + /// // Will print "Other". + /// print_error(ErrorKind::Other.into()); + /// // Will print "AddrInUse". + /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); + /// } + /// + /// fn main() { + /// emit_error(); + /// } + /// ``` + pub fn kind(&self) -> ErrorKind { + match self.repr { + Repr::Custom(ref c) => c.kind, + Repr::Simple(kind) => kind, + } + } +} + +impl fmt::Debug for Repr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), + Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.repr { + Repr::Custom(ref c) => c.error.fmt(fmt), + Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), + } + } +} + +fn _assert_error_is_sync_send() { + fn _is_sync_send() {} + _is_sync_send::(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/impls.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/impls.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,176 @@ +use super::error::{Error, ErrorKind, Result}; +use super::traits::{BufRead, Read, Seek, SeekFrom, Write}; +use core::{cmp, fmt, mem}; + +// ============================================================================= +// Forwarding implementations + +impl Read for &mut R { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + (**self).read(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + (**self).read_exact(buf) + } +} + +impl Write for &mut W { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + (**self).write(buf) + } + + #[inline] + fn flush(&mut self) -> Result<()> { + (**self).flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { + (**self).write_fmt(fmt) + } +} + +impl Seek for &mut S { + #[inline] + fn seek(&mut self, pos: SeekFrom) -> Result { + (**self).seek(pos) + } +} + +impl BufRead for &mut B { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { + (**self).fill_buf() + } + + #[inline] + fn consume(&mut self, amt: usize) { + (**self).consume(amt) + } +} + +// ============================================================================= +// In-memory buffer implementations + +/// Read is implemented for `&[u8]` by copying from the slice. +/// +/// Note that reading updates the slice to point to the yet unread part. +/// The slice will be empty when EOF is reached. +impl Read for &[u8] { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + let amt = cmp::min(buf.len(), self.len()); + let (a, b) = self.split_at(amt); + + // First check if the amount of bytes we want to read is small: + // `copy_from_slice` will generally expand to a call to `memcpy`, and + // for a single byte the overhead is significant. + if amt == 1 { + buf[0] = a[0]; + } else { + buf[..amt].copy_from_slice(a); + } + + *self = b; + Ok(amt) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + if buf.len() > self.len() { + return Err(Error::new( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer", + )); + } + let (a, b) = self.split_at(buf.len()); + + // First check if the amount of bytes we want to read is small: + // `copy_from_slice` will generally expand to a call to `memcpy`, and + // for a single byte the overhead is significant. + if buf.len() == 1 { + buf[0] = a[0]; + } else { + buf.copy_from_slice(a); + } + + *self = b; + Ok(()) + } +} + +impl BufRead for &[u8] { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { + Ok(*self) + } + + #[inline] + fn consume(&mut self, amt: usize) { + *self = &self[amt..]; + } +} + +/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting +/// its data. +/// +/// Note that writing updates the slice to point to the yet unwritten part. +/// The slice will be empty when it has been completely overwritten. +impl Write for &mut [u8] { + #[inline] + fn write(&mut self, data: &[u8]) -> Result { + let amt = cmp::min(data.len(), self.len()); + let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); + a.copy_from_slice(&data[..amt]); + *self = b; + Ok(amt) + } + + #[inline] + fn write_all(&mut self, data: &[u8]) -> Result<()> { + if self.write(data)? == data.len() { + Ok(()) + } else { + Err(Error::new( + ErrorKind::WriteZero, + "failed to write whole buffer", + )) + } + } + + #[inline] + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} + +/// Write is implemented for `Vec` by appending to the vector. +/// The vector will grow as needed. +#[cfg(feature = "alloc")] +impl Write for alloc::vec::Vec { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/mod.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,26 @@ +#[cfg(feature = "nightly")] +mod buffered; +mod cursor; +mod error; +mod impls; +mod traits; +mod util; + +#[cfg(not(feature = "std"))] +pub use cursor::Cursor; +#[cfg(not(feature = "std"))] +pub use error::{Error, ErrorKind, Result}; +#[cfg(not(feature = "std"))] +pub use traits::{BufRead, Bytes, Chain, Read, Seek, SeekFrom, Take, Write}; + +#[cfg(feature = "std")] +pub use std::io::{ + BufRead, Bytes, Chain, Cursor, Error, ErrorKind, Read, Result, Seek, SeekFrom, Take, Write, +}; + +// Use this crate's implementation on both std and no_std +#[cfg(feature = "nightly")] +pub use buffered::{BufReader, BufWriter, LineWriter}; + +#[cfg(feature = "nightly")] +pub use util::copy; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/traits.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,1363 @@ +use super::error::{Error, ErrorKind, Result}; +use core::{cmp, fmt, slice}; + +#[cfg(feature = "alloc")] +pub use alloc::vec::Vec; + +#[cfg(feature = "alloc")] +struct Guard<'a> { + buf: &'a mut Vec, + len: usize, +} + +#[cfg(feature = "alloc")] +impl Drop for Guard<'_> { + fn drop(&mut self) { + unsafe { + self.buf.set_len(self.len); + } + } +} + +// This uses an adaptive system to extend the vector when it fills. We want to +// avoid paying to allocate and zero a huge chunk of memory if the reader only +// has 4 bytes while still making large reads if the reader does have a ton +// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every +// time is 4,500 times (!) slower than a default reservation size of 32 if the +// reader has a very small amount of data to return. +// +// Because we're extending the buffer with uninitialized data for trusted +// readers, we need to make sure to truncate that if any of this panics. +#[cfg(feature = "alloc")] +fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { + read_to_end_with_reservation(r, buf, |_| 32) +} + +#[cfg(feature = "alloc")] +fn read_to_end_with_reservation( + r: &mut R, + buf: &mut Vec, + mut reservation_size: F, +) -> Result +where + R: Read + ?Sized, + F: FnMut(&R) -> usize, +{ + let start_len = buf.len(); + let mut g = Guard { + len: buf.len(), + buf, + }; + loop { + if g.len == g.buf.len() { + unsafe { + // FIXME(danielhenrymantilla): #42788 + // + // - This creates a (mut) reference to a slice of + // _uninitialized_ integers, which is **undefined behavior** + // + // - Only the standard library gets to soundly "ignore" this, + // based on its privileged knowledge of unstable rustc + // internals; + g.buf.reserve(reservation_size(r)); + let capacity = g.buf.capacity(); + g.buf.set_len(capacity); + r.initializer().initialize(&mut g.buf[g.len..]); + } + } + + let buf = &mut g.buf[g.len..]; + match r.read(buf) { + Ok(0) => return Ok(g.len - start_len), + Ok(n) => { + // We can't allow bogus values from read. If it is too large, the returned vec could have its length + // set past its capacity, or if it overflows the vec could be shortened which could create an invalid + // string if this is called via read_to_string. + assert!(n <= buf.len()); + g.len += n; + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } +} + +/// The `Read` trait allows for reading bytes from a source. +/// +/// Implementors of the `Read` trait are called 'readers'. +/// +/// Readers are defined by one required method, [`read()`]. Each call to [`read()`] +/// will attempt to pull bytes from this source into a provided buffer. A +/// number of other methods are implemented in terms of [`read()`], giving +/// implementors a number of ways to read bytes while only needing to implement +/// a single method. +/// +/// Readers are intended to be composable with one another. Many implementors +/// throughout [`std::io`] take and provide types which implement the `Read` +/// trait. +/// +/// Please note that each call to [`read()`] may involve a system call, and +/// therefore, using something that implements [`BufRead`], such as +/// [`BufReader`], will be more efficient. +/// +/// # Examples +/// +/// [`File`]s implement `Read`: +/// +/// ```no_run +/// use std::io; +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; +/// let mut buffer = [0; 10]; +/// +/// // read up to 10 bytes +/// f.read(&mut buffer)?; +/// +/// let mut buffer = Vec::new(); +/// // read the whole file +/// f.read_to_end(&mut buffer)?; +/// +/// // read into a String, so that you don't need to do the conversion. +/// let mut buffer = String::new(); +/// f.read_to_string(&mut buffer)?; +/// +/// // and more! See the other methods for more details. +/// Ok(()) +/// } +/// ``` +/// +/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: +/// +/// ```no_run +/// # use std::io; +/// use std::io::prelude::*; +/// +/// fn main() -> io::Result<()> { +/// let mut b = "This string will be read".as_bytes(); +/// let mut buffer = [0; 10]; +/// +/// // read up to 10 bytes +/// b.read(&mut buffer)?; +/// +/// // etc... it works exactly as a File does! +/// Ok(()) +/// } +/// ``` +/// +/// [`read()`]: Read::read +/// [`&str`]: prim@str +/// [`std::io`]: self +/// [`File`]: crate::fs::File +/// [slice]: ../../std/primitive.slice.html +pub trait Read { + /// Pull some bytes from this source into the specified buffer, returning + /// how many bytes were read. + /// + /// This function does not provide any guarantees about whether it blocks + /// waiting for data, but if an object needs to block for a read and cannot, + /// it will typically signal this via an [`Err`] return value. + /// + /// If the return value of this method is [`Ok(n)`], then it must be + /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates + /// that the buffer `buf` has been filled in with `n` bytes of data from this + /// source. If `n` is `0`, then it can indicate one of two scenarios: + /// + /// 1. This reader has reached its "end of file" and will likely no longer + /// be able to produce bytes. Note that this does not mean that the + /// reader will *always* no longer be able to produce bytes. + /// 2. The buffer specified was 0 bytes in length. + /// + /// It is not an error if the returned value `n` is smaller than the buffer size, + /// even when the reader is not at the end of the stream yet. + /// This may happen for example because fewer bytes are actually available right now + /// (e. g. being close to end-of-file) or because read() was interrupted by a signal. + /// + /// No guarantees are provided about the contents of `buf` when this + /// function is called, implementations cannot rely on any property of the + /// contents of `buf` being true. It is recommended that *implementations* + /// only write data to `buf` instead of reading its contents. + /// + /// Correspondingly, however, *callers* of this method may not assume any guarantees + /// about how the implementation uses `buf`. The trait is safe to implement, + /// so it is possible that the code that's supposed to write to the buffer might also read + /// from it. It is your responsibility to make sure that `buf` is initialized + /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one + /// obtains via [`MaybeUninit`]) is not safe, and can lead to undefined behavior. + /// + /// [`MaybeUninit`]: crate::mem::MaybeUninit + /// + /// # Errors + /// + /// If this function encounters any form of I/O or other error, an error + /// variant will be returned. If an error is returned then it must be + /// guaranteed that no bytes were read. + /// + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read + /// operation should be retried if there is nothing else to do. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`Ok(n)`]: Ok + /// [`File`]: crate::fs::File + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; + /// + /// // read up to 10 bytes + /// let n = f.read(&mut buffer[..])?; + /// + /// println!("The bytes: {:?}", &buffer[..n]); + /// Ok(()) + /// } + /// ``` + fn read(&mut self, buf: &mut [u8]) -> Result; + + /// Read all bytes until EOF in this source, placing them into `buf`. + /// + /// All bytes read from this source will be appended to the specified buffer + /// `buf`. This function will continuously call [`read()`] to append more data to + /// `buf` until [`read()`] returns either [`Ok(0)`] or an error of + /// non-[`ErrorKind::Interrupted`] kind. + /// + /// If successful, this function will return the total number of bytes read. + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation + /// will continue. + /// + /// If any other read error is encountered then this function immediately + /// returns. Any bytes which have already been read will be appended to + /// `buf`. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`read()`]: Read::read + /// [`Ok(0)`]: Ok + /// [`File`]: crate::fs::File + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); + /// + /// // read the whole file + /// f.read_to_end(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + /// + /// (See also the [`std::fs::read`] convenience function for reading from a + /// file.) + /// + /// [`std::fs::read`]: crate::fs::read + #[cfg(feature = "alloc")] + fn read_to_end(&mut self, buf: &mut Vec) -> Result { + read_to_end(self, buf) + } + + /// Determines if this `Read`er can work with buffers of uninitialized + /// memory. + /// + /// The default implementation returns an initializer which will zero + /// buffers. + /// + /// If a `Read`er guarantees that it can work properly with uninitialized + /// memory, it should call [`Initializer::nop()`]. See the documentation for + /// [`Initializer`] for details. + /// + /// The behavior of this method must be independent of the state of the + /// `Read`er - the method only takes `&self` so that it can be used through + /// trait objects. + /// + /// # Safety + /// + /// This method is unsafe because a `Read`er could otherwise return a + /// non-zeroing `Initializer` from another `Read` type without an `unsafe` + /// block. + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::zeroing() + } + + /// Read the exact number of bytes required to fill `buf`. + /// + /// This function reads as many bytes as necessary to completely fill the + /// specified buffer `buf`. + /// + /// No guarantees are provided about the contents of `buf` when this + /// function is called, implementations cannot rely on any property of the + /// contents of `buf` being true. It is recommended that implementations + /// only write data to `buf` instead of reading its contents. The + /// documentation on [`read`] has a more detailed explanation on this + /// subject. + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation + /// will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// The contents of `buf` are unspecified in this case. + /// + /// If any other read error is encountered then this function immediately + /// returns. The contents of `buf` are unspecified in this case. + /// + /// If this function returns an error, it is unspecified how many bytes it + /// has read, but it will never read more than would be necessary to + /// completely fill the buffer. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`read`]: Read::read + /// [`File`]: crate::fs::File + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; + /// + /// // read exactly 10 bytes + /// f.read_exact(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { + while !buf.is_empty() { + match self.read(buf) { + Ok(0) => break, + Ok(n) => { + let tmp = buf; + buf = &mut tmp[n..]; + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { + Err(Error::new( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer", + )) + } else { + Ok(()) + } + } + + /// Creates a "by reference" adaptor for this instance of `Read`. + /// + /// The returned adaptor also implements `Read` and will simply borrow this + /// current reader. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`File`]: crate::fs::File + /// + /// ```no_run + /// use std::io; + /// use std::io::Read; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); + /// let mut other_buffer = Vec::new(); + /// + /// { + /// let reference = f.by_ref(); + /// + /// // read at most 5 bytes + /// reference.take(5).read_to_end(&mut buffer)?; + /// + /// } // drop our &mut reference so we can use f again + /// + /// // original file still usable, read the rest + /// f.read_to_end(&mut other_buffer)?; + /// Ok(()) + /// } + /// ``` + fn by_ref(&mut self) -> &mut Self + where + Self: Sized, + { + self + } + + /// Transforms this `Read` instance to an [`Iterator`] over its bytes. + /// + /// The returned type implements [`Iterator`] where the `Item` is + /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`. + /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`] + /// otherwise. EOF is mapped to returning [`None`] from this iterator. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`File`]: crate::fs::File + /// [`Result`]: crate::result::Result + /// [`io::Error`]: self::Error + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// + /// for byte in f.bytes() { + /// println!("{}", byte.unwrap()); + /// } + /// Ok(()) + /// } + /// ``` + fn bytes(self) -> Bytes + where + Self: Sized, + { + Bytes { inner: self } + } + + /// Creates an adaptor which will chain this stream with another. + /// + /// The returned `Read` instance will first read all bytes from this object + /// until EOF is encountered. Afterwards the output is equivalent to the + /// output of `next`. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`File`]: crate::fs::File + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f1 = File::open("foo.txt")?; + /// let mut f2 = File::open("bar.txt")?; + /// + /// let mut handle = f1.chain(f2); + /// let mut buffer = String::new(); + /// + /// // read the value into a String. We could use any Read method here, + /// // this is just one example. + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + fn chain(self, next: R) -> Chain + where + Self: Sized, + { + Chain { + first: self, + second: next, + done_first: false, + } + } + + /// Creates an adaptor which will read at most `limit` bytes from it. + /// + /// This function returns a new instance of `Read` which will read at most + /// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any + /// read errors will not count towards the number of bytes read and future + /// calls to [`read()`] may succeed. + /// + /// # Examples + /// + /// [`File`]s implement `Read`: + /// + /// [`File`]: crate::fs::File + /// [`Ok(0)`]: Ok + /// [`read()`]: Read::read + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 5]; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// + /// handle.read(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + fn take(self, limit: u64) -> Take + where + Self: Sized, + { + Take { inner: self, limit } + } +} + +/// A type used to conditionally initialize buffers passed to `Read` methods. +#[derive(Debug)] +pub struct Initializer(bool); + +impl Initializer { + /// Returns a new `Initializer` which will zero out buffers. + #[inline] + pub fn zeroing() -> Initializer { + Initializer(true) + } + + /// Returns a new `Initializer` which will not zero out buffers. + /// + /// # Safety + /// + /// This may only be called by `Read`ers which guarantee that they will not + /// read from buffers passed to `Read` methods, and that the return value of + /// the method accurately reflects the number of bytes that have been + /// written to the head of the buffer. + #[inline] + pub unsafe fn nop() -> Initializer { + Initializer(false) + } + + /// Indicates if a buffer should be initialized. + #[inline] + pub fn should_initialize(&self) -> bool { + self.0 + } + + /// Initializes a buffer if necessary. + #[inline] + pub fn initialize(&self, buf: &mut [u8]) { + if self.should_initialize() { + unsafe { core::ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } + } + } +} + +/// A trait for objects which are byte-oriented sinks. +/// +/// Implementors of the `Write` trait are sometimes called 'writers'. +/// +/// Writers are defined by two required methods, [`write`] and [`flush`]: +/// +/// * The [`write`] method will attempt to write some data into the object, +/// returning how many bytes were successfully written. +/// +/// * The [`flush`] method is useful for adaptors and explicit buffers +/// themselves for ensuring that all buffered data has been pushed out to the +/// 'true sink'. +/// +/// Writers are intended to be composable with one another. Many implementors +/// throughout [`std::io`] take and provide types which implement the `Write` +/// trait. +/// +/// [`write`]: Write::write +/// [`flush`]: Write::flush +/// [`std::io`]: self +/// +/// # Examples +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// fn main() -> std::io::Result<()> { +/// let data = b"some bytes"; +/// +/// let mut pos = 0; +/// let mut buffer = File::create("foo.txt")?; +/// +/// while pos < data.len() { +/// let bytes_written = buffer.write(&data[pos..])?; +/// pos += bytes_written; +/// } +/// Ok(()) +/// } +/// ``` +/// +/// The trait also provides convenience methods like [`write_all`], which calls +/// `write` in a loop until its entire input has been written. +/// +/// [`write_all`]: Write::write_all +pub trait Write { + /// Write a buffer into this writer, returning how many bytes were written. + /// + /// This function will attempt to write the entire contents of `buf`, but + /// the entire write may not succeed, or the write may also generate an + /// error. A call to `write` represents *at most one* attempt to write to + /// any wrapped object. + /// + /// Calls to `write` are not guaranteed to block waiting for data to be + /// written, and a write which would otherwise block can be indicated through + /// an [`Err`] variant. + /// + /// If the return value is [`Ok(n)`] then it must be guaranteed that + /// `n <= buf.len()`. A return value of `0` typically means that the + /// underlying object is no longer able to accept bytes and will likely not + /// be able to in the future as well, or that the buffer provided is empty. + /// + /// # Errors + /// + /// Each call to `write` may generate an I/O error indicating that the + /// operation could not be completed. If an error is returned then no bytes + /// in the buffer were written to this writer. + /// + /// It is **not** considered an error if the entire buffer could not be + /// written to this writer. + /// + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the + /// write operation should be retried if there is nothing else to do. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + /// + /// [`Ok(n)`]: Ok + fn write(&mut self, buf: &[u8]) -> Result; + + /// Flush this output stream, ensuring that all intermediately buffered + /// contents reach their destination. + /// + /// # Errors + /// + /// It is considered an error if not all bytes could be written due to + /// I/O errors or EOF being reached. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::io::BufWriter; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(File::create("foo.txt")?); + /// + /// buffer.write_all(b"some bytes")?; + /// buffer.flush()?; + /// Ok(()) + /// } + /// ``` + fn flush(&mut self) -> Result<()>; + + /// Attempts to write an entire buffer into this writer. + /// + /// This method will continuously call [`write`] until there is no more data + /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// returned. + /// + /// If the buffer contains no data, this will never call [`write`]. + /// + /// # Errors + /// + /// This function will return the first error of + /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns. + /// + /// [`write`]: Write::write + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// buffer.write_all(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { + while !buf.is_empty() { + match self.write(buf) { + Ok(0) => { + return Err(Error::new( + ErrorKind::WriteZero, + "failed to write whole buffer", + )); + } + Ok(n) => buf = &buf[n..], + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } + /// Writes a formatted string into this writer, returning any error + /// encountered. + /// + /// This method is primarily used to interface with the + /// [`format_args!()`] macro, but it is rare that this should + /// explicitly be called. The [`write!()`] macro should be favored to + /// invoke this method instead. + /// + /// This function internally uses the [`write_all`] method on + /// this trait and hence will continuously write data so long as no errors + /// are received. This also means that partial writes are not indicated in + /// this signature. + /// + /// [`write_all`]: Write::write_all + /// + /// # Errors + /// + /// This function will return any I/O error reported while formatting. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // this call + /// write!(buffer, "{:.*}", 2, 1.234567)?; + /// // turns into this: + /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; + /// Ok(()) + /// } + /// ``` + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { + // Create a shim which translates a Write to a fmt::Write and saves + // off I/O errors. instead of discarding them + struct Adaptor<'a, T: ?Sized + 'a> { + inner: &'a mut T, + error: Result<()>, + } + + impl fmt::Write for Adaptor<'_, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write_all(s.as_bytes()) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + let mut output = Adaptor { + inner: self, + error: Ok(()), + }; + match fmt::write(&mut output, fmt) { + Ok(()) => Ok(()), + Err(..) => { + // check if the error came from the underlying `Write` or not + if output.error.is_err() { + output.error + } else { + Err(Error::new(ErrorKind::Other, "formatter error")) + } + } + } + } + + /// Creates a "by reference" adaptor for this instance of `Write`. + /// + /// The returned adaptor also implements `Write` and will simply borrow this + /// current writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::Write; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// let reference = buffer.by_ref(); + /// + /// // we can use reference just like our original buffer + /// reference.write_all(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + fn by_ref(&mut self) -> &mut Self + where + Self: Sized, + { + self + } +} + +/// The `Seek` trait provides a cursor which can be moved within a stream of +/// bytes. +/// +/// The stream typically has a fixed size, allowing seeking relative to either +/// end or the current offset. +/// +/// # Examples +/// +/// [`File`]s implement `Seek`: +/// +/// [`File`]: crate::fs::File +/// +/// ```no_run +/// use std::io; +/// use std::io::prelude::*; +/// use std::fs::File; +/// use std::io::SeekFrom; +/// +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; +/// +/// // move the cursor 42 bytes from the start of the file +/// f.seek(SeekFrom::Start(42))?; +/// Ok(()) +/// } +/// ``` +pub trait Seek { + /// Seek to an offset, in bytes, in a stream. + /// + /// A seek beyond the end of a stream is allowed, but behavior is defined + /// by the implementation. + /// + /// If the seek operation completed successfully, + /// this method returns the new position from the start of the stream. + /// That position can be used later with [`SeekFrom::Start`]. + /// + /// # Errors + /// + /// Seeking to a negative offset is considered an error. + fn seek(&mut self, pos: SeekFrom) -> Result; +} + +/// Enumeration of possible methods to seek within an I/O object. +/// +/// It is used by the [`Seek`] trait. +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +pub enum SeekFrom { + /// Sets the offset to the provided number of bytes. + Start(u64), + + /// Sets the offset to the size of this object plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + End(i64), + + /// Sets the offset to the current position plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + Current(i64), +} + +/// An iterator over `u8` values of a reader. +/// +/// This struct is generally created by calling [`bytes`] on a reader. +/// Please see the documentation of [`bytes`] for more details. +/// +/// [`bytes`]: Read::bytes +#[derive(Debug)] +pub struct Bytes { + inner: R, +} + +impl Iterator for Bytes { + type Item = Result; + + fn next(&mut self) -> Option> { + let mut byte = 0; + loop { + return match self.inner.read(slice::from_mut(&mut byte)) { + Ok(0) => None, + Ok(..) => Some(Ok(byte)), + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => Some(Err(e)), + }; + } + } +} + +/// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it +/// to perform extra ways of reading. +/// +/// For example, reading line-by-line is inefficient without using a buffer, so +/// if you want to read by line, you'll need `BufRead`, which includes a +/// [`read_line`] method as well as a [`lines`] iterator. +/// +/// # Examples +/// +/// A locked standard input implements `BufRead`: +/// +/// ```no_run +/// use std::io; +/// use std::io::prelude::*; +/// +/// let stdin = io::stdin(); +/// for line in stdin.lock().lines() { +/// println!("{}", line.unwrap()); +/// } +/// ``` +/// +/// If you have something that implements [`Read`], you can use the [`BufReader` +/// type][`BufReader`] to turn it into a `BufRead`. +/// +/// For example, [`File`] implements [`Read`], but not `BufRead`. +/// [`BufReader`] to the rescue! +/// +/// [`File`]: crate::fs::File +/// [`read_line`]: BufRead::read_line +/// [`lines`]: BufRead::lines +/// +/// ```no_run +/// use std::io::{self, BufReader}; +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// fn main() -> io::Result<()> { +/// let f = File::open("foo.txt")?; +/// let f = BufReader::new(f); +/// +/// for line in f.lines() { +/// println!("{}", line.unwrap()); +/// } +/// +/// Ok(()) +/// } +/// ``` +pub trait BufRead: Read { + /// Returns the contents of the internal buffer, filling it with more data + /// from the inner reader if it is empty. + /// + /// This function is a lower-level call. It needs to be paired with the + /// [`consume`] method to function properly. When calling this + /// method, none of the contents will be "read" in the sense that later + /// calling `read` may return the same contents. As such, [`consume`] must + /// be called with the number of bytes that are consumed from this buffer to + /// ensure that the bytes are never returned twice. + /// + /// [`consume`]: BufRead::consume + /// + /// An empty buffer returned indicates that the stream has reached EOF. + /// + /// # Errors + /// + /// This function will return an I/O error if the underlying reader was + /// read, but returned an error. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`: + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// + /// let buffer = stdin.fill_buf().unwrap(); + /// + /// // work with buffer + /// println!("{:?}", buffer); + /// + /// // ensure the bytes we worked with aren't returned again later + /// let length = buffer.len(); + /// stdin.consume(length); + /// ``` + fn fill_buf(&mut self) -> Result<&[u8]>; + + /// Tells this buffer that `amt` bytes have been consumed from the buffer, + /// so they should no longer be returned in calls to `read`. + /// + /// This function is a lower-level call. It needs to be paired with the + /// [`fill_buf`] method to function properly. This function does + /// not perform any I/O, it simply informs this object that some amount of + /// its buffer, returned from [`fill_buf`], has been consumed and should + /// no longer be returned. As such, this function may do odd things if + /// [`fill_buf`] isn't called before calling it. + /// + /// The `amt` must be `<=` the number of bytes in the buffer returned by + /// [`fill_buf`]. + /// + /// # Examples + /// + /// Since `consume()` is meant to be used with [`fill_buf`], + /// that method's example includes an example of `consume()`. + /// + /// [`fill_buf`]: BufRead::fill_buf + fn consume(&mut self, amt: usize); +} + +/// Adaptor to chain together two readers. +/// +/// This struct is generally created by calling [`chain`] on a reader. +/// Please see the documentation of [`chain`] for more details. +/// +/// [`chain`]: Read::chain +pub struct Chain { + first: T, + second: U, + done_first: bool, +} + +impl Chain { + /// Consumes the `Chain`, returning the wrapped readers. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// Ok(()) + /// } + /// ``` + pub fn into_inner(self) -> (T, U) { + (self.first, self.second) + } + + /// Gets references to the underlying readers in this `Chain`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// Ok(()) + /// } + /// ``` + pub fn get_ref(&self) -> (&T, &U) { + (&self.first, &self.second) + } + + /// Gets mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// Ok(()) + /// } + /// ``` + pub fn get_mut(&mut self) -> (&mut T, &mut U) { + (&mut self.first, &mut self.second) + } +} + +impl fmt::Debug for Chain { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Chain") + .field("t", &self.first) + .field("u", &self.second) + .finish() + } +} + +impl Read for Chain { + fn read(&mut self, buf: &mut [u8]) -> Result { + if !self.done_first { + match self.first.read(buf)? { + 0 if !buf.is_empty() => self.done_first = true, + n => return Ok(n), + } + } + self.second.read(buf) + } + + unsafe fn initializer(&self) -> Initializer { + let initializer = self.first.initializer(); + if initializer.should_initialize() { + initializer + } else { + self.second.initializer() + } + } +} + +impl BufRead for Chain { + fn fill_buf(&mut self) -> Result<&[u8]> { + if !self.done_first { + match self.first.fill_buf()? { + buf if buf.is_empty() => { + self.done_first = true; + } + buf => return Ok(buf), + } + } + self.second.fill_buf() + } + + fn consume(&mut self, amt: usize) { + if !self.done_first { + self.first.consume(amt) + } else { + self.second.consume(amt) + } + } +} + +/// Reader adaptor which limits the bytes read from an underlying reader. +/// +/// This struct is generally created by calling [`take`] on a reader. +/// Please see the documentation of [`take`] for more details. +/// +/// [`take`]: Read::take +#[derive(Debug)] +pub struct Take { + inner: T, + limit: u64, +} + +impl Take { + /// Returns the number of bytes that can be read before this instance will + /// return EOF. + /// + /// # Note + /// + /// This instance may reach `EOF` after reading fewer bytes than indicated by + /// this method if the underlying [`Read`] instance reaches EOF. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let handle = f.take(5); + /// + /// println!("limit: {}", handle.limit()); + /// Ok(()) + /// } + /// ``` + pub fn limit(&self) -> u64 { + self.limit + } + + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); + /// + /// assert_eq!(handle.limit(), 10); + /// Ok(()) + /// } + /// ``` + pub fn set_limit(&mut self, limit: u64) { + self.limit = limit; + } + + /// Consumes the `Take`, returning the wrapped reader. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.into_inner(); + /// Ok(()) + /// } + /// ``` + pub fn into_inner(self) -> T { + self.inner + } + + /// Gets a reference to the underlying reader. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_ref(); + /// Ok(()) + /// } + /// ``` + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying reader. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_mut(); + /// Ok(()) + /// } + /// ``` + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } +} + +impl Read for Take { + fn read(&mut self, buf: &mut [u8]) -> Result { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(0); + } + + let max = cmp::min(buf.len() as u64, self.limit) as usize; + let n = self.inner.read(&mut buf[..max])?; + self.limit -= n as u64; + Ok(n) + } + + unsafe fn initializer(&self) -> Initializer { + self.inner.initializer() + } + + #[cfg(feature = "alloc")] + fn read_to_end(&mut self, buf: &mut Vec) -> Result { + // Pass in a reservation_size closure that respects the current value + // of limit for each read. If we hit the read limit, this prevents the + // final zero-byte read from allocating again. + read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize) + } +} + +impl BufRead for Take { + fn fill_buf(&mut self) -> Result<&[u8]> { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(&[]); + } + + let buf = self.inner.fill_buf()?; + let cap = cmp::min(buf.len() as u64, self.limit) as usize; + Ok(&buf[..cap]) + } + + fn consume(&mut self, amt: usize) { + // Don't let callers reset the limit by passing an overlarge value + let amt = cmp::min(amt as u64, self.limit) as usize; + self.limit -= amt as u64; + self.inner.consume(amt); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/util.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/io/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/io/util.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,40 @@ +#[cfg(feature = "nightly")] +use core::mem::MaybeUninit; + +#[cfg(feature = "nightly")] +use crate::io::{ErrorKind, Read, Write}; + +#[cfg(feature = "nightly")] +pub fn copy( + reader: &mut R, + writer: &mut W, +) -> crate::io::Result +where + R: Read, + W: Write, +{ + let mut buf = MaybeUninit::<[u8; S]>::uninit(); + // FIXME: #42788 + // + // - This creates a (mut) reference to a slice of + // _uninitialized_ integers, which is **undefined behavior** + // + // - Only the standard library gets to soundly "ignore" this, + // based on its privileged knowledge of unstable rustc + // internals; + unsafe { + reader.initializer().initialize(buf.assume_init_mut()); + } + + let mut written = 0; + loop { + let len = match reader.read(unsafe { buf.assume_init_mut() }) { + Ok(0) => return Ok(written), + Ok(len) => len, + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + }; + writer.write_all(unsafe { &buf.assume_init_ref()[..len] })?; + written += len as u64; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/src/lib.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,20 @@ +#![cfg_attr(feature = "nightly", feature(maybe_uninit_ref))] +#![cfg_attr(feature = "nightly", feature(never_type))] +#![cfg_attr(all(feature = "std", feature = "nightly"), feature(read_initializer))] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "std", allow(dead_code))] + +#[cfg(not(feature = "std"))] +pub mod error; + +#[cfg(feature = "std")] +pub use std::error as error; + +#[cfg(not(feature = "std"))] +pub mod io; + +#[cfg(feature = "std")] +pub use std::io as io; + +#[cfg(feature = "alloc")] +extern crate alloc; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/core2/tests/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/core2/tests/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/core2/tests/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/core2/tests/tests.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,501 @@ +use core::cmp; +use core2::io::{self as io, BufRead, Cursor, Read, Write}; + +// #[test] +// #[cfg_attr(target_os = "emscripten", ignore)] +// fn read_until() { +// let mut buf = Cursor::new(&b"12"[..]); +// let mut v = Vec::new(); +// assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); +// assert_eq!(v, b"12"); + +// let mut buf = Cursor::new(&b"1233"[..]); +// let mut v = Vec::new(); +// assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); +// assert_eq!(v, b"123"); +// v.truncate(0); +// assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); +// assert_eq!(v, b"3"); +// v.truncate(0); +// assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); +// assert_eq!(v, []); +// } + +// #[test] +// fn split() { +// let buf = Cursor::new(&b"12"[..]); +// let mut s = buf.split(b'3'); +// assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); +// assert!(s.next().is_none()); + +// let buf = Cursor::new(&b"1233"[..]); +// let mut s = buf.split(b'3'); +// assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); +// assert_eq!(s.next().unwrap().unwrap(), vec![]); +// assert!(s.next().is_none()); +// } + +// #[test] +// fn read_line() { +// let mut buf = Cursor::new(&b"12"[..]); +// let mut v = String::new(); +// assert_eq!(buf.read_line(&mut v).unwrap(), 2); +// assert_eq!(v, "12"); + +// let mut buf = Cursor::new(&b"12\n\n"[..]); +// let mut v = String::new(); +// assert_eq!(buf.read_line(&mut v).unwrap(), 3); +// assert_eq!(v, "12\n"); +// v.truncate(0); +// assert_eq!(buf.read_line(&mut v).unwrap(), 1); +// assert_eq!(v, "\n"); +// v.truncate(0); +// assert_eq!(buf.read_line(&mut v).unwrap(), 0); +// assert_eq!(v, ""); +// } + +// #[test] +// fn lines() { +// let buf = Cursor::new(&b"12\r"[..]); +// let mut s = buf.lines(); +// assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string()); +// assert!(s.next().is_none()); + +// let buf = Cursor::new(&b"12\r\n\n"[..]); +// let mut s = buf.lines(); +// assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); +// assert_eq!(s.next().unwrap().unwrap(), "".to_string()); +// assert!(s.next().is_none()); +// } + +// #[test] +// fn read_to_end() { +// let mut c = Cursor::new(&b""[..]); +// let mut v = Vec::new(); +// assert_eq!(c.read_to_end(&mut v).unwrap(), 0); +// assert_eq!(v, []); + +// let mut c = Cursor::new(&b"1"[..]); +// let mut v = Vec::new(); +// assert_eq!(c.read_to_end(&mut v).unwrap(), 1); +// assert_eq!(v, b"1"); + +// let cap = 1024 * 1024; +// let data = (0..cap).map(|i| (i / 3) as u8).collect::>(); +// let mut v = Vec::new(); +// let (a, b) = data.split_at(data.len() / 2); +// assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len()); +// assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len()); +// assert_eq!(v, data); +// } + +// #[test] +// fn read_to_string() { +// let mut c = Cursor::new(&b""[..]); +// let mut v = String::new(); +// assert_eq!(c.read_to_string(&mut v).unwrap(), 0); +// assert_eq!(v, ""); + +// let mut c = Cursor::new(&b"1"[..]); +// let mut v = String::new(); +// assert_eq!(c.read_to_string(&mut v).unwrap(), 1); +// assert_eq!(v, "1"); + +// let mut c = Cursor::new(&b"\xff"[..]); +// let mut v = String::new(); +// assert!(c.read_to_string(&mut v).is_err()); +// } + +#[test] +fn read_exact() { + let mut buf = [0; 4]; + + let mut c = Cursor::new(&b""[..]); + assert_eq!( + c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); + + let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..])); + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"1234"); + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"5678"); + assert_eq!( + c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); +} + +#[test] +fn read_exact_slice() { + let mut buf = [0; 4]; + + let mut c = &b""[..]; + assert_eq!( + c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); + + let mut c = &b"123"[..]; + assert_eq!( + c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); + // make sure the optimized (early returning) method is being used + assert_eq!(&buf, &[0; 4]); + + let mut c = &b"1234"[..]; + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"1234"); + + let mut c = &b"56789"[..]; + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"5678"); + assert_eq!(c, b"9"); +} + +#[test] +fn take_eof() { + struct R; + + impl Read for R { + fn read(&mut self, _: &mut [u8]) -> io::Result { + Err(io::Error::new(io::ErrorKind::Other, "")) + } + } + impl BufRead for R { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + Err(io::Error::new(io::ErrorKind::Other, "")) + } + fn consume(&mut self, _amt: usize) {} + } + + let mut buf = [0; 1]; + assert_eq!(0, R.take(0).read(&mut buf).unwrap()); + assert_eq!(b"", R.take(0).fill_buf().unwrap()); +} + +fn cmp_bufread(mut br1: Br1, mut br2: Br2, exp: &[u8]) { + let mut cat = Vec::new(); + loop { + let consume = { + let buf1 = br1.fill_buf().unwrap(); + let buf2 = br2.fill_buf().unwrap(); + let minlen = if buf1.len() < buf2.len() { + buf1.len() + } else { + buf2.len() + }; + assert_eq!(buf1[..minlen], buf2[..minlen]); + cat.extend_from_slice(&buf1[..minlen]); + minlen + }; + if consume == 0 { + break; + } + br1.consume(consume); + br2.consume(consume); + } + assert_eq!(br1.fill_buf().unwrap().len(), 0); + assert_eq!(br2.fill_buf().unwrap().len(), 0); + assert_eq!(&cat[..], &exp[..]) +} + +#[test] +fn chain_bufread() { + let testdata = b"ABCDEFGHIJKL"; + let chain1 = (&testdata[..3]) + .chain(&testdata[3..6]) + .chain(&testdata[6..9]) + .chain(&testdata[9..]); + let chain2 = (&testdata[..4]) + .chain(&testdata[4..8]) + .chain(&testdata[8..]); + cmp_bufread(chain1, chain2, &testdata[..]); +} + +// #[test] +// fn chain_zero_length_read_is_not_eof() { +// let a = b"A"; +// let b = b"B"; +// let mut s = String::new(); +// let mut chain = (&a[..]).chain(&b[..]); +// chain.read(&mut []).unwrap(); +// chain.read_to_string(&mut s).unwrap(); +// assert_eq!("AB", s); +// } + +// #[bench] +// #[cfg_attr(target_os = "emscripten", ignore)] +// fn bench_read_to_end(b: &mut test::Bencher) { +// b.iter(|| { +// let mut lr = repeat(1).take(10000000); +// let mut vec = Vec::with_capacity(1024); +// super::read_to_end(&mut lr, &mut vec) +// }); +// } + +// #[test] +// fn seek_len() -> io::Result<()> { +// let mut c = Cursor::new(vec![0; 15]); +// assert_eq!(c.stream_len()?, 15); + +// c.seek(SeekFrom::End(0))?; +// let old_pos = c.stream_position()?; +// assert_eq!(c.stream_len()?, 15); +// assert_eq!(c.stream_position()?, old_pos); + +// c.seek(SeekFrom::Start(7))?; +// c.seek(SeekFrom::Current(2))?; +// let old_pos = c.stream_position()?; +// assert_eq!(c.stream_len()?, 15); +// assert_eq!(c.stream_position()?, old_pos); + +// Ok(()) +// } + +// #[test] +// fn seek_position() -> io::Result<()> { +// // All `asserts` are duplicated here to make sure the method does not +// // change anything about the seek state. +// let mut c = Cursor::new(vec![0; 15]); +// assert_eq!(c.stream_position()?, 0); +// assert_eq!(c.stream_position()?, 0); + +// c.seek(SeekFrom::End(0))?; +// assert_eq!(c.stream_position()?, 15); +// assert_eq!(c.stream_position()?, 15); + +// c.seek(SeekFrom::Start(7))?; +// c.seek(SeekFrom::Current(2))?; +// assert_eq!(c.stream_position()?, 9); +// assert_eq!(c.stream_position()?, 9); + +// c.seek(SeekFrom::End(-3))?; +// c.seek(SeekFrom::Current(1))?; +// c.seek(SeekFrom::Current(-5))?; +// assert_eq!(c.stream_position()?, 8); +// assert_eq!(c.stream_position()?, 8); + +// Ok(()) +// } + +// A simple example reader which uses the default implementation of +// read_to_end. +struct ExampleSliceReader<'a> { + slice: &'a [u8], +} + +impl<'a> Read for ExampleSliceReader<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = cmp::min(self.slice.len(), buf.len()); + buf[..len].copy_from_slice(&self.slice[..len]); + self.slice = &self.slice[len..]; + Ok(len) + } +} + +// #[test] +// fn test_read_to_end_capacity() -> io::Result<()> { +// let input = &b"foo"[..]; + +// // read_to_end() generally needs to over-allocate, both for efficiency +// // and so that it can distinguish EOF. Assert that this is the case +// // with this simple ExampleSliceReader struct, which uses the default +// // implementation of read_to_end. Even though vec1 is allocated with +// // exactly enough capacity for the read, read_to_end will allocate more +// // space here. +// let mut vec1 = Vec::with_capacity(input.len()); +// ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; +// assert_eq!(vec1.len(), input.len()); +// assert!(vec1.capacity() > input.len(), "allocated more"); + +// // However, std::io::Take includes an implementation of read_to_end +// // that will not allocate when the limit has already been reached. In +// // this case, vec2 never grows. +// let mut vec2 = Vec::with_capacity(input.len()); +// ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?; +// assert_eq!(vec2.len(), input.len()); +// assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); + +// Ok(()) +// } + +// #[test] +// fn io_slice_mut_advance() { +// let mut buf1 = [1; 8]; +// let mut buf2 = [2; 16]; +// let mut buf3 = [3; 8]; +// let mut bufs = &mut [ +// IoSliceMut::new(&mut buf1), +// IoSliceMut::new(&mut buf2), +// IoSliceMut::new(&mut buf3), +// ][..]; + +// // Only in a single buffer.. +// bufs = IoSliceMut::advance(bufs, 1); +// assert_eq!(bufs[0].deref(), [1; 7].as_ref()); +// assert_eq!(bufs[1].deref(), [2; 16].as_ref()); +// assert_eq!(bufs[2].deref(), [3; 8].as_ref()); + +// // Removing a buffer, leaving others as is. +// bufs = IoSliceMut::advance(bufs, 7); +// assert_eq!(bufs[0].deref(), [2; 16].as_ref()); +// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); + +// // Removing a buffer and removing from the next buffer. +// bufs = IoSliceMut::advance(bufs, 18); +// assert_eq!(bufs[0].deref(), [3; 6].as_ref()); +// } + +// #[test] +// fn io_slice_mut_advance_empty_slice() { +// let empty_bufs = &mut [][..]; +// // Shouldn't panic. +// IoSliceMut::advance(empty_bufs, 1); +// } + +// #[test] +// fn io_slice_mut_advance_beyond_total_length() { +// let mut buf1 = [1; 8]; +// let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; + +// // Going beyond the total length should be ok. +// bufs = IoSliceMut::advance(bufs, 9); +// assert!(bufs.is_empty()); +// } + +// #[test] +// fn io_slice_advance() { +// let buf1 = [1; 8]; +// let buf2 = [2; 16]; +// let buf3 = [3; 8]; +// let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..]; + +// // Only in a single buffer.. +// bufs = IoSlice::advance(bufs, 1); +// assert_eq!(bufs[0].deref(), [1; 7].as_ref()); +// assert_eq!(bufs[1].deref(), [2; 16].as_ref()); +// assert_eq!(bufs[2].deref(), [3; 8].as_ref()); + +// // Removing a buffer, leaving others as is. +// bufs = IoSlice::advance(bufs, 7); +// assert_eq!(bufs[0].deref(), [2; 16].as_ref()); +// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); + +// // Removing a buffer and removing from the next buffer. +// bufs = IoSlice::advance(bufs, 18); +// assert_eq!(bufs[0].deref(), [3; 6].as_ref()); +// } + +// #[test] +// fn io_slice_advance_empty_slice() { +// let empty_bufs = &mut [][..]; +// // Shouldn't panic. +// IoSlice::advance(empty_bufs, 1); +// } + +// #[test] +// fn io_slice_advance_beyond_total_length() { +// let buf1 = [1; 8]; +// let mut bufs = &mut [IoSlice::new(&buf1)][..]; + +// // Going beyond the total length should be ok. +// bufs = IoSlice::advance(bufs, 9); +// assert!(bufs.is_empty()); +// } + +/// Create a new writer that reads from at most `n_bufs` and reads +/// `per_call` bytes (in total) per call to write. +fn test_writer() -> TestWriter { + TestWriter { + written: Vec::new(), + per_call: 2, + } +} + +struct TestWriter { + written: Vec, + per_call: usize, +} + +impl Write for TestWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + let n = self.per_call.min(buf.len()); + self.written.extend_from_slice(&buf[..n]); + Ok(n) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[test] +fn test_writer_read_from_one_buf() { + let mut writer = test_writer(); + + assert_eq!(writer.write(&[]).unwrap(), 0); + // assert_eq!(writer.write_vectored(&[]).unwrap(), 0); + + // Read at most 2 bytes. + assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2); + assert_eq!(writer.write(&[2, 2, 2]).unwrap(), 2); + + // Only read from first buf. + assert_eq!(writer.write(&[3]).unwrap(), 1); + + assert_eq!(writer.written, &[1, 1, 2, 2, 3]); +} + +// #[test] +// fn test_writer_read_from_multiple_bufs() { +// let mut writer = test_writer(3, 3); + +// // Read at most 3 bytes from two buffers. +// let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])]; +// assert_eq!(writer.write_vectored(bufs).unwrap(), 3); + +// // Read at most 3 bytes from three buffers. +// let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])]; +// assert_eq!(writer.write_vectored(bufs).unwrap(), 3); + +// assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]); +// } + +// #[test] +// fn test_write_all_vectored() { +// #[rustfmt::skip] // Becomes unreadable otherwise. +// let tests: Vec<(_, &'static [u8])> = vec![ +// (vec![], &[]), +// (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]), +// (vec![IoSlice::new(&[1])], &[1]), +// (vec![IoSlice::new(&[1, 2])], &[1, 2]), +// (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]), +// (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]), +// (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]), +// (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]), +// (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]), +// (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]), +// (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), +// (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), +// (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]), +// (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]), +// (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]), +// (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]), +// (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]), +// (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]), +// (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]), +// ]; + +// let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]; + +// for (n_bufs, per_call) in writer_configs.iter().copied() { +// for (mut input, wanted) in tests.clone().into_iter() { +// let mut writer = test_writer(n_bufs, per_call); +// assert!(writer.write_all_vectored(&mut *input).is_ok()); +// assert_eq!(&*writer.written, &*wanted); +// } +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"9016ecbd27290a1a62d928537c9ee912901c21e3505644eb51da432112e8c27d","Cargo.toml":"12903d32a56e22fc63a9810a1184f5e70c71a7f58fe9d3c3abd3ed5b5f66ffe8","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"904801faf3f1850328af8e1aa1047b9190cc22ed40df5c87f2d93d17f847ef67","README.md":"bc4339a8bfc78dc28ab4782cc539629bc6af72e724543f3e15d173c705e2977a","src/aarch64.rs":"ca05d0dca4bb1aad54c275934bf2761fecc92525aa045f333d55d74f23583af4","src/lib.rs":"1a192980dfc9a2658bea08a98d46f6819a0ffaca6544cabfa6870af09ae7d310","src/loongarch64.rs":"489db8bc4c3ffc3b89ae8ecf94181c5d456d139d66bb74403a597ee4cb58ca2c","src/miri.rs":"acf1a7e7ae31a1de07941084c6b589a2d4c6ea5f87012c811592c865d04c02cb","src/x86.rs":"b7627384419d2db09bc76df76d957e4c6a63d1d6b6c5f2b46456d09a20db6186","tests/aarch64.rs":"f6f0f55d821dbcac61e54cec8d35bf944cd09f90f3422eee2b6d55a1e9899635","tests/loongarch64.rs":"1b95140c68f673721699dcb40176540818641785f7863a99214bcad2014aa181","tests/x86.rs":"fcf476ca6ebd0845ab547cea4fe40c2ba2a2324c024264d9a86f666586f3a480"},"package":"53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"fde17a0f98ba043c572962a94d36df7454a66f34e4e810219b5e3f4967562b25","CHANGELOG.md":"9016ecbd27290a1a62d928537c9ee912901c21e3505644eb51da432112e8c27d","Cargo.toml":"12903d32a56e22fc63a9810a1184f5e70c71a7f58fe9d3c3abd3ed5b5f66ffe8","Cargo.toml.orig":"3beaa2274f7c796a01711512f75e27a96f62b628f3dee8841d6046dd0503cde2","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"904801faf3f1850328af8e1aa1047b9190cc22ed40df5c87f2d93d17f847ef67","README.md":"bc4339a8bfc78dc28ab4782cc539629bc6af72e724543f3e15d173c705e2977a","src/aarch64.rs":"ca05d0dca4bb1aad54c275934bf2761fecc92525aa045f333d55d74f23583af4","src/lib.rs":"1a192980dfc9a2658bea08a98d46f6819a0ffaca6544cabfa6870af09ae7d310","src/loongarch64.rs":"489db8bc4c3ffc3b89ae8ecf94181c5d456d139d66bb74403a597ee4cb58ca2c","src/miri.rs":"acf1a7e7ae31a1de07941084c6b589a2d4c6ea5f87012c811592c865d04c02cb","src/x86.rs":"b7627384419d2db09bc76df76d957e4c6a63d1d6b6c5f2b46456d09a20db6186","tests/aarch64.rs":"f6f0f55d821dbcac61e54cec8d35bf944cd09f90f3422eee2b6d55a1e9899635","tests/loongarch64.rs":"1b95140c68f673721699dcb40176540818641785f7863a99214bcad2014aa181","tests/x86.rs":"fcf476ca6ebd0845ab547cea4fe40c2ba2a2324c024264d9a86f666586f3a480"},"package":"53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5abf0fd47a5bb0def41648c321bd766453f81521" + }, + "path_in_vcs": "cpufeatures" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/cpufeatures/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/cpufeatures/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +[package] +name = "cpufeatures" +version = "0.2.12" +description = """ +Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, +with no_std support and support for mobile targets including Android and iOS +""" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/cpufeatures" +repository = "https://github.com/RustCrypto/utils" +keywords = ["cpuid", "target-feature"] +categories = ["hardware-support", "no-std"] +edition = "2018" +readme = "README.md" + +[target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] +libc = "0.2.149" + +[target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] +libc = "0.2.149" + +[target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies] +libc = "0.2.149" + +[target.aarch64-linux-android.dependencies] +libc = "0.2.149" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"809ce4c4c8f9e155db21c279572a2e3d8d324f94f65dabdcbc382e64eeb704c8","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"61d383b05b87d78f94d2937e2580cce47226d17823c0430fbcad09596537efcf","README.md":"4b1a2bfbbda9923f78565bd52bd68cd172a188482061b0d2d159ff1a3b57127d","benches/bench.rs":"fb71f17c9f472d0985aead2c71e4ac4f717e5a1eeedc2fbfe75de8709033542d","build.rs":"4ccc50c3da67eb27f0b622440d2b7aee2f73fa9c71884571f3c041122231d105","src/baseline.rs":"bbe8fe49ceccbf9749052fa9c2756cf95f0fc79a063e5d3b509e3600283464ea","src/combine.rs":"7147fc4002190d36d253ea5e194e0419035b087304bcb17887efe09a8a198815","src/lib.rs":"169fbc635e42ad7fe4e7c6361808797e71e79df7a60e25bea0cd13ba4304bf44","src/specialized/aarch64.rs":"b1fb41b7eaa40b95b9603c445f6e502d6d65ecfb70f9eef4bb90c49c41dfaca9","src/specialized/mod.rs":"267634816329f32d95b66e2fcc1a8eca6652334bddd454446f4d78b66470b06d","src/specialized/pclmulqdq.rs":"4a175c9bef6dd3ff20d4f0cd0e8da027fe9f2a4fddf1a87f8664d4fa8ae087e2","src/table.rs":"1a566a6311b32b654fa05b324301611e0866b10db63692b53e8c1b9b529d4c17"},"package":"b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"c1275ba80fd6a537d544d915a133e84fcbd6b09f33219e993d096376e0231504",".travis.yml":"84da55b3d6346a6b797b48698835090207f87babee61fbc0a19408c08562f3ea","Cargo.toml":"809ce4c4c8f9e155db21c279572a2e3d8d324f94f65dabdcbc382e64eeb704c8","Cargo.toml.orig":"bdc4885adc2e3788fd25c76e6a03f8e227fbd198a08f697da7a1893928e320df","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"61d383b05b87d78f94d2937e2580cce47226d17823c0430fbcad09596537efcf","README.md":"4b1a2bfbbda9923f78565bd52bd68cd172a188482061b0d2d159ff1a3b57127d","benches/bench.rs":"fb71f17c9f472d0985aead2c71e4ac4f717e5a1eeedc2fbfe75de8709033542d","build.rs":"4ccc50c3da67eb27f0b622440d2b7aee2f73fa9c71884571f3c041122231d105","src/baseline.rs":"bbe8fe49ceccbf9749052fa9c2756cf95f0fc79a063e5d3b509e3600283464ea","src/combine.rs":"7147fc4002190d36d253ea5e194e0419035b087304bcb17887efe09a8a198815","src/lib.rs":"169fbc635e42ad7fe4e7c6361808797e71e79df7a60e25bea0cd13ba4304bf44","src/specialized/aarch64.rs":"b1fb41b7eaa40b95b9603c445f6e502d6d65ecfb70f9eef4bb90c49c41dfaca9","src/specialized/mod.rs":"267634816329f32d95b66e2fcc1a8eca6652334bddd454446f4d78b66470b06d","src/specialized/pclmulqdq.rs":"4a175c9bef6dd3ff20d4f0cd0e8da027fe9f2a4fddf1a87f8664d4fa8ae087e2","src/table.rs":"1a566a6311b32b654fa05b324301611e0866b10db63692b53e8c1b9b529d4c17"},"package":"b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "309c5a39c1c284c42e56e885d5d0b22e7e2749cc" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/.travis.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +language: rust +services: docker +cache: + - cargo + +matrix: + include: + - rust: 1.46.0 # MSRV + - rust: stable + - rust: beta + - rust: nightly + - os: osx + # Tier 1 + - env: CROSS_TEST=i686-unknown-linux-gnu + # Tier 2 + - env: CROSS_TEST=aarch64-unknown-linux-gnu + - env: CROSS_CHECK=wasm32-unknown-unknown + +script: + - | + set -e + if [[ "$TRAVIS_RUST_VERSION" == nightly ]] + then + # Make sure the benchmarks compile + cargo build --benches --all + + export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0" + export RUST_BACKTRACE=1 + + # Run address sanitizer + RUSTFLAGS="-Z sanitizer=address" \ + cargo test --lib --target x86_64-unknown-linux-gnu + fi + - | + set -e + if [[ "$CROSS_CHECK" ]] + then + rustup target add $CROSS_CHECK + cargo check --target $CROSS_CHECK + cargo check --target $CROSS_CHECK --no-default-features + elif [[ "$CROSS_TEST" ]] + then + cargo install --force cross + cross test --target=$CROSS_TEST + cross check --target $CROSS_TEST --no-default-features + else + cargo test --no-fail-fast + cargo test --no-fail-fast --release + cargo check --no-default-features + fi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crc32fast/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crc32fast/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +[package] +name = "crc32fast" +version = "1.4.0" +license = "MIT OR Apache-2.0" +authors = [ + "Sam Rijs ", + "Alex Crichton " +] +description = "Fast, SIMD-accelerated CRC32 (IEEE) checksum computation" +repository = "https://github.com/srijs/rust-crc32fast" +readme = "README.md" +keywords = ["checksum", "crc", "crc32", "simd", "fast"] + +[dependencies] +cfg-if = "1.0" + +[dev-dependencies] +bencher = "0.1" +quickcheck = { version = "1.0", default-features = false } +rand = "0.8" + +[features] +default = ["std"] +std = [] +nightly = [] + +[[bench]] +name = "bench" +harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"b0fe0b71bd530094d7aaf823bdfd5984fe4a2feea6fec3ae62975bcaed562d8c","Cargo.toml":"7c0f037ccc56d911f51bda22c475aa094e757baeb23e723bd2c2c02f324d117e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"86445da156ad68ea1d1f2dc49a3cef942ccc377ff56316aefe89732ded763aba","src/deque.rs":"54ef2940700056eff8f099e5efed10838cdf5c3ec1de91659ffcb19115fa3593","src/lib.rs":"b9899494f3933c041b059fd920fecb3226f5e91b06c3736b19501799289633e1","tests/fifo.rs":"3d98e0d4ca7cfddf10708b71642cf1ff05543d067ad837e48401d63cc31c0a18","tests/injector.rs":"fb054ef9fcac5f12e08b7b3451f370b96ab7589d32ef5c02e25958a473c45519","tests/lifo.rs":"57abdb3fc5920a422f785ba308b658bdc5400947532eeffb799f2395a2061549","tests/steal.rs":"cdf588cc13eeb275ef1231eb18e3245faca7a2d054fa6527bfdba2a34bc8f7bf"},"package":"613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ddf17913013fc6727900a9e5048ea654a59b873e155437207eabcc7d2dd589b9","CHANGELOG.md":"b0fe0b71bd530094d7aaf823bdfd5984fe4a2feea6fec3ae62975bcaed562d8c","Cargo.toml":"7c0f037ccc56d911f51bda22c475aa094e757baeb23e723bd2c2c02f324d117e","Cargo.toml.orig":"903b0364df63e260b4c724c41d48c9832bb277e40b187cdf70425fd4e9b51f59","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"86445da156ad68ea1d1f2dc49a3cef942ccc377ff56316aefe89732ded763aba","src/deque.rs":"54ef2940700056eff8f099e5efed10838cdf5c3ec1de91659ffcb19115fa3593","src/lib.rs":"b9899494f3933c041b059fd920fecb3226f5e91b06c3736b19501799289633e1","tests/fifo.rs":"3d98e0d4ca7cfddf10708b71642cf1ff05543d067ad837e48401d63cc31c0a18","tests/injector.rs":"fb054ef9fcac5f12e08b7b3451f370b96ab7589d32ef5c02e25958a473c45519","tests/lifo.rs":"57abdb3fc5920a422f785ba308b658bdc5400947532eeffb799f2395a2061549","tests/steal.rs":"cdf588cc13eeb275ef1231eb18e3245faca7a2d054fa6527bfdba2a34bc8f7bf"},"package":"613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9c3182abebb36bdc9446d75d4644190fef70fa01" + }, + "path_in_vcs": "crossbeam-deque" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-deque/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-deque/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +[package] +name = "crossbeam-deque" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md +# - Create "crossbeam-deque-X.Y.Z" git tag +version = "0.8.5" +edition = "2021" +rust-version = "1.61" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque" +description = "Concurrent work-stealing deque" +keywords = ["chase-lev", "lock-free", "scheduler", "scheduling"] +categories = ["algorithms", "concurrency", "data-structures"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +# +# NOTE: Disabling `std` feature is not supported yet. +std = ["crossbeam-epoch/std", "crossbeam-utils/std"] + +[dependencies] +crossbeam-epoch = { version = "0.9.17", path = "../crossbeam-epoch", default-features = false } +crossbeam-utils = { version = "0.8.18", path = "../crossbeam-utils", default-features = false } + +[dev-dependencies] +rand = "0.8" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"678c7c5b4e522345076d63e8f24f7ab4dc9f6b7428ca2f665e4017f7ef24a087","Cargo.lock":"fd85f51f6b4a2dabbb41d9f96775abd21d89221fa01c154afac970c539022f17","Cargo.toml":"cfbceb820c7a1519351826839decd3ff1b1ad54ef2c4dfc4d2c9f173e4726046","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"6ba897c52496a66705df72da33dea5f6e0ce5caa87c4ff073b0faf4e05516dad","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","src/atomic.rs":"48b8b02d1e0235b2d87342c13c09d778fba076f79addef32294bed5b8f67b21a","src/collector.rs":"df05c7573413a8f3ac933de7cf941d24bd0ca7341f5923dcad2f811a020c49eb","src/default.rs":"8196e9a2a7a43fdd668177585ba1d4deaec2d16a8a9532f819e4d9afd64ca73d","src/deferred.rs":"092c49e65d5f0ccad8c868b9bcaf431b580c98b7efed98c3797d82d0b9d0c471","src/epoch.rs":"e6813975198df667423c7e1911f7a0f5cb3a917e56080eecd6250d9cca7af950","src/guard.rs":"8db7a20503f55e9e29fc1cf33f99522ec0a5873683ab16638e0e55c917bfc30a","src/internal.rs":"74a15b34b235ab428ffa41cb3a01930e29e3f91e35a288f8f6e0c3c2f56e63f6","src/lib.rs":"3f81f1727c3f74114fbd2f9225a4899834fc254f1444f7c7355901c8fd755494","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/queue.rs":"d4ad500501c52a90b6624dc31196793be09bd19e9c298d5dd7b3ae37bee6b6a8","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"419f1b11148246c8db81f32a3476d51490dd1d5251d343c42a3a66c4b7c4638c","CHANGELOG.md":"4c9eb194b40755d85bc51cad9d1b8ccec3136e0abacf364c6e579128c8632aab","Cargo.lock":"877dfecb029677e7c4f08c55f171c77a81f8572ace18110450611aa58faedc8a","Cargo.toml":"aa33b807f5f74c0336045aecd27e90f9f4c8e0fceceb3967fdc154237b76c3a6","Cargo.toml.orig":"09f371f8080f375812e8c8a9ead76bb33d85c25e8bacd8c8803eef3f30d047ac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"6ba897c52496a66705df72da33dea5f6e0ce5caa87c4ff073b0faf4e05516dad","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","build.rs":"e40cf96d7d7b1650f9f53a3f578633a178324dbea1d905b3f71a75b45d3982a1","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","src/atomic.rs":"d738c357e6cc2ddc0b744117e98c21362097ffa5cab1e268df090b7c09c7534d","src/collector.rs":"12c6a00496fd702facaff3efdc993f326049d2bbb21fb2c9db1b8ffe6f54cf69","src/default.rs":"a153392422d2a473afb01873d83c8d92f34a3bab5dde2f3743d916acce36f9b9","src/deferred.rs":"5ad2032c40f96e32f3bab367c843c3091c4300402e938217d2706070f20c6811","src/epoch.rs":"65d910a683413a8939a4c3c2dfd88a5e05b6f4e8f7a26a0abdaed775c7d9e1f2","src/guard.rs":"555bb756fe0c422d7f778121226834158cd143c664211a955662c789c867d6d1","src/internal.rs":"75db50474a2b17c1808746917299fe9bba6657c6d409ada1794c596d8dc0961f","src/lib.rs":"4c7266a7f5f480aed776a78fe221d95e712731527555b78270eda0f44c4ebb44","src/sync/list.rs":"6950177b01fa6f51d3f4ca22f3ce4e77143eed28bec04579ecc8a8599ab17031","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/queue.rs":"0324e9b07dfd0f76ba0058395a4b9ae4b4a6e5ab0aec41d98edab7864bac3157","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "239bae00257967a109911b9ebe7c0554d6333501" + }, + "path_in_vcs": "crossbeam-epoch" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,15 @@ +# Version 0.9.20 + +- Fix invalid pointer dereference in `fmt::Pointer` impl for `Atomic`/`Shared` when the underlying pointer is invalid. This fixes unsoundness that was not fully addressed in 0.9.19's fix. (#1276) + +# Version 0.9.19 + +- Fix null pointer dereference in `fmt::Pointer` impl for `Atomic`/`Shared` when it is a null pointer. (#1273) +- Fix return value of `Atomic::fetch_update`. (#1197) +- Improve compatibility with ThreadSanitizer. (#998) +- Allow unsized types in `Guard::defer_destroy`. (#1201) +- Use 64-bit integer for epoch representation on 32-bit platforms if `AtomicU64` is available. (#1230) + # Version 0.9.18 - Remove dependency on `cfg-if`. (#1072) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -4,31 +4,32 @@ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ - "libc", + "find-msvc-tools", + "shlex", ] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" dependencies = [ "crossbeam-utils", "loom", @@ -37,32 +38,39 @@ [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" dependencies = [ - "cfg-if", "loom", ] [[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] name = "generator" -version = "0.7.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" dependencies = [ "cc", + "cfg-if", "libc", "log", "rustversion", - "windows", + "windows-link", + "windows-result", ] [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -71,27 +79,27 @@ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "log" -version = "0.4.20" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" [[package]] name = "loom" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e045d70ddfbc984eacfa964ded019534e8f6cbf36f6410aee0ed5cefa5a9175" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ "cfg-if", "generator", @@ -102,76 +110,72 @@ [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] name = "memchr" -version = "2.7.1" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha", @@ -198,54 +202,27 @@ ] [[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scoped-tls" @@ -263,16 +240,22 @@ ] [[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] name = "smallvec" -version = "1.11.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -281,41 +264,28 @@ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] [[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -334,14 +304,14 @@ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -352,106 +322,62 @@ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets", + "windows-link", ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "zerocopy" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "75726053136156d419e285b9b7eddaaea9e3fea6ce32eed44a89901f0bd98de1" +dependencies = [ + "zerocopy-derive", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "zerocopy-derive" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "4714fd92cf900833d49538023a9b3915155210801d1c1169eba513b2addefd71" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -13,7 +13,13 @@ edition = "2021" rust-version = "1.61" name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Epoch-based garbage collection" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch" readme = "README.md" @@ -31,13 +37,6 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" -[dependencies.crossbeam-utils] -version = "0.8.18" -default-features = false - -[dev-dependencies.rand] -version = "0.8" - [features] alloc = [] default = ["std"] @@ -51,7 +50,54 @@ "crossbeam-utils/std", ] +[lib] +name = "crossbeam_epoch" +path = "src/lib.rs" + +[[example]] +name = "sanitize" +path = "examples/sanitize.rs" + +[[test]] +name = "loom" +path = "tests/loom.rs" + +[[bench]] +name = "defer" +path = "benches/defer.rs" + +[[bench]] +name = "flush" +path = "benches/flush.rs" + +[[bench]] +name = "pin" +path = "benches/pin.rs" + +[dependencies.crossbeam-utils] +version = "0.8.18" +default-features = false + +[dev-dependencies.rand] +version = "0.8" + [target."cfg(crossbeam_loom)".dependencies.loom-crate] version = "0.7.1" optional = true package = "loom" + +[lints.clippy.declare_interior_mutable_const] +level = "allow" +priority = 1 + +[lints.clippy.lint_groups_priority] +level = "allow" +priority = 1 + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(crossbeam_loom)", + "cfg(crossbeam_sanitize)", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +[package] +name = "crossbeam-epoch" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md (when increasing major or minor version) +# - Run './tools/publish.sh crossbeam-epoch ' +version = "0.9.20" +edition = "2021" +rust-version = "1.61" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch" +description = "Epoch-based garbage collection" +keywords = ["lock-free", "rcu", "atomic", "garbage"] +categories = ["concurrency", "memory-management", "no-std"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +std = ["alloc", "crossbeam-utils/std"] + +# Enable to use APIs that require `alloc`. +# This is enabled by default and also enabled if the `std` feature is enabled. +# +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. +alloc = [] + +# These features are no longer used. +# TODO: remove in the next major version. +# Enable to use of unstable functionality. +# This is disabled by default and requires recent nightly compiler. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +nightly = ["crossbeam-utils/nightly"] + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +loom = ["loom-crate", "crossbeam-utils/loom"] + +[dependencies] +crossbeam-utils = { version = "0.8.18", path = "../crossbeam-utils", default-features = false } + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +[target.'cfg(crossbeam_loom)'.dependencies] +loom-crate = { package = "loom", version = "0.7.1", optional = true } + +[dev-dependencies] +rand = "0.8" + +[lints] +workspace = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/build.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +// The rustc-cfg emitted by the build script are *not* public API. + +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rustc-check-cfg=cfg(crossbeam_sanitize_thread)"); + + // `cfg(sanitize = "..")` is not stabilized. + let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); + if sanitize.contains("thread") { + println!("cargo:rustc-cfg=crossbeam_sanitize_thread"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/atomic.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/atomic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/atomic.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/atomic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -232,7 +232,6 @@ /// along with pointer as in `Box<[T]>`). /// /// Elements are not present in the type, but they will be in the allocation. -/// ``` #[repr(C)] struct Array { /// The number of elements (not the number of bytes). @@ -635,7 +634,7 @@ let mut prev = self.load(fail_order, guard); while let Some(next) = func(prev) { match self.compare_exchange_weak(prev, next, set_order, fail_order, guard) { - Ok(shared) => return Ok(shared), + Ok(_result) => return Ok(prev), Err(next_prev) => prev = next_prev.current, } } @@ -943,7 +942,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let data = self.data.load(Ordering::SeqCst); let (raw, _) = decompose_tag::(data); - fmt::Pointer::fmt(&(unsafe { T::deref(raw) as *const _ }), f) + fmt::Pointer::fmt(&(raw as *const ()), f) } } @@ -1662,7 +1661,8 @@ impl fmt::Pointer for Shared<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&(unsafe { self.deref() as *const _ }), f) + let (raw, _) = decompose_tag::(self.data); + fmt::Pointer::fmt(&(raw as *const ()), f) } } @@ -1674,8 +1674,8 @@ #[cfg(all(test, not(crossbeam_loom)))] mod tests { - use super::{Owned, Shared}; - use std::mem::MaybeUninit; + use super::{Atomic, Owned, Shared}; + use std::{format, mem::MaybeUninit}; #[test] fn valid_tag_i8() { @@ -1695,8 +1695,22 @@ #[test] fn array_init() { - let owned = Owned::<[MaybeUninit]>::init(10); - let arr: &[MaybeUninit] = &owned; + let mut owned = Owned::<[MaybeUninit]>::init(10); + let arr: &mut [MaybeUninit] = &mut owned; + arr[arr.len() - 1].write(20); assert_eq!(arr.len(), 10); } + + #[test] + fn format_null() { + let atomic = Atomic::::null(); + assert_eq!(format!("{atomic:p}"), "0x0"); + let atomic = Atomic::<[MaybeUninit]>::null(); + assert_eq!(format!("{atomic:p}"), "0x0"); + + let shared = Shared::::null(); + assert_eq!(format!("{shared:p}"), "0x0"); + let shared = Shared::<[MaybeUninit]>::null(); + assert_eq!(format!("{shared:p}"), "0x0"); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/collector.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/collector.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/collector.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/collector.rs 2006-07-24 01:21:28.000000000 +0000 @@ -113,6 +113,7 @@ mod tests { use std::mem::ManuallyDrop; use std::sync::atomic::{AtomicUsize, Ordering}; + use std::vec::Vec; use crossbeam_utils::thread; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/default.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/default.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/default.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/default.rs 2006-07-24 01:21:28.000000000 +0000 @@ -76,7 +76,7 @@ } } - thread_local! { + std::thread_local! { static FOO: Foo = const { Foo }; } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/deferred.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/deferred.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/deferred.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/deferred.rs 2006-07-24 01:21:28.000000000 +0000 @@ -90,8 +90,11 @@ #[cfg(all(test, not(crossbeam_loom)))] mod tests { use super::Deferred; + use std::boxed::Box; use std::cell::Cell; use std::convert::identity; + use std::string::ToString; + use std::vec; #[test] fn on_stack() { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/epoch.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/epoch.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/epoch.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/epoch.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,7 +7,23 @@ //! If an object became garbage in some epoch, then we can be sure that after two advancements no //! participant will hold a reference to it. That is the crux of safe memory reclamation. -use crate::primitive::sync::atomic::{AtomicUsize, Ordering}; +use crate::primitive::sync::atomic::Ordering; + +// Ideally, we want to always use AtomicU64, but since it is not available on all platforms, +// we only use it when it is available for now. +// TODO: On platforms where AtomicU64 is unavailable, we may want to use AtomicCell instead of AtomicUsize. +#[cfg(target_has_atomic = "64")] +type AtomicEpochRepr = crate::primitive::sync::atomic::AtomicU64; +#[cfg(not(target_has_atomic = "64"))] +type AtomicEpochRepr = crate::primitive::sync::atomic::AtomicUsize; +#[cfg(target_has_atomic = "64")] +type EpochRepr = u64; +#[cfg(not(target_has_atomic = "64"))] +type EpochRepr = usize; +#[cfg(target_has_atomic = "64")] +type EpochReprSigned = i64; +#[cfg(not(target_has_atomic = "64"))] +type EpochReprSigned = isize; /// An epoch that can be marked as pinned or unpinned. /// @@ -16,7 +32,7 @@ #[derive(Copy, Clone, Default, Debug, Eq, PartialEq)] pub(crate) struct Epoch { /// The least significant bit is set if pinned. The rest of the bits hold the epoch. - data: usize, + data: EpochRepr, } impl Epoch { @@ -30,11 +46,11 @@ /// /// Internally, epochs are represented as numbers in the range `(isize::MIN / 2) .. (isize::MAX /// / 2)`, so the returned distance will be in the same interval. - pub(crate) fn wrapping_sub(self, rhs: Self) -> isize { + pub(crate) fn wrapping_sub(self, rhs: Self) -> EpochReprSigned { // The result is the same with `(self.data & !1).wrapping_sub(rhs.data & !1) as isize >> 1`, // because the possible difference of LSB in `(self.data & !1).wrapping_sub(rhs.data & !1)` // will be ignored in the shift operation. - self.data.wrapping_sub(rhs.data & !1) as isize >> 1 + self.data.wrapping_sub(rhs.data & !1) as EpochReprSigned >> 1 } /// Returns `true` if the epoch is marked as pinned. @@ -75,15 +91,15 @@ pub(crate) struct AtomicEpoch { /// Since `Epoch` is just a wrapper around `usize`, an `AtomicEpoch` is similarly represented /// using an `AtomicUsize`. - data: AtomicUsize, + data: AtomicEpochRepr, } impl AtomicEpoch { /// Creates a new atomic epoch. #[inline] pub(crate) fn new(epoch: Epoch) -> Self { - let data = AtomicUsize::new(epoch.data); - AtomicEpoch { data } + let data = AtomicEpochRepr::new(epoch.data); + Self { data } } /// Loads a value from the atomic epoch. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/guard.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/guard.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/guard.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/guard.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ use core::fmt; use core::mem; -use crate::atomic::Shared; +use crate::atomic::{Pointable, Shared}; use crate::collector::Collector; use crate::deferred::Deferred; use crate::internal::Local; @@ -265,7 +265,7 @@ /// } /// # unsafe { drop(a.into_owned()); } // avoid leak /// ``` - pub unsafe fn defer_destroy(&self, ptr: Shared<'_, T>) { + pub unsafe fn defer_destroy(&self, ptr: Shared<'_, T>) { self.defer_unchecked(move || ptr.into_owned()); } @@ -273,7 +273,7 @@ /// global cache. /// /// Call this method after deferring execution of a function if you want to get it executed as - /// soon as possible. Flushing will make sure it is residing in in the global cache, so that + /// soon as possible. Flushing will make sure it is residing in the global cache, so that /// any thread has a chance of taking the function and executing it. /// /// If this method is called from an [`unprotected`] guard, it is a no-op (nothing happens). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/internal.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/internal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/internal.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/internal.rs 2006-07-24 01:21:28.000000000 +0000 @@ -229,6 +229,11 @@ let global_epoch = self.epoch.load(Ordering::Relaxed); atomic::fence(Ordering::SeqCst); + // For ThreadSanitizer that does not understand fences, we simulate the equivalent effect. + // It is unfortunate that allocation is required, but without it, synchronization might + // occur in cases where it should not, potentially causing false positives. + #[cfg(crossbeam_sanitize_thread)] + let mut locals = alloc::vec![]; // TODO(stjepang): `Local`s are stored in a linked list because linked lists are fairly // easy to implement in a lock-free manner. However, traversal can be slow due to cache // misses and data dependencies. We should experiment with other data structures as well. @@ -248,9 +253,17 @@ if local_epoch.is_pinned() && local_epoch.unpinned() != global_epoch { return global_epoch; } + + #[cfg(crossbeam_sanitize_thread)] + locals.push(local); } } } + #[cfg(crossbeam_sanitize_thread)] + for local in locals { + local.epoch.load(Ordering::Acquire); + } + #[cfg(not(crossbeam_sanitize_thread))] atomic::fence(Ordering::Acquire); // All pinned participants were pinned in the current global epoch. @@ -556,7 +569,7 @@ #[cfg(all(test, not(crossbeam_loom)))] mod tests { - use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::atomic::AtomicUsize; use super::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -48,6 +48,7 @@ //! For majority of use cases, just use the default garbage collector by invoking [`pin`]. If you //! want to create your own garbage collector, use the [`Collector`] API. +#![no_std] #![doc(test( no_crate_inject, attr( @@ -61,10 +62,11 @@ rust_2018_idioms, unreachable_pub )] -#![cfg_attr(not(feature = "std"), no_std)] #[cfg(crossbeam_loom)] extern crate loom_crate as loom; +#[cfg(feature = "std")] +extern crate std; #[cfg(crossbeam_loom)] #[allow(unused_imports, dead_code)] @@ -74,6 +76,8 @@ } pub(crate) mod sync { pub(crate) mod atomic { + #[cfg(target_has_atomic = "64")] + pub(crate) use loom::sync::atomic::AtomicU64; pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering}; // FIXME: loom does not support compiler_fence at the moment. @@ -119,13 +123,9 @@ } } pub(crate) mod sync { - pub(crate) mod atomic { - pub(crate) use core::sync::atomic::{ - compiler_fence, fence, AtomicPtr, AtomicUsize, Ordering, - }; - } #[cfg(feature = "alloc")] pub(crate) use alloc::sync::Arc; + pub(crate) use core::sync::atomic; } #[cfg(feature = "std")] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/list.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/list.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/list.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/list.rs 2006-07-24 01:21:28.000000000 +0000 @@ -301,6 +301,7 @@ use crate::{Collector, Owned}; use crossbeam_utils::thread; use std::sync::Barrier; + use std::vec::Vec; impl IsElement for Entry { fn entry_of(entry: &Entry) -> &Entry { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/queue.rs clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/queue.rs --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/queue.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-epoch/src/sync/queue.rs 2006-07-24 01:21:28.000000000 +0000 @@ -219,6 +219,7 @@ use super::*; use crate::pin; use crossbeam_utils::thread; + use std::vec; struct Queue { queue: super::Queue, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"d7909ae4ead8b43562d21228996e55da832b4a07afaa2c1f0cb99d6434f70bc3","Cargo.toml":"13f1b9770df2e39284906c62f32ac71bdeff4b9da966c1d3583572de20ee8faa","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"3c82bbb994f54ab76a9ed30a42dfd095c6e636258d379b9be3fbf66324310e71","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build-common.rs":"502cb7494549bed6fa10ac7bea36e880eeb60290dc69b679ac5c92b376469562","build.rs":"34da4dc8f582959d727db84557cce37e1d2d54e8db78d355135774e70e0a7864","no_atomic.rs":"31a8276afd38e39987a169eeb02e9bed32670de5ca36d7eb74aab7e506cf9dc4","src/atomic/atomic_cell.rs":"cc7078265c6df82f544eb1adf0962ee9fffbb650b8f793d57047afbf205022ac","src/atomic/consume.rs":"381c2a8b13312ca0525d53ca1b7d0d4f525ddb154951fa3e216b061ad22012ff","src/atomic/mod.rs":"6e729c1829e958a7382870e082afe79109a58c6f6bf98590b68f8d1106c52b13","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"8715f0303ec91d1847c8ac3fc24bcc002a22a7284ade610e5eff4181f85827c7","src/cache_padded.rs":"e5a4cb14c343f161a01692dddc91efa441724dff980e0a74690faf32ef21e076","src/lib.rs":"c8c994e21ac6e2de2699a225c7ca580a6f6a0faae8da68a46f5ff69aad2eca9d","src/sync/mod.rs":"eca73c04f821859b8434d2b93db87d160dc6a3f65498ca201cd40d732ca4c134","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/parker.rs":"698996e7530da1f3815df11c89df7d916155229cbfd022cccbd555f1d1d31985","src/sync/sharded_lock.rs":"f27cff33fd00cb6cee51cdb2d429df99ae4b81a1fefb99655ae7e3506f534fd1","src/sync/wait_group.rs":"3e339aab014f50e214fea535c841755113ea058153378ed54e50a4acb403c937","src/thread.rs":"0b7577bbbac46fab2d15d1f2756a13dbdedafdb06ad535aa8d9c34c268747e4e","tests/atomic_cell.rs":"716c864d4e103039dc5cd8bf6110da4cbabafc7e4e03819aa197828e8fb0a9c7","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"314adeb8a651a28935f7a49c9a261b8fa1fd82bf6a16c865a5aced6216d7e40b","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"2a41533a5f7f113d19cd2bdafcc2abf86509109652274156efdd74abd00896b6"},"package":"248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"281a9dda74aaa66eedcc991d0ca1594b1b65aa0b54fc145d569303d7820166b9","CHANGELOG.md":"d7909ae4ead8b43562d21228996e55da832b4a07afaa2c1f0cb99d6434f70bc3","Cargo.toml":"13f1b9770df2e39284906c62f32ac71bdeff4b9da966c1d3583572de20ee8faa","Cargo.toml.orig":"1a3c655f1e25f28b5f2d4af0932df4f14930156f12a95d2b87efeb7f73023b1f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"3c82bbb994f54ab76a9ed30a42dfd095c6e636258d379b9be3fbf66324310e71","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build-common.rs":"502cb7494549bed6fa10ac7bea36e880eeb60290dc69b679ac5c92b376469562","build.rs":"34da4dc8f582959d727db84557cce37e1d2d54e8db78d355135774e70e0a7864","no_atomic.rs":"31a8276afd38e39987a169eeb02e9bed32670de5ca36d7eb74aab7e506cf9dc4","src/atomic/atomic_cell.rs":"cc7078265c6df82f544eb1adf0962ee9fffbb650b8f793d57047afbf205022ac","src/atomic/consume.rs":"381c2a8b13312ca0525d53ca1b7d0d4f525ddb154951fa3e216b061ad22012ff","src/atomic/mod.rs":"6e729c1829e958a7382870e082afe79109a58c6f6bf98590b68f8d1106c52b13","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"8715f0303ec91d1847c8ac3fc24bcc002a22a7284ade610e5eff4181f85827c7","src/cache_padded.rs":"e5a4cb14c343f161a01692dddc91efa441724dff980e0a74690faf32ef21e076","src/lib.rs":"c8c994e21ac6e2de2699a225c7ca580a6f6a0faae8da68a46f5ff69aad2eca9d","src/sync/mod.rs":"eca73c04f821859b8434d2b93db87d160dc6a3f65498ca201cd40d732ca4c134","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/parker.rs":"698996e7530da1f3815df11c89df7d916155229cbfd022cccbd555f1d1d31985","src/sync/sharded_lock.rs":"f27cff33fd00cb6cee51cdb2d429df99ae4b81a1fefb99655ae7e3506f534fd1","src/sync/wait_group.rs":"3e339aab014f50e214fea535c841755113ea058153378ed54e50a4acb403c937","src/thread.rs":"0b7577bbbac46fab2d15d1f2756a13dbdedafdb06ad535aa8d9c34c268747e4e","tests/atomic_cell.rs":"716c864d4e103039dc5cd8bf6110da4cbabafc7e4e03819aa197828e8fb0a9c7","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"314adeb8a651a28935f7a49c9a261b8fa1fd82bf6a16c865a5aced6216d7e40b","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"2a41533a5f7f113d19cd2bdafcc2abf86509109652274156efdd74abd00896b6"},"package":"248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9c3182abebb36bdc9446d75d4644190fef70fa01" + }, + "path_in_vcs": "crossbeam-utils" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crossbeam-utils/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crossbeam-utils/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ +[package] +name = "crossbeam-utils" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md +# - Create "crossbeam-utils-X.Y.Z" git tag +version = "0.8.19" +edition = "2021" +rust-version = "1.60" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils" +description = "Utilities for concurrent programming" +keywords = ["scoped", "thread", "atomic", "cache"] +categories = ["algorithms", "concurrency", "data-structures", "no-std"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +std = [] + +# These features are no longer used. +# TODO: remove in the next major version. +# Enable to use of unstable functionality. +# This is disabled by default and requires recent nightly compiler. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +nightly = [] + +[dependencies] + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +[target.'cfg(crossbeam_loom)'.dependencies] +loom = { version = "0.7.1", optional = true } + +[dev-dependencies] +rand = "0.8" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crunchy/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crunchy/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"5238a96db3efb623481ac00afca51748372d99e472bc4943f2d1762ad4cc6cf0","README.md":"6d402ec0e7baa639139f550f501b26f0fcd7e33d4b5b1184e027c5836cd6ec06","build.rs":"1fae5664addf11f9e703430663950a6f48aa9d48bfe1b80281e0b25999da3814","src/lib.rs":"e9696c988b07c250de57b4b65254869cfd75e24f5acaa0a7dd54d80facfc3fd9"},"package":"7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"cb0c02f3c4e1466f57a30420449693f0423a67e17516377a3778819c1fabb915","Cargo.toml":"5238a96db3efb623481ac00afca51748372d99e472bc4943f2d1762ad4cc6cf0","Cargo.toml.orig":"8028bb2179d640dcee54ef0b851061820640816ff64a60ab2094cd3096da2607","README.md":"6d402ec0e7baa639139f550f501b26f0fcd7e33d4b5b1184e027c5836cd6ec06","build.rs":"1fae5664addf11f9e703430663950a6f48aa9d48bfe1b80281e0b25999da3814","src/lib.rs":"e9696c988b07c250de57b4b65254869cfd75e24f5acaa0a7dd54d80facfc3fd9"},"package":"7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crunchy/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crunchy/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crunchy/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "1bf90cf2d0a8cfcb2c5592275a23ab028dff6468" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crunchy/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crunchy/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crunchy/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crunchy/Cargo.toml.orig 2019-05-07 08:48:08.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "crunchy" +version = "0.2.2" +authors = ["Vurich "] +description = "Crunchy unroller: deterministically unroll constant loops" +license = "MIT" +build = "build.rs" + +[dependencies] + +[features] +"std" = [] +"limit_64" = [] +"limit_128" = [] +"limit_256" = [] +"limit_512" = [] +"limit_1024" = [] +"limit_2048" = [] +"default" = ["limit_128"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"15cc3255034d5c244f5f201bcd496b3120656cafcc69bcaa350e57e0f8be99c3","Cargo.toml":"0d7c931e6a6c24d1b440ba45ae038f396d5356c39d9eff40df8ba224254bd64a","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"3521672491a3479422d5fe1aca6645dd2984090f85da6e5205abfb18fb7a6897","README.md":"3451ce2bc0b658041902a8e792023d9874700e9292eac9153c45f203430e24a0","src/lib.rs":"5dd00d7ea362d1e4fc06141aae07a0f15166a0b8836ac8e8713f7d7f31d26a1e"},"package":"1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"47d6c720b1bb4b32d868f5f3da3ede18b5a705b1bd2fc0145cae02504b25c69b","CHANGELOG.md":"15cc3255034d5c244f5f201bcd496b3120656cafcc69bcaa350e57e0f8be99c3","Cargo.toml":"0d7c931e6a6c24d1b440ba45ae038f396d5356c39d9eff40df8ba224254bd64a","Cargo.toml.orig":"08e4d81647aa9daffaadea42678336a30b0cb7867434fed5cb88ee661cb010e6","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"3521672491a3479422d5fe1aca6645dd2984090f85da6e5205abfb18fb7a6897","README.md":"3451ce2bc0b658041902a8e792023d9874700e9292eac9153c45f203430e24a0","src/lib.rs":"5dd00d7ea362d1e4fc06141aae07a0f15166a0b8836ac8e8713f7d7f31d26a1e"},"package":"1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "950acd038ce5f60ff9a5f2f83e7d468f2977d5fc" + }, + "path_in_vcs": "crypto-common" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/crypto-common/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/crypto-common/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,27 @@ +[package] +name = "crypto-common" +description = "Common cryptographic traits" +version = "0.1.6" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/crypto-common" +repository = "https://github.com/RustCrypto/traits" +keywords = ["crypto", "traits"] +categories = ["cryptography", "no-std"] + +[dependencies] +generic-array = { version = "0.14.4", features = ["more_lengths"] } +typenum = "1.14" # earlier versions of typenum don't satisfy the 'static bound on U* types + +# optional dependencies +rand_core = { version = "0.6", optional = true } + +[features] +std = [] +getrandom = ["rand_core/getrandom"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/delharc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/delharc/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"2b576e427f611b77dcc1cce9ee37c2e0a10119e21f556e3f88273e1c4886003a","Cargo.lock":"f43bf33812ee671de111127284a85fdbfc3fd60a3c680fd407b72ba272e85dae","Cargo.toml":"2e85f806d127cacb492a451e9b472a0aabd1b9f3c3295441cfae7431c25ca48a","LICENSE-APACHE":"16d60889ec8d40f8598768b372d8beeff86684cab5a5162b25e72fc8256609c5","LICENSE-MIT":"3f0f27cf19289d8d56a3cdf6ef91de7f699cfe3e1653a1245b2531abd85f598f","README.md":"2d6dd92b25f618bc1d5f7dea8273e40de876093a2b5fd7ab3570f0a333e97cfb","src/bitstream.rs":"a58a5cffb6818d7026133d6b9ebeb7a9340dd998d1506d559890732af9e4ccae","src/crc.rs":"4c1f25bb255c836f00433ef7b52361c910c63fdbde0ea5c3f75c17fbfb840ac2","src/decode.rs":"7972c33902a7e5c0c4f95b590510a1c103386502a711ac58b6e227be0815a9cd","src/decode/lhv1.rs":"7b629663b03be68581422d161b58e98446ecd0397b4cbaee41f92fc5bc6a2cf6","src/decode/lhv1/dyntree.rs":"ed0f23ea85a29e45a2bb99fff058631203f11f70b5feb7f6aa0a5a75b0a67ee6","src/decode/lhv2.rs":"8ae11d4697fec336c0d12a2e07bd8e039f11960322da45e7bff6dc17944bc6e7","src/decode/lz5.rs":"c4bb025a1063b045d3c62f8b0717e9c113f854ca9d2b08d57787ae90e370acef","src/decode/lzs.rs":"652ef0530bf1d5dbe9e5fc076bd9a009fc5a18aebe4cd95ff66edcb26116f84f","src/error.rs":"ac95bdbf0d08768405d97695ebceb619199d39cdbdee496a2c2a29dccb4e174a","src/header.rs":"ce85001af7bd46e56fe91fc991d5241da5e7c8c59ffca4b7b41be6da5851b03c","src/header/compression.rs":"3fbe4c377263c7fd35dd2c162397ea05cff056c4d532332bb7f0aea4fce9ecb0","src/header/msdos.rs":"22e4576ee32f4fac8c213a30d4510a007dfc4a7f44a6ffc781819bca79949e8b","src/header/ostype.rs":"058fad25ce4db3bfa3f2c38cdbfe9e115c525e88928b83ef5c7a1b3e38c31814","src/header/parser.rs":"959c0c93b567d4894b5c57cb0d84a2498a0cf364cb7461878ebf2f7d0a99673f","src/header/timestamp.rs":"8f0f29450acbaa240999a0adf3fcb48c7db440173f9b596bcd292890c6c4f457","src/lib.rs":"107d816a2f0daa52acdb6474096ecc914a0e8015ad5663a3f22af15b46eec97a","src/ringbuf.rs":"a4f0979052eba6b149a18269afb326380e09c9487274f6ca6a9c7b378d14edcb","src/statictree.rs":"cbc7217846578d25d145e5fd6894ecd22e7435c3d11fc2384342866f802dacee","src/statictree/entry.rs":"2b0b3021558494a525cf132df7486d9b3123badf1d742ab4847df6a290d5d1dc","src/stub_io.rs":"a47d8f012db443dc86bb5f72ade0c5f975d8cd19a70778a7a899edb0587e1f87"},"package":"1c93ba2617f5094875af777b3e1e5d66e79d7c832e4ae2e25722c965a482e5a1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"be55d2c45701764b122ae187d77a6ed6434ce40cb98b3d70ddc3b5132781bb28","CHANGELOG.md":"2b576e427f611b77dcc1cce9ee37c2e0a10119e21f556e3f88273e1c4886003a","Cargo.lock":"f43bf33812ee671de111127284a85fdbfc3fd60a3c680fd407b72ba272e85dae","Cargo.toml":"2e85f806d127cacb492a451e9b472a0aabd1b9f3c3295441cfae7431c25ca48a","Cargo.toml.orig":"dcf8b758a7a8819341791391b171eb8c8637fe1d641a714397260f68f1bf90ad","LICENSE-APACHE":"16d60889ec8d40f8598768b372d8beeff86684cab5a5162b25e72fc8256609c5","LICENSE-MIT":"3f0f27cf19289d8d56a3cdf6ef91de7f699cfe3e1653a1245b2531abd85f598f","README.md":"2d6dd92b25f618bc1d5f7dea8273e40de876093a2b5fd7ab3570f0a333e97cfb","src/bitstream.rs":"a58a5cffb6818d7026133d6b9ebeb7a9340dd998d1506d559890732af9e4ccae","src/crc.rs":"4c1f25bb255c836f00433ef7b52361c910c63fdbde0ea5c3f75c17fbfb840ac2","src/decode.rs":"7972c33902a7e5c0c4f95b590510a1c103386502a711ac58b6e227be0815a9cd","src/decode/lhv1.rs":"7b629663b03be68581422d161b58e98446ecd0397b4cbaee41f92fc5bc6a2cf6","src/decode/lhv1/dyntree.rs":"ed0f23ea85a29e45a2bb99fff058631203f11f70b5feb7f6aa0a5a75b0a67ee6","src/decode/lhv2.rs":"8ae11d4697fec336c0d12a2e07bd8e039f11960322da45e7bff6dc17944bc6e7","src/decode/lz5.rs":"c4bb025a1063b045d3c62f8b0717e9c113f854ca9d2b08d57787ae90e370acef","src/decode/lzs.rs":"652ef0530bf1d5dbe9e5fc076bd9a009fc5a18aebe4cd95ff66edcb26116f84f","src/error.rs":"ac95bdbf0d08768405d97695ebceb619199d39cdbdee496a2c2a29dccb4e174a","src/header.rs":"ce85001af7bd46e56fe91fc991d5241da5e7c8c59ffca4b7b41be6da5851b03c","src/header/compression.rs":"3fbe4c377263c7fd35dd2c162397ea05cff056c4d532332bb7f0aea4fce9ecb0","src/header/msdos.rs":"22e4576ee32f4fac8c213a30d4510a007dfc4a7f44a6ffc781819bca79949e8b","src/header/ostype.rs":"058fad25ce4db3bfa3f2c38cdbfe9e115c525e88928b83ef5c7a1b3e38c31814","src/header/parser.rs":"959c0c93b567d4894b5c57cb0d84a2498a0cf364cb7461878ebf2f7d0a99673f","src/header/timestamp.rs":"8f0f29450acbaa240999a0adf3fcb48c7db440173f9b596bcd292890c6c4f457","src/lib.rs":"107d816a2f0daa52acdb6474096ecc914a0e8015ad5663a3f22af15b46eec97a","src/ringbuf.rs":"a4f0979052eba6b149a18269afb326380e09c9487274f6ca6a9c7b378d14edcb","src/statictree.rs":"cbc7217846578d25d145e5fd6894ecd22e7435c3d11fc2384342866f802dacee","src/statictree/entry.rs":"2b0b3021558494a525cf132df7486d9b3123badf1d742ab4847df6a290d5d1dc","src/stub_io.rs":"a47d8f012db443dc86bb5f72ade0c5f975d8cd19a70778a7a899edb0587e1f87"},"package":"1c93ba2617f5094875af777b3e1e5d66e79d7c832e4ae2e25722c965a482e5a1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/delharc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/delharc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/delharc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "969e19d90ddf0a8e93598ac5cf117dfd8d1c2b7d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/delharc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/delharc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/delharc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/delharc/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,116 @@ +[package] +name = "delharc" +version = "0.6.1" +authors = ["Rafal Michalski "] +edition = "2021" +description = "A library for parsing and extracting files from LHA/LZH archives." +categories = ["compression"] +keywords = ["LHA", "LZH", "UNLHA"] +homepage = "https://github.com/royaltm/rust-delharc" +repository = "https://github.com/royaltm/rust-delharc" +license = "MIT OR Apache-2.0" +readme = "README.md" +exclude = [".github", ".gitignore", "tests/*", "examples/*"] + +[package.metadata.docs.rs] +all-features = true + +[features] +default = ["std", "lh1", "lz"] +std = ["chrono/std", "chrono/clock"] +lh1 = [] +lhx = [] +lz = [] + +[dependencies] +chrono = { version = "0.4", default-features = false } +bitflags = "2.5" +memchr = { version = "2", default-features = false } + +[dev-dependencies] +crc-any = { version = "2.5", default-features = false } +rand = "0.8.5" + +[[example]] +name = "extract" +path = "examples/extract.rs" +required-features = ["std"] + +[[test]] +name = "decode" +path = "tests/decode.rs" +required-features = ["std"] +[[test]] +name = "larc333" +path = "tests/larc333.rs" +required-features = ["std"] +[[test]] +name = "lenghts" +path = "tests/lenghts.rs" +required-features = ["std"] +[[test]] +name = "lha213" +path = "tests/lha213.rs" +required-features = ["std"] +[[test]] +name = "lha255e" +path = "tests/lha255e.rs" +required-features = ["std"] +[[test]] +name = "lha_amiga_122" +path = "tests/lha_amiga_122.rs" +required-features = ["std"] +[[test]] +name = "lha_amiga_212" +path = "tests/lha_amiga_212.rs" +required-features = ["std"] +[[test]] +name = "lha_os2_208" +path = "tests/lha_os2_208.rs" +required-features = ["std"] +[[test]] +name = "lha_os9_211c" +path = "tests/lha_os9_211c.rs" +required-features = ["std"] +[[test]] +name = "lha_osk_201" +path = "tests/lha_osk_201.rs" +required-features = ["std"] +[[test]] +name = "lha_unix114i" +path = "tests/lha_unix114i.rs" +required-features = ["std"] +[[test]] +name = "lha_x68k_213" +path = "tests/lha_x68k_213.rs" +required-features = ["std"] +[[test]] +name = "lharc113" +path = "tests/lharc113.rs" +required-features = ["std"] +[[test]] +name = "lharc_atari_313a" +path = "tests/lharc_atari_313a.rs" +required-features = ["std"] +[[test]] +name = "lhmelt_16536" +path = "tests/lhmelt_16536.rs" +required-features = ["std"] +[[test]] +name = "lzs" +path = "tests/lzs.rs" +required-features = ["std"] +[[test]] +name = "regression" +path = "tests/regression.rs" +required-features = ["std"] +[[test]] +name = "unlha32" +path = "tests/unlha32.rs" +required-features = ["std"] + +[workspace] +members = [ + ".", + "examples/embedded" +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/digest/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/digest/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"e89e1b904ddcb022d2413bf6eb0cc14418c0177f669c4da5520c2566ebb3800c","Cargo.toml":"f0cc2fc18c6e7f3533658b9e59d71b55e641e7d8226e5d1b915a5e7c0a1d3f36","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","README.md":"edf9f16c57466b06d201b8646182b7332324c7aba28f832dde7f57d03249637d","src/core_api.rs":"b52728aba8a84f980f3f9cc8a94a64d3a97f1eb5f4db144904822c2f8eefb1f8","src/core_api/ct_variable.rs":"703bd62fb693a437e319d1192988bd674f9127a6b76f73b4c58c71afc79bc013","src/core_api/rt_variable.rs":"b57f89bf3991a313e2ddde09c701375e23539e7df74d685a161707ba1fbc99e4","src/core_api/wrapper.rs":"033777bed7d140b158e15d50fda8a6e06557ce89bd0738fcca692be2c39e8b8a","src/core_api/xof_reader.rs":"f33ca7b2c17eb99d84ea460d5567af68690e4fa6c2d94069a5d6748f8c8620eb","src/dev.rs":"cbaeab07489efcadec917d7b7bcf2fdade79e78a4839ab3c3d8ad442f8f82833","src/dev/fixed.rs":"1cbabc651645c1e781d31825791132b4e3741f426e99d7e40988e2a5ee49bddd","src/dev/mac.rs":"e8837d3b99dc8b6ddb398e7fad5731c2ed36931f851ed625d3ae59fb31244165","src/dev/rng.rs":"156f42e9eb8fb2083cd12dc4a9bff9d57a321d33367efe6cd42cdc02c17ed2dc","src/dev/variable.rs":"51939602b43f5a813fc725bc603a34246bbf76facaa7930cb7bf78c283ec94a7","src/dev/xof.rs":"b3971175e50f615247e4158cba87d77c369461eda22751d888725cec45b61985","src/digest.rs":"8beab74640774c9f6811daa6dac9b5a8867f5beeb0b552a9b5ddbc5cfc196ed0","src/lib.rs":"5128199102bf0f7638fba0bbcf42b23822e31065841fb0c4304b64f681fde961","src/mac.rs":"6303caa2c5b76513346c082dd600e007354179ad440fc83dad3d7f4240281803"},"package":"9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"502c194bd5d933bbfd4878b4b899b5a530457b360c5f5445c949d91f0608922b","CHANGELOG.md":"e89e1b904ddcb022d2413bf6eb0cc14418c0177f669c4da5520c2566ebb3800c","Cargo.toml":"f0cc2fc18c6e7f3533658b9e59d71b55e641e7d8226e5d1b915a5e7c0a1d3f36","Cargo.toml.orig":"392589a36b44e59e13c815d47584682c5b0b26864bab89992c1e42bb73aa6b93","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","README.md":"edf9f16c57466b06d201b8646182b7332324c7aba28f832dde7f57d03249637d","src/core_api.rs":"b52728aba8a84f980f3f9cc8a94a64d3a97f1eb5f4db144904822c2f8eefb1f8","src/core_api/ct_variable.rs":"703bd62fb693a437e319d1192988bd674f9127a6b76f73b4c58c71afc79bc013","src/core_api/rt_variable.rs":"b57f89bf3991a313e2ddde09c701375e23539e7df74d685a161707ba1fbc99e4","src/core_api/wrapper.rs":"033777bed7d140b158e15d50fda8a6e06557ce89bd0738fcca692be2c39e8b8a","src/core_api/xof_reader.rs":"f33ca7b2c17eb99d84ea460d5567af68690e4fa6c2d94069a5d6748f8c8620eb","src/dev.rs":"cbaeab07489efcadec917d7b7bcf2fdade79e78a4839ab3c3d8ad442f8f82833","src/dev/fixed.rs":"1cbabc651645c1e781d31825791132b4e3741f426e99d7e40988e2a5ee49bddd","src/dev/mac.rs":"e8837d3b99dc8b6ddb398e7fad5731c2ed36931f851ed625d3ae59fb31244165","src/dev/rng.rs":"156f42e9eb8fb2083cd12dc4a9bff9d57a321d33367efe6cd42cdc02c17ed2dc","src/dev/variable.rs":"51939602b43f5a813fc725bc603a34246bbf76facaa7930cb7bf78c283ec94a7","src/dev/xof.rs":"b3971175e50f615247e4158cba87d77c369461eda22751d888725cec45b61985","src/digest.rs":"8beab74640774c9f6811daa6dac9b5a8867f5beeb0b552a9b5ddbc5cfc196ed0","src/lib.rs":"5128199102bf0f7638fba0bbcf42b23822e31065841fb0c4304b64f681fde961","src/mac.rs":"6303caa2c5b76513346c082dd600e007354179ad440fc83dad3d7f4240281803"},"package":"9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/digest/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/digest/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/digest/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "344389411fd9718a0742435152e933a9e71461ee" + }, + "path_in_vcs": "digest" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/digest/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/digest/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/digest/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/digest/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +[package] +name = "digest" +description = "Traits for cryptographic hash functions and message authentication codes" +version = "0.10.7" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/digest" +repository = "https://github.com/RustCrypto/traits" +keywords = ["digest", "crypto", "hash"] +categories = ["cryptography", "no-std"] + +[dependencies] +crypto-common = { version = "0.1.3", path = "../crypto-common" } + +# optional dependencies +block-buffer = { version = "0.10", optional = true } +subtle = { version = "2.4", default-features = false, optional = true } +blobby = { version = "0.3", optional = true } +const-oid = { version = "0.9", optional = true } + +[features] +default = ["core-api"] +core-api = ["block-buffer"] # Enable Core API traits +mac = ["subtle"] # Enable MAC traits +rand_core = ["crypto-common/rand_core"] # Enable random key generation methods +oid = ["const-oid"] # OID support. WARNING: Bumps MSRV to 1.57 +alloc = [] +std = ["alloc", "crypto-common/std"] +dev = ["blobby"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/either/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/either/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"bb722071e213518ebb05391c409035740ae813ba44e7b92ba85a86d7409b1105","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README-crates.io.md":"b775991a01ab4a0a8de6169f597775319d9ce8178f5c74ccdc634f13a286b20c","README.rst":"0bef6ca52265c62e70db879980423f7bc8c69a6d3431d2c3b5ed5d19039086a8","src/into_either.rs":"0477f226bbba78ef017de08b87d421d3cd99fbc95b90ba4e6e3e803e3d15254e","src/iterator.rs":"2dcf3e361961c2f8c0545b7e603c225d4f20cc994b37f6be56ff8b2089c2f8e0","src/lib.rs":"4fbfa03b22b84d877610dfce1c7f279c97d80f4dc2c079c7dda364e4cf56ef13","src/serde_untagged.rs":"e826ee0ab31616e49c3e3f3711c8441001ee424b3e7a8c4c466cfcc4f8a7701a","src/serde_untagged_optional.rs":"86265f09d0795428bb2ce013b070d1badf1e2210217844a9ff3f04b2795868ab"},"package":"a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"cad78e3b91733d5ee5560ea1401efce123863219028e609b450dcc86e99f3ae8",".github/workflows/ci.yml":"fae2755eca2d8e0577e550e29a09241918243ac0808d9eae61abb7f0f4b90970","Cargo.toml":"bb722071e213518ebb05391c409035740ae813ba44e7b92ba85a86d7409b1105","Cargo.toml.orig":"8107cf368e7debdb9c2c074dd4ce580dad10a9f3f255c8e8a26a26d937235b1e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README-crates.io.md":"b775991a01ab4a0a8de6169f597775319d9ce8178f5c74ccdc634f13a286b20c","README.rst":"0bef6ca52265c62e70db879980423f7bc8c69a6d3431d2c3b5ed5d19039086a8","src/into_either.rs":"0477f226bbba78ef017de08b87d421d3cd99fbc95b90ba4e6e3e803e3d15254e","src/iterator.rs":"2dcf3e361961c2f8c0545b7e603c225d4f20cc994b37f6be56ff8b2089c2f8e0","src/lib.rs":"4fbfa03b22b84d877610dfce1c7f279c97d80f4dc2c079c7dda364e4cf56ef13","src/serde_untagged.rs":"e826ee0ab31616e49c3e3f3711c8441001ee424b3e7a8c4c466cfcc4f8a7701a","src/serde_untagged_optional.rs":"86265f09d0795428bb2ce013b070d1badf1e2210217844a9ff3f04b2795868ab"},"package":"a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/either/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/either/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/either/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "864eae45407c6e25b55a39c9f9b09a0aca9928f2" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/either/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/either/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/either/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/either/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +on: + push: + branches: [ main ] + pull_request: + merge_group: + +name: CI + +jobs: + ci: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: + - 1.36.0 # MSRV + - stable + - beta + - nightly + features: + - "" + - "serde" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache the registry + uses: actions/cache@v4 + if: startsWith(matrix.rust, '1') + with: + path: ~/.cargo/registry/index + key: cargo-${{ matrix.rust }}-git-index + + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: MSRV dependencies + if: matrix.rust == '1.36.0' + run: | + cargo generate-lockfile + cargo update -p serde_json --precise 1.0.99 + cargo update -p serde --precise 1.0.156 + cargo update -p quote --precise 1.0.30 + cargo update -p proc-macro2 --precise 1.0.65 + + - name: Build (no_std) + run: cargo build --no-default-features + + - name: Build + run: cargo build --features "${{ matrix.features }}" + + - name: Test + run: cargo test --features "${{ matrix.features }}" + + - name: Doc + run: cargo doc --features "${{ matrix.features }}" + + clippy: + name: Rustfmt and Clippy + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up nightly Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt, clippy + + - name: Rustfmt + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy # -- -D warnings + + # One job that "summarizes" the success state of this pipeline. This can then be added to branch + # protection, rather than having to add each job separately. + success: + name: Success + runs-on: ubuntu-latest + needs: [ci, clippy] + # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency + # failed" as success. So we have to do some contortions to ensure the job fails if any of its + # dependencies fails. + if: always() # make sure this is never "skipped" + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: check if any dependency failed + run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/either/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/either/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/either/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/either/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +[package] +name = "either" +version = "1.11.0" +authors = ["bluss"] +edition = "2018" +rust-version = "1.36" + +license = "MIT OR Apache-2.0" +repository = "https://github.com/rayon-rs/either" +documentation = "https://docs.rs/either/1/" +readme = "README-crates.io.md" + +description = """ +The enum `Either` with variants `Left` and `Right` is a general purpose sum type with two cases. +""" + +keywords = ["data-structure", "no_std"] +categories = ["data-structures", "no-std"] + +[dependencies] +serde = { version = "1.0", optional = true, features = ["derive"] } + +[features] +default = ["use_std"] +use_std = [] + +[dev-dependencies] +serde_json = "1.0.0" + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[package.metadata.docs.rs] +features = ["serde"] + +[package.metadata.playground] +features = ["serde"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"ca1901f3e8532fb4cec894fd3664f0eaa898c0c4b961d1b992d1ed54eacf362a","COPYRIGHT":"11789f45bb180841cd362a5eee6789c68ddb573a11105e30768c308a6add0190","Cargo.toml":"22a4d210c92dae9f32c6944ef340ee8fdd027f99c081577e8907123e2a93383e","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"3fa4ca83dcc9237839b1bdeb2e6d16bdfb5ec0c5ce42b24694d8bbf0dcbef72c","LICENSE-WHATWG":"838118388fe5c2e7f1dbbaeed13e1c7f3ebf88be91319c7c1d77c18e987d1a50","README.md":"1d08aefcb92afa81b18154049c9abbcad4540a23f7172e9f9bbed5af33f1a087","ci/miri.sh":"43cb8d82f49e3bfe2d2274b6ccd6f0714a4188ccef0cecc040829883cfdbee25","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"be989dd25c6b946e3e8745fdc8e8a80fcf24b3be99ad0b4b78153ba3f6ab6310","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"588e38b01e666d5e7462617ea7e90a108d608dec9e016f3d273ac0744af2e05d","src/big5.rs":"ec6e2913011a38e9a3e825a1731f139a7ca1d5b264fefae51a3cc1a68a57cef9","src/data.rs":"8a617cc57032092d65850eb27e00de687c80aea3299e839a1f58b42d0b35abf3","src/euc_jp.rs":"32047f5b540188c4cb19c07165f846b9786a09f18e315ed3e9bda1293dae52aa","src/euc_kr.rs":"9b25afc72d9378700eecfac58d55ad1c5946d6cd0ccde2c29c08200ef2de6bb9","src/gb18030.rs":"808587168d73f0c80f8520f0ca9b161866ed2efeb17a05e85fdf3b8efe7ba28a","src/handles.rs":"b08cef1f5785bb6a4822f2e844c6df1b046b737b7a075e4593eaa8c4208e9fe2","src/iso_2022_jp.rs":"9bb485e82574f4b7d4b2364f0ff276acb6a0bc111758420a3b0ec5e04c196652","src/lib.rs":"834f44b670ec48ee82c0e12223d1567313fdd9f88bca5f4b117c82c1828f559f","src/macros.rs":"200997f8870de8bfd8cdc475e92115df42108c0df661e49d3d1cbc32056e1d99","src/mem.rs":"948571137d3b151df8db4fb2c733e74ae595d055cdf0ad83abcab9341d6adabe","src/replacement.rs":"7660b34a53f8c1ca2bdfa0e51e843ec28326950952ad8bc96569feb93ac62308","src/shift_jis.rs":"6951ae67e36b1a12fa3a30734957f444d8b1b4ae0e2bde52060b29bd0f16d9d9","src/simd_funcs.rs":"05c6e77af74bfe73cd39a752067c11425d6b46e5da419910f54bf75a5c02a984","src/single_byte.rs":"3ad87116fb339434a4b58e8f2b15485f2b66b9f7814d708f16194ed08f6d6ccf","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"23a2e11b02b3b8d15fb5613a625e3edb2c61e70e3c581abfd638719a4088200d","src/testing.rs":"f59e671e95a98a56f6b573e8c6be4d71e670bf52f7e20eb1605d990aafa1894e","src/utf_16.rs":"c071a147fad38d750c2c247e141b76b929a48007b99f26b2922b9caecdaf2f25","src/utf_8.rs":"7b7d887b347f1aefa03246b028a36a72758a4ce76c28f3b45c19467851aa7839","src/variant.rs":"1fab5363588a1554a7169de8731ea9cded7ac63ea35caabdd1c27a8dde68c27b","src/x_user_defined.rs":"9456ca46168ef86c98399a2536f577ef7be3cdde90c0c51392d8ac48519d3fae"},"package":"b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"1be67659b2fcbdbb30a1c88528fd28a181709b5e1dac489d80cdd600c7b4266a","CONTRIBUTING.md":"ca1901f3e8532fb4cec894fd3664f0eaa898c0c4b961d1b992d1ed54eacf362a","COPYRIGHT":"11789f45bb180841cd362a5eee6789c68ddb573a11105e30768c308a6add0190","Cargo.toml":"22a4d210c92dae9f32c6944ef340ee8fdd027f99c081577e8907123e2a93383e","Cargo.toml.orig":"dff90f6522d4f495553a822f84ba3b79d84c0a54eebe6a74dabf8acbe702ea23","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"3fa4ca83dcc9237839b1bdeb2e6d16bdfb5ec0c5ce42b24694d8bbf0dcbef72c","LICENSE-WHATWG":"838118388fe5c2e7f1dbbaeed13e1c7f3ebf88be91319c7c1d77c18e987d1a50","README.md":"1d08aefcb92afa81b18154049c9abbcad4540a23f7172e9f9bbed5af33f1a087","ci/miri.sh":"43cb8d82f49e3bfe2d2274b6ccd6f0714a4188ccef0cecc040829883cfdbee25","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"be989dd25c6b946e3e8745fdc8e8a80fcf24b3be99ad0b4b78153ba3f6ab6310","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"588e38b01e666d5e7462617ea7e90a108d608dec9e016f3d273ac0744af2e05d","src/big5.rs":"ec6e2913011a38e9a3e825a1731f139a7ca1d5b264fefae51a3cc1a68a57cef9","src/data.rs":"8a617cc57032092d65850eb27e00de687c80aea3299e839a1f58b42d0b35abf3","src/euc_jp.rs":"32047f5b540188c4cb19c07165f846b9786a09f18e315ed3e9bda1293dae52aa","src/euc_kr.rs":"9b25afc72d9378700eecfac58d55ad1c5946d6cd0ccde2c29c08200ef2de6bb9","src/gb18030.rs":"808587168d73f0c80f8520f0ca9b161866ed2efeb17a05e85fdf3b8efe7ba28a","src/handles.rs":"b08cef1f5785bb6a4822f2e844c6df1b046b737b7a075e4593eaa8c4208e9fe2","src/iso_2022_jp.rs":"9bb485e82574f4b7d4b2364f0ff276acb6a0bc111758420a3b0ec5e04c196652","src/lib.rs":"834f44b670ec48ee82c0e12223d1567313fdd9f88bca5f4b117c82c1828f559f","src/macros.rs":"200997f8870de8bfd8cdc475e92115df42108c0df661e49d3d1cbc32056e1d99","src/mem.rs":"948571137d3b151df8db4fb2c733e74ae595d055cdf0ad83abcab9341d6adabe","src/replacement.rs":"7660b34a53f8c1ca2bdfa0e51e843ec28326950952ad8bc96569feb93ac62308","src/shift_jis.rs":"6951ae67e36b1a12fa3a30734957f444d8b1b4ae0e2bde52060b29bd0f16d9d9","src/simd_funcs.rs":"05c6e77af74bfe73cd39a752067c11425d6b46e5da419910f54bf75a5c02a984","src/single_byte.rs":"3ad87116fb339434a4b58e8f2b15485f2b66b9f7814d708f16194ed08f6d6ccf","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"23a2e11b02b3b8d15fb5613a625e3edb2c61e70e3c581abfd638719a4088200d","src/testing.rs":"f59e671e95a98a56f6b573e8c6be4d71e670bf52f7e20eb1605d990aafa1894e","src/utf_16.rs":"c071a147fad38d750c2c247e141b76b929a48007b99f26b2922b9caecdaf2f25","src/utf_8.rs":"7b7d887b347f1aefa03246b028a36a72758a4ce76c28f3b45c19467851aa7839","src/variant.rs":"1fab5363588a1554a7169de8731ea9cded7ac63ea35caabdd1c27a8dde68c27b","src/x_user_defined.rs":"9456ca46168ef86c98399a2536f577ef7be3cdde90c0c51392d8ac48519d3fae"},"package":"b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a0c5c578db4d21e6b5f6f0febbea0a8b063f93b1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/encoding_rs/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/encoding_rs/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +[package] +name = "encoding_rs" +description = "A Gecko-oriented implementation of the Encoding Standard" +version = "0.8.34" +edition = '2018' +authors = ["Henri Sivonen "] +license = "(Apache-2.0 OR MIT) AND BSD-3-Clause" +readme = "README.md" +documentation = "https://docs.rs/encoding_rs/" +homepage = "https://docs.rs/encoding_rs/" +repository = "https://github.com/hsivonen/encoding_rs" +keywords = ["encoding", "web", "unicode", "charset"] +categories = ["text-processing", "encoding", "web-programming", "internationalization"] +rust-version = "1.36" + +[features] +default = ["alloc"] +alloc = [] +simd-accel = ["any_all_workaround"] +less-slow-kanji-encode = [] +less-slow-big5-hanzi-encode = [] +less-slow-gb-hanzi-encode = [] +fast-hangul-encode = [] +fast-hanja-encode = [] +fast-kanji-encode = [] +fast-gb-hanzi-encode = [] +fast-big5-hanzi-encode = [] +fast-legacy-encode = ["fast-hangul-encode", + "fast-hanja-encode", + "fast-kanji-encode", + "fast-gb-hanzi-encode", + "fast-big5-hanzi-encode"] + +[dependencies] +cfg-if = "1.0" +serde = { version = "1.0", optional = true } +any_all_workaround = { version = "0.1.0" , optional = true } + +[dev-dependencies] +serde_derive = "1.0" +bincode = "1.0" +serde_json = "1.0" + +[profile.release] +lto = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"75976e8cf25b724bd1db6d176d3bd98ad19554a2d64a57aaffa1b14c64a55f7a","Cargo.toml":"3d3e91b17cb7b10e130d8db6ebcfff05f37d799a8d5039d67aca802998501ae7","LICENSE":"819e0555b295079201b0670bb3302855303bdbbcc739f3819b13e1b3d2ec03bb","README.md":"a0d505b975f799d351e539720d26ed64f2022adcc8257d63c343c32a0c88f5de","src/lib.rs":"3751e744d351269d320cdc58e7fefd0f4bf657ed3a09b0fca68205696a1927c0"},"package":"c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"220ae1e3c9bff99a85c7224dcd5e75d545ded2807c1ec9fd4c14e120baace5c6",".gitlab-ci.yml":"7d38e7b0666cabeaa3c2a1c52c9fb12f8eafa241846b03b6711dbd3b234218cf","CHANGELOG.md":"75976e8cf25b724bd1db6d176d3bd98ad19554a2d64a57aaffa1b14c64a55f7a","Cargo.toml":"3d3e91b17cb7b10e130d8db6ebcfff05f37d799a8d5039d67aca802998501ae7","Cargo.toml.orig":"8713e42b316880c849381fd7086b0e99978bf912ac4947e2157e65fa35f2b242","LICENSE":"819e0555b295079201b0670bb3302855303bdbbcc739f3819b13e1b3d2ec03bb","README.md":"a0d505b975f799d351e539720d26ed64f2022adcc8257d63c343c32a0c88f5de","src/lib.rs":"3751e744d351269d320cdc58e7fefd0f4bf657ed3a09b0fca68205696a1927c0"},"package":"c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "bdb12f31b4ad96c0cc9d0d2fc3bf5c00ca2f4110" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.gitlab-ci.yml clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.gitlab-ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/.gitlab-ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,43 @@ +stages: + - build + +build-1_34: + stage: build + image: rust:1.34-slim + dependencies: [] + script: + - cargo build --verbose + - cargo test --verbose + - cargo doc --verbose + +build-stable: + stage: build + image: rust:latest + dependencies: [] + script: + - cargo build --verbose + - cargo test --verbose + - cargo doc --verbose + +build-beta: + stage: build + image: rust:latest + dependencies: [] + before_script: + - rustup default beta + script: + - cargo build --verbose + - cargo test --verbose + - cargo doc --verbose + +build-nightly: + stage: build + image: rust:latest + dependencies: [] + before_script: + - rustup default nightly + script: + - cargo generate-lockfile -Z minimal-versions + - cargo build --verbose --locked + - cargo test --verbose --locked + - cargo doc --verbose --locked diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/enum-primitive-derive/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/enum-primitive-derive/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,26 @@ +[package] +name = "enum-primitive-derive" +version = "0.2.2" +authors = ["Doug Goldstein "] +license = "MIT" +description = "enum_primitive implementation using procedural macros to have a custom derive" +readme = "README.md" +homepage = "https://gitlab.com/cardoe/enum-primitive-derive" +repository = "https://gitlab.com/cardoe/enum-primitive-derive.git" +keywords = ["derive", "enum", "fromprimitive", "primitive", "ffi"] +categories = ["rust-patterns"] +edition = "2018" + +[badges] +gitlab = { repository = "cardoe/enum-primitive-derive" } + +[lib] +proc-macro = true + +[dependencies] +quote = "1" +syn = "1" + +[dependencies.num-traits] +version = "0.2" +default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/equator/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"c81f835d155c45af8e20d8675439c5459a97480a2f9a9edf6c248f7b04516fc4","Cargo.lock":"f22894827353c195dd044c6534ffaa29c824c226e8f70014c1b879215a695827","Cargo.toml":"bbe179256e0bcf127f48349be1eab4465a999dd792935ed3c6cc920d16e95e23","Cargo.toml.orig":"0761077a162dee5022609c1f0106ec2ee8dd129ffa7c08f81b795a5664ad303e","LICENSE":"97d3424e347e8fa236806725ce9837bb453d4dfc9ce1d4733fd6023a8038000a","README.md":"3477627e4a66b980a6923938a98223a960c182f7cffcc22f54dc91cbe74ba45f","src/decompose.rs":"39d940bd829fe2b76672da56f9627976b5e9282909aabb5767a1170e4e3c3b12","src/lib.rs":"97aeba75706a5c5692fd9a7cfed654638cd50b70ed9ecc5aef7945df4fd894e2","src/spec.rs":"3930f8f93df7219a34ec1f478798045c119db300fba73ba59db1c7561b4af3e2","src/spec/by_val.rs":"560fe3ff1d59119de2594ad5da98f502a9aac77330c8a4f8c3f374e9b0e8f2b1","src/spec/debug.rs":"683a5e5c866b6e4df7eb26cf2cad5461efe9fba7a0b8229a4d0403136f715ce4","src/spec/sized.rs":"37111a47bb25ac590f91e68f27f99655752a21f515d8b3ef09075f7f8417c693","src/structures.rs":"091edc9d5f8d0e88c26877215771e1d5548133d585a51d427f3349d4053fae6d","src/traits.rs":"99767983603be5f1e0437dcba097111012cb701937142d874b168c39d1456d71","tests/test_asm.rs":"4ac68ebb47e10b01ac7aec2b145dac5685eb9df09aac4d9fdaeb998c072c60ad"},"package":"4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/equator/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8054473359c17be1e25c0ac551a54f924337319f" + }, + "path_in_vcs": "equator" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,204 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "assert2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d31fea2b6e18dfe892863c3a0a68f9e005b0195565f3d55b8612946ebca789cc" +dependencies = [ + "assert2-macros", + "diff", + "is-terminal", + "yansi", +] + +[[package]] +name = "assert2-macros" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1ac052c642f6d94e4be0b33028b346b7ab809ea5432b584eb8859f12f7ad2c" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "equator" +version = "0.4.2" +dependencies = [ + "assert2", + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "libc" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "equator" +version = "0.4.2" +authors = ["sarah <>"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Composable assertion library" +readme = "README.md" +keywords = ["assert"] +license = "MIT" +repository = "https://github.com/sarah-ek/equator/" + +[lib] +name = "equator" +path = "src/lib.rs" + +[[test]] +name = "test_asm" +path = "tests/test_asm.rs" + +[dependencies.equator-macro] +version = "0.4.2" + +[dev-dependencies.assert2] +version = "0.3.14" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/equator/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +[package] +name = "equator" +version = "0.4.2" +edition = "2021" +authors = ["sarah <>"] +description = "Composable assertion library" +readme = "../README.md" +repository = "https://github.com/sarah-ek/equator/" +license = "MIT" +keywords = ["assert"] + +[dependencies] +equator-macro = { version = "0.4.2", path = "../equator-macro" } + +[dev-dependencies] +assert2 = "0.3.14" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/equator/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/equator/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 sarah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/README.md clamav-1.4.6+dfsg/.cargo/vendor/equator/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/equator/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +# equator + +`equator` is an assertion library that aims to provide helpful diagnostics when +multiple conditions need to be asserted at once, without short-circuiting. + +Valid assertions must be of the form: + + - `cond` for testing a single condition, + - `all(...)` for testing that multiple conditions all hold simultaneously, + - `any(...)` for testing that at least one condition holds. + +`all` and `any` may be arbitrarily nested. + +# Example +``` +let x = 0; +let y = 1; + +let a = 4; +let b = 2; + +// `equator::debug_assert!` is also available for debug-only assertions +equator::assert!(all(x == y, a < b)); +``` + +This should panic with an error message like +``` +Assertion failed at path/main.rs:8:1 +Assertion failed: x == y +- x = 0 +- y = 1 +Assertion failed: a < b +- a = 4 +- b = 2 +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/decompose.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/decompose.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/decompose.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/decompose.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,326 @@ +use crate::{ + expr, + structures::{DebugMessage, DebugMessageImpl}, + traits::Eval, + CmpDisplay, +}; +use core::fmt; + +pub type PtrToDeref = unsafe fn(*const *const ()) -> *const (); +pub type PtrToCmp = unsafe fn(out: *mut (), cmp: *const (), lhs: *const (), rhs: *const ()); +pub type PtrToDebug = unsafe fn(*const ()) -> &'static dyn fmt::Debug; +pub type PtrToDisplay = + unsafe fn(*const ()) -> &'static dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>; + +pub trait Decompose { + type Decomposed: Recompose; +} + +pub trait Recompose: Sized { + type Result: Eval; + type Source; + type VTable: 'static; + type DebugLhs: Copy + fmt::Debug; + type DebugRhs: Copy + fmt::Debug; + type DebugCmp: Copy + fmt::Debug; + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result; + fn eval_impl( + debug_lhs: &Self::DebugLhs, + debug_rhs: &Self::DebugRhs, + debug_cmp: Self::DebugCmp, + vtable: &Self::VTable, + ) -> Self::Result; + + fn debug_final(full: &DebugMessage<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let result = &Self::eval_impl( + &full.debug_lhs, + &full.debug_rhs, + full.debug_cmp, + &full.source.vtable, + ); + + let message = full.message; + let inner = DebugMessageImpl::<'_, Self> { + result, + source: &full.source.source, + debug_lhs: &full.debug_lhs, + debug_rhs: &full.debug_rhs, + debug_cmp: full.debug_cmp, + vtable: full.source.vtable, + }; + write!( + f, + "Assertion failed at {}:{}:{}\n", + full.source.file, full.source.line, full.source.col + )?; + if message.as_str() != Some("") { + write!(f, "{message:#?}\n")?; + } + Self::debug_impl(&inner, f) + } +} + +impl Recompose for bool { + type Result = Result<(), ()>; + type Source = &'static str; + type VTable = (); + type DebugLhs = (); + type DebugRhs = (); + type DebugCmp = bool; + + fn eval_impl( + _: &Self::DebugLhs, + _: &Self::DebugRhs, + debug_cmp: Self::DebugCmp, + _: &Self::VTable, + ) -> Self::Result { + if debug_cmp { + Ok(()) + } else { + Err(()) + } + } + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let source = *message.source; + let result = message.result.is_ok(); + write!(f, "Assertion failed: {source}\n")?; + write!(f, "- {source} = {result:#?}") + } +} + +impl Recompose for crate::CmpExpr { + type Result = Result<(), ()>; + type Source = expr::CmpExpr<(), &'static str, &'static str>; + type VTable = + expr::CmpExpr<(PtrToDisplay, PtrToCmp), (PtrToDebug, PtrToDeref), (PtrToDebug, PtrToDeref)>; + type DebugLhs = *const (); + type DebugRhs = *const (); + type DebugCmp = (); + + fn eval_impl( + debug_lhs: &Self::DebugLhs, + debug_rhs: &Self::DebugRhs, + _: Self::DebugCmp, + vtable: &Self::VTable, + ) -> Self::Result { + let debug_lhs = unsafe { (vtable.lhs.1)(debug_lhs) }; + let debug_rhs = unsafe { (vtable.rhs.1)(debug_rhs) }; + let mut result = core::mem::MaybeUninit::::uninit(); + unsafe { + (vtable.cmp.1)( + (&mut result) as *mut core::mem::MaybeUninit as *mut (), + core::ptr::NonNull::<()>::dangling().as_ptr(), + debug_lhs, + debug_rhs, + ) + } + unsafe { result.assume_init() } + } + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let lhs_source = message.source.lhs; + let rhs_source = message.source.rhs; + let debug_lhs = unsafe { (message.vtable.lhs.1)(message.debug_lhs) }; + let debug_rhs = unsafe { (message.vtable.rhs.1)(message.debug_rhs) }; + + let lhs = unsafe { (message.vtable.lhs.0)(debug_lhs) }; + let rhs = unsafe { (message.vtable.rhs.0)(debug_rhs) }; + + let err = + unsafe { (message.vtable.cmp.0)(message.result.as_ref().unwrap_err() as *const ()) }; + err.fmt( + &(core::ptr::NonNull::<()>::dangling().as_ptr() as *const ()), + lhs, + lhs_source, + lhs, + rhs, + rhs_source, + rhs, + f, + ) + } +} + +impl Recompose for crate::CustomCmpExpr { + type Result = Result<(), E>; + type Source = expr::CustomCmpExpr<(), &'static str, &'static str>; + type VTable = expr::CustomCmpExpr< + (PtrToDisplay, PtrToCmp), + (PtrToDebug, PtrToDeref), + (PtrToDebug, PtrToDeref), + >; + type DebugLhs = *const (); + type DebugRhs = *const (); + type DebugCmp = *const (); + + fn eval_impl( + debug_lhs: &Self::DebugLhs, + debug_rhs: &Self::DebugRhs, + debug_cmp: Self::DebugCmp, + vtable: &Self::VTable, + ) -> Self::Result { + let debug_lhs = unsafe { (vtable.lhs.1)(debug_lhs) }; + let debug_rhs = unsafe { (vtable.rhs.1)(debug_rhs) }; + + let mut result = core::mem::MaybeUninit::::uninit(); + unsafe { + (vtable.cmp.1)( + (&mut result) as *mut core::mem::MaybeUninit as *mut (), + debug_cmp, + debug_lhs, + debug_rhs, + ) + } + unsafe { result.assume_init() } + } + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let lhs_source = message.source.lhs; + let rhs_source = message.source.rhs; + let debug_lhs = unsafe { (message.vtable.lhs.1)(message.debug_lhs) }; + let debug_rhs = unsafe { (message.vtable.rhs.1)(message.debug_rhs) }; + + let lhs = unsafe { (message.vtable.lhs.0)(debug_lhs) }; + let rhs = unsafe { (message.vtable.rhs.0)(debug_rhs) }; + + let err = unsafe { + (message.vtable.cmp.0)(message.result.as_ref().unwrap_err() as *const E as *const ()) + }; + err.fmt( + &message.debug_cmp, + lhs, + lhs_source, + lhs, + rhs, + rhs_source, + rhs, + f, + ) + } +} + +impl Recompose for crate::AndExpr { + type Result = expr::AndExpr; + type Source = expr::AndExpr; + type VTable = expr::AndExpr<&'static L::VTable, &'static R::VTable>; + type DebugCmp = expr::AndExpr; + type DebugLhs = expr::AndExpr; + type DebugRhs = expr::AndExpr; + + fn eval_impl( + debug_lhs: &Self::DebugLhs, + debug_rhs: &Self::DebugRhs, + debug_cmp: Self::DebugCmp, + vtable: &Self::VTable, + ) -> Self::Result { + let lhs = L::eval_impl(&debug_lhs.lhs, &debug_rhs.lhs, debug_cmp.lhs, vtable.lhs); + let rhs = R::eval_impl(&debug_lhs.rhs, &debug_rhs.rhs, debug_cmp.rhs, vtable.rhs); + expr::AndExpr { lhs, rhs } + } + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let lhs = DebugMessageImpl::<'_, L> { + result: &message.result.lhs, + source: &message.source.lhs, + vtable: message.vtable.lhs, + debug_lhs: &message.debug_lhs.lhs, + debug_rhs: &message.debug_rhs.lhs, + debug_cmp: message.debug_cmp.lhs, + }; + let rhs = DebugMessageImpl::<'_, R> { + result: &message.result.rhs, + source: &message.source.rhs, + vtable: message.vtable.rhs, + debug_lhs: &message.debug_lhs.rhs, + debug_rhs: &message.debug_rhs.rhs, + debug_cmp: message.debug_cmp.rhs, + }; + + let lhs_eval = lhs.result.eval(); + let rhs_eval = rhs.result.eval(); + if !(lhs_eval && rhs_eval) { + if !lhs_eval { + L::debug_impl(&lhs, f)?; + if !rhs_eval { + f.write_str("\n")?; + } + } + if !rhs_eval { + R::debug_impl(&rhs, f)?; + } + } + Ok(()) + } +} + +impl Recompose for crate::OrExpr { + type Result = expr::OrExpr; + type Source = expr::OrExpr; + type VTable = expr::OrExpr<&'static L::VTable, &'static R::VTable>; + type DebugCmp = expr::OrExpr; + type DebugLhs = expr::OrExpr; + type DebugRhs = expr::OrExpr; + + fn eval_impl( + debug_lhs: &Self::DebugLhs, + debug_rhs: &Self::DebugRhs, + debug_cmp: Self::DebugCmp, + vtable: &Self::VTable, + ) -> Self::Result { + let lhs = L::eval_impl(&debug_lhs.lhs, &debug_rhs.lhs, debug_cmp.lhs, vtable.lhs); + let rhs = R::eval_impl(&debug_lhs.rhs, &debug_rhs.rhs, debug_cmp.rhs, vtable.rhs); + expr::OrExpr { lhs, rhs } + } + + fn debug_impl(message: &DebugMessageImpl<'_, Self>, f: &mut fmt::Formatter) -> fmt::Result { + let lhs = DebugMessageImpl::<'_, L> { + result: &message.result.lhs, + source: &message.source.lhs, + vtable: message.vtable.lhs, + debug_lhs: &message.debug_lhs.lhs, + debug_rhs: &message.debug_rhs.lhs, + debug_cmp: message.debug_cmp.lhs, + }; + let rhs = DebugMessageImpl::<'_, R> { + result: &message.result.rhs, + source: &message.source.rhs, + vtable: message.vtable.rhs, + debug_lhs: &message.debug_lhs.rhs, + debug_rhs: &message.debug_rhs.rhs, + debug_cmp: message.debug_cmp.rhs, + }; + + let lhs_eval = lhs.result.eval(); + let rhs_eval = rhs.result.eval(); + if !(lhs_eval || rhs_eval) { + if !lhs_eval { + L::debug_impl(&lhs, f)?; + if !rhs_eval { + f.write_str("\n")?; + } + } + if !rhs_eval { + R::debug_impl(&rhs, f)?; + } + } + Ok(()) + } +} + +impl Decompose for &'static str { + type Decomposed = bool; +} +impl Decompose for expr::CmpExpr<(), &'static str, &'static str> { + type Decomposed = crate::CmpExpr; +} +impl Decompose for expr::CustomCmpExpr<(), &'static str, &'static str> { + type Decomposed = crate::CustomCmpExpr<()>; +} +impl Decompose for expr::AndExpr { + type Decomposed = crate::AndExpr; +} +impl Decompose for expr::OrExpr { + type Decomposed = crate::OrExpr; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,372 @@ +#![no_std] + +use core::fmt; + +#[doc(hidden)] +pub use equator_macro as imp; + +#[macro_export] +macro_rules! assert { + ($($tokens: tt)*) => { + $crate::imp::assert!($crate, $($tokens)*) + }; +} + +#[macro_export] +macro_rules! debug_assert { + ($($tokens: tt)*) => { + if cfg!(debug_assertions) { + $crate::imp::assert!($crate, $($tokens)*) + } + }; +} + +#[doc(hidden)] +pub mod decompose; +#[doc(hidden)] +pub mod spec; +#[doc(hidden)] +pub mod structures; +#[doc(hidden)] +pub mod traits; + +#[doc(hidden)] +pub mod expr { + #[derive(Copy, Clone, Debug)] + #[repr(C)] + pub struct CmpExpr { + pub cmp: Cmp, + pub lhs: Lhs, + pub rhs: Rhs, + } + + #[derive(Copy, Clone, Debug)] + #[repr(C)] + pub struct CustomCmpExpr { + pub cmp: Cmp, + pub lhs: Lhs, + pub rhs: Rhs, + } + + #[derive(Copy, Clone, Debug)] + pub struct AndExpr { + pub lhs: Lhs, + pub rhs: Rhs, + } + + #[derive(Copy, Clone, Debug)] + pub struct OrExpr { + pub lhs: Lhs, + pub rhs: Rhs, + } +} + +pub trait CmpError: Sized { + type Error; +} + +pub trait CmpDisplay { + fn fmt( + &self, + cmp: &C, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result; +} + +pub trait Cmp: CmpError { + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), Self::Error>; +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Eq; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Ne; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Le; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Ge; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Lt; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Gt; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct EqError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct NeError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct LeError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GeError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct LtError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GtError; + +fn display_cmp_impl( + cmp: &str, + lhs: &dyn fmt::Debug, + lhs_source: &str, + rhs: &dyn fmt::Debug, + rhs_source: &str, + f: &mut fmt::Formatter, +) -> fmt::Result { + write!(f, "Assertion failed: {lhs_source} {cmp} {rhs_source}\n")?; + write!(f, "- {lhs_source} = {lhs:#?}\n")?; + write!(f, "- {rhs_source} = {rhs:#?}") +} + +impl CmpError for Eq { + type Error = EqError; +} +impl CmpDisplay for EqError { + fn fmt( + &self, + cmp: &Eq, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl("==", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl CmpError for Ne { + type Error = NeError; +} +impl CmpDisplay for NeError { + fn fmt( + &self, + cmp: &Ne, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl("!=", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl CmpError for Lt { + type Error = LtError; +} +impl CmpDisplay for LtError { + fn fmt( + &self, + cmp: &Lt, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl("<", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl CmpError for Gt { + type Error = GtError; +} +impl CmpDisplay for GtError { + fn fmt( + &self, + cmp: &Gt, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl(">", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl CmpError for Le { + type Error = LeError; +} +impl CmpDisplay for LeError { + fn fmt( + &self, + cmp: &Le, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl("<=", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl CmpError for Ge { + type Error = GeError; +} +impl CmpDisplay for GeError { + fn fmt( + &self, + cmp: &Ge, + lhs: &Lhs, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Rhs, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + _ = (lhs, rhs, cmp); + display_cmp_impl(">=", lhs_debug, lhs_source, rhs_debug, rhs_source, f) + } +} + +impl> Cmp for Eq { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), EqError> { + if *lhs == *rhs { + Ok(()) + } else { + Err(EqError) + } + } +} +impl> Cmp for Ne { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), NeError> { + if *lhs != *rhs { + Ok(()) + } else { + Err(NeError) + } + } +} +impl> Cmp for Le { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), LeError> { + if *lhs <= *rhs { + Ok(()) + } else { + Err(LeError) + } + } +} +impl> Cmp for Ge { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), GeError> { + if *lhs >= *rhs { + Ok(()) + } else { + Err(GeError) + } + } +} +impl> Cmp for Lt { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), LtError> { + if *lhs < *rhs { + Ok(()) + } else { + Err(LtError) + } + } +} +impl> Cmp for Gt { + #[inline(always)] + fn test(&self, lhs: &Lhs, rhs: &Rhs) -> Result<(), GtError> { + if *lhs > *rhs { + Ok(()) + } else { + Err(GtError) + } + } +} + +#[doc(hidden)] +pub struct CmpExpr; +#[doc(hidden)] +pub struct CustomCmpExpr(pub core::marker::PhantomData); +#[doc(hidden)] +pub struct AndExpr(pub L, pub R); +#[doc(hidden)] +pub struct OrExpr(pub L, pub R); + +#[doc(hidden)] +pub struct Message<'a>(pub core::fmt::Arguments<'a>); +#[doc(hidden)] +pub struct NoMessage; + +impl From for core::fmt::Arguments<'_> { + fn from(_: NoMessage) -> Self { + core::format_args!("") + } +} + +impl<'a> From> for core::fmt::Arguments<'a> { + fn from(t: Message<'a>) -> Self { + t.0 + } +} + +#[cold] +#[inline(never)] +#[doc(hidden)] +#[track_caller] +pub fn panic_failed_assert<'a, M: Into>, D: decompose::Recompose>( + __marker: core::marker::PhantomData, + debug_lhs: D::DebugLhs, + debug_rhs: D::DebugRhs, + debug_cmp: D::DebugCmp, + source: &'static structures::WithSource, + message: M, +) -> ! { + panic!( + "{:#?}", + structures::DebugMessage:: { + source, + debug_lhs, + debug_rhs, + debug_cmp, + message: message.into(), + } + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn test_assert() { + assert!(false); + } + + #[cfg(debug_assertions)] + #[test] + #[should_panic] + fn test_debug_assert() { + debug_assert!(false); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/by_val.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/by_val.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/by_val.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/by_val.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,203 @@ +use crate::{ + decompose::PtrToDeref, + spec::{debug::CmpDebugWrapper, sized::CmpSizedWrapper, Wrapper}, + Cmp, CmpDisplay, CmpError, +}; +use core::fmt; + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct ByVal(pub T); + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct ByRef(pub T); + +impl fmt::Debug for ByVal { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Debug for ByRef { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl ByRef { + #[inline(always)] + pub fn get_ptr(&self) -> *const () { + self as *const _ as *const () + } +} + +impl ByVal { + const FIT_IN_PTR: bool = core::mem::size_of::() <= core::mem::size_of::<*const ()>() + && core::mem::align_of::() <= core::mem::align_of::<*const ()>(); + + #[inline(always)] + pub fn get_ptr(&self) -> *const () { + if Self::FIT_IN_PTR { + let mut out = core::ptr::null::<()>(); + unsafe { + *((&mut out) as *mut *const () as *mut T) = self.0; + }; + out + } else { + self as *const _ as *const () + } + } +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: Cmp, Wrapper>, + > Cmp, Wrapper> for CmpByValWrapper +{ + #[inline(always)] + fn test(&self, lhs: &Wrapper, rhs: &Wrapper) -> Result<(), Self::Error> { + self.0 + .test( + unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper) }, + unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper) }, + ) + .map_err(CmpByValWrapper) + } +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: CmpError, Wrapper>, + > CmpError, Wrapper, Wrapper> for CmpByValWrapper +{ + type Error = CmpByValWrapper; +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C, + E: CmpDisplay, Wrapper>, + > CmpDisplay, Wrapper, Wrapper> for CmpByValWrapper +{ + fn fmt( + &self, + cmp: &CmpByValWrapper, + lhs: &Wrapper, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Wrapper, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + self.0.fmt( + &cmp.0, + unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper) }, + lhs_source, + lhs_debug, + unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper) }, + rhs_source, + rhs_debug, + f, + ) + } +} + +impl core::ops::Deref for ByVal { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl core::ops::Deref for ByRef { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ByValWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> &ByVal { + unsafe { &*(value as *const T as *const _) } + } +} +impl ByRefWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> &ByRef { + unsafe { &*(value as *const T as *const _) } + } +} + +impl<'a, C> CmpByValWrapper>> { + #[inline(always)] + pub fn __wrap_ref(self) -> &'a CmpByValWrapper>> { + unsafe { + &*(self.0 .0 .0 as *const C + as *const CmpByValWrapper>>) + } + } +} +impl TryByValWrap for &Wrapper<&T> { + type Wrap = ByValWrap; + + #[inline] + fn wrap_by_val(&self) -> Self::Wrap { + ByValWrap + } +} +impl TryByValWrap for Wrapper { + type Wrap = ByRefWrap; + + #[inline] + fn wrap_by_val(&self) -> Self::Wrap { + ByRefWrap + } +} + +pub struct ByValWrap; +pub struct ByRefWrap; + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct CmpByValWrapper(pub T); + +pub trait TryByValWrap { + type Wrap; + fn wrap_by_val(&self) -> Self::Wrap; +} + +pub(crate) trait DerefVTable { + const VTABLE: unsafe fn(*const *const ()) -> *const (); +} + +unsafe fn no_deref(ptr: *const *const ()) -> *const () { + ptr as *const () +} +unsafe fn deref(ptr: *const *const ()) -> *const () { + *ptr +} + +impl DerefVTable for ByVal { + const VTABLE: PtrToDeref = { + if ByVal::::FIT_IN_PTR { + no_deref + } else { + deref + } + }; +} +impl DerefVTable for ByRef { + const VTABLE: PtrToDeref = { deref }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/debug.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/debug.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/debug.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/debug.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,132 @@ +use crate::{spec::Wrapper, Cmp, CmpDisplay, CmpError}; +use core::fmt; + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct DebugWrapper(pub T); +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct NoDebugWrapper(pub T); + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: CmpError, + > CmpError, Wrapper, Wrapper> for CmpDebugWrapper +{ + type Error = CmpDebugWrapper; +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C, + E: CmpDisplay, + > CmpDisplay, Wrapper, Wrapper> for CmpDebugWrapper +{ + fn fmt( + &self, + cmp: &CmpDebugWrapper, + lhs: &Wrapper, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Wrapper, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + self.0.fmt( + &cmp.0, &*lhs.0, lhs_source, lhs_debug, &*rhs.0, rhs_source, rhs_debug, f, + ) + } +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: Cmp, + > Cmp, Wrapper> for CmpDebugWrapper +{ + #[inline(always)] + fn test(&self, lhs: &Wrapper, rhs: &Wrapper) -> Result<(), Self::Error> { + self.0.test(&*lhs.0, &*rhs.0).map_err(CmpDebugWrapper) + } +} + +impl core::ops::Deref for DebugWrapper { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl core::ops::Deref for NoDebugWrapper { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl fmt::Debug for DebugWrapper { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} +impl fmt::Debug for NoDebugWrapper { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "", + core::any::type_name::(), + self as *const _ as *const () + ) + } +} + +pub struct DebugWrap; +pub struct NoDebugWrap; + +impl DebugWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> &DebugWrapper { + unsafe { &*(value as *const T as *const DebugWrapper) } + } +} +impl NoDebugWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> &NoDebugWrapper { + unsafe { &*(value as *const T as *const NoDebugWrapper) } + } +} + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct CmpDebugWrapper(pub T); + +pub trait TryDebugWrap { + type Wrap; + fn wrap_debug(&self) -> Self::Wrap; +} + +impl TryDebugWrap for &Wrapper { + type Wrap = DebugWrap; + + #[inline] + fn wrap_debug(&self) -> Self::Wrap { + DebugWrap + } +} +impl TryDebugWrap for Wrapper { + type Wrap = NoDebugWrap; + + #[inline] + fn wrap_debug(&self) -> Self::Wrap { + NoDebugWrap + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/sized.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/sized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec/sized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec/sized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,160 @@ +use crate::{spec::Wrapper, Cmp, CmpDisplay, CmpError}; +use core::fmt; + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct SizedWrapper(pub T); +#[repr(transparent)] +pub struct NoSizedWrapper<'a, T: ?Sized>(pub &'a T); + +impl Copy for NoSizedWrapper<'_, T> {} +impl Clone for NoSizedWrapper<'_, T> { + #[inline(always)] + fn clone(&self) -> Self { + *self + } +} + +impl fmt::Debug for SizedWrapper { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Debug for NoSizedWrapper<'_, T> { + #[inline(always)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl SizedWrapper { + #[inline(always)] + pub fn get(&self) -> &Self { + self + } +} +impl NoSizedWrapper<'_, T> { + #[inline(always)] + pub fn get(&self) -> &Self { + self + } +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: Cmp, Wrapper>, + > Cmp, Wrapper> for CmpSizedWrapper +{ + #[inline(always)] + fn test(&self, lhs: &Wrapper, rhs: &Wrapper) -> Result<(), Self::Error> { + self.0 + .test( + unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper) }, + unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper) }, + ) + .map_err(CmpSizedWrapper) + } +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C: CmpError, Wrapper>, + > CmpError, Wrapper, Wrapper> for CmpSizedWrapper +{ + type Error = CmpSizedWrapper; +} + +impl< + Lhs: ?Sized + core::ops::Deref, + Rhs: ?Sized + core::ops::Deref, + C, + E: CmpDisplay, Wrapper>, + > CmpDisplay, Wrapper, Wrapper> for CmpSizedWrapper +{ + fn fmt( + &self, + cmp: &CmpSizedWrapper, + lhs: &Wrapper, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &Wrapper, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + self.0.fmt( + &cmp.0, + unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper) }, + lhs_source, + lhs_debug, + unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper) }, + rhs_source, + rhs_debug, + f, + ) + } +} + +impl core::ops::Deref for SizedWrapper { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl core::ops::Deref for NoSizedWrapper<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + self.0 + } +} + +impl SizedWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> &SizedWrapper { + unsafe { &*(value as *const T as *const _) } + } +} +impl NoSizedWrap { + #[inline(always)] + pub fn do_wrap(self, value: &T) -> NoSizedWrapper<'_, T> { + NoSizedWrapper(value) + } +} + +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct CmpSizedWrapper(pub T); + +pub struct SizedWrap; +pub struct NoSizedWrap; + +pub trait TrySizedWrap { + type Wrap; + fn wrap_sized(&self) -> Self::Wrap; +} + +impl TrySizedWrap for &Wrapper<&T> { + type Wrap = SizedWrap; + + #[inline] + fn wrap_sized(&self) -> Self::Wrap { + SizedWrap + } +} +impl TrySizedWrap for Wrapper<&T> { + type Wrap = NoSizedWrap; + + #[inline] + fn wrap_sized(&self) -> Self::Wrap { + NoSizedWrap + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/spec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/spec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +use crate::CmpDisplay; +use core::fmt; + +pub mod by_val; +pub mod debug; +pub mod sized; + +impl> + CmpDisplay< + by_val::CmpByValWrapper>>, + dyn fmt::Debug + 'static, + dyn fmt::Debug + 'static, + > for by_val::CmpByValWrapper>> +{ + fn fmt( + &self, + cmp: &by_val::CmpByValWrapper>>, + lhs: &(dyn fmt::Debug + 'static), + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &(dyn fmt::Debug + 'static), + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + self.0 .0 .0.fmt( + &cmp.0 .0 .0, + lhs, + lhs_source, + lhs_debug, + rhs, + rhs_source, + rhs_debug, + f, + ) + } +} + +#[repr(transparent)] +pub struct Wrapper(pub T); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/structures.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/structures.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/structures.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/structures.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +use crate::{ + decompose, + traits::{DynInfo, DynInfoType, Expr}, +}; +use core::fmt; + +pub struct DebugMessageImpl<'a, D: decompose::Recompose> { + pub result: &'a D::Result, + pub source: &'a D::Source, + pub debug_lhs: &'a D::DebugLhs, + pub debug_rhs: &'a D::DebugRhs, + pub debug_cmp: D::DebugCmp, + pub vtable: &'a D::VTable, +} +pub struct DebugMessage<'a, D: decompose::Recompose> { + pub source: &'a WithSource, + pub debug_lhs: D::DebugLhs, + pub debug_rhs: D::DebugRhs, + pub debug_cmp: D::DebugCmp, + pub message: fmt::Arguments<'a>, +} +impl fmt::Debug for DebugMessage<'_, D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + D::debug_final(self, f) + } +} + +impl Copy for DebugMessage<'_, D> {} +impl Clone for DebugMessage<'_, D> { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Copy, Clone)] +pub struct WithSource { + pub source: S, + pub file: &'static str, + pub line: u32, + pub col: u32, + pub vtable: V, +} + +#[derive(Copy, Clone)] +pub struct Finalize { + pub inner: E, +} + +impl DynInfoType for Finalize { + type VTable = E::VTable; + const NULL_VTABLE: &'static Self::VTable = E::NULL_VTABLE; +} + +impl DynInfo for Finalize { + const VTABLE: &'static Self::VTable = E::VTABLE; +} + +impl Expr for &Finalize { + type Result = Result<(), ()>; + type Marker = bool; + + #[inline(always)] + fn eval_expr(&self) -> bool { + core::unreachable!() + } +} + +impl Expr for &&Finalize { + type Result = E::Result; + type Marker = E::Marker; + + #[inline(always)] + fn eval_expr(&self) -> bool { + self.inner.eval_expr() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/src/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,469 @@ +use crate::{ + decompose::{PtrToCmp, PtrToDebug, PtrToDeref, PtrToDisplay}, + expr, spec, + spec::by_val::{ByVal, DerefVTable}, + spec::Wrapper, + Cmp, CmpDisplay, +}; +use core::{fmt, ops::Deref}; + +pub trait Expr { + type Result: Eval; + type Marker; + + fn eval_expr(&self) -> bool; + #[inline(always)] + fn __marker(&self) -> core::marker::PhantomData { + core::marker::PhantomData + } +} + +pub trait Eval { + fn eval(&self) -> bool; +} + +impl Eval for Result<(), E> { + #[inline(always)] + fn eval(&self) -> bool { + self.is_ok() + } +} +impl Eval for expr::AndExpr { + #[inline(always)] + fn eval(&self) -> bool { + self.lhs.eval() && self.rhs.eval() + } +} +impl Eval for expr::OrExpr { + #[inline(always)] + fn eval(&self) -> bool { + self.lhs.eval() || self.rhs.eval() + } +} + +impl Expr for bool { + type Result = Result<(), ()>; + type Marker = bool; + + #[inline(always)] + fn eval_expr(&self) -> bool { + *self + } +} + +impl< + Lhs3: Deref, + Rhs3: Deref, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > Expr + for expr::CmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + Lhs3::Target: Deref, + Rhs3::Target: Deref, + ::Target: Deref, + ::Target: Deref, +{ + type Result = Result<(), C::Error>; + type Marker = crate::CmpExpr; + + #[inline(always)] + fn eval_expr(&self) -> bool { + self.cmp.0 .0 .0.test(&***self.lhs, &***self.rhs).is_ok() + } +} + +impl< + Lhs3: Deref, + Rhs3: Deref, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > Expr + for expr::CustomCmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + Lhs3::Target: Deref, + Rhs3::Target: Deref, + ::Target: Deref, + ::Target: Deref, +{ + type Result = Result<(), C::Error>; + type Marker = crate::CustomCmpExpr; + + #[inline(always)] + fn eval_expr(&self) -> bool { + self.cmp.0 .0 .0.test(&***self.lhs, &***self.rhs).is_ok() + } +} + +impl Expr for expr::AndExpr { + type Result = expr::AndExpr; + type Marker = crate::AndExpr; + + #[inline(always)] + fn eval_expr(&self) -> bool { + self.lhs.eval_expr() && self.rhs.eval_expr() + } +} + +impl Expr for expr::OrExpr { + type Result = expr::OrExpr; + type Marker = crate::OrExpr; + + #[inline(always)] + fn eval_expr(&self) -> bool { + self.lhs.eval_expr() || self.rhs.eval_expr() + } +} + +pub trait DynInfoType { + type VTable: Copy + 'static; + const NULL_VTABLE: &'static Self::VTable; +} + +pub trait DynInfo: DynInfoType { + const VTABLE: &'static Self::VTable; + + #[inline(always)] + fn vtable(&self) -> &'static Self::VTable { + Self::VTABLE + } +} + +impl DynInfoType for bool { + type VTable = (); + const NULL_VTABLE: &'static Self::VTable = &(); +} +impl DynInfo for bool { + const VTABLE: &'static Self::VTable = &(); +} + +impl DynInfoType for expr::AndExpr { + type VTable = expr::AndExpr<&'static Lhs::VTable, &'static Rhs::VTable>; + const NULL_VTABLE: &'static Self::VTable = &expr::AndExpr { + lhs: Lhs::NULL_VTABLE, + rhs: Rhs::NULL_VTABLE, + }; +} +impl DynInfoType for expr::OrExpr { + type VTable = expr::OrExpr<&'static Lhs::VTable, &'static Rhs::VTable>; + const NULL_VTABLE: &'static Self::VTable = &expr::OrExpr { + lhs: Lhs::NULL_VTABLE, + rhs: Rhs::NULL_VTABLE, + }; +} + +impl DynInfo for expr::AndExpr { + const VTABLE: &'static Self::VTable = &expr::AndExpr { + lhs: Lhs::VTABLE, + rhs: Rhs::VTABLE, + }; +} +impl DynInfo for expr::OrExpr { + const VTABLE: &'static Self::VTable = &expr::OrExpr { + lhs: Lhs::VTABLE, + rhs: Rhs::VTABLE, + }; +} + +unsafe fn as_display_vptr<'a, C, Lhs, Rhs, E: CmpDisplay>( + ptr: *const (), +) -> &'a dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> { + #[repr(transparent)] + struct DynDisplay( + E, + core::marker::PhantomData, + core::marker::PhantomData, + core::marker::PhantomData, + ); + + impl> + CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> for DynDisplay + { + fn fmt( + &self, + cmp: &*const (), + lhs: &dyn fmt::Debug, + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &dyn fmt::Debug, + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + unsafe { + let lhs = &*(lhs as *const dyn fmt::Debug as *const Lhs); + let rhs = &*(rhs as *const dyn fmt::Debug as *const Rhs); + let cmp = &*((*cmp) as *const C); + let err = &self.0; + + err.fmt( + cmp, lhs, lhs_source, lhs_debug, rhs, rhs_source, rhs_debug, f, + ) + } + } + } + + core::mem::transmute::< + &'_ dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + &'static dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + >( + (&*(ptr as *const DynDisplay)) + as &dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + ) +} + +unsafe fn as_dyn_display_vptr<'a, C, E: CmpDisplay>( + ptr: *const (), +) -> &'a dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> { + #[repr(transparent)] + struct DynDisplay(E, core::marker::PhantomData); + + impl> + CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> for DynDisplay + { + fn fmt( + &self, + cmp: &*const (), + lhs: &(dyn fmt::Debug + 'static), + lhs_source: &str, + lhs_debug: &dyn fmt::Debug, + rhs: &(dyn fmt::Debug + 'static), + rhs_source: &str, + rhs_debug: &dyn fmt::Debug, + f: &mut fmt::Formatter, + ) -> fmt::Result { + unsafe { + let cmp = &*((*cmp) as *const C); + let err = &self.0; + err.fmt( + cmp, lhs, lhs_source, lhs_debug, rhs, rhs_source, rhs_debug, f, + ) + } + } + } + + core::mem::transmute::< + &'_ dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + &'static dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + >( + (&*(ptr as *const DynDisplay)) + as &dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>, + ) +} + +unsafe fn as_cmp_vptr< + Lhs2: Deref, + Rhs2: Deref, + C: Cmp<::Target, ::Target>, +>( + out: *mut (), + cmp: *const (), + lhs: *const (), + rhs: *const (), +) where + Lhs2::Target: Deref, + Rhs2::Target: Deref, +{ + let out = out as *mut Result<(), C::Error>; + let cmp = &*(cmp as *const C); + let lhs = &*(lhs as *const Lhs2); + let rhs = &*(rhs as *const Rhs2); + out.write(cmp.test(&**lhs, &**rhs)); +} + +unsafe fn as_debug_vptr(ptr: *const ()) -> &'static dyn fmt::Debug { + core::mem::transmute::<&'_ dyn fmt::Debug, &'static dyn fmt::Debug>( + (&*(ptr as *const T)) as &dyn fmt::Debug, + ) +} + +impl< + Lhs3: Deref + fmt::Debug + DerefVTable, + Rhs3: Deref + fmt::Debug + DerefVTable, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > DynInfoType + for expr::CmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + C::Error: CmpDisplay, + Lhs3::Target: Deref, + Rhs3::Target: Deref, + ::Target: Deref, + ::Target: Deref, +{ + type VTable = + expr::CmpExpr<(PtrToDisplay, PtrToCmp), (PtrToDebug, PtrToDeref), (PtrToDebug, PtrToDeref)>; + const NULL_VTABLE: &'static Self::VTable = &expr::CmpExpr { + cmp: ( + as_dyn_display_vptr::< + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + >, + as_cmp_vptr::>, ByVal>, crate::Eq>, + ), + lhs: (as_debug_vptr::, Lhs3::VTABLE), + rhs: (as_debug_vptr::, Rhs3::VTABLE), + }; +} + +impl< + Lhs3: Deref + fmt::Debug + DerefVTable, + Rhs3: Deref + fmt::Debug + DerefVTable, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > DynInfoType + for expr::CustomCmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + C::Error: CmpDisplay< + C, + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + Lhs3::Target: Deref, + Rhs3::Target: Deref, + ::Target: Deref, + ::Target: Deref, +{ + type VTable = expr::CustomCmpExpr< + (PtrToDisplay, PtrToCmp), + (PtrToDebug, PtrToDeref), + (PtrToDebug, PtrToDeref), + >; + const NULL_VTABLE: &'static Self::VTable = &expr::CustomCmpExpr { + cmp: ( + as_display_vptr::< + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + Wrapper, + Wrapper, + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + >, + as_cmp_vptr::>, ByVal>, crate::Eq>, + ), + lhs: (as_debug_vptr::, Lhs3::VTABLE), + rhs: (as_debug_vptr::, Rhs3::VTABLE), + }; +} + +impl< + Lhs3: Deref + fmt::Debug + DerefVTable, + Rhs3: Deref + fmt::Debug + DerefVTable, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > DynInfo + for expr::CmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + C::Error: CmpDisplay, + Lhs3::Target: Sized + Deref, + Rhs3::Target: Sized + Deref, + ::Target: Deref, + ::Target: Deref, +{ + const VTABLE: &'static Self::VTable = &expr::CmpExpr { + cmp: ( + as_dyn_display_vptr::< + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + >, + as_cmp_vptr::, + ), + lhs: (as_debug_vptr::, Lhs3::VTABLE), + rhs: (as_debug_vptr::, Rhs3::VTABLE), + }; +} + +impl< + Lhs3: Deref + fmt::Debug + DerefVTable, + Rhs3: Deref + fmt::Debug + DerefVTable, + C: Cmp< + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + > DynInfo + for expr::CustomCmpExpr< + &spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + &Lhs3, + &Rhs3, + > +where + C::Error: CmpDisplay< + C, + <<::Target as Deref>::Target as Deref>::Target, + <<::Target as Deref>::Target as Deref>::Target, + >, + Lhs3::Target: Sized + Deref, + Rhs3::Target: Sized + Deref, + ::Target: Deref, + ::Target: Deref, +{ + const VTABLE: &'static Self::VTable = &expr::CustomCmpExpr { + cmp: ( + as_display_vptr::< + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + Wrapper, + Wrapper, + spec::by_val::CmpByValWrapper< + spec::sized::CmpSizedWrapper>, + >, + >, + as_cmp_vptr::, + ), + lhs: (as_debug_vptr::, Lhs3::VTABLE), + rhs: (as_debug_vptr::, Rhs3::VTABLE), + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator/tests/test_asm.rs clamav-1.4.6+dfsg/.cargo/vendor/equator/tests/test_asm.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator/tests/test_asm.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator/tests/test_asm.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,194 @@ +use core::hint::black_box; +use equator::assert; +use std::collections::HashMap; + +#[test] +#[should_panic] +pub fn test() { + black_box(test_asm_1_med as fn(_, _)); + black_box(test_asm_2_smol as fn(_, _, _, _)); + black_box(test_asm_2_med as fn(_, _, _, _)); + black_box(test_asm_2_big as fn(_, _, _, _)); + + black_box(test_std_asm_1_med as fn(_, _)); + black_box(test_std_asm_2_smol as fn(_, _, _, _)); + black_box(test_std_asm_2_med as fn(_, _, _, _)); + black_box(test_std_asm_2_big as fn(_, _, _, _)); + + black_box(test_assert2_asm_1_med as fn(_, _)); + black_box(test_assert2_asm_2_smol as fn(_, _, _, _)); + black_box(test_assert2_asm_2_med as fn(_, _, _, _)); + black_box(test_assert2_asm_2_big as fn(_, _, _, _)); + + let x = 3; + let y = 2; + let z = true; + + assert!(true == false); + assert!(all(true == false, x < y, any(!z, z))); + assert!(all(true == false, x + 1 < y, any(!z, z))); +} + +#[test] +#[should_panic] +pub fn test_different_types() { + assert!(*[0, 1, 2usize].as_slice() == [0, 1usize]); +} + +#[derive(Copy, Clone, Debug)] +struct ApproxEq { + symbol: &'static str, + tol: f64, +} + +#[derive(Copy, Clone, Debug)] +enum ApproxEqError { + Absolute { distance: f64 }, +} + +impl equator::CmpError for ApproxEq { + type Error = ApproxEqError; +} +impl equator::Cmp for ApproxEq { + fn test(&self, lhs: &f64, rhs: &f64) -> Result<(), Self::Error> { + let distance = (lhs - rhs).abs(); + let result = if distance <= self.tol { + Ok(()) + } else { + Err(ApproxEqError::Absolute { distance }) + }; + + result + } +} +impl equator::CmpDisplay for ApproxEqError { + fn fmt( + &self, + cmp: &ApproxEq, + lhs: &f64, + lhs_source: &str, + _: &dyn core::fmt::Debug, + rhs: &f64, + rhs_source: &str, + _: &dyn core::fmt::Debug, + f: &mut core::fmt::Formatter, + ) -> core::fmt::Result { + let ApproxEq { symbol, tol } = *cmp; + let ApproxEqError::Absolute { distance } = self; + + writeln!( + f, + "Assertion failed: {lhs_source} {symbol} {rhs_source}, with absolute tolerance {tol:.1e}" + )?; + writeln!(f, "- {lhs_source} = {lhs:#?}")?; + writeln!(f, "- {rhs_source} = {rhs:#?}")?; + write!(f, "- distance = {distance:#?}") + } +} + +#[test] +pub fn test_move() { + let ref mut m = HashMap::>::new(); + let x = vec![]; + assert!(*x == []); + assert!(*x == [], "oops {x:?}"); + assert!(m.insert(0, x).is_none()); +} + +#[inline(never)] +pub fn test_asm_1_med(a: usize, b: usize) { + assert!(a == b); +} + +#[inline(never)] +pub fn test_asm_2_smol(a: u8, b: u8, c: u8, d: u8) { + assert!([a, c] == [b, d]); +} + +#[inline(never)] +pub fn test_asm_2_med(a: usize, b: usize, c: usize, d: usize) { + assert!(all(a == b, c == d)); +} + +#[inline(never)] +pub fn test_asm_2_big(a: usize, b: usize, c: usize, d: usize) { + assert!([a, c] == [b, d]); +} + +#[inline(never)] +pub fn test_std_asm_2_smol(a: u8, b: u8, c: u8, d: u8) { + std::assert_eq!([a, c], [b, d]); +} + +#[inline(never)] +pub fn test_std_asm_2_med(a: usize, b: usize, c: usize, d: usize) { + std::assert_eq!(a, b); + std::assert_eq!(c, d); +} + +#[inline(never)] +pub fn test_std_asm_2_big(a: usize, b: usize, c: usize, d: usize) { + std::assert_eq!([a, c], [b, d]); +} + +#[inline(never)] +pub fn test_assert2_asm_2_smol(a: u8, b: u8, c: u8, d: u8) { + assert2::assert!([a, c] == [b, d]); +} + +#[inline(never)] +pub fn test_assert2_asm_2_med(a: usize, b: usize, c: usize, d: usize) { + assert2::assert!(a == b); + assert2::assert!(c == d); +} + +#[inline(never)] +pub fn test_assert2_asm_2_big(a: usize, b: usize, c: usize, d: usize) { + assert2::assert!([a, c] == [b, d]); +} + +#[inline(never)] +pub fn test_std_asm_1_med(a: usize, b: usize) { + std::assert_eq!(a, b); +} + +#[inline(never)] +pub fn test_assert2_asm_1_med(a: usize, b: usize) { + assert2::assert!(a == b); +} + +#[test] +#[should_panic] +pub fn test_big_fail() { + let x = [core::ptr::null::<()>(); 2]; + assert!(x != x); +} + +#[test] +pub fn test_big() { + let x = [core::ptr::null::<()>(); 2]; + assert!(x == x); +} + +#[test] +#[should_panic] +pub fn test_custom_fail() { + let approx_eq = ApproxEq { + tol: 0.01, + symbol: "~", + }; + + let x = 0.1; + assert!(all(x ~ 0.2, x ~ 0.1, x ~ 0.3)); +} + +#[test] +pub fn test_custom() { + let approx_eq = ApproxEq { + tol: 0.01, + symbol: "~", + }; + + assert!(0.1 :approx_eq: 0.10001); + assert!(0.1 ~ 0.10001); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"9b453135a0c4f23f89558b27025f6734a39e9b68f54d58f68089b942ad865fba","Cargo.lock":"165c3d870e3d7f7b803155d86ab8569fe8601de80d2cf1a100d8469c6737aef7","Cargo.toml":"9196049aa1e101c76012bf3c21db5e04d6fbe9cef9b83ab77eb623a03e140b64","Cargo.toml.orig":"c2e1af99259ff3689331bfc3591686edb8f42f2e931e4fd57b014231dd196abd","LICENSE":"97d3424e347e8fa236806725ce9837bb453d4dfc9ce1d4733fd6023a8038000a","README.md":"3477627e4a66b980a6923938a98223a960c182f7cffcc22f54dc91cbe74ba45f","src/lib.rs":"b5f2f39d2d2ef7fda38b4cc71db5e7757fa4dffea2911684cfbeb8f1bc9c5721"},"package":"44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8054473359c17be1e25c0ac551a54f924337319f" + }, + "path_in_vcs": "equator-macro" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "equator-macro" +version = "0.4.2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "equator-macro" +version = "0.4.2" +authors = ["sarah <>"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Composable assertion library" +readme = "README.md" +keywords = ["assert"] +license = "MIT" +repository = "https://github.com/sarah-ek/equator/" + +[lib] +name = "equator_macro" +path = "src/lib.rs" +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0.86" + +[dependencies.quote] +version = "1.0.36" + +[dependencies.syn] +version = "2.0.72" +features = ["full"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +[package] +name = "equator-macro" +version = "0.4.2" +edition = "2021" +authors = ["sarah <>"] +description = "Composable assertion library" +readme = "../README.md" +repository = "https://github.com/sarah-ek/equator/" +license = "MIT" +keywords = ["assert"] + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.86" +quote = "1.0.36" +syn = { version = "2.0.72", features = ["full"] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 sarah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/README.md clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +# equator + +`equator` is an assertion library that aims to provide helpful diagnostics when +multiple conditions need to be asserted at once, without short-circuiting. + +Valid assertions must be of the form: + + - `cond` for testing a single condition, + - `all(...)` for testing that multiple conditions all hold simultaneously, + - `any(...)` for testing that at least one condition holds. + +`all` and `any` may be arbitrarily nested. + +# Example +``` +let x = 0; +let y = 1; + +let a = 4; +let b = 2; + +// `equator::debug_assert!` is also available for debug-only assertions +equator::assert!(all(x == y, a < b)); +``` + +This should panic with an error message like +``` +Assertion failed at path/main.rs:8:1 +Assertion failed: x == y +- x = 0 +- y = 1 +Assertion failed: a < b +- a = 4 +- b = 2 +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/equator-macro/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/equator-macro/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,840 @@ +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use spanned::Spanned; +use syn::*; +use syn_expr::{CmpOp, CustomExpr}; + +mod syn_expr { + #![allow(dead_code)] + + use syn::{ + custom_keyword, parenthesized, punctuated::Punctuated, token::Paren, BinOp, Expr, + ExprBinary, Token, + }; + + custom_keyword!(all); + custom_keyword!(any); + + #[derive(Clone)] + pub enum CmpOp { + Custom(Token![:], Expr, Token![:]), + Approx(Token![~]), + Eq(Token![==]), + Ne(Token![!=]), + Ge(Token![>=]), + Le(Token![<=]), + Gt(Token![>]), + Lt(Token![<]), + } + + #[derive(Clone)] + pub enum CustomExpr { + All { + all_token: all, + paren_token: Paren, + args: Punctuated, + }, + Any { + any_token: any, + paren_token: Paren, + args: Punctuated, + }, + Cmp { + left: Expr, + op: CmpOp, + right: Expr, + }, + Boolean(Expr), + } + + impl syn::parse::Parse for CustomExpr { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let lookahead = input.lookahead1(); + if lookahead.peek(all) { + let _: syn::token::Tilde; + let content; + Ok(CustomExpr::All { + all_token: input.parse()?, + paren_token: parenthesized!(content in input), + args: content.parse_terminated(Self::parse, Token![,])?, + }) + } else if lookahead.peek(any) { + let content; + Ok(CustomExpr::Any { + any_token: input.parse()?, + paren_token: parenthesized!(content in input), + args: content.parse_terminated(Self::parse, Token![,])?, + }) + } else { + let expr = input.parse()?; + let lookahead = input.lookahead1(); + + match expr { + Expr::Binary(ExprBinary { + attrs: _, + left, + op: + op @ (BinOp::Eq(_) + | BinOp::Ne(_) + | BinOp::Ge(_) + | BinOp::Le(_) + | BinOp::Gt(_) + | BinOp::Lt(_)), + + right, + }) => match op { + BinOp::Eq(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Eq(op), + right: *right, + }), + BinOp::Ne(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Ne(op), + right: *right, + }), + BinOp::Ge(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Ge(op), + right: *right, + }), + BinOp::Le(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Le(op), + right: *right, + }), + BinOp::Gt(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Gt(op), + right: *right, + }), + BinOp::Lt(op) => Ok(CustomExpr::Cmp { + left: *left, + op: CmpOp::Lt(op), + right: *right, + }), + _ => unreachable!(), + }, + expr => { + if lookahead.peek(Token![~]) { + let left = expr; + let op = CmpOp::Approx(input.parse()?); + let right: Expr = input.parse()?; + return Ok(CustomExpr::Cmp { left, op, right }); + } + + if lookahead.peek(Token![:]) { + let left = expr; + let op = CmpOp::Custom(input.parse()?, input.parse()?, input.parse()?); + let right = input.parse()?; + return Ok(CustomExpr::Cmp { left, op, right }); + }; + + Ok(CustomExpr::Boolean(expr)) + } + } + } + } + } +} + +struct Operand { + placeholder_id: Ident, + diagnostic_expr: TokenStream, +} + +enum AssertExpr { + BoolExpr(Operand), + CmpExpr { + custom: bool, + cmp: Operand, + left: Operand, + right: Operand, + }, + AndExpr(Box<(AssertExpr, AssertExpr)>), + OrExpr(Box<(AssertExpr, AssertExpr)>), +} + +struct Code { + assert_expr: TokenStream, + source: TokenStream, + source_type: TokenStream, + debug_lhs: TokenStream, + debug_rhs: TokenStream, + debug_cmp: TokenStream, +} + +impl AssertExpr { + fn code(&self, crate_name: &Path) -> Code { + match self { + AssertExpr::BoolExpr(Operand { + placeholder_id, + diagnostic_expr: expr, + }) => Code { + assert_expr: quote! { (#placeholder_id).0.0.0 }, + source: quote! { #expr }, + source_type: quote! { &'static ::core::primitive::str }, + debug_lhs: quote! { () }, + debug_rhs: quote! { () }, + debug_cmp: quote! { #placeholder_id.0.0.0 }, + }, + AssertExpr::CmpExpr { + custom, + cmp: + Operand { + placeholder_id: cmp_placeholder_id, + diagnostic_expr: _, + }, + left: + Operand { + placeholder_id: left_placeholder_id, + diagnostic_expr: left_expr, + }, + right: + Operand { + placeholder_id: right_placeholder_id, + diagnostic_expr: right_expr, + }, + } => { + let name = if *custom { + quote! { CustomCmpExpr } + } else { + quote! { CmpExpr } + }; + Code { + assert_expr: quote! { + #crate_name::expr::#name { + cmp: #cmp_placeholder_id, + lhs: #left_placeholder_id, + rhs: #right_placeholder_id, + } + }, + source: quote! { + #crate_name::expr::#name { + cmp: (), + lhs: #left_expr, + rhs: #right_expr, + } + }, + source_type: quote! { + #crate_name::expr::#name< + (), + &'static ::core::primitive::str, + &'static ::core::primitive::str, + > + }, + debug_lhs: quote! { (#left_placeholder_id).get_ptr() }, + debug_rhs: quote! { (#right_placeholder_id).get_ptr() }, + debug_cmp: if *custom { + quote! { (&(#cmp_placeholder_id).0.0.0) as *const _ as *const () } + } else { + quote! { () } + }, + } + } + AssertExpr::AndExpr(inner) => { + let (left, right) = &**inner; + let Code { + assert_expr: left_assert_expr, + source: left_source, + source_type: left_source_type, + debug_lhs: left_debug_lhs, + debug_rhs: left_debug_rhs, + debug_cmp: left_debug_cmp, + } = left.code(crate_name); + let Code { + assert_expr: right_assert_expr, + source: right_source, + source_type: right_source_type, + debug_lhs: right_debug_lhs, + debug_rhs: right_debug_rhs, + debug_cmp: right_debug_cmp, + } = right.code(crate_name); + Code { + assert_expr: quote! { + #crate_name::expr::AndExpr { + lhs: (#left_assert_expr), + rhs: (#right_assert_expr), + } + }, + source: quote! { + #crate_name::expr::AndExpr { + lhs: (#left_source), + rhs: (#right_source), + } + }, + source_type: quote! { + #crate_name::expr::AndExpr<#left_source_type, #right_source_type> + }, + debug_lhs: quote! { + #crate_name::expr::AndExpr { + lhs: (#left_debug_lhs), + rhs: (#right_debug_lhs), + } + }, + debug_rhs: quote! { + #crate_name::expr::AndExpr { + lhs: (#left_debug_rhs), + rhs: (#right_debug_rhs), + } + }, + debug_cmp: quote! { + #crate_name::expr::AndExpr { + lhs: (#left_debug_cmp), + rhs: (#right_debug_cmp), + } + }, + } + } + AssertExpr::OrExpr(inner) => { + let (left, right) = &**inner; + let Code { + assert_expr: left_assert_expr, + source: left_source, + source_type: left_source_type, + debug_lhs: left_debug_lhs, + debug_rhs: left_debug_rhs, + debug_cmp: left_debug_cmp, + } = left.code(crate_name); + let Code { + assert_expr: right_assert_expr, + source: right_source, + source_type: right_source_type, + debug_lhs: right_debug_lhs, + debug_rhs: right_debug_rhs, + debug_cmp: right_debug_cmp, + } = right.code(crate_name); + Code { + assert_expr: quote! { + #crate_name::expr::OrExpr { + lhs: (#left_assert_expr), + rhs: (#right_assert_expr), + } + }, + source: quote! { + #crate_name::expr::OrExpr { + lhs: (#left_source), + rhs: (#right_source), + } + }, + source_type: quote! { + #crate_name::expr::OrExpr<#left_source_type, #right_source_type> + }, + debug_lhs: quote! { + #crate_name::expr::OrExpr { + lhs: (#left_debug_lhs), + rhs: (#right_debug_lhs), + } + }, + debug_rhs: quote! { + #crate_name::expr::OrExpr { + lhs: (#left_debug_rhs), + rhs: (#right_debug_rhs), + } + }, + debug_cmp: quote! { + #crate_name::expr::OrExpr { + lhs: (#left_debug_cmp), + rhs: (#right_debug_cmp), + } + }, + } + } + } + } +} + +fn usize_to_ident(idx: usize) -> Ident { + Ident::new(&format!("__operand_{idx}"), Span::call_site()) +} + +fn cmp_usize_to_ident(idx: usize) -> Ident { + Ident::new(&format!("__cmp_{idx}"), Span::call_site()) +} + +fn handle_expr( + crate_name: &Path, + atomics: &mut Vec, + cmp_atomics: &mut Vec, + diagnostics: &mut Vec, + mut placeholder_id: usize, + mut cmp_placeholder_id: usize, + expr: CustomExpr, +) -> (AssertExpr, usize, usize) { + match expr { + CustomExpr::All { + all_token: _, + paren_token: _, + args, + } => { + let mut args = args.into_iter().collect::>(); + if args.is_empty() { + let expr = Expr::Lit(ExprLit { + attrs: Vec::new(), + lit: Lit::Bool(LitBool { + value: true, + span: Span::call_site(), + }), + }); + let diagnostic_expr = quote! { ::core::stringify!(#expr) }; + atomics.push(expr); + ( + AssertExpr::BoolExpr(Operand { + placeholder_id: usize_to_ident(placeholder_id), + diagnostic_expr, + }), + placeholder_id + 1, + cmp_placeholder_id, + ) + } else { + let mut assert_expr; + let mut arg_expr; + (assert_expr, placeholder_id, cmp_placeholder_id) = handle_expr( + crate_name, + atomics, + cmp_atomics, + diagnostics, + placeholder_id, + cmp_placeholder_id, + args.pop().unwrap(), + ); + while let Some(arg) = args.pop() { + (arg_expr, placeholder_id, cmp_placeholder_id) = handle_expr( + crate_name, + atomics, + cmp_atomics, + diagnostics, + placeholder_id, + cmp_placeholder_id, + arg, + ); + assert_expr = AssertExpr::AndExpr(Box::new((arg_expr, assert_expr))); + } + (assert_expr, placeholder_id, cmp_placeholder_id) + } + } + CustomExpr::Any { + any_token: _, + paren_token: _, + args, + } => { + let mut args = args.into_iter().collect::>(); + if args.is_empty() { + let expr = Expr::Lit(ExprLit { + attrs: Vec::new(), + lit: Lit::Bool(LitBool { + value: false, + span: Span::call_site(), + }), + }); + let diagnostic_expr = quote! { ::core::stringify!(#expr) }; + atomics.push(expr); + ( + AssertExpr::BoolExpr(Operand { + placeholder_id: usize_to_ident(placeholder_id), + diagnostic_expr, + }), + placeholder_id + 1, + cmp_placeholder_id, + ) + } else { + let mut assert_expr; + let mut arg_expr; + (assert_expr, placeholder_id, cmp_placeholder_id) = handle_expr( + crate_name, + atomics, + cmp_atomics, + diagnostics, + placeholder_id, + cmp_placeholder_id, + args.pop().unwrap(), + ); + while let Some(arg) = args.pop() { + (arg_expr, placeholder_id, cmp_placeholder_id) = handle_expr( + crate_name, + atomics, + cmp_atomics, + diagnostics, + placeholder_id, + cmp_placeholder_id, + arg, + ); + assert_expr = AssertExpr::OrExpr(Box::new((arg_expr, assert_expr))); + } + (assert_expr, placeholder_id, cmp_placeholder_id) + } + } + CustomExpr::Cmp { + left, + right, + op: CmpOp::Custom(_, cmp, _), + } => handle_cmp( + true, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |crate_name, cmp, lhs, rhs| quote! { #crate_name::Cmp::test(#cmp, #lhs, #rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + cmp, + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Approx(op), + } => handle_cmp( + true, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |crate_name, cmp, lhs, rhs| quote! { #crate_name::Cmp::test(#cmp, #lhs, #rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + Expr::Path(ExprPath { + attrs: vec![], + qself: None, + path: Ident::new("approx_eq", op.spans[0]).into(), + }), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Eq(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) == *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Eq"), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Ne(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) != *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Ne"), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Lt(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) < *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Lt"), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Gt(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) > *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Gt"), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Le(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) <= *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Le"), + ), + CustomExpr::Cmp { + left, + right, + op: CmpOp::Ge(_), + } => handle_cmp( + false, + crate_name, + atomics, + cmp_atomics, + diagnostics, + |_, _, lhs, rhs| quote! { *(#lhs) >= *(#rhs) }, + placeholder_id, + cmp_placeholder_id, + left, + right, + make_cmp(crate_name, "Ge"), + ), + CustomExpr::Boolean(expr) => ( + AssertExpr::BoolExpr(Operand { + placeholder_id: usize_to_ident(placeholder_id), + diagnostic_expr: quote! { ::core::stringify!(#expr) }, + }), + { + let val = usize_to_ident(placeholder_id); + diagnostics.push(quote! { *#val }); + atomics.push(expr); + placeholder_id + 1 + }, + cmp_placeholder_id, + ), + } +} + +fn make_cmp(crate_name: &Path, name: &str) -> Expr { + let span = crate_name.span(); + let mut path = crate_name.clone(); + path.segments.push_punct(Token![::](crate_name.span())); + path.segments.push_value(PathSegment { + ident: Ident::new(name, span), + arguments: PathArguments::None, + }); + Expr::Path(ExprPath { + attrs: vec![], + qself: None, + path, + }) +} + +fn handle_cmp( + custom: bool, + crate_name: &Path, + atomics: &mut Vec, + cmp_atomics: &mut Vec, + diagnostics: &mut Vec, + diagnose: fn(crate_name: &Path, cmp: Ident, lhs: Ident, rhs: Ident) -> TokenStream, + placeholder_id: usize, + cmp_placeholder_id: usize, + left: Expr, + right: Expr, + cmp: Expr, +) -> (AssertExpr, usize, usize) { + ( + AssertExpr::CmpExpr { + custom, + cmp: Operand { + placeholder_id: cmp_usize_to_ident(cmp_placeholder_id), + diagnostic_expr: quote! {}, + }, + left: Operand { + placeholder_id: usize_to_ident(placeholder_id), + diagnostic_expr: quote! { ::core::stringify!(#left) }, + }, + right: Operand { + placeholder_id: usize_to_ident(placeholder_id + 1), + diagnostic_expr: quote! { ::core::stringify!(#right) }, + }, + }, + { + { + let cmp = cmp_usize_to_ident(cmp_placeholder_id); + let lhs = usize_to_ident(placeholder_id); + let rhs = usize_to_ident(placeholder_id + 1); + diagnostics.push(diagnose(crate_name, cmp, lhs, rhs)); + } + cmp_atomics.push(cmp); + atomics.push(left); + atomics.push(right); + placeholder_id + 2 + }, + cmp_placeholder_id + 1, + ) +} + +type FormatArgs = syn::punctuated::Punctuated; + +struct Args { + crate_name: Path, + expr: CustomExpr, + format_args: Option, +} + +impl syn::parse::Parse for Args { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let crate_name = input.parse()?; + let _comma: syn::token::Comma = input.parse()?; + let expr = input.parse()?; + let format_args = if input.is_empty() { + FormatArgs::new() + } else { + input.parse::()?; + FormatArgs::parse_terminated(input)? + }; + + let format_args = Some(format_args).filter(|x| !x.is_empty()); + Ok(Self { + crate_name, + expr, + format_args, + }) + } +} + +#[proc_macro] +pub fn assert(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = syn::parse_macro_input!(item as Args); + + let crate_name = &input.crate_name; + let args = input.format_args; + let body = input.expr; + + let mut atomics = Vec::new(); + let mut cmp_atomics = Vec::new(); + let mut diagnostics = Vec::new(); + let assert_expr = handle_expr( + crate_name, + &mut atomics, + &mut cmp_atomics, + &mut diagnostics, + 0, + 0, + body.clone(), + ) + .0; + let atomics = atomics; + let cmp_atomics = cmp_atomics; + let placeholders = &*atomics + .iter() + .enumerate() + .map(|(idx, _)| Ident::new(&format!("__operand_{idx}"), Span::call_site())) + .collect::>(); + + let cmp_placeholders = &*cmp_atomics + .iter() + .enumerate() + .map(|(idx, _)| Ident::new(&format!("__cmp_{idx}"), Span::call_site())) + .collect::>(); + + let Code { + assert_expr, + source, + source_type, + debug_cmp, + debug_lhs, + debug_rhs, + } = assert_expr.code(crate_name); + + let message = match args { + Some(args) => quote! { #crate_name::Message(::core::format_args!(#args)) }, + None => quote! { #crate_name::NoMessage }, + }; + + let outer_block = { + quote! { + match (#(&(#atomics),)* #(&(#cmp_atomics),)*) { + (#(#placeholders,)* #(#cmp_placeholders,)*) => { + if false { + #(let _ = #diagnostics;)* + } + use #crate_name::spec::debug::TryDebugWrap; + use #crate_name::spec::sized::TrySizedWrap; + use #crate_name::spec::by_val::TryByValWrap; + use #crate_name::traits::Expr; + + #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_debug().do_wrap(#placeholders);)* + #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_sized().do_wrap(#placeholders);)* + #(let #placeholders = (#placeholders).get();)* + #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_by_val().do_wrap(#placeholders);)* + + #(let #cmp_placeholders = #crate_name::spec::debug::CmpDebugWrapper(#cmp_placeholders);)* + #(let #cmp_placeholders = #crate_name::spec::sized::CmpSizedWrapper(#cmp_placeholders);)* + #(let #cmp_placeholders = #crate_name::spec::by_val::CmpByValWrapper(#cmp_placeholders).__wrap_ref();)* + + let __assert_expr = #crate_name::structures::Finalize { + inner: #assert_expr, + }; + + if !(&&&__assert_expr).eval_expr() { + struct Source<'a, V>(pub &'a V); + impl #crate_name::traits::DynInfoType for &Source<'_, V> { + type VTable = #crate_name::structures::WithSource<#source_type, &'static V::VTable>; + const NULL_VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource { + source: #source, + file: ::core::file!(), + line: ::core::line!(), + col: ::core::column!(), + vtable: V::NULL_VTABLE, + }; + } + impl #crate_name::traits::DynInfo for &Source<'_, V> { + const VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource { + source: #source, + file: ::core::file!(), + line: ::core::line!(), + col: ::core::column!(), + vtable: V::VTABLE, + }; + } + impl #crate_name::traits::DynInfoType for Source<'_, V> { + type VTable = #crate_name::structures::WithSource<&'static str, &'static ()>; + const NULL_VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource { + source: "", + file: ::core::file!(), + line: ::core::line!(), + col: ::core::column!(), + vtable: &(), + }; + } + impl #crate_name::traits::DynInfo for Source<'_, V> { + const VTABLE: &'static Self::VTable = ::NULL_VTABLE; + } + + #[allow(clippy::useless_transmute)] + #crate_name::panic_failed_assert( + (&&&__assert_expr).__marker(), + unsafe { ::core::mem::transmute(#debug_lhs) }, + unsafe { ::core::mem::transmute(#debug_rhs) }, + unsafe { ::core::mem::transmute(#debug_cmp) }, + { + use #crate_name::traits::DynInfo; + (&&Source(&__assert_expr)).vtable() + }, + #message, + ); + } + } + } + } + }; + + outer_block.into() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/errno/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/errno/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"b640a4e74c65505290775558e36ede1968ed26a551edaf7574f661891920ff48","Cargo.toml":"329c6992879c5c2ac32dd09263f4d9cad0da477ac9c44e50e6ae503fd9616467","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8764a597675778ddfd4e25f81b08a05dbcf089ac05662df7613fe67f150e3aa2","README.md":"a1817eb8a0b2208d3f3989202b6af03c8261747b281039d4c7790649b587fd0b","clippy.toml":"6409bb805741d8bedfb1e58eb0ce4b63bd1d384ad5e29b7a3c0997a872f31206","src/hermit.rs":"ad03355bc4d79c180ab3210e1d3edd538eccaaea8d4f9a9b7eb8a0dc2d39b5df","src/lib.rs":"318f864b8cb9296c85f70f9dfb855c552303630b3a9390f147bb4b581b8d8b5c","src/unix.rs":"6ee5c13893fa1114fa1782239f2539f1b0a9554e5ed45cf0ee78729145882032","src/wasi.rs":"c83052e5c45c31e2a4630c00a4d0b92f39205774a4d419b4aa5c06dc5992280c","src/windows.rs":"7cbcdb8e74582f357fa945bb1c44c4d19c1a10bec958da1223305bf68ec35baf"},"package":"a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f623d1a5444887d2c93f91a30f3b0c441bae4cafad5d48644cb467e0e510dcb0",".github/dependabot.yml":"514557e7c5180a3f89e89cdc98112fd32c362216ae8478bfac4dcfee874f330f",".github/workflows/main.yml":"9fc3cb3c03afc62268ef2f673f33637de6035cd597477a1cdd5a4113001a739c","CHANGELOG.md":"b640a4e74c65505290775558e36ede1968ed26a551edaf7574f661891920ff48","Cargo.toml":"329c6992879c5c2ac32dd09263f4d9cad0da477ac9c44e50e6ae503fd9616467","Cargo.toml.orig":"ca02ddf7aab0aab53c5cb57788d847bc5d850f099f04e89e4033d43fdf7eba72","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8764a597675778ddfd4e25f81b08a05dbcf089ac05662df7613fe67f150e3aa2","README.md":"a1817eb8a0b2208d3f3989202b6af03c8261747b281039d4c7790649b587fd0b","clippy.toml":"6409bb805741d8bedfb1e58eb0ce4b63bd1d384ad5e29b7a3c0997a872f31206","src/hermit.rs":"ad03355bc4d79c180ab3210e1d3edd538eccaaea8d4f9a9b7eb8a0dc2d39b5df","src/lib.rs":"318f864b8cb9296c85f70f9dfb855c552303630b3a9390f147bb4b581b8d8b5c","src/unix.rs":"6ee5c13893fa1114fa1782239f2539f1b0a9554e5ed45cf0ee78729145882032","src/wasi.rs":"c83052e5c45c31e2a4630c00a4d0b92f39205774a4d419b4aa5c06dc5992280c","src/windows.rs":"7cbcdb8e74582f357fa945bb1c44c4d19c1a10bec958da1223305bf68ec35baf"},"package":"a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/errno/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/errno/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/errno/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "529718762b1f752ccc894de5380d3aa10889733d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/errno/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/errno/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/errno/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/errno/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/errno/.github/workflows/main.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +on: + push: + branches: + - main + pull_request: + schedule: + - cron: '5 21 * * 5' + workflow_dispatch: + +name: CI + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + rust: [stable, nightly, '1.56'] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - name: Setup cache + uses: Swatinem/rust-cache@v2 + - name: Test (no features) + run: cargo test --no-default-features + - name: Test (all features) + run: cargo test --all-features + + + wasi: + name: Test WASI + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@nightly + with: + targets: wasm32-wasi + - name: Install wasmtime + run: | + curl https://wasmtime.dev/install.sh -sSf | bash + echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH + - name: Test (no features) + run: CARGO_TARGET_WASM32_WASI_RUNNER=wasmtime cargo test --target wasm32-wasi --no-default-features + - name: Test (all features) + run: CARGO_TARGET_WASM32_WASI_RUNNER=wasmtime cargo test --target wasm32-wasi --all-features + + + lints: + name: Rustfmt & Clippy + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + - name: Check formatting + run: cargo fmt --check + - name: Check clippy + run: cargo clippy -- -D warnings diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/errno/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/errno/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/errno/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/errno/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +[package] + +name = "errno" +version = "0.3.8" +authors = ["Chris Wong "] + +license = "MIT OR Apache-2.0" +edition = "2018" +documentation = "https://docs.rs/errno" +repository = "https://github.com/lambda-fairy/rust-errno" +description = "Cross-platform interface to the `errno` variable." +categories = ["no-std", "os"] +rust-version = "1.56" + +[target.'cfg(unix)'.dependencies] +libc = { version = "0.2", default-features = false } + +[target.'cfg(windows)'.dependencies.windows-sys] +version = "0.52" +features = [ + "Win32_Foundation", + "Win32_System_Diagnostics_Debug", +] + +[target.'cfg(target_os="wasi")'.dependencies] +libc = { version = "0.2", default-features = false } + +[target.'cfg(target_os="hermit")'.dependencies] +libc = { version = "0.2", default-features = false } + +[features] +default = ["std"] +std = ["libc/std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CONTRIBUTORS.md":"10e949977ca053080f01326a3a6fcdf56ea8b6c11a760e763942f4bb2c4f1549","Cargo.lock":"1c8a55c62c76a10940732f9f778dbab215ca5f25faf0879a8b34354e9a76e973","Cargo.toml":"ee83f8176af2c0d394d917f0a1780e436007bb1ff1d661bf3357ed45de708b06","GUIDE.md":"3011e54211d114914d062936be21ddd119e2403629e55ca338ff82c81517594d","LICENSE.md":"97e4d3aa7a9e8ac31979c16ca8bb2b628a9cb72c3362185ad2bf4ad77f43551f","README.md":"8db5141ec3eecdcd36b60387dee56abfce50561647d359455dbaf49e512da771","benches/pixel_format_conversion.rs":"1646621fdf20a37a2e0777bafc1e68dba207dc77ab09d56bc62d0ea1ab8a410b","benches/profiling.rs":"4c89961554a3e9e0e2fe24ae08caceff766d5d7a7d81d039d3d9cb8f654bc0ae","benches/read.rs":"eac00afb3aaf22ad932064c75d3f84fd4682b8ca46a64cecc59e9ad16c271660","benches/write.rs":"d8034375c6b5cac8efdebad4b0bc3372af6348b1da906919b5fdde7551470b59","examples/0a_write_rgba.rs":"c45a4fa86f4d0aeb546b976ee69db7987ba40201a13e7c8ad3bc94d79260ac17","examples/0b_read_meta.rs":"493c9f6104167b0f4caa5c0d4eb27f507c57a901f11e7bfa15eba6c0600492a4","examples/0c_read_rgba.rs":"568a8d407152bbb7cd006c7fea5f8af4cae05c267ed31886070f3064cba5bd5d","examples/1a_write_rgba_with_metadata.rs":"d28729916b75ee6a5cbe6670a83101c77724c1fc2f3a90433a628f45e85914ff","examples/1b_convert_exr_to_png.rs":"2df5eb30918ed616f15041f2f74dde71ee5e6ea22ba99a5bd433fb935466bfcd","examples/2_rgba_adjust_exposure.rs":"08a4c06f46e4e5acef091b4fc2ba48ea3206934fe27e214c3fbc79857b962b1e","examples/3a_write_dynamic_channels_with_metadata.rs":"f29e64b784940f66fd3301f2eef1515cb2fb63713e8f10e84db5fdeced84260e","examples/3b_read_all_channels_with_metadata.rs":"3c8fb31e9824849735dadc5f5ab602246d60202a4b6f4457843aedb7e8aa7034","examples/4a_write_custom_fixed_channels.rs":"4a06074e44f9e85eba32f4c8bbd178f22bb41e75f4883ef7fe83319f1ce2e442","examples/4b_read_custom_fixed_channels.rs":"0c4176949760775fc75e6cbddac1212eeba377dd100057ce945bb3fc06d11f9e","examples/5a_write_multiple_layers.rs":"c046f5170dc71c28be12973f44f93260e8edeae491a56da145e0b54475a24b17","examples/5b_extract_exr_layers_as_pngs.rs":"3d16a953e02cb2f56b90391f83744629d0db2481c13a61026a170d56cefc260f","examples/5c_write_mip_maps.rs":"d95e37e4aaec0eb5e2fcdd567cd2c2849f7bc55c8625054b97f7995fe438382c","examples/5d_write_legacy_layers.rs":"b46a0d480a354d8eba788c0444db0b05e5b18ed816b86e4c213be46f131d740d","examples/6_extract_mip_map_pngs.rs":"69be1d63bd3831e6e7961e77f421c448486b45a1357e036a3389dbb7a79a4009","examples/7_crop_alpha_any_image.rs":"d00dcd1e3c64474e94d18be06836d1316b9776fb4f047664de76107c2f683229","examples/7_crop_alpha_rgba.rs":"e7f4b9a9753f6921ca852523bf95e0b1c3b27a2f55565587b2f35a66d704c518","examples/7_write_raw_blocks.rs":"06617b466dc320d14690294e5b4a19dd4190c5486be04039417aab003ee01acd","examples/8_read_raw_blocks.rs":"ca98e1dcc95cc3d155f55172d2bfa3e132da7fe8da619a631a79be2374071ea4","examples/README.md":"f48dfff06b3554dd2f21da8aba8a661210cd156a21bab96107bdf512d52f36a2","releasing.md":"f4657d6adf32f44ae77cec9a8221b8c54d2eb727eec9818eb672893c254e511f","src/block/chunk.rs":"a7ba8a9d401bc414597aa4fc11c2f2218a782c84659aef318e31e1cdb7ddff9b","src/block/lines.rs":"230241879d3399233194b0ca5824188bcfe62d18b07e5e0040ea7ce69947d2dd","src/block/mod.rs":"e50e6a7668d6ded2c68ab95edb717e96067b29acd9beb2211e0be42ab3de8f15","src/block/reader.rs":"4eb0a18458dc43983e5f12c1bfd3e6bbf3d9c35fa260e600e494a41b9c6cdad8","src/block/samples.rs":"94013224cb670c56aa8030fbc9e42c506d3cc4f396c28a2ee523e42bb79e52ac","src/block/writer.rs":"8193bb70f23b1a8ea8b71f77738a1d321c21d65228322044667328591830ee18","src/compression/b44/mod.rs":"252df26e1a061d42decc44ba79240231922d61b229eaf11722fa35fcd082d202","src/compression/b44/table.rs":"2b1d1dc47b0d210044b713b7e0feba743f2e02bd4c9f7da9023387411758b54c","src/compression/mod.rs":"2613efd230dc9d08c7065ea9c96fe5a3e90e522cef9ae2cfec59988ea8fa1d99","src/compression/piz/huffman.rs":"15faeb244312edf2c37684f5ab198df937268f24a4d59883e543c88a85e18e2b","src/compression/piz/mod.rs":"1c4787f71fb3859530b4ee125d006b14878586b2ea4969e0dc6720776a93562e","src/compression/piz/wavelet.rs":"d830399ce5c1d3c749c328bd0956effd16771a4a7873f0a7f94999f0cb7275b6","src/compression/pxr24.rs":"a04d7150458d4f9400618138c88b992d4cb69cb3ecddbab1c0371e89bcfb5895","src/compression/rle.rs":"2d8d0479c626af82c71c097d5b0ebd2aaa4e48f57fe585760c533a0250a88ebe","src/compression/zip.rs":"fc89822f3e164c261d0502389dfd4ce963dd1752c00e0b5aee25e05cd57bd02d","src/error.rs":"b30f00a21b26a774ec1bdee41f36d303da1df974f327218ab44407bd923ab045","src/image/channel_groups.rs":"2e8ed9f0d1f4cea6e500eedcaedcc8b1b5a2eeb91083253836c5ccf7ff61f07b","src/image/crop.rs":"b549101e84c38603d1f8f6a28a8b949e092ff9f24ecfd02984334441f79c1779","src/image/mod.rs":"e4b2615e27e321f2bbb6ecafbce58a3892c29f1eaf8b3bb3e95d730782b15ff8","src/image/pixel_vec.rs":"0011a9b211a1f6df8e269facfa569408647fb0dfc787f254b098e15a91219455","src/image/read/any_channels.rs":"691abe56ce69aebca17a4395a3ba6aeadba3f02f1ae14bf1081d3ba9946f3d87","src/image/read/image.rs":"bec781482efa1c05a3e0e0b5c075f09a81f9d0c8c7f71e0db2cea848e2bc2adc","src/image/read/layers.rs":"6b1c155ce5131e3c4350b2d2e3b939bf0533e41bc4efc3642f888c99847985c1","src/image/read/levels.rs":"aeef8b0b6a66ed541b17eb09ead683cb1b62b0fb72f1460274cf7980f3e7fb55","src/image/read/mod.rs":"ff4950469b3d67316f4cd4440fa1e503346fd305c82f05255acec6c65c3c0065","src/image/read/samples.rs":"8143d291cc2191d3c6e0127de6ae25787201efe9b535dd6212e00438c0dab0b3","src/image/read/specific_channels.rs":"712517eb9b33854a9f86ed470911d518335ec89a19d45367e5bd2a1e402e3767","src/image/recursive.rs":"88c3270fae8d4d0cbf30301e1f6ee5ec91ccf28eb2c825010ab648e5f3787908","src/image/write/channels.rs":"c80fc4316dc9273aae0c187ae5badcef9a3e0e90328259546efbf037c29f93ac","src/image/write/layers.rs":"49b821a14394e215efd3520ae4ecaade7228b41ac3e4ded5c6236a10e9708a05","src/image/write/mod.rs":"4c69b094bd1fd18c0b5b0cec8c09bcdff43743e0aca8eda4f63fc9631d8961bf","src/image/write/samples.rs":"4eb4b91b467c99d9595055811817836d5d3ffb8e0a788d753e7cae1bf47b2e03","src/io.rs":"d869316c3ad643aaebc7f8b5d0a5d6f20673473930d857b244634058739c3951","src/lib.rs":"7f5724c98504161c45b508bd1e806bad1bf292fdb1cbfd4f59949212aca5b9b4","src/math.rs":"2e204e7f273189748fe89f93243a3c76694ba33a9089cda9440bbe4f4b27ef38","src/meta/attribute.rs":"9b5cae525f43a13449b2cf8093d39b645db1da631375d3374af897f2a6d0671f","src/meta/header.rs":"13688efae965a64147ff4911efd6df86cd1c7b5e663740228e988a0f24a3833b","src/meta/mod.rs":"50667aaad24dd4c9c34528d4d88f89b0d31669e88f6d5c59e30df457f3203069","tests/across_compression.rs":"17eda072a1bc76a8e693f297e3abce3df3f05fadc60c2653848610877941ccc7","tests/dev.rs":"f10858a0df2bbc1c78680eda7e00b03611de1c4618fa7cba837dba3254104f1f","tests/fuzz.rs":"d8947b4993b0d2261f83b983beeea0a6f13e9c86ac3a0ffc0fbfcbe442138463","tests/roundtrip.rs":"1bbf87730ed262b1948bfee13b0533ed5e3f9bc2047c4054d1815fb8dada465b"},"package":"887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"78900453282da404152ef449caec9712c971043d01b8cd2d995fe59ecfae312c",".github/ISSUE_TEMPLATE/bug_report.md":"6bfbdf374af1e7c006ddeae739c0fbea80d7ad01fedf90ee850da32f8da3e789",".github/ISSUE_TEMPLATE/feature_request.md":"8096fd7d092e718f6b4df4a47d55aef33fb57753570a8a5d352e700fabb009f8",".github/ISSUE_TEMPLATE/other.md":"4f9b431300eb857ab88a452a6614c36b4b73a2367640a924a896ce235eb87897",".github/ISSUE_TEMPLATE/question.md":"7af3bf113383097515f99e8a5d37efc87d26b5ec7f95517f86bdef48089e93c5",".github/workflows/rust.yml":"25c893a1d5c6169b6df2df7c0852fa8c58d6e492c69ba5656f46adefe18f1d50","CONTRIBUTORS.md":"10e949977ca053080f01326a3a6fcdf56ea8b6c11a760e763942f4bb2c4f1549","Cargo.lock":"685c13db5c149a1bc901e0166d41ea7fb40fa7d43793f52745de9b1f87c94af9","Cargo.toml":"bd14ef89f5874ee35664e3bcadd6ef77cf3a9690f618d09c0aa2724bf40c1ccc","Cargo.toml.orig":"dca55c628d2bcb5a4124920178d77b0a256db4a3a5a12f716bf602239213a0b1","GUIDE.md":"3011e54211d114914d062936be21ddd119e2403629e55ca338ff82c81517594d","LICENSE.md":"97e4d3aa7a9e8ac31979c16ca8bb2b628a9cb72c3362185ad2bf4ad77f43551f","README.md":"e9887ec6b7d1f79351856548d6601369f49f06e879f3216ba629b29ff7482c61","benches/pixel_format_conversion.rs":"e97615c84b744deaedcc4d85a8598baac8ea879ae5b5715628f261707aee26ad","benches/profiling.rs":"4c89961554a3e9e0e2fe24ae08caceff766d5d7a7d81d039d3d9cb8f654bc0ae","benches/read.rs":"eac00afb3aaf22ad932064c75d3f84fd4682b8ca46a64cecc59e9ad16c271660","benches/write.rs":"d8034375c6b5cac8efdebad4b0bc3372af6348b1da906919b5fdde7551470b59","examples/0a_write_rgba.rs":"c45a4fa86f4d0aeb546b976ee69db7987ba40201a13e7c8ad3bc94d79260ac17","examples/0b_read_meta.rs":"493c9f6104167b0f4caa5c0d4eb27f507c57a901f11e7bfa15eba6c0600492a4","examples/0c_read_rgba.rs":"568a8d407152bbb7cd006c7fea5f8af4cae05c267ed31886070f3064cba5bd5d","examples/1a_write_rgba_with_metadata.rs":"d28729916b75ee6a5cbe6670a83101c77724c1fc2f3a90433a628f45e85914ff","examples/1b_convert_exr_to_png.rs":"2df5eb30918ed616f15041f2f74dde71ee5e6ea22ba99a5bd433fb935466bfcd","examples/2_rgba_adjust_exposure.rs":"08a4c06f46e4e5acef091b4fc2ba48ea3206934fe27e214c3fbc79857b962b1e","examples/3a_write_dynamic_channels_with_metadata.rs":"f29e64b784940f66fd3301f2eef1515cb2fb63713e8f10e84db5fdeced84260e","examples/3b_read_all_channels_with_metadata.rs":"3c8fb31e9824849735dadc5f5ab602246d60202a4b6f4457843aedb7e8aa7034","examples/4a_write_custom_fixed_channels.rs":"4a06074e44f9e85eba32f4c8bbd178f22bb41e75f4883ef7fe83319f1ce2e442","examples/4b_read_custom_fixed_channels.rs":"0c4176949760775fc75e6cbddac1212eeba377dd100057ce945bb3fc06d11f9e","examples/5a_write_multiple_layers.rs":"c046f5170dc71c28be12973f44f93260e8edeae491a56da145e0b54475a24b17","examples/5b_extract_exr_layers_as_pngs.rs":"3d16a953e02cb2f56b90391f83744629d0db2481c13a61026a170d56cefc260f","examples/5c_write_mip_maps.rs":"d95e37e4aaec0eb5e2fcdd567cd2c2849f7bc55c8625054b97f7995fe438382c","examples/5d_write_legacy_layers.rs":"b46a0d480a354d8eba788c0444db0b05e5b18ed816b86e4c213be46f131d740d","examples/6_extract_mip_map_pngs.rs":"69be1d63bd3831e6e7961e77f421c448486b45a1357e036a3389dbb7a79a4009","examples/7_crop_alpha_any_image.rs":"d00dcd1e3c64474e94d18be06836d1316b9776fb4f047664de76107c2f683229","examples/7_crop_alpha_rgba.rs":"e7f4b9a9753f6921ca852523bf95e0b1c3b27a2f55565587b2f35a66d704c518","examples/7_write_raw_blocks.rs":"06617b466dc320d14690294e5b4a19dd4190c5486be04039417aab003ee01acd","examples/8_read_raw_blocks.rs":"ca98e1dcc95cc3d155f55172d2bfa3e132da7fe8da619a631a79be2374071ea4","examples/README.md":"3755e08b3c86c8f398a6b585ca486e4fd8e5617f48f52997dd400adbe6dbddb3","releasing.md":"f4657d6adf32f44ae77cec9a8221b8c54d2eb727eec9818eb672893c254e511f","src/block/chunk.rs":"2f1ccb18e44a1e7e0b443574b7eb5480c80038b2c1395cd2c0ee9151dbb7dc02","src/block/lines.rs":"c7b255bab08f2f8b73a90a3b51ef67d11b1494fc5e3f07e51e4a71d5180137f2","src/block/mod.rs":"f5e3b6a5897a1a350c50b1298d2cd4aedc42343240f4e760c0abb48c8e2b35c3","src/block/reader.rs":"3a3ce127fe1ba943d21b54b81f6a3848a0442cd073831b26b790e5a93bc46925","src/block/samples.rs":"94013224cb670c56aa8030fbc9e42c506d3cc4f396c28a2ee523e42bb79e52ac","src/block/writer.rs":"78774e11d3a048e48f88c376e0566fe391b6874027ae1f62a70d06c7d587d8f4","src/compression/b44/mod.rs":"287e763c8f2aa39cf731ac4a840a49e0dc347d72b18c3d3a8c33df0efce7888e","src/compression/b44/table.rs":"2b1d1dc47b0d210044b713b7e0feba743f2e02bd4c9f7da9023387411758b54c","src/compression/mod.rs":"3161c1e814add058dfdf88b0161df93ddacc686623632c3eee6270e9007243d1","src/compression/piz/huffman.rs":"4d94571178f390f065f469d142b76640f61e5c5d30ca0731ae9e731d1763347c","src/compression/piz/mod.rs":"a55da17fc9626c178bd9a846dc4293da8687bcb5453b5965dd3b2e232892cf60","src/compression/piz/wavelet.rs":"d830399ce5c1d3c749c328bd0956effd16771a4a7873f0a7f94999f0cb7275b6","src/compression/pxr24.rs":"d106da66ca339e03a0b6c4d137ca73dfc803a06e2fdd53b105157281ed170fbc","src/compression/rle.rs":"679d1207cff831c9ee2e0426386fd83321a436343fb63d20064d7614890bb1d0","src/compression/zip.rs":"d582a016d853b7c1a2daa0696b8bfee878e09891944c8516111ad5ed8f3152ee","src/error.rs":"a519ced787beaf1aedf348a6e69162e6ef5b3a83ee9cd81c481b446f39389abd","src/image/channel_groups.rs":"2e8ed9f0d1f4cea6e500eedcaedcc8b1b5a2eeb91083253836c5ccf7ff61f07b","src/image/crop.rs":"b549101e84c38603d1f8f6a28a8b949e092ff9f24ecfd02984334441f79c1779","src/image/mod.rs":"f4a4c255c160c810bd849ec04de80c4ca0ba4efede0b7ac8493eb94fd3456c57","src/image/pixel_vec.rs":"0011a9b211a1f6df8e269facfa569408647fb0dfc787f254b098e15a91219455","src/image/read/any_channels.rs":"691abe56ce69aebca17a4395a3ba6aeadba3f02f1ae14bf1081d3ba9946f3d87","src/image/read/image.rs":"478a030e5d82085020248a5465770397109a5503e1cfacc0a2b5689070d05ec6","src/image/read/layers.rs":"6b1c155ce5131e3c4350b2d2e3b939bf0533e41bc4efc3642f888c99847985c1","src/image/read/levels.rs":"aeef8b0b6a66ed541b17eb09ead683cb1b62b0fb72f1460274cf7980f3e7fb55","src/image/read/mod.rs":"ff4950469b3d67316f4cd4440fa1e503346fd305c82f05255acec6c65c3c0065","src/image/read/samples.rs":"8143d291cc2191d3c6e0127de6ae25787201efe9b535dd6212e00438c0dab0b3","src/image/read/specific_channels.rs":"d0c63901a02cca62745dd0e4eda96d808c29f9818ab7fce28daab9e06d6beb52","src/image/recursive.rs":"88c3270fae8d4d0cbf30301e1f6ee5ec91ccf28eb2c825010ab648e5f3787908","src/image/write/channels.rs":"b6084d613331334ab04b7d4b5396a1299b427c6a871902fcdf033c74f4b7fc4c","src/image/write/layers.rs":"49b821a14394e215efd3520ae4ecaade7228b41ac3e4ded5c6236a10e9708a05","src/image/write/mod.rs":"28d9252fa63a3f41c76f917ddd6ce53f6fc0f00dddcc4fc6b47e3acd2b1460e4","src/image/write/samples.rs":"4eb4b91b467c99d9595055811817836d5d3ffb8e0a788d753e7cae1bf47b2e03","src/io.rs":"080089c0fed82e7fedb3ecbd2ae393416ffcddb3b45b359a1269206bd6112224","src/lib.rs":"7f5724c98504161c45b508bd1e806bad1bf292fdb1cbfd4f59949212aca5b9b4","src/math.rs":"2e204e7f273189748fe89f93243a3c76694ba33a9089cda9440bbe4f4b27ef38","src/meta/attribute.rs":"66d434fdce550403661bbf2e530cf732f4f8c282b2fb670b4f4d3f6e21959938","src/meta/header.rs":"43fd3e85f0a822495249b115a0638ef1c79040a25a4b5e3a717a7833958cee10","src/meta/mod.rs":"0f96f70ebea8bdaf472c507c20b64f1559a95891e0ac497daf01d3b2703fb504","tests/across_compression.rs":"a35d98f679ade1991f77ed16d55d981e18d72384a6b4d10cf7d00979c07ceac0","tests/dev.rs":"f10858a0df2bbc1c78680eda7e00b03611de1c4618fa7cba837dba3254104f1f","tests/fuzz.rs":"d8947b4993b0d2261f83b983beeea0a6f13e9c86ac3a0ffc0fbfcbe442138463","tests/roundtrip.rs":"4a0d78851c89b713222a512c88ca957b5ed12ef47ae8a861bfd48412508bf5ee"},"package":"4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "15d67d8202e2dbcdbdcc0e680bde87f747abe81e" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/bug_report.md clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/bug_report.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/bug_report.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/bug_report.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +# Description +What happened? + +# Reproducing +How can we reproduce the behaviour? Embed code snippets and problematic EXR files. + +# Environment +- Operating System +- CPU Model (Big Endian or Little Endian?) +- EXRS Version used diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/feature_request.md clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/feature_request.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/feature_request.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/feature_request.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: 'enhancement' +assignees: '' + +--- + +## What can be improved or is missing? +"Feature X is important for doing Y." + +## Implementation Approach +If you have an idea, +outline one or two approaches +how the feature could look on the surface. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/other.md clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/other.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/other.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/other.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +--- +name: Other +about: Nothing of above +title: '' +assignees: '' +--- diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/question.md clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/question.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/question.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/ISSUE_TEMPLATE/question.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +--- +name: Question +about: Something's unclear or undocumented +title: '' +labels: question +assignees: '' + +--- + +I wanted to do X. +I expected to find it in the documentation for Y or example Z. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/exr/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,127 @@ +name: Rust + +on: + push: + branches: [ master, dev ] + pull_request: + branches: [ master, dev ] + +jobs: + ubuntu: + runs-on: ubuntu-latest + name: test on ubuntu + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v2 + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v1.3.0 + - name: Build without default features + run: cargo build --no-default-features --verbose + - name: Run tests without default features + run: cargo test --no-default-features --verbose + - name: Build with rayon feature + run: cargo build --features rayon --verbose + - name: Run tests with rayon feature + run: cargo test --features rayon --verbose + + + macos: + runs-on: macos-latest + name: test on mac os + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v2 + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v1.3.0 + - name: Build without default features + run: cargo build --no-default-features --verbose + - name: Run tests without default features + run: cargo test --no-default-features --verbose + - name: Build with rayon feature + run: cargo build --features rayon --verbose + - name: Run tests with rayon feature + run: cargo test --features rayon --verbose + + verify-msrv: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + name: verify minimum supported rust version without cache (takes longer, but caching produces unexpected behaviour) + timeout-minutes: 30 + + # we are using the `cargo-msrv` app + # https://github.com/foresterre/cargo-msrv + + steps: + - uses: actions/checkout@v2 + + - name: Install foresterre/cargo-msrv + run: cargo install cargo-msrv + + - uses: dtolnay/rust-toolchain@nightly + - name: Generate Cargo.lock with minimal-version dependencies + run: cargo -Zminimal-versions generate-lockfile + + - name: Verify the Rustc version declared in `Cargo.toml` with `minimal-versions` + run: cargo-msrv verify + + # github actions does not support big endian systems directly, but it does support QEMU. + # so we use cross-rs, which uses QEMU internally. + big-endian: + runs-on: ubuntu-latest + name: test on emulated big endian system + timeout-minutes: 90 # todo just make tests faster wtf + + # we are using the cross project for cross compilation: + # https://github.com/cross-rs/cross + + steps: + - uses: actions/checkout@v2 + + - name: Install or use cached cross-rs/cross + uses: baptiste0928/cargo-install@v1 + with: + crate: cross + + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v1.3.0 + + - name: Start Docker + run: sudo systemctl start docker + + # https://github.com/cross-rs/cross#supported-targets + - name: Cross-Compile project to powerpc-unknown-linux-gnu without rayon feature + run: cross build --target powerpc-unknown-linux-gnu --no-default-features --verbose + + - name: Cross-Run Tests in powerpc-unknown-linux-gnu without rayon feature + run: cross test --target powerpc-unknown-linux-gnu --no-default-features --verbose + + - name: Cross-Compile project to powerpc-unknown-linux-gnu with rayon feature + run: cross build --target powerpc-unknown-linux-gnu --features rayon --verbose + + - name: Cross-Run Tests in powerpc-unknown-linux-gnu with rayon feature + run: cross test --target powerpc-unknown-linux-gnu --features rayon --verbose + + wasm32: + runs-on: ubuntu-latest + name: test on wasm32 + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v1.3.0 + + - name: Add wasm32 Target + run: rustup target add wasm32-unknown-unknown + + - name: Build without default features + run: cargo build --verbose --no-default-features --target wasm32-unknown-unknown + + - name: Run tests without default features + run: cargo test --verbose --no-default-features + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -3,16 +3,16 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bencher" @@ -22,54 +22,48 @@ [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "bytemuck" -version = "1.14.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" [[package]] -name = "byteorder" -version = "1.5.0" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "color_quant" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -86,29 +80,28 @@ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "either" -version = "1.9.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "exr" -version = "1.72.0" +version = "1.74.0" dependencies = [ "bencher", "bit_field", - "flume", "half", "image", "lebe", @@ -123,37 +116,28 @@ [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] - -[[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -162,9 +146,9 @@ [[package]] name = "half" -version = "2.3.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -172,13 +156,13 @@ [[package]] name = "image" -version = "0.24.8" +version = "0.25.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" dependencies = [ "bytemuck", - "byteorder", - "color_quant", + "byteorder-lite", + "moxcms", "num-traits", "png", ] @@ -191,44 +175,44 @@ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] -name = "lock_api" -version = "0.4.11" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "autocfg", - "scopeguard", + "adler2", + "simd-adler32", ] [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "moxcms" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" dependencies = [ - "adler", - "simd-adler32", + "num-traits", + "pxfm", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "png" -version = "0.17.11" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ "bitflags", "crc32fast", @@ -239,9 +223,39 @@ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55f4fedc84ed39cb7a489322318976425e42a147e2be79d8f878e2884f94e84" +dependencies = [ + "num-traits", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] [[package]] name = "rand" @@ -275,9 +289,9 @@ [[package]] name = "rayon" -version = "1.8.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -285,9 +299,9 @@ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -303,12 +317,6 @@ ] [[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -316,24 +324,32 @@ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "spin" -version = "0.9.8" +name = "syn" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ - "lock_api", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -341,40 +357,118 @@ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "winapi" -version = "0.3.9" +name = "winapi-util" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-sys", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] -name = "winapi-util" -version = "0.1.6" +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "winapi", + "zerocopy-derive", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "zerocopy-derive" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "zune-inflate" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -13,14 +13,20 @@ edition = "2018" rust-version = "1.61.0" name = "exr" -version = "1.72.0" -authors = ["johannesvollmer "] +version = "1.74.0" +authors = ["johannesvollmer "] +build = false exclude = [ "specification/*", "specification/**", "tests/images/*", "tests/images/**", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Read and write OpenEXR files without any unsafe code" readme = "README.md" keywords = [ @@ -39,69 +45,143 @@ license = "BSD-3-Clause" repository = "https://github.com/johannesvollmer/exrs" -[profile.bench] -opt-level = 3 -lto = true -codegen-units = 1 -debug = 2 -debug-assertions = false -overflow-checks = false - -[profile.dev] -opt-level = 3 -lto = true -debug = 2 -debug-assertions = true -overflow-checks = true -incremental = true - -[profile.release] -opt-level = 3 -lto = true -codegen-units = 1 -debug = 0 -debug-assertions = false +[badges.maintenance] +status = "actively-developed" -[profile.test] -opt-level = 3 -lto = true -debug = 2 -debug-assertions = true -overflow-checks = true -incremental = true +[features] +default = ["rayon"] +rayon = ["dep:rayon-core"] [lib] +name = "exr" path = "src/lib.rs" test = true doctest = true bench = true doc = true -plugin = false proc-macro = false +[[example]] +name = "0a_write_rgba" +path = "examples/0a_write_rgba.rs" + +[[example]] +name = "0b_read_meta" +path = "examples/0b_read_meta.rs" + +[[example]] +name = "0c_read_rgba" +path = "examples/0c_read_rgba.rs" + +[[example]] +name = "1a_write_rgba_with_metadata" +path = "examples/1a_write_rgba_with_metadata.rs" + +[[example]] +name = "1b_convert_exr_to_png" +path = "examples/1b_convert_exr_to_png.rs" + +[[example]] +name = "2_rgba_adjust_exposure" +path = "examples/2_rgba_adjust_exposure.rs" + +[[example]] +name = "3a_write_dynamic_channels_with_metadata" +path = "examples/3a_write_dynamic_channels_with_metadata.rs" + +[[example]] +name = "3b_read_all_channels_with_metadata" +path = "examples/3b_read_all_channels_with_metadata.rs" + +[[example]] +name = "4a_write_custom_fixed_channels" +path = "examples/4a_write_custom_fixed_channels.rs" + +[[example]] +name = "4b_read_custom_fixed_channels" +path = "examples/4b_read_custom_fixed_channels.rs" + +[[example]] +name = "5a_write_multiple_layers" +path = "examples/5a_write_multiple_layers.rs" + +[[example]] +name = "5b_extract_exr_layers_as_pngs" +path = "examples/5b_extract_exr_layers_as_pngs.rs" + +[[example]] +name = "5c_write_mip_maps" +path = "examples/5c_write_mip_maps.rs" + +[[example]] +name = "5d_write_legacy_layers" +path = "examples/5d_write_legacy_layers.rs" + +[[example]] +name = "6_extract_mip_map_pngs" +path = "examples/6_extract_mip_map_pngs.rs" + +[[example]] +name = "7_crop_alpha_any_image" +path = "examples/7_crop_alpha_any_image.rs" + +[[example]] +name = "7_crop_alpha_rgba" +path = "examples/7_crop_alpha_rgba.rs" + +[[example]] +name = "7_write_raw_blocks" +path = "examples/7_write_raw_blocks.rs" +required-features = ["rayon"] + +[[example]] +name = "8_read_raw_blocks" +path = "examples/8_read_raw_blocks.rs" +required-features = ["rayon"] + +[[test]] +name = "across_compression" +path = "tests/across_compression.rs" + +[[test]] +name = "dev" +path = "tests/dev.rs" + +[[test]] +name = "fuzz" +path = "tests/fuzz.rs" + +[[test]] +name = "roundtrip" +path = "tests/roundtrip.rs" + [[bench]] -name = "read" +name = "pixel_format_conversion" +path = "benches/pixel_format_conversion.rs" harness = false +required-features = ["rayon"] [[bench]] name = "profiling" +path = "benches/profiling.rs" harness = false +required-features = ["rayon"] [[bench]] -name = "write" +name = "read" +path = "benches/read.rs" harness = false +required-features = ["rayon"] [[bench]] -name = "pixel_format_conversion" +name = "write" +path = "benches/write.rs" harness = false +required-features = ["rayon"] [dependencies.bit_field] version = "^0.10.1" -[dependencies.flume] -version = "^0.11.0" -default-features = false - [dependencies.half] version = "2.1.0" @@ -109,10 +189,11 @@ version = "^0.5.2" [dependencies.miniz_oxide] -version = "^0.7.1" +version = "^0.8.0" [dependencies.rayon-core] version = "^1.11.0" +optional = true [dependencies.smallvec] version = "^1.7.0" @@ -126,7 +207,7 @@ version = "0.1.5" [dev-dependencies.image] -version = "0.24.3" +version = "0.25.2" features = ["png"] default-features = false @@ -139,5 +220,33 @@ [dev-dependencies.walkdir] version = "2.3.2" -[badges.maintenance] -status = "actively-developed" +[profile.bench] +opt-level = 3 +lto = true +codegen-units = 1 +debug = 2 +debug-assertions = false +overflow-checks = false + +[profile.dev] +opt-level = 3 +lto = true +debug = 2 +debug-assertions = true +overflow-checks = true +incremental = true + +[profile.release] +opt-level = 3 +lto = true +codegen-units = 1 +debug = 0 +debug-assertions = false + +[profile.test] +opt-level = 3 +lto = true +debug = 2 +debug-assertions = true +overflow-checks = true +incremental = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/exr/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,113 @@ +[package] +name = "exr" +description = "Read and write OpenEXR files without any unsafe code" +keywords = ["exr", "openexr", "file", "binary", "io"] +categories = ["encoding", "filesystem", "graphics", "multimedia"] + +version = "1.74.0" +edition = "2018" +authors = ["johannesvollmer "] + +repository = "https://github.com/johannesvollmer/exrs" +readme = "README.md" +license = "BSD-3-Clause" +exclude = [ "specification/*", "specification/**", "tests/images/*", "tests/images/**" ] +rust-version = "1.61.0" + +[badges] +maintenance = { status = "actively-developed" } + +[lib] +path = "src/lib.rs" +test = true +doctest = true +bench = true +doc = true +plugin = false +proc-macro = false + +[dependencies] +lebe = "^0.5.2" # generic binary serialization +half = "2.1.0" # 16 bit float pixel data type +bit_field = "^0.10.1" # exr file version bit flags +miniz_oxide = "^0.8.0" # zip compression for pxr24 +smallvec = "^1.7.0" # make cache-friendly allocations TODO profile if smallvec is really an improvement! +rayon-core = { version = "^1.11.0", optional = true } # threading for parallel compression +zune-inflate = { version = "^0.2.3", default-features = false, features = ["zlib"] } # zip decompression, faster than miniz_oxide + +[dev-dependencies] +image = { version = "0.25.2", default-features = false, features = ["png"] } # used to convert one exr to some pngs + +bencher = "0.1.5" +walkdir = "2.3.2" # automatically test things for all files in a directory +rand = "0.8.5" # used for fuzz testing +rayon = "1.5.3" # run tests for many files in parallel + +[features] +default = ["rayon"] + +# rayon is used for parallel compression +rayon = ["dep:rayon-core"] + +[[example]] +name = "7_write_raw_blocks" +required-features = ["rayon"] + +[[example]] +name = "8_read_raw_blocks" +required-features = ["rayon"] + +[[bench]] +name = "read" +harness = false +required-features = ["rayon"] + +[[bench]] +name = "profiling" +harness = false +required-features = ["rayon"] + +[[bench]] +name = "write" +harness = false +required-features = ["rayon"] + +[[bench]] +name = "pixel_format_conversion" +harness = false +required-features = ["rayon"] + +# recommended release settings for max runtime performance +[profile.release] +opt-level = 3 +lto = true +debug = false +debug-assertions = false +codegen-units = 1 + +# test with fast runtime speed and slow build speed +[profile.dev] +incremental = true +opt-level = 3 +debug-assertions = true +overflow-checks = true +debug = true +lto = true + +# test with fast runtime speed and moderate build speed +[profile.test] +incremental = true +opt-level = 3 +debug-assertions = true +overflow-checks = true +debug = true +lto = true + +# bench with fastest runtime speed +[profile.bench] +opt-level = 3 +debug-assertions = false +overflow-checks = false +lto = true +debug = true +codegen-units = 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/README.md clamav-1.4.6+dfsg/.cargo/vendor/exr/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,6 @@ -[![Rust Docs](https://docs.rs/exr/badge.svg)](https://docs.rs/exr) [![Rust Crate](https://img.shields.io/crates/v/exr.svg)](https://crates.io/crates/exr) -[![Rust Lang Version](https://img.shields.io/badge/rustc-1.61.0-lightgray.svg)](https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html) +[![Crates.io MSRV](https://img.shields.io/crates/msrv/exr?label=minimum%20rust%20version)](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field) +[![Rust Docs](https://docs.rs/exr/badge.svg)](https://docs.rs/exr) [![Wasm Ready](https://img.shields.io/badge/wasm-supported-%236d0)](https://github.com/johannesvollmer/exrs/actions?query=branch%3Amaster) [![downloads](https://img.shields.io/crates/d/exr)](https://crates.io/crates/exr) [![Lines of Code](https://tokei.rs/b1/github/johannesvollmer/exrs?category=code)](https://tokei.rs) @@ -68,7 +68,7 @@ - [x] a full-fledged image data structure that can contain any exr image, can open any image with a single function call (`read_all_data_from_file`) without knowing anything about the file in advance - - [x] decompress and decompress image sections either + - [x] compress and decompress image sections either in parallel or with low memory overhead - [x] read and write progress callback - [x] write blocks streams, one after another @@ -164,7 +164,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -exr = "1.72.0" +exr = "1.74.0" # also, optionally add this to your crate for smaller binary size # and better runtime performance @@ -301,6 +301,10 @@ To run all fast tests on an emulated system, use one of the following commands. Each command requires a running `docker` instance, and `cross-rs` to be installed on your machine (`cargo install cross`). -- Mips (Big Endian) `cross test --target mips-unknown-linux-gnu --verbose` +- Powerpc (Big Endian) `cross test --target powerpc-unknown-linux-gnu --verbose` +You may also need to install the toolchain beforehand, using +`rustup toolchain add stable-x86_64-unknown-linux-gnu --profile minimal --force-non-host` +and `rustup target add powerpc-unknown-linux-gnu`. + To benchmark the library, simply run `cargo bench`. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/benches/pixel_format_conversion.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/benches/pixel_format_conversion.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/benches/pixel_format_conversion.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/benches/pixel_format_conversion.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,7 +8,6 @@ use std::fs; use std::io::Cursor; use exr::image::pixel_vec::PixelVec; -use exr::io::Data; use exr::block::samples::FromNativeSample; const F32_ZIPS_PATH: &'static str = "tests/images/valid/custom/crowskull/crow_zips.exr"; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/examples/README.md clamav-1.4.6+dfsg/.cargo/vendor/exr/examples/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/exr/examples/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/examples/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -18,7 +18,8 @@ ## Older Versions The examples for any specific `exrs` version can be found on the `docs.rs` page: +- [docs.rs/crate/exr/1.74.0/source/examples/](https://docs.rs/crate/exr/1.74.0/source/examples/) +- [docs.rs/crate/exr/1.73.0/source/examples/](https://docs.rs/crate/exr/1.73.0/source/examples/) - [docs.rs/crate/exr/1.72.0/source/examples/](https://docs.rs/crate/exr/1.7.0/source/examples/) - [docs.rs/crate/exr/1.71.0/source/examples/](https://docs.rs/crate/exr/1.7.0/source/examples/) -- [docs.rs/crate/exr/1.7.0/source/examples/](https://docs.rs/crate/exr/1.7.0/source/examples/) - ... \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/chunk.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/chunk.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/chunk.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/chunk.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,6 +9,8 @@ /// All pixel data in a file is split into a list of chunks. /// Also contains positioning information that locates this /// data block in the referenced layer. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub struct Chunk { @@ -18,6 +20,7 @@ pub layer_index: usize, /// The compressed pixel contents. + /// This data is compressed and in little-endian format. pub compressed_block: CompressedBlock, } @@ -26,6 +29,8 @@ /// Also contains positioning information that locates this /// data block in the corresponding layer. /// Exists inside a `Chunk`. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub enum CompressedBlock { @@ -44,6 +49,8 @@ /// A `Block` of possibly compressed flat scan lines. /// Corresponds to type attribute `scanlineimage`. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub struct CompressedScanLineBlock { @@ -54,11 +61,14 @@ /// One or more scan lines may be stored together as a scan line block. /// The number of scan lines per block depends on how the pixel data are compressed. /// For each line in the tile, for each channel, the row values are contiguous. - pub compressed_pixels: Vec, + /// This data is compressed and in little-endian format. + pub compressed_pixels_le: Vec, } /// This `Block` is a tile of flat (non-deep) data. /// Corresponds to type attribute `tiledimage`. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub struct CompressedTileBlock { @@ -68,7 +78,8 @@ /// One or more scan lines may be stored together as a scan line block. /// The number of scan lines per block depends on how the pixel data are compressed. /// For each line in the tile, for each channel, the row values are contiguous. - pub compressed_pixels: Vec, + /// This data is compressed and in little-endian format. + pub compressed_pixels_le: Vec, } /// Indicates the position and resolution level of a `TileBlock` or `DeepTileBlock`. @@ -84,6 +95,8 @@ /// This `Block` consists of one or more deep scan lines. /// Corresponds to type attribute `deepscanline`. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub struct CompressedDeepScanLineBlock { @@ -102,11 +115,13 @@ /// One or more scan lines may be stored together as a scan line block. /// The number of scan lines per block depends on how the pixel data are compressed. /// For each line in the tile, for each channel, the row values are contiguous. - pub compressed_sample_data: Vec, + pub compressed_sample_data_le: Vec, } /// This `Block` is a tile of deep data. /// Corresponds to type attribute `deeptile`. +/// The byte data is in little-endian format, +/// as these bytes will be written into the file directly. #[derive(Debug, Clone)] pub struct CompressedDeepTileBlock { @@ -124,7 +139,7 @@ /// One or more scan lines may be stored together as a scan line block. /// The number of scan lines per block depends on how the pixel data are compressed. /// For each line in the tile, for each channel, the row values are contiguous. - pub compressed_sample_data: Vec, + pub compressed_sample_data_le: Vec, } @@ -134,20 +149,20 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - i32::write(usize_to_i32(self.tile_index.x()), write)?; - i32::write(usize_to_i32(self.tile_index.y()), write)?; - i32::write(usize_to_i32(self.level_index.x()), write)?; - i32::write(usize_to_i32(self.level_index.y()), write)?; + i32::write_le(usize_to_i32(self.tile_index.x(), "tile x")?, write)?; + i32::write_le(usize_to_i32(self.tile_index.y(), "tile y")?, write)?; + i32::write_le(usize_to_i32(self.level_index.x(), "level x")?, write)?; + i32::write_le(usize_to_i32(self.level_index.y(), "level y")?, write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut impl Read) -> Result { - let tile_x = i32::read(read)?; - let tile_y = i32::read(read)?; + let tile_x = i32::read_le(read)?; + let tile_y = i32::read_le(read)?; - let level_x = i32::read(read)?; - let level_y = i32::read(read)?; + let level_x = i32::read_le(read)?; + let level_y = i32::read_le(read)?; if level_x > 31 || level_y > 31 { // there can be at most 31 levels, because the largest level would have a size of 2^31, @@ -173,7 +188,7 @@ } else { Ok(IntegerBounds { - position: Vec2(usize_to_i32(x), usize_to_i32(y)), + position: Vec2(usize_to_i32(x, "tile x")?, usize_to_i32(y, "tile y")?), size: Vec2( calculate_block_size(max.x(), tile_size.width(), x)?, calculate_block_size(max.y(), tile_size.height(), y)?, @@ -202,18 +217,18 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - debug_assert_ne!(self.compressed_pixels.len(), 0, "empty blocks should not be put in the file bug"); + debug_assert_ne!(self.compressed_pixels_le.len(), 0, "empty blocks should not be put in the file bug"); - i32::write(self.y_coordinate, write)?; - u8::write_i32_sized_slice(write, &self.compressed_pixels)?; + i32::write_le(self.y_coordinate, write)?; + u8::write_i32_sized_slice_le(write, &self.compressed_pixels_le)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result { - let y_coordinate = i32::read(read)?; - let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "scan line block sample count")?; - Ok(CompressedScanLineBlock { y_coordinate, compressed_pixels }) + let y_coordinate = i32::read_le(read)?; + let compressed_pixels_le = u8::read_i32_sized_vec_le(read, max_block_byte_size, Some(max_block_byte_size), "scan line block sample count")?; + Ok(CompressedScanLineBlock { y_coordinate, compressed_pixels_le }) } } @@ -221,18 +236,18 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - debug_assert_ne!(self.compressed_pixels.len(), 0, "empty blocks should not be put in the file bug"); + debug_assert_ne!(self.compressed_pixels_le.len(), 0, "empty blocks should not be put in the file bug"); self.coordinates.write(write)?; - u8::write_i32_sized_slice(write, &self.compressed_pixels)?; + u8::write_i32_sized_slice_le(write, &self.compressed_pixels_le)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result { let coordinates = TileCoordinates::read(read)?; - let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "tile block sample count")?; - Ok(CompressedTileBlock { coordinates, compressed_pixels }) + let compressed_pixels_le = u8::read_i32_sized_vec_le(read, max_block_byte_size, Some(max_block_byte_size), "tile block sample count")?; + Ok(CompressedTileBlock { coordinates, compressed_pixels_le }) } } @@ -240,32 +255,32 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - debug_assert_ne!(self.compressed_sample_data.len(), 0, "empty blocks should not be put in the file bug"); + debug_assert_ne!(self.compressed_sample_data_le.len(), 0, "empty blocks should not be put in the file bug"); - i32::write(self.y_coordinate, write)?; - u64::write(self.compressed_pixel_offset_table.len() as u64, write)?; - u64::write(self.compressed_sample_data.len() as u64, write)?; // TODO just guessed - u64::write(self.decompressed_sample_data_size as u64, write)?; - i8::write_slice(write, &self.compressed_pixel_offset_table)?; - u8::write_slice(write, &self.compressed_sample_data)?; + i32::write_le(self.y_coordinate, write)?; + u64::write_le(self.compressed_pixel_offset_table.len() as u64, write)?; + u64::write_le(self.compressed_sample_data_le.len() as u64, write)?; // TODO just guessed + u64::write_le(self.decompressed_sample_data_size as u64, write)?; + i8::write_slice_le(write, &self.compressed_pixel_offset_table)?; + u8::write_slice_le(write, &self.compressed_sample_data_le)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result { - let y_coordinate = i32::read(read)?; - let compressed_pixel_offset_table_size = u64_to_usize(u64::read(read)?); - let compressed_sample_data_size = u64_to_usize(u64::read(read)?); - let decompressed_sample_data_size = u64_to_usize(u64::read(read)?); + let y_coordinate = i32::read_le(read)?; + let compressed_pixel_offset_table_size = u64_to_usize(u64::read_le(read)?, "deep table size")?; + let compressed_sample_data_size = u64_to_usize(u64::read_le(read)?, "deep size")?; + let decompressed_sample_data_size = u64_to_usize(u64::read_le(read)?, "raw deep size")?; // doc said i32, try u8 - let compressed_pixel_offset_table = i8::read_vec( + let compressed_pixel_offset_table = i8::read_vec_le( read, compressed_pixel_offset_table_size, 6 * u16::MAX as usize, Some(max_block_byte_size), "deep scan line block table size" )?; - let compressed_sample_data = u8::read_vec( + let compressed_sample_data_le = u8::read_vec_le( read, compressed_sample_data_size, 6 * u16::MAX as usize, Some(max_block_byte_size), "deep scan line block sample count" @@ -275,7 +290,7 @@ y_coordinate, decompressed_sample_data_size, compressed_pixel_offset_table, - compressed_sample_data, + compressed_sample_data_le, }) } } @@ -285,31 +300,31 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - debug_assert_ne!(self.compressed_sample_data.len(), 0, "empty blocks should not be put in the file bug"); + debug_assert_ne!(self.compressed_sample_data_le.len(), 0, "empty blocks should not be put in the file bug"); self.coordinates.write(write)?; - u64::write(self.compressed_pixel_offset_table.len() as u64, write)?; - u64::write(self.compressed_sample_data.len() as u64, write)?; // TODO just guessed - u64::write(self.decompressed_sample_data_size as u64, write)?; - i8::write_slice(write, &self.compressed_pixel_offset_table)?; - u8::write_slice(write, &self.compressed_sample_data)?; + u64::write_le(self.compressed_pixel_offset_table.len() as u64, write)?; + u64::write_le(self.compressed_sample_data_le.len() as u64, write)?; // TODO just guessed + u64::write_le(self.decompressed_sample_data_size as u64, write)?; + i8::write_slice_le(write, &self.compressed_pixel_offset_table)?; + u8::write_slice_le(write, &self.compressed_sample_data_le)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut impl Read, hard_max_block_byte_size: usize) -> Result { let coordinates = TileCoordinates::read(read)?; - let compressed_pixel_offset_table_size = u64_to_usize(u64::read(read)?); - let compressed_sample_data_size = u64_to_usize(u64::read(read)?); // TODO u64 just guessed - let decompressed_sample_data_size = u64_to_usize(u64::read(read)?); + let compressed_pixel_offset_table_size = u64_to_usize(u64::read_le(read)?,"deep table size")?; + let compressed_sample_data_size = u64_to_usize(u64::read_le(read)?, "deep size")?; // TODO u64 just guessed + let decompressed_sample_data_size = u64_to_usize(u64::read_le(read)?, "raw deep size")?; - let compressed_pixel_offset_table = i8::read_vec( + let compressed_pixel_offset_table = i8::read_vec_le( read, compressed_pixel_offset_table_size, 6 * u16::MAX as usize, Some(hard_max_block_byte_size), "deep tile block table size" )?; - let compressed_sample_data = u8::read_vec( + let compressed_sample_data_le = u8::read_vec_le( read, compressed_sample_data_size, 6 * u16::MAX as usize, Some(hard_max_block_byte_size), "deep tile block sample count" @@ -319,7 +334,7 @@ coordinates, decompressed_sample_data_size, compressed_pixel_offset_table, - compressed_sample_data, + compressed_sample_data_le, }) } } @@ -334,7 +349,7 @@ pub fn write(&self, write: &mut impl Write, header_count: usize) -> UnitResult { debug_assert!(self.layer_index < header_count, "layer index bug"); // validation is done in full_image or simple_image - if header_count != 1 { usize_to_i32(self.layer_index).write(write)?; } + if header_count != 1 { usize_to_i32(self.layer_index, "layer index")?.write_le(write)?; } else { assert_eq!(self.layer_index, 0, "invalid header index for single layer file"); } match self.compressed_block { @@ -348,7 +363,7 @@ /// Read the value without validating. pub fn read(read: &mut impl Read, meta_data: &MetaData) -> Result { let layer_number = i32_to_usize( - if meta_data.requirements.is_multilayer() { i32::read(read)? } // documentation says u64, but is i32 + if meta_data.requirements.is_multilayer() { i32::read_le(read)? } // documentation says u64, but is i32 else { 0_i32 }, // reference the first header for single-layer images "chunk data part number" )?; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/lines.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/lines.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/lines.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/lines.rs 2006-07-24 01:21:28.000000000 +0000 @@ -145,14 +145,14 @@ impl<'s> LineRefMut<'s> { /// Writes the samples (f16, f32, u32 values) into this line value reference. - /// Use `write_samples` if there is not slice available. + /// Use `write_samples` if there is no slice available. #[inline] #[must_use] pub fn write_samples_from_slice(self, slice: &[T]) -> UnitResult { debug_assert_eq!(slice.len(), self.location.sample_count, "slice size does not match the line width"); debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size"); - T::write_slice(&mut Cursor::new(self.value), slice) + T::write_slice_ne(&mut Cursor::new(self.value), slice) } /// Iterate over all samples in this line, from left to right. @@ -168,7 +168,7 @@ let mut write = Cursor::new(self.value); for index in 0..self.location.sample_count { - T::write(get_sample(index), &mut write)?; + T::write_ne(get_sample(index), &mut write)?; } Ok(()) @@ -183,7 +183,7 @@ debug_assert_eq!(slice.len(), self.location.sample_count, "slice size does not match the line width"); debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size"); - T::read_slice(&mut Cursor::new(self.value), slice) + T::read_slice_ne(&mut Cursor::new(self.value), slice) } /// Iterate over all samples in this line, from left to right. @@ -192,6 +192,6 @@ debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size"); let mut read = self.value; // FIXME deep data - (0..self.location.sample_count).map(move |_| T::read(&mut read)) + (0..self.location.sample_count).map(move |_| T::read_ne(&mut read)) } } \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -48,6 +48,8 @@ } /// Contains a block of pixel data and where that data should be placed in the actual image. +/// The bytes must be encoded in native-endian format. +/// The conversion to little-endian format happens when converting to chunks (potentially in parallel). #[derive(Clone, Eq, PartialEq, Debug)] pub struct UncompressedBlock { @@ -59,6 +61,7 @@ /// This byte vector contains all pixel rows, one after another. /// For each line in the tile, for each channel, the row values are contiguous. /// Stores all samples of the first channel, then all samples of the second channel, and so on. + /// This data is in native-endian format. pub data: ByteVec, } @@ -126,10 +129,10 @@ absolute_indices.validate(Some(header.layer_size))?; match chunk.compressed_block { - CompressedBlock::Tile(CompressedTileBlock { compressed_pixels, .. }) | - CompressedBlock::ScanLine(CompressedScanLineBlock { compressed_pixels, .. }) => { + CompressedBlock::Tile(CompressedTileBlock { compressed_pixels_le, .. }) | + CompressedBlock::ScanLine(CompressedScanLineBlock { compressed_pixels_le, .. }) => { Ok(UncompressedBlock { - data: header.compression.decompress_image_section(header, compressed_pixels, absolute_indices, pedantic)?, + data: header.compression.decompress_image_section_from_le(header, compressed_pixels_le, absolute_indices, pedantic)?, index: BlockIndex { layer: chunk.layer_index, pixel_position: absolute_indices.position.to_usize("data indices start")?, @@ -168,9 +171,9 @@ absolute_indices.validate(Some(header.layer_size))?; if !header.compression.may_loose_data() { debug_assert_eq!( - &header.compression.decompress_image_section( + &header.compression.decompress_image_section_from_le( header, - header.compression.compress_image_section(header, data.clone(), absolute_indices)?, + header.compression.compress_image_section_to_le(header, data.clone(), absolute_indices)?, absolute_indices, true ).unwrap(), @@ -178,20 +181,20 @@ "compression method not round trippin'" ); } - let compressed_data = header.compression.compress_image_section(header, data, absolute_indices)?; + let compressed_pixels_le = header.compression.compress_image_section_to_le(header, data, absolute_indices)?; Ok(Chunk { layer_index: index.layer, compressed_block : match header.blocks { BlockDescription::ScanLines => CompressedBlock::ScanLine(CompressedScanLineBlock { - compressed_pixels: compressed_data, + compressed_pixels_le, // FIXME this calculation should not be made here but elsewhere instead (in meta::header?) - y_coordinate: usize_to_i32(index.pixel_position.y()) + header.own_attributes.layer_position.y(), // TODO sampling?? + y_coordinate: usize_to_i32(index.pixel_position.y(), "pixel index")? + header.own_attributes.layer_position.y(), // TODO sampling?? }), BlockDescription::Tiles(_) => CompressedBlock::Tile(CompressedTileBlock { - compressed_pixels: compressed_data, + compressed_pixels_le, coordinates: tile_coordinates, }), } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/reader.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,13 +4,8 @@ use std::convert::TryFrom; use std::fmt::Debug; use std::io::{Read, Seek}; -use rayon_core::{ThreadPool, ThreadPoolBuildError}; - -use smallvec::alloc::sync::Arc; - use crate::block::{BlockIndex, UncompressedBlock}; use crate::block::chunk::{Chunk, TileCoordinates}; -use crate::compression::Compression; use crate::error::{Error, Result, u64_to_usize, UnitResult}; use crate::io::{PeekRead, Tracking}; use crate::meta::{MetaData, OffsetTables}; @@ -56,8 +51,7 @@ offset_tables.iter().map(|table| table.len()).sum() } else { - usize::try_from(MetaData::skip_offset_tables(&mut self.remaining_reader, &self.meta_data.headers)?) - .expect("too large chunk count for this machine") + MetaData::skip_offset_tables(&mut self.remaining_reader, &self.meta_data.headers)? } }; @@ -133,8 +127,11 @@ // check that each offset is within the bounds let end_byte = chunks_start_byte + max_pixel_bytes; - let is_invalid = offset_tables.iter().flatten().map(|&u64| u64_to_usize(u64)) - .any(|chunk_start| chunk_start < chunks_start_byte || chunk_start > end_byte); + let is_invalid = offset_tables.iter().flatten().map(|&u64| u64_to_usize(u64, "chunk start")) + .any(|maybe_chunk_start| match maybe_chunk_start { + Ok(chunk_start) => chunk_start < chunks_start_byte || chunk_start > end_byte, + Err(_) => true + }); if is_invalid { Err(Error::invalid("offset table")) } else { Ok(()) } @@ -211,6 +208,7 @@ OnProgressChunksReader { chunks_reader: self, callback: on_progress, decoded_chunks: 0 } } + #[cfg(feature = "rayon")] /// Decompress all blocks in the file, using multiple cpu cores, and call the supplied closure for each block. /// The order of the blocks is not deterministic. /// You can also use `parallel_decompressor` to obtain an iterator instead. @@ -234,6 +232,7 @@ Ok(()) } + #[cfg(feature = "rayon")] /// Return an iterator that decompresses the chunks with multiple threads. /// The order of the blocks is not deterministic. /// Use `ParallelBlockDecompressor::new` if you want to use your own thread pool. @@ -342,8 +341,7 @@ // read as many chunks as we have desired chunk offsets self.remaining_filtered_chunk_indices.next().map(|next_chunk_location|{ self.remaining_bytes.skip_to( // no-op for seek at current position, uses skip_bytes for small amounts - usize::try_from(next_chunk_location) - .expect("too large chunk position for this machine") + usize::try_from(next_chunk_location)? )?; let meta_data = &self.meta_data; @@ -379,6 +377,7 @@ } } +#[cfg(feature = "rayon")] /// Decompress the chunks in a file in parallel. /// The first call to `next` will fill the thread pool with jobs, /// starting to decompress the next few blocks. @@ -387,17 +386,18 @@ #[derive(Debug)] pub struct ParallelBlockDecompressor { remaining_chunks: R, - sender: flume::Sender>, - receiver: flume::Receiver>, + sender: std::sync::mpsc::Sender>, + receiver: std::sync::mpsc::Receiver>, currently_decompressing_count: usize, max_threads: usize, - shared_meta_data_ref: Arc, + shared_meta_data_ref: std::sync::Arc, pedantic: bool, - pool: ThreadPool, + pool: rayon_core::ThreadPool, } +#[cfg(feature = "rayon")] impl ParallelBlockDecompressor { /// Create a new decompressor. Does not immediately spawn any tasks. @@ -417,12 +417,15 @@ /// Returns the chunks if parallel decompression should not be used. pub fn new_with_thread_pool(chunks: R, pedantic: bool, try_create_thread_pool: CreatePool) -> std::result::Result - where CreatePool: FnOnce() -> std::result::Result + where CreatePool: FnOnce() -> std::result::Result { + use crate::compression::Compression; + + let is_entirely_uncompressed = chunks.meta_data().headers.iter() + .all(|head|head.compression == Compression::Uncompressed); + // if no compression is used in the file, don't use a threadpool - if chunks.meta_data().headers.iter() - .all(|head|head.compression == Compression::Uncompressed) - { + if is_entirely_uncompressed { return Err(chunks); } @@ -437,10 +440,10 @@ let max_threads = pool.current_num_threads().max(1).min(chunks.len()) + 2; // ca one block for each thread at all times - let (send, recv) = flume::unbounded(); // TODO bounded channel simplifies logic? + let (send, recv) = std::sync::mpsc::channel(); // TODO bounded channel simplifies logic? Ok(Self { - shared_meta_data_ref: Arc::new(chunks.meta_data().clone()), + shared_meta_data_ref: std::sync::Arc::new(chunks.meta_data().clone()), currently_decompressing_count: 0, remaining_chunks: chunks, sender: send, @@ -511,7 +514,9 @@ fn size_hint(&self) -> (usize, Option) { self.remaining_chunks_reader.size_hint() } } +#[cfg(feature = "rayon")] impl ExactSizeIterator for ParallelBlockDecompressor {} +#[cfg(feature = "rayon")] impl Iterator for ParallelBlockDecompressor { type Item = Result; fn next(&mut self) -> Option { self.decompress_next_block() } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/block/writer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/block/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,13 +5,10 @@ use std::io::Seek; use std::iter::Peekable; use std::ops::Not; -use rayon_core::{ThreadPool, ThreadPoolBuildError}; use smallvec::alloc::collections::BTreeMap; - use crate::block::UncompressedBlock; -use crate::block::chunk::{Chunk}; -use crate::compression::Compression; +use crate::block::chunk::Chunk; use crate::error::{Error, Result, UnitResult, usize_to_u64}; use crate::io::{Data, Tracking, Write}; use crate::meta::{Headers, MetaData, OffsetTables}; @@ -79,6 +76,7 @@ SequentialBlocksCompressor::new(meta, self) } + #[cfg(feature = "rayon")] /// Obtain a new writer that can compress blocks to chunks on multiple threads, which are then passed to this writer. /// Returns none if the sequential compressor should be used instead (thread pool creation failure or too large performance overhead). fn parallel_blocks_compressor<'w>(&'w mut self, meta: &'w MetaData) -> Option> { @@ -100,6 +98,7 @@ Ok(()) } + #[cfg(feature = "rayon")] /// Compresses all blocks to the file. /// The index of the block must be in increasing line order within the header. /// Obtain iterator with `MetaData::collect_ordered_blocks(...)` or similar methods. @@ -142,7 +141,7 @@ return Err(Error::invalid(format!("chunk at index {} is already written", index_in_header_increasing_y))); } - *chunk_index_slot = usize_to_u64(self.byte_writer.byte_position()); + *chunk_index_slot = usize_to_u64(self.byte_writer.byte_position(), "seek position")?; chunk.write(&mut self.byte_writer, self.header_count)?; Ok(()) } @@ -190,7 +189,7 @@ } /// Seek back to the meta data, write offset tables, and flush the byte writer. - /// Leaves the writer seeked to the middle of the file. + /// Leaves the writer seeked to the middle of the file, therefore we drop it. fn complete_meta_data(mut self) -> UnitResult { if self.chunk_indices_increasing_y.iter().flatten().any(|&index| index == 0) { return Err(Error::invalid("some chunks are not written yet")) @@ -201,7 +200,7 @@ self.byte_writer.seek_write_to(self.chunk_indices_byte_location.start)?; for table in self.chunk_indices_increasing_y { - u64::write_slice(&mut self.byte_writer, table.as_slice())?; + u64::write_slice_le(&mut self.byte_writer, table.as_slice())?; } self.byte_writer.flush()?; // make sure we catch all (possibly delayed) io errors before returning @@ -330,15 +329,18 @@ } } + + /// Compress blocks to a chunk writer with multiple threads. +#[cfg(feature = "rayon")] #[derive(Debug)] #[must_use] pub struct ParallelBlocksCompressor<'w, W> { meta: &'w MetaData, sorted_writer: SortedBlocksWriter<'w, W>, - sender: flume::Sender>, - receiver: flume::Receiver>, + sender: std::sync::mpsc::Sender>, + receiver: std::sync::mpsc::Receiver>, pool: rayon_core::ThreadPool, currently_compressing_count: usize, @@ -347,6 +349,7 @@ next_incoming_chunk_index: usize, // used to remember original chunk order } +#[cfg(feature = "rayon")] impl<'w, W> ParallelBlocksCompressor<'w, W> where W: 'w + ChunksWriter { /// New blocks writer. Returns none if sequential compression should be used. @@ -363,9 +366,14 @@ pub fn new_with_thread_pool( meta: &'w MetaData, chunks_writer: &'w mut W, try_create_thread_pool: CreatePool) -> Option - where CreatePool: FnOnce() -> std::result::Result + where CreatePool: FnOnce() -> std::result::Result { - if meta.headers.iter().all(|head|head.compression == Compression::Uncompressed) { + use crate::compression::Compression; + + let is_entirely_uncompressed = meta.headers.iter() + .all(|head|head.compression == Compression::Uncompressed); + + if is_entirely_uncompressed { return None; } @@ -379,7 +387,7 @@ }; let max_threads = pool.current_num_threads().max(1).min(chunks_writer.total_chunks_count()) + 2; // ca one block for each thread at all times - let (send, recv) = flume::unbounded(); // TODO bounded channel simplifies logic? + let (send, recv) = std::sync::mpsc::channel(); // TODO bounded channel simplifies logic? Some(Self { sorted_writer: SortedBlocksWriter::new(meta, chunks_writer), diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/b44/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/b44/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/b44/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/b44/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -258,7 +258,7 @@ pub fn decompress( channels: &ChannelList, - compressed: ByteVec, + compressed_le: ByteVec, rectangle: IntegerBounds, expected_byte_size: usize, _pedantic: bool, @@ -271,7 +271,7 @@ debug_assert!(!channels.list.is_empty(), "no channels found"); - if compressed.is_empty() { + if compressed_le.is_empty() { return Ok(Vec::new()); } @@ -304,11 +304,11 @@ // Index in the compressed buffer. let mut in_i = 0usize; - let mut remaining = compressed.len(); + let mut remaining_le = compressed_le.len(); for channel in &channel_data { - debug_assert_eq!(remaining, compressed.len()-in_i); + debug_assert_eq!(remaining_le, compressed_le.len() - in_i); // Compute information for current channel. let sample_count = channel.resolution.area() * channel.samples_per_pixel; @@ -320,14 +320,14 @@ debug_assert_eq!(channel.sample_type.bytes_per_sample(), 4); - if remaining < byte_count { + if remaining_le < byte_count { return Err(Error::invalid("not enough data")); } - tmp.extend_from_slice(&compressed[in_i..(in_i + byte_count)]); + tmp.extend_from_slice(&compressed_le[in_i..(in_i + byte_count)]); in_i += byte_count; - remaining -= byte_count; + remaining_le -= byte_count; continue; } @@ -362,29 +362,29 @@ // Extract the 4 by 4 block of 16-bit floats from the compressed buffer. let mut s = [0u16; 16]; - if remaining < 3 { + if remaining_le < 3 { return Err(Error::invalid("not enough data")); } // If shift exponent is 63, call unpack14 (ignoring unused bits) - if compressed[in_i + 2] >= (13 << 2) { - if remaining < 3 { + if compressed_le[in_i + 2] >= (13 << 2) { + if remaining_le < 3 { return Err(Error::invalid("not enough data")); } - unpack3(&compressed[in_i..(in_i + 3)], &mut s); + unpack3(&compressed_le[in_i..(in_i + 3)], &mut s); in_i += 3; - remaining -= 3; + remaining_le -= 3; } else { - if remaining < 14 { + if remaining_le < 14 { return Err(Error::invalid("not enough data")); } - unpack14(&compressed[in_i..(in_i + 14)], &mut s); + unpack14(&compressed_le[in_i..(in_i + 14)], &mut s); in_i += 14; - remaining -= 14; + remaining_le -= 14; } if channel.quantize_linearly { @@ -436,7 +436,7 @@ for y in rectangle.position.y()..rectangle.end().y() { for channel in &mut channel_data { - if mod_p(y, usize_to_i32(channel.y_sampling)) != 0 { + if mod_p(y, usize_to_i32(channel.y_sampling, "sampling")?) != 0 { continue; } @@ -463,7 +463,7 @@ } } else { - u8::write_slice(&mut out, channel_bytes) + u8::write_slice_ne(&mut out, channel_bytes) .expect("write to in-memory failed"); } } @@ -480,23 +480,23 @@ // TODO do not convert endianness for f16-only images // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - Ok(super::convert_little_endian_to_current(out, channels, rectangle)) + super::convert_little_endian_to_current(out, channels, rectangle) } pub fn compress( channels: &ChannelList, - uncompressed: ByteVec, + uncompressed_ne: ByteVec, rectangle: IntegerBounds, optimize_flat_fields: bool, ) -> Result { - if uncompressed.is_empty() { + if uncompressed_ne.is_empty() { return Ok(Vec::new()); } // TODO do not convert endianness for f16-only images // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - let uncompressed = super::convert_current_to_little_endian(uncompressed, channels, rectangle); - let uncompressed = uncompressed.as_slice(); // TODO no alloc + let uncompressed_le = super::convert_current_to_little_endian(uncompressed_ne, channels, rectangle)?; + let uncompressed_le = uncompressed_le.as_slice(); // TODO no alloc let mut channel_data = Vec::new(); @@ -521,15 +521,15 @@ channel_data.push(channel); } - let mut tmp = vec![0_u8; uncompressed.len()]; + let mut tmp = vec![0_u8; uncompressed_le.len()]; debug_assert_eq!(tmp_end_index, tmp.len()); - let mut remaining_uncompressed_bytes = uncompressed; + let mut remaining_uncompressed_bytes = uncompressed_le; for y in rectangle.position.y()..rectangle.end().y() { for channel in &mut channel_data { - if mod_p(y, usize_to_i32(channel.y_sampling)) != 0 { + if mod_p(y, usize_to_i32(channel.y_sampling, "sampling")?) != 0 { continue; } @@ -557,14 +557,14 @@ } } else { - u8::read_slice(&mut remaining_uncompressed_bytes, target) + u8::read_slice_ne(&mut remaining_uncompressed_bytes, target) .expect("in-memory read failed"); } } } // Generate a whole buffer that we will crop to proper size once compression is done. - let mut b44_compressed = vec![0; std::cmp::max(2048, uncompressed.len())]; + let mut b44_compressed = vec![0; std::cmp::max(2048, uncompressed_le.len())]; let mut b44_end = 0; // Buffer byte index for storing next compressed values. for channel in &channel_data { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -12,10 +12,8 @@ use std::convert::TryInto; -use std::mem::size_of; -use half::f16; use crate::meta::attribute::{IntegerBounds, SampleType, ChannelList}; -use crate::error::{Result, Error, usize_to_i32}; +use crate::error::{Result, Error, usize_to_i32, UnitResult}; use crate::meta::header::Header; @@ -134,7 +132,15 @@ // of 256 scanlines. More efficient space // wise and faster to decode full frames // than DWAA_COMPRESSION. - DWAB(Option), // TODO collapse with B44. default Compression Level setting is 45.0 + DWAB(Option), // TODO collapse with DWAA. default Compression Level setting is 45.0 + + /// __This lossy compression is not yet supported by this implementation.__ + // High-Throughput JPEG 2000 (32 lines) + HTJ2K32, + + /// __This lossy compression is not yet supported by this implementation.__ + // High-Throughput JPEG 2000 (256 lines) + HTJ2K256, } impl std::fmt::Display for Compression { @@ -150,6 +156,8 @@ Compression::DWAB(_) => "dwab", Compression::PIZ => "piz", Compression::PXR24 => "pxr24", + Compression::HTJ2K32 => "ht j2k 32", + Compression::HTJ2K256 => "ht j2k 256", }) } } @@ -158,8 +166,8 @@ impl Compression { - /// Compress the image section of bytes. - pub fn compress_image_section(self, header: &Header, uncompressed_native_endian: ByteVec, pixel_section: IntegerBounds) -> Result { + /// Compress the image section, converting from native endian into with little-endian format. + pub fn compress_image_section_to_le(self, header: &Header, uncompressed_native_endian: ByteVec, pixel_section: IntegerBounds) -> Result { let max_tile_size = header.max_block_pixel_size(); assert!(pixel_section.validate(Some(max_tile_size)).is_ok(), "decompress tile coordinate bug"); @@ -168,9 +176,9 @@ use self::Compression::*; let compressed_little_endian = match self { Uncompressed => { - return Ok(convert_current_to_little_endian( + return convert_current_to_little_endian( uncompressed_native_endian, &header.channels, pixel_section - )) + ) }, // we need to clone here, because we might have to fallback to the uncompressed data later (when compressed data is larger than raw data) @@ -194,12 +202,12 @@ } else { // if we do not use compression, manually convert uncompressed data - Ok(convert_current_to_little_endian(uncompressed_native_endian, &header.channels, pixel_section)) + convert_current_to_little_endian(uncompressed_native_endian, &header.channels, pixel_section) } } - /// Decompress the image section of bytes. - pub fn decompress_image_section(self, header: &Header, compressed: ByteVec, pixel_section: IntegerBounds, pedantic: bool) -> Result { + /// Decompress the image section from bytes of little-endian format, returning native-endian format. + pub fn decompress_image_section_from_le(self, header: &Header, compressed_le: ByteVec, pixel_section: IntegerBounds, pedantic: bool) -> Result { let max_tile_size = header.max_block_pixel_size(); assert!(pixel_section.validate(Some(max_tile_size)).is_ok(), "decompress tile coordinate bug"); @@ -208,25 +216,25 @@ let expected_byte_size = pixel_section.size.area() * header.channels.bytes_per_pixel; // FIXME this needs to account for subsampling anywhere // note: always true where self == Uncompressed - if compressed.len() == expected_byte_size { + if compressed_le.len() == expected_byte_size { // the compressed data was larger than the raw data, so the small raw data has been written - Ok(convert_little_endian_to_current(compressed, &header.channels, pixel_section)) + convert_little_endian_to_current(compressed_le, &header.channels, pixel_section) } else { use self::Compression::*; - let bytes = match self { - Uncompressed => Ok(convert_little_endian_to_current(compressed, &header.channels, pixel_section)), - ZIP16 => zip::decompress_bytes(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), - ZIP1 => zip::decompress_bytes(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), - RLE => rle::decompress_bytes(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), - PIZ => piz::decompress(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), - PXR24 => pxr24::decompress(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), - B44 | B44A => b44::decompress(&header.channels, compressed, pixel_section, expected_byte_size, pedantic), + let bytes_ne = match self { + Uncompressed => convert_little_endian_to_current(compressed_le, &header.channels, pixel_section), + ZIP16 => zip::decompress_bytes(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), + ZIP1 => zip::decompress_bytes(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), + RLE => rle::decompress_bytes(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), + PIZ => piz::decompress(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), + PXR24 => pxr24::decompress(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), + B44 | B44A => b44::decompress(&header.channels, compressed_le, pixel_section, expected_byte_size, pedantic), _ => return Err(Error::unsupported(format!("yet unimplemented compression method: {}", self))) }; // map all errors to compression errors - let bytes = bytes + let bytes_ne = bytes_ne .map_err(|decompression_error| match decompression_error { Error::NotSupported(message) => Error::unsupported(format!("yet unimplemented compression special case ({})", message)), @@ -237,11 +245,11 @@ )), })?; - if bytes.len() != expected_byte_size { + if bytes_ne.len() != expected_byte_size { Err(Error::invalid("decompressed data")) } - else { Ok(bytes) } + else { Ok(bytes_ne) } } } @@ -251,10 +259,10 @@ pub fn scan_lines_per_block(self) -> usize { use self::Compression::*; match self { - Uncompressed | RLE | ZIP1 => 1, - ZIP16 | PXR24 => 16, - PIZ | B44 | B44A | DWAA(_) => 32, - DWAB(_) => 256, + Uncompressed | RLE | ZIP1 => 1, + ZIP16 | PXR24 => 16, + PIZ | B44 | B44A | DWAA(_) | HTJ2K32 => 32, + DWAB(_) | HTJ2K256 => 256, } } @@ -262,8 +270,12 @@ pub fn supports_deep_data(self) -> bool { use self::Compression::*; match self { - Uncompressed | RLE | ZIP1 => true, - _ => false, + Uncompressed | RLE | ZIP1 => + true, + + ZIP16 | PXR24 | PIZ | B44 | B44A | + DWAA(_) | DWAB(_) | HTJ2K256 | HTJ2K32 => + false, } } @@ -274,7 +286,7 @@ match self { PXR24 => sample_type != SampleType::F32, // pxr reduces f32 to f24 B44 | B44A => sample_type != SampleType::F16, // b44 only compresses f16 values, others are left uncompressed - Uncompressed | RLE | ZIP1 | ZIP16 | PIZ => true, + Uncompressed | RLE | ZIP1 | ZIP16 | PIZ | HTJ2K32 | HTJ2K256 => true, DWAB(_) | DWAA(_) => false, } } @@ -284,18 +296,31 @@ pub fn may_loose_data(self) -> bool { use self::Compression::*; match self { - Uncompressed | RLE | ZIP1 | ZIP16 | PIZ => false, - PXR24 | B44 | B44A | DWAB(_) | DWAA(_) => true, + Uncompressed | RLE | ZIP1 | ZIP16 | PIZ | HTJ2K32 | HTJ2K256 => false, + PXR24 | B44 | B44A | DWAB(_) | DWAA(_) => true, } } /// Most compression methods will reconstruct the exact pixel bytes, /// but some might replace NaN with zeroes. + /// This might also depend on the sample type of the pixels. + /// Even a compression method that supports NaN might change the bit patterns of those NaNs. pub fn supports_nan(self) -> bool { use self::Compression::*; match self { - B44 | B44A | DWAB(_) | DWAA(_) => false, // TODO dwa might support it? - _ => true + B44A | DWAB(_) | DWAA(_) => false, + Uncompressed | PXR24 | RLE | ZIP1 | ZIP16 | PIZ | B44 | HTJ2K32 | HTJ2K256 => true, + } + } + + /// Most compression methods will reconstruct the exact pixel and NaN bits, + /// but some might replace NaN bits with other NaN bits. + /// This might also depend on the sample type of the pixels. + pub fn preserves_nan_bits(self) -> bool { + use self::Compression::*; + match self { + B44A | PXR24 | DWAB(_) | DWAA(_) => false, + B44 | Uncompressed | RLE | ZIP1 | ZIP16 | PIZ | HTJ2K32 | HTJ2K256 => true } } @@ -304,45 +329,50 @@ // see https://github.com/AcademySoftwareFoundation/openexr/blob/6a9f8af6e89547bcd370ae3cec2b12849eee0b54/OpenEXR/IlmImf/ImfMisc.cpp#L1456-L1541 #[allow(unused)] // allows the extra parameters to be unused -fn convert_current_to_little_endian(mut bytes: ByteVec, channels: &ChannelList, rectangle: IntegerBounds) -> ByteVec { - #[cfg(target = "big_endian")] - reverse_block_endianness(&mut byte_vec, channels, rectangle); +fn convert_current_to_little_endian(mut bytes: ByteVec, channels: &ChannelList, rectangle: IntegerBounds) -> Result { + #[cfg(target_endian = "big")] + reverse_block_endianness(&mut bytes, channels, rectangle)?; - bytes + Ok(bytes) } #[allow(unused)] // allows the extra parameters to be unused -fn convert_little_endian_to_current(mut bytes: ByteVec, channels: &ChannelList, rectangle: IntegerBounds) -> ByteVec { - #[cfg(target = "big_endian")] - reverse_block_endianness(&mut bytes, channels, rectangle); +fn convert_little_endian_to_current(mut bytes: ByteVec, channels: &ChannelList, rectangle: IntegerBounds) -> Result { + #[cfg(target_endian = "big")] + reverse_block_endianness(&mut bytes, channels, rectangle)?; - bytes + Ok(bytes) } #[allow(unused)] // unused when on little endian system -fn reverse_block_endianness(bytes: &mut [u8], channels: &ChannelList, rectangle: IntegerBounds){ +fn reverse_block_endianness(bytes: &mut [u8], channels: &ChannelList, rectangle: IntegerBounds) -> UnitResult { let mut remaining_bytes: &mut [u8] = bytes; for y in rectangle.position.y() .. rectangle.end().y() { for channel in &channels.list { - let line_is_subsampled = mod_p(y, usize_to_i32(channel.sampling.y())) != 0; + let line_is_subsampled = mod_p(y, usize_to_i32(channel.sampling.y(), "sampling")?) != 0; if line_is_subsampled { continue; } let sample_count = rectangle.size.width() / channel.sampling.x(); match channel.sample_type { - SampleType::F16 => remaining_bytes = chomp_convert_n::(reverse_2_bytes, remaining_bytes, sample_count), - SampleType::F32 => remaining_bytes = chomp_convert_n::(reverse_4_bytes, remaining_bytes, sample_count), - SampleType::U32 => remaining_bytes = chomp_convert_n::(reverse_4_bytes, remaining_bytes, sample_count), + SampleType::F16 => + remaining_bytes = convert_byte_chunks(reverse_2_bytes, 2, remaining_bytes, sample_count), + + SampleType::F32 => + remaining_bytes = convert_byte_chunks(reverse_4_bytes, 4, remaining_bytes, sample_count), + + SampleType::U32 => + remaining_bytes = convert_byte_chunks(reverse_4_bytes, 4, remaining_bytes, sample_count), } } } + // Converts groups of bytes (e.g. 2 bytes), as many groups as specified. Returns a slice of the remaining bytes. #[inline] - fn chomp_convert_n(convert_single_value: fn(&mut[u8]), mut bytes: &mut [u8], count: usize) -> &mut [u8] { - let type_size = size_of::(); - let (line_bytes, rest) = bytes.split_at_mut(count * type_size); - let value_byte_chunks = line_bytes.chunks_exact_mut(type_size); + fn convert_byte_chunks(convert_single_value: fn(&mut[u8]), batch_size: usize, bytes: &mut [u8], batch_count: usize) -> &mut [u8] { + let (line_bytes, rest) = bytes.split_at_mut(batch_count * batch_size); + let value_byte_chunks = line_bytes.chunks_exact_mut(batch_size); for value_bytes in value_byte_chunks { convert_single_value(value_bytes); @@ -352,6 +382,7 @@ } debug_assert!(remaining_bytes.is_empty(), "not all bytes were converted to little endian"); + Ok(()) } #[inline] @@ -553,42 +584,42 @@ }); } -/// Separate the bytes such that the second half contains every other byte. -/// This performs deinterleaving - the inverse of interleaving. -pub fn separate_bytes_fragments(source: &mut [u8]) { - with_reused_buffer(source.len(), |separated| { - - // Split the two halves that we are going to interleave. - let (first_half, second_half) = separated.split_at_mut((source.len() + 1) / 2); - // The first half can be 1 byte longer than the second if the length of the input is odd, - // but the loop below only processes numbers in pairs. - // To handle it, preserve the last element of the input, to be handled after the loop. - let last = source.last(); - let first_half_iter = &mut first_half[..second_half.len()]; - - // Main loop that performs the deinterleaving - for ((first, second), interleaved) in first_half_iter.iter_mut().zip(second_half.iter_mut()) - .zip(source.chunks_exact(2)) { - // The length of each chunk is known to be 2 at compile time, - // and each index is also a constant. - // This allows the compiler to remove the bounds checks. - *first = interleaved[0]; - *second = interleaved[1]; - } - - // If the length of the slice was odd, restore the last element of the input that we saved - if source.len() % 2 == 1 { - if let Some(value) = last { - // we can unwrap() here because we just checked that the lenght is non-zero: - // `% 2 == 1` will fail for zero - *first_half.last_mut().unwrap() = *value; + /// Separate the bytes such that the second half contains every other byte. + /// This performs deinterleaving - the inverse of interleaving. + pub fn separate_bytes_fragments(source: &mut [u8]) { + with_reused_buffer(source.len(), |separated| { + + // Split the two halves that we are going to interleave. + let (first_half, second_half) = separated.split_at_mut((source.len() + 1) / 2); + // The first half can be 1 byte longer than the second if the length of the input is odd, + // but the loop below only processes numbers in pairs. + // To handle it, preserve the last element of the input, to be handled after the loop. + let last = source.last(); + let first_half_iter = &mut first_half[..second_half.len()]; + + // Main loop that performs the deinterleaving + for ((first, second), interleaved) in first_half_iter.iter_mut().zip(second_half.iter_mut()) + .zip(source.chunks_exact(2)) { + // The length of each chunk is known to be 2 at compile time, + // and each index is also a constant. + // This allows the compiler to remove the bounds checks. + *first = interleaved[0]; + *second = interleaved[1]; } - } - // write out the results - source.copy_from_slice(&separated); - }); -} + // If the length of the slice was odd, restore the last element of the input that we saved + if source.len() % 2 == 1 { + if let Some(value) = last { + // we can unwrap() here because we just checked that the lenght is non-zero: + // `% 2 == 1` will fail for zero + *first_half.last_mut().unwrap() = *value; + } + } + + // write out the results + source.copy_from_slice(&separated); + }); + } #[cfg(test)] @@ -621,7 +652,7 @@ #[cfg(test)] -pub mod test { +mod test { use super::*; use crate::meta::attribute::ChannelDescription; use crate::block::samples::IntoNativeSample; @@ -655,11 +686,11 @@ ){ let little_endian = convert_current_to_little_endian( current_endian.clone(), channels, rectangle - ); + ).unwrap(); let current_endian_decoded = convert_little_endian_to_current( little_endian.clone(), channels, rectangle - ); + ).unwrap(); assert_eq!(current_endian, current_endian_decoded, "endianness conversion failed"); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/piz/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/piz/huffman.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -18,13 +18,13 @@ pub fn decompress(compressed: &[u8], expected_size: usize) -> Result> { let mut remaining_compressed = compressed; - let min_code_index = usize::try_from(u32::read(&mut remaining_compressed)?)?; - let max_code_index_32 = u32::read(&mut remaining_compressed)?; - let _table_size = usize::try_from(u32::read(&mut remaining_compressed)?)?; // TODO check this and return Err? - let bit_count = usize::try_from(u32::read(&mut remaining_compressed)?)?; - let _skipped = u32::read(&mut remaining_compressed)?; // what is this + let min_code_index = usize::try_from(u32::read_le(&mut remaining_compressed)?)?; + let max_code_index_32 = u32::read_le(&mut remaining_compressed)?; + let _table_size = usize::try_from(u32::read_le(&mut remaining_compressed)?)?; // TODO check this and return Err? + let bit_count = usize::try_from(u32::read_le(&mut remaining_compressed)?)?; + let _skipped = u32::read_le(&mut remaining_compressed)?; // what is this - let max_code_index = usize::try_from(max_code_index_32).unwrap(); + let max_code_index = usize::try_from(max_code_index_32)?; if min_code_index >= ENCODING_TABLE_SIZE || max_code_index >= ENCODING_TABLE_SIZE { return Err(Error::invalid(INVALID_TABLE_SIZE)); } @@ -54,10 +54,10 @@ if uncompressed.is_empty() { return Ok(vec![]); } let mut frequencies = count_frequencies(uncompressed); - let (min_code_index, max_code_index) = build_encoding_table(&mut frequencies); + let (min_code_index, max_code_index) = build_encoding_table(&mut frequencies)?; let mut result = Cursor::new(Vec::with_capacity(uncompressed.len())); - u32::write_slice(&mut result, &[0; 5])?; // we come back to these later after we know more about the compressed data + u32::write_slice_le(&mut result, &[0; 5])?; // we come back to these later after we know more about the compressed data let table_start = result.position(); pack_encoding_table( @@ -79,11 +79,11 @@ result.set_position(0); let table_length = data_start - table_start; - u32::try_from(min_code_index)?.write(&mut result)?; - u32::try_from(max_code_index)?.write(&mut result)?; - u32::try_from(table_length)?.write(&mut result)?; - u32::try_from(bit_count)?.write(&mut result)?; - 0_u32.write(&mut result)?; + u32::try_from(min_code_index)?.write_le(&mut result)?; + u32::try_from(max_code_index)?.write_le(&mut result)?; + u32::try_from(table_length)?.write_le(&mut result)?; + u32::try_from(bit_count)?.write_le(&mut result)?; + 0_u32.write_le(&mut result)?; Ok(result.into_inner()) } @@ -139,7 +139,7 @@ // Access decoding table while code_bit_count >= DECODE_BITS { let code_index = (code_bits >> (code_bit_count - DECODE_BITS)) & DECODE_MASK; - let code = &decoding_table[u64_to_usize(code_index)]; + let code = &decoding_table[u64_to_usize(code_index, "huffman code index")?]; // Get short code if let Code::Short(code) = code { @@ -160,7 +160,7 @@ let long_code = long_codes.iter() .filter_map(|&long_code|{ - let encoded_long_code = encoding_table[u32_to_usize(long_code)]; + let encoded_long_code = encoding_table[u32_to_usize(long_code, "huffman long code").ok()?]; let length = length(encoded_long_code); while code_bit_count < length && input.len() > 0 { @@ -201,11 +201,13 @@ let count = u64::try_from((8 - input_bit_count) & 7)?; code_bits >>= count; - code_bit_count -= count; + + code_bit_count = code_bit_count.checked_sub(count) + .ok_or_else(|| Error::invalid("code"))?; while code_bit_count > 0 { let index = (code_bits << (DECODE_BITS - code_bit_count)) & DECODE_MASK; - let code = &decoding_table[u64_to_usize(index)]; + let code = &decoding_table[u64_to_usize(index, "huffman code index")?]; if let Code::Short(short_code) = code { if short_code.len() > code_bit_count { return Err(Error::invalid("code")) }; // FIXME why does this happen?? @@ -257,7 +259,7 @@ } if length > DECODE_BITS { - let long_code = &mut decoding_table[u64_to_usize(code >> (length - DECODE_BITS))]; + let long_code = &mut decoding_table[u64_to_usize(code >> (length - DECODE_BITS), "long code index")?]; match long_code { Code::Empty => *long_code = Code::Long(smallvec![code_index]), @@ -271,8 +273,8 @@ len: length as u8, }); - let start_index = u64_to_usize(code << (DECODE_BITS - length)); - let count = u64_to_usize(1 << (DECODE_BITS - length)); + let start_index = u64_to_usize(code << (DECODE_BITS - length), "huffman start index")?; + let count = u64_to_usize(1 << (DECODE_BITS - length), "huffman count")?; for value in &mut decoding_table[start_index .. start_index + count] { *value = default_value.clone(); @@ -294,7 +296,7 @@ let mut code_bit_count = 0_u64; // TODO push() into encoding table instead of index stuff? - let mut encoding_table = vec![0_u64; ENCODING_TABLE_SIZE]; + let mut encoding_table = vec![0_u64; ENCODING_TABLE_SIZE]; let mut code_index = min_code_index; while code_index <= max_code_index { let code_len = read_bits(6, &mut code_bits, &mut code_bit_count, packed)?; @@ -331,7 +333,7 @@ } } - build_canonical_table(&mut encoding_table); + build_canonical_table(&mut encoding_table)?; Ok(encoding_table) } @@ -354,7 +356,7 @@ #[inline] fn read_byte(code_bits: &mut u64, bit_count: &mut u64, input: &mut impl Read) -> UnitResult { - *code_bits = (*code_bits << 8) | u8::read(input)? as u64; + *code_bits = (*code_bits << 8) | u8::read_ne(input)? as u64; *bit_count += 8; Ok(()) } @@ -600,13 +602,13 @@ /// symbol lengths alone, the code table can be transmitted /// without sending the actual code values /// - see http://www.compressconsult.com/huffman/ -fn build_canonical_table(code_table: &mut [u64]) { +fn build_canonical_table(code_table: &mut [u64]) -> UnitResult { debug_assert_eq!(code_table.len(), ENCODING_TABLE_SIZE); let mut count_per_code = [0_u64; 59]; for &code in code_table.iter() { - count_per_code[u64_to_usize(code)] += 1; + count_per_code[u64_to_usize(code, "table entry")?] += 1; } // For each i from 58 through 1, compute the @@ -627,12 +629,14 @@ // l and the code in code[i]. // TODO iter + filter ? for symbol_length in code_table.iter_mut() { let current_length = *symbol_length; - let code_index = u64_to_usize(current_length); + let code_index = u64_to_usize(current_length, "huffman code index")?; if current_length > 0 { *symbol_length = current_length | (count_per_code[code_index] << 6); count_per_code[code_index] += 1; } } + + Ok(()) } @@ -649,7 +653,7 @@ /// produced a resultant sorted heap that is identical across OSes. fn build_encoding_table( frequencies: &mut [u64], // input frequencies, output encoding table -) -> (usize, usize) // return frequency max min range +) -> Result<(usize, usize)> // return frequency max min range { debug_assert_eq!(frequencies.len(), ENCODING_TABLE_SIZE); @@ -816,10 +820,10 @@ // Build a canonical Huffman code table, replacing the code // lengths in scode with (code, code length) pairs. Copy the // code table from scode into frq. - build_canonical_table(&mut s_code); + build_canonical_table(&mut s_code)?; frequencies.copy_from_slice(&s_code); - (min_frequency_index, max_frequency_index) + Ok((min_frequency_index, max_frequency_index)) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/piz/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/piz/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/piz/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -31,7 +31,7 @@ pub fn decompress( channels: &ChannelList, - compressed: ByteVec, + compressed_le: ByteVec, rectangle: IntegerBounds, expected_byte_size: usize, // TODO remove expected byte size as it can be computed with `rectangle.size.area() * channels.bytes_per_pixel` pedantic: bool @@ -41,7 +41,7 @@ debug_assert_eq!(expected_byte_size, rectangle.size.area() * channels.bytes_per_pixel); debug_assert!(!channels.list.is_empty()); - if compressed.is_empty() { + if compressed_le.is_empty() { return Ok(Vec::new()); } @@ -49,29 +49,29 @@ let mut bitmap = vec![0_u8; BITMAP_SIZE]; // FIXME use bit_vec! - let mut remaining_input = compressed.as_slice(); - let min_non_zero = u16::read(&mut remaining_input)? as usize; - let max_non_zero = u16::read(&mut remaining_input)? as usize; + let mut remaining_input_le = compressed_le.as_slice(); + let min_non_zero = u16::read_le(&mut remaining_input_le)? as usize; + let max_non_zero = u16::read_le(&mut remaining_input_le)? as usize; if max_non_zero >= BITMAP_SIZE || min_non_zero >= BITMAP_SIZE { return Err(Error::invalid("compression data")); } if min_non_zero <= max_non_zero { - u8::read_slice(&mut remaining_input, &mut bitmap[min_non_zero ..= max_non_zero])?; + u8::read_slice_ne(&mut remaining_input_le, &mut bitmap[min_non_zero ..= max_non_zero])?; } let (lookup_table, max_value) = reverse_lookup_table_from_bitmap(&bitmap); { - let length = i32::read(&mut remaining_input)?; - if pedantic && length as i64 != remaining_input.len() as i64 { + let length = i32::read_le(&mut remaining_input_le)?; + if pedantic && length as i64 != remaining_input_le.len() as i64 { // TODO length might be smaller than remaining?? return Err(Error::invalid("compression data")); } } - let mut tmp_u16_buffer = huffman::decompress(remaining_input, expected_u16_count)?; + let mut tmp_u16_buffer = huffman::decompress(remaining_input_le, expected_u16_count)?; let mut channel_data: SmallVec<[ChannelData; 6]> = { let mut tmp_read_index = 0; @@ -115,7 +115,7 @@ for y in rectangle.position.y() .. rectangle.end().y() { for channel in &mut channel_data { - if mod_p(y, usize_to_i32(channel.y_sampling)) != 0 { + if mod_p(y, usize_to_i32(channel.y_sampling, "sampling factor")?) != 0 { continue; } @@ -129,7 +129,7 @@ // We can support uncompressed data in the machine's native format // if all image channels are of type HALF, and if the Xdr and the // native representations of a half have the same size. - u16::write_slice(&mut out, values).expect("write to in-memory failed"); + u16::write_slice_le(&mut out, values).expect("write to in-memory failed"); } } @@ -143,27 +143,27 @@ // TODO optimize for when all channels are f16! // we should be able to omit endianness conversions in that case // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - Ok(super::convert_little_endian_to_current(out, channels, rectangle)) + super::convert_little_endian_to_current(out, channels, rectangle) } pub fn compress( channels: &ChannelList, - uncompressed: ByteVec, + uncompressed_ne: ByteVec, rectangle: IntegerBounds ) -> Result { - if uncompressed.is_empty() { + if uncompressed_ne.is_empty() { return Ok(Vec::new()); } - // TODO do not convert endianness for f16-only images + // TODO do not convert endianness for f16-only images twice // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - let uncompressed = super::convert_current_to_little_endian(uncompressed, channels, rectangle); - let uncompressed = uncompressed.as_slice();// TODO no alloc + let uncompressed_le = super::convert_current_to_little_endian(uncompressed_ne, channels, rectangle)?; + let uncompressed_le = uncompressed_le.as_slice();// TODO no alloc - let mut tmp = vec![0_u16; uncompressed.len() / 2 ]; + let mut tmp = vec![0_u16; uncompressed_le.len() / 2 ]; let mut channel_data: SmallVec<[ChannelData; 6]> = { let mut tmp_end_index = 0; @@ -188,10 +188,10 @@ vec }; - let mut remaining_uncompressed_bytes = uncompressed; + let mut remaining_uncompressed_bytes_le = uncompressed_le; for y in rectangle.position.y() .. rectangle.end().y() { for channel in &mut channel_data { - if mod_p(y, usize_to_i32(channel.y_sampling)) != 0 { continue; } + if mod_p(y, usize_to_i32(channel.y_sampling, "sampling")?) != 0 { continue; } let u16s_per_line = channel.resolution.x() * channel.samples_per_pixel; let next_tmp_end_index = channel.tmp_end_index + u16s_per_line; let target = &mut tmp[channel.tmp_end_index .. next_tmp_end_index]; @@ -202,7 +202,7 @@ // We can support uncompressed data in the machine's native format // if all image channels are of type HALF, and if the Xdr and the // native representations of a half have the same size. - u16::read_slice(&mut remaining_uncompressed_bytes, target).expect("in-memory read failed"); + u16::read_slice_le(&mut remaining_uncompressed_bytes_le, target).expect("in-memory read failed"); } } @@ -211,9 +211,9 @@ let (max_value, table) = forward_lookup_table_from_bitmap(&bitmap); apply_lookup_table(&mut tmp, &table); - let mut piz_compressed = Vec::with_capacity(uncompressed.len() / 2); - u16::try_from(min_non_zero)?.write(&mut piz_compressed)?; - u16::try_from(max_non_zero)?.write(&mut piz_compressed)?; + let mut piz_compressed = Vec::with_capacity(uncompressed_le.len() / 2); + u16::try_from(min_non_zero)?.write_le(&mut piz_compressed)?; + u16::try_from(max_non_zero)?.write_le(&mut piz_compressed)?; if min_non_zero <= max_non_zero { piz_compressed.extend_from_slice(&bitmap[min_non_zero ..= max_non_zero]); @@ -231,7 +231,7 @@ } let huffman_compressed: Vec = huffman::compress(&tmp)?; - u8::write_i32_sized_slice(&mut piz_compressed, &huffman_compressed).expect("in-memory write failed"); + u8::write_i32_sized_slice_le(&mut piz_compressed, &huffman_compressed).expect("in-memory write failed"); Ok(piz_compressed) } @@ -262,12 +262,12 @@ for (index, entry) in table.iter_mut().enumerate() { if index == 0 || bitmap[index >> 3] as usize & (1 << (index & 7)) != 0 { - *entry = usize_to_u16(count).unwrap(); + *entry = usize_to_u16(count, "piz entry").unwrap(); count += 1; } } - (usize_to_u16(count - 1).unwrap(), table) + (usize_to_u16(count - 1, "piz count").unwrap(), table) } fn reverse_lookup_table_from_bitmap(bitmap: Bytes<'_>) -> (Vec, u16) { @@ -275,12 +275,12 @@ for index in 0 .. U16_RANGE { // cannot use iter because filter removes capacity sizehint if index == 0 || ((bitmap[index >> 3] as usize & (1 << (index & 7))) != 0) { - table.push(usize_to_u16(index).unwrap()); + table.push(usize_to_u16(index, "table entry").unwrap()); } } debug_assert!(!table.is_empty()); - let max_value = usize_to_u16(table.len() - 1).unwrap(); + let max_value = usize_to_u16(table.len() - 1, "table size").unwrap(); // fill remaining up to u16 range assert!(table.len() <= U16_RANGE); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/pxr24.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/pxr24.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/pxr24.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/pxr24.rs 2006-07-24 01:21:28.000000000 +0000 @@ -33,60 +33,56 @@ use lebe::io::ReadPrimitive; -// scanline decompression routine, see https://github.com/openexr/openexr/blob/master/OpenEXR/IlmImf/ImfScanLineInputFile.cpp +// scanline decompreroussion tine, see https://github.com/openexr/openexr/blob/master/OpenEXR/IlmImf/ImfScanLineInputFile.cpp // 1. Uncompress the data, if necessary (If the line is uncompressed, it's in XDR format, regardless of the compressor's output format.) // 3. Convert one scan line's worth of pixel data back from the machine-independent representation // 4. Fill the frame buffer with pixel data, respective to sampling and whatnot -#[cfg_attr(target_endian = "big", allow(unused, unreachable_code))] -pub fn compress(channels: &ChannelList, remaining_bytes: ByteVec, area: IntegerBounds) -> Result { - #[cfg(target_endian = "big")] { - return Err(Error::unsupported( - "PXR24 compression method not supported yet on big endian processor architecture" - )) - } - - if remaining_bytes.is_empty() { return Ok(Vec::new()); } +pub fn compress(channels: &ChannelList, bytes_ne: ByteVec, area: IntegerBounds) -> Result { + if bytes_ne.is_empty() { return Ok(Vec::new()); } - // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - let remaining_bytes = super::convert_current_to_little_endian(remaining_bytes, channels, area); - let mut remaining_bytes = remaining_bytes.as_slice(); // TODO less allocation + let mut remaining_bytes_ne = bytes_ne.as_slice(); // TODO less allocation let bytes_per_pixel: usize = channels.list.iter() .map(|channel| match channel.sample_type { - SampleType::F16 => 2, SampleType::F32 => 3, SampleType::U32 => 4, + SampleType::F16 => 2, + SampleType::F32 => 3, + SampleType::U32 => 4, }) .sum(); - let mut raw = vec![0_u8; bytes_per_pixel * area.size.area()]; + let mut encoded_be = vec![0_u8; bytes_per_pixel * area.size.area()]; { - let mut write = raw.as_mut_slice(); + let mut write = encoded_be.as_mut_slice(); - // TODO this loop should be an iterator in the `IntegerBounds` class, as it is used in all compressio methods + // TODO this loop should be an iterator in the `IntegerBounds` class, as it is used in all compression methods for y in area.position.1..area.end().1 { for channel in &channels.list { - if mod_p(y, usize_to_i32(channel.sampling.1)) != 0 { continue; } + if mod_p(y, usize_to_i32(channel.sampling.1, "sampling factor")?) != 0 { continue; } - // this apparently can't be a closure in Rust 1.43 due to borrowing ambiguity let sample_count_x = channel.subsampled_resolution(area.size).0; + + // this apparently can't be a closure in Rust 1.43 due to borrowing ambiguity macro_rules! split_off_write_slice { () => {{ let (slice, rest) = write.split_at_mut(sample_count_x); write = rest; slice }}; } - let mut previous_pixel: u32 = 0; - match channel.sample_type { SampleType::F16 => { let out_byte_tuples = split_off_write_slice!().iter_mut() .zip(split_off_write_slice!()); + let mut previous_pixel: u32 = 0; for (out_byte_0, out_byte_1) in out_byte_tuples { - let pixel = u16::read_from_native_endian(&mut remaining_bytes).unwrap() as u32; - let [byte_1, byte_0] = (pixel.wrapping_sub(previous_pixel) as u16).to_ne_bytes(); + let pixel = u16::read_from_native_endian(&mut remaining_bytes_ne) + .expect("failed to read from in-memory bytes") as u32; + + let [byte_0, byte_1] = (pixel.wrapping_sub(previous_pixel) as u16) + .to_be_bytes(); *out_byte_0 = byte_0; *out_byte_1 = byte_1; @@ -100,9 +96,13 @@ .zip(split_off_write_slice!()) .zip(split_off_write_slice!()); + let mut previous_pixel: u32 = 0; for (((out_byte_0, out_byte_1), out_byte_2), out_byte_3) in out_byte_quadruplets { - let pixel = u32::read_from_native_endian(&mut remaining_bytes).unwrap(); - let [byte_3, byte_2, byte_1, byte_0] = pixel.wrapping_sub(previous_pixel).to_ne_bytes(); + let pixel = u32::read_from_native_endian(&mut remaining_bytes_ne) + .expect("failed to read from in-memory bytes"); + + let [byte_0, byte_1, byte_2, byte_3] = pixel + .wrapping_sub(previous_pixel).to_be_bytes(); *out_byte_0 = byte_0; *out_byte_1 = byte_1; @@ -117,14 +117,20 @@ .zip(split_off_write_slice!()) .zip(split_off_write_slice!()); + let mut previous_pixel: u32 = 0; for ((out_byte_0, out_byte_1), out_byte_2) in out_byte_triplets { - let pixel = f32_to_f24(f32::read_from_native_endian(&mut remaining_bytes).unwrap()); - let [byte_2, byte_1, byte_0, _] = pixel.wrapping_sub(previous_pixel).to_ne_bytes(); - previous_pixel = pixel; + let pixel = f32_to_f24( + f32::read_from_native_endian(&mut remaining_bytes_ne) + .expect("failed to read from in-memory bytes") + ); + + let [_, byte_0, byte_1, byte_2] = pixel + .wrapping_sub(previous_pixel).to_be_bytes(); *out_byte_0 = byte_0; *out_byte_1 = byte_1; *out_byte_2 = byte_2; + previous_pixel = pixel; } }, } @@ -134,46 +140,40 @@ debug_assert_eq!(write.len(), 0, "bytes left after compression"); } - Ok(miniz_oxide::deflate::compress_to_vec_zlib(raw.as_slice(), 4)) + Ok(miniz_oxide::deflate::compress_to_vec_zlib(encoded_be.as_slice(), 4)) } -#[cfg_attr(target_endian = "big", allow(unused, unreachable_code))] -pub fn decompress(channels: &ChannelList, bytes: ByteVec, area: IntegerBounds, expected_byte_size: usize, pedantic: bool) -> Result { - #[cfg(target_endian = "big")] { - return Err(Error::unsupported( - "PXR24 decompression method not supported yet on big endian processor architecture" - )) - } - +pub fn decompress(channels: &ChannelList, bytes_le: ByteVec, area: IntegerBounds, expected_byte_size: usize, pedantic: bool) -> Result { let options = zune_inflate::DeflateOptions::default().set_limit(expected_byte_size).set_size_hint(expected_byte_size); - let mut decoder = zune_inflate::DeflateDecoder::new_with_options(&bytes, options); - let raw = decoder.decode_zlib() + let mut decompressor = zune_inflate::DeflateDecoder::new_with_options(&bytes_le, options); + + let encoded_be = decompressor.decode_zlib() .map_err(|_| Error::invalid("zlib-compressed data malformed"))?; // TODO share code with zip? - let mut read = raw.as_slice(); + let mut encoded_be = encoded_be.as_slice(); let mut out = Vec::with_capacity(expected_byte_size.min(2048*4)); for y in area.position.1 .. area.end().1 { for channel in &channels.list { - if mod_p(y, usize_to_i32(channel.sampling.1)) != 0 { continue; } + if mod_p(y, usize_to_i32(channel.sampling.1, "sampling")?) != 0 { continue; } let sample_count_x = channel.subsampled_resolution(area.size).0; let mut read_sample_line = ||{ - if sample_count_x > read.len() { return Err(Error::invalid("not enough data")) } - let (samples, rest) = read.split_at(sample_count_x); - read = rest; + if sample_count_x > encoded_be.len() { return Err(Error::invalid("not enough data")) } + let (samples, rest) = encoded_be.split_at(sample_count_x); + encoded_be = rest; Ok(samples) }; - let mut pixel_accumulation: u32 = 0; match channel.sample_type { SampleType::F16 => { let sample_byte_pairs = read_sample_line()?.iter() .zip(read_sample_line()?); + let mut pixel_accumulation: u32 = 0; for (&in_byte_0, &in_byte_1) in sample_byte_pairs { - let difference = u16::from_ne_bytes([in_byte_1, in_byte_0]) as u32; + let difference = u16::from_be_bytes([in_byte_0, in_byte_1]) as u32; pixel_accumulation = pixel_accumulation.overflowing_add(difference).0; out.extend_from_slice(&(pixel_accumulation as u16).to_ne_bytes()); } @@ -185,8 +185,9 @@ .zip(read_sample_line()?) .zip(read_sample_line()?); + let mut pixel_accumulation: u32 = 0; for (((&in_byte_0, &in_byte_1), &in_byte_2), &in_byte_3) in sample_byte_quads { - let difference = u32::from_ne_bytes([in_byte_3, in_byte_2, in_byte_1, in_byte_0]); + let difference = u32::from_be_bytes([in_byte_0, in_byte_1, in_byte_2, in_byte_3]); pixel_accumulation = pixel_accumulation.overflowing_add(difference).0; out.extend_from_slice(&pixel_accumulation.to_ne_bytes()); } @@ -196,8 +197,9 @@ let sample_byte_triplets = read_sample_line()?.iter() .zip(read_sample_line()?).zip(read_sample_line()?); + let mut pixel_accumulation: u32 = 0; for ((&in_byte_0, &in_byte_1), &in_byte_2) in sample_byte_triplets { - let difference = u32::from_ne_bytes([0, in_byte_2, in_byte_1, in_byte_0]); + let difference = u32::from_be_bytes([in_byte_0, in_byte_1, in_byte_2, 0]); pixel_accumulation = pixel_accumulation.overflowing_add(difference).0; out.extend_from_slice(&pixel_accumulation.to_ne_bytes()); } @@ -206,11 +208,11 @@ } } - if pedantic && !read.is_empty() { + if pedantic && !encoded_be.is_empty() { return Err(Error::invalid("too much data")); } - Ok(super::convert_little_endian_to_current(out, channels, area)) + Ok(out) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/rle.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/rle.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/rle.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/rle.rs 2006-07-24 01:21:28.000000000 +0000 @@ -11,82 +11,82 @@ pub fn decompress_bytes( channels: &ChannelList, - compressed: ByteVec, + compressed_le: ByteVec, rectangle: IntegerBounds, expected_byte_size: usize, pedantic: bool, ) -> Result { - let mut remaining = compressed.as_slice(); - let mut decompressed = Vec::with_capacity(expected_byte_size.min(8*2048)); + let mut remaining_le = compressed_le.as_slice(); + let mut decompressed_le = Vec::with_capacity(expected_byte_size.min(8*2048)); - while !remaining.is_empty() && decompressed.len() != expected_byte_size { - let count = take_1(&mut remaining)? as i8 as i32; + while !remaining_le.is_empty() && decompressed_le.len() != expected_byte_size { + let count = take_1(&mut remaining_le)? as i8 as i32; if count < 0 { // take the next '-count' bytes as-is - let values = take_n(&mut remaining, (-count) as usize)?; - decompressed.extend_from_slice(values); + let values = take_n(&mut remaining_le, (-count) as usize)?; + decompressed_le.extend_from_slice(values); } else { // repeat the next value 'count + 1' times - let value = take_1(&mut remaining)?; - decompressed.resize(decompressed.len() + count as usize + 1, value); + let value = take_1(&mut remaining_le)?; + decompressed_le.resize(decompressed_le.len() + count as usize + 1, value); } } - if pedantic && !remaining.is_empty() { + if pedantic && !remaining_le.is_empty() { return Err(Error::invalid("data amount")); } - differences_to_samples(&mut decompressed); - interleave_byte_blocks(&mut decompressed); - Ok(super::convert_little_endian_to_current(decompressed, channels, rectangle))// TODO no alloc + differences_to_samples(&mut decompressed_le); + interleave_byte_blocks(&mut decompressed_le); + super::convert_little_endian_to_current(decompressed_le, channels, rectangle) // TODO no alloc } -pub fn compress_bytes(channels: &ChannelList, uncompressed: ByteVec, rectangle: IntegerBounds) -> Result { +pub fn compress_bytes(channels: &ChannelList, uncompressed_ne: ByteVec, rectangle: IntegerBounds) -> Result { // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - let mut data = super::convert_current_to_little_endian(uncompressed, channels, rectangle);// TODO no alloc + let mut data_le = super::convert_current_to_little_endian(uncompressed_ne, channels, rectangle)?;// TODO no alloc - separate_bytes_fragments(&mut data); - samples_to_differences(&mut data); + separate_bytes_fragments(&mut data_le); + samples_to_differences(&mut data_le); - let mut compressed = Vec::with_capacity(data.len()); + let mut compressed_le = Vec::with_capacity(data_le.len()); let mut run_start = 0; let mut run_end = 1; - while run_start < data.len() { + while run_start < data_le.len() { while - run_end < data.len() - && data[run_start] == data[run_end] + run_end < data_le.len() + && data_le[run_start] == data_le[run_end] && (run_end - run_start) as i32 - 1 < MAX_RUN_LENGTH as i32 { run_end += 1; } if run_end - run_start >= MIN_RUN_LENGTH { - compressed.push(((run_end - run_start) as i32 - 1) as u8); - compressed.push(data[run_start]); + compressed_le.push(((run_end - run_start) as i32 - 1) as u8); + compressed_le.push(data_le[run_start]); run_start = run_end; } else { while - run_end < data.len() && ( - (run_end + 1 >= data.len() || data[run_end] != data[run_end + 1]) - || (run_end + 2 >= data.len() || data[run_end + 1] != data[run_end + 2]) + run_end < data_le.len() && ( + (run_end + 1 >= data_le.len() || data_le[run_end] != data_le[run_end + 1]) + || (run_end + 2 >= data_le.len() || data_le[run_end + 1] != data_le[run_end + 2]) ) && run_end - run_start < MAX_RUN_LENGTH { run_end += 1; } - compressed.push((run_start as i32 - run_end as i32) as u8); - compressed.extend_from_slice(&data[run_start .. run_end]); + compressed_le.push((run_start as i32 - run_end as i32) as u8); + compressed_le.extend_from_slice(&data_le[run_start .. run_end]); run_start = run_end; run_end += 1; } } - Ok(compressed) + Ok(compressed_le) } fn take_1(slice: &mut &[u8]) -> Result { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/zip.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/zip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/compression/zip.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/compression/zip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -14,28 +14,28 @@ pub fn decompress_bytes( channels: &ChannelList, - data: ByteVec, + data_le: ByteVec, rectangle: IntegerBounds, expected_byte_size: usize, _pedantic: bool, ) -> Result { let options = zune_inflate::DeflateOptions::default().set_limit(expected_byte_size).set_size_hint(expected_byte_size); - let mut decoder = zune_inflate::DeflateDecoder::new_with_options(&data, options); - let mut decompressed = decoder.decode_zlib() + let mut decoder = zune_inflate::DeflateDecoder::new_with_options(&data_le, options); + let mut decompressed_le = decoder.decode_zlib() .map_err(|_| Error::invalid("zlib-compressed data malformed"))?; - differences_to_samples(&mut decompressed); - interleave_byte_blocks(&mut decompressed); + differences_to_samples(&mut decompressed_le); + interleave_byte_blocks(&mut decompressed_le); - Ok(super::convert_little_endian_to_current(decompressed, channels, rectangle))// TODO no alloc + super::convert_little_endian_to_current(decompressed_le, channels, rectangle) // TODO no alloc } -pub fn compress_bytes(channels: &ChannelList, uncompressed: ByteVec, rectangle: IntegerBounds) -> Result { +pub fn compress_bytes(channels: &ChannelList, uncompressed_ne: ByteVec, rectangle: IntegerBounds) -> Result { // see https://github.com/AcademySoftwareFoundation/openexr/blob/3bd93f85bcb74c77255f28cdbb913fdbfbb39dfe/OpenEXR/IlmImf/ImfTiledOutputFile.cpp#L750-L842 - let mut packed = convert_current_to_little_endian(uncompressed, channels, rectangle); + let mut packed_le = convert_current_to_little_endian(uncompressed_ne, channels, rectangle)?; - separate_bytes_fragments(&mut packed); - samples_to_differences(&mut packed); + separate_bytes_fragments(&mut packed_le); + samples_to_differences(&mut packed_le); - Ok(miniz_oxide::deflate::compress_to_vec_zlib(packed.as_slice(), 4)) + Ok(miniz_oxide::deflate::compress_to_vec_zlib(packed_le.as_slice(), 4)) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -99,38 +99,47 @@ } } -/// Return error on invalid range. +/// Typically used during decoding. Return error on invalid range. #[inline] pub(crate) fn i32_to_usize(value: i32, error_message: &'static str) -> Result { - usize::try_from(value).map_err(|_| Error::invalid(error_message)) + usize::try_from(value).map_err(|_| { + if value < 0 { Error::invalid(error_message) } + else { Error::unsupported(error_message) } + }) } -/// Return error on invalid range. +/// Typically used during encoding. Return error on overflow. #[inline] -pub(crate) fn usize_to_u16(value: usize) -> Result { - Ok(u16::try_from(value)?) +pub(crate) fn usize_to_u32(value: usize, error_message: &'static str) -> Result { + u32::try_from(value).map_err(|_| Error::invalid(error_message)) } -/// Panic on overflow. +/// Typically used during encoding. Return error on invalid range. #[inline] -pub(crate) fn u64_to_usize(value: u64) -> usize { - usize::try_from(value).expect("(u64 as usize) overflowed") +pub(crate) fn usize_to_u16(value: usize, error_message: &'static str) -> Result { + u16::try_from(value).map_err(|_| Error::invalid(error_message)) } -/// Panic on overflow. +/// Typically used during decoding. Return error on invalid range. #[inline] -pub(crate) fn u32_to_usize(value: u32) -> usize { - usize::try_from(value).expect("(u32 as usize) overflowed") +pub(crate) fn u64_to_usize(value: u64, error_message: &'static str) -> Result { + usize::try_from(value).map_err(|_| Error::unsupported(error_message)) } -/// Panic on overflow. +/// Typically used during decoding. Return error on invalid range. #[inline] -pub(crate) fn usize_to_i32(value: usize) -> i32 { - i32::try_from(value).expect("(usize as i32) overflowed") +pub(crate) fn u32_to_usize(value: u32, error_message: &'static str) -> Result { + usize::try_from(value).map_err(|_| Error::unsupported(error_message)) } -/// Panic on overflow. +/// Typically used during encoding. Return error on invalid range. #[inline] -pub(crate) fn usize_to_u64(value: usize) -> u64 { - u64::try_from(value).expect("(usize as u64) overflowed") +pub(crate) fn usize_to_i32(value: usize, error_message: &'static str) -> Result { + i32::try_from(value).map_err(|_| Error::invalid(error_message)) +} + +/// Typically used during encoding. Return error on invalid range. +#[inline] +pub(crate) fn usize_to_u64(value: usize, error_message: &'static str) -> Result { + u64::try_from(value).map_err(|_| Error::invalid(error_message)) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -881,7 +881,6 @@ use std::ops::Not; use crate::block::samples::IntoNativeSample; - /// Compare two objects, but with a few special quirks. /// Intended mainly for unit testing. pub trait ValidateResult { @@ -1321,6 +1320,81 @@ object.assert_equals_result(&object); } } + + + #[test] + fn test_nan_compression_attribute(){ + use crate::prelude::*; + use crate::prelude::Compression::*; + use std::io::Cursor; + use crate::image::pixel_vec::PixelVec; + use crate::prelude::LineOrder::Increasing; + + let all_compression_methods = [ + Uncompressed, RLE, ZIP1, ZIP16, PXR24, PIZ, B44, B44A, + ]; + + let original_pixels: [(f32,f32,f16); 4] = [ + (f32::NAN, f32::from_bits(0x7fc01234), f16::from_bits(0x7E01)), + (f32::NAN, f32::from_bits(0xffcabcde), f16::from_bits(0x7FFF)), + (f32::NAN, f32::from_bits(0x7f800001), f16::from_bits(0xFE01)), + (f32::NAN, f32::NAN, f16::NAN), + ]; + + assert!( + original_pixels.iter() + .all(|&(a,b,c)| a.is_nan() && b.is_nan() && c.is_nan()), + "test case has a bug" + ); + + for compression in all_compression_methods { + let mut file_bytes = Vec::new(); + + let original_image = Image::from_encoded_channels( + (2, 2), + Encoding { + compression, + line_order: Increasing, + ..Encoding::default() + }, + SpecificChannels::rgb(PixelVec::new((2, 2), original_pixels.to_vec())) + ); + + let result = original_image.write().to_buffered(Cursor::new(&mut file_bytes)); + if let Err(Error::NotSupported(_)) = result { continue; } + + let reconstructed_image = + read().no_deep_data().largest_resolution_level() + .rgb_channels(PixelVec::<(f32, f32, f16)>::constructor, PixelVec::set_pixel) + .first_valid_layer().all_attributes().from_buffered(Cursor::new(&file_bytes)).unwrap(); + + assert_eq!( + original_image.layer_data.channel_data.pixels.pixels.len(), + reconstructed_image.layer_data.channel_data.pixels.pixels.len() + ); + + let was_nanness_preserved = reconstructed_image.layer_data.channel_data.pixels.pixels + .iter().all(|(r,g,b)| r.is_nan() && g.is_nan() && b.is_nan()); + + assert_eq!( + was_nanness_preserved, compression.supports_nan(), + "{} nanness claims do not match real output", compression + ); + + let was_nan_pattern_preserved = reconstructed_image.layer_data.channel_data.pixels.pixels + .iter().zip(original_pixels.iter()) + .all(|((r2, g2, b2), (r1, g1, b1))| + r2.to_bits() == r1.to_bits() && + g2.to_bits() == g1.to_bits() && + b2.to_bits() == b1.to_bits() + ); + + assert_eq!( + was_nan_pattern_preserved, compression.preserves_nan_bits(), + "{} nan bit claims do not match real output", compression + ); + } + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/read/image.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/read/image.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/image.rs 2006-07-24 01:21:28.000000000 +0000 @@ -29,7 +29,11 @@ pub fn new(read_layers: L, on_progress: F) -> Self { Self { on_progress, read_layers, - pedantic: false, parallel: true, + pedantic: false, + #[cfg(not(feature = "rayon"))] + parallel: false, + #[cfg(feature = "rayon")] + parallel: true, } } @@ -120,6 +124,10 @@ // TODO propagate send requirement further upwards if parallel { + #[cfg(not(feature = "rayon"))] + return Err(crate::error::Error::unsupported("parallel decompression requires the rayon feature")); + + #[cfg(feature = "rayon")] block_reader.decompress_parallel(pedantic, |meta_data, block|{ image_collector.read_block(&meta_data.headers, block) })?; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/read/specific_channels.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/specific_channels.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/read/specific_channels.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/read/specific_channels.rs 2006-07-24 01:21:28.000000000 +0000 @@ -315,6 +315,7 @@ /// Reads the samples for one line, using the sample type specified in the file, /// and then converts those to the desired sample types. /// Uses batches to allow vectorization, converting multiple values with one instruction. +/// Does not convert endianness. fn read_and_convert_all_samples_batched<'t, From, To>( mut in_bytes: impl Read, out_samples: &mut impl ExactSizeIterator, @@ -344,7 +345,7 @@ // error[E0658]: attributes on expressions are experimental, // see issue #15701 for more information let read_n_samples = &mut move |samples: &mut [From]| { - Data::read_slice(&mut in_bytes, samples).expect(byte_error_msg); + Data::read_slice_ne(&mut in_bytes, samples).expect(byte_error_msg); }; // temporary arrays with fixed size, operations should be vectorized within these arrays @@ -377,7 +378,7 @@ fn equals_naive_f32(){ for total_array_size in [3, 7, 30, 41, 120, 10_423] { let input_f32s = (0..total_array_size).map(|_| rand::random::()).collect::>(); - let in_f32s_bytes = input_f32s.iter().cloned().flat_map(f32::to_le_bytes).collect::>(); + let in_f32s_bytes = input_f32s.iter().cloned().flat_map(f32::to_ne_bytes).collect::>(); let mut out_f16_samples_batched = vec![ f16::from_f32(rand::random::()); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/write/channels.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/channels.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/write/channels.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/channels.rs 2006-07-24 01:21:28.000000000 +0000 @@ -306,9 +306,9 @@ // match outside the loop to avoid matching on every single sample match self.target_sample_type { // TODO does this boil down to a `memcpy` where the sample type equals the type parameter? - SampleType::F16 => for sample in samples { sample.to_f16().write(byte_writer).expect(write_error_msg); }, - SampleType::F32 => for sample in samples { sample.to_f32().write(byte_writer).expect(write_error_msg); }, - SampleType::U32 => for sample in samples { sample.to_u32().write(byte_writer).expect(write_error_msg); }, + SampleType::F16 => for sample in samples { sample.to_f16().write_ne(byte_writer).expect(write_error_msg); }, + SampleType::F32 => for sample in samples { sample.to_f32().write_ne(byte_writer).expect(write_error_msg); }, + SampleType::U32 => for sample in samples { sample.to_u32().write_ne(byte_writer).expect(write_error_msg); }, }; debug_assert!(byte_writer.is_empty(), "all samples are written, but more were expected"); @@ -352,7 +352,7 @@ #[cfg(test)] -pub mod test { +mod test { use crate::image::write::channels::WritableChannels; use crate::image::SpecificChannels; use crate::prelude::{f16}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/write/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/image/write/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/image/write/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -73,7 +73,13 @@ WriteImageWithOptions { image: self, check_compatibility: true, + + #[cfg(not(feature = "rayon"))] + parallel: false, + + #[cfg(feature = "rayon")] parallel: true, + on_progress: ignore_progress } } @@ -158,24 +164,19 @@ crate::block::write( write, headers, self.check_compatibility, move |meta, chunk_writer|{ - let blocks = meta.collect_ordered_block_data(|block_index| layers.extract_uncompressed_block(&meta.headers, block_index) ); let chunk_writer = chunk_writer.on_progress(self.on_progress); - if self.parallel { chunk_writer.compress_all_blocks_parallel(&meta, blocks)?; } - else { chunk_writer.compress_all_blocks_sequential(&meta, blocks)?; } - /*let blocks_writer = chunk_writer.as_blocks_writer(&meta); - - // TODO propagate send requirement further upwards if self.parallel { - blocks_writer.compress_all_blocks_parallel(blocks)?; - } - else { - blocks_writer.compress_all_blocks_sequential(blocks)?; - }*/ + #[cfg(not(feature = "rayon"))] + return Err(crate::error::Error::unsupported("parallel compression requires the rayon feature")); + #[cfg(feature = "rayon")] + chunk_writer.compress_all_blocks_parallel(&meta, blocks)?; + } + else { chunk_writer.compress_all_blocks_sequential(&meta, blocks)?; } Ok(()) } ) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/io.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/io.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -13,7 +13,7 @@ use std::path::Path; use std::fs::File; use std::convert::TryFrom; - +use smallvec::{Array, SmallVec}; /// Skip reading uninteresting bytes without allocating. #[inline] @@ -264,30 +264,52 @@ /// Number of bytes this would consume in an exr file. const BYTE_SIZE: usize = ::std::mem::size_of::(); - /// Read a value of type `Self`. - fn read(read: &mut impl Read) -> Result; + /// Read a value of type `Self` from a little-endian source. + fn read_le(read: &mut impl Read) -> Result; + + /// Read a value of type `Self` from a **native-endian** source (no conversion). + fn read_ne(read: &mut impl Read) -> Result; + + /// Read as many values of type `Self` as fit into the specified slice, from a little-endian source. + /// If the slice cannot be filled completely, returns `Error::Invalid`. + fn read_slice_le(read: &mut impl Read, slice: &mut[Self]) -> UnitResult; - /// Read as many values of type `Self` as fit into the specified slice. + /// Read as many values of type `Self` as fit into the specified slice, from a **native-endian** source (no conversion). /// If the slice cannot be filled completely, returns `Error::Invalid`. - fn read_slice(read: &mut impl Read, slice: &mut[Self]) -> UnitResult; + fn read_slice_ne(read: &mut impl Read, slice: &mut[Self]) -> UnitResult; /// Read as many values of type `Self` as specified with `data_size`. /// /// This method will not allocate more memory than `soft_max` at once. /// If `hard_max` is specified, it will never read any more than that. - /// Returns `Error::Invalid` if reader does not contain the desired number of elements. + /// Returns `Error::Invalid` if the reader does not contain the desired number of elements. + /// Reads from little-endian byte source. #[inline] - fn read_vec(read: &mut impl Read, data_size: usize, soft_max: usize, hard_max: Option, purpose: &'static str) -> Result> { + fn read_vec_le(read: &mut impl Read, data_size: usize, soft_max: usize, hard_max: Option, purpose: &'static str) + -> Result> + { + if let Some(max) = hard_max { + if data_size > max { + return Err(Error::invalid(purpose)) + } + } + let mut vec = Vec::with_capacity(data_size.min(soft_max)); - Self::read_into_vec(read, &mut vec, data_size, soft_max, hard_max, purpose)?; + Self::read_into_vec_le(read, &mut vec, data_size, soft_max, hard_max, purpose)?; Ok(vec) } - /// Write this value to the writer. - fn write(self, write: &mut impl Write) -> UnitResult; + /// Write this value to the writer, converting to little-endian format. + fn write_le(self, write: &mut impl Write) -> UnitResult; + + /// Write this value to the writer, in **native-endian** format (no conversion). + fn write_ne(self, write: &mut impl Write) -> UnitResult; + + /// Write all values of that slice to the writer, converting to little-endian format. + fn write_slice_le(write: &mut impl Write, slice: &[Self]) -> UnitResult; - /// Write all values of that slice to the writer. - fn write_slice(write: &mut impl Write, slice: &[Self]) -> UnitResult; + /// Write all values of that slice to the writer, in **native-endian** format (no conversion). + fn write_slice_ne(write: &mut impl Write, slice: &[Self]) -> UnitResult; /// Read as many values of type `Self` as specified with `data_size` into the provided vector. @@ -296,7 +318,12 @@ /// If `hard_max` is specified, it will never read any more than that. /// Returns `Error::Invalid` if reader does not contain the desired number of elements. #[inline] - fn read_into_vec(read: &mut impl Read, data: &mut Vec, data_size: usize, soft_max: usize, hard_max: Option, purpose: &'static str) -> UnitResult { + fn read_into_vec_le( + read: &mut impl Read, + data: &mut impl ResizableVec, + data_size: usize, soft_max: usize, hard_max: Option, + purpose: &'static str + ) -> UnitResult { if let Some(max) = hard_max { if data_size > max { return Err(Error::invalid(purpose)) @@ -313,17 +340,17 @@ let chunk_end = (chunk_start + soft_max).min(data_size); data.resize(chunk_end, Self::default()); - Self::read_slice(read, &mut data[chunk_start .. chunk_end])?; // safe because of `min(data_size)`` + Self::read_slice_le(read, &mut data.as_mut()[chunk_start .. chunk_end])?; // safe because of `min(data_size)` } Ok(()) } - /// Write the length of the slice and then its contents. + /// Write the length of the slice and then its contents, converting to little-endian format. #[inline] - fn write_i32_sized_slice(write: &mut W, slice: &[Self]) -> UnitResult { - i32::try_from(slice.len())?.write(write)?; - Self::write_slice(write, slice) + fn write_i32_sized_slice_le(write: &mut W, slice: &[Self]) -> UnitResult { + i32::try_from(slice.len())?.write_le(write)?; + Self::write_slice_le(write, slice) } /// Read the desired element count and then read that many items into a vector. @@ -332,9 +359,9 @@ /// If `hard_max` is specified, it will never read any more than that. /// Returns `Error::Invalid` if reader does not contain the desired number of elements. #[inline] - fn read_i32_sized_vec(read: &mut impl Read, soft_max: usize, hard_max: Option, purpose: &'static str) -> Result> { - let size = usize::try_from(i32::read(read)?)?; - Self::read_vec(read, size, soft_max, hard_max, purpose) + fn read_i32_sized_vec_le(read: &mut impl Read, soft_max: usize, hard_max: Option, purpose: &'static str) -> Result> { + let size = usize::try_from(i32::read_le(read)?)?; + Self::read_vec_le(read, size, soft_max, hard_max, purpose) } /// Fill the slice with this value. @@ -347,32 +374,81 @@ } } +/// A unifying trait that is implemented for Vec and SmallVec, +/// focused on resizing capabilities. +pub trait ResizableVec: AsMut<[T]> { + fn resize(&mut self, new_len: usize, value: T); + fn len(&self) -> usize; +} + +impl ResizableVec for Vec { + fn resize(&mut self, new_len: usize, value: T) { + Vec::resize(self, new_len, value) + } + fn len(&self) -> usize { + Vec::len(self) + } +} + +impl> ResizableVec for SmallVec { + fn resize(&mut self, new_len: usize, value: T) { + SmallVec::resize(self, new_len, value) + } + fn len(&self) -> usize { + SmallVec::len(self) + } +} + + macro_rules! implement_data_for_primitive { ($kind: ident) => { impl Data for $kind { #[inline] - fn read(read: &mut impl Read) -> Result { + fn read_le(read: &mut impl Read) -> Result { Ok(read.read_from_little_endian()?) } #[inline] - fn write(self, write: &mut impl Write) -> Result<()> { + fn read_ne(read: &mut impl Read) -> Result { + Ok(read.read_from_native_endian()?) + } + + #[inline] + fn write_le(self, write: &mut impl Write) -> Result<()> { write.write_as_little_endian(&self)?; Ok(()) } #[inline] - fn read_slice(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { + fn write_ne(self, write: &mut impl Write) -> Result<()> { + write.write_as_native_endian(&self)?; + Ok(()) + } + + #[inline] + fn read_slice_le(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { read.read_from_little_endian_into(slice)?; Ok(()) } #[inline] - fn write_slice(write: &mut impl Write, slice: &[Self]) -> Result<()> { + fn read_slice_ne(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { + read.read_from_native_endian_into(slice)?; + Ok(()) + } + + #[inline] + fn write_slice_le(write: &mut impl Write, slice: &[Self]) -> Result<()> { write.write_as_little_endian(slice)?; Ok(()) } + + #[inline] + fn write_slice_ne(write: &mut impl Write, slice: &[Self]) -> Result<()> { + write.write_as_native_endian(slice)?; + Ok(()) + } } }; } @@ -391,25 +467,47 @@ impl Data for f16 { #[inline] - fn read(read: &mut impl Read) -> Result { - u16::read(read).map(f16::from_bits) + fn read_le(read: &mut impl Read) -> Result { + u16::read_le(read).map(f16::from_bits) } #[inline] - fn read_slice(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { - let bits = slice.reinterpret_cast_mut(); - u16::read_slice(read, bits) + fn read_ne(read: &mut impl Read) -> Result { + u16::read_ne(read).map(f16::from_bits) } #[inline] - fn write(self, write: &mut impl Write) -> Result<()> { - self.to_bits().write(write) + fn read_slice_le(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { + let bits_mut = slice.reinterpret_cast_mut(); + u16::read_slice_le(read, bits_mut) + } + + #[inline] + fn read_slice_ne(read: &mut impl Read, slice: &mut [Self]) -> Result<()> { + let bits_mut = slice.reinterpret_cast_mut(); + u16::read_slice_ne(read, bits_mut) + } + + #[inline] + fn write_le(self, write: &mut impl Write) -> Result<()> { + self.to_bits().write_le(write) + } + + #[inline] + fn write_ne(self, write: &mut impl Write) -> Result<()> { + self.to_bits().write_ne(write) + } + + #[inline] + fn write_slice_le(write: &mut impl Write, slice: &[Self]) -> Result<()> { + let bits = slice.reinterpret_cast(); + u16::write_slice_le(write, bits) } #[inline] - fn write_slice(write: &mut impl Write, slice: &[Self]) -> Result<()> { + fn write_slice_ne(write: &mut impl Write, slice: &[Self]) -> Result<()> { let bits = slice.reinterpret_cast(); - u16::write_slice(write, bits) + u16::write_slice_ne(write, bits) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/attribute.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/attribute.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/attribute.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/attribute.rs 2006-07-24 01:21:28.000000000 +0000 @@ -82,6 +82,20 @@ /// 3D float vector. FloatVec3((f32, f32, f32)), + /// An explicitly untyped attribute for binary application data. + /// Also contains the type name of this value. + /// The format of the byte contents is explicitly unspecified. + /// Used for custom application data. + Bytes { + + /// An application-specific type hint of the byte contents. + type_hint: Text, + + /// The contents of this byte array are completely unspecified + /// and should be treated as untrusted data. + bytes: SmallVec<[u8; 16]> + }, + /// A custom attribute. /// Contains the type name of this value. Custom { @@ -91,12 +105,12 @@ /// The value, stored in little-endian byte order, of the value. /// Use the `exr::io::Data` trait to extract binary values from this vector. - bytes: Vec + bytes: SmallVec<[u8; 16]> }, } /// A byte array with each byte being a char. -/// This is not UTF an must be constructed from a standard string. +/// This is not UTF and it must be constructed from a standard string. // TODO is this ascii? use a rust ascii crate? #[derive(Clone, PartialEq, Ord, PartialOrd, Default)] // hash implemented manually pub struct Text { @@ -490,23 +504,41 @@ self.bytes.len() + i32::BYTE_SIZE } + /// The byte count this string would occupy if it were encoded as a size-prefixed string. + pub fn u32_sized_byte_size(&self) -> usize { + self.bytes.len() + u32::BYTE_SIZE + } + + /// Write the length of a string and then the contents with that length. + pub fn write_i32_sized_le(&self, write: &mut W) -> UnitResult { + debug_assert!(self.validate( false, None).is_ok(), "text size bug"); + i32::write_le(usize_to_i32(self.bytes.len(), "text length")?, write)?; + Self::write_unsized_bytes(self.bytes.as_slice(), write) + } + /// Write the length of a string and then the contents with that length. - pub fn write_i32_sized(&self, write: &mut W) -> UnitResult { + pub fn write_u32_sized_le(&self, write: &mut W) -> UnitResult { debug_assert!(self.validate( false, None).is_ok(), "text size bug"); - i32::write(usize_to_i32(self.bytes.len()), write)?; + u32::write_le(usize_to_u32(self.bytes.len(), "text length")?, write)?; Self::write_unsized_bytes(self.bytes.as_slice(), write) } /// Without validation, write this instance to the byte stream. fn write_unsized_bytes(bytes: &[u8], write: &mut W) -> UnitResult { - u8::write_slice(write, bytes)?; + u8::write_slice_le(write, bytes)?; Ok(()) } /// Read the length of a string and then the contents with that length. - pub fn read_i32_sized(read: &mut R, max_size: usize) -> Result { - let size = i32_to_usize(i32::read(read)?, "vector size")?; - Ok(Text::from_bytes_unchecked(SmallVec::from_vec(u8::read_vec(read, size, 1024, Some(max_size), "text attribute length")?))) + pub fn read_i32_sized_le(read: &mut R, max_size: usize) -> Result { + let size = i32_to_usize(i32::read_le(read)?, "vector size")?; + Ok(Text::from_bytes_unchecked(SmallVec::from_vec(u8::read_vec_le(read, size, 1024, Some(max_size), "text attribute length")?))) + } + + /// Read the length of a string and then the contents with that length. + pub fn read_u32_sized_le(read: &mut R, max_size: usize) -> Result { + let size = u32_to_usize(u32::read_le(read)?, "text length")?; + Ok(Text::from_bytes_unchecked(SmallVec::from_vec(u8::read_vec_le(read, size, 1024, Some(max_size), "text attribute length")?))) } /// Read the contents with that length. @@ -524,7 +556,7 @@ // for large strings, read a dynamic vec of arbitrary size else { - Ok(Text::from_bytes_unchecked(SmallVec::from_vec(u8::read_vec(read, size, 1024, None, "text attribute length")?))) + Ok(Text::from_bytes_unchecked(SmallVec::from_vec(u8::read_vec_le(read, size, 1024, None, "text attribute length")?))) } } @@ -544,10 +576,10 @@ /// Read a string until the null-terminator is found. Then skips the null-terminator. pub fn read_null_terminated(read: &mut R, max_len: usize) -> Result { - let mut bytes = smallvec![ u8::read(read)? ]; // null-terminated strings are always at least 1 byte + let mut bytes = smallvec![ u8::read_le(read)? ]; // null-terminated strings are always at least 1 byte loop { - match u8::read(read)? { + match u8::read_le(read)? { 0 => break, non_terminator => bytes.push(non_terminator), } @@ -562,7 +594,7 @@ /// Allows any text length since it is only used for attribute values, /// but not attribute names, attribute type names, or channel names. - fn read_vec_of_i32_sized( + fn read_vec_of_i32_sized_texts_le( read: &mut PeekRead, total_byte_size: usize ) -> Result> @@ -573,7 +605,7 @@ let mut processed_bytes = 0; while processed_bytes < total_byte_size { - let text = Text::read_i32_sized(read, total_byte_size)?; + let text = Text::read_i32_sized_le(read, total_byte_size)?; processed_bytes += ::std::mem::size_of::(); // size i32 of the text processed_bytes += text.bytes.len(); result.push(text); @@ -589,10 +621,10 @@ /// Allows any text length since it is only used for attribute values, /// but not attribute names, attribute type names, or channel names. - fn write_vec_of_i32_sized_texts(write: &mut W, texts: &[Text]) -> UnitResult { + fn write_vec_of_i32_sized_texts_le(write: &mut W, texts: &[Text]) -> UnitResult { // length of the text-vector can be inferred from attribute size for text in texts { - text.write_i32_sized(write)?; + text.write_i32_sized_le(write)?; } Ok(()) @@ -770,7 +802,7 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut impl Write) -> UnitResult { - u8::write_slice(write, self.to_text_bytes())?; + u8::write_slice_le(write, self.to_text_bytes())?; Ok(()) } @@ -862,19 +894,19 @@ let Vec2(x_min, y_min) = self.position; let Vec2(x_max, y_max) = self.max(); - x_min.write(write)?; - y_min.write(write)?; - x_max.write(write)?; - y_max.write(write)?; + x_min.write_le(write)?; + y_min.write_le(write)?; + x_max.write_le(write)?; + y_max.write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { - let x_min = i32::read(read)?; - let y_min = i32::read(read)?; - let x_max = i32::read(read)?; - let y_max = i32::read(read)?; + let x_min = i32::read_le(read)?; + let y_min = i32::read_le(read)?; + let x_max = i32::read_le(read)?; + let y_max = i32::read_le(read)?; let min = Vec2(x_min.min(x_max), y_min.min(y_max)); let max = Vec2(x_min.max(x_max), y_min.max(y_max)); @@ -916,19 +948,19 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - self.min.x().write(write)?; - self.min.y().write(write)?; - self.max.x().write(write)?; - self.max.y().write(write)?; + self.min.x().write_le(write)?; + self.min.y().write_le(write)?; + self.max.x().write_le(write)?; + self.max.y().write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { - let x_min = f32::read(read)?; - let y_min = f32::read(read)?; - let x_max = f32::read(read)?; - let y_max = f32::read(read)?; + let x_min = f32::read_le(read)?; + let y_min = f32::read_le(read)?; + let x_max = f32::read_le(read)?; + let y_max = f32::read_le(read)?; Ok(FloatRect { min: Vec2(x_min, y_min), @@ -959,7 +991,7 @@ SampleType::U32 => 0_i32, SampleType::F16 => 1_i32, SampleType::F32 => 2_i32, - }.write(write)?; + }.write_le(write)?; Ok(()) } @@ -967,7 +999,7 @@ /// Read the value without validating. pub fn read(read: &mut R) -> Result { // there's definitely going to be more than 255 different pixel types in the future - Ok(match i32::read(read)? { + Ok(match i32::read_le(read)? { 0 => SampleType::U32, 1 => SampleType::F16, 2 => SampleType::F32, @@ -1033,11 +1065,11 @@ match self.quantize_linearly { false => 0_u8, true => 1_u8, - }.write(write)?; + }.write_le(write)?; - i8::write_slice(write, &[0_i8, 0_i8, 0_i8])?; - i32::write(usize_to_i32(self.sampling.x()), write)?; - i32::write(usize_to_i32(self.sampling.y()), write)?; + i8::write_slice_le(write, &[0_i8, 0_i8, 0_i8])?; + i32::write_le(usize_to_i32(self.sampling.x(), "text length")?, write)?; + i32::write_le(usize_to_i32(self.sampling.y(), "text length")?, write)?; Ok(()) } @@ -1046,17 +1078,17 @@ let name = Text::read_null_terminated(read, 256)?; let sample_type = SampleType::read(read)?; - let is_linear = match u8::read(read)? { + let is_linear = match u8::read_le(read)? { 1 => true, 0 => false, _ => return Err(Error::invalid("channel linearity attribute value")), }; let mut reserved = [0_i8; 3]; - i8::read_slice(read, &mut reserved)?; + i8::read_slice_le(read, &mut reserved)?; - let x_sampling = i32_to_usize(i32::read(read)?, "x channel sampling")?; - let y_sampling = i32_to_usize(i32::read(read)?, "y channel sampling")?; + let x_sampling = i32_to_usize(i32::read_le(read)?, "x channel sampling")?; + let y_sampling = i32_to_usize(i32::read_le(read)?, "y channel sampling")?; Ok(ChannelDescription { name, sample_type, @@ -1294,15 +1326,15 @@ /// Write this time code to the byte stream, encoded as TV60 integers. /// Returns an `Error::Invalid` if the fields are out of the allowed range. pub fn write(&self, write: &mut W) -> UnitResult { - self.pack_time_as_tv60_u32()?.write(write)?; // will validate - self.pack_user_data_as_u32().write(write)?; + self.pack_time_as_tv60_u32()?.write_le(write)?; // will validate + self.pack_user_data_as_u32().write_le(write)?; Ok(()) } /// Read the time code, without validating, extracting from TV60 integers. pub fn read(read: &mut R) -> Result { - let time_and_flags = u32::read(read)?; - let user_data = u32::read(read)?; + let time_and_flags = u32::read_le(read)?; + let user_data = u32::read_le(read)?; Ok(Self::from_tv60_time(time_and_flags, user_data)) } } @@ -1316,27 +1348,27 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - self.red.x().write(write)?; - self.red.y().write(write)?; + self.red.x().write_le(write)?; + self.red.y().write_le(write)?; - self.green.x().write(write)?; - self.green.y().write(write)?; + self.green.x().write_le(write)?; + self.green.y().write_le(write)?; - self.blue.x().write(write)?; - self.blue.y().write(write)?; + self.blue.x().write_le(write)?; + self.blue.y().write_le(write)?; - self.white.x().write(write)?; - self.white.y().write(write)?; + self.white.x().write_le(write)?; + self.white.y().write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { Ok(Chromaticities { - red: Vec2(f32::read(read)?, f32::read(read)?), - green: Vec2(f32::read(read)?, f32::read(read)?), - blue: Vec2(f32::read(read)?, f32::read(read)?), - white: Vec2(f32::read(read)?, f32::read(read)?), + red: Vec2(f32::read_le(read)?, f32::read_le(read)?), + green: Vec2(f32::read_le(read)?, f32::read_le(read)?), + blue: Vec2(f32::read_le(read)?, f32::read_le(read)?), + white: Vec2(f32::read_le(read)?, f32::read_le(read)?), }) } } @@ -1360,14 +1392,16 @@ B44A => 7_u8, DWAA(_) => 8_u8, DWAB(_) => 9_u8, - }.write(write)?; + HTJ2K256 => 10_u8, + HTJ2K32 => 11_u8, + }.write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { use self::Compression::*; - Ok(match u8::read(read)? { + Ok(match u8::read_le(read)? { 0 => Uncompressed, 1 => RLE, 2 => ZIP1, @@ -1378,6 +1412,8 @@ 7 => B44A, 8 => DWAA(None), 9 => DWAB(None), + 10 => HTJ2K256, + 11 => HTJ2K32, _ => return Err(Error::unsupported("unknown compression method")), }) } @@ -1396,7 +1432,7 @@ match self { LatitudeLongitude => 0_u8, Cube => 1_u8 - }.write(write)?; + }.write_le(write)?; Ok(()) } @@ -1404,7 +1440,7 @@ /// Read the value without validating. pub fn read(read: &mut R) -> Result { use self::EnvironmentMap::*; - Ok(match u8::read(read)? { + Ok(match u8::read_le(read)? { 0 => LatitudeLongitude, 1 => Cube, _ => return Err(Error::invalid("environment map attribute value")), @@ -1421,25 +1457,25 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - self.film_manufacturer_code.write(write)?; - self.film_type.write(write)?; - self.film_roll_prefix.write(write)?; - self.count.write(write)?; - self.perforation_offset.write(write)?; - self.perforations_per_count.write(write)?; + self.film_manufacturer_code.write_le(write)?; + self.film_type.write_le(write)?; + self.film_roll_prefix.write_le(write)?; + self.count.write_le(write)?; + self.perforation_offset.write_le(write)?; + self.perforations_per_count.write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { Ok(KeyCode { - film_manufacturer_code: i32::read(read)?, - film_type: i32::read(read)?, - film_roll_prefix: i32::read(read)?, - count: i32::read(read)?, - perforation_offset: i32::read(read)?, - perforations_per_frame: i32::read(read)?, - perforations_per_count: i32::read(read)?, + film_manufacturer_code: i32::read_le(read)?, + film_type: i32::read_le(read)?, + film_roll_prefix: i32::read_le(read)?, + count: i32::read_le(read)?, + perforation_offset: i32::read_le(read)?, + perforations_per_frame: i32::read_le(read)?, + perforations_per_count: i32::read_le(read)?, }) } } @@ -1458,7 +1494,7 @@ Increasing => 0_u8, Decreasing => 1_u8, Unspecified => 2_u8, - }.write(write)?; + }.write_le(write)?; Ok(()) } @@ -1466,7 +1502,7 @@ /// Read the value without validating. pub fn read(read: &mut R) -> Result { use self::LineOrder::*; - Ok(match u8::read(read)? { + Ok(match u8::read_le(read)? { 0 => Increasing, 1 => Decreasing, 2 => Unspecified, @@ -1487,22 +1523,22 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - u32::write(self.size.width() as u32, write)?; - u32::write(self.size.height() as u32, write)?; + u32::write_le(self.size.width() as u32, write)?; + u32::write_le(self.size.height() as u32, write)?; - i8::write_slice(write, &self.pixel_data)?; + i8::write_slice_le(write, &self.pixel_data)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { - let width = u32::read(read)? as usize; - let height = u32::read(read)? as usize; + let width = u32::read_le(read)? as usize; + let height = u32::read_le(read)? as usize; if let Some(pixel_count) = width.checked_mul(height) { // Multiply by the number of bytes per pixel. if let Some(byte_count) = pixel_count.checked_mul(4) { - let pixel_data = i8::read_vec( + let pixel_data = i8::read_vec_le( read, byte_count, 1024 * 1024 * 4, @@ -1551,8 +1587,8 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut W) -> UnitResult { - u32::write(self.tile_size.width() as u32, write)?; - u32::write(self.tile_size.height() as u32, write)?; + u32::write_le(self.tile_size.width() as u32, write)?; + u32::write_le(self.tile_size.height() as u32, write)?; let level_mode = match self.level_mode { LevelMode::Singular => 0_u8, @@ -1566,16 +1602,16 @@ }; let mode: u8 = level_mode + (rounding_mode * 16); - mode.write(write)?; + mode.write_le(write)?; Ok(()) } /// Read the value without validating. pub fn read(read: &mut R) -> Result { - let x_size = u32::read(read)? as usize; - let y_size = u32::read(read)? as usize; + let x_size = u32::read_le(read)? as usize; + let y_size = u32::read_le(read)? as usize; - let mode = u8::read(read)?; + let mode = u8::read_le(read)?; // wow you really saved that one byte here // mode = level_mode + (rounding_mode * 16) @@ -1623,10 +1659,10 @@ } /// Without validation, write this attribute to the byte stream. -pub fn write(name: &[u8], value: &AttributeValue, write: &mut W) -> UnitResult { +pub fn write(name: &TextSlice, value: &AttributeValue, write: &mut W) -> UnitResult { Text::write_null_terminated_bytes(name, write)?; Text::write_null_terminated_bytes(value.kind_name(), write)?; - i32::write(value.byte_size() as i32, write)?; + i32::write_le(value.byte_size() as i32, write)?; value.write(write) } @@ -1634,7 +1670,7 @@ pub fn read(read: &mut PeekRead, max_size: usize) -> Result<(Text, Result)> { let name = Text::read_null_terminated(read, max_size)?; let kind = Text::read_null_terminated(read, max_size)?; - let size = i32_to_usize(i32::read(read)?, "attribute size")?; + let size = i32_to_usize(i32::read_le(read)?, "attribute size")?; let value = AttributeValue::read(read, kind, size)?; Ok((name, value)) } @@ -1688,12 +1724,15 @@ TextVector(ref value) => value.iter().map(self::Text::i32_sized_byte_size).sum(), TileDescription(_) => self::TileDescription::byte_size(), Custom { ref bytes, .. } => bytes.len(), - BlockType(ref kind) => kind.byte_size() + BlockType(ref kind) => kind.byte_size(), + + Bytes { ref bytes, ref type_hint } => + type_hint.u32_sized_byte_size() + bytes.len(), } } /// The exr name string of the type that an attribute can have. - pub fn kind_name(&self) -> &[u8] { + pub fn kind_name(&self) -> &TextSlice { use self::AttributeValue::*; use self::type_names as ty; @@ -1721,8 +1760,9 @@ Text(_) => ty::TEXT, TextVector(_) => ty::TEXT_VECTOR, TileDescription(_) => ty::TILES, - Custom { ref kind, .. } => &kind.bytes, BlockType(_) => super::BlockType::TYPE_NAME, + Bytes{ .. } => ty::BYTES, + Custom { ref kind, .. } => kind.as_slice(), } } @@ -1733,17 +1773,17 @@ IntegerBounds(value) => value.write(write)?, FloatRect(value) => value.write(write)?, - I32(value) => value.write(write)?, - F32(value) => value.write(write)?, - F64(value) => value.write(write)?, - - Rational((a, b)) => { a.write(write)?; b.write(write)?; }, - TimeCode(codes) => { codes.write(write)?; }, - - IntVec2(Vec2(x, y)) => { x.write(write)?; y.write(write)?; }, - FloatVec2(Vec2(x, y)) => { x.write(write)?; y.write(write)?; }, - IntVec3((x, y, z)) => { x.write(write)?; y.write(write)?; z.write(write)?; }, - FloatVec3((x, y, z)) => { x.write(write)?; y.write(write)?; z.write(write)?; }, + I32(value) => value.write_le(write)?, + F32(value) => value.write_le(write)?, + F64(value) => value.write_le(write)?, + + Rational((a, b)) => { a.write_le(write)?; b.write_le(write)?; }, + TimeCode(codes) => codes.write(write)?, + + IntVec2(Vec2(x, y)) => { x.write_le(write)?; y.write_le(write)?; }, + FloatVec2(Vec2(x, y)) => { x.write_le(write)?; y.write_le(write)?; }, + IntVec3((x, y, z)) => { x.write_le(write)?; y.write_le(write)?; z.write_le(write)?; }, + FloatVec3((x, y, z)) => { x.write_le(write)?; y.write_le(write)?; z.write_le(write)?; }, ChannelList(ref channels) => channels.write(write)?, Chromaticities(ref value) => value.write(write)?, @@ -1753,19 +1793,25 @@ KeyCode(value) => value.write(write)?, LineOrder(value) => value.write(write)?, - Matrix3x3(mut value) => f32::write_slice(write, &mut value)?, - Matrix4x4(mut value) => f32::write_slice(write, &mut value)?, + Matrix3x3(mut value) => f32::write_slice_le(write, &mut value)?, + Matrix4x4(mut value) => f32::write_slice_le(write, &mut value)?, - Preview(ref value) => { value.write(write)?; }, + Preview(ref value) => value.write(write)?, // attribute value texts never have limited size. // also, don't serialize size, as it can be inferred from attribute size - Text(ref value) => u8::write_slice(write, value.bytes.as_slice())?, + Text(ref value) => u8::write_slice_le(write, value.bytes.as_slice())?, - TextVector(ref value) => self::Text::write_vec_of_i32_sized_texts(write, value)?, + TextVector(ref value) => self::Text::write_vec_of_i32_sized_texts_le(write, value)?, TileDescription(ref value) => value.write(write)?, - Custom { ref bytes, .. } => u8::write_slice(write, &bytes)?, // write.write(&bytes).map(|_| ()), - BlockType(kind) => kind.write(write)? + BlockType(kind) => kind.write(write)?, + + Bytes { ref type_hint, ref bytes } => { + type_hint.write_u32_sized_le(write)?; // no idea why this one is u32, everything else is usually i32... + u8::write_slice_le(write, bytes.as_slice())? + } + + Custom { ref bytes, .. } => u8::write_slice_le(write, &bytes)?, // write.write(&bytes).map(|_| ()), }; Ok(()) @@ -1773,15 +1819,17 @@ /// Read the value without validating. /// Returns `Ok(Ok(attribute))` for valid attributes. - /// Returns `Ok(Err(Error))` for invalid attributes from a valid byte source. + /// Returns `Ok(Err(Error))` for malformed attributes from a valid byte source. /// Returns `Err(Error)` for invalid byte sources, for example for invalid files. pub fn read(read: &mut PeekRead, kind: Text, byte_size: usize) -> Result> { use self::AttributeValue::*; use self::type_names as ty; - // always read bytes - let attribute_bytes = u8::read_vec(read, byte_size, 128, None, "attribute value size")?; - // TODO no allocation for small attributes // : SmallVec<[u8; 64]> = smallvec![0; byte_size]; + // always read bytes as to leave the read position at the end of the attribute + // even if the attribute contents fails to decode + let mut attribute_bytes = SmallVec::<[u8; 64]>::new(); + u8::read_into_vec_le(read, &mut attribute_bytes, byte_size, 64, None, "attribute value size")?; + // TODO: don't read into an array at all, just read directly from the reader and optionally seek afterwards? let parse_attribute = move || { let reader = &mut attribute_bytes.as_slice(); @@ -1790,41 +1838,41 @@ ty::I32BOX2 => IntegerBounds(self::IntegerBounds::read(reader)?), ty::F32BOX2 => FloatRect(self::FloatRect::read(reader)?), - ty::I32 => I32(i32::read(reader)?), - ty::F32 => F32(f32::read(reader)?), - ty::F64 => F64(f64::read(reader)?), + ty::I32 => I32(i32::read_le(reader)?), + ty::F32 => F32(f32::read_le(reader)?), + ty::F64 => F64(f64::read_le(reader)?), ty::RATIONAL => Rational({ - let a = i32::read(reader)?; - let b = u32::read(reader)?; + let a = i32::read_le(reader)?; + let b = u32::read_le(reader)?; (a, b) }), ty::TIME_CODE => TimeCode(self::TimeCode::read(reader)?), ty::I32VEC2 => IntVec2({ - let a = i32::read(reader)?; - let b = i32::read(reader)?; + let a = i32::read_le(reader)?; + let b = i32::read_le(reader)?; Vec2(a, b) }), ty::F32VEC2 => FloatVec2({ - let a = f32::read(reader)?; - let b = f32::read(reader)?; + let a = f32::read_le(reader)?; + let b = f32::read_le(reader)?; Vec2(a, b) }), ty::I32VEC3 => IntVec3({ - let a = i32::read(reader)?; - let b = i32::read(reader)?; - let c = i32::read(reader)?; + let a = i32::read_le(reader)?; + let b = i32::read_le(reader)?; + let c = i32::read_le(reader)?; (a, b, c) }), ty::F32VEC3 => FloatVec3({ - let a = f32::read(reader)?; - let b = f32::read(reader)?; - let c = f32::read(reader)?; + let a = f32::read_le(reader)?; + let b = f32::read_le(reader)?; + let c = f32::read_le(reader)?; (a, b, c) }), @@ -1838,13 +1886,13 @@ ty::F32MATRIX3X3 => Matrix3x3({ let mut result = [0.0_f32; 9]; - f32::read_slice(reader, &mut result)?; + f32::read_slice_le(reader, &mut result)?; result }), ty::F32MATRIX4X4 => Matrix4x4({ let mut result = [0.0_f32; 16]; - f32::read_slice(reader, &mut result)?; + f32::read_slice_le(reader, &mut result)?; result }), @@ -1852,14 +1900,21 @@ ty::TEXT => Text(self::Text::read_sized(reader, byte_size)?), // the number of strings can be inferred from the total attribute size - ty::TEXT_VECTOR => TextVector(self::Text::read_vec_of_i32_sized( + ty::TEXT_VECTOR => TextVector(self::Text::read_vec_of_i32_sized_texts_le( &mut PeekRead::new(attribute_bytes.as_slice()), byte_size )?), - ty::TILES => TileDescription(self::TileDescription::read(reader)?), + ty::TILES => TileDescription(self::TileDescription::read(reader)?), + + ty::BYTES => { + // for some reason, they went for unsigned sizes, in this place only + let type_hint = self::Text::read_u32_sized_le(reader, reader.len())?; + let bytes = SmallVec::from(*reader); + Bytes { type_hint, bytes } + } - _ => Custom { kind: kind.clone(), bytes: attribute_bytes.clone() } // TODO no clone + _ => Custom { kind: kind.clone(), bytes: SmallVec::from(*reader) } }) }; @@ -1972,7 +2027,8 @@ PREVIEW: b"preview", TEXT: b"string", TEXT_VECTOR: b"stringvector", - TILES: b"tiledesc" + TILES: b"tiledesc", + BYTES: b"bytes" } } @@ -2108,6 +2164,13 @@ }), ), ( + Text::from("custom byte sequence: prime numbers single byte"), + AttributeValue::Bytes{ + type_hint: Text::from("byte-primes"), + bytes: smallvec![2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73], + }, + ), + ( Text::from("leg count, again"), AttributeValue::ChannelList(ChannelList::new(smallvec![ ChannelDescription { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/header.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/header.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/header.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/header.rs 2006-07-24 01:21:28.000000000 +0000 @@ -515,7 +515,7 @@ )?; Ok(IntegerBounds { - position: Vec2(0, usize_to_i32(y)), + position: Vec2(0, usize_to_i32(y, "tile y")?), size: Vec2(self.layer_size.width(), height) }) } @@ -737,6 +737,159 @@ Ok(()) } + /// Iterate over all `(name, attribute_value)` pairs in this header that would be written to a file. + /// The order of attributes is arbitrary and may change in future versions. + /// Will always contain all strictly required attributes, such as channels, compression, data window, and similar. + /// Hint: Use `attribute.kind_name()` to obtain the standardized name of the attribute type. + /// Does not validate the header or attributes. + // This function is used for writing the attributes to files. + #[inline] + pub fn all_named_attributes(&self) -> impl '_ + Iterator { + use std::iter::{once, once_with, empty}; + use crate::meta::header::standard_names::*; + use AttributeValue::*; + + #[inline] fn optional<'t, T: Clone>( + name: &'t TextSlice, + to_attribute: impl Fn(T) -> AttributeValue, + value: &'t Option + ) + -> impl Iterator + { + value.as_ref().map(move |value| (name, to_attribute(value.clone()))).into_iter() + } + + #[inline] fn required<'s, T: Clone>(name: &'s TextSlice, to_attribute: impl Fn(T) -> AttributeValue, value: &'s T) + -> impl Iterator + { + once((name, to_attribute((*value).clone()))) + } + + // used to type-check local variables. only requried because you cannot do `let i: impl Iterator<> = ...` + #[inline] fn expect_is_iter<'s, T: Iterator>(val: T) -> T { val } + + macro_rules! iter_all { + ( $( $value:expr ),* ) => { + empty() $( .chain( $value ) )* + }; + } + + macro_rules! required_attributes { + ( $($name: ident : $variant: ident = $value: expr),* ) => { + expect_is_iter(iter_all!( + $( required($name, $variant, $value) ),* + )) + }; + } + + macro_rules! optional_attributes { + ( $($name: ident : $variant: ident = $value: expr),* ) => { + expect_is_iter(iter_all!( + $( optional($name, $variant, $value) ),* + )) + }; + } + + #[inline] fn usize_as_i32(value: usize) -> AttributeValue { + I32(i32::try_from(value).expect("usize exceeds i32 range")) + } + + + let block_type_and_tiles = expect_is_iter(once_with(move ||{ + let (block_type, tiles) = match self.blocks { + BlockDescription::ScanLines => (attribute::BlockType::ScanLine, None), + BlockDescription::Tiles(tiles) => (attribute::BlockType::Tile, Some(tiles)) + }; + + once((BLOCK_TYPE, BlockType(block_type))) + .chain(tiles.map(|tiles| (TILES, TileDescription(tiles)))) + }).flatten()); + + let data_window = expect_is_iter(once_with(move ||{ + (DATA_WINDOW, IntegerBounds(self.data_window())) + })); + + // dwa writes compression parameters as attribute. + let dwa_compr_level = expect_is_iter( + once_with(move ||{ + match self.compression { + attribute::Compression::DWAA(Some(level)) | + attribute::Compression::DWAB(Some(level)) => + Some((DWA_COMPRESSION_LEVEL, F32(level))), + + _ => None + } + }).flatten() + ); + + let opt_core_attrs = optional_attributes!( + DEEP_DATA_VERSION: I32 = &self.deep_data_version, + MAX_SAMPLES: usize_as_i32 = &self.max_samples_per_pixel + ).chain(block_type_and_tiles).chain(dwa_compr_level); + + let req_core_attrs = required_attributes!( + // chunks is not actually required, but always computed in this library anyways + CHUNKS: usize_as_i32 = &self.chunk_count, + + CHANNELS: ChannelList = &self.channels, + COMPRESSION: Compression = &self.compression, + LINE_ORDER: LineOrder = &self.line_order, + + DISPLAY_WINDOW: IntegerBounds = &self.shared_attributes.display_window, + PIXEL_ASPECT: F32 = &self.shared_attributes.pixel_aspect, + + WINDOW_CENTER: FloatVec2 = &self.own_attributes.screen_window_center, + WINDOW_WIDTH: F32 = &self.own_attributes.screen_window_width + ).chain(data_window); + + let opt_attr = optional_attributes!( + NAME: Text = &self.own_attributes.layer_name, + WHITE_LUMINANCE: F32 = &self.own_attributes.white_luminance, + ADOPTED_NEUTRAL: FloatVec2 = &self.own_attributes.adopted_neutral, + RENDERING_TRANSFORM: Text = &self.own_attributes.rendering_transform_name, + LOOK_MOD_TRANSFORM: Text = &self.own_attributes.look_modification_transform_name, + X_DENSITY: F32 = &self.own_attributes.horizontal_density, + OWNER: Text = &self.own_attributes.owner, + COMMENTS: Text = &self.own_attributes.comments, + CAPTURE_DATE: Text = &self.own_attributes.capture_date, + UTC_OFFSET: F32 = &self.own_attributes.utc_offset, + LONGITUDE: F32 = &self.own_attributes.longitude, + LATITUDE: F32 = &self.own_attributes.latitude, + ALTITUDE: F32 = &self.own_attributes.altitude, + FOCUS: F32 = &self.own_attributes.focus, + EXPOSURE_TIME: F32 = &self.own_attributes.exposure, + APERTURE: F32 = &self.own_attributes.aperture, + ISO_SPEED: F32 = &self.own_attributes.iso_speed, + ENVIRONMENT_MAP: EnvironmentMap = &self.own_attributes.environment_map, + KEY_CODE: KeyCode = &self.own_attributes.film_key_code, + TIME_CODE: TimeCode = &self.shared_attributes.time_code, + WRAP_MODES: Text = &self.own_attributes.wrap_mode_name, + FRAMES_PER_SECOND: Rational = &self.own_attributes.frames_per_second, + MULTI_VIEW: TextVector = &self.own_attributes.multi_view_names, + WORLD_TO_CAMERA: Matrix4x4 = &self.own_attributes.world_to_camera, + WORLD_TO_NDC: Matrix4x4 = &self.own_attributes.world_to_normalized_device, + DEEP_IMAGE_STATE: Rational = &self.own_attributes.deep_image_state, + ORIGINAL_DATA_WINDOW: IntegerBounds = &self.own_attributes.original_data_window, + CHROMATICITIES: Chromaticities = &self.shared_attributes.chromaticities, + PREVIEW: Preview = &self.own_attributes.preview, + VIEW: Text = &self.own_attributes.view_name, + NEAR: F32 = &self.own_attributes.near_clip_plane, + FAR: F32 = &self.own_attributes.far_clip_plane, + FOV_X: F32 = &self.own_attributes.horizontal_field_of_view, + FOV_Y: F32 = &self.own_attributes.vertical_field_of_view, + SOFTWARE: Text = &self.own_attributes.software_name + ); + + let other = self.own_attributes.other.iter() + .chain(self.shared_attributes.other.iter()) + .map(|(name, val)| (name.as_slice(), val.clone())); // TODO no clone + + req_core_attrs + .chain(opt_core_attrs) + .chain(opt_attr) + .chain(other) + } + /// Read the value without validating. pub fn read(read: &mut PeekRead, requirements: &Requirements, pedantic: bool) -> Result { let max_string_len = if requirements.has_long_names { 256 } else { 32 }; // TODO DRY this information @@ -752,7 +905,6 @@ let mut data_window = None; let mut display_window = None; let mut line_order = None; - let mut dwa_compression_level = None; let mut layer_attributes = LayerAttributes::default(); @@ -916,110 +1068,8 @@ /// Without validation, write this instance to the byte stream. pub fn write(&self, write: &mut impl Write) -> UnitResult { - - macro_rules! write_attributes { - ( $($name: ident : $variant: ident = $value: expr),* ) => { $( - attribute::write($name, & $variant ($value .clone()), write)?; // TODO without clone - )* }; - } - - macro_rules! write_optional_attributes { - ( $($name: ident : $variant: ident = $value: expr),* ) => { $( - if let Some(value) = $value { - attribute::write($name, & $variant (value.clone()), write)?; // TODO without clone - }; - )* }; - } - - use crate::meta::header::standard_names::*; - use AttributeValue::*; - - let (block_type, tiles) = match self.blocks { - BlockDescription::ScanLines => (attribute::BlockType::ScanLine, None), - BlockDescription::Tiles(tiles) => (attribute::BlockType::Tile, Some(tiles)) - }; - - fn usize_as_i32(value: usize) -> AttributeValue { - I32(i32::try_from(value).expect("u32 exceeds i32 range")) - } - - write_optional_attributes!( - TILES: TileDescription = &tiles, - DEEP_DATA_VERSION: I32 = &self.deep_data_version, - MAX_SAMPLES: usize_as_i32 = &self.max_samples_per_pixel - ); - - write_attributes!( - // chunks is not actually required, but always computed in this library anyways - CHUNKS: usize_as_i32 = &self.chunk_count, - - BLOCK_TYPE: BlockType = &block_type, - CHANNELS: ChannelList = &self.channels, - COMPRESSION: Compression = &self.compression, - LINE_ORDER: LineOrder = &self.line_order, - DATA_WINDOW: IntegerBounds = &self.data_window(), - - DISPLAY_WINDOW: IntegerBounds = &self.shared_attributes.display_window, - PIXEL_ASPECT: F32 = &self.shared_attributes.pixel_aspect, - - WINDOW_CENTER: FloatVec2 = &self.own_attributes.screen_window_center, - WINDOW_WIDTH: F32 = &self.own_attributes.screen_window_width - ); - - write_optional_attributes!( - NAME: Text = &self.own_attributes.layer_name, - WHITE_LUMINANCE: F32 = &self.own_attributes.white_luminance, - ADOPTED_NEUTRAL: FloatVec2 = &self.own_attributes.adopted_neutral, - RENDERING_TRANSFORM: Text = &self.own_attributes.rendering_transform_name, - LOOK_MOD_TRANSFORM: Text = &self.own_attributes.look_modification_transform_name, - X_DENSITY: F32 = &self.own_attributes.horizontal_density, - OWNER: Text = &self.own_attributes.owner, - COMMENTS: Text = &self.own_attributes.comments, - CAPTURE_DATE: Text = &self.own_attributes.capture_date, - UTC_OFFSET: F32 = &self.own_attributes.utc_offset, - LONGITUDE: F32 = &self.own_attributes.longitude, - LATITUDE: F32 = &self.own_attributes.latitude, - ALTITUDE: F32 = &self.own_attributes.altitude, - FOCUS: F32 = &self.own_attributes.focus, - EXPOSURE_TIME: F32 = &self.own_attributes.exposure, - APERTURE: F32 = &self.own_attributes.aperture, - ISO_SPEED: F32 = &self.own_attributes.iso_speed, - ENVIRONMENT_MAP: EnvironmentMap = &self.own_attributes.environment_map, - KEY_CODE: KeyCode = &self.own_attributes.film_key_code, - TIME_CODE: TimeCode = &self.shared_attributes.time_code, - WRAP_MODES: Text = &self.own_attributes.wrap_mode_name, - FRAMES_PER_SECOND: Rational = &self.own_attributes.frames_per_second, - MULTI_VIEW: TextVector = &self.own_attributes.multi_view_names, - WORLD_TO_CAMERA: Matrix4x4 = &self.own_attributes.world_to_camera, - WORLD_TO_NDC: Matrix4x4 = &self.own_attributes.world_to_normalized_device, - DEEP_IMAGE_STATE: Rational = &self.own_attributes.deep_image_state, - ORIGINAL_DATA_WINDOW: IntegerBounds = &self.own_attributes.original_data_window, - CHROMATICITIES: Chromaticities = &self.shared_attributes.chromaticities, - PREVIEW: Preview = &self.own_attributes.preview, - VIEW: Text = &self.own_attributes.view_name, - NEAR: F32 = &self.own_attributes.near_clip_plane, - FAR: F32 = &self.own_attributes.far_clip_plane, - FOV_X: F32 = &self.own_attributes.horizontal_field_of_view, - FOV_Y: F32 = &self.own_attributes.vertical_field_of_view, - SOFTWARE: Text = &self.own_attributes.software_name - ); - - // dwa writes compression parameters as attribute. - match self.compression { - attribute::Compression::DWAA(Some(level)) | - attribute::Compression::DWAB(Some(level)) => - attribute::write(DWA_COMPRESSION_LEVEL, &F32(level), write)?, - - _ => {} - }; - - - for (name, value) in &self.shared_attributes.other { - attribute::write(name.as_slice(), value, write)?; - } - - for (name, value) in &self.own_attributes.other { - attribute::write(name.as_slice(), value, write)?; + for (name, value) in self.all_named_attributes() { + attribute::write(name, &value, write)?; } sequence_end::write(write)?; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/src/meta/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/src/meta/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -163,14 +163,14 @@ /// Without validation, write this instance to the byte stream. pub fn write(write: &mut impl Write) -> Result<()> { - u8::write_slice(write, &self::BYTES) + u8::write_slice_ne(write, &self::BYTES) } /// Consumes four bytes from the reader and returns whether the file may be an exr file. // TODO check if exr before allocating BufRead pub fn is_exr(read: &mut impl Read) -> Result { let mut magic_num = [0; 4]; - u8::read_slice(read, &mut magic_num)?; + u8::read_slice_ne(read, &mut magic_num)?; Ok(magic_num == self::BYTES) } @@ -196,7 +196,7 @@ /// Without validation, write this instance to the byte stream. pub fn write(write: &mut W) -> UnitResult { - 0_u8.write(write) + 0_u8.write_le(write) } /// Peeks the next byte. If it is zero, consumes the byte and returns true. @@ -420,7 +420,7 @@ /// Read one offset table from the reader for each header. pub fn read_offset_tables(read: &mut PeekRead, headers: &Headers) -> Result { headers.iter() - .map(|header| u64::read_vec(read, header.chunk_count, u16::MAX as usize, None, "offset table size")) + .map(|header| u64::read_vec_le(read, header.chunk_count, u16::MAX as usize, None, "offset table size")) .collect() } @@ -559,7 +559,7 @@ pub fn read(read: &mut R) -> Result { use ::bit_field::BitField; - let version_and_flags = u32::read(read)?; + let version_and_flags = u32::read_le(read)?; // take the 8 least significant bits, they contain the file format version number let version = (version_and_flags & 0x000F) as u8; @@ -603,7 +603,7 @@ version_and_flags.set_bit(12, self.has_multiple_layers); // all remaining bits except 9, 10, 11 and 12 are reserved and should be 0 - version_and_flags.write(write)?; + version_and_flags.write_le(write)?; Ok(()) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/tests/across_compression.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/across_compression.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/tests/across_compression.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/across_compression.rs 2006-07-24 01:21:28.000000000 +0000 @@ -173,13 +173,11 @@ #[test] -#[cfg(target_endian = "little")] // TODO make it work on big endian fn compare_compression_contents_pxr24_f16() { expect_eq_other("f16", "pxr24.exr", "decompressed_pxr24.exr"); } #[test] -#[cfg(target_endian = "little")] // TODO make it work on big endian fn compare_compression_contents_pxr24_f32() { expect_eq_other("f32", "pxr24.exr", "decompressed_pxr24.exr"); } @@ -225,7 +223,6 @@ } #[test] -#[cfg(target_endian = "little")] // TODO make it work on big endian fn compare_png_to_pxr24_f16() { expect_eq_png("f16_pxr24.exr"); } @@ -257,7 +254,6 @@ } #[test] -#[cfg(target_endian = "little")] // TODO make it work on big endian fn compare_png_to_pxr24_f32() { expect_eq_png("f32_pxr24.exr"); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/exr/tests/roundtrip.rs clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/roundtrip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/exr/tests/roundtrip.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/exr/tests/roundtrip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -289,20 +289,6 @@ } #[test] -#[cfg(target_endian = "big")] // TODO big endian pxr24 -fn pxr24_expect_error_on_big_endian(){ - let image = exr::prelude::read_all_data_from_file( - "tests/images/valid/custom/compression_methods/f16/pxr24.exr" - ); - - match image { - Err(Error::NotSupported(_)) => {} - _ => panic!("pxr24 should report an error on big endian architecture") - } -} - -#[test] -#[cfg(target_endian = "little")] // TODO big endian pxr24 fn roundtrip_pxr24() { test_mixed_roundtrip_with_compression(Compression::PXR24) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fastrand/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/fastrand/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"6ca6847ad25257cf48bbc6d0494d2f90da8108ddb4c08e897a944a70e7dfacce","Cargo.toml":"42d7ae0a6dd7fe0530c9b9d4e35a6a5737c5c201cb213b842ffbfc00c3c9fac3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0edb1fd8febaf826eb3a8a769d0a64ac6a53684363dc1a7741f1145e4672ef41","benches/bench.rs":"8e3cb6b96bb656731e88b4f70d942fe58eb43fa51d9b6374899c54c06dce244f","src/global_rng.rs":"f053fae35faf49f3f9971587522bab14deab986bb491ed45598aff195ae5a077","src/lib.rs":"241e9c5bdb1b280059d6547a2c7b0b057585c91ba3aabe1429c492869b9c437d","tests/char.rs":"a530b41837f5bf43701d983ef0267d9b44779d455f24cbf30b881cd348de9ee1","tests/smoke.rs":"8eac48144705364d142882538be43b8d69018959579404c3b1e638827888e62e"},"package":"9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"38eecda5b9170526800bd8aeb633ca0b6a4a91059385d66d554f3100e9795076","CHANGELOG.md":"6ca6847ad25257cf48bbc6d0494d2f90da8108ddb4c08e897a944a70e7dfacce","Cargo.toml":"42d7ae0a6dd7fe0530c9b9d4e35a6a5737c5c201cb213b842ffbfc00c3c9fac3","Cargo.toml.orig":"6b1ce5ec3cae8aec5feff84bfe6901a50788b278a578cf7ae211a1f4f04605af","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0edb1fd8febaf826eb3a8a769d0a64ac6a53684363dc1a7741f1145e4672ef41","benches/bench.rs":"8e3cb6b96bb656731e88b4f70d942fe58eb43fa51d9b6374899c54c06dce244f","src/global_rng.rs":"f053fae35faf49f3f9971587522bab14deab986bb491ed45598aff195ae5a077","src/lib.rs":"241e9c5bdb1b280059d6547a2c7b0b057585c91ba3aabe1429c492869b9c437d","tests/char.rs":"a530b41837f5bf43701d983ef0267d9b44779d455f24cbf30b881cd348de9ee1","tests/smoke.rs":"8eac48144705364d142882538be43b8d69018959579404c3b1e638827888e62e"},"package":"9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fastrand/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/fastrand/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fastrand/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7e60c7f688f9be3dcd4f59f216c87dac88ca2902" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fastrand/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/fastrand/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/fastrand/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fastrand/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +[package] +name = "fastrand" +# When publishing a new version: +# - Update CHANGELOG.md +# - Create "v2.x.y" git tag +version = "2.1.0" +authors = ["Stjepan Glavina "] +edition = "2018" +rust-version = "1.36" +description = "A simple and fast random number generator" +license = "Apache-2.0 OR MIT" +repository = "https://github.com/smol-rs/fastrand" +keywords = ["simple", "fast", "rand", "random", "wyrand"] +categories = ["algorithms"] +exclude = ["/.*"] + +[features] +default = ["std"] +alloc = [] +std = ["alloc"] +js = ["std", "getrandom"] + +[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies] +getrandom = { version = "0.2", features = ["js"], optional = true } + +[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dev-dependencies] +wasm-bindgen-test = "0.3" +getrandom = { version = "0.2", features = ["js"] } + +[dev-dependencies] +rand = "0.8" +wyhash = "0.5" +getrandom = "0.2" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/fax/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"8b1ec00499c92edd76afe1a00b06dccfe5d728a0a682c04321a758e8e4d28b36","Cargo.lock":"308c21fd095a4967a8dca0fc273c6328b11efa889f092306f5e824845bf15e4c","Cargo.toml":"0ea204979bda3a271442d39e327b479e65d5998bf9525c3272d5ce60a53a621d","Cargo.toml.orig":"e8f20f4f701f02b565ffa289e1007008d07f933fb4f64f1a3879f8438a4a8406","README.md":"c79f0c2a08d8b13daaaf45be481e80b12d1818c3feb91ba89e8967fe9e3a2d84","examples/bitdiff.rs":"f74f4611437404e60a5decc5d3a4579de9e4ccfb4f6b1702c1f8c6814be0311b","examples/check.rs":"7eedd29a3a6ed462d4c8fe4d761197795cd6b099ead523bf559c705304ba9e5e","examples/fax2pbm.rs":"d9d7bb9a2bdfc4bdb013970dde7d5cf8d9991cf76e0182a60550b14d1bb90d7d","examples/fax2tiff.rs":"9cf41806cfcdf33d3737d5ed2a65dfbddef250c62974880b5c23641cbc8c6a3d","examples/pbm2fax.rs":"7476485cbd695924454150c829151c0175ea311cb11dddf2131018bc59bd15f3","examples/validate.rs":"c9aea130ea5fefc03fa02aabffedec848d1211c6ef313dbf432192f80f0f2258","src/decoder.rs":"65d240af7c7846b16647fa98a6c2fc03aff81d860525d7ea308a16a2cde3ba51","src/encoder.rs":"27fdfc929edb4c3343892efdc4d1322cb0db783076249d792b9e62e9728ea582","src/lib.rs":"6577456342c26b8b3e7472d1faccc58aabbaa22c2092ca77894bb88caec36ecb","src/maps.rs":"b35f21caa2632702b5c972c71bd4ce7707ca15d65ca04ec95777e57a78421402","src/tiff.rs":"fcf8628c35157133a87c7b30a7a06c6df34d872cb4daa1e639630804fadeffdc","tests/check.rs":"dab77c1a0d46d6c2ce6c4c31deb2d3e42190b659e3db1d8d91d5052388ecd698"},"package":"f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/fax/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "40b226eb97b391355e971fd95a8dd532a4c127a0" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "fax" +version = "0.2.6" +dependencies = [ + "fax_derive", + "tiff", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,77 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "fax" +version = "0.2.6" +authors = ["Sebastian K "] +build = false +exclude = [ + "T-REC-T.6-198811-I!!PDF-E.pdf", + ".vscode/*", + ".gitignore", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Decoder and Encoder for CCITT Group 3 and 4 bi-level image encodings used by fax machines TIFF and PDF." +readme = "README.md" +keywords = [ + "CCITT", + "fax", + "CCITTFaxDecode", +] +license = "MIT" +repository = "https://github.com/pdf-rs/fax" + +[features] +debug = [] + +[lib] +name = "fax" +path = "src/lib.rs" + +[[example]] +name = "bitdiff" +path = "examples/bitdiff.rs" + +[[example]] +name = "check" +path = "examples/check.rs" + +[[example]] +name = "fax2pbm" +path = "examples/fax2pbm.rs" + +[[example]] +name = "fax2tiff" +path = "examples/fax2tiff.rs" + +[[example]] +name = "pbm2fax" +path = "examples/pbm2fax.rs" + +[[example]] +name = "validate" +path = "examples/validate.rs" + +[[test]] +name = "check" +path = "tests/check.rs" + +[dependencies.fax_derive] +version = "0.2.0" + +[dev-dependencies.tiff] +version = "0.9" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/fax/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "fax" +version = "0.2.6" +authors = ["Sebastian K "] +edition = "2018" +description = "Decoder and Encoder for CCITT Group 3 and 4 bi-level image encodings used by fax machines TIFF and PDF." +license = "MIT" +keywords = ["CCITT", "fax", "CCITTFaxDecode"] +repository = "https://github.com/pdf-rs/fax" +exclude = ["T-REC-T.6-198811-I!!PDF-E.pdf", ".vscode/*", ".gitignore"] + +[features] +debug = [] + +[dependencies] +fax_derive = { version = "0.2.0", path = "derive" } + +[dev-dependencies] +tiff = { version = "0.9" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/README.md clamav-1.4.6+dfsg/.cargo/vendor/fax/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/fax/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +# CCITT Group 3 and 4 image encodings. + +Currently supported: +- de- and encoding group 4 images +- decoding group 3 images + + +You can ask questions on [Zulip](https://type.zulipchat.com/#narrow/stream/209232-pdf/topic/fax.20.2F.20master) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/bitdiff.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/bitdiff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/bitdiff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/bitdiff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +use std::fs; + +fn main() { + let mut args = std::env::args().skip(1); + let a = fs::read(&args.next().unwrap()).unwrap(); + let b = fs::read(&args.next().unwrap()).unwrap(); + + for (i, (&a, &b)) in a.iter().zip(b.iter()).enumerate() { + if a != b { + println!("mismatch at byte {}: {:08b} vs. {:08b}", i, a, b); + break; + } + } + if a.len() > b.len() { + println!("a has additional {:?}", &a[b.len()..]); + } + if b.len() > a.len() { + println!("b has additional {:?}", &b[a.len()..]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/check.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/check.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/check.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/check.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +#![feature(slice_split_once)] + +use fax::{VecWriter, decoder, decoder::pels, BitWriter, Bits, Color}; +use std::io::Write; +use std::fs::{self, File}; + +fn main() { + let mut args = std::env::args().skip(1); + let input: String = args.next().unwrap(); + let reference = args.next().unwrap(); + + let ref_data = std::fs::read(&reference).unwrap(); + let (header1, data) = ref_data.split_once(|&b| b == b'\n').unwrap(); + assert_eq!(header1, b"P4"); + let (header2, ref_image) = data.split_once(|&b| b == b'\n').unwrap(); + let header2 = std::str::from_utf8(header2).unwrap(); + dbg!(header2); + let (w, h) = header2.split_once(" ").unwrap(); + let width: u16 = w.parse().unwrap(); + let h: u16 = h.parse().unwrap(); + + let mut ref_lines = ref_image.chunks_exact((width as usize + 7) / 8); + + let data; + let inverted; + if input.ends_with(".tiff") { + use tiff::{decoder::Decoder, tags::Tag}; + let tiff = std::fs::read(&input).unwrap(); + let reader = std::io::Cursor::new(tiff.as_slice()); + let mut decoder = Decoder::new(reader).unwrap(); + let (w, h) = decoder.chunk_dimensions(); + let mut buf = vec![0; w as usize * h as usize]; + let strip_offset = decoder.get_tag(Tag::StripOffsets).unwrap().into_u32().unwrap() as usize; + let strip_bytes = decoder.get_tag(Tag::StripByteCounts).unwrap().into_u32().unwrap() as usize; + + let interpr = decoder.get_tag(Tag::PhotometricInterpretation).unwrap().into_u16().unwrap(); + + data = tiff[strip_offset .. strip_offset + strip_bytes].to_vec(); + inverted = interpr != 0; + } else { + data = fs::read(&input).unwrap(); + inverted = false; + } + let mut height = 0; + let (black, white) = match inverted { + false => (Bits { data: 1, len: 1 }, Bits { data: 0, len: 1 }), + true => (Bits { data: 0, len: 1 }, Bits { data: 1, len: 1 }) + }; + decoder::decode_g4(data.iter().cloned(), width, None, |transitions| { + let mut writer = VecWriter::new(); + for c in pels(transitions, width) { + let bit = match c { + Color::Black => black, + Color::White => white, + }; + writer.write(bit); + } + writer.pad(); + let data = writer.finish(); + let ref_line = ref_lines.next().unwrap(); + println!("{height:3} dec: {}", Line(&data)); + if ref_line != data { + println!(" ref: {}", Line(ref_line)); + 'a: for (byte, (&r, &v)) in ref_line.iter().zip(data.iter()).enumerate() { + if r != v { + for i in (0 .. 8).rev() { + if r & (1 << i) != v & (1 << i) { + println!("mismatch at pos {}", (8 * byte) + 7-i); + break 'a; + } + } + } + } + panic!("decode error"); + } + height += 1; + }); +} + +struct Line<'a>(&'a [u8]); +impl<'a> std::fmt::Display for Line<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let codes = [' ', '▐', '▌', '█']; + for b in self.0.iter().flat_map(|b| [b >> 6, (b >> 4) & 3, (b >>2) & 3, b & 3]) { + write!(f, "{}", codes[b as usize])?; + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/fax2pbm.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2pbm.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/fax2pbm.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2pbm.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +use fax::{VecWriter, decoder, decoder::pels, BitWriter, Bits, Color}; +use std::io::Write; +use std::fs::{self, File}; + +fn main() { + let mut args = std::env::args().skip(1); + let input: String = args.next().unwrap(); + let width: u16 = args.next().unwrap().parse().unwrap(); + let output = args.next().unwrap(); + + let data = fs::read(&input).unwrap(); + let mut writer = VecWriter::new(); + let mut height = 0; + decoder::decode_g4(data.iter().cloned(), width, None, |transitions| { + for c in pels(transitions, width) { + let bit = match c { + Color::Black => Bits { data: 1, len: 1 }, + Color::White => Bits { data: 0, len: 1 } + }; + writer.write(bit); + } + writer.pad(); + height += 1; + }); + let data = writer.finish(); + assert_eq!(data.len(), height as usize * ((width as usize + 7) / 8)); + + let header = format!("P4\n{} {}\n", width, height); + let mut out = File::create(&output).unwrap(); + out.write_all(header.as_bytes()).unwrap(); + out.write_all(&data).unwrap(); +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/fax2tiff.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2tiff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/fax2tiff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/fax2tiff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +use fax::tiff::wrap; +use fax::{VecWriter, decoder, decoder::pels, BitWriter, Bits, Color}; +use std::io::Write; +use std::fs::{self, File}; + +fn main() { + let mut args = std::env::args().skip(1); + let input: String = args.next().unwrap(); + let width: u16 = args.next().unwrap().parse().unwrap(); + let output = args.next().unwrap(); + + let data = fs::read(&input).unwrap(); + let mut height = 0; + decoder::decode_g4(data.iter().cloned(), width, None, |transitions| { + height += 1; + }); + + std::fs::write(output, wrap(&data, width as _, height)).unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/pbm2fax.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/pbm2fax.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/pbm2fax.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/pbm2fax.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +use fax::{encoder::Encoder, slice_bits, tiff, ByteReader, Color, VecWriter}; +use std::fs; + +fn main() { + let mut args = std::env::args().skip(1); + let input: String = args.next().unwrap(); + let output = args.next().unwrap(); + + let data = fs::read(&input).unwrap(); + let mut parts = data.splitn(3, |&b| b == b'\n'); + assert_eq!(parts.next().unwrap(), b"P4"); + let mut size = parts.next().unwrap().splitn(2, |&b| b == b' '); + let width: u32 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); + let height: u32 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); + + let writer = VecWriter::new(); + let mut encoder = Encoder::new(writer); + + for line in parts.next().unwrap().chunks((width as usize + 7) / 8).take(height as _) { + let line = slice_bits(line).take(width as usize) + .map(|b| match b { + false => Color::White, + true => Color::Black + }); + encoder.encode_line(line, width as u16).unwrap(); + } + let data = encoder.finish().unwrap().finish(); + + fs::write(&output, &tiff::wrap(&data, width, height)).unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/validate.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/validate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/examples/validate.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/examples/validate.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +use fax::{encoder::Encoder, slice_bits, slice_reader, BitReader, BitWriter, Bits, ByteReader, Color}; +use std::{convert::Infallible, fs}; + +fn main() { + let mut args = std::env::args().skip(1); + let input: String = args.next().unwrap(); + let output = args.next().unwrap(); + + let data = fs::read(&input).unwrap(); + let reference_data = fs::read(&output).unwrap(); + let mut parts = data.splitn(3, |&b| b == b'\n'); + assert_eq!(parts.next().unwrap(), b"P4"); + let mut size = parts.next().unwrap().splitn(2, |&b| b == b' '); + let width: u16 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); + let height: u16 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); + + //let writer = VecWriter::new(); + let writer = Validator { reader: slice_reader(&reference_data) }; + let mut encoder = Encoder::new(writer); + + for (y, line) in parts.next().unwrap().chunks((width as usize + 7) / 8).enumerate().take(height as _) { + println!("\nline {}", y); + let line = slice_bits(line).take(width as usize) + .map(|b| match b { + false => Color::Black, + true => Color::White + }); + encoder.encode_line(line, width).unwrap(); + } + let mut writer = encoder.finish().unwrap(); + writer.reader.print_remaining(); + + + //let (data, _) = encoder.into_writer().finish(); + //fs::write(&output, &data).unwrap(); +} + +struct Validator { + reader: ByteReader +} +impl BitWriter for Validator +where ByteReader: BitReader +{ + type Error = (); + fn write(&mut self, bits: Bits) -> Result<(), ()> { + let expected = Bits { data: self.reader.peek(bits.len).unwrap(), len: bits.len }; + if expected != bits { + println!("{} != {}", expected, bits); + return Err(()); + } + self.reader.consume(bits.len); + Ok(()) + } +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/src/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,265 @@ +use std::convert::Infallible; +use std::io::{self, Bytes, Read}; + +use crate::{BitReader, ByteReader, Color, Transitions}; +use crate::maps::{Mode, black, white, mode, EDFB_HALF, EOL}; + + +fn with_markup(decoder: D, reader: &mut R) -> Option + where D: Fn(&mut R) -> Option +{ + let mut sum = 0; + while let Some(n) = decoder(reader) { + //print!("{} ", n); + sum += n; + if n < 64 { + //debug!("= {}", sum); + return Some(sum) + } + } + None +} + +fn colored(current: Color, reader: &mut impl BitReader) -> Option { + //debug!("{:?}", current); + match current { + Color::Black => with_markup(black::decode, reader), + Color::White => with_markup(white::decode, reader), + } +} + +/// Turn a list of color changing position into an iterator of pixel colors +/// +/// The width of the line/image has to be given in `width`. +/// The iterator will produce exactly that many items. +pub fn pels(line: &[u16], width: u16) -> impl Iterator + '_ { + use std::iter::repeat; + let mut color = Color::White; + let mut last = 0; + let pad_color = if line.len() & 1 == 1 { + !color + } else { + color + }; + line.iter().flat_map(move |&p| { + let c = color; + color = !color; + let n = p.saturating_sub(last); + last = p; + repeat(c).take(n as usize) + }).chain(repeat(pad_color)).take(width as usize) +} + +/// Decode a Group 3 encoded image. +/// +/// The callback `line_cb` is called for each decoded line. +/// The argument is the list of positions of color change, starting with white. +/// +/// To obtain an iterator over the pixel colors, the `pels` function is provided. +pub fn decode_g3(input: impl Iterator, mut line_cb: impl FnMut(&[u16])) -> Option<()> { + let reader = input.map(Result::::Ok); + let mut decoder = Group3Decoder::new(reader).ok()?; + + while let Ok(status) = decoder.advance() { + if status == DecodeStatus::End { + return Some(()); + } + line_cb(decoder.transitions()); + } + None +} + +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub enum DecodeStatus { + Incomplete, + End, +} + +pub struct Group3Decoder { + reader: ByteReader, + current: Vec +} +impl>> Group3Decoder { + pub fn new(reader: R) -> Result> { + let mut reader = ByteReader::new(reader).map_err(DecodeError::Reader)?; + reader.expect(EOL).map_err(|_| DecodeError::Invalid)?; + + Ok(Group3Decoder { reader, current: vec![] }) + } + pub fn advance(&mut self) -> Result> { + self.current.clear(); + let mut a0 = 0; + let mut color = Color::White; + while let Some(p) = colored(color, &mut self.reader) { + a0 += p; + self.current.push(a0); + color = !color; + } + self.reader.expect(EOL).map_err(|_| DecodeError::Invalid)?; + + for _ in 0 .. 6 { + if self.reader.peek(EOL.len) == Some(EOL.data) { + self.reader.consume(EOL.len).map_err(DecodeError::Reader)?; + } else { + return Ok(DecodeStatus::Incomplete) + } + } + + Ok(DecodeStatus::End) + } + pub fn transitions(&self) -> &[u16] { + &self.current + } +} + +/// Decode a Group 4 Image +/// +/// - `width` is the width of the image. +/// - The callback `line_cb` is called for each decoded line. +/// The argument is the list of positions of color change, starting with white. +/// +/// If `height` is specified, at most that many lines will be decoded, +/// otherwise data is decoded until the end-of-block marker (or end of data). +/// +/// To obtain an iterator over the pixel colors, the `pels` function is provided. +pub fn decode_g4(input: impl Iterator, width: u16, height: Option, mut line_cb: impl FnMut(&[u16])) -> Option<()> { + let reader = input.map(Result::::Ok); + let mut decoder = Group4Decoder::new(reader, width).ok()?; + + for y in 0 .. height.unwrap_or(u16::MAX) { + let status = decoder.advance().ok()?; + if status == DecodeStatus::End { + return Some(()); + } + line_cb(decoder.transition()); + } + Some(()) +} + +#[derive(Debug)] +pub enum DecodeError { + Reader(E), + Invalid, + Unsupported, +} +impl std::fmt::Display for DecodeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Decode Error") + } +} +impl std::error::Error for DecodeError { +} + +pub struct Group4Decoder { + reader: ByteReader, + reference: Vec, + current: Vec, + width: u16 +} +impl>> Group4Decoder { + pub fn new(reader: R, width: u16) -> Result { + Ok(Group4Decoder { + reader: ByteReader::new(reader)?, + reference: Vec::new(), + current: Vec::new(), + width + }) + } + // when Complete::Complete is returned, there is no useful data in .transitions() or .line() + pub fn advance(&mut self) -> Result> { + let mut transitions = Transitions::new(&self.reference); + let mut a0 = 0; + let mut color = Color::White; + let mut start_of_row = true; + //debug!("\n\nline {}", y); + + loop { + //reader.print_peek(); + let mode = match mode::decode(&mut self.reader) { + Some(mode) => mode, + None => return Err(DecodeError::Invalid), + }; + //debug!(" {:?}, color={:?}, a0={}", mode, color, a0); + + match mode { + Mode::Pass => { + if start_of_row && color == Color::White { + transitions.pos += 1; + } else { + transitions.next_color(a0, !color, false).ok_or(DecodeError::Invalid)?; + } + //debug!("b1={}", b1); + if let Some(b2) = transitions.next() { + //debug!("b2={}", b2); + a0 = b2; + } + } + Mode::Vertical(delta) => { + let b1 = transitions.next_color(a0, !color, start_of_row).unwrap_or(self.width); + let a1 = (b1 as i16 + delta as i16) as u16; + if a1 >= self.width { + break; + } + //debug!("transition to {:?} at {}", !color, a1); + self.current.push(a1); + color = !color; + a0 = a1; + if delta < 0 { + transitions.seek_back(a0); + } + } + Mode::Horizontal => { + let a0a1 = colored(color, &mut self.reader).ok_or(DecodeError::Invalid)?; + let a1a2 = colored(!color, &mut self.reader).ok_or(DecodeError::Invalid)?; + let a1 = a0 + a0a1; + let a2 = a1 + a1a2; + //debug!("a0a1={}, a1a2={}, a1={}, a2={}", a0a1, a1a2, a1, a2); + + self.current.push(a1); + if a2 >= self.width { + break; + } + self.current.push(a2); + a0 = a2; + } + Mode::Extension => { + let xxx = self.reader.peek(3).ok_or(DecodeError::Invalid)?; + // debug!("extension: {:03b}", xxx); + self.reader.consume(3); + // debug!("{:?}", current); + return Err(DecodeError::Unsupported); + } + Mode::EOF => return Ok(DecodeStatus::End), + } + start_of_row = false; + + if a0 >= self.width { + break; + } + } + //debug!("{:?}", current); + + std::mem::swap(&mut self.reference, &mut self.current); + self.current.clear(); + + Ok(DecodeStatus::Incomplete) + } + + pub fn transition(&self) -> &[u16] { + &self.reference + } + + pub fn line(&self) -> Line { + Line { transitions: &self.reference, width: self.width } + } +} + +pub struct Line<'a> { + pub transitions: &'a [u16], + pub width: u16 +} +impl<'a> Line<'a> { + pub fn pels(&self) -> impl Iterator + 'a { + pels(&self.transitions, self.width) + } +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/src/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/src/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/src/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/src/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,134 @@ +use crate::{Color, BitWriter, Transitions, maps::{Mode, mode, black, white, EDFB_HALF}}; + +fn absdiff(a: u16, b: u16) -> u16 { + if a > b { + a - b + } else { + b - a + } +} + +pub struct Encoder { + writer: W, + reference: Vec, + current: Vec, +} +fn encode_color(writer: &mut W, color: Color, mut n: u16) -> Result<(), W::Error> { + let table = match color { + Color::White => &white::ENTRIES, + Color::Black => &black::ENTRIES, + }; + let mut write = |n: u16| { + let idx = if n >= 64 { 63 + n / 64 } else { n } as usize; + let (v, bits) = table[idx]; + assert_eq!(v, n); + //debug!("{}", n); + writer.write(bits) + }; + + while n >= 2560 { + write(2560)?; + n -= 2560; + } + if n >= 64 { + let d = n & !63; + write(d)?; + n -= d; + } + + write(n) +} +impl Encoder { + pub fn new(writer: W) -> Self { + Encoder { + writer, + reference: vec![], + current: vec![], + } + } + pub fn encode_line(&mut self, pels: impl Iterator, width: u16) -> Result<(), W::Error> { + let mut color = Color::White; + let mut transitions = Transitions::new(&self.reference); + let mut a0 = 0; + let mut start_of_line = true; + let mut pels = pels.enumerate() + .scan(Color::White, |state, (i, c)| { + Some(if c != *state { + debug!(" {i} {c:?}"); + *state = c; + Some(i as u16) + } else { + None + }) + }).filter_map(|x| x); + let writer = &mut self.writer; + self.current.clear(); + + while a0 < width { + let a1; + if let Some(a1_) = pels.next() { + self.current.push(a1_); + a1 = a1_; + } else { + a1 = width; + } + loop { + transitions.seek_back(a0); + let b1 = transitions.next_color(a0, !color, start_of_line).unwrap_or(width); + let b2 = transitions.peek(); + start_of_line = false; + debug!(" a0={a0}, a1={a1}, b1={:?}, b2={:?}", b1, b2); + match (b1, b2) { + (_b1, Some(b2)) if b2 < a1 => { + debug!(" Pass"); + let bits = mode::encode(Mode::Pass).unwrap(); + writer.write(bits)?; + transitions.skip(1); + a0 = b2; + continue; + } + (b1, _) if absdiff(a1, b1) <= 3 => { + let delta = a1 as i16 - b1 as i16; + debug!(" Vertical({})", delta); + let bits = mode::encode(Mode::Vertical(delta as i8)).unwrap(); + writer.write(bits)?; + a0 = a1; + color = !color; + } + _ => { + let a2 = match pels.next() { + Some(a2) => { + self.current.push(a2); + a2 + }, + None => width + }; + let a0a1 = a1 - a0; + let a1a2 = a2 - a1; + debug!(" Horizontal({}, {}) color={color:?}", a0a1, a1a2); + let bits = mode::encode(Mode::Horizontal).unwrap(); + writer.write(bits)?; + let c = if a0 + a1 == 0 { + Color::White + } else { + color + }; + encode_color(writer, c, a0a1)?; + encode_color(writer, !c, a1a2)?; + a0 = a2; + } + } + break; + } + } + + std::mem::swap(&mut self.reference, &mut self.current); + debug!("next line"); + Ok(()) + } + pub fn finish(mut self) -> Result { + self.writer.write(EDFB_HALF)?; + self.writer.write(EDFB_HALF)?; + Ok(self.writer) + } +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,294 @@ +use std::convert::Infallible; +use std::io::{self, Read}; +use std::iter::Map; +use std::ops::Not; +use std::fmt; + +#[cfg(feature="debug")] +macro_rules! debug { + ($($arg:expr),*) => ( + println!($($arg),*) + ) +} +#[cfg(not(feature="debug"))] +macro_rules! debug { + ($($arg:expr),*) => ( + () + ) +} + +pub mod maps; + +/// Decoder module +pub mod decoder; + +/// Encoder module +pub mod encoder; + +/// TIFF helper functions +pub mod tiff; + +/// Trait used to read data bitwise. +/// +/// For lazy people `ByteReader` is provided which implements this trait. +pub trait BitReader { + type Error; + + /// look at the next (up to 16) bits of data + /// + /// Data is returned in the lower bits of the `u16`. + fn peek(&self, bits: u8) -> Option; + + /// Consume the given amount of bits from the input. + fn consume(&mut self, bits: u8) -> Result<(), Self::Error>; + + /// Assert that the next bits matches the given pattern. + /// + /// If it does not match, the found pattern is returned if enough bits are aviable. + /// Otherwise None is returned. + fn expect(&mut self, bits: Bits) -> Result<(), Option> { + match self.peek(bits.len) { + None => Err(None), + Some(val) if val == bits.data => Ok(()), + Some(val) => Err(Some(Bits { data: val, len: bits.len })) + } + } + + fn bits_to_byte_boundary(&self) -> u8; +} + +/// Trait to write data bitwise +/// +/// The `VecWriter` struct is provided for convinience. +pub trait BitWriter { + type Error; + fn write(&mut self, bits: Bits) -> Result<(), Self::Error>; +} +pub struct VecWriter { + data: Vec, + partial: u32, + len: u8 +} +impl BitWriter for VecWriter { + type Error = Infallible; + fn write(&mut self, bits: Bits) -> Result<(), Self::Error> { + self.partial |= (bits.data as u32) << (32 - self.len - bits.len); + self.len += bits.len; + while self.len >= 8 { + self.data.push((self.partial >> 24) as u8); + self.partial <<= 8; + self.len -= 8; + } + Ok(()) + } +} +impl VecWriter { + pub fn new() -> Self { + VecWriter { + data: Vec::new(), + partial: 0, + len: 0 + } + } + // with capacity of `n` bits. + pub fn with_capacity(n: usize) -> Self { + VecWriter { + data: Vec::with_capacity((n + 7) / 8), + partial: 0, + len: 0 + } + } + + /// Pad the output with `0` bits until it is at a byte boundary. + pub fn pad(&mut self) { + if self.len > 0 { + self.data.push((self.partial >> 24) as u8); + self.partial = 0; + self.len = 0; + } + } + + /// pad and return the accumulated bytes + pub fn finish(mut self) -> Vec { + self.pad(); + self.data + } +} + +pub struct ByteReader { + read: R, + partial: u32, + valid: u8, +} +impl>> ByteReader { + /// Construct a new `ByteReader` from an iterator of `u8` + pub fn new(read: R) -> Result { + let mut bits = ByteReader { + read, + partial: 0, + valid: 0 + }; + bits.fill()?; + Ok(bits) + } + fn fill(&mut self) -> Result<(), E> { + while self.valid < 16 { + match self.read.next() { + Some(Ok(byte)) => { + self.partial = self.partial << 8 | byte as u32; + self.valid += 8; + } + Some(Err(e)) => return Err(e), + None => break + } + } + Ok(()) + } + /// Print the remaining data + /// + /// Note: For debug purposes only, not part of the API. + pub fn print_remaining(&mut self) { + println!("partial: {:0w$b}, valid: {}", self.partial & ((1 << self.valid) - 1), self.valid, w=self.valid as usize); + while let Some(Ok(b)) = self.read.next() { + print!("{:08b} ", b); + } + println!(); + } + pub fn print_peek(&self) { + println!("partial: {:0w$b}, valid: {}", self.partial & ((1 << self.valid) - 1), self.valid, w=self.valid as usize); + } +} + +pub fn slice_reader(slice: &[u8]) -> ByteReader> + '_> { + ByteReader::new(slice.iter().cloned().map(Ok)).unwrap() +} +pub fn slice_bits(slice: &[u8]) -> impl Iterator + '_ { + slice.iter().flat_map(|&b| [7,6,5,4,3,2,1,0].map(|i| (b >> i) & 1 != 0)) +} + +impl>> BitReader for ByteReader { + type Error = E; + + fn peek(&self, bits: u8) -> Option { + assert!(bits <= 16); + if self.valid >= bits { + let shift = self.valid - bits; + let out = (self.partial >> shift) as u16 & ((1 << bits) - 1); + Some(out) + } else { + None + } + } + fn consume(&mut self, bits: u8) -> Result<(), E> { + self.valid -= bits; + self.fill() + } + fn bits_to_byte_boundary(&self) -> u8 { + self.valid & 7 + } +} + + +#[test] +fn test_bits() { + let mut bits = slice_reader(&[0b0000_1101, 0b1010_0000]); + assert_eq!(maps::black::decode(&mut bits), Some(42)); +} + +/// Enum used to signal black/white. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Color { + Black, + White +} +impl Not for Color { + type Output = Self; + fn not(self) -> Self { + match self { + Color::Black => Color::White, + Color::White => Color::Black, + } + } +} + +struct Transitions<'a> { + edges: &'a [u16], + pos: usize +} +impl<'a> Transitions<'a> { + fn new(edges: &'a [u16]) -> Self { + Transitions { edges, pos: 0 } + } + fn seek_back(&mut self, start: u16) { + self.pos = self.pos.min(self.edges.len().saturating_sub(1)); + while self.pos > 0 { + if start < self.edges[self.pos-1] { + self.pos -= 1; + } else { + break; + } + } + } + fn next_color(&mut self, start: u16, color: Color, start_of_row: bool) -> Option { + if start_of_row { + if color == Color::Black { + self.pos = 1; + return self.edges.get(0).cloned() + } else { + self.pos = 2; + return self.edges.get(1).cloned() + } + } + while self.pos < self.edges.len() { + if self.edges[self.pos] <= start { + self.pos += 1; + continue; + } + + if (self.pos % 2 == 0) != (color == Color::Black) { + self.pos += 1; + } + + break; + } + if self.pos < self.edges.len() { + let val = self.edges[self.pos]; + self.pos += 1; + Some(val) + } else { + None + } + } + fn next(&mut self) -> Option { + if self.pos < self.edges.len() { + let val = self.edges[self.pos]; + self.pos += 1; + Some(val) + } else { + None + } + } + fn peek(&self) -> Option { + self.edges.get(self.pos).cloned() + } + fn skip(&mut self, n: usize) { + self.pos += n; + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Bits { + pub data: u16, + pub len: u8 +} + +impl fmt::Debug for Bits { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "d={:0b} w={}", self.data, self.len) + } +} +impl fmt::Display for Bits { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:0w$b}", self.data & ((1 << self.len) - 1), w=self.len as usize) + } +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/src/maps.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/src/maps.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/src/maps.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/src/maps.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,279 @@ +use fax_derive::bitmaps; +use crate::{BitReader, Bits}; + +enum Entry { + Leaf(u8, &'static [Option<(T, u8)>]), + Value(T, u8), + Prefix(u8, &'static [Entry]) +} +impl Entry { + fn find(&self, reader: &mut impl BitReader) -> Option { + match *self { + Entry::Value(val, len) => { + reader.consume(len); + Some(val) + } + Entry::Leaf(width, lut) => { + let index = reader.peek(width)?; + let (val, len) = lut[index as usize]?; + reader.consume(len); + Some(val) + } + Entry::Prefix(width, lut) => { + let index = reader.peek(width)?; + let entry = &lut[index as usize]; + match *entry { + Entry::Value(val, len) => { + reader.consume(len); + Some(val) + } + _ => { + reader.consume(width); + entry.find(reader) + } + } + } + } + } +} + +pub const EDFB_HALF: Bits = Bits { data: 1, len: 12 }; +pub const EOL: Bits = Bits { data: 1, len: 12 }; + +#[derive(Copy, Clone, Debug)] +pub enum Mode { + Pass, + Horizontal, + Vertical(i8), + Extension, + EOF, +} + +bitmaps! { + mode { + 0001 => Mode::Pass, + 001 => Mode::Horizontal, + 1 => Mode::Vertical(0), + 011 => Mode::Vertical(1), + 000011 => Mode::Vertical(2), + 0000011 => Mode::Vertical(3), + 010 => Mode::Vertical(-1), + 000010 => Mode::Vertical(-2), + 0000010 => Mode::Vertical(-3), + 0000001 => Mode::Extension, + 000000000001 => Mode::EOF, + }, + black { + 0000110111 => 0, + 010 => 1, + 11 => 2, + 10 => 3, + 011 => 4, + 0011 => 5, + 0010 => 6, + 00011 => 7, + 000101 => 8, + 000100 => 9, + 0000100 => 10, + 0000101 => 11, + 0000111 => 12, + 00000100 => 13, + 00000111 => 14, + 000011000 => 15, + 0000010111 => 16, + 0000011000 => 17, + 0000001000 => 18, + 00001100111 => 19, + 00001101000 => 20, + 00001101100 => 21, + 00000110111 => 22, + 00000101000 => 23, + 00000010111 => 24, + 00000011000 => 25, + 000011001010 => 26, + 000011001011 => 27, + 000011001100 => 28, + 000011001101 => 29, + 000001101000 => 30, + 000001101001 => 31, + 000001101010 => 32, + 000001101011 => 33, + 000011010010 => 34, + 000011010011 => 35, + 000011010100 => 36, + 000011010101 => 37, + 000011010110 => 38, + 000011010111 => 39, + 000001101100 => 40, + 000001101101 => 41, + 000011011010 => 42, + 000011011011 => 43, + 000001010100 => 44, + 000001010101 => 45, + 000001010110 => 46, + 000001010111 => 47, + 000001100100 => 48, + 000001100101 => 49, + 000001010010 => 50, + 000001010011 => 51, + 000000100100 => 52, + 000000110111 => 53, + 000000111000 => 54, + 000000100111 => 55, + 000000101000 => 56, + 000001011000 => 57, + 000001011001 => 58, + 000000101011 => 59, + 000000101100 => 60, + 000001011010 => 61, + 000001100110 => 62, + 000001100111 => 63, + 0000001111 => 64, + 000011001000 => 128, + 000011001001 => 192, + 000001011011 => 256, + 000000110011 => 320, + 000000110100 => 384, + 000000110101 => 448, + 0000001101100 => 512, + 0000001101101 => 576, + 0000001001010 => 640, + 0000001001011 => 704, + 0000001001100 => 768, + 0000001001101 => 832, + 0000001110010 => 896, + 0000001110011 => 960, + 0000001110100 => 1024, + 0000001110101 => 1088, + 0000001110110 => 1152, + 0000001110111 => 1216, + 0000001010010 => 1280, + 0000001010011 => 1344, + 0000001010100 => 1408, + 0000001010101 => 1472, + 0000001011010 => 1536, + 0000001011011 => 1600, + 0000001100100 => 1664, + 0000001100101 => 1728, + 00000001000 => 1792, + 00000001100 => 1856, + 00000001101 => 1920, + 000000010010 => 1984, + 000000010011 => 2048, + 000000010100 => 2112, + 000000010101 => 2176, + 000000010110 => 2240, + 000000010111 => 2304, + 000000011100 => 2368, + 000000011101 => 2432, + 000000011110 => 2496, + 000000011111 => 2560, + }, + white { + 00110101 => 0, + 000111 => 1, + 0111 => 2, + 1000 => 3, + 1011 => 4, + 1100 => 5, + 1110 => 6, + 1111 => 7, + 10011 => 8, + 10100 => 9, + 00111 => 10, + 01000 => 11, + 001000 => 12, + 000011 => 13, + 110100 => 14, + 110101 => 15, + 101010 => 16, + 101011 => 17, + 0100111 => 18, + 0001100 => 19, + 0001000 => 20, + 0010111 => 21, + 0000011 => 22, + 0000100 => 23, + 0101000 => 24, + 0101011 => 25, + 0010011 => 26, + 0100100 => 27, + 0011000 => 28, + 00000010 => 29, + 00000011 => 30, + 00011010 => 31, + 00011011 => 32, + 00010010 => 33, + 00010011 => 34, + 00010100 => 35, + 00010101 => 36, + 00010110 => 37, + 00010111 => 38, + 00101000 => 39, + 00101001 => 40, + 00101010 => 41, + 00101011 => 42, + 00101100 => 43, + 00101101 => 44, + 00000100 => 45, + 00000101 => 46, + 00001010 => 47, + 00001011 => 48, + 01010010 => 49, + 01010011 => 50, + 01010100 => 51, + 01010101 => 52, + 00100100 => 53, + 00100101 => 54, + 01011000 => 55, + 01011001 => 56, + 01011010 => 57, + 01011011 => 58, + 01001010 => 59, + 01001011 => 60, + 00110010 => 61, + 00110011 => 62, + 00110100 => 63, + 11011 => 64, + 10010 => 128, + 010111 => 192, + 0110111 => 256, + 00110110 => 320, + 00110111 => 384, + 01100100 => 448, + 01100101 => 512, + 01101000 => 576, + 01100111 => 640, + 011001100 => 704, + 011001101 => 768, + 011010010 => 832, + 011010011 => 896, + 011010100 => 960, + 011010101 => 1024, + 011010110 => 1088, + 011010111 => 1152, + 011011000 => 1216, + 011011001 => 1280, + 011011010 => 1344, + 011011011 => 1408, + 010011000 => 1472, + 010011001 => 1536, + 010011010 => 1600, + 011000 => 1664, + 010011011 => 1728, + 00000001000 => 1792, + 00000001100 => 1856, + 00000001101 => 1920, + 000000010010 => 1984, + 000000010011 => 2048, + 000000010100 => 2112, + 000000010101 => 2176, + 000000010110 => 2240, + 000000010111 => 2304, + 000000011100 => 2368, + 000000011101 => 2432, + 000000011110 => 2496, + 000000011111 => 2560, + }, +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/src/tiff.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/src/tiff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/src/tiff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/src/tiff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,73 @@ +#[derive(Copy, Clone)] +enum Value { + Short(u16), + Long(u32), + Rational(u32, u32), + DataOffset, +} + +pub fn wrap(data: &[u8], width: u32, height: u32) -> Vec { + use Value::*; + let header_data = [ + (256, Long(width)), // ImageWidth + (257, Long(height)), // ImageLength + (259, Short(4)), // Compression + (262, Short(0)), // PhotometricInterpretation + (273, DataOffset), // StripOffsets + (274, Short(1)), // Orientation + (278, Long(height)), // RowsPerStrip + (279, Long(data.len() as u32)), // StripByteCounts + (282, Rational(200, 1)), // XResolution + (283, Rational(200, 1)), // YResolution + (296, Short(2)), // ResolutionUnit + ]; + let rat_data_len = 2 * 8; // number of rationals * 8 + let ifd_end = + 4 + // magic + 4 + // IFD offset + 2 + // IFD entry count + 12 * header_data.len() + // IFD enties + 4; // null pointer at end of IFD + let header_size = ifd_end + rat_data_len; + + let mut out = Vec::with_capacity(header_size + data.len()); + + out.extend_from_slice(&[73, 73, 42, 0]); + let ifd_offset: u32 = 8; + out.extend_from_slice(&ifd_offset.to_le_bytes()); + + out.extend_from_slice(&u16::to_le_bytes(header_data.len() as u16)); + + let mut num_rat = 0; + for &(tag, val) in header_data.iter() { + let (typ_num, val) = match val { + Short(n) => (3, n as u32), + Long(n) => (4, n), + Rational(_, _) => { + let o = ifd_end + 8 * num_rat; + num_rat += 1; + (5, o as u32) + } + DataOffset => (4, header_size as u32) + }; + let count = 1; + out.extend_from_slice(&u16::to_le_bytes(tag)); + out.extend_from_slice(&u16::to_le_bytes(typ_num)); + out.extend_from_slice(&u32::to_le_bytes(count)); + out.extend_from_slice(&u32::to_le_bytes(val)); + } + // NULL at IFD end + out.extend_from_slice(&[0; 4]); + + // write additional data + for &(_, val) in header_data.iter() { + if let Value::Rational(nom, denom) = val { + out.extend_from_slice(&nom.to_le_bytes()); + out.extend_from_slice(&denom.to_le_bytes()); + } + } + + assert_eq!(out.len(), header_size); + out.extend_from_slice(data); + out +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax/tests/check.rs clamav-1.4.6+dfsg/.cargo/vendor/fax/tests/check.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax/tests/check.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax/tests/check.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,167 @@ +#![feature(slice_split_once)] + +use fax::{encoder, slice_bits, slice_reader, BitReader, ByteReader}; +use fax::{VecWriter, decoder, decoder::pels, BitWriter, Bits, Color}; +use std::fmt::Debug; +use std::io::Write; +use std::fs::{self, File}; +use std::path::Path; + +#[test] +fn main() { + let data_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../fax-test"); + + let mut fails = vec![]; + + for r in data_path.read_dir().unwrap() { + let e = r.unwrap(); + let p = e.path(); + + let base = data_path.join(p.file_stem().unwrap()); + let pbm = base.with_extension("pbm"); + let r = if p.extension().is_some_and(|e| e == "fax") { + read_pbm(&pbm).test_fax(&p) + } else if p.extension().is_some_and(|e| e == "tiff") { + read_pbm(&pbm).test_tiff(&p) + } else { + continue; + }; + println!("{base:?} {r:?}"); + if r.is_err() { + fails.push(p); + } + } + + if fails.len() > 0 { + println!("failures: {fails:?}"); + //panic!(""); + } +} + +struct TestImage { + width: u16, + height: u16, + data: Vec, +} +fn read_pbm(path: &Path) -> TestImage { + let ref_data = std::fs::read(path).unwrap(); + let (header1, data) = ref_data.split_once(|&b| b == b'\n').unwrap(); + assert_eq!(header1, b"P4"); + let (header2, ref_image) = data.split_once(|&b| b == b'\n').unwrap(); + let header2 = std::str::from_utf8(header2).unwrap(); + let (w, h) = header2.split_once(" ").unwrap(); + let width: u16 = w.parse().unwrap(); + let h: u16 = h.parse().unwrap(); + + TestImage { width, height: h, data: ref_image.to_vec() } +} +impl TestImage { + fn test_fax(&self, fax_path: &Path) -> Result<(), ()> { + let data = fs::read(fax_path).unwrap(); + self.test_stream(&data, false) + } + + fn test_tiff(&self, path: &Path) -> Result<(), ()> { + use tiff::{decoder::Decoder, tags::Tag}; + let data = std::fs::read(path).unwrap(); + let reader = std::io::Cursor::new(data.as_slice()); + let mut decoder = Decoder::new(reader).unwrap(); + let strip_offset = decoder.get_tag(Tag::StripOffsets).unwrap().into_u32().unwrap() as usize; + let strip_bytes = decoder.get_tag(Tag::StripByteCounts).unwrap().into_u32().unwrap() as usize; + decoder.goto_offset_u64(strip_offset as _).unwrap(); + + let white_is_1 = decoder.get_tag(Tag::PhotometricInterpretation).unwrap().into_u16().unwrap() != 0; + + let data = &data[strip_offset .. strip_offset + strip_bytes]; + self.test_stream(&data, white_is_1) + } + + fn test_stream(&self, data: &[u8], white_is_1: bool) -> Result<(), ()> { + let mut ref_lines = self.data.chunks_exact((self.width as usize + 7) / 8).take(self.height as _); + + let (black, white) = match white_is_1 { + false => (Bits { data: 1, len: 1 }, Bits { data: 0, len: 1 }), + true => (Bits { data: 0, len: 1 }, Bits { data: 1, len: 1 }) + }; + + let mut height = 0; + let mut errors = 0; + let ok = decoder::decode_g4(data.iter().cloned(), self.width, None, |transitions| { + //println!("{}", transitions.len()); + let mut writer = VecWriter::new(); + for c in pels(transitions, self.width) { + let bit = match c { + Color::Black => black, + Color::White => white + }; + writer.write(bit).unwrap(); + } + writer.pad(); + let data = writer.finish(); + let ref_line = ref_lines.next().unwrap(); + if ref_line != data { + println!("line {height} mismatch"); + errors += 1; + } + height += 1; + }).is_some(); + + if errors > 0 { + println!("{} errors", errors); + if height == self.height { + return Ok(()); + } + return Err(()); + } + if !ok { + println!("not ok"); + return Err(()); + } + + + fn pixels(line: &[u8], white_is_1: bool) -> impl Iterator + '_ { + slice_bits(line).map(move |b| if b ^ white_is_1 { Color::Black } else { Color::White }) + } + let mut expected = slice_reader(data); + let mut encoder = encoder::Encoder::new(TestWriter { expected: &mut expected, offset: 0 }); + let ref_lines = self.data.chunks_exact((self.width as usize + 7) / 8).take(self.height as _); + let mut fail = false; + for (i, line) in ref_lines.enumerate() { + println!("line {i}"); + if encoder.encode_line(pixels(line, white_is_1), self.width).is_err() { + println!("fail at line {i} of {}", self.height); + fail = true; + break; + } + } + + dbg!(fax::maps::mode::decode(&mut expected)); + + if fail { + return Err(()); + } + Ok(()) + } +} + +struct TestWriter<'a, R> { + offset: usize, + expected: &'a mut ByteReader, +} +impl<'a, E: Debug, R: Iterator>> BitWriter for TestWriter<'a, R> { + type Error = (usize, u8); + fn write(&mut self, bits: Bits) -> Result<(), Self::Error> { + match self.expected.expect(bits) { + Ok(()) => { + self.expected.consume(bits.len).unwrap(); + } + Err(_) => { + self.expected.print_peek(); + println!(" @{}+{} found {}", self.offset/8, self.offset%8, bits); + return Err((self.offset / 8, (self.offset % 8) as u8)); + }, + } + self.offset += bits.len as usize; + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"aabbe6618b641afe07fb831d6d184d88d5bbf5a45d71350c4b7ebd5a3d1f3544","Cargo.lock":"59bf7ba3516854c2529dcb522e378e390c309e8f201b8a97abbc7cb2e9061af8","Cargo.toml":"6cdaeb86f6147dd70051f5e61cc6d1f89b5f4dd1f1d175c7874d4798292b3e2a","Cargo.toml.orig":"34da4cab7ff30ef38fd413da49c787c83a32f782db304c93687567f168060725","src/lib.rs":"06b28015d3282c4d8ffcad90adc2e9933f53e9c5ea7186c4f04f1bb930ffcc7b"},"package":"a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "40b226eb97b391355e971fd95a8dd532a4c127a0" + }, + "path_in_vcs": "derive" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "fax_derive" +version = "0.2.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "fax_derive" +version = "0.2.0" +authors = ["Sebastian K "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Bitstream matcher for the fax crate" +readme = false +license = "MIT" +repository = "https://github.com/pdf-rs/fax" + +[lib] +name = "fax_derive" +path = "src/lib.rs" +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +[package] +name = "fax_derive" +version = "0.2.0" +authors = ["Sebastian K "] +edition = "2018" +description = "Bitstream matcher for the fax crate" +license = "MIT" +repository = "https://github.com/pdf-rs/fax" + +[dependencies] +syn = "2.0" +quote = "1.0" +proc-macro2 = "1.0" + +[lib] +proc-macro = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/fax_derive/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fax_derive/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,391 @@ +use proc_macro2::{TokenStream, Span, Literal}; +use quote::{quote, ToTokens}; +use syn::{ + parse_macro_input, Expr, Error, parse::{ParseStream, Parse}, Result, Token, Ident, + punctuated::Punctuated, braced, Type, +}; +use std::fmt::{self, Debug}; +use std::ops::Range; + +#[proc_macro] +pub fn bitmaps(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + // Parse the input tokens into a syntax tree + let input = parse_macro_input!(input as BitMaps); + + // Build the output, possibly using quasi-quotation + let maps = input.maps.iter().map(|map| { + let (code, root) = map.build(); + let name = &map.name; + let typ = match map.typ { + Some(ref t) => quote!{ #t }, + None => quote! { u16 } + }; + let list = map.entries.iter().map(|entry| { + let bits = entry.bits; + let val = &entry.value; + quote!{ (#val, #bits) } + }); + let arms = map.entries.iter().map(|entry| { + let bits = entry.bits; + let val = &entry.value; + quote!{ #val => #bits } + }); + let n = map.entries.len(); + + quote! { + pub mod #name { + pub use super::*; + use crate::{BitReader, Bits}; + + #code + + pub fn decode(reader: &mut impl BitReader) -> Option<#typ> { + let root = #root; + root.find(reader) + } + + pub fn encode(val: #typ) -> Option { + let bits = match val { + #(#arms,)* + _ => return None + }; + Some(bits) + } + + pub static ENTRIES: [(#typ, Bits); #n] = [ #(#list,)* ]; + } + } + }); + let expanded = quote! { + #(#maps)* + }; + + // Hand the output tokens back to the compiler + proc_macro::TokenStream::from(expanded) +} + +struct BitMaps { + maps: Vec +} +impl Parse for BitMaps { + fn parse(input: ParseStream) -> Result { + let entries = Punctuated::<_, Token![,]>::parse_terminated(input)?; + + Ok(BitMaps { maps: entries.into_pairs().map(|p| p.into_value()).collect() }) + } +} + +struct BitMap { + name: Ident, + entries: Vec, + typ: Option +} +impl Parse for BitMap { + fn parse(input: ParseStream) -> Result { + let name: Ident = input.parse()?; + let typ; + if input.peek(Token![<]) { + let _ = input.parse::()?; + typ = Some(input.parse::()?); + let _ = input.parse::]>()?; + } else { + typ = None; + } + + let content; + + braced!(content in input); + let entries = Punctuated::<_, Token![,]>::parse_terminated(&content)?; + + Ok(BitMap { + name, typ, + entries: entries.into_pairs().map(|p| p.into_value()).collect() + }) + } +} +impl BitMap { + fn build(&self) -> (TokenStream, TokenStream) { + let patterns: Vec<(usize, Bits)> = self.entries.iter().enumerate().map(|(i, e)| (i, e.bits)).collect(); + let node = Node::build(&patterns).unwrap(); + + let mut defs = vec![]; + let out = self.walk(&mut defs, &node, Bits::empty()); + + (quote! { + #(#defs)* + }, out) + } + fn walk(&self, defs: &mut Vec, node: &Node, bits: Bits) -> TokenStream { + match *node { + Node::Value(idx, len) => { + let val = &self.entries[idx].value; + quote!{ Entry::Value(#val, #len) } + } + Node::LeafLut(ref lut) => { + let name = Ident::new(&format!("LEAF_LUT_{}", bits), Span::call_site()); + let size = lut.data.len(); + let width = lut.width; + let entries = lut.data.iter().map(|e| match *e { + Some((idx, len)) => { + let val = &self.entries[idx].value; + quote! { Some((#val, #len)) } + }, + None => quote!{ None } + }); + let typ = match self.typ { + Some(ref t) => quote!{ #t }, + None => quote! { u16 } + }; + defs.push(quote!{ + static #name: [Option<(#typ, u8)>; #size] = [ + #(#entries,)* + ]; + }); + quote! { Entry::Leaf(#width, &#name) } + } + Node::PrefixLut(ref lut) => { + let name = Ident::new(&format!("PREFIX_LUT_{}", bits), Span::call_site()); + let size = 1usize << lut.width; + let width = lut.width; + let entries: Vec<_> = lut.data.iter().enumerate().map(|(i, node)| match node { + None => quote!{ Entry::Empty }.into(), + Some(node) => { + let entry_bits = bits.concat(Bits::new(i as u16, lut.width)); + self.walk(defs, node, entry_bits) + } + }).collect(); + + let typ = match self.typ { + Some(ref t) => quote!{ Entry<#t> }, + None => quote! { Entry } + }; + defs.push(quote!{ + static #name: [#typ; #size] = [ + #(#entries,)* + ]; + }); + + quote! { Entry::Prefix(#width, &#name) } + } + } + } +} +struct BitMapEntry { + bits: Bits, + value: Expr, +} +impl Parse for BitMapEntry { + fn parse(input: ParseStream) -> Result { + let bits = input.parse()?; + let _ = input.parse::]>()?; + let value = input.parse()?; + Ok(BitMapEntry { bits, value }) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct Bits { + data: u16, + len: u8 +} +impl Bits { + fn new(data: u16, len: u8) -> Bits { + Bits { data, len } + } + fn concat(self, rhs: Bits) -> Bits { + Bits { + data: self.data << rhs.len | rhs.data, + len: self.len + rhs.len + } + } + fn common_prefix_len(self, other: Bits) -> u8 { + (self.align_left() ^ other.align_left()).leading_zeros() as u8 + } + fn align_left(self) -> u16 { + self.data << (16 - self.len) + } + fn prefix(self, len: u8) -> u16 { + assert!(len <= self.len); + self.data >> (self.len - len) + } + fn prefix_range(self, len: u8) -> Range { + assert!(len >= self.len); + let s = len - self.len; + let n = 1 << (len - self.len); + let m = self.data << s; + m .. m + n + } + fn strip_prefix(self, len: u8) -> Bits { + assert!(len <= self.len); + let len = self.len - len; + Bits { + data: self.data & ((1< Bits { + Bits { + data: 0, + len: 0 + } + } +} +impl fmt::Display for Bits { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:0w$b}", self.data, w=self.len as usize) + } +} +impl fmt::Debug for Bits { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "d={:0b} w={}", self.data, self.len) + } +} +impl ToTokens for Bits { + fn to_tokens(&self, tokens: &mut TokenStream) { + let Bits { data, len } = *self; + tokens.extend(quote! { + Bits { data: #data, len: #len } + }) + } +} +impl Parse for Bits { + fn parse(input: ParseStream) -> Result { + let lit: Literal = input.parse()?; + + let mut data = 0; + let mut len = 0; + let s = lit.to_string(); + for c in s.chars() { + let b = match c { + '0' => 0, + '1' => 1, + _ => return Err(Error::new(lit.span(), "only 0 and 1 are allowed")) + }; + data = data << 1 | b; + len += 1; + } + Ok(Bits { data, len }) + } +} + +struct LeafLut { + width: u8, + data: Vec> +} +impl LeafLut { + fn build(patterns: &[(T, Bits)], prefix: u8, width: u8) -> Self { + assert!(patterns.len() > 1); + + let mut data = vec![None; 1usize << width]; + for (val, pat) in patterns { + let pat = pat.strip_prefix(prefix); + + for idx in pat.prefix_range(width) { + data[idx as usize] = Some((val.clone(), pat.len)); + } + } + + assert!(data.len() > 1); + LeafLut { + data, + width + } + } +} +enum Node { + Value(T, u8), + LeafLut(LeafLut), + PrefixLut(PrefixLut) +} +impl Node { + fn size(&self) -> usize { + match self { + Node::Value(_, _) => 1, + Node::LeafLut(ref lut) => 1 << lut.width, + Node::PrefixLut(ref lut) => lut.size(), + } + } + fn cost(&self) -> f64 { + match self { + Node::Value(_, _) => 0.0, + Node::LeafLut(_) => 1.0, + Node::PrefixLut(ref lut) => lut.cost(), + } + } + fn build(patterns: &[(T, Bits)]) -> Option> { + Self::build_prefix(patterns, 0) + } + fn build_prefix(patterns: &[(T, Bits)], prefix: u8) -> Option> { + //debug!("{:?}", patterns); + match patterns.len() { + 0 => None, + 1 => { + let (val, bits) = patterns[0]; + Some(Node::Value(val, bits.len)) + } + _ => { + let width = patterns.iter().map(|(_, b)| b.len).max().unwrap() - prefix; + if width > 8 { + Some(Node::PrefixLut(PrefixLut::build(&patterns, prefix))) + } else { + Some(Node::LeafLut(LeafLut::build(patterns, prefix, width) )) + } + } + } + } +} + +struct PrefixLut { + width: u8, + data: Vec>> +} +impl PrefixLut { + fn size(&self) -> usize { + self.data.iter().filter_map(|o| o.as_ref().map(|n| n.size())).sum::() + self.data.len() + } + // cost per 1 bit + fn cost(&self) -> f64 { + self.data.iter().filter_map(|o| o.as_ref().map(|n| n.cost())).sum::() * 0.5f64.powi(-(self.width as i32)) + } + fn build(patterns: &[(T, Bits)], prefix: u8) -> Self { + // determine LUT size + let max_width = patterns.iter().map(|(_, b)| b.len).max().unwrap() - prefix; + + let mut best = None; + let mut best_cost = f64::INFINITY; + for w in max_width.min(4) .. max_width { + let lut = Self::build_width(patterns, w, prefix); + let cost = lut.cost(); + if cost < best_cost { + best_cost = cost; + best = Some(lut); + } + } + best.expect("empty results") + } + fn build_width(patterns: &[(T, Bits)], width: u8, prefix: u8) -> Self { + let mut slots = vec![vec![]; 1 << width]; + //dbg!(patterns); + for &(val, bits) in patterns { + let bits = bits.strip_prefix(prefix); + //debug!("{} - {}bits ({:?})", bits, width, val); + + if bits.len >= width { + //debug!(" = {}", bits.strip_prefix(width)); + slots[bits.prefix(width) as usize].push((val, bits)); + } else { + for k in bits.prefix_range(width) { + //debug!(" -> {}", k); + slots[k as usize].push((val, bits)); + } + } + } + + let data: Vec<_> = slots.iter().map(|patterns| Node::build_prefix(&patterns, width)).collect(); + + PrefixLut { + data, + width + } + } +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"b601f0da34c8c669ed6e8accba125564da294546e9459fa9fb74cab20758f8ee","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"c77a4cf9da729987d0fe7ccd811e3bd27393914ddf3d23467c18cc22954513b3","README.md":"6707d3998971b67156f79f414a9032f24977977911e9d74ad251115b0c16203e","src/compress.rs":"2dab44a76819bab3ef22b7d90b9e9e71d0bc83f6f3721aab6bf4eaf28fa5c901","src/decompress.rs":"c32e9416d0ec03f98e7bd4184acc30aedf6035173716a3c38bcbb906d609a71c","src/lib.rs":"c24ffe479bf33436f40b0fabc6dcfd673285558b6adabc523258ebd2f4ba9c9a","src/tables.rs":"5e59a2710471574d83b18c3fcfa6550ad3e6c50fa155fc6ac6a9402d973044c3"},"package":"4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"fd0c7906964bed13b871a5650f7ccefcbb5b92582432248553ee3c431f72694f","Cargo.toml":"b601f0da34c8c669ed6e8accba125564da294546e9459fa9fb74cab20758f8ee","Cargo.toml.orig":"d0fb3f89a570ebcc29d1e8fea5c26f50c9da6ef3b97a8d6a8efac22561840839","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"c77a4cf9da729987d0fe7ccd811e3bd27393914ddf3d23467c18cc22954513b3","README.md":"6707d3998971b67156f79f414a9032f24977977911e9d74ad251115b0c16203e","src/compress.rs":"2dab44a76819bab3ef22b7d90b9e9e71d0bc83f6f3721aab6bf4eaf28fa5c901","src/decompress.rs":"c32e9416d0ec03f98e7bd4184acc30aedf6035173716a3c38bcbb906d609a71c","src/lib.rs":"c24ffe479bf33436f40b0fabc6dcfd673285558b6adabc523258ebd2f4ba9c9a","src/tables.rs":"5e59a2710471574d83b18c3fcfa6550ad3e6c50fa155fc6ac6a9402d973044c3"},"package":"4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "11d05bdaec5f2ff9e5d1a8aed555958789f4cef8" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/fdeflate/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/fdeflate/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +[package] +name = "fdeflate" +version = "0.3.4" +edition = "2021" + +# note: when changed, also update test runner in `.github/workflows/rust.yml` +rust-version = "1.57.0" + +license = "MIT OR Apache-2.0" +description = "Fast specialized deflate implementation" +authors = ["The image-rs Developers"] +include = ["/src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] + +# crates.io metadata +documentation = "https://docs.rs/fdeflate" +repository = "https://github.com/image-rs/fdeflate" +homepage = "https://github.com/image-rs/fdeflate" +categories = ["compression"] + +[dependencies] +simd-adler32 = "0.3.4" + +[dev-dependencies] +miniz_oxide = "0.7.1" +rand = "0.8.5" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"5fb6c3723bf6f993cb2b16592d6c6249b66a95b18e09bae5b4fcd0aa54dd60e0","Cargo.toml":"b402b6825d8d31ca58995cdf03ab4d9ccc2db52e559eb49441d0a4681f62eedd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","MAINTENANCE.md":"20ef2cb336c850d849652b110ec4806b71e69ed5dd50518a95eb9d453f8bf645","README.md":"a8fab33160befebe83eece4801f401da5932c0e1cca8e97a7ae4bce4aae1b061","examples/compress_file.rs":"cbdb8b0c556409b82f894ad5326babb6dba42c219d2d675927e7f5820053b295","examples/decompress_file.rs":"cd50dfbaccc905b3e02d6c50b26586196a682880203a8694343e0391799b70d5","examples/deflatedecoder-bufread.rs":"5b8abebce157f9b7cc3f6b5c90b9d533890a514e5f8d91bb43439f52fdc9ddce","examples/deflatedecoder-read.rs":"921e13031c5436494d8af0a8705a0adda2da536edefef2e1e311dffa8acd120f","examples/deflatedecoder-write.rs":"cfce37e8758c6d543dd130c7bdff571af3c8cd11bafcc933740107a3576832df","examples/deflateencoder-bufread.rs":"9fdd7d632d861f099d19a3ec1de539d9600f8004a119dd2a70f6aba5965b2e1c","examples/deflateencoder-read.rs":"8740a942ec7d07ccb4b57c5baac7a4d649817bffe4e37ce9a06c7d6d70378e4c","examples/deflateencoder-write.rs":"8e45425684b2368ef95f3704dce6f8077f38b9a90a38d147594c7c570f0d1c6c","examples/gzbuilder.rs":"d09c83417e4a01a8593ce3462a33340e6fe17fa51b4b0b3a6005b68959df4d8c","examples/gzdecoder-bufread.rs":"76880f3e6e10ed4a0bf564be9ddae1c50811aeabf61fb573039538b81805f390","examples/gzdecoder-read.rs":"d99e9a9ce03a27f280244a24e8f5a3282e5af15b455270d99c4bfecd19238d0d","examples/gzdecoder-write.rs":"d0a982377ca1d2fd1786bb32f16454b4f0afdba5e1c7f0ab97e15e8827d351d5","examples/gzencoder-bufread.rs":"760670c124b1c5776b63c300c7e8a1dcd5e0ae633017dcf2e3d2d6e997dcc9c4","examples/gzencoder-read.rs":"27ec68675418bb7d1a110b8d1f33e7b1069f42bcce6f21f8d9235bde405cdf9f","examples/gzencoder-write.rs":"f127f2e398231d03269770fa18ac5d465f8d56d283f1118055f04f1d03369c31","examples/gzmultidecoder-bufread.rs":"bfa6c5554c3da5a61a7d1e1dad115b7ee784d136e2ac61272c87ad3e1eb4ec4c","examples/gzmultidecoder-read.rs":"c058d5eee5bf45b38132f8e487a714c9521191c7dabe2459362d2f8de689c6bf","examples/hello_world.txt":"d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26","examples/hello_world.txt.gz":"8b4c5972b92b8ee8dc99116e278afb9165276ddb13c0d334c8da2770fd4d1f7d","examples/zlibdecoder-bufread.rs":"0f541ec64c635d45fc206a02718c0b90c49123a0441a95455d6a8a9e0d20e011","examples/zlibdecoder-read.rs":"bbd85b47b8b804c3294b3f23f978eaf6fb09a187cb46eb86ae1ae2790dfab8d9","examples/zlibdecoder-write.rs":"f347a831d7201d3efd604b006c88421fa2a5906c6377b47c7ae391d0809186e6","examples/zlibencoder-bufread.rs":"e0e05686ad4521ba18b742a5cbbc5937cec1fd8b9e8313070b32c6f178dfbaf6","examples/zlibencoder-read.rs":"4a3156dc73cd77e6ac56700680652be63a1270d95ce384ebcd5c014cce2d5179","examples/zlibencoder-write.rs":"822d4cd326ac7402ff8f828c1dbb3aa108c68a89fc04488da252ca6a74e624b0","src/bufreader.rs":"2d6a59330e8f838eb6474d19104f21cb98236125c189f36bdff75a069a4cea8f","src/crc.rs":"f02b9ffbedf06360c8164f98ecf51fe7f70c48cdb3bfc72e176421419c1de030","src/deflate/bufread.rs":"da2065b113205f6f29ed8e316d3e6a703495b456805748d114c1f76a885e700a","src/deflate/mod.rs":"d33ef6a3d502d599a4ba6ac99c6312b414002dba43c388d271fc1f8c9c609363","src/deflate/read.rs":"57f7a9609a111e88fb079188fdc0a79e1e20d97d363bd133f134ad11049220e0","src/deflate/write.rs":"0001436c147fa2cf2dfc2df0a1324a3c6a9d419ddf45c9cb4f17f182dca57fed","src/ffi/c.rs":"00d1ca68014710f628ab491c34395e87167d7a54f1a8e64d5bc5dd1ffdf3d3ce","src/ffi/mod.rs":"2b811be787e23654e56a1a5748f64f6b6953a829594aef9bdb8f223fe9a1bba9","src/ffi/rust.rs":"0a69aac9bd08728d212f503a16c0e7fb64a7822a7531bc3a96e78c89c09b6e80","src/gz/bufread.rs":"c3518d9ddb76980987ad1ed5faf9000b6b369b51d854415c3bab4edc5569b8ff","src/gz/mod.rs":"c3449201bd4bad2e4289f4cd1081a4be4505e7d9e8fee5a2838248bf979ef9f0","src/gz/read.rs":"7801c738001d6a2b12ee2a8532e4d7dae9f7e3c3f19c52561e82f8a56a905b71","src/gz/write.rs":"78954929f24229875503ffdc04944924120c199fa502a0742e195cffcc135631","src/lib.rs":"9651a09ff275d464ff4865974797a6dc8f2f786225e159b6bd0dbbfd5afc0cef","src/mem.rs":"3ca7e5236e85cb1ca4e9ef92e82d64962e1aff14e551ce55fcb30537b1779350","src/zio.rs":"ed5f375f5d6c4f094dfdd43185c9af5e91d1129bfbfa31edc6902a1f7496920b","src/zlib/bufread.rs":"cbdb0eab7b8b70bd194127bfd6feb3bb56b34545e11276bb13f37436e3b90774","src/zlib/mod.rs":"18ea5785b913d90191c6ad8483f57d0c5f98599137659e72f3c0c78324b4f8fa","src/zlib/read.rs":"4a06d07ea137390efd823554afed7d05a8acfc3ab4f5a5382202030380281f23","src/zlib/write.rs":"c9a7c61a0d8671cf697ee5fafd73cbb44862dd1483d8b353a56afc96c15cbac5","tests/corrupt-gz-file.bin":"083dd284aa1621916a2d0f66ea048c8d3ba7a722b22d0d618722633f51e7d39c","tests/early-flush.rs":"9a4db8fcbac659c52cafe5e1ab647d86781cf8b1f298d8dee34223c0292e0d74","tests/empty-read.rs":"39143ff0383655bb115e995b2a953f11e82d0ac03b4bec080973be7c2d421054","tests/good-file.gz":"87296963e53024a74752179ce7e54087565d358a85d3e65c3b37ef36eaa3d4a6","tests/good-file.txt":"bc4e03658a441fe2ad2df7cd2197144b87e41696f01e327b380e869cd9b485a0","tests/gunzip.rs":"c00946db2147b23c4300c77fedf0a04e65c774101575e9828433831311416a50","tests/multi.gz":"efa3341da052f95056314cc6920e02a3da15bdef30234b2552fb407812db5cc6","tests/multi.txt":"dbea9325179efe46ea2add94f7b6b745ca983fabb208dc6d34aa064623d7ee23","tests/zero-write.rs":"cde1a675491d88e59a711103d3b0df4c77b60e8152b90d5a4f01b97879f8f8dc"},"package":"5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"231c061f522dfb6515076fb9fe101755a236558cec6bf6e147f4c789a43a82f5","Cargo.lock":"e899bdc056009f14104cf335093ce342f3761c85e9d70c2387e266a52879ac7f","Cargo.toml":"dcff605fcc59e74e53342b05b8afdce143aa8de914664b7fd4a3933e8748b189","Cargo.toml.orig":"bc3fc08433b16ad1fe1badc19105e0b9d016094f18196888c30337f97d1401d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"75d3bf11a47fed60aee0a6cc56a97b896b470ee8fb52d6cd553bd8348337f422","MAINTENANCE.md":"2904034aa8766570e5ba28b787084ea123b7c137bd688c0900d3bb6cf69a17eb","README.md":"7958879222474ae6e290335294d3e752bb9142d611bcf800bb1c8ba0a9620871","examples/compress_file.rs":"cbdb8b0c556409b82f894ad5326babb6dba42c219d2d675927e7f5820053b295","examples/decompress_file.rs":"d626001235de051b3372d0fe8cc61a8fdf3da078e28cc4a5414578708792cad8","examples/deflatedecoder-bufread.rs":"5b8abebce157f9b7cc3f6b5c90b9d533890a514e5f8d91bb43439f52fdc9ddce","examples/deflatedecoder-read.rs":"921e13031c5436494d8af0a8705a0adda2da536edefef2e1e311dffa8acd120f","examples/deflatedecoder-write.rs":"cfce37e8758c6d543dd130c7bdff571af3c8cd11bafcc933740107a3576832df","examples/deflateencoder-bufread.rs":"9fdd7d632d861f099d19a3ec1de539d9600f8004a119dd2a70f6aba5965b2e1c","examples/deflateencoder-read.rs":"8740a942ec7d07ccb4b57c5baac7a4d649817bffe4e37ce9a06c7d6d70378e4c","examples/deflateencoder-write.rs":"8e45425684b2368ef95f3704dce6f8077f38b9a90a38d147594c7c570f0d1c6c","examples/gzbuilder.rs":"d09c83417e4a01a8593ce3462a33340e6fe17fa51b4b0b3a6005b68959df4d8c","examples/gzdecoder-bufread.rs":"76880f3e6e10ed4a0bf564be9ddae1c50811aeabf61fb573039538b81805f390","examples/gzdecoder-read.rs":"d99e9a9ce03a27f280244a24e8f5a3282e5af15b455270d99c4bfecd19238d0d","examples/gzdecoder-write.rs":"d0a982377ca1d2fd1786bb32f16454b4f0afdba5e1c7f0ab97e15e8827d351d5","examples/gzencoder-bufread.rs":"760670c124b1c5776b63c300c7e8a1dcd5e0ae633017dcf2e3d2d6e997dcc9c4","examples/gzencoder-read.rs":"27ec68675418bb7d1a110b8d1f33e7b1069f42bcce6f21f8d9235bde405cdf9f","examples/gzencoder-write.rs":"f127f2e398231d03269770fa18ac5d465f8d56d283f1118055f04f1d03369c31","examples/gzmultidecoder-bufread.rs":"bfa6c5554c3da5a61a7d1e1dad115b7ee784d136e2ac61272c87ad3e1eb4ec4c","examples/gzmultidecoder-read.rs":"c058d5eee5bf45b38132f8e487a714c9521191c7dabe2459362d2f8de689c6bf","examples/hello_world.txt":"d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26","examples/hello_world.txt.gz":"8b4c5972b92b8ee8dc99116e278afb9165276ddb13c0d334c8da2770fd4d1f7d","examples/zlibdecoder-bufread.rs":"0f541ec64c635d45fc206a02718c0b90c49123a0441a95455d6a8a9e0d20e011","examples/zlibdecoder-read.rs":"bbd85b47b8b804c3294b3f23f978eaf6fb09a187cb46eb86ae1ae2790dfab8d9","examples/zlibdecoder-write.rs":"f347a831d7201d3efd604b006c88421fa2a5906c6377b47c7ae391d0809186e6","examples/zlibencoder-bufread.rs":"e0e05686ad4521ba18b742a5cbbc5937cec1fd8b9e8313070b32c6f178dfbaf6","examples/zlibencoder-read.rs":"4a3156dc73cd77e6ac56700680652be63a1270d95ce384ebcd5c014cce2d5179","examples/zlibencoder-write.rs":"822d4cd326ac7402ff8f828c1dbb3aa108c68a89fc04488da252ca6a74e624b0","src/bufreader.rs":"2d6a59330e8f838eb6474d19104f21cb98236125c189f36bdff75a069a4cea8f","src/crc.rs":"de4eb1fcaa2e070cf6f1b55ad461467862683cfdd7a3ddd92cf73a2a795e645a","src/deflate/bufread.rs":"21377a7a79026adce886bc1e91535ef52d89ae00245935629586bbb96dc050e5","src/deflate/mod.rs":"5f26c8d2e21fb3c5b1275b18b38adc945d6398575eb863c289d7d4ecc71b6ee1","src/deflate/read.rs":"6562c1747898f2fa43c487cef5254f490f8ca38f2613315db279ee96c112e2e4","src/deflate/write.rs":"15c730f70cdec6ebac7246a56f475db2774f3ba77d25ddc54f3d0f04ab4670a7","src/ffi/c.rs":"8764b99ab668628507f420adf09152ff802339aa6c0b36edd281a33194e84edb","src/ffi/mod.rs":"2a944baf590f7f2db0b4f737e824e0874b9aa5b634161bcb1239410243392865","src/ffi/rust.rs":"30d5e3179913ae2a1c6b5a8f44ee129f04aa8aab6f27b7adc3b6210cb3d22888","src/gz/bufread.rs":"f8620d184d9590a695a3219bb17227b906aab0e588e444d90402e5b1e430f5a9","src/gz/mod.rs":"beb35e684123af26a393576653038c82291202a0e28a126e15d2d2993f55b959","src/gz/read.rs":"6cbb895787e3058eec59e01ab3fc959d77c338d76972a21b65947945e3a3fc3a","src/gz/write.rs":"09c06d423a2ef29774edd4d3436fb3fbcb00516aa619c0c4f7470bb5ff27277f","src/lib.rs":"dc9f546845d0dbf45e04b6dbac148eb76acbb6faf6057074c136333deb2b3157","src/mem.rs":"89df22e50cac384f6dd75477f19d96ab7bc038ad3a162e06e1bd46c809255e57","src/zio.rs":"7f26494078fb112f21c738b6dc3a1469e3a6e4f5ca3a8842cc2e5fff43245a44","src/zlib/bufread.rs":"111ca2eae88a707ea16202149108ef0af5628d16f076d25a36b4d806bbb05722","src/zlib/mod.rs":"e535804b61af961019139ce28e5e75272c2037dd897a64b19f1723b24efd9c28","src/zlib/read.rs":"4c6399cd986a483190309b4ea8795f30afe4319b4f28215c4541b932c99d3467","src/zlib/write.rs":"933c37c726c89aec71e71750a221a8d96b90449582a57a5c7f16f659ca28ceb5","tests/corrupt-gz-file.bin":"083dd284aa1621916a2d0f66ea048c8d3ba7a722b22d0d618722633f51e7d39c","tests/early-flush.rs":"9a4db8fcbac659c52cafe5e1ab647d86781cf8b1f298d8dee34223c0292e0d74","tests/empty-read.rs":"39143ff0383655bb115e995b2a953f11e82d0ac03b4bec080973be7c2d421054","tests/good-file.gz":"87296963e53024a74752179ce7e54087565d358a85d3e65c3b37ef36eaa3d4a6","tests/good-file.txt":"bc4e03658a441fe2ad2df7cd2197144b87e41696f01e327b380e869cd9b485a0","tests/gunzip.rs":"c00946db2147b23c4300c77fedf0a04e65c774101575e9828433831311416a50","tests/multi.gz":"efa3341da052f95056314cc6920e02a3da15bdef30234b2552fb407812db5cc6","tests/multi.txt":"dbea9325179efe46ea2add94f7b6b745ca983fabb208dc6d34aa064623d7ee23","tests/zero-write.rs":"cde1a675491d88e59a711103d3b0df4c77b60e8152b90d5a4f01b97879f8f8dc"},"package":"bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "2661fbb3107a5489ad8d2315049d4d1a295f130b" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -3,16 +3,25 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "cc" -version = "1.0.88" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -22,9 +31,9 @@ [[package]] name = "cloudflare-zlib-sys" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3185ff8c69c53ab346d5ac89f418e194b997d48393cae321cb611dd05f83c90" +checksum = "32b785d676ed9aed12ebbfb77c5e02d4bb888b652a6e88acbf31ab81a84d5983" dependencies = [ "cc", ] @@ -49,7 +58,7 @@ [[package]] name = "flate2" -version = "1.0.30" +version = "1.1.5" dependencies = [ "cloudflare-zlib-sys", "crc32fast", @@ -58,7 +67,7 @@ "libz-sys", "miniz_oxide", "quickcheck", - "rand", + "rand 0.9.1", ] [[package]] @@ -69,20 +78,32 @@ dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libz-ng-sys" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6409efc61b12687963e602df8ecf70e8ddacf95bc6576bcf16e3ac6328083c5" +checksum = "4436751a01da56f1277f323c80d584ffad94a3d14aecd959dd0dff75aa73a438" dependencies = [ "cmake", "libc", @@ -90,19 +111,18 @@ [[package]] name = "libz-rs-sys" -version = "0.1.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c4423250be0f3892a490cd6ddc490f5153335678776f08fca307f5fea3b28" +checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221" dependencies = [ - "libc", "zlib-rs", ] [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "cmake", @@ -113,11 +133,12 @@ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "adler", + "adler2", + "simd-adler32", ] [[package]] @@ -138,28 +159,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ - "rand", + "rand 0.8.5", ] [[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.3", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", ] [[package]] @@ -168,10 +203,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.12", ] [[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.2", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -184,7 +240,25 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] name = "zlib-rs" -version = "0.1.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52105e2dc6760ec88755876659dc301b51f6728f3b7a1bbdeeb66c6af4d44a1" +checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,12 +11,20 @@ [package] edition = "2018" +rust-version = "1.67.0" name = "flate2" -version = "1.0.30" +version = "1.1.5" authors = [ "Alex Crichton ", "Josh Triplett ", ] +build = false +exclude = [".*"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = """ DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, @@ -46,44 +54,6 @@ "docsrs", ] -[dependencies.cloudflare-zlib-sys] -version = "0.3.0" -optional = true - -[dependencies.crc32fast] -version = "1.2.0" - -[dependencies.libz-ng-sys] -version = "1.1.8" -optional = true - -[dependencies.libz-rs-sys] -version = "0.1.1" -features = [ - "std", - "rust-allocator", -] -optional = true -default-features = false - -[dependencies.libz-sys] -version = "1.1.8" -optional = true -default-features = false - -[dependencies.miniz_oxide] -version = "0.7.1" -features = ["with-alloc"] -optional = true -default-features = false - -[dev-dependencies.quickcheck] -version = "1.0" -default-features = false - -[dev-dependencies.rand] -version = "0.8" - [features] any_impl = [] any_zlib = ["any_impl"] @@ -118,7 +88,163 @@ "libz-rs-sys", ] -[target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.miniz_oxide] -version = "0.7.1" -features = ["with-alloc"] +[lib] +name = "flate2" +path = "src/lib.rs" + +[[example]] +name = "compress_file" +path = "examples/compress_file.rs" + +[[example]] +name = "decompress_file" +path = "examples/decompress_file.rs" + +[[example]] +name = "deflatedecoder-bufread" +path = "examples/deflatedecoder-bufread.rs" + +[[example]] +name = "deflatedecoder-read" +path = "examples/deflatedecoder-read.rs" + +[[example]] +name = "deflatedecoder-write" +path = "examples/deflatedecoder-write.rs" + +[[example]] +name = "deflateencoder-bufread" +path = "examples/deflateencoder-bufread.rs" + +[[example]] +name = "deflateencoder-read" +path = "examples/deflateencoder-read.rs" + +[[example]] +name = "deflateencoder-write" +path = "examples/deflateencoder-write.rs" + +[[example]] +name = "gzbuilder" +path = "examples/gzbuilder.rs" + +[[example]] +name = "gzdecoder-bufread" +path = "examples/gzdecoder-bufread.rs" + +[[example]] +name = "gzdecoder-read" +path = "examples/gzdecoder-read.rs" + +[[example]] +name = "gzdecoder-write" +path = "examples/gzdecoder-write.rs" + +[[example]] +name = "gzencoder-bufread" +path = "examples/gzencoder-bufread.rs" + +[[example]] +name = "gzencoder-read" +path = "examples/gzencoder-read.rs" + +[[example]] +name = "gzencoder-write" +path = "examples/gzencoder-write.rs" + +[[example]] +name = "gzmultidecoder-bufread" +path = "examples/gzmultidecoder-bufread.rs" + +[[example]] +name = "gzmultidecoder-read" +path = "examples/gzmultidecoder-read.rs" + +[[example]] +name = "zlibdecoder-bufread" +path = "examples/zlibdecoder-bufread.rs" + +[[example]] +name = "zlibdecoder-read" +path = "examples/zlibdecoder-read.rs" + +[[example]] +name = "zlibdecoder-write" +path = "examples/zlibdecoder-write.rs" + +[[example]] +name = "zlibencoder-bufread" +path = "examples/zlibencoder-bufread.rs" + +[[example]] +name = "zlibencoder-read" +path = "examples/zlibencoder-read.rs" + +[[example]] +name = "zlibencoder-write" +path = "examples/zlibencoder-write.rs" + +[[test]] +name = "early-flush" +path = "tests/early-flush.rs" + +[[test]] +name = "empty-read" +path = "tests/empty-read.rs" + +[[test]] +name = "gunzip" +path = "tests/gunzip.rs" + +[[test]] +name = "zero-write" +path = "tests/zero-write.rs" + +[dependencies.cloudflare-zlib-sys] +version = "0.3.6" +optional = true + +[dependencies.crc32fast] +version = "1.2.0" + +[dependencies.libz-ng-sys] +version = "1.1.16" +optional = true + +[dependencies.libz-rs-sys] +version = "0.5.1" +features = [ + "std", + "rust-allocator", +] +optional = true +default-features = false + +[dependencies.libz-sys] +version = "1.1.20" +optional = true +default-features = false + +[dependencies.miniz_oxide] +version = "0.8.5" +features = [ + "with-alloc", + "simd", +] +optional = true +default-features = false + +[dev-dependencies.quickcheck] +version = "1.0" +default-features = false + +[dev-dependencies.rand] +version = "0.9" + +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies.miniz_oxide] +version = "0.8.5" +features = [ + "with-alloc", + "simd", +] default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +[package] +name = "flate2" +authors = ["Alex Crichton ", "Josh Triplett "] +version = "1.1.5" +edition = "2018" +license = "MIT OR Apache-2.0" +readme = "README.md" +rust-version = "1.67.0" +keywords = ["gzip", "deflate", "zlib", "zlib-ng", "encoding"] +categories = ["compression", "api-bindings"] +repository = "https://github.com/rust-lang/flate2-rs" +homepage = "https://github.com/rust-lang/flate2-rs" +documentation = "https://docs.rs/flate2" +description = """ +DEFLATE compression and decompression exposed as Read/BufRead/Write streams. +Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, +and raw deflate streams. +""" +exclude = [".*"] + +[dependencies] +libz-sys = { version = "1.1.20", optional = true, default-features = false } +libz-ng-sys = { version = "1.1.16", optional = true } +# this matches the default features, but we don't want to depend on the default features staying the same +libz-rs-sys = { version = "0.5.1", optional = true, default-features = false, features = ["std", "rust-allocator"] } +cloudflare-zlib-sys = { version = "0.3.6", optional = true } +miniz_oxide = { version = "0.8.5", optional = true, default-features = false, features = ["with-alloc", "simd"] } +crc32fast = "1.2.0" + +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc", "simd"] } + +[dev-dependencies] +rand = "0.9" +quickcheck = { version = "1.0", default-features = false } + +[features] +default = ["rust_backend"] +any_zlib = ["any_impl"] # note: this is not a real user-facing feature +any_impl = [] # note: this is not a real user-facing feature +zlib = ["any_zlib", "libz-sys"] +zlib-default = ["any_zlib", "libz-sys/default"] +zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"] +zlib-ng = ["any_zlib", "libz-ng-sys"] +zlib-rs = ["any_zlib", "libz-rs-sys"] +cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"] +rust_backend = ["miniz_oxide", "any_impl"] +miniz-sys = ["rust_backend"] # For backwards compatibility + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/flate2/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/LICENSE-MIT 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2014 Alex Crichton +Copyright (c) 2014-2025 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/MAINTENANCE.md clamav-1.4.6+dfsg/.cargo/vendor/flate2/MAINTENANCE.md --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/MAINTENANCE.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/MAINTENANCE.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,12 @@ This document explains how to perform the project's maintenance tasks. +### Repository Configuration + +Some repository settings, including branch protection and required approvals, are managed in the +[Rust team repo](https://github.com/rust-lang/team/blob/master/repos/rust-lang/flate2-rs.toml). +See the [repository schema](https://github.com/rust-lang/team/blob/aaa8039a2420a07cab9bbaca3885b3ad95a256a7/docs/toml-schema.md?plain=1#L248) +for supported directives. + ### Creating a new release #### Artifacts @@ -11,11 +18,11 @@ To generate all the artifacts above, one proceeds as follows: -1. `git checkout -b release-` - move to a branch to prepare making changes to the repository. *Changes cannot be made to `main` as it is protected.* -2. Edit `Cargo.toml` to the next package version. -3. `gh pr create` to create a new PR for the current branch and **get it merged**. +1. `git checkout -b release-` - create a branch to make changes to the repository. *Changes cannot be made to `main` as it is protected.* +2. Edit `Cargo.toml` to update the package version to ``. +3. Create a new PR for the branch (e.g. using `gh pr create`) and **get it approved and merged**. +4. Pull the `main` branch and ensure that you are at the merged commit. 4. `cargo publish` to create a new release on `crates.io`. 5. `git tag ` to remember the commit. 6. `git push --tags` to push the new tag. 7. Go to the newly created release page on GitHub and edit it by pressing the "Generate Release Notes" and the `@` button. Save the release. - diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/README.md clamav-1.4.6+dfsg/.cargo/vendor/flate2/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -23,9 +23,18 @@ ## MSRV (Minimum Supported Rust Version) Policy -This crate supports the current stable and the last stable for the latest version. -For example, if the current stable is 1.64, this crate supports 1.64 and 1.63. -Older stables may work, but we don't guarantee these will continue to work. +This crate supports the current and previous stable versions of the Rust compiler. +For example, if the current stable is 1.80, this crate supports 1.80 and 1.79. + +Other compiler versions may work, but failures may not be treated as a `flate2` bug. + +The `Cargo.toml` file specifies a `rust-version` for which builds of the current version +passed at some point. This value is indicative only, and may change at any time. + +The `rust-version` is a best-effort measured value and is different to the MSRV. The +`rust-version` can be incremented by a PR in order to pass tests, as long as the MSRV +continues to hold. When the `rust-version` increases, the next release should be a minor +version, to allow any affected users to pin to a previous minor version. ## Compression @@ -58,8 +67,20 @@ ## Backends -The default `miniz_oxide` backend has the advantage of being pure Rust. If you -want maximum performance, you can use the zlib-ng C library: +The default `miniz_oxide` backend has the advantage of only using safe Rust. + +If you want maximum performance while still benefiting from a Rust +implementation at the cost of some `unsafe`, you can use `zlib-rs`: + +```toml +[dependencies] +flate2 = { version = "1.0.17", features = ["zlib-rs"], default-features = false } +``` + +### C backends + +While zlib-rs is [the fastest overall](https://trifectatech.org/blog/zlib-rs-is-faster-than-c/), +the zlib-ng C library can be slightly faster in certain cases: ```toml [dependencies] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/examples/decompress_file.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/examples/decompress_file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/examples/decompress_file.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/examples/decompress_file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -17,7 +17,7 @@ let start = Instant::now(); let mut decoder = bufread::GzDecoder::new(input); copy(&mut decoder, &mut output).unwrap(); - println!("Source len: {:?}", source_len); + println!("Source len: {source_len:?}"); println!("Target len: {:?}", output.metadata().unwrap().len()); println!("Elapsed: {:?}", start.elapsed()); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/crc.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/crc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/crc.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/crc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,7 +8,7 @@ /// The CRC calculated by a [`CrcReader`]. /// /// [`CrcReader`]: struct.CrcReader.html -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Crc { amt: u32, hasher: Hasher, @@ -23,19 +23,10 @@ crc: Crc, } -impl Default for Crc { - fn default() -> Self { - Self::new() - } -} - impl Crc { /// Create a new CRC. - pub fn new() -> Crc { - Crc { - amt: 0, - hasher: Hasher::new(), - } + pub fn new() -> Self { + Self::default() } /// Returns the current crc32 checksum. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/bufread.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/bufread.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/bufread.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/bufread.rs 2006-07-24 01:21:28.000000000 +0000 @@ -127,6 +127,11 @@ /// This structure implements a [`Read`] interface. When read from, it reads /// compressed data from the underlying [`BufRead`] and provides the uncompressed data. /// +/// After reading a single member of the DEFLATE data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// If you need the following bytes, call `into_inner()` after Ok(0) to +/// recover the underlying reader. +/// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// @@ -259,7 +264,7 @@ let compressed = { let mut e = write::DeflateEncoder::new(Vec::new(), Compression::default()); - e.write(expected.as_ref()).unwrap(); + e.write_all(expected.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,7 +6,7 @@ mod tests { use std::io::prelude::*; - use rand::{thread_rng, Rng}; + use rand::{rng, Rng}; use super::{read, write}; use crate::Compression; @@ -17,7 +17,7 @@ let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { - let to_write = &v[..thread_rng().gen_range(0..v.len())]; + let to_write = &v[..rng().random_range(0..v.len())]; real.extend(to_write.iter().copied()); w.write_all(to_write).unwrap(); } @@ -46,7 +46,7 @@ let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { - let to_write = &v[..thread_rng().gen_range(0..v.len())]; + let to_write = &v[..rng().random_range(0..v.len())]; real.extend(to_write.iter().copied()); w.write_all(to_write).unwrap(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/read.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/read.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -123,6 +123,12 @@ /// This structure implements a [`Read`] interface. When read from, it reads /// compressed data from the underlying [`Read`] and provides the uncompressed data. /// +/// After reading a single member of the DEFLATE data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// `DeflateDecoder` may have read additional bytes past the end of the DEFLATE data. +/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader` +/// and use `bufread::DeflateDecoder` instead. +/// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/write.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/deflate/write.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/deflate/write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -172,6 +172,10 @@ /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// +/// After decoding a single member of the DEFLATE data this writer will return the number of bytes up to +/// to the end of the DEFLATE member and subsequent writes will return Ok(0) allowing the caller to +/// handle any data following the DEFLATE member. +/// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples @@ -338,7 +342,7 @@ fn decode_extra_data() { let compressed = { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/c.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/c.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/c.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/c.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,14 @@ //! Implementation for C backends. -use std::cmp; use std::fmt; use std::marker; +use std::mem::MaybeUninit; use std::os::raw::{c_int, c_uint}; use std::ptr; use super::*; use crate::mem; -#[derive(Default)] +#[derive(Clone, Default)] pub struct ErrorMessage(Option<&'static str>); impl ErrorMessage { @@ -50,27 +50,38 @@ reserved: 0, opaque: ptr::null_mut(), state: ptr::null_mut(), - #[cfg(all( - feature = "any_zlib", - not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys")) + + #[cfg(any( + // zlib-ng + feature = "zlib-ng", + // libz-sys + all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")) ))] zalloc: allocator::zalloc, - #[cfg(all( - feature = "any_zlib", - not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys")) + #[cfg(any( + // zlib-ng + feature = "zlib-ng", + // libz-sys + all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")) ))] zfree: allocator::zfree, - #[cfg(all(feature = "any_zlib", feature = "cloudflare-zlib-sys"))] + #[cfg( + // cloudflare-zlib + all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")), + )] zalloc: Some(allocator::zalloc), - #[cfg(all(feature = "any_zlib", feature = "cloudflare-zlib-sys"))] + #[cfg( + // cloudflare-zlib + all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")), + )] zfree: Some(allocator::zfree), // for zlib-rs, it is most efficient to have it provide the allocator. // The libz-rs-sys dependency is configured to use the rust system allocator - #[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))] + #[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))] zalloc: None, - #[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))] + #[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))] zfree: None, })), } @@ -87,7 +98,14 @@ } } -#[cfg(all(feature = "any_zlib", not(feature = "libz-rs-sys")))] +#[cfg(any( + // zlib-ng + feature = "zlib-ng", + // cloudflare-zlib + all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")), + // libz-sys + all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")), +))] mod allocator { use super::*; @@ -208,34 +226,12 @@ pub inner: Stream, } -impl InflateBackend for Inflate { - fn make(zlib_header: bool, window_bits: u8) -> Self { - unsafe { - let state = StreamWrapper::default(); - let ret = mz_inflateInit2( - state.inner, - if zlib_header { - window_bits as c_int - } else { - -(window_bits as c_int) - }, - ); - assert_eq!(ret, 0); - Inflate { - inner: Stream { - stream_wrapper: state, - total_in: 0, - total_out: 0, - _marker: marker::PhantomData, - }, - } - } - } - - fn decompress( +impl Inflate { + unsafe fn decompress_inner( &mut self, input: &[u8], - output: &mut [u8], + output_ptr: *mut u8, + output_len: usize, flush: FlushDecompress, ) -> Result { let raw = self.inner.stream_wrapper.inner; @@ -245,16 +241,16 @@ unsafe { (*raw).msg = ptr::null_mut(); (*raw).next_in = input.as_ptr() as *mut u8; - (*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint; - (*raw).next_out = output.as_mut_ptr(); - (*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint; + (*raw).avail_in = input.len().min(c_uint::MAX as usize) as c_uint; + (*raw).next_out = output_ptr; + (*raw).avail_out = output_len.min(c_uint::MAX as usize) as c_uint; let rc = mz_inflate(raw, flush as c_int); // Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64; - self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64; + self.inner.total_out += ((*raw).next_out as usize - output_ptr as usize) as u64; // reset these pointers so we don't accidentally read them later (*raw).next_in = ptr::null_mut(); @@ -263,15 +259,59 @@ (*raw).avail_out = 0; match rc { - MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(self.inner.msg()), + MZ_DATA_ERROR | MZ_STREAM_ERROR | MZ_MEM_ERROR => { + mem::decompress_failed(self.inner.msg()) + } MZ_OK => Ok(Status::Ok), MZ_BUF_ERROR => Ok(Status::BufError), MZ_STREAM_END => Ok(Status::StreamEnd), + #[allow(clippy::unnecessary_cast)] MZ_NEED_DICT => mem::decompress_need_dict((*raw).adler as u32), c => panic!("unknown return code: {}", c), } } } +} +impl InflateBackend for Inflate { + fn make(zlib_header: bool, window_bits: u8) -> Self { + unsafe { + let state = StreamWrapper::default(); + let ret = mz_inflateInit2( + state.inner, + if zlib_header { + window_bits as c_int + } else { + -(window_bits as c_int) + }, + ); + assert_eq!(ret, 0); + Inflate { + inner: Stream { + stream_wrapper: state, + total_in: 0, + total_out: 0, + _marker: marker::PhantomData, + }, + } + } + } + + fn decompress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result { + unsafe { self.decompress_inner(input, output.as_mut_ptr(), output.len(), flush) } + } + fn decompress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushDecompress, + ) -> Result { + unsafe { self.decompress_inner(input, output.as_mut_ptr() as *mut _, output.len(), flush) } + } fn reset(&mut self, zlib_header: bool) { let bits = if zlib_header { @@ -304,37 +344,12 @@ pub inner: Stream, } -impl DeflateBackend for Deflate { - fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { - unsafe { - let state = StreamWrapper::default(); - let ret = mz_deflateInit2( - state.inner, - level.0 as c_int, - MZ_DEFLATED, - if zlib_header { - window_bits as c_int - } else { - -(window_bits as c_int) - }, - 8, - MZ_DEFAULT_STRATEGY, - ); - assert_eq!(ret, 0); - Deflate { - inner: Stream { - stream_wrapper: state, - total_in: 0, - total_out: 0, - _marker: marker::PhantomData, - }, - } - } - } - fn compress( +impl Deflate { + unsafe fn compress_inner( &mut self, input: &[u8], - output: &mut [u8], + output_ptr: *mut u8, + output_len: usize, flush: FlushCompress, ) -> Result { let raw = self.inner.stream_wrapper.inner; @@ -344,9 +359,9 @@ unsafe { (*raw).msg = ptr::null_mut(); (*raw).next_in = input.as_ptr() as *mut _; - (*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint; - (*raw).next_out = output.as_mut_ptr(); - (*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint; + (*raw).avail_in = input.len().min(c_uint::MAX as usize) as c_uint; + (*raw).next_out = output_ptr; + (*raw).avail_out = output_len.min(c_uint::MAX as usize) as c_uint; let rc = mz_deflate(raw, flush as c_int); @@ -354,7 +369,7 @@ // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64; - self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64; + self.inner.total_out += ((*raw).next_out as usize - output_ptr as usize) as u64; // reset these pointers so we don't accidentally read them later (*raw).next_in = ptr::null_mut(); (*raw).avail_in = 0; @@ -370,7 +385,51 @@ } } } +} +impl DeflateBackend for Deflate { + fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { + unsafe { + let state = StreamWrapper::default(); + let ret = mz_deflateInit2( + state.inner, + level.0 as c_int, + MZ_DEFLATED, + if zlib_header { + window_bits as c_int + } else { + -(window_bits as c_int) + }, + 8, + MZ_DEFAULT_STRATEGY, + ); + assert_eq!(ret, 0); + Deflate { + inner: Stream { + stream_wrapper: state, + total_in: 0, + total_out: 0, + _marker: marker::PhantomData, + }, + } + } + } + fn compress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result { + unsafe { self.compress_inner(input, output.as_mut_ptr(), output.len(), flush) } + } + fn compress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushCompress, + ) -> Result { + unsafe { self.compress_inner(input, output.as_mut_ptr() as *mut _, output.len(), flush) } + } fn reset(&mut self) { self.inner.total_in = 0; self.inner.total_out = 0; @@ -403,17 +462,19 @@ #[cfg(feature = "zlib-ng")] use libz_ng_sys as libz; - #[cfg(all(not(feature = "zlib-ng"), feature = "zlib-rs"))] + #[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))] use libz_rs_sys as libz; - #[cfg(all(not(feature = "zlib-ng"), feature = "cloudflare_zlib"))] + #[cfg( + // cloudflare-zlib + all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")), + )] use cloudflare_zlib_sys as libz; - #[cfg(all( - not(feature = "cloudflare_zlib"), - not(feature = "zlib-ng"), - not(feature = "zlib-rs") - ))] + #[cfg( + // libz-sys + all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")), + )] use libz_sys as libz; pub use libz::deflate as mz_deflate; @@ -431,6 +492,7 @@ pub use libz::Z_DEFLATED as MZ_DEFLATED; pub use libz::Z_FINISH as MZ_FINISH; pub use libz::Z_FULL_FLUSH as MZ_FULL_FLUSH; + pub use libz::Z_MEM_ERROR as MZ_MEM_ERROR; pub use libz::Z_NEED_DICT as MZ_NEED_DICT; pub use libz::Z_NO_FLUSH as MZ_NO_FLUSH; pub use libz::Z_OK as MZ_OK; @@ -441,13 +503,6 @@ pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15; - #[cfg(feature = "zlib-ng")] - const ZLIB_VERSION: &'static str = "2.1.0.devel\0"; - #[cfg(all(not(feature = "zlib-ng"), feature = "zlib-rs"))] - const ZLIB_VERSION: &'static str = "0.1.0\0"; - #[cfg(not(any(feature = "zlib-ng", feature = "zlib-rs")))] - const ZLIB_VERSION: &'static str = "1.2.8\0"; - pub unsafe extern "C" fn mz_deflateInit2( stream: *mut mz_stream, level: c_int, @@ -463,7 +518,7 @@ window_bits, mem_level, strategy, - ZLIB_VERSION.as_ptr() as *const c_char, + zlibVersion(), mem::size_of::() as c_int, ) } @@ -471,7 +526,7 @@ libz::inflateInit2_( stream, window_bits, - ZLIB_VERSION.as_ptr() as *const c_char, + zlibVersion(), mem::size_of::() as c_int, ) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,6 +2,15 @@ use crate::mem::{CompressError, DecompressError, FlushCompress, FlushDecompress, Status}; use crate::Compression; +use std::mem::MaybeUninit; + +fn initialize_buffer(output: &mut [MaybeUninit]) -> &mut [u8] { + // SAFETY: Here we zero-initialize the output and cast it to [u8] + unsafe { + output.as_mut_ptr().write_bytes(0, output.len()); + &mut *(output as *mut [MaybeUninit] as *mut [u8]) + } +} /// Traits specifying the interface of the backends. /// @@ -20,6 +29,14 @@ output: &mut [u8], flush: FlushDecompress, ) -> Result; + fn decompress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushDecompress, + ) -> Result { + self.decompress(input, initialize_buffer(output), flush) + } fn reset(&mut self, zlib_header: bool); } @@ -31,6 +48,14 @@ output: &mut [u8], flush: FlushCompress, ) -> Result; + fn compress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushCompress, + ) -> Result { + self.compress(input, initialize_buffer(output), flush) + } fn reset(&mut self); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/rust.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/rust.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/ffi/rust.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/ffi/rust.rs 2006-07-24 01:21:28.000000000 +0000 @@ -17,7 +17,7 @@ use crate::mem; // miniz_oxide doesn't provide any error messages (yet?) -#[derive(Default)] +#[derive(Clone, Default)] pub struct ErrorMessage; impl ErrorMessage { @@ -50,6 +50,16 @@ } } +impl From for MZFlush { + fn from(value: FlushDecompress) -> Self { + match value { + FlushDecompress::None => Self::None, + FlushDecompress::Sync => Self::Sync, + FlushDecompress::Finish => Self::Finish, + } + } +} + impl InflateBackend for Inflate { fn make(zlib_header: bool, _window_bits: u8) -> Self { let format = format_from_bool(zlib_header); @@ -67,9 +77,8 @@ output: &mut [u8], flush: FlushDecompress, ) -> Result { - let flush = MZFlush::new(flush as i32).unwrap(); - - let res = inflate::stream::inflate(&mut self.inner, input, output, flush); + let mz_flush = flush.into(); + let res = inflate::stream::inflate(&mut self.inner, input, output, mz_flush); self.total_in += res.bytes_consumed as u64; self.total_out += res.bytes_written as u64; @@ -123,6 +132,17 @@ } } +impl From for MZFlush { + fn from(value: FlushCompress) -> Self { + match value { + FlushCompress::None => Self::None, + FlushCompress::Partial | FlushCompress::Sync => Self::Sync, + FlushCompress::Full => Self::Full, + FlushCompress::Finish => Self::Finish, + } + } +} + impl DeflateBackend for Deflate { fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self { // Check in case the integer value changes at some point. @@ -145,8 +165,8 @@ output: &mut [u8], flush: FlushCompress, ) -> Result { - let flush = MZFlush::new(flush as i32).unwrap(); - let res = deflate::stream::deflate(&mut self.inner, input, output, flush); + let mz_flush = flush.into(); + let res = deflate::stream::deflate(&mut self.inner, input, output, mz_flush); self.total_in += res.bytes_consumed as u64; self.total_out += res.bytes_written as u64; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/bufread.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/bufread.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/bufread.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/bufread.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,9 +10,7 @@ fn copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize { let min = cmp::min(into.len(), from.len() - *pos); - for (slot, val) in into.iter_mut().zip(from[*pos..*pos + min].iter()) { - *slot = *val; - } + into[..min].copy_from_slice(&from[*pos..*pos + min]); *pos += min; min } @@ -82,17 +80,18 @@ return Ok(0); } let crc = self.inner.get_ref().crc(); - let ref arr = [ - (crc.sum() >> 0) as u8, - (crc.sum() >> 8) as u8, - (crc.sum() >> 16) as u8, - (crc.sum() >> 24) as u8, - (crc.amount() >> 0) as u8, + let calced_crc_bytes = crc.sum().to_le_bytes(); + let arr = [ + calced_crc_bytes[0], + calced_crc_bytes[1], + calced_crc_bytes[2], + calced_crc_bytes[3], + crc.amount() as u8, (crc.amount() >> 8) as u8, (crc.amount() >> 16) as u8, (crc.amount() >> 24) as u8, ]; - Ok(copy(into, arr, &mut self.pos)) + Ok(copy(into, &arr, &mut self.pos)) } } @@ -118,11 +117,11 @@ #[inline] fn finish(buf: &[u8; 8]) -> (u32, u32) { - let crc = ((buf[0] as u32) << 0) + let crc = (buf[0] as u32) | ((buf[1] as u32) << 8) | ((buf[2] as u32) << 16) | ((buf[3] as u32) << 24); - let amt = ((buf[4] as u32) << 0) + let amt = (buf[4] as u32) | ((buf[5] as u32) << 8) | ((buf[6] as u32) << 16) | ((buf[7] as u32) << 24); @@ -304,7 +303,7 @@ if *pos < buf.len() { *pos += read_into(self.reader.get_mut().get_mut(), &mut buf[*pos..])?; } else { - let (crc, amt) = finish(&buf); + let (crc, amt) = finish(buf); if crc != self.reader.crc().sum() || amt != self.reader.crc().amount() { self.state = GzState::End(Some(mem::take(header))); @@ -450,7 +449,7 @@ let compressed = { let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); - e.write(expected.as_ref()).unwrap(); + e.write_all(expected.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -87,7 +87,7 @@ } } -#[derive(Debug)] +#[derive(Debug, Default)] pub enum GzHeaderState { Start(u8, [u8; 10]), Xlen(Option>, u8, [u8; 2]), @@ -95,15 +95,10 @@ Filename(Option>), Comment(Option>), Crc(Option>, u8, [u8; 2]), + #[default] Complete, } -impl Default for GzHeaderState { - fn default() -> Self { - Self::Complete - } -} - #[derive(Debug, Default)] pub struct GzHeaderParser { state: GzHeaderState, @@ -120,7 +115,7 @@ } } - fn parse<'a, R: Read>(&mut self, r: &'a mut R) -> Result<()> { + fn parse(&mut self, r: &mut R) -> Result<()> { loop { match &mut self.state { GzHeaderState::Start(count, buffer) => { @@ -140,7 +135,7 @@ if self.flags & FRESERVED != 0 { return Err(bad_header()); } - self.header.mtime = ((buffer[4] as u32) << 0) + self.header.mtime = (buffer[4] as u32) | ((buffer[5] as u32) << 8) | ((buffer[6] as u32) << 16) | ((buffer[7] as u32) << 24); @@ -163,7 +158,7 @@ if let Some(crc) = crc { crc.update(buffer); } - let xlen = parse_le_u16(&buffer); + let xlen = parse_le_u16(buffer); self.header.extra = Some(vec![0; xlen as usize]); self.state = GzHeaderState::Extra(crc.take(), 0); } else { @@ -209,7 +204,7 @@ while (*count as usize) < buffer.len() { *count += read_into(r, &mut buffer[*count as usize..])? as u8; } - let stored_crc = parse_le_u16(&buffer); + let stored_crc = parse_le_u16(buffer); let calced_crc = crc.sum() as u16; if stored_crc != calced_crc { return Err(corrupt()); @@ -253,13 +248,11 @@ } // Read `r` up to the first nul byte, pushing non-nul bytes to `buffer`. -fn read_to_nul(r: &mut R, buffer: &mut Vec) -> Result<()> { +fn read_to_nul(r: &mut R, buffer: &mut Vec) -> Result<()> { let mut bytes = r.bytes(); loop { match bytes.next().transpose()? { - Some(byte) if byte == 0 => { - return Ok(()); - } + Some(0) => return Ok(()), Some(_) if buffer.len() == MAX_HEADER_BUF => { return Err(Error::new( ErrorKind::InvalidInput, @@ -277,7 +270,7 @@ } fn parse_le_u16(buffer: &[u8; 2]) -> u16 { - (buffer[0] as u16) | ((buffer[1] as u16) << 8) + u16::from_le_bytes(*buffer) } fn bad_header() -> Error { @@ -317,7 +310,7 @@ /// # Ok(()) /// # } /// ``` -#[derive(Debug)] +#[derive(Debug, Default)] pub struct GzBuilder { extra: Option>, filename: Option, @@ -326,22 +319,10 @@ mtime: u32, } -impl Default for GzBuilder { - fn default() -> Self { - Self::new() - } -} - impl GzBuilder { /// Create a new blank builder with no header by default. pub fn new() -> GzBuilder { - GzBuilder { - extra: None, - filename: None, - comment: None, - operating_system: None, - mtime: 0, - } + Self::default() } /// Configure the `mtime` field in the gzip header. @@ -421,8 +402,7 @@ let mut header = vec![0u8; 10]; if let Some(v) = extra { flg |= FEXTRA; - header.push((v.len() >> 0) as u8); - header.push((v.len() >> 8) as u8); + header.extend((v.len() as u16).to_le_bytes()); header.extend(v); } if let Some(filename) = filename { @@ -437,7 +417,7 @@ header[1] = 0x8b; header[2] = 8; header[3] = flg; - header[4] = (mtime >> 0) as u8; + header[4] = mtime as u8; header[5] = (mtime >> 8) as u8; header[6] = (mtime >> 16) as u8; header[7] = (mtime >> 24) as u8; @@ -464,7 +444,7 @@ use super::{read, write, GzBuilder, GzHeaderParser}; use crate::{Compression, GzHeader}; - use rand::{thread_rng, Rng}; + use rand::{rng, Rng}; #[test] fn roundtrip() { @@ -493,7 +473,7 @@ let mut w = write::GzEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { - let to_write = &v[..thread_rng().gen_range(0..v.len())]; + let to_write = &v[..rng().random_range(0..v.len())]; real.extend(to_write.iter().copied()); w.write_all(to_write).unwrap(); } @@ -532,7 +512,7 @@ if c & 1 != 0 { c = 0xedb88320 ^ (c >> 1); } else { - c = c >> 1; + c >>= 1; } } crc.crc_table[n] = c; @@ -571,7 +551,7 @@ .into_header(Compression::fast()); // Add a CRC to the header - header[3] = header[3] ^ super::FHCRC; + header[3] ^= super::FHCRC; let rfc1952_crc = Rfc1952Crc::new(); let crc32 = rfc1952_crc.crc(&header); let crc16 = crc32 as u16; @@ -594,7 +574,7 @@ #[test] fn fields() { - let r = vec![0, 2, 4, 6]; + let r = [0, 2, 4, 6]; let e = GzBuilder::new() .filename("foo.rs") .comment("bar") diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/read.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/read.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -316,16 +316,16 @@ } pub fn set_position(&mut self, pos: u64) { - return self.cursor.set_position(pos); + self.cursor.set_position(pos) } } impl Write for BlockingCursor { fn write(&mut self, buf: &[u8]) -> Result { - return self.cursor.write(buf); + self.cursor.write(buf) } fn flush(&mut self) -> Result<()> { - return self.cursor.flush(); + self.cursor.flush() } } @@ -345,7 +345,7 @@ } Ok(_n) => {} } - return r; + r } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/write.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/gz/write.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/gz/write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -93,11 +93,11 @@ while self.crc_bytes_written < 8 { let (sum, amt) = (self.crc.sum(), self.crc.amount()); let buf = [ - (sum >> 0) as u8, + sum as u8, (sum >> 8) as u8, (sum >> 16) as u8, (sum >> 24) as u8, - (amt >> 0) as u8, + amt as u8, (amt >> 8) as u8, (amt >> 16) as u8, (amt >> 24) as u8, @@ -294,11 +294,11 @@ return Err(corrupt()); } - let crc = ((self.crc_bytes[0] as u32) << 0) + let crc = (self.crc_bytes[0] as u32) | ((self.crc_bytes[1] as u32) << 8) | ((self.crc_bytes[2] as u32) << 16) | ((self.crc_bytes[3] as u32) << 24); - let amt = ((self.crc_bytes[4] as u32) << 0) + let amt = (self.crc_bytes[4] as u32) | ((self.crc_bytes[5] as u32) << 8) | ((self.crc_bytes[6] as u32) << 16) | ((self.crc_bytes[7] as u32) << 24); @@ -477,13 +477,13 @@ #[test] fn decode_writer_one_chunk() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); let n = decoder.write(&bytes[..]).unwrap(); - decoder.write(&bytes[n..]).unwrap(); + decoder.write_all(&bytes[n..]).unwrap(); decoder.try_finish().unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); @@ -493,7 +493,7 @@ #[test] fn decode_writer_partial_header() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); @@ -501,7 +501,7 @@ assert_eq!(decoder.write(&bytes[..5]).unwrap(), 5); let n = decoder.write(&bytes[5..]).unwrap(); if n < bytes.len() - 5 { - decoder.write(&bytes[n + 5..]).unwrap(); + decoder.write_all(&bytes[n + 5..]).unwrap(); } writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); @@ -522,7 +522,7 @@ assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12); let n = decoder.write(&bytes[12..]).unwrap(); if n < bytes.len() - 12 { - decoder.write(&bytes[n + 12..]).unwrap(); + decoder.write_all(&bytes[n + 12..]).unwrap(); } assert_eq!( decoder.header().unwrap().filename().unwrap(), @@ -547,7 +547,7 @@ assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12); let n = decoder.write(&bytes[12..]).unwrap(); if n < bytes.len() - 12 { - decoder.write(&bytes[n + 12..]).unwrap(); + decoder.write_all(&bytes[n + 12..]).unwrap(); } assert_eq!( decoder.header().unwrap().comment().unwrap(), @@ -561,13 +561,13 @@ #[test] fn decode_writer_exact_header() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); assert_eq!(decoder.write(&bytes[..10]).unwrap(), 10); - decoder.write(&bytes[10..]).unwrap(); + decoder.write_all(&bytes[10..]).unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); @@ -576,14 +576,14 @@ #[test] fn decode_writer_partial_crc() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); let l = bytes.len() - 5; let n = decoder.write(&bytes[..l]).unwrap(); - decoder.write(&bytes[n..]).unwrap(); + decoder.write_all(&bytes[n..]).unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); @@ -594,7 +594,7 @@ #[test] fn decode_multi_writer() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap().repeat(2); let mut writer = Vec::new(); @@ -617,7 +617,7 @@ fn decode_extra_data() { let compressed = { let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -17,20 +17,18 @@ //! backends, controlled through this crate's features: //! //! * `default`, or `rust_backend` - this implementation uses the `miniz_oxide` -//! crate which is a port of `miniz.c` (below) to Rust. This feature does not -//! require a C compiler and only requires Rust code. +//! crate which is a port of `miniz.c` to Rust. This feature does not +//! require a C compiler, and only uses safe Rust code. //! -//! * `zlib` - this feature will enable linking against the `libz` library, typically found on most -//! Linux systems by default. If the library isn't found to already be on the system it will be -//! compiled from source (this is a C library). -//! -//! There's various tradeoffs associated with each implementation, but in general you probably -//! won't have to tweak the defaults. The default choice is selected to avoid the need for a C -//! compiler at build time. `zlib-ng-compat` is useful if you're using zlib for compatibility but -//! want performance via zlib-ng's zlib-compat mode. `zlib` is useful if something else in your -//! dependencies links the original zlib so you cannot use zlib-ng-compat. The compression ratios -//! and performance of each of these feature should be roughly comparable, but you'll likely want -//! to run your own tests if you're curious about the performance. +//! * `zlib-rs` - this implementation utilizes the `zlib-rs` crate, a Rust rewrite of zlib. +//! This backend is the fastest, at the cost of some `unsafe` Rust code. +//! +//! Several backends implemented in C are also available. +//! These are useful in case you are already using a specific C implementation +//! and need the result of compression to be bit-identical. +//! See the crate's README for details on the available C backends. +//! +//! The `zlib-rs` backend typically outperforms all the C implementations. //! //! # Organization //! @@ -77,7 +75,7 @@ //! //! The [`MultiGzDecoder`] on the other hand will decode all members of a `gzip` file //! into one consecutive stream of bytes, which hides the underlying *members* entirely. -//! If a file contains contains non-gzip data after the gzip data, MultiGzDecoder will +//! If a file contains non-gzip data after the gzip data, MultiGzDecoder will //! emit an error after decoding the gzip data. This behavior matches the `gzip`, //! `gunzip`, and `zcat` command line tools. //! @@ -94,7 +92,7 @@ #![deny(missing_debug_implementations)] #![allow(trivial_numeric_casts)] #![cfg_attr(test, deny(warnings))] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(not(feature = "any_impl",))] compile_error!("You need to choose a zlib backend"); @@ -213,7 +211,7 @@ } /// Returns an integer representing the compression level, typically on a - /// scale of 0-9 + /// scale of 0-9. See [`new`](Self::new) for details about compression levels. pub fn level(&self) -> u32 { self.0 } @@ -230,5 +228,5 @@ use rand::Rng; use std::iter; - iter::repeat(()).map(|_| rand::thread_rng().gen()) + iter::repeat(()).map(|_| rand::rng().random()) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/mem.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/mem.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/mem.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/mem.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ use std::error::Error; use std::fmt; use std::io; +use std::mem::MaybeUninit; use crate::ffi::{self, Backend, Deflate, DeflateBackend, ErrorMessage, Inflate, InflateBackend}; use crate::Compression; @@ -43,12 +44,23 @@ /// in-memory data. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[non_exhaustive] +#[allow(clippy::unnecessary_cast)] pub enum FlushCompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to /// accumulate before producing output in order to maximize compression. None = ffi::MZ_NO_FLUSH as isize, + /// All pending output is flushed to the output buffer, but the output is + /// not aligned to a byte boundary. + /// + /// All input data so far will be available to the decompressor (as with + /// `Flush::Sync`). This completes the current deflate block and follows it + /// with an empty fixed codes block that is 10 bits long, and it assures + /// that enough bytes are output in order for the decompressor to finish the + /// block before the empty fixed code block. + Partial = ffi::MZ_PARTIAL_FLUSH as isize, + /// All pending output is flushed to the output buffer and the output is /// aligned on a byte boundary so that the decompressor can get all input /// data available so far. @@ -58,16 +70,6 @@ /// deflate block and follow it with an empty stored block. Sync = ffi::MZ_SYNC_FLUSH as isize, - /// All pending output is flushed to the output buffer, but the output is - /// not aligned to a byte boundary. - /// - /// All of the input data so far will be available to the decompressor (as - /// with `Flush::Sync`. This completes the current deflate block and follows - /// it with an empty fixed codes block that is 10 bites long, and it assures - /// that enough bytes are output in order for the decompressor to finish the - /// block before the empty fixed code block. - Partial = ffi::MZ_PARTIAL_FLUSH as isize, - /// All output is flushed as with `Flush::Sync` and the compression state is /// reset so decompression can restart from this point if previous /// compressed data has been damaged or if random access is desired. @@ -86,6 +88,7 @@ /// decompressing in-memory data. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[non_exhaustive] +#[allow(clippy::unnecessary_cast)] pub enum FlushDecompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to @@ -109,7 +112,7 @@ } /// The inner state for an error when decompressing -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) enum DecompressErrorInner { General { msg: ErrorMessage }, NeedsDictionary(u32), @@ -117,7 +120,7 @@ /// Error returned when a decompression object finds that the input stream of /// bytes was not a valid input stream of bytes. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct DecompressError(pub(crate) DecompressErrorInner); impl DecompressError { @@ -147,7 +150,7 @@ /// Error returned when a compression object is used incorrectly or otherwise /// generates an error. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CompressError { pub(crate) msg: ErrorMessage, } @@ -277,6 +280,7 @@ match rc { ffi::MZ_STREAM_ERROR => compress_failed(self.inner.inner.msg()), + #[allow(clippy::unnecessary_cast)] ffi::MZ_OK => Ok(unsafe { (*stream).adler } as u32), c => panic!("unknown return code: {}", c), } @@ -334,6 +338,20 @@ self.inner.compress(input, output, flush) } + /// Similar to [`Self::compress`] but accepts uninitialized buffer. + /// + /// If you want to avoid the overhead of zero initializing the + /// buffer and you don't want to use a [`Vec`], then please use + /// this API. + pub fn compress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushCompress, + ) -> Result { + self.inner.compress_uninit(input, output, flush) + } + /// Compresses the input data into the extra space of the output, consuming /// only as much input as needed and writing as much output as possible. /// @@ -348,12 +366,15 @@ output: &mut Vec, flush: FlushCompress, ) -> Result { - write_to_spare_capacity_of_vec(output, |out| { - let before = self.total_out(); - let ret = self.compress(input, out, flush); - let bytes_written = self.total_out() - before; - (bytes_written as usize, ret) - }) + // SAFETY: bytes_written is the number of bytes written into `out` + unsafe { + write_to_spare_capacity_of_vec(output, |out| { + let before = self.total_out(); + let ret = self.compress_uninit(input, out, flush); + let bytes_written = self.total_out() - before; + (bytes_written as usize, ret) + }) + } } } @@ -452,6 +473,20 @@ self.inner.decompress(input, output, flush) } + /// Similar to [`Self::decompress`] but accepts uninitialized buffer + /// + /// If you want to avoid the overhead of zero initializing the + /// buffer and you don't want to use a [`Vec`], then please use + /// this API. + pub fn decompress_uninit( + &mut self, + input: &[u8], + output: &mut [MaybeUninit], + flush: FlushDecompress, + ) -> Result { + self.inner.decompress_uninit(input, output, flush) + } + /// Decompresses the input data into the extra space in the output vector /// specified by `output`. /// @@ -472,12 +507,15 @@ output: &mut Vec, flush: FlushDecompress, ) -> Result { - write_to_spare_capacity_of_vec(output, |out| { - let before = self.total_out(); - let ret = self.decompress(input, out, flush); - let bytes_written = self.total_out() - before; - (bytes_written as usize, ret) - }) + // SAFETY: bytes_written is the number of bytes written into `out` + unsafe { + write_to_spare_capacity_of_vec(output, |out| { + let before = self.total_out(); + let ret = self.decompress_uninit(input, out, flush); + let bytes_written = self.total_out() - before; + (bytes_written as usize, ret) + }) + } } /// Specifies the decompression dictionary to use. @@ -493,6 +531,7 @@ ffi::inflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt) }; + #[allow(clippy::unnecessary_cast)] match rc { ffi::MZ_STREAM_ERROR => decompress_failed(self.inner.inner.msg()), ffi::MZ_DATA_ERROR => decompress_need_dict(unsafe { (*stream).adler } as u32), @@ -539,7 +578,7 @@ DecompressErrorInner::NeedsDictionary { .. } => Some("requires a dictionary"), }; match msg { - Some(msg) => write!(f, "deflate decompression error: {}", msg), + Some(msg) => write!(f, "deflate decompression error: {msg}"), None => write!(f, "deflate decompression error"), } } @@ -563,7 +602,7 @@ impl fmt::Display for CompressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.msg.get() { - Some(msg) => write!(f, "deflate compression error: {}", msg), + Some(msg) => write!(f, "deflate compression error: {msg}"), None => write!(f, "deflate compression error"), } } @@ -576,18 +615,20 @@ /// /// `writer` needs to return the number of bytes written (and can also return /// another arbitrary return value). -fn write_to_spare_capacity_of_vec( +/// +/// # Safety: +/// +/// The length returned by the `writer` must be equal to actual number of bytes written +/// to the uninitialized slice passed in and initialized. +unsafe fn write_to_spare_capacity_of_vec( output: &mut Vec, - writer: impl FnOnce(&mut [u8]) -> (usize, T), + writer: impl FnOnce(&mut [MaybeUninit]) -> (usize, T), ) -> T { let cap = output.capacity(); let len = output.len(); - output.resize(output.capacity(), 0); - let (bytes_written, ret) = writer(&mut output[len..]); - - let new_len = core::cmp::min(len + bytes_written, cap); // Sanitizes `bytes_written`. - output.resize(new_len, 0 /* unused */); + let (bytes_written, ret) = writer(output.spare_capacity_mut()); + output.set_len(cap.min(len + bytes_written)); // Sanitizes `bytes_written`. ret } @@ -604,7 +645,7 @@ #[test] fn issue51() { - let data = vec![ + let data = [ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xb3, 0xc9, 0x28, 0xc9, 0xcd, 0xb1, 0xe3, 0xe5, 0xb2, 0xc9, 0x48, 0x4d, 0x4c, 0xb1, 0xb3, 0x29, 0xc9, 0x2c, 0xc9, 0x49, 0xb5, 0x33, 0x31, 0x30, 0x51, 0xf0, 0xcb, 0x2f, 0x51, 0x70, 0xcb, 0x2f, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zio.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zio.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zio.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zio.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,7 +2,9 @@ use std::io::prelude::*; use std::mem; -use crate::{Compress, Decompress, DecompressError, FlushCompress, FlushDecompress, Status}; +use crate::{ + Compress, CompressError, Decompress, DecompressError, FlushCompress, FlushDecompress, Status, +}; #[derive(Debug)] pub struct Writer { @@ -12,6 +14,7 @@ } pub trait Ops { + type Error: Into; type Flush: Flush; fn total_in(&self) -> u64; fn total_out(&self) -> u64; @@ -20,16 +23,17 @@ input: &[u8], output: &mut [u8], flush: Self::Flush, - ) -> Result; + ) -> Result; fn run_vec( &mut self, input: &[u8], output: &mut Vec, flush: Self::Flush, - ) -> Result; + ) -> Result; } impl Ops for Compress { + type Error = CompressError; type Flush = FlushCompress; fn total_in(&self) -> u64 { self.total_in() @@ -42,20 +46,21 @@ input: &[u8], output: &mut [u8], flush: FlushCompress, - ) -> Result { - Ok(self.compress(input, output, flush).unwrap()) + ) -> Result { + self.compress(input, output, flush) } fn run_vec( &mut self, input: &[u8], output: &mut Vec, flush: FlushCompress, - ) -> Result { - Ok(self.compress_vec(input, output, flush).unwrap()) + ) -> Result { + self.compress_vec(input, output, flush) } } impl Ops for Decompress { + type Error = DecompressError; type Flush = FlushDecompress; fn total_in(&self) -> u64 { self.total_in() @@ -170,7 +175,9 @@ self.dump()?; let before = self.data.total_out(); - self.data.run_vec(&[], &mut self.buf, D::Flush::finish())?; + self.data + .run_vec(&[], &mut self.buf, Flush::finish()) + .map_err(Into::into)?; if before == self.data.total_out() { return Ok(()); } @@ -254,8 +261,8 @@ fn flush(&mut self) -> io::Result<()> { self.data - .run_vec(&[], &mut self.buf, D::Flush::sync()) - .unwrap(); + .run_vec(&[], &mut self.buf, Flush::sync()) + .map_err(Into::into)?; // Unfortunately miniz doesn't actually tell us when we're done with // pulling out all the data from the internal stream. To remedy this we @@ -266,8 +273,8 @@ self.dump()?; let before = self.data.total_out(); self.data - .run_vec(&[], &mut self.buf, D::Flush::none()) - .unwrap(); + .run_vec(&[], &mut self.buf, Flush::none()) + .map_err(Into::into)?; if before == self.data.total_out() { break; } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/bufread.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/bufread.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/bufread.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/bufread.rs 2006-07-24 01:21:28.000000000 +0000 @@ -132,6 +132,11 @@ /// This structure implements a [`Read`] interface. When read from, it reads /// compressed data from the underlying [`BufRead`] and provides the uncompressed data. /// +/// After reading a single member of the ZLIB data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// If you need the following bytes, call `into_inner()` after Ok(0) to +/// recover the underlying reader. +/// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// @@ -267,7 +272,7 @@ let compressed = { let mut e = write::ZlibEncoder::new(Vec::new(), Compression::default()); - e.write(expected.as_ref()).unwrap(); + e.write_all(expected.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,7 +7,7 @@ use std::io; use std::io::prelude::*; - use rand::{thread_rng, Rng}; + use rand::{rng, Rng}; use crate::zlib::{read, write}; use crate::Compression; @@ -18,7 +18,7 @@ let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { - let to_write = &v[..thread_rng().gen_range(0..v.len())]; + let to_write = &v[..rng().random_range(0..v.len())]; real.extend(to_write.iter().copied()); w.write_all(to_write).unwrap(); } @@ -47,7 +47,7 @@ let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { - let to_write = &v[..thread_rng().gen_range(0..v.len())]; + let to_write = &v[..rng().random_range(0..v.len())]; real.extend(to_write.iter().copied()); w.write_all(to_write).unwrap(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/read.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/read.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/read.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/read.rs 2006-07-24 01:21:28.000000000 +0000 @@ -129,6 +129,12 @@ /// This structure implements a [`Read`] interface. When read from, it reads /// compressed data from the underlying [`Read`] and provides the uncompressed data. /// +/// After reading a single member of the ZLIB data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// `ZlibDecoder` may have read additional bytes past the end of the ZLIB data. +/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader` +/// and use `bufread::ZlibDecoder` instead. +/// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/write.rs clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/write.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flate2/src/zlib/write.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flate2/src/zlib/write.rs 2006-07-24 01:21:28.000000000 +0000 @@ -180,6 +180,10 @@ /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// +/// After decoding a single member of the ZLIB data this writer will return the number of bytes up +/// to the end of the ZLIB member and subsequent writes will return Ok(0) allowing the caller to +/// handle any data following the ZLIB member. +/// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples @@ -356,7 +360,7 @@ fn decode_extra_data() { let compressed = { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write(STR.as_ref()).unwrap(); + e.write_all(STR.as_ref()).unwrap(); let mut b = e.finish().unwrap(); b.push(b'x'); b diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/flume/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/flume/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"378edfec4dde51dee9c0d1e8285d88b3d218cb9b8b42ffa3e27405661c23b0b6","Cargo.lock":"cc14608e4a0c130f6f898cc6187e3b8964639f6c960bc9c08589dcac06506526","Cargo.toml":"6246515094dda94c71890606c39275b555aed886b5f4c789eb362ce7b1eea40f","LICENSE-APACHE":"d8621ec2eee5b9ca3c65f8492505f3590de8574fac0fdf5132a77232dba47abc","LICENSE-MIT":"30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652","README.md":"48f7ca4326cfcd3440931e5c82fc21f7b8a6f40041bc94be817c291ad71b6c5b","benches/basic.rs":"61ecb5f7c092b82382cc20e73ca84677dd4973cc358ea6bff15f92fda227b481","examples/async.rs":"7a0bb8848d94bd1fa9a857ffba0b3fbea6d57d7058ed65d2a7cbcf8518ec8652","examples/perf.rs":"52b67c619932a283ad9109c5fe5b47d32f7d3e7533356170047b686dfac330c9","examples/select.rs":"7659b015889545a59b9bce046fc353fea7bcaa9d54cb59f6bd5c002e15872909","examples/simple.rs":"f96d308b808b5fd66ca03dac9f09c13e5f13141992698551503415a411f6596a","src/async.rs":"851b0db2f8115eb222a9eb3c39d3dcdd8699c5b8e757580f26a03ca71c88d0e4","src/lib.rs":"36f84973b6bb45e54161dfb8eb574b30bace69d4b382e7fe8669d5636473d9ea","src/select.rs":"940cbdfbb26b9a2811bf42df3b26f1a619bd71896b8a6b6f2cdbb350c4fab270","src/signal.rs":"20a1732fdbfe888b9a25438bf16a185393f18fb1ad795926fae969c6817fe43b","tests/after.rs":"53e17263eab8eb733f575e4d1d43e054c6d22556d36e105f3f87c4cfb891880c","tests/array.rs":"2b071429d678e07ca52b79b4792120816a1ec7e64afd29c5781ddddbbbd7888b","tests/async.rs":"45bce43e990694578cf03c27dcf112df8d9ec1806e7c1be866885d76bb5abf85","tests/basic.rs":"0606408fe5ff1512839d43cc5c5f6a98c1e09fe919b5ad843643b5019926100b","tests/check_same_channel.rs":"e9e313d1ada50ac0ab0b9bcf19b901efd8cc226902edac62a8d573cea54e06ca","tests/golang.rs":"9e821cefd322a2353b288c7368902028daca643648da2e223ec1174c0e93e4ef","tests/iter.rs":"82d4f7acd20c9b10d2623211e71f5b6c37e4dafda2e13c871008c03995d76ced","tests/list.rs":"5885ee800d5c93b410d3bfa12d834fd817fd3362bca15a08b0aa7f84de58432e","tests/method_sharing.rs":"4d6c867e689254840ecbb1ae8a70ab3226d45bf92282e3bd2681c83726983ffa","tests/mpsc.rs":"965e18abbfcdebec09380f8ec9bb62e5556ad2aa0176ed088ce091994c1d2500","tests/never.rs":"cb838011c6f39c150c67e6836eb880300d53c22a2ea0312cdec999efb779ca29","tests/ready.rs":"5e1234ce49e8cbf89ec4f28bd2f4fe10641891bf6a7915d2fef6f9ab0c343997","tests/same_channel.rs":"71524e90dc364cc2c8085a9517757abe55f59a25b95600029abb283bc8677ad9","tests/select.rs":"67f8a647a7976f0d77673f4cc8d03b74690f3e8578c47e1bc64caeab68dd7df7","tests/select_macro.rs":"32793ac9775879e72ae3ce3975aa87f7407c6e7023d3d85f50f06a3ac5e308a3","tests/stream.rs":"c6d9500813d7216fd514f35dadb1b7b58282def553f40d76b37032221bb05cd6","tests/thread_locals.rs":"ad92e07a4ef5c3dd8b6ff8620161ab93963b3de241a680db551f2be60c8e3853","tests/tick.rs":"35fabd118073decf0cd830e9245c77a1a2e19227f7b4f73d239589728a591601","tests/zero.rs":"23a15a51681596716d5882242cd2c8cd0925c6ea2d0ef289f80775f3f2d6d10c"},"package":"55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/flume/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/flume/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -# Unreleased - -### Added - -### Removed - -### Changed - -### Fixed - -# [0.11.0] - 2023-08-16 - -### Added - -- `WeakSender`, a sender that doesn't keep the channel open -- `Sender/Receiver::sender_count/receiver_count`, a way to query the number of senders and receivers attached to a channel -- `Sender/Receiver::same_channel`, a way to determine whether senders and receivers are attached to the same channel - -### Changed - -- Relaxed some API features -- Make all remaining spinlocks opt-in - -### Fixed - -- Fixed a rare race condition in the async implementation - -# [0.10.14] - 2022-07-21 - -### Fixed - -- Fixed unbounded memory usage in `RecvFut::poll_inner` - -# [0.10.13] - 2022-06-10 - -### Added - -- `SendSink::sender`, to get the sender of a `SendSink` - -# [0.10.12] - 2022-03-10 - -### Changed - -- Updated `nanorand` to 0.7 - -# [0.10.11] - 2022-02-14 - -### Fixed - -- Out-of-order bug when using channels asynchronously - -# [0.10.10] - 2022-01-11 - -### Added - -- `From` and `From` impls for other error types -- Marked futures as `#[must_use]` - -### Changes - -- Switched to scheduler-driven locking by default, with a `spin` feature to reenable the old behaviour -- Minor doc improvements - -# [0.10.9] - 2021-08-25 - -### Changed - -- Switched from `spinning_top` to `spin` - -# [0.10.8] - 2021-08-06 - -### Changed - -- Updated `nanorand` to `0.6` - -# [0.10.7] - 2021-06-10 - -### Fixed - -- Removed accidental nightly-only syntax - -# [0.10.6] - 2021-06-10 - -### Added - -- `fn into_inner(self) -> T` for send errors, allowing for easy access to the unsent message - -# [0.10.5] - 2021-04-26 - -### Added - -- `is_disconnected`, `is_empty`, `is_full`, `len`, and `capacity` on future types - -# [0.10.4] - 2021-04-12 - -### Fixed - -- Shutdown-related race condition with async recv that caused spurious errors - -# [0.10.3] - 2021-04-09 - -### Fixed - -- Compilation error when enabling `select` without `eventual_fairness` - -# [0.10.2] - 2021-02-07 - -### Fixed - -- Incorrect pointer comparison in `Selector` causing missing receives - -# [0.10.1] - 2020-12-30 - -### Removed - -- Removed `T: Unpin` requirement from async traits using `pin_project` - -# [0.10.0] - 2020-12-09 - -### Changed - -- Renamed `SendFuture` to `SendFut` to be consistent with `RecvFut` -- Improved async-related documentation - -### Fixed - -- Updated `nanorand` to address security advisory diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/flume/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 @@ -1,1312 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" -dependencies = [ - "memchr", -] - -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix", - "slab", - "socket2", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" -dependencies = [ - "async-io", - "async-lock", - "autocfg", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "signal-hook", - "windows-sys", -] - -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-attributes", - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" - -[[package]] -name = "atomic-waker" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "blocking" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "log", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap", - "unicode-width", -] - -[[package]] -name = "concurrent-queue" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "csv" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "flume" -version = "0.11.0" -dependencies = [ - "async-std", - "criterion", - "crossbeam-channel", - "crossbeam-utils", - "futures", - "futures-core", - "futures-sink", - "nanorand", - "rand", - "spin", - "tokio", - "waker-fn", -] - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "parking" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" - -[[package]] -name = "pin-project-lite" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "regex" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tokio" -version = "1.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" -dependencies = [ - "backtrace", - "pin-project-lite", - "tokio-macros", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "value-bag" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.28", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/flume/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -name = "flume" -version = "0.11.0" -authors = ["Joshua Barretto "] -exclude = [ - "/.github", - "/misc", -] -description = "A blazingly fast multi-producer channel" -documentation = "https://docs.rs/flume" -readme = "README.md" -keywords = [ - "mpsc", - "fifo", - "channel", - "thread", - "mpmc", -] -categories = [ - "concurrency", - "data-structures", -] -license = "Apache-2.0/MIT" -repository = "https://github.com/zesterer/flume" - -[[bench]] -name = "basic" -harness = false - -[dependencies.futures-core] -version = "0.3" -optional = true -default_features = false - -[dependencies.futures-sink] -version = "0.3" -optional = true -default_features = false - -[dependencies.nanorand] -version = "0.7" -features = ["getrandom"] -optional = true - -[dependencies.spin1] -version = "0.9.8" -features = ["mutex"] -package = "spin" - -[dev-dependencies.async-std] -version = "1.9.0" -features = [ - "attributes", - "unstable", -] - -[dev-dependencies.criterion] -version = "0.3.4" - -[dev-dependencies.crossbeam-channel] -version = "0.5.5" - -[dev-dependencies.crossbeam-utils] -version = "0.8.10" - -[dev-dependencies.futures] -version = "^0.3" -features = ["std"] - -[dev-dependencies.rand] -version = "0.8.3" - -[dev-dependencies.tokio] -version = "^1.16.1" -features = [ - "rt", - "macros", -] - -[dev-dependencies.waker-fn] -version = "1.1.0" - -[features] -async = [ - "futures-sink", - "futures-core", -] -default = [ - "async", - "select", - "eventual-fairness", -] -eventual-fairness = [ - "select", - "nanorand", -] -select = [] -spin = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/flume/LICENSE-APACHE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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 - - http://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. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/flume/LICENSE-MIT 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/README.md clamav-1.4.6+dfsg/.cargo/vendor/flume/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/flume/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -# Flume - -A blazingly fast multi-producer, multi-consumer channel. - -[![Cargo](https://img.shields.io/crates/v/flume.svg)]( -https://crates.io/crates/flume) -[![Documentation](https://docs.rs/flume/badge.svg)]( -https://docs.rs/flume) -[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)]( -https://github.com/zesterer/flume) -![actions-badge](https://github.com/zesterer/flume/workflows/Rust/badge.svg?branch=master) - -```rust -use std::thread; - -fn main() { - println!("Hello, world!"); - - let (tx, rx) = flume::unbounded(); - - thread::spawn(move || { - (0..10).for_each(|i| { - tx.send(i).unwrap(); - }) - }); - - let received: u32 = rx.iter().sum(); - - assert_eq!((0..10).sum::(), received); -} -``` - -## Why Flume? - -- **Featureful**: Unbounded, bounded and rendezvous queues -- **Fast**: Always faster than `std::sync::mpsc` and sometimes `crossbeam-channel` -- **Safe**: No `unsafe` code anywhere in the codebase! -- **Flexible**: `Sender` and `Receiver` both implement `Send + Sync + Clone` -- **Familiar**: Drop-in replacement for `std::sync::mpsc` -- **Capable**: Additional features like MPMC support and send timeouts/deadlines -- **Simple**: Few dependencies, minimal codebase, fast to compile -- **Asynchronous**: `async` support, including mix 'n match with sync code -- **Ergonomic**: Powerful `select`-like interface - -## Usage - -To use Flume, place the following line under the `[dependencies]` section in your `Cargo.toml`: - -```toml -flume = "x.y" -``` - -## Cargo Features - -Flume comes with several optional features: - -- `spin`: use spinlocks instead of OS-level synchronisation primitives internally for some kind of data access (may be more performant on a small number of platforms for specific workloads) - -- `select`: Adds support for the [`Selector`](https://docs.rs/flume/latest/flume/select/struct.Selector.html) API, allowing a thread to wait on several channels/operations at once - -- `async`: Adds support for the [async API](https://docs.rs/flume/latest/flume/async/index.html), including on otherwise synchronous channels - -- `eventual-fairness`: Use randomness in the implementation of `Selector` to avoid biasing/saturating certain events over others - -You can enable these features by changing the dependency in your `Cargo.toml` like so: - -```toml -flume = { version = "x.y", default-features = false, features = ["async", "select"] } -``` - -## [Benchmarks](https://what-if.xkcd.com/147/) - -Although Flume has its own extensive benchmarks, don't take it from here that Flume is quick. -The following graph is from the `crossbeam-channel` benchmark suite. - -Tests were performed on an AMD Ryzen 7 3700x with 8/16 cores running Linux kernel 5.11.2 with the bfq scheduler. - -# Flume benchmarks (crossbeam benchmark suite) - -## License - -Flume is licensed under either of: - -- Apache License 2.0, (http://www.apache.org/licenses/LICENSE-2.0) - -- MIT license (http://opensource.org/licenses/MIT) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/benches/basic.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/benches/basic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/benches/basic.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/benches/basic.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,474 +0,0 @@ -#[macro_use] -extern crate criterion; - -use std::{ - sync::mpsc, - thread, - fmt::Debug, -}; -use criterion::{Criterion, Bencher, black_box}; -use std::time::Instant; - -trait Sender: Clone + Send + Sized + 'static { - type Item: Debug + Default; - type BoundedSender: Sender; - type Receiver: Receiver; - - fn unbounded() -> (Self, Self::Receiver); - fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver); - fn send(&self, msg: Self::Item); -} - -trait Receiver: Send + Sized + 'static { - type Item: Default; - fn recv(&self) -> Self::Item; - fn iter(&self) -> Box + '_>; -} - -impl Sender for flume::Sender { - type Item = T; - type BoundedSender = Self; - type Receiver = flume::Receiver; - - fn unbounded() -> (Self, Self::Receiver) { - flume::unbounded() - } - - fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) { - flume::bounded(n) - } - - fn send(&self, msg: T) { - flume::Sender::send(self, msg).unwrap(); - } -} - -impl Receiver for flume::Receiver { - type Item = T; - - fn recv(&self) -> Self::Item { - flume::Receiver::recv(self).unwrap() - } - - fn iter(&self) -> Box + '_> { - Box::new(std::iter::from_fn(move || flume::Receiver::recv(self).ok())) - } -} - -impl Sender for crossbeam_channel::Sender { - type Item = T; - type BoundedSender = Self; - type Receiver = crossbeam_channel::Receiver; - - fn unbounded() -> (Self, Self::Receiver) { - crossbeam_channel::unbounded() - } - - fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) { - crossbeam_channel::bounded(n) - } - - fn send(&self, msg: T) { - crossbeam_channel::Sender::send(self, msg).unwrap(); - } -} - -impl Receiver for crossbeam_channel::Receiver { - type Item = T; - - fn recv(&self) -> Self::Item { - crossbeam_channel::Receiver::recv(self).unwrap() - } - - fn iter(&self) -> Box + '_> { - Box::new(crossbeam_channel::Receiver::iter(self)) - } -} - -impl Sender for mpsc::Sender { - type Item = T; - type BoundedSender = mpsc::SyncSender; - type Receiver = mpsc::Receiver; - - fn unbounded() -> (Self, Self::Receiver) { - mpsc::channel() - } - - fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) { - mpsc::sync_channel(n) - } - - fn send(&self, msg: T) { - mpsc::Sender::send(self, msg).unwrap(); - } -} - -impl Sender for mpsc::SyncSender { - type Item = T; - type BoundedSender = Self; - type Receiver = mpsc::Receiver; - - fn unbounded() -> (Self, Self::Receiver) { unimplemented!() } - fn bounded(_: usize) -> (Self::BoundedSender, Self::Receiver) { unimplemented!() } - - fn send(&self, msg: T) { - mpsc::SyncSender::send(self, msg).unwrap(); - } -} - -impl Receiver for mpsc::Receiver { - type Item = T; - - fn recv(&self) -> Self::Item { - mpsc::Receiver::recv(self).unwrap() - } - - fn iter(&self) -> Box + '_> { - Box::new(mpsc::Receiver::iter(self)) - } -} - -fn test_create(b: &mut Bencher) { - b.iter(|| S::unbounded()); -} - -fn test_oneshot(b: &mut Bencher) { - b.iter(|| { - let (tx, rx) = S::unbounded(); - tx.send(Default::default()); - black_box(rx.recv()); - }); -} - -fn test_inout(b: &mut Bencher) { - let (tx, rx) = S::unbounded(); - b.iter(|| { - tx.send(Default::default()); - black_box(rx.recv()); - }); -} - -fn test_hydra(b: &mut Bencher, thread_num: usize, msg_num: usize) { - let (main_tx, main_rx) = S::unbounded(); - - let mut txs = Vec::new(); - for _ in 0..thread_num { - let main_tx = main_tx.clone(); - let (tx, rx) = S::unbounded(); - txs.push(tx); - - thread::spawn(move || { - for msg in rx.iter() { - main_tx.send(msg); - } - }); - } - - drop(main_tx); - - b.iter(|| { - for tx in &txs { - for _ in 0..msg_num { - tx.send(Default::default()); - } - } - - for _ in 0..thread_num { - for _ in 0..msg_num { - black_box(main_rx.recv()); - } - } - }); -} - -fn test_kitsune(b: &mut Bencher, thread_num: usize, msg_num: usize) - where S::Receiver: Clone -{ - let (out_tx, out_rx) = S::unbounded(); - let (in_tx, in_rx) = S::unbounded(); - - for _ in 0..thread_num { - let in_tx = in_tx.clone(); - let out_rx = out_rx.clone(); - - thread::spawn(move || { - for msg in out_rx.iter() { - in_tx.send(msg); - } - }); - } - - b.iter(|| { - for _ in 0..thread_num { - for _ in 0..msg_num { - out_tx.send(Default::default()); - } - } - - for _ in 0..thread_num { - for _ in 0..msg_num { - black_box(in_rx.recv()); - } - } - }); -} - -fn test_robin_u(b: &mut Bencher, thread_num: usize, msg_num: usize) { - let (mut main_tx, main_rx) = S::unbounded(); - - for _ in 0..thread_num { - let (mut tx, rx) = S::unbounded(); - std::mem::swap(&mut tx, &mut main_tx); - - thread::spawn(move || { - for msg in rx.iter() { - tx.send(msg); - } - }); - } - - b.iter(|| { - for _ in 0..msg_num { - main_tx.send(Default::default()); - } - - for _ in 0..msg_num { - black_box(main_rx.recv()); - } - }); -} - -fn test_robin_b(b: &mut Bencher, thread_num: usize, msg_num: usize) { - let (mut main_tx, main_rx) = S::bounded(1); - - for _ in 0..thread_num { - let (mut tx, rx) = S::bounded(1); - std::mem::swap(&mut tx, &mut main_tx); - - thread::spawn(move || { - for msg in rx.iter() { - tx.send(msg); - } - }); - } - - b.iter(|| { - let main_tx = main_tx.clone(); - thread::spawn(move || { - for _ in 0..msg_num { - main_tx.send(Default::default()); - } - }); - - for _ in 0..msg_num { - black_box(main_rx.recv()); - } - }); -} - -fn test_mpsc_bounded_no_wait(b: &mut Bencher, thread_num: u64) { - b.iter_custom(|iters| { - let iters = iters * 1000; - let (tx, rx) = S::bounded(iters as usize); - let start = Instant::now(); - - crossbeam_utils::thread::scope(|scope| { - for _ in 0..thread_num { - let tx = tx.clone(); - scope.spawn(move |_| { - for _ in 0..iters / thread_num { - tx.send(Default::default()); - } - }); - } - - for _ in 0..iters - ((iters / thread_num) * thread_num) { - tx.send(Default::default()); - } - - for _ in 0..iters { - black_box(rx.recv()); - } - }) - .unwrap(); - - start.elapsed() - }) -} - -fn test_mpsc_bounded(b: &mut Bencher, bound: usize, thread_num: usize) { - b.iter_custom(|iters| { - let (tx, rx) = S::bounded(bound); - let start = Instant::now(); - - crossbeam_utils::thread::scope(|scope| { - let msgs = iters as usize * bound.max(1); - - for _ in 0..thread_num { - let tx = tx.clone(); - scope.spawn(move |_| { - for _ in 0..msgs / thread_num as usize { - tx.send(Default::default()); - } - }); - } - - scope.spawn(move |_| { - // Remainder - for _ in 0..msgs - (msgs / thread_num as usize * thread_num) { - tx.send(Default::default()); - } - }); - - for _ in 0..msgs { - black_box(rx.recv()); - } - }) - .unwrap(); - - start.elapsed() - }) -} - -fn create(b: &mut Criterion) { - b.bench_function("create-flume", |b| test_create::>(b)); - b.bench_function("create-crossbeam", |b| test_create::>(b)); - b.bench_function("create-std", |b| test_create::>(b)); -} - -fn oneshot(b: &mut Criterion) { - b.bench_function("oneshot-flume", |b| test_oneshot::>(b)); - b.bench_function("oneshot-crossbeam", |b| test_oneshot::>(b)); - b.bench_function("oneshot-std", |b| test_oneshot::>(b)); -} - -fn inout(b: &mut Criterion) { - b.bench_function("inout-flume", |b| test_inout::>(b)); - b.bench_function("inout-crossbeam", |b| test_inout::>(b)); - b.bench_function("inout-std", |b| test_inout::>(b)); -} - -fn hydra_32t_1m(b: &mut Criterion) { - b.bench_function("hydra-32t-1m-flume", |b| test_hydra::>(b, 32, 1)); - b.bench_function("hydra-32t-1m-crossbeam", |b| test_hydra::>(b, 32, 1)); - b.bench_function("hydra-32t-1m-std", |b| test_hydra::>(b, 32, 1)); -} - -fn hydra_32t_1000m(b: &mut Criterion) { - b.bench_function("hydra-32t-1000m-flume", |b| test_hydra::>(b, 32, 1000)); - b.bench_function("hydra-32t-1000m-crossbeam", |b| test_hydra::>(b, 32, 1000)); - b.bench_function("hydra-32t-1000m-std", |b| test_hydra::>(b, 32, 1000)); -} - -fn hydra_256t_1m(b: &mut Criterion) { - b.bench_function("hydra-256t-1m-flume", |b| test_hydra::>(b, 256, 1)); - b.bench_function("hydra-256t-1m-crossbeam", |b| test_hydra::>(b, 256, 1)); - b.bench_function("hydra-256t-1m-std", |b| test_hydra::>(b, 256, 1)); -} - -fn hydra_1t_1000m(b: &mut Criterion) { - b.bench_function("hydra-1t-1000m-flume", |b| test_hydra::>(b, 1, 1000)); - b.bench_function("hydra-1t-1000m-crossbeam", |b| test_hydra::>(b, 1, 1000)); - b.bench_function("hydra-1t-1000m-std", |b| test_hydra::>(b, 1, 1000)); -} - -fn hydra_4t_10000m(b: &mut Criterion) { - b.bench_function("hydra-4t-10000m-flume", |b| test_hydra::>(b, 4, 10000)); - b.bench_function("hydra-4t-10000m-crossbeam", |b| test_hydra::>(b, 4, 10000)); - b.bench_function("hydra-4t-10000m-std", |b| test_hydra::>(b, 4, 10000)); -} - -fn kitsune_32t_1m(b: &mut Criterion) { - b.bench_function("kitsune-32t-1m-flume", |b| test_kitsune::>(b, 32, 1)); - b.bench_function("kitsune-32t-1m-crossbeam", |b| test_kitsune::>(b, 32, 1)); - //b.bench_function("kitsune-32t-1m-std", |b| test_kitsune::>(b, 32, 1)); -} - -fn kitsune_32t_1000m(b: &mut Criterion) { - b.bench_function("kitsune-32t-1000m-flume", |b| test_kitsune::>(b, 32, 1000)); - b.bench_function("kitsune-32t-1000m-crossbeam", |b| test_kitsune::>(b, 32, 1000)); - //b.bench_function("kitsune-32t-1000m-std", |b| test_kitsune::>(b, 32, 1000)); -} - -fn kitsune_256t_1m(b: &mut Criterion) { - b.bench_function("kitsune-256t-1m-flume", |b| test_kitsune::>(b, 256, 1)); - b.bench_function("kitsune-256t-1m-crossbeam", |b| test_kitsune::>(b, 256, 1)); - //b.bench_function("kitsune-256t-1m-std", |b| test_kitsune::>(b, 256, 1)); -} - -fn kitsune_1t_1000m(b: &mut Criterion) { - b.bench_function("kitsune-1t-1000m-flume", |b| test_kitsune::>(b, 1, 1000)); - b.bench_function("kitsune-1t-1000m-crossbeam", |b| test_kitsune::>(b, 1, 1000)); - //b.bench_function("kitsune-1t-1000m-std", |b| test_kitsune::>(b, 1, 1000)); -} - -fn kitsune_4t_10000m(b: &mut Criterion) { - b.bench_function("kitsune-4t-10000m-flume", |b| test_kitsune::>(b, 4, 10000)); - b.bench_function("kitsune-4t-10000m-crossbeam", |b| test_kitsune::>(b, 4, 10000)); - //b.bench_function("kitsune-4t-10000m-std", |b| test_kitsune::>(b, 4, 10000)); -} - -fn robin_u_32t_1m(b: &mut Criterion) { - b.bench_function("robin-u-32t-1m-flume", |b| test_robin_u::>(b, 32, 1)); - b.bench_function("robin-u-32t-1m-crossbeam", |b| test_robin_u::>(b, 32, 1)); - b.bench_function("robin-u-32t-1m-std", |b| test_robin_u::>(b, 32, 1)); -} - -fn robin_u_4t_1000m(b: &mut Criterion) { - b.bench_function("robin-u-4t-1000m-flume", |b| test_robin_u::>(b, 4, 1000)); - b.bench_function("robin-u-4t-1000m-crossbeam", |b| test_robin_u::>(b, 4, 1000)); - b.bench_function("robin-u-4t-1000m-std", |b| test_robin_u::>(b, 4, 1000)); -} - -fn robin_b_32t_16m(b: &mut Criterion) { - b.bench_function("robin-b-32t-16m-flume", |b| test_robin_b::>(b, 32, 16)); - b.bench_function("robin-b-32t-16m-crossbeam", |b| test_robin_b::>(b, 32, 16)); - b.bench_function("robin-b-32t-16m-std", |b| test_robin_b::>(b, 32, 16)); -} - -fn robin_b_4t_1000m(b: &mut Criterion) { - b.bench_function("robin-b-4t-1000m-flume", |b| test_robin_b::>(b, 4, 1000)); - b.bench_function("robin-b-4t-1000m-crossbeam", |b| test_robin_b::>(b, 4, 1000)); - b.bench_function("robin-b-4t-1000m-std", |b| test_robin_b::>(b, 4, 1000)); -} - -fn mpsc_bounded_no_wait_4t(b: &mut Criterion) { - b.bench_function("mpsc-bounded-no-wait-4t-flume", |b| test_mpsc_bounded_no_wait::>(b, 4)); - b.bench_function("mpsc-bounded-no-wait-4t-crossbeam", |b| test_mpsc_bounded_no_wait::>(b, 4)); - b.bench_function("mpsc-bounded-no-wait-4t-std", |b| test_mpsc_bounded_no_wait::>(b, 4)); -} - -fn mpsc_bounded_4t(b: &mut Criterion) { - for bound in &[0, 1, 10, 50, 10_000] { - let text = format!("mpsc-bounded-small-4t-{}m-", bound); - let bound = *bound; - - b.bench_function(&format!("{}{}", text, "flume"), |b| test_mpsc_bounded::>(b, bound, 4)); - b.bench_function(&format!("{}{}", text, "crossbeam"), |b| test_mpsc_bounded::>(b, bound, 4)); - b.bench_function(&format!("{}{}", text, "std"), |b| test_mpsc_bounded::>(b, bound, 4)); - } -} - -criterion_group!( - compare, - create, - oneshot, - inout, - hydra_32t_1m, - hydra_32t_1000m, - hydra_256t_1m, - hydra_1t_1000m, - hydra_4t_10000m, - robin_b_32t_16m, - robin_b_4t_1000m, - robin_u_32t_1m, - robin_u_4t_1000m, - mpsc_bounded_no_wait_4t, - mpsc_bounded_4t, - kitsune_32t_1m, - kitsune_32t_1000m, - kitsune_256t_1m, - kitsune_1t_1000m, - kitsune_4t_10000m, -); -criterion_main!(compare); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/async.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/async.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/async.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/async.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#[cfg(feature = "async")] -#[async_std::main] -async fn main() { - let (tx, rx) = flume::bounded(1); - - let t = async_std::task::spawn(async move { - while let Ok(msg) = rx.recv_async().await { - println!("Received: {}", msg); - } - }); - - tx.send_async("Hello, world!").await.unwrap(); - tx.send_async("How are you today?").await.unwrap(); - - drop(tx); - - t.await; -} - -#[cfg(not(feature = "async"))] -fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/perf.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/perf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/perf.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/perf.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -fn main() { - let thread_num = 32; - let msg_num = 16; - - let (mut main_tx, main_rx) = flume::bounded::<()>(1); - - for _ in 0..thread_num { - let (mut tx, rx) = flume::bounded(1); - std::mem::swap(&mut tx, &mut main_tx); - - std::thread::spawn(move || { - for msg in rx.iter() { - tx.send(msg).unwrap(); - } - }); - } - - for _ in 0..1000 { - let main_tx = main_tx.clone(); - std::thread::spawn(move || { - for _ in 0..msg_num { - main_tx.send(Default::default()).unwrap(); - } - }); - - for _ in 0..msg_num { - main_rx.recv().unwrap(); - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/select.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/select.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/select.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/select.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#[cfg(feature = "select")] -use flume::Selector; - -#[cfg(feature = "select")] -fn main() { - // Create two channels - let (red_tx, red_rx) = flume::unbounded(); - let (blue_tx, blue_rx) = flume::unbounded(); - - // Spawn two threads that each send a message into their respective channel - std::thread::spawn(move || { let _ = red_tx.send("Red"); }); - std::thread::spawn(move || { let _ = blue_tx.send("Blue"); }); - - // Race them to see which one sends their message first - let winner = Selector::new() - .recv(&red_rx, |msg| msg) - .recv(&blue_rx, |msg| msg) - .wait() - .unwrap(); - - println!("{} won!", winner); -} - -#[cfg(not(feature = "select"))] -fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/simple.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/simple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/examples/simple.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/examples/simple.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -use std::thread; - -fn main() { - let (tx, rx) = flume::unbounded(); - - let t = thread::spawn(move || { - for msg in rx.iter() { - println!("Received: {}", msg); - } - }); - - tx.send("Hello, world!").unwrap(); - tx.send("How are you today?").unwrap(); - - drop(tx); - - t.join().unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/src/async.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/src/async.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/src/async.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/src/async.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,543 +0,0 @@ -//! Futures and other types that allow asynchronous interaction with channels. - -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll, Waker}, - any::Any, - ops::Deref, -}; -use crate::*; -use futures_core::{stream::{Stream, FusedStream}, future::FusedFuture}; -use futures_sink::Sink; -use spin1::Mutex as Spinlock; - -struct AsyncSignal { - waker: Spinlock, - woken: AtomicBool, - stream: bool, -} - -impl AsyncSignal { - fn new(cx: &Context, stream: bool) -> Self { - AsyncSignal { - waker: Spinlock::new(cx.waker().clone()), - woken: AtomicBool::new(false), - stream, - } - } -} - -impl Signal for AsyncSignal { - fn fire(&self) -> bool { - self.woken.store(true, Ordering::SeqCst); - self.waker.lock().wake_by_ref(); - self.stream - } - - fn as_any(&self) -> &(dyn Any + 'static) { self } - fn as_ptr(&self) -> *const () { self as *const _ as *const () } -} - -impl Hook { - // Update the hook to point to the given Waker. - // Returns whether the hook has been previously awakened - fn update_waker(&self, cx_waker: &Waker) -> bool { - let mut waker = self.1.waker.lock(); - let woken = self.1.woken.load(Ordering::SeqCst); - if !waker.will_wake(cx_waker) { - *waker = cx_waker.clone(); - - // Avoid the edge case where the waker was woken just before the wakers were - // swapped. - if woken { - cx_waker.wake_by_ref(); - } - } - woken - } -} - -#[derive(Clone)] -enum OwnedOrRef<'a, T> { - Owned(T), - Ref(&'a T), -} - -impl<'a, T> Deref for OwnedOrRef<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - match self { - OwnedOrRef::Owned(arc) => &arc, - OwnedOrRef::Ref(r) => r, - } - } -} - -impl Sender { - /// Asynchronously send a value into the channel, returning an error if all receivers have been - /// dropped. If the channel is bounded and is full, the returned future will yield to the async - /// runtime. - /// - /// In the current implementation, the returned future will not yield to the async runtime if the - /// channel is unbounded. This may change in later versions. - pub fn send_async(&self, item: T) -> SendFut { - SendFut { - sender: OwnedOrRef::Ref(&self), - hook: Some(SendState::NotYetSent(item)), - } - } - - /// Convert this sender into a future that asynchronously sends a single message into the channel, - /// returning an error if all receivers have been dropped. If the channel is bounded and is full, - /// this future will yield to the async runtime. - /// - /// In the current implementation, the returned future will not yield to the async runtime if the - /// channel is unbounded. This may change in later versions. - pub fn into_send_async<'a>(self, item: T) -> SendFut<'a, T> { - SendFut { - sender: OwnedOrRef::Owned(self), - hook: Some(SendState::NotYetSent(item)), - } - } - - /// Create an asynchronous sink that uses this sender to asynchronously send messages into the - /// channel. The sender will continue to be usable after the sink has been dropped. - /// - /// In the current implementation, the returned sink will not yield to the async runtime if the - /// channel is unbounded. This may change in later versions. - pub fn sink(&self) -> SendSink<'_, T> { - SendSink(SendFut { - sender: OwnedOrRef::Ref(&self), - hook: None, - }) - } - - /// Convert this sender into a sink that allows asynchronously sending messages into the channel. - /// - /// In the current implementation, the returned sink will not yield to the async runtime if the - /// channel is unbounded. This may change in later versions. - pub fn into_sink<'a>(self) -> SendSink<'a, T> { - SendSink(SendFut { - sender: OwnedOrRef::Owned(self), - hook: None, - }) - } -} - -enum SendState { - NotYetSent(T), - QueuedItem(Arc>), -} - -/// A future that sends a value into a channel. -/// -/// Can be created via [`Sender::send_async`] or [`Sender::into_send_async`]. -#[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"] -pub struct SendFut<'a, T> { - sender: OwnedOrRef<'a, Sender>, - // Only none after dropping - hook: Option>, -} - -impl std::marker::Unpin for SendFut<'_, T> {} - -impl<'a, T> SendFut<'a, T> { - /// Reset the hook, clearing it and removing it from the waiting sender's queue. This is called - /// on drop and just before `start_send` in the `Sink` implementation. - fn reset_hook(&mut self) { - if let Some(SendState::QueuedItem(hook)) = self.hook.take() { - let hook: Arc> = hook; - wait_lock(&self.sender.shared.chan).sending - .as_mut() - .unwrap().1 - .retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - } - } - - /// See [`Sender::is_disconnected`]. - pub fn is_disconnected(&self) -> bool { - self.sender.is_disconnected() - } - - /// See [`Sender::is_empty`]. - pub fn is_empty(&self) -> bool { - self.sender.is_empty() - } - - /// See [`Sender::is_full`]. - pub fn is_full(&self) -> bool { - self.sender.is_full() - } - - /// See [`Sender::len`]. - pub fn len(&self) -> usize { - self.sender.len() - } - - /// See [`Sender::capacity`]. - pub fn capacity(&self) -> Option { - self.sender.capacity() - } -} - -impl<'a, T> Drop for SendFut<'a, T> { - fn drop(&mut self) { - self.reset_hook() - } -} - - -impl<'a, T> Future for SendFut<'a, T> { - type Output = Result<(), SendError>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - if let Some(SendState::QueuedItem(hook)) = self.hook.as_ref() { - if hook.is_empty() { - Poll::Ready(Ok(())) - } else if self.sender.shared.is_disconnected() { - let item = hook.try_take(); - self.hook = None; - match item { - Some(item) => Poll::Ready(Err(SendError(item))), - None => Poll::Ready(Ok(())), - } - } else { - hook.update_waker(cx.waker()); - Poll::Pending - } - } else if let Some(SendState::NotYetSent(item)) = self.hook.take() { - let this = self.get_mut(); - let (shared, this_hook) = (&this.sender.shared, &mut this.hook); - - shared.send( - // item - item, - // should_block - true, - // make_signal - |msg| Hook::slot(Some(msg), AsyncSignal::new(cx, false)), - // do_block - |hook| { - *this_hook = Some(SendState::QueuedItem(hook)); - Poll::Pending - }, - ) - .map(|r| r.map_err(|err| match err { - TrySendTimeoutError::Disconnected(msg) => SendError(msg), - _ => unreachable!(), - })) - } else { // Nothing to do - Poll::Ready(Ok(())) - } - } -} - -impl<'a, T> FusedFuture for SendFut<'a, T> { - fn is_terminated(&self) -> bool { - self.sender.shared.is_disconnected() - } -} - -/// A sink that allows sending values into a channel. -/// -/// Can be created via [`Sender::sink`] or [`Sender::into_sink`]. -pub struct SendSink<'a, T>(SendFut<'a, T>); - -impl<'a, T> SendSink<'a, T> { - /// Returns a clone of a sending half of the channel of this sink. - pub fn sender(&self) -> &Sender { - &self.0.sender - } - - /// See [`Sender::is_disconnected`]. - pub fn is_disconnected(&self) -> bool { - self.0.is_disconnected() - } - - /// See [`Sender::is_empty`]. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// See [`Sender::is_full`]. - pub fn is_full(&self) -> bool { - self.0.is_full() - } - - /// See [`Sender::len`]. - pub fn len(&self) -> usize { - self.0.len() - } - - /// See [`Sender::capacity`]. - pub fn capacity(&self) -> Option { - self.0.capacity() - } - - /// Returns whether the SendSinks are belong to the same channel. - pub fn same_channel(&self, other: &Self) -> bool { - self.sender().same_channel(other.sender()) - } -} - -impl<'a, T> Sink for SendSink<'a, T> { - type Error = SendError; - - fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Pin::new(&mut self.0).poll(cx) - } - - fn start_send(mut self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> { - self.0.reset_hook(); - self.0.hook = Some(SendState::NotYetSent(item)); - - Ok(()) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Pin::new(&mut self.0).poll(cx) // TODO: A different strategy here? - } - - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Pin::new(&mut self.0).poll(cx) // TODO: A different strategy here? - } -} - -impl<'a, T> Clone for SendSink<'a, T> { - fn clone(&self) -> SendSink<'a, T> { - SendSink(SendFut { - sender: self.0.sender.clone(), - hook: None, - }) - } -} - -impl Receiver { - /// Asynchronously receive a value from the channel, returning an error if all senders have been - /// dropped. If the channel is empty, the returned future will yield to the async runtime. - pub fn recv_async(&self) -> RecvFut<'_, T> { - RecvFut::new(OwnedOrRef::Ref(self)) - } - - /// Convert this receiver into a future that asynchronously receives a single message from the - /// channel, returning an error if all senders have been dropped. If the channel is empty, this - /// future will yield to the async runtime. - pub fn into_recv_async<'a>(self) -> RecvFut<'a, T> { - RecvFut::new(OwnedOrRef::Owned(self)) - } - - /// Create an asynchronous stream that uses this receiver to asynchronously receive messages - /// from the channel. The receiver will continue to be usable after the stream has been dropped. - pub fn stream(&self) -> RecvStream<'_, T> { - RecvStream(RecvFut::new(OwnedOrRef::Ref(self))) - } - - /// Convert this receiver into a stream that allows asynchronously receiving messages from the channel. - pub fn into_stream<'a>(self) -> RecvStream<'a, T> { - RecvStream(RecvFut::new(OwnedOrRef::Owned(self))) - } -} - -/// A future which allows asynchronously receiving a message. -/// -/// Can be created via [`Receiver::recv_async`] or [`Receiver::into_recv_async`]. -#[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"] -pub struct RecvFut<'a, T> { - receiver: OwnedOrRef<'a, Receiver>, - hook: Option>>, -} - -impl<'a, T> RecvFut<'a, T> { - fn new(receiver: OwnedOrRef<'a, Receiver>) -> Self { - Self { - receiver, - hook: None, - } - } - - /// Reset the hook, clearing it and removing it from the waiting receivers queue and waking - /// another receiver if this receiver has been woken, so as not to cause any missed wakeups. - /// This is called on drop and after a new item is received in `Stream::poll_next`. - fn reset_hook(&mut self) { - if let Some(hook) = self.hook.take() { - let hook: Arc> = hook; - let mut chan = wait_lock(&self.receiver.shared.chan); - // We'd like to use `Arc::ptr_eq` here but it doesn't seem to work consistently with wide pointers? - chan.waiting.retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - if hook.signal().as_any().downcast_ref::().unwrap().woken.load(Ordering::SeqCst) { - // If this signal has been fired, but we're being dropped (and so not listening to it), - // pass the signal on to another receiver - chan.try_wake_receiver_if_pending(); - } - } - } - - fn poll_inner( - self: Pin<&mut Self>, - cx: &mut Context, - stream: bool, - ) -> Poll> { - if self.hook.is_some() { - match self.receiver.shared.recv_sync(None) { - Ok(msg) => return Poll::Ready(Ok(msg)), - Err(TryRecvTimeoutError::Disconnected) => { - return Poll::Ready(Err(RecvError::Disconnected)) - } - _ => (), - } - - let hook = self.hook.as_ref().map(Arc::clone).unwrap(); - if hook.update_waker(cx.waker()) { - // If the previous hook was awakened, we need to insert it back to the - // queue, otherwise, it remains valid. - wait_lock(&self.receiver.shared.chan) - .waiting - .push_back(hook); - } - // To avoid a missed wakeup, re-check disconnect status here because the channel might have - // gotten shut down before we had a chance to push our hook - if self.receiver.shared.is_disconnected() { - // And now, to avoid a race condition between the first recv attempt and the disconnect check we - // just performed, attempt to recv again just in case we missed something. - Poll::Ready( - self.receiver - .shared - .recv_sync(None) - .map(Ok) - .unwrap_or(Err(RecvError::Disconnected)), - ) - } else { - Poll::Pending - } - } else { - let mut_self = self.get_mut(); - let (shared, this_hook) = (&mut_self.receiver.shared, &mut mut_self.hook); - - shared.recv( - // should_block - true, - // make_signal - || Hook::trigger(AsyncSignal::new(cx, stream)), - // do_block - |hook| { - *this_hook = Some(hook); - Poll::Pending - }, - ) - .map(|r| r.map_err(|err| match err { - TryRecvTimeoutError::Disconnected => RecvError::Disconnected, - _ => unreachable!(), - })) - } - } - - /// See [`Receiver::is_disconnected`]. - pub fn is_disconnected(&self) -> bool { - self.receiver.is_disconnected() - } - - /// See [`Receiver::is_empty`]. - pub fn is_empty(&self) -> bool { - self.receiver.is_empty() - } - - /// See [`Receiver::is_full`]. - pub fn is_full(&self) -> bool { - self.receiver.is_full() - } - - /// See [`Receiver::len`]. - pub fn len(&self) -> usize { - self.receiver.len() - } - - /// See [`Receiver::capacity`]. - pub fn capacity(&self) -> Option { - self.receiver.capacity() - } -} - -impl<'a, T> Drop for RecvFut<'a, T> { - fn drop(&mut self) { - self.reset_hook(); - } -} - -impl<'a, T> Future for RecvFut<'a, T> { - type Output = Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - self.poll_inner(cx, false) // stream = false - } -} - -impl<'a, T> FusedFuture for RecvFut<'a, T> { - fn is_terminated(&self) -> bool { - self.receiver.shared.is_disconnected() && self.receiver.shared.is_empty() - } -} - -/// A stream which allows asynchronously receiving messages. -/// -/// Can be created via [`Receiver::stream`] or [`Receiver::into_stream`]. -pub struct RecvStream<'a, T>(RecvFut<'a, T>); - -impl<'a, T> RecvStream<'a, T> { - /// See [`Receiver::is_disconnected`]. - pub fn is_disconnected(&self) -> bool { - self.0.is_disconnected() - } - - /// See [`Receiver::is_empty`]. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// See [`Receiver::is_full`]. - pub fn is_full(&self) -> bool { - self.0.is_full() - } - - /// See [`Receiver::len`]. - pub fn len(&self) -> usize { - self.0.len() - } - - /// See [`Receiver::capacity`]. - pub fn capacity(&self) -> Option { - self.0.capacity() - } - - /// Returns whether the SendSinks are belong to the same channel. - pub fn same_channel(&self, other: &Self) -> bool { - self.0.receiver.same_channel(&*other.0.receiver) - } -} - -impl<'a, T> Clone for RecvStream<'a, T> { - fn clone(&self) -> RecvStream<'a, T> { - RecvStream(RecvFut::new(self.0.receiver.clone())) - } -} - -impl<'a, T> Stream for RecvStream<'a, T> { - type Item = T; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match Pin::new(&mut self.0).poll_inner(cx, true) { // stream = true - Poll::Pending => Poll::Pending, - Poll::Ready(item) => { - self.0.reset_hook(); - Poll::Ready(item.ok()) - } - } - } -} - -impl<'a, T> FusedStream for RecvStream<'a, T> { - fn is_terminated(&self) -> bool { - self.0.is_terminated() - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1142 +0,0 @@ -//! # Flume -//! -//! A blazingly fast multi-producer, multi-consumer channel. -//! -//! *"Do not communicate by sharing memory; instead, share memory by communicating."* -//! -//! ## Why Flume? -//! -//! - **Featureful**: Unbounded, bounded and rendezvous queues -//! - **Fast**: Always faster than `std::sync::mpsc` and sometimes `crossbeam-channel` -//! - **Safe**: No `unsafe` code anywhere in the codebase! -//! - **Flexible**: `Sender` and `Receiver` both implement `Send + Sync + Clone` -//! - **Familiar**: Drop-in replacement for `std::sync::mpsc` -//! - **Capable**: Additional features like MPMC support and send timeouts/deadlines -//! - **Simple**: Few dependencies, minimal codebase, fast to compile -//! - **Asynchronous**: `async` support, including mix 'n match with sync code -//! - **Ergonomic**: Powerful `select`-like interface -//! -//! ## Example -//! -//! ``` -//! let (tx, rx) = flume::unbounded(); -//! -//! tx.send(42).unwrap(); -//! assert_eq!(rx.recv().unwrap(), 42); -//! ``` - -#![deny(missing_docs)] - -#[cfg(feature = "select")] -pub mod select; -#[cfg(feature = "async")] -pub mod r#async; - -mod signal; - -// Reexports -#[cfg(feature = "select")] -pub use select::Selector; - -use std::{ - collections::VecDeque, - sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}, Weak}, - time::{Duration, Instant}, - marker::PhantomData, - thread, - fmt, -}; - -#[cfg(feature = "spin")] -use spin1::{Mutex as Spinlock, MutexGuard as SpinlockGuard}; -use crate::signal::{Signal, SyncSignal}; - -/// An error that may be emitted when attempting to send a value into a channel on a sender when -/// all receivers are dropped. -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct SendError(pub T); - -impl SendError { - /// Consume the error, yielding the message that failed to send. - pub fn into_inner(self) -> T { self.0 } -} - -impl fmt::Debug for SendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "SendError(..)".fmt(f) - } -} - -impl fmt::Display for SendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "sending on a closed channel".fmt(f) - } -} - -impl std::error::Error for SendError {} - -/// An error that may be emitted when attempting to send a value into a channel on a sender when -/// the channel is full or all receivers are dropped. -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum TrySendError { - /// The channel the message is sent on has a finite capacity and was full when the send was attempted. - Full(T), - /// All channel receivers were dropped and so the message has nobody to receive it. - Disconnected(T), -} - -impl TrySendError { - /// Consume the error, yielding the message that failed to send. - pub fn into_inner(self) -> T { - match self { - Self::Full(msg) | Self::Disconnected(msg) => msg, - } - } -} - -impl fmt::Debug for TrySendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - TrySendError::Full(..) => "Full(..)".fmt(f), - TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f), - } - } -} - -impl fmt::Display for TrySendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - TrySendError::Full(..) => "sending on a full channel".fmt(f), - TrySendError::Disconnected(..) => "sending on a closed channel".fmt(f), - } - } -} - -impl std::error::Error for TrySendError {} - -impl From> for TrySendError { - fn from(err: SendError) -> Self { - match err { - SendError(item) => Self::Disconnected(item), - } - } -} - -/// An error that may be emitted when sending a value into a channel on a sender with a timeout when -/// the send operation times out or all receivers are dropped. -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum SendTimeoutError { - /// A timeout occurred when attempting to send the message. - Timeout(T), - /// All channel receivers were dropped and so the message has nobody to receive it. - Disconnected(T), -} - -impl SendTimeoutError { - /// Consume the error, yielding the message that failed to send. - pub fn into_inner(self) -> T { - match self { - Self::Timeout(msg) | Self::Disconnected(msg) => msg, - } - } -} - -impl fmt::Debug for SendTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "SendTimeoutError(..)".fmt(f) - } -} - -impl fmt::Display for SendTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SendTimeoutError::Timeout(..) => "timed out sending on a full channel".fmt(f), - SendTimeoutError::Disconnected(..) => "sending on a closed channel".fmt(f), - } - } -} - -impl std::error::Error for SendTimeoutError {} - -impl From> for SendTimeoutError { - fn from(err: SendError) -> Self { - match err { - SendError(item) => Self::Disconnected(item), - } - } -} - -enum TrySendTimeoutError { - Full(T), - Disconnected(T), - Timeout(T), -} - -/// An error that may be emitted when attempting to wait for a value on a receiver when all senders -/// are dropped and there are no more messages in the channel. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum RecvError { - /// All senders were dropped and no messages are waiting in the channel, so no further messages can be received. - Disconnected, -} - -impl fmt::Display for RecvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - RecvError::Disconnected => "receiving on a closed channel".fmt(f), - } - } -} - -impl std::error::Error for RecvError {} - -/// An error that may be emitted when attempting to fetch a value on a receiver when there are no -/// messages in the channel. If there are no messages in the channel and all senders are dropped, -/// then `TryRecvError::Disconnected` will be returned. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum TryRecvError { - /// The channel was empty when the receive was attempted. - Empty, - /// All senders were dropped and no messages are waiting in the channel, so no further messages can be received. - Disconnected, -} - -impl fmt::Display for TryRecvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - TryRecvError::Empty => "receiving on an empty channel".fmt(f), - TryRecvError::Disconnected => "channel is empty and closed".fmt(f), - } - } -} - -impl std::error::Error for TryRecvError {} - -impl From for TryRecvError { - fn from(err: RecvError) -> Self { - match err { - RecvError::Disconnected => Self::Disconnected, - } - } -} - -/// An error that may be emitted when attempting to wait for a value on a receiver with a timeout -/// when the receive operation times out or all senders are dropped and there are no values left -/// in the channel. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum RecvTimeoutError { - /// A timeout occurred when attempting to receive a message. - Timeout, - /// All senders were dropped and no messages are waiting in the channel, so no further messages can be received. - Disconnected, -} - -impl fmt::Display for RecvTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - RecvTimeoutError::Timeout => "timed out waiting on a channel".fmt(f), - RecvTimeoutError::Disconnected => "channel is empty and closed".fmt(f), - } - } -} - -impl std::error::Error for RecvTimeoutError {} - -impl From for RecvTimeoutError { - fn from(err: RecvError) -> Self { - match err { - RecvError::Disconnected => Self::Disconnected, - } - } -} - -enum TryRecvTimeoutError { - Empty, - Timeout, - Disconnected, -} - -// TODO: Investigate some sort of invalidation flag for timeouts -#[cfg(feature = "spin")] -struct Hook(Option>>, S); - -#[cfg(not(feature = "spin"))] -struct Hook(Option>>, S); - -#[cfg(feature = "spin")] -impl Hook { - pub fn slot(msg: Option, signal: S) -> Arc - where - S: Sized, - { - Arc::new(Self(Some(Spinlock::new(msg)), signal)) - } - - fn lock(&self) -> Option>> { - self.0.as_ref().map(|s| s.lock()) - } -} - -#[cfg(not(feature = "spin"))] -impl Hook { - pub fn slot(msg: Option, signal: S) -> Arc - where - S: Sized, - { - Arc::new(Self(Some(Mutex::new(msg)), signal)) - } - - fn lock(&self) -> Option>> { - self.0.as_ref().map(|s| s.lock().unwrap()) - } -} - -impl Hook { - pub fn fire_recv(&self) -> (T, &S) { - let msg = self.lock().unwrap().take().unwrap(); - (msg, self.signal()) - } - - pub fn fire_send(&self, msg: T) -> (Option, &S) { - let ret = match self.lock() { - Some(mut lock) => { - *lock = Some(msg); - None - } - None => Some(msg), - }; - (ret, self.signal()) - } - - pub fn is_empty(&self) -> bool { - self.lock().map(|s| s.is_none()).unwrap_or(true) - } - - pub fn try_take(&self) -> Option { - self.lock().unwrap().take() - } - - pub fn trigger(signal: S) -> Arc - where - S: Sized, - { - Arc::new(Self(None, signal)) - } - - pub fn signal(&self) -> &S { - &self.1 - } - - pub fn fire_nothing(&self) -> bool { - self.signal().fire() - } -} - -impl Hook { - pub fn wait_recv(&self, abort: &AtomicBool) -> Option { - loop { - let disconnected = abort.load(Ordering::SeqCst); // Check disconnect *before* msg - let msg = self.lock().unwrap().take(); - if let Some(msg) = msg { - break Some(msg); - } else if disconnected { - break None; - } else { - self.signal().wait() - } - } - } - - // Err(true) if timeout - pub fn wait_deadline_recv(&self, abort: &AtomicBool, deadline: Instant) -> Result { - loop { - let disconnected = abort.load(Ordering::SeqCst); // Check disconnect *before* msg - let msg = self.lock().unwrap().take(); - if let Some(msg) = msg { - break Ok(msg); - } else if disconnected { - break Err(false); - } else if let Some(dur) = deadline.checked_duration_since(Instant::now()) { - self.signal().wait_timeout(dur); - } else { - break Err(true); - } - } - } - - pub fn wait_send(&self, abort: &AtomicBool) { - loop { - let disconnected = abort.load(Ordering::SeqCst); // Check disconnect *before* msg - if disconnected || self.lock().unwrap().is_none() { - break; - } - - self.signal().wait(); - } - } - - // Err(true) if timeout - pub fn wait_deadline_send(&self, abort: &AtomicBool, deadline: Instant) -> Result<(), bool> { - loop { - let disconnected = abort.load(Ordering::SeqCst); // Check disconnect *before* msg - if self.lock().unwrap().is_none() { - break Ok(()); - } else if disconnected { - break Err(false); - } else if let Some(dur) = deadline.checked_duration_since(Instant::now()) { - self.signal().wait_timeout(dur); - } else { - break Err(true); - } - } - } -} - -#[cfg(feature = "spin")] -#[inline] -fn wait_lock(lock: &Spinlock) -> SpinlockGuard { - let mut i = 4; - loop { - for _ in 0..10 { - if let Some(guard) = lock.try_lock() { - return guard; - } - thread::yield_now(); - } - // Sleep for at most ~1 ms - thread::sleep(Duration::from_nanos(1 << i.min(20))); - i += 1; - } -} - -#[cfg(not(feature = "spin"))] -#[inline] -fn wait_lock<'a, T>(lock: &'a Mutex) -> MutexGuard<'a, T> { - lock.lock().unwrap() -} - -#[cfg(not(feature = "spin"))] -use std::sync::{Mutex, MutexGuard}; - -#[cfg(feature = "spin")] -type ChanLock = Spinlock; -#[cfg(not(feature = "spin"))] -type ChanLock = Mutex; - - -type SignalVec = VecDeque>>; -struct Chan { - sending: Option<(usize, SignalVec)>, - queue: VecDeque, - waiting: SignalVec, -} - -impl Chan { - fn pull_pending(&mut self, pull_extra: bool) { - if let Some((cap, sending)) = &mut self.sending { - let effective_cap = *cap + pull_extra as usize; - - while self.queue.len() < effective_cap { - if let Some(s) = sending.pop_front() { - let (msg, signal) = s.fire_recv(); - signal.fire(); - self.queue.push_back(msg); - } else { - break; - } - } - } - } - - fn try_wake_receiver_if_pending(&mut self) { - if !self.queue.is_empty() { - while Some(false) == self.waiting.pop_front().map(|s| s.fire_nothing()) {} - } - } -} - -struct Shared { - chan: ChanLock>, - disconnected: AtomicBool, - sender_count: AtomicUsize, - receiver_count: AtomicUsize, -} - -impl Shared { - fn new(cap: Option) -> Self { - Self { - chan: ChanLock::new(Chan { - sending: cap.map(|cap| (cap, VecDeque::new())), - queue: VecDeque::new(), - waiting: VecDeque::new(), - }), - disconnected: AtomicBool::new(false), - sender_count: AtomicUsize::new(1), - receiver_count: AtomicUsize::new(1), - } - } - - fn send>>>( - &self, - msg: T, - should_block: bool, - make_signal: impl FnOnce(T) -> Arc>, - do_block: impl FnOnce(Arc>) -> R, - ) -> R { - let mut chan = wait_lock(&self.chan); - - if self.is_disconnected() { - Err(TrySendTimeoutError::Disconnected(msg)).into() - } else if !chan.waiting.is_empty() { - let mut msg = Some(msg); - - loop { - let slot = chan.waiting.pop_front(); - match slot.as_ref().map(|r| r.fire_send(msg.take().unwrap())) { - // No more waiting receivers and msg in queue, so break out of the loop - None if msg.is_none() => break, - // No more waiting receivers, so add msg to queue and break out of the loop - None => { - chan.queue.push_back(msg.unwrap()); - break; - } - Some((Some(m), signal)) => { - if signal.fire() { - // Was async and a stream, so didn't acquire the message. Wake another - // receiver, and do not yet push the message. - msg.replace(m); - continue; - } else { - // Was async and not a stream, so it did acquire the message. Push the - // message to the queue for it to be received. - chan.queue.push_back(m); - drop(chan); - break; - } - }, - Some((None, signal)) => { - drop(chan); - signal.fire(); - break; // Was sync, so it has acquired the message - }, - } - } - - Ok(()).into() - } else if chan.sending.as_ref().map(|(cap, _)| chan.queue.len() < *cap).unwrap_or(true) { - chan.queue.push_back(msg); - Ok(()).into() - } else if should_block { // Only bounded from here on - let hook = make_signal(msg); - chan.sending.as_mut().unwrap().1.push_back(hook.clone()); - drop(chan); - - do_block(hook) - } else { - Err(TrySendTimeoutError::Full(msg)).into() - } - } - - fn send_sync( - &self, - msg: T, - block: Option>, - ) -> Result<(), TrySendTimeoutError> { - self.send( - // msg - msg, - // should_block - block.is_some(), - // make_signal - |msg| Hook::slot(Some(msg), SyncSignal::default()), - // do_block - |hook| if let Some(deadline) = block.unwrap() { - hook.wait_deadline_send(&self.disconnected, deadline) - .or_else(|timed_out| { - if timed_out { // Remove our signal - let hook: Arc> = hook.clone(); - wait_lock(&self.chan).sending - .as_mut() - .unwrap().1 - .retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - } - hook.try_take().map(|msg| if self.is_disconnected() { - Err(TrySendTimeoutError::Disconnected(msg)) - } else { - Err(TrySendTimeoutError::Timeout(msg)) - }) - .unwrap_or(Ok(())) - }) - } else { - hook.wait_send(&self.disconnected); - - match hook.try_take() { - Some(msg) => Err(TrySendTimeoutError::Disconnected(msg)), - None => Ok(()), - } - }, - ) - } - - fn recv>>( - &self, - should_block: bool, - make_signal: impl FnOnce() -> Arc>, - do_block: impl FnOnce(Arc>) -> R, - ) -> R { - let mut chan = wait_lock(&self.chan); - chan.pull_pending(true); - - if let Some(msg) = chan.queue.pop_front() { - drop(chan); - Ok(msg).into() - } else if self.is_disconnected() { - drop(chan); - Err(TryRecvTimeoutError::Disconnected).into() - } else if should_block { - let hook = make_signal(); - chan.waiting.push_back(hook.clone()); - drop(chan); - - do_block(hook) - } else { - drop(chan); - Err(TryRecvTimeoutError::Empty).into() - } - } - - fn recv_sync(&self, block: Option>) -> Result { - self.recv( - // should_block - block.is_some(), - // make_signal - || Hook::slot(None, SyncSignal::default()), - // do_block - |hook| if let Some(deadline) = block.unwrap() { - hook.wait_deadline_recv(&self.disconnected, deadline) - .or_else(|timed_out| { - if timed_out { // Remove our signal - let hook: Arc> = hook.clone(); - wait_lock(&self.chan).waiting - .retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - } - match hook.try_take() { - Some(msg) => Ok(msg), - None => { - let disconnected = self.is_disconnected(); // Check disconnect *before* msg - if let Some(msg) = wait_lock(&self.chan).queue.pop_front() { - Ok(msg) - } else if disconnected { - Err(TryRecvTimeoutError::Disconnected) - } else { - Err(TryRecvTimeoutError::Timeout) - } - }, - } - }) - } else { - hook.wait_recv(&self.disconnected) - .or_else(|| wait_lock(&self.chan).queue.pop_front()) - .ok_or(TryRecvTimeoutError::Disconnected) - }, - ) - } - - /// Disconnect anything listening on this channel (this will not prevent receivers receiving - /// msgs that have already been sent) - fn disconnect_all(&self) { - self.disconnected.store(true, Ordering::Relaxed); - - let mut chan = wait_lock(&self.chan); - chan.pull_pending(false); - if let Some((_, sending)) = chan.sending.as_ref() { - sending.iter().for_each(|hook| { - hook.signal().fire(); - }) - } - chan.waiting.iter().for_each(|hook| { - hook.signal().fire(); - }); - } - - fn is_disconnected(&self) -> bool { - self.disconnected.load(Ordering::SeqCst) - } - - fn is_empty(&self) -> bool { - self.len() == 0 - } - - fn is_full(&self) -> bool { - self.capacity().map(|cap| cap == self.len()).unwrap_or(false) - } - - fn len(&self) -> usize { - let mut chan = wait_lock(&self.chan); - chan.pull_pending(false); - chan.queue.len() - } - - fn capacity(&self) -> Option { - wait_lock(&self.chan).sending.as_ref().map(|(cap, _)| *cap) - } - - fn sender_count(&self) -> usize { - self.sender_count.load(Ordering::Relaxed) - } - - fn receiver_count(&self) -> usize { - self.receiver_count.load(Ordering::Relaxed) - } -} - -/// A transmitting end of a channel. -pub struct Sender { - shared: Arc>, -} - -impl Sender { - /// Attempt to send a value into the channel. If the channel is bounded and full, or all - /// receivers have been dropped, an error is returned. If the channel associated with this - /// sender is unbounded, this method has the same behaviour as [`Sender::send`]. - pub fn try_send(&self, msg: T) -> Result<(), TrySendError> { - self.shared.send_sync(msg, None).map_err(|err| match err { - TrySendTimeoutError::Full(msg) => TrySendError::Full(msg), - TrySendTimeoutError::Disconnected(msg) => TrySendError::Disconnected(msg), - _ => unreachable!(), - }) - } - - /// Send a value into the channel, returning an error if all receivers have been dropped. - /// If the channel is bounded and is full, this method will block until space is available - /// or all receivers have been dropped. If the channel is unbounded, this method will not - /// block. - pub fn send(&self, msg: T) -> Result<(), SendError> { - self.shared.send_sync(msg, Some(None)).map_err(|err| match err { - TrySendTimeoutError::Disconnected(msg) => SendError(msg), - _ => unreachable!(), - }) - } - - /// Send a value into the channel, returning an error if all receivers have been dropped - /// or the deadline has passed. If the channel is bounded and is full, this method will - /// block until space is available, the deadline is reached, or all receivers have been - /// dropped. - pub fn send_deadline(&self, msg: T, deadline: Instant) -> Result<(), SendTimeoutError> { - self.shared.send_sync(msg, Some(Some(deadline))).map_err(|err| match err { - TrySendTimeoutError::Disconnected(msg) => SendTimeoutError::Disconnected(msg), - TrySendTimeoutError::Timeout(msg) => SendTimeoutError::Timeout(msg), - _ => unreachable!(), - }) - } - - /// Send a value into the channel, returning an error if all receivers have been dropped - /// or the timeout has expired. If the channel is bounded and is full, this method will - /// block until space is available, the timeout has expired, or all receivers have been - /// dropped. - pub fn send_timeout(&self, msg: T, dur: Duration) -> Result<(), SendTimeoutError> { - self.send_deadline(msg, Instant::now().checked_add(dur).unwrap()) - } - - /// Returns true if all receivers for this channel have been dropped. - pub fn is_disconnected(&self) -> bool { - self.shared.is_disconnected() - } - - /// Returns true if the channel is empty. - /// Note: Zero-capacity channels are always empty. - pub fn is_empty(&self) -> bool { - self.shared.is_empty() - } - - /// Returns true if the channel is full. - /// Note: Zero-capacity channels are always full. - pub fn is_full(&self) -> bool { - self.shared.is_full() - } - - /// Returns the number of messages in the channel - pub fn len(&self) -> usize { - self.shared.len() - } - - /// If the channel is bounded, returns its capacity. - pub fn capacity(&self) -> Option { - self.shared.capacity() - } - - /// Get the number of senders that currently exist, including this one. - pub fn sender_count(&self) -> usize { - self.shared.sender_count() - } - - /// Get the number of receivers that currently exist. - /// - /// Note that this method makes no guarantees that a subsequent send will succeed; it's - /// possible that between `receiver_count()` being called and a `send()`, all open receivers - /// could drop. - pub fn receiver_count(&self) -> usize { - self.shared.receiver_count() - } - - /// Creates a [`WeakSender`] that does not keep the channel open. - /// - /// The channel is closed once all `Sender`s are dropped, even if there - /// are still active `WeakSender`s. - pub fn downgrade(&self) -> WeakSender { - WeakSender { - shared: Arc::downgrade(&self.shared), - } - } - - /// Returns whether the senders are belong to the same channel. - pub fn same_channel(&self, other: &Sender) -> bool { - Arc::ptr_eq(&self.shared, &other.shared) - } -} - -impl Clone for Sender { - /// Clone this sender. [`Sender`] acts as a handle to the ending a channel. Remaining channel - /// contents will only be cleaned up when all senders and the receiver have been dropped. - fn clone(&self) -> Self { - self.shared.sender_count.fetch_add(1, Ordering::Relaxed); - Self { shared: self.shared.clone() } - } -} - -impl fmt::Debug for Sender { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Sender").finish() - } -} - -impl Drop for Sender { - fn drop(&mut self) { - // Notify receivers that all senders have been dropped if the number of senders drops to 0. - if self.shared.sender_count.fetch_sub(1, Ordering::Relaxed) == 1 { - self.shared.disconnect_all(); - } - } -} - -/// A sender that does not prevent the channel from being closed. -/// -/// Weak senders do not count towards the number of active senders on the channel. As soon as -/// all normal [`Sender`]s are dropped, the channel is closed, even if there is still a -/// `WeakSender`. -/// -/// To send messages, a `WeakSender` must first be upgraded to a `Sender` using the [`upgrade`] -/// method. -pub struct WeakSender { - shared: Weak>, -} - -impl WeakSender { - /// Tries to upgrade the `WeakSender` to a [`Sender`], in order to send messages. - /// - /// Returns `None` if the channel was closed already. Note that a `Some` return value - /// does not guarantee that the channel is still open. - pub fn upgrade(&self) -> Option> { - self.shared - .upgrade() - // check that there are still live senders - .filter(|shared| { - shared - .sender_count - .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count| { - if count == 0 { - // all senders are closed already -> don't increase the sender count - None - } else { - // there is still at least one active sender - Some(count + 1) - } - }) - .is_ok() - }) - .map(|shared| Sender { shared }) - } -} - -/// The receiving end of a channel. -/// -/// Note: Cloning the receiver *does not* turn this channel into a broadcast channel. -/// Each message will only be received by a single receiver. This is useful for -/// implementing work stealing for concurrent programs. -pub struct Receiver { - shared: Arc>, -} - -impl Receiver { - /// Attempt to fetch an incoming value from the channel associated with this receiver, - /// returning an error if the channel is empty or if all senders have been dropped. - pub fn try_recv(&self) -> Result { - self.shared.recv_sync(None).map_err(|err| match err { - TryRecvTimeoutError::Disconnected => TryRecvError::Disconnected, - TryRecvTimeoutError::Empty => TryRecvError::Empty, - _ => unreachable!(), - }) - } - - /// Wait for an incoming value from the channel associated with this receiver, returning an - /// error if all senders have been dropped. - pub fn recv(&self) -> Result { - self.shared.recv_sync(Some(None)).map_err(|err| match err { - TryRecvTimeoutError::Disconnected => RecvError::Disconnected, - _ => unreachable!(), - }) - } - - /// Wait for an incoming value from the channel associated with this receiver, returning an - /// error if all senders have been dropped or the deadline has passed. - pub fn recv_deadline(&self, deadline: Instant) -> Result { - self.shared.recv_sync(Some(Some(deadline))).map_err(|err| match err { - TryRecvTimeoutError::Disconnected => RecvTimeoutError::Disconnected, - TryRecvTimeoutError::Timeout => RecvTimeoutError::Timeout, - _ => unreachable!(), - }) - } - - /// Wait for an incoming value from the channel associated with this receiver, returning an - /// error if all senders have been dropped or the timeout has expired. - pub fn recv_timeout(&self, dur: Duration) -> Result { - self.recv_deadline(Instant::now().checked_add(dur).unwrap()) - } - - /// Create a blocking iterator over the values received on the channel that finishes iteration - /// when all senders have been dropped. - /// - /// You can also create a self-owned iterator with [`Receiver::into_iter`]. - pub fn iter(&self) -> Iter { - Iter { receiver: &self } - } - - /// A non-blocking iterator over the values received on the channel that finishes iteration - /// when all senders have been dropped or the channel is empty. - pub fn try_iter(&self) -> TryIter { - TryIter { receiver: &self } - } - - /// Take all msgs currently sitting in the channel and produce an iterator over them. Unlike - /// `try_iter`, the iterator will not attempt to fetch any more values from the channel once - /// the function has been called. - pub fn drain(&self) -> Drain { - let mut chan = wait_lock(&self.shared.chan); - chan.pull_pending(false); - let queue = std::mem::take(&mut chan.queue); - - Drain { queue, _phantom: PhantomData } - } - - /// Returns true if all senders for this channel have been dropped. - pub fn is_disconnected(&self) -> bool { - self.shared.is_disconnected() - } - - /// Returns true if the channel is empty. - /// Note: Zero-capacity channels are always empty. - pub fn is_empty(&self) -> bool { - self.shared.is_empty() - } - - /// Returns true if the channel is full. - /// Note: Zero-capacity channels are always full. - pub fn is_full(&self) -> bool { - self.shared.is_full() - } - - /// Returns the number of messages in the channel. - pub fn len(&self) -> usize { - self.shared.len() - } - - /// If the channel is bounded, returns its capacity. - pub fn capacity(&self) -> Option { - self.shared.capacity() - } - - /// Get the number of senders that currently exist. - pub fn sender_count(&self) -> usize { - self.shared.sender_count() - } - - /// Get the number of receivers that currently exist, including this one. - pub fn receiver_count(&self) -> usize { - self.shared.receiver_count() - } - - /// Returns whether the receivers are belong to the same channel. - pub fn same_channel(&self, other: &Receiver) -> bool { - Arc::ptr_eq(&self.shared, &other.shared) - } -} - -impl Clone for Receiver { - /// Clone this receiver. [`Receiver`] acts as a handle to the ending a channel. Remaining - /// channel contents will only be cleaned up when all senders and the receiver have been - /// dropped. - /// - /// Note: Cloning the receiver *does not* turn this channel into a broadcast channel. - /// Each message will only be received by a single receiver. This is useful for - /// implementing work stealing for concurrent programs. - fn clone(&self) -> Self { - self.shared.receiver_count.fetch_add(1, Ordering::Relaxed); - Self { shared: self.shared.clone() } - } -} - -impl fmt::Debug for Receiver { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Receiver").finish() - } -} - -impl Drop for Receiver { - fn drop(&mut self) { - // Notify senders that all receivers have been dropped if the number of receivers drops - // to 0. - if self.shared.receiver_count.fetch_sub(1, Ordering::Relaxed) == 1 { - self.shared.disconnect_all(); - } - } -} - -/// This exists as a shorthand for [`Receiver::iter`]. -impl<'a, T> IntoIterator for &'a Receiver { - type Item = T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - Iter { receiver: self } - } -} - -impl IntoIterator for Receiver { - type Item = T; - type IntoIter = IntoIter; - - /// Creates a self-owned but semantically equivalent alternative to [`Receiver::iter`]. - fn into_iter(self) -> Self::IntoIter { - IntoIter { receiver: self } - } -} - -/// An iterator over the msgs received from a channel. -pub struct Iter<'a, T> { - receiver: &'a Receiver, -} - -impl<'a, T> Iterator for Iter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.receiver.recv().ok() - } -} - -/// An non-blocking iterator over the msgs received from a channel. -pub struct TryIter<'a, T> { - receiver: &'a Receiver, -} - -impl<'a, T> Iterator for TryIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.receiver.try_recv().ok() - } -} - -/// An fixed-sized iterator over the msgs drained from a channel. -#[derive(Debug)] -pub struct Drain<'a, T> { - queue: VecDeque, - /// A phantom field used to constrain the lifetime of this iterator. We do this because the - /// implementation may change and we don't want to unintentionally constrain it. Removing this - /// lifetime later is a possibility. - _phantom: PhantomData<&'a ()>, -} - -impl<'a, T> Iterator for Drain<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.queue.pop_front() - } -} - -impl<'a, T> ExactSizeIterator for Drain<'a, T> { - fn len(&self) -> usize { - self.queue.len() - } -} - -/// An owned iterator over the msgs received from a channel. -pub struct IntoIter { - receiver: Receiver, -} - -impl Iterator for IntoIter { - type Item = T; - - fn next(&mut self) -> Option { - self.receiver.recv().ok() - } -} - -/// Create a channel with no maximum capacity. -/// -/// Create an unbounded channel with a [`Sender`] and [`Receiver`] connected to each end respectively. Values sent in -/// one end of the channel will be received on the other end. The channel is thread-safe, and both [`Sender`] and -/// [`Receiver`] may be sent to or shared between threads as necessary. In addition, both [`Sender`] and [`Receiver`] -/// may be cloned. -/// -/// # Examples -/// ``` -/// let (tx, rx) = flume::unbounded(); -/// -/// tx.send(42).unwrap(); -/// assert_eq!(rx.recv().unwrap(), 42); -/// ``` -pub fn unbounded() -> (Sender, Receiver) { - let shared = Arc::new(Shared::new(None)); - ( - Sender { shared: shared.clone() }, - Receiver { shared }, - ) -} - -/// Create a channel with a maximum capacity. -/// -/// Create a bounded channel with a [`Sender`] and [`Receiver`] connected to each end respectively. Values sent in one -/// end of the channel will be received on the other end. The channel is thread-safe, and both [`Sender`] and -/// [`Receiver`] may be sent to or shared between threads as necessary. In addition, both [`Sender`] and [`Receiver`] -/// may be cloned. -/// -/// Unlike an [`unbounded`] channel, if there is no space left for new messages, calls to -/// [`Sender::send`] will block (unblocking once a receiver has made space). If blocking behaviour -/// is not desired, [`Sender::try_send`] may be used. -/// -/// Like `std::sync::mpsc`, `flume` supports 'rendezvous' channels. A bounded queue with a maximum capacity of zero -/// will block senders until a receiver is available to take the value. You can imagine a rendezvous channel as a -/// ['Glienicke Bridge'](https://en.wikipedia.org/wiki/Glienicke_Bridge)-style location at which senders and receivers -/// perform a handshake and transfer ownership of a value. -/// -/// # Examples -/// ``` -/// let (tx, rx) = flume::bounded(32); -/// -/// for i in 1..33 { -/// tx.send(i).unwrap(); -/// } -/// assert!(tx.try_send(33).is_err()); -/// -/// assert_eq!(rx.try_iter().sum::(), (1..33).sum()); -/// ``` -pub fn bounded(cap: usize) -> (Sender, Receiver) { - let shared = Arc::new(Shared::new(Some(cap))); - ( - Sender { shared: shared.clone() }, - Receiver { shared }, - ) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/src/select.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/src/select.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/src/select.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/src/select.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,405 +0,0 @@ -//! Types that permit waiting upon multiple blocking operations using the [`Selector`] interface. - -use crate::*; -use spin1::Mutex as Spinlock; -use std::{any::Any, marker::PhantomData}; - -#[cfg(feature = "eventual-fairness")] -use nanorand::Rng; - -// A unique token corresponding to an event in a selector -type Token = usize; - -struct SelectSignal( - thread::Thread, - Token, - AtomicBool, - Arc>>, -); - -impl Signal for SelectSignal { - fn fire(&self) -> bool { - self.2.store(true, Ordering::SeqCst); - self.3.lock().push_back(self.1); - self.0.unpark(); - false - } - - fn as_any(&self) -> &(dyn Any + 'static) { - self - } - fn as_ptr(&self) -> *const () { - self as *const _ as *const () - } -} - -trait Selection<'a, T> { - fn init(&mut self) -> Option; - fn poll(&mut self) -> Option; - fn deinit(&mut self); -} - -/// An error that may be emitted when attempting to wait for a value on a receiver. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum SelectError { - /// A timeout occurred when waiting on a `Selector`. - Timeout, -} - -impl fmt::Display for SelectError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SelectError::Timeout => "timeout occurred".fmt(f), - } - } -} - -impl std::error::Error for SelectError {} - -/// A type used to wait upon multiple blocking operations at once. -/// -/// A [`Selector`] implements [`select`](https://en.wikipedia.org/wiki/Select_(Unix))-like behaviour, -/// allowing a thread to wait upon the result of more than one operation at once. -/// -/// # Examples -/// ``` -/// let (tx0, rx0) = flume::unbounded(); -/// let (tx1, rx1) = flume::unbounded(); -/// -/// std::thread::spawn(move || { -/// tx0.send(true).unwrap(); -/// tx1.send(42).unwrap(); -/// }); -/// -/// flume::Selector::new() -/// .recv(&rx0, |b| println!("Received {:?}", b)) -/// .recv(&rx1, |n| println!("Received {:?}", n)) -/// .wait(); -/// ``` -pub struct Selector<'a, T: 'a> { - selections: Vec + 'a>>, - next_poll: usize, - signalled: Arc>>, - #[cfg(feature = "eventual-fairness")] - rng: nanorand::WyRand, - phantom: PhantomData<*const ()>, -} - -impl<'a, T: 'a> Default for Selector<'a, T> { - fn default() -> Self { - Self::new() - } -} - -impl<'a, T: 'a> fmt::Debug for Selector<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Selector").finish() - } -} - -impl<'a, T> Selector<'a, T> { - /// Create a new selector. - pub fn new() -> Self { - Self { - selections: Vec::new(), - next_poll: 0, - signalled: Arc::default(), - phantom: PhantomData::default(), - #[cfg(feature = "eventual-fairness")] - rng: nanorand::WyRand::new(), - } - } - - /// Add a send operation to the selector that sends the provided value. - /// - /// Once added, the selector can be used to run the provided handler function on completion of this operation. - pub fn send>) -> T + 'a>( - mut self, - sender: &'a Sender, - msg: U, - mapper: F, - ) -> Self { - struct SendSelection<'a, T, F, U> { - sender: &'a Sender, - msg: Option, - token: Token, - signalled: Arc>>, - hook: Option>>, - mapper: F, - phantom: PhantomData, - } - - impl<'a, T, F, U> Selection<'a, T> for SendSelection<'a, T, F, U> - where - F: FnMut(Result<(), SendError>) -> T, - { - fn init(&mut self) -> Option { - let token = self.token; - let signalled = self.signalled.clone(); - let r = self.sender.shared.send( - self.msg.take().unwrap(), - true, - |msg| { - Hook::slot( - Some(msg), - SelectSignal( - thread::current(), - token, - AtomicBool::new(false), - signalled, - ), - ) - }, - // Always runs - |h| { - self.hook = Some(h); - Ok(()) - }, - ); - - if self.hook.is_none() { - Some((self.mapper)(match r { - Ok(()) => Ok(()), - Err(TrySendTimeoutError::Disconnected(msg)) => Err(SendError(msg)), - _ => unreachable!(), - })) - } else { - None - } - } - - fn poll(&mut self) -> Option { - let res = if self.sender.shared.is_disconnected() { - // Check the hook one last time - if let Some(msg) = self.hook.as_ref()?.try_take() { - Err(SendError(msg)) - } else { - Ok(()) - } - } else if self.hook.as_ref().unwrap().is_empty() { - // The message was sent - Ok(()) - } else { - return None; - }; - - Some((&mut self.mapper)(res)) - } - - fn deinit(&mut self) { - if let Some(hook) = self.hook.take() { - // Remove hook - let hook: Arc> = hook; - wait_lock(&self.sender.shared.chan) - .sending - .as_mut() - .unwrap() - .1 - .retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - } - } - } - - let token = self.selections.len(); - self.selections.push(Box::new(SendSelection { - sender, - msg: Some(msg), - token, - signalled: self.signalled.clone(), - hook: None, - mapper, - phantom: Default::default(), - })); - - self - } - - /// Add a receive operation to the selector. - /// - /// Once added, the selector can be used to run the provided handler function on completion of this operation. - pub fn recv) -> T + 'a>( - mut self, - receiver: &'a Receiver, - mapper: F, - ) -> Self { - struct RecvSelection<'a, T, F, U> { - receiver: &'a Receiver, - token: Token, - signalled: Arc>>, - hook: Option>>, - mapper: F, - received: bool, - phantom: PhantomData, - } - - impl<'a, T, F, U> Selection<'a, T> for RecvSelection<'a, T, F, U> - where - F: FnMut(Result) -> T, - { - fn init(&mut self) -> Option { - let token = self.token; - let signalled = self.signalled.clone(); - let r = self.receiver.shared.recv( - true, - || { - Hook::trigger(SelectSignal( - thread::current(), - token, - AtomicBool::new(false), - signalled, - )) - }, - // Always runs - |h| { - self.hook = Some(h); - Err(TryRecvTimeoutError::Timeout) - }, - ); - - if self.hook.is_none() { - Some((self.mapper)(match r { - Ok(msg) => Ok(msg), - Err(TryRecvTimeoutError::Disconnected) => Err(RecvError::Disconnected), - _ => unreachable!(), - })) - } else { - None - } - } - - fn poll(&mut self) -> Option { - let res = if let Ok(msg) = self.receiver.try_recv() { - self.received = true; - Ok(msg) - } else if self.receiver.shared.is_disconnected() { - Err(RecvError::Disconnected) - } else { - return None; - }; - - Some((&mut self.mapper)(res)) - } - - fn deinit(&mut self) { - if let Some(hook) = self.hook.take() { - // Remove hook - let hook: Arc> = hook; - wait_lock(&self.receiver.shared.chan) - .waiting - .retain(|s| s.signal().as_ptr() != hook.signal().as_ptr()); - // If we were woken, but never polled, wake up another - if !self.received - && hook - .signal() - .as_any() - .downcast_ref::() - .unwrap() - .2 - .load(Ordering::SeqCst) - { - wait_lock(&self.receiver.shared.chan).try_wake_receiver_if_pending(); - } - } - } - } - - let token = self.selections.len(); - self.selections.push(Box::new(RecvSelection { - receiver, - token, - signalled: self.signalled.clone(), - hook: None, - mapper, - received: false, - phantom: Default::default(), - })); - - self - } - - fn wait_inner(mut self, deadline: Option) -> Option { - #[cfg(feature = "eventual-fairness")] - { - self.next_poll = self.rng.generate_range(0..self.selections.len()); - } - - let res = 'outer: loop { - // Init signals - for _ in 0..self.selections.len() { - if let Some(val) = self.selections[self.next_poll].init() { - break 'outer Some(val); - } - self.next_poll = (self.next_poll + 1) % self.selections.len(); - } - - // Speculatively poll - if let Some(msg) = self.poll() { - break 'outer Some(msg); - } - - loop { - if let Some(deadline) = deadline { - if let Some(dur) = deadline.checked_duration_since(Instant::now()) { - thread::park_timeout(dur); - } - } else { - thread::park(); - } - - if deadline.map(|d| Instant::now() >= d).unwrap_or(false) { - break 'outer self.poll(); - } - - let token = if let Some(token) = self.signalled.lock().pop_front() { - token - } else { - // Spurious wakeup, park again - continue; - }; - - // Attempt to receive a message - if let Some(msg) = self.selections[token].poll() { - break 'outer Some(msg); - } - } - }; - - // Deinit signals - for s in &mut self.selections { - s.deinit(); - } - - res - } - - fn poll(&mut self) -> Option { - for _ in 0..self.selections.len() { - if let Some(val) = self.selections[self.next_poll].poll() { - return Some(val); - } - self.next_poll = (self.next_poll + 1) % self.selections.len(); - } - None - } - - /// Wait until one of the events associated with this [`Selector`] has completed. If the `eventual-fairness` - /// feature flag is enabled, this method is fair and will handle a random event of those that are ready. - pub fn wait(self) -> T { - self.wait_inner(None).unwrap() - } - - /// Wait until one of the events associated with this [`Selector`] has completed or the timeout has expired. If the - /// `eventual-fairness` feature flag is enabled, this method is fair and will handle a random event of those that - /// are ready. - pub fn wait_timeout(self, dur: Duration) -> Result { - self.wait_inner(Some(Instant::now() + dur)) - .ok_or(SelectError::Timeout) - } - - /// Wait until one of the events associated with this [`Selector`] has completed or the deadline has been reached. - /// If the `eventual-fairness` feature flag is enabled, this method is fair and will handle a random event of those - /// that are ready. - pub fn wait_deadline(self, deadline: Instant) -> Result { - self.wait_inner(Some(deadline)).ok_or(SelectError::Timeout) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/src/signal.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/src/signal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/src/signal.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/src/signal.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -use std::{thread::{self, Thread}, time::Duration, any::Any}; - -pub trait Signal: Send + Sync + 'static { - /// Fire the signal, returning whether it is a stream signal. This is because streams do not - /// acquire a message when woken, so signals must be fired until one that does acquire a message - /// is fired, otherwise a wakeup could be missed, leading to a lost message until one is eagerly - /// grabbed by a receiver. - fn fire(&self) -> bool; - fn as_any(&self) -> &(dyn Any + 'static); - fn as_ptr(&self) -> *const (); -} - -pub struct SyncSignal(Thread); - -impl Default for SyncSignal { - fn default() -> Self { - Self(thread::current()) - } -} - -impl Signal for SyncSignal { - fn fire(&self) -> bool { - self.0.unpark(); - false - } - fn as_any(&self) -> &(dyn Any + 'static) { self } - fn as_ptr(&self) -> *const () { self as *const _ as *const () } -} - -impl SyncSignal { - pub fn wait(&self) { thread::park(); } - pub fn wait_timeout(&self, dur: Duration) { thread::park_timeout(dur); } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/after.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/after.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/after.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/after.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -// //! Tests for the after channel flavor. - -// #[macro_use] -// extern crate crossbeam_channel; -// extern crate crossbeam_utils; -// extern crate rand; - -// use std::sync::atomic::AtomicUsize; -// use std::sync::atomic::Ordering; -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{after, Select, TryRecvError}; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn fire() { -// let start = Instant::now(); -// let r = after(ms(50)); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// thread::sleep(ms(100)); - -// let fired = r.try_recv().unwrap(); -// assert!(start < fired); -// assert!(fired - start >= ms(50)); - -// let now = Instant::now(); -// assert!(fired < now); -// assert!(now - fired >= ms(50)); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - -// select! { -// recv(r) -> _ => panic!(), -// default => {} -// } - -// select! { -// recv(r) -> _ => panic!(), -// recv(after(ms(200))) -> _ => {} -// } -// } - -// #[test] -// fn capacity() { -// const COUNT: usize = 10; - -// for i in 0..COUNT { -// let r = after(ms(i as u64)); -// assert_eq!(r.capacity(), Some(1)); -// } -// } - -// #[test] -// fn len_empty_full() { -// let r = after(ms(50)); - -// assert_eq!(r.len(), 0); -// assert_eq!(r.is_empty(), true); -// assert_eq!(r.is_full(), false); - -// thread::sleep(ms(100)); - -// assert_eq!(r.len(), 1); -// assert_eq!(r.is_empty(), false); -// assert_eq!(r.is_full(), true); - -// r.try_recv().unwrap(); - -// assert_eq!(r.len(), 0); -// assert_eq!(r.is_empty(), true); -// assert_eq!(r.is_full(), false); -// } - -// #[test] -// fn try_recv() { -// let r = after(ms(200)); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(100)); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(200)); -// assert!(r.try_recv().is_ok()); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(200)); -// assert!(r.try_recv().is_err()); -// } - -// #[test] -// fn recv() { -// let start = Instant::now(); -// let r = after(ms(50)); - -// let fired = r.recv().unwrap(); -// assert!(start < fired); -// assert!(fired - start >= ms(50)); - -// let now = Instant::now(); -// assert!(fired < now); -// assert!(now - fired < fired - start); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn recv_timeout() { -// let start = Instant::now(); -// let r = after(ms(200)); - -// assert!(r.recv_timeout(ms(100)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(100)); -// assert!(now - start <= ms(150)); - -// let fired = r.recv_timeout(ms(200)).unwrap(); -// assert!(fired - start >= ms(200)); -// assert!(fired - start <= ms(250)); - -// assert!(r.recv_timeout(ms(200)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(400)); -// assert!(now - start <= ms(450)); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn recv_two() { -// let r1 = after(ms(50)); -// let r2 = after(ms(50)); - -// scope(|scope| { -// scope.spawn(|_| { -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// } -// }); -// scope.spawn(|_| { -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn recv_race() { -// select! { -// recv(after(ms(50))) -> _ => {} -// recv(after(ms(100))) -> _ => panic!(), -// } - -// select! { -// recv(after(ms(100))) -> _ => panic!(), -// recv(after(ms(50))) -> _ => {} -// } -// } - -// #[test] -// fn stress_default() { -// const COUNT: usize = 10; - -// for _ in 0..COUNT { -// select! { -// recv(after(ms(0))) -> _ => {} -// default => panic!(), -// } -// } - -// for _ in 0..COUNT { -// select! { -// recv(after(ms(100))) -> _ => panic!(), -// default => {} -// } -// } -// } - -// #[test] -// fn select() { -// const THREADS: usize = 4; -// const COUNT: usize = 1000; -// const TIMEOUT_MS: u64 = 100; - -// let v = (0..COUNT) -// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2))) -// .collect::>(); -// let hits = AtomicUsize::new(0); - -// scope(|scope| { -// for _ in 0..THREADS { -// scope.spawn(|_| { -// let v: Vec<&_> = v.iter().collect(); - -// loop { -// let timeout = after(ms(TIMEOUT_MS)); -// let mut sel = Select::new(); -// for r in &v { -// sel.recv(r); -// } -// let oper_timeout = sel.recv(&timeout); - -// let oper = sel.select(); -// match oper.index() { -// i if i == oper_timeout => { -// oper.recv(&timeout).unwrap(); -// break; -// } -// i => { -// oper.recv(&v[i]).unwrap(); -// hits.fetch_add(1, Ordering::SeqCst); -// } -// } -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(hits.load(Ordering::SeqCst), COUNT); -// } - -// #[test] -// fn ready() { -// const THREADS: usize = 4; -// const COUNT: usize = 1000; -// const TIMEOUT_MS: u64 = 100; - -// let v = (0..COUNT) -// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2))) -// .collect::>(); -// let hits = AtomicUsize::new(0); - -// scope(|scope| { -// for _ in 0..THREADS { -// scope.spawn(|_| { -// let v: Vec<&_> = v.iter().collect(); - -// loop { -// let timeout = after(ms(TIMEOUT_MS)); -// let mut sel = Select::new(); -// for r in &v { -// sel.recv(r); -// } -// let oper_timeout = sel.recv(&timeout); - -// loop { -// let i = sel.ready(); -// if i == oper_timeout { -// timeout.try_recv().unwrap(); -// return; -// } else if v[i].try_recv().is_ok() { -// hits.fetch_add(1, Ordering::SeqCst); -// break; -// } -// } -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(hits.load(Ordering::SeqCst), COUNT); -// } - -// #[test] -// fn stress_clone() { -// const RUNS: usize = 1000; -// const THREADS: usize = 10; -// const COUNT: usize = 50; - -// for i in 0..RUNS { -// let r = after(ms(i as u64)); - -// scope(|scope| { -// for _ in 0..THREADS { -// scope.spawn(|_| { -// let r = r.clone(); -// let _ = r.try_recv(); - -// for _ in 0..COUNT { -// drop(r.clone()); -// thread::yield_now(); -// } -// }); -// } -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn fairness() { -// const COUNT: usize = 1000; - -// for &dur in &[0, 1] { -// let mut hits = [0usize; 2]; - -// for _ in 0..COUNT { -// select! { -// recv(after(ms(dur))) -> _ => hits[0] += 1, -// recv(after(ms(dur))) -> _ => hits[1] += 1, -// } -// } - -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } -// } - -// #[test] -// fn fairness_duplicates() { -// const COUNT: usize = 1000; - -// for &dur in &[0, 1] { -// let mut hits = [0usize; 5]; - -// for _ in 0..COUNT { -// let r = after(ms(dur)); -// select! { -// recv(r) -> _ => hits[0] += 1, -// recv(r) -> _ => hits[1] += 1, -// recv(r) -> _ => hits[2] += 1, -// recv(r) -> _ => hits[3] += 1, -// recv(r) -> _ => hits[4] += 1, -// } -// } - -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/array.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/array.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/array.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,657 +0,0 @@ -//! Tests for the array channel flavor. - -extern crate crossbeam_utils; -extern crate rand; - -use std::any::Any; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; -use std::thread; -use std::time::Duration; - -use flume::{bounded, Receiver}; -use flume::{RecvError, RecvTimeoutError, TryRecvError}; -use flume::{SendError, SendTimeoutError, TrySendError}; -use crossbeam_utils::thread::scope; -use rand::{thread_rng, Rng}; - -fn ms(ms: u64) -> Duration { - Duration::from_millis(ms) -} - -#[test] -fn smoke() { - let (s, r) = bounded(1); - s.send(7).unwrap(); - assert_eq!(r.try_recv(), Ok(7)); - - s.send(8).unwrap(); - assert_eq!(r.recv(), Ok(8)); - - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout)); -} - -#[test] -fn capacity() { - for i in 1..10 { - let (s, r) = bounded::<()>(i); - assert_eq!(s.capacity(), Some(i)); - assert_eq!(r.capacity(), Some(i)); - } -} - -#[test] -fn len_empty_full() { - let (s, r) = bounded(2); - - assert_eq!(s.len(), 0); - assert_eq!(s.is_empty(), true); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 0); - assert_eq!(r.is_empty(), true); - assert_eq!(r.is_full(), false); - - s.send(()).unwrap(); - - assert_eq!(s.len(), 1); - assert_eq!(s.is_empty(), false); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 1); - assert_eq!(r.is_empty(), false); - assert_eq!(r.is_full(), false); - - s.send(()).unwrap(); - - assert_eq!(s.len(), 2); - assert_eq!(s.is_empty(), false); - assert_eq!(s.is_full(), true); - assert_eq!(r.len(), 2); - assert_eq!(r.is_empty(), false); - assert_eq!(r.is_full(), true); - - r.recv().unwrap(); - - assert_eq!(s.len(), 1); - assert_eq!(s.is_empty(), false); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 1); - assert_eq!(r.is_empty(), false); - assert_eq!(r.is_full(), false); -} - -#[test] -fn try_recv() { - let (s, r) = bounded(100); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - thread::sleep(ms(1500)); - assert_eq!(r.try_recv(), Ok(7)); - thread::sleep(ms(500)); - assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv() { - let (s, r) = bounded(100); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv(), Ok(7)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(8)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(9)); - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - s.send(8).unwrap(); - s.send(9).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv_timeout() { - let (s, r) = bounded::(100); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout)); - assert_eq!(r.recv_timeout(ms(1000)), Ok(7)); - assert_eq!( - r.recv_timeout(ms(1000)), - Err(RecvTimeoutError::Disconnected) - ); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn try_send() { - let (s, r) = bounded(1); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(s.try_send(1), Ok(())); - assert_eq!(s.try_send(2), Err(TrySendError::Full(2))); - thread::sleep(ms(1500)); - assert_eq!(s.try_send(3), Ok(())); - thread::sleep(ms(500)); - assert_eq!(s.try_send(4), Err(TrySendError::Disconnected(4))); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - assert_eq!(r.try_recv(), Ok(1)); - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(r.recv(), Ok(3)); - }); - }) - .unwrap(); -} - -#[test] -fn send() { - let (s, r) = bounded(1); - - scope(|scope| { - scope.spawn(|_| { - s.send(7).unwrap(); - thread::sleep(ms(1000)); - s.send(8).unwrap(); - thread::sleep(ms(1000)); - s.send(9).unwrap(); - thread::sleep(ms(1000)); - s.send(10).unwrap(); - }); - scope.spawn(|_| { - thread::sleep(ms(1500)); - assert_eq!(r.recv(), Ok(7)); - assert_eq!(r.recv(), Ok(8)); - assert_eq!(r.recv(), Ok(9)); - }); - }) - .unwrap(); -} - -#[test] -fn send_timeout() { - let (s, r) = bounded(2); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(s.send_timeout(1, ms(1000)), Ok(())); - assert_eq!(s.send_timeout(2, ms(1000)), Ok(())); - assert_eq!( - s.send_timeout(3, ms(500)), - Err(SendTimeoutError::Timeout(3)) - ); - thread::sleep(ms(1000)); - assert_eq!(s.send_timeout(4, ms(1000)), Ok(())); - thread::sleep(ms(1000)); - assert_eq!(s.send(5), Err(SendError(5))); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(1)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(2)); - assert_eq!(r.recv(), Ok(4)); - }); - }) - .unwrap(); -} - -#[test] -fn send_after_disconnect() { - let (s, r) = bounded(100); - - s.send(1).unwrap(); - s.send(2).unwrap(); - s.send(3).unwrap(); - - drop(r); - - assert_eq!(s.send(4), Err(SendError(4))); - assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5))); - assert_eq!( - s.send_timeout(6, ms(500)), - Err(SendTimeoutError::Disconnected(6)) - ); -} - -#[test] -fn recv_after_disconnect() { - let (s, r) = bounded(100); - - s.send(1).unwrap(); - s.send(2).unwrap(); - s.send(3).unwrap(); - - drop(s); - - assert_eq!(r.recv(), Ok(1)); - assert_eq!(r.recv(), Ok(2)); - assert_eq!(r.recv(), Ok(3)); - assert!(r.recv().is_err()); -} - -#[test] -fn len() { - const COUNT: usize = 25_000; - const CAP: usize = 1000; - - let (s, r) = bounded(CAP); - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); - - for _ in 0..CAP / 10 { - for i in 0..50 { - s.send(i).unwrap(); - assert_eq!(s.len(), i + 1); - } - - for i in 0..50 { - r.recv().unwrap(); - assert_eq!(r.len(), 50 - i - 1); - } - } - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); - - for i in 0..CAP { - s.send(i).unwrap(); - assert_eq!(s.len(), i + 1); - } - - for _ in 0..CAP { - r.recv().unwrap(); - } - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); - - scope(|scope| { - scope.spawn(|_| { - for i in 0..COUNT { - assert_eq!(r.recv(), Ok(i)); - let len = r.len(); - assert!(len <= CAP); - } - }); - - scope.spawn(|_| { - for i in 0..COUNT { - s.send(i).unwrap(); - let len = s.len(); - assert!(len <= CAP); - } - }); - }) - .unwrap(); - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); -} - -#[test] -fn disconnect_wakes_sender() { - let (s, r) = bounded(1); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(s.send(()), Ok(())); - assert_eq!(s.send(()), Err(SendError(()))); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - drop(r); - }); - }) - .unwrap(); -} - -#[test] -fn disconnect_wakes_receiver() { - let (s, r) = bounded::<()>(1); - - scope(|scope| { - scope.spawn(move |_| { - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - drop(s); - }); - }) - .unwrap(); -} - -#[test] -fn spsc() { - const COUNT: usize = 100_000; - - let (s, r) = bounded(3); - - scope(|scope| { - scope.spawn(move |_| { - for i in 0..COUNT { - assert_eq!(r.recv(), Ok(i)); - } - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - }) - .unwrap(); -} - -#[test] -fn mpmc() { - const COUNT: usize = 25_000; - const THREADS: usize = 4; - - let (s, r) = bounded::(3); - let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::>(); - - scope(|scope| { - for _ in 0..THREADS { - scope.spawn(|_| { - for _ in 0..COUNT { - let n = r.recv().unwrap(); - v[n].fetch_add(1, Ordering::SeqCst); - } - }); - } - for _ in 0..THREADS { - scope.spawn(|_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - } - }) - .unwrap(); - - for c in v { - assert_eq!(c.load(Ordering::SeqCst), THREADS); - } -} - -#[test] -fn stress_oneshot() { - const COUNT: usize = 10_000; - - for _ in 0..COUNT { - let (s, r) = bounded(1); - - scope(|scope| { - scope.spawn(|_| r.recv().unwrap()); - scope.spawn(|_| s.send(0).unwrap()); - }) - .unwrap(); - } -} - -#[test] -fn stress_iter() { - const COUNT: usize = 100_000; - - let (request_s, request_r) = bounded(1); - let (response_s, response_r) = bounded(1); - - scope(|scope| { - scope.spawn(move |_| { - let mut count = 0; - loop { - for x in response_r.try_iter() { - count += x; - if count == COUNT { - return; - } - } - request_s.send(()).unwrap(); - } - }); - - for _ in request_r.iter() { - if response_s.send(1).is_err() { - break; - } - } - }) - .unwrap(); -} - -#[test] -fn stress_timeout_two_threads() { - const COUNT: usize = 100; - - let (s, r) = bounded(2); - - scope(|scope| { - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - loop { - if let Ok(()) = s.send_timeout(i, ms(10)) { - break; - } - } - } - }); - - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - loop { - if let Ok(x) = r.recv_timeout(ms(10)) { - assert_eq!(x, i); - break; - } - } - } - }); - }) - .unwrap(); -} - -#[test] -fn drops() { - const RUNS: usize = 100; - - static DROPS: AtomicUsize = AtomicUsize::new(0); - - #[derive(Debug, PartialEq)] - struct DropCounter; - - impl Drop for DropCounter { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - let mut rng = thread_rng(); - - for _ in 0..RUNS { - let steps = rng.gen_range(0..10_000); - let additional = rng.gen_range(0..50); - - DROPS.store(0, Ordering::SeqCst); - let (s, r) = bounded::(50); - - scope(|scope| { - scope.spawn(|_| { - for _ in 0..steps { - r.recv().unwrap(); - } - }); - - scope.spawn(|_| { - for _ in 0..steps { - s.send(DropCounter).unwrap(); - } - }); - }) - .unwrap(); - - for _ in 0..additional { - s.send(DropCounter).unwrap(); - } - - assert_eq!(DROPS.load(Ordering::SeqCst), steps); - drop(s); - drop(r); - assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional); - } -} - -#[test] -fn linearizable() { - const COUNT: usize = 25_000; - const THREADS: usize = 4; - - let (s, r) = bounded(THREADS); - - scope(|scope| { - for _ in 0..THREADS { - scope.spawn(|_| { - for _ in 0..COUNT { - s.send(0).unwrap(); - r.try_recv().unwrap(); - } - }); - } - }) - .unwrap(); -} - -// #[test] -// fn fairness() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(COUNT); -// let (s2, r2) = bounded::<()>(COUNT); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let mut hits = [0usize; 2]; -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn fairness_duplicates() { -// const COUNT: usize = 10_000; - -// let (s, r) = bounded::<()>(COUNT); - -// for _ in 0..COUNT { -// s.send(()).unwrap(); -// } - -// let mut hits = [0usize; 5]; -// for _ in 0..COUNT { -// select! { -// recv(r) -> _ => hits[0] += 1, -// recv(r) -> _ => hits[1] += 1, -// recv(r) -> _ => hits[2] += 1, -// recv(r) -> _ => hits[3] += 1, -// recv(r) -> _ => hits[4] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn recv_in_send() { -// let (s, _r) = bounded(1); -// s.send(()).unwrap(); - -// #[allow(unreachable_code)] -// { -// select! { -// send(s, panic!()) -> _ => panic!(), -// default => {} -// } -// } - -// let (s, r) = bounded(2); -// s.send(()).unwrap(); - -// select! { -// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {} -// } -// } - -#[test] -fn channel_through_channel() { - const COUNT: usize = 1000; - - type T = Box; - - let (s, r) = bounded::(1); - - scope(|scope| { - scope.spawn(move |_| { - let mut s = s; - - for _ in 0..COUNT { - let (new_s, new_r) = bounded(1); - let new_r: T = Box::new(Some(new_r)); - - s.send(new_r).unwrap(); - s = new_s; - } - }); - - scope.spawn(move |_| { - let mut r = r; - - for _ in 0..COUNT { - r = r - .recv() - .unwrap() - .downcast_mut::>>() - .unwrap() - .take() - .unwrap() - } - }); - }) - .unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/async.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/async.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/async.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/async.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -#[cfg(feature = "async")] -use { - flume::*, - futures::{stream::FuturesUnordered, StreamExt, TryFutureExt, Future}, - futures::task::{Context, Waker, Poll}, - async_std::prelude::FutureExt, - std::{time::Duration, sync::{atomic::{AtomicUsize, Ordering}, Arc}}, -}; - -#[cfg(feature = "async")] -#[test] -fn r#async_recv() { - let (tx, rx) = unbounded(); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - tx.send(42u32).unwrap(); - }); - - async_std::task::block_on(async { - assert_eq!(rx.recv_async().await.unwrap(), 42); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn r#async_send() { - let (tx, rx) = bounded(1); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - assert_eq!(rx.recv(), Ok(42)); - }); - - async_std::task::block_on(async { - tx.send_async(42u32).await.unwrap(); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn r#async_recv_disconnect() { - let (tx, rx) = bounded::(0); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - drop(tx) - }); - - async_std::task::block_on(async { - assert_eq!(rx.recv_async().await, Err(RecvError::Disconnected)); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn r#async_send_disconnect() { - let (tx, rx) = bounded(0); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - drop(rx) - }); - - async_std::task::block_on(async { - assert_eq!(tx.send_async(42u32).await, Err(SendError(42))); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn r#async_recv_drop_recv() { - let (tx, rx) = bounded::(10); - - let recv_fut = rx.recv_async(); - - async_std::task::block_on(async { - let res = async_std::future::timeout(std::time::Duration::from_millis(500), rx.recv_async()).await; - assert!(res.is_err()); - }); - - let rx2 = rx.clone(); - let t = std::thread::spawn(move || { - async_std::task::block_on(async { - rx2.recv_async().await - }) - }); - - std::thread::sleep(std::time::Duration::from_millis(500)); - - tx.send(42).unwrap(); - - drop(recv_fut); - - assert_eq!(t.join().unwrap(), Ok(42)) -} - -#[cfg(feature = "async")] -#[async_std::test] -async fn r#async_send_1_million_no_drop_or_reorder() { - #[derive(Debug)] - enum Message { - Increment { - old: u64, - }, - ReturnCount, - } - - let (tx, rx) = unbounded(); - - let t = async_std::task::spawn(async move { - let mut count = 0u64; - - while let Ok(Message::Increment { old }) = rx.recv_async().await { - assert_eq!(old, count); - count += 1; - } - - count - }); - - for next in 0..1_000_000 { - tx.send(Message::Increment { old: next }).unwrap(); - } - - tx.send(Message::ReturnCount).unwrap(); - - let count = t.await; - assert_eq!(count, 1_000_000) -} - -#[cfg(feature = "async")] -#[async_std::test] -async fn parallel_async_receivers() { - let (tx, rx) = flume::unbounded(); - let send_fut = async move { - let n_sends: usize = 100000; - for _ in 0..n_sends { - tx.send_async(()).await.unwrap(); - } - }; - - async_std::task::spawn( - send_fut - .timeout(Duration::from_secs(5)) - .map_err(|_| panic!("Send timed out!")) - ); - - let mut futures_unordered = (0..250) - .map(|_| async { - while let Ok(()) = rx.recv_async().await - /* rx.recv() is OK */ - {} - }) - .collect::>(); - - let recv_fut = async { - while futures_unordered.next().await.is_some() {} - }; - - recv_fut - .timeout(Duration::from_secs(5)) - .map_err(|_| panic!("Receive timed out!")) - .await - .unwrap(); - - println!("recv end"); -} - -#[cfg(feature = "async")] -#[test] -fn change_waker() { - let (tx, rx) = flume::bounded(1); - tx.send(()).unwrap(); - - struct DebugWaker(Arc, Waker); - - impl DebugWaker { - fn new() -> Self { - let woken = Arc::new(AtomicUsize::new(0)); - let woken_cloned = woken.clone(); - let waker = waker_fn::waker_fn(move || { - woken.fetch_add(1, Ordering::SeqCst); - }); - DebugWaker(woken_cloned, waker) - } - - fn woken(&self) -> usize { - self.0.load(Ordering::SeqCst) - } - - fn ctx(&self) -> Context { - Context::from_waker(&self.1) - } - } - - // Check that the waker is correctly updated when sending tasks change their wakers - { - let send_fut = tx.send_async(()); - futures::pin_mut!(send_fut); - - let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new()); - - // Set the waker to waker1 - assert_eq!(send_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending); - - // Change the waker to waker2 - assert_eq!(send_fut.poll(&mut waker2.ctx()), Poll::Pending); - - // Wake the future - rx.recv().unwrap(); - - // Check that waker2 was woken and waker1 was not - assert_eq!(waker1.woken(), 0); - assert_eq!(waker2.woken(), 1); - } - - // Check that the waker is correctly updated when receiving tasks change their wakers - { - rx.recv().unwrap(); - let recv_fut = rx.recv_async(); - futures::pin_mut!(recv_fut); - - let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new()); - - // Set the waker to waker1 - assert_eq!(recv_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending); - - // Change the waker to waker2 - assert_eq!(recv_fut.poll(&mut waker2.ctx()), Poll::Pending); - - // Wake the future - tx.send(()).unwrap(); - - // Check that waker2 was woken and waker1 was not - assert_eq!(waker1.woken(), 0); - assert_eq!(waker2.woken(), 1); - } -} - -#[cfg(feature = "async")] -#[test] -fn spsc_single_threaded_value_ordering() { - async fn test() { - let (tx, rx) = flume::bounded(4); - tokio::select! { - _ = producer(tx) => {}, - _ = consumer(rx) => {}, - } - } - - async fn producer(tx: flume::Sender) { - for i in 0..100 { - tx.send_async(i).await.unwrap(); - } - } - - async fn consumer(rx: flume::Receiver) { - let mut expected = 0; - while let Ok(value) = rx.recv_async().await { - assert_eq!(value, expected); - expected += 1; - } - } - - let rt = tokio::runtime::Builder::new_current_thread().build().unwrap(); - rt.block_on(test()); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/basic.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/basic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/basic.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/basic.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,428 +0,0 @@ -use std::time::{Instant, Duration}; -use flume::*; - -#[test] -fn send_recv() { - let (tx, rx) = unbounded(); - for i in 0..1000 { tx.send(i).unwrap(); } - for i in 0..1000 { assert_eq!(rx.try_recv().unwrap(), i); } - assert!(rx.try_recv().is_err()); -} - -#[test] -fn iter() { - let (tx, rx) = unbounded(); - for i in 0..1000 { tx.send(i).unwrap(); } - drop(tx); - assert_eq!(rx.iter().sum::(), (0..1000).sum()); -} - -#[test] -fn try_iter() { - let (tx, rx) = unbounded(); - for i in 0..1000 { tx.send(i).unwrap(); } - assert_eq!(rx.try_iter().sum::(), (0..1000).sum()); -} - -#[test] -fn iter_threaded() { - let (tx, rx) = unbounded(); - for i in 0..1000 { - let tx = tx.clone(); - std::thread::spawn(move || tx.send(i).unwrap()); - } - drop(tx); - assert_eq!(rx.iter().sum::(), (0..1000).sum()); -} - -#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41 -#[test] -fn send_timeout() { - let dur = Duration::from_millis(350); - let max_error = Duration::from_millis(5); - let dur_min = dur.checked_sub(max_error).unwrap(); - let dur_max = dur.checked_add(max_error).unwrap(); - - let (tx, rx) = bounded(1); - - assert!(tx.send_timeout(42, dur).is_ok()); - - let then = Instant::now(); - assert!(tx.send_timeout(43, dur).is_err()); - let now = Instant::now(); - - let this = now.duration_since(then); - if !(dur_min < this && this < dur_max) { - panic!("timeout exceeded: {:?}", this); - } - - assert_eq!(rx.drain().count(), 1); - - drop(rx); - - assert!(tx.send_timeout(42, Duration::from_millis(350)).is_err()); -} - -#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41 -#[test] -fn recv_timeout() { - let dur = Duration::from_millis(350); - let max_error = Duration::from_millis(5); - let dur_min = dur.checked_sub(max_error).unwrap(); - let dur_max = dur.checked_add(max_error).unwrap(); - - let (tx, rx) = unbounded(); - let then = Instant::now(); - assert!(rx.recv_timeout(dur).is_err()); - let now = Instant::now(); - - let this = now.duration_since(then); - if !(dur_min < this && this < dur_max) { - panic!("timeout exceeded: {:?}", this); - } - - tx.send(42).unwrap(); - assert_eq!(rx.recv_timeout(dur), Ok(42)); - assert!(Instant::now().duration_since(now) < max_error); -} - -#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41 -#[test] -fn recv_deadline() { - let dur = Duration::from_millis(350); - let max_error = Duration::from_millis(5); - let dur_min = dur.checked_sub(max_error).unwrap(); - let dur_max = dur.checked_add(max_error).unwrap(); - - let (tx, rx) = unbounded(); - let then = Instant::now(); - assert!(rx.recv_deadline(then.checked_add(dur).unwrap()).is_err()); - let now = Instant::now(); - - let this = now.duration_since(then); - if !(dur_min < this && this < dur_max) { - panic!("timeout exceeded: {:?}", this); - } - - tx.send(42).unwrap(); - assert_eq!(rx.recv_deadline(now.checked_add(dur).unwrap()), Ok(42)); - assert!(Instant::now().duration_since(now) < max_error); -} - -#[test] -fn recv_timeout_missed_send() { - let (tx, rx) = bounded(10); - - assert!(rx.recv_timeout(Duration::from_millis(100)).is_err()); - - tx.send(42).unwrap(); - - assert_eq!(rx.recv(), Ok(42)); -} - -#[test] -fn disconnect_tx() { - let (tx, rx) = unbounded::<()>(); - drop(tx); - assert!(rx.recv().is_err()); -} - -#[test] -fn disconnect_rx() { - let (tx, rx) = unbounded(); - drop(rx); - assert!(tx.send(0).is_err()); -} - -#[test] -fn drain() { - let (tx, rx) = unbounded(); - - for i in 0..100 { - tx.send(i).unwrap(); - } - - assert_eq!(rx.drain().sum::(), (0..100).sum()); - - for i in 0..100 { - tx.send(i).unwrap(); - } - - for i in 0..100 { - tx.send(i).unwrap(); - } - - rx.recv().unwrap(); - - (1u32..100).chain(0..100).zip(rx).for_each(|(l, r)| assert_eq!(l, r)); -} - -#[test] -fn try_send() { - let (tx, rx) = bounded(5); - - for i in 0..5 { - tx.try_send(i).unwrap(); - } - - assert!(tx.try_send(42).is_err()); - - assert_eq!(rx.recv(), Ok(0)); - - assert_eq!(tx.try_send(42), Ok(())); - - assert_eq!(rx.recv(), Ok(1)); - drop(rx); - - assert!(tx.try_send(42).is_err()); -} - -#[test] -fn send_bounded() { - let (tx, rx) = bounded(5); - - for _ in 0..5 { - tx.send(42).unwrap(); - } - - let _ = rx.recv().unwrap(); - - tx.send(42).unwrap(); - - assert!(tx.try_send(42).is_err()); - - rx.drain(); - - let mut ts = Vec::new(); - for _ in 0..100 { - let tx = tx.clone(); - ts.push(std::thread::spawn(move || { - for i in 0..10000 { - tx.send(i).unwrap(); - } - })); - } - - drop(tx); - - assert_eq!(rx.iter().sum::(), (0..10000).sum::() * 100); - - for t in ts { - t.join().unwrap(); - } - - assert!(rx.recv().is_err()); -} - -#[test] -fn rendezvous() { - let (tx, rx) = bounded(0); - - for i in 0..5 { - let tx = tx.clone(); - let t = std::thread::spawn(move || { - assert!(tx.try_send(()).is_err()); - - let then = Instant::now(); - tx.send(()).unwrap(); - let now = Instant::now(); - - assert!(now.duration_since(then) > Duration::from_millis(100), "iter = {}", i); - }); - - std::thread::sleep(Duration::from_millis(1000)); - rx.recv().unwrap(); - - t.join().unwrap(); - } -} - -#[test] -fn hydra() { - let thread_num = 32; - let msg_num = 1000; - - let (main_tx, main_rx) = unbounded::<()>(); - - let mut txs = Vec::new(); - for _ in 0..thread_num { - let main_tx = main_tx.clone(); - let (tx, rx) = unbounded(); - txs.push(tx); - - std::thread::spawn(move || { - for msg in rx.iter() { - main_tx.send(msg).unwrap(); - } - }); - } - - drop(main_tx); - - for _ in 0..10 { - for tx in &txs { - for _ in 0..msg_num { - tx.send(Default::default()).unwrap(); - } - } - - for _ in 0..thread_num { - for _ in 0..msg_num { - main_rx.recv().unwrap(); - } - } - } - - drop(txs); - assert!(main_rx.recv().is_err()); -} - -#[test] -fn robin() { - let thread_num = 32; - let msg_num = 10; - - let (mut main_tx, main_rx) = bounded::<()>(1); - - for _ in 0..thread_num { - let (mut tx, rx) = bounded(100); - std::mem::swap(&mut tx, &mut main_tx); - - std::thread::spawn(move || { - for msg in rx.iter() { - tx.send(msg).unwrap(); - } - }); - } - - for _ in 0..10 { - let main_tx = main_tx.clone(); - std::thread::spawn(move || { - for _ in 0..msg_num { - main_tx.send(Default::default()).unwrap(); - } - }); - - for _ in 0..msg_num { - main_rx.recv().unwrap(); - } - } -} - -#[cfg(feature = "select")] -#[test] -fn select_general() { - #[derive(Debug, PartialEq)] - struct Foo(usize); - - let (tx0, rx0) = bounded(1); - let (tx1, rx1) = unbounded(); - - for (i, t) in vec![tx0.clone(), tx1].into_iter().enumerate() { - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - let _ = t.send(Foo(i)); - }); - } - - let x = Selector::new() - .recv(&rx0, |x| x) - .recv(&rx1, |x| x) - .wait() - .unwrap(); - - if x == Foo(0) { - assert!(rx1.recv().unwrap() == Foo(1)); - } else { - assert!(rx0.recv().unwrap() == Foo(0)); - } - - tx0.send(Foo(42)).unwrap(); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(100)); - assert_eq!(rx0.recv().unwrap(), Foo(42)); - assert_eq!(rx0.recv().unwrap(), Foo(43)); - - }); - - Selector::new() - .send(&tx0, Foo(43), |x| x) - .wait() - .unwrap(); - - t.join().unwrap(); -} - -struct MessageWithoutDebug(u32); - -#[test] -// This is a 'does it build' test, to make sure that the error types can turn -// into a std::error::Error without requiring the payload (which is not used -// there) to impl Debug. -fn std_error_without_debug() { - let (tx, rx) = unbounded::(); - - match tx.send(MessageWithoutDebug(1)) { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } - - match rx.recv() { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } - - match tx.try_send(MessageWithoutDebug(2)) { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } - - match rx.try_recv() { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } - - match tx.send_timeout(MessageWithoutDebug(3), Duration::from_secs(1000000)) { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } - - match rx.recv_timeout(Duration::from_secs(10000000)) { - Ok(_) => {} - Err(e) => { - let _std_err: &dyn std::error::Error = &e; - } - } -} - -#[test] -fn weak_close() { - let (tx, rx) = unbounded::<()>(); - let weak = tx.downgrade(); - drop(tx); - assert!(weak.upgrade().is_none()); - assert!(rx.is_disconnected()); - assert!(rx.try_recv().is_err()); -} - -#[test] -fn weak_upgrade() { - let (tx, rx) = unbounded(); - let weak = tx.downgrade(); - let tx2 = weak.upgrade().unwrap(); - drop(tx); - assert!(!rx.is_disconnected()); - tx2.send(()).unwrap(); - assert!(rx.try_recv().is_ok()); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/check_same_channel.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/check_same_channel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/check_same_channel.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/check_same_channel.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -#[test] -fn same_sender() { - let (tx1, _rx) = flume::unbounded::<()>(); - let tx2 = tx1.clone(); - - assert!(tx1.same_channel(&tx2)); - - let (tx3, _rx) = flume::unbounded::<()>(); - - assert!(!tx1.same_channel(&tx3)); - assert!(!tx2.same_channel(&tx3)); -} - -#[test] -fn same_receiver() { - let (_tx, rx1) = flume::unbounded::<()>(); - let rx2 = rx1.clone(); - - assert!(rx1.same_channel(&rx2)); - - let (_tx, rx3) = flume::unbounded::<()>(); - - assert!(!rx1.same_channel(&rx3)); - assert!(!rx2.same_channel(&rx3)); -} - -#[cfg(feature = "async")] -#[test] -fn same_send_sink() { - let (tx1, _rx) = flume::unbounded::<()>(); - let tx1 = tx1.into_sink(); - let tx2 = tx1.clone(); - - assert!(tx1.same_channel(&tx2)); - - let (tx3, _rx) = flume::unbounded::<()>(); - let tx3 = tx3.into_sink(); - - assert!(!tx1.same_channel(&tx3)); - assert!(!tx2.same_channel(&tx3)); -} - -#[cfg(feature = "async")] -#[test] -fn same_recv_stream() { - let (_tx, rx1) = flume::unbounded::<()>(); - let rx1 = rx1.into_stream(); - let rx2 = rx1.clone(); - - assert!(rx1.same_channel(&rx2)); - - let (_tx, rx3) = flume::unbounded::<()>(); - let rx3 = rx3.into_stream(); - - assert!(!rx1.same_channel(&rx3)); - assert!(!rx2.same_channel(&rx3)); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/golang.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/golang.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/golang.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/golang.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1445 +0,0 @@ -// //! Tests copied from Go and manually rewritten in Rust. -// //! -// //! Source: -// //! - https://github.com/golang/go -// //! -// //! Copyright & License: -// //! - Copyright (c) 2009 The Go Authors -// //! - https://golang.org/AUTHORS -// //! - https://golang.org/LICENSE -// //! - https://golang.org/PATENTS - -// use std::any::Any; -// use std::cell::Cell; -// use std::collections::HashMap; -// use std::sync::{Arc, Condvar, Mutex}; -// use std::thread; -// use std::time::Duration; - -// use flume::{bounded, tick, Receiver, Select, Sender}; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// struct Chan { -// inner: Arc>>, -// } - -// struct ChanInner { -// s: Option>, -// r: Receiver, -// } - -// impl Clone for Chan { -// fn clone(&self) -> Chan { -// Chan { -// inner: self.inner.clone(), -// } -// } -// } - -// impl Chan { -// fn send(&self, msg: T) { -// let s = self -// .inner -// .lock() -// .unwrap() -// .s -// .as_ref() -// .expect("sending into closed channel") -// .clone(); -// let _ = s.send(msg); -// } - -// fn try_recv(&self) -> Option { -// let r = self.inner.lock().unwrap().r.clone(); -// r.try_recv().ok() -// } - -// fn recv(&self) -> Option { -// let r = self.inner.lock().unwrap().r.clone(); -// r.recv().ok() -// } - -// fn close(&self) { -// self.inner -// .lock() -// .unwrap() -// .s -// .take() -// .expect("channel already closed"); -// } - -// fn rx(&self) -> Receiver { -// self.inner.lock().unwrap().r.clone() -// } - -// fn tx(&self) -> Sender { -// match self.inner.lock().unwrap().s.as_ref() { -// None => { -// let (s, r) = bounded(0); -// std::mem::forget(r); -// s -// } -// Some(s) => s.clone(), -// } -// } -// } - -// impl Iterator for Chan { -// type Item = T; - -// fn next(&mut self) -> Option { -// self.recv() -// } -// } - -// impl<'a, T> IntoIterator for &'a Chan { -// type Item = T; -// type IntoIter = Chan; - -// fn into_iter(self) -> Self::IntoIter { -// self.clone() -// } -// } - -// fn make(cap: usize) -> Chan { -// let (s, r) = bounded(cap); -// Chan { -// inner: Arc::new(Mutex::new(ChanInner { s: Some(s), r })), -// } -// } - -// #[derive(Clone)] -// struct WaitGroup(Arc); - -// struct WaitGroupInner { -// cond: Condvar, -// count: Mutex, -// } - -// impl WaitGroup { -// fn new() -> WaitGroup { -// WaitGroup(Arc::new(WaitGroupInner { -// cond: Condvar::new(), -// count: Mutex::new(0), -// })) -// } - -// fn add(&self, delta: i32) { -// let mut count = self.0.count.lock().unwrap(); -// *count += delta; -// assert!(*count >= 0); -// self.0.cond.notify_all(); -// } - -// fn done(&self) { -// self.add(-1); -// } - -// fn wait(&self) { -// let mut count = self.0.count.lock().unwrap(); -// while *count > 0 { -// count = self.0.cond.wait(count).unwrap(); -// } -// } -// } - -// struct Defer { -// f: Option>, -// } - -// impl Drop for Defer { -// fn drop(&mut self) { -// let f = self.f.take().unwrap(); -// let mut f = Some(f); -// let mut f = move || f.take().unwrap()(); -// f(); -// } -// } - -// macro_rules! defer { -// ($body:expr) => { -// let _defer = Defer { -// f: Some(Box::new(|| $body)), -// }; -// }; -// } - -// macro_rules! go { -// (@parse ref $v:ident, $($tail:tt)*) => {{ -// let ref $v = $v; -// go!(@parse $($tail)*) -// }}; -// (@parse move $v:ident, $($tail:tt)*) => {{ -// let $v = $v; -// go!(@parse $($tail)*) -// }}; -// (@parse $v:ident, $($tail:tt)*) => {{ -// let $v = $v.clone(); -// go!(@parse $($tail)*) -// }}; -// (@parse $body:expr) => { -// ::std::thread::spawn(move || { -// let res = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| { -// $body -// })); -// if res.is_err() { -// eprintln!("goroutine panicked: {:?}", res); -// ::std::process::abort(); -// } -// }) -// }; -// (@parse $($tail:tt)*) => { -// compile_error!("invalid `go!` syntax") -// }; -// ($($tail:tt)*) => {{ -// go!(@parse $($tail)*) -// }}; -// } - -// // https://github.com/golang/go/blob/master/test/chan/doubleselect.go -// mod doubleselect { -// use super::*; - -// const ITERATIONS: i32 = 10_000; - -// fn sender(n: i32, c1: Chan, c2: Chan, c3: Chan, c4: Chan) { -// defer! { c1.close() } -// defer! { c2.close() } -// defer! { c3.close() } -// defer! { c4.close() } - -// for i in 0..n { -// select! { -// send(c1.tx(), i) -> _ => {} -// send(c2.tx(), i) -> _ => {} -// send(c3.tx(), i) -> _ => {} -// send(c4.tx(), i) -> _ => {} -// } -// } -// } - -// fn mux(out: Chan, inp: Chan, done: Chan) { -// for v in inp { -// out.send(v); -// } -// done.send(true); -// } - -// fn recver(inp: Chan) { -// let mut seen = HashMap::new(); - -// for v in &inp { -// if seen.contains_key(&v) { -// panic!("got duplicate value for {}", v); -// } -// seen.insert(v, true); -// } -// } - -// #[test] -// fn main() { -// let c1 = make::(0); -// let c2 = make::(0); -// let c3 = make::(0); -// let c4 = make::(0); -// let done = make::(0); -// let cmux = make::(0); - -// go!(c1, c2, c3, c4, sender(ITERATIONS, c1, c2, c3, c4)); -// go!(cmux, c1, done, mux(cmux, c1, done)); -// go!(cmux, c2, done, mux(cmux, c2, done)); -// go!(cmux, c3, done, mux(cmux, c3, done)); -// go!(cmux, c4, done, mux(cmux, c4, done)); -// go!(done, cmux, { -// done.recv(); -// done.recv(); -// done.recv(); -// done.recv(); -// cmux.close(); -// }); -// recver(cmux); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/fifo.go -// mod fifo { -// use super::*; - -// const N: i32 = 10; - -// #[test] -// fn asynch_fifo() { -// let ch = make::(N as usize); -// for i in 0..N { -// ch.send(i); -// } -// for i in 0..N { -// if ch.recv() != Some(i) { -// panic!("bad receive"); -// } -// } -// } - -// fn chain(ch: Chan, val: i32, inp: Chan, out: Chan) { -// inp.recv(); -// if ch.recv() != Some(val) { -// panic!(val); -// } -// out.send(1); -// } - -// #[test] -// fn synch_fifo() { -// let ch = make::(0); -// let mut inp = make::(0); -// let start = inp.clone(); - -// for i in 0..N { -// let out = make::(0); -// go!(ch, i, inp, out, chain(ch, i, inp, out)); -// inp = out; -// } - -// start.send(0); -// for i in 0..N { -// ch.send(i); -// } -// inp.recv(); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/goroutines.go -// mod goroutines { -// use super::*; - -// fn f(left: Chan, right: Chan) { -// left.send(right.recv().unwrap()); -// } - -// #[test] -// fn main() { -// let n = 100i32; - -// let leftmost = make::(0); -// let mut right = leftmost.clone(); -// let mut left = leftmost.clone(); - -// for _ in 0..n { -// right = make::(0); -// go!(left, right, f(left, right)); -// left = right.clone(); -// } - -// go!(right, right.send(1)); -// leftmost.recv().unwrap(); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/nonblock.go -// mod nonblock { -// use super::*; - -// fn i32receiver(c: Chan, strobe: Chan) { -// if c.recv().unwrap() != 123 { -// panic!("i32 value"); -// } -// strobe.send(true); -// } - -// fn i32sender(c: Chan, strobe: Chan) { -// c.send(234); -// strobe.send(true); -// } - -// fn i64receiver(c: Chan, strobe: Chan) { -// if c.recv().unwrap() != 123456 { -// panic!("i64 value"); -// } -// strobe.send(true); -// } - -// fn i64sender(c: Chan, strobe: Chan) { -// c.send(234567); -// strobe.send(true); -// } - -// fn breceiver(c: Chan, strobe: Chan) { -// if !c.recv().unwrap() { -// panic!("b value"); -// } -// strobe.send(true); -// } - -// fn bsender(c: Chan, strobe: Chan) { -// c.send(true); -// strobe.send(true); -// } - -// fn sreceiver(c: Chan, strobe: Chan) { -// if c.recv().unwrap() != "hello" { -// panic!("x value"); -// } -// strobe.send(true); -// } - -// fn ssender(c: Chan, strobe: Chan) { -// c.send("hello again".to_string()); -// strobe.send(true); -// } - -// const MAX_TRIES: usize = 10000; // Up to 100ms per test. - -// #[test] -// fn main() { -// let ticker = tick(Duration::new(0, 10_000)); // 10 us -// let sleep = || { -// ticker.recv().unwrap(); -// ticker.recv().unwrap(); -// thread::yield_now(); -// thread::yield_now(); -// thread::yield_now(); -// }; - -// let sync = make::(0); - -// for buffer in 0..2 { -// let c32 = make::(buffer); -// let c64 = make::(buffer); -// let cb = make::(buffer); -// let cs = make::(buffer); - -// select! { -// recv(c32.rx()) -> _ => panic!("blocked i32sender"), -// default => {} -// } - -// select! { -// recv(c64.rx()) -> _ => panic!("blocked i64sender"), -// default => {} -// } - -// select! { -// recv(cb.rx()) -> _ => panic!("blocked bsender"), -// default => {} -// } - -// select! { -// recv(cs.rx()) -> _ => panic!("blocked ssender"), -// default => {} -// } - -// go!(c32, sync, i32receiver(c32, sync)); -// let mut try = 0; -// loop { -// select! { -// send(c32.tx(), 123) -> _ => break, -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("i32receiver buffer={}", buffer); -// panic!("fail") -// } -// sleep(); -// } -// } -// } -// sync.recv(); -// go!(c32, sync, i32sender(c32, sync)); -// if buffer > 0 { -// sync.recv(); -// } -// let mut try = 0; -// loop { -// select! { -// recv(c32.rx()) -> v => { -// if v != Ok(234) { -// panic!("i32sender value"); -// } -// break; -// } -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("i32sender buffer={}", buffer); -// panic!("fail"); -// } -// sleep(); -// } -// } -// } -// if buffer == 0 { -// sync.recv(); -// } - -// go!(c64, sync, i64receiver(c64, sync)); -// let mut try = 0; -// loop { -// select! { -// send(c64.tx(), 123456) -> _ => break, -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("i64receiver buffer={}", buffer); -// panic!("fail") -// } -// sleep(); -// } -// } -// } -// sync.recv(); -// go!(c64, sync, i64sender(c64, sync)); -// if buffer > 0 { -// sync.recv(); -// } -// let mut try = 0; -// loop { -// select! { -// recv(c64.rx()) -> v => { -// if v != Ok(234567) { -// panic!("i64sender value"); -// } -// break; -// } -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("i64sender buffer={}", buffer); -// panic!("fail"); -// } -// sleep(); -// } -// } -// } -// if buffer == 0 { -// sync.recv(); -// } - -// go!(cb, sync, breceiver(cb, sync)); -// let mut try = 0; -// loop { -// select! { -// send(cb.tx(), true) -> _ => break, -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("breceiver buffer={}", buffer); -// panic!("fail") -// } -// sleep(); -// } -// } -// } -// sync.recv(); -// go!(cb, sync, bsender(cb, sync)); -// if buffer > 0 { -// sync.recv(); -// } -// let mut try = 0; -// loop { -// select! { -// recv(cb.rx()) -> v => { -// if v != Ok(true) { -// panic!("bsender value"); -// } -// break; -// } -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("bsender buffer={}", buffer); -// panic!("fail"); -// } -// sleep(); -// } -// } -// } -// if buffer == 0 { -// sync.recv(); -// } - -// go!(cs, sync, sreceiver(cs, sync)); -// let mut try = 0; -// loop { -// select! { -// send(cs.tx(), "hello".to_string()) -> _ => break, -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("sreceiver buffer={}", buffer); -// panic!("fail") -// } -// sleep(); -// } -// } -// } -// sync.recv(); -// go!(cs, sync, ssender(cs, sync)); -// if buffer > 0 { -// sync.recv(); -// } -// let mut try = 0; -// loop { -// select! { -// recv(cs.rx()) -> v => { -// if v != Ok("hello again".to_string()) { -// panic!("ssender value"); -// } -// break; -// } -// default => { -// try += 1; -// if try > MAX_TRIES { -// println!("ssender buffer={}", buffer); -// panic!("fail"); -// } -// sleep(); -// } -// } -// } -// if buffer == 0 { -// sync.recv(); -// } -// } -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/select.go -// mod select { -// use super::*; - -// #[test] -// fn main() { -// let shift = Cell::new(0); -// let counter = Cell::new(0); - -// let get_value = || { -// counter.set(counter.get() + 1); -// 1 << shift.get() -// }; - -// let send = |mut a: Option<&Chan>, mut b: Option<&Chan>| { -// let mut i = 0; -// let never = make::(0); -// loop { -// let nil1 = never.tx(); -// let nil2 = never.tx(); -// let v1 = get_value(); -// let v2 = get_value(); -// select! { -// send(a.map(|c| c.tx()).unwrap_or(nil1), v1) -> _ => { -// i += 1; -// a = None; -// } -// send(b.map(|c| c.tx()).unwrap_or(nil2), v2) -> _ => { -// i += 1; -// b = None; -// } -// default => break, -// } -// shift.set(shift.get() + 1); -// } -// i -// }; - -// let a = make::(1); -// let b = make::(1); - -// assert_eq!(send(Some(&a), Some(&b)), 2); - -// let av = a.recv().unwrap(); -// let bv = b.recv().unwrap(); -// assert_eq!(av | bv, 3); - -// assert_eq!(send(Some(&a), None), 1); -// assert_eq!(counter.get(), 10); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/select2.go -// mod select2 { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/test/chan/select3.go -// mod select3 { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/test/chan/select4.go -// mod select4 { -// use super::*; - -// #[test] -// fn main() { -// let c = make::(1); -// let c1 = make::(0); -// c.send(42); -// select! { -// recv(c1.rx()) -> _ => panic!("BUG"), -// recv(c.rx()) -> v => assert_eq!(v, Ok(42)), -// } -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/select6.go -// mod select6 { -// use super::*; - -// #[test] -// fn main() { -// let c1 = make::(0); -// let c2 = make::(0); -// let c3 = make::(0); - -// go!(c1, c1.recv()); -// go!(c1, c2, c3, { -// select! { -// recv(c1.rx()) -> _ => panic!("dummy"), -// recv(c2.rx()) -> _ => c3.send(true), -// } -// c1.recv(); -// }); -// go!(c2, c2.send(true)); - -// c3.recv(); -// c1.send(true); -// c1.send(true); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/select7.go -// mod select7 { -// use super::*; - -// fn recv1(c: Chan) { -// c.recv().unwrap(); -// } - -// fn recv2(c: Chan) { -// select! { -// recv(c.rx()) -> _ => () -// } -// } - -// fn recv3(c: Chan) { -// let c2 = make::(1); -// select! { -// recv(c.rx()) -> _ => (), -// recv(c2.rx()) -> _ => () -// } -// } - -// fn send1(recv: fn(Chan)) { -// let c = make::(1); -// go!(c, recv(c)); -// thread::yield_now(); -// c.send(1); -// } - -// fn send2(recv: fn(Chan)) { -// let c = make::(1); -// go!(c, recv(c)); -// thread::yield_now(); -// select! { -// send(c.tx(), 1) -> _ => () -// } -// } - -// fn send3(recv: fn(Chan)) { -// let c = make::(1); -// go!(c, recv(c)); -// thread::yield_now(); -// let c2 = make::(1); -// select! { -// send(c.tx(), 1) -> _ => (), -// send(c2.tx(), 1) -> _ => () -// } -// } - -// #[test] -// fn main() { -// send1(recv1); -// send2(recv1); -// send3(recv1); -// send1(recv2); -// send2(recv2); -// send3(recv2); -// send1(recv3); -// send2(recv3); -// send3(recv3); -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/sieve1.go -// mod sieve1 { -// use super::*; - -// fn generate(ch: Chan) { -// let mut i = 2; -// loop { -// ch.send(i); -// i += 1; -// } -// } - -// fn filter(in_ch: Chan, out_ch: Chan, prime: i32) { -// for i in in_ch { -// if i % prime != 0 { -// out_ch.send(i); -// } -// } -// } - -// fn sieve(primes: Chan) { -// let mut ch = make::(1); -// go!(ch, generate(ch)); -// loop { -// let prime = ch.recv().unwrap(); -// primes.send(prime); - -// let ch1 = make::(1); -// go!(ch, ch1, prime, filter(ch, ch1, prime)); -// ch = ch1; -// } -// } - -// #[test] -// fn main() { -// let primes = make::(1); -// go!(primes, sieve(primes)); - -// let a = [ -// 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, -// 89, 97, -// ]; -// for item in a.iter() { -// let x = primes.recv().unwrap(); -// if x != *item { -// println!("{} != {}", x, item); -// panic!("fail"); -// } -// } -// } -// } - -// // https://github.com/golang/go/blob/master/test/chan/zerosize.go -// mod zerosize { -// use super::*; - -// #[test] -// fn zero_size_struct() { -// struct ZeroSize; -// let _ = make::(0); -// } - -// #[test] -// fn zero_size_array() { -// let _ = make::<[u8; 0]>(0); -// } -// } - -// // https://github.com/golang/go/blob/master/src/runtime/chan_test.go -// mod chan_test { -// use super::*; - -// #[test] -// fn test_chan() { -// const N: i32 = 200; - -// for cap in 0..N { -// { -// // Ensure that receive from empty chan blocks. -// let c = make::(cap as usize); - -// let recv1 = Arc::new(Mutex::new(false)); -// go!(c, recv1, { -// c.recv(); -// *recv1.lock().unwrap() = true; -// }); - -// let recv2 = Arc::new(Mutex::new(false)); -// go!(c, recv2, { -// c.recv(); -// *recv2.lock().unwrap() = true; -// }); - -// thread::sleep(ms(1)); - -// if *recv1.lock().unwrap() || *recv2.lock().unwrap() { -// panic!(); -// } - -// // Ensure that non-blocking receive does not block. -// select! { -// recv(c.rx()) -> _ => panic!(), -// default => {} -// } -// select! { -// recv(c.rx()) -> _ => panic!(), -// default => {} -// } - -// c.send(0); -// c.send(0); -// } - -// { -// // Ensure that send to full chan blocks. -// let c = make::(cap as usize); -// for i in 0..cap { -// c.send(i); -// } - -// let sent = Arc::new(Mutex::new(0)); -// go!(sent, c, { -// c.send(0); -// *sent.lock().unwrap() = 1; -// }); - -// thread::sleep(ms(1)); - -// if *sent.lock().unwrap() != 0 { -// panic!(); -// } - -// // Ensure that non-blocking send does not block. -// select! { -// send(c.tx(), 0) -> _ => panic!(), -// default => {} -// } -// c.recv(); -// } - -// { -// // Ensure that we receive 0 from closed chan. -// let c = make::(cap as usize); -// for i in 0..cap { -// c.send(i); -// } -// c.close(); - -// for i in 0..cap { -// let v = c.recv(); -// if v != Some(i) { -// panic!(); -// } -// } - -// if c.recv() != None { -// panic!(); -// } -// if c.try_recv() != None { -// panic!(); -// } -// } - -// { -// // Ensure that close unblocks receive. -// let c = make::(cap as usize); -// let done = make::(0); - -// go!(c, done, { -// let v = c.try_recv(); -// done.send(v.is_some()); -// }); - -// thread::sleep(ms(1)); -// c.close(); - -// if !done.recv().unwrap() { -// // panic!(); -// } -// } - -// { -// // Send 100 integers, -// // ensure that we receive them non-corrupted in FIFO order. -// let c = make::(cap as usize); -// go!(c, { -// for i in 0..100 { -// c.send(i); -// } -// }); -// for i in 0..100 { -// if c.recv() != Some(i) { -// panic!(); -// } -// } - -// // Same, but using recv2. -// go!(c, { -// for i in 0..100 { -// c.send(i); -// } -// }); -// for i in 0..100 { -// if c.recv() != Some(i) { -// panic!(); -// } -// } -// } -// } -// } - -// #[test] -// fn test_nonblock_recv_race() { -// const N: usize = 1000; - -// for _ in 0..N { -// let c = make::(1); -// c.send(1); - -// let t = go!(c, { -// select! { -// recv(c.rx()) -> _ => {} -// default => panic!("chan is not ready"), -// } -// }); - -// c.close(); -// c.recv(); -// t.join().unwrap(); -// } -// } - -// #[test] -// fn test_nonblock_select_race() { -// const N: usize = 1000; - -// let done = make::(1); -// for _ in 0..N { -// let c1 = make::(1); -// let c2 = make::(1); -// c1.send(1); - -// go!(c1, c2, done, { -// select! { -// recv(c1.rx()) -> _ => {} -// recv(c2.rx()) -> _ => {} -// default => { -// done.send(false); -// return; -// } -// } -// done.send(true); -// }); - -// c2.send(1); -// select! { -// recv(c1.rx()) -> _ => {} -// default => {} -// } -// if !done.recv().unwrap() { -// panic!("no chan is ready"); -// } -// } -// } - -// #[test] -// fn test_nonblock_select_race2() { -// const N: usize = 1000; - -// let done = make::(1); -// for _ in 0..N { -// let c1 = make::(1); -// let c2 = make::(0); -// c1.send(1); - -// go!(c1, c2, done, { -// select! { -// recv(c1.rx()) -> _ => {} -// recv(c2.rx()) -> _ => {} -// default => { -// done.send(false); -// return; -// } -// } -// done.send(true); -// }); - -// c2.close(); -// select! { -// recv(c1.rx()) -> _ => {} -// default => {} -// } -// if !done.recv().unwrap() { -// panic!("no chan is ready"); -// } -// } -// } - -// #[test] -// fn test_self_select() { -// // Ensure that send/recv on the same chan in select -// // does not crash nor deadlock. - -// for &cap in &[0, 10] { -// let wg = WaitGroup::new(); -// wg.add(2); -// let c = make::(cap); - -// for p in 0..2 { -// let p = p; -// go!(wg, p, c, { -// defer! { wg.done() } -// for i in 0..1000 { -// if p == 0 || i % 2 == 0 { -// select! { -// send(c.tx(), p) -> _ => {} -// recv(c.rx()) -> v => { -// if cap == 0 && v.ok() == Some(p) { -// panic!("self receive"); -// } -// } -// } -// } else { -// select! { -// recv(c.rx()) -> v => { -// if cap == 0 && v.ok() == Some(p) { -// panic!("self receive"); -// } -// } -// send(c.tx(), p) -> _ => {} -// } -// } -// } -// }); -// } -// wg.wait(); -// } -// } - -// #[test] -// fn test_select_stress() { -// let c = vec![ -// make::(0), -// make::(0), -// make::(2), -// make::(3), -// ]; - -// const N: usize = 10000; - -// // There are 4 goroutines that send N values on each of the chans, -// // + 4 goroutines that receive N values on each of the chans, -// // + 1 goroutine that sends N values on each of the chans in a single select, -// // + 1 goroutine that receives N values on each of the chans in a single select. -// // All these sends, receives and selects interact chaotically at runtime, -// // but we are careful that this whole construct does not deadlock. -// let wg = WaitGroup::new(); -// wg.add(10); - -// for k in 0..4 { -// go!(k, c, wg, { -// for _ in 0..N { -// c[k].send(0); -// } -// wg.done(); -// }); -// go!(k, c, wg, { -// for _ in 0..N { -// c[k].recv(); -// } -// wg.done(); -// }); -// } - -// go!(c, wg, { -// let mut n = [0; 4]; -// let mut c1 = c.iter().map(|c| Some(c.rx().clone())).collect::>(); - -// for _ in 0..4 * N { -// let index = { -// let mut sel = Select::new(); -// let mut opers = [!0; 4]; -// for &i in &[3, 2, 0, 1] { -// if let Some(c) = &c1[i] { -// opers[i] = sel.recv(c); -// } -// } - -// let oper = sel.select(); -// let mut index = !0; -// for i in 0..4 { -// if opers[i] == oper.index() { -// index = i; -// let _ = oper.recv(c1[i].as_ref().unwrap()); -// break; -// } -// } -// index -// }; - -// n[index] += 1; -// if n[index] == N { -// c1[index] = None; -// } -// } -// wg.done(); -// }); - -// go!(c, wg, { -// let mut n = [0; 4]; -// let mut c1 = c.iter().map(|c| Some(c.tx().clone())).collect::>(); - -// for _ in 0..4 * N { -// let index = { -// let mut sel = Select::new(); -// let mut opers = [!0; 4]; -// for &i in &[0, 1, 2, 3] { -// if let Some(c) = &c1[i] { -// opers[i] = sel.send(c); -// } -// } - -// let oper = sel.select(); -// let mut index = !0; -// for i in 0..4 { -// if opers[i] == oper.index() { -// index = i; -// let _ = oper.send(c1[i].as_ref().unwrap(), 0); -// break; -// } -// } -// index -// }; - -// n[index] += 1; -// if n[index] == N { -// c1[index] = None; -// } -// } -// wg.done(); -// }); - -// wg.wait(); -// } - -// #[test] -// fn test_select_fairness() { -// const TRIALS: usize = 10000; - -// let c1 = make::(TRIALS + 1); -// let c2 = make::(TRIALS + 1); - -// for _ in 0..TRIALS + 1 { -// c1.send(1); -// c2.send(2); -// } - -// let c3 = make::(0); -// let c4 = make::(0); -// let out = make::(0); -// let done = make::(0); -// let wg = WaitGroup::new(); - -// wg.add(1); -// go!(wg, c1, c2, c3, c4, out, done, { -// defer! { wg.done() }; -// loop { -// let b; -// select! { -// recv(c3.rx()) -> m => b = m.unwrap(), -// recv(c4.rx()) -> m => b = m.unwrap(), -// recv(c1.rx()) -> m => b = m.unwrap(), -// recv(c2.rx()) -> m => b = m.unwrap(), -// } -// select! { -// send(out.tx(), b) -> _ => {} -// recv(done.rx()) -> _ => return, -// } -// } -// }); - -// let (mut cnt1, mut cnt2) = (0, 0); -// for _ in 0..TRIALS { -// match out.recv() { -// Some(1) => cnt1 += 1, -// Some(2) => cnt2 += 1, -// b => panic!("unexpected value {:?} on channel", b), -// } -// } - -// // If the select in the goroutine is fair, -// // cnt1 and cnt2 should be about the same value. -// // With 10,000 trials, the expected margin of error at -// // a confidence level of five nines is 4.4172 / (2 * Sqrt(10000)). - -// let r = cnt1 as f64 / TRIALS as f64; -// let e = (r - 0.5).abs(); - -// if e > 4.4172 / (2.0 * (TRIALS as f64).sqrt()) { -// panic!( -// "unfair select: in {} trials, results were {}, {}", -// TRIALS, cnt1, cnt2, -// ); -// } - -// done.close(); -// wg.wait(); -// } - -// #[test] -// fn test_chan_send_interface() { -// struct Mt; - -// let c = make::>(1); -// c.send(Box::new(Mt)); - -// select! { -// send(c.tx(), Box::new(Mt)) -> _ => {} -// default => {} -// } - -// select! { -// send(c.tx(), Box::new(Mt)) -> _ => {} -// send(c.tx(), Box::new(Mt)) -> _ => {} -// default => {} -// } -// } - -// #[test] -// fn test_pseudo_random_send() { -// const N: usize = 100; - -// for cap in 0..N { -// let c = make::(cap); -// let l = Arc::new(Mutex::new(vec![0i32; N])); -// let done = make::(0); - -// go!(c, done, l, { -// let mut l = l.lock().unwrap(); -// for i in 0..N { -// thread::yield_now(); -// l[i] = c.recv().unwrap(); -// } -// done.send(true); -// }); - -// for _ in 0..N { -// select! { -// send(c.tx(), 1) -> _ => {} -// send(c.tx(), 0) -> _ => {} -// } -// } -// done.recv(); - -// let mut n0 = 0; -// let mut n1 = 0; -// for &i in l.lock().unwrap().iter() { -// n0 += (i + 1) % 2; -// n1 += i; -// } - -// if n0 <= N as i32 / 10 || n1 <= N as i32 / 10 { -// panic!( -// "Want pseudorandom, got {} zeros and {} ones (chan cap {})", -// n0, n1, cap, -// ); -// } -// } -// } - -// #[test] -// fn test_multi_consumer() { -// const NWORK: usize = 23; -// const NITER: usize = 271828; - -// let pn = [2, 3, 7, 11, 13, 17, 19, 23, 27, 31]; - -// let q = make::(NWORK * 3); -// let r = make::(NWORK * 3); - -// let wg = WaitGroup::new(); -// for i in 0..NWORK { -// wg.add(1); -// let w = i; -// go!(q, r, wg, pn, { -// for v in &q { -// if pn[w % pn.len()] == v { -// thread::yield_now(); -// } -// r.send(v); -// } -// wg.done(); -// }); -// } - -// let expect = Arc::new(Mutex::new(0)); -// go!(q, r, expect, wg, pn, { -// for i in 0..NITER { -// let v = pn[i % pn.len()]; -// *expect.lock().unwrap() += v; -// q.send(v); -// } -// q.close(); -// wg.wait(); -// r.close(); -// }); - -// let mut n = 0; -// let mut s = 0; -// for v in &r { -// n += 1; -// s += v; -// } - -// if n != NITER || s != *expect.lock().unwrap() { -// panic!(); -// } -// } - -// #[test] -// fn test_select_duplicate_channel() { -// // This test makes sure we can queue a G on -// // the same channel multiple times. -// let c = make::(0); -// let d = make::(0); -// let e = make::(0); - -// go!(c, d, e, { -// select! { -// recv(c.rx()) -> _ => {} -// recv(d.rx()) -> _ => {} -// recv(e.rx()) -> _ => {} -// } -// e.send(9); -// }); -// thread::sleep(ms(1)); - -// go!(c, c.recv()); -// thread::sleep(ms(1)); - -// d.send(7); -// e.recv(); -// c.send(8); -// } -// } - -// // https://github.com/golang/go/blob/master/test/closedchan.go -// mod closedchan { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/src/runtime/chanbarrier_test.go -// mod chanbarrier_test { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/src/runtime/race/testdata/chan_test.go -// mod race_chan_test { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/test/ken/chan.go -// mod chan { -// // TODO -// } - -// // https://github.com/golang/go/blob/master/test/ken/chan1.go -// mod chan1 { -// // TODO -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/iter.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/iter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/iter.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/iter.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -//! Tests for iteration over receivers. - -extern crate crossbeam_utils; - -use flume::unbounded; -use crossbeam_utils::thread::scope; - -#[test] -fn nested_recv_iter() { - let (s, r) = unbounded::(); - let (total_s, total_r) = unbounded::(); - - scope(|scope| { - scope.spawn(move |_| { - let mut acc = 0; - for x in r.iter() { - acc += x; - } - total_s.send(acc).unwrap(); - }); - - s.send(3).unwrap(); - s.send(1).unwrap(); - s.send(2).unwrap(); - drop(s); - assert_eq!(total_r.recv().unwrap(), 6); - }) - .unwrap(); -} - -#[test] -fn recv_iter_break() { - let (s, r) = unbounded::(); - let (count_s, count_r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - let mut count = 0; - for x in r.iter() { - if count >= 3 { - break; - } else { - count += x; - } - } - count_s.send(count).unwrap(); - }); - - s.send(2).unwrap(); - s.send(2).unwrap(); - s.send(2).unwrap(); - let _ = s.send(2); - drop(s); - assert_eq!(count_r.recv().unwrap(), 4); - }) - .unwrap(); -} - -#[test] -fn recv_try_iter() { - let (request_s, request_r) = unbounded(); - let (response_s, response_r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - let mut count = 0; - loop { - for x in response_r.try_iter() { - count += x; - if count == 6 { - return; - } - } - request_s.send(()).unwrap(); - } - }); - - for _ in request_r.iter() { - if response_s.send(2).is_err() { - break; - } - } - }) - .unwrap(); -} - -#[test] -fn recv_into_iter_owned() { - let mut iter = { - let (s, r) = unbounded::(); - s.send(1).unwrap(); - s.send(2).unwrap(); - r.into_iter() - }; - - assert_eq!(iter.next().unwrap(), 1); - assert_eq!(iter.next().unwrap(), 2); - assert_eq!(iter.next().is_none(), true); -} - -#[test] -fn recv_into_iter_borrowed() { - let (s, r) = unbounded::(); - s.send(1).unwrap(); - s.send(2).unwrap(); - drop(s); - - let mut iter = (&r).into_iter(); - assert_eq!(iter.next().unwrap(), 1); - assert_eq!(iter.next().unwrap(), 2); - assert_eq!(iter.next().is_none(), true); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/list.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/list.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/list.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/list.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,536 +0,0 @@ -//! Tests for the list channel flavor. - -extern crate crossbeam_utils; -extern crate rand; - -use std::any::Any; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; -use std::thread; -use std::time::Duration; - -use flume::{unbounded, Receiver}; -use flume::{RecvError, RecvTimeoutError, TryRecvError}; -use flume::{SendError, SendTimeoutError, TrySendError}; -use crossbeam_utils::thread::scope; -use rand::{thread_rng, Rng}; - -fn ms(ms: u64) -> Duration { - Duration::from_millis(ms) -} - -#[test] -fn smoke() { - let (s, r) = unbounded(); - s.try_send(7).unwrap(); - assert_eq!(r.try_recv(), Ok(7)); - - s.send(8).unwrap(); - assert_eq!(r.recv(), Ok(8)); - - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout)); -} - -#[test] -fn capacity() { - let (s, r) = unbounded::<()>(); - assert_eq!(s.capacity(), None); - assert_eq!(r.capacity(), None); -} - -#[test] -fn len_empty_full() { - let (s, r) = unbounded(); - - assert_eq!(s.len(), 0); - assert_eq!(s.is_empty(), true); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 0); - assert_eq!(r.is_empty(), true); - assert_eq!(r.is_full(), false); - - s.send(()).unwrap(); - - assert_eq!(s.len(), 1); - assert_eq!(s.is_empty(), false); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 1); - assert_eq!(r.is_empty(), false); - assert_eq!(r.is_full(), false); - - r.recv().unwrap(); - - assert_eq!(s.len(), 0); - assert_eq!(s.is_empty(), true); - assert_eq!(s.is_full(), false); - assert_eq!(r.len(), 0); - assert_eq!(r.is_empty(), true); - assert_eq!(r.is_full(), false); -} - -#[test] -fn try_recv() { - let (s, r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - thread::sleep(ms(1500)); - assert_eq!(r.try_recv(), Ok(7)); - thread::sleep(ms(500)); - assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv() { - let (s, r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv(), Ok(7)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(8)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(9)); - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - s.send(8).unwrap(); - s.send(9).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv_timeout() { - let (s, r) = unbounded::(); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout)); - assert_eq!(r.recv_timeout(ms(1000)), Ok(7)); - assert_eq!( - r.recv_timeout(ms(1000)), - Err(RecvTimeoutError::Disconnected) - ); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn try_send() { - let (s, r) = unbounded(); - for i in 0..1000 { - assert_eq!(s.try_send(i), Ok(())); - } - - drop(r); - assert_eq!(s.try_send(777), Err(TrySendError::Disconnected(777))); -} - -#[test] -fn send() { - let (s, r) = unbounded(); - for i in 0..1000 { - assert_eq!(s.send(i), Ok(())); - } - - drop(r); - assert_eq!(s.send(777), Err(SendError(777))); -} - -#[test] -fn send_timeout() { - let (s, r) = unbounded(); - for i in 0..1000 { - assert_eq!(s.send_timeout(i, ms(i as u64)), Ok(())); - } - - drop(r); - assert_eq!( - s.send_timeout(777, ms(0)), - Err(SendTimeoutError::Disconnected(777)) - ); -} - -#[test] -fn send_after_disconnect() { - let (s, r) = unbounded(); - - s.send(1).unwrap(); - s.send(2).unwrap(); - s.send(3).unwrap(); - - drop(r); - - assert_eq!(s.send(4), Err(SendError(4))); - assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5))); - assert_eq!( - s.send_timeout(6, ms(0)), - Err(SendTimeoutError::Disconnected(6)) - ); -} - -#[test] -fn recv_after_disconnect() { - let (s, r) = unbounded(); - - s.send(1).unwrap(); - s.send(2).unwrap(); - s.send(3).unwrap(); - - drop(s); - - assert_eq!(r.recv(), Ok(1)); - assert_eq!(r.recv(), Ok(2)); - assert_eq!(r.recv(), Ok(3)); - assert!(r.recv().is_err()); -} - -#[test] -fn len() { - let (s, r) = unbounded(); - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); - - for i in 0..50 { - s.send(i).unwrap(); - assert_eq!(s.len(), i + 1); - } - - for i in 0..50 { - r.recv().unwrap(); - assert_eq!(r.len(), 50 - i - 1); - } - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); -} - -#[test] -fn disconnect_wakes_receiver() { - let (s, r) = unbounded::<()>(); - - scope(|scope| { - scope.spawn(move |_| { - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - drop(s); - }); - }) - .unwrap(); -} - -#[test] -fn spsc() { - const COUNT: usize = 100_000; - - let (s, r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - for i in 0..COUNT { - assert_eq!(r.recv(), Ok(i)); - } - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - }) - .unwrap(); -} - -#[test] -fn mpmc() { - const COUNT: usize = 25_000; - const THREADS: usize = 4; - - let (s, r) = unbounded::(); - let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::>(); - - scope(|scope| { - for _ in 0..THREADS { - scope.spawn(|_| { - for _ in 0..COUNT { - let n = r.recv().unwrap(); - v[n].fetch_add(1, Ordering::SeqCst); - } - }); - } - for _ in 0..THREADS { - scope.spawn(|_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - } - }) - .unwrap(); - - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - - for c in v { - assert_eq!(c.load(Ordering::SeqCst), THREADS); - } -} - -#[test] -fn stress_oneshot() { - const COUNT: usize = 10_000; - - for _ in 0..COUNT { - let (s, r) = unbounded(); - - scope(|scope| { - scope.spawn(|_| r.recv().unwrap()); - scope.spawn(|_| s.send(0).unwrap()); - }) - .unwrap(); - } -} - -#[test] -fn stress_iter() { - const COUNT: usize = 100_000; - - let (request_s, request_r) = unbounded(); - let (response_s, response_r) = unbounded(); - - scope(|scope| { - scope.spawn(move |_| { - let mut count = 0; - loop { - for x in response_r.try_iter() { - count += x; - if count == COUNT { - return; - } - } - request_s.send(()).unwrap(); - } - }); - - for _ in request_r.iter() { - if response_s.send(1).is_err() { - break; - } - } - }) - .unwrap(); -} - -#[test] -fn stress_timeout_two_threads() { - const COUNT: usize = 100; - - let (s, r) = unbounded(); - - scope(|scope| { - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - s.send(i).unwrap(); - } - }); - - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - loop { - if let Ok(x) = r.recv_timeout(ms(10)) { - assert_eq!(x, i); - break; - } - } - } - }); - }) - .unwrap(); -} - -#[test] -fn drops() { - static DROPS: AtomicUsize = AtomicUsize::new(0); - - #[derive(Debug, PartialEq)] - struct DropCounter; - - impl Drop for DropCounter { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - let mut rng = thread_rng(); - - for _ in 0..100 { - let steps = rng.gen_range(0..10_000); - let additional = rng.gen_range(0..1000); - - DROPS.store(0, Ordering::SeqCst); - let (s, r) = unbounded::(); - - scope(|scope| { - scope.spawn(|_| { - for _ in 0..steps { - r.recv().unwrap(); - } - }); - - scope.spawn(|_| { - for _ in 0..steps { - s.send(DropCounter).unwrap(); - } - }); - }) - .unwrap(); - - for _ in 0..additional { - s.try_send(DropCounter).unwrap(); - } - - assert_eq!(DROPS.load(Ordering::SeqCst), steps); - drop(s); - drop(r); - assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional); - } -} - -#[test] -fn linearizable() { - const COUNT: usize = 25_000; - const THREADS: usize = 4; - - let (s, r) = unbounded(); - - scope(|scope| { - for _ in 0..THREADS { - scope.spawn(|_| { - for _ in 0..COUNT { - s.send(0).unwrap(); - r.try_recv().unwrap(); - } - }); - } - }) - .unwrap(); -} - -// #[test] -// fn fairness() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = unbounded::<()>(); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let mut hits = [0usize; 2]; -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn fairness_duplicates() { -// const COUNT: usize = 10_000; - -// let (s, r) = unbounded(); - -// for _ in 0..COUNT { -// s.send(()).unwrap(); -// } - -// let mut hits = [0usize; 5]; -// for _ in 0..COUNT { -// select! { -// recv(r) -> _ => hits[0] += 1, -// recv(r) -> _ => hits[1] += 1, -// recv(r) -> _ => hits[2] += 1, -// recv(r) -> _ => hits[3] += 1, -// recv(r) -> _ => hits[4] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn recv_in_send() { -// let (s, r) = unbounded(); -// s.send(()).unwrap(); - -// select! { -// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {} -// } -// } - -#[test] -fn channel_through_channel() { - const COUNT: usize = 1000; - - type T = Box; - - let (s, r) = unbounded::(); - - scope(|scope| { - scope.spawn(move |_| { - let mut s = s; - - for _ in 0..COUNT { - let (new_s, new_r) = unbounded(); - let new_r: T = Box::new(Some(new_r)); - - s.send(new_r).unwrap(); - s = new_s; - } - }); - - scope.spawn(move |_| { - let mut r = r; - - for _ in 0..COUNT { - r = r - .recv() - .unwrap() - .downcast_mut::>>() - .unwrap() - .take() - .unwrap() - } - }); - }) - .unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/method_sharing.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/method_sharing.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/method_sharing.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/method_sharing.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -#[cfg(feature = "async")] -use flume::*; - -#[cfg(feature = "async")] -#[async_std::test] -async fn sender() { - let (sender, receiver) = bounded(1); - - let sender_fut = sender.send_async(()); - assert_eq!(sender.is_disconnected(), sender_fut.is_disconnected()); - assert_eq!(sender.is_empty(), sender_fut.is_empty()); - assert_eq!(sender.is_full(), sender_fut.is_full()); - assert_eq!(sender.len(), sender_fut.len()); - assert_eq!(sender.capacity(), sender_fut.capacity()); - - let sender_sink = sender.sink(); - assert_eq!(sender.is_disconnected(), sender_sink.is_disconnected()); - assert_eq!(sender.is_empty(), sender_sink.is_empty()); - assert_eq!(sender.is_full(), sender_sink.is_full()); - assert_eq!(sender.len(), sender_sink.len()); - assert_eq!(sender.capacity(), sender_sink.capacity()); - - let receiver_fut = receiver.recv_async(); - assert_eq!(receiver.is_disconnected(), receiver_fut.is_disconnected()); - assert_eq!(receiver.is_empty(), receiver_fut.is_empty()); - assert_eq!(receiver.is_full(), receiver_fut.is_full()); - assert_eq!(receiver.len(), receiver_fut.len()); - assert_eq!(receiver.capacity(), receiver_fut.capacity()); - - let receiver_stream = receiver.stream(); - assert_eq!( - receiver.is_disconnected(), - receiver_stream.is_disconnected() - ); - assert_eq!(receiver.is_empty(), receiver_stream.is_empty()); - assert_eq!(receiver.is_full(), receiver_stream.is_full()); - assert_eq!(receiver.len(), receiver_stream.len()); - assert_eq!(receiver.capacity(), receiver_stream.capacity()); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/mpsc.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/mpsc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/mpsc.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/mpsc.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2095 +0,0 @@ -//! Tests copied from `std::sync::mpsc`. -//! -//! This is a copy of tests for the `std::sync::mpsc` channels from the standard library, but -//! modified to work with `crossbeam-channel` instead. -//! -//! Minor tweaks were needed to make the tests compile: -//! -//! - Replace `box` syntax with `Box::new`. -//! - Replace all uses of `Select` with `select!`. -//! - Change the imports. -//! - Join all spawned threads. -//! - Removed assertion from oneshot_multi_thread_send_close_stress tests. -//! -//! Source: -//! - https://github.com/rust-lang/rust/tree/master/src/libstd/sync/mpsc -//! -//! Copyright & License: -//! - Copyright 2013-2014 The Rust Project Developers -//! - Apache License, Version 2.0 or MIT license, at your option -//! - https://github.com/rust-lang/rust/blob/master/COPYRIGHT -//! - https://www.rust-lang.org/en-US/legal.html - -#[macro_use] -extern crate crossbeam_channel as cc; - -use std::sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError}; -use std::sync::mpsc::{SendError, TrySendError}; -use std::thread::JoinHandle; -use std::time::Duration; - -pub struct Sender { - pub inner: cc::Sender, -} - -impl Sender { - pub fn send(&self, t: T) -> Result<(), SendError> { - self.inner.send(t).map_err(|cc::SendError(m)| SendError(m)) - } -} - -impl Clone for Sender { - fn clone(&self) -> Sender { - Sender { - inner: self.inner.clone(), - } - } -} - -pub struct SyncSender { - pub inner: cc::Sender, -} - -impl SyncSender { - pub fn send(&self, t: T) -> Result<(), SendError> { - self.inner.send(t).map_err(|cc::SendError(m)| SendError(m)) - } - - pub fn try_send(&self, t: T) -> Result<(), TrySendError> { - self.inner.try_send(t).map_err(|err| match err { - cc::TrySendError::Full(m) => TrySendError::Full(m), - cc::TrySendError::Disconnected(m) => TrySendError::Disconnected(m), - }) - } -} - -impl Clone for SyncSender { - fn clone(&self) -> SyncSender { - SyncSender { - inner: self.inner.clone(), - } - } -} - -pub struct Receiver { - pub inner: cc::Receiver, -} - -impl Receiver { - pub fn try_recv(&self) -> Result { - self.inner.try_recv().map_err(|err| match err { - cc::TryRecvError::Empty => TryRecvError::Empty, - cc::TryRecvError::Disconnected => TryRecvError::Disconnected, - }) - } - - pub fn recv(&self) -> Result { - self.inner.recv().map_err(|_| RecvError) - } - - pub fn recv_timeout(&self, timeout: Duration) -> Result { - self.inner.recv_timeout(timeout).map_err(|err| match err { - cc::RecvTimeoutError::Timeout => RecvTimeoutError::Timeout, - cc::RecvTimeoutError::Disconnected => RecvTimeoutError::Disconnected, - }) - } - - pub fn iter(&self) -> Iter { - Iter { inner: self } - } - - pub fn try_iter(&self) -> TryIter { - TryIter { inner: self } - } -} - -impl<'a, T> IntoIterator for &'a Receiver { - type Item = T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Iter<'a, T> { - self.iter() - } -} - -impl IntoIterator for Receiver { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - IntoIter { inner: self } - } -} - -pub struct TryIter<'a, T: 'a> { - inner: &'a Receiver, -} - -impl<'a, T> Iterator for TryIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.inner.try_recv().ok() - } -} - -pub struct Iter<'a, T: 'a> { - inner: &'a Receiver, -} - -impl<'a, T> Iterator for Iter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.inner.recv().ok() - } -} - -pub struct IntoIter { - inner: Receiver, -} - -impl Iterator for IntoIter { - type Item = T; - - fn next(&mut self) -> Option { - self.inner.recv().ok() - } -} - -pub fn channel() -> (Sender, Receiver) { - let (s, r) = cc::unbounded(); - let s = Sender { inner: s }; - let r = Receiver { inner: r }; - (s, r) -} - -pub fn sync_channel(bound: usize) -> (SyncSender, Receiver) { - let (s, r) = cc::bounded(bound); - let s = SyncSender { inner: s }; - let r = Receiver { inner: r }; - (s, r) -} - -macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - crossbeam_channel_internal! { - $( - recv(($rx).inner) -> res => { - let $name = res.map_err(|_| ::std::sync::mpsc::RecvError); - $code - } - )+ - } - }) -} - -// Source: https://github.com/rust-lang/rust/blob/master/src/libstd/sync/mpsc/mod.rs -mod channel_tests { - use super::*; - - use std::env; - use std::thread; - use std::time::{Duration, Instant}; - - pub fn stress_factor() -> usize { - match env::var("RUST_TEST_STRESS") { - Ok(val) => val.parse().unwrap(), - Err(..) => 1, - } - } - - #[test] - fn smoke() { - let (tx, rx) = channel::(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } - - #[test] - fn drop_full() { - let (tx, _rx) = channel::>(); - tx.send(Box::new(1)).unwrap(); - } - - #[test] - fn drop_full_shared() { - let (tx, _rx) = channel::>(); - drop(tx.clone()); - drop(tx.clone()); - tx.send(Box::new(1)).unwrap(); - } - - #[test] - fn smoke_shared() { - let (tx, rx) = channel::(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - let tx = tx.clone(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } - - #[test] - fn smoke_threads() { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - tx.send(1).unwrap(); - }); - assert_eq!(rx.recv().unwrap(), 1); - t.join().unwrap(); - } - - #[test] - fn smoke_port_gone() { - let (tx, rx) = channel::(); - drop(rx); - assert!(tx.send(1).is_err()); - } - - #[test] - fn smoke_shared_port_gone() { - let (tx, rx) = channel::(); - drop(rx); - assert!(tx.send(1).is_err()) - } - - #[test] - fn smoke_shared_port_gone2() { - let (tx, rx) = channel::(); - drop(rx); - let tx2 = tx.clone(); - drop(tx); - assert!(tx2.send(1).is_err()); - } - - #[test] - fn port_gone_concurrent() { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - rx.recv().unwrap(); - }); - while tx.send(1).is_ok() {} - t.join().unwrap(); - } - - #[test] - fn port_gone_concurrent_shared() { - let (tx, rx) = channel::(); - let tx2 = tx.clone(); - let t = thread::spawn(move || { - rx.recv().unwrap(); - }); - while tx.send(1).is_ok() && tx2.send(1).is_ok() {} - t.join().unwrap(); - } - - #[test] - fn smoke_chan_gone() { - let (tx, rx) = channel::(); - drop(tx); - assert!(rx.recv().is_err()); - } - - #[test] - fn smoke_chan_gone_shared() { - let (tx, rx) = channel::<()>(); - let tx2 = tx.clone(); - drop(tx); - drop(tx2); - assert!(rx.recv().is_err()); - } - - #[test] - fn chan_gone_concurrent() { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - tx.send(1).unwrap(); - tx.send(1).unwrap(); - }); - while rx.recv().is_ok() {} - t.join().unwrap(); - } - - #[test] - fn stress() { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - for _ in 0..10000 { - tx.send(1).unwrap(); - } - }); - for _ in 0..10000 { - assert_eq!(rx.recv().unwrap(), 1); - } - t.join().ok().unwrap(); - } - - #[test] - fn stress_shared() { - const AMT: u32 = 10000; - const NTHREADS: u32 = 8; - let (tx, rx) = channel::(); - - let t = thread::spawn(move || { - for _ in 0..AMT * NTHREADS { - assert_eq!(rx.recv().unwrap(), 1); - } - match rx.try_recv() { - Ok(..) => panic!(), - _ => {} - } - }); - - let mut ts = Vec::with_capacity(NTHREADS as usize); - for _ in 0..NTHREADS { - let tx = tx.clone(); - let t = thread::spawn(move || { - for _ in 0..AMT { - tx.send(1).unwrap(); - } - }); - ts.push(t); - } - drop(tx); - t.join().ok().unwrap(); - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn send_from_outside_runtime() { - let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::(); - let t1 = thread::spawn(move || { - tx1.send(()).unwrap(); - for _ in 0..40 { - assert_eq!(rx2.recv().unwrap(), 1); - } - }); - rx1.recv().unwrap(); - let t2 = thread::spawn(move || { - for _ in 0..40 { - tx2.send(1).unwrap(); - } - }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); - } - - #[test] - fn recv_from_outside_runtime() { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - for _ in 0..40 { - assert_eq!(rx.recv().unwrap(), 1); - } - }); - for _ in 0..40 { - tx.send(1).unwrap(); - } - t.join().ok().unwrap(); - } - - #[test] - fn no_runtime() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let t1 = thread::spawn(move || { - assert_eq!(rx1.recv().unwrap(), 1); - tx2.send(2).unwrap(); - }); - let t2 = thread::spawn(move || { - tx1.send(1).unwrap(); - assert_eq!(rx2.recv().unwrap(), 2); - }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); - } - - #[test] - fn oneshot_single_thread_close_port_first() { - // Simple test of closing without sending - let (_tx, rx) = channel::(); - drop(rx); - } - - #[test] - fn oneshot_single_thread_close_chan_first() { - // Simple test of closing without sending - let (tx, _rx) = channel::(); - drop(tx); - } - - #[test] - fn oneshot_single_thread_send_port_close() { - // Testing that the sender cleans up the payload if receiver is closed - let (tx, rx) = channel::>(); - drop(rx); - assert!(tx.send(Box::new(0)).is_err()); - } - - #[test] - fn oneshot_single_thread_recv_chan_close() { - let (tx, rx) = channel::(); - drop(tx); - assert_eq!(rx.recv(), Err(RecvError)); - } - - #[test] - fn oneshot_single_thread_send_then_recv() { - let (tx, rx) = channel::>(); - tx.send(Box::new(10)).unwrap(); - assert!(*rx.recv().unwrap() == 10); - } - - #[test] - fn oneshot_single_thread_try_send_open() { - let (tx, rx) = channel::(); - assert!(tx.send(10).is_ok()); - assert!(rx.recv().unwrap() == 10); - } - - #[test] - fn oneshot_single_thread_try_send_closed() { - let (tx, rx) = channel::(); - drop(rx); - assert!(tx.send(10).is_err()); - } - - #[test] - fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = channel::(); - tx.send(10).unwrap(); - assert!(rx.recv() == Ok(10)); - } - - #[test] - fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = channel::(); - drop(tx); - assert!(rx.recv().is_err()); - } - - #[test] - fn oneshot_single_thread_peek_data() { - let (tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - tx.send(10).unwrap(); - assert_eq!(rx.try_recv(), Ok(10)); - } - - #[test] - fn oneshot_single_thread_peek_close() { - let (tx, rx) = channel::(); - drop(tx); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - } - - #[test] - fn oneshot_single_thread_peek_open() { - let (_tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - } - - #[test] - fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = channel::>(); - let t = thread::spawn(move || { - assert!(*rx.recv().unwrap() == 10); - }); - - tx.send(Box::new(10)).unwrap(); - t.join().unwrap(); - } - - #[test] - fn oneshot_multi_task_recv_then_close() { - let (tx, rx) = channel::>(); - let t = thread::spawn(move || { - drop(tx); - }); - thread::spawn(move || { - assert_eq!(rx.recv(), Err(RecvError)); - }) - .join() - .unwrap(); - t.join().unwrap(); - } - - #[test] - fn oneshot_multi_thread_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - drop(rx); - }); - ts.push(t); - drop(tx); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_send_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(2 * stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - drop(rx); - }); - ts.push(t); - thread::spawn(move || { - let _ = tx.send(1); - }) - .join() - .unwrap(); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_recv_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(2 * stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = channel::(); - let t = thread::spawn(move || { - thread::spawn(move || { - assert_eq!(rx.recv(), Err(RecvError)); - }) - .join() - .unwrap(); - }); - ts.push(t); - let t2 = thread::spawn(move || { - let t = thread::spawn(move || { - drop(tx); - }); - t.join().unwrap(); - }); - ts.push(t2); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_send_recv_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = channel::>(); - let t = thread::spawn(move || { - tx.send(Box::new(10)).unwrap(); - }); - ts.push(t); - assert!(*rx.recv().unwrap() == 10); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn stream_send_recv_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(2 * stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = channel(); - - if let Some(t) = send(tx, 0) { - ts.push(t); - } - if let Some(t2) = recv(rx, 0) { - ts.push(t2); - } - - fn send(tx: Sender>, i: i32) -> Option> { - if i == 10 { - return None; - } - - Some(thread::spawn(move || { - tx.send(Box::new(i)).unwrap(); - send(tx, i + 1); - })) - } - - fn recv(rx: Receiver>, i: i32) -> Option> { - if i == 10 { - return None; - } - - Some(thread::spawn(move || { - assert!(*rx.recv().unwrap() == i); - recv(rx, i + 1); - })) - } - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_single_thread_recv_timeout() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(())); - assert_eq!( - rx.recv_timeout(Duration::from_millis(1)), - Err(RecvTimeoutError::Timeout) - ); - tx.send(()).unwrap(); - assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(())); - } - - #[test] - fn stress_recv_timeout_two_threads() { - let (tx, rx) = channel(); - let stress = stress_factor() + 100; - let timeout = Duration::from_millis(100); - - let t = thread::spawn(move || { - for i in 0..stress { - if i % 2 == 0 { - thread::sleep(timeout * 2); - } - tx.send(1usize).unwrap(); - } - }); - - let mut recv_count = 0; - loop { - match rx.recv_timeout(timeout) { - Ok(n) => { - assert_eq!(n, 1usize); - recv_count += 1; - } - Err(RecvTimeoutError::Timeout) => continue, - Err(RecvTimeoutError::Disconnected) => break, - } - } - - assert_eq!(recv_count, stress); - t.join().unwrap() - } - - #[test] - fn recv_timeout_upgrade() { - let (tx, rx) = channel::<()>(); - let timeout = Duration::from_millis(1); - let _tx_clone = tx.clone(); - - let start = Instant::now(); - assert_eq!(rx.recv_timeout(timeout), Err(RecvTimeoutError::Timeout)); - assert!(Instant::now() >= start + timeout); - } - - #[test] - fn stress_recv_timeout_shared() { - let (tx, rx) = channel(); - let stress = stress_factor() + 100; - - let mut ts = Vec::with_capacity(stress); - for i in 0..stress { - let tx = tx.clone(); - let t = thread::spawn(move || { - thread::sleep(Duration::from_millis(i as u64 * 10)); - tx.send(1usize).unwrap(); - }); - ts.push(t); - } - - drop(tx); - - let mut recv_count = 0; - loop { - match rx.recv_timeout(Duration::from_millis(10)) { - Ok(n) => { - assert_eq!(n, 1usize); - recv_count += 1; - } - Err(RecvTimeoutError::Timeout) => continue, - Err(RecvTimeoutError::Disconnected) => break, - } - } - - assert_eq!(recv_count, stress); - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn recv_a_lot() { - // Regression test that we don't run out of stack in scheduler context - let (tx, rx) = channel(); - for _ in 0..10000 { - tx.send(()).unwrap(); - } - for _ in 0..10000 { - rx.recv().unwrap(); - } - } - - #[test] - fn shared_recv_timeout() { - let (tx, rx) = channel(); - let total = 5; - let mut ts = Vec::with_capacity(total); - for _ in 0..total { - let tx = tx.clone(); - let t = thread::spawn(move || { - tx.send(()).unwrap(); - }); - ts.push(t); - } - - for _ in 0..total { - rx.recv().unwrap(); - } - - assert_eq!( - rx.recv_timeout(Duration::from_millis(1)), - Err(RecvTimeoutError::Timeout) - ); - tx.send(()).unwrap(); - assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(())); - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn shared_chan_stress() { - let (tx, rx) = channel(); - let total = stress_factor() + 100; - let mut ts = Vec::with_capacity(total); - for _ in 0..total { - let tx = tx.clone(); - let t = thread::spawn(move || { - tx.send(()).unwrap(); - }); - ts.push(t); - } - - for _ in 0..total { - rx.recv().unwrap(); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn test_nested_recv_iter() { - let (tx, rx) = channel::(); - let (total_tx, total_rx) = channel::(); - - let t = thread::spawn(move || { - let mut acc = 0; - for x in rx.iter() { - acc += x; - } - total_tx.send(acc).unwrap(); - }); - - tx.send(3).unwrap(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); - drop(tx); - assert_eq!(total_rx.recv().unwrap(), 6); - t.join().unwrap(); - } - - #[test] - fn test_recv_iter_break() { - let (tx, rx) = channel::(); - let (count_tx, count_rx) = channel(); - - let t = thread::spawn(move || { - let mut count = 0; - for x in rx.iter() { - if count >= 3 { - break; - } else { - count += x; - } - } - count_tx.send(count).unwrap(); - }); - - tx.send(2).unwrap(); - tx.send(2).unwrap(); - tx.send(2).unwrap(); - let _ = tx.send(2); - drop(tx); - assert_eq!(count_rx.recv().unwrap(), 4); - t.join().unwrap(); - } - - #[test] - fn test_recv_try_iter() { - let (request_tx, request_rx) = channel(); - let (response_tx, response_rx) = channel(); - - // Request `x`s until we have `6`. - let t = thread::spawn(move || { - let mut count = 0; - loop { - for x in response_rx.try_iter() { - count += x; - if count == 6 { - return count; - } - } - request_tx.send(()).unwrap(); - } - }); - - for _ in request_rx.iter() { - if response_tx.send(2).is_err() { - break; - } - } - - assert_eq!(t.join().unwrap(), 6); - } - - #[test] - fn test_recv_into_iter_owned() { - let mut iter = { - let (tx, rx) = channel::(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); - - rx.into_iter() - }; - assert_eq!(iter.next().unwrap(), 1); - assert_eq!(iter.next().unwrap(), 2); - assert_eq!(iter.next().is_none(), true); - } - - #[test] - fn test_recv_into_iter_borrowed() { - let (tx, rx) = channel::(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); - drop(tx); - let mut iter = (&rx).into_iter(); - assert_eq!(iter.next().unwrap(), 1); - assert_eq!(iter.next().unwrap(), 2); - assert_eq!(iter.next().is_none(), true); - } - - #[test] - fn try_recv_states() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::<()>(); - let (tx3, rx3) = channel::<()>(); - let t = thread::spawn(move || { - rx2.recv().unwrap(); - tx1.send(1).unwrap(); - tx3.send(()).unwrap(); - rx2.recv().unwrap(); - drop(tx1); - tx3.send(()).unwrap(); - }); - - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); - t.join().unwrap(); - } - - // This bug used to end up in a livelock inside of the Receiver destructor - // because the internal state of the Shared packet was corrupted - #[test] - fn destroy_upgraded_shared_port_when_sender_still_active() { - let (tx, rx) = channel(); - let (tx2, rx2) = channel(); - let t = thread::spawn(move || { - rx.recv().unwrap(); // wait on a oneshot - drop(rx); // destroy a shared - tx2.send(()).unwrap(); - }); - // make sure the other thread has gone to sleep - for _ in 0..5000 { - thread::yield_now(); - } - - // upgrade to a shared chan and send a message - let tx2 = tx.clone(); - drop(tx); - tx2.send(()).unwrap(); - - // wait for the child thread to exit before we exit - rx2.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn issue_32114() { - let (tx, _) = channel(); - let _ = tx.send(123); - assert_eq!(tx.send(123), Err(SendError(123))); - } -} - -// Source: https://github.com/rust-lang/rust/blob/master/src/libstd/sync/mpsc/mod.rs -mod sync_channel_tests { - use super::*; - - use std::env; - use std::thread; - use std::time::Duration; - - pub fn stress_factor() -> usize { - match env::var("RUST_TEST_STRESS") { - Ok(val) => val.parse().unwrap(), - Err(..) => 1, - } - } - - #[test] - fn smoke() { - let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } - - #[test] - fn drop_full() { - let (tx, _rx) = sync_channel::>(1); - tx.send(Box::new(1)).unwrap(); - } - - #[test] - fn smoke_shared() { - let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - let tx = tx.clone(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } - - #[test] - fn recv_timeout() { - let (tx, rx) = sync_channel::(1); - assert_eq!( - rx.recv_timeout(Duration::from_millis(1)), - Err(RecvTimeoutError::Timeout) - ); - tx.send(1).unwrap(); - assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(1)); - } - - #[test] - fn smoke_threads() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - tx.send(1).unwrap(); - }); - assert_eq!(rx.recv().unwrap(), 1); - t.join().unwrap(); - } - - #[test] - fn smoke_port_gone() { - let (tx, rx) = sync_channel::(0); - drop(rx); - assert!(tx.send(1).is_err()); - } - - #[test] - fn smoke_shared_port_gone2() { - let (tx, rx) = sync_channel::(0); - drop(rx); - let tx2 = tx.clone(); - drop(tx); - assert!(tx2.send(1).is_err()); - } - - #[test] - fn port_gone_concurrent() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - rx.recv().unwrap(); - }); - while tx.send(1).is_ok() {} - t.join().unwrap(); - } - - #[test] - fn port_gone_concurrent_shared() { - let (tx, rx) = sync_channel::(0); - let tx2 = tx.clone(); - let t = thread::spawn(move || { - rx.recv().unwrap(); - }); - while tx.send(1).is_ok() && tx2.send(1).is_ok() {} - t.join().unwrap(); - } - - #[test] - fn smoke_chan_gone() { - let (tx, rx) = sync_channel::(0); - drop(tx); - assert!(rx.recv().is_err()); - } - - #[test] - fn smoke_chan_gone_shared() { - let (tx, rx) = sync_channel::<()>(0); - let tx2 = tx.clone(); - drop(tx); - drop(tx2); - assert!(rx.recv().is_err()); - } - - #[test] - fn chan_gone_concurrent() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - tx.send(1).unwrap(); - tx.send(1).unwrap(); - }); - while rx.recv().is_ok() {} - t.join().unwrap(); - } - - #[test] - fn stress() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - for _ in 0..10000 { - tx.send(1).unwrap(); - } - }); - for _ in 0..10000 { - assert_eq!(rx.recv().unwrap(), 1); - } - t.join().unwrap(); - } - - #[test] - fn stress_recv_timeout_two_threads() { - let (tx, rx) = sync_channel::(0); - - let t = thread::spawn(move || { - for _ in 0..10000 { - tx.send(1).unwrap(); - } - }); - - let mut recv_count = 0; - loop { - match rx.recv_timeout(Duration::from_millis(1)) { - Ok(v) => { - assert_eq!(v, 1); - recv_count += 1; - } - Err(RecvTimeoutError::Timeout) => continue, - Err(RecvTimeoutError::Disconnected) => break, - } - } - - assert_eq!(recv_count, 10000); - t.join().unwrap(); - } - - #[test] - fn stress_recv_timeout_shared() { - const AMT: u32 = 1000; - const NTHREADS: u32 = 8; - let (tx, rx) = sync_channel::(0); - let (dtx, drx) = sync_channel::<()>(0); - - let t = thread::spawn(move || { - let mut recv_count = 0; - loop { - match rx.recv_timeout(Duration::from_millis(10)) { - Ok(v) => { - assert_eq!(v, 1); - recv_count += 1; - } - Err(RecvTimeoutError::Timeout) => continue, - Err(RecvTimeoutError::Disconnected) => break, - } - } - - assert_eq!(recv_count, AMT * NTHREADS); - assert!(rx.try_recv().is_err()); - - dtx.send(()).unwrap(); - }); - - let mut ts = Vec::with_capacity(NTHREADS as usize); - for _ in 0..NTHREADS { - let tx = tx.clone(); - let t = thread::spawn(move || { - for _ in 0..AMT { - tx.send(1).unwrap(); - } - }); - ts.push(t); - } - - drop(tx); - - drx.recv().unwrap(); - for t in ts { - t.join().unwrap(); - } - t.join().unwrap(); - } - - #[test] - fn stress_shared() { - const AMT: u32 = 1000; - const NTHREADS: u32 = 8; - let (tx, rx) = sync_channel::(0); - let (dtx, drx) = sync_channel::<()>(0); - - let t = thread::spawn(move || { - for _ in 0..AMT * NTHREADS { - assert_eq!(rx.recv().unwrap(), 1); - } - match rx.try_recv() { - Ok(..) => panic!(), - _ => {} - } - dtx.send(()).unwrap(); - }); - - let mut ts = Vec::with_capacity(NTHREADS as usize); - for _ in 0..NTHREADS { - let tx = tx.clone(); - let t = thread::spawn(move || { - for _ in 0..AMT { - tx.send(1).unwrap(); - } - }); - ts.push(t); - } - drop(tx); - drx.recv().unwrap(); - for t in ts { - t.join().unwrap(); - } - t.join().unwrap(); - } - - #[test] - fn oneshot_single_thread_close_port_first() { - // Simple test of closing without sending - let (_tx, rx) = sync_channel::(0); - drop(rx); - } - - #[test] - fn oneshot_single_thread_close_chan_first() { - // Simple test of closing without sending - let (tx, _rx) = sync_channel::(0); - drop(tx); - } - - #[test] - fn oneshot_single_thread_send_port_close() { - // Testing that the sender cleans up the payload if receiver is closed - let (tx, rx) = sync_channel::>(0); - drop(rx); - assert!(tx.send(Box::new(0)).is_err()); - } - - #[test] - fn oneshot_single_thread_recv_chan_close() { - let (tx, rx) = sync_channel::(0); - drop(tx); - assert_eq!(rx.recv(), Err(RecvError)); - } - - #[test] - fn oneshot_single_thread_send_then_recv() { - let (tx, rx) = sync_channel::>(1); - tx.send(Box::new(10)).unwrap(); - assert!(*rx.recv().unwrap() == 10); - } - - #[test] - fn oneshot_single_thread_try_send_open() { - let (tx, rx) = sync_channel::(1); - assert_eq!(tx.try_send(10), Ok(())); - assert!(rx.recv().unwrap() == 10); - } - - #[test] - fn oneshot_single_thread_try_send_closed() { - let (tx, rx) = sync_channel::(0); - drop(rx); - assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10))); - } - - #[test] - fn oneshot_single_thread_try_send_closed2() { - let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); - } - - #[test] - fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = sync_channel::(1); - tx.send(10).unwrap(); - assert!(rx.recv() == Ok(10)); - } - - #[test] - fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = sync_channel::(0); - drop(tx); - assert!(rx.recv().is_err()); - } - - #[test] - fn oneshot_single_thread_try_recv_closed_with_data() { - let (tx, rx) = sync_channel::(1); - tx.send(10).unwrap(); - drop(tx); - assert_eq!(rx.try_recv(), Ok(10)); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - } - - #[test] - fn oneshot_single_thread_peek_data() { - let (tx, rx) = sync_channel::(1); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - tx.send(10).unwrap(); - assert_eq!(rx.try_recv(), Ok(10)); - } - - #[test] - fn oneshot_single_thread_peek_close() { - let (tx, rx) = sync_channel::(0); - drop(tx); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - } - - #[test] - fn oneshot_single_thread_peek_open() { - let (_tx, rx) = sync_channel::(0); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - } - - #[test] - fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = sync_channel::>(0); - let t = thread::spawn(move || { - assert!(*rx.recv().unwrap() == 10); - }); - - tx.send(Box::new(10)).unwrap(); - t.join().unwrap(); - } - - #[test] - fn oneshot_multi_task_recv_then_close() { - let (tx, rx) = sync_channel::>(0); - let t = thread::spawn(move || { - drop(tx); - }); - thread::spawn(move || { - assert_eq!(rx.recv(), Err(RecvError)); - }) - .join() - .unwrap(); - t.join().unwrap(); - } - - #[test] - fn oneshot_multi_thread_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - drop(rx); - }); - ts.push(t); - drop(tx); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_send_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - drop(rx); - }); - ts.push(t); - thread::spawn(move || { - let _ = tx.send(1); - }) - .join() - .unwrap(); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_recv_close_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(2 * stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - thread::spawn(move || { - assert_eq!(rx.recv(), Err(RecvError)); - }) - .join() - .unwrap(); - }); - ts.push(t); - let t2 = thread::spawn(move || { - thread::spawn(move || { - drop(tx); - }); - }); - ts.push(t2); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn oneshot_multi_thread_send_recv_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = sync_channel::>(0); - let t = thread::spawn(move || { - tx.send(Box::new(10)).unwrap(); - }); - ts.push(t); - assert!(*rx.recv().unwrap() == 10); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn stream_send_recv_stress() { - let stress_factor = stress_factor(); - let mut ts = Vec::with_capacity(2 * stress_factor); - for _ in 0..stress_factor { - let (tx, rx) = sync_channel::>(0); - - if let Some(t) = send(tx, 0) { - ts.push(t); - } - if let Some(t) = recv(rx, 0) { - ts.push(t); - } - - fn send(tx: SyncSender>, i: i32) -> Option> { - if i == 10 { - return None; - } - - Some(thread::spawn(move || { - tx.send(Box::new(i)).unwrap(); - send(tx, i + 1); - })) - } - - fn recv(rx: Receiver>, i: i32) -> Option> { - if i == 10 { - return None; - } - - Some(thread::spawn(move || { - assert!(*rx.recv().unwrap() == i); - recv(rx, i + 1); - })) - } - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn recv_a_lot() { - // Regression test that we don't run out of stack in scheduler context - let (tx, rx) = sync_channel(10000); - for _ in 0..10000 { - tx.send(()).unwrap(); - } - for _ in 0..10000 { - rx.recv().unwrap(); - } - } - - #[test] - fn shared_chan_stress() { - let (tx, rx) = sync_channel(0); - let total = stress_factor() + 100; - let mut ts = Vec::with_capacity(total); - for _ in 0..total { - let tx = tx.clone(); - let t = thread::spawn(move || { - tx.send(()).unwrap(); - }); - ts.push(t); - } - - for _ in 0..total { - rx.recv().unwrap(); - } - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn test_nested_recv_iter() { - let (tx, rx) = sync_channel::(0); - let (total_tx, total_rx) = sync_channel::(0); - - let t = thread::spawn(move || { - let mut acc = 0; - for x in rx.iter() { - acc += x; - } - total_tx.send(acc).unwrap(); - }); - - tx.send(3).unwrap(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); - drop(tx); - assert_eq!(total_rx.recv().unwrap(), 6); - t.join().unwrap(); - } - - #[test] - fn test_recv_iter_break() { - let (tx, rx) = sync_channel::(0); - let (count_tx, count_rx) = sync_channel(0); - - let t = thread::spawn(move || { - let mut count = 0; - for x in rx.iter() { - if count >= 3 { - break; - } else { - count += x; - } - } - count_tx.send(count).unwrap(); - }); - - tx.send(2).unwrap(); - tx.send(2).unwrap(); - tx.send(2).unwrap(); - let _ = tx.try_send(2); - drop(tx); - assert_eq!(count_rx.recv().unwrap(), 4); - t.join().unwrap(); - } - - #[test] - fn try_recv_states() { - let (tx1, rx1) = sync_channel::(1); - let (tx2, rx2) = sync_channel::<()>(1); - let (tx3, rx3) = sync_channel::<()>(1); - let t = thread::spawn(move || { - rx2.recv().unwrap(); - tx1.send(1).unwrap(); - tx3.send(()).unwrap(); - rx2.recv().unwrap(); - drop(tx1); - tx3.send(()).unwrap(); - }); - - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); - t.join().unwrap(); - } - - // This bug used to end up in a livelock inside of the Receiver destructor - // because the internal state of the Shared packet was corrupted - #[test] - fn destroy_upgraded_shared_port_when_sender_still_active() { - let (tx, rx) = sync_channel::<()>(0); - let (tx2, rx2) = sync_channel::<()>(0); - let t = thread::spawn(move || { - rx.recv().unwrap(); // wait on a oneshot - drop(rx); // destroy a shared - tx2.send(()).unwrap(); - }); - // make sure the other thread has gone to sleep - for _ in 0..5000 { - thread::yield_now(); - } - - // upgrade to a shared chan and send a message - let tx2 = tx.clone(); - drop(tx); - tx2.send(()).unwrap(); - - // wait for the child thread to exit before we exit - rx2.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn send1() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - rx.recv().unwrap(); - }); - assert_eq!(tx.send(1), Ok(())); - t.join().unwrap(); - } - - #[test] - fn send2() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - drop(rx); - }); - assert!(tx.send(1).is_err()); - t.join().unwrap(); - } - - #[test] - fn send3() { - let (tx, rx) = sync_channel::(1); - assert_eq!(tx.send(1), Ok(())); - let t = thread::spawn(move || { - drop(rx); - }); - assert!(tx.send(1).is_err()); - t.join().unwrap(); - } - - #[test] - fn send4() { - let (tx, rx) = sync_channel::(0); - let tx2 = tx.clone(); - let (done, donerx) = channel(); - let done2 = done.clone(); - let t = thread::spawn(move || { - assert!(tx.send(1).is_err()); - done.send(()).unwrap(); - }); - let t2 = thread::spawn(move || { - assert!(tx2.send(2).is_err()); - done2.send(()).unwrap(); - }); - drop(rx); - donerx.recv().unwrap(); - donerx.recv().unwrap(); - t.join().unwrap(); - t2.join().unwrap(); - } - - #[test] - fn try_send1() { - let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); - } - - #[test] - fn try_send2() { - let (tx, _rx) = sync_channel::(1); - assert_eq!(tx.try_send(1), Ok(())); - assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); - } - - #[test] - fn try_send3() { - let (tx, rx) = sync_channel::(1); - assert_eq!(tx.try_send(1), Ok(())); - drop(rx); - assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); - } - - #[test] - fn issue_15761() { - fn repro() { - let (tx1, rx1) = sync_channel::<()>(3); - let (tx2, rx2) = sync_channel::<()>(3); - - let _t = thread::spawn(move || { - rx1.recv().unwrap(); - tx2.try_send(()).unwrap(); - }); - - tx1.try_send(()).unwrap(); - rx2.recv().unwrap(); - } - - for _ in 0..100 { - repro() - } - } -} - -// Source: https://github.com/rust-lang/rust/blob/master/src/libstd/sync/mpsc/select.rs -mod select_tests { - use super::*; - - use std::thread; - - #[test] - fn smoke() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - tx1.send(1).unwrap(); - select! { - foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, - _bar = rx2.recv() => { panic!() } - } - tx2.send(2).unwrap(); - select! { - _foo = rx1.recv() => { panic!() }, - bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } - } - drop(tx1); - select! { - foo = rx1.recv() => { assert!(foo.is_err()); }, - _bar = rx2.recv() => { panic!() } - } - drop(tx2); - select! { - bar = rx2.recv() => { assert!(bar.is_err()); } - } - } - - #[test] - fn smoke2() { - let (_tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (_tx3, rx3) = channel::(); - let (_tx4, rx4) = channel::(); - let (tx5, rx5) = channel::(); - tx5.send(4).unwrap(); - select! { - _foo = rx1.recv() => { panic!("1") }, - _foo = rx2.recv() => { panic!("2") }, - _foo = rx3.recv() => { panic!("3") }, - _foo = rx4.recv() => { panic!("4") }, - foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } - } - } - - #[test] - fn closed() { - let (_tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - drop(tx2); - - select! { - _a1 = rx1.recv() => { panic!() }, - a2 = rx2.recv() => { assert!(a2.is_err()); } - } - } - - #[test] - fn unblocks() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::(); - - let t = thread::spawn(move || { - for _ in 0..20 { - thread::yield_now(); - } - tx1.send(1).unwrap(); - rx3.recv().unwrap(); - for _ in 0..20 { - thread::yield_now(); - } - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - _b = rx2.recv() => { panic!() } - } - tx3.send(1).unwrap(); - select! { - a = rx1.recv() => { assert!(a.is_err()) }, - _b = rx2.recv() => { panic!() } - } - t.join().unwrap(); - } - - #[test] - fn both_ready() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let t = thread::spawn(move || { - for _ in 0..20 { - thread::yield_now(); - } - tx1.send(1).unwrap(); - tx2.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); - tx3.send(()).unwrap(); - t.join().unwrap(); - } - - #[test] - fn stress() { - const AMT: i32 = 10000; - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let t = thread::spawn(move || { - for i in 0..AMT { - if i % 2 == 0 { - tx1.send(i).unwrap(); - } else { - tx2.send(i).unwrap(); - } - rx3.recv().unwrap(); - } - }); - - for i in 0..AMT { - select! { - i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, - i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } - } - tx3.send(()).unwrap(); - } - t.join().unwrap(); - } - - #[allow(unused_must_use)] - #[test] - fn cloning() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let t = thread::spawn(move || { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); - t.join().unwrap(); - } - - #[allow(unused_must_use)] - #[test] - fn cloning2() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let t = thread::spawn(move || { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); - t.join().unwrap(); - } - - #[test] - fn cloning3() { - let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::<()>(); - let (tx3, rx3) = channel::<()>(); - let t = thread::spawn(move || { - select! { - _ = rx1.recv() => panic!(), - _ = rx2.recv() => {} - } - tx3.send(()).unwrap(); - }); - - for _ in 0..1000 { - thread::yield_now(); - } - drop(tx1.clone()); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn preflight1() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight2() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight3() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight4() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn preflight5() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn preflight6() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn preflight7() { - let (tx, rx) = channel::<()>(); - drop(tx); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn preflight8() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn preflight9() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - select! { - _ = rx.recv() => {} - } - } - - #[test] - fn oneshot_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - let t = thread::spawn(move || { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { - thread::yield_now() - } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn stream_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - tx1.send(()).unwrap(); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - rx1.recv().unwrap(); - let t = thread::spawn(move || { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { - thread::yield_now() - } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn shared_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - drop(tx1.clone()); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - let t = thread::spawn(move || { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { - thread::yield_now() - } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn sync1() { - let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } - } - - #[test] - fn sync2() { - let (tx, rx) = sync_channel::(0); - let t = thread::spawn(move || { - for _ in 0..100 { - thread::yield_now() - } - tx.send(1).unwrap(); - }); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } - t.join().unwrap(); - } - - #[test] - fn sync3() { - let (tx1, rx1) = sync_channel::(0); - let (tx2, rx2): (Sender, Receiver) = channel(); - let t = thread::spawn(move || { - tx1.send(1).unwrap(); - }); - let t2 = thread::spawn(move || { - tx2.send(2).unwrap(); - }); - select! { - n = rx1.recv() => { - let n = n.unwrap(); - assert_eq!(n, 1); - assert_eq!(rx2.recv().unwrap(), 2); - }, - n = rx2.recv() => { - let n = n.unwrap(); - assert_eq!(n, 2); - assert_eq!(rx1.recv().unwrap(), 1); - } - } - t.join().unwrap(); - t2.join().unwrap(); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/never.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/never.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/never.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/never.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -// //! Tests for the never channel flavor. - -// #[macro_use] -// extern crate crossbeam_channel; -// extern crate rand; - -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{never, tick, unbounded}; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn smoke() { -// select! { -// recv(never::()) -> _ => panic!(), -// default => {} -// } -// } - -// #[test] -// fn optional() { -// let (s, r) = unbounded::(); -// s.send(1).unwrap(); -// s.send(2).unwrap(); - -// let mut r = Some(&r); -// select! { -// recv(r.unwrap_or(&never())) -> _ => {} -// default => panic!(), -// } - -// r = None; -// select! { -// recv(r.unwrap_or(&never())) -> _ => panic!(), -// default => {} -// } -// } - -// #[test] -// fn tick_n() { -// let mut r = tick(ms(100)); -// let mut step = 0; - -// loop { -// select! { -// recv(r) -> _ => step += 1, -// default(ms(500)) => break, -// } - -// if step == 10 { -// r = never(); -// } -// } - -// assert_eq!(step, 10); -// } - -// #[test] -// fn capacity() { -// let r = never::(); -// assert_eq!(r.capacity(), Some(0)); -// } - -// #[test] -// fn len_empty_full() { -// let r = never::(); -// assert_eq!(r.len(), 0); -// assert_eq!(r.is_empty(), true); -// assert_eq!(r.is_full(), true); -// } - -// #[test] -// fn try_recv() { -// let r = never::(); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(100)); -// assert!(r.try_recv().is_err()); -// } - -// #[test] -// fn recv_timeout() { -// let start = Instant::now(); -// let r = never::(); - -// assert!(r.recv_timeout(ms(100)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(100)); -// assert!(now - start <= ms(150)); - -// assert!(r.recv_timeout(ms(100)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(200)); -// assert!(now - start <= ms(250)); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/ready.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/ready.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/ready.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/ready.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,837 +0,0 @@ -// //! Tests for channel readiness using the `Select` struct. - -// extern crate crossbeam_channel; -// extern crate crossbeam_utils; - -// use std::any::Any; -// use std::cell::Cell; -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{after, bounded, tick, unbounded}; -// use crossbeam_channel::{Receiver, Select, TryRecvError, TrySendError}; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn smoke1() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// s1.send(1).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// assert_eq!(sel.ready(), 0); -// assert_eq!(r1.try_recv(), Ok(1)); - -// s2.send(2).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// assert_eq!(sel.ready(), 1); -// assert_eq!(r2.try_recv(), Ok(2)); -// } - -// #[test] -// fn smoke2() { -// let (_s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (_s3, r3) = unbounded::(); -// let (_s4, r4) = unbounded::(); -// let (s5, r5) = unbounded::(); - -// s5.send(5).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// sel.recv(&r3); -// sel.recv(&r4); -// sel.recv(&r5); -// assert_eq!(sel.ready(), 4); -// assert_eq!(r5.try_recv(), Ok(5)); -// } - -// #[test] -// fn disconnected() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// drop(s1); -// thread::sleep(ms(500)); -// s2.send(5).unwrap(); -// }); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready_timeout(ms(1000)) { -// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } - -// r2.recv().unwrap(); -// }) -// .unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready_timeout(ms(1000)) { -// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// drop(s2); -// }); - -// let mut sel = Select::new(); -// sel.recv(&r2); -// match sel.ready_timeout(ms(1000)) { -// Ok(0) => assert_eq!(r2.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// assert!(sel.try_ready().is_err()); - -// drop(s1); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.try_ready() { -// Ok(0) => assert!(r1.try_recv().is_err()), -// _ => panic!(), -// } - -// s2.send(2).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r2); -// match sel.try_ready() { -// Ok(0) => assert_eq!(r2.try_recv(), Ok(2)), -// _ => panic!(), -// } - -// let mut sel = Select::new(); -// sel.recv(&r2); -// assert!(sel.try_ready().is_err()); - -// let mut sel = Select::new(); -// assert!(sel.try_ready().is_err()); -// } - -// #[test] -// fn timeout() { -// let (_s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(1500)); -// s2.send(2).unwrap(); -// }); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// assert!(sel.ready_timeout(ms(1000)).is_err()); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready_timeout(ms(1000)) { -// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)), -// _ => panic!(), -// } -// }) -// .unwrap(); - -// scope(|scope| { -// let (s, r) = unbounded::(); - -// scope.spawn(move |_| { -// thread::sleep(ms(500)); -// drop(s); -// }); - -// let mut sel = Select::new(); -// assert!(sel.ready_timeout(ms(1000)).is_err()); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.try_ready() { -// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default_when_disconnected() { -// let (_, r) = unbounded::(); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.try_ready() { -// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } - -// let (_, r) = unbounded::(); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready_timeout(ms(1000)) { -// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } - -// let (s, _) = bounded::(0); - -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.try_ready() { -// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))), -// _ => panic!(), -// } - -// let (s, _) = bounded::(0); - -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.ready_timeout(ms(1000)) { -// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))), -// _ => panic!(), -// } -// } - -// #[test] -// fn default_only() { -// let start = Instant::now(); - -// let mut sel = Select::new(); -// assert!(sel.try_ready().is_err()); -// let now = Instant::now(); -// assert!(now - start <= ms(50)); - -// let start = Instant::now(); -// let mut sel = Select::new(); -// assert!(sel.ready_timeout(ms(500)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(450)); -// assert!(now - start <= ms(550)); -// } - -// #[test] -// fn unblocks() { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = bounded::(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s2.send(2).unwrap(); -// }); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready_timeout(ms(1000)) { -// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)), -// _ => panic!(), -// } -// }) -// .unwrap(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// assert_eq!(r1.recv().unwrap(), 1); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s1); -// let oper2 = sel.send(&s2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => oper.send(&s1, 1).unwrap(), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn both_ready() { -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s1.send(1).unwrap(); -// assert_eq!(r2.recv().unwrap(), 2); -// }); - -// for _ in 0..2 { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.send(&s2); -// match sel.ready() { -// 0 => assert_eq!(r1.try_recv(), Ok(1)), -// 1 => s2.try_send(2).unwrap(), -// _ => panic!(), -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn cloning1() { -// scope(|scope| { -// let (s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (s3, r3) = unbounded::<()>(); - -// scope.spawn(move |_| { -// r3.recv().unwrap(); -// drop(s1.clone()); -// assert!(r3.try_recv().is_err()); -// s1.send(1).unwrap(); -// r3.recv().unwrap(); -// }); - -// s3.send(()).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready() { -// 0 => drop(r1.try_recv()), -// 1 => drop(r2.try_recv()), -// _ => panic!(), -// } - -// s3.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn cloning2() { -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = unbounded::<()>(); -// let (_s3, _r3) = unbounded::<()>(); - -// scope(|scope| { -// scope.spawn(move |_| { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready() { -// 0 => panic!(), -// 1 => drop(r2.try_recv()), -// _ => panic!(), -// } -// }); - -// thread::sleep(ms(500)); -// drop(s1.clone()); -// s2.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn preflight1() { -// let (s, r) = unbounded(); -// s.send(()).unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => drop(r.try_recv()), -// _ => panic!(), -// } -// } - -// #[test] -// fn preflight2() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => assert_eq!(r.try_recv(), Ok(())), -// _ => panic!(), -// } - -// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); -// } - -// #[test] -// fn preflight3() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); -// r.recv().unwrap(); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)), -// _ => panic!(), -// } -// } - -// #[test] -// fn duplicate_operations() { -// let (s, r) = unbounded::(); -// let hit = vec![Cell::new(false); 4]; - -// while hit.iter().map(|h| h.get()).any(|hit| !hit) { -// let mut sel = Select::new(); -// sel.recv(&r); -// sel.recv(&r); -// sel.send(&s); -// sel.send(&s); -// match sel.ready() { -// 0 => { -// assert!(r.try_recv().is_ok()); -// hit[0].set(true); -// } -// 1 => { -// assert!(r.try_recv().is_ok()); -// hit[1].set(true); -// } -// 2 => { -// assert!(s.try_send(0).is_ok()); -// hit[2].set(true); -// } -// 3 => { -// assert!(s.try_send(0).is_ok()); -// hit[3].set(true); -// } -// _ => panic!(), -// } -// } -// } - -// #[test] -// fn nesting() { -// let (s, r) = unbounded::(); - -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.ready() { -// 0 => { -// assert!(s.try_send(0).is_ok()); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => { -// assert_eq!(r.try_recv(), Ok(0)); - -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.ready() { -// 0 => { -// assert!(s.try_send(1).is_ok()); - -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => { -// assert_eq!(r.try_recv(), Ok(1)); -// } -// _ => panic!(), -// } -// } -// _ => panic!(), -// } -// } -// _ => panic!(), -// } -// } -// _ => panic!(), -// } -// } - -// #[test] -// fn stress_recv() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded(); -// let (s2, r2) = bounded(5); -// let (s3, r3) = bounded(0); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// r3.recv().unwrap(); - -// s2.send(i).unwrap(); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// match sel.ready() { -// 0 => assert_eq!(r1.try_recv(), Ok(i)), -// 1 => assert_eq!(r2.try_recv(), Ok(i)), -// _ => panic!(), -// } - -// s3.send(()).unwrap(); -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_send() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// assert_eq!(r1.recv().unwrap(), i); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// sel.send(&s1); -// sel.send(&s2); -// match sel.ready() { -// 0 => assert!(s1.try_send(i).is_ok()), -// 1 => assert!(s2.try_send(i).is_ok()), -// _ => panic!(), -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_mixed() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.send(&s2); -// match sel.ready() { -// 0 => assert_eq!(r1.try_recv(), Ok(i)), -// 1 => assert!(s2.try_send(i).is_ok()), -// _ => panic!(), -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_timeout_two_threads() { -// const COUNT: usize = 20; - -// let (s, r) = bounded(2); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// let done = false; -// while !done { -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.ready_timeout(ms(100)) { -// Err(_) => {} -// Ok(0) => { -// assert!(s.try_send(i).is_ok()); -// break; -// } -// Ok(_) => panic!(), -// } -// } -// } -// }); - -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// let mut done = false; -// while !done { -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready_timeout(ms(100)) { -// Err(_) => {} -// Ok(0) => { -// assert_eq!(r.try_recv(), Ok(i)); -// done = true; -// } -// Ok(_) => panic!(), -// } -// } -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn send_recv_same_channel() { -// let (s, r) = bounded::(0); -// let mut sel = Select::new(); -// sel.send(&s); -// sel.recv(&r); -// assert!(sel.ready_timeout(ms(100)).is_err()); - -// let (s, r) = unbounded::(); -// let mut sel = Select::new(); -// sel.send(&s); -// sel.recv(&r); -// match sel.ready_timeout(ms(100)) { -// Err(_) => panic!(), -// Ok(0) => assert!(s.try_send(0).is_ok()), -// Ok(_) => panic!(), -// } -// } - -// #[test] -// fn channel_through_channel() { -// const COUNT: usize = 1000; - -// type T = Box; - -// for cap in 1..4 { -// let (s, r) = bounded::(cap); - -// scope(|scope| { -// scope.spawn(move |_| { -// let mut s = s; - -// for _ in 0..COUNT { -// let (new_s, new_r) = bounded(cap); -// let new_r: T = Box::new(Some(new_r)); - -// { -// let mut sel = Select::new(); -// sel.send(&s); -// match sel.ready() { -// 0 => assert!(s.try_send(new_r).is_ok()), -// _ => panic!(), -// } -// } - -// s = new_s; -// } -// }); - -// scope.spawn(move |_| { -// let mut r = r; - -// for _ in 0..COUNT { -// let new = { -// let mut sel = Select::new(); -// sel.recv(&r); -// match sel.ready() { -// 0 => r -// .try_recv() -// .unwrap() -// .downcast_mut::>>() -// .unwrap() -// .take() -// .unwrap(), -// _ => panic!(), -// } -// }; -// r = new; -// } -// }); -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn fairness1() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(COUNT); -// let (s2, r2) = unbounded::<()>(); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let hits = vec![Cell::new(0usize); 4]; -// for _ in 0..COUNT { -// let after = after(ms(0)); -// let tick = tick(ms(0)); - -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// sel.recv(&after); -// sel.recv(&tick); -// match sel.ready() { -// 0 => { -// r1.try_recv().unwrap(); -// hits[0].set(hits[0].get() + 1); -// } -// 1 => { -// r2.try_recv().unwrap(); -// hits[1].set(hits[1].get() + 1); -// } -// 2 => { -// after.try_recv().unwrap(); -// hits[2].set(hits[2].get() + 1); -// } -// 3 => { -// tick.try_recv().unwrap(); -// hits[3].set(hits[3].get() + 1); -// } -// _ => panic!(), -// } -// } -// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn fairness2() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = bounded::<()>(1); -// let (s3, r3) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// let mut sel = Select::new(); -// let mut oper1 = None; -// let mut oper2 = None; -// if s1.is_empty() { -// oper1 = Some(sel.send(&s1)); -// } -// if s2.is_empty() { -// oper2 = Some(sel.send(&s2)); -// } -// let oper3 = sel.send(&s3); -// let oper = sel.select(); -// match oper.index() { -// i if Some(i) == oper1 => assert!(oper.send(&s1, ()).is_ok()), -// i if Some(i) == oper2 => assert!(oper.send(&s2, ()).is_ok()), -// i if i == oper3 => assert!(oper.send(&s3, ()).is_ok()), -// _ => unreachable!(), -// } -// } -// }); - -// let hits = vec![Cell::new(0usize); 3]; -// for _ in 0..COUNT { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// sel.recv(&r3); -// loop { -// match sel.ready() { -// 0 => { -// if r1.try_recv().is_ok() { -// hits[0].set(hits[0].get() + 1); -// break; -// } -// } -// 1 => { -// if r2.try_recv().is_ok() { -// hits[1].set(hits[1].get() + 1); -// break; -// } -// } -// 2 => { -// if r3.try_recv().is_ok() { -// hits[2].set(hits[2].get() + 1); -// break; -// } -// } -// _ => unreachable!(), -// } -// } -// } -// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 10)); -// }) -// .unwrap(); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/same_channel.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/same_channel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/same_channel.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/same_channel.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -// extern crate crossbeam_channel; - -// use std::time::Duration; - -// use crossbeam_channel::{after, bounded, never, tick, unbounded}; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn after_same_channel() { -// let r = after(ms(50)); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// let r3 = after(ms(50)); -// assert!(!r.same_channel(&r3)); -// assert!(!r2.same_channel(&r3)); - -// let r4 = after(ms(100)); -// assert!(!r.same_channel(&r4)); -// assert!(!r2.same_channel(&r4)); -// } - -// #[test] -// fn array_same_channel() { -// let (s, r) = bounded::(1); - -// let s2 = s.clone(); -// assert!(s.same_channel(&s2)); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// let (s3, r3) = bounded::(1); -// assert!(!s.same_channel(&s3)); -// assert!(!s2.same_channel(&s3)); -// assert!(!r.same_channel(&r3)); -// assert!(!r2.same_channel(&r3)); -// } - -// #[test] -// fn list_same_channel() { -// let (s, r) = unbounded::(); - -// let s2 = s.clone(); -// assert!(s.same_channel(&s2)); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// let (s3, r3) = unbounded::(); -// assert!(!s.same_channel(&s3)); -// assert!(!s2.same_channel(&s3)); -// assert!(!r.same_channel(&r3)); -// assert!(!r2.same_channel(&r3)); -// } - -// #[test] -// fn never_same_channel() { -// let r = never::(); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// // Never channel are always equal to one another. -// let r3 = never::(); -// assert!(r.same_channel(&r3)); -// assert!(r2.same_channel(&r3)); -// } - -// #[test] -// fn tick_same_channel() { -// let r = tick(ms(50)); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// let r3 = tick(ms(50)); -// assert!(!r.same_channel(&r3)); -// assert!(!r2.same_channel(&r3)); - -// let r4 = tick(ms(100)); -// assert!(!r.same_channel(&r4)); -// assert!(!r2.same_channel(&r4)); -// } - -// #[test] -// fn zero_same_channel() { -// let (s, r) = bounded::(0); - -// let s2 = s.clone(); -// assert!(s.same_channel(&s2)); - -// let r2 = r.clone(); -// assert!(r.same_channel(&r2)); - -// let (s3, r3) = bounded::(0); -// assert!(!s.same_channel(&s3)); -// assert!(!s2.same_channel(&s3)); -// assert!(!r.same_channel(&r3)); -// assert!(!r2.same_channel(&r3)); -// } - -// #[test] -// fn different_flavors_same_channel() { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = unbounded::(); - -// assert!(!s1.same_channel(&s2)); -// assert!(!r1.same_channel(&r2)); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/select.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/select.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1304 +0,0 @@ -// //! Tests for channel selection using the `Select` struct. - -// extern crate crossbeam_channel; -// extern crate crossbeam_utils; - -// use std::any::Any; -// use std::cell::Cell; -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{after, bounded, tick, unbounded, Receiver, Select, TryRecvError}; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn smoke1() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// s1.send(1).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// } - -// s2.send(2).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)), -// _ => unreachable!(), -// } -// } - -// #[test] -// fn smoke2() { -// let (_s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (_s3, r3) = unbounded::(); -// let (_s4, r4) = unbounded::(); -// let (s5, r5) = unbounded::(); - -// s5.send(5).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper3 = sel.recv(&r3); -// let oper4 = sel.recv(&r4); -// let oper5 = sel.recv(&r5); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => panic!(), -// i if i == oper3 => panic!(), -// i if i == oper4 => panic!(), -// i if i == oper5 => assert_eq!(oper.recv(&r5), Ok(5)), -// _ => unreachable!(), -// } -// } - -// #[test] -// fn disconnected() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// drop(s1); -// thread::sleep(ms(500)); -// s2.send(5).unwrap(); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r1).is_err()), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } - -// r2.recv().unwrap(); -// }) -// .unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r1).is_err()), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// drop(s2); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r2).is_err()), -// _ => unreachable!(), -// }, -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// let mut sel = Select::new(); -// let _oper1 = sel.recv(&r1); -// let _oper2 = sel.recv(&r2); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(_) => panic!(), -// } - -// drop(s1); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.try_select(); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r1).is_err()), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } - -// s2.send(2).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r2); -// let oper = sel.try_select(); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert_eq!(oper.recv(&r2), Ok(2)), -// _ => unreachable!(), -// }, -// } - -// let mut sel = Select::new(); -// let _oper1 = sel.recv(&r2); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(_) => panic!(), -// } - -// let mut sel = Select::new(); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(_) => panic!(), -// } -// } - -// #[test] -// fn timeout() { -// let (_s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(1500)); -// s2.send(2).unwrap(); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)), -// _ => unreachable!(), -// }, -// } -// }) -// .unwrap(); - -// scope(|scope| { -// let (s, r) = unbounded::(); - -// scope.spawn(move |_| { -// thread::sleep(ms(500)); -// drop(s); -// }); - -// let mut sel = Select::new(); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.try_select(); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r).is_err()), -// _ => unreachable!(), -// }, -// } -// } -// Ok(_) => unreachable!(), -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default_when_disconnected() { -// let (_, r) = unbounded::(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.try_select(); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r).is_err()), -// _ => unreachable!(), -// }, -// } - -// let (_, r) = unbounded::(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r).is_err()), -// _ => unreachable!(), -// }, -// } - -// let (s, _) = bounded::(0); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.try_select(); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.send(&s, 0).is_err()), -// _ => unreachable!(), -// }, -// } - -// let (s, _) = bounded::(0); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert!(oper.send(&s, 0).is_err()), -// _ => unreachable!(), -// }, -// } -// } - -// #[test] -// fn default_only() { -// let start = Instant::now(); - -// let mut sel = Select::new(); -// let oper = sel.try_select(); -// assert!(oper.is_err()); -// let now = Instant::now(); -// assert!(now - start <= ms(50)); - -// let start = Instant::now(); -// let mut sel = Select::new(); -// let oper = sel.select_timeout(ms(500)); -// assert!(oper.is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(450)); -// assert!(now - start <= ms(550)); -// } - -// #[test] -// fn unblocks() { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = bounded::(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s2.send(2).unwrap(); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)), -// _ => unreachable!(), -// }, -// } -// }) -// .unwrap(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// assert_eq!(r1.recv().unwrap(), 1); -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s1); -// let oper2 = sel.send(&s2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// i if i == oper1 => oper.send(&s1, 1).unwrap(), -// i if i == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn both_ready() { -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s1.send(1).unwrap(); -// assert_eq!(r2.recv().unwrap(), 2); -// }); - -// for _ in 0..2 { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.send(&s2); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)), -// i if i == oper2 => oper.send(&s2, 2).unwrap(), -// _ => unreachable!(), -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn loop_try() { -// const RUNS: usize = 20; - -// for _ in 0..RUNS { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = bounded::(0); -// let (s_end, r_end) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| loop { -// let mut done = false; - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s1); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// i if i == oper1 => { -// let _ = oper.send(&s1, 1); -// done = true; -// } -// _ => unreachable!(), -// }, -// } -// if done { -// break; -// } - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r_end); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// i if i == oper1 => { -// let _ = oper.recv(&r_end); -// done = true; -// } -// _ => unreachable!(), -// }, -// } -// if done { -// break; -// } -// }); - -// scope.spawn(|_| loop { -// if let Ok(x) = r2.try_recv() { -// assert_eq!(x, 2); -// break; -// } - -// let mut done = false; -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r_end); -// let oper = sel.try_select(); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// i if i == oper1 => { -// let _ = oper.recv(&r_end); -// done = true; -// } -// _ => unreachable!(), -// }, -// } -// if done { -// break; -// } -// }); - -// scope.spawn(|_| { -// thread::sleep(ms(500)); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.send(&s2); -// let oper = sel.select_timeout(ms(1000)); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)), -// i if i == oper2 => assert!(oper.send(&s2, 2).is_ok()), -// _ => unreachable!(), -// }, -// } - -// drop(s_end); -// }); -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn cloning1() { -// scope(|scope| { -// let (s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (s3, r3) = unbounded::<()>(); - -// scope.spawn(move |_| { -// r3.recv().unwrap(); -// drop(s1.clone()); -// assert!(r3.try_recv().is_err()); -// s1.send(1).unwrap(); -// r3.recv().unwrap(); -// }); - -// s3.send(()).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => drop(oper.recv(&r1)), -// i if i == oper2 => drop(oper.recv(&r2)), -// _ => unreachable!(), -// } - -// s3.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn cloning2() { -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = unbounded::<()>(); -// let (_s3, _r3) = unbounded::<()>(); - -// scope(|scope| { -// scope.spawn(move |_| { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => panic!(), -// i if i == oper2 => drop(oper.recv(&r2)), -// _ => unreachable!(), -// } -// }); - -// thread::sleep(ms(500)); -// drop(s1.clone()); -// s2.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn preflight1() { -// let (s, r) = unbounded(); -// s.send(()).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => drop(oper.recv(&r)), -// _ => unreachable!(), -// } -// } - -// #[test] -// fn preflight2() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => assert_eq!(oper.recv(&r), Ok(())), -// _ => unreachable!(), -// } - -// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); -// } - -// #[test] -// fn preflight3() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); -// r.recv().unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => assert!(oper.recv(&r).is_err()), -// _ => unreachable!(), -// } -// } - -// #[test] -// fn duplicate_operations() { -// let (s, r) = unbounded::(); -// let hit = vec![Cell::new(false); 4]; - -// while hit.iter().map(|h| h.get()).any(|hit| !hit) { -// let mut sel = Select::new(); -// let oper0 = sel.recv(&r); -// let oper1 = sel.recv(&r); -// let oper2 = sel.send(&s); -// let oper3 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper0 => { -// assert!(oper.recv(&r).is_ok()); -// hit[0].set(true); -// } -// i if i == oper1 => { -// assert!(oper.recv(&r).is_ok()); -// hit[1].set(true); -// } -// i if i == oper2 => { -// assert!(oper.send(&s, 0).is_ok()); -// hit[2].set(true); -// } -// i if i == oper3 => { -// assert!(oper.send(&s, 0).is_ok()); -// hit[3].set(true); -// } -// _ => unreachable!(), -// } -// } -// } - -// #[test] -// fn nesting() { -// let (s, r) = unbounded::(); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// assert!(oper.send(&s, 0).is_ok()); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// assert_eq!(oper.recv(&r), Ok(0)); - -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// assert!(oper.send(&s, 1).is_ok()); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// assert_eq!(oper.recv(&r), Ok(1)); -// } -// _ => unreachable!(), -// } -// } -// _ => unreachable!(), -// } -// } -// _ => unreachable!(), -// } -// } -// _ => unreachable!(), -// } -// } - -// #[test] -// fn stress_recv() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded(); -// let (s2, r2) = bounded(5); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// r3.recv().unwrap(); - -// s2.send(i).unwrap(); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)), -// ix if ix == oper2 => assert_eq!(oper.recv(&r2), Ok(i)), -// _ => unreachable!(), -// } - -// s3.send(()).unwrap(); -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_send() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// assert_eq!(r1.recv().unwrap(), i); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// let oper1 = sel.send(&s1); -// let oper2 = sel.send(&s2); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert!(oper.send(&s1, i).is_ok()), -// ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()), -// _ => unreachable!(), -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_mixed() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.send(&s2); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()), -// _ => unreachable!(), -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_timeout_two_threads() { -// const COUNT: usize = 20; - -// let (s, r) = bounded(2); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// let done = false; -// while !done { -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.select_timeout(ms(100)); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => { -// assert!(oper.send(&s, i).is_ok()); -// break; -// } -// _ => unreachable!(), -// }, -// } -// } -// } -// }); - -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// let mut done = false; -// while !done { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select_timeout(ms(100)); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => { -// assert_eq!(oper.recv(&r), Ok(i)); -// done = true; -// } -// _ => unreachable!(), -// }, -// } -// } -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn send_recv_same_channel() { -// let (s, r) = bounded::(0); -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper2 = sel.recv(&r); -// let oper = sel.select_timeout(ms(100)); -// match oper { -// Err(_) => {} -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => panic!(), -// ix if ix == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } - -// let (s, r) = unbounded::(); -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper2 = sel.recv(&r); -// let oper = sel.select_timeout(ms(100)); -// match oper { -// Err(_) => panic!(), -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => assert!(oper.send(&s, 0).is_ok()), -// ix if ix == oper2 => panic!(), -// _ => unreachable!(), -// }, -// } -// } - -// #[test] -// fn matching() { -// const THREADS: usize = 44; - -// let (s, r) = &bounded::(0); - -// scope(|scope| { -// for i in 0..THREADS { -// scope.spawn(move |_| { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper2 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()), -// _ => unreachable!(), -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn matching_with_leftover() { -// const THREADS: usize = 55; - -// let (s, r) = &bounded::(0); - -// scope(|scope| { -// for i in 0..THREADS { -// scope.spawn(move |_| { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper2 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()), -// _ => unreachable!(), -// } -// }); -// } -// s.send(!0).unwrap(); -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn channel_through_channel() { -// const COUNT: usize = 1000; - -// type T = Box; - -// for cap in 0..3 { -// let (s, r) = bounded::(cap); - -// scope(|scope| { -// scope.spawn(move |_| { -// let mut s = s; - -// for _ in 0..COUNT { -// let (new_s, new_r) = bounded(cap); -// let new_r: T = Box::new(Some(new_r)); - -// { -// let mut sel = Select::new(); -// let oper1 = sel.send(&s); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert!(oper.send(&s, new_r).is_ok()), -// _ => unreachable!(), -// } -// } - -// s = new_s; -// } -// }); - -// scope.spawn(move |_| { -// let mut r = r; - -// for _ in 0..COUNT { -// let new = { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => oper -// .recv(&r) -// .unwrap() -// .downcast_mut::>>() -// .unwrap() -// .take() -// .unwrap(), -// _ => unreachable!(), -// } -// }; -// r = new; -// } -// }); -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn linearizable_try() { -// const COUNT: usize = 100_000; - -// for step in 0..2 { -// let (start_s, start_r) = bounded::<()>(0); -// let (end_s, end_r) = bounded::<()>(0); - -// let ((s1, r1), (s2, r2)) = if step == 0 { -// (bounded::(1), bounded::(1)) -// } else { -// (unbounded::(), unbounded::()) -// }; - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// start_s.send(()).unwrap(); - -// s1.send(1).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.try_select(); -// match oper { -// Err(_) => unreachable!(), -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => assert!(oper.recv(&r1).is_ok()), -// ix if ix == oper2 => assert!(oper.recv(&r2).is_ok()), -// _ => unreachable!(), -// }, -// } - -// end_s.send(()).unwrap(); -// let _ = r2.try_recv(); -// } -// }); - -// for _ in 0..COUNT { -// start_r.recv().unwrap(); - -// s2.send(1).unwrap(); -// let _ = r1.try_recv(); - -// end_r.recv().unwrap(); -// } -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn linearizable_timeout() { -// const COUNT: usize = 100_000; - -// for step in 0..2 { -// let (start_s, start_r) = bounded::<()>(0); -// let (end_s, end_r) = bounded::<()>(0); - -// let ((s1, r1), (s2, r2)) = if step == 0 { -// (bounded::(1), bounded::(1)) -// } else { -// (unbounded::(), unbounded::()) -// }; - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// start_s.send(()).unwrap(); - -// s1.send(1).unwrap(); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper = sel.select_timeout(ms(0)); -// match oper { -// Err(_) => unreachable!(), -// Ok(oper) => match oper.index() { -// ix if ix == oper1 => assert!(oper.recv(&r1).is_ok()), -// ix if ix == oper2 => assert!(oper.recv(&r2).is_ok()), -// _ => unreachable!(), -// }, -// } - -// end_s.send(()).unwrap(); -// let _ = r2.try_recv(); -// } -// }); - -// for _ in 0..COUNT { -// start_r.recv().unwrap(); - -// s2.send(1).unwrap(); -// let _ = r1.try_recv(); - -// end_r.recv().unwrap(); -// } -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn fairness1() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(COUNT); -// let (s2, r2) = unbounded::<()>(); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let hits = vec![Cell::new(0usize); 4]; -// for _ in 0..COUNT { -// let after = after(ms(0)); -// let tick = tick(ms(0)); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper3 = sel.recv(&after); -// let oper4 = sel.recv(&tick); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// oper.recv(&r1).unwrap(); -// hits[0].set(hits[0].get() + 1); -// } -// i if i == oper2 => { -// oper.recv(&r2).unwrap(); -// hits[1].set(hits[1].get() + 1); -// } -// i if i == oper3 => { -// oper.recv(&after).unwrap(); -// hits[2].set(hits[2].get() + 1); -// } -// i if i == oper4 => { -// oper.recv(&tick).unwrap(); -// hits[3].set(hits[3].get() + 1); -// } -// _ => unreachable!(), -// } -// } -// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn fairness2() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = bounded::<()>(1); -// let (s3, r3) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// let mut sel = Select::new(); -// let mut oper1 = None; -// let mut oper2 = None; -// if s1.is_empty() { -// oper1 = Some(sel.send(&s1)); -// } -// if s2.is_empty() { -// oper2 = Some(sel.send(&s2)); -// } -// let oper3 = sel.send(&s3); -// let oper = sel.select(); -// match oper.index() { -// i if Some(i) == oper1 => assert!(oper.send(&s1, ()).is_ok()), -// i if Some(i) == oper2 => assert!(oper.send(&s2, ()).is_ok()), -// i if i == oper3 => assert!(oper.send(&s3, ()).is_ok()), -// _ => unreachable!(), -// } -// } -// }); - -// let hits = vec![Cell::new(0usize); 3]; -// for _ in 0..COUNT { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper3 = sel.recv(&r3); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// oper.recv(&r1).unwrap(); -// hits[0].set(hits[0].get() + 1); -// } -// i if i == oper2 => { -// oper.recv(&r2).unwrap(); -// hits[1].set(hits[1].get() + 1); -// } -// i if i == oper3 => { -// oper.recv(&r3).unwrap(); -// hits[2].set(hits[2].get() + 1); -// } -// _ => unreachable!(), -// } -// } -// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 50)); -// }) -// .unwrap(); -// } - -// #[test] -// fn sync_and_clone() { -// const THREADS: usize = 20; - -// let (s, r) = &bounded::(0); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper2 = sel.send(&s); -// let sel = &sel; - -// scope(|scope| { -// for i in 0..THREADS { -// scope.spawn(move |_| { -// let mut sel = sel.clone(); -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()), -// _ => unreachable!(), -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn send_and_clone() { -// const THREADS: usize = 20; - -// let (s, r) = &bounded::(0); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r); -// let oper2 = sel.send(&s); - -// scope(|scope| { -// for i in 0..THREADS { -// let mut sel = sel.clone(); -// scope.spawn(move |_| { -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()), -// _ => unreachable!(), -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn reuse() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.send(&s2); - -// for i in 0..COUNT { -// for _ in 0..2 { -// let oper = sel.select(); -// match oper.index() { -// ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)), -// ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()), -// _ => unreachable!(), -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/select_macro.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select_macro.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/select_macro.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/select_macro.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1440 +0,0 @@ -// //! Tests for the `select!` macro. - -// #![deny(unsafe_code)] - -// #[macro_use] -// extern crate crossbeam_channel; -// extern crate crossbeam_utils; - -// use std::any::Any; -// use std::cell::Cell; -// use std::ops::Deref; -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{after, bounded, never, tick, unbounded}; -// use crossbeam_channel::{Receiver, RecvError, SendError, Sender, TryRecvError}; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn smoke1() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// s1.send(1).unwrap(); - -// select! { -// recv(r1) -> v => assert_eq!(v, Ok(1)), -// recv(r2) -> _ => panic!(), -// } - -// s2.send(2).unwrap(); - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> v => assert_eq!(v, Ok(2)), -// } -// } - -// #[test] -// fn smoke2() { -// let (_s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (_s3, r3) = unbounded::(); -// let (_s4, r4) = unbounded::(); -// let (s5, r5) = unbounded::(); - -// s5.send(5).unwrap(); - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> _ => panic!(), -// recv(r3) -> _ => panic!(), -// recv(r4) -> _ => panic!(), -// recv(r5) -> v => assert_eq!(v, Ok(5)), -// } -// } - -// #[test] -// fn disconnected() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// drop(s1); -// thread::sleep(ms(500)); -// s2.send(5).unwrap(); -// }); - -// select! { -// recv(r1) -> v => assert!(v.is_err()), -// recv(r2) -> _ => panic!(), -// default(ms(1000)) => panic!(), -// } - -// r2.recv().unwrap(); -// }) -// .unwrap(); - -// select! { -// recv(r1) -> v => assert!(v.is_err()), -// recv(r2) -> _ => panic!(), -// default(ms(1000)) => panic!(), -// } - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// drop(s2); -// }); - -// select! { -// recv(r2) -> v => assert!(v.is_err()), -// default(ms(1000)) => panic!(), -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default() { -// let (s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> _ => panic!(), -// default => {} -// } - -// drop(s1); - -// select! { -// recv(r1) -> v => assert!(v.is_err()), -// recv(r2) -> _ => panic!(), -// default => panic!(), -// } - -// s2.send(2).unwrap(); - -// select! { -// recv(r2) -> v => assert_eq!(v, Ok(2)), -// default => panic!(), -// } - -// select! { -// recv(r2) -> _ => panic!(), -// default => {}, -// } - -// select! { -// default => {}, -// } -// } - -// #[test] -// fn timeout() { -// let (_s1, r1) = unbounded::(); -// let (s2, r2) = unbounded::(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(1500)); -// s2.send(2).unwrap(); -// }); - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> _ => panic!(), -// default(ms(1000)) => {}, -// } - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> v => assert_eq!(v, Ok(2)), -// default(ms(1000)) => panic!(), -// } -// }) -// .unwrap(); - -// scope(|scope| { -// let (s, r) = unbounded::(); - -// scope.spawn(move |_| { -// thread::sleep(ms(500)); -// drop(s); -// }); - -// select! { -// default(ms(1000)) => { -// select! { -// recv(r) -> v => assert!(v.is_err()), -// default => panic!(), -// } -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn default_when_disconnected() { -// let (_, r) = unbounded::(); - -// select! { -// recv(r) -> res => assert!(res.is_err()), -// default => panic!(), -// } - -// let (_, r) = unbounded::(); - -// select! { -// recv(r) -> res => assert!(res.is_err()), -// default(ms(1000)) => panic!(), -// } - -// let (s, _) = bounded::(0); - -// select! { -// send(s, 0) -> res => assert!(res.is_err()), -// default => panic!(), -// } - -// let (s, _) = bounded::(0); - -// select! { -// send(s, 0) -> res => assert!(res.is_err()), -// default(ms(1000)) => panic!(), -// } -// } - -// #[test] -// fn default_only() { -// let start = Instant::now(); -// select! { -// default => {} -// } -// let now = Instant::now(); -// assert!(now - start <= ms(50)); - -// let start = Instant::now(); -// select! { -// default(ms(500)) => {} -// } -// let now = Instant::now(); -// assert!(now - start >= ms(450)); -// assert!(now - start <= ms(550)); -// } - -// #[test] -// fn unblocks() { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = bounded::(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s2.send(2).unwrap(); -// }); - -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> v => assert_eq!(v, Ok(2)), -// default(ms(1000)) => panic!(), -// } -// }) -// .unwrap(); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// assert_eq!(r1.recv().unwrap(), 1); -// }); - -// select! { -// send(s1, 1) -> _ => {}, -// send(s2, 2) -> _ => panic!(), -// default(ms(1000)) => panic!(), -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn both_ready() { -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s1.send(1).unwrap(); -// assert_eq!(r2.recv().unwrap(), 2); -// }); - -// for _ in 0..2 { -// select! { -// recv(r1) -> v => assert_eq!(v, Ok(1)), -// send(s2, 2) -> _ => {}, -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn loop_try() { -// const RUNS: usize = 20; - -// for _ in 0..RUNS { -// let (s1, r1) = bounded::(0); -// let (s2, r2) = bounded::(0); -// let (s_end, r_end) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| loop { -// select! { -// send(s1, 1) -> _ => break, -// default => {} -// } - -// select! { -// recv(r_end) -> _ => break, -// default => {} -// } -// }); - -// scope.spawn(|_| loop { -// if let Ok(x) = r2.try_recv() { -// assert_eq!(x, 2); -// break; -// } - -// select! { -// recv(r_end) -> _ => break, -// default => {} -// } -// }); - -// scope.spawn(|_| { -// thread::sleep(ms(500)); - -// select! { -// recv(r1) -> v => assert_eq!(v, Ok(1)), -// send(s2, 2) -> _ => {}, -// default(ms(500)) => panic!(), -// } - -// drop(s_end); -// }); -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn cloning1() { -// scope(|scope| { -// let (s1, r1) = unbounded::(); -// let (_s2, r2) = unbounded::(); -// let (s3, r3) = unbounded::<()>(); - -// scope.spawn(move |_| { -// r3.recv().unwrap(); -// drop(s1.clone()); -// assert_eq!(r3.try_recv(), Err(TryRecvError::Empty)); -// s1.send(1).unwrap(); -// r3.recv().unwrap(); -// }); - -// s3.send(()).unwrap(); - -// select! { -// recv(r1) -> _ => {}, -// recv(r2) -> _ => {}, -// } - -// s3.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn cloning2() { -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = unbounded::<()>(); -// let (_s3, _r3) = unbounded::<()>(); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// recv(r1) -> _ => panic!(), -// recv(r2) -> _ => {}, -// } -// }); - -// thread::sleep(ms(500)); -// drop(s1.clone()); -// s2.send(()).unwrap(); -// }) -// .unwrap(); -// } - -// #[test] -// fn preflight1() { -// let (s, r) = unbounded(); -// s.send(()).unwrap(); - -// select! { -// recv(r) -> _ => {} -// } -// } - -// #[test] -// fn preflight2() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); - -// select! { -// recv(r) -> v => assert!(v.is_ok()), -// } -// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); -// } - -// #[test] -// fn preflight3() { -// let (s, r) = unbounded(); -// drop(s.clone()); -// s.send(()).unwrap(); -// drop(s); -// r.recv().unwrap(); - -// select! { -// recv(r) -> v => assert!(v.is_err()) -// } -// } - -// #[test] -// fn duplicate_operations() { -// let (s, r) = unbounded::(); -// let mut hit = [false; 4]; - -// while hit.iter().any(|hit| !hit) { -// select! { -// recv(r) -> _ => hit[0] = true, -// recv(r) -> _ => hit[1] = true, -// send(s, 0) -> _ => hit[2] = true, -// send(s, 0) -> _ => hit[3] = true, -// } -// } -// } - -// #[test] -// fn nesting() { -// let (s, r) = unbounded::(); - -// select! { -// send(s, 0) -> _ => { -// select! { -// recv(r) -> v => { -// assert_eq!(v, Ok(0)); -// select! { -// send(s, 1) -> _ => { -// select! { -// recv(r) -> v => { -// assert_eq!(v, Ok(1)); -// } -// } -// } -// } -// } -// } -// } -// } -// } - -// #[test] -// #[should_panic(expected = "send panicked")] -// fn panic_sender() { -// fn get() -> Sender { -// panic!("send panicked") -// } - -// #[allow(unreachable_code)] -// { -// select! { -// send(get(), panic!()) -> _ => {} -// } -// } -// } - -// #[test] -// #[should_panic(expected = "recv panicked")] -// fn panic_receiver() { -// fn get() -> Receiver { -// panic!("recv panicked") -// } - -// select! { -// recv(get()) -> _ => {} -// } -// } - -// #[test] -// fn stress_recv() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded(); -// let (s2, r2) = bounded(5); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// r3.recv().unwrap(); - -// s2.send(i).unwrap(); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// select! { -// recv(r1) -> v => assert_eq!(v, Ok(i)), -// recv(r2) -> v => assert_eq!(v, Ok(i)), -// } - -// s3.send(()).unwrap(); -// } -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_send() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// assert_eq!(r1.recv().unwrap(), i); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// select! { -// send(s1, i) -> _ => {}, -// send(s2, i) -> _ => {}, -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_mixed() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded(0); -// let (s2, r2) = bounded(0); -// let (s3, r3) = bounded(100); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// s1.send(i).unwrap(); -// assert_eq!(r2.recv().unwrap(), i); -// r3.recv().unwrap(); -// } -// }); - -// for i in 0..COUNT { -// for _ in 0..2 { -// select! { -// recv(r1) -> v => assert_eq!(v, Ok(i)), -// send(s2, i) -> _ => {}, -// } -// } -// s3.send(()).unwrap(); -// } -// }) -// .unwrap(); -// } - -// #[test] -// fn stress_timeout_two_threads() { -// const COUNT: usize = 20; - -// let (s, r) = bounded(2); - -// scope(|scope| { -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// loop { -// select! { -// send(s, i) -> _ => break, -// default(ms(100)) => {} -// } -// } -// } -// }); - -// scope.spawn(|_| { -// for i in 0..COUNT { -// if i % 2 == 0 { -// thread::sleep(ms(500)); -// } - -// loop { -// select! { -// recv(r) -> v => { -// assert_eq!(v, Ok(i)); -// break; -// } -// default(ms(100)) => {} -// } -// } -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn send_recv_same_channel() { -// let (s, r) = bounded::(0); -// select! { -// send(s, 0) -> _ => panic!(), -// recv(r) -> _ => panic!(), -// default(ms(500)) => {} -// } - -// let (s, r) = unbounded::(); -// select! { -// send(s, 0) -> _ => {}, -// recv(r) -> _ => panic!(), -// default(ms(500)) => panic!(), -// } -// } - -// #[test] -// fn matching() { -// const THREADS: usize = 44; - -// let (s, r) = &bounded::(0); - -// scope(|scope| { -// for i in 0..THREADS { -// scope.spawn(move |_| { -// select! { -// recv(r) -> v => assert_ne!(v.unwrap(), i), -// send(s, i) -> _ => {}, -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn matching_with_leftover() { -// const THREADS: usize = 55; - -// let (s, r) = &bounded::(0); - -// scope(|scope| { -// for i in 0..THREADS { -// scope.spawn(move |_| { -// select! { -// recv(r) -> v => assert_ne!(v.unwrap(), i), -// send(s, i) -> _ => {}, -// } -// }); -// } -// s.send(!0).unwrap(); -// }) -// .unwrap(); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn channel_through_channel() { -// const COUNT: usize = 1000; - -// type T = Box; - -// for cap in 0..3 { -// let (s, r) = bounded::(cap); - -// scope(|scope| { -// scope.spawn(move |_| { -// let mut s = s; - -// for _ in 0..COUNT { -// let (new_s, new_r) = bounded(cap); -// let new_r: T = Box::new(Some(new_r)); - -// select! { -// send(s, new_r) -> _ => {} -// } - -// s = new_s; -// } -// }); - -// scope.spawn(move |_| { -// let mut r = r; - -// for _ in 0..COUNT { -// r = select! { -// recv(r) -> msg => { -// msg.unwrap() -// .downcast_mut::>>() -// .unwrap() -// .take() -// .unwrap() -// } -// } -// } -// }); -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn linearizable_default() { -// const COUNT: usize = 100_000; - -// for step in 0..2 { -// let (start_s, start_r) = bounded::<()>(0); -// let (end_s, end_r) = bounded::<()>(0); - -// let ((s1, r1), (s2, r2)) = if step == 0 { -// (bounded::(1), bounded::(1)) -// } else { -// (unbounded::(), unbounded::()) -// }; - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// start_s.send(()).unwrap(); - -// s1.send(1).unwrap(); -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// default => unreachable!() -// } - -// end_s.send(()).unwrap(); -// let _ = r2.try_recv(); -// } -// }); - -// for _ in 0..COUNT { -// start_r.recv().unwrap(); - -// s2.send(1).unwrap(); -// let _ = r1.try_recv(); - -// end_r.recv().unwrap(); -// } -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn linearizable_timeout() { -// const COUNT: usize = 100_000; - -// for step in 0..2 { -// let (start_s, start_r) = bounded::<()>(0); -// let (end_s, end_r) = bounded::<()>(0); - -// let ((s1, r1), (s2, r2)) = if step == 0 { -// (bounded::(1), bounded::(1)) -// } else { -// (unbounded::(), unbounded::()) -// }; - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..COUNT { -// start_s.send(()).unwrap(); - -// s1.send(1).unwrap(); -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// default(ms(0)) => unreachable!() -// } - -// end_s.send(()).unwrap(); -// let _ = r2.try_recv(); -// } -// }); - -// for _ in 0..COUNT { -// start_r.recv().unwrap(); - -// s2.send(1).unwrap(); -// let _ = r1.try_recv(); - -// end_r.recv().unwrap(); -// } -// }) -// .unwrap(); -// } -// } - -// #[test] -// fn fairness1() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(COUNT); -// let (s2, r2) = unbounded::<()>(); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let mut hits = [0usize; 4]; -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// recv(after(ms(0))) -> _ => hits[2] += 1, -// recv(tick(ms(0))) -> _ => hits[3] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } - -// #[test] -// fn fairness2() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = unbounded::<()>(); -// let (s2, r2) = bounded::<()>(1); -// let (s3, r3) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| { -// let (hole, _r) = bounded(0); - -// for _ in 0..COUNT { -// let s1 = if s1.is_empty() { &s1 } else { &hole }; -// let s2 = if s2.is_empty() { &s2 } else { &hole }; - -// select! { -// send(s1, ()) -> res => assert!(res.is_ok()), -// send(s2, ()) -> res => assert!(res.is_ok()), -// send(s3, ()) -> res => assert!(res.is_ok()), -// } -// } -// }); - -// let hits = vec![Cell::new(0usize); 3]; -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0].set(hits[0].get() + 1), -// recv(r2) -> _ => hits[1].set(hits[1].get() + 1), -// recv(r3) -> _ => hits[2].set(hits[2].get() + 1), -// } -// } -// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 50)); -// }) -// .unwrap(); -// } - -// #[test] -// fn fairness_recv() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(COUNT); -// let (s2, r2) = unbounded::<()>(); - -// for _ in 0..COUNT { -// s1.send(()).unwrap(); -// s2.send(()).unwrap(); -// } - -// let mut hits = [0usize; 2]; -// while hits[0] + hits[1] < COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / 4)); -// } - -// #[test] -// fn fairness_send() { -// const COUNT: usize = 10_000; - -// let (s1, _r1) = bounded::<()>(COUNT); -// let (s2, _r2) = unbounded::<()>(); - -// let mut hits = [0usize; 2]; -// for _ in 0..COUNT { -// select! { -// send(s1, ()) -> _ => hits[0] += 1, -// send(s2, ()) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / 4)); -// } - -// #[test] -// fn references() { -// let (s, r) = unbounded::(); -// select! { -// send(s, 0) -> _ => {} -// recv(r) -> _ => {} -// } -// select! { -// send(&&&&s, 0) -> _ => {} -// recv(&&&&r) -> _ => {} -// } -// select! { -// recv(Some(&r).unwrap_or(&never())) -> _ => {}, -// default => {} -// } -// select! { -// recv(Some(r).unwrap_or(never())) -> _ => {}, -// default => {} -// } -// } - -// #[test] -// fn case_blocks() { -// let (s, r) = unbounded::(); - -// select! { -// recv(r) -> _ => 3.0, -// recv(r) -> _ => loop { -// unreachable!() -// }, -// recv(r) -> _ => match 7 + 3 { -// _ => unreachable!() -// }, -// default => 7. -// }; - -// select! { -// recv(r) -> msg => if msg.is_ok() { -// unreachable!() -// }, -// default => () -// } - -// drop(s); -// } - -// #[test] -// fn move_handles() { -// let (s, r) = unbounded::(); -// select! { -// recv((move || r)()) -> _ => {} -// send((move || s)(), 0) -> _ => {} -// } -// } - -// #[test] -// fn infer_types() { -// let (s, r) = unbounded(); -// select! { -// recv(r) -> _ => {} -// default => {} -// } -// s.send(()).unwrap(); - -// let (s, r) = unbounded(); -// select! { -// send(s, ()) -> _ => {} -// } -// r.recv().unwrap(); -// } - -// #[test] -// fn default_syntax() { -// let (s, r) = bounded::(0); - -// select! { -// recv(r) -> _ => panic!(), -// default => {} -// } -// select! { -// send(s, 0) -> _ => panic!(), -// default() => {} -// } -// select! { -// default => {} -// } -// select! { -// default() => {} -// } -// } - -// #[test] -// fn same_variable_name() { -// let (_, r) = unbounded::(); -// select! { -// recv(r) -> r => assert!(r.is_err()), -// } -// } - -// #[test] -// fn handles_on_heap() { -// let (s, r) = unbounded::(); -// let (s, r) = (Box::new(s), Box::new(r)); - -// select! { -// send(*s, 0) -> _ => {} -// recv(*r) -> _ => {} -// default => {} -// } - -// drop(s); -// drop(r); -// } - -// #[test] -// fn once_blocks() { -// let (s, r) = unbounded::(); - -// let once = Box::new(()); -// select! { -// send(s, 0) -> _ => drop(once), -// } - -// let once = Box::new(()); -// select! { -// recv(r) -> _ => drop(once), -// } - -// let once1 = Box::new(()); -// let once2 = Box::new(()); -// select! { -// send(s, 0) -> _ => drop(once1), -// default => drop(once2), -// } - -// let once1 = Box::new(()); -// let once2 = Box::new(()); -// select! { -// recv(r) -> _ => drop(once1), -// default => drop(once2), -// } - -// let once1 = Box::new(()); -// let once2 = Box::new(()); -// select! { -// recv(r) -> _ => drop(once1), -// send(s, 0) -> _ => drop(once2), -// } -// } - -// #[test] -// fn once_receiver() { -// let (_, r) = unbounded::(); - -// let once = Box::new(()); -// let get = move || { -// drop(once); -// r -// }; - -// select! { -// recv(get()) -> _ => {} -// } -// } - -// #[test] -// fn once_sender() { -// let (s, _) = unbounded::(); - -// let once = Box::new(()); -// let get = move || { -// drop(once); -// s -// }; - -// select! { -// send(get(), 5) -> _ => {} -// } -// } - -// #[test] -// fn parse_nesting() { -// let (_, r) = unbounded::(); - -// select! { -// recv(r) -> _ => {} -// recv(r) -> _ => { -// select! { -// recv(r) -> _ => {} -// recv(r) -> _ => { -// select! { -// recv(r) -> _ => {} -// recv(r) -> _ => { -// select! { -// default => {} -// } -// } -// } -// } -// } -// } -// } -// } - -// #[test] -// fn evaluate() { -// let (s, r) = unbounded::(); - -// let v = select! { -// recv(r) -> _ => "foo".into(), -// send(s, 0) -> _ => "bar".to_owned(), -// default => "baz".to_string(), -// }; -// assert_eq!(v, "bar"); - -// let v = select! { -// recv(r) -> _ => "foo".into(), -// default => "baz".to_string(), -// }; -// assert_eq!(v, "foo"); - -// let v = select! { -// recv(r) -> _ => "foo".into(), -// default => "baz".to_string(), -// }; -// assert_eq!(v, "baz"); -// } - -// #[test] -// fn deref() { -// use crossbeam_channel as cc; - -// struct Sender(cc::Sender); -// struct Receiver(cc::Receiver); - -// impl Deref for Receiver { -// type Target = cc::Receiver; - -// fn deref(&self) -> &Self::Target { -// &self.0 -// } -// } - -// impl Deref for Sender { -// type Target = cc::Sender; - -// fn deref(&self) -> &Self::Target { -// &self.0 -// } -// } - -// let (s, r) = bounded::(0); -// let (s, r) = (Sender(s), Receiver(r)); - -// select! { -// send(s, 0) -> _ => panic!(), -// recv(r) -> _ => panic!(), -// default => {} -// } -// } - -// #[test] -// fn result_types() { -// let (s, _) = bounded::(0); -// let (_, r) = bounded::(0); - -// select! { -// recv(r) -> res => drop::>(res), -// } -// select! { -// recv(r) -> res => drop::>(res), -// default => {} -// } -// select! { -// recv(r) -> res => drop::>(res), -// default(ms(0)) => {} -// } - -// select! { -// send(s, 0) -> res => drop::>>(res), -// } -// select! { -// send(s, 0) -> res => drop::>>(res), -// default => {} -// } -// select! { -// send(s, 0) -> res => drop::>>(res), -// default(ms(0)) => {} -// } - -// select! { -// send(s, 0) -> res => drop::>>(res), -// recv(r) -> res => drop::>(res), -// } -// } - -// #[test] -// fn try_recv() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// recv(r) -> _ => panic!(), -// default => {} -// } -// thread::sleep(ms(1500)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(7)), -// default => panic!(), -// } -// thread::sleep(ms(500)); -// select! { -// recv(r) -> v => assert_eq!(v, Err(RecvError)), -// default => panic!(), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1000)); -// select! { -// send(s, 7) -> res => res.unwrap(), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn recv() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// recv(r) -> v => assert_eq!(v, Ok(7)), -// } -// thread::sleep(ms(1000)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(8)), -// } -// thread::sleep(ms(1000)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(9)), -// } -// select! { -// recv(r) -> v => assert_eq!(v, Err(RecvError)), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1500)); -// select! { -// send(s, 7) -> res => res.unwrap(), -// } -// select! { -// send(s, 8) -> res => res.unwrap(), -// } -// select! { -// send(s, 9) -> res => res.unwrap(), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn recv_timeout() { -// let (s, r) = bounded::(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// recv(r) -> _ => panic!(), -// default(ms(1000)) => {} -// } -// select! { -// recv(r) -> v => assert_eq!(v, Ok(7)), -// default(ms(1000)) => panic!(), -// } -// select! { -// recv(r) -> v => assert_eq!(v, Err(RecvError)), -// default(ms(1000)) => panic!(), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1500)); -// select! { -// send(s, 7) -> res => res.unwrap(), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn try_send() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// send(s, 7) -> _ => panic!(), -// default => {} -// } -// thread::sleep(ms(1500)); -// select! { -// send(s, 8) -> res => res.unwrap(), -// default => panic!(), -// } -// thread::sleep(ms(500)); -// select! { -// send(s, 8) -> res => assert_eq!(res, Err(SendError(8))), -// default => panic!(), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1000)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(8)), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn send() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// send(s, 7) -> res => res.unwrap(), -// } -// thread::sleep(ms(1000)); -// select! { -// send(s, 8) -> res => res.unwrap(), -// } -// thread::sleep(ms(1000)); -// select! { -// send(s, 9) -> res => res.unwrap(), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1500)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(7)), -// } -// select! { -// recv(r) -> v => assert_eq!(v, Ok(8)), -// } -// select! { -// recv(r) -> v => assert_eq!(v, Ok(9)), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn send_timeout() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// send(s, 7) -> _ => panic!(), -// default(ms(1000)) => {} -// } -// select! { -// send(s, 8) -> res => res.unwrap(), -// default(ms(1000)) => panic!(), -// } -// select! { -// send(s, 9) -> res => assert_eq!(res, Err(SendError(9))), -// default(ms(1000)) => panic!(), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1500)); -// select! { -// recv(r) -> v => assert_eq!(v, Ok(8)), -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn disconnect_wakes_sender() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// send(s, ()) -> res => assert_eq!(res, Err(SendError(()))), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1000)); -// drop(r); -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn disconnect_wakes_receiver() { -// let (s, r) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(move |_| { -// select! { -// recv(r) -> res => assert_eq!(res, Err(RecvError)), -// } -// }); -// scope.spawn(move |_| { -// thread::sleep(ms(1000)); -// drop(s); -// }); -// }) -// .unwrap(); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/stream.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/stream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/stream.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/stream.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ -#[cfg(feature = "async")] -use { - flume::*, - futures::{stream::FuturesUnordered, StreamExt, TryFutureExt}, - async_std::prelude::FutureExt, - std::time::Duration, -}; -use futures::{stream, Stream}; - -#[cfg(feature = "async")] -#[test] -fn stream_recv() { - let (tx, rx) = unbounded(); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - tx.send(42u32).unwrap(); - println!("sent"); - }); - - async_std::task::block_on(async { - println!("receiving..."); - let x = rx.stream().next().await; - println!("received"); - assert_eq!(x, Some(42)); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn stream_recv_disconnect() { - let (tx, rx) = bounded::(0); - - let t = std::thread::spawn(move || { - tx.send(42); - std::thread::sleep(std::time::Duration::from_millis(250)); - drop(tx) - }); - - async_std::task::block_on(async { - let mut stream = rx.into_stream(); - assert_eq!(stream.next().await, Some(42)); - assert_eq!(stream.next().await, None); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn stream_recv_drop_recv() { - let (tx, rx) = bounded::(10); - - let rx2 = rx.clone(); - let mut stream = rx.into_stream(); - - async_std::task::block_on(async { - let res = async_std::future::timeout( - std::time::Duration::from_millis(500), - stream.next() - ).await; - - assert!(res.is_err()); - }); - - let t = std::thread::spawn(move || { - async_std::task::block_on(async { - rx2.stream().next().await - }) - }); - - std::thread::sleep(std::time::Duration::from_millis(500)); - - tx.send(42).unwrap(); - - drop(stream); - - assert_eq!(t.join().unwrap(), Some(42)) -} - -#[cfg(feature = "async")] -#[test] -fn r#stream_drop_send_disconnect() { - let (tx, rx) = bounded::(1); - - let t = std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(250)); - drop(tx); - }); - - async_std::task::block_on(async { - let mut stream = rx.into_stream(); - assert_eq!(stream.next().await, None); - }); - - t.join().unwrap(); -} - -#[cfg(feature = "async")] -#[async_std::test] -async fn stream_send_1_million_no_drop_or_reorder() { - #[derive(Debug)] - enum Message { - Increment { - old: u64, - }, - ReturnCount, - } - - let (tx, rx) = unbounded(); - - let t = async_std::task::spawn(async move { - let mut count = 0u64; - let mut stream = rx.into_stream(); - - while let Some(Message::Increment { old }) = stream.next().await { - assert_eq!(old, count); - count += 1; - } - - count - }); - - for next in 0..1_000_000 { - tx.send(Message::Increment { old: next }).unwrap(); - } - - tx.send(Message::ReturnCount).unwrap(); - - let count = t.await; - assert_eq!(count, 1_000_000) -} - -#[cfg(feature = "async")] -#[async_std::test] -async fn parallel_streams_and_async_recv() { - let (tx, rx) = flume::unbounded(); - let rx = ℞ - let send_fut = async move { - let n_sends: usize = 100000; - for _ in 0..n_sends { - tx.send_async(()).await.unwrap(); - } - }; - - async_std::task::spawn( - send_fut - .timeout(Duration::from_secs(5)) - .map_err(|_| panic!("Send timed out!")) - ); - - let mut futures_unordered = (0..250) - .map(|n| async move { - if n % 2 == 0 { - let mut stream = rx.stream(); - while let Some(()) = stream.next().await {} - } else { - while let Ok(()) = rx.recv_async().await {} - } - - }) - .collect::>(); - - let recv_fut = async { - while futures_unordered.next().await.is_some() {} - }; - - recv_fut - .timeout(Duration::from_secs(5)) - .map_err(|_| panic!("Receive timed out!")) - .await - .unwrap(); -} - -#[cfg(feature = "async")] -#[test] -fn stream_no_double_wake() { - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Arc; - use std::pin::Pin; - use std::task::Context; - use futures::task::{waker, ArcWake}; - use futures::Stream; - - let count = Arc::new(AtomicUsize::new(0)); - - // all this waker does is count how many times it is called - struct CounterWaker { - count: Arc, - } - - impl ArcWake for CounterWaker { - fn wake_by_ref(arc_self: &Arc) { - arc_self.count.fetch_add(1, Ordering::SeqCst); - } - } - - // create waker and context - let w = CounterWaker { - count: count.clone(), - }; - let w = waker(Arc::new(w)); - let cx = &mut Context::from_waker(&w); - - // create unbounded channel - let (tx, rx) = unbounded::<()>(); - let mut stream = rx.stream(); - - // register waker with stream - let _ = Pin::new(&mut stream).poll_next(cx); - - // send multiple items - tx.send(()).unwrap(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - - // verify that stream is only woken up once. - assert_eq!(count.load(Ordering::SeqCst), 1); -} - -#[cfg(feature = "async")] -#[async_std::test] -async fn stream_forward_issue_55() { // https://github.com/zesterer/flume/issues/55 - fn dummy_stream() -> impl Stream { - stream::unfold(0, |count| async move { - if count < 1000 { - Some((count, count + 1)) - } else { - None - } - }) - } - - let (send_task, recv_task) = { - use futures::SinkExt; - let (tx, rx) = flume::bounded(100); - - let send_task = dummy_stream() - .map(|i| Ok(i)) - .forward(tx.into_sink().sink_map_err(|e| { - panic!("send error:{:#?}", e) - })); - - let recv_task = rx - .into_stream() - .for_each(|item| async move {}); - (send_task, recv_task) - }; - - let jh = async_std::task::spawn(send_task); - async_std::task::block_on(recv_task); - jh.await.unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/thread_locals.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/thread_locals.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/thread_locals.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/thread_locals.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -// //! Tests that make sure accessing thread-locals while exiting the thread doesn't cause panics. - -// extern crate crossbeam_utils; - -// use std::thread; -// use std::time::Duration; - -// use flume::unbounded; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// #[cfg_attr(target_os = "macos", ignore = "TLS is destroyed too early on macOS")] -// fn use_while_exiting() { -// struct Foo; - -// impl Drop for Foo { -// fn drop(&mut self) { -// // A blocking operation after the thread-locals have been dropped. This will attempt to -// // use the thread-locals and must not panic. -// let (_s, r) = unbounded::<()>(); -// select! { -// recv(r) -> _ => {} -// default(ms(100)) => {} -// } -// } -// } - -// thread_local! { -// static FOO: Foo = Foo; -// } - -// let (s, r) = unbounded::<()>(); - -// scope(|scope| { -// scope.spawn(|_| { -// // First initialize `FOO`, then the thread-locals related to crossbeam-channel. -// FOO.with(|_| ()); -// r.recv().unwrap(); -// // At thread exit, thread-locals related to crossbeam-channel get dropped first and -// // `FOO` is dropped last. -// }); - -// scope.spawn(|_| { -// thread::sleep(ms(100)); -// s.send(()).unwrap(); -// }); -// }) -// .unwrap(); -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/tick.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/tick.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/tick.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/tick.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,353 +0,0 @@ -// //! Tests for the tick channel flavor. - -// #[macro_use] -// extern crate crossbeam_channel; -// extern crate crossbeam_utils; -// extern crate rand; - -// use std::sync::atomic::AtomicUsize; -// use std::sync::atomic::Ordering; -// use std::thread; -// use std::time::{Duration, Instant}; - -// use crossbeam_channel::{after, tick, Select, TryRecvError}; -// use crossbeam_utils::thread::scope; - -// fn ms(ms: u64) -> Duration { -// Duration::from_millis(ms) -// } - -// #[test] -// fn fire() { -// let start = Instant::now(); -// let r = tick(ms(50)); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// thread::sleep(ms(100)); - -// let fired = r.try_recv().unwrap(); -// assert!(start < fired); -// assert!(fired - start >= ms(50)); - -// let now = Instant::now(); -// assert!(fired < now); -// assert!(now - fired >= ms(50)); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - -// select! { -// recv(r) -> _ => panic!(), -// default => {} -// } - -// select! { -// recv(r) -> _ => {} -// recv(tick(ms(200))) -> _ => panic!(), -// } -// } - -// #[test] -// fn intervals() { -// let start = Instant::now(); -// let r = tick(ms(50)); - -// let t1 = r.recv().unwrap(); -// assert!(start + ms(50) <= t1); -// assert!(start + ms(100) > t1); - -// thread::sleep(ms(300)); -// let t2 = r.try_recv().unwrap(); -// assert!(start + ms(100) <= t2); -// assert!(start + ms(150) > t2); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// let t3 = r.recv().unwrap(); -// assert!(start + ms(400) <= t3); -// assert!(start + ms(450) > t3); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn capacity() { -// const COUNT: usize = 10; - -// for i in 0..COUNT { -// let r = tick(ms(i as u64)); -// assert_eq!(r.capacity(), Some(1)); -// } -// } - -// #[test] -// fn len_empty_full() { -// let r = tick(ms(50)); - -// assert_eq!(r.len(), 0); -// assert_eq!(r.is_empty(), true); -// assert_eq!(r.is_full(), false); - -// thread::sleep(ms(100)); - -// assert_eq!(r.len(), 1); -// assert_eq!(r.is_empty(), false); -// assert_eq!(r.is_full(), true); - -// r.try_recv().unwrap(); - -// assert_eq!(r.len(), 0); -// assert_eq!(r.is_empty(), true); -// assert_eq!(r.is_full(), false); -// } - -// #[test] -// fn try_recv() { -// let r = tick(ms(200)); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(100)); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(200)); -// assert!(r.try_recv().is_ok()); -// assert!(r.try_recv().is_err()); - -// thread::sleep(ms(200)); -// assert!(r.try_recv().is_ok()); -// assert!(r.try_recv().is_err()); -// } - -// #[test] -// fn recv() { -// let start = Instant::now(); -// let r = tick(ms(50)); - -// let fired = r.recv().unwrap(); -// assert!(start < fired); -// assert!(fired - start >= ms(50)); - -// let now = Instant::now(); -// assert!(fired < now); -// assert!(now - fired < fired - start); - -// assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -// } - -// #[test] -// fn recv_timeout() { -// let start = Instant::now(); -// let r = tick(ms(200)); - -// assert!(r.recv_timeout(ms(100)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(100)); -// assert!(now - start <= ms(150)); - -// let fired = r.recv_timeout(ms(200)).unwrap(); -// assert!(fired - start >= ms(200)); -// assert!(fired - start <= ms(250)); - -// assert!(r.recv_timeout(ms(100)).is_err()); -// let now = Instant::now(); -// assert!(now - start >= ms(300)); -// assert!(now - start <= ms(350)); - -// let fired = r.recv_timeout(ms(200)).unwrap(); -// assert!(fired - start >= ms(400)); -// assert!(fired - start <= ms(450)); -// } - -// #[test] -// fn recv_two() { -// let r1 = tick(ms(50)); -// let r2 = tick(ms(50)); - -// scope(|scope| { -// scope.spawn(|_| { -// for _ in 0..10 { -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// } -// } -// }); -// scope.spawn(|_| { -// for _ in 0..10 { -// select! { -// recv(r1) -> _ => {} -// recv(r2) -> _ => {} -// } -// } -// }); -// }) -// .unwrap(); -// } - -// #[test] -// fn recv_race() { -// select! { -// recv(tick(ms(50))) -> _ => {} -// recv(tick(ms(100))) -> _ => panic!(), -// } - -// select! { -// recv(tick(ms(100))) -> _ => panic!(), -// recv(tick(ms(50))) -> _ => {} -// } -// } - -// #[test] -// fn stress_default() { -// const COUNT: usize = 10; - -// for _ in 0..COUNT { -// select! { -// recv(tick(ms(0))) -> _ => {} -// default => panic!(), -// } -// } - -// for _ in 0..COUNT { -// select! { -// recv(tick(ms(100))) -> _ => panic!(), -// default => {} -// } -// } -// } - -// #[test] -// fn select() { -// const THREADS: usize = 4; - -// let hits = AtomicUsize::new(0); -// let r1 = tick(ms(200)); -// let r2 = tick(ms(300)); - -// scope(|scope| { -// for _ in 0..THREADS { -// scope.spawn(|_| { -// let timeout = after(ms(1100)); -// loop { -// let mut sel = Select::new(); -// let oper1 = sel.recv(&r1); -// let oper2 = sel.recv(&r2); -// let oper3 = sel.recv(&timeout); -// let oper = sel.select(); -// match oper.index() { -// i if i == oper1 => { -// oper.recv(&r1).unwrap(); -// hits.fetch_add(1, Ordering::SeqCst); -// } -// i if i == oper2 => { -// oper.recv(&r2).unwrap(); -// hits.fetch_add(1, Ordering::SeqCst); -// } -// i if i == oper3 => { -// oper.recv(&timeout).unwrap(); -// break; -// } -// _ => unreachable!(), -// } -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(hits.load(Ordering::SeqCst), 8); -// } - -// #[test] -// fn ready() { -// const THREADS: usize = 4; - -// let hits = AtomicUsize::new(0); -// let r1 = tick(ms(200)); -// let r2 = tick(ms(300)); - -// scope(|scope| { -// for _ in 0..THREADS { -// scope.spawn(|_| { -// let timeout = after(ms(1100)); -// 'outer: loop { -// let mut sel = Select::new(); -// sel.recv(&r1); -// sel.recv(&r2); -// sel.recv(&timeout); -// loop { -// match sel.ready() { -// 0 => { -// if r1.try_recv().is_ok() { -// hits.fetch_add(1, Ordering::SeqCst); -// break; -// } -// } -// 1 => { -// if r2.try_recv().is_ok() { -// hits.fetch_add(1, Ordering::SeqCst); -// break; -// } -// } -// 2 => { -// if timeout.try_recv().is_ok() { -// break 'outer; -// } -// } -// _ => unreachable!(), -// } -// } -// } -// }); -// } -// }) -// .unwrap(); - -// assert_eq!(hits.load(Ordering::SeqCst), 8); -// } - -// #[test] -// fn fairness() { -// const COUNT: usize = 30; - -// for &dur in &[0, 1] { -// let mut hits = [0usize; 2]; - -// for _ in 0..COUNT { -// let r1 = tick(ms(dur)); -// let r2 = tick(ms(dur)); - -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// } -// } -// } - -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } -// } - -// #[test] -// fn fairness_duplicates() { -// const COUNT: usize = 30; - -// for &dur in &[0, 1] { -// let mut hits = [0usize; 5]; - -// for _ in 0..COUNT { -// let r = tick(ms(dur)); - -// for _ in 0..COUNT { -// select! { -// recv(r) -> _ => hits[0] += 1, -// recv(r) -> _ => hits[1] += 1, -// recv(r) -> _ => hits[2] += 1, -// recv(r) -> _ => hits[3] += 1, -// recv(r) -> _ => hits[4] += 1, -// } -// } -// } - -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// } -// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/zero.rs clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/zero.rs --- clamav-1.4.3+dfsg/.cargo/vendor/flume/tests/zero.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/flume/tests/zero.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,557 +0,0 @@ -//! Tests for the zero channel flavor. - -extern crate crossbeam_utils; -extern crate rand; - -use std::any::Any; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; -use std::thread; -use std::time::Duration; - -use flume::{bounded, Receiver}; -use flume::{RecvError, RecvTimeoutError, TryRecvError}; -use flume::{SendError, SendTimeoutError, TrySendError}; -use crossbeam_utils::thread::scope; -use rand::{thread_rng, Rng}; - -fn ms(ms: u64) -> Duration { - Duration::from_millis(ms) -} - -#[test] -fn smoke() { - let (s, r) = bounded(0); - assert_eq!(s.try_send(7), Err(TrySendError::Full(7))); - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); -} - -#[test] -fn capacity() { - let (s, r) = bounded::<()>(0); - assert_eq!(s.capacity(), Some(0)); - assert_eq!(r.capacity(), Some(0)); -} - -#[test] -fn len_empty_full() { - let (s, r) = bounded(0); - - assert_eq!(s.len(), 0); - assert_eq!(s.is_empty(), true); - assert_eq!(s.is_full(), true); - assert_eq!(r.len(), 0); - assert_eq!(r.is_empty(), true); - assert_eq!(r.is_full(), true); - - scope(|scope| { - scope.spawn(|_| s.send(0).unwrap()); - scope.spawn(|_| r.recv().unwrap()); - }) - .unwrap(); - - assert_eq!(s.len(), 0); - assert_eq!(s.is_empty(), true); - assert_eq!(s.is_full(), true); - assert_eq!(r.len(), 0); - assert_eq!(r.is_empty(), true); - assert_eq!(r.is_full(), true); -} - -#[test] -fn try_recv() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); - thread::sleep(ms(1500)); - assert_eq!(r.try_recv(), Ok(7)); - thread::sleep(ms(500)); - assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv(), Ok(7)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(8)); - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(9)); - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - s.send(8).unwrap(); - s.send(9).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn recv_timeout() { - let (s, r) = bounded::(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout)); - assert_eq!(r.recv_timeout(ms(1000)), Ok(7)); - assert_eq!( - r.recv_timeout(ms(1000)), - Err(RecvTimeoutError::Disconnected) - ); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - s.send(7).unwrap(); - }); - }) - .unwrap(); -} - -#[test] -fn try_send() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(s.try_send(7), Err(TrySendError::Full(7))); - thread::sleep(ms(1500)); - assert_eq!(s.try_send(8), Ok(())); - thread::sleep(ms(500)); - assert_eq!(s.try_send(9), Err(TrySendError::Disconnected(9))); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - assert_eq!(r.recv(), Ok(8)); - }); - }) - .unwrap(); -} - -#[test] -fn send() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - s.send(7).unwrap(); - thread::sleep(ms(1000)); - s.send(8).unwrap(); - thread::sleep(ms(1000)); - s.send(9).unwrap(); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - assert_eq!(r.recv(), Ok(7)); - assert_eq!(r.recv(), Ok(8)); - assert_eq!(r.recv(), Ok(9)); - }); - }) - .unwrap(); -} - -#[test] -fn send_timeout() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!( - s.send_timeout(7, ms(1000)), - Err(SendTimeoutError::Timeout(7)) - ); - assert_eq!(s.send_timeout(8, ms(1000)), Ok(())); - assert_eq!( - s.send_timeout(9, ms(1000)), - Err(SendTimeoutError::Disconnected(9)) - ); - }); - scope.spawn(move |_| { - thread::sleep(ms(1500)); - assert_eq!(r.recv(), Ok(8)); - }); - }) - .unwrap(); -} - -#[test] -fn len() { - const COUNT: usize = 25_000; - - let (s, r) = bounded(0); - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); - - scope(|scope| { - scope.spawn(|_| { - for i in 0..COUNT { - assert_eq!(r.recv(), Ok(i)); - assert_eq!(r.len(), 0); - } - }); - - scope.spawn(|_| { - for i in 0..COUNT { - s.send(i).unwrap(); - assert_eq!(s.len(), 0); - } - }); - }) - .unwrap(); - - assert_eq!(s.len(), 0); - assert_eq!(r.len(), 0); -} - -#[test] -fn disconnect_wakes_sender() { - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - assert_eq!(s.send(()), Err(SendError(()))); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - drop(r); - }); - }) - .unwrap(); -} - -#[test] -fn disconnect_wakes_receiver() { - let (s, r) = bounded::<()>(0); - - scope(|scope| { - scope.spawn(move |_| { - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - thread::sleep(ms(1000)); - drop(s); - }); - }) - .unwrap(); -} - -#[test] -fn spsc() { - const COUNT: usize = 100_000; - - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - for i in 0..COUNT { - assert_eq!(r.recv(), Ok(i)); - } - assert!(r.recv().is_err()); - }); - scope.spawn(move |_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - }) - .unwrap(); -} - -#[test] -fn mpmc() { - const COUNT: usize = 25_000; - const THREADS: usize = 4; - - let (s, r) = bounded::(0); - let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::>(); - - scope(|scope| { - for _ in 0..THREADS { - scope.spawn(|_| { - for _ in 0..COUNT { - let n = r.recv().unwrap(); - v[n].fetch_add(1, Ordering::SeqCst); - } - }); - } - for _ in 0..THREADS { - scope.spawn(|_| { - for i in 0..COUNT { - s.send(i).unwrap(); - } - }); - } - }) - .unwrap(); - - for c in v { - assert_eq!(c.load(Ordering::SeqCst), THREADS); - } -} - -#[test] -fn stress_oneshot() { - const COUNT: usize = 10_000; - - for _ in 0..COUNT { - let (s, r) = bounded(1); - - scope(|scope| { - scope.spawn(|_| r.recv().unwrap()); - scope.spawn(|_| s.send(0).unwrap()); - }) - .unwrap(); - } -} - -#[test] -fn stress_iter() { - const COUNT: usize = 1000; - - let (request_s, request_r) = bounded(0); - let (response_s, response_r) = bounded(0); - - scope(|scope| { - scope.spawn(move |_| { - let mut count = 0; - loop { - for x in response_r.try_iter() { - count += x; - if count == COUNT { - return; - } - } - let _ = request_s.try_send(()); - } - }); - - for _ in request_r.iter() { - if response_s.send(1).is_err() { - break; - } - } - }) - .unwrap(); -} - -#[test] -fn stress_timeout_two_threads() { - const COUNT: usize = 100; - - let (s, r) = bounded(0); - - scope(|scope| { - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - loop { - if let Ok(()) = s.send_timeout(i, ms(10)) { - break; - } - } - } - }); - - scope.spawn(|_| { - for i in 0..COUNT { - if i % 2 == 0 { - thread::sleep(ms(50)); - } - loop { - if let Ok(x) = r.recv_timeout(ms(10)) { - assert_eq!(x, i); - break; - } - } - } - }); - }) - .unwrap(); -} - -#[test] -fn drops() { - static DROPS: AtomicUsize = AtomicUsize::new(0); - - #[derive(Debug, PartialEq)] - struct DropCounter; - - impl Drop for DropCounter { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - let mut rng = thread_rng(); - - for _ in 0..100 { - let steps = rng.gen_range(0..3_000); - - DROPS.store(0, Ordering::SeqCst); - let (s, r) = bounded::(0); - - scope(|scope| { - scope.spawn(|_| { - for _ in 0..steps { - r.recv().unwrap(); - } - }); - - scope.spawn(|_| { - for _ in 0..steps { - s.send(DropCounter).unwrap(); - } - }); - }) - .unwrap(); - - assert_eq!(DROPS.load(Ordering::SeqCst), steps); - drop(s); - drop(r); - assert_eq!(DROPS.load(Ordering::SeqCst), steps); - } -} - -// #[test] -// fn fairness() { -// const COUNT: usize = 10_000; - -// let (s1, r1) = bounded::<()>(0); -// let (s2, r2) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| { -// let mut hits = [0usize; 2]; -// for _ in 0..COUNT { -// select! { -// recv(r1) -> _ => hits[0] += 1, -// recv(r2) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// }); - -// let mut hits = [0usize; 2]; -// for _ in 0..COUNT { -// select! { -// send(s1, ()) -> _ => hits[0] += 1, -// send(s2, ()) -> _ => hits[1] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// }) -// .unwrap(); -// } - -// #[test] -// fn fairness_duplicates() { -// const COUNT: usize = 10_000; - -// let (s, r) = bounded::<()>(0); - -// scope(|scope| { -// scope.spawn(|_| { -// let mut hits = [0usize; 5]; -// for _ in 0..COUNT { -// select! { -// recv(r) -> _ => hits[0] += 1, -// recv(r) -> _ => hits[1] += 1, -// recv(r) -> _ => hits[2] += 1, -// recv(r) -> _ => hits[3] += 1, -// recv(r) -> _ => hits[4] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// }); - -// let mut hits = [0usize; 5]; -// for _ in 0..COUNT { -// select! { -// send(s, ()) -> _ => hits[0] += 1, -// send(s, ()) -> _ => hits[1] += 1, -// send(s, ()) -> _ => hits[2] += 1, -// send(s, ()) -> _ => hits[3] += 1, -// send(s, ()) -> _ => hits[4] += 1, -// } -// } -// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2)); -// }) -// .unwrap(); -// } - -// #[test] -// fn recv_in_send() { -// let (s, r) = bounded(0); - -// scope(|scope| { -// scope.spawn(|_| { -// thread::sleep(ms(100)); -// r.recv() -// }); - -// scope.spawn(|_| { -// thread::sleep(ms(500)); -// s.send(()).unwrap(); -// }); - -// select! { -// send(s, r.recv().unwrap()) -> _ => {} -// } -// }) -// .unwrap(); -// } - -#[test] -fn channel_through_channel() { - const COUNT: usize = 1000; - - type T = Box; - - let (s, r) = bounded::(0); - - scope(|scope| { - scope.spawn(move |_| { - let mut s = s; - - for _ in 0..COUNT { - let (new_s, new_r) = bounded(0); - let new_r: T = Box::new(Some(new_r)); - - s.send(new_r).unwrap(); - s = new_s; - } - }); - - scope.spawn(move |_| { - let mut r = r; - - for _ in 0..COUNT { - r = r - .recv() - .unwrap() - .downcast_mut::>>() - .unwrap() - .take() - .unwrap() - } - }); - }) - .unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/generic-array/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/generic-array/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"478d33deb9d0c943c20671eed67bc393891aad1679e61f74412f98c9a5017f84","Cargo.toml":"4b5daed75505275d11f4854dd9172f910da61d9856ca2936d95e2e6e0c9040e4","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","src/arr.rs":"c115d6926deb769ced772e9c4e1c84baf1bdea4fe4b9eb2061658a63869eab62","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impl_zeroize.rs":"dd1af63ef2cba2120c6f775350c98eb12bb1be6ba784d5350d07d4ae5419c292","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"4f50253f4130caa0780984b64467ca1916a881410f631f7eb85a1724b3ab4ced","src/lib.rs":"20b64b4359b0e82a3523fd536ad06de25e174cead734cffd3fa5f7c48f659247","src/sequence.rs":"26679cfec035bae7298f067f37e8d42a1eda8fe241e9cf2c2977ba4bddddab1d"},"package":"85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"4ffa26adbb029ef507f165ca47fb9699af8b49e642d1e60942666273c5a521a9","CHANGELOG.md":"478d33deb9d0c943c20671eed67bc393891aad1679e61f74412f98c9a5017f84","Cargo.toml":"4b5daed75505275d11f4854dd9172f910da61d9856ca2936d95e2e6e0c9040e4","Cargo.toml.orig":"12c6e718e7f54564e81ca6e5f5e3d0fef220a86e8dab77215e6ff38b6f6c2081","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","src/arr.rs":"c115d6926deb769ced772e9c4e1c84baf1bdea4fe4b9eb2061658a63869eab62","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impl_zeroize.rs":"dd1af63ef2cba2120c6f775350c98eb12bb1be6ba784d5350d07d4ae5419c292","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"4f50253f4130caa0780984b64467ca1916a881410f631f7eb85a1724b3ab4ced","src/lib.rs":"20b64b4359b0e82a3523fd536ad06de25e174cead734cffd3fa5f7c48f659247","src/sequence.rs":"26679cfec035bae7298f067f37e8d42a1eda8fe241e9cf2c2977ba4bddddab1d"},"package":"85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/generic-array/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/generic-array/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/generic-array/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "1397d2bb40c406901b7827161b73b34b056cbe3a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/generic-array/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/generic-array/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/generic-array/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/generic-array/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,43 @@ +[package] + +name = "generic-array" +version = "0.14.7" +authors = [ "Bartłomiej Kamiński ", "Aaron Trent " ] + +description = "Generic types implementing functionality of arrays" +readme = "README.md" + +license = "MIT" + +documentation = "http://fizyk20.github.io/generic-array/generic_array/" +repository = "https://github.com/fizyk20/generic-array.git" + +keywords = ["generic", "array"] +categories = ["data-structures", "no-std"] + +include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md", "build.rs"] + +[badges] +travis-ci = { repository = "fizyk20/generic-array" } + +[lib] +name = "generic_array" + +[features] +more_lengths = [] + +[dependencies] +typenum = "1.12" +serde = { version = "1.0", optional = true, default-features = false } +zeroize = { version = "1", optional = true, default-features = false } + +[dev_dependencies] +# this can't yet be made optional, see https://github.com/rust-lang/cargo/issues/1596 +serde_json = "1.0" +bincode = "1.0" + +[build_dependencies] +version_check = "0.9" + +[package.metadata.docs.rs] +features = ["serde", "zeroize"] \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"9930208af94a68f65edfe7acb4b4f967c9aaa8bdf8f8e5bb5806539207f9f039","CHANGELOG.md":"3793e1d3c10656813cf278d674fe943c7ec251b30cba434d8f6c7d6b4948a830","Cargo.lock":"2fe4bb173cc0f4b6b515d87feab12aab157ebf12f4f14869aebf24f1a028c8d2","Cargo.toml":"5fd1d61c342777480822b8f8259a7bd8cbf6c2486a3d389b2d5b235f667a7952","Cargo.toml.orig":"4b13c332865245a22cb5fef091e02547ef792a0aa7291dcf2d9c07ae783f19b0","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"29e9fe5074bd27e0e5d5d110394fbbcd841baee2651a3c4b4560a632702cede4","README.md":"39a9371cee9b72f7aff7fcbe0018e1a90c1a0692266cacdcaac25166080b9cb0","SECURITY.md":"816ea79f8c7937888ab5a972a1efb270c4bada028b448953a195359fe11d526e","benches/buffer.rs":"20fb7dd9edafe0c182f1fe037b28d7542f8e0ae742d51e97aeebf418edde49aa","build.rs":"d542c9c3bbc2f64a26c758eac8af16178aab52464bdd8bf0b9a767ba87665021","src/backends.rs":"61f8d982cd502f3229f49bef2f9b40e181c7c16fb41d029aa2e77f32b10c10a6","src/backends/apple_other.rs":"f8fa784588f347cfd7c2b5f37a96b23d446f95c3157668069d7146e281fa783b","src/backends/custom.rs":"c8776ff0dda65cef1373b8624043f8a42ce4fd6183fbeb8918f9df5d4a13d457","src/backends/efi_rng.rs":"873b7343a003a5f222753fbd50cba3f2beeacec4386ad3272ec98d654a4466d4","src/backends/esp_idf.rs":"b50d6c582b49488204151c2036a100aac7902b8215fb791f271e1b5fc772db9a","src/backends/fuchsia.rs":"d7c660a62f1da2c41c537ccea085bba6d3f83b82c34e6e63175130feca9dece8","src/backends/getentropy.rs":"a0fdf57546e20be8e76d21ec5f815f07a3a4dfb590d4d693cc2e78b494676304","src/backends/getrandom.rs":"49a7ca8cc47178b47339ee4aeb59e11b629735eb9fedaa21ee2da7073b2574c5","src/backends/hermit.rs":"92e0cf4103b5ddc15ed48cad8d7165ba8e344fde0f07960385b36590466ee67c","src/backends/linux_android_with_fallback.rs":"af1e4fdd6904f8c78c6cef9af21c626bf4ba1b38d4bf8cd081cb739acc0a34b2","src/backends/linux_raw.rs":"2647e9492e46afdb1838c824094f6ab6e14fb4a82fa8274bea8dd2d4151f32dd","src/backends/netbsd.rs":"ca6a6c4c17c04ec987002296debdd7a03b10f5efd5bcb79f159b9a13c4b6821f","src/backends/rdrand.rs":"2a06eb62ad7e97c2486ab1b0159e4b9fe3a1c0a39d479a836d23051f89cb9aed","src/backends/rndr.rs":"bc06a88e3314a06494b6fe70bdae684fe45f9a6a63d28c61dbd90f66595424d0","src/backends/sanitizer.rs":"ea6d986ccacc31d2efdf116e7f0ef509845f596b4f8aced11c622df12a13be25","src/backends/solaris.rs":"b263a3e8bc3c490a0c589d2a1a67d8fdb36119993df1f8d05f43975ff88f9c3e","src/backends/solid.rs":"1c92fc4c5a8ac67b64af560bb7843d6e447efe9785e557f064348fb84b83ceb8","src/backends/unsupported.rs":"a531ab9883b7d7b584c6f37a5c13543ec63d25d3acc36608d57d5d82ef44cbff","src/backends/use_file.rs":"6c1e982be1663e91d8551fa21529710ac5551506bb1af8803ff87b180d091f00","src/backends/vxworks.rs":"64ee8619c5b5aa267761aabc99552ba8df71d14cda7cc66d6c1e4f4fb1ed8d00","src/backends/wasi_p1.rs":"77755c8fefb9f36509b2e6764edb9f8293dc1efa3d5a9bc85d28723ceeb7aec0","src/backends/wasi_p2.rs":"3aff410d753db6ad875b79bc6a94e05e0e98d38f9e0078ef71871f185cbacecf","src/backends/wasm_js.rs":"5913b33ec9cb4076cef65d461ce82af98e9233f621eac8fab44b68fd37080927","src/backends/windows.rs":"49a08dee7b1758954d25f879efe028147a6fc0598c77500ebb2925412eaf7e0b","src/backends/windows_legacy.rs":"b0b7b47c98a03ea017c6cac3531a0f0754a716bcb87b734e3d66c393d4ab72aa","src/error.rs":"43f4918d3c47d211d223543fa4b93074f883dcb7232b673b03c8b7fe19ef8e7a","src/error_std_impls.rs":"4c068e81d876237a7e0a0e91519896bd670c2f999ca729f7fb970caf888cab46","src/lazy.rs":"9c7e3efcc7b4cc2252751d29e42465bae8cbe49461a4a81a006d8d2c45003fd1","src/lib.rs":"f7628991475fd0ef00ec841ee3d28c2e6e2309d0e5c528dd9e6d8044ab296e66","src/util.rs":"207e21353f4e402daf84ff137c8d4aa4ffafa48141194ae7148252e06dcadd9f","src/util_libc.rs":"1d3f16d8996295822e6cbfc848e90912795f378913627c6b765f47b2185d9480","tests/mod.rs":"b8e88300a1ec0b2f6cbc03d40cc66eacae625d1fdc1163f4cf50fae7712d2bdc"},"package":"899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38e4ad38309a85b56eef4fc759535ccfc322ba9a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/getrandom/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,673 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.3.4] - 2025-10-14 + +### Major change to `wasm_js` backend + +Now, when the `wasm_js` feature is enabled, the `wasm_js` backend will be used +by default. Users of `wasm32-unknown-unknown` targeting JavaScript environments +like the Web and Node.js will no longer need to specify: +``` +--cfg getrandom_backend="wasm_js" +``` +in `RUSTFLAGS` for the crate to compile. They can now simple enable a feature. + +Note: this should not affect non-JS users of the `wasm32-unknown-unknown` +target. Using `--cfg getrandom_backend` will still override the source of +randomness _even if_ the `wasm_js` feature is enabled. This includes +`--cfg getrandom_backend=custom` and `--cfg getrandom_backend=unsupported`. + +For more information, see the discussions in [#671], [#675], and [#730]. + +### Added +- `unsupported` opt-in backend [#667] +- `windows_legacy` opt-in backend [#724] + +### Changed +- Implement Memory Sanitizer unpoisoning more precisely [#678] +- Relax MSRV for the `linux_raw` opt-in backend on ARM targets [#688] +- Use `getrandom` syscall on all RISC-V Linux targets [#699] +- Replaced `wasi` dependency with `wasip2` [#721] +- Enable `wasm_js` backend by default if the `wasm_js` feature is enabled [#730] + +### Removed +- Unstable `rustc-dep-of-std` crate feature [#694] + +[#667]: https://github.com/rust-random/getrandom/pull/667 +[#671]: https://github.com/rust-random/getrandom/issues/671 +[#675]: https://github.com/rust-random/getrandom/pull/675 +[#678]: https://github.com/rust-random/getrandom/pull/678 +[#688]: https://github.com/rust-random/getrandom/pull/688 +[#694]: https://github.com/rust-random/getrandom/pull/694 +[#699]: https://github.com/rust-random/getrandom/pull/699 +[#721]: https://github.com/rust-random/getrandom/pull/721 +[#724]: https://github.com/rust-random/getrandom/pull/724 +[#730]: https://github.com/rust-random/getrandom/pull/730 + +## [0.3.3] - 2025-05-09 + +### Changed +- Doc improvements [#632] [#634] [#635] +- Add crate version to docs.rs links used in `compile_error!`s [#639] + +### Fixed +- Error handling in WASI p1 [#661] + +[#632]: https://github.com/rust-random/getrandom/pull/632 +[#634]: https://github.com/rust-random/getrandom/pull/634 +[#635]: https://github.com/rust-random/getrandom/pull/635 +[#639]: https://github.com/rust-random/getrandom/pull/639 +[#661]: https://github.com/rust-random/getrandom/pull/661 + +## [0.3.2] - 2025-03-17 + +### Added +- `efi_rng` opt-in backend [#570] +- `linux_raw` opt-in backend [#572] +- `.cargo/config.toml` example in the crate-level docs [#591] +- `getrandom_test_linux_without_fallback` configuration flag to test that file fallback + is not triggered in the `linux_android_with_fallback` backend [#605] +- Built-in support for `*-linux-none` targets [#618] +- Cygwin support [#626] + +### Changed +- Update `wasi` dependency to v0.14 [#594] +- Add `#[inline]` attribute to the inner functions [#596] +- Update WASI and Emscripten links in the crate-level docs [#597] +- Do not use `dlsym` on MUSL targets in the `linux_android_with_fallback` backend [#602] +- Remove `linux_android.rs` and use `getrandom.rs` instead [#603] +- Always use `RtlGenRandom` on Windows targets when compiling with pre-1.78 Rust [#610] +- Internal representation of the `Error` type [#614] +- Remove `windows-targets` dependency and use [`raw-dylib`] directly [#627] + +### Removed +- `Error::INTERNAL_START` and `Error::CUSTOM_START` associated constants [#614] + +[#570]: https://github.com/rust-random/getrandom/pull/570 +[#572]: https://github.com/rust-random/getrandom/pull/572 +[#591]: https://github.com/rust-random/getrandom/pull/591 +[#594]: https://github.com/rust-random/getrandom/pull/594 +[#596]: https://github.com/rust-random/getrandom/pull/596 +[#597]: https://github.com/rust-random/getrandom/pull/597 +[#602]: https://github.com/rust-random/getrandom/pull/602 +[#603]: https://github.com/rust-random/getrandom/pull/603 +[#605]: https://github.com/rust-random/getrandom/pull/605 +[#610]: https://github.com/rust-random/getrandom/pull/610 +[#614]: https://github.com/rust-random/getrandom/pull/614 +[#618]: https://github.com/rust-random/getrandom/pull/618 +[#626]: https://github.com/rust-random/getrandom/pull/626 +[#627]: https://github.com/rust-random/getrandom/pull/627 +[`raw-dylib`]: https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=link#dylib-versus-raw-dylib + +## [0.3.1] - 2025-01-28 + +### Fixed +- Build error on Android [#588] + +[#588]: https://github.com/rust-random/getrandom/pull/588 + +## [0.3.0] - 2025-01-25 + +### Breaking Changes + +#### Changed +- Bump MSRV to 1.63 [#542] +- Rename `getrandom` and `getrandom_uninit` functions to `fill` and `fill_uninit` respectively [#532] + +#### Removed +- `wasm32-wasi` target support (use `wasm32-wasip1` or `wasm32-wasip2` instead) [#499] +- `linux_disable_fallback`, `rdrand`, `js`, `test-in-browser`, and `custom` crate features + in favor of configuration flags [#504] +- `register_custom_getrandom!` macro [#504] +- Implementation of `From` for `Error` and `Error::code` method [#507] +- Internet Explorer 11 support [#554] +- Target-specific associated `Error` constants [#562] + +### Changed +- Use `ProcessPrng` on Windows 10 and up, and use `RtlGenRandom` on older Windows versions [#415] +- Do not use locale-specific `strerror_r` for retrieving error code descriptions [#440] +- Avoid assuming `usize` is the native word size in the `rdrand` backend [#442] +- Do not read from `errno` when `libc` did not indicate error on Solaris [#448] +- Switch from `libpthread`'s mutex to `futex` on Linux and to `nanosleep`-based wait loop + on other targets in the `use_file` backend [#490] +- Do not retry on `EAGAIN` while polling `/dev/random` on Linux [#522] +- Remove separate codepath for Node.js in the `wasm_js` backend + (bumps minimum supported Node.js version to v19) [#557] +- Use `js_namespace` in the `wasm_js` backend [#559] + +### Added +- `wasm32-wasip1` and `wasm32-wasip2` support [#499] +- `getrandom_backend` configuration flag for selection of opt-in backends [#504] +- `Error::new_custom` method [#507] +- `rndr` opt-in backend [#512] +- Automatic MemorySanitizer support [#521] [#571] +- `u32` and `u64` functions for generating random values of the respective type [#544] +- `wasm32v1-none` support in the `wasm_js` backend [#560] +- `wasm_js` crate feature which allows users to enable the `wasm_js` opt-in backend [#574] + +### Fixed +- NetBSD fallback code based on `KERN_ARND` [#555] + +[#415]: https://github.com/rust-random/getrandom/pull/415 +[#440]: https://github.com/rust-random/getrandom/pull/440 +[#442]: https://github.com/rust-random/getrandom/pull/442 +[#448]: https://github.com/rust-random/getrandom/pull/448 +[#490]: https://github.com/rust-random/getrandom/pull/490 +[#499]: https://github.com/rust-random/getrandom/pull/499 +[#504]: https://github.com/rust-random/getrandom/pull/504 +[#507]: https://github.com/rust-random/getrandom/pull/507 +[#512]: https://github.com/rust-random/getrandom/pull/512 +[#521]: https://github.com/rust-random/getrandom/pull/521 +[#522]: https://github.com/rust-random/getrandom/pull/522 +[#532]: https://github.com/rust-random/getrandom/pull/532 +[#542]: https://github.com/rust-random/getrandom/pull/542 +[#544]: https://github.com/rust-random/getrandom/pull/544 +[#554]: https://github.com/rust-random/getrandom/pull/554 +[#555]: https://github.com/rust-random/getrandom/pull/555 +[#557]: https://github.com/rust-random/getrandom/pull/557 +[#559]: https://github.com/rust-random/getrandom/pull/559 +[#560]: https://github.com/rust-random/getrandom/pull/560 +[#562]: https://github.com/rust-random/getrandom/pull/562 +[#571]: https://github.com/rust-random/getrandom/pull/571 +[#574]: https://github.com/rust-random/getrandom/pull/574 + +## [0.2.16] - 2025-04-22 +### Added +- Cygwin support (backport of [#626]) [#654] + +[#654]: https://github.com/rust-random/getrandom/pull/654 + +## [0.2.15] - 2024-05-06 +### Added +- Apple visionOS support [#410] + +### Changed +- Use `libc::getrandom` on DragonflyBSD, FreeBSD, illumos, and Solaris [#411] [#416] [#417] [#420] +- Unify `libc::getentropy`-based implementations [#418] + +[#410]: https://github.com/rust-random/getrandom/pull/410 +[#411]: https://github.com/rust-random/getrandom/pull/411 +[#416]: https://github.com/rust-random/getrandom/pull/416 +[#417]: https://github.com/rust-random/getrandom/pull/417 +[#418]: https://github.com/rust-random/getrandom/pull/418 +[#420]: https://github.com/rust-random/getrandom/pull/420 + +## [0.2.14] - 2024-04-08 +### Fixed +- Enable `/dev/urandom` fallback for MUSL-based Linux targets [#408] + +[#408]: https://github.com/rust-random/getrandom/pull/408 + +## [0.2.13] - 2024-04-06 +### Added +- `linux_disable_fallback` crate feature to disable `/dev/urandom`-based fallback on Linux and + Android targets. Enabling this feature bumps minimum supported Linux kernel version to 3.17 and + Android API level to 23 (Marshmallow). [#396] + +### Changed +- Disable `/dev/urandom` fallback for Linux targets outside of the following `target_arch`es: + `aarch64`, `arm`, `powerpc`, `powerpc64`, `s390x`, `x86`, `x86_64` [#396] +- Do not catch `EPERM` error code on Android while checking availability of + the `getrandom` syscall [#396] + +[#396]: https://github.com/rust-random/getrandom/pull/396 + +## [0.2.12] - 2024-01-09 +### Fixed +- Custom backend for targets without atomics [#385] + +### Changed +- Improve robustness of the Hermit backend and `sys_fill_exact` [#386] +- Raise minimum supported Apple OS versions to macOS 10.12 and iOS 10 [#388] + +### Added +- Document platform support policy [#387] + +[#385]: https://github.com/rust-random/getrandom/pull/385 +[#386]: https://github.com/rust-random/getrandom/pull/386 +[#387]: https://github.com/rust-random/getrandom/pull/387 +[#388]: https://github.com/rust-random/getrandom/pull/388 + +## [0.2.11] - 2023-11-08 +### Added +- GNU/Hurd support [#370] + +### Changed +- Renamed `__getrandom_internal` to `__GETRANDOM_INTERNAL` [#369] +- Updated link to Hermit docs [#374] + +[#369]: https://github.com/rust-random/getrandom/pull/369 +[#370]: https://github.com/rust-random/getrandom/pull/370 +[#374]: https://github.com/rust-random/getrandom/pull/374 + +## [0.2.10] - 2023-06-06 +### Added +- Support for PS Vita (`armv7-sony-vita-newlibeabihf`) [#359] + +### Changed +- Use getentropy from libc on Emscripten targets [#362] + +[#359]: https://github.com/rust-random/getrandom/pull/359 +[#362]: https://github.com/rust-random/getrandom/pull/362 + +## [0.2.9] - 2023-04-06 +### Added +- AIX support [#282] +- `getrandom_uninit` function [#291] +- `wasm64-unknown-unknown` support [#303] +- tvOS and watchOS support [#317] +- QNX/nto support [#325] +- Support for `getrandom` syscall on NetBSD ≥ 10.0 [#331] +- `RtlGenRandom` fallback for non-UWP Windows [#337] + +### Breaking Changes +- Update MSRV to 1.36 [#291] + +### Fixed +- Solaris/OpenBSD/Dragonfly build [#301] + +### Changed +- Update MSRV to 1.36 [#291] +- Use getentropy on Emscripten [#307] +- Solaris: consistently use `/dev/random` source [#310] +- Move 3ds selection above rdrand/js/custom fallback [#312] +- Remove buffer zeroing from Node.js implementation [#315] +- Use `open` instead of `open64` [#326] +- Remove #cfg from bsd_arandom.rs [#332] +- Hermit: use `sys_read_entropy` syscall [#333] +- Eliminate potential panic in sys_fill_exact [#334] +- rdrand: Remove checking for 0 and !0 and instead check CPU family and do a self-test [#335] +- Move `__getrandom_custom` definition into a const block [#344] +- Switch the custom backend to Rust ABI [#347] + +[#282]: https://github.com/rust-random/getrandom/pull/282 +[#291]: https://github.com/rust-random/getrandom/pull/291 +[#301]: https://github.com/rust-random/getrandom/pull/301 +[#303]: https://github.com/rust-random/getrandom/pull/303 +[#307]: https://github.com/rust-random/getrandom/pull/307 +[#310]: https://github.com/rust-random/getrandom/pull/310 +[#312]: https://github.com/rust-random/getrandom/pull/312 +[#315]: https://github.com/rust-random/getrandom/pull/315 +[#317]: https://github.com/rust-random/getrandom/pull/317 +[#325]: https://github.com/rust-random/getrandom/pull/325 +[#326]: https://github.com/rust-random/getrandom/pull/326 +[#331]: https://github.com/rust-random/getrandom/pull/331 +[#332]: https://github.com/rust-random/getrandom/pull/332 +[#333]: https://github.com/rust-random/getrandom/pull/333 +[#334]: https://github.com/rust-random/getrandom/pull/334 +[#335]: https://github.com/rust-random/getrandom/pull/335 +[#337]: https://github.com/rust-random/getrandom/pull/337 +[#344]: https://github.com/rust-random/getrandom/pull/344 +[#347]: https://github.com/rust-random/getrandom/pull/347 + +## [0.2.8] - 2022-10-20 +### Changed +- The [Web Cryptography API] will now be preferred on `wasm32-unknown-unknown` + when using the `"js"` feature, even on Node.js [#284] [#295] + +### Added +- Added benchmarks to track buffer initialization cost [#272] + +### Fixed +- Use `$crate` in `register_custom_getrandom!` [#270] + +### Documentation +- Add information about enabling `"js"` feature [#280] +- Fix link to `wasm-bindgen` [#278] +- Document the varied implementations for underlying randomness sources [#276] + +[Web Cryptography API]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API +[#284]: https://github.com/rust-random/getrandom/pull/284 +[#295]: https://github.com/rust-random/getrandom/pull/295 +[#272]: https://github.com/rust-random/getrandom/pull/272 +[#270]: https://github.com/rust-random/getrandom/pull/270 +[#280]: https://github.com/rust-random/getrandom/pull/280 +[#278]: https://github.com/rust-random/getrandom/pull/278 +[#276]: https://github.com/rust-random/getrandom/pull/276 + +## [0.2.7] - 2022-06-14 +### Changed +- Update `wasi` dependency to `0.11` [#253] + +### Fixed +- Use `AtomicPtr` instead of `AtomicUsize` for Strict Provenance compatibility. [#263] + +### Documentation +- Add comments explaining use of fallback mechanisms [#257] [#260] + +[#263]: https://github.com/rust-random/getrandom/pull/263 +[#260]: https://github.com/rust-random/getrandom/pull/260 +[#253]: https://github.com/rust-random/getrandom/pull/253 +[#257]: https://github.com/rust-random/getrandom/pull/257 + +## [0.2.6] - 2022-03-28 +### Added +- Nintendo 3DS (`armv6k-nintendo-3ds`) support [#248] + +### Changed +- Retry `open` when interrupted [#252] + +[#248]: https://github.com/rust-random/getrandom/pull/248 +[#252]: https://github.com/rust-random/getrandom/pull/252 + +## [0.2.5] - 2022-02-22 +### Added +- ESP-IDF targets (`*‑espidf`) support [#245] + +### Fixed +- Webpack warning caused by dynamic require [#234] +- Error checking on iOS for `SecRandomCopyBytes` [#244] + +[#234]: https://github.com/rust-random/getrandom/pull/234 +[#244]: https://github.com/rust-random/getrandom/pull/244 +[#245]: https://github.com/rust-random/getrandom/pull/245 + +## [0.2.4] - 2021-12-13 +### Changed +- Use explicit imports in the `js` backend [#220] +- Use `/dev/urandom` on Redox instead of `rand:` [#222] +- Use `NonZeroU32::new_unchecked` to convert wasi error [#233] + +### Added +- SOLID targets (`*-kmc-solid_*`) support [#235] +- Limited Hermit (`x86_64-unknown-hermit`) support [#236] + +[#220]: https://github.com/rust-random/getrandom/pull/220 +[#222]: https://github.com/rust-random/getrandom/pull/222 +[#233]: https://github.com/rust-random/getrandom/pull/233 +[#235]: https://github.com/rust-random/getrandom/pull/235 +[#236]: https://github.com/rust-random/getrandom/pull/236 + +## [0.2.3] - 2021-04-10 +### Changed +- Replace build.rs with link attributes. [#205] +- Add support for getrandom syscall on DragonFly BSD. [#210] +- Improve Node.js detection. [#215] + +[#205]: https://github.com/rust-random/getrandom/pull/205 +[#210]: https://github.com/rust-random/getrandom/pull/210 +[#215]: https://github.com/rust-random/getrandom/pull/215 + +## [0.2.2] - 2021-01-19 +### Changed +- Forward `rustc-dep-of-std` to dependencies. [#198] +- Highlight feature-dependent functionality in documentation using the `doc_cfg` feature. [#200] + +[#198]: https://github.com/rust-random/getrandom/pull/198 +[#200]: https://github.com/rust-random/getrandom/pull/200 + +## [0.2.1] - 2021-01-03 +### Changed +- Update `cfg-if` to v1.0. [#166] +- Update `wasi` to v0.10. [#167] + +### Fixed +- Multithreaded WASM support. [#165] + +### Removed +- Windows XP support. [#177] +- Direct `stdweb` support. [#178] +- CloudABI support. [#184] + +[#165]: https://github.com/rust-random/getrandom/pull/165 +[#166]: https://github.com/rust-random/getrandom/pull/166 +[#167]: https://github.com/rust-random/getrandom/pull/167 +[#177]: https://github.com/rust-random/getrandom/pull/177 +[#178]: https://github.com/rust-random/getrandom/pull/178 +[#184]: https://github.com/rust-random/getrandom/pull/184 + +## [0.2.0] - 2020-09-10 +### Features for using getrandom on unsupported targets + +The following (off by default) Cargo features have been added: +- `"rdrand"` - use the RDRAND instruction on `no_std` `x86`/`x86_64` targets [#133] +- `"js"` - use JavaScript calls on `wasm32-unknown-unknown` [#149] + - Replaces the `stdweb` and `wasm-bindgen` features (which are removed) +- `"custom"` - allows a user to specify a custom implementation [#109] + +### Breaking Changes +- Unsupported targets no longer compile [#107] +- Change/Add `Error` constants [#120] +- Only impl `std` traits when the `"std"` Cargo feature is specified [#106] +- Remove official support for Hermit, L4Re, and UEFI [#133] +- Remove optional `"log"` dependency [#131] +- Update minimum supported Linux kernel to 2.6.32 [#153] +- Update MSRV to 1.34 [#159] + +[#106]: https://github.com/rust-random/getrandom/pull/106 +[#107]: https://github.com/rust-random/getrandom/pull/107 +[#109]: https://github.com/rust-random/getrandom/pull/109 +[#120]: https://github.com/rust-random/getrandom/pull/120 +[#131]: https://github.com/rust-random/getrandom/pull/131 +[#133]: https://github.com/rust-random/getrandom/pull/133 +[#149]: https://github.com/rust-random/getrandom/pull/149 +[#153]: https://github.com/rust-random/getrandom/pull/153 +[#159]: https://github.com/rust-random/getrandom/pull/159 + +## [0.1.16] - 2020-12-31 +### Changed +- Update `cfg-if` to v1.0. [#173] +- Implement `std::error::Error` for the `Error` type on additional targets. [#169] + +### Fixed +- Multithreaded WASM support. [#171] + +[#173]: https://github.com/rust-random/getrandom/pull/173 +[#171]: https://github.com/rust-random/getrandom/pull/171 +[#169]: https://github.com/rust-random/getrandom/pull/169 + +## [0.1.15] - 2020-09-10 +### Changed +- Added support for Internet Explorer 11 [#139] +- Fix Webpack require warning with `wasm-bindgen` [#137] + +[#137]: https://github.com/rust-random/getrandom/pull/137 +[#139]: https://github.com/rust-random/getrandom/pull/139 + +## [0.1.14] - 2020-01-07 +### Changed +- Remove use of spin-locks in the `use_file` module. [#125] +- Update `wasi` to v0.9. [#126] +- Do not read errno value on DragonFlyBSD to fix compilation failure. [#129] + +[#125]: https://github.com/rust-random/getrandom/pull/125 +[#126]: https://github.com/rust-random/getrandom/pull/126 +[#129]: https://github.com/rust-random/getrandom/pull/129 + +## [0.1.13] - 2019-08-25 +### Added +- VxWorks targets support. [#86] + +### Changed +- If zero-length slice is passed to the `getrandom` function, always return +`Ok(())` immediately without doing any calls to the underlying operating +system. [#104] +- Use the `kern.arandom` sysctl on NetBSD. [#115] + +### Fixed +- Bump `cfg-if` minimum version from 0.1.0 to 0.1.2. [#112] +- Typos and bad doc links. [#117] + +[#86]: https://github.com/rust-random/getrandom/pull/86 +[#104]: https://github.com/rust-random/getrandom/pull/104 +[#112]: https://github.com/rust-random/getrandom/pull/112 +[#115]: https://github.com/rust-random/getrandom/pull/115 +[#117]: https://github.com/rust-random/getrandom/pull/117 + +## [0.1.12] - 2019-08-18 +### Changed +- Update wasi dependency from v0.5 to v0.7. [#100] + +[#100]: https://github.com/rust-random/getrandom/pull/100 + +## [0.1.11] - 2019-08-25 +### Fixed +- Implement `std`-dependent traits for selected targets even if `std` +feature is disabled. (backward compatibility with v0.1.8) [#96] + +[#96]: https://github.com/rust-random/getrandom/pull/96 + +## [0.1.10] - 2019-08-18 [YANKED] +### Changed +- Use the dummy implementation on `wasm32-unknown-unknown` even with the +disabled `dummy` feature. [#90] + +### Fixed +- Fix CSP error for `wasm-bindgen`. [#92] + +[#90]: https://github.com/rust-random/getrandom/pull/90 +[#92]: https://github.com/rust-random/getrandom/pull/92 + +## [0.1.9] - 2019-08-14 [YANKED] +### Changed +- Remove `std` dependency for opening and reading files. [#58] +- Use `wasi` instead of `libc` on WASI target. [#64] +- By default emit a compile-time error when built for an unsupported target. +This behaviour can be disabled by using the `dummy` feature. [#71] + +### Added +- Add support for UWP targets. [#69] +- Add unstable `rustc-dep-of-std` feature. [#78] + +[#58]: https://github.com/rust-random/getrandom/pull/58 +[#64]: https://github.com/rust-random/getrandom/pull/64 +[#69]: https://github.com/rust-random/getrandom/pull/69 +[#71]: https://github.com/rust-random/getrandom/pull/71 +[#78]: https://github.com/rust-random/getrandom/pull/78 + +## [0.1.8] - 2019-07-29 +### Changed +- Explicitly specify types to arguments of 'libc::syscall'. [#74] + +[#74]: https://github.com/rust-random/getrandom/pull/74 + +## [0.1.7] - 2019-07-29 +### Added +- Support for hermit and l4re. [#61] +- `Error::raw_os_error` method, `Error::INTERNAL_START` and +`Error::CUSTOM_START` constants. Use `libc` for retrieving OS error descriptions. [#54] + +### Changed +- Remove `lazy_static` dependency and use custom structures for lock-free +initialization. [#51] [#52] +- Try `getrandom()` first on FreeBSD. [#57] + +### Removed +- Bitrig support. [#56] + +### Deprecated +- `Error::UNKNOWN`, `Error::UNAVAILABLE`. [#54] + +[#51]: https://github.com/rust-random/getrandom/pull/51 +[#52]: https://github.com/rust-random/getrandom/pull/52 +[#54]: https://github.com/rust-random/getrandom/pull/54 +[#56]: https://github.com/rust-random/getrandom/pull/56 +[#57]: https://github.com/rust-random/getrandom/pull/57 +[#61]: https://github.com/rust-random/getrandom/pull/61 + +## [0.1.6] - 2019-06-30 +### Changed +- Minor change of RDRAND AMD bug handling. [#48] + +[#48]: https://github.com/rust-random/getrandom/pull/48 + +## [0.1.5] - 2019-06-29 +### Fixed +- Use shared `File` instead of shared file descriptor. [#44] +- Workaround for RDRAND hardware bug present on some AMD CPUs. [#43] + +### Changed +- Try `getentropy` and then fallback to `/dev/random` on macOS. [#38] + +[#38]: https://github.com/rust-random/getrandom/issues/38 +[#43]: https://github.com/rust-random/getrandom/pull/43 +[#44]: https://github.com/rust-random/getrandom/issues/44 + +## [0.1.4] - 2019-06-28 +### Added +- Add support for `x86_64-unknown-uefi` target by using RDRAND with CPUID +feature detection. [#30] + +### Fixed +- Fix long buffer issues on Windows and Linux. [#31] [#32] +- Check `EPERM` in addition to `ENOSYS` on Linux. [#37] + +### Changed +- Improve efficiency by sharing file descriptor across threads. [#13] +- Remove `cloudabi`, `winapi`, and `fuchsia-cprng` dependencies. [#40] +- Improve RDRAND implementation. [#24] +- Don't block during syscall detection on Linux. [#26] +- Increase consistency with libc implementation on FreeBSD. [#36] +- Apply `rustfmt`. [#39] + +[#30]: https://github.com/rust-random/getrandom/pull/30 +[#13]: https://github.com/rust-random/getrandom/issues/13 +[#40]: https://github.com/rust-random/getrandom/pull/40 +[#26]: https://github.com/rust-random/getrandom/pull/26 +[#24]: https://github.com/rust-random/getrandom/pull/24 +[#39]: https://github.com/rust-random/getrandom/pull/39 +[#36]: https://github.com/rust-random/getrandom/pull/36 +[#31]: https://github.com/rust-random/getrandom/issues/31 +[#32]: https://github.com/rust-random/getrandom/issues/32 +[#37]: https://github.com/rust-random/getrandom/issues/37 + +## [0.1.3] - 2019-05-15 +- Update for `wasm32-unknown-wasi` being renamed to `wasm32-wasi`, and for + WASI being categorized as an OS. + +## [0.1.2] - 2019-04-06 +- Add support for `wasm32-unknown-wasi` target. + +## [0.1.1] - 2019-04-05 +- Enable std functionality for CloudABI by default. + +## [0.1.0] - 2019-03-23 +Publish initial implementation. + +## [0.0.0] - 2019-01-19 +Publish an empty template library. + +[0.3.4]: https://github.com/rust-random/getrandom/compare/v0.3.3...v0.3.4 +[0.3.3]: https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3 +[0.3.2]: https://github.com/rust-random/getrandom/compare/v0.3.1...v0.3.2 +[0.3.1]: https://github.com/rust-random/getrandom/compare/v0.3.0...v0.3.1 +[0.3.0]: https://github.com/rust-random/getrandom/compare/v0.2.15...v0.3.0 +[0.2.16]: https://github.com/rust-random/getrandom/compare/v0.2.15...v0.2.16 +[0.2.15]: https://github.com/rust-random/getrandom/compare/v0.2.14...v0.2.15 +[0.2.14]: https://github.com/rust-random/getrandom/compare/v0.2.13...v0.2.14 +[0.2.13]: https://github.com/rust-random/getrandom/compare/v0.2.12...v0.2.13 +[0.2.12]: https://github.com/rust-random/getrandom/compare/v0.2.11...v0.2.12 +[0.2.11]: https://github.com/rust-random/getrandom/compare/v0.2.10...v0.2.11 +[0.2.10]: https://github.com/rust-random/getrandom/compare/v0.2.9...v0.2.10 +[0.2.9]: https://github.com/rust-random/getrandom/compare/v0.2.8...v0.2.9 +[0.2.8]: https://github.com/rust-random/getrandom/compare/v0.2.7...v0.2.8 +[0.2.7]: https://github.com/rust-random/getrandom/compare/v0.2.6...v0.2.7 +[0.2.6]: https://github.com/rust-random/getrandom/compare/v0.2.5...v0.2.6 +[0.2.5]: https://github.com/rust-random/getrandom/compare/v0.2.4...v0.2.5 +[0.2.4]: https://github.com/rust-random/getrandom/compare/v0.2.3...v0.2.4 +[0.2.3]: https://github.com/rust-random/getrandom/compare/v0.2.2...v0.2.3 +[0.2.2]: https://github.com/rust-random/getrandom/compare/v0.2.1...v0.2.2 +[0.2.1]: https://github.com/rust-random/getrandom/compare/v0.2.0...v0.2.1 +[0.2.0]: https://github.com/rust-random/getrandom/compare/v0.1.16...v0.2.0 +[0.1.16]: https://github.com/rust-random/getrandom/compare/v0.1.15...v0.1.16 +[0.1.15]: https://github.com/rust-random/getrandom/compare/v0.1.14...v0.1.15 +[0.1.14]: https://github.com/rust-random/getrandom/compare/v0.1.13...v0.1.14 +[0.1.13]: https://github.com/rust-random/getrandom/compare/v0.1.12...v0.1.13 +[0.1.12]: https://github.com/rust-random/getrandom/compare/v0.1.11...v0.1.12 +[0.1.11]: https://github.com/rust-random/getrandom/compare/v0.1.10...v0.1.11 +[0.1.10]: https://github.com/rust-random/getrandom/compare/v0.1.9...v0.1.10 +[0.1.9]: https://github.com/rust-random/getrandom/compare/v0.1.8...v0.1.9 +[0.1.8]: https://github.com/rust-random/getrandom/compare/v0.1.7...v0.1.8 +[0.1.7]: https://github.com/rust-random/getrandom/compare/v0.1.6...v0.1.7 +[0.1.6]: https://github.com/rust-random/getrandom/compare/v0.1.5...v0.1.6 +[0.1.5]: https://github.com/rust-random/getrandom/compare/v0.1.4...v0.1.5 +[0.1.4]: https://github.com/rust-random/getrandom/compare/v0.1.3...v0.1.4 +[0.1.3]: https://github.com/rust-random/getrandom/compare/v0.1.2...v0.1.3 +[0.1.2]: https://github.com/rust-random/getrandom/compare/v0.1.1...v0.1.2 +[0.1.1]: https://github.com/rust-random/getrandom/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/rust-random/getrandom/compare/v0.0.0...v0.1.0 +[0.0.0]: https://github.com/rust-random/getrandom/releases/tag/v0.0.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,292 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cc" +version = "1.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "getrandom" +version = "0.3.4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", + "wasm-bindgen-test", +] + +[[package]] +name = "js-sys" +version = "0.3.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b221ff421256839509adbb55998214a70d829d3a28c69b4a6672e9d2a42f67" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aee0a0f5343de9221a0d233b04520ed8dc2e6728dce180b1dcd9288ec9d9fa3c" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a369369e4360c2884c3168d22bded735c43cccae97bbc147586d4b480edd138d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,133 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63" +name = "getrandom" +version = "0.3.4" +authors = ["The Rand Project Developers"] +build = "build.rs" +exclude = [".*"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A small cross-platform library for retrieving random data from system source" +documentation = "https://docs.rs/getrandom" +readme = "README.md" +categories = [ + "os", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/getrandom" + +[package.metadata.docs.rs] +features = ["std"] + +[package.metadata.cross.target.x86_64-unknown-netbsd] +pre-build = [ + "mkdir -p /tmp/netbsd", + "curl -fO https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/amd64/binary/sets/base.tar.xz", + "tar -C /tmp/netbsd -xJf base.tar.xz", + "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", + "rm base.tar.xz", + "rm -rf /tmp/netbsd", +] + +[features] +std = [] +wasm_js = [ + "dep:wasm-bindgen", + "dep:js-sys", +] + +[lib] +name = "getrandom" +path = "src/lib.rs" + +[[test]] +name = "mod" +path = "tests/mod.rs" + +[[bench]] +name = "buffer" +path = "benches/buffer.rs" + +[dependencies.cfg-if] +version = "1" + +[target.'cfg(all(any(target_os = "linux", target_os = "android"), not(any(all(target_os = "linux", target_env = ""), getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dependencies.wasm-bindgen] +version = "0.2.98" +optional = true +default-features = false + +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies.wasm-bindgen-test] +version = "0.3" + +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), target_feature = "atomics"))'.dependencies.js-sys] +version = "0.3.77" +optional = true +default-features = false + +[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))'.dependencies.wasip2] +version = "1" +default-features = false + +[target.'cfg(all(target_os = "uefi", getrandom_backend = "efi_rng"))'.dependencies.r-efi] +version = "5.1" +default-features = false + +[target.'cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", target_os = "illumos", target_os = "cygwin", all(target_os = "horizon", target_arch = "arm")))'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(any(target_os = "haiku", target_os = "redox", target_os = "nto", target_os = "aix"))'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(any(target_os = "ios", target_os = "visionos", target_os = "watchos", target_os = "tvos"))'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(any(target_os = "macos", target_os = "openbsd", target_os = "vita", target_os = "emscripten"))'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(target_os = "netbsd")'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(target_os = "solaris")'.dependencies.libc] +version = "0.2.154" +default-features = false + +[target.'cfg(target_os = "vxworks")'.dependencies.libc] +version = "0.2.154" +default-features = false + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + 'cfg(getrandom_backend, values("custom", "efi_rng", "rdrand", "rndr", "linux_getrandom", "linux_raw", "wasm_js", "windows_legacy", "unsupported"))', + "cfg(getrandom_msan)", + "cfg(getrandom_test_linux_fallback)", + "cfg(getrandom_test_linux_without_fallback)", + "cfg(getrandom_test_netbsd_fallback)", + 'cfg(target_os, values("cygwin"))', +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +[package] +name = "getrandom" +version = "0.3.4" +edition = "2021" +rust-version = "1.63" # Sync tests.yml and README.md. +authors = ["The Rand Project Developers"] +license = "MIT OR Apache-2.0" +description = "A small cross-platform library for retrieving random data from system source" +documentation = "https://docs.rs/getrandom" +repository = "https://github.com/rust-random/getrandom" +categories = ["os", "no-std"] +exclude = [".*"] + +[features] +# Implement std::error::Error for getrandom::Error and +# use std to retrieve OS error descriptions +std = [] + +# Optional backend: wasm_js +# This flag enables the wasm_js backend and uses it by default on wasm32 where +# the target_os is unknown. The getrandom_backend cfg may override this. +# WARNING: It is highly recommended to enable this feature only for binary crates and tests, +# i.e. avoid unconditionally enabling it in library crates. +wasm_js = ["dep:wasm-bindgen", "dep:js-sys"] + +[dependencies] +cfg-if = "1" + +# getrandom / linux_android_with_fallback +[target.'cfg(all(any(target_os = "linux", target_os = "android"), not(any(all(target_os = "linux", target_env = ""), getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# apple-other +[target.'cfg(any(target_os = "ios", target_os = "visionos", target_os = "watchos", target_os = "tvos"))'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# efi_rng +[target.'cfg(all(target_os = "uefi", getrandom_backend = "efi_rng"))'.dependencies] +r-efi = { version = "5.1", default-features = false } + +# getentropy +[target.'cfg(any(target_os = "macos", target_os = "openbsd", target_os = "vita", target_os = "emscripten"))'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# getrandom +[target.'cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", target_os = "illumos", target_os = "cygwin", all(target_os = "horizon", target_arch = "arm")))'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# netbsd +[target.'cfg(target_os = "netbsd")'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# solaris +[target.'cfg(target_os = "solaris")'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# use_file +[target.'cfg(any(target_os = "haiku", target_os = "redox", target_os = "nto", target_os = "aix"))'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# vxworks +[target.'cfg(target_os = "vxworks")'.dependencies] +libc = { version = "0.2.154", default-features = false } + +# wasi_p2 +[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))'.dependencies] +wasip2 = { version = "1", default-features = false } + +# wasm_js +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dependencies] +wasm-bindgen = { version = "0.2.98", default-features = false, optional = true } +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), target_feature = "atomics"))'.dependencies] +js-sys = { version = "0.3.77", default-features = false, optional = true } +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies] +wasm-bindgen-test = "0.3" + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + 'cfg(getrandom_backend, values("custom", "efi_rng", "rdrand", "rndr", "linux_getrandom", "linux_raw", "wasm_js", "windows_legacy", "unsupported"))', + 'cfg(getrandom_msan)', + 'cfg(getrandom_test_linux_fallback)', + 'cfg(getrandom_test_linux_without_fallback)', + 'cfg(getrandom_test_netbsd_fallback)', + 'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this. +] + +[package.metadata.docs.rs] +features = ["std"] + +# workaround for https://github.com/cross-rs/cross/issues/1345 +[package.metadata.cross.target.x86_64-unknown-netbsd] +pre-build = [ + "mkdir -p /tmp/netbsd", + "curl -fO https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/amd64/binary/sets/base.tar.xz", + "tar -C /tmp/netbsd -xJf base.tar.xz", + "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", + "rm base.tar.xz", + "rm -rf /tmp/netbsd", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright (c) 2018-2025 The rust-random Project Developers +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/README.md clamav-1.4.6+dfsg/.cargo/vendor/getrandom/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,386 @@ +# getrandom: system's random number generator + +[![Build Status]][GitHub Actions] +[![Crate]][crates.io] +[![Documentation]][docs.rs] +[![Dependency Status]][deps.rs] +[![Downloads]][crates.io] +[![License]][LICENSE-MIT] + +`getrandom` is a Rust library for retrieving random data from (operating) system sources. + +It is assumed that the system always provides high-quality, cryptographically secure random +data, ideally backed by hardware entropy sources. This crate derives its name from +the Linux `getrandom` syscall but is cross-platform, roughly supporting the same set +of platforms as Rust's `std` library. + +This is a low-level API. Most users should prefer using a higher-level random-number +library like [`rand`]. + +[`rand`]: https://crates.io/crates/rand + +## Usage + +Add the `getrandom` dependency to your `Cargo.toml` file: + +```toml +[dependencies] +getrandom = "0.3" +``` + +Then invoke the `fill` function on a byte buffer to fill it with random data: + +```rust +fn get_random_u128() -> Result { + let mut buf = [0u8; 16]; + getrandom::fill(&mut buf)?; + Ok(u128::from_ne_bytes(buf)) +} +``` + +## Supported targets + +| Target | Target Triple | Implementation +| ------------------ | ------------------ | -------------- +| Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` +| Windows 10+ | `*‑windows‑*` | [`ProcessPrng`] on Rust 1.78+, [`RtlGenRandom`] otherwise +| Windows 7, 8 | `*-win7‑windows‑*` | [`RtlGenRandom`] +| macOS | `*‑apple‑darwin` | [`getentropy`][3] +| iOS, tvOS, watchOS | `*‑apple‑{ios,tvos,watchos}` | [`CCRandomGenerateBytes`] +| FreeBSD | `*‑freebsd` | [`getrandom`][5] +| OpenBSD | `*‑openbsd` | [`getentropy`][7] +| NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8] +| Dragonfly BSD | `*‑dragonfly` | [`getrandom`][9] +| Solaris | `*‑solaris` | [`getrandom`][11] with `GRND_RANDOM` +| illumos | `*‑illumos` | [`getrandom`][12] +| Fuchsia OS | `*‑fuchsia` | [`cprng_draw`] +| Redox | `*‑redox` | `/dev/urandom` +| Haiku | `*‑haiku` | `/dev/urandom` (identical to `/dev/random`) +| Hermit | `*-hermit` | [`sys_read_entropy`] +| Hurd | `*-hurd-*` | [`getrandom`][17] +| SGX | `x86_64‑*‑sgx` | [`RDRAND`] +| VxWorks | `*‑wrs‑vxworks‑*` | `randABytes` after checking entropy pool initialization with `randSecure` +| Emscripten | `*‑emscripten` | [`getentropy`][13] +| WASI 0.1 | `wasm32‑wasip1` | [`random_get`] +| WASI 0.2 | `wasm32‑wasip2` | [`get-random-u64`] +| SOLID | `*-kmc-solid_*` | `SOLID_RNG_SampleRandomBytes` +| Nintendo 3DS | `*-nintendo-3ds` | [`getrandom`][18] +| ESP-IDF | `*‑espidf` | [`esp_fill_random`] WARNING: see "Early Boot" section below +| PS Vita | `*-vita-*` | [`getentropy`][19] +| QNX Neutrino | `*‑nto-qnx*` | [`/dev/urandom`][14] (identical to `/dev/random`) +| AIX | `*-ibm-aix` | [`/dev/urandom`][15] +| Cygwin | `*-cygwin` | [`getrandom`][20] (based on [`RtlGenRandom`]) + +Pull Requests that add support for new targets to `getrandom` are always welcome. + +### Opt-in backends + +`getrandom` also provides optional (opt-in) backends, which allow users to customize the source +of randomness based on their specific needs: + +| Backend name | Target | Target Triple | Implementation +| ----------------- | -------------------- | ------------------------ | -------------- +| `linux_getrandom` | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call (without `/dev/urandom` fallback). Bumps minimum supported Linux kernel version to 3.17 and Android API level to 23 (Marshmallow). +| `linux_raw` | Linux, Android | `*‑linux‑*` | Same as `linux_getrandom`, but uses raw `asm!`-based syscalls instead of `libc`. +| `rdrand` | x86, x86-64 | `x86_64-*`, `i686-*` | [`RDRAND`] instruction +| `rndr` | AArch64 | `aarch64-*` | [`RNDR`] register +| `wasm_js` | Web Browser, Node.js | `wasm32‑unknown‑unknown`, `wasm32v1-none` | [`Crypto.getRandomValues`]. Enabled by the `wasm_js` feature ([see below](#webassembly-support)). +| `efi_rng` | UEFI | `*-unknown‑uefi` | [`EFI_RNG_PROTOCOL`] with `EFI_RNG_ALGORITHM_RAW` (requires `std` and Nightly compiler) +| `windows_legacy` | Windows | `*-windows-*` | [`RtlGenRandom`] +| `custom` | All targets | `*` | User-provided custom implementation (see [custom backend]) +| `unsupported` | All targets | `*` | Always returns `Err(Error::UNSUPPORTED)` (see [unsupported backend]) + +Opt-in backends can be enabled using the `getrandom_backend` configuration flag. +The flag can be set either by specifying the `rustflags` field in [`.cargo/config.toml`]: +```toml +# It's recommended to set the flag on a per-target basis: +[target.wasm32-unknown-unknown] +rustflags = ['--cfg', 'getrandom_backend="wasm_js"'] +``` + +Or by using the `RUSTFLAGS` environment variable: + +```sh +RUSTFLAGS='--cfg getrandom_backend="linux_getrandom"' cargo build +``` + +Enabling an opt-in backend will replace the backend used by default. Doing this for +an incorrect target (e.g. using `linux_getrandom` while compiling for a Windows target) +will result in a compilation error. Be extremely careful while using opt-in backends, +as incorrect configuration may result in vulnerable applications or applications +that always panic. + +Note that using an opt-in backend in a library (e.g. for tests or benchmarks) +WILL NOT have any effect on its downstream users. + +[`.cargo/config.toml`]: https://doc.rust-lang.org/cargo/reference/config.html + +### Raw Linux syscall support + +Currently the `linux_raw` backend supports only targets with stabilized `asm!` macro, +i.e. `arm`, `aarch64`, `loongarch64`, `riscv32`, `riscv64`, `s390x`, `x86`, and `x86_64`. + +Note that the raw syscall backend may be slower than backends based on `libc::getrandom`, +e.g. it does not implement vDSO optimizations and on `x86` it uses the infamously slow +`int 0x80` instruction to perform syscall. + +### WebAssembly support + +This crate fully supports the [WASI] and [Emscripten] targets. However, +the `wasm32-unknown-unknown` target (i.e. the target used by `wasm-pack`) +is not automatically supported since, from the target name alone, we cannot deduce +which JavaScript interface should be used (or if JavaScript is available at all). + +We do not include support for this target in the default configuration because +our JS backend (supporting web browsers, web workers and Node.js v19 or later) +requires [`wasm-bindgen`], **bloating `Cargo.lock`** and +**potentially breaking builds** on non-web WASM platforms. + +To enable `getrandom`'s functionality on `wasm32-unknown-unknown` using the Web +Crypto methods [described above][opt-in] via [`wasm-bindgen`], enable the +`wasm_js` feature flag. Setting `RUSTFLAGS='--cfg getrandom_backend="wasm_js"'` +is allowed but is no longer required and does nothing (it was required in a +prior version of this crate). + +WARNING: enabling the `wasm_js` feature will bloat `Cargo.lock` on all platforms +(where [`wasm-bindgen`] is not an existing dependency) and is known to cause +build issues on some non-web WASM platforms, even when a different backend is +selected via `getrandom_backend`. + +### Custom backend + +If this crate does not support your target out of the box or you have to use +a non-default entropy source, then you can provide a custom implementation. +You need to enable the custom backend as described in the +[opt-in backends][opt-in] section. + +Next, you need to define an `extern` function with the following signature: + +```rust +use getrandom::Error; + +#[no_mangle] +unsafe extern "Rust" fn __getrandom_v03_custom( + dest: *mut u8, + len: usize, +) -> Result<(), Error> { + todo!() +} +``` + +This function should, ideally, be defined in the root crate of your project, +e.g. in your `main.rs`. This function MUST be defined only once for your +project, i.e. upstream library crates SHOULD NOT define it outside of +tests and benchmarks. Improper configuration of this backend may result +in linking errors. + +The function accepts a pointer to a buffer that should be filled with random +data and its length in bytes. Note that the buffer MAY be uninitialized. +On success, the function should return `Ok(())` and fully fill the input buffer; +otherwise, it should return an error value. + +While wrapping functions which work with byte slices you should fully initialize +the buffer before passing it to the function: +```rust +use getrandom::Error; + +fn my_entropy_source(buf: &mut [u8]) -> Result<(), getrandom::Error> { + // ... + Ok(()) +} + +#[no_mangle] +unsafe extern "Rust" fn __getrandom_v03_custom( + dest: *mut u8, + len: usize, +) -> Result<(), Error> { + let buf = unsafe { + // fill the buffer with zeros + core::ptr::write_bytes(dest, 0, len); + // create mutable byte slice + core::slice::from_raw_parts_mut(dest, len) + }; + my_entropy_source(buf) +} +``` + +### Unsupported backend + +In some rare scenarios, you might be compiling this crate for an unsupported +target (e.g. `wasm32-unknown-unknown`), but this crate's functionality +is not actually used by your code. If you are confident that `getrandom` is +not used in your project, but it gets pulled nevertheless by one of your +dependencies, then you can enable the `unsupported` backend, which always +returns `Err(Error::UNSUPPORTED)`. + +### Platform Support + +This crate generally supports the same operating system and platform versions +that the Rust standard library does. Additional targets may be supported using +the opt-in custom backend. + +This means that as Rust drops support for old versions of operating systems +(such as old Linux kernel versions, Android API levels, etc.) in stable releases, +`getrandom` may create new patch releases that remove support for +outdated platform versions. + +### `/dev/urandom` fallback on Linux and Android + +On Linux targets, the `/dev/urandom` fallback is present only if either `target_env` +is `musl`, or `target_arch` is one of the following: `aarch64`, `arm`, `powerpc`, +`powerpc64`, `s390x`, `x86`, `x86_64`. Other supported targets [require][platform-support] +kernel versions that support the `getrandom` system call, so the fallback is not needed. + +On Android targets the fallback is present only for the following `target_arch`es: +`aarch64`, `arm`, `x86`, `x86_64`. Other `target_arch`es (e.g. RISC-V) require +sufficiently high API levels. + +The fallback can be disabled by enabling the `linux_getrandom` opt-in backend. +Note that doing so will bump minimum supported Linux kernel version to 3.17 +and Android API level to 23 (Marshmallow). + +### Early boot + +Sometimes, early in the boot process, the OS has not collected enough +entropy to securely seed its RNG. This is especially common on virtual +machines, where standard "random" events are hard to come by. + +Some operating system interfaces always block until the RNG is securely +seeded. This can take anywhere from a few seconds to more than a minute. +A few (Linux, NetBSD and Solaris) offer a choice between blocking and +getting an error; in these cases, we always choose to block. + +On Linux (when the `getrandom` system call is not available), reading from +`/dev/urandom` never blocks, even when the OS hasn't collected enough +entropy yet. To avoid returning low-entropy bytes, we first poll +`/dev/random` and only switch to `/dev/urandom` once this has succeeded. + +On OpenBSD, this kind of entropy accounting isn't available, and on +NetBSD, blocking on it is discouraged. On these platforms, nonblocking +interfaces are used, even when reliable entropy may not be available. +On the platforms where it is used, the reliability of entropy accounting +itself isn't free from controversy. This library provides randomness +sourced according to the platform's best practices, but each platform has +its own limits on the grade of randomness it can promise in environments +with few sources of entropy. + +On ESP-IDF, if `esp_fill_random` is used before enabling WiFi, BT, or the +voltage noise entropy source (SAR ADC), the Hardware RNG will only be seeded +via RC_FAST_CLK. This can occur during early boot unless +`bootloader_random_enable()` is called. For more information see the +[ESP-IDF RNG Docs][esp-idf-rng] or the +[RNG section of the ESP32 Technical Reference Manual][esp-trng-docs]. + +## Error handling + +We always prioritize failure over returning known insecure "random" bytes. +Generally, on supported platforms, failure is highly unlikely, though not +impossible. If an error does occur, it is likely that it will occur +on every call to `getrandom`. Therefore, after the first successful call, +one can be reasonably confident that no errors will occur. + +## Panic handling + +We strive to eliminate all potential panics from our backend implementations. +In other words, when compiled with optimizations enabled, the generated +binary code for `getrandom` functions should not contain any panic branches. +Even if the platform misbehaves and returns an unexpected result, +our code should correctly handle it and return an error, e.g. +[`Error::UNEXPECTED`]. + +## Sanitizer support + +If your code uses [`fill_uninit`] and you enable +[MemorySanitizer](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#memorysanitizer) +(i.e. `-Zsanitizer=memory`), we will automatically handle unpoisoning +of the destination buffer filled by `fill_uninit`. + +You can run sanitizer tests for your crate dependent on `getrandom` like this: +```sh +RUSTFLAGS="-Zsanitizer=memory" cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu +``` + +## Minimum Supported Rust Version + +This crate requires Rust 1.63 or later. + +## License + +The `getrandom` library is distributed under either of + + * [Apache License, Version 2.0][LICENSE-APACHE] + * [MIT license][LICENSE-MIT] + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[GitHub Actions]: https://github.com/rust-random/getrandom/actions?query=branch:master +[Build Status]: https://github.com/rust-random/getrandom/actions/workflows/tests.yml/badge.svg?branch=master +[crates.io]: https://crates.io/crates/getrandom +[Crate]: https://img.shields.io/crates/v/getrandom +[docs.rs]: https://docs.rs/getrandom +[Documentation]: https://docs.rs/getrandom/badge.svg +[deps.rs]: https://deps.rs/repo/github/rust-random/getrandom +[Dependency Status]: https://deps.rs/repo/github/rust-random/getrandom/status.svg +[Downloads]: https://img.shields.io/crates/d/getrandom +[License]: https://img.shields.io/crates/l/getrandom + +[//]: # (supported targets) + +[1]: https://manned.org/getrandom.2 +[2]: https://manned.org/urandom.4 +[3]: https://www.unix.com/man-page/mojave/2/getentropy/ +[4]: https://www.unix.com/man-page/mojave/4/urandom/ +[5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable +[7]: https://man.openbsd.org/getentropy.2 +[8]: https://man.netbsd.org/sysctl.7 +[9]: https://leaf.dragonflybsd.org/cgi/web-man?command=getrandom +[11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html +[12]: https://illumos.org/man/2/getrandom +[13]: https://github.com/emscripten-core/emscripten/pull/12240 +[14]: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/r/random.html +[15]: https://www.ibm.com/docs/en/aix/7.3?topic=files-random-urandom-devices +[16]: https://man.netbsd.org/getrandom.2 +[17]: https://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getrandom +[18]: https://github.com/rust3ds/shim-3ds/commit/b01d2568836dea2a65d05d662f8e5f805c64389d +[19]: https://github.com/vitasdk/newlib/blob/2d869fe47aaf02b8e52d04e9a2b79d5b210fd016/newlib/libc/sys/vita/getentropy.c +[20]: https://github.com/cygwin/cygwin/blob/main/winsup/cygwin/libc/getentropy.cc + +[`ProcessPrng`]: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng +[`RtlGenRandom`]: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom +[`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues +[`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide +[`RNDR`]: https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers/RNDR--Random-Number +[`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html +[`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw +[`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html#functions +[esp-idf-rng]: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html +[esp-trng-docs]: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#rng +[`EFI_RNG_PROTOCOL`]: https://uefi.org/specs/UEFI/2.10/37_Secure_Technologies.html#efi-rng-protocol +[`random_get`]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno +[`get-random-u64`]: https://github.com/WebAssembly/WASI/blob/v0.2.1/wasip2/random/random.wit#L23-L28 +[configuration flags]: #configuration-flags +[custom backend]: #custom-backend +[unsupported backend]: #unsupported-backend +[`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen +[`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html +[`sys_read_entropy`]: https://github.com/hermit-os/kernel/blob/315f58ff5efc81d9bf0618af85a59963ff55f8b1/src/syscalls/entropy.rs#L47-L55 +[platform-support]: https://doc.rust-lang.org/stable/rustc/platform-support.html +[WASI]: https://github.com/WebAssembly/WASI +[Emscripten]: https://emscripten.org +[opt-in]: #opt-in-backends + +[//]: # (licenses) + +[LICENSE-APACHE]: https://github.com/rust-random/getrandom/blob/master/LICENSE-APACHE +[LICENSE-MIT]: https://github.com/rust-random/getrandom/blob/master/LICENSE-MIT + +[`Error::UNEXPECTED`]: https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.UNEXPECTED +[`fill_uninit`]: https://docs.rs/getrandom/latest/getrandom/fn.fill_uninit.html diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/SECURITY.md clamav-1.4.6+dfsg/.cargo/vendor/getrandom/SECURITY.md --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/SECURITY.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/SECURITY.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Security updates are applied only to the latest release. + +## Reporting a Vulnerability + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/rust-random/getrandom/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/benches/buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/benches/buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/benches/buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/benches/buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +#![feature(test, maybe_uninit_uninit_array_transpose)] +extern crate test; + +use std::{ + mem::{size_of, MaybeUninit}, + slice, +}; + +// Call getrandom on a zero-initialized stack buffer +#[inline(always)] +fn bench_fill() { + let mut buf = [0u8; N]; + getrandom::fill(&mut buf).unwrap(); + test::black_box(&buf[..]); +} + +// Call fill_uninit on an uninitialized stack buffer +#[inline(always)] +fn bench_fill_uninit() { + let mut uninit = [MaybeUninit::uninit(); N]; + let buf: &[u8] = getrandom::fill_uninit(&mut uninit).unwrap(); + test::black_box(buf); +} + +#[bench] +pub fn bench_u32(b: &mut test::Bencher) { + #[inline(never)] + fn inner() -> u32 { + getrandom::u32().unwrap() + } + b.bytes = 4; + b.iter(inner); +} +#[bench] +pub fn bench_u32_via_fill(b: &mut test::Bencher) { + #[inline(never)] + fn inner() -> u32 { + let mut res = MaybeUninit::::uninit(); + let dst: &mut [MaybeUninit] = + unsafe { slice::from_raw_parts_mut(res.as_mut_ptr().cast(), size_of::()) }; + getrandom::fill_uninit(dst).unwrap(); + unsafe { res.assume_init() } + } + b.bytes = 4; + b.iter(inner); +} + +#[bench] +pub fn bench_u64(b: &mut test::Bencher) { + #[inline(never)] + fn inner() -> u64 { + getrandom::u64().unwrap() + } + b.bytes = 8; + b.iter(inner); +} + +#[bench] +pub fn bench_u64_via_fill(b: &mut test::Bencher) { + #[inline(never)] + fn inner() -> u64 { + let mut res = MaybeUninit::::uninit(); + let dst: &mut [MaybeUninit] = + unsafe { slice::from_raw_parts_mut(res.as_mut_ptr().cast(), size_of::()) }; + getrandom::fill_uninit(dst).unwrap(); + unsafe { res.assume_init() } + } + b.bytes = 8; + b.iter(inner); +} + +// We benchmark using #[inline(never)] "inner" functions for two reasons: +// - Avoiding inlining reduces a source of variance when running benchmarks. +// - It is _much_ easier to get the assembly or IR for the inner loop. +// +// For example, using cargo-show-asm (https://github.com/pacak/cargo-show-asm), +// we can get the assembly for a particular benchmark's inner loop by running: +// cargo asm --bench buffer --release buffer::p384::bench_getrandom::inner +macro_rules! bench { + ( $name:ident, $size:expr ) => { + pub mod $name { + #[bench] + pub fn bench_fill(b: &mut test::Bencher) { + #[inline(never)] + fn inner() { + super::bench_fill::<{ $size }>() + } + + b.bytes = $size as u64; + b.iter(inner); + } + #[bench] + pub fn bench_fill_uninit(b: &mut test::Bencher) { + #[inline(never)] + fn inner() { + super::bench_fill_uninit::<{ $size }>() + } + + b.bytes = $size as u64; + b.iter(inner); + } + } + }; +} + +// 16 bytes (128 bits) is the size of an 128-bit AES key/nonce. +bench!(aes128, 128 / 8); + +// 32 bytes (256 bits) is the seed sized used for rand::thread_rng +// and the `random` value in a ClientHello/ServerHello for TLS. +// This is also the size of a 256-bit AES/HMAC/P-256/Curve25519 key +// and/or nonce. +bench!(p256, 256 / 8); + +// A P-384/HMAC-384 key and/or nonce. +bench!(p384, 384 / 8); + +// Initializing larger buffers is not the primary use case of this library, as +// this should normally be done by a userspace CSPRNG. However, we have a test +// here to see the effects of a lower (amortized) syscall overhead. +bench!(page, 4096); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/build.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +use std::{env, ffi::OsString, process::Command}; + +/// Tries to get the minor version of the Rust compiler in use. +/// If it fails for any reason, returns `None`. +/// +/// Based on the `rustc_version` crate. +fn rustc_minor_version() -> Option { + let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); + let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER").filter(|w| !w.is_empty()) { + let mut cmd = Command::new(wrapper); + cmd.arg(rustc); + cmd + } else { + Command::new(rustc) + }; + + let out = cmd.arg("-vV").output().ok()?; + + if !out.status.success() { + return None; + } + + let stdout = std::str::from_utf8(&out.stdout).ok()?; + + // Assumes that the first line contains "rustc 1.xx.0-channel (abcdef 2025-01-01)" + // where "xx" is the minor version which we want to extract + let mut lines = stdout.lines(); + let first_line = lines.next()?; + let minor_ver_str = first_line.split('.').nth(1)?; + minor_ver_str.parse().ok() +} + +fn main() { + // Automatically detect cfg(sanitize = "memory") even if cfg(sanitize) isn't + // supported. Build scripts get cfg() info, even if the cfg is unstable. + println!("cargo:rerun-if-changed=build.rs"); + let sanitizers = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); + if sanitizers.contains("memory") { + println!("cargo:rustc-cfg=getrandom_msan"); + } + + // Use `RtlGenRandom` on older compiler versions since win7 targets + // TODO(MSRV 1.78): Remove this check + let target_family = env::var_os("CARGO_CFG_TARGET_FAMILY").and_then(|f| f.into_string().ok()); + if target_family.as_deref() == Some("windows") { + /// Minor version of the Rust compiler in which win7 targets were inroduced + const WIN7_INTRODUCED_MINOR_VER: u64 = 78; + + match rustc_minor_version() { + Some(minor_ver) if minor_ver < WIN7_INTRODUCED_MINOR_VER => { + println!("cargo:rustc-cfg=getrandom_backend=\"windows_legacy\""); + } + None => println!("cargo:warning=Couldn't detect minor version of the Rust compiler"), + _ => {} + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/apple_other.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/apple_other.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/apple_other.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/apple_other.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable. +use crate::Error; +use core::{ffi::c_void, mem::MaybeUninit}; + +pub use crate::util::{inner_u32, inner_u64}; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let dst_ptr = dest.as_mut_ptr().cast::(); + let ret = unsafe { libc::CCRandomGenerateBytes(dst_ptr, dest.len()) }; + if ret == libc::kCCSuccess { + Ok(()) + } else { + Err(Error::IOS_RANDOM_GEN) + } +} + +impl Error { + /// Call to `CCRandomGenerateBytes` failed. + pub(crate) const IOS_RANDOM_GEN: Error = Self::new_internal(10); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/custom.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/custom.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/custom.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/custom.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +//! An implementation which calls out to an externally defined function. +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + extern "Rust" { + fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), Error>; + } + unsafe { __getrandom_v03_custom(dest.as_mut_ptr().cast(), dest.len()) } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/efi_rng.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/efi_rng.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/efi_rng.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/efi_rng.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +//! Implementation for UEFI using EFI_RNG_PROTOCOL +use crate::Error; +use core::{ + mem::MaybeUninit, + ptr::{self, null_mut, NonNull}, + sync::atomic::{AtomicPtr, Ordering::Relaxed}, +}; +use r_efi::{ + efi::{BootServices, Handle}, + protocols::rng, +}; + +extern crate std; + +pub use crate::util::{inner_u32, inner_u64}; + +#[cfg(not(target_os = "uefi"))] +compile_error!("`efi_rng` backend can be enabled only for UEFI targets!"); + +static RNG_PROTOCOL: AtomicPtr = AtomicPtr::new(null_mut()); + +#[cold] +#[inline(never)] +fn init() -> Result, Error> { + const HANDLE_SIZE: usize = size_of::(); + + let boot_services = std::os::uefi::env::boot_services() + .ok_or(Error::BOOT_SERVICES_UNAVAILABLE)? + .cast::(); + + let mut handles = [ptr::null_mut(); 16]; + // `locate_handle` operates with length in bytes + let mut buf_size = handles.len() * HANDLE_SIZE; + let mut guid = rng::PROTOCOL_GUID; + let ret = unsafe { + ((*boot_services.as_ptr()).locate_handle)( + r_efi::efi::BY_PROTOCOL, + &mut guid, + null_mut(), + &mut buf_size, + handles.as_mut_ptr(), + ) + }; + + if ret.is_error() { + return Err(Error::from_uefi_code(ret.as_usize())); + } + + let handles_len = buf_size / HANDLE_SIZE; + let handles = handles.get(..handles_len).ok_or(Error::UNEXPECTED)?; + + let system_handle = std::os::uefi::env::image_handle(); + for &handle in handles { + let mut protocol: MaybeUninit<*mut rng::Protocol> = MaybeUninit::uninit(); + + let mut protocol_guid = rng::PROTOCOL_GUID; + let ret = unsafe { + ((*boot_services.as_ptr()).open_protocol)( + handle, + &mut protocol_guid, + protocol.as_mut_ptr().cast(), + system_handle.as_ptr(), + ptr::null_mut(), + r_efi::system::OPEN_PROTOCOL_GET_PROTOCOL, + ) + }; + + let protocol = if ret.is_error() { + continue; + } else { + let protocol = unsafe { protocol.assume_init() }; + NonNull::new(protocol).ok_or(Error::UNEXPECTED)? + }; + + // Try to use the acquired protocol handle + let mut buf = [0u8; 8]; + let mut alg_guid = rng::ALGORITHM_RAW; + let ret = unsafe { + ((*protocol.as_ptr()).get_rng)( + protocol.as_ptr(), + &mut alg_guid, + buf.len(), + buf.as_mut_ptr(), + ) + }; + + if ret.is_error() { + continue; + } + + RNG_PROTOCOL.store(protocol.as_ptr(), Relaxed); + return Ok(protocol); + } + Err(Error::NO_RNG_HANDLE) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let protocol = match NonNull::new(RNG_PROTOCOL.load(Relaxed)) { + Some(p) => p, + None => init()?, + }; + + let mut alg_guid = rng::ALGORITHM_RAW; + let ret = unsafe { + ((*protocol.as_ptr()).get_rng)( + protocol.as_ptr(), + &mut alg_guid, + dest.len(), + dest.as_mut_ptr().cast::(), + ) + }; + + if ret.is_error() { + Err(Error::from_uefi_code(ret.as_usize())) + } else { + Ok(()) + } +} + +impl Error { + pub(crate) const BOOT_SERVICES_UNAVAILABLE: Error = Self::new_internal(10); + pub(crate) const NO_RNG_HANDLE: Error = Self::new_internal(11); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/esp_idf.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/esp_idf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/esp_idf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/esp_idf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +//! Implementation for ESP-IDF +use crate::Error; +use core::{ffi::c_void, mem::MaybeUninit}; + +pub use crate::util::{inner_u32, inner_u64}; + +extern "C" { + fn esp_fill_random(buf: *mut c_void, len: usize) -> u32; +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Not that NOT enabling WiFi, BT, or the voltage noise entropy source (via `bootloader_random_enable`) + // will cause ESP-IDF to return pseudo-random numbers based on the voltage noise entropy, after the initial boot process: + // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html + // + // However tracking if some of these entropy sources is enabled is way too difficult to implement here + unsafe { esp_fill_random(dest.as_mut_ptr().cast(), dest.len()) }; + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/fuchsia.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/fuchsia.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/fuchsia.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/fuchsia.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +//! Implementation for Fuchsia Zircon +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +#[link(name = "zircon")] +extern "C" { + fn zx_cprng_draw(buffer: *mut u8, length: usize); +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + unsafe { zx_cprng_draw(dest.as_mut_ptr().cast::(), dest.len()) } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/getentropy.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getentropy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/getentropy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getentropy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +//! Implementation using getentropy(2) +//! +//! Available since: +//! - macOS 10.12 +//! - OpenBSD 5.6 +//! - Emscripten 2.0.5 +//! - vita newlib since Dec 2021 +//! +//! For these targets, we use getentropy(2) because getrandom(2) doesn't exist. +use crate::Error; +use core::{ffi::c_void, mem::MaybeUninit}; + +pub use crate::util::{inner_u32, inner_u64}; + +#[path = "../util_libc.rs"] +mod util_libc; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + for chunk in dest.chunks_mut(256) { + let ret = unsafe { libc::getentropy(chunk.as_mut_ptr().cast::(), chunk.len()) }; + if ret != 0 { + return Err(util_libc::last_os_error()); + } + } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/getrandom.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getrandom.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/getrandom.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/getrandom.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +//! Implementation using getrandom(2). +//! +//! Available since: +//! - Linux Kernel 3.17, Glibc 2.25, Musl 1.1.20 +//! - Android API level 23 (Marshmallow) +//! - NetBSD 10.0 +//! - FreeBSD 12.0 +//! - illumos since Dec 2018 +//! - DragonFly 5.7 +//! - Hurd Glibc 2.31 +//! - shim-3ds since Feb 2022 +//! +//! For these platforms, we always use the default pool and never set the +//! GRND_RANDOM flag to use the /dev/random pool. On Linux/Android/Hurd, using +//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does +//! nothing. On illumos, the default pool is used to implement getentropy(2), +//! so we assume it is acceptable here. +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +#[path = "../util_libc.rs"] +mod util_libc; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + util_libc::sys_fill_exact(dest, |buf| unsafe { + let ret = libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0); + + #[cfg(any(target_os = "android", target_os = "linux"))] + #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. + unsafe { + super::sanitizer::unpoison_linux_getrandom_result(buf, ret); + } + + ret + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/hermit.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/hermit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/hermit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/hermit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +//! Implementation for Hermit +use crate::Error; +use core::mem::MaybeUninit; + +extern "C" { + fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize; + // Note that `sys_secure_rand32/64` are implemented using `sys_read_entropy`: + // https://github.com/hermit-os/kernel/blob/430da84/src/syscalls/entropy.rs#L62-L104 + // But this may change in future and can depend on compilation target, + // so to future-proof we use these "syscalls". + fn sys_secure_rand32(value: *mut u32) -> i32; + fn sys_secure_rand64(value: *mut u64) -> i32; +} + +#[inline] +pub fn inner_u32() -> Result { + let mut res = MaybeUninit::uninit(); + let ret = unsafe { sys_secure_rand32(res.as_mut_ptr()) }; + match ret { + 0 => Ok(unsafe { res.assume_init() }), + -1 => Err(Error::UNSUPPORTED), + _ => Err(Error::UNEXPECTED), + } +} + +#[inline] +pub fn inner_u64() -> Result { + let mut res = MaybeUninit::uninit(); + let ret = unsafe { sys_secure_rand64(res.as_mut_ptr()) }; + match ret { + 0 => Ok(unsafe { res.assume_init() }), + -1 => Err(Error::UNSUPPORTED), + _ => Err(Error::UNEXPECTED), + } +} + +#[inline] +pub fn fill_inner(mut dest: &mut [MaybeUninit]) -> Result<(), Error> { + while !dest.is_empty() { + let res = unsafe { sys_read_entropy(dest.as_mut_ptr().cast::(), dest.len(), 0) }; + match res { + res if res > 0 => { + let len = usize::try_from(res).map_err(|_| Error::UNEXPECTED)?; + dest = dest.get_mut(len..).ok_or(Error::UNEXPECTED)?; + } + code => { + let code = i32::try_from(code).map_err(|_| Error::UNEXPECTED)?; + return Err(Error::from_neg_error_code(code)); + } + } + } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/linux_android_with_fallback.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_android_with_fallback.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/linux_android_with_fallback.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_android_with_fallback.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +//! Implementation for Linux / Android with `/dev/urandom` fallback +use super::{sanitizer, use_file}; +use crate::Error; +use core::{ + ffi::c_void, + mem::{transmute, MaybeUninit}, + ptr::NonNull, + sync::atomic::{AtomicPtr, Ordering}, +}; +use use_file::util_libc; + +pub use crate::util::{inner_u32, inner_u64}; + +type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t; + +/// Sentinel value which indicates that `libc::getrandom` either not available, +/// or not supported by kernel. +const NOT_AVAILABLE: NonNull = unsafe { NonNull::new_unchecked(usize::MAX as *mut c_void) }; + +static GETRANDOM_FN: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +#[cold] +#[inline(never)] +fn init() -> NonNull { + // Use static linking to `libc::getrandom` on MUSL targets and `dlsym` everywhere else + #[cfg(not(target_env = "musl"))] + let raw_ptr = { + static NAME: &[u8] = b"getrandom\0"; + let name_ptr = NAME.as_ptr().cast::(); + unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) } + }; + #[cfg(target_env = "musl")] + let raw_ptr = { + let fptr: GetRandomFn = libc::getrandom; + unsafe { transmute::(fptr) } + }; + + let res_ptr = match NonNull::new(raw_ptr) { + Some(fptr) => { + let getrandom_fn = unsafe { transmute::, GetRandomFn>(fptr) }; + let dangling_ptr = NonNull::dangling().as_ptr(); + // Check that `getrandom` syscall is supported by kernel + let res = unsafe { getrandom_fn(dangling_ptr, 0, 0) }; + if cfg!(getrandom_test_linux_fallback) { + NOT_AVAILABLE + } else if res.is_negative() { + match util_libc::last_os_error().raw_os_error() { + Some(libc::ENOSYS) => NOT_AVAILABLE, // No kernel support + // The fallback on EPERM is intentionally not done on Android since this workaround + // seems to be needed only for specific Linux-based products that aren't based + // on Android. See https://github.com/rust-random/getrandom/issues/229. + #[cfg(target_os = "linux")] + Some(libc::EPERM) => NOT_AVAILABLE, // Blocked by seccomp + _ => fptr, + } + } else { + fptr + } + } + None => NOT_AVAILABLE, + }; + + #[cfg(getrandom_test_linux_without_fallback)] + if res_ptr == NOT_AVAILABLE { + panic!("Fallback is triggered with enabled `getrandom_test_linux_without_fallback`") + } + + GETRANDOM_FN.store(res_ptr.as_ptr(), Ordering::Release); + res_ptr +} + +// Prevent inlining of the fallback implementation +#[inline(never)] +fn use_file_fallback(dest: &mut [MaybeUninit]) -> Result<(), Error> { + use_file::fill_inner(dest) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Despite being only a single atomic variable, we still cannot always use + // Ordering::Relaxed, as we need to make sure a successful call to `init` + // is "ordered before" any data read through the returned pointer (which + // occurs when the function is called). Our implementation mirrors that of + // the one in libstd, meaning that the use of non-Relaxed operations is + // probably unnecessary. + let raw_ptr = GETRANDOM_FN.load(Ordering::Acquire); + let fptr = match NonNull::new(raw_ptr) { + Some(p) => p, + None => init(), + }; + + if fptr == NOT_AVAILABLE { + use_file_fallback(dest) + } else { + // note: `transmute` is currently the only way to convert a pointer into a function reference + let getrandom_fn = unsafe { transmute::, GetRandomFn>(fptr) }; + util_libc::sys_fill_exact(dest, |buf| unsafe { + let ret = getrandom_fn(buf.as_mut_ptr().cast(), buf.len(), 0); + sanitizer::unpoison_linux_getrandom_result(buf, ret); + ret + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/linux_raw.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_raw.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/linux_raw.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/linux_raw.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,143 @@ +//! Implementation for Linux / Android using `asm!`-based syscalls. +use super::sanitizer; +pub use crate::util::{inner_u32, inner_u64}; +use crate::{Error, MaybeUninit}; + +#[cfg(not(any(target_os = "android", target_os = "linux")))] +compile_error!("`linux_raw` backend can be enabled only for Linux/Android targets!"); + +#[allow(non_upper_case_globals)] +unsafe fn getrandom_syscall(buf: *mut u8, buflen: usize, flags: u32) -> isize { + let r0; + + // Based on `rustix` and `linux-raw-sys` code. + cfg_if! { + if #[cfg(target_arch = "arm")] { + // TODO(MSRV-1.78): Also check `target_abi = "eabi"`. + // In thumb-mode, r7 is the frame pointer and is not permitted to be used in + // an inline asm operand, so we have to use a different register and copy it + // into r7 inside the inline asm. + // Theoretically, we could detect thumb mode in the build script, but several + // register moves are cheap enough compared to the syscall cost, so we do not + // bother with it. + core::arch::asm!( + "mov {tmp}, r7", + // TODO(MSRV-1.82): replace with `nr = const __NR_getrandom,` + "mov r7, #384", + "svc 0", + "mov r7, {tmp}", + tmp = out(reg) _, + inlateout("r0") buf => r0, + in("r1") buflen, + in("r2") flags, + options(nostack, preserves_flags) + ); + } else if #[cfg(target_arch = "aarch64")] { + // TODO(MSRV-1.78): Also check `any(target_abi = "", target_abi = "ilp32")` above. + // According to the ILP32 patch for the kernel that hasn't yet + // been merged into the mainline, "AARCH64/ILP32 ABI uses standard + // syscall table [...] with the exceptions listed below," where + // getrandom is not mentioned as an exception. + const __NR_getrandom: u32 = 278; + core::arch::asm!( + "svc 0", + in("x8") __NR_getrandom, + inlateout("x0") buf => r0, + in("x1") buflen, + in("x2") flags, + options(nostack, preserves_flags) + ); + } else if #[cfg(target_arch = "loongarch64")] { + // TODO(MSRV-1.78): Also check `any(target_abi = "", target_abi = "ilp32")` above. + const __NR_getrandom: u32 = 278; + core::arch::asm!( + "syscall 0", + in("$a7") __NR_getrandom, + inlateout("$a0") buf => r0, + in("$a1") buflen, + in("$a2") flags, + options(nostack, preserves_flags) + ); + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + const __NR_getrandom: u32 = 278; + core::arch::asm!( + "ecall", + in("a7") __NR_getrandom, + inlateout("a0") buf => r0, + in("a1") buflen, + in("a2") flags, + options(nostack, preserves_flags) + ); + } else if #[cfg(target_arch = "s390x")] { + const __NR_getrandom: u32 = 349; + core::arch::asm!( + "svc 0", + in("r1") __NR_getrandom, + inlateout("r2") buf => r0, + in("r3") buflen, + in("r4") flags, + options(nostack, preserves_flags) + ); + } else if #[cfg(target_arch = "x86")] { + const __NR_getrandom: u32 = 355; + // `int 0x80` is famously slow, but implementing vDSO is too complex + // and `sysenter`/`syscall` have their own portability issues, + // so we use the simple "legacy" way of doing syscalls. + core::arch::asm!( + "int $$0x80", + in("eax") __NR_getrandom, + in("ebx") buf, + in("ecx") buflen, + in("edx") flags, + lateout("eax") r0, + options(nostack, preserves_flags) + ); + } else if #[cfg(target_arch = "x86_64")] { + // TODO(MSRV-1.78): Add `any(target_abi = "", target_abi = "x32")` above. + const __X32_SYSCALL_BIT: u32 = 0x40000000; + const OFFSET: u32 = if cfg!(target_pointer_width = "32") { __X32_SYSCALL_BIT } else { 0 }; + const __NR_getrandom: u32 = OFFSET + 318; + + core::arch::asm!( + "syscall", + in("rax") __NR_getrandom, + in("rdi") buf, + in("rsi") buflen, + in("rdx") flags, + lateout("rax") r0, + lateout("rcx") _, + lateout("r11") _, + options(nostack, preserves_flags) + ); + } else { + compile_error!("`linux_raw` backend does not support this target arch"); + } + } + + r0 +} + +#[inline] +pub fn fill_inner(mut dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Value of this error code is stable across all target arches. + const EINTR: isize = -4; + + loop { + let ret = unsafe { getrandom_syscall(dest.as_mut_ptr().cast(), dest.len(), 0) }; + unsafe { sanitizer::unpoison_linux_getrandom_result(dest, ret) }; + match usize::try_from(ret) { + Ok(0) => return Err(Error::UNEXPECTED), + Ok(len) => { + dest = dest.get_mut(len..).ok_or(Error::UNEXPECTED)?; + if dest.is_empty() { + return Ok(()); + } + } + Err(_) if ret == EINTR => continue, + Err(_) => { + let code = i32::try_from(ret).map_err(|_| Error::UNEXPECTED)?; + return Err(Error::from_neg_error_code(code)); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/netbsd.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/netbsd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/netbsd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/netbsd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +//! Implementation for NetBSD +//! +//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we +//! implement our own weak linkage to it, and provide a fallback based on the +//! KERN_ARND sysctl. +use crate::Error; +use core::{ + cmp, + ffi::c_void, + mem::{self, MaybeUninit}, + ptr, + sync::atomic::{AtomicPtr, Ordering}, +}; + +pub use crate::util::{inner_u32, inner_u64}; + +#[path = "../util_libc.rs"] +mod util_libc; + +unsafe extern "C" fn polyfill_using_kern_arand( + buf: *mut c_void, + buflen: libc::size_t, + flags: libc::c_uint, +) -> libc::ssize_t { + debug_assert_eq!(flags, 0); + + const MIB_LEN: libc::c_uint = 2; + static MIB: [libc::c_int; MIB_LEN as usize] = [libc::CTL_KERN, libc::KERN_ARND]; + + // NetBSD will only return up to 256 bytes at a time, and + // older NetBSD kernels will fail on longer buffers. + let mut len = cmp::min(buflen, 256); + let ret = unsafe { libc::sysctl(MIB.as_ptr(), MIB_LEN, buf, &mut len, ptr::null(), 0) }; + + match ret { + 0 if len <= 256 => libc::ssize_t::try_from(len).expect("len is in the range of 0..=256"), + -1 => -1, + // Zero return result will be converted into `Error::UNEXPECTED` by `sys_fill_exact` + _ => 0, + } +} + +type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t; + +static GETRANDOM: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + +#[cold] +#[inline(never)] +fn init() -> *mut c_void { + static NAME: &[u8] = b"getrandom\0"; + let name_ptr = NAME.as_ptr().cast::(); + let mut ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) }; + if ptr.is_null() || cfg!(getrandom_test_netbsd_fallback) { + // Verify `polyfill_using_kern_arand` has the right signature. + const POLYFILL: GetRandomFn = polyfill_using_kern_arand; + ptr = POLYFILL as *mut c_void; + } + GETRANDOM.store(ptr, Ordering::Release); + ptr +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Despite being only a single atomic variable, we still cannot always use + // Ordering::Relaxed, as we need to make sure a successful call to `init` + // is "ordered before" any data read through the returned pointer (which + // occurs when the function is called). Our implementation mirrors that of + // the one in libstd, meaning that the use of non-Relaxed operations is + // probably unnecessary. + let mut fptr = GETRANDOM.load(Ordering::Acquire); + if fptr.is_null() { + fptr = init(); + } + let fptr = unsafe { mem::transmute::<*mut c_void, GetRandomFn>(fptr) }; + util_libc::sys_fill_exact(dest, |buf| unsafe { + fptr(buf.as_mut_ptr().cast::(), buf.len(), 0) + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/rdrand.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rdrand.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/rdrand.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rdrand.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,182 @@ +//! RDRAND backend for x86(-64) targets +use crate::{util::slice_as_uninit, Error}; +use core::mem::{size_of, MaybeUninit}; + +#[path = "../lazy.rs"] +mod lazy; + +#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] +compile_error!("`rdrand` backend can be enabled only for x86 and x86-64 targets!"); + +cfg_if! { + if #[cfg(target_arch = "x86_64")] { + use core::arch::x86_64 as arch; + use arch::_rdrand64_step as rdrand_step; + type Word = u64; + } else if #[cfg(target_arch = "x86")] { + use core::arch::x86 as arch; + use arch::_rdrand32_step as rdrand_step; + type Word = u32; + } +} + +static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new(); + +// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software +// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures +// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1. +const RETRY_LIMIT: usize = 10; + +#[target_feature(enable = "rdrand")] +unsafe fn rdrand() -> Option { + for _ in 0..RETRY_LIMIT { + let mut val = 0; + if rdrand_step(&mut val) == 1 { + return Some(val); + } + } + None +} + +// "rdrand" target feature requires "+rdrand" flag, see https://github.com/rust-lang/rust/issues/49653. +#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))] +compile_error!( + "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrand." +); + +// Run a small self-test to make sure we aren't repeating values +// Adapted from Linux's test in arch/x86/kernel/cpu/rdrand.c +// Fails with probability < 2^(-90) on 32-bit systems +#[target_feature(enable = "rdrand")] +unsafe fn self_test() -> bool { + // On AMD, RDRAND returns 0xFF...FF on failure, count it as a collision. + let mut prev = !0; // TODO(MSRV 1.43): Move to usize::MAX + let mut fails = 0; + for _ in 0..8 { + match rdrand() { + Some(val) if val == prev => fails += 1, + Some(val) => prev = val, + None => return false, + }; + } + fails <= 2 +} + +fn is_rdrand_good() -> bool { + #[cfg(not(target_feature = "rdrand"))] + { + // SAFETY: All Rust x86 targets are new enough to have CPUID, and we + // check that leaf 1 is supported before using it. + let cpuid0 = unsafe { arch::__cpuid(0) }; + if cpuid0.eax < 1 { + return false; + } + let cpuid1 = unsafe { arch::__cpuid(1) }; + + let vendor_id = [ + cpuid0.ebx.to_le_bytes(), + cpuid0.edx.to_le_bytes(), + cpuid0.ecx.to_le_bytes(), + ]; + if vendor_id == [*b"Auth", *b"enti", *b"cAMD"] { + let mut family = (cpuid1.eax >> 8) & 0xF; + if family == 0xF { + family += (cpuid1.eax >> 20) & 0xFF; + } + // AMD CPUs families before 17h (Zen) sometimes fail to set CF when + // RDRAND fails after suspend. Don't use RDRAND on those families. + // See https://bugzilla.redhat.com/show_bug.cgi?id=1150286 + if family < 0x17 { + return false; + } + } + + const RDRAND_FLAG: u32 = 1 << 30; + if cpuid1.ecx & RDRAND_FLAG == 0 { + return false; + } + } + + // SAFETY: We have already checked that rdrand is available. + unsafe { self_test() } +} + +// TODO: make this function safe when we have feature(target_feature_11) +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_exact(dest: &mut [MaybeUninit]) -> Option<()> { + // We use chunks_exact_mut instead of chunks_mut as it allows almost all + // calls to memcpy to be elided by the compiler. + let mut chunks = dest.chunks_exact_mut(size_of::()); + for chunk in chunks.by_ref() { + let src = rdrand()?.to_ne_bytes(); + chunk.copy_from_slice(slice_as_uninit(&src)); + } + + let tail = chunks.into_remainder(); + let n = tail.len(); + if n > 0 { + let src = rdrand()?.to_ne_bytes(); + tail.copy_from_slice(slice_as_uninit(&src[..n])); + } + Some(()) +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_u32() -> Option { + rdrand().map(crate::util::truncate) +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_u64() -> Option { + rdrand() +} + +#[cfg(target_arch = "x86")] +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_u32() -> Option { + rdrand() +} + +#[cfg(target_arch = "x86")] +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_u64() -> Option { + let a = rdrand()?; + let b = rdrand()?; + Some((u64::from(a) << 32) | u64::from(b)) +} + +#[inline] +pub fn inner_u32() -> Result { + if !RDRAND_GOOD.unsync_init(is_rdrand_good) { + return Err(Error::NO_RDRAND); + } + // SAFETY: After this point, we know rdrand is supported. + unsafe { rdrand_u32() }.ok_or(Error::FAILED_RDRAND) +} + +#[inline] +pub fn inner_u64() -> Result { + if !RDRAND_GOOD.unsync_init(is_rdrand_good) { + return Err(Error::NO_RDRAND); + } + // SAFETY: After this point, we know rdrand is supported. + unsafe { rdrand_u64() }.ok_or(Error::FAILED_RDRAND) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + if !RDRAND_GOOD.unsync_init(is_rdrand_good) { + return Err(Error::NO_RDRAND); + } + // SAFETY: After this point, we know rdrand is supported. + unsafe { rdrand_exact(dest) }.ok_or(Error::FAILED_RDRAND) +} + +impl Error { + /// RDRAND instruction failed due to a hardware issue. + pub(crate) const FAILED_RDRAND: Error = Self::new_internal(10); + /// RDRAND instruction unsupported on this target. + pub(crate) const NO_RDRAND: Error = Self::new_internal(11); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/rndr.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rndr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/rndr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/rndr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,145 @@ +//! RNDR register backend for aarch64 targets +//! +//! Arm Architecture Reference Manual for A-profile architecture: +//! ARM DDI 0487K.a, ID032224, D23.2.147 RNDR, Random Number +use crate::{ + util::{slice_as_uninit, truncate}, + Error, +}; +use core::arch::asm; +use core::mem::{size_of, MaybeUninit}; + +#[cfg(not(target_arch = "aarch64"))] +compile_error!("the `rndr` backend can be enabled only for AArch64 targets!"); + +const RETRY_LIMIT: usize = 5; + +/// Read a random number from the aarch64 RNDR register +/// +/// Callers must ensure that FEAT_RNG is available on the system +/// The function assumes that the RNDR register is available +/// If it fails to read a random number, it will retry up to 5 times +/// After 5 failed reads the function will return `None` +#[target_feature(enable = "rand")] +unsafe fn rndr() -> Option { + for _ in 0..RETRY_LIMIT { + let mut x: u64; + let mut nzcv: u64; + + // AArch64 RNDR register is accessible by s3_3_c2_c4_0 + asm!( + "mrs {x}, RNDR", + "mrs {nzcv}, NZCV", + x = out(reg) x, + nzcv = out(reg) nzcv, + ); + + // If the hardware returns a genuine random number, PSTATE.NZCV is set to 0b0000 + if nzcv == 0 { + return Some(x); + } + } + + None +} + +#[target_feature(enable = "rand")] +unsafe fn rndr_fill(dest: &mut [MaybeUninit]) -> Option<()> { + let mut chunks = dest.chunks_exact_mut(size_of::()); + for chunk in chunks.by_ref() { + let src = rndr()?.to_ne_bytes(); + chunk.copy_from_slice(slice_as_uninit(&src)); + } + + let tail = chunks.into_remainder(); + let n = tail.len(); + if n > 0 { + let src = rndr()?.to_ne_bytes(); + tail.copy_from_slice(slice_as_uninit(&src[..n])); + } + Some(()) +} + +#[cfg(target_feature = "rand")] +fn is_rndr_available() -> bool { + true +} + +#[cfg(not(target_feature = "rand"))] +fn is_rndr_available() -> bool { + #[path = "../lazy.rs"] + mod lazy; + static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new(); + + cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + extern crate std; + RNDR_GOOD.unsync_init(|| std::arch::is_aarch64_feature_detected!("rand")) + } else if #[cfg(target_os = "linux")] { + /// Check whether FEAT_RNG is available on the system + /// + /// Requires the caller either be running in EL1 or be on a system supporting MRS + /// emulation. Due to the above, the implementation is currently restricted to Linux. + /// + /// Relying on runtime detection bumps minimum supported Linux kernel version to 4.11. + fn mrs_check() -> bool { + let mut id_aa64isar0: u64; + + // If FEAT_RNG is implemented, ID_AA64ISAR0_EL1.RNDR (bits 60-63) are 0b0001 + // This is okay to do from EL0 in Linux because Linux will emulate MRS as per + // https://docs.kernel.org/arch/arm64/cpu-feature-registers.html + unsafe { + asm!( + "mrs {id}, ID_AA64ISAR0_EL1", + id = out(reg) id_aa64isar0, + ); + } + + (id_aa64isar0 >> 60) & 0xf >= 1 + } + + RNDR_GOOD.unsync_init(mrs_check) + } else { + compile_error!( + "RNDR `no_std` runtime detection is currently supported only on Linux targets. \ + Either enable the `std` crate feature, or `rand` target feature at compile time." + ); + } + } +} + +#[inline] +pub fn inner_u32() -> Result { + if !is_rndr_available() { + return Err(Error::RNDR_NOT_AVAILABLE); + } + // SAFETY: after this point, we know the `rand` target feature is enabled + let res = unsafe { rndr() }; + res.map(truncate).ok_or(Error::RNDR_FAILURE) +} + +#[inline] +pub fn inner_u64() -> Result { + if !is_rndr_available() { + return Err(Error::RNDR_NOT_AVAILABLE); + } + // SAFETY: after this point, we know the `rand` target feature is enabled + let res = unsafe { rndr() }; + res.ok_or(Error::RNDR_FAILURE) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + if !is_rndr_available() { + return Err(Error::RNDR_NOT_AVAILABLE); + } + // SAFETY: after this point, we know the `rand` target feature is enabled + unsafe { rndr_fill(dest).ok_or(Error::RNDR_FAILURE) } +} + +impl Error { + /// RNDR register read failed due to a hardware issue. + pub(crate) const RNDR_FAILURE: Error = Self::new_internal(10); + /// RNDR register is not supported on this target. + pub(crate) const RNDR_NOT_AVAILABLE: Error = Self::new_internal(11); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/sanitizer.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/sanitizer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/sanitizer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/sanitizer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +use core::mem::MaybeUninit; + +/// Unpoisons `buf` if MSAN support is enabled. +/// +/// Most backends do not need to unpoison their output. Rust language- and +/// library- provided functionality unpoisons automatically. Similarly, libc +/// either natively supports MSAN and/or MSAN hooks libc-provided functions +/// to unpoison outputs on success. Only when all of these things are +/// bypassed do we need to do it ourselves. +/// +/// The call to unpoison should be done as close to the write as possible. +/// For example, if the backend partially fills the output buffer in chunks, +/// each chunk should be unpoisoned individually. This way, the correctness of +/// the chunking logic can be validated (in part) using MSAN. +pub unsafe fn unpoison(buf: &mut [MaybeUninit]) { + cfg_if! { + if #[cfg(getrandom_msan)] { + extern "C" { + fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize); + } + let a = buf.as_mut_ptr().cast(); + let size = buf.len(); + #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. + unsafe { + __msan_unpoison(a, size); + } + } else { + let _ = buf; + } + } +} + +/// Interprets the result of the `getrandom` syscall of Linux, unpoisoning any +/// written part of `buf`. +/// +/// `buf` must be the output buffer that was originally passed to the `getrandom` +/// syscall. +/// +/// `ret` must be the result returned by `getrandom`. If `ret` is negative or +/// larger than the length of `buf` then nothing is done. +/// +/// Memory Sanitizer only intercepts `getrandom` on this condition (from its +/// source code): +/// ```c +/// #define SANITIZER_INTERCEPT_GETRANDOM \ +/// ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD || SI_SOLARIS) +/// ``` +/// So, effectively, we have to assume that it is never intercepted on Linux. +#[cfg(any(target_os = "android", target_os = "linux"))] +pub unsafe fn unpoison_linux_getrandom_result(buf: &mut [MaybeUninit], ret: isize) { + if let Ok(bytes_written) = usize::try_from(ret) { + if let Some(written) = buf.get_mut(..bytes_written) { + #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. + unsafe { + unpoison(written) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/solaris.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solaris.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/solaris.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solaris.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +//! Solaris implementation using getrandom(2). +//! +//! While getrandom(2) has been available since Solaris 11.3, it has a few +//! quirks not present on other OSes. First, on Solaris 11.3, calls will always +//! fail if bufsz > 1024. Second, it will always either fail or completely fill +//! the buffer (returning bufsz). Third, error is indicated by returning 0, +//! rather than by returning -1. Finally, "if GRND_RANDOM is not specified +//! then getrandom(2) is always a non blocking call". This _might_ imply that +//! in early-boot scenarios with low entropy, getrandom(2) will not properly +//! block. To be safe, we set GRND_RANDOM, mirroring the man page examples. +//! +//! For more information, see the man page linked in lib.rs and this blog post: +//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2 +//! which also explains why this crate should not use getentropy(2). +use crate::Error; +use core::{ffi::c_void, mem::MaybeUninit}; + +pub use crate::util::{inner_u32, inner_u64}; + +#[path = "../util_libc.rs"] +mod util_libc; + +const MAX_BYTES: usize = 1024; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + for chunk in dest.chunks_mut(MAX_BYTES) { + let ptr = chunk.as_mut_ptr().cast::(); + let ret = unsafe { libc::getrandom(ptr, chunk.len(), libc::GRND_RANDOM) }; + // In case the man page has a typo, we also check for negative ret. + // If getrandom(2) succeeds, it should have completely filled chunk. + match usize::try_from(ret) { + // Good. Keep going. + Ok(ret) if ret == chunk.len() => {} + // The syscall failed. + Ok(0) => return Err(util_libc::last_os_error()), + // All other cases should be impossible. + _ => return Err(Error::UNEXPECTED), + } + } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/solid.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solid.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/solid.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/solid.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +//! Implementation for SOLID +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +extern "C" { + pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> i32; +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr().cast::(), dest.len()) }; + if ret >= 0 { + Ok(()) + } else { + Err(Error::from_neg_error_code(ret)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/unsupported.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/unsupported.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/unsupported.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/unsupported.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +//! Implementation that errors at runtime. +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +pub fn fill_inner(_dest: &mut [MaybeUninit]) -> Result<(), Error> { + Err(Error::UNSUPPORTED) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/use_file.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/use_file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/use_file.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/use_file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,234 @@ +//! Implementations that just need to read from a file +use crate::Error; +use core::{ + ffi::c_void, + mem::MaybeUninit, + sync::atomic::{AtomicI32, Ordering}, +}; + +#[cfg(not(any(target_os = "android", target_os = "linux")))] +pub use crate::util::{inner_u32, inner_u64}; + +#[path = "../util_libc.rs"] +pub(super) mod util_libc; + +/// For all platforms, we use `/dev/urandom` rather than `/dev/random`. +/// For more information see the linked man pages in lib.rs. +/// - On Linux, "/dev/urandom is preferred and sufficient in all use cases". +/// - On Redox, only /dev/urandom is provided. +/// - On AIX, /dev/urandom will "provide cryptographically secure output". +/// - On Haiku and QNX Neutrino they are identical. +const FILE_PATH: &[u8] = b"/dev/urandom\0"; + +// File descriptor is a "nonnegative integer", so we can safely use negative sentinel values. +const FD_UNINIT: libc::c_int = -1; +const FD_ONGOING_INIT: libc::c_int = -2; + +// In theory `libc::c_int` could be something other than `i32`, but for the +// targets we currently support that use `use_file`, it is always `i32`. +// If/when we add support for a target where that isn't the case, we may +// need to use a different atomic type or make other accommodations. The +// compiler will let us know if/when that is the case, because the +// `FD.store(fd)` would fail to compile. +// +// The opening of the file, by libc/libstd/etc. may write some unknown +// state into in-process memory. (Such state may include some sanitizer +// bookkeeping, or we might be operating in a unikernal-like environment +// where all the "kernel" file descriptor bookkeeping is done in our +// process.) `get_fd_locked` stores into FD using `Ordering::Release` to +// ensure any such state is synchronized. `get_fd` loads from `FD` with +// `Ordering::Acquire` to synchronize with it. +static FD: AtomicI32 = AtomicI32::new(FD_UNINIT); + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let mut fd = FD.load(Ordering::Acquire); + if fd == FD_UNINIT || fd == FD_ONGOING_INIT { + fd = open_or_wait()?; + } + util_libc::sys_fill_exact(dest, |buf| unsafe { + libc::read(fd, buf.as_mut_ptr().cast::(), buf.len()) + }) +} + +/// Open a file in read-only mode. +/// +/// # Panics +/// If `path` does not contain any zeros. +// TODO: Move `path` to `CStr` and use `CStr::from_bytes_until_nul` (MSRV 1.69) +// or C-string literals (MSRV 1.77) for statics +fn open_readonly(path: &[u8]) -> Result { + assert!(path.contains(&0)); + loop { + let fd = unsafe { + libc::open( + path.as_ptr().cast::(), + libc::O_RDONLY | libc::O_CLOEXEC, + ) + }; + if fd >= 0 { + return Ok(fd); + } + let err = util_libc::last_os_error(); + // We should try again if open() was interrupted. + if err.raw_os_error() != Some(libc::EINTR) { + return Err(err); + } + } +} + +#[cold] +#[inline(never)] +fn open_or_wait() -> Result { + loop { + match FD.load(Ordering::Acquire) { + FD_UNINIT => { + let res = FD.compare_exchange_weak( + FD_UNINIT, + FD_ONGOING_INIT, + Ordering::AcqRel, + Ordering::Relaxed, + ); + if res.is_ok() { + break; + } + } + FD_ONGOING_INIT => sync::wait(), + fd => return Ok(fd), + } + } + + let res = open_fd(); + let val = match res { + Ok(fd) => fd, + Err(_) => FD_UNINIT, + }; + FD.store(val, Ordering::Release); + + // On non-Linux targets `wait` is just 1 ms sleep, + // so we don't need any explicit wake up in addition + // to updating value of `FD`. + #[cfg(any(target_os = "android", target_os = "linux"))] + sync::wake(); + + res +} + +fn open_fd() -> Result { + #[cfg(any(target_os = "android", target_os = "linux"))] + sync::wait_until_rng_ready()?; + let fd = open_readonly(FILE_PATH)?; + debug_assert!(fd >= 0); + Ok(fd) +} + +#[cfg(not(any(target_os = "android", target_os = "linux")))] +mod sync { + /// Sleep 1 ms before checking `FD` again. + /// + /// On non-Linux targets the critical section only opens file, + /// which should not block, so in the unlikely contended case, + /// we can sleep-wait for the opening operation to finish. + pub(super) fn wait() { + let rqtp = libc::timespec { + tv_sec: 0, + tv_nsec: 1_000_000, + }; + let mut rmtp = libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }; + // We do not care if sleep gets interrupted, so the return value is ignored + unsafe { + libc::nanosleep(&rqtp, &mut rmtp); + } + } +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +mod sync { + use super::{open_readonly, util_libc::last_os_error, Error, FD, FD_ONGOING_INIT}; + + /// Wait for atomic `FD` to change value from `FD_ONGOING_INIT` to something else. + /// + /// Futex syscall with `FUTEX_WAIT` op puts the current thread to sleep + /// until futex syscall with `FUTEX_WAKE` op gets executed for `FD`. + /// + /// For more information read: https://www.man7.org/linux/man-pages/man2/futex.2.html + pub(super) fn wait() { + let op = libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG; + let timeout_ptr = core::ptr::null::(); + let ret = unsafe { libc::syscall(libc::SYS_futex, &FD, op, FD_ONGOING_INIT, timeout_ptr) }; + // FUTEX_WAIT should return either 0 or EAGAIN error + debug_assert!({ + match ret { + 0 => true, + -1 => last_os_error().raw_os_error() == Some(libc::EAGAIN), + _ => false, + } + }); + } + + /// Wake up all threads which wait for value of atomic `FD` to change. + pub(super) fn wake() { + let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; + let ret = unsafe { libc::syscall(libc::SYS_futex, &FD, op, libc::INT_MAX) }; + debug_assert!(ret >= 0); + } + + // Polls /dev/random to make sure it is ok to read from /dev/urandom. + // + // Polling avoids draining the estimated entropy from /dev/random; + // short-lived processes reading even a single byte from /dev/random could + // be problematic if they are being executed faster than entropy is being + // collected. + // + // OTOH, reading a byte instead of polling is more compatible with + // sandboxes that disallow `poll()` but which allow reading /dev/random, + // e.g. sandboxes that assume that `poll()` is for network I/O. This way, + // fewer applications will have to insert pre-sandbox-initialization logic. + // Often (blocking) file I/O is not allowed in such early phases of an + // application for performance and/or security reasons. + // + // It is hard to write a sandbox policy to support `libc::poll()` because + // it may invoke the `poll`, `ppoll`, `ppoll_time64` (since Linux 5.1, with + // newer versions of glibc), and/or (rarely, and probably only on ancient + // systems) `select`. depending on the libc implementation (e.g. glibc vs + // musl), libc version, potentially the kernel version at runtime, and/or + // the target architecture. + // + // BoringSSL and libstd don't try to protect against insecure output from + // `/dev/urandom'; they don't open `/dev/random` at all. + // + // OpenSSL uses `libc::select()` unless the `dev/random` file descriptor + // is too large; if it is too large then it does what we do here. + // + // libsodium uses `libc::poll` similarly to this. + pub(super) fn wait_until_rng_ready() -> Result<(), Error> { + let fd = open_readonly(b"/dev/random\0")?; + let mut pfd = libc::pollfd { + fd, + events: libc::POLLIN, + revents: 0, + }; + + let res = loop { + // A negative timeout means an infinite timeout. + let res = unsafe { libc::poll(&mut pfd, 1, -1) }; + if res >= 0 { + // We only used one fd, and cannot timeout. + debug_assert_eq!(res, 1); + break Ok(()); + } + let err = last_os_error(); + // Assuming that `poll` is called correctly, + // on Linux it can return only EINTR and ENOMEM errors. + match err.raw_os_error() { + Some(libc::EINTR) => continue, + _ => break Err(err), + } + }; + unsafe { libc::close(fd) }; + res + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/vxworks.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/vxworks.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/vxworks.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/vxworks.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +//! Implementation for VxWorks +use crate::Error; +use core::{ + cmp::Ordering::{Equal, Greater, Less}, + mem::MaybeUninit, + sync::atomic::{AtomicBool, Ordering::Relaxed}, +}; + +#[path = "../util_libc.rs"] +mod util_libc; + +pub use crate::util::{inner_u32, inner_u64}; + +static RNG_INIT: AtomicBool = AtomicBool::new(false); + +#[cold] +fn init() -> Result<(), Error> { + let ret = unsafe { libc::randSecure() }; + match ret.cmp(&0) { + Greater => RNG_INIT.store(true, Relaxed), + Equal => unsafe { + libc::usleep(10); + }, + Less => return Err(Error::VXWORKS_RAND_SECURE), + } + Ok(()) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + while !RNG_INIT.load(Relaxed) { + init()?; + } + + // Prevent overflow of i32 + let chunk_size = usize::try_from(i32::MAX).expect("VxWorks does not support 16-bit targets"); + for chunk in dest.chunks_mut(chunk_size) { + let chunk_len: libc::c_int = chunk + .len() + .try_into() + .expect("chunk size is bounded by i32::MAX"); + let p: *mut libc::c_uchar = chunk.as_mut_ptr().cast(); + let ret = unsafe { libc::randABytes(p, chunk_len) }; + if ret != 0 { + return Err(util_libc::last_os_error()); + } + } + Ok(()) +} + +impl Error { + /// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized). + pub(crate) const VXWORKS_RAND_SECURE: Error = Self::new_internal(10); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p1.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +//! Implementation for WASI Preview 1 +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +// This linking is vendored from the wasi crate: +// https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2344-2350 +#[link(wasm_import_module = "wasi_snapshot_preview1")] +extern "C" { + fn random_get(arg0: i32, arg1: i32) -> i32; +} + +/// WASI p1 uses `u16` for error codes in its witx definitions: +/// https://github.com/WebAssembly/WASI/blob/38454e9e/legacy/preview1/witx/typenames.witx#L34-L39 +const MAX_ERROR_CODE: i32 = u16::MAX as i32; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Based on the wasi code: + // https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2046-2062 + // Note that size of an allocated object can not be bigger than isize::MAX bytes. + // WASI 0.1 supports only 32-bit WASM, so casting length to `i32` is safe. + #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] + let ret = unsafe { random_get(dest.as_mut_ptr() as i32, dest.len() as i32) }; + match ret { + 0 => Ok(()), + // WASI functions should return positive error codes which are smaller than `MAX_ERROR_CODE` + code if code <= MAX_ERROR_CODE => Err(Error::from_neg_error_code(-code)), + _ => Err(Error::UNEXPECTED), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p2.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasi_p2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +//! Implementation for WASI Preview 2. +use crate::Error; +use core::{mem::MaybeUninit, ptr::copy_nonoverlapping}; +use wasip2::random::random::get_random_u64; + +#[inline] +pub fn inner_u32() -> Result { + let val = get_random_u64(); + Ok(crate::util::truncate(val)) +} + +#[inline] +pub fn inner_u64() -> Result { + Ok(get_random_u64()) +} + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let (prefix, chunks, suffix) = unsafe { dest.align_to_mut::>() }; + + // We use `get_random_u64` instead of `get_random_bytes` because the latter creates + // an allocation due to the Wit IDL [restrictions][0]. This should be fine since + // the main use case of `getrandom` is seed generation. + // + // [0]: https://github.com/WebAssembly/wasi-random/issues/27 + if !prefix.is_empty() { + let val = get_random_u64(); + let src = (&val as *const u64).cast(); + unsafe { + copy_nonoverlapping(src, prefix.as_mut_ptr(), prefix.len()); + } + } + + for dst in chunks { + dst.write(get_random_u64()); + } + + if !suffix.is_empty() { + let val = get_random_u64(); + let src = (&val as *const u64).cast(); + unsafe { + copy_nonoverlapping(src, suffix.as_mut_ptr(), suffix.len()); + } + } + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasm_js.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasm_js.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/wasm_js.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/wasm_js.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +//! Implementation for WASM based on Web and Node.js +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))] +compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!"); + +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +// Maximum buffer size allowed in `Crypto.getRandomValuesSize` is 65536 bytes. +// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues +const MAX_BUFFER_SIZE: usize = 65536; + +#[cfg(not(target_feature = "atomics"))] +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + for chunk in dest.chunks_mut(MAX_BUFFER_SIZE) { + if get_random_values(chunk).is_err() { + return Err(Error::WEB_CRYPTO); + } + } + Ok(()) +} + +#[cfg(target_feature = "atomics")] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // getRandomValues does not work with all types of WASM memory, + // so we initially write to browser memory to avoid exceptions. + let buf_len = usize::min(dest.len(), MAX_BUFFER_SIZE); + let buf_len_u32 = buf_len + .try_into() + .expect("buffer length is bounded by MAX_BUFFER_SIZE"); + let buf = js_sys::Uint8Array::new_with_length(buf_len_u32); + for chunk in dest.chunks_mut(buf_len) { + let chunk_len = chunk + .len() + .try_into() + .expect("chunk length is bounded by MAX_BUFFER_SIZE"); + // The chunk can be smaller than buf's length, so we call to + // JS to create a smaller view of buf without allocation. + let sub_buf = if chunk_len == buf_len_u32 { + &buf + } else { + &buf.subarray(0, chunk_len) + }; + + if get_random_values(sub_buf).is_err() { + return Err(Error::WEB_CRYPTO); + } + + sub_buf.copy_to_uninit(chunk); + } + Ok(()) +} + +#[wasm_bindgen] +extern "C" { + // Crypto.getRandomValues() + #[cfg(not(target_feature = "atomics"))] + #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)] + fn get_random_values(buf: &mut [MaybeUninit]) -> Result<(), JsValue>; + #[cfg(target_feature = "atomics")] + #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)] + fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>; +} + +impl Error { + /// The environment does not support the Web Crypto API. + pub(crate) const WEB_CRYPTO: Error = Self::new_internal(10); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/windows.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/windows.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +//! Implementation for Windows 10 and later +//! +//! On Windows 10 and later, ProcessPrng "is the primary interface to the +//! user-mode per-processor PRNGs" and only requires bcryptprimitives.dll, +//! making it a better option than the other Windows RNG APIs: +//! - BCryptGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom +//! - Requires bcrypt.dll (which loads bcryptprimitives.dll anyway) +//! - Can cause crashes/hangs as BCrypt accesses the Windows Registry: +//! https://github.com/rust-lang/rust/issues/99341 +//! - Causes issues inside sandboxed code: +//! https://issues.chromium.org/issues/40277768 +//! - CryptGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom +//! - Deprecated and not available on UWP targets +//! - Requires advapi32.lib/advapi32.dll (in addition to bcryptprimitives.dll) +//! - Thin wrapper around ProcessPrng +//! - RtlGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom +//! - Deprecated and not available on UWP targets +//! - Requires advapi32.dll (in addition to bcryptprimitives.dll) +//! - Requires using name "SystemFunction036" +//! - Thin wrapper around ProcessPrng +//! +//! For more information see the Windows RNG Whitepaper: https://aka.ms/win10rng +use crate::Error; +use core::mem::MaybeUninit; + +pub use crate::util::{inner_u32, inner_u64}; + +// Binding to the Windows.Win32.Security.Cryptography.ProcessPrng API. As +// bcryptprimitives.dll lacks an import library, we use "raw-dylib". This +// was added in Rust 1.65 for x86_64/aarch64 and in Rust 1.71 for x86. +// We don't need MSRV 1.71, as we only use this backend on Rust 1.78 and later. +#[cfg_attr( + target_arch = "x86", + link( + name = "bcryptprimitives", + kind = "raw-dylib", + import_name_type = "undecorated" + ) +)] +#[cfg_attr( + not(target_arch = "x86"), + link(name = "bcryptprimitives", kind = "raw-dylib") +)] +extern "system" { + fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} +#[allow(clippy::upper_case_acronyms, clippy::incompatible_msrv)] +type BOOL = core::ffi::c_int; // MSRV 1.64, similarly OK for this backend. +const TRUE: BOOL = 1; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + let result = unsafe { ProcessPrng(dest.as_mut_ptr().cast::(), dest.len()) }; + // Since Windows 10, calls to the user-mode RNG are guaranteed to never + // fail during runtime (rare windows W); `ProcessPrng` will only ever + // return 1 (which is how windows represents TRUE). + // See the bottom of page 6 of the aforementioned Windows RNG + // whitepaper for more information. + debug_assert!(result == TRUE); + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/windows_legacy.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows_legacy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends/windows_legacy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends/windows_legacy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +//! Legacy implementation for Windows XP and later +//! +//! For targets where we cannot use ProcessPrng (added in Windows 10), we use +//! RtlGenRandom. See windows.rs for a more detailed discussion of the Windows +//! RNG APIs (and why we don't use BCryptGenRandom). On versions prior to +//! Windows 10, this implementation is secure. On Windows 10 and later, this +//! implementation behaves identically to the windows.rs implementation, except +//! that it forces the loading of an additional DLL (advapi32.dll). +//! +//! This implementation will not work on UWP targets (which lack advapi32.dll), +//! but such targets require Windows 10, so can use the standard implementation. +use crate::Error; +use core::{ffi::c_void, mem::MaybeUninit}; + +pub use crate::util::{inner_u32, inner_u64}; + +#[cfg(not(windows))] +compile_error!("`windows_legacy` backend can be enabled only for Windows targets!"); + +// Binding to the Windows.Win32.Security.Authentication.Identity.RtlGenRandom +// API. Don't use windows-targets as it doesn't support Windows 7 targets. +#[link(name = "advapi32")] +extern "system" { + #[link_name = "SystemFunction036"] + fn RtlGenRandom(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN; +} +#[allow(clippy::upper_case_acronyms)] +type BOOLEAN = u8; +const TRUE: BOOLEAN = 1u8; + +#[inline] +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Prevent overflow of u32 + let chunk_size = usize::try_from(i32::MAX).expect("Windows does not support 16-bit targets"); + for chunk in dest.chunks_mut(chunk_size) { + let chunk_len = u32::try_from(chunk.len()).expect("chunk size is bounded by i32::MAX"); + let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr().cast::(), chunk_len) }; + if ret != TRUE { + return Err(Error::WINDOWS_RTL_GEN_RANDOM); + } + } + Ok(()) +} + +impl Error { + /// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed. + pub(crate) const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(10); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/backends.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/backends.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,209 @@ +//! System-specific implementations. +//! +//! This module should provide `fill_inner` with the signature +//! `fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error>`. +//! The function MUST fully initialize `dest` when `Ok(())` is returned; +//! the function may need to use `sanitizer::unpoison` as well. +//! The function MUST NOT ever write uninitialized bytes into `dest`, +//! regardless of what value it returns. + +cfg_if! { + if #[cfg(getrandom_backend = "custom")] { + mod custom; + pub use custom::*; + } else if #[cfg(getrandom_backend = "linux_getrandom")] { + mod getrandom; + mod sanitizer; + pub use getrandom::*; + } else if #[cfg(getrandom_backend = "linux_raw")] { + mod linux_raw; + mod sanitizer; + pub use linux_raw::*; + } else if #[cfg(getrandom_backend = "rdrand")] { + mod rdrand; + pub use rdrand::*; + } else if #[cfg(getrandom_backend = "rndr")] { + mod rndr; + pub use rndr::*; + } else if #[cfg(getrandom_backend = "efi_rng")] { + mod efi_rng; + pub use efi_rng::*; + } else if #[cfg(getrandom_backend = "windows_legacy")] { + mod windows_legacy; + pub use windows_legacy::*; + } else if #[cfg(getrandom_backend = "wasm_js")] { + cfg_if! { + if #[cfg(feature = "wasm_js")] { + mod wasm_js; + pub use wasm_js::*; + } else { + compile_error!(concat!( + "The \"wasm_js\" backend requires the `wasm_js` feature \ + for `getrandom`. For more information see: \ + https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#webassembly-support" + )); + } + } + } else if #[cfg(getrandom_backend = "unsupported")] { + mod unsupported; + pub use unsupported::*; + } else if #[cfg(all(target_os = "linux", target_env = ""))] { + mod linux_raw; + mod sanitizer; + pub use linux_raw::*; + } else if #[cfg(target_os = "espidf")] { + mod esp_idf; + pub use esp_idf::*; + } else if #[cfg(any( + target_os = "haiku", + target_os = "redox", + target_os = "nto", + target_os = "aix", + ))] { + mod use_file; + pub use use_file::*; + } else if #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "vita", + target_os = "emscripten", + ))] { + mod getentropy; + pub use getentropy::*; + } else if #[cfg(any( + // Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets + // level 21 (Lollipop) [1], while `getrandom(2)` was added only in + // level 23 (Marshmallow). Note that it applies only to the "old" `target_arch`es, + // RISC-V Android targets sufficiently new API level, same will apply for potential + // new Android `target_arch`es. + // [0]: https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html + // [1]: https://github.com/rust-lang/rust/pull/120593 + all( + target_os = "android", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "x86", + target_arch = "x86_64", + ), + ), + // Only on these `target_arch`es Rust supports Linux kernel versions (3.2+) + // that precede the version (3.17) in which `getrandom(2)` was added: + // https://doc.rust-lang.org/stable/rustc/platform-support.html + all( + target_os = "linux", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x", + target_arch = "x86", + target_arch = "x86_64", + // Minimum supported Linux kernel version for MUSL targets + // is not specified explicitly (as of Rust 1.77) and they + // are used in practice to target pre-3.17 kernels. + all( + target_env = "musl", + not( + any( + target_arch = "riscv64", + target_arch = "riscv32", + ), + ), + ), + ), + ) + ))] { + mod use_file; + mod linux_android_with_fallback; + mod sanitizer; + pub use linux_android_with_fallback::*; + } else if #[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "hurd", + target_os = "illumos", + target_os = "cygwin", + // Check for target_arch = "arm" to only include the 3DS. Does not + // include the Nintendo Switch (which is target_arch = "aarch64"). + all(target_os = "horizon", target_arch = "arm"), + ))] { + mod getrandom; + #[cfg(any(target_os = "android", target_os = "linux"))] + mod sanitizer; + pub use getrandom::*; + } else if #[cfg(target_os = "solaris")] { + mod solaris; + pub use solaris::*; + } else if #[cfg(target_os = "netbsd")] { + mod netbsd; + pub use netbsd::*; + } else if #[cfg(target_os = "fuchsia")] { + mod fuchsia; + pub use fuchsia::*; + } else if #[cfg(any( + target_os = "ios", + target_os = "visionos", + target_os = "watchos", + target_os = "tvos", + ))] { + mod apple_other; + pub use apple_other::*; + } else if #[cfg(all(target_arch = "wasm32", target_os = "wasi"))] { + cfg_if! { + if #[cfg(target_env = "p1")] { + mod wasi_p1; + pub use wasi_p1::*; + } else if #[cfg(target_env = "p2")] { + mod wasi_p2; + pub use wasi_p2::*; + } else { + compile_error!( + "Unknown version of WASI (only previews 1 and 2 are supported) \ + or Rust version older than 1.80 was used" + ); + } + } + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(target_os = "vxworks")] { + mod vxworks; + pub use vxworks::*; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + pub use solid::*; + } else if #[cfg(all(windows, target_vendor = "win7"))] { + mod windows_legacy; + pub use windows_legacy::*; + } else if #[cfg(windows)] { + mod windows; + pub use windows::*; + } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] { + mod rdrand; + pub use rdrand::*; + } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] { + cfg_if! { + if #[cfg(feature = "wasm_js")] { + mod wasm_js; + pub use wasm_js::*; + } else { + compile_error!(concat!( + "The wasm32-unknown-unknown targets are not supported by default; \ + you may need to enable the \"wasm_js\" configuration flag. Note \ + that enabling the `wasm_js` feature flag alone is insufficient. \ + For more information see: \ + https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#webassembly-support" + )); + } + } + } else { + compile_error!(concat!( + "target is not supported. You may need to define a custom backend see: \ + https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#custom-backend" + )); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +#[cfg(feature = "std")] +extern crate std; + +use core::fmt; + +// This private alias mirrors `std::io::RawOsError`: +// https://doc.rust-lang.org/std/io/type.RawOsError.html) +cfg_if::cfg_if!( + if #[cfg(target_os = "uefi")] { + // See the UEFI spec for more information: + // https://uefi.org/specs/UEFI/2.10/Apx_D_Status_Codes.html + type RawOsError = usize; + type NonZeroRawOsError = core::num::NonZeroUsize; + const UEFI_ERROR_FLAG: RawOsError = 1 << (RawOsError::BITS - 1); + } else { + type RawOsError = i32; + type NonZeroRawOsError = core::num::NonZeroI32; + } +); + +/// A small and `no_std` compatible error type +/// +/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and +/// if so, which error code the OS gave the application. If such an error is +/// encountered, please consult with your system documentation. +/// +/// *If this crate's `"std"` Cargo feature is enabled*, then: +/// - [`getrandom::Error`][Error] implements +/// [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html) +/// - [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) implements +/// [`From`](https://doc.rust-lang.org/std/convert/trait.From.html). + +// note: on non-UEFI targets OS errors are represented as negative integers, +// while on UEFI targets OS errors have the highest bit set to 1. +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Error(NonZeroRawOsError); + +impl Error { + /// This target/platform is not supported by `getrandom`. + pub const UNSUPPORTED: Error = Self::new_internal(0); + /// The platform-specific `errno` returned a non-positive value. + pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1); + /// Encountered an unexpected situation which should not happen in practice. + pub const UNEXPECTED: Error = Self::new_internal(2); + + /// Internal errors can be in the range of 2^16..2^17 + const INTERNAL_START: RawOsError = 1 << 16; + /// Custom errors can be in the range of 2^17..(2^17 + 2^16) + const CUSTOM_START: RawOsError = 1 << 17; + + /// Creates a new instance of an `Error` from a negative error code. + #[cfg(not(target_os = "uefi"))] + #[allow(dead_code)] + pub(super) fn from_neg_error_code(code: RawOsError) -> Self { + if code < 0 { + let code = NonZeroRawOsError::new(code).expect("`code` is negative"); + Self(code) + } else { + Error::UNEXPECTED + } + } + + /// Creates a new instance of an `Error` from an UEFI error code. + #[cfg(target_os = "uefi")] + #[allow(dead_code)] + pub(super) fn from_uefi_code(code: RawOsError) -> Self { + if code & UEFI_ERROR_FLAG != 0 { + let code = NonZeroRawOsError::new(code).expect("The highest bit of `code` is set to 1"); + Self(code) + } else { + Self::UNEXPECTED + } + } + + /// Extract the raw OS error code (if this error came from the OS) + /// + /// This method is identical to [`std::io::Error::raw_os_error()`][1], except + /// that it works in `no_std` contexts. On most targets this method returns + /// `Option`, but some platforms (e.g. UEFI) may use a different primitive + /// type like `usize`. Consult with the [`RawOsError`] docs for more information. + /// + /// If this method returns `None`, the error value can still be formatted via + /// the `Display` implementation. + /// + /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error + /// [`RawOsError`]: https://doc.rust-lang.org/std/io/type.RawOsError.html + #[inline] + pub fn raw_os_error(self) -> Option { + let code = self.0.get(); + + // note: in this method we need to cover only backends which rely on + // `Error::{from_error_code, from_errno, from_uefi_code}` methods, + // on all other backends this method always returns `None`. + + #[cfg(target_os = "uefi")] + { + if code & UEFI_ERROR_FLAG != 0 { + Some(code) + } else { + None + } + } + + #[cfg(not(target_os = "uefi"))] + { + // On most targets `std` expects positive error codes while retrieving error strings: + // - `libc`-based targets use `strerror_r` which expects positive error codes. + // - Hermit relies on the `hermit-abi` crate, which expects positive error codes: + // https://docs.rs/hermit-abi/0.4.0/src/hermit_abi/errno.rs.html#400-532 + // - WASIp1 uses the same conventions as `libc`: + // https://github.com/rust-lang/rust/blob/1.85.0/library/std/src/sys/pal/wasi/os.rs#L57-L67 + // + // The only exception is Solid, `std` expects negative system error codes, see: + // https://github.com/rust-lang/rust/blob/1.85.0/library/std/src/sys/pal/solid/error.rs#L5-L31 + if code >= 0 { + None + } else if cfg!(not(target_os = "solid_asp3")) { + code.checked_neg() + } else { + Some(code) + } + } + } + + /// Creates a new instance of an `Error` from a particular custom error code. + pub const fn new_custom(n: u16) -> Error { + // SAFETY: code > 0 as CUSTOM_START > 0 and adding `n` won't overflow `RawOsError`. + let code = Error::CUSTOM_START + (n as RawOsError); + Error(unsafe { NonZeroRawOsError::new_unchecked(code) }) + } + + /// Creates a new instance of an `Error` from a particular internal error code. + pub(crate) const fn new_internal(n: u16) -> Error { + // SAFETY: code > 0 as INTERNAL_START > 0 and adding `n` won't overflow `RawOsError`. + let code = Error::INTERNAL_START + (n as RawOsError); + Error(unsafe { NonZeroRawOsError::new_unchecked(code) }) + } + + fn internal_desc(&self) -> Option<&'static str> { + let desc = match *self { + Error::UNSUPPORTED => "getrandom: this target is not supported", + Error::ERRNO_NOT_POSITIVE => "errno: did not return a positive value", + Error::UNEXPECTED => "unexpected situation", + #[cfg(any( + target_os = "ios", + target_os = "visionos", + target_os = "watchos", + target_os = "tvos", + ))] + Error::IOS_RANDOM_GEN => "SecRandomCopyBytes: iOS Security framework failure", + #[cfg(all(windows, target_vendor = "win7"))] + Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure", + #[cfg(all(feature = "wasm_js", getrandom_backend = "wasm_js"))] + Error::WEB_CRYPTO => "Web Crypto API is unavailable", + #[cfg(target_os = "vxworks")] + Error::VXWORKS_RAND_SECURE => "randSecure: VxWorks RNG module is not initialized", + + #[cfg(any( + getrandom_backend = "rdrand", + all(target_arch = "x86_64", target_env = "sgx") + ))] + Error::FAILED_RDRAND => "RDRAND: failed multiple times: CPU issue likely", + #[cfg(any( + getrandom_backend = "rdrand", + all(target_arch = "x86_64", target_env = "sgx") + ))] + Error::NO_RDRAND => "RDRAND: instruction not supported", + + #[cfg(getrandom_backend = "rndr")] + Error::RNDR_FAILURE => "RNDR: Could not generate a random number", + #[cfg(getrandom_backend = "rndr")] + Error::RNDR_NOT_AVAILABLE => "RNDR: Register not supported", + _ => return None, + }; + Some(desc) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut dbg = f.debug_struct("Error"); + if let Some(errno) = self.raw_os_error() { + dbg.field("os_error", &errno); + #[cfg(feature = "std")] + dbg.field("description", &std::io::Error::from_raw_os_error(errno)); + } else if let Some(desc) = self.internal_desc() { + dbg.field("internal_code", &self.0.get()); + dbg.field("description", &desc); + } else { + dbg.field("unknown_code", &self.0.get()); + } + dbg.finish() + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(errno) = self.raw_os_error() { + cfg_if! { + if #[cfg(feature = "std")] { + std::io::Error::from_raw_os_error(errno).fmt(f) + } else { + write!(f, "OS Error: {errno}") + } + } + } else if let Some(desc) = self.internal_desc() { + f.write_str(desc) + } else { + write!(f, "Unknown Error: {}", self.0.get()) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/error_std_impls.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error_std_impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/error_std_impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/error_std_impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +extern crate std; + +use crate::Error; +use std::io; + +impl From for io::Error { + fn from(err: Error) -> Self { + match err.raw_os_error() { + Some(errno) => io::Error::from_raw_os_error(errno), + None => io::Error::new(io::ErrorKind::Other, err), + } + } +} + +impl std::error::Error for Error {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/lazy.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lazy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/lazy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lazy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +//! Helpers built around pointer-sized atomics. +use core::sync::atomic::{AtomicUsize, Ordering}; + +// This structure represents a lazily initialized static usize value. Useful +// when it is preferable to just rerun initialization instead of locking. +// unsync_init will invoke an init() function until it succeeds, then return the +// cached value for future calls. +// +// unsync_init supports init() "failing". If the init() method returns UNINIT, +// that value will be returned as normal, but will not be cached. +// +// Users should only depend on the _value_ returned by init() functions. +// Specifically, for the following init() function: +// fn init() -> usize { +// a(); +// let v = b(); +// c(); +// v +// } +// the effects of c() or writes to shared memory will not necessarily be +// observed and additional synchronization methods may be needed. +struct LazyUsize(AtomicUsize); + +impl LazyUsize { + // The initialization is not completed. + const UNINIT: usize = usize::MAX; + + const fn new() -> Self { + Self(AtomicUsize::new(Self::UNINIT)) + } + + // Runs the init() function at most once, returning the value of some run of + // init(). Multiple callers can run their init() functions in parallel. + // init() should always return the same value, if it succeeds. + fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize { + #[cold] + fn do_init(this: &LazyUsize, init: impl FnOnce() -> usize) -> usize { + let val = init(); + this.0.store(val, Ordering::Relaxed); + val + } + + // Relaxed ordering is fine, as we only have a single atomic variable. + let val = self.0.load(Ordering::Relaxed); + if val != Self::UNINIT { + val + } else { + do_init(self, init) + } + } +} + +// Identical to LazyUsize except with bool instead of usize. +pub(crate) struct LazyBool(LazyUsize); + +impl LazyBool { + pub const fn new() -> Self { + Self(LazyUsize::new()) + } + + pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool { + self.0.unsync_init(|| usize::from(init())) != 0 + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +// Overwrite links to crate items with intra-crate links +//! [`Error::UNEXPECTED`]: Error::UNEXPECTED +//! [`fill_uninit`]: fill_uninit + +#![no_std] +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico" +)] +#![doc = include_str!("../README.md")] +#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(getrandom_backend = "efi_rng", feature(uefi_std))] +#![deny( + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_ptr_alignment, + clippy::cast_sign_loss, + clippy::char_lit_as_u8, + clippy::checked_conversions, + clippy::fn_to_numeric_cast, + clippy::fn_to_numeric_cast_with_truncation, + clippy::ptr_as_ptr, + clippy::unnecessary_cast, + clippy::useless_conversion +)] + +#[macro_use] +extern crate cfg_if; + +use core::mem::MaybeUninit; + +mod backends; +mod error; +mod util; + +#[cfg(feature = "std")] +mod error_std_impls; + +pub use crate::error::Error; + +/// Fill `dest` with random bytes from the system's preferred random number source. +/// +/// This function returns an error on any failure, including partial reads. We +/// make no guarantees regarding the contents of `dest` on error. If `dest` is +/// empty, `getrandom` immediately returns success, making no calls to the +/// underlying operating system. +/// +/// Blocking is possible, at least during early boot; see module documentation. +/// +/// In general, `getrandom` will be fast enough for interactive usage, though +/// significantly slower than a user-space CSPRNG; for the latter consider +/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html). +/// +/// # Examples +/// +/// ``` +/// # fn main() -> Result<(), getrandom::Error> { +/// let mut buf = [0u8; 32]; +/// getrandom::fill(&mut buf)?; +/// # Ok(()) } +/// ``` +#[inline] +pub fn fill(dest: &mut [u8]) -> Result<(), Error> { + // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape, + // and `fill_uninit` guarantees it will never de-initialize + // any part of `dest`. + fill_uninit(unsafe { util::slice_as_uninit_mut(dest) })?; + Ok(()) +} + +/// Fill potentially uninitialized buffer `dest` with random bytes from +/// the system's preferred random number source and return a mutable +/// reference to those bytes. +/// +/// On successful completion this function is guaranteed to return a slice +/// which points to the same memory as `dest` and has the same length. +/// In other words, it's safe to assume that `dest` is initialized after +/// this function has returned `Ok`. +/// +/// No part of `dest` will ever be de-initialized at any point, regardless +/// of what is returned. +/// +/// # Examples +/// +/// ```ignore +/// # // We ignore this test since `uninit_array` is unstable. +/// #![feature(maybe_uninit_uninit_array)] +/// # fn main() -> Result<(), getrandom::Error> { +/// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>(); +/// let buf: &mut [u8] = getrandom::fill_uninit(&mut buf)?; +/// # Ok(()) } +/// ``` +#[inline] +pub fn fill_uninit(dest: &mut [MaybeUninit]) -> Result<&mut [u8], Error> { + if !dest.is_empty() { + backends::fill_inner(dest)?; + } + + #[cfg(getrandom_msan)] + extern "C" { + fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize); + } + + // SAFETY: `dest` has been fully initialized by `imp::fill_inner` + // since it returned `Ok`. + Ok(unsafe { util::slice_assume_init_mut(dest) }) +} + +/// Get random `u32` from the system's preferred random number source. +/// +/// # Examples +/// +/// ``` +/// # fn main() -> Result<(), getrandom::Error> { +/// let rng_seed = getrandom::u32()?; +/// # Ok(()) } +/// ``` +#[inline] +pub fn u32() -> Result { + backends::inner_u32() +} + +/// Get random `u64` from the system's preferred random number source. +/// +/// # Examples +/// +/// ``` +/// # fn main() -> Result<(), getrandom::Error> { +/// let rng_seed = getrandom::u64()?; +/// # Ok(()) } +/// ``` +#[inline] +pub fn u64() -> Result { + backends::inner_u64() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/util.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +#![allow(dead_code)] +use crate::Error; +use core::{mem::MaybeUninit, ptr, slice}; + +/// Polyfill for `maybe_uninit_slice` feature's +/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have +/// been initialized. +#[inline(always)] +#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. +pub unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &mut [T] { + let ptr = ptr_from_mut::<[MaybeUninit]>(slice) as *mut [T]; + // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. + unsafe { &mut *ptr } +} + +#[inline] +pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit]) -> &mut [u8] { + unsafe { ptr::write_bytes(slice.as_mut_ptr(), 0, slice.len()) }; + unsafe { slice_assume_init_mut(slice) } +} + +#[inline(always)] +pub fn slice_as_uninit(slice: &[T]) -> &[MaybeUninit] { + let ptr = ptr_from_ref::<[T]>(slice) as *const [MaybeUninit]; + // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. + unsafe { &*ptr } +} + +/// View an mutable initialized array as potentially-uninitialized. +/// +/// This is unsafe because it allows assigning uninitialized values into +/// `slice`, which would be undefined behavior. +#[inline(always)] +#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. +pub unsafe fn slice_as_uninit_mut(slice: &mut [T]) -> &mut [MaybeUninit] { + let ptr = ptr_from_mut::<[T]>(slice) as *mut [MaybeUninit]; + // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. + unsafe { &mut *ptr } +} + +// TODO: MSRV(1.76.0): Replace with `core::ptr::from_mut`. +fn ptr_from_mut(r: &mut T) -> *mut T { + r +} + +// TODO: MSRV(1.76.0): Replace with `core::ptr::from_ref`. +fn ptr_from_ref(r: &T) -> *const T { + r +} + +/// Default implementation of `inner_u32` on top of `fill_uninit` +#[inline] +pub fn inner_u32() -> Result { + let mut res = MaybeUninit::::uninit(); + // SAFETY: the created slice has the same size as `res` + let dst = unsafe { + let p: *mut MaybeUninit = res.as_mut_ptr().cast(); + slice::from_raw_parts_mut(p, core::mem::size_of::()) + }; + crate::fill_uninit(dst)?; + // SAFETY: `dst` has been fully initialized by `imp::fill_inner` + // since it returned `Ok`. + Ok(unsafe { res.assume_init() }) +} + +/// Default implementation of `inner_u64` on top of `fill_uninit` +#[inline] +pub fn inner_u64() -> Result { + let mut res = MaybeUninit::::uninit(); + // SAFETY: the created slice has the same size as `res` + let dst = unsafe { + let p: *mut MaybeUninit = res.as_mut_ptr().cast(); + slice::from_raw_parts_mut(p, core::mem::size_of::()) + }; + crate::fill_uninit(dst)?; + // SAFETY: `dst` has been fully initialized by `imp::fill_inner` + // since it returned `Ok`. + Ok(unsafe { res.assume_init() }) +} + +/// Truncates `u64` and returns the lower 32 bits as `u32` +pub(crate) fn truncate(val: u64) -> u32 { + u32::try_from(val & u64::from(u32::MAX)).expect("The higher 32 bits are masked") +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/util_libc.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util_libc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/src/util_libc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/src/util_libc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +use crate::Error; +use core::mem::MaybeUninit; + +cfg_if! { + if #[cfg(any(target_os = "netbsd", target_os = "openbsd", target_os = "android", target_os = "cygwin"))] { + use libc::__errno as errno_location; + } else if #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "hurd", target_os = "redox", target_os = "dragonfly"))] { + use libc::__errno_location as errno_location; + } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { + use libc::___errno as errno_location; + } else if #[cfg(any(target_os = "macos", target_os = "freebsd"))] { + use libc::__error as errno_location; + } else if #[cfg(target_os = "haiku")] { + use libc::_errnop as errno_location; + } else if #[cfg(target_os = "nto")] { + use libc::__get_errno_ptr as errno_location; + } else if #[cfg(any(all(target_os = "horizon", target_arch = "arm"), target_os = "vita"))] { + extern "C" { + // Not provided by libc: https://github.com/rust-lang/libc/issues/1995 + fn __errno() -> *mut libc::c_int; + } + use __errno as errno_location; + } else if #[cfg(target_os = "aix")] { + use libc::_Errno as errno_location; + } +} + +cfg_if! { + if #[cfg(target_os = "vxworks")] { + use libc::errnoGet as get_errno; + } else { + unsafe fn get_errno() -> libc::c_int { *errno_location() } + } +} + +pub(crate) fn last_os_error() -> Error { + // We assume that on all targets which use the `util_libc` module `c_int` is equal to `i32` + let errno: i32 = unsafe { get_errno() }; + + if errno > 0 { + let code = errno + .checked_neg() + .expect("Positive number can be always negated"); + Error::from_neg_error_code(code) + } else { + Error::ERRNO_NOT_POSITIVE + } +} + +/// Fill a buffer by repeatedly invoking `sys_fill`. +/// +/// The `sys_fill` function: +/// - should return -1 and set errno on failure +/// - should return the number of bytes written on success +#[allow(dead_code)] +pub(crate) fn sys_fill_exact( + mut buf: &mut [MaybeUninit], + sys_fill: impl Fn(&mut [MaybeUninit]) -> libc::ssize_t, +) -> Result<(), Error> { + while !buf.is_empty() { + let res = sys_fill(buf); + match res { + res if res > 0 => { + let len = usize::try_from(res).map_err(|_| Error::UNEXPECTED)?; + buf = buf.get_mut(len..).ok_or(Error::UNEXPECTED)?; + } + -1 => { + let err = last_os_error(); + // We should try again if the call was interrupted. + if err.raw_os_error() != Some(libc::EINTR) { + return Err(err); + } + } + // Negative return codes not equal to -1 should be impossible. + // EOF (ret = 0) should be impossible, as the data we are reading + // should be an infinite stream of random bytes. + _ => return Err(Error::UNEXPECTED), + } + } + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/getrandom/tests/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/getrandom/tests/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/getrandom/tests/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/getrandom/tests/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,297 @@ +use core::mem::MaybeUninit; +use getrandom::{fill, fill_uninit}; + +#[cfg(all(feature = "wasm_js", target_arch = "wasm32", target_os = "unknown"))] +use wasm_bindgen_test::wasm_bindgen_test as test; + +#[test] +fn test_zero() { + // Test that APIs are happy with zero-length requests + fill(&mut [0u8; 0]).unwrap(); + let res = fill_uninit(&mut []).unwrap(); + assert!(res.is_empty()); +} + +trait DiffBits: Sized { + fn diff_bits(ab: (&Self, &Self)) -> usize; +} + +impl DiffBits for u8 { + fn diff_bits((a, b): (&Self, &Self)) -> usize { + (a ^ b).count_ones() as usize + } +} + +impl DiffBits for u32 { + fn diff_bits((a, b): (&Self, &Self)) -> usize { + (a ^ b).count_ones() as usize + } +} + +impl DiffBits for u64 { + fn diff_bits((a, b): (&Self, &Self)) -> usize { + (a ^ b).count_ones() as usize + } +} + +// Return the number of bits in which s1 and s2 differ +fn num_diff_bits(s1: &[T], s2: &[T]) -> usize { + assert_eq!(s1.len(), s2.len()); + s1.iter().zip(s2.iter()).map(T::diff_bits).sum() +} + +// TODO: use `[const { MaybeUninit::uninit() }; N]` after MSRV is bumped to 1.79+ +// or `MaybeUninit::uninit_array` +fn uninit_vec(n: usize) -> Vec> { + vec![MaybeUninit::uninit(); n] +} + +// Tests the quality of calling getrandom on two large buffers +#[test] +fn test_diff() { + const N: usize = 1000; + let mut v1 = [0u8; N]; + let mut v2 = [0u8; N]; + fill(&mut v1).unwrap(); + fill(&mut v2).unwrap(); + + let mut t1 = uninit_vec(N); + let mut t2 = uninit_vec(N); + let r1 = fill_uninit(&mut t1).unwrap(); + let r2 = fill_uninit(&mut t2).unwrap(); + assert_eq!(r1.len(), N); + assert_eq!(r2.len(), N); + + // Between 3.5 and 4.5 bits per byte should differ. Probability of failure: + // ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500] + let d1 = num_diff_bits(&v1, &v2); + assert!(d1 > 3500); + assert!(d1 < 4500); + let d2 = num_diff_bits(r1, r2); + assert!(d2 > 3500); + assert!(d2 < 4500); +} + +#[test] +fn test_diff_u32() { + const N: usize = 1000 / 4; + let mut v1 = [0u32; N]; + let mut v2 = [0u32; N]; + for v in v1.iter_mut() { + *v = getrandom::u32().unwrap(); + } + for v in v2.iter_mut() { + *v = getrandom::u32().unwrap(); + } + + // Between 3.5 and 4.5 bits per byte should differ. Probability of failure: + // ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500] + let d1 = num_diff_bits(&v1, &v2); + assert!(d1 > 3500); + assert!(d1 < 4500); +} + +#[test] +fn test_diff_u64() { + const N: usize = 1000 / 8; + let mut v1 = [0u64; N]; + let mut v2 = [0u64; N]; + for v in v1.iter_mut() { + *v = getrandom::u64().unwrap(); + } + for v in v2.iter_mut() { + *v = getrandom::u64().unwrap(); + } + + // Between 3.5 and 4.5 bits per byte should differ. Probability of failure: + // ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500] + let d1 = num_diff_bits(&v1, &v2); + assert!(d1 > 3500); + assert!(d1 < 4500); +} + +#[test] +fn test_small() { + const N: usize = 64; + // For each buffer size, get at least 256 bytes and check that between + // 3 and 5 bits per byte differ. Probability of failure: + // ~ 2^(-91) = 64 * 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256] + for size in 1..=N { + let mut num_bytes = 0; + let mut diff_bits = 0; + while num_bytes < 256 { + let mut buf1 = [0u8; N]; + let mut buf2 = [0u8; N]; + + let s1 = &mut buf1[..size]; + let s2 = &mut buf2[..size]; + + fill(s1).unwrap(); + fill(s2).unwrap(); + + num_bytes += size; + diff_bits += num_diff_bits(s1, s2); + } + assert!(diff_bits > 3 * num_bytes); + assert!(diff_bits < 5 * num_bytes); + } +} + +// Tests the quality of calling getrandom repeatedly on small buffers +#[test] +fn test_small_uninit() { + const N: usize = 64; + // For each buffer size, get at least 256 bytes and check that between + // 3 and 5 bits per byte differ. Probability of failure: + // ~ 2^(-91) = 64 * 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256] + for size in 1..=N { + let mut num_bytes = 0; + let mut diff_bits = 0; + while num_bytes < 256 { + let mut buf1 = uninit_vec(N); + let mut buf2 = uninit_vec(N); + + let s1 = &mut buf1[..size]; + let s2 = &mut buf2[..size]; + + let r1 = fill_uninit(s1).unwrap(); + let r2 = fill_uninit(s2).unwrap(); + assert_eq!(r1.len(), size); + assert_eq!(r2.len(), size); + + num_bytes += size; + diff_bits += num_diff_bits(r1, r2); + } + assert!(diff_bits > 3 * num_bytes); + assert!(diff_bits < 5 * num_bytes); + } +} + +#[test] +fn test_huge() { + let mut huge = [0u8; 100_000]; + fill(&mut huge).unwrap(); +} + +#[test] +fn test_huge_uninit() { + const N: usize = 100_000; + let mut huge = uninit_vec(N); + let res = fill_uninit(&mut huge).unwrap(); + assert_eq!(res.len(), N); +} + +#[test] +#[cfg_attr( + target_arch = "wasm32", + ignore = "The thread API always fails/panics on WASM" +)] +fn test_multithreading() { + extern crate std; + use std::{sync::mpsc::channel, thread, vec}; + + let mut txs = vec![]; + for _ in 0..20 { + let (tx, rx) = channel(); + txs.push(tx); + + thread::spawn(move || { + // wait until all the tasks are ready to go. + rx.recv().unwrap(); + let mut v = [0u8; 1000]; + + for _ in 0..100 { + fill(&mut v).unwrap(); + thread::yield_now(); + } + }); + } + + // start all the tasks + for tx in txs.iter() { + tx.send(()).unwrap(); + } +} + +#[cfg(getrandom_backend = "custom")] +mod custom { + use getrandom::Error; + + struct Xoshiro128PlusPlus { + s: [u32; 4], + } + + impl Xoshiro128PlusPlus { + fn new(mut seed: u64) -> Self { + const PHI: u64 = 0x9e3779b97f4a7c15; + let mut s = [0u32; 4]; + for val in s.iter_mut() { + seed = seed.wrapping_add(PHI); + let mut z = seed; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); + z = z ^ (z >> 31); + *val = z as u32; + } + Self { s } + } + + fn next_u32(&mut self) -> u32 { + let res = self.s[0] + .wrapping_add(self.s[3]) + .rotate_left(7) + .wrapping_add(self.s[0]); + + let t = self.s[1] << 9; + + self.s[2] ^= self.s[0]; + self.s[3] ^= self.s[1]; + self.s[1] ^= self.s[2]; + self.s[0] ^= self.s[3]; + + self.s[2] ^= t; + + self.s[3] = self.s[3].rotate_left(11); + + res + } + } + + // This implementation uses current timestamp as a PRNG seed. + // + // WARNING: this custom implementation is for testing purposes ONLY! + #[no_mangle] + unsafe extern "Rust" fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), Error> { + use std::time::{SystemTime, UNIX_EPOCH}; + + assert_ne!(len, 0); + + if len == 142 { + return Err(Error::new_custom(142)); + } + + let dest_u32 = dest.cast::(); + let ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let mut rng = Xoshiro128PlusPlus::new(ts.as_nanos() as u64); + for i in 0..len / 4 { + let val = rng.next_u32(); + core::ptr::write_unaligned(dest_u32.add(i), val); + } + if len % 4 != 0 { + let start = 4 * (len / 4); + for i in start..len { + let val = rng.next_u32(); + core::ptr::write_unaligned(dest.add(i), val as u8); + } + } + Ok(()) + } + + // Test that enabling the custom feature indeed uses the custom implementation + #[test] + fn test_custom() { + let mut buf = [0u8; 142]; + let res = getrandom::fill(&mut buf); + assert!(res.is_err()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/gif/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"85d01d15997217374c59f21053876e60160428cadacbd15f1a59f6ab893ae2da","Cargo.toml":"36fd4a0f8b4bd40d4e61e1a35b5bddcc2660276634cda50e6c4bba0058ef20be","LICENSE-APACHE":"769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb","LICENSE-MIT":"77257f3d2181236b1aee78920238062ae64efe13c5d858b2db126e79c9e1b14f","README.md":"2fdb933b17e84901abbc50ff9fae053a6fb363b56b7093a26695c18863214c95","benches/decode.rs":"5fc9d14ea26af6f86456fb6900848b5e4cc0f144ca5fc3f759254b250fea55c8","benches/rgb_frame.rs":"5ccb6a8ddc14517390d90c2337948751c22e02779069483695ae9d69015d37d2","src/common.rs":"a860332438b51a2e67a4781e9b018fbafd9adf53ad0e95de3861def4760d265b","src/encoder.rs":"14726503aaf765ea142b393c9230c93b717a880cf65bc916d876e02607d6cc5a","src/lib.rs":"ef37151233563e06ac8de0aece3074738f45cfbc323fb0eef0a333a448c75fe4","src/reader/converter.rs":"4c20d9b655cbb0257703430e274b7889f9628dab4bf1922e1a4bbe26c5ec4638","src/reader/decoder.rs":"0e30c6a2944cccb5958845cb988fba4bf64df269aed49a819dd5d6db151525c6","src/reader/mod.rs":"79d7b2be0d01d0cc5cbc78bd8d5d4617d581484b17b96f248704a64446441154","src/traits.rs":"f3597d81298be0b8aa00806776abf7a922257cd31289389cfbfa260bd8425853"},"package":"3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"21f2623dd05cb5a98cf827087ffdf2887b4b45556dfb98eff504140c3158c069","Cargo.lock":"e9dd4f78772cdfcc430867bfb94ba614d29abd8f677e200a93ad51e2adca2615","Cargo.toml":"e99d25efa5921283f9eb92a3322903c09e2b4f2c8422babfaf85b35ab0380d80","Cargo.toml.orig":"d5add59f8f32a6294bfa4d877d7b1c4279d896e623073e2c79b7a1d6aec8b2f6","LICENSE-APACHE":"769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb","LICENSE-MIT":"77257f3d2181236b1aee78920238062ae64efe13c5d858b2db126e79c9e1b14f","README.md":"2fdb933b17e84901abbc50ff9fae053a6fb363b56b7093a26695c18863214c95","benches/decode.rs":"3e2907fe09bb5c1efcf1588ea663baa9f8cb9dda9be5ceccc5613190e3e105b8","benches/rgb_frame.rs":"b0c0416eb5c9cfb7a4005117565e44ca717819e9c673d4bdc13a38007f34f1b6","src/common.rs":"c5705b324e5d2c4dc01f25b3212565fad59ab02d2de09525633af73b646ade44","src/encoder.rs":"fe147e8deaf3b60513dca260507b9c126ecc4239c17339d6210769077d65f4ba","src/lib.rs":"cda24a61e925aee2c0152917c9927e4ed3a654ec6f4abd68945206c1dc5e2ab8","src/reader/converter.rs":"d6963365ae8f94e6850814ea28a83724b64447509cf48c4ad7375264bb413ccd","src/reader/decoder.rs":"09386d020d4cf0eda0b23ef525f7f460c5f8363834d7e7666182b3d7059b7881","src/reader/mod.rs":"d5a1d2f648a23a0053c872ce647eb17a5b35377f444ae3ea2e05174bc216b2f3","src/traits.rs":"9aee56967cbf1fff121aa06cd16308e0907497ff34fa1db39b0a3ecb7bc8344f"},"package":"f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/gif/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c1a6c4f18aec2884fe4fa7ce4fdbead92c975af1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -3,16 +3,16 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -25,33 +25,27 @@ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "cast" @@ -61,15 +55,15 @@ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -78,15 +72,15 @@ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -94,18 +88,18 @@ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstyle", "clap_lex", @@ -113,9 +107,9 @@ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "color_quant" @@ -125,34 +119,31 @@ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "criterion" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", - "is-terminal", "itertools", "num-traits", - "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -160,9 +151,9 @@ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", "itertools", @@ -170,9 +161,9 @@ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -189,40 +180,36 @@ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "either" -version = "1.9.0" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "errno" -version = "0.3.8" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys", -] +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -230,7 +217,7 @@ [[package]] name = "gif" -version = "0.13.1" +version = "0.14.1" dependencies = [ "color_quant", "criterion", @@ -242,117 +229,93 @@ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hermit-abi" -version = "0.3.4" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" - -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ - "hermit-abi", - "rustix", - "windows-sys", + "cfg-if", + "crunchy", ] [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] -name = "libc" -version = "0.2.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] name = "log" -version = "0.4.20" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -363,26 +326,26 @@ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "png" -version = "0.17.11" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags", "crc32fast", "fdeflate", "flate2", @@ -391,27 +354,27 @@ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" -version = "1.8.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -419,9 +382,9 @@ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -429,9 +392,9 @@ [[package]] name = "regex" -version = "1.10.3" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -441,9 +404,9 @@ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -452,28 +415,21 @@ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] -name = "rustix" -version = "0.38.30" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -486,18 +442,18 @@ [[package]] name = "serde" -version = "1.0.195" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -506,11 +462,12 @@ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -523,9 +480,9 @@ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -544,15 +501,15 @@ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -560,23 +517,24 @@ [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -585,9 +543,9 @@ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -595,9 +553,9 @@ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -608,15 +566,18 @@ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -624,59 +585,45 @@ [[package]] name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "winapi", + "windows-sys", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -685,42 +632,48 @@ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,32 +11,53 @@ [package] edition = "2021" +rust-version = "1.62" name = "gif" -version = "0.13.1" +version = "0.14.1" authors = ["The image-rs Developers"] +build = false include = [ "src/**", "LICENSE-*", "README.md", "benches/*.rs", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "GIF de- and encoder" homepage = "https://github.com/image-rs/image-gif" documentation = "https://docs.rs/gif" readme = "README.md" -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/image-rs/image-gif" +[features] +color_quant = ["dep:color_quant"] +default = [ + "raii_no_panic", + "std", + "color_quant", +] +raii_no_panic = [] +std = [] + [lib] +name = "gif" +path = "src/lib.rs" bench = false [[bench]] name = "decode" +path = "benches/decode.rs" harness = false required-features = ["std"] [[bench]] name = "rgb_frame" +path = "benches/rgb_frame.rs" harness = false required-features = [ "std", @@ -48,26 +69,16 @@ optional = true [dependencies.weezl] -version = "0.1.8" +version = "0.1.10" [dev-dependencies.criterion] -version = "0.5.1" +version = "0.7.0" [dev-dependencies.glob] version = "0.3" [dev-dependencies.png] -version = "0.17.10" +version = "0.18.0" [dev-dependencies.rayon] -version = "1.8.0" - -[features] -color_quant = ["dep:color_quant"] -default = [ - "raii_no_panic", - "std", - "color_quant", -] -raii_no_panic = [] -std = [] +version = "1.10.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/gif/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +[package] +name = "gif" +license = "MIT OR Apache-2.0" +version = "0.14.1" +description = "GIF de- and encoder" +authors = ["The image-rs Developers"] +readme = "README.md" +homepage = "https://github.com/image-rs/image-gif" +repository = "https://github.com/image-rs/image-gif" +documentation = "https://docs.rs/gif" +edition = "2021" +include = ["src/**", "LICENSE-*", "README.md", "benches/*.rs"] +rust-version = "1.62" + +[lib] +bench = false + +[dependencies] +weezl = "0.1.10" +color_quant = { version = "1.1", optional = true } + +[dev-dependencies] +glob = "0.3" +criterion = "0.7.0" +png = "0.18.0" +rayon = "1.10.0" # for parallel reencoding example + +[features] +default = ["raii_no_panic", "std", "color_quant"] +# The `Encoder` finishes writing in `Drop`, and if the write fails, it either ignores the error (`raii_no_panic`) or panics. +# Use `Encoder::into_inner` to avoid the issue entirely +raii_no_panic = [] +color_quant = ["dep:color_quant"] +# Reservation for a feature turning off std +std = [] + +[[bench]] +name = "decode" +harness = false +required-features = ["std"] + +[[bench]] +name = "rgb_frame" +harness = false +required-features = ["std", "color_quant"] + +[[example]] +name = "check" +required-features = ["std"] + +[[example]] +name = "explode" +required-features = ["std"] + +[[example]] +name = "parallel" +required-features = ["std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/benches/decode.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/decode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/benches/decode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/decode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,17 +1,19 @@ -use criterion::{black_box, BenchmarkId, BenchmarkGroup, Criterion, Throughput, measurement::Measurement}; +use criterion::{measurement::Measurement, BenchmarkGroup, BenchmarkId, Criterion, Throughput}; use gif::Decoder; +use std::hint::black_box; fn read_image(image: &[u8]) -> Option> { let decoder = Decoder::new(black_box(image)); //decoder.set_param(gif::ColorOutput::RGBA); let mut reader = decoder.unwrap(); - while let Some(_) = reader.next_frame_info().unwrap() { + if reader.next_frame_info().unwrap().is_some() { let mut v = vec![0; reader.buffer_size()]; reader.fill_buffer(&mut v).unwrap(); - return Some(v); + Some(v) + } else { + None } - None } fn read_metadata(image: &[u8]) { @@ -34,46 +36,57 @@ BenchmarkId::new(def.id, def.data.len()), def.data, |b, input| { - b.iter(|| read_image(input)) - } + b.iter(|| read_image(input)); + }, ); } let mut c = Criterion::default().configure_from_args(); let mut group = c.benchmark_group("gif"); - run_bench_def(&mut group, BenchDef { - data: include_bytes!("note.gif"), - id: "note.gif", - sample_size: 100, - }); - - run_bench_def(&mut group, BenchDef { - data: include_bytes!("photo.gif"), - id: "photo.gif", - sample_size: 20, - }); - - run_bench_def(&mut group, BenchDef { - data: include_bytes!("../tests/samples/sample_1.gif"), - id: "sample_1.gif", - sample_size: 100, - }); - - run_bench_def(&mut group, BenchDef { - data: include_bytes!("../tests/samples/sample_big.gif"), - id: "sample_big.gif", - sample_size: 20, - }); - - group - .bench_with_input( - "extract-metadata-note", - include_bytes!("note.gif"), - |b, input| { - b.iter(|| read_metadata(input)) - } - ); + run_bench_def( + &mut group, + BenchDef { + data: include_bytes!("note.gif"), + id: "note.gif", + sample_size: 100, + }, + ); + + run_bench_def( + &mut group, + BenchDef { + data: include_bytes!("photo.gif"), + id: "photo.gif", + sample_size: 20, + }, + ); + + run_bench_def( + &mut group, + BenchDef { + data: include_bytes!("../tests/samples/sample_1.gif"), + id: "sample_1.gif", + sample_size: 100, + }, + ); + + run_bench_def( + &mut group, + BenchDef { + data: include_bytes!("../tests/samples/sample_big.gif"), + id: "sample_big.gif", + sample_size: 20, + }, + ); + + group.bench_with_input( + "extract-metadata-note", + include_bytes!("note.gif"), + |b, input| { + b.iter(|| read_metadata(input)); + }, + ); group.finish(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/benches/rgb_frame.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/rgb_frame.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/benches/rgb_frame.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/benches/rgb_frame.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,11 @@ -use std::fs; +use std::{fs, io}; use criterion::{Criterion, Throughput}; use gif::{Encoder, Frame, Repeat}; -use png; const DIR: &str = "benches/samples"; -fn main() -{ +fn main() { let mut c = Criterion::default().configure_from_args(); let mut group = c.benchmark_group("rgb_frame"); @@ -21,11 +19,11 @@ let mut reader = { let input = fs::File::open(&path).unwrap(); - let decoder = png::Decoder::new(input); + let decoder = png::Decoder::new(io::BufReader::new(input)); decoder.read_info().unwrap() }; - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.next_frame(&mut buf).unwrap(); let (w, h, size) = { @@ -37,20 +35,18 @@ group .sample_size(50) .throughput(Throughput::Bytes(size as u64)) - .bench_function(path.file_name().unwrap().to_str().unwrap(), - |b| { - match info.color_type { - png::ColorType::Rgb => b.iter(|| { - Frame::from_rgb_speed(w, h, &mut buf[..size], 30) - }), - png::ColorType::Rgba => b.iter(|| { - Frame::from_rgba_speed(w, h, &mut buf[..size], 30) - }), + .bench_function( + path.file_name().unwrap().to_str().unwrap(), + |b| match info.color_type { + png::ColorType::Rgb => b.iter(|| Frame::from_rgb_speed(w, h, &buf[..size], 30)), + png::ColorType::Rgba => { + b.iter(|| Frame::from_rgba_speed(w, h, &mut buf[..size], 30)) + } c => { - println!("Image has wrong color type: {:?}", c); + println!("Image has wrong color type: {c:?}"); } - } - }); + }, + ); // actually write the image as a singe frame gif... while MSE can be used // for quality check, it might not be as good as visual inspection @@ -61,7 +57,7 @@ encoder.set_repeat(Repeat::Finite(0)).unwrap(); let frame = match info.color_type { - png::ColorType::Rgb => Frame::from_rgb(w, h, &mut buf[..size]), + png::ColorType::Rgb => Frame::from_rgb(w, h, &buf[..size]), png::ColorType::Rgba => Frame::from_rgba(w, h, &mut buf[..size]), _ => continue, }; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/common.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/common.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/common.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/common.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,14 @@ -use std::borrow::Cow; +use alloc::borrow::Cow; +use alloc::vec::Vec; + #[cfg(feature = "color_quant")] -use std::collections::{HashMap, HashSet}; +use alloc::collections::{BTreeMap, BTreeSet}; /// Disposal method #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(u8)] pub enum DisposalMethod { - /// StreamingDecoder is not required to take any action. + /// `StreamingDecoder` is not required to take any action. Any = 0, /// Do not dispose. Keep = 1, @@ -19,12 +21,12 @@ impl DisposalMethod { /// Converts `u8` to `Option` #[must_use] - pub fn from_u8(n: u8) -> Option { + pub const fn from_u8(n: u8) -> Option { match n { - 0 => Some(DisposalMethod::Any), - 1 => Some(DisposalMethod::Keep), - 2 => Some(DisposalMethod::Background), - 3 => Some(DisposalMethod::Previous), + 0 => Some(Self::Any), + 1 => Some(Self::Keep), + 2 => Some(Self::Background), + 3 => Some(Self::Previous), _ => None, } } @@ -54,11 +56,11 @@ impl Block { /// Converts `u8` to `Option` #[must_use] - pub fn from_u8(n: u8) -> Option { + pub const fn from_u8(n: u8) -> Option { match n { - 0x2C => Some(Block::Image), - 0x21 => Some(Block::Extension), - 0x3B => Some(Block::Trailer), + 0x2C => Some(Self::Image), + 0x21 => Some(Self::Extension), + 0x3B => Some(Self::Trailer), _ => None, } } @@ -105,26 +107,26 @@ impl AnyExtension { /// Decode the label as a known extension. #[must_use] - pub fn into_known(self) -> Option { + pub const fn into_known(self) -> Option { Extension::from_u8(self.0) } } impl From for AnyExtension { fn from(ext: Extension) -> Self { - AnyExtension(ext as u8) + Self(ext as u8) } } impl Extension { /// Converts `u8` to a `Extension` if it is known. #[must_use] - pub fn from_u8(n: u8) -> Option { + pub const fn from_u8(n: u8) -> Option { match n { - 0x01 => Some(Extension::Text), - 0xF9 => Some(Extension::Control), - 0xFE => Some(Extension::Comment), - 0xFF => Some(Extension::Application), + 0x01 => Some(Self::Text), + 0xF9 => Some(Self::Control), + 0xFE => Some(Self::Comment), + 0xFF => Some(Self::Application), _ => None, } } @@ -158,8 +160,8 @@ pub buffer: Cow<'a, [u8]>, } -impl<'a> Default for Frame<'a> { - fn default() -> Frame<'a> { +impl Default for Frame<'_> { + fn default() -> Self { Frame { delay: 0, dispose: DisposalMethod::Keep, @@ -189,7 +191,8 @@ /// # Panics: /// * If the length of pixels does not equal `width * height * 4`. #[cfg(feature = "color_quant")] - pub fn from_rgba(width: u16, height: u16, pixels: &mut [u8]) -> Frame<'static> { + #[track_caller] + pub fn from_rgba(width: u16, height: u16, pixels: &mut [u8]) -> Self { Frame::from_rgba_speed(width, height, pixels, 1) } @@ -208,13 +211,25 @@ /// * If the length of pixels does not equal `width * height * 4`. /// * If `speed < 1` or `speed > 30` #[cfg(feature = "color_quant")] - pub fn from_rgba_speed(width: u16, height: u16, pixels: &mut [u8], speed: i32) -> Frame<'static> { + #[track_caller] + pub fn from_rgba_speed(width: u16, height: u16, pixels: &mut [u8], speed: i32) -> Self { assert_eq!(width as usize * height as usize * 4, pixels.len(), "Too much or too little pixel data for the given width and height to create a GIF Frame"); - assert!(speed >= 1 && speed <= 30, "speed needs to be in the range [1, 30]"); - let mut transparent = None; + assert!( + speed >= 1 && speed <= 30, + "speed needs to be in the range [1, 30]" + ); + let mut transparent: Option<[u8; 4]> = None; for pix in pixels.chunks_exact_mut(4) { if pix[3] != 0 { pix[3] = 0xFF; + continue; + } + + if let Some([r, g, b, a]) = transparent { + pix[0] = r; + pix[1] = g; + pix[2] = b; + pix[3] = a; } else { transparent = Some([pix[0], pix[1], pix[2], pix[3]]); } @@ -222,7 +237,7 @@ // Attempt to build a palette of all colors. If we go over 256 colors, // switch to the NeuQuant algorithm. - let mut colors: HashSet<(u8, u8, u8, u8)> = HashSet::new(); + let mut colors: BTreeSet<(u8, u8, u8, u8)> = BTreeSet::new(); for pixel in pixels.chunks_exact(4) { if colors.insert((pixel[0], pixel[1], pixel[2], pixel[3])) && colors.len() > 256 { // > 256 colours, let's use NeuQuant. @@ -231,7 +246,12 @@ return Frame { width, height, - buffer: Cow::Owned(pixels.chunks_exact(4).map(|pix| nq.index_of(pix) as u8).collect()), + buffer: Cow::Owned( + pixels + .chunks_exact(4) + .map(|pix| nq.index_of(pix) as u8) + .collect(), + ), palette: Some(nq.color_map_rgb()), transparent: transparent.map(|t| nq.index_of(&t) as u8), ..Frame::default() @@ -242,20 +262,118 @@ // Palette size <= 256 elements, we can build an exact palette. let mut colors_vec: Vec<(u8, u8, u8, u8)> = colors.into_iter().collect(); colors_vec.sort_unstable(); - let palette = colors_vec.iter().flat_map(|&(r, g, b, _a)| [r, g, b]).collect(); - let colors_lookup: HashMap<(u8, u8, u8, u8), u8> = colors_vec.into_iter().zip(0..=255).collect(); - - let index_of = | pixel: &[u8] | - colors_lookup.get(&(pixel[0], pixel[1], pixel[2], pixel[3])).copied().unwrap_or(0); + let palette = colors_vec + .iter() + .flat_map(|&(r, g, b, _a)| [r, g, b]) + .collect(); + let colors_lookup: BTreeMap<(u8, u8, u8, u8), u8> = + colors_vec.into_iter().zip(0..=255).collect(); + + let index_of = |pixel: &[u8]| { + colors_lookup + .get(&(pixel[0], pixel[1], pixel[2], pixel[3])) + .copied() + .unwrap_or(0) + }; - return Frame { + Frame { width, height, buffer: Cow::Owned(pixels.chunks_exact(4).map(index_of).collect()), palette: Some(palette), transparent: transparent.map(|t| index_of(&t)), ..Frame::default() + } + } + + /// Creates a frame from pixels in LumaAlpha format (grayscale pixels with transparency). + /// + /// This is a lossy method. The `gif` format does not support arbitrary alpha but only a 1-bit + /// transparency mask per pixel. Any non-zero alpha value will be interpreted as a fully opaque + /// pixel. The least used color will be used to indicate alpha and replace with the closest other color + /// in the image. Different frames have independent palettes. + /// + /// # Panics: + /// * If the length of pixels does not equal `width * height * 2`. + pub fn from_grayscale_with_alpha(width: u16, height: u16, pixels: &[u8]) -> Self { + assert_eq!(width as usize * height as usize * 2, pixels.len(), "Too much or too little pixel data for the given width and height to create a GIF Frame"); + + // Input is in LumaA format. + // Count the occurrences of all the colors, then pick the least common color as alpha. + let mut num_transparent_pixels: u32 = 0; + let mut color_frequencies: [u32; 256] = [0; 256]; + for pixel in pixels.chunks_exact(2) { + let color = pixel[0]; + let alpha = pixel[1]; + // do not count colors in fully transparent pixels + if alpha == 0 { + num_transparent_pixels += 1; + } else { + color_frequencies[color as usize] += 1; + } + } + + let grayscale_palette: Vec = (0..=255).flat_map(|i| [i, i, i]).collect(); + + // If there were no fully transparent pixels, do not allocate a color to transparency in the GIF + // and return immediately with the generic grayscale palette + if num_transparent_pixels == 0 { + let stripped_alpha: Vec = pixels.chunks_exact(2).map(|pixel| pixel[0]).collect(); + return Frame { + width, + height, + buffer: Cow::Owned(stripped_alpha), + palette: Some(grayscale_palette), + transparent: None, + ..Frame::default() + }; + } + + // Choose the color that will be our alpha color + let least_used_color = color_frequencies + .iter() + .enumerate() + .min_by_key(|(_, &value)| value) + .map(|(index, _)| index as u8) + .expect("input slice is empty"); + + // pick the less used color out of the neighbours as the replacement color + let replacement_color = if least_used_color == 255 { + 254 + } else if least_used_color == 0 { + 1 + } else if color_frequencies[(least_used_color - 1) as usize] + < color_frequencies[(least_used_color + 1) as usize] + { + least_used_color - 1 + } else { + least_used_color + 1 }; + + // Strip alpha and replace fully transparent pixels with the chosen color + let paletted: Vec = pixels + .chunks_exact(2) + .map(|pixel| { + let color = pixel[0]; + let alpha = pixel[1]; + if alpha == 0 { + least_used_color + } else if color == least_used_color { + replacement_color + } else { + color + } + }) + .collect(); + + Frame { + width, + height, + buffer: Cow::Owned(paletted), + palette: Some(grayscale_palette), + transparent: Some(least_used_color), + ..Frame::default() + } } /// Creates a frame from a palette and indexed pixels. @@ -263,11 +381,25 @@ /// # Panics: /// * If the length of pixels does not equal `width * height`. /// * If the length of palette > `256 * 3`. - pub fn from_palette_pixels(width: u16, height: u16, pixels: impl Into>, palette: impl Into>, transparent: Option) -> Frame<'static> { + #[track_caller] + pub fn from_palette_pixels( + width: u16, + height: u16, + pixels: impl Into>, + palette: impl Into>, + transparent: Option, + ) -> Self { let pixels = pixels.into(); let palette = palette.into(); - assert_eq!(width as usize * height as usize, pixels.len(), "Too many or too little pixels for the given width and height to create a GIF Frame"); - assert!(palette.len() <= 256*3, "Too many palette values to create a GIF Frame"); + assert_eq!( + width as usize * height as usize, + pixels.len(), + "Too many or too little pixels for the given width and height to create a GIF Frame" + ); + assert!( + palette.len() <= 256 * 3, + "Too many palette values to create a GIF Frame" + ); Frame { width, @@ -283,14 +415,24 @@ /// /// # Panics: /// * If the length of pixels does not equal `width * height`. - pub fn from_indexed_pixels(width: u16, height: u16, pixels: impl Into>, transparent: Option) -> Frame<'static> { + #[track_caller] + pub fn from_indexed_pixels( + width: u16, + height: u16, + pixels: impl Into>, + transparent: Option, + ) -> Self { let pixels = pixels.into(); - assert_eq!(width as usize * height as usize, pixels.len(), "Too many or too little pixels for the given width and height to create a GIF Frame"); + assert_eq!( + width as usize * height as usize, + pixels.len(), + "Too many or too little pixels for the given width and height to create a GIF Frame" + ); Frame { width, height, - buffer: Cow::Owned(pixels.clone()), + buffer: Cow::Owned(pixels), palette: None, transparent, ..Frame::default() @@ -309,7 +451,8 @@ /// * If the length of pixels does not equal `width * height * 3`. #[cfg(feature = "color_quant")] #[must_use] - pub fn from_rgb(width: u16, height: u16, pixels: &[u8]) -> Frame<'static> { + #[track_caller] + pub fn from_rgb(width: u16, height: u16, pixels: &[u8]) -> Self { Frame::from_rgb_speed(width, height, pixels, 1) } @@ -329,10 +472,12 @@ /// * If `speed < 1` or `speed > 30` #[cfg(feature = "color_quant")] #[must_use] - pub fn from_rgb_speed(width: u16, height: u16, pixels: &[u8], speed: i32) -> Frame<'static> { + #[track_caller] + pub fn from_rgb_speed(width: u16, height: u16, pixels: &[u8], speed: i32) -> Self { assert_eq!(width as usize * height as usize * 3, pixels.len(), "Too much or too little pixel data for the given width and height to create a GIF Frame"); let mut vec: Vec = Vec::new(); - vec.try_reserve_exact(pixels.len() + width as usize * height as usize).expect("OOM"); + vec.try_reserve_exact(pixels.len() + width as usize * height as usize) + .expect("OOM"); for v in pixels.chunks_exact(3) { vec.extend_from_slice(&[v[0], v[1], v[2], 0xFF]); } @@ -352,8 +497,8 @@ width: self.width, height: self.height, interlaced: self.interlaced, - palette: std::mem::take(&mut self.palette), - buffer: std::mem::replace(&mut self.buffer, Cow::Borrowed(&[])), + palette: core::mem::take(&mut self.palette), + buffer: core::mem::replace(&mut self.buffer, Cow::Borrowed(&[])), } } } @@ -365,6 +510,6 @@ // Changing .zip(0_u8..) to .zip(0_u8..=255) fixes this issue. fn rgba_speed_avoid_panic_256_colors() { let side = 16; - let pixel_data: Vec = (0..=255).map(|a| vec![a, a, a]).flatten().collect(); + let pixel_data: Vec = (0..=255).flat_map(|a| [a, a, a]).collect(); let _ = Frame::from_rgb(side, side, &pixel_data); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,16 @@ //! # Minimal gif encoder -use std::io; -use std::io::prelude::*; -use std::fmt; + +use alloc::borrow::Cow; +use alloc::fmt; +use alloc::vec::Vec; use std::error; -use std::borrow::Cow; +use std::io; +use std::io::Write; -use weezl::{BitOrder, encode::Encoder as LzwEncoder}; +use weezl::{encode::Encoder as LzwEncoder, BitOrder}; -use crate::traits::WriteBytesExt; use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame}; +use crate::traits::WriteBytesExt; /// The image has incorrect properties, making it impossible to encode as a gif. #[derive(Debug)] @@ -28,15 +30,25 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::TooManyColors => write!(fmt, "the image has too many colors"), - Self::MissingColorPalette => write!(fmt, "the GIF format requires a color palette but none was given"), + Self::MissingColorPalette => write!( + fmt, + "the GIF format requires a color palette but none was given" + ), Self::InvalidMinCodeSize => write!(fmt, "LZW data is invalid"), } } } -#[derive(Debug)] /// Encoding error. +#[derive(Debug)] +#[non_exhaustive] pub enum EncodingError { + /// Frame buffer is too small for the declared dimensions. + FrameBufferTooSmallForDimensions, + /// Failed to internally allocate a buffer of sufficient size. + OutOfMemory, + /// Expected a writer but none found. + WriterNotFound, /// Returned if the to image is not encodable as a gif. Format(EncodingFormatError), /// Wraps `std::io::Error`. @@ -47,8 +59,13 @@ #[cold] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - EncodingError::Io(err) => err.fmt(fmt), - EncodingError::Format(err) => err.fmt(fmt), + Self::FrameBufferTooSmallForDimensions => { + fmt.write_str("Frame Buffer Too Small for Dimensions") + } + Self::OutOfMemory => fmt.write_str("Out of Memory"), + Self::WriterNotFound => fmt.write_str("Writer Not Found"), + Self::Io(err) => err.fmt(fmt), + Self::Format(err) => err.fmt(fmt), } } } @@ -57,8 +74,11 @@ #[cold] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match self { - EncodingError::Io(err) => Some(err), - EncodingError::Format(err) => Some(err), + Self::FrameBufferTooSmallForDimensions => None, + Self::OutOfMemory => None, + Self::WriterNotFound => None, + Self::Io(err) => Some(err), + Self::Format(err) => Some(err), } } } @@ -66,14 +86,14 @@ impl From for EncodingError { #[cold] fn from(err: io::Error) -> Self { - EncodingError::Io(err) + Self::Io(err) } } impl From for EncodingError { #[cold] fn from(err: EncodingFormatError) -> Self { - EncodingError::Format(err) + Self::Format(err) } } @@ -112,19 +132,24 @@ /// Constructor for control extension data. /// /// `delay` is given in units of 10 ms. - #[must_use] pub fn new_control_ext(delay: u16, dispose: DisposalMethod, - needs_user_input: bool, trns: Option) -> ExtensionData { + #[must_use] + pub fn new_control_ext( + delay: u16, + dispose: DisposalMethod, + needs_user_input: bool, + trns: Option, + ) -> Self { let mut flags = 0; let trns = match trns { Some(trns) => { flags |= 1; trns - }, - None => 0 + } + None => 0, }; flags |= u8::from(needs_user_input) << 1; flags |= (dispose as u8) << 2; - ExtensionData::Control { flags, delay, trns } + Self::Control { flags, delay, trns } } } @@ -133,13 +158,20 @@ /// /// `global_palette` gives the global color palette in the format `[r, g, b, ...]`, /// if no global palette shall be used an empty slice may be supplied. - pub fn new(w: W, width: u16, height: u16, global_palette: &[u8]) -> Result { - Encoder { + pub fn new( + w: W, + width: u16, + height: u16, + global_palette: &[u8], + ) -> Result { + Self { w: Some(w), global_palette: false, - width, height, + width, + height, buffer: Vec::new(), - }.write_global_palette(global_palette) + } + .write_global_palette(global_palette) } /// Write an extension block that signals a repeat behaviour. @@ -167,10 +199,16 @@ /// /// Note: This function also writes a control extension if necessary. pub fn write_frame(&mut self, frame: &Frame<'_>) -> Result<(), EncodingError> { - if usize::from(frame.width).checked_mul(usize::from(frame.height)).map_or(true, |size| frame.buffer.len() < size) { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "frame.buffer is too small for its width/height").into()); - } - debug_assert!((frame.width > 0 && frame.height > 0) || frame.buffer.is_empty(), "the frame has 0 pixels, but non-empty buffer"); + if usize::from(frame.width) + .checked_mul(usize::from(frame.height)) + .map_or(true, |size| frame.buffer.len() < size) + { + return Err(EncodingError::FrameBufferTooSmallForDimensions); + } + debug_assert!( + (frame.width > 0 && frame.height > 0) || frame.buffer.is_empty(), + "the frame has 0 pixels, but non-empty buffer" + ); self.write_frame_header(frame)?; self.write_image_block(&frame.buffer) } @@ -189,12 +227,16 @@ let palette = match frame.palette { Some(ref palette) => { flags |= 0b1000_0000; - let (palette, padding, table_size) = Self::check_color_table(&palette)?; + let (palette, padding, table_size) = Self::check_color_table(palette)?; flags |= table_size; Some((palette, padding)) - }, + } None if self.global_palette => None, - _ => return Err(EncodingError::from(EncodingFormatError::MissingColorPalette)) + _ => { + return Err(EncodingError::from( + EncodingFormatError::MissingColorPalette, + )) + } }; let mut tmp = tmp_buf::<10>(); tmp.write_le(Block::Image as u8)?; @@ -213,15 +255,19 @@ fn write_image_block(&mut self, data: &[u8]) -> Result<(), EncodingError> { self.buffer.clear(); - self.buffer.try_reserve(data.len() / 4) - .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + self.buffer + .try_reserve(data.len() / 4) + .map_err(|_| EncodingError::OutOfMemory)?; lzw_encode(data, &mut self.buffer); - let writer = self.w.as_mut().ok_or(io::Error::from(io::ErrorKind::Unsupported))?; + let writer = self.w.as_mut().ok_or(EncodingError::WriterNotFound)?; Self::write_encoded_image_block(writer, &self.buffer) } - fn write_encoded_image_block(writer: &mut W, data_with_min_code_size: &[u8]) -> Result<(), EncodingError> { + fn write_encoded_image_block( + writer: &mut W, + data_with_min_code_size: &[u8], + ) -> Result<(), EncodingError> { let (&min_code_size, data) = data_with_min_code_size.split_first().unwrap_or((&2, &[])); writer.write_le(min_code_size)?; @@ -240,8 +286,12 @@ writer.write_le(0u8).map_err(Into::into) } - fn write_color_table(writer: &mut W, table: &[u8], padding: usize) -> Result<(), EncodingError> { - writer.write_all(&table)?; + fn write_color_table( + writer: &mut W, + table: &[u8], + padding: usize, + ) -> Result<(), EncodingError> { + writer.write_all(table)?; // Waste some space as of gif spec for _ in 0..padding { writer.write_all(&[0, 0, 0])?; @@ -304,7 +354,11 @@ /// This method can be used to write an unsupported extension to the file. `func` is the extension /// identifier (e.g. `Extension::Application as u8`). `data` are the extension payload blocks. If any /// contained slice has a lenght > 255 it is automatically divided into sub-blocks. - pub fn write_raw_extension(&mut self, func: AnyExtension, data: &[&[u8]]) -> io::Result<()> { + pub fn write_raw_extension( + &mut self, + func: AnyExtension, + data: &[&[u8]], + ) -> Result<(), EncodingError> { let writer = self.writer()?; writer.write_le(Block::Extension as u8)?; writer.write_le(func.0)?; @@ -314,7 +368,7 @@ writer.write_all(chunk)?; } } - writer.write_le(0u8) + Ok(writer.write_le(0u8)?) } /// Writes a frame to the image, but expects `Frame.buffer` to contain LZW-encoded data @@ -323,9 +377,11 @@ /// Note: This function also writes a control extension if necessary. pub fn write_lzw_pre_encoded_frame(&mut self, frame: &Frame<'_>) -> Result<(), EncodingError> { // empty data is allowed - if let Some(&min_code_size) = frame.buffer.get(0) { + if let Some(&min_code_size) = frame.buffer.first() { if min_code_size > 11 || min_code_size < 2 { - return Err(EncodingError::Format(EncodingFormatError::InvalidMinCodeSize)); + return Err(EncodingError::Format( + EncodingFormatError::InvalidMinCodeSize, + )); } } @@ -335,7 +391,7 @@ } /// Writes the logical screen desriptor - fn write_screen_desc(&mut self, flags: u8) -> io::Result<()> { + fn write_screen_desc(&mut self, flags: u8) -> Result<(), EncodingError> { let mut tmp = tmp_buf::<13>(); tmp.write_all(b"GIF89a")?; tmp.write_le(self.width)?; @@ -343,7 +399,7 @@ tmp.write_le(flags)?; // packed field tmp.write_le(0u8)?; // bg index tmp.write_le(0u8)?; // aspect ratio - tmp.finish(self.writer()?) + Ok(tmp.finish(self.writer()?)?) } /// Gets a reference to the writer instance used by this encoder. @@ -359,19 +415,19 @@ } /// Finishes writing, and returns the `io::Write` instance used by this encoder - pub fn into_inner(mut self) -> io::Result { + pub fn into_inner(mut self) -> Result { self.write_trailer()?; - self.w.take().ok_or(io::Error::from(io::ErrorKind::Unsupported)) + self.w.take().ok_or(EncodingError::WriterNotFound) } /// Write the final tailer. - fn write_trailer(&mut self) -> io::Result<()> { - self.writer()?.write_le(Block::Trailer as u8) + fn write_trailer(&mut self) -> Result<(), EncodingError> { + Ok(self.writer()?.write_le(Block::Trailer as u8)?) } #[inline] - fn writer(&mut self) -> io::Result<&mut W> { - self.w.as_mut().ok_or(io::Error::from(io::ErrorKind::Unsupported)) + fn writer(&mut self) -> Result<&mut W, EncodingError> { + self.w.as_mut().ok_or(EncodingError::WriterNotFound) } } @@ -389,13 +445,13 @@ } } } - let palette_min_len = max_byte as u32 + 1; + let palette_min_len = u32::from(max_byte) + 1; // As per gif spec: The minimal code size has to be >= 2 let min_code_size = palette_min_len.max(4).next_power_of_two().trailing_zeros() as u8; buffer.push(min_code_size); let mut enc = LzwEncoder::new(BitOrder::Lsb, min_code_size); let len = enc.into_vec(buffer).encode_all(data).consumed_out; - buffer.truncate(len+1); + buffer.truncate(len + 1); } impl Frame<'_> { @@ -437,11 +493,12 @@ // Color table size converted to flag bits fn flag_size(size: usize) -> u8 { - (size.max(2).min(255).next_power_of_two().trailing_zeros()-1) as u8 + (size.clamp(2, 255).next_power_of_two().trailing_zeros() - 1) as u8 } #[test] fn test_flag_size() { + #[rustfmt::skip] fn expected(size: usize) -> u8 { match size { 0 ..=2 => 0, @@ -464,13 +521,17 @@ 1 => 2, n => n, }; - let actual = (i as u32 + 1).max(4).next_power_of_two().trailing_zeros() as u8; + let actual = (u32::from(i) + 1) + .max(4) + .next_power_of_two() + .trailing_zeros() as u8; assert_eq!(actual, expected); } } struct Buf { - buf: [u8; N], pos: usize + buf: [u8; N], + pos: usize, } impl Write for Buf { @@ -478,21 +539,29 @@ fn write(&mut self, buf: &[u8]) -> io::Result { let len = buf.len(); let pos = self.pos; - self.buf[pos.. pos + len].copy_from_slice(buf); + self.buf + .get_mut(pos..pos + len) + .ok_or(io::ErrorKind::WriteZero)? + .copy_from_slice(buf); self.pos += len; Ok(len) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } fn tmp_buf() -> Buf { - Buf { buf: [0; N], pos: 0 } + Buf { + buf: [0; N], + pos: 0, + } } impl Buf { #[inline(always)] - fn finish(&mut self, mut w: impl Write) -> io::Result<()> { + fn finish(&self, mut w: impl Write) -> io::Result<()> { debug_assert_eq!(self.pos, N); w.write_all(&self.buf) } @@ -500,5 +569,7 @@ #[test] fn error_cast() { - let _ : Box = EncodingError::from(EncodingFormatError::MissingColorPalette).into(); + use alloc::boxed::Box; + let _: Box = + EncodingError::from(EncodingFormatError::MissingColorPalette).into(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -111,19 +111,30 @@ // ``` #![deny(missing_docs)] #![cfg(feature = "std")] +#![allow(unknown_lints)] // Certain lints only apply to later versions of Rust +#![allow(clippy::manual_range_contains)] +#![allow(clippy::new_without_default)] +#![deny(clippy::alloc_instead_of_core)] +#![deny(clippy::std_instead_of_alloc)] +#![deny(clippy::std_instead_of_core)] +#![no_std] + +#[macro_use] +extern crate alloc; +extern crate std; -mod traits; mod common; -mod reader; mod encoder; +mod reader; +mod traits; -pub use crate::common::{AnyExtension, Extension, DisposalMethod, Frame}; +pub use crate::common::{AnyExtension, DisposalMethod, Extension, Frame}; -pub use crate::reader::{DecodingError, DecodingFormatError}; pub use crate::reader::{ColorOutput, MemoryLimit}; pub use crate::reader::{DecodeOptions, Decoder, Version}; +pub use crate::reader::{DecodingError, DecodingFormatError}; -pub use crate::encoder::{Encoder, ExtensionData, Repeat, EncodingError, EncodingFormatError}; +pub use crate::encoder::{Encoder, EncodingError, EncodingFormatError, ExtensionData, Repeat}; /// Low-level, advanced decoder. Prefer [`Decoder`] instead, which can stream frames too. pub mod streaming_decoder { @@ -135,7 +146,7 @@ macro_rules! insert_as_doc { { $content:expr } => { #[allow(unused_doc_comments)] - #[doc = $content] extern { } + #[doc = $content] extern "C" { } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/converter.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/converter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/converter.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/converter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,12 @@ -use std::borrow::Cow; -use std::io; -use std::mem; -use std::iter; +use alloc::borrow::Cow; +use alloc::vec::Vec; +use core::iter; +use core::mem; + +use super::decoder::{DecodingError, OutputBuffer, PLTE_CHANNELS}; use crate::common::Frame; use crate::MemoryLimit; -use super::decoder::{ - PLTE_CHANNELS, DecodingError, OutputBuffer -}; - pub(crate) const N_CHANNELS: usize = 4; /// Output mode for the image data @@ -25,47 +23,56 @@ Indexed = 1, } -pub(crate) type FillBufferCallback<'a> = &'a mut dyn FnMut(&mut OutputBuffer<'_>) -> Result; +pub(crate) type FillBufferCallback<'a> = + &'a mut dyn FnMut(&mut OutputBuffer<'_>) -> Result; /// Deinterlaces and expands to RGBA if needed pub(crate) struct PixelConverter { - memory_limit: MemoryLimit, color_output: ColorOutput, buffer: Vec, global_palette: Option>, } impl PixelConverter { - pub(crate) fn new(color_output: ColorOutput, memory_limit: MemoryLimit) -> Self { + pub(crate) const fn new(color_output: ColorOutput) -> Self { Self { - memory_limit, color_output, buffer: Vec::new(), global_palette: None, } } - pub(crate) fn check_buffer_size(&mut self, frame: &Frame<'_>) -> Result { - let pixel_bytes = self.memory_limit + pub(crate) fn check_buffer_size( + &self, + frame: &Frame<'_>, + memory_limit: &MemoryLimit, + ) -> Result { + let pixel_bytes = memory_limit .buffer_size(self.color_output, frame.width, frame.height) - .ok_or_else(|| io::Error::new(io::ErrorKind::OutOfMemory, "image is too large"))?; + .ok_or_else(|| DecodingError::OutOfMemory)?; debug_assert_eq!( - pixel_bytes, self.buffer_size(frame).unwrap(), + pixel_bytes, + self.buffer_size(frame).unwrap(), "Checked computation diverges from required buffer size" ); Ok(pixel_bytes) } #[inline] - pub(crate) fn read_frame(&mut self, frame: &mut Frame<'_>, data_callback: FillBufferCallback<'_>) -> Result<(), DecodingError> { - let pixel_bytes = self.check_buffer_size(frame)?; + pub(crate) fn read_frame( + &mut self, + frame: &mut Frame<'_>, + data_callback: FillBufferCallback<'_>, + memory_limit: &MemoryLimit, + ) -> Result<(), DecodingError> { + let pixel_bytes = self.check_buffer_size(frame, memory_limit)?; let mut vec = match mem::replace(&mut frame.buffer, Cow::Borrowed(&[])) { // reuse buffer if possible without reallocating Cow::Owned(mut vec) if vec.capacity() >= pixel_bytes => { vec.resize(pixel_bytes, 0); vec - }, + } // resizing would realloc anyway, and 0-init is faster than a copy _ => vec![0; pixel_bytes], }; @@ -76,13 +83,13 @@ } #[inline] - pub(crate) fn buffer_size(&self, frame: &Frame<'_>) -> Option { + pub(crate) const fn buffer_size(&self, frame: &Frame<'_>) -> Option { self.line_length(frame).checked_mul(frame.height as usize) } #[inline] - pub(crate) fn line_length(&self, frame: &Frame<'_>) -> usize { - use self::ColorOutput::*; + pub(crate) const fn line_length(&self, frame: &Frame<'_>) -> usize { + use self::ColorOutput::{Indexed, RGBA}; match self.color_output { RGBA => frame.width as usize * N_CHANNELS, Indexed => frame.width as usize, @@ -91,7 +98,12 @@ /// Use `read_into_buffer` to deinterlace #[inline(never)] - pub(crate) fn fill_buffer(&mut self, current_frame: &Frame<'_>, mut buf: &mut [u8], data_callback: FillBufferCallback<'_>) -> Result { + pub(crate) fn fill_buffer( + &mut self, + current_frame: &Frame<'_>, + mut buf: &mut [u8], + data_callback: FillBufferCallback<'_>, + ) -> Result { loop { let decode_into = match self.color_output { // When decoding indexed data, LZW can write the pixels directly @@ -115,27 +127,38 @@ match self.color_output { ColorOutput::RGBA => { let transparent = current_frame.transparent; - let palette: &[u8] = current_frame.palette.as_deref() + let palette: &[u8] = current_frame + .palette + .as_deref() .or(self.global_palette.as_deref()) .unwrap_or_default(); // next_frame_info already checked it won't happen let (pixels, rest) = buf.split_at_mut(bytes_decoded * N_CHANNELS); buf = rest; - for (rgba, idx) in pixels.chunks_exact_mut(N_CHANNELS).zip(self.buffer.iter().copied().take(bytes_decoded)) { + for (rgba, idx) in pixels + .chunks_exact_mut(N_CHANNELS) + .zip(self.buffer.iter().copied().take(bytes_decoded)) + { let plte_offset = PLTE_CHANNELS * idx as usize; - if let Some(colors) = palette.get(plte_offset..plte_offset+PLTE_CHANNELS) { + if let Some(colors) = + palette.get(plte_offset..plte_offset + PLTE_CHANNELS) + { rgba[0] = colors[0]; rgba[1] = colors[1]; rgba[2] = colors[2]; rgba[3] = if let Some(t) = transparent { - if t == idx { 0x00 } else { 0xFF } + if t == idx { + 0x00 + } else { + 0xFF + } } else { 0xFF }; } } - }, + } ColorOutput::Indexed => { buf = &mut buf[bytes_decoded..]; } @@ -143,7 +166,7 @@ if buf.is_empty() { return Ok(true); } - }, + } } } } @@ -163,21 +186,34 @@ /// Applies deinterlacing /// /// Set `frame.interlaced = false` afterwards if you're putting the buffer back into the `Frame` - pub(crate) fn read_into_buffer(&mut self, frame: &Frame<'_>, buf: &mut [u8], data_callback: FillBufferCallback<'_>) -> Result<(), DecodingError> { + pub(crate) fn read_into_buffer( + &mut self, + frame: &Frame<'_>, + buf: &mut [u8], + data_callback: FillBufferCallback<'_>, + ) -> Result<(), DecodingError> { if frame.interlaced { let width = self.line_length(frame); - for row in (InterlaceIterator { len: frame.height, next: 0, pass: 0 }) { + for row in (InterlaceIterator { + len: frame.height, + next: 0, + pass: 0, + }) { // this can't overflow 32-bit, because row never equals (maximum) height let start = row * width; // Handle a too-small buffer and 32-bit usize overflow without panicking - let line = buf.get_mut(start..).and_then(|b| b.get_mut(..width)) + let line = buf + .get_mut(start..) + .and_then(|b| b.get_mut(..width)) .ok_or_else(|| DecodingError::format("buffer too small"))?; if !self.fill_buffer(frame, line, data_callback)? { return Err(DecodingError::format("image truncated")); } } } else { - let buf = self.buffer_size(frame).and_then(|buffer_size| buf.get_mut(..buffer_size)) + let buf = self + .buffer_size(frame) + .and_then(|buffer_size| buf.get_mut(..buffer_size)) .ok_or_else(|| DecodingError::format("buffer too small"))?; if !self.fill_buffer(frame, buf, data_callback)? { return Err(DecodingError::format("image truncated")); @@ -216,8 +252,11 @@ #[cfg(test)] mod test { + use alloc::vec::Vec; + use super::InterlaceIterator; + #[rustfmt::skip] #[test] fn test_interlace_iterator() { for &(len, expect) in &[ @@ -248,7 +287,11 @@ #[test] fn interlace_max() { - let iter = InterlaceIterator { len: 0xFFFF, next: 0, pass: 0 }; + let iter = InterlaceIterator { + len: 0xFFFF, + next: 0, + pass: 0, + }; assert_eq!(65533, iter.last().unwrap()); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,18 +1,20 @@ -use std::borrow::Cow; -use std::cmp; +use alloc::borrow::Cow; +use alloc::boxed::Box; +use alloc::fmt; +use alloc::vec::Vec; +use core::cmp; +use core::default::Default; +use core::mem; +use core::num::NonZeroUsize; + use std::error; -use std::fmt; use std::io; -use std::mem; -use std::default::Default; -use std::num::NonZeroUsize; -use crate::Repeat; -use crate::MemoryLimit; use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame}; use crate::reader::DecodeOptions; +use crate::MemoryLimit; -use weezl::{BitOrder, decode::Decoder as LzwDecoder, LzwError, LzwStatus}; +use weezl::{decode::Decoder as LzwDecoder, BitOrder, LzwError, LzwStatus}; /// GIF palettes are RGB pub const PLTE_CHANNELS: usize = 3; @@ -37,9 +39,22 @@ } } -#[derive(Debug)] /// Decoding error. +#[derive(Debug)] +#[non_exhaustive] pub enum DecodingError { + /// Failed to internally allocate a buffer of sufficient size. + OutOfMemory, + /// Allocation exceeded set memory limit + MemoryLimit, + /// Expected a decoder but none found. + DecoderNotFound, + /// Expected an end-code, but none found. + EndCodeNotFound, + /// Decoding could not complete as the reader completed prematurely. + UnexpectedEof, + /// Error encountered while decoding an LZW stream. + LzwError(LzwError), /// Returned if the image is found to be malformed. Format(DecodingFormatError), /// Wraps `std::io::Error`. @@ -49,7 +64,7 @@ impl DecodingError { #[cold] pub(crate) fn format(err: &'static str) -> Self { - DecodingError::Format(DecodingFormatError { + Self::Format(DecodingFormatError { underlying: err.into(), }) } @@ -59,8 +74,14 @@ #[cold] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - DecodingError::Format(ref d) => d.fmt(fmt), - DecodingError::Io(ref err) => err.fmt(fmt), + Self::OutOfMemory => fmt.write_str("Out of Memory"), + Self::MemoryLimit => fmt.write_str("Memory limit reached"), + Self::DecoderNotFound => fmt.write_str("Decoder Not Found"), + Self::EndCodeNotFound => fmt.write_str("End-Code Not Found"), + Self::UnexpectedEof => fmt.write_str("Unexpected End of File"), + Self::LzwError(ref err) => err.fmt(fmt), + Self::Format(ref d) => d.fmt(fmt), + Self::Io(ref err) => err.fmt(fmt), } } } @@ -69,30 +90,36 @@ #[cold] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { - DecodingError::Format(ref err) => Some(err), - DecodingError::Io(ref err) => Some(err), + Self::OutOfMemory => None, + Self::MemoryLimit => None, + Self::DecoderNotFound => None, + Self::EndCodeNotFound => None, + Self::UnexpectedEof => None, + Self::LzwError(ref err) => Some(err), + Self::Format(ref err) => Some(err), + Self::Io(ref err) => Some(err), } } } -impl From for DecodingError { +impl From for DecodingError { #[inline] - fn from(err: io::Error) -> Self { - DecodingError::Io(err) + fn from(err: LzwError) -> Self { + Self::LzwError(err) } } -impl From for DecodingError { - #[cold] - fn from(err: io::ErrorKind) -> Self { - DecodingError::Io(io::Error::from(err)) +impl From for DecodingError { + #[inline] + fn from(err: io::Error) -> Self { + Self::Io(err) } } impl From for DecodingError { #[inline] fn from(err: DecodingFormatError) -> Self { - DecodingError::Format(err) + Self::Format(err) } } @@ -118,28 +145,21 @@ GlobalPalette(Box<[u8]>), /// Index of the background color in the global palette. BackgroundColor(u8), - /// Loop count is known - Repetitions(Repeat), /// Palette and optional `Application` extension have been parsed, /// reached frame data. HeaderEnd, /// The start of a block. /// `BlockStart(Block::Trailer)` is the very last decode event BlockStart(Block), - /// Decoded a sub-block. More sub-block are available. - /// - /// Indicates the label of the extension which might be unknown. A label of `0` is used when - /// the sub block does not belong to an extension. + /// Decoded a sub-block. /// - /// Call `last_ext()` to get the data - SubBlockFinished(AnyExtension), - /// Decoded the last (or only) sub-block of a block. - /// - /// Indicates the label of the extension which might be unknown. A label of `0` is used when - /// the sub block does not belong to an extension. - /// - /// Call `last_ext()` to get the data - BlockFinished(AnyExtension), + /// Call `last_ext_sub_block()` to get the sub-block data. It won't be available after this event. + SubBlock { + /// An ext label of `0` is used when the sub block does not belong to an extension. + ext: AnyExtension, + /// if true, then no more sub-blocks are available in this block. + is_last: bool, + }, /// Decoded all information of the next frame, except the image data. /// /// The returned frame does **not** contain any owned image data. @@ -157,17 +177,18 @@ /// Internal state of the GIF decoder #[derive(Debug, Copy, Clone)] enum State { - Magic(u8, [u8; 6]), - U16Byte1(U16Value, u8), - U16(U16Value), - Byte(ByteValue), + Magic, + ScreenDescriptor, + ImageBlockStart, GlobalPalette(usize), BlockStart(u8), BlockEnd, - ExtensionBlock(AnyExtension), + ExtensionBlockStart, + /// Resets ext.data + ExtensionDataSubBlockStart(usize), /// Collects data in ext.data - ExtensionDataBlock(usize), - ApplicationExtension, + ExtensionDataSubBlock(usize), + ExtensionBlockEnd, LocalPalette(usize), LzwInit(u8), /// Decompresses LZW @@ -181,41 +202,11 @@ use super::converter::PixelConverter; -/// U16 values that may occur in a GIF image -#[derive(Debug, Copy, Clone)] -enum U16Value { - /// Logical screen descriptor width - ScreenWidth, - /// Logical screen descriptor height - ScreenHeight, - /// Delay time - Delay, - /// Left frame offset - ImageLeft, - /// Top frame offset - ImageTop, - /// Frame width - ImageWidth, - /// Frame height - ImageHeight, -} - -/// Single byte screen descriptor values -#[derive(Debug, Copy, Clone)] -enum ByteValue { - GlobalFlags, - Background { global_flags: u8 }, - AspectRatio { global_flags: u8 }, - ControlFlags, - ImageFlags, - TransparentIdx, - CodeSize, -} - /// Decoder for `Frame::make_lzw_pre_encoded` pub struct FrameDecoder { lzw_reader: LzwReader, pixel_converter: PixelConverter, + memory_limit: MemoryLimit, } impl FrameDecoder { @@ -225,7 +216,8 @@ pub fn new(options: DecodeOptions) -> Self { Self { lzw_reader: LzwReader::new(options.check_for_end_code), - pixel_converter: PixelConverter::new(options.color_output, options.memory_limit), + pixel_converter: PixelConverter::new(options.color_output), + memory_limit: options.memory_limit.clone(), } } @@ -240,7 +232,9 @@ /// If you get an error about invalid min code size, the buffer was probably pixels, not compressed data. #[inline] pub fn decode_lzw_encoded_frame(&mut self, frame: &mut Frame<'_>) -> Result<(), DecodingError> { - let pixel_bytes = self.pixel_converter.check_buffer_size(frame)?; + let pixel_bytes = self + .pixel_converter + .check_buffer_size(frame, &self.memory_limit)?; let mut vec = vec![0; pixel_bytes]; self.decode_lzw_encoded_frame_into_buffer(frame, &mut vec)?; frame.buffer = Cow::Owned(vec); @@ -251,19 +245,22 @@ /// Converts into the given buffer. It must be [`buffer_size()`] bytes large. /// /// Pixels are always deinterlaced, so update `frame.interlaced` afterwards if you're putting the buffer back into the frame. - pub fn decode_lzw_encoded_frame_into_buffer(&mut self, frame: &Frame<'_>, buf: &mut [u8]) -> Result<(), DecodingError> { + pub fn decode_lzw_encoded_frame_into_buffer( + &mut self, + frame: &Frame<'_>, + buf: &mut [u8], + ) -> Result<(), DecodingError> { let (&min_code_size, mut data) = frame.buffer.split_first().unwrap_or((&2, &[])); self.lzw_reader.reset(min_code_size)?; let lzw_reader = &mut self.lzw_reader; - self.pixel_converter.read_into_buffer(frame, buf, &mut move |out| { - loop { - let (bytes_read, bytes_written) = lzw_reader.decode_bytes(data, out)?; - data = &data.get(bytes_read..).unwrap_or_default(); - if bytes_written > 0 || bytes_read == 0 || data.is_empty() { - return Ok(bytes_written) + self.pixel_converter + .read_into_buffer(frame, buf, &mut move |out| loop { + let (bytes_read, bytes_written, status) = lzw_reader.decode_bytes(data, out)?; + data = data.get(bytes_read..).unwrap_or_default(); + if bytes_written > 0 || matches!(status, LzwStatus::NoProgress) { + return Ok(bytes_written); } - } - })?; + })?; Ok(()) } @@ -307,7 +304,10 @@ self.min_code_size = min_code_size; self.decoder = Some(LzwDecoder::new(BitOrder::Lsb, min_code_size)); } else { - self.decoder.as_mut().ok_or_else(|| DecodingError::format("bad state"))?.reset(); + self.decoder + .as_mut() + .ok_or_else(|| DecodingError::format("bad state"))? + .reset(); } Ok(()) @@ -317,29 +317,43 @@ self.decoder.as_ref().map_or(true, |e| e.has_ended()) } - pub fn decode_bytes(&mut self, lzw_data: &[u8], decode_buffer: &mut OutputBuffer<'_>) -> io::Result<(usize, usize)> { - let decoder = self.decoder.as_mut().ok_or(io::ErrorKind::Unsupported)?; - - let decode_buffer = match decode_buffer { - OutputBuffer::Slice(buf) => &mut **buf, - OutputBuffer::None => &mut [], - OutputBuffer::Vec(_) => return Err(io::Error::from(io::ErrorKind::Unsupported)), + pub fn decode_bytes( + &mut self, + lzw_data: &[u8], + decode_buffer: &mut OutputBuffer<'_>, + ) -> Result<(usize, usize, LzwStatus), DecodingError> { + let decoder = self + .decoder + .as_mut() + .ok_or(DecodingError::DecoderNotFound)?; + + let (status, consumed_in, consumed_out) = match decode_buffer { + OutputBuffer::Slice(buf) => { + let decoded = decoder.decode_bytes(lzw_data, buf); + (decoded.status, decoded.consumed_in, decoded.consumed_out) + } + OutputBuffer::None => { + let decoded = decoder.decode_bytes(lzw_data, &mut []); + (decoded.status, decoded.consumed_in, decoded.consumed_out) + } + OutputBuffer::Vec(buf) => { + let decoded = decoder.into_vec(buf).decode(lzw_data); + (decoded.status, decoded.consumed_in, decoded.consumed_out) + } }; - let decoded = decoder.decode_bytes(lzw_data, decode_buffer); - - match decoded.status { - Ok(LzwStatus::Done | LzwStatus::Ok) => {}, - Ok(LzwStatus::NoProgress) => { + let status = match status? { + ok @ LzwStatus::Done | ok @ LzwStatus::Ok => ok, + ok @ LzwStatus::NoProgress => { if self.check_for_end_code { - return Err(io::Error::new(io::ErrorKind::InvalidData, "no end code in lzw stream")); + return Err(DecodingError::EndCodeNotFound); } - }, - Err(err @ LzwError::InvalidCode) => { - return Err(io::Error::new(io::ErrorKind::InvalidData, err)); + + ok } - } - Ok((decoded.consumed_in, decoded.consumed_out)) + }; + + Ok((consumed_in, consumed_out, status)) } } @@ -348,6 +362,9 @@ /// To just get GIF frames, use [`crate::Decoder`] instead. pub struct StreamingDecoder { state: State, + /// Input bytes are collected here if `update` got `buf` smaller than the minimum required + internal_buffer: [u8; 9], + unused_internal_buffer_len: u8, lzw_reader: LzwReader, skip_frame_decoding: bool, check_frame_consistency: bool, @@ -357,7 +374,6 @@ width: u16, height: u16, global_color_table: Vec, - background_color: [u8; 4], /// ext buffer ext: ExtensionData, /// Frame data @@ -378,7 +394,6 @@ struct ExtensionData { id: AnyExtension, data: Vec, - is_block_end: bool, } /// Destination to write to for `StreamingDecoder::update` @@ -391,24 +406,27 @@ None, } -impl<'a> OutputBuffer<'a> { - fn append(&mut self, buf: &[u8], memory_limit: &MemoryLimit) -> Result<(usize, usize), DecodingError> { +impl OutputBuffer<'_> { + fn append( + &mut self, + buf: &[u8], + memory_limit: &MemoryLimit, + ) -> Result<(usize, usize), DecodingError> { let (consumed, copied) = match self { OutputBuffer::Slice(slice) => { let len = cmp::min(buf.len(), slice.len()); slice[..len].copy_from_slice(&buf[..len]); (len, len) - }, + } OutputBuffer::Vec(vec) => { let vec: &mut Vec = vec; let len = buf.len(); - memory_limit.check_size(vec.len() + len)?; - vec.try_reserve(len).map_err(|_| io::ErrorKind::OutOfMemory)?; + memory_limit.try_reserve(vec, len)?; if vec.capacity() - vec.len() >= len { vec.extend_from_slice(buf); } (len, len) - }, + } // It's valid that bytes are discarded. For example, // when using next_frame_info() with skip_frame_decoding to only get metadata. OutputBuffer::None => (buf.len(), 0), @@ -420,14 +438,16 @@ impl StreamingDecoder { /// Creates a new streaming decoder #[must_use] - pub fn new() -> StreamingDecoder { + pub fn new() -> Self { let options = DecodeOptions::new(); Self::with_options(&options) } pub(crate) fn with_options(options: &DecodeOptions) -> Self { - StreamingDecoder { - state: Magic(0, [0; 6]), + Self { + internal_buffer: [0; 9], + unused_internal_buffer_len: 0, + state: Magic, lzw_reader: LzwReader::new(options.check_for_end_code), skip_frame_decoding: options.skip_frame_decoding, check_frame_consistency: options.check_frame_consistency, @@ -437,11 +457,9 @@ width: 0, height: 0, global_color_table: Vec::new(), - background_color: [0, 0, 0, 0xFF], ext: ExtensionData { id: AnyExtension(0), data: Vec::with_capacity(256), // 0xFF + 1 byte length - is_block_end: true, }, current: None, header_end_reached: false, @@ -452,8 +470,8 @@ /// /// Returns the number of bytes consumed from the input buffer /// and the last decoding result. - pub fn update<'a>( - &'a mut self, + pub fn update( + &mut self, mut buf: &[u8], write_into: &mut OutputBuffer<'_>, ) -> Result<(usize, Decoded), DecodingError> { @@ -462,19 +480,20 @@ let (bytes, decoded) = self.next_state(buf, write_into)?; buf = buf.get(bytes..).unwrap_or_default(); match decoded { - Decoded::Nothing => {}, + Decoded::Nothing => {} result => { - return Ok((len-buf.len(), result)); - }, + return Ok((len - buf.len(), result)); + } }; } Ok((len - buf.len(), Decoded::Nothing)) } - /// Returns the data of the last extension that has been decoded. + /// Data of the last extension sub block that has been decoded. + /// You need to concatenate all subblocks together to get the overall block content. #[must_use] - pub fn last_ext(&self) -> (AnyExtension, &[u8], bool) { - (self.ext.id, &self.ext.data, self.ext.is_block_end) + pub fn last_ext_sub_block(&mut self) -> &[u8] { + &self.ext.data } /// Current frame info as a mutable ref. @@ -494,7 +513,9 @@ /// Current frame info as a mutable ref. #[inline(always)] fn try_current_frame(&mut self) -> Result<&mut Frame<'static>, DecodingError> { - self.current.as_mut().ok_or_else(|| DecodingError::format("bad state")) + self.current + .as_mut() + .ok_or_else(|| DecodingError::format("bad state")) } /// Width of the image @@ -519,7 +540,11 @@ } #[inline] - fn next_state(&mut self, buf: &[u8], write_into: &mut OutputBuffer<'_>) -> Result<(usize, Decoded), DecodingError> { + fn next_state( + &mut self, + buf: &[u8], + write_into: &mut OutputBuffer<'_>, + ) -> Result<(usize, Decoded), DecodingError> { macro_rules! goto ( ($n:expr, $state:expr) => ({ self.state = $state; @@ -539,114 +564,117 @@ }) ); - let b = *buf.get(0).ok_or(io::ErrorKind::UnexpectedEof)?; - - match self.state { - Magic(i, mut version) => if i < 6 { - version[i as usize] = b; - goto!(Magic(i+1, version)) - } else if &version[..3] == b"GIF" { - self.version = match &version[3..] { - b"87a" => Version::V87a, - b"89a" => Version::V89a, - _ => return Err(DecodingError::format("malformed GIF header")) - }; - goto!(U16Byte1(U16Value::ScreenWidth, b)) - } else { - Err(DecodingError::format("malformed GIF header")) - }, - Byte(value) => { - use self::ByteValue::*; - match value { - GlobalFlags => { - goto!(Byte(Background { global_flags: b })) - }, - Background { global_flags } => { - goto!( - Byte(AspectRatio { global_flags }), - emit Decoded::BackgroundColor(b) - ) - }, - AspectRatio { global_flags } => { - let global_table = global_flags & 0x80 != 0; - let table_size = if global_table { - let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize); - self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::ErrorKind::OutOfMemory)?; - table_size + macro_rules! ensure_min_length_buffer ( + ($required:expr) => ({ + let required: usize = $required; + if buf.len() >= required && self.unused_internal_buffer_len == 0 { + (required, &buf[..required]) + } else { + let has = usize::from(self.unused_internal_buffer_len); + let mut consumed = 0; + if has < required { + let to_copy = buf.len().min(required - has); + let new_len = has + to_copy; + self.internal_buffer[has .. new_len].copy_from_slice(&buf[..to_copy]); + consumed += to_copy; + if new_len < required { + self.unused_internal_buffer_len = new_len as u8; + return Ok((consumed, Decoded::Nothing)); } else { - 0usize - }; - goto!(GlobalPalette(table_size)) - }, - ControlFlags => { - self.ext.data.push(b); - let frame = self.try_current_frame()?; - let control_flags = b; - if control_flags & 1 != 0 { - // Set to Some(...), gets overwritten later - frame.transparent = Some(0); + self.unused_internal_buffer_len = 0; } - frame.needs_user_input = - control_flags & 0b10 != 0; - frame.dispose = match DisposalMethod::from_u8( - (control_flags & 0b11100) >> 2 - ) { - Some(method) => method, - None => DisposalMethod::Any - }; - goto!(U16(U16Value::Delay)) - } - TransparentIdx => { - self.ext.data.push(b); - if let Some(ref mut idx) = self.try_current_frame()?.transparent { - *idx = b; - } - goto!(ExtensionDataBlock(0)) } - ImageFlags => { - let local_table = (b & 0b1000_0000) != 0; - let interlaced = (b & 0b0100_0000) != 0; - let table_size = b & 0b0000_0111; - let check_frame_consistency = self.check_frame_consistency; - let (width, height) = (self.width, self.height); - - let frame = self.try_current_frame()?; - - frame.interlaced = interlaced; - if check_frame_consistency { - // Consistency checks. - if width.checked_sub(frame.width) < Some(frame.left) - || height.checked_sub(frame.height) < Some(frame.top) - { - return Err(DecodingError::format("frame descriptor is out-of-bounds")) - } - } + (consumed, &self.internal_buffer[..required]) + } + }) + ); - if local_table { - let entries = PLTE_CHANNELS * (1 << (table_size + 1)); - let mut pal = Vec::new(); - pal.try_reserve_exact(entries).map_err(|_| io::ErrorKind::OutOfMemory)?; - frame.palette = Some(pal); - goto!(LocalPalette(entries)) - } else { - goto!(Byte(CodeSize)) - } + let b = *buf.first().ok_or(DecodingError::UnexpectedEof)?; + + match self.state { + Magic => { + let (consumed, version) = ensure_min_length_buffer!(6); + + self.version = match version { + b"GIF87a" => Version::V87a, + b"GIF89a" => Version::V89a, + _ => return Err(DecodingError::format("malformed GIF header")), + }; + + goto!(consumed, ScreenDescriptor) + } + ScreenDescriptor => { + let (consumed, desc) = ensure_min_length_buffer!(7); + + self.width = u16::from_le_bytes(desc[..2].try_into().unwrap()); + self.height = u16::from_le_bytes(desc[2..4].try_into().unwrap()); + let global_flags = desc[4]; + let background_color = desc[5]; + + let global_table = global_flags & 0x80 != 0; + let table_size = if global_table { + let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize); + self.global_color_table + .try_reserve_exact(table_size) + .map_err(|_| DecodingError::OutOfMemory)?; + table_size + } else { + 0usize + }; + + goto!( + consumed, + GlobalPalette(table_size), + emit Decoded::BackgroundColor(background_color) + ) + } + ImageBlockStart => { + let (consumed, header) = ensure_min_length_buffer!(9); + + let frame = self + .current + .as_mut() + .ok_or_else(|| DecodingError::format("bad state"))?; + frame.left = u16::from_le_bytes(header[..2].try_into().unwrap()); + frame.top = u16::from_le_bytes(header[2..4].try_into().unwrap()); + frame.width = u16::from_le_bytes(header[4..6].try_into().unwrap()); + frame.height = u16::from_le_bytes(header[6..8].try_into().unwrap()); + + let flags = header[8]; + frame.interlaced = (flags & 0b0100_0000) != 0; + + if self.check_frame_consistency { + // Consistency checks. + if self.width.checked_sub(frame.width) < Some(frame.left) + || self.height.checked_sub(frame.height) < Some(frame.top) + { + return Err(DecodingError::format("frame descriptor is out-of-bounds")); } - CodeSize => goto!(LzwInit(b)), + } + + let local_table = (flags & 0b1000_0000) != 0; + if local_table { + let table_size = flags & 0b0000_0111; + let pal_len = PLTE_CHANNELS * (1 << (table_size + 1)); + frame + .palette + .get_or_insert_with(Vec::new) + .try_reserve_exact(pal_len) + .map_err(|_| DecodingError::OutOfMemory)?; + goto!(consumed, LocalPalette(pal_len)) + } else { + goto!(consumed, LocalPalette(0)) } } GlobalPalette(left) => { - let n = cmp::min(left, buf.len()); + // the global_color_table is guaranteed to have the exact capacity required if left > 0 { - self.global_color_table.extend_from_slice(&buf[..n]); + let n = cmp::min(left, buf.len()); + if n <= self.global_color_table.capacity() - self.global_color_table.len() { + self.global_color_table.extend_from_slice(&buf[..n]); + } goto!(n, GlobalPalette(left - n)) } else { - let idx = self.background_color[0]; - match self.global_color_table.chunks_exact(PLTE_CHANNELS).nth(idx as usize) { - Some(chunk) => self.background_color[..PLTE_CHANNELS] - .copy_from_slice(&chunk[..PLTE_CHANNELS]), - None => self.background_color[0] = 0 - } goto!(BlockStart(b), emit Decoded::GlobalPalette( mem::take(&mut self.global_color_table).into_boxed_slice() )) @@ -661,10 +689,16 @@ match Block::from_u8(type_) { Some(Block::Image) => { self.add_frame(); - goto!(U16Byte1(U16Value::ImageLeft, b), emit Decoded::BlockStart(Block::Image)) + goto!(0, ImageBlockStart, emit Decoded::BlockStart(Block::Image)) } Some(Block::Extension) => { - goto!(ExtensionBlock(AnyExtension(b)), emit Decoded::BlockStart(Block::Extension)) + self.ext.id = AnyExtension(b); + if !self.allow_unknown_blocks && self.ext.id.into_known().is_none() { + return Err(DecodingError::format( + "unknown extension block encountered", + )); + } + goto!(ExtensionBlockStart) } Some(Block::Trailer) => { // The `Trailer` is the final state, and isn't reachable without extraneous data after the end of file @@ -672,13 +706,21 @@ } None => { if self.allow_unknown_blocks { - goto!(ExtensionDataBlock(b as usize)) + self.ext.id = AnyExtension(0); + goto!(0, ExtensionBlockStart) } else { Err(DecodingError::format("unknown block type encountered")) } } } - }, + } + ExtensionBlockStart => { + goto!(ExtensionDataSubBlockStart(b as usize), emit Decoded::BlockStart(Block::Extension)) + } + ExtensionBlockEnd => { + self.ext.data.clear(); + goto!(0, BlockEnd) + } BlockEnd => { if b == Block::Trailer as u8 { // can't consume yet, because the trailer is not a real block, @@ -688,60 +730,35 @@ goto!(BlockStart(b)) } } - ExtensionBlock(id) => { - use Extension::*; - self.ext.id = id; + ExtensionDataSubBlockStart(sub_block_len) => { self.ext.data.clear(); - self.ext.data.push(b); - if let Some(ext) = Extension::from_u8(id.0) { - match ext { - Control => { - goto!(self.read_control_extension(b)?) - } - Text | Comment | Application => { - goto!(ExtensionDataBlock(b as usize)) - } - } - } else { - Err(DecodingError::format("unknown block type encountered")) - } + goto!(0, ExtensionDataSubBlock(sub_block_len)) } - ExtensionDataBlock(left) => { + ExtensionDataSubBlock(left) => { if left > 0 { let n = cmp::min(left, buf.len()); - self.memory_limit.check_size(self.ext.data.len() + n)?; - self.ext.data.try_reserve(n).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + let needs_to_grow = + n > self.ext.data.capacity().wrapping_sub(self.ext.data.len()); + if needs_to_grow { + return Err(DecodingError::OutOfMemory); + } self.ext.data.extend_from_slice(&buf[..n]); - goto!(n, ExtensionDataBlock(left - n)) + goto!(n, ExtensionDataSubBlock(left - n)) } else if b == 0 { - self.ext.is_block_end = true; - if self.ext.id.into_known() == Some(Extension::Application) { - goto!(0, ApplicationExtension, emit Decoded::BlockFinished(self.ext.id)) - } else { - goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id)) + if self.ext.id.into_known() == Some(Extension::Control) { + self.read_control_extension()?; } + goto!(ExtensionBlockEnd, emit Decoded::SubBlock { ext: self.ext.id, is_last: true }) } else { - self.ext.is_block_end = false; - goto!(ExtensionDataBlock(b as usize), emit Decoded::SubBlockFinished(self.ext.id)) - } - } - ApplicationExtension => { - debug_assert_eq!(0, b); - // the parser removes sub-block lenghts, so app name and data are concatenated - if self.ext.data.len() >= 15 && &self.ext.data[1..13] == b"NETSCAPE2.0\x01" { - let repeat = &self.ext.data[13..15]; - let repeat = u16::from(repeat[0]) | u16::from(repeat[1]) << 8; - goto!(BlockEnd, emit Decoded::Repetitions(if repeat == 0 { Repeat::Infinite } else { Repeat::Finite(repeat) })) - } else { - goto!(BlockEnd) + goto!(ExtensionDataSubBlockStart(b as usize), emit Decoded::SubBlock { ext: self.ext.id, is_last: false }) } } LocalPalette(left) => { - let n = cmp::min(left, buf.len()); if left > 0 { + let n = cmp::min(left, buf.len()); let src = &buf[..n]; if let Some(pal) = self.try_current_frame()?.palette.as_mut() { - // capacity has already been reserved in ImageFlags + // capacity has already been reserved in ImageBlockStart if pal.capacity() - pal.len() >= src.len() { pal.extend_from_slice(src); } @@ -781,10 +798,11 @@ return goto!(n, DecodeSubBlock(left - n), emit Decoded::Nothing); } - let (mut consumed, bytes_len) = self.lzw_reader.decode_bytes(&buf[..n], write_into)?; + let (mut consumed, bytes_len, status) = + self.lzw_reader.decode_bytes(&buf[..n], write_into)?; // skip if can't make progress (decode would fail if check_for_end_code was set) - if consumed == 0 && bytes_len == 0 { + if matches!(status, LzwStatus::NoProgress) { consumed = n; } @@ -794,22 +812,23 @@ Decoded::Nothing }; goto!(consumed, DecodeSubBlock(left - consumed), emit decoded) - } else if b != 0 { // decode next sub-block + } else if b != 0 { + // decode next sub-block goto!(DecodeSubBlock(b as usize)) } else { - let (_, bytes_len) = self.lzw_reader.decode_bytes(&[], write_into)?; + let (_, bytes_len, status) = self.lzw_reader.decode_bytes(&[], write_into)?; if let Some(bytes_len) = NonZeroUsize::new(bytes_len) { goto!(0, DecodeSubBlock(0), emit Decoded::BytesDecoded(bytes_len)) + } else if matches!(status, LzwStatus::Ok) { + goto!(0, DecodeSubBlock(0), emit Decoded::Nothing) + } else if matches!(status, LzwStatus::Done) { + goto!(0, FrameDecoded) } else { goto!(0, FrameDecoded) } } } - U16(next) => goto!(U16Byte1(next, b)), - U16Byte1(next, value) => { - goto!(self.read_second_byte(next, value, b)?) - } FrameDecoded => { // end of image data reached self.current = None; @@ -820,50 +839,22 @@ } } - fn read_second_byte(&mut self, next: U16Value, value: u8, b: u8) -> Result { - use self::U16Value::*; - let value = (u16::from(b) << 8) | u16::from(value); - Ok(match (next, value) { - (ScreenWidth, width) => { - self.width = width; - U16(U16Value::ScreenHeight) - }, - (ScreenHeight, height) => { - self.height = height; - Byte(ByteValue::GlobalFlags) - }, - (Delay, delay) => { - self.try_current_frame()?.delay = delay; - self.ext.data.push(value as u8); - self.ext.data.push(b); - Byte(ByteValue::TransparentIdx) - }, - (ImageLeft, left) => { - self.try_current_frame()?.left = left; - U16(U16Value::ImageTop) - }, - (ImageTop, top) => { - self.try_current_frame()?.top = top; - U16(U16Value::ImageWidth) - }, - (ImageWidth, width) => { - self.try_current_frame()?.width = width; - U16(U16Value::ImageHeight) - }, - (ImageHeight, height) => { - self.try_current_frame()?.height = height; - Byte(ByteValue::ImageFlags) - } - }) - } - - fn read_control_extension(&mut self, b: u8) -> Result { - self.add_frame(); - self.ext.data.push(b); - if b != 4 { + fn read_control_extension(&mut self) -> Result<(), DecodingError> { + if self.ext.data.len() != 4 { return Err(DecodingError::format("control extension has wrong length")); } - Ok(Byte(ByteValue::ControlFlags)) + let control = &self.ext.data; + + let frame = self.current.get_or_insert_with(Frame::default); + let control_flags = control[0]; + frame.needs_user_input = control_flags & 0b10 != 0; + frame.dispose = match DisposalMethod::from_u8((control_flags & 0b11100) >> 2) { + Some(method) => method, + None => DisposalMethod::Any, + }; + frame.delay = u16::from_le_bytes(control[1..3].try_into().unwrap()); + frame.transparent = (control_flags & 1 != 0).then_some(control[3]); + Ok(()) } fn add_frame(&mut self) { @@ -875,5 +866,5 @@ #[test] fn error_cast() { - let _ : Box = DecodingError::format("testing").into(); + let _: Box = DecodingError::format("testing").into(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/reader/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/reader/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,25 +1,25 @@ -use std::borrow::Cow; +use alloc::borrow::Cow; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; +use core::iter::FusedIterator; +use core::mem; +use core::num::NonZeroU64; use std::io; -use std::iter::FusedIterator; -use std::mem; - use std::io::prelude::*; -use std::num::NonZeroU64; -use std::convert::{TryFrom, TryInto}; -use crate::Repeat; use crate::common::{Block, Frame}; +use crate::{AnyExtension, Extension, Repeat}; -mod decoder; mod converter; +mod decoder; pub use self::decoder::{ - PLTE_CHANNELS, StreamingDecoder, Decoded, DecodingError, DecodingFormatError, - Version, FrameDataType, OutputBuffer, FrameDecoder + Decoded, DecodingError, DecodingFormatError, FrameDataType, FrameDecoder, OutputBuffer, + StreamingDecoder, Version, PLTE_CHANNELS, }; -use self::converter::PixelConverter; pub use self::converter::ColorOutput; +use self::converter::PixelConverter; #[derive(Clone, Debug)] /// The maximum amount of memory the decoder is allowed to use for each frame @@ -49,14 +49,14 @@ impl MemoryLimit { fn check_size(&self, size: usize) -> Result<(), DecodingError> { match self { - MemoryLimit::Unlimited => Ok(()), - MemoryLimit::Bytes(limit) => { + Self::Unlimited => Ok(()), + Self::Bytes(limit) => { if size as u64 <= limit.get() { Ok(()) } else { - Err(DecodingError::format("memory limit reached")) + Err(DecodingError::MemoryLimit) } - }, + } } } @@ -75,16 +75,28 @@ let usize_bytes = usize::try_from(total_bytes).ok()?; match self { - MemoryLimit::Unlimited => Some(usize_bytes), - MemoryLimit::Bytes(limit) => { + Self::Unlimited => Some(usize_bytes), + Self::Bytes(limit) => { if total_bytes > limit.get() { None } else { Some(usize_bytes) } - }, + } } } + + #[inline] + fn try_reserve(&self, vec: &mut Vec, additional: usize) -> Result<(), DecodingError> { + let len = vec + .len() + .checked_add(additional) + .ok_or(DecodingError::MemoryLimit)?; + self.check_size(len)?; + vec.try_reserve(additional) + .map_err(|_| DecodingError::OutOfMemory)?; + Ok(()) + } } /// Options for opening a GIF decoder. [`DecodeOptions::read_info`] will start the decoder. @@ -108,8 +120,8 @@ /// Creates a new decoder builder #[must_use] #[inline] - pub fn new() -> DecodeOptions { - DecodeOptions { + pub fn new() -> Self { + Self { memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), // 50 MB color_output: ColorOutput::Indexed, check_frame_consistency: false, @@ -182,6 +194,10 @@ /// or `Trailer` block. Otherwise, the decoded image will return an error. /// If an unknown block error is returned from decoding, enabling this /// setting may allow for a further state of decoding on the next attempt. + /// + /// This option also allows unknown extension blocks. The decoder assumes the follow the same + /// block layout, i.e. a sequence of zero-length terminated sub-blocks immediately follow the + /// extension introducer. pub fn allow_unknown_blocks(&mut self, check: bool) { self.allow_unknown_blocks = check; } @@ -202,12 +218,15 @@ impl ReadDecoder { #[inline(never)] - fn decode_next(&mut self, write_into: &mut OutputBuffer<'_>) -> Result, DecodingError> { + fn decode_next( + &mut self, + write_into: &mut OutputBuffer<'_>, + ) -> Result, DecodingError> { while !self.at_eof { let (consumed, result) = { let buf = self.reader.fill_buf()?; if buf.is_empty() { - return Err(io::ErrorKind::UnexpectedEof.into()); + return Err(DecodingError::UnexpectedEof); } self.decoder.update(buf, write_into)? @@ -217,8 +236,8 @@ Decoded::Nothing => (), Decoded::BlockStart(Block::Trailer) => { self.at_eof = true; - }, - result => return Ok(Some(result)) + } + result => return Ok(Some(result)), } } Ok(None) @@ -236,19 +255,42 @@ } } } +/// Headers for supported extensions. +const EXT_NAME_NETSCAPE: &[u8] = b"NETSCAPE2.0"; +const EXT_NAME_XMP: &[u8] = b"XMP DataXMP"; +const EXT_NAME_ICC: &[u8] = b"ICCRGBG1012"; + +/// State when parsing application extension +enum AppExtensionState { + /// Waiting for app name + None, + Netscape, + Xmp, + Icc, + Skip, +} #[allow(dead_code)] /// GIF decoder. Create [`DecodeOptions`] to get started, and call [`DecodeOptions::read_info`]. pub struct Decoder { decoder: ReadDecoder, pixel_converter: PixelConverter, + memory_limit: MemoryLimit, bg_color: Option, repeat: Repeat, current_frame: Frame<'static>, current_frame_data_type: FrameDataType, + app_extension_state: AppExtensionState, + /// XMP metadata bytes. + xmp_metadata: Option>, + /// ICC profile bytes. + icc_profile: Option>, } -impl Decoder where R: Read { +impl Decoder +where + R: Read, +{ /// Create a new decoder with default options. #[inline] pub fn new(reader: R) -> Result { @@ -262,22 +304,27 @@ DecodeOptions::new() } - fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Decoder { - Decoder { + fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Self { + Self { decoder: ReadDecoder { reader: io::BufReader::new(reader), decoder, at_eof: false, }, bg_color: None, - pixel_converter: PixelConverter::new(options.color_output, options.memory_limit), + pixel_converter: PixelConverter::new(options.color_output), + memory_limit: options.memory_limit.clone(), repeat: Repeat::default(), current_frame: Frame::default(), current_frame_data_type: FrameDataType::Pixels, + app_extension_state: AppExtensionState::None, + xmp_metadata: None, + icc_profile: None, } } fn init(mut self) -> Result { + const APP_EXTENSION: AnyExtension = AnyExtension(Extension::Application as u8); loop { match self.decoder.decode_next(&mut OutputBuffer::None)? { Some(Decoded::BackgroundColor(bg_color)) => { @@ -285,20 +332,23 @@ } Some(Decoded::GlobalPalette(palette)) => { self.pixel_converter.set_global_palette(palette.into()); - }, - Some(Decoded::Repetitions(repeat)) => { - self.repeat = repeat; - }, - Some(Decoded::HeaderEnd) => { - break - }, + } + Some(Decoded::SubBlock { + ext: APP_EXTENSION, + is_last, + }) => { + self.read_application_extension(is_last)?; + } + Some(Decoded::HeaderEnd) => break, Some(_) => { // There will be extra events when parsing application extension - continue - }, - None => return Err(DecodingError::format( - "file does not contain any image data" - )) + continue; + } + None => { + return Err(DecodingError::format( + "file does not contain any image data", + )) + } } } // If the background color is invalid, ignore it @@ -310,6 +360,74 @@ Ok(self) } + fn read_application_extension(&mut self, is_last: bool) -> Result<(), DecodingError> { + let data = self.decoder.decoder.last_ext_sub_block(); + match self.app_extension_state { + AppExtensionState::None => { + // GIF spec requires len == 11 + self.app_extension_state = match data { + EXT_NAME_NETSCAPE => AppExtensionState::Netscape, + EXT_NAME_XMP => { + self.xmp_metadata = Some(Vec::new()); + AppExtensionState::Xmp + } + EXT_NAME_ICC => { + self.icc_profile = Some(Vec::new()); + AppExtensionState::Icc + } + _ => AppExtensionState::Skip, + } + } + AppExtensionState::Netscape => { + if let [1, rest @ ..] = data { + if let Ok(repeat) = rest.try_into().map(u16::from_le_bytes) { + self.repeat = if repeat == 0 { + Repeat::Infinite + } else { + Repeat::Finite(repeat) + }; + } + } + self.app_extension_state = AppExtensionState::Skip; + } + AppExtensionState::Xmp => { + if let Some(xmp_metadata) = &mut self.xmp_metadata { + // XMP is not written as a valid "pascal-string", so we need to stitch together + // the text from our collected sublock-lengths. + self.memory_limit + .try_reserve(xmp_metadata, 1 + data.len())?; + xmp_metadata.push(data.len() as u8); + xmp_metadata.extend_from_slice(data); + if is_last { + // XMP adds a "ramp" of 257 bytes to the end of the metadata to let the "pascal-strings" + // parser converge to the null byte. The ramp looks like "0x01, 0xff, .., 0x01, 0x00". + // For convenience and to allow consumers to not be bothered with this implementation detail, + // we cut the ramp. + const RAMP_SIZE: usize = 257; + if xmp_metadata.len() >= RAMP_SIZE + && xmp_metadata.ends_with(&[0x03, 0x02, 0x01, 0x00]) + && xmp_metadata[xmp_metadata.len() - RAMP_SIZE..] + .starts_with(&[0x01, 0x0ff]) + { + xmp_metadata.truncate(xmp_metadata.len() - RAMP_SIZE); + } + } + } + } + AppExtensionState::Icc => { + if let Some(icc) = &mut self.icc_profile { + self.memory_limit.try_reserve(icc, data.len())?; + icc.extend_from_slice(data); + } + } + AppExtensionState::Skip => {} + }; + if is_last { + self.app_extension_state = AppExtensionState::None; + } + Ok(()) + } + /// Returns the next frame info pub fn next_frame_info(&mut self) -> Result>, DecodingError> { loop { @@ -331,6 +449,17 @@ Ok(Some(&self.current_frame)) } + /// Query information about the frame previously advanced with [`Self::next_frame_info`]. + /// + /// Returns `None` past the end of file. + pub fn current_frame_info(&self) -> Option<&Frame<'static>> { + if self.decoder.at_eof { + None + } else { + Some(&self.current_frame) + } + } + /// Reads the next frame from the image. /// /// Do not call `Self::next_frame_info` beforehand. @@ -338,25 +467,35 @@ /// /// You can also call `.into_iter()` on the decoder to use it as a regular iterator. pub fn read_next_frame(&mut self) -> Result>, DecodingError> { - if let Some(_) = self.next_frame_info()? { + if self.next_frame_info()?.is_some() { match self.current_frame_data_type { FrameDataType::Pixels => { - self.pixel_converter.read_frame(&mut self.current_frame, &mut |out| self.decoder.decode_next_bytes(out))?; - }, + self.pixel_converter.read_frame( + &mut self.current_frame, + &mut |out| self.decoder.decode_next_bytes(out), + &self.memory_limit, + )?; + } FrameDataType::Lzw { min_code_size } => { let mut vec = if matches!(self.current_frame.buffer, Cow::Owned(_)) { - let mut vec = mem::replace(&mut self.current_frame.buffer, Cow::Borrowed(&[])).into_owned(); + let mut vec = + mem::replace(&mut self.current_frame.buffer, Cow::Borrowed(&[])) + .into_owned(); vec.clear(); vec } else { Vec::new() }; // Guesstimate 2bpp - vec.try_reserve(usize::from(self.current_frame.width) * usize::from(self.current_frame.height) / 4) - .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + vec.try_reserve( + usize::from(self.current_frame.width) + * usize::from(self.current_frame.height) + / 4, + ) + .map_err(|_| DecodingError::OutOfMemory)?; self.copy_lzw_into_buffer(min_code_size, &mut vec)?; self.current_frame.buffer = Cow::Owned(vec); - }, + } } Ok(Some(&self.current_frame)) } else { @@ -378,15 +517,22 @@ /// The length of `buf` must be at least `Self::buffer_size`. /// Deinterlaces the result. pub fn read_into_buffer(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> { - self.pixel_converter.read_into_buffer(&mut self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out)) + self.pixel_converter + .read_into_buffer(&self.current_frame, buf, &mut |out| { + self.decoder.decode_next_bytes(out) + }) } - fn copy_lzw_into_buffer(&mut self, min_code_size: u8, buf: &mut Vec) -> Result<(), DecodingError> { + fn copy_lzw_into_buffer( + &mut self, + min_code_size: u8, + buf: &mut Vec, + ) -> Result<(), DecodingError> { // `write_lzw_pre_encoded_frame` smuggles `min_code_size` in the first byte. buf.push(min_code_size); loop { match self.decoder.decode_next(&mut OutputBuffer::Vec(buf))? { - Some(Decoded::LzwDataCopied(_len)) => {}, + Some(Decoded::LzwDataCopied(_len)) => {} Some(Decoded::DataEnd) => return Ok(()), _ => return Err(DecodingError::format("unexpected data")), } @@ -401,12 +547,17 @@ /// `Self::next_frame_info` needs to be called beforehand. Returns `true` if the supplied /// buffer could be filled completely. Should not be called after `false` had been returned. pub fn fill_buffer(&mut self, buf: &mut [u8]) -> Result { - self.pixel_converter.fill_buffer(&mut self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out)) + self.pixel_converter + .fill_buffer(&self.current_frame, buf, &mut |out| { + self.decoder.decode_next_bytes(out) + }) } /// Output buffer size pub fn buffer_size(&self) -> usize { - self.pixel_converter.buffer_size(&self.current_frame).unwrap() + self.pixel_converter + .buffer_size(&self.current_frame) + .unwrap() } /// Line length of the current frame @@ -419,9 +570,9 @@ pub fn palette(&self) -> Result<&[u8], DecodingError> { Ok(match self.current_frame.palette { Some(ref table) => table, - None => self.global_palette().ok_or(DecodingError::format( - "no color table available for current frame", - ))?, + None => self.global_palette().ok_or_else(|| { + DecodingError::format("no color table available for current frame") + })?, }) } @@ -442,6 +593,20 @@ self.decoder.decoder.height() } + /// XMP metadata stored in the image. + #[inline] + #[must_use] + pub fn xmp_metadata(&self) -> Option<&[u8]> { + self.xmp_metadata.as_deref() + } + + /// ICC profile stored in the image. + #[inline] + #[must_use] + pub fn icc_profile(&self) -> Option<&[u8]> { + self.icc_profile.as_deref() + } + /// Abort decoding and recover the `io::Read` instance pub fn into_inner(self) -> io::BufReader { self.decoder.into_inner() @@ -502,11 +667,11 @@ Ok(None) => { self.ended = true; None - }, + } Err(err) => { self.ended = true; Some(Err(err)) - }, + } } } else { None diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/gif/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/gif/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/gif/src/traits.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/gif/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -24,22 +24,20 @@ impl WriteBytesExt for W { #[inline] fn write_le(&mut self, n: u16) -> io::Result<()> { - self.write_all(&[n as u8, (n >> 8) as u8]) + self.write_all(&n.to_le_bytes()) } } impl WriteBytesExt for W { #[inline] fn write_le(&mut self, n: u32) -> io::Result<()> { - self.write_le(n as u16)?; - self.write_le((n >> 16) as u16) + self.write_all(&n.to_le_bytes()) } } impl WriteBytesExt for W { #[inline] fn write_le(&mut self, n: u64) -> io::Result<()> { - self.write_le(n as u32)?; - self.write_le((n >> 32) as u32) + self.write_all(&n.to_le_bytes()) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/glob/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/glob/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"6791dcdd292ecaeeec9535afae7189026dca9d8486211acd27208673edfa995a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"3482ed957e7e22efdf5f368d92c497b932c665bce3ad17db8ec31c1007164539","src/lib.rs":"b2f3c3f48eb07f1767a7e5bb02847d10e02655f1dbf57281eb63fd001427e28b","tests/glob-std.rs":"b0a0aa11d7b8cc2cc0216fb117a543d6e584eec8b51173994dfd19761ab00a62","triagebot.toml":"a135e10c777cd13459559bdf74fb704c1379af7c9b0f70bc49fa6f5a837daa81"},"package":"d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"0c95f31b9a69e964907a3eadec0a30b10d7d6ea95ff1ed8d57429df484dea818",".github/workflows/rust.yml":"ff5d6a8ed87ba97fd1a1fb281b5005d4daf7929c25082aefbd826ccf62a214f9","Cargo.toml":"6791dcdd292ecaeeec9535afae7189026dca9d8486211acd27208673edfa995a","Cargo.toml.orig":"da7804fe4f301691ddc657c229b0406ce33e9abf56dc7d2163c3a4ae7f0fc864","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"3482ed957e7e22efdf5f368d92c497b932c665bce3ad17db8ec31c1007164539","src/lib.rs":"b2f3c3f48eb07f1767a7e5bb02847d10e02655f1dbf57281eb63fd001427e28b","tests/glob-std.rs":"b0a0aa11d7b8cc2cc0216fb117a543d6e584eec8b51173994dfd19761ab00a62","triagebot.toml":"a135e10c777cd13459559bdf74fb704c1379af7c9b0f70bc49fa6f5a837daa81"},"package":"d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/glob/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/glob/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/glob/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "408e579f74830c2073180a7e4e214a2677d38a49" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/glob/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/glob/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/glob/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/glob/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +name: Continuous integration + +on: + pull_request: + push: + branches: + - master + +jobs: + os_tests: + name: "Tests / OS: ${{ matrix.os }} - ${{ matrix.channel }}" + runs-on: ${{ matrix.os }} + strategy: + matrix: + channel: + - stable + - beta + - nightly + - 1.23.0 + os: + # FIXME: compiling with 1.23 on macOS 12 fails to linL + # archive member 'rust.metadata.bin' with length 40821 is not mach-o or llvm bitcode file + - macos-11 + - windows-2022 + - ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Update rust + run: rustup update ${{ matrix.channel }} --no-self-update + + - name: Tests + run: cargo +${{ matrix.channel }} test --all diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/glob/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/glob/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/glob/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/glob/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +[package] + +name = "glob" +version = "0.3.1" +authors = ["The Rust Project Developers"] +license = "MIT OR Apache-2.0" +homepage = "https://github.com/rust-lang/glob" +repository = "https://github.com/rust-lang/glob" +documentation = "https://docs.rs/glob/0.3.1" +description = """ +Support for matching file paths against Unix shell style patterns. +""" +categories = ["filesystem"] + +[dev-dependencies] +tempdir = "0.3" +doc-comment = "0.3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/half/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/half/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"b8b6451c21361c8e4397c3e730c77c3ecd4d74f97d2c043cd9c7232e4bfea84a","Cargo.toml":"ae446aae10cf2bab51ec7f442be490da352349e830198e152f7cd867aea9a9d5","LICENSE":"36bb253818ac13761081556ff5c457d626da9df1eb4f56194d9ad3926c418a68","LICENSES/Apache-2.0.txt":"074e6e32c86a4c0ef8b3ed25b721ca23aca83df277cd88106ef7177c354615ff","LICENSES/MIT.txt":"b85dcd3e453d05982552c52b5fc9e0bdd6d23c6f8e844b984a88af32570b0cc0","Makefile.toml":"4787032fbaa47e82cb436de7b21614426c71f1ba31c4abd6a95e96772d738010","README.md":"e50b3c803ab2143a84a0c669301e69d5aca62d44335c821e6692d01bd4ddbe74","benches/convert.rs":"b5d320abfa395b014385c172a27c77ab669a23113ec9eee62e21bac7cbc1ce6d","src/bfloat.rs":"0b9fbd2662f6db0604236f29b982868d60f7dbe79bfae4a593f059197ee98d52","src/bfloat/convert.rs":"77cdca97ea63d693371b8bab8f4e12f0a066d8e02313e0c8ae0e1d538a0b9c4e","src/binary16.rs":"4d7b0f42598100c547fcf7eae255e3f2115a1adcf83305e7ce70adc4799586a0","src/binary16/arch.rs":"01d93995fa17887bbe1d3d3ec4da6daacf9a36f07bf75495443bbfa81c79f764","src/binary16/arch/aarch64.rs":"0678e02c03aa8acb53bb154d16edc93850f059a2d4ad285ab4e5d1ad8dc2a508","src/binary16/arch/x86.rs":"fa89187b4412fe20529f80cc85d030bde1d4ca784714b6c2885134c89154cf7f","src/leading_zeros.rs":"2578faaea742a2f522bc62783a304c0a1a492d1bf3f2dea0bafac26639183370","src/lib.rs":"7aec7794cbd99621a1daf0a306e7bba70ec265900823c36d2e36d936164b6422","src/num_traits.rs":"59ec779bc1c2ede142e5f6fb317164bab9a816e9321d5f3f795f109d36432390","src/rand_distr.rs":"5a4e8a9b6d26a8955edeadc7061205fc60f837b088c129ece7dffe38c647b066","src/slice.rs":"f739f09bf4b8f912b35472668744bb0884191d972ea98fa72860943e57e8ec1d","src/vec.rs":"7763d1485d4c96f562ccde9058ef4fdc484f630704e50a2ba4c514d72a4fcbad"},"package":"6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"71924d837808c0118914a693d91a98d79f47f8f2b1ce5ba20fb6590110eacdb0",".reuse/dep5":"7aa615df0376504c0dfa905f81759d00e64155345640a802db721b72ad4ec19e","CHANGELOG.md":"b8b6451c21361c8e4397c3e730c77c3ecd4d74f97d2c043cd9c7232e4bfea84a","Cargo.toml":"ae446aae10cf2bab51ec7f442be490da352349e830198e152f7cd867aea9a9d5","Cargo.toml.orig":"87f197890b2d124af25b224a376c880fdfd21b51b5cab31f077be042c08d3d99","LICENSE":"36bb253818ac13761081556ff5c457d626da9df1eb4f56194d9ad3926c418a68","LICENSES/Apache-2.0.txt":"074e6e32c86a4c0ef8b3ed25b721ca23aca83df277cd88106ef7177c354615ff","LICENSES/MIT.txt":"b85dcd3e453d05982552c52b5fc9e0bdd6d23c6f8e844b984a88af32570b0cc0","Makefile.toml":"4787032fbaa47e82cb436de7b21614426c71f1ba31c4abd6a95e96772d738010","README.md":"e50b3c803ab2143a84a0c669301e69d5aca62d44335c821e6692d01bd4ddbe74","benches/convert.rs":"b5d320abfa395b014385c172a27c77ab669a23113ec9eee62e21bac7cbc1ce6d","src/bfloat.rs":"0b9fbd2662f6db0604236f29b982868d60f7dbe79bfae4a593f059197ee98d52","src/bfloat/convert.rs":"77cdca97ea63d693371b8bab8f4e12f0a066d8e02313e0c8ae0e1d538a0b9c4e","src/binary16.rs":"4d7b0f42598100c547fcf7eae255e3f2115a1adcf83305e7ce70adc4799586a0","src/binary16/arch.rs":"01d93995fa17887bbe1d3d3ec4da6daacf9a36f07bf75495443bbfa81c79f764","src/binary16/arch/aarch64.rs":"0678e02c03aa8acb53bb154d16edc93850f059a2d4ad285ab4e5d1ad8dc2a508","src/binary16/arch/x86.rs":"fa89187b4412fe20529f80cc85d030bde1d4ca784714b6c2885134c89154cf7f","src/leading_zeros.rs":"2578faaea742a2f522bc62783a304c0a1a492d1bf3f2dea0bafac26639183370","src/lib.rs":"7aec7794cbd99621a1daf0a306e7bba70ec265900823c36d2e36d936164b6422","src/num_traits.rs":"59ec779bc1c2ede142e5f6fb317164bab9a816e9321d5f3f795f109d36432390","src/rand_distr.rs":"5a4e8a9b6d26a8955edeadc7061205fc60f837b088c129ece7dffe38c647b066","src/slice.rs":"f739f09bf4b8f912b35472668744bb0884191d972ea98fa72860943e57e8ec1d","src/vec.rs":"7763d1485d4c96f562ccde9058ef4fdc484f630704e50a2ba4c514d72a4fcbad"},"package":"6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/half/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/half/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/half/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "b2c5209f437fbe189e7e1533b3919a596f4a8dc5" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/half/.reuse/dep5 clamav-1.4.6+dfsg/.cargo/vendor/half/.reuse/dep5 --- clamav-1.4.3+dfsg/.cargo/vendor/half/.reuse/dep5 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/half/.reuse/dep5 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Copyright: Kathryn Long +License: MIT OR Apache-2.0 + +Files: * +Copyright: 2021 Kathryn Long +License: MIT OR Apache-2.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/half/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/half/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/half/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/half/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +[package] +name = "half" +# Remember to keep in sync with html_root_url crate attribute +version = "2.4.1" +authors = ["Kathryn Long "] +description = "Half-precision floating point f16 and bf16 types for Rust implementing the IEEE 754-2008 standard binary16 and bfloat16 types." +repository = "https://github.com/starkat99/half-rs" +readme = "README.md" +keywords = ["f16", "bfloat16", "no_std"] +license = "MIT OR Apache-2.0" +categories = ["no-std", "data-structures", "encoding"] +edition = "2021" +rust-version = "1.70" +exclude = [".git*", ".editorconfig", ".circleci"] + +[features] +default = ["std"] +std = ["alloc"] +use-intrinsics = [] # Deprecated +alloc = [] +rand_distr = ["dep:rand", "dep:rand_distr"] + +[dependencies] +cfg-if = "1.0.0" +bytemuck = { version = "1.4.1", default-features = false, features = [ + "derive", +], optional = true } +serde = { version = "1.0", default-features = false, features = [ + "derive", +], optional = true } +num-traits = { version = "0.2.14", default-features = false, features = [ + "libm", +], optional = true } +zerocopy = { version = "0.6.0", default-features = false, optional = true } +rand = { version = "0.8.5", default-features = false, optional = true } +rand_distr = { version = "0.4.3", default-features = false, optional = true } +rkyv = { version = "0.7", optional = true } + +[target.'cfg(target_arch = "spirv")'.dependencies] +crunchy = "0.2.2" + +[dev-dependencies] +criterion = "0.4.0" +quickcheck = "1.0" +quickcheck_macros = "1.0" +rand = "0.8.5" +crunchy = "0.2.2" + +[[bench]] +name = "convert" +harness = false + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] +all-features = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"ade49a29d368e16ce508aee91b477ecbad7e2e52eb6fee7b4c1fc86199963f0e","Cargo.toml":"421b3a71d97faf0a7e52c3b2bfbe0f1c036b9dbf6232b4e5b41221bb54358f5a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"a536b3bb3f3521e59836080f05a4783150fa8484f759a31468ce3b6dba1f33eb","benches/bench.rs":"aadc39d815eadf094ed9357d946319df2d93194203bbccb7c33cea6951d654df","benches/insert_unique_unchecked.rs":"cb84275f22d5f95a5ac995ac6b2df74ffcf342765b401d27c95f2955c7b7cb9f","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"ba105bf0853ebc45157f22116ad0f55d3bdab75e721d8e7a677c7b912d0c0c6d","src/external_trait_impls/rayon/map.rs":"2809e2a0071db8101c38789deb955f3830c5c3455eb1794ff64a0cf2ceb53fc7","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"e62c5f3ca5fffea47357e64b6f8c34cec94af62d9bd28a2b87934da46c22b66e","src/external_trait_impls/rayon/set.rs":"c4c44d44e56c2f59e9e1355662e29d8744ac96645ca4414127a359fb46cb0fbf","src/external_trait_impls/serde.rs":"0bc1a1f218d1ae7a5262557a5e3737b9334caf7d50c136dbdc75ff75680c223b","src/lib.rs":"c82fbee9684bfff40ef55d5f0c9f855c11f71f9fd1720fb084ef8331bdbc41d8","src/macros.rs":"36fe532656879c80f7753d13354b889f5b45caef451a1bb3a27dbc32d74c9878","src/map.rs":"df39edae67c569378dea9a4d928685cb4d06569712c6ac36a54df76fb5d87fe3","src/raw/alloc.rs":"184a0345bc2c7544b65c28724063be26b1f2b28dbaaa028a0b01192ccac25557","src/raw/bitmask.rs":"820d90b19b7e3433a1048ace008c9526331cd53a576cb0cfc1ff9960b6fe52f8","src/raw/generic.rs":"f5013a50d6d82d5cc8bad8b8c26c24d00fa810197f9f123256c58ac92e0d98f9","src/raw/mod.rs":"fa38247c6b3bd70636be50400debb9966a3446d49ee13e4f4e2dfe4ceed1b201","src/raw/sse2.rs":"838cfdb1daa1e70951ed25f985283b8b7ab4b46fa130f92eda152047ce6086f6","src/rustc_entry.rs":"cdd70972cba5b79ca1cad79869cb5e184d6dc4798ef90822e966ef89679ba011","src/scopeguard.rs":"d13de1b12897add7fe1c3eba6f906c9cc09d86509b6cfe06b95d63803fe9265c","src/set.rs":"6877d4a42eeadd681e3b8881528e4b20f14cfedbc11e9318bfcf425ef96d1546","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"83d5289771542203f539a41cccb889fbe7ce70f5adf5b903ac9f051e3ba13cfa","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"01cf39efb04646ef4c63a809ebb96dfa63cfec472bf8bdb6c121f6526d40c40e"},"package":"8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"480bba3005be9515acc4df53efd4060d17fa8560b5f467ad7d6e87c844650019","CHANGELOG.md":"ade49a29d368e16ce508aee91b477ecbad7e2e52eb6fee7b4c1fc86199963f0e","Cargo.toml":"421b3a71d97faf0a7e52c3b2bfbe0f1c036b9dbf6232b4e5b41221bb54358f5a","Cargo.toml.orig":"9f31637058f15f6c44a1d6fb955f3567440d2edf82fa923ec7abd1e48be67739","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"a536b3bb3f3521e59836080f05a4783150fa8484f759a31468ce3b6dba1f33eb","benches/bench.rs":"aadc39d815eadf094ed9357d946319df2d93194203bbccb7c33cea6951d654df","benches/insert_unique_unchecked.rs":"cb84275f22d5f95a5ac995ac6b2df74ffcf342765b401d27c95f2955c7b7cb9f","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"ba105bf0853ebc45157f22116ad0f55d3bdab75e721d8e7a677c7b912d0c0c6d","src/external_trait_impls/rayon/map.rs":"2809e2a0071db8101c38789deb955f3830c5c3455eb1794ff64a0cf2ceb53fc7","src/external_trait_impls/rayon/mod.rs":"156de9c1ad0123334ea3b7e5a17444faf1b8bf971aa88a1f23e2f2d1c3021141","src/external_trait_impls/rayon/raw.rs":"e62c5f3ca5fffea47357e64b6f8c34cec94af62d9bd28a2b87934da46c22b66e","src/external_trait_impls/rayon/set.rs":"c4c44d44e56c2f59e9e1355662e29d8744ac96645ca4414127a359fb46cb0fbf","src/external_trait_impls/serde.rs":"0bc1a1f218d1ae7a5262557a5e3737b9334caf7d50c136dbdc75ff75680c223b","src/lib.rs":"c82fbee9684bfff40ef55d5f0c9f855c11f71f9fd1720fb084ef8331bdbc41d8","src/macros.rs":"36fe532656879c80f7753d13354b889f5b45caef451a1bb3a27dbc32d74c9878","src/map.rs":"df39edae67c569378dea9a4d928685cb4d06569712c6ac36a54df76fb5d87fe3","src/raw/alloc.rs":"184a0345bc2c7544b65c28724063be26b1f2b28dbaaa028a0b01192ccac25557","src/raw/bitmask.rs":"820d90b19b7e3433a1048ace008c9526331cd53a576cb0cfc1ff9960b6fe52f8","src/raw/generic.rs":"f5013a50d6d82d5cc8bad8b8c26c24d00fa810197f9f123256c58ac92e0d98f9","src/raw/mod.rs":"fa38247c6b3bd70636be50400debb9966a3446d49ee13e4f4e2dfe4ceed1b201","src/raw/sse2.rs":"838cfdb1daa1e70951ed25f985283b8b7ab4b46fa130f92eda152047ce6086f6","src/rustc_entry.rs":"cdd70972cba5b79ca1cad79869cb5e184d6dc4798ef90822e966ef89679ba011","src/scopeguard.rs":"d13de1b12897add7fe1c3eba6f906c9cc09d86509b6cfe06b95d63803fe9265c","src/set.rs":"6877d4a42eeadd681e3b8881528e4b20f14cfedbc11e9318bfcf425ef96d1546","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"83d5289771542203f539a41cccb889fbe7ce70f5adf5b903ac9f051e3ba13cfa","tests/serde.rs":"6bac8054db722dd049901b37a6e006535bac30f425eb5cd91af19b5bc1dfe78e","tests/set.rs":"01cf39efb04646ef4c63a809ebb96dfa63cfec472bf8bdb6c121f6526d40c40e"},"package":"8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "1d2c1a81d1b53285decbd64410a21a90112613d7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/hashbrown/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hashbrown/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +[package] +name = "hashbrown" +version = "0.12.3" +authors = ["Amanieu d'Antras "] +description = "A Rust port of Google's SwissTable hash map" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/hashbrown" +readme = "README.md" +keywords = ["hash", "no_std", "hashmap", "swisstable"] +categories = ["data-structures", "no-std"] +exclude = [".github", "/ci/*"] +edition = "2021" +rust-version = "1.56.0" + +[dependencies] +# For the default hasher +ahash = { version = "0.7.0", default-features = false, optional = true } + +# For external trait impls +rayon = { version = "1.0", optional = true } +serde = { version = "1.0.25", default-features = false, optional = true } + +# When built as part of libstd +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +compiler_builtins = { version = "0.1.2", optional = true } +alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } + +# Optional support for bumpalo +bumpalo = { version = "3.5.0", optional = true } + +[dev-dependencies] +lazy_static = "1.4" +rand = { version = "0.8.3", features = ["small_rng"] } +rayon = "1.0" +fnv = "1.0.7" +serde_test = "1.0" +doc-comment = "0.3.1" + +[features] +default = ["ahash", "inline-more"] + +ahash-compile-time-rng = ["ahash/compile-time-rng"] +nightly = [] +rustc-internal-api = [] +rustc-dep-of-std = [ + "nightly", + "core", + "compiler_builtins", + "alloc", + "rustc-internal-api", +] +raw = [] + +# Enables usage of `#[inline]` on far more functions than by default in this +# crate. This may lead to a performance increase but often comes at a compile +# time cost. +inline-more = [] + +[package.metadata.docs.rs] +features = ["nightly", "rayon", "serde", "raw"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/heck/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/heck/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"be2b711f318b4447b7c0fa067ac1804dff0b01894d2782722646910a6b2c4b10","Cargo.toml":"bef2e967708cafccb70a6de0f2eeed8914f9a58c1fc9094cf0e6bde671768f7b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"a53c56a404fa7b97e4a5426798430186e715fcf38480327d42700494cae70f76","src/kebab.rs":"f2a4900541fe36584b0705108f5f1d23501bcb3429fffe04106077baecc6dc5a","src/lib.rs":"6cf5759deb604eb1035061ed52c1f71a629ac3fa6faefecceeb9d3cb9f4a9919","src/lower_camel.rs":"24a3ea7ce7f765b27fb0adec207498569f27045edc56c9089ae05fc428c54d5f","src/shouty_kebab.rs":"4516fbb2295c400869221912257828c90e7c0d43f3bdf4aaefb6d384606f4866","src/shouty_snake.rs":"01b8c1e7ac5e680827e2744e62bf4704fc7ebd0d555c5b040bca5f5fb50e4ffd","src/snake.rs":"fc69443dd1a9248667484d5feb52911a1c6dfed1442b01b5b23e371c5b716a5e","src/title.rs":"0cc0b3014559ab6047ed9e7afb624bbe97014a4498297a4c3b28f3410b75d1dc","src/train.rs":"6d20c7153b2e574653c57d039a5077c707c4f15e5b8be765bd5042a4dabc32d4","src/upper_camel.rs":"9cb094ade94cf6212a4b6e491b0fdad92ad8fbb0d55095c70691f9d66ce25366"},"package":"95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"b97d0ec2b50fa9c7df03d29849722043453f113a2c0fe0ebe6bcbb1ea5d17a76","CHANGELOG.md":"be2b711f318b4447b7c0fa067ac1804dff0b01894d2782722646910a6b2c4b10","Cargo.toml":"bef2e967708cafccb70a6de0f2eeed8914f9a58c1fc9094cf0e6bde671768f7b","Cargo.toml.orig":"8ff4ce2f2ce7dd637a1c4be3d2f87bef6c21811a980acd4418e7e9f52091e331","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"a53c56a404fa7b97e4a5426798430186e715fcf38480327d42700494cae70f76","src/kebab.rs":"f2a4900541fe36584b0705108f5f1d23501bcb3429fffe04106077baecc6dc5a","src/lib.rs":"6cf5759deb604eb1035061ed52c1f71a629ac3fa6faefecceeb9d3cb9f4a9919","src/lower_camel.rs":"24a3ea7ce7f765b27fb0adec207498569f27045edc56c9089ae05fc428c54d5f","src/shouty_kebab.rs":"4516fbb2295c400869221912257828c90e7c0d43f3bdf4aaefb6d384606f4866","src/shouty_snake.rs":"01b8c1e7ac5e680827e2744e62bf4704fc7ebd0d555c5b040bca5f5fb50e4ffd","src/snake.rs":"fc69443dd1a9248667484d5feb52911a1c6dfed1442b01b5b23e371c5b716a5e","src/title.rs":"0cc0b3014559ab6047ed9e7afb624bbe97014a4498297a4c3b28f3410b75d1dc","src/train.rs":"6d20c7153b2e574653c57d039a5077c707c4f15e5b8be765bd5042a4dabc32d4","src/upper_camel.rs":"9cb094ade94cf6212a4b6e491b0fdad92ad8fbb0d55095c70691f9d66ce25366"},"package":"95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/heck/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/heck/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/heck/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "76a8274f948fbe3551413dc09026b733aca71995" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/heck/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/heck/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/heck/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/heck/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +[package] +authors = ["Without Boats "] +name = "heck" +version = "0.4.1" +edition = "2018" +license = "MIT OR Apache-2.0" +description = "heck is a case conversion library." +homepage = "https://github.com/withoutboats/heck" +repository = "https://github.com/withoutboats/heck" +documentation = "https://docs.rs/heck" +keywords = ["string", "case", "camel", "snake", "unicode"] +readme = "README.md" +include = ["src/**/*", "LICENSE-*", "README.md", "CHANGELOG.md"] + +[features] +default = [] +unicode = ["unicode-segmentation"] + +[dependencies] +unicode-segmentation = { version = "1.2.0", optional = true } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/hex/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"85a822957796d1aa30bd28d695fae3dc86ca8832d6879a8f71e323cc4a130174","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f7bdb3426d045cd50efd4953026e3eb5a83d0199f458a075602611b9344da5b9","README.md":"ec487a539f41489876f5f2143e6f2071754ad96b1ca74092bdeab8135f6a819e","benches/hex.rs":"17f5081cc970fc5a0e7bf7e781da066ece95c4453b46ad8c129e665b19733885","src/error.rs":"489873510e45802b3b1858668daf46eb559cf0d0cebb41ca34cf5879dabe730e","src/lib.rs":"bc16c851822629225d2d2653ea080f131b0f2c4704d3ff27fed955c9b8b42f71","src/serde.rs":"d1297456aa4e9e11eb45ac41fb7b9d7d88b7de371a118e4c100bd78fc208ea86","tests/serde.rs":"567b0b58d9d1fac12b4ebb7bff6164bdef01b7c9edc59435a2d7507214c6481b","tests/version-number.rs":"913773b7a6b62c6fbea14f155571eb77c2ae8b0ac811dde8e028dee25a4155be"},"package":"7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"99b421178459616d6bf8286229acf14f20221fc9e6e7d7a74541ff980798ccb5",".github/workflows/rust.yml":"ee65195fe2a52ffe4b70c20f1e53913516e73ff7f4aed5ee85f1389590b89186",".gitlab-ci.yml":"2e80da9bfd343ab2406fb099be07f5086a19b79e4f3781143f7af895171acec6",".travis.yml":"71c9f9bd2f1104528ef6a098806a3305c4787b2383d4d53b989c40560bda692e","Cargo.toml":"85a822957796d1aa30bd28d695fae3dc86ca8832d6879a8f71e323cc4a130174","Cargo.toml.orig":"129b27aacc44d45c6439469e998065432b86c7e2a25a0928639e34e8da5a9da0","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f7bdb3426d045cd50efd4953026e3eb5a83d0199f458a075602611b9344da5b9","README.md":"ec487a539f41489876f5f2143e6f2071754ad96b1ca74092bdeab8135f6a819e","benches/hex.rs":"17f5081cc970fc5a0e7bf7e781da066ece95c4453b46ad8c129e665b19733885","src/error.rs":"489873510e45802b3b1858668daf46eb559cf0d0cebb41ca34cf5879dabe730e","src/lib.rs":"bc16c851822629225d2d2653ea080f131b0f2c4704d3ff27fed955c9b8b42f71","src/serde.rs":"d1297456aa4e9e11eb45ac41fb7b9d7d88b7de371a118e4c100bd78fc208ea86","tests/serde.rs":"567b0b58d9d1fac12b4ebb7bff6164bdef01b7c9edc59435a2d7507214c6481b","tests/version-number.rs":"913773b7a6b62c6fbea14f155571eb77c2ae8b0ac811dde8e028dee25a4155be"},"package":"7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/hex/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "b2b4370b5bf021b98ee7adc92233e8de3f2de792" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/hex/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/hex/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/.github/workflows/rust.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,32 @@ +name: Test hex +on: [push, pull_request] + +env: + RUST_BACKTRACE: '1' + RUSTFLAGS: -D warnings + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + # We want the tests to run on all configurations, even if jobs (like on nightly), fail. + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + rust: [stable, beta, nightly] + + steps: + - uses: actions/checkout@v2 + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose + - name: Run tests [no-default-features] + run: cargo test --verbose --no-default-features + - name: Run tests [serde] + run: cargo test --verbose --features serde + - name: Validate benches still work + run: cargo bench --all -- --test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/.gitlab-ci.yml clamav-1.4.6+dfsg/.cargo/vendor/hex/.gitlab-ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/hex/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/.gitlab-ci.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,47 @@ +stages: + - compile + - test + +compile: + stage: compile + image: liuchong/rustup:$RUST_VERSION + script: + - cargo build + cache: + key: "$CI_COMMIT_REF_SLUG:$RUST_VERSION" + paths: + - target/ + parallel: + matrix: + - RUST_VERSION: + - stable + - stable-musl + - beta + - beta-musl + - nightly + - nightly-musl + +test: + stage: test + image: liuchong/rustup:$RUST_VERSION + script: + - cargo test + - cargo test --no-default-features + - cargo test --no-default-features --features alloc + - cargo test --no-default-features --features std + - cargo test --no-default-features --features serde + cache: + key: "$CI_COMMIT_REF_SLUG:$RUST_VERSION" + paths: + - target/ + needs: + - compile + parallel: + matrix: + - RUST_VERSION: + - stable + - stable-musl + - beta + - beta-musl + - nightly + - nightly-musl diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/hex/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/hex/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/.travis.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,32 @@ +language: rust +os: + - linux + - windows + - osx +rust: + - stable + - beta + - nightly +env: + global: + - RUST_BACKTRACE=1 + - RUSTFLAGS="-D warnings" +matrix: + allow_failures: + - rust: nightly + +install: + - if [[ $TRAVIS_RUST_VERSION == "stable" && $TRAVIS_OS_NAME == "linux" ]]; then rustup component add rustfmt; fi + - if [[ $TRAVIS_RUST_VERSION == "stable" && $TRAVIS_OS_NAME == "linux" ]]; then rustup component add clippy; fi + +script: + - if [[ $TRAVIS_RUST_VERSION == "stable" && $TRAVIS_OS_NAME == "linux" ]]; then cargo fmt -- --check; fi + - if [[ $TRAVIS_RUST_VERSION == "stable" && $TRAVIS_OS_NAME == "linux" ]]; then cargo clippy -- -W clippy::all; fi + - cargo test + - cargo test --features serde + - cargo test --no-default-features + - cargo test --no-default-features --features std + - cargo test --no-default-features --features alloc + - cargo test --no-default-features --features serde + # Validate benches still work. + - cargo bench --all -- --test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/hex/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/hex/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex/Cargo.toml.orig 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,40 @@ +[package] +name = "hex" +version = "0.4.3" +authors = ["KokaKiwi "] +description = "Encoding and decoding data into/from hexadecimal representation." +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/hex/" +repository = "https://github.com/KokaKiwi/rust-hex" +edition = "2018" +readme = "README.md" +keywords = ["no_std", "hex"] +categories = ["encoding", "no-std"] + +[badges] +maintenance = { status = "actively-developed" } + +[features] +default = ["std"] +alloc = [] +std = ["alloc"] + +[[bench]] +name = "hex" +harness = false + +[dependencies] +serde = { version = "1.0", default-features = false, optional = true } + +[dev-dependencies] +criterion = "0.3" +rustc-hex = "2.1" +faster-hex = "0.5" +version-sync = "0.9" +pretty_assertions = "0.6" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"cb5b1db18b4d0f2636f2d4da9d9610c98f44eca8795559eb367ce065c4b2d467","Cargo.toml":"260ca1c082c1b92ae23c8a6357c643b4a195896f2169241b2f37ed0ed9c327a6","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"fbe7b9b51878efdfa613d4ec42ebfc9c7fb0c29806249ef9a3cd8f31ca5ef855","README.md":"c12b95a1033ab5ddd524d3f03185b6b2a0747dcf38ace12276c4fad20ad157ac","src/lib.rs":"a8738a2877a3d0015aa725f053afb26fe5c194ac230d5bcc6e3225213c973704","tests/basic.rs":"0ad2d301202a8fbbea2f4157c7eeb6d2b2cd2bc24654e749813b4160dd38bbf2"},"package":"6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e6dffd10f2228c99a61f9b646d308f20af9a7dda1455fae38f2449ec121abee1","CHANGELOG.md":"cb5b1db18b4d0f2636f2d4da9d9610c98f44eca8795559eb367ce065c4b2d467","Cargo.toml":"260ca1c082c1b92ae23c8a6357c643b4a195896f2169241b2f37ed0ed9c327a6","Cargo.toml.orig":"55d236c8be90180cfd77c8e22fd6b231abbd5caaf0a3fd9a5ffeed325aae7581","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"fbe7b9b51878efdfa613d4ec42ebfc9c7fb0c29806249ef9a3cd8f31ca5ef855","README.md":"c12b95a1033ab5ddd524d3f03185b6b2a0747dcf38ace12276c4fad20ad157ac","src/lib.rs":"a8738a2877a3d0015aa725f053afb26fe5c194ac230d5bcc6e3225213c973704","tests/basic.rs":"0ad2d301202a8fbbea2f4157c7eeb6d2b2cd2bc24654e749813b4160dd38bbf2"},"package":"6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "b8bd42f441f8e2987ded60fbaa809e7bf9d17a8e" + }, + "path_in_vcs": "hex-literal" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/hex-literal/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/hex-literal/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +[package] +name = "hex-literal" +version = "0.4.1" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +description = "Macro for converting hexadecimal string to a byte array at compile time" +documentation = "https://docs.rs/hex-literal" +repository = "https://github.com/RustCrypto/utils" +keywords = ["hex", "literals"] +edition = "2021" +rust-version = "1.57" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/home/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/home/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"f7861a9fdbed65ce6969d3baa0ebf300c01723d4c2f79bc30f49aad2d1b2445b","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"132d9e72011322528376c46965004ffb3d1be30841eb6ff5683a4a75deb35b37","src/env.rs":"de5ce25abee28dca6dc4af52257ed6dc230c2a09c587a361a2dda2ffec8f2bd9","src/lib.rs":"f986d439da63d1597057be177b7ffde982c3081b5ed967f0dcaed99d3490a0b2","src/windows.rs":"bfc979fb1db4bea3a13b5a9e987c8a0f19cfdf88aa1e66576a357394eefa26bd"},"package":"e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"fdb253378f01705bbcf4b99fd56ed55f0a3c50ac52149d47064fd6dcabed27fb","Cargo.toml":"f7861a9fdbed65ce6969d3baa0ebf300c01723d4c2f79bc30f49aad2d1b2445b","Cargo.toml.orig":"2c3cc0362f66107ceeae95e6201a262975ec54ef1dcbcd2b269ddd539bcb36a6","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"132d9e72011322528376c46965004ffb3d1be30841eb6ff5683a4a75deb35b37","src/env.rs":"de5ce25abee28dca6dc4af52257ed6dc230c2a09c587a361a2dda2ffec8f2bd9","src/lib.rs":"f986d439da63d1597057be177b7ffde982c3081b5ed967f0dcaed99d3490a0b2","src/windows.rs":"bfc979fb1db4bea3a13b5a9e987c8a0f19cfdf88aa1e66576a357394eefa26bd"},"package":"e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/home/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/home/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/home/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "37bc5f0232a0bb72dedd2c14149614fd8cdae649" + }, + "path_in_vcs": "crates/home" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/home/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/home/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/home/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/home/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "home" +version = "0.5.9" +authors = ["Brian Anderson "] +rust-version = "1.70.0" # MSRV:3 +documentation = "https://docs.rs/home" +edition.workspace = true +include = [ + "/src", + "/Cargo.toml", + "/CHANGELOG", + "/LICENSE-*", + "/README.md", +] +license.workspace = true +repository = "https://github.com/rust-lang/cargo" +description = "Shared definitions of home directories." + +[target.'cfg(windows)'.dependencies] +windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Com"] } + +[lints] +workspace = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"421f7c0f863b5d5ebc8d052ec82fef1e4d4ae94e8206dd268074cb002c459441","Cargo.lock":"58ce78eaa86f26989a95e4c12f2076bbadacf7889c0fd12d04e51d0e8efc9c7b","Cargo.toml":"ac38b03bf7a6c1adc8819b7821819b4446825a353fe4498e7c553339fb0cdeaf","LICENSE-APACHE":"696759d65dfe558ff7d9f031c76db19ec5c0767470fb67c4e8d990820d1e99c9","LICENSE-MIT":"da28ccc6b158fc2d8cccc74e99794b1cff1d29bd7bbeb019442fcf0c04c6cad9","README.md":"620fdbc62e16014c8152092558a98dc20e26db152589b6f55c869c7b7e584c89","bindings.txt":"608c53ab0830c3da96367755f20082cb4d5d0e88eda37620aaf5a93be36584fa","examples/get_timezone.rs":"c4db7b1cc71c7b3728ddd70e76c0dbd40239c6b1b8c705cb63476757d3177dec","examples/stress-test.rs":"3ad469de5a650389699c9ffe5fd78af2bdd46e7140cc05391c60d793fc6f8e98","src/Windows.rs":"d03104c3fbeb63b239ba0191cf0b8fcfecbbe99d59a7a061adc0d745cd931c8e","src/ffi_utils.rs":"bfbd155b004c2fc4e793aec4604c7b353f71caf35bf67e9b34cd07349628571f","src/lib.rs":"6f0c90477b86f05edf9bfed7cd67f3277ac01bc6c039cc6d8f157e8d33429227","src/platform.rs":"7847381ca6976d9f39ce84759a3b0d7aabe31eae7a88bc20d7fb99bc376782b0","src/tz_aix.rs":"3eb9b1fe8cd6d2547ec6a52bedc120dca88100bef5e7610427048461daa237eb","src/tz_android.rs":"3da37f1b87f87a0ed215734f2b373b2d187bcf49386adfe8bfff207f9a5e8fe2","src/tz_freebsd.rs":"4247af5c6dd0712705186ed54d789193c64139f707af316d4fde86aa1e2a1b13","src/tz_haiku.rs":"761afd80301683a44bf937bbf6b13c5c792af42ed7037623bbeccbab6d0aa8fc","src/tz_illumos.rs":"375ae951d1417f63e6d77c9add7f7f646f24c0054cb8407bd4b9f06907494888","src/tz_linux.rs":"3f04dbc1345ef6783881f3ff9aef4449819dbdc8a1578ffad69c03dc65623f9a","src/tz_macos.rs":"081d5e60955268a1b6949089354eb6657de1c2eb569a69f4e094b995270d540d","src/tz_netbsd.rs":"ec278bbe1cb5f648c063ec23bff6081146454b9f6aa3918b9ca50b8804d5838f","src/tz_wasm32.rs":"10aa33caa86645a16e2126fe1a86dda2b57f63caa9addcd726245fbc9657dc1b","src/tz_windows.rs":"9eda7e9a4cc830f09c06cdaf70026cc95ca55248260a335e1fced68f381bbdfc"},"package":"e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"b2628d32c1c1062d63ee200da26722d1de18b459e4d64909b6bb39186f66f55a",".clang-format":"14f2a77d6cb86bb43dcab6c9011089858b442293ce2e6c9a4eb942c5f31de3b4",".github/dependabot.yml":"0852d249089dca78289a901e040b029514161f87a7a5fe63e46fd9e40a112ea6",".github/workflows/rust.yml":"cf9eb0fade712a367756655045c4f7664e32be754250d8cf2dbf245b4be74454","CHANGELOG.md":"421f7c0f863b5d5ebc8d052ec82fef1e4d4ae94e8206dd268074cb002c459441","Cargo.lock":"58ce78eaa86f26989a95e4c12f2076bbadacf7889c0fd12d04e51d0e8efc9c7b","Cargo.toml":"ac38b03bf7a6c1adc8819b7821819b4446825a353fe4498e7c553339fb0cdeaf","Cargo.toml.orig":"d946be67c0078e896a933cf1f4dfa5b07adcc520c78b2aa0e2d868430e2c71cd","LICENSE-APACHE":"696759d65dfe558ff7d9f031c76db19ec5c0767470fb67c4e8d990820d1e99c9","LICENSE-MIT":"da28ccc6b158fc2d8cccc74e99794b1cff1d29bd7bbeb019442fcf0c04c6cad9","README.md":"620fdbc62e16014c8152092558a98dc20e26db152589b6f55c869c7b7e584c89","bindings.txt":"608c53ab0830c3da96367755f20082cb4d5d0e88eda37620aaf5a93be36584fa","examples/get_timezone.rs":"c4db7b1cc71c7b3728ddd70e76c0dbd40239c6b1b8c705cb63476757d3177dec","examples/stress-test.rs":"3ad469de5a650389699c9ffe5fd78af2bdd46e7140cc05391c60d793fc6f8e98","src/Windows.rs":"d03104c3fbeb63b239ba0191cf0b8fcfecbbe99d59a7a061adc0d745cd931c8e","src/ffi_utils.rs":"bfbd155b004c2fc4e793aec4604c7b353f71caf35bf67e9b34cd07349628571f","src/lib.rs":"6f0c90477b86f05edf9bfed7cd67f3277ac01bc6c039cc6d8f157e8d33429227","src/platform.rs":"7847381ca6976d9f39ce84759a3b0d7aabe31eae7a88bc20d7fb99bc376782b0","src/tz_aix.rs":"3eb9b1fe8cd6d2547ec6a52bedc120dca88100bef5e7610427048461daa237eb","src/tz_android.rs":"3da37f1b87f87a0ed215734f2b373b2d187bcf49386adfe8bfff207f9a5e8fe2","src/tz_freebsd.rs":"4247af5c6dd0712705186ed54d789193c64139f707af316d4fde86aa1e2a1b13","src/tz_haiku.rs":"761afd80301683a44bf937bbf6b13c5c792af42ed7037623bbeccbab6d0aa8fc","src/tz_illumos.rs":"375ae951d1417f63e6d77c9add7f7f646f24c0054cb8407bd4b9f06907494888","src/tz_linux.rs":"3f04dbc1345ef6783881f3ff9aef4449819dbdc8a1578ffad69c03dc65623f9a","src/tz_macos.rs":"081d5e60955268a1b6949089354eb6657de1c2eb569a69f4e094b995270d540d","src/tz_netbsd.rs":"ec278bbe1cb5f648c063ec23bff6081146454b9f6aa3918b9ca50b8804d5838f","src/tz_wasm32.rs":"10aa33caa86645a16e2126fe1a86dda2b57f63caa9addcd726245fbc9657dc1b","src/tz_windows.rs":"9eda7e9a4cc830f09c06cdaf70026cc95ca55248260a335e1fced68f381bbdfc"},"package":"e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "bf8375336a9cc5fbdb0c40f92bdd0b1b13a8a879" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.clang-format clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.clang-format --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.clang-format 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.clang-format 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +--- +BasedOnStyle: Google +IndentWidth: 4 +ColumnLimit: 100 +--- +Language: Cpp +SortIncludes: false +TabWidth: 4 +UseTab: Never diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 10 + ignore: + - dependency-name: winrt + versions: + - 0.8.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,389 @@ +name: build + +on: + push: + branches: + - main + pull_request: + branches: [ '**' ] + schedule: + # At 23:25 on Thursday. + - cron: "25 23 * * 4" + +jobs: + test: + strategy: + fail-fast: false + matrix: + runs-on: [ubuntu-20.04, windows-2022, macos-12] + toolchain: + - "1.48" + - stable + - nightly + versions: + - "" + - "-Zminimal-versions" + exclude: + # `windows-core >= 0.51` uses `edition = "2021"`, but users of the library can can use + # `windows-core == 0.50` to be rust 1.48 compatible. + - runs-on: windows-2022 + toolchain: "1.48" + versions: "" + runs-on: ${{ matrix.runs-on }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - uses: maxim-lobanov/setup-xcode@v1 + if: matrix.runs-on == 'macos-12' && matrix.toolchain == '1.48' + with: + xcode-version: "13.4.1" + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + - run: cargo test --all-targets + - run: cargo run --example stress-test + + build-wasm: + strategy: + fail-fast: false + matrix: + versions: + - "" + - "-Zminimal-versions" + toolchain: + - stable + - nightly + include: + # Without `-Zminimal-versions` a too recent bumpalo version is selected. Newer versions use `edition = "2021"`. + - versions: "-Zminimal-versions" + - toolchain: "1.48" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --target wasm32-unknown-unknown + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + - run: cargo build --lib + + test-wasm: + strategy: + fail-fast: false + matrix: + versions: + - "" + - "-Zminimal-versions" + toolchain: + - stable + - nightly + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --target wasm32-unknown-unknown + rustup default ${{ matrix.toolchain }} + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 14 + - name: Install "wasm-pack" + uses: taiki-e/install-action@v2 + with: + tool: wasm-pack + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + - run: wasm-pack test --node + + build-cross: + strategy: + fail-fast: false + matrix: + target: + - x86_64-unknown-freebsd + - x86_64-unknown-illumos + - x86_64-unknown-netbsd + - sparcv9-sun-solaris + versions: + - "" + - "-Zminimal-versions" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install stable --profile minimal --no-self-update --target ${{ matrix.target }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + + - name: Install "cross" + uses: taiki-e/install-action@v2 + with: + tool: cross + + - run: cross build --target ${{ matrix.target }} --examples + + build-android: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: rustup toolchain install stable --profile minimal --no-self-update + - name: Add Rust components + run: rustup component add clippy rust-src + - name: Add Rust toolchain + run: rustup target add aarch64-linux-android armv7-linux-androideabi + - name: Setup Android NDK + uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r25b + local-cache: true + + - name: Install "cargo ndk" + uses: taiki-e/install-action@v2 + with: + tool: cargo-ndk + + - name: Check + run: cargo ndk check --lib + env: + ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + + - name: Clippy + run: cargo ndk clippy --lib + env: + ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + + - name: Build library + run: cargo ndk build --lib + env: + ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + + build-ios-cross: + strategy: + fail-fast: false + matrix: + toolchain: + - "1.48" + - stable + target: + - x86_64-apple-ios + versions: + - "" + - "-Zminimal-versions" + exclude: + # Support for this target was added quite recently. + - target: aarch64-apple-ios-sim + - toolchain: "1.48" + runs-on: macos-12 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --target ${{ matrix.target }} + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + - name: Install "cross" + run: curl --location --silent --show-error --fail https://github.com/cargo-bins/cargo-quickinstall/releases/download/cross-0.2.5-x86_64-apple-darwin/cross-0.2.5-x86_64-apple-darwin.tar.gz | tar -xzvvf - -C $HOME/.cargo/bin + - run: cross build --target ${{ matrix.target }} --examples + + check: + strategy: + fail-fast: false + matrix: + toolchain: + - "1.48" + - stable + - nightly + versions: + - "" + - "-Zminimal-versions" + runs-on: ubuntu-latest + env: + RUSTFLAGS: -D warnings + RUST_BACKTRACE: 1 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --component clippy + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + env: + RUSTC_BOOTSTRAP: 1 + - run: cargo check --all-targets + - run: cargo clippy --all-targets + + no-docker-image-check-only: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install nightly --profile minimal --no-self-update --component rust-src + rustup default nightly + - run: cargo check --target x86_64-unknown-haiku -Z build-std --examples + + doc: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install nightly --profile minimal --no-self-update + rustup default nightly + - run: RUSTDOCFLAGS="-D warnings" cargo doc --all-features + + audit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Audit + uses: rustsec/audit-check@v1.4.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + fallback: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install stable --profile minimal --no-self-update --target x86_64-fortanix-unknown-sgx + # Should fail (outcome is negated): + - run: if cargo build --lib --target x86_64-fortanix-unknown-sgx; then exit 1; fi + # Should succeed: + - run: cargo build --lib --target x86_64-fortanix-unknown-sgx --features fallback + + c: + name: Lint and format C + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node.js runtime + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Install npm + run: npm i -f -g npm@8.16.0 + + - name: Lint and check formatting with clang-format + run: npx github:artichoke/clang-format --check + + test-haiku: + strategy: + fail-fast: false + matrix: + runs-on: [ubuntu-20.04, windows-2022, macos-12] + toolchain: + - stable + versions: + - "" + runs-on: ${{ matrix.runs-on }} + env: + RUSTFLAGS: -D warnings + RUST_BACKTRACE: 1 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --target x86_64-fortanix-unknown-sgx + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + working-directory: haiku + env: + RUSTC_BOOTSTRAP: 1 + - run: cargo test --all-targets + working-directory: haiku + + check-haiku: + strategy: + fail-fast: false + matrix: + toolchain: + - stable + versions: + - "" + runs-on: ubuntu-latest + env: + RUSTFLAGS: -D warnings + RUST_BACKTRACE: 1 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + run: | + rustup toolchain install ${{ matrix.toolchain }} --profile minimal --no-self-update --component clippy + rustup default ${{ matrix.toolchain }} + - name: Update lockfile + run: cargo generate-lockfile ${{ matrix.versions }} + working-directory: haiku + env: + RUSTC_BOOTSTRAP: 1 + - run: cargo check --all-targets + working-directory: haiku + - run: cargo clippy --all-targets + working-directory: haiku + + check-all-versions: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Rust + run: | + rustup toolchain install nightly --profile minimal --no-self-update + rustup default nightly + + - name: Install "cargo hack" + uses: taiki-e/install-action@v2 + with: + tool: cargo-hack + + - run: cargo hack check --version-range 1.36.. --version-step 2 --clean-per-version --clean-per-run + + generate-windows-bindings: + name: Generate windows-core bindings with windows-bindgen + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Clean + run: rm -rf src/Windows.rs + - name: Generate + run: cargo r --manifest-path=api_gen/Cargo.toml + - name: Diff generated Rust code + run: test -z "$(git status --porcelain)" || (echo "::error::Generated files are different, please regenerate with cargo run --manifest-path=api_gen/Cargo.toml!"; git status; false) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +[package] +name = "iana-time-zone" +description = "get the IANA time zone for the current system" +version = "0.1.60" +authors = [ + "Andrew Straw ", + "René Kijewski ", + "Ryan Lopopolo ", +] +repository = "https://github.com/strawlab/iana-time-zone" +license = "MIT OR Apache-2.0" +keywords = ["IANA", "time"] +categories = ["date-and-time", "internationalization", "os"] +readme = "README.md" +edition = "2018" + +[features] +# When enabled, the library will succeed to compile for unknown target platforms, and return an `Err(GetTimezoneError::OsError)` at runtime. +fallback = [] + +[target.'cfg(target_os = "android")'.dependencies] +android_system_properties = "0.1.5" + +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] +core-foundation-sys = "0.8.3" + +[target.'cfg(target_os = "windows")'.dependencies] +windows-core = { version = ">=0.50, <=0.52" } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = "0.3.50" +wasm-bindgen = "0.2.70" + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" + +[target.'cfg(target_os = "haiku")'.dependencies] +iana-time-zone-haiku = { version = "0.1.1", path = "haiku" } + +[workspace] +members = [".", "haiku"] +default-members = ["."] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"8f06eca1c0e108d0422687eeb87030520ae7bd956efc92352599cc9cf079d9a3","LICENSE-APACHE":"696759d65dfe558ff7d9f031c76db19ec5c0767470fb67c4e8d990820d1e99c9","LICENSE-MIT":"da28ccc6b158fc2d8cccc74e99794b1cff1d29bd7bbeb019442fcf0c04c6cad9","README.md":"5b1ad9309b716374cc1bdcd025f525fac31b2f413e6c4d311e207fa6b1f96a83","build.rs":"10304831100a60c1c2b990762dcfeb47dae8342cf9b54595bec94884e7de5784","src/implementation.cc":"66d2ecfe58ec543e27a6fb3a96526a07cd1ac43a2370344f856529e5a112ce0f","src/lib.rs":"e58db019554bd372f0a187f8f51f96624cdf21bcef507de2093e1d49ca0787cd"},"package":"f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e35aa42766bae2002cba8470471a6d73c1916a4b33cf5f99930927ece3ee28d4","Cargo.toml":"8f06eca1c0e108d0422687eeb87030520ae7bd956efc92352599cc9cf079d9a3","Cargo.toml.orig":"4257cf4466c8db10eea012268e3633c483884992885286f906056c4085f192f5","LICENSE-APACHE":"696759d65dfe558ff7d9f031c76db19ec5c0767470fb67c4e8d990820d1e99c9","LICENSE-MIT":"da28ccc6b158fc2d8cccc74e99794b1cff1d29bd7bbeb019442fcf0c04c6cad9","README.md":"5b1ad9309b716374cc1bdcd025f525fac31b2f413e6c4d311e207fa6b1f96a83","build.rs":"10304831100a60c1c2b990762dcfeb47dae8342cf9b54595bec94884e7de5784","src/implementation.cc":"66d2ecfe58ec543e27a6fb3a96526a07cd1ac43a2370344f856529e5a112ce0f","src/lib.rs":"e58db019554bd372f0a187f8f51f96624cdf21bcef507de2093e1d49ca0787cd"},"package":"f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "668ef37a89162b7d24fb1cf8ee90054a8a2f3ad9" + }, + "path_in_vcs": "haiku" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/iana-time-zone-haiku/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/iana-time-zone-haiku/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +[package] +name = "iana-time-zone-haiku" +description = "iana-time-zone support crate for Haiku OS" +version = "0.1.2" +authors = ["René Kijewski "] +repository = "https://github.com/strawlab/iana-time-zone" +license = "MIT OR Apache-2.0" +keywords = ["IANA", "time"] +categories = ["date-and-time", "internationalization", "os"] +readme = "README.md" +edition = "2018" + +[dependencies] + +[build-dependencies] +cc = "1.0.79" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/image/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGES.md":"815d7e46f2f73a1dbdd0fe508c6226be5f8f84a0fc5ed10083cad94cb126ea74","Cargo.lock":"640166185330228aee7a298f03483cf4e1044deefee1a6cb7860b396ef65864d","Cargo.toml":"85b3de65adb710c7a972333a20f3feb5b3881e3afd3c63eeb9261f4d9a690536","Cargo.toml.public-private-dependencies":"238a2c5c16555e2b02ac452efe24c6b14a734cd5edf020c6c9567c0933d7ca42","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"c77a4cf9da729987d0fe7ccd811e3bd27393914ddf3d23467c18cc22954513b3","README.md":"5f31423cd81aacc4d701df32ae89ea02734faafdefd75b3b999f4e6f105384a7","benches/README.md":"87b2ea4d1cea80c1e24fc18f1222a7ee1a38f5a92e98110bb84a4827fb997b62","benches/copy_from.rs":"62570f462abe7b9765dcfb8ba4af2aab37868058de3d5b7c29180b6ed536f6b7","benches/decode.rs":"263995c14d49ec0ae2ff35da2ebdd1b5f56850f3c98b492a2050908ce7c774ac","benches/encode.rs":"95345fdee195884f474ce5bb2d76a22643dada5d0e27d4cde86420d8632d60d0","deny.toml":"2f4b1af2ccba0115897da29ee1ed89a2a87072248c709a6873a5c7945fbc3afc","docs/2019-04-23-memory-unsafety.md":"b59a9af84bdb5efa1bc1f33c8aa22ff42590701817fb03f55ca2dd50af91bb8d","examples/concat/200x300.png":"72f43dd3d825417a8feba4647410cab8d520f4fb7dfd8ea228eee1cc9effae93","examples/concat/300x300.png":"a0e43576bd0fc65f118b4da1babf8d2ee6cc442c9b2930dfdc26aa51aa655982","examples/concat/400x300.png":"8a195cf85d4047261f8afdf6924fedfe1419d4c7fda685fd0088775f4efe9916","examples/concat/main.rs":"3474e498bbbd74ff8f4bd0e230e25b7075163652839580d6c2b75df80011b40f","examples/convert.rs":"046ee37d89b5ff54ae93fe31f0128102c0431e29a76657cc61b1d794a7f5daa4","examples/decode.rs":"2c2ec382a4c2b8687fa5620c0775608d93dd41ed12e1299e7dfa1ae069d02ff3","examples/fractal.png":"b35b0c8580bdaa9de463c5a3799de24fd2bf6597740d8e745f6b6faf3a6844de","examples/fractal.png.png":"b35b0c8580bdaa9de463c5a3799de24fd2bf6597740d8e745f6b6faf3a6844de","examples/fractal.rs":"dfb794d39201301d52610d61cb0075164775a550af6ed6c36827816be020047f","examples/gradient/main.rs":"3224d985ce1dc7fda5842b147084917b1f790eb1395e93c914b4832b8cb7a3ce","examples/opening.rs":"9be02755ad2afe87d8f12b05565d5f7746d1878989f47c6e4ef5d94c7634d6d5","examples/scaledown/main.rs":"28115c607c1dcc0e8c4f31a4fb5e71e396c0aea9a665d6af076473647b5d1d64","examples/scaledown/scaledown-test-cmr.png":"7b2cd94c7e35b576168402c388fe8a6eca1ae0f734ca210bb3e28133e6760dbc","examples/scaledown/scaledown-test-gauss.png":"f2e53f586d89dcbbca3efd0a1b736531e9df2bed3514f9e41c025bd87c08e758","examples/scaledown/scaledown-test-lcz2.png":"fe020e5aa433bafc8b76bed947ee3feb1b2e6333b1b2bcf00f0f03b5e83926ba","examples/scaledown/scaledown-test-near.png":"d1f1f8fde065624c41bb6b2407932feb7fd0183117f67b3a5b3144dd7a1d046d","examples/scaledown/scaledown-test-tri.png":"3388af145d2513d945a723dececd1a85cdd76ed946a6048574477e1a253a4119","examples/scaledown/test.jpg":"8ee18f55a06b4b4a05d9696bbd6d1ff4511a103f271817a1dcd9808243aa663c","examples/scaleup/main.rs":"85becf7a7303b05bdf20d82913c077ce45004736c62c75b6bd157312077a393c","examples/scaleup/tinycross.png":"8b47b457aa2c9d844efccd37a31925fa8abc8e669a43670953bce402e163319c","examples/tile/main.rs":"2d8b1aae364a8d466bf67d8d99de52c76642193582a01c4b56088c3842ad197c","release.sh":"70f8d6272ab65f5ca80ac95e6ceeeb5041f9c183c87a1fdac2b7f2d16e0827d4","src/animation.rs":"76cbff95b7029becb2d285ded2fbd1b059f396cfd6954d8eec1b300f8ebc4f31","src/buffer.rs":"e2fb8fb66e1a560aa00ecf6036591b98c2956f9b1b4c78abbc25f5d4e7bfa471","src/buffer_par.rs":"a995e1a85bfd5b2c5d3b88ab7f725de39c8a8dd553711165adf5d830e568ad3f","src/codecs/avif/decoder.rs":"b8d43ac27207c241a749c78de501503bcc14aa2ccc298909485b992c53abd46d","src/codecs/avif/encoder.rs":"8d7d9f64bab01b0d0baac5af5d95fa2cbe8f77c968c303d5e879da871575bc5b","src/codecs/avif/mod.rs":"31fcc5c582aefb2db95a8d95b6f99b4e69cbeb1cef16719390a84ee8002f432e","src/codecs/bmp/decoder.rs":"56f2aadd81e038d9f38c4548aab24e9f874f4aa2fcf60ab6b2d9ed5779d79716","src/codecs/bmp/encoder.rs":"f33873789ff5786d3187bbbe258181c69eef48d8214bcabbe0a51090429cef02","src/codecs/bmp/mod.rs":"9c86c6ebb956bd7f5ad2c41bc1b34e59957a1dc08a6ecdb61bfbcf5599eeae59","src/codecs/dds.rs":"32e8b808b88215feb6603284785c14ea13c1a5104533a8a9047a3a5215fe519d","src/codecs/dxt.rs":"38a3d33525b8966c57ac935c9bc64a406d6cd4de686fb10ba9346371475177b0","src/codecs/farbfeld.rs":"b17c97d1425fad91b6c2cb002de1d148dc09545f3df33fe410819c4ddb543356","src/codecs/gif.rs":"d710c241f081bb66eb2b63913f2b9baf99c949c1302db699d4a36b5c37e35c85","src/codecs/hdr/decoder.rs":"2f49b699534834ee716dd55846a3ca3b8d9e76d39e0775209d050f98b395e602","src/codecs/hdr/encoder.rs":"2da1f0b11d8b9c73d22beee716c491adc420a8ba8697040bccc9410d84073155","src/codecs/hdr/mod.rs":"96eb63b7e43f117cb46b8ffe705b477426dde75881f2dea63cab29ffd820e01d","src/codecs/ico/decoder.rs":"f316f618d0d79e4efb7baa36f93863273ee7efc2b6ea2ecb1d62a56129398b0e","src/codecs/ico/encoder.rs":"9001f1383bd33b57a165a59d83dca2640baa5e4ef95a1da01d1959505d70c583","src/codecs/ico/mod.rs":"cd5f9c67256b2083049bb6f8c8963aedca2be8178e198f9e0851c18e6f956845","src/codecs/jpeg/decoder.rs":"363611be342dae2615ffd5d09521d1d75eb83b4570d4c33c7b5212b7012d4332","src/codecs/jpeg/encoder.rs":"3f484231e11f9f0fa65fcef9aa3ae743149ec8717a5c9f2e8f2dff090c5c0fc1","src/codecs/jpeg/entropy.rs":"074975ec5b0040d6caea59f2682e328550d367688d99ee9d0b5674bc7a68682a","src/codecs/jpeg/mod.rs":"cc9fc9c6dad3135184b2f43171f601336d0b53bc75606d5f25cfa8b2f4ba35b9","src/codecs/jpeg/transform.rs":"65490ae7ce990dda33044b4c52afc1bdcfa836b474a1b6a06c611af6e53a70db","src/codecs/openexr.rs":"531909db368d1623d2fb672c9e8c5b6c27d7b33f32db66f71eff1307dafe4e5d","src/codecs/png.rs":"79d7a3a7a8cc56020a1157024a5d0f7316e7181f6c7c3604ac3f61339d7f6d86","src/codecs/pnm/autobreak.rs":"f52a14475c13c1a360f95cd53835d8a234c9b1fa8b675442d0485c5eaa42dfc6","src/codecs/pnm/decoder.rs":"cdb4ce6f5b55eff802e8e283b170b63e4ffba2ef2bd2e452bc3ab58e88f869de","src/codecs/pnm/encoder.rs":"1dc51ae0854187e35268c916a7c9e1e3a3116770e127ec6b0da9995af546e356","src/codecs/pnm/header.rs":"1479bceb32a4edf761b6ed75d392e915e9667ed81c157f244ba0b81436ba79f7","src/codecs/pnm/mod.rs":"9106f90a9bda10d97bf3393189a88f4f6dac27172dac21af0e8e514ac9127867","src/codecs/qoi.rs":"da346a7fb8cd064cb0dc96f84bc456912b3b71af0391d1eed37f7d8e6bfed27f","src/codecs/tga/decoder.rs":"4570ac821569afc9f6ad8b610a07eb303211fb2eb7f46ef46b95e2da0fa077f1","src/codecs/tga/encoder.rs":"98033f015df38e8d5b1d578a4ffa25d4a1e0511010de5d1907d4b7650fbdfd5a","src/codecs/tga/header.rs":"c58013793297fb1ee30df82c7a467873519d25bedcc4d1f3adda9efc3f936bbe","src/codecs/tga/mod.rs":"e25e77180883c56657097d851427d4f1f3c2add5a9eec24e24bc42d65953b0df","src/codecs/tiff.rs":"761a07bacb707e8fa6f297d4c027247b73adea5324b383ea6a4bd8bb10181451","src/codecs/webp/decoder.rs":"c3b75a77f116d0b1b1e55f1ebbce7ea19a9b43ac2409e851387cce50e64b00e4","src/codecs/webp/encoder.rs":"9281debf41142f3ced41c62b4a59af90ff2f78ee1e7ffd0dcda8e77d2fd165fc","src/codecs/webp/extended.rs":"83a44ee34ead5c66b631d92aea82600772fb25bbd15f25a39ab1dd2d32ffebb9","src/codecs/webp/huffman.rs":"8068bc6e844bca90dedae9e4b9859d039f2596e2d016b5729525f2a490e6518a","src/codecs/webp/loop_filter.rs":"58b5291a1a9a574d4f43c912b8f9ce965ac246668f98ea0202aaa3b039a4c020","src/codecs/webp/lossless.rs":"7d6f576e67a5423678adef96935b17d6ca3e6e6193a4b8304999e8e2c82929e0","src/codecs/webp/lossless_transform.rs":"28779701c980128dbe8072300435648bcd87bb49b8382f481c4b3d6746f1ba43","src/codecs/webp/mod.rs":"f280989c0ffcc69bf323427cca134ed6e6c8566a2b6b81cd3c742c98e794b5cd","src/codecs/webp/transform.rs":"f3fe75cf76503ec605d0f19c6757ceb2491784222ab71d79cca46e7bf330140f","src/codecs/webp/vp8.rs":"8c895be04fe9c85daa5bc4e157059e06d56eb6b574655527d74a883cb3892466","src/color.rs":"206ef798d7fc8b59c3a4bb3201af25f00d076d0ed01da0bc1487614d48e374ab","src/dynimage.rs":"54d232707790fcd9d0c8e41e0d87fc3125797402382017d788f83127444676e5","src/error.rs":"f89db8d590768d25d1213ccedb79f7619aa49d802a4a7934b16be0e59b97fd06","src/flat.rs":"fd8eff49e66199f732b0b7ef7ec4ce02d1b73513e00e7e9a0f5565826f2b69e7","src/image.rs":"a5165a96bc8f99f532eda21205a44980f5b5bb2548259d1efae475ce3f134f4e","src/imageops/affine.rs":"6bbdd65600e041ccd7f45fcc1a82c7a50fcef23f6666e9cf0788b4a5bec1aa47","src/imageops/colorops.rs":"c8c8a1d823720da360985dee76464d64d59b57acf5fe9870421e138a36224546","src/imageops/mod.rs":"75632984f1a620f9866f1707f18510b71d6a326c6f1a0c976396c42b32f16963","src/imageops/sample.rs":"3d7c373a3dd6b045805b0e9fcf37cb1b37325bea61cb1ae41b75c14503396633","src/io/free_functions.rs":"c5e64322d7d29498e305431d5cb17931ec3fb973d3119bd34ed532dff39ec440","src/io/mod.rs":"e7932dc1917bd1d3694223f89f720695418d079c8922f39c391ae24684a04845","src/io/reader.rs":"768e219db06c940f4ff7314dc2e9e78308244a49f3643ba64ad503a6d0cbba2f","src/lib.rs":"75243acd54ef1cab174785121a3a63d2f84db3beee10bb8c0ac9f65e2994335b","src/math/mod.rs":"2ee5ea1d5187cbd6e106900f67bd515d0b276e9962e9cda1a2203d536e0052e5","src/math/rect.rs":"10a6f8c76988ff7583f2824be6c3fe005a171777080e3ad0cbe169c6dc574edd","src/math/utils.rs":"72636d83f978250cbc1a2b012e8893b210d83b140e2c3ff98c01a0531cb03072","src/traits.rs":"2037030ca88b4095b2b0f1b1e1dd087f527ec59d1eea11e7756937d2dd462b92","src/utils/mod.rs":"34c729e6f1a1e7b72ecda7271c2fbec084edd4ced89f1cabcab6826e8634c038","tests/conversions.rs":"4891b2a66df7e9057c95c98a278b453a4344ed3a0893c73a6d62ff262cd2925f","tests/images/bmp/images/Bad_badbitcount.bad_bmp":"bdb1eff2635f1eb02ce53bc99172b3df46ac39006b7f28bb3c76fdf83e5d858d","tests/images/bmp/images/Bad_badplanes.bad_bmp":"536bdf4c6db6f1067343aaeef4e6322417cf152551c3a901257390a78a5cc78f","tests/images/bmp/images/Bad_clrsUsed.bad_bmp":"691a6fa915c2ba0c46edd5997b4cb01debc6cfaf2b53e3b5a1b387eeb202863b","tests/images/bmp/images/Bad_height.bad_bmp":"e7744aab98041f77feb9ee80b1225c0bfe1dd48aa4331dd200b774e06ae2b753","tests/images/bmp/images/Bad_pal8oversizepal.bad_bmp":"51c89919fc6b85cc11850054ff16bb947c11dead620e35a92e46d7b0fde79faf","tests/images/bmp/images/Bad_reallybig.bad_bmp":"83051b876c015cd1d0b23598608bc1a2fa1a91bc4bcf4713f009a8bfdeef1df5","tests/images/bmp/images/Bad_rletopdown.bad_bmp":"bdd5c9dfe4e730cf8ca053fcc6f3cf72d79a1ebcc221dbaec3f448a7aa5bd9fa","tests/images/bmp/images/Bad_shortfile.bad_bmp":"7402abcfcaa49130f51bf3a19293c1a3e7e2488cfa51a9e44527db6e8cfa7aeb","tests/images/bmp/images/Bad_unusual_extend_buffer_usage.bad_bmp":"386805d2e7445b96a8661aef2b1348c8a76f4da8e95b1e6a7f1630a3bc8d4a8e","tests/images/bmp/images/Bad_width.bad_bmp":"2f973cc0c224b008261c22028a292ed7539961a423cbf88464a5a79fffb15337","tests/images/bmp/images/Core_1_Bit.bmp":"bbfc2a43b369840c091b791e8d86d18992427b0869e8a0516535edadaec54b7b","tests/images/bmp/images/Core_4_Bit.bmp":"7c7923549c03ac1e5feda0f0f5aa0f32cbdc7b5076e1ea9935324f89497e7475","tests/images/bmp/images/Core_8_Bit.bmp":"a2efaed4258f05ffad03ff1084de6526038271fd01256f5dd2363d6bc3a97ae1","tests/images/bmp/images/Info_1_Bit.bmp":"5b42d528a3cc48efafd2510dc680732fa17c3f09b95bd0a8232cce81df4f604b","tests/images/bmp/images/Info_1_Bit_Top_Down.bmp":"215ec0eb52feeec474fe08f550f574dcbc971ac1a7686bcd8cf48a20d54737e9","tests/images/bmp/images/Info_4_Bit.bmp":"3ed0dcbec3bbc698b238ad9b62fdc289dad66b958dd92dda1da6d32b39b022ed","tests/images/bmp/images/Info_4_Bit_Top_Down.bmp":"3d1764fcbc208daac9fa60e80d92aab6f6a6053f67f3e30181d9488009f689d4","tests/images/bmp/images/Info_8_Bit.bmp":"b2099d2872410b89c4836b6b47ca8d72523fbcc251c1486fab629a7e97bedb4d","tests/images/bmp/images/Info_8_Bit_Top_Down.bmp":"586a7579e8e2a5de8a2d491ce83e0898acaf3b02ec10178e4387416b2858c6a7","tests/images/bmp/images/Info_A8_R8_G8_B8.bmp":"e053b28aa1da9cd940ad7553e5d8c0caec7772d4523f6f573577e107e4ac5d35","tests/images/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp":"f62021c6f4569623d939aa6e88aceda40ae5c168f56a0c5f3f65cac5f1fa331e","tests/images/bmp/images/Info_R8_G8_B8.bmp":"4b37cbc58b7eb221ef3e504db4e6bd804799568316b1fd7c2f9783ef7e898fdc","tests/images/bmp/images/Info_R8_G8_B8_Top_Down.bmp":"fa67c7f03c488eb9fbbd57429dd9a307e4e903602466663e48706218335ea794","tests/images/bmp/images/Info_X1_R5_G5_B5.bmp":"925928f785fab83ca1429ae03b7dc2515eb195e6a4c007a720871b39105c3254","tests/images/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp":"632f26bb0b378c44429c0f7338af58ce2f689dcdbf71de8f8531b56eb19c3a05","tests/images/bmp/images/V3_A1_R5_G5_B5.bmp":"dd045c6ab24dacaddbfba52a95e85d7f3b613a94e532bb1c43f7a853b966c7eb","tests/images/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp":"005a2d89038fbd628189bd13be7b03b8619b44ae0dce9c59d19968d88eb4e1f8","tests/images/bmp/images/V3_A4_R4_G4_B4.bmp":"9bfa2507dd6b2d4e80b5fcb0b64f2397e11f2b777c6f69910dd5545afb459e8b","tests/images/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp":"ba020e5bc84726eb2bdce80b6f13a25107c8fd5c38af13ec6ce0348e8c2c343e","tests/images/bmp/images/V3_R5_G6_B5.bmp":"14fe66854c9529260f300761993bc75124db72c44b7d6a99d6981af50eda8b31","tests/images/bmp/images/V3_R5_G6_B5_Top_Down.bmp":"736323cc833a3a1e96b2b74f48f2800faef0279359bbd7ebde4dc891a429b325","tests/images/bmp/images/V3_X4_R4_G4_B4.bmp":"1189b16fadec897be1b2bdd2de8f98504e1f4a2f04c5dea09d4c37cd6926689d","tests/images/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp":"8a514cdcfc02a34947121a55431ef43573ad3a69e8ffa2dde8ef6d3a773a6ca4","tests/images/bmp/images/V3_X8_R8_G8_B8.bmp":"b7e066c7672623521ee2f2f17c6e347582daf5e265c0a0d1184837034c1f6d2e","tests/images/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp":"e85bdb4948f7678c3de3c656704ff13e53b30fa4cca234daddd27d169b08ae53","tests/images/bmp/images/V4_24_Bit.bmp":"1e202e0102069c1fd28ae5b90e5fc058f238579d2bb5024ce54ef373a9c6d070","tests/images/bmp/images/V5_24_Bit.bmp":"afe598e42c464b3e5e5ed821c40b51bec3a67ae47ab1dbde2b162e46a40bd01d","tests/images/bmp/images/pal2.bmp":"bac6eec4100831e635fcd34a9e0e34a8a9082abdec132ac327aa1bfc7137d40f","tests/images/bmp/images/pal2color.bmp":"6ac541592afb207524091aa19d59614851c293193600eacb1170b4854d351dae","tests/images/bmp/images/pal4rle.bmp":"3c26b6bdd22311e03b1ac0713b0a3b6af5e579bef16694cbea74ae0c4a2599e4","tests/images/bmp/images/pal4rlecut.bmp":"e3dcbe1f39144845f339a88c9cbf34adc3e0b355440dbcb13e987aec77bb2137","tests/images/bmp/images/pal4rletrns.bmp":"2fcbaa0f387c57ba678ced91dfb2db5b2e544e2ed28a7875459e551b514daf84","tests/images/bmp/images/pal8badindex.bmp":"5e27aa644c3e53cc3c23e0958c000a181ead9fda33edbc5fe0092fc2619c7a1c","tests/images/bmp/images/pal8rle.bmp":"809938ab0e821710b5f566d85ba735870e5b8ef690eaca7f54a81cf1729fe10a","tests/images/bmp/images/pal8v4.bmp":"9f34c156be84cd56f12eb037302cf48763f9dc8e89cb8880ecdacea8908a87bb","tests/images/bmp/images/pal8v5.bmp":"65ac4a579189d2fc30b3499b8246f30127e032f35d6cde90335dafe87a1b23c3","tests/images/bmp/images/rgb16-231.bmp":"f8ae32cc34bbbc1538df81d8086f05ef913df4eed0683234e512b05cf70ac3c7","tests/images/bmp/images/rgb16-565.bmp":"c2ffadac9c1239fb397834415c7b5f85d5c6044bd9c31fa66e23056a19b82b1d","tests/images/bmp/images/rgb16.bmp":"fcecd482048c853d08255430c5bac462821522683f4429626442580058aa5e5e","tests/images/bmp/images/rgb24.bmp":"a9c4fbfbf8cb6df8d2d9d1484359d037aebd25078b21137bfd6c69739fcbe2e1","tests/images/bmp/images/rgb32-111110.bmp":"5045e023d870eeb2716e8037604053ed7e2b0328701754a04563b6189023786f","tests/images/bmp/images/rgb32.bmp":"b4c79cb8ffd2f1c096af27f9d82b5feaa0aa2cb049c791e0f6251de0435066e5","tests/images/bmp/images/rgb32bf.bmp":"4c1189e3a039b1e5aae6347024684937c495a5736a3c309dc7c2e3c161f89751","tests/images/bmp/images/rgba16-1924.bmp":"1c9b03e6aa57449747ea1e42222e283c9468363275d96a02d22e07736dc5c9e7","tests/images/bmp/images/rgba32-61754.bmp":"df2041fae7c11bb62ddc5dbc163427a5e79d5a7fc2c09b168ea17608e838a8ce","tests/images/bmp/images/rgba32.bmp":"257e0127fa0ccdb6eb8381338dda0fb692b2ea4d38775f1aed56dfdccaed2ab4","tests/images/exr/cropping - data window differs display window.exr":"5c7780df79eae260622f9b79225f0fcea58a14a2cb313c098b18cbffc970e9d3","tests/images/exr/cropping - uncropped original.exr":"e9de97ba58cfb6b602ed3e225e0b96fc28e298c6f54e603b80b13748f35dae99","tests/images/exr/overexposed gradient - data window equals display window.exr":"f3bd45eb0c382efcaa90da81fa1497198e804f91acc56f9936e7788d53687e21","tests/images/exr/overexposed gradient.hdr":"299bc0b1b5ebfd3742ddf4090a0ae531cde537662335825e4a10cf85bd08263a","tests/images/farbfeld/transparency/acid2.ff":"93a2d1ba307435bbc462898addc3a917ee796a7277eb66272e93a694696ee7f6","tests/images/farbfeld/transparency/tbbn0g04.ff":"e988b1ee713a1aa81ccdfccf406ae15cbb7ebf49b7354f49a65f5b18b05e4eb1","tests/images/farbfeld/transparency/tbbn3p08.ff":"0e609dad94b3f2d0d9687c867a96e42785a6a9277d079aa7cd7368654e35af9f","tests/images/farbfeld/transparency/tbgn3p08.ff":"0e609dad94b3f2d0d9687c867a96e42785a6a9277d079aa7cd7368654e35af9f","tests/images/farbfeld/transparency/tbrn2c08.ff":"6bf466a72d9be3633e37acce6dac620dc10764100d1ecd41e78d608b9a3050ee","tests/images/farbfeld/transparency/tbwn3p08.ff":"0e609dad94b3f2d0d9687c867a96e42785a6a9277d079aa7cd7368654e35af9f","tests/images/farbfeld/transparency/tbyn3p08.ff":"0e609dad94b3f2d0d9687c867a96e42785a6a9277d079aa7cd7368654e35af9f","tests/images/farbfeld/transparency/tm3n3p02.ff":"5954ff9b8637f4fedcd2df57957bfee13f046dc7b9819138cf07e3060d8a86d9","tests/images/farbfeld/transparency/tp0n0g08.ff":"b14082890bbf956a397b79f23dc331f0ff3ff7578ae32e6932333f96781039f7","tests/images/farbfeld/transparency/tp0n2c08.ff":"de1362b6a45da030a94fb6fa357347caafc4cc71dc78aea23028185717f59145","tests/images/farbfeld/transparency/tp0n3p08.ff":"0a74010aa542cb261ef18b9dcdb52904a942eb8501b0735dbacf7b29b27bea39","tests/images/farbfeld/transparency/tp1n3p08.ff":"0e609dad94b3f2d0d9687c867a96e42785a6a9277d079aa7cd7368654e35af9f","tests/images/gif/anim/any-disposal.gif":"33a29843c79ab2ae264bf14aa5f9466c2eec9cd9597e2c03cf0fa834ab979d60","tests/images/gif/anim/border_touching_layers.gif":"38bd62b98b086ffed7eb31915d36e1e9f8939dc0609aa482589dbb146951ce36","tests/images/gif/anim/interlaced.gif":"e5771812f4575268f9c1d84681254d0e5c59c37754c0cb1c94b6cfef0d861f44","tests/images/gif/anim/issue_1455_undersized.gif":"526a5f5760f9be9b86b2b903f7e6df1b784a799eb8b8dcfed70f37ad71a267df","tests/images/gif/anim/large-gif-anim-combine.gif":"a8b38a5e3b1ae024c213ad48fd101ced6ffdc6e6f7efd0c305d5540e71623a7d","tests/images/gif/anim/large-gif-anim-full-frame-replace.gif":"8232e887deb1344ed72170c777e883bc9f7e98f235b239646d459e21c8add41f","tests/images/gif/anim/mixed-disposal.gif":"60b2528d3955c2e0ebe57bfce5592b10bcec12258ac46abe45a13768d439022d","tests/images/gif/anim/oob.gif":"9e50933811f15ef0191702ff3095440e97cea8fb60d5d5262019326b847558ec","tests/images/gif/simple/alpha_gif_a.gif":"a2662e1042631e29fc08ca008041854091cc3383d0f4c1f735edbeff3cdfb55b","tests/images/gif/simple/issue_1455_oversized.gif":"15d8b90c26eb187b1828948d42ce43c1f37026178c4b5bd855284a57fbf2cbf2","tests/images/gif/simple/sample_1.gif":"b7f4cb970d8f3c1705e190b6dbe398592a89986bf94b060b59bfe716f045e6f6","tests/images/hdr/images/image1.hdr":"1d0d5a10182cf5e8855564c29da26afb8cc76eccc6f613c7dad1e02022225bb7","tests/images/hdr/images/rgbr4x4.hdr":"81efc2f846214ffcff7ce02acd1e0166ff58bf383e703ee878960e1a052b227f","tests/images/ico/images/Bad_smile-incorrect-image-length.bad_ico":"ebee9654386a65a46cafc2ff3dbd91e4d3ad05442164322f0e432aae5ff43a50","tests/images/ico/images/bmp-24bpp-mask.ico":"95b636373d1d43f16135330b0eeb8d4a4eedbc50d7581014743f1c600957da11","tests/images/ico/images/bmp-32bpp-alpha.ico":"8928f44c1a4f9402dc94db4ca1c3aa478ff37e6c70a4d49e410c7c2ad39455c4","tests/images/ico/images/png-32bpp-alpha.ico":"4d9bbd9530791dbb97c47256a2cac0d50577183fd5e730d660d4b47a35d60d1c","tests/images/ico/images/smile.ico":"e17d21133b1a9e7318cb48c036820089efebcbc09b452c7cac848498a9d7684c","tests/images/jpg/progressive/3.jpg":"d19ebc7245629cc1e55cd0876fe671bde324893e73a75f3c467b8b4991214837","tests/images/jpg/progressive/cat.jpg":"f8dcbaf051bfb52ea7a9481cbe3b125210c236518762b0be65444bfc073792db","tests/images/jpg/progressive/test.jpg":"4014ce154e09f4bc480f9cf6b00745ff76a86e37af8f94e694eea1b6e770edbe","tests/images/pbm/images/issue-794.pbm":"3a982c4e584851dbdef9662cf4d266c14110ff0d0305ddea28aa45ef2978e57b","tests/images/png/16bpc/basn6a16.png":"8f9d81060aebf4576461403c5057de7f23f73157016b659402b906df805845aa","tests/images/png/apng/ball.png":"ce0905f339f44370c0fecc226ef4b422d86f06a3ec4f194e5cfb9d0b50aafb2e","tests/images/png/bugfixes/debug_triangle_corners_widescreen.png":"73af416381942e013d45e68936976f68e1e50a40f2e93bfe2fe6ced9645102aa","tests/images/png/bugfixes/issue#2026.png":"bf282001281417100ac90856b46692383eb04c8c7fddfaea9bff5df7c5140d90","tests/images/png/bugfixes/issue#403.png":"c27973460bbd796574d9623ec70089128996119ba715d27c22938dbfdf9ecf80","tests/images/png/interlaced/basi2c08.png":"b2690d4475cdc39faf5a7d2de20de4e14eb96c6360fa791ec2003b4085ecacde","tests/images/png/transparency/acid2.png":"b95534c515880250a4d87a2dede9d39f086249c6d0b61d1d448da28ea43a444c","tests/images/png/transparency/tbbn0g04.png":"c5e7eeaffa677bfac002ee968a0423e0fea3be7701d39ccd6a015df1d2d85e40","tests/images/png/transparency/tbbn3p08.png":"8eb43a6020fda8ed7c8c9b88b974ef794ee8452db29212ae7e5c11003bfd76a3","tests/images/png/transparency/tbgn3p08.png":"6f798628935a021fe446dce3d62861d1f7369aaf01bad10daa4917c5abccad7d","tests/images/png/transparency/tbrn2c08.png":"8223d8b0c5f84b149f0c1f0e1f658346e07fcbd03ffc02b2e9eeea1481eb19bf","tests/images/png/transparency/tbwn3p08.png":"978b28cec43bd219517083b63661bb30a7b9cdf9fd4476ab4e70844565980d51","tests/images/png/transparency/tbyn3p08.png":"7b4eb64b4bd7eb36417752873ddaca027ce77a07f474b2af569f4eea1e984111","tests/images/png/transparency/tm3n3p02.png":"f05e317f64a038123faf96fdbd6fc3ab3eec14e1fc1eb87fd7da4d996be63526","tests/images/png/transparency/tp0n0g08.png":"a253e055d8cd94049cd95e9392e7aa60f3d5c922a8f0cccb84762b0c5f547545","tests/images/png/transparency/tp0n2c08.png":"5dced3fde56b950e61ce86f4ad54458336f66389ce8ca68524d4fd8ec546ff5b","tests/images/png/transparency/tp0n3p08.png":"da40ddb18bd45db32ed03dc89e2250b096d808efe975a88477e4f5a91a4677c9","tests/images/png/transparency/tp1n3p08.png":"50bc927fe6cf1816454a7c27f8c743734be8db45e37e5ee3ede540f4e895e6c5","tests/images/qoi/basic-test.qoi":"848eae7cce0ddcff68baf9368a7d230ab38ea2701ca31ea7c0bf2db48d9ed1ef","tests/images/tga/encoding/black_white.tga":"fc796f16f34b24afdf0e507cb4c17c58b4ea8b7075e73577597773e27bab88a8","tests/images/tga/testsuite/LICENSE":"8a0a57eda34cb129c52fa6d17a9edf627396efde24a55cfdaa771a1f77a1ad65","tests/images/tga/testsuite/cbw8.tga":"e594d822698501a6fa5d35dca3768150fc473962e62e8393276fbbfe2c44d558","tests/images/tga/testsuite/ccm8.tga":"67b3ffaaa75561d8b959258d6b26a1f9ca3228b02a3df98a614ea43241aaea52","tests/images/tga/testsuite/ctc24.tga":"09476dca727360d41688664c82f2fabf0e3c8627af4d10c41d019767bf43d386","tests/images/tga/testsuite/ubw8.tga":"f85102f04bb2a8ea5a2427bbf79d3b1f91f20e5d33111521f5ac8607b90e3e6d","tests/images/tga/testsuite/ucm8.tga":"985424e2d5f58ca14eea24869e034ad6a73cce172e06935d4735df564dff0ab6","tests/images/tga/testsuite/utc16.tga":"fdd97c1dbdecf79c67bd96f72672366d9405cda70f5245ab6db399d6a7932ecc","tests/images/tga/testsuite/utc24.tga":"e4d9a8f44119937748c481886b4bbe48d09bc02c21bd06a1a8192ec802a5c7a5","tests/images/tga/testsuite/utc32.tga":"7c65731c8f2adb700b4352eafb63bf9702832d692f09262807a56a5a269c5338","tests/images/tiff/testsuite/hpredict.tiff":"7c43bde225d30f1f435238469ee2bd01d17e2205bba92fd5af91fa4b57321fad","tests/images/tiff/testsuite/hpredict_cmyk.tiff":"f28f444f89bd0f2e89482eac5e2eff11b5f7638f70d7fe69722043a9658300d9","tests/images/tiff/testsuite/hpredict_packbits.tiff":"6996306b956e6068dba56f5b66712c302145fddbe39585e000a2bf72d7749b04","tests/images/tiff/testsuite/mandrill.tiff":"3f590b52279fb59b81906f1e928ae713a5357b1afc1a2017a103adb563fb4494","tests/images/tiff/testsuite/rgb-3c-16b.tiff":"31ff3a1f416cb7281acfbcbb4b56ee8bb94e9f91489602ff2806e5a49abc03c0","tests/images/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp":"5fd83430e1dca3ffcced5bcac452147f30296ab83cae00d84603959ba96abfb6","tests/images/webp/extended_images/anim.webp":"459d0f8601844487cebd09dd11d0f50346fa45820bb7a7d817140dcc811496b4","tests/images/webp/extended_images/lossy_alpha.webp":"8d5b0f27f821d87106ed178831a9e62c95c09063e515b5d2ca89ad215547879f","tests/images/webp/lossless_images/2-color.webp":"284ddab37b3cf76424a5a9a32351a84e815a0972f4bffd68571f6f67874c38d3","tests/images/webp/lossless_images/multi-color.webp":"6c1d82198912f1b07c81ce8ccd9fecb5825ec07fcdb42c352703e208cb2ea8d0","tests/images/webp/lossless_images/simple.webp":"16dbdf943d5281fcc58758e278c703a61f9a7ef572343178948637ee4135880a","tests/images/webp/lossy_images/simple-gray.webp":"e8c20d94a8f2c7a86d82d394708169bb3637b35c5338faac7154eb7af1ce8c43","tests/images/webp/lossy_images/simple-rgb.webp":"76ef749015935542838ffda9df014b823d4153a7ffeab09fd5670ef4e7fa0386","tests/limits.rs":"3ecadc1410a2786bff86257935c787076e6ef5eb7872a51dee6d1e40e4ab0d55","tests/limits_anim.rs":"c0dc5c6a8a0ad87676fecffb0eeacdb11fc31e48bd2ab9a64c80b3e9e644a34b","tests/reference/README.txt":"9639893247ff95a7661b987b901817f88393e446797b18b9def4bba29fbbbf93","tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png":"fe3c00b9e20950156836d40e58fbc85139b183ad491d0f1f0cc804245038a5b3","tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png":"2b95a7bdbcbc8f1b09b72bfadb29284f29c5f1ccb909f972a5ebf3e91b3334f8","tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png":"f3819da28a4ea1995536d20555ca7ca2c1008d60b5b5c5e367ed8ceea0a8e428","tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png":"9e6f07e35c114d013ee38c02bebbc5dbef92a3f8d7be6762a7bf9537462295b2","tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png":"9e6f07e35c114d013ee38c02bebbc5dbef92a3f8d7be6762a7bf9537462295b2","tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png":"a42954cb13fe9901ef38f5a86383dd40082959dab1ee1757742b8da688b2b2e1","tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png":"a42954cb13fe9901ef38f5a86383dd40082959dab1ee1757742b8da688b2b2e1","tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png":"a42954cb13fe9901ef38f5a86383dd40082959dab1ee1757742b8da688b2b2e1","tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png":"a42954cb13fe9901ef38f5a86383dd40082959dab1ee1757742b8da688b2b2e1","tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png":"4beab0cfd1fc03186b25db1b5ea5339d4924dc213e8bafa7b32c528e530eaafb","tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png":"97fead12f46fd568b0dcf5feef2e115847e8cbae5efd8b8844c16e00b17fc232","tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png":"97fead12f46fd568b0dcf5feef2e115847e8cbae5efd8b8844c16e00b17fc232","tests/reference/bmp/images/pal2.bmp.da27594.png":"766e7e612d775e60268b8a73661ccfba6928aec272af47ff1564fce788c796e1","tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png":"d5d1a717ff82168a6a216bc4d35b7e2b39f9046eb8625ebd965b8c9fd07ab16f","tests/reference/bmp/images/pal4rle.bmp.288e4371.png":"100c3f284861f06222b321fc0ed63057d2c6e2055bc71d5fe40892e88ae93927","tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png":"3c17fac7a376dd9bb15c8d51b28ec25e0108d1111797636147eca77918f67d40","tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png":"d6d7f1d668a45a02668a8c652c09387639c4cb641da5c25276b3f228dc618680","tests/reference/bmp/images/pal8badindex.bmp.4500d02.png":"3edd45ac3c74cc491f880519bcd52044eee1f82e995567336ed4811ef6069622","tests/reference/bmp/images/pal8rle.bmp.38454155.png":"13f5420df6d92220173847ad7b7a13836e2b5f109fe62b2f6d5b1afbeb0bb67a","tests/reference/bmp/images/pal8v4.bmp.38454155.png":"13f5420df6d92220173847ad7b7a13836e2b5f109fe62b2f6d5b1afbeb0bb67a","tests/reference/bmp/images/pal8v5.bmp.38454155.png":"13f5420df6d92220173847ad7b7a13836e2b5f109fe62b2f6d5b1afbeb0bb67a","tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png":"19a5c2af81cbc91478bd7b5b5e687a6b633928c2a4e283cffbd3afa7454c9b52","tests/reference/bmp/images/rgb16-565.bmp.80839b35.png":"96b9d581f30715883f41163a4c562640381ae2027db57411f84dc1f26168f6ab","tests/reference/bmp/images/rgb16.bmp.46dd68ad.png":"1c5f60b2881c89a27ea76ce9934836731bdd93bf308a980637210037c6f1fe6c","tests/reference/bmp/images/rgb24.bmp.25bba0a.png":"27b2e878f350dc116ba9ab9ad875a041bac1f38c4cd39341c03acccec70a45ac","tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png":"5d87e392b99958731598cf90d0f24be24b827646475ade4f4e46d2f56970f002","tests/reference/bmp/images/rgb32.bmp.25bba0a.png":"27b2e878f350dc116ba9ab9ad875a041bac1f38c4cd39341c03acccec70a45ac","tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png":"27b2e878f350dc116ba9ab9ad875a041bac1f38c4cd39341c03acccec70a45ac","tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png":"77e55ffb814da2e29b8ac10d299a88e80b0c953cce902c1367cd60a13e3597cd","tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png":"59b8e0de1eae59c86d530d8d23080e8452693b8b4075957311a66f98c6fa6bc4","tests/reference/bmp/images/rgba32.bmp.e041b498.png":"979b20ef6f5135c60f5178e6ffa85a0074640cf88814e5c5607e8a6a03d24c69","tests/reference/gif/anim/any-disposal.gif.ace8cccc.png":"4b14aa80314162bf0d6fb2bcd5a2bd1650c6482a483bcb0a750d527096030d76","tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png":"c83e5687abd36dafdeb7978d4ad526d049f79f70c149d0a75fc5c8fdf04e60ae","tests/reference/gif/anim/interlaced.gif.ad3a4823.png":"ad5189f2b7b83be2b22e97b829ae3cc745a5599fa2e10d2719d51a1dafc9a69d","tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png":"c24432336e85dba808fa47f8c4b79bd354cd03605db38f7f4acf5ab4857d9433","tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png":"4b14aa80314162bf0d6fb2bcd5a2bd1650c6482a483bcb0a750d527096030d76","tests/reference/gif/anim/oob.gif.da695a00.png":"6060b2ab09ed7eeed32cd6b5d0ad40863812b8a9e0386e06086cc2e2fa15b6e9","tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png":"ab486c603622d336aafb7deb34d101318bf1545c8da0e851dd9b2c38681efdd0","tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png":"8ec8b0204bdce454c3e2136917bebf9aa1c3e39a86ae0a74071d2472a0bb040b","tests/reference/gif/simple/sample_1.gif.c33b036b.png":"dc0ef96a8847204e08fefda10219570dd1dd57dc087c89714579297d94590411","tests/reference/hdr/images/image1.hdr.bd02cf8f.png":"332bdd679c315842634b5364b8aece2c669bb365c68e6097dd4ab36493964ac3","tests/reference/hdr/images/image1.raw":"ecccda27ad8c75ea8776fa505603ec5f9a0619312f9180640578ab3a7bc1928e","tests/reference/hdr/images/rgbr4x4.hdr.72ffeca1.png":"5ab3a9ed297443e0e8b2a3f2f4ae2b20e5f05191d376a90bcf04d4537f20c0a4","tests/reference/hdr/images/rgbr4x4.raw":"649a3d02eab7ed928542c017ecf2eacdcfa6b73eb4c2b5dd47615496673b90d1","tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png":"99010edb2b855e556896ee51120d00e5258d700d5b4655cfc496b4c7b4a52137","tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png":"99010edb2b855e556896ee51120d00e5258d700d5b4655cfc496b4c7b4a52137","tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png":"99010edb2b855e556896ee51120d00e5258d700d5b4655cfc496b4c7b4a52137","tests/reference/ico/images/smile.ico.291e3bb0.png":"1b73757a8dc3ef0c42d166749f5a367db3bf7b08b9791a606841b022577268a2","tests/reference/jpg/progressive/3.jpg.79e90ab0.png":"1188725174a8217bc6e21cd5f8a9a95fac274c774a379b423d1f84b9022d61b4","tests/reference/jpg/progressive/cat.jpg.a1b69d49.png":"045d47b378b5eb00e69426203f2b5b22df53cfc7b443f468769a27e7dc417e55","tests/reference/jpg/progressive/test.jpg.f0362c80.png":"3c0a930a2ee2c71a4972f73247981947badb3e38f8d01fa99cdf8b61dc37d850","tests/reference/pbm/images/issue-794.pbm.80cbc790.png":"2da2a7890c1327a7c948adc27b15c06709971827481ce98e5f6b11a8d8aa73b8","tests/reference/png/16bpc/basn6a16.png.87be531.png":"9866ed21f3aa488af32bdbab171856f08936cfad0058756de9436b5aa93d08ad","tests/reference/png/apng/ball.png.1c840a9.png":"c34135322ba59cada73529be54c10597d1f2e63f07f30365de320a4f00245a7d","tests/reference/png/apng/ball.png.anim_01_01c840a9.png":"c888212557ccbe0ca7040c36986f7065f5fd8771d9b49ac221eadfd75507f2a5","tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png":"91ff427be4dafd09780d0468f2de5798e228bbbd94e80b95177a291d0cd9d217","tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png":"d60ff736c385f8875b592aa4eafd0f252abf061d7389122d56bf2d76838424da","tests/reference/png/apng/ball.png.anim_04_26897da3.png":"757d94f166982861a143af046b2b5d6045639874e0e317ad28912cacc142c734","tests/reference/png/apng/ball.png.anim_05_123fe3c5.png":"dace913100a7e9db7c95beafe3d153a5706cd8d2ffcef614fa9c67f26c9aef78","tests/reference/png/apng/ball.png.anim_06_69c299ea.png":"3d9d779d7e6e1861983622649d6ac7d3f50b99e185a68c49d954c19737bb0a41","tests/reference/png/apng/ball.png.anim_07_765d3648.png":"952d8fa73de406125b41bd07a8590c22b8ba0b78b6b63261d69ffe80102636ad","tests/reference/png/apng/ball.png.anim_08_e44a80f7.png":"c28e973f9405f85ffd52be1990620437f76273b3a6a600eb10d094b73760e232","tests/reference/png/apng/ball.png.anim_09_dd6883db.png":"5471fd99c99f10233fda4fde4bc520e46474489bb2626d98dfb02cccfe937ca3","tests/reference/png/apng/ball.png.anim_10_3b68b97b.png":"0a2f8410d9e91662af9c819d93ea7070374680b927f22311f333774ca4802498","tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png":"11f0f22958ca80fd27f7beb596ee33c812f0137f2f5003824699f4a03ede9fee","tests/reference/png/apng/ball.png.anim_12_0796c12e.png":"6987452d772adacced300cc2bcb86ecf7169de9288b2988a9b8fb998ab4305a9","tests/reference/png/apng/ball.png.anim_13_bf335902.png":"68ad81337317ba9e3cf4bab0fe51a47c8a6ff092e8f30247050863ae162c9b8c","tests/reference/png/apng/ball.png.anim_14_ee765a97.png":"41826b5c0c5284f92b5a804f235e4271b3dca23c5276589f4efc8e20c3383e76","tests/reference/png/apng/ball.png.anim_15_56f89914.png":"fe904b09ca1fc3f3f0689742e78208105f3c6c1c515866cbc90241793dce7fa1","tests/reference/png/apng/ball.png.anim_16_cd899432.png":"e94b5b08bb6b1745fc4601ca42a88ba7b3fbd4a6eb52a2fa79fea98ff7fb3509","tests/reference/png/apng/ball.png.anim_17_0c3b039a.png":"3d02c3a9bc269d0f46744c140e10a283f2f108068f91468e01a11a52fad81a8f","tests/reference/png/apng/ball.png.anim_18_611a8f5d.png":"b860cd0c3e94e84015cf3959e35c8cca3e9841f25e3cc77c54d9015a34dbd10c","tests/reference/png/apng/ball.png.anim_19_d7316ce1.png":"15f20b761b77a192c50e1cf3e7d7198c20c0548fe92188196ba274d885e27f08","tests/reference/png/apng/ball.png.anim_20_1e8b755f.png":"8e49591f7730ecc1d2336923f99ad9c2fbb5e98bfaec8ab6c5d0c37e589f1980","tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png":"838dcd7816a848891d6699aa2aca116aeb56e1c57c624cbd27dbcc796627906f","tests/reference/png/bugfixes/issue#403.png.b0818cef.png":"bd78f08034b1c304b1b8a75228079a41b4695cbd956aec062cbe651fbac93c38","tests/reference/png/interlaced/basi2c08.png.7855b9bf.png":"ee22854ca7807b9be816078ddab859ba6969e47cdcce78e2b64e8531da6a18f7","tests/reference/png/transparency/acid2.png.8de8ca3f.png":"46521cc0f2356add16d5c8dab12b40de2fd81dd84fe99c6a2916cba07b25e989","tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png":"baa63f4cc70516a1d6dd62dbbe58ecb1441c66b290a761e21821e3000260000a","tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png":"fcfabea9d06fb1f08b6a8edbc6a682a76681632d99c127b91233475bb5913bbf","tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png":"fcfabea9d06fb1f08b6a8edbc6a682a76681632d99c127b91233475bb5913bbf","tests/reference/png/transparency/tbrn2c08.png.370ef89.png":"3216614e4cac1d189908e754927e2e3904f00ebde3062011dc77b41cdd40e473","tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png":"fcfabea9d06fb1f08b6a8edbc6a682a76681632d99c127b91233475bb5913bbf","tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png":"fcfabea9d06fb1f08b6a8edbc6a682a76681632d99c127b91233475bb5913bbf","tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png":"4d5b09f619a3a055f1d285e3b60ef6c7f2bc55d528b85993f3c9cee26066d009","tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png":"42bee01d96b6c8d151f35a0f379544f218b7cace9a403e8545b9a57b21279569","tests/reference/png/transparency/tp0n2c08.png.b426b350.png":"b12ed012406bf3b35b3c4e187acb6dd08ccac2037cad1a943a628ca333d2e9fb","tests/reference/png/transparency/tp0n3p08.png.15493236.png":"a34f62f9c95006b87f9c55fc40b90d2ce60e66d01833b7c61a748ac2d3c2d07d","tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png":"fcfabea9d06fb1f08b6a8edbc6a682a76681632d99c127b91233475bb5913bbf","tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png":"91e112fbcbb32d53ec25965a0f50b0eb189f830765d85ca812f25b3bba06d5c0","tests/reference/tga/testsuite/ctc24.tga.b7096b3.png":"5149e5fa55d8b59637956aa9cacc4b1b11f18ac6b5d78c8431a35b0b2dcc5d77","tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png":"91e112fbcbb32d53ec25965a0f50b0eb189f830765d85ca812f25b3bba06d5c0","tests/reference/tga/testsuite/utc24.tga.b7096b3.png":"5149e5fa55d8b59637956aa9cacc4b1b11f18ac6b5d78c8431a35b0b2dcc5d77","tests/reference/tga/testsuite/utc32.tga.134a83ba.png":"d475eab3a641afecbf3bdd8d6bbcf488be5ddd9c09111f841f7fff017ba8a2c3","tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png":"54ff8c581c3263e3de5bd09c032e7541a2fad4723002a1cf10dcc1cedc1fca1e","tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png":"ec2371f3a6007afae35b1c4bef84a4d642b1d09712497d91d2eac7f62ffa7707","tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png":"e933c8b88e0cc55817cd45b0125faa307d64b2455886277e5f97039db0ef3f03","tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png":"a0c51dcada74bc1db3863e4129fcab0a409c99b796a906e20bfb497eb924e144","tests/reference/webp/extended_images/anim.webp.f6449d24.png":"cbd13db9ac76f195762e82479f4f7ade7de635a3c10d862af60c67b23a8f1b12","tests/reference/webp/extended_images/lossy_alpha.webp.37efcff9.png":"45a2118170f6ec8cb2cdf40a8c0053442af51d902dc4d0e344dc02efa2973b56","tests/reference/webp/lossless_images/2-color.webp.d5b9a8bd.png":"00cda4d408ca02fc21d8e8aacefa5ef648ca664634e658db67a182bc225060f5","tests/reference/webp/lossless_images/multi-color.webp.d98bd812.png":"2f0aa2debd97e88b70ae94d00bbb40cb121aadc3fa799ef9cac06d7b1715aef5","tests/reference/webp/lossless_images/simple.webp.18d31ac3.png":"dc238a6eb1b52bd5e1a8b893e69eff277747868025f1db235db9cb8128cff250","tests/reference/webp/lossy_images/simple-gray.webp.6b294f50.png":"ef3f81d4a1d02374b05bcf01f78820948ce6f280a9639845f7e401e422971b50","tests/reference/webp/lossy_images/simple-rgb.webp.4bb22be5.png":"bb59d78637f846950436d15792b10a9e4017b25f82d3fd8345d9174881496576","tests/reference_images.rs":"837a957d4553f44b6ca9ebc53794fd2cfce0783b9612a85401e6248f84255787","tests/regression.rs":"5e5c8a7f2edb4adb926c791e6b990d32fd5154d9d1779b0c55ff652c6dd4f891","tests/regression/ico/crash-981fee302fe0fc543ee48292cc3d6ace7e97e633.ico":"9a57694369821ea11bdf6f039413272d3fbd6b054b2d2d3348ed17d39b05b444","tests/regression/jpg/oss-fuzz-36829.jpeg":"20256cb7ba0b6643be0593a2f5cc7685a8e32295c847201639ee6e72ac91cde4","tests/regression/tga/bad-color-map.tga":"064aa6d92c77d4fa7459cba97d1588dc524988981f52e44aa83f6fe4106f4c99","tests/regression/tga/flip-zero-height.tga":"c4ab9fc92b023833ec567f660548d8abc196a99a33e686ada9bad9a07bdc48c6","tests/regression/tga/flip-zero-height2.tga":"2e2e2e9762edb46a40a9184e7565dc8b4050883d563d17581ddc19fcdcc8758d","tests/regression/tga/overfull-image.tga":"af478d22026e5f57e20a000ac5a6a366215adbc916161a3daba6143846ad8310","tests/regression/tga/sixteen-bit-gray-colormap.tga":"b2c31c19a8d3db57e2841dae94de06fa48356e9ed5abf42736dde763d0b082b7","tests/regression/tga/sixteen-bit-gray-colormap2.tga":"00d75ea0e2bc9fbb9b32c37024f1676367adf754535f952a884cab2b12421a24","tests/regression/tiff/clusterfuzz-testcase-minimized-fuzzer_script_tiff-5026894169374720.tif":"00e4343544412c9a529bbc40f47bf81b0e68a71e5dc6b8011064e51feb631978","tests/regression/webp/panic.webp":"cf34d6890786e48bd00b1a1532de1a8508d96f8b5ca8c1c08b16230db86532af","tests/save_jpeg.rs":"cb2416e3d71f3f10f8986ac808e351663bdf4ffe1b0ad7638e1a5bafd432b53b","tests/truncate_images.rs":"7e14fb550aab465bdae836029b086c91fd8bdad517e5cfb78f5ae9760158c21a"},"package":"5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f60667ae61fc412768f6448ff14e7dc39291738f605c5308fd87ea514200d0f9","CHANGES.md":"98a73cb48e9b6fb10ef23484a2c5b34e84fab32e534e5c2c2db43436c6e91020","Cargo.lock":"67eddeb1b5905b20a42e2007f6829d3b6114f5d6602aa2c1a42221950aaf4945","Cargo.toml":"d79806c07cc951a84a25c3b4991e8c949e36da0d083926eb1a7cf6260ed56a16","Cargo.toml.orig":"51be861a74e1b761254eb507b81b685ad98614047fcbb636fdbaffb475ac4ae9","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"c77a4cf9da729987d0fe7ccd811e3bd27393914ddf3d23467c18cc22954513b3","README.md":"0a4736ce72b0b42d56c07a02fe92ce61911031889638b986692da60c0e594607","benches/README.md":"87b2ea4d1cea80c1e24fc18f1222a7ee1a38f5a92e98110bb84a4827fb997b62","benches/blur.rs":"10a1665e61204fec84ed1e22c31b4758e431d1eedd1f79d67b92ad8888d162f9","benches/copy_from.rs":"b775438ee55f3fbb7565d6d342cac7e455feb709654658cc9d77814bf9ab819b","benches/decode.rs":"a37a94fd64694aee7123224059e9bc95e5e4cdce53c2abf9e86e7c7e48ff3d20","benches/encode.rs":"4d59105c85a4e891c4286b5f87a3fa1d1c51fa4ded84974a2e60fdef324d2beb","benches/fast_blur.rs":"09ed202ff9549ad4e771148318aba36e9e685843f2756777c69c8637f66c173a","src/animation.rs":"26e4ec3e46eed769b3879a784527fb998fd0d99a7b2d84dcb32c93caa6263c2a","src/codecs/avif/decoder.rs":"a68d2e288008d9f7a1d6aadee0cf394df58523a469c163397cef071b06c726db","src/codecs/avif/encoder.rs":"a97eff4551f1b549e85118296dd620a43e88a396be525b637345fae719226aaa","src/codecs/avif/mod.rs":"b3372fe1eaf9c1952094d756acd3233298c401d1d0ed7e3debcc328822a0798c","src/codecs/avif/ycgco.rs":"711d48fef081c73898db1e3427dac0edcf03896b1b4e1f4117aee5b6a6a44dac","src/codecs/avif/yuv.rs":"95b010015215c7868af391e54c7966e27d6ae554c569b65392e91fe0e0f4df55","src/codecs/bmp/decoder.rs":"65b44b407eb8ea0e472f4788d02590010ba0d33425670b98b7d04988360a7b63","src/codecs/bmp/encoder.rs":"e3c25c06e5ebd993405b6d63ea06b51149bc8c62589ee930490a0174ed909ae3","src/codecs/bmp/mod.rs":"00cb001e0a0997a62db013411a6ce8c35c70514037abb856107060e2434be73b","src/codecs/dds.rs":"92a731e7fd32b35131f57addcd36bd96943f8adc6d8251e5cfe5c6a9e0e091db","src/codecs/dxt.rs":"c8d6279d6c793a09d4880b4dc5d21f806a7acadc9ef3ed5f173ea444ba33f68a","src/codecs/farbfeld.rs":"030f24045907f54dd60b79a1156bb0936780b6474f06ba776d4e256a6ec95dd1","src/codecs/gif.rs":"864d5bbede5c50045ed6d328aa93a874155c6b6db52c6502ca0a167059167a69","src/codecs/hdr/decoder.rs":"980ed70b1ed57d4d3ef2c56f07160b7a1681b52a7d09f1c8b5852d5626209d4c","src/codecs/hdr/encoder.rs":"a62b3ac6bdfccf74b32c4c7a57c88ddc068640227a286b691bafe2331acf49aa","src/codecs/hdr/mod.rs":"40eda05d916a62d99448e23c1b4d402de8e3860d09b8dfdc0370403c6f5e538e","src/codecs/ico/decoder.rs":"f976b435200332acee84987e660845257620a31ea29bcc4ac0d9f724882b3813","src/codecs/ico/encoder.rs":"2b5a10efb7750f785735c4a5c41118255fade83f66ba8da5943655f9d00662c4","src/codecs/ico/mod.rs":"cd5f9c67256b2083049bb6f8c8963aedca2be8178e198f9e0851c18e6f956845","src/codecs/jpeg/decoder.rs":"135116b08028d03ba7481f7e704a461e239b01f960f576c1e70f48d7e9616569","src/codecs/jpeg/encoder.rs":"d5081535ac29f040daeeaedf13080c8d4af840be821755419cf057d8aa2b6269","src/codecs/jpeg/entropy.rs":"074975ec5b0040d6caea59f2682e328550d367688d99ee9d0b5674bc7a68682a","src/codecs/jpeg/mod.rs":"696b7f1291bb2201b39d6ce2d5f438080497f8431d8df66c761b7a144d871234","src/codecs/jpeg/transform.rs":"65490ae7ce990dda33044b4c52afc1bdcfa836b474a1b6a06c611af6e53a70db","src/codecs/openexr.rs":"0d822bd4c5199e6b86198cd3a4185a09a145644e0bd8cd4e65151ab3a2557a7f","src/codecs/png.rs":"4c01803f75d816bff7501d2ad2e09b0b413d1dd51b2d1d3f40818070cac35c1c","src/codecs/pnm/autobreak.rs":"b38d8f9db918e7a4be713881224f00a84378de27981d15ccff84e92a70ac259d","src/codecs/pnm/decoder.rs":"119c74cc323c956c51d281ba3601327eb4a663fdde7b2965d87c717797e79f4a","src/codecs/pnm/encoder.rs":"09b4df98566e7ae47247022f240b5785689d02c4197a9a8bffdade6508dd26cc","src/codecs/pnm/header.rs":"7ef17159bc44a9c57cb3093bdbcf80d1919a4dff5354d914b8861a2a8cc986c1","src/codecs/pnm/mod.rs":"3ad8fade4249504d14bece9fb7fab73e6beb1a9ebaed3b1a17b30263ebd47223","src/codecs/qoi.rs":"c991fc5eabf3ba167226f10acde1106cda704b6b789301734e9fd7cda1d02734","src/codecs/tga/decoder.rs":"9d9898580b610688d7a8a45fa27e92c35b859dca4a950a47eb2653b23bc69c50","src/codecs/tga/encoder.rs":"23ebcbb054ddcdd0fb9ef07840d0931c54b307277fd81c421611e89d0aad5c93","src/codecs/tga/header.rs":"f838d3a7ffc1aaced3167f3a9995c76773a7791d1db2f2e5a65742ab10d77986","src/codecs/tga/mod.rs":"e25e77180883c56657097d851427d4f1f3c2add5a9eec24e24bc42d65953b0df","src/codecs/tiff.rs":"e1939632e49cbf2ec028abfc413435cffc8c14d271c0ed1b7132614df1d195fe","src/codecs/webp/decoder.rs":"c8934fbdcde2f2587df4c7640a0894f19a6375a18456bbf8ade8601e2fd00d04","src/codecs/webp/encoder.rs":"0099d2bf04f0dc6cfa15635b1051cc76646d08084d5928b44e8213432c2b3293","src/codecs/webp/mod.rs":"fc317d6c26b4df18c3b326c86fe0a71f2deb9cc72e1267a0324c7d98fd331109","src/color.rs":"a0ed7414d7a07f4d44337b644f4302556b8803e1d1183ed6d115a484e72163ec","src/error.rs":"eb86a2e948122254fecc317c547b7ebe57257d389a7e0a4c9deefb10b0800af5","src/hooks.rs":"9b30b5c4c1b64c491422cc6ffdabae2495eb9e9fd0ce5d1509780b01555bac3e","src/imageops/affine.rs":"61a1bfa8d02c0b7cc7603dfb725e4f75a79f01d17600bb5ea2e6a856c2a598cc","src/imageops/colorops.rs":"e1675b3ecc3f9cc5a2c42fa4539f1c29e4937bfd57e843c94fffaba8e14357d9","src/imageops/fast_blur.rs":"c9642434f80f5d20b951fa64398ea8355383f00816236587435e4a3718d280d8","src/imageops/filter_1d.rs":"a9ba57c1d5725af00d8f5efb21627d94ff7d2db0fc645a13f3eaeae19ae76a40","src/imageops/mod.rs":"376afc01dcbe4677572568f92f798ec67de7fd4a348a08819b5688560ba2fdea","src/imageops/sample.rs":"364962477058be5b8999c7c3667a7e1f997527b62e3c7c1a41216819710fb4e9","src/images.rs":"bac04c9d0242efd6f47db430752ec776a8d0edc4ab4deb09933bfda40bc75020","src/images/buffer.rs":"7d6e7ce7adf420019321c2289ff9333f8c9a814c43a45e61eb501b39a700d341","src/images/buffer_par.rs":"b1072a035617df35dbc5c5dda8777cf3027cbe1b46b9d3fd233faeae72404f62","src/images/dynimage.rs":"66001e5af9d022f5f73242405b62d44f6ec68805b2c9a417c83a954b697eb26f","src/images/flat.rs":"8bc092001829ad01d9f8df995ee77c47a47696e5299e222b5de2e3af7d113ad1","src/images/generic_image.rs":"a2defb55d7c3a1a6cab7e1dbed3463774509e96a4f5f74286c9401bb2d419f91","src/images/sub_image.rs":"c68ca5f3d5eb901da37b52e8414a43ba82608313967cfcc3fef714e50c1ff6ac","src/io.rs":"d9c7fc22afa81b963a2565d4d000497967a6e28739d3ba1acd0c776a7f097f65","src/io/decoder.rs":"992940ec979d1ee2f32b13879e585d188ef2f55239cf2e0f07f9e55f43778d6b","src/io/encoder.rs":"4a2f66ad4977ddb55e25e3ea774d6c90bbcbd029fcc9e8cffa58844c84ea69f3","src/io/format.rs":"dc570d8edefeb9ad1e6424239d875062db1975b4dcd2078db459c1a2d19733ce","src/io/free_functions.rs":"cabda0450ab8aedcff9048e3ec2b4f006a4cf7889f97e57d65349f39005296f1","src/io/image_reader_type.rs":"de35b428b582b96ecd44465f15d5b3d6ba203a060614e79fb1d4866312c12b42","src/io/limits.rs":"a6a291fd1a3da07e240f511fffa06b5500d54894413c0f873b683015bc020787","src/lib.rs":"6e47fec523655d8881a7d638045062f3b30f28e13a0ab041cdaf80027b6156a3","src/math/mod.rs":"88f11f4ee99ce0258633f3bd07bc614e9c69b1045107fe8547715f95abc7470e","src/math/rect.rs":"ab97ae75b85485d45716d810973487a4315e41827718958386abc0f35bd54a68","src/math/utils.rs":"a70c17e2d4276d90a1b76339e4d103bbc6f8b5a77222ef052e744f180e0f27ff","src/metadata.rs":"45dc4f7e23016c8900754150681e9c8d91890545c9264483fe4eaccb810bf7e2","src/metadata/cicp.rs":"85eff874b04641681246c2269902af232541337ebd6eb12c7b2142a17a1eb6b0","src/traits.rs":"070fbe6aa657a043d56ecbfa129e4f56df58f04ce32cca5cbb4f57c21c0e3d8b","src/utils/mod.rs":"2efe2fa09d0b6119c1cc96316454caf05319a69af7dfab61cb28dc320c1c7be8"},"package":"e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/image/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5ceb6af6c2b6671931a02fda955ce1676321711d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/CHANGES.md clamav-1.4.6+dfsg/.cargo/vendor/image/CHANGES.md --- clamav-1.4.3+dfsg/.cargo/vendor/image/CHANGES.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/CHANGES.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,171 @@ # Release Notes ## Known issues -- Many decoders will panic on malicous input. In most cases, this is caused by - not enforcing memory limits, though other panics have been seen from fuzzing. +- Many decoders will panic on malicious input. - The color space information of pixels is not clearly communicated. ## Changes +### Version 0.25.9 + +Features: + - Support extracting XMP metadata from PNG, JPEG, GIF, WebP and TIFF files (#2567, #2634, #2644) + - Support reading IPTC metadata from PNG and JPG files (#2611) + - Support reading ICC profile from GIF files (#2644) + - Allow setting a specific DEFLATE compression level when writing PNG (#2583) + - Initial support for 16-bit CMYK TIFF files (#2588) + - Allow extracting the alpha channel of a `Pixel` in a generic way (#2638) + +Structural changes: + - EXR format decoding now only uses multi-threading via Rayon when the `rayon` feature is enabled (#2643) + - Upgraded zune-jpeg to 0.5.x, ravif to 0.12.x, gif to 0.14.x + - pnm: parse integers in PBM/PGM/PPM headers without allocations (#2620) + - Replace `doc_auto_cfg` with `doc_cfg` (#2637) + +Bug fixes: + - Do not encode empty JPEG images (#2624) + - tga: reject empty images (#2614) + - tga: fix orientation flip for color mapped images (#2607) + - tga: adjust colormap lookup to match tga 2.0 spec (#2608) + +### Version 0.25.8 + +Re-release of `0.25.7` + +Fixes: +- Reverted a signature change to `load_from_memory` that lead to large scale + type inference breakage despite being technically compatible. +- Color conversion Luma to Rgb used incorrect coefficients instead of broadcasting. + +### Version 0.25.7 (yanked) + +Features: + - Added an API for external image format implementations to register themselves as decoders for a specific format in `image` (#2372) + - Added [CICP](https://www.color.org/iccmax/download/CICP_tag_and_type_amendment.pdf) awarenes via [moxcms](https://crates.io/crates/moxcms) to support color spaces (#2531). The support for transforming is limited for now and will be gradually expanded. + - You can now embed Exif metadata when writing JPEG, PNG and WebP images (#2537, #2539) + - Added functions to extract orientation from Exif metadata and optionally clear it in the Exif chunk (#2484) + - Serde support for more types (#2445) + - PNM encoder now supports writing 16-bit images (#2431) + +Structural changes: + - Increased MSRV to 1.85.0 (from 1.78.0) + +API improvements: + - `save`, `save_with_format`, `write_to` and `write_with_encoder` methods on `DynamicImage` now automatically convert the pixel format when necessary instead of returning an error (#2501) + - Added `DynamicImage::has_alpha()` convenience method + - Implemented `TryFrom` for `ColorType` (#2444) + - Added `const HAS_ALPHA` to trait `Pixel` + - Unified the error for unsupported encoder colors (#2543) + - Added a `hooks` module to customize builtin behavior, `register_format_detection_hook` and `register_decoding_hook` for the determining format of a file and selecting an `ImageDecoder` implementation respectively. (#2372) + +Performance improvements: + - Gaussian blur (#2496) and box blur (#2515) are now faster + - Improve compilation times by avoiding unnecessary instantiation of generic functions (#2468, #2470) + +Bug fixes: + - Many improvements to image format decoding: TIFF, WebP, AVIF, PNG, GIF, BMP, TGA + - Fixed `GifEncoder::encode()` ignoring the speed parameter and always using the slowest speed (#2504) + - `.pnm` is now recognized as a file extension for the PNM format (#2559) + + +### Version 0.25.6 + +Features: + - Improved format detection ([#2418](https://github.com/image-rs/image/pull/2418)) + - Implement writing ICC profiles for JPEG and PNG images ([#2389](https://github.com/image-rs/image/pull/2389)) + +Bug fixes: + - JPEG encoding bugfix ([#2387](https://github.com/image-rs/image/pull/2387)) + - Expanded ICO format detection ([#2434](https://github.com/image-rs/image/pull/2434)) + - Fixed EXR bug with NaNs ([#2381](https://github.com/image-rs/image/pull/2381)) + - Various documentation improvements + +### Version 0.25.5 + +Features: + - Added support for decoding 10-bit and 12-bit AVIF + - Initial, opt-in serde support for an enum. This may be extended to other types in the future. + +Bug fixes: + - [Multiple bug fixes in AVIF decoding](https://github.com/image-rs/image/pull/2373) + - The `rayon` feature now correctly toggles the use of `rayon` when encoding AVIF. (Previously it would be either always on or always off depending on the version of the `ravif` crate in your dependency tree.) + - "jfif" file extension for JPEG images is now recognized + +### Version 0.25.4 + +Features: + - Much faster decoding of lossless WebP due to a variety of optimizations. Our benchmarks show 2x to 2.5x improvement. + - Added support for orientation metadata, so that e.g. smartphone camera images could be displayed correctly: + - Added `ImageDecoder::orientation()` and implemented orientation metadata extraction for JPEG, WebP and TIFF formats + - Added `DynamicImage::apply_orientation()` to apply the orientation to an image + - Added support for extracting Exif metadata from images via `ImageDecoder::exif_metadata()`, and implemented it for JPEG and WebP formats + - Added `ImageEncoder::set_icc_profile()` and implemented it for WebP format. Pull requests with implementations for other formats are welcome. + - Added `DynamicImage::fast_blur()` for a linear-time approximation of Gaussian blur, which is much faster at larger blur radii + +Bug fixes: + - Fixed some APNG images being decoded incorrectly + - Fixed the iterator over animated WebP frames to return `None` instead of an error when the end of the animation is reached + +### Version 0.25.3 + +Yanked! This version accidentally missed a commit that should have been +included with the release. The `Orientation` struct should be in the +appropriate module instead of the top-level. This release won't be supported. + +### Version 0.25.2 + +Features: +- Added the HDR encoder to supported formats in generic write methods with the + `hdr` feature enabled. Supports 32-bit float RGB color only, for now. +- When cloning `ImageBuffer`, `DynamicImage` and `Frame` the existing buffer + will now be reused if possible. +- Added `image::ImageReader` as an alias. +- Implement `ImageEncoder` for `HdrEncoder`. + +Structural changes +- Switch from `byteorder` to `byteorder-lite`, consolidating some casting + unsafety to `bytemuck`. +- Many methods on `DynamicImage` and buffers gained `#[must_use]` indications. + +Bug fixes: +- Removed test data included in the crate archive. +- The WebP animation decoder stops when reaching the indicate frame count. +- Fixed bugs in the `bmp` decoder. +- Format support gated on the `exr` feature now compiles in isolation. + +### Version 0.25.1 + +Bug fixes: +- Fixed corrupt JPEG output when attempting to encode images containing an alpha + channel. +- Only accept ".ff" file extension for farbfeld images. +- Correct farbfeld feature flag for `ImageFormat::{reading_enabled, writing_enabled}`. +- Disable strict mode for JPEG decoder. +- Add nasm feature to optionally enable faster AVIF encoding. + + +### Version 0.25.0 + +Breaking changes: +- Added `BufRead` + `Seek` bound on many decoders. +- Use `ExtendedColorType` instead of `ColorType` when encoding. +- Removed `ImageOutputFormat`, `GenericImageView::bounds`, and several other + deprecated items. +- Removed incremental decoding support and changed `ImageDecoder` so the trait + is object safe. +- Pixel types are now `repr(transparent)` rather than `repr(C)`. +- Made color_quant dependency optional. +- Renamed some feature flags. + +Structural changes: +- Increased MSRV to 1.67.1 + +Codec changes: +- Switched to image-webp for WebP encoding. +- Switched to zune-jpeg for JPEG decoding. +- Made the HDR decoder produce f32 images. +- Removed DXT encoding and decoding support. + ### Version 0.24.9 Structural changes: @@ -21,7 +180,7 @@ Bug fixes: - Correct limit tests for TIFF. - Avoid overflow in gif::Decoder::buffer_size. -- Return error instead of using asssertion for Avif decoder unsupported or +- Return error instead of using assertions for Avif decoder unsupported or invalid bit depth. ### Version 0.24.8 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -1,57 +1,68 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.9" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "cfg-if", + "getrandom 0.2.7", "once_cell", "version_check", - "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.1.2" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] [[package]] -name = "anes" -version = "0.1.6" +name = "aligned" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] [[package]] -name = "anstyle" -version = "1.0.6" +name = "aligned-vec" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" [[package]] -name = "anyhow" -version = "1.0.80" +name = "aligned-vec" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] [[package]] -name = "arbitrary" -version = "0.4.7" +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anyhow" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "arbitrary" @@ -67,16 +78,22 @@ dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" dependencies = [ - "serde", + "stable_deref_trait", ] [[package]] @@ -86,34 +103,67 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] +name = "av-data" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b98a3525d00f920df9a2d44cc99b9cc5b7dc70d7fbb612cd755270dbe6552" +dependencies = [ + "byte-slice-cast", + "bytes", + "num-derive", + "num-rational", + "num-traits", + "thiserror 1.0.59", +] + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.17", + "v_frame", + "y4m", +] + +[[package]] name = "av1-grain" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" dependencies = [ "anyhow", "arrayvec", "log", "nom", "num-rational", - "serde", "v_frame", ] [[package]] name = "avif-serialize" -version = "0.8.1" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" dependencies = [ "arrayvec", ] [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" [[package]] name = "bitflags" @@ -123,75 +173,69 @@ [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitreader" -version = "0.3.8" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd859c9d97f7c468252795b35aeccc412bdbb1e90ee6969c4fa6328272eaeff" +checksum = "d84ea71c85d1fe98fe67a9b9988b1695bc24c0b0d3bfb18d4c510f44b4b09941" dependencies = [ "cfg-if", ] [[package]] name = "bitstream-io" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e445576659fd04a57b44cbd00aa37aaa815ebefa0aa3cb677a6b5e63d883074f" - -[[package]] -name = "bitstream-io" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c9989a51171e2e81038ab168b6ae22886fe9ded214430dbb4f41c28cf176da" - -[[package]] -name = "built" -version = "0.5.2" +version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9c056b9ed43aee5e064b683aa1ec783e19c6acec7559e3ae931b7490472fbe" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" dependencies = [ - "cargo-lock", + "core2", ] [[package]] name = "built" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d17f4d6e4dc36d1a02fbedc2753a096848e7c1b0772f7654eab8e2c927dd53" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" -version = "1.5.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] -name = "cargo-lock" -version = "8.0.3" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031718ddb8f78aa5def78a09e90defe30151d1f6c672f937af4dd916429ed996" -dependencies = [ - "semver", - "serde", - "toml 0.5.11", - "url", -] +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cast" @@ -201,18 +245,20 @@ [[package]] name = "cc" -version = "1.0.86" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ + "jobserver", "libc", + "shlex", ] [[package]] name = "cfg-expr" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", "target-lexicon", @@ -253,28 +299,22 @@ [[package]] name = "clap" -version = "4.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.1" +version = "4.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ - "anstyle", + "bitflags 1.3.2", "clap_lex", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] [[package]] name = "color_quant" @@ -283,10 +323,19 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] name = "crc32fast" -version = "1.4.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] @@ -329,28 +378,36 @@ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ + "autocfg", + "cfg-if", "crossbeam-utils", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +dependencies = [ + "cfg-if", +] [[package]] name = "crunchy" @@ -360,12 +417,14 @@ [[package]] name = "dav1d" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7eb1fa9954b7ae85ff0d43ef6d186d1b3469d4aa1574845d1938bef05377030" +checksum = "0d4b54a40baf633a71c6f0fb49494a7e4ee7bc26f3e727212b6cb915aa1ea1e1" dependencies = [ - "bitflags 2.4.2", + "av-data", + "bitflags 2.5.0", "dav1d-sys", + "static_assertions", ] [[package]] @@ -379,20 +438,10 @@ ] [[package]] -name = "dcv-color-primitives" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ad62edfed069700a5b33af6babd29c498d7e33eb01d96ffa8841ee1841634c" -dependencies = [ - "paste", - "wasm-bindgen", -] - -[[package]] name = "either" -version = "1.10.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "env_logger" @@ -405,6 +454,26 @@ ] [[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -412,12 +481,11 @@ [[package]] name = "exr" -version = "1.72.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", - "flume", "half", "lebe", "miniz_oxide", @@ -428,55 +496,57 @@ [[package]] name = "fallible_collections" -version = "0.4.9" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" +checksum = "c195cf4b2285d3c993eb887b4dc56b0d5728bbe1d0f9a99c0ac6bec2da3e4d85" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.12.3", ] [[package]] -name = "fdeflate" -version = "0.3.4" +name = "fax" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" dependencies = [ - "simd-adler32", + "fax_derive", ] [[package]] -name = "flate2" -version = "1.0.28" +name = "fax_derive" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" dependencies = [ - "crc32fast", - "miniz_oxide", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "flume" -version = "0.11.0" +name = "fdeflate" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ - "spin", + "simd-adler32", ] [[package]] -name = "form_urlencoded" -version = "1.2.1" +name = "flate2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ - "percent-encoding", + "crc32fast", + "miniz_oxide", ] [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -484,10 +554,22 @@ ] [[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] name = "gif" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +checksum = "f954a9e9159ec994f73a30a12b96a702dde78f5547bcb561174597924f7d4162" dependencies = [ "color_quant", "weezl", @@ -495,15 +577,15 @@ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "half" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", @@ -511,56 +593,46 @@ [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" - -[[package]] -name = "idna" -version = "0.5.0" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "image" -version = "0.24.9" +version = "0.25.9" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", "color_quant", "crc32fast", "criterion", "dav1d", - "dcv-color-primitives", "exr", "gif", "glob", - "jpeg-decoder", + "image-webp", + "moxcms", "mp4parse", "num-complex", "num-traits", @@ -570,24 +642,36 @@ "ravif", "rayon", "rgb", + "serde", "tiff", - "webp", + "zune-core 0.5.0", + "zune-jpeg 0.5.5", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", ] [[package]] name = "imgref" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -598,7 +682,7 @@ dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] @@ -623,33 +707,33 @@ [[package]] name = "itertools" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] -name = "jpeg-decoder" -version = "0.3.1" +name = "jobserver" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "rayon", + "libc", ] [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -662,19 +746,9 @@ [[package]] name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "libfuzzer-sys" -version = "0.3.5" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef" -dependencies = [ - "arbitrary 0.4.7", - "cc", -] +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libfuzzer-sys" @@ -682,38 +756,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" dependencies = [ - "arbitrary 1.3.2", + "arbitrary", "cc", "once_cell", ] [[package]] -name = "libwebp-sys" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829b6b604f31ed6d2bccbac841fe0788de93dbd87e4eb1ba2c4adfe8c012a838" -dependencies = [ - "cc", - "glob", -] - -[[package]] -name = "lock_api" -version = "0.4.11" +name = "log" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "autocfg", - "scopeguard", + "cfg-if", ] [[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] name = "loop9" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -724,9 +781,9 @@ [[package]] name = "maybe-rayon" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +checksum = "57c0bd354d2614d2feeb08dd2afdb744a91ad3c886e2a04dac63e12fb32eb7f7" dependencies = [ "cfg-if", "rayon", @@ -734,27 +791,40 @@ [[package]] name = "memchr" -version = "2.7.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "memoffset" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] +name = "moxcms" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] name = "mp4parse" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -770,11 +840,12 @@ [[package]] name = "nasm-rs" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4d98d0065f4b1daf164b3eafb11974c94662e5e2396cf03f32d0bb5c17da51" +checksum = "34f676553b60ccbb76f41f9ae8f2428dac3f259ff8f1c2468a174778d06a1af9" dependencies = [ - "rayon", + "jobserver", + "log", ] [[package]] @@ -785,12 +856,11 @@ [[package]] name = "nom" -version = "7.1.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" dependencies = [ "memchr", - "minimal-lexical", ] [[package]] @@ -801,9 +871,9 @@ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -812,51 +882,40 @@ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", ] [[package]] name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-derive" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ + "autocfg", "num-traits", ] [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -864,9 +923,9 @@ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -884,28 +943,34 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] name = "paste" -version = "1.0.14" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] -name = "percent-encoding" -version = "2.3.1" +name = "pastey" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -916,26 +981,26 @@ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "png" -version = "0.17.13" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "crc32fast", "fdeflate", "flate2", @@ -944,15 +1009,15 @@ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -973,7 +1038,16 @@ checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.50", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069f3b41a7e17d18b8af925e597c8b2430591341415f98c5e1ecb2a245cea7ae" +dependencies = [ + "num-traits", ] [[package]] @@ -999,37 +1073,51 @@ dependencies = [ "env_logger", "log", - "rand", + "rand 0.8.5", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.3", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", ] [[package]] @@ -1038,104 +1126,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.7", ] [[package]] -name = "rav1e" -version = "0.6.6" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c383692a5e7abd9f6d1eddb1a5e0269f859392387883361bb09e5555852ec1" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "arbitrary 0.4.7", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io 1.10.0", - "built 0.5.2", - "cc", - "cfg-if", - "interpolate_name", - "itertools 0.10.5", - "libc", - "libfuzzer-sys 0.3.5", - "log", - "maybe-rayon", - "nasm-rs", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive 0.3.3", - "num-traits", - "once_cell", - "paste", - "rand", - "rand_chacha", - "rust_hawktracer", - "rustc_version", - "simd_helpers", - "system-deps", - "thiserror", - "v_frame", - "wasm-bindgen", + "getrandom 0.3.4", ] [[package]] name = "rav1e" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" dependencies = [ - "arbitrary 1.3.2", + "aligned-vec 0.6.4", + "arbitrary", "arg_enum_proc_macro", "arrayvec", + "av-scenechange", "av1-grain", - "bitstream-io 2.2.0", - "built 0.7.1", + "bitstream-io", + "built", "cc", "cfg-if", "interpolate_name", - "itertools 0.12.1", + "itertools 0.14.0", "libc", - "libfuzzer-sys 0.4.7", + "libfuzzer-sys", "log", "maybe-rayon", "nasm-rs", "new_debug_unreachable", "noop_proc_macro", - "num-derive 0.4.2", + "num-derive", "num-traits", - "once_cell", "paste", "profiling", - "rand", + "rand 0.9.2", "rand_chacha", "simd_helpers", - "system-deps", - "thiserror", + "thiserror 2.0.17", "v_frame", + "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44feba0b8a381a5efa2c0baf8dace8418904403260233f4a614503b018fc288" +checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" dependencies = [ "avif-serialize", "imgref", "loop9", "quick-error", - "rav1e 0.6.6", - "rav1e 0.7.1", + "rav1e", "rayon", "rgb", ] [[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1153,21 +1212,9 @@ [[package]] name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -1176,55 +1223,21 @@ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "rust_hawktracer" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3480a29b927f66c6e06527be7f49ef4d291a01d694ec1fe85b0de71d6b02ac1" -dependencies = [ - "rust_hawktracer_normal_macro", - "rust_hawktracer_proc_macro", -] - -[[package]] -name = "rust_hawktracer_normal_macro" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a570059949e1dcdc6f35228fa389f54c2c84dfe0c94c05022baacd56eacd2e9" - -[[package]] -name = "rust_hawktracer_proc_macro" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb626abdbed5e93f031baae60d72032f56bc964e11ac2ff65f2ba3ed98d6d3e1" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -1237,44 +1250,35 @@ [[package]] name = "scopeguard" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" -dependencies = [ - "serde", -] +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074" dependencies = [ "itoa", "ryu", @@ -1291,6 +1295,12 @@ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1307,18 +1317,15 @@ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] -name = "spin" -version = "0.9.8" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -1328,20 +1335,9 @@ [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.50" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1350,14 +1346,14 @@ [[package]] name = "system-deps" -version = "6.2.0" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 0.8.10", + "toml", "version-compare", ] @@ -1369,74 +1365,73 @@ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.59", ] [[package]] -name = "thiserror-impl" -version = "1.0.57" +name = "thiserror" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", + "thiserror-impl 2.0.17", ] [[package]] -name = "tiff" -version = "0.9.1" +name = "thiserror-impl" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tinytemplate" -version = "1.2.1" +name = "thiserror-impl" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ - "serde", - "serde_json", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tiff" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" dependencies = [ - "tinyvec_macros", + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg 0.4.20", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "toml" -version = "0.5.11" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", + "serde_json", ] [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -1455,9 +1450,9 @@ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", @@ -1467,55 +1462,27 @@ ] [[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "2.5.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "v_frame" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c372e4e6fad129795fb86fda6021b258948560b39883b80ed00510a7d19846b0" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" dependencies = [ - "cfg-if", - "noop_proc_macro", - "num-derive 0.4.2", + "aligned-vec 0.5.0", "num-traits", - "profiling", + "wasm-bindgen", ] [[package]] name = "version-compare" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" @@ -1525,11 +1492,12 @@ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", + "winapi", "winapi-util", ] @@ -1540,10 +1508,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1551,24 +1528,24 @@ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1576,47 +1553,38 @@ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] -name = "webp" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb5d8e7814e92297b0e1c773ce43d290bef6c17452dafd9fc49e5edb5beba71" -dependencies = [ - "libwebp-sys", -] - -[[package]] name = "weezl" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi" @@ -1636,9 +1604,9 @@ [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] @@ -1660,13 +1628,14 @@ [[package]] name = "windows-targets" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -1675,74 +1644,84 @@ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.52.3" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.2" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] [[package]] -name = "zerocopy" -version = "0.7.32" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] -name = "zerocopy-derive" -version = "0.7.32" +name = "y4m" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", -] +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" [[package]] name = "zune-inflate" @@ -1752,3 +1731,21 @@ dependencies = [ "simd-adler32", ] + +[[package]] +name = "zune-jpeg" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +dependencies = [ + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fb7703e32e9a07fb3f757360338b3a567a5054f21b5f52a666752e333d58e" +dependencies = [ + "zune-core 0.5.0", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,10 +11,29 @@ [package] edition = "2021" -rust-version = "1.63.0" +rust-version = "1.85.0" name = "image" -version = "0.24.9" +version = "0.25.9" authors = ["The image-rs Developers"] +build = false +exclude = [ + "src/png/testdata/*", + "examples/*", + "tests/*", +] +include = [ + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/CHANGES.md", + "/src/", + "/benches/", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Imaging library. Provides basic image processing and encoders/decoders for common image formats." homepage = "https://github.com/image-rs/image" documentation = "https://docs.rs/image" @@ -28,21 +47,93 @@ repository = "https://github.com/image-rs/image" resolver = "2" +[package.metadata.cargo-semver-checks.lints.enum_discriminants_undefined_non_unit_variant] +level = "warn" + [package.metadata.docs.rs] all-features = true -include = [ - "/LICENSE-APACHE", - "/LICENSE-MIT", - "/README.md", - "/CHANGES.md", - "/src/", - "/benches/", -] rustdoc-args = [ "--cfg", "docsrs", ] +[features] +avif = [ + "dep:ravif", + "dep:rgb", +] +avif-native = [ + "dep:mp4parse", + "dep:dav1d", +] +benchmarks = [] +bmp = [] +color_quant = ["dep:color_quant"] +dds = [] +default = [ + "rayon", + "default-formats", +] +default-formats = [ + "avif", + "bmp", + "dds", + "exr", + "ff", + "gif", + "hdr", + "ico", + "jpeg", + "png", + "pnm", + "qoi", + "tga", + "tiff", + "webp", +] +exr = ["dep:exr"] +ff = [] +gif = [ + "dep:gif", + "dep:color_quant", +] +hdr = [] +ico = [ + "bmp", + "png", +] +jpeg = [ + "dep:zune-core", + "dep:zune-jpeg", +] +nasm = ["ravif?/asm"] +png = ["dep:png"] +pnm = [] +qoi = ["dep:qoi"] +rayon = [ + "dep:rayon", + "ravif?/threading", + "exr?/rayon", +] +serde = ["dep:serde"] +tga = [] +tiff = ["dep:tiff"] +webp = ["dep:image-webp"] + +[lib] +name = "image" +path = "src/lib.rs" + +[[bench]] +name = "blur" +path = "benches/blur.rs" +harness = false + +[[bench]] +name = "copy_from" +path = "benches/copy_from.rs" +harness = false + [[bench]] name = "decode" path = "benches/decode.rs" @@ -54,46 +145,40 @@ harness = false [[bench]] -name = "copy_from" +name = "fast_blur" +path = "benches/fast_blur.rs" harness = false [dependencies.bytemuck] version = "1.8.0" features = ["extern_crate_alloc"] -[dependencies.byteorder] -version = "1.3.2" +[dependencies.byteorder-lite] +version = "0.1.0" [dependencies.color_quant] version = "1.1" - -[dependencies.dav1d] -version = "0.10.2" optional = true -[dependencies.dcv-color-primitives] -version = "0.6.1" +[dependencies.dav1d] +version = "0.10.3" optional = true [dependencies.exr] -version = "1.5.0" +version = "1.74.0" optional = true +default-features = false [dependencies.gif] -version = "0.13" +version = "0.14.0" optional = true -[dependencies.jpeg] -version = "0.3.0" +[dependencies.image-webp] +version = "0.2.0" optional = true -default-features = false -package = "jpeg-decoder" -[dependencies.libwebp] -version = "0.2.2" -optional = true -default-features = false -package = "webp" +[dependencies.moxcms] +version = "0.7.4" [dependencies.mp4parse] version = "0.17.0" @@ -103,7 +188,7 @@ version = "0.2.0" [dependencies.png] -version = "0.17.6" +version = "0.18.0" optional = true [dependencies.qoi] @@ -111,19 +196,35 @@ optional = true [dependencies.ravif] -version = "0.11.0" +version = "0.12" optional = true +default-features = false [dependencies.rayon] version = "1.7.0" optional = true [dependencies.rgb] -version = "0.8.25" +version = "0.8.48" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0.214" +features = ["derive"] optional = true [dependencies.tiff] -version = "0.9.0" +version = "0.10.3" +optional = true + +[dependencies.zune-core] +version = "0.5.0" +optional = true +default-features = false + +[dependencies.zune-jpeg] +version = "0.5.5" optional = true [dev-dependencies.crc32fast] @@ -135,64 +236,8 @@ [dev-dependencies.glob] version = "0.3" -[dev-dependencies.jpeg] -version = "0.3.0" -features = ["platform_independent"] -default-features = false -package = "jpeg-decoder" - [dev-dependencies.num-complex] version = "0.4" [dev-dependencies.quickcheck] version = "1" - -[features] -avif = ["avif-encoder"] -avif-decoder = [ - "mp4parse", - "dcv-color-primitives", - "dav1d", -] -avif-encoder = [ - "ravif", - "rgb", -] -benchmarks = [] -bmp = [] -dds = ["dxt"] -default = [ - "gif", - "jpeg", - "ico", - "png", - "pnm", - "tga", - "tiff", - "webp", - "bmp", - "hdr", - "dxt", - "dds", - "farbfeld", - "jpeg_rayon", - "openexr", - "qoi", -] -dxt = [] -farbfeld = [] -hdr = [] -ico = [ - "bmp", - "png", -] -jpeg_rayon = ["jpeg/rayon"] -openexr = ["exr"] -pnm = [] -qoi = ["dep:qoi"] -tga = [] -webp = [] -webp-encoder = [ - "libwebp", - "webp", -] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +[package] +name = "image" +version = "0.25.9" +edition = "2021" +resolver = "2" + +# note: when changed, also update test runner in `.github/workflows/rust.yml` +rust-version = "1.85.0" + +license = "MIT OR Apache-2.0" +description = "Imaging library. Provides basic image processing and encoders/decoders for common image formats." +authors = ["The image-rs Developers"] +readme = "README.md" + +# crates.io metadata +documentation = "https://docs.rs/image" +repository = "https://github.com/image-rs/image" +homepage = "https://github.com/image-rs/image" +categories = ["multimedia::images", "multimedia::encoding", "encoding"] + +# Crate build related +exclude = ["src/png/testdata/*", "examples/*", "tests/*"] + +include = [ + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/CHANGES.md", + "/src/", + "/benches/", +] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +bytemuck = { version = "1.8.0", features = ["extern_crate_alloc"] } # includes cast_vec +byteorder-lite = "0.1.0" +moxcms = { version = "0.7.4" } +num-traits = { version = "0.2.0" } + +# Optional dependencies +color_quant = { version = "1.1", optional = true } +dav1d = { version = "0.10.3", optional = true } +exr = { version = "1.74.0", default-features = false, optional = true } +gif = { version = "0.14.0", optional = true } +image-webp = { version = "0.2.0", optional = true } +mp4parse = { version = "0.17.0", optional = true } +png = { version = "0.18.0", optional = true } +qoi = { version = "0.4", optional = true } +ravif = { version = "0.12", default-features = false, optional = true } +rayon = { version = "1.7.0", optional = true } +rgb = { version = "0.8.48", default-features = false, optional = true } +tiff = { version = "0.10.3", optional = true } +zune-core = { version = "0.5.0", default-features = false, optional = true } +zune-jpeg = { version = "0.5.5", optional = true } +serde = { version = "1.0.214", optional = true, features = ["derive"] } + +[dev-dependencies] +crc32fast = "1.2.0" +num-complex = "0.4" +glob = "0.3" +quickcheck = "1" +criterion = "0.5.0" + +[features] +default = ["rayon", "default-formats"] + +# Format features +default-formats = ["avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp"] +avif = ["dep:ravif", "dep:rgb"] +bmp = [] +dds = [] +exr = ["dep:exr"] +ff = [] # Farbfeld image format +gif = ["dep:gif", "dep:color_quant"] +hdr = [] +ico = ["bmp", "png"] +jpeg = ["dep:zune-core", "dep:zune-jpeg"] +png = ["dep:png"] +pnm = [] +qoi = ["dep:qoi"] +tga = [] +tiff = ["dep:tiff"] +webp = ["dep:image-webp"] + +# Other features +rayon = ["dep:rayon", "ravif?/threading", "exr?/rayon"] # Enables multi-threading +nasm = ["ravif?/asm"] # Enables use of nasm by rav1e (requires nasm to be installed) +color_quant = ["dep:color_quant"] # Enables color quantization +avif-native = ["dep:mp4parse", "dep:dav1d"] # Enable native dependency libdav1d +benchmarks = [] # Build some inline benchmarks. Useful only during development (requires nightly Rust) +serde = ["dep:serde"] + +[[bench]] +path = "benches/decode.rs" +name = "decode" +harness = false + +[[bench]] +path = "benches/encode.rs" +name = "encode" +harness = false + +[[bench]] +name = "copy_from" +harness = false + +[[bench]] +path = "benches/fast_blur.rs" +name = "fast_blur" +harness = false + +[[bench]] +path = "benches/blur.rs" +name = "blur" +harness = false + +# because of https://github.com/image-rs/image/pull/2583 +# TODO: remove when shipping the next major release after 0.25 +[package.metadata.cargo-semver-checks.lints] +enum_discriminants_undefined_non_unit_variant = { level = "warn" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml.public-private-dependencies clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.public-private-dependencies --- clamav-1.4.3+dfsg/.cargo/vendor/image/Cargo.toml.public-private-dependencies 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/Cargo.toml.public-private-dependencies 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -cargo-features = ["public-dependency"] - -[package] -name = "image" -version = "0.24.0-alpha" -edition = "2021" -rust-version = "1.63.0" - -license = "MIT" -description = "Imaging library written in Rust. Provides basic filters and decoders for the most common image formats." -authors = ["The image-rs Developers"] -readme = "README.md" - -# crates.io metadata -documentation = "https://docs.rs/image" -repository = "https://github.com/image-rs/image" -homepage = "https://github.com/image-rs/image" -categories = ["multimedia::images", "multimedia::encoding"] - -# Crate build related -exclude = [ - "src/png/testdata/*", - "examples/*", - "tests/*", -] - -[lib] -name = "image" -path = "./src/lib.rs" - -[dependencies] -bytemuck = { version = "1.7.0", features = ["extern_crate_alloc"] } # includes cast_vec -byteorder = "1.3.2" -num-iter = "0.1.32" -num-rational = { version = "0.4", default-features = false } -num-traits = { version = "0.2.0", public = true } -gif = { version = "0.11.1", optional = true } -jpeg = { package = "jpeg-decoder", version = "0.2.1", default-features = false, optional = true } -png = { version = "0.17.0", optional = true } -tiff = { version = "0.9.0", optional = true } -ravif = { version = "0.8.0", optional = true } -rgb = { version = "0.8.25", optional = true } -mp4parse = { version = "0.12.0", optional = true } -dav1d = { version = "0.6.0", optional = true } -dcv-color-primitives = { version = "0.4.0", optional = true } -exr = { version = "1.4.1", optional = true } -color_quant = { version = "1.1", public = true } - -[dev-dependencies] -crc32fast = "1.2.0" -num-complex = "0.4" -glob = "0.3" -quickcheck = "1" -criterion = "0.3" - -[features] -# TODO: Add "avif" to this list while preparing for 0.24.0 -default = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld", "jpeg_rayon", "openexr"] - -ico = ["bmp", "png"] -pnm = [] -tga = [] -webp = [] -bmp = [] -hdr = [] -dxt = [] -dds = ["dxt"] -farbfeld = [] -openexr = ["exr"] - -# Enables multi-threading. -# Requires latest stable Rust. -jpeg_rayon = ["jpeg/rayon"] -# Non-default, enables avif support. -# Requires latest stable Rust. -avif = ["avif-encoder"] -# Requires latest stable Rust and recent nasm (>= 2.14). -avif-encoder = ["ravif", "rgb"] -# Non-default, even in `avif`. Requires stable Rust and native dependency libdav1d. -avif-decoder = ["mp4parse", "dcv-color-primitives", "dav1d"] - -# Build some inline benchmarks. Useful only during development. -# Requires rustc nightly for feature test. -benchmarks = [] - -[[bench]] -path = "benches/decode.rs" -name = "decode" -harness = false - -[[bench]] -path = "benches/encode.rs" -name = "encode" -harness = false - -[[bench]] -name = "copy_from" -harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/README.md clamav-1.4.6+dfsg/.cargo/vendor/image/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/image/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -4,7 +4,7 @@ [![Build Status](https://github.com/image-rs/image/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image/actions) [![Gitter](https://badges.gitter.im/image-rs/image.svg)](https://gitter.im/image-rs/image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -Maintainers: [@HeroicKatora](https://github.com/HeroicKatora), [@fintelia](https://github.com/fintelia) +Maintainers: [@197g](https://github.com/197g), [@fintelia](https://github.com/fintelia) [How to contribute](https://github.com/image-rs/organization/blob/master/CONTRIBUTING.md) @@ -14,34 +14,78 @@ All image processing functions provided operate on types that implement the `GenericImageView` and `GenericImage` traits and return an `ImageBuffer`. +## High level API + +Load images using [`ImageReader`]: + +```rust,ignore +use std::io::Cursor; +use image::ImageReader; + +let img = ImageReader::open("myimage.png")?.decode()?; +let img2 = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?.decode()?; +``` + +And save them using [`save`] or [`write_to`] methods: + +```rust,ignore +img.save("empty.jpg")?; + +let mut bytes: Vec = Vec::new(); +img2.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)?; +``` + ## Supported Image Formats -`image` provides implementations of common image format encoders and decoders. +With default features enabled, `image` provides implementations of [many common +image format encoders and decoders.](https://docs.rs/image/latest/image/codecs/index.html#supported-formats) + +Decoding support for additional image formats is provided by +[`image-extras`](https://github.com/image-rs/image-extras), and the same plugin +interface lets third-party crates act as format implementations for `image`. If +you need to handle some other image format, check crates.io for crates that +implement it. + +## Feature Flags + +| Feature | Description +| ----------------- | ----------- +| `default-formats` | **Default**
Format support for common image formats: AVIF, BMP, DDS, EXR, FF, GIF, HDR, ICO, JPEG, PNG, PNM, QOI, TGA, TIFF, and WebP +| `rayon` | **Default**
Enables multi-threading with rayon context in some dependencies +| `nasm` | Enables the build-time use of `nasm` for `ravif`, requires `nasm` installed +| `color_quant` | Includes `color_quant` as an implementation of `imageops::ColorMap` +| `avif-native` | Enables non-Rust dependencies of `avif` (`mp4parse` and `dav1d`) +| `serde` | Enables `serde` integration for various structs and options + +Note: When using `image` in a library you intend to publish, it is recommended to set `default-features = false` and then explicitly enable format features that are absolutely necessary. This ensures a smaller dependency tree and faster iteration time. The default feature configuration would also enable multithreading which may cause unexpected behavior when running for inherently single-threaded environments such as `wasm` targets. + +## Image Types + +This crate provides a number of different types for representing images. +Individual pixels within images are indexed with (0,0) at the top left corner. + +### [`ImageBuffer`](https://docs.rs/image/*/image/struct.ImageBuffer.html) +An image parameterised by its Pixel type, represented by a width and height and +a vector of pixels. It provides direct access to its pixels and implements the +`GenericImageView` and `GenericImage` traits. + +### [`DynamicImage`](https://docs.rs/image/*/image/enum.DynamicImage.html) +A `DynamicImage` is an enumeration over all supported `ImageBuffer

` types. +Its exact image type is determined at runtime. It is the type returned when +opening an image. For convenience `DynamicImage` reimplements all image +processing functions. + +### The [`GenericImageView`](https://docs.rs/image/*/image/trait.GenericImageView.html) and [`GenericImage`](https://docs.rs/image/*/image/trait.GenericImage.html) Traits - +Traits that provide methods for inspecting (`GenericImageView`) and manipulating (`GenericImage`) images, parameterised over the image's pixel type. -| Format | Decoding | Encoding | -| -------- | ----------------------------------------- | --------------------------------------- | -| AVIF | Only 8-bit \*\* | Lossy | -| BMP | Yes | Rgb8, Rgba8, Gray8, GrayA8 | -| DDS | DXT1, DXT3, DXT5 | No | -| Farbfeld | Yes | Yes | -| GIF | Yes | Yes | -| HDR | Yes | Yes | -| ICO | Yes | Yes | -| JPEG | Baseline and progressive | Baseline JPEG | -| OpenEXR | Rgb32F, Rgba32F (no dwa compression) | Rgb32F, Rgba32F (no dwa compression) | -| PNG | All supported color types | Same as decoding | -| PNM | PBM, PGM, PPM, standard PAM | Yes | -| QOI | Yes | Yes | -| TGA | Yes | Rgb8, Rgba8, Bgr8, Bgra8, Gray8, GrayA8 | -| TIFF | Baseline(no fax support) + LZW + PackBits | Rgb8, Rgba8, Gray8 | -| WebP | Yes | Rgb8, Rgba8 \* | +### [`SubImage`](https://docs.rs/image/*/image/struct.SubImage.html) +A view into another image, delimited by the coordinates of a rectangle. +The coordinates given set the position of the top left corner of the rectangle. +This is used to perform image processing functions on a subregion of an image. -- \* Requires the `webp-encoder` feature, uses the libwebp C library. -- \*\* Requires the `avif-decoder` feature, uses the libdav1d C library. -### The [`ImageDecoder`](https://docs.rs/image/*/image/trait.ImageDecoder.html) and [`ImageDecoderRect`](https://docs.rs/image/*/image/trait.ImageDecoderRect.html) Traits +## The [`ImageDecoder`](https://docs.rs/image/*/image/trait.ImageDecoder.html) and [`ImageDecoderRect`](https://docs.rs/image/*/image/trait.ImageDecoderRect.html) Traits All image format decoders implement the `ImageDecoder` trait which provide basic methods for getting image metadata and decoding images. Some formats @@ -63,174 +107,96 @@ All pixels are parameterised by their component type. -## Images -Individual pixels within images are indexed with (0,0) at the top left corner. -### The [`GenericImageView`](https://docs.rs/image/*/image/trait.GenericImageView.html) and [`GenericImage`](https://docs.rs/image/*/image/trait.GenericImage.html) Traits - -Traits that provide methods for inspecting (`GenericImageView`) and manipulating (`GenericImage`) images, parameterised over the image's pixel type. - -Some of these methods for `GenericImageView` are... -+ **dimensions**: Return a tuple containing the width and height of the image. -+ **get_pixel**: Returns the pixel located at (x, y). -+ **pixels**: Returns an Iterator over the pixels of this image. - -While some of the methods for `GenericImage` are... -+ **put_pixel**: Put a pixel at location (x, y). -+ **copy_from**: Copies all of the pixels from another image into this image. - -### Representation of Images -`image` provides two main ways of representing image data: - -#### [`ImageBuffer`](https://docs.rs/image/*/image/struct.ImageBuffer.html) -An image parameterised by its Pixel types, represented by a width and height and a vector of pixels. It provides direct access to its pixels and implements the `GenericImageView` and `GenericImage` traits. - -```rust -use image::{GenericImage, GenericImageView, ImageBuffer, RgbImage}; - -// Construct a new RGB ImageBuffer with the specified width and height. -let img: RgbImage = ImageBuffer::new(512, 512); - -// Construct a new by repeated calls to the supplied closure. -let mut img = ImageBuffer::from_fn(512, 512, |x, y| { - if x % 2 == 0 { - image::Luma([0u8]) - } else { - image::Luma([255u8]) - } -}); - -// Obtain the image's width and height. -let (width, height) = img.dimensions(); - -// Access the pixel at coordinate (100, 100). -let pixel = img[(100, 100)]; - -// Or use the `get_pixel` method from the `GenericImage` trait. -let pixel = *img.get_pixel(100, 100); - -// Put a pixel at coordinate (100, 100). -img.put_pixel(100, 100, pixel); - -// Iterate over all pixels in the image. -for pixel in img.pixels() { - // Do something with pixel. -} -``` - -#### [`DynamicImage`](https://docs.rs/image/*/image/enum.DynamicImage.html) -A `DynamicImage` is an enumeration over all supported `ImageBuffer

` types. -Its exact image type is determined at runtime. It is the type returned when opening an image. -For convenience `DynamicImage` reimplements all image processing functions. - -`DynamicImage` implement the `GenericImageView` and `GenericImage` traits for RGBA pixels. - -#### [`SubImage`](https://docs.rs/image/*/image/struct.SubImage.html) -A view into another image, delimited by the coordinates of a rectangle. -The coordinates given set the position of the top left corner of the rectangle. -This is used to perform image processing functions on a subregion of an image. - -```rust -use image::{GenericImageView, ImageBuffer, RgbImage, imageops}; - -let mut img: RgbImage = ImageBuffer::new(512, 512); -let subimg = imageops::crop(&mut img, 0, 0, 100, 100); - -assert!(subimg.dimensions() == (100, 100)); -``` - ## Image Processing Functions -These are the functions defined in the `imageops` module. All functions operate on types that implement the `GenericImage` trait. + +These are the functions defined in the [`imageops`](https://docs.rs/image/latest/image/imageops/index.html) module. All functions operate on types that implement the [`GenericImage`](https://docs.rs/image/latest/image/trait.GenericImage.html) trait. Note that some of the functions are very slow in debug mode. Make sure to use release mode if you experience any performance issues. -+ **blur**: Performs a Gaussian blur on the supplied image. -+ **brighten**: Brighten the supplied image. -+ **huerotate**: Hue rotate the supplied image by degrees. -+ **contrast**: Adjust the contrast of the supplied image. -+ **crop**: Return a mutable view into an image. -+ **filter3x3**: Perform a 3x3 box filter on the supplied image. -+ **flip_horizontal**: Flip an image horizontally. -+ **flip_vertical**: Flip an image vertically. -+ **grayscale**: Convert the supplied image to grayscale. -+ **invert**: Invert each pixel within the supplied image This function operates in place. -+ **resize**: Resize the supplied image to the specified dimensions. -+ **rotate180**: Rotate an image 180 degrees clockwise. -+ **rotate270**: Rotate an image 270 degrees clockwise. -+ **rotate90**: Rotate an image 90 degrees clockwise. -+ **unsharpen**: Performs an unsharpen mask on the supplied image. ++ [**blur**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.blur): Performs a Gaussian blur on the supplied image. ++ [**brighten**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.brighten): Brighten the supplied image. ++ [**huerotate**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.huerotate): Hue rotate the supplied image by degrees. ++ [**contrast**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.adjust_contrast): Adjust the contrast of the supplied image. ++ [**crop**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.crop): Return a mutable view into an image. ++ [**filter3x3**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.filter3x3): Perform a 3x3 box filter on the supplied image. ++ [**flip_horizontal**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.fliph): Flip an image horizontally. ++ [**flip_vertical**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.flipv): Flip an image vertically. ++ [**grayscale**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.grayscale): Convert the supplied image to grayscale. ++ [**invert**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.invert): Invert each pixel within the supplied image This function operates in place. ++ [**resize**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.resize): Resize the supplied image to the specified dimensions. ++ [**rotate180**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.rotate180): Rotate an image 180 degrees clockwise. ++ [**rotate270**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.rotate270): Rotate an image 270 degrees clockwise. ++ [**rotate90**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.rotate90): Rotate an image 90 degrees clockwise. ++ [**unsharpen**](https://docs.rs/image/latest/image/enum.DynamicImage.html#method.unsharpen): Performs an unsharpen mask on the supplied image. For more options, see the [`imageproc`](https://crates.io/crates/imageproc) crate. ## Examples ### Opening and Saving Images -`image` provides the `open` function for opening images from a path. The image +`image` provides the [`open`](https://docs.rs/image/latest/image/fn.open.html) function for opening images from a path. The image format is determined from the path's file extension. An `io` module provides a reader which offer some more control. ```rust,no_run use image::GenericImageView; -fn main() { - // Use the open function to load an image from a Path. - // `open` returns a `DynamicImage` on success. - let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap(); +// Use the open function to load an image from a Path. +// `open` returns a `DynamicImage` on success. +let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap(); - // The dimensions method returns the images width and height. - println!("dimensions {:?}", img.dimensions()); +// The dimensions method returns the images width and height. +println!("dimensions {:?}", img.dimensions()); - // The color method returns the image's `ColorType`. - println!("{:?}", img.color()); +// The color method returns the image's `ColorType`. +println!("{:?}", img.color()); - // Write the contents of this image to the Writer in PNG format. - img.save("test.png").unwrap(); -} +// Write the contents of this image to the Writer in PNG format. +img.save("test.png").unwrap(); ``` ### Generating Fractals ```rust,no_run //! An example of generating julia fractals. -fn main() { - let imgx = 800; - let imgy = 800; - - let scalex = 3.0 / imgx as f32; - let scaley = 3.0 / imgy as f32; - - // Create a new ImgBuf with width: imgx and height: imgy - let mut imgbuf = image::ImageBuffer::new(imgx, imgy); - - // Iterate over the coordinates and pixels of the image - for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { - let r = (0.3 * x as f32) as u8; - let b = (0.3 * y as f32) as u8; - *pixel = image::Rgb([r, 0, b]); - } +let imgx = 800; +let imgy = 800; + +let scalex = 3.0 / imgx as f32; +let scaley = 3.0 / imgy as f32; + +// Create a new ImgBuf with width: imgx and height: imgy +let mut imgbuf = image::ImageBuffer::new(imgx, imgy); - // A redundant loop to demonstrate reading image data - for x in 0..imgx { - for y in 0..imgy { - let cx = y as f32 * scalex - 1.5; - let cy = x as f32 * scaley - 1.5; - - let c = num_complex::Complex::new(-0.4, 0.6); - let mut z = num_complex::Complex::new(cx, cy); - - let mut i = 0; - while i < 255 && z.norm() <= 2.0 { - z = z * z + c; - i += 1; - } - - let pixel = imgbuf.get_pixel_mut(x, y); - let image::Rgb(data) = *pixel; - *pixel = image::Rgb([data[0], i as u8, data[2]]); +// Iterate over the coordinates and pixels of the image +for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { + let r = (0.3 * x as f32) as u8; + let b = (0.3 * y as f32) as u8; + *pixel = image::Rgb([r, 0, b]); +} + +// A redundant loop to demonstrate reading image data +for x in 0..imgx { + for y in 0..imgy { + let cx = y as f32 * scalex - 1.5; + let cy = x as f32 * scaley - 1.5; + + let c = num_complex::Complex::new(-0.4, 0.6); + let mut z = num_complex::Complex::new(cx, cy); + + let mut i = 0; + while i < 255 && z.norm() <= 2.0 { + z = z * z + c; + i += 1; } - } - // Save the image as “fractal.png”, the format is deduced from the path - imgbuf.save("fractal.png").unwrap(); + let pixel = imgbuf.get_pixel_mut(x, y); + let image::Rgb(data) = *pixel; + *pixel = image::Rgb([data[0], i as u8, data[2]]); + } } + +// Save the image as “fractal.png”, the format is deduced from the path +imgbuf.save("fractal.png").unwrap(); ``` Example output: @@ -238,14 +204,11 @@ A Julia Fractal, c: -0.4 + 0.6i ### Writing raw buffers -If the high level interface is not needed because the image was obtained by other means, `image` provides the function `save_buffer` to save a buffer to a file. +If the high level interface is not needed because the image was obtained by other means, `image` provides the function [`save_buffer`](https://docs.rs/image/latest/image/fn.save_buffer.html) to save a buffer to a file. ```rust,no_run -fn main() { - - let buffer: &[u8] = unimplemented!(); // Generate the image data +let buffer: &[u8] = unimplemented!(); // Generate the image data - // Save the buffer as "image.png" - image::save_buffer("image.png", buffer, 800, 600, image::ColorType::Rgb8).unwrap() -} +// Save the buffer as "image.png" +image::save_buffer("image.png", buffer, 800, 600, image::ExtendedColorType::Rgb8).unwrap() ``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/benches/blur.rs clamav-1.4.6+dfsg/.cargo/vendor/image/benches/blur.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/benches/blur.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/benches/blur.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use image::imageops::{blur_advanced, fast_blur, GaussianBlurParameters}; +use image::{DynamicImage, ImageBuffer, Rgb, RgbImage}; + +pub fn bench_fast_blur(c: &mut Criterion) { + let src = ImageBuffer::from_pixel(1024, 768, Rgb([255u8, 0, 0])); + let dynamic = DynamicImage::ImageRgb8(RgbImage::from_pixel(1024, 768, Rgb([255u8, 0, 0]))); + + c.bench_function("fast blur: sigma 3.0", |b| { + b.iter(|| fast_blur(&src, 3.0)); + }); + + c.bench_function("fast blur: sigma 7.0", |b| { + b.iter(|| fast_blur(&src, 7.0)); + }); + + c.bench_function("fast blur: sigma 50.0", |b| { + b.iter(|| fast_blur(&src, 50.0)); + }); + + c.bench_function("gaussian blur: sigma 3.0", |b| { + b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(3.0))); + }); + + c.bench_function("gaussian blur: sigma 7.0", |b| { + b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(7.0))); + }); + + c.bench_function("gaussian blur: sigma 50.0", |b| { + b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(50.0))); + }); + + c.bench_function("gaussian blur (dynamic image): sigma 3.0", |b| { + b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(3.0))); + }); + + c.bench_function("gaussian blur (dynamic image): sigma 7.0", |b| { + b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(7.0))); + }); + + c.bench_function("gaussian blur (dynamic image): sigma 50.0", |b| { + b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(50.0))); + }); +} + +criterion_group!(benches, bench_fast_blur); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/benches/copy_from.rs clamav-1.4.6+dfsg/.cargo/vendor/image/benches/copy_from.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/benches/copy_from.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/benches/copy_from.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,7 +6,7 @@ let mut dst = ImageBuffer::from_pixel(2048, 2048, Rgba([0u8, 0, 0, 255])); c.bench_function("copy_from", |b| { - b.iter(|| dst.copy_from(black_box(&src), 0, 0)) + b.iter(|| dst.copy_from(black_box(&src), 0, 0)); }); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/benches/decode.rs clamav-1.4.6+dfsg/.cargo/vendor/image/benches/decode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/benches/decode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/benches/decode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -67,6 +67,8 @@ "hpredict_packbits.tiff", "mandrill.tiff", "rgb-3c-16b.tiff", + "rgb32f_bw.tiff", + "rgb32f_color.tiff", ], format: ImageFormat::Tiff, }, @@ -96,7 +98,7 @@ group.bench_function(file_name.to_owned(), |b| { b.iter(|| { image::load_from_memory_with_format(&buf, def.format).unwrap(); - }) + }); }); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/benches/encode.rs clamav-1.4.6+dfsg/.cargo/vendor/image/benches/encode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/benches/encode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/benches/encode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,15 +1,16 @@ extern crate criterion; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use image::ExtendedColorType; use image::{codecs::bmp::BmpEncoder, codecs::jpeg::JpegEncoder, ColorType}; use std::fs::File; use std::io::{BufWriter, Seek, SeekFrom, Write}; trait Encoder { - fn encode_raw(&self, into: &mut Vec, im: &[u8], dims: u32, color: ColorType); - fn encode_bufvec(&self, into: &mut Vec, im: &[u8], dims: u32, color: ColorType); - fn encode_file(&self, file: &File, im: &[u8], dims: u32, color: ColorType); + fn encode_raw(&self, into: &mut Vec, im: &[u8], dims: u32, color: ExtendedColorType); + fn encode_bufvec(&self, into: &mut Vec, im: &[u8], dims: u32, color: ExtendedColorType); + fn encode_file(&self, file: &File, im: &[u8], dims: u32, color: ExtendedColorType); } #[derive(Clone, Copy)] @@ -37,7 +38,7 @@ ]; for definition in BENCH_DEFS { - encode_definition(c, definition) + encode_definition(c, definition); } } @@ -50,12 +51,11 @@ /// /// For compressed formats this is surely not representative of encoding a normal image but it's a /// start for benchmarking. -fn encode_zeroed(group: &mut BenchGroup, with: &dyn Encoder, size: u32, color: ColorType) { - let bytes = size as usize * usize::from(color.bytes_per_pixel()); - let im = vec![0; bytes * bytes]; +fn encode_zeroed(group: &mut BenchGroup, with: &dyn Encoder, size: u32, color: ExtendedColorType) { + let im = vec![0; (color.bits_per_pixel() as usize * size as usize).div_ceil(8) * size as usize]; group.bench_with_input( - BenchmarkId::new(format!("zero-{:?}-rawvec", color), size), + BenchmarkId::new(format!("zero-{color:?}-rawvec"), size), &im, |b, image| { let mut v = vec![]; @@ -64,7 +64,7 @@ }, ); group.bench_with_input( - BenchmarkId::new(format!("zero-{:?}-bufvec", color), size), + BenchmarkId::new(format!("zero-{color:?}-bufvec"), size), &im, |b, image| { let mut v = vec![]; @@ -73,7 +73,7 @@ }, ); group.bench_with_input( - BenchmarkId::new(format!("zero-{:?}-file", color), size), + BenchmarkId::new(format!("zero-{color:?}-file"), size), &im, |b, image| { let file = File::create("temp.bmp").unwrap(); @@ -87,7 +87,7 @@ for &color in def.colors { for &size in def.sizes { - encode_zeroed(&mut group, def.with, size, color); + encode_zeroed(&mut group, def.with, size, color.into()); } } } @@ -97,22 +97,22 @@ struct Jpeg; trait EncoderBase { - fn encode(&self, into: impl Write, im: &[u8], dims: u32, color: ColorType); + fn encode(&self, into: impl Write, im: &[u8], dims: u32, color: ExtendedColorType); } impl Encoder for T { - fn encode_raw(&self, into: &mut Vec, im: &[u8], dims: u32, color: ColorType) { + fn encode_raw(&self, into: &mut Vec, im: &[u8], dims: u32, color: ExtendedColorType) { into.clear(); self.encode(into, im, dims, color); } - fn encode_bufvec(&self, into: &mut Vec, im: &[u8], dims: u32, color: ColorType) { + fn encode_bufvec(&self, into: &mut Vec, im: &[u8], dims: u32, color: ExtendedColorType) { into.clear(); let buf = BufWriter::new(into); self.encode(buf, im, dims, color); } - fn encode_file(&self, mut file: &File, im: &[u8], dims: u32, color: ColorType) { + fn encode_file(&self, mut file: &File, im: &[u8], dims: u32, color: ExtendedColorType) { file.seek(SeekFrom::Start(0)).unwrap(); let buf = BufWriter::new(file); self.encode(buf, im, dims, color); @@ -120,14 +120,14 @@ } impl EncoderBase for Bmp { - fn encode(&self, mut into: impl Write, im: &[u8], size: u32, color: ColorType) { + fn encode(&self, mut into: impl Write, im: &[u8], size: u32, color: ExtendedColorType) { let mut x = BmpEncoder::new(&mut into); x.encode(im, size, size, color).unwrap(); } } impl EncoderBase for Jpeg { - fn encode(&self, mut into: impl Write, im: &[u8], size: u32, color: ColorType) { + fn encode(&self, mut into: impl Write, im: &[u8], size: u32, color: ExtendedColorType) { let mut x = JpegEncoder::new(&mut into); x.encode(im, size, size, color).unwrap(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/benches/fast_blur.rs clamav-1.4.6+dfsg/.cargo/vendor/image/benches/fast_blur.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/benches/fast_blur.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/benches/fast_blur.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use image::{imageops::fast_blur, ImageBuffer, Rgb}; + +pub fn bench_fast_blur(c: &mut Criterion) { + let src = ImageBuffer::from_pixel(1024, 768, Rgb([255u8, 0, 0])); + + c.bench_function("fast_blur", |b| { + b.iter(|| fast_blur(&src, 50.0)); + }); +} + +criterion_group!(benches, bench_fast_blur); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/deny.toml clamav-1.4.6+dfsg/.cargo/vendor/image/deny.toml --- clamav-1.4.3+dfsg/.cargo/vendor/image/deny.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/deny.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -# https://embarkstudios.github.io/cargo-deny/ - -targets = [ - { triple = "aarch64-apple-darwin" }, - { triple = "aarch64-linux-android" }, - { triple = "x86_64-apple-darwin" }, - { triple = "x86_64-pc-windows-msvc" }, - { triple = "x86_64-unknown-linux-gnu" }, - { triple = "x86_64-unknown-linux-musl" }, -] - - -[advisories] -vulnerability = "deny" -unmaintained = "warn" -yanked = "deny" -ignore = [] - - -[bans] -multiple-versions = "deny" -wildcards = "allow" # at least until https://github.com/EmbarkStudios/cargo-deny/issues/241 is fixed -deny = [] -skip = [ - { name = "num-derive" } # ravif transatively depends on 0.3 and 0.4. -] -skip-tree = [ - { name = "criterion" }, # dev-dependency - { name = "quickcheck" }, # dev-dependency - { name = "dav1d" }, # TODO: needs upgrade - { name = "clap" }, -] - - -[licenses] -unlicensed = "allow" -allow-osi-fsf-free = "either" -copyleft = "allow" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/docs/2019-04-23-memory-unsafety.md clamav-1.4.6+dfsg/.cargo/vendor/image/docs/2019-04-23-memory-unsafety.md --- clamav-1.4.3+dfsg/.cargo/vendor/image/docs/2019-04-23-memory-unsafety.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/docs/2019-04-23-memory-unsafety.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -# Advisory about potential memory unsafety issues - -[While reviewing][i885] some `unsafe Vec::from_raw_parts` operations within the -library, trying to justify their existence with stronger reasoning, we noticed -that they instead did not meet the required conditions set by the standard -library. This unsoundness was quickly removed, but we noted that the same -unjustified reasoning had been applied by a dependency introduced in `0.21`. - -For efficiency reasons, we had tried to reuse the allocations made by decoders -for the buffer of the final image. However, that process is error prone. Most -image decoding algorithms change the representation type of color samples to -some degree. Notably, the output pixel type may have a different size and -alignment than the type used in the temporary decoding buffer. In this specific -instance, the `ImageBuffer` of the output expects a linear arrangement of `u8` -samples while the implementation of the `hdr` decoder uses a pixel -representation of `Rgb`, which has three times the size. One of the -requirements of `Vec::from_raw_parts` reads: - -> ptr's T needs to have the same size and alignment as it was allocated with. - -This requirement is not present on slices `[T]`, as it is motivated by the -allocator interface. The validity invariant of a reference and slice only -requires the correct alignment here, which was considered in the design of -`Rgb<_>` by giving it a well-defined representation, `#[repr(C)]`. But -critically, this does not guarantee that we can reuse the existing allocation -through effectively transmuting a `Vec<_>`! - -The actual impact of this issue is, in real world implementations, limited to -allocators which handle allocations for types of size `1` and `3`/`4` -differently. To the best of my knowledge, this does not apply to `jemalloc` and -the `libc` allocator. However, we decided to proceed with caution here. - -## Lessons for the future - -New library dependencies will be under a stricter policy. Not only would they -need to be justified by functionality but also require at least some level of -reasoning how they solve that problem better than alternatives. Some appearance -of maintenance, or the existence of `#[deny(unsafe)]`, will help. We'll -additionally look into existing dependencies trying to identify similar issues -and minimizing the potential surface for implementation risks. - -## Sound and safe buffer reuse - -It seems that the `Vec` representation is entirely unfit for buffer reuse in -the style which an image library requires. In particular, using pixel types of -different sizes is likely common to handle either whole (encoded) pixels or -individual samples. Thus, we started a new sub-project to address this use -case, [image-canvas][image-canvas]. Contributions and review of its safety are -very welcome, we ask for the communities help here. The release of `v0.1` will -not occur until at least one such review has occurred. - - -[i885]: https://github.com/image-rs/image/pull/885 -[image-canvas]: https://github.com/image-rs/canvas Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/concat/200x300.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/200x300.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/concat/300x300.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/300x300.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/concat/400x300.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/400x300.png differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/concat/main.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/concat/main.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/concat/main.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -use image::{GenericImage, GenericImageView, ImageBuffer, Pixel, Primitive}; - -/// Example showcasing a generic implementation of image concatenation. -/// -/// The example images are coming from https://placeholder.com/ -/// -/// Run from the root of the repository with: -/// cargo run --release --example concat -fn main() { - h_concat(&[ - image::open("examples/concat/200x300.png").unwrap(), - image::open("examples/concat/300x300.png").unwrap(), - image::open("examples/concat/400x300.png").unwrap(), - ]) - .save("examples/concat/concatenated_900x300.png") - .unwrap(); -} - -/// Concatenate horizontally images with the same pixel type. -fn h_concat(images: &[I]) -> ImageBuffer> -where - I: GenericImageView, - P: Pixel + 'static, - S: Primitive + 'static, -{ - // The final width is the sum of all images width. - let img_width_out: u32 = images.iter().map(|im| im.width()).sum(); - - // The final height is the maximum height from the input images. - let img_height_out: u32 = images.iter().map(|im| im.height()).max().unwrap_or(0); - - // Initialize an image buffer with the appropriate size. - let mut imgbuf = image::ImageBuffer::new(img_width_out, img_height_out); - let mut accumulated_width = 0; - - // Copy each input image at the correct location in the output image. - for img in images { - imgbuf.copy_from(img, accumulated_width, 0).unwrap(); - accumulated_width += img.width(); - } - - imgbuf -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/convert.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/convert.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/convert.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -//! An example of opening an image. -extern crate image; - -use std::env; -use std::path::Path; - -fn main() { - let (from, into) = if env::args_os().count() == 3 { - ( - env::args_os().nth(1).unwrap(), - env::args_os().nth(2).unwrap(), - ) - } else { - println!("Please enter a from and into path."); - std::process::exit(1); - }; - - // Use the open function to load an image from a Path. - // ```open``` returns a dynamic image. - let im = image::open(Path::new(&from)).unwrap(); - // Write the contents of this image using extension guessing. - im.save(Path::new(&into)).unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/decode.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/decode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/decode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/decode.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -//! An example of opening an image. -use std::env; -use std::path::Path; - -fn main() { - let from = if env::args_os().count() == 2 { - env::args_os().nth(1).unwrap() - } else { - println!("Please enter a from and into path."); - std::process::exit(1); - }; - - // Use the open function to load an image from a Path. - // ```open``` returns a dynamic image. - let im = image::open(Path::new(&from)).unwrap(); - println!("{}", im.as_bytes().len()); -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/fractal.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/fractal.png.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.png.png differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/fractal.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/fractal.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/fractal.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -//! An example of generating julia fractals. -extern crate image; -extern crate num_complex; - -fn main() { - let imgx = 800; - let imgy = 800; - - let scalex = 3.0 / imgx as f32; - let scaley = 3.0 / imgy as f32; - - // Create a new ImgBuf with width: imgx and height: imgy - let mut imgbuf = image::ImageBuffer::new(imgx, imgy); - - // Iterate over the coordinates and pixels of the image - for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { - let r = (0.3 * x as f32) as u8; - let b = (0.3 * y as f32) as u8; - *pixel = image::Rgb([r, 0, b]); - } - - // A redundant loop to demonstrate reading image data - for x in 0..imgx { - for y in 0..imgy { - let cx = y as f32 * scalex - 1.5; - let cy = x as f32 * scaley - 1.5; - - let c = num_complex::Complex::new(-0.4, 0.6); - let mut z = num_complex::Complex::new(cx, cy); - - let mut i = 0; - while i < 255 && z.norm() <= 2.0 { - z = z * z + c; - i += 1; - } - - let pixel = imgbuf.get_pixel_mut(x, y); - let data = (*pixel as image::Rgb).0; - *pixel = image::Rgb([data[0], i as u8, data[2]]); - } - } - - // Save the image as “fractal.png”, the format is deduced from the path - imgbuf.save("fractal.png").unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/gradient/main.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/gradient/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/gradient/main.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/gradient/main.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -use image::{Pixel, Rgba, RgbaImage}; - -fn main() { - let mut img = RgbaImage::new(100, 100); - - let start = Rgba::from_slice(&[0, 128, 0, 0]); - let end = Rgba::from_slice(&[255, 255, 255, 255]); - - image::imageops::vertical_gradient(&mut img, start, end); - img.save("vertical_gradient.png").unwrap(); - image::imageops::vertical_gradient(&mut img, end, start); - img.save("vertical_gradient_reverse.png").unwrap(); - - image::imageops::horizontal_gradient(&mut img, start, end); - img.save("horizontal_gradient.png").unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/opening.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/opening.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/opening.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/opening.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -//! An example of opening an image. -extern crate image; - -use std::env; -use std::fs::File; -use std::path::Path; - -use image::{GenericImageView, ImageFormat}; - -fn main() { - let file = if env::args().count() == 2 { - env::args().nth(1).unwrap() - } else { - panic!("Please enter a file") - }; - - // Use the open function to load an image from a Path. - // ```open``` returns a dynamic image. - let im = image::open(Path::new(&file)).unwrap(); - - // The dimensions method returns the images width and height - println!("dimensions {:?}", im.dimensions()); - - // The color method returns the image's ColorType - println!("{:?}", im.color()); - - let fout = &mut File::create(Path::new(&format!("{}.png", file))).unwrap(); - - // Write the contents of this image to the Writer in PNG format. - im.write_to(fout, ImageFormat::Png).unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/main.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/main.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/main.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -use image::imageops::FilterType; -use image::ImageFormat; -use std::fmt; -use std::fs::File; -use std::time::{Duration, Instant}; - -struct Elapsed(Duration); - -impl Elapsed { - fn from(start: &Instant) -> Self { - Elapsed(start.elapsed()) - } -} - -impl fmt::Display for Elapsed { - fn fmt(&self, out: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match (self.0.as_secs(), self.0.subsec_nanos()) { - (0, n) if n < 1000 => write!(out, "{} ns", n), - (0, n) if n < 1_000_000 => write!(out, "{} µs", n / 1000), - (0, n) => write!(out, "{} ms", n / 1_000_000), - (s, n) if s < 10 => write!(out, "{}.{:02} s", s, n / 10_000_000), - (s, _) => write!(out, "{} s", s), - } - } -} - -fn main() { - let img = image::open("examples/scaledown/test.jpg").unwrap(); - for &(name, filter) in [ - ("near", FilterType::Nearest), - ("tri", FilterType::Triangle), - ("cmr", FilterType::CatmullRom), - ("gauss", FilterType::Gaussian), - ("lcz2", FilterType::Lanczos3), - ] - .iter() - { - let timer = Instant::now(); - let scaled = img.resize(400, 400, filter); - println!("Scaled by {} in {}", name, Elapsed::from(&timer)); - let mut output = File::create(&format!("test-{}.png", name)).unwrap(); - scaled.write_to(&mut output, ImageFormat::Png).unwrap(); - } - - for size in &[20_u32, 40, 100, 200, 400] { - let timer = Instant::now(); - let scaled = img.thumbnail(*size, *size); - println!("Thumbnailed to {} in {}", size, Elapsed::from(&timer)); - let mut output = File::create(format!("test-thumb{}.png", size)).unwrap(); - scaled.write_to(&mut output, ImageFormat::Png).unwrap(); - } -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-cmr.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-cmr.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-gauss.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-gauss.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-lcz2.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-lcz2.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-near.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-near.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-tri.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/scaledown-test-tri.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaledown/test.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaledown/test.jpg differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaleup/main.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaleup/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaleup/main.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaleup/main.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -use image::imageops::FilterType; -use image::ImageFormat; -use std::fmt; -use std::fs::File; -use std::time::{Duration, Instant}; - -struct Elapsed(Duration); - -impl Elapsed { - fn from(start: &Instant) -> Self { - Elapsed(start.elapsed()) - } -} - -impl fmt::Display for Elapsed { - fn fmt(&self, out: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match (self.0.as_secs(), self.0.subsec_nanos()) { - (0, n) if n < 1000 => write!(out, "{} ns", n), - (0, n) if n < 1_000_000 => write!(out, "{} µs", n / 1000), - (0, n) => write!(out, "{} ms", n / 1_000_000), - (s, n) if s < 10 => write!(out, "{}.{:02} s", s, n / 10_000_000), - (s, _) => write!(out, "{} s", s), - } - } -} - -fn main() { - let tiny = image::open("examples/scaleup/tinycross.png").unwrap(); - for &(name, filter) in [ - ("near", FilterType::Nearest), - ("tri", FilterType::Triangle), - ("xcmr", FilterType::CatmullRom), - ("ygauss", FilterType::Gaussian), - ("zlcz2", FilterType::Lanczos3), - ] - .iter() - { - let timer = Instant::now(); - let scaled = tiny.resize(32, 32, filter); - println!("Scaled by {} in {}", name, Elapsed::from(&timer)); - let mut output = File::create(&format!("up2-{}.png", name)).unwrap(); - scaled.write_to(&mut output, ImageFormat::Png).unwrap(); - - let timer = Instant::now(); - let scaled = tiny.resize(48, 48, filter); - println!("Scaled by {} in {}", name, Elapsed::from(&timer)); - let mut output = File::create(&format!("up3-{}.png", name)).unwrap(); - scaled.write_to(&mut output, ImageFormat::Png).unwrap(); - } -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/examples/scaleup/tinycross.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/examples/scaleup/tinycross.png differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/examples/tile/main.rs clamav-1.4.6+dfsg/.cargo/vendor/image/examples/tile/main.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/examples/tile/main.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/examples/tile/main.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -use image::RgbaImage; - -fn main() { - let mut img = RgbaImage::new(1920, 1080); - let tile = image::open("examples/scaleup/tinycross.png").unwrap(); - - image::imageops::tile(&mut img, &tile); - img.save("tiled_wallpaper.png").unwrap(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/release.sh clamav-1.4.6+dfsg/.cargo/vendor/image/release.sh --- clamav-1.4.3+dfsg/.cargo/vendor/image/release.sh 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/release.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/bin/bash -# Checks automatic preconditions for a release -determine_new_version() { - grep "version = " Cargo.toml | sed -Ee 's/version = "(.*)"/\1/' | head -1 -} - -check_notexists_version() { - # Does the api information start with: '{"errors":' - [[ $(wget "https://crates.io/api/v1/crates/image/$1" -qO -) == "{\"errors\":"* ]] -} - -check_release_description() { - major=${1%%.*} - minor_patch=${1#$major.} - minor=${minor_patch%%.*} - patch=${minor_patch#$minor.} - # We just need to find a fitting header line - grep -Eq "^### Version ${major}.${minor}$" CHANGES.md -} - -version="$(determine_new_version)" -check_release_description $version || { echo "Version does not have a release description"; exit 1; } -check_notexists_version $version || { echo "Version $version appears already published"; exit 1; } - diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/animation.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/animation.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/animation.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/animation.rs 2006-07-24 01:21:28.000000000 +0000 @@ -11,6 +11,7 @@ impl<'a> Frames<'a> { /// Creates a new `Frames` from an implementation specific iterator. + #[must_use] pub fn new(iterator: Box> + 'a>) -> Self { Frames { iterator } } @@ -25,15 +26,15 @@ } } -impl<'a> Iterator for Frames<'a> { +impl Iterator for Frames<'_> { type Item = ImageResult; + fn next(&mut self) -> Option> { self.iterator.next() } } /// A single animation frame -#[derive(Clone)] pub struct Frame { /// Delay between the frames in milliseconds delay: Delay, @@ -44,7 +45,38 @@ buffer: RgbaImage, } +impl Clone for Frame { + fn clone(&self) -> Self { + Self { + delay: self.delay, + left: self.left, + top: self.top, + buffer: self.buffer.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.delay = source.delay; + self.left = source.left; + self.top = source.top; + self.buffer.clone_from(&source.buffer); + } +} + /// The delay of a frame relative to the previous one. +/// +/// The ratio is reduced on construction which means equality comparisons is reliable even when +/// mixing different bases. Note however that there is an upper limit to the delays that can be +/// represented exactly when using [`Self::from_saturating_duration`] which depends on the +/// granularity of the interval. +/// +/// ``` +/// use image::Delay; +/// let delay_10ms = Delay::from_numer_denom_ms(10, 1); +/// let delay_10000us = Delay::from_numer_denom_ms(10_000, 1_000); +/// +/// assert_eq!(delay_10ms, delay_10000us); +/// ``` #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)] pub struct Delay { ratio: Ratio, @@ -52,6 +84,7 @@ impl Frame { /// Constructs a new frame without any delay. + #[must_use] pub fn new(buffer: RgbaImage) -> Frame { Frame { delay: Delay::from_ratio(Ratio { numer: 0, denom: 1 }), @@ -62,6 +95,7 @@ } /// Constructs a new frame + #[must_use] pub fn from_parts(buffer: RgbaImage, left: u32, top: u32, delay: Delay) -> Frame { Frame { delay, @@ -72,11 +106,13 @@ } /// Delay of this frame + #[must_use] pub fn delay(&self) -> Delay { self.delay } /// Returns the image buffer + #[must_use] pub fn buffer(&self) -> &RgbaImage { &self.buffer } @@ -87,16 +123,19 @@ } /// Returns the image buffer + #[must_use] pub fn into_buffer(self) -> RgbaImage { self.buffer } /// Returns the x offset + #[must_use] pub fn left(&self) -> u32 { self.left } /// Returns the y offset + #[must_use] pub fn top(&self) -> u32 { self.top } @@ -111,6 +150,7 @@ /// use image::Delay; /// let delay_10ms = Delay::from_numer_denom_ms(10, 1); /// ``` + #[must_use] pub fn from_numer_denom_ms(numerator: u32, denominator: u32) -> Self { Delay { ratio: Ratio::new(numerator, denominator), @@ -131,6 +171,7 @@ /// let duration = Duration::from_millis(20); /// let delay = Delay::from_saturating_duration(duration); /// ``` + #[must_use] pub fn from_saturating_duration(duration: Duration) -> Self { // A few notes: The largest number we can represent as a ratio is u32::MAX but we can // sometimes represent much smaller numbers. @@ -140,7 +181,7 @@ // > `0 < b <= (u32::MAX + 1)/(millis + 1)` // Corollary: millis <= u32::MAX - const MILLIS_BOUND: u128 = u32::max_value() as u128; + const MILLIS_BOUND: u128 = u32::MAX as u128; let millis = duration.as_millis().min(MILLIS_BOUND); let submillis = (duration.as_nanos() % 1_000_000) as u32; @@ -160,6 +201,7 @@ /// /// This is guaranteed to be an exact conversion if the `Delay` was previously created with the /// `from_numer_denom_ms` constructor. + #[must_use] pub fn numer_denom_ms(self) -> (u32, u32) { (self.ratio.numer, self.ratio.denom) } @@ -275,6 +317,14 @@ } } +#[inline] +const fn gcd(mut a: u32, mut b: u32) -> u32 { + while b != 0 { + (a, b) = (b, a.rem_euclid(b)); + } + a +} + #[derive(Copy, Clone, Debug)] pub(crate) struct Ratio { numer: u32, @@ -285,14 +335,15 @@ #[inline] pub(crate) fn new(numerator: u32, denominator: u32) -> Self { assert_ne!(denominator, 0); + let divisor = gcd(numerator, denominator); Self { - numer: numerator, - denom: denominator, + numer: numerator / divisor, + denom: denominator / divisor, } } #[inline] - pub(crate) fn to_integer(&self) -> u32 { + pub(crate) fn to_integer(self) -> u32 { self.numer / self.denom } } @@ -328,7 +379,7 @@ // We cast the types from `u32` to `u64` in order // to not overflow the multiplications. - (a as u64 * d as u64).cmp(&(c as u64 * b as u64)) + (u64::from(a) * u64::from(d)).cmp(&(u64::from(c) * u64::from(b))) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1805 +0,0 @@ -//! Contains the generic `ImageBuffer` struct. -use num_traits::Zero; -use std::fmt; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut, Index, IndexMut, Range}; -use std::path::Path; -use std::slice::{ChunksExact, ChunksExactMut}; - -use crate::color::{FromColor, Luma, LumaA, Rgb, Rgba}; -use crate::dynimage::{save_buffer, save_buffer_with_format, write_buffer_with_format}; -use crate::error::ImageResult; -use crate::flat::{FlatSamples, SampleLayout}; -use crate::image::{GenericImage, GenericImageView, ImageEncoder, ImageFormat, ImageOutputFormat}; -use crate::math::Rect; -use crate::traits::{EncodableLayout, Pixel, PixelWithColorType}; -use crate::utils::expand_packed; -use crate::DynamicImage; - -/// Iterate over pixel refs. -pub struct Pixels<'a, P: Pixel + 'a> -where - P::Subpixel: 'a, -{ - chunks: ChunksExact<'a, P::Subpixel>, -} - -impl<'a, P: Pixel + 'a> Iterator for Pixels<'a, P> -where - P::Subpixel: 'a, -{ - type Item = &'a P; - - #[inline(always)] - fn next(&mut self) -> Option<&'a P> { - self.chunks.next().map(|v|

::from_slice(v)) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for Pixels<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.chunks.len() - } -} - -impl<'a, P: Pixel + 'a> DoubleEndedIterator for Pixels<'a, P> -where - P::Subpixel: 'a, -{ - #[inline(always)] - fn next_back(&mut self) -> Option<&'a P> { - self.chunks.next_back().map(|v|

::from_slice(v)) - } -} - -impl Clone for Pixels<'_, P> { - fn clone(&self) -> Self { - Pixels { - chunks: self.chunks.clone(), - } - } -} - -impl fmt::Debug for Pixels<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Pixels") - .field("chunks", &self.chunks) - .finish() - } -} - -/// Iterate over mutable pixel refs. -pub struct PixelsMut<'a, P: Pixel + 'a> -where - P::Subpixel: 'a, -{ - chunks: ChunksExactMut<'a, P::Subpixel>, -} - -impl<'a, P: Pixel + 'a> Iterator for PixelsMut<'a, P> -where - P::Subpixel: 'a, -{ - type Item = &'a mut P; - - #[inline(always)] - fn next(&mut self) -> Option<&'a mut P> { - self.chunks.next().map(|v|

::from_slice_mut(v)) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for PixelsMut<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.chunks.len() - } -} - -impl<'a, P: Pixel + 'a> DoubleEndedIterator for PixelsMut<'a, P> -where - P::Subpixel: 'a, -{ - #[inline(always)] - fn next_back(&mut self) -> Option<&'a mut P> { - self.chunks - .next_back() - .map(|v|

::from_slice_mut(v)) - } -} - -impl fmt::Debug for PixelsMut<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("PixelsMut") - .field("chunks", &self.chunks) - .finish() - } -} - -/// Iterate over rows of an image -/// -/// This iterator is created with [`ImageBuffer::rows`]. See its document for details. -/// -/// [`ImageBuffer::rows`]: ../struct.ImageBuffer.html#method.rows -pub struct Rows<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - pixels: ChunksExact<'a, P::Subpixel>, -} - -impl<'a, P: Pixel + 'a> Rows<'a, P> { - /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic - /// condition. The `pixels` slice must be large enough so that all pixels are addressable. - fn with_image(pixels: &'a [P::Subpixel], width: u32, height: u32) -> Self { - let row_len = (width as usize) * usize::from(

::CHANNEL_COUNT); - if row_len == 0 { - Rows { - pixels: [].chunks_exact(1), - } - } else { - let pixels = pixels - .get(..row_len * height as usize) - .expect("Pixel buffer has too few subpixels"); - // Rows are physically present. In particular, height is smaller than `usize::MAX` as - // all subpixels can be indexed. - Rows { - pixels: pixels.chunks_exact(row_len), - } - } - } -} - -impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P> -where - P::Subpixel: 'a, -{ - type Item = Pixels<'a, P>; - - #[inline(always)] - fn next(&mut self) -> Option> { - let row = self.pixels.next()?; - Some(Pixels { - // Note: this is not reached when CHANNEL_COUNT is 0. - chunks: row.chunks_exact(

::CHANNEL_COUNT as usize), - }) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.pixels.len() - } -} - -impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P> -where - P::Subpixel: 'a, -{ - #[inline(always)] - fn next_back(&mut self) -> Option> { - let row = self.pixels.next_back()?; - Some(Pixels { - // Note: this is not reached when CHANNEL_COUNT is 0. - chunks: row.chunks_exact(

::CHANNEL_COUNT as usize), - }) - } -} - -impl Clone for Rows<'_, P> { - fn clone(&self) -> Self { - Rows { - pixels: self.pixels.clone(), - } - } -} - -impl fmt::Debug for Rows<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Rows") - .field("pixels", &self.pixels) - .finish() - } -} - -/// Iterate over mutable rows of an image -/// -/// This iterator is created with [`ImageBuffer::rows_mut`]. See its document for details. -/// -/// [`ImageBuffer::rows_mut`]: ../struct.ImageBuffer.html#method.rows_mut -pub struct RowsMut<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - pixels: ChunksExactMut<'a, P::Subpixel>, -} - -impl<'a, P: Pixel + 'a> RowsMut<'a, P> { - /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic - /// condition. The `pixels` slice must be large enough so that all pixels are addressable. - fn with_image(pixels: &'a mut [P::Subpixel], width: u32, height: u32) -> Self { - let row_len = (width as usize) * usize::from(

::CHANNEL_COUNT); - if row_len == 0 { - RowsMut { - pixels: [].chunks_exact_mut(1), - } - } else { - let pixels = pixels - .get_mut(..row_len * height as usize) - .expect("Pixel buffer has too few subpixels"); - // Rows are physically present. In particular, height is smaller than `usize::MAX` as - // all subpixels can be indexed. - RowsMut { - pixels: pixels.chunks_exact_mut(row_len), - } - } - } -} - -impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P> -where - P::Subpixel: 'a, -{ - type Item = PixelsMut<'a, P>; - - #[inline(always)] - fn next(&mut self) -> Option> { - let row = self.pixels.next()?; - Some(PixelsMut { - // Note: this is not reached when CHANNEL_COUNT is 0. - chunks: row.chunks_exact_mut(

::CHANNEL_COUNT as usize), - }) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.pixels.len() - } -} - -impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P> -where - P::Subpixel: 'a, -{ - #[inline(always)] - fn next_back(&mut self) -> Option> { - let row = self.pixels.next_back()?; - Some(PixelsMut { - // Note: this is not reached when CHANNEL_COUNT is 0. - chunks: row.chunks_exact_mut(

::CHANNEL_COUNT as usize), - }) - } -} - -impl fmt::Debug for RowsMut<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("RowsMut") - .field("pixels", &self.pixels) - .finish() - } -} - -/// Enumerate the pixels of an image. -pub struct EnumeratePixels<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - pixels: Pixels<'a, P>, - x: u32, - y: u32, - width: u32, -} - -impl<'a, P: Pixel + 'a> Iterator for EnumeratePixels<'a, P> -where - P::Subpixel: 'a, -{ - type Item = (u32, u32, &'a P); - - #[inline(always)] - fn next(&mut self) -> Option<(u32, u32, &'a P)> { - if self.x >= self.width { - self.x = 0; - self.y += 1; - } - let (x, y) = (self.x, self.y); - self.x += 1; - self.pixels.next().map(|p| (x, y, p)) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixels<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.pixels.len() - } -} - -impl Clone for EnumeratePixels<'_, P> { - fn clone(&self) -> Self { - EnumeratePixels { - pixels: self.pixels.clone(), - ..*self - } - } -} - -impl fmt::Debug for EnumeratePixels<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumeratePixels") - .field("pixels", &self.pixels) - .field("x", &self.x) - .field("y", &self.y) - .field("width", &self.width) - .finish() - } -} - -/// Enumerate the rows of an image. -pub struct EnumerateRows<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - rows: Rows<'a, P>, - y: u32, - width: u32, -} - -impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P> -where - P::Subpixel: 'a, -{ - type Item = (u32, EnumeratePixels<'a, P>); - - #[inline(always)] - fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> { - let y = self.y; - self.y += 1; - self.rows.next().map(|r| { - ( - y, - EnumeratePixels { - x: 0, - y, - width: self.width, - pixels: r, - }, - ) - }) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.rows.len() - } -} - -impl Clone for EnumerateRows<'_, P> { - fn clone(&self) -> Self { - EnumerateRows { - rows: self.rows.clone(), - ..*self - } - } -} - -impl fmt::Debug for EnumerateRows<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumerateRows") - .field("rows", &self.rows) - .field("y", &self.y) - .field("width", &self.width) - .finish() - } -} - -/// Enumerate the pixels of an image. -pub struct EnumeratePixelsMut<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - pixels: PixelsMut<'a, P>, - x: u32, - y: u32, - width: u32, -} - -impl<'a, P: Pixel + 'a> Iterator for EnumeratePixelsMut<'a, P> -where - P::Subpixel: 'a, -{ - type Item = (u32, u32, &'a mut P); - - #[inline(always)] - fn next(&mut self) -> Option<(u32, u32, &'a mut P)> { - if self.x >= self.width { - self.x = 0; - self.y += 1; - } - let (x, y) = (self.x, self.y); - self.x += 1; - self.pixels.next().map(|p| (x, y, p)) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixelsMut<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.pixels.len() - } -} - -impl fmt::Debug for EnumeratePixelsMut<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumeratePixelsMut") - .field("pixels", &self.pixels) - .field("x", &self.x) - .field("y", &self.y) - .field("width", &self.width) - .finish() - } -} - -/// Enumerate the rows of an image. -pub struct EnumerateRowsMut<'a, P: Pixel + 'a> -where -

::Subpixel: 'a, -{ - rows: RowsMut<'a, P>, - y: u32, - width: u32, -} - -impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P> -where - P::Subpixel: 'a, -{ - type Item = (u32, EnumeratePixelsMut<'a, P>); - - #[inline(always)] - fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> { - let y = self.y; - self.y += 1; - self.rows.next().map(|r| { - ( - y, - EnumeratePixelsMut { - x: 0, - y, - width: self.width, - pixels: r, - }, - ) - }) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } -} - -impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P> -where - P::Subpixel: 'a, -{ - fn len(&self) -> usize { - self.rows.len() - } -} - -impl fmt::Debug for EnumerateRowsMut<'_, P> -where - P::Subpixel: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumerateRowsMut") - .field("rows", &self.rows) - .field("y", &self.y) - .field("width", &self.width) - .finish() - } -} - -/// Generic image buffer -/// -/// This is an image parameterised by its Pixel types, represented by a width and height and a -/// container of channel data. It provides direct access to its pixels and implements the -/// [`GenericImageView`] and [`GenericImage`] traits. In many ways, this is the standard buffer -/// implementing those traits. Using this concrete type instead of a generic type parameter has -/// been shown to improve performance. -/// -/// The crate defines a few type aliases with regularly used pixel types for your convenience, such -/// as [`RgbImage`], [`GrayImage`] etc. -/// -/// [`GenericImage`]: trait.GenericImage.html -/// [`GenericImageView`]: trait.GenericImageView.html -/// [`RgbImage`]: type.RgbImage.html -/// [`GrayImage`]: type.GrayImage.html -/// -/// To convert between images of different Pixel types use [`DynamicImage`]. -/// -/// You can retrieve a complete description of the buffer's layout and contents through -/// [`as_flat_samples`] and [`as_flat_samples_mut`]. This can be handy to also use the contents in -/// a foreign language, map it as a GPU host buffer or other similar tasks. -/// -/// [`DynamicImage`]: enum.DynamicImage.html -/// [`as_flat_samples`]: #method.as_flat_samples -/// [`as_flat_samples_mut`]: #method.as_flat_samples_mut -/// -/// ## Examples -/// -/// Create a simple canvas and paint a small cross. -/// -/// ``` -/// use image::{RgbImage, Rgb}; -/// -/// let mut img = RgbImage::new(32, 32); -/// -/// for x in 15..=17 { -/// for y in 8..24 { -/// img.put_pixel(x, y, Rgb([255, 0, 0])); -/// img.put_pixel(y, x, Rgb([255, 0, 0])); -/// } -/// } -/// ``` -/// -/// Overlays an image on top of a larger background raster. -/// -/// ```no_run -/// use image::{GenericImage, GenericImageView, ImageBuffer, open}; -/// -/// let on_top = open("path/to/some.png").unwrap().into_rgb8(); -/// let mut img = ImageBuffer::from_fn(512, 512, |x, y| { -/// if (x + y) % 2 == 0 { -/// image::Rgb([0, 0, 0]) -/// } else { -/// image::Rgb([255, 255, 255]) -/// } -/// }); -/// -/// image::imageops::overlay(&mut img, &on_top, 128, 128); -/// ``` -/// -/// Convert an RgbaImage to a GrayImage. -/// -/// ```no_run -/// use image::{open, DynamicImage}; -/// -/// let rgba = open("path/to/some.png").unwrap().into_rgba8(); -/// let gray = DynamicImage::ImageRgba8(rgba).into_luma8(); -/// ``` -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct ImageBuffer { - width: u32, - height: u32, - _phantom: PhantomData

, - data: Container, -} - -// generic implementation, shared along all image buffers -impl ImageBuffer -where - P: Pixel, - Container: Deref, -{ - /// Constructs a buffer from a generic container - /// (for example a `Vec` or a slice) - /// - /// Returns `None` if the container is not big enough (including when the image dimensions - /// necessitate an allocation of more bytes than supported by the container). - pub fn from_raw(width: u32, height: u32, buf: Container) -> Option> { - if Self::check_image_fits(width, height, buf.len()) { - Some(ImageBuffer { - data: buf, - width, - height, - _phantom: PhantomData, - }) - } else { - None - } - } - - /// Returns the underlying raw buffer - pub fn into_raw(self) -> Container { - self.data - } - - /// Returns the underlying raw buffer - pub fn as_raw(&self) -> &Container { - &self.data - } - - /// The width and height of this image. - pub fn dimensions(&self) -> (u32, u32) { - (self.width, self.height) - } - - /// The width of this image. - pub fn width(&self) -> u32 { - self.width - } - - /// The height of this image. - pub fn height(&self) -> u32 { - self.height - } - - // TODO: choose name under which to expose. - pub(crate) fn inner_pixels(&self) -> &[P::Subpixel] { - let len = Self::image_buffer_len(self.width, self.height).unwrap(); - &self.data[..len] - } - - /// Returns an iterator over the pixels of this image. - /// The iteration order is x = 0 to width then y = 0 to height - pub fn pixels(&self) -> Pixels

{ - Pixels { - chunks: self - .inner_pixels() - .chunks_exact(

::CHANNEL_COUNT as usize), - } - } - - /// Returns an iterator over the rows of this image. - /// - /// Only non-empty rows can be iterated in this manner. In particular the iterator will not - /// yield any item when the width of the image is `0` or a pixel type without any channels is - /// used. This ensures that its length can always be represented by `usize`. - pub fn rows(&self) -> Rows

{ - Rows::with_image(&self.data, self.width, self.height) - } - - /// Enumerates over the pixels of the image. - /// The iterator yields the coordinates of each pixel - /// along with a reference to them. - /// The iteration order is x = 0 to width then y = 0 to height - /// Starting from the top left. - pub fn enumerate_pixels(&self) -> EnumeratePixels

{ - EnumeratePixels { - pixels: self.pixels(), - x: 0, - y: 0, - width: self.width, - } - } - - /// Enumerates over the rows of the image. - /// The iterator yields the y-coordinate of each row - /// along with a reference to them. - pub fn enumerate_rows(&self) -> EnumerateRows

{ - EnumerateRows { - rows: self.rows(), - y: 0, - width: self.width, - } - } - - /// Gets a reference to the pixel at location `(x, y)` - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of the bounds `(width, height)`. - #[inline] - #[track_caller] - pub fn get_pixel(&self, x: u32, y: u32) -> &P { - match self.pixel_indices(x, y) { - None => panic!( - "Image index {:?} out of bounds {:?}", - (x, y), - (self.width, self.height) - ), - Some(pixel_indices) =>

::from_slice(&self.data[pixel_indices]), - } - } - - /// Gets a reference to the pixel at location `(x, y)` or returns `None` if - /// the index is out of the bounds `(width, height)`. - pub fn get_pixel_checked(&self, x: u32, y: u32) -> Option<&P> { - if x >= self.width { - return None; - } - let num_channels =

::CHANNEL_COUNT as usize; - let i = (y as usize) - .saturating_mul(self.width as usize) - .saturating_add(x as usize) - .saturating_mul(num_channels); - - self.data - .get(i..i.checked_add(num_channels)?) - .map(|pixel_indices|

::from_slice(pixel_indices)) - } - - /// Test that the image fits inside the buffer. - /// - /// Verifies that the maximum image of pixels inside the bounds is smaller than the provided - /// length. Note that as a corrolary we also have that the index calculation of pixels inside - /// the bounds will not overflow. - fn check_image_fits(width: u32, height: u32, len: usize) -> bool { - let checked_len = Self::image_buffer_len(width, height); - checked_len.map(|min_len| min_len <= len).unwrap_or(false) - } - - fn image_buffer_len(width: u32, height: u32) -> Option { - Some(

::CHANNEL_COUNT as usize) - .and_then(|size| size.checked_mul(width as usize)) - .and_then(|size| size.checked_mul(height as usize)) - } - - #[inline(always)] - fn pixel_indices(&self, x: u32, y: u32) -> Option> { - if x >= self.width || y >= self.height { - return None; - } - - Some(self.pixel_indices_unchecked(x, y)) - } - - #[inline(always)] - fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range { - let no_channels =

::CHANNEL_COUNT as usize; - // If in bounds, this can't overflow as we have tested that at construction! - let min_index = (y as usize * self.width as usize + x as usize) * no_channels; - min_index..min_index + no_channels - } - - /// Get the format of the buffer when viewed as a matrix of samples. - pub fn sample_layout(&self) -> SampleLayout { - // None of these can overflow, as all our memory is addressable. - SampleLayout::row_major_packed(

::CHANNEL_COUNT, self.width, self.height) - } - - /// Return the raw sample buffer with its stride an dimension information. - /// - /// The returned buffer is guaranteed to be well formed in all cases. It is laid out by - /// colors, width then height, meaning `channel_stride <= width_stride <= height_stride`. All - /// strides are in numbers of elements but those are mostly `u8` in which case the strides are - /// also byte strides. - pub fn into_flat_samples(self) -> FlatSamples - where - Container: AsRef<[P::Subpixel]>, - { - // None of these can overflow, as all our memory is addressable. - let layout = self.sample_layout(); - FlatSamples { - samples: self.data, - layout, - color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType - } - } - - /// Return a view on the raw sample buffer. - /// - /// See [`into_flat_samples`](#method.into_flat_samples) for more details. - pub fn as_flat_samples(&self) -> FlatSamples<&[P::Subpixel]> - where - Container: AsRef<[P::Subpixel]>, - { - let layout = self.sample_layout(); - FlatSamples { - samples: self.data.as_ref(), - layout, - color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType - } - } - - /// Return a mutable view on the raw sample buffer. - /// - /// See [`into_flat_samples`](#method.into_flat_samples) for more details. - pub fn as_flat_samples_mut(&mut self) -> FlatSamples<&mut [P::Subpixel]> - where - Container: AsMut<[P::Subpixel]>, - { - let layout = self.sample_layout(); - FlatSamples { - samples: self.data.as_mut(), - layout, - color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType - } - } -} - -impl ImageBuffer -where - P: Pixel, - Container: Deref + DerefMut, -{ - // TODO: choose name under which to expose. - pub(crate) fn inner_pixels_mut(&mut self) -> &mut [P::Subpixel] { - let len = Self::image_buffer_len(self.width, self.height).unwrap(); - &mut self.data[..len] - } - - /// Returns an iterator over the mutable pixels of this image. - pub fn pixels_mut(&mut self) -> PixelsMut

{ - PixelsMut { - chunks: self - .inner_pixels_mut() - .chunks_exact_mut(

::CHANNEL_COUNT as usize), - } - } - - /// Returns an iterator over the mutable rows of this image. - /// - /// Only non-empty rows can be iterated in this manner. In particular the iterator will not - /// yield any item when the width of the image is `0` or a pixel type without any channels is - /// used. This ensures that its length can always be represented by `usize`. - pub fn rows_mut(&mut self) -> RowsMut

{ - RowsMut::with_image(&mut self.data, self.width, self.height) - } - - /// Enumerates over the pixels of the image. - /// The iterator yields the coordinates of each pixel - /// along with a mutable reference to them. - pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut

{ - let width = self.width; - EnumeratePixelsMut { - pixels: self.pixels_mut(), - x: 0, - y: 0, - width, - } - } - - /// Enumerates over the rows of the image. - /// The iterator yields the y-coordinate of each row - /// along with a mutable reference to them. - pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut

{ - let width = self.width; - EnumerateRowsMut { - rows: self.rows_mut(), - y: 0, - width, - } - } - - /// Gets a reference to the mutable pixel at location `(x, y)` - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of the bounds `(width, height)`. - #[inline] - #[track_caller] - pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P { - match self.pixel_indices(x, y) { - None => panic!( - "Image index {:?} out of bounds {:?}", - (x, y), - (self.width, self.height) - ), - Some(pixel_indices) =>

::from_slice_mut(&mut self.data[pixel_indices]), - } - } - - /// Gets a reference to the mutable pixel at location `(x, y)` or returns - /// `None` if the index is out of the bounds `(width, height)`. - pub fn get_pixel_mut_checked(&mut self, x: u32, y: u32) -> Option<&mut P> { - if x >= self.width { - return None; - } - let num_channels =

::CHANNEL_COUNT as usize; - let i = (y as usize) - .saturating_mul(self.width as usize) - .saturating_add(x as usize) - .saturating_mul(num_channels); - - self.data - .get_mut(i..i.checked_add(num_channels)?) - .map(|pixel_indices|

::from_slice_mut(pixel_indices)) - } - - /// Puts a pixel at location `(x, y)` - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of the bounds `(width, height)`. - #[inline] - #[track_caller] - pub fn put_pixel(&mut self, x: u32, y: u32, pixel: P) { - *self.get_pixel_mut(x, y) = pixel - } -} - -impl ImageBuffer -where - P: Pixel, - [P::Subpixel]: EncodableLayout, - Container: Deref, -{ - /// Saves the buffer to a file at the path specified. - /// - /// The image format is derived from the file extension. - pub fn save(&self, path: Q) -> ImageResult<()> - where - Q: AsRef, - P: PixelWithColorType, - { - save_buffer( - path, - self.inner_pixels().as_bytes(), - self.width(), - self.height(), -

::COLOR_TYPE, - ) - } -} - -impl ImageBuffer -where - P: Pixel, - [P::Subpixel]: EncodableLayout, - Container: Deref, -{ - /// Saves the buffer to a file at the specified path in - /// the specified format. - /// - /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for - /// supported types. - pub fn save_with_format(&self, path: Q, format: ImageFormat) -> ImageResult<()> - where - Q: AsRef, - P: PixelWithColorType, - { - // This is valid as the subpixel is u8. - save_buffer_with_format( - path, - self.inner_pixels().as_bytes(), - self.width(), - self.height(), -

::COLOR_TYPE, - format, - ) - } -} - -impl ImageBuffer -where - P: Pixel, - [P::Subpixel]: EncodableLayout, - Container: Deref, -{ - /// Writes the buffer to a writer in the specified format. - /// - /// Assumes the writer is buffered. In most cases, - /// you should wrap your writer in a `BufWriter` for best performance. - /// - /// See [`ImageOutputFormat`](enum.ImageOutputFormat.html) for - /// supported types. - pub fn write_to(&self, writer: &mut W, format: F) -> ImageResult<()> - where - W: std::io::Write + std::io::Seek, - F: Into, - P: PixelWithColorType, - { - // This is valid as the subpixel is u8. - write_buffer_with_format( - writer, - self.inner_pixels().as_bytes(), - self.width(), - self.height(), -

::COLOR_TYPE, - format, - ) - } -} - -impl ImageBuffer -where - P: Pixel, - [P::Subpixel]: EncodableLayout, - Container: Deref, -{ - /// Writes the buffer with the given encoder. - pub fn write_with_encoder(&self, encoder: E) -> ImageResult<()> - where - E: ImageEncoder, - P: PixelWithColorType, - { - // This is valid as the subpixel is u8. - encoder.write_image( - self.inner_pixels().as_bytes(), - self.width(), - self.height(), -

::COLOR_TYPE, - ) - } -} - -impl Default for ImageBuffer -where - P: Pixel, - Container: Default, -{ - fn default() -> Self { - Self { - width: 0, - height: 0, - _phantom: PhantomData, - data: Default::default(), - } - } -} - -impl Deref for ImageBuffer -where - P: Pixel, - Container: Deref, -{ - type Target = [P::Subpixel]; - - fn deref(&self) -> &::Target { - &self.data - } -} - -impl DerefMut for ImageBuffer -where - P: Pixel, - Container: Deref + DerefMut, -{ - fn deref_mut(&mut self) -> &mut ::Target { - &mut self.data - } -} - -impl Index<(u32, u32)> for ImageBuffer -where - P: Pixel, - Container: Deref, -{ - type Output = P; - - fn index(&self, (x, y): (u32, u32)) -> &P { - self.get_pixel(x, y) - } -} - -impl IndexMut<(u32, u32)> for ImageBuffer -where - P: Pixel, - Container: Deref + DerefMut, -{ - fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P { - self.get_pixel_mut(x, y) - } -} - -impl Clone for ImageBuffer -where - P: Pixel, - Container: Deref + Clone, -{ - fn clone(&self) -> ImageBuffer { - ImageBuffer { - data: self.data.clone(), - width: self.width, - height: self.height, - _phantom: PhantomData, - } - } -} - -impl GenericImageView for ImageBuffer -where - P: Pixel, - Container: Deref + Deref, -{ - type Pixel = P; - - fn dimensions(&self) -> (u32, u32) { - self.dimensions() - } - - fn bounds(&self) -> (u32, u32, u32, u32) { - (0, 0, self.width, self.height) - } - - fn get_pixel(&self, x: u32, y: u32) -> P { - *self.get_pixel(x, y) - } - - /// Returns the pixel located at (x, y), ignoring bounds checking. - #[inline(always)] - unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P { - let indices = self.pixel_indices_unchecked(x, y); - *

::from_slice(self.data.get_unchecked(indices)) - } -} - -impl GenericImage for ImageBuffer -where - P: Pixel, - Container: Deref + DerefMut, -{ - fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P { - self.get_pixel_mut(x, y) - } - - fn put_pixel(&mut self, x: u32, y: u32, pixel: P) { - *self.get_pixel_mut(x, y) = pixel - } - - /// Puts a pixel at location (x, y), ignoring bounds checking. - #[inline(always)] - unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) { - let indices = self.pixel_indices_unchecked(x, y); - let p =

::from_slice_mut(self.data.get_unchecked_mut(indices)); - *p = pixel - } - - /// Put a pixel at location (x, y), taking into account alpha channels - /// - /// DEPRECATED: This method will be removed. Blend the pixel directly instead. - fn blend_pixel(&mut self, x: u32, y: u32, p: P) { - self.get_pixel_mut(x, y).blend(&p) - } - - fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool { - let Rect { - x: sx, - y: sy, - width, - height, - } = source; - let dx = x; - let dy = y; - assert!(sx < self.width() && dx < self.width()); - assert!(sy < self.height() && dy < self.height()); - if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height { - return false; - } - - if sy < dy { - for y in (0..height).rev() { - let sy = sy + y; - let dy = dy + y; - let Range { start, .. } = self.pixel_indices_unchecked(sx, sy); - let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy); - let dst = self.pixel_indices_unchecked(dx, dy).start; - self.data.copy_within(start..end, dst); - } - } else { - for y in 0..height { - let sy = sy + y; - let dy = dy + y; - let Range { start, .. } = self.pixel_indices_unchecked(sx, sy); - let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy); - let dst = self.pixel_indices_unchecked(dx, dy).start; - self.data.copy_within(start..end, dst); - } - } - true - } -} - -// concrete implementation for `Vec`-backed buffers -// TODO: I think that rustc does not "see" this impl any more: the impl with -// Container meets the same requirements. At least, I got compile errors that -// there is no such function as `into_vec`, whereas `into_raw` did work, and -// `into_vec` is redundant anyway, because `into_raw` will give you the vector, -// and it is more generic. -impl ImageBuffer> { - /// Creates a new image buffer based on a `Vec`. - /// - /// # Panics - /// - /// Panics when the resulting image is larger than the maximum size of a vector. - pub fn new(width: u32, height: u32) -> ImageBuffer> { - let size = Self::image_buffer_len(width, height) - .expect("Buffer length in `ImageBuffer::new` overflows usize"); - ImageBuffer { - data: vec![Zero::zero(); size], - width, - height, - _phantom: PhantomData, - } - } - - /// Constructs a new ImageBuffer by copying a pixel - /// - /// # Panics - /// - /// Panics when the resulting image is larger the the maximum size of a vector. - pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuffer> { - let mut buf = ImageBuffer::new(width, height); - for p in buf.pixels_mut() { - *p = pixel - } - buf - } - - /// Constructs a new ImageBuffer by repeated application of the supplied function. - /// - /// The arguments to the function are the pixel's x and y coordinates. - /// - /// # Panics - /// - /// Panics when the resulting image is larger the the maximum size of a vector. - pub fn from_fn(width: u32, height: u32, mut f: F) -> ImageBuffer> - where - F: FnMut(u32, u32) -> P, - { - let mut buf = ImageBuffer::new(width, height); - for (x, y, p) in buf.enumerate_pixels_mut() { - *p = f(x, y) - } - buf - } - - /// Creates an image buffer out of an existing buffer. - /// Returns None if the buffer is not big enough. - pub fn from_vec( - width: u32, - height: u32, - buf: Vec, - ) -> Option>> { - ImageBuffer::from_raw(width, height, buf) - } - - /// Consumes the image buffer and returns the underlying data - /// as an owned buffer - pub fn into_vec(self) -> Vec { - self.into_raw() - } -} - -/// Provides color conversions for whole image buffers. -pub trait ConvertBuffer { - /// Converts `self` to a buffer of type T - /// - /// A generic implementation is provided to convert any image buffer to a image buffer - /// based on a `Vec`. - fn convert(&self) -> T; -} - -// concrete implementation Luma -> Rgba -impl GrayImage { - /// Expands a color palette by re-using the existing buffer. - /// Assumes 8 bit per pixel. Uses an optionally transparent index to - /// adjust it's alpha value accordingly. - pub fn expand_palette( - self, - palette: &[(u8, u8, u8)], - transparent_idx: Option, - ) -> RgbaImage { - let (width, height) = self.dimensions(); - let mut data = self.into_raw(); - let entries = data.len(); - data.resize(entries.checked_mul(4).unwrap(), 0); - let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap(); - expand_packed(&mut buffer, 4, 8, |idx, pixel| { - let (r, g, b) = palette[idx as usize]; - let a = if let Some(t_idx) = transparent_idx { - if t_idx == idx { - 0 - } else { - 255 - } - } else { - 255 - }; - pixel[0] = r; - pixel[1] = g; - pixel[2] = b; - pixel[3] = a; - }); - buffer - } -} - -// TODO: Equality constraints are not yet supported in where clauses, when they -// are, the T parameter should be removed in favor of ToType::Subpixel, which -// will then be FromType::Subpixel. -impl - ConvertBuffer>> for ImageBuffer -where - Container: Deref, - ToType: FromColor, -{ - /// # Examples - /// Convert RGB image to gray image. - /// ```no_run - /// use image::buffer::ConvertBuffer; - /// use image::GrayImage; - /// - /// let image_path = "examples/fractal.png"; - /// let image = image::open(&image_path) - /// .expect("Open file failed") - /// .to_rgba8(); - /// - /// let gray_image: GrayImage = image.convert(); - /// ``` - fn convert(&self) -> ImageBuffer> { - let mut buffer: ImageBuffer> = - ImageBuffer::new(self.width, self.height); - for (to, from) in buffer.pixels_mut().zip(self.pixels()) { - to.from_color(from) - } - buffer - } -} - -/// Sendable Rgb image buffer -pub type RgbImage = ImageBuffer, Vec>; -/// Sendable Rgb + alpha channel image buffer -pub type RgbaImage = ImageBuffer, Vec>; -/// Sendable grayscale image buffer -pub type GrayImage = ImageBuffer, Vec>; -/// Sendable grayscale + alpha channel image buffer -pub type GrayAlphaImage = ImageBuffer, Vec>; -/// Sendable 16-bit Rgb image buffer -pub(crate) type Rgb16Image = ImageBuffer, Vec>; -/// Sendable 16-bit Rgb + alpha channel image buffer -pub(crate) type Rgba16Image = ImageBuffer, Vec>; -/// Sendable 16-bit grayscale image buffer -pub(crate) type Gray16Image = ImageBuffer, Vec>; -/// Sendable 16-bit grayscale + alpha channel image buffer -pub(crate) type GrayAlpha16Image = ImageBuffer, Vec>; - -/// An image buffer for 32-bit float RGB pixels, -/// where the backing container is a flattened vector of floats. -pub type Rgb32FImage = ImageBuffer, Vec>; - -/// An image buffer for 32-bit float RGBA pixels, -/// where the backing container is a flattened vector of floats. -pub type Rgba32FImage = ImageBuffer, Vec>; - -impl From for RgbImage { - fn from(value: DynamicImage) -> Self { - value.into_rgb8() - } -} - -impl From for RgbaImage { - fn from(value: DynamicImage) -> Self { - value.into_rgba8() - } -} - -impl From for GrayImage { - fn from(value: DynamicImage) -> Self { - value.into_luma8() - } -} - -impl From for GrayAlphaImage { - fn from(value: DynamicImage) -> Self { - value.into_luma_alpha8() - } -} - -impl From for Rgb16Image { - fn from(value: DynamicImage) -> Self { - value.into_rgb16() - } -} - -impl From for Rgba16Image { - fn from(value: DynamicImage) -> Self { - value.into_rgba16() - } -} - -impl From for Gray16Image { - fn from(value: DynamicImage) -> Self { - value.into_luma16() - } -} - -impl From for GrayAlpha16Image { - fn from(value: DynamicImage) -> Self { - value.into_luma_alpha16() - } -} - -impl From for Rgba32FImage { - fn from(value: DynamicImage) -> Self { - value.into_rgba32f() - } -} - -#[cfg(test)] -mod test { - use super::{GrayImage, ImageBuffer, ImageOutputFormat, RgbImage}; - use crate::math::Rect; - use crate::GenericImage as _; - use crate::{color, Rgb}; - - #[test] - /// Tests if image buffers from slices work - fn slice_buffer() { - let data = [0; 9]; - let buf: ImageBuffer, _> = ImageBuffer::from_raw(3, 3, &data[..]).unwrap(); - assert_eq!(&*buf, &data[..]) - } - - #[test] - fn get_pixel() { - let mut a: RgbImage = ImageBuffer::new(10, 10); - { - let b = a.get_mut(3 * 10).unwrap(); - *b = 255; - } - assert_eq!(a.get_pixel(0, 1)[0], 255) - } - - #[test] - fn get_pixel_checked() { - let mut a: RgbImage = ImageBuffer::new(10, 10); - a.get_pixel_mut_checked(0, 1).unwrap()[0] = 255; - - assert_eq!(a.get_pixel_checked(0, 1), Some(&Rgb([255, 0, 0]))); - assert_eq!(a.get_pixel_checked(0, 1).unwrap(), a.get_pixel(0, 1)); - assert_eq!(a.get_pixel_checked(10, 0), None); - assert_eq!(a.get_pixel_checked(0, 10), None); - assert_eq!(a.get_pixel_mut_checked(10, 0), None); - assert_eq!(a.get_pixel_mut_checked(0, 10), None); - - // From image/issues/1672 - const WHITE: Rgb = Rgb([255_u8, 255, 255]); - let mut a = RgbImage::new(2, 1); - a.put_pixel(1, 0, WHITE); - - assert_eq!(a.get_pixel_checked(1, 0), Some(&WHITE)); - assert_eq!(a.get_pixel_checked(1, 0).unwrap(), a.get_pixel(1, 0)); - } - - #[test] - fn mut_iter() { - let mut a: RgbImage = ImageBuffer::new(10, 10); - { - let val = a.pixels_mut().next().unwrap(); - *val = Rgb([42, 0, 0]); - } - assert_eq!(a.data[0], 42) - } - - #[test] - fn zero_width_zero_height() { - let mut image = RgbImage::new(0, 0); - - assert_eq!(image.rows_mut().count(), 0); - assert_eq!(image.pixels_mut().count(), 0); - assert_eq!(image.rows().count(), 0); - assert_eq!(image.pixels().count(), 0); - } - - #[test] - fn zero_width_nonzero_height() { - let mut image = RgbImage::new(0, 2); - - assert_eq!(image.rows_mut().count(), 0); - assert_eq!(image.pixels_mut().count(), 0); - assert_eq!(image.rows().count(), 0); - assert_eq!(image.pixels().count(), 0); - } - - #[test] - fn nonzero_width_zero_height() { - let mut image = RgbImage::new(2, 0); - - assert_eq!(image.rows_mut().count(), 0); - assert_eq!(image.pixels_mut().count(), 0); - assert_eq!(image.rows().count(), 0); - assert_eq!(image.pixels().count(), 0); - } - - #[test] - fn pixels_on_large_buffer() { - let mut image = RgbImage::from_raw(1, 1, vec![0; 6]).unwrap(); - - assert_eq!(image.pixels().count(), 1); - assert_eq!(image.enumerate_pixels().count(), 1); - assert_eq!(image.pixels_mut().count(), 1); - assert_eq!(image.enumerate_pixels_mut().count(), 1); - - assert_eq!(image.rows().count(), 1); - assert_eq!(image.rows_mut().count(), 1); - } - - #[test] - fn default() { - let image = ImageBuffer::, Vec>::default(); - assert_eq!(image.dimensions(), (0, 0)); - } - - #[test] - #[rustfmt::skip] - fn test_image_buffer_copy_within_oob() { - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap(); - assert!(!image.copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0)); - assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0)); - assert!(!image.copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0)); - assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0)); - assert!(!image.copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0)); - assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1)); - assert!(!image.copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0)); - } - - #[test] - fn test_image_buffer_copy_within_tl() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.copy_within( - Rect { - x: 0, - y: 0, - width: 3, - height: 3 - }, - 1, - 1 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_image_buffer_copy_within_tr() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.copy_within( - Rect { - x: 1, - y: 0, - width: 3, - height: 3 - }, - 0, - 1 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_image_buffer_copy_within_bl() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.copy_within( - Rect { - x: 0, - y: 1, - width: 3, - height: 3 - }, - 1, - 0 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_image_buffer_copy_within_br() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.copy_within( - Rect { - x: 1, - y: 1, - width: 3, - height: 3 - }, - 0, - 0 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - #[cfg(feature = "png")] - fn write_to_with_large_buffer() { - // A buffer of 1 pixel, padded to 4 bytes as would be common in, e.g. BMP. - let img: GrayImage = ImageBuffer::from_raw(1, 1, vec![0u8; 4]).unwrap(); - let mut buffer = std::io::Cursor::new(vec![]); - assert!(img.write_to(&mut buffer, ImageOutputFormat::Png).is_ok()); - } - - #[test] - fn exact_size_iter_size_hint() { - // The docs for `std::iter::ExactSizeIterator` requires that the implementation of - // `size_hint` on the iterator returns the same value as the `len` implementation. - - // This test should work for any size image. - const N: u32 = 10; - - let mut image = RgbImage::from_raw(N, N, vec![0; (N * N * 3) as usize]).unwrap(); - - let iter = image.pixels(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.pixels_mut(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.rows(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.rows_mut(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.enumerate_pixels(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.enumerate_rows(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.enumerate_pixels_mut(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - - let iter = image.enumerate_rows_mut(); - let exact_len = ExactSizeIterator::len(&iter); - assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); - } -} - -#[cfg(test)] -#[cfg(feature = "benchmarks")] -mod benchmarks { - use super::{ConvertBuffer, GrayImage, ImageBuffer, Pixel, RgbImage}; - - #[bench] - fn conversion(b: &mut test::Bencher) { - let mut a: RgbImage = ImageBuffer::new(1000, 1000); - for p in a.pixels_mut() { - let rgb = p.channels_mut(); - rgb[0] = 255; - rgb[1] = 23; - rgb[2] = 42; - } - assert!(a.data[0] != 0); - b.iter(|| { - let b: GrayImage = a.convert(); - assert!(0 != b.data[0]); - assert!(a.data[0] != b.data[0]); - test::black_box(b); - }); - b.bytes = 1000 * 1000 * 3 - } - - #[bench] - fn image_access_row_by_row(b: &mut test::Bencher) { - let mut a: RgbImage = ImageBuffer::new(1000, 1000); - for p in a.pixels_mut() { - let rgb = p.channels_mut(); - rgb[0] = 255; - rgb[1] = 23; - rgb[2] = 42; - } - - b.iter(move || { - let image: &RgbImage = test::black_box(&a); - let mut sum: usize = 0; - for y in 0..1000 { - for x in 0..1000 { - let pixel = image.get_pixel(x, y); - sum = sum.wrapping_add(pixel[0] as usize); - sum = sum.wrapping_add(pixel[1] as usize); - sum = sum.wrapping_add(pixel[2] as usize); - } - } - test::black_box(sum) - }); - - b.bytes = 1000 * 1000 * 3; - } - - #[bench] - fn image_access_col_by_col(b: &mut test::Bencher) { - let mut a: RgbImage = ImageBuffer::new(1000, 1000); - for p in a.pixels_mut() { - let rgb = p.channels_mut(); - rgb[0] = 255; - rgb[1] = 23; - rgb[2] = 42; - } - - b.iter(move || { - let image: &RgbImage = test::black_box(&a); - let mut sum: usize = 0; - for x in 0..1000 { - for y in 0..1000 { - let pixel = image.get_pixel(x, y); - sum = sum.wrapping_add(pixel[0] as usize); - sum = sum.wrapping_add(pixel[1] as usize); - sum = sum.wrapping_add(pixel[2] as usize); - } - } - test::black_box(sum) - }); - - b.bytes = 1000 * 1000 * 3; - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/buffer_par.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer_par.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/buffer_par.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/buffer_par.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,496 +0,0 @@ -use rayon::iter::plumbing::*; -use rayon::iter::{IndexedParallelIterator, ParallelIterator}; -use rayon::slice::{ChunksExact, ChunksExactMut, ParallelSlice, ParallelSliceMut}; -use std::fmt; -use std::ops::{Deref, DerefMut}; - -use crate::traits::Pixel; -use crate::ImageBuffer; - -/// Parallel iterator over pixel refs. -#[derive(Clone)] -pub struct PixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - chunks: ChunksExact<'a, P::Subpixel>, -} - -impl<'a, P> ParallelIterator for PixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - type Item = &'a P; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.chunks - .map(|v|

::from_slice(v)) - .drive_unindexed(consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl<'a, P> IndexedParallelIterator for PixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - fn drive>(self, consumer: C) -> C::Result { - self.chunks - .map(|v|

::from_slice(v)) - .drive(consumer) - } - - fn len(&self) -> usize { - self.chunks.len() - } - - fn with_producer>(self, callback: CB) -> CB::Output { - self.chunks - .map(|v|

::from_slice(v)) - .with_producer(callback) - } -} - -impl

fmt::Debug for PixelsPar<'_, P> -where - P: Pixel + Sync, - P::Subpixel: Sync + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("PixelsPar") - .field("chunks", &self.chunks) - .finish() - } -} - -/// Parallel iterator over mutable pixel refs. -pub struct PixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - chunks: ChunksExactMut<'a, P::Subpixel>, -} - -impl<'a, P> ParallelIterator for PixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - type Item = &'a mut P; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.chunks - .map(|v|

::from_slice_mut(v)) - .drive_unindexed(consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl<'a, P> IndexedParallelIterator for PixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - fn drive>(self, consumer: C) -> C::Result { - self.chunks - .map(|v|

::from_slice_mut(v)) - .drive(consumer) - } - - fn len(&self) -> usize { - self.chunks.len() - } - - fn with_producer>(self, callback: CB) -> CB::Output { - self.chunks - .map(|v|

::from_slice_mut(v)) - .with_producer(callback) - } -} - -impl

fmt::Debug for PixelsMutPar<'_, P> -where - P: Pixel + Send + Sync, - P::Subpixel: Send + Sync + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("PixelsMutPar") - .field("chunks", &self.chunks) - .finish() - } -} - -/// Parallel iterator over pixel refs and their coordinates. -#[derive(Clone)] -pub struct EnumeratePixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - pixels: PixelsPar<'a, P>, - width: u32, -} - -impl<'a, P> ParallelIterator for EnumeratePixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - type Item = (u32, u32, &'a P); - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .drive_unindexed(consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl<'a, P> IndexedParallelIterator for EnumeratePixelsPar<'a, P> -where - P: Pixel + Sync + 'a, - P::Subpixel: Sync + 'a, -{ - fn drive>(self, consumer: C) -> C::Result { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .drive(consumer) - } - - fn len(&self) -> usize { - self.pixels.len() - } - - fn with_producer>(self, callback: CB) -> CB::Output { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .with_producer(callback) - } -} - -impl

fmt::Debug for EnumeratePixelsPar<'_, P> -where - P: Pixel + Sync, - P::Subpixel: Sync + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumeratePixelsPar") - .field("pixels", &self.pixels) - .field("width", &self.width) - .finish() - } -} - -/// Parallel iterator over mutable pixel refs and their coordinates. -pub struct EnumeratePixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - pixels: PixelsMutPar<'a, P>, - width: u32, -} - -impl<'a, P> ParallelIterator for EnumeratePixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - type Item = (u32, u32, &'a mut P); - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .drive_unindexed(consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl<'a, P> IndexedParallelIterator for EnumeratePixelsMutPar<'a, P> -where - P: Pixel + Send + Sync + 'a, - P::Subpixel: Send + Sync + 'a, -{ - fn drive>(self, consumer: C) -> C::Result { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .drive(consumer) - } - - fn len(&self) -> usize { - self.pixels.len() - } - - fn with_producer>(self, callback: CB) -> CB::Output { - self.pixels - .enumerate() - .map(|(i, p)| { - ( - (i % self.width as usize) as u32, - (i / self.width as usize) as u32, - p, - ) - }) - .with_producer(callback) - } -} - -impl

fmt::Debug for EnumeratePixelsMutPar<'_, P> -where - P: Pixel + Send + Sync, - P::Subpixel: Send + Sync + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EnumeratePixelsMutPar") - .field("pixels", &self.pixels) - .field("width", &self.width) - .finish() - } -} - -impl ImageBuffer -where - P: Pixel + Sync, - P::Subpixel: Sync, - Container: Deref, -{ - /// Returns a parallel iterator over the pixels of this image, usable with `rayon`. - /// See [`pixels`] for more information. - /// - /// [`pixels`]: #method.pixels - pub fn par_pixels(&self) -> PixelsPar

{ - PixelsPar { - chunks: self - .inner_pixels() - .par_chunks_exact(

::CHANNEL_COUNT as usize), - } - } - - /// Returns a parallel iterator over the pixels of this image and their coordinates, usable with `rayon`. - /// See [`enumerate_pixels`] for more information. - /// - /// [`enumerate_pixels`]: #method.enumerate_pixels - pub fn par_enumerate_pixels(&self) -> EnumeratePixelsPar

{ - EnumeratePixelsPar { - pixels: self.par_pixels(), - width: self.width(), - } - } -} - -impl ImageBuffer -where - P: Pixel + Send + Sync, - P::Subpixel: Send + Sync, - Container: Deref + DerefMut, -{ - /// Returns a parallel iterator over the mutable pixels of this image, usable with `rayon`. - /// See [`pixels_mut`] for more information. - /// - /// [`pixels_mut`]: #method.pixels_mut - pub fn par_pixels_mut(&mut self) -> PixelsMutPar

{ - PixelsMutPar { - chunks: self - .inner_pixels_mut() - .par_chunks_exact_mut(

::CHANNEL_COUNT as usize), - } - } - - /// Returns a parallel iterator over the mutable pixels of this image and their coordinates, usable with `rayon`. - /// See [`enumerate_pixels_mut`] for more information. - /// - /// [`enumerate_pixels_mut`]: #method.enumerate_pixels_mut - pub fn par_enumerate_pixels_mut(&mut self) -> EnumeratePixelsMutPar

{ - let width = self.width(); - EnumeratePixelsMutPar { - pixels: self.par_pixels_mut(), - width, - } - } -} - -impl

ImageBuffer> -where - P: Pixel + Send + Sync, - P::Subpixel: Send + Sync, -{ - /// Constructs a new ImageBuffer by repeated application of the supplied function, - /// utilizing multi-threading via `rayon`. - /// - /// The arguments to the function are the pixel's x and y coordinates. - /// - /// # Panics - /// - /// Panics when the resulting image is larger the the maximum size of a vector. - pub fn from_par_fn(width: u32, height: u32, f: F) -> ImageBuffer> - where - F: Fn(u32, u32) -> P + Send + Sync, - { - let mut buf = ImageBuffer::new(width, height); - buf.par_enumerate_pixels_mut().for_each(|(x, y, p)| { - *p = f(x, y); - }); - - buf - } -} - -#[cfg(test)] -mod test { - use crate::{Rgb, RgbImage}; - use rayon::iter::{IndexedParallelIterator, ParallelIterator}; - - fn test_width_height(width: u32, height: u32, len: usize) { - let mut image = RgbImage::new(width, height); - - assert_eq!(image.par_enumerate_pixels_mut().len(), len); - assert_eq!(image.par_enumerate_pixels().len(), len); - assert_eq!(image.par_pixels_mut().len(), len); - assert_eq!(image.par_pixels().len(), len); - } - - #[test] - fn zero_width_zero_height() { - test_width_height(0, 0, 0); - } - - #[test] - fn zero_width_nonzero_height() { - test_width_height(0, 2, 0); - } - - #[test] - fn nonzero_width_zero_height() { - test_width_height(2, 0, 0); - } - - #[test] - fn iter_parity() { - let mut image1 = RgbImage::from_fn(17, 29, |x, y| { - Rgb(std::array::from_fn(|i| { - ((x + y * 98 + i as u32 * 27) % 255) as u8 - })) - }); - let mut image2 = image1.clone(); - - assert_eq!( - image1.enumerate_pixels_mut().collect::>(), - image2.par_enumerate_pixels_mut().collect::>() - ); - assert_eq!( - image1.enumerate_pixels().collect::>(), - image2.par_enumerate_pixels().collect::>() - ); - assert_eq!( - image1.pixels_mut().collect::>(), - image2.par_pixels_mut().collect::>() - ); - assert_eq!( - image1.pixels().collect::>(), - image2.par_pixels().collect::>() - ); - } -} - -#[cfg(test)] -#[cfg(feature = "benchmarks")] -mod benchmarks { - use crate::{Rgb, RgbImage}; - - const S: u32 = 1024; - - #[bench] - fn creation(b: &mut test::Bencher) { - let mut bytes = 0; - b.iter(|| { - let img = RgbImage::from_fn(S, S, |_, _| test::black_box(pixel_func())); - - bytes += img.as_raw().len() as u64; - }); - - b.bytes = bytes; - } - - #[bench] - fn creation_par(b: &mut test::Bencher) { - let mut bytes = 0; - b.iter(|| { - let img = RgbImage::from_par_fn(S, S, |_, _| test::black_box(pixel_func())); - - bytes += img.as_raw().len() as u64; - }); - - b.bytes = bytes; - } - - fn pixel_func() -> Rgb { - use std::collections::hash_map::RandomState; - use std::hash::{BuildHasher, Hasher}; - Rgb(std::array::from_fn(|_| { - RandomState::new().build_hasher().finish() as u8 - })) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,18 +1,25 @@ //! Decoding of AVIF images. +use crate::error::{ + DecodingError, ImageFormatHint, LimitError, LimitErrorKind, UnsupportedError, + UnsupportedErrorKind, +}; +use crate::{ColorType, ImageDecoder, ImageError, ImageFormat, ImageResult}; /// /// The [AVIF] specification defines an image derivative of the AV1 bitstream, an open video codec. /// /// [AVIF]: https://aomediacodec.github.io/av1-avif/ use std::error::Error; -use std::io::{self, Cursor, Read}; +use std::fmt::{Display, Formatter}; +use std::io::Read; use std::marker::PhantomData; -use std::mem; - -use crate::error::{DecodingError, ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; -use crate::{ColorType, ImageDecoder, ImageError, ImageFormat, ImageResult}; +use crate::codecs::avif::ycgco::{ + ycgco420_to_rgba10, ycgco420_to_rgba12, ycgco420_to_rgba8, ycgco422_to_rgba10, + ycgco422_to_rgba12, ycgco422_to_rgba8, ycgco444_to_rgba10, ycgco444_to_rgba12, + ycgco444_to_rgba8, +}; +use crate::codecs::avif::yuv::*; use dav1d::{PixelLayout, PlanarImageComponent}; -use dcv_color_primitives as dcp; use mp4parse::{read_avif, ParseStrictness}; fn error_map>>(err: E) -> ImageError { @@ -29,6 +36,43 @@ icc_profile: Option>, } +#[derive(Debug, Clone, PartialEq, Eq)] +enum AvifDecoderError { + AlphaPlaneFormat(PixelLayout), + YuvLayoutOnIdentityMatrix(PixelLayout), + UnsupportedLayoutAndMatrix(PixelLayout, YuvMatrixStrategy), +} + +impl Display for AvifDecoderError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AvifDecoderError::AlphaPlaneFormat(pixel_layout) => match pixel_layout { + PixelLayout::I400 => unreachable!("This option must be handled correctly"), + PixelLayout::I420 => f.write_str("Alpha layout must be 4:0:0, but it was 4:2:0"), + PixelLayout::I422 => f.write_str("Alpha layout must be 4:0:0, but it was 4:2:2"), + PixelLayout::I444 => f.write_str("Alpha layout must be 4:0:0, but it was 4:4:4"), + }, + AvifDecoderError::YuvLayoutOnIdentityMatrix(pixel_layout) => match pixel_layout { + PixelLayout::I400 => { + f.write_str("YUV layout on 'Identity' matrix must be 4:4:4, but it was 4:0:0") + } + PixelLayout::I420 => { + f.write_str("YUV layout on 'Identity' matrix must be 4:4:4, but it was 4:2:0") + } + PixelLayout::I422 => { + f.write_str("YUV layout on 'Identity' matrix must be 4:4:4, but it was 4:2:2") + } + PixelLayout::I444 => unreachable!("This option must be handled correctly"), + }, + AvifDecoderError::UnsupportedLayoutAndMatrix(layout, matrix) => f.write_fmt( + format_args!("YUV layout {layout:?} on matrix {matrix:?} is not supported",), + ), + } + } +} + +impl Error for AvifDecoderError {} + impl AvifDecoder { /// Create a new decoder that reads its input from `r`. pub fn new(mut r: R) -> ImageResult { @@ -57,17 +101,7 @@ match picture.bit_depth() { 8 => (), - 10 | 12 => { - return ImageResult::Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormatHint::Exact(ImageFormat::Avif), - UnsupportedErrorKind::GenericFeature(format!( - "Only 8 bit depth is supported but was {}", - picture.bit_depth() - )), - ), - )) - } + 10 | 12 => (), _ => { return ImageResult::Err(ImageError::Decoding(DecodingError::new( ImageFormatHint::Exact(ImageFormat::Avif), @@ -87,120 +121,537 @@ } } -/// Wrapper struct around a `Cursor>` -pub struct AvifReader(Cursor>, PhantomData); +/// Reshaping incorrectly aligned or sized FFI data into Rust constraints +fn reshape_plane(source: &[u8], stride: usize, width: usize, height: usize) -> Vec { + let mut target_plane = vec![0u16; width * height]; + for (shaped_row, src_row) in target_plane + .chunks_exact_mut(width) + .zip(source.chunks_exact(stride)) + { + for (dst, src) in shaped_row.iter_mut().zip(src_row.chunks_exact(2)) { + *dst = u16::from_ne_bytes([src[0], src[1]]); + } + } + target_plane +} -impl Read for AvifReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) +struct Plane16View<'a> { + data: std::borrow::Cow<'a, [u16]>, + stride: usize, +} + +impl Default for Plane16View<'_> { + fn default() -> Self { + Plane16View { + data: std::borrow::Cow::Owned(vec![]), + stride: 0, + } + } +} + +/// This is correct to transmute FFI data for Y plane and Alpha plane +fn transmute_y_plane16( + plane: &dav1d::Plane, + stride: usize, + width: usize, + height: usize, +) -> Plane16View<'_> { + let mut y_plane_stride = stride >> 1; + + let mut bind_y = vec![]; + let plane_ref = plane.as_ref(); + + let mut shape_y_plane = || { + y_plane_stride = width; + bind_y = reshape_plane(plane_ref, stride, width, height); + }; + + if stride & 1 == 0 { + match bytemuck::try_cast_slice(plane_ref) { + Ok(slice) => Plane16View { + data: std::borrow::Cow::Borrowed(slice), + stride: y_plane_stride, + }, + Err(_) => { + shape_y_plane(); + Plane16View { + data: std::borrow::Cow::Owned(bind_y), + stride: y_plane_stride, + } + } + } + } else { + shape_y_plane(); + Plane16View { + data: std::borrow::Cow::Owned(bind_y), + stride: y_plane_stride, } } } -impl<'a, R: 'a + Read> ImageDecoder<'a> for AvifDecoder { - type Reader = AvifReader; +/// This is correct to transmute FFI data for Y plane and Alpha plane +fn transmute_chroma_plane16( + plane: &dav1d::Plane, + pixel_layout: PixelLayout, + stride: usize, + width: usize, + height: usize, +) -> Plane16View<'_> { + let plane_ref = plane.as_ref(); + let mut chroma_plane_stride = stride >> 1; + let mut bind_chroma = vec![]; + + let mut shape_chroma_plane = || { + chroma_plane_stride = match pixel_layout { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 | PixelLayout::I422 => width.div_ceil(2), + PixelLayout::I444 => width, + }; + let u_plane_height = match pixel_layout { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 => height.div_ceil(2), + PixelLayout::I422 | PixelLayout::I444 => height, + }; + bind_chroma = reshape_plane(plane_ref, stride, chroma_plane_stride, u_plane_height); + }; + if stride & 1 == 0 { + match bytemuck::try_cast_slice(plane_ref) { + Ok(slice) => Plane16View { + data: std::borrow::Cow::Borrowed(slice), + stride: chroma_plane_stride, + }, + Err(_) => { + shape_chroma_plane(); + Plane16View { + data: std::borrow::Cow::Owned(bind_chroma), + stride: chroma_plane_stride, + } + } + } + } else { + shape_chroma_plane(); + Plane16View { + data: std::borrow::Cow::Owned(bind_chroma), + stride: chroma_plane_stride, + } + } +} + +#[derive(Copy, Clone, Debug, PartialOrd, Eq, PartialEq)] +enum YuvMatrixStrategy { + KrKb(YuvStandardMatrix), + CgCo, + Identity, +} + +/// Getting one of prebuilt matrix of fails +fn get_matrix( + david_matrix: dav1d::pixel::MatrixCoefficients, +) -> Result { + match david_matrix { + dav1d::pixel::MatrixCoefficients::Identity => Ok(YuvMatrixStrategy::Identity), + dav1d::pixel::MatrixCoefficients::BT709 => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Bt709)) + } + // This is arguable, some applications prefer to go with Bt.709 as default, + // and some applications prefer Bt.601 as default. + // For ex. `Chrome` always prefer Bt.709 even for SD content + // However, nowadays standard should be Bt.709 for HD+ size otherwise Bt.601 + dav1d::pixel::MatrixCoefficients::Unspecified => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Bt709)) + } + dav1d::pixel::MatrixCoefficients::Reserved => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Avif.into(), + UnsupportedErrorKind::GenericFeature( + "Using 'Reserved' color matrix is not supported".to_string(), + ), + ), + )), + dav1d::pixel::MatrixCoefficients::BT470M => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Bt470_6)) + } + dav1d::pixel::MatrixCoefficients::BT470BG => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Bt601)) + } + dav1d::pixel::MatrixCoefficients::ST170M => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Smpte240)) + } + dav1d::pixel::MatrixCoefficients::ST240M => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Smpte240)) + } + dav1d::pixel::MatrixCoefficients::YCgCo => Ok(YuvMatrixStrategy::CgCo), + dav1d::pixel::MatrixCoefficients::BT2020NonConstantLuminance => { + Ok(YuvMatrixStrategy::KrKb(YuvStandardMatrix::Bt2020)) + } + dav1d::pixel::MatrixCoefficients::BT2020ConstantLuminance => { + // This matrix significantly differs from others because linearize values is required + // to compute Y instead of Y'. + // Actually it is almost everywhere is not implemented. + // Libavif + libheif missing this also so actually AVIF images + // with CL BT.2020 might be made only by mistake + Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Avif.into(), + UnsupportedErrorKind::GenericFeature( + "BT2020ConstantLuminance matrix is not supported".to_string(), + ), + ), + )) + } + dav1d::pixel::MatrixCoefficients::ST2085 => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Avif.into(), + UnsupportedErrorKind::GenericFeature("ST2085 matrix is not supported".to_string()), + ), + )), + dav1d::pixel::MatrixCoefficients::ChromaticityDerivedConstantLuminance + | dav1d::pixel::MatrixCoefficients::ChromaticityDerivedNonConstantLuminance => Err( + ImageError::Unsupported(UnsupportedError::from_format_and_kind( + ImageFormat::Avif.into(), + UnsupportedErrorKind::GenericFeature( + "Chromaticity Derived Luminance matrix is not supported".to_string(), + ), + )), + ), + dav1d::pixel::MatrixCoefficients::ICtCp => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Avif.into(), + UnsupportedErrorKind::GenericFeature( + "ICtCp Derived Luminance matrix is not supported".to_string(), + ), + ), + )), + } +} + +impl ImageDecoder for AvifDecoder { fn dimensions(&self) -> (u32, u32) { (self.picture.width(), self.picture.height()) } fn color_type(&self) -> ColorType { - ColorType::Rgba8 - } - - fn icc_profile(&mut self) -> Option> { - self.icc_profile.clone() + if self.picture.bit_depth() == 8 { + ColorType::Rgba8 + } else { + ColorType::Rgba16 + } } - fn into_reader(self) -> ImageResult { - let plane = self.picture.plane(PlanarImageComponent::Y); - Ok(AvifReader( - Cursor::new(plane.as_ref().to_vec()), - PhantomData, - )) + fn icc_profile(&mut self) -> ImageResult>> { + Ok(self.icc_profile.clone()) } fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - if self.picture.pixel_layout() != PixelLayout::I400 { - let pixel_format = match self.picture.pixel_layout() { - PixelLayout::I400 => todo!(), - PixelLayout::I420 => dcp::PixelFormat::I420, - PixelLayout::I422 => dcp::PixelFormat::I422, - PixelLayout::I444 => dcp::PixelFormat::I444, - }; - let src_format = dcp::ImageFormat { - pixel_format, - color_space: dcp::ColorSpace::Bt601, - num_planes: 3, - }; - let dst_format = dcp::ImageFormat { - pixel_format: dcp::PixelFormat::Rgba, - color_space: dcp::ColorSpace::Rgb, - num_planes: 1, + let bit_depth = self.picture.bit_depth(); + + // Normally this should never happen, + // if this happens then there is an incorrect implementation somewhere else + assert!(bit_depth == 8 || bit_depth == 10 || bit_depth == 12); + + let (width, height) = self.dimensions(); + // This is suspicious if this happens, better fail early + if width == 0 || height == 0 { + return Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::DimensionError, + ))); + } + + let yuv_range = match self.picture.color_range() { + dav1d::pixel::YUVRange::Limited => YuvIntensityRange::Tv, + dav1d::pixel::YUVRange::Full => YuvIntensityRange::Pc, + }; + + let matrix_strategy = get_matrix(self.picture.matrix_coefficients())?; + + // Identity matrix should be possible only on 4:4:4 + if matrix_strategy == YuvMatrixStrategy::Identity + && self.picture.pixel_layout() != PixelLayout::I444 + { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + AvifDecoderError::YuvLayoutOnIdentityMatrix(self.picture.pixel_layout()), + ))); + } + + if matrix_strategy == YuvMatrixStrategy::CgCo + && self.picture.pixel_layout() == PixelLayout::I400 + { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + AvifDecoderError::UnsupportedLayoutAndMatrix( + self.picture.pixel_layout(), + matrix_strategy, + ), + ))); + } + + if bit_depth == 8 { + let ref_y = self.picture.plane(PlanarImageComponent::Y); + let ref_u = self.picture.plane(PlanarImageComponent::U); + let ref_v = self.picture.plane(PlanarImageComponent::V); + + let image = YuvPlanarImage { + y_plane: ref_y.as_ref(), + y_stride: self.picture.stride(PlanarImageComponent::Y) as usize, + u_plane: ref_u.as_ref(), + u_stride: self.picture.stride(PlanarImageComponent::U) as usize, + v_plane: ref_v.as_ref(), + v_stride: self.picture.stride(PlanarImageComponent::V) as usize, + width: width as usize, + height: height as usize, }; - let (width, height) = self.dimensions(); - let planes = &[ - self.picture.plane(PlanarImageComponent::Y), - self.picture.plane(PlanarImageComponent::U), - self.picture.plane(PlanarImageComponent::V), - ]; - let src_buffers = planes.iter().map(AsRef::as_ref).collect::>(); - let strides = &[ - self.picture.stride(PlanarImageComponent::Y) as usize, + + match matrix_strategy { + YuvMatrixStrategy::KrKb(standard) => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => yuv400_to_rgba8, + PixelLayout::I420 => yuv420_to_rgba8, + PixelLayout::I422 => yuv422_to_rgba8, + PixelLayout::I444 => yuv444_to_rgba8, + }; + + worker(image, buf, yuv_range, standard)?; + } + YuvMatrixStrategy::CgCo => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 => ycgco420_to_rgba8, + PixelLayout::I422 => ycgco422_to_rgba8, + PixelLayout::I444 => ycgco444_to_rgba8, + }; + + worker(image, buf, yuv_range)?; + } + YuvMatrixStrategy::Identity => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 => unreachable!(), + PixelLayout::I422 => unreachable!(), + PixelLayout::I444 => gbr_to_rgba8, + }; + + worker(image, buf, yuv_range)?; + } + } + + // Squashing alpha plane into a picture + if let Some(picture) = self.alpha_picture { + if picture.pixel_layout() != PixelLayout::I400 { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + AvifDecoderError::AlphaPlaneFormat(picture.pixel_layout()), + ))); + } + + let stride = picture.stride(PlanarImageComponent::Y) as usize; + let plane = picture.plane(PlanarImageComponent::Y); + + for (buf, slice) in Iterator::zip( + buf.chunks_exact_mut(width as usize * 4), + plane.as_ref().chunks_exact(stride), + ) { + for (rgba, a_src) in buf.chunks_exact_mut(4).zip(slice) { + rgba[3] = *a_src; + } + } + } + } else { + // // 8+ bit-depth case + if let Ok(buf) = bytemuck::try_cast_slice_mut(buf) { + let target_slice: &mut [u16] = buf; + self.process_16bit_picture(target_slice, yuv_range, matrix_strategy)?; + } else { + // If buffer from Decoder is unaligned + let mut aligned_store = vec![0u16; buf.len() / 2]; + self.process_16bit_picture(&mut aligned_store, yuv_range, matrix_strategy)?; + for (dst, src) in buf.chunks_exact_mut(2).zip(aligned_store.iter()) { + let bytes = src.to_ne_bytes(); + dst[0] = bytes[0]; + dst[1] = bytes[1]; + } + } + } + + Ok(()) + } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } +} + +impl AvifDecoder { + fn process_16bit_picture( + &self, + target: &mut [u16], + yuv_range: YuvIntensityRange, + matrix_strategy: YuvMatrixStrategy, + ) -> ImageResult<()> { + let y_dav1d_plane = self.picture.plane(PlanarImageComponent::Y); + + let (width, height) = (self.picture.width(), self.picture.height()); + let bit_depth = self.picture.bit_depth(); + + // dav1d may return not aligned and not correctly constrained data, + // or at least I can't find guarantees on that + // so if it is happened, instead casting we'll need to reshape it into a target slice + // required criteria: bytemuck allows this align of this data, and stride must be dividable by 2 + + let y_plane_view = transmute_y_plane16( + &y_dav1d_plane, + self.picture.stride(PlanarImageComponent::Y) as usize, + width as usize, + height as usize, + ); + + let u_dav1d_plane = self.picture.plane(PlanarImageComponent::U); + let v_dav1d_plane = self.picture.plane(PlanarImageComponent::V); + let mut u_plane_view = Plane16View::default(); + let mut v_plane_view = Plane16View::default(); + + if self.picture.pixel_layout() != PixelLayout::I400 { + u_plane_view = transmute_chroma_plane16( + &u_dav1d_plane, + self.picture.pixel_layout(), self.picture.stride(PlanarImageComponent::U) as usize, + width as usize, + height as usize, + ); + v_plane_view = transmute_chroma_plane16( + &v_dav1d_plane, + self.picture.pixel_layout(), self.picture.stride(PlanarImageComponent::V) as usize, - ]; - let dst_buffers = &mut [&mut buf[..]]; - dcp::convert_image( - width, - height, - &src_format, - Some(strides), - &src_buffers, - &dst_format, - None, - dst_buffers, - ) - .map_err(error_map)?; - } else { - let plane = self.picture.plane(PlanarImageComponent::Y); - buf.copy_from_slice(plane.as_ref()); + width as usize, + height as usize, + ); + } + + let image = YuvPlanarImage { + y_plane: y_plane_view.data.as_ref(), + y_stride: y_plane_view.stride, + u_plane: u_plane_view.data.as_ref(), + u_stride: u_plane_view.stride, + v_plane: v_plane_view.data.as_ref(), + v_stride: v_plane_view.stride, + width: width as usize, + height: height as usize, + }; + + match matrix_strategy { + YuvMatrixStrategy::KrKb(standard) => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => { + if bit_depth == 10 { + yuv400_to_rgba10 + } else { + yuv400_to_rgba12 + } + } + PixelLayout::I420 => { + if bit_depth == 10 { + yuv420_to_rgba10 + } else { + yuv420_to_rgba12 + } + } + PixelLayout::I422 => { + if bit_depth == 10 { + yuv422_to_rgba10 + } else { + yuv422_to_rgba12 + } + } + PixelLayout::I444 => { + if bit_depth == 10 { + yuv444_to_rgba10 + } else { + yuv444_to_rgba12 + } + } + }; + worker(image, target, yuv_range, standard)?; + } + YuvMatrixStrategy::CgCo => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 => { + if bit_depth == 10 { + ycgco420_to_rgba10 + } else { + ycgco420_to_rgba12 + } + } + PixelLayout::I422 => { + if bit_depth == 10 { + ycgco422_to_rgba10 + } else { + ycgco422_to_rgba12 + } + } + PixelLayout::I444 => { + if bit_depth == 10 { + ycgco444_to_rgba10 + } else { + ycgco444_to_rgba12 + } + } + }; + worker(image, target, yuv_range)?; + } + YuvMatrixStrategy::Identity => { + let worker = match self.picture.pixel_layout() { + PixelLayout::I400 => unreachable!(), + PixelLayout::I420 => unreachable!(), + PixelLayout::I422 => unreachable!(), + PixelLayout::I444 => { + if bit_depth == 10 { + gbr_to_rgba10 + } else { + gbr_to_rgba12 + } + } + }; + worker(image, target, yuv_range)?; + } } - if let Some(picture) = self.alpha_picture { + // Squashing alpha plane into a picture + if let Some(picture) = &self.alpha_picture { if picture.pixel_layout() != PixelLayout::I400 { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Avif.into(), - UnsupportedErrorKind::GenericFeature(format!( - "Alpha must be PixelLayout::I400 but was: {:?}", - picture.pixel_layout() // PixelLayout does not implement display - )), - ), - )); + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + AvifDecoderError::AlphaPlaneFormat(picture.pixel_layout()), + ))); } - let stride = picture.stride(PlanarImageComponent::Y) as usize; - let plane = picture.plane(PlanarImageComponent::Y); - let width = picture.width(); + + let a_dav1d_plane = picture.plane(PlanarImageComponent::Y); + let a_plane_view = transmute_y_plane16( + &a_dav1d_plane, + picture.stride(PlanarImageComponent::Y) as usize, + width as usize, + height as usize, + ); + for (buf, slice) in Iterator::zip( - buf.chunks_exact_mut(width as usize * 4), - plane.as_ref().chunks_exact(stride), + target.chunks_exact_mut(width as usize * 4), + a_plane_view.data.as_ref().chunks_exact(a_plane_view.stride), ) { - for i in 0..width as usize { - buf[3 + i * 4] = slice[i]; + for (rgba, a_src) in buf.chunks_exact_mut(4).zip(slice) { + rgba[3] = *a_src; } } } + // Expand current bit depth to target 16 + let target_expand_bits = 16u32 - self.picture.bit_depth() as u32; + for item in target.iter_mut() { + *item = (*item).rotate_left(target_expand_bits); + } + Ok(()) } } @@ -212,7 +663,7 @@ loop { match decoder.get_picture() { Err(dav1d::Error::Again) => match decoder.send_pending_data() { - Ok(_) => {} + Ok(()) => {} Err(dav1d::Error::Again) => {} Err(e) => return Err(error_map(e)), }, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,18 +6,19 @@ use std::borrow::Cow; use std::cmp::min; use std::io::Write; +use std::mem::size_of; use crate::buffer::ConvertBuffer; use crate::color::{FromColor, Luma, LumaA, Rgb, Rgba}; use crate::error::{ EncodingError, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, }; -use crate::{ColorType, ImageBuffer, ImageEncoder, ImageFormat, Pixel}; +use crate::{ExtendedColorType, ImageBuffer, ImageEncoder, ImageFormat, Pixel}; use crate::{ImageError, ImageResult}; use bytemuck::{try_cast_slice, try_cast_slice_mut, Pod, PodCastError}; use num_traits::Zero; -use ravif::{Encoder, Img, RGB8, RGBA8}; +use ravif::{BitDepth, Encoder, Img, RGB8, RGBA8}; use rgb::AsPixels; /// AVIF Encoder. @@ -39,10 +40,10 @@ } impl ColorSpace { - fn to_ravif(self) -> ravif::ColorSpace { + fn to_ravif(self) -> ravif::ColorModel { match self { - Self::Srgb => ravif::ColorSpace::RGB, - Self::Bt709 => ravif::ColorSpace::YCbCr, + Self::Srgb => ravif::ColorModel::RGB, + Self::Bt709 => ravif::ColorModel::YCbCr, } } } @@ -71,7 +72,7 @@ .with_quality(f32::from(quality)) .with_alpha_quality(f32::from(quality)) .with_speed(speed) - .with_depth(Some(8)); + .with_bit_depth(BitDepth::Eight); AvifEncoder { inner: w, encoder } } @@ -80,7 +81,7 @@ pub fn with_colorspace(mut self, color_space: ColorSpace) -> Self { self.encoder = self .encoder - .with_internal_color_space(color_space.to_ravif()); + .with_internal_color_model(color_space.to_ravif()); self } @@ -104,10 +105,9 @@ data: &[u8], width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color.bytes_per_pixel() as u64); + let expected_buffer_len = color.buffer_size(width, height); assert_eq!( expected_buffer_len, data.len() as u64, @@ -134,7 +134,7 @@ impl AvifEncoder { // Does not currently do anything. Mirrors behaviour of old config function. - fn set_color(&mut self, _color: ColorType) { + fn set_color(&mut self, _color: ExtendedColorType) { // self.config.color_space = ColorSpace::RGB; } @@ -143,7 +143,7 @@ data: &'buf [u8], width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, ) -> ImageResult> { // Error wrapping utility for color dependent buffer dimensions. fn try_from_raw( @@ -176,7 +176,7 @@ // Cast the input slice using few buffer allocations if possible. // In particular try not to allocate if the caller did the infallible reverse. - fn cast_buffer(buf: &[u8]) -> ImageResult> + fn cast_buffer(buf: &[u8]) -> ImageResult> where Channel: Pod + Zero, { @@ -188,12 +188,12 @@ Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) => { // Sad, but let's allocate. // bytemuck checks alignment _before_ slop but size mismatch before this.. - if buf.len() % std::mem::size_of::() != 0 { + if buf.len() % size_of::() != 0 { Err(ImageError::Parameter(ParameterError::from_kind( ParameterErrorKind::DimensionMismatch, ))) } else { - let len = buf.len() / std::mem::size_of::(); + let len = buf.len() / size_of::(); let mut data = vec![Channel::zero(); len]; let view = try_cast_slice_mut::<_, u8>(data.as_mut_slice()).unwrap(); view.copy_from_slice(buf); @@ -203,14 +203,14 @@ Err(err) => { // Are you trying to encode a ZST?? Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::Generic(format!("{:?}", err)), + ParameterErrorKind::Generic(format!("{err:?}")), ))) } } } match color { - ColorType::Rgb8 => { + ExtendedColorType::Rgb8 => { // ravif doesn't do any checks but has some asserts, so we do the checks. let img = try_from_raw::>(data, width, height)?; // Now, internally ravif uses u32 but it takes usize. We could do some checked @@ -222,12 +222,12 @@ } Ok(RgbColor::Rgb8(Img::new( - rgb::AsPixels::as_pixels(data), + AsPixels::as_pixels(data), width as usize, height as usize, ))) } - ColorType::Rgba8 => { + ExtendedColorType::Rgba8 => { // ravif doesn't do any checks but has some asserts, so we do the checks. let img = try_from_raw::>(data, width, height)?; // Now, internally ravif uses u32 but it takes usize. We could do some checked @@ -239,37 +239,37 @@ } Ok(RgbColor::Rgba8(Img::new( - rgb::AsPixels::as_pixels(data), + AsPixels::as_pixels(data), width as usize, height as usize, ))) } // we need a separate buffer.. - ColorType::L8 => { + ExtendedColorType::L8 => { let image = try_from_raw::>(data, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) } - ColorType::La8 => { + ExtendedColorType::La8 => { let image = try_from_raw::>(data, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) } // we need to really convert data.. - ColorType::L16 => { + ExtendedColorType::L16 => { let buffer = cast_buffer(data)?; let image = try_from_raw::>(&buffer, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) } - ColorType::La16 => { + ExtendedColorType::La16 => { let buffer = cast_buffer(data)?; let image = try_from_raw::>(&buffer, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) } - ColorType::Rgb16 => { + ExtendedColorType::Rgb16 => { let buffer = cast_buffer(data)?; let image = try_from_raw::>(&buffer, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) } - ColorType::Rgba16 => { + ExtendedColorType::Rgba16 => { let buffer = cast_buffer(data)?; let image = try_from_raw::>(&buffer, width, height)?; Ok(RgbColor::Rgba8(convert_into(fallback, image))) @@ -278,7 +278,7 @@ _ => Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Avif.into(), - UnsupportedErrorKind::Color(color.into()), + UnsupportedErrorKind::Color(color), ), )), } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,12 +3,16 @@ /// The [AVIF] specification defines an image derivative of the AV1 bitstream, an open video codec. /// /// [AVIF]: https://aomediacodec.github.io/av1-avif/ -#[cfg(feature = "avif-decoder")] +#[cfg(feature = "avif-native")] pub use self::decoder::AvifDecoder; -#[cfg(feature = "avif-encoder")] +#[cfg(feature = "avif")] pub use self::encoder::{AvifEncoder, ColorSpace}; -#[cfg(feature = "avif-decoder")] +#[cfg(feature = "avif-native")] mod decoder; -#[cfg(feature = "avif-encoder")] +#[cfg(feature = "avif")] mod encoder; +#[cfg(feature = "avif-native")] +mod ycgco; +#[cfg(feature = "avif-native")] +mod yuv; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/ycgco.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/ycgco.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/ycgco.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/ycgco.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,419 @@ +use crate::codecs::avif::yuv::{ + check_rgb_preconditions, check_yuv_plane_preconditions, qrshr, yuv420_to_rgbx_invoker, + yuv422_to_rgbx_invoker, CbCrInverseTransform, HalvedRowHandler, PlaneDefinition, + YuvChromaRange, YuvIntensityRange, YuvPlanarImage, YuvStandardMatrix, +}; +use crate::ImageError; +use num_traits::AsPrimitive; + +/// Computes YCgCo inverse in limited range +/// # Arguments +/// - `dst` - dest buffer +/// - `y_value` - Y value with subtracted bias +/// - `cb` - Cb value with subtracted bias +/// - `cr` - Cr value with subtracted bias +#[inline(always)] +fn ycgco_execute_limited< + V: Copy + AsPrimitive + 'static + Sized, + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + dst: &mut [V; CHANNELS], + y_value: i32, + cg: i32, + co: i32, + scale: i32, +) where + i32: AsPrimitive, +{ + let t0 = y_value - cg; + + let r = qrshr::((t0 + co) * scale); + let b = qrshr::((t0 - co) * scale); + let g = qrshr::((y_value + cg) * scale); + + if CHANNELS == 4 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + dst[3] = ((1i32 << BIT_DEPTH) - 1).as_(); + } else if CHANNELS == 3 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + } else { + unreachable!(); + } +} + +/// Computes YCgCo inverse in full range +/// # Arguments +/// - `dst` - dest buffer +/// - `y_value` - Y value with subtracted bias +/// - `cb` - Cb value with subtracted bias +/// - `cr` - Cr value with subtracted bias +#[inline(always)] +fn ycgco_execute_full< + V: Copy + AsPrimitive + 'static + Sized, + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + dst: &mut [V; CHANNELS], + y_value: i32, + cg: i32, + co: i32, +) where + i32: AsPrimitive, +{ + let t0 = y_value - cg; + + let max_value = (1i32 << BIT_DEPTH) - 1; + + let r = (t0 + co).clamp(0, max_value); + let b = (t0 - co).clamp(0, max_value); + let g = (y_value + cg).clamp(0, max_value); + + if CHANNELS == 4 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + dst[3] = max_value.as_(); + } else if CHANNELS == 3 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + } else { + unreachable!(); + } +} + +#[inline(always)] +fn process_halved_chroma_row_cgco< + V: Copy + AsPrimitive + 'static + Sized, + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + _: &CbCrInverseTransform, + range: &YuvChromaRange, +) where + i32: AsPrimitive, +{ + let max_value = (1i32 << BIT_DEPTH) - 1; + + // If the stride is larger than the plane size, + // it might contain junk data beyond the actual valid region. + // To avoid processing artifacts when working with odd-sized images, + // the buffer is reshaped to its actual size, + // preventing accidental use of invalid values from the trailing region. + + let y_plane = &image.y_plane[..image.width]; + let chroma_size = image.width.div_ceil(2); + let u_plane = &image.u_plane[..chroma_size]; + let v_plane = &image.v_plane[..chroma_size]; + let rgba = &mut rgba[..image.width * CHANNELS]; + + let bias_y = range.bias_y as i32; + let bias_uv = range.bias_uv as i32; + let y_iter = y_plane.chunks_exact(2); + let rgb_chunks = rgba.chunks_exact_mut(CHANNELS * 2); + + let scale_coef = ((max_value as f32 / range.range_y as f32) * (1 << PRECISION) as f32) as i32; + + for (((y_src, &u_src), &v_src), rgb_dst) in y_iter.zip(u_plane).zip(v_plane).zip(rgb_chunks) { + let y_value0: i32 = y_src[0].as_() - bias_y; + let cg_value: i32 = u_src.as_() - bias_uv; + let co_value: i32 = v_src.as_() - bias_uv; + + let dst0 = &mut rgb_dst[..CHANNELS]; + + ycgco_execute_limited::( + dst0.try_into().unwrap(), + y_value0, + cg_value, + co_value, + scale_coef, + ); + + let y_value1 = y_src[1].as_() - bias_y; + + let dst1 = &mut rgb_dst[CHANNELS..2 * CHANNELS]; + + ycgco_execute_limited::( + dst1.try_into().unwrap(), + y_value1, + cg_value, + co_value, + scale_coef, + ); + } + + // Process remainder if width is odd. + if image.width & 1 != 0 { + let y_left = y_plane.chunks_exact(2).remainder(); + let rgb_chunks = rgba + .chunks_exact_mut(CHANNELS * 2) + .into_remainder() + .chunks_exact_mut(CHANNELS); + let u_iter = u_plane.iter().rev(); + let v_iter = v_plane.iter().rev(); + + for (((y_src, u_src), v_src), rgb_dst) in + y_left.iter().zip(u_iter).zip(v_iter).zip(rgb_chunks) + { + let y_value = y_src.as_() - bias_y; + let cg_value = u_src.as_() - bias_uv; + let co_value = v_src.as_() - bias_uv; + + ycgco_execute_limited::( + rgb_dst.try_into().unwrap(), + y_value, + cg_value, + co_value, + scale_coef, + ); + } + } +} + +/// Converts YCgCo 444 planar format to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// +fn ycgco444_to_rgbx_impl< + V: Copy + AsPrimitive + 'static + Sized, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + yuv_range: YuvIntensityRange, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "YUV 4:4:4 -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + + let y_plane = image.y_plane; + let u_plane = image.u_plane; + let v_plane = image.v_plane; + let y_stride = image.y_stride; + let u_stride = image.u_stride; + let v_stride = image.v_stride; + let height = image.height; + let width = image.width; + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, height)?; + check_yuv_plane_preconditions(u_plane, PlaneDefinition::U, u_stride, height)?; + check_yuv_plane_preconditions(v_plane, PlaneDefinition::V, v_stride, height)?; + + check_rgb_preconditions(rgba, image.width * CHANNELS, height)?; + + let range = yuv_range.get_yuv_range(BIT_DEPTH as u32); + const PRECISION: i32 = 13; + + let bias_y = range.bias_y as i32; + let bias_uv = range.bias_uv as i32; + + let rgb_stride = width * CHANNELS; + + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgba.chunks_exact_mut(rgb_stride); + let u_iter = u_plane.chunks_exact(u_stride); + let v_iter = v_plane.chunks_exact(v_stride); + + let max_value: i32 = (1 << BIT_DEPTH) - 1; + + // All branches on generic const will be optimized out. + for (((y_src, u_src), v_src), rgb) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + match yuv_range { + YuvIntensityRange::Tv => { + let y_coef = + ((max_value as f32 / range.range_y as f32) * (1 << PRECISION) as f32) as i32; + for (((y_src, u_src), v_src), rgb_dst) in + y_src.iter().zip(u_src).zip(v_src).zip(rgb_chunks) + { + let y_value = y_src.as_() - bias_y; + let cg_value = u_src.as_() - bias_uv; + let co_value = v_src.as_() - bias_uv; + + ycgco_execute_limited::( + rgb_dst.try_into().unwrap(), + y_value, + cg_value, + co_value, + y_coef, + ); + } + } + YuvIntensityRange::Pc => { + for (((y_src, u_src), v_src), rgb_dst) in + y_src.iter().zip(u_src).zip(v_src).zip(rgb_chunks) + { + let y_value = y_src.as_() - bias_y; + let cg_value = u_src.as_() - bias_uv; + let co_value = v_src.as_() - bias_uv; + + ycgco_execute_full::( + rgb_dst.try_into().unwrap(), + y_value, + cg_value, + co_value, + ); + } + } + } + } + + Ok(()) +} + +macro_rules! define_ycgco_half_chroma { + ($name: ident, $invoker: ident, $storage: ident, $cn: expr, $bp: expr, $description: expr) => { + #[doc = concat!($description, " + + # Arguments + + * `image`: see [YuvPlanarImage] + * `rgb`: RGB image layout + * `range`: see [YuvIntensityRange] + * `matrix`: see [YuvStandardMatrix]")] + pub(crate) fn $name( + image: YuvPlanarImage<$storage>, + rgb: &mut [$storage], + range: YuvIntensityRange, + ) -> Result<(), ImageError> { + const P: i32 = 13; + $invoker::<$storage, HalvedRowHandler<$storage>, P, $cn, $bp>( + image, + rgb, + range, + YuvStandardMatrix::Bt709, + process_halved_chroma_row_cgco::<$storage, P, $cn, $bp>, + ) + } + }; +} + +const RGBA_CN: usize = 4; + +define_ycgco_half_chroma!( + ycgco420_to_rgba8, + yuv420_to_rgbx_invoker, + u8, + RGBA_CN, + 8, + "Converts YCgCo 420 8-bit planar format to Rgba 8-bit" +); + +define_ycgco_half_chroma!( + ycgco422_to_rgba8, + yuv422_to_rgbx_invoker, + u8, + RGBA_CN, + 8, + "Converts YCgCo 420 8-bit planar format to Rgba 8-bit" +); + +define_ycgco_half_chroma!( + ycgco420_to_rgba10, + yuv420_to_rgbx_invoker, + u16, + RGBA_CN, + 10, + "Converts YCgCo 420 10-bit planar format to Rgba 10-bit" +); + +define_ycgco_half_chroma!( + ycgco422_to_rgba10, + yuv422_to_rgbx_invoker, + u16, + RGBA_CN, + 10, + "Converts YCgCo 422 10-bit planar format to Rgba 10-bit" +); + +define_ycgco_half_chroma!( + ycgco420_to_rgba12, + yuv420_to_rgbx_invoker, + u16, + RGBA_CN, + 12, + "Converts YCgCo 420 12-bit planar format to Rgba 12-bit" +); + +define_ycgco_half_chroma!( + ycgco422_to_rgba12, + yuv422_to_rgbx_invoker, + u16, + RGBA_CN, + 12, + "Converts YCgCo 422 12-bit planar format to Rgba 12-bit" +); + +macro_rules! define_ycgcg_full_chroma { + ($name: ident, $storage: ident, $cn: expr, $bp: expr, $description: expr) => { + #[doc = concat!($description, " + + # Arguments + + * `image`: see [YuvPlanarImage] + * `rgba`: RGB image layout + * `range`: see [YuvIntensityRange] + * `matrix`: see [YuvStandardMatrix] + ")] + pub(crate) fn $name( + image: YuvPlanarImage<$storage>, + rgba: &mut [$storage], + range: YuvIntensityRange, + ) -> Result<(), ImageError> { + ycgco444_to_rgbx_impl::<$storage, $cn, $bp>(image, rgba, range) + } + }; +} + +define_ycgcg_full_chroma!( + ycgco444_to_rgba8, + u8, + RGBA_CN, + 8, + "Converts YCgCo 444 planar format 8 bit-depth to Rgba 8 bit" +); +define_ycgcg_full_chroma!( + ycgco444_to_rgba10, + u16, + RGBA_CN, + 10, + "Converts YCgCo 444 planar format 10 bit-depth to Rgba 10 bit" +); +define_ycgcg_full_chroma!( + ycgco444_to_rgba12, + u16, + RGBA_CN, + 12, + "Converts YCgCo 444 planar format 12 bit-depth to Rgba 12 bit" +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/yuv.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/yuv.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/avif/yuv.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/avif/yuv.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1279 @@ +use crate::error::DecodingError; +use crate::{ImageError, ImageFormat}; +use num_traits::AsPrimitive; +use std::fmt::{Display, Formatter}; +use std::mem::size_of; + +#[derive(Debug, Copy, Clone)] +/// Representation of inversion matrix +pub(crate) struct CbCrInverseTransform { + y_coef: T, + cr_coef: T, + cb_coef: T, + g_coeff_1: T, + g_coeff_2: T, +} + +impl CbCrInverseTransform { + fn to_integers(self, precision: u32) -> CbCrInverseTransform { + let precision_scale: i32 = 1i32 << (precision as i32); + let cr_coef = (self.cr_coef * precision_scale as f32) as i32; + let cb_coef = (self.cb_coef * precision_scale as f32) as i32; + let y_coef = (self.y_coef * precision_scale as f32) as i32; + let g_coef_1 = (self.g_coeff_1 * precision_scale as f32) as i32; + let g_coef_2 = (self.g_coeff_2 * precision_scale as f32) as i32; + CbCrInverseTransform:: { + y_coef, + cr_coef, + cb_coef, + g_coeff_1: g_coef_1, + g_coeff_2: g_coef_2, + } + } +} + +#[derive(Copy, Clone, Debug)] +struct ErrorSize { + expected: usize, + received: usize, +} + +#[derive(Copy, Clone, Debug)] +pub(crate) enum PlaneDefinition { + Y, + U, + V, +} + +impl Display for PlaneDefinition { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + match self { + PlaneDefinition::Y => f.write_str("Luma"), + PlaneDefinition::U => f.write_str("U chroma"), + PlaneDefinition::V => f.write_str("V chroma"), + } + } +} + +#[derive(Debug, Clone, Copy)] +enum YuvConversionError { + YuvPlaneSizeMismatch(PlaneDefinition, ErrorSize), + RgbDestinationSizeMismatch(ErrorSize), +} + +impl Display for YuvConversionError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + YuvConversionError::YuvPlaneSizeMismatch(plane, error_size) => { + f.write_fmt(format_args!( + "For plane {} expected size is {} but was received {}", + plane, error_size.received, error_size.expected, + )) + } + YuvConversionError::RgbDestinationSizeMismatch(error_size) => { + f.write_fmt(format_args!( + "For RGB destination expected size is {} but was received {}", + error_size.received, error_size.expected, + )) + } + } + } +} + +impl std::error::Error for YuvConversionError {} + +#[inline] +pub(crate) fn check_yuv_plane_preconditions( + plane: &[V], + plane_definition: PlaneDefinition, + stride: usize, + height: usize, +) -> Result<(), ImageError> { + if plane.len() != stride * height { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + YuvConversionError::YuvPlaneSizeMismatch( + plane_definition, + ErrorSize { + expected: stride * height, + received: plane.len(), + }, + ), + ))); + } + Ok(()) +} + +#[inline] +pub(crate) fn check_rgb_preconditions( + rgb_data: &[V], + stride: usize, + height: usize, +) -> Result<(), ImageError> { + if rgb_data.len() != stride * height { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Avif.into(), + YuvConversionError::RgbDestinationSizeMismatch(ErrorSize { + expected: stride * height, + received: rgb_data.len(), + }), + ))); + } + Ok(()) +} + +/// Transformation YUV to RGB with coefficients as specified in [ITU-R](https://www.itu.int/rec/T-REC-H.273/en) +fn get_inverse_transform( + range_bgra: u32, + range_y: u32, + range_uv: u32, + kr: f32, + kb: f32, + precision: u32, +) -> CbCrInverseTransform { + let range_uv = range_bgra as f32 / range_uv as f32; + let y_coef = range_bgra as f32 / range_y as f32; + let cr_coeff = (2f32 * (1f32 - kr)) * range_uv; + let cb_coeff = (2f32 * (1f32 - kb)) * range_uv; + let kg = 1.0f32 - kr - kb; + assert_ne!(kg, 0., "1.0f - kr - kg must not be 0"); + let g_coeff_1 = (2f32 * ((1f32 - kr) * kr / kg)) * range_uv; + let g_coeff_2 = (2f32 * ((1f32 - kb) * kb / kg)) * range_uv; + let exact_transform = CbCrInverseTransform { + y_coef, + cr_coef: cr_coeff, + cb_coef: cb_coeff, + g_coeff_1, + g_coeff_2, + }; + exact_transform.to_integers(precision) +} + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +/// Declares YUV range TV (limited) or PC (full), +/// more info [ITU-R](https://www.itu.int/rec/T-REC-H.273/en) +pub(crate) enum YuvIntensityRange { + /// Limited range Y ∈ [16 << (depth - 8), 16 << (depth - 8) + 224 << (depth - 8)], + /// UV ∈ [-1 << (depth - 1), -1 << (depth - 1) + 1 << (depth - 1)] + Tv, + /// Full range Y ∈ [0, 2^bit_depth - 1], + /// UV ∈ [-1 << (depth - 1), -1 << (depth - 1) + 2^bit_depth - 1] + Pc, +} + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +pub(crate) struct YuvChromaRange { + pub(crate) bias_y: u32, + pub(crate) bias_uv: u32, + pub(crate) range_y: u32, + pub(crate) range_uv: u32, + pub(crate) range: YuvIntensityRange, +} + +impl YuvIntensityRange { + pub(crate) const fn get_yuv_range(self, depth: u32) -> YuvChromaRange { + match self { + YuvIntensityRange::Tv => YuvChromaRange { + bias_y: 16 << (depth - 8), + bias_uv: 1 << (depth - 1), + range_y: 219 << (depth - 8), + range_uv: 224 << (depth - 8), + range: self, + }, + YuvIntensityRange::Pc => YuvChromaRange { + bias_y: 0, + bias_uv: 1 << (depth - 1), + range_uv: (1 << depth) - 1, + range_y: (1 << depth) - 1, + range: self, + }, + } + } +} + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq)] +/// Declares standard prebuilt YUV conversion matrices, +/// check [ITU-R](https://www.itu.int/rec/T-REC-H.273/en) information for more info +pub(crate) enum YuvStandardMatrix { + Bt601, + Bt709, + Bt2020, + Smpte240, + Bt470_6, +} + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +struct YuvBias { + kr: f32, + kb: f32, +} + +impl YuvStandardMatrix { + const fn get_kr_kb(self) -> YuvBias { + match self { + YuvStandardMatrix::Bt601 => YuvBias { + kr: 0.299f32, + kb: 0.114f32, + }, + YuvStandardMatrix::Bt709 => YuvBias { + kr: 0.2126f32, + kb: 0.0722f32, + }, + YuvStandardMatrix::Bt2020 => YuvBias { + kr: 0.2627f32, + kb: 0.0593f32, + }, + YuvStandardMatrix::Smpte240 => YuvBias { + kr: 0.087f32, + kb: 0.212f32, + }, + YuvStandardMatrix::Bt470_6 => YuvBias { + kr: 0.2220f32, + kb: 0.0713f32, + }, + } + } +} + +pub(crate) struct YuvPlanarImage<'a, T> { + pub(crate) y_plane: &'a [T], + pub(crate) y_stride: usize, + pub(crate) u_plane: &'a [T], + pub(crate) u_stride: usize, + pub(crate) v_plane: &'a [T], + pub(crate) v_stride: usize, + pub(crate) width: usize, + pub(crate) height: usize, +} + +#[inline(always)] +/// Saturating rounding shift right against bit depth +pub(crate) fn qrshr(val: i32) -> i32 { + let rounding: i32 = 1 << (PRECISION - 1); + let max_value: i32 = (1 << BIT_DEPTH) - 1; + ((val + rounding) >> PRECISION).clamp(0, max_value) +} + +/// Converts Yuv 400 planar format 8 bit to Rgba 8 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvGrayImage] +/// * `rgba`: RGBA image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv400_to_rgba8( + image: YuvPlanarImage, + rgba: &mut [u8], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv400_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 400 planar format 10 bit to Rgba 10 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvGrayImage] +/// * `rgba`: RGBA image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv400_to_rgba10( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv400_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 400 planar format 12 bit to Rgba 12 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvGrayImage] +/// * `rgba`: RGBA image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv400_to_rgba12( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv400_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 400 planar format to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvGrayImage] +/// * `rgba`: RGBA image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +#[inline] +fn yuv400_to_rgbx_impl< + V: Copy + AsPrimitive + 'static + Sized, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "YUV 4:0:0 -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + + let y_plane = image.y_plane; + let y_stride = image.y_stride; + let height = image.height; + let width = image.width; + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, height)?; + check_rgb_preconditions(rgba, width * CHANNELS, height)?; + + let rgba_stride = width * CHANNELS; + + let max_value = (1 << BIT_DEPTH) - 1; + + // If luma plane is in full range it can be just redistributed across the image + if range == YuvIntensityRange::Pc { + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgba.chunks_exact_mut(rgba_stride); + + // All branches on generic const will be optimized out. + for (y_src, rgb) in y_iter.zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + + for (y_src, rgb_dst) in y_src.iter().zip(rgb_chunks) { + let r = *y_src; + rgb_dst[0] = r; + rgb_dst[1] = r; + rgb_dst[2] = r; + if CHANNELS == 4 { + rgb_dst[3] = max_value.as_(); + } + } + } + return Ok(()); + } + + let range = range.get_yuv_range(BIT_DEPTH as u32); + let kr_kb = matrix.get_kr_kb(); + const PRECISION: i32 = 11; + + let inverse_transform = get_inverse_transform( + (1 << BIT_DEPTH) - 1, + range.range_y, + range.range_uv, + kr_kb.kr, + kr_kb.kb, + PRECISION as u32, + ); + let y_coef = inverse_transform.y_coef; + + let bias_y = range.bias_y as i32; + + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgba.chunks_exact_mut(rgba_stride); + + // All branches on generic const will be optimized out. + for (y_src, rgb) in y_iter.zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + + for (y_src, rgb_dst) in y_src.iter().zip(rgb_chunks) { + let y_value = (y_src.as_() - bias_y) * y_coef; + + let r = qrshr::(y_value); + rgb_dst[0] = r.as_(); + rgb_dst[1] = r.as_(); + rgb_dst[2] = r.as_(); + if CHANNELS == 4 { + rgb_dst[3] = max_value.as_(); + } + } + } + + Ok(()) +} + +/// Converts YUV420 8 bit-depth to Rgba 8 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv420_to_rgba8( + image: YuvPlanarImage, + rgb: &mut [u8], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv420_to_rgbx_invoker::, P, 4, 8>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +/// Converts YUV420 10 bit-depth to Rgba 10 bit-depth +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv420_to_rgba10( + image: YuvPlanarImage, + rgb: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv420_to_rgbx_invoker::, P, 4, 10>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +pub(crate) type HalvedRowHandler = + fn(YuvPlanarImage, &mut [V], &CbCrInverseTransform, &YuvChromaRange); + +/// Converts YUV420 12 bit-depth to Rgba 12 bit-depth +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv420_to_rgba12( + image: YuvPlanarImage, + rgb: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv420_to_rgbx_invoker::, P, 4, 12>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +/// Computes YCbCr inverse +/// # Arguments +/// - `dst` - dest buffer +/// - `y_value` - Y value with subtracted bias +/// - `cb` - Cb value with subtracted bias +/// - `cr` - Cr value with subtracted bias +#[inline(always)] +fn ycbcr_execute< + V: Copy + AsPrimitive + 'static + Sized, + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + dst: &mut [V; CHANNELS], + y_value: i32, + cb: i32, + cr: i32, + t: &CbCrInverseTransform, +) where + i32: AsPrimitive, +{ + let y_scaled = y_value * t.y_coef; + let r = qrshr::(y_scaled + t.cr_coef * cr); + let b = qrshr::(y_scaled + t.cb_coef * cb); + let g = qrshr::(y_scaled - t.g_coeff_1 * cr - t.g_coeff_2 * cb); + + if CHANNELS == 4 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + dst[3] = ((1i32 << BIT_DEPTH) - 1).as_(); + } else if CHANNELS == 3 { + dst[0] = r.as_(); + dst[1] = g.as_(); + dst[2] = b.as_(); + } else { + unreachable!(); + } +} + +#[inline] +fn process_halved_chroma_row_cbcr< + V: Copy + AsPrimitive + 'static + Sized, + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + transform: &CbCrInverseTransform, + range: &YuvChromaRange, +) where + i32: AsPrimitive, +{ + // If the stride is larger than the plane size, + // it might contain junk data beyond the actual valid region. + // To avoid processing artifacts when working with odd-sized images, + // the buffer is reshaped to its actual size, + // preventing accidental use of invalid values from the trailing region. + + let y_plane = &image.y_plane[0..image.width]; + let chroma_size = image.width.div_ceil(2); + let u_plane = &image.u_plane[0..chroma_size]; + let v_plane = &image.v_plane[0..chroma_size]; + let rgba = &mut rgba[0..image.width * CHANNELS]; + + let bias_y = range.bias_y as i32; + let bias_uv = range.bias_uv as i32; + let y_iter = y_plane.chunks_exact(2); + let rgb_chunks = rgba.chunks_exact_mut(CHANNELS * 2); + for (((y_src, &u_src), &v_src), rgb_dst) in y_iter.zip(u_plane).zip(v_plane).zip(rgb_chunks) { + let y_value0: i32 = y_src[0].as_() - bias_y; + let cb_value: i32 = u_src.as_() - bias_uv; + let cr_value: i32 = v_src.as_() - bias_uv; + + let dst0 = &mut rgb_dst[..CHANNELS]; + + ycbcr_execute::( + dst0.try_into().unwrap(), + y_value0, + cb_value, + cr_value, + transform, + ); + + let y_value1 = y_src[1].as_() - bias_y; + + let dst1 = &mut rgb_dst[CHANNELS..2 * CHANNELS]; + + ycbcr_execute::( + dst1.try_into().unwrap(), + y_value1, + cb_value, + cr_value, + transform, + ); + } + + // Process remainder if width is odd. + if image.width & 1 != 0 { + let y_left = y_plane.chunks_exact(2).remainder(); + let rgb_chunks = rgba + .chunks_exact_mut(CHANNELS * 2) + .into_remainder() + .chunks_exact_mut(CHANNELS); + let u_iter = u_plane.iter().rev(); + let v_iter = v_plane.iter().rev(); + + for (((y_src, u_src), v_src), rgb_dst) in + y_left.iter().zip(u_iter).zip(v_iter).zip(rgb_chunks) + { + let y_value = y_src.as_() - bias_y; + let cb_value = u_src.as_() - bias_uv; + let cr_value = v_src.as_() - bias_uv; + + ycbcr_execute::( + rgb_dst.try_into().unwrap(), + y_value, + cb_value, + cr_value, + transform, + ); + } + } +} + +/// Converts YUV420 to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv420_to_rgbx_invoker< + V: Copy + AsPrimitive + 'static + Sized, + W: Fn(YuvPlanarImage, &mut [V], &CbCrInverseTransform, &YuvChromaRange), + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgb: &mut [V], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, + worker: W, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "YUV 4:2:0 -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + let y_plane = image.y_plane; + let u_plane = image.u_plane; + let v_plane = image.v_plane; + let y_stride = image.y_stride; + let u_stride = image.u_stride; + let v_stride = image.v_stride; + let chroma_height = image.height.div_ceil(2); + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, image.height)?; + check_yuv_plane_preconditions(u_plane, PlaneDefinition::U, u_stride, chroma_height)?; + check_yuv_plane_preconditions(v_plane, PlaneDefinition::V, v_stride, chroma_height)?; + + check_rgb_preconditions(rgb, image.width * CHANNELS, image.height)?; + + let range = range.get_yuv_range(BIT_DEPTH as u32); + let kr_kb = matrix.get_kr_kb(); + let inverse_transform = get_inverse_transform( + (1 << BIT_DEPTH) - 1, + range.range_y, + range.range_uv, + kr_kb.kr, + kr_kb.kb, + PRECISION as u32, + ); + + let rgb_stride = image.width * CHANNELS; + + let y_iter = y_plane.chunks_exact(y_stride * 2); + let rgb_iter = rgb.chunks_exact_mut(rgb_stride * 2); + let u_iter = u_plane.chunks_exact(u_stride); + let v_iter = v_plane.chunks_exact(v_stride); + + /* + Sample 4x4 YUV420 planar image + start_y + 0: Y00 Y01 Y02 Y03 + start_y + 4: Y04 Y05 Y06 Y07 + start_y + 8: Y08 Y09 Y10 Y11 + start_y + 12: Y12 Y13 Y14 Y15 + start_cb + 0: Cb00 Cb01 + start_cb + 2: Cb02 Cb03 + start_cr + 0: Cr00 Cr01 + start_cr + 2: Cr02 Cr03 + + For 4 luma components (2x2 on rows and cols) there are 1 chroma Cb/Cr components. + Luma channel must have always exact size as RGB target layout, but chroma is not. + + We're sectioning an image by pair of rows, then for each pair of luma and RGB row, + there is one chroma row. + + As chroma is shrunk by factor of 2 then we're processing by pairs of RGB and luma, + for each RGB and luma pair there is one chroma component. + + If image have odd width then luma channel must be exact, and we're replicating last + chroma component. + + If image have odd height then luma channel is exact, and we're replicating last chroma rows. + */ + + // All branches on generic const will be optimized out. + for (((y_src, u_src), v_src), rgb) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + // Since we're processing two rows in one loop we need to re-slice once more + let y_iter = y_src.chunks_exact(y_stride); + let rgb_iter = rgb.chunks_exact_mut(rgb_stride); + for (y_src, rgba) in y_iter.zip(rgb_iter) { + let image = YuvPlanarImage { + y_plane: y_src, + y_stride: 0, + u_plane: u_src, + u_stride: 0, + v_plane: v_src, + v_stride: 0, + width: image.width, + height: image.height, + }; + worker(image, rgba, &inverse_transform, &range); + } + } + + // Process remainder if height is odd + + let y_iter = y_plane + .chunks_exact(y_stride * 2) + .remainder() + .chunks_exact(y_stride); + let rgb_iter = rgb.chunks_exact_mut(rgb_stride).rev(); + let u_iter = u_plane.chunks_exact(u_stride).rev(); + let v_iter = v_plane.chunks_exact(v_stride).rev(); + + for (((y_src, u_src), v_src), rgba) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let image = YuvPlanarImage { + y_plane: y_src, + y_stride: 0, + u_plane: u_src, + u_stride: 0, + v_plane: v_src, + v_stride: 0, + width: image.width, + height: image.height, + }; + worker(image, rgba, &inverse_transform, &range); + } + + Ok(()) +} + +/// Converts Yuv 422 8-bit planar format to Rgba 8-bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv422_to_rgba8( + image: YuvPlanarImage, + rgb: &mut [u8], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv422_to_rgbx_invoker::, P, 4, 8>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +/// Converts Yuv 422 10-bit planar format to Rgba 10-bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv422_to_rgba10( + image: YuvPlanarImage, + rgb: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv422_to_rgbx_invoker::, P, 4, 10>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +/// Converts Yuv 422 12-bit planar format to Rgba 12-bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv422_to_rgba12( + image: YuvPlanarImage, + rgb: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + const P: i32 = 13; + yuv422_to_rgbx_invoker::, P, 4, 12>( + image, + rgb, + range, + matrix, + process_halved_chroma_row_cbcr::, + ) +} + +/// Converts Yuv 422 planar format to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv422_to_rgbx_invoker< + V: Copy + AsPrimitive + 'static + Sized, + W: Fn(YuvPlanarImage, &mut [V], &CbCrInverseTransform, &YuvChromaRange), + const PRECISION: i32, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgb: &mut [V], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, + worker: W, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "YUV 4:2:2 -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!(PRECISION < 16); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + let y_plane = image.y_plane; + let u_plane = image.u_plane; + let v_plane = image.v_plane; + let y_stride = image.y_stride; + let u_stride = image.u_stride; + let v_stride = image.v_stride; + let width = image.width; + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, image.height)?; + check_yuv_plane_preconditions(u_plane, PlaneDefinition::U, u_stride, image.height)?; + check_yuv_plane_preconditions(v_plane, PlaneDefinition::V, v_stride, image.height)?; + + check_rgb_preconditions(rgb, image.width * CHANNELS, image.height)?; + + let range = range.get_yuv_range(BIT_DEPTH as u32); + let kr_kb = matrix.get_kr_kb(); + + let inverse_transform = get_inverse_transform( + (1 << BIT_DEPTH) - 1, + range.range_y, + range.range_uv, + kr_kb.kr, + kr_kb.kb, + PRECISION as u32, + ); + + /* + Sample 4x4 YUV422 planar image + start_y + 0: Y00 Y01 Y02 Y03 + start_y + 4: Y04 Y05 Y06 Y07 + start_y + 8: Y08 Y09 Y10 Y11 + start_y + 12: Y12 Y13 Y14 Y15 + start_cb + 0: Cb00 Cb01 + start_cb + 2: Cb02 Cb03 + start_cb + 4: Cb04 Cb05 + start_cb + 6: Cb06 Cb07 + start_cr + 0: Cr00 Cr01 + start_cr + 2: Cr02 Cr03 + start_cr + 4: Cr04 Cr05 + start_cr + 6: Cr06 Cr07 + + For 2 luma components there are 1 chroma Cb/Cr components. + Luma channel must have always exact size as RGB target layout, but chroma is not. + + As chroma is shrunk by factor of 2 then we're processing by pairs of RGB and luma, + for each RGB and luma pair there is one chroma component. + + If image have odd width then luma channel must be exact, and we're replicating last + chroma component. + */ + + let rgb_stride = width * CHANNELS; + + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgb.chunks_exact_mut(rgb_stride); + let u_iter = u_plane.chunks_exact(u_stride); + let v_iter = v_plane.chunks_exact(v_stride); + + // All branches on generic const will be optimized out. + for (((y_src, u_src), v_src), rgba) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let image = YuvPlanarImage { + y_plane: y_src, + y_stride: 0, + u_plane: u_src, + u_stride: 0, + v_plane: v_src, + v_stride: 0, + width: image.width, + height: image.height, + }; + worker(image, rgba, &inverse_transform, &range); + } + + Ok(()) +} + +/// Converts Yuv 444 planar format 8 bit-depth to Rgba 8 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(crate) fn yuv444_to_rgba8( + image: YuvPlanarImage, + rgba: &mut [u8], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv444_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 444 planar format 10 bit-depth to Rgba 10 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(super) fn yuv444_to_rgba10( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv444_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 444 planar format 12 bit-depth to Rgba 12 bit +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +pub(super) fn yuv444_to_rgba12( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> { + yuv444_to_rgbx_impl::(image, rgba, range, matrix) +} + +/// Converts Yuv 444 planar format to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// * `matrix`: see [YuvStandardMatrix] +/// +#[inline] +fn yuv444_to_rgbx_impl< + V: Copy + AsPrimitive + 'static + Sized, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + range: YuvIntensityRange, + matrix: YuvStandardMatrix, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "YUV 4:4:4 -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + + let y_plane = image.y_plane; + let u_plane = image.u_plane; + let v_plane = image.v_plane; + let y_stride = image.y_stride; + let u_stride = image.u_stride; + let v_stride = image.v_stride; + let height = image.height; + let width = image.width; + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, height)?; + check_yuv_plane_preconditions(u_plane, PlaneDefinition::U, u_stride, height)?; + check_yuv_plane_preconditions(v_plane, PlaneDefinition::V, v_stride, height)?; + + check_rgb_preconditions(rgba, image.width * CHANNELS, height)?; + + let range = range.get_yuv_range(BIT_DEPTH as u32); + let kr_kb = matrix.get_kr_kb(); + const PRECISION: i32 = 13; + + let inverse_transform = get_inverse_transform( + (1 << BIT_DEPTH) - 1, + range.range_y, + range.range_uv, + kr_kb.kr, + kr_kb.kb, + PRECISION as u32, + ); + + let bias_y = range.bias_y as i32; + let bias_uv = range.bias_uv as i32; + + let rgb_stride = width * CHANNELS; + + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgba.chunks_exact_mut(rgb_stride); + let u_iter = u_plane.chunks_exact(u_stride); + let v_iter = v_plane.chunks_exact(v_stride); + + // All branches on generic const will be optimized out. + for (((y_src, u_src), v_src), rgb) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + + for (((y_src, u_src), v_src), rgb_dst) in y_src.iter().zip(u_src).zip(v_src).zip(rgb_chunks) + { + let y_value = y_src.as_() - bias_y; + let cb_value = u_src.as_() - bias_uv; + let cr_value = v_src.as_() - bias_uv; + + ycbcr_execute::( + rgb_dst.try_into().unwrap(), + y_value, + cb_value, + cr_value, + &inverse_transform, + ); + } + } + + Ok(()) +} + +/// Converts Gbr 8 bit planar format to Rgba 8 bit-depth +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// +pub(crate) fn gbr_to_rgba8( + image: YuvPlanarImage, + rgb: &mut [u8], + range: YuvIntensityRange, +) -> Result<(), ImageError> { + gbr_to_rgbx_impl::(image, rgb, range) +} + +/// Converts Gbr 10 bit planar format to Rgba 10 bit-depth +/// +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGBx image layout +/// * `range`: see [YuvIntensityRange] +/// +pub(crate) fn gbr_to_rgba10( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, +) -> Result<(), ImageError> { + gbr_to_rgbx_impl::(image, rgba, range) +} + +/// Converts Gbr 12 bit planar format to Rgba 12 bit-depth +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgba`: RGBx image layout +/// * `range`: see [YuvIntensityRange] +/// +pub(crate) fn gbr_to_rgba12( + image: YuvPlanarImage, + rgba: &mut [u16], + range: YuvIntensityRange, +) -> Result<(), ImageError> { + gbr_to_rgbx_impl::(image, rgba, range) +} + +/// Converts Gbr planar format to Rgba +/// +/// # Arguments +/// +/// * `image`: see [YuvPlanarImage] +/// * `rgb`: RGB image layout +/// * `range`: see [YuvIntensityRange] +/// +#[inline] +fn gbr_to_rgbx_impl< + V: Copy + AsPrimitive + 'static + Sized, + const CHANNELS: usize, + const BIT_DEPTH: usize, +>( + image: YuvPlanarImage, + rgba: &mut [V], + yuv_range: YuvIntensityRange, +) -> Result<(), ImageError> +where + i32: AsPrimitive, +{ + assert!( + CHANNELS == 3 || CHANNELS == 4, + "GBR -> RGB is implemented only on 3 and 4 channels" + ); + assert!( + (8..=16).contains(&BIT_DEPTH), + "Invalid bit depth is provided" + ); + assert!( + if BIT_DEPTH > 8 { + size_of::() == 2 + } else { + size_of::() == 1 + }, + "Unsupported bit depth and data type combination" + ); + let y_plane = image.y_plane; + let u_plane = image.u_plane; + let v_plane = image.v_plane; + let y_stride = image.y_stride; + let u_stride = image.u_stride; + let v_stride = image.v_stride; + let height = image.height; + let width = image.width; + + check_yuv_plane_preconditions(y_plane, PlaneDefinition::Y, y_stride, height)?; + check_yuv_plane_preconditions(u_plane, PlaneDefinition::U, u_stride, height)?; + check_yuv_plane_preconditions(v_plane, PlaneDefinition::V, v_stride, height)?; + + check_rgb_preconditions(rgba, width * CHANNELS, height)?; + + let max_value = (1 << BIT_DEPTH) - 1; + + let rgb_stride = width * CHANNELS; + + let y_iter = y_plane.chunks_exact(y_stride); + let rgb_iter = rgba.chunks_exact_mut(rgb_stride); + let u_iter = u_plane.chunks_exact(u_stride); + let v_iter = v_plane.chunks_exact(v_stride); + + match yuv_range { + YuvIntensityRange::Tv => { + const PRECISION: i32 = 11; + // All channels on identity should use Y range + let range = yuv_range.get_yuv_range(BIT_DEPTH as u32); + let range_rgba = (1 << BIT_DEPTH) - 1; + let y_coef = + ((range_rgba as f32 / range.range_y as f32) * (1 << PRECISION) as f32) as i32; + let y_bias = range.bias_y as i32; + + for (((y_src, u_src), v_src), rgb) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + + for (((&y_src, &u_src), &v_src), rgb_dst) in + y_src.iter().zip(u_src).zip(v_src).zip(rgb_chunks) + { + rgb_dst[0] = + qrshr::((v_src.as_() - y_bias) * y_coef).as_(); + rgb_dst[1] = + qrshr::((y_src.as_() - y_bias) * y_coef).as_(); + rgb_dst[2] = + qrshr::((u_src.as_() - y_bias) * y_coef).as_(); + if CHANNELS == 4 { + rgb_dst[3] = max_value.as_(); + } + } + } + } + YuvIntensityRange::Pc => { + for (((y_src, u_src), v_src), rgb) in y_iter.zip(u_iter).zip(v_iter).zip(rgb_iter) { + let rgb_chunks = rgb.chunks_exact_mut(CHANNELS); + + for (((&y_src, &u_src), &v_src), rgb_dst) in + y_src.iter().zip(u_src).zip(v_src).zip(rgb_chunks) + { + rgb_dst[0] = v_src; + rgb_dst[1] = y_src; + rgb_dst[2] = u_src; + if CHANNELS == 4 { + rgb_dst[3] = max_value.as_(); + } + } + } + } + } + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,17 +1,19 @@ +use crate::utils::vec_try_with_capacity; use std::cmp::{self, Ordering}; -use std::io::{self, Cursor, Read, Seek, SeekFrom}; +use std::io::{self, BufRead, Seek, SeekFrom}; use std::iter::{repeat, Rev}; -use std::marker::PhantomData; -use std::slice::ChunksMut; -use std::{error, fmt, mem}; +use std::slice::ChunksExactMut; +use std::{error, fmt}; -use byteorder::{LittleEndian, ReadBytesExt}; +use byteorder_lite::{LittleEndian, ReadBytesExt}; use crate::color::ColorType; use crate::error::{ DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageFormat, Progress}; +use crate::io::free_functions::load_rect; +use crate::io::ReadExt; +use crate::{ImageDecoder, ImageDecoderRect, ImageFormat}; const BITMAPCOREHEADER_SIZE: u32 = 12; const BITMAPINFOHEADER_SIZE: u32 = 40; @@ -94,8 +96,8 @@ } enum Chunker<'a> { - FromTop(ChunksMut<'a, u8>), - FromBottom(Rev>), + FromTop(ChunksExactMut<'a, u8>), + FromBottom(Rev>), } pub(crate) struct RowIterator<'a> { @@ -167,38 +169,35 @@ DecoderError::BitfieldMaskNonContiguous => f.write_str("Non-contiguous bitfield mask"), DecoderError::BitfieldMaskInvalid => f.write_str("Invalid bitfield mask"), DecoderError::BitfieldMaskMissing(bb) => { - f.write_fmt(format_args!("Missing {}-bit bitfield mask", bb)) + f.write_fmt(format_args!("Missing {bb}-bit bitfield mask")) } DecoderError::BitfieldMasksMissing(bb) => { - f.write_fmt(format_args!("Missing {}-bit bitfield masks", bb)) + f.write_fmt(format_args!("Missing {bb}-bit bitfield masks")) } DecoderError::BmpSignatureInvalid => f.write_str("BMP signature not found"), DecoderError::MoreThanOnePlane => f.write_str("More than one plane"), DecoderError::InvalidChannelWidth(tp, n) => { - f.write_fmt(format_args!("Invalid channel bit count for {}: {}", tp, n)) + f.write_fmt(format_args!("Invalid channel bit count for {tp}: {n}")) } - DecoderError::NegativeWidth(w) => f.write_fmt(format_args!("Negative width ({})", w)), + DecoderError::NegativeWidth(w) => f.write_fmt(format_args!("Negative width ({w})")), DecoderError::ImageTooLarge(w, h) => f.write_fmt(format_args!( - "Image too large (one of ({}, {}) > soft limit of {})", - w, h, MAX_WIDTH_HEIGHT + "Image too large (one of ({w}, {h}) > soft limit of {MAX_WIDTH_HEIGHT})" )), DecoderError::InvalidHeight => f.write_str("Invalid height"), DecoderError::ImageTypeInvalidForTopDown(tp) => f.write_fmt(format_args!( - "Invalid image type {} for top-down image.", - tp + "Invalid image type {tp} for top-down image." )), DecoderError::ImageTypeUnknown(tp) => { - f.write_fmt(format_args!("Unknown image compression type {}", tp)) + f.write_fmt(format_args!("Unknown image compression type {tp}")) } DecoderError::HeaderTooSmall(s) => { - f.write_fmt(format_args!("Bitmap header too small ({} bytes)", s)) + f.write_fmt(format_args!("Bitmap header too small ({s} bytes)")) } DecoderError::PaletteSizeExceeded { colors_used, bit_count, } => f.write_fmt(format_args!( - "Palette size {} exceeds maximum size for BMP with bit count of {}", - colors_used, bit_count + "Palette size {colors_used} exceeds maximum size for BMP with bit count of {bit_count}" )), } } @@ -245,8 +244,7 @@ ImageError::Unsupported(UnsupportedError::from_format_and_kind( ImageFormat::Bmp.into(), UnsupportedErrorKind::GenericFeature(format!( - "Image dimensions ({}x{} w/{} channels) are too large", - width, length, channels + "Image dimensions ({width}x{length} w/{channels} channels) are too large" )), )) }) @@ -297,7 +295,7 @@ } fn set_8bit_pixel_run<'a, T: Iterator>( - pixel_iter: &mut ChunksMut, + pixel_iter: &mut ChunksExactMut, palette: &[[u8; 3]], indices: T, n_pixels: usize, @@ -316,7 +314,7 @@ } fn set_4bit_pixel_run<'a, T: Iterator>( - pixel_iter: &mut ChunksMut, + pixel_iter: &mut ChunksExactMut, palette: &[[u8; 3]], indices: T, mut n_pixels: usize, @@ -346,7 +344,7 @@ #[rustfmt::skip] fn set_2bit_pixel_run<'a, T: Iterator>( - pixel_iter: &mut ChunksMut, + pixel_iter: &mut ChunksExactMut, palette: &[[u8; 3]], indices: T, mut n_pixels: usize, @@ -377,7 +375,7 @@ } fn set_1bit_pixel_run<'a, T: Iterator>( - pixel_iter: &mut ChunksMut, + pixel_iter: &mut ChunksExactMut, palette: &[[u8; 3]], indices: T, ) { @@ -385,7 +383,7 @@ let mut bit = 0x80; loop { if let Some(pixel) = pixel_iter.next() { - let rgb = palette[((idx & bit) != 0) as usize]; + let rgb = palette[usize::from((idx & bit) != 0)]; pixel[0] = rgb[0]; pixel[1] = rgb[1]; pixel[2] = rgb[2]; @@ -436,7 +434,7 @@ 4 => LOOKUP_TABLE_4_BIT_TO_8_BIT[(data & 0b00_1111) as usize], 5 => LOOKUP_TABLE_5_BIT_TO_8_BIT[(data & 0b01_1111) as usize], 6 => LOOKUP_TABLE_6_BIT_TO_8_BIT[(data & 0b11_1111) as usize], - 7 => ((data & 0x7f) << 1 | (data & 0x7f) >> 6) as u8, + 7 => (((data & 0x7f) << 1) | ((data & 0x7f) >> 6)) as u8, 8 => (data & 0xff) as u8, _ => panic!(), } @@ -502,7 +500,7 @@ PixelRun(u8, u8), } -impl BmpDecoder { +impl BmpDecoder { fn new_decoder(reader: R) -> BmpDecoder { BmpDecoder { reader, @@ -534,7 +532,7 @@ } /// Create a new decoder that decodes from the stream ```r``` without first - /// reading a BITMAPFILEHEADER. This is useful for decoding the CF_DIB format + /// reading a BITMAPFILEHEADER. This is useful for decoding the `CF_DIB` format /// directly from the Windows clipboard. pub fn new_without_file_header(reader: R) -> ImageResult> { let mut decoder = Self::new_decoder(reader); @@ -582,7 +580,7 @@ Ok(()) } - /// Read BITMAPCOREHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183372(v=vs.85).aspx + /// Read BITMAPCOREHEADER /// /// returns Err if any of the values are invalid. fn read_bitmap_core_header(&mut self) -> ImageResult<()> { @@ -614,7 +612,7 @@ Ok(()) } - /// Read BITMAPINFOHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183376(v=vs.85).aspx + /// Read BITMAPINFOHEADER /// or BITMAPV{2|3|4|5}HEADER. /// /// returns Err if any of the values are invalid. @@ -631,7 +629,7 @@ return Err(DecoderError::ImageTooLarge(self.width, self.height).into()); } - if self.height == i32::min_value() { + if self.height == i32::MIN { return Err(DecoderError::InvalidHeight.into()); } @@ -803,8 +801,7 @@ UnsupportedError::from_format_and_kind( ImageFormat::Bmp.into(), UnsupportedErrorKind::GenericFeature(format!( - "Unknown bitmap header type (size={})", - bmp_header_size + "Unknown bitmap header type (size={bmp_header_size})" )), ), )) @@ -822,19 +819,36 @@ | BMPHeaderType::V5 => { self.read_bitmap_info_header()?; } - }; + } - match self.image_type { - ImageType::Bitfields16 | ImageType::Bitfields32 => self.read_bitmasks()?, - _ => {} + let mut bitmask_bytes_offset = 0; + if self.image_type == ImageType::Bitfields16 + || self.image_type == ImageType::Bitfields32 + { + self.read_bitmasks()?; + + // Per https://learn.microsoft.com/en-us/windows/win32/gdi/bitmap-header-types, bitmaps + // using the `BITMAPINFOHEADER`, `BITMAPV4HEADER`, or `BITMAPV5HEADER` structures with + // an image type of `BI_BITFIELD` contain RGB bitfield masks immediately after the header. + // + // `read_bitmasks` correctly reads these from earlier in the header itself but we must + // ensure the reader starts on the image data itself, not these extra mask bytes. + if matches!( + self.bmp_header_type, + BMPHeaderType::Info | BMPHeaderType::V4 | BMPHeaderType::V5 + ) { + // This is `size_of::() * 3` (a red, green, and blue mask), but with less noise. + bitmask_bytes_offset = 12; + } }; - self.reader.seek(SeekFrom::Start(bmp_header_end))?; + self.reader + .seek(SeekFrom::Start(bmp_header_end + bitmask_bytes_offset))?; match self.image_type { ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?, _ => {} - }; + } if self.no_file_header { // Use the offset of the end of metadata instead of reading a BMP file header. @@ -890,7 +904,7 @@ let max_length = MAX_PALETTE_SIZE * bytes_per_color; let length = palette_size * bytes_per_color; - let mut buf = Vec::with_capacity(max_length); + let mut buf = vec_try_with_capacity(max_length)?; // Resize and read the palette entries to the buffer. // We limit the buffer to at most 256 colours to avoid any oom issues as @@ -942,11 +956,11 @@ let stride = self.width as usize * self.num_channels(); if self.top_down { RowIterator { - chunks: Chunker::FromTop(pixel_data.chunks_mut(stride)), + chunks: Chunker::FromTop(pixel_data.chunks_exact_mut(stride)), } } else { RowIterator { - chunks: Chunker::FromBottom(pixel_data.chunks_mut(stride).rev()), + chunks: Chunker::FromBottom(pixel_data.chunks_exact_mut(stride).rev()), } } } @@ -978,7 +992,7 @@ if skip_palette { row.clone_from_slice(&indices[0..width]); } else { - let mut pixel_iter = row.chunks_mut(num_channels); + let mut pixel_iter = row.chunks_exact_mut(num_channels); match bit_count { 1 => { set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter()); @@ -993,7 +1007,7 @@ set_8bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width); } _ => panic!(), - }; + } } Ok(()) }, @@ -1150,7 +1164,7 @@ let mut row_iter = self.rows(buf); while let Some(row) = row_iter.next() { - let mut pixel_iter = row.chunks_mut(num_channels); + let mut pixel_iter = row.chunks_exact_mut(num_channels); let mut x = 0; loop { @@ -1171,11 +1185,11 @@ _ => { let mut length = op as usize; if self.image_type == ImageType::RLE4 { - length = (length + 1) / 2; + length = length.div_ceil(2); } length += length & 1; - let mut buffer = vec![0; length]; - self.reader.read_exact(&mut buffer)?; + let mut buffer = Vec::new(); + self.reader.read_exact_vec(&mut buffer, length)?; RLEInsn::Absolute(op, buffer) } } @@ -1218,7 +1232,7 @@ pixel_iter = row_iter .next() .ok_or(DecoderError::CorruptRleData)? - .chunks_mut(num_channels); + .chunks_exact_mut(num_channels); // Zero out the pixels up to the current point in the row. for _ in 0..x { @@ -1265,19 +1279,20 @@ x += length as usize; } RLEInsn::PixelRun(n_pixels, palette_index) => { - // A pixel run isn't allowed to span rows, but we - // simply continue on to the next row if we run - // out of pixels to set. match image_type { ImageType::RLE8 => { - if !set_8bit_pixel_run( - &mut pixel_iter, - p, - repeat(&palette_index), - n_pixels as usize, - ) { - return Err(DecoderError::CorruptRleData.into()); - } + // A pixel run isn't allowed to span rows. + // imagemagick produces invalid images where n_pixels exceeds row length, + // so we clamp n_pixels to the row length to display them properly: + // https://github.com/image-rs/image/issues/2321 + // + // This is like set_8bit_pixel_run() but doesn't fail when `n_pixels` is too large + let repeat_pixel: [u8; 3] = p[palette_index as usize]; + (&mut pixel_iter).take(n_pixels as usize).for_each(|p| { + p[2] = repeat_pixel[2]; + p[1] = repeat_pixel[1]; + p[0] = repeat_pixel[0]; + }); } ImageType::RLE4 => { if !set_4bit_pixel_run( @@ -1329,25 +1344,7 @@ } } -/// Wrapper struct around a `Cursor>` -pub struct BmpReader(Cursor>, PhantomData); -impl Read for BmpReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } - } -} - -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for BmpDecoder { - type Reader = BmpReader; - +impl ImageDecoder for BmpDecoder { fn dimensions(&self) -> (u32, u32) { (self.width as u32, self.height as u32) } @@ -1362,38 +1359,36 @@ } } - fn into_reader(self) -> ImageResult { - Ok(BmpReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); self.read_image_data(buf) } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } -impl<'a, R: 'a + Read + Seek> ImageDecoderRect<'a> for BmpDecoder { - fn read_rect_with_progress( +impl ImageDecoderRect for BmpDecoder { + fn read_rect( &mut self, x: u32, y: u32, width: u32, height: u32, buf: &mut [u8], - progress_callback: F, + row_pitch: usize, ) -> ImageResult<()> { let start = self.reader.stream_position()?; - image::load_rect( + load_rect( x, y, width, height, buf, - progress_callback, + row_pitch, self, + self.total_bytes() as usize, |_, _| Ok(()), |s, buf| s.read_image_data(buf), )?; @@ -1404,6 +1399,8 @@ #[cfg(test)] mod test { + use std::io::{BufReader, Cursor}; + use super::*; #[test] @@ -1412,9 +1409,9 @@ let bitfield = Bitfield { shift: 0, len }; for i in 0..(1 << len) { let read = bitfield.read(i); - let calc = (i as f64 / ((1 << len) - 1) as f64 * 255f64).round() as u8; + let calc = (f64::from(i) / f64::from((1 << len) - 1) * 255f64).round() as u8; if read != calc { - println!("len:{} i:{} read:{} calc:{}", len, i, read, calc); + println!("len:{len} i:{i} read:{read} calc:{calc}"); } assert_eq!(read, calc); } @@ -1423,11 +1420,12 @@ #[test] fn read_rect() { - let f = std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap(); - let mut decoder = super::BmpDecoder::new(f).unwrap(); + let f = + BufReader::new(std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap()); + let mut decoder = BmpDecoder::new(f).unwrap(); let mut buf: Vec = vec![0; 8 * 8 * 3]; - decoder.read_rect(0, 0, 8, 8, &mut buf).unwrap(); + decoder.read_rect(0, 0, 8, 8, &mut buf, 8 * 3).unwrap(); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,11 @@ -use byteorder::{LittleEndian, WriteBytesExt}; +use byteorder_lite::{LittleEndian, WriteBytesExt}; use std::io::{self, Write}; use crate::error::{ EncodingError, ImageError, ImageFormatHint, ImageResult, ParameterError, ParameterErrorKind, + UnsupportedError, UnsupportedErrorKind, }; -use crate::image::ImageEncoder; -use crate::{color, ImageFormat}; +use crate::{DynamicImage, ExtendedColorType, ImageEncoder, ImageFormat}; const BITMAPFILEHEADER_SIZE: u32 = 14; const BITMAPINFOHEADER_SIZE: u32 = 40; @@ -22,7 +22,7 @@ BmpEncoder { writer: w } } - /// Encodes the image `image` that has dimensions `width` and `height` and `ColorType` `c`. + /// Encodes the image `image` that has dimensions `width` and `height` and `ExtendedColorType` `c`. /// /// # Panics /// @@ -33,7 +33,7 @@ image: &[u8], width: u32, height: u32, - c: color::ColorType, + c: ExtendedColorType, ) -> ImageResult<()> { self.encode_with_palette(image, width, height, c, None) } @@ -50,21 +50,21 @@ image: &[u8], width: u32, height: u32, - c: color::ColorType, + color_type: ExtendedColorType, palette: Option<&[[u8; 3]]>, ) -> ImageResult<()> { - if palette.is_some() && c != color::ColorType::L8 && c != color::ColorType::La8 { - return Err(ImageError::IoError(io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "Unsupported color type {:?} when using a non-empty palette. Supported types: Gray(8), GrayA(8).", - c + if palette.is_some() + && color_type != ExtendedColorType::L8 + && color_type != ExtendedColorType::La8 + { + return Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::Generic( + "Palette given which must only be used with L8 or La8 color types".to_string(), ), ))); } - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(c.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, image.len() as u64, @@ -75,18 +75,32 @@ let bmp_header_size = BITMAPFILEHEADER_SIZE; let (dib_header_size, written_pixel_size, palette_color_count) = - get_pixel_info(c, palette)?; - let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes - let image_size = width - .checked_mul(height) - .and_then(|v| v.checked_mul(written_pixel_size)) - .and_then(|v| v.checked_add(height * row_pad_size)) + written_pixel_info(color_type, palette)?; + + let (padded_row, image_size) = width + .checked_mul(written_pixel_size) + // each row must be padded to a multiple of 4 bytes + .and_then(|v| v.checked_next_multiple_of(4)) + .and_then(|v| { + let image_bytes = v.checked_mul(height)?; + Some((v, image_bytes)) + }) .ok_or_else(|| { ImageError::Parameter(ParameterError::from_kind( ParameterErrorKind::DimensionMismatch, )) })?; - let palette_size = palette_color_count * 4; // all palette colors are BGRA + + let row_padding = padded_row - width * written_pixel_size; + + // all palette colors are BGRA + let palette_size = palette_color_count.checked_mul(4).ok_or_else(|| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Bmp), + "calculated palette size larger than 2^32", + )) + })?; + let file_size = bmp_header_size .checked_add(dib_header_size) .and_then(|v| v.checked_add(palette_size)) @@ -98,14 +112,23 @@ )) })?; + let image_data_offset = bmp_header_size + .checked_add(dib_header_size) + .and_then(|v| v.checked_add(palette_size)) + .ok_or_else(|| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Bmp), + "calculated BMP size larger than 2^32", + )) + })?; + // write BMP header self.writer.write_u8(b'B')?; self.writer.write_u8(b'M')?; self.writer.write_u32::(file_size)?; // file size self.writer.write_u16::(0)?; // reserved 1 self.writer.write_u16::(0)?; // reserved 2 - self.writer - .write_u32::(bmp_header_size + dib_header_size + palette_size)?; // image data offset + self.writer.write_u32::(image_data_offset)?; // image data offset // write DIB header self.writer.write_u32::(dib_header_size)?; @@ -131,7 +154,7 @@ self.writer.write_u32::(0xff << 8)?; // green mask self.writer.write_u32::(0xff)?; // blue mask self.writer.write_u32::(0xff << 24)?; // alpha mask - self.writer.write_u32::(0x73524742)?; // colorspace - sRGB + self.writer.write_u32::(0x7352_4742)?; // colorspace - sRGB // endpoints (3x3) and gamma (3) for _ in 0..12 { @@ -140,20 +163,22 @@ } // write image data - match c { - color::ColorType::Rgb8 => self.encode_rgb(image, width, height, row_pad_size, 3)?, - color::ColorType::Rgba8 => self.encode_rgba(image, width, height, row_pad_size, 4)?, - color::ColorType::L8 => { - self.encode_gray(image, width, height, row_pad_size, 1, palette)? + match color_type { + ExtendedColorType::Rgb8 => self.encode_rgb(image, width, height, row_padding, 3)?, + ExtendedColorType::Rgba8 => self.encode_rgba(image, width, height, row_padding, 4)?, + ExtendedColorType::L8 => { + self.encode_gray(image, width, height, row_padding, 1, palette)?; } - color::ColorType::La8 => { - self.encode_gray(image, width, height, row_pad_size, 2, palette)? + ExtendedColorType::La8 => { + self.encode_gray(image, width, height, row_padding, 2, palette)?; } _ => { - return Err(ImageError::IoError(io::Error::new( - io::ErrorKind::InvalidInput, - &get_unsupported_error_message(c)[..], - ))) + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Bmp.into(), + UnsupportedErrorKind::Color(color_type), + ), + )); } } @@ -165,7 +190,7 @@ image: &[u8], width: u32, height: u32, - row_pad_size: u32, + row_padding: u32, bytes_per_pixel: u32, ) -> io::Result<()> { let width = width as usize; @@ -182,7 +207,7 @@ // written as BGR self.writer.write_all(&[b, g, r])?; } - self.write_row_pad(row_pad_size)?; + self.write_row_pad(row_padding)?; } Ok(()) @@ -193,7 +218,7 @@ image: &[u8], width: u32, height: u32, - row_pad_size: u32, + row_padding: u32, bytes_per_pixel: u32, ) -> io::Result<()> { let width = width as usize; @@ -211,7 +236,7 @@ // written as BGRA self.writer.write_all(&[b, g, r, a])?; } - self.write_row_pad(row_pad_size)?; + self.write_row_pad(row_padding)?; } Ok(()) @@ -222,7 +247,7 @@ image: &[u8], width: u32, height: u32, - row_pad_size: u32, + row_padding: u32, bytes_per_pixel: u32, palette: Option<&[[u8; 3]]>, ) -> io::Result<()> { @@ -245,14 +270,21 @@ for row in (0..height).rev() { // from the bottom up let row_start = row * y_stride; - for col in 0..width { - let pixel_start = (row_start + (col * x_stride)) as usize; - // color value is equal to the palette index - self.writer.write_u8(image[pixel_start])?; - // alpha is never written as it's not widely supported + + // color value is equal to the palette index + if x_stride == 1 { + // improve performance by writing the whole row at once + self.writer + .write_all(&image[row_start as usize..][..y_stride as usize])?; + } else { + for col in 0..width { + let pixel_start = (row_start + (col * x_stride)) as usize; + self.writer.write_u8(image[pixel_start])?; + // alpha is never written as it's not widely supported + } } - self.write_row_pad(row_pad_size)?; + self.write_row_pad(row_padding)?; } Ok(()) @@ -267,61 +299,75 @@ } } -impl<'a, W: Write> ImageEncoder for BmpEncoder<'a, W> { +impl ImageEncoder for BmpEncoder<'_, W> { #[track_caller] fn write_image( mut self, buf: &[u8], width: u32, height: u32, - color_type: color::ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { self.encode(buf, width, height, color_type) } -} -fn get_unsupported_error_message(c: color::ColorType) -> String { - format!( - "Unsupported color type {:?}. Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).", - c - ) + fn make_compatible_img( + &self, + _: crate::io::encoder::MethodSealedToImage, + img: &DynamicImage, + ) -> Option { + crate::io::encoder::dynimage_conversion_8bit(img) + } } /// Returns a tuple representing: (dib header size, written pixel size, palette color count). -fn get_pixel_info(c: color::ColorType, palette: Option<&[[u8; 3]]>) -> io::Result<(u32, u32, u32)> { - let sizes = match c { - color::ColorType::Rgb8 => (BITMAPINFOHEADER_SIZE, 3, 0), - color::ColorType::Rgba8 => (BITMAPV4HEADER_SIZE, 4, 0), - color::ColorType::L8 => ( +fn written_pixel_info( + c: ExtendedColorType, + palette: Option<&[[u8; 3]]>, +) -> Result<(u32, u32, u32), ImageError> { + let (header, color_bytes, palette_count) = match c { + ExtendedColorType::Rgb8 => (BITMAPINFOHEADER_SIZE, 3, Some(0)), + ExtendedColorType::Rgba8 => (BITMAPV4HEADER_SIZE, 4, Some(0)), + ExtendedColorType::L8 => ( BITMAPINFOHEADER_SIZE, 1, - palette.map(|p| p.len()).unwrap_or(256) as u32, + u32::try_from(palette.map(|p| p.len()).unwrap_or(256)).ok(), ), - color::ColorType::La8 => ( + ExtendedColorType::La8 => ( BITMAPINFOHEADER_SIZE, 1, - palette.map(|p| p.len()).unwrap_or(256) as u32, + u32::try_from(palette.map(|p| p.len()).unwrap_or(256)).ok(), ), _ => { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - &get_unsupported_error_message(c)[..], - )) + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Bmp.into(), + UnsupportedErrorKind::Color(c), + ), + )); } }; - Ok(sizes) + let palette_count = palette_count.ok_or_else(|| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Bmp), + "calculated palette size larger than 2^32", + )) + })?; + + Ok((header, color_bytes, palette_count)) } #[cfg(test)] mod tests { use super::super::BmpDecoder; use super::BmpEncoder; - use crate::color::ColorType; - use crate::image::ImageDecoder; + + use crate::ExtendedColorType; + use crate::ImageDecoder as _; use std::io::Cursor; - fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec { + fn round_trip_image(image: &[u8], width: u32, height: u32, c: ExtendedColorType) -> Vec { let mut encoded_data = Vec::new(); { let mut encoder = BmpEncoder::new(&mut encoded_data); @@ -340,7 +386,7 @@ #[test] fn round_trip_single_pixel_rgb() { let image = [255u8, 0, 0]; // single red pixel - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 1, 1, ExtendedColorType::Rgb8); assert_eq!(3, decoded.len()); assert_eq!(255, decoded[0]); assert_eq!(0, decoded[1]); @@ -353,27 +399,27 @@ let mut encoded_data = Vec::new(); let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap let mut encoder = BmpEncoder::new(&mut encoded_data); - let result = encoder.encode(&image, 40_000, 40_000, ColorType::Rgb8); + let result = encoder.encode(&image, 40_000, 40_000, ExtendedColorType::Rgb8); assert!(result.is_err()); } #[test] fn round_trip_single_pixel_rgba() { let image = [1, 2, 3, 4]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8); + let decoded = round_trip_image(&image, 1, 1, ExtendedColorType::Rgba8); assert_eq!(&decoded[..], &image[..]); } #[test] fn round_trip_3px_rgb() { let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel - let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8); + let _decoded = round_trip_image(&image, 3, 3, ExtendedColorType::Rgb8); } #[test] fn round_trip_gray() { let image = [0u8, 1, 2]; // 3 pixels - let decoded = round_trip_image(&image, 3, 1, ColorType::L8); + let decoded = round_trip_image(&image, 3, 1, ExtendedColorType::L8); // should be read back as 3 RGB pixels assert_eq!(9, decoded.len()); assert_eq!(0, decoded[0]); @@ -390,7 +436,7 @@ #[test] fn round_trip_graya() { let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel - let decoded = round_trip_image(&image, 1, 3, ColorType::La8); + let decoded = round_trip_image(&image, 1, 3, ExtendedColorType::La8); // should be read back as 3 RGB pixels assert_eq!(9, decoded.len()); assert_eq!(0, decoded[0]); @@ -403,4 +449,13 @@ assert_eq!(2, decoded[7]); assert_eq!(2, decoded[8]); } + + #[test] + fn regression_issue_2604() { + let mut image = vec![]; + let mut encoder = BmpEncoder::new(&mut image); + encoder + .encode(&[], 1 << 31, 0, ExtendedColorType::Rgb8) + .unwrap_err(); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/bmp/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/bmp/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,7 +5,6 @@ //! # Related Links //! * //! * -//! pub use self::decoder::BmpDecoder; pub use self::encoder::BmpEncoder; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/dds.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dds.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/dds.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dds.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,18 +8,19 @@ use std::io::Read; use std::{error, fmt}; -use byteorder::{LittleEndian, ReadBytesExt}; +use byteorder_lite::{LittleEndian, ReadBytesExt}; #[allow(deprecated)] -use crate::codecs::dxt::{DxtDecoder, DxtReader, DxtVariant}; +use crate::codecs::dxt::{DxtDecoder, DxtVariant}; use crate::color::ColorType; use crate::error::{ DecodingError, ImageError, ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{ImageDecoder, ImageFormat}; +use crate::{ImageDecoder, ImageFormat}; /// Errors that can occur during decoding and parsing a DDS image #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[allow(clippy::enum_variant_names)] enum DecoderError { /// Wrong DDS channel width PixelFormatSizeInvalid(u32), @@ -45,25 +46,25 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { DecoderError::PixelFormatSizeInvalid(s) => { - f.write_fmt(format_args!("Invalid DDS PixelFormat size: {}", s)) + f.write_fmt(format_args!("Invalid DDS PixelFormat size: {s}")) } DecoderError::HeaderSizeInvalid(s) => { - f.write_fmt(format_args!("Invalid DDS header size: {}", s)) + f.write_fmt(format_args!("Invalid DDS header size: {s}")) } DecoderError::HeaderFlagsInvalid(fs) => { - f.write_fmt(format_args!("Invalid DDS header flags: {:#010X}", fs)) + f.write_fmt(format_args!("Invalid DDS header flags: {fs:#010X}")) } DecoderError::DxgiFormatInvalid(df) => { - f.write_fmt(format_args!("Invalid DDS DXGI format: {}", df)) + f.write_fmt(format_args!("Invalid DDS DXGI format: {df}")) } DecoderError::ResourceDimensionInvalid(d) => { - f.write_fmt(format_args!("Invalid DDS resource dimension: {}", d)) + f.write_fmt(format_args!("Invalid DDS resource dimension: {d}")) } DecoderError::Dx10FlagsInvalid(fs) => { - f.write_fmt(format_args!("Invalid DDS DX10 header flags: {:#010X}", fs)) + f.write_fmt(format_args!("Invalid DDS DX10 header flags: {fs:#010X}")) } DecoderError::Dx10ArraySizeInvalid(s) => { - f.write_fmt(format_args!("Invalid DDS DX10 array size: {}", s)) + f.write_fmt(format_args!("Invalid DDS DX10 array size: {s}")) } DecoderError::DdsSignatureInvalid => f.write_str("DDS signature not found"), } @@ -145,7 +146,7 @@ } const REQUIRED_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x1000; - const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x800000; + const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x0080_0000; let flags = r.read_u32::()?; if flags & (REQUIRED_FLAGS | !VALID_FLAGS) != REQUIRED_FLAGS { return Err(DecoderError::HeaderFlagsInvalid(flags).into()); @@ -287,10 +288,7 @@ return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Dds.into(), - UnsupportedErrorKind::GenericFeature(format!( - "DDS FourCC {:?}", - fourcc - )), + UnsupportedErrorKind::GenericFeature(format!("DDS FourCC {fourcc:?}")), ), )) } @@ -327,10 +325,7 @@ } } -impl<'a, R: 'a + Read> ImageDecoder<'a> for DdsDecoder { - #[allow(deprecated)] - type Reader = DxtReader; - +impl ImageDecoder for DdsDecoder { fn dimensions(&self) -> (u32, u32) { self.inner.dimensions() } @@ -339,19 +334,13 @@ self.inner.color_type() } - fn scanline_bytes(&self) -> u64 { - #[allow(deprecated)] - self.inner.scanline_bytes() - } - - fn into_reader(self) -> ImageResult { - #[allow(deprecated)] - self.inner.into_reader() - } - fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { self.inner.read_image(buf) } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } #[cfg(test)] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/dxt.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dxt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/dxt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/dxt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,17 +7,18 @@ //! //! Note: this module only implements bare DXT encoding/decoding, it does not parse formats that can contain DXT files like .dds -use std::io::{self, Read, Seek, SeekFrom, Write}; +use std::io::{self, Read}; use crate::color::ColorType; use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; -use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageReadBuffer, Progress}; +use crate::io::ReadExt; +use crate::ImageDecoder; /// What version of DXT compression are we using? /// Note that DXT2 and DXT4 are left away as they're /// just DXT3 and DXT5 with premultiplied alpha #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DxtVariant { +pub(crate) enum DxtVariant { /// The DXT1 format. 48 bytes of RGB data in a 4x4 pixel square is /// compressed into an 8 byte block of DXT1 data DXT1, @@ -48,7 +49,7 @@ } /// Returns the color type that is stored in this DXT variant - pub fn color_type(self) -> ColorType { + pub(crate) fn color_type(self) -> ColorType { match self { DxtVariant::DXT1 => ColorType::Rgb8, DxtVariant::DXT3 | DxtVariant::DXT5 => ColorType::Rgba8, @@ -57,7 +58,7 @@ } /// DXT decoder -pub struct DxtDecoder { +pub(crate) struct DxtDecoder { inner: R, width_blocks: u32, height_blocks: u32, @@ -73,7 +74,7 @@ /// DXT variant in ```variant```. /// width and height are required to be powers of 2 and at least 4. /// otherwise an error will be returned - pub fn new( + pub(crate) fn new( r: R, width: u32, height: u32, @@ -98,6 +99,10 @@ }) } + fn scanline_bytes(&self) -> u64 { + self.variant.decoded_bytes_per_block() as u64 * u64::from(self.width_blocks) + } + fn read_scanline(&mut self, buf: &mut [u8]) -> io::Result { assert_eq!( u64::try_from(buf.len()), @@ -107,9 +112,10 @@ ) ); - let mut src = - vec![0u8; self.variant.encoded_bytes_per_block() * self.width_blocks as usize]; - self.inner.read_exact(&mut src)?; + let len = self.variant.encoded_bytes_per_block() * self.width_blocks as usize; + let mut src = Vec::new(); + self.inner.read_exact_vec(&mut src, len)?; + match self.variant { DxtVariant::DXT1 => decode_dxt1_row(&src, buf), DxtVariant::DXT3 => decode_dxt3_row(&src, buf), @@ -122,9 +128,7 @@ // Note that, due to the way that DXT compression works, a scanline is considered to consist out of // 4 lines of pixels. -impl<'a, R: 'a + Read> ImageDecoder<'a> for DxtDecoder { - type Reader = DxtReader; - +impl ImageDecoder for DxtDecoder { fn dimensions(&self) -> (u32, u32) { (self.width_blocks * 4, self.height_blocks * 4) } @@ -133,21 +137,6 @@ self.variant.color_type() } - fn scanline_bytes(&self) -> u64 { - self.variant.decoded_bytes_per_block() as u64 * u64::from(self.width_blocks) - } - - fn into_reader(self) -> ImageResult { - Ok(DxtReader { - buffer: ImageReadBuffer::new( - #[allow(deprecated)] - self.scanline_bytes(), - self.total_bytes(), - ), - decoder: self, - }) - } - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); @@ -157,107 +146,15 @@ } Ok(()) } -} - -impl<'a, R: 'a + Read + Seek> ImageDecoderRect<'a> for DxtDecoder { - fn read_rect_with_progress( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - progress_callback: F, - ) -> ImageResult<()> { - let encoded_scanline_bytes = - self.variant.encoded_bytes_per_block() as u64 * u64::from(self.width_blocks); - - let start = self.inner.stream_position()?; - image::load_rect( - x, - y, - width, - height, - buf, - progress_callback, - self, - |s, scanline| { - s.inner - .seek(SeekFrom::Start(start + scanline * encoded_scanline_bytes))?; - Ok(()) - }, - |s, buf| s.read_scanline(buf).map(|_| ()), - )?; - self.inner.seek(SeekFrom::Start(start))?; - Ok(()) - } -} - -/// DXT reader -pub struct DxtReader { - buffer: ImageReadBuffer, - decoder: DxtDecoder, -} -impl Read for DxtReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let decoder = &mut self.decoder; - self.buffer.read(buf, |buf| decoder.read_scanline(buf)) - } -} - -/// DXT encoder -pub struct DxtEncoder { - w: W, -} - -impl DxtEncoder { - /// Create a new encoder that writes its output to ```w``` - pub fn new(w: W) -> DxtEncoder { - DxtEncoder { w } - } - - /// Encodes the image data ```data``` - /// that has dimensions ```width``` and ```height``` - /// in ```DxtVariant``` ```variant``` - /// data is assumed to be in variant.color_type() - pub fn encode( - mut self, - data: &[u8], - width: u32, - height: u32, - variant: DxtVariant, - ) -> ImageResult<()> { - if width % 4 != 0 || height % 4 != 0 { - // TODO: this is not very idiomatic yet. Should return an EncodingError. - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))); - } - let width_blocks = width / 4; - let height_blocks = height / 4; - - let stride = variant.decoded_bytes_per_block(); - - assert!(data.len() >= width_blocks as usize * height_blocks as usize * stride); - - for chunk in data.chunks(width_blocks as usize * stride) { - let data = match variant { - DxtVariant::DXT1 => encode_dxt1_row(chunk), - DxtVariant::DXT3 => encode_dxt3_row(chunk), - DxtVariant::DXT5 => encode_dxt5_row(chunk), - }; - self.w.write_all(&data)?; - } - Ok(()) + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } } /** * Actual encoding/decoding logic below. */ -use std::mem::swap; - type Rgb = [u8; 3]; /// decodes a 5-bit R, 6-bit G, 5-bit B 16-bit packed color value into 8-bit RGB @@ -274,27 +171,6 @@ ] } -/// encodes an 8-bit RGB value into a 5-bit R, 6-bit G, 5-bit B 16-bit packed color value -/// mapping preserves min/max values. It is guaranteed that i == encode(decode(i)) for all i -fn enc565_encode(rgb: Rgb) -> u16 { - let red = (u16::from(rgb[0]) * 0x1F + 0x7E) / 0xFF; - let green = (u16::from(rgb[1]) * 0x3F + 0x7E) / 0xFF; - let blue = (u16::from(rgb[2]) * 0x1F + 0x7E) / 0xFF; - (red << 11) | (green << 5) | blue -} - -/// utility function: squares a value -fn square(a: i32) -> i32 { - a * a -} - -/// returns the squared error between two RGB values -fn diff(a: Rgb, b: Rgb) -> i32 { - square(i32::from(a[0]) - i32::from(b[0])) - + square(i32::from(a[1]) - i32::from(b[1])) - + square(i32::from(a[2]) - i32::from(b[2])) -} - /* * Functions for decoding DXT compression */ @@ -320,6 +196,7 @@ /// decodes an 8-byte dxt color block into the RGB channels of a 16xRGB or 16xRGBA block. /// source should have a length of 8, dest a length of 48 (RGB) or 64 (RGBA) +#[allow(clippy::needless_range_loop)] // False positive, the 0..3 loop is not an enumerate fn decode_dxt_colors(source: &[u8], dest: &mut [u8], is_dxt1: bool) { // sanity checks, also enable the compiler to elide all following bound checks assert!(source.len() == 8 && (dest.len() == 48 || dest.len() == 64)); @@ -350,7 +227,7 @@ } else { // linearly interpolate one other entry, keep the other at 0 for i in 0..3 { - colors[2][i] = ((u16::from(colors[0][i]) + u16::from(colors[1][i]) + 1) / 2) as u8; + colors[2][i] = (u16::from(colors[0][i]) + u16::from(colors[1][i])).div_ceil(2) as u8; } } @@ -372,7 +249,7 @@ .rev() .fold(0, |t, &b| (t << 8) | u64::from(b)); - // alhpa level decode + // alpha level decode let alphas = alpha_table_dxt5(source[0], source[1]); // serialize alpha @@ -410,7 +287,7 @@ } /// Decode a row of DXT1 data to four rows of RGB data. -/// source.len() should be a multiple of 8, otherwise this panics. +/// `source.len()` should be a multiple of 8, otherwise this panics. fn decode_dxt1_row(source: &[u8], dest: &mut [u8]) { assert!(source.len() % 8 == 0); let block_count = source.len() / 8; @@ -431,7 +308,7 @@ } /// Decode a row of DXT3 data to four rows of RGBA data. -/// source.len() should be a multiple of 16, otherwise this panics. +/// `source.len()` should be a multiple of 16, otherwise this panics. fn decode_dxt3_row(source: &[u8], dest: &mut [u8]) { assert!(source.len() % 16 == 0); let block_count = source.len() / 16; @@ -452,7 +329,7 @@ } /// Decode a row of DXT5 data to four rows of RGBA data. -/// source.len() should be a multiple of 16, otherwise this panics. +/// `source.len()` should be a multiple of 16, otherwise this panics. fn decode_dxt5_row(source: &[u8], dest: &mut [u8]) { assert!(source.len() % 16 == 0); let block_count = source.len() / 16; @@ -471,409 +348,3 @@ } } } - -/* - * Functions for encoding DXT compression - */ - -/// Tries to perform the color encoding part of dxt compression -/// the approach taken is simple, it picks unique combinations -/// of the colors present in the block, and attempts to encode the -/// block with each, picking the encoding that yields the least -/// squared error out of all of them. -/// -/// This could probably be faster but is already reasonably fast -/// and a good reference impl to optimize others against. -/// -/// Another way to perform this analysis would be to perform a -/// singular value decomposition of the different colors, and -/// then pick 2 points on this line as the base colors. But -/// this is still rather unwieldy math and has issues -/// with the 3-linear-colors-and-0 case, it's also worse -/// at conserving the original colors. -/// -/// source: should be RGBAx16 or RGBx16 bytes of data, -/// dest 8 bytes of resulting encoded color data -fn encode_dxt_colors(source: &[u8], dest: &mut [u8], is_dxt1: bool) { - // sanity checks and determine stride when parsing the source data - assert!((source.len() == 64 || source.len() == 48) && dest.len() == 8); - let stride = source.len() / 16; - - // reference colors array - let mut colors = [[0u8; 3]; 4]; - - // Put the colors we're going to be processing in an array with pure RGB layout - // note: we reverse the pixel order here. The reason for this is found in the inner quantization loop. - let mut targets = [[0u8; 3]; 16]; - for (s, d) in source.chunks(stride).rev().zip(&mut targets) { - *d = [s[0], s[1], s[2]]; - } - - // roundtrip all colors through the r5g6b5 encoding - for rgb in &mut targets { - *rgb = enc565_decode(enc565_encode(*rgb)); - } - - // and deduplicate the set of colors to choose from as the algorithm is O(N^2) in this - let mut colorspace_ = [[0u8; 3]; 16]; - let mut colorspace_len = 0; - for color in &targets { - if !colorspace_[..colorspace_len].contains(color) { - colorspace_[colorspace_len] = *color; - colorspace_len += 1; - } - } - let mut colorspace = &colorspace_[..colorspace_len]; - - // in case of slight gradients it can happen that there's only one entry left in the color table. - // as the resulting banding can be quite bad if we would just left the block at the closest - // encodable color, we have a special path here that tries to emulate the wanted color - // using the linear interpolation between gradients - if colorspace.len() == 1 { - // the base color we got from colorspace reduction - let ref_rgb = colorspace[0]; - // the unreduced color in this block that's the furthest away from the actual block - let mut rgb = targets - .iter() - .cloned() - .max_by_key(|rgb| diff(*rgb, ref_rgb)) - .unwrap(); - // amplify differences by 2.5, which should push them to the next quantized value - // if possible without overshoot - for i in 0..3 { - rgb[i] = - ((i16::from(rgb[i]) - i16::from(ref_rgb[i])) * 5 / 2 + i16::from(ref_rgb[i])) as u8; - } - - // roundtrip it through quantization - let encoded = enc565_encode(rgb); - let rgb = enc565_decode(encoded); - - // in case this didn't land us a different color the best way to represent this field is - // as a single color block - if rgb == ref_rgb { - dest[0] = encoded as u8; - dest[1] = (encoded >> 8) as u8; - - for d in dest.iter_mut().take(8).skip(2) { - *d = 0; - } - return; - } - - // we did find a separate value: add it to the options so after one round of quantization - // we're done - colorspace_[1] = rgb; - colorspace = &colorspace_[..2]; - } - - // block quantization loop: we basically just try every possible combination, returning - // the combination with the least squared error - // stores the best candidate colors - let mut chosen_colors = [[0; 3]; 4]; - // did this index table use the [0,0,0] variant - let mut chosen_use_0 = false; - // error calculated for the last entry - let mut chosen_error = 0xFFFF_FFFFu32; - - // loop through unique permutations of the colorspace, where c1 != c2 - 'search: for (i, &c1) in colorspace.iter().enumerate() { - colors[0] = c1; - - for &c2 in &colorspace[0..i] { - colors[1] = c2; - - if is_dxt1 { - // what's inside here is ran at most 120 times. - for use_0 in 0..2 { - // and 240 times here. - - if use_0 != 0 { - // interpolate one color, set the other to 0 - for i in 0..3 { - colors[2][i] = - ((u16::from(colors[0][i]) + u16::from(colors[1][i]) + 1) / 2) as u8; - } - colors[3] = [0, 0, 0]; - } else { - // interpolate to get 2 more colors - for i in 0..3 { - colors[2][i] = - ((u16::from(colors[0][i]) * 2 + u16::from(colors[1][i]) + 1) / 3) - as u8; - colors[3][i] = - ((u16::from(colors[0][i]) + u16::from(colors[1][i]) * 2 + 1) / 3) - as u8; - } - } - - // calculate the total error if we were to quantize the block with these color combinations - // both these loops have statically known iteration counts and are well vectorizable - // note that the inside of this can be run about 15360 times worst case, i.e. 960 times per - // pixel. - let total_error = targets - .iter() - .map(|t| colors.iter().map(|c| diff(*c, *t) as u32).min().unwrap()) - .sum(); - - // update the match if we found a better one - if total_error < chosen_error { - chosen_colors = colors; - chosen_use_0 = use_0 != 0; - chosen_error = total_error; - - // if we've got a perfect or at most 1 LSB off match, we're done - if total_error < 4 { - break 'search; - } - } - } - } else { - // what's inside here is ran at most 120 times. - - // interpolate to get 2 more colors - for i in 0..3 { - colors[2][i] = - ((u16::from(colors[0][i]) * 2 + u16::from(colors[1][i]) + 1) / 3) as u8; - colors[3][i] = - ((u16::from(colors[0][i]) + u16::from(colors[1][i]) * 2 + 1) / 3) as u8; - } - - // calculate the total error if we were to quantize the block with these color combinations - // both these loops have statically known iteration counts and are well vectorizable - // note that the inside of this can be run about 15360 times worst case, i.e. 960 times per - // pixel. - let total_error = targets - .iter() - .map(|t| colors.iter().map(|c| diff(*c, *t) as u32).min().unwrap()) - .sum(); - - // update the match if we found a better one - if total_error < chosen_error { - chosen_colors = colors; - chosen_error = total_error; - - // if we've got a perfect or at most 1 LSB off match, we're done - if total_error < 4 { - break 'search; - } - } - } - } - } - - // calculate the final indices - // note that targets is already in reverse pixel order, to make the index computation easy. - let mut chosen_indices = 0u32; - for t in &targets { - let (idx, _) = chosen_colors - .iter() - .enumerate() - .min_by_key(|&(_, c)| diff(*c, *t)) - .unwrap(); - chosen_indices = (chosen_indices << 2) | idx as u32; - } - - // encode the colors - let mut color0 = enc565_encode(chosen_colors[0]); - let mut color1 = enc565_encode(chosen_colors[1]); - - // determine encoding. Note that color0 == color1 is impossible at this point - if is_dxt1 { - if color0 > color1 { - if chosen_use_0 { - swap(&mut color0, &mut color1); - // Indexes are packed 2 bits wide, swap index 0/1 but preserve 2/3. - let filter = (chosen_indices & 0xAAAA_AAAA) >> 1; - chosen_indices ^= filter ^ 0x5555_5555; - } - } else if !chosen_use_0 { - swap(&mut color0, &mut color1); - // Indexes are packed 2 bits wide, swap index 0/1 and 2/3. - chosen_indices ^= 0x5555_5555; - } - } - - // encode everything. - dest[0] = color0 as u8; - dest[1] = (color0 >> 8) as u8; - dest[2] = color1 as u8; - dest[3] = (color1 >> 8) as u8; - for i in 0..4 { - dest[i + 4] = (chosen_indices >> (i * 8)) as u8; - } -} - -/// Encodes a buffer of 16 alpha bytes into a dxt5 alpha index table, -/// where the alpha table they are indexed against is created by -/// calling alpha_table_dxt5(alpha0, alpha1) -/// returns the resulting error and alpha table -fn encode_dxt5_alpha(alpha0: u8, alpha1: u8, alphas: &[u8; 16]) -> (i32, u64) { - // create a table for the given alpha ranges - let table = alpha_table_dxt5(alpha0, alpha1); - let mut indices = 0u64; - let mut total_error = 0i32; - - // least error brute force search - for (i, &a) in alphas.iter().enumerate() { - let (index, error) = table - .iter() - .enumerate() - .map(|(i, &e)| (i, square(i32::from(e) - i32::from(a)))) - .min_by_key(|&(_, e)| e) - .unwrap(); - total_error += error; - indices |= (index as u64) << (i * 3); - } - - (total_error, indices) -} - -/// Encodes a RGBAx16 sequence of bytes to a 16 bytes DXT5 block -fn encode_dxt5_block(source: &[u8], dest: &mut [u8]) { - assert!(source.len() == 64 && dest.len() == 16); - - // perform dxt color encoding - encode_dxt_colors(source, &mut dest[8..16], false); - - // copy out the alpha bytes - let mut alphas = [0; 16]; - for i in 0..16 { - alphas[i] = source[i * 4 + 3]; - } - - // try both alpha compression methods, see which has the least error. - let alpha07 = alphas.iter().cloned().min().unwrap(); - let alpha17 = alphas.iter().cloned().max().unwrap(); - let (error7, indices7) = encode_dxt5_alpha(alpha07, alpha17, &alphas); - - // if all alphas are 0 or 255 it doesn't particularly matter what we do here. - let alpha05 = alphas - .iter() - .cloned() - .filter(|&i| i != 255) - .max() - .unwrap_or(255); - let alpha15 = alphas - .iter() - .cloned() - .filter(|&i| i != 0) - .min() - .unwrap_or(0); - let (error5, indices5) = encode_dxt5_alpha(alpha05, alpha15, &alphas); - - // pick the best one, encode the min/max values - let mut alpha_table = if error5 < error7 { - dest[0] = alpha05; - dest[1] = alpha15; - indices5 - } else { - dest[0] = alpha07; - dest[1] = alpha17; - indices7 - }; - - // encode the alphas - for byte in dest[2..8].iter_mut() { - *byte = alpha_table as u8; - alpha_table >>= 8; - } -} - -/// Encodes a RGBAx16 sequence of bytes into a 16 bytes DXT3 block -fn encode_dxt3_block(source: &[u8], dest: &mut [u8]) { - assert!(source.len() == 64 && dest.len() == 16); - - // perform dxt color encoding - encode_dxt_colors(source, &mut dest[8..16], false); - - // DXT3 alpha compression is very simple, just round towards the nearest value - - // index the alpha values into the 64bit alpha table - let mut alpha_table = 0u64; - for i in 0..16 { - let alpha = u64::from(source[i * 4 + 3]); - let alpha = (alpha + 0x8) / 0x11; - alpha_table |= alpha << (i * 4); - } - - // encode the alpha values - for byte in &mut dest[0..8] { - *byte = alpha_table as u8; - alpha_table >>= 8; - } -} - -/// Encodes a RGBx16 sequence of bytes into a 8 bytes DXT1 block -fn encode_dxt1_block(source: &[u8], dest: &mut [u8]) { - assert!(source.len() == 48 && dest.len() == 8); - - // perform dxt color encoding - encode_dxt_colors(source, dest, true); -} - -/// Decode a row of DXT1 data to four rows of RGBA data. -/// source.len() should be a multiple of 8, otherwise this panics. -fn encode_dxt1_row(source: &[u8]) -> Vec { - assert!(source.len() % 48 == 0); - let block_count = source.len() / 48; - - let mut dest = vec![0u8; block_count * 8]; - // contains the 16 decoded pixels per block - let mut decoded_block = [0u8; 48]; - - for (x, encoded_block) in dest.chunks_mut(8).enumerate() { - // copy the values from the decoded block to linewise RGB layout - for line in 0..4 { - let offset = (block_count * line + x) * 12; - decoded_block[line * 12..(line + 1) * 12].copy_from_slice(&source[offset..offset + 12]); - } - - encode_dxt1_block(&decoded_block, encoded_block); - } - dest -} - -/// Decode a row of DXT3 data to four rows of RGBA data. -/// source.len() should be a multiple of 16, otherwise this panics. -fn encode_dxt3_row(source: &[u8]) -> Vec { - assert!(source.len() % 64 == 0); - let block_count = source.len() / 64; - - let mut dest = vec![0u8; block_count * 16]; - // contains the 16 decoded pixels per block - let mut decoded_block = [0u8; 64]; - - for (x, encoded_block) in dest.chunks_mut(16).enumerate() { - // copy the values from the decoded block to linewise RGB layout - for line in 0..4 { - let offset = (block_count * line + x) * 16; - decoded_block[line * 16..(line + 1) * 16].copy_from_slice(&source[offset..offset + 16]); - } - - encode_dxt3_block(&decoded_block, encoded_block); - } - dest -} - -/// Decode a row of DXT5 data to four rows of RGBA data. -/// source.len() should be a multiple of 16, otherwise this panics. -fn encode_dxt5_row(source: &[u8]) -> Vec { - assert!(source.len() % 64 == 0); - let block_count = source.len() / 64; - - let mut dest = vec![0u8; block_count * 16]; - // contains the 16 decoded pixels per block - let mut decoded_block = [0u8; 64]; - - for (x, encoded_block) in dest.chunks_mut(16).enumerate() { - // copy the values from the decoded block to linewise RGB layout - for line in 0..4 { - let offset = (block_count * line + x) * 16; - decoded_block[line * 16..(line + 1) * 16].copy_from_slice(&source[offset..offset + 16]); - } - - encode_dxt5_block(&decoded_block, encoded_block); - } - dest -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/farbfeld.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/farbfeld.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/farbfeld.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/farbfeld.rs 2006-07-24 01:21:28.000000000 +0000 @@ -16,14 +16,14 @@ //! # Related Links //! * - the farbfeld specification -use std::i64; use std::io::{self, Read, Seek, SeekFrom, Write}; -use crate::color::ColorType; +use crate::color::ExtendedColorType; use crate::error::{ DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageEncoder, ImageFormat, Progress}; +use crate::io::free_functions::load_rect; +use crate::{ColorType, ImageDecoder, ImageDecoderRect, ImageEncoder, ImageFormat}; /// farbfeld Reader pub struct FarbfeldReader { @@ -52,7 +52,7 @@ if &magic != b"farbfeld" { return Err(ImageError::Decoding(DecodingError::new( ImageFormat::Farbfeld.into(), - format!("Invalid magic: {:02x?}", magic), + format!("Invalid magic: {magic:02x?}"), ))); } @@ -67,8 +67,8 @@ if crate::utils::check_dimension_overflow( reader.width, reader.height, - // ColorType is always rgba16 - ColorType::Rgba16.bytes_per_pixel(), + // ExtendedColorType is always rgba16 + 8, ) { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( @@ -136,7 +136,7 @@ } let original_offset = self.current_offset; - let end_offset = self.width as u64 * self.height as u64 * 2; + let end_offset = u64::from(self.width) * u64::from(self.height) * 2; let offset_from_current = parse_offset(original_offset, end_offset, pos).ok_or_else(|| { io::Error::new( @@ -195,9 +195,7 @@ } } -impl<'a, R: 'a + Read> ImageDecoder<'a> for FarbfeldDecoder { - type Reader = FarbfeldReader; - +impl ImageDecoder for FarbfeldDecoder { fn dimensions(&self) -> (u32, u32) { (self.reader.width, self.reader.height) } @@ -206,36 +204,39 @@ ColorType::Rgba16 } - fn into_reader(self) -> ImageResult { - Ok(self.reader) + fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { + assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); + self.reader.read_exact(buf)?; + Ok(()) } - fn scanline_bytes(&self) -> u64 { - 2 + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } } -impl<'a, R: 'a + Read + Seek> ImageDecoderRect<'a> for FarbfeldDecoder { - fn read_rect_with_progress( +impl ImageDecoderRect for FarbfeldDecoder { + fn read_rect( &mut self, x: u32, y: u32, width: u32, height: u32, buf: &mut [u8], - progress_callback: F, + row_pitch: usize, ) -> ImageResult<()> { // A "scanline" (defined as "shortest non-caching read" in the doc) is just one channel in this case let start = self.reader.stream_position()?; - image::load_rect( + load_rect( x, y, width, height, buf, - progress_callback, + row_pitch, self, + 2, |s, scanline| s.reader.seek(SeekFrom::Start(scanline * 2)).map(|_| ()), |s, buf| s.reader.read_exact(buf), )?; @@ -262,7 +263,7 @@ /// Panics if `width * height * 8 != data.len()`. #[track_caller] pub fn encode(self, data: &[u8], width: u32, height: u32) -> ImageResult<()> { - let expected_buffer_len = (width as u64 * height as u64).saturating_mul(8); + let expected_buffer_len = (u64::from(width) * u64::from(height)).saturating_mul(8); assert_eq!( expected_buffer_len, data.len() as u64, @@ -295,13 +296,13 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - if color_type != ColorType::Rgba16 { + if color_type != ExtendedColorType::Rgba16 { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Farbfeld.into(), - UnsupportedErrorKind::Color(color_type.into()), + UnsupportedErrorKind::Color(color_type), ), )); } @@ -314,7 +315,7 @@ mod tests { use crate::codecs::farbfeld::FarbfeldDecoder; use crate::ImageDecoderRect; - use byteorder::{ByteOrder, NativeEndian}; + use byteorder_lite::{ByteOrder, NativeEndian}; use std::io::{Cursor, Seek, SeekFrom}; static RECTANGLE_IN: &[u8] = b"farbfeld\ @@ -375,7 +376,7 @@ let mut out_buf = [0u8; 64]; FarbfeldDecoder::new(input_cur) .unwrap() - .read_rect(0, 2, 1, 1, &mut out_buf) + .read_rect(0, 2, 1, 1, &mut out_buf, 8) .unwrap(); let exp = degenerate_pixels(RECTANGLE_OUT); assert_eq!(&out_buf[..exp.len()], &exp[..]); @@ -392,7 +393,7 @@ let mut out_buf = [0u8; 64]; FarbfeldDecoder::new(Cursor::new(RECTANGLE_IN)) .unwrap() - .read_rect(x, y, width, height, &mut out_buf) + .read_rect(x, y, width, height, &mut out_buf, width as usize * 8) .unwrap(); let exp = degenerate_pixels(exp_wide); assert_eq!(&out_buf[..exp.len()], &exp[..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/gif.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/gif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/gif.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/gif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,9 +10,10 @@ //! use image::codecs::gif::{GifDecoder, GifEncoder}; //! use image::{ImageDecoder, AnimationDecoder}; //! use std::fs::File; +//! use std::io::BufReader; //! # fn main() -> std::io::Result<()> { //! // Decode a gif into frames -//! let file_in = File::open("foo.gif")?; +//! let file_in = BufReader::new(File::open("foo.gif")?); //! let mut decoder = GifDecoder::new(file_in).unwrap(); //! let frames = decoder.into_frames(); //! let frames = frames.collect_frames().expect("error decoding gif"); @@ -26,7 +27,7 @@ //! ``` #![allow(clippy::while_let_loop)] -use std::io::{self, Cursor, Read, Write}; +use std::io::{self, BufRead, Cursor, Read, Seek, Write}; use std::marker::PhantomData; use std::mem; @@ -35,16 +36,15 @@ use crate::animation::{self, Ratio}; use crate::color::{ColorType, Rgba}; -use crate::error::LimitError; -use crate::error::LimitErrorKind; use crate::error::{ - DecodingError, EncodingError, ImageError, ImageResult, ParameterError, ParameterErrorKind, - UnsupportedError, UnsupportedErrorKind, + DecodingError, EncodingError, ImageError, ImageResult, LimitError, LimitErrorKind, + ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, AnimationDecoder, ImageDecoder, ImageFormat}; -use crate::io::Limits; use crate::traits::Pixel; -use crate::ImageBuffer; +use crate::{ + AnimationDecoder, ExtendedColorType, ImageBuffer, ImageDecoder, ImageEncoder, ImageFormat, + Limits, +}; /// GIF decoder pub struct GifDecoder { @@ -63,24 +63,18 @@ limits: Limits::no_limits(), }) } - - /// Creates a new decoder that decodes the input steam `r`, using limits `limits` - #[deprecated(since = "0.24.8", note = "Use `new` followed by `set_limits` instead")] - pub fn with_limits(r: R, limits: Limits) -> ImageResult> { - let mut decoder = Self::new(r)?; - // call `.set_limits()` instead of just setting the field directly - // so that we raise an error in case they are exceeded - decoder.set_limits(limits)?; - Ok(decoder) - } } /// Wrapper struct around a `Cursor>` +#[allow(dead_code)] +#[deprecated] pub struct GifReader(Cursor>, PhantomData); +#[allow(deprecated)] impl Read for GifReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { if self.0.position() == 0 && buf.is_empty() { mem::swap(buf, self.0.get_mut()); @@ -91,9 +85,7 @@ } } -impl<'a, R: 'a + Read> ImageDecoder<'a> for GifDecoder { - type Reader = GifReader; - +impl ImageDecoder for GifDecoder { fn dimensions(&self) -> (u32, u32) { ( u32::from(self.reader.width()), @@ -105,15 +97,8 @@ ColorType::Rgba8 } - fn into_reader(self) -> ImageResult { - Ok(GifReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - fn set_limits(&mut self, limits: Limits) -> ImageResult<()> { - limits.check_support(&crate::io::LimitSupport::default())?; + limits.check_support(&crate::LimitSupport::default())?; let (width, height) = self.dimensions(); limits.check_dimensions(width, height)?; @@ -143,7 +128,7 @@ if frame.left == 0 && frame.width == width - && (frame.top as u64 + frame.height as u64 <= height as u64) + && (u64::from(frame.top) + u64::from(frame.height) <= u64::from(height)) { // If the frame matches the logical screen, or, as a more general case, // fits into it and touches its left and right borders, then @@ -228,6 +213,20 @@ Ok(()) } + + fn icc_profile(&mut self) -> ImageResult>> { + // Similar to XMP metadata + Ok(self.reader.icc_profile().map(Vec::from)) + } + + fn xmp_metadata(&mut self) -> ImageResult>> { + // XMP metadata must be part of the header which is read with `read_info`. + Ok(self.reader.xmp_metadata().map(Vec::from)) + } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } struct GifFrameIterator { @@ -238,9 +237,12 @@ non_disposed_frame: Option, Vec>>, limits: Limits, + // `is_end` is used to indicate whether the iterator has reached the end of the frames. + // Or encounter any un-recoverable error. + is_end: bool, } -impl GifFrameIterator { +impl GifFrameIterator { fn new(decoder: GifDecoder) -> GifFrameIterator { let (width, height) = decoder.dimensions(); let limits = decoder.limits.clone(); @@ -253,6 +255,7 @@ height, non_disposed_frame: None, limits, + is_end: false, } } } @@ -261,6 +264,10 @@ type Item = ImageResult; fn next(&mut self) -> Option> { + if self.is_end { + return None; + } + // The iterator always produces RGBA8 images const COLOR_TYPE: ColorType = ColorType::Rgba8; @@ -294,7 +301,18 @@ return None; } } - Err(err) => return Some(Err(ImageError::from_decoding(err))), + Err(err) => match err { + gif::DecodingError::Io(ref e) => { + if e.kind() == io::ErrorKind::UnexpectedEof { + // end of file reached, no more frames + self.is_end = true; + } + return Some(Err(ImageError::from_decoding(err))); + } + _ => { + return Some(Err(ImageError::from_decoding(err))); + } + }, }; // All allocations we do from now on will be freed at the end of this function. @@ -318,19 +336,16 @@ // correct storage requirement if the result does not fit in `usize`. // on the other hand, `ImageBuffer::from_raw` detects overflow and // reports by returning `None`. - let mut frame_buffer = match ImageBuffer::from_raw(frame.width, frame.height, vec) { - Some(frame_buffer) => frame_buffer, - None => { - return Some(Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Gif.into(), - UnsupportedErrorKind::GenericFeature(format!( - "Image dimensions ({}, {}) are too large", - frame.width, frame.height - )), - ), - ))) - } + let Some(mut frame_buffer) = ImageBuffer::from_raw(frame.width, frame.height, vec) else { + return Some(Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Gif.into(), + UnsupportedErrorKind::GenericFeature(format!( + "Image dimensions ({}, {}) are too large", + frame.width, frame.height + )), + ), + ))); }; // blend the current frame with the non-disposed frame, then update @@ -406,7 +421,7 @@ } } -impl<'a, R: Read + 'a> AnimationDecoder<'a> for GifDecoder { +impl<'a, R: BufRead + Seek + 'a> AnimationDecoder<'a> for GifDecoder { fn into_frames(self) -> animation::Frames<'a> { animation::Frames::new(Box::new(GifFrameIterator::new(self))) } @@ -445,9 +460,9 @@ } impl Repeat { - pub(crate) fn to_gif_enum(&self) -> gif::Repeat { + pub(crate) fn to_gif_enum(self) -> gif::Repeat { match self { - Repeat::Finite(n) => gif::Repeat::Finite(*n), + Repeat::Finite(n) => gif::Repeat::Finite(n), Repeat::Infinite => gif::Repeat::Infinite, } } @@ -500,18 +515,23 @@ data: &[u8], width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, ) -> ImageResult<()> { let (width, height) = self.gif_dimensions(width, height)?; match color { - ColorType::Rgb8 => self.encode_gif(Frame::from_rgb(width, height, data)), - ColorType::Rgba8 => { - self.encode_gif(Frame::from_rgba(width, height, &mut data.to_owned())) + ExtendedColorType::Rgb8 => { + self.encode_gif(Frame::from_rgb_speed(width, height, data, self.speed)) } + ExtendedColorType::Rgba8 => self.encode_gif(Frame::from_rgba_speed( + width, + height, + &mut data.to_owned(), + self.speed, + )), _ => Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Gif.into(), - UnsupportedErrorKind::Color(color.into()), + UnsupportedErrorKind::Color(color), ), )), } @@ -564,7 +584,7 @@ // would require a new special cased variant in ParameterErrorKind which most // likely couldn't be reused for other cases. This isn't a bad trade-off given // that the current algorithm is already lossy. - frame.delay = (frame_delay / 10).try_into().unwrap_or(std::u16::MAX); + frame.delay = (frame_delay / 10).try_into().unwrap_or(u16::MAX); Ok(frame) } @@ -598,35 +618,42 @@ .map_err(ImageError::from_encoding)?; } self.gif_encoder = Some(encoder); - gif_encoder = self.gif_encoder.as_mut().unwrap() + gif_encoder = self.gif_encoder.as_mut().unwrap(); } - frame.dispose = gif::DisposalMethod::Background; + frame.dispose = DisposalMethod::Background; gif_encoder .write_frame(&frame) .map_err(ImageError::from_encoding) } } +impl ImageEncoder for GifEncoder { + fn write_image( + mut self, + buf: &[u8], + width: u32, + height: u32, + color_type: ExtendedColorType, + ) -> ImageResult<()> { + self.encode(buf, width, height, color_type) + } +} impl ImageError { fn from_decoding(err: gif::DecodingError) -> ImageError { use gif::DecodingError::*; match err { - err @ Format(_) => { - ImageError::Decoding(DecodingError::new(ImageFormat::Gif.into(), err)) - } Io(io_err) => ImageError::IoError(io_err), + other => ImageError::Decoding(DecodingError::new(ImageFormat::Gif.into(), other)), } } fn from_encoding(err: gif::EncodingError) -> ImageError { use gif::EncodingError::*; match err { - err @ Format(_) => { - ImageError::Encoding(EncodingError::new(ImageFormat::Gif.into(), err)) - } Io(io_err) => ImageError::IoError(io_err), + other => ImageError::Encoding(EncodingError::new(ImageFormat::Gif.into(), other)), } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,12 @@ -use crate::Primitive; -use num_traits::identities::Zero; -#[cfg(test)] -use std::borrow::Cow; -use std::io::{self, BufRead, Cursor, Read, Seek}; -use std::marker::PhantomData; +use std::io::{self, Read}; + use std::num::{ParseFloatError, ParseIntError}; -use std::path::Path; -use std::{error, fmt, mem}; +use std::{error, fmt}; -use crate::color::{ColorType, Rgb}; use crate::error::{ - DecodingError, ImageError, ImageFormatHint, ImageResult, ParameterError, ParameterErrorKind, - UnsupportedError, UnsupportedErrorKind, + DecodingError, ImageError, ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageFormat, Progress}; +use crate::{ColorType, ImageDecoder, ImageFormat, Rgb}; /// Errors that can occur during decoding and parsing of a HDR image #[derive(Debug, Clone, PartialEq, Eq)] @@ -55,26 +48,23 @@ DecoderError::TruncatedHeader => f.write_str("EOF in header"), DecoderError::TruncatedDimensions => f.write_str("EOF in dimensions line"), DecoderError::UnparsableF32(line, pe) => { - f.write_fmt(format_args!("Cannot parse {} value as f32: {}", line, pe)) + f.write_fmt(format_args!("Cannot parse {line} value as f32: {pe}")) } DecoderError::UnparsableU32(line, pe) => { - f.write_fmt(format_args!("Cannot parse {} value as u32: {}", line, pe)) + f.write_fmt(format_args!("Cannot parse {line} value as u32: {pe}")) } DecoderError::LineTooShort(line) => { - f.write_fmt(format_args!("Not enough numbers in {}", line)) + f.write_fmt(format_args!("Not enough numbers in {line}")) } DecoderError::ExtraneousColorcorrNumbers => f.write_str("Extra numbers in COLORCORR"), DecoderError::DimensionsLineTooShort(elements, expected) => f.write_fmt(format_args!( - "Dimensions line too short: have {} elements, expected {}", - elements, expected + "Dimensions line too short: have {elements} elements, expected {expected}" )), DecoderError::DimensionsLineTooLong(expected) => f.write_fmt(format_args!( - "Dimensions line too long, expected {} elements", - expected + "Dimensions line too long, expected {expected} elements" )), DecoderError::WrongScanlineLength(len, expected) => f.write_fmt(format_args!( - "Wrong length of decoded scanline: got {}, expected {}", - len, expected + "Wrong length of decoded scanline: got {len}, expected {expected}" )), DecoderError::FirstPixelRlMarker => { f.write_str("First pixel of a scanline shouldn't be run length marker") @@ -121,117 +111,6 @@ } } -/// Adapter to conform to `ImageDecoder` trait -#[derive(Debug)] -pub struct HdrAdapter { - inner: Option>, - // data: Option>, - meta: HdrMetadata, -} - -impl HdrAdapter { - /// Creates adapter - pub fn new(r: R) -> ImageResult> { - let decoder = HdrDecoder::new(r)?; - let meta = decoder.metadata(); - Ok(HdrAdapter { - inner: Some(decoder), - meta, - }) - } - - /// Allows reading old Radiance HDR images - pub fn new_nonstrict(r: R) -> ImageResult> { - let decoder = HdrDecoder::with_strictness(r, false)?; - let meta = decoder.metadata(); - Ok(HdrAdapter { - inner: Some(decoder), - meta, - }) - } - - /// Read the actual data of the image, and store it in Self::data. - fn read_image_data(&mut self, buf: &mut [u8]) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - match self.inner.take() { - Some(decoder) => { - let img: Vec> = decoder.read_image_ldr()?; - for (i, Rgb(data)) in img.into_iter().enumerate() { - buf[(i * 3)..][..3].copy_from_slice(&data); - } - - Ok(()) - } - None => Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::NoMoreData, - ))), - } - } -} - -/// Wrapper struct around a `Cursor>` -pub struct HdrReader(Cursor>, PhantomData); -impl Read for HdrReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } - } -} - -impl<'a, R: 'a + BufRead> ImageDecoder<'a> for HdrAdapter { - type Reader = HdrReader; - - fn dimensions(&self) -> (u32, u32) { - (self.meta.width, self.meta.height) - } - - fn color_type(&self) -> ColorType { - ColorType::Rgb8 - } - - fn into_reader(self) -> ImageResult { - Ok(HdrReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { - self.read_image_data(buf) - } -} - -impl<'a, R: 'a + BufRead + Seek> ImageDecoderRect<'a> for HdrAdapter { - fn read_rect_with_progress( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - progress_callback: F, - ) -> ImageResult<()> { - image::load_rect( - x, - y, - width, - height, - buf, - progress_callback, - self, - |_, _| unreachable!(), - |s, buf| s.read_image_data(buf), - ) - } -} - /// Radiance HDR file signature pub const SIGNATURE: &[u8] = b"#?RADIANCE"; const SIGNATURE_LENGTH: usize = 10; @@ -248,22 +127,22 @@ /// Refer to [wikipedia](https://en.wikipedia.org/wiki/RGBE_image_format) #[repr(C)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct Rgbe8Pixel { +pub(crate) struct Rgbe8Pixel { /// Color components - pub c: [u8; 3], + pub(crate) c: [u8; 3], /// Exponent - pub e: u8, + pub(crate) e: u8, } /// Creates `Rgbe8Pixel` from components -pub fn rgbe8(r: u8, g: u8, b: u8, e: u8) -> Rgbe8Pixel { +pub(crate) fn rgbe8(r: u8, g: u8, b: u8, e: u8) -> Rgbe8Pixel { Rgbe8Pixel { c: [r, g, b], e } } impl Rgbe8Pixel { /// Converts `Rgbe8Pixel` into `Rgb` linearly #[inline] - pub fn to_hdr(self) -> Rgb { + pub(crate) fn to_hdr(self) -> Rgb { if self.e == 0 { Rgb([0.0, 0.0, 0.0]) } else { @@ -276,63 +155,21 @@ ]) } } - - /// Converts `Rgbe8Pixel` into `Rgb` with scale=1 and gamma=2.2 - /// - /// color_ldr = (color_hdr*scale)gamma - /// - /// # Panic - /// - /// Panics when `T::max_value()` cannot be represented as f32. - #[inline] - pub fn to_ldr(self) -> Rgb { - self.to_ldr_scale_gamma(1.0, 2.2) - } - - /// Converts `Rgbe8Pixel` into `Rgb` using provided scale and gamma - /// - /// color_ldr = (color_hdr*scale)gamma - /// - /// # Panic - /// - /// Panics when `T::max_value()` cannot be represented as f32. - /// Panics when scale or gamma is NaN - #[inline] - pub fn to_ldr_scale_gamma(self, scale: f32, gamma: f32) -> Rgb { - let Rgb(data) = self.to_hdr(); - let (r, g, b) = (data[0], data[1], data[2]); - #[inline] - fn sg(v: f32, scale: f32, gamma: f32) -> T { - let t_max = T::max_value(); - // Disassembly shows that t_max_f32 is compiled into constant - let t_max_f32: f32 = num_traits::NumCast::from(t_max) - .expect("to_ldr_scale_gamma: maximum value of type is not representable as f32"); - let fv = f32::powf(v * scale, gamma) * t_max_f32 + 0.5; - if fv < 0.0 { - T::zero() - } else if fv > t_max_f32 { - t_max - } else { - num_traits::NumCast::from(fv) - .expect("to_ldr_scale_gamma: cannot convert f32 to target type. NaN?") - } - } - Rgb([ - sg(r, scale, gamma), - sg(g, scale, gamma), - sg(b, scale, gamma), - ]) - } } -impl HdrDecoder { - /// Reads Radiance HDR image header from stream `r` - /// if the header is valid, creates HdrDecoder +impl HdrDecoder { + /// Reads Radiance HDR image header from stream ```r``` + /// if the header is valid, creates `HdrDecoder` /// strict mode is enabled - pub fn new(reader: R) -> ImageResult> { + pub fn new(reader: R) -> ImageResult { HdrDecoder::with_strictness(reader, true) } + /// Allows reading old Radiance HDR images + pub fn new_nonstrict(reader: R) -> ImageResult { + Self::with_strictness(reader, false) + } + /// Reads Radiance HDR image header from stream `reader`, /// if the header is valid, creates `HdrDecoder`. /// @@ -400,8 +237,7 @@ UnsupportedError::from_format_and_kind( ImageFormat::Hdr.into(), UnsupportedErrorKind::GenericFeature(format!( - "Image dimensions ({}x{}) are too large", - width, height + "Image dimensions ({width}x{height}) are too large" )), ), )); @@ -425,23 +261,8 @@ self.meta.clone() } - /// Consumes decoder and returns a vector of RGBE8 pixels - pub fn read_image_native(mut self) -> ImageResult> { - // Don't read anything if image is empty - if self.width == 0 || self.height == 0 { - return Ok(vec![]); - } - // expression self.width > 0 && self.height > 0 is true from now to the end of this method - let pixel_count = self.width as usize * self.height as usize; - let mut ret = vec![Default::default(); pixel_count]; - for chunk in ret.chunks_mut(self.width as usize) { - read_scanline(&mut self.r, chunk)?; - } - Ok(ret) - } - /// Consumes decoder and returns a vector of transformed pixels - pub fn read_image_transform T>( + fn read_image_transform T>( mut self, f: F, output_slice: &mut [T], @@ -469,118 +290,35 @@ } Ok(()) } +} - /// Consumes decoder and returns a vector of `Rgb` pixels. - /// scale = 1, gamma = 2.2 - pub fn read_image_ldr(self) -> ImageResult>> { - let mut ret = vec![Rgb([0, 0, 0]); self.width as usize * self.height as usize]; - self.read_image_transform(|pix| pix.to_ldr(), &mut ret[..])?; - Ok(ret) +impl ImageDecoder for HdrDecoder { + fn dimensions(&self) -> (u32, u32) { + (self.meta.width, self.meta.height) } - /// Consumes decoder and returns a vector of `Rgb` pixels. - /// - pub fn read_image_hdr(self) -> ImageResult>> { - let mut ret = vec![Rgb([0.0, 0.0, 0.0]); self.width as usize * self.height as usize]; - self.read_image_transform(|pix| pix.to_hdr(), &mut ret[..])?; - Ok(ret) + fn color_type(&self) -> ColorType { + ColorType::Rgb32F } -} -impl IntoIterator for HdrDecoder { - type Item = ImageResult; - type IntoIter = HdrImageDecoderIterator; - - fn into_iter(self) -> Self::IntoIter { - HdrImageDecoderIterator { - r: self.r, - scanline_cnt: self.height as usize, - buf: vec![Default::default(); self.width as usize], - col: 0, - scanline: 0, - trouble: true, // make first call to `next()` read scanline - error_encountered: false, - } - } -} + fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { + assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); -/// Scanline buffered pixel by pixel iterator -pub struct HdrImageDecoderIterator { - r: R, - scanline_cnt: usize, - buf: Vec, // scanline buffer - col: usize, // current position in scanline - scanline: usize, // current scanline - trouble: bool, // optimization, true indicates that we need to check something - error_encountered: bool, -} + let mut img = vec![Rgb([0.0, 0.0, 0.0]); self.width as usize * self.height as usize]; + self.read_image_transform(|pix| pix.to_hdr(), &mut img[..])?; -impl HdrImageDecoderIterator { - // Advances counter to the next pixel - #[inline] - fn advance(&mut self) { - self.col += 1; - if self.col == self.buf.len() { - self.col = 0; - self.scanline += 1; - self.trouble = true; + for (i, Rgb(data)) in img.into_iter().enumerate() { + buf[(i * 12)..][..12].copy_from_slice(bytemuck::cast_slice(&data)); } - } -} -impl Iterator for HdrImageDecoderIterator { - type Item = ImageResult; - - fn next(&mut self) -> Option { - if !self.trouble { - let ret = self.buf[self.col]; - self.advance(); - Some(Ok(ret)) - } else { - // some condition is pending - if self.buf.is_empty() || self.scanline == self.scanline_cnt { - // No more pixels - return None; - } // no else - if self.error_encountered { - self.advance(); - // Error was encountered. Keep producing errors. - // ImageError can't implement Clone, so just dump some error - return Some(Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::FailedAlready, - )))); - } // no else - if self.col == 0 { - // fill scanline buffer - match read_scanline(&mut self.r, &mut self.buf[..]) { - Ok(_) => { - // no action required - } - Err(err) => { - self.advance(); - self.error_encountered = true; - self.trouble = true; - return Some(Err(err)); - } - } - } // no else - self.trouble = false; - let ret = self.buf[0]; - self.advance(); - Some(Ok(ret)) - } + Ok(()) } - fn size_hint(&self) -> (usize, Option) { - let total_cnt = self.buf.len() * self.scanline_cnt; - let cur_cnt = self.buf.len() * self.scanline + self.col; - let remaining = total_cnt - cur_cnt; - (remaining, Some(remaining)) + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } } -impl ExactSizeIterator for HdrImageDecoderIterator {} - // Precondition: buf.len() > 0 fn read_scanline(r: &mut R, buf: &mut [Rgbe8Pixel]) -> ImageResult<()> { assert!(!buf.is_empty()); @@ -775,7 +513,9 @@ Some((key, val)) => self .custom_attributes .push((key.to_owned(), val.to_owned())), - None => self.custom_attributes.push(("".into(), line.to_owned())), + None => self + .custom_attributes + .push((String::new(), line.to_owned())), } // parse known attributes match maybe_key_value { @@ -806,7 +546,7 @@ .into()); } // no else, skip this line in non-strict mode } - }; + } } Some(("PIXASPECT", val)) => { match val.trim().parse::() { @@ -823,7 +563,7 @@ .into()); } // no else, skip this line in non-strict mode } - }; + } } Some(("COLORCORR", val)) => { let mut rgbcorr = [1.0, 1.0, 1.0]; @@ -940,91 +680,73 @@ } } -#[test] -fn split_at_first_test() { - assert_eq!(split_at_first(&Cow::Owned("".into()), "="), None); - assert_eq!(split_at_first(&Cow::Owned("=".into()), "="), None); - assert_eq!(split_at_first(&Cow::Owned("= ".into()), "="), None); - assert_eq!( - split_at_first(&Cow::Owned(" = ".into()), "="), - Some((" ", " ")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE= ".into()), "="), - Some(("EXPOSURE", " ")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE= =".into()), "="), - Some(("EXPOSURE", " =")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE== =".into()), "=="), - Some(("EXPOSURE", " =")) - ); - assert_eq!(split_at_first(&Cow::Owned("EXPOSURE".into()), ""), None); -} - // Reads input until b"\n" or EOF // Returns vector of read bytes NOT including end of line characters // or return None to indicate end of file -fn read_line_u8(r: &mut R) -> ::std::io::Result>> { +fn read_line_u8(r: &mut R) -> io::Result>> { + // keeping repeated redundant allocations to avoid added complexity of having a `&mut tmp` argument + #[allow(clippy::disallowed_methods)] let mut ret = Vec::with_capacity(16); - match r.read_until(b'\n', &mut ret) { - Ok(0) => Ok(None), - Ok(_) => { - if let Some(&b'\n') = ret[..].last() { - let _ = ret.pop(); + loop { + let mut byte = [0]; + if r.read(&mut byte)? == 0 || byte[0] == b'\n' { + if ret.is_empty() && byte[0] != b'\n' { + return Ok(None); } - Ok(Some(ret)) + return Ok(Some(ret)); } - Err(err) => Err(err), + ret.push(byte[0]); } } -#[test] -fn read_line_u8_test() { - let buf: Vec<_> = (&b"One\nTwo\nThree\nFour\n\n\n"[..]).into(); - let input = &mut ::std::io::Cursor::new(buf); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"One"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Two"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Three"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Four"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); - assert_eq!(read_line_u8(input).unwrap(), None); -} - -/// Helper function for reading raw 3-channel f32 images -pub fn read_raw_file>(path: P) -> ::std::io::Result>> { - use byteorder::{LittleEndian as LE, ReadBytesExt}; - use std::fs::File; - use std::io::BufReader; - - let mut r = BufReader::new(File::open(path)?); - let w = r.read_u32::()? as usize; - let h = r.read_u32::()? as usize; - let c = r.read_u32::()? as usize; - assert_eq!(c, 3); - let cnt = w * h; - let mut ret = Vec::with_capacity(cnt); - for _ in 0..cnt { - let cr = r.read_f32::()?; - let cg = r.read_f32::()?; - let cb = r.read_f32::()?; - ret.push(Rgb([cr, cg, cb])); - } - Ok(ret) -} - #[cfg(test)] -mod test { +mod tests { + use std::{borrow::Cow, io::Cursor}; + use super::*; #[test] + fn split_at_first_test() { + assert_eq!(split_at_first(&Cow::Owned(String::new()), "="), None); + assert_eq!(split_at_first(&Cow::Owned("=".into()), "="), None); + assert_eq!(split_at_first(&Cow::Owned("= ".into()), "="), None); + assert_eq!( + split_at_first(&Cow::Owned(" = ".into()), "="), + Some((" ", " ")) + ); + assert_eq!( + split_at_first(&Cow::Owned("EXPOSURE= ".into()), "="), + Some(("EXPOSURE", " ")) + ); + assert_eq!( + split_at_first(&Cow::Owned("EXPOSURE= =".into()), "="), + Some(("EXPOSURE", " =")) + ); + assert_eq!( + split_at_first(&Cow::Owned("EXPOSURE== =".into()), "=="), + Some(("EXPOSURE", " =")) + ); + assert_eq!(split_at_first(&Cow::Owned("EXPOSURE".into()), ""), None); + } + + #[test] + fn read_line_u8_test() { + let buf: Vec<_> = (&b"One\nTwo\nThree\nFour\n\n\n"[..]).into(); + let input = &mut Cursor::new(buf); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"One"[..]); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Two"[..]); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Three"[..]); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Four"[..]); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); + assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); + assert_eq!(read_line_u8(input).unwrap(), None); + } + + #[test] fn dimension_overflow() { let data = b"#?RADIANCE\nFORMAT=32-bit_rle_rgbe\n\n -Y 4294967295 +X 4294967295"; - assert!(HdrAdapter::new(Cursor::new(data)).is_err()); - assert!(HdrAdapter::new_nonstrict(Cursor::new(data)).is_err()); + assert!(HdrDecoder::new(Cursor::new(data)).is_err()); + assert!(HdrDecoder::new_nonstrict(Cursor::new(data)).is_err()); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,34 +1,80 @@ -use crate::codecs::hdr::{rgbe8, Rgbe8Pixel, SIGNATURE}; -use crate::color::Rgb; -use crate::error::ImageResult; use std::cmp::Ordering; use std::io::{Result, Write}; +use crate::codecs::hdr::{rgbe8, Rgbe8Pixel, SIGNATURE}; +use crate::color::Rgb; +use crate::error::{ImageResult, UnsupportedError, UnsupportedErrorKind}; +use crate::{ExtendedColorType, ImageEncoder, ImageError, ImageFormat}; + /// Radiance HDR encoder pub struct HdrEncoder { w: W, } +impl ImageEncoder for HdrEncoder { + fn write_image( + self, + unaligned_bytes: &[u8], + width: u32, + height: u32, + color_type: ExtendedColorType, + ) -> ImageResult<()> { + match color_type { + ExtendedColorType::Rgb32F => { + let bytes_per_pixel = color_type.bits_per_pixel() as usize / 8; + let rgbe_pixels = unaligned_bytes + .chunks_exact(bytes_per_pixel) + .map(|bytes| to_rgbe8(Rgb::(bytemuck::pod_read_unaligned(bytes)))); + + // the length will be checked inside encode_pixels + self.encode_pixels(rgbe_pixels, width as usize, height as usize) + } + _ => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Hdr.into(), + UnsupportedErrorKind::Color(color_type), + ), + )), + } + } +} + impl HdrEncoder { /// Creates encoder pub fn new(w: W) -> HdrEncoder { HdrEncoder { w } } - /// Encodes the image ```data``` + /// Encodes the image ```rgb``` /// that has dimensions ```width``` and ```height``` - pub fn encode(mut self, data: &[Rgb], width: usize, height: usize) -> ImageResult<()> { - assert!(data.len() >= width * height); + pub fn encode(self, rgb: &[Rgb], width: usize, height: usize) -> ImageResult<()> { + self.encode_pixels(rgb.iter().map(|&rgb| to_rgbe8(rgb)), width, height) + } + + /// Encodes the image ```flattened_rgbe_pixels``` + /// that has dimensions ```width``` and ```height```. + /// The callback must return the color for the given flattened index of the pixel (row major). + fn encode_pixels( + mut self, + mut flattened_rgbe_pixels: impl ExactSizeIterator, + width: usize, + height: usize, + ) -> ImageResult<()> { + assert!( + flattened_rgbe_pixels.len() >= width * height, + "not enough pixels provided" + ); // bonus: this might elide some bounds checks + let w = &mut self.w; w.write_all(SIGNATURE)?; w.write_all(b"\n")?; w.write_all(b"# Rust HDR encoder\n")?; w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n")?; - w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes())?; + w.write_all(format!("-Y {height} +X {width}\n").as_bytes())?; if !(8..=32_768).contains(&width) { - for &pix in data { - write_rgbe8(w, to_rgbe8(pix))?; + for pixel in flattened_rgbe_pixels { + write_rgbe8(w, pixel)?; } } else { // new RLE marker contains scanline width @@ -39,20 +85,22 @@ let mut bufb = vec![0; width]; let mut bufe = vec![0; width]; let mut rle_buf = vec![0; width]; - for scanline in data.chunks(width) { - for ((((r, g), b), e), &pix) in bufr + for _scanline_index in 0..height { + assert!(flattened_rgbe_pixels.len() >= width); // may reduce the bound checks + + for ((((r, g), b), e), pixel) in bufr .iter_mut() .zip(bufg.iter_mut()) .zip(bufb.iter_mut()) .zip(bufe.iter_mut()) - .zip(scanline.iter()) + .zip(&mut flattened_rgbe_pixels) { - let cp = to_rgbe8(pix); - *r = cp.c[0]; - *g = cp.c[1]; - *b = cp.c[2]; - *e = cp.e; + *r = pixel.c[0]; + *g = pixel.c[1]; + *b = pixel.c[2]; + *e = pixel.e; } + write_rgbe8(w, marker)?; // New RLE encoding marker rle_buf.clear(); rle_compress(&bufr[..], &mut rle_buf); @@ -77,6 +125,7 @@ Run(u8, usize), Norun(usize, usize), } + use self::RunOrNot::{Norun, Run}; const RUN_MAX_LEN: usize = 127; @@ -93,7 +142,7 @@ } } -impl<'a> Iterator for RunIterator<'a> { +impl Iterator for RunIterator<'_> { type Item = RunOrNot; fn next(&mut self) -> Option { @@ -132,8 +181,9 @@ } // Combines sequential noruns produced by RunIterator -impl<'a> Iterator for NorunCombineIterator<'a> { +impl Iterator for NorunCombineIterator<'_> { type Item = RunOrNot; + fn next(&mut self) -> Option { loop { match self.prev.take() { @@ -227,7 +277,7 @@ } /// Converts ```Rgb``` into ```Rgbe8Pixel``` -pub fn to_rgbe8(pix: Rgb) -> Rgbe8Pixel { +pub(crate) fn to_rgbe8(pix: Rgb) -> Rgbe8Pixel { let pix = pix.0; let mx = f32::max(pix[0], f32::max(pix[1], pix[2])); if mx <= 0.0 { @@ -303,10 +353,7 @@ // Maximal value is normalized to the range 128..256, thus we have 1/128 precision assert!( rel_dist <= 1.0 / 128.0, - "Relative distance ({}) exceeds 1/128 for {:?} and {:?}", - rel_dist, - c1, - c2 + "Relative distance ({rel_dist}) exceeds 1/128 for {c1:?} and {c2:?}" ); } } @@ -421,8 +468,8 @@ assert_eq!(rsi.next(), Some(Norun(129, 7))); assert_eq!(rsi.next(), None); - let v: Vec<_> = ::std::iter::repeat(()) - .flat_map(|_| (0..2)) + let v: Vec<_> = std::iter::repeat(()) + .flat_map(|()| 0..2) .take(257) .collect(); let mut rsi = NorunCombineIterator::new(&v[..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/hdr/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/hdr/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,7 +6,6 @@ //! //! * //! * -//! mod decoder; mod encoder; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/ico/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/ico/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,12 @@ -use byteorder::{LittleEndian, ReadBytesExt}; -use std::io::{self, Cursor, Read, Seek, SeekFrom}; -use std::marker::PhantomData; -use std::{error, fmt, mem}; +use byteorder_lite::{LittleEndian, ReadBytesExt}; +use std::io::{BufRead, Read, Seek, SeekFrom}; +use std::{error, fmt}; use crate::color::ColorType; use crate::error::{ DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, ImageDecoder, ImageFormat}; +use crate::{ImageDecoder, ImageFormat}; use self::InnerDecoder::*; use crate::codecs::bmp::BmpDecoder; @@ -25,7 +24,7 @@ /// The entry is in PNG format and specified a length that is shorter than PNG header. PngShorterThanHeader, - /// The enclosed PNG is not in RGBA, which is invalid: https://blogs.msdn.microsoft.com/oldnewthing/20101022-00/?p=12473/. + /// The enclosed PNG is not in RGBA, which is invalid: /. PngNotRgba, /// The entry is in BMP format and specified a data size that is not correct for the image and optional mask data. @@ -64,8 +63,7 @@ entry, image, } => f.write_fmt(format_args!( - "Entry{:?} and {}{:?} dimensions do not match!", - entry, format, image + "Entry{entry:?} and {format}{image:?} dimensions do not match!" )), } } @@ -107,12 +105,12 @@ } /// An ico decoder -pub struct IcoDecoder { +pub struct IcoDecoder { selected_entry: DirEntry, inner_decoder: InnerDecoder, } -enum InnerDecoder { +enum InnerDecoder { Bmp(BmpDecoder), Png(Box>), } @@ -142,7 +140,7 @@ image_offset: u32, } -impl IcoDecoder { +impl IcoDecoder { /// Create a new decoder that decodes from the stream ```r``` pub fn new(mut r: R) -> ImageResult> { let entries = read_entries(&mut r)?; @@ -249,7 +247,7 @@ Ok(signature == PNG_SIGNATURE) } - fn decoder(&self, mut r: R) -> ImageResult> { + fn decoder(&self, mut r: R) -> ImageResult> { let is_png = self.is_png(&mut r)?; self.seek_to_start(&mut r)?; @@ -261,25 +259,7 @@ } } -/// Wrapper struct around a `Cursor>` -pub struct IcoReader(Cursor>, PhantomData); -impl Read for IcoReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } - } -} - -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for IcoDecoder { - type Reader = IcoReader; - +impl ImageDecoder for IcoDecoder { fn dimensions(&self) -> (u32, u32) { match self.inner_decoder { Bmp(ref decoder) => decoder.dimensions(), @@ -294,13 +274,6 @@ } } - fn into_reader(self) -> ImageResult { - Ok(IcoReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); match self.inner_decoder { @@ -362,7 +335,7 @@ let data_end = u64::from(self.selected_entry.image_offset) + u64::from(self.selected_entry.image_length); - let mask_row_bytes = ((width + 31) / 32) * 4; + let mask_row_bytes = width.div_ceil(32) * 4; let mask_length = u64::from(mask_row_bytes) * u64::from(height); // data_end should be image_end + the mask length (mask_row_bytes * height). @@ -402,6 +375,10 @@ } } } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } #[cfg(test)] @@ -462,7 +439,7 @@ 0x50, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x37, 0x61, ]; - let decoder = IcoDecoder::new(Cursor::new(&data)).unwrap(); + let decoder = IcoDecoder::new(std::io::Cursor::new(&data)).unwrap(); let mut buf = vec![0; usize::try_from(decoder.total_bytes()).unwrap()]; assert!(decoder.read_image(&mut buf).is_err()); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/ico/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/ico/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/ico/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,10 @@ -use byteorder::{LittleEndian, WriteBytesExt}; +use byteorder_lite::{LittleEndian, WriteBytesExt}; use std::borrow::Cow; use std::io::{self, Write}; -use crate::color::ColorType; -use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; -use crate::image::ImageEncoder; - use crate::codecs::png::PngEncoder; +use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; +use crate::{ExtendedColorType, ImageEncoder}; // Enum value indicating an ICO image (as opposed to a CUR image): const ICO_IMAGE_TYPE: u16 = 1; @@ -28,7 +26,7 @@ width: u8, // Stored as `0 => 256, n => n` height: u8, - color_type: ColorType, + color_type: ExtendedColorType, } impl<'a> IcoFrame<'a> { @@ -39,15 +37,14 @@ encoded_image: impl Into>, width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult { let encoded_image = encoded_image.into(); if !(1..=256).contains(&width) { return Err(ImageError::Parameter(ParameterError::from_kind( ParameterErrorKind::Generic(format!( - "the image width must be `1..=256`, instead width {} was provided", - width, + "the image width must be `1..=256`, instead width {width} was provided", )), ))); } @@ -55,8 +52,7 @@ if !(1..=256).contains(&height) { return Err(ImageError::Parameter(ParameterError::from_kind( ParameterErrorKind::Generic(format!( - "the image height must be `1..=256`, instead height {} was provided", - height, + "the image height must be `1..=256`, instead height {height} was provided", )), ))); } @@ -72,7 +68,12 @@ /// Construct a new `IcoFrame` by encoding `buf` as a PNG /// /// The `width` and `height` must be between 1 and 256 (inclusive) - pub fn as_png(buf: &[u8], width: u32, height: u32, color_type: ColorType) -> ImageResult { + pub fn as_png( + buf: &[u8], + width: u32, + height: u32, + color_type: ExtendedColorType, + ) -> ImageResult { let mut image_data: Vec = Vec::new(); PngEncoder::new(&mut image_data).write_image(buf, width, height, color_type)?; @@ -87,21 +88,6 @@ IcoEncoder { w } } - /// Encodes the image ```image``` that has dimensions ```width``` and - /// ```height``` and ```ColorType``` ```c```. The dimensions of the image - /// must be between 1 and 256 (inclusive) or an error will be returned. - /// - /// Expects data to be big endian. - #[deprecated = "Use `IcoEncoder::write_image` instead. Beware that `write_image` has a different endianness convention"] - pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> { - let mut image_data: Vec = Vec::new(); - #[allow(deprecated)] - PngEncoder::new(&mut image_data).encode(data, width, height, color)?; - - let image = IcoFrame::with_encoded(&image_data, width, height, color)?; - self.encode_images(&[image]) - } - /// Takes some [`IcoFrame`]s and encodes them into an ICO. /// /// `images` is a list of images, usually ordered by dimension, which @@ -151,10 +137,9 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, buf.len() as u64, @@ -181,7 +166,7 @@ w: &mut W, width: u8, height: u8, - color: ColorType, + color: ExtendedColorType, data_start: u32, data_size: u32, ) -> io::Result<()> { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,1288 +1,254 @@ -use std::io::{self, Cursor, Read}; +use std::io::{BufRead, Seek}; use std::marker::PhantomData; -use std::mem; + +use zune_core::bytestream::ZCursor; use crate::color::ColorType; use crate::error::{ - DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, + DecodingError, ImageError, ImageResult, LimitError, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{ImageDecoder, ImageFormat}; +use crate::metadata::Orientation; +use crate::{ImageDecoder, ImageFormat, Limits}; + +type ZuneColorSpace = zune_core::colorspace::ColorSpace; /// JPEG decoder pub struct JpegDecoder { - decoder: jpeg::Decoder, - metadata: jpeg::ImageInfo, + input: Vec, + orig_color_space: ZuneColorSpace, + width: u16, + height: u16, + limits: Limits, + orientation: Option, + // For API compatibility with the previous jpeg_decoder wrapper. + // Can be removed later, which would be an API break. + phantom: PhantomData, } -impl JpegDecoder { +impl JpegDecoder { /// Create a new decoder that decodes from the stream ```r``` pub fn new(r: R) -> ImageResult> { - let mut decoder = jpeg::Decoder::new(r); - - decoder.read_info().map_err(ImageError::from_jpeg)?; - let mut metadata = decoder.info().ok_or_else(|| { - ImageError::Decoding(DecodingError::from_format_hint(ImageFormat::Jpeg.into())) - })?; - - // We convert CMYK data to RGB before returning it to the user. - if metadata.pixel_format == jpeg::PixelFormat::CMYK32 { - metadata.pixel_format = jpeg::PixelFormat::RGB24; - } - - Ok(JpegDecoder { decoder, metadata }) - } - - /// Configure the decoder to scale the image during decoding. - /// - /// This efficiently scales the image by the smallest supported - /// scale factor that produces an image larger than or equal to - /// the requested size in at least one axis. The currently - /// implemented scale factors are 1/8, 1/4, 1/2 and 1. - /// - /// To generate a thumbnail of an exact size, pass the desired - /// size and then scale to the final size using a traditional - /// resampling algorithm. - /// - /// The size of the image to be loaded, with the scale factor - /// applied, is returned. - pub fn scale( - &mut self, - requested_width: u16, - requested_height: u16, - ) -> ImageResult<(u16, u16)> { - let result = self - .decoder - .scale(requested_width, requested_height) - .map_err(ImageError::from_jpeg)?; + let mut input = Vec::new(); + let mut r = r; + r.read_to_end(&mut input)?; + let options = zune_core::options::DecoderOptions::default() + .set_strict_mode(false) + .set_max_width(usize::MAX) + .set_max_height(usize::MAX); + let mut decoder = + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(input.as_slice()), options); + decoder.decode_headers().map_err(ImageError::from_jpeg)?; + // now that we've decoded the headers we can `.unwrap()` + // all these functions that only fail if called before decoding the headers + let (width, height) = decoder.dimensions().unwrap(); + // JPEG can only express dimensions up to 65535x65535, so this conversion cannot fail + let width: u16 = width.try_into().unwrap(); + let height: u16 = height.try_into().unwrap(); + let orig_color_space = decoder.input_colorspace().expect("headers were decoded"); + + // Now configure the decoder color output. + decoder.set_options({ + let requested_color = match orig_color_space { + ZuneColorSpace::RGB + | ZuneColorSpace::RGBA + | ZuneColorSpace::Luma + | ZuneColorSpace::LumaA => orig_color_space, + // Late failure + _ => ZuneColorSpace::RGB, + }; - self.metadata.width = result.0; - self.metadata.height = result.1; + decoder.options().jpeg_set_out_colorspace(requested_color) + }); - Ok(result) + // Limits are disabled by default in the constructor for all decoders + let limits = Limits::no_limits(); + Ok(JpegDecoder { + input, + orig_color_space, + width, + height, + limits, + orientation: None, + phantom: PhantomData, + }) } } -/// Wrapper struct around a `Cursor>` -pub struct JpegReader(Cursor>, PhantomData); -impl Read for JpegReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) +impl ImageDecoder for JpegDecoder { + fn dimensions(&self) -> (u32, u32) { + (u32::from(self.width), u32::from(self.height)) } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } + + fn color_type(&self) -> ColorType { + ColorType::from_jpeg(self.orig_color_space) } -} -impl<'a, R: 'a + Read> ImageDecoder<'a> for JpegDecoder { - type Reader = JpegReader; + fn icc_profile(&mut self) -> ImageResult>> { + let options = zune_core::options::DecoderOptions::default() + .set_strict_mode(false) + .set_max_width(usize::MAX) + .set_max_height(usize::MAX); + let mut decoder = + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&self.input), options); + decoder.decode_headers().map_err(ImageError::from_jpeg)?; + Ok(decoder.icc_profile()) + } + + fn exif_metadata(&mut self) -> ImageResult>> { + let options = zune_core::options::DecoderOptions::default() + .set_strict_mode(false) + .set_max_width(usize::MAX) + .set_max_height(usize::MAX); + let mut decoder = + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&self.input), options); + decoder.decode_headers().map_err(ImageError::from_jpeg)?; + let exif = decoder.exif().cloned(); + + self.orientation = Some( + exif.as_ref() + .and_then(|exif| Orientation::from_exif_chunk(exif)) + .unwrap_or(Orientation::NoTransforms), + ); - fn dimensions(&self) -> (u32, u32) { - ( - u32::from(self.metadata.width), - u32::from(self.metadata.height), - ) + Ok(exif) } - fn color_type(&self) -> ColorType { - ColorType::from_jpeg(self.metadata.pixel_format) - } + fn xmp_metadata(&mut self) -> ImageResult>> { + let options = zune_core::options::DecoderOptions::default() + .set_strict_mode(false) + .set_max_width(usize::MAX) + .set_max_height(usize::MAX); + let mut decoder = + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&self.input), options); + decoder.decode_headers().map_err(ImageError::from_jpeg)?; - fn icc_profile(&mut self) -> Option> { - self.decoder.icc_profile() + Ok(decoder.xmp().cloned()) } - fn into_reader(mut self) -> ImageResult { - let mut data = self.decoder.decode().map_err(ImageError::from_jpeg)?; - data = match self.decoder.info().unwrap().pixel_format { - jpeg::PixelFormat::CMYK32 => cmyk_to_rgb(&data), - _ => data, - }; + fn iptc_metadata(&mut self) -> ImageResult>> { + let options = zune_core::options::DecoderOptions::default() + .set_strict_mode(false) + .set_max_width(usize::MAX) + .set_max_height(usize::MAX); + let mut decoder = + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&self.input), options); + decoder.decode_headers().map_err(ImageError::from_jpeg)?; + + Ok(decoder.iptc().cloned()) + } - Ok(JpegReader(Cursor::new(data), PhantomData)) + fn orientation(&mut self) -> ImageResult { + // `exif_metadata` caches the orientation, so call it if `orientation` hasn't been set yet. + if self.orientation.is_none() { + let _ = self.exif_metadata()?; + } + Ok(self.orientation.unwrap()) } - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); + fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { + let advertised_len = self.total_bytes(); + let actual_len = buf.len() as u64; - let mut data = self.decoder.decode().map_err(ImageError::from_jpeg)?; - data = match self.decoder.info().unwrap().pixel_format { - jpeg::PixelFormat::CMYK32 => cmyk_to_rgb(&data), - _ => data, - }; + if actual_len != advertised_len { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Jpeg.into(), + format!( + "Length of the decoded data {actual_len} \ + doesn't match the advertised dimensions of the image \ + that imply length {advertised_len}" + ), + ))); + } - buf.copy_from_slice(&data); + let mut decoder = new_zune_decoder(&self.input, self.orig_color_space, self.limits); + decoder.decode_into(buf).map_err(ImageError::from_jpeg)?; Ok(()) } -} -fn cmyk_to_rgb(input: &[u8]) -> Vec { - let count = input.len() / 4; - let mut output = vec![0; 3 * count]; - - let in_pixels = input[..4 * count].chunks_exact(4); - let out_pixels = output[..3 * count].chunks_exact_mut(3); - - for (pixel, outp) in in_pixels.zip(out_pixels) { - let c = 255 - u16::from(pixel[0]); - let m = 255 - u16::from(pixel[1]); - let y = 255 - u16::from(pixel[2]); - let k = 255 - u16::from(pixel[3]); - // CMY -> RGB - let r = (k * c) / 255; - let g = (k * m) / 255; - let b = (k * y) / 255; - - outp[0] = r as u8; - outp[1] = g as u8; - outp[2] = b as u8; + fn set_limits(&mut self, limits: Limits) -> ImageResult<()> { + limits.check_support(&crate::LimitSupport::default())?; + let (width, height) = self.dimensions(); + limits.check_dimensions(width, height)?; + self.limits = limits; + Ok(()) } - output + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } impl ColorType { - fn from_jpeg(pixel_format: jpeg::PixelFormat) -> ColorType { - use jpeg::PixelFormat::*; - match pixel_format { - L8 => ColorType::L8, - L16 => ColorType::L16, - RGB24 => ColorType::Rgb8, - CMYK32 => panic!(), + fn from_jpeg(colorspace: ZuneColorSpace) -> ColorType { + let colorspace = to_supported_color_space(colorspace); + use zune_core::colorspace::ColorSpace::*; + match colorspace { + // As of zune-jpeg 0.3.13 the output is always 8-bit, + // but support for 16-bit JPEG might be added in the future. + RGB => ColorType::Rgb8, + RGBA => ColorType::Rgba8, + Luma => ColorType::L8, + LumaA => ColorType::La8, + // to_supported_color_space() doesn't return any of the other variants + _ => unreachable!(), } } } +fn to_supported_color_space(orig: ZuneColorSpace) -> ZuneColorSpace { + use zune_core::colorspace::ColorSpace::*; + match orig { + RGB | RGBA | Luma | LumaA => orig, + // the rest is not supported by `image` so it will be converted to RGB during decoding + _ => RGB, + } +} + +fn new_zune_decoder( + input: &[u8], + orig_color_space: ZuneColorSpace, + limits: Limits, +) -> zune_jpeg::JpegDecoder> { + let target_color_space = to_supported_color_space(orig_color_space); + let mut options = zune_core::options::DecoderOptions::default() + .jpeg_set_out_colorspace(target_color_space) + .set_strict_mode(false); + options = options.set_max_width(match limits.max_image_width { + Some(max_width) => max_width as usize, // u32 to usize never truncates + None => usize::MAX, + }); + options = options.set_max_height(match limits.max_image_height { + Some(max_height) => max_height as usize, // u32 to usize never truncates + None => usize::MAX, + }); + zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(input), options) +} + impl ImageError { - fn from_jpeg(err: jpeg::Error) -> ImageError { - use jpeg::Error::*; + fn from_jpeg(err: zune_jpeg::errors::DecodeErrors) -> ImageError { + use zune_jpeg::errors::DecodeErrors::*; match err { - err @ Format(_) => { - ImageError::Decoding(DecodingError::new(ImageFormat::Jpeg.into(), err)) - } Unsupported(desc) => ImageError::Unsupported(UnsupportedError::from_format_and_kind( ImageFormat::Jpeg.into(), - UnsupportedErrorKind::GenericFeature(format!("{:?}", desc)), + UnsupportedErrorKind::GenericFeature(format!("{desc:?}")), + )), + LargeDimensions(_) => ImageError::Limits(LimitError::from_kind( + crate::error::LimitErrorKind::DimensionError, )), - Io(err) => ImageError::IoError(err), - Internal(err) => { - ImageError::Decoding(DecodingError::new(ImageFormat::Jpeg.into(), err)) - } + err => ImageError::Decoding(DecodingError::new(ImageFormat::Jpeg.into(), err)), } } } #[cfg(test)] mod tests { - #[cfg(feature = "benchmarks")] - extern crate test; - - use super::cmyk_to_rgb; - #[cfg(feature = "benchmarks")] - use test::Bencher; - - #[cfg(feature = "benchmarks")] - const W: usize = 256; - #[cfg(feature = "benchmarks")] - const H: usize = 256; + use super::*; + use std::{fs, io::Cursor}; #[test] - fn cmyk_to_rgb_correct() { - for c in 0..=255 { - for k in 0..=255 { - // Based on R = 255 * (1-C/255) * (1-K/255) - let r = (255.0 - f32::from(c)) * (255.0 - f32::from(k)) / 255.0; - let r_u8 = r as u8; - let convert_r = cmyk_to_rgb(&[c, 0, 0, k])[0]; - let convert_g = cmyk_to_rgb(&[0, c, 0, k])[1]; - let convert_b = cmyk_to_rgb(&[0, 0, c, k])[2]; - - assert_eq!( - convert_r, r_u8, - "c = {}, k = {}, cymk_to_rgb[0] = {}, should be {}", - c, k, convert_r, r_u8 - ); - assert_eq!( - convert_g, r_u8, - "m = {}, k = {}, cymk_to_rgb[1] = {}, should be {}", - c, k, convert_g, r_u8 - ); - assert_eq!( - convert_b, r_u8, - "y = {}, k = {}, cymk_to_rgb[2] = {}, should be {}", - c, k, convert_b, r_u8 - ); - } - } - } - - fn single_pix_correct(cmyk_pix: [u8; 4], rgb_pix_true: [u8; 3]) { - let rgb_pix = cmyk_to_rgb(&cmyk_pix); - assert_eq!( - rgb_pix_true[0], rgb_pix[0], - "With CMYK {:?} expected {:?}, got {:?}", - cmyk_pix, rgb_pix_true, rgb_pix - ); - assert_eq!( - rgb_pix_true[1], rgb_pix[1], - "With CMYK {:?} expected {:?}, got {:?}", - cmyk_pix, rgb_pix_true, rgb_pix - ); - assert_eq!( - rgb_pix_true[2], rgb_pix[2], - "With CMYK {:?} expected {:?}, got {:?}", - cmyk_pix, rgb_pix_true, rgb_pix - ); - } - - #[test] - fn test_assorted_colors() { - let cmyk_pixels = vec![ - [0, 51, 102, 65], - [153, 204, 0, 65], - [0, 0, 0, 67], - [0, 85, 170, 69], - [0, 0, 0, 71], - [0, 0, 0, 73], - [0, 17, 34, 75], - [51, 68, 85, 75], - [102, 119, 136, 75], - [153, 170, 187, 75], - [204, 221, 238, 75], - [0, 0, 0, 77], - [0, 0, 0, 79], - [0, 85, 170, 81], - [0, 0, 0, 83], - [0, 3, 6, 85], - [9, 12, 15, 85], - [18, 21, 24, 85], - [27, 30, 33, 85], - [36, 39, 42, 85], - [45, 48, 51, 85], - [54, 57, 60, 85], - [63, 66, 69, 85], - [72, 75, 78, 85], - [81, 84, 87, 85], - [90, 93, 96, 85], - [99, 102, 105, 85], - [108, 111, 114, 85], - [117, 120, 123, 85], - [126, 129, 132, 85], - [135, 138, 141, 85], - [144, 147, 150, 85], - [153, 156, 159, 85], - [162, 165, 168, 85], - [171, 174, 177, 85], - [180, 183, 186, 85], - [189, 192, 195, 85], - [198, 201, 204, 85], - [207, 210, 213, 85], - [216, 219, 222, 85], - [225, 228, 231, 85], - [234, 237, 240, 85], - [243, 246, 249, 85], - [252, 0, 0, 85], - [0, 85, 170, 87], - [0, 0, 0, 89], - [0, 0, 0, 91], - [0, 85, 170, 93], - [0, 51, 102, 95], - [153, 204, 0, 95], - [0, 0, 0, 97], - [0, 85, 170, 99], - [0, 0, 0, 101], - [0, 0, 0, 103], - [0, 17, 34, 105], - [51, 68, 85, 105], - [102, 119, 136, 105], - [153, 170, 187, 105], - [204, 221, 238, 105], - [0, 0, 0, 107], - [0, 0, 0, 109], - [0, 85, 170, 111], - [0, 0, 0, 113], - [0, 51, 102, 115], - [153, 204, 0, 115], - [0, 85, 170, 117], - [0, 15, 30, 119], - [45, 60, 75, 119], - [90, 105, 120, 119], - [135, 150, 165, 119], - [180, 195, 210, 119], - [225, 240, 0, 119], - [0, 0, 0, 121], - [0, 85, 170, 123], - [0, 51, 102, 125], - [153, 204, 0, 125], - [0, 0, 0, 127], - [0, 0, 0, 128], - [0, 85, 170, 129], - [0, 51, 102, 130], - [153, 204, 0, 130], - [0, 0, 0, 131], - [0, 85, 170, 132], - [0, 0, 0, 133], - [0, 0, 0, 134], - [0, 17, 34, 135], - [51, 68, 85, 135], - [102, 119, 136, 135], - [153, 170, 187, 135], - [204, 221, 238, 135], - [0, 15, 30, 136], - [45, 60, 75, 136], - [90, 105, 120, 136], - [135, 150, 165, 136], - [180, 195, 210, 136], - [225, 240, 0, 136], - [0, 0, 0, 137], - [0, 85, 170, 138], - [0, 0, 0, 139], - [0, 51, 102, 140], - [153, 204, 0, 140], - [0, 85, 170, 141], - [0, 0, 0, 142], - [0, 0, 0, 143], - [0, 85, 170, 144], - [0, 51, 102, 145], - [153, 204, 0, 145], - [0, 0, 0, 146], - [0, 85, 170, 147], - [0, 0, 0, 148], - [0, 0, 0, 149], - [0, 17, 34, 150], - [51, 68, 85, 150], - [102, 119, 136, 150], - [153, 170, 187, 150], - [204, 221, 238, 150], - [0, 0, 0, 151], - [0, 0, 0, 152], - [0, 5, 10, 153], - [15, 20, 25, 153], - [30, 35, 40, 153], - [45, 50, 55, 153], - [60, 65, 70, 153], - [75, 80, 85, 153], - [90, 95, 100, 153], - [105, 110, 115, 153], - [120, 125, 130, 153], - [135, 140, 145, 153], - [150, 155, 160, 153], - [165, 170, 175, 153], - [180, 185, 190, 153], - [195, 200, 205, 153], - [210, 215, 220, 153], - [225, 230, 235, 153], - [240, 245, 250, 153], - [0, 0, 0, 154], - [0, 51, 102, 155], - [153, 204, 0, 155], - [0, 85, 170, 156], - [0, 0, 0, 157], - [0, 0, 0, 158], - [0, 85, 170, 159], - [0, 51, 102, 160], - [153, 204, 0, 160], - [0, 0, 0, 161], - [0, 85, 170, 162], - [0, 0, 0, 163], - [0, 0, 0, 164], - [0, 17, 34, 165], - [51, 68, 85, 165], - [102, 119, 136, 165], - [153, 170, 187, 165], - [204, 221, 238, 165], - [0, 0, 0, 166], - [0, 0, 0, 167], - [0, 85, 170, 168], - [0, 0, 0, 169], - [0, 3, 6, 170], - [9, 12, 15, 170], - [18, 21, 24, 170], - [27, 30, 33, 170], - [36, 39, 42, 170], - [45, 48, 51, 170], - [54, 57, 60, 170], - [63, 66, 69, 170], - [72, 75, 78, 170], - [81, 84, 87, 170], - [90, 93, 96, 170], - [99, 102, 105, 170], - [108, 111, 114, 170], - [117, 120, 123, 170], - [126, 129, 132, 170], - [135, 138, 141, 170], - [144, 147, 150, 170], - [153, 156, 159, 170], - [162, 165, 168, 170], - [171, 174, 177, 170], - [180, 183, 186, 170], - [189, 192, 195, 170], - [198, 201, 204, 170], - [207, 210, 213, 170], - [216, 219, 222, 170], - [225, 228, 231, 170], - [234, 237, 240, 170], - [243, 246, 249, 170], - [252, 0, 0, 170], - [0, 85, 170, 171], - [0, 0, 0, 172], - [0, 0, 0, 173], - [0, 85, 170, 174], - [0, 51, 102, 175], - [153, 204, 0, 175], - [0, 0, 0, 176], - [0, 85, 170, 177], - [0, 0, 0, 178], - [0, 0, 0, 179], - [0, 17, 34, 180], - [51, 68, 85, 180], - [102, 119, 136, 180], - [153, 170, 187, 180], - [204, 221, 238, 180], - [0, 0, 0, 181], - [0, 0, 0, 182], - [0, 85, 170, 183], - [0, 0, 0, 184], - [0, 51, 102, 185], - [153, 204, 0, 185], - [0, 85, 170, 186], - [0, 15, 30, 187], - [45, 60, 75, 187], - [90, 105, 120, 187], - [135, 150, 165, 187], - [180, 195, 210, 187], - [225, 240, 0, 187], - [0, 0, 0, 188], - [0, 85, 170, 189], - [0, 51, 102, 190], - [153, 204, 0, 190], - [0, 0, 0, 191], - [0, 85, 170, 192], - [0, 0, 0, 193], - [0, 0, 0, 194], - [0, 17, 34, 195], - [51, 68, 85, 195], - [102, 119, 136, 195], - [153, 170, 187, 195], - [204, 221, 238, 195], - [0, 0, 0, 196], - [0, 0, 0, 197], - [0, 85, 170, 198], - [0, 0, 0, 199], - [0, 51, 102, 200], - [153, 204, 0, 200], - [0, 85, 170, 201], - [0, 0, 0, 202], - [0, 0, 0, 203], - [0, 5, 10, 204], - [15, 20, 25, 204], - [30, 35, 40, 204], - [45, 50, 55, 204], - [60, 65, 70, 204], - [75, 80, 85, 204], - [90, 95, 100, 204], - [105, 110, 115, 204], - [120, 125, 130, 204], - [135, 140, 145, 204], - [150, 155, 160, 204], - [165, 170, 175, 204], - [180, 185, 190, 204], - [195, 200, 205, 204], - [210, 215, 220, 204], - [225, 230, 235, 204], - [240, 245, 250, 204], - [0, 51, 102, 205], - [153, 204, 0, 205], - [0, 0, 0, 206], - [0, 85, 170, 207], - [0, 0, 0, 208], - [0, 0, 0, 209], - [0, 17, 34, 210], - [51, 68, 85, 210], - [102, 119, 136, 210], - [153, 170, 187, 210], - [204, 221, 238, 210], - [0, 0, 0, 211], - [0, 0, 0, 212], - [0, 85, 170, 213], - [0, 0, 0, 214], - [0, 51, 102, 215], - [153, 204, 0, 215], - [0, 85, 170, 216], - [0, 0, 0, 217], - [0, 0, 0, 218], - [0, 85, 170, 219], - [0, 51, 102, 220], - [153, 204, 0, 220], - [0, 15, 30, 221], - [45, 60, 75, 221], - [90, 105, 120, 221], - [135, 150, 165, 221], - [180, 195, 210, 221], - [225, 240, 0, 221], - [0, 85, 170, 222], - [0, 0, 0, 223], - [0, 0, 0, 224], - [0, 17, 34, 225], - [51, 68, 85, 225], - [102, 119, 136, 225], - [153, 170, 187, 225], - [204, 221, 238, 225], - [0, 0, 0, 226], - [0, 0, 0, 227], - [0, 85, 170, 228], - [0, 0, 0, 229], - [0, 51, 102, 230], - [153, 204, 0, 230], - [0, 85, 170, 231], - [0, 0, 0, 232], - [0, 0, 0, 233], - [0, 85, 170, 234], - [0, 51, 102, 235], - [153, 204, 0, 235], - [0, 0, 0, 236], - [0, 85, 170, 237], - [0, 15, 30, 238], - [45, 60, 75, 238], - [90, 105, 120, 238], - [135, 150, 165, 238], - [180, 195, 210, 238], - [225, 240, 0, 238], - [0, 0, 0, 239], - [0, 17, 34, 240], - [51, 68, 85, 240], - [102, 119, 136, 240], - [153, 170, 187, 240], - [204, 221, 238, 240], - [0, 0, 0, 241], - [0, 0, 0, 242], - [0, 85, 170, 243], - [0, 0, 0, 244], - [0, 51, 102, 245], - [153, 204, 0, 245], - [0, 85, 170, 246], - [0, 0, 0, 247], - [0, 0, 0, 248], - [0, 85, 170, 249], - [0, 51, 102, 250], - [153, 204, 0, 250], - [0, 0, 0, 251], - [0, 85, 170, 252], - [0, 0, 0, 253], - [0, 0, 0, 254], - [5, 15, 25, 102], - [35, 40, 45, 102], - [50, 55, 60, 102], - [65, 70, 75, 102], - [80, 85, 90, 102], - [95, 100, 105, 102], - [110, 115, 120, 102], - [125, 130, 135, 102], - [140, 145, 150, 102], - [155, 160, 165, 102], - [170, 175, 180, 102], - [185, 190, 195, 102], - [200, 205, 210, 102], - [215, 220, 225, 102], - [230, 235, 240, 102], - [245, 250, 0, 102], - [15, 45, 60, 68], - [75, 90, 105, 68], - [120, 135, 150, 68], - [165, 180, 195, 68], - [210, 225, 240, 68], - [17, 34, 51, 45], - [68, 85, 102, 45], - [119, 136, 153, 45], - [170, 187, 204, 45], - [221, 238, 0, 45], - [17, 51, 68, 60], - [85, 102, 119, 60], - [136, 153, 170, 60], - [187, 204, 221, 60], - [238, 0, 0, 60], - [17, 34, 51, 90], - [68, 85, 102, 90], - [119, 136, 153, 90], - [170, 187, 204, 90], - [221, 238, 0, 90], - [17, 34, 51, 120], - [68, 85, 102, 120], - [119, 136, 153, 120], - [170, 187, 204, 120], - [221, 238, 0, 120], - [20, 25, 30, 51], - [35, 40, 45, 51], - [50, 55, 60, 51], - [65, 70, 75, 51], - [80, 85, 90, 51], - [95, 100, 105, 51], - [110, 115, 120, 51], - [125, 130, 135, 51], - [140, 145, 150, 51], - [155, 160, 165, 51], - [170, 175, 180, 51], - [185, 190, 195, 51], - [200, 205, 210, 51], - [215, 220, 225, 51], - [230, 235, 240, 51], - [245, 250, 0, 51], - [45, 60, 75, 17], - [90, 105, 120, 17], - [135, 150, 165, 17], - [180, 195, 210, 17], - [225, 240, 0, 17], - [45, 75, 90, 34], - [105, 120, 135, 34], - [150, 165, 180, 34], - [195, 210, 225, 34], - [240, 0, 0, 34], - [51, 153, 204, 20], - [51, 102, 153, 25], - [204, 0, 0, 25], - [51, 85, 119, 30], - [136, 153, 170, 30], - [187, 204, 221, 30], - [238, 0, 0, 30], - [51, 102, 153, 35], - [204, 0, 0, 35], - [51, 102, 153, 40], - [204, 0, 0, 40], - [51, 102, 153, 50], - [204, 0, 0, 50], - [51, 102, 153, 55], - [204, 0, 0, 55], - [51, 102, 153, 70], - [204, 0, 0, 70], - [51, 102, 153, 80], - [204, 0, 0, 80], - [51, 102, 153, 100], - [204, 0, 0, 100], - [51, 102, 153, 110], - [204, 0, 0, 110], - [65, 67, 69, 0], - [71, 73, 75, 0], - [77, 79, 81, 0], - [83, 85, 87, 0], - [89, 91, 93, 0], - [95, 97, 99, 0], - [101, 103, 105, 0], - [107, 109, 111, 0], - [113, 115, 117, 0], - [119, 121, 123, 0], - [125, 127, 128, 0], - [129, 130, 131, 0], - [132, 133, 134, 0], - [135, 136, 137, 0], - [138, 139, 140, 0], - [141, 142, 143, 0], - [144, 145, 146, 0], - [147, 148, 149, 0], - [150, 151, 152, 0], - [153, 154, 155, 0], - [156, 157, 158, 0], - [159, 160, 161, 0], - [162, 163, 164, 0], - [165, 166, 167, 0], - [168, 169, 170, 0], - [171, 172, 173, 0], - [174, 175, 176, 0], - [177, 178, 179, 0], - [180, 181, 182, 0], - [183, 184, 185, 0], - [186, 187, 188, 0], - [189, 190, 191, 0], - [192, 193, 194, 0], - [195, 196, 197, 0], - [198, 199, 200, 0], - [201, 202, 203, 0], - [204, 205, 206, 0], - [207, 208, 209, 0], - [210, 211, 212, 0], - [213, 214, 215, 0], - [216, 217, 218, 0], - [219, 220, 221, 0], - [222, 223, 224, 0], - [225, 226, 227, 0], - [228, 229, 230, 0], - [231, 232, 233, 0], - [234, 235, 236, 0], - [237, 238, 239, 0], - [240, 241, 242, 0], - [243, 244, 245, 0], - [246, 247, 248, 0], - [249, 250, 251, 0], - [252, 253, 254, 0], - [68, 85, 102, 15], - [119, 136, 153, 15], - [170, 187, 204, 15], - [221, 238, 0, 15], - [85, 170, 0, 3], - [85, 170, 0, 6], - [85, 170, 0, 9], - [85, 170, 0, 12], - [85, 170, 0, 18], - [85, 170, 0, 21], - [85, 170, 0, 24], - [85, 170, 0, 27], - [85, 170, 0, 33], - [85, 170, 0, 36], - [85, 170, 0, 39], - [85, 170, 0, 42], - [85, 170, 0, 48], - [85, 170, 0, 54], - [85, 170, 0, 57], - [85, 170, 0, 63], - [85, 170, 0, 66], - [85, 170, 0, 72], - [85, 170, 0, 78], - [85, 170, 0, 84], - [85, 170, 0, 96], - [85, 170, 0, 108], - [85, 170, 0, 114], - [85, 170, 0, 126], - [102, 153, 204, 5], - [153, 204, 0, 10], - ]; - let rgb_pixels = vec![ - [190, 152, 114], - [76, 38, 190], - [188, 188, 188], - [186, 124, 62], - [184, 184, 184], - [182, 182, 182], - [180, 168, 156], - [144, 132, 120], - [108, 96, 84], - [72, 60, 48], - [36, 24, 12], - [178, 178, 178], - [176, 176, 176], - [174, 116, 58], - [172, 172, 172], - [170, 168, 166], - [164, 162, 160], - [158, 156, 154], - [152, 150, 148], - [146, 144, 142], - [140, 138, 136], - [134, 132, 130], - [128, 126, 124], - [122, 120, 118], - [116, 114, 112], - [110, 108, 106], - [104, 102, 100], - [98, 96, 94], - [92, 90, 88], - [86, 84, 82], - [80, 78, 76], - [74, 72, 70], - [68, 66, 64], - [62, 60, 58], - [56, 54, 52], - [50, 48, 46], - [44, 42, 40], - [38, 36, 34], - [32, 30, 28], - [26, 24, 22], - [20, 18, 16], - [14, 12, 10], - [8, 6, 4], - [2, 170, 170], - [168, 112, 56], - [166, 166, 166], - [164, 164, 164], - [162, 108, 54], - [160, 128, 96], - [64, 32, 160], - [158, 158, 158], - [156, 104, 52], - [154, 154, 154], - [152, 152, 152], - [150, 140, 130], - [120, 110, 100], - [90, 80, 70], - [60, 50, 40], - [30, 20, 10], - [148, 148, 148], - [146, 146, 146], - [144, 96, 48], - [142, 142, 142], - [140, 112, 84], - [56, 28, 140], - [138, 92, 46], - [136, 128, 120], - [112, 104, 96], - [88, 80, 72], - [64, 56, 48], - [40, 32, 24], - [16, 8, 136], - [134, 134, 134], - [132, 88, 44], - [130, 104, 78], - [52, 26, 130], - [128, 128, 128], - [127, 127, 127], - [126, 84, 42], - [125, 100, 75], - [50, 25, 125], - [124, 124, 124], - [123, 82, 41], - [122, 122, 122], - [121, 121, 121], - [120, 112, 104], - [96, 88, 80], - [72, 64, 56], - [48, 40, 32], - [24, 16, 8], - [119, 112, 105], - [98, 91, 84], - [77, 70, 63], - [56, 49, 42], - [35, 28, 21], - [14, 7, 119], - [118, 118, 118], - [117, 78, 39], - [116, 116, 116], - [115, 92, 69], - [46, 23, 115], - [114, 76, 38], - [113, 113, 113], - [112, 112, 112], - [111, 74, 37], - [110, 88, 66], - [44, 22, 110], - [109, 109, 109], - [108, 72, 36], - [107, 107, 107], - [106, 106, 106], - [105, 98, 91], - [84, 77, 70], - [63, 56, 49], - [42, 35, 28], - [21, 14, 7], - [104, 104, 104], - [103, 103, 103], - [102, 100, 98], - [96, 94, 92], - [90, 88, 86], - [84, 82, 80], - [78, 76, 74], - [72, 70, 68], - [66, 64, 62], - [60, 58, 56], - [54, 52, 50], - [48, 46, 44], - [42, 40, 38], - [36, 34, 32], - [30, 28, 26], - [24, 22, 20], - [18, 16, 14], - [12, 10, 8], - [6, 4, 2], - [101, 101, 101], - [100, 80, 60], - [40, 20, 100], - [99, 66, 33], - [98, 98, 98], - [97, 97, 97], - [96, 64, 32], - [95, 76, 57], - [38, 19, 95], - [94, 94, 94], - [93, 62, 31], - [92, 92, 92], - [91, 91, 91], - [90, 84, 78], - [72, 66, 60], - [54, 48, 42], - [36, 30, 24], - [18, 12, 6], - [89, 89, 89], - [88, 88, 88], - [87, 58, 29], - [86, 86, 86], - [85, 84, 83], - [82, 81, 80], - [79, 78, 77], - [76, 75, 74], - [73, 72, 71], - [70, 69, 68], - [67, 66, 65], - [64, 63, 62], - [61, 60, 59], - [58, 57, 56], - [55, 54, 53], - [52, 51, 50], - [49, 48, 47], - [46, 45, 44], - [43, 42, 41], - [40, 39, 38], - [37, 36, 35], - [34, 33, 32], - [31, 30, 29], - [28, 27, 26], - [25, 24, 23], - [22, 21, 20], - [19, 18, 17], - [16, 15, 14], - [13, 12, 11], - [10, 9, 8], - [7, 6, 5], - [4, 3, 2], - [1, 85, 85], - [84, 56, 28], - [83, 83, 83], - [82, 82, 82], - [81, 54, 27], - [80, 64, 48], - [32, 16, 80], - [79, 79, 79], - [78, 52, 26], - [77, 77, 77], - [76, 76, 76], - [75, 70, 65], - [60, 55, 50], - [45, 40, 35], - [30, 25, 20], - [15, 10, 5], - [74, 74, 74], - [73, 73, 73], - [72, 48, 24], - [71, 71, 71], - [70, 56, 42], - [28, 14, 70], - [69, 46, 23], - [68, 64, 60], - [56, 52, 48], - [44, 40, 36], - [32, 28, 24], - [20, 16, 12], - [8, 4, 68], - [67, 67, 67], - [66, 44, 22], - [65, 52, 39], - [26, 13, 65], - [64, 64, 64], - [63, 42, 21], - [62, 62, 62], - [61, 61, 61], - [60, 56, 52], - [48, 44, 40], - [36, 32, 28], - [24, 20, 16], - [12, 8, 4], - [59, 59, 59], - [58, 58, 58], - [57, 38, 19], - [56, 56, 56], - [55, 44, 33], - [22, 11, 55], - [54, 36, 18], - [53, 53, 53], - [52, 52, 52], - [51, 50, 49], - [48, 47, 46], - [45, 44, 43], - [42, 41, 40], - [39, 38, 37], - [36, 35, 34], - [33, 32, 31], - [30, 29, 28], - [27, 26, 25], - [24, 23, 22], - [21, 20, 19], - [18, 17, 16], - [15, 14, 13], - [12, 11, 10], - [9, 8, 7], - [6, 5, 4], - [3, 2, 1], - [50, 40, 30], - [20, 10, 50], - [49, 49, 49], - [48, 32, 16], - [47, 47, 47], - [46, 46, 46], - [45, 42, 39], - [36, 33, 30], - [27, 24, 21], - [18, 15, 12], - [9, 6, 3], - [44, 44, 44], - [43, 43, 43], - [42, 28, 14], - [41, 41, 41], - [40, 32, 24], - [16, 8, 40], - [39, 26, 13], - [38, 38, 38], - [37, 37, 37], - [36, 24, 12], - [35, 28, 21], - [14, 7, 35], - [34, 32, 30], - [28, 26, 24], - [22, 20, 18], - [16, 14, 12], - [10, 8, 6], - [4, 2, 34], - [33, 22, 11], - [32, 32, 32], - [31, 31, 31], - [30, 28, 26], - [24, 22, 20], - [18, 16, 14], - [12, 10, 8], - [6, 4, 2], - [29, 29, 29], - [28, 28, 28], - [27, 18, 9], - [26, 26, 26], - [25, 20, 15], - [10, 5, 25], - [24, 16, 8], - [23, 23, 23], - [22, 22, 22], - [21, 14, 7], - [20, 16, 12], - [8, 4, 20], - [19, 19, 19], - [18, 12, 6], - [17, 16, 15], - [14, 13, 12], - [11, 10, 9], - [8, 7, 6], - [5, 4, 3], - [2, 1, 17], - [16, 16, 16], - [15, 14, 13], - [12, 11, 10], - [9, 8, 7], - [6, 5, 4], - [3, 2, 1], - [14, 14, 14], - [13, 13, 13], - [12, 8, 4], - [11, 11, 11], - [10, 8, 6], - [4, 2, 10], - [9, 6, 3], - [8, 8, 8], - [7, 7, 7], - [6, 4, 2], - [5, 4, 3], - [2, 1, 5], - [4, 4, 4], - [3, 2, 1], - [2, 2, 2], - [1, 1, 1], - [150, 144, 138], - [132, 129, 126], - [123, 120, 117], - [114, 111, 108], - [105, 102, 99], - [96, 93, 90], - [87, 84, 81], - [78, 75, 72], - [69, 66, 63], - [60, 57, 54], - [51, 48, 45], - [42, 39, 36], - [33, 30, 27], - [24, 21, 18], - [15, 12, 9], - [6, 3, 153], - [176, 154, 143], - [132, 121, 110], - [99, 88, 77], - [66, 55, 44], - [33, 22, 11], - [196, 182, 168], - [154, 140, 126], - [112, 98, 84], - [70, 56, 42], - [28, 14, 210], - [182, 156, 143], - [130, 117, 104], - [91, 78, 65], - [52, 39, 26], - [13, 195, 195], - [154, 143, 132], - [121, 110, 99], - [88, 77, 66], - [55, 44, 33], - [22, 11, 165], - [126, 117, 108], - [99, 90, 81], - [72, 63, 54], - [45, 36, 27], - [18, 9, 135], - [188, 184, 180], - [176, 172, 168], - [164, 160, 156], - [152, 148, 144], - [140, 136, 132], - [128, 124, 120], - [116, 112, 108], - [104, 100, 96], - [92, 88, 84], - [80, 76, 72], - [68, 64, 60], - [56, 52, 48], - [44, 40, 36], - [32, 28, 24], - [20, 16, 12], - [8, 4, 204], - [196, 182, 168], - [154, 140, 126], - [112, 98, 84], - [70, 56, 42], - [28, 14, 238], - [182, 156, 143], - [130, 117, 104], - [91, 78, 65], - [52, 39, 26], - [13, 221, 221], - [188, 94, 47], - [184, 138, 92], - [46, 230, 230], - [180, 150, 120], - [105, 90, 75], - [60, 45, 30], - [15, 225, 225], - [176, 132, 88], - [44, 220, 220], - [172, 129, 86], - [43, 215, 215], - [164, 123, 82], - [41, 205, 205], - [160, 120, 80], - [40, 200, 200], - [148, 111, 74], - [37, 185, 185], - [140, 105, 70], - [35, 175, 175], - [124, 93, 62], - [31, 155, 155], - [116, 87, 58], - [29, 145, 145], - [190, 188, 186], - [184, 182, 180], - [178, 176, 174], - [172, 170, 168], - [166, 164, 162], - [160, 158, 156], - [154, 152, 150], - [148, 146, 144], - [142, 140, 138], - [136, 134, 132], - [130, 128, 127], - [126, 125, 124], - [123, 122, 121], - [120, 119, 118], - [117, 116, 115], - [114, 113, 112], - [111, 110, 109], - [108, 107, 106], - [105, 104, 103], - [102, 101, 100], - [99, 98, 97], - [96, 95, 94], - [93, 92, 91], - [90, 89, 88], - [87, 86, 85], - [84, 83, 82], - [81, 80, 79], - [78, 77, 76], - [75, 74, 73], - [72, 71, 70], - [69, 68, 67], - [66, 65, 64], - [63, 62, 61], - [60, 59, 58], - [57, 56, 55], - [54, 53, 52], - [51, 50, 49], - [48, 47, 46], - [45, 44, 43], - [42, 41, 40], - [39, 38, 37], - [36, 35, 34], - [33, 32, 31], - [30, 29, 28], - [27, 26, 25], - [24, 23, 22], - [21, 20, 19], - [18, 17, 16], - [15, 14, 13], - [12, 11, 10], - [9, 8, 7], - [6, 5, 4], - [3, 2, 1], - [176, 160, 144], - [128, 112, 96], - [80, 64, 48], - [32, 16, 240], - [168, 84, 252], - [166, 83, 249], - [164, 82, 246], - [162, 81, 243], - [158, 79, 237], - [156, 78, 234], - [154, 77, 231], - [152, 76, 228], - [148, 74, 222], - [146, 73, 219], - [144, 72, 216], - [142, 71, 213], - [138, 69, 207], - [134, 67, 201], - [132, 66, 198], - [128, 64, 192], - [126, 63, 189], - [122, 61, 183], - [118, 59, 177], - [114, 57, 171], - [106, 53, 159], - [98, 49, 147], - [94, 47, 141], - [86, 43, 129], - [150, 100, 50], - [98, 49, 245], - ]; - for (&cmyk_pixel, rgb_pixel) in cmyk_pixels.iter().zip(rgb_pixels) { - single_pix_correct(cmyk_pixel, rgb_pixel); - } - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_cmyk_to_rgb(b: &mut Bencher) { - let mut v = Vec::with_capacity(W * H * 4); - for c in 0..=255 { - for k in 0..=255 { - v.push(c as u8); - v.push(0); - v.push(0); - v.push(k as u8); - } - } - - b.iter(|| { - cmyk_to_rgb(&v); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_cmyk_to_rgb_single(b: &mut Bencher) { - b.iter(|| { - cmyk_to_rgb(&[128, 128, 128, 128]); - }); + fn test_exif_orientation() { + let data = fs::read("tests/images/jpg/portrait_2.jpg").unwrap(); + let mut decoder = JpegDecoder::new(Cursor::new(data)).unwrap(); + assert_eq!(decoder.orientation().unwrap(), Orientation::FlipHorizontal); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,22 @@ #![allow(clippy::too_many_arguments)] - use std::borrow::Cow; use std::io::{self, Write}; +use std::{error, fmt}; use crate::error::{ - ImageError, ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, - UnsupportedErrorKind, + EncodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{ImageEncoder, ImageFormat}; +use crate::traits::PixelWithColorType; use crate::utils::clamp; -use crate::{ColorType, GenericImageView, ImageBuffer, Luma, LumaA, Pixel, Rgb, Rgba}; +use crate::{ + ColorType, DynamicImage, ExtendedColorType, GenericImageView, ImageBuffer, ImageEncoder, + ImageFormat, Luma, Pixel, Rgb, +}; + +use num_traits::ToPrimitive; use super::entropy::build_huff_lut_const; use super::transform; -use crate::traits::PixelWithColorType; // Markers // Baseline DCT @@ -30,6 +33,8 @@ static DQT: u8 = 0xDB; // Application segments start and end static APP0: u8 = 0xE0; +static APP1: u8 = 0xE1; +static APP2: u8 = 0xE2; // section K.1 // table K.1 @@ -149,6 +154,10 @@ 53, 60, 61, 54, 47, 55, 62, 63, ]; +// E x i f \0 \0 +/// The header for an EXIF APP1 segment +static EXIF_HEADER: [u8; 6] = [0x45, 0x78, 0x69, 0x66, 0x00, 0x00]; + /// A representation of a JPEG component #[derive(Copy, Clone)] struct Component { @@ -219,9 +228,7 @@ fn huffman_encode(&mut self, val: u8, table: &[(u8, u16); 256]) -> io::Result<()> { let (size, code) = table[val as usize]; - if size > 16 { - panic!("bad huffman value"); - } + assert!(size <= 16, "bad huffman value"); self.write_bits(code, size) } @@ -316,6 +323,7 @@ /// Creates the most common pixel density type: /// the horizontal and the vertical density are equal, /// and measured in pixels per inch. + #[must_use] pub fn dpi(density: u16) -> Self { PixelDensity { density: (density, density), @@ -334,6 +342,32 @@ } } +/// Errors that can occur when encoding a JPEG image +#[derive(Debug, Copy, Clone)] +enum EncoderError { + /// JPEG does not support this size + InvalidSize(u32, u32), +} + +impl fmt::Display for EncoderError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + EncoderError::InvalidSize(w, h) => f.write_fmt(format_args!( + "Invalid image size ({w} x {h}) to encode as JPEG: \ + width and height must be >= 1 and <= 65535" + )), + } + } +} + +impl From for ImageError { + fn from(e: EncoderError) -> ImageError { + ImageError::Encoding(EncodingError::new(ImageFormat::Jpeg.into(), e)) + } +} + +impl error::Error for EncoderError {} + /// The representation of a JPEG encoder pub struct JpegEncoder { writer: BitWriter, @@ -347,6 +381,9 @@ chroma_actable: Cow<'static, [(u8, u16); 256]>, pixel_density: PixelDensity, + + icc_profile: Vec, + exif: Vec, } impl JpegEncoder { @@ -398,15 +435,11 @@ }; let mut tables = vec![STD_LUMA_QTABLE, STD_CHROMA_QTABLE]; - tables.iter_mut().for_each(|t| { - t.iter_mut().for_each(|v| { - *v = clamp( - (u32::from(*v) * scale + 50) / 100, - 1, - u32::from(u8::max_value()), - ) as u8; - }) - }); + for t in tables.iter_mut() { + for v in t.iter_mut() { + *v = clamp((u32::from(*v) * scale + 50) / 100, 1, u32::from(u8::MAX)) as u8; + } + } JpegEncoder { writer: BitWriter::new(w), @@ -420,6 +453,9 @@ chroma_actable: Cow::Borrowed(&STD_CHROMA_AC_HUFF_LUT), pixel_density: PixelDensity::default(), + + icc_profile: Vec::new(), + exif: Vec::new(), } } @@ -445,10 +481,9 @@ image: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, image.len() as u64, @@ -457,35 +492,35 @@ ); match color_type { - ColorType::L8 => { + ExtendedColorType::L8 => { let image: ImageBuffer, _> = ImageBuffer::from_raw(width, height, image).unwrap(); self.encode_image(&image) } - ColorType::La8 => { - let image: ImageBuffer, _> = - ImageBuffer::from_raw(width, height, image).unwrap(); - self.encode_image(&image) - } - ColorType::Rgb8 => { + ExtendedColorType::Rgb8 => { let image: ImageBuffer, _> = ImageBuffer::from_raw(width, height, image).unwrap(); self.encode_image(&image) } - ColorType::Rgba8 => { - let image: ImageBuffer, _> = - ImageBuffer::from_raw(width, height, image).unwrap(); - self.encode_image(&image) - } _ => Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Jpeg.into(), - UnsupportedErrorKind::Color(color_type.into()), + UnsupportedErrorKind::Color(color_type), ), )), } } + fn write_exif(&mut self) -> ImageResult<()> { + if !self.exif.is_empty() { + let mut formatted = EXIF_HEADER.to_vec(); + formatted.extend_from_slice(&self.exif); + self.writer.write_segment(APP1, &formatted)?; + } + + Ok(()) + } + /// Encodes the given image. /// /// As a special feature this does not require the whole image to be present in memory at the @@ -503,28 +538,27 @@ let color_type = I::Pixel::COLOR_TYPE; let num_components = if n == 1 || n == 2 { 1 } else { 3 }; + let (width, height) = match (u16::try_from(image.width()), u16::try_from(image.height())) { + (Ok(w @ 1..), Ok(h @ 1..)) => (w, h), + _ => return Err(EncoderError::InvalidSize(image.width(), image.height()).into()), + }; + self.writer.write_marker(SOI)?; let mut buf = Vec::new(); build_jfif_header(&mut buf, self.pixel_density); self.writer.write_segment(APP0, &buf)?; + self.write_exif()?; + + // Write ICC profile chunks if present + self.write_icc_profile_chunks()?; build_frame_header( &mut buf, 8, - // TODO: not idiomatic yet. Should be an EncodingError and mention jpg. Further it - // should check dimensions prior to writing. - u16::try_from(image.width()).map_err(|_| { - ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - )) - })?, - u16::try_from(image.height()).map_err(|_| { - ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - )) - })?, + width, + height, &self.components[..num_components], ); self.writer.write_segment(SOF0, &buf)?; @@ -578,7 +612,7 @@ build_scan_header(&mut buf, &self.components[..num_components]); self.writer.write_segment(SOS, &buf)?; - if color_type.has_color() { + if ExtendedColorType::Rgb8 == color_type || ExtendedColorType::Rgba8 == color_type { self.encode_rgb(image) } else { self.encode_gray(image) @@ -664,6 +698,43 @@ Ok(()) } + + fn write_icc_profile_chunks(&mut self) -> io::Result<()> { + if self.icc_profile.is_empty() { + return Ok(()); + } + + const MAX_CHUNK_SIZE: usize = 65533 - 14; + const MAX_CHUNK_COUNT: usize = 255; + const MAX_ICC_PROFILE_SIZE: usize = MAX_CHUNK_SIZE * MAX_CHUNK_COUNT; + + if self.icc_profile.len() > MAX_ICC_PROFILE_SIZE { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "ICC profile too large", + )); + } + + let chunk_iter = self.icc_profile.chunks(MAX_CHUNK_SIZE); + let num_chunks = chunk_iter.len() as u8; + let mut segment = Vec::new(); + + for (i, chunk) in chunk_iter.enumerate() { + let chunk_number = (i + 1) as u8; + let length = 14 + chunk.len(); + + segment.clear(); + segment.reserve(length); + segment.extend_from_slice(b"ICC_PROFILE\0"); + segment.push(chunk_number); + segment.push(num_chunks); + segment.extend_from_slice(chunk); + + self.writer.write_segment(APP2, &segment)?; + } + + Ok(()) + } } impl ImageEncoder for JpegEncoder { @@ -673,10 +744,33 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { self.encode(buf, width, height, color_type) } + + fn set_icc_profile(&mut self, icc_profile: Vec) -> Result<(), UnsupportedError> { + self.icc_profile = icc_profile; + Ok(()) + } + + fn set_exif_metadata(&mut self, exif: Vec) -> Result<(), UnsupportedError> { + self.exif = exif; + Ok(()) + } + + fn make_compatible_img( + &self, + _: crate::io::encoder::MethodSealedToImage, + img: &DynamicImage, + ) -> Option { + use ColorType::*; + match img.color() { + L8 | Rgb8 => None, + La8 | L16 | La16 => Some(img.to_luma8().into()), + Rgba8 | Rgb16 | Rgb32F | Rgba16 | Rgba32F => Some(img.to_rgb8().into()), + } + } } fn build_jfif_header(m: &mut Vec, density: PixelDensity) { @@ -711,7 +805,7 @@ m.extend_from_slice(&width.to_be_bytes()); m.push(components.len() as u8); - for &comp in components.iter() { + for &comp in components { let hv = (comp.h << 4) | comp.v; m.extend_from_slice(&[comp.id, hv, comp.tq]); } @@ -722,7 +816,7 @@ m.push(components.len() as u8); - for &comp in components.iter() { + for &comp in components { let tables = (comp.dc_table << 4) | comp.ac_table; m.extend_from_slice(&[comp.id, tables]); } @@ -787,19 +881,36 @@ #[inline] fn rgb_to_ycbcr(pixel: P) -> (u8, u8, u8) { - use crate::traits::Primitive; - use num_traits::cast::ToPrimitive; - let [r, g, b] = pixel.to_rgb().0; - let max: f32 = P::Subpixel::DEFAULT_MAX_VALUE.to_f32().unwrap(); - let r: f32 = r.to_f32().unwrap(); - let g: f32 = g.to_f32().unwrap(); - let b: f32 = b.to_f32().unwrap(); - - // Coefficients from JPEG File Interchange Format (Version 1.02), multiplied for 255 maximum. - let y = 76.245 / max * r + 149.685 / max * g + 29.07 / max * b; - let cb = -43.0185 / max * r - 84.4815 / max * g + 127.5 / max * b + 128.; - let cr = 127.5 / max * r - 106.7685 / max * g - 20.7315 / max * b + 128.; + let r: i32 = i32::from(r.to_u8().unwrap()); + let g: i32 = i32::from(g.to_u8().unwrap()); + let b: i32 = i32::from(b.to_u8().unwrap()); + + /* + JPEG RGB -> YCbCr is defined as following equations using Bt.601 Full Range matrix: + Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + 128 + Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + 128 + + To avoid using slow floating point conversion is done in fixed point, + using following coefficients with rounding to nearest integer mode: + */ + + const C_YR: i32 = 19595; // 0.29900 = 19595 * 2^-16 + const C_YG: i32 = 38469; // 0.58700 = 38469 * 2^-16 + const C_YB: i32 = 7471; // 0.11400 = 7471 * 2^-16 + const Y_ROUNDING: i32 = (1 << 15) - 1; // + 0.5 to perform rounding shift right in-place + const C_UR: i32 = 11059; // 0.16874 = 11059 * 2^-16 + const C_UG: i32 = 21709; // 0.33126 = 21709 * 2^-16 + const C_UB: i32 = 32768; // 0.5 = 32768 * 2^-16 + const UV_BIAS_ROUNDING: i32 = (128 * (1 << 16)) + ((1 << 15) - 1); // 128 + 0.5 = ((128 * (1 << 16)) + ((1 << 15) - 1)) * 2^-16 ; + 0.5 to perform rounding shift right in-place + const C_VR: i32 = C_UB; // 0.5 = 32768 * 2^-16 + const C_VG: i32 = 27439; // 0.41869 = 27439 * 2^-16 + const C_VB: i32 = 5329; // 0.08131409 = 5329 * 2^-16 + + let y = (C_YR * r + C_YG * g + C_YB * b + Y_ROUNDING) >> 16; + let cb = (-C_UR * r - C_UG * g + C_UB * b + UV_BIAS_ROUNDING) >> 16; + let cr = (C_VR * r - C_VG * g - C_VB * b + UV_BIAS_ROUNDING) >> 16; (y as u8, cb as u8, cr as u8) } @@ -855,10 +966,8 @@ #[cfg(feature = "benchmarks")] use test::Bencher; - use crate::color::ColorType; - use crate::error::ParameterErrorKind::DimensionMismatch; - use crate::image::ImageDecoder; - use crate::{ImageEncoder, ImageError}; + use crate::{ColorType, DynamicImage, ExtendedColorType, ImageEncoder, ImageError}; + use crate::{ImageDecoder as _, ImageFormat}; use super::super::JpegDecoder; use super::{ @@ -887,7 +996,7 @@ { let encoder = JpegEncoder::new_with_quality(&mut encoded_img, 100); encoder - .write_image(&img, 1, 1, ColorType::Rgb8) + .write_image(&img, 1, 1, ExtendedColorType::Rgb8) .expect("Could not encode image"); } @@ -913,7 +1022,7 @@ { let encoder = JpegEncoder::new_with_quality(&mut encoded_img, 100); encoder - .write_image(&img[..], 2, 2, ColorType::L8) + .write_image(&img[..], 2, 2, ExtendedColorType::L8) .expect("Could not encode image"); } @@ -963,18 +1072,12 @@ // Try to encode an image that is too large let mut encoded = Vec::new(); let encoder = JpegEncoder::new_with_quality(&mut encoded, 100); - let result = encoder.write_image(&img, 65_536, 1, ColorType::L8); - match result { - Err(ImageError::Parameter(err)) => { - assert_eq!(err.kind(), DimensionMismatch) - } - other => { - panic!( - "Encoding an image that is too large should return a DimensionError \ - it returned {:?} instead", - other - ) - } + let result = encoder.write_image(&img, 65_536, 1, ExtendedColorType::L8); + if !matches!(result, Err(ImageError::Encoding(_))) { + panic!( + "Encoding an image that is too large should return an \ + EncodingError; it returned {result:?} instead" + ) } } @@ -1015,7 +1118,7 @@ build_frame_header(&mut buf, 5, 100, 150, &components); assert_eq!( buf, - [5, 0, 150, 0, 100, 2, 1, 1 << 4 | 1, 5, 2, 1 << 4 | 1, 4] + [5, 0, 150, 0, 100, 2, 1, (1 << 4) | 1, 5, 2, (1 << 4) | 1, 4] ); } @@ -1043,7 +1146,7 @@ }, ]; build_scan_header(&mut buf, &components); - assert_eq!(buf, [2, 1, 5 << 4 | 5, 2, 4 << 4 | 4, 0, 63, 0]); + assert_eq!(buf, [2, 1, (5 << 4) | 5, 2, (4 << 4) | 4, 0, 63, 0]); } #[test] @@ -1073,7 +1176,31 @@ let mut expected = vec![]; expected.push(1); expected.extend_from_slice(&[0; 64]); - assert_eq!(buf, expected) + assert_eq!(buf, expected); + } + + #[test] + fn check_color_types() { + const ALL: &[ColorType] = &[ + ColorType::L8, + ColorType::L16, + ColorType::La8, + ColorType::Rgb8, + ColorType::Rgba8, + ColorType::La16, + ColorType::Rgb16, + ColorType::Rgba16, + ColorType::Rgb32F, + ColorType::Rgba32F, + ]; + + for color in ALL { + let image = DynamicImage::new(1, 1, *color); + + image + .write_to(&mut Cursor::new(vec![]), ImageFormat::Jpeg) + .expect("supported or converted"); + } } #[cfg(feature = "benchmarks")] @@ -1082,6 +1209,20 @@ b.iter(|| { let mut y = vec![]; let _x = JpegEncoder::new(&mut y); - }) + }); } } + +// Tests regressions of `encode_image` against #1412, confusion about the subimage's position vs. +// dimensions. (We no longer have a position, four `u32` returns was confusing). +#[test] +fn sub_image_encoder_regression_1412() { + let image = DynamicImage::new_rgb8(1280, 720); + let subimg = crate::imageops::crop_imm(&image, 0, 358, 425, 361); + + let mut encoded_crop = vec![]; + let mut encoder = JpegEncoder::new(&mut encoded_crop); + + let result = encoder.encode_image(&*subimg); + assert!(result.is_ok(), "Failed to encode subimage: {result:?}"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/jpeg/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/jpeg/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,7 +5,6 @@ //! //! # Related Links //! * - The JPEG specification -//! pub use self::decoder::JpegDecoder; pub use self::encoder::{JpegEncoder, PixelDensity, PixelDensityUnit}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/openexr.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/openexr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/openexr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/openexr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -22,13 +22,12 @@ //! - (chroma) subsampling not supported yet by the exr library use exr::prelude::*; -use crate::error::{DecodingError, EncodingError, ImageFormatHint}; -use crate::image::decoder_to_vec; +use crate::error::{DecodingError, ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; use crate::{ ColorType, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageFormat, ImageResult, - Progress, }; -use std::io::{Cursor, Read, Seek, Write}; + +use std::io::{BufRead, Seek, Write}; /// An OpenEXR decoder. Immediately reads the meta data from the file. #[derive(Debug)] @@ -46,7 +45,7 @@ alpha_present_in_file: bool, } -impl OpenExrDecoder { +impl OpenExrDecoder { /// Create a decoder. Consumes the first few bytes of the source to extract image dimensions. /// Assumes the reader is buffered. In most cases, /// you should wrap your reader in a `BufReader` for best performance. @@ -105,9 +104,7 @@ } } -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for OpenExrDecoder { - type Reader = Cursor>; - +impl ImageDecoder for OpenExrDecoder { fn dimensions(&self) -> (u32, u32) { let size = self .selected_exr_header() @@ -134,27 +131,9 @@ } } - /// Use `read_image` instead if possible, - /// as this method creates a whole new buffer just to contain the entire image. - fn into_reader(self) -> ImageResult { - Ok(Cursor::new(decoder_to_vec(self)?)) - } - - fn scanline_bytes(&self) -> u64 { - // we cannot always read individual scan lines for every file, - // as the tiles or lines in the file could be in random or reversed order. - // therefore we currently read all lines at once - // Todo: optimize for specific exr.line_order? - self.total_bytes() - } - // reads with or without alpha, depending on `self.alpha_preference` and `self.alpha_present_in_file` - fn read_image_with_progress( - self, - unaligned_bytes: &mut [u8], - progress_callback: F, - ) -> ImageResult<()> { - let blocks_in_header = self.selected_exr_header().chunk_count as u64; + fn read_image(self, unaligned_bytes: &mut [u8]) -> ImageResult<()> { + let _blocks_in_header = self.selected_exr_header().chunk_count as u64; let channel_count = self.color_type().channel_count() as usize; let display_window = self.selected_exr_header().shared_attributes.display_window; @@ -176,9 +155,10 @@ // therefore data is too small, so it is invalid. .unwrap_or(true); - if has_invalid_size_or_overflowed { - panic!("byte buffer not large enough for the specified dimensions and f32 pixels"); - } + assert!( + !has_invalid_size_or_overflowed, + "byte buffer not large enough for the specified dimensions and f32 pixels" + ); } let result = read() @@ -212,14 +192,6 @@ ) .first_valid_layer() // TODO select exact layer by self.header_index? .all_attributes() - .on_progress(|progress| { - progress_callback( - Progress::new( - (progress * blocks_in_header as f64) as u64, - blocks_in_header, - ), // TODO precision errors? - ); - }) .from_chunks(self.exr_reader) .map_err(to_image_err)?; @@ -232,6 +204,10 @@ )); Ok(()) } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } /// Write a raw byte buffer of pixels, @@ -245,37 +221,15 @@ unaligned_bytes: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { let width = width as usize; let height = height as usize; - - { - // check whether the buffer is large enough for the specified dimensions - let expected_byte_count = width - .checked_mul(height) - .and_then(|size| size.checked_mul(color_type.bytes_per_pixel() as usize)); - - // if the width and height does not match the length of the bytes, the arguments are invalid - let has_invalid_size_or_overflowed = expected_byte_count - .map(|expected_byte_count| unaligned_bytes.len() < expected_byte_count) - // otherwise, size calculation overflowed, is bigger than memory, - // therefore data is too small, so it is invalid. - .unwrap_or(true); - - if has_invalid_size_or_overflowed { - return Err(ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::OpenExr), - "byte buffer not large enough for the specified dimensions and f32 pixels", - ))); - } - } - - let bytes_per_pixel = color_type.bytes_per_pixel() as usize; + let bytes_per_pixel = color_type.bits_per_pixel() as usize / 8; match color_type { - ColorType::Rgb32F => { - exr::prelude::Image // TODO compression method zip?? + ExtendedColorType::Rgb32F => { + Image // TODO compression method zip?? ::from_channels( (width, height), SpecificChannels::rgb(|pixel: Vec2| { @@ -295,8 +249,8 @@ .map_err(to_image_err)?; } - ColorType::Rgba32F => { - exr::prelude::Image // TODO compression method zip?? + ExtendedColorType::Rgba32F => { + Image // TODO compression method zip?? ::from_channels( (width, height), SpecificChannels::rgba(|pixel: Vec2| { @@ -318,13 +272,12 @@ // TODO other color types and channel types unsupported_color_type => { - return Err(ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::OpenExr), - format!( - "writing color type {:?} not yet supported", - unsupported_color_type + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::OpenExr.into(), + UnsupportedErrorKind::Color(unsupported_color_type), ), - ))) + )) } } @@ -358,10 +311,9 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, buf.len() as u64, @@ -384,12 +336,14 @@ mod test { use super::*; - use std::io::BufReader; + use std::fs::File; + use std::io::{BufReader, Cursor}; use std::path::{Path, PathBuf}; - use crate::buffer_::{Rgb32FImage, Rgba32FImage}; use crate::error::{LimitError, LimitErrorKind}; - use crate::{ImageBuffer, Rgb, Rgba}; + use crate::images::buffer::{Rgb32FImage, Rgba32FImage}; + use crate::io::free_functions::decoder_to_vec; + use crate::{DynamicImage, ImageBuffer, Rgb, Rgba}; const BASE_PATH: &[&str] = &[".", "tests", "images", "exr"]; @@ -402,7 +356,7 @@ bytemuck::cast_slice(image.as_raw().as_slice()), image.width(), image.height(), - ColorType::Rgb32F, + ExtendedColorType::Rgb32F, ) } @@ -415,22 +369,22 @@ bytemuck::cast_slice(image.as_raw().as_slice()), image.width(), image.height(), - ColorType::Rgba32F, + ExtendedColorType::Rgba32F, ) } /// Read the file from the specified path into an `Rgba32FImage`. fn read_as_rgba_image_from_file(path: impl AsRef) -> ImageResult { - read_as_rgba_image(BufReader::new(std::fs::File::open(path)?)) + read_as_rgba_image(BufReader::new(File::open(path)?)) } /// Read the file from the specified path into an `Rgb32FImage`. fn read_as_rgb_image_from_file(path: impl AsRef) -> ImageResult { - read_as_rgb_image(BufReader::new(std::fs::File::open(path)?)) + read_as_rgb_image(BufReader::new(File::open(path)?)) } /// Read the file from the specified path into an `Rgb32FImage`. - fn read_as_rgb_image(read: impl Read + Seek) -> ImageResult { + fn read_as_rgb_image(read: impl BufRead + Seek) -> ImageResult { let decoder = OpenExrDecoder::with_alpha_preference(read, Some(false))?; let (width, height) = decoder.dimensions(); let buffer: Vec = decoder_to_vec(decoder)?; @@ -444,7 +398,7 @@ } /// Read the file from the specified path into an `Rgba32FImage`. - fn read_as_rgba_image(read: impl Read + Seek) -> ImageResult { + fn read_as_rgba_image(read: impl BufRead + Seek) -> ImageResult { let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?; let (width, height) = decoder.dimensions(); let buffer: Vec = decoder_to_vec(decoder)?; @@ -465,34 +419,30 @@ #[cfg(feature = "hdr")] { - let folder = BASE_PATH.iter().collect::(); - let reference_path = folder.clone().join("overexposed gradient.hdr"); - let exr_path = folder - .clone() - .join("overexposed gradient - data window equals display window.exr"); + use crate::codecs::hdr::HdrDecoder; - let hdr: Vec> = crate::codecs::hdr::HdrDecoder::new(std::io::BufReader::new( - std::fs::File::open(reference_path).unwrap(), - )) - .unwrap() - .read_image_hdr() - .unwrap(); + let folder = BASE_PATH.iter().collect::(); + let reference_path = folder.join("overexposed gradient.hdr"); + let exr_path = + folder.join("overexposed gradient - data window equals display window.exr"); + + let hdr_decoder = + HdrDecoder::new(BufReader::new(File::open(reference_path).unwrap())).unwrap(); + let hdr: Rgb32FImage = match DynamicImage::from_decoder(hdr_decoder).unwrap() { + DynamicImage::ImageRgb32F(image) => image, + _ => panic!("expected rgb32f image"), + }; let exr_pixels: Rgb32FImage = read_as_rgb_image_from_file(exr_path).unwrap(); - assert_eq!( - exr_pixels.dimensions().0 * exr_pixels.dimensions().1, - hdr.len() as u32 - ); + assert_eq!(exr_pixels.dimensions(), hdr.dimensions()); - for (expected, found) in hdr.iter().zip(exr_pixels.pixels()) { + for (expected, found) in hdr.pixels().zip(exr_pixels.pixels()) { for (expected, found) in expected.0.iter().zip(found.0.iter()) { // the large tolerance seems to be caused by // the RGBE u8x4 pixel quantization of the hdr image format assert!( (expected - found).abs() < 0.1, - "expected {}, found {}", - expected, - found + "expected {expected}, found {found}" ); } } @@ -564,10 +514,8 @@ // auto-cropped image will be reproduced to the original. let exr_path = BASE_PATH.iter().collect::(); - let original = exr_path.clone().join("cropping - uncropped original.exr"); - let cropped = exr_path - .clone() - .join("cropping - data window differs display window.exr"); + let original = exr_path.join("cropping - uncropped original.exr"); + let cropped = exr_path.join("cropping - data window differs display window.exr"); // smoke-check that the exr files are actually not the same { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/png.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/png.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/png.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/png.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,117 +4,38 @@ //! //! # Related Links //! * - The PNG Specification -//! -use std::fmt; -use std::io::{self, Read, Write}; +use std::borrow::Cow; +use std::io::{BufRead, Seek, Write}; -use png::{BlendOp, DisposeOp}; +use png::{BlendOp, DeflateCompression, DisposeOp}; use crate::animation::{Delay, Frame, Frames, Ratio}; use crate::color::{Blend, ColorType, ExtendedColorType}; use crate::error::{ - DecodingError, EncodingError, ImageError, ImageResult, LimitError, LimitErrorKind, - ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, + DecodingError, ImageError, ImageResult, LimitError, LimitErrorKind, ParameterError, + ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, +}; +use crate::utils::vec_try_with_capacity; +use crate::{ + AnimationDecoder, DynamicImage, GenericImage, GenericImageView, ImageBuffer, ImageDecoder, + ImageEncoder, ImageFormat, Limits, Luma, LumaA, Rgb, Rgba, RgbaImage, }; -use crate::image::{AnimationDecoder, ImageDecoder, ImageEncoder, ImageFormat}; -use crate::io::Limits; -use crate::{DynamicImage, GenericImage, ImageBuffer, Luma, LumaA, Rgb, Rgba, RgbaImage}; // http://www.w3.org/TR/PNG-Structure.html // The first eight bytes of a PNG file always contain the following (decimal) values: pub(crate) const PNG_SIGNATURE: [u8; 8] = [137, 80, 78, 71, 13, 10, 26, 10]; - -/// Png Reader -/// -/// This reader will try to read the png one row at a time, -/// however for interlaced png files this is not possible and -/// these are therefore read at once. -pub struct PngReader { - reader: png::Reader, - buffer: Vec, - index: usize, -} - -impl PngReader { - fn new(mut reader: png::Reader) -> ImageResult> { - let len = reader.output_buffer_size(); - // Since interlaced images do not come in - // scanline order it is almost impossible to - // read them in a streaming fashion, however - // this shouldn't be a too big of a problem - // as most interlaced images should fit in memory. - let buffer = if reader.info().interlaced { - let mut buffer = vec![0; len]; - reader - .next_frame(&mut buffer) - .map_err(ImageError::from_png)?; - buffer - } else { - Vec::new() - }; - - Ok(PngReader { - reader, - buffer, - index: 0, - }) - } -} - -impl Read for PngReader { - fn read(&mut self, mut buf: &mut [u8]) -> io::Result { - // io::Write::write for slice cannot fail - let readed = buf.write(&self.buffer[self.index..]).unwrap(); - - let mut bytes = readed; - self.index += readed; - - while self.index >= self.buffer.len() { - match self.reader.next_row()? { - Some(row) => { - // Faster to copy directly to external buffer - let readed = buf.write(row.data()).unwrap(); - bytes += readed; - - self.buffer = row.data()[readed..].to_owned(); - self.index = 0; - } - None => return Ok(bytes), - } - } - - Ok(bytes) - } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - let mut bytes = self.buffer.len(); - if buf.is_empty() { - std::mem::swap(&mut self.buffer, buf); - } else { - buf.extend_from_slice(&self.buffer); - self.buffer.clear(); - } - - self.index = 0; - - while let Some(row) = self.reader.next_row()? { - buf.extend_from_slice(row.data()); - bytes += row.data().len(); - } - - Ok(bytes) - } -} +const XMP_KEY: &str = "XML:com.adobe.xmp"; +const IPTC_KEYS: &[&str] = &["Raw profile type iptc", "Raw profile type 8bim"]; /// PNG decoder -pub struct PngDecoder { +pub struct PngDecoder { color_type: ColorType, reader: png::Reader, limits: Limits, } -impl PngDecoder { +impl PngDecoder { /// Creates a new decoder that decodes from the stream ```r``` pub fn new(r: R) -> ImageResult> { Self::with_limits(r, Limits::no_limits()) @@ -122,11 +43,11 @@ /// Creates a new decoder that decodes from the stream ```r``` with the given limits. pub fn with_limits(r: R, limits: Limits) -> ImageResult> { - limits.check_support(&crate::io::LimitSupport::default())?; + limits.check_support(&crate::LimitSupport::default())?; let max_bytes = usize::try_from(limits.max_alloc.unwrap_or(u64::MAX)).unwrap_or(usize::MAX); let mut decoder = png::Decoder::new_with_limits(r, png::Limits { bytes: max_bytes }); - decoder.set_ignore_text_chunk(true); + decoder.set_ignore_text_chunk(false); let info = decoder.read_header_info().map_err(ImageError::from_png)?; limits.check_dimensions(info.width, info.height)?; @@ -211,7 +132,7 @@ .reader .info() .source_gamma - .map(|x| x.into_scaled() as f64 / 100000.0)) + .map(|x| f64::from(x.into_scaled()) / 100_000.0)) } /// Turn this into an iterator over the animation frames. @@ -224,8 +145,8 @@ /// If something is not supported or a limit is violated then the decoding step that requires /// them will fail and an error will be returned instead of the frame. No further frames will /// be returned. - pub fn apng(self) -> ApngDecoder { - ApngDecoder::new(self) + pub fn apng(self) -> ImageResult> { + Ok(ApngDecoder::new(self)) } /// Returns if the image contains an animation. @@ -234,8 +155,8 @@ /// animation. When it is not the common interpretation is to use it as a thumbnail. /// /// If a non-animated image is converted into an `ApngDecoder` then its iterator is empty. - pub fn is_apng(&self) -> bool { - self.reader.info().animation_control.is_some() + pub fn is_apng(&self) -> ImageResult { + Ok(self.reader.info().animation_control.is_some()) } } @@ -246,9 +167,7 @@ )) } -impl<'a, R: 'a + Read> ImageDecoder<'a> for PngDecoder { - type Reader = PngReader; - +impl ImageDecoder for PngDecoder { fn dimensions(&self) -> (u32, u32) { self.reader.info().size() } @@ -257,16 +176,68 @@ self.color_type } - fn icc_profile(&mut self) -> Option> { - self.reader.info().icc_profile.as_ref().map(|x| x.to_vec()) + fn icc_profile(&mut self) -> ImageResult>> { + Ok(self.reader.info().icc_profile.as_ref().map(|x| x.to_vec())) } - fn into_reader(self) -> ImageResult { - PngReader::new(self.reader) + fn exif_metadata(&mut self) -> ImageResult>> { + Ok(self + .reader + .info() + .exif_metadata + .as_ref() + .map(|x| x.to_vec())) + } + + fn xmp_metadata(&mut self) -> ImageResult>> { + if let Some(mut itx_chunk) = self + .reader + .info() + .utf8_text + .iter() + .find(|chunk| chunk.keyword.contains(XMP_KEY)) + .cloned() + { + itx_chunk.decompress_text().map_err(ImageError::from_png)?; + return itx_chunk + .get_text() + .map(|text| Some(text.as_bytes().to_vec())) + .map_err(ImageError::from_png); + } + Ok(None) + } + + fn iptc_metadata(&mut self) -> ImageResult>> { + if let Some(mut text_chunk) = self + .reader + .info() + .compressed_latin1_text + .iter() + .find(|chunk| IPTC_KEYS.iter().any(|key| chunk.keyword.contains(key))) + .cloned() + { + text_chunk.decompress_text().map_err(ImageError::from_png)?; + return text_chunk + .get_text() + .map(|text| Some(text.as_bytes().to_vec())) + .map_err(ImageError::from_png); + } + + if let Some(text_chunk) = self + .reader + .info() + .uncompressed_latin1_text + .iter() + .find(|chunk| IPTC_KEYS.iter().any(|key| chunk.keyword.contains(key))) + .cloned() + { + return Ok(Some(text_chunk.text.into_bytes())); + } + Ok(None) } fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { - use byteorder::{BigEndian, ByteOrder, NativeEndian}; + use byteorder_lite::{BigEndian, ByteOrder, NativeEndian}; assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); self.reader.next_frame(buf).map_err(ImageError::from_png)?; @@ -280,20 +251,19 @@ 1 => (), // No reodering necessary for u8 2 => buf.chunks_exact_mut(2).for_each(|c| { let v = BigEndian::read_u16(c); - NativeEndian::write_u16(c, v) + NativeEndian::write_u16(c, v); }), _ => unreachable!(), } Ok(()) } - fn scanline_bytes(&self) -> u64 { - let width = self.reader.info().width; - self.reader.output_line_size(width) as u64 + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } fn set_limits(&mut self, limits: Limits) -> ImageResult<()> { - limits.check_support(&crate::io::LimitSupport::default())?; + limits.check_support(&crate::LimitSupport::default())?; let info = self.reader.info(); limits.check_dimensions(info.width, info.height)?; self.limits = limits; @@ -310,7 +280,7 @@ /// [`AnimationDecoder`]: ../trait.AnimationDecoder.html /// [`PngDecoder`]: struct.PngDecoder.html /// [`PngDecoder::apng`]: struct.PngDecoder.html#method.apng -pub struct ApngDecoder { +pub struct ApngDecoder { inner: PngDecoder, /// The current output buffer. current: Option, @@ -318,13 +288,16 @@ previous: Option, /// The dispose op of the current frame. dispose: DisposeOp, + + /// The region to dispose of the previous frame. + dispose_region: Option<(u32, u32, u32, u32)>, /// The number of image still expected to be able to load. remaining: u32, /// The next (first) image is the thumbnail. has_thumbnail: bool, } -impl ApngDecoder { +impl ApngDecoder { fn new(inner: PngDecoder) -> Self { let info = inner.reader.info(); let remaining = match info.animation_control() { @@ -340,6 +313,7 @@ current: None, previous: None, dispose: DisposeOp::Background, + dispose_region: None, remaining, has_thumbnail, } @@ -381,8 +355,13 @@ if self.has_thumbnail { // Clone the limits so that our one-off allocation that's destroyed after this scope doesn't persist let mut limits = self.inner.limits.clone(); - limits.reserve_usize(self.inner.reader.output_buffer_size())?; - let mut buffer = vec![0; self.inner.reader.output_buffer_size()]; + + let buffer_size = self.inner.reader.output_buffer_size().ok_or_else(|| { + ImageError::Limits(LimitError::from_kind(LimitErrorKind::InsufficientMemory)) + })?; + + limits.reserve_usize(buffer_size)?; + let mut buffer = vec![0; buffer_size]; // TODO: add `png::Reader::change_limits()` and call it here // to also constrain the internal buffer allocations in the PNG crate self.inner @@ -399,18 +378,37 @@ let current = self.current.as_mut().unwrap(); // Dispose of the previous frame. + match self.dispose { DisposeOp::None => { previous.clone_from(current); } DisposeOp::Background => { previous.clone_from(current); - current - .pixels_mut() - .for_each(|pixel| *pixel = Rgba([0, 0, 0, 0])); + if let Some((px, py, width, height)) = self.dispose_region { + let mut region_current = current.sub_image(px, py, width, height); + + // FIXME: This is a workaround for the fact that `pixels_mut` is not implemented + let pixels: Vec<_> = region_current.pixels().collect(); + + for (x, y, _) in &pixels { + region_current.put_pixel(*x, *y, Rgba::from([0, 0, 0, 0])); + } + } else { + // The first frame is always a background frame. + current.pixels_mut().for_each(|pixel| { + *pixel = Rgba::from([0, 0, 0, 0]); + }); + } } DisposeOp::Previous => { - current.clone_from(previous); + let (px, py, width, height) = self + .dispose_region + .expect("The first frame must not set dispose=Previous"); + let region_previous = previous.sub_image(px, py, width, height); + current + .copy_from(®ion_previous.to_image(), px, py) + .unwrap(); } } @@ -420,7 +418,10 @@ let mut limits = self.inner.limits.clone(); // Read next frame data. - let raw_frame_size = self.inner.reader.output_buffer_size(); + let raw_frame_size = self.inner.reader.output_buffer_size().ok_or_else(|| { + ImageError::Limits(LimitError::from_kind(LimitErrorKind::InsufficientMemory)) + })?; + limits.reserve_usize(raw_frame_size)?; let mut buffer = vec![0; raw_frame_size]; // TODO: add `png::Reader::change_limits()` and call it here @@ -449,7 +450,9 @@ blend = fc.blend_op; self.dispose = fc.dispose_op; } - }; + } + + self.dispose_region = Some((px, py, width, height)); // Turn the data into an rgba image proper. limits.reserve_buffer(width, height, COLOR_TYPE)?; @@ -493,6 +496,7 @@ // Ok, we can proceed with actually remaining images. self.remaining = remaining; // Return composited output buffer. + Ok(Some(self.current.as_ref().unwrap())) } @@ -508,11 +512,11 @@ } } -impl<'a, R: Read + 'a> AnimationDecoder<'a> for ApngDecoder { +impl<'a, R: BufRead + Seek + 'a> AnimationDecoder<'a> for ApngDecoder { fn into_frames(self) -> Frames<'a> { - struct FrameIterator(ApngDecoder); + struct FrameIterator(ApngDecoder); - impl Iterator for FrameIterator { + impl Iterator for FrameIterator { type Item = ImageResult; fn next(&mut self) -> Option { @@ -545,9 +549,11 @@ w: W, compression: CompressionType, filter: FilterType, + icc_profile: Vec, + exif_metadata: Vec, } -/// Compression level of a PNG encoder. The default setting is `Fast`. +/// DEFLATE compression level of a PNG encoder. The default setting is `Fast`. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[non_exhaustive] #[derive(Default)] @@ -559,12 +565,10 @@ Fast, /// High compression level Best, - /// Huffman coding compression - #[deprecated(note = "use one of the other compression levels instead, such as 'Fast'")] - Huffman, - /// Run-length encoding compression - #[deprecated(note = "use one of the other compression levels instead, such as 'Fast'")] - Rle, + /// No compression whatsoever + Uncompressed, + /// Detailed compression level between 1 and 9 + Level(u8), } /// Filter algorithms used to process image data to improve compression. @@ -591,12 +595,6 @@ Adaptive, } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[non_exhaustive] -enum BadPngRepresentation { - ColorType(ColorType), -} - impl PngEncoder { /// Create a new encoder that writes its output to ```w``` pub fn new(w: W) -> PngEncoder { @@ -604,6 +602,8 @@ w, compression: CompressionType::default(), filter: FilterType::default(), + icc_profile: Vec::new(), + exif_metadata: Vec::new(), } } @@ -628,65 +628,81 @@ w, compression, filter, + icc_profile: Vec::new(), + exif_metadata: Vec::new(), } } - /// Encodes the image `data` that has dimensions `width` and `height` and `ColorType` `c`. - /// - /// Expects data in big endian. - #[deprecated = "Use `PngEncoder::write_image` instead. Beware that `write_image` has a different endianness convention"] - pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> { - self.encode_inner(data, width, height, color) - } - fn encode_inner( self, data: &[u8], width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, ) -> ImageResult<()> { let (ct, bits) = match color { - ColorType::L8 => (png::ColorType::Grayscale, png::BitDepth::Eight), - ColorType::L16 => (png::ColorType::Grayscale, png::BitDepth::Sixteen), - ColorType::La8 => (png::ColorType::GrayscaleAlpha, png::BitDepth::Eight), - ColorType::La16 => (png::ColorType::GrayscaleAlpha, png::BitDepth::Sixteen), - ColorType::Rgb8 => (png::ColorType::Rgb, png::BitDepth::Eight), - ColorType::Rgb16 => (png::ColorType::Rgb, png::BitDepth::Sixteen), - ColorType::Rgba8 => (png::ColorType::Rgba, png::BitDepth::Eight), - ColorType::Rgba16 => (png::ColorType::Rgba, png::BitDepth::Sixteen), + ExtendedColorType::L8 => (png::ColorType::Grayscale, png::BitDepth::Eight), + ExtendedColorType::L16 => (png::ColorType::Grayscale, png::BitDepth::Sixteen), + ExtendedColorType::La8 => (png::ColorType::GrayscaleAlpha, png::BitDepth::Eight), + ExtendedColorType::La16 => (png::ColorType::GrayscaleAlpha, png::BitDepth::Sixteen), + ExtendedColorType::Rgb8 => (png::ColorType::Rgb, png::BitDepth::Eight), + ExtendedColorType::Rgb16 => (png::ColorType::Rgb, png::BitDepth::Sixteen), + ExtendedColorType::Rgba8 => (png::ColorType::Rgba, png::BitDepth::Eight), + ExtendedColorType::Rgba16 => (png::ColorType::Rgba, png::BitDepth::Sixteen), _ => { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Png.into(), - UnsupportedErrorKind::Color(color.into()), + UnsupportedErrorKind::Color(color), ), )) } }; + let comp = match self.compression { - CompressionType::Default => png::Compression::Default, - CompressionType::Best => png::Compression::Best, - _ => png::Compression::Fast, + CompressionType::Default => png::Compression::Balanced, + CompressionType::Best => png::Compression::High, + CompressionType::Fast => png::Compression::Fast, + CompressionType::Uncompressed => png::Compression::NoCompression, + CompressionType::Level(0) => png::Compression::NoCompression, + CompressionType::Level(_) => png::Compression::Fast, // whatever, will be overridden }; - let (filter, adaptive_filter) = match self.filter { - FilterType::NoFilter => ( - png::FilterType::NoFilter, - png::AdaptiveFilterType::NonAdaptive, - ), - FilterType::Sub => (png::FilterType::Sub, png::AdaptiveFilterType::NonAdaptive), - FilterType::Up => (png::FilterType::Up, png::AdaptiveFilterType::NonAdaptive), - FilterType::Avg => (png::FilterType::Avg, png::AdaptiveFilterType::NonAdaptive), - FilterType::Paeth => (png::FilterType::Paeth, png::AdaptiveFilterType::NonAdaptive), - FilterType::Adaptive => (png::FilterType::Sub, png::AdaptiveFilterType::Adaptive), + + let advanced_comp = match self.compression { + // Do not set level 0 as a Zlib level to avoid Zlib backend variance. + // For example, in miniz_oxide level 0 is very slow. + CompressionType::Level(n @ 1..) => Some(DeflateCompression::Level(n)), + _ => None, }; - let mut encoder = png::Encoder::new(self.w, width, height); + let filter = match self.filter { + FilterType::NoFilter => png::Filter::NoFilter, + FilterType::Sub => png::Filter::Sub, + FilterType::Up => png::Filter::Up, + FilterType::Avg => png::Filter::Avg, + FilterType::Paeth => png::Filter::Paeth, + FilterType::Adaptive => png::Filter::Adaptive, + }; + + let mut info = png::Info::with_size(width, height); + + if !self.icc_profile.is_empty() { + info.icc_profile = Some(Cow::Borrowed(&self.icc_profile)); + } + if !self.exif_metadata.is_empty() { + info.exif_metadata = Some(Cow::Borrowed(&self.exif_metadata)); + } + + let mut encoder = + png::Encoder::with_info(self.w, info).map_err(|e| ImageError::IoError(e.into()))?; + encoder.set_color(ct); encoder.set_depth(bits); encoder.set_compression(comp); + if let Some(compression) = advanced_comp { + encoder.set_deflate_compression(compression); + } encoder.set_filter(filter); - encoder.set_adaptive_filter(adaptive_filter); let mut writer = encoder .write_header() .map_err(|e| ImageError::IoError(e.into()))?; @@ -700,7 +716,7 @@ /// Write a PNG image with the specified width, height, and color type. /// /// For color types with 16-bit per channel or larger, the contents of `buf` should be in - /// native endian. PngEncoder will automatically convert to big endian as required by the + /// native endian. `PngEncoder` will automatically convert to big endian as required by the /// underlying PNG format. #[track_caller] fn write_image( @@ -708,17 +724,15 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - use byteorder::{BigEndian, ByteOrder, NativeEndian}; - use ColorType::*; + use ExtendedColorType::*; - let expected_bufffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( - expected_bufffer_len, + expected_buffer_len, buf.len() as u64, - "Invalid buffer length: expected {expected_bufffer_len} got {} for {width}x{height} image", + "Invalid buffer length: expected {expected_buffer_len} got {} for {width}x{height} image", buf.len(), ); @@ -735,18 +749,34 @@ // Because the buffer is immutable and the PNG encoder does not // yet take Write/Read traits, create a temporary buffer for // big endian reordering. - let mut reordered = vec![0; buf.len()]; - buf.chunks_exact(2) - .zip(reordered.chunks_exact_mut(2)) - .for_each(|(b, r)| BigEndian::write_u16(r, NativeEndian::read_u16(b))); - self.encode_inner(&reordered, width, height, color_type) - } - _ => Err(ImageError::Encoding(EncodingError::new( - ImageFormat::Png.into(), - BadPngRepresentation::ColorType(color_type), - ))), + let mut reordered; + let buf = if cfg!(target_endian = "little") { + reordered = vec_try_with_capacity(buf.len())?; + reordered.extend(buf.chunks_exact(2).flat_map(|le| [le[1], le[0]])); + &reordered + } else { + buf + }; + self.encode_inner(buf, width, height, color_type) + } + _ => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Png.into(), + UnsupportedErrorKind::Color(color_type), + ), + )), } } + + fn set_icc_profile(&mut self, icc_profile: Vec) -> Result<(), UnsupportedError> { + self.icc_profile = icc_profile; + Ok(()) + } + + fn set_exif_metadata(&mut self, exif: Vec) -> Result<(), UnsupportedError> { + self.exif_metadata = exif; + Ok(()) + } } impl ImageError { @@ -772,33 +802,18 @@ } } -impl fmt::Display for BadPngRepresentation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::ColorType(color_type) => write!( - f, - "The color {:?} can not be represented in PNG.", - color_type - ), - } - } -} - -impl std::error::Error for BadPngRepresentation {} - #[cfg(test)] mod tests { use super::*; - use crate::ImageOutputFormat; - - use std::io::Cursor; + use crate::io::free_functions::decoder_to_vec; + use std::io::{BufReader, Cursor, Read}; #[test] fn ensure_no_decoder_off_by_one() { - let dec = PngDecoder::new( + let dec = PngDecoder::new(BufReader::new( std::fs::File::open("tests/images/png/bugfixes/debug_triangle_corners_widescreen.png") .unwrap(), - ) + )) .expect("Unable to read PNG file (does it exist?)"); assert_eq![(2000, 1000), dec.dimensions()]; @@ -809,9 +824,7 @@ "Image MUST have the Rgb8 format" ]; - #[allow(deprecated)] - let correct_bytes = dec - .into_reader() + let correct_bytes = decoder_to_vec(dec) .expect("Unable to read file") .bytes() .map(|x| x.expect("Unable to read byte")) @@ -829,7 +842,7 @@ .unwrap(); not_png[0] = 0; - let error = PngDecoder::new(¬_png[..]).err().unwrap(); + let error = PngDecoder::new(Cursor::new(¬_png)).err().unwrap(); let _ = error .source() .unwrap() @@ -842,6 +855,6 @@ // regression test for issue #1663 let image = DynamicImage::new_rgb32f(1, 1); let mut target = Cursor::new(vec![]); - let _ = image.write_to(&mut target, ImageOutputFormat::Png); + let _ = image.write_to(&mut target, ImageFormat::Png); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/autobreak.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/autobreak.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/autobreak.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/autobreak.rs 2006-07-24 01:21:28.000000000 +0000 @@ -13,14 +13,16 @@ } impl AutoBreak { - pub(crate) fn new(writer: W, line_capacity: usize) -> Self { - AutoBreak { + pub(crate) fn new(writer: W, line_capacity: usize) -> io::Result { + let mut line = Vec::new(); + line.try_reserve_exact(line_capacity + 1)?; + Ok(AutoBreak { wrapped: writer, line_capacity, - line: Vec::with_capacity(line_capacity + 1), + line, has_newline: false, panicked: false, - } + }) } fn flush_buf(&mut self) -> io::Result<()> { @@ -98,7 +100,7 @@ let mut output = Vec::new(); { - let mut writer = AutoBreak::new(&mut output, 10); + let mut writer = AutoBreak::new(&mut output, 10).unwrap(); writer.write_all(b"0123456789").unwrap(); writer.write_all(b"0123456789").unwrap(); } @@ -111,7 +113,7 @@ let mut output = Vec::new(); { - let mut writer = AutoBreak::new(&mut output, 10); + let mut writer = AutoBreak::new(&mut output, 10).unwrap(); writer.write_all(b"012").unwrap(); writer.write_all(b"345").unwrap(); writer.write_all(b"0123456789").unwrap(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,9 @@ use std::error; use std::fmt::{self, Display}; -use std::io::{self, BufRead, Cursor, Read}; -use std::marker::PhantomData; -use std::mem; +use std::io::{self, Read}; +use std::mem::size_of; use std::num::ParseIntError; -use std::str::{self, FromStr}; +use std::str; use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader}; use super::{HeaderRecord, PnmHeader, PnmSubtype, SampleEncoding}; @@ -12,10 +11,10 @@ use crate::error::{ DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{self, ImageDecoder, ImageFormat}; -use crate::utils; +use crate::io::ReadExt; +use crate::{utils, ImageDecoder, ImageFormat}; -use byteorder::{BigEndian, ByteOrder, NativeEndian}; +use byteorder_lite::{BigEndian, ByteOrder, NativeEndian}; /// All errors that can occur when attempting to parse a PNM #[derive(Debug, Clone)] @@ -29,8 +28,8 @@ NonAsciiByteInHeader(u8), /// The PAM header contained a non-ASCII byte NonAsciiLineInPamHeader, - /// A sample string contained a non-ASCII byte - NonAsciiSample, + /// Couldn't parse an integer: expected but did not get an ASCII digit + InvalidDigit(ErrorDataSource), /// The byte after the P7 magic was not 0x0A NEWLINE NotNewlineAfterP7Magic(u8), @@ -78,7 +77,7 @@ TupleTypeUnrecognised, /// Overflowed the specified value when parsing - Overflow, + Overflow(ErrorDataSource), } impl Display for DecoderError { @@ -89,29 +88,27 @@ magic[0], magic[1] )), DecoderError::UnparsableValue(src, data, err) => { - f.write_fmt(format_args!("Error parsing {:?} as {}: {}", data, src, err)) + f.write_fmt(format_args!("Error parsing {data:?} as {src}: {err}")) } DecoderError::NonAsciiByteInHeader(c) => { - f.write_fmt(format_args!("Non-ASCII character {:#04X?} in header", c)) + f.write_fmt(format_args!("Non-ASCII character {c:#04X?} in header")) } DecoderError::NonAsciiLineInPamHeader => f.write_str("Non-ASCII line in PAM header"), - DecoderError::NonAsciiSample => { - f.write_str("Non-ASCII character where sample value was expected") + DecoderError::InvalidDigit(src) => { + f.write_fmt(format_args!("Non-ASCII-digit character when parsing number in {src}")) } DecoderError::NotNewlineAfterP7Magic(c) => f.write_fmt(format_args!( - "Expected newline after P7 magic, got {:#04X?}", - c + "Expected newline after P7 magic, got {c:#04X?}" )), DecoderError::UnexpectedPnmHeaderEnd => f.write_str("Unexpected end of PNM header"), DecoderError::HeaderLineDuplicated(line) => { - f.write_fmt(format_args!("Duplicate {} line", line)) + f.write_fmt(format_args!("Duplicate {line} line")) } DecoderError::HeaderLineUnknown(identifier) => f.write_fmt(format_args!( - "Unknown header line with identifier {:?}", - identifier + "Unknown header line with identifier {identifier:?}" )), DecoderError::HeaderLineMissing { height, @@ -119,19 +116,17 @@ depth, maxval, } => f.write_fmt(format_args!( - "Missing header line: have height={:?}, width={:?}, depth={:?}, maxval={:?}", - height, width, depth, maxval + "Missing header line: have height={height:?}, width={width:?}, depth={depth:?}, maxval={maxval:?}" )), DecoderError::InputTooShort => { f.write_str("Not enough data was provided to the Decoder to decode the image") } DecoderError::UnexpectedByteInRaster(c) => f.write_fmt(format_args!( - "Unexpected character {:#04X?} within sample raster", - c + "Unexpected character {c:#04X?} within sample raster" )), DecoderError::SampleOutOfBounds(val) => { - f.write_fmt(format_args!("Sample value {} outside of bounds", val)) + f.write_fmt(format_args!("Sample value {val} outside of bounds")) } DecoderError::MaxvalZero => f.write_str("Image MAXVAL is zero"), DecoderError::MaxvalTooBig(maxval) => { @@ -154,7 +149,9 @@ tuple_type.name() )), DecoderError::TupleTypeUnrecognised => f.write_str("Tuple type not recognized"), - DecoderError::Overflow => f.write_str("Overflow when parsing value"), + DecoderError::Overflow(src) => f.write_fmt(format_args!( + "Overflow when parsing integer in {src}" + )) } } } @@ -226,10 +223,15 @@ enum TupleType { PbmBit, BWBit, + BWAlphaBit, GrayU8, + GrayAlphaU8, GrayU16, + GrayAlphaU16, RGBU8, + RGBAlphaU8, RGBU16, + RGBAlphaU16, } trait Sample { @@ -237,7 +239,7 @@ /// Representation size in bytes fn sample_size() -> u32 { - std::mem::size_of::() as u32 + size_of::() as u32 } fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult { Ok((width * height * samples * Self::sample_size()) as usize) @@ -262,7 +264,7 @@ tuple: TupleType, } -impl PnmDecoder { +impl PnmDecoder { /// Create a new decoder that decodes from the stream ```read``` pub fn new(mut buffered_read: R) -> ImageResult> { let magic = buffered_read.read_magic_constant()?; @@ -305,6 +307,11 @@ Ok(decoder) } + /// Get the header of the decoded image. + pub fn header(&self) -> &PnmHeader { + &self.header + } + /// Extract the reader and header after an image has been read. pub fn into_inner(self) -> (R, PnmHeader) { (self.reader, self.header) @@ -362,7 +369,7 @@ } } -trait HeaderReader: BufRead { +trait HeaderReader: Read { /// Reads the two magic constant bytes fn read_magic_constant(&mut self) -> ImageResult<[u8; 2]> { let mut magic: [u8; 2] = [0, 0]; @@ -370,11 +377,11 @@ Ok(magic) } - /// Reads a string as well as a single whitespace after it, ignoring comments - fn read_next_string(&mut self) -> ImageResult { - let mut bytes = Vec::new(); - + /// Reads an integer as well as a single whitespace after it, ignoring comments + /// and leading whitespace + fn read_next_u32(&mut self) -> ImageResult { // pair input bytes with a bool mask to remove comments + #[allow(clippy::unbuffered_bytes)] let mark_comments = self.bytes().scan(true, |partof, read| { let byte = match read { Err(err) => return Some((*partof, Err(err))), @@ -386,10 +393,15 @@ Some((cur_enabled, Ok(byte))) }); + // Streaming parse of the integer. To match Netpbm, this accepts values + // with leading zeros, like 000005, but no leading + or - + let mut value: u32 = 0; + let mut found_digit = false; + for (_, byte) in mark_comments.filter(|e| e.0) { match byte { - Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => { - if !bytes.is_empty() { + Ok(b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ') => { + if found_digit { break; // We're done as we already have some content } } @@ -397,32 +409,43 @@ return Err(DecoderError::NonAsciiByteInHeader(byte).into()) } Ok(byte) => { - bytes.push(byte); + let digit = match byte { + b'0'..=b'9' => u32::from(byte - b'0'), + _ => { + return Err(DecoderError::InvalidDigit(ErrorDataSource::Preamble).into()) + } + }; + value = value + .checked_mul(10) + .ok_or(DecoderError::Overflow(ErrorDataSource::Preamble))?; + value = value + .checked_add(digit) + .ok_or(DecoderError::Overflow(ErrorDataSource::Preamble))?; + found_digit = true; } Err(_) => break, } } - if bytes.is_empty() { + if !found_digit { return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())); } - if !bytes.as_slice().is_ascii() { - // We have only filled the buffer with characters for which `byte.is_ascii()` holds. - unreachable!("Non-ASCII character should have returned sooner") - } - - let string = String::from_utf8(bytes) - // We checked the precondition ourselves a few lines before, `bytes.as_slice().is_ascii()`. - .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded")); - - Ok(string) + Ok(value) } - fn read_next_u32(&mut self) -> ImageResult { - let s = self.read_next_string()?; - s.parse::() - .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) + fn read_next_line(&mut self) -> ImageResult { + let mut buffer = Vec::new(); + loop { + let mut byte = [0]; + if self.read(&mut byte)? == 0 || byte[0] == b'\n' { + break; + } + buffer.push(byte[0]); + } + + String::from_utf8(buffer) + .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) } fn read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult { @@ -430,8 +453,8 @@ let height = self.read_next_u32()?; Ok(BitmapHeader { encoding, - width, height, + width, }) } @@ -457,8 +480,8 @@ let maxval = self.read_next_u32()?; Ok(PixmapHeader { encoding, - width, height, + width, maxval, }) } @@ -480,6 +503,7 @@ } } + #[allow(clippy::unbuffered_bytes)] match self.bytes().next() { None => return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())), Some(Err(io)) => return Err(ImageError::IoError(io)), @@ -487,16 +511,15 @@ Some(Ok(c)) => return Err(DecoderError::NotNewlineAfterP7Magic(c).into()), } - let mut line = String::new(); + let mut line; let mut height: Option = None; let mut width: Option = None; let mut depth: Option = None; let mut maxval: Option = None; let mut tupltype: Option = None; loop { - line.truncate(0); - let len = self.read_line(&mut line)?; - if len == 0 { + line = self.read_next_line()?; + if line.is_empty() { return Err(DecoderError::UnexpectedPnmHeaderEnd.into()); } if line.as_bytes()[0] == b'#' { @@ -532,17 +555,14 @@ } } - let (h, w, d, m) = match (height, width, depth, maxval) { - (Some(h), Some(w), Some(d), Some(m)) => (h, w, d, m), - _ => { - return Err(DecoderError::HeaderLineMissing { - height, - width, - depth, - maxval, - } - .into()) + let (Some(h), Some(w), Some(d), Some(m)) = (height, width, depth, maxval) else { + return Err(DecoderError::HeaderLineMissing { + height, + width, + depth, + maxval, } + .into()); }; let tupltype = match tupltype { @@ -568,27 +588,9 @@ } } -impl HeaderReader for R where R: BufRead {} - -/// Wrapper struct around a `Cursor>` -pub struct PnmReader(Cursor>, PhantomData); -impl Read for PnmReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } - } -} - -impl<'a, R: 'a + Read> ImageDecoder<'a> for PnmDecoder { - type Reader = PnmReader; +impl HeaderReader for R where R: Read {} +impl ImageDecoder for PnmDecoder { fn dimensions(&self) -> (u32, u32) { (self.header.width(), self.header.height()) } @@ -597,10 +599,15 @@ match self.tuple { TupleType::PbmBit => ColorType::L8, TupleType::BWBit => ColorType::L8, + TupleType::BWAlphaBit => ColorType::La8, TupleType::GrayU8 => ColorType::L8, + TupleType::GrayAlphaU8 => ColorType::La8, TupleType::GrayU16 => ColorType::L16, + TupleType::GrayAlphaU16 => ColorType::La16, TupleType::RGBU8 => ColorType::Rgb8, + TupleType::RGBAlphaU8 => ColorType::Rgba8, TupleType::RGBU16 => ColorType::Rgb16, + TupleType::RGBAlphaU16 => ColorType::Rgba16, } } @@ -608,31 +615,38 @@ match self.tuple { TupleType::PbmBit => ExtendedColorType::L1, TupleType::BWBit => ExtendedColorType::L1, + TupleType::BWAlphaBit => ExtendedColorType::La1, TupleType::GrayU8 => ExtendedColorType::L8, + TupleType::GrayAlphaU8 => ExtendedColorType::La8, TupleType::GrayU16 => ExtendedColorType::L16, + TupleType::GrayAlphaU16 => ExtendedColorType::La16, TupleType::RGBU8 => ExtendedColorType::Rgb8, + TupleType::RGBAlphaU8 => ExtendedColorType::Rgba8, TupleType::RGBU16 => ExtendedColorType::Rgb16, + TupleType::RGBAlphaU16 => ExtendedColorType::Rgba16, } } - fn into_reader(self) -> ImageResult { - Ok(PnmReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); match self.tuple { TupleType::PbmBit => self.read_samples::(1, buf), TupleType::BWBit => self.read_samples::(1, buf), + TupleType::BWAlphaBit => self.read_samples::(2, buf), TupleType::RGBU8 => self.read_samples::(3, buf), + TupleType::RGBAlphaU8 => self.read_samples::(4, buf), TupleType::RGBU16 => self.read_samples::(3, buf), + TupleType::RGBAlphaU16 => self.read_samples::(4, buf), TupleType::GrayU8 => self.read_samples::(1, buf), + TupleType::GrayAlphaU8 => self.read_samples::(2, buf), TupleType::GrayU16 => self.read_samples::(1, buf), + TupleType::GrayAlphaU16 => self.read_samples::(2, buf), } } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } impl PnmDecoder { @@ -644,29 +658,24 @@ let bytecount = S::bytelen(width, height, components)?; let mut bytes = vec![]; - self.reader - .by_ref() - // This conversion is potentially lossy but unlikely and in that case we error - // later anyways. - .take(bytecount as u64) - .read_to_end(&mut bytes)?; - if bytes.len() != bytecount { - return Err(DecoderError::InputTooShort.into()); - } + self.reader.read_exact_vec(&mut bytes, bytecount)?; - let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; - let components: usize = - components.try_into().map_err(|_| DecoderError::Overflow)?; + let width: usize = width + .try_into() + .map_err(|_| DecoderError::Overflow(ErrorDataSource::Sample))?; + let components: usize = components + .try_into() + .map_err(|_| DecoderError::Overflow(ErrorDataSource::Sample))?; let row_size = width .checked_mul(components) - .ok_or(DecoderError::Overflow)?; + .ok_or(DecoderError::Overflow(ErrorDataSource::Sample))?; S::from_bytes(&bytes, row_size, buf)?; } SampleEncoding::Ascii => { self.read_ascii::(buf)?; } - }; + } // Scale samples if 8bit or 16bit is not saturated let current_sample_max = self.header.maximal_sample(); @@ -676,13 +685,13 @@ let factor = target_sample_max as f32 / current_sample_max as f32; if S::sample_size() == 1 { - buf.iter_mut().for_each(|v| { - *v = (*v as f32 * factor).round() as u8; - }) + for v in buf.iter_mut() { + *v = (f32::from(*v) * factor).round() as u8; + } } else if S::sample_size() == 2 { for chunk in buf.chunks_exact_mut(2) { let v = NativeEndian::read_u16(chunk); - NativeEndian::write_u16(chunk, (v as f32 * factor).round() as u16); + NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); } } } @@ -700,29 +709,36 @@ } } -fn read_separated_ascii>(reader: &mut dyn Read) -> ImageResult -where - T::Err: Display, -{ - let is_separator = |v: &u8| matches! { *v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ' }; +fn read_separated_ascii>(reader: &mut dyn Read) -> ImageResult { + let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); - let token = reader + let mut v: u16 = 0; + let mut had_any = false; + #[allow(clippy::unbuffered_bytes)] + for rc in reader .bytes() - .skip_while(|v| v.as_ref().ok().map(is_separator).unwrap_or(false)) - .take_while(|v| v.as_ref().ok().map(|c| !is_separator(c)).unwrap_or(false)) - .collect::, _>>()?; - - if !token.is_ascii() { - return Err(DecoderError::NonAsciiSample.into()); + .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) + .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) + { + let c = rc?; + let digit = match c { + b'0'..=b'9' => u16::from(c - b'0'), + _ => return Err(DecoderError::InvalidDigit(ErrorDataSource::Sample).into()), + }; + v = v + .checked_mul(10) + .ok_or(DecoderError::Overflow(ErrorDataSource::Sample))?; + v = v + .checked_add(digit) + .ok_or(DecoderError::Overflow(ErrorDataSource::Sample))?; + had_any = true; } - let string = str::from_utf8(&token) - // We checked the precondition ourselves a few lines before with `token.is_ascii()`. - .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded")); + if !had_any { + return Err(DecoderError::InputTooShort.into()); + } - string.parse().map_err(|err| { - DecoderError::UnparsableValue(ErrorDataSource::Sample, string.to_owned(), err).into() - }) + Ok(T::try_from(v).or(Err(DecoderError::Overflow(ErrorDataSource::Sample)))?) } impl Sample for U8 { @@ -770,13 +786,13 @@ fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult { let count = width * samples; - let linelen = (count / 8) + ((count % 8) != 0) as u32; + let linelen = (count / 8) + u32::from((count % 8) != 0); Ok((linelen * height) as usize) } fn from_bytes(bytes: &[u8], row_size: usize, output_buf: &mut [u8]) -> ImageResult<()> { let mut expanded = utils::expand_bits(1, row_size.try_into().unwrap(), bytes); - for b in expanded.iter_mut() { + for b in &mut expanded { *b = !*b; } output_buf.copy_from_slice(&expanded); @@ -784,6 +800,7 @@ } fn from_ascii(reader: &mut dyn Read, output_buf: &mut [u8]) -> ImageResult<()> { + #[allow(clippy::unbuffered_bytes)] let mut bytes = reader.bytes(); for b in output_buf { loop { @@ -854,19 +871,9 @@ match self.tupltype { _ if self.maxval == 0 => Err(DecoderError::MaxvalZero.into()), None if self.depth == 1 => Ok(TupleType::GrayU8), - None if self.depth == 2 => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Pnm.into(), - UnsupportedErrorKind::Color(ExtendedColorType::La8), - ), - )), + None if self.depth == 2 => Ok(TupleType::GrayAlphaU8), None if self.depth == 3 => Ok(TupleType::RGBU8), - None if self.depth == 4 => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Pnm.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Rgba8), - ), - )), + None if self.depth == 4 => Ok(TupleType::RGBAlphaU8), Some(ArbitraryTuplType::BlackAndWhite) if self.maxval == 1 && self.depth == 1 => { Ok(TupleType::BWBit) @@ -903,31 +910,46 @@ } .into()), - Some(ArbitraryTuplType::BlackAndWhiteAlpha) => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Pnm.into(), - UnsupportedErrorKind::GenericFeature(format!( - "Color type {}", - ArbitraryTuplType::BlackAndWhiteAlpha.name() - )), - ), - )), - Some(ArbitraryTuplType::GrayscaleAlpha) => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Pnm.into(), - UnsupportedErrorKind::Color(ExtendedColorType::La8), - ), - )), - Some(ArbitraryTuplType::RGBAlpha) => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Pnm.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Rgba8), - ), - )), + Some(ArbitraryTuplType::BlackAndWhiteAlpha) if self.depth == 2 && self.maxval == 1 => { + Ok(TupleType::BWAlphaBit) + } + Some(ArbitraryTuplType::BlackAndWhiteAlpha) => { + Err(DecoderError::InvalidDepthOrMaxval { + tuple_type: ArbitraryTuplType::BlackAndWhiteAlpha, + maxval: self.maxval, + depth: self.depth, + } + .into()) + } + + Some(ArbitraryTuplType::GrayscaleAlpha) if self.depth == 2 && self.maxval <= 0xFF => { + Ok(TupleType::GrayAlphaU8) + } + Some(ArbitraryTuplType::GrayscaleAlpha) if self.depth == 2 && self.maxval <= 0xFFFF => { + Ok(TupleType::GrayAlphaU16) + } + Some(ArbitraryTuplType::GrayscaleAlpha) => Err(DecoderError::InvalidDepth { + tuple_type: ArbitraryTuplType::GrayscaleAlpha, + depth: self.depth, + } + .into()), + + Some(ArbitraryTuplType::RGBAlpha) if self.depth == 4 && self.maxval <= 0xFF => { + Ok(TupleType::RGBAlphaU8) + } + Some(ArbitraryTuplType::RGBAlpha) if self.depth == 4 && self.maxval <= 0xFFFF => { + Ok(TupleType::RGBAlphaU16) + } + Some(ArbitraryTuplType::RGBAlpha) => Err(DecoderError::InvalidDepth { + tuple_type: ArbitraryTuplType::RGBAlpha, + depth: self.depth, + } + .into()), + Some(ArbitraryTuplType::Custom(ref custom)) => Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Pnm.into(), - UnsupportedErrorKind::GenericFeature(format!("Tuple type {:?}", custom)), + UnsupportedErrorKind::GenericFeature(format!("Tuple type {custom:?}")), ), )), None => Err(DecoderError::TupleTypeUnrecognised.into()), @@ -984,6 +1006,46 @@ } } + /// Tests reading of a valid blackandwhite_alpha pam + #[test] + fn pam_blackandwhite_alpha() { + let pamdata = b"P7 +WIDTH 2 +HEIGHT 2 +DEPTH 2 +MAXVAL 1 +TUPLTYPE BLACKANDWHITE_ALPHA +# Comment line +ENDHDR +\x01\x00\x00\x01\x01\x00\x00\x01"; + let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); + assert_eq!(decoder.color_type(), ColorType::La8); + assert_eq!(decoder.original_color_type(), ExtendedColorType::La1); + assert_eq!(decoder.dimensions(), (2, 2)); + assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); + + let mut image = vec![0; decoder.total_bytes() as usize]; + decoder.read_image(&mut image).unwrap(); + assert_eq!(image, vec![0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF,]); + match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { + ( + _, + PnmHeader { + decoded: + HeaderRecord::Arbitrary(ArbitraryHeader { + width: 2, + height: 2, + maxval: 1, + depth: 2, + tupltype: Some(ArbitraryTuplType::BlackAndWhiteAlpha), + }), + encoded: _, + }, + ) => (), + _ => panic!("Decoded header is incorrect"), + } + } + /// Tests reading of a valid grayscale pam #[test] fn pam_grayscale() { @@ -1029,6 +1091,55 @@ } } + /// Tests reading of a valid grayscale_alpha pam + #[test] + fn pam_grayscale_alpha() { + let pamdata = b"P7 +HEIGHT 1 +WIDTH 2 +MAXVAL 65535 +DEPTH 2 +TUPLTYPE GRAYSCALE_ALPHA +# Comment line +ENDHDR +\xdc\xba\x32\x10\xdc\xba\x32\x10"; + let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); + assert_eq!(decoder.color_type(), ColorType::La16); + assert_eq!(decoder.original_color_type(), ExtendedColorType::La16); + assert_eq!(decoder.dimensions(), (2, 1)); + assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); + + let mut image = vec![0; decoder.total_bytes() as usize]; + decoder.read_image(&mut image).unwrap(); + assert_eq!( + image, + [ + u16::to_ne_bytes(0xdcba), + u16::to_ne_bytes(0x3210), + u16::to_ne_bytes(0xdcba), + u16::to_ne_bytes(0x3210) + ] + .concat() + ); + match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { + ( + _, + PnmHeader { + decoded: + HeaderRecord::Arbitrary(ArbitraryHeader { + width: 2, + height: 1, + maxval: 65535, + depth: 2, + tupltype: Some(ArbitraryTuplType::GrayscaleAlpha), + }), + encoded: _, + }, + ) => (), + _ => panic!("Decoded header is incorrect"), + } + } + /// Tests reading of a valid rgb pam #[test] fn pam_rgb() { @@ -1071,11 +1182,51 @@ } } + /// Tests reading of a valid rgb_alpha pam + #[test] + fn pam_rgb_alpha() { + let pamdata = b"P7 +WIDTH 1 +HEIGHT 3 +DEPTH 4 +MAXVAL 15 +TUPLTYPE RGB_ALPHA +# Comment line +ENDHDR +\x00\x01\x02\x03\x0a\x0b\x0c\x0d\x05\x06\x07\x08"; + let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); + assert_eq!(decoder.color_type(), ColorType::Rgba8); + assert_eq!(decoder.original_color_type(), ExtendedColorType::Rgba8); + assert_eq!(decoder.dimensions(), (1, 3)); + assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); + + let mut image = vec![0; decoder.total_bytes() as usize]; + decoder.read_image(&mut image).unwrap(); + assert_eq!(image, b"\x00\x11\x22\x33\xaa\xbb\xcc\xdd\x55\x66\x77\x88",); + match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { + ( + _, + PnmHeader { + decoded: + HeaderRecord::Arbitrary(ArbitraryHeader { + width: 1, + height: 3, + maxval: 15, + depth: 4, + tupltype: Some(ArbitraryTuplType::RGBAlpha), + }), + encoded: _, + }, + ) => (), + _ => panic!("Decoded header is incorrect"), + } + } + #[test] fn pbm_binary() { // The data contains two rows of the image (each line is padded to the full byte). For // comments on its format, see documentation of `impl SampleType for PbmBit`. - let pbmbinary = [&b"P4 6 2\n"[..], &[0b01101100_u8, 0b10110111]].concat(); + let pbmbinary = [&b"P4 6 2\n"[..], &[0b0110_1100_u8, 0b1011_0111]].concat(); let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); assert_eq!(decoder.color_type(), ColorType::L8); assert_eq!(decoder.original_color_type(), ExtendedColorType::L1); @@ -1312,4 +1463,46 @@ let mut image = vec![0; decoder.total_bytes() as usize]; let _ = decoder.read_image(&mut image); } + + #[test] + fn data_too_short() { + let data = b"P3 16 16 1\n"; + let decoder = PnmDecoder::new(&data[..]).unwrap(); + let mut image = vec![0; decoder.total_bytes() as usize]; + + let _ = decoder.read_image(&mut image).unwrap_err(); + } + + #[test] + fn no_integers_with_plus() { + let data = b"P3 +1 1 1\n"; + assert!(PnmDecoder::new(&data[..]).is_err()); + } + + #[test] + fn incomplete_pnm_header() { + let data = b"P5 2 3 \n"; + assert!(PnmDecoder::new(&data[..]).is_err()); + } + + #[test] + fn leading_zeros() { + let data = b"P2 03 00000000000002 00100\n011 22 033\n44 055 66\n"; + let decoder = PnmDecoder::new(&data[..]).unwrap(); + let mut image = vec![0; decoder.total_bytes() as usize]; + assert!(decoder.read_image(&mut image).is_ok()); + } + + #[test] + fn header_overflow() { + let data = b"P1 4294967295 4294967297\n"; + assert!(PnmDecoder::new(&data[..]).is_err()); + } + + #[test] + fn header_large_dimension() { + let data = b"P4 1 01234567890\n"; + let decoder = PnmDecoder::new(&data[..]).unwrap(); + assert!(decoder.dimensions() == (1, 1234567890)); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,20 +1,21 @@ //! Encoding of PNM Images +use crate::utils::vec_try_with_capacity; use std::fmt; use std::io; - use std::io::Write; use super::AutoBreak; use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader}; use super::{HeaderRecord, PnmHeader, PnmSubtype, SampleEncoding}; -use crate::color::{ColorType, ExtendedColorType}; + +use crate::color::ExtendedColorType; use crate::error::{ ImageError, ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{ImageEncoder, ImageFormat}; +use crate::{ImageEncoder, ImageFormat}; -use byteorder::{BigEndian, WriteBytesExt}; +use byteorder_lite::{BigEndian, WriteBytesExt}; enum HeaderStrategy { Dynamic, @@ -79,7 +80,7 @@ } impl PnmEncoder { - /// Create new PnmEncoder from the `writer`. + /// Create new `PnmEncoder` from the `writer`. /// /// The encoded images will have some `pnm` format. If more control over the image type is /// required, use either one of `with_subtype` or `with_header`. For more information on the @@ -135,7 +136,12 @@ } } - /// Encode an image whose samples are represented as `u8`. + /// Encode an image whose samples are represented as a sequence of `u8` or `u16` data. + /// + /// If `image` is a slice of `u8`, the samples will be interpreted based on the chosen `color` option. + /// Color types of 16-bit precision means that the bytes are reinterpreted as 16-bit samples, + /// otherwise they are treated as 8-bit samples. + /// If `image` is a slice of `u16`, the samples will be interpreted as 16-bit samples directly. /// /// Some `pnm` subtypes are incompatible with some color options, a chosen header most /// certainly with any deviation from the original decoded image. @@ -144,27 +150,65 @@ image: S, width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, ) -> ImageResult<()> where S: Into>, { let image = image.into(); - match self.header { - HeaderStrategy::Dynamic => { - self.write_dynamic_header(image, width, height, color.into()) + + // adapt samples so that they are aligned even in 16-bit samples, + // required due to the narrowing of the image buffer to &[u8] + // on dynamic image writing + let image = match (image, color) { + ( + FlatSamples::U8(samples), + ExtendedColorType::L16 + | ExtendedColorType::La16 + | ExtendedColorType::Rgb16 + | ExtendedColorType::Rgba16, + ) => { + match bytemuck::try_cast_slice(samples) { + // proceed with aligned 16-bit samples + Ok(samples) => FlatSamples::U16(samples), + Err(_e) => { + // reallocation is required + let new_samples: Vec = samples + .chunks(2) + .map(|chunk| u16::from_ne_bytes([chunk[0], chunk[1]])) + .collect(); + + let image = FlatSamples::U16(&new_samples); + + // make a separate encoding path, + // because the image buffer lifetime has changed + return self.encode_impl(image, width, height, color); + } + } } + // should not be necessary for any other case + _ => image, + }; + + self.encode_impl(image, width, height, color) + } + + /// Encode an image whose samples are already interpreted correctly. + fn encode_impl( + &mut self, + samples: FlatSamples<'_>, + width: u32, + height: u32, + color: ExtendedColorType, + ) -> ImageResult<()> { + match self.header { + HeaderStrategy::Dynamic => self.write_dynamic_header(samples, width, height, color), HeaderStrategy::Subtype(subtype) => { - self.write_subtyped_header(subtype, image, width, height, color.into()) + self.write_subtyped_header(subtype, samples, width, height, color) + } + HeaderStrategy::Chosen(ref header) => { + Self::write_with_header(&mut self.writer, header, samples, width, height, color) } - HeaderStrategy::Chosen(ref header) => Self::write_with_header( - &mut self.writer, - header, - image, - width, - height, - color.into(), - ), } } @@ -245,21 +289,23 @@ }), encoded: None, }, - (PnmSubtype::Bitmap(encoding), ExtendedColorType::L8) - | (PnmSubtype::Bitmap(encoding), ExtendedColorType::L1) => PnmHeader { - decoded: HeaderRecord::Bitmap(BitmapHeader { - encoding, - width, - height, - }), - encoded: None, - }, + (PnmSubtype::Bitmap(encoding), ExtendedColorType::L8 | ExtendedColorType::L1) => { + PnmHeader { + decoded: HeaderRecord::Bitmap(BitmapHeader { + encoding, + height, + width, + }), + encoded: None, + } + } (_, _) => { - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::Generic( - "Color type can not be represented in the chosen format".to_owned(), + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Pnm.into(), + UnsupportedErrorKind::Color(color), ), - ))); + )) } }; @@ -295,10 +341,9 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, buf.len() as u64, @@ -424,15 +469,16 @@ (&Some(ArbitraryTuplType::GrayscaleAlpha), ExtendedColorType::La8) => (), (&Some(ArbitraryTuplType::RGB), ExtendedColorType::Rgb8) => (), + (&Some(ArbitraryTuplType::RGB), ExtendedColorType::Rgb16) => (), (&Some(ArbitraryTuplType::RGBAlpha), ExtendedColorType::Rgba8) => (), + (&Some(ArbitraryTuplType::RGBAlpha), ExtendedColorType::Rgba16) => (), (&None, _) if depth == components => (), (&Some(ArbitraryTuplType::Custom(_)), _) if depth == components => (), _ if depth != components => { return Err(ImageError::Parameter(ParameterError::from_kind( ParameterErrorKind::Generic(format!( - "Depth mismatch: header {} vs. color {}", - depth, components + "Depth mismatch: header {depth} vs. color {components}" )), ))) } @@ -530,15 +576,15 @@ struct SampleWriter<'a>(&'a mut dyn Write); -impl<'a> SampleWriter<'a> { +impl SampleWriter<'_> { fn write_samples_ascii(self, samples: V) -> io::Result<()> where V: Iterator, V::Item: fmt::Display, { - let mut auto_break_writer = AutoBreak::new(self.0, 70); + let mut auto_break_writer = AutoBreak::new(self.0, 70)?; for value in samples { - write!(auto_break_writer, "{} ", value)?; + write!(auto_break_writer, "{value} ")?; } auto_break_writer.flush() } @@ -552,7 +598,7 @@ let line_width = (width - 1) / 8 + 1; // We'll be writing single bytes, so buffer - let mut line_buffer = Vec::with_capacity(line_width as usize); + let mut line_buffer = vec_try_with_capacity(line_width as usize)?; for line in samples.chunks(width as usize) { for byte_bits in line.chunks(8) { @@ -561,11 +607,11 @@ // Black pixels are encoded as 1s if let Some(&v) = byte_bits.get(i) { if v == V::default() { - byte |= 1u8 << (7 - i) + byte |= 1u8 << (7 - i); } } } - line_buffer.push(byte) + line_buffer.push(byte); } self.0.write_all(line_buffer.as_slice())?; line_buffer.clear(); @@ -585,8 +631,8 @@ fn all_smaller(&self, max_val: u32) -> bool { match *self { - FlatSamples::U8(arr) => arr.iter().any(|&val| u32::from(val) > max_val), - FlatSamples::U16(arr) => arr.iter().any(|&val| u32::from(val) > max_val), + FlatSamples::U8(arr) => arr.iter().all(|&val| u32::from(val) <= max_val), + FlatSamples::U16(arr) => arr.iter().all(|&val| u32::from(val) <= max_val), } } @@ -641,7 +687,7 @@ } } -impl<'a> TupleEncoding<'a> { +impl TupleEncoding<'_> { fn write_image(&self, writer: &mut dyn Write) -> ImageResult<()> { match *self { TupleEncoding::PbmBits { @@ -681,3 +727,44 @@ } } } + +#[test] +fn pbm_allows_black() { + let imgbuf = crate::DynamicImage::new_luma8(50, 50); + + let mut buffer = vec![]; + let encoder = + PnmEncoder::new(&mut buffer).with_subtype(PnmSubtype::Bitmap(SampleEncoding::Ascii)); + + imgbuf + .write_with_encoder(encoder) + .expect("all-zeroes is a black image"); +} + +#[test] +fn pbm_allows_white() { + let imgbuf = + crate::DynamicImage::ImageLuma8(crate::ImageBuffer::from_pixel(50, 50, crate::Luma([1]))); + + let mut buffer = vec![]; + let encoder = + PnmEncoder::new(&mut buffer).with_subtype(PnmSubtype::Bitmap(SampleEncoding::Ascii)); + + imgbuf + .write_with_encoder(encoder) + .expect("all-zeroes is a white image"); +} + +#[test] +fn pbm_verifies_pixels() { + let imgbuf = + crate::DynamicImage::ImageLuma8(crate::ImageBuffer::from_pixel(50, 50, crate::Luma([255]))); + + let mut buffer = vec![]; + let encoder = + PnmEncoder::new(&mut buffer).with_subtype(PnmSubtype::Bitmap(SampleEncoding::Ascii)); + + imgbuf + .write_with_encoder(encoder) + .expect_err("failed to catch violating samples"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/header.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/header.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/header.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/header.rs 2006-07-24 01:21:28.000000000 +0000 @@ -32,11 +32,13 @@ /// it is possible to recover the header and construct an encoder. Using the encoder on the just /// loaded image should result in a byte copy of the original file (for single image pnms without /// additional trailing data). +#[derive(Clone)] pub struct PnmHeader { pub(crate) decoded: HeaderRecord, pub(crate) encoded: Option>, } +#[derive(Clone)] pub(crate) enum HeaderRecord { Bitmap(BitmapHeader), Graymap(GraymapHeader), @@ -149,6 +151,7 @@ impl PnmSubtype { /// Get the two magic constant bytes corresponding to this format subtype. + #[must_use] pub fn magic_constant(self) -> &'static [u8; 2] { match self { PnmSubtype::Bitmap(SampleEncoding::Ascii) => b"P1", @@ -162,6 +165,7 @@ } /// Whether samples are stored as binary or as decimal ascii + #[must_use] pub fn sample_encoding(self) -> SampleEncoding { match self { PnmSubtype::ArbitraryMap => SampleEncoding::Binary, @@ -174,6 +178,7 @@ impl PnmHeader { /// Retrieve the format subtype from which the header was created. + #[must_use] pub fn subtype(&self) -> PnmSubtype { match self.decoded { HeaderRecord::Bitmap(BitmapHeader { encoding, .. }) => PnmSubtype::Bitmap(encoding), @@ -184,6 +189,7 @@ } /// The width of the image this header is for. + #[must_use] pub fn width(&self) -> u32 { match self.decoded { HeaderRecord::Bitmap(BitmapHeader { width, .. }) => width, @@ -194,6 +200,7 @@ } /// The height of the image this header is for. + #[must_use] pub fn height(&self) -> u32 { match self.decoded { HeaderRecord::Bitmap(BitmapHeader { height, .. }) => height, @@ -204,6 +211,7 @@ } /// The biggest value a sample can have. In other words, the colour resolution. + #[must_use] pub fn maximal_sample(&self) -> u32 { match self.decoded { HeaderRecord::Bitmap(BitmapHeader { .. }) => 1, @@ -214,6 +222,7 @@ } /// Retrieve the underlying bitmap header if any + #[must_use] pub fn as_bitmap(&self) -> Option<&BitmapHeader> { match self.decoded { HeaderRecord::Bitmap(ref bitmap) => Some(bitmap), @@ -222,6 +231,7 @@ } /// Retrieve the underlying graymap header if any + #[must_use] pub fn as_graymap(&self) -> Option<&GraymapHeader> { match self.decoded { HeaderRecord::Graymap(ref graymap) => Some(graymap), @@ -230,6 +240,7 @@ } /// Retrieve the underlying pixmap header if any + #[must_use] pub fn as_pixmap(&self) -> Option<&PixmapHeader> { match self.decoded { HeaderRecord::Pixmap(ref pixmap) => Some(pixmap), @@ -238,6 +249,7 @@ } /// Retrieve the underlying arbitrary header if any + #[must_use] pub fn as_arbitrary(&self) -> Option<&ArbitraryHeader> { match self.decoded { HeaderRecord::Arbitrary(ref arbitrary) => Some(arbitrary), @@ -261,7 +273,7 @@ height, }), .. - } => writeln!(writer, "\n{} {}", width, height), + } => writeln!(writer, "\n{width} {height}"), PnmHeader { decoded: HeaderRecord::Graymap(GraymapHeader { @@ -271,7 +283,7 @@ maxwhite, }), .. - } => writeln!(writer, "\n{} {} {}", width, height, maxwhite), + } => writeln!(writer, "\n{width} {height} {maxwhite}"), PnmHeader { decoded: HeaderRecord::Pixmap(PixmapHeader { @@ -281,7 +293,7 @@ maxval, }), .. - } => writeln!(writer, "\n{} {} {}", width, height, maxval), + } => writeln!(writer, "\n{width} {height} {maxval}"), PnmHeader { decoded: HeaderRecord::Arbitrary(ArbitraryHeader { @@ -294,7 +306,7 @@ .. } => { struct TupltypeWriter<'a>(&'a Option); - impl<'a> fmt::Display for TupltypeWriter<'a> { + impl fmt::Display for TupltypeWriter<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { Some(tt) => writeln!(f, "TUPLTYPE {}", tt.name()), diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/pnm/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/pnm/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,9 @@ //! Decoding of netpbm image formats (pbm, pgm, ppm and pam). //! -//! The formats pbm, pgm and ppm are fully supported. The pam decoder recognizes the tuple types -//! `BLACKANDWHITE`, `GRAYSCALE` and `RGB` and explicitly recognizes but rejects their `_ALPHA` -//! variants for now as alpha color types are unsupported. +//! The formats pbm, pgm and ppm are fully supported. Only the official subformats +//! (`BLACKANDWHITE`, `GRAYSCALE`, `RGB`, `BLACKANDWHITE_ALPHA`, `GRAYSCALE_ALPHA`, +//! and `RGB_ALPHA`) of pam are supported; custom tuple types have no clear +//! interpretation as an image and will be rejected. use self::autobreak::AutoBreak; pub use self::decoder::PnmDecoder; pub use self::encoder::PnmEncoder; @@ -20,11 +21,11 @@ #[cfg(test)] mod tests { use super::*; - use crate::color::ColorType; - use crate::image::ImageDecoder; - use byteorder::{ByteOrder, NativeEndian}; + use crate::ExtendedColorType; + use crate::ImageDecoder as _; + use byteorder_lite::{ByteOrder, NativeEndian}; - fn execute_roundtrip_default(buffer: &[u8], width: u32, height: u32, color: ColorType) { + fn execute_roundtrip_default(buffer: &[u8], width: u32, height: u32, color: ExtendedColorType) { let mut encoded_buffer = Vec::new(); { @@ -47,7 +48,7 @@ assert_eq!(header.width(), width); assert_eq!(header.height(), height); - assert_eq!(loaded_color, color); + assert_eq!(ExtendedColorType::from(loaded_color), color); assert_eq!(loaded_image.as_slice(), buffer); } @@ -55,7 +56,7 @@ buffer: &[u8], width: u32, height: u32, - color: ColorType, + color: ExtendedColorType, subtype: PnmSubtype, ) { let mut encoded_buffer = Vec::new(); @@ -81,11 +82,11 @@ assert_eq!(header.width(), width); assert_eq!(header.height(), height); assert_eq!(header.subtype(), subtype); - assert_eq!(loaded_color, color); + assert_eq!(ExtendedColorType::from(loaded_color), color); assert_eq!(loaded_image.as_slice(), buffer); } - fn execute_roundtrip_u16(buffer: &[u16], width: u32, height: u32, color: ColorType) { + fn execute_roundtrip_u16(buffer: &[u16], width: u32, height: u32, color: ExtendedColorType) { let mut encoded_buffer = Vec::new(); { @@ -111,7 +112,7 @@ assert_eq!(header.width(), width); assert_eq!(header.height(), height); - assert_eq!(loaded_color, color); + assert_eq!(ExtendedColorType::from(loaded_color), color); assert_eq!(loaded_image, buffer_u8); } @@ -125,20 +126,20 @@ 255, 0, 0, 0, ]; - execute_roundtrip_default(&buf, 4, 4, ColorType::L8); - execute_roundtrip_with_subtype(&buf, 4, 4, ColorType::L8, PnmSubtype::ArbitraryMap); + execute_roundtrip_default(&buf, 4, 4, ExtendedColorType::L8); + execute_roundtrip_with_subtype(&buf, 4, 4, ExtendedColorType::L8, PnmSubtype::ArbitraryMap); execute_roundtrip_with_subtype( &buf, 4, 4, - ColorType::L8, + ExtendedColorType::L8, PnmSubtype::Graymap(SampleEncoding::Ascii), ); execute_roundtrip_with_subtype( &buf, 4, 4, - ColorType::L8, + ExtendedColorType::L8, PnmSubtype::Graymap(SampleEncoding::Binary), ); } @@ -157,20 +158,26 @@ 255, 255, 255, 255, 255, 255, ]; - execute_roundtrip_default(&buf, 3, 3, ColorType::Rgb8); - execute_roundtrip_with_subtype(&buf, 3, 3, ColorType::Rgb8, PnmSubtype::ArbitraryMap); + execute_roundtrip_default(&buf, 3, 3, ExtendedColorType::Rgb8); execute_roundtrip_with_subtype( &buf, 3, 3, - ColorType::Rgb8, + ExtendedColorType::Rgb8, + PnmSubtype::ArbitraryMap, + ); + execute_roundtrip_with_subtype( + &buf, + 3, + 3, + ExtendedColorType::Rgb8, PnmSubtype::Pixmap(SampleEncoding::Binary), ); execute_roundtrip_with_subtype( &buf, 3, 3, - ColorType::Rgb8, + ExtendedColorType::Rgb8, PnmSubtype::Pixmap(SampleEncoding::Ascii), ); } @@ -179,6 +186,6 @@ fn roundtrip_u16() { let buf: [u16; 6] = [0, 1, 0xFFFF, 0x1234, 0x3412, 0xBEAF]; - execute_roundtrip_u16(&buf, 6, 1, ColorType::L16); + execute_roundtrip_u16(&buf, 6, 1, ExtendedColorType::L16); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/qoi.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/qoi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/qoi.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/qoi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,10 @@ //! Decoding and encoding of QOI images +use crate::error::{DecodingError, EncodingError, UnsupportedError, UnsupportedErrorKind}; use crate::{ - error::{DecodingError, EncodingError}, - ColorType, ImageDecoder, ImageEncoder, ImageError, ImageFormat, ImageResult, + ColorType, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageFormat, ImageResult, }; -use std::io::{Cursor, Read, Write}; +use std::io::{Read, Write}; /// QOI decoder pub struct QoiDecoder { @@ -22,9 +22,7 @@ } } -impl<'a, R: Read + 'a> ImageDecoder<'a> for QoiDecoder { - type Reader = Cursor>; - +impl ImageDecoder for QoiDecoder { fn dimensions(&self) -> (u32, u32) { (self.decoder.header().width, self.decoder.header().height) } @@ -36,9 +34,13 @@ } } - fn into_reader(mut self) -> ImageResult { - let buffer = self.decoder.decode_to_vec().map_err(decoding_error)?; - Ok(Cursor::new(buffer)) + fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { + self.decoder.decode_to_buf(buf).map_err(decoding_error)?; + Ok(()) + } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } } @@ -69,17 +71,21 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - if !matches!(color_type, ColorType::Rgba8 | ColorType::Rgb8) { - return Err(ImageError::Encoding(EncodingError::new( - ImageFormat::Qoi.into(), - format!("unsupported color type {color_type:?}. Supported are Rgba8 and Rgb8."), - ))); + if !matches!( + color_type, + ExtendedColorType::Rgba8 | ExtendedColorType::Rgb8 + ) { + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Qoi.into(), + UnsupportedErrorKind::Color(color_type), + ), + )); } - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, buf.len() as u64, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,16 +1,14 @@ -use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK}; +use super::header::{Header, ImageType, ALPHA_BIT_MASK}; +use crate::error::DecodingError; +use crate::io::ReadExt; +use crate::utils::vec_try_with_capacity; use crate::{ color::{ColorType, ExtendedColorType}, - error::{ - ImageError, ImageResult, LimitError, LimitErrorKind, UnsupportedError, UnsupportedErrorKind, - }, - image::{ImageDecoder, ImageFormat, ImageReadBuffer}, -}; -use byteorder::ReadBytesExt; -use std::{ - io::{self, Read, Seek}, - mem, + error::{ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind}, + ImageDecoder, ImageFormat, }; +use byteorder_lite::ReadBytesExt; +use std::io::{self, Read}; struct ColorMap { /// sizes in bytes @@ -20,27 +18,9 @@ } impl ColorMap { - pub(crate) fn from_reader( - r: &mut dyn Read, - start_offset: u16, - num_entries: u16, - bits_per_entry: u8, - ) -> ImageResult { - let bytes_per_entry = (bits_per_entry as usize + 7) / 8; - - let mut bytes = vec![0; bytes_per_entry * num_entries as usize]; - r.read_exact(&mut bytes)?; - - Ok(ColorMap { - entry_size: bytes_per_entry, - start_offset: start_offset as usize, - bytes, - }) - } - /// Get one entry from the color map pub(crate) fn get(&self, index: usize) -> Option<&[u8]> { - let entry = self.start_offset + self.entry_size * index; + let entry = self.entry_size * index.checked_sub(self.start_offset)?; self.bytes.get(entry..entry + self.entry_size) } } @@ -51,8 +31,10 @@ width: usize, height: usize, - bytes_per_pixel: usize, - has_loaded_metadata: bool, + + // The number of bytes in the raw input data for each pixel. If a color map is used, this is the + // number of bytes for each color map index. + raw_bytes_per_pixel: usize, image_type: ImageType, color_type: ColorType, @@ -60,187 +42,190 @@ header: Header, color_map: Option, - - // Used in read_scanline - line_read: Option, - line_remain_buff: Vec, } -impl TgaDecoder { - /// Create a new decoder that decodes from the stream `r` - pub fn new(r: R) -> ImageResult> { - let mut decoder = TgaDecoder { - r, - - width: 0, - height: 0, - bytes_per_pixel: 0, - has_loaded_metadata: false, - - image_type: ImageType::Unknown, - color_type: ColorType::L8, - original_color_type: None, - - header: Header::default(), - color_map: None, - - line_read: None, - line_remain_buff: Vec::new(), - }; - decoder.read_metadata()?; - Ok(decoder) - } +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] +enum TgaOrientation { + TopLeft, + TopRight, + BottomRight, + BottomLeft, +} - fn read_header(&mut self) -> ImageResult<()> { - self.header = Header::from_reader(&mut self.r)?; - self.image_type = ImageType::new(self.header.image_type); - self.width = self.header.image_width as usize; - self.height = self.header.image_height as usize; - self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8; - Ok(()) +impl TgaOrientation { + fn from_image_desc_byte(value: u8) -> Self { + // Set bits 4 and 5 indicates direction, if bit 4 is set then pixel order right -> left, + // when bit 5 is set it indicates rows top -> bottom direction. + // Sources: + // https://en.wikipedia.org/wiki/Truevision_TGA ; Image specification (field 5) + if value & (1u8 << 4) == 0 { + // Left -> Right + if value & (1u8 << 5) == 0 { + TgaOrientation::BottomLeft + } else { + TgaOrientation::TopLeft + } + } else { + // Right -> Left + if value & (1u8 << 5) == 0 { + TgaOrientation::BottomRight + } else { + TgaOrientation::TopRight + } + } } +} - fn read_metadata(&mut self) -> ImageResult<()> { - if !self.has_loaded_metadata { - self.read_header()?; - self.read_image_id()?; - self.read_color_map()?; - self.read_color_information()?; - self.has_loaded_metadata = true; +impl TgaDecoder { + /// Create a new decoder that decodes from the stream `r` + pub fn new(mut r: R) -> ImageResult> { + // Read header + let header = Header::from_reader(&mut r)?; + let image_type = ImageType::new(header.image_type); + let width = header.image_width as usize; + let height = header.image_height as usize; + let raw_bytes_per_pixel = (header.pixel_depth as usize).div_ceil(8); + let num_alpha_bits = header.image_desc & ALPHA_BIT_MASK; + + if width == 0 || height == 0 { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "Invalid empty image", + ))); } - Ok(()) - } - /// Loads the color information for the decoder - /// - /// To keep things simple, we won't handle bit depths that aren't divisible - /// by 8 and are larger than 32. - fn read_color_information(&mut self) -> ImageResult<()> { - if self.header.pixel_depth % 8 != 0 || self.header.pixel_depth > 32 { - // Bit depth must be divisible by 8, and must be less than or equal - // to 32. + // Validate header + if ![8, 16, 24, 32].contains(&header.pixel_depth) || ![0, 8].contains(&num_alpha_bits) { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), + UnsupportedErrorKind::Color(ExtendedColorType::Unknown(header.pixel_depth)), ), )); } + if image_type.is_color_mapped() { + if header.map_type != 1 { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "Color map type must be 1 for color mapped images", + ))); + } else if ![8, 16].contains(&header.pixel_depth) { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "Color map must use 1 or 2 byte indexes", + ))); + } else if header.pixel_depth > header.map_entry_size { + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Tga.into(), + UnsupportedErrorKind::GenericFeature( + "Indices larger than pixel values".into(), + ), + ), + )); + } + } - let num_alpha_bits = self.header.image_desc & ALPHA_BIT_MASK; + // TODO: validate the rest of the fields in the header. - let other_channel_bits = if self.header.map_type != 0 { - self.header.map_entry_size - } else { - if num_alpha_bits > self.header.pixel_depth { + // Read image ID (and ignore it) + let mut tmp = [0u8; 256]; + r.read_exact(&mut tmp[0..header.id_length as usize])?; + + // Read color map + let mut color_map = None; + if header.map_type == 1 { + let entry_size = (header.map_entry_size as usize).div_ceil(8); + if ![2, 3, 4].contains(&entry_size) { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), + UnsupportedErrorKind::GenericFeature( + "Unsupported color map entry size".into(), + ), ), )); } - self.header.pixel_depth - num_alpha_bits + let mut bytes = Vec::new(); + r.read_exact_vec(&mut bytes, entry_size * header.map_length as usize)?; + + // Color maps are technically allowed in non-color-mapped images, so check that we + // actually need the color map before storing it. + if image_type.is_color_mapped() { + color_map = Some(ColorMap { + entry_size, + start_offset: header.map_origin as usize, + bytes, + }); + } + } + + // Compute output pixel depth + let total_pixel_bits = if header.map_type == 1 { + header.map_entry_size + } else { + header.pixel_depth }; - let color = self.image_type.is_color(); + let num_other_bits = total_pixel_bits + .checked_sub(num_alpha_bits) + .ok_or_else(|| { + ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "More alpha bits than pixel bits", + )) + })?; - match (num_alpha_bits, other_channel_bits, color) { - // really, the encoding is BGR and BGRA, this is fixed - // up with `TgaDecoder::reverse_encoding`. - (0, 32, true) => self.color_type = ColorType::Rgba8, - (8, 24, true) => self.color_type = ColorType::Rgba8, - (0, 24, true) => self.color_type = ColorType::Rgb8, - (8, 8, false) => self.color_type = ColorType::La8, - (0, 8, false) => self.color_type = ColorType::L8, + // Determine color type + let color_type; + let mut original_color_type = None; + match (num_alpha_bits, num_other_bits, image_type.is_color()) { + // really, the encoding is BGR and BGRA, this is fixed up with + // `TgaDecoder::reverse_encoding`. + (0, 32, true) => color_type = ColorType::Rgba8, + (8, 24, true) => color_type = ColorType::Rgba8, + (0, 24, true) => color_type = ColorType::Rgb8, + (8, 8, false) => color_type = ColorType::La8, + (0, 8, false) => color_type = ColorType::L8, (8, 0, false) => { // alpha-only image is treated as L8 - self.color_type = ColorType::L8; - self.original_color_type = Some(ExtendedColorType::A8); + color_type = ColorType::L8; + original_color_type = Some(ExtendedColorType::A8); } _ => { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), + UnsupportedErrorKind::Color(ExtendedColorType::Unknown(header.pixel_depth)), ), )) } } - Ok(()) - } - - /// Read the image id field - /// - /// We're not interested in this field, so this function skips it if it - /// is present - fn read_image_id(&mut self) -> ImageResult<()> { - self.r - .seek(io::SeekFrom::Current(i64::from(self.header.id_length)))?; - Ok(()) - } - - fn read_color_map(&mut self) -> ImageResult<()> { - if self.header.map_type == 1 { - // FIXME: we could reverse the map entries, which avoids having to reverse all pixels - // in the final output individually. - self.color_map = Some(ColorMap::from_reader( - &mut self.r, - self.header.map_origin, - self.header.map_length, - self.header.map_entry_size, - )?); - } - Ok(()) - } - - /// Expands indices into its mapped color - fn expand_color_map(&self, pixel_data: &[u8]) -> io::Result> { - #[inline] - fn bytes_to_index(bytes: &[u8]) -> usize { - let mut result = 0usize; - for byte in bytes.iter() { - result = result << 8 | *byte as usize; - } - result - } - - let bytes_per_entry = (self.header.map_entry_size as usize + 7) / 8; - let mut result = Vec::with_capacity(self.width * self.height * bytes_per_entry); - - if self.bytes_per_pixel == 0 { - return Err(io::ErrorKind::Other.into()); - } - let color_map = self - .color_map - .as_ref() - .ok_or_else(|| io::Error::from(io::ErrorKind::Other))?; + Ok(TgaDecoder { + r, - for chunk in pixel_data.chunks(self.bytes_per_pixel) { - let index = bytes_to_index(chunk); - if let Some(color) = color_map.get(index) { - result.extend_from_slice(color); - } else { - return Err(io::ErrorKind::Other.into()); - } - } + width, + height, + raw_bytes_per_pixel, + + image_type, + color_type, + original_color_type, - Ok(result) + header, + color_map, + }) } /// Reads a run length encoded data for given number of bytes - fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result> { - let mut pixel_data = Vec::with_capacity(num_bytes); - let mut repeat_buf = Vec::with_capacity(self.bytes_per_pixel); + fn read_encoded_data(&mut self, buf: &mut [u8]) -> io::Result<()> { + assert!(self.raw_bytes_per_pixel <= 4); + let mut repeat_buf = [0; 4]; + let repeat_buf = &mut repeat_buf[..self.raw_bytes_per_pixel]; - while pixel_data.len() < num_bytes { + let mut index = 0; + while index < buf.len() { let run_packet = self.r.read_u8()?; // If the highest bit in `run_packet` is set, then we repeat pixels // @@ -249,76 +234,69 @@ if (run_packet & 0x80) != 0 { // high bit set, so we will repeat the data let repeat_count = ((run_packet & !0x80) + 1) as usize; - self.r - .by_ref() - .take(self.bytes_per_pixel as u64) - .read_to_end(&mut repeat_buf)?; - - // get the repeating pixels from the bytes of the pixel stored in `repeat_buf` - let data = repeat_buf - .iter() - .cycle() - .take(repeat_count * self.bytes_per_pixel); - pixel_data.extend(data); - repeat_buf.clear(); + self.r.read_exact(repeat_buf)?; + + for chunk in buf[index..] + .chunks_exact_mut(self.raw_bytes_per_pixel) + .take(repeat_count) + { + chunk.copy_from_slice(repeat_buf); + } + index += repeat_count * self.raw_bytes_per_pixel; } else { // not set, so `run_packet+1` is the number of non-encoded pixels - let num_raw_bytes = (run_packet + 1) as usize * self.bytes_per_pixel; - self.r - .by_ref() - .take(num_raw_bytes as u64) - .read_to_end(&mut pixel_data)?; - } - } + let num_raw_bytes = + ((run_packet + 1) as usize * self.raw_bytes_per_pixel).min(buf.len() - index); - if pixel_data.len() > num_bytes { - // FIXME: the last packet contained more data than we asked for! - // This is at least a warning. We truncate the data since some methods rely on the - // length to be accurate in the success case. - pixel_data.truncate(num_bytes); + self.r.read_exact(&mut buf[index..][..num_raw_bytes])?; + index += num_raw_bytes; + } } - Ok(pixel_data) - } - - /// Reads a run length encoded packet - fn read_all_encoded_data(&mut self) -> ImageResult> { - let num_bytes = self.width * self.height * self.bytes_per_pixel; - - Ok(self.read_encoded_data(num_bytes)?) + Ok(()) } - /// Reads a run length encoded line - fn read_encoded_line(&mut self) -> io::Result> { - let line_num_bytes = self.width * self.bytes_per_pixel; - let remain_len = self.line_remain_buff.len(); - - if remain_len >= line_num_bytes { - // `Vec::split_to` if std had it - let bytes = { - let bytes_after = self.line_remain_buff.split_off(line_num_bytes); - mem::replace(&mut self.line_remain_buff, bytes_after) - }; - - return Ok(bytes); + /// Expands indices into its mapped color + fn expand_color_map( + &self, + input: &[u8], + output: &mut [u8], + color_map: &ColorMap, + ) -> ImageResult<()> { + if self.raw_bytes_per_pixel == 1 { + for (&index, chunk) in input + .iter() + .zip(output.chunks_exact_mut(color_map.entry_size)) + { + if let Some(color) = color_map.get(index as usize) { + chunk.copy_from_slice(color); + } else { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "Invalid color map index", + ))); + } + } + } else if self.raw_bytes_per_pixel == 2 { + for (index, chunk) in input + .chunks_exact(2) + .zip(output.chunks_exact_mut(color_map.entry_size)) + { + let index = u16::from_le_bytes(index.try_into().unwrap()); + if let Some(color) = color_map.get(index as usize) { + chunk.copy_from_slice(color); + } else { + return Err(ImageError::Decoding(DecodingError::new( + ImageFormat::Tga.into(), + "Invalid color map index", + ))); + } + } + } else { + unreachable!("Supported bytes_per_pixel values are checked in TgaDecoder::new"); } - let num_bytes = line_num_bytes - remain_len; - - let line_data = self.read_encoded_data(num_bytes)?; - - let mut pixel_data = Vec::with_capacity(line_num_bytes); - pixel_data.append(&mut self.line_remain_buff); - pixel_data.extend_from_slice(&line_data[..num_bytes]); - - // put the remain data to line_remain_buff. - // expects `self.line_remain_buff` to be empty from - // the above `pixel_data.append` call - debug_assert!(self.line_remain_buff.is_empty()); - self.line_remain_buff - .extend_from_slice(&line_data[num_bytes..]); - - Ok(pixel_data) + Ok(()) } /// Reverse from BGR encoding to RGB encoding @@ -337,82 +315,49 @@ } } - /// Flip the image vertically depending on the screen origin bit - /// - /// The bit in position 5 of the image descriptor byte is the screen origin bit. - /// If it's 1, the origin is in the top left corner. - /// If it's 0, the origin is in the bottom left corner. - /// This function checks the bit, and if it's 0, flips the image vertically. - fn flip_vertically(&mut self, pixels: &mut [u8]) { - if self.is_flipped_vertically() { - if self.height == 0 { - return; - } - - let num_bytes = pixels.len(); - - let width_bytes = num_bytes / self.height; - - // Flip the image vertically. - for vertical_index in 0..(self.height / 2) { - let vertical_target = (self.height - vertical_index) * width_bytes - width_bytes; - - for horizontal_index in 0..width_bytes { - let source = vertical_index * width_bytes + horizontal_index; - let target = vertical_target + horizontal_index; - - pixels.swap(target, source); + /// Change image orientation depending on the flags set + fn fixup_orientation(&mut self, pixels: &mut [u8]) { + let orientation = TgaOrientation::from_image_desc_byte(self.header.image_desc); + + // Flip image if bottom->top direction + if (orientation == TgaOrientation::BottomLeft || orientation == TgaOrientation::BottomRight) + && self.height > 1 + { + let row_stride = self.width * self.raw_bytes_per_pixel; + + let (left_part, right_part) = pixels.split_at_mut(self.height / 2 * row_stride); + + for (src, dst) in left_part + .chunks_exact_mut(row_stride) + .zip(right_part.chunks_exact_mut(row_stride).rev()) + { + for (src, dst) in src.iter_mut().zip(dst.iter_mut()) { + std::mem::swap(src, dst); } } } - } - - /// Check whether the image is vertically flipped - /// - /// The bit in position 5 of the image descriptor byte is the screen origin bit. - /// If it's 1, the origin is in the top left corner. - /// If it's 0, the origin is in the bottom left corner. - /// This function checks the bit, and if it's 0, flips the image vertically. - fn is_flipped_vertically(&self) -> bool { - let screen_origin_bit = SCREEN_ORIGIN_BIT_MASK & self.header.image_desc != 0; - !screen_origin_bit - } - fn read_scanline(&mut self, buf: &mut [u8]) -> io::Result { - if let Some(line_read) = self.line_read { - if line_read == self.height { - return Ok(0); + // Flop image if right->left direction + if (orientation == TgaOrientation::BottomRight || orientation == TgaOrientation::TopRight) + && self.width > 1 + { + for row in pixels.chunks_exact_mut(self.width * self.raw_bytes_per_pixel) { + let (left_part, right_part) = + row.split_at_mut(self.width / 2 * self.raw_bytes_per_pixel); + for (src, dst) in left_part + .chunks_exact_mut(self.raw_bytes_per_pixel) + .zip(right_part.chunks_exact_mut(self.raw_bytes_per_pixel).rev()) + { + for (src, dst) in src.iter_mut().zip(dst.iter_mut()) { + std::mem::swap(dst, src); + } + } } } - - // read the pixels from the data region - let mut pixel_data = if self.image_type.is_encoded() { - self.read_encoded_line()? - } else { - let num_raw_bytes = self.width * self.bytes_per_pixel; - let mut buf = vec![0; num_raw_bytes]; - self.r.by_ref().read_exact(&mut buf)?; - buf - }; - - // expand the indices using the color map if necessary - if self.image_type.is_color_mapped() { - pixel_data = self.expand_color_map(&pixel_data)?; - } - self.reverse_encoding_in_output(&mut pixel_data); - - // copy to the output buffer - buf[..pixel_data.len()].copy_from_slice(&pixel_data); - - self.line_read = Some(self.line_read.unwrap_or(0) + 1); - - Ok(pixel_data.len()) } } -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TgaDecoder { - type Reader = TGAReader; - +impl ImageDecoder for TgaDecoder { fn dimensions(&self) -> (u32, u32) { (self.width as u32, self.height as u32) } @@ -426,80 +371,39 @@ .unwrap_or_else(|| self.color_type().into()) } - fn scanline_bytes(&self) -> u64 { - // This cannot overflow because TGA has a maximum width of u16::MAX_VALUE and - // `bytes_per_pixel` is a u8. - u64::from(self.color_type.bytes_per_pixel()) * self.width as u64 - } - - fn into_reader(self) -> ImageResult { - Ok(TGAReader { - buffer: ImageReadBuffer::new( - #[allow(deprecated)] - self.scanline_bytes(), - self.total_bytes(), - ), - decoder: self, - }) - } - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - // In indexed images, we might need more bytes than pixels to read them. That's nonsensical - // to encode but we'll not want to crash. - let mut fallback_buf = vec![]; - // read the pixels from the data region - let rawbuf = if self.image_type.is_encoded() { - let pixel_data = self.read_all_encoded_data()?; - if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) { - buf[..pixel_data.len()].copy_from_slice(&pixel_data); - &buf[..pixel_data.len()] - } else { - fallback_buf = pixel_data; - &fallback_buf[..] - } + // Decode the raw data + // + // We have already checked in `TgaDecoder::new` that the indices take less space than the + // pixels they encode, so it is safe to read the raw data into `buf`. + let num_raw_bytes = self.width * self.height * self.raw_bytes_per_pixel; + if self.image_type.is_encoded() { + self.read_encoded_data(&mut buf[..num_raw_bytes])?; } else { - let num_raw_bytes = self.width * self.height * self.bytes_per_pixel; - if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) { - self.r.by_ref().read_exact(&mut buf[..num_raw_bytes])?; - &buf[..num_raw_bytes] - } else { - fallback_buf.resize(num_raw_bytes, 0u8); - self.r - .by_ref() - .read_exact(&mut fallback_buf[..num_raw_bytes])?; - &fallback_buf[..num_raw_bytes] - } - }; + self.r.read_exact(&mut buf[..num_raw_bytes])?; + } - // expand the indices using the color map if necessary - if self.image_type.is_color_mapped() { - let pixel_data = self.expand_color_map(rawbuf)?; - // not enough data to fill the buffer, or would overflow the buffer - if pixel_data.len() != buf.len() { - return Err(ImageError::Limits(LimitError::from_kind( - LimitErrorKind::DimensionError, - ))); - } - buf.copy_from_slice(&pixel_data); + self.fixup_orientation(&mut buf[..num_raw_bytes]); + + // Expand the indices using the color map if necessary + if let Some(ref color_map) = self.color_map { + // This allocation could be avoided by expanding each row (or block of pixels) as it is + // read, or by doing the color map expansion in-place. But those may be more effort than + // it is worth. + let mut rawbuf = vec_try_with_capacity(num_raw_bytes)?; + rawbuf.extend_from_slice(&buf[..num_raw_bytes]); + + self.expand_color_map(&rawbuf, buf, color_map)?; } self.reverse_encoding_in_output(buf); - self.flip_vertically(buf); - Ok(()) } -} -pub struct TGAReader { - buffer: ImageReadBuffer, - decoder: TgaDecoder, -} -impl Read for TGAReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let decoder = &mut self.decoder; - self.buffer.read(buf, |buf| decoder.read_scanline(buf)) + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,6 @@ use super::header::Header; -use crate::{ - codecs::tga::header::ImageType, error::EncodingError, ColorType, ImageEncoder, ImageError, - ImageFormat, ImageResult, -}; +use crate::{codecs::tga::header::ImageType, error::EncodingError, utils::vec_try_with_capacity}; +use crate::{DynamicImage, ExtendedColorType, ImageEncoder, ImageError, ImageFormat, ImageResult}; use std::{error, fmt, io::Write}; /// Errors that can occur during encoding and saving of a TGA image. @@ -13,15 +11,17 @@ /// Invalid TGA height. HeightInvalid(u32), + + /// Empty + Empty(u32, u32), } impl fmt::Display for EncoderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - EncoderError::WidthInvalid(s) => f.write_fmt(format_args!("Invalid TGA width: {}", s)), - EncoderError::HeightInvalid(s) => { - f.write_fmt(format_args!("Invalid TGA height: {}", s)) - } + EncoderError::WidthInvalid(s) => f.write_fmt(format_args!("Invalid TGA width: {s}")), + EncoderError::HeightInvalid(s) => f.write_fmt(format_args!("Invalid TGA height: {s}")), + EncoderError::Empty(w, h) => f.write_fmt(format_args!("Invalid TGA size: {w}x{h}")), } } } @@ -85,15 +85,19 @@ } /// Writes the run-length encoded buffer to the writer - fn run_length_encode(&mut self, image: &[u8], color_type: ColorType) -> ImageResult<()> { + fn run_length_encode( + &mut self, + image: &[u8], + color_type: ExtendedColorType, + ) -> ImageResult<()> { use PacketType::*; - let bytes_per_pixel = color_type.bytes_per_pixel(); + let bytes_per_pixel = color_type.bits_per_pixel() / 8; let capacity_in_bytes = usize::from(MAX_RUN_LENGTH) * usize::from(bytes_per_pixel); // Buffer to temporarily store pixels // so we can choose whether to use RLE or not when we need to - let mut buf = Vec::with_capacity(capacity_in_bytes); + let mut buf = vec_try_with_capacity(capacity_in_bytes)?; let mut counter = 0; let mut prev_pixel = None; @@ -162,10 +166,9 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color_type.bytes_per_pixel() as u64); + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, buf.len() as u64, @@ -174,6 +177,10 @@ ); // Validate dimensions. + if width == 0 || height == 0 { + return Err(ImageError::from(EncoderError::Empty(width, height))); + } + let width = u16::try_from(width) .map_err(|_| ImageError::from(EncoderError::WidthInvalid(width)))?; @@ -192,10 +199,11 @@ // Write run-length encoded image data match color_type { - ColorType::Rgb8 | ColorType::Rgba8 => { + ExtendedColorType::Rgb8 | ExtendedColorType::Rgba8 => { let mut image = Vec::from(buf); - for pixel in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) { + for pixel in image.chunks_mut(usize::from(color_type.bits_per_pixel() / 8)) + { pixel.swap(0, 2); } @@ -210,10 +218,11 @@ // Write uncompressed image data match color_type { - ColorType::Rgb8 | ColorType::Rgba8 => { + ExtendedColorType::Rgb8 | ExtendedColorType::Rgba8 => { let mut image = Vec::from(buf); - for pixel in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) { + for pixel in image.chunks_mut(usize::from(color_type.bits_per_pixel() / 8)) + { pixel.swap(0, 2); } @@ -237,16 +246,24 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { self.encode(buf, width, height, color_type) } + + fn make_compatible_img( + &self, + _: crate::io::encoder::MethodSealedToImage, + img: &DynamicImage, + ) -> Option { + crate::io::encoder::dynimage_conversion_8bit(img) + } } #[cfg(test)] mod tests { use super::{EncoderError, TgaEncoder}; - use crate::{codecs::tga::TgaDecoder, ColorType, ImageDecoder, ImageError}; + use crate::{codecs::tga::TgaDecoder, ExtendedColorType, ImageDecoder, ImageError}; use std::{error::Error, io::Cursor}; #[test] @@ -260,7 +277,7 @@ // Try to encode an image that is too large let mut encoded = Vec::new(); let encoder = TgaEncoder::new(&mut encoded); - let result = encoder.encode(&img, dimension, 1, ColorType::L8); + let result = encoder.encode(&img, dimension, 1, ExtendedColorType::L8); match result { Err(ImageError::Encoding(err)) => { @@ -273,8 +290,7 @@ } other => panic!( "Encoding an image that is too wide should return a InvalidWidth \ - it returned {:?} instead", - other + it returned {other:?} instead" ), } } @@ -290,7 +306,7 @@ // Try to encode an image that is too large let mut encoded = Vec::new(); let encoder = TgaEncoder::new(&mut encoded); - let result = encoder.encode(&img, 1, dimension, ColorType::L8); + let result = encoder.encode(&img, 1, dimension, ExtendedColorType::L8); match result { Err(ImageError::Encoding(err)) => { @@ -303,8 +319,7 @@ } other => panic!( "Encoding an image that is too tall should return a InvalidHeight \ - it returned {:?} instead", - other + it returned {other:?} instead" ), } } @@ -317,7 +332,7 @@ let mut encoded_data = Vec::new(); let encoder = TgaEncoder::new(&mut encoded_data).disable_rle(); encoder - .encode(&image, 5, 1, ColorType::Rgb8) + .encode(&image, 5, 1, ExtendedColorType::Rgb8) .expect("could not encode image"); encoded_data @@ -327,7 +342,7 @@ let mut encoded_data = Vec::new(); let encoder = TgaEncoder::new(&mut encoded_data); encoder - .encode(&image, 5, 1, ColorType::Rgb8) + .encode(&image, 5, 1, ExtendedColorType::Rgb8) .expect("could not encode image"); encoded_data @@ -339,7 +354,12 @@ mod compressed { use super::*; - fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec { + fn round_trip_image( + image: &[u8], + width: u32, + height: u32, + c: ExtendedColorType, + ) -> Vec { let mut encoded_data = Vec::new(); { let encoder = TgaEncoder::new(&mut encoded_data); @@ -359,7 +379,7 @@ let image = [ 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, ]; - let decoded = round_trip_image(&image, 5, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 5, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -367,7 +387,7 @@ #[test] fn round_trip_gray() { let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 3, 1, ColorType::L8); + let decoded = round_trip_image(&image, 3, 1, ExtendedColorType::L8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -375,7 +395,7 @@ #[test] fn round_trip_graya() { let image = [0, 1, 2, 3, 4, 5]; - let decoded = round_trip_image(&image, 1, 3, ColorType::La8); + let decoded = round_trip_image(&image, 1, 3, ExtendedColorType::La8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -383,7 +403,7 @@ #[test] fn round_trip_single_pixel_rgb() { let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 1, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -391,7 +411,7 @@ #[test] fn round_trip_three_pixel_rgb() { let image = [0, 1, 2, 0, 1, 2, 0, 1, 2]; - let decoded = round_trip_image(&image, 3, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 3, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -399,7 +419,7 @@ #[test] fn round_trip_3px_rgb() { let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel - let decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8); + let decoded = round_trip_image(&image, 3, 3, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -407,7 +427,7 @@ #[test] fn round_trip_different() { let image = [0, 1, 2, 0, 1, 3, 0, 1, 4]; - let decoded = round_trip_image(&image, 3, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 3, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -415,7 +435,7 @@ #[test] fn round_trip_different_2() { let image = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 4]; - let decoded = round_trip_image(&image, 4, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 4, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -423,7 +443,7 @@ #[test] fn round_trip_different_3() { let image = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 4, 0, 1, 2]; - let decoded = round_trip_image(&image, 5, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 5, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -436,7 +456,7 @@ let (width, height) = (image.width(), image.height()); let image = image.as_rgb8().unwrap().to_vec(); - let decoded = round_trip_image(&image, width, height, ColorType::Rgb8); + let decoded = round_trip_image(&image, width, height, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -445,7 +465,12 @@ mod uncompressed { use super::*; - fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec { + fn round_trip_image( + image: &[u8], + width: u32, + height: u32, + c: ExtendedColorType, + ) -> Vec { let mut encoded_data = Vec::new(); { let encoder = TgaEncoder::new(&mut encoded_data).disable_rle(); @@ -464,7 +489,7 @@ #[test] fn round_trip_single_pixel_rgb() { let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8); + let decoded = round_trip_image(&image, 1, 1, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -472,7 +497,7 @@ #[test] fn round_trip_single_pixel_rgba() { let image = [0, 1, 2, 3]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8); + let decoded = round_trip_image(&image, 1, 1, ExtendedColorType::Rgba8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -480,7 +505,7 @@ #[test] fn round_trip_gray() { let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 3, 1, ColorType::L8); + let decoded = round_trip_image(&image, 3, 1, ExtendedColorType::L8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -488,7 +513,7 @@ #[test] fn round_trip_graya() { let image = [0, 1, 2, 3, 4, 5]; - let decoded = round_trip_image(&image, 1, 3, ColorType::La8); + let decoded = round_trip_image(&image, 1, 3, ExtendedColorType::La8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } @@ -496,7 +521,7 @@ #[test] fn round_trip_3px_rgb() { let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel - let decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8); + let decoded = round_trip_image(&image, 3, 3, ExtendedColorType::Rgb8); assert_eq!(decoded.len(), image.len()); assert_eq!(decoded.as_slice(), image); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/header.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/header.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tga/header.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tga/header.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,6 @@ -use crate::{ - error::{UnsupportedError, UnsupportedErrorKind}, - ColorType, ImageError, ImageFormat, ImageResult, -}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use crate::error::{UnsupportedError, UnsupportedErrorKind}; +use crate::{ExtendedColorType, ImageError, ImageFormat, ImageResult}; +use byteorder_lite::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::io::{Read, Write}; pub(crate) const ALPHA_BIT_MASK: u8 = 0b1111; @@ -51,12 +49,15 @@ /// Does the image use a color map. pub(crate) fn is_color_mapped(&self) -> bool { - matches! { *self, ImageType::RawColorMap | ImageType::RunColorMap } + matches!(*self, Self::RawColorMap | Self::RunColorMap) } /// Is the image run length encoded. pub(crate) fn is_encoded(&self) -> bool { - matches! {*self, ImageType::RunColorMap | ImageType::RunTrueColor | ImageType::RunGrayScale } + matches!( + *self, + Self::RunColorMap | Self::RunTrueColor | Self::RunGrayScale + ) } } @@ -80,7 +81,7 @@ impl Header { /// Load the header with values from pixel information. pub(crate) fn from_pixel_info( - color_type: ColorType, + color_type: ExtendedColorType, width: u16, height: u16, use_rle: bool, @@ -89,19 +90,19 @@ if width > 0 && height > 0 { let (num_alpha_bits, other_channel_bits, image_type) = match (color_type, use_rle) { - (ColorType::Rgba8, true) => (8, 24, ImageType::RunTrueColor), - (ColorType::Rgb8, true) => (0, 24, ImageType::RunTrueColor), - (ColorType::La8, true) => (8, 8, ImageType::RunGrayScale), - (ColorType::L8, true) => (0, 8, ImageType::RunGrayScale), - (ColorType::Rgba8, false) => (8, 24, ImageType::RawTrueColor), - (ColorType::Rgb8, false) => (0, 24, ImageType::RawTrueColor), - (ColorType::La8, false) => (8, 8, ImageType::RawGrayScale), - (ColorType::L8, false) => (0, 8, ImageType::RawGrayScale), + (ExtendedColorType::Rgba8, true) => (8, 24, ImageType::RunTrueColor), + (ExtendedColorType::Rgb8, true) => (0, 24, ImageType::RunTrueColor), + (ExtendedColorType::La8, true) => (8, 8, ImageType::RunGrayScale), + (ExtendedColorType::L8, true) => (0, 8, ImageType::RunGrayScale), + (ExtendedColorType::Rgba8, false) => (8, 24, ImageType::RawTrueColor), + (ExtendedColorType::Rgb8, false) => (0, 24, ImageType::RawTrueColor), + (ExtendedColorType::La8, false) => (8, 8, ImageType::RawGrayScale), + (ExtendedColorType::L8, false) => (0, 8, ImageType::RawGrayScale), _ => { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(color_type.into()), + UnsupportedErrorKind::Color(color_type), ), )) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tiff.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tiff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/tiff.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/tiff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,55 +5,74 @@ //! //! # Related Links //! * - The TIFF specification - -extern crate tiff; - -use std::io::{self, Cursor, Read, Seek, Write}; +use std::io::{self, BufRead, Cursor, Read, Seek, Write}; use std::marker::PhantomData; use std::mem; +use tiff::decoder::{Decoder, DecodingResult}; +use tiff::tags::Tag; + use crate::color::{ColorType, ExtendedColorType}; use crate::error::{ DecodingError, EncodingError, ImageError, ImageResult, LimitError, LimitErrorKind, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, }; -use crate::image::{ImageDecoder, ImageEncoder, ImageFormat}; -use crate::utils; +use crate::metadata::Orientation; +use crate::{utils, ImageDecoder, ImageEncoder, ImageFormat}; + +const TAG_XML_PACKET: Tag = Tag::Unknown(700); /// Decoder for TIFF images. pub struct TiffDecoder where - R: Read + Seek, + R: BufRead + Seek, { dimensions: (u32, u32), color_type: ColorType, original_color_type: ExtendedColorType, // We only use an Option here so we can call with_limits on the decoder without moving. - inner: Option>, + inner: Option>, } impl TiffDecoder where - R: Read + Seek, + R: BufRead + Seek, { - /// Create a new TiffDecoder. + /// Create a new `TiffDecoder`. pub fn new(r: R) -> Result, ImageError> { - let mut inner = tiff::decoder::Decoder::new(r).map_err(ImageError::from_tiff_decode)?; + let mut inner = Decoder::new(r).map_err(ImageError::from_tiff_decode)?; let dimensions = inner.dimensions().map_err(ImageError::from_tiff_decode)?; let tiff_color_type = inner.colortype().map_err(ImageError::from_tiff_decode)?; - match inner.find_tag_unsigned_vec::(tiff::tags::Tag::SampleFormat) { + + match inner.find_tag_unsigned_vec::(Tag::SampleFormat) { Ok(Some(sample_formats)) => { for format in sample_formats { - check_sample_format(format)?; + check_sample_format(format, tiff_color_type)?; } } Ok(None) => { /* assume UInt format */ } Err(other) => return Err(ImageError::from_tiff_decode(other)), - }; + } + + let planar_config = inner + .find_tag(Tag::PlanarConfiguration) + .map(|res| res.and_then(|r| r.into_u16().ok()).unwrap_or_default()) + .unwrap_or_default(); + + // Decode not supported for non Chunky Planar Configuration + if planar_config > 1 { + Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Tiff.into(), + UnsupportedErrorKind::GenericFeature(String::from("PlanarConfiguration = 2")), + ), + ))?; + } let color_type = match tiff_color_type { + tiff::ColorType::Gray(1) => ColorType::L8, tiff::ColorType::Gray(8) => ColorType::L8, tiff::ColorType::Gray(16) => ColorType::L16, tiff::ColorType::GrayA(8) => ColorType::La8, @@ -63,6 +82,9 @@ tiff::ColorType::RGBA(8) => ColorType::Rgba8, tiff::ColorType::RGBA(16) => ColorType::Rgba16, tiff::ColorType::CMYK(8) => ColorType::Rgb8, + tiff::ColorType::CMYK(16) => ColorType::Rgb16, + tiff::ColorType::RGB(32) => ColorType::Rgb32F, + tiff::ColorType::RGBA(32) => ColorType::Rgba32F, tiff::ColorType::Palette(n) | tiff::ColorType::Gray(n) => { return Err(err_unknown_color_type(n)) @@ -73,10 +95,21 @@ tiff::ColorType::RGBA(n) | tiff::ColorType::CMYK(n) => { return Err(err_unknown_color_type(n.saturating_mul(4))) } + tiff::ColorType::Multiband { + bit_depth, + num_samples, + } => { + return Err(err_unknown_color_type( + bit_depth.saturating_mul(num_samples.min(255) as u8), + )) + } + _ => return Err(err_unknown_color_type(0)), }; let original_color_type = match tiff_color_type { + tiff::ColorType::Gray(1) => ExtendedColorType::L1, tiff::ColorType::CMYK(8) => ExtendedColorType::Cmyk8, + tiff::ColorType::CMYK(16) => ExtendedColorType::Cmyk16, _ => color_type.into(), }; @@ -92,30 +125,57 @@ fn total_bytes_buffer(&self) -> u64 { let dimensions = self.dimensions(); let total_pixels = u64::from(dimensions.0) * u64::from(dimensions.1); - let bytes_per_pixel = if self.original_color_type == ExtendedColorType::Cmyk8 { - 16 - } else { - u64::from(self.color_type().bytes_per_pixel()) + + let bytes_per_pixel = match self.original_color_type { + ExtendedColorType::Cmyk8 => 4, + ExtendedColorType::Cmyk16 => 8, + _ => u64::from(self.color_type().bytes_per_pixel()), }; total_pixels.saturating_mul(bytes_per_pixel) } } -fn check_sample_format(sample_format: u16) -> Result<(), ImageError> { - match tiff::tags::SampleFormat::from_u16(sample_format) { - Some(tiff::tags::SampleFormat::Uint) => Ok(()), - Some(other) => Err(ImageError::Unsupported( +fn check_sample_format(sample_format: u16, color_type: tiff::ColorType) -> Result<(), ImageError> { + use tiff::{tags::SampleFormat, ColorType}; + let num_bits = match color_type { + ColorType::CMYK(k) => k, + ColorType::Gray(k) => k, + ColorType::RGB(k) => k, + ColorType::RGBA(k) => k, + ColorType::GrayA(k) => k, + ColorType::Palette(k) | ColorType::YCbCr(k) => { + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Tiff.into(), + UnsupportedErrorKind::GenericFeature(format!( + "Unhandled TIFF color type {color_type:?} for {k} bits", + )), + ), + )) + } + _ => { + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormat::Tiff.into(), + UnsupportedErrorKind::GenericFeature(format!( + "Unhandled TIFF color type {color_type:?}", + )), + ), + )) + } + }; + + match SampleFormat::from_u16(sample_format) { + Some(SampleFormat::Uint) if num_bits <= 16 => Ok(()), + Some(SampleFormat::IEEEFP) if num_bits == 32 => Ok(()), + _ => Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tiff.into(), UnsupportedErrorKind::GenericFeature(format!( - "Unhandled TIFF sample format {:?}", - other + "Unhandled TIFF sample format {sample_format:?} for {num_bits} bits", )), ), )), - None => Err(ImageError::Decoding(DecodingError::from_format_hint( - ImageFormat::Tiff.into(), - ))), } } @@ -130,9 +190,9 @@ fn from_tiff_decode(err: tiff::TiffError) -> ImageError { match err { tiff::TiffError::IoError(err) => ImageError::IoError(err), - err @ tiff::TiffError::FormatError(_) - | err @ tiff::TiffError::IntSizeError - | err @ tiff::TiffError::UsageError(_) => { + err @ (tiff::TiffError::FormatError(_) + | tiff::TiffError::IntSizeError + | tiff::TiffError::UsageError(_)) => { ImageError::Decoding(DecodingError::new(ImageFormat::Tiff.into(), err)) } tiff::TiffError::UnsupportedError(desc) => { @@ -150,9 +210,9 @@ fn from_tiff_encode(err: tiff::TiffError) -> ImageError { match err { tiff::TiffError::IoError(err) => ImageError::IoError(err), - err @ tiff::TiffError::FormatError(_) - | err @ tiff::TiffError::IntSizeError - | err @ tiff::TiffError::UsageError(_) => { + err @ (tiff::TiffError::FormatError(_) + | tiff::TiffError::IntSizeError + | tiff::TiffError::UsageError(_)) => { ImageError::Encoding(EncodingError::new(ImageFormat::Tiff.into(), err)) } tiff::TiffError::UnsupportedError(desc) => { @@ -169,11 +229,15 @@ } /// Wrapper struct around a `Cursor>` +#[allow(dead_code)] +#[deprecated] pub struct TiffReader(Cursor>, PhantomData); +#[allow(deprecated)] impl Read for TiffReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { if self.0.position() == 0 && buf.is_empty() { mem::swap(buf, self.0.get_mut()); @@ -184,9 +248,7 @@ } } -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TiffDecoder { - type Reader = TiffReader; - +impl ImageDecoder for TiffDecoder { fn dimensions(&self) -> (u32, u32) { self.dimensions } @@ -199,16 +261,46 @@ self.original_color_type } - fn icc_profile(&mut self) -> Option> { + fn icc_profile(&mut self) -> ImageResult>> { if let Some(decoder) = &mut self.inner { - decoder.get_tag_u8_vec(tiff::tags::Tag::Unknown(34675)).ok() + Ok(decoder.get_tag_u8_vec(Tag::Unknown(34675)).ok()) } else { - None + Ok(None) } } - fn set_limits(&mut self, limits: crate::io::Limits) -> ImageResult<()> { - limits.check_support(&crate::io::LimitSupport::default())?; + fn xmp_metadata(&mut self) -> ImageResult>> { + let Some(decoder) = &mut self.inner else { + return Ok(None); + }; + + let value = match decoder.get_tag(TAG_XML_PACKET) { + Ok(value) => value, + Err(tiff::TiffError::FormatError(tiff::TiffFormatError::RequiredTagNotFound(_))) => { + return Ok(None); + } + Err(err) => return Err(ImageError::from_tiff_decode(err)), + }; + value + .into_u8_vec() + .map(Some) + .map_err(ImageError::from_tiff_decode) + } + + fn orientation(&mut self) -> ImageResult { + if let Some(decoder) = &mut self.inner { + Ok(decoder + .find_tag(Tag::Orientation) + .map_err(ImageError::from_tiff_decode)? + .and_then(|v| Orientation::from_exif(v.into_u16().ok()?.min(255) as u8)) + .unwrap_or(Orientation::NoTransforms)) + } else { + Ok(Orientation::NoTransforms) + } + } + + fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { + limits.check_support(&crate::LimitSupport::default())?; let (width, height) = self.dimensions(); limits.check_dimensions(width, height)?; @@ -227,77 +319,76 @@ Ok(()) } - fn into_reader(self) -> ImageResult { - let buf = match self - .inner - .unwrap() - .read_image() - .map_err(ImageError::from_tiff_decode)? - { - tiff::decoder::DecodingResult::U8(v) => v, - tiff::decoder::DecodingResult::U16(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::U32(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::U64(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::I8(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::I16(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::I32(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::I64(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::F32(v) => utils::vec_copy_to_u8(&v), - tiff::decoder::DecodingResult::F64(v) => utils::vec_copy_to_u8(&v), - }; - - Ok(TiffReader(Cursor::new(buf), PhantomData)) - } - fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); + match self .inner .unwrap() .read_image() .map_err(ImageError::from_tiff_decode)? { - tiff::decoder::DecodingResult::U8(v) - if self.original_color_type == ExtendedColorType::Cmyk8 => - { + DecodingResult::U8(v) if self.original_color_type == ExtendedColorType::Cmyk8 => { let mut out_cur = Cursor::new(buf); for cmyk in v.chunks_exact(4) { out_cur.write_all(&cmyk_to_rgb(cmyk))?; } } - tiff::decoder::DecodingResult::U8(v) => { + DecodingResult::U16(v) if self.original_color_type == ExtendedColorType::Cmyk16 => { + let mut out_cur = Cursor::new(buf); + for cmyk in v.chunks_exact(4) { + out_cur.write_all(bytemuck::cast_slice(&cmyk_to_rgb16(cmyk)))?; + } + } + DecodingResult::U8(v) if self.original_color_type == ExtendedColorType::L1 => { + let width = self.dimensions.0; + let row_bytes = width.div_ceil(8); + + for (in_row, out_row) in v + .chunks_exact(row_bytes as usize) + .zip(buf.chunks_exact_mut(width as usize)) + { + out_row.copy_from_slice(&utils::expand_bits(1, width, in_row)); + } + } + DecodingResult::U8(v) => { buf.copy_from_slice(&v); } - tiff::decoder::DecodingResult::U16(v) => { + DecodingResult::U16(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::U32(v) => { + DecodingResult::U32(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::U64(v) => { + DecodingResult::U64(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::I8(v) => { + DecodingResult::I8(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::I16(v) => { + DecodingResult::I16(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::I32(v) => { + DecodingResult::I32(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::I64(v) => { + DecodingResult::I64(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::F32(v) => { + DecodingResult::F32(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } - tiff::decoder::DecodingResult::F64(v) => { + DecodingResult::F64(v) => { buf.copy_from_slice(bytemuck::cast_slice(&v)); } + DecodingResult::F16(_) => unreachable!(), } Ok(()) } + + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } } /// Encoder for tiff images @@ -306,10 +397,10 @@ } fn cmyk_to_rgb(cmyk: &[u8]) -> [u8; 3] { - let c = cmyk[0] as f32; - let m = cmyk[1] as f32; - let y = cmyk[2] as f32; - let kf = 1. - cmyk[3] as f32 / 255.; + let c = f32::from(cmyk[0]); + let m = f32::from(cmyk[1]); + let y = f32::from(cmyk[2]); + let kf = 1. - f32::from(cmyk[3]) / 255.; [ ((255. - c) * kf) as u8, ((255. - m) * kf) as u8, @@ -317,18 +408,44 @@ ] } -// Utility to simplify and deduplicate error handling during 16-bit encoding. -fn u8_slice_as_u16(buf: &[u8]) -> ImageResult<&[u16]> { - bytemuck::try_cast_slice(buf).map_err(|err| { - // If the buffer is not aligned or the correct length for a u16 slice, err. - // - // `bytemuck::PodCastError` of bytemuck-1.2.0 does not implement - // `Error` and `Display` trait. - // See . - ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::Generic( - format!("{:?}", err), - ))) - }) +fn cmyk_to_rgb16(cmyk: &[u16]) -> [u16; 3] { + let c = f32::from(cmyk[0]); + let m = f32::from(cmyk[1]); + let y = f32::from(cmyk[2]); + let kf = 1. - f32::from(cmyk[3]) / 65535.; + [ + ((65535. - c) * kf) as u16, + ((65535. - m) * kf) as u16, + ((65535. - y) * kf) as u16, + ] +} + +/// Convert a slice of sample bytes to its semantic type, being a `Pod`. +fn u8_slice_as_pod(buf: &[u8]) -> ImageResult> { + bytemuck::try_cast_slice(buf) + .map(std::borrow::Cow::Borrowed) + .or_else(|err| { + match err { + bytemuck::PodCastError::TargetAlignmentGreaterAndInputNotAligned => { + // If the buffer is not aligned for a native slice, copy the buffer into a Vec, + // aligning it in the process. This is only done if the element count can be + // represented exactly. + let vec = bytemuck::allocation::pod_collect_to_vec(buf); + Ok(std::borrow::Cow::Owned(vec)) + } + /* only expecting: bytemuck::PodCastError::OutputSliceWouldHaveSlop */ + _ => { + // `bytemuck::PodCastError` of bytemuck-1.2.0 does not implement `Error` and + // `Display` trait. + // See . + Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::Generic(format!( + "Casting samples to their representation failed: {err:?}", + )), + ))) + } + } + }) } impl TiffEncoder { @@ -345,48 +462,53 @@ /// /// Panics if `width * height * color_type.bytes_per_pixel() != data.len()`. #[track_caller] - pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color.bytes_per_pixel() as u64); + pub fn encode( + self, + buf: &[u8], + width: u32, + height: u32, + color_type: ExtendedColorType, + ) -> ImageResult<()> { + use tiff::encoder::colortype::{ + Gray16, Gray8, RGB32Float, RGBA32Float, RGB16, RGB8, RGBA16, RGBA8, + }; + let expected_buffer_len = color_type.buffer_size(width, height); assert_eq!( expected_buffer_len, - data.len() as u64, + buf.len() as u64, "Invalid buffer length: expected {expected_buffer_len} got {} for {width}x{height} image", - data.len(), + buf.len(), ); - let mut encoder = tiff::encoder::TiffEncoder::new(self.w).map_err(ImageError::from_tiff_encode)?; - match color { - ColorType::L8 => { - encoder.write_image::(width, height, data) + match color_type { + ExtendedColorType::L8 => encoder.write_image::(width, height, buf), + ExtendedColorType::Rgb8 => encoder.write_image::(width, height, buf), + ExtendedColorType::Rgba8 => encoder.write_image::(width, height, buf), + ExtendedColorType::L16 => { + encoder.write_image::(width, height, u8_slice_as_pod::(buf)?.as_ref()) } - ColorType::Rgb8 => { - encoder.write_image::(width, height, data) + ExtendedColorType::Rgb16 => { + encoder.write_image::(width, height, u8_slice_as_pod::(buf)?.as_ref()) } - ColorType::Rgba8 => { - encoder.write_image::(width, height, data) + ExtendedColorType::Rgba16 => { + encoder.write_image::(width, height, u8_slice_as_pod::(buf)?.as_ref()) } - ColorType::L16 => encoder.write_image::( - width, - height, - u8_slice_as_u16(data)?, - ), - ColorType::Rgb16 => encoder.write_image::( + ExtendedColorType::Rgb32F => encoder.write_image::( width, height, - u8_slice_as_u16(data)?, + u8_slice_as_pod::(buf)?.as_ref(), ), - ColorType::Rgba16 => encoder.write_image::( + ExtendedColorType::Rgba32F => encoder.write_image::( width, height, - u8_slice_as_u16(data)?, + u8_slice_as_pod::(buf)?.as_ref(), ), _ => { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::Tiff.into(), - UnsupportedErrorKind::Color(color.into()), + UnsupportedErrorKind::Color(color_type), ), )) } @@ -404,7 +526,7 @@ buf: &[u8], width: u32, height: u32, - color_type: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { self.encode(buf, width, height, color_type) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,377 +1,157 @@ -use byteorder::{LittleEndian, ReadBytesExt}; -use std::io::{self, Cursor, Error, Read}; -use std::marker::PhantomData; -use std::{error, fmt, mem}; - -use crate::error::{DecodingError, ImageError, ImageResult, ParameterError, ParameterErrorKind}; -use crate::image::{ImageDecoder, ImageFormat}; -use crate::{color, AnimationDecoder, Frames, Rgba}; - -use super::lossless::{LosslessDecoder, LosslessFrame}; -use super::vp8::{Frame as VP8Frame, Vp8Decoder}; - -use super::extended::{read_extended_header, ExtendedImage}; - -/// All errors that can occur when attempting to parse a WEBP container -#[derive(Debug, Clone, Copy)] -pub(crate) enum DecoderError { - /// RIFF's "RIFF" signature not found or invalid - RiffSignatureInvalid([u8; 4]), - /// WebP's "WEBP" signature not found or invalid - WebpSignatureInvalid([u8; 4]), - /// Chunk Header was incorrect or invalid in its usage - ChunkHeaderInvalid([u8; 4]), -} - -impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - struct SignatureWriter([u8; 4]); - impl fmt::Display for SignatureWriter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "[{:#04X?}, {:#04X?}, {:#04X?}, {:#04X?}]", - self.0[0], self.0[1], self.0[2], self.0[3] - ) - } - } - - match self { - DecoderError::RiffSignatureInvalid(riff) => f.write_fmt(format_args!( - "Invalid RIFF signature: {}", - SignatureWriter(*riff) - )), - DecoderError::WebpSignatureInvalid(webp) => f.write_fmt(format_args!( - "Invalid WebP signature: {}", - SignatureWriter(*webp) - )), - DecoderError::ChunkHeaderInvalid(header) => f.write_fmt(format_args!( - "Invalid Chunk header: {}", - SignatureWriter(*header) - )), - } - } -} - -impl From for ImageError { - fn from(e: DecoderError) -> ImageError { - ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e)) - } -} - -impl error::Error for DecoderError {} - -/// All possible RIFF chunks in a WebP image file -#[allow(clippy::upper_case_acronyms)] -#[derive(Debug, Clone, Copy, PartialEq)] -pub(crate) enum WebPRiffChunk { - RIFF, - WEBP, - VP8, - VP8L, - VP8X, - ANIM, - ANMF, - ALPH, - ICCP, - EXIF, - XMP, -} - -impl WebPRiffChunk { - pub(crate) fn from_fourcc(chunk_fourcc: [u8; 4]) -> ImageResult { - match &chunk_fourcc { - b"RIFF" => Ok(Self::RIFF), - b"WEBP" => Ok(Self::WEBP), - b"VP8 " => Ok(Self::VP8), - b"VP8L" => Ok(Self::VP8L), - b"VP8X" => Ok(Self::VP8X), - b"ANIM" => Ok(Self::ANIM), - b"ANMF" => Ok(Self::ANMF), - b"ALPH" => Ok(Self::ALPH), - b"ICCP" => Ok(Self::ICCP), - b"EXIF" => Ok(Self::EXIF), - b"XMP " => Ok(Self::XMP), - _ => Err(DecoderError::ChunkHeaderInvalid(chunk_fourcc).into()), - } - } +use std::io::{BufRead, Read, Seek}; - pub(crate) fn to_fourcc(&self) -> [u8; 4] { - match self { - Self::RIFF => *b"RIFF", - Self::WEBP => *b"WEBP", - Self::VP8 => *b"VP8 ", - Self::VP8L => *b"VP8L", - Self::VP8X => *b"VP8X", - Self::ANIM => *b"ANIM", - Self::ANMF => *b"ANMF", - Self::ALPH => *b"ALPH", - Self::ICCP => *b"ICCP", - Self::EXIF => *b"EXIF", - Self::XMP => *b"XMP ", - } - } -} - -enum WebPImage { - Lossy(VP8Frame), - Lossless(LosslessFrame), - Extended(ExtendedImage), -} - -/// WebP Image format decoder. Currently only supports lossy RGB images or lossless RGBA images. +use crate::buffer::ConvertBuffer; +use crate::error::{DecodingError, ImageError, ImageResult}; +use crate::metadata::Orientation; +use crate::{ + AnimationDecoder, ColorType, Delay, Frame, Frames, ImageDecoder, ImageFormat, RgbImage, Rgba, + RgbaImage, +}; + +/// WebP Image format decoder. +/// +/// Supports both lossless and lossy WebP images. pub struct WebPDecoder { - r: R, - image: WebPImage, + inner: image_webp::WebPDecoder, + orientation: Option, } -impl WebPDecoder { - /// Create a new WebPDecoder from the Reader ```r```. - /// This function takes ownership of the Reader. - pub fn new(r: R) -> ImageResult> { - let image = WebPImage::Lossy(Default::default()); - - let mut decoder = WebPDecoder { r, image }; - decoder.read_data()?; - Ok(decoder) - } - - //reads the 12 bytes of the WebP file header - fn read_riff_header(&mut self) -> ImageResult { - let mut riff = [0; 4]; - self.r.read_exact(&mut riff)?; - if &riff != b"RIFF" { - return Err(DecoderError::RiffSignatureInvalid(riff).into()); - } - - let size = self.r.read_u32::()?; - - let mut webp = [0; 4]; - self.r.read_exact(&mut webp)?; - if &webp != b"WEBP" { - return Err(DecoderError::WebpSignatureInvalid(webp).into()); - } - - Ok(size) - } - - //reads the chunk header, decodes the frame and returns the inner decoder - fn read_frame(&mut self) -> ImageResult { - let chunk = read_chunk(&mut self.r)?; - - match chunk { - Some((cursor, WebPRiffChunk::VP8)) => { - let mut vp8_decoder = Vp8Decoder::new(cursor); - let frame = vp8_decoder.decode_frame()?; - - Ok(WebPImage::Lossy(frame.clone())) - } - Some((cursor, WebPRiffChunk::VP8L)) => { - let mut lossless_decoder = LosslessDecoder::new(cursor); - let frame = lossless_decoder.decode_frame()?; - - Ok(WebPImage::Lossless(frame.clone())) - } - Some((mut cursor, WebPRiffChunk::VP8X)) => { - let info = read_extended_header(&mut cursor)?; - - let image = ExtendedImage::read_extended_chunks(&mut self.r, info)?; - - Ok(WebPImage::Extended(image)) - } - None => Err(ImageError::IoError(Error::from( - io::ErrorKind::UnexpectedEof, - ))), - Some((_, chunk)) => Err(DecoderError::ChunkHeaderInvalid(chunk.to_fourcc()).into()), - } - } - - fn read_data(&mut self) -> ImageResult<()> { - let _size = self.read_riff_header()?; - - let image = self.read_frame()?; - - self.image = image; - - Ok(()) +impl WebPDecoder { + /// Create a new `WebPDecoder` from the Reader `r`. + pub fn new(r: R) -> ImageResult { + Ok(Self { + inner: image_webp::WebPDecoder::new(r).map_err(ImageError::from_webp_decode)?, + orientation: None, + }) } /// Returns true if the image as described by the bitstream is animated. pub fn has_animation(&self) -> bool { - match &self.image { - WebPImage::Lossy(_) => false, - WebPImage::Lossless(_) => false, - WebPImage::Extended(extended) => extended.has_animation(), - } + self.inner.is_animated() } /// Sets the background color if the image is an extended and animated webp. pub fn set_background_color(&mut self, color: Rgba) -> ImageResult<()> { - match &mut self.image { - WebPImage::Extended(image) => image.set_background_color(color), - _ => Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::Generic( - "Background color can only be set on animated webp".to_owned(), - ), - ))), - } + self.inner + .set_background_color(color.0) + .map_err(ImageError::from_webp_decode) } } -pub(crate) fn read_len_cursor(r: &mut R) -> ImageResult>> -where - R: Read, -{ - let unpadded_len = u64::from(r.read_u32::()?); - - // RIFF chunks containing an uneven number of bytes append - // an extra 0x00 at the end of the chunk - // - // The addition cannot overflow since we have a u64 that was created from a u32 - let len = unpadded_len + (unpadded_len % 2); - - let mut framedata = Vec::new(); - r.by_ref().take(len).read_to_end(&mut framedata)?; - - //remove padding byte - if unpadded_len % 2 == 1 { - framedata.pop(); +impl ImageDecoder for WebPDecoder { + fn dimensions(&self) -> (u32, u32) { + self.inner.dimensions() } - Ok(io::Cursor::new(framedata)) -} - -/// Reads a chunk header FourCC -/// Returns None if and only if we hit end of file reading the four character code of the chunk -/// The inner error is `Err` if and only if the chunk header FourCC is present but unknown -pub(crate) fn read_fourcc(r: &mut R) -> ImageResult>> { - let mut chunk_fourcc = [0; 4]; - let result = r.read_exact(&mut chunk_fourcc); - - match result { - Ok(()) => {} - Err(err) => { - if err.kind() == io::ErrorKind::UnexpectedEof { - return Ok(None); - } else { - return Err(err.into()); - } + fn color_type(&self) -> ColorType { + if self.inner.has_alpha() { + ColorType::Rgba8 + } else { + ColorType::Rgb8 } } - let chunk = WebPRiffChunk::from_fourcc(chunk_fourcc); - Ok(Some(chunk)) -} + fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { + assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); -/// Reads a chunk -/// Returns an error if the chunk header is not a valid webp header or some other reading error -/// Returns None if and only if we hit end of file reading the four character code of the chunk -pub(crate) fn read_chunk(r: &mut R) -> ImageResult>, WebPRiffChunk)>> -where - R: Read, -{ - if let Some(chunk) = read_fourcc(r)? { - let chunk = chunk?; - let cursor = read_len_cursor(r)?; - Ok(Some((cursor, chunk))) - } else { - Ok(None) + self.inner + .read_image(buf) + .map_err(ImageError::from_webp_decode) } -} -/// Wrapper struct around a `Cursor>` -pub struct WebpReader(Cursor>, PhantomData); -impl Read for WebpReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) } -} -impl<'a, R: 'a + Read> ImageDecoder<'a> for WebPDecoder { - type Reader = WebpReader; + fn icc_profile(&mut self) -> ImageResult>> { + self.inner + .icc_profile() + .map_err(ImageError::from_webp_decode) + } - fn dimensions(&self) -> (u32, u32) { - match &self.image { - WebPImage::Lossy(vp8_frame) => { - (u32::from(vp8_frame.width), u32::from(vp8_frame.height)) - } - WebPImage::Lossless(lossless_frame) => ( - u32::from(lossless_frame.width), - u32::from(lossless_frame.height), - ), - WebPImage::Extended(extended) => extended.dimensions(), - } + fn exif_metadata(&mut self) -> ImageResult>> { + let exif = self + .inner + .exif_metadata() + .map_err(ImageError::from_webp_decode)?; + + self.orientation = Some( + exif.as_ref() + .and_then(|exif| Orientation::from_exif_chunk(exif)) + .unwrap_or(Orientation::NoTransforms), + ); + + Ok(exif) } - fn color_type(&self) -> color::ColorType { - match &self.image { - WebPImage::Lossy(_) => color::ColorType::Rgb8, - WebPImage::Lossless(_) => color::ColorType::Rgba8, - WebPImage::Extended(extended) => extended.color_type(), - } + fn xmp_metadata(&mut self) -> ImageResult>> { + self.inner + .xmp_metadata() + .map_err(ImageError::from_webp_decode) } - fn into_reader(self) -> ImageResult { - match &self.image { - WebPImage::Lossy(vp8_frame) => { - let mut data = vec![0; vp8_frame.get_buf_size()]; - vp8_frame.fill_rgb(data.as_mut_slice()); - Ok(WebpReader(Cursor::new(data), PhantomData)) - } - WebPImage::Lossless(lossless_frame) => { - let mut data = vec![0; lossless_frame.get_buf_size()]; - lossless_frame.fill_rgba(data.as_mut_slice()); - Ok(WebpReader(Cursor::new(data), PhantomData)) - } - WebPImage::Extended(extended) => { - let mut data = vec![0; extended.get_buf_size()]; - extended.fill_buf(data.as_mut_slice()); - Ok(WebpReader(Cursor::new(data), PhantomData)) - } + fn orientation(&mut self) -> ImageResult { + // `exif_metadata` caches the orientation, so call it if `orientation` hasn't been set yet. + if self.orientation.is_none() { + let _ = self.exif_metadata()?; } + Ok(self.orientation.unwrap()) } +} - fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - - match &self.image { - WebPImage::Lossy(vp8_frame) => { - vp8_frame.fill_rgb(buf); - } - WebPImage::Lossless(lossless_frame) => { - lossless_frame.fill_rgba(buf); - } - WebPImage::Extended(extended) => { - extended.fill_buf(buf); +impl<'a, R: 'a + BufRead + Seek> AnimationDecoder<'a> for WebPDecoder { + fn into_frames(self) -> Frames<'a> { + struct FramesInner { + decoder: WebPDecoder, + current: u32, + } + impl Iterator for FramesInner { + type Item = ImageResult; + + fn next(&mut self) -> Option { + if self.current == self.decoder.inner.num_frames() { + return None; + } + self.current += 1; + let (width, height) = self.decoder.inner.dimensions(); + + let (img, delay) = if self.decoder.inner.has_alpha() { + let mut img = RgbaImage::new(width, height); + match self.decoder.inner.read_frame(&mut img) { + Ok(delay) => (img, delay), + Err(image_webp::DecodingError::NoMoreFrames) => return None, + Err(e) => return Some(Err(ImageError::from_webp_decode(e))), + } + } else { + let mut img = RgbImage::new(width, height); + match self.decoder.inner.read_frame(&mut img) { + Ok(delay) => (img.convert(), delay), + Err(image_webp::DecodingError::NoMoreFrames) => return None, + Err(e) => return Some(Err(ImageError::from_webp_decode(e))), + } + }; + + Some(Ok(Frame::from_parts( + img, + 0, + 0, + Delay::from_numer_denom_ms(delay, 1), + ))) } } - Ok(()) - } - fn icc_profile(&mut self) -> Option> { - if let WebPImage::Extended(extended) = &self.image { - extended.icc_profile() - } else { - None - } + Frames::new(Box::new(FramesInner { + decoder: self, + current: 0, + })) } } -impl<'a, R: 'a + Read> AnimationDecoder<'a> for WebPDecoder { - fn into_frames(self) -> Frames<'a> { - match self.image { - WebPImage::Lossy(_) | WebPImage::Lossless(_) => { - Frames::new(Box::new(std::iter::empty())) - } - WebPImage::Extended(extended_image) => extended_image.into_frames(), +impl ImageError { + fn from_webp_decode(e: image_webp::DecodingError) -> Self { + match e { + image_webp::DecodingError::IoError(e) => ImageError::IoError(e), + _ => ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e)), } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,741 +1,123 @@ //! Encoding of WebP images. -use std::collections::BinaryHeap; -/// -/// Uses the simple encoding API from the [libwebp] library. -/// -/// [libwebp]: https://developers.google.com/speed/webp/docs/api#simple_encoding_api -use std::io::{self, Write}; -use std::slice::ChunksExact; - -#[cfg(feature = "webp-encoder")] -use libwebp::{Encoder, PixelLayout, WebPMemory}; - -use crate::error::{ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind}; -use crate::flat::SampleLayout; -use crate::{ColorType, ImageEncoder, ImageError, ImageFormat, ImageResult}; - -/// WebP Encoder. -pub struct WebPEncoder { - writer: W, - quality: WebPQuality, - - chunk_buffer: Vec, - buffer: u64, - nbits: u8, -} -/// WebP encoder quality. -#[derive(Debug, Copy, Clone)] -pub struct WebPQuality(Quality); - -#[derive(Debug, Copy, Clone)] -enum Quality { - Lossless, - #[allow(unused)] - #[deprecated = "Lossy encoding will be removed in a future version. See: https://github.com/image-rs/image/issues/1984"] - Lossy(u8), -} +use std::io::Write; -impl WebPQuality { - /// Minimum lossy quality value (0). - pub const MIN: u8 = 0; - /// Maximum lossy quality value (100). - pub const MAX: u8 = 100; - /// Default lossy quality (80), providing a balance of quality and file size. - pub const DEFAULT: u8 = 80; - - /// Lossless encoding. - pub fn lossless() -> Self { - Self(Quality::Lossless) - } +use crate::error::{EncodingError, UnsupportedError, UnsupportedErrorKind}; +use crate::{DynamicImage, ExtendedColorType, ImageEncoder, ImageError, ImageFormat, ImageResult}; - /// Lossy encoding. 0 = low quality, small size; 100 = high quality, large size. - /// - /// Values are clamped from 0 to 100. - #[deprecated = "Lossy encoding will be removed in a future version. See: https://github.com/image-rs/image/issues/1984"] - pub fn lossy(quality: u8) -> Self { - #[allow(deprecated)] - Self(Quality::Lossy(quality.clamp(Self::MIN, Self::MAX))) - } -} - -impl Default for WebPQuality { - fn default() -> Self { - #[allow(deprecated)] - Self::lossy(WebPQuality::DEFAULT) - } +/// WebP Encoder. +/// +/// ### Limitations +/// +/// Right now only **lossless** encoding is supported. +/// +/// If you need **lossy** encoding, you'll have to use `libwebp`. +/// Example code for encoding a [`DynamicImage`](crate::DynamicImage) with `libwebp` +/// via the [`webp`](https://docs.rs/webp/latest/webp/) crate can be found +/// [here](https://github.com/jaredforth/webp/blob/main/examples/convert.rs). +/// +/// ### Compression ratio +/// +/// This encoder reaches compression ratios higher than PNG at a fraction of the encoding time. +/// However, it does not reach the full potential of lossless WebP for reducing file size. +/// +/// If you need an even higher compression ratio at the cost of much slower encoding, +/// please encode the image with `libwebp` as outlined above. +pub struct WebPEncoder { + inner: image_webp::WebPEncoder, } impl WebPEncoder { /// Create a new encoder that writes its output to `w`. /// - /// Defaults to lossy encoding, see [`WebPQuality::DEFAULT`]. - #[deprecated = "Use `new_lossless` instead. Lossy encoding will be removed in a future version. See: https://github.com/image-rs/image/issues/1984"] - #[cfg(feature = "webp-encoder")] - pub fn new(w: W) -> Self { - #[allow(deprecated)] - WebPEncoder::new_with_quality(w, WebPQuality::default()) - } - - /// Create a new encoder with the specified quality, that writes its output to `w`. - #[deprecated = "Use `new_lossless` instead. Lossy encoding will be removed in a future version. See: https://github.com/image-rs/image/issues/1984"] - #[cfg(feature = "webp-encoder")] - pub fn new_with_quality(w: W, quality: WebPQuality) -> Self { - Self { - writer: w, - quality, - chunk_buffer: Vec::new(), - buffer: 0, - nbits: 0, - } - } - - /// Create a new encoder that writes its output to `w`. - /// /// Uses "VP8L" lossless encoding. pub fn new_lossless(w: W) -> Self { Self { - writer: w, - quality: WebPQuality::lossless(), - chunk_buffer: Vec::new(), - buffer: 0, - nbits: 0, - } - } - - fn write_bits(&mut self, bits: u64, nbits: u8) -> io::Result<()> { - debug_assert!(nbits <= 64); - - self.buffer |= bits << self.nbits; - self.nbits += nbits; - - if self.nbits >= 64 { - self.chunk_buffer.write_all(&self.buffer.to_le_bytes())?; - self.nbits -= 64; - self.buffer = bits.checked_shr((nbits - self.nbits) as u32).unwrap_or(0); + inner: image_webp::WebPEncoder::new(w), } - debug_assert!(self.nbits < 64); - Ok(()) } - fn flush(&mut self) -> io::Result<()> { - if self.nbits % 8 != 0 { - self.write_bits(0, 8 - self.nbits % 8)?; - } - if self.nbits > 0 { - self.chunk_buffer - .write_all(&self.buffer.to_le_bytes()[..self.nbits as usize / 8]) - .unwrap(); - self.buffer = 0; - self.nbits = 0; - } - Ok(()) - } - - fn write_single_entry_huffman_tree(&mut self, symbol: u8) -> io::Result<()> { - self.write_bits(1, 2)?; - if symbol <= 1 { - self.write_bits(0, 1)?; - self.write_bits(symbol as u64, 1)?; - } else { - self.write_bits(1, 1)?; - self.write_bits(symbol as u64, 8)?; - } - Ok(()) - } - - fn build_huffman_tree( - &mut self, - frequencies: &[u32], - lengths: &mut [u8], - codes: &mut [u16], - length_limit: u8, - ) -> bool { - assert_eq!(frequencies.len(), lengths.len()); - assert_eq!(frequencies.len(), codes.len()); - - if frequencies.iter().filter(|&&f| f > 0).count() <= 1 { - lengths.fill(0); - codes.fill(0); - return false; - } - - #[derive(Eq, PartialEq, Copy, Clone, Debug)] - struct Item(u32, u16); - impl Ord for Item { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - other.0.cmp(&self.0) - } - } - impl PartialOrd for Item { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - // Build a huffman tree - let mut internal_nodes = Vec::new(); - let mut nodes = BinaryHeap::from_iter( - frequencies - .iter() - .enumerate() - .filter(|(_, &frequency)| frequency > 0) - .map(|(i, &frequency)| Item(frequency, i as u16)), - ); - while nodes.len() > 1 { - let Item(frequency1, index1) = nodes.pop().unwrap(); - let mut root = nodes.peek_mut().unwrap(); - internal_nodes.push((index1, root.1)); - *root = Item( - frequency1 + root.0, - internal_nodes.len() as u16 + frequencies.len() as u16 - 1, - ); - } - - // Walk the tree to assign code lengths - lengths.fill(0); - let mut stack = Vec::new(); - stack.push((nodes.pop().unwrap().1, 0)); - while let Some((node, depth)) = stack.pop() { - let node = node as usize; - if node < frequencies.len() { - lengths[node] = depth as u8; - } else { - let (left, right) = internal_nodes[node - frequencies.len()]; - stack.push((left, depth + 1)); - stack.push((right, depth + 1)); - } - } - - // Limit the codes to length length_limit - let mut max_length = 0; - for &length in lengths.iter() { - max_length = max_length.max(length); - } - if max_length > length_limit { - let mut counts = [0u32; 16]; - for &length in lengths.iter() { - counts[length.min(length_limit) as usize] += 1; - } - - let mut total = 0; - for (i, count) in counts - .iter() - .enumerate() - .skip(1) - .take(length_limit as usize) - { - total += count << (length_limit as usize - i); - } - - while total > 1u32 << length_limit { - let mut i = length_limit as usize - 1; - while counts[i] == 0 { - i -= 1; - } - counts[i] -= 1; - counts[length_limit as usize] -= 1; - counts[i + 1] += 2; - total -= 1; - } - - // assign new lengths - let mut len = length_limit; - let mut indexes = frequencies.iter().copied().enumerate().collect::>(); - indexes.sort_unstable_by_key(|&(_, frequency)| frequency); - for &(i, frequency) in indexes.iter() { - if frequency > 0 { - while counts[len as usize] == 0 { - len -= 1; - } - lengths[i] = len; - counts[len as usize] -= 1; - } - } - } - - // Assign codes - codes.fill(0); - let mut code = 0u32; - for len in 1..=length_limit { - for (i, &length) in lengths.iter().enumerate() { - if length == len { - codes[i] = (code as u16).reverse_bits() >> (16 - len); - code += 1; - } - } - code <<= 1; - } - assert_eq!(code, 2 << length_limit); - - true - } - - fn write_huffman_tree( - &mut self, - frequencies: &[u32], - lengths: &mut [u8], - codes: &mut [u16], - ) -> io::Result<()> { - if !self.build_huffman_tree(frequencies, lengths, codes, 15) { - let symbol = frequencies - .iter() - .position(|&frequency| frequency > 0) - .unwrap_or(0); - return self.write_single_entry_huffman_tree(symbol as u8); - } - - let mut code_length_lengths = [0u8; 16]; - let mut code_length_codes = [0u16; 16]; - let mut code_length_frequencies = [0u32; 16]; - for &length in lengths.iter() { - code_length_frequencies[length as usize] += 1; - } - let single_code_length_length = !self.build_huffman_tree( - &code_length_frequencies, - &mut code_length_lengths, - &mut code_length_codes, - 7, - ); - - const CODE_LENGTH_ORDER: [usize; 19] = [ - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - ]; - - // Write the huffman tree - self.write_bits(0, 1)?; // normal huffman tree - self.write_bits(19 - 4, 4)?; // num_code_lengths - 4 - - for &i in CODE_LENGTH_ORDER.iter() { - if i > 15 || code_length_frequencies[i] == 0 { - self.write_bits(0, 3)?; - } else if single_code_length_length { - self.write_bits(1, 3)?; - } else { - self.write_bits(code_length_lengths[i] as u64, 3)?; - } - } - - match lengths.len() { - 256 => { - self.write_bits(1, 1)?; // max_symbol is stored - self.write_bits(3, 3)?; // max_symbol_nbits / 2 - 2 - self.write_bits(254, 8)?; // max_symbol - 2 - } - 280 => self.write_bits(0, 1)?, - _ => unreachable!(), - } - - // Write the huffman codes - if !single_code_length_length { - for &len in lengths.iter() { - self.write_bits( - code_length_codes[len as usize] as u64, - code_length_lengths[len as usize], - )?; - } - } - - Ok(()) - } - - fn length_to_symbol(len: u16) -> (u16, u8) { - let len = len - 1; - let highest_bit = 15 - len.leading_zeros() as u16; // TODO: use ilog2 once MSRV >= 1.67 - let second_highest_bit = (len >> (highest_bit - 1)) & 1; - let extra_bits = highest_bit - 1; - let symbol = 2 * highest_bit + second_highest_bit; - (symbol, extra_bits as u8) - } - - #[inline(always)] - fn count_run( - pixel: &[u8], - it: &mut std::iter::Peekable>, - frequencies1: &mut [u32; 280], - ) { - let mut run_length = 0; - while run_length < 4096 && it.peek() == Some(&pixel) { - run_length += 1; - it.next(); - } - if run_length > 0 { - if run_length <= 4 { - let symbol = 256 + run_length - 1; - frequencies1[symbol] += 1; - } else { - let (symbol, _extra_bits) = Self::length_to_symbol(run_length as u16); - frequencies1[256 + symbol as usize] += 1; - } - } - } - - #[inline(always)] - fn write_run( - &mut self, - pixel: &[u8], - it: &mut std::iter::Peekable>, - codes1: &[u16; 280], - lengths1: &[u8; 280], - ) -> io::Result<()> { - let mut run_length = 0; - while run_length < 4096 && it.peek() == Some(&pixel) { - run_length += 1; - it.next(); - } - if run_length > 0 { - if run_length <= 4 { - let symbol = 256 + run_length - 1; - self.write_bits(codes1[symbol] as u64, lengths1[symbol])?; - } else { - let (symbol, extra_bits) = Self::length_to_symbol(run_length as u16); - self.write_bits( - codes1[256 + symbol as usize] as u64, - lengths1[256 + symbol as usize], - )?; - self.write_bits( - (run_length as u64 - 1) & ((1 << extra_bits) - 1), - extra_bits, - )?; - } - } - Ok(()) - } - - fn encode_lossless( - mut self, - data: &[u8], + /// Encode image data with the indicated color type. + /// + /// The encoder requires image data be Rgb8 or Rgba8. + /// + /// # Panics + /// + /// Panics if `width * height * color.bytes_per_pixel() != data.len()`. + #[track_caller] + pub fn encode( + self, + buf: &[u8], width: u32, height: u32, - color: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - if width == 0 - || width > 16384 - || height == 0 - || height > 16384 - || !SampleLayout::row_major_packed(color.channel_count(), width, height) - .fits(data.len()) - { - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))); - } + let expected_buffer_len = color_type.buffer_size(width, height); + assert_eq!( + expected_buffer_len, + buf.len() as u64, + "Invalid buffer length: expected {expected_buffer_len} got {} for {width}x{height} image", + buf.len(), + ); - let (is_color, is_alpha) = match color { - ColorType::L8 => (false, false), - ColorType::La8 => (false, true), - ColorType::Rgb8 => (true, false), - ColorType::Rgba8 => (true, true), + let color_type = match color_type { + ExtendedColorType::L8 => image_webp::ColorType::L8, + ExtendedColorType::La8 => image_webp::ColorType::La8, + ExtendedColorType::Rgb8 => image_webp::ColorType::Rgb8, + ExtendedColorType::Rgba8 => image_webp::ColorType::Rgba8, _ => { return Err(ImageError::Unsupported( UnsupportedError::from_format_and_kind( ImageFormat::WebP.into(), - UnsupportedErrorKind::Color(color.into()), + UnsupportedErrorKind::Color(color_type), ), )) } }; - self.write_bits(0x2f, 8)?; // signature - self.write_bits(width as u64 - 1, 14)?; - self.write_bits(height as u64 - 1, 14)?; - - self.write_bits(is_alpha as u64, 1)?; // alpha used - self.write_bits(0x0, 3)?; // version - - // subtract green transform - self.write_bits(0b101, 3)?; - - // predictor transform - self.write_bits(0b111001, 6)?; - self.write_bits(0x0, 1)?; // no color cache - self.write_single_entry_huffman_tree(2)?; - for _ in 0..4 { - self.write_single_entry_huffman_tree(0)?; - } - - // transforms done - self.write_bits(0x0, 1)?; - - // color cache - self.write_bits(0x0, 1)?; - - // meta-huffman codes - self.write_bits(0x0, 1)?; - - // expand to RGBA - let mut pixels = match color { - ColorType::L8 => data.iter().flat_map(|&p| [p, p, p, 255]).collect(), - ColorType::La8 => data - .chunks_exact(2) - .flat_map(|p| [p[0], p[0], p[0], p[1]]) - .collect(), - ColorType::Rgb8 => data - .chunks_exact(3) - .flat_map(|p| [p[0], p[1], p[2], 255]) - .collect(), - ColorType::Rgba8 => data.to_vec(), - _ => unreachable!(), - }; - - // compute subtract green transform - for pixel in pixels.chunks_exact_mut(4) { - pixel[0] = pixel[0].wrapping_sub(pixel[1]); - pixel[2] = pixel[2].wrapping_sub(pixel[1]); - } - - // compute predictor transform - let row_bytes = width as usize * 4; - for y in (1..height as usize).rev() { - let (prev, current) = - pixels[(y - 1) * row_bytes..][..row_bytes * 2].split_at_mut(row_bytes); - for (c, p) in current.iter_mut().zip(prev) { - *c = c.wrapping_sub(*p); - } - } - for i in (4..row_bytes).rev() { - pixels[i] = pixels[i].wrapping_sub(pixels[i - 4]); - } - pixels[3] = pixels[3].wrapping_sub(255); - - // compute frequencies - let mut frequencies0 = [0u32; 256]; - let mut frequencies1 = [0u32; 280]; - let mut frequencies2 = [0u32; 256]; - let mut frequencies3 = [0u32; 256]; - let mut it = pixels.chunks_exact(4).peekable(); - match color { - ColorType::L8 => { - frequencies0[0] = 1; - frequencies2[0] = 1; - frequencies3[0] = 1; - while let Some(pixel) = it.next() { - frequencies1[pixel[1] as usize] += 1; - Self::count_run(pixel, &mut it, &mut frequencies1); - } - } - ColorType::La8 => { - frequencies0[0] = 1; - frequencies2[0] = 1; - while let Some(pixel) = it.next() { - frequencies1[pixel[1] as usize] += 1; - frequencies3[pixel[3] as usize] += 1; - Self::count_run(pixel, &mut it, &mut frequencies1); - } - } - ColorType::Rgb8 => { - frequencies3[0] = 1; - while let Some(pixel) = it.next() { - frequencies0[pixel[0] as usize] += 1; - frequencies1[pixel[1] as usize] += 1; - frequencies2[pixel[2] as usize] += 1; - Self::count_run(pixel, &mut it, &mut frequencies1); - } - } - ColorType::Rgba8 => { - while let Some(pixel) = it.next() { - frequencies0[pixel[0] as usize] += 1; - frequencies1[pixel[1] as usize] += 1; - frequencies2[pixel[2] as usize] += 1; - frequencies3[pixel[3] as usize] += 1; - Self::count_run(pixel, &mut it, &mut frequencies1); - } - } - _ => unreachable!(), - } - - // compute and write huffman codes - let mut lengths0 = [0u8; 256]; - let mut lengths1 = [0u8; 280]; - let mut lengths2 = [0u8; 256]; - let mut lengths3 = [0u8; 256]; - let mut codes0 = [0u16; 256]; - let mut codes1 = [0u16; 280]; - let mut codes2 = [0u16; 256]; - let mut codes3 = [0u16; 256]; - self.write_huffman_tree(&frequencies1, &mut lengths1, &mut codes1)?; - if is_color { - self.write_huffman_tree(&frequencies0, &mut lengths0, &mut codes0)?; - self.write_huffman_tree(&frequencies2, &mut lengths2, &mut codes2)?; - } else { - self.write_single_entry_huffman_tree(0)?; - self.write_single_entry_huffman_tree(0)?; - } - if is_alpha { - self.write_huffman_tree(&frequencies3, &mut lengths3, &mut codes3)?; - } else { - self.write_single_entry_huffman_tree(0)?; - } - self.write_single_entry_huffman_tree(1)?; - - // Write image data - let mut it = pixels.chunks_exact(4).peekable(); - match color { - ColorType::L8 => { - while let Some(pixel) = it.next() { - self.write_bits( - codes1[pixel[1] as usize] as u64, - lengths1[pixel[1] as usize], - )?; - self.write_run(pixel, &mut it, &codes1, &lengths1)?; - } - } - ColorType::La8 => { - while let Some(pixel) = it.next() { - let len1 = lengths1[pixel[1] as usize]; - let len3 = lengths3[pixel[3] as usize]; - - let code = codes1[pixel[1] as usize] as u64 - | (codes3[pixel[3] as usize] as u64) << len1; - - self.write_bits(code, len1 + len3)?; - self.write_run(pixel, &mut it, &codes1, &lengths1)?; - } - } - ColorType::Rgb8 => { - while let Some(pixel) = it.next() { - let len1 = lengths1[pixel[1] as usize]; - let len0 = lengths0[pixel[0] as usize]; - let len2 = lengths2[pixel[2] as usize]; - - let code = codes1[pixel[1] as usize] as u64 - | (codes0[pixel[0] as usize] as u64) << len1 - | (codes2[pixel[2] as usize] as u64) << (len1 + len0); - - self.write_bits(code, len1 + len0 + len2)?; - self.write_run(pixel, &mut it, &codes1, &lengths1)?; - } - } - ColorType::Rgba8 => { - while let Some(pixel) = it.next() { - let len1 = lengths1[pixel[1] as usize]; - let len0 = lengths0[pixel[0] as usize]; - let len2 = lengths2[pixel[2] as usize]; - let len3 = lengths3[pixel[3] as usize]; - - let code = codes1[pixel[1] as usize] as u64 - | (codes0[pixel[0] as usize] as u64) << len1 - | (codes2[pixel[2] as usize] as u64) << (len1 + len0) - | (codes3[pixel[3] as usize] as u64) << (len1 + len0 + len2); - - self.write_bits(code, len1 + len0 + len2 + len3)?; - self.write_run(pixel, &mut it, &codes1, &lengths1)?; - } - } - _ => unreachable!(), - } - - // flush writer - self.flush()?; - if self.chunk_buffer.len() % 2 == 1 { - self.chunk_buffer.push(0); - } - - // write container - self.writer.write_all(b"RIFF")?; - self.writer - .write_all(&(self.chunk_buffer.len() as u32 + 12).to_le_bytes())?; - self.writer.write_all(b"WEBP")?; - self.writer.write_all(b"VP8L")?; - self.writer - .write_all(&(self.chunk_buffer.len() as u32).to_le_bytes())?; - self.writer.write_all(&self.chunk_buffer)?; - - Ok(()) + self.inner + .encode(buf, width, height, color_type) + .map_err(ImageError::from_webp_encode) } +} - #[cfg(feature = "webp-encoder")] - fn encode_lossy( - mut self, - data: &[u8], +impl ImageEncoder for WebPEncoder { + #[track_caller] + fn write_image( + self, + buf: &[u8], width: u32, height: u32, - color: ColorType, + color_type: ExtendedColorType, ) -> ImageResult<()> { - // TODO: convert color types internally? - let layout = match color { - ColorType::Rgb8 => PixelLayout::Rgb, - ColorType::Rgba8 => PixelLayout::Rgba, - _ => { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::WebP.into(), - UnsupportedErrorKind::Color(color.into()), - ), - )) - } - }; - - // Validate dimensions upfront to avoid panics. - if width == 0 - || height == 0 - || !SampleLayout::row_major_packed(color.channel_count(), width, height) - .fits(data.len()) - { - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))); - } - - // Call the native libwebp library to encode the image. - let encoder = Encoder::new(data, layout, width, height); - let encoded: WebPMemory = match self.quality.0 { - Quality::Lossless => encoder.encode_lossless(), - #[allow(deprecated)] - Quality::Lossy(quality) => encoder.encode(quality as f32), - }; - - // The simple encoding API in libwebp does not return errors. - if encoded.is_empty() { - return Err(ImageError::Encoding(crate::error::EncodingError::new( - ImageFormat::WebP.into(), - "encoding failed, output empty", - ))); - } + self.encode(buf, width, height, color_type) + } - self.writer.write_all(&encoded)?; + fn set_icc_profile(&mut self, icc_profile: Vec) -> Result<(), UnsupportedError> { + self.inner.set_icc_profile(icc_profile); Ok(()) } - /// Encode image data with the indicated color type. - /// - /// The encoder requires image data be Rgb8 or Rgba8. - /// - /// # Panics - /// - /// Panics if `width * height * color.bytes_per_pixel() != data.len()`. - #[track_caller] - pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> { - let expected_buffer_len = - (width as u64 * height as u64).saturating_mul(color.bytes_per_pixel() as u64); - assert_eq!( - expected_buffer_len, - data.len() as u64, - "Invalid buffer length: expected {expected_buffer_len} got {} for {width}x{height} image", - data.len(), - ); + fn set_exif_metadata(&mut self, exif: Vec) -> Result<(), UnsupportedError> { + self.inner.set_exif_metadata(exif); + Ok(()) + } - if let WebPQuality(Quality::Lossless) = self.quality { - self.encode_lossless(data, width, height, color) - } else { - #[cfg(feature = "webp-encoder")] - return self.encode_lossy(data, width, height, color); - #[cfg(not(feature = "webp-encoder"))] - unreachable!() - } + fn make_compatible_img( + &self, + _: crate::io::encoder::MethodSealedToImage, + img: &DynamicImage, + ) -> Option { + crate::io::encoder::dynimage_conversion_8bit(img) } } -impl ImageEncoder for WebPEncoder { - #[track_caller] - fn write_image( - self, - buf: &[u8], - width: u32, - height: u32, - color_type: ColorType, - ) -> ImageResult<()> { - self.encode(buf, width, height, color_type) +impl ImageError { + fn from_webp_encode(e: image_webp::EncodingError) -> Self { + match e { + image_webp::EncodingError::IoError(e) => ImageError::IoError(e), + _ => ImageError::Encoding(EncodingError::new(ImageFormat::WebP.into(), e)), + } } } @@ -753,7 +135,7 @@ img.inner_pixels(), img.width(), img.height(), - crate::ColorType::Rgba8, + crate::ExtendedColorType::Rgba8, ) .unwrap(); @@ -764,81 +146,3 @@ assert_eq!(img, img2); } } - -#[cfg(test)] -#[cfg(feature = "webp-encoder")] -mod native_tests { - use crate::codecs::webp::{WebPEncoder, WebPQuality}; - use crate::{ColorType, ImageEncoder}; - - #[derive(Debug, Clone)] - struct MockImage { - width: u32, - height: u32, - color: ColorType, - data: Vec, - } - - impl quickcheck::Arbitrary for MockImage { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - // Limit to small, non-empty images <= 512x512. - let width = u32::arbitrary(g) % 512 + 1; - let height = u32::arbitrary(g) % 512 + 1; - let (color, stride) = if bool::arbitrary(g) { - (ColorType::Rgb8, 3) - } else { - (ColorType::Rgba8, 4) - }; - let size = width * height * stride; - let data: Vec = (0..size).map(|_| u8::arbitrary(g)).collect(); - MockImage { - width, - height, - color, - data, - } - } - } - - quickcheck! { - fn fuzz_webp_valid_image(image: MockImage, quality: u8) -> bool { - // Check valid images do not panic. - let mut buffer = Vec::::new(); - for webp_quality in [WebPQuality::lossless(), #[allow(deprecated)] WebPQuality::lossy(quality)] { - buffer.clear(); - #[allow(deprecated)] - let encoder = WebPEncoder::new_with_quality(&mut buffer, webp_quality); - if encoder - .write_image(&image.data, image.width, image.height, image.color).is_err() { - return false; - } - } - true - } - - fn fuzz_webp_no_panic(data: Vec, width: u8, height: u8, quality: u8) -> bool { - // Check random (usually invalid) parameters do not panic. - - if data.len() < width as usize * height as usize * 4 { - return true; - } - - let mut buffer = Vec::::new(); - for color in [ColorType::Rgb8, ColorType::Rgba8] { - for webp_quality in [WebPQuality::lossless(), #[allow(deprecated)] WebPQuality::lossy(quality)] { - buffer.clear(); - #[allow(deprecated)] - let encoder = WebPEncoder::new_with_quality(&mut buffer, webp_quality); - // Ignore errors. - let _ = encoder.write_image( - &data[..width as usize * height as usize * color.bytes_per_pixel() as usize], - width as u32, - height as u32, - color, - ); - } - } - true - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/extended.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/extended.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/extended.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/extended.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,868 +0,0 @@ -use std::io::{self, Cursor, Error, Read, Seek}; -use std::{error, fmt}; - -use super::decoder::{ - read_chunk, read_fourcc, read_len_cursor, DecoderError::ChunkHeaderInvalid, WebPRiffChunk, -}; -use super::lossless::{LosslessDecoder, LosslessFrame}; -use super::vp8::{Frame as VP8Frame, Vp8Decoder}; -use crate::error::{DecodingError, ParameterError, ParameterErrorKind}; -use crate::image::ImageFormat; -use crate::{ - ColorType, Delay, Frame, Frames, ImageError, ImageResult, Rgb, RgbImage, Rgba, RgbaImage, -}; -use byteorder::{LittleEndian, ReadBytesExt}; - -//all errors that can occur while parsing extended chunks in a WebP file -#[derive(Debug, Clone, Copy)] -enum DecoderError { - // Some bits were invalid - InfoBitsInvalid { name: &'static str, value: u32 }, - // Alpha chunk doesn't match the frame's size - AlphaChunkSizeMismatch, - // Image is too large, either for the platform's pointer size or generally - ImageTooLarge, - // Frame would go out of the canvas - FrameOutsideImage, -} - -impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DecoderError::InfoBitsInvalid { name, value } => f.write_fmt(format_args!( - "Info bits `{}` invalid, received value: {}", - name, value - )), - DecoderError::AlphaChunkSizeMismatch => { - f.write_str("Alpha chunk doesn't match the size of the frame") - } - DecoderError::ImageTooLarge => f.write_str("Image is too large to be decoded"), - DecoderError::FrameOutsideImage => { - f.write_str("Frame is too large and would go outside the image") - } - } - } -} - -impl From for ImageError { - fn from(e: DecoderError) -> ImageError { - ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e)) - } -} - -impl error::Error for DecoderError {} - -#[derive(Debug, Clone)] -pub(crate) struct WebPExtendedInfo { - _icc_profile: bool, - _alpha: bool, - _exif_metadata: bool, - _xmp_metadata: bool, - _animation: bool, - canvas_width: u32, - canvas_height: u32, - icc_profile: Option>, -} - -#[derive(Debug)] -enum ExtendedImageData { - Animation { - frames: Vec>, - first_frame: AnimatedFrame, - anim_info: WebPAnimatedInfo, - }, - Static(WebPStatic), -} - -#[derive(Debug)] -pub(crate) struct ExtendedImage { - info: WebPExtendedInfo, - image: ExtendedImageData, -} - -impl ExtendedImage { - pub(crate) fn dimensions(&self) -> (u32, u32) { - (self.info.canvas_width, self.info.canvas_height) - } - - pub(crate) fn has_animation(&self) -> bool { - self.info._animation - } - - pub(crate) fn icc_profile(&self) -> Option> { - self.info.icc_profile.clone() - } - - pub(crate) fn color_type(&self) -> ColorType { - match &self.image { - ExtendedImageData::Animation { first_frame, .. } => &first_frame.image, - ExtendedImageData::Static(image) => image, - } - .color_type() - } - - pub(crate) fn into_frames<'a>(self) -> Frames<'a> { - struct FrameIterator { - image: ExtendedImage, - index: usize, - canvas: RgbaImage, - } - - impl Iterator for FrameIterator { - type Item = ImageResult; - - fn next(&mut self) -> Option { - if let ExtendedImageData::Animation { - frames, - anim_info, - first_frame, - } = &self.image.image - { - let anim_frame_data = frames.get(self.index)?; - let anim_frame; - let frame; - - if self.index == 0 { - // Use already decoded first frame - anim_frame = first_frame; - } else { - frame = read_anim_frame( - &mut Cursor::new(anim_frame_data), - self.image.info.canvas_width, - self.image.info.canvas_height, - ) - .ok()?; - anim_frame = &frame; - }; - - self.index += 1; - ExtendedImage::draw_subimage( - &mut self.canvas, - anim_frame, - anim_info.background_color, - ) - } else { - None - } - } - } - - let width = self.info.canvas_width; - let height = self.info.canvas_height; - let background_color = - if let ExtendedImageData::Animation { ref anim_info, .. } = self.image { - anim_info.background_color - } else { - Rgba([0, 0, 0, 0]) - }; - - let frame_iter = FrameIterator { - image: self, - index: 0, - canvas: RgbaImage::from_pixel(width, height, background_color), - }; - - Frames::new(Box::new(frame_iter)) - } - - pub(crate) fn read_extended_chunks( - reader: &mut R, - mut info: WebPExtendedInfo, - ) -> ImageResult { - let mut anim_info: Option = None; - let mut anim_frames: Vec> = Vec::new(); - let mut anim_first_frame: Option = None; - let mut static_frame: Option = None; - //go until end of file and while chunk headers are valid - while let Some((mut cursor, chunk)) = read_extended_chunk(reader)? { - match chunk { - WebPRiffChunk::EXIF | WebPRiffChunk::XMP => { - //ignore these chunks - } - WebPRiffChunk::ANIM => { - if anim_info.is_none() { - anim_info = Some(Self::read_anim_info(&mut cursor)?); - } - } - WebPRiffChunk::ANMF => { - let mut frame_data = Vec::new(); - - // Store first frame decoded to avoid decoding it for certain function calls - if anim_first_frame.is_none() { - anim_first_frame = Some(read_anim_frame( - &mut cursor, - info.canvas_width, - info.canvas_height, - )?); - - cursor.rewind().unwrap(); - } - - cursor.read_to_end(&mut frame_data)?; - anim_frames.push(frame_data); - } - WebPRiffChunk::ALPH => { - if static_frame.is_none() { - let alpha_chunk = - read_alpha_chunk(&mut cursor, info.canvas_width, info.canvas_height)?; - - let vp8_frame = read_lossy_with_chunk(reader)?; - - let img = WebPStatic::from_alpha_lossy(alpha_chunk, vp8_frame)?; - - static_frame = Some(img); - } - } - WebPRiffChunk::ICCP => { - let mut icc_profile = Vec::new(); - cursor.read_to_end(&mut icc_profile)?; - info.icc_profile = Some(icc_profile); - } - WebPRiffChunk::VP8 => { - if static_frame.is_none() { - let vp8_frame = read_lossy(cursor)?; - - let img = WebPStatic::from_lossy(vp8_frame)?; - - static_frame = Some(img); - } - } - WebPRiffChunk::VP8L => { - if static_frame.is_none() { - let mut lossless_decoder = LosslessDecoder::new(cursor); - let frame = lossless_decoder.decode_frame()?; - let image = WebPStatic::Lossless(frame.clone()); - - static_frame = Some(image); - } - } - _ => return Err(ChunkHeaderInvalid(chunk.to_fourcc()).into()), - } - } - - let image = if let (Some(anim_info), Some(first_frame)) = (anim_info, anim_first_frame) { - ExtendedImageData::Animation { - frames: anim_frames, - first_frame, - anim_info, - } - } else if let Some(frame) = static_frame { - ExtendedImageData::Static(frame) - } else { - //reached end of file too early before image data was reached - return Err(ImageError::IoError(Error::from( - io::ErrorKind::UnexpectedEof, - ))); - }; - - let image = ExtendedImage { image, info }; - - Ok(image) - } - - fn read_anim_info(reader: &mut R) -> ImageResult { - let mut colors: [u8; 4] = [0; 4]; - reader.read_exact(&mut colors)?; - - //background color is [blue, green, red, alpha] - let background_color = Rgba([colors[2], colors[1], colors[0], colors[3]]); - - let loop_count = reader.read_u16::()?; - - let info = WebPAnimatedInfo { - background_color, - _loop_count: loop_count, - }; - - Ok(info) - } - - fn draw_subimage( - canvas: &mut RgbaImage, - anim_image: &AnimatedFrame, - background_color: Rgba, - ) -> Option> { - let mut buffer = vec![0; anim_image.image.get_buf_size()]; - anim_image.image.fill_buf(&mut buffer); - let has_alpha = anim_image.image.has_alpha(); - let pixel_len: u32 = anim_image.image.color_type().bytes_per_pixel().into(); - - 'x: for x in 0..anim_image.width { - for y in 0..anim_image.height { - let canvas_index: (u32, u32) = (x + anim_image.offset_x, y + anim_image.offset_y); - // Negative offsets are not possible due to unsigned ints - // If we go out of bounds by height, still continue by x - if canvas_index.1 >= canvas.height() { - continue 'x; - } - // If we go out of bounds by width, it doesn't make sense to continue at all - if canvas_index.0 >= canvas.width() { - break 'x; - } - let index: usize = ((y * anim_image.width + x) * pixel_len).try_into().unwrap(); - canvas[canvas_index] = if anim_image.use_alpha_blending && has_alpha { - let buffer: [u8; 4] = buffer[index..][..4].try_into().unwrap(); - ExtendedImage::do_alpha_blending(buffer, canvas[canvas_index]) - } else { - Rgba([ - buffer[index], - buffer[index + 1], - buffer[index + 2], - if has_alpha { buffer[index + 3] } else { 255 }, - ]) - }; - } - } - - let delay = Delay::from_numer_denom_ms(anim_image.duration, 1); - let img = canvas.clone(); - let frame = Frame::from_parts(img, 0, 0, delay); - - if anim_image.dispose { - for x in 0..anim_image.width { - for y in 0..anim_image.height { - let canvas_index = (x + anim_image.offset_x, y + anim_image.offset_y); - canvas[canvas_index] = background_color; - } - } - } - - Some(Ok(frame)) - } - - fn do_alpha_blending(buffer: [u8; 4], canvas: Rgba) -> Rgba { - let canvas_alpha = f64::from(canvas[3]); - let buffer_alpha = f64::from(buffer[3]); - let blend_alpha_f64 = buffer_alpha + canvas_alpha * (1.0 - buffer_alpha / 255.0); - //value should be between 0 and 255, this truncates the fractional part - let blend_alpha: u8 = blend_alpha_f64 as u8; - - let blend_rgb: [u8; 3] = if blend_alpha == 0 { - [0, 0, 0] - } else { - let mut rgb = [0u8; 3]; - for i in 0..3 { - let canvas_f64 = f64::from(canvas[i]); - let buffer_f64 = f64::from(buffer[i]); - - let val = (buffer_f64 * buffer_alpha - + canvas_f64 * canvas_alpha * (1.0 - buffer_alpha / 255.0)) - / blend_alpha_f64; - //value should be between 0 and 255, this truncates the fractional part - rgb[i] = val as u8; - } - - rgb - }; - - Rgba([blend_rgb[0], blend_rgb[1], blend_rgb[2], blend_alpha]) - } - - pub(crate) fn fill_buf(&self, buf: &mut [u8]) { - match &self.image { - // will always have at least one frame - ExtendedImageData::Animation { - anim_info, - first_frame, - .. - } => { - let (canvas_width, canvas_height) = self.dimensions(); - if canvas_width == first_frame.width && canvas_height == first_frame.height { - first_frame.image.fill_buf(buf); - } else { - let bg_color = match &self.info._alpha { - true => Rgba::from([0, 0, 0, 0]), - false => anim_info.background_color, - }; - let mut canvas = RgbaImage::from_pixel(canvas_width, canvas_height, bg_color); - let _ = ExtendedImage::draw_subimage(&mut canvas, first_frame, bg_color) - .unwrap() - .unwrap(); - buf.copy_from_slice(canvas.into_raw().as_slice()); - } - } - ExtendedImageData::Static(image) => { - image.fill_buf(buf); - } - } - } - - pub(crate) fn get_buf_size(&self) -> usize { - match &self.image { - // will always have at least one frame - ExtendedImageData::Animation { first_frame, .. } => &first_frame.image, - ExtendedImageData::Static(image) => image, - } - .get_buf_size() - } - - pub(crate) fn set_background_color(&mut self, color: Rgba) -> ImageResult<()> { - match &mut self.image { - ExtendedImageData::Animation { anim_info, .. } => { - anim_info.background_color = color; - Ok(()) - } - _ => Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::Generic( - "Background color can only be set on animated webp".to_owned(), - ), - ))), - } - } -} - -#[derive(Debug)] -enum WebPStatic { - LossyWithAlpha(RgbaImage), - LossyWithoutAlpha(RgbImage), - Lossless(LosslessFrame), -} - -impl WebPStatic { - pub(crate) fn from_alpha_lossy( - alpha: AlphaChunk, - vp8_frame: VP8Frame, - ) -> ImageResult { - if alpha.data.len() != usize::from(vp8_frame.width) * usize::from(vp8_frame.height) { - return Err(DecoderError::AlphaChunkSizeMismatch.into()); - } - - let size = usize::from(vp8_frame.width).checked_mul(usize::from(vp8_frame.height) * 4); - let mut image_vec = match size { - Some(size) => vec![0u8; size], - None => return Err(DecoderError::ImageTooLarge.into()), - }; - - vp8_frame.fill_rgba(&mut image_vec); - - for y in 0..vp8_frame.height { - for x in 0..vp8_frame.width { - let predictor: u8 = WebPStatic::get_predictor( - x.into(), - y.into(), - vp8_frame.width.into(), - alpha.filtering_method, - &image_vec, - ); - let predictor = u16::from(predictor); - - let alpha_index = usize::from(y) * usize::from(vp8_frame.width) + usize::from(x); - let alpha_val = alpha.data[alpha_index]; - let alpha: u8 = ((predictor + u16::from(alpha_val)) % 256) - .try_into() - .unwrap(); - - let alpha_index = alpha_index * 4 + 3; - image_vec[alpha_index] = alpha; - } - } - - let image = RgbaImage::from_vec(vp8_frame.width.into(), vp8_frame.height.into(), image_vec) - .unwrap(); - - Ok(WebPStatic::LossyWithAlpha(image)) - } - - fn get_predictor( - x: usize, - y: usize, - width: usize, - filtering_method: FilteringMethod, - image_slice: &[u8], - ) -> u8 { - match filtering_method { - FilteringMethod::None => 0, - FilteringMethod::Horizontal => { - if x == 0 && y == 0 { - 0 - } else if x == 0 { - let index = (y - 1) * width + x; - image_slice[index * 4 + 3] - } else { - let index = y * width + x - 1; - image_slice[index * 4 + 3] - } - } - FilteringMethod::Vertical => { - if x == 0 && y == 0 { - 0 - } else if y == 0 { - let index = y * width + x - 1; - image_slice[index * 4 + 3] - } else { - let index = (y - 1) * width + x; - image_slice[index * 4 + 3] - } - } - FilteringMethod::Gradient => { - let (left, top, top_left) = match (x, y) { - (0, 0) => (0, 0, 0), - (0, y) => { - let above_index = (y - 1) * width + x; - let val = image_slice[above_index * 4 + 3]; - (val, val, val) - } - (x, 0) => { - let before_index = y * width + x - 1; - let val = image_slice[before_index * 4 + 3]; - (val, val, val) - } - (x, y) => { - let left_index = y * width + x - 1; - let left = image_slice[left_index * 4 + 3]; - let top_index = (y - 1) * width + x; - let top = image_slice[top_index * 4 + 3]; - let top_left_index = (y - 1) * width + x - 1; - let top_left = image_slice[top_left_index * 4 + 3]; - - (left, top, top_left) - } - }; - - let combination = i16::from(left) + i16::from(top) - i16::from(top_left); - i16::clamp(combination, 0, 255).try_into().unwrap() - } - } - } - - pub(crate) fn from_lossy(vp8_frame: VP8Frame) -> ImageResult { - let mut image = RgbImage::from_pixel( - vp8_frame.width.into(), - vp8_frame.height.into(), - Rgb([0, 0, 0]), - ); - - vp8_frame.fill_rgb(&mut image); - - Ok(WebPStatic::LossyWithoutAlpha(image)) - } - - pub(crate) fn fill_buf(&self, buf: &mut [u8]) { - match self { - WebPStatic::LossyWithAlpha(image) => { - buf.copy_from_slice(image); - } - WebPStatic::LossyWithoutAlpha(image) => { - buf.copy_from_slice(image); - } - WebPStatic::Lossless(lossless) => { - lossless.fill_rgba(buf); - } - } - } - - pub(crate) fn get_buf_size(&self) -> usize { - match self { - WebPStatic::LossyWithAlpha(rgb_image) => rgb_image.len(), - WebPStatic::LossyWithoutAlpha(rgba_image) => rgba_image.len(), - WebPStatic::Lossless(lossless) => lossless.get_buf_size(), - } - } - - pub(crate) fn color_type(&self) -> ColorType { - if self.has_alpha() { - ColorType::Rgba8 - } else { - ColorType::Rgb8 - } - } - - pub(crate) fn has_alpha(&self) -> bool { - match self { - Self::LossyWithAlpha(..) | Self::Lossless(..) => true, - Self::LossyWithoutAlpha(..) => false, - } - } -} - -#[derive(Debug)] -struct WebPAnimatedInfo { - background_color: Rgba, - _loop_count: u16, -} - -#[derive(Debug)] -struct AnimatedFrame { - offset_x: u32, - offset_y: u32, - width: u32, - height: u32, - duration: u32, - use_alpha_blending: bool, - dispose: bool, - image: WebPStatic, -} - -/// Reads a chunk, but silently ignores unknown chunks at the end of a file -fn read_extended_chunk(r: &mut R) -> ImageResult>, WebPRiffChunk)>> -where - R: Read, -{ - let mut unknown_chunk = Ok(()); - - while let Some(chunk) = read_fourcc(r)? { - let cursor = read_len_cursor(r)?; - match chunk { - Ok(chunk) => return unknown_chunk.and(Ok(Some((cursor, chunk)))), - Err(err) => unknown_chunk = unknown_chunk.and(Err(err)), - } - } - - Ok(None) -} - -pub(crate) fn read_extended_header(reader: &mut R) -> ImageResult { - let chunk_flags = reader.read_u8()?; - - let reserved_first = chunk_flags & 0b11000000; - let icc_profile = chunk_flags & 0b00100000 != 0; - let alpha = chunk_flags & 0b00010000 != 0; - let exif_metadata = chunk_flags & 0b00001000 != 0; - let xmp_metadata = chunk_flags & 0b00000100 != 0; - let animation = chunk_flags & 0b00000010 != 0; - let reserved_second = chunk_flags & 0b00000001; - - let reserved_third = read_3_bytes(reader)?; - - if reserved_first != 0 || reserved_second != 0 || reserved_third != 0 { - let value: u32 = if reserved_first != 0 { - reserved_first.into() - } else if reserved_second != 0 { - reserved_second.into() - } else { - reserved_third - }; - return Err(DecoderError::InfoBitsInvalid { - name: "reserved", - value, - } - .into()); - } - - let canvas_width = read_3_bytes(reader)? + 1; - let canvas_height = read_3_bytes(reader)? + 1; - - //product of canvas dimensions cannot be larger than u32 max - if u32::checked_mul(canvas_width, canvas_height).is_none() { - return Err(DecoderError::ImageTooLarge.into()); - } - - let info = WebPExtendedInfo { - _icc_profile: icc_profile, - _alpha: alpha, - _exif_metadata: exif_metadata, - _xmp_metadata: xmp_metadata, - _animation: animation, - canvas_width, - canvas_height, - icc_profile: None, - }; - - Ok(info) -} - -fn read_anim_frame( - mut reader: R, - canvas_width: u32, - canvas_height: u32, -) -> ImageResult { - //offsets for the frames are twice the values - let frame_x = read_3_bytes(&mut reader)? * 2; - let frame_y = read_3_bytes(&mut reader)? * 2; - - let frame_width = read_3_bytes(&mut reader)? + 1; - let frame_height = read_3_bytes(&mut reader)? + 1; - - if frame_x + frame_width > canvas_width || frame_y + frame_height > canvas_height { - return Err(DecoderError::FrameOutsideImage.into()); - } - - let duration = read_3_bytes(&mut reader)?; - - let frame_info = reader.read_u8()?; - let reserved = frame_info & 0b11111100; - if reserved != 0 { - return Err(DecoderError::InfoBitsInvalid { - name: "reserved", - value: reserved.into(), - } - .into()); - } - let use_alpha_blending = frame_info & 0b00000010 == 0; - let dispose = frame_info & 0b00000001 != 0; - - //read normal bitstream now - let static_image = read_image(&mut reader, frame_width, frame_height)?; - - let frame = AnimatedFrame { - offset_x: frame_x, - offset_y: frame_y, - width: frame_width, - height: frame_height, - duration, - use_alpha_blending, - dispose, - image: static_image, - }; - - Ok(frame) -} - -fn read_3_bytes(reader: &mut R) -> ImageResult { - let mut buffer: [u8; 3] = [0; 3]; - reader.read_exact(&mut buffer)?; - let value: u32 = - (u32::from(buffer[2]) << 16) | (u32::from(buffer[1]) << 8) | u32::from(buffer[0]); - Ok(value) -} - -fn read_lossy_with_chunk(reader: &mut R) -> ImageResult { - let (cursor, chunk) = - read_chunk(reader)?.ok_or_else(|| Error::from(io::ErrorKind::UnexpectedEof))?; - - if chunk != WebPRiffChunk::VP8 { - return Err(ChunkHeaderInvalid(chunk.to_fourcc()).into()); - } - - read_lossy(cursor) -} - -fn read_lossy(cursor: Cursor>) -> ImageResult { - let mut vp8_decoder = Vp8Decoder::new(cursor); - let frame = vp8_decoder.decode_frame()?; - - Ok(frame.clone()) -} - -fn read_image(reader: &mut R, width: u32, height: u32) -> ImageResult { - let chunk = read_chunk(reader)?; - - match chunk { - Some((cursor, WebPRiffChunk::VP8)) => { - let mut vp8_decoder = Vp8Decoder::new(cursor); - let frame = vp8_decoder.decode_frame()?; - - let img = WebPStatic::from_lossy(frame.clone())?; - - Ok(img) - } - Some((cursor, WebPRiffChunk::VP8L)) => { - let mut lossless_decoder = LosslessDecoder::new(cursor); - let frame = lossless_decoder.decode_frame()?; - - let img = WebPStatic::Lossless(frame.clone()); - - Ok(img) - } - Some((mut cursor, WebPRiffChunk::ALPH)) => { - let alpha_chunk = read_alpha_chunk(&mut cursor, width, height)?; - - let vp8_frame = read_lossy_with_chunk(reader)?; - - let img = WebPStatic::from_alpha_lossy(alpha_chunk, vp8_frame)?; - - Ok(img) - } - None => Err(ImageError::IoError(Error::from( - io::ErrorKind::UnexpectedEof, - ))), - Some((_, chunk)) => Err(ChunkHeaderInvalid(chunk.to_fourcc()).into()), - } -} - -#[derive(Debug)] -struct AlphaChunk { - _preprocessing: bool, - filtering_method: FilteringMethod, - data: Vec, -} - -#[derive(Debug, Copy, Clone)] -enum FilteringMethod { - None, - Horizontal, - Vertical, - Gradient, -} - -fn read_alpha_chunk(reader: &mut R, width: u32, height: u32) -> ImageResult { - let info_byte = reader.read_u8()?; - - let reserved = info_byte & 0b11000000; - let preprocessing = (info_byte & 0b00110000) >> 4; - let filtering = (info_byte & 0b00001100) >> 2; - let compression = info_byte & 0b00000011; - - if reserved != 0 { - return Err(DecoderError::InfoBitsInvalid { - name: "reserved", - value: reserved.into(), - } - .into()); - } - - let preprocessing = match preprocessing { - 0 => false, - 1 => true, - _ => { - return Err(DecoderError::InfoBitsInvalid { - name: "reserved", - value: preprocessing.into(), - } - .into()) - } - }; - - let filtering_method = match filtering { - 0 => FilteringMethod::None, - 1 => FilteringMethod::Horizontal, - 2 => FilteringMethod::Vertical, - 3 => FilteringMethod::Gradient, - _ => unreachable!(), - }; - - let lossless_compression = match compression { - 0 => false, - 1 => true, - _ => { - return Err(DecoderError::InfoBitsInvalid { - name: "lossless compression", - value: compression.into(), - } - .into()) - } - }; - - let mut framedata = Vec::new(); - reader.read_to_end(&mut framedata)?; - - let data = if lossless_compression { - let cursor = io::Cursor::new(framedata); - - let mut decoder = LosslessDecoder::new(cursor); - //this is a potential problem for large images; would require rewriting lossless decoder to use u32 for width and height - let width: u16 = width - .try_into() - .map_err(|_| ImageError::from(DecoderError::ImageTooLarge))?; - let height: u16 = height - .try_into() - .map_err(|_| ImageError::from(DecoderError::ImageTooLarge))?; - let frame = decoder.decode_frame_implicit_dims(width, height)?; - - let mut data = vec![0u8; usize::from(width) * usize::from(height)]; - - frame.fill_green(&mut data); - - data - } else { - framedata - }; - - let chunk = AlphaChunk { - _preprocessing: preprocessing, - filtering_method, - data, - }; - - Ok(chunk) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/huffman.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/huffman.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ -use super::lossless::BitReader; -use super::lossless::DecoderError; -use crate::ImageResult; - -/// Rudimentary utility for reading Canonical Huffman Codes. -/// Based off https://github.com/webmproject/libwebp/blob/7f8472a610b61ec780ef0a8873cd954ac512a505/src/utils/huffman.c -/// - -const MAX_ALLOWED_CODE_LENGTH: usize = 15; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum HuffmanTreeNode { - Branch(usize), //offset in vector to children - Leaf(u16), //symbol stored in leaf - Empty, -} - -/// Huffman tree -#[derive(Clone, Debug, Default)] -pub(crate) struct HuffmanTree { - tree: Vec, - max_nodes: usize, - num_nodes: usize, -} - -impl HuffmanTree { - fn is_full(&self) -> bool { - self.num_nodes == self.max_nodes - } - - /// Turns a node from empty into a branch and assigns its children - fn assign_children(&mut self, node_index: usize) -> usize { - let offset_index = self.num_nodes - node_index; - self.tree[node_index] = HuffmanTreeNode::Branch(offset_index); - self.num_nodes += 2; - - offset_index - } - - /// Init a huffman tree - fn init(num_leaves: usize) -> ImageResult { - if num_leaves == 0 { - return Err(DecoderError::HuffmanError.into()); - } - - let max_nodes = 2 * num_leaves - 1; - let tree = vec![HuffmanTreeNode::Empty; max_nodes]; - let num_nodes = 1; - - let tree = HuffmanTree { - tree, - max_nodes, - num_nodes, - }; - - Ok(tree) - } - - /// Converts code lengths to codes - fn code_lengths_to_codes(code_lengths: &[u16]) -> ImageResult>> { - let max_code_length = *code_lengths - .iter() - .reduce(|a, b| if a >= b { a } else { b }) - .unwrap(); - - if max_code_length > MAX_ALLOWED_CODE_LENGTH.try_into().unwrap() { - return Err(DecoderError::HuffmanError.into()); - } - - let mut code_length_hist = [0; MAX_ALLOWED_CODE_LENGTH + 1]; - - for &length in code_lengths.iter() { - code_length_hist[usize::from(length)] += 1; - } - - code_length_hist[0] = 0; - - let mut curr_code = 0; - let mut next_codes = [None; MAX_ALLOWED_CODE_LENGTH + 1]; - - for code_len in 1..=usize::from(max_code_length) { - curr_code = (curr_code + code_length_hist[code_len - 1]) << 1; - next_codes[code_len] = Some(curr_code); - } - - let mut huff_codes = vec![None; code_lengths.len()]; - - for (symbol, &length) in code_lengths.iter().enumerate() { - let length = usize::from(length); - if length > 0 { - huff_codes[symbol] = next_codes[length]; - if let Some(value) = next_codes[length].as_mut() { - *value += 1; - } - } else { - huff_codes[symbol] = None; - } - } - - Ok(huff_codes) - } - - /// Adds a symbol to a huffman tree - fn add_symbol(&mut self, symbol: u16, code: u16, code_length: u16) -> ImageResult<()> { - let mut node_index = 0; - let code = usize::from(code); - - for length in (0..code_length).rev() { - if node_index >= self.max_nodes { - return Err(DecoderError::HuffmanError.into()); - } - - let node = self.tree[node_index]; - - let offset = match node { - HuffmanTreeNode::Empty => { - if self.is_full() { - return Err(DecoderError::HuffmanError.into()); - } - self.assign_children(node_index) - } - HuffmanTreeNode::Leaf(_) => return Err(DecoderError::HuffmanError.into()), - HuffmanTreeNode::Branch(offset) => offset, - }; - - node_index += offset + ((code >> length) & 1); - } - - match self.tree[node_index] { - HuffmanTreeNode::Empty => self.tree[node_index] = HuffmanTreeNode::Leaf(symbol), - HuffmanTreeNode::Leaf(_) => return Err(DecoderError::HuffmanError.into()), - HuffmanTreeNode::Branch(_offset) => return Err(DecoderError::HuffmanError.into()), - } - - Ok(()) - } - - /// Builds a tree implicitly, just from code lengths - pub(crate) fn build_implicit(code_lengths: Vec) -> ImageResult { - let mut num_symbols = 0; - let mut root_symbol = 0; - - for (symbol, length) in code_lengths.iter().enumerate() { - if *length > 0 { - num_symbols += 1; - root_symbol = symbol.try_into().unwrap(); - } - } - - let mut tree = HuffmanTree::init(num_symbols)?; - - if num_symbols == 1 { - tree.add_symbol(root_symbol, 0, 0)?; - } else { - let codes = HuffmanTree::code_lengths_to_codes(&code_lengths)?; - - for (symbol, &length) in code_lengths.iter().enumerate() { - if length > 0 && codes[symbol].is_some() { - tree.add_symbol(symbol.try_into().unwrap(), codes[symbol].unwrap(), length)?; - } - } - } - - Ok(tree) - } - - /// Builds a tree explicitly from lengths, codes and symbols - pub(crate) fn build_explicit( - code_lengths: Vec, - codes: Vec, - symbols: Vec, - ) -> ImageResult { - let mut tree = HuffmanTree::init(symbols.len())?; - - for i in 0..symbols.len() { - tree.add_symbol(symbols[i], codes[i], code_lengths[i])?; - } - - Ok(tree) - } - - /// Reads a symbol using the bitstream - pub(crate) fn read_symbol(&self, bit_reader: &mut BitReader) -> ImageResult { - let mut index = 0; - let mut node = self.tree[index]; - - while let HuffmanTreeNode::Branch(children_offset) = node { - index += children_offset + bit_reader.read_bits::(1)?; - node = self.tree[index]; - } - - let symbol = match node { - HuffmanTreeNode::Branch(_) => unreachable!(), - HuffmanTreeNode::Empty => return Err(DecoderError::HuffmanError.into()), - HuffmanTreeNode::Leaf(symbol) => symbol, - }; - - Ok(symbol) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/loop_filter.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/loop_filter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/loop_filter.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/loop_filter.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -//! Does loop filtering on webp lossy images - -use crate::utils::clamp; - -#[inline] -fn c(val: i32) -> i32 { - clamp(val, -128, 127) -} - -//unsigned to signed -#[inline] -fn u2s(val: u8) -> i32 { - i32::from(val) - 128 -} - -//signed to unsigned -#[inline] -fn s2u(val: i32) -> u8 { - (c(val) + 128) as u8 -} - -#[inline] -fn diff(val1: u8, val2: u8) -> u8 { - if val1 > val2 { - val1 - val2 - } else { - val2 - val1 - } -} - -//15.2 -fn common_adjust(use_outer_taps: bool, pixels: &mut [u8], point: usize, stride: usize) -> i32 { - let p1 = u2s(pixels[point - 2 * stride]); - let p0 = u2s(pixels[point - stride]); - let q0 = u2s(pixels[point]); - let q1 = u2s(pixels[point + stride]); - - //value for the outer 2 pixels - let outer = if use_outer_taps { c(p1 - q1) } else { 0 }; - - let mut a = c(outer + 3 * (q0 - p0)); - - let b = (c(a + 3)) >> 3; - - a = (c(a + 4)) >> 3; - - pixels[point] = s2u(q0 - a); - pixels[point - stride] = s2u(p0 + b); - - a -} - -fn simple_threshold(filter_limit: i32, pixels: &[u8], point: usize, stride: usize) -> bool { - i32::from(diff(pixels[point - stride], pixels[point])) * 2 - + i32::from(diff(pixels[point - 2 * stride], pixels[point + stride])) / 2 - <= filter_limit -} - -fn should_filter( - interior_limit: u8, - edge_limit: u8, - pixels: &[u8], - point: usize, - stride: usize, -) -> bool { - simple_threshold(i32::from(edge_limit), pixels, point, stride) - && diff(pixels[point - 4 * stride], pixels[point - 3 * stride]) <= interior_limit - && diff(pixels[point - 3 * stride], pixels[point - 2 * stride]) <= interior_limit - && diff(pixels[point - 2 * stride], pixels[point - stride]) <= interior_limit - && diff(pixels[point + 3 * stride], pixels[point + 2 * stride]) <= interior_limit - && diff(pixels[point + 2 * stride], pixels[point + stride]) <= interior_limit - && diff(pixels[point + stride], pixels[point]) <= interior_limit -} - -fn high_edge_variance(threshold: u8, pixels: &[u8], point: usize, stride: usize) -> bool { - diff(pixels[point - 2 * stride], pixels[point - stride]) > threshold - || diff(pixels[point + stride], pixels[point]) > threshold -} - -//simple filter -//effects 4 pixels on an edge(2 each side) -pub(crate) fn simple_segment(edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) { - if simple_threshold(i32::from(edge_limit), pixels, point, stride) { - common_adjust(true, pixels, point, stride); - } -} - -//normal filter -//works on the 8 pixels on the edges between subblocks inside a macroblock -pub(crate) fn subblock_filter( - hev_threshold: u8, - interior_limit: u8, - edge_limit: u8, - pixels: &mut [u8], - point: usize, - stride: usize, -) { - if should_filter(interior_limit, edge_limit, pixels, point, stride) { - let hv = high_edge_variance(hev_threshold, pixels, point, stride); - - let a = (common_adjust(hv, pixels, point, stride) + 1) >> 1; - - if !hv { - pixels[point + stride] = s2u(u2s(pixels[point + stride]) - a); - pixels[point - 2 * stride] = s2u(u2s(pixels[point - 2 * stride]) - a); - } - } -} - -//normal filter -//works on the 8 pixels on the edges between macroblocks -pub(crate) fn macroblock_filter( - hev_threshold: u8, - interior_limit: u8, - edge_limit: u8, - pixels: &mut [u8], - point: usize, - stride: usize, -) { - let mut spixels = [0i32; 8]; - for i in 0..8 { - spixels[i] = u2s(pixels[point + i * stride - 4 * stride]); - } - - if should_filter(interior_limit, edge_limit, pixels, point, stride) { - if !high_edge_variance(hev_threshold, pixels, point, stride) { - let w = c(c(spixels[2] - spixels[5]) + 3 * (spixels[4] - spixels[3])); - - let mut a = c((27 * w + 63) >> 7); - - pixels[point] = s2u(spixels[4] - a); - pixels[point - stride] = s2u(spixels[3] + a); - - a = c((18 * w + 63) >> 7); - - pixels[point + stride] = s2u(spixels[5] - a); - pixels[point - 2 * stride] = s2u(spixels[2] + a); - - a = c((9 * w + 63) >> 7); - - pixels[point + 2 * stride] = s2u(spixels[6] - a); - pixels[point - 3 * stride] = s2u(spixels[1] + a); - } else { - common_adjust(true, pixels, point, stride); - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/lossless.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/lossless.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,781 +0,0 @@ -//! Decoding of lossless WebP images -//! -//! [Lossless spec](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification) -//! - -use std::{ - error, fmt, - io::Read, - ops::{AddAssign, Shl}, -}; - -use byteorder::ReadBytesExt; - -use crate::{error::DecodingError, ImageError, ImageFormat, ImageResult}; - -use super::huffman::HuffmanTree; -use super::lossless_transform::{add_pixels, TransformType}; - -const CODE_LENGTH_CODES: usize = 19; -const CODE_LENGTH_CODE_ORDER: [usize; CODE_LENGTH_CODES] = [ - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -]; - -#[rustfmt::skip] -const DISTANCE_MAP: [(i8, i8); 120] = [ - (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), (-1, 2), - (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), (1, 3), (-1, 3), - (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), (-3, 2), (0, 4), (4, 0), - (1, 4), (-1, 4), (4, 1), (-4, 1), (3, 3), (-3, 3), (2, 4), (-2, 4), - (4, 2), (-4, 2), (0, 5), (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), - (1, 5), (-1, 5), (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), - (4, 4), (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), - (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), (-6, 2), - (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), (6, 3), (-6, 3), - (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), (-5, 5), (7, 1), (-7, 1), - (4, 6), (-4, 6), (6, 4), (-6, 4), (2, 7), (-2, 7), (7, 2), (-7, 2), - (3, 7), (-3, 7), (7, 3), (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), - (8, 0), (4, 7), (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), - (-6, 6), (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), - (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7) -]; - -const GREEN: usize = 0; -const RED: usize = 1; -const BLUE: usize = 2; -const ALPHA: usize = 3; -const DIST: usize = 4; - -const HUFFMAN_CODES_PER_META_CODE: usize = 5; - -type HuffmanCodeGroup = [HuffmanTree; HUFFMAN_CODES_PER_META_CODE]; - -const ALPHABET_SIZE: [u16; HUFFMAN_CODES_PER_META_CODE] = [256 + 24, 256, 256, 256, 40]; - -#[inline] -pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { - ((u32::from(size) + (1u32 << bits) - 1) >> bits) - .try_into() - .unwrap() -} - -#[derive(Debug, Clone, Copy)] -pub(crate) enum DecoderError { - /// Signature of 0x2f not found - LosslessSignatureInvalid(u8), - /// Version Number must be 0 - VersionNumberInvalid(u8), - - /// - InvalidColorCacheBits(u8), - - HuffmanError, - - BitStreamError, - - TransformError, -} - -impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DecoderError::LosslessSignatureInvalid(sig) => { - f.write_fmt(format_args!("Invalid lossless signature: {}", sig)) - } - DecoderError::VersionNumberInvalid(num) => { - f.write_fmt(format_args!("Invalid version number: {}", num)) - } - DecoderError::InvalidColorCacheBits(num) => f.write_fmt(format_args!( - "Invalid color cache(must be between 1-11): {}", - num - )), - DecoderError::HuffmanError => f.write_fmt(format_args!("Error building Huffman Tree")), - DecoderError::BitStreamError => { - f.write_fmt(format_args!("Error while reading bitstream")) - } - DecoderError::TransformError => { - f.write_fmt(format_args!("Error while reading or writing transforms")) - } - } - } -} - -impl From for ImageError { - fn from(e: DecoderError) -> ImageError { - ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e)) - } -} - -impl error::Error for DecoderError {} - -const NUM_TRANSFORM_TYPES: usize = 4; - -//Decodes lossless WebP images -#[derive(Debug)] -pub(crate) struct LosslessDecoder { - r: R, - bit_reader: BitReader, - frame: LosslessFrame, - transforms: [Option; NUM_TRANSFORM_TYPES], - transform_order: Vec, -} - -impl LosslessDecoder { - /// Create a new decoder - pub(crate) fn new(r: R) -> LosslessDecoder { - LosslessDecoder { - r, - bit_reader: BitReader::new(), - frame: Default::default(), - transforms: [None, None, None, None], - transform_order: Vec::new(), - } - } - - /// Reads the frame - pub(crate) fn decode_frame(&mut self) -> ImageResult<&LosslessFrame> { - let signature = self.r.read_u8()?; - - if signature != 0x2f { - return Err(DecoderError::LosslessSignatureInvalid(signature).into()); - } - - let mut buf = Vec::new(); - self.r.read_to_end(&mut buf)?; - self.bit_reader.init(buf); - - self.frame.width = self.bit_reader.read_bits::(14)? + 1; - self.frame.height = self.bit_reader.read_bits::(14)? + 1; - - let _alpha_used = self.bit_reader.read_bits::(1)?; - - let version_num = self.bit_reader.read_bits::(3)?; - - if version_num != 0 { - return Err(DecoderError::VersionNumberInvalid(version_num).into()); - } - - let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?; - - for &trans_index in self.transform_order.iter().rev() { - let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap(); - trans.apply_transform(&mut data, self.frame.width, self.frame.height)?; - } - - self.frame.buf = data; - Ok(&self.frame) - } - - //used for alpha data in extended decoding - pub(crate) fn decode_frame_implicit_dims( - &mut self, - width: u16, - height: u16, - ) -> ImageResult<&LosslessFrame> { - let mut buf = Vec::new(); - self.r.read_to_end(&mut buf)?; - self.bit_reader.init(buf); - - self.frame.width = width; - self.frame.height = height; - - let mut data = self.decode_image_stream(self.frame.width, self.frame.height, true)?; - - //transform_order is vector of indices(0-3) into transforms in order decoded - for &trans_index in self.transform_order.iter().rev() { - let trans = self.transforms[usize::from(trans_index)].as_ref().unwrap(); - trans.apply_transform(&mut data, self.frame.width, self.frame.height)?; - } - - self.frame.buf = data; - Ok(&self.frame) - } - - /// Reads Image data from the bitstream - /// Can be in any of the 5 roles described in the Specification - /// ARGB Image role has different behaviour to the other 4 - /// xsize and ysize describe the size of the blocks where each block has its own entropy code - fn decode_image_stream( - &mut self, - xsize: u16, - ysize: u16, - is_argb_img: bool, - ) -> ImageResult> { - let trans_xsize = if is_argb_img { - self.read_transforms()? - } else { - xsize - }; - - let color_cache_bits = self.read_color_cache()?; - - let color_cache = color_cache_bits.map(|bits| { - let size = 1 << bits; - let cache = vec![0u32; size]; - ColorCache { - color_cache_bits: bits, - color_cache: cache, - } - }); - - let huffman_info = self.read_huffman_codes(is_argb_img, trans_xsize, ysize, color_cache)?; - - //decode data - let data = self.decode_image_data(trans_xsize, ysize, huffman_info)?; - - Ok(data) - } - - /// Reads transforms and their data from the bitstream - fn read_transforms(&mut self) -> ImageResult { - let mut xsize = self.frame.width; - - while self.bit_reader.read_bits::(1)? == 1 { - let transform_type_val = self.bit_reader.read_bits::(2)?; - - if self.transforms[usize::from(transform_type_val)].is_some() { - //can only have one of each transform, error - return Err(DecoderError::TransformError.into()); - } - - self.transform_order.push(transform_type_val); - - let transform_type = match transform_type_val { - 0 => { - //predictor - - let size_bits = self.bit_reader.read_bits::(3)? + 2; - - let block_xsize = subsample_size(xsize, size_bits); - let block_ysize = subsample_size(self.frame.height, size_bits); - - let data = self.decode_image_stream(block_xsize, block_ysize, false)?; - - TransformType::PredictorTransform { - size_bits, - predictor_data: data, - } - } - 1 => { - //color transform - - let size_bits = self.bit_reader.read_bits::(3)? + 2; - - let block_xsize = subsample_size(xsize, size_bits); - let block_ysize = subsample_size(self.frame.height, size_bits); - - let data = self.decode_image_stream(block_xsize, block_ysize, false)?; - - TransformType::ColorTransform { - size_bits, - transform_data: data, - } - } - 2 => { - //subtract green - - TransformType::SubtractGreen - } - 3 => { - let color_table_size = self.bit_reader.read_bits::(8)? + 1; - - let mut color_map = self.decode_image_stream(color_table_size, 1, false)?; - - let bits = if color_table_size <= 2 { - 3 - } else if color_table_size <= 4 { - 2 - } else if color_table_size <= 16 { - 1 - } else { - 0 - }; - xsize = subsample_size(xsize, bits); - - Self::adjust_color_map(&mut color_map); - - TransformType::ColorIndexingTransform { - table_size: color_table_size, - table_data: color_map, - } - } - _ => unreachable!(), - }; - - self.transforms[usize::from(transform_type_val)] = Some(transform_type); - } - - Ok(xsize) - } - - /// Adjusts the color map since it's subtraction coded - fn adjust_color_map(color_map: &mut [u32]) { - for i in 1..color_map.len() { - color_map[i] = add_pixels(color_map[i], color_map[i - 1]); - } - } - - /// Reads huffman codes associated with an image - fn read_huffman_codes( - &mut self, - read_meta: bool, - xsize: u16, - ysize: u16, - color_cache: Option, - ) -> ImageResult { - let mut num_huff_groups = 1; - - let mut huffman_bits = 0; - let mut huffman_xsize = 1; - let mut huffman_ysize = 1; - let mut entropy_image = Vec::new(); - - if read_meta && self.bit_reader.read_bits::(1)? == 1 { - //meta huffman codes - huffman_bits = self.bit_reader.read_bits::(3)? + 2; - huffman_xsize = subsample_size(xsize, huffman_bits); - huffman_ysize = subsample_size(ysize, huffman_bits); - - entropy_image = self.decode_image_stream(huffman_xsize, huffman_ysize, false)?; - - for pixel in entropy_image.iter_mut() { - let meta_huff_code = (*pixel >> 8) & 0xffff; - - *pixel = meta_huff_code; - - if meta_huff_code >= num_huff_groups { - num_huff_groups = meta_huff_code + 1; - } - } - } - - let mut hufftree_groups = Vec::new(); - - for _i in 0..num_huff_groups { - let mut group: HuffmanCodeGroup = Default::default(); - for j in 0..HUFFMAN_CODES_PER_META_CODE { - let mut alphabet_size = ALPHABET_SIZE[j]; - if j == 0 { - if let Some(color_cache) = color_cache.as_ref() { - alphabet_size += 1 << color_cache.color_cache_bits; - } - } - - let tree = self.read_huffman_code(alphabet_size)?; - group[j] = tree; - } - hufftree_groups.push(group); - } - - let huffman_mask = if huffman_bits == 0 { - !0 - } else { - (1 << huffman_bits) - 1 - }; - - let info = HuffmanInfo { - xsize: huffman_xsize, - _ysize: huffman_ysize, - color_cache, - image: entropy_image, - bits: huffman_bits, - mask: huffman_mask, - huffman_code_groups: hufftree_groups, - }; - - Ok(info) - } - - /// Decodes and returns a single huffman tree - fn read_huffman_code(&mut self, alphabet_size: u16) -> ImageResult { - let simple = self.bit_reader.read_bits::(1)? == 1; - - if simple { - let num_symbols = self.bit_reader.read_bits::(1)? + 1; - - let mut code_lengths = vec![u16::from(num_symbols - 1)]; - let mut codes = vec![0]; - let mut symbols = Vec::new(); - - let is_first_8bits = self.bit_reader.read_bits::(1)?; - symbols.push(self.bit_reader.read_bits::(1 + 7 * is_first_8bits)?); - - if num_symbols == 2 { - symbols.push(self.bit_reader.read_bits::(8)?); - code_lengths.push(1); - codes.push(1); - } - - HuffmanTree::build_explicit(code_lengths, codes, symbols) - } else { - let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; - - let num_code_lengths = 4 + self.bit_reader.read_bits::(4)?; - for i in 0..num_code_lengths { - code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = - self.bit_reader.read_bits(3)?; - } - - let new_code_lengths = - self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; - - HuffmanTree::build_implicit(new_code_lengths) - } - } - - /// Reads huffman code lengths - fn read_huffman_code_lengths( - &mut self, - code_length_code_lengths: Vec, - num_symbols: u16, - ) -> ImageResult> { - let table = HuffmanTree::build_implicit(code_length_code_lengths)?; - - let mut max_symbol = if self.bit_reader.read_bits::(1)? == 1 { - let length_nbits = 2 + 2 * self.bit_reader.read_bits::(3)?; - 2 + self.bit_reader.read_bits::(length_nbits)? - } else { - num_symbols - }; - - let mut code_lengths = vec![0; usize::from(num_symbols)]; - let mut prev_code_len = 8; //default code length - - let mut symbol = 0; - while symbol < num_symbols { - if max_symbol == 0 { - break; - } - max_symbol -= 1; - - let code_len = table.read_symbol(&mut self.bit_reader)?; - - if code_len < 16 { - code_lengths[usize::from(symbol)] = code_len; - symbol += 1; - if code_len != 0 { - prev_code_len = code_len; - } - } else { - let use_prev = code_len == 16; - let slot = code_len - 16; - let extra_bits = match slot { - 0 => 2, - 1 => 3, - 2 => 7, - _ => return Err(DecoderError::BitStreamError.into()), - }; - let repeat_offset = match slot { - 0 | 1 => 3, - 2 => 11, - _ => return Err(DecoderError::BitStreamError.into()), - }; - - let mut repeat = self.bit_reader.read_bits::(extra_bits)? + repeat_offset; - - if symbol + repeat > num_symbols { - return Err(DecoderError::BitStreamError.into()); - } else { - let length = if use_prev { prev_code_len } else { 0 }; - while repeat > 0 { - repeat -= 1; - code_lengths[usize::from(symbol)] = length; - symbol += 1; - } - } - } - } - - Ok(code_lengths) - } - - /// Decodes the image data using the huffman trees and either of the 3 methods of decoding - fn decode_image_data( - &mut self, - width: u16, - height: u16, - mut huffman_info: HuffmanInfo, - ) -> ImageResult> { - let num_values = usize::from(width) * usize::from(height); - let mut data = vec![0; num_values]; - - let huff_index = huffman_info.get_huff_index(0, 0); - let mut tree = &huffman_info.huffman_code_groups[huff_index]; - let mut last_cached = 0; - let mut index = 0; - let mut x = 0; - let mut y = 0; - while index < num_values { - if (x & huffman_info.mask) == 0 { - let index = huffman_info.get_huff_index(x, y); - tree = &huffman_info.huffman_code_groups[index]; - } - - let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; - - //check code - if code < 256 { - //literal, so just use huffman codes and read as argb - let red = tree[RED].read_symbol(&mut self.bit_reader)?; - let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; - let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; - - data[index] = (u32::from(alpha) << 24) - + (u32::from(red) << 16) - + (u32::from(code) << 8) - + u32::from(blue); - - index += 1; - x += 1; - if x >= width { - x = 0; - y += 1; - } - } else if code < 256 + 24 { - //backward reference, so go back and use that to add image data - let length_symbol = code - 256; - let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; - - let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; - let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; - let dist = Self::plane_code_to_distance(width, dist_code); - - if index < dist || num_values - index < length { - return Err(DecoderError::BitStreamError.into()); - } - - for i in 0..length { - data[index + i] = data[index + i - dist]; - } - index += length; - x += u16::try_from(length).unwrap(); - while x >= width { - x -= width; - y += 1; - } - if index < num_values { - let index = huffman_info.get_huff_index(x, y); - tree = &huffman_info.huffman_code_groups[index]; - } - } else { - //color cache, so use previously stored pixels to get this pixel - let key = code - 256 - 24; - - if let Some(color_cache) = huffman_info.color_cache.as_mut() { - //cache old colors - while last_cached < index { - color_cache.insert(data[last_cached]); - last_cached += 1; - } - data[index] = color_cache.lookup(key.into())?; - } else { - return Err(DecoderError::BitStreamError.into()); - } - index += 1; - x += 1; - if x >= width { - x = 0; - y += 1; - } - } - } - - Ok(data) - } - - /// Reads color cache data from the bitstream - fn read_color_cache(&mut self) -> ImageResult> { - if self.bit_reader.read_bits::(1)? == 1 { - let code_bits = self.bit_reader.read_bits::(4)?; - - if !(1..=11).contains(&code_bits) { - return Err(DecoderError::InvalidColorCacheBits(code_bits).into()); - } - - Ok(Some(code_bits)) - } else { - Ok(None) - } - } - - /// Gets the copy distance from the prefix code and bitstream - fn get_copy_distance(bit_reader: &mut BitReader, prefix_code: u16) -> ImageResult { - if prefix_code < 4 { - return Ok(usize::from(prefix_code + 1)); - } - let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); - let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; - - Ok(offset + bit_reader.read_bits::(extra_bits)? + 1) - } - - /// Gets distance to pixel - fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { - if plane_code > 120 { - plane_code - 120 - } else { - let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; - - let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); - if dist < 1 { - return 1; - } - dist.try_into().unwrap() - } - } -} - -#[derive(Debug, Clone)] -struct HuffmanInfo { - xsize: u16, - _ysize: u16, - color_cache: Option, - image: Vec, - bits: u8, - mask: u16, - huffman_code_groups: Vec, -} - -impl HuffmanInfo { - fn get_huff_index(&self, x: u16, y: u16) -> usize { - if self.bits == 0 { - return 0; - } - let position = usize::from((y >> self.bits) * self.xsize + (x >> self.bits)); - let meta_huff_code: usize = self.image[position].try_into().unwrap(); - meta_huff_code - } -} - -#[derive(Debug, Clone)] -struct ColorCache { - color_cache_bits: u8, - color_cache: Vec, -} - -impl ColorCache { - fn insert(&mut self, color: u32) { - let index = (0x1e35a7bdu32.overflowing_mul(color).0) >> (32 - self.color_cache_bits); - self.color_cache[index as usize] = color; - } - - fn lookup(&self, index: usize) -> ImageResult { - match self.color_cache.get(index) { - Some(&value) => Ok(value), - None => Err(DecoderError::BitStreamError.into()), - } - } -} - -#[derive(Debug, Clone)] -pub(crate) struct BitReader { - buf: Vec, - index: usize, - bit_count: u8, -} - -impl BitReader { - fn new() -> BitReader { - BitReader { - buf: Vec::new(), - index: 0, - bit_count: 0, - } - } - - fn init(&mut self, buf: Vec) { - self.buf = buf; - } - - pub(crate) fn read_bits(&mut self, num: u8) -> ImageResult - where - T: num_traits::Unsigned + Shl + AddAssign + From, - { - let mut value: T = T::zero(); - - for i in 0..num { - if self.buf.len() <= self.index { - return Err(DecoderError::BitStreamError.into()); - } - let bit_true = self.buf[self.index] & (1 << self.bit_count) != 0; - value += T::from(bit_true) << i; - self.bit_count = if self.bit_count == 7 { - self.index += 1; - 0 - } else { - self.bit_count + 1 - }; - } - - Ok(value) - } -} - -#[derive(Debug, Clone, Default)] -pub(crate) struct LosslessFrame { - pub(crate) width: u16, - pub(crate) height: u16, - - pub(crate) buf: Vec, -} - -impl LosslessFrame { - /// Fills a buffer by converting from argb to rgba - pub(crate) fn fill_rgba(&self, buf: &mut [u8]) { - for (&argb_val, chunk) in self.buf.iter().zip(buf.chunks_exact_mut(4)) { - chunk[0] = ((argb_val >> 16) & 0xff).try_into().unwrap(); - chunk[1] = ((argb_val >> 8) & 0xff).try_into().unwrap(); - chunk[2] = (argb_val & 0xff).try_into().unwrap(); - chunk[3] = ((argb_val >> 24) & 0xff).try_into().unwrap(); - } - } - - /// Get buffer size from the image - pub(crate) fn get_buf_size(&self) -> usize { - usize::from(self.width) * usize::from(self.height) * 4 - } - - /// Fills a buffer with just the green values from the lossless decoding - /// Used in extended alpha decoding - pub(crate) fn fill_green(&self, buf: &mut [u8]) { - for (&argb_val, buf_value) in self.buf.iter().zip(buf.iter_mut()) { - *buf_value = ((argb_val >> 8) & 0xff).try_into().unwrap(); - } - } -} - -#[cfg(test)] -mod test { - - use super::BitReader; - - #[test] - fn bit_read_test() { - let mut bit_reader = BitReader::new(); - - //10011100 01000001 11100001 - let buf = vec![0x9C, 0x41, 0xE1]; - - bit_reader.init(buf); - - assert_eq!(bit_reader.read_bits::(3).unwrap(), 4); //100 - assert_eq!(bit_reader.read_bits::(2).unwrap(), 3); //11 - assert_eq!(bit_reader.read_bits::(6).unwrap(), 12); //001100 - assert_eq!(bit_reader.read_bits::(10).unwrap(), 40); //0000101000 - assert_eq!(bit_reader.read_bits::(3).unwrap(), 7); //111 - } - - #[test] - fn bit_read_error_test() { - let mut bit_reader = BitReader::new(); - - //01101010 - let buf = vec![0x6A]; - - bit_reader.init(buf); - - assert_eq!(bit_reader.read_bits::(3).unwrap(), 2); //010 - assert_eq!(bit_reader.read_bits::(5).unwrap(), 13); //01101 - assert!(bit_reader.read_bits::(4).is_err()); //error - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/lossless_transform.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless_transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/lossless_transform.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/lossless_transform.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,461 +0,0 @@ -use super::lossless::subsample_size; -use super::lossless::DecoderError; - -#[derive(Debug, Clone)] -pub(crate) enum TransformType { - PredictorTransform { - size_bits: u8, - predictor_data: Vec, - }, - ColorTransform { - size_bits: u8, - transform_data: Vec, - }, - SubtractGreen, - ColorIndexingTransform { - table_size: u16, - table_data: Vec, - }, -} - -impl TransformType { - /// Applies a transform to the image data - pub(crate) fn apply_transform( - &self, - image_data: &mut Vec, - width: u16, - height: u16, - ) -> Result<(), DecoderError> { - match self { - TransformType::PredictorTransform { - size_bits, - predictor_data, - } => { - let block_xsize = usize::from(subsample_size(width, *size_bits)); - let width = usize::from(width); - let height = usize::from(height); - - if image_data.len() < width * height { - return Err(DecoderError::TransformError); - } - - //handle top and left borders specially - //this involves ignoring mode and just setting prediction values like this - image_data[0] = add_pixels(image_data[0], 0xff000000); - - for x in 1..width { - image_data[x] = add_pixels(image_data[x], get_left(image_data, x, 0, width)); - } - - for y in 1..height { - image_data[y * width] = - add_pixels(image_data[y * width], get_top(image_data, 0, y, width)); - } - - for y in 1..height { - for x in 1..width { - let block_index = (y >> size_bits) * block_xsize + (x >> size_bits); - - let index = y * width + x; - - let green = (predictor_data[block_index] >> 8) & 0xff; - - match green { - 0 => image_data[index] = add_pixels(image_data[index], 0xff000000), - 1 => { - image_data[index] = - add_pixels(image_data[index], get_left(image_data, x, y, width)) - } - 2 => { - image_data[index] = - add_pixels(image_data[index], get_top(image_data, x, y, width)) - } - 3 => { - image_data[index] = add_pixels( - image_data[index], - get_top_right(image_data, x, y, width), - ) - } - 4 => { - image_data[index] = add_pixels( - image_data[index], - get_top_left(image_data, x, y, width), - ) - } - 5 => { - image_data[index] = add_pixels(image_data[index], { - let first = average2( - get_left(image_data, x, y, width), - get_top_right(image_data, x, y, width), - ); - average2(first, get_top(image_data, x, y, width)) - }) - } - 6 => { - image_data[index] = add_pixels( - image_data[index], - average2( - get_left(image_data, x, y, width), - get_top_left(image_data, x, y, width), - ), - ) - } - 7 => { - image_data[index] = add_pixels( - image_data[index], - average2( - get_left(image_data, x, y, width), - get_top(image_data, x, y, width), - ), - ) - } - 8 => { - image_data[index] = add_pixels( - image_data[index], - average2( - get_top_left(image_data, x, y, width), - get_top(image_data, x, y, width), - ), - ) - } - 9 => { - image_data[index] = add_pixels( - image_data[index], - average2( - get_top(image_data, x, y, width), - get_top_right(image_data, x, y, width), - ), - ) - } - 10 => { - image_data[index] = add_pixels(image_data[index], { - let first = average2( - get_left(image_data, x, y, width), - get_top_left(image_data, x, y, width), - ); - let second = average2( - get_top(image_data, x, y, width), - get_top_right(image_data, x, y, width), - ); - average2(first, second) - }) - } - 11 => { - image_data[index] = add_pixels( - image_data[index], - select( - get_left(image_data, x, y, width), - get_top(image_data, x, y, width), - get_top_left(image_data, x, y, width), - ), - ) - } - 12 => { - image_data[index] = add_pixels( - image_data[index], - clamp_add_subtract_full( - get_left(image_data, x, y, width), - get_top(image_data, x, y, width), - get_top_left(image_data, x, y, width), - ), - ) - } - 13 => { - image_data[index] = add_pixels(image_data[index], { - let first = average2( - get_left(image_data, x, y, width), - get_top(image_data, x, y, width), - ); - clamp_add_subtract_half( - first, - get_top_left(image_data, x, y, width), - ) - }) - } - _ => {} - } - } - } - } - TransformType::ColorTransform { - size_bits, - transform_data, - } => { - let block_xsize = usize::from(subsample_size(width, *size_bits)); - let width = usize::from(width); - let height = usize::from(height); - - for y in 0..height { - for x in 0..width { - let block_index = (y >> size_bits) * block_xsize + (x >> size_bits); - - let index = y * width + x; - - let multiplier = - ColorTransformElement::from_color_code(transform_data[block_index]); - - image_data[index] = transform_color(&multiplier, image_data[index]); - } - } - } - TransformType::SubtractGreen => { - let width = usize::from(width); - for y in 0..usize::from(height) { - for x in 0..width { - image_data[y * width + x] = add_green(image_data[y * width + x]); - } - } - } - TransformType::ColorIndexingTransform { - table_size, - table_data, - } => { - let mut new_image_data = - Vec::with_capacity(usize::from(width) * usize::from(height)); - - let table_size = *table_size; - let width_bits: u8 = if table_size <= 2 { - 3 - } else if table_size <= 4 { - 2 - } else if table_size <= 16 { - 1 - } else { - 0 - }; - - let bits_per_pixel = 8 >> width_bits; - let mask = (1 << bits_per_pixel) - 1; - - let mut src = 0; - let width = usize::from(width); - - let pixels_per_byte = 1 << width_bits; - let count_mask = pixels_per_byte - 1; - let mut packed_pixels = 0; - - for _y in 0..usize::from(height) { - for x in 0..width { - if (x & count_mask) == 0 { - packed_pixels = (image_data[src] >> 8) & 0xff; - src += 1; - } - - let pixels: usize = (packed_pixels & mask).try_into().unwrap(); - let new_val = if pixels >= table_size.into() { - 0x00000000 - } else { - table_data[pixels] - }; - - new_image_data.push(new_val); - - packed_pixels >>= bits_per_pixel; - } - } - - *image_data = new_image_data; - } - } - - Ok(()) - } -} - -//predictor functions - -/// Adds 2 pixels mod 256 for each pixel -pub(crate) fn add_pixels(a: u32, b: u32) -> u32 { - let new_alpha = ((a >> 24) + (b >> 24)) & 0xff; - let new_red = (((a >> 16) & 0xff) + ((b >> 16) & 0xff)) & 0xff; - let new_green = (((a >> 8) & 0xff) + ((b >> 8) & 0xff)) & 0xff; - let new_blue = ((a & 0xff) + (b & 0xff)) & 0xff; - - (new_alpha << 24) + (new_red << 16) + (new_green << 8) + new_blue -} - -/// Get left pixel -fn get_left(data: &[u32], x: usize, y: usize, width: usize) -> u32 { - data[y * width + x - 1] -} - -/// Get top pixel -fn get_top(data: &[u32], x: usize, y: usize, width: usize) -> u32 { - data[(y - 1) * width + x] -} - -/// Get pixel to top right -fn get_top_right(data: &[u32], x: usize, y: usize, width: usize) -> u32 { - // if x == width - 1 this gets the left most pixel of the current row - // as described in the specification - data[(y - 1) * width + x + 1] -} - -/// Get pixel to top left -fn get_top_left(data: &[u32], x: usize, y: usize, width: usize) -> u32 { - data[(y - 1) * width + x - 1] -} - -/// Get average of 2 pixels -fn average2(a: u32, b: u32) -> u32 { - let mut avg = 0u32; - for i in 0..4 { - let sub_a: u8 = ((a >> (i * 8)) & 0xff).try_into().unwrap(); - let sub_b: u8 = ((b >> (i * 8)) & 0xff).try_into().unwrap(); - avg |= u32::from(sub_average2(sub_a, sub_b)) << (i * 8); - } - avg -} - -/// Get average of 2 bytes -fn sub_average2(a: u8, b: u8) -> u8 { - ((u16::from(a) + u16::from(b)) / 2).try_into().unwrap() -} - -/// Get a specific byte from argb pixel -fn get_byte(val: u32, byte: u8) -> u8 { - ((val >> (byte * 8)) & 0xff).try_into().unwrap() -} - -/// Get byte as i32 for convenience -fn get_byte_i32(val: u32, byte: u8) -> i32 { - i32::from(get_byte(val, byte)) -} - -/// Select left or top byte -fn select(left: u32, top: u32, top_left: u32) -> u32 { - let predict_alpha = get_byte_i32(left, 3) + get_byte_i32(top, 3) - get_byte_i32(top_left, 3); - let predict_red = get_byte_i32(left, 2) + get_byte_i32(top, 2) - get_byte_i32(top_left, 2); - let predict_green = get_byte_i32(left, 1) + get_byte_i32(top, 1) - get_byte_i32(top_left, 1); - let predict_blue = get_byte_i32(left, 0) + get_byte_i32(top, 0) - get_byte_i32(top_left, 0); - - let predict_left = i32::abs(predict_alpha - get_byte_i32(left, 3)) - + i32::abs(predict_red - get_byte_i32(left, 2)) - + i32::abs(predict_green - get_byte_i32(left, 1)) - + i32::abs(predict_blue - get_byte_i32(left, 0)); - let predict_top = i32::abs(predict_alpha - get_byte_i32(top, 3)) - + i32::abs(predict_red - get_byte_i32(top, 2)) - + i32::abs(predict_green - get_byte_i32(top, 1)) - + i32::abs(predict_blue - get_byte_i32(top, 0)); - - if predict_left < predict_top { - left - } else { - top - } -} - -/// Clamp a to [0, 255] -fn clamp(a: i32) -> i32 { - if a < 0 { - 0 - } else if a > 255 { - 255 - } else { - a - } -} - -/// Clamp add subtract full on one part -fn clamp_add_subtract_full_sub(a: i32, b: i32, c: i32) -> i32 { - clamp(a + b - c) -} - -/// Clamp add subtract half on one part -fn clamp_add_subtract_half_sub(a: i32, b: i32) -> i32 { - clamp(a + (a - b) / 2) -} - -/// Clamp add subtract full on 3 pixels -fn clamp_add_subtract_full(a: u32, b: u32, c: u32) -> u32 { - let mut value: u32 = 0; - for i in 0..4u8 { - let sub_a: i32 = ((a >> (i * 8)) & 0xff).try_into().unwrap(); - let sub_b: i32 = ((b >> (i * 8)) & 0xff).try_into().unwrap(); - let sub_c: i32 = ((c >> (i * 8)) & 0xff).try_into().unwrap(); - value |= - u32::try_from(clamp_add_subtract_full_sub(sub_a, sub_b, sub_c)).unwrap() << (i * 8); - } - value -} - -/// Clamp add subtract half on 2 pixels -fn clamp_add_subtract_half(a: u32, b: u32) -> u32 { - let mut value = 0; - for i in 0..4u8 { - let sub_a: i32 = ((a >> (i * 8)) & 0xff).try_into().unwrap(); - let sub_b: i32 = ((b >> (i * 8)) & 0xff).try_into().unwrap(); - value |= u32::try_from(clamp_add_subtract_half_sub(sub_a, sub_b)).unwrap() << (i * 8); - } - - value -} - -//color transform - -#[derive(Debug, Clone, Copy)] -struct ColorTransformElement { - green_to_red: u8, - green_to_blue: u8, - red_to_blue: u8, -} - -impl ColorTransformElement { - fn from_color_code(color_code: u32) -> ColorTransformElement { - ColorTransformElement { - green_to_red: (color_code & 0xff).try_into().unwrap(), - green_to_blue: ((color_code >> 8) & 0xff).try_into().unwrap(), - red_to_blue: ((color_code >> 16) & 0xff).try_into().unwrap(), - } - } -} - -/// Does color transform on red and blue transformed by green -fn color_transform(red: u8, blue: u8, green: u8, trans: &ColorTransformElement) -> (u8, u8) { - let mut temp_red = u32::from(red); - let mut temp_blue = u32::from(blue); - - //as does the conversion from u8 to signed two's complement i8 required - temp_red += color_transform_delta(trans.green_to_red as i8, green as i8); - temp_blue += color_transform_delta(trans.green_to_blue as i8, green as i8); - temp_blue += color_transform_delta(trans.red_to_blue as i8, temp_red as i8); - - ( - (temp_red & 0xff).try_into().unwrap(), - (temp_blue & 0xff).try_into().unwrap(), - ) -} - -/// Does color transform on 2 numbers -fn color_transform_delta(t: i8, c: i8) -> u32 { - ((i16::from(t) * i16::from(c)) as u32) >> 5 -} - -// Does color transform on a pixel with a color transform element -fn transform_color(multiplier: &ColorTransformElement, color_value: u32) -> u32 { - let alpha = get_byte(color_value, 3); - let red = get_byte(color_value, 2); - let green = get_byte(color_value, 1); - let blue = get_byte(color_value, 0); - - let (new_red, new_blue) = color_transform(red, blue, green, multiplier); - - (u32::from(alpha) << 24) - + (u32::from(new_red) << 16) - + (u32::from(green) << 8) - + u32::from(new_blue) -} - -//subtract green function - -/// Adds green to red and blue of a pixel -fn add_green(argb: u32) -> u32 { - let red = (argb >> 16) & 0xff; - let green = (argb >> 8) & 0xff; - let blue = argb & 0xff; - - let new_red = (red + green) & 0xff; - let new_blue = (blue + green) & 0xff; - - (argb & 0xff00ff00) | (new_red << 16) | (new_blue) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,28 +1,7 @@ //! Decoding and Encoding of WebP Images -#[cfg(feature = "webp")] -pub use self::encoder::{WebPEncoder, WebPQuality}; - -#[cfg(feature = "webp")] +mod decoder; mod encoder; -#[cfg(feature = "webp")] pub use self::decoder::WebPDecoder; - -#[cfg(feature = "webp")] -mod decoder; -#[cfg(feature = "webp")] -mod extended; -#[cfg(feature = "webp")] -mod huffman; -#[cfg(feature = "webp")] -mod loop_filter; -#[cfg(feature = "webp")] -mod lossless; -#[cfg(feature = "webp")] -mod lossless_transform; -#[cfg(feature = "webp")] -mod transform; - -#[cfg(feature = "webp")] -pub mod vp8; +pub use self::encoder::WebPEncoder; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/transform.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/transform.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/transform.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -static CONST1: i64 = 20091; -static CONST2: i64 = 35468; - -pub(crate) fn idct4x4(block: &mut [i32]) { - // The intermediate results may overflow the types, so we stretch the type. - fn fetch(block: &[i32], idx: usize) -> i64 { - i64::from(block[idx]) - } - - for i in 0usize..4 { - let a1 = fetch(block, i) + fetch(block, 8 + i); - let b1 = fetch(block, i) - fetch(block, 8 + i); - - let t1 = (fetch(block, 4 + i) * CONST2) >> 16; - let t2 = fetch(block, 12 + i) + ((fetch(block, 12 + i) * CONST1) >> 16); - let c1 = t1 - t2; - - let t1 = fetch(block, 4 + i) + ((fetch(block, 4 + i) * CONST1) >> 16); - let t2 = (fetch(block, 12 + i) * CONST2) >> 16; - let d1 = t1 + t2; - - block[i] = (a1 + d1) as i32; - block[4 + i] = (b1 + c1) as i32; - block[4 * 3 + i] = (a1 - d1) as i32; - block[4 * 2 + i] = (b1 - c1) as i32; - } - - for i in 0usize..4 { - let a1 = fetch(block, 4 * i) + fetch(block, 4 * i + 2); - let b1 = fetch(block, 4 * i) - fetch(block, 4 * i + 2); - - let t1 = (fetch(block, 4 * i + 1) * CONST2) >> 16; - let t2 = fetch(block, 4 * i + 3) + ((fetch(block, 4 * i + 3) * CONST1) >> 16); - let c1 = t1 - t2; - - let t1 = fetch(block, 4 * i + 1) + ((fetch(block, 4 * i + 1) * CONST1) >> 16); - let t2 = (fetch(block, 4 * i + 3) * CONST2) >> 16; - let d1 = t1 + t2; - - block[4 * i] = ((a1 + d1 + 4) >> 3) as i32; - block[4 * i + 3] = ((a1 - d1 + 4) >> 3) as i32; - block[4 * i + 1] = ((b1 + c1 + 4) >> 3) as i32; - block[4 * i + 2] = ((b1 - c1 + 4) >> 3) as i32; - } -} - -// 14.3 -pub(crate) fn iwht4x4(block: &mut [i32]) { - for i in 0usize..4 { - let a1 = block[i] + block[12 + i]; - let b1 = block[4 + i] + block[8 + i]; - let c1 = block[4 + i] - block[8 + i]; - let d1 = block[i] - block[12 + i]; - - block[i] = a1 + b1; - block[4 + i] = c1 + d1; - block[8 + i] = a1 - b1; - block[12 + i] = d1 - c1; - } - - for i in 0usize..4 { - let a1 = block[4 * i] + block[4 * i + 3]; - let b1 = block[4 * i + 1] + block[4 * i + 2]; - let c1 = block[4 * i + 1] - block[4 * i + 2]; - let d1 = block[4 * i] - block[4 * i + 3]; - - let a2 = a1 + b1; - let b2 = c1 + d1; - let c2 = a1 - b1; - let d2 = d1 - c1; - - block[4 * i] = (a2 + 3) >> 3; - block[4 * i + 1] = (b2 + 3) >> 3; - block[4 * i + 2] = (c2 + 3) >> 3; - block[4 * i + 3] = (d2 + 3) >> 3; - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/vp8.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/vp8.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/codecs/webp/vp8.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/codecs/webp/vp8.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2916 +0,0 @@ -//! An implementation of the VP8 Video Codec -//! -//! This module contains a partial implementation of the -//! VP8 video format as defined in RFC-6386. -//! -//! It decodes Keyframes only. -//! VP8 is the underpinning of the WebP image format -//! -//! # Related Links -//! * [rfc-6386](http://tools.ietf.org/html/rfc6386) - The VP8 Data Format and Decoding Guide -//! * [VP8.pdf](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37073.pdf) - An overview of -//! of the VP8 format -//! - -use byteorder::{LittleEndian, ReadBytesExt}; -use std::default::Default; -use std::io::Read; -use std::{cmp, error, fmt}; - -use super::loop_filter; -use super::transform; -use crate::error::{ - DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, -}; -use crate::image::ImageFormat; - -use crate::utils::clamp; - -const MAX_SEGMENTS: usize = 4; -const NUM_DCT_TOKENS: usize = 12; - -// Prediction modes -const DC_PRED: i8 = 0; -const V_PRED: i8 = 1; -const H_PRED: i8 = 2; -const TM_PRED: i8 = 3; -const B_PRED: i8 = 4; - -const B_DC_PRED: i8 = 0; -const B_TM_PRED: i8 = 1; -const B_VE_PRED: i8 = 2; -const B_HE_PRED: i8 = 3; -const B_LD_PRED: i8 = 4; -const B_RD_PRED: i8 = 5; -const B_VR_PRED: i8 = 6; -const B_VL_PRED: i8 = 7; -const B_HD_PRED: i8 = 8; -const B_HU_PRED: i8 = 9; - -// Prediction mode enum -#[repr(i8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -enum LumaMode { - /// Predict DC using row above and column to the left. - #[default] - DC = DC_PRED, - - /// Predict rows using row above. - V = V_PRED, - - /// Predict columns using column to the left. - H = H_PRED, - - /// Propagate second differences. - TM = TM_PRED, - - /// Each Y subblock is independently predicted. - B = B_PRED, -} - -#[repr(i8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -enum ChromaMode { - /// Predict DC using row above and column to the left. - #[default] - DC = DC_PRED, - - /// Predict rows using row above. - V = V_PRED, - - /// Predict columns using column to the left. - H = H_PRED, - - /// Propagate second differences. - TM = TM_PRED, -} - -#[repr(i8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -enum IntraMode { - #[default] - DC = B_DC_PRED, - TM = B_TM_PRED, - VE = B_VE_PRED, - HE = B_HE_PRED, - LD = B_LD_PRED, - RD = B_RD_PRED, - VR = B_VR_PRED, - VL = B_VL_PRED, - HD = B_HD_PRED, - HU = B_HU_PRED, -} - -type Prob = u8; - -static SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3]; - -// Section 11.2 -// Tree for determining the keyframe luma intra prediction modes: -static KEYFRAME_YMODE_TREE: [i8; 8] = [-B_PRED, 2, 4, 6, -DC_PRED, -V_PRED, -H_PRED, -TM_PRED]; - -// Default probabilities for decoding the keyframe luma modes -static KEYFRAME_YMODE_PROBS: [Prob; 4] = [145, 156, 163, 128]; - -// Tree for determining the keyframe B_PRED mode: -static KEYFRAME_BPRED_MODE_TREE: [i8; 18] = [ - -B_DC_PRED, 2, -B_TM_PRED, 4, -B_VE_PRED, 6, 8, 12, -B_HE_PRED, 10, -B_RD_PRED, -B_VR_PRED, - -B_LD_PRED, 14, -B_VL_PRED, 16, -B_HD_PRED, -B_HU_PRED, -]; - -// Probabilities for the BPRED_MODE_TREE -static KEYFRAME_BPRED_MODE_PROBS: [[[u8; 9]; 10]; 10] = [ - [ - [231, 120, 48, 89, 115, 113, 120, 152, 112], - [152, 179, 64, 126, 170, 118, 46, 70, 95], - [175, 69, 143, 80, 85, 82, 72, 155, 103], - [56, 58, 10, 171, 218, 189, 17, 13, 152], - [144, 71, 10, 38, 171, 213, 144, 34, 26], - [114, 26, 17, 163, 44, 195, 21, 10, 173], - [121, 24, 80, 195, 26, 62, 44, 64, 85], - [170, 46, 55, 19, 136, 160, 33, 206, 71], - [63, 20, 8, 114, 114, 208, 12, 9, 226], - [81, 40, 11, 96, 182, 84, 29, 16, 36], - ], - [ - [134, 183, 89, 137, 98, 101, 106, 165, 148], - [72, 187, 100, 130, 157, 111, 32, 75, 80], - [66, 102, 167, 99, 74, 62, 40, 234, 128], - [41, 53, 9, 178, 241, 141, 26, 8, 107], - [104, 79, 12, 27, 217, 255, 87, 17, 7], - [74, 43, 26, 146, 73, 166, 49, 23, 157], - [65, 38, 105, 160, 51, 52, 31, 115, 128], - [87, 68, 71, 44, 114, 51, 15, 186, 23], - [47, 41, 14, 110, 182, 183, 21, 17, 194], - [66, 45, 25, 102, 197, 189, 23, 18, 22], - ], - [ - [88, 88, 147, 150, 42, 46, 45, 196, 205], - [43, 97, 183, 117, 85, 38, 35, 179, 61], - [39, 53, 200, 87, 26, 21, 43, 232, 171], - [56, 34, 51, 104, 114, 102, 29, 93, 77], - [107, 54, 32, 26, 51, 1, 81, 43, 31], - [39, 28, 85, 171, 58, 165, 90, 98, 64], - [34, 22, 116, 206, 23, 34, 43, 166, 73], - [68, 25, 106, 22, 64, 171, 36, 225, 114], - [34, 19, 21, 102, 132, 188, 16, 76, 124], - [62, 18, 78, 95, 85, 57, 50, 48, 51], - ], - [ - [193, 101, 35, 159, 215, 111, 89, 46, 111], - [60, 148, 31, 172, 219, 228, 21, 18, 111], - [112, 113, 77, 85, 179, 255, 38, 120, 114], - [40, 42, 1, 196, 245, 209, 10, 25, 109], - [100, 80, 8, 43, 154, 1, 51, 26, 71], - [88, 43, 29, 140, 166, 213, 37, 43, 154], - [61, 63, 30, 155, 67, 45, 68, 1, 209], - [142, 78, 78, 16, 255, 128, 34, 197, 171], - [41, 40, 5, 102, 211, 183, 4, 1, 221], - [51, 50, 17, 168, 209, 192, 23, 25, 82], - ], - [ - [125, 98, 42, 88, 104, 85, 117, 175, 82], - [95, 84, 53, 89, 128, 100, 113, 101, 45], - [75, 79, 123, 47, 51, 128, 81, 171, 1], - [57, 17, 5, 71, 102, 57, 53, 41, 49], - [115, 21, 2, 10, 102, 255, 166, 23, 6], - [38, 33, 13, 121, 57, 73, 26, 1, 85], - [41, 10, 67, 138, 77, 110, 90, 47, 114], - [101, 29, 16, 10, 85, 128, 101, 196, 26], - [57, 18, 10, 102, 102, 213, 34, 20, 43], - [117, 20, 15, 36, 163, 128, 68, 1, 26], - ], - [ - [138, 31, 36, 171, 27, 166, 38, 44, 229], - [67, 87, 58, 169, 82, 115, 26, 59, 179], - [63, 59, 90, 180, 59, 166, 93, 73, 154], - [40, 40, 21, 116, 143, 209, 34, 39, 175], - [57, 46, 22, 24, 128, 1, 54, 17, 37], - [47, 15, 16, 183, 34, 223, 49, 45, 183], - [46, 17, 33, 183, 6, 98, 15, 32, 183], - [65, 32, 73, 115, 28, 128, 23, 128, 205], - [40, 3, 9, 115, 51, 192, 18, 6, 223], - [87, 37, 9, 115, 59, 77, 64, 21, 47], - ], - [ - [104, 55, 44, 218, 9, 54, 53, 130, 226], - [64, 90, 70, 205, 40, 41, 23, 26, 57], - [54, 57, 112, 184, 5, 41, 38, 166, 213], - [30, 34, 26, 133, 152, 116, 10, 32, 134], - [75, 32, 12, 51, 192, 255, 160, 43, 51], - [39, 19, 53, 221, 26, 114, 32, 73, 255], - [31, 9, 65, 234, 2, 15, 1, 118, 73], - [88, 31, 35, 67, 102, 85, 55, 186, 85], - [56, 21, 23, 111, 59, 205, 45, 37, 192], - [55, 38, 70, 124, 73, 102, 1, 34, 98], - ], - [ - [102, 61, 71, 37, 34, 53, 31, 243, 192], - [69, 60, 71, 38, 73, 119, 28, 222, 37], - [68, 45, 128, 34, 1, 47, 11, 245, 171], - [62, 17, 19, 70, 146, 85, 55, 62, 70], - [75, 15, 9, 9, 64, 255, 184, 119, 16], - [37, 43, 37, 154, 100, 163, 85, 160, 1], - [63, 9, 92, 136, 28, 64, 32, 201, 85], - [86, 6, 28, 5, 64, 255, 25, 248, 1], - [56, 8, 17, 132, 137, 255, 55, 116, 128], - [58, 15, 20, 82, 135, 57, 26, 121, 40], - ], - [ - [164, 50, 31, 137, 154, 133, 25, 35, 218], - [51, 103, 44, 131, 131, 123, 31, 6, 158], - [86, 40, 64, 135, 148, 224, 45, 183, 128], - [22, 26, 17, 131, 240, 154, 14, 1, 209], - [83, 12, 13, 54, 192, 255, 68, 47, 28], - [45, 16, 21, 91, 64, 222, 7, 1, 197], - [56, 21, 39, 155, 60, 138, 23, 102, 213], - [85, 26, 85, 85, 128, 128, 32, 146, 171], - [18, 11, 7, 63, 144, 171, 4, 4, 246], - [35, 27, 10, 146, 174, 171, 12, 26, 128], - ], - [ - [190, 80, 35, 99, 180, 80, 126, 54, 45], - [85, 126, 47, 87, 176, 51, 41, 20, 32], - [101, 75, 128, 139, 118, 146, 116, 128, 85], - [56, 41, 15, 176, 236, 85, 37, 9, 62], - [146, 36, 19, 30, 171, 255, 97, 27, 20], - [71, 30, 17, 119, 118, 255, 17, 18, 138], - [101, 38, 60, 138, 55, 70, 43, 26, 142], - [138, 45, 61, 62, 219, 1, 81, 188, 64], - [32, 41, 20, 117, 151, 142, 20, 21, 163], - [112, 19, 12, 61, 195, 128, 48, 4, 24], - ], -]; - -// Section 11.4 Tree for determining macroblock the chroma mode -static KEYFRAME_UV_MODE_TREE: [i8; 6] = [-DC_PRED, 2, -V_PRED, 4, -H_PRED, -TM_PRED]; - -// Probabilities for determining macroblock mode -static KEYFRAME_UV_MODE_PROBS: [Prob; 3] = [142, 114, 183]; - -// Section 13.4 -type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4]; - -// Probabilities that a token's probability will be updated -static COEFF_UPDATE_PROBS: TokenProbTables = [ - [ - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255], - [249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255], - [234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255], - [250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255], - [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - ], - [ - [ - [217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255], - [234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255], - ], - [ - [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - ], - [ - [ - [186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255], - [234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255], - [251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255], - ], - [ - [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - ], - [ - [ - [248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255], - [248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255], - [248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255], - [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - [ - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - ], - ], -]; - -// Section 13.5 -// Default Probabilities for tokens -static COEFF_PROBS: TokenProbTables = [ - [ - [ - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - ], - [ - [253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128], - [189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128], - [106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128], - ], - [ - [1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128], - [181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128], - [78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128], - ], - [ - [1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128], - [184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128], - [77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128], - ], - [ - [1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128], - [170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128], - [37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128], - ], - [ - [1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128], - [207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128], - [102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128], - ], - [ - [1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128], - [177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128], - [80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128], - ], - [ - [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - ], - ], - [ - [ - [198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62], - [131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1], - [68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128], - ], - [ - [1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128], - [184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128], - [81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128], - ], - [ - [1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128], - [99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128], - [23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128], - ], - [ - [1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128], - [109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128], - [44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128], - ], - [ - [1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128], - [94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128], - [22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128], - ], - [ - [1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128], - [124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128], - [35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128], - ], - [ - [1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128], - [121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128], - [45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128], - ], - [ - [1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128], - [203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128], - [137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128], - ], - ], - [ - [ - [253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128], - [175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128], - [73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128], - ], - [ - [1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128], - [239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128], - [155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128], - ], - [ - [1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128], - [201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128], - [69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128], - ], - [ - [1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128], - [223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128], - [141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128], - ], - [ - [1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128], - [190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128], - [149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - ], - [ - [1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128], - ], - [ - [1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128], - [213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128], - [55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128], - ], - [ - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], - ], - ], - [ - [ - [202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255], - [126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128], - [61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128], - ], - [ - [1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128], - [166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128], - [39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128], - ], - [ - [1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128], - [124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128], - [24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128], - ], - [ - [1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128], - [149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128], - [28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128], - ], - [ - [1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128], - [123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128], - [20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128], - ], - [ - [1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128], - [168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128], - [47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128], - ], - [ - [1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128], - [141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128], - [42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128], - ], - [ - [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - [238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], - ], - ], -]; - -// DCT Tokens -const DCT_0: i8 = 0; -const DCT_1: i8 = 1; -const DCT_2: i8 = 2; -const DCT_3: i8 = 3; -const DCT_4: i8 = 4; -const DCT_CAT1: i8 = 5; -const DCT_CAT2: i8 = 6; -const DCT_CAT3: i8 = 7; -const DCT_CAT4: i8 = 8; -const DCT_CAT5: i8 = 9; -const DCT_CAT6: i8 = 10; -const DCT_EOB: i8 = 11; - -static DCT_TOKEN_TREE: [i8; 22] = [ - -DCT_EOB, 2, -DCT_0, 4, -DCT_1, 6, 8, 12, -DCT_2, 10, -DCT_3, -DCT_4, 14, 16, -DCT_CAT1, - -DCT_CAT2, 18, 20, -DCT_CAT3, -DCT_CAT4, -DCT_CAT5, -DCT_CAT6, -]; - -static PROB_DCT_CAT: [[Prob; 12]; 6] = [ - [159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [165, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0], - [180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0], - [254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0], -]; - -static DCT_CAT_BASE: [u8; 6] = [5, 7, 11, 19, 35, 67]; -static COEFF_BANDS: [u8; 16] = [0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7]; - -#[rustfmt::skip] -static DC_QUANT: [i16; 128] = [ - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157, -]; - -#[rustfmt::skip] -static AC_QUANT: [i16; 128] = [ - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284, -]; - -static ZIGZAG: [u8; 16] = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15]; - -/// All errors that can occur when attempting to parse a VP8 codec inside WebP -#[derive(Debug, Clone, Copy)] -enum DecoderError { - /// VP8's `[0x9D, 0x01, 0x2A]` magic not found or invalid - Vp8MagicInvalid([u8; 3]), - - /// Decoder initialisation wasn't provided with enough data - NotEnoughInitData, - - /// At time of writing, only the YUV colour-space encoded as `0` is specified - ColorSpaceInvalid(u8), - /// LUMA prediction mode was not recognised - LumaPredictionModeInvalid(i8), - /// Intra-prediction mode was not recognised - IntraPredictionModeInvalid(i8), - /// Chroma prediction mode was not recognised - ChromaPredictionModeInvalid(i8), -} - -impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DecoderError::Vp8MagicInvalid(tag) => f.write_fmt(format_args!( - "Invalid VP8 magic: [{:#04X?}, {:#04X?}, {:#04X?}]", - tag[0], tag[1], tag[2] - )), - - DecoderError::NotEnoughInitData => { - f.write_str("Expected at least 2 bytes of VP8 decoder initialization data") - } - - DecoderError::ColorSpaceInvalid(cs) => { - f.write_fmt(format_args!("Invalid non-YUV VP8 color space {}", cs)) - } - DecoderError::LumaPredictionModeInvalid(pm) => { - f.write_fmt(format_args!("Invalid VP8 LUMA prediction mode {}", pm)) - } - DecoderError::IntraPredictionModeInvalid(i) => { - f.write_fmt(format_args!("Invalid VP8 intra-prediction mode {}", i)) - } - DecoderError::ChromaPredictionModeInvalid(c) => { - f.write_fmt(format_args!("Invalid VP8 chroma prediction mode {}", c)) - } - } - } -} - -impl From for ImageError { - fn from(e: DecoderError) -> ImageError { - ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e)) - } -} - -impl error::Error for DecoderError {} - -struct BoolReader { - buf: Vec, - index: usize, - - range: u32, - value: u32, - bit_count: u8, -} - -impl BoolReader { - pub(crate) fn new() -> BoolReader { - BoolReader { - buf: Vec::new(), - range: 0, - value: 0, - bit_count: 0, - index: 0, - } - } - - pub(crate) fn init(&mut self, buf: Vec) -> ImageResult<()> { - if buf.len() < 2 { - return Err(DecoderError::NotEnoughInitData.into()); - } - - self.buf = buf; - // Direct access safe, since length has just been validated. - self.value = (u32::from(self.buf[0]) << 8) | u32::from(self.buf[1]); - self.index = 2; - self.range = 255; - self.bit_count = 0; - - Ok(()) - } - - pub(crate) fn read_bool(&mut self, probability: u8) -> bool { - let split = 1 + (((self.range - 1) * u32::from(probability)) >> 8); - let bigsplit = split << 8; - - let retval = if self.value >= bigsplit { - self.range -= split; - self.value -= bigsplit; - true - } else { - self.range = split; - false - }; - - while self.range < 128 { - self.value <<= 1; - self.range <<= 1; - self.bit_count += 1; - - if self.bit_count == 8 { - self.bit_count = 0; - - // If no more bits are available, just don't do anything. - // This strategy is suggested in the reference implementation of RFC6386 (p.135) - if self.index < self.buf.len() { - self.value |= u32::from(self.buf[self.index]); - self.index += 1; - } - } - } - - retval - } - - pub(crate) fn read_literal(&mut self, n: u8) -> u8 { - let mut v = 0u8; - let mut n = n; - - while n != 0 { - v = (v << 1) + self.read_bool(128u8) as u8; - n -= 1; - } - - v - } - - pub(crate) fn read_magnitude_and_sign(&mut self, n: u8) -> i32 { - let magnitude = self.read_literal(n); - let sign = self.read_literal(1); - - if sign == 1 { - -i32::from(magnitude) - } else { - i32::from(magnitude) - } - } - - pub(crate) fn read_with_tree(&mut self, tree: &[i8], probs: &[Prob], start: isize) -> i8 { - let mut index = start; - - loop { - let a = self.read_bool(probs[index as usize >> 1]); - let b = index + a as isize; - index = tree[b as usize] as isize; - - if index <= 0 { - break; - } - } - - -index as i8 - } - - pub(crate) fn read_flag(&mut self) -> bool { - 0 != self.read_literal(1) - } -} - -#[derive(Default, Clone, Copy)] -struct MacroBlock { - bpred: [IntraMode; 16], - complexity: [u8; 9], - luma_mode: LumaMode, - chroma_mode: ChromaMode, - segmentid: u8, - coeffs_skipped: bool, -} - -/// A Representation of the last decoded video frame -#[derive(Default, Debug, Clone)] -pub struct Frame { - /// The width of the luma plane - pub width: u16, - - /// The height of the luma plane - pub height: u16, - - /// The luma plane of the frame - pub ybuf: Vec, - - /// The blue plane of the frame - pub ubuf: Vec, - - /// The red plane of the frame - pub vbuf: Vec, - - /// Indicates whether this frame is a keyframe - pub keyframe: bool, - - version: u8, - - /// Indicates whether this frame is intended for display - pub for_display: bool, - - // Section 9.2 - /// The pixel type of the frame as defined by Section 9.2 - /// of the VP8 Specification - pub pixel_type: u8, - - // Section 9.4 and 15 - filter_type: bool, //if true uses simple filter // if false uses normal filter - filter_level: u8, - sharpness_level: u8, -} - -impl Frame { - /// Chroma plane is half the size of the Luma plane - fn chroma_width(&self) -> u16 { - (self.width + 1) / 2 - } - - fn chroma_height(&self) -> u16 { - (self.height + 1) / 2 - } - - /// Fills an rgb buffer with the image - pub(crate) fn fill_rgb(&self, buf: &mut [u8]) { - for (index, rgb_chunk) in (0..self.ybuf.len()).zip(buf.chunks_exact_mut(3)) { - let y = index / self.width as usize; - let x = index % self.width as usize; - let chroma_index = self.chroma_width() as usize * (y / 2) + x / 2; - - Frame::fill_single( - self.ybuf[index], - self.ubuf[chroma_index], - self.vbuf[chroma_index], - rgb_chunk, - ); - } - } - - /// Fills an rgba buffer by skipping the alpha values - pub(crate) fn fill_rgba(&self, buf: &mut [u8]) { - for (index, rgba_chunk) in (0..self.ybuf.len()).zip(buf.chunks_exact_mut(4)) { - let y = index / self.width as usize; - let x = index % self.width as usize; - let chroma_index = self.chroma_width() as usize * (y / 2) + x / 2; - - Frame::fill_single( - self.ybuf[index], - self.ubuf[chroma_index], - self.vbuf[chroma_index], - rgba_chunk, - ); - } - } - - /// Conversion values from https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-8-bit-yuv-to-rgb888 - fn fill_single(y: u8, u: u8, v: u8, rgb: &mut [u8]) { - let c: i32 = i32::from(y) - 16; - let d: i32 = i32::from(u) - 128; - let e: i32 = i32::from(v) - 128; - - let r: u8 = clamp((298 * c + 409 * e + 128) >> 8, 0, 255) - .try_into() - .unwrap(); - let g: u8 = clamp((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255) - .try_into() - .unwrap(); - let b: u8 = clamp((298 * c + 516 * d + 128) >> 8, 0, 255) - .try_into() - .unwrap(); - - rgb[0] = r; - rgb[1] = g; - rgb[2] = b; - } - - /// Gets the buffer size - pub fn get_buf_size(&self) -> usize { - self.ybuf.len() * 3 - } -} - -#[derive(Clone, Copy, Default)] -struct Segment { - ydc: i16, - yac: i16, - - y2dc: i16, - y2ac: i16, - - uvdc: i16, - uvac: i16, - - delta_values: bool, - - quantizer_level: i8, - loopfilter_level: i8, -} - -/// VP8 Decoder -/// -/// Only decodes keyframes -pub struct Vp8Decoder { - r: R, - b: BoolReader, - - mbwidth: u16, - mbheight: u16, - macroblocks: Vec, - - frame: Frame, - - segments_enabled: bool, - segments_update_map: bool, - segment: [Segment; MAX_SEGMENTS], - - ref_delta: [i32; 4], - mode_delta: [i32; 4], - - partitions: [BoolReader; 8], - num_partitions: u8, - - segment_tree_probs: [Prob; 3], - token_probs: Box, - - // Section 9.10 - prob_intra: Prob, - - // Section 9.11 - prob_skip_false: Option, - - top: Vec, - left: MacroBlock, - - top_border: Vec, - left_border: Vec, -} - -impl Vp8Decoder { - /// Create a new decoder. - /// The reader must present a raw vp8 bitstream to the decoder - pub fn new(r: R) -> Vp8Decoder { - let f = Frame::default(); - let s = Segment::default(); - let m = MacroBlock::default(); - - Vp8Decoder { - r, - b: BoolReader::new(), - - mbwidth: 0, - mbheight: 0, - macroblocks: Vec::new(), - - frame: f, - segments_enabled: false, - segments_update_map: false, - segment: [s; MAX_SEGMENTS], - - ref_delta: [0; 4], - mode_delta: [0; 4], - - partitions: [ - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - BoolReader::new(), - ], - - num_partitions: 1, - - segment_tree_probs: [255u8; 3], - token_probs: Box::new(COEFF_PROBS), - - // Section 9.10 - prob_intra: 0u8, - - // Section 9.11 - prob_skip_false: None, - - top: Vec::new(), - left: m, - - top_border: Vec::new(), - left_border: Vec::new(), - } - } - - fn update_token_probabilities(&mut self) { - for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() { - for (j, js) in is.iter().enumerate() { - for (k, ks) in js.iter().enumerate() { - for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) { - if self.b.read_bool(*prob) { - let v = self.b.read_literal(8); - self.token_probs[i][j][k][t] = v; - } - } - } - } - } - } - - fn init_partitions(&mut self, n: usize) -> ImageResult<()> { - if n > 1 { - let mut sizes = vec![0; 3 * n - 3]; - self.r.read_exact(sizes.as_mut_slice())?; - - for (i, s) in sizes.chunks(3).enumerate() { - let size = { s } - .read_u24::() - .expect("Reading from &[u8] can't fail and the chunk is complete"); - - let mut buf = vec![0; size as usize]; - self.r.read_exact(buf.as_mut_slice())?; - - self.partitions[i].init(buf)?; - } - } - - let mut buf = Vec::new(); - self.r.read_to_end(&mut buf)?; - self.partitions[n - 1].init(buf)?; - - Ok(()) - } - - fn read_quantization_indices(&mut self) { - fn dc_quant(index: i32) -> i16 { - DC_QUANT[clamp(index, 0, 127) as usize] - } - - fn ac_quant(index: i32) -> i16 { - AC_QUANT[clamp(index, 0, 127) as usize] - } - - let yac_abs = self.b.read_literal(7); - let ydc_delta = if self.b.read_flag() { - self.b.read_magnitude_and_sign(4) - } else { - 0 - }; - - let y2dc_delta = if self.b.read_flag() { - self.b.read_magnitude_and_sign(4) - } else { - 0 - }; - - let y2ac_delta = if self.b.read_flag() { - self.b.read_magnitude_and_sign(4) - } else { - 0 - }; - - let uvdc_delta = if self.b.read_flag() { - self.b.read_magnitude_and_sign(4) - } else { - 0 - }; - - let uvac_delta = if self.b.read_flag() { - self.b.read_magnitude_and_sign(4) - } else { - 0 - }; - - let n = if self.segments_enabled { - MAX_SEGMENTS - } else { - 1 - }; - for i in 0usize..n { - let base = i32::from(if !self.segment[i].delta_values { - i16::from(self.segment[i].quantizer_level) - } else { - i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs) - }); - - self.segment[i].ydc = dc_quant(base + ydc_delta); - self.segment[i].yac = ac_quant(base); - - self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2; - // The intermediate result (max`284*155`) can be larger than the `i16` range. - self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16; - - self.segment[i].uvdc = dc_quant(base + uvdc_delta); - self.segment[i].uvac = ac_quant(base + uvac_delta); - - if self.segment[i].y2ac < 8 { - self.segment[i].y2ac = 8; - } - - if self.segment[i].uvdc > 132 { - self.segment[i].uvdc = 132; - } - } - } - - fn read_loop_filter_adjustments(&mut self) { - if self.b.read_flag() { - for i in 0usize..4 { - let ref_frame_delta_update_flag = self.b.read_flag(); - - self.ref_delta[i] = if ref_frame_delta_update_flag { - self.b.read_magnitude_and_sign(6) - } else { - 0i32 - }; - } - - for i in 0usize..4 { - let mb_mode_delta_update_flag = self.b.read_flag(); - - self.mode_delta[i] = if mb_mode_delta_update_flag { - self.b.read_magnitude_and_sign(6) - } else { - 0i32 - }; - } - } - } - - fn read_segment_updates(&mut self) { - // Section 9.3 - self.segments_update_map = self.b.read_flag(); - let update_segment_feature_data = self.b.read_flag(); - - if update_segment_feature_data { - let segment_feature_mode = self.b.read_flag(); - - for i in 0usize..MAX_SEGMENTS { - self.segment[i].delta_values = !segment_feature_mode; - } - - for i in 0usize..MAX_SEGMENTS { - let update = self.b.read_flag(); - - self.segment[i].quantizer_level = if update { - self.b.read_magnitude_and_sign(7) - } else { - 0i32 - } as i8; - } - - for i in 0usize..MAX_SEGMENTS { - let update = self.b.read_flag(); - - self.segment[i].loopfilter_level = if update { - self.b.read_magnitude_and_sign(6) - } else { - 0i32 - } as i8; - } - } - - if self.segments_update_map { - for i in 0usize..3 { - let update = self.b.read_flag(); - - self.segment_tree_probs[i] = if update { self.b.read_literal(8) } else { 255 }; - } - } - } - - fn read_frame_header(&mut self) -> ImageResult<()> { - let tag = self.r.read_u24::()?; - - self.frame.keyframe = tag & 1 == 0; - self.frame.version = ((tag >> 1) & 7) as u8; - self.frame.for_display = (tag >> 4) & 1 != 0; - - let first_partition_size = tag >> 5; - - if self.frame.keyframe { - let mut tag = [0u8; 3]; - self.r.read_exact(&mut tag)?; - - if tag != [0x9d, 0x01, 0x2a] { - return Err(DecoderError::Vp8MagicInvalid(tag).into()); - } - - let w = self.r.read_u16::()?; - let h = self.r.read_u16::()?; - - self.frame.width = w & 0x3FFF; - self.frame.height = h & 0x3FFF; - - self.top = init_top_macroblocks(self.frame.width as usize); - // Almost always the first macro block, except when non exists (i.e. `width == 0`) - self.left = self.top.first().cloned().unwrap_or_default(); - - self.mbwidth = (self.frame.width + 15) / 16; - self.mbheight = (self.frame.height + 15) / 16; - - self.frame.ybuf = vec![0u8; self.frame.width as usize * self.frame.height as usize]; - self.frame.ubuf = - vec![0u8; self.frame.chroma_width() as usize * self.frame.chroma_height() as usize]; - self.frame.vbuf = - vec![0u8; self.frame.chroma_width() as usize * self.frame.chroma_height() as usize]; - - self.top_border = vec![127u8; self.frame.width as usize + 4 + 16]; - self.left_border = vec![129u8; 1 + 16]; - } - - let mut buf = vec![0; first_partition_size as usize]; - self.r.read_exact(&mut buf)?; - - // initialise binary decoder - self.b.init(buf)?; - - if self.frame.keyframe { - let color_space = self.b.read_literal(1); - self.frame.pixel_type = self.b.read_literal(1); - - if color_space != 0 { - return Err(DecoderError::ColorSpaceInvalid(color_space).into()); - } - } - - self.segments_enabled = self.b.read_flag(); - if self.segments_enabled { - self.read_segment_updates(); - } - - self.frame.filter_type = self.b.read_flag(); - self.frame.filter_level = self.b.read_literal(6); - self.frame.sharpness_level = self.b.read_literal(3); - - let lf_adjust_enable = self.b.read_flag(); - if lf_adjust_enable { - self.read_loop_filter_adjustments(); - } - - self.num_partitions = (1usize << self.b.read_literal(2) as usize) as u8; - let num_partitions = self.num_partitions as usize; - self.init_partitions(num_partitions)?; - - self.read_quantization_indices(); - - if !self.frame.keyframe { - // 9.7 refresh golden frame and altref frame - // FIXME: support this? - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::WebP.into(), - UnsupportedErrorKind::GenericFeature("Non-keyframe frames".to_owned()), - ), - )); - } else { - // Refresh entropy probs ????? - let _ = self.b.read_literal(1); - } - - self.update_token_probabilities(); - - let mb_no_skip_coeff = self.b.read_literal(1); - self.prob_skip_false = if mb_no_skip_coeff == 1 { - Some(self.b.read_literal(8)) - } else { - None - }; - - if !self.frame.keyframe { - // 9.10 remaining frame data - self.prob_intra = 0; - - // FIXME: support this? - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::WebP.into(), - UnsupportedErrorKind::GenericFeature("Non-keyframe frames".to_owned()), - ), - )); - } else { - // Reset motion vectors - } - - Ok(()) - } - - fn read_macroblock_header(&mut self, mbx: usize) -> ImageResult { - let mut mb = MacroBlock::default(); - - if self.segments_enabled && self.segments_update_map { - mb.segmentid = self - .b - .read_with_tree(&SEGMENT_ID_TREE, &self.segment_tree_probs, 0) - as u8; - }; - - mb.coeffs_skipped = if self.prob_skip_false.is_some() { - self.b.read_bool(*self.prob_skip_false.as_ref().unwrap()) - } else { - false - }; - - let inter_predicted = if !self.frame.keyframe { - self.b.read_bool(self.prob_intra) - } else { - false - }; - - if inter_predicted { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::WebP.into(), - UnsupportedErrorKind::GenericFeature("VP8 inter-prediction".to_owned()), - ), - )); - } - - if self.frame.keyframe { - // intra prediction - let luma = self - .b - .read_with_tree(&KEYFRAME_YMODE_TREE, &KEYFRAME_YMODE_PROBS, 0); - mb.luma_mode = - LumaMode::from_i8(luma).ok_or(DecoderError::LumaPredictionModeInvalid(luma))?; - - match mb.luma_mode.into_intra() { - // `LumaMode::B` - This is predicted individually - None => { - for y in 0usize..4 { - for x in 0usize..4 { - let top = self.top[mbx].bpred[12 + x]; - let left = self.left.bpred[y]; - let intra = self.b.read_with_tree( - &KEYFRAME_BPRED_MODE_TREE, - &KEYFRAME_BPRED_MODE_PROBS[top as usize][left as usize], - 0, - ); - let bmode = IntraMode::from_i8(intra) - .ok_or(DecoderError::IntraPredictionModeInvalid(intra))?; - mb.bpred[x + y * 4] = bmode; - - self.top[mbx].bpred[12 + x] = bmode; - self.left.bpred[y] = bmode; - } - } - } - Some(mode) => { - for i in 0usize..4 { - mb.bpred[12 + i] = mode; - self.left.bpred[i] = mode; - } - } - } - - let chroma = self - .b - .read_with_tree(&KEYFRAME_UV_MODE_TREE, &KEYFRAME_UV_MODE_PROBS, 0); - mb.chroma_mode = ChromaMode::from_i8(chroma) - .ok_or(DecoderError::ChromaPredictionModeInvalid(chroma))?; - } - - self.top[mbx].chroma_mode = mb.chroma_mode; - self.top[mbx].luma_mode = mb.luma_mode; - self.top[mbx].bpred = mb.bpred; - - Ok(mb) - } - - fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { - let stride = 1usize + 16 + 4; - let w = self.frame.width as usize; - let mw = self.mbwidth as usize; - let mut ws = create_border_luma(mbx, mby, mw, &self.top_border, &self.left_border); - - match mb.luma_mode { - LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride), - LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride), - LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride), - LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0), - LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata), - } - - if mb.luma_mode != LumaMode::B { - for y in 0usize..4 { - for x in 0usize..4 { - let i = x + y * 4; - // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work). - let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); - let y0 = 1 + y * 4; - let x0 = 1 + x * 4; - - add_residue(&mut ws, rb, y0, x0, stride); - } - } - } - - self.left_border[0] = ws[16]; - - for i in 0usize..16 { - self.top_border[mbx * 16 + i] = ws[16 * stride + 1 + i]; - self.left_border[i + 1] = ws[(i + 1) * stride + 16]; - } - - // Length is the remainder to the border, but maximally the current chunk. - let ylength = cmp::min(self.frame.height as usize - mby * 16, 16); - let xlength = cmp::min(self.frame.width as usize - mbx * 16, 16); - - for y in 0usize..ylength { - for x in 0usize..xlength { - self.frame.ybuf[(mby * 16 + y) * w + mbx * 16 + x] = ws[(1 + y) * stride + 1 + x]; - } - } - } - - fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { - let stride = 1usize + 8; - - let w = self.frame.chroma_width() as usize; - - //8x8 with left top border of 1 - let mut uws = [0u8; (8 + 1) * (8 + 1)]; - let mut vws = [0u8; (8 + 1) * (8 + 1)]; - - let ylength = cmp::min(self.frame.chroma_height() as usize - mby * 8, 8); - let xlength = cmp::min(self.frame.chroma_width() as usize - mbx * 8, 8); - - //left border - for y in 0usize..8 { - let (uy, vy) = if mbx == 0 || y >= ylength { - (129, 129) - } else { - let index = (mby * 8 + y) * w + ((mbx - 1) * 8 + 7); - (self.frame.ubuf[index], self.frame.vbuf[index]) - }; - - uws[(y + 1) * stride] = uy; - vws[(y + 1) * stride] = vy; - } - //top border - for x in 0usize..8 { - let (ux, vx) = if mby == 0 || x >= xlength { - (127, 127) - } else { - let index = ((mby - 1) * 8 + 7) * w + (mbx * 8 + x); - (self.frame.ubuf[index], self.frame.vbuf[index]) - }; - - uws[x + 1] = ux; - vws[x + 1] = vx; - } - - //top left point - let (u1, v1) = if mby == 0 { - (127, 127) - } else if mbx == 0 { - (129, 129) - } else { - let index = ((mby - 1) * 8 + 7) * w + (mbx - 1) * 8 + 7; - if index >= self.frame.ubuf.len() { - (127, 127) - } else { - (self.frame.ubuf[index], self.frame.vbuf[index]) - } - }; - - uws[0] = u1; - vws[0] = v1; - - match mb.chroma_mode { - ChromaMode::DC => { - predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0); - predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0); - } - ChromaMode::V => { - predict_vpred(&mut uws, 8, 1, 1, stride); - predict_vpred(&mut vws, 8, 1, 1, stride); - } - ChromaMode::H => { - predict_hpred(&mut uws, 8, 1, 1, stride); - predict_hpred(&mut vws, 8, 1, 1, stride); - } - ChromaMode::TM => { - predict_tmpred(&mut uws, 8, 1, 1, stride); - predict_tmpred(&mut vws, 8, 1, 1, stride); - } - } - - for y in 0usize..2 { - for x in 0usize..2 { - let i = x + y * 2; - let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap(); - - let y0 = 1 + y * 4; - let x0 = 1 + x * 4; - add_residue(&mut uws, urb, y0, x0, stride); - - let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap(); - - add_residue(&mut vws, vrb, y0, x0, stride); - } - } - - for y in 0usize..ylength { - for x in 0usize..xlength { - self.frame.ubuf[(mby * 8 + y) * w + mbx * 8 + x] = uws[(1 + y) * stride + 1 + x]; - self.frame.vbuf[(mby * 8 + y) * w + mbx * 8 + x] = vws[(1 + y) * stride + 1 + x]; - } - } - } - - fn read_coefficients( - &mut self, - block: &mut [i32], - p: usize, - plane: usize, - complexity: usize, - dcq: i16, - acq: i16, - ) -> bool { - let first = if plane == 0 { 1usize } else { 0usize }; - let probs = &self.token_probs[plane]; - let tree = &DCT_TOKEN_TREE; - - let mut complexity = complexity; - let mut has_coefficients = false; - let mut skip = false; - - for i in first..16usize { - let table = &probs[COEFF_BANDS[i] as usize][complexity]; - - let token = if !skip { - self.partitions[p].read_with_tree(tree, table, 0) - } else { - self.partitions[p].read_with_tree(tree, table, 2) - }; - - let mut abs_value = i32::from(match token { - DCT_EOB => break, - - DCT_0 => { - skip = true; - has_coefficients = true; - complexity = 0; - continue; - } - - literal @ DCT_1..=DCT_4 => i16::from(literal), - - category @ DCT_CAT1..=DCT_CAT6 => { - let t = PROB_DCT_CAT[(category - DCT_CAT1) as usize]; - - let mut extra = 0i16; - let mut j = 0; - - while t[j] > 0 { - extra = extra + extra + self.partitions[p].read_bool(t[j]) as i16; - j += 1; - } - - i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra - } - - c => panic!("unknown token: {}", c), - }); - - skip = false; - - complexity = if abs_value == 0 { - 0 - } else if abs_value == 1 { - 1 - } else { - 2 - }; - - if self.partitions[p].read_bool(128) { - abs_value = -abs_value; - } - - block[ZIGZAG[i] as usize] = - abs_value * i32::from(if ZIGZAG[i] > 0 { acq } else { dcq }); - - has_coefficients = true; - } - - has_coefficients - } - - fn read_residual_data(&mut self, mb: &MacroBlock, mbx: usize, p: usize) -> [i32; 384] { - let sindex = mb.segmentid as usize; - let mut blocks = [0i32; 384]; - let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 }; - - if plane == 1 { - let complexity = self.top[mbx].complexity[0] + self.left.complexity[0]; - let mut block = [0i32; 16]; - let dcq = self.segment[sindex].y2dc; - let acq = self.segment[sindex].y2ac; - let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq); - - self.left.complexity[0] = if n { 1 } else { 0 }; - self.top[mbx].complexity[0] = if n { 1 } else { 0 }; - - transform::iwht4x4(&mut block); - - for k in 0usize..16 { - blocks[16 * k] = block[k]; - } - - plane = 0; - } - - for y in 0usize..4 { - let mut left = self.left.complexity[y + 1]; - for x in 0usize..4 { - let i = x + y * 4; - let block = &mut blocks[i * 16..i * 16 + 16]; - - let complexity = self.top[mbx].complexity[x + 1] + left; - let dcq = self.segment[sindex].ydc; - let acq = self.segment[sindex].yac; - - let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq); - - if block[0] != 0 || n { - transform::idct4x4(block); - } - - left = if n { 1 } else { 0 }; - self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 }; - } - - self.left.complexity[y + 1] = left; - } - - plane = 2; - - for &j in &[5usize, 7usize] { - for y in 0usize..2 { - let mut left = self.left.complexity[y + j]; - - for x in 0usize..2 { - let i = x + y * 2 + if j == 5 { 16 } else { 20 }; - let block = &mut blocks[i * 16..i * 16 + 16]; - - let complexity = self.top[mbx].complexity[x + j] + left; - let dcq = self.segment[sindex].uvdc; - let acq = self.segment[sindex].uvac; - - let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq); - if block[0] != 0 || n { - transform::idct4x4(block); - } - - left = if n { 1 } else { 0 }; - self.top[mbx].complexity[x + j] = if n { 1 } else { 0 }; - } - - self.left.complexity[y + j] = left; - } - } - - blocks - } - - /// Does loop filtering on the macroblock - fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) { - let luma_w = self.frame.width as usize; - let luma_h = self.frame.height as usize; - let chroma_w = self.frame.chroma_width() as usize; - let chroma_h = self.frame.chroma_height() as usize; - - let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb); - - if filter_level > 0 { - let mbedge_limit = (filter_level + 2) * 2 + interior_limit; - let sub_bedge_limit = (filter_level * 2) + interior_limit; - - let luma_ylength = cmp::min(luma_h - 16 * mby, 16); - let luma_xlength = cmp::min(luma_w - 16 * mbx, 16); - - let chroma_ylength = cmp::min(chroma_h - 8 * mby, 8); - let chroma_xlength = cmp::min(chroma_w - 8 * mbx, 8); - - //filter across left of macroblock - if mbx > 0 { - //simple loop filtering - if self.frame.filter_type { - if luma_xlength >= 2 { - for y in 0usize..luma_ylength { - let y0 = mby * 16 + y; - let x0 = mbx * 16; - - loop_filter::simple_segment( - mbedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - 1, - ); - } - } - } else { - if luma_xlength >= 4 { - for y in 0usize..luma_ylength { - let y0 = mby * 16 + y; - let x0 = mbx * 16; - - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - 1, - ); - } - } - - if chroma_xlength >= 4 { - for y in 0usize..chroma_ylength { - let y0 = mby * 8 + y; - let x0 = mbx * 8; - - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.ubuf[..], - y0 * chroma_w + x0, - 1, - ); - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.vbuf[..], - y0 * chroma_w + x0, - 1, - ); - } - } - } - } - - //filter across vertical subblocks in macroblock - if mb.luma_mode == LumaMode::B || !mb.coeffs_skipped { - if self.frame.filter_type { - for x in (4usize..luma_xlength - 1).step_by(4) { - for y in 0..luma_ylength { - let y0 = mby * 16 + y; - let x0 = mbx * 16 + x; - - loop_filter::simple_segment( - sub_bedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - 1, - ); - } - } - } else { - if luma_xlength > 3 { - for x in (4usize..luma_xlength - 3).step_by(4) { - for y in 0..luma_ylength { - let y0 = mby * 16 + y; - let x0 = mbx * 16 + x; - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - 1, - ); - } - } - } - - if chroma_xlength == 8 { - for y in 0usize..chroma_ylength { - let y0 = mby * 8 + y; - let x0 = mbx * 8 + 4; - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.ubuf[..], - y0 * chroma_w + x0, - 1, - ); - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.vbuf[..], - y0 * chroma_w + x0, - 1, - ); - } - } - } - } - - //filter across top of macroblock - if mby > 0 { - if self.frame.filter_type { - if luma_ylength >= 2 { - for x in 0usize..luma_xlength { - let y0 = mby * 16; - let x0 = mbx * 16 + x; - - loop_filter::simple_segment( - mbedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - luma_w, - ); - } - } - } else { - //if bottom macroblock, can only filter if there is 3 pixels below - if luma_ylength >= 4 { - for x in 0usize..luma_xlength { - let y0 = mby * 16; - let x0 = mbx * 16 + x; - - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - luma_w, - ); - } - } - - if chroma_ylength >= 4 { - for x in 0usize..chroma_xlength { - let y0 = mby * 8; - let x0 = mbx * 8 + x; - - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.ubuf[..], - y0 * chroma_w + x0, - chroma_w, - ); - loop_filter::macroblock_filter( - hev_threshold, - interior_limit, - mbedge_limit, - &mut self.frame.vbuf[..], - y0 * chroma_w + x0, - chroma_w, - ); - } - } - } - } - - //filter across horizontal subblock edges within the macroblock - if mb.luma_mode == LumaMode::B || !mb.coeffs_skipped { - if self.frame.filter_type { - for y in (4usize..luma_ylength - 1).step_by(4) { - for x in 0..luma_xlength { - let y0 = mby * 16 + y; - let x0 = mbx * 16 + x; - - loop_filter::simple_segment( - sub_bedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - luma_w, - ); - } - } - } else { - if luma_ylength > 3 { - for y in (4usize..luma_ylength - 3).step_by(4) { - for x in 0..luma_xlength { - let y0 = mby * 16 + y; - let x0 = mbx * 16 + x; - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.ybuf[..], - y0 * luma_w + x0, - luma_w, - ); - } - } - } - - if chroma_ylength == 8 { - for x in 0..chroma_xlength { - let y0 = mby * 8 + 4; - let x0 = mbx * 8 + x; - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.ubuf[..], - y0 * chroma_w + x0, - chroma_w, - ); - - loop_filter::subblock_filter( - hev_threshold, - interior_limit, - sub_bedge_limit, - &mut self.frame.vbuf[..], - y0 * chroma_w + x0, - chroma_w, - ); - } - } - } - } - } - } - - //return values are the filter level, interior limit and hev threshold - fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) { - let segment = self.segment[macroblock.segmentid as usize]; - let mut filter_level = self.frame.filter_level as i32; - - if self.segments_enabled { - if segment.delta_values { - filter_level += i32::from(segment.loopfilter_level); - } else { - filter_level = i32::from(segment.loopfilter_level); - } - } - - filter_level = clamp(filter_level, 0, 63); - - if macroblock.luma_mode == LumaMode::B { - filter_level += self.mode_delta[0]; - } - - let filter_level = clamp(filter_level, 0, 63) as u8; - - //interior limit - let mut interior_limit = filter_level; - - if self.frame.sharpness_level > 0 { - interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 }; - - if interior_limit > 9 - self.frame.sharpness_level { - interior_limit = 9 - self.frame.sharpness_level; - } - } - - if interior_limit == 0 { - interior_limit = 1; - } - - //high edge variance threshold - let mut hev_threshold = 0; - - #[allow(clippy::collapsible_else_if)] - if self.frame.keyframe { - if filter_level >= 40 { - hev_threshold = 2; - } else { - hev_threshold = 1; - } - } else { - if filter_level >= 40 { - hev_threshold = 3; - } else if filter_level >= 20 { - hev_threshold = 2; - } else if filter_level >= 15 { - hev_threshold = 1; - } - } - - (filter_level, interior_limit, hev_threshold) - } - - /// Decodes the current frame - pub fn decode_frame(&mut self) -> ImageResult<&Frame> { - self.read_frame_header()?; - - for mby in 0..self.mbheight as usize { - let p = mby % self.num_partitions as usize; - self.left = MacroBlock::default(); - - for mbx in 0..self.mbwidth as usize { - let mb = self.read_macroblock_header(mbx)?; - let blocks = if !mb.coeffs_skipped { - self.read_residual_data(&mb, mbx, p) - } else { - if mb.luma_mode != LumaMode::B { - self.left.complexity[0] = 0; - self.top[mbx].complexity[0] = 0; - } - - for i in 1usize..9 { - self.left.complexity[i] = 0; - self.top[mbx].complexity[i] = 0; - } - - [0i32; 384] - }; - - self.intra_predict_luma(mbx, mby, &mb, &blocks); - self.intra_predict_chroma(mbx, mby, &mb, &blocks); - - self.macroblocks.push(mb); - } - - self.left_border = vec![129u8; 1 + 16]; - } - - //do loop filtering - for mby in 0..self.mbheight as usize { - for mbx in 0..self.mbwidth as usize { - let mb = self.macroblocks[mby * self.mbwidth as usize + mbx]; - self.loop_filter(mbx, mby, &mb); - } - } - - Ok(&self.frame) - } -} - -impl LumaMode { - fn from_i8(val: i8) -> Option { - Some(match val { - DC_PRED => LumaMode::DC, - V_PRED => LumaMode::V, - H_PRED => LumaMode::H, - TM_PRED => LumaMode::TM, - B_PRED => LumaMode::B, - _ => return None, - }) - } - - fn into_intra(self) -> Option { - Some(match self { - LumaMode::DC => IntraMode::DC, - LumaMode::V => IntraMode::VE, - LumaMode::H => IntraMode::HE, - LumaMode::TM => IntraMode::TM, - LumaMode::B => return None, - }) - } -} - -impl ChromaMode { - fn from_i8(val: i8) -> Option { - Some(match val { - DC_PRED => ChromaMode::DC, - V_PRED => ChromaMode::V, - H_PRED => ChromaMode::H, - TM_PRED => ChromaMode::TM, - _ => return None, - }) - } -} - -impl IntraMode { - fn from_i8(val: i8) -> Option { - Some(match val { - B_DC_PRED => IntraMode::DC, - B_TM_PRED => IntraMode::TM, - B_VE_PRED => IntraMode::VE, - B_HE_PRED => IntraMode::HE, - B_LD_PRED => IntraMode::LD, - B_RD_PRED => IntraMode::RD, - B_VR_PRED => IntraMode::VR, - B_VL_PRED => IntraMode::VL, - B_HD_PRED => IntraMode::HD, - B_HU_PRED => IntraMode::HU, - _ => return None, - }) - } -} - -fn init_top_macroblocks(width: usize) -> Vec { - let mb_width = (width + 15) / 16; - - let mb = MacroBlock { - // Section 11.3 #3 - bpred: [IntraMode::DC; 16], - luma_mode: LumaMode::DC, - ..MacroBlock::default() - }; - - vec![mb; mb_width] -} - -fn create_border_luma(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] { - let stride = 1usize + 16 + 4; - let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)]; - - // A - { - let above = &mut ws[1..stride]; - if mby == 0 { - for above in above.iter_mut() { - *above = 127; - } - } else { - for i in 0usize..16 { - above[i] = top[mbx * 16 + i]; - } - - if mbx == mbw - 1 { - for above in above.iter_mut().skip(16) { - *above = top[mbx * 16 + 15]; - } - } else { - for i in 16usize..above.len() { - above[i] = top[mbx * 16 + i]; - } - } - } - } - - for i in 17usize..stride { - ws[4 * stride + i] = ws[i]; - ws[8 * stride + i] = ws[i]; - ws[12 * stride + i] = ws[i]; - } - - // L - if mbx == 0 { - for i in 0usize..16 { - ws[(i + 1) * stride] = 129; - } - } else { - for i in 0usize..16 { - ws[(i + 1) * stride] = left[i + 1]; - } - } - - // P - ws[0] = if mby == 0 { - 127 - } else if mbx == 0 { - 129 - } else { - left[0] - }; - - ws -} - -fn avg3(left: u8, this: u8, right: u8) -> u8 { - let avg = (u16::from(left) + 2 * u16::from(this) + u16::from(right) + 2) >> 2; - avg as u8 -} - -fn avg2(this: u8, right: u8) -> u8 { - let avg = (u16::from(this) + u16::from(right) + 1) >> 1; - avg as u8 -} - -// Only 16 elements from rblock are used to add residue, so it is restricted to 16 elements -// to enable SIMD and other optimizations. -fn add_residue(pblock: &mut [u8], rblock: &[i32; 16], y0: usize, x0: usize, stride: usize) { - let mut pos = y0 * stride + x0; - for row in rblock.chunks(4) { - for (p, &a) in pblock[pos..pos + 4].iter_mut().zip(row.iter()) { - *p = clamp(a + i32::from(*p), 0, 255) as u8; - } - pos += stride; - } -} - -fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) { - for sby in 0usize..4 { - for sbx in 0usize..4 { - let i = sbx + sby * 4; - let y0 = sby * 4 + 1; - let x0 = sbx * 4 + 1; - - match modes[i] { - IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride), - IntraMode::VE => predict_bvepred(ws, x0, y0, stride), - IntraMode::HE => predict_bhepred(ws, x0, y0, stride), - IntraMode::DC => predict_bdcpred(ws, x0, y0, stride), - IntraMode::LD => predict_bldpred(ws, x0, y0, stride), - IntraMode::RD => predict_brdpred(ws, x0, y0, stride), - IntraMode::VR => predict_bvrpred(ws, x0, y0, stride), - IntraMode::VL => predict_bvlpred(ws, x0, y0, stride), - IntraMode::HD => predict_bhdpred(ws, x0, y0, stride), - IntraMode::HU => predict_bhupred(ws, x0, y0, stride), - } - - let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); - add_residue(ws, rb, y0, x0, stride); - } - } -} - -fn predict_vpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { - for y in 0usize..size { - for x in 0usize..size { - a[(x + x0) + stride * (y + y0)] = a[(x + x0) + stride * (y0 + y - 1)]; - } - } -} - -fn predict_hpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { - for y in 0usize..size { - for x in 0usize..size { - a[(x + x0) + stride * (y + y0)] = a[(x + x0 - 1) + stride * (y0 + y)]; - } - } -} - -fn predict_dcpred(a: &mut [u8], size: usize, stride: usize, above: bool, left: bool) { - let mut sum = 0; - let mut shf = if size == 8 { 2 } else { 3 }; - - if left { - for y in 0usize..size { - sum += u32::from(a[(y + 1) * stride]); - } - - shf += 1; - } - - if above { - for x in 0usize..size { - sum += u32::from(a[x + 1]); - } - - shf += 1; - } - - let dcval = if !left && !above { - 128 - } else { - (sum + (1 << (shf - 1))) >> shf - }; - - for y in 0usize..size { - for x in 0usize..size { - a[(x + 1) + stride * (y + 1)] = dcval as u8; - } - } -} - -fn predict_tmpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { - for y in 0usize..size { - for x in 0usize..size { - let pred = i32::from(a[(y0 + y) * stride + x0 - 1]) - + i32::from(a[(y0 - 1) * stride + x0 + x]) - - i32::from(a[(y0 - 1) * stride + x0 - 1]); - - a[(x + x0) + stride * (y + y0)] = clamp(pred, 0, 255) as u8; - } - } -} - -fn predict_bdcpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let mut v = 4; - for i in 0usize..4 { - v += u32::from(a[(y0 + i) * stride + x0 - 1]) + u32::from(a[(y0 - 1) * stride + x0 + i]); - } - - v >>= 3; - for y in 0usize..4 { - for x in 0usize..4 { - a[x + x0 + stride * (y + y0)] = v as u8; - } - } -} - -fn topleft_pixel(a: &[u8], x0: usize, y0: usize, stride: usize) -> u8 { - a[(y0 - 1) * stride + x0 - 1] -} - -fn top_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8, u8, u8, u8, u8) { - let pos = (y0 - 1) * stride + x0; - let a_slice = &a[pos..pos + 8]; - let a0 = a_slice[0]; - let a1 = a_slice[1]; - let a2 = a_slice[2]; - let a3 = a_slice[3]; - let a4 = a_slice[4]; - let a5 = a_slice[5]; - let a6 = a_slice[6]; - let a7 = a_slice[7]; - - (a0, a1, a2, a3, a4, a5, a6, a7) -} - -fn left_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8) { - let l0 = a[y0 * stride + x0 - 1]; - let l1 = a[(y0 + 1) * stride + x0 - 1]; - let l2 = a[(y0 + 2) * stride + x0 - 1]; - let l3 = a[(y0 + 3) * stride + x0 - 1]; - - (l0, l1, l2, l3) -} - -fn edge_pixels( - a: &[u8], - x0: usize, - y0: usize, - stride: usize, -) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8) { - let pos = (y0 - 1) * stride + x0 - 1; - let a_slice = &a[pos..=pos + 4]; - let e0 = a[pos + 4 * stride]; - let e1 = a[pos + 3 * stride]; - let e2 = a[pos + 2 * stride]; - let e3 = a[pos + stride]; - let e4 = a_slice[0]; - let e5 = a_slice[1]; - let e6 = a_slice[2]; - let e7 = a_slice[3]; - let e8 = a_slice[4]; - - (e0, e1, e2, e3, e4, e5, e6, e7, e8) -} - -fn predict_bvepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let p = topleft_pixel(a, x0, y0, stride); - let (a0, a1, a2, a3, a4, _, _, _) = top_pixels(a, x0, y0, stride); - let avg_1 = avg3(p, a0, a1); - let avg_2 = avg3(a0, a1, a2); - let avg_3 = avg3(a1, a2, a3); - let avg_4 = avg3(a2, a3, a4); - - let avg = [avg_1, avg_2, avg_3, avg_4]; - - let mut pos = y0 * stride + x0; - for _ in 0..4 { - a[pos..=pos + 3].copy_from_slice(&avg); - pos += stride; - } -} - -fn predict_bhepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let p = topleft_pixel(a, x0, y0, stride); - let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); - - let avgs = [ - avg3(p, l0, l1), - avg3(l0, l1, l2), - avg3(l1, l2, l3), - avg3(l2, l3, l3), - ]; - - let mut pos = y0 * stride + x0; - for &avg in avgs.iter() { - for a_p in a[pos..=pos + 3].iter_mut() { - *a_p = avg; - } - pos += stride; - } -} - -fn predict_bldpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); - - let avgs = [ - avg3(a0, a1, a2), - avg3(a1, a2, a3), - avg3(a2, a3, a4), - avg3(a3, a4, a5), - avg3(a4, a5, a6), - avg3(a5, a6, a7), - avg3(a6, a7, a7), - ]; - - let mut pos = y0 * stride + x0; - - for i in 0..4 { - a[pos..=pos + 3].copy_from_slice(&avgs[i..=i + 3]); - pos += stride; - } -} - -fn predict_brdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); - - let avgs = [ - avg3(e0, e1, e2), - avg3(e1, e2, e3), - avg3(e2, e3, e4), - avg3(e3, e4, e5), - avg3(e4, e5, e6), - avg3(e5, e6, e7), - avg3(e6, e7, e8), - ]; - let mut pos = y0 * stride + x0; - - for i in 0..4 { - a[pos..=pos + 3].copy_from_slice(&avgs[3 - i..7 - i]); - pos += stride; - } -} - -fn predict_bvrpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (_, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); - - a[(y0 + 3) * stride + x0] = avg3(e1, e2, e3); - a[(y0 + 2) * stride + x0] = avg3(e2, e3, e4); - a[(y0 + 3) * stride + x0 + 1] = avg3(e3, e4, e5); - a[(y0 + 1) * stride + x0] = avg3(e3, e4, e5); - a[(y0 + 2) * stride + x0 + 1] = avg2(e4, e5); - a[y0 * stride + x0] = avg2(e4, e5); - a[(y0 + 3) * stride + x0 + 2] = avg3(e4, e5, e6); - a[(y0 + 1) * stride + x0 + 1] = avg3(e4, e5, e6); - a[(y0 + 2) * stride + x0 + 2] = avg2(e5, e6); - a[y0 * stride + x0 + 1] = avg2(e5, e6); - a[(y0 + 3) * stride + x0 + 3] = avg3(e5, e6, e7); - a[(y0 + 1) * stride + x0 + 2] = avg3(e5, e6, e7); - a[(y0 + 2) * stride + x0 + 3] = avg2(e6, e7); - a[y0 * stride + x0 + 2] = avg2(e6, e7); - a[(y0 + 1) * stride + x0 + 3] = avg3(e6, e7, e8); - a[y0 * stride + x0 + 3] = avg2(e7, e8); -} - -fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); - - a[y0 * stride + x0] = avg2(a0, a1); - a[(y0 + 1) * stride + x0] = avg3(a0, a1, a2); - a[(y0 + 2) * stride + x0] = avg2(a1, a2); - a[y0 * stride + x0 + 1] = avg2(a1, a2); - a[(y0 + 1) * stride + x0 + 1] = avg3(a1, a2, a3); - a[(y0 + 3) * stride + x0] = avg3(a1, a2, a3); - a[(y0 + 2) * stride + x0 + 1] = avg2(a2, a3); - a[y0 * stride + x0 + 2] = avg2(a2, a3); - a[(y0 + 3) * stride + x0 + 1] = avg3(a2, a3, a4); - a[(y0 + 1) * stride + x0 + 2] = avg3(a2, a3, a4); - a[(y0 + 2) * stride + x0 + 2] = avg2(a3, a4); - a[y0 * stride + x0 + 3] = avg2(a3, a4); - a[(y0 + 3) * stride + x0 + 2] = avg3(a3, a4, a5); - a[(y0 + 1) * stride + x0 + 3] = avg3(a3, a4, a5); - a[(y0 + 2) * stride + x0 + 3] = avg3(a4, a5, a6); - a[(y0 + 3) * stride + x0 + 3] = avg3(a5, a6, a7); -} - -fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (e0, e1, e2, e3, e4, e5, e6, e7, _) = edge_pixels(a, x0, y0, stride); - - a[(y0 + 3) * stride + x0] = avg2(e0, e1); - a[(y0 + 3) * stride + x0 + 1] = avg3(e0, e1, e2); - a[(y0 + 2) * stride + x0] = avg2(e1, e2); - a[(y0 + 3) * stride + x0 + 2] = avg2(e1, e2); - a[(y0 + 2) * stride + x0 + 1] = avg3(e1, e2, e3); - a[(y0 + 3) * stride + x0 + 3] = avg3(e1, e2, e3); - a[(y0 + 2) * stride + x0 + 2] = avg2(e2, e3); - a[(y0 + 1) * stride + x0] = avg2(e2, e3); - a[(y0 + 2) * stride + x0 + 3] = avg3(e2, e3, e4); - a[(y0 + 1) * stride + x0 + 1] = avg3(e2, e3, e4); - a[(y0 + 1) * stride + x0 + 2] = avg2(e3, e4); - a[y0 * stride + x0] = avg2(e3, e4); - a[(y0 + 1) * stride + x0 + 3] = avg3(e3, e4, e5); - a[y0 * stride + x0 + 1] = avg3(e3, e4, e5); - a[y0 * stride + x0 + 2] = avg3(e4, e5, e6); - a[y0 * stride + x0 + 3] = avg3(e5, e6, e7); -} - -fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { - let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); - - a[y0 * stride + x0] = avg2(l0, l1); - a[y0 * stride + x0 + 1] = avg3(l0, l1, l2); - a[y0 * stride + x0 + 2] = avg2(l1, l2); - a[(y0 + 1) * stride + x0] = avg2(l1, l2); - a[y0 * stride + x0 + 3] = avg3(l1, l2, l3); - a[(y0 + 1) * stride + x0 + 1] = avg3(l1, l2, l3); - a[(y0 + 1) * stride + x0 + 2] = avg2(l2, l3); - a[(y0 + 2) * stride + x0] = avg2(l2, l3); - a[(y0 + 1) * stride + x0 + 3] = avg3(l2, l3, l3); - a[(y0 + 2) * stride + x0 + 1] = avg3(l2, l3, l3); - a[(y0 + 2) * stride + x0 + 2] = l3; - a[(y0 + 2) * stride + x0 + 3] = l3; - a[(y0 + 3) * stride + x0] = l3; - a[(y0 + 3) * stride + x0 + 1] = l3; - a[(y0 + 3) * stride + x0 + 2] = l3; - a[(y0 + 3) * stride + x0 + 3] = l3; -} - -#[cfg(test)] -mod test { - - #[cfg(feature = "benchmarks")] - extern crate test; - use super::{ - add_residue, avg2, avg3, edge_pixels, predict_bhepred, predict_bldpred, predict_brdpred, - predict_bvepred, top_pixels, - }; - #[cfg(feature = "benchmarks")] - use super::{predict_4x4, IntraMode}; - #[cfg(feature = "benchmarks")] - use test::{black_box, Bencher}; - - #[cfg(feature = "benchmarks")] - const W: usize = 256; - #[cfg(feature = "benchmarks")] - const H: usize = 256; - - #[cfg(feature = "benchmarks")] - fn make_sample_image() -> Vec { - let mut v = Vec::with_capacity(W * H * 4); - for c in 0u8..=255 { - for k in 0u8..=255 { - v.push(c); - v.push(0); - v.push(0); - v.push(k); - } - } - v - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_predict_4x4(b: &mut Bencher) { - let mut v = black_box(make_sample_image()); - - let res_data = vec![1i32; W * H * 4]; - let modes = [ - IntraMode::TM, - IntraMode::VE, - IntraMode::HE, - IntraMode::DC, - IntraMode::LD, - IntraMode::RD, - IntraMode::VR, - IntraMode::VL, - IntraMode::HD, - IntraMode::HU, - IntraMode::TM, - IntraMode::VE, - IntraMode::HE, - IntraMode::DC, - IntraMode::LD, - IntraMode::RD, - ]; - - b.iter(|| { - predict_4x4(&mut v, W * 2, &modes, &res_data); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_predict_bvepred(b: &mut Bencher) { - let mut v = make_sample_image(); - - b.iter(|| { - predict_bvepred(black_box(&mut v), 5, 5, W * 2); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_predict_bldpred(b: &mut Bencher) { - let mut v = black_box(make_sample_image()); - - b.iter(|| { - predict_bldpred(black_box(&mut v), 5, 5, W * 2); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_predict_brdpred(b: &mut Bencher) { - let mut v = black_box(make_sample_image()); - - b.iter(|| { - predict_brdpred(black_box(&mut v), 5, 5, W * 2); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_predict_bhepred(b: &mut Bencher) { - let mut v = black_box(make_sample_image()); - - b.iter(|| { - predict_bhepred(black_box(&mut v), 5, 5, W * 2); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_top_pixels(b: &mut Bencher) { - let v = black_box(make_sample_image()); - - b.iter(|| { - black_box(top_pixels(black_box(&v), 5, 5, W * 2)); - }); - } - - #[cfg(feature = "benchmarks")] - #[bench] - fn bench_edge_pixels(b: &mut Bencher) { - let v = black_box(make_sample_image()); - - b.iter(|| { - black_box(edge_pixels(black_box(&v), 5, 5, W * 2)); - }); - } - - #[test] - fn test_avg2() { - for i in 0u8..=255 { - for j in 0u8..=255 { - let ceil_avg = ((i as f32) + (j as f32)) / 2.0; - let ceil_avg = ceil_avg.ceil() as u8; - assert_eq!( - ceil_avg, - avg2(i, j), - "avg2({}, {}), expected {}, got {}.", - i, - j, - ceil_avg, - avg2(i, j) - ); - } - } - } - - #[test] - fn test_avg2_specific() { - assert_eq!( - 255, - avg2(255, 255), - "avg2(255, 255), expected 255, got {}.", - avg2(255, 255) - ); - assert_eq!(1, avg2(1, 1), "avg2(1, 1), expected 1, got {}.", avg2(1, 1)); - assert_eq!(2, avg2(2, 1), "avg2(2, 1), expected 2, got {}.", avg2(2, 1)); - } - - #[test] - fn test_avg3() { - for i in 0u8..=255 { - for j in 0u8..=255 { - for k in 0u8..=255 { - let floor_avg = ((i as f32) + 2.0 * (j as f32) + { k as f32 } + 2.0) / 4.0; - let floor_avg = floor_avg.floor() as u8; - assert_eq!( - floor_avg, - avg3(i, j, k), - "avg3({}, {}, {}), expected {}, got {}.", - i, - j, - k, - floor_avg, - avg3(i, j, k) - ); - } - } - } - } - - #[test] - fn test_edge_pixels() { - #[rustfmt::skip] - let im = vec![5, 6, 7, 8, 9, - 4, 0, 0, 0, 0, - 3, 0, 0, 0, 0, - 2, 0, 0, 0, 0, - 1, 0, 0, 0, 0]; - let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(&im, 1, 1, 5); - assert_eq!(e0, 1); - assert_eq!(e1, 2); - assert_eq!(e2, 3); - assert_eq!(e3, 4); - assert_eq!(e4, 5); - assert_eq!(e5, 6); - assert_eq!(e6, 7); - assert_eq!(e7, 8); - assert_eq!(e8, 9); - } - - #[test] - fn test_top_pixels() { - #[rustfmt::skip] - let im = vec![1, 2, 3, 4, 5, 6, 7, 8, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0]; - let (e0, e1, e2, e3, e4, e5, e6, e7) = top_pixels(&im, 0, 1, 8); - assert_eq!(e0, 1); - assert_eq!(e1, 2); - assert_eq!(e2, 3); - assert_eq!(e3, 4); - assert_eq!(e4, 5); - assert_eq!(e5, 6); - assert_eq!(e6, 7); - assert_eq!(e7, 8); - } - - #[test] - fn test_add_residue() { - let mut pblock = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let rblock = [ - -1, -2, -3, -4, 250, 249, 248, 250, -10, -18, -192, -17, -3, 15, 18, 9, - ]; - let expected: [u8; 16] = [0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 10, 29, 33, 25]; - - add_residue(&mut pblock, &rblock, 0, 0, 4); - - for (&e, &i) in expected.iter().zip(&pblock) { - assert_eq!(e, i); - } - } - - #[test] - fn test_predict_bhepred() { - #[rustfmt::skip] - let expected: Vec = vec![5, 0, 0, 0, 0, - 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1]; - - #[rustfmt::skip] - let mut im = vec![5, 0, 0, 0, 0, - 4, 0, 0, 0, 0, - 3, 0, 0, 0, 0, - 2, 0, 0, 0, 0, - 1, 0, 0, 0, 0]; - predict_bhepred(&mut im, 1, 1, 5); - for (&e, i) in expected.iter().zip(im) { - assert_eq!(e, i); - } - } - - #[test] - fn test_predict_brdpred() { - #[rustfmt::skip] - let expected: Vec = vec![5, 6, 7, 8, 9, - 4, 5, 6, 7, 8, - 3, 4, 5, 6, 7, - 2, 3, 4, 5, 6, - 1, 2, 3, 4, 5]; - - #[rustfmt::skip] - let mut im = vec![5, 6, 7, 8, 9, - 4, 0, 0, 0, 0, - 3, 0, 0, 0, 0, - 2, 0, 0, 0, 0, - 1, 0, 0, 0, 0]; - predict_brdpred(&mut im, 1, 1, 5); - for (&e, i) in expected.iter().zip(im) { - assert_eq!(e, i); - } - } - - #[test] - fn test_predict_bldpred() { - #[rustfmt::skip] - let mut im: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0]; - let avg_1 = 2u8; - let avg_2 = 3u8; - let avg_3 = 4u8; - let avg_4 = 5u8; - let avg_5 = 6u8; - let avg_6 = 7u8; - let avg_7 = 8u8; - - predict_bldpred(&mut im, 0, 1, 8); - - assert_eq!(im[8], avg_1); - assert_eq!(im[9], avg_2); - assert_eq!(im[10], avg_3); - assert_eq!(im[11], avg_4); - assert_eq!(im[16], avg_2); - assert_eq!(im[17], avg_3); - assert_eq!(im[18], avg_4); - assert_eq!(im[19], avg_5); - assert_eq!(im[24], avg_3); - assert_eq!(im[25], avg_4); - assert_eq!(im[26], avg_5); - assert_eq!(im[27], avg_6); - assert_eq!(im[32], avg_4); - assert_eq!(im[33], avg_5); - assert_eq!(im[34], avg_6); - assert_eq!(im[35], avg_7); - } - - #[test] - fn test_predict_bvepred() { - #[rustfmt::skip] - let mut im: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0]; - let avg_1 = 2u8; - let avg_2 = 3u8; - let avg_3 = 4u8; - let avg_4 = 5u8; - - predict_bvepred(&mut im, 1, 1, 9); - - assert_eq!(im[10], avg_1); - assert_eq!(im[11], avg_2); - assert_eq!(im[12], avg_3); - assert_eq!(im[13], avg_4); - assert_eq!(im[19], avg_1); - assert_eq!(im[20], avg_2); - assert_eq!(im[21], avg_3); - assert_eq!(im[22], avg_4); - assert_eq!(im[28], avg_1); - assert_eq!(im[29], avg_2); - assert_eq!(im[30], avg_3); - assert_eq!(im[31], avg_4); - assert_eq!(im[37], avg_1); - assert_eq!(im[38], avg_2); - assert_eq!(im[39], avg_3); - assert_eq!(im[40], avg_4); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/color.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/color.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/color.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/color.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,10 +2,14 @@ use num_traits::{NumCast, ToPrimitive, Zero}; -use crate::traits::{Enlargeable, Pixel, Primitive}; +use crate::{ + error::TryFromExtendedColorError, + traits::{Enlargeable, Pixel, Primitive}, +}; /// An enumeration over supported color types and bit depths #[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[non_exhaustive] pub enum ColorType { /// Pixel is 8-bit luminance @@ -34,6 +38,7 @@ impl ColorType { /// Returns the number of bytes contained in a pixel of `ColorType` ```c``` + #[must_use] pub fn bytes_per_pixel(self) -> u8 { match self { ColorType::L8 => 1, @@ -48,6 +53,7 @@ } /// Returns if there is an alpha channel. + #[must_use] pub fn has_alpha(self) -> bool { use ColorType::*; match self { @@ -57,6 +63,7 @@ } /// Returns false if the color scheme is grayscale, true otherwise. + #[must_use] pub fn has_color(self) -> bool { use ColorType::*; match self { @@ -67,11 +74,13 @@ /// Returns the number of bits contained in a pixel of `ColorType` ```c``` (which will always be /// a multiple of 8). + #[must_use] pub fn bits_per_pixel(self) -> u16 { >::from(self.bytes_per_pixel()) * 8 } /// Returns the number of color channels that make up this pixel + #[must_use] pub fn channel_count(self) -> u8 { let e: ExtendedColorType = self.into(); e.channel_count() @@ -87,6 +96,7 @@ /// Another purpose is to advise users of a rough estimate of the accuracy and effort of the /// decoding from and encoding to such an image format. #[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[non_exhaustive] pub enum ExtendedColorType { /// Pixel is 8-bit alpha @@ -144,6 +154,8 @@ /// Pixel is 8-bit CMYK Cmyk8, + /// Pixel is 16-bit CMYK + Cmyk16, /// Pixel is of unknown color type with the specified bits per pixel. This can apply to pixels /// which are associated with an external palette. In that case, the pixel value is an index @@ -156,6 +168,7 @@ /// /// Note that the `Unknown` variant returns a value of `1` since pixels can only be treated as /// an opaque datum by the library. + #[must_use] pub fn channel_count(self) -> u8 { match self { ExtendedColorType::A8 @@ -184,10 +197,93 @@ | ExtendedColorType::Rgba16 | ExtendedColorType::Rgba32F | ExtendedColorType::Bgra8 - | ExtendedColorType::Cmyk8 => 4, + | ExtendedColorType::Cmyk8 + | ExtendedColorType::Cmyk16 => 4, } } + + /// Returns the number of bits per pixel for this color type. + #[must_use] + pub fn bits_per_pixel(&self) -> u16 { + match *self { + ExtendedColorType::A8 => 8, + ExtendedColorType::L1 => 1, + ExtendedColorType::La1 => 2, + ExtendedColorType::Rgb1 => 3, + ExtendedColorType::Rgba1 => 4, + ExtendedColorType::L2 => 2, + ExtendedColorType::La2 => 4, + ExtendedColorType::Rgb2 => 6, + ExtendedColorType::Rgba2 => 8, + ExtendedColorType::L4 => 4, + ExtendedColorType::La4 => 8, + ExtendedColorType::Rgb4 => 12, + ExtendedColorType::Rgba4 => 16, + ExtendedColorType::L8 => 8, + ExtendedColorType::La8 => 16, + ExtendedColorType::Rgb8 => 24, + ExtendedColorType::Rgba8 => 32, + ExtendedColorType::L16 => 16, + ExtendedColorType::La16 => 32, + ExtendedColorType::Rgb16 => 48, + ExtendedColorType::Rgba16 => 64, + ExtendedColorType::Rgb32F => 96, + ExtendedColorType::Rgba32F => 128, + ExtendedColorType::Bgr8 => 24, + ExtendedColorType::Bgra8 => 32, + ExtendedColorType::Cmyk8 => 32, + ExtendedColorType::Cmyk16 => 64, + ExtendedColorType::Unknown(bpp) => bpp as u16, + } + } + + /// Returns the ColorType that is equivalent to this ExtendedColorType. + /// + /// # Example + /// + /// ``` + /// use image::{ColorType, ExtendedColorType}; + /// + /// assert_eq!(Some(ColorType::L8), ExtendedColorType::L8.color_type()); + /// assert_eq!(None, ExtendedColorType::L1.color_type()); + /// ``` + /// + /// The method is equivalent to converting via the `TryFrom`/`TryInto` traits except for the + /// error path. Choose the more ergonomic option in your usage. + /// + /// ``` + /// use image::{ColorType, ExtendedColorType, ImageError}; + /// + /// fn handle_errors() -> Result<(), ImageError> { + /// let color: ColorType = ExtendedColorType::L8.try_into()?; + /// assert_eq!(color, ColorType::L8); + /// # Ok(()) + /// } + /// ``` + pub fn color_type(&self) -> Option { + match *self { + ExtendedColorType::L8 => Some(ColorType::L8), + ExtendedColorType::La8 => Some(ColorType::La8), + ExtendedColorType::Rgb8 => Some(ColorType::Rgb8), + ExtendedColorType::Rgba8 => Some(ColorType::Rgba8), + ExtendedColorType::L16 => Some(ColorType::L16), + ExtendedColorType::La16 => Some(ColorType::La16), + ExtendedColorType::Rgb16 => Some(ColorType::Rgb16), + ExtendedColorType::Rgba16 => Some(ColorType::Rgba16), + ExtendedColorType::Rgb32F => Some(ColorType::Rgb32F), + ExtendedColorType::Rgba32F => Some(ColorType::Rgba32F), + _ => None, + } + } + + /// Returns the number of bytes required to hold a width x height image of this color type. + pub(crate) fn buffer_size(self, width: u32, height: u32) -> u64 { + let bpp = self.bits_per_pixel() as u64; + let row_pitch = (width as u64 * bpp).div_ceil(8); + row_pitch.saturating_mul(height as u64) + } } + impl From for ExtendedColorType { fn from(c: ColorType) -> Self { match c { @@ -205,6 +301,16 @@ } } +impl TryFrom for ColorType { + type Error = TryFromExtendedColorError; + + fn try_from(value: ExtendedColorType) -> Result { + value + .color_type() + .ok_or(TryFromExtendedColorError { was: value }) + } +} + macro_rules! define_colors { {$( $(#[$doc:meta])* @@ -216,7 +322,7 @@ $(#[$doc])* #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)] -#[repr(C)] +#[repr(transparent)] #[allow(missing_docs)] pub struct $ident (pub [T; $channels]); @@ -237,6 +343,18 @@ const COLOR_MODEL: &'static str = $interpretation; + const HAS_ALPHA: bool = $alphas > 0; + + #[inline] + fn alpha(&self) -> Self::Subpixel { + if Self::HAS_ALPHA { + // all our types have alpha channel at the end: RgbA, LumaA + *self.channels().last().unwrap() + } else { + Self::Subpixel::DEFAULT_MAX_VALUE + } + } + fn channels4(&self) -> (T, T, T, T) { const CHANNELS: usize = $channels; let mut channels = [T::DEFAULT_MAX_VALUE; 4]; @@ -389,17 +507,25 @@ // Note that in to-integer-conversion we are performing rounding but NumCast::from is implemented // as truncate towards zero. We emulate rounding by adding a bias. +// All other special values are clamped inbetween 0.0 and 1.0 (infinities and subnormals) +// NaN however always maps to NaN therefore we have to force it towards some value. +// 1.0 (white) was picked as firefox and chrome choose to map NaN to that. +#[inline] +fn normalize_float(float: f32, max: f32) -> f32 { + #[allow(clippy::neg_cmp_op_on_partial_ord)] + let clamped = if !(float < 1.0) { 1.0 } else { float.max(0.0) }; + (clamped * max).round() +} + impl FromPrimitive for u8 { fn from_primitive(float: f32) -> Self { - let inner = (float.clamp(0.0, 1.0) * u8::MAX as f32).round(); - NumCast::from(inner).unwrap() + NumCast::from(normalize_float(float, u8::MAX as f32)).unwrap() } } impl FromPrimitive for u16 { fn from_primitive(float: f32) -> Self { - let inner = (float.clamp(0.0, 1.0) * u16::MAX as f32).round(); - NumCast::from(inner).unwrap() + NumCast::from(normalize_float(float, u16::MAX as f32)).unwrap() } } @@ -444,6 +570,7 @@ /// Provides color conversions for the different pixel types. pub trait FromColor { /// Changes `self` to represent `Other` in the color space of `Self` + #[allow(clippy::wrong_self_convention)] fn from_color(&mut self, _: &Other); } @@ -452,6 +579,7 @@ // rather than assuming sRGB. pub(crate) trait IntoColor { /// Constructs a pixel of the target type and converts this pixel into it. + #[allow(clippy::wrong_self_convention)] fn into_color(&self) -> Other; } @@ -459,6 +587,7 @@ where O: Pixel + FromColor, { + #[allow(clippy::wrong_self_convention)] fn into_color(&self) -> O { // Note we cannot use Pixel::CHANNELS_COUNT here to directly construct // the pixel due to a current bug/limitation of consts. @@ -498,7 +627,7 @@ T: FromPrimitive, { fn from_color(&mut self, other: &LumaA) { - self.channels_mut()[0] = T::from_primitive(other.channels()[0]) + self.channels_mut()[0] = T::from_primitive(other.channels()[0]); } } @@ -721,13 +850,13 @@ *self = LumaA([ NumCast::from(max_t * out_luma).unwrap(), NumCast::from(max_t * alpha_final).unwrap(), - ]) + ]); } } impl Blend for Luma { fn blend(&mut self, other: &Luma) { - *self = *other + *self = *other; } } @@ -791,13 +920,13 @@ NumCast::from(max_t * out_g).unwrap(), NumCast::from(max_t * out_b).unwrap(), NumCast::from(max_t * alpha_final).unwrap(), - ]) + ]); } } impl Blend for Rgb { fn blend(&mut self, other: &Rgb) { - *self = *other + *self = *other; } } @@ -812,7 +941,7 @@ let l = self.0; let max = T::DEFAULT_MAX_VALUE; - *self = LumaA([max - l[0], l[1]]) + *self = LumaA([max - l[0], l[1]]); } } @@ -823,7 +952,7 @@ let max = T::DEFAULT_MAX_VALUE; let l1 = max - l[0]; - *self = Luma([l1]) + *self = Luma([l1]); } } @@ -833,7 +962,7 @@ let max = T::DEFAULT_MAX_VALUE; - *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]]) + *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]]); } } @@ -847,7 +976,7 @@ let g1 = max - rgb[1]; let b1 = max - rgb[2]; - *self = Rgb([r1, g1, b1]) + *self = Rgb([r1, g1, b1]); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/dynimage.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/dynimage.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/dynimage.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/dynimage.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1378 +0,0 @@ -use std::io; -use std::io::{Seek, Write}; -use std::path::Path; -use std::u32; - -#[cfg(feature = "gif")] -use crate::codecs::gif; -#[cfg(feature = "png")] -use crate::codecs::png; -#[cfg(feature = "pnm")] -use crate::codecs::pnm; - -use crate::buffer_::{ - ConvertBuffer, Gray16Image, GrayAlpha16Image, GrayAlphaImage, GrayImage, ImageBuffer, - Rgb16Image, RgbImage, Rgba16Image, RgbaImage, -}; -use crate::color::{self, IntoColor}; -use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; -use crate::flat::FlatSamples; -use crate::image::{ - GenericImage, GenericImageView, ImageDecoder, ImageEncoder, ImageFormat, ImageOutputFormat, -}; -use crate::imageops; -use crate::io::free_functions; -use crate::math::resize_dimensions; -use crate::traits::Pixel; -use crate::{image, Luma, LumaA}; -use crate::{Rgb32FImage, Rgba32FImage}; - -/// A Dynamic Image -/// -/// This represents a _matrix_ of _pixels_ which are _convertible_ from and to an _RGBA_ -/// representation. More variants that adhere to these principles may get added in the future, in -/// particular to cover other combinations typically used. -/// -/// # Usage -/// -/// This type can act as a converter between specific `ImageBuffer` instances. -/// -/// ``` -/// use image::{DynamicImage, GrayImage, RgbImage}; -/// -/// let rgb: RgbImage = RgbImage::new(10, 10); -/// let luma: GrayImage = DynamicImage::ImageRgb8(rgb).into_luma8(); -/// ``` -/// -/// # Design -/// -/// There is no goal to provide an all-encompassing type with all possible memory layouts. This -/// would hardly be feasible as a simple enum, due to the sheer number of combinations of channel -/// kinds, channel order, and bit depth. Rather, this type provides an opinionated selection with -/// normalized channel order which can store common pixel values without loss. -#[derive(Clone, Debug, PartialEq)] -#[non_exhaustive] -pub enum DynamicImage { - /// Each pixel in this image is 8-bit Luma - ImageLuma8(GrayImage), - - /// Each pixel in this image is 8-bit Luma with alpha - ImageLumaA8(GrayAlphaImage), - - /// Each pixel in this image is 8-bit Rgb - ImageRgb8(RgbImage), - - /// Each pixel in this image is 8-bit Rgb with alpha - ImageRgba8(RgbaImage), - - /// Each pixel in this image is 16-bit Luma - ImageLuma16(Gray16Image), - - /// Each pixel in this image is 16-bit Luma with alpha - ImageLumaA16(GrayAlpha16Image), - - /// Each pixel in this image is 16-bit Rgb - ImageRgb16(Rgb16Image), - - /// Each pixel in this image is 16-bit Rgb with alpha - ImageRgba16(Rgba16Image), - - /// Each pixel in this image is 32-bit float Rgb - ImageRgb32F(Rgb32FImage), - - /// Each pixel in this image is 32-bit float Rgb with alpha - ImageRgba32F(Rgba32FImage), -} - -macro_rules! dynamic_map( - ($dynimage: expr, $image: pat => $action: expr) => ({ - use DynamicImage::*; - match $dynimage { - ImageLuma8($image) => ImageLuma8($action), - ImageLumaA8($image) => ImageLumaA8($action), - ImageRgb8($image) => ImageRgb8($action), - ImageRgba8($image) => ImageRgba8($action), - ImageLuma16($image) => ImageLuma16($action), - ImageLumaA16($image) => ImageLumaA16($action), - ImageRgb16($image) => ImageRgb16($action), - ImageRgba16($image) => ImageRgba16($action), - ImageRgb32F($image) => ImageRgb32F($action), - ImageRgba32F($image) => ImageRgba32F($action), - } - }); - - ($dynimage: expr, $image:pat_param, $action: expr) => ( - match $dynimage { - DynamicImage::ImageLuma8($image) => $action, - DynamicImage::ImageLumaA8($image) => $action, - DynamicImage::ImageRgb8($image) => $action, - DynamicImage::ImageRgba8($image) => $action, - DynamicImage::ImageLuma16($image) => $action, - DynamicImage::ImageLumaA16($image) => $action, - DynamicImage::ImageRgb16($image) => $action, - DynamicImage::ImageRgba16($image) => $action, - DynamicImage::ImageRgb32F($image) => $action, - DynamicImage::ImageRgba32F($image) => $action, - } - ); -); - -impl DynamicImage { - /// Creates a dynamic image backed by a buffer depending on - /// the color type given. - pub fn new(w: u32, h: u32, color: color::ColorType) -> DynamicImage { - use color::ColorType::*; - match color { - L8 => Self::new_luma8(w, h), - La8 => Self::new_luma_a8(w, h), - Rgb8 => Self::new_rgb8(w, h), - Rgba8 => Self::new_rgba8(w, h), - L16 => Self::new_luma16(w, h), - La16 => Self::new_luma_a16(w, h), - Rgb16 => Self::new_rgb16(w, h), - Rgba16 => Self::new_rgba16(w, h), - Rgb32F => Self::new_rgb32f(w, h), - Rgba32F => Self::new_rgba32f(w, h), - } - } - - /// Creates a dynamic image backed by a buffer of gray pixels. - pub fn new_luma8(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageLuma8(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of gray - /// pixels with transparency. - pub fn new_luma_a8(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageLumaA8(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGB pixels. - pub fn new_rgb8(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgb8(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGBA pixels. - pub fn new_rgba8(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgba8(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of gray pixels. - pub fn new_luma16(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageLuma16(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of gray - /// pixels with transparency. - pub fn new_luma_a16(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageLumaA16(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGB pixels. - pub fn new_rgb16(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgb16(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGBA pixels. - pub fn new_rgba16(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgba16(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGB pixels. - pub fn new_rgb32f(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgb32F(ImageBuffer::new(w, h)) - } - - /// Creates a dynamic image backed by a buffer of RGBA pixels. - pub fn new_rgba32f(w: u32, h: u32) -> DynamicImage { - DynamicImage::ImageRgba32F(ImageBuffer::new(w, h)) - } - - /// Decodes an encoded image into a dynamic image. - pub fn from_decoder<'a>(decoder: impl ImageDecoder<'a>) -> ImageResult { - decoder_to_image(decoder) - } - - /// Returns a copy of this image as an RGB image. - pub fn to_rgb8(&self) -> RgbImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as an RGB image. - pub fn to_rgb16(&self) -> Rgb16Image { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as an RGB image. - pub fn to_rgb32f(&self) -> Rgb32FImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as an RGBA image. - pub fn to_rgba8(&self) -> RgbaImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as an RGBA image. - pub fn to_rgba16(&self) -> Rgba16Image { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as an RGBA image. - pub fn to_rgba32f(&self) -> Rgba32FImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a Luma image. - pub fn to_luma8(&self) -> GrayImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a Luma image. - pub fn to_luma16(&self) -> Gray16Image { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a Luma image. - pub fn to_luma32f(&self) -> ImageBuffer, Vec> { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a LumaA image. - pub fn to_luma_alpha8(&self) -> GrayAlphaImage { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a LumaA image. - pub fn to_luma_alpha16(&self) -> GrayAlpha16Image { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Returns a copy of this image as a LumaA image. - pub fn to_luma_alpha32f(&self) -> ImageBuffer, Vec> { - dynamic_map!(*self, ref p, p.convert()) - } - - /// Consume the image and returns a RGB image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgb8(self) -> RgbImage { - match self { - DynamicImage::ImageRgb8(x) => x, - x => x.to_rgb8(), - } - } - - /// Consume the image and returns a RGB image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgb16(self) -> Rgb16Image { - match self { - DynamicImage::ImageRgb16(x) => x, - x => x.to_rgb16(), - } - } - - /// Consume the image and returns a RGB image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgb32f(self) -> Rgb32FImage { - match self { - DynamicImage::ImageRgb32F(x) => x, - x => x.to_rgb32f(), - } - } - - /// Consume the image and returns a RGBA image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgba8(self) -> RgbaImage { - match self { - DynamicImage::ImageRgba8(x) => x, - x => x.to_rgba8(), - } - } - - /// Consume the image and returns a RGBA image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgba16(self) -> Rgba16Image { - match self { - DynamicImage::ImageRgba16(x) => x, - x => x.to_rgba16(), - } - } - - /// Consume the image and returns a RGBA image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_rgba32f(self) -> Rgba32FImage { - match self { - DynamicImage::ImageRgba32F(x) => x, - x => x.to_rgba32f(), - } - } - - /// Consume the image and returns a Luma image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_luma8(self) -> GrayImage { - match self { - DynamicImage::ImageLuma8(x) => x, - x => x.to_luma8(), - } - } - - /// Consume the image and returns a Luma image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_luma16(self) -> Gray16Image { - match self { - DynamicImage::ImageLuma16(x) => x, - x => x.to_luma16(), - } - } - - /// Consume the image and returns a LumaA image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_luma_alpha8(self) -> GrayAlphaImage { - match self { - DynamicImage::ImageLumaA8(x) => x, - x => x.to_luma_alpha8(), - } - } - - /// Consume the image and returns a LumaA image. - /// - /// If the image was already the correct format, it is returned as is. - /// Otherwise, a copy is created. - pub fn into_luma_alpha16(self) -> GrayAlpha16Image { - match self { - DynamicImage::ImageLumaA16(x) => x, - x => x.to_luma_alpha16(), - } - } - - /// Return a cut-out of this image delimited by the bounding rectangle. - /// - /// Note: this method does *not* modify the object, - /// and its signature will be replaced with `crop_imm()`'s in the 0.24 release - pub fn crop(&mut self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage { - dynamic_map!(*self, ref mut p => imageops::crop(p, x, y, width, height).to_image()) - } - - /// Return a cut-out of this image delimited by the bounding rectangle. - pub fn crop_imm(&self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::crop_imm(p, x, y, width, height).to_image()) - } - - /// Return a reference to an 8bit RGB image - pub fn as_rgb8(&self) -> Option<&RgbImage> { - match *self { - DynamicImage::ImageRgb8(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 8bit RGB image - pub fn as_mut_rgb8(&mut self) -> Option<&mut RgbImage> { - match *self { - DynamicImage::ImageRgb8(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 8bit RGBA image - pub fn as_rgba8(&self) -> Option<&RgbaImage> { - match *self { - DynamicImage::ImageRgba8(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 8bit RGBA image - pub fn as_mut_rgba8(&mut self) -> Option<&mut RgbaImage> { - match *self { - DynamicImage::ImageRgba8(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 8bit Grayscale image - pub fn as_luma8(&self) -> Option<&GrayImage> { - match *self { - DynamicImage::ImageLuma8(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 8bit Grayscale image - pub fn as_mut_luma8(&mut self) -> Option<&mut GrayImage> { - match *self { - DynamicImage::ImageLuma8(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 8bit Grayscale image with an alpha channel - pub fn as_luma_alpha8(&self) -> Option<&GrayAlphaImage> { - match *self { - DynamicImage::ImageLumaA8(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 8bit Grayscale image with an alpha channel - pub fn as_mut_luma_alpha8(&mut self) -> Option<&mut GrayAlphaImage> { - match *self { - DynamicImage::ImageLumaA8(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 16bit RGB image - pub fn as_rgb16(&self) -> Option<&Rgb16Image> { - match *self { - DynamicImage::ImageRgb16(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 16bit RGB image - pub fn as_mut_rgb16(&mut self) -> Option<&mut Rgb16Image> { - match *self { - DynamicImage::ImageRgb16(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 16bit RGBA image - pub fn as_rgba16(&self) -> Option<&Rgba16Image> { - match *self { - DynamicImage::ImageRgba16(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 16bit RGBA image - pub fn as_mut_rgba16(&mut self) -> Option<&mut Rgba16Image> { - match *self { - DynamicImage::ImageRgba16(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 32bit RGB image - pub fn as_rgb32f(&self) -> Option<&Rgb32FImage> { - match *self { - DynamicImage::ImageRgb32F(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 32bit RGB image - pub fn as_mut_rgb32f(&mut self) -> Option<&mut Rgb32FImage> { - match *self { - DynamicImage::ImageRgb32F(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 32bit RGBA image - pub fn as_rgba32f(&self) -> Option<&Rgba32FImage> { - match *self { - DynamicImage::ImageRgba32F(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 16bit RGBA image - pub fn as_mut_rgba32f(&mut self) -> Option<&mut Rgba32FImage> { - match *self { - DynamicImage::ImageRgba32F(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 16bit Grayscale image - pub fn as_luma16(&self) -> Option<&Gray16Image> { - match *self { - DynamicImage::ImageLuma16(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 16bit Grayscale image - pub fn as_mut_luma16(&mut self) -> Option<&mut Gray16Image> { - match *self { - DynamicImage::ImageLuma16(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a reference to an 16bit Grayscale image with an alpha channel - pub fn as_luma_alpha16(&self) -> Option<&GrayAlpha16Image> { - match *self { - DynamicImage::ImageLumaA16(ref p) => Some(p), - _ => None, - } - } - - /// Return a mutable reference to an 16bit Grayscale image with an alpha channel - pub fn as_mut_luma_alpha16(&mut self) -> Option<&mut GrayAlpha16Image> { - match *self { - DynamicImage::ImageLumaA16(ref mut p) => Some(p), - _ => None, - } - } - - /// Return a view on the raw sample buffer for 8 bit per channel images. - pub fn as_flat_samples_u8(&self) -> Option> { - match *self { - DynamicImage::ImageLuma8(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageLumaA8(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageRgb8(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageRgba8(ref p) => Some(p.as_flat_samples()), - _ => None, - } - } - - /// Return a view on the raw sample buffer for 16 bit per channel images. - pub fn as_flat_samples_u16(&self) -> Option> { - match *self { - DynamicImage::ImageLuma16(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageLumaA16(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageRgb16(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageRgba16(ref p) => Some(p.as_flat_samples()), - _ => None, - } - } - - /// Return a view on the raw sample buffer for 32bit per channel images. - pub fn as_flat_samples_f32(&self) -> Option> { - match *self { - DynamicImage::ImageRgb32F(ref p) => Some(p.as_flat_samples()), - DynamicImage::ImageRgba32F(ref p) => Some(p.as_flat_samples()), - _ => None, - } - } - - /// Return this image's pixels as a native endian byte slice. - pub fn as_bytes(&self) -> &[u8] { - // we can do this because every variant contains an `ImageBuffer<_, Vec<_>>` - dynamic_map!( - *self, - ref image_buffer, - bytemuck::cast_slice(image_buffer.as_raw().as_ref()) - ) - } - - // TODO: choose a name under which to expose? - fn inner_bytes(&self) -> &[u8] { - // we can do this because every variant contains an `ImageBuffer<_, Vec<_>>` - dynamic_map!( - *self, - ref image_buffer, - bytemuck::cast_slice(image_buffer.inner_pixels()) - ) - } - - /// Return this image's pixels as a byte vector. If the `ImageBuffer` - /// container is `Vec`, this operation is free. Otherwise, a copy - /// is returned. - pub fn into_bytes(self) -> Vec { - // we can do this because every variant contains an `ImageBuffer<_, Vec<_>>` - dynamic_map!(self, image_buffer, { - match bytemuck::allocation::try_cast_vec(image_buffer.into_raw()) { - Ok(vec) => vec, - Err((_, vec)) => { - // Fallback: vector requires an exact alignment and size match - // Reuse of the allocation as done in the Ok branch only works if the - // underlying container is exactly Vec (or compatible but that's the only - // alternative at the time of writing). - // In all other cases we must allocate a new vector with the 'same' contents. - bytemuck::cast_slice(&vec).to_owned() - } - } - }) - } - - /// Return a copy of this image's pixels as a byte vector. - /// Deprecated, because it does nothing but hide an expensive clone operation. - #[deprecated( - since = "0.24.0", - note = "use `image.into_bytes()` or `image.as_bytes().to_vec()` instead" - )] - pub fn to_bytes(&self) -> Vec { - self.as_bytes().to_vec() - } - - /// Return this image's color type. - pub fn color(&self) -> color::ColorType { - match *self { - DynamicImage::ImageLuma8(_) => color::ColorType::L8, - DynamicImage::ImageLumaA8(_) => color::ColorType::La8, - DynamicImage::ImageRgb8(_) => color::ColorType::Rgb8, - DynamicImage::ImageRgba8(_) => color::ColorType::Rgba8, - DynamicImage::ImageLuma16(_) => color::ColorType::L16, - DynamicImage::ImageLumaA16(_) => color::ColorType::La16, - DynamicImage::ImageRgb16(_) => color::ColorType::Rgb16, - DynamicImage::ImageRgba16(_) => color::ColorType::Rgba16, - DynamicImage::ImageRgb32F(_) => color::ColorType::Rgb32F, - DynamicImage::ImageRgba32F(_) => color::ColorType::Rgba32F, - } - } - - /// Returns the width of the underlying image - pub fn width(&self) -> u32 { - dynamic_map!(*self, ref p, { p.width() }) - } - - /// Returns the height of the underlying image - pub fn height(&self) -> u32 { - dynamic_map!(*self, ref p, { p.height() }) - } - - /// Return a grayscale version of this image. - /// Returns `Luma` images in most cases. However, for `f32` images, - /// this will return a grayscale `Rgb/Rgba` image instead. - pub fn grayscale(&self) -> DynamicImage { - match *self { - DynamicImage::ImageLuma8(ref p) => DynamicImage::ImageLuma8(p.clone()), - DynamicImage::ImageLumaA8(ref p) => { - DynamicImage::ImageLumaA8(imageops::grayscale_alpha(p)) - } - DynamicImage::ImageRgb8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)), - DynamicImage::ImageRgba8(ref p) => { - DynamicImage::ImageLumaA8(imageops::grayscale_alpha(p)) - } - DynamicImage::ImageLuma16(ref p) => DynamicImage::ImageLuma16(p.clone()), - DynamicImage::ImageLumaA16(ref p) => { - DynamicImage::ImageLumaA16(imageops::grayscale_alpha(p)) - } - DynamicImage::ImageRgb16(ref p) => DynamicImage::ImageLuma16(imageops::grayscale(p)), - DynamicImage::ImageRgba16(ref p) => { - DynamicImage::ImageLumaA16(imageops::grayscale_alpha(p)) - } - DynamicImage::ImageRgb32F(ref p) => { - DynamicImage::ImageRgb32F(imageops::grayscale_with_type(p)) - } - DynamicImage::ImageRgba32F(ref p) => { - DynamicImage::ImageRgba32F(imageops::grayscale_with_type_alpha(p)) - } - } - } - - /// Invert the colors of this image. - /// This method operates inplace. - pub fn invert(&mut self) { - dynamic_map!(*self, ref mut p, imageops::invert(p)) - } - - /// Resize this image using the specified filter algorithm. - /// Returns a new image. The image's aspect ratio is preserved. - /// The image is scaled to the maximum possible size that fits - /// within the bounds specified by `nwidth` and `nheight`. - pub fn resize(&self, nwidth: u32, nheight: u32, filter: imageops::FilterType) -> DynamicImage { - if (nwidth, nheight) == self.dimensions() { - return self.clone(); - } - let (width2, height2) = - resize_dimensions(self.width(), self.height(), nwidth, nheight, false); - - self.resize_exact(width2, height2, filter) - } - - /// Resize this image using the specified filter algorithm. - /// Returns a new image. Does not preserve aspect ratio. - /// `nwidth` and `nheight` are the new image's dimensions - pub fn resize_exact( - &self, - nwidth: u32, - nheight: u32, - filter: imageops::FilterType, - ) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::resize(p, nwidth, nheight, filter)) - } - - /// Scale this image down to fit within a specific size. - /// Returns a new image. The image's aspect ratio is preserved. - /// The image is scaled to the maximum possible size that fits - /// within the bounds specified by `nwidth` and `nheight`. - /// - /// This method uses a fast integer algorithm where each source - /// pixel contributes to exactly one target pixel. - /// May give aliasing artifacts if new size is close to old size. - pub fn thumbnail(&self, nwidth: u32, nheight: u32) -> DynamicImage { - let (width2, height2) = - resize_dimensions(self.width(), self.height(), nwidth, nheight, false); - self.thumbnail_exact(width2, height2) - } - - /// Scale this image down to a specific size. - /// Returns a new image. Does not preserve aspect ratio. - /// `nwidth` and `nheight` are the new image's dimensions. - /// This method uses a fast integer algorithm where each source - /// pixel contributes to exactly one target pixel. - /// May give aliasing artifacts if new size is close to old size. - pub fn thumbnail_exact(&self, nwidth: u32, nheight: u32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::thumbnail(p, nwidth, nheight)) - } - - /// Resize this image using the specified filter algorithm. - /// Returns a new image. The image's aspect ratio is preserved. - /// The image is scaled to the maximum possible size that fits - /// within the larger (relative to aspect ratio) of the bounds - /// specified by `nwidth` and `nheight`, then cropped to - /// fit within the other bound. - pub fn resize_to_fill( - &self, - nwidth: u32, - nheight: u32, - filter: imageops::FilterType, - ) -> DynamicImage { - let (width2, height2) = - resize_dimensions(self.width(), self.height(), nwidth, nheight, true); - - let mut intermediate = self.resize_exact(width2, height2, filter); - let (iwidth, iheight) = intermediate.dimensions(); - let ratio = u64::from(iwidth) * u64::from(nheight); - let nratio = u64::from(nwidth) * u64::from(iheight); - - if nratio > ratio { - intermediate.crop(0, (iheight - nheight) / 2, nwidth, nheight) - } else { - intermediate.crop((iwidth - nwidth) / 2, 0, nwidth, nheight) - } - } - - /// Performs a Gaussian blur on this image. - /// `sigma` is a measure of how much to blur by. - pub fn blur(&self, sigma: f32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::blur(p, sigma)) - } - - /// Performs an unsharpen mask on this image. - /// `sigma` is the amount to blur the image by. - /// `threshold` is a control of how much to sharpen. - /// - /// See - pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold)) - } - - /// Filters this image with the specified 3x3 kernel. - pub fn filter3x3(&self, kernel: &[f32]) -> DynamicImage { - if kernel.len() != 9 { - panic!("filter must be 3 x 3") - } - - dynamic_map!(*self, ref p => imageops::filter3x3(p, kernel)) - } - - /// Adjust the contrast of this image. - /// `contrast` is the amount to adjust the contrast by. - /// Negative values decrease the contrast and positive values increase the contrast. - pub fn adjust_contrast(&self, c: f32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::contrast(p, c)) - } - - /// Brighten the pixels of this image. - /// `value` is the amount to brighten each pixel by. - /// Negative values decrease the brightness and positive values increase it. - pub fn brighten(&self, value: i32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::brighten(p, value)) - } - - /// Hue rotate the supplied image. - /// `value` is the degrees to rotate each pixel by. - /// 0 and 360 do nothing, the rest rotates by the given degree value. - /// just like the css webkit filter hue-rotate(180) - pub fn huerotate(&self, value: i32) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::huerotate(p, value)) - } - - /// Flip this image vertically - pub fn flipv(&self) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::flip_vertical(p)) - } - - /// Flip this image horizontally - pub fn fliph(&self) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::flip_horizontal(p)) - } - - /// Rotate this image 90 degrees clockwise. - pub fn rotate90(&self) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::rotate90(p)) - } - - /// Rotate this image 180 degrees clockwise. - pub fn rotate180(&self) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::rotate180(p)) - } - - /// Rotate this image 270 degrees clockwise. - pub fn rotate270(&self) -> DynamicImage { - dynamic_map!(*self, ref p => imageops::rotate270(p)) - } - - /// Encode this image and write it to ```w```. - /// - /// Assumes the writer is buffered. In most cases, - /// you should wrap your writer in a `BufWriter` for best performance. - pub fn write_to>( - &self, - w: &mut W, - format: F, - ) -> ImageResult<()> { - let bytes = self.inner_bytes(); - let (width, height) = self.dimensions(); - let color = self.color(); - let format = format.into(); - - // TODO do not repeat this match statement across the crate - - #[allow(deprecated)] - match format { - #[cfg(feature = "png")] - image::ImageOutputFormat::Png => { - let p = png::PngEncoder::new(w); - p.write_image(bytes, width, height, color)?; - Ok(()) - } - - #[cfg(feature = "pnm")] - image::ImageOutputFormat::Pnm(subtype) => { - let p = pnm::PnmEncoder::new(w).with_subtype(subtype); - p.write_image(bytes, width, height, color)?; - Ok(()) - } - - #[cfg(feature = "gif")] - image::ImageOutputFormat::Gif => { - let mut g = gif::GifEncoder::new(w); - g.encode_frame(crate::animation::Frame::new(self.to_rgba8()))?; - Ok(()) - } - - format => write_buffer_with_format(w, bytes, width, height, color, format), - } - } - - /// Encode this image with the provided encoder. - pub fn write_with_encoder(&self, encoder: impl ImageEncoder) -> ImageResult<()> { - dynamic_map!(self, ref p, p.write_with_encoder(encoder)) - } - - /// Saves the buffer to a file at the path specified. - /// - /// The image format is derived from the file extension. - pub fn save(&self, path: Q) -> ImageResult<()> - where - Q: AsRef, - { - dynamic_map!(*self, ref p, p.save(path)) - } - - /// Saves the buffer to a file at the specified path in - /// the specified format. - /// - /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for - /// supported types. - pub fn save_with_format(&self, path: Q, format: ImageFormat) -> ImageResult<()> - where - Q: AsRef, - { - dynamic_map!(*self, ref p, p.save_with_format(path, format)) - } -} - -impl From for DynamicImage { - fn from(image: GrayImage) -> Self { - DynamicImage::ImageLuma8(image) - } -} - -impl From for DynamicImage { - fn from(image: GrayAlphaImage) -> Self { - DynamicImage::ImageLumaA8(image) - } -} - -impl From for DynamicImage { - fn from(image: RgbImage) -> Self { - DynamicImage::ImageRgb8(image) - } -} - -impl From for DynamicImage { - fn from(image: RgbaImage) -> Self { - DynamicImage::ImageRgba8(image) - } -} - -impl From for DynamicImage { - fn from(image: Gray16Image) -> Self { - DynamicImage::ImageLuma16(image) - } -} - -impl From for DynamicImage { - fn from(image: GrayAlpha16Image) -> Self { - DynamicImage::ImageLumaA16(image) - } -} - -impl From for DynamicImage { - fn from(image: Rgb16Image) -> Self { - DynamicImage::ImageRgb16(image) - } -} - -impl From for DynamicImage { - fn from(image: Rgba16Image) -> Self { - DynamicImage::ImageRgba16(image) - } -} - -impl From for DynamicImage { - fn from(image: Rgb32FImage) -> Self { - DynamicImage::ImageRgb32F(image) - } -} - -impl From for DynamicImage { - fn from(image: Rgba32FImage) -> Self { - DynamicImage::ImageRgba32F(image) - } -} - -impl From, Vec>> for DynamicImage { - fn from(image: ImageBuffer, Vec>) -> Self { - DynamicImage::ImageRgb32F(image.convert()) - } -} - -impl From, Vec>> for DynamicImage { - fn from(image: ImageBuffer, Vec>) -> Self { - DynamicImage::ImageRgba32F(image.convert()) - } -} - -#[allow(deprecated)] -impl GenericImageView for DynamicImage { - type Pixel = color::Rgba; // TODO use f32 as default for best precision and unbounded color? - - fn dimensions(&self) -> (u32, u32) { - dynamic_map!(*self, ref p, p.dimensions()) - } - - fn bounds(&self) -> (u32, u32, u32, u32) { - dynamic_map!(*self, ref p, p.bounds()) - } - - fn get_pixel(&self, x: u32, y: u32) -> color::Rgba { - dynamic_map!(*self, ref p, p.get_pixel(x, y).to_rgba().into_color()) - } -} - -#[allow(deprecated)] -impl GenericImage for DynamicImage { - fn put_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { - match *self { - DynamicImage::ImageLuma8(ref mut p) => p.put_pixel(x, y, pixel.to_luma()), - DynamicImage::ImageLumaA8(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha()), - DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, pixel.to_rgb()), - DynamicImage::ImageRgba8(ref mut p) => p.put_pixel(x, y, pixel), - DynamicImage::ImageLuma16(ref mut p) => p.put_pixel(x, y, pixel.to_luma().into_color()), - DynamicImage::ImageLumaA16(ref mut p) => { - p.put_pixel(x, y, pixel.to_luma_alpha().into_color()) - } - DynamicImage::ImageRgb16(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()), - DynamicImage::ImageRgba16(ref mut p) => p.put_pixel(x, y, pixel.into_color()), - DynamicImage::ImageRgb32F(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()), - DynamicImage::ImageRgba32F(ref mut p) => p.put_pixel(x, y, pixel.into_color()), - } - } - - fn blend_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { - match *self { - DynamicImage::ImageLuma8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma()), - DynamicImage::ImageLumaA8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha()), - DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb()), - DynamicImage::ImageRgba8(ref mut p) => p.blend_pixel(x, y, pixel), - DynamicImage::ImageLuma16(ref mut p) => { - p.blend_pixel(x, y, pixel.to_luma().into_color()) - } - DynamicImage::ImageLumaA16(ref mut p) => { - p.blend_pixel(x, y, pixel.to_luma_alpha().into_color()) - } - DynamicImage::ImageRgb16(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb().into_color()), - DynamicImage::ImageRgba16(ref mut p) => p.blend_pixel(x, y, pixel.into_color()), - DynamicImage::ImageRgb32F(ref mut p) => { - p.blend_pixel(x, y, pixel.to_rgb().into_color()) - } - DynamicImage::ImageRgba32F(ref mut p) => p.blend_pixel(x, y, pixel.into_color()), - } - } - - /// Do not use is function: It is unimplemented! - fn get_pixel_mut(&mut self, _: u32, _: u32) -> &mut color::Rgba { - unimplemented!() - } -} - -impl Default for DynamicImage { - fn default() -> Self { - Self::ImageRgba8(Default::default()) - } -} - -/// Decodes an image and stores it into a dynamic image -fn decoder_to_image<'a, I: ImageDecoder<'a>>(decoder: I) -> ImageResult { - let (w, h) = decoder.dimensions(); - let color_type = decoder.color_type(); - - let image = match color_type { - color::ColorType::Rgb8 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb8) - } - - color::ColorType::Rgba8 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba8) - } - - color::ColorType::L8 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma8) - } - - color::ColorType::La8 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA8) - } - - color::ColorType::Rgb16 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb16) - } - - color::ColorType::Rgba16 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba16) - } - - color::ColorType::Rgb32F => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb32F) - } - - color::ColorType::Rgba32F => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba32F) - } - - color::ColorType::L16 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma16) - } - - color::ColorType::La16 => { - let buf = image::decoder_to_vec(decoder)?; - ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA16) - } - }; - - match image { - Some(image) => Ok(image), - None => Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))), - } -} - -/// Open the image located at the path specified. -/// The image's format is determined from the path's file extension. -/// -/// Try [`io::Reader`] for more advanced uses, including guessing the format based on the file's -/// content before its path. -/// -/// [`io::Reader`]: io/struct.Reader.html -pub fn open

(path: P) -> ImageResult -where - P: AsRef, -{ - // thin wrapper function to strip generics before calling open_impl - free_functions::open_impl(path.as_ref()) -} - -/// Read a tuple containing the (width, height) of the image located at the specified path. -/// This is faster than fully loading the image and then getting its dimensions. -/// -/// Try [`io::Reader`] for more advanced uses, including guessing the format based on the file's -/// content before its path or manually supplying the format. -/// -/// [`io::Reader`]: io/struct.Reader.html -pub fn image_dimensions

(path: P) -> ImageResult<(u32, u32)> -where - P: AsRef, -{ - // thin wrapper function to strip generics before calling open_impl - free_functions::image_dimensions_impl(path.as_ref()) -} - -/// Saves the supplied buffer to a file at the path specified. -/// -/// The image format is derived from the file extension. The buffer is assumed to have -/// the correct format according to the specified color type. -/// -/// This will lead to corrupted files if the buffer contains malformed data. Currently only -/// jpeg, png, ico, pnm, bmp, exr and tiff files are supported. -pub fn save_buffer

( - path: P, - buf: &[u8], - width: u32, - height: u32, - color: color::ColorType, -) -> ImageResult<()> -where - P: AsRef, -{ - // thin wrapper function to strip generics before calling save_buffer_impl - free_functions::save_buffer_impl(path.as_ref(), buf, width, height, color) -} - -/// Saves the supplied buffer to a file at the path specified -/// in the specified format. -/// -/// The buffer is assumed to have the correct format according -/// to the specified color type. -/// This will lead to corrupted files if the buffer contains -/// malformed data. Currently only jpeg, png, ico, bmp, exr and -/// tiff files are supported. -pub fn save_buffer_with_format

( - path: P, - buf: &[u8], - width: u32, - height: u32, - color: color::ColorType, - format: ImageFormat, -) -> ImageResult<()> -where - P: AsRef, -{ - // thin wrapper function to strip generics - free_functions::save_buffer_with_format_impl(path.as_ref(), buf, width, height, color, format) -} - -/// Writes the supplied buffer to a writer in the specified format. -/// -/// The buffer is assumed to have the correct format according -/// to the specified color type. -/// This will lead to corrupted writers if the buffer contains -/// malformed data. -/// -/// See [`ImageOutputFormat`](enum.ImageOutputFormat.html) for -/// supported types. -/// -/// Assumes the writer is buffered. In most cases, -/// you should wrap your writer in a `BufWriter` for best performance. -pub fn write_buffer_with_format( - buffered_writer: &mut W, - buf: &[u8], - width: u32, - height: u32, - color: color::ColorType, - format: F, -) -> ImageResult<()> -where - W: Write + Seek, - F: Into, -{ - // thin wrapper function to strip generics - free_functions::write_buffer_impl(buffered_writer, buf, width, height, color, format.into()) -} - -/// Create a new image from a byte slice -/// -/// Makes an educated guess about the image format. -/// TGA is not supported by this function. -/// -/// Try [`io::Reader`] for more advanced uses. -/// -/// [`io::Reader`]: io/struct.Reader.html -pub fn load_from_memory(buffer: &[u8]) -> ImageResult { - let format = free_functions::guess_format(buffer)?; - load_from_memory_with_format(buffer, format) -} - -/// Create a new image from a byte slice -/// -/// This is just a simple wrapper that constructs an `std::io::Cursor` around the buffer and then -/// calls `load` with that reader. -/// -/// Try [`io::Reader`] for more advanced uses. -/// -/// [`load`]: fn.load.html -/// [`io::Reader`]: io/struct.Reader.html -#[inline(always)] -pub fn load_from_memory_with_format(buf: &[u8], format: ImageFormat) -> ImageResult { - let b = io::Cursor::new(buf); - free_functions::load(b, format) -} - -#[cfg(test)] -mod bench { - #[bench] - #[cfg(feature = "benchmarks")] - fn bench_conversion(b: &mut test::Bencher) { - let a = super::DynamicImage::ImageRgb8(crate::ImageBuffer::new(1000, 1000)); - b.iter(|| a.to_luma8()); - b.bytes = 1000 * 1000 * 3 - } -} - -#[cfg(test)] -mod test { - use crate::color::ColorType; - - #[test] - fn test_empty_file() { - assert!(super::load_from_memory(b"").is_err()); - } - - #[cfg(feature = "jpeg")] - #[test] - fn image_dimensions() { - let im_path = "./tests/images/jpg/progressive/cat.jpg"; - let dims = super::image_dimensions(im_path).unwrap(); - assert_eq!(dims, (320, 240)); - } - - #[cfg(feature = "png")] - #[test] - fn open_16bpc_png() { - let im_path = "./tests/images/png/16bpc/basn6a16.png"; - let image = super::open(im_path).unwrap(); - assert_eq!(image.color(), super::color::ColorType::Rgba16); - } - - fn test_grayscale(mut img: super::DynamicImage, alpha_discarded: bool) { - use crate::image::{GenericImage, GenericImageView}; - img.put_pixel(0, 0, crate::color::Rgba([255, 0, 0, 100])); - let expected_alpha = if alpha_discarded { 255 } else { 100 }; - assert_eq!( - img.grayscale().get_pixel(0, 0), - crate::color::Rgba([54, 54, 54, expected_alpha]) - ); - } - - fn test_grayscale_alpha_discarded(img: super::DynamicImage) { - test_grayscale(img, true); - } - - fn test_grayscale_alpha_preserved(img: super::DynamicImage) { - test_grayscale(img, false); - } - - #[test] - fn test_grayscale_luma8() { - test_grayscale_alpha_discarded(super::DynamicImage::new_luma8(1, 1)); - test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::L8)); - } - - #[test] - fn test_grayscale_luma_a8() { - test_grayscale_alpha_preserved(super::DynamicImage::new_luma_a8(1, 1)); - test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::La8)); - } - - #[test] - fn test_grayscale_rgb8() { - test_grayscale_alpha_discarded(super::DynamicImage::new_rgb8(1, 1)); - test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb8)); - } - - #[test] - fn test_grayscale_rgba8() { - test_grayscale_alpha_preserved(super::DynamicImage::new_rgba8(1, 1)); - test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba8)); - } - - #[test] - fn test_grayscale_luma16() { - test_grayscale_alpha_discarded(super::DynamicImage::new_luma16(1, 1)); - test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::L16)); - } - - #[test] - fn test_grayscale_luma_a16() { - test_grayscale_alpha_preserved(super::DynamicImage::new_luma_a16(1, 1)); - test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::La16)); - } - - #[test] - fn test_grayscale_rgb16() { - test_grayscale_alpha_discarded(super::DynamicImage::new_rgb16(1, 1)); - test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb16)); - } - - #[test] - fn test_grayscale_rgba16() { - test_grayscale_alpha_preserved(super::DynamicImage::new_rgba16(1, 1)); - test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba16)); - } - - #[test] - fn test_grayscale_rgb32f() { - test_grayscale_alpha_discarded(super::DynamicImage::new_rgb32f(1, 1)); - test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb32F)); - } - - #[test] - fn test_grayscale_rgba32f() { - test_grayscale_alpha_preserved(super::DynamicImage::new_rgba32f(1, 1)); - test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba32F)); - } - - #[test] - fn test_dynamic_image_default_implementation() { - // Test that structs wrapping a DynamicImage are able to auto-derive the Default trait - // ensures that DynamicImage implements Default (if it didn't, this would cause a compile error). - #[derive(Default)] - struct Foo { - _image: super::DynamicImage, - } - } - - #[test] - fn test_to_vecu8() { - let _ = super::DynamicImage::new_luma8(1, 1).into_bytes(); - let _ = super::DynamicImage::new_luma16(1, 1).into_bytes(); - } - - #[test] - fn issue_1705_can_turn_16bit_image_into_bytes() { - let pixels = vec![65535u16; 64 * 64]; - let img = super::ImageBuffer::from_vec(64, 64, pixels).unwrap(); - - let img = super::DynamicImage::ImageLuma16(img); - assert!(img.as_luma16().is_some()); - - let bytes: Vec = img.into_bytes(); - assert_eq!(bytes, vec![0xFF; 64 * 64 * 2]); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -13,11 +13,12 @@ //! //! [`ImageError`]: enum.ImageError.html +use std::collections::TryReserveError; use std::error::Error; use std::{fmt, io}; use crate::color::ExtendedColorType; -use crate::image::ImageFormat; +use crate::{metadata::Cicp, ImageFormat}; /// The generic error type for image operations. /// @@ -81,6 +82,10 @@ pub enum UnsupportedErrorKind { /// The required color type can not be handled. Color(ExtendedColorType), + /// Dealing with an intricate layout is not implemented for an algorithm. + ColorLayout(ExtendedColorType), + /// The colors or transfer function of the CICP are not supported. + ColorspaceCicp(Cicp), /// An image format is not supported. Format(ImageFormatHint), /// Some feature specified by string. @@ -120,11 +125,20 @@ DimensionMismatch, /// Repeated an operation for which error that could not be cloned was emitted already. FailedAlready, + /// The cicp is required to be RGB-like but had other matrix transforms or narrow range. + RgbCicpRequired(Cicp), /// A string describing the parameter. /// This is discouraged and is likely to get deprecated (but not removed). Generic(String), /// The end of the image has been reached. NoMoreData, + /// An operation expected a concrete color space but another was found. + CicpMismatch { + /// The cicp that was expected. + expected: Cicp, + /// The cicp that was found. + found: Cicp, + }, } /// An error was encountered while decoding an image. @@ -166,9 +180,9 @@ /// The specified strict limits are not supported for this operation Unsupported { /// The given limits - limits: crate::io::Limits, + limits: crate::Limits, /// The supported strict limits - supported: crate::io::LimitSupport, + supported: crate::LimitSupport, }, } @@ -194,16 +208,19 @@ /// /// If the operation was not connected to a particular image format then the hint may be /// `Unknown`. + #[must_use] pub fn from_format_and_kind(format: ImageFormatHint, kind: UnsupportedErrorKind) -> Self { UnsupportedError { format, kind } } /// Returns the corresponding `UnsupportedErrorKind` of the error. + #[must_use] pub fn kind(&self) -> UnsupportedErrorKind { self.kind.clone() } /// Returns the image format associated with this error. + #[must_use] pub fn format_hint(&self) -> ImageFormatHint { self.format.clone() } @@ -221,6 +238,7 @@ /// Create a `DecodingError` for an image format. /// /// The error will not contain any further information but is very easy to create. + #[must_use] pub fn from_format_hint(format: ImageFormatHint) -> Self { DecodingError { format, @@ -229,6 +247,7 @@ } /// Returns the image format associated with this error. + #[must_use] pub fn format_hint(&self) -> ImageFormatHint { self.format.clone() } @@ -246,6 +265,7 @@ /// Create an `EncodingError` for an image format. /// /// The error will not contain any further information but is very easy to create. + #[must_use] pub fn from_format_hint(format: ImageFormatHint) -> Self { EncodingError { format, @@ -254,6 +274,7 @@ } /// Return the image format associated with this error. + #[must_use] pub fn format_hint(&self) -> ImageFormatHint { self.format.clone() } @@ -261,6 +282,7 @@ impl ParameterError { /// Construct a `ParameterError` directly from a corresponding kind. + #[must_use] pub fn from_kind(kind: ParameterErrorKind) -> Self { ParameterError { kind, @@ -269,6 +291,7 @@ } /// Returns the corresponding `ParameterErrorKind` of the error. + #[must_use] pub fn kind(&self) -> ParameterErrorKind { self.kind.clone() } @@ -276,22 +299,36 @@ impl LimitError { /// Construct a generic `LimitError` directly from a corresponding kind. + #[must_use] pub fn from_kind(kind: LimitErrorKind) -> Self { LimitError { kind } } /// Returns the corresponding `LimitErrorKind` of the error. + #[must_use] pub fn kind(&self) -> LimitErrorKind { self.kind.clone() } } +impl From for LimitError { + fn from(kind: LimitErrorKind) -> Self { + Self { kind } + } +} + impl From for ImageError { fn from(err: io::Error) -> ImageError { ImageError::IoError(err) } } +impl From for ImageError { + fn from(_: TryReserveError) -> ImageError { + ImageError::Limits(LimitErrorKind::InsufficientMemory.into()) + } +} + impl From for ImageFormatHint { fn from(format: ImageFormat) -> Self { ImageFormatHint::Exact(format) @@ -353,27 +390,32 @@ } UnsupportedErrorKind::Format(format @ ImageFormatHint::PathExtension(_)) => write!( fmt, - "The file extension {} was not recognized as an image format", - format, + "The file extension {format} was not recognized as an image format", ), UnsupportedErrorKind::Format(format) => { - write!(fmt, "The image format {} is not supported", format,) + write!(fmt, "The image format {format} is not supported",) } UnsupportedErrorKind::Color(color) => write!( fmt, - "The decoder for {} does not support the color type `{:?}`", + "The encoder or decoder for {} does not support the color type `{:?}`", self.format, color, ), + UnsupportedErrorKind::ColorLayout(layout) => write!( + fmt, + "Converting with the texel memory layout {layout:?} is not supported", + ), + UnsupportedErrorKind::ColorspaceCicp(color) => write!( + fmt, + "The colorimetric interpretation of a CICP color space is not supported for `{color:?}`", + ), UnsupportedErrorKind::GenericFeature(message) => match &self.format { ImageFormatHint::Unknown => write!( fmt, - "The decoder does not support the format feature {}", - message, + "The decoder does not support the format feature {message}", ), other => write!( fmt, - "The decoder for {} does not support the format features {}", - other, message, + "The decoder for {other} does not support the format features {message}", ), }, } @@ -394,14 +436,24 @@ fmt, "The end the image stream has been reached due to a previous error" ), + ParameterErrorKind::RgbCicpRequired(cicp) => { + write!(fmt, "The CICP {cicp:?} can not be used for RGB images",) + } + ParameterErrorKind::Generic(message) => { - write!(fmt, "The parameter is malformed: {}", message,) + write!(fmt, "The parameter is malformed: {message}",) } ParameterErrorKind::NoMoreData => write!(fmt, "The end of the image has been reached",), + ParameterErrorKind::CicpMismatch { expected, found } => { + write!( + fmt, + "The color space {found:?} does not match the expected {expected:?}", + ) + } }?; if let Some(underlying) = &self.underlying { - write!(fmt, "\n{}", underlying)?; + write!(fmt, "\n{underlying}")?; } Ok(()) @@ -480,22 +532,58 @@ impl fmt::Display for ImageFormatHint { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - ImageFormatHint::Exact(format) => write!(fmt, "{:?}", format), - ImageFormatHint::Name(name) => write!(fmt, "`{}`", name), - ImageFormatHint::PathExtension(ext) => write!(fmt, "`.{:?}`", ext), + ImageFormatHint::Exact(format) => write!(fmt, "{format:?}"), + ImageFormatHint::Name(name) => write!(fmt, "`{name}`"), + ImageFormatHint::PathExtension(ext) => write!(fmt, "`.{ext:?}`"), ImageFormatHint::Unknown => write!(fmt, "`Unknown`"), } } } +/// Converting [`ExtendedColorType`] to [`ColorType`][`crate::ColorType`] failed. +/// +/// This type is convertible to [`ImageError`] as [`ImageError::Unsupported`]. +#[derive(Clone)] +#[allow(missing_copy_implementations)] +pub struct TryFromExtendedColorError { + pub(crate) was: ExtendedColorType, +} + +impl fmt::Debug for TryFromExtendedColorError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Display for TryFromExtendedColorError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "The pixel layout {:?} is not supported as a buffer ColorType", + self.was + ) + } +} + +impl Error for TryFromExtendedColorError {} + +impl From for ImageError { + fn from(err: TryFromExtendedColorError) -> ImageError { + ImageError::Unsupported(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::Color(err.was), + )) + } +} + #[cfg(test)] mod tests { use super::*; - use std::mem; + use std::mem::size_of; #[allow(dead_code)] // This will fail to compile if the size of this type is large. - const ASSERT_SMALLISH: usize = [0][(mem::size_of::() >= 200) as usize]; + const ASSERT_SMALLISH: usize = [0][(size_of::() >= 200) as usize]; #[test] fn test_send_sync_stability() { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/flat.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/flat.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/flat.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/flat.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1738 +0,0 @@ -//! Image representations for ffi. -//! -//! # Usage -//! -//! Imagine you want to offer a very simple ffi interface: The caller provides an image buffer and -//! your program creates a thumbnail from it and dumps that image as `png`. This module is designed -//! to help you transition from raw memory data to Rust representation. -//! -//! ```no_run -//! use std::ptr; -//! use std::slice; -//! use image::Rgb; -//! use image::flat::{FlatSamples, SampleLayout}; -//! use image::imageops::thumbnail; -//! -//! #[no_mangle] -//! pub extern "C" fn store_rgb8_compressed( -//! data: *const u8, len: usize, -//! layout: *const SampleLayout -//! ) -//! -> bool -//! { -//! let samples = unsafe { slice::from_raw_parts(data, len) }; -//! let layout = unsafe { ptr::read(layout) }; -//! -//! let buffer = FlatSamples { -//! samples, -//! layout, -//! color_hint: None, -//! }; -//! -//! let view = match buffer.as_view::>() { -//! Err(_) => return false, // Invalid layout. -//! Ok(view) => view, -//! }; -//! -//! thumbnail(&view, 64, 64) -//! .save("output.png") -//! .map(|_| true) -//! .unwrap_or_else(|_| false) -//! } -//! ``` -//! -use std::marker::PhantomData; -use std::ops::{Deref, Index, IndexMut}; -use std::{cmp, error, fmt}; - -use num_traits::Zero; - -use crate::color::ColorType; -use crate::error::{ - DecodingError, ImageError, ImageFormatHint, ParameterError, ParameterErrorKind, - UnsupportedError, UnsupportedErrorKind, -}; -use crate::image::{GenericImage, GenericImageView}; -use crate::traits::Pixel; -use crate::ImageBuffer; - -/// A flat buffer over a (multi channel) image. -/// -/// In contrast to `ImageBuffer`, this representation of a sample collection is much more lenient -/// in the layout thereof. It also allows grouping by color planes instead of by pixel as long as -/// the strides of each extent are constant. This struct itself has no invariants on the strides -/// but not every possible configuration can be interpreted as a [`GenericImageView`] or -/// [`GenericImage`]. The methods [`as_view`] and [`as_view_mut`] construct the actual implementors -/// of these traits and perform necessary checks. To manually perform this and other layout checks -/// use [`is_normal`] or [`has_aliased_samples`]. -/// -/// Instances can be constructed not only by hand. The buffer instances returned by library -/// functions such as [`ImageBuffer::as_flat_samples`] guarantee that the conversion to a generic -/// image or generic view succeeds. A very different constructor is [`with_monocolor`]. It uses a -/// single pixel as the backing storage for an arbitrarily sized read-only raster by mapping each -/// pixel to the same samples by setting some strides to `0`. -/// -/// [`GenericImage`]: ../trait.GenericImage.html -/// [`GenericImageView`]: ../trait.GenericImageView.html -/// [`ImageBuffer::as_flat_samples`]: ../struct.ImageBuffer.html#method.as_flat_samples -/// [`is_normal`]: #method.is_normal -/// [`has_aliased_samples`]: #method.has_aliased_samples -/// [`as_view`]: #method.as_view -/// [`as_view_mut`]: #method.as_view_mut -/// [`with_monocolor`]: #method.with_monocolor -#[derive(Clone, Debug)] -pub struct FlatSamples { - /// Underlying linear container holding sample values. - pub samples: Buffer, - - /// A `repr(C)` description of the layout of buffer samples. - pub layout: SampleLayout, - - /// Supplementary color information. - /// - /// You may keep this as `None` in most cases. This is NOT checked in `View` or other - /// converters. It is intended mainly as a way for types that convert to this buffer type to - /// attach their otherwise static color information. A dynamic image representation could - /// however use this to resolve representational ambiguities such as the order of RGB channels. - pub color_hint: Option, -} - -/// A ffi compatible description of a sample buffer. -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct SampleLayout { - /// The number of channels in the color representation of the image. - pub channels: u8, - - /// Add this to an index to get to the sample in the next channel. - pub channel_stride: usize, - - /// The width of the represented image. - pub width: u32, - - /// Add this to an index to get to the next sample in x-direction. - pub width_stride: usize, - - /// The height of the represented image. - pub height: u32, - - /// Add this to an index to get to the next sample in y-direction. - pub height_stride: usize, -} - -/// Helper struct for an unnamed (stride, length) pair. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -struct Dim(usize, usize); - -impl SampleLayout { - /// Describe a row-major image packed in all directions. - /// - /// The resulting will surely be `NormalForm::RowMajorPacked`. It can therefore be converted to - /// safely to an `ImageBuffer` with a large enough underlying buffer. - /// - /// ``` - /// # use image::flat::{NormalForm, SampleLayout}; - /// let layout = SampleLayout::row_major_packed(3, 640, 480); - /// assert!(layout.is_normal(NormalForm::RowMajorPacked)); - /// ``` - /// - /// # Panics - /// - /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride - /// in the `height` direction would be larger than `usize::max_value()`. On other platforms - /// where it can surely accommodate `u8::max_value() * u32::max_value(), this can never happen. - pub fn row_major_packed(channels: u8, width: u32, height: u32) -> Self { - let height_stride = (channels as usize).checked_mul(width as usize).expect( - "Row major packed image can not be described because it does not fit into memory", - ); - SampleLayout { - channels, - channel_stride: 1, - width, - width_stride: channels as usize, - height, - height_stride, - } - } - - /// Describe a column-major image packed in all directions. - /// - /// The resulting will surely be `NormalForm::ColumnMajorPacked`. This is not particularly - /// useful for conversion but can be used to describe such a buffer without pitfalls. - /// - /// ``` - /// # use image::flat::{NormalForm, SampleLayout}; - /// let layout = SampleLayout::column_major_packed(3, 640, 480); - /// assert!(layout.is_normal(NormalForm::ColumnMajorPacked)); - /// ``` - /// - /// # Panics - /// - /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride - /// in the `width` direction would be larger than `usize::max_value()`. On other platforms - /// where it can surely accommodate `u8::max_value() * u32::max_value(), this can never happen. - pub fn column_major_packed(channels: u8, width: u32, height: u32) -> Self { - let width_stride = (channels as usize).checked_mul(height as usize).expect( - "Column major packed image can not be described because it does not fit into memory", - ); - SampleLayout { - channels, - channel_stride: 1, - height, - height_stride: channels as usize, - width, - width_stride, - } - } - - /// Get the strides for indexing matrix-like `[(c, w, h)]`. - /// - /// For a row-major layout with grouped samples, this tuple is strictly - /// increasing. - pub fn strides_cwh(&self) -> (usize, usize, usize) { - (self.channel_stride, self.width_stride, self.height_stride) - } - - /// Get the dimensions `(channels, width, height)`. - /// - /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be - /// before width and height. - pub fn extents(&self) -> (usize, usize, usize) { - ( - self.channels as usize, - self.width as usize, - self.height as usize, - ) - } - - /// Tuple of bounds in the order of coordinate inputs. - /// - /// This function should be used whenever working with image coordinates opposed to buffer - /// coordinates. The only difference compared to `extents` is the output type. - pub fn bounds(&self) -> (u8, u32, u32) { - (self.channels, self.width, self.height) - } - - /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. - /// - /// This method will allow zero strides, allowing compact representations of monochrome images. - /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no - /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the - /// other cases, the reasoning is slightly more involved. - /// - /// # Explanation - /// - /// Note that there is a difference between `min_length` and the index of the sample - /// 'one-past-the-end`. This is due to strides that may be larger than the dimension below. - /// - /// ## Example with holes - /// - /// Let's look at an example of a grayscale image with - /// * `width_stride = 1` - /// * `width = 2` - /// * `height_stride = 3` - /// * `height = 2` - /// - /// ```text - /// | x x | x x m | $ - /// min_length m ^ - /// ^ one-past-the-end $ - /// ``` - /// - /// The difference is also extreme for empty images with large strides. The one-past-the-end - /// sample index is still as large as the largest of these strides while `min_length = 0`. - /// - /// ## Example with aliasing - /// - /// The concept gets even more important when you allow samples to alias each other. Here we - /// have the buffer of a small grayscale image where this is the case, this time we will first - /// show the buffer and then the individual rows below. - /// - /// * `width_stride = 1` - /// * `width = 3` - /// * `height_stride = 2` - /// * `height = 2` - /// - /// ```text - /// 1 2 3 4 5 m - /// |1 2 3| row one - /// |3 4 5| row two - /// ^ m min_length - /// ^ ??? one-past-the-end - /// ``` - /// - /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its - /// dimension. That still points inside the image because `height*height_stride = 4` but also - /// `index_of(1, 2) = 4`. - pub fn min_length(&self) -> Option { - if self.width == 0 || self.height == 0 || self.channels == 0 { - return Some(0); - } - - self.index(self.channels - 1, self.width - 1, self.height - 1) - .and_then(|idx| idx.checked_add(1)) - } - - /// Check if a buffer of length `len` is large enough. - pub fn fits(&self, len: usize) -> bool { - self.min_length().map(|min| len >= min).unwrap_or(false) - } - - /// The extents of this array, in order of increasing strides. - fn increasing_stride_dims(&self) -> [Dim; 3] { - // Order extents by strides, then check that each is less equal than the next stride. - let mut grouped: [Dim; 3] = [ - Dim(self.channel_stride, self.channels as usize), - Dim(self.width_stride, self.width as usize), - Dim(self.height_stride, self.height as usize), - ]; - - grouped.sort(); - - let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); - assert!(min_dim.stride() <= mid_dim.stride() && mid_dim.stride() <= max_dim.stride()); - - grouped - } - - /// If there are any samples aliasing each other. - /// - /// If this is not the case, it would always be safe to allow mutable access to two different - /// samples at the same time. Otherwise, this operation would need additional checks. When one - /// dimension overflows `usize` with its stride we also consider this aliasing. - pub fn has_aliased_samples(&self) -> bool { - let grouped = self.increasing_stride_dims(); - let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); - - let min_size = match min_dim.checked_len() { - None => return true, - Some(size) => size, - }; - - let mid_size = match mid_dim.checked_len() { - None => return true, - Some(size) => size, - }; - - match max_dim.checked_len() { - None => return true, - Some(_) => (), // Only want to know this didn't overflow. - }; - - // Each higher dimension must walk over all of one lower dimension. - min_size > mid_dim.stride() || mid_size > max_dim.stride() - } - - /// Check if a buffer fulfills the requirements of a normal form. - /// - /// Certain conversions have preconditions on the structure of the sample buffer that are not - /// captured (by design) by the type system. These are then checked before the conversion. Such - /// checks can all be done in constant time and will not inspect the buffer content. You can - /// perform these checks yourself when the conversion is not required at this moment but maybe - /// still performed later. - pub fn is_normal(&self, form: NormalForm) -> bool { - if self.has_aliased_samples() { - return false; - } - - if form >= NormalForm::PixelPacked && self.channel_stride != 1 { - return false; - } - - if form >= NormalForm::ImagePacked { - // has aliased already checked for overflows. - let grouped = self.increasing_stride_dims(); - let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); - - if 1 != min_dim.stride() { - return false; - } - - if min_dim.len() != mid_dim.stride() { - return false; - } - - if mid_dim.len() != max_dim.stride() { - return false; - } - } - - if form >= NormalForm::RowMajorPacked { - if self.width_stride != self.channels as usize { - return false; - } - - if self.width as usize * self.width_stride != self.height_stride { - return false; - } - } - - if form >= NormalForm::ColumnMajorPacked { - if self.height_stride != self.channels as usize { - return false; - } - - if self.height as usize * self.height_stride != self.width_stride { - return false; - } - } - - true - } - - /// Check that the pixel and the channel index are in bounds. - /// - /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a - /// buffer index does not overflow. However, if such a buffer large enough to hold all samples - /// actually exists in memory, this property of course follows. - pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool { - channel < self.channels && x < self.width && y < self.height - } - - /// Resolve the index of a particular sample. - /// - /// `None` if the index is outside the bounds or does not fit into a `usize`. - pub fn index(&self, channel: u8, x: u32, y: u32) -> Option { - if !self.in_bounds(channel, x, y) { - return None; - } - - self.index_ignoring_bounds(channel as usize, x as usize, y as usize) - } - - /// Get the theoretical position of sample (channel, x, y). - /// - /// The 'check' is for overflow during index calculation, not that it is contained in the - /// image. Two samples may return the same index, even when one of them is out of bounds. This - /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image. - pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option { - let idx_c = channel.checked_mul(self.channel_stride); - let idx_x = x.checked_mul(self.width_stride); - let idx_y = y.checked_mul(self.height_stride); - - let (idx_c, idx_x, idx_y) = match (idx_c, idx_x, idx_y) { - (Some(idx_c), Some(idx_x), Some(idx_y)) => (idx_c, idx_x, idx_y), - _ => return None, - }; - - Some(0usize) - .and_then(|b| b.checked_add(idx_c)) - .and_then(|b| b.checked_add(idx_x)) - .and_then(|b| b.checked_add(idx_y)) - } - - /// Get an index provided it is inbouds. - /// - /// Assumes that the image is backed by some sufficiently large buffer. Then computation can - /// not overflow as we could represent the maximum coordinate. Since overflow is defined either - /// way, this method can not be unsafe. - /// - /// Behavior is *unspecified* if the index is out of bounds or this sample layout would require - /// a buffer larger than `isize::MAX` bytes. - pub fn in_bounds_index(&self, c: u8, x: u32, y: u32) -> usize { - let (c_stride, x_stride, y_stride) = self.strides_cwh(); - (y as usize * y_stride) + (x as usize * x_stride) + (c as usize * c_stride) - } - - /// Shrink the image to the minimum of current and given extents. - /// - /// This does not modify the strides, so that the resulting sample buffer may have holes - /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when - /// samples had aliased each other before. - pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) { - self.channels = self.channels.min(channels); - self.width = self.width.min(width); - self.height = self.height.min(height); - } -} - -impl Dim { - fn stride(self) -> usize { - self.0 - } - - /// Length of this dimension in memory. - fn checked_len(self) -> Option { - self.0.checked_mul(self.1) - } - - fn len(self) -> usize { - self.0 * self.1 - } -} - -impl FlatSamples { - /// Get the strides for indexing matrix-like `[(c, w, h)]`. - /// - /// For a row-major layout with grouped samples, this tuple is strictly - /// increasing. - pub fn strides_cwh(&self) -> (usize, usize, usize) { - self.layout.strides_cwh() - } - - /// Get the dimensions `(channels, width, height)`. - /// - /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be - /// before width and height. - pub fn extents(&self) -> (usize, usize, usize) { - self.layout.extents() - } - - /// Tuple of bounds in the order of coordinate inputs. - /// - /// This function should be used whenever working with image coordinates opposed to buffer - /// coordinates. The only difference compared to `extents` is the output type. - pub fn bounds(&self) -> (u8, u32, u32) { - self.layout.bounds() - } - - /// Get a reference based version. - pub fn as_ref(&self) -> FlatSamples<&[T]> - where - Buffer: AsRef<[T]>, - { - FlatSamples { - samples: self.samples.as_ref(), - layout: self.layout, - color_hint: self.color_hint, - } - } - - /// Get a mutable reference based version. - pub fn as_mut(&mut self) -> FlatSamples<&mut [T]> - where - Buffer: AsMut<[T]>, - { - FlatSamples { - samples: self.samples.as_mut(), - layout: self.layout, - color_hint: self.color_hint, - } - } - - /// Copy the data into an owned vector. - pub fn to_vec(&self) -> FlatSamples> - where - T: Clone, - Buffer: AsRef<[T]>, - { - FlatSamples { - samples: self.samples.as_ref().to_vec(), - layout: self.layout, - color_hint: self.color_hint, - } - } - - /// Get a reference to a single sample. - /// - /// This more restrictive than the method based on `std::ops::Index` but guarantees to properly - /// check all bounds and not panic as long as `Buffer::as_ref` does not do so. - /// - /// ``` - /// # use image::{RgbImage}; - /// let flat = RgbImage::new(480, 640).into_flat_samples(); - /// - /// // Get the blue channel at (10, 10). - /// assert!(flat.get_sample(1, 10, 10).is_some()); - /// - /// // There is no alpha channel. - /// assert!(flat.get_sample(3, 10, 10).is_none()); - /// ``` - /// - /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating - /// bounds checks with `min_length` in a type similar to `View`. Then you may use - /// `in_bounds_index` as a small speedup over the index calculation of this method which relies - /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample - /// coordinate is in fact backed by any memory buffer. - pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&T> - where - Buffer: AsRef<[T]>, - { - self.index(channel, x, y) - .and_then(|idx| self.samples.as_ref().get(idx)) - } - - /// Get a mutable reference to a single sample. - /// - /// This more restrictive than the method based on `std::ops::IndexMut` but guarantees to - /// properly check all bounds and not panic as long as `Buffer::as_ref` does not do so. - /// Contrary to conversion to `ViewMut`, this does not require that samples are packed since it - /// does not need to convert samples to a color representation. - /// - /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned - /// here can in fact modify more than the coordinate in the argument. - /// - /// ``` - /// # use image::{RgbImage}; - /// let mut flat = RgbImage::new(480, 640).into_flat_samples(); - /// - /// // Assign some new color to the blue channel at (10, 10). - /// *flat.get_mut_sample(1, 10, 10).unwrap() = 255; - /// - /// // There is no alpha channel. - /// assert!(flat.get_mut_sample(3, 10, 10).is_none()); - /// ``` - /// - /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating - /// bounds checks with `min_length` in a type similar to `View`. Then you may use - /// `in_bounds_index` as a small speedup over the index calculation of this method which relies - /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample - /// coordinate is in fact backed by any memory buffer. - pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut T> - where - Buffer: AsMut<[T]>, - { - match self.index(channel, x, y) { - None => None, - Some(idx) => self.samples.as_mut().get_mut(idx), - } - } - - /// View this buffer as an image over some type of pixel. - /// - /// This first ensures that all in-bounds coordinates refer to valid indices in the sample - /// buffer. It also checks that the specified pixel format expects the same number of channels - /// that are present in this buffer. Neither are larger nor a smaller number will be accepted. - /// There is no automatic conversion. - pub fn as_view

(&self) -> Result, Error> - where - P: Pixel, - Buffer: AsRef<[P::Subpixel]>, - { - if self.layout.channels != P::CHANNEL_COUNT { - return Err(Error::ChannelCountMismatch( - self.layout.channels, - P::CHANNEL_COUNT, - )); - } - - let as_ref = self.samples.as_ref(); - if !self.layout.fits(as_ref.len()) { - return Err(Error::TooLarge); - } - - Ok(View { - inner: FlatSamples { - samples: as_ref, - layout: self.layout, - color_hint: self.color_hint, - }, - phantom: PhantomData, - }) - } - - /// View this buffer but keep mutability at a sample level. - /// - /// This is similar to `as_view` but subtly different from `as_view_mut`. The resulting type - /// can be used as a `GenericImage` with the same prior invariants needed as for `as_view`. - /// It can not be used as a mutable `GenericImage` but does not need channels to be packed in - /// their pixel representation. - /// - /// This first ensures that all in-bounds coordinates refer to valid indices in the sample - /// buffer. It also checks that the specified pixel format expects the same number of channels - /// that are present in this buffer. Neither are larger nor a smaller number will be accepted. - /// There is no automatic conversion. - /// - /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned - /// for one sample can in fact modify other samples as well. Sometimes exactly this is - /// intended. - pub fn as_view_with_mut_samples

(&mut self) -> Result, Error> - where - P: Pixel, - Buffer: AsMut<[P::Subpixel]>, - { - if self.layout.channels != P::CHANNEL_COUNT { - return Err(Error::ChannelCountMismatch( - self.layout.channels, - P::CHANNEL_COUNT, - )); - } - - let as_mut = self.samples.as_mut(); - if !self.layout.fits(as_mut.len()) { - return Err(Error::TooLarge); - } - - Ok(View { - inner: FlatSamples { - samples: as_mut, - layout: self.layout, - color_hint: self.color_hint, - }, - phantom: PhantomData, - }) - } - - /// Interpret this buffer as a mutable image. - /// - /// To succeed, the pixels in this buffer may not alias each other and the samples of each - /// pixel must be packed (i.e. `channel_stride` is `1`). The number of channels must be - /// consistent with the channel count expected by the pixel format. - /// - /// This is similar to an `ImageBuffer` except it is a temporary view that is not normalized as - /// strongly. To get an owning version, consider copying the data into an `ImageBuffer`. This - /// provides many more operations, is possibly faster (if not you may want to open an issue) is - /// generally polished. You can also try to convert this buffer inline, see - /// `ImageBuffer::from_raw`. - pub fn as_view_mut

(&mut self) -> Result, Error> - where - P: Pixel, - Buffer: AsMut<[P::Subpixel]>, - { - if !self.layout.is_normal(NormalForm::PixelPacked) { - return Err(Error::NormalFormRequired(NormalForm::PixelPacked)); - } - - if self.layout.channels != P::CHANNEL_COUNT { - return Err(Error::ChannelCountMismatch( - self.layout.channels, - P::CHANNEL_COUNT, - )); - } - - let as_mut = self.samples.as_mut(); - if !self.layout.fits(as_mut.len()) { - return Err(Error::TooLarge); - } - - Ok(ViewMut { - inner: FlatSamples { - samples: as_mut, - layout: self.layout, - color_hint: self.color_hint, - }, - phantom: PhantomData, - }) - } - - /// View the samples as a slice. - /// - /// The slice is not limited to the region of the image and not all sample indices are valid - /// indices into this buffer. See `image_mut_slice` as an alternative. - pub fn as_slice(&self) -> &[T] - where - Buffer: AsRef<[T]>, - { - self.samples.as_ref() - } - - /// View the samples as a slice. - /// - /// The slice is not limited to the region of the image and not all sample indices are valid - /// indices into this buffer. See `image_mut_slice` as an alternative. - pub fn as_mut_slice(&mut self) -> &mut [T] - where - Buffer: AsMut<[T]>, - { - self.samples.as_mut() - } - - /// Return the portion of the buffer that holds sample values. - /// - /// This may fail when the coordinates in this image are either out-of-bounds of the underlying - /// buffer or can not be represented. Note that the slice may have holes that do not correspond - /// to any sample in the image represented by it. - pub fn image_slice(&self) -> Option<&[T]> - where - Buffer: AsRef<[T]>, - { - let min_length = match self.min_length() { - None => return None, - Some(index) => index, - }; - - let slice = self.samples.as_ref(); - if slice.len() < min_length { - return None; - } - - Some(&slice[..min_length]) - } - - /// Mutable portion of the buffer that holds sample values. - pub fn image_mut_slice(&mut self) -> Option<&mut [T]> - where - Buffer: AsMut<[T]>, - { - let min_length = match self.min_length() { - None => return None, - Some(index) => index, - }; - - let slice = self.samples.as_mut(); - if slice.len() < min_length { - return None; - } - - Some(&mut slice[..min_length]) - } - - /// Move the data into an image buffer. - /// - /// This does **not** convert the sample layout. The buffer needs to be in packed row-major form - /// before calling this function. In case of an error, returns the buffer again so that it does - /// not release any allocation. - pub fn try_into_buffer

(self) -> Result, (Error, Self)> - where - P: Pixel + 'static, - P::Subpixel: 'static, - Buffer: Deref, - { - if !self.is_normal(NormalForm::RowMajorPacked) { - return Err((Error::NormalFormRequired(NormalForm::RowMajorPacked), self)); - } - - if self.layout.channels != P::CHANNEL_COUNT { - return Err(( - Error::ChannelCountMismatch(self.layout.channels, P::CHANNEL_COUNT), - self, - )); - } - - if !self.fits(self.samples.deref().len()) { - return Err((Error::TooLarge, self)); - } - - Ok( - ImageBuffer::from_raw(self.layout.width, self.layout.height, self.samples) - .unwrap_or_else(|| { - panic!("Preconditions should have been ensured before conversion") - }), - ) - } - - /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. - /// - /// This method will allow zero strides, allowing compact representations of monochrome images. - /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no - /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the - /// other cases, the reasoning is slightly more involved. - /// - /// # Explanation - /// - /// Note that there is a difference between `min_length` and the index of the sample - /// 'one-past-the-end`. This is due to strides that may be larger than the dimension below. - /// - /// ## Example with holes - /// - /// Let's look at an example of a grayscale image with - /// * `width_stride = 1` - /// * `width = 2` - /// * `height_stride = 3` - /// * `height = 2` - /// - /// ```text - /// | x x | x x m | $ - /// min_length m ^ - /// ^ one-past-the-end $ - /// ``` - /// - /// The difference is also extreme for empty images with large strides. The one-past-the-end - /// sample index is still as large as the largest of these strides while `min_length = 0`. - /// - /// ## Example with aliasing - /// - /// The concept gets even more important when you allow samples to alias each other. Here we - /// have the buffer of a small grayscale image where this is the case, this time we will first - /// show the buffer and then the individual rows below. - /// - /// * `width_stride = 1` - /// * `width = 3` - /// * `height_stride = 2` - /// * `height = 2` - /// - /// ```text - /// 1 2 3 4 5 m - /// |1 2 3| row one - /// |3 4 5| row two - /// ^ m min_length - /// ^ ??? one-past-the-end - /// ``` - /// - /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its - /// dimension. That still points inside the image because `height*height_stride = 4` but also - /// `index_of(1, 2) = 4`. - pub fn min_length(&self) -> Option { - self.layout.min_length() - } - - /// Check if a buffer of length `len` is large enough. - pub fn fits(&self, len: usize) -> bool { - self.layout.fits(len) - } - - /// If there are any samples aliasing each other. - /// - /// If this is not the case, it would always be safe to allow mutable access to two different - /// samples at the same time. Otherwise, this operation would need additional checks. When one - /// dimension overflows `usize` with its stride we also consider this aliasing. - pub fn has_aliased_samples(&self) -> bool { - self.layout.has_aliased_samples() - } - - /// Check if a buffer fulfills the requirements of a normal form. - /// - /// Certain conversions have preconditions on the structure of the sample buffer that are not - /// captured (by design) by the type system. These are then checked before the conversion. Such - /// checks can all be done in constant time and will not inspect the buffer content. You can - /// perform these checks yourself when the conversion is not required at this moment but maybe - /// still performed later. - pub fn is_normal(&self, form: NormalForm) -> bool { - self.layout.is_normal(form) - } - - /// Check that the pixel and the channel index are in bounds. - /// - /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a - /// buffer index does not overflow. However, if such a buffer large enough to hold all samples - /// actually exists in memory, this property of course follows. - pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool { - self.layout.in_bounds(channel, x, y) - } - - /// Resolve the index of a particular sample. - /// - /// `None` if the index is outside the bounds or does not fit into a `usize`. - pub fn index(&self, channel: u8, x: u32, y: u32) -> Option { - self.layout.index(channel, x, y) - } - - /// Get the theoretical position of sample (x, y, channel). - /// - /// The 'check' is for overflow during index calculation, not that it is contained in the - /// image. Two samples may return the same index, even when one of them is out of bounds. This - /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image. - pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option { - self.layout.index_ignoring_bounds(channel, x, y) - } - - /// Get an index provided it is inbouds. - /// - /// Assumes that the image is backed by some sufficiently large buffer. Then computation can - /// not overflow as we could represent the maximum coordinate. Since overflow is defined either - /// way, this method can not be unsafe. - pub fn in_bounds_index(&self, channel: u8, x: u32, y: u32) -> usize { - self.layout.in_bounds_index(channel, x, y) - } - - /// Shrink the image to the minimum of current and given extents. - /// - /// This does not modify the strides, so that the resulting sample buffer may have holes - /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when - /// samples had aliased each other before. - pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) { - self.layout.shrink_to(channels, width, height) - } -} - -impl<'buf, Subpixel> FlatSamples<&'buf [Subpixel]> { - /// Create a monocolor image from a single pixel. - /// - /// This can be used as a very cheap source of a `GenericImageView` with an arbitrary number of - /// pixels of a single color, without any dynamic allocation. - /// - /// ## Examples - /// - /// ``` - /// # fn paint_something(_: T) {} - /// use image::{flat::FlatSamples, GenericImage, RgbImage, Rgb}; - /// - /// let background = Rgb([20, 20, 20]); - /// let bg = FlatSamples::with_monocolor(&background, 200, 200);; - /// - /// let mut image = RgbImage::new(200, 200); - /// paint_something(&mut image); - /// - /// // Reset the canvas - /// image.copy_from(&bg.as_view().unwrap(), 0, 0); - /// ``` - pub fn with_monocolor

(pixel: &'buf P, width: u32, height: u32) -> Self - where - P: Pixel, - Subpixel: crate::Primitive, - { - FlatSamples { - samples: pixel.channels(), - layout: SampleLayout { - channels: P::CHANNEL_COUNT, - channel_stride: 1, - width, - width_stride: 0, - height, - height_stride: 0, - }, - - // TODO this value is never set. It should be set in all places where the Pixel type implements PixelWithColorType - color_hint: None, - } - } -} - -/// A flat buffer that can be used as an image view. -/// -/// This is a nearly trivial wrapper around a buffer but at least sanitizes by checking the buffer -/// length first and constraining the pixel type. -/// -/// Note that this does not eliminate panics as the `AsRef<[T]>` implementation of `Buffer` may be -/// unreliable, i.e. return different buffers at different times. This of course is a non-issue for -/// all common collections where the bounds check once must be enough. -/// -/// # Inner invariants -/// -/// * For all indices inside bounds, the corresponding index is valid in the buffer -/// * `P::channel_count()` agrees with `self.inner.layout.channels` -/// -#[derive(Clone, Debug)] -pub struct View -where - Buffer: AsRef<[P::Subpixel]>, -{ - inner: FlatSamples, - phantom: PhantomData

, -} - -/// A mutable owning version of a flat buffer. -/// -/// While this wraps a buffer similar to `ImageBuffer`, this is mostly intended as a utility. The -/// library endorsed normalized representation is still `ImageBuffer`. Also, the implementation of -/// `AsMut<[P::Subpixel]>` must always yield the same buffer. Therefore there is no public way to -/// construct this with an owning buffer. -/// -/// # Inner invariants -/// -/// * For all indices inside bounds, the corresponding index is valid in the buffer -/// * There is no aliasing of samples -/// * The samples are packed, i.e. `self.inner.layout.sample_stride == 1` -/// * `P::channel_count()` agrees with `self.inner.layout.channels` -/// -#[derive(Clone, Debug)] -pub struct ViewMut -where - Buffer: AsMut<[P::Subpixel]>, -{ - inner: FlatSamples, - phantom: PhantomData

, -} - -/// Denotes invalid flat sample buffers when trying to convert to stricter types. -/// -/// The biggest use case being `ImageBuffer` which expects closely packed -/// samples in a row major matrix representation. But this error type may be -/// resused for other import functions. A more versatile user may also try to -/// correct the underlying representation depending on the error variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum Error { - /// The represented image was too large. - /// - /// The optional value denotes a possibly accepted maximal bound. - TooLarge, - - /// The represented image can not use this representation. - /// - /// Has an additional value of the normalized form that would be accepted. - NormalFormRequired(NormalForm), - - /// The color format did not match the channel count. - /// - /// In some cases you might be able to fix this by lowering the reported pixel count of the - /// buffer without touching the strides. - /// - /// In very special circumstances you *may* do the opposite. This is **VERY** dangerous but not - /// directly memory unsafe although that will likely alias pixels. One scenario is when you - /// want to construct an `Rgba` image but have only 3 bytes per pixel and for some reason don't - /// care about the value of the alpha channel even though you need `Rgba`. - ChannelCountMismatch(u8, u8), - - /// Deprecated - ChannelCountMismatch is used instead - WrongColor(ColorType), -} - -/// Different normal forms of buffers. -/// -/// A normal form is an unaliased buffer with some additional constraints. The `ÌmageBuffer` uses -/// row major form with packed samples. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum NormalForm { - /// No pixel aliases another. - /// - /// Unaliased also guarantees that all index calculations in the image bounds using - /// `dim_index*dim_stride` (such as `x*width_stride + y*height_stride`) do not overflow. - Unaliased, - - /// At least pixels are packed. - /// - /// Images of these types can wrap `[T]`-slices into the standard color types. This is a - /// precondition for `GenericImage` which requires by-reference access to pixels. - PixelPacked, - - /// All samples are packed. - /// - /// This is orthogonal to `PixelPacked`. It requires that there are no holes in the image but - /// it is not necessary that the pixel samples themselves are adjacent. An example of this - /// behaviour is a planar image layout. - ImagePacked, - - /// The samples are in row-major form and all samples are packed. - /// - /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is - /// in row-major form. - RowMajorPacked, - - /// The samples are in column-major form and all samples are packed. - /// - /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is - /// in column-major form. - ColumnMajorPacked, -} - -impl View -where - Buffer: AsRef<[P::Subpixel]>, -{ - /// Take out the sample buffer. - /// - /// Gives up the normalization invariants on the buffer format. - pub fn into_inner(self) -> FlatSamples { - self.inner - } - - /// Get a reference on the inner sample descriptor. - /// - /// There is no mutable counterpart as modifying the buffer format, including strides and - /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified - /// if the inner buffer is the same as the buffer of the image from which this view was - /// created. It might have been truncated as an optimization. - pub fn flat(&self) -> &FlatSamples { - &self.inner - } - - /// Get a reference on the inner buffer. - /// - /// There is no mutable counter part since it is not intended to allow you to reassign the - /// buffer or otherwise change its size or properties. - pub fn samples(&self) -> &Buffer { - &self.inner.samples - } - - /// Get a reference to a selected subpixel if it is in-bounds. - /// - /// This method will return `None` when the sample is out-of-bounds. All errors that could - /// occur due to overflow have been eliminated while construction the `View`. - pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel> { - if !self.inner.in_bounds(channel, x, y) { - return None; - } - - let index = self.inner.in_bounds_index(channel, x, y); - // Should always be `Some(_)` but checking is more costly. - self.samples().as_ref().get(index) - } - - /// Get a mutable reference to a selected subpixel if it is in-bounds. - /// - /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`. This - /// method will return `None` when the sample is out-of-bounds. All errors that could occur due - /// to overflow have been eliminated while construction the `View`. - /// - /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned - /// here can in fact modify more than the coordinate in the argument. - pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel> - where - Buffer: AsMut<[P::Subpixel]>, - { - if !self.inner.in_bounds(channel, x, y) { - return None; - } - - let index = self.inner.in_bounds_index(channel, x, y); - // Should always be `Some(_)` but checking is more costly. - self.inner.samples.as_mut().get_mut(index) - } - - /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. - /// - /// See `FlatSamples::min_length`. This method will always succeed. - pub fn min_length(&self) -> usize { - self.inner.min_length().unwrap() - } - - /// Return the portion of the buffer that holds sample values. - /// - /// While this can not fail–the validity of all coordinates has been validated during the - /// conversion from `FlatSamples`–the resulting slice may still contain holes. - pub fn image_slice(&self) -> &[P::Subpixel] { - &self.samples().as_ref()[..self.min_length()] - } - - /// Return the mutable portion of the buffer that holds sample values. - /// - /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`. While - /// this can not fail–the validity of all coordinates has been validated during the conversion - /// from `FlatSamples`–the resulting slice may still contain holes. - pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel] - where - Buffer: AsMut<[P::Subpixel]>, - { - let min_length = self.min_length(); - &mut self.inner.samples.as_mut()[..min_length] - } - - /// Shrink the inner image. - /// - /// The new dimensions will be the minimum of the previous dimensions. Since the set of - /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`. - /// Note that you can not change the number of channels as an intrinsic property of `P`. - pub fn shrink_to(&mut self, width: u32, height: u32) { - let channels = self.inner.layout.channels; - self.inner.shrink_to(channels, width, height) - } - - /// Try to convert this into an image with mutable pixels. - /// - /// The resulting image implements `GenericImage` in addition to `GenericImageView`. While this - /// has mutable samples, it does not enforce that pixel can not alias and that samples are - /// packed enough for a mutable pixel reference. This is slightly cheaper than the chain - /// `self.into_inner().as_view_mut()` and keeps the `View` alive on failure. - /// - /// ``` - /// # use image::RgbImage; - /// # use image::Rgb; - /// let mut buffer = RgbImage::new(480, 640).into_flat_samples(); - /// let view = buffer.as_view_with_mut_samples::>().unwrap(); - /// - /// // Inspect some pixels, … - /// - /// // Doesn't fail because it was originally an `RgbImage`. - /// let view_mut = view.try_upgrade().unwrap(); - /// ``` - pub fn try_upgrade(self) -> Result, (Error, Self)> - where - Buffer: AsMut<[P::Subpixel]>, - { - if !self.inner.is_normal(NormalForm::PixelPacked) { - return Err((Error::NormalFormRequired(NormalForm::PixelPacked), self)); - } - - // No length check or channel count check required, all the same. - Ok(ViewMut { - inner: self.inner, - phantom: PhantomData, - }) - } -} - -impl ViewMut -where - Buffer: AsMut<[P::Subpixel]>, -{ - /// Take out the sample buffer. - /// - /// Gives up the normalization invariants on the buffer format. - pub fn into_inner(self) -> FlatSamples { - self.inner - } - - /// Get a reference on the sample buffer descriptor. - /// - /// There is no mutable counterpart as modifying the buffer format, including strides and - /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified - /// if the inner buffer is the same as the buffer of the image from which this view was - /// created. It might have been truncated as an optimization. - pub fn flat(&self) -> &FlatSamples { - &self.inner - } - - /// Get a reference on the inner buffer. - /// - /// There is no mutable counter part since it is not intended to allow you to reassign the - /// buffer or otherwise change its size or properties. However, its contents can be accessed - /// mutable through a slice with `image_mut_slice`. - pub fn samples(&self) -> &Buffer { - &self.inner.samples - } - - /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. - /// - /// See `FlatSamples::min_length`. This method will always succeed. - pub fn min_length(&self) -> usize { - self.inner.min_length().unwrap() - } - - /// Get a reference to a selected subpixel. - /// - /// This method will return `None` when the sample is out-of-bounds. All errors that could - /// occur due to overflow have been eliminated while construction the `View`. - pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel> - where - Buffer: AsRef<[P::Subpixel]>, - { - if !self.inner.in_bounds(channel, x, y) { - return None; - } - - let index = self.inner.in_bounds_index(channel, x, y); - // Should always be `Some(_)` but checking is more costly. - self.samples().as_ref().get(index) - } - - /// Get a mutable reference to a selected sample. - /// - /// This method will return `None` when the sample is out-of-bounds. All errors that could - /// occur due to overflow have been eliminated while construction the `View`. - pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel> { - if !self.inner.in_bounds(channel, x, y) { - return None; - } - - let index = self.inner.in_bounds_index(channel, x, y); - // Should always be `Some(_)` but checking is more costly. - self.inner.samples.as_mut().get_mut(index) - } - - /// Return the portion of the buffer that holds sample values. - /// - /// While this can not fail–the validity of all coordinates has been validated during the - /// conversion from `FlatSamples`–the resulting slice may still contain holes. - pub fn image_slice(&self) -> &[P::Subpixel] - where - Buffer: AsRef<[P::Subpixel]>, - { - &self.inner.samples.as_ref()[..self.min_length()] - } - - /// Return the mutable buffer that holds sample values. - pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel] { - let length = self.min_length(); - &mut self.inner.samples.as_mut()[..length] - } - - /// Shrink the inner image. - /// - /// The new dimensions will be the minimum of the previous dimensions. Since the set of - /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`. - /// Note that you can not change the number of channels as an intrinsic property of `P`. - pub fn shrink_to(&mut self, width: u32, height: u32) { - let channels = self.inner.layout.channels; - self.inner.shrink_to(channels, width, height) - } -} - -// The out-of-bounds panic for single sample access similar to `slice::index`. -#[inline(never)] -#[cold] -fn panic_cwh_out_of_bounds( - (c, x, y): (u8, u32, u32), - bounds: (u8, u32, u32), - strides: (usize, usize, usize), -) -> ! { - panic!( - "Sample coordinates {:?} out of sample matrix bounds {:?} with strides {:?}", - (c, x, y), - bounds, - strides - ) -} - -// The out-of-bounds panic for pixel access similar to `slice::index`. -#[inline(never)] -#[cold] -fn panic_pixel_out_of_bounds((x, y): (u32, u32), bounds: (u32, u32)) -> ! { - panic!("Image index {:?} out of bounds {:?}", (x, y), bounds) -} - -impl Index<(u8, u32, u32)> for FlatSamples -where - Buffer: Index, -{ - type Output = Buffer::Output; - - /// Return a reference to a single sample at specified coordinates. - /// - /// # Panics - /// - /// When the coordinates are out of bounds or the index calculation fails. - fn index(&self, (c, x, y): (u8, u32, u32)) -> &Self::Output { - let bounds = self.bounds(); - let strides = self.strides_cwh(); - let index = self - .index(c, x, y) - .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides)); - &self.samples[index] - } -} - -impl IndexMut<(u8, u32, u32)> for FlatSamples -where - Buffer: IndexMut, -{ - /// Return a mutable reference to a single sample at specified coordinates. - /// - /// # Panics - /// - /// When the coordinates are out of bounds or the index calculation fails. - fn index_mut(&mut self, (c, x, y): (u8, u32, u32)) -> &mut Self::Output { - let bounds = self.bounds(); - let strides = self.strides_cwh(); - let index = self - .index(c, x, y) - .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides)); - &mut self.samples[index] - } -} - -impl GenericImageView for View -where - Buffer: AsRef<[P::Subpixel]>, -{ - type Pixel = P; - - fn dimensions(&self) -> (u32, u32) { - (self.inner.layout.width, self.inner.layout.height) - } - - fn bounds(&self) -> (u32, u32, u32, u32) { - let (w, h) = self.dimensions(); - (0, w, 0, h) - } - - fn in_bounds(&self, x: u32, y: u32) -> bool { - let (w, h) = self.dimensions(); - x < w && y < h - } - - fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { - if !self.inner.in_bounds(0, x, y) { - panic_pixel_out_of_bounds((x, y), self.dimensions()) - } - - let image = self.inner.samples.as_ref(); - let base_index = self.inner.in_bounds_index(0, x, y); - let channels = P::CHANNEL_COUNT as usize; - - let mut buffer = [Zero::zero(); 256]; - buffer - .iter_mut() - .enumerate() - .take(channels) - .for_each(|(c, to)| { - let index = base_index + c * self.inner.layout.channel_stride; - *to = image[index]; - }); - - *P::from_slice(&buffer[..channels]) - } -} - -impl GenericImageView for ViewMut -where - Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>, -{ - type Pixel = P; - - fn dimensions(&self) -> (u32, u32) { - (self.inner.layout.width, self.inner.layout.height) - } - - fn bounds(&self) -> (u32, u32, u32, u32) { - let (w, h) = self.dimensions(); - (0, w, 0, h) - } - - fn in_bounds(&self, x: u32, y: u32) -> bool { - let (w, h) = self.dimensions(); - x < w && y < h - } - - fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { - if !self.inner.in_bounds(0, x, y) { - panic_pixel_out_of_bounds((x, y), self.dimensions()) - } - - let image = self.inner.samples.as_ref(); - let base_index = self.inner.in_bounds_index(0, x, y); - let channels = P::CHANNEL_COUNT as usize; - - let mut buffer = [Zero::zero(); 256]; - buffer - .iter_mut() - .enumerate() - .take(channels) - .for_each(|(c, to)| { - let index = base_index + c * self.inner.layout.channel_stride; - *to = image[index]; - }); - - *P::from_slice(&buffer[..channels]) - } -} - -impl GenericImage for ViewMut -where - Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>, -{ - fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel { - if !self.inner.in_bounds(0, x, y) { - panic_pixel_out_of_bounds((x, y), self.dimensions()) - } - - let base_index = self.inner.in_bounds_index(0, x, y); - let channel_count =

::CHANNEL_COUNT as usize; - let pixel_range = base_index..base_index + channel_count; - P::from_slice_mut(&mut self.inner.samples.as_mut()[pixel_range]) - } - - #[allow(deprecated)] - fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { - *self.get_pixel_mut(x, y) = pixel; - } - - #[allow(deprecated)] - fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { - self.get_pixel_mut(x, y).blend(&pixel); - } -} - -impl From for ImageError { - fn from(error: Error) -> ImageError { - #[derive(Debug)] - struct NormalFormRequiredError(NormalForm); - impl fmt::Display for NormalFormRequiredError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Required sample buffer in normal form {:?}", self.0) - } - } - impl error::Error for NormalFormRequiredError {} - - match error { - Error::TooLarge => ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - )), - Error::NormalFormRequired(form) => ImageError::Decoding(DecodingError::new( - ImageFormatHint::Unknown, - NormalFormRequiredError(form), - )), - Error::ChannelCountMismatch(_lc, _pc) => ImageError::Parameter( - ParameterError::from_kind(ParameterErrorKind::DimensionMismatch), - ), - Error::WrongColor(color) => { - ImageError::Unsupported(UnsupportedError::from_format_and_kind( - ImageFormatHint::Unknown, - UnsupportedErrorKind::Color(color.into()), - )) - } - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::TooLarge => write!(f, "The layout is too large"), - Error::NormalFormRequired(form) => write!( - f, - "The layout needs to {}", - match form { - NormalForm::ColumnMajorPacked => "be packed and in column major form", - NormalForm::ImagePacked => "be fully packed", - NormalForm::PixelPacked => "have packed pixels", - NormalForm::RowMajorPacked => "be packed and in row major form", - NormalForm::Unaliased => "not have any aliasing channels", - } - ), - Error::ChannelCountMismatch(layout_channels, pixel_channels) => write!( - f, - "The channel count of the chosen pixel (={}) does agree with the layout (={})", - pixel_channels, layout_channels - ), - Error::WrongColor(color) => write!( - f, - "The chosen color type does not match the hint {:?}", - color - ), - } - } -} - -impl error::Error for Error {} - -impl PartialOrd for NormalForm { - /// Compares the logical preconditions. - /// - /// `a < b` if the normal form `a` has less preconditions than `b`. - fn partial_cmp(&self, other: &Self) -> Option { - match (*self, *other) { - (NormalForm::Unaliased, NormalForm::Unaliased) => Some(cmp::Ordering::Equal), - (NormalForm::PixelPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Equal), - (NormalForm::ImagePacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Equal), - (NormalForm::RowMajorPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Equal), - (NormalForm::ColumnMajorPacked, NormalForm::ColumnMajorPacked) => { - Some(cmp::Ordering::Equal) - } - - (NormalForm::Unaliased, _) => Some(cmp::Ordering::Less), - (_, NormalForm::Unaliased) => Some(cmp::Ordering::Greater), - - (NormalForm::PixelPacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less), - (NormalForm::PixelPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less), - (NormalForm::RowMajorPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Greater), - (NormalForm::ColumnMajorPacked, NormalForm::PixelPacked) => { - Some(cmp::Ordering::Greater) - } - - (NormalForm::ImagePacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less), - (NormalForm::ImagePacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less), - (NormalForm::RowMajorPacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Greater), - (NormalForm::ColumnMajorPacked, NormalForm::ImagePacked) => { - Some(cmp::Ordering::Greater) - } - - (NormalForm::ImagePacked, NormalForm::PixelPacked) => None, - (NormalForm::PixelPacked, NormalForm::ImagePacked) => None, - (NormalForm::RowMajorPacked, NormalForm::ColumnMajorPacked) => None, - (NormalForm::ColumnMajorPacked, NormalForm::RowMajorPacked) => None, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::buffer_::GrayAlphaImage; - use crate::color::{LumaA, Rgb}; - - #[test] - fn aliasing_view() { - let buffer = FlatSamples { - samples: &[42], - layout: SampleLayout { - channels: 3, - channel_stride: 0, - width: 100, - width_stride: 0, - height: 100, - height_stride: 0, - }, - color_hint: None, - }; - - let view = buffer.as_view::>().expect("This is a valid view"); - let pixel_count = view - .pixels() - .inspect(|pixel| assert!(pixel.2 == Rgb([42, 42, 42]))) - .count(); - assert_eq!(pixel_count, 100 * 100); - } - - #[test] - fn mutable_view() { - let mut buffer = FlatSamples { - samples: [0; 18], - layout: SampleLayout { - channels: 2, - channel_stride: 1, - width: 3, - width_stride: 2, - height: 3, - height_stride: 6, - }, - color_hint: None, - }; - - { - let mut view = buffer - .as_view_mut::>() - .expect("This should be a valid mutable buffer"); - assert_eq!(view.dimensions(), (3, 3)); - #[allow(deprecated)] - for i in 0..9 { - *view.get_pixel_mut(i % 3, i / 3) = LumaA([2 * i as u16, 2 * i as u16 + 1]); - } - } - - buffer - .samples - .iter() - .enumerate() - .for_each(|(idx, sample)| assert_eq!(idx, *sample as usize)); - } - - #[test] - fn normal_forms() { - assert!(FlatSamples { - samples: [0u8; 0], - layout: SampleLayout { - channels: 2, - channel_stride: 1, - width: 3, - width_stride: 9, - height: 3, - height_stride: 28, - }, - color_hint: None, - } - .is_normal(NormalForm::PixelPacked)); - - assert!(FlatSamples { - samples: [0u8; 0], - layout: SampleLayout { - channels: 2, - channel_stride: 8, - width: 4, - width_stride: 1, - height: 2, - height_stride: 4, - }, - color_hint: None, - } - .is_normal(NormalForm::ImagePacked)); - - assert!(FlatSamples { - samples: [0u8; 0], - layout: SampleLayout { - channels: 2, - channel_stride: 1, - width: 4, - width_stride: 2, - height: 2, - height_stride: 8, - }, - color_hint: None, - } - .is_normal(NormalForm::RowMajorPacked)); - - assert!(FlatSamples { - samples: [0u8; 0], - layout: SampleLayout { - channels: 2, - channel_stride: 1, - width: 4, - width_stride: 4, - height: 2, - height_stride: 2, - }, - color_hint: None, - } - .is_normal(NormalForm::ColumnMajorPacked)); - } - - #[test] - fn image_buffer_conversion() { - let expected_layout = SampleLayout { - channels: 2, - channel_stride: 1, - width: 4, - width_stride: 2, - height: 2, - height_stride: 8, - }; - - let initial = GrayAlphaImage::new(expected_layout.width, expected_layout.height); - let buffer = initial.into_flat_samples(); - - assert_eq!(buffer.layout, expected_layout); - - let _: GrayAlphaImage = buffer.try_into_buffer().unwrap_or_else(|(error, _)| { - panic!("Expected buffer to be convertible but {:?}", error) - }); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/hooks.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/hooks.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/hooks.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/hooks.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +//! This module provides a way to register decoding hooks for image formats not directly supported +//! by this crate. + +use std::{ + collections::HashMap, + ffi::{OsStr, OsString}, + io::{BufRead, BufReader, Read, Seek}, + sync::RwLock, +}; + +use crate::{ImageDecoder, ImageResult}; + +pub(crate) trait ReadSeek: Read + Seek {} +impl ReadSeek for T {} + +pub(crate) static DECODING_HOOKS: RwLock>> = + RwLock::new(None); + +pub(crate) type DetectionHook = (&'static [u8], &'static [u8], OsString); +pub(crate) static GUESS_FORMAT_HOOKS: RwLock> = RwLock::new(Vec::new()); + +/// A wrapper around a type-erased trait object that implements `Read` and `Seek`. +pub struct GenericReader<'a>(pub(crate) BufReader>); +impl Read for GenericReader<'_> { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result { + self.0.read_vectored(bufs) + } + fn read_to_end(&mut self, buf: &mut Vec) -> std::io::Result { + self.0.read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> std::io::Result { + self.0.read_to_string(buf) + } + fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { + self.0.read_exact(buf) + } +} +impl BufRead for GenericReader<'_> { + fn fill_buf(&mut self) -> std::io::Result<&[u8]> { + self.0.fill_buf() + } + fn consume(&mut self, amt: usize) { + self.0.consume(amt) + } + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> std::io::Result { + self.0.read_until(byte, buf) + } + fn read_line(&mut self, buf: &mut String) -> std::io::Result { + self.0.read_line(buf) + } +} +impl Seek for GenericReader<'_> { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + self.0.seek(pos) + } + fn rewind(&mut self) -> std::io::Result<()> { + self.0.rewind() + } + fn stream_position(&mut self) -> std::io::Result { + self.0.stream_position() + } + + // TODO: Add `seek_relative` once MSRV is at least 1.80.0 +} + +/// A function to produce an `ImageDecoder` for a given image format. +pub type DecodingHook = + Box Fn(GenericReader<'a>) -> ImageResult> + Send + Sync>; + +/// Register a new decoding hook or returns false if one already exists for the given format. +pub fn register_decoding_hook(extension: OsString, hook: DecodingHook) -> bool { + let mut hooks = DECODING_HOOKS.write().unwrap(); + if hooks.is_none() { + *hooks = Some(HashMap::new()); + } + match hooks.as_mut().unwrap().entry(extension) { + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(hook); + true + } + std::collections::hash_map::Entry::Occupied(_) => false, + } +} + +/// Returns whether a decoding hook has been registered for the given format. +pub fn decoding_hook_registered(extension: &OsStr) -> bool { + DECODING_HOOKS + .read() + .unwrap() + .as_ref() + .map(|hooks| hooks.contains_key(extension)) + .unwrap_or(false) +} + +/// Registers a format detection hook. +/// +/// The signature field holds the magic bytes from the start of the file that must be matched to +/// detect the format. The mask field is optional and can be used to specify which bytes in the +/// signature should be ignored during the detection. +/// +/// # Examples +/// +/// ## Using the mask to ignore some bytes +/// +/// ``` +/// # use image::hooks::register_format_detection_hook; +/// // WebP signature is 'riff' followed by 4 bytes of length and then by 'webp'. +/// // This requires a mask to ignore the length. +/// register_format_detection_hook("webp".into(), +/// &[b'r', b'i', b'f', b'f', 0, 0, 0, 0, b'w', b'e', b'b', b'p'], +/// Some(&[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff]), +/// ); +/// ``` +/// +/// ## Multiple signatures +/// +/// ``` +/// # use image::hooks::register_format_detection_hook; +/// // JPEG XL has two different signatures: https://en.wikipedia.org/wiki/JPEG_XL +/// // This function should be called twice to register them both. +/// register_format_detection_hook("jxl".into(), &[0xff, 0x0a], None); +/// register_format_detection_hook("jxl".into(), +/// &[0x00, 0x00, 0x00, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0x0a, 0x87, 0x0a], None, +/// ); +/// ``` +/// +pub fn register_format_detection_hook( + extension: OsString, + signature: &'static [u8], + mask: Option<&'static [u8]>, +) { + GUESS_FORMAT_HOOKS + .write() + .unwrap() + .push((signature, mask.unwrap_or(&[]), extension)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/image.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/image.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/image.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2008 +0,0 @@ -#![allow(clippy::too_many_arguments)] -use std::ffi::OsStr; -use std::io; -use std::io::Read; -use std::ops::{Deref, DerefMut}; -use std::path::Path; -use std::usize; - -use crate::color::{ColorType, ExtendedColorType}; -use crate::error::{ - ImageError, ImageFormatHint, ImageResult, LimitError, LimitErrorKind, ParameterError, - ParameterErrorKind, -}; -use crate::math::Rect; -use crate::traits::Pixel; -use crate::ImageBuffer; - -use crate::animation::Frames; - -#[cfg(feature = "pnm")] -use crate::codecs::pnm::PnmSubtype; - -/// An enumeration of supported image formats. -/// Not all formats support both encoding and decoding. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -#[non_exhaustive] -pub enum ImageFormat { - /// An Image in PNG Format - Png, - - /// An Image in JPEG Format - Jpeg, - - /// An Image in GIF Format - Gif, - - /// An Image in WEBP Format - WebP, - - /// An Image in general PNM Format - Pnm, - - /// An Image in TIFF Format - Tiff, - - /// An Image in TGA Format - Tga, - - /// An Image in DDS Format - Dds, - - /// An Image in BMP Format - Bmp, - - /// An Image in ICO Format - Ico, - - /// An Image in Radiance HDR Format - Hdr, - - /// An Image in OpenEXR Format - OpenExr, - - /// An Image in farbfeld Format - Farbfeld, - - /// An Image in AVIF format. - Avif, - - /// An Image in QOI format. - Qoi, -} - -impl ImageFormat { - /// Return the image format specified by a path's file extension. - /// - /// # Example - /// - /// ``` - /// use image::ImageFormat; - /// - /// let format = ImageFormat::from_extension("jpg"); - /// assert_eq!(format, Some(ImageFormat::Jpeg)); - /// ``` - #[inline] - pub fn from_extension(ext: S) -> Option - where - S: AsRef, - { - // thin wrapper function to strip generics - fn inner(ext: &OsStr) -> Option { - let ext = ext.to_str()?.to_ascii_lowercase(); - - Some(match ext.as_str() { - "avif" => ImageFormat::Avif, - "jpg" | "jpeg" => ImageFormat::Jpeg, - "png" => ImageFormat::Png, - "gif" => ImageFormat::Gif, - "webp" => ImageFormat::WebP, - "tif" | "tiff" => ImageFormat::Tiff, - "tga" => ImageFormat::Tga, - "dds" => ImageFormat::Dds, - "bmp" => ImageFormat::Bmp, - "ico" => ImageFormat::Ico, - "hdr" => ImageFormat::Hdr, - "exr" => ImageFormat::OpenExr, - "pbm" | "pam" | "ppm" | "pgm" => ImageFormat::Pnm, - "ff" | "farbfeld" => ImageFormat::Farbfeld, - "qoi" => ImageFormat::Qoi, - _ => return None, - }) - } - - inner(ext.as_ref()) - } - - /// Return the image format specified by the path's file extension. - /// - /// # Example - /// - /// ``` - /// use image::ImageFormat; - /// - /// let format = ImageFormat::from_path("images/ferris.png")?; - /// assert_eq!(format, ImageFormat::Png); - /// - /// # Ok::<(), image::error::ImageError>(()) - /// ``` - #[inline] - pub fn from_path

(path: P) -> ImageResult - where - P: AsRef, - { - // thin wrapper function to strip generics - fn inner(path: &Path) -> ImageResult { - let exact_ext = path.extension(); - exact_ext - .and_then(ImageFormat::from_extension) - .ok_or_else(|| { - let format_hint = match exact_ext { - None => ImageFormatHint::Unknown, - Some(os) => ImageFormatHint::PathExtension(os.into()), - }; - ImageError::Unsupported(format_hint.into()) - }) - } - - inner(path.as_ref()) - } - - /// Return the image format specified by a MIME type. - /// - /// # Example - /// - /// ``` - /// use image::ImageFormat; - /// - /// let format = ImageFormat::from_mime_type("image/png").unwrap(); - /// assert_eq!(format, ImageFormat::Png); - /// ``` - pub fn from_mime_type(mime_type: M) -> Option - where - M: AsRef, - { - match mime_type.as_ref() { - "image/avif" => Some(ImageFormat::Avif), - "image/jpeg" => Some(ImageFormat::Jpeg), - "image/png" => Some(ImageFormat::Png), - "image/gif" => Some(ImageFormat::Gif), - "image/webp" => Some(ImageFormat::WebP), - "image/tiff" => Some(ImageFormat::Tiff), - "image/x-targa" | "image/x-tga" => Some(ImageFormat::Tga), - "image/vnd-ms.dds" => Some(ImageFormat::Dds), - "image/bmp" => Some(ImageFormat::Bmp), - "image/x-icon" => Some(ImageFormat::Ico), - "image/vnd.radiance" => Some(ImageFormat::Hdr), - "image/x-exr" => Some(ImageFormat::OpenExr), - "image/x-portable-bitmap" - | "image/x-portable-graymap" - | "image/x-portable-pixmap" - | "image/x-portable-anymap" => Some(ImageFormat::Pnm), - // Qoi's MIME type is being worked on. - // See: https://github.com/phoboslab/qoi/issues/167 - "image/x-qoi" => Some(ImageFormat::Qoi), - _ => None, - } - } - - /// Return the MIME type for this image format or "application/octet-stream" if no MIME type - /// exists for the format. - /// - /// Some notes on a few of the MIME types: - /// - /// - The portable anymap format has a separate MIME type for the pixmap, graymap and bitmap - /// formats, but this method returns the general "image/x-portable-anymap" MIME type. - /// - The Targa format has two common MIME types, "image/x-targa" and "image/x-tga"; this - /// method returns "image/x-targa" for that format. - /// - The QOI MIME type is still a work in progress. This method returns "image/x-qoi" for - /// that format. - /// - /// # Example - /// - /// ``` - /// use image::ImageFormat; - /// - /// let mime_type = ImageFormat::Png.to_mime_type(); - /// assert_eq!(mime_type, "image/png"); - /// ``` - pub fn to_mime_type(&self) -> &'static str { - match self { - ImageFormat::Avif => "image/avif", - ImageFormat::Jpeg => "image/jpeg", - ImageFormat::Png => "image/png", - ImageFormat::Gif => "image/gif", - ImageFormat::WebP => "image/webp", - ImageFormat::Tiff => "image/tiff", - // the targa MIME type has two options, but this one seems to be used more - ImageFormat::Tga => "image/x-targa", - ImageFormat::Dds => "image/vnd-ms.dds", - ImageFormat::Bmp => "image/bmp", - ImageFormat::Ico => "image/x-icon", - ImageFormat::Hdr => "image/vnd.radiance", - ImageFormat::OpenExr => "image/x-exr", - // return the most general MIME type - ImageFormat::Pnm => "image/x-portable-anymap", - // Qoi's MIME type is being worked on. - // See: https://github.com/phoboslab/qoi/issues/167 - ImageFormat::Qoi => "image/x-qoi", - // farbfield's MIME type taken from https://www.wikidata.org/wiki/Q28206109 - ImageFormat::Farbfeld => "application/octet-stream", - } - } - - /// Return if the ImageFormat can be decoded by the lib. - #[inline] - pub fn can_read(&self) -> bool { - // Needs to be updated once a new variant's decoder is added to free_functions.rs::load - match self { - ImageFormat::Png => true, - ImageFormat::Gif => true, - ImageFormat::Jpeg => true, - ImageFormat::WebP => true, - ImageFormat::Tiff => true, - ImageFormat::Tga => true, - ImageFormat::Dds => false, - ImageFormat::Bmp => true, - ImageFormat::Ico => true, - ImageFormat::Hdr => true, - ImageFormat::OpenExr => true, - ImageFormat::Pnm => true, - ImageFormat::Farbfeld => true, - ImageFormat::Avif => true, - ImageFormat::Qoi => true, - } - } - - /// Return if the ImageFormat can be encoded by the lib. - #[inline] - pub fn can_write(&self) -> bool { - // Needs to be updated once a new variant's encoder is added to free_functions.rs::save_buffer_with_format_impl - match self { - ImageFormat::Gif => true, - ImageFormat::Ico => true, - ImageFormat::Jpeg => true, - ImageFormat::Png => true, - ImageFormat::Bmp => true, - ImageFormat::Tiff => true, - ImageFormat::Tga => true, - ImageFormat::Pnm => true, - ImageFormat::Farbfeld => true, - ImageFormat::Avif => true, - ImageFormat::WebP => true, - ImageFormat::Hdr => false, - ImageFormat::OpenExr => true, - ImageFormat::Dds => false, - ImageFormat::Qoi => true, - } - } - - /// Return a list of applicable extensions for this format. - /// - /// All currently recognized image formats specify at least on extension but for future - /// compatibility you should not rely on this fact. The list may be empty if the format has no - /// recognized file representation, for example in case it is used as a purely transient memory - /// format. - /// - /// The method name `extensions` remains reserved for introducing another method in the future - /// that yields a slice of `OsStr` which is blocked by several features of const evaluation. - pub fn extensions_str(self) -> &'static [&'static str] { - match self { - ImageFormat::Png => &["png"], - ImageFormat::Jpeg => &["jpg", "jpeg"], - ImageFormat::Gif => &["gif"], - ImageFormat::WebP => &["webp"], - ImageFormat::Pnm => &["pbm", "pam", "ppm", "pgm"], - ImageFormat::Tiff => &["tiff", "tif"], - ImageFormat::Tga => &["tga"], - ImageFormat::Dds => &["dds"], - ImageFormat::Bmp => &["bmp"], - ImageFormat::Ico => &["ico"], - ImageFormat::Hdr => &["hdr"], - ImageFormat::OpenExr => &["exr"], - ImageFormat::Farbfeld => &["ff"], - // According to: https://aomediacodec.github.io/av1-avif/#mime-registration - ImageFormat::Avif => &["avif"], - ImageFormat::Qoi => &["qoi"], - } - } - - /// Return the ImageFormats which are enabled for reading. - #[inline] - pub fn reading_enabled(&self) -> bool { - match self { - ImageFormat::Png => cfg!(feature = "png"), - ImageFormat::Gif => cfg!(feature = "gif"), - ImageFormat::Jpeg => cfg!(feature = "jpeg"), - ImageFormat::WebP => cfg!(feature = "webp"), - ImageFormat::Tiff => cfg!(feature = "tiff"), - ImageFormat::Tga => cfg!(feature = "tga"), - ImageFormat::Bmp => cfg!(feature = "bmp"), - ImageFormat::Ico => cfg!(feature = "ico"), - ImageFormat::Hdr => cfg!(feature = "hdr"), - ImageFormat::OpenExr => cfg!(feature = "openexr"), - ImageFormat::Pnm => cfg!(feature = "pnm"), - ImageFormat::Farbfeld => cfg!(feature = "farbfeld"), - ImageFormat::Avif => cfg!(feature = "avif"), - ImageFormat::Qoi => cfg!(feature = "qoi"), - ImageFormat::Dds => false, - } - } - - /// Return the ImageFormats which are enabled for writing. - #[inline] - pub fn writing_enabled(&self) -> bool { - match self { - ImageFormat::Gif => cfg!(feature = "gif"), - ImageFormat::Ico => cfg!(feature = "ico"), - ImageFormat::Jpeg => cfg!(feature = "jpeg"), - ImageFormat::Png => cfg!(feature = "png"), - ImageFormat::Bmp => cfg!(feature = "bmp"), - ImageFormat::Tiff => cfg!(feature = "tiff"), - ImageFormat::Tga => cfg!(feature = "tga"), - ImageFormat::Pnm => cfg!(feature = "pnm"), - ImageFormat::Farbfeld => cfg!(feature = "farbfeld"), - ImageFormat::Avif => cfg!(feature = "avif"), - ImageFormat::WebP => cfg!(feature = "webp"), - ImageFormat::OpenExr => cfg!(feature = "openexr"), - ImageFormat::Qoi => cfg!(feature = "qoi"), - ImageFormat::Dds => false, - ImageFormat::Hdr => false, - } - } - - /// Return all ImageFormats - pub fn all() -> impl Iterator { - [ - ImageFormat::Gif, - ImageFormat::Ico, - ImageFormat::Jpeg, - ImageFormat::Png, - ImageFormat::Bmp, - ImageFormat::Tiff, - ImageFormat::Tga, - ImageFormat::Pnm, - ImageFormat::Farbfeld, - ImageFormat::Avif, - ImageFormat::WebP, - ImageFormat::OpenExr, - ImageFormat::Qoi, - ImageFormat::Dds, - ImageFormat::Hdr, - ] - .iter() - .copied() - } -} - -/// An enumeration of supported image formats for encoding. -#[derive(Clone, PartialEq, Eq, Debug)] -#[non_exhaustive] -pub enum ImageOutputFormat { - #[cfg(feature = "png")] - /// An Image in PNG Format - Png, - - #[cfg(feature = "jpeg")] - /// An Image in JPEG Format with specified quality, up to 100 - Jpeg(u8), - - #[cfg(feature = "pnm")] - /// An Image in one of the PNM Formats - Pnm(PnmSubtype), - - #[cfg(feature = "gif")] - /// An Image in GIF Format - Gif, - - #[cfg(feature = "ico")] - /// An Image in ICO Format - Ico, - - #[cfg(feature = "bmp")] - /// An Image in BMP Format - Bmp, - - #[cfg(feature = "farbfeld")] - /// An Image in farbfeld Format - Farbfeld, - - #[cfg(feature = "tga")] - /// An Image in TGA Format - Tga, - - #[cfg(feature = "exr")] - /// An Image in OpenEXR Format - OpenExr, - - #[cfg(feature = "tiff")] - /// An Image in TIFF Format - Tiff, - - #[cfg(feature = "avif-encoder")] - /// An image in AVIF Format - Avif, - - #[cfg(feature = "qoi")] - /// An image in QOI Format - Qoi, - - #[cfg(feature = "webp")] - /// An image in WebP Format. - WebP, - - /// A value for signalling an error: An unsupported format was requested - // Note: When TryFrom is stabilized, this value should not be needed, and - // a TryInto should be used instead of an Into. - Unsupported(String), -} - -impl From for ImageOutputFormat { - fn from(fmt: ImageFormat) -> Self { - match fmt { - #[cfg(feature = "png")] - ImageFormat::Png => ImageOutputFormat::Png, - #[cfg(feature = "jpeg")] - ImageFormat::Jpeg => ImageOutputFormat::Jpeg(75), - #[cfg(feature = "pnm")] - ImageFormat::Pnm => ImageOutputFormat::Pnm(PnmSubtype::ArbitraryMap), - #[cfg(feature = "gif")] - ImageFormat::Gif => ImageOutputFormat::Gif, - #[cfg(feature = "ico")] - ImageFormat::Ico => ImageOutputFormat::Ico, - #[cfg(feature = "bmp")] - ImageFormat::Bmp => ImageOutputFormat::Bmp, - #[cfg(feature = "farbfeld")] - ImageFormat::Farbfeld => ImageOutputFormat::Farbfeld, - #[cfg(feature = "tga")] - ImageFormat::Tga => ImageOutputFormat::Tga, - #[cfg(feature = "exr")] - ImageFormat::OpenExr => ImageOutputFormat::OpenExr, - #[cfg(feature = "tiff")] - ImageFormat::Tiff => ImageOutputFormat::Tiff, - - #[cfg(feature = "avif-encoder")] - ImageFormat::Avif => ImageOutputFormat::Avif, - #[cfg(feature = "webp")] - ImageFormat::WebP => ImageOutputFormat::WebP, - - #[cfg(feature = "qoi")] - ImageFormat::Qoi => ImageOutputFormat::Qoi, - - f => ImageOutputFormat::Unsupported(format!("{:?}", f)), - } - } -} - -// This struct manages buffering associated with implementing `Read` and `Seek` on decoders that can -// must decode ranges of bytes at a time. -#[allow(dead_code)] -// When no image formats that use it are enabled -pub(crate) struct ImageReadBuffer { - scanline_bytes: usize, - buffer: Vec, - consumed: usize, - - total_bytes: u64, - offset: u64, -} -impl ImageReadBuffer { - /// Create a new ImageReadBuffer. - /// - /// Panics if scanline_bytes doesn't fit into a usize, because that would mean reading anything - /// from the image would take more RAM than the entire virtual address space. In other words, - /// actually using this struct would instantly OOM so just get it out of the way now. - #[allow(dead_code)] - // When no image formats that use it are enabled - pub(crate) fn new(scanline_bytes: u64, total_bytes: u64) -> Self { - Self { - scanline_bytes: usize::try_from(scanline_bytes).unwrap(), - buffer: Vec::new(), - consumed: 0, - total_bytes, - offset: 0, - } - } - - #[allow(dead_code)] - // When no image formats that use it are enabled - pub(crate) fn read(&mut self, buf: &mut [u8], mut read_scanline: F) -> io::Result - where - F: FnMut(&mut [u8]) -> io::Result, - { - if self.buffer.len() == self.consumed { - if self.offset == self.total_bytes { - return Ok(0); - } else if buf.len() >= self.scanline_bytes { - // If there is nothing buffered and the user requested a full scanline worth of - // data, skip buffering. - let bytes_read = read_scanline(&mut buf[..self.scanline_bytes])?; - self.offset += u64::try_from(bytes_read).unwrap(); - return Ok(bytes_read); - } else { - // Lazily allocate buffer the first time that read is called with a buffer smaller - // than the scanline size. - if self.buffer.is_empty() { - self.buffer.resize(self.scanline_bytes, 0); - } - - self.consumed = 0; - let bytes_read = read_scanline(&mut self.buffer[..])?; - self.buffer.resize(bytes_read, 0); - self.offset += u64::try_from(bytes_read).unwrap(); - - assert!(bytes_read == self.scanline_bytes || self.offset == self.total_bytes); - } - } - - // Finally, copy bytes into output buffer. - let bytes_buffered = self.buffer.len() - self.consumed; - if bytes_buffered > buf.len() { - buf.copy_from_slice(&self.buffer[self.consumed..][..buf.len()]); - self.consumed += buf.len(); - Ok(buf.len()) - } else { - buf[..bytes_buffered].copy_from_slice(&self.buffer[self.consumed..][..bytes_buffered]); - self.consumed = self.buffer.len(); - Ok(bytes_buffered) - } - } -} - -/// Decodes a specific region of the image, represented by the rectangle -/// starting from ```x``` and ```y``` and having ```length``` and ```width``` -#[allow(dead_code)] -// When no image formats that use it are enabled -pub(crate) fn load_rect<'a, D, F, F1, F2, E>( - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - progress_callback: F, - decoder: &mut D, - mut seek_scanline: F1, - mut read_scanline: F2, -) -> ImageResult<()> -where - D: ImageDecoder<'a>, - F: Fn(Progress), - F1: FnMut(&mut D, u64) -> io::Result<()>, - F2: FnMut(&mut D, &mut [u8]) -> Result<(), E>, - ImageError: From, -{ - let (x, y, width, height) = ( - u64::from(x), - u64::from(y), - u64::from(width), - u64::from(height), - ); - let dimensions = decoder.dimensions(); - let bytes_per_pixel = u64::from(decoder.color_type().bytes_per_pixel()); - let row_bytes = bytes_per_pixel * u64::from(dimensions.0); - #[allow(deprecated)] - let scanline_bytes = decoder.scanline_bytes(); - let total_bytes = width * height * bytes_per_pixel; - - if buf.len() < usize::try_from(total_bytes).unwrap_or(usize::max_value()) { - panic!( - "output buffer too short\n expected `{}`, provided `{}`", - total_bytes, - buf.len() - ); - } - - let mut bytes_read = 0u64; - let mut current_scanline = 0; - let mut tmp = Vec::new(); - let mut tmp_scanline = None; - - { - // Read a range of the image starting from byte number `start` and continuing until byte - // number `end`. Updates `current_scanline` and `bytes_read` appropriately. - let mut read_image_range = |mut start: u64, end: u64| -> ImageResult<()> { - // If the first scanline we need is already stored in the temporary buffer, then handle - // it first. - let target_scanline = start / scanline_bytes; - if tmp_scanline == Some(target_scanline) { - let position = target_scanline * scanline_bytes; - let offset = start.saturating_sub(position); - let len = (end - start) - .min(scanline_bytes - offset) - .min(end - position); - - buf[(bytes_read as usize)..][..len as usize] - .copy_from_slice(&tmp[offset as usize..][..len as usize]); - bytes_read += len; - start += len; - - progress_callback(Progress { - current: bytes_read, - total: total_bytes, - }); - - if start == end { - return Ok(()); - } - } - - let target_scanline = start / scanline_bytes; - if target_scanline != current_scanline { - seek_scanline(decoder, target_scanline)?; - current_scanline = target_scanline; - } - - let mut position = current_scanline * scanline_bytes; - while position < end { - if position >= start && end - position >= scanline_bytes { - read_scanline( - decoder, - &mut buf[(bytes_read as usize)..][..(scanline_bytes as usize)], - )?; - bytes_read += scanline_bytes; - } else { - tmp.resize(scanline_bytes as usize, 0u8); - read_scanline(decoder, &mut tmp)?; - tmp_scanline = Some(current_scanline); - - let offset = start.saturating_sub(position); - let len = (end - start) - .min(scanline_bytes - offset) - .min(end - position); - - buf[(bytes_read as usize)..][..len as usize] - .copy_from_slice(&tmp[offset as usize..][..len as usize]); - bytes_read += len; - } - - current_scanline += 1; - position += scanline_bytes; - progress_callback(Progress { - current: bytes_read, - total: total_bytes, - }); - } - Ok(()) - }; - - if x + width > u64::from(dimensions.0) - || y + height > u64::from(dimensions.1) - || width == 0 - || height == 0 - { - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))); - } - if scanline_bytes > usize::max_value() as u64 { - return Err(ImageError::Limits(LimitError::from_kind( - LimitErrorKind::InsufficientMemory, - ))); - } - - progress_callback(Progress { - current: 0, - total: total_bytes, - }); - if x == 0 && width == u64::from(dimensions.0) { - let start = x * bytes_per_pixel + y * row_bytes; - let end = (x + width) * bytes_per_pixel + (y + height - 1) * row_bytes; - read_image_range(start, end)?; - } else { - for row in y..(y + height) { - let start = x * bytes_per_pixel + row * row_bytes; - let end = (x + width) * bytes_per_pixel + row * row_bytes; - read_image_range(start, end)?; - } - } - } - - // Seek back to the start - Ok(seek_scanline(decoder, 0)?) -} - -/// Reads all of the bytes of a decoder into a Vec. No particular alignment -/// of the output buffer is guaranteed. -/// -/// Panics if there isn't enough memory to decode the image. -pub(crate) fn decoder_to_vec<'a, T>(decoder: impl ImageDecoder<'a>) -> ImageResult> -where - T: crate::traits::Primitive + bytemuck::Pod, -{ - let total_bytes = usize::try_from(decoder.total_bytes()); - if total_bytes.is_err() || total_bytes.unwrap() > isize::max_value() as usize { - return Err(ImageError::Limits(LimitError::from_kind( - LimitErrorKind::InsufficientMemory, - ))); - } - - let mut buf = vec![num_traits::Zero::zero(); total_bytes.unwrap() / std::mem::size_of::()]; - decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?; - Ok(buf) -} - -/// Represents the progress of an image operation. -/// -/// Note that this is not necessarily accurate and no change to the values passed to the progress -/// function during decoding will be considered breaking. A decoder could in theory report the -/// progress `(0, 0)` if progress is unknown, without violating the interface contract of the type. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct Progress { - current: u64, - total: u64, -} - -impl Progress { - /// Create Progress. Result in invalid progress if you provide a greater `current` than `total`. - pub(crate) fn new(current: u64, total: u64) -> Self { - Self { current, total } - } - - /// A measure of completed decoding. - pub fn current(self) -> u64 { - self.current - } - - /// A measure of all necessary decoding work. - /// - /// This is in general greater or equal than `current`. - pub fn total(self) -> u64 { - self.total - } - - /// Calculate a measure for remaining decoding work. - pub fn remaining(self) -> u64 { - self.total.max(self.current) - self.current - } -} - -/// The trait that all decoders implement -pub trait ImageDecoder<'a>: Sized { - /// The type of reader produced by `into_reader`. - type Reader: Read + 'a; - - /// Returns a tuple containing the width and height of the image - fn dimensions(&self) -> (u32, u32); - - /// Returns the color type of the image data produced by this decoder - fn color_type(&self) -> ColorType; - - /// Returns the color type of the image file before decoding - fn original_color_type(&self) -> ExtendedColorType { - self.color_type().into() - } - - /// Returns the ICC color profile embedded in the image - /// - /// For formats that don't support embedded profiles this function will always return `None`. - /// This feature is currently only supported for the JPEG, PNG, and AVIF formats. - fn icc_profile(&mut self) -> Option> { - None - } - - /// Returns a reader that can be used to obtain the bytes of the image. For the best - /// performance, always try to read at least `scanline_bytes` from the reader at a time. Reading - /// fewer bytes will cause the reader to perform internal buffering. - #[deprecated = "Planned for removal. See https://github.com/image-rs/image/issues/1989"] - fn into_reader(self) -> ImageResult; - - /// Returns the total number of bytes in the decoded image. - /// - /// This is the size of the buffer that must be passed to `read_image` or - /// `read_image_with_progress`. The returned value may exceed usize::MAX, in - /// which case it isn't actually possible to construct a buffer to decode all the image data - /// into. If, however, the size does not fit in a u64 then u64::MAX is returned. - fn total_bytes(&self) -> u64 { - let dimensions = self.dimensions(); - let total_pixels = u64::from(dimensions.0) * u64::from(dimensions.1); - let bytes_per_pixel = u64::from(self.color_type().bytes_per_pixel()); - total_pixels.saturating_mul(bytes_per_pixel) - } - - /// Returns the minimum number of bytes that can be efficiently read from this decoder. This may - /// be as few as 1 or as many as `total_bytes()`. - #[deprecated = "Planned for removal. See https://github.com/image-rs/image/issues/1989"] - fn scanline_bytes(&self) -> u64 { - self.total_bytes() - } - - /// Returns all the bytes in the image. - /// - /// This function takes a slice of bytes and writes the pixel data of the image into it. - /// Although not required, for certain color types callers may want to pass buffers which are - /// aligned to 2 or 4 byte boundaries to the slice can be cast to a [u16] or [u32]. To accommodate - /// such casts, the returned contents will always be in native endian. - /// - /// # Panics - /// - /// This function panics if buf.len() != self.total_bytes(). - /// - /// # Examples - /// - /// ```no_build - /// use zerocopy::{AsBytes, FromBytes}; - /// fn read_16bit_image(decoder: impl ImageDecoder) -> Vec<16> { - /// let mut buf: Vec = vec![0; decoder.total_bytes()/2]; - /// decoder.read_image(buf.as_bytes()); - /// buf - /// } - /// ``` - fn read_image(self, buf: &mut [u8]) -> ImageResult<()> { - #[allow(deprecated)] - self.read_image_with_progress(buf, |_| {}) - } - - /// Same as `read_image` but periodically calls the provided callback to give updates on loading - /// progress. - #[deprecated = "Use read_image instead. See https://github.com/image-rs/image/issues/1989"] - fn read_image_with_progress( - self, - buf: &mut [u8], - progress_callback: F, - ) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - - let total_bytes = self.total_bytes() as usize; - #[allow(deprecated)] - let scanline_bytes = self.scanline_bytes() as usize; - let target_read_size = if scanline_bytes < 4096 { - (4096 / scanline_bytes) * scanline_bytes - } else { - scanline_bytes - }; - - #[allow(deprecated)] - let mut reader = self.into_reader()?; - - let mut bytes_read = 0; - while bytes_read < total_bytes { - let read_size = target_read_size.min(total_bytes - bytes_read); - reader.read_exact(&mut buf[bytes_read..][..read_size])?; - bytes_read += read_size; - - progress_callback(Progress { - current: bytes_read as u64, - total: total_bytes as u64, - }); - } - - Ok(()) - } - - /// Set decoding limits for this decoder. See [`Limits`] for the different kinds of - /// limits that is possible to set. - /// - /// Note to implementors: make sure you call [`Limits::check_support`] so that - /// decoding fails if any unsupported strict limits are set. Also make sure - /// you call [`Limits::check_dimensions`] to check the `max_image_width` and - /// `max_image_height` limits. - /// - /// [`Limits`]: ./io/struct.Limits.html - /// [`Limits::check_support`]: ./io/struct.Limits.html#method.check_support - /// [`Limits::check_dimensions`]: ./io/struct.Limits.html#method.check_dimensions - fn set_limits(&mut self, limits: crate::io::Limits) -> ImageResult<()> { - limits.check_support(&crate::io::LimitSupport::default())?; - - let (width, height) = self.dimensions(); - limits.check_dimensions(width, height)?; - - Ok(()) - } -} - -/// Specialized image decoding not be supported by all formats -pub trait ImageDecoderRect<'a>: ImageDecoder<'a> + Sized { - /// Decode a rectangular section of the image; see [`read_rect_with_progress()`](#fn.read_rect_with_progress). - fn read_rect( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - ) -> ImageResult<()> { - #[allow(deprecated)] - self.read_rect_with_progress(x, y, width, height, buf, |_| {}) - } - - /// Decode a rectangular section of the image, periodically reporting progress. - /// - /// The output buffer will be filled with fields specified by - /// [`ImageDecoder::color_type()`](trait.ImageDecoder.html#fn.color_type), - /// in that order, each field represented in native-endian. - /// - /// The progress callback will be called at least once at the start and the end of decoding, - /// implementations are encouraged to call this more often, - /// with a frequency meaningful for display to the end-user. - /// - /// This function will panic if the output buffer isn't at least - /// `color_type().bytes_per_pixel() * color_type().channel_count() * width * height` bytes long. - #[deprecated = "Use read_image instead. See https://github.com/image-rs/image/issues/1989"] - fn read_rect_with_progress( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - progress_callback: F, - ) -> ImageResult<()>; -} - -/// AnimationDecoder trait -pub trait AnimationDecoder<'a> { - /// Consume the decoder producing a series of frames. - fn into_frames(self) -> Frames<'a>; -} - -/// The trait all encoders implement -pub trait ImageEncoder { - /// Writes all the bytes in an image to the encoder. - /// - /// This function takes a slice of bytes of the pixel data of the image - /// and encodes them. Unlike particular format encoders inherent impl encode - /// methods where endianness is not specified, here image data bytes should - /// always be in native endian. The implementor will reorder the endianness - /// as necessary for the target encoding format. - /// - /// See also `ImageDecoder::read_image` which reads byte buffers into - /// native endian. - /// - /// # Panics - /// - /// Panics if `width * height * color_type.bytes_per_pixel() != buf.len()`. - fn write_image( - self, - buf: &[u8], - width: u32, - height: u32, - color_type: ColorType, - ) -> ImageResult<()>; -} - -/// Immutable pixel iterator -#[derive(Debug)] -pub struct Pixels<'a, I: ?Sized + 'a> { - image: &'a I, - x: u32, - y: u32, - width: u32, - height: u32, -} - -impl<'a, I: GenericImageView> Iterator for Pixels<'a, I> { - type Item = (u32, u32, I::Pixel); - - fn next(&mut self) -> Option<(u32, u32, I::Pixel)> { - if self.x >= self.width { - self.x = 0; - self.y += 1; - } - - if self.y >= self.height { - None - } else { - let pixel = self.image.get_pixel(self.x, self.y); - let p = (self.x, self.y, pixel); - - self.x += 1; - - Some(p) - } - } -} - -impl Clone for Pixels<'_, I> { - fn clone(&self) -> Self { - Pixels { ..*self } - } -} - -/// Trait to inspect an image. -/// -/// ``` -/// use image::{GenericImageView, Rgb, RgbImage}; -/// -/// let buffer = RgbImage::new(10, 10); -/// let image: &dyn GenericImageView> = &buffer; -/// ``` -pub trait GenericImageView { - /// The type of pixel. - type Pixel: Pixel; - - /// The width and height of this image. - fn dimensions(&self) -> (u32, u32); - - /// The width of this image. - fn width(&self) -> u32 { - let (w, _) = self.dimensions(); - w - } - - /// The height of this image. - fn height(&self) -> u32 { - let (_, h) = self.dimensions(); - h - } - - /// The bounding rectangle of this image. - #[deprecated = "This method has inconsistent behavior between implementations (#1829). Use `dimensions` instead"] - fn bounds(&self) -> (u32, u32, u32, u32); - - /// Returns true if this x, y coordinate is contained inside the image. - fn in_bounds(&self, x: u32, y: u32) -> bool { - #[allow(deprecated)] - let (ix, iy, iw, ih) = self.bounds(); - x >= ix && x < ix + iw && y >= iy && y < iy + ih - } - - /// Returns the pixel located at (x, y). Indexed from top left. - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of bounds. - fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel; - - /// Returns the pixel located at (x, y). Indexed from top left. - /// - /// This function can be implemented in a way that ignores bounds checking. - /// # Safety - /// - /// The coordinates must be [`in_bounds`] of the image. - /// - /// [`in_bounds`]: #method.in_bounds - unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel { - self.get_pixel(x, y) - } - - /// Returns an Iterator over the pixels of this image. - /// The iterator yields the coordinates of each pixel - /// along with their value - fn pixels(&self) -> Pixels - where - Self: Sized, - { - let (width, height) = self.dimensions(); - - Pixels { - image: self, - x: 0, - y: 0, - width, - height, - } - } - - /// Returns a subimage that is an immutable view into this image. - /// You can use [`GenericImage::sub_image`] if you need a mutable view instead. - /// The coordinates set the position of the top left corner of the view. - fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self> - where - Self: Sized, - { - assert!(x as u64 + width as u64 <= self.width() as u64); - assert!(y as u64 + height as u64 <= self.height() as u64); - SubImage::new(self, x, y, width, height) - } -} - -/// A trait for manipulating images. -pub trait GenericImage: GenericImageView { - /// Gets a reference to the mutable pixel at location `(x, y)`. Indexed from top left. - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of bounds. - /// - /// Panics for dynamic images (this method is deprecated and will be removed). - /// - /// ## Known issues - /// - /// This requires the buffer to contain a unique set of continuous channels in the exact order - /// and byte representation that the pixel type requires. This is somewhat restrictive. - /// - /// TODO: Maybe use some kind of entry API? this would allow pixel type conversion on the fly - /// while still doing only one array lookup: - /// - /// ```ignore - /// let px = image.pixel_entry_at(x,y); - /// px.set_from_rgba(rgba) - /// ``` - #[deprecated(since = "0.24.0", note = "Use `get_pixel` and `put_pixel` instead.")] - fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel; - - /// Put a pixel at location (x, y). Indexed from top left. - /// - /// # Panics - /// - /// Panics if `(x, y)` is out of bounds. - fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel); - - /// Puts a pixel at location (x, y). Indexed from top left. - /// - /// This function can be implemented in a way that ignores bounds checking. - /// # Safety - /// - /// The coordinates must be [`in_bounds`] of the image. - /// - /// [`in_bounds`]: traits.GenericImageView.html#method.in_bounds - unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { - self.put_pixel(x, y, pixel); - } - - /// Put a pixel at location (x, y), taking into account alpha channels - #[deprecated( - since = "0.24.0", - note = "Use iterator `pixels_mut` to blend the pixels directly" - )] - fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel); - - /// Copies all of the pixels from another image into this image. - /// - /// The other image is copied with the top-left corner of the - /// other image placed at (x, y). - /// - /// In order to copy only a piece of the other image, use [`GenericImageView::view`]. - /// - /// You can use [`FlatSamples`] to source pixels from an arbitrary regular raster of channel - /// values, for example from a foreign interface or a fixed image. - /// - /// # Returns - /// Returns an error if the image is too large to be copied at the given position - /// - /// [`GenericImageView::view`]: trait.GenericImageView.html#method.view - /// [`FlatSamples`]: flat/struct.FlatSamples.html - fn copy_from(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()> - where - O: GenericImageView, - { - // Do bounds checking here so we can use the non-bounds-checking - // functions to copy pixels. - if self.width() < other.width() + x || self.height() < other.height() + y { - return Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::DimensionMismatch, - ))); - } - - for k in 0..other.height() { - for i in 0..other.width() { - let p = other.get_pixel(i, k); - self.put_pixel(i + x, k + y, p); - } - } - Ok(()) - } - - /// Copies all of the pixels from one part of this image to another part of this image. - /// - /// The destination rectangle of the copy is specified with the top-left corner placed at (x, y). - /// - /// # Returns - /// `true` if the copy was successful, `false` if the image could not - /// be copied due to size constraints. - fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool { - let Rect { - x: sx, - y: sy, - width, - height, - } = source; - let dx = x; - let dy = y; - assert!(sx < self.width() && dx < self.width()); - assert!(sy < self.height() && dy < self.height()); - if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height { - return false; - } - // since `.rev()` creates a new dype we would either have to go with dynamic dispatch for the ranges - // or have quite a lot of code bloat. A macro gives us static dispatch with less visible bloat. - macro_rules! copy_within_impl_ { - ($xiter:expr, $yiter:expr) => { - for y in $yiter { - let sy = sy + y; - let dy = dy + y; - for x in $xiter { - let sx = sx + x; - let dx = dx + x; - let pixel = self.get_pixel(sx, sy); - self.put_pixel(dx, dy, pixel); - } - } - }; - } - // check how target and source rectangles relate to each other so we dont overwrite data before we copied it. - match (sx < dx, sy < dy) { - (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()), - (true, false) => copy_within_impl_!((0..width).rev(), 0..height), - (false, true) => copy_within_impl_!(0..width, (0..height).rev()), - (false, false) => copy_within_impl_!(0..width, 0..height), - } - true - } - - /// Returns a mutable subimage that is a view into this image. - /// If you want an immutable subimage instead, use [`GenericImageView::view`] - /// The coordinates set the position of the top left corner of the SubImage. - fn sub_image(&mut self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&mut Self> - where - Self: Sized, - { - assert!(x as u64 + width as u64 <= self.width() as u64); - assert!(y as u64 + height as u64 <= self.height() as u64); - SubImage::new(self, x, y, width, height) - } -} - -/// A View into another image -/// -/// Instances of this struct can be created using: -/// - [`GenericImage::sub_image`] to create a mutable view, -/// - [`GenericImageView::view`] to create an immutable view, -/// - [`SubImage::new`] to instantiate the struct directly. -/// -/// Note that this does _not_ implement `GenericImage`, but it dereferences to one which allows you -/// to use it as if it did. See [Design Considerations](#Design-Considerations) below for details. -/// -/// # Design Considerations -/// -/// For reasons relating to coherence, this is not itself a `GenericImage` or a `GenericImageView`. -/// In short, we want to reserve the ability of adding traits implemented for _all_ generic images -/// but in a different manner for `SubImage`. This may be required to ensure that stacking -/// sub-images comes at no double indirect cost. -/// -/// If, ultimately, this is not needed then a directly implementation of `GenericImage` can and -/// will get added. This inconvenience may alternatively get resolved if Rust allows some forms of -/// specialization, which might make this trick unnecessary and thus also allows for a direct -/// implementation. -#[derive(Copy, Clone)] -pub struct SubImage { - inner: SubImageInner, -} - -/// The inner type of `SubImage` that implements `GenericImage{,View}`. -/// -/// This type is _nominally_ `pub` but it is not exported from the crate. It should be regarded as -/// an existential type in any case. -#[derive(Copy, Clone)] -pub struct SubImageInner { - image: I, - xoffset: u32, - yoffset: u32, - xstride: u32, - ystride: u32, -} - -/// Alias to access Pixel behind a reference -type DerefPixel = <::Target as GenericImageView>::Pixel; - -/// Alias to access Subpixel behind a reference -type DerefSubpixel = as Pixel>::Subpixel; - -impl SubImage { - /// Construct a new subimage - /// The coordinates set the position of the top left corner of the SubImage. - pub fn new(image: I, x: u32, y: u32, width: u32, height: u32) -> SubImage { - SubImage { - inner: SubImageInner { - image, - xoffset: x, - yoffset: y, - xstride: width, - ystride: height, - }, - } - } - - /// Change the coordinates of this subimage. - pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) { - self.inner.xoffset = x; - self.inner.yoffset = y; - self.inner.xstride = width; - self.inner.ystride = height; - } - - /// The offsets of this subimage relative to the underlying image. - pub fn offsets(&self) -> (u32, u32) { - (self.inner.xoffset, self.inner.yoffset) - } - - /// Convert this subimage to an ImageBuffer - pub fn to_image(&self) -> ImageBuffer, Vec>> - where - I: Deref, - I::Target: GenericImageView + 'static, - { - let mut out = ImageBuffer::new(self.inner.xstride, self.inner.ystride); - let borrowed = self.inner.image.deref(); - - for y in 0..self.inner.ystride { - for x in 0..self.inner.xstride { - let p = borrowed.get_pixel(x + self.inner.xoffset, y + self.inner.yoffset); - out.put_pixel(x, y, p); - } - } - - out - } -} - -/// Methods for readable images. -impl SubImage -where - I: Deref, - I::Target: GenericImageView, -{ - /// Create a sub-view of the image. - /// - /// The coordinates given are relative to the current view on the underlying image. - /// - /// Note that this method is preferred to the one from `GenericImageView`. This is accessible - /// with the explicit method call syntax but it should rarely be needed due to causing an - /// extra level of indirection. - /// - /// ``` - /// use image::{GenericImageView, RgbImage, SubImage}; - /// let buffer = RgbImage::new(10, 10); - /// - /// let subimage: SubImage<&RgbImage> = buffer.view(0, 0, 10, 10); - /// let subview: SubImage<&RgbImage> = subimage.view(0, 0, 10, 10); - /// - /// // Less efficient and NOT &RgbImage - /// let _: SubImage<&_> = GenericImageView::view(&*subimage, 0, 0, 10, 10); - /// ``` - pub fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&I::Target> { - use crate::GenericImageView as _; - assert!(x as u64 + width as u64 <= self.inner.width() as u64); - assert!(y as u64 + height as u64 <= self.inner.height() as u64); - let x = self.inner.xoffset.saturating_add(x); - let y = self.inner.yoffset.saturating_add(y); - SubImage::new(&*self.inner.image, x, y, width, height) - } - - /// Get a reference to the underlying image. - pub fn inner(&self) -> &I::Target { - &self.inner.image - } -} - -impl SubImage -where - I: DerefMut, - I::Target: GenericImage, -{ - /// Create a mutable sub-view of the image. - /// - /// The coordinates given are relative to the current view on the underlying image. - pub fn sub_image( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - ) -> SubImage<&mut I::Target> { - assert!(x as u64 + width as u64 <= self.inner.width() as u64); - assert!(y as u64 + height as u64 <= self.inner.height() as u64); - let x = self.inner.xoffset.saturating_add(x); - let y = self.inner.yoffset.saturating_add(y); - SubImage::new(&mut *self.inner.image, x, y, width, height) - } - - /// Get a mutable reference to the underlying image. - pub fn inner_mut(&mut self) -> &mut I::Target { - &mut self.inner.image - } -} - -impl Deref for SubImage -where - I: Deref, -{ - type Target = SubImageInner; - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl DerefMut for SubImage -where - I: DerefMut, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - -#[allow(deprecated)] -impl GenericImageView for SubImageInner -where - I: Deref, - I::Target: GenericImageView, -{ - type Pixel = DerefPixel; - - fn dimensions(&self) -> (u32, u32) { - (self.xstride, self.ystride) - } - - fn bounds(&self) -> (u32, u32, u32, u32) { - (self.xoffset, self.yoffset, self.xstride, self.ystride) - } - - fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { - self.image.get_pixel(x + self.xoffset, y + self.yoffset) - } -} - -#[allow(deprecated)] -impl GenericImage for SubImageInner -where - I: DerefMut, - I::Target: GenericImage + Sized, -{ - fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel { - self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset) - } - - fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { - self.image - .put_pixel(x + self.xoffset, y + self.yoffset, pixel) - } - - /// DEPRECATED: This method will be removed. Blend the pixel directly instead. - fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { - self.image - .blend_pixel(x + self.xoffset, y + self.yoffset, pixel) - } -} - -#[cfg(test)] -mod tests { - use std::collections::HashSet; - use std::io; - use std::path::Path; - - use super::{ - load_rect, ColorType, GenericImage, GenericImageView, ImageDecoder, ImageFormat, - ImageResult, - }; - use crate::color::Rgba; - use crate::math::Rect; - use crate::{GrayImage, ImageBuffer}; - - #[test] - #[allow(deprecated)] - /// Test that alpha blending works as expected - fn test_image_alpha_blending() { - let mut target = ImageBuffer::new(1, 1); - target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255])); - assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255])); - target.blend_pixel(0, 0, Rgba([0, 255, 0, 255])); - assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255])); - - // Blending an alpha channel onto a solid background - target.blend_pixel(0, 0, Rgba([255, 0, 0, 127])); - assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255])); - - // Blending two alpha channels - target.put_pixel(0, 0, Rgba([0, 255, 0, 127])); - target.blend_pixel(0, 0, Rgba([255, 0, 0, 127])); - assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190])); - } - - #[test] - fn test_in_bounds() { - let mut target = ImageBuffer::new(2, 2); - target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255])); - - assert!(target.in_bounds(0, 0)); - assert!(target.in_bounds(1, 0)); - assert!(target.in_bounds(0, 1)); - assert!(target.in_bounds(1, 1)); - - assert!(!target.in_bounds(2, 0)); - assert!(!target.in_bounds(0, 2)); - assert!(!target.in_bounds(2, 2)); - } - - #[test] - fn test_can_subimage_clone_nonmut() { - let mut source = ImageBuffer::new(3, 3); - source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255])); - - // A non-mutable copy of the source image - let source = source.clone(); - - // Clone a view into non-mutable to a separate buffer - let cloned = source.view(1, 1, 1, 1).to_image(); - - assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1)); - } - - #[test] - fn test_can_nest_views() { - let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - - { - let mut sub1 = source.sub_image(0, 0, 2, 2); - let mut sub2 = sub1.sub_image(1, 1, 1, 1); - sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0])); - } - - assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0])); - - let view1 = source.view(0, 0, 2, 2); - assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1)); - - let view2 = view1.view(1, 1, 1, 1); - assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0)); - } - - #[test] - #[should_panic] - fn test_view_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(1, 1, 3, 3); - } - - #[test] - #[should_panic] - fn test_view_coordinates_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(3, 3, 3, 3); - } - - #[test] - #[should_panic] - fn test_view_width_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(1, 1, 3, 2); - } - - #[test] - #[should_panic] - fn test_view_height_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(1, 1, 2, 3); - } - - #[test] - #[should_panic] - fn test_view_x_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(3, 1, 3, 3); - } - - #[test] - #[should_panic] - fn test_view_y_out_of_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(1, 3, 3, 3); - } - - #[test] - fn test_view_in_bounds() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - source.view(0, 0, 3, 3); - source.view(1, 1, 2, 2); - source.view(2, 2, 0, 0); - } - - #[test] - fn test_copy_sub_image() { - let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); - let view = source.view(0, 0, 3, 3); - let _view2 = view; - view.to_image(); - } - - #[test] - fn test_load_rect() { - struct MockDecoder { - scanline_number: u64, - scanline_bytes: u64, - } - impl<'a> ImageDecoder<'a> for MockDecoder { - type Reader = Box; - fn dimensions(&self) -> (u32, u32) { - (5, 5) - } - fn color_type(&self) -> ColorType { - ColorType::L8 - } - fn into_reader(self) -> ImageResult { - unimplemented!() - } - fn scanline_bytes(&self) -> u64 { - self.scanline_bytes - } - } - - const DATA: [u8; 25] = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, - ]; - - fn seek_scanline(m: &mut MockDecoder, n: u64) -> io::Result<()> { - m.scanline_number = n; - Ok(()) - } - fn read_scanline(m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> { - let bytes_read = m.scanline_number * m.scanline_bytes; - if bytes_read >= 25 { - return Ok(()); - } - - let len = m.scanline_bytes.min(25 - bytes_read); - buf[..(len as usize)].copy_from_slice(&DATA[(bytes_read as usize)..][..(len as usize)]); - m.scanline_number += 1; - Ok(()) - } - - for scanline_bytes in 1..30 { - let mut output = [0u8; 26]; - - load_rect( - 0, - 0, - 5, - 5, - &mut output, - |_| {}, - &mut MockDecoder { - scanline_number: 0, - scanline_bytes, - }, - seek_scanline, - read_scanline, - ) - .unwrap(); - assert_eq!(output[0..25], DATA); - assert_eq!(output[25], 0); - - output = [0u8; 26]; - load_rect( - 3, - 2, - 1, - 1, - &mut output, - |_| {}, - &mut MockDecoder { - scanline_number: 0, - scanline_bytes, - }, - seek_scanline, - read_scanline, - ) - .unwrap(); - assert_eq!(output[0..2], [13, 0]); - - output = [0u8; 26]; - load_rect( - 3, - 2, - 2, - 2, - &mut output, - |_| {}, - &mut MockDecoder { - scanline_number: 0, - scanline_bytes, - }, - seek_scanline, - read_scanline, - ) - .unwrap(); - assert_eq!(output[0..5], [13, 14, 18, 19, 0]); - - output = [0u8; 26]; - load_rect( - 1, - 1, - 2, - 4, - &mut output, - |_| {}, - &mut MockDecoder { - scanline_number: 0, - scanline_bytes, - }, - seek_scanline, - read_scanline, - ) - .unwrap(); - assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]); - } - } - - #[test] - fn test_load_rect_single_scanline() { - const DATA: [u8; 25] = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, - ]; - - struct MockDecoder; - impl<'a> ImageDecoder<'a> for MockDecoder { - type Reader = Box; - fn dimensions(&self) -> (u32, u32) { - (5, 5) - } - fn color_type(&self) -> ColorType { - ColorType::L8 - } - fn into_reader(self) -> ImageResult { - unimplemented!() - } - fn scanline_bytes(&self) -> u64 { - 25 - } - } - - // Ensure that seek scanline is called only once. - let mut seeks = 0; - let seek_scanline = |_d: &mut MockDecoder, n: u64| -> io::Result<()> { - seeks += 1; - assert_eq!(n, 0); - assert_eq!(seeks, 1); - Ok(()) - }; - - fn read_scanline(_m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> { - buf.copy_from_slice(&DATA); - Ok(()) - } - - let mut output = [0; 26]; - load_rect( - 1, - 1, - 2, - 4, - &mut output, - |_| {}, - &mut MockDecoder, - seek_scanline, - read_scanline, - ) - .unwrap(); - assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]); - } - - #[test] - fn test_image_format_from_path() { - fn from_path(s: &str) -> ImageResult { - ImageFormat::from_path(Path::new(s)) - } - assert_eq!(from_path("./a.jpg").unwrap(), ImageFormat::Jpeg); - assert_eq!(from_path("./a.jpeg").unwrap(), ImageFormat::Jpeg); - assert_eq!(from_path("./a.JPEG").unwrap(), ImageFormat::Jpeg); - assert_eq!(from_path("./a.pNg").unwrap(), ImageFormat::Png); - assert_eq!(from_path("./a.gif").unwrap(), ImageFormat::Gif); - assert_eq!(from_path("./a.webp").unwrap(), ImageFormat::WebP); - assert_eq!(from_path("./a.tiFF").unwrap(), ImageFormat::Tiff); - assert_eq!(from_path("./a.tif").unwrap(), ImageFormat::Tiff); - assert_eq!(from_path("./a.tga").unwrap(), ImageFormat::Tga); - assert_eq!(from_path("./a.dds").unwrap(), ImageFormat::Dds); - assert_eq!(from_path("./a.bmp").unwrap(), ImageFormat::Bmp); - assert_eq!(from_path("./a.Ico").unwrap(), ImageFormat::Ico); - assert_eq!(from_path("./a.hdr").unwrap(), ImageFormat::Hdr); - assert_eq!(from_path("./a.exr").unwrap(), ImageFormat::OpenExr); - assert_eq!(from_path("./a.pbm").unwrap(), ImageFormat::Pnm); - assert_eq!(from_path("./a.pAM").unwrap(), ImageFormat::Pnm); - assert_eq!(from_path("./a.Ppm").unwrap(), ImageFormat::Pnm); - assert_eq!(from_path("./a.pgm").unwrap(), ImageFormat::Pnm); - assert_eq!(from_path("./a.AViF").unwrap(), ImageFormat::Avif); - assert!(from_path("./a.txt").is_err()); - assert!(from_path("./a").is_err()); - } - - #[test] - fn test_generic_image_copy_within_oob() { - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap(); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 0, - width: 5, - height: 4 - }, - 0, - 0 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 0, - width: 4, - height: 5 - }, - 0, - 0 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 1, - y: 0, - width: 4, - height: 4 - }, - 0, - 0 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 0, - width: 4, - height: 4 - }, - 1, - 0 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 1, - width: 4, - height: 4 - }, - 0, - 0 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 0, - width: 4, - height: 4 - }, - 0, - 1 - )); - assert!(!image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 1, - y: 1, - width: 4, - height: 4 - }, - 0, - 0 - )); - } - - #[test] - fn test_generic_image_copy_within_tl() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 0, - width: 3, - height: 3 - }, - 1, - 1 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_generic_image_copy_within_tr() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 1, - y: 0, - width: 3, - height: 3 - }, - 0, - 1 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_generic_image_copy_within_bl() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 0, - y: 1, - width: 3, - height: 3 - }, - 1, - 0 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn test_generic_image_copy_within_br() { - let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15]; - let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); - assert!(image.sub_image(0, 0, 4, 4).copy_within( - Rect { - x: 1, - y: 1, - width: 3, - height: 3 - }, - 0, - 0 - )); - assert_eq!(&image.into_raw(), &expected); - } - - #[test] - fn image_formats_are_recognized() { - use ImageFormat::*; - const ALL_FORMATS: &[ImageFormat] = &[ - Avif, Png, Jpeg, Gif, WebP, Pnm, Tiff, Tga, Dds, Bmp, Ico, Hdr, Farbfeld, OpenExr, - ]; - for &format in ALL_FORMATS { - let mut file = Path::new("file.nothing").to_owned(); - for ext in format.extensions_str() { - assert!(file.set_extension(ext)); - match ImageFormat::from_path(&file) { - Err(_) => panic!("Path {} not recognized as {:?}", file.display(), format), - Ok(result) => assert_eq!(format, result), - } - } - } - } - - #[test] - fn total_bytes_overflow() { - struct D; - impl<'a> ImageDecoder<'a> for D { - type Reader = std::io::Cursor>; - fn color_type(&self) -> ColorType { - ColorType::Rgb8 - } - fn dimensions(&self) -> (u32, u32) { - (0xffffffff, 0xffffffff) - } - fn into_reader(self) -> ImageResult { - unreachable!() - } - } - assert_eq!(D.total_bytes(), u64::max_value()); - - let v: ImageResult> = super::decoder_to_vec(D); - assert!(v.is_err()); - } - - #[test] - fn all() { - let all_formats: HashSet = HashSet::from_iter(ImageFormat::all()); - assert!(all_formats.contains(&ImageFormat::Avif)); - assert!(all_formats.contains(&ImageFormat::Gif)); - assert!(all_formats.contains(&ImageFormat::Bmp)); - assert!(all_formats.contains(&ImageFormat::Farbfeld)); - assert!(all_formats.contains(&ImageFormat::Jpeg)); - } - - #[test] - fn reading_enabled() { - assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.reading_enabled()); - assert!(!ImageFormat::Dds.reading_enabled()); - } - - #[test] - fn writing_enabled() { - assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.writing_enabled()); - assert!(!ImageFormat::Hdr.writing_enabled()); - assert!(!ImageFormat::Dds.writing_enabled()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/affine.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/affine.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/affine.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/affine.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,8 @@ //! Functions for performing affine transformations. use crate::error::{ImageError, ParameterError, ParameterErrorKind}; -use crate::image::{GenericImage, GenericImageView}; use crate::traits::Pixel; -use crate::ImageBuffer; +use crate::{GenericImage, GenericImageView, ImageBuffer}; /// Rotate an image 90 degrees clockwise. pub fn rotate90( @@ -13,7 +12,7 @@ I::Pixel: 'static, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(height, width); + let mut out = image.buffer_with_dimensions(height, width); let _ = rotate90_in(image, &mut out); out } @@ -26,7 +25,7 @@ I::Pixel: 'static, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_with_dimensions(width, height); let _ = rotate180_in(image, &mut out); out } @@ -39,7 +38,7 @@ I::Pixel: 'static, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(height, width); + let mut out = image.buffer_with_dimensions(height, width); let _ = rotate270_in(image, &mut out); out } @@ -129,8 +128,7 @@ where I::Pixel: 'static, { - let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let _ = flip_horizontal_in(image, &mut out); out } @@ -142,8 +140,7 @@ where I::Pixel: 'static, { - let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let _ = flip_vertical_in(image, &mut out); out } @@ -267,9 +264,9 @@ flip_horizontal, flip_horizontal_in_place, flip_vertical, flip_vertical_in_place, rotate180, rotate180_in_place, rotate270, rotate90, }; - use crate::image::GenericImage; + use crate::traits::Pixel; - use crate::{GrayImage, ImageBuffer}; + use crate::{GenericImage, GrayImage, ImageBuffer}; macro_rules! assert_pixels_eq { ($actual:expr, $expected:expr) => {{ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/colorops.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/colorops.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/colorops.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/colorops.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,12 @@ //! Functions for altering and converting the color of pixelbufs use num_traits::NumCast; -use std::f64::consts::PI; -use crate::color::{FromColor, IntoColor, Luma, LumaA, Rgba}; -use crate::image::{GenericImage, GenericImageView}; +use crate::color::{FromColor, IntoColor, Luma, LumaA}; +use crate::metadata::{CicpColorPrimaries, CicpTransferCharacteristics}; use crate::traits::{Pixel, Primitive}; use crate::utils::clamp; -use crate::ImageBuffer; +use crate::{GenericImage, GenericImageView, ImageBuffer}; type Subpixel = <::Pixel as Pixel>::Subpixel; @@ -34,6 +33,7 @@ { let (width, height) = image.dimensions(); let mut out = ImageBuffer::new(width, height); + out.copy_color_space_from(&image.buffer_with_dimensions(0, 0)); for (x, y, pixel) in image.pixels() { let grayscale = pixel.to_luma(); @@ -54,6 +54,7 @@ { let (width, height) = image.dimensions(); let mut out = ImageBuffer::new(width, height); + out.copy_color_space_from(&image.buffer_with_dimensions(0, 0)); for (x, y, pixel) in image.pixels() { let grayscale = pixel.to_luma_alpha(); @@ -92,8 +93,7 @@ P: Pixel + 'static, S: Primitive + 'static, { - let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let max = S::DEFAULT_MAX_VALUE; let max: f32 = NumCast::from(max).unwrap(); @@ -159,8 +159,7 @@ P: Pixel + 'static, S: Primitive + 'static, { - let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let max = S::DEFAULT_MAX_VALUE; let max: i32 = NumCast::from(max).unwrap(); @@ -225,13 +224,12 @@ P: Pixel + 'static, S: Primitive + 'static, { - let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let angle: f64 = NumCast::from(value).unwrap(); - let cosv = (angle * PI / 180.0).cos(); - let sinv = (angle * PI / 180.0).sin(); + let cosv = angle.to_radians().cos(); + let sinv = angle.to_radians().sin(); let matrix: [f64; 9] = [ // Reds 0.213 + cosv * 0.787 - sinv * 0.213, @@ -280,6 +278,7 @@ } /// Hue rotate the supplied image in place. +/// /// `value` is the degrees to rotate each pixel by. /// 0 and 360 do nothing, the rest rotates by the given degree value. /// just like the css webkit filter hue-rotate(180) @@ -293,8 +292,8 @@ let angle: f64 = NumCast::from(value).unwrap(); - let cosv = (angle * PI / 180.0).cos(); - let sinv = (angle * PI / 180.0).sin(); + let cosv = angle.to_radians().cos(); + let sinv = angle.to_radians().sin(); let matrix: [f64; 9] = [ // Reds 0.213 + cosv * 0.787 - sinv * 0.213, @@ -355,12 +354,12 @@ /// in the color map. fn index_of(&self, color: &Self::Color) -> usize; /// Looks up color by index in the color map. If `idx` is out of range for the color map, or - /// ColorMap doesn't implement `lookup` `None` is returned. + /// `ColorMap` doesn't implement `lookup` `None` is returned. fn lookup(&self, index: usize) -> Option { let _ = index; None } - /// Determine if this implementation of ColorMap overrides the default `lookup`. + /// Determine if this implementation of `ColorMap` overrides the default `lookup`. fn has_lookup(&self) -> bool { false } @@ -422,7 +421,7 @@ } } - /// Indicate NeuQuant implements `lookup`. + /// Indicate `NeuQuant` implements `lookup`. fn has_lookup(&self) -> bool { true } @@ -435,11 +434,12 @@ } } +#[cfg(feature = "color_quant")] impl ColorMap for color_quant::NeuQuant { - type Color = Rgba; + type Color = crate::color::Rgba; #[inline(always)] - fn index_of(&self, color: &Rgba) -> usize { + fn index_of(&self, color: &Self::Color) -> usize { self.index_of(color.channels()) } @@ -454,8 +454,8 @@ } #[inline(always)] - fn map_color(&self, color: &mut Rgba) { - self.map_pixel(color.channels_mut()) + fn map_color(&self, color: &mut Self::Color) { + self.map_pixel(color.channels_mut()); } } @@ -534,9 +534,12 @@ Map: ColorMap + ?Sized, Pix: Pixel + 'static, { + // Special case, we do *not* want to copy the color space here. let mut indices = ImageBuffer::new(image.width(), image.height()); + indices.set_rgb_primaries(CicpColorPrimaries::Unspecified); + indices.set_transfer_function(CicpTransferCharacteristics::Unspecified); for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) { - *idx = Luma([color_map.index_of(pixel) as u8]) + *idx = Luma([color_map.index_of(pixel) as u8]); } indices } @@ -584,7 +587,7 @@ let cmap = BiLevel; dither(&mut image, &cmap); assert_eq!(&*image, &[0, 0xFF, 0xFF, 0]); - assert_eq!(index_colors(&image, &cmap).into_raw(), vec![0, 1, 1, 0]) + assert_eq!(index_colors(&image, &cmap).into_raw(), vec![0, 1, 1, 0]); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/fast_blur.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/fast_blur.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/fast_blur.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/fast_blur.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,573 @@ +use num_traits::Bounded; + +use crate::imageops::filter_1d::{SafeAdd, SafeMul}; +use crate::{ImageBuffer, Pixel, Primitive}; + +/// Approximation of Gaussian blur. +/// +/// # Arguments +/// +/// * `image_buffer` - source image. +/// * `sigma` - value controls image flattening level. +/// +/// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. +/// +/// Source: Kovesi, P.: Fast Almost-Gaussian Filtering The Australian Pattern +/// Recognition Society Conference: DICTA 2010. December 2010. Sydney. +#[must_use] +pub fn fast_blur( + input_buffer: &ImageBuffer>, + sigma: f32, +) -> ImageBuffer> { + let (width, height) = input_buffer.dimensions(); + + if width == 0 || height == 0 { + return input_buffer.clone(); + } + + let num_passes = 3; + + let boxes = boxes_for_gauss(sigma, num_passes); + if boxes.is_empty() { + return input_buffer.clone(); + } + + let samples = input_buffer.as_flat_samples().samples; + + let destination_size = match (width as usize) + .safe_mul(height as usize) + .and_then(|x| x.safe_mul(P::CHANNEL_COUNT as usize)) + { + Ok(s) => s, + Err(_) => panic!("Width and height and channels count exceeded pointer size"), + }; + + let first_box = boxes[0]; + + let mut transient = vec![P::Subpixel::min_value(); destination_size]; + let mut dst = vec![P::Subpixel::min_value(); destination_size]; + + // If destination_size isn't failed this one must not fail either + let stride = width as usize * P::CHANNEL_COUNT as usize; + + // bound + radius + 1 must fit in a pointer size + test_radius_size(width as usize, first_box); + test_radius_size(height as usize, first_box); + + box_blur_horizontal_pass_strategy::( + samples, + stride, + &mut transient, + stride, + width, + first_box, + ); + + box_blur_vertical_pass_strategy::( + &transient, stride, &mut dst, stride, width, height, first_box, + ); + + for &box_container in boxes.iter().skip(1) { + // bound + radius + 1 must fit in a pointer size + test_radius_size(width as usize, box_container); + test_radius_size(height as usize, box_container); + + box_blur_horizontal_pass_strategy::( + &dst, + stride, + &mut transient, + stride, + width, + box_container, + ); + + box_blur_vertical_pass_strategy::( + &transient, + stride, + &mut dst, + stride, + width, + height, + box_container, + ); + } + + let mut buffer = ImageBuffer::from_raw(width, height, dst).unwrap(); + buffer.copy_color_space_from(input_buffer); + buffer +} + +#[inline] +fn test_radius_size(bound: usize, radius: usize) { + match bound.safe_add(radius) { + Ok(_) => {} + Err(_) => panic!("Radius overflowed maximum possible size"), + } +} + +fn boxes_for_gauss(sigma: f32, n: usize) -> Vec { + let w_ideal = f32::sqrt((12.0 * sigma.powi(2) / (n as f32)) + 1.0); + let mut w_l = w_ideal.floor(); + if w_l % 2.0 == 0.0 { + w_l -= 1.0; + } + let w_u = w_l + 2.0; + + let m_ideal = 0.25 * (n as f32) * (w_l + 3.0) - 3.0 * sigma.powi(2) * (w_l + 1.0).recip(); + + let m = f32::round(m_ideal) as usize; + + (0..n) + .map(|i| if i < m { w_l as usize } else { w_u as usize }) + .map(|i| ceil_to_odd(i.saturating_sub(1) / 2)) + .collect::>() +} + +#[inline] +fn ceil_to_odd(x: usize) -> usize { + if x % 2 == 0 { + x + 1 + } else { + x + } +} + +#[inline] +#[allow(clippy::manual_clamp)] +fn rounding_saturating_mul(v: f32, w: f32) -> T { + // T::DEFAULT_MAX_VALUE is equal to 1.0 only in cases where storage type if `f32/f64`, + // that means it should be safe to round here. + if T::DEFAULT_MAX_VALUE.to_f32().unwrap() != 1.0 { + T::from( + (v * w) + .round() + .min(T::DEFAULT_MAX_VALUE.to_f32().unwrap()) + .max(T::DEFAULT_MIN_VALUE.to_f32().unwrap()), + ) + .unwrap() + } else { + T::from( + (v * w) + .min(T::DEFAULT_MAX_VALUE.to_f32().unwrap()) + .max(T::DEFAULT_MIN_VALUE.to_f32().unwrap()), + ) + .unwrap() + } +} + +fn box_blur_horizontal_pass_strategy( + src: &[P], + src_stride: usize, + dst: &mut [P], + dst_stride: usize, + width: u32, + radius: usize, +) where + T: Pixel, +{ + if T::CHANNEL_COUNT == 1 { + box_blur_horizontal_pass_impl::(src, src_stride, dst, dst_stride, width, radius); + } else if T::CHANNEL_COUNT == 2 { + box_blur_horizontal_pass_impl::(src, src_stride, dst, dst_stride, width, radius); + } else if T::CHANNEL_COUNT == 3 { + box_blur_horizontal_pass_impl::(src, src_stride, dst, dst_stride, width, radius); + } else if T::CHANNEL_COUNT == 4 { + box_blur_horizontal_pass_impl::(src, src_stride, dst, dst_stride, width, radius); + } else { + unimplemented!("More than 4 channels is not yet implemented"); + } +} + +fn box_blur_vertical_pass_strategy( + src: &[P], + src_stride: usize, + dst: &mut [P], + dst_stride: usize, + width: u32, + height: u32, + radius: usize, +) { + if T::CHANNEL_COUNT == 1 { + box_blur_vertical_pass_impl::( + src, src_stride, dst, dst_stride, width, height, radius, + ); + } else if T::CHANNEL_COUNT == 2 { + box_blur_vertical_pass_impl::( + src, src_stride, dst, dst_stride, width, height, radius, + ); + } else if T::CHANNEL_COUNT == 3 { + box_blur_vertical_pass_impl::( + src, src_stride, dst, dst_stride, width, height, radius, + ); + } else if T::CHANNEL_COUNT == 4 { + box_blur_vertical_pass_impl::( + src, src_stride, dst, dst_stride, width, height, radius, + ); + } else { + unimplemented!("More than 4 channels is not yet implemented"); + } +} + +fn box_blur_horizontal_pass_impl( + src: &[T], + src_stride: usize, + dst: &mut [T], + dst_stride: usize, + width: u32, + radius: usize, +) where + T: Primitive, +{ + assert!(width > 0, "Width must be sanitized before this method"); + test_radius_size(width as usize, radius); + + let kernel_size = radius * 2 + 1; + let edge_count = ((kernel_size / 2) + 1) as f32; + let half_kernel = kernel_size / 2; + + let weight = 1f32 / (radius * 2 + 1) as f32; + + let width_bound = width as usize - 1; + + // Horizontal blurring consists from 4 phases + // 1 - Fill initial sliding window + // 2 - Blur dangerous leading zone where clamping is required + // 3 - Blur *normal* zone where clamping is not required + // 4 - Blur dangerous trailing zone where clamping is required + + for (dst, src) in dst + .chunks_exact_mut(dst_stride) + .zip(src.chunks_exact(src_stride)) + { + let mut weight1: f32 = 0.; + let mut weight2: f32 = 0.; + let mut weight3: f32 = 0.; + + let chunk0 = &src[..CN]; + + // replicate edge + let mut weight0 = chunk0[0].to_f32().unwrap() * edge_count; + if CN > 1 { + weight1 = chunk0[1].to_f32().unwrap() * edge_count; + } + if CN > 2 { + weight2 = chunk0[2].to_f32().unwrap() * edge_count; + } + if CN == 4 { + weight3 = chunk0[3].to_f32().unwrap() * edge_count; + } + + for x in 1..=half_kernel { + let px = x.min(width_bound) * CN; + let chunk0 = &src[px..px + CN]; + weight0 += chunk0[0].to_f32().unwrap(); + if CN > 1 { + weight1 += chunk0[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 += chunk0[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 += chunk0[3].to_f32().unwrap(); + } + } + + for x in 0..half_kernel.min(width as usize) { + let next = (x + half_kernel + 1).min(width_bound) * CN; + let previous = (x as i64 - half_kernel as i64).max(0) as usize * CN; + + let dst_chunk = &mut dst[x * CN..x * CN + CN]; + dst_chunk[0] = rounding_saturating_mul(weight0, weight); + if CN > 1 { + dst_chunk[1] = rounding_saturating_mul(weight1, weight); + } + if CN > 2 { + dst_chunk[2] = rounding_saturating_mul(weight2, weight); + } + if CN == 4 { + dst_chunk[3] = rounding_saturating_mul(weight3, weight); + } + + let next_chunk = &src[next..next + CN]; + let previous_chunk = &src[previous..previous + CN]; + + weight0 += next_chunk[0].to_f32().unwrap(); + if CN > 1 { + weight1 += next_chunk[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 += next_chunk[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 += next_chunk[3].to_f32().unwrap(); + } + + weight0 -= previous_chunk[0].to_f32().unwrap(); + if CN > 1 { + weight1 -= previous_chunk[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 -= previous_chunk[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 -= previous_chunk[3].to_f32().unwrap(); + } + } + + let max_x_before_clamping = width_bound.saturating_sub(half_kernel + 1); + let row_length = src.len(); + + let mut last_processed_item = half_kernel; + + if ((half_kernel * 2 + 1) * CN < row_length) && ((max_x_before_clamping * CN) < row_length) + { + let data_section = src; + let advanced_kernel_part = &data_section[(half_kernel * 2 + 1) * CN..]; + let section_length = max_x_before_clamping - half_kernel; + let dst = &mut dst[half_kernel * CN..(half_kernel * CN + section_length * CN)]; + + for ((dst, src_previous), src_next) in dst + .chunks_exact_mut(CN) + .zip(data_section.chunks_exact(CN)) + .zip(advanced_kernel_part.chunks_exact(CN)) + { + let dst_chunk = &mut dst[..CN]; + dst_chunk[0] = rounding_saturating_mul(weight0, weight); + if CN > 1 { + dst_chunk[1] = rounding_saturating_mul(weight1, weight); + } + if CN > 2 { + dst_chunk[2] = rounding_saturating_mul(weight2, weight); + } + if CN == 4 { + dst_chunk[3] = rounding_saturating_mul(weight3, weight); + } + + weight0 += src_next[0].to_f32().unwrap(); + if CN > 1 { + weight1 += src_next[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 += src_next[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 += src_next[3].to_f32().unwrap(); + } + + weight0 -= src_previous[0].to_f32().unwrap(); + if CN > 1 { + weight1 -= src_previous[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 -= src_previous[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 -= src_previous[3].to_f32().unwrap(); + } + } + + last_processed_item = max_x_before_clamping; + } + + for x in last_processed_item..width as usize { + let next = (x + half_kernel + 1).min(width_bound) * CN; + let previous = (x as i64 - half_kernel as i64).max(0) as usize * CN; + let dst_chunk = &mut dst[x * CN..x * CN + CN]; + dst_chunk[0] = rounding_saturating_mul(weight0, weight); + if CN > 1 { + dst_chunk[1] = rounding_saturating_mul(weight1, weight); + } + if CN > 2 { + dst_chunk[2] = rounding_saturating_mul(weight2, weight); + } + if CN == 4 { + dst_chunk[3] = rounding_saturating_mul(weight3, weight); + } + + let next_chunk = &src[next..next + CN]; + let previous_chunk = &src[previous..previous + CN]; + + weight0 += next_chunk[0].to_f32().unwrap(); + if CN > 1 { + weight1 += next_chunk[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 += next_chunk[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 += next_chunk[3].to_f32().unwrap(); + } + + weight0 -= previous_chunk[0].to_f32().unwrap(); + if CN > 1 { + weight1 -= previous_chunk[1].to_f32().unwrap(); + } + if CN > 2 { + weight2 -= previous_chunk[2].to_f32().unwrap(); + } + if CN == 4 { + weight3 -= previous_chunk[3].to_f32().unwrap(); + } + } + } +} + +fn box_blur_vertical_pass_impl( + src: &[T], + src_stride: usize, + dst: &mut [T], + dst_stride: usize, + width: u32, + height: u32, + radius: usize, +) { + assert!(width > 0, "Width must be sanitized before this method"); + assert!(height > 0, "Height must be sanitized before this method"); + test_radius_size(width as usize, radius); + + let kernel_size = radius * 2 + 1; + + let edge_count = ((kernel_size / 2) + 1) as f32; + let half_kernel = kernel_size / 2; + + let weight = 1f32 / (radius * 2 + 1) as f32; + + let buf_size = width as usize * CN; + + let buf_cap = buf_size; + + let height_bound = height as usize - 1; + + // Instead of summing each column separately we use here transient buffer that + // averages columns in row manner. + // So, we make the initial buffer at the top edge + // and then doing blur by averaging the whole row ( which is in buffer ) + // and subtracting and adding next and previous rows in horizontal manner. + + let mut buffer = vec![0f32; buf_cap]; + + for (x, (v, bf)) in src.iter().zip(buffer.iter_mut()).enumerate() { + let mut w = v.to_f32().unwrap() * edge_count; + for y in 1..=half_kernel { + let y_src_shift = y.min(height_bound) * src_stride; + w += src[y_src_shift + x].to_f32().unwrap(); + } + *bf = w; + } + + for (dst, y) in dst.chunks_exact_mut(dst_stride).zip(0..height as usize) { + let next = (y + half_kernel + 1).min(height_bound) * src_stride; + let previous = (y as i64 - half_kernel as i64).max(0) as usize * src_stride; + + let next_row = &src[next..next + width as usize * CN]; + let previous_row = &src[previous..previous + width as usize * CN]; + + for (((src_next, src_previous), buffer), dst) in next_row + .iter() + .zip(previous_row.iter()) + .zip(buffer.iter_mut()) + .zip(dst.iter_mut()) + { + let mut weight0 = *buffer; + + *dst = rounding_saturating_mul(weight0, weight); + + weight0 += src_next.to_f32().unwrap(); + weight0 -= src_previous.to_f32().unwrap(); + + *buffer = weight0; + } + } +} + +#[cfg(test)] +mod tests { + use crate::{DynamicImage, GrayAlphaImage, GrayImage, RgbImage, RgbaImage}; + use std::time::{SystemTime, UNIX_EPOCH}; + + struct Rng { + state: u64, + } + + impl Rng { + fn new(seed: u64) -> Self { + Self { state: seed } + } + fn next_u32(&mut self) -> u32 { + self.state = self.state.wrapping_mul(6364136223846793005).wrapping_add(1); + (self.state >> 32) as u32 + } + + fn next_u8(&mut self) -> u8 { + (self.next_u32() % 256) as u8 + } + + fn next_f32_in_range(&mut self, a: f32, b: f32) -> f32 { + let u = self.next_u32(); + let unit = (u as f32) / (u32::MAX as f32 + 1.0); + a + (b - a) * unit + } + } + + #[test] + fn test_box_blur() { + let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let mut rng = Rng::new((now.as_millis() & 0xffff_ffff_ffff_ffff) as u64); + for _ in 0..35 { + let width = rng.next_u8(); + let height = rng.next_u8(); + let sigma = rng.next_f32_in_range(0., 100.); + let px = rng.next_u8(); + let cn = rng.next_u8(); + if width == 0 || height == 0 || sigma <= 0. { + continue; + } + match cn % 4 { + 0 => { + let vc = vec![px; width as usize * height as usize]; + let image = DynamicImage::from( + GrayImage::from_vec(u32::from(width), u32::from(height), vc).unwrap(), + ); + let res = image.fast_blur(sigma); + for clr in res.as_bytes() { + assert_eq!(*clr, px); + } + } + 1 => { + let vc = vec![px; width as usize * height as usize * 2]; + let image = DynamicImage::from( + GrayAlphaImage::from_vec(u32::from(width), u32::from(height), vc).unwrap(), + ); + let res = image.fast_blur(sigma); + for clr in res.as_bytes() { + assert_eq!(*clr, px); + } + } + 2 => { + let vc = vec![px; width as usize * height as usize * 3]; + let image = DynamicImage::from( + RgbImage::from_vec(u32::from(width), u32::from(height), vc).unwrap(), + ); + let res = image.fast_blur(sigma); + for clr in res.as_bytes() { + assert_eq!(*clr, px); + } + } + 3 => { + let vc = vec![px; width as usize * height as usize * 4]; + let image = DynamicImage::from( + RgbaImage::from_vec(u32::from(width), u32::from(height), vc).unwrap(), + ); + let res = image.fast_blur(sigma); + for clr in res.as_bytes() { + assert_eq!(*clr, px); + } + } + _ => {} + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/filter_1d.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/filter_1d.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/filter_1d.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/filter_1d.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1000 @@ +#![forbid(unsafe_code)] +use crate::error::{LimitError, LimitErrorKind}; +use crate::math::multiply_accumulate; +use crate::ImageError; + +use num_traits::{AsPrimitive, MulAdd}; +use std::mem::size_of; +use std::ops::{Add, Mul}; + +pub(crate) trait SafeMul { + fn safe_mul(&self, rhs: S) -> Result; +} + +pub(crate) trait SafeAdd { + fn safe_add(&self, rhs: S) -> Result; +} + +impl SafeMul for usize { + #[inline] + fn safe_mul(&self, rhs: usize) -> Result { + if let Some(product) = self.checked_mul(rhs) { + Ok(product) + } else { + Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::DimensionError, + ))) + } + } +} + +impl SafeAdd for usize { + #[inline] + fn safe_add(&self, rhs: usize) -> Result { + if let Some(product) = self.checked_add(rhs) { + Ok(product) + } else { + Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::DimensionError, + ))) + } + } +} + +#[derive(Debug, Clone, Copy)] +struct KernelShape { + width: usize, + height: usize, +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct FilterImageSize { + pub(crate) width: usize, + pub(crate) height: usize, +} + +/// Pads an image row with *clamp* strategy +/// +/// This method copies real content into center of new buffer +/// and filling leading and trailing physical padded parts with *clamp* strategy +fn make_arena_row( + image: &[T], + row_buffer: &mut [T], + source_y: usize, + image_size: FilterImageSize, + kernel_size: KernelShape, +) -> Result<(), ImageError> +where + T: Default + Copy + Send + Sync + 'static, + f64: AsPrimitive, +{ + assert_eq!(image.len(), N * image_size.width * image_size.height); + + let pad_w = (kernel_size.width / 2).max(1); + + let arena_width = image_size + .width + .safe_mul(N)? + .safe_add(pad_w.safe_mul(2 * N)?)?; + + let source_offset = source_y * image_size.width * N; + assert_eq!(row_buffer.len(), arena_width); + + let row_dst = &mut row_buffer[pad_w * N..(pad_w * N + image_size.width * N)]; + + let source_row = &image[source_offset..(source_offset + image_size.width * N)]; + + for (dst, src) in row_dst.iter_mut().zip(source_row.iter()) { + *dst = *src; + } + + for (x, dst) in (0..pad_w).zip(row_buffer.chunks_exact_mut(N)) { + let old_x = x.saturating_sub(pad_w).min(image_size.width - 1); + let old_px = old_x * N; + let src_iter = &source_row[old_px..(old_px + N)]; + for (dst, src) in dst.iter_mut().zip(src_iter.iter()) { + *dst = *src; + } + } + + for (x, dst) in + (image_size.width..(image_size.width + pad_w)).zip(row_buffer.chunks_exact_mut(N).rev()) + { + let old_x = x.max(0).min(image_size.width - 1); + let old_px = old_x * N; + let src_iter = &source_row[old_px..(old_px + N)]; + for (dst, src) in dst.iter_mut().zip(src_iter.iter()) { + *dst = *src; + } + } + Ok(()) +} + +#[derive(Clone)] +struct ArenaColumns +where + T: Copy, +{ + top_pad: Vec, + bottom_pad: Vec, +} + +/// Pads a column image with *clamp* strategy +/// +/// This method is used for *virtual* column padding. +/// It produces two arrays that represents virtual image top part and bottom +fn make_columns_arenas( + image: &[T], + image_size: FilterImageSize, + kernel_size: KernelShape, +) -> ArenaColumns +where + T: Default + Copy + Send + Sync + 'static, + f64: AsPrimitive, +{ + assert_eq!(image.len(), N * image_size.width * image_size.height); + let pad_h = kernel_size.height / 2; + + let mut top_pad = vec![T::default(); pad_h * image_size.width * N]; + let mut bottom_pad = vec![T::default(); pad_h * image_size.width * N]; + + let top_pad_stride = image_size.width * N; + + for (ky, dst) in (0..pad_h).zip(top_pad.chunks_exact_mut(top_pad_stride)) { + for (kx, dst) in (0..image_size.width).zip(dst.chunks_exact_mut(N)) { + let y = ky.saturating_sub(pad_h).min(image_size.height - 1); + let v_src = y * top_pad_stride + kx * N; + + let src_iter = &image[v_src..(v_src + N)]; + for (dst, src) in dst.iter_mut().zip(src_iter.iter()) { + *dst = *src; + } + } + } + + let bottom_iter_dst = bottom_pad.chunks_exact_mut(top_pad_stride); + + for (ky, dst) in (0..pad_h).zip(bottom_iter_dst) { + for (kx, dst) in (0..image_size.width).zip(dst.chunks_exact_mut(N)) { + let y = (ky + image_size.height).min(image_size.height - 1); + let v_src = y * top_pad_stride + kx * N; + let src_iter = &image[v_src..(v_src + N)]; + for (dst, src) in dst.iter_mut().zip(src_iter.iter()) { + *dst = *src; + } + } + } + + ArenaColumns { + top_pad, + bottom_pad, + } +} + +trait ToStorage { + fn to_(self) -> S; +} + +const Q0_15: i32 = 15; + +impl ToStorage for u32 { + #[inline(always)] + fn to_(self) -> u8 { + ((self + (1 << (Q0_15 - 1))) >> Q0_15).min(255) as u8 + } +} + +impl ToStorage for u32 { + #[inline(always)] + fn to_(self) -> u16 { + ((self + (1 << (Q0_15 - 1))) >> Q0_15).min(u16::MAX as u32) as u16 + } +} + +impl ToStorage for f32 { + #[inline(always)] + fn to_(self) -> u16 { + self.round().min(u16::MAX as f32) as u16 + } +} + +impl ToStorage for f32 { + #[inline(always)] + fn to_(self) -> f32 { + self + } +} + +/// Performs column convolution pass for symmetrical filter +/// +/// Common convolution formula O(x,y)=∑K(k)⋅I(x,y+k); where sums goes from 0...R +/// when filter is symmetric that we can half kernel reads by using formula +/// O(x,y)=(∑K(k)⋅(I(x,y+k) + I(x,y+(R-k)))) + K(R/2)⋅I(x,y+R/2); where sums goes from 0...R/2 +fn filter_symmetric_column( + arena_src: &[&[T]], + dst_row: &mut [T], + image_size: FilterImageSize, + kernel: &[F], +) where + T: Copy + AsPrimitive, + F: ToStorage + + Mul + + MulAdd + + Add + + Default + + Copy + + 'static, +{ + let dst_stride = image_size.width * N; + + let length = kernel.len(); + let half_len = length / 2; + + let mut cx = 0usize; + + let coeff = kernel[half_len]; + + let mut dst_rem = dst_row; + + if size_of::() == 1 { + for chunk in dst_rem.chunks_exact_mut(32) { + let mut store0: [F; 16] = [F::default(); 16]; + let mut store1: [F; 16] = [F::default(); 16]; + + let v_src0 = &arena_src[half_len][cx..(cx + 16)]; + let v_src1 = &arena_src[half_len][(cx + 16)..(cx + 32)]; + + for (dst, src) in store0.iter_mut().zip(v_src0) { + *dst = src.as_().mul(coeff); + } + for (dst, src) in store1.iter_mut().zip(v_src1) { + *dst = src.as_().mul(coeff); + } + + for (i, &coeff) in kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw_src = arena_src[i]; + let rw_src = arena_src[other_side]; + let fw0 = &fw_src[cx..(cx + 16)]; + let bw0 = &rw_src[cx..(cx + 16)]; + let fw1 = &fw_src[(cx + 16)..(cx + 32)]; + let bw1 = &rw_src[(cx + 16)..(cx + 32)]; + + for ((dst, fw), bw) in store0.iter_mut().zip(fw0).zip(bw0) { + *dst = multiply_accumulate(*dst, fw.as_().add(bw.as_()), coeff); + } + + for ((dst, fw), bw) in store1.iter_mut().zip(fw1).zip(bw1) { + *dst = multiply_accumulate(*dst, fw.as_().add(bw.as_()), coeff); + } + } + + let shaped_dst0 = &mut chunk[..16]; + + for (src, dst) in store0.iter().zip(shaped_dst0.iter_mut()) { + *dst = src.to_(); + } + + let shaped_dst1 = &mut chunk[16..32]; + + for (src, dst) in store1.iter().zip(shaped_dst1.iter_mut()) { + *dst = src.to_(); + } + + cx += 32; + } + + dst_rem = dst_rem.chunks_exact_mut(32).into_remainder(); + } + + for chunk in dst_rem.chunks_exact_mut(16) { + let mut store: [F; 16] = [F::default(); 16]; + + let v_src = &arena_src[half_len][cx..(cx + 16)]; + + for (dst, src) in store.iter_mut().zip(v_src) { + *dst = src.as_().mul(coeff); + } + + for (i, &coeff) in kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw = &arena_src[i][cx..(cx + 16)]; + let bw = &arena_src[other_side][cx..(cx + 16)]; + + for ((dst, fw), bw) in store.iter_mut().zip(fw).zip(bw) { + *dst = multiply_accumulate(*dst, fw.as_().add(bw.as_()), coeff); + } + } + + for (src, dst) in store.iter().zip(chunk.iter_mut()) { + *dst = src.to_(); + } + + cx += 16; + } + + dst_rem = dst_rem.chunks_exact_mut(16).into_remainder(); + + for chunk in dst_rem.chunks_exact_mut(4) { + let v_src = &arena_src[half_len][cx..(cx + 4)]; + + let mut k0 = v_src[0].as_().mul(coeff); + let mut k1 = v_src[1].as_().mul(coeff); + let mut k2 = v_src[2].as_().mul(coeff); + let mut k3 = v_src[3].as_().mul(coeff); + + for (i, &coeff) in kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw = &arena_src[i][cx..(cx + 4)]; + let bw = &arena_src[other_side][cx..(cx + 4)]; + k0 = multiply_accumulate(k0, fw[0].as_().add(bw[0].as_()), coeff); + k1 = multiply_accumulate(k1, fw[1].as_().add(bw[1].as_()), coeff); + k2 = multiply_accumulate(k2, fw[2].as_().add(bw[2].as_()), coeff); + k3 = multiply_accumulate(k3, fw[3].as_().add(bw[3].as_()), coeff); + } + + chunk[0] = k0.to_(); + chunk[1] = k1.to_(); + chunk[2] = k2.to_(); + chunk[3] = k3.to_(); + cx += 4; + } + + dst_rem = dst_rem.chunks_exact_mut(4).into_remainder(); + + for (chunk, x) in dst_rem.iter_mut().zip(cx..dst_stride) { + let v_src = &arena_src[half_len][x..(x + 1)]; + + let mut k0 = v_src[0].as_().mul(coeff); + + for (i, &coeff) in kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw = &arena_src[i][x..(x + 1)]; + let bw = &arena_src[other_side][x..(x + 1)]; + k0 = multiply_accumulate(k0, fw[0].as_().add(bw[0].as_()), coeff); + } + + *chunk = k0.to_(); + } +} + +/// Performs horizontal convolution for row +/// +/// Common convolution formula O(x,y)=∑K(k)⋅I(x+k,y); where sums goes from 0...R +/// when filter is symmetric that we can half kernel reads by using formula +/// O(x,y)=(∑K(k)⋅(I(x+k,y) + I(x+(R-k),y))) + K(R/2)⋅I(x+R/2,y); where sums goes from 0...R/2 +fn filter_symmetric_row(arena: &[T], dst_row: &mut [T], scanned_kernel: &[F]) +where + T: Copy + AsPrimitive + Default, + F: ToStorage + + Mul + + MulAdd + + Default + + Add + + Copy + + 'static, + i32: AsPrimitive, +{ + let src = arena; + + let length = scanned_kernel.len(); + let half_len = length / 2; + + let hc = scanned_kernel[half_len]; + + for (x, dst) in dst_row.chunks_exact_mut(4).enumerate() { + let v_cx = x * 4; + let src = &src[v_cx..]; + + let chunk = &src[half_len * N..half_len * N + 4]; + + let mut k0 = chunk[0].as_() * hc; + let mut k1 = chunk[1].as_() * hc; + let mut k2 = chunk[2].as_() * hc; + let mut k3 = chunk[3].as_() * hc; + + // Note why here is no window operators: + // https://github.com/image-rs/image/pull/2496#discussion_r2155171034 + for (i, &coeff) in scanned_kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw = &src[(i * N)..(i * N) + 4]; + let bw = &src[(other_side * N)..(other_side * N) + 4]; + k0 = multiply_accumulate(k0, fw[0].as_() + bw[0].as_(), coeff); + k1 = multiply_accumulate(k1, fw[1].as_() + bw[1].as_(), coeff); + k2 = multiply_accumulate(k2, fw[2].as_() + bw[2].as_(), coeff); + k3 = multiply_accumulate(k3, fw[3].as_() + bw[3].as_(), coeff); + } + + dst[0] = k0.to_(); + dst[1] = k1.to_(); + dst[2] = k2.to_(); + dst[3] = k3.to_(); + } + + let dzx = dst_row.chunks_exact_mut(4).len() * 4; + let remainder = dst_row.chunks_exact_mut(4).into_remainder(); + + for (x, dst) in remainder.iter_mut().enumerate() { + let v_cx = x + dzx; + let src = &src[v_cx..]; + + let mut k0 = src[half_len * N].as_() * hc; + + for (i, &coeff) in scanned_kernel.iter().take(half_len).enumerate() { + let other_side = length - i - 1; + let fw = &src[(i * N)..(i * N) + 1]; + let bw = &src[(other_side * N)..(other_side * N) + 1]; + k0 = multiply_accumulate(k0, fw[0].as_() + bw[0].as_(), coeff); + } + + *dst = k0.to_(); + } +} + +trait KernelTransformer { + fn transform(input: F) -> I; +} + +impl KernelTransformer for u8 { + fn transform(input: f32) -> u32 { + const SCALE: f32 = (1 << Q0_15) as f32; + (input * SCALE).min(((1u32 << Q0_15) - 1) as f32).max(0.) as u32 + } +} + +impl KernelTransformer for u16 { + fn transform(input: f32) -> u32 { + const SCALE: f32 = (1 << Q0_15) as f32; + (input * SCALE).min(((1u32 << Q0_15) - 1) as f32).max(0.) as u32 + } +} + +impl KernelTransformer for f32 { + fn transform(input: f32) -> f32 { + input + } +} + +impl KernelTransformer for u16 { + fn transform(input: f32) -> f32 { + input + } +} + +/// Removes meaningless values from kernel preserving symmetry +fn prepare_symmetric_kernel(kernel: &[I]) -> Vec +where + i32: AsPrimitive, +{ + let zeros: I = 0i32.as_(); + let mut new_kernel = kernel.to_vec(); + while new_kernel.len() > 2 + && (new_kernel.last().unwrap().eq(&zeros) && new_kernel.first().unwrap().eq(&zeros)) + { + new_kernel.remove(0); + new_kernel.remove(new_kernel.len() - 1); + } + + new_kernel +} + +const RING_QUEUE_CIRCULAR_CUTOFF: usize = 55; + +/// This is typical *Divide & Conquer* method with not typical *Sliding Window*. +/// Thus, instead of transient image here sliding window is used in a ring queue form. +/// +/// Let's define R(n) as row with number: R0,R1,R2,R3 and so forth. +/// So to convolve an image the buffer that represents a ring is created with size: +/// `image_width * channels_count * vertical_kernel_length` as our ring is representing +/// columnar queue. +/// +/// So at the very first time it's fully filled if we convolve image with vertical kernel size = 5, +/// then it holds: R0,R1,R2,R3,R4, each is already blurred horizontally. +/// Instead of removing/adding items from ring iterator position is hold +/// and after iterator is adjusted the new row just replaces the old ones. +/// Therefore, at the very moment of the first fulfilling we actually should blur now *R2* +/// that is central item, but our iterator already at *R4*, thus our *ring queue* is always +/// *ahead* of current row by `kernel_size/2`. So to send rows correctly to columnar pass, +/// it's required to reshuffle as `(current_iterator_position+1)%vertical_kernel_size` +/// our ring first ,since the iterator is always at the tail, advanced by +/// `kernel_size/2` from current row, and ahead from start by `kernel_size`. +/// +/// After columnar pass iterator is adjusted one position forward in a ring style: +/// to fill the ring, the next row blurred, then it will replace leading row with a new one. +/// The flow after the first fill looks like: +/// - R0,R1,R2,R3,R4(iterator here, denoted as `I`) +/// - R5(I),R1,R2,R3,R4 +/// - R5,R6(I),R2,R3,R4 +/// - R5,R6,R7(I),R3,R4 +/// - R5,R6,R7,R8(I),R4 +/// - R5,R6,R7,R8,R9(I) +/// - R10(I),R6,R7,R8,R9 +/// +/// This approach is significantly more efficient for small kernels, +/// and several times faster in multithreaded environments +/// despite the presence of overlapping regions. +/// +/// The algorithm consists of 3 stages that should be different for multithreaded and single-threaded +/// modes: +/// +/// Single threaded: +/// - Blurring horizontal R0 and copy it into a ring buffer +/// up to `kernel_size/2 * channels_count * vertical_kernel_length` because we always clamp here +/// and first row the same +/// - Blur next row and adjust iterator until ring the first full ring fill. +/// - Blur vertically ring buffer, store row into destination, +/// adjust iterator, blur horizontally next row and repeat it until end +/// +/// Multithreaded: +/// - Fill the ring buffer from tile's Y starting before the first full ring fill. +/// - Blur vertically ring buffer, store row into destination, +/// adjust iterator, blur horizontally next row and repeat it until end. +fn filter_2d_separable_ring_queue( + image: &[T], + destination: &mut [T], + image_size: FilterImageSize, + row_kernel: &[I], + column_kernel: &[I], +) -> Result<(), ImageError> +where + T: Copy + Default + Send + Sync + AsPrimitive, + I: ToStorage + + Mul + + Add + + MulAdd + + Send + + Sync + + PartialEq + + Default + + 'static + + Copy, + i32: AsPrimitive, + f64: AsPrimitive, +{ + let pad_w = (row_kernel.len() / 2).max(1); + + let arena_width = image_size + .width + .safe_mul(N)? + .safe_add(pad_w.safe_mul(2 * N)?)?; + let mut row_buffer = vec![T::default(); arena_width]; + + let full_width = image_size.width * N; + + // This is flat ring queue + let mut buffer = vec![T::default(); (image_size.width * N).safe_mul(column_kernel.len())?]; + + let column_kernel_len = column_kernel.len(); + + let half_kernel = column_kernel_len / 2; + + make_arena_row::( + image, + &mut row_buffer, + 0, + image_size, + KernelShape { + width: row_kernel.len(), + height: 0, + }, + )?; + + // Blurring horizontally R0 + filter_symmetric_row::(&row_buffer, &mut buffer[..full_width], row_kernel); + + // Distribute R0 up to half of kernel into a ring + let (src_row, rest) = buffer.split_at_mut(full_width); + for dst in rest.chunks_exact_mut(full_width).take(half_kernel) { + for (dst, src) in dst.iter_mut().zip(src_row.iter()) { + *dst = *src; + } + } + + let mut start_ky = column_kernel_len / 2 + 1; + // This needs in case of anisotropy + start_ky %= column_kernel_len; + + // image_size.height + half_kernel is here because as in description + // we're always in advance on half of vertical kernel + for y in 1..image_size.height + half_kernel { + let new_y = if y < image_size.height { + y + } else { + y.min(image_size.height - 1) + }; + + make_arena_row::( + image, + &mut row_buffer, + new_y, + image_size, + KernelShape { + width: row_kernel.len(), + height: 0, + }, + )?; + + filter_symmetric_row::( + &row_buffer, + &mut buffer[start_ky * full_width..(start_ky + 1) * full_width], + row_kernel, + ); + + // As we always in advance on half of vertical kernel so half_kernel = R0 + // this is real image start + if y >= half_kernel { + let mut brows = vec![image; column_kernel_len]; + + for (i, brow) in brows.iter_mut().enumerate() { + let ky = (i + start_ky + 1) % column_kernel_len; + *brow = &buffer[ky * full_width..(ky + 1) * full_width]; + } + + let dy = y - half_kernel; + + let dst = &mut destination[dy * full_width..(dy + 1) * full_width]; + + filter_symmetric_column::(&brows, dst, image_size, column_kernel); + } + + start_ky += 1; + start_ky %= column_kernel_len; + } + + Ok(()) +} + +/// Performs 2D separable convolution on the image +/// +/// Currently implemented only for symmetrical filters +/// +/// # Arguments +/// +/// * `image`: Single plane image +/// * `destination`: Destination image +/// * `image_size`: Image size see [FilterImageSize] +/// * `row_kernel`: Row kernel, *size must be odd*! +/// * `column_kernel`: Column kernel, *size must be odd*! +/// +/// If both kernels after kernel scan appears to be an identity then just copy is performed. +fn filter_2d_separable( + image: &[T], + destination: &mut [T], + image_size: FilterImageSize, + row_kernel: &[F], + column_kernel: &[F], +) -> Result<(), ImageError> +where + T: Copy + AsPrimitive + Default + Send + Sync + KernelTransformer + AsPrimitive, + F: Default + 'static + Copy, + I: ToStorage + + Mul + + Add + + MulAdd + + Send + + Sync + + PartialEq + + Default + + 'static + + Copy, + i32: AsPrimitive + AsPrimitive, + f64: AsPrimitive, +{ + if image.len() != image_size.width.safe_mul(image_size.height)?.safe_mul(N)? { + return Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::DimensionError, + ))); + } + if destination.len() != image.len() { + return Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::DimensionError, + ))); + } + + assert_ne!(row_kernel.len() & 1, 0, "Row kernel length must be odd"); + assert_ne!( + column_kernel.len() & 1, + 0, + "Column kernel length must be odd" + ); + + let mut scanned_row_kernel = row_kernel + .iter() + .map(|&x| T::transform(x)) + .collect::>(); + let mut scanned_column_kernel = column_kernel + .iter() + .map(|&x| T::transform(x)) + .collect::>(); + + scanned_row_kernel = prepare_symmetric_kernel(&scanned_row_kernel); + scanned_column_kernel = prepare_symmetric_kernel(&scanned_column_kernel); + + if scanned_row_kernel.is_empty() && scanned_column_kernel.is_empty() { + destination.copy_from_slice(image); + return Ok(()); + } + + if column_kernel.len() < RING_QUEUE_CIRCULAR_CUTOFF { + return filter_2d_separable_ring_queue::( + image, + destination, + image_size, + &scanned_row_kernel, + &scanned_column_kernel, + ); + } + + let pad_w = (scanned_row_kernel.len() / 2).max(1); + + let arena_width = image_size.width * N + pad_w * 2 * N; + let mut row_buffer = vec![T::default(); arena_width]; + + let mut transient_image = vec![T::default(); image_size.width * image_size.height * N]; + + for (y, dst) in transient_image + .chunks_exact_mut(image_size.width * N) + .enumerate() + { + // This is important to perform padding before convolution. + // That approach allows to iterate without unnecessary branching + // and highly effective from low sized kernels to reasonable huge kernels. + // It is especially more effective for low sized kernels than copying + // specifically for big sized images. + // If image row is `asdfgh` then this method with clamp will produce row + // `aaa asdfgh hhh` padded exactly on half kernel size + make_arena_row::( + image, + &mut row_buffer, + y, + image_size, + KernelShape { + width: scanned_row_kernel.len(), + height: 0, + }, + )?; + + filter_symmetric_row::(&row_buffer, dst, &scanned_row_kernel); + } + + let column_kernel_shape = KernelShape { + width: 0, + height: scanned_column_kernel.len(), + }; + + // This is important to perform padding before convolution. + // That approach allows to iterate without unnecessary branching + // and highly effective from low sized kernels to reasonable huge kernels. + // It is especially more effective for low sized kernels than copying + // specifically for big sized images. + // `This is virtual padding!` that means it produces two non-contiguous arrays. + // They will virtually replace image row, when convolution kernel goes out of bounds on Y coordinate. + let column_arena_k = + make_columns_arenas::(transient_image.as_slice(), image_size, column_kernel_shape); + + let top_pad = column_arena_k.top_pad.as_slice(); + let bottom_pad = column_arena_k.bottom_pad.as_slice(); + + let pad_h = column_kernel_shape.height / 2; + + let transient_image_slice = transient_image.as_slice(); + + let src_stride = image_size.width * N; + + for (y, dst) in destination + .chunks_exact_mut(image_size.width * N) + .enumerate() + { + let mut brows: Vec<&[T]> = vec![&transient_image_slice[0..]; column_kernel_shape.height]; + + for (k, row) in (0..column_kernel_shape.height).zip(brows.iter_mut()) { + if (y as i64 - pad_h as i64 + k as i64) < 0 { + *row = &top_pad[(pad_h - k - 1) * src_stride..]; + } else if (y as i64 - pad_h as i64 + k as i64) as usize >= image_size.height { + *row = &bottom_pad[(k - pad_h - 1) * src_stride..]; + } else { + let fy = (y as i64 + k as i64 - pad_h as i64) as usize; + let start_offset = src_stride * fy; + *row = &transient_image_slice[start_offset..(start_offset + src_stride)]; + } + } + + let brows_slice = brows.as_slice(); + + filter_symmetric_column::(brows_slice, dst, image_size, &scanned_column_kernel); + } + + Ok(()) +} + +pub(crate) fn filter_2d_sep_plane( + image: &[u8], + destination: &mut [u8], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_la( + image: &[u8], + destination: &mut [u8], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgb( + image: &[u8], + destination: &mut [u8], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgba( + image: &[u8], + destination: &mut [u8], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_la_f32( + image: &[f32], + destination: &mut [f32], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_plane_f32( + image: &[f32], + destination: &mut [f32], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgb_f32( + image: &[f32], + destination: &mut [f32], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgba_f32( + image: &[f32], + destination: &mut [f32], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgb_u16( + image: &[u16], + destination: &mut [u16], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_rgba_u16( + image: &[u16], + destination: &mut [u16], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_la_u16( + image: &[u16], + destination: &mut [u16], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} + +pub(crate) fn filter_2d_sep_plane_u16( + image: &[u16], + destination: &mut [u16], + image_size: FilterImageSize, + row_kernel: &[f32], + column_kernel: &[f32], +) -> Result<(), ImageError> { + filter_2d_separable::( + image, + destination, + image_size, + row_kernel, + column_kernel, + ) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,8 @@ //! Image Processing Functions use std::cmp; -use crate::image::{GenericImage, GenericImageView, SubImage}; use crate::traits::{Lerp, Pixel, Primitive}; +use crate::{GenericImage, GenericImageView, SubImage}; pub use self::sample::FilterType; @@ -15,7 +15,6 @@ rotate90, rotate90_in, }; -/// Image sampling pub use self::sample::{ blur, filter3x3, interpolate_bilinear, interpolate_nearest, resize, sample_bilinear, sample_nearest, thumbnail, unsharpen, @@ -31,8 +30,14 @@ // Public only because of Rust bug: // https://github.com/rust-lang/rust/issues/18241 pub mod colorops; +mod fast_blur; +mod filter_1d; mod sample; +pub use fast_blur::fast_blur; +pub(crate) use sample::gaussian_blur_dyn_image; +pub use sample::{blur_advanced, GaussianBlurParameters}; + /// Return a mutable view into an image /// The coordinates set the position of the top left corner of the crop. pub fn crop( @@ -132,6 +137,7 @@ /// ``` /// /// Proof is the same for height. +#[must_use] pub fn overlay_bounds( (bottom_width, bottom_height): (u32, u32), (top_width, top_height): (u32, u32), @@ -165,7 +171,6 @@ /// In particular, we want to ensure that all these coordinate accesses are safe: /// 1. `bottom.get_pixel(origin_bottom_x + [0..x_range), origin_bottom_y + [0..y_range))` /// 2. `top.get_pixel(origin_top_y + [0..x_range), origin_top_y + [0..y_range))` -/// fn overlay_bounds_ext( (bottom_width, bottom_height): (u32, u32), (top_width, top_height): (u32, u32), @@ -242,7 +247,7 @@ /// /// # Examples /// ```no_run -/// use image::{RgbaImage}; +/// use image::RgbaImage; /// /// let mut img = RgbaImage::new(1920, 1080); /// let tile = image::open("tile.png").unwrap(); @@ -352,9 +357,12 @@ #[cfg(test)] mod tests { - use super::{overlay, overlay_bounds_ext}; + use super::*; use crate::color::Rgb; + use crate::GrayAlphaImage; + use crate::GrayImage; use crate::ImageBuffer; + use crate::RgbImage; use crate::RgbaImage; #[test] @@ -438,8 +446,8 @@ overlay( &mut target, &source, - i64::from(u32::max_value() - 31), - i64::from(u32::max_value() - 31), + i64::from(u32::MAX - 31), + i64::from(u32::MAX - 31), ); assert!(*target.get_pixel(0, 0) == Rgb([0, 0, 0])); assert!(*target.get_pixel(1, 1) == Rgb([0, 0, 0])); @@ -477,9 +485,88 @@ } #[test] - /// Test blur doesn't panick when passed 0.0 + /// Test blur doesn't panic when passed 0.0 fn test_blur_zero() { let image = RgbaImage::new(50, 50); - let _ = super::blur(&image, 0.0); + let _ = blur(&image, 0.); + } + + #[test] + /// Test fast blur doesn't panic when passed 0.0 + fn test_fast_blur_zero() { + let image = RgbaImage::new(50, 50); + let _ = fast_blur(&image, 0.0); + } + + #[test] + /// Test fast blur doesn't panic when passed negative numbers + fn test_fast_blur_negative() { + let image = RgbaImage::new(50, 50); + let _ = fast_blur(&image, -1.0); + } + + #[test] + /// Test fast blur doesn't panic when sigma produces boxes larger than the image + fn test_fast_large_sigma() { + let image = RgbaImage::new(1, 1); + let _ = fast_blur(&image, 50.0); + } + + #[test] + /// Test blur doesn't panic when passed an empty image (any direction) + fn test_fast_blur_empty() { + let image = RgbaImage::new(0, 0); + let _ = fast_blur(&image, 1.0); + let image = RgbaImage::new(20, 0); + let _ = fast_blur(&image, 1.0); + let image = RgbaImage::new(0, 20); + let _ = fast_blur(&image, 1.0); + } + + #[test] + /// Test fast blur works with 3 channels + fn test_fast_blur_3_channels() { + let image = RgbImage::new(50, 50); + let _ = fast_blur(&image, 1.0); + } + + #[test] + /// Test fast blur works with 2 channels + fn test_fast_blur_2_channels() { + let image = GrayAlphaImage::new(50, 50); + let _ = fast_blur(&image, 1.0); + } + + #[test] + /// Test fast blur works with 1 channel + fn test_fast_blur_1_channels() { + let image = GrayImage::new(50, 50); + let _ = fast_blur(&image, 1.0); + } + + #[test] + #[cfg(feature = "tiff")] + fn fast_blur_approximates_gaussian_blur_well() { + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/images/tiff/testsuite/rgb-3c-16b.tiff" + ); + let image = crate::open(path).unwrap(); + let image_blurred_gauss = image + .blur_advanced(GaussianBlurParameters::new_from_sigma(50.0)) + .to_rgb8(); + let image_blurred_gauss_samples = image_blurred_gauss.as_flat_samples(); + let image_blurred_gauss_bytes = image_blurred_gauss_samples.as_slice(); + let image_blurred_fast = image.fast_blur(50.0).to_rgb8(); + let image_blurred_fast_samples = image_blurred_fast.as_flat_samples(); + let image_blurred_fast_bytes = image_blurred_fast_samples.as_slice(); + + let error = image_blurred_gauss_bytes + .iter() + .zip(image_blurred_fast_bytes.iter()) + .map(|(a, b)| (f32::from(*a) - f32::from(*b)) / f32::from(*a)) + .sum::() + / (image_blurred_gauss_bytes.len() as f32); + assert!(error < 0.05); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/sample.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/sample.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/imageops/sample.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/imageops/sample.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,14 +3,23 @@ // See http://cs.brown.edu/courses/cs123/lectures/08_Image_Processing_IV.pdf // for some of the theory behind image scaling and convolution -use std::f32; - use num_traits::{NumCast, ToPrimitive, Zero}; +use std::f32; +use std::ops::Mul; -use crate::image::{GenericImage, GenericImageView}; +use crate::imageops::filter_1d::{ + filter_2d_sep_la, filter_2d_sep_la_f32, filter_2d_sep_la_u16, filter_2d_sep_plane, + filter_2d_sep_plane_f32, filter_2d_sep_plane_u16, filter_2d_sep_rgb, filter_2d_sep_rgb_f32, + filter_2d_sep_rgb_u16, filter_2d_sep_rgba, filter_2d_sep_rgba_f32, filter_2d_sep_rgba_u16, + FilterImageSize, +}; +use crate::images::buffer::{Gray16Image, GrayAlpha16Image, Rgb16Image, Rgba16Image}; use crate::traits::{Enlargeable, Pixel, Primitive}; use crate::utils::clamp; -use crate::{ImageBuffer, Rgba32FImage}; +use crate::{ + DynamicImage, GenericImage, GenericImageView, GrayAlphaImage, GrayImage, ImageBuffer, + Rgb32FImage, RgbImage, Rgba32FImage, RgbaImage, +}; /// Available Sampling Filters. /// @@ -18,35 +27,35 @@ /// /// To test the different sampling filters on a real example, you can find two /// examples called -/// [`scaledown`](https://github.com/image-rs/image/tree/master/examples/scaledown) +/// [`scaledown`](https://github.com/image-rs/image/tree/main/examples/scaledown) /// and -/// [`scaleup`](https://github.com/image-rs/image/tree/master/examples/scaleup) +/// [`scaleup`](https://github.com/image-rs/image/tree/main/examples/scaleup) /// in the `examples` directory of the crate source code. /// /// Here is a 3.58 MiB -/// [test image](https://github.com/image-rs/image/blob/master/examples/scaledown/test.jpg) +/// [test image](https://github.com/image-rs/image/blob/main/examples/scaledown/test.jpg) /// that has been scaled down to 300x225 px: /// /// ///

///
-///
+///
/// Nearest Neighbor ///
///
-///
+///
/// Linear: Triangle ///
///
-///
+///
/// Cubic: Catmull-Rom ///
///
-///
+///
/// Gaussian ///
///
-///
+///
/// Lanczos with window 3 ///
///
@@ -78,7 +87,8 @@ /// 1170 ms /// /// -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FilterType { /// Nearest Neighbor Nearest, @@ -221,6 +231,8 @@ // ```new_width``` is the desired width of the new image // ```filter``` is the filter to use for sampling. // ```image``` is not necessarily Rgba and the order of channels is passed through. +// +// Note: if an empty image is passed in, panics unless the image is truly empty. fn horizontal_sample( image: &Rgba32FImage, new_width: u32, @@ -231,7 +243,15 @@ S: Primitive + 'static, { let (width, height) = image.dimensions(); + // This is protection against a memory usage similar to #2340. See `vertical_sample`. + assert!( + // Checks the implication: (width == 0) -> (height == 0) + width != 0 || height == 0, + "Unexpected prior allocation size. This case should have been handled by the caller" + ); + let mut out = ImageBuffer::new(new_width, height); + out.copy_color_space_from(image); let mut ws = Vec::new(); let max: f32 = NumCast::from(S::DEFAULT_MAX_VALUE).unwrap(); @@ -272,7 +292,9 @@ ws.push(w); sum += w; } - ws.iter_mut().for_each(|w| *w /= sum); + for w in ws.iter_mut() { + *w /= sum; + } for y in 0..height { let mut t = (0.0, 0.0, 0.0, 0.0); @@ -463,6 +485,8 @@ // ```filter``` is the filter to use for sampling. // The return value is not necessarily Rgba, the underlying order of channels in ```image``` is // preserved. +// +// Note: if an empty image is passed in, panics unless the image is truly empty. fn vertical_sample(image: &I, new_height: u32, filter: &mut Filter) -> Rgba32FImage where I: GenericImageView, @@ -470,7 +494,17 @@ S: Primitive + 'static, { let (width, height) = image.dimensions(); + + // This is protection against a regression in memory usage such as #2340. Since the strategy to + // deal with it depends on the caller it is a precondition of this function. + assert!( + // Checks the implication: (height == 0) -> (width == 0) + height != 0 || width == 0, + "Unexpected prior allocation size. This case should have been handled by the caller" + ); + let mut out = ImageBuffer::new(width, new_height); + out.copy_color_space_from(&image.buffer_with_dimensions(0, 0)); let mut ws = Vec::new(); let ratio = height as f32 / new_height as f32; @@ -501,7 +535,9 @@ ws.push(w); sum += w; } - ws.iter_mut().for_each(|w| *w /= sum); + for w in ws.iter_mut() { + *w /= sum; + } for x in 0..width { let mut t = (0.0, 0.0, 0.0, 0.0); @@ -581,7 +617,8 @@ S: Primitive + Enlargeable + 'static, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(new_width, new_height); + let mut out = image.buffer_with_dimensions(new_width, new_height); + if height == 0 || width == 0 { return out; } @@ -823,7 +860,14 @@ } /// Perform a 3x3 box filter on the supplied image. -/// ```kernel``` is an array of the filter weights of length 9. +/// +/// # Arguments: +/// +/// * `image` - source image. +/// * `kernel` - is an array of the filter weights of length 9. +/// +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. pub fn filter3x3(image: &I, kernel: &[f32]) -> ImageBuffer> where I: GenericImageView, @@ -844,17 +888,15 @@ ]; let (width, height) = image.dimensions(); - - let mut out = ImageBuffer::new(width, height); + let mut out = image.buffer_like(); let max = S::DEFAULT_MAX_VALUE; let max: f32 = NumCast::from(max).unwrap(); - let sum = match kernel.iter().fold(0.0, |s, &item| s + item) { - x if x == 0.0 => 1.0, - sum => sum, + let inverse_sum = match kernel.iter().sum() { + 0.0 => 1.0, + sum => 1.0 / sum, }; - let sum = (sum, sum, sum, sum); for y in 1..height - 1 { for x in 1..width - 1 { @@ -864,7 +906,6 @@ // Only a subtract and addition is needed for pixels after the first // in each row. for (&k, &(a, b)) in kernel.iter().zip(taps.iter()) { - let k = (k, k, k, k); let x0 = x as isize + a; let y0 = y as isize + b; @@ -880,13 +921,18 @@ NumCast::from(k4).unwrap(), ); - t.0 += vec.0 * k.0; - t.1 += vec.1 * k.1; - t.2 += vec.2 * k.2; - t.3 += vec.3 * k.3; + t.0 += vec.0 * k; + t.1 += vec.1 * k; + t.2 += vec.2 * k; + t.3 += vec.3 * k; } - let (t1, t2, t3, t4) = (t.0 / sum.0, t.1 / sum.1, t.2 / sum.2, t.3 / sum.3); + let (t1, t2, t3, t4) = ( + t.0 * inverse_sum, + t.1 * inverse_sum, + t.2 * inverse_sum, + t.3 * inverse_sum, + ); #[allow(deprecated)] let t = Pixel::from_channels( @@ -904,8 +950,17 @@ } /// Resize the supplied image to the specified dimensions. -/// ```nwidth``` and ```nheight``` are the new dimensions. -/// ```filter``` is the sampling filter to use. +/// +/// # Arguments: +/// +/// * `nwidth` - new image width. +/// * `nheight` - new image height. +/// * `filter` - is the sampling filter to use, see [FilterType] for mor information. +/// +/// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. pub fn resize( image: &I, nwidth: u32, @@ -916,9 +971,19 @@ I::Pixel: 'static, ::Subpixel: 'static, { + // Check if there is nothing to sample from. + let is_empty = { + let (width, height) = image.dimensions(); + width == 0 || height == 0 + }; + + if is_empty { + return image.buffer_with_dimensions(nwidth, nheight); + } + // check if the new dimensions are the same as the old. if they are, make a copy instead of resampling if (nwidth, nheight) == image.dimensions() { - let mut tmp = ImageBuffer::new(image.width(), image.height()); + let mut tmp = image.buffer_like(); tmp.copy_from(image, 0, 0).unwrap(); return tmp; } @@ -952,7 +1017,16 @@ } /// Performs a Gaussian blur on the supplied image. -/// ```sigma``` is a measure of how much to blur by. +/// +/// # Arguments +/// +/// - `sigma` - gaussian bell flattening level. +/// +/// Use [`crate::imageops::fast_blur()`] for a faster but less +/// accurate version. +/// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. pub fn blur( image: &I, sigma: f32, @@ -960,34 +1034,550 @@ where I::Pixel: 'static, { - let sigma = if sigma <= 0.0 { 1.0 } else { sigma }; + gaussian_blur_indirect( + image, + GaussianBlurParameters::new_from_sigma(if sigma == 0.0 { 0.8 } else { sigma }), + ) +} + +/// Performs a Gaussian blur on the supplied image. +/// +/// # Arguments +/// +/// - `parameters` - see [GaussianBlurParameters] for more info. +/// +/// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. +pub fn blur_advanced( + image: &I, + parameters: GaussianBlurParameters, +) -> ImageBuffer::Subpixel>> +where + I::Pixel: 'static, +{ + gaussian_blur_indirect(image, parameters) +} - let mut method = Filter { - kernel: Box::new(|x| gaussian(x, sigma)), - support: 2.0 * sigma, +fn get_gaussian_kernel_1d(width: usize, sigma: f32) -> Vec { + let mut sum_norm: f32 = 0f32; + let mut kernel = vec![0f32; width]; + let scale = 1f32 / (f32::sqrt(2f32 * f32::consts::PI) * sigma); + let mean = (width / 2) as f32; + + for (x, weight) in kernel.iter_mut().enumerate() { + let new_weight = f32::exp(-0.5f32 * f32::powf((x as f32 - mean) / sigma, 2.0f32)) * scale; + *weight = new_weight; + sum_norm += new_weight; + } + + if sum_norm != 0f32 { + let sum_scale = 1f32 / sum_norm; + for weight in &mut kernel { + *weight = weight.mul(sum_scale); + } + } + + kernel +} + +/// Holds analytical gaussian blur representation +#[derive(Copy, Clone, PartialOrd, PartialEq)] +pub struct GaussianBlurParameters { + /// X-axis kernel, must be odd + x_axis_kernel_size: u32, + /// X-axis sigma, must > 0, not subnormal, and not NaN + x_axis_sigma: f32, + /// Y-axis kernel, must be odd + y_axis_kernel_size: u32, + /// Y-axis sigma, must > 0, not subnormal, and not NaN + y_axis_sigma: f32, +} + +impl GaussianBlurParameters { + /// Built-in smoothing kernel with size 3. + pub const SMOOTHING_3: GaussianBlurParameters = GaussianBlurParameters { + x_axis_kernel_size: 3, + x_axis_sigma: 0.8, + y_axis_kernel_size: 3, + y_axis_sigma: 0.8, }; - let (width, height) = image.dimensions(); + /// Built-in smoothing kernel with size 5. + pub const SMOOTHING_5: GaussianBlurParameters = GaussianBlurParameters { + x_axis_kernel_size: 5, + x_axis_sigma: 1.1, + y_axis_kernel_size: 5, + y_axis_sigma: 1.1, + }; - // Keep width and height the same for horizontal and - // vertical sampling. - // Note: tmp is not necessarily actually Rgba - let tmp: Rgba32FImage = vertical_sample(image, height, &mut method); - horizontal_sample(&tmp, width, &mut method) + /// Built-in smoothing kernel with size 7. + pub const SMOOTHING_7: GaussianBlurParameters = GaussianBlurParameters { + x_axis_kernel_size: 7, + x_axis_sigma: 1.4, + y_axis_kernel_size: 7, + y_axis_sigma: 1.4, + }; + + /// Creates a new parameters set from radius only. + pub fn new_from_radius(radius: f32) -> GaussianBlurParameters { + // Previous implementation was allowing passing 0 so we'll allow here also. + assert!(radius >= 0.0); + if radius != 0. { + assert!( + radius.is_normal(), + "Radius do not allow infinities, NaNs or subnormals" + ); + } + GaussianBlurParameters::new_from_kernel_size(radius * 2. + 1.) + } + + /// Creates a new parameters set from kernel size only. + /// + /// Kernel size will be rounded to nearest odd, and used with fraction + /// to compute accurate required sigma. + pub fn new_from_kernel_size(kernel_size: f32) -> GaussianBlurParameters { + assert!( + kernel_size > 0., + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + assert!( + kernel_size.is_normal(), + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + let i_kernel_size = GaussianBlurParameters::round_to_nearest_odd(kernel_size); + assert_ne!(i_kernel_size % 2, 0, "Kernel size must be odd"); + let v_sigma = GaussianBlurParameters::sigma_size(kernel_size); + GaussianBlurParameters { + x_axis_kernel_size: i_kernel_size, + x_axis_sigma: v_sigma, + y_axis_kernel_size: i_kernel_size, + y_axis_sigma: v_sigma, + } + } + + /// Creates a new anisotropic parameter set from kernel sizes + /// + /// Kernel size will be rounded to nearest odd, and used with fraction + /// to compute accurate required sigma. + pub fn new_anisotropic_kernel_size( + x_axis_kernel_size: f32, + y_axis_kernel_size: f32, + ) -> GaussianBlurParameters { + assert!( + x_axis_kernel_size > 0., + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + assert!( + y_axis_kernel_size.is_normal(), + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + assert!( + y_axis_kernel_size > 0., + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + assert!( + y_axis_kernel_size.is_normal(), + "Kernel size do not allow infinities, zeros, NaNs or subnormals or negatives" + ); + let x_kernel_size = GaussianBlurParameters::round_to_nearest_odd(x_axis_kernel_size); + assert_ne!(x_kernel_size % 2, 0, "Kernel size must be odd"); + let y_kernel_size = GaussianBlurParameters::round_to_nearest_odd(y_axis_kernel_size); + assert_ne!(y_kernel_size % 2, 0, "Kernel size must be odd"); + let x_sigma = GaussianBlurParameters::sigma_size(x_axis_kernel_size); + let y_sigma = GaussianBlurParameters::sigma_size(y_axis_kernel_size); + GaussianBlurParameters { + x_axis_kernel_size: x_kernel_size, + x_axis_sigma: x_sigma, + y_axis_kernel_size: y_kernel_size, + y_axis_sigma: y_sigma, + } + } + + /// Creates a new parameters set from sigma only + pub fn new_from_sigma(sigma: f32) -> GaussianBlurParameters { + assert!( + sigma.is_normal(), + "Sigma cannot be NaN, Infinities, subnormal or zero" + ); + assert!(sigma > 0.0, "Sigma must be positive"); + let kernel_size = GaussianBlurParameters::kernel_size_from_sigma(sigma); + GaussianBlurParameters { + x_axis_kernel_size: kernel_size, + x_axis_sigma: sigma, + y_axis_kernel_size: kernel_size, + y_axis_sigma: sigma, + } + } + + #[inline] + fn round_to_nearest_odd(x: f32) -> u32 { + let n = x.round() as u32; + if n % 2 != 0 { + n + } else { + let lower = n - 1; + let upper = n + 1; + + let dist_lower = (x - lower as f32).abs(); + let dist_upper = (x - upper as f32).abs(); + + if dist_lower <= dist_upper { + lower + } else { + upper + } + } + } + + fn sigma_size(kernel_size: f32) -> f32 { + let safe_kernel_size = if kernel_size <= 1. { 0.8 } else { kernel_size }; + 0.3 * ((safe_kernel_size - 1.) * 0.5 - 1.) + 0.8 + } + + fn kernel_size_from_sigma(sigma: f32) -> u32 { + let possible_size = (((((sigma - 0.8) / 0.3) + 1.) * 2.) + 1.).max(3.) as u32; + if possible_size % 2 == 0 { + return possible_size + 1; + } + possible_size + } +} + +pub(crate) fn gaussian_blur_dyn_image( + image: &DynamicImage, + parameters: GaussianBlurParameters, +) -> DynamicImage { + let x_axis_kernel = get_gaussian_kernel_1d( + parameters.x_axis_kernel_size as usize, + parameters.x_axis_sigma, + ); + + let y_axis_kernel = get_gaussian_kernel_1d( + parameters.y_axis_kernel_size as usize, + parameters.y_axis_sigma, + ); + + let filter_image_size = FilterImageSize { + width: image.width() as usize, + height: image.height() as usize, + }; + + let mut target = match image { + DynamicImage::ImageLuma8(img) => { + let mut dest_image = vec![0u8; img.len()]; + filter_2d_sep_plane( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageLuma8( + GrayImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageLumaA8(img) => { + let mut dest_image = vec![0u8; img.len()]; + filter_2d_sep_la( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageLumaA8( + GrayAlphaImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgb8(img) => { + let mut dest_image = vec![0u8; img.len()]; + filter_2d_sep_rgb( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgb8( + RgbImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgba8(img) => { + let mut dest_image = vec![0u8; img.len()]; + filter_2d_sep_rgba( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgba8( + RgbaImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageLuma16(img) => { + let mut dest_image = vec![0u16; img.len()]; + filter_2d_sep_plane_u16( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageLuma16( + Gray16Image::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageLumaA16(img) => { + let mut dest_image = vec![0u16; img.len()]; + filter_2d_sep_la_u16( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageLumaA16( + GrayAlpha16Image::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgb16(img) => { + let mut dest_image = vec![0u16; img.len()]; + filter_2d_sep_rgb_u16( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgb16( + Rgb16Image::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgba16(img) => { + let mut dest_image = vec![0u16; img.len()]; + filter_2d_sep_rgba_u16( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgba16( + Rgba16Image::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgb32F(img) => { + let mut dest_image = vec![0f32; img.len()]; + filter_2d_sep_rgb_f32( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgb32F( + Rgb32FImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + DynamicImage::ImageRgba32F(img) => { + let mut dest_image = vec![0f32; img.len()]; + filter_2d_sep_rgba_f32( + img.as_raw(), + &mut dest_image, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + DynamicImage::ImageRgba32F( + Rgba32FImage::from_raw(img.width(), img.height(), dest_image).unwrap(), + ) + } + }; + + // Must succeed. + let _ = target.set_color_space(image.color_space()); + target +} + +fn gaussian_blur_indirect( + image: &I, + parameters: GaussianBlurParameters, +) -> ImageBuffer::Subpixel>> +where + I::Pixel: 'static, +{ + match I::Pixel::CHANNEL_COUNT { + 1 => gaussian_blur_indirect_impl::(image, parameters), + 2 => gaussian_blur_indirect_impl::(image, parameters), + 3 => gaussian_blur_indirect_impl::(image, parameters), + 4 => gaussian_blur_indirect_impl::(image, parameters), + _ => unimplemented!(), + } +} + +fn gaussian_blur_indirect_impl( + image: &I, + parameters: GaussianBlurParameters, +) -> ImageBuffer::Subpixel>> +where + I::Pixel: 'static, +{ + let mut transient = vec![0f32; image.width() as usize * image.height() as usize * CN]; + for (pixel, dst) in image.pixels().zip(transient.chunks_exact_mut(CN)) { + let px = pixel.2.channels(); + match CN { + 1 => { + dst[0] = NumCast::from(px[0]).unwrap(); + } + 2 => { + dst[0] = NumCast::from(px[0]).unwrap(); + dst[1] = NumCast::from(px[1]).unwrap(); + } + 3 => { + dst[0] = NumCast::from(px[0]).unwrap(); + dst[1] = NumCast::from(px[1]).unwrap(); + dst[2] = NumCast::from(px[2]).unwrap(); + } + 4 => { + dst[0] = NumCast::from(px[0]).unwrap(); + dst[1] = NumCast::from(px[1]).unwrap(); + dst[2] = NumCast::from(px[2]).unwrap(); + dst[3] = NumCast::from(px[3]).unwrap(); + } + _ => unreachable!(), + } + } + + let mut transient_dst = vec![0.; image.width() as usize * image.height() as usize * CN]; + + let x_axis_kernel = get_gaussian_kernel_1d( + parameters.x_axis_kernel_size as usize, + parameters.x_axis_sigma, + ); + let y_axis_kernel = get_gaussian_kernel_1d( + parameters.y_axis_kernel_size as usize, + parameters.y_axis_sigma, + ); + + let filter_image_size = FilterImageSize { + width: image.width() as usize, + height: image.height() as usize, + }; + + match CN { + 1 => { + filter_2d_sep_plane_f32( + &transient, + &mut transient_dst, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + } + 2 => { + filter_2d_sep_la_f32( + &transient, + &mut transient_dst, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + } + 3 => { + filter_2d_sep_rgb_f32( + &transient, + &mut transient_dst, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + } + 4 => { + filter_2d_sep_rgba_f32( + &transient, + &mut transient_dst, + filter_image_size, + &x_axis_kernel, + &y_axis_kernel, + ) + .unwrap(); + } + _ => unreachable!(), + } + + let mut out = image.buffer_like(); + for (dst, src) in out.pixels_mut().zip(transient_dst.chunks_exact_mut(CN)) { + match CN { + 1 => { + let v0 = NumCast::from(FloatNearest(src[0])).unwrap(); + #[allow(deprecated)] + let t = Pixel::from_channels(v0, v0, v0, v0); + *dst = t; + } + 2 => { + let v0 = NumCast::from(FloatNearest(src[0])).unwrap(); + let v1 = NumCast::from(FloatNearest(src[1])).unwrap(); + #[allow(deprecated)] + let t = Pixel::from_channels(v0, v1, v0, v0); + *dst = t; + } + 3 => { + let v0 = NumCast::from(FloatNearest(src[0])).unwrap(); + let v1 = NumCast::from(FloatNearest(src[1])).unwrap(); + let v2 = NumCast::from(FloatNearest(src[2])).unwrap(); + #[allow(deprecated)] + let t = Pixel::from_channels(v0, v1, v2, v0); + *dst = t; + } + 4 => { + let v0 = NumCast::from(FloatNearest(src[0])).unwrap(); + let v1 = NumCast::from(FloatNearest(src[1])).unwrap(); + let v2 = NumCast::from(FloatNearest(src[2])).unwrap(); + let v3 = NumCast::from(FloatNearest(src[3])).unwrap(); + #[allow(deprecated)] + let t = Pixel::from_channels(v0, v1, v2, v3); + *dst = t; + } + _ => unreachable!(), + } + } + + out } /// Performs an unsharpen mask on the supplied image. -/// ```sigma``` is the amount to blur the image by. -/// ```threshold``` is the threshold for minimal brightness change that will be sharpened. /// -/// See +/// # Arguments: +/// +/// * `sigma` - is the amount to blur the image by. +/// * `threshold` - is the threshold for minimal brightness change that will be sharpened. +/// +/// This method typically assumes that the input is scene-linear light. +/// If it is not, color distortion may occur. +/// +/// See [Digital unsharp masking](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) for more information. pub fn unsharpen(image: &I, sigma: f32, threshold: i32) -> ImageBuffer> where I: GenericImageView, P: Pixel + 'static, S: Primitive + 'static, { - let mut tmp = blur(image, sigma); + let mut tmp = blur_advanced(image, GaussianBlurParameters::new_from_sigma(sigma)); let max = S::DEFAULT_MAX_VALUE; let max: i32 = NumCast::from(max).unwrap(); @@ -1044,7 +1634,7 @@ use std::path::Path; let img = crate::open(Path::new("./examples/fractal.png")).unwrap(); let resize = img.resize(img.width(), img.height(), FilterType::Triangle); - assert!(img.pixels().eq(resize.pixels())) + assert!(img.pixels().eq(resize.pixels())); } #[test] @@ -1167,7 +1757,7 @@ b.iter(|| { test::black_box(image.resize(image.width(), image.height(), FilterType::CatmullRom)); }); - b.bytes = (image.width() * image.height() * 3) as u64; + b.bytes = u64::from(image.width() * image.height() * 3); } #[test] @@ -1232,9 +1822,7 @@ let alpha = pixel.0[3]; assert!( alpha != 254 && alpha != 253, - "alpha value: {}, {:?}", - alpha, - filter + "alpha value: {alpha}, {filter:?}" ); } } @@ -1257,4 +1845,26 @@ let result = resize(&image, 22, 22, FilterType::Lanczos3); assert!(result.into_raw().into_iter().any(|c| c != 0)); } + + #[test] + fn issue_2340() { + let empty = crate::GrayImage::from_raw(1 << 31, 0, vec![]).unwrap(); + // Really we're checking that no overflow / outsized allocation happens here. + let result = resize(&empty, 1, 1, FilterType::Lanczos3); + assert!(result.into_raw().into_iter().all(|c| c == 0)); + // With the previous strategy before the regression this would allocate 1TB of memory for a + // temporary during the sampling evaluation. + let result = resize(&empty, 256, 256, FilterType::Lanczos3); + assert!(result.into_raw().into_iter().all(|c| c == 0)); + } + + #[test] + fn issue_2340_refl() { + // Tests the swapped coordinate version of `issue_2340`. + let empty = crate::GrayImage::from_raw(0, 1 << 31, vec![]).unwrap(); + let result = resize(&empty, 1, 1, FilterType::Lanczos3); + assert!(result.into_raw().into_iter().all(|c| c == 0)); + let result = resize(&empty, 256, 256, FilterType::Lanczos3); + assert!(result.into_raw().into_iter().all(|c| c == 0)); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2214 @@ +//! Contains the generic `ImageBuffer` struct. +use num_traits::Zero; +use std::fmt; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut, Index, IndexMut, Range}; +use std::path::Path; +use std::slice::{ChunksExact, ChunksExactMut}; + +use crate::color::{FromColor, FromPrimitive, Luma, LumaA, Rgb, Rgba}; +use crate::error::{ + ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, +}; +use crate::flat::{FlatSamples, SampleLayout}; +use crate::math::Rect; +use crate::metadata::cicp::{CicpApplicable, CicpPixelCast, CicpRgb, ColorComponentForCicp}; +use crate::traits::{EncodableLayout, Pixel, PixelWithColorType}; +use crate::utils::expand_packed; +use crate::{ + metadata::{Cicp, CicpColorPrimaries, CicpTransferCharacteristics, CicpTransform}, + save_buffer, save_buffer_with_format, write_buffer_with_format, ImageError, +}; +use crate::{DynamicImage, GenericImage, GenericImageView, ImageEncoder, ImageFormat}; + +/// Iterate over pixel refs. +pub struct Pixels<'a, P: Pixel + 'a> +where + P::Subpixel: 'a, +{ + chunks: ChunksExact<'a, P::Subpixel>, +} + +impl<'a, P: Pixel + 'a> Iterator for Pixels<'a, P> +where + P::Subpixel: 'a, +{ + type Item = &'a P; + + #[inline(always)] + fn next(&mut self) -> Option<&'a P> { + self.chunks.next().map(|v|

::from_slice(v)) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for Pixels<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.chunks.len() + } +} + +impl<'a, P: Pixel + 'a> DoubleEndedIterator for Pixels<'a, P> +where + P::Subpixel: 'a, +{ + #[inline(always)] + fn next_back(&mut self) -> Option<&'a P> { + self.chunks.next_back().map(|v|

::from_slice(v)) + } +} + +impl Clone for Pixels<'_, P> { + fn clone(&self) -> Self { + Pixels { + chunks: self.chunks.clone(), + } + } +} + +impl fmt::Debug for Pixels<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Pixels") + .field("chunks", &self.chunks) + .finish() + } +} + +/// Iterate over mutable pixel refs. +pub struct PixelsMut<'a, P: Pixel + 'a> +where + P::Subpixel: 'a, +{ + chunks: ChunksExactMut<'a, P::Subpixel>, +} + +impl<'a, P: Pixel + 'a> Iterator for PixelsMut<'a, P> +where + P::Subpixel: 'a, +{ + type Item = &'a mut P; + + #[inline(always)] + fn next(&mut self) -> Option<&'a mut P> { + self.chunks.next().map(|v|

::from_slice_mut(v)) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for PixelsMut<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.chunks.len() + } +} + +impl<'a, P: Pixel + 'a> DoubleEndedIterator for PixelsMut<'a, P> +where + P::Subpixel: 'a, +{ + #[inline(always)] + fn next_back(&mut self) -> Option<&'a mut P> { + self.chunks + .next_back() + .map(|v|

::from_slice_mut(v)) + } +} + +impl fmt::Debug for PixelsMut<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("PixelsMut") + .field("chunks", &self.chunks) + .finish() + } +} + +/// Iterate over rows of an image +/// +/// This iterator is created with [`ImageBuffer::rows`]. See its document for details. +/// +/// [`ImageBuffer::rows`]: ../struct.ImageBuffer.html#method.rows +pub struct Rows<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + pixels: ChunksExact<'a, P::Subpixel>, +} + +impl<'a, P: Pixel + 'a> Rows<'a, P> { + /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic + /// condition. The `pixels` slice must be large enough so that all pixels are addressable. + fn with_image(pixels: &'a [P::Subpixel], width: u32, height: u32) -> Self { + let row_len = (width as usize) * usize::from(

::CHANNEL_COUNT); + if row_len == 0 { + Rows { + pixels: [].chunks_exact(1), + } + } else { + let pixels = pixels + .get(..row_len * height as usize) + .expect("Pixel buffer has too few subpixels"); + // Rows are physically present. In particular, height is smaller than `usize::MAX` as + // all subpixels can be indexed. + Rows { + pixels: pixels.chunks_exact(row_len), + } + } + } +} + +impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P> +where + P::Subpixel: 'a, +{ + type Item = Pixels<'a, P>; + + #[inline(always)] + fn next(&mut self) -> Option> { + let row = self.pixels.next()?; + Some(Pixels { + // Note: this is not reached when CHANNEL_COUNT is 0. + chunks: row.chunks_exact(

::CHANNEL_COUNT as usize), + }) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.pixels.len() + } +} + +impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P> +where + P::Subpixel: 'a, +{ + #[inline(always)] + fn next_back(&mut self) -> Option> { + let row = self.pixels.next_back()?; + Some(Pixels { + // Note: this is not reached when CHANNEL_COUNT is 0. + chunks: row.chunks_exact(

::CHANNEL_COUNT as usize), + }) + } +} + +impl Clone for Rows<'_, P> { + fn clone(&self) -> Self { + Rows { + pixels: self.pixels.clone(), + } + } +} + +impl fmt::Debug for Rows<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Rows") + .field("pixels", &self.pixels) + .finish() + } +} + +/// Iterate over mutable rows of an image +/// +/// This iterator is created with [`ImageBuffer::rows_mut`]. See its document for details. +/// +/// [`ImageBuffer::rows_mut`]: ../struct.ImageBuffer.html#method.rows_mut +pub struct RowsMut<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + pixels: ChunksExactMut<'a, P::Subpixel>, +} + +impl<'a, P: Pixel + 'a> RowsMut<'a, P> { + /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic + /// condition. The `pixels` slice must be large enough so that all pixels are addressable. + fn with_image(pixels: &'a mut [P::Subpixel], width: u32, height: u32) -> Self { + let row_len = (width as usize) * usize::from(

::CHANNEL_COUNT); + if row_len == 0 { + RowsMut { + pixels: [].chunks_exact_mut(1), + } + } else { + let pixels = pixels + .get_mut(..row_len * height as usize) + .expect("Pixel buffer has too few subpixels"); + // Rows are physically present. In particular, height is smaller than `usize::MAX` as + // all subpixels can be indexed. + RowsMut { + pixels: pixels.chunks_exact_mut(row_len), + } + } + } +} + +impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P> +where + P::Subpixel: 'a, +{ + type Item = PixelsMut<'a, P>; + + #[inline(always)] + fn next(&mut self) -> Option> { + let row = self.pixels.next()?; + Some(PixelsMut { + // Note: this is not reached when CHANNEL_COUNT is 0. + chunks: row.chunks_exact_mut(

::CHANNEL_COUNT as usize), + }) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.pixels.len() + } +} + +impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P> +where + P::Subpixel: 'a, +{ + #[inline(always)] + fn next_back(&mut self) -> Option> { + let row = self.pixels.next_back()?; + Some(PixelsMut { + // Note: this is not reached when CHANNEL_COUNT is 0. + chunks: row.chunks_exact_mut(

::CHANNEL_COUNT as usize), + }) + } +} + +impl fmt::Debug for RowsMut<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RowsMut") + .field("pixels", &self.pixels) + .finish() + } +} + +/// Enumerate the pixels of an image. +pub struct EnumeratePixels<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + pixels: Pixels<'a, P>, + x: u32, + y: u32, + width: u32, +} + +impl<'a, P: Pixel + 'a> Iterator for EnumeratePixels<'a, P> +where + P::Subpixel: 'a, +{ + type Item = (u32, u32, &'a P); + + #[inline(always)] + fn next(&mut self) -> Option<(u32, u32, &'a P)> { + if self.x >= self.width { + self.x = 0; + self.y += 1; + } + let (x, y) = (self.x, self.y); + self.x += 1; + self.pixels.next().map(|p| (x, y, p)) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixels<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.pixels.len() + } +} + +impl Clone for EnumeratePixels<'_, P> { + fn clone(&self) -> Self { + EnumeratePixels { + pixels: self.pixels.clone(), + ..*self + } + } +} + +impl fmt::Debug for EnumeratePixels<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumeratePixels") + .field("pixels", &self.pixels) + .field("x", &self.x) + .field("y", &self.y) + .field("width", &self.width) + .finish() + } +} + +/// Enumerate the rows of an image. +pub struct EnumerateRows<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + rows: Rows<'a, P>, + y: u32, + width: u32, +} + +impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P> +where + P::Subpixel: 'a, +{ + type Item = (u32, EnumeratePixels<'a, P>); + + #[inline(always)] + fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> { + let y = self.y; + self.y += 1; + self.rows.next().map(|r| { + ( + y, + EnumeratePixels { + x: 0, + y, + width: self.width, + pixels: r, + }, + ) + }) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.rows.len() + } +} + +impl Clone for EnumerateRows<'_, P> { + fn clone(&self) -> Self { + EnumerateRows { + rows: self.rows.clone(), + ..*self + } + } +} + +impl fmt::Debug for EnumerateRows<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumerateRows") + .field("rows", &self.rows) + .field("y", &self.y) + .field("width", &self.width) + .finish() + } +} + +/// Enumerate the pixels of an image. +pub struct EnumeratePixelsMut<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + pixels: PixelsMut<'a, P>, + x: u32, + y: u32, + width: u32, +} + +impl<'a, P: Pixel + 'a> Iterator for EnumeratePixelsMut<'a, P> +where + P::Subpixel: 'a, +{ + type Item = (u32, u32, &'a mut P); + + #[inline(always)] + fn next(&mut self) -> Option<(u32, u32, &'a mut P)> { + if self.x >= self.width { + self.x = 0; + self.y += 1; + } + let (x, y) = (self.x, self.y); + self.x += 1; + self.pixels.next().map(|p| (x, y, p)) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixelsMut<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.pixels.len() + } +} + +impl fmt::Debug for EnumeratePixelsMut<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumeratePixelsMut") + .field("pixels", &self.pixels) + .field("x", &self.x) + .field("y", &self.y) + .field("width", &self.width) + .finish() + } +} + +/// Enumerate the rows of an image. +pub struct EnumerateRowsMut<'a, P: Pixel + 'a> +where +

::Subpixel: 'a, +{ + rows: RowsMut<'a, P>, + y: u32, + width: u32, +} + +impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P> +where + P::Subpixel: 'a, +{ + type Item = (u32, EnumeratePixelsMut<'a, P>); + + #[inline(always)] + fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> { + let y = self.y; + self.y += 1; + self.rows.next().map(|r| { + ( + y, + EnumeratePixelsMut { + x: 0, + y, + width: self.width, + pixels: r, + }, + ) + }) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P> +where + P::Subpixel: 'a, +{ + fn len(&self) -> usize { + self.rows.len() + } +} + +impl fmt::Debug for EnumerateRowsMut<'_, P> +where + P::Subpixel: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumerateRowsMut") + .field("rows", &self.rows) + .field("y", &self.y) + .field("width", &self.width) + .finish() + } +} + +/// Generic image buffer +/// +/// This is an image parameterised by its Pixel types, represented by a width and height and a +/// container of channel data. It provides direct access to its pixels and implements the +/// [`GenericImageView`] and [`GenericImage`] traits. In many ways, this is the standard buffer +/// implementing those traits. Using this concrete type instead of a generic type parameter has +/// been shown to improve performance. +/// +/// The crate defines a few type aliases with regularly used pixel types for your convenience, such +/// as [`RgbImage`], [`GrayImage`] etc. +/// +/// [`GenericImage`]: trait.GenericImage.html +/// [`GenericImageView`]: trait.GenericImageView.html +/// [`RgbImage`]: type.RgbImage.html +/// [`GrayImage`]: type.GrayImage.html +/// +/// To convert between images of different Pixel types use [`DynamicImage`]. +/// +/// You can retrieve a complete description of the buffer's layout and contents through +/// [`as_flat_samples`] and [`as_flat_samples_mut`]. This can be handy to also use the contents in +/// a foreign language, map it as a GPU host buffer or other similar tasks. +/// +/// [`DynamicImage`]: enum.DynamicImage.html +/// [`as_flat_samples`]: #method.as_flat_samples +/// [`as_flat_samples_mut`]: #method.as_flat_samples_mut +/// +/// ## Examples +/// +/// Create a simple canvas and paint a small cross. +/// +/// ``` +/// use image::{RgbImage, Rgb}; +/// +/// let mut img = RgbImage::new(32, 32); +/// +/// for x in 15..=17 { +/// for y in 8..24 { +/// img.put_pixel(x, y, Rgb([255, 0, 0])); +/// img.put_pixel(y, x, Rgb([255, 0, 0])); +/// } +/// } +/// ``` +/// +/// Overlays an image on top of a larger background raster. +/// +/// ```no_run +/// use image::{GenericImage, GenericImageView, ImageBuffer, open}; +/// +/// let on_top = open("path/to/some.png").unwrap().into_rgb8(); +/// let mut img = ImageBuffer::from_fn(512, 512, |x, y| { +/// if (x + y) % 2 == 0 { +/// image::Rgb([0, 0, 0]) +/// } else { +/// image::Rgb([255, 255, 255]) +/// } +/// }); +/// +/// image::imageops::overlay(&mut img, &on_top, 128, 128); +/// ``` +/// +/// Convert an `RgbaImage` to a `GrayImage`. +/// +/// ```no_run +/// use image::{open, DynamicImage}; +/// +/// let rgba = open("path/to/some.png").unwrap().into_rgba8(); +/// let gray = DynamicImage::ImageRgba8(rgba).into_luma8(); +/// ``` +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ImageBuffer { + width: u32, + height: u32, + _phantom: PhantomData

, + color: CicpRgb, + data: Container, +} + +// generic implementation, shared along all image buffers +impl ImageBuffer +where + P: Pixel, + Container: Deref, +{ + /// Constructs a buffer from a generic container + /// (for example a `Vec` or a slice) + /// + /// Returns `None` if the container is not big enough (including when the image dimensions + /// necessitate an allocation of more bytes than supported by the container). + pub fn from_raw(width: u32, height: u32, buf: Container) -> Option> { + if Self::check_image_fits(width, height, buf.len()) { + Some(ImageBuffer { + data: buf, + width, + height, + color: Cicp::SRGB.into_rgb(), + _phantom: PhantomData, + }) + } else { + None + } + } + + /// Returns the underlying raw buffer + pub fn into_raw(self) -> Container { + self.data + } + + /// Returns the underlying raw buffer + pub fn as_raw(&self) -> &Container { + &self.data + } + + /// The width and height of this image. + pub fn dimensions(&self) -> (u32, u32) { + (self.width, self.height) + } + + /// The width of this image. + pub fn width(&self) -> u32 { + self.width + } + + /// The height of this image. + pub fn height(&self) -> u32 { + self.height + } + + // TODO: choose name under which to expose. + pub(crate) fn inner_pixels(&self) -> &[P::Subpixel] { + let len = Self::image_buffer_len(self.width, self.height).unwrap(); + &self.data[..len] + } + + /// Returns an iterator over the pixels of this image. + /// The iteration order is x = 0 to width then y = 0 to height + pub fn pixels(&self) -> Pixels<'_, P> { + Pixels { + chunks: self + .inner_pixels() + .chunks_exact(

::CHANNEL_COUNT as usize), + } + } + + /// Returns an iterator over the rows of this image. + /// + /// Only non-empty rows can be iterated in this manner. In particular the iterator will not + /// yield any item when the width of the image is `0` or a pixel type without any channels is + /// used. This ensures that its length can always be represented by `usize`. + pub fn rows(&self) -> Rows<'_, P> { + Rows::with_image(&self.data, self.width, self.height) + } + + /// Enumerates over the pixels of the image. + /// The iterator yields the coordinates of each pixel + /// along with a reference to them. + /// The iteration order is x = 0 to width then y = 0 to height + /// Starting from the top left. + pub fn enumerate_pixels(&self) -> EnumeratePixels<'_, P> { + EnumeratePixels { + pixels: self.pixels(), + x: 0, + y: 0, + width: self.width, + } + } + + /// Enumerates over the rows of the image. + /// The iterator yields the y-coordinate of each row + /// along with a reference to them. + pub fn enumerate_rows(&self) -> EnumerateRows<'_, P> { + EnumerateRows { + rows: self.rows(), + y: 0, + width: self.width, + } + } + + /// Gets a reference to the pixel at location `(x, y)` + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of the bounds `(width, height)`. + #[inline] + #[track_caller] + pub fn get_pixel(&self, x: u32, y: u32) -> &P { + match self.pixel_indices(x, y) { + None => panic!( + "Image index {:?} out of bounds {:?}", + (x, y), + (self.width, self.height) + ), + Some(pixel_indices) =>

::from_slice(&self.data[pixel_indices]), + } + } + + /// Gets a reference to the pixel at location `(x, y)` or returns `None` if + /// the index is out of the bounds `(width, height)`. + pub fn get_pixel_checked(&self, x: u32, y: u32) -> Option<&P> { + if x >= self.width { + return None; + } + let num_channels =

::CHANNEL_COUNT as usize; + let i = (y as usize) + .saturating_mul(self.width as usize) + .saturating_add(x as usize) + .saturating_mul(num_channels); + + self.data + .get(i..i.checked_add(num_channels)?) + .map(|pixel_indices|

::from_slice(pixel_indices)) + } + + /// Test that the image fits inside the buffer. + /// + /// Verifies that the maximum image of pixels inside the bounds is smaller than the provided + /// length. Note that as a corrolary we also have that the index calculation of pixels inside + /// the bounds will not overflow. + fn check_image_fits(width: u32, height: u32, len: usize) -> bool { + let checked_len = Self::image_buffer_len(width, height); + checked_len.is_some_and(|min_len| min_len <= len) + } + + fn image_buffer_len(width: u32, height: u32) -> Option { + Some(

::CHANNEL_COUNT as usize) + .and_then(|size| size.checked_mul(width as usize)) + .and_then(|size| size.checked_mul(height as usize)) + } + + #[inline(always)] + fn pixel_indices(&self, x: u32, y: u32) -> Option> { + if x >= self.width || y >= self.height { + return None; + } + + Some(self.pixel_indices_unchecked(x, y)) + } + + #[inline(always)] + fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range { + let no_channels =

::CHANNEL_COUNT as usize; + // If in bounds, this can't overflow as we have tested that at construction! + let min_index = (y as usize * self.width as usize + x as usize) * no_channels; + min_index..min_index + no_channels + } + + /// Get the format of the buffer when viewed as a matrix of samples. + pub fn sample_layout(&self) -> SampleLayout { + // None of these can overflow, as all our memory is addressable. + SampleLayout::row_major_packed(

::CHANNEL_COUNT, self.width, self.height) + } + + /// Return the raw sample buffer with its stride an dimension information. + /// + /// The returned buffer is guaranteed to be well formed in all cases. It is laid out by + /// colors, width then height, meaning `channel_stride <= width_stride <= height_stride`. All + /// strides are in numbers of elements but those are mostly `u8` in which case the strides are + /// also byte strides. + pub fn into_flat_samples(self) -> FlatSamples + where + Container: AsRef<[P::Subpixel]>, + { + // None of these can overflow, as all our memory is addressable. + let layout = self.sample_layout(); + FlatSamples { + samples: self.data, + layout, + color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType + } + } + + /// Return a view on the raw sample buffer. + /// + /// See [`into_flat_samples`](#method.into_flat_samples) for more details. + pub fn as_flat_samples(&self) -> FlatSamples<&[P::Subpixel]> + where + Container: AsRef<[P::Subpixel]>, + { + let layout = self.sample_layout(); + FlatSamples { + samples: self.data.as_ref(), + layout, + color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType + } + } + + /// Return a mutable view on the raw sample buffer. + /// + /// See [`into_flat_samples`](#method.into_flat_samples) for more details. + pub fn as_flat_samples_mut(&mut self) -> FlatSamples<&mut [P::Subpixel]> + where + Container: AsMut<[P::Subpixel]>, + { + let layout = self.sample_layout(); + FlatSamples { + samples: self.data.as_mut(), + layout, + color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType + } + } +} + +impl ImageBuffer +where + P: Pixel, + Container: Deref + DerefMut, +{ + // TODO: choose name under which to expose. + pub(crate) fn inner_pixels_mut(&mut self) -> &mut [P::Subpixel] { + let len = Self::image_buffer_len(self.width, self.height).unwrap(); + &mut self.data[..len] + } + + /// Returns an iterator over the mutable pixels of this image. + pub fn pixels_mut(&mut self) -> PixelsMut<'_, P> { + PixelsMut { + chunks: self + .inner_pixels_mut() + .chunks_exact_mut(

::CHANNEL_COUNT as usize), + } + } + + /// Returns an iterator over the mutable rows of this image. + /// + /// Only non-empty rows can be iterated in this manner. In particular the iterator will not + /// yield any item when the width of the image is `0` or a pixel type without any channels is + /// used. This ensures that its length can always be represented by `usize`. + pub fn rows_mut(&mut self) -> RowsMut<'_, P> { + RowsMut::with_image(&mut self.data, self.width, self.height) + } + + /// Enumerates over the pixels of the image. + /// The iterator yields the coordinates of each pixel + /// along with a mutable reference to them. + pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut<'_, P> { + let width = self.width; + EnumeratePixelsMut { + pixels: self.pixels_mut(), + x: 0, + y: 0, + width, + } + } + + /// Enumerates over the rows of the image. + /// The iterator yields the y-coordinate of each row + /// along with a mutable reference to them. + pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<'_, P> { + let width = self.width; + EnumerateRowsMut { + rows: self.rows_mut(), + y: 0, + width, + } + } + + /// Gets a reference to the mutable pixel at location `(x, y)` + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of the bounds `(width, height)`. + #[inline] + #[track_caller] + pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P { + match self.pixel_indices(x, y) { + None => panic!( + "Image index {:?} out of bounds {:?}", + (x, y), + (self.width, self.height) + ), + Some(pixel_indices) =>

::from_slice_mut(&mut self.data[pixel_indices]), + } + } + + /// Gets a reference to the mutable pixel at location `(x, y)` or returns + /// `None` if the index is out of the bounds `(width, height)`. + pub fn get_pixel_mut_checked(&mut self, x: u32, y: u32) -> Option<&mut P> { + if x >= self.width { + return None; + } + let num_channels =

::CHANNEL_COUNT as usize; + let i = (y as usize) + .saturating_mul(self.width as usize) + .saturating_add(x as usize) + .saturating_mul(num_channels); + + self.data + .get_mut(i..i.checked_add(num_channels)?) + .map(|pixel_indices|

::from_slice_mut(pixel_indices)) + } + + /// Puts a pixel at location `(x, y)` + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of the bounds `(width, height)`. + #[inline] + #[track_caller] + pub fn put_pixel(&mut self, x: u32, y: u32, pixel: P) { + *self.get_pixel_mut(x, y) = pixel; + } +} + +impl ImageBuffer { + /// Define the color space for the image. + /// + /// The color data is unchanged. Reinterprets the existing red, blue, green channels as points + /// in the new set of primary colors, changing the apparent shade of pixels. + /// + /// Note that the primaries also define a reference whitepoint When this buffer contains Luma + /// data, the luminance channel is interpreted as the `Y` channel of a related `YCbCr` color + /// space as if by a non-constant chromaticity derived matrix. That is, coefficients are *not* + /// applied in the linear RGB space but use encoded channel values. (In a color space with the + /// linear transfer function there is no difference). + /// + /// The default color space is [`Cicp::SRGB`]. + pub fn set_rgb_primaries(&mut self, color: CicpColorPrimaries) { + self.color.primaries = color; + } + + /// Define the transfer function for the image. + /// + /// The color data is unchanged. Reinterprets all (non-alpha) components in the image, + /// potentially changing the apparent shade of pixels. Individual components are always + /// interpreted as encoded numbers. To denote numbers in a linear RGB space, use + /// [`CicpTransferCharacteristics::Linear`]. + /// + /// The default color space is [`Cicp::SRGB`]. + pub fn set_transfer_function(&mut self, tf: CicpTransferCharacteristics) { + self.color.transfer = tf; + } + + /// Get the Cicp encoding of this buffer's color data. + pub fn color_space(&self) -> Cicp { + self.color.into() + } + + /// Set primaries and transfer characteristics from a Cicp color space. + /// + /// Returns an error if `cicp` uses features that are not support with an RGB color space, e.g. + /// a matrix or narrow range (studio encoding) channels. + pub fn set_color_space(&mut self, cicp: Cicp) -> ImageResult<()> { + self.color = cicp.try_into_rgb()?; + Ok(()) + } + + pub(crate) fn set_rgb_color_space(&mut self, color: CicpRgb) { + self.color = color; + } +} + +impl ImageBuffer +where + P: Pixel, + [P::Subpixel]: EncodableLayout, + Container: Deref, +{ + /// Saves the buffer to a file at the path specified. + /// + /// The image format is derived from the file extension. + pub fn save(&self, path: Q) -> ImageResult<()> + where + Q: AsRef, + P: PixelWithColorType, + { + save_buffer( + path, + self.inner_pixels().as_bytes(), + self.width(), + self.height(), +

::COLOR_TYPE, + ) + } +} + +impl ImageBuffer +where + P: Pixel, + [P::Subpixel]: EncodableLayout, + Container: Deref, +{ + /// Saves the buffer to a file at the specified path in + /// the specified format. + /// + /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for + /// supported types. + pub fn save_with_format(&self, path: Q, format: ImageFormat) -> ImageResult<()> + where + Q: AsRef, + P: PixelWithColorType, + { + // This is valid as the subpixel is u8. + save_buffer_with_format( + path, + self.inner_pixels().as_bytes(), + self.width(), + self.height(), +

::COLOR_TYPE, + format, + ) + } +} + +impl ImageBuffer +where + P: Pixel, + [P::Subpixel]: EncodableLayout, + Container: Deref, +{ + /// Writes the buffer to a writer in the specified format. + /// + /// Assumes the writer is buffered. In most cases, you should wrap your writer in a `BufWriter` + /// for best performance. + pub fn write_to(&self, writer: &mut W, format: ImageFormat) -> ImageResult<()> + where + W: std::io::Write + std::io::Seek, + P: PixelWithColorType, + { + // This is valid as the subpixel is u8. + write_buffer_with_format( + writer, + self.inner_pixels().as_bytes(), + self.width(), + self.height(), +

::COLOR_TYPE, + format, + ) + } +} + +impl ImageBuffer +where + P: Pixel, + [P::Subpixel]: EncodableLayout, + Container: Deref, +{ + /// Writes the buffer with the given encoder. + pub fn write_with_encoder(&self, encoder: E) -> ImageResult<()> + where + E: ImageEncoder, + P: PixelWithColorType, + { + // This is valid as the subpixel is u8. + encoder.write_image( + self.inner_pixels().as_bytes(), + self.width(), + self.height(), +

::COLOR_TYPE, + ) + } +} + +impl Default for ImageBuffer +where + P: Pixel, + Container: Default, +{ + fn default() -> Self { + Self { + width: 0, + height: 0, + _phantom: PhantomData, + color: Cicp::SRGB_LINEAR.into_rgb(), + data: Default::default(), + } + } +} + +impl Deref for ImageBuffer +where + P: Pixel, + Container: Deref, +{ + type Target = [P::Subpixel]; + + fn deref(&self) -> &::Target { + &self.data + } +} + +impl DerefMut for ImageBuffer +where + P: Pixel, + Container: Deref + DerefMut, +{ + fn deref_mut(&mut self) -> &mut ::Target { + &mut self.data + } +} + +impl Index<(u32, u32)> for ImageBuffer +where + P: Pixel, + Container: Deref, +{ + type Output = P; + + fn index(&self, (x, y): (u32, u32)) -> &P { + self.get_pixel(x, y) + } +} + +impl IndexMut<(u32, u32)> for ImageBuffer +where + P: Pixel, + Container: Deref + DerefMut, +{ + fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P { + self.get_pixel_mut(x, y) + } +} + +impl Clone for ImageBuffer +where + P: Pixel, + Container: Deref + Clone, +{ + fn clone(&self) -> ImageBuffer { + ImageBuffer { + data: self.data.clone(), + width: self.width, + height: self.height, + color: self.color, + _phantom: PhantomData, + } + } + + fn clone_from(&mut self, source: &Self) { + self.data.clone_from(&source.data); + self.width = source.width; + self.height = source.height; + self.color = source.color; + } +} + +impl GenericImageView for ImageBuffer +where + P: Pixel, + Container: Deref + Deref, +{ + type Pixel = P; + + fn dimensions(&self) -> (u32, u32) { + self.dimensions() + } + + fn get_pixel(&self, x: u32, y: u32) -> P { + *self.get_pixel(x, y) + } + + /// Returns the pixel located at (x, y), ignoring bounds checking. + #[inline(always)] + unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P { + let indices = self.pixel_indices_unchecked(x, y); + *

::from_slice(self.data.get_unchecked(indices)) + } + + fn buffer_with_dimensions(&self, width: u32, height: u32) -> ImageBuffer> { + let mut buffer = ImageBuffer::new(width, height); + buffer.copy_color_space_from(self); + buffer + } +} + +impl GenericImage for ImageBuffer +where + P: Pixel, + Container: Deref + DerefMut, +{ + fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P { + self.get_pixel_mut(x, y) + } + + fn put_pixel(&mut self, x: u32, y: u32, pixel: P) { + *self.get_pixel_mut(x, y) = pixel; + } + + /// Puts a pixel at location (x, y), ignoring bounds checking. + #[inline(always)] + unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) { + let indices = self.pixel_indices_unchecked(x, y); + let p =

::from_slice_mut(self.data.get_unchecked_mut(indices)); + *p = pixel; + } + + /// Put a pixel at location (x, y), taking into account alpha channels + /// + /// DEPRECATED: This method will be removed. Blend the pixel directly instead. + fn blend_pixel(&mut self, x: u32, y: u32, p: P) { + self.get_pixel_mut(x, y).blend(&p); + } + + fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool { + let Rect { + x: sx, + y: sy, + width, + height, + } = source; + let dx = x; + let dy = y; + assert!(sx < self.width() && dx < self.width()); + assert!(sy < self.height() && dy < self.height()); + if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height { + return false; + } + + if sy < dy { + for y in (0..height).rev() { + let sy = sy + y; + let dy = dy + y; + let Range { start, .. } = self.pixel_indices_unchecked(sx, sy); + let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy); + let dst = self.pixel_indices_unchecked(dx, dy).start; + self.data.copy_within(start..end, dst); + } + } else { + for y in 0..height { + let sy = sy + y; + let dy = dy + y; + let Range { start, .. } = self.pixel_indices_unchecked(sx, sy); + let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy); + let dst = self.pixel_indices_unchecked(dx, dy).start; + self.data.copy_within(start..end, dst); + } + } + true + } +} + +// concrete implementation for `Vec`-backed buffers +// TODO: I think that rustc does not "see" this impl any more: the impl with +// Container meets the same requirements. At least, I got compile errors that +// there is no such function as `into_vec`, whereas `into_raw` did work, and +// `into_vec` is redundant anyway, because `into_raw` will give you the vector, +// and it is more generic. +impl ImageBuffer> { + /// Creates a new image buffer based on a `Vec`. + /// + /// all the pixels of this image have a value of zero, regardless of the data type or number of channels. + /// + /// The color space is initially set to [`sRGB`][`Cicp::SRGB`]. + /// + /// # Panics + /// + /// Panics when the resulting image is larger than the maximum size of a vector. + #[must_use] + pub fn new(width: u32, height: u32) -> ImageBuffer> { + let size = Self::image_buffer_len(width, height) + .expect("Buffer length in `ImageBuffer::new` overflows usize"); + ImageBuffer { + data: vec![Zero::zero(); size], + width, + height, + color: Cicp::SRGB.into_rgb(), + _phantom: PhantomData, + } + } + + /// Constructs a new `ImageBuffer` by copying a pixel + /// + /// # Panics + /// + /// Panics when the resulting image is larger than the maximum size of a vector. + pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuffer> { + let mut buf = ImageBuffer::new(width, height); + for p in buf.pixels_mut() { + *p = pixel; + } + buf + } + + /// Constructs a new `ImageBuffer` by repeated application of the supplied function. + /// + /// The arguments to the function are the pixel's x and y coordinates. + /// + /// # Panics + /// + /// Panics when the resulting image is larger than the maximum size of a vector. + pub fn from_fn(width: u32, height: u32, mut f: F) -> ImageBuffer> + where + F: FnMut(u32, u32) -> P, + { + let mut buf = ImageBuffer::new(width, height); + for (x, y, p) in buf.enumerate_pixels_mut() { + *p = f(x, y); + } + buf + } + + /// Creates an image buffer out of an existing buffer. + /// Returns None if the buffer is not big enough. + #[must_use] + pub fn from_vec( + width: u32, + height: u32, + buf: Vec, + ) -> Option>> { + ImageBuffer::from_raw(width, height, buf) + } + + /// Consumes the image buffer and returns the underlying data + /// as an owned buffer + #[must_use] + pub fn into_vec(self) -> Vec { + self.into_raw() + } + + /// Transfer the meta data, not the pixel values. + /// + /// This will reinterpret all the pixels. + /// + /// We may want to export this but under what name? + pub(crate) fn copy_color_space_from(&mut self, other: &ImageBuffer) { + self.color = other.color; + } +} + +/// Provides color conversions for whole image buffers. +pub trait ConvertBuffer { + /// Converts `self` to a buffer of type T + /// + /// A generic implementation is provided to convert any image buffer to a image buffer + /// based on a `Vec`. + fn convert(&self) -> T; +} + +// concrete implementation Luma -> Rgba +impl GrayImage { + /// Expands a color palette by re-using the existing buffer. + /// Assumes 8 bit per pixel. Uses an optionally transparent index to + /// adjust it's alpha value accordingly. + #[must_use] + pub fn expand_palette( + self, + palette: &[(u8, u8, u8)], + transparent_idx: Option, + ) -> RgbaImage { + let (width, height) = self.dimensions(); + let mut data = self.into_raw(); + let entries = data.len(); + data.resize(entries.checked_mul(4).unwrap(), 0); + let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap(); + expand_packed(&mut buffer, 4, 8, |idx, pixel| { + let (r, g, b) = palette[idx as usize]; + let a = if let Some(t_idx) = transparent_idx { + if t_idx == idx { + 0 + } else { + 255 + } + } else { + 255 + }; + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; + pixel[3] = a; + }); + buffer + } +} + +/// This copies the color space information but is somewhat wrong, in numeric terms this conversion +/// fails to actually convert rgb/luma with consistent treatment. But this trait impl is too +/// generic to handle it correctly (missing any CICP related parameter for the coefficients) so the +/// best effort here is to copy the metadata and have slighly incorrect color. May you've only been +/// adding an alpha channel or converting sample types, which is fine. +/// +/// It will very likely be deprecated in a future release. +impl + ConvertBuffer>> for ImageBuffer +where + Container: Deref, + ToType: FromColor, +{ + /// # Examples + /// Convert RGB image to gray image. + /// ```no_run + /// use image::buffer::ConvertBuffer; + /// use image::GrayImage; + /// + /// let image_path = "examples/fractal.png"; + /// let image = image::open(&image_path) + /// .expect("Open file failed") + /// .to_rgba8(); + /// + /// let gray_image: GrayImage = image.convert(); + /// ``` + fn convert(&self) -> ImageBuffer> { + let mut buffer: ImageBuffer> = + ImageBuffer::new(self.width, self.height); + buffer.copy_color_space_from(self); + for (to, from) in buffer.pixels_mut().zip(self.pixels()) { + to.from_color(from); + } + buffer + } +} + +/// Inputs to [`ImageBuffer::copy_from_color_space`]. +#[non_exhaustive] +#[derive(Default)] +pub struct ConvertColorOptions { + /// A pre-calculated transform. This is only used when the actual colors of the input and + /// output image match the color spaces with which the was constructed. + /// + /// FIXME: Clarify that the transform is cheap to clone, i.e. internally an Arc of precomputed + /// tables and not expensive despite having `Clone`. + pub(crate) transform: Option, + /// Make sure we can later add options that are bound to the thread. That does not mean that + /// all attributes will be bound to the thread, only that we can add `!Sync` options later. You + /// should be constructing the options at the call site with each attribute being cheap to move + /// into here. + pub(crate) _auto_traits: PhantomData>, +} + +impl ConvertColorOptions { + pub(crate) fn as_transform( + &mut self, + from_color: Cicp, + into_color: Cicp, + ) -> Result<&CicpTransform, ImageError> { + if let Some(tr) = &self.transform { + tr.check_applicable(from_color, into_color)?; + } + + if self.transform.is_none() { + self.transform = CicpTransform::new(from_color, into_color); + } + + self.transform.as_ref().ok_or_else(|| { + ImageError::Unsupported(UnsupportedError::from_format_and_kind( + crate::error::ImageFormatHint::Unknown, + // One of them is responsible. + UnsupportedErrorKind::ColorspaceCicp(if from_color.qualify_stability() { + into_color + } else { + from_color + }), + )) + }) + } + + pub(crate) fn as_transform_fn( + &mut self, + from_color: Cicp, + into_color: Cicp, + ) -> Result<&'_ CicpApplicable<'_, FromType::Subpixel>, ImageError> + where + FromType: PixelWithColorType, + IntoType: PixelWithColorType, + { + Ok(self + .as_transform(from_color, into_color)? + .supported_transform_fn::()) + } +} + +impl ImageBuffer +where + SelfPixel: PixelWithColorType, + C: Deref + DerefMut, +{ + /// Convert the color data to another pixel type, the color space. + /// + /// This method is supposed to be called by exposed monomorphized methods, not directly by + /// users. In particular it serves to implement `DynamicImage`'s casts that go beyond those + /// offered by `PixelWithColorType` and include, e.g., `LumaAlpha`. + /// + /// Before exposing this method, decide if we want a design like [`DynamicImage::to`] (many + /// trait parameters) with color space aware `FromColor` or if we want a design that takes a + /// `ColorType` parameter / `PixelWithColorType`. The latter is not quite as flexible but + /// allows much greater internal changes that do not tie in with the _external_ stable API. + pub(crate) fn cast_in_color_space( + &self, + ) -> ImageBuffer> + where + SelfPixel: Pixel, + IntoPixel: Pixel, + IntoPixel: CicpPixelCast, + SelfPixel::Subpixel: ColorComponentForCicp, + IntoPixel::Subpixel: ColorComponentForCicp + FromPrimitive, + { + let vec = self + .color + .cast_pixels::(self.inner_pixels(), &|| [0.2126, 0.7152, 0.0722]); + let mut buffer = ImageBuffer::from_vec(self.width, self.height, vec) + .expect("cast_pixels returned the right number of pixels"); + buffer.copy_color_space_from(self); + buffer + } + + /// Copy pixel data from one buffer to another, calculating equivalent color representations + /// for the target's color space. + /// + /// Returns `Ok` if: + /// - Both images to have the same dimensions, otherwise returns a [`ImageError::Parameter`]. + /// - The primaries and transfer functions of both image's color spaces must be supported, + /// otherwise returns a [`ImageError::Unsupported`]. + /// - The pixel's channel layout must be supported for conversion, otherwise returns a + /// [`ImageError::Unsupported`]. You can rely on RGB and RGBA always being supported. If a + /// layout is supported for one color space it is supported for all of them. + /// + /// To copy color data of arbitrary channel layouts use `DynamicImage` with the overhead of + /// having data converted into and from RGB representation. + pub fn copy_from_color_space( + &mut self, + from: &ImageBuffer, + mut options: ConvertColorOptions, + ) -> ImageResult<()> + where + FromType: Pixel + PixelWithColorType, + D: Deref, + { + if self.dimensions() != from.dimensions() { + return Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + ))); + } + + let transform = options + .as_transform_fn::(from.color_space(), self.color_space())?; + + let from = from.inner_pixels(); + let into = self.inner_pixels_mut(); + + debug_assert_eq!( + from.len() / usize::from(FromType::CHANNEL_COUNT), + into.len() / usize::from(SelfPixel::CHANNEL_COUNT), + "Diverging pixel count despite same size", + ); + + transform(from, into); + + Ok(()) + } + + /// Convert this buffer into a newly allocated buffer, changing the color representation. + /// + /// This will avoid an allocation if the target layout or the color conversion is not supported + /// (yet). + /// + /// See [`ImageBuffer::copy_from_color_space`] if you intend to assign to an existing buffer, + /// swapping the argument with `self`. + pub fn to_color_space( + &self, + color: Cicp, + mut options: ConvertColorOptions, + ) -> Result>, ImageError> + where + IntoType: Pixel + PixelWithColorType, + { + let transform = + options.as_transform_fn::(self.color_space(), color)?; + + let (width, height) = self.dimensions(); + let mut target = ImageBuffer::new(width, height); + + let from = self.inner_pixels(); + let into = target.inner_pixels_mut(); + + transform(from, into); + + Ok(target) + } + + /// Apply a color space to an image, transforming the pixel representation. + pub fn apply_color_space( + &mut self, + color: Cicp, + mut options: ConvertColorOptions, + ) -> ImageResult<()> { + if self.color_space() == color { + return Ok(()); + } + + let transform = + options.as_transform_fn::(self.color_space(), color)?; + + let mut scratch = [::DEFAULT_MIN_VALUE; 1200]; + let chunk_len = scratch.len() / usize::from(::CHANNEL_COUNT) + * usize::from(::CHANNEL_COUNT); + + for chunk in self.data.chunks_mut(chunk_len) { + let scratch = &mut scratch[..chunk.len()]; + scratch.copy_from_slice(chunk); + transform(scratch, chunk); + } + + self.color = color.into_rgb(); + + Ok(()) + } +} + +/// Sendable Rgb image buffer +pub type RgbImage = ImageBuffer, Vec>; +/// Sendable Rgb + alpha channel image buffer +pub type RgbaImage = ImageBuffer, Vec>; +/// Sendable grayscale image buffer +pub type GrayImage = ImageBuffer, Vec>; +/// Sendable grayscale + alpha channel image buffer +pub type GrayAlphaImage = ImageBuffer, Vec>; +/// Sendable 16-bit Rgb image buffer +pub(crate) type Rgb16Image = ImageBuffer, Vec>; +/// Sendable 16-bit Rgb + alpha channel image buffer +pub(crate) type Rgba16Image = ImageBuffer, Vec>; +/// Sendable 16-bit grayscale image buffer +pub(crate) type Gray16Image = ImageBuffer, Vec>; +/// Sendable 16-bit grayscale + alpha channel image buffer +pub(crate) type GrayAlpha16Image = ImageBuffer, Vec>; + +/// An image buffer for 32-bit float RGB pixels, +/// where the backing container is a flattened vector of floats. +pub type Rgb32FImage = ImageBuffer, Vec>; + +/// An image buffer for 32-bit float RGBA pixels, +/// where the backing container is a flattened vector of floats. +pub type Rgba32FImage = ImageBuffer, Vec>; + +impl From for RgbImage { + fn from(value: DynamicImage) -> Self { + value.into_rgb8() + } +} + +impl From for RgbaImage { + fn from(value: DynamicImage) -> Self { + value.into_rgba8() + } +} + +impl From for GrayImage { + fn from(value: DynamicImage) -> Self { + value.into_luma8() + } +} + +impl From for GrayAlphaImage { + fn from(value: DynamicImage) -> Self { + value.into_luma_alpha8() + } +} + +impl From for Rgb16Image { + fn from(value: DynamicImage) -> Self { + value.into_rgb16() + } +} + +impl From for Rgba16Image { + fn from(value: DynamicImage) -> Self { + value.into_rgba16() + } +} + +impl From for Gray16Image { + fn from(value: DynamicImage) -> Self { + value.into_luma16() + } +} + +impl From for GrayAlpha16Image { + fn from(value: DynamicImage) -> Self { + value.into_luma_alpha16() + } +} + +impl From for Rgba32FImage { + fn from(value: DynamicImage) -> Self { + value.into_rgba32f() + } +} + +#[cfg(test)] +mod test { + use super::{GrayImage, ImageBuffer, RgbImage}; + use crate::math::Rect; + use crate::metadata::Cicp; + use crate::metadata::CicpTransform; + use crate::GenericImage as _; + use crate::ImageFormat; + use crate::{Luma, LumaA, Pixel, Rgb, Rgba}; + use num_traits::Zero; + + #[test] + /// Tests if image buffers from slices work + fn slice_buffer() { + let data = [0; 9]; + let buf: ImageBuffer, _> = ImageBuffer::from_raw(3, 3, &data[..]).unwrap(); + assert_eq!(&*buf, &data[..]); + } + + macro_rules! new_buffer_zero_test { + ($test_name:ident, $pxt:ty) => { + #[test] + fn $test_name() { + let buffer = ImageBuffer::<$pxt, Vec<<$pxt as Pixel>::Subpixel>>::new(2, 2); + assert!(buffer + .iter() + .all(|p| *p == <$pxt as Pixel>::Subpixel::zero())); + } + }; + } + + new_buffer_zero_test!(luma_u8_zero_test, Luma); + new_buffer_zero_test!(luma_u16_zero_test, Luma); + new_buffer_zero_test!(luma_f32_zero_test, Luma); + new_buffer_zero_test!(luma_a_u8_zero_test, LumaA); + new_buffer_zero_test!(luma_a_u16_zero_test, LumaA); + new_buffer_zero_test!(luma_a_f32_zero_test, LumaA); + new_buffer_zero_test!(rgb_u8_zero_test, Rgb); + new_buffer_zero_test!(rgb_u16_zero_test, Rgb); + new_buffer_zero_test!(rgb_f32_zero_test, Rgb); + new_buffer_zero_test!(rgb_a_u8_zero_test, Rgba); + new_buffer_zero_test!(rgb_a_u16_zero_test, Rgba); + new_buffer_zero_test!(rgb_a_f32_zero_test, Rgba); + + #[test] + fn get_pixel() { + let mut a: RgbImage = ImageBuffer::new(10, 10); + { + let b = a.get_mut(3 * 10).unwrap(); + *b = 255; + } + assert_eq!(a.get_pixel(0, 1)[0], 255); + } + + #[test] + fn get_pixel_checked() { + let mut a: RgbImage = ImageBuffer::new(10, 10); + a.get_pixel_mut_checked(0, 1).unwrap()[0] = 255; + + assert_eq!(a.get_pixel_checked(0, 1), Some(&Rgb([255, 0, 0]))); + assert_eq!(a.get_pixel_checked(0, 1).unwrap(), a.get_pixel(0, 1)); + assert_eq!(a.get_pixel_checked(10, 0), None); + assert_eq!(a.get_pixel_checked(0, 10), None); + assert_eq!(a.get_pixel_mut_checked(10, 0), None); + assert_eq!(a.get_pixel_mut_checked(0, 10), None); + + // From image/issues/1672 + const WHITE: Rgb = Rgb([255_u8, 255, 255]); + let mut a = RgbImage::new(2, 1); + a.put_pixel(1, 0, WHITE); + + assert_eq!(a.get_pixel_checked(1, 0), Some(&WHITE)); + assert_eq!(a.get_pixel_checked(1, 0).unwrap(), a.get_pixel(1, 0)); + } + + #[test] + fn mut_iter() { + let mut a: RgbImage = ImageBuffer::new(10, 10); + { + let val = a.pixels_mut().next().unwrap(); + *val = Rgb([42, 0, 0]); + } + assert_eq!(a.data[0], 42); + } + + #[test] + fn zero_width_zero_height() { + let mut image = RgbImage::new(0, 0); + + assert_eq!(image.rows_mut().count(), 0); + assert_eq!(image.pixels_mut().count(), 0); + assert_eq!(image.rows().count(), 0); + assert_eq!(image.pixels().count(), 0); + } + + #[test] + fn zero_width_nonzero_height() { + let mut image = RgbImage::new(0, 2); + + assert_eq!(image.rows_mut().count(), 0); + assert_eq!(image.pixels_mut().count(), 0); + assert_eq!(image.rows().count(), 0); + assert_eq!(image.pixels().count(), 0); + } + + #[test] + fn nonzero_width_zero_height() { + let mut image = RgbImage::new(2, 0); + + assert_eq!(image.rows_mut().count(), 0); + assert_eq!(image.pixels_mut().count(), 0); + assert_eq!(image.rows().count(), 0); + assert_eq!(image.pixels().count(), 0); + } + + #[test] + fn pixels_on_large_buffer() { + let mut image = RgbImage::from_raw(1, 1, vec![0; 6]).unwrap(); + + assert_eq!(image.pixels().count(), 1); + assert_eq!(image.enumerate_pixels().count(), 1); + assert_eq!(image.pixels_mut().count(), 1); + assert_eq!(image.enumerate_pixels_mut().count(), 1); + + assert_eq!(image.rows().count(), 1); + assert_eq!(image.rows_mut().count(), 1); + } + + #[test] + fn default() { + let image = ImageBuffer::, Vec>::default(); + assert_eq!(image.dimensions(), (0, 0)); + } + + #[test] + #[rustfmt::skip] + fn test_image_buffer_copy_within_oob() { + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap(); + assert!(!image.copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0)); + assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0)); + assert!(!image.copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0)); + assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0)); + assert!(!image.copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0)); + assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1)); + assert!(!image.copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0)); + } + + #[test] + fn test_image_buffer_copy_within_tl() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.copy_within( + Rect { + x: 0, + y: 0, + width: 3, + height: 3 + }, + 1, + 1 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_image_buffer_copy_within_tr() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.copy_within( + Rect { + x: 1, + y: 0, + width: 3, + height: 3 + }, + 0, + 1 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_image_buffer_copy_within_bl() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.copy_within( + Rect { + x: 0, + y: 1, + width: 3, + height: 3 + }, + 1, + 0 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_image_buffer_copy_within_br() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.copy_within( + Rect { + x: 1, + y: 1, + width: 3, + height: 3 + }, + 0, + 0 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + #[cfg(feature = "png")] + fn write_to_with_large_buffer() { + // A buffer of 1 pixel, padded to 4 bytes as would be common in, e.g. BMP. + + let img: GrayImage = ImageBuffer::from_raw(1, 1, vec![0u8; 4]).unwrap(); + let mut buffer = std::io::Cursor::new(vec![]); + assert!(img.write_to(&mut buffer, ImageFormat::Png).is_ok()); + } + + #[test] + fn exact_size_iter_size_hint() { + // The docs for `std::iter::ExactSizeIterator` requires that the implementation of + // `size_hint` on the iterator returns the same value as the `len` implementation. + + // This test should work for any size image. + const N: u32 = 10; + + let mut image = RgbImage::from_raw(N, N, vec![0; (N * N * 3) as usize]).unwrap(); + + let iter = image.pixels(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.pixels_mut(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.rows(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.rows_mut(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.enumerate_pixels(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.enumerate_rows(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.enumerate_pixels_mut(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + + let iter = image.enumerate_rows_mut(); + let exact_len = ExactSizeIterator::len(&iter); + assert_eq!(iter.size_hint(), (exact_len, Some(exact_len))); + } + + #[test] + fn color_conversion() { + let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255, 0, 0])); + let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + + target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + target.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + assert_eq!(target[(0, 0)], Rgba([234u8, 51, 35, 255])); + } + + #[test] + fn gray_conversions() { + let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8])); + let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + + target.set_rgb_primaries(Cicp::SRGB.primaries); + target.set_transfer_function(Cicp::SRGB.transfer); + + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + assert_eq!(target[(0, 0)], Rgba([u8::MAX; 4])); + } + + #[test] + fn rgb_to_gray_conversion() { + let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([128u8; 3])); + let mut target = ImageBuffer::from_fn(128, 128, |_, _| Luma(Default::default())); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + + target.set_rgb_primaries(Cicp::SRGB.primaries); + target.set_transfer_function(Cicp::SRGB.transfer); + + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + assert_eq!(target[(0, 0)], Luma([128u8])); + } + + #[test] + fn apply_color() { + let mut buffer = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255u8, 0, 0])); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + buffer.set_transfer_function(Cicp::SRGB.transfer); + + buffer + .apply_color_space(Cicp::DISPLAY_P3, Default::default()) + .expect("supported transform"); + + buffer.pixels().for_each(|&p| { + assert_eq!(p, Rgb([234u8, 51, 35])); + }); + } + + #[test] + fn to_color() { + let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgba([255u8, 0, 0, 255])); + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + + let target = source + .to_color_space::>(Cicp::DISPLAY_P3, Default::default()) + .expect("supported transform"); + + assert_eq!(target[(0, 0)], Rgb([234u8, 51, 35])); + } + + #[test] + fn transformation_mismatch() { + let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8])); + let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())); + + source.set_color_space(Cicp::SRGB).unwrap(); + target.set_color_space(Cicp::DISPLAY_P3).unwrap(); + + let options = super::ConvertColorOptions { + transform: CicpTransform::new(Cicp::SRGB, Cicp::SRGB), + ..super::ConvertColorOptions::default() + }; + + let result = target.copy_from_color_space(&source, options); + assert!(matches!(result, Err(crate::ImageError::Parameter(_)))); + } +} + +#[cfg(test)] +#[cfg(feature = "benchmarks")] +mod benchmarks { + use super::{ConvertBuffer, GrayImage, ImageBuffer, Pixel, RgbImage}; + + #[bench] + fn conversion(b: &mut test::Bencher) { + let mut a: RgbImage = ImageBuffer::new(1000, 1000); + for p in a.pixels_mut() { + let rgb = p.channels_mut(); + rgb[0] = 255; + rgb[1] = 23; + rgb[2] = 42; + } + + assert!(a.data[0] != 0); + b.iter(|| { + let b: GrayImage = a.convert(); + assert!(0 != b.data[0]); + assert!(a.data[0] != b.data[0]); + test::black_box(b); + }); + b.bytes = 1000 * 1000 * 3; + } + + #[bench] + fn image_access_row_by_row(b: &mut test::Bencher) { + let mut a: RgbImage = ImageBuffer::new(1000, 1000); + for p in a.pixels_mut() { + let rgb = p.channels_mut(); + rgb[0] = 255; + rgb[1] = 23; + rgb[2] = 42; + } + + b.iter(move || { + let image: &RgbImage = test::black_box(&a); + let mut sum: usize = 0; + for y in 0..1000 { + for x in 0..1000 { + let pixel = image.get_pixel(x, y); + sum = sum.wrapping_add(pixel[0] as usize); + sum = sum.wrapping_add(pixel[1] as usize); + sum = sum.wrapping_add(pixel[2] as usize); + } + } + test::black_box(sum) + }); + + b.bytes = 1000 * 1000 * 3; + } + + #[bench] + fn image_access_col_by_col(b: &mut test::Bencher) { + let mut a: RgbImage = ImageBuffer::new(1000, 1000); + for p in a.pixels_mut() { + let rgb = p.channels_mut(); + rgb[0] = 255; + rgb[1] = 23; + rgb[2] = 42; + } + + b.iter(move || { + let image: &RgbImage = test::black_box(&a); + let mut sum: usize = 0; + for x in 0..1000 { + for y in 0..1000 { + let pixel = image.get_pixel(x, y); + sum = sum.wrapping_add(pixel[0] as usize); + sum = sum.wrapping_add(pixel[1] as usize); + sum = sum.wrapping_add(pixel[2] as usize); + } + } + test::black_box(sum) + }); + + b.bytes = 1000 * 1000 * 3; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/buffer_par.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer_par.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/buffer_par.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/buffer_par.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,496 @@ +use rayon::iter::plumbing::*; +use rayon::iter::{IndexedParallelIterator, ParallelIterator}; +use rayon::slice::{ChunksExact, ChunksExactMut, ParallelSlice, ParallelSliceMut}; +use std::fmt; +use std::ops::{Deref, DerefMut}; + +use crate::traits::Pixel; +use crate::ImageBuffer; + +/// Parallel iterator over pixel refs. +#[derive(Clone)] +pub struct PixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + chunks: ChunksExact<'a, P::Subpixel>, +} + +impl<'a, P> ParallelIterator for PixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + type Item = &'a P; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + self.chunks + .map(|v|

::from_slice(v)) + .drive_unindexed(consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl<'a, P> IndexedParallelIterator for PixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + fn drive>(self, consumer: C) -> C::Result { + self.chunks + .map(|v|

::from_slice(v)) + .drive(consumer) + } + + fn len(&self) -> usize { + self.chunks.len() + } + + fn with_producer>(self, callback: CB) -> CB::Output { + self.chunks + .map(|v|

::from_slice(v)) + .with_producer(callback) + } +} + +impl

fmt::Debug for PixelsPar<'_, P> +where + P: Pixel + Sync, + P::Subpixel: Sync + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("PixelsPar") + .field("chunks", &self.chunks) + .finish() + } +} + +/// Parallel iterator over mutable pixel refs. +pub struct PixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + chunks: ChunksExactMut<'a, P::Subpixel>, +} + +impl<'a, P> ParallelIterator for PixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + type Item = &'a mut P; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + self.chunks + .map(|v|

::from_slice_mut(v)) + .drive_unindexed(consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl<'a, P> IndexedParallelIterator for PixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + fn drive>(self, consumer: C) -> C::Result { + self.chunks + .map(|v|

::from_slice_mut(v)) + .drive(consumer) + } + + fn len(&self) -> usize { + self.chunks.len() + } + + fn with_producer>(self, callback: CB) -> CB::Output { + self.chunks + .map(|v|

::from_slice_mut(v)) + .with_producer(callback) + } +} + +impl

fmt::Debug for PixelsMutPar<'_, P> +where + P: Pixel + Send + Sync, + P::Subpixel: Send + Sync + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("PixelsMutPar") + .field("chunks", &self.chunks) + .finish() + } +} + +/// Parallel iterator over pixel refs and their coordinates. +#[derive(Clone)] +pub struct EnumeratePixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + pixels: PixelsPar<'a, P>, + width: u32, +} + +impl<'a, P> ParallelIterator for EnumeratePixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + type Item = (u32, u32, &'a P); + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .drive_unindexed(consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl<'a, P> IndexedParallelIterator for EnumeratePixelsPar<'a, P> +where + P: Pixel + Sync + 'a, + P::Subpixel: Sync + 'a, +{ + fn drive>(self, consumer: C) -> C::Result { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .drive(consumer) + } + + fn len(&self) -> usize { + self.pixels.len() + } + + fn with_producer>(self, callback: CB) -> CB::Output { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .with_producer(callback) + } +} + +impl

fmt::Debug for EnumeratePixelsPar<'_, P> +where + P: Pixel + Sync, + P::Subpixel: Sync + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumeratePixelsPar") + .field("pixels", &self.pixels) + .field("width", &self.width) + .finish() + } +} + +/// Parallel iterator over mutable pixel refs and their coordinates. +pub struct EnumeratePixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + pixels: PixelsMutPar<'a, P>, + width: u32, +} + +impl<'a, P> ParallelIterator for EnumeratePixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + type Item = (u32, u32, &'a mut P); + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .drive_unindexed(consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl<'a, P> IndexedParallelIterator for EnumeratePixelsMutPar<'a, P> +where + P: Pixel + Send + Sync + 'a, + P::Subpixel: Send + Sync + 'a, +{ + fn drive>(self, consumer: C) -> C::Result { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .drive(consumer) + } + + fn len(&self) -> usize { + self.pixels.len() + } + + fn with_producer>(self, callback: CB) -> CB::Output { + self.pixels + .enumerate() + .map(|(i, p)| { + ( + (i % self.width as usize) as u32, + (i / self.width as usize) as u32, + p, + ) + }) + .with_producer(callback) + } +} + +impl

fmt::Debug for EnumeratePixelsMutPar<'_, P> +where + P: Pixel + Send + Sync, + P::Subpixel: Send + Sync + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("EnumeratePixelsMutPar") + .field("pixels", &self.pixels) + .field("width", &self.width) + .finish() + } +} + +impl ImageBuffer +where + P: Pixel + Sync, + P::Subpixel: Sync, + Container: Deref, +{ + /// Returns a parallel iterator over the pixels of this image, usable with `rayon`. + /// See [`pixels`] for more information. + /// + /// [`pixels`]: #method.pixels + pub fn par_pixels(&self) -> PixelsPar<'_, P> { + PixelsPar { + chunks: self + .inner_pixels() + .par_chunks_exact(

::CHANNEL_COUNT as usize), + } + } + + /// Returns a parallel iterator over the pixels of this image and their coordinates, usable with `rayon`. + /// See [`enumerate_pixels`] for more information. + /// + /// [`enumerate_pixels`]: #method.enumerate_pixels + pub fn par_enumerate_pixels(&self) -> EnumeratePixelsPar<'_, P> { + EnumeratePixelsPar { + pixels: self.par_pixels(), + width: self.width(), + } + } +} + +impl ImageBuffer +where + P: Pixel + Send + Sync, + P::Subpixel: Send + Sync, + Container: Deref + DerefMut, +{ + /// Returns a parallel iterator over the mutable pixels of this image, usable with `rayon`. + /// See [`pixels_mut`] for more information. + /// + /// [`pixels_mut`]: #method.pixels_mut + pub fn par_pixels_mut(&mut self) -> PixelsMutPar<'_, P> { + PixelsMutPar { + chunks: self + .inner_pixels_mut() + .par_chunks_exact_mut(

::CHANNEL_COUNT as usize), + } + } + + /// Returns a parallel iterator over the mutable pixels of this image and their coordinates, usable with `rayon`. + /// See [`enumerate_pixels_mut`] for more information. + /// + /// [`enumerate_pixels_mut`]: #method.enumerate_pixels_mut + pub fn par_enumerate_pixels_mut(&mut self) -> EnumeratePixelsMutPar<'_, P> { + let width = self.width(); + EnumeratePixelsMutPar { + pixels: self.par_pixels_mut(), + width, + } + } +} + +impl

ImageBuffer> +where + P: Pixel + Send + Sync, + P::Subpixel: Send + Sync, +{ + /// Constructs a new `ImageBuffer` by repeated application of the supplied function, + /// utilizing multi-threading via `rayon`. + /// + /// The arguments to the function are the pixel's x and y coordinates. + /// + /// # Panics + /// + /// Panics when the resulting image is larger than the maximum size of a vector. + pub fn from_par_fn(width: u32, height: u32, f: F) -> ImageBuffer> + where + F: Fn(u32, u32) -> P + Send + Sync, + { + let mut buf = ImageBuffer::new(width, height); + buf.par_enumerate_pixels_mut().for_each(|(x, y, p)| { + *p = f(x, y); + }); + + buf + } +} + +#[cfg(test)] +mod test { + use crate::{Rgb, RgbImage}; + use rayon::iter::{IndexedParallelIterator, ParallelIterator}; + + fn test_width_height(width: u32, height: u32, len: usize) { + let mut image = RgbImage::new(width, height); + + assert_eq!(image.par_enumerate_pixels_mut().len(), len); + assert_eq!(image.par_enumerate_pixels().len(), len); + assert_eq!(image.par_pixels_mut().len(), len); + assert_eq!(image.par_pixels().len(), len); + } + + #[test] + fn zero_width_zero_height() { + test_width_height(0, 0, 0); + } + + #[test] + fn zero_width_nonzero_height() { + test_width_height(0, 2, 0); + } + + #[test] + fn nonzero_width_zero_height() { + test_width_height(2, 0, 0); + } + + #[test] + fn iter_parity() { + let mut image1 = RgbImage::from_fn(17, 29, |x, y| { + Rgb(std::array::from_fn(|i| { + ((x + y * 98 + i as u32 * 27) % 255) as u8 + })) + }); + let mut image2 = image1.clone(); + + assert_eq!( + image1.enumerate_pixels_mut().collect::>(), + image2.par_enumerate_pixels_mut().collect::>() + ); + assert_eq!( + image1.enumerate_pixels().collect::>(), + image2.par_enumerate_pixels().collect::>() + ); + assert_eq!( + image1.pixels_mut().collect::>(), + image2.par_pixels_mut().collect::>() + ); + assert_eq!( + image1.pixels().collect::>(), + image2.par_pixels().collect::>() + ); + } +} + +#[cfg(test)] +#[cfg(feature = "benchmarks")] +mod benchmarks { + use crate::{Rgb, RgbImage}; + + const S: u32 = 1024; + + #[bench] + fn creation(b: &mut test::Bencher) { + let mut bytes = 0; + b.iter(|| { + let img = RgbImage::from_fn(S, S, |_, _| test::black_box(pixel_func())); + + bytes += img.as_raw().len() as u64; + }); + + b.bytes = bytes; + } + + #[bench] + fn creation_par(b: &mut test::Bencher) { + let mut bytes = 0; + b.iter(|| { + let img = RgbImage::from_par_fn(S, S, |_, _| test::black_box(pixel_func())); + + bytes += img.as_raw().len() as u64; + }); + + b.bytes = bytes; + } + + fn pixel_func() -> Rgb { + use std::collections::hash_map::RandomState; + use std::hash::{BuildHasher, Hasher}; + Rgb(std::array::from_fn(|_| { + RandomState::new().build_hasher().finish() as u8 + })) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/dynimage.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/dynimage.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/dynimage.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/dynimage.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2246 @@ +use std::fs::File; +use std::io::{self, BufWriter, Seek, Write}; +use std::path::Path; + +use crate::color::{self, FromColor, IntoColor}; +use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; +use crate::flat::FlatSamples; +use crate::imageops::{gaussian_blur_dyn_image, GaussianBlurParameters}; +use crate::images::buffer::{ + ConvertBuffer, Gray16Image, GrayAlpha16Image, GrayAlphaImage, GrayImage, ImageBuffer, + Rgb16Image, Rgb32FImage, RgbImage, Rgba16Image, Rgba32FImage, RgbaImage, +}; +use crate::io::encoder::ImageEncoderBoxed; +use crate::io::free_functions::{self, encoder_for_format}; +use crate::math::resize_dimensions; +use crate::metadata::Orientation; +use crate::traits::Pixel; +use crate::{ + imageops, + metadata::{Cicp, CicpColorPrimaries, CicpTransferCharacteristics}, + ConvertColorOptions, ExtendedColorType, GenericImage, GenericImageView, ImageDecoder, + ImageEncoder, ImageFormat, ImageReader, Luma, LumaA, +}; + +/// A Dynamic Image +/// +/// This represents a _matrix_ of _pixels_ which are _convertible_ from and to an _RGBA_ +/// representation. More variants that adhere to these principles may get added in the future, in +/// particular to cover other combinations typically used. +/// +/// # Usage +/// +/// This type can act as a converter between specific `ImageBuffer` instances. +/// +/// ``` +/// use image::{DynamicImage, GrayImage, RgbImage}; +/// +/// let rgb: RgbImage = RgbImage::new(10, 10); +/// let luma: GrayImage = DynamicImage::ImageRgb8(rgb).into_luma8(); +/// ``` +/// +/// # Design +/// +/// There is no goal to provide an all-encompassing type with all possible memory layouts. This +/// would hardly be feasible as a simple enum, due to the sheer number of combinations of channel +/// kinds, channel order, and bit depth. Rather, this type provides an opinionated selection with +/// normalized channel order which can store common pixel values without loss. +/// +/// # Color space +/// +/// Each image has an associated color space in the form of [CICP] data ([ITU Rec H.273]). Not all +/// color spaces are supported in the sense that you can compute in them ([Context][w3c-png]). +/// Conversion into different pixels types ([`ColorType`][`crate::ColorType`]) _generally_ take the +/// color space into account, with the exception of [`DynamicImage::to`] due to historical design +/// baggage. +/// +/// The imageops functions operate in _encoded_ space, directly on the channel values, and do _not_ +/// linearize colors internally as you might be used to from GPU shader programming. Their return +/// values however copy the color space annotation of the source. +/// +/// The IO functions do _not yet_ write ICC or CICP indications into the result formats. We're +/// aware of this problem, it is tracked in [#2493] and [#1460]. +/// +/// [CICP]: https://www.w3.org/TR/png-3/#cICP-chunk +/// [w3c-png]: https://github.com/w3c/png/issues/312 +/// [ITU Rec H.273]: https://www.itu.int/rec/T-REC-H.273-202407-I/en +/// [#2493]: https://github.com/image-rs/image/issues/2493 +/// [#1460]: https://github.com/image-rs/image/issues/1460 +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub enum DynamicImage { + /// Each pixel in this image is 8-bit Luma + ImageLuma8(GrayImage), + + /// Each pixel in this image is 8-bit Luma with alpha + ImageLumaA8(GrayAlphaImage), + + /// Each pixel in this image is 8-bit Rgb + ImageRgb8(RgbImage), + + /// Each pixel in this image is 8-bit Rgb with alpha + ImageRgba8(RgbaImage), + + /// Each pixel in this image is 16-bit Luma + ImageLuma16(Gray16Image), + + /// Each pixel in this image is 16-bit Luma with alpha + ImageLumaA16(GrayAlpha16Image), + + /// Each pixel in this image is 16-bit Rgb + ImageRgb16(Rgb16Image), + + /// Each pixel in this image is 16-bit Rgb with alpha + ImageRgba16(Rgba16Image), + + /// Each pixel in this image is 32-bit float Rgb + ImageRgb32F(Rgb32FImage), + + /// Each pixel in this image is 32-bit float Rgb with alpha + ImageRgba32F(Rgba32FImage), +} + +macro_rules! dynamic_map( + ($dynimage: expr, $image: pat => $action: expr) => ({ + use DynamicImage::*; + match $dynimage { + ImageLuma8($image) => ImageLuma8($action), + ImageLumaA8($image) => ImageLumaA8($action), + ImageRgb8($image) => ImageRgb8($action), + ImageRgba8($image) => ImageRgba8($action), + ImageLuma16($image) => ImageLuma16($action), + ImageLumaA16($image) => ImageLumaA16($action), + ImageRgb16($image) => ImageRgb16($action), + ImageRgba16($image) => ImageRgba16($action), + ImageRgb32F($image) => ImageRgb32F($action), + ImageRgba32F($image) => ImageRgba32F($action), + } + }); + + ($dynimage: expr, $image:pat_param, $action: expr) => ( + match $dynimage { + DynamicImage::ImageLuma8($image) => $action, + DynamicImage::ImageLumaA8($image) => $action, + DynamicImage::ImageRgb8($image) => $action, + DynamicImage::ImageRgba8($image) => $action, + DynamicImage::ImageLuma16($image) => $action, + DynamicImage::ImageLumaA16($image) => $action, + DynamicImage::ImageRgb16($image) => $action, + DynamicImage::ImageRgba16($image) => $action, + DynamicImage::ImageRgb32F($image) => $action, + DynamicImage::ImageRgba32F($image) => $action, + } + ); +); + +impl Clone for DynamicImage { + fn clone(&self) -> Self { + dynamic_map!(*self, ref p, DynamicImage::from(p.clone())) + } + + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Self::ImageLuma8(p1), Self::ImageLuma8(p2)) => p1.clone_from(p2), + (Self::ImageLumaA8(p1), Self::ImageLumaA8(p2)) => p1.clone_from(p2), + (Self::ImageRgb8(p1), Self::ImageRgb8(p2)) => p1.clone_from(p2), + (Self::ImageRgba8(p1), Self::ImageRgba8(p2)) => p1.clone_from(p2), + (Self::ImageLuma16(p1), Self::ImageLuma16(p2)) => p1.clone_from(p2), + (Self::ImageLumaA16(p1), Self::ImageLumaA16(p2)) => p1.clone_from(p2), + (Self::ImageRgb16(p1), Self::ImageRgb16(p2)) => p1.clone_from(p2), + (Self::ImageRgba16(p1), Self::ImageRgba16(p2)) => p1.clone_from(p2), + (Self::ImageRgb32F(p1), Self::ImageRgb32F(p2)) => p1.clone_from(p2), + (Self::ImageRgba32F(p1), Self::ImageRgba32F(p2)) => p1.clone_from(p2), + (this, source) => *this = source.clone(), + } + } +} + +impl DynamicImage { + /// Creates a dynamic image backed by a buffer depending on + /// the color type given. + /// + /// The color space is initially set to [`sRGB`][`Cicp::SRGB`]. + #[must_use] + pub fn new(w: u32, h: u32, color: color::ColorType) -> DynamicImage { + use color::ColorType::*; + match color { + L8 => Self::new_luma8(w, h), + La8 => Self::new_luma_a8(w, h), + Rgb8 => Self::new_rgb8(w, h), + Rgba8 => Self::new_rgba8(w, h), + L16 => Self::new_luma16(w, h), + La16 => Self::new_luma_a16(w, h), + Rgb16 => Self::new_rgb16(w, h), + Rgba16 => Self::new_rgba16(w, h), + Rgb32F => Self::new_rgb32f(w, h), + Rgba32F => Self::new_rgba32f(w, h), + } + } + + /// Creates a dynamic image backed by a buffer of gray pixels. + #[must_use] + pub fn new_luma8(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageLuma8(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of gray + /// pixels with transparency. + #[must_use] + pub fn new_luma_a8(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageLumaA8(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGB pixels. + #[must_use] + pub fn new_rgb8(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgb8(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGBA pixels. + #[must_use] + pub fn new_rgba8(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgba8(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of gray pixels. + #[must_use] + pub fn new_luma16(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageLuma16(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of gray + /// pixels with transparency. + #[must_use] + pub fn new_luma_a16(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageLumaA16(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGB pixels. + #[must_use] + pub fn new_rgb16(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgb16(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGBA pixels. + #[must_use] + pub fn new_rgba16(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgba16(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGB pixels. + #[must_use] + pub fn new_rgb32f(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgb32F(ImageBuffer::new(w, h)) + } + + /// Creates a dynamic image backed by a buffer of RGBA pixels. + #[must_use] + pub fn new_rgba32f(w: u32, h: u32) -> DynamicImage { + DynamicImage::ImageRgba32F(ImageBuffer::new(w, h)) + } + + /// Decodes an encoded image into a dynamic image. + pub fn from_decoder(decoder: impl ImageDecoder) -> ImageResult { + decoder_to_image(decoder) + } + + /// Encodes a dynamic image into a buffer. + /// + /// **WARNING**: Conversion between RGB and Luma is not aware of the color space and always + /// uses sRGB coefficients to determine a non-constant luminance from an RGB color (and + /// conversely). + /// + /// This unfortunately owes to the public bounds of `T` which does not allow for passing a + /// color space as a parameter. This function will likely be deprecated and replaced. + #[inline] + #[must_use] + pub fn to< + T: Pixel + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor> + + FromColor>, + >( + &self, + ) -> ImageBuffer> { + dynamic_map!(*self, ref p, p.convert()) + } + + /// Returns a copy of this image as an RGB image. + #[must_use] + pub fn to_rgb8(&self) -> RgbImage { + match self { + DynamicImage::ImageRgb8(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as an RGB image. + #[must_use] + pub fn to_rgb16(&self) -> Rgb16Image { + match self { + DynamicImage::ImageRgb16(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as an RGB image. + #[must_use] + pub fn to_rgb32f(&self) -> Rgb32FImage { + match self { + DynamicImage::ImageRgb32F(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as an RGBA image. + #[must_use] + pub fn to_rgba8(&self) -> RgbaImage { + match self { + DynamicImage::ImageRgba8(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as an RGBA image. + #[must_use] + pub fn to_rgba16(&self) -> Rgba16Image { + match self { + DynamicImage::ImageRgba16(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as an RGBA image. + #[must_use] + pub fn to_rgba32f(&self) -> Rgba32FImage { + match self { + DynamicImage::ImageRgba32F(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as a Luma image. + #[must_use] + pub fn to_luma8(&self) -> GrayImage { + match self { + DynamicImage::ImageLuma8(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as a Luma image. + #[must_use] + pub fn to_luma16(&self) -> Gray16Image { + match self { + DynamicImage::ImageLuma16(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as a Luma image. + #[must_use] + pub fn to_luma32f(&self) -> ImageBuffer, Vec> { + dynamic_map!(self, ref p, p.cast_in_color_space()) + } + + /// Returns a copy of this image as a `LumaA` image. + #[must_use] + pub fn to_luma_alpha8(&self) -> GrayAlphaImage { + match self { + DynamicImage::ImageLumaA8(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as a `LumaA` image. + #[must_use] + pub fn to_luma_alpha16(&self) -> GrayAlpha16Image { + match self { + DynamicImage::ImageLumaA16(x) => x.clone(), + x => dynamic_map!(x, ref p, p.cast_in_color_space()), + } + } + + /// Returns a copy of this image as a `LumaA` image. + #[must_use] + pub fn to_luma_alpha32f(&self) -> ImageBuffer, Vec> { + dynamic_map!(self, ref p, p.cast_in_color_space()) + } + + /// Consume the image and returns a RGB image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgb8(self) -> RgbImage { + match self { + DynamicImage::ImageRgb8(x) => x, + x => x.to_rgb8(), + } + } + + /// Consume the image and returns a RGB image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgb16(self) -> Rgb16Image { + match self { + DynamicImage::ImageRgb16(x) => x, + x => x.to_rgb16(), + } + } + + /// Consume the image and returns a RGB image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgb32f(self) -> Rgb32FImage { + match self { + DynamicImage::ImageRgb32F(x) => x, + x => x.to_rgb32f(), + } + } + + /// Consume the image and returns a RGBA image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgba8(self) -> RgbaImage { + match self { + DynamicImage::ImageRgba8(x) => x, + x => x.to_rgba8(), + } + } + + /// Consume the image and returns a RGBA image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgba16(self) -> Rgba16Image { + match self { + DynamicImage::ImageRgba16(x) => x, + x => x.to_rgba16(), + } + } + + /// Consume the image and returns a RGBA image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_rgba32f(self) -> Rgba32FImage { + match self { + DynamicImage::ImageRgba32F(x) => x, + x => x.to_rgba32f(), + } + } + + /// Consume the image and returns a Luma image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_luma8(self) -> GrayImage { + match self { + DynamicImage::ImageLuma8(x) => x, + x => x.to_luma8(), + } + } + + /// Consume the image and returns a Luma image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_luma16(self) -> Gray16Image { + match self { + DynamicImage::ImageLuma16(x) => x, + x => x.to_luma16(), + } + } + + /// Consume the image and returns a `LumaA` image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_luma_alpha8(self) -> GrayAlphaImage { + match self { + DynamicImage::ImageLumaA8(x) => x, + x => x.to_luma_alpha8(), + } + } + + /// Consume the image and returns a `LumaA` image. + /// + /// If the image was already the correct format, it is returned as is. + /// Otherwise, a copy is created. + #[must_use] + pub fn into_luma_alpha16(self) -> GrayAlpha16Image { + match self { + DynamicImage::ImageLumaA16(x) => x, + x => x.to_luma_alpha16(), + } + } + + /// Return a cut-out of this image delimited by the bounding rectangle. + /// + /// Note: this method does *not* modify the object, + /// and its signature will be replaced with `crop_imm()`'s in the 0.24 release + #[must_use] + pub fn crop(&mut self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage { + dynamic_map!(*self, ref mut p => imageops::crop(p, x, y, width, height).to_image()) + } + + /// Return a cut-out of this image delimited by the bounding rectangle. + #[must_use] + pub fn crop_imm(&self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::crop_imm(p, x, y, width, height).to_image()) + } + + /// Return a reference to an 8bit RGB image + #[must_use] + pub fn as_rgb8(&self) -> Option<&RgbImage> { + match *self { + DynamicImage::ImageRgb8(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 8bit RGB image + pub fn as_mut_rgb8(&mut self) -> Option<&mut RgbImage> { + match *self { + DynamicImage::ImageRgb8(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 8bit RGBA image + #[must_use] + pub fn as_rgba8(&self) -> Option<&RgbaImage> { + match *self { + DynamicImage::ImageRgba8(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 8bit RGBA image + pub fn as_mut_rgba8(&mut self) -> Option<&mut RgbaImage> { + match *self { + DynamicImage::ImageRgba8(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 8bit Grayscale image + #[must_use] + pub fn as_luma8(&self) -> Option<&GrayImage> { + match *self { + DynamicImage::ImageLuma8(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 8bit Grayscale image + pub fn as_mut_luma8(&mut self) -> Option<&mut GrayImage> { + match *self { + DynamicImage::ImageLuma8(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 8bit Grayscale image with an alpha channel + #[must_use] + pub fn as_luma_alpha8(&self) -> Option<&GrayAlphaImage> { + match *self { + DynamicImage::ImageLumaA8(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 8bit Grayscale image with an alpha channel + pub fn as_mut_luma_alpha8(&mut self) -> Option<&mut GrayAlphaImage> { + match *self { + DynamicImage::ImageLumaA8(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 16bit RGB image + #[must_use] + pub fn as_rgb16(&self) -> Option<&Rgb16Image> { + match *self { + DynamicImage::ImageRgb16(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 16bit RGB image + pub fn as_mut_rgb16(&mut self) -> Option<&mut Rgb16Image> { + match *self { + DynamicImage::ImageRgb16(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 16bit RGBA image + #[must_use] + pub fn as_rgba16(&self) -> Option<&Rgba16Image> { + match *self { + DynamicImage::ImageRgba16(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 16bit RGBA image + pub fn as_mut_rgba16(&mut self) -> Option<&mut Rgba16Image> { + match *self { + DynamicImage::ImageRgba16(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 32bit RGB image + #[must_use] + pub fn as_rgb32f(&self) -> Option<&Rgb32FImage> { + match *self { + DynamicImage::ImageRgb32F(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 32bit RGB image + pub fn as_mut_rgb32f(&mut self) -> Option<&mut Rgb32FImage> { + match *self { + DynamicImage::ImageRgb32F(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 32bit RGBA image + #[must_use] + pub fn as_rgba32f(&self) -> Option<&Rgba32FImage> { + match *self { + DynamicImage::ImageRgba32F(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 32bit RGBA image + pub fn as_mut_rgba32f(&mut self) -> Option<&mut Rgba32FImage> { + match *self { + DynamicImage::ImageRgba32F(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 16bit Grayscale image + #[must_use] + pub fn as_luma16(&self) -> Option<&Gray16Image> { + match *self { + DynamicImage::ImageLuma16(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 16bit Grayscale image + pub fn as_mut_luma16(&mut self) -> Option<&mut Gray16Image> { + match *self { + DynamicImage::ImageLuma16(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a reference to an 16bit Grayscale image with an alpha channel + #[must_use] + pub fn as_luma_alpha16(&self) -> Option<&GrayAlpha16Image> { + match *self { + DynamicImage::ImageLumaA16(ref p) => Some(p), + _ => None, + } + } + + /// Return a mutable reference to an 16bit Grayscale image with an alpha channel + pub fn as_mut_luma_alpha16(&mut self) -> Option<&mut GrayAlpha16Image> { + match *self { + DynamicImage::ImageLumaA16(ref mut p) => Some(p), + _ => None, + } + } + + /// Return a view on the raw sample buffer for 8 bit per channel images. + #[must_use] + pub fn as_flat_samples_u8(&self) -> Option> { + match *self { + DynamicImage::ImageLuma8(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageLumaA8(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageRgb8(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageRgba8(ref p) => Some(p.as_flat_samples()), + _ => None, + } + } + + /// Return a view on the raw sample buffer for 16 bit per channel images. + #[must_use] + pub fn as_flat_samples_u16(&self) -> Option> { + match *self { + DynamicImage::ImageLuma16(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageLumaA16(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageRgb16(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageRgba16(ref p) => Some(p.as_flat_samples()), + _ => None, + } + } + + /// Return a view on the raw sample buffer for 32bit per channel images. + #[must_use] + pub fn as_flat_samples_f32(&self) -> Option> { + match *self { + DynamicImage::ImageRgb32F(ref p) => Some(p.as_flat_samples()), + DynamicImage::ImageRgba32F(ref p) => Some(p.as_flat_samples()), + _ => None, + } + } + + /// Return this image's pixels as a native endian byte slice. + #[must_use] + pub fn as_bytes(&self) -> &[u8] { + // we can do this because every variant contains an `ImageBuffer<_, Vec<_>>` + dynamic_map!( + *self, + ref image_buffer, + bytemuck::cast_slice(image_buffer.as_raw()) + ) + } + + /// Return this image's pixels as a byte vector. If the `ImageBuffer` + /// container is `Vec`, this operation is free. Otherwise, a copy + /// is returned. + #[must_use] + pub fn into_bytes(self) -> Vec { + // we can do this because every variant contains an `ImageBuffer<_, Vec<_>>` + dynamic_map!(self, image_buffer, { + match bytemuck::allocation::try_cast_vec(image_buffer.into_raw()) { + Ok(vec) => vec, + Err((_, vec)) => { + // Fallback: vector requires an exact alignment and size match + // Reuse of the allocation as done in the Ok branch only works if the + // underlying container is exactly Vec (or compatible but that's the only + // alternative at the time of writing). + // In all other cases we must allocate a new vector with the 'same' contents. + bytemuck::cast_slice(&vec).to_owned() + } + } + }) + } + + /// Return this image's color type. + #[must_use] + pub fn color(&self) -> color::ColorType { + match *self { + DynamicImage::ImageLuma8(_) => color::ColorType::L8, + DynamicImage::ImageLumaA8(_) => color::ColorType::La8, + DynamicImage::ImageRgb8(_) => color::ColorType::Rgb8, + DynamicImage::ImageRgba8(_) => color::ColorType::Rgba8, + DynamicImage::ImageLuma16(_) => color::ColorType::L16, + DynamicImage::ImageLumaA16(_) => color::ColorType::La16, + DynamicImage::ImageRgb16(_) => color::ColorType::Rgb16, + DynamicImage::ImageRgba16(_) => color::ColorType::Rgba16, + DynamicImage::ImageRgb32F(_) => color::ColorType::Rgb32F, + DynamicImage::ImageRgba32F(_) => color::ColorType::Rgba32F, + } + } + + /// Returns the width of the underlying image + #[must_use] + pub fn width(&self) -> u32 { + dynamic_map!(*self, ref p, { p.width() }) + } + + /// Returns the height of the underlying image + #[must_use] + pub fn height(&self) -> u32 { + dynamic_map!(*self, ref p, { p.height() }) + } + + /// Define the color space for the image. + /// + /// The color data is unchanged. Reinterprets the existing red, blue, green channels as points + /// in the new set of primary colors, changing the apparent shade of pixels. + /// + /// Note that the primaries also define a reference whitepoint When this buffer contains Luma + /// data, the luminance channel is interpreted as the `Y` channel of a related `YCbCr` color + /// space as if by a non-constant chromaticity derived matrix. That is, coefficients are *not* + /// applied in the linear RGB space but use encoded channel values. (In a color space with the + /// linear transfer function there is no difference). + pub fn set_rgb_primaries(&mut self, color: CicpColorPrimaries) { + dynamic_map!(self, ref mut p, p.set_rgb_primaries(color)); + } + + /// Define the transfer function for the image. + /// + /// The color data is unchanged. Reinterprets all (non-alpha) components in the image, + /// potentially changing the apparent shade of pixels. Individual components are always + /// interpreted as encoded numbers. To denote numbers in a linear RGB space, use + /// [`CicpTransferCharacteristics::Linear`]. + pub fn set_transfer_function(&mut self, tf: CicpTransferCharacteristics) { + dynamic_map!(self, ref mut p, p.set_transfer_function(tf)); + } + + /// Get the Cicp encoding of this buffer's color data. + pub fn color_space(&self) -> Cicp { + dynamic_map!(self, ref p, p.color_space()) + } + + /// Set primaries and transfer characteristics from a Cicp color space. + /// + /// Returns an error if `cicp` uses features that are not support with an RGB color space, e.g. + /// a matrix or narrow range (studio encoding) channels. + pub fn set_color_space(&mut self, cicp: Cicp) -> ImageResult<()> { + dynamic_map!(self, ref mut p, p.set_color_space(cicp)) + } + + /// Whether the image contains an alpha channel + /// + /// This is a convenience wrapper around `self.color().has_alpha()`. + /// For inspecting other properties of the color type you should call + /// [DynamicImage::color] and use the methods on the returned [ColorType](color::ColorType). + /// + /// This only checks that the image's pixel type can express transparency, + /// not whether the image actually has any transparent areas. + #[must_use] + pub fn has_alpha(&self) -> bool { + self.color().has_alpha() + } + + /// Return a grayscale version of this image. + /// Returns `Luma` images in most cases. However, for `f32` images, + /// this will return a grayscale `Rgb/Rgba` image instead. + #[must_use] + pub fn grayscale(&self) -> DynamicImage { + match *self { + DynamicImage::ImageLuma8(ref p) => DynamicImage::ImageLuma8(p.clone()), + DynamicImage::ImageLumaA8(ref p) => { + DynamicImage::ImageLumaA8(imageops::grayscale_alpha(p)) + } + DynamicImage::ImageRgb8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)), + DynamicImage::ImageRgba8(ref p) => { + DynamicImage::ImageLumaA8(imageops::grayscale_alpha(p)) + } + DynamicImage::ImageLuma16(ref p) => DynamicImage::ImageLuma16(p.clone()), + DynamicImage::ImageLumaA16(ref p) => { + DynamicImage::ImageLumaA16(imageops::grayscale_alpha(p)) + } + DynamicImage::ImageRgb16(ref p) => DynamicImage::ImageLuma16(imageops::grayscale(p)), + DynamicImage::ImageRgba16(ref p) => { + DynamicImage::ImageLumaA16(imageops::grayscale_alpha(p)) + } + DynamicImage::ImageRgb32F(ref p) => { + DynamicImage::ImageRgb32F(imageops::grayscale_with_type(p)) + } + DynamicImage::ImageRgba32F(ref p) => { + DynamicImage::ImageRgba32F(imageops::grayscale_with_type_alpha(p)) + } + } + } + + /// Invert the colors of this image. + /// This method operates inplace. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + pub fn invert(&mut self) { + dynamic_map!(*self, ref mut p, imageops::invert(p)); + } + + /// Resize this image using the specified filter algorithm. + /// Returns a new image. The image's aspect ratio is preserved. + /// The image is scaled to the maximum possible size that fits + /// within the bounds specified by `nwidth` and `nheight`. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn resize(&self, nwidth: u32, nheight: u32, filter: imageops::FilterType) -> DynamicImage { + if (nwidth, nheight) == self.dimensions() { + return self.clone(); + } + let (width2, height2) = + resize_dimensions(self.width(), self.height(), nwidth, nheight, false); + + self.resize_exact(width2, height2, filter) + } + + /// Resize this image using the specified filter algorithm. + /// Returns a new image. Does not preserve aspect ratio. + /// `nwidth` and `nheight` are the new image's dimensions + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn resize_exact( + &self, + nwidth: u32, + nheight: u32, + filter: imageops::FilterType, + ) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::resize(p, nwidth, nheight, filter)) + } + + /// Scale this image down to fit within a specific size. + /// Returns a new image. The image's aspect ratio is preserved. + /// The image is scaled to the maximum possible size that fits + /// within the bounds specified by `nwidth` and `nheight`. + /// + /// This method uses a fast integer algorithm where each source + /// pixel contributes to exactly one target pixel. + /// May give aliasing artifacts if new size is close to old size. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn thumbnail(&self, nwidth: u32, nheight: u32) -> DynamicImage { + let (width2, height2) = + resize_dimensions(self.width(), self.height(), nwidth, nheight, false); + self.thumbnail_exact(width2, height2) + } + + /// Scale this image down to a specific size. + /// Returns a new image. Does not preserve aspect ratio. + /// `nwidth` and `nheight` are the new image's dimensions. + /// This method uses a fast integer algorithm where each source + /// pixel contributes to exactly one target pixel. + /// May give aliasing artifacts if new size is close to old size. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn thumbnail_exact(&self, nwidth: u32, nheight: u32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::thumbnail(p, nwidth, nheight)) + } + + /// Resize this image using the specified filter algorithm. + /// Returns a new image. The image's aspect ratio is preserved. + /// The image is scaled to the maximum possible size that fits + /// within the larger (relative to aspect ratio) of the bounds + /// specified by `nwidth` and `nheight`, then cropped to + /// fit within the other bound. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn resize_to_fill( + &self, + nwidth: u32, + nheight: u32, + filter: imageops::FilterType, + ) -> DynamicImage { + let (width2, height2) = + resize_dimensions(self.width(), self.height(), nwidth, nheight, true); + + let mut intermediate = self.resize_exact(width2, height2, filter); + let (iwidth, iheight) = intermediate.dimensions(); + let ratio = u64::from(iwidth) * u64::from(nheight); + let nratio = u64::from(nwidth) * u64::from(iheight); + + if nratio > ratio { + intermediate.crop(0, (iheight - nheight) / 2, nwidth, nheight) + } else { + intermediate.crop((iwidth - nwidth) / 2, 0, nwidth, nheight) + } + } + + /// Performs a Gaussian blur on this image. + /// + /// # Arguments + /// + /// * `sigma` - gaussian bell flattening level. + /// + /// Use [DynamicImage::fast_blur()] for a faster but less + /// accurate version. + /// + /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. + /// This method typically assumes that the input is scene-linear light. + /// If it is not, color distortion may occur. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn blur(&self, sigma: f32) -> DynamicImage { + gaussian_blur_dyn_image( + self, + GaussianBlurParameters::new_from_sigma(if sigma == 0.0 { 0.8 } else { sigma }), + ) + } + + /// Performs a Gaussian blur on this image. + /// + /// # Arguments + /// + /// * `parameters` - see [GaussianBlurParameters] for more info + /// + /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. + /// This method typically assumes that the input is scene-linear light. + /// If it is not, color distortion may occur. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn blur_advanced(&self, parameters: GaussianBlurParameters) -> DynamicImage { + gaussian_blur_dyn_image(self, parameters) + } + + /// Performs a fast blur on this image. + /// + /// # Arguments + /// + /// * `sigma` - value controls image flattening level. + /// + /// This method typically assumes that the input is scene-linear light. + /// If it is not, color distortion may occur. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn fast_blur(&self, sigma: f32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::fast_blur(p, sigma)) + } + + /// Performs an unsharpen mask on this image. + /// + /// # Arguments + /// + /// * `sigma` - value controls image flattening level. + /// * `threshold` - is a control of how much to sharpen. + /// + /// This method typically assumes that the input is scene-linear light. If it is not, color + /// distortion may occur. It operates on pixel channel values directly without taking into + /// account color space data. + /// + /// See [Digital unsharp masking](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) + /// for more information + #[must_use] + pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold)) + } + + /// Filters this image with the specified 3x3 kernel. + /// + /// # Arguments + /// + /// * `kernel` - slice contains filter. Only slice len is 9 length is accepted. + /// + /// This method typically assumes that the input is scene-linear light. It operates on pixel + /// channel values directly without taking into account color space data. If it is not, color + /// distortion may occur. + #[must_use] + pub fn filter3x3(&self, kernel: &[f32]) -> DynamicImage { + assert_eq!(9, kernel.len(), "filter must be 3 x 3"); + + dynamic_map!(*self, ref p => imageops::filter3x3(p, kernel)) + } + + /// Adjust the contrast of this image. + /// `contrast` is the amount to adjust the contrast by. + /// Negative values decrease the contrast and positive values increase the contrast. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn adjust_contrast(&self, c: f32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::contrast(p, c)) + } + + /// Brighten the pixels of this image. + /// `value` is the amount to brighten each pixel by. + /// Negative values decrease the brightness and positive values increase it. + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. + #[must_use] + pub fn brighten(&self, value: i32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::brighten(p, value)) + } + + /// Hue rotate the supplied image. + /// `value` is the degrees to rotate each pixel by. + /// 0 and 360 do nothing, the rest rotates by the given degree value. + /// just like the css webkit filter hue-rotate(180) + /// + /// This method operates on pixel channel values directly without taking into account color + /// space data. The HSV color space is dependent on the current color space primaries. + #[must_use] + pub fn huerotate(&self, value: i32) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::huerotate(p, value)) + } + + /// Flip this image vertically + /// + /// Use [`apply_orientation`](Self::apply_orientation) if you want to flip the image in-place instead. + #[must_use] + pub fn flipv(&self) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::flip_vertical(p)) + } + + /// Flip this image vertically in place + fn flipv_in_place(&mut self) { + dynamic_map!(*self, ref mut p, imageops::flip_vertical_in_place(p)) + } + + /// Flip this image horizontally + /// + /// Use [`apply_orientation`](Self::apply_orientation) if you want to flip the image in-place. + #[must_use] + pub fn fliph(&self) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::flip_horizontal(p)) + } + + /// Flip this image horizontally in place + fn fliph_in_place(&mut self) { + dynamic_map!(*self, ref mut p, imageops::flip_horizontal_in_place(p)) + } + + /// Rotate this image 90 degrees clockwise. + #[must_use] + pub fn rotate90(&self) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::rotate90(p)) + } + + /// Rotate this image 180 degrees. + /// + /// Use [`apply_orientation`](Self::apply_orientation) if you want to rotate the image in-place. + #[must_use] + pub fn rotate180(&self) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::rotate180(p)) + } + + /// Rotate this image 180 degrees in place. + fn rotate180_in_place(&mut self) { + dynamic_map!(*self, ref mut p, imageops::rotate180_in_place(p)) + } + + /// Rotate this image 270 degrees clockwise. + #[must_use] + pub fn rotate270(&self) -> DynamicImage { + dynamic_map!(*self, ref p => imageops::rotate270(p)) + } + + /// Rotates and/or flips the image as indicated by [Orientation]. + /// + /// This can be used to apply Exif orientation to an image, + /// e.g. to correctly display a photo taken by a smartphone camera: + /// + /// ``` + /// # fn only_check_if_this_compiles() -> Result<(), Box> { + /// use image::{DynamicImage, ImageReader, ImageDecoder}; + /// + /// let mut decoder = ImageReader::open("file.jpg")?.into_decoder()?; + /// let orientation = decoder.orientation()?; + /// let mut image = DynamicImage::from_decoder(decoder)?; + /// image.apply_orientation(orientation); + /// # Ok(()) + /// # } + /// ``` + /// + /// Note that for some orientations cannot be efficiently applied in-place. + /// In that case this function will make a copy of the image internally. + /// + /// If this matters to you, please see the documentation on the variants of [Orientation] + /// to learn which orientations can and cannot be applied without copying. + pub fn apply_orientation(&mut self, orientation: Orientation) { + let image = self; + match orientation { + Orientation::NoTransforms => (), + Orientation::Rotate90 => *image = image.rotate90(), + Orientation::Rotate180 => image.rotate180_in_place(), + Orientation::Rotate270 => *image = image.rotate270(), + Orientation::FlipHorizontal => image.fliph_in_place(), + Orientation::FlipVertical => image.flipv_in_place(), + Orientation::Rotate90FlipH => { + let mut new_image = image.rotate90(); + new_image.fliph_in_place(); + *image = new_image; + } + Orientation::Rotate270FlipH => { + let mut new_image = image.rotate270(); + new_image.fliph_in_place(); + *image = new_image; + } + } + } + + /// Copy pixel data from one buffer to another. + /// + /// On success, this dynamic image contains color data equivalent to the sources color data. + /// Neither the color space nor the sample type of `self` is changed, the data representation + /// is transformed and copied into the current buffer. + /// + /// Returns `Ok` if: + /// - Both images to have the same dimensions, otherwise returns a [`ImageError::Parameter`]. + /// - The primaries and transfer functions of both image's color spaces must be supported, + /// otherwise returns a [`ImageError::Unsupported`]. + /// + /// See also [`Self::apply_color_space`] and [`Self::convert_color_space`] to modify an image + /// directly. + /// + /// ## Accuracy + /// + /// All color values are subject to change to their _intended_ values. Please do not rely on + /// them further than your own colorimetric understanding shows them correct. For instance, + /// conversion of RGB to their corresponding Luma values needs to be modified in future + /// versions of this library. Expect colors to be too bright or too dark until further notice. + pub fn copy_from_color_space( + &mut self, + other: &DynamicImage, + mut options: ConvertColorOptions, + ) -> ImageResult<()> { + // Try to no-op this transformation, we may be lucky.. + if self.color_space() == other.color_space() { + // Nothing to transform, just rescale samples and type cast. + dynamic_map!( + self, + ref mut p, + *p = dynamic_map!(other, ref o, o.cast_in_color_space()) + ); + + return Ok(()); + } + + // Do a transformation from existing buffer to existing buffer, only for color types that + // are currently supported. Other color types must use the fallback below. If we expand the + // range of supported color types we must consider how to write this more neatly. + match (&mut *self, other) { + // u8 sample types + (DynamicImage::ImageRgb8(img), DynamicImage::ImageRgb8(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgb8(img), DynamicImage::ImageRgba8(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba8(img), DynamicImage::ImageRgb8(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba8(img), DynamicImage::ImageRgba8(other)) => { + return img.copy_from_color_space(other, options); + } + // u16 sample types + (DynamicImage::ImageRgb16(img), DynamicImage::ImageRgb16(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgb16(img), DynamicImage::ImageRgba16(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba16(img), DynamicImage::ImageRgb16(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba16(img), DynamicImage::ImageRgba16(other)) => { + return img.copy_from_color_space(other, options); + } + // 32F sample types. + (DynamicImage::ImageRgb32F(img), DynamicImage::ImageRgb32F(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgb32F(img), DynamicImage::ImageRgba32F(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba32F(img), DynamicImage::ImageRgb32F(other)) => { + return img.copy_from_color_space(other, options); + } + (DynamicImage::ImageRgba32F(img), DynamicImage::ImageRgba32F(other)) => { + return img.copy_from_color_space(other, options); + } + _ => {} + }; + + // If we reach here we have a mismatch of sample types. Our conversion supports only input + // and output of the same sample type. As a simplification we will do the conversion only + // in `f32` samples. Thus we first convert the source to `f32` samples taking care it does + // not involve (lossy) color conversion (into with luma -> rgb for instance). Note: we do + // not have Luma as a type. + let cicp = options.as_transform(other.color_space(), self.color_space())?; + cicp.transform_dynamic(self, other); + + Ok(()) + } + + /// Change the color space, modifying pixel values to refer to the same colors. + /// + /// On success, this dynamic image contains color data equivalent to its previous color data. + /// The sample type of `self` is not changed, the data representation is transformed within the + /// current buffer. + /// + /// Returns `Ok` if: + /// - The primaries and transfer functions of both image's color spaces must be supported, + /// otherwise returns a [`ImageError::Unsupported`]. + /// - The target `Cicp` must have full range and an `Identity` matrix. (This library's + /// [`Luma`][`crate::Luma`] refers implicity to a chromaticity derived non-constant luminance + /// color). + /// + /// See also [`Self::copy_from_color_space`]. + pub fn apply_color_space( + &mut self, + cicp: Cicp, + options: ConvertColorOptions, + ) -> ImageResult<()> { + // If the color space is already set, we can just return. + if self.color_space() == cicp { + return Ok(()); + } + + // We could conceivably do this in-place faster but to handle the Luma conversion as we + // want this requires the full machinery as `CicpTransform::transform_dynamic` which is + // quite the replication. Let's just see if it is fast enough. Feel free to PR something if + // it is easy enough to review. + let mut target = self.clone(); + target.set_color_space(cicp)?; + target.copy_from_color_space(self, options)?; + + *self = target; + Ok(()) + } + + /// Change the color space and pixel type of this image. + /// + /// On success, this dynamic image contains color data equivalent to its previous color data + /// with another type of pixels. + /// + /// Returns `Ok` if: + /// - The primaries and transfer functions of both image's color spaces must be supported, + /// otherwise returns a [`ImageError::Unsupported`]. + /// - The target `Cicp` must have full range and an `Identity` matrix. (This library's + /// [`Luma`][`crate::Luma`] refers implicity to a chromaticity derived non-constant luminance + /// color). + /// + /// See also [`Self::copy_from_color_space`]. + pub fn convert_color_space( + &mut self, + cicp: Cicp, + options: ConvertColorOptions, + color: color::ColorType, + ) -> ImageResult<()> { + if self.color() == color { + return self.apply_color_space(cicp, options); + } + + // Forward compatibility: make sure we do not drop any details here. + let rgb = cicp.try_into_rgb()?; + let mut target = DynamicImage::new(self.width(), self.height(), color); + dynamic_map!(target, ref mut p, p.set_rgb_color_space(rgb)); + target.copy_from_color_space(self, options)?; + + *self = target; + Ok(()) + } + + fn write_with_encoder_impl<'a>( + &self, + encoder: Box, + ) -> ImageResult<()> { + let converted = encoder.make_compatible_img(crate::io::encoder::MethodSealedToImage, self); + let img = converted.as_ref().unwrap_or(self); + + encoder.write_image( + img.as_bytes(), + img.width(), + img.height(), + img.color().into(), + ) + } + + /// Encode this image and write it to `w`. + /// + /// Assumes the writer is buffered. In most cases, you should wrap your writer in a `BufWriter` + /// for best performance. + /// + /// ## Color Conversion + /// + /// Unlike other encoding methods in this crate, methods on `DynamicImage` try to automatically + /// convert the image to some color type supported by the encoder. This may result in a loss of + /// precision or the removal of the alpha channel. + pub fn write_to(&self, mut w: W, format: ImageFormat) -> ImageResult<()> { + let encoder = encoder_for_format(format, &mut w)?; + self.write_with_encoder_impl(encoder) + } + + /// Encode this image with the provided encoder. + /// + /// ## Color Conversion + /// + /// Unlike other encoding methods in this crate, methods on `DynamicImage` try to automatically + /// convert the image to some color type supported by the encoder. This may result in a loss of + /// precision or the removal of the alpha channel. + pub fn write_with_encoder(&self, encoder: impl ImageEncoder) -> ImageResult<()> { + self.write_with_encoder_impl(Box::new(encoder)) + } + + /// Saves the buffer to a file with the format derived from the file extension. + /// + /// ## Color Conversion + /// + /// Unlike other encoding methods in this crate, methods on `DynamicImage` try to automatically + /// convert the image to some color type supported by the encoder. This may result in a loss of + /// precision or the removal of the alpha channel. + pub fn save(&self, path: Q) -> ImageResult<()> + where + Q: AsRef, + { + let format = ImageFormat::from_path(path.as_ref())?; + self.save_with_format(path, format) + } + + /// Saves the buffer to a file with the specified format. + /// + /// ## Color Conversion + /// + /// Unlike other encoding methods in this crate, methods on `DynamicImage` try to automatically + /// convert the image to some color type supported by the encoder. This may result in a loss of + /// precision or the removal of the alpha channel. + pub fn save_with_format(&self, path: Q, format: ImageFormat) -> ImageResult<()> + where + Q: AsRef, + { + let file = &mut BufWriter::new(File::create(path)?); + let encoder = encoder_for_format(format, file)?; + self.write_with_encoder_impl(encoder) + } +} + +impl From for DynamicImage { + fn from(image: GrayImage) -> Self { + DynamicImage::ImageLuma8(image) + } +} + +impl From for DynamicImage { + fn from(image: GrayAlphaImage) -> Self { + DynamicImage::ImageLumaA8(image) + } +} + +impl From for DynamicImage { + fn from(image: RgbImage) -> Self { + DynamicImage::ImageRgb8(image) + } +} + +impl From for DynamicImage { + fn from(image: RgbaImage) -> Self { + DynamicImage::ImageRgba8(image) + } +} + +impl From for DynamicImage { + fn from(image: Gray16Image) -> Self { + DynamicImage::ImageLuma16(image) + } +} + +impl From for DynamicImage { + fn from(image: GrayAlpha16Image) -> Self { + DynamicImage::ImageLumaA16(image) + } +} + +impl From for DynamicImage { + fn from(image: Rgb16Image) -> Self { + DynamicImage::ImageRgb16(image) + } +} + +impl From for DynamicImage { + fn from(image: Rgba16Image) -> Self { + DynamicImage::ImageRgba16(image) + } +} + +impl From for DynamicImage { + fn from(image: Rgb32FImage) -> Self { + DynamicImage::ImageRgb32F(image) + } +} + +impl From for DynamicImage { + fn from(image: Rgba32FImage) -> Self { + DynamicImage::ImageRgba32F(image) + } +} + +impl From, Vec>> for DynamicImage { + fn from(image: ImageBuffer, Vec>) -> Self { + DynamicImage::ImageRgb32F(image.convert()) + } +} + +impl From, Vec>> for DynamicImage { + fn from(image: ImageBuffer, Vec>) -> Self { + DynamicImage::ImageRgba32F(image.convert()) + } +} + +#[allow(deprecated)] +impl GenericImageView for DynamicImage { + type Pixel = color::Rgba; // TODO use f32 as default for best precision and unbounded color? + + fn dimensions(&self) -> (u32, u32) { + dynamic_map!(*self, ref p, p.dimensions()) + } + + fn get_pixel(&self, x: u32, y: u32) -> color::Rgba { + dynamic_map!(*self, ref p, p.get_pixel(x, y).to_rgba().into_color()) + } +} + +#[allow(deprecated)] +impl GenericImage for DynamicImage { + fn put_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { + match *self { + DynamicImage::ImageLuma8(ref mut p) => p.put_pixel(x, y, pixel.to_luma()), + DynamicImage::ImageLumaA8(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha()), + DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, pixel.to_rgb()), + DynamicImage::ImageRgba8(ref mut p) => p.put_pixel(x, y, pixel), + DynamicImage::ImageLuma16(ref mut p) => p.put_pixel(x, y, pixel.to_luma().into_color()), + DynamicImage::ImageLumaA16(ref mut p) => { + p.put_pixel(x, y, pixel.to_luma_alpha().into_color()); + } + DynamicImage::ImageRgb16(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()), + DynamicImage::ImageRgba16(ref mut p) => p.put_pixel(x, y, pixel.into_color()), + DynamicImage::ImageRgb32F(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()), + DynamicImage::ImageRgba32F(ref mut p) => p.put_pixel(x, y, pixel.into_color()), + } + } + + fn blend_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { + match *self { + DynamicImage::ImageLuma8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma()), + DynamicImage::ImageLumaA8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha()), + DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb()), + DynamicImage::ImageRgba8(ref mut p) => p.blend_pixel(x, y, pixel), + DynamicImage::ImageLuma16(ref mut p) => { + p.blend_pixel(x, y, pixel.to_luma().into_color()); + } + DynamicImage::ImageLumaA16(ref mut p) => { + p.blend_pixel(x, y, pixel.to_luma_alpha().into_color()); + } + DynamicImage::ImageRgb16(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb().into_color()), + DynamicImage::ImageRgba16(ref mut p) => p.blend_pixel(x, y, pixel.into_color()), + DynamicImage::ImageRgb32F(ref mut p) => { + p.blend_pixel(x, y, pixel.to_rgb().into_color()); + } + DynamicImage::ImageRgba32F(ref mut p) => p.blend_pixel(x, y, pixel.into_color()), + } + } + + /// Do not use is function: It is unimplemented! + fn get_pixel_mut(&mut self, _: u32, _: u32) -> &mut color::Rgba { + unimplemented!() + } +} + +impl Default for DynamicImage { + fn default() -> Self { + Self::ImageRgba8(Default::default()) + } +} + +/// Decodes an image and stores it into a dynamic image +fn decoder_to_image(decoder: I) -> ImageResult { + let (w, h) = decoder.dimensions(); + let color_type = decoder.color_type(); + + let mut image = match color_type { + color::ColorType::Rgb8 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb8) + } + + color::ColorType::Rgba8 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba8) + } + + color::ColorType::L8 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma8) + } + + color::ColorType::La8 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA8) + } + + color::ColorType::Rgb16 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb16) + } + + color::ColorType::Rgba16 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba16) + } + + color::ColorType::Rgb32F => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb32F) + } + + color::ColorType::Rgba32F => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba32F) + } + + color::ColorType::L16 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma16) + } + + color::ColorType::La16 => { + let buf = free_functions::decoder_to_vec(decoder)?; + ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA16) + } + } + .ok_or_else(|| { + ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + )) + })?; + + // Presume SRGB for now. This is the one we convert into in some decoders and the one that is + // most widely used in the wild. FIXME: add an API to decoder to indicate the color space as a + // CICP directly or through interpreting the ICC information. + image.set_rgb_primaries(Cicp::SRGB.primaries); + image.set_transfer_function(Cicp::SRGB.transfer); + + Ok(image) +} + +/// Open the image located at the path specified. +/// The image's format is determined from the path's file extension. +/// +/// Try [`ImageReader`] for more advanced uses, including guessing the format based on the file's +/// content before its path. +pub fn open

(path: P) -> ImageResult +where + P: AsRef, +{ + ImageReader::open(path)?.decode() +} + +/// Read a tuple containing the (width, height) of the image located at the specified path. +/// This is faster than fully loading the image and then getting its dimensions. +/// +/// Try [`ImageReader`] for more advanced uses, including guessing the format based on the file's +/// content before its path or manually supplying the format. +pub fn image_dimensions

(path: P) -> ImageResult<(u32, u32)> +where + P: AsRef, +{ + ImageReader::open(path)?.into_dimensions() +} + +/// Writes the supplied buffer to a writer in the specified format. +/// +/// The buffer is assumed to have the correct format according to the specified color type. This +/// will lead to corrupted writers if the buffer contains malformed data. +/// +/// Assumes the writer is buffered. In most cases, you should wrap your writer in a `BufWriter` for +/// best performance. +pub fn write_buffer_with_format( + buffered_writer: &mut W, + buf: &[u8], + width: u32, + height: u32, + color: impl Into, + format: ImageFormat, +) -> ImageResult<()> { + let encoder = encoder_for_format(format, buffered_writer)?; + encoder.write_image(buf, width, height, color.into()) +} + +/// Create a new image from a byte slice +/// +/// Makes an educated guess about the image format. +/// TGA is not supported by this function. +/// +/// Try [`ImageReader`] for more advanced uses. +pub fn load_from_memory(buffer: &[u8]) -> ImageResult { + let format = free_functions::guess_format(buffer)?; + load_from_memory_with_format(buffer, format) +} + +/// Create a new image from a byte slice +/// +/// This is just a simple wrapper that constructs an `std::io::Cursor` around the buffer and then +/// calls `load` with that reader. +/// +/// Try [`ImageReader`] for more advanced uses. +/// +/// [`load`]: fn.load.html +#[inline(always)] +pub fn load_from_memory_with_format(buf: &[u8], format: ImageFormat) -> ImageResult { + // Note: this function (and `load_from_memory`) were supposed to be generic over `AsRef<[u8]>` + // so that we do not monomorphize copies of all our decoders unless some downsteam crate + // actually calls one of these functions. See https://github.com/image-rs/image/pull/2470. + // + // However the type inference break of this is apparently quite large in the ecosystem so for + // now they are unfortunately not. See https://github.com/image-rs/image/issues/2585. + let b = io::Cursor::new(buf); + free_functions::load(b, format) +} + +#[cfg(test)] +mod bench { + #[bench] + #[cfg(feature = "benchmarks")] + fn bench_conversion(b: &mut test::Bencher) { + let a = super::DynamicImage::ImageRgb8(crate::ImageBuffer::new(1000, 1000)); + b.iter(|| a.to_luma8()); + b.bytes = 1000 * 1000 * 3; + } +} + +#[cfg(test)] +mod test { + use crate::metadata::{CicpColorPrimaries, CicpTransform}; + use crate::ConvertColorOptions; + use crate::{color::ColorType, images::dynimage::Gray16Image}; + use crate::{metadata::Cicp, ImageBuffer, Luma, Rgb, Rgba}; + + #[test] + fn test_empty_file() { + assert!(super::load_from_memory(b"").is_err()); + } + + #[cfg(feature = "jpeg")] + #[test] + fn image_dimensions() { + let im_path = "./tests/images/jpg/progressive/cat.jpg"; + let dims = super::image_dimensions(im_path).unwrap(); + assert_eq!(dims, (320, 240)); + } + + #[cfg(feature = "png")] + #[test] + fn open_16bpc_png() { + let im_path = "./tests/images/png/16bpc/basn6a16.png"; + let image = super::open(im_path).unwrap(); + assert_eq!(image.color(), ColorType::Rgba16); + } + + fn test_grayscale(mut img: super::DynamicImage, alpha_discarded: bool) { + use crate::{GenericImage as _, GenericImageView as _}; + img.put_pixel(0, 0, Rgba([255, 0, 0, 100])); + let expected_alpha = if alpha_discarded { 255 } else { 100 }; + assert_eq!( + img.grayscale().get_pixel(0, 0), + Rgba([54, 54, 54, expected_alpha]) + ); + } + + fn test_grayscale_alpha_discarded(img: super::DynamicImage) { + test_grayscale(img, true); + } + + fn test_grayscale_alpha_preserved(img: super::DynamicImage) { + test_grayscale(img, false); + } + + #[test] + fn test_grayscale_luma8() { + test_grayscale_alpha_discarded(super::DynamicImage::new_luma8(1, 1)); + test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::L8)); + } + + #[test] + fn test_grayscale_luma_a8() { + test_grayscale_alpha_preserved(super::DynamicImage::new_luma_a8(1, 1)); + test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::La8)); + } + + #[test] + fn test_grayscale_rgb8() { + test_grayscale_alpha_discarded(super::DynamicImage::new_rgb8(1, 1)); + test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb8)); + } + + #[test] + fn test_grayscale_rgba8() { + test_grayscale_alpha_preserved(super::DynamicImage::new_rgba8(1, 1)); + test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba8)); + } + + #[test] + fn test_grayscale_luma16() { + test_grayscale_alpha_discarded(super::DynamicImage::new_luma16(1, 1)); + test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::L16)); + } + + #[test] + fn test_grayscale_luma_a16() { + test_grayscale_alpha_preserved(super::DynamicImage::new_luma_a16(1, 1)); + test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::La16)); + } + + #[test] + fn test_grayscale_rgb16() { + test_grayscale_alpha_discarded(super::DynamicImage::new_rgb16(1, 1)); + test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb16)); + } + + #[test] + fn test_grayscale_rgba16() { + test_grayscale_alpha_preserved(super::DynamicImage::new_rgba16(1, 1)); + test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba16)); + } + + #[test] + fn test_grayscale_rgb32f() { + test_grayscale_alpha_discarded(super::DynamicImage::new_rgb32f(1, 1)); + test_grayscale_alpha_discarded(super::DynamicImage::new(1, 1, ColorType::Rgb32F)); + } + + #[test] + fn test_grayscale_rgba32f() { + test_grayscale_alpha_preserved(super::DynamicImage::new_rgba32f(1, 1)); + test_grayscale_alpha_preserved(super::DynamicImage::new(1, 1, ColorType::Rgba32F)); + } + + #[test] + fn test_dynamic_image_default_implementation() { + // Test that structs wrapping a DynamicImage are able to auto-derive the Default trait + // ensures that DynamicImage implements Default (if it didn't, this would cause a compile error). + #[derive(Default)] + #[allow(dead_code)] + struct Foo { + _image: super::DynamicImage, + } + } + + #[test] + fn test_to_vecu8() { + let _ = super::DynamicImage::new_luma8(1, 1).into_bytes(); + let _ = super::DynamicImage::new_luma16(1, 1).into_bytes(); + } + + #[test] + fn issue_1705_can_turn_16bit_image_into_bytes() { + let pixels = vec![65535u16; 64 * 64]; + let img = ImageBuffer::from_vec(64, 64, pixels).unwrap(); + + let img = super::DynamicImage::ImageLuma16(img); + assert!(img.as_luma16().is_some()); + + let bytes: Vec = img.into_bytes(); + assert_eq!(bytes, vec![0xFF; 64 * 64 * 2]); + } + + #[test] + fn test_convert_to() { + use crate::Luma; + let image_luma8 = super::DynamicImage::new_luma8(1, 1); + let image_luma16 = super::DynamicImage::new_luma16(1, 1); + assert_eq!(image_luma8.to_luma16(), image_luma16.to_luma16()); + + // test conversion using typed result + let conv: Gray16Image = image_luma8.to(); + assert_eq!(image_luma8.to_luma16(), conv); + + // test conversion using turbofish syntax + let converted = image_luma8.to::>(); + assert_eq!(image_luma8.to_luma16(), converted); + } + + #[test] + fn color_conversion_srgb_p3() { + let mut source = super::DynamicImage::ImageRgb8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([255, 0, 0])) + }); + + let mut target = super::DynamicImage::ImageRgba8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())) + }); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + target.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + let target = target.as_rgba8().expect("Sample type unchanged"); + assert_eq!(target[(0, 0)], Rgba([234u8, 51, 35, 255])); + } + + #[test] + fn color_conversion_preserves_sample() { + let mut source = super::DynamicImage::ImageRgb16({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u16::MAX, 0, 0])) + }); + + let mut target = super::DynamicImage::ImageRgba8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())) + }); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + target.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + let target = target.as_rgba8().expect("Sample type unchanged"); + assert_eq!(target[(0, 0)], Rgba([234u8, 51, 35, 255])); + } + + #[test] + fn color_conversion_preserves_sample_in_fastpath() { + let source = super::DynamicImage::ImageRgb16({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u16::MAX, 0, 0])) + }); + + let mut target = super::DynamicImage::ImageRgba8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default())) + }); + + // No color space change takes place, but still sample should be converted. + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + let target = target.as_rgba8().expect("Sample type unchanged"); + assert_eq!(target[(0, 0)], Rgba([255u8, 0, 0, 255])); + } + + #[test] + fn color_conversion_rgb_to_luma() { + let source = super::DynamicImage::ImageRgb16({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([0, u16::MAX, 0])) + }); + + let mut target = super::DynamicImage::ImageLuma8({ + ImageBuffer::from_fn(128, 128, |_, _| Luma(Default::default())) + }); + + // No color space change takes place, but still sample should be converted. + let result = target.copy_from_color_space(&source, Default::default()); + + assert!(result.is_ok(), "{result:?}"); + // FIXME: but the result value is .. not ideal. + target.as_luma8().expect("Sample type unchanged"); + } + + #[test] + fn copy_color_space_coverage() { + const TYPES: [ColorType; 10] = [ + ColorType::L8, + ColorType::La8, + ColorType::Rgb8, + ColorType::Rgba8, + ColorType::L16, + ColorType::La16, + ColorType::Rgb16, + ColorType::Rgba16, + ColorType::Rgb32F, + ColorType::Rgba32F, + ]; + + let transform = + CicpTransform::new(Cicp::SRGB, Cicp::DISPLAY_P3).expect("Failed to create transform"); + + for from in TYPES { + for to in TYPES { + let mut source = super::DynamicImage::new(16, 16, from); + let mut target = super::DynamicImage::new(16, 16, to); + + source.set_rgb_primaries(Cicp::SRGB.primaries); + source.set_transfer_function(Cicp::SRGB.transfer); + + target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + target.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + target + .copy_from_color_space( + &source, + ConvertColorOptions { + transform: Some(transform.clone()), + ..Default::default() + }, + ) + .expect("Failed to convert color space"); + } + } + } + + #[test] + fn apply_color_space() { + let mut buffer = super::DynamicImage::ImageRgb8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u8::MAX, 0, 0])) + }); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + buffer.set_transfer_function(Cicp::SRGB.transfer); + + buffer + .apply_color_space(Cicp::DISPLAY_P3, Default::default()) + .unwrap(); + + let target = buffer.as_rgb8().expect("Sample type unchanged"); + assert_eq!(target[(0, 0)], Rgb([234u8, 51, 35])); + } + + #[test] + fn apply_color_space_coverage() { + const TYPES: [ColorType; 10] = [ + ColorType::L8, + ColorType::La8, + ColorType::Rgb8, + ColorType::Rgba8, + ColorType::L16, + ColorType::La16, + ColorType::Rgb16, + ColorType::Rgba16, + ColorType::Rgb32F, + ColorType::Rgba32F, + ]; + + let transform = + CicpTransform::new(Cicp::SRGB, Cicp::DISPLAY_P3).expect("Failed to create transform"); + + for buffer in TYPES { + let mut buffer = super::DynamicImage::new(16, 16, buffer); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + buffer.set_transfer_function(Cicp::SRGB.transfer); + + buffer + .apply_color_space( + Cicp::DISPLAY_P3, + ConvertColorOptions { + transform: Some(transform.clone()), + ..Default::default() + }, + ) + .expect("Failed to convert color space"); + } + } + + #[test] + fn convert_color_space() { + let mut buffer = super::DynamicImage::ImageRgb16({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u16::MAX, 0, 0])) + }); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + buffer.set_transfer_function(Cicp::SRGB.transfer); + + buffer + .convert_color_space(Cicp::DISPLAY_P3, Default::default(), ColorType::Rgb8) + .unwrap(); + + let target = buffer.as_rgb8().expect("Sample type now rgb8"); + assert_eq!(target[(0, 0)], Rgb([234u8, 51, 35])); + } + + #[test] + fn into_luma_is_color_space_aware() { + let mut buffer = super::DynamicImage::ImageRgb16({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u16::MAX, 0, 0])) + }); + + buffer.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + buffer.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + let luma8 = buffer.clone().into_luma8(); + assert_eq!(luma8[(0, 0)], Luma([58u8])); + assert_eq!(luma8.color_space(), Cicp::DISPLAY_P3); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + + let luma8 = buffer.clone().into_luma8(); + assert_eq!(luma8[(0, 0)], Luma([54u8])); + assert_ne!(luma8.color_space(), Cicp::DISPLAY_P3); + } + + #[test] + fn from_luma_is_color_space_aware() { + let mut buffer = super::DynamicImage::ImageLuma16({ + ImageBuffer::from_fn(128, 128, |_, _| Luma([u16::MAX])) + }); + + buffer.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + buffer.set_transfer_function(Cicp::DISPLAY_P3.transfer); + + let rgb8 = buffer.clone().into_rgb8(); + assert_eq!(rgb8[(0, 0)], Rgb([u8::MAX; 3])); + assert_eq!(rgb8.color_space(), Cicp::DISPLAY_P3); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + + let rgb8 = buffer.clone().into_rgb8(); + assert_eq!(rgb8[(0, 0)], Rgb([u8::MAX; 3])); + assert_ne!(rgb8.color_space(), Cicp::DISPLAY_P3); + } + + #[test] + fn from_luma_for_all_chromaticities() { + const CHROMA: &[CicpColorPrimaries] = &[ + (CicpColorPrimaries::SRgb), + (CicpColorPrimaries::RgbM), + (CicpColorPrimaries::RgbB), + (CicpColorPrimaries::Bt601), + (CicpColorPrimaries::Rgb240m), + (CicpColorPrimaries::GenericFilm), + (CicpColorPrimaries::Rgb2020), + // Note: here red=X and blue=Z and both are free of luminance + (CicpColorPrimaries::Xyz), + (CicpColorPrimaries::SmpteRp431), + (CicpColorPrimaries::SmpteRp432), + (CicpColorPrimaries::Industry22), + // Falls back to sRGB + (CicpColorPrimaries::Unspecified), + ]; + + let mut buffer = super::DynamicImage::ImageLuma16({ + ImageBuffer::from_fn(128, 128, |_, _| Luma([u16::MAX])) + }); + + for &chroma in CHROMA { + buffer.set_rgb_primaries(chroma); + let rgb = buffer.to_rgb8(); + assert_eq!( + rgb[(0, 0)], + Rgb([u8::MAX; 3]), + "Failed for chroma: {chroma:?}" + ); + } + } + + #[test] + fn from_rgb_for_all_chromaticities() { + // The colors following the coefficients must result in a luma that is the square-root + // length of the coefficient vector, which is unique enough for a test. + const CHROMA: &[(CicpColorPrimaries, [u8; 3], u8)] = &[ + (CicpColorPrimaries::SRgb, [54, 182, 18], 143), + (CicpColorPrimaries::RgbM, [76, 150, 29], 114), + (CicpColorPrimaries::RgbB, [57, 180, 18], 141), + (CicpColorPrimaries::Bt601, [54, 179, 22], 139), + (CicpColorPrimaries::Rgb240m, [54, 179, 22], 139), + (CicpColorPrimaries::GenericFilm, [65, 173, 17], 135), + (CicpColorPrimaries::Rgb2020, [67, 173, 15], 136), + // Note: here red=X and blue=Z and both are free of luminance + (CicpColorPrimaries::Xyz, [0, 255, 0], 255), + (CicpColorPrimaries::SmpteRp431, [53, 184, 18], 145), + (CicpColorPrimaries::SmpteRp432, [58, 176, 20], 137), + (CicpColorPrimaries::Industry22, [59, 171, 24], 131), + // Falls back to sRGB + (CicpColorPrimaries::Unspecified, [54, 182, 18], 143), + ]; + + let mut buffer = super::DynamicImage::ImageRgb8({ + ImageBuffer::from_fn(128, 128, |_, _| Rgb([u8::MAX; 3])) + }); + + for &(chroma, rgb, luma) in CHROMA { + buffer.set_rgb_primaries(chroma); + + for px in buffer.as_mut_rgb8().unwrap().pixels_mut() { + px.0 = rgb; + } + + let buf = buffer.to_luma8(); + assert_eq!(buf[(0, 0)], Luma([luma]), "Failed for chroma: {chroma:?}"); + } + } + + #[test] + fn convert_color_space_coverage() { + const TYPES: [ColorType; 10] = [ + ColorType::L8, + ColorType::La8, + ColorType::Rgb8, + ColorType::Rgba8, + ColorType::L16, + ColorType::La16, + ColorType::Rgb16, + ColorType::Rgba16, + ColorType::Rgb32F, + ColorType::Rgba32F, + ]; + + let transform = + CicpTransform::new(Cicp::SRGB, Cicp::DISPLAY_P3).expect("Failed to create transform"); + + for from in TYPES { + for to in TYPES { + let mut buffer = super::DynamicImage::new(16, 16, from); + + buffer.set_rgb_primaries(Cicp::SRGB.primaries); + buffer.set_transfer_function(Cicp::SRGB.transfer); + + let options = ConvertColorOptions { + transform: Some(transform.clone()), + ..Default::default() + }; + + buffer + .convert_color_space(Cicp::DISPLAY_P3, options, to) + .expect("Failed to convert color space"); + } + } + } + + /// Check that operations that are not cicp-aware behave as such. We introduce new methods (not + /// based directly on the public imageops interface) at a later point. + #[cfg(feature = "png")] + #[test] + fn color_space_independent_imageops() { + let im_path = "./tests/images/png/16bpc/basn6a16.png"; + + let mut image = super::open(im_path).unwrap(); + let mut clone = image.clone(); + + image.set_color_space(Cicp::SRGB).unwrap(); + clone.set_color_space(Cicp::DISPLAY_P3).unwrap(); + + const IMAGEOPS: &[&dyn Fn(&super::DynamicImage) -> super::DynamicImage] = &[ + &|img| img.resize(32, 32, crate::imageops::FilterType::Lanczos3), + &|img| img.resize_exact(32, 32, crate::imageops::FilterType::Lanczos3), + &|img| img.thumbnail(8, 8), + &|img| img.thumbnail_exact(8, 8), + &|img| img.resize_to_fill(32, 32, crate::imageops::FilterType::Lanczos3), + &|img| img.blur(1.0), + &|img| { + img.blur_advanced( + crate::imageops::GaussianBlurParameters::new_anisotropic_kernel_size(1.0, 2.0), + ) + }, + &|img| img.fast_blur(1.0), + &|img| img.unsharpen(1.0, 3), + &|img| img.filter3x3(&[0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0]), + &|img| img.adjust_contrast(0.5), + &|img| img.brighten(10), + &|img| img.huerotate(180), + ]; + + for (idx, &op) in IMAGEOPS.iter().enumerate() { + let result_a = op(&image); + let result_b = op(&clone); + assert_eq!(result_a.color_space(), image.color_space(), "{idx}"); + assert_eq!(result_b.color_space(), clone.color_space(), "{idx}"); + + assert_ne!(result_a, result_b, "{idx}"); + assert_eq!(result_a.as_bytes(), result_b.as_bytes(), "{idx}"); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/flat.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/flat.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/flat.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/flat.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1716 @@ +//! Image representations for ffi. +//! +//! # Usage +//! +//! Imagine you want to offer a very simple ffi interface: The caller provides an image buffer and +//! your program creates a thumbnail from it and dumps that image as `png`. This module is designed +//! to help you transition from raw memory data to Rust representation. +//! +//! ```no_run +//! use std::ptr; +//! use std::slice; +//! use image::Rgb; +//! use image::flat::{FlatSamples, SampleLayout}; +//! use image::imageops::thumbnail; +//! +//! #[no_mangle] +//! pub extern "C" fn store_rgb8_compressed( +//! data: *const u8, len: usize, +//! layout: *const SampleLayout +//! ) +//! -> bool +//! { +//! let samples = unsafe { slice::from_raw_parts(data, len) }; +//! let layout = unsafe { ptr::read(layout) }; +//! +//! let buffer = FlatSamples { +//! samples, +//! layout, +//! color_hint: None, +//! }; +//! +//! let view = match buffer.as_view::>() { +//! Err(_) => return false, // Invalid layout. +//! Ok(view) => view, +//! }; +//! +//! thumbnail(&view, 64, 64) +//! .save("output.png") +//! .map(|_| true) +//! .unwrap_or_else(|_| false) +//! } +//! ``` +//! +use std::marker::PhantomData; +use std::ops::{Deref, Index, IndexMut}; +use std::{cmp, error, fmt}; + +use num_traits::Zero; + +use crate::color::ColorType; +use crate::error::{ + DecodingError, ImageError, ImageFormatHint, ParameterError, ParameterErrorKind, + UnsupportedError, UnsupportedErrorKind, +}; +use crate::traits::Pixel; +use crate::{GenericImage, GenericImageView, ImageBuffer}; + +/// A flat buffer over a (multi channel) image. +/// +/// In contrast to `ImageBuffer`, this representation of a sample collection is much more lenient +/// in the layout thereof. It also allows grouping by color planes instead of by pixel as long as +/// the strides of each extent are constant. This struct itself has no invariants on the strides +/// but not every possible configuration can be interpreted as a [`GenericImageView`] or +/// [`GenericImage`]. The methods [`as_view`] and [`as_view_mut`] construct the actual implementors +/// of these traits and perform necessary checks. To manually perform this and other layout checks +/// use [`is_normal`] or [`has_aliased_samples`]. +/// +/// Instances can be constructed not only by hand. The buffer instances returned by library +/// functions such as [`ImageBuffer::as_flat_samples`] guarantee that the conversion to a generic +/// image or generic view succeeds. A very different constructor is [`with_monocolor`]. It uses a +/// single pixel as the backing storage for an arbitrarily sized read-only raster by mapping each +/// pixel to the same samples by setting some strides to `0`. +/// +/// [`GenericImage`]: ../trait.GenericImage.html +/// [`GenericImageView`]: ../trait.GenericImageView.html +/// [`ImageBuffer::as_flat_samples`]: ../struct.ImageBuffer.html#method.as_flat_samples +/// [`is_normal`]: #method.is_normal +/// [`has_aliased_samples`]: #method.has_aliased_samples +/// [`as_view`]: #method.as_view +/// [`as_view_mut`]: #method.as_view_mut +/// [`with_monocolor`]: #method.with_monocolor +#[derive(Clone, Debug)] +pub struct FlatSamples { + /// Underlying linear container holding sample values. + pub samples: Buffer, + + /// A `repr(C)` description of the layout of buffer samples. + pub layout: SampleLayout, + + /// Supplementary color information. + /// + /// You may keep this as `None` in most cases. This is NOT checked in `View` or other + /// converters. It is intended mainly as a way for types that convert to this buffer type to + /// attach their otherwise static color information. A dynamic image representation could + /// however use this to resolve representational ambiguities such as the order of RGB channels. + pub color_hint: Option, +} + +/// A ffi compatible description of a sample buffer. +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct SampleLayout { + /// The number of channels in the color representation of the image. + pub channels: u8, + + /// Add this to an index to get to the sample in the next channel. + pub channel_stride: usize, + + /// The width of the represented image. + pub width: u32, + + /// Add this to an index to get to the next sample in x-direction. + pub width_stride: usize, + + /// The height of the represented image. + pub height: u32, + + /// Add this to an index to get to the next sample in y-direction. + pub height_stride: usize, +} + +/// Helper struct for an unnamed (stride, length) pair. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Dim(usize, usize); + +impl SampleLayout { + /// Describe a row-major image packed in all directions. + /// + /// The resulting will surely be `NormalForm::RowMajorPacked`. It can therefore be converted to + /// safely to an `ImageBuffer` with a large enough underlying buffer. + /// + /// ``` + /// # use image::flat::{NormalForm, SampleLayout}; + /// let layout = SampleLayout::row_major_packed(3, 640, 480); + /// assert!(layout.is_normal(NormalForm::RowMajorPacked)); + /// ``` + /// + /// # Panics + /// + /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride + /// in the `height` direction would be larger than `usize::MAX`. On other platforms + /// where it can surely accommodate `u8::MAX * u32::MAX`, this can never happen. + #[must_use] + pub fn row_major_packed(channels: u8, width: u32, height: u32) -> Self { + let height_stride = (channels as usize).checked_mul(width as usize).expect( + "Row major packed image can not be described because it does not fit into memory", + ); + SampleLayout { + channels, + channel_stride: 1, + width, + width_stride: channels as usize, + height, + height_stride, + } + } + + /// Describe a column-major image packed in all directions. + /// + /// The resulting will surely be `NormalForm::ColumnMajorPacked`. This is not particularly + /// useful for conversion but can be used to describe such a buffer without pitfalls. + /// + /// ``` + /// # use image::flat::{NormalForm, SampleLayout}; + /// let layout = SampleLayout::column_major_packed(3, 640, 480); + /// assert!(layout.is_normal(NormalForm::ColumnMajorPacked)); + /// ``` + /// + /// # Panics + /// + /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride + /// in the `width` direction would be larger than `usize::MAX`. On other platforms + /// where it can surely accommodate `u8::MAX * u32::MAX`, this can never happen. + #[must_use] + pub fn column_major_packed(channels: u8, width: u32, height: u32) -> Self { + let width_stride = (channels as usize).checked_mul(height as usize).expect( + "Column major packed image can not be described because it does not fit into memory", + ); + SampleLayout { + channels, + channel_stride: 1, + height, + height_stride: channels as usize, + width, + width_stride, + } + } + + /// Get the strides for indexing matrix-like `[(c, w, h)]`. + /// + /// For a row-major layout with grouped samples, this tuple is strictly + /// increasing. + #[must_use] + pub fn strides_cwh(&self) -> (usize, usize, usize) { + (self.channel_stride, self.width_stride, self.height_stride) + } + + /// Get the dimensions `(channels, width, height)`. + /// + /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be + /// before width and height. + #[must_use] + pub fn extents(&self) -> (usize, usize, usize) { + ( + self.channels as usize, + self.width as usize, + self.height as usize, + ) + } + + /// Tuple of bounds in the order of coordinate inputs. + /// + /// This function should be used whenever working with image coordinates opposed to buffer + /// coordinates. The only difference compared to `extents` is the output type. + #[must_use] + pub fn bounds(&self) -> (u8, u32, u32) { + (self.channels, self.width, self.height) + } + + /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. + /// + /// This method will allow zero strides, allowing compact representations of monochrome images. + /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no + /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the + /// other cases, the reasoning is slightly more involved. + /// + /// # Explanation + /// + /// Note that there is a difference between `min_length` and the index of the sample + /// 'one-past-the-end'. This is due to strides that may be larger than the dimension below. + /// + /// ## Example with holes + /// + /// Let's look at an example of a grayscale image with + /// * `width_stride = 1` + /// * `width = 2` + /// * `height_stride = 3` + /// * `height = 2` + /// + /// ```text + /// | x x | x x m | $ + /// min_length m ^ + /// ^ one-past-the-end $ + /// ``` + /// + /// The difference is also extreme for empty images with large strides. The one-past-the-end + /// sample index is still as large as the largest of these strides while `min_length = 0`. + /// + /// ## Example with aliasing + /// + /// The concept gets even more important when you allow samples to alias each other. Here we + /// have the buffer of a small grayscale image where this is the case, this time we will first + /// show the buffer and then the individual rows below. + /// + /// * `width_stride = 1` + /// * `width = 3` + /// * `height_stride = 2` + /// * `height = 2` + /// + /// ```text + /// 1 2 3 4 5 m + /// |1 2 3| row one + /// |3 4 5| row two + /// ^ m min_length + /// ^ ??? one-past-the-end + /// ``` + /// + /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its + /// dimension. That still points inside the image because `height*height_stride = 4` but also + /// `index_of(1, 2) = 4`. + #[must_use] + pub fn min_length(&self) -> Option { + if self.width == 0 || self.height == 0 || self.channels == 0 { + return Some(0); + } + + self.index(self.channels - 1, self.width - 1, self.height - 1) + .and_then(|idx| idx.checked_add(1)) + } + + /// Check if a buffer of length `len` is large enough. + #[must_use] + pub fn fits(&self, len: usize) -> bool { + self.min_length().is_some_and(|min| len >= min) + } + + /// The extents of this array, in order of increasing strides. + fn increasing_stride_dims(&self) -> [Dim; 3] { + // Order extents by strides, then check that each is less equal than the next stride. + let mut grouped: [Dim; 3] = [ + Dim(self.channel_stride, self.channels as usize), + Dim(self.width_stride, self.width as usize), + Dim(self.height_stride, self.height as usize), + ]; + + grouped.sort(); + + let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); + assert!(min_dim.stride() <= mid_dim.stride() && mid_dim.stride() <= max_dim.stride()); + + grouped + } + + /// If there are any samples aliasing each other. + /// + /// If this is not the case, it would always be safe to allow mutable access to two different + /// samples at the same time. Otherwise, this operation would need additional checks. When one + /// dimension overflows `usize` with its stride we also consider this aliasing. + #[must_use] + pub fn has_aliased_samples(&self) -> bool { + let grouped = self.increasing_stride_dims(); + let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); + + let min_size = match min_dim.checked_len() { + None => return true, + Some(size) => size, + }; + + let mid_size = match mid_dim.checked_len() { + None => return true, + Some(size) => size, + }; + + if max_dim.checked_len().is_none() { + return true; + } + + // Each higher dimension must walk over all of one lower dimension. + min_size > mid_dim.stride() || mid_size > max_dim.stride() + } + + /// Check if a buffer fulfills the requirements of a normal form. + /// + /// Certain conversions have preconditions on the structure of the sample buffer that are not + /// captured (by design) by the type system. These are then checked before the conversion. Such + /// checks can all be done in constant time and will not inspect the buffer content. You can + /// perform these checks yourself when the conversion is not required at this moment but maybe + /// still performed later. + #[must_use] + pub fn is_normal(&self, form: NormalForm) -> bool { + if self.has_aliased_samples() { + return false; + } + + if form >= NormalForm::PixelPacked && self.channel_stride != 1 { + return false; + } + + if form >= NormalForm::ImagePacked { + // has aliased already checked for overflows. + let grouped = self.increasing_stride_dims(); + let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]); + + if 1 != min_dim.stride() { + return false; + } + + if min_dim.len() != mid_dim.stride() { + return false; + } + + if mid_dim.len() != max_dim.stride() { + return false; + } + } + + if form >= NormalForm::RowMajorPacked { + if self.width_stride != self.channels as usize { + return false; + } + + if self.width as usize * self.width_stride != self.height_stride { + return false; + } + } + + if form >= NormalForm::ColumnMajorPacked { + if self.height_stride != self.channels as usize { + return false; + } + + if self.height as usize * self.height_stride != self.width_stride { + return false; + } + } + + true + } + + /// Check that the pixel and the channel index are in bounds. + /// + /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a + /// buffer index does not overflow. However, if such a buffer large enough to hold all samples + /// actually exists in memory, this property of course follows. + #[must_use] + pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool { + channel < self.channels && x < self.width && y < self.height + } + + /// Resolve the index of a particular sample. + /// + /// `None` if the index is outside the bounds or does not fit into a `usize`. + #[must_use] + pub fn index(&self, channel: u8, x: u32, y: u32) -> Option { + if !self.in_bounds(channel, x, y) { + return None; + } + + self.index_ignoring_bounds(channel as usize, x as usize, y as usize) + } + + /// Get the theoretical position of sample (channel, x, y). + /// + /// The 'check' is for overflow during index calculation, not that it is contained in the + /// image. Two samples may return the same index, even when one of them is out of bounds. This + /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image. + #[must_use] + pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option { + let idx_c = channel.checked_mul(self.channel_stride); + let idx_x = x.checked_mul(self.width_stride); + let idx_y = y.checked_mul(self.height_stride); + + let (Some(idx_c), Some(idx_x), Some(idx_y)) = (idx_c, idx_x, idx_y) else { + return None; + }; + + Some(0usize) + .and_then(|b| b.checked_add(idx_c)) + .and_then(|b| b.checked_add(idx_x)) + .and_then(|b| b.checked_add(idx_y)) + } + + /// Get an index provided it is inbouds. + /// + /// Assumes that the image is backed by some sufficiently large buffer. Then computation can + /// not overflow as we could represent the maximum coordinate. Since overflow is defined either + /// way, this method can not be unsafe. + /// + /// Behavior is *unspecified* if the index is out of bounds or this sample layout would require + /// a buffer larger than `isize::MAX` bytes. + #[must_use] + pub fn in_bounds_index(&self, c: u8, x: u32, y: u32) -> usize { + let (c_stride, x_stride, y_stride) = self.strides_cwh(); + (y as usize * y_stride) + (x as usize * x_stride) + (c as usize * c_stride) + } + + /// Shrink the image to the minimum of current and given extents. + /// + /// This does not modify the strides, so that the resulting sample buffer may have holes + /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when + /// samples had aliased each other before. + pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) { + self.channels = self.channels.min(channels); + self.width = self.width.min(width); + self.height = self.height.min(height); + } +} + +impl Dim { + fn stride(self) -> usize { + self.0 + } + + /// Length of this dimension in memory. + fn checked_len(self) -> Option { + self.0.checked_mul(self.1) + } + + fn len(self) -> usize { + self.0 * self.1 + } +} + +impl FlatSamples { + /// Get the strides for indexing matrix-like `[(c, w, h)]`. + /// + /// For a row-major layout with grouped samples, this tuple is strictly + /// increasing. + pub fn strides_cwh(&self) -> (usize, usize, usize) { + self.layout.strides_cwh() + } + + /// Get the dimensions `(channels, width, height)`. + /// + /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be + /// before width and height. + pub fn extents(&self) -> (usize, usize, usize) { + self.layout.extents() + } + + /// Tuple of bounds in the order of coordinate inputs. + /// + /// This function should be used whenever working with image coordinates opposed to buffer + /// coordinates. The only difference compared to `extents` is the output type. + pub fn bounds(&self) -> (u8, u32, u32) { + self.layout.bounds() + } + + /// Get a reference based version. + pub fn as_ref(&self) -> FlatSamples<&[T]> + where + Buffer: AsRef<[T]>, + { + FlatSamples { + samples: self.samples.as_ref(), + layout: self.layout, + color_hint: self.color_hint, + } + } + + /// Get a mutable reference based version. + pub fn as_mut(&mut self) -> FlatSamples<&mut [T]> + where + Buffer: AsMut<[T]>, + { + FlatSamples { + samples: self.samples.as_mut(), + layout: self.layout, + color_hint: self.color_hint, + } + } + + /// Copy the data into an owned vector. + pub fn to_vec(&self) -> FlatSamples> + where + T: Clone, + Buffer: AsRef<[T]>, + { + FlatSamples { + samples: self.samples.as_ref().to_vec(), + layout: self.layout, + color_hint: self.color_hint, + } + } + + /// Get a reference to a single sample. + /// + /// This more restrictive than the method based on `std::ops::Index` but guarantees to properly + /// check all bounds and not panic as long as `Buffer::as_ref` does not do so. + /// + /// ``` + /// # use image::{RgbImage}; + /// let flat = RgbImage::new(480, 640).into_flat_samples(); + /// + /// // Get the blue channel at (10, 10). + /// assert!(flat.get_sample(1, 10, 10).is_some()); + /// + /// // There is no alpha channel. + /// assert!(flat.get_sample(3, 10, 10).is_none()); + /// ``` + /// + /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating + /// bounds checks with `min_length` in a type similar to `View`. Then you may use + /// `in_bounds_index` as a small speedup over the index calculation of this method which relies + /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample + /// coordinate is in fact backed by any memory buffer. + pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&T> + where + Buffer: AsRef<[T]>, + { + self.index(channel, x, y) + .and_then(|idx| self.samples.as_ref().get(idx)) + } + + /// Get a mutable reference to a single sample. + /// + /// This more restrictive than the method based on `std::ops::IndexMut` but guarantees to + /// properly check all bounds and not panic as long as `Buffer::as_ref` does not do so. + /// Contrary to conversion to `ViewMut`, this does not require that samples are packed since it + /// does not need to convert samples to a color representation. + /// + /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned + /// here can in fact modify more than the coordinate in the argument. + /// + /// ``` + /// # use image::{RgbImage}; + /// let mut flat = RgbImage::new(480, 640).into_flat_samples(); + /// + /// // Assign some new color to the blue channel at (10, 10). + /// *flat.get_mut_sample(1, 10, 10).unwrap() = 255; + /// + /// // There is no alpha channel. + /// assert!(flat.get_mut_sample(3, 10, 10).is_none()); + /// ``` + /// + /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating + /// bounds checks with `min_length` in a type similar to `View`. Then you may use + /// `in_bounds_index` as a small speedup over the index calculation of this method which relies + /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample + /// coordinate is in fact backed by any memory buffer. + pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut T> + where + Buffer: AsMut<[T]>, + { + match self.index(channel, x, y) { + None => None, + Some(idx) => self.samples.as_mut().get_mut(idx), + } + } + + /// View this buffer as an image over some type of pixel. + /// + /// This first ensures that all in-bounds coordinates refer to valid indices in the sample + /// buffer. It also checks that the specified pixel format expects the same number of channels + /// that are present in this buffer. Neither are larger nor a smaller number will be accepted. + /// There is no automatic conversion. + pub fn as_view

(&self) -> Result, Error> + where + P: Pixel, + Buffer: AsRef<[P::Subpixel]>, + { + if self.layout.channels != P::CHANNEL_COUNT { + return Err(Error::ChannelCountMismatch( + self.layout.channels, + P::CHANNEL_COUNT, + )); + } + + let as_ref = self.samples.as_ref(); + if !self.layout.fits(as_ref.len()) { + return Err(Error::TooLarge); + } + + Ok(View { + inner: FlatSamples { + samples: as_ref, + layout: self.layout, + color_hint: self.color_hint, + }, + phantom: PhantomData, + }) + } + + /// View this buffer but keep mutability at a sample level. + /// + /// This is similar to `as_view` but subtly different from `as_view_mut`. The resulting type + /// can be used as a `GenericImage` with the same prior invariants needed as for `as_view`. + /// It can not be used as a mutable `GenericImage` but does not need channels to be packed in + /// their pixel representation. + /// + /// This first ensures that all in-bounds coordinates refer to valid indices in the sample + /// buffer. It also checks that the specified pixel format expects the same number of channels + /// that are present in this buffer. Neither are larger nor a smaller number will be accepted. + /// There is no automatic conversion. + /// + /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned + /// for one sample can in fact modify other samples as well. Sometimes exactly this is + /// intended. + pub fn as_view_with_mut_samples

(&mut self) -> Result, Error> + where + P: Pixel, + Buffer: AsMut<[P::Subpixel]>, + { + if self.layout.channels != P::CHANNEL_COUNT { + return Err(Error::ChannelCountMismatch( + self.layout.channels, + P::CHANNEL_COUNT, + )); + } + + let as_mut = self.samples.as_mut(); + if !self.layout.fits(as_mut.len()) { + return Err(Error::TooLarge); + } + + Ok(View { + inner: FlatSamples { + samples: as_mut, + layout: self.layout, + color_hint: self.color_hint, + }, + phantom: PhantomData, + }) + } + + /// Interpret this buffer as a mutable image. + /// + /// To succeed, the pixels in this buffer may not alias each other and the samples of each + /// pixel must be packed (i.e. `channel_stride` is `1`). The number of channels must be + /// consistent with the channel count expected by the pixel format. + /// + /// This is similar to an `ImageBuffer` except it is a temporary view that is not normalized as + /// strongly. To get an owning version, consider copying the data into an `ImageBuffer`. This + /// provides many more operations, is possibly faster (if not you may want to open an issue) is + /// generally polished. You can also try to convert this buffer inline, see + /// `ImageBuffer::from_raw`. + pub fn as_view_mut

(&mut self) -> Result, Error> + where + P: Pixel, + Buffer: AsMut<[P::Subpixel]>, + { + if !self.layout.is_normal(NormalForm::PixelPacked) { + return Err(Error::NormalFormRequired(NormalForm::PixelPacked)); + } + + if self.layout.channels != P::CHANNEL_COUNT { + return Err(Error::ChannelCountMismatch( + self.layout.channels, + P::CHANNEL_COUNT, + )); + } + + let as_mut = self.samples.as_mut(); + if !self.layout.fits(as_mut.len()) { + return Err(Error::TooLarge); + } + + Ok(ViewMut { + inner: FlatSamples { + samples: as_mut, + layout: self.layout, + color_hint: self.color_hint, + }, + phantom: PhantomData, + }) + } + + /// View the samples as a slice. + /// + /// The slice is not limited to the region of the image and not all sample indices are valid + /// indices into this buffer. See `image_mut_slice` as an alternative. + pub fn as_slice(&self) -> &[T] + where + Buffer: AsRef<[T]>, + { + self.samples.as_ref() + } + + /// View the samples as a slice. + /// + /// The slice is not limited to the region of the image and not all sample indices are valid + /// indices into this buffer. See `image_mut_slice` as an alternative. + pub fn as_mut_slice(&mut self) -> &mut [T] + where + Buffer: AsMut<[T]>, + { + self.samples.as_mut() + } + + /// Return the portion of the buffer that holds sample values. + /// + /// This may fail when the coordinates in this image are either out-of-bounds of the underlying + /// buffer or can not be represented. Note that the slice may have holes that do not correspond + /// to any sample in the image represented by it. + pub fn image_slice(&self) -> Option<&[T]> + where + Buffer: AsRef<[T]>, + { + let min_length = self.min_length()?; + + let slice = self.samples.as_ref(); + if slice.len() < min_length { + return None; + } + + Some(&slice[..min_length]) + } + + /// Mutable portion of the buffer that holds sample values. + pub fn image_mut_slice(&mut self) -> Option<&mut [T]> + where + Buffer: AsMut<[T]>, + { + let min_length = self.min_length()?; + + let slice = self.samples.as_mut(); + if slice.len() < min_length { + return None; + } + + Some(&mut slice[..min_length]) + } + + /// Move the data into an image buffer. + /// + /// This does **not** convert the sample layout. The buffer needs to be in packed row-major form + /// before calling this function. In case of an error, returns the buffer again so that it does + /// not release any allocation. + pub fn try_into_buffer

(self) -> Result, (Error, Self)> + where + P: Pixel + 'static, + P::Subpixel: 'static, + Buffer: Deref, + { + if !self.is_normal(NormalForm::RowMajorPacked) { + return Err((Error::NormalFormRequired(NormalForm::RowMajorPacked), self)); + } + + if self.layout.channels != P::CHANNEL_COUNT { + return Err(( + Error::ChannelCountMismatch(self.layout.channels, P::CHANNEL_COUNT), + self, + )); + } + + if !self.fits(self.samples.deref().len()) { + return Err((Error::TooLarge, self)); + } + + Ok( + ImageBuffer::from_raw(self.layout.width, self.layout.height, self.samples) + .unwrap_or_else(|| { + panic!("Preconditions should have been ensured before conversion") + }), + ) + } + + /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. + /// + /// This method will allow zero strides, allowing compact representations of monochrome images. + /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no + /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the + /// other cases, the reasoning is slightly more involved. + /// + /// # Explanation + /// + /// Note that there is a difference between `min_length` and the index of the sample + /// 'one-past-the-end'. This is due to strides that may be larger than the dimension below. + /// + /// ## Example with holes + /// + /// Let's look at an example of a grayscale image with + /// * `width_stride = 1` + /// * `width = 2` + /// * `height_stride = 3` + /// * `height = 2` + /// + /// ```text + /// | x x | x x m | $ + /// min_length m ^ + /// ^ one-past-the-end $ + /// ``` + /// + /// The difference is also extreme for empty images with large strides. The one-past-the-end + /// sample index is still as large as the largest of these strides while `min_length = 0`. + /// + /// ## Example with aliasing + /// + /// The concept gets even more important when you allow samples to alias each other. Here we + /// have the buffer of a small grayscale image where this is the case, this time we will first + /// show the buffer and then the individual rows below. + /// + /// * `width_stride = 1` + /// * `width = 3` + /// * `height_stride = 2` + /// * `height = 2` + /// + /// ```text + /// 1 2 3 4 5 m + /// |1 2 3| row one + /// |3 4 5| row two + /// ^ m min_length + /// ^ ??? one-past-the-end + /// ``` + /// + /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its + /// dimension. That still points inside the image because `height*height_stride = 4` but also + /// `index_of(1, 2) = 4`. + pub fn min_length(&self) -> Option { + self.layout.min_length() + } + + /// Check if a buffer of length `len` is large enough. + pub fn fits(&self, len: usize) -> bool { + self.layout.fits(len) + } + + /// If there are any samples aliasing each other. + /// + /// If this is not the case, it would always be safe to allow mutable access to two different + /// samples at the same time. Otherwise, this operation would need additional checks. When one + /// dimension overflows `usize` with its stride we also consider this aliasing. + pub fn has_aliased_samples(&self) -> bool { + self.layout.has_aliased_samples() + } + + /// Check if a buffer fulfills the requirements of a normal form. + /// + /// Certain conversions have preconditions on the structure of the sample buffer that are not + /// captured (by design) by the type system. These are then checked before the conversion. Such + /// checks can all be done in constant time and will not inspect the buffer content. You can + /// perform these checks yourself when the conversion is not required at this moment but maybe + /// still performed later. + pub fn is_normal(&self, form: NormalForm) -> bool { + self.layout.is_normal(form) + } + + /// Check that the pixel and the channel index are in bounds. + /// + /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a + /// buffer index does not overflow. However, if such a buffer large enough to hold all samples + /// actually exists in memory, this property of course follows. + pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool { + self.layout.in_bounds(channel, x, y) + } + + /// Resolve the index of a particular sample. + /// + /// `None` if the index is outside the bounds or does not fit into a `usize`. + pub fn index(&self, channel: u8, x: u32, y: u32) -> Option { + self.layout.index(channel, x, y) + } + + /// Get the theoretical position of sample (x, y, channel). + /// + /// The 'check' is for overflow during index calculation, not that it is contained in the + /// image. Two samples may return the same index, even when one of them is out of bounds. This + /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image. + pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option { + self.layout.index_ignoring_bounds(channel, x, y) + } + + /// Get an index provided it is inbouds. + /// + /// Assumes that the image is backed by some sufficiently large buffer. Then computation can + /// not overflow as we could represent the maximum coordinate. Since overflow is defined either + /// way, this method can not be unsafe. + pub fn in_bounds_index(&self, channel: u8, x: u32, y: u32) -> usize { + self.layout.in_bounds_index(channel, x, y) + } + + /// Shrink the image to the minimum of current and given extents. + /// + /// This does not modify the strides, so that the resulting sample buffer may have holes + /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when + /// samples had aliased each other before. + pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) { + self.layout.shrink_to(channels, width, height); + } +} + +impl<'buf, Subpixel> FlatSamples<&'buf [Subpixel]> { + /// Create a monocolor image from a single pixel. + /// + /// This can be used as a very cheap source of a `GenericImageView` with an arbitrary number of + /// pixels of a single color, without any dynamic allocation. + /// + /// ## Examples + /// + /// ``` + /// # fn paint_something(_: T) {} + /// use image::{flat::FlatSamples, GenericImage, RgbImage, Rgb}; + /// + /// let background = Rgb([20, 20, 20]); + /// let bg = FlatSamples::with_monocolor(&background, 200, 200); + /// + /// let mut image = RgbImage::new(200, 200); + /// paint_something(&mut image); + /// + /// // Reset the canvas + /// image.copy_from(&bg.as_view().unwrap(), 0, 0); + /// ``` + pub fn with_monocolor

(pixel: &'buf P, width: u32, height: u32) -> Self + where + P: Pixel, + Subpixel: crate::Primitive, + { + FlatSamples { + samples: pixel.channels(), + layout: SampleLayout { + channels: P::CHANNEL_COUNT, + channel_stride: 1, + width, + width_stride: 0, + height, + height_stride: 0, + }, + + // TODO this value is never set. It should be set in all places where the Pixel type implements PixelWithColorType + color_hint: None, + } + } +} + +/// A flat buffer that can be used as an image view. +/// +/// This is a nearly trivial wrapper around a buffer but at least sanitizes by checking the buffer +/// length first and constraining the pixel type. +/// +/// Note that this does not eliminate panics as the `AsRef<[T]>` implementation of `Buffer` may be +/// unreliable, i.e. return different buffers at different times. This of course is a non-issue for +/// all common collections where the bounds check once must be enough. +/// +/// # Inner invariants +/// +/// * For all indices inside bounds, the corresponding index is valid in the buffer +/// * `P::channel_count()` agrees with `self.inner.layout.channels` +#[derive(Clone, Debug)] +pub struct View +where + Buffer: AsRef<[P::Subpixel]>, +{ + inner: FlatSamples, + phantom: PhantomData

, +} + +/// A mutable owning version of a flat buffer. +/// +/// While this wraps a buffer similar to `ImageBuffer`, this is mostly intended as a utility. The +/// library endorsed normalized representation is still `ImageBuffer`. Also, the implementation of +/// `AsMut<[P::Subpixel]>` must always yield the same buffer. Therefore there is no public way to +/// construct this with an owning buffer. +/// +/// # Inner invariants +/// +/// * For all indices inside bounds, the corresponding index is valid in the buffer +/// * There is no aliasing of samples +/// * The samples are packed, i.e. `self.inner.layout.sample_stride == 1` +/// * `P::channel_count()` agrees with `self.inner.layout.channels` +#[derive(Clone, Debug)] +pub struct ViewMut +where + Buffer: AsMut<[P::Subpixel]>, +{ + inner: FlatSamples, + phantom: PhantomData

, +} + +/// Denotes invalid flat sample buffers when trying to convert to stricter types. +/// +/// The biggest use case being `ImageBuffer` which expects closely packed +/// samples in a row major matrix representation. But this error type may be +/// reused for other import functions. A more versatile user may also try to +/// correct the underlying representation depending on the error variant. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum Error { + /// The represented image was too large. + /// + /// The optional value denotes a possibly accepted maximal bound. + TooLarge, + + /// The represented image can not use this representation. + /// + /// Has an additional value of the normalized form that would be accepted. + NormalFormRequired(NormalForm), + + /// The color format did not match the channel count. + /// + /// In some cases you might be able to fix this by lowering the reported pixel count of the + /// buffer without touching the strides. + /// + /// In very special circumstances you *may* do the opposite. This is **VERY** dangerous but not + /// directly memory unsafe although that will likely alias pixels. One scenario is when you + /// want to construct an `Rgba` image but have only 3 bytes per pixel and for some reason don't + /// care about the value of the alpha channel even though you need `Rgba`. + ChannelCountMismatch(u8, u8), + + /// Deprecated - `ChannelCountMismatch` is used instead + WrongColor(ColorType), +} + +/// Different normal forms of buffers. +/// +/// A normal form is an unaliased buffer with some additional constraints. The `ÌmageBuffer` uses +/// row major form with packed samples. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum NormalForm { + /// No pixel aliases another. + /// + /// Unaliased also guarantees that all index calculations in the image bounds using + /// `dim_index*dim_stride` (such as `x*width_stride + y*height_stride`) do not overflow. + Unaliased, + + /// At least pixels are packed. + /// + /// Images of these types can wrap `[T]`-slices into the standard color types. This is a + /// precondition for `GenericImage` which requires by-reference access to pixels. + PixelPacked, + + /// All samples are packed. + /// + /// This is orthogonal to `PixelPacked`. It requires that there are no holes in the image but + /// it is not necessary that the pixel samples themselves are adjacent. An example of this + /// behaviour is a planar image layout. + ImagePacked, + + /// The samples are in row-major form and all samples are packed. + /// + /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is + /// in row-major form. + RowMajorPacked, + + /// The samples are in column-major form and all samples are packed. + /// + /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is + /// in column-major form. + ColumnMajorPacked, +} + +impl View +where + Buffer: AsRef<[P::Subpixel]>, +{ + /// Take out the sample buffer. + /// + /// Gives up the normalization invariants on the buffer format. + pub fn into_inner(self) -> FlatSamples { + self.inner + } + + /// Get a reference on the inner sample descriptor. + /// + /// There is no mutable counterpart as modifying the buffer format, including strides and + /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified + /// if the inner buffer is the same as the buffer of the image from which this view was + /// created. It might have been truncated as an optimization. + pub fn flat(&self) -> &FlatSamples { + &self.inner + } + + /// Get a reference on the inner buffer. + /// + /// There is no mutable counter part since it is not intended to allow you to reassign the + /// buffer or otherwise change its size or properties. + pub fn samples(&self) -> &Buffer { + &self.inner.samples + } + + /// Get a reference to a selected subpixel if it is in-bounds. + /// + /// This method will return `None` when the sample is out-of-bounds. All errors that could + /// occur due to overflow have been eliminated while construction the `View`. + pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel> { + if !self.inner.in_bounds(channel, x, y) { + return None; + } + + let index = self.inner.in_bounds_index(channel, x, y); + // Should always be `Some(_)` but checking is more costly. + self.samples().as_ref().get(index) + } + + /// Get a mutable reference to a selected subpixel if it is in-bounds. + /// + /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`. This + /// method will return `None` when the sample is out-of-bounds. All errors that could occur due + /// to overflow have been eliminated while construction the `View`. + /// + /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned + /// here can in fact modify more than the coordinate in the argument. + pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel> + where + Buffer: AsMut<[P::Subpixel]>, + { + if !self.inner.in_bounds(channel, x, y) { + return None; + } + + let index = self.inner.in_bounds_index(channel, x, y); + // Should always be `Some(_)` but checking is more costly. + self.inner.samples.as_mut().get_mut(index) + } + + /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. + /// + /// See `FlatSamples::min_length`. This method will always succeed. + pub fn min_length(&self) -> usize { + self.inner.min_length().unwrap() + } + + /// Return the portion of the buffer that holds sample values. + /// + /// While this can not fail–the validity of all coordinates has been validated during the + /// conversion from `FlatSamples`–the resulting slice may still contain holes. + pub fn image_slice(&self) -> &[P::Subpixel] { + &self.samples().as_ref()[..self.min_length()] + } + + /// Return the mutable portion of the buffer that holds sample values. + /// + /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`. While + /// this can not fail–the validity of all coordinates has been validated during the conversion + /// from `FlatSamples`–the resulting slice may still contain holes. + pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel] + where + Buffer: AsMut<[P::Subpixel]>, + { + let min_length = self.min_length(); + &mut self.inner.samples.as_mut()[..min_length] + } + + /// Shrink the inner image. + /// + /// The new dimensions will be the minimum of the previous dimensions. Since the set of + /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`. + /// Note that you can not change the number of channels as an intrinsic property of `P`. + pub fn shrink_to(&mut self, width: u32, height: u32) { + let channels = self.inner.layout.channels; + self.inner.shrink_to(channels, width, height); + } + + /// Try to convert this into an image with mutable pixels. + /// + /// The resulting image implements `GenericImage` in addition to `GenericImageView`. While this + /// has mutable samples, it does not enforce that pixel can not alias and that samples are + /// packed enough for a mutable pixel reference. This is slightly cheaper than the chain + /// `self.into_inner().as_view_mut()` and keeps the `View` alive on failure. + /// + /// ``` + /// # use image::RgbImage; + /// # use image::Rgb; + /// let mut buffer = RgbImage::new(480, 640).into_flat_samples(); + /// let view = buffer.as_view_with_mut_samples::>().unwrap(); + /// + /// // Inspect some pixels, … + /// + /// // Doesn't fail because it was originally an `RgbImage`. + /// let view_mut = view.try_upgrade().unwrap(); + /// ``` + pub fn try_upgrade(self) -> Result, (Error, Self)> + where + Buffer: AsMut<[P::Subpixel]>, + { + if !self.inner.is_normal(NormalForm::PixelPacked) { + return Err((Error::NormalFormRequired(NormalForm::PixelPacked), self)); + } + + // No length check or channel count check required, all the same. + Ok(ViewMut { + inner: self.inner, + phantom: PhantomData, + }) + } +} + +impl ViewMut +where + Buffer: AsMut<[P::Subpixel]>, +{ + /// Take out the sample buffer. + /// + /// Gives up the normalization invariants on the buffer format. + pub fn into_inner(self) -> FlatSamples { + self.inner + } + + /// Get a reference on the sample buffer descriptor. + /// + /// There is no mutable counterpart as modifying the buffer format, including strides and + /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified + /// if the inner buffer is the same as the buffer of the image from which this view was + /// created. It might have been truncated as an optimization. + pub fn flat(&self) -> &FlatSamples { + &self.inner + } + + /// Get a reference on the inner buffer. + /// + /// There is no mutable counter part since it is not intended to allow you to reassign the + /// buffer or otherwise change its size or properties. However, its contents can be accessed + /// mutable through a slice with `image_mut_slice`. + pub fn samples(&self) -> &Buffer { + &self.inner.samples + } + + /// Get the minimum length of a buffer such that all in-bounds samples have valid indices. + /// + /// See `FlatSamples::min_length`. This method will always succeed. + pub fn min_length(&self) -> usize { + self.inner.min_length().unwrap() + } + + /// Get a reference to a selected subpixel. + /// + /// This method will return `None` when the sample is out-of-bounds. All errors that could + /// occur due to overflow have been eliminated while construction the `View`. + pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel> + where + Buffer: AsRef<[P::Subpixel]>, + { + if !self.inner.in_bounds(channel, x, y) { + return None; + } + + let index = self.inner.in_bounds_index(channel, x, y); + // Should always be `Some(_)` but checking is more costly. + self.samples().as_ref().get(index) + } + + /// Get a mutable reference to a selected sample. + /// + /// This method will return `None` when the sample is out-of-bounds. All errors that could + /// occur due to overflow have been eliminated while construction the `View`. + pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel> { + if !self.inner.in_bounds(channel, x, y) { + return None; + } + + let index = self.inner.in_bounds_index(channel, x, y); + // Should always be `Some(_)` but checking is more costly. + self.inner.samples.as_mut().get_mut(index) + } + + /// Return the portion of the buffer that holds sample values. + /// + /// While this can not fail–the validity of all coordinates has been validated during the + /// conversion from `FlatSamples`–the resulting slice may still contain holes. + pub fn image_slice(&self) -> &[P::Subpixel] + where + Buffer: AsRef<[P::Subpixel]>, + { + &self.inner.samples.as_ref()[..self.min_length()] + } + + /// Return the mutable buffer that holds sample values. + pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel] { + let length = self.min_length(); + &mut self.inner.samples.as_mut()[..length] + } + + /// Shrink the inner image. + /// + /// The new dimensions will be the minimum of the previous dimensions. Since the set of + /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`. + /// Note that you can not change the number of channels as an intrinsic property of `P`. + pub fn shrink_to(&mut self, width: u32, height: u32) { + let channels = self.inner.layout.channels; + self.inner.shrink_to(channels, width, height); + } +} + +// The out-of-bounds panic for single sample access similar to `slice::index`. +#[inline(never)] +#[cold] +fn panic_cwh_out_of_bounds( + (c, x, y): (u8, u32, u32), + bounds: (u8, u32, u32), + strides: (usize, usize, usize), +) -> ! { + panic!( + "Sample coordinates {:?} out of sample matrix bounds {:?} with strides {:?}", + (c, x, y), + bounds, + strides + ) +} + +// The out-of-bounds panic for pixel access similar to `slice::index`. +#[inline(never)] +#[cold] +fn panic_pixel_out_of_bounds((x, y): (u32, u32), bounds: (u32, u32)) -> ! { + panic!("Image index {:?} out of bounds {:?}", (x, y), bounds) +} + +impl Index<(u8, u32, u32)> for FlatSamples +where + Buffer: Index, +{ + type Output = Buffer::Output; + + /// Return a reference to a single sample at specified coordinates. + /// + /// # Panics + /// + /// When the coordinates are out of bounds or the index calculation fails. + fn index(&self, (c, x, y): (u8, u32, u32)) -> &Self::Output { + let bounds = self.bounds(); + let strides = self.strides_cwh(); + let index = self + .index(c, x, y) + .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides)); + &self.samples[index] + } +} + +impl IndexMut<(u8, u32, u32)> for FlatSamples +where + Buffer: IndexMut, +{ + /// Return a mutable reference to a single sample at specified coordinates. + /// + /// # Panics + /// + /// When the coordinates are out of bounds or the index calculation fails. + fn index_mut(&mut self, (c, x, y): (u8, u32, u32)) -> &mut Self::Output { + let bounds = self.bounds(); + let strides = self.strides_cwh(); + let index = self + .index(c, x, y) + .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides)); + &mut self.samples[index] + } +} + +impl GenericImageView for View +where + Buffer: AsRef<[P::Subpixel]>, +{ + type Pixel = P; + + fn dimensions(&self) -> (u32, u32) { + (self.inner.layout.width, self.inner.layout.height) + } + + fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { + if !self.inner.in_bounds(0, x, y) { + panic_pixel_out_of_bounds((x, y), self.dimensions()) + } + + let image = self.inner.samples.as_ref(); + let base_index = self.inner.in_bounds_index(0, x, y); + let channels = P::CHANNEL_COUNT as usize; + + let mut buffer = [Zero::zero(); 256]; + buffer + .iter_mut() + .enumerate() + .take(channels) + .for_each(|(c, to)| { + let index = base_index + c * self.inner.layout.channel_stride; + *to = image[index]; + }); + + *P::from_slice(&buffer[..channels]) + } +} + +impl GenericImageView for ViewMut +where + Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>, +{ + type Pixel = P; + + fn dimensions(&self) -> (u32, u32) { + (self.inner.layout.width, self.inner.layout.height) + } + + fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { + if !self.inner.in_bounds(0, x, y) { + panic_pixel_out_of_bounds((x, y), self.dimensions()) + } + + let image = self.inner.samples.as_ref(); + let base_index = self.inner.in_bounds_index(0, x, y); + let channels = P::CHANNEL_COUNT as usize; + + let mut buffer = [Zero::zero(); 256]; + buffer + .iter_mut() + .enumerate() + .take(channels) + .for_each(|(c, to)| { + let index = base_index + c * self.inner.layout.channel_stride; + *to = image[index]; + }); + + *P::from_slice(&buffer[..channels]) + } +} + +impl GenericImage for ViewMut +where + Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>, +{ + fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel { + if !self.inner.in_bounds(0, x, y) { + panic_pixel_out_of_bounds((x, y), self.dimensions()) + } + + let base_index = self.inner.in_bounds_index(0, x, y); + let channel_count =

::CHANNEL_COUNT as usize; + let pixel_range = base_index..base_index + channel_count; + P::from_slice_mut(&mut self.inner.samples.as_mut()[pixel_range]) + } + + #[allow(deprecated)] + fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { + *self.get_pixel_mut(x, y) = pixel; + } + + #[allow(deprecated)] + fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { + self.get_pixel_mut(x, y).blend(&pixel); + } +} + +impl From for ImageError { + fn from(error: Error) -> ImageError { + #[derive(Debug)] + struct NormalFormRequiredError(NormalForm); + impl fmt::Display for NormalFormRequiredError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Required sample buffer in normal form {:?}", self.0) + } + } + impl error::Error for NormalFormRequiredError {} + + match error { + Error::TooLarge => ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + )), + Error::NormalFormRequired(form) => ImageError::Decoding(DecodingError::new( + ImageFormatHint::Unknown, + NormalFormRequiredError(form), + )), + Error::ChannelCountMismatch(_lc, _pc) => ImageError::Parameter( + ParameterError::from_kind(ParameterErrorKind::DimensionMismatch), + ), + Error::WrongColor(color) => { + ImageError::Unsupported(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::Color(color.into()), + )) + } + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::TooLarge => write!(f, "The layout is too large"), + Error::NormalFormRequired(form) => write!( + f, + "The layout needs to {}", + match form { + NormalForm::ColumnMajorPacked => "be packed and in column major form", + NormalForm::ImagePacked => "be fully packed", + NormalForm::PixelPacked => "have packed pixels", + NormalForm::RowMajorPacked => "be packed and in row major form", + NormalForm::Unaliased => "not have any aliasing channels", + } + ), + Error::ChannelCountMismatch(layout_channels, pixel_channels) => { + write!(f, "The channel count of the chosen pixel (={pixel_channels}) does agree with the layout (={layout_channels})") + } + Error::WrongColor(color) => { + write!(f, "The chosen color type does not match the hint {color:?}") + } + } + } +} + +impl error::Error for Error {} + +impl PartialOrd for NormalForm { + /// Compares the logical preconditions. + /// + /// `a < b` if the normal form `a` has less preconditions than `b`. + fn partial_cmp(&self, other: &Self) -> Option { + match (*self, *other) { + (NormalForm::Unaliased, NormalForm::Unaliased) => Some(cmp::Ordering::Equal), + (NormalForm::PixelPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Equal), + (NormalForm::ImagePacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Equal), + (NormalForm::RowMajorPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Equal), + (NormalForm::ColumnMajorPacked, NormalForm::ColumnMajorPacked) => { + Some(cmp::Ordering::Equal) + } + + (NormalForm::Unaliased, _) => Some(cmp::Ordering::Less), + (_, NormalForm::Unaliased) => Some(cmp::Ordering::Greater), + + (NormalForm::PixelPacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less), + (NormalForm::PixelPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less), + (NormalForm::RowMajorPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Greater), + (NormalForm::ColumnMajorPacked, NormalForm::PixelPacked) => { + Some(cmp::Ordering::Greater) + } + + (NormalForm::ImagePacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less), + (NormalForm::ImagePacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less), + (NormalForm::RowMajorPacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Greater), + (NormalForm::ColumnMajorPacked, NormalForm::ImagePacked) => { + Some(cmp::Ordering::Greater) + } + + (NormalForm::ImagePacked, NormalForm::PixelPacked) => None, + (NormalForm::PixelPacked, NormalForm::ImagePacked) => None, + (NormalForm::RowMajorPacked, NormalForm::ColumnMajorPacked) => None, + (NormalForm::ColumnMajorPacked, NormalForm::RowMajorPacked) => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::color::{LumaA, Rgb}; + use crate::images::buffer::GrayAlphaImage; + + #[test] + fn aliasing_view() { + let buffer = FlatSamples { + samples: &[42], + layout: SampleLayout { + channels: 3, + channel_stride: 0, + width: 100, + width_stride: 0, + height: 100, + height_stride: 0, + }, + color_hint: None, + }; + + let view = buffer.as_view::>().expect("This is a valid view"); + let pixel_count = view + .pixels() + .inspect(|pixel| assert!(pixel.2 == Rgb([42, 42, 42]))) + .count(); + assert_eq!(pixel_count, 100 * 100); + } + + #[test] + fn mutable_view() { + let mut buffer = FlatSamples { + samples: [0; 18], + layout: SampleLayout { + channels: 2, + channel_stride: 1, + width: 3, + width_stride: 2, + height: 3, + height_stride: 6, + }, + color_hint: None, + }; + + { + let mut view = buffer + .as_view_mut::>() + .expect("This should be a valid mutable buffer"); + assert_eq!(view.dimensions(), (3, 3)); + #[allow(deprecated)] + for i in 0..9 { + *view.get_pixel_mut(i % 3, i / 3) = LumaA([2 * i as u16, 2 * i as u16 + 1]); + } + } + + buffer + .samples + .iter() + .enumerate() + .for_each(|(idx, sample)| assert_eq!(idx, *sample as usize)); + } + + #[test] + fn normal_forms() { + assert!(FlatSamples { + samples: [0u8; 0], + layout: SampleLayout { + channels: 2, + channel_stride: 1, + width: 3, + width_stride: 9, + height: 3, + height_stride: 28, + }, + color_hint: None, + } + .is_normal(NormalForm::PixelPacked)); + + assert!(FlatSamples { + samples: [0u8; 0], + layout: SampleLayout { + channels: 2, + channel_stride: 8, + width: 4, + width_stride: 1, + height: 2, + height_stride: 4, + }, + color_hint: None, + } + .is_normal(NormalForm::ImagePacked)); + + assert!(FlatSamples { + samples: [0u8; 0], + layout: SampleLayout { + channels: 2, + channel_stride: 1, + width: 4, + width_stride: 2, + height: 2, + height_stride: 8, + }, + color_hint: None, + } + .is_normal(NormalForm::RowMajorPacked)); + + assert!(FlatSamples { + samples: [0u8; 0], + layout: SampleLayout { + channels: 2, + channel_stride: 1, + width: 4, + width_stride: 4, + height: 2, + height_stride: 2, + }, + color_hint: None, + } + .is_normal(NormalForm::ColumnMajorPacked)); + } + + #[test] + fn image_buffer_conversion() { + let expected_layout = SampleLayout { + channels: 2, + channel_stride: 1, + width: 4, + width_stride: 2, + height: 2, + height_stride: 8, + }; + + let initial = GrayAlphaImage::new(expected_layout.width, expected_layout.height); + let buffer = initial.into_flat_samples(); + + assert_eq!(buffer.layout, expected_layout); + + let _: GrayAlphaImage = buffer + .try_into_buffer() + .unwrap_or_else(|(error, _)| panic!("Expected buffer to be convertible but {error:?}")); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/generic_image.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/generic_image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/generic_image.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/generic_image.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,608 @@ +use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind}; +use crate::math::Rect; +use crate::traits::Pixel; +use crate::{ImageBuffer, SubImage}; + +/// Trait to inspect an image. +/// +/// ``` +/// use image::{GenericImageView, Rgb, RgbImage}; +/// +/// let buffer = RgbImage::new(10, 10); +/// let image: &dyn GenericImageView> = &buffer; +/// ``` +pub trait GenericImageView { + /// The type of pixel. + type Pixel: Pixel; + + /// The width and height of this image. + fn dimensions(&self) -> (u32, u32); + + /// The width of this image. + fn width(&self) -> u32 { + let (w, _) = self.dimensions(); + w + } + + /// The height of this image. + fn height(&self) -> u32 { + let (_, h) = self.dimensions(); + h + } + + /// Returns true if this x, y coordinate is contained inside the image. + fn in_bounds(&self, x: u32, y: u32) -> bool { + let (width, height) = self.dimensions(); + x < width && y < height + } + + /// Returns the pixel located at (x, y). Indexed from top left. + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of bounds. + fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel; + + /// Returns the pixel located at (x, y). Indexed from top left. + /// + /// This function can be implemented in a way that ignores bounds checking. + /// # Safety + /// + /// The coordinates must be [`in_bounds`] of the image. + /// + /// [`in_bounds`]: #method.in_bounds + unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel { + self.get_pixel(x, y) + } + + /// Returns an Iterator over the pixels of this image. + /// The iterator yields the coordinates of each pixel + /// along with their value + fn pixels(&self) -> Pixels<'_, Self> + where + Self: Sized, + { + let (width, height) = self.dimensions(); + + Pixels { + image: self, + x: 0, + y: 0, + width, + height, + } + } + + /// Returns a subimage that is an immutable view into this image. + /// You can use [`GenericImage::sub_image`] if you need a mutable view instead. + /// The coordinates set the position of the top left corner of the view. + /// + /// # Panics + /// + /// Panics if the dimensions provided fall out of bounds. + fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self> + where + Self: Sized, + { + assert!(u64::from(x) + u64::from(width) <= u64::from(self.width())); + assert!(u64::from(y) + u64::from(height) <= u64::from(self.height())); + SubImage::new(self, x, y, width, height) + } + + /// Returns a subimage that is an immutable view into this image so long as + /// the provided coordinates and dimensions are within the bounds of this Image. + fn try_view( + &self, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result, ImageError> + where + Self: Sized, + { + if u64::from(x) + u64::from(width) > u64::from(self.width()) + || u64::from(y) + u64::from(height) > u64::from(self.height()) + { + Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + ))) + } else { + Ok(SubImage::new(self, x, y, width, height)) + } + } + + /// Create an empty [`ImageBuffer`] with the same pixel type as this image. + /// + /// This should ensure metadata such as the color space are transferred without copying any of + /// the pixel data. The idea is to prepare a buffer ready to be filled with a filtered or + /// portion of the channel data from the current image without performing the work of copying + /// the data into that buffer twice. + /// + /// The default implementation defers to [`GenericImageView::buffer_like`]. + fn buffer_like(&self) -> ImageBuffer::Subpixel>> { + let (w, h) = self.dimensions(); + self.buffer_with_dimensions(w, h) + } + + /// Create an empty [`ImageBuffer`] with different dimensions. + /// + /// See [`GenericImageView::buffer_like`]. + /// + /// Uses for this are for instances preparing a buffer for only a portion of the image, or + /// extracting the metadata to prepare a buffer of a different pixel type. + fn buffer_with_dimensions( + &self, + width: u32, + height: u32, + ) -> ImageBuffer::Subpixel>> { + ImageBuffer::new(width, height) + } +} + +/// Immutable pixel iterator +#[derive(Debug)] +pub struct Pixels<'a, I: ?Sized + 'a> { + image: &'a I, + x: u32, + y: u32, + width: u32, + height: u32, +} + +impl Iterator for Pixels<'_, I> { + type Item = (u32, u32, I::Pixel); + + fn next(&mut self) -> Option<(u32, u32, I::Pixel)> { + if self.x >= self.width { + self.x = 0; + self.y += 1; + } + + if self.y >= self.height { + None + } else { + let pixel = self.image.get_pixel(self.x, self.y); + let p = (self.x, self.y, pixel); + + self.x += 1; + + Some(p) + } + } +} + +impl Clone for Pixels<'_, I> { + fn clone(&self) -> Self { + Pixels { ..*self } + } +} + +/// A trait for manipulating images. +pub trait GenericImage: GenericImageView { + /// Gets a reference to the mutable pixel at location `(x, y)`. Indexed from top left. + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of bounds. + /// + /// Panics for dynamic images (this method is deprecated and will be removed). + /// + /// ## Known issues + /// + /// This requires the buffer to contain a unique set of continuous channels in the exact order + /// and byte representation that the pixel type requires. This is somewhat restrictive. + /// + /// TODO: Maybe use some kind of entry API? this would allow pixel type conversion on the fly + /// while still doing only one array lookup: + /// + /// ```ignore + /// let px = image.pixel_entry_at(x,y); + /// px.set_from_rgba(rgba) + /// ``` + #[deprecated(since = "0.24.0", note = "Use `get_pixel` and `put_pixel` instead.")] + fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel; + + /// Put a pixel at location (x, y). Indexed from top left. + /// + /// # Panics + /// + /// Panics if `(x, y)` is out of bounds. + fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel); + + /// Puts a pixel at location (x, y). Indexed from top left. + /// + /// This function can be implemented in a way that ignores bounds checking. + /// # Safety + /// + /// The coordinates must be [`in_bounds`] of the image. + /// + /// [`in_bounds`]: traits.GenericImageView.html#method.in_bounds + unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { + self.put_pixel(x, y, pixel); + } + + /// Put a pixel at location (x, y), taking into account alpha channels + #[deprecated( + since = "0.24.0", + note = "Use iterator `pixels_mut` to blend the pixels directly" + )] + fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel); + + /// Copies all of the pixels from another image into this image. + /// + /// The other image is copied with the top-left corner of the + /// other image placed at (x, y). + /// + /// In order to copy only a piece of the other image, use [`GenericImageView::view`]. + /// + /// You can use [`FlatSamples`] to source pixels from an arbitrary regular raster of channel + /// values, for example from a foreign interface or a fixed image. + /// + /// # Returns + /// Returns an error if the image is too large to be copied at the given position + /// + /// [`GenericImageView::view`]: trait.GenericImageView.html#method.view + /// [`FlatSamples`]: flat/struct.FlatSamples.html + fn copy_from(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()> + where + O: GenericImageView, + { + // Do bounds checking here so we can use the non-bounds-checking + // functions to copy pixels. + if self.width() < other.width() + x || self.height() < other.height() + y { + return Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + ))); + } + + for k in 0..other.height() { + for i in 0..other.width() { + let p = other.get_pixel(i, k); + self.put_pixel(i + x, k + y, p); + } + } + Ok(()) + } + + /// Copies all of the pixels from one part of this image to another part of this image. + /// + /// The destination rectangle of the copy is specified with the top-left corner placed at (x, y). + /// + /// # Returns + /// `true` if the copy was successful, `false` if the image could not + /// be copied due to size constraints. + fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool { + let Rect { + x: sx, + y: sy, + width, + height, + } = source; + let dx = x; + let dy = y; + assert!(sx < self.width() && dx < self.width()); + assert!(sy < self.height() && dy < self.height()); + if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height { + return false; + } + // since `.rev()` creates a new dype we would either have to go with dynamic dispatch for the ranges + // or have quite a lot of code bloat. A macro gives us static dispatch with less visible bloat. + macro_rules! copy_within_impl_ { + ($xiter:expr, $yiter:expr) => { + for y in $yiter { + let sy = sy + y; + let dy = dy + y; + for x in $xiter { + let sx = sx + x; + let dx = dx + x; + let pixel = self.get_pixel(sx, sy); + self.put_pixel(dx, dy, pixel); + } + } + }; + } + // check how target and source rectangles relate to each other so we dont overwrite data before we copied it. + match (sx < dx, sy < dy) { + (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()), + (true, false) => copy_within_impl_!((0..width).rev(), 0..height), + (false, true) => copy_within_impl_!(0..width, (0..height).rev()), + (false, false) => copy_within_impl_!(0..width, 0..height), + } + true + } + + /// Returns a mutable subimage that is a view into this image. + /// If you want an immutable subimage instead, use [`GenericImageView::view`] + /// The coordinates set the position of the top left corner of the `SubImage`. + fn sub_image(&mut self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&mut Self> + where + Self: Sized, + { + assert!(u64::from(x) + u64::from(width) <= u64::from(self.width())); + assert!(u64::from(y) + u64::from(height) <= u64::from(self.height())); + SubImage::new(self, x, y, width, height) + } +} + +#[cfg(test)] +mod tests { + use super::{GenericImage, GenericImageView}; + + use crate::color::Rgba; + use crate::math::Rect; + use crate::{GrayImage, ImageBuffer}; + + #[test] + #[allow(deprecated)] + /// Test that alpha blending works as expected + fn test_image_alpha_blending() { + let mut target = ImageBuffer::new(1, 1); + target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255])); + assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255])); + target.blend_pixel(0, 0, Rgba([0, 255, 0, 255])); + assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255])); + + // Blending an alpha channel onto a solid background + target.blend_pixel(0, 0, Rgba([255, 0, 0, 127])); + assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255])); + + // Blending two alpha channels + target.put_pixel(0, 0, Rgba([0, 255, 0, 127])); + target.blend_pixel(0, 0, Rgba([255, 0, 0, 127])); + assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190])); + } + + #[test] + fn test_in_bounds() { + let mut target = ImageBuffer::new(2, 2); + target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255])); + + assert!(target.in_bounds(0, 0)); + assert!(target.in_bounds(1, 0)); + assert!(target.in_bounds(0, 1)); + assert!(target.in_bounds(1, 1)); + + assert!(!target.in_bounds(2, 0)); + assert!(!target.in_bounds(0, 2)); + assert!(!target.in_bounds(2, 2)); + } + + #[test] + fn test_can_subimage_clone_nonmut() { + let mut source = ImageBuffer::new(3, 3); + source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255])); + + // A non-mutable copy of the source image + let source = source.clone(); + + // Clone a view into non-mutable to a separate buffer + let cloned = source.view(1, 1, 1, 1).to_image(); + + assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1)); + } + + #[test] + fn test_can_nest_views() { + let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + + { + let mut sub1 = source.sub_image(0, 0, 2, 2); + let mut sub2 = sub1.sub_image(1, 1, 1, 1); + sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0])); + } + + assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0])); + + let view1 = source.view(0, 0, 2, 2); + assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1)); + + let view2 = view1.view(1, 1, 1, 1); + assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0)); + } + + #[test] + #[should_panic] + fn test_view_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(1, 1, 3, 3); + } + + #[test] + #[should_panic] + fn test_view_coordinates_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(3, 3, 3, 3); + } + + #[test] + #[should_panic] + fn test_view_width_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(1, 1, 3, 2); + } + + #[test] + #[should_panic] + fn test_view_height_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(1, 1, 2, 3); + } + + #[test] + #[should_panic] + fn test_view_x_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(3, 1, 3, 3); + } + + #[test] + #[should_panic] + fn test_view_y_out_of_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(1, 3, 3, 3); + } + + #[test] + fn test_view_in_bounds() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + source.view(0, 0, 3, 3); + source.view(1, 1, 2, 2); + source.view(2, 2, 0, 0); + } + + #[test] + fn test_copy_sub_image() { + let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255])); + let view = source.view(0, 0, 3, 3); + let _view2 = view; + view.to_image(); + } + + #[test] + fn test_generic_image_copy_within_oob() { + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap(); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 0, + width: 5, + height: 4 + }, + 0, + 0 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 0, + width: 4, + height: 5 + }, + 0, + 0 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 1, + y: 0, + width: 4, + height: 4 + }, + 0, + 0 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 0, + width: 4, + height: 4 + }, + 1, + 0 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 1, + width: 4, + height: 4 + }, + 0, + 0 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 0, + width: 4, + height: 4 + }, + 0, + 1 + )); + assert!(!image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 1, + y: 1, + width: 4, + height: 4 + }, + 0, + 0 + )); + } + + #[test] + fn test_generic_image_copy_within_tl() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 0, + width: 3, + height: 3 + }, + 1, + 1 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_generic_image_copy_within_tr() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 1, + y: 0, + width: 3, + height: 3 + }, + 0, + 1 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_generic_image_copy_within_bl() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 0, + y: 1, + width: 3, + height: 3 + }, + 1, + 0 + )); + assert_eq!(&image.into_raw(), &expected); + } + + #[test] + fn test_generic_image_copy_within_br() { + let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15]; + let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap(); + assert!(image.sub_image(0, 0, 4, 4).copy_within( + Rect { + x: 1, + y: 1, + width: 3, + height: 3 + }, + 0, + 0 + )); + assert_eq!(&image.into_raw(), &expected); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/sub_image.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/sub_image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images/sub_image.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images/sub_image.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,263 @@ +use crate::{GenericImage, GenericImageView, ImageBuffer, Pixel}; +use std::ops::{Deref, DerefMut}; + +/// A View into another image +/// +/// Instances of this struct can be created using: +/// - [`GenericImage::sub_image`] to create a mutable view, +/// - [`GenericImageView::view`] to create an immutable view, +/// - [`SubImage::new`] to instantiate the struct directly. +/// +/// Note that this does _not_ implement `GenericImage`, but it dereferences to one which allows you +/// to use it as if it did. See [Design Considerations](#Design-Considerations) below for details. +/// +/// # Design Considerations +/// +/// For reasons relating to coherence, this is not itself a `GenericImage` or a `GenericImageView`. +/// In short, we want to reserve the ability of adding traits implemented for _all_ generic images +/// but in a different manner for `SubImage`. This may be required to ensure that stacking +/// sub-images comes at no double indirect cost. +/// +/// If, ultimately, this is not needed then a directly implementation of `GenericImage` can and +/// will get added. This inconvenience may alternatively get resolved if Rust allows some forms of +/// specialization, which might make this trick unnecessary and thus also allows for a direct +/// implementation. +#[derive(Copy, Clone)] +pub struct SubImage { + inner: SubImageInner, +} + +/// The inner type of `SubImage` that implements `GenericImage{,View}`. +/// +/// This type is _nominally_ `pub` but it is not exported from the crate. It should be regarded as +/// an existential type in any case. +#[derive(Copy, Clone)] +pub struct SubImageInner { + image: I, + xoffset: u32, + yoffset: u32, + xstride: u32, + ystride: u32, +} + +/// Alias to access Pixel behind a reference +type DerefPixel = <::Target as GenericImageView>::Pixel; + +/// Alias to access Subpixel behind a reference +type DerefSubpixel = as Pixel>::Subpixel; + +impl SubImage { + /// Construct a new subimage + /// The coordinates set the position of the top left corner of the `SubImage`. + pub fn new(image: I, x: u32, y: u32, width: u32, height: u32) -> SubImage { + SubImage { + inner: SubImageInner { + image, + xoffset: x, + yoffset: y, + xstride: width, + ystride: height, + }, + } + } + + /// Change the coordinates of this subimage. + pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) { + self.inner.xoffset = x; + self.inner.yoffset = y; + self.inner.xstride = width; + self.inner.ystride = height; + } + + /// The offsets of this subimage relative to the underlying image. + pub fn offsets(&self) -> (u32, u32) { + (self.inner.xoffset, self.inner.yoffset) + } + + /// Convert this subimage to an `ImageBuffer` + pub fn to_image(&self) -> ImageBuffer, Vec>> + where + I: Deref, + I::Target: GenericImageView + 'static, + { + let borrowed = &*self.inner.image; + let mut out = borrowed.buffer_with_dimensions(self.inner.xstride, self.inner.ystride); + + for y in 0..self.inner.ystride { + for x in 0..self.inner.xstride { + let p = borrowed.get_pixel(x + self.inner.xoffset, y + self.inner.yoffset); + out.put_pixel(x, y, p); + } + } + + out + } +} + +/// Methods for readable images. +impl SubImage +where + I: Deref, + I::Target: GenericImageView, +{ + /// Create a sub-view of the image. + /// + /// The coordinates given are relative to the current view on the underlying image. + /// + /// Note that this method is preferred to the one from `GenericImageView`. This is accessible + /// with the explicit method call syntax but it should rarely be needed due to causing an + /// extra level of indirection. + /// + /// ``` + /// use image::{GenericImageView, RgbImage, SubImage}; + /// let buffer = RgbImage::new(10, 10); + /// + /// let subimage: SubImage<&RgbImage> = buffer.view(0, 0, 10, 10); + /// let subview: SubImage<&RgbImage> = subimage.view(0, 0, 10, 10); + /// + /// // Less efficient and NOT &RgbImage + /// let _: SubImage<&_> = GenericImageView::view(&*subimage, 0, 0, 10, 10); + /// ``` + pub fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&I::Target> { + use crate::GenericImageView as _; + assert!(u64::from(x) + u64::from(width) <= u64::from(self.inner.width())); + assert!(u64::from(y) + u64::from(height) <= u64::from(self.inner.height())); + let x = self.inner.xoffset.saturating_add(x); + let y = self.inner.yoffset.saturating_add(y); + SubImage::new(&*self.inner.image, x, y, width, height) + } + + /// Get a reference to the underlying image. + pub fn inner(&self) -> &I::Target { + &self.inner.image + } +} + +impl SubImage +where + I: DerefMut, + I::Target: GenericImage, +{ + /// Create a mutable sub-view of the image. + /// + /// The coordinates given are relative to the current view on the underlying image. + pub fn sub_image( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> SubImage<&mut I::Target> { + assert!(u64::from(x) + u64::from(width) <= u64::from(self.inner.width())); + assert!(u64::from(y) + u64::from(height) <= u64::from(self.inner.height())); + let x = self.inner.xoffset.saturating_add(x); + let y = self.inner.yoffset.saturating_add(y); + SubImage::new(&mut *self.inner.image, x, y, width, height) + } + + /// Get a mutable reference to the underlying image. + pub fn inner_mut(&mut self) -> &mut I::Target { + &mut self.inner.image + } +} + +impl Deref for SubImage +where + I: Deref, +{ + type Target = SubImageInner; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for SubImage +where + I: DerefMut, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +#[allow(deprecated)] +impl GenericImageView for SubImageInner +where + I: Deref, + I::Target: GenericImageView, +{ + type Pixel = DerefPixel; + + fn dimensions(&self) -> (u32, u32) { + (self.xstride, self.ystride) + } + + fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel { + self.image.get_pixel(x + self.xoffset, y + self.yoffset) + } + + /// Create a buffer with the (color) metadata of the underlying image. + fn buffer_with_dimensions( + &self, + width: u32, + height: u32, + ) -> ImageBuffer< + ::Pixel, + Vec<<::Pixel as Pixel>::Subpixel>, + > { + self.image.buffer_with_dimensions(width, height) + } +} + +#[allow(deprecated)] +impl GenericImage for SubImageInner +where + I: DerefMut, + I::Target: GenericImage + Sized, +{ + fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel { + self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset) + } + + fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { + self.image + .put_pixel(x + self.xoffset, y + self.yoffset, pixel); + } + + /// DEPRECATED: This method will be removed. Blend the pixel directly instead. + fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { + self.image + .blend_pixel(x + self.xoffset, y + self.yoffset, pixel); + } +} + +#[cfg(test)] +mod tests { + use crate::{metadata::Cicp, GenericImageView, RgbaImage}; + + #[test] + fn preserves_color_space() { + let mut buffer = RgbaImage::new(16, 16); + buffer[(0, 0)] = crate::Rgba([0xff, 0, 0, 255]); + buffer.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + + let view = buffer.view(0, 0, 16, 16); + let result = view.buffer_like(); + + assert_eq!(buffer.color_space(), result.color_space()); + } + + #[test] + fn deep_preserves_color_space() { + let mut buffer = RgbaImage::new(16, 16); + buffer[(0, 0)] = crate::Rgba([0xff, 0, 0, 255]); + buffer.set_rgb_primaries(Cicp::DISPLAY_P3.primaries); + + let view = buffer.view(0, 0, 16, 16); + let view = view.view(0, 0, 16, 16); + let result = view.buffer_like(); + + assert_eq!(buffer.color_space(), result.color_space()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/images.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/images.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/images.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +//! An internal module for grouping all forms of image buffers. +pub(crate) mod buffer; +#[cfg(feature = "rayon")] +pub(crate) mod buffer_par; +pub(crate) mod dynimage; +pub(crate) mod generic_image; +// Public as we re-export the whole module including its documentation. +pub mod flat; +pub(crate) mod sub_image; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,230 @@ +use crate::animation::Frames; +use crate::color::{ColorType, ExtendedColorType}; +use crate::error::ImageResult; +use crate::metadata::Orientation; + +/// The trait that all decoders implement +pub trait ImageDecoder { + /// Returns a tuple containing the width and height of the image + fn dimensions(&self) -> (u32, u32); + + /// Returns the color type of the image data produced by this decoder + fn color_type(&self) -> ColorType; + + /// Returns the color type of the image file before decoding + fn original_color_type(&self) -> ExtendedColorType { + self.color_type().into() + } + + /// Returns the ICC color profile embedded in the image, or `Ok(None)` if the image does not have one. + /// + /// For formats that don't support embedded profiles this function should always return `Ok(None)`. + fn icc_profile(&mut self) -> ImageResult>> { + Ok(None) + } + + /// Returns the raw [Exif](https://en.wikipedia.org/wiki/Exif) chunk, if it is present. + /// A third-party crate such as [`kamadak-exif`](https://docs.rs/kamadak-exif/) is required to actually parse it. + /// + /// For formats that don't support embedded profiles this function should always return `Ok(None)`. + fn exif_metadata(&mut self) -> ImageResult>> { + Ok(None) + } + + /// Returns the raw [XMP](https://en.wikipedia.org/wiki/Extensible_Metadata_Platform) chunk, if it is present. + /// A third-party crate such as [`roxmltree`](https://docs.rs/roxmltree/) is required to actually parse it. + /// + /// For formats that don't support embedded profiles this function should always return `Ok(None)`. + fn xmp_metadata(&mut self) -> ImageResult>> { + Ok(None) + } + + /// Returns the raw [IPTC](https://en.wikipedia.org/wiki/IPTC_Information_Interchange_Model) chunk, if it is present. + /// + /// For formats that don't support embedded profiles this function should always return `Ok(None)`. + fn iptc_metadata(&mut self) -> ImageResult>> { + Ok(None) + } + + /// Returns the orientation of the image. + /// + /// This is usually obtained from the Exif metadata, if present. Formats that don't support + /// indicating orientation in their image metadata will return `Ok(Orientation::NoTransforms)`. + fn orientation(&mut self) -> ImageResult { + Ok(self + .exif_metadata()? + .and_then(|chunk| Orientation::from_exif_chunk(&chunk)) + .unwrap_or(Orientation::NoTransforms)) + } + + /// Returns the total number of bytes in the decoded image. + /// + /// This is the size of the buffer that must be passed to `read_image` or + /// `read_image_with_progress`. The returned value may exceed `usize::MAX`, in + /// which case it isn't actually possible to construct a buffer to decode all the image data + /// into. If, however, the size does not fit in a u64 then `u64::MAX` is returned. + fn total_bytes(&self) -> u64 { + let dimensions = self.dimensions(); + let total_pixels = u64::from(dimensions.0) * u64::from(dimensions.1); + let bytes_per_pixel = u64::from(self.color_type().bytes_per_pixel()); + total_pixels.saturating_mul(bytes_per_pixel) + } + + /// Returns all the bytes in the image. + /// + /// This function takes a slice of bytes and writes the pixel data of the image into it. + /// `buf` does not need to be aligned to any byte boundaries. However, + /// alignment to 2 or 4 byte boundaries may result in small performance + /// improvements for certain decoder implementations. + /// + /// The returned pixel data will always be in native endian. This allows + /// `[u16]` and `[f32]` slices to be cast to `[u8]` and used for this method. + /// + /// # Panics + /// + /// This function panics if `buf.len() != self.total_bytes()`. + /// + /// # Examples + /// + /// ``` + /// # use image::ImageDecoder; + /// fn read_16bit_image(decoder: impl ImageDecoder) -> Vec { + /// let mut buf: Vec = vec![0; (decoder.total_bytes() / 2) as usize]; + /// decoder.read_image(bytemuck::cast_slice_mut(&mut buf)); + /// buf + /// } + /// ``` + fn read_image(self, buf: &mut [u8]) -> ImageResult<()> + where + Self: Sized; + + /// Set the decoder to have the specified limits. See [`Limits`] for the different kinds of + /// limits that is possible to set. + /// + /// Note to implementors: make sure you call [`Limits::check_support`] so that + /// decoding fails if any unsupported strict limits are set. Also make sure + /// you call [`Limits::check_dimensions`] to check the `max_image_width` and + /// `max_image_height` limits. + /// + /// **Note**: By default, _no_ limits are defined. This may be changed in future major version + /// increases. + /// + /// [`Limits`]: ./io/struct.Limits.html + /// [`Limits::check_support`]: ./io/struct.Limits.html#method.check_support + /// [`Limits::check_dimensions`]: ./io/struct.Limits.html#method.check_dimensions + fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { + limits.check_support(&crate::LimitSupport::default())?; + let (width, height) = self.dimensions(); + limits.check_dimensions(width, height)?; + Ok(()) + } + + /// Use `read_image` instead; this method is an implementation detail needed so the trait can + /// be object safe. + /// + /// Note to implementors: This method should be implemented by calling `read_image` on + /// the boxed decoder... + /// ```ignore + /// fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + /// (*self).read_image(buf) + /// } + /// ``` + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()>; +} + +#[deny(clippy::missing_trait_methods)] +impl ImageDecoder for Box { + fn dimensions(&self) -> (u32, u32) { + (**self).dimensions() + } + fn color_type(&self) -> ColorType { + (**self).color_type() + } + fn original_color_type(&self) -> ExtendedColorType { + (**self).original_color_type() + } + fn icc_profile(&mut self) -> ImageResult>> { + (**self).icc_profile() + } + fn exif_metadata(&mut self) -> ImageResult>> { + (**self).exif_metadata() + } + fn xmp_metadata(&mut self) -> ImageResult>> { + (**self).xmp_metadata() + } + fn iptc_metadata(&mut self) -> ImageResult>> { + (**self).iptc_metadata() + } + fn orientation(&mut self) -> ImageResult { + (**self).orientation() + } + fn total_bytes(&self) -> u64 { + (**self).total_bytes() + } + fn read_image(self, buf: &mut [u8]) -> ImageResult<()> + where + Self: Sized, + { + T::read_image_boxed(self, buf) + } + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + T::read_image_boxed(*self, buf) + } + fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { + (**self).set_limits(limits) + } +} + +/// Specialized image decoding not be supported by all formats +pub trait ImageDecoderRect: ImageDecoder { + /// Decode a rectangular section of the image. + /// + /// This function takes a slice of bytes and writes the pixel data of the image into it. + /// The rectangle is specified by the x and y coordinates of the top left corner, the width + /// and height of the rectangle, and the row pitch of the buffer. The row pitch is the number + /// of bytes between the start of one row and the start of the next row. The row pitch must be + /// at least as large as the width of the rectangle in bytes. + fn read_rect( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + buf: &mut [u8], + row_pitch: usize, + ) -> ImageResult<()>; +} + +/// `AnimationDecoder` trait +pub trait AnimationDecoder<'a> { + /// Consume the decoder producing a series of frames. + fn into_frames(self) -> Frames<'a>; +} + +#[cfg(test)] +mod tests { + use super::{ColorType, ImageDecoder, ImageResult}; + + #[test] + fn total_bytes_overflow() { + struct D; + impl ImageDecoder for D { + fn color_type(&self) -> ColorType { + ColorType::Rgb8 + } + fn dimensions(&self) -> (u32, u32) { + (0xffff_ffff, 0xffff_ffff) + } + fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> { + unimplemented!() + } + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } + } + assert_eq!(D.total_bytes(), u64::MAX); + + let v: ImageResult> = crate::io::free_functions::decoder_to_vec(D); + assert!(v.is_err()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,132 @@ +use crate::error::{ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind}; +use crate::{ColorType, DynamicImage, ExtendedColorType}; + +/// Nominally public but DO NOT expose this type. +/// +/// To be somewhat sure here's a compile fail test: +/// +/// ```compile_fail +/// use image::MethodSealedToImage; +/// ``` +/// +/// ```compile_fail +/// use image::io::MethodSealedToImage; +/// ``` +/// +/// The same implementation strategy for a partially public trait is used in the standard library, +/// for the different effect of forbidding `Error::type_id` overrides thus making them reliable for +/// their calls through the `dyn` version of the trait. +/// +/// Read more: +#[derive(Clone, Copy)] +pub struct MethodSealedToImage; + +/// The trait all encoders implement +pub trait ImageEncoder { + /// Writes all the bytes in an image to the encoder. + /// + /// This function takes a slice of bytes of the pixel data of the image + /// and encodes them. Just like for [`ImageDecoder::read_image`], no particular + /// alignment is required and data is expected to be in native endian. + /// The implementation will reorder the endianness as necessary for the target encoding format. + /// + /// # Panics + /// + /// Panics if `width * height * color_type.bytes_per_pixel() != buf.len()`. + fn write_image( + self, + buf: &[u8], + width: u32, + height: u32, + color_type: ExtendedColorType, + ) -> ImageResult<()>; + + /// Set the ICC profile to use for the image. + /// + /// This function is a no-op for formats that don't support ICC profiles. + /// For formats that do support ICC profiles, the profile will be embedded + /// in the image when it is saved. + /// + /// # Errors + /// + /// This function returns an error if the format does not support ICC profiles. + fn set_icc_profile(&mut self, icc_profile: Vec) -> Result<(), UnsupportedError> { + let _ = icc_profile; + Err(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::GenericFeature( + "ICC profiles are not supported for this format".into(), + ), + )) + } + + /// Set the EXIF metadata to use for the image. + /// + /// This function is a no-op for formats that don't support EXIF metadata. + /// For formats that do support EXIF metadata, the metadata will be embedded + /// in the image when it is saved. + /// + /// # Errors + /// + /// This function returns an error if the format does not support EXIF metadata or if the + /// encoder doesn't implement saving EXIF metadata yet. + fn set_exif_metadata(&mut self, exif: Vec) -> Result<(), UnsupportedError> { + let _ = exif; + Err(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::GenericFeature( + "EXIF metadata is not supported for this format".into(), + ), + )) + } + + /// Convert the image to a compatible format for the encoder. This is used by the encoding + /// methods on `DynamicImage`. + /// + /// Note that this is method is sealed to the crate and effectively pub(crate) due to the + /// argument type not being nameable. + #[doc(hidden)] + fn make_compatible_img( + &self, + _: MethodSealedToImage, + _input: &DynamicImage, + ) -> Option { + None + } +} + +pub(crate) trait ImageEncoderBoxed: ImageEncoder { + fn write_image( + self: Box, + buf: &'_ [u8], + width: u32, + height: u32, + color: ExtendedColorType, + ) -> ImageResult<()>; +} +impl ImageEncoderBoxed for T { + fn write_image( + self: Box, + buf: &'_ [u8], + width: u32, + height: u32, + color: ExtendedColorType, + ) -> ImageResult<()> { + (*self).write_image(buf, width, height, color) + } +} + +/// Implement `dynimage_conversion_sequence` for the common case of supporting only 8-bit colors +/// (with and without alpha). +#[allow(unused)] +pub(crate) fn dynimage_conversion_8bit(img: &DynamicImage) -> Option { + use ColorType::*; + + match img.color() { + Rgb8 | Rgba8 | L8 | La8 => None, + L16 => Some(img.to_luma8().into()), + La16 => Some(img.to_luma_alpha8().into()), + Rgb16 | Rgb32F => Some(img.to_rgb8().into()), + Rgba16 | Rgba32F => Some(img.to_rgba8().into()), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/format.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/format.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/format.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/format.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,470 @@ +use std::ffi::OsStr; +use std::path::Path; + +use crate::error::{ImageError, ImageFormatHint, ImageResult}; + +/// An enumeration of supported image formats. +/// Not all formats support both encoding and decoding. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[non_exhaustive] +pub enum ImageFormat { + /// An Image in PNG Format + Png, + + /// An Image in JPEG Format + Jpeg, + + /// An Image in GIF Format + Gif, + + /// An Image in WEBP Format + WebP, + + /// An Image in general PNM Format + Pnm, + + /// An Image in TIFF Format + Tiff, + + /// An Image in TGA Format + Tga, + + /// An Image in DDS Format + Dds, + + /// An Image in BMP Format + Bmp, + + /// An Image in ICO Format + Ico, + + /// An Image in Radiance HDR Format + Hdr, + + /// An Image in OpenEXR Format + OpenExr, + + /// An Image in farbfeld Format + Farbfeld, + + /// An Image in AVIF Format + Avif, + + /// An Image in QOI Format + Qoi, + + /// An Image in PCX Format + #[cfg_attr(not(feature = "serde"), deprecated)] + #[doc(hidden)] + Pcx, +} + +impl ImageFormat { + /// Return the image format specified by a path's file extension. + /// + /// # Example + /// + /// ``` + /// use image::ImageFormat; + /// + /// let format = ImageFormat::from_extension("jpg"); + /// assert_eq!(format, Some(ImageFormat::Jpeg)); + /// ``` + #[inline] + pub fn from_extension(ext: S) -> Option + where + S: AsRef, + { + // thin wrapper function to strip generics + fn inner(ext: &OsStr) -> Option { + let ext = ext.to_str()?.to_ascii_lowercase(); + // NOTE: when updating this, also update extensions_str() + Some(match ext.as_str() { + "avif" => ImageFormat::Avif, + "jpg" | "jpeg" | "jfif" => ImageFormat::Jpeg, + "png" | "apng" => ImageFormat::Png, + "gif" => ImageFormat::Gif, + "webp" => ImageFormat::WebP, + "tif" | "tiff" => ImageFormat::Tiff, + "tga" => ImageFormat::Tga, + "dds" => ImageFormat::Dds, + "bmp" => ImageFormat::Bmp, + "ico" => ImageFormat::Ico, + "hdr" => ImageFormat::Hdr, + "exr" => ImageFormat::OpenExr, + "pbm" | "pam" | "ppm" | "pgm" | "pnm" => ImageFormat::Pnm, + "ff" => ImageFormat::Farbfeld, + "qoi" => ImageFormat::Qoi, + _ => return None, + }) + } + + inner(ext.as_ref()) + } + + /// Return the image format specified by the path's file extension. + /// + /// # Example + /// + /// ``` + /// use image::ImageFormat; + /// + /// let format = ImageFormat::from_path("images/ferris.png")?; + /// assert_eq!(format, ImageFormat::Png); + /// + /// # Ok::<(), image::error::ImageError>(()) + /// ``` + #[inline] + pub fn from_path

(path: P) -> ImageResult + where + P: AsRef, + { + // thin wrapper function to strip generics + fn inner(path: &Path) -> ImageResult { + let exact_ext = path.extension(); + exact_ext + .and_then(ImageFormat::from_extension) + .ok_or_else(|| { + let format_hint = match exact_ext { + None => ImageFormatHint::Unknown, + Some(os) => ImageFormatHint::PathExtension(os.into()), + }; + ImageError::Unsupported(format_hint.into()) + }) + } + + inner(path.as_ref()) + } + + /// Return the image format specified by a MIME type. + /// + /// # Example + /// + /// ``` + /// use image::ImageFormat; + /// + /// let format = ImageFormat::from_mime_type("image/png").unwrap(); + /// assert_eq!(format, ImageFormat::Png); + /// ``` + pub fn from_mime_type(mime_type: M) -> Option + where + M: AsRef, + { + match mime_type.as_ref() { + "image/avif" => Some(ImageFormat::Avif), + "image/jpeg" => Some(ImageFormat::Jpeg), + "image/png" => Some(ImageFormat::Png), + "image/gif" => Some(ImageFormat::Gif), + "image/webp" => Some(ImageFormat::WebP), + "image/tiff" => Some(ImageFormat::Tiff), + "image/x-targa" | "image/x-tga" => Some(ImageFormat::Tga), + "image/vnd-ms.dds" => Some(ImageFormat::Dds), + "image/bmp" => Some(ImageFormat::Bmp), + "image/x-icon" | "image/vnd.microsoft.icon" => Some(ImageFormat::Ico), + "image/vnd.radiance" => Some(ImageFormat::Hdr), + "image/x-exr" => Some(ImageFormat::OpenExr), + "image/x-portable-bitmap" + | "image/x-portable-graymap" + | "image/x-portable-pixmap" + | "image/x-portable-anymap" => Some(ImageFormat::Pnm), + // Qoi's MIME type is being worked on. + // See: https://github.com/phoboslab/qoi/issues/167 + "image/x-qoi" => Some(ImageFormat::Qoi), + _ => None, + } + } + + /// Return the MIME type for this image format or "application/octet-stream" if no MIME type + /// exists for the format. + /// + /// Some notes on a few of the MIME types: + /// + /// - The portable anymap format has a separate MIME type for the pixmap, graymap and bitmap + /// formats, but this method returns the general "image/x-portable-anymap" MIME type. + /// - The Targa format has two common MIME types, "image/x-targa" and "image/x-tga"; this + /// method returns "image/x-targa" for that format. + /// - The QOI MIME type is still a work in progress. This method returns "image/x-qoi" for + /// that format. + /// + /// # Example + /// + /// ``` + /// use image::ImageFormat; + /// + /// let mime_type = ImageFormat::Png.to_mime_type(); + /// assert_eq!(mime_type, "image/png"); + /// ``` + #[must_use] + pub fn to_mime_type(&self) -> &'static str { + match self { + ImageFormat::Avif => "image/avif", + ImageFormat::Jpeg => "image/jpeg", + ImageFormat::Png => "image/png", + ImageFormat::Gif => "image/gif", + ImageFormat::WebP => "image/webp", + ImageFormat::Tiff => "image/tiff", + // the targa MIME type has two options, but this one seems to be used more + ImageFormat::Tga => "image/x-targa", + ImageFormat::Dds => "image/vnd-ms.dds", + ImageFormat::Bmp => "image/bmp", + ImageFormat::Ico => "image/x-icon", + ImageFormat::Hdr => "image/vnd.radiance", + ImageFormat::OpenExr => "image/x-exr", + // return the most general MIME type + ImageFormat::Pnm => "image/x-portable-anymap", + // Qoi's MIME type is being worked on. + // See: https://github.com/phoboslab/qoi/issues/167 + ImageFormat::Qoi => "image/x-qoi", + // farbfeld's MIME type taken from https://www.wikidata.org/wiki/Q28206109 + ImageFormat::Farbfeld => "application/octet-stream", + #[allow(deprecated)] + ImageFormat::Pcx => "image/vnd.zbrush.pcx", + } + } + + /// Return if the `ImageFormat` can be decoded by the lib. + #[inline] + #[must_use] + pub fn can_read(&self) -> bool { + // Needs to be updated once a new variant's decoder is added to free_functions.rs::load + match self { + ImageFormat::Png => true, + ImageFormat::Gif => true, + ImageFormat::Jpeg => true, + ImageFormat::WebP => true, + ImageFormat::Tiff => true, + ImageFormat::Tga => true, + ImageFormat::Dds => false, + ImageFormat::Bmp => true, + ImageFormat::Ico => true, + ImageFormat::Hdr => true, + ImageFormat::OpenExr => true, + ImageFormat::Pnm => true, + ImageFormat::Farbfeld => true, + ImageFormat::Avif => true, + ImageFormat::Qoi => true, + #[allow(deprecated)] + ImageFormat::Pcx => false, + } + } + + /// Return if the `ImageFormat` can be encoded by the lib. + #[inline] + #[must_use] + pub fn can_write(&self) -> bool { + // Needs to be updated once a new variant's encoder is added to free_functions.rs::save_buffer_with_format_impl + match self { + ImageFormat::Gif => true, + ImageFormat::Ico => true, + ImageFormat::Jpeg => true, + ImageFormat::Png => true, + ImageFormat::Bmp => true, + ImageFormat::Tiff => true, + ImageFormat::Tga => true, + ImageFormat::Pnm => true, + ImageFormat::Farbfeld => true, + ImageFormat::Avif => true, + ImageFormat::WebP => true, + ImageFormat::Hdr => true, + ImageFormat::OpenExr => true, + ImageFormat::Dds => false, + ImageFormat::Qoi => true, + #[allow(deprecated)] + ImageFormat::Pcx => false, + } + } + + /// Return a list of applicable extensions for this format. + /// + /// All currently recognized image formats specify at least on extension but for future + /// compatibility you should not rely on this fact. The list may be empty if the format has no + /// recognized file representation, for example in case it is used as a purely transient memory + /// format. + /// + /// The method name `extensions` remains reserved for introducing another method in the future + /// that yields a slice of `OsStr` which is blocked by several features of const evaluation. + #[must_use] + pub fn extensions_str(self) -> &'static [&'static str] { + // NOTE: when updating this, also update from_extension() + match self { + ImageFormat::Png => &["png"], + ImageFormat::Jpeg => &["jpg", "jpeg"], + ImageFormat::Gif => &["gif"], + ImageFormat::WebP => &["webp"], + ImageFormat::Pnm => &["pbm", "pam", "ppm", "pgm", "pnm"], + ImageFormat::Tiff => &["tiff", "tif"], + ImageFormat::Tga => &["tga"], + ImageFormat::Dds => &["dds"], + ImageFormat::Bmp => &["bmp"], + ImageFormat::Ico => &["ico"], + ImageFormat::Hdr => &["hdr"], + ImageFormat::OpenExr => &["exr"], + ImageFormat::Farbfeld => &["ff"], + // According to: https://aomediacodec.github.io/av1-avif/#mime-registration + ImageFormat::Avif => &["avif"], + ImageFormat::Qoi => &["qoi"], + #[allow(deprecated)] + ImageFormat::Pcx => &["pcx"], + } + } + + /// Return the `ImageFormat`s which are enabled for reading. + #[inline] + #[must_use] + pub fn reading_enabled(&self) -> bool { + match self { + ImageFormat::Png => cfg!(feature = "png"), + ImageFormat::Gif => cfg!(feature = "gif"), + ImageFormat::Jpeg => cfg!(feature = "jpeg"), + ImageFormat::WebP => cfg!(feature = "webp"), + ImageFormat::Tiff => cfg!(feature = "tiff"), + ImageFormat::Tga => cfg!(feature = "tga"), + ImageFormat::Bmp => cfg!(feature = "bmp"), + ImageFormat::Ico => cfg!(feature = "ico"), + ImageFormat::Hdr => cfg!(feature = "hdr"), + ImageFormat::OpenExr => cfg!(feature = "exr"), + ImageFormat::Pnm => cfg!(feature = "pnm"), + ImageFormat::Farbfeld => cfg!(feature = "ff"), + ImageFormat::Avif => cfg!(feature = "avif"), + ImageFormat::Qoi => cfg!(feature = "qoi"), + #[allow(deprecated)] + ImageFormat::Pcx => false, + ImageFormat::Dds => false, + } + } + + /// Return the `ImageFormat`s which are enabled for writing. + #[inline] + #[must_use] + pub fn writing_enabled(&self) -> bool { + match self { + ImageFormat::Gif => cfg!(feature = "gif"), + ImageFormat::Ico => cfg!(feature = "ico"), + ImageFormat::Jpeg => cfg!(feature = "jpeg"), + ImageFormat::Png => cfg!(feature = "png"), + ImageFormat::Bmp => cfg!(feature = "bmp"), + ImageFormat::Tiff => cfg!(feature = "tiff"), + ImageFormat::Tga => cfg!(feature = "tga"), + ImageFormat::Pnm => cfg!(feature = "pnm"), + ImageFormat::Farbfeld => cfg!(feature = "ff"), + ImageFormat::Avif => cfg!(feature = "avif"), + ImageFormat::WebP => cfg!(feature = "webp"), + ImageFormat::OpenExr => cfg!(feature = "exr"), + ImageFormat::Qoi => cfg!(feature = "qoi"), + ImageFormat::Hdr => cfg!(feature = "hdr"), + #[allow(deprecated)] + ImageFormat::Pcx => false, + ImageFormat::Dds => false, + } + } + + /// Return all `ImageFormat`s + pub fn all() -> impl Iterator { + [ + ImageFormat::Gif, + ImageFormat::Ico, + ImageFormat::Jpeg, + ImageFormat::Png, + ImageFormat::Bmp, + ImageFormat::Tiff, + ImageFormat::Tga, + ImageFormat::Pnm, + ImageFormat::Farbfeld, + ImageFormat::Avif, + ImageFormat::WebP, + ImageFormat::OpenExr, + ImageFormat::Qoi, + ImageFormat::Dds, + ImageFormat::Hdr, + #[allow(deprecated)] + ImageFormat::Pcx, + ] + .iter() + .copied() + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashSet; + use std::path::Path; + + use super::{ImageFormat, ImageResult}; + + #[test] + fn test_image_format_from_path() { + fn from_path(s: &str) -> ImageResult { + ImageFormat::from_path(Path::new(s)) + } + assert_eq!(from_path("./a.jpg").unwrap(), ImageFormat::Jpeg); + assert_eq!(from_path("./a.jpeg").unwrap(), ImageFormat::Jpeg); + assert_eq!(from_path("./a.JPEG").unwrap(), ImageFormat::Jpeg); + assert_eq!(from_path("./a.pNg").unwrap(), ImageFormat::Png); + assert_eq!(from_path("./a.gif").unwrap(), ImageFormat::Gif); + assert_eq!(from_path("./a.webp").unwrap(), ImageFormat::WebP); + assert_eq!(from_path("./a.tiFF").unwrap(), ImageFormat::Tiff); + assert_eq!(from_path("./a.tif").unwrap(), ImageFormat::Tiff); + assert_eq!(from_path("./a.tga").unwrap(), ImageFormat::Tga); + assert_eq!(from_path("./a.dds").unwrap(), ImageFormat::Dds); + assert_eq!(from_path("./a.bmp").unwrap(), ImageFormat::Bmp); + assert_eq!(from_path("./a.Ico").unwrap(), ImageFormat::Ico); + assert_eq!(from_path("./a.hdr").unwrap(), ImageFormat::Hdr); + assert_eq!(from_path("./a.exr").unwrap(), ImageFormat::OpenExr); + assert_eq!(from_path("./a.pbm").unwrap(), ImageFormat::Pnm); + assert_eq!(from_path("./a.pAM").unwrap(), ImageFormat::Pnm); + assert_eq!(from_path("./a.Ppm").unwrap(), ImageFormat::Pnm); + assert_eq!(from_path("./a.pgm").unwrap(), ImageFormat::Pnm); + assert_eq!(from_path("./a.AViF").unwrap(), ImageFormat::Avif); + assert!(from_path("./a.txt").is_err()); + assert!(from_path("./a").is_err()); + } + + #[test] + fn image_formats_are_recognized() { + use ImageFormat::*; + const ALL_FORMATS: &[ImageFormat] = &[ + Avif, Png, Jpeg, Gif, WebP, Pnm, Tiff, Tga, Dds, Bmp, Ico, Hdr, Farbfeld, OpenExr, + ]; + for &format in ALL_FORMATS { + let mut file = Path::new("file.nothing").to_owned(); + for ext in format.extensions_str() { + assert!(file.set_extension(ext)); + match ImageFormat::from_path(&file) { + Err(_) => panic!("Path {} not recognized as {:?}", file.display(), format), + Ok(result) => assert_eq!(format, result), + } + } + } + } + + #[test] + fn all() { + let all_formats: HashSet = ImageFormat::all().collect(); + assert!(all_formats.contains(&ImageFormat::Avif)); + assert!(all_formats.contains(&ImageFormat::Gif)); + assert!(all_formats.contains(&ImageFormat::Bmp)); + assert!(all_formats.contains(&ImageFormat::Farbfeld)); + assert!(all_formats.contains(&ImageFormat::Jpeg)); + } + + #[test] + fn reading_enabled() { + assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.reading_enabled()); + assert_eq!( + cfg!(feature = "ff"), + ImageFormat::Farbfeld.reading_enabled() + ); + assert!(!ImageFormat::Dds.reading_enabled()); + } + + #[test] + fn writing_enabled() { + assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.writing_enabled()); + assert_eq!( + cfg!(feature = "ff"), + ImageFormat::Farbfeld.writing_enabled() + ); + assert!(!ImageFormat::Dds.writing_enabled()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/free_functions.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/free_functions.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/free_functions.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/free_functions.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,292 +1,133 @@ use std::fs::File; -use std::io::{BufRead, BufReader, BufWriter, Seek}; +use std::io::{self, BufRead, BufWriter, Seek, Write}; use std::path::Path; -use std::u32; +use std::{iter, mem::size_of}; -use crate::codecs::*; +use crate::io::encoder::ImageEncoderBoxed; +use crate::{codecs::*, ExtendedColorType, ImageReader}; -use crate::dynimage::DynamicImage; -use crate::error::{ImageError, ImageFormatHint, ImageResult}; -use crate::image; -use crate::image::ImageFormat; -#[allow(unused_imports)] // When no features are supported -use crate::image::{ImageDecoder, ImageEncoder}; -use crate::{ - color, - error::{UnsupportedError, UnsupportedErrorKind}, - ImageOutputFormat, +use crate::error::{ + ImageError, ImageFormatHint, ImageResult, LimitError, LimitErrorKind, ParameterError, + ParameterErrorKind, UnsupportedError, UnsupportedErrorKind, }; - -pub(crate) fn open_impl(path: &Path) -> ImageResult { - let buffered_read = BufReader::new(File::open(path).map_err(ImageError::IoError)?); - - load(buffered_read, ImageFormat::from_path(path)?) -} +use crate::{DynamicImage, ImageDecoder, ImageFormat}; /// Create a new image from a Reader. /// /// Assumes the reader is already buffered. For optimal performance, /// consider wrapping the reader with a `BufReader::new()`. /// -/// Try [`io::Reader`] for more advanced uses. -/// -/// [`io::Reader`]: io/struct.Reader.html -#[allow(unused_variables)] -// r is unused if no features are supported. +/// Try [`ImageReader`] for more advanced uses. pub fn load(r: R, format: ImageFormat) -> ImageResult { - load_inner(r, super::Limits::default(), format) -} - -pub(crate) trait DecoderVisitor { - type Result; - fn visit_decoder<'a, D: ImageDecoder<'a>>(self, decoder: D) -> ImageResult; + let mut reader = ImageReader::new(r); + reader.set_format(format); + reader.decode() } -pub(crate) fn load_decoder( - r: R, - format: ImageFormat, - limits: super::Limits, - visitor: V, -) -> ImageResult { - #[allow(unreachable_patterns)] - // Default is unreachable if all features are supported. - match format { - #[cfg(feature = "avif-decoder")] - image::ImageFormat::Avif => visitor.visit_decoder(avif::AvifDecoder::new(r)?), - #[cfg(feature = "png")] - image::ImageFormat::Png => visitor.visit_decoder(png::PngDecoder::with_limits(r, limits)?), - #[cfg(feature = "gif")] - image::ImageFormat::Gif => visitor.visit_decoder(gif::GifDecoder::new(r)?), - #[cfg(feature = "jpeg")] - image::ImageFormat::Jpeg => visitor.visit_decoder(jpeg::JpegDecoder::new(r)?), - #[cfg(feature = "webp")] - image::ImageFormat::WebP => visitor.visit_decoder(webp::WebPDecoder::new(r)?), - #[cfg(feature = "tiff")] - image::ImageFormat::Tiff => visitor.visit_decoder(tiff::TiffDecoder::new(r)?), - #[cfg(feature = "tga")] - image::ImageFormat::Tga => visitor.visit_decoder(tga::TgaDecoder::new(r)?), - #[cfg(feature = "dds")] - image::ImageFormat::Dds => visitor.visit_decoder(dds::DdsDecoder::new(r)?), - #[cfg(feature = "bmp")] - image::ImageFormat::Bmp => visitor.visit_decoder(bmp::BmpDecoder::new(r)?), - #[cfg(feature = "ico")] - image::ImageFormat::Ico => visitor.visit_decoder(ico::IcoDecoder::new(r)?), - #[cfg(feature = "hdr")] - image::ImageFormat::Hdr => visitor.visit_decoder(hdr::HdrAdapter::new(BufReader::new(r))?), - #[cfg(feature = "exr")] - image::ImageFormat::OpenExr => visitor.visit_decoder(openexr::OpenExrDecoder::new(r)?), - #[cfg(feature = "pnm")] - image::ImageFormat::Pnm => visitor.visit_decoder(pnm::PnmDecoder::new(r)?), - #[cfg(feature = "farbfeld")] - image::ImageFormat::Farbfeld => visitor.visit_decoder(farbfeld::FarbfeldDecoder::new(r)?), - #[cfg(feature = "qoi")] - image::ImageFormat::Qoi => visitor.visit_decoder(qoi::QoiDecoder::new(r)?), - _ => Err(ImageError::Unsupported( - ImageFormatHint::Exact(format).into(), - )), - } -} - -pub(crate) fn load_inner( - r: R, - limits: super::Limits, - format: ImageFormat, -) -> ImageResult { - struct LoadVisitor(super::Limits); - - impl DecoderVisitor for LoadVisitor { - type Result = DynamicImage; - - fn visit_decoder<'a, D: ImageDecoder<'a>>( - self, - mut decoder: D, - ) -> ImageResult { - let mut limits = self.0; - // Check that we do not allocate a bigger buffer than we are allowed to - // FIXME: should this rather go in `DynamicImage::from_decoder` somehow? - limits.reserve(decoder.total_bytes())?; - decoder.set_limits(limits)?; - DynamicImage::from_decoder(decoder) - } - } - - load_decoder(r, format, limits.clone(), LoadVisitor(limits)) -} - -pub(crate) fn image_dimensions_impl(path: &Path) -> ImageResult<(u32, u32)> { - let format = image::ImageFormat::from_path(path)?; - let reader = BufReader::new(File::open(path)?); - image_dimensions_with_format_impl(reader, format) -} - -#[allow(unused_variables)] -// fin is unused if no features are supported. -pub(crate) fn image_dimensions_with_format_impl( - buffered_read: R, - format: ImageFormat, -) -> ImageResult<(u32, u32)> { - struct DimVisitor; - - impl DecoderVisitor for DimVisitor { - type Result = (u32, u32); - fn visit_decoder<'a, D: ImageDecoder<'a>>(self, decoder: D) -> ImageResult { - Ok(decoder.dimensions()) - } - } - - load_decoder(buffered_read, format, super::Limits::default(), DimVisitor) -} - -#[allow(unused_variables)] -// Most variables when no features are supported -pub(crate) fn save_buffer_impl( - path: &Path, +/// Saves the supplied buffer to a file at the path specified. +/// +/// The image format is derived from the file extension. The buffer is assumed to have the correct +/// format according to the specified color type. This will lead to corrupted files if the buffer +/// contains malformed data. +pub fn save_buffer( + path: impl AsRef, buf: &[u8], width: u32, height: u32, - color: color::ColorType, + color: impl Into, ) -> ImageResult<()> { - let format = ImageFormat::from_path(path)?; - save_buffer_with_format_impl(path, buf, width, height, color, format) + let format = ImageFormat::from_path(path.as_ref())?; + save_buffer_with_format(path, buf, width, height, color, format) } -#[allow(unused_variables)] -// Most variables when no features are supported -pub(crate) fn save_buffer_with_format_impl( - path: &Path, +/// Saves the supplied buffer to a file given the path and desired format. +/// +/// The buffer is assumed to have the correct format according to the specified color type. This +/// will lead to corrupted files if the buffer contains malformed data. +pub fn save_buffer_with_format( + path: impl AsRef, buf: &[u8], width: u32, height: u32, - color: color::ColorType, + color: impl Into, format: ImageFormat, ) -> ImageResult<()> { let buffered_file_write = &mut BufWriter::new(File::create(path)?); // always seekable - - let format = match format { - #[cfg(feature = "pnm")] - image::ImageFormat::Pnm => { - let ext = path - .extension() - .and_then(|s| s.to_str()) - .map_or("".to_string(), |s| s.to_ascii_lowercase()); - ImageOutputFormat::Pnm(match &*ext { - "pbm" => pnm::PnmSubtype::Bitmap(pnm::SampleEncoding::Binary), - "pgm" => pnm::PnmSubtype::Graymap(pnm::SampleEncoding::Binary), - "ppm" => pnm::PnmSubtype::Pixmap(pnm::SampleEncoding::Binary), - "pam" => pnm::PnmSubtype::ArbitraryMap, - _ => { - return Err(ImageError::Unsupported( - ImageFormatHint::Exact(format).into(), - )) - } // Unsupported Pnm subtype. - }) - } - // #[cfg(feature = "hdr")] - // image::ImageFormat::Hdr => hdr::HdrEncoder::new(fout).encode(&[Rgb], width, height), // usize - format => format.into(), - }; - - write_buffer_impl(buffered_file_write, buf, width, height, color, format) + let encoder = encoder_for_format(format, buffered_file_write)?; + encoder.write_image(buf, width, height, color.into()) } -#[allow(unused_variables)] -// Most variables when no features are supported -pub(crate) fn write_buffer_impl( - buffered_write: &mut W, - buf: &[u8], - width: u32, - height: u32, - color: color::ColorType, - format: ImageOutputFormat, -) -> ImageResult<()> { - match format { +pub(crate) fn encoder_for_format<'a, W: Write + Seek>( + format: ImageFormat, + buffered_write: &'a mut W, +) -> ImageResult> { + Ok(match format { #[cfg(feature = "png")] - ImageOutputFormat::Png => { - png::PngEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Png => Box::new(png::PngEncoder::new(buffered_write)), #[cfg(feature = "jpeg")] - ImageOutputFormat::Jpeg(quality) => { - jpeg::JpegEncoder::new_with_quality(buffered_write, quality) - .write_image(buf, width, height, color) - } + ImageFormat::Jpeg => Box::new(jpeg::JpegEncoder::new(buffered_write)), #[cfg(feature = "pnm")] - ImageOutputFormat::Pnm(subtype) => pnm::PnmEncoder::new(buffered_write) - .with_subtype(subtype) - .write_image(buf, width, height, color), + ImageFormat::Pnm => Box::new(pnm::PnmEncoder::new(buffered_write)), #[cfg(feature = "gif")] - ImageOutputFormat::Gif => { - gif::GifEncoder::new(buffered_write).encode(buf, width, height, color) - } + ImageFormat::Gif => Box::new(gif::GifEncoder::new(buffered_write)), #[cfg(feature = "ico")] - ImageOutputFormat::Ico => { - ico::IcoEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Ico => Box::new(ico::IcoEncoder::new(buffered_write)), #[cfg(feature = "bmp")] - ImageOutputFormat::Bmp => { - bmp::BmpEncoder::new(buffered_write).write_image(buf, width, height, color) - } - #[cfg(feature = "farbfeld")] - ImageOutputFormat::Farbfeld => { - farbfeld::FarbfeldEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Bmp => Box::new(bmp::BmpEncoder::new(buffered_write)), + #[cfg(feature = "ff")] + ImageFormat::Farbfeld => Box::new(farbfeld::FarbfeldEncoder::new(buffered_write)), #[cfg(feature = "tga")] - ImageOutputFormat::Tga => { - tga::TgaEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Tga => Box::new(tga::TgaEncoder::new(buffered_write)), #[cfg(feature = "exr")] - ImageOutputFormat::OpenExr => { - openexr::OpenExrEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::OpenExr => Box::new(openexr::OpenExrEncoder::new(buffered_write)), #[cfg(feature = "tiff")] - ImageOutputFormat::Tiff => { - tiff::TiffEncoder::new(buffered_write).write_image(buf, width, height, color) - } - #[cfg(feature = "avif-encoder")] - ImageOutputFormat::Avif => { - avif::AvifEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Tiff => Box::new(tiff::TiffEncoder::new(buffered_write)), + #[cfg(feature = "avif")] + ImageFormat::Avif => Box::new(avif::AvifEncoder::new(buffered_write)), #[cfg(feature = "qoi")] - ImageOutputFormat::Qoi => { - qoi::QoiEncoder::new(buffered_write).write_image(buf, width, height, color) - } + ImageFormat::Qoi => Box::new(qoi::QoiEncoder::new(buffered_write)), #[cfg(feature = "webp")] - ImageOutputFormat::WebP => { - webp::WebPEncoder::new_lossless(buffered_write).write_image(buf, width, height, color) - } - - image::ImageOutputFormat::Unsupported(msg) => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormatHint::Unknown, - UnsupportedErrorKind::Format(ImageFormatHint::Name(msg)), - ), - )), - } -} - -static MAGIC_BYTES: [(&[u8], ImageFormat); 23] = [ - (b"\x89PNG\r\n\x1a\n", ImageFormat::Png), - (&[0xff, 0xd8, 0xff], ImageFormat::Jpeg), - (b"GIF89a", ImageFormat::Gif), - (b"GIF87a", ImageFormat::Gif), - (b"RIFF", ImageFormat::WebP), // TODO: better magic byte detection, see https://github.com/image-rs/image/issues/660 - (b"MM\x00*", ImageFormat::Tiff), - (b"II*\x00", ImageFormat::Tiff), - (b"DDS ", ImageFormat::Dds), - (b"BM", ImageFormat::Bmp), - (&[0, 0, 1, 0], ImageFormat::Ico), - (b"#?RADIANCE", ImageFormat::Hdr), - (b"P1", ImageFormat::Pnm), - (b"P2", ImageFormat::Pnm), - (b"P3", ImageFormat::Pnm), - (b"P4", ImageFormat::Pnm), - (b"P5", ImageFormat::Pnm), - (b"P6", ImageFormat::Pnm), - (b"P7", ImageFormat::Pnm), - (b"farbfeld", ImageFormat::Farbfeld), - (b"\0\0\0 ftypavif", ImageFormat::Avif), - (b"\0\0\0\x1cftypavif", ImageFormat::Avif), - (&[0x76, 0x2f, 0x31, 0x01], ImageFormat::OpenExr), // = &exr::meta::magic_number::BYTES - (b"qoif", ImageFormat::Qoi), + ImageFormat::WebP => Box::new(webp::WebPEncoder::new_lossless(buffered_write)), + #[cfg(feature = "hdr")] + ImageFormat::Hdr => Box::new(hdr::HdrEncoder::new(buffered_write)), + _ => { + return Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::Format(ImageFormatHint::Name(format!("{format:?}"))), + ), + )); + } + }) +} + +static MAGIC_BYTES: [(&[u8], &[u8], ImageFormat); 22] = [ + (b"\x89PNG\r\n\x1a\n", b"", ImageFormat::Png), + (&[0xff, 0xd8, 0xff], b"", ImageFormat::Jpeg), + (b"GIF89a", b"", ImageFormat::Gif), + (b"GIF87a", b"", ImageFormat::Gif), + ( + b"RIFF\0\0\0\0WEBP", + b"\xFF\xFF\xFF\xFF\0\0\0\0", + ImageFormat::WebP, + ), + (b"MM\x00*", b"", ImageFormat::Tiff), + (b"II*\x00", b"", ImageFormat::Tiff), + (b"DDS ", b"", ImageFormat::Dds), + (b"BM", b"", ImageFormat::Bmp), + (&[0, 0, 1, 0], b"", ImageFormat::Ico), + (b"#?RADIANCE", b"", ImageFormat::Hdr), + (b"\0\0\0\0ftypavif", b"\xFF\xFF\0\0", ImageFormat::Avif), + (&[0x76, 0x2f, 0x31, 0x01], b"", ImageFormat::OpenExr), // = &exr::meta::magic_number::BYTES + (b"qoif", b"", ImageFormat::Qoi), + (b"P1", b"", ImageFormat::Pnm), + (b"P2", b"", ImageFormat::Pnm), + (b"P3", b"", ImageFormat::Pnm), + (b"P4", b"", ImageFormat::Pnm), + (b"P5", b"", ImageFormat::Pnm), + (b"P6", b"", ImageFormat::Pnm), + (b"P7", b"", ImageFormat::Pnm), + (b"farbfeld", b"", ImageFormat::Farbfeld), ]; /// Guess image format from memory block @@ -302,11 +143,362 @@ } pub(crate) fn guess_format_impl(buffer: &[u8]) -> Option { - for &(signature, format) in &MAGIC_BYTES { - if buffer.starts_with(signature) { + for &(signature, mask, format) in &MAGIC_BYTES { + if mask.is_empty() { + if buffer.starts_with(signature) { + return Some(format); + } + } else if buffer.len() >= signature.len() + && buffer + .iter() + .zip(signature.iter()) + .zip(mask.iter().chain(iter::repeat(&0xFF))) + .all(|((&byte, &sig), &mask)| byte & mask == sig) + { return Some(format); } } None } + +/// Decodes a specific region of the image, represented by the rectangle +/// starting from ```x``` and ```y``` and having ```length``` and ```width``` +#[allow(dead_code)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn load_rect( + x: u32, + y: u32, + width: u32, + height: u32, + buf: &mut [u8], + row_pitch: usize, + decoder: &mut D, + scanline_bytes: usize, + mut seek_scanline: F1, + mut read_scanline: F2, +) -> ImageResult<()> +where + D: ImageDecoder, + F1: FnMut(&mut D, u64) -> io::Result<()>, + F2: FnMut(&mut D, &mut [u8]) -> Result<(), E>, + ImageError: From, +{ + let scanline_bytes = u64::try_from(scanline_bytes).unwrap(); + let row_pitch = u64::try_from(row_pitch).unwrap(); + + let (x, y, width, height) = ( + u64::from(x), + u64::from(y), + u64::from(width), + u64::from(height), + ); + let dimensions = decoder.dimensions(); + let bytes_per_pixel = u64::from(decoder.color_type().bytes_per_pixel()); + let row_bytes = bytes_per_pixel * u64::from(dimensions.0); + let total_bytes = width * height * bytes_per_pixel; + + assert!( + buf.len() >= usize::try_from(total_bytes).unwrap_or(usize::MAX), + "output buffer too short\n expected `{}`, provided `{}`", + total_bytes, + buf.len() + ); + + let mut current_scanline = 0; + let mut tmp = Vec::new(); + let mut tmp_scanline = None; + + { + // Read a range of the image starting from byte number `start` and continuing until byte + // number `end`. Updates `current_scanline` and `bytes_read` appropriately. + let mut read_image_range = + |mut start: u64, end: u64, mut output: &mut [u8]| -> ImageResult<()> { + // If the first scanline we need is already stored in the temporary buffer, then handle + // it first. + let target_scanline = start / scanline_bytes; + if tmp_scanline == Some(target_scanline) { + let position = target_scanline * scanline_bytes; + let offset = start.saturating_sub(position); + let len = (end - start) + .min(scanline_bytes - offset) + .min(end - position); + + output + .write_all(&tmp[offset as usize..][..len as usize]) + .unwrap(); + start += len; + + if start == end { + return Ok(()); + } + } + + let target_scanline = start / scanline_bytes; + if target_scanline != current_scanline { + seek_scanline(decoder, target_scanline)?; + current_scanline = target_scanline; + } + + let mut position = current_scanline * scanline_bytes; + while position < end { + if position >= start && end - position >= scanline_bytes { + read_scanline(decoder, &mut output[..(scanline_bytes as usize)])?; + output = &mut output[scanline_bytes as usize..]; + } else { + tmp.resize(scanline_bytes as usize, 0u8); + read_scanline(decoder, &mut tmp)?; + tmp_scanline = Some(current_scanline); + + let offset = start.saturating_sub(position); + let len = (end - start) + .min(scanline_bytes - offset) + .min(end - position); + + output + .write_all(&tmp[offset as usize..][..len as usize]) + .unwrap(); + } + + current_scanline += 1; + position += scanline_bytes; + } + Ok(()) + }; + + if x + width > u64::from(dimensions.0) + || y + height > u64::from(dimensions.1) + || width == 0 + || height == 0 + { + return Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::DimensionMismatch, + ))); + } + if scanline_bytes > usize::MAX as u64 { + return Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::InsufficientMemory, + ))); + } + + if x == 0 && width == u64::from(dimensions.0) && row_pitch == row_bytes { + let start = x * bytes_per_pixel + y * row_bytes; + let end = (x + width) * bytes_per_pixel + (y + height - 1) * row_bytes; + read_image_range(start, end, buf)?; + } else { + for (output_slice, row) in buf.chunks_mut(row_pitch as usize).zip(y..(y + height)) { + let start = x * bytes_per_pixel + row * row_bytes; + let end = (x + width) * bytes_per_pixel + row * row_bytes; + read_image_range(start, end, output_slice)?; + } + } + } + + // Seek back to the start + Ok(seek_scanline(decoder, 0)?) +} + +/// Reads all of the bytes of a decoder into a Vec. No particular alignment +/// of the output buffer is guaranteed. +/// +/// Panics if there isn't enough memory to decode the image. +pub(crate) fn decoder_to_vec(decoder: impl ImageDecoder) -> ImageResult> +where + T: crate::traits::Primitive + bytemuck::Pod, +{ + let total_bytes = usize::try_from(decoder.total_bytes()); + if total_bytes.is_err() || total_bytes.unwrap() > isize::MAX as usize { + return Err(ImageError::Limits(LimitError::from_kind( + LimitErrorKind::InsufficientMemory, + ))); + } + + let mut buf = vec![num_traits::Zero::zero(); total_bytes.unwrap() / size_of::()]; + decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?; + Ok(buf) +} + +#[cfg(test)] +mod tests { + use crate::ColorType; + use std::io; + + use super::{load_rect, ImageDecoder, ImageResult}; + + #[test] + fn test_load_rect() { + struct MockDecoder { + scanline_number: u64, + scanline_bytes: u64, + } + impl ImageDecoder for MockDecoder { + fn dimensions(&self) -> (u32, u32) { + (5, 5) + } + fn color_type(&self) -> ColorType { + ColorType::L8 + } + fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> { + unimplemented!() + } + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } + } + + const DATA: [u8; 25] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, + ]; + + fn seek_scanline(m: &mut MockDecoder, n: u64) -> io::Result<()> { + m.scanline_number = n; + Ok(()) + } + fn read_scanline(m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> { + let bytes_read = m.scanline_number * m.scanline_bytes; + if bytes_read >= 25 { + return Ok(()); + } + + let len = m.scanline_bytes.min(25 - bytes_read); + buf[..(len as usize)].copy_from_slice(&DATA[(bytes_read as usize)..][..(len as usize)]); + m.scanline_number += 1; + Ok(()) + } + + for scanline_bytes in 1..30 { + let mut output = [0u8; 26]; + + load_rect( + 0, + 0, + 5, + 5, + &mut output, + 5, + &mut MockDecoder { + scanline_number: 0, + scanline_bytes, + }, + scanline_bytes as usize, + seek_scanline, + read_scanline, + ) + .unwrap(); + assert_eq!(output[0..25], DATA); + assert_eq!(output[25], 0); + + output = [0u8; 26]; + load_rect( + 3, + 2, + 1, + 1, + &mut output, + 1, + &mut MockDecoder { + scanline_number: 0, + scanline_bytes, + }, + scanline_bytes as usize, + seek_scanline, + read_scanline, + ) + .unwrap(); + assert_eq!(output[0..2], [13, 0]); + + output = [0u8; 26]; + load_rect( + 3, + 2, + 2, + 2, + &mut output, + 2, + &mut MockDecoder { + scanline_number: 0, + scanline_bytes, + }, + scanline_bytes as usize, + seek_scanline, + read_scanline, + ) + .unwrap(); + assert_eq!(output[0..5], [13, 14, 18, 19, 0]); + + output = [0u8; 26]; + load_rect( + 1, + 1, + 2, + 4, + &mut output, + 2, + &mut MockDecoder { + scanline_number: 0, + scanline_bytes, + }, + scanline_bytes as usize, + seek_scanline, + read_scanline, + ) + .unwrap(); + assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]); + } + } + + #[test] + fn test_load_rect_single_scanline() { + const DATA: [u8; 25] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, + ]; + + struct MockDecoder; + impl ImageDecoder for MockDecoder { + fn dimensions(&self) -> (u32, u32) { + (5, 5) + } + fn color_type(&self) -> ColorType { + ColorType::L8 + } + fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> { + unimplemented!() + } + fn read_image_boxed(self: Box, buf: &mut [u8]) -> ImageResult<()> { + (*self).read_image(buf) + } + } + + // Ensure that seek scanline is called only once. + let mut seeks = 0; + let seek_scanline = |_d: &mut MockDecoder, n: u64| -> io::Result<()> { + seeks += 1; + assert_eq!(n, 0); + assert_eq!(seeks, 1); + Ok(()) + }; + + fn read_scanline(_m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> { + buf.copy_from_slice(&DATA); + Ok(()) + } + + let mut output = [0; 26]; + load_rect( + 1, + 1, + 2, + 4, + &mut output, + 2, + &mut MockDecoder, + DATA.len(), + seek_scanline, + read_scanline, + ) + .unwrap(); + assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/image_reader_type.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/image_reader_type.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/image_reader_type.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/image_reader_type.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,363 @@ +use std::ffi::OsString; +use std::fs::File; +use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom}; +use std::iter; +use std::path::Path; + +use crate::error::{ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind}; +use crate::hooks::{GenericReader, DECODING_HOOKS, GUESS_FORMAT_HOOKS}; +use crate::io::limits::Limits; +use crate::{DynamicImage, ImageDecoder, ImageError, ImageFormat}; + +use super::free_functions; + +#[derive(Clone)] +enum Format { + BuiltIn(ImageFormat), + Extension(OsString), +} + +/// A multi-format image reader. +/// +/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate +/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations. +/// +/// ## Usage +/// +/// Opening a file, deducing the format based on the file path automatically, and trying to decode +/// the image contained can be performed by constructing the reader and immediately consuming it. +/// +/// ```no_run +/// # use image::ImageError; +/// # use image::ImageReader; +/// # fn main() -> Result<(), ImageError> { +/// let image = ImageReader::open("path/to/image.png")? +/// .decode()?; +/// # Ok(()) } +/// ``` +/// +/// It is also possible to make a guess based on the content. This is especially handy if the +/// source is some blob in memory and you have constructed the reader in another way. Here is an +/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values. +/// +/// ``` +/// # use image::ImageError; +/// # use image::ImageReader; +/// # fn main() -> Result<(), ImageError> { +/// use std::io::Cursor; +/// use image::ImageFormat; +/// +/// let raw_data = b"P1 2 2\n\ +/// 0 1\n\ +/// 1 0\n"; +/// +/// let mut reader = ImageReader::new(Cursor::new(raw_data)) +/// .with_guessed_format() +/// .expect("Cursor io never fails"); +/// assert_eq!(reader.format(), Some(ImageFormat::Pnm)); +/// +/// # #[cfg(feature = "pnm")] +/// let image = reader.decode()?; +/// # Ok(()) } +/// ``` +/// +/// As a final fallback or if only a specific format must be used, the reader always allows manual +/// specification of the supposed image format with [`set_format`]. +/// +/// [`set_format`]: #method.set_format +/// [`ImageDecoder`]: ../trait.ImageDecoder.html +pub struct ImageReader { + /// The reader. Should be buffered. + inner: R, + /// The format, if one has been set or deduced. + format: Option, + /// Decoding limits + limits: Limits, +} + +impl<'a, R: 'a + BufRead + Seek> ImageReader { + /// Create a new image reader without a preset format. + /// + /// Assumes the reader is already buffered. For optimal performance, + /// consider wrapping the reader with a `BufReader::new()`. + /// + /// It is possible to guess the format based on the content of the read object with + /// [`with_guessed_format`], or to set the format directly with [`set_format`]. + /// + /// [`with_guessed_format`]: #method.with_guessed_format + /// [`set_format`]: method.set_format + pub fn new(buffered_reader: R) -> Self { + ImageReader { + inner: buffered_reader, + format: None, + limits: Limits::default(), + } + } + + /// Construct a reader with specified format. + /// + /// Assumes the reader is already buffered. For optimal performance, + /// consider wrapping the reader with a `BufReader::new()`. + pub fn with_format(buffered_reader: R, format: ImageFormat) -> Self { + ImageReader { + inner: buffered_reader, + format: Some(Format::BuiltIn(format)), + limits: Limits::default(), + } + } + + /// Get the currently determined format. + pub fn format(&self) -> Option { + match self.format { + Some(Format::BuiltIn(ref format)) => Some(*format), + Some(Format::Extension(ref ext)) => ImageFormat::from_extension(ext), + None => None, + } + } + + /// Supply the format as which to interpret the read image. + pub fn set_format(&mut self, format: ImageFormat) { + self.format = Some(Format::BuiltIn(format)); + } + + /// Remove the current information on the image format. + /// + /// Note that many operations require format information to be present and will return e.g. an + /// `ImageError::Unsupported` when the image format has not been set. + pub fn clear_format(&mut self) { + self.format = None; + } + + /// Disable all decoding limits. + pub fn no_limits(&mut self) { + self.limits = Limits::no_limits(); + } + + /// Set a custom set of decoding limits. + pub fn limits(&mut self, limits: Limits) { + self.limits = limits; + } + + /// Unwrap the reader. + pub fn into_inner(self) -> R { + self.inner + } + + /// Makes a decoder. + /// + /// For all formats except PNG, the limits are ignored and can be set with + /// `ImageDecoder::set_limits` after calling this function. PNG is handled specially because that + /// decoder has a different API which does not allow setting limits after construction. + fn make_decoder( + format: Format, + reader: R, + limits_for_png: Limits, + ) -> ImageResult> { + #[allow(unused)] + use crate::codecs::*; + + let format = match format { + Format::BuiltIn(format) => format, + Format::Extension(ext) => { + { + let hooks = DECODING_HOOKS.read().unwrap(); + if let Some(hooks) = hooks.as_ref() { + if let Some(hook) = hooks.get(&ext) { + return hook(GenericReader(BufReader::new(Box::new(reader)))); + } + } + } + + ImageFormat::from_extension(&ext).ok_or(ImageError::Unsupported( + ImageFormatHint::PathExtension(ext.into()).into(), + ))? + } + }; + + #[allow(unreachable_patterns)] + // Default is unreachable if all features are supported. + Ok(match format { + #[cfg(feature = "avif-native")] + ImageFormat::Avif => Box::new(avif::AvifDecoder::new(reader)?), + #[cfg(feature = "png")] + ImageFormat::Png => Box::new(png::PngDecoder::with_limits(reader, limits_for_png)?), + #[cfg(feature = "gif")] + ImageFormat::Gif => Box::new(gif::GifDecoder::new(reader)?), + #[cfg(feature = "jpeg")] + ImageFormat::Jpeg => Box::new(jpeg::JpegDecoder::new(reader)?), + #[cfg(feature = "webp")] + ImageFormat::WebP => Box::new(webp::WebPDecoder::new(reader)?), + #[cfg(feature = "tiff")] + ImageFormat::Tiff => Box::new(tiff::TiffDecoder::new(reader)?), + #[cfg(feature = "tga")] + ImageFormat::Tga => Box::new(tga::TgaDecoder::new(reader)?), + #[cfg(feature = "dds")] + ImageFormat::Dds => Box::new(dds::DdsDecoder::new(reader)?), + #[cfg(feature = "bmp")] + ImageFormat::Bmp => Box::new(bmp::BmpDecoder::new(reader)?), + #[cfg(feature = "ico")] + ImageFormat::Ico => Box::new(ico::IcoDecoder::new(reader)?), + #[cfg(feature = "hdr")] + ImageFormat::Hdr => Box::new(hdr::HdrDecoder::new(reader)?), + #[cfg(feature = "exr")] + ImageFormat::OpenExr => Box::new(openexr::OpenExrDecoder::new(reader)?), + #[cfg(feature = "pnm")] + ImageFormat::Pnm => Box::new(pnm::PnmDecoder::new(reader)?), + #[cfg(feature = "ff")] + ImageFormat::Farbfeld => Box::new(farbfeld::FarbfeldDecoder::new(reader)?), + #[cfg(feature = "qoi")] + ImageFormat::Qoi => Box::new(qoi::QoiDecoder::new(reader)?), + format => { + return Err(ImageError::Unsupported( + ImageFormatHint::Exact(format).into(), + )); + } + }) + } + + /// Convert the reader into a decoder. + pub fn into_decoder(mut self) -> ImageResult { + let mut decoder = + Self::make_decoder(self.require_format()?, self.inner, self.limits.clone())?; + decoder.set_limits(self.limits)?; + Ok(decoder) + } + + /// Make a format guess based on the content, replacing it on success. + /// + /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current + /// format if the guess was successful. If the guess was unable to determine a format then + /// the current format of the reader is unchanged. + /// + /// Returns an error if the underlying reader fails. The format is unchanged. The error is a + /// `std::io::Error` and not `ImageError` since the only error case is an error when the + /// underlying reader seeks. + /// + /// When an error occurs, the reader may not have been properly reset and it is potentially + /// hazardous to continue with more io. + /// + /// ## Usage + /// + /// This supplements the path based type deduction from [`ImageReader::open()`] with content based deduction. + /// This is more common in Linux and UNIX operating systems and also helpful if the path can + /// not be directly controlled. + /// + /// ```no_run + /// # use image::ImageError; + /// # use image::ImageReader; + /// # fn main() -> Result<(), ImageError> { + /// let image = ImageReader::open("image.unknown")? + /// .with_guessed_format()? + /// .decode()?; + /// # Ok(()) } + /// ``` + pub fn with_guessed_format(mut self) -> io::Result { + let format = self.guess_format()?; + // Replace format if found, keep current state if not. + self.format = format.or(self.format); + Ok(self) + } + + fn guess_format(&mut self) -> io::Result> { + let mut start = [0; 16]; + + // Save current offset, read start, restore offset. + let cur = self.inner.stream_position()?; + let len = io::copy( + // Accept shorter files but read at most 16 bytes. + &mut self.inner.by_ref().take(16), + &mut Cursor::new(&mut start[..]), + )?; + self.inner.seek(SeekFrom::Start(cur))?; + + let hooks = GUESS_FORMAT_HOOKS.read().unwrap(); + for &(signature, mask, ref extension) in &*hooks { + if mask.is_empty() { + if start.starts_with(signature) { + return Ok(Some(Format::Extension(extension.clone()))); + } + } else if start.len() >= signature.len() + && start + .iter() + .zip(signature.iter()) + .zip(mask.iter().chain(iter::repeat(&0xFF))) + .all(|((&byte, &sig), &mask)| byte & mask == sig) + { + return Ok(Some(Format::Extension(extension.clone()))); + } + } + + if let Some(format) = free_functions::guess_format_impl(&start[..len as usize]) { + return Ok(Some(Format::BuiltIn(format))); + } + + Ok(None) + } + + /// Read the image dimensions. + /// + /// Uses the current format to construct the correct reader for the format. + /// + /// If no format was determined, returns an `ImageError::Unsupported`. + pub fn into_dimensions(self) -> ImageResult<(u32, u32)> { + self.into_decoder().map(|d| d.dimensions()) + } + + /// Read the image (replaces `load`). + /// + /// Uses the current format to construct the correct reader for the format. + /// + /// If no format was determined, returns an `ImageError::Unsupported`. + pub fn decode(mut self) -> ImageResult { + let format = self.require_format()?; + + let mut limits = self.limits; + let mut decoder = Self::make_decoder(format, self.inner, limits.clone())?; + + // Check that we do not allocate a bigger buffer than we are allowed to + // FIXME: should this rather go in `DynamicImage::from_decoder` somehow? + limits.reserve(decoder.total_bytes())?; + decoder.set_limits(limits)?; + + DynamicImage::from_decoder(decoder) + } + + fn require_format(&mut self) -> ImageResult { + self.format.clone().ok_or_else(|| { + ImageError::Unsupported(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::Format(ImageFormatHint::Unknown), + )) + }) + } +} + +impl ImageReader> { + /// Open a file to read, format will be guessed from path. + /// + /// This will not attempt any io operation on the opened file. + /// + /// If you want to inspect the content for a better guess on the format, which does not depend + /// on file extensions, follow this call with a call to [`with_guessed_format`]. + /// + /// [`with_guessed_format`]: #method.with_guessed_format + pub fn open

(path: P) -> io::Result + where + P: AsRef, + { + Self::open_impl(path.as_ref()) + } + + fn open_impl(path: &Path) -> io::Result { + let format = path + .extension() + .filter(|ext| !ext.is_empty()) + .map(|ext| Format::Extension(ext.to_owned())); + + Ok(ImageReader { + inner: BufReader::new(File::open(path)?), + format, + limits: Limits::default(), + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/limits.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/limits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/limits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/limits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,172 @@ +use crate::{error, ColorType, ImageError, ImageResult}; + +/// Set of supported strict limits for a decoder. +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] +#[allow(missing_copy_implementations)] +#[non_exhaustive] +pub struct LimitSupport {} + +/// Resource limits for decoding. +/// +/// Limits can be either *strict* or *non-strict*. Non-strict limits are best-effort +/// limits where the library does not guarantee that limit will not be exceeded. Do note +/// that it is still considered a bug if a non-strict limit is exceeded. +/// Some of the underlying decoders do not support such limits, so one cannot +/// rely on these limits being supported. For strict limits, the library makes a stronger +/// guarantee that the limit will not be exceeded. Exceeding a strict limit is considered +/// a critical bug. If a decoder cannot guarantee that it will uphold a strict limit, it +/// *must* fail with [`error::LimitErrorKind::Unsupported`]. +/// +/// The only currently supported strict limits are the `max_image_width` and `max_image_height` +/// limits, but more will be added in the future. [`LimitSupport`] will default to support +/// being false, and decoders should enable support for the limits they support in +/// [`ImageDecoder::set_limits`]. +/// +/// The limit check should only ever fail if a limit will be exceeded or an unsupported strict +/// limit is used. +/// +/// [`LimitSupport`]: ./struct.LimitSupport.html +/// [`ImageDecoder::set_limits`]: ../trait.ImageDecoder.html#method.set_limits +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[allow(missing_copy_implementations)] +#[non_exhaustive] +pub struct Limits { + /// The maximum allowed image width. This limit is strict. The default is no limit. + pub max_image_width: Option, + /// The maximum allowed image height. This limit is strict. The default is no limit. + pub max_image_height: Option, + /// The maximum allowed sum of allocations allocated by the decoder at any one time excluding + /// allocator overhead. This limit is non-strict by default and some decoders may ignore it. + /// The bytes required to store the output image count towards this value. The default is + /// 512MiB. + pub max_alloc: Option, +} + +/// Add some reasonable limits. +/// +/// **Note**: This is not equivalent to _not_ adding limits. This may be changed in future major +/// version increases. +impl Default for Limits { + fn default() -> Limits { + Limits { + max_image_width: None, + max_image_height: None, + max_alloc: Some(512 * 1024 * 1024), + } + } +} + +impl Limits { + /// Disable all limits. + #[must_use] + pub fn no_limits() -> Limits { + Limits { + max_image_width: None, + max_image_height: None, + max_alloc: None, + } + } + + /// This function checks that all currently set strict limits are supported. + pub fn check_support(&self, _supported: &LimitSupport) -> ImageResult<()> { + Ok(()) + } + + /// This function checks the `max_image_width` and `max_image_height` limits given + /// the image width and height. + pub fn check_dimensions(&self, width: u32, height: u32) -> ImageResult<()> { + if let Some(max_width) = self.max_image_width { + if width > max_width { + return Err(ImageError::Limits(error::LimitError::from_kind( + error::LimitErrorKind::DimensionError, + ))); + } + } + + if let Some(max_height) = self.max_image_height { + if height > max_height { + return Err(ImageError::Limits(error::LimitError::from_kind( + error::LimitErrorKind::DimensionError, + ))); + } + } + + Ok(()) + } + + /// This function checks that the current limit allows for reserving the set amount + /// of bytes, it then reduces the limit accordingly. + pub fn reserve(&mut self, amount: u64) -> ImageResult<()> { + if let Some(max_alloc) = self.max_alloc.as_mut() { + if *max_alloc < amount { + return Err(ImageError::Limits(error::LimitError::from_kind( + error::LimitErrorKind::InsufficientMemory, + ))); + } + + *max_alloc -= amount; + } + + Ok(()) + } + + /// This function acts identically to [`reserve`], but takes a `usize` for convenience. + /// + /// [`reserve`]: #method.reserve + pub fn reserve_usize(&mut self, amount: usize) -> ImageResult<()> { + match u64::try_from(amount) { + Ok(n) => self.reserve(n), + Err(_) if self.max_alloc.is_some() => Err(ImageError::Limits( + error::LimitError::from_kind(error::LimitErrorKind::InsufficientMemory), + )), + Err(_) => { + // Out of bounds, but we weren't asked to consider any limit. + Ok(()) + } + } + } + + /// This function acts identically to [`reserve`], but accepts the width, height and color type + /// used to create an [`ImageBuffer`] and does all the math for you. + /// + /// [`ImageBuffer`]: crate::ImageBuffer + /// [`reserve`]: #method.reserve + pub fn reserve_buffer( + &mut self, + width: u32, + height: u32, + color_type: ColorType, + ) -> ImageResult<()> { + self.check_dimensions(width, height)?; + let in_memory_size = u64::from(width) + .saturating_mul(u64::from(height)) + .saturating_mul(color_type.bytes_per_pixel().into()); + self.reserve(in_memory_size)?; + Ok(()) + } + + /// This function increases the `max_alloc` limit with amount. Should only be used + /// together with [`reserve`]. + /// + /// [`reserve`]: #method.reserve + pub fn free(&mut self, amount: u64) { + if let Some(max_alloc) = self.max_alloc.as_mut() { + *max_alloc = max_alloc.saturating_add(amount); + } + } + + /// This function acts identically to [`free`], but takes a `usize` for convenience. + /// + /// [`free`]: #method.free + pub fn free_usize(&mut self, amount: usize) { + match u64::try_from(amount) { + Ok(n) => self.free(n), + Err(_) if self.max_alloc.is_some() => { + panic!("max_alloc is set, we should have exited earlier when the reserve failed"); + } + Err(_) => { + // Out of bounds, but we weren't asked to consider any limit. + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/mod.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -//! Input and output of images. - -use crate::{error, ColorType, ImageError, ImageResult}; - -pub(crate) mod free_functions; -mod reader; - -pub use self::reader::Reader; - -/// Set of supported strict limits for a decoder. -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -#[allow(missing_copy_implementations)] -#[allow(clippy::manual_non_exhaustive)] -pub struct LimitSupport { - _non_exhaustive: (), -} - -#[allow(clippy::derivable_impls)] -impl Default for LimitSupport { - fn default() -> LimitSupport { - LimitSupport { - _non_exhaustive: (), - } - } -} - -/// Resource limits for decoding. -/// -/// Limits can be either *strict* or *non-strict*. Non-strict limits are best-effort -/// limits where the library does not guarantee that limit will not be exceeded. Do note -/// that it is still considered a bug if a non-strict limit is exceeded, however as -/// some of the underlying decoders do not support not support such limits one cannot -/// rely on these limits being supported. For stric limits the library makes a stronger -/// guarantee that the limit will not be exceeded. Exceeding a strict limit is considered -/// a critical bug. If a decoder cannot guarantee that it will uphold a strict limit it -/// *must* fail with `image::error::LimitErrorKind::Unsupported`. -/// -/// Currently the only strict limits supported are the `max_image_width` and `max_image_height` -/// limits, however more will be added in the future. [`LimitSupport`] will default to support -/// being false and decoders should enable support for the limits they support in -/// [`ImageDecoder::set_limits`]. -/// -/// The limit check should only ever fail if a limit will be exceeded or an unsupported strict -/// limit is used. -/// -/// [`LimitSupport`]: ./struct.LimitSupport.html -/// [`ImageDecoder::set_limits`]: ../trait.ImageDecoder.html#method.set_limits -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -#[allow(missing_copy_implementations)] -#[allow(clippy::manual_non_exhaustive)] -pub struct Limits { - /// The maximum allowed image width. This limit is strict. The default is no limit. - pub max_image_width: Option, - /// The maximum allowed image height. This limit is strict. The default is no limit. - pub max_image_height: Option, - /// The maximum allowed sum of allocations allocated by the decoder at any one time excluding - /// allocator overhead. This limit is non-strict by default and some decoders may ignore it. - /// The default is 512MiB. - pub max_alloc: Option, - _non_exhaustive: (), -} - -impl Default for Limits { - fn default() -> Limits { - Limits { - max_image_width: None, - max_image_height: None, - max_alloc: Some(512 * 1024 * 1024), - _non_exhaustive: (), - } - } -} - -impl Limits { - /// Disable all limits. - pub fn no_limits() -> Limits { - Limits { - max_image_width: None, - max_image_height: None, - max_alloc: None, - _non_exhaustive: (), - } - } - - /// This function checks that all currently set strict limits are supported. - pub fn check_support(&self, _supported: &LimitSupport) -> ImageResult<()> { - Ok(()) - } - - /// This function checks the `max_image_width` and `max_image_height` limits given - /// the image width and height. - pub fn check_dimensions(&self, width: u32, height: u32) -> ImageResult<()> { - if let Some(max_width) = self.max_image_width { - if width > max_width { - return Err(ImageError::Limits(error::LimitError::from_kind( - error::LimitErrorKind::DimensionError, - ))); - } - } - - if let Some(max_height) = self.max_image_height { - if height > max_height { - return Err(ImageError::Limits(error::LimitError::from_kind( - error::LimitErrorKind::DimensionError, - ))); - } - } - - Ok(()) - } - - /// This function checks that the current limit allows for reserving the set amount - /// of bytes, it then reduces the limit accordingly. - pub fn reserve(&mut self, amount: u64) -> ImageResult<()> { - if let Some(max_alloc) = self.max_alloc.as_mut() { - if *max_alloc < amount { - return Err(ImageError::Limits(error::LimitError::from_kind( - error::LimitErrorKind::InsufficientMemory, - ))); - } - - *max_alloc -= amount; - } - - Ok(()) - } - - /// This function acts identically to [`reserve`], but takes a `usize` for convenience. - pub fn reserve_usize(&mut self, amount: usize) -> ImageResult<()> { - match u64::try_from(amount) { - Ok(n) => self.reserve(n), - Err(_) if self.max_alloc.is_some() => Err(ImageError::Limits( - error::LimitError::from_kind(error::LimitErrorKind::InsufficientMemory), - )), - Err(_) => { - // Out of bounds, but we weren't asked to consider any limit. - Ok(()) - } - } - } - - /// This function acts identically to [`reserve`], but accepts the width, height and color type - /// used to create an [`ImageBuffer`] and does all the math for you. - pub fn reserve_buffer( - &mut self, - width: u32, - height: u32, - color_type: ColorType, - ) -> ImageResult<()> { - self.check_dimensions(width, height)?; - let in_memory_size = (width as u64) - .saturating_mul(height as u64) - .saturating_mul(color_type.bytes_per_pixel().into()); - self.reserve(in_memory_size)?; - Ok(()) - } - - /// This function increases the `max_alloc` limit with amount. Should only be used - /// together with [`reserve`]. - /// - /// [`reserve`]: #method.reserve - pub fn free(&mut self, amount: u64) { - if let Some(max_alloc) = self.max_alloc.as_mut() { - *max_alloc = max_alloc.saturating_add(amount); - } - } - - /// This function acts identically to [`free`], but takes a `usize` for convenience. - pub fn free_usize(&mut self, amount: usize) { - match u64::try_from(amount) { - Ok(n) => self.free(n), - Err(_) if self.max_alloc.is_some() => { - panic!("max_alloc is set, we should have exited earlier when the reserve failed"); - } - Err(_) => { - // Out of bounds, but we weren't asked to consider any limit. - } - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io/reader.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io/reader.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,239 +0,0 @@ -use std::fs::File; -use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom}; -use std::path::Path; - -use crate::dynimage::DynamicImage; -use crate::error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; -use crate::image::ImageFormat; -use crate::{ImageError, ImageResult}; - -use super::free_functions; - -/// A multi-format image reader. -/// -/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate -/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations. -/// -/// ## Usage -/// -/// Opening a file, deducing the format based on the file path automatically, and trying to decode -/// the image contained can be performed by constructing the reader and immediately consuming it. -/// -/// ```no_run -/// # use image::ImageError; -/// # use image::io::Reader; -/// # fn main() -> Result<(), ImageError> { -/// let image = Reader::open("path/to/image.png")? -/// .decode()?; -/// # Ok(()) } -/// ``` -/// -/// It is also possible to make a guess based on the content. This is especially handy if the -/// source is some blob in memory and you have constructed the reader in another way. Here is an -/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values. -/// -/// ``` -/// # use image::ImageError; -/// # use image::io::Reader; -/// # fn main() -> Result<(), ImageError> { -/// use std::io::Cursor; -/// use image::ImageFormat; -/// -/// let raw_data = b"P1 2 2\n\ -/// 0 1\n\ -/// 1 0\n"; -/// -/// let mut reader = Reader::new(Cursor::new(raw_data)) -/// .with_guessed_format() -/// .expect("Cursor io never fails"); -/// assert_eq!(reader.format(), Some(ImageFormat::Pnm)); -/// -/// # #[cfg(feature = "pnm")] -/// let image = reader.decode()?; -/// # Ok(()) } -/// ``` -/// -/// As a final fallback or if only a specific format must be used, the reader always allows manual -/// specification of the supposed image format with [`set_format`]. -/// -/// [`set_format`]: #method.set_format -/// [`ImageDecoder`]: ../trait.ImageDecoder.html -pub struct Reader { - /// The reader. Should be buffered. - inner: R, - /// The format, if one has been set or deduced. - format: Option, - /// Decoding limits - limits: super::Limits, -} - -impl Reader { - /// Create a new image reader without a preset format. - /// - /// Assumes the reader is already buffered. For optimal performance, - /// consider wrapping the reader with a `BufReader::new()`. - /// - /// It is possible to guess the format based on the content of the read object with - /// [`with_guessed_format`], or to set the format directly with [`set_format`]. - /// - /// [`with_guessed_format`]: #method.with_guessed_format - /// [`set_format`]: method.set_format - pub fn new(buffered_reader: R) -> Self { - Reader { - inner: buffered_reader, - format: None, - limits: super::Limits::default(), - } - } - - /// Construct a reader with specified format. - /// - /// Assumes the reader is already buffered. For optimal performance, - /// consider wrapping the reader with a `BufReader::new()`. - pub fn with_format(buffered_reader: R, format: ImageFormat) -> Self { - Reader { - inner: buffered_reader, - format: Some(format), - limits: super::Limits::default(), - } - } - - /// Get the currently determined format. - pub fn format(&self) -> Option { - self.format - } - - /// Supply the format as which to interpret the read image. - pub fn set_format(&mut self, format: ImageFormat) { - self.format = Some(format); - } - - /// Remove the current information on the image format. - /// - /// Note that many operations require format information to be present and will return e.g. an - /// `ImageError::Unsupported` when the image format has not been set. - pub fn clear_format(&mut self) { - self.format = None; - } - - /// Disable all decoding limits. - pub fn no_limits(&mut self) { - self.limits = super::Limits::no_limits(); - } - - /// Set a custom set of decoding limits. - pub fn limits(&mut self, limits: super::Limits) { - self.limits = limits; - } - - /// Unwrap the reader. - pub fn into_inner(self) -> R { - self.inner - } -} - -impl Reader> { - /// Open a file to read, format will be guessed from path. - /// - /// This will not attempt any io operation on the opened file. - /// - /// If you want to inspect the content for a better guess on the format, which does not depend - /// on file extensions, follow this call with a call to [`with_guessed_format`]. - /// - /// [`with_guessed_format`]: #method.with_guessed_format - pub fn open

(path: P) -> io::Result - where - P: AsRef, - { - Self::open_impl(path.as_ref()) - } - - fn open_impl(path: &Path) -> io::Result { - Ok(Reader { - inner: BufReader::new(File::open(path)?), - format: ImageFormat::from_path(path).ok(), - limits: super::Limits::default(), - }) - } -} - -impl Reader { - /// Make a format guess based on the content, replacing it on success. - /// - /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current - /// format if the guess was successful. If the guess was unable to determine a format then - /// the current format of the reader is unchanged. - /// - /// Returns an error if the underlying reader fails. The format is unchanged. The error is a - /// `std::io::Error` and not `ImageError` since the only error case is an error when the - /// underlying reader seeks. - /// - /// When an error occurs, the reader may not have been properly reset and it is potentially - /// hazardous to continue with more io. - /// - /// ## Usage - /// - /// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction. - /// This is more common in Linux and UNIX operating systems and also helpful if the path can - /// not be directly controlled. - /// - /// ```no_run - /// # use image::ImageError; - /// # use image::io::Reader; - /// # fn main() -> Result<(), ImageError> { - /// let image = Reader::open("image.unknown")? - /// .with_guessed_format()? - /// .decode()?; - /// # Ok(()) } - /// ``` - pub fn with_guessed_format(mut self) -> io::Result { - let format = self.guess_format()?; - // Replace format if found, keep current state if not. - self.format = format.or(self.format); - Ok(self) - } - - fn guess_format(&mut self) -> io::Result> { - let mut start = [0; 16]; - - // Save current offset, read start, restore offset. - let cur = self.inner.stream_position()?; - let len = io::copy( - // Accept shorter files but read at most 16 bytes. - &mut self.inner.by_ref().take(16), - &mut Cursor::new(&mut start[..]), - )?; - self.inner.seek(SeekFrom::Start(cur))?; - - Ok(free_functions::guess_format_impl(&start[..len as usize])) - } - - /// Read the image dimensions. - /// - /// Uses the current format to construct the correct reader for the format. - /// - /// If no format was determined, returns an `ImageError::Unsupported`. - pub fn into_dimensions(mut self) -> ImageResult<(u32, u32)> { - let format = self.require_format()?; - free_functions::image_dimensions_with_format_impl(self.inner, format) - } - - /// Read the image (replaces `load`). - /// - /// Uses the current format to construct the correct reader for the format. - /// - /// If no format was determined, returns an `ImageError::Unsupported`. - pub fn decode(mut self) -> ImageResult { - let format = self.require_format()?; - free_functions::load_inner(self.inner, self.limits, format) - } - - fn require_format(&mut self) -> ImageResult { - self.format.ok_or_else(|| { - ImageError::Unsupported(UnsupportedError::from_format_and_kind( - ImageFormatHint::Unknown, - UnsupportedErrorKind::Format(ImageFormatHint::Unknown), - )) - }) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/io.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +//! Input and output of images. + +use std::io; +use std::io::Read as _; + +/// The decoder traits. +pub(crate) mod decoder; +/// The encoder traits. +pub(crate) mod encoder; + +pub(crate) mod format; +pub(crate) mod free_functions; +pub(crate) mod image_reader_type; +pub(crate) mod limits; + +#[deprecated(note = "this type has been moved and renamed to image::ImageReader")] +/// Deprecated re-export of `ImageReader` as `Reader` +pub type Reader = ImageReader; +#[deprecated(note = "this type has been moved to image::Limits")] +/// Deprecated re-export of `Limits` +pub type Limits = limits::Limits; +#[deprecated(note = "this type has been moved to image::LimitSupport")] +/// Deprecated re-export of `LimitSupport` +pub type LimitSupport = limits::LimitSupport; + +pub(crate) use self::image_reader_type::ImageReader; + +/// Adds `read_exact_vec` +pub(crate) trait ReadExt { + fn read_exact_vec(&mut self, vec: &mut Vec, len: usize) -> io::Result<()>; +} + +impl ReadExt for R { + fn read_exact_vec(&mut self, vec: &mut Vec, len: usize) -> io::Result<()> { + let initial_len = vec.len(); + vec.try_reserve(len)?; + match self.take(len as u64).read_to_end(vec) { + Ok(read) if read == len => Ok(()), + fail => { + vec.truncate(initial_len); + Err(fail.err().unwrap_or(io::ErrorKind::UnexpectedEof.into())) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,7 +3,7 @@ //! This crate provides native rust implementations of image encoding and decoding as well as some //! basic image manipulation functions. Additional documentation can currently also be found in the //! [README.md file which is most easily viewed on -//! github](https://github.com/image-rs/image/blob/master/README.md). +//! github](https://github.com/image-rs/image/blob/main/README.md). //! //! There are two core problems for which this library provides solutions: a unified interface for image //! encodings and simple generic buffers for their content. It's possible to use either feature @@ -13,11 +13,11 @@ //! //! # High level API //! -//! Load images using [`io::Reader`]: +//! Load images using [`ImageReader`](crate::ImageReader): //! //! ```rust,no_run //! use std::io::Cursor; -//! use image::io::Reader as ImageReader; +//! use image::ImageReader; //! # fn main() -> Result<(), image::ImageError> { //! # let bytes = vec![0u8]; //! @@ -31,7 +31,7 @@ //! //! ```rust,no_run //! # use std::io::{Write, Cursor}; -//! # use image::{DynamicImage, ImageOutputFormat}; +//! # use image::{DynamicImage, ImageFormat}; //! # #[cfg(feature = "png")] //! # fn main() -> Result<(), image::ImageError> { //! # let img: DynamicImage = unimplemented!(); @@ -39,7 +39,7 @@ //! img.save("empty.jpg")?; //! //! let mut bytes: Vec = Vec::new(); -//! img2.write_to(&mut Cursor::new(&mut bytes), image::ImageOutputFormat::Png)?; +//! img2.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)?; //! # Ok(()) //! # } //! # #[cfg(not(feature = "png"))] fn main() {} @@ -49,20 +49,20 @@ //! //! [`save`]: enum.DynamicImage.html#method.save //! [`write_to`]: enum.DynamicImage.html#method.write_to -//! [`io::Reader`]: io/struct.Reader.html +//! [`ImageReader`]: struct.Reader.html //! //! # Image buffers //! //! The two main types for storing images: //! * [`ImageBuffer`] which holds statically typed image contents. -//! * [`DynamicImage`] which is an enum over the supported ImageBuffer formats -//! and supports conversions between them. +//! * [`DynamicImage`] which is an enum over the supported `ImageBuffer` formats +//! and supports conversions between them. //! //! As well as a few more specialized options: //! * [`GenericImage`] trait for a mutable image buffer. -//! * [`GenericImageView`] trait for read only references to a GenericImage. +//! * [`GenericImageView`] trait for read only references to a `GenericImage`. //! * [`flat`] module containing types for interoperability with generic channel -//! matrices and foreign interfaces. +//! matrices and foreign interfaces. //! //! [`GenericImageView`]: trait.GenericImageView.html //! [`GenericImage`]: trait.GenericImage.html @@ -91,14 +91,14 @@ //! While [`ImageDecoder`] and [`ImageDecoderRect`] give access to more advanced decoding options: //! //! ```rust,no_run -//! # use std::io::Read; +//! # use std::io::{BufReader, Cursor}; //! # use image::DynamicImage; //! # use image::ImageDecoder; //! # #[cfg(feature = "png")] //! # fn main() -> Result<(), image::ImageError> { //! # use image::codecs::png::PngDecoder; //! # let img: DynamicImage = unimplemented!(); -//! # let reader: Box = unimplemented!(); +//! # let reader: BufReader> = unimplemented!(); //! let decoder = PngDecoder::new(&mut reader)?; //! let icc = decoder.icc_profile(); //! let img = DynamicImage::from_decoder(decoder)?; @@ -117,9 +117,7 @@ #![deny(deprecated)] #![deny(missing_copy_implementations)] #![cfg_attr(all(test, feature = "benchmarks"), feature(test))] -// it's a backwards compatibility break -#![allow(clippy::wrong_self_convention, clippy::enum_variant_names)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(all(test, feature = "benchmarks"))] extern crate test; @@ -134,22 +132,12 @@ pub use crate::error::{ImageError, ImageResult}; -pub use crate::image::{ - AnimationDecoder, - GenericImage, - GenericImageView, - ImageDecoder, - ImageDecoderRect, - ImageEncoder, - ImageFormat, - ImageOutputFormat, - // Iterators - Pixels, - Progress, - SubImage, -}; +pub use crate::images::generic_image::{GenericImage, GenericImageView, Pixels}; + +pub use crate::images::sub_image::SubImage; -pub use crate::buffer_::{ +pub use crate::images::buffer::{ + ConvertColorOptions, GrayAlphaImage, GrayImage, // Image types @@ -166,13 +154,21 @@ pub use crate::traits::{EncodableLayout, Pixel, PixelWithColorType, Primitive}; // Opening and loading images -pub use crate::dynimage::{ - image_dimensions, load_from_memory, load_from_memory_with_format, open, save_buffer, - save_buffer_with_format, write_buffer_with_format, +pub use crate::images::dynimage::{ + image_dimensions, load_from_memory, load_from_memory_with_format, open, + write_buffer_with_format, }; -pub use crate::io::free_functions::{guess_format, load}; +pub use crate::io::free_functions::{guess_format, load, save_buffer, save_buffer_with_format}; -pub use crate::dynimage::DynamicImage; +pub use crate::io::{ + decoder::{AnimationDecoder, ImageDecoder, ImageDecoderRect}, + encoder::ImageEncoder, + format::ImageFormat, + image_reader_type::ImageReader, + limits::{LimitSupport, Limits}, +}; + +pub use crate::images::dynimage::DynamicImage; pub use crate::animation::{Delay, Frame, Frames}; @@ -182,13 +178,13 @@ /// Iterators and other auxiliary structure for the `ImageBuffer` type. pub mod buffer { // Only those not exported at the top-level - pub use crate::buffer_::{ + pub use crate::images::buffer::{ ConvertBuffer, EnumeratePixels, EnumeratePixelsMut, EnumerateRows, EnumerateRowsMut, Pixels, PixelsMut, Rows, RowsMut, }; #[cfg(feature = "rayon")] - pub use crate::buffer_par::*; + pub use crate::images::buffer_par::*; } // Math utils @@ -197,35 +193,30 @@ // Image processing functions pub mod imageops; -// Io bindings -pub mod io; - // Buffer representations for ffi. -pub mod flat; +pub use crate::images::flat; /// Encoding and decoding for various image file formats. /// /// # Supported formats /// -/// -/// -/// | Format | Decoding | Encoding | -/// | -------- | ----------------------------------------- | --------------------------------------- | -/// | AVIF | Only 8-bit | Lossy | -/// | BMP | Yes | Rgb8, Rgba8, Gray8, GrayA8 | -/// | DDS | DXT1, DXT3, DXT5 | No | -/// | Farbfeld | Yes | Yes | -/// | GIF | Yes | Yes | -/// | HDR | Yes | Yes | -/// | ICO | Yes | Yes | -/// | JPEG | Baseline and progressive | Baseline JPEG | -/// | OpenEXR | Rgb32F, Rgba32F (no dwa compression) | Rgb32F, Rgba32F (no dwa compression) | -/// | PNG | All supported color types | Same as decoding | -/// | PNM | PBM, PGM, PPM, standard PAM | Yes | -/// | QOI | Yes | Yes | -/// | TGA | Yes | Rgb8, Rgba8, Bgr8, Bgra8, Gray8, GrayA8 | -/// | TIFF | Baseline(no fax support) + LZW + PackBits | Rgb8, Rgba8, Gray8 | -/// | WebP | Yes | Rgb8, Rgba8 | +/// | Feature | Format | Notes +/// | ------- | -------- | ----- +/// | `avif` | AVIF | Decoding requires the `avif-native` feature, uses the libdav1d C library. +/// | `bmp` | BMP | +/// | `dds` | DDS | Only decoding is supported. +/// | `exr` | OpenEXR | +/// | `ff` | Farbfeld | +/// | `gif` | GIF | +/// | `hdr` | HDR | +/// | `ico` | ICO | +/// | `jpeg` | JPEG | +/// | `png` | PNG | +/// | `pnm` | PNM | +/// | `qoi` | QOI | +/// | `tga` | TGA | +/// | `tiff` | TIFF | +/// | `webp` | WebP | Only lossless encoding is currently supported. /// /// ## A note on format specific features /// @@ -249,16 +240,13 @@ /// /// Re-exports of dependencies that reach version `1` will be discussed when it happens. pub mod codecs { - #[cfg(any(feature = "avif-encoder", feature = "avif-decoder"))] + #[cfg(any(feature = "avif", feature = "avif-native"))] pub mod avif; #[cfg(feature = "bmp")] pub mod bmp; #[cfg(feature = "dds")] pub mod dds; - #[cfg(feature = "dxt")] - #[deprecated = "DXT support will be removed or reworked in a future version. Prefer the `squish` crate instead. See https://github.com/image-rs/image/issues/1623"] - pub mod dxt; - #[cfg(feature = "farbfeld")] + #[cfg(feature = "ff")] pub mod farbfeld; #[cfg(feature = "gif")] pub mod gif; @@ -282,16 +270,20 @@ pub mod tiff; #[cfg(feature = "webp")] pub mod webp; + + #[cfg(feature = "dds")] + mod dxt; } mod animation; -#[path = "buffer.rs"] -mod buffer_; -#[cfg(feature = "rayon")] -mod buffer_par; mod color; -mod dynimage; -mod image; +pub mod hooks; +mod images; +/// Deprecated io module the original io module has been renamed to `image_reader`. +/// This is going to be internal. +pub mod io; +pub mod metadata; +//TODO delete this module after a few releases mod traits; mod utils; @@ -307,7 +299,7 @@ macro_rules! insert_as_doc { { $content:expr } => { #[allow(unused_doc_comments)] - #[doc = $content] extern { } + #[doc = $content] extern "Rust" { } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,4 +3,5 @@ mod utils; pub use self::rect::Rect; +pub(crate) use utils::multiply_accumulate; pub(super) use utils::resize_dimensions; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/rect.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/rect.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/rect.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/rect.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,6 @@ /// A Rectangle defined by its top left corner, width and height. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Rect { /// The x coordinate of the top left corner. pub x: u32, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/utils.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/math/utils.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/math/utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,50 @@ //! Shared mathematical utility functions. - use std::cmp::max; +use std::ops::{Add, Mul}; + +use num_traits::MulAdd; + +#[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + all(target_arch = "aarch64", target_feature = "neon") +))] +#[inline(always)] +/// Uses fused multiply add when available +/// +/// It is important not to call it if FMA flag is not turned on, +/// Rust inserts libc `fmaf` based implementation here if FMA is clearly not available at compile time. +/// This needs for speed only, one rounding error don't do anything useful here, thus it's blocked when +/// we can't detect FMA availability at compile time. +pub(crate) fn multiply_accumulate< + T: Copy + Mul + Add + MulAdd, +>( + acc: T, + a: T, + b: T, +) -> T { + MulAdd::mul_add(a, b, acc) +} + +#[inline(always)] +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + all(target_arch = "aarch64", target_feature = "neon") +)))] +pub(crate) fn multiply_accumulate< + T: Copy + Mul + Add + MulAdd, +>( + acc: T, + a: T, + b: T, +) -> T { + acc + a * b +} /// Calculates the width and height an image should be resized to. /// This preserves aspect ratio, and based on the `fill` parameter @@ -16,8 +60,8 @@ nheight: u32, fill: bool, ) -> (u32, u32) { - let wratio = nwidth as f64 / width as f64; - let hratio = nheight as f64 / height as f64; + let wratio = f64::from(nwidth) / f64::from(width); + let hratio = f64::from(nheight) / f64::from(height); let ratio = if fill { f64::max(wratio, hratio) @@ -25,15 +69,15 @@ f64::min(wratio, hratio) }; - let nw = max((width as f64 * ratio).round() as u64, 1); - let nh = max((height as f64 * ratio).round() as u64, 1); + let nw = max((f64::from(width) * ratio).round() as u64, 1); + let nh = max((f64::from(height) * ratio).round() as u64, 1); if nw > u64::from(u32::MAX) { - let ratio = u32::MAX as f64 / width as f64; - (u32::MAX, max((height as f64 * ratio).round() as u32, 1)) + let ratio = f64::from(u32::MAX) / f64::from(width); + (u32::MAX, max((f64::from(height) * ratio).round() as u32, 1)) } else if nh > u64::from(u32::MAX) { - let ratio = u32::MAX as f64 / height as f64; - (max((width as f64 * ratio).round() as u32, 1), u32::MAX) + let ratio = f64::from(u32::MAX) / f64::from(height); + (max((f64::from(width) * ratio).round() as u32, 1), u32::MAX) } else { (nw as u32, nh as u32) } @@ -46,10 +90,10 @@ if old_w == 0 || new_w == 0 { return true; } // In this case, the scaling is limited by scaling of height. // We could check that case separately but it does not conform to the same expectation. - if new_w as u64 * 400u64 >= old_w as u64 * u64::from(u32::MAX) { return true; } + if u64::from(new_w) * 400u64 >= u64::from(old_w) * u64::from(u32::MAX) { return true; } - let result = super::resize_dimensions(old_w, 400, new_w, ::std::u32::MAX, false); - let exact = (400_f64 * new_w as f64 / old_w as f64).round() as u32; + let result = super::resize_dimensions(old_w, 400, new_w, u32::MAX, false); + let exact = (400_f64 * f64::from(new_w) / f64::from(old_w)).round() as u32; result.0 == new_w && result.1 == exact.max(1) } } @@ -59,10 +103,10 @@ if old_h == 0 || new_h == 0 { return true; } // In this case, the scaling is limited by scaling of width. // We could check that case separately but it does not conform to the same expectation. - if 400u64 * new_h as u64 >= old_h as u64 * u64::from(u32::MAX) { return true; } + if 400u64 * u64::from(new_h) >= u64::from(old_h) * u64::from(u32::MAX) { return true; } - let result = super::resize_dimensions(400, old_h, ::std::u32::MAX, new_h, false); - let exact = (400_f64 * new_h as f64 / old_h as f64).round() as u32; + let result = super::resize_dimensions(400, old_h, u32::MAX, new_h, false); + let exact = (400_f64 * f64::from(new_h) / f64::from(old_h)).round() as u32; result.1 == new_h && result.0 == exact.max(1) } } @@ -87,12 +131,12 @@ #[test] fn resize_handles_overflow() { - let result = super::resize_dimensions(100, ::std::u32::MAX, 200, ::std::u32::MAX, true); + let result = super::resize_dimensions(100, u32::MAX, 200, u32::MAX, true); assert!(result.0 == 100); - assert!(result.1 == ::std::u32::MAX); + assert!(result.1 == u32::MAX); - let result = super::resize_dimensions(::std::u32::MAX, 100, ::std::u32::MAX, 200, true); - assert!(result.0 == ::std::u32::MAX); + let result = super::resize_dimensions(u32::MAX, 100, u32::MAX, 200, true); + assert!(result.0 == u32::MAX); assert!(result.1 == 100); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/metadata/cicp.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata/cicp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/metadata/cicp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata/cicp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1632 @@ +use std::sync::Arc; + +/// CICP (coding independent code points) defines the colorimetric interpretation of rgb-ish color +/// components. +use crate::{ + color::FromPrimitive, + error::{ParameterError, ParameterErrorKind}, + math::multiply_accumulate, + traits::{ + private::{LayoutWithColor, SealedPixelWithColorType}, + PixelWithColorType, + }, + utils::vec_try_with_capacity, + DynamicImage, ImageError, Pixel, Primitive, +}; + +/// Reference: (V4) +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub struct Cicp { + /// Defines the exact color of red, green, blue primary colors. + pub primaries: CicpColorPrimaries, + /// The electro-optical transfer function (EOTF) that maps color components to linear values. + pub transfer: CicpTransferCharacteristics, + /// A matrix between linear values and primary color representation. + /// + /// For an RGB space this is the identity matrix. + pub matrix: CicpMatrixCoefficients, + /// Whether the color components use all bits of the encoded values, or have headroom. + /// + /// For compute purposes, `image` only supports [`CicpVideoFullRangeFlag::FullRange`] and you + /// get errors when trying to pass a non-full-range color profile to transform APIs such as + /// [`DynamicImage::apply_color_space`] or [`CicpTransform::new`]. + pub full_range: CicpVideoFullRangeFlag, +} + +/// An internal representation of what our `T: PixelWithColorType` can do, i.e. ImageBuffer. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub(crate) struct CicpRgb { + pub(crate) primaries: CicpColorPrimaries, + pub(crate) transfer: CicpTransferCharacteristics, + pub(crate) luminance: DerivedLuminance, +} + +/// Defines the exact color of red, green, blue primary colors. +/// +/// Each set defines the CIE 1931 XYZ (2°) color space coordinates of the primary colors and an +/// illuminant/whitepoint under which those colors are viewed. +/// +/// Refer to Rec H.273 Table 2. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[non_exhaustive] +pub enum CicpColorPrimaries { + /// ITU-R BT.709-6 + SRgb = 1, + /// Explicitly, the color space is not determined. + Unspecified = 2, + /// ITU-R BT.470-6 System M + RgbM = 4, + /// ITU-R BT.470-6 System B, G + RgbB = 5, + /// SMPTE 170M + /// functionally equivalent to 7 + Bt601 = 6, + /// SMPTE 240M + /// functionally equivalent to 6 + Rgb240m = 7, + /// Generic film (colour filters using Illuminant C) + GenericFilm = 8, + /// Rec. ITU-R BT.2020-2 + /// Rec. ITU-R BT.2100-2 + Rgb2020 = 9, + /// SMPTE ST 428-1 + /// + /// (CIE 1931 XYZ as in ISO/CIE 11664-1) + Xyz = 10, + /// SMPTE RP 431-2 (aka. DCI P3) + SmpteRp431 = 11, + /// SMPTE EG 432-1, DCI P3 variant with the D65 whitepoint (matching sRGB and BT.2020) + SmpteRp432 = 12, + /// Corresponds to value 22 but + /// + /// > No corresponding industry specification identified + /// + /// But moxcms identifies it as EBU Tech 3213-E: + /// + /// However, there are some differences in the second digit of red's CIE 1931 and the precision + /// is only 2 digits whereas CICP names three; so unsure if this is fully accurate as the + /// actual source material. + Industry22 = 22, +} + +impl CicpColorPrimaries { + fn to_moxcms(self) -> moxcms::CicpColorPrimaries { + use moxcms::CicpColorPrimaries as M; + + match self { + CicpColorPrimaries::SRgb => M::Bt709, + CicpColorPrimaries::Unspecified => M::Unspecified, + CicpColorPrimaries::RgbM => M::Bt470M, + CicpColorPrimaries::RgbB => M::Bt470Bg, + CicpColorPrimaries::Bt601 => M::Bt601, + CicpColorPrimaries::Rgb240m => M::Smpte240, + CicpColorPrimaries::GenericFilm => M::GenericFilm, + CicpColorPrimaries::Rgb2020 => M::Bt2020, + CicpColorPrimaries::Xyz => M::Xyz, + CicpColorPrimaries::SmpteRp431 => M::Smpte431, + CicpColorPrimaries::SmpteRp432 => M::Smpte432, + CicpColorPrimaries::Industry22 => M::Ebu3213, + } + } +} + +/// The transfer characteristics, expressing relation between encoded values and linear color +/// values. +/// +/// Refer to Rec H.273 Table 3. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[non_exhaustive] +pub enum CicpTransferCharacteristics { + /// Rec. ITU-R BT.709-6 + /// Rec. ITU-R BT.1361-0 conventional + /// (functionally the same as the values 6, 14 and 15) + Bt709 = 1, + /// Explicitly, the transfer characteristics are not determined. + Unspecified = 2, + /// Rec. ITU-R BT.470-6 System M (historical) + /// United States National Television System Committee 1953 Recommendation for transmission standards for color television + /// United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20) + /// Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM + /// + /// Assumed gamma of 2.2 + Bt470M = 4, + /// Rec. ITU-R BT.470-6 System B, G (historical) + Bt470BG = 5, + /// Rec. ITU-R BT.601-7 525 or 625 + /// Rec. ITU-R BT.1358-1 525 or 625 (historical) + /// Rec. ITU-R BT.1700-0 NTSC + /// SMPTE ST 170 (functionally the same as the values 1, 14 and 15) + Bt601 = 6, + /// SMPTE ST 240 + Smpte240m = 7, + /// Linear transfer characteristics + Linear = 8, + /// Logarithmic transfer characteristic (100:1 range) + Log100 = 9, + /// Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range) + LogSqrt = 10, + /// IEC 61966-2-4 + Iec61966_2_4 = 11, + /// Rec. ITU-R BT.1361-0 extended colour gamut system (historical) + Bt1361 = 12, + /// IEC 61966-2-1 sRGB (with MatrixCoefficients equal to 0) + /// IEC 61966-2-1 sYCC (with MatrixCoefficients equal to 5) + SRgb = 13, + /// Rec. ITU-R BT.2020-2 (10-bit system) + /// (functionally the same as the values 1, 6 and 15) + Bt2020_10bit = 14, + /// Rec. ITU-R BT.2020-2 (12-bit system) + /// (functionally the same as the values 1, 6 and 14) + Bt2020_12bit = 15, + /// SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + /// Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system + Smpte2084 = 16, + /// SMPTE ST 428-1 + Smpte428 = 17, + /// ARIB STD-B67 + /// Rec. ITU-R BT.2100-2 hybrid log- gamma (HLG) system + Bt2100Hlg = 18, +} + +impl CicpTransferCharacteristics { + fn to_moxcms(self) -> moxcms::TransferCharacteristics { + use moxcms::TransferCharacteristics as T; + + match self { + CicpTransferCharacteristics::Bt709 => T::Bt709, + CicpTransferCharacteristics::Unspecified => T::Unspecified, + CicpTransferCharacteristics::Bt470M => T::Bt470M, + CicpTransferCharacteristics::Bt470BG => T::Bt470Bg, + CicpTransferCharacteristics::Bt601 => T::Bt601, + CicpTransferCharacteristics::Smpte240m => T::Smpte240, + CicpTransferCharacteristics::Linear => T::Linear, + CicpTransferCharacteristics::Log100 => T::Log100, + CicpTransferCharacteristics::LogSqrt => T::Log100sqrt10, + CicpTransferCharacteristics::Iec61966_2_4 => T::Iec61966, + CicpTransferCharacteristics::Bt1361 => T::Bt1361, + CicpTransferCharacteristics::SRgb => T::Srgb, + CicpTransferCharacteristics::Bt2020_10bit => T::Bt202010bit, + CicpTransferCharacteristics::Bt2020_12bit => T::Bt202012bit, + CicpTransferCharacteristics::Smpte2084 => T::Smpte2084, + CicpTransferCharacteristics::Smpte428 => T::Smpte428, + CicpTransferCharacteristics::Bt2100Hlg => T::Hlg, + } + } +} + +/// +/// Refer to Rec H.273 Table 4. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[non_exhaustive] +pub enum CicpMatrixCoefficients { + /// The identity matrix. + /// Typically used for GBR (often referred to as RGB); however, may also be used for YZX (often referred to as XYZ); + /// IEC 61966-2-1 sRGB + /// SMPTE ST 428-1 + Identity = 0, + /// Rec. ITU-R BT.709-6 + /// Rec. ITU-R BT.1361-0 conventional colour gamut system and extended colour gamut system (historical) + /// IEC 61966-2-4 xvYCC709 + /// SMPTE RP 177 Annex B + Bt709 = 1, + /// Explicitly, the matrix coefficients are not determined. + Unspecified = 2, + /// United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20) + UsFCC = 4, + /// Rec. ITU-R BT.470-6 System B, G (historical) + /// Rec. ITU-R BT.601-7 625 + /// Rec. ITU-R BT.1358-0 625 (historical) + /// Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM + /// IEC 61966-2-1 sYCC + /// IEC 61966-2-4 xvYCC601 + /// (functionally the same as the value 6) + Bt470BG = 5, + /// (functionally the same as the value 5) + Smpte170m = 6, + /// SMPTE ST 240 + Smpte240m = 7, + /// YCgCo + YCgCo = 8, + /// Rec. ITU-R BT.2020-2 (non-constant luminance) + /// Rec. ITU-R BT.2100-2 Y′CbCr + Bt2020NonConstant = 9, + /// Rec. ITU-R BT.2020-2 (constant luminance) + Bt2020Constant = 10, + /// SMPTE ST 2085 + Smpte2085 = 11, + /// Chromaticity-derived non-constant luminance system + ChromaticityDerivedNonConstant = 12, + /// Chromaticity-derived constant luminance system + ChromaticityDerivedConstant = 13, + /// Rec. ITU-R BT.2100-2 ICTCp + Bt2100 = 14, + /// Colour representation developed in SMPTE as IPT-PQ-C2. + IptPqC2 = 15, + /// YCgCo with added bit-depth (2-bit). + YCgCoRe = 16, + /// YCgCo with added bit-depth (1-bit). + YCgCoRo = 17, +} + +impl CicpMatrixCoefficients { + fn to_moxcms(self) -> Option { + use moxcms::MatrixCoefficients as M; + + Some(match self { + CicpMatrixCoefficients::Identity => M::Identity, + CicpMatrixCoefficients::Unspecified => M::Unspecified, + CicpMatrixCoefficients::Bt709 => M::Bt709, + CicpMatrixCoefficients::UsFCC => M::Fcc, + CicpMatrixCoefficients::Bt470BG => M::Bt470Bg, + CicpMatrixCoefficients::Smpte170m => M::Smpte170m, + CicpMatrixCoefficients::Smpte240m => M::Smpte240m, + CicpMatrixCoefficients::YCgCo => M::YCgCo, + CicpMatrixCoefficients::Bt2020NonConstant => M::Bt2020Ncl, + CicpMatrixCoefficients::Bt2020Constant => M::Bt2020Cl, + CicpMatrixCoefficients::Smpte2085 => M::Smpte2085, + CicpMatrixCoefficients::ChromaticityDerivedNonConstant => M::ChromaticityDerivedNCL, + CicpMatrixCoefficients::ChromaticityDerivedConstant => M::ChromaticityDerivedCL, + CicpMatrixCoefficients::Bt2100 => M::ICtCp, + CicpMatrixCoefficients::IptPqC2 + | CicpMatrixCoefficients::YCgCoRe + | CicpMatrixCoefficients::YCgCoRo => return None, + }) + } +} + +/// The used encoded value range. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[non_exhaustive] +pub enum CicpVideoFullRangeFlag { + /// The color components are encoded in a limited range, e.g., 16-235 for 8-bit. + /// + /// Do note that `image` does not support computing with this setting (yet). + NarrowRange = 0, + /// The color components are encoded in the full range, e.g., 0-255 for 8-bit. + FullRange = 1, +} + +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub(crate) enum DerivedLuminance { + /// Luminance is calculated in linear space: + /// Y' = dot(K_rgb, RGB)' + #[allow(dead_code)] // We do not support this yet but should prepare call sites for the + // eventuality. + Constant, + /// Luminance is calculated in the transferred space: + /// Y' = dot(K_rgb, RGB') + NonConstant, +} + +/// Apply to colors of the input color space to get output color values. +/// +/// We do not support all possible Cicp color spaces, but when we support one then all builtin +/// `Pixel` types can be converted with their respective components. This value is used to signify +/// that some particular combination is supported. +#[derive(Clone)] +pub struct CicpTransform { + from: Cicp, + into: Cicp, + u8: RgbTransforms, + u16: RgbTransforms, + f32: RgbTransforms, + // Converting RGB to Y in the output. + output_coefs: [f32; 3], +} + +pub(crate) type CicpApplicable<'lt, C> = dyn Fn(&[C], &mut [C]) + Send + Sync + 'lt; + +#[derive(Clone)] +struct RgbTransforms { + slices: [Arc>; 4], + luma_rgb: [Arc>; 4], + rgb_luma: [Arc>; 4], + luma_luma: [Arc>; 4], +} + +impl CicpTransform { + /// Construct a transform between two color spaces. + /// + /// Returns `Some` if the transform is guaranteed to be supported by `image`. Both color spaces + /// are well understood and can be expected to be supported in future versions. However, we do + /// not make guarantees about adjusting the rounding modes, accuracy, and exact numeric values + /// used in the transform. Also, out-of-gamut colors may be handled differently per API. + /// + /// Returns `None` if the transformation is not (yet) supported. + /// + /// This is used with [`ConvertColorOptions`][`crate::ConvertColorOptions`] in + /// [`ImageBuffer::copy_from_color_space`][`crate::ImageBuffer::copy_from_color_space`], + /// [`DynamicImage::copy_from_color_space`][`DynamicImage::copy_from_color_space`]. + pub fn new(from: Cicp, into: Cicp) -> Option { + if !from.qualify_stability() || !into.qualify_stability() { + // To avoid regressions, we do not support all kinds of transforms from the start. + // Instead, a selected list will be gradually enlarged as more in-depth tests are done + // and the selected implementation library is checked for suitability in use. + return None; + } + + // Unused, but introduces symmetry to the supported color space transforms. That said we + // calculate the derived luminance coefficients for all color that have a matching moxcms + // profile so this really should not block anything. + let _input_coefs = from.into_rgb().derived_luminance()?; + let output_coefs = into.into_rgb().derived_luminance()?; + + let mox_from = from.to_moxcms_compute_profile()?; + let mox_into = into.to_moxcms_compute_profile()?; + + let opt = moxcms::TransformOptions::default(); + + let f32_fallback = { + let try_f32 = Self::LAYOUTS.map(|(from_layout, into_layout)| { + let (from, from_layout) = mox_from.map_layout(from_layout); + let (into, into_layout) = mox_into.map_layout(into_layout); + + from.create_transform_f32(from_layout, into, into_layout, opt) + .map(Arc:: + Send + Sync>::from) + .ok() + }); + + if try_f32.iter().any(Option::is_none) { + return None; + } + + try_f32.map(Option::unwrap) + }; + + // TODO: really these should be lazy, eh? + Some(CicpTransform { + from, + into, + u8: Self::build_transforms( + Self::LAYOUTS.map(|(from_layout, into_layout)| { + let (from, from_layout) = mox_from.map_layout(from_layout); + let (into, into_layout) = mox_into.map_layout(into_layout); + + from.create_transform_8bit(from_layout, into, into_layout, opt) + .map(Arc:: + Send + Sync>::from) + .ok() + }), + f32_fallback.clone(), + output_coefs, + )?, + u16: Self::build_transforms( + Self::LAYOUTS.map(|(from_layout, into_layout)| { + let (from, from_layout) = mox_from.map_layout(from_layout); + let (into, into_layout) = mox_into.map_layout(into_layout); + + from.create_transform_16bit(from_layout, into, into_layout, opt) + .map(Arc:: + Send + Sync>::from) + .ok() + }), + f32_fallback.clone(), + output_coefs, + )?, + f32: Self::build_transforms( + f32_fallback.clone().map(Some), + f32_fallback.clone(), + output_coefs, + )?, + output_coefs, + }) + } + + /// For a Pixel with known color layout (`ColorType`) get a transform that is accurate. + /// + /// This returns `None` if we do not support the transform. At writing that is true for + /// instance for transforms involved 'Luma` pixels which are interpreted as the `Y` in a + /// `YCbCr` color based off the actual whitepoint, with coefficients according to each + /// primary's luminance. Only Rgb transforms are supported via `moxcms`. + /// + /// Maybe provide publicly? + pub(crate) fn supported_transform_fn( + &self, + ) -> &'_ CicpApplicable<'_, From::Subpixel> { + use crate::traits::private::double_dispatch_transform_from_sealed; + double_dispatch_transform_from_sealed::(self) + } + + /// Does this transform realize the conversion `from` to `into`. + pub(crate) fn check_applicable(&self, from: Cicp, into: Cicp) -> Result<(), ImageError> { + let check_expectation = |expected, found| { + if expected == found { + Ok(()) + } else { + Err(ParameterError::from_kind( + ParameterErrorKind::CicpMismatch { expected, found }, + )) + } + }; + + check_expectation(self.from, from).map_err(ImageError::Parameter)?; + check_expectation(self.into, into).map_err(ImageError::Parameter)?; + + Ok(()) + } + + fn build_transforms( + trs: [Option + Send + Sync>>; 4], + f32: [Arc + Send + Sync>; 4], + output_coef: [f32; 3], + ) -> Option> { + // We would use `[array]::try_map` here, but it is not stable yet. + if trs.iter().any(Option::is_none) { + return None; + } + + let trs = trs.map(Option::unwrap); + + // rgb-rgb transforms are done directly via moxcms. + let slices = trs.clone().map(|tr| { + Arc::new(move |input: &[P], output: &mut [P]| { + tr.transform(input, output).expect("transform failed") + }) as Arc + }); + + const N: usize = 256; + + // luma-rgb transforms expand the Luma to Rgb (and LumaAlpha to Rgba) + let luma_rgb = { + let [tr33, tr34, tr43, tr44] = f32.clone(); + + [ + Arc::new(move |input: &[P], output: &mut [P]| { + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (luma, output) in input.chunks(N).zip(output.chunks_mut(3 * N)) { + let n = luma.len(); + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_luma_rgb(luma, ibuffer); + tr33.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb(obuffer, output); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (luma, output) in input.chunks(N).zip(output.chunks_mut(4 * N)) { + let n = luma.len(); + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_luma_rgb(luma, ibuffer); + tr34.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba(obuffer, output); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (luma, output) in input.chunks(2 * N).zip(output.chunks_mut(3 * N)) { + let n = luma.len() / 2; + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_luma_rgba(luma, ibuffer); + tr43.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb(obuffer, output); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (luma, output) in input.chunks(2 * N).zip(output.chunks_mut(4 * N)) { + let n = luma.len() / 2; + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_luma_rgba(luma, ibuffer); + tr44.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba(obuffer, output); + } + }) as Arc, + ] + }; + + // rgb-luma transforms contract Rgb to Luma (and Rgba to LumaAlpha) + let rgb_luma = { + let [tr33, tr34, tr43, tr44] = f32.clone(); + + [ + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 3, output.len()); + + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (rgb, output) in input.chunks(3 * N).zip(output.chunks_mut(N)) { + let n = output.len(); + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_rgb(rgb, ibuffer); + tr33.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 3, output.len() / 2); + + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (rgb, output) in input.chunks(4 * N).zip(output.chunks_mut(2 * N)) { + let n = output.len() / 2; + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_rgb(rgb, ibuffer); + tr34.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 4, output.len()); + + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (rgba, output) in input.chunks(4 * N).zip(output.chunks_mut(N)) { + let n = output.len(); + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_rgba(rgba, ibuffer); + tr43.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 4, output.len() / 2); + + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (rgba, output) in input.chunks(4 * N).zip(output.chunks_mut(2 * N)) { + let n = output.len() / 2; + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_rgba(rgba, ibuffer); + tr44.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba_luma(obuffer, output, output_coef); + } + }) as Arc, + ] + }; + + // luma-luma both expand and contract + let luma_luma = { + let [tr33, tr34, tr43, tr44] = f32.clone(); + + [ + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len(), output.len()); + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (luma, output) in input.chunks(N).zip(output.chunks_mut(N)) { + let n = luma.len(); + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_luma_rgb(luma, ibuffer); + tr33.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len(), output.len() / 2); + let mut ibuffer = [0.0f32; 3 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (luma, output) in input.chunks(N).zip(output.chunks_mut(2 * N)) { + let n = luma.len(); + let ibuffer = &mut ibuffer[..3 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_luma_rgb(luma, ibuffer); + tr34.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 2, output.len()); + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 3 * N]; + + for (luma, output) in input.chunks(2 * N).zip(output.chunks_mut(N)) { + let n = luma.len() / 2; + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..3 * n]; + Self::expand_luma_rgba(luma, ibuffer); + tr43.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgb_luma(obuffer, output, output_coef); + } + }) as Arc, + Arc::new(move |input: &[P], output: &mut [P]| { + debug_assert_eq!(input.len() / 2, output.len() / 2); + let mut ibuffer = [0.0f32; 4 * N]; + let mut obuffer = [0.0f32; 4 * N]; + + for (luma, output) in input.chunks(2 * N).zip(output.chunks_mut(2 * N)) { + let n = luma.len() / 2; + let ibuffer = &mut ibuffer[..4 * n]; + let obuffer = &mut obuffer[..4 * n]; + Self::expand_luma_rgba(luma, ibuffer); + tr44.transform(ibuffer, obuffer).expect("transform failed"); + Self::clamp_rgba_luma(obuffer, output, output_coef); + } + }) as Arc, + ] + }; + + Some(RgbTransforms { + slices, + luma_rgb, + rgb_luma, + luma_luma, + }) + } + + pub(crate) fn transform_dynamic(&self, lhs: &mut DynamicImage, rhs: &DynamicImage) { + const STEP: usize = 256; + + let mut ibuffer = [0.0f32; 4 * STEP]; + let mut obuffer = [0.0f32; 4 * STEP]; + + let pixels = (u64::from(lhs.width()) * u64::from(lhs.height())) as usize; + + let input_samples; + let output_samples; + + let inner_transform = match ( + LayoutWithColor::from(lhs.color()), + LayoutWithColor::from(rhs.color()), + ) { + ( + LayoutWithColor::Luma | LayoutWithColor::Rgb, + LayoutWithColor::Luma | LayoutWithColor::Rgb, + ) => { + output_samples = 3; + input_samples = 3; + &*self.f32.slices[0] + } + ( + LayoutWithColor::LumaAlpha | LayoutWithColor::Rgba, + LayoutWithColor::Luma | LayoutWithColor::Rgb, + ) => { + output_samples = 4; + input_samples = 3; + &*self.f32.slices[1] + } + ( + LayoutWithColor::Luma | LayoutWithColor::Rgb, + LayoutWithColor::LumaAlpha | LayoutWithColor::Rgba, + ) => { + output_samples = 3; + input_samples = 4; + &*self.f32.slices[2] + } + ( + LayoutWithColor::LumaAlpha | LayoutWithColor::Rgba, + LayoutWithColor::LumaAlpha | LayoutWithColor::Rgba, + ) => { + output_samples = 4; + input_samples = 4; + &*self.f32.slices[3] + } + }; + + for start_idx in (0..pixels).step_by(STEP) { + let end_idx = (start_idx + STEP).min(pixels); + let count = end_idx - start_idx; + + // Expand pixels from `other` into `ibuffer`. All of these have different types, so + // here's two large switch statements. + match rhs { + DynamicImage::ImageLuma8(buf) => { + CicpTransform::expand_luma_rgb( + &buf.inner_pixels()[start_idx..end_idx], + &mut ibuffer[..3 * count], + ); + } + DynamicImage::ImageLumaA8(buf) => { + CicpTransform::expand_luma_rgba( + &buf.inner_pixels()[2 * start_idx..2 * end_idx], + &mut ibuffer[..4 * count], + ); + } + DynamicImage::ImageRgb8(buf) => { + CicpTransform::expand_rgb( + &buf.inner_pixels()[3 * start_idx..3 * end_idx], + &mut ibuffer[..3 * count], + ); + } + DynamicImage::ImageRgba8(buf) => { + CicpTransform::expand_rgba( + &buf.inner_pixels()[4 * start_idx..4 * end_idx], + &mut ibuffer[..4 * count], + ); + } + DynamicImage::ImageLuma16(buf) => { + CicpTransform::expand_luma_rgb( + &buf.inner_pixels()[start_idx..end_idx], + &mut ibuffer[..3 * count], + ); + } + DynamicImage::ImageLumaA16(buf) => { + CicpTransform::expand_luma_rgba( + &buf.inner_pixels()[2 * start_idx..2 * end_idx], + &mut ibuffer[..4 * count], + ); + } + DynamicImage::ImageRgb16(buf) => { + CicpTransform::expand_rgb( + &buf.inner_pixels()[3 * start_idx..3 * end_idx], + &mut ibuffer[..3 * count], + ); + } + + DynamicImage::ImageRgba16(buf) => { + CicpTransform::expand_rgba( + &buf.inner_pixels()[4 * start_idx..4 * end_idx], + &mut ibuffer[..4 * count], + ); + } + DynamicImage::ImageRgb32F(buf) => { + CicpTransform::expand_rgb( + &buf.inner_pixels()[3 * start_idx..3 * end_idx], + &mut ibuffer[..3 * count], + ); + } + DynamicImage::ImageRgba32F(buf) => { + CicpTransform::expand_rgba( + &buf.inner_pixels()[4 * start_idx..4 * end_idx], + &mut ibuffer[..4 * count], + ); + } + } + + let islice = &ibuffer[..input_samples * count]; + let oslice = &mut obuffer[..output_samples * count]; + + inner_transform(islice, oslice); + + match lhs { + DynamicImage::ImageLuma8(buf) => { + CicpTransform::clamp_rgb_luma( + &obuffer[..3 * count], + &mut buf.inner_pixels_mut()[start_idx..end_idx], + self.output_coefs, + ); + } + DynamicImage::ImageLumaA8(buf) => { + CicpTransform::clamp_rgba_luma( + &obuffer[..4 * count], + &mut buf.inner_pixels_mut()[2 * start_idx..2 * end_idx], + self.output_coefs, + ); + } + DynamicImage::ImageRgb8(buf) => { + CicpTransform::clamp_rgb( + &obuffer[..3 * count], + &mut buf.inner_pixels_mut()[3 * start_idx..3 * end_idx], + ); + } + DynamicImage::ImageRgba8(buf) => { + CicpTransform::clamp_rgba( + &obuffer[..4 * count], + &mut buf.inner_pixels_mut()[4 * start_idx..4 * end_idx], + ); + } + DynamicImage::ImageLuma16(buf) => { + CicpTransform::clamp_rgb_luma( + &obuffer[..3 * count], + &mut buf.inner_pixels_mut()[start_idx..end_idx], + self.output_coefs, + ); + } + DynamicImage::ImageLumaA16(buf) => { + CicpTransform::clamp_rgba_luma( + &obuffer[..4 * count], + &mut buf.inner_pixels_mut()[2 * start_idx..2 * end_idx], + self.output_coefs, + ); + } + DynamicImage::ImageRgb16(buf) => { + CicpTransform::clamp_rgba( + &obuffer[..3 * count], + &mut buf.inner_pixels_mut()[3 * start_idx..3 * end_idx], + ); + } + + DynamicImage::ImageRgba16(buf) => { + CicpTransform::clamp_rgba( + &obuffer[..4 * count], + &mut buf.inner_pixels_mut()[4 * start_idx..4 * end_idx], + ); + } + DynamicImage::ImageRgb32F(buf) => { + CicpTransform::clamp_rgb( + &obuffer[..3 * count], + &mut buf.inner_pixels_mut()[3 * start_idx..3 * end_idx], + ); + } + DynamicImage::ImageRgba32F(buf) => { + CicpTransform::clamp_rgba( + &obuffer[..4 * count], + &mut buf.inner_pixels_mut()[4 * start_idx..4 * end_idx], + ); + } + } + } + } + + // Note on this design: When we dispatch into this function, we have a `Self` type that is + // qualified to have the appropriate bound here. However, for the target type of the transform + // we have, e.g., `Rgba`. Now we know that these are also with color for the + // most part but we can not convince the compiler (indeed, there is or was an asymmetry with + // gray pixels where they do not have float equivalents). It is hence necessary to provide the + // output layout as a runtime parameter, not a compile-time type. + pub(crate) fn select_transform_u8>( + &self, + into: LayoutWithColor, + ) -> &Arc> { + self.u8.select_transform::

(into) + } + + pub(crate) fn select_transform_u16>( + &self, + into: LayoutWithColor, + ) -> &Arc> { + self.u16.select_transform::(into) + } + + pub(crate) fn select_transform_f32>( + &self, + into: LayoutWithColor, + ) -> &Arc> { + self.f32.select_transform::(into) + } + + const LAYOUTS: [(LayoutWithColor, LayoutWithColor); 4] = [ + (LayoutWithColor::Rgb, LayoutWithColor::Rgb), + (LayoutWithColor::Rgb, LayoutWithColor::Rgba), + (LayoutWithColor::Rgba, LayoutWithColor::Rgb), + (LayoutWithColor::Rgba, LayoutWithColor::Rgba), + ]; + + pub(crate) fn expand_luma_rgb(luma: &[P], rgb: &mut [f32]) { + for (&pix, rgb) in luma.iter().zip(rgb.chunks_exact_mut(3)) { + let luma = pix.expand_to_f32(); + rgb[0] = luma; + rgb[1] = luma; + rgb[2] = luma; + } + } + + pub(crate) fn expand_luma_rgba(luma: &[P], rgb: &mut [f32]) { + for (pix, rgb) in luma.chunks_exact(2).zip(rgb.chunks_exact_mut(4)) { + let luma = pix[0].expand_to_f32(); + rgb[0] = luma; + rgb[1] = luma; + rgb[2] = luma; + rgb[3] = pix[1].expand_to_f32(); + } + } + + pub(crate) fn expand_rgb(input: &[P], output: &mut [f32]) { + for (&component, val) in input.iter().zip(output) { + *val = component.expand_to_f32(); + } + } + + pub(crate) fn expand_rgba(input: &[P], output: &mut [f32]) { + for (&component, val) in input.iter().zip(output) { + *val = component.expand_to_f32(); + } + } + + pub(crate) fn clamp_rgb(input: &[f32], output: &mut [P]) { + // Everything is mapped.. + for (&component, val) in input.iter().zip(output) { + *val = P::clamp_from_f32(component); + } + } + + pub(crate) fn clamp_rgba(input: &[f32], output: &mut [P]) { + for (&component, val) in input.iter().zip(output) { + *val = P::clamp_from_f32(component); + } + } + + pub(crate) fn clamp_rgb_luma( + input: &[f32], + output: &mut [P], + coef: [f32; 3], + ) { + for (rgb, pix) in input.chunks_exact(3).zip(output) { + let mut luma = 0.0; + + for (&component, coef) in rgb.iter().zip(coef) { + luma = multiply_accumulate(luma, component, coef); + } + + *pix = P::clamp_from_f32(luma); + } + } + + pub(crate) fn clamp_rgba_luma( + input: &[f32], + output: &mut [P], + coef: [f32; 3], + ) { + for (rgba, pix) in input.chunks_exact(4).zip(output.chunks_exact_mut(2)) { + let mut luma = 0.0; + + for (&component, coef) in rgba[..3].iter().zip(coef) { + luma = multiply_accumulate(luma, component, coef); + } + + pix[0] = P::clamp_from_f32(luma); + pix[1] = P::clamp_from_f32(rgba[3]); + } + } +} + +impl CicpRgb { + /// Internal utility for converting color buffers of different pixel representations, assuming + /// they have this same cicp. This method returns a buffer, avoiding the pre-zeroing + /// the vector. + pub(crate) fn cast_pixels( + &self, + buffer: &[FromColor::Subpixel], + // Since this is not performance sensitive, we can use a dyn closure here instead of an + // impl closure just in case we call this from multiple different paths. + color_space_fallback: &dyn Fn() -> [f32; 3], + ) -> Vec + where + FromColor: Pixel + SealedPixelWithColorType, + IntoColor: Pixel, + IntoColor: CicpPixelCast, + FromColor::Subpixel: ColorComponentForCicp, + IntoColor::Subpixel: ColorComponentForCicp + FromPrimitive, + { + use crate::traits::private::PrivateToken; + let from_layout = ::layout(PrivateToken); + let into_layout = ::layout(PrivateToken); + + let mut output = match self.cast_pixels_from_subpixels(buffer, from_layout, into_layout) { + Ok(ok) => return ok, + Err(buffer) => buffer, + }; + + // If we get here we need to transform through Rgb(a) 32F + let color_space_coefs = self + .derived_luminance() + // Since `cast_pixels` must be infallible we have no choice but to fallback to + // something here. This something is chosen by the caller, which would allow them to + // detect it has happened. + .unwrap_or_else(color_space_fallback); + + let pixels = buffer.len() / from_layout.channels(); + + // All of the following is done in-place; so we must allow the buffer space in which the + // output is written ahead of time although such initialization is technically redundant. + // We best do this once to allow for a very efficient memset initialization. + output.resize( + pixels * into_layout.channels(), + ::DEFAULT_MIN_VALUE, + ); + + Self::cast_pixels_by_fallback( + buffer, + output.as_mut_slice(), + from_layout, + into_layout, + color_space_coefs, + ); + output + } + + fn cast_pixels_by_fallback< + From: Primitive + ColorComponentForCicp, + Into: ColorComponentForCicp, + >( + buffer: &[From], + output: &mut [Into], + from_layout: LayoutWithColor, + into_layout: LayoutWithColor, + color_space_coefs: [f32; 3], + ) { + use LayoutWithColor as Layout; + + const STEP: usize = 256; + let pixels = buffer.len() / from_layout.channels(); + + let mut ibuffer = [0.0f32; 4 * STEP]; + let mut obuffer = [0.0f32; 4 * STEP]; + + let ibuf_step = match from_layout { + Layout::Rgb | Layout::Luma => 3, + Layout::Rgba | Layout::LumaAlpha => 4, + }; + + let obuf_step = match into_layout { + Layout::Rgb | Layout::Luma => 3, + Layout::Rgba | Layout::LumaAlpha => 4, + }; + + for start_idx in (0..pixels).step_by(STEP) { + let end_idx = (start_idx + STEP).min(pixels); + let count = end_idx - start_idx; + + let ibuffer = &mut ibuffer[..ibuf_step * count]; + + match from_layout { + Layout::Rgb => { + CicpTransform::expand_rgb(&buffer[3 * start_idx..3 * end_idx], ibuffer) + } + Layout::Rgba => { + CicpTransform::expand_rgba(&buffer[4 * start_idx..4 * end_idx], ibuffer) + } + Layout::Luma => { + CicpTransform::expand_luma_rgb(&buffer[start_idx..end_idx], ibuffer) + } + Layout::LumaAlpha => { + CicpTransform::expand_luma_rgba(&buffer[2 * start_idx..2 * end_idx], ibuffer) + } + } + + // Add or subtract the alpha channel. We could do that as part of the store but this + // keeps the code simpler—there is a one-to-one correspondence with the methods needed + // for a full conversion. + let obuffer = match (ibuf_step, obuf_step) { + (3, 4) => { + for (rgb, rgba) in ibuffer + .chunks_exact(3) + .zip(obuffer.chunks_exact_mut(4)) + .take(count) + { + rgba[0] = rgb[0]; + rgba[1] = rgb[1]; + rgba[2] = rgb[2]; + rgba[3] = 1.0; + } + + &obuffer[..4 * count] + } + (4, 3) => { + for (rgba, rgb) in ibuffer + .chunks_exact(4) + .zip(obuffer.chunks_exact_mut(3)) + .take(count) + { + rgb[0] = rgba[0]; + rgb[1] = rgba[1]; + rgb[2] = rgba[2]; + } + + &obuffer[..3 * count] + } + (n, m) => { + debug_assert_eq!(n, m); + &ibuffer[..m * count] + } + }; + + match into_layout { + Layout::Rgb => { + CicpTransform::clamp_rgb(obuffer, &mut output[3 * start_idx..3 * end_idx]); + } + Layout::Rgba => { + CicpTransform::clamp_rgba(obuffer, &mut output[4 * start_idx..4 * end_idx]); + } + Layout::Luma => { + CicpTransform::clamp_rgb_luma( + obuffer, + &mut output[start_idx..end_idx], + color_space_coefs, + ); + } + Layout::LumaAlpha => { + CicpTransform::clamp_rgba_luma( + obuffer, + &mut output[2 * start_idx..2 * end_idx], + color_space_coefs, + ); + } + } + } + } + + /// Make sure this is only monomorphized for subpixel combinations, not for every pixel + /// combination! There's ample time to do that in `cast_pixels`. + pub(crate) fn cast_pixels_from_subpixels( + &self, + buffer: &[FromSubpixel], + from_layout: LayoutWithColor, + into_layout: LayoutWithColor, + ) -> Result, Vec> + where + FromSubpixel: ColorComponentForCicp, + IntoSubpixel: ColorComponentForCicp + FromPrimitive + Primitive, + { + use crate::traits::private::LayoutWithColor as Layout; + + assert!(buffer.len() % from_layout.channels() == 0); + let pixels = buffer.len() / from_layout.channels(); + + let mut output: Vec = vec_try_with_capacity(pixels * into_layout.channels()) + // Not entirely failsafe, if you expand luma to rgba you can get a factor of 4 but at + // least this will not overflow. And that's why I'm a fan of in-place operations. + .expect("input layout already allocated with appropriate layout"); + let map_channel = >::from_primitive; + + match (from_layout, into_layout) { + // First detect if we can use simple channel-by-channel component conversion. + (Layout::Rgb, Layout::Rgb) + | (Layout::Rgba, Layout::Rgba) + | (Layout::Luma, Layout::Luma) + | (Layout::LumaAlpha, Layout::LumaAlpha) => { + output.extend(buffer.iter().copied().map(map_channel)); + } + (Layout::Rgb, Layout::Rgba) => { + // Use `as_chunks` with Rust 1.88 + output.extend(buffer.chunks_exact(3).flat_map(|rgb| { + let &rgb: &[_; 3] = rgb.try_into().unwrap(); + let [r, g, b] = rgb.map(map_channel); + let a = ::DEFAULT_MAX_VALUE; + [r, g, b, a] + })); + } + (Layout::Rgba, Layout::Rgb) => { + output.extend(buffer.chunks_exact(4).flat_map(|rgb| { + let &[r, g, b, _]: &[_; 4] = rgb.try_into().unwrap(); + [r, g, b].map(map_channel) + })); + } + (Layout::Luma, Layout::LumaAlpha) => { + output.extend(buffer.iter().copied().flat_map(|luma| { + let l = map_channel(luma); + let a = ::DEFAULT_MAX_VALUE; + [l, a] + })); + } + (Layout::LumaAlpha, Layout::Luma) => { + output.extend(buffer.chunks_exact(2).map(|rgb| { + let &[luma, _]: &[_; 2] = rgb.try_into().unwrap(); + map_channel(luma) + })); + } + _ => return Err(output), + } + + Ok(output) + } +} + +/// Color types that can be converted by [`CicpRgb::cast_pixels`]. +/// +/// This is a utility to avoid dealing with lots of bounds everywhere. In the actual implementation +/// we avoid the concrete pixel types and care just about the layout (as a runtime property) and +/// the channel type to be promotable into a float for normalization. If the pixels have layouts +/// that are convertible with intra-channel numerics we instead try and promote the channels via +/// `Primitive` instead. +pub(crate) trait CicpPixelCast +where + // Ensure we can get components from both, get the layout, and that all components are + // compatible with our intermediate connection space (rgba32f). + Self: Pixel + SealedPixelWithColorType::Subpixel>, + FromColor: + Pixel + SealedPixelWithColorType::Subpixel>, + Self::Subpixel: ColorComponentForCicp + FromPrimitive, + FromColor::Subpixel: ColorComponentForCicp, +{ +} + +impl CicpPixelCast for IntoColor +where + IntoColor: Pixel + SealedPixelWithColorType, + FromColor: Pixel + SealedPixelWithColorType, + IntoColor::Subpixel: ColorComponentForCicp + FromPrimitive, + FromColor::Subpixel: ColorComponentForCicp, +{ +} + +pub(crate) trait ColorComponentForCicp: Copy { + fn expand_to_f32(self) -> f32; + + fn clamp_from_f32(val: f32) -> Self; +} + +impl ColorComponentForCicp for u8 { + fn expand_to_f32(self) -> f32 { + const R: f32 = 1.0 / u8::MAX as f32; + self as f32 * R + } + + #[inline] + fn clamp_from_f32(val: f32) -> Self { + // Note: saturating conversion does the clamp for us + (val * Self::MAX as f32).round() as u8 + } +} + +impl ColorComponentForCicp for u16 { + fn expand_to_f32(self) -> f32 { + const R: f32 = 1.0 / u16::MAX as f32; + self as f32 * R + } + + #[inline] + fn clamp_from_f32(val: f32) -> Self { + // Note: saturating conversion does the clamp for us + (val * Self::MAX as f32).round() as u16 + } +} + +impl ColorComponentForCicp for f32 { + fn expand_to_f32(self) -> f32 { + self + } + + fn clamp_from_f32(val: f32) -> Self { + val + } +} + +impl

RgbTransforms

{ + fn select_transform( + &self, + into: LayoutWithColor, + ) -> &Arc> { + use crate::traits::private::{LayoutWithColor as Layout, PrivateToken}; + let from = O::layout(PrivateToken); + + match (from, into) { + (Layout::Rgb, Layout::Rgb) => &self.slices[0], + (Layout::Rgb, Layout::Rgba) => &self.slices[1], + (Layout::Rgba, Layout::Rgb) => &self.slices[2], + (Layout::Rgba, Layout::Rgba) => &self.slices[3], + (Layout::Rgb, Layout::Luma) => &self.rgb_luma[0], + (Layout::Rgb, Layout::LumaAlpha) => &self.rgb_luma[1], + (Layout::Rgba, Layout::Luma) => &self.rgb_luma[2], + (Layout::Rgba, Layout::LumaAlpha) => &self.rgb_luma[3], + (Layout::Luma, Layout::Rgb) => &self.luma_rgb[0], + (Layout::Luma, Layout::Rgba) => &self.luma_rgb[1], + (Layout::LumaAlpha, Layout::Rgb) => &self.luma_rgb[2], + (Layout::LumaAlpha, Layout::Rgba) => &self.luma_rgb[3], + (Layout::Luma, Layout::Luma) => &self.luma_luma[0], + (Layout::Luma, Layout::LumaAlpha) => &self.luma_luma[1], + (Layout::LumaAlpha, Layout::Luma) => &self.luma_luma[2], + (Layout::LumaAlpha, Layout::LumaAlpha) => &self.luma_luma[3], + } + } +} + +impl Cicp { + /// The sRGB color space, BT.709 transfer function and D65 whitepoint. + pub const SRGB: Self = Cicp { + primaries: CicpColorPrimaries::SRgb, + transfer: CicpTransferCharacteristics::SRgb, + matrix: CicpMatrixCoefficients::Identity, + full_range: CicpVideoFullRangeFlag::FullRange, + }; + + /// SRGB primaries and whitepoint with linear samples. + pub const SRGB_LINEAR: Self = Cicp { + primaries: CicpColorPrimaries::SRgb, + transfer: CicpTransferCharacteristics::Linear, + matrix: CicpMatrixCoefficients::Identity, + full_range: CicpVideoFullRangeFlag::FullRange, + }; + + /// The Display-P3 color space, a wide-gamut choice with SMPTE RP 432-2 primaries. + /// + /// Note that this modern Display P3 uses a D65 whitepoint. Use the primaries `SmpteRp431` for + /// the previous standard. The advantage of the new standard is the color system shares its + /// whitepoint with sRGB and BT.2020. + pub const DISPLAY_P3: Self = Cicp { + primaries: CicpColorPrimaries::SmpteRp432, + transfer: CicpTransferCharacteristics::SRgb, + matrix: CicpMatrixCoefficients::Identity, + full_range: CicpVideoFullRangeFlag::FullRange, + }; + + /// Get an compute representation of an ICC profile for RGB. + /// + /// Note you should *not* be using this profile for export in a file, as discussed below. + /// + /// This is straightforward for Rgb and RgbA representations. + /// + /// Our luma models a Y component of a YCbCr color space. It turns out that ICC V4 does + /// not support pure Luma in any other whitepoint apart from D50 (the native profile + /// connection space). The use of a grayTRC does *not* take the chromatic adaptation + /// matrix into account. Of course we can encode the adaptation into the TRC as a + /// coefficient, the Y component of the product of the whitepoint adaptation matrix + /// inverse and the pcs's whitepoint XYZ, but that is only correct for gray -> gray + /// conversion (and that coefficient should generally be `1`). + /// + /// Hence we use a YCbCr. The data->pcs path could be modelled by ("M" curves, matrix, "B" + /// curves) where B curves or M curves are all the identity, depending on whether constant or + /// non-constant luma is in use. This is a subset of the capabilities that a lutAToBType + /// allows. Unfortunately, this is not implemented in moxcms yet and for efficiency we would + /// like to have a masked `create_transform_*` in which the CbCr channels are discarded / + /// assumed 0 instead of them being in memory. Due to this special case and for supporting + /// conversions between sample types, we implement said promotion as part of conversion to + /// Rgba32F in this crate. + /// + /// For export to file, it would arguably correct to use a carefully crafted gray profile which + /// we may implement in another function. That is, we could setup a tone reproduction curve + /// which maps each sample value (which ICC regards as D50) into XYZ D50 in such a way that it + /// _appears_ with the correct D50 luminance that we would get if we had used the conversion + /// unders its true input whitepoint. The resulting color has a slightly wrong chroma as it is + /// linearly dependent on D50 instead, but it's brightness would be correctly presented. At + /// least for perceptual intent this might be alright. + fn to_moxcms_compute_profile(self) -> Option { + let mut rgb = moxcms::ColorProfile::new_srgb(); + + rgb.update_rgb_colorimetry_from_cicp(moxcms::CicpProfile { + color_primaries: self.primaries.to_moxcms(), + transfer_characteristics: self.transfer.to_moxcms(), + matrix_coefficients: self.matrix.to_moxcms()?, + full_range: match self.full_range { + CicpVideoFullRangeFlag::NarrowRange => false, + CicpVideoFullRangeFlag::FullRange => true, + }, + }); + + Some(ColorProfile { rgb }) + } + + /// Whether we have invested enough testing to ensure that color values can be assumed to be + /// stable and correspond to an intended effect, in particular if there even is a well-defined + /// meaning to these color spaces. + /// + /// For instance, our current code for the 'luma' equivalent space assumes that the color space + /// has a shared transfer function for all its color components. Also the judgment should not + /// depend on whether we can represent the profile in `moxcms` but rather if we understand the + /// profile well enough so that conversion implemented through another library can be derived. + /// (Consider the case of a builtin transform-while-encoding that may be more performant for a + /// format that does not support CICP or ICC profiles.) + /// + /// A stable profile should also have `derived_luminance` implemented. + pub(crate) const fn qualify_stability(&self) -> bool { + const _: () = { + // Out public constants _should_ be stable. + assert!(Cicp::SRGB.qualify_stability()); + assert!(Cicp::SRGB_LINEAR.qualify_stability()); + assert!(Cicp::DISPLAY_P3.qualify_stability()); + }; + + matches!(self.full_range, CicpVideoFullRangeFlag::FullRange) + && matches!( + self.matrix, + // For pure RGB color + CicpMatrixCoefficients::Identity + // The equivalent of our Luma color as a type.. + | CicpMatrixCoefficients::ChromaticityDerivedNonConstant + ) + && matches!( + self.primaries, + CicpColorPrimaries::SRgb + | CicpColorPrimaries::SmpteRp431 + | CicpColorPrimaries::SmpteRp432 + | CicpColorPrimaries::Bt601 + | CicpColorPrimaries::Rgb240m + ) + && matches!( + self.transfer, + CicpTransferCharacteristics::SRgb + | CicpTransferCharacteristics::Bt709 + | CicpTransferCharacteristics::Bt601 + | CicpTransferCharacteristics::Linear + ) + } + + /// Discard matrix and range information. + pub(crate) const fn into_rgb(self) -> CicpRgb { + CicpRgb { + primaries: self.primaries, + transfer: self.transfer, + // NOTE: if we add support for constant luminance (through the CMS having support for + // the Luma->YCbCr->Rgb expansion natively or otherwise) then consider if we should + // track here whether the matrix was `Identity` or `ChromaticityDerivedNonConstant` so + // that the `ImageBuffer::color_space()` function roundtrips the value. It may be + // important to know whether the non-constant chromaticity was an invention by `image` + // or part of the file. The colorimetry is the same either way. + luminance: DerivedLuminance::NonConstant, + } + } + + pub(crate) fn try_into_rgb(self) -> Result { + if Cicp::from(self.into_rgb()) != self { + Err(ImageError::Parameter(ParameterError::from_kind( + ParameterErrorKind::RgbCicpRequired(self), + ))) + } else { + Ok(self.into_rgb()) + } + } +} + +impl CicpRgb { + /// Calculate the luminance cofactors according to Rec H.273 (39) and (40). + /// + /// Returns cofactors for red, green, and blue in that order. + pub(crate) fn derived_luminance(&self) -> Option<[f32; 3]> { + let primaries = match self.primaries { + CicpColorPrimaries::SRgb => moxcms::ColorPrimaries::BT_709, + CicpColorPrimaries::RgbM => moxcms::ColorPrimaries::BT_470M, + CicpColorPrimaries::RgbB => moxcms::ColorPrimaries::BT_470BG, + CicpColorPrimaries::Bt601 => moxcms::ColorPrimaries::BT_601, + CicpColorPrimaries::Rgb240m => moxcms::ColorPrimaries::SMPTE_240, + CicpColorPrimaries::GenericFilm => moxcms::ColorPrimaries::GENERIC_FILM, + CicpColorPrimaries::Rgb2020 => moxcms::ColorPrimaries::BT_2020, + CicpColorPrimaries::Xyz => moxcms::ColorPrimaries::XYZ, + CicpColorPrimaries::SmpteRp431 => moxcms::ColorPrimaries::DISPLAY_P3, + CicpColorPrimaries::SmpteRp432 => moxcms::ColorPrimaries::DISPLAY_P3, + CicpColorPrimaries::Industry22 => moxcms::ColorPrimaries::EBU_3213, + CicpColorPrimaries::Unspecified => return None, + }; + + const ILLUMINANT_C: moxcms::Chromaticity = moxcms::Chromaticity::new(0.310, 0.316); + + let whitepoint = match self.primaries { + CicpColorPrimaries::SRgb => moxcms::Chromaticity::D65, + CicpColorPrimaries::RgbM => ILLUMINANT_C, + CicpColorPrimaries::RgbB => moxcms::Chromaticity::D65, + CicpColorPrimaries::Bt601 => moxcms::Chromaticity::D65, + CicpColorPrimaries::Rgb240m => moxcms::Chromaticity::D65, + CicpColorPrimaries::GenericFilm => ILLUMINANT_C, + CicpColorPrimaries::Rgb2020 => moxcms::Chromaticity::D65, + CicpColorPrimaries::Xyz => moxcms::Chromaticity::new(1. / 3., 1. / 3.), + CicpColorPrimaries::SmpteRp431 => moxcms::Chromaticity::new(0.314, 0.351), + CicpColorPrimaries::SmpteRp432 => moxcms::Chromaticity::D65, + CicpColorPrimaries::Industry22 => moxcms::Chromaticity::D65, + CicpColorPrimaries::Unspecified => return None, + }; + + let matrix = primaries.transform_to_xyz(whitepoint); + + // Our result is the Y row of this matrix. + Some(matrix.v[1]) + } +} + +impl From for Cicp { + fn from(cicp: CicpRgb) -> Self { + Cicp { + primaries: cicp.primaries, + transfer: cicp.transfer, + matrix: CicpMatrixCoefficients::Identity, + full_range: CicpVideoFullRangeFlag::FullRange, + } + } +} + +/// An RGB profile with its related (same tone-mapping) gray profile. +/// +/// This is the whole input information which we must be able to pass to the CMS in a support +/// transform, to handle all possible combinations of `ColorType` pixels that can be thrown at us. +/// For instance, in a previous iteration we had a separate gray profile here (but now handle that +/// internally by expansion to RGB through an YCbCr). Future iterations may add additional structs +/// to be computed for validating `CicpTransform::new`. +struct ColorProfile { + rgb: moxcms::ColorProfile, +} + +impl ColorProfile { + fn map_layout(&self, layout: LayoutWithColor) -> (&moxcms::ColorProfile, moxcms::Layout) { + match layout { + LayoutWithColor::Rgb => (&self.rgb, moxcms::Layout::Rgb), + LayoutWithColor::Rgba => (&self.rgb, moxcms::Layout::Rgba), + // See comment in `to_moxcms_profile`. + LayoutWithColor::Luma | LayoutWithColor::LumaAlpha => unreachable!(), + } + } +} + +#[cfg(test)] +#[test] +fn moxcms() { + let l = moxcms::TransferCharacteristics::Linear; + assert_eq!(l.linearize(1.0), 1.0); + assert_eq!(l.gamma(1.0), 1.0); + + assert_eq!(l.gamma(0.5), 0.5); +} + +#[cfg(test)] +#[test] +fn derived_luminance() { + let luminance = Cicp::SRGB.into_rgb().derived_luminance(); + let [kr, kg, kb] = luminance.unwrap(); + assert!((kr - 0.2126).abs() < 1e-4); + assert!((kg - 0.7152).abs() < 1e-4); + assert!((kb - 0.0722).abs() < 1e-4); +} + +#[cfg(test)] +mod tests { + use super::{Cicp, CicpTransform}; + use crate::{Luma, LumaA, Rgb, Rgba}; + + #[test] + fn can_create_transforms() { + assert!(CicpTransform::new(Cicp::SRGB, Cicp::SRGB).is_some()); + assert!(CicpTransform::new(Cicp::SRGB, Cicp::DISPLAY_P3).is_some()); + assert!(CicpTransform::new(Cicp::DISPLAY_P3, Cicp::SRGB).is_some()); + assert!(CicpTransform::new(Cicp::DISPLAY_P3, Cicp::DISPLAY_P3).is_some()); + } + + fn no_coefficient_fallback() -> [f32; 3] { + panic!("Fallback coefficients required") + } + + #[test] + fn transform_pixels_srgb() { + // Non-constant luminance so: + // Y = dot(rgb, coefs) + let data = [255, 0, 0, 255]; + let color = Cicp::SRGB.into_rgb(); + let rgba = color.cast_pixels::, Rgb>(&data, &no_coefficient_fallback); + assert_eq!(rgba, [255, 0, 0]); + let luma = color.cast_pixels::, Luma>(&data, &no_coefficient_fallback); + assert_eq!(luma, [54]); // 255 * 0.2126 + let luma_a = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma_a, [54, 255]); + } + + #[test] + fn transform_pixels_srgb_16() { + // Non-constant luminance so: + // Y = dot(rgb, coefs) + let data = [u16::MAX / 2]; + let color = Cicp::SRGB.into_rgb(); + let rgba = color.cast_pixels::, Rgb>(&data, &no_coefficient_fallback); + assert_eq!(rgba, [127; 3]); + let luma = color.cast_pixels::, Luma>(&data, &no_coefficient_fallback); + assert_eq!(luma, [127]); + let luma_a = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma_a, [127, 255]); + + let data = [u16::MAX / 2 + 1]; + let color = Cicp::SRGB.into_rgb(); + let rgba = color.cast_pixels::, Rgb>(&data, &no_coefficient_fallback); + assert_eq!(rgba, [128; 3]); + let luma = color.cast_pixels::, Luma>(&data, &no_coefficient_fallback); + assert_eq!(luma, [128]); + let luma_a = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma_a, [128, 255]); + } + + #[test] + fn transform_pixels_srgb_luma_alpha() { + // Non-constant luminance so: + // Y = dot(rgb, coefs) + let data = [u16::MAX / 2, u16::MAX]; + let color = Cicp::SRGB.into_rgb(); + let rgba = color.cast_pixels::, Rgb>(&data, &no_coefficient_fallback); + assert_eq!(rgba, [127; 3]); + let luma = color.cast_pixels::, Luma>(&data, &no_coefficient_fallback); + assert_eq!(luma, [127]); + let luma = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma, [127, u8::MAX]); + let luma_a = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma_a, [127, 255]); + + let data = [u16::MAX / 2 + 1, u16::MAX]; + let color = Cicp::SRGB.into_rgb(); + let rgba = color.cast_pixels::, Rgb>(&data, &no_coefficient_fallback); + assert_eq!(rgba, [128; 3]); + let luma = color.cast_pixels::, Luma>(&data, &no_coefficient_fallback); + assert_eq!(luma, [128]); + let luma = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma, [128, u8::MAX]); + let luma_a = color.cast_pixels::, LumaA>(&data, &no_coefficient_fallback); + assert_eq!(luma_a, [128, 255]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/metadata.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/metadata.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/metadata.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,192 @@ +//! Types describing image metadata +pub(crate) mod cicp; + +use std::io::{Cursor, Read}; + +use byteorder_lite::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; + +pub use self::cicp::{ + Cicp, CicpColorPrimaries, CicpMatrixCoefficients, CicpTransferCharacteristics, CicpTransform, + CicpVideoFullRangeFlag, +}; + +/// Describes the transformations to be applied to the image. +/// Compatible with [Exif orientation](https://web.archive.org/web/20200412005226/https://www.impulseadventure.com/photo/exif-orientation.html). +/// +/// Orientation is specified in the file's metadata, and is often written by cameras. +/// +/// You can apply it to an image via [`DynamicImage::apply_orientation`](crate::DynamicImage::apply_orientation). +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Orientation { + /// Do not perform any transformations. + NoTransforms, + /// Rotate by 90 degrees clockwise. + Rotate90, + /// Rotate by 180 degrees. Can be performed in-place. + Rotate180, + /// Rotate by 270 degrees clockwise. Equivalent to rotating by 90 degrees counter-clockwise. + Rotate270, + /// Flip horizontally. Can be performed in-place. + FlipHorizontal, + /// Flip vertically. Can be performed in-place. + FlipVertical, + /// Rotate by 90 degrees clockwise and flip horizontally. + Rotate90FlipH, + /// Rotate by 270 degrees clockwise and flip horizontally. + Rotate270FlipH, +} + +impl Orientation { + /// Converts from [Exif orientation](https://web.archive.org/web/20200412005226/https://www.impulseadventure.com/photo/exif-orientation.html) + #[must_use] + pub fn from_exif(exif_orientation: u8) -> Option { + match exif_orientation { + 1 => Some(Self::NoTransforms), + 2 => Some(Self::FlipHorizontal), + 3 => Some(Self::Rotate180), + 4 => Some(Self::FlipVertical), + 5 => Some(Self::Rotate90FlipH), + 6 => Some(Self::Rotate90), + 7 => Some(Self::Rotate270FlipH), + 8 => Some(Self::Rotate270), + 0 | 9.. => None, + } + } + + /// Converts into [Exif orientation](https://web.archive.org/web/20200412005226/https://www.impulseadventure.com/photo/exif-orientation.html) + #[must_use] + pub fn to_exif(self) -> u8 { + match self { + Self::NoTransforms => 1, + Self::FlipHorizontal => 2, + Self::Rotate180 => 3, + Self::FlipVertical => 4, + Self::Rotate90FlipH => 5, + Self::Rotate90 => 6, + Self::Rotate270FlipH => 7, + Self::Rotate270 => 8, + } + } + + /// Extracts the image orientation from a raw Exif chunk. + /// + /// You can obtain the Exif chunk using + /// [ImageDecoder::exif_metadata](crate::ImageDecoder::exif_metadata). + /// + /// It is more convenient to use [ImageDecoder::orientation](crate::ImageDecoder::orientation) + /// than to invoke this function. + /// Only use this function if you extract and process the Exif chunk separately. + #[must_use] + pub fn from_exif_chunk(chunk: &[u8]) -> Option { + Self::from_exif_chunk_inner(chunk).map(|res| res.0) + } + + /// Extracts the image orientation from a raw Exif chunk and sets the orientation in the Exif chunk to `Orientation::NoTransforms`. + /// This is useful if you want to apply the orientation yourself, and then encode the image with the rest of the Exif chunk intact. + /// + /// If the orientation data is not cleared from the Exif chunk after you apply the orientation data yourself, + /// the image will end up being rotated once again by any software that correctly handles Exif, leading to an incorrect result. + /// + /// If the Exif value is present but invalid, `None` is returned and the Exif chunk is not modified. + #[must_use] + pub fn remove_from_exif_chunk(chunk: &mut [u8]) -> Option { + if let Some((orientation, offset, endian)) = Self::from_exif_chunk_inner(chunk) { + let mut writer = Cursor::new(chunk); + writer.set_position(offset); + let no_orientation: u16 = Self::NoTransforms.to_exif().into(); + match endian { + ExifEndian::Big => writer.write_u16::(no_orientation).unwrap(), + ExifEndian::Little => writer.write_u16::(no_orientation).unwrap(), + } + Some(orientation) + } else { + None + } + } + + /// Returns the orientation, the offset in the Exif chunk where it was found, and Exif chunk endianness + #[must_use] + fn from_exif_chunk_inner(chunk: &[u8]) -> Option<(Self, u64, ExifEndian)> { + let mut reader = Cursor::new(chunk); + + let mut magic = [0; 4]; + reader.read_exact(&mut magic).ok()?; + + match magic { + [0x49, 0x49, 42, 0] => { + return Self::locate_orientation_entry::(&mut reader) + .map(|(orient, offset)| (orient, offset, ExifEndian::Little)); + } + [0x4d, 0x4d, 0, 42] => { + return Self::locate_orientation_entry::(&mut reader) + .map(|(orient, offset)| (orient, offset, ExifEndian::Big)); + } + _ => {} + } + None + } + + /// Extracted into a helper function to be generic over endianness + fn locate_orientation_entry(reader: &mut Cursor<&[u8]>) -> Option<(Self, u64)> + where + B: byteorder_lite::ByteOrder, + { + let ifd_offset = reader.read_u32::().ok()?; + reader.set_position(u64::from(ifd_offset)); + let entries = reader.read_u16::().ok()?; + for _ in 0..entries { + let tag = reader.read_u16::().ok()?; + let format = reader.read_u16::().ok()?; + let count = reader.read_u32::().ok()?; + let value = reader.read_u16::().ok()?; + let _padding = reader.read_u16::().ok()?; + if tag == 0x112 && format == 3 && count == 1 { + let offset = reader.position() - 4; // we've read 4 bytes (2 * u16) past the start of the value + let orientation = Self::from_exif(value.min(255) as u8); + return orientation.map(|orient| (orient, offset)); + } + } + // If we reached this point without returning early, there was no orientation + None + } +} + +#[derive(Debug, Copy, Clone)] +enum ExifEndian { + Big, + Little, +} + +#[cfg(all(test, feature = "jpeg"))] +mod tests { + use crate::{codecs::jpeg::JpegDecoder, ImageDecoder as _}; + + // This brings all the items from the parent module into scope, + // so you can directly use `add` instead of `super::add`. + use super::*; + + const TEST_IMAGE: &[u8] = include_bytes!("../tests/images/jpg/portrait_2.jpg"); + + #[test] // This attribute marks the function as a test function. + fn test_extraction_and_clearing() { + let reader = Cursor::new(TEST_IMAGE); + let mut decoder = JpegDecoder::new(reader).expect("Failed to decode test image"); + let mut exif_chunk = decoder + .exif_metadata() + .expect("Failed to extract Exif chunk") + .expect("No Exif chunk found in test image"); + + let orientation = Orientation::from_exif_chunk(&exif_chunk) + .expect("Failed to extract orientation from Exif chunk"); + assert_eq!(orientation, Orientation::FlipHorizontal); + + let orientation = Orientation::remove_from_exif_chunk(&mut exif_chunk) + .expect("Failed to remove orientation from Exif chunk"); + assert_eq!(orientation, Orientation::FlipHorizontal); + // Now that the orientation has been cleared, any subsequent extractions should return NoTransforms + let orientation = Orientation::from_exif_chunk(&exif_chunk) + .expect("Failed to extract orientation from Exif chunk after clearing it"); + assert_eq!(orientation, Orientation::NoTransforms); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/traits.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,7 +5,8 @@ use num_traits::{Bounded, Num, NumCast}; use std::ops::AddAssign; -use crate::color::{ColorType, Luma, LumaA, Rgb, Rgba}; +use crate::color::{Luma, LumaA, Rgb, Rgba}; +use crate::ExtendedColorType; /// Types which are safe to treat as an immutable byte slice in a pixel layout /// for image encoding. @@ -67,7 +68,7 @@ declare_primitive!(f32: (0.0)..1.0); declare_primitive!(f64: (0.0)..1.0); -/// An Enlargable::Larger value should be enough to calculate +/// An `Enlargable::Larger` value should be enough to calculate /// the sum (average) of a few hundred or thousand Enlargeable values. pub trait Enlargeable: Sized + Bounded + NumCast { type Larger: Copy + NumCast + Num + PartialOrd + Clone + Bounded + AddAssign; @@ -168,65 +169,247 @@ /// The pixel with an associated `ColorType`. /// Not all possible pixels represent one of the predefined `ColorType`s. -pub trait PixelWithColorType: Pixel + self::private::SealedPixelWithColorType { +pub trait PixelWithColorType: + Pixel + private::SealedPixelWithColorType::Subpixel> +{ /// This pixel has the format of one of the predefined `ColorType`s, /// such as `Rgb8`, `La16` or `Rgba32F`. /// This is needed for automatically detecting /// a color format when saving an image as a file. - const COLOR_TYPE: ColorType; + const COLOR_TYPE: ExtendedColorType; } impl PixelWithColorType for Rgb { - const COLOR_TYPE: ColorType = ColorType::Rgb8; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb8; } impl PixelWithColorType for Rgb { - const COLOR_TYPE: ColorType = ColorType::Rgb16; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb16; } impl PixelWithColorType for Rgb { - const COLOR_TYPE: ColorType = ColorType::Rgb32F; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb32F; } impl PixelWithColorType for Rgba { - const COLOR_TYPE: ColorType = ColorType::Rgba8; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba8; } impl PixelWithColorType for Rgba { - const COLOR_TYPE: ColorType = ColorType::Rgba16; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba16; } impl PixelWithColorType for Rgba { - const COLOR_TYPE: ColorType = ColorType::Rgba32F; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba32F; } impl PixelWithColorType for Luma { - const COLOR_TYPE: ColorType = ColorType::L8; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::L8; } impl PixelWithColorType for Luma { - const COLOR_TYPE: ColorType = ColorType::L16; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::L16; } impl PixelWithColorType for LumaA { - const COLOR_TYPE: ColorType = ColorType::La8; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::La8; } impl PixelWithColorType for LumaA { - const COLOR_TYPE: ColorType = ColorType::La16; + const COLOR_TYPE: ExtendedColorType = ExtendedColorType::La16; } /// Prevents down-stream users from implementing the `Primitive` trait -mod private { +pub(crate) mod private { use crate::color::*; + use crate::metadata::cicp::{self, CicpApplicable}; - pub trait SealedPixelWithColorType {} - impl SealedPixelWithColorType for Rgb {} - impl SealedPixelWithColorType for Rgb {} - impl SealedPixelWithColorType for Rgb {} - - impl SealedPixelWithColorType for Rgba {} - impl SealedPixelWithColorType for Rgba {} - impl SealedPixelWithColorType for Rgba {} + #[derive(Clone, Copy, Debug)] + pub enum LayoutWithColor { + Rgb, + Rgba, + Luma, + LumaAlpha, + } + + impl From for LayoutWithColor { + fn from(color: ColorType) -> LayoutWithColor { + match color { + ColorType::L8 | ColorType::L16 => LayoutWithColor::Luma, + ColorType::La8 | ColorType::La16 => LayoutWithColor::LumaAlpha, + ColorType::Rgb8 | ColorType::Rgb16 | ColorType::Rgb32F => LayoutWithColor::Rgb, + ColorType::Rgba8 | ColorType::Rgba16 | ColorType::Rgba32F => LayoutWithColor::Rgba, + } + } + } + + impl LayoutWithColor { + pub(crate) fn channels(self) -> usize { + match self { + Self::Rgb => 3, + Self::Rgba => 4, + Self::Luma => 1, + Self::LumaAlpha => 2, + } + } + } + + #[derive(Clone, Copy)] + pub struct PrivateToken; + + pub trait SealedPixelWithColorType { + #[expect(private_bounds)] // This is a sealed trait. + type TransformableSubpixel: HelpDispatchTransform; + fn layout(_: PrivateToken) -> LayoutWithColor; + } + + impl SealedPixelWithColorType for Rgb { + type TransformableSubpixel = u8; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgb + } + } + + impl SealedPixelWithColorType for Rgb { + type TransformableSubpixel = u16; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgb + } + } + + impl SealedPixelWithColorType for Rgb { + type TransformableSubpixel = f32; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgb + } + } + + impl SealedPixelWithColorType for Rgba { + type TransformableSubpixel = u8; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgba + } + } + + impl SealedPixelWithColorType for Rgba { + type TransformableSubpixel = u16; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgba + } + } + + impl SealedPixelWithColorType for Rgba { + type TransformableSubpixel = f32; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Rgba + } + } + + impl SealedPixelWithColorType for Luma { + type TransformableSubpixel = u8; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Luma + } + } + + impl SealedPixelWithColorType for LumaA { + type TransformableSubpixel = u8; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::LumaAlpha + } + } + + impl SealedPixelWithColorType for Luma { + type TransformableSubpixel = u16; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Luma + } + } + + impl SealedPixelWithColorType for Luma { + type TransformableSubpixel = f32; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::Luma + } + } + + impl SealedPixelWithColorType for LumaA { + type TransformableSubpixel = u16; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::LumaAlpha + } + } + + impl SealedPixelWithColorType for LumaA { + type TransformableSubpixel = f32; + fn layout(_: PrivateToken) -> LayoutWithColor { + LayoutWithColor::LumaAlpha + } + } + + // Consider a situation in a function bounded `Self: Pixel + PixelWithColorType`. Then, if we + // tried this directly: + // + // < + // ::TransformableSubpixel as HelpDispatchTransform + // >::transform_on::(tr, LayoutWithColor::Rgb); + // + // the type checker is mightily confused. I think what's going on is as follows: It find the + // fact that `Self::Subpixel` is used for `TransformableSubpixel` from the bound on + // `PixelWithColorType`, but then there is no existing bound on `Subpixel` that would guarantee + // that `HelpDispatchTransform` is fulfilled. That would only be available by substituting + // _back_ so that the bound on `TransformableSubpixel` gets applied to the `Subpixel` generic, + // too. But now there are no variables here, so unification of bounds takes place we never + // never get to see the bound (until next gen, I guess?). It finally find that there is still + // an unfulfilled bound and complains. + // + // Hence we must avoid mentioning the `Pixel` and `PixelWithColorType` bound so that _only_ the + // `TransformableSubpixel` is available. Then all substitutions work forwards, and since we + // return a `TransformableSubpixel` we get the function back without new variables to solve + // for, and that can then be unified just fine. This extra function essentially introduces that + // missing unknown which can unify the available impl set. Yay. + pub(crate) fn dispatch_transform_from_sealed( + transform: &cicp::CicpTransform, + into: LayoutWithColor, + ) -> &'_ CicpApplicable<'_, P::TransformableSubpixel> { + ::transform_on::

(transform, into) + } - impl SealedPixelWithColorType for Luma {} - impl SealedPixelWithColorType for LumaA {} + pub(crate) fn double_dispatch_transform_from_sealed< + P: SealedPixelWithColorType, + Into: SealedPixelWithColorType, + >( + transform: &cicp::CicpTransform, + ) -> &'_ CicpApplicable<'_, P::TransformableSubpixel> { + dispatch_transform_from_sealed::

+4 examples (click to expand) + +```rust +use std::fmt; + +/* ===== Simple derive. ===== */ +#[derive(Debug)] +struct Name1 { + iter: I, +} + +/* ===== With an unclonable field. ===== */ +struct Name2 { + iter: I, + func: F, +} + +// No `F: Debug` bound and the field `func` is ignored. +impl fmt::Debug for Name2 { + // it defines the `fmt` function from a struct name and the fields you want to debug. + debug_fmt_fields!(Name2, iter); +} + +/* ===== With an unclonable field, but another bound to add. ===== */ +struct Name3 { + iter: I, + item: Option, + func: F, +} + +// Same about `F` and `func`, similar about `I` but we must add the `I::Item: Debug` bound. +impl fmt::Debug for Name3 +where + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Name3, iter, item); +} + +/* ===== With an unclonable field for which we can provide some information. ===== */ +struct Name4 { + iter: I, + func: Option, +} + +// If ignore a field is not good enough, implement Debug fully manually. +impl fmt::Debug for Name4 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let func = if self.func.is_some() { "Some(_)" } else { "None" }; + f.debug_struct("Name4") + .field("iter", &self.iter) + .field("func", &func) + .finish() + } +} +``` +
+ +### When/How to implement [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html) +All our iterators should implement `Clone` when possible. + +Note that a mutable reference is never clonable so `struct Name<'a, I: 'a> { iter: &'a mut I }` can not implement `Clone`. + +Derive `Clone` on a generic struct adds the bound `Clone` on each generic parameter. +It might be an issue in which case you should manually implement it with our helper macro `clone_fields` (it defines the `clone` function calling `clone` on each field) and be careful about the bounds. + +### When to implement [`std::iter::FusedIterator`](https://doc.rust-lang.org/std/iter/trait.FusedIterator.html) +This trait should be implemented _by all iterators that always return `None` after returning `None` once_, because it allows to optimize `Iterator::fuse()`. + +The conditions on which it should be implemented are usually the ones from the `Iterator` implementation, eventually refined to ensure it behaves in a fused way. + +### When to implement [`ExactSizeIterator`](https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html) +_When we are always able to return an exact non-overflowing length._ + +Therefore, we do not implement it on adaptors that makes the iterator longer as the resulting length could overflow. + +One should not override `ExactSizeIterator::len` method but rely on an exact `Iterator::size_hint` implementation, meaning it returns `(length, Some(length))` (unless you could make `len` more performant than the default). + +The conditions on which it should be implemented are usually the ones from the `Iterator` implementation, probably refined to ensure the size hint is exact. + +### When to implement [`DoubleEndedIterator`](https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) +When the iterator structure allows to handle _iterating on both fronts simultaneously_. +The iteration might stop in the middle when both fronts meet. + +The conditions on which it should be implemented are usually the ones from the `Iterator` implementation, probably refined to ensure we can iterate on both fronts simultaneously. + +### When to implement [`itertools::PeekingNext`](https://docs.rs/itertools/latest/itertools/trait.PeekingNext.html) +TODO + +This is currently **tested** in `tests/test_std.rs`. + +## About lending iterators +TODO + + +## Other notes +No guideline about using `#[inline]` yet. + +### `.fold` / `.for_each` / `.try_fold` / `.try_for_each` +In the Rust standard library, it's quite common for `fold` to be implemented in terms of `try_fold`. But it's not something we do yet because we can not specialize `try_fold` methods yet (it uses the unstable `Try`). + +From [#781](https://github.com/rust-itertools/itertools/pull/781), the general rule to follow is something like this: + +- If you need to completely consume an iterator: + - Use `fold` if you need an _owned_ access to an accumulator. + - Use `for_each` otherwise. +- If you need to partly consume an iterator, the same applies with `try_` versions: + - Use `try_fold` if you need an _owned_ access to an accumulator. + - Use `try_for_each` otherwise. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,740 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +dependencies = [ + "criterion", + "either", + "paste", + "permutohedron", + "quickcheck", + "rand", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "permutohedron" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quickcheck" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -3,71 +3,165 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" +rust-version = "1.63.0" name = "itertools" -version = "0.10.5" +version = "0.14.0" authors = ["bluss"] -exclude = ["/bors.toml"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Extra iterator adaptors, iterator methods, free functions, and macros." documentation = "https://docs.rs/itertools/" readme = "README.md" -keywords = ["iterator", "data-structure", "zip", "product", "group-by"] -categories = ["algorithms", "rust-patterns"] -license = "MIT/Apache-2.0" +keywords = [ + "iterator", + "data-structure", + "zip", + "product", +] +categories = [ + "algorithms", + "rust-patterns", + "no-std", + "no-std::no-alloc", +] +license = "MIT OR Apache-2.0" repository = "https://github.com/rust-itertools/itertools" -[package.metadata.release] -no-dev-version = true -[profile.bench] -debug = true + +[features] +default = ["use_std"] +use_alloc = [] +use_std = [ + "use_alloc", + "either/use_std", +] [lib] +name = "itertools" +path = "src/lib.rs" test = false bench = false +[[example]] +name = "iris" +path = "examples/iris.rs" + +[[test]] +name = "adaptors_no_collect" +path = "tests/adaptors_no_collect.rs" + +[[test]] +name = "flatten_ok" +path = "tests/flatten_ok.rs" + +[[test]] +name = "laziness" +path = "tests/laziness.rs" + +[[test]] +name = "macros_hygiene" +path = "tests/macros_hygiene.rs" + +[[test]] +name = "merge_join" +path = "tests/merge_join.rs" + +[[test]] +name = "peeking_take_while" +path = "tests/peeking_take_while.rs" + +[[test]] +name = "quick" +path = "tests/quick.rs" + +[[test]] +name = "specializations" +path = "tests/specializations.rs" + +[[test]] +name = "test_core" +path = "tests/test_core.rs" + +[[test]] +name = "test_std" +path = "tests/test_std.rs" + +[[test]] +name = "tuples" +path = "tests/tuples.rs" + +[[test]] +name = "zip" +path = "tests/zip.rs" + [[bench]] -name = "tuple_combinations" +name = "bench1" +path = "benches/bench1.rs" harness = false [[bench]] -name = "tuples" +name = "combinations" +path = "benches/combinations.rs" +harness = false + +[[bench]] +name = "combinations_with_replacement" +path = "benches/combinations_with_replacement.rs" harness = false [[bench]] name = "fold_specialization" +path = "benches/fold_specialization.rs" harness = false [[bench]] -name = "combinations_with_replacement" +name = "k_smallest" +path = "benches/k_smallest.rs" harness = false [[bench]] -name = "tree_fold1" +name = "powerset" +path = "benches/powerset.rs" harness = false [[bench]] -name = "bench1" +name = "specializations" +path = "benches/specializations.rs" harness = false [[bench]] -name = "combinations" +name = "tree_reduce" +path = "benches/tree_reduce.rs" harness = false [[bench]] -name = "powerset" +name = "tuple_combinations" +path = "benches/tuple_combinations.rs" harness = false + +[[bench]] +name = "tuples" +path = "benches/tuples.rs" +harness = false + [dependencies.either] version = "1.0" default-features = false + [dev-dependencies.criterion] -version = "=0" +version = "0.4.0" +features = ["html_reports"] [dev-dependencies.paste] version = "1.0.0" @@ -82,7 +176,5 @@ [dev-dependencies.rand] version = "0.7" -[features] -default = ["use_std"] -use_alloc = [] -use_std = ["use_alloc", "either/use_std"] +[profile.bench] +debug = 2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +[package] +name = "itertools" +version = "0.14.0" + +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-itertools/itertools" +documentation = "https://docs.rs/itertools/" +authors = ["bluss"] +readme = "README.md" + +description = "Extra iterator adaptors, iterator methods, free functions, and macros." + +keywords = ["iterator", "data-structure", "zip", "product"] +categories = ["algorithms", "rust-patterns", "no-std", "no-std::no-alloc"] + +edition = "2018" + +# When bumping, please resolve all `#[allow(clippy::*)]` that are newly resolvable. +rust-version = "1.63.0" + +[lib] +bench = false +test = false + +[dependencies] +either = { version = "1.0", default-features = false } + +[dev-dependencies] +rand = "0.7" +criterion = { version = "0.4.0", features = ["html_reports"] } +paste = "1.0.0" # Used in test_std to instantiate generic tests +permutohedron = "0.2" +quickcheck = { version = "0.9", default-features = false } + +[features] +default = ["use_std"] +use_std = ["use_alloc", "either/use_std"] +use_alloc = [] + +[profile] +bench = { debug = true } + +[[bench]] +name = "tuple_combinations" +harness = false + +[[bench]] +name = "tuples" +harness = false + +[[bench]] +name = "fold_specialization" +harness = false + +[[bench]] +name = "combinations_with_replacement" +harness = false + +[[bench]] +name = "tree_reduce" +harness = false + +[[bench]] +name = "bench1" +harness = false + +[[bench]] +name = "combinations" +harness = false + +[[bench]] +name = "powerset" +harness = false + +[[bench]] +name = "specializations" +harness = false + +[[bench]] +name = "k_smallest" +harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/README.md clamav-1.4.6+dfsg/.cargo/vendor/itertools/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -4,14 +4,11 @@ Please read the [API documentation here](https://docs.rs/itertools/). -[![build_status](https://github.com/rust-itertools/itertools/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-itertools/itertools/actions) -[![crates.io](https://img.shields.io/crates/v/itertools.svg)](https://crates.io/crates/itertools) - How to use with Cargo: ```toml [dependencies] -itertools = "0.10.5" +itertools = "0.14.0" ``` How to use in your crate: @@ -21,17 +18,9 @@ ``` ## How to contribute +If you're not sure what to work on, try checking the [help wanted](https://github.com/rust-itertools/itertools/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label. -- Fix a bug or implement a new thing -- Include tests for your new feature, preferably a QuickCheck test -- Make a Pull Request - -For new features, please first consider filing a PR to [rust-lang/rust](https://github.com/rust-lang/rust), -adding your new feature to the `Iterator` trait of the standard library, if you believe it is reasonable. -If it isn't accepted there, proposing it for inclusion in ``itertools`` is a good idea. -The reason for doing is this is so that we avoid future breakage as with ``.flatten()``. -However, if your feature involves heap allocation, such as storing elements in a ``Vec``, -then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead. +See our [CONTRIBUTING.md](https://github.com/rust-itertools/itertools/blob/master/CONTRIBUTING.md) for a detailed guide. ## License diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/bench1.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/bench1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/bench1.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/bench1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,22 +1,20 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use itertools::Itertools; +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; use itertools::free::cloned; use itertools::iproduct; +use itertools::Itertools; -use std::iter::repeat; use std::cmp; +use std::iter::repeat; use std::ops::{Add, Range}; -mod extra; - -use crate::extra::ZipSlices; - fn slice_iter(c: &mut Criterion) { let xs: Vec<_> = repeat(1i32).take(20).collect(); c.bench_function("slice iter", move |b| { - b.iter(|| for elt in xs.iter() { - black_box(elt); + b.iter(|| { + for elt in xs.iter() { + black_box(elt); + } }) }); } @@ -25,8 +23,10 @@ let xs: Vec<_> = repeat(1i32).take(20).collect(); c.bench_function("slice iter rev", move |b| { - b.iter(|| for elt in xs.iter().rev() { - black_box(elt); + b.iter(|| { + for elt in xs.iter().rev() { + black_box(elt); + } }) }); } @@ -116,72 +116,6 @@ }); } -fn zipslices(c: &mut Criterion) { - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - c.bench_function("zipslices", move |b| { - b.iter(|| { - for (&x, &y) in ZipSlices::new(&xs, &ys) { - black_box(x); - black_box(y); - } - }) - }); -} - -fn zipslices_mut(c: &mut Criterion) { - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let mut ys = black_box(ys); - - c.bench_function("zipslices mut", move |b| { - b.iter(|| { - for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - black_box(x); - black_box(y); - } - }) - }); -} - -fn zipdot_i32_zipslices(c: &mut Criterion) { - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - c.bench_function("zipdot i32 zipslices", move |b| { - b.iter(|| { - let mut s = 0i32; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) - }); -} - -fn zipdot_f32_zipslices(c: &mut Criterion) { - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - c.bench_function("zipdot f32 zipslices", move |b| { - b.iter(|| { - let mut s = 0.; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) - }); -} - fn zip_checked_counted_loop(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; @@ -307,10 +241,10 @@ let len = cmp::min(xs.len(), ys.len()); for i in 0..len { unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - black_box(x); - black_box(y); + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + black_box(x); + black_box(y); } } }) @@ -329,9 +263,9 @@ let mut s = 0i32; for i in 0..len { unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; } } s @@ -351,9 +285,9 @@ let mut s = 0f32; for i in 0..len { unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; } } s @@ -374,19 +308,19 @@ let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); for i in 0..len { unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - let z = *zs.get_unchecked(i); - black_box(x); - black_box(y); - black_box(z); + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + let z = *zs.get_unchecked(i); + black_box(x); + black_box(y); + black_box(z); } } }) }); } -fn group_by_lazy_1(c: &mut Criterion) { +fn chunk_by_lazy_1(c: &mut Criterion) { let mut data = vec![0; 1024]; for (index, elt) in data.iter_mut().enumerate() { *elt = index / 10; @@ -394,10 +328,10 @@ let data = black_box(data); - c.bench_function("group by lazy 1", move |b| { + c.bench_function("chunk by lazy 1", move |b| { b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { + for (_key, chunk) in &data.iter().chunk_by(|elt| **elt) { + for elt in chunk { black_box(elt); } } @@ -405,7 +339,7 @@ }); } -fn group_by_lazy_2(c: &mut Criterion) { +fn chunk_by_lazy_2(c: &mut Criterion) { let mut data = vec![0; 1024]; for (index, elt) in data.iter_mut().enumerate() { *elt = index / 2; @@ -413,10 +347,10 @@ let data = black_box(data); - c.bench_function("group by lazy 2", move |b| { + c.bench_function("chunk by lazy 2", move |b| { b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { + for (_key, chunk) in &data.iter().chunk_by(|elt| **elt) { + for elt in chunk { black_box(elt); } } @@ -432,8 +366,8 @@ c.bench_function("slice chunks", move |b| { b.iter(|| { - for group in data.chunks(sz) { - for elt in group { + for chunk in data.chunks(sz) { + for elt in chunk { black_box(elt); } } @@ -449,8 +383,8 @@ c.bench_function("chunks lazy 1", move |b| { b.iter(|| { - for group in &data.iter().chunks(sz) { - for elt in group { + for chunk in &data.iter().chunks(sz) { + for elt in chunk { black_box(elt); } } @@ -464,17 +398,15 @@ let alpha = black_box(&data[1..]); let beta = black_box(&data[..l - 1]); - c.bench_function("equal", move |b| { - b.iter(|| { - itertools::equal(alpha, beta) - }) - }); + c.bench_function("equal", move |b| b.iter(|| itertools::equal(alpha, beta))); } fn merge_default(c: &mut Criterion) { let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -493,9 +425,7 @@ let data2 = black_box(data2); c.bench_function("merge default", move |b| { - b.iter(|| { - data1.iter().merge(&data2).count() - }) + b.iter(|| data1.iter().merge(&data2).count()) }); } @@ -503,6 +433,8 @@ let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -521,9 +453,7 @@ let data2 = black_box(data2); c.bench_function("merge by cmp", move |b| { - b.iter(|| { - data1.iter().merge_by(&data2, PartialOrd::le).count() - }) + b.iter(|| data1.iter().merge_by(&data2, PartialOrd::le).count()) }); } @@ -531,6 +461,8 @@ let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -549,9 +481,7 @@ let data2 = black_box(data2); c.bench_function("merge by lt", move |b| { - b.iter(|| { - data1.iter().merge_by(&data2, |a, b| a <= b).count() - }) + b.iter(|| data1.iter().merge_by(&data2, |a, b| a <= b).count()) }); } @@ -559,6 +489,8 @@ let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -578,9 +510,7 @@ let its = &[data1.iter(), data2.iter()]; c.bench_function("kmerge default", move |b| { - b.iter(|| { - its.iter().cloned().kmerge().count() - }) + b.iter(|| its.iter().cloned().kmerge().count()) }); } @@ -589,7 +519,7 @@ let mut state = 1729u16; fn rng(state: &mut u16) -> u16 { - let new = state.wrapping_mul(31421) + 6927; + let new = state.wrapping_mul(31421).wrapping_add(6927); *state = new; new } @@ -600,10 +530,10 @@ let mut chunks = Vec::new(); let mut rest = &mut data[..]; - while rest.len() > 0 { + while !rest.is_empty() { let chunk_len = 1 + rng(&mut state) % 512; let chunk_len = cmp::min(rest.len(), chunk_len as usize); - let (fst, tail) = {rest}.split_at_mut(chunk_len); + let (fst, tail) = { rest }.split_at_mut(chunk_len); fst.sort(); chunks.push(fst.iter().cloned()); rest = tail; @@ -612,15 +542,14 @@ // println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len()))); c.bench_function("kmerge tenway", move |b| { - b.iter(|| { - chunks.iter().cloned().kmerge().count() - }) + b.iter(|| chunks.iter().cloned().kmerge().count()) }); } fn fast_integer_sum(iter: I) -> I::Item - where I: IntoIterator, - I::Item: Default + Add +where + I: IntoIterator, + I::Item: Default + Add, { iter.into_iter().fold(<_>::default(), |x, y| x + y) } @@ -629,9 +558,7 @@ let v = vec![0; 1024]; c.bench_function("step vec 2", move |b| { - b.iter(|| { - fast_integer_sum(cloned(v.iter().step_by(2))) - }) + b.iter(|| fast_integer_sum(cloned(v.iter().step_by(2)))) }); } @@ -639,9 +566,7 @@ let v = vec![0; 1024]; c.bench_function("step vec 10", move |b| { - b.iter(|| { - fast_integer_sum(cloned(v.iter().step_by(10))) - }) + b.iter(|| fast_integer_sum(cloned(v.iter().step_by(10)))) }); } @@ -649,9 +574,7 @@ let v = black_box(0..1024); c.bench_function("step range 2", move |b| { - b.iter(|| { - fast_integer_sum(v.clone().step_by(2)) - }) + b.iter(|| fast_integer_sum(v.clone().step_by(2))) }); } @@ -659,9 +582,23 @@ let v = black_box(0..1024); c.bench_function("step range 10", move |b| { - b.iter(|| { - fast_integer_sum(v.clone().step_by(10)) - }) + b.iter(|| fast_integer_sum(v.clone().step_by(10))) + }); +} + +fn vec_iter_mut_partition(c: &mut Criterion) { + let data = std::iter::repeat(-1024i32..1024) + .take(256) + .flatten() + .collect_vec(); + c.bench_function("vec iter mut partition", move |b| { + b.iter_batched( + || data.clone(), + |mut data| { + black_box(itertools::partition(black_box(&mut data), |n| *n >= 0)); + }, + BatchSize::LargeInput, + ) }); } @@ -681,22 +618,6 @@ }); } -fn cartesian_product_fold(c: &mut Criterion) { - let xs = vec![0; 16]; - - c.bench_function("cartesian product fold", move |b| { - b.iter(|| { - let mut sum = 0; - iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| { - sum += x; - sum += y; - sum += z; - }); - sum - }) - }); -} - fn multi_cartesian_product_iterator(c: &mut Criterion) { let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; @@ -713,22 +634,6 @@ }); } -fn multi_cartesian_product_fold(c: &mut Criterion) { - let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; - - c.bench_function("multi cartesian product fold", move |b| { - b.iter(|| { - let mut sum = 0; - xs.iter().multi_cartesian_product().fold((), |(), x| { - sum += x[0]; - sum += x[1]; - sum += x[2]; - }); - sum - }) - }); -} - fn cartesian_product_nested_for(c: &mut Criterion) { let xs = vec![0; 16]; @@ -753,9 +658,7 @@ let mut xs = vec![0; 5_000_000]; xs.extend(vec![1; 5_000_000]); - c.bench_function("all equal", move |b| { - b.iter(|| xs.iter().all_equal()) - }); + c.bench_function("all equal", move |b| b.iter(|| xs.iter().all_equal())); } fn all_equal_for(c: &mut Criterion) { @@ -797,21 +700,17 @@ } c.bench_function("permutations iter", move |b| { - b.iter(|| { - for _ in NewIterator(0..PERM_COUNT).permutations(PERM_COUNT) { - - } - }) + b.iter( + || { + for _ in NewIterator(0..PERM_COUNT).permutations(PERM_COUNT) {} + }, + ) }); } fn permutations_range(c: &mut Criterion) { c.bench_function("permutations range", move |b| { - b.iter(|| { - for _ in (0..PERM_COUNT).permutations(PERM_COUNT) { - - } - }) + b.iter(|| for _ in (0..PERM_COUNT).permutations(PERM_COUNT) {}) }); } @@ -819,11 +718,7 @@ let v = (0..PERM_COUNT).collect_vec(); c.bench_function("permutations slice", move |b| { - b.iter(|| { - for _ in v.as_slice().iter().permutations(PERM_COUNT) { - - } - }) + b.iter(|| for _ in v.as_slice().iter().permutations(PERM_COUNT) {}) }); } @@ -836,10 +731,6 @@ zipdot_f32_default_zip, zip_default_zip3, zip_slices_ziptuple, - zipslices, - zipslices_mut, - zipdot_i32_zipslices, - zipdot_f32_zipslices, zip_checked_counted_loop, zipdot_i32_checked_counted_loop, zipdot_f32_checked_counted_loop, @@ -848,8 +739,8 @@ zipdot_i32_unchecked_counted_loop, zipdot_f32_unchecked_counted_loop, zip_unchecked_counted_loop3, - group_by_lazy_1, - group_by_lazy_2, + chunk_by_lazy_1, + chunk_by_lazy_2, slice_chunks, chunks_lazy_1, equal, @@ -862,10 +753,9 @@ step_vec_10, step_range_2, step_range_10, + vec_iter_mut_partition, cartesian_product_iterator, - cartesian_product_fold, multi_cartesian_product_iterator, - multi_cartesian_product_fold, cartesian_product_nested_for, all_equal, all_equal_for, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/combinations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/combinations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/combinations.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/combinations.rs 2006-07-24 01:21:28.000000000 +0000 @@ -111,15 +111,7 @@ } criterion_group!( - benches, - comb_for1, - comb_for2, - comb_for3, - comb_for4, - comb_c1, - comb_c2, - comb_c3, - comb_c4, + benches, comb_for1, comb_for2, comb_for3, comb_for4, comb_c1, comb_c2, comb_c3, comb_c4, comb_c14, ); criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/extra/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/extra/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/mod.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -pub use self::zipslices::ZipSlices; -mod zipslices; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/extra/zipslices.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/zipslices.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/extra/zipslices.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/extra/zipslices.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -use std::cmp; - -// Note: There are different ways to implement ZipSlices. -// This version performed the best in benchmarks. -// -// I also implemented a version with three pointers (tptr, tend, uptr), -// that mimiced slice::Iter and only checked bounds by using tptr == tend, -// but that was inferior to this solution. - -/// An iterator which iterates two slices simultaneously. -/// -/// `ZipSlices` acts like a double-ended `.zip()` iterator. -/// -/// It was intended to be more efficient than `.zip()`, and it was, then -/// rustc changed how it optimizes so it can not promise improved performance -/// at this time. -/// -/// Note that elements past the end of the shortest of the two slices are ignored. -/// -/// Iterator element type for `ZipSlices` is `(T::Item, U::Item)`. For example, -/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`. -#[derive(Clone)] -pub struct ZipSlices { - t: T, - u: U, - len: usize, - index: usize, -} - -impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> { - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn new(a: &'a [A], b: &'b [B]) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl ZipSlices - where T: Slice, - U: Slice -{ - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn from_slices(a: T, b: U) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl Iterator for ZipSlices - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - #[inline(always)] - fn next(&mut self) -> Option { - unsafe { - if self.index >= self.len { - None - } else { - let i = self.index; - self.index += 1; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = self.len - self.index; - (len, Some(len)) - } -} - -impl DoubleEndedIterator for ZipSlices - where T: Slice, - U: Slice -{ - #[inline(always)] - fn next_back(&mut self) -> Option { - unsafe { - if self.index >= self.len { - None - } else { - self.len -= 1; - let i = self.len; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } -} - -impl ExactSizeIterator for ZipSlices - where T: Slice, - U: Slice -{} - -unsafe impl Slice for ZipSlices - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - fn len(&self) -> usize { - self.len - self.index - } - - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - (self.t.get_unchecked(i), - self.u.get_unchecked(i)) - } -} - -/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. -/// -/// Unsafe trait because: -/// -/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. -pub unsafe trait Slice { - /// The type of a reference to the slice's elements - type Item; - #[doc(hidden)] - fn len(&self) -> usize; - #[doc(hidden)] - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; -} - -unsafe impl<'a, T> Slice for &'a [T] { - type Item = &'a T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - debug_assert!(i < self.len()); - (**self).get_unchecked(i) - } -} - -unsafe impl<'a, T> Slice for &'a mut [T] { - type Item = &'a mut T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - debug_assert!(i < self.len()); - // override the lifetime constraints of &mut &'a mut [T] - (*(*self as *mut [T])).get_unchecked_mut(i) - } -} - -#[test] -fn zipslices() { - - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys)); - - let xs = [1, 2, 3, 4, 5, 6]; - let mut ys = [0; 6]; - for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - *y = *x; - } - ::itertools::assert_equal(&xs, &ys); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/fold_specialization.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/fold_specialization.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/fold_specialization.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/fold_specialization.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,13 @@ +#![allow(unstable_name_collisions)] + use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; struct Unspecialized(I); impl Iterator for Unspecialized -where I: Iterator +where + I: Iterator, { type Item = I::Item; @@ -25,8 +28,7 @@ pub mod intersperse { use super::*; - pub fn external(c: &mut Criterion) - { + pub fn external(c: &mut Criterion) { let arr = [1; 1024]; c.bench_function("external", move |b| { @@ -40,23 +42,23 @@ }); } - pub fn internal_specialized(c: &mut Criterion) - { + pub fn internal_specialized(c: &mut Criterion) { let arr = [1; 1024]; c.bench_function("internal specialized", move |b| { b.iter(|| { + #[allow(clippy::unnecessary_fold)] arr.iter().intersperse(&0).fold(0, |acc, x| acc + x) }) }); } - pub fn internal_unspecialized(c: &mut Criterion) - { + pub fn internal_unspecialized(c: &mut Criterion) { let arr = [1; 1024]; c.bench_function("internal unspecialized", move |b| { b.iter(|| { + #[allow(clippy::unnecessary_fold)] Unspecialized(arr.iter().intersperse(&0)).fold(0, |acc, x| acc + x) }) }); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/k_smallest.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/k_smallest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/k_smallest.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/k_smallest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +use criterion::{black_box, criterion_group, criterion_main, Bencher, BenchmarkId, Criterion}; +use itertools::Itertools; +use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; + +fn strict(b: &mut Bencher, (k, vals): &(usize, &Vec)) { + b.iter(|| black_box(vals.iter()).k_smallest(*k)) +} + +fn relaxed(b: &mut Bencher, (k, vals): &(usize, &Vec)) { + b.iter(|| black_box(vals.iter()).k_smallest_relaxed(*k)) +} + +fn ascending(n: usize) -> Vec { + (0..n).collect() +} + +fn random(n: usize) -> Vec { + let mut vals = (0..n).collect_vec(); + vals.shuffle(&mut StdRng::seed_from_u64(42)); + vals +} + +fn descending(n: usize) -> Vec { + (0..n).rev().collect() +} + +fn k_smallest(c: &mut Criterion, order: &str, vals: fn(usize) -> Vec) { + let mut g = c.benchmark_group(format!("k-smallest/{order}")); + + for log_n in 20..23 { + let n = 1 << log_n; + + let vals = vals(n); + + for log_k in 7..10 { + let k = 1 << log_k; + + let params = format!("{log_n}/{log_k}"); + let input = (k, &vals); + g.bench_with_input(BenchmarkId::new("strict", ¶ms), &input, strict); + g.bench_with_input(BenchmarkId::new("relaxed", ¶ms), &input, relaxed); + } + } + + g.finish() +} + +fn k_smallest_asc(c: &mut Criterion) { + k_smallest(c, "asc", ascending); +} + +fn k_smallest_rand(c: &mut Criterion) { + k_smallest(c, "rand", random); +} + +fn k_smallest_desc(c: &mut Criterion) { + k_smallest(c, "desc", descending); +} + +criterion_group!(benches, k_smallest_asc, k_smallest_rand, k_smallest_desc); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/powerset.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/powerset.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/powerset.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/powerset.rs 2006-07-24 01:21:28.000000000 +0000 @@ -20,17 +20,64 @@ }); } -fn powerset_0(c: &mut Criterion) { powerset_n(c, 0); } +fn powerset_n_fold(c: &mut Criterion, n: usize) { + let id = format!("powerset {} fold", n); + c.bench_function(id.as_str(), move |b| { + b.iter(|| { + for _ in 0..calc_iters(n) { + (0..n).powerset().fold(0, |s, elt| s + black_box(elt).len()); + } + }) + }); +} -fn powerset_1(c: &mut Criterion) { powerset_n(c, 1); } +fn powerset_0(c: &mut Criterion) { + powerset_n(c, 0); +} -fn powerset_2(c: &mut Criterion) { powerset_n(c, 2); } +fn powerset_1(c: &mut Criterion) { + powerset_n(c, 1); +} -fn powerset_4(c: &mut Criterion) { powerset_n(c, 4); } +fn powerset_2(c: &mut Criterion) { + powerset_n(c, 2); +} -fn powerset_8(c: &mut Criterion) { powerset_n(c, 8); } +fn powerset_4(c: &mut Criterion) { + powerset_n(c, 4); +} -fn powerset_12(c: &mut Criterion) { powerset_n(c, 12); } +fn powerset_8(c: &mut Criterion) { + powerset_n(c, 8); +} + +fn powerset_12(c: &mut Criterion) { + powerset_n(c, 12); +} + +fn powerset_0_fold(c: &mut Criterion) { + powerset_n_fold(c, 0); +} + +fn powerset_1_fold(c: &mut Criterion) { + powerset_n_fold(c, 1); +} + +fn powerset_2_fold(c: &mut Criterion) { + powerset_n_fold(c, 2); +} + +fn powerset_4_fold(c: &mut Criterion) { + powerset_n_fold(c, 4); +} + +fn powerset_8_fold(c: &mut Criterion) { + powerset_n_fold(c, 8); +} + +fn powerset_12_fold(c: &mut Criterion) { + powerset_n_fold(c, 12); +} criterion_group!( benches, @@ -40,5 +87,11 @@ powerset_4, powerset_8, powerset_12, + powerset_0_fold, + powerset_1_fold, + powerset_2_fold, + powerset_4_fold, + powerset_8_fold, + powerset_12_fold, ); -criterion_main!(benches); \ No newline at end of file +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/specializations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/specializations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/specializations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/specializations.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,669 @@ +#![allow(unstable_name_collisions)] + +use criterion::black_box; +use criterion::BenchmarkId; +use itertools::Itertools; + +const NTH_INPUTS: &[usize] = &[0, 1, 2, 4, 8]; + +/// Create multiple functions each defining a benchmark group about iterator methods. +/// +/// Each created group has functions with the following ids: +/// +/// - `next`, `size_hint`, `count`, `last`, `nth`, `collect`, `fold` +/// - and when marked as `DoubleEndedIterator`: `next_back`, `nth_back`, `rfold` +/// - and when marked as `ExactSizeIterator`: `len` +/// +/// Note that this macro can be called only once. +macro_rules! bench_specializations { + ( + $( + $name:ident { + $($extra:ident)* + {$( + $init:stmt; + )*} + $iterator:expr + } + )* + ) => { + $( + #[allow(unused_must_use)] + fn $name(c: &mut ::criterion::Criterion) { + let mut bench_group = c.benchmark_group(stringify!($name)); + $( + $init + )* + let bench_first_its = { + let mut bench_idx = 0; + [0; 1000].map(|_| { + let mut it = $iterator; + if bench_idx != 0 { + it.nth(bench_idx - 1); + } + bench_idx += 1; + it + }) + }; + bench_specializations!(@Iterator bench_group bench_first_its: $iterator); + $( + bench_specializations!(@$extra bench_group bench_first_its: $iterator); + )* + bench_group.finish(); + } + )* + + ::criterion::criterion_group!(benches, $($name, )*); + ::criterion::criterion_main!(benches); + }; + + (@Iterator $group:ident $first_its:ident: $iterator:expr) => { + $group.bench_function("next", |bencher| bencher.iter(|| { + let mut it = $iterator; + while let Some(x) = it.next() { + black_box(x); + } + })); + $group.bench_function("size_hint", |bencher| bencher.iter(|| { + $first_its.iter().for_each(|it| { + black_box(it.size_hint()); + }) + })); + $group.bench_function("count", |bencher| bencher.iter(|| { + $iterator.count() + })); + $group.bench_function("last", |bencher| bencher.iter(|| { + $iterator.last() + })); + for n in NTH_INPUTS { + $group.bench_with_input(BenchmarkId::new("nth", n), n, |bencher, n| bencher.iter(|| { + for start in 0_usize..10 { + let mut it = $iterator; + if let Some(s) = start.checked_sub(1) { + black_box(it.nth(s)); + } + while let Some(x) = it.nth(*n) { + black_box(x); + } + } + })); + } + $group.bench_function("collect", |bencher| bencher.iter(|| { + $iterator.collect::>() + })); + $group.bench_function("fold", |bencher| bencher.iter(|| { + $iterator.fold((), |(), x| { + black_box(x); + }) + })); + }; + + (@DoubleEndedIterator $group:ident $_first_its:ident: $iterator:expr) => { + $group.bench_function("next_back", |bencher| bencher.iter(|| { + let mut it = $iterator; + while let Some(x) = it.next_back() { + black_box(x); + } + })); + for n in NTH_INPUTS { + $group.bench_with_input(BenchmarkId::new("nth_back", n), n, |bencher, n| bencher.iter(|| { + for start in 0_usize..10 { + let mut it = $iterator; + if let Some(s) = start.checked_sub(1) { + black_box(it.nth_back(s)); + } + while let Some(x) = it.nth_back(*n) { + black_box(x); + } + } + })); + } + $group.bench_function("rfold", |bencher| bencher.iter(|| { + $iterator.rfold((), |(), x| { + black_box(x); + }) + })); + }; + + (@ExactSizeIterator $group:ident $first_its:ident: $_iterator:expr) => { + $group.bench_function("len", |bencher| bencher.iter(|| { + $first_its.iter().for_each(|it| { + black_box(it.len()); + }) + })); + }; +} + +// Usage examples: +// - For `ZipLongest::fold` only: +// cargo bench --bench specializations zip_longest/fold +// - For `.combinations(k).nth(8)`: +// cargo bench --bench specializations combinations./nth/8 +bench_specializations! { + interleave { + { + let v1 = black_box(vec![0; 1024]); + let v2 = black_box(vec![0; 768]); + } + v1.iter().interleave(&v2) + } + interleave_shortest { + { + let v1 = black_box(vec![0; 1024]); + let v2 = black_box(vec![0; 768]); + } + v1.iter().interleave_shortest(&v2) + } + batching { + { + let v = black_box(vec![0; 1024]); + } + v.iter().batching(Iterator::next) + } + tuple_windows1 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuple_windows::<(_,)>() + } + tuple_windows2 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuple_windows::<(_, _)>() + } + tuple_windows3 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuple_windows::<(_, _, _)>() + } + tuple_windows4 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuple_windows::<(_, _, _, _)>() + } + circular_tuple_windows1 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().circular_tuple_windows::<(_,)>() + } + circular_tuple_windows2 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().circular_tuple_windows::<(_, _)>() + } + circular_tuple_windows3 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().circular_tuple_windows::<(_, _, _)>() + } + circular_tuple_windows4 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().circular_tuple_windows::<(_, _, _, _)>() + } + tuples1 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuples::<(_,)>() + } + tuples2 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuples::<(_, _)>() + } + tuples3 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuples::<(_, _, _)>() + } + tuples4 { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuples::<(_, _, _, _)>() + } + tuple_buffer { + ExactSizeIterator + { + let v = black_box(vec![0; 11]); + // Short but the buffer can't have 12 or more elements. + } + { + let mut it = v.iter().tuples::<(_, _, _, _, _, _, _, _, _, _, _, _)>(); + it.next(); // No element but it fills the buffer. + it.into_buffer() + } + } + cartesian_product { + { + let v = black_box(vec![0; 16]); + } + itertools::iproduct!(&v, &v, &v) + } + multi_cartesian_product { + { + let vs = black_box([0; 3].map(|_| vec![0; 16])); + } + vs.iter().multi_cartesian_product() + } + coalesce { + { + let v = black_box(vec![0; 1024]); + } + v.iter().coalesce(|x, y| if x == y { Ok(x) } else { Err((x, y)) }) + } + dedup { + { + let v = black_box((0..32).flat_map(|x| [x; 32]).collect_vec()); + } + v.iter().dedup() + } + dedup_by { + { + let v = black_box((0..32).flat_map(|x| [x; 32]).collect_vec()); + } + v.iter().dedup_by(PartialOrd::ge) + } + dedup_with_count { + { + let v = black_box((0..32).flat_map(|x| [x; 32]).collect_vec()); + } + v.iter().dedup_with_count() + } + dedup_by_with_count { + { + let v = black_box((0..32).flat_map(|x| [x; 32]).collect_vec()); + } + v.iter().dedup_by_with_count(PartialOrd::ge) + } + duplicates { + DoubleEndedIterator + { + let v = black_box((0..32).cycle().take(1024).collect_vec()); + } + v.iter().duplicates() + } + duplicates_by { + DoubleEndedIterator + { + let v = black_box((0..1024).collect_vec()); + } + v.iter().duplicates_by(|x| *x % 10) + } + unique { + DoubleEndedIterator + { + let v = black_box((0..32).cycle().take(1024).collect_vec()); + } + v.iter().unique() + } + unique_by { + DoubleEndedIterator + { + let v = black_box((0..1024).collect_vec()); + } + v.iter().unique_by(|x| *x % 50) + } + take_while_inclusive { + { + let v = black_box((0..1024).collect_vec()); + } + v.iter().take_while_inclusive(|x| **x < 1000) + } + pad_using { + DoubleEndedIterator + ExactSizeIterator + { + let v = black_box((0..1024).collect_vec()); + } + v.iter().copied().pad_using(2048, |i| 5 * i) + } + positions { + DoubleEndedIterator + { + let v = black_box((0..1024).collect_vec()); + } + v.iter().positions(|x| x % 5 == 0) + } + update { + DoubleEndedIterator + ExactSizeIterator + { + let v = black_box((0_i32..1024).collect_vec()); + } + v.iter().copied().update(|x| *x *= 7) + } + tuple_combinations1 { + { + let v = black_box(vec![0; 1024]); + } + v.iter().tuple_combinations::<(_,)>() + } + tuple_combinations2 { + { + let v = black_box(vec![0; 64]); + } + v.iter().tuple_combinations::<(_, _)>() + } + tuple_combinations3 { + { + let v = black_box(vec![0; 64]); + } + v.iter().tuple_combinations::<(_, _, _)>() + } + tuple_combinations4 { + { + let v = black_box(vec![0; 64]); + } + v.iter().tuple_combinations::<(_, _, _, _)>() + } + intersperse { + { + let v = black_box(vec![0; 1024]); + let n = black_box(0); + } + v.iter().intersperse(&n) + } + intersperse_with { + { + let v = black_box(vec![0; 1024]); + let n = black_box(0); + } + v.iter().intersperse_with(|| &n) + } + combinations1 { + { + let v = black_box(vec![0; 1792]); + } + v.iter().combinations(1) + } + combinations2 { + { + let v = black_box(vec![0; 60]); + } + v.iter().combinations(2) + } + combinations3 { + { + let v = black_box(vec![0; 23]); + } + v.iter().combinations(3) + } + combinations4 { + { + let v = black_box(vec![0; 16]); + } + v.iter().combinations(4) + } + combinations_with_replacement1 { + { + let v = black_box(vec![0; 4096]); + } + v.iter().combinations_with_replacement(1) + } + combinations_with_replacement2 { + { + let v = black_box(vec![0; 90]); + } + v.iter().combinations_with_replacement(2) + } + combinations_with_replacement3 { + { + let v = black_box(vec![0; 28]); + } + v.iter().combinations_with_replacement(3) + } + combinations_with_replacement4 { + { + let v = black_box(vec![0; 16]); + } + v.iter().combinations_with_replacement(4) + } + permutations1 { + { + let v = black_box(vec![0; 1024]); + } + v.iter().permutations(1) + } + permutations2 { + { + let v = black_box(vec![0; 36]); + } + v.iter().permutations(2) + } + permutations3 { + { + let v = black_box(vec![0; 12]); + } + v.iter().permutations(3) + } + permutations4 { + { + let v = black_box(vec![0; 8]); + } + v.iter().permutations(4) + } + powerset { + { + let v = black_box(vec![0; 10]); + } + v.iter().powerset() + } + while_some { + {} + (0..) + .map(black_box) + .map(|i| char::from_digit(i, 16)) + .while_some() + } + with_position { + ExactSizeIterator + { + let v = black_box((0..10240).collect_vec()); + } + v.iter().with_position() + } + zip_longest { + DoubleEndedIterator + ExactSizeIterator + { + let xs = black_box(vec![0; 1024]); + let ys = black_box(vec![0; 768]); + } + xs.iter().zip_longest(ys.iter()) + } + zip_eq { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + v.iter().zip_eq(v.iter().rev()) + } + multizip { + DoubleEndedIterator + ExactSizeIterator + { + let v1 = black_box(vec![0; 1024]); + let v2 = black_box(vec![0; 768]); + let v3 = black_box(vec![0; 2048]); + } + itertools::multizip((&v1, &v2, &v3)) + } + izip { + DoubleEndedIterator + ExactSizeIterator + { + let v1 = black_box(vec![0; 1024]); + let v2 = black_box(vec![0; 768]); + let v3 = black_box(vec![0; 2048]); + } + itertools::izip!(&v1, &v2, &v3) + } + put_back { + { + let v = black_box(vec![0; 1024]); + } + itertools::put_back(&v).with_value(black_box(&0)) + } + put_back_n { + { + let v1 = black_box(vec![0; 1024]); + let v2 = black_box(vec![0; 16]); + } + { + let mut it = itertools::put_back_n(&v1); + for n in &v2 { + it.put_back(n); + } + it + } + } + exactly_one_error { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + } + // Use `at_most_one` would be similar. + v.iter().exactly_one().unwrap_err() + } + multipeek { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + let n = black_box(16); + } + { + let mut it = v.iter().multipeek(); + for _ in 0..n { + it.peek(); + } + it + } + } + peek_nth { + ExactSizeIterator + { + let v = black_box(vec![0; 1024]); + let n = black_box(16); + } + { + let mut it = itertools::peek_nth(&v); + it.peek_nth(n); + it + } + } + repeat_n { + DoubleEndedIterator + ExactSizeIterator + {} + itertools::repeat_n(black_box(0), black_box(1024)) + } + merge { + { + let v1 = black_box((0..1024).collect_vec()); + let v2 = black_box((0..768).collect_vec()); + } + v1.iter().merge(&v2) + } + merge_by { + { + let v1 = black_box((0..1024).collect_vec()); + let v2 = black_box((0..768).collect_vec()); + } + v1.iter().merge_by(&v2, PartialOrd::ge) + } + merge_join_by_ordering { + { + let v1 = black_box((0..1024).collect_vec()); + let v2 = black_box((0..768).collect_vec()); + } + v1.iter().merge_join_by(&v2, Ord::cmp) + } + merge_join_by_bool { + { + let v1 = black_box((0..1024).collect_vec()); + let v2 = black_box((0..768).collect_vec()); + } + v1.iter().merge_join_by(&v2, PartialOrd::ge) + } + kmerge { + { + let vs = black_box(vec![vec![0; 1024], vec![0; 256], vec![0; 768]]); + } + vs.iter().kmerge() + } + kmerge_by { + { + let vs = black_box(vec![vec![0; 1024], vec![0; 256], vec![0; 768]]); + } + vs.iter().kmerge_by(PartialOrd::ge) + } + map_into { + DoubleEndedIterator + ExactSizeIterator + { + let v = black_box(vec![0_u8; 1024]); + } + v.iter().copied().map_into::() + } + map_ok { + DoubleEndedIterator + ExactSizeIterator + { + let v = black_box((0_u32..1024) + .map(|x| if x % 2 == 1 { Err(x) } else { Ok(x) }) + .collect_vec()); + } + v.iter().copied().map_ok(|x| x + 1) + } + filter_ok { + DoubleEndedIterator + { + let v = black_box((0_u32..1024) + .map(|x| if x % 2 == 1 { Err(x) } else { Ok(x) }) + .collect_vec()); + } + v.iter().copied().filter_ok(|x| x % 3 == 0) + } + filter_map_ok { + DoubleEndedIterator + { + let v = black_box((0_u32..1024) + .map(|x| if x % 2 == 1 { Err(x) } else { Ok(x) }) + .collect_vec()); + } + v.iter().copied().filter_map_ok(|x| if x % 3 == 0 { Some(x + 1) } else { None }) + } + flatten_ok { + DoubleEndedIterator + { + let d = black_box(vec![0; 8]); + let v = black_box((0..512) + .map(|x| if x % 2 == 0 { Ok(&d) } else { Err(x) }) + .collect_vec()); + } + v.iter().copied().flatten_ok() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tree_fold1.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_fold1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tree_fold1.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_fold1.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use itertools::{Itertools, cloned}; - -trait IterEx : Iterator { - // Another efficient implementation against which to compare, - // but needs `std` so is less desirable. - fn tree_fold1_vec(self, mut f: F) -> Option - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - let hint = self.size_hint().0; - let cap = std::mem::size_of::() * 8 - hint.leading_zeros() as usize; - let mut stack = Vec::with_capacity(cap); - self.enumerate().for_each(|(mut i, mut x)| { - while (i & 1) != 0 { - x = f(stack.pop().unwrap(), x); - i >>= 1; - } - stack.push(x); - }); - stack.into_iter().fold1(f) - } -} -impl IterEx for T {} - -macro_rules! def_benchs { - ($N:expr, - $FUN:ident, - $BENCH_NAME:ident, - ) => ( - mod $BENCH_NAME { - use super::*; - - pub fn sum(c: &mut Criterion) { - let v: Vec = (0.. $N).collect(); - - c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " sum"), move |b| { - b.iter(|| { - cloned(&v).$FUN(|x, y| x + y) - }) - }); - } - - pub fn complex_iter(c: &mut Criterion) { - let u = (3..).take($N / 2); - let v = (5..).take($N / 2); - let it = u.chain(v); - - c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " complex iter"), move |b| { - b.iter(|| { - it.clone().map(|x| x as f32).$FUN(f32::atan2) - }) - }); - } - - pub fn string_format(c: &mut Criterion) { - // This goes quadratic with linear `fold1`, so use a smaller - // size to not waste too much time in travis. The allocations - // in here are so expensive anyway that it'll still take - // way longer per iteration than the other two benchmarks. - let v: Vec = (0.. ($N/4)).collect(); - - c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " string format"), move |b| { - b.iter(|| { - cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) - }) - }); - } - } - - criterion_group!( - $BENCH_NAME, - $BENCH_NAME::sum, - $BENCH_NAME::complex_iter, - $BENCH_NAME::string_format, - ); - ) -} - -def_benchs!{ - 10_000, - fold1, - fold1_10k, -} - -def_benchs!{ - 10_000, - tree_fold1, - tree_fold1_stack_10k, -} - -def_benchs!{ - 10_000, - tree_fold1_vec, - tree_fold1_vec_10k, -} - -def_benchs!{ - 100, - fold1, - fold1_100, -} - -def_benchs!{ - 100, - tree_fold1, - tree_fold1_stack_100, -} - -def_benchs!{ - 100, - tree_fold1_vec, - tree_fold1_vec_100, -} - -def_benchs!{ - 8, - fold1, - fold1_08, -} - -def_benchs!{ - 8, - tree_fold1, - tree_fold1_stack_08, -} - -def_benchs!{ - 8, - tree_fold1_vec, - tree_fold1_vec_08, -} - -criterion_main!( - fold1_10k, - tree_fold1_stack_10k, - tree_fold1_vec_10k, - fold1_100, - tree_fold1_stack_100, - tree_fold1_vec_100, - fold1_08, - tree_fold1_stack_08, - tree_fold1_vec_08, -); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tree_reduce.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_reduce.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tree_reduce.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tree_reduce.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,150 @@ +#![allow(deprecated)] + +use criterion::{criterion_group, criterion_main, Criterion}; +use itertools::{cloned, Itertools}; + +trait IterEx: Iterator { + // Another efficient implementation against which to compare, + // but needs `std` so is less desirable. + fn tree_reduce_vec(self, mut f: F) -> Option + where + F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + let hint = self.size_hint().0; + let cap = std::mem::size_of::() * 8 - hint.leading_zeros() as usize; + let mut stack = Vec::with_capacity(cap); + self.enumerate().for_each(|(mut i, mut x)| { + while (i & 1) != 0 { + x = f(stack.pop().unwrap(), x); + i >>= 1; + } + stack.push(x); + }); + stack.into_iter().fold1(f) + } +} +impl IterEx for T {} + +macro_rules! def_benchs { + ($N:expr, + $FUN:ident, + $BENCH_NAME:ident, + ) => { + mod $BENCH_NAME { + use super::*; + + pub fn sum(c: &mut Criterion) { + let v: Vec = (0..$N).collect(); + + c.bench_function( + &(stringify!($BENCH_NAME).replace('_', " ") + " sum"), + move |b| b.iter(|| cloned(&v).$FUN(|x, y| x + y)), + ); + } + + pub fn complex_iter(c: &mut Criterion) { + let u = (3..).take($N / 2); + let v = (5..).take($N / 2); + let it = u.chain(v); + + c.bench_function( + &(stringify!($BENCH_NAME).replace('_', " ") + " complex iter"), + move |b| b.iter(|| it.clone().map(|x| x as f32).$FUN(f32::atan2)), + ); + } + + pub fn string_format(c: &mut Criterion) { + // This goes quadratic with linear `fold1`, so use a smaller + // size to not waste too much time in travis. The allocations + // in here are so expensive anyway that it'll still take + // way longer per iteration than the other two benchmarks. + let v: Vec = (0..($N / 4)).collect(); + + c.bench_function( + &(stringify!($BENCH_NAME).replace('_', " ") + " string format"), + move |b| { + b.iter(|| { + cloned(&v) + .map(|x| x.to_string()) + .$FUN(|x, y| format!("{} + {}", x, y)) + }) + }, + ); + } + } + + criterion_group!( + $BENCH_NAME, + $BENCH_NAME::sum, + $BENCH_NAME::complex_iter, + $BENCH_NAME::string_format, + ); + }; +} + +def_benchs! { + 10_000, + fold1, + fold1_10k, +} + +def_benchs! { + 10_000, + tree_reduce, + tree_reduce_stack_10k, +} + +def_benchs! { + 10_000, + tree_reduce_vec, + tree_reduce_vec_10k, +} + +def_benchs! { + 100, + fold1, + fold1_100, +} + +def_benchs! { + 100, + tree_reduce, + tree_reduce_stack_100, +} + +def_benchs! { + 100, + tree_reduce_vec, + tree_reduce_vec_100, +} + +def_benchs! { + 8, + fold1, + fold1_08, +} + +def_benchs! { + 8, + tree_reduce, + tree_reduce_stack_08, +} + +def_benchs! { + 8, + tree_reduce_vec, + tree_reduce_vec_08, +} + +criterion_main!( + fold1_10k, + tree_reduce_stack_10k, + tree_reduce_vec_10k, + fold1_100, + tree_reduce_stack_100, + tree_reduce_vec_100, + fold1_08, + tree_reduce_stack_08, + tree_reduce_vec_08, +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tuples.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tuples.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/benches/tuples.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/benches/tuples.rs 2006-07-24 01:21:28.000000000 +0000 @@ -33,7 +33,7 @@ s4(s[0], s[1], s[2], s[3]) } -fn sum_t1(s: &(&u32, )) -> u32 { +fn sum_t1(s: &(&u32,)) -> u32 { s1(*s.0) } @@ -60,9 +60,9 @@ $WINDOWS:ident; $FOR_CHUNKS:ident, $FOR_WINDOWS:ident - ) => ( + ) => { fn $FOR_CHUNKS(c: &mut Criterion) { - let v: Vec = (0.. $N * 1_000).collect(); + let v: Vec = (0..$N * 1_000).collect(); let mut s = 0; c.bench_function(&stringify!($FOR_CHUNKS).replace('_', " "), move |b| { b.iter(|| { @@ -90,7 +90,7 @@ } fn $TUPLES(c: &mut Criterion) { - let v: Vec = (0.. $N * 1_000).collect(); + let v: Vec = (0..$N * 1_000).collect(); let mut s = 0; c.bench_function(&stringify!($TUPLES).replace('_', " "), move |b| { b.iter(|| { @@ -103,7 +103,7 @@ } fn $CHUNKS(c: &mut Criterion) { - let v: Vec = (0.. $N * 1_000).collect(); + let v: Vec = (0..$N * 1_000).collect(); let mut s = 0; c.bench_function(&stringify!($CHUNKS).replace('_', " "), move |b| { b.iter(|| { @@ -150,10 +150,10 @@ $TUPLE_WINDOWS, $WINDOWS, ); - ) + }; } -def_benchs!{ +def_benchs! { 1; benches_1, sum_t1, @@ -166,7 +166,7 @@ for_windows_1 } -def_benchs!{ +def_benchs! { 2; benches_2, sum_t2, @@ -179,7 +179,7 @@ for_windows_2 } -def_benchs!{ +def_benchs! { 3; benches_3, sum_t3, @@ -192,7 +192,7 @@ for_windows_3 } -def_benchs!{ +def_benchs! { 4; benches_4, sum_t4, @@ -205,9 +205,4 @@ for_windows_4 } -criterion_main!( - benches_1, - benches_2, - benches_3, - benches_4, -); +criterion_main!(benches_1, benches_2, benches_3, benches_4,); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/itertools/clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/clippy.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/clippy.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -msrv = "1.36.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/examples/iris.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/examples/iris.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/examples/iris.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/examples/iris.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,14 +3,13 @@ /// and does some simple manipulations. /// /// Iterators and itertools functionality are used throughout. - use itertools::Itertools; use std::collections::HashMap; use std::iter::repeat; use std::num::ParseFloatError; use std::str::FromStr; -static DATA: &'static str = include_str!("iris.data"); +static DATA: &str = include_str!("iris.data"); #[derive(Clone, Debug)] struct Iris { @@ -18,6 +17,7 @@ data: [f32; 4], } +#[allow(dead_code)] // fields are currently ignored #[derive(Clone, Debug)] enum ParseError { Numeric(ParseFloatError), @@ -26,7 +26,7 @@ impl From for ParseError { fn from(err: ParseFloatError) -> Self { - ParseError::Numeric(err) + Self::Numeric(err) } } @@ -35,8 +35,11 @@ type Err = ParseError; fn from_str(s: &str) -> Result { - let mut iris = Iris { name: "".into(), data: [0.; 4] }; - let mut parts = s.split(",").map(str::trim); + let mut iris = Self { + name: "".into(), + data: [0.; 4], + }; + let mut parts = s.split(',').map(str::trim); // using Iterator::by_ref() for (index, part) in parts.by_ref().take(4).enumerate() { @@ -45,7 +48,7 @@ if let Some(name) = parts.next() { iris.name = name.into(); } else { - return Err(ParseError::Other("Missing name")) + return Err(ParseError::Other("Missing name")); } Ok(iris) } @@ -53,12 +56,13 @@ fn main() { // using Itertools::fold_results to create the result of parsing - let irises = DATA.lines() - .map(str::parse) - .fold_ok(Vec::new(), |mut v, iris: Iris| { - v.push(iris); - v - }); + let irises = DATA + .lines() + .map(str::parse) + .fold_ok(Vec::new(), |mut v, iris: Iris| { + v.push(iris); + v + }); let mut irises = match irises { Err(e) => { println!("Error parsing: {:?}", e); @@ -74,19 +78,18 @@ let mut plot_symbols = "+ox".chars().cycle(); let mut symbolmap = HashMap::new(); - // using Itertools::group_by - for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) { + // using Itertools::chunk_by + for (species, species_chunk) in &irises.iter().chunk_by(|iris| &iris.name) { // assign a plot symbol - symbolmap.entry(species).or_insert_with(|| { - plot_symbols.next().unwrap() - }); + symbolmap + .entry(species) + .or_insert_with(|| plot_symbols.next().unwrap()); println!("{} (symbol={})", species, symbolmap[species]); - for iris in species_group { + for iris in species_chunk { // using Itertools::format for lazy formatting println!("{:>3.1}", iris.data.iter().format(", ")); } - } // Look at all combinations of the four columns diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/coalesce.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/coalesce.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/coalesce.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/coalesce.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,62 +4,78 @@ use crate::size_hint; #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct CoalesceBy +pub struct CoalesceBy where I: Iterator, + C: CountItem, { iter: I, - last: Option, + /// `last` is `None` while no item have been taken out of `iter` (at definition). + /// Then `last` will be `Some(Some(item))` until `iter` is exhausted, + /// in which case `last` will be `Some(None)`. + last: Option>, f: F, } -impl Clone for CoalesceBy +impl Clone for CoalesceBy where - I: Iterator, + I: Clone + Iterator, + F: Clone, + C: CountItem, + C::CItem: Clone, { clone_fields!(last, iter, f); } -impl fmt::Debug for CoalesceBy +impl fmt::Debug for CoalesceBy where I: Iterator + fmt::Debug, - T: fmt::Debug, + C: CountItem, + C::CItem: fmt::Debug, { - debug_fmt_fields!(CoalesceBy, iter); + debug_fmt_fields!(CoalesceBy, iter, last); } pub trait CoalescePredicate { fn coalesce_pair(&mut self, t: T, item: Item) -> Result; } -impl Iterator for CoalesceBy +impl Iterator for CoalesceBy where I: Iterator, - F: CoalescePredicate, + F: CoalescePredicate, + C: CountItem, { - type Item = T; + type Item = C::CItem; fn next(&mut self) -> Option { + let Self { iter, last, f } = self; // this fuses the iterator - let last = self.last.take()?; + let init = match last { + Some(elt) => elt.take(), + None => { + *last = Some(None); + iter.next().map(C::new) + } + }?; - let self_last = &mut self.last; - let self_f = &mut self.f; Some( - self.iter - .try_fold(last, |last, next| match self_f.coalesce_pair(last, next) { - Ok(joined) => Ok(joined), - Err((last_, next_)) => { - *self_last = Some(next_); - Err(last_) - } - }) - .unwrap_or_else(|x| x), + iter.try_fold(init, |accum, next| match f.coalesce_pair(accum, next) { + Ok(joined) => Ok(joined), + Err((last_, next_)) => { + *last = Some(Some(next_)); + Err(last_) + } + }) + .unwrap_or_else(|x| x), ) } fn size_hint(&self) -> (usize, Option) { - let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), self.last.is_some() as usize); + let (low, hi) = size_hint::add_scalar( + self.iter.size_hint(), + matches!(self.last, Some(Some(_))) as usize, + ); ((low > 0) as usize, hi) } @@ -67,9 +83,13 @@ where FnAcc: FnMut(Acc, Self::Item) -> Acc, { - if let Some(last) = self.last { - let mut f = self.f; - let (last, acc) = self.iter.fold((last, acc), |(last, acc), elt| { + let Self { + mut iter, + last, + mut f, + } = self; + if let Some(last) = last.unwrap_or_else(|| iter.next().map(C::new)) { + let (last, acc) = iter.fold((last, acc), |(last, acc), elt| { match f.coalesce_pair(last, elt) { Ok(joined) => (joined, acc), Err((last_, next_)) => (next_, fn_acc(acc, last_)), @@ -82,12 +102,43 @@ } } -impl, T> FusedIterator for CoalesceBy {} +impl FusedIterator for CoalesceBy +where + I: Iterator, + F: CoalescePredicate, + C: CountItem, +{ +} + +pub struct NoCount; + +pub struct WithCount; + +pub trait CountItem { + type CItem; + fn new(t: T) -> Self::CItem; +} + +impl CountItem for NoCount { + type CItem = T; + #[inline(always)] + fn new(t: T) -> T { + t + } +} + +impl CountItem for WithCount { + type CItem = (usize, T); + #[inline(always)] + fn new(t: T) -> (usize, T) { + (1, t) + } +} /// An iterator adaptor that may join together adjacent elements. /// /// See [`.coalesce()`](crate::Itertools::coalesce) for more information. -pub type Coalesce = CoalesceBy::Item>; +pub type Coalesce = CoalesceBy; impl CoalescePredicate for F where @@ -99,12 +150,12 @@ } /// Create a new `Coalesce`. -pub fn coalesce(mut iter: I, f: F) -> Coalesce +pub fn coalesce(iter: I, f: F) -> Coalesce where I: Iterator, { Coalesce { - last: iter.next(), + last: None, iter, f, } @@ -113,7 +164,7 @@ /// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function. /// /// See [`.dedup_by()`](crate::Itertools::dedup_by) or [`.dedup()`](crate::Itertools::dedup) for more information. -pub type DedupBy = CoalesceBy, ::Item>; +pub type DedupBy = CoalesceBy, NoCount>; #[derive(Clone)] pub struct DedupPred2CoalescePred(DP); @@ -156,12 +207,12 @@ } /// Create a new `DedupBy`. -pub fn dedup_by(mut iter: I, dedup_pred: Pred) -> DedupBy +pub fn dedup_by(iter: I, dedup_pred: Pred) -> DedupBy where I: Iterator, { DedupBy { - last: iter.next(), + last: None, iter, f: DedupPred2CoalescePred(dedup_pred), } @@ -186,7 +237,7 @@ /// See [`.dedup_by_with_count()`](crate::Itertools::dedup_by_with_count) or /// [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information. pub type DedupByWithCount = - CoalesceBy, (usize, ::Item)>; + CoalesceBy, WithCount>; #[derive(Clone, Debug)] pub struct DedupPredWithCount2CoalescePred(DP); @@ -215,12 +266,12 @@ pub type DedupWithCount = DedupByWithCount; /// Create a new `DedupByWithCount`. -pub fn dedup_by_with_count(mut iter: I, dedup_pred: Pred) -> DedupByWithCount +pub fn dedup_by_with_count(iter: I, dedup_pred: Pred) -> DedupByWithCount where I: Iterator, { DedupByWithCount { - last: iter.next().map(|v| (1, v)), + last: None, iter, f: DedupPredWithCount2CoalescePred(dedup_pred), } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/map.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/map.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,8 +4,8 @@ #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct MapSpecialCase { - iter: I, - f: F, + pub(crate) iter: I, + pub(crate) f: F, } pub trait MapSpecialCaseFn { @@ -67,10 +67,6 @@ /// See [`.map_ok()`](crate::Itertools::map_ok) for more information. pub type MapOk = MapSpecialCase>; -/// See [`MapOk`]. -#[deprecated(note = "Use MapOk instead", since = "0.10.0")] -pub type MapResults = MapOk; - impl MapSpecialCaseFn> for MapSpecialCaseFnOk where F: FnMut(T) -> U, @@ -112,9 +108,19 @@ } } -#[derive(Clone, Debug)] pub struct MapSpecialCaseFnInto(PhantomData); +impl std::fmt::Debug for MapSpecialCaseFnInto { + debug_fmt_fields!(MapSpecialCaseFnInto, 0); +} + +impl Clone for MapSpecialCaseFnInto { + #[inline] + fn clone(&self) -> Self { + Self(PhantomData) + } +} + /// Create a new [`MapInto`] iterator. pub fn map_into(iter: I) -> MapInto { MapSpecialCase { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,19 +5,17 @@ //! except according to those terms. mod coalesce; -mod map; +pub(crate) mod map; mod multi_product; pub use self::coalesce::*; pub use self::map::{map_into, map_ok, MapInto, MapOk}; -#[allow(deprecated)] -pub use self::map::MapResults; #[cfg(feature = "use_alloc")] pub use self::multi_product::*; +use crate::size_hint::{self, SizeHint}; use std::fmt; -use std::iter::{Fuse, Peekable, FromIterator, FusedIterator}; +use std::iter::{Enumerate, FromIterator, Fuse, FusedIterator}; use std::marker::PhantomData; -use crate::size_hint; /// An iterator adaptor that alternates elements from two iterators until both /// run out. @@ -28,55 +26,90 @@ #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Interleave { - a: Fuse, - b: Fuse, - flag: bool, + i: Fuse, + j: Fuse, + next_coming_from_j: bool, } /// Create an iterator that interleaves elements in `i` and `j`. /// -/// [`IntoIterator`] enabled version of `[Itertools::interleave]`. -pub fn interleave(i: I, j: J) -> Interleave<::IntoIter, ::IntoIter> - where I: IntoIterator, - J: IntoIterator +/// [`IntoIterator`] enabled version of [`Itertools::interleave`](crate::Itertools::interleave). +pub fn interleave( + i: I, + j: J, +) -> Interleave<::IntoIter, ::IntoIter> +where + I: IntoIterator, + J: IntoIterator, { Interleave { - a: i.into_iter().fuse(), - b: j.into_iter().fuse(), - flag: false, + i: i.into_iter().fuse(), + j: j.into_iter().fuse(), + next_coming_from_j: false, } } impl Iterator for Interleave - where I: Iterator, - J: Iterator +where + I: Iterator, + J: Iterator, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - self.flag = !self.flag; - if self.flag { - match self.a.next() { - None => self.b.next(), + self.next_coming_from_j = !self.next_coming_from_j; + if self.next_coming_from_j { + match self.i.next() { + None => self.j.next(), r => r, } } else { - match self.b.next() { - None => self.a.next(), + match self.j.next() { + None => self.i.next(), r => r, } } } fn size_hint(&self) -> (usize, Option) { - size_hint::add(self.a.size_hint(), self.b.size_hint()) + size_hint::add(self.i.size_hint(), self.j.size_hint()) + } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let Self { + mut i, + mut j, + next_coming_from_j, + } = self; + if next_coming_from_j { + match j.next() { + Some(y) => init = f(init, y), + None => return i.fold(init, f), + } + } + let res = i.try_fold(init, |mut acc, x| { + acc = f(acc, x); + match j.next() { + Some(y) => Ok(f(acc, y)), + None => Err(acc), + } + }); + match res { + Ok(acc) => j.fold(acc, f), + Err(acc) => i.fold(acc, f), + } } } impl FusedIterator for Interleave - where I: Iterator, - J: Iterator -{} +where + I: Iterator, + J: Iterator, +{ +} /// An iterator adaptor that alternates elements from the two iterators until /// one of them runs out. @@ -88,37 +121,44 @@ #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct InterleaveShortest - where I: Iterator, - J: Iterator +where + I: Iterator, + J: Iterator, { - it0: I, - it1: J, - phase: bool, // false ==> it0, true ==> it1 + i: I, + j: J, + next_coming_from_j: bool, } /// Create a new `InterleaveShortest` iterator. -pub fn interleave_shortest(a: I, b: J) -> InterleaveShortest - where I: Iterator, - J: Iterator +pub fn interleave_shortest(i: I, j: J) -> InterleaveShortest +where + I: Iterator, + J: Iterator, { InterleaveShortest { - it0: a, - it1: b, - phase: false, + i, + j, + next_coming_from_j: false, } } impl Iterator for InterleaveShortest - where I: Iterator, - J: Iterator +where + I: Iterator, + J: Iterator, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - let e = if self.phase { self.it1.next() } else { self.it0.next() }; + let e = if self.next_coming_from_j { + self.j.next() + } else { + self.i.next() + }; if e.is_some() { - self.phase = !self.phase; + self.next_coming_from_j = !self.next_coming_from_j; } e } @@ -126,24 +166,23 @@ #[inline] fn size_hint(&self) -> (usize, Option) { let (curr_hint, next_hint) = { - let it0_hint = self.it0.size_hint(); - let it1_hint = self.it1.size_hint(); - if self.phase { - (it1_hint, it0_hint) + let i_hint = self.i.size_hint(); + let j_hint = self.j.size_hint(); + if self.next_coming_from_j { + (j_hint, i_hint) } else { - (it0_hint, it1_hint) + (i_hint, j_hint) } }; let (curr_lower, curr_upper) = curr_hint; let (next_lower, next_upper) = next_hint; let (combined_lower, combined_upper) = size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); - let lower = - if curr_lower > next_lower { - combined_lower + 1 - } else { - combined_lower - }; + let lower = if curr_lower > next_lower { + combined_lower + 1 + } else { + combined_lower + }; let upper = { let extra_elem = match (curr_upper, next_upper) { (_, None) => false, @@ -158,20 +197,52 @@ }; (lower, upper) } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let Self { + mut i, + mut j, + next_coming_from_j, + } = self; + if next_coming_from_j { + match j.next() { + Some(y) => init = f(init, y), + None => return init, + } + } + let res = i.try_fold(init, |mut acc, x| { + acc = f(acc, x); + match j.next() { + Some(y) => Ok(f(acc, y)), + None => Err(acc), + } + }); + match res { + Ok(val) => val, + Err(val) => val, + } + } } impl FusedIterator for InterleaveShortest - where I: FusedIterator, - J: FusedIterator -{} +where + I: FusedIterator, + J: FusedIterator, +{ +} #[derive(Clone, Debug)] /// An iterator adaptor that allows putting back a single /// item to the front of the iterator. /// /// Iterator element type is `I::Item`. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct PutBack - where I: Iterator +where + I: Iterator, { top: Option, iter: I, @@ -179,7 +250,8 @@ /// Create an iterator where you can put back a single item pub fn put_back(iterable: I) -> PutBack - where I: IntoIterator +where + I: IntoIterator, { PutBack { top: None, @@ -188,7 +260,8 @@ } impl PutBack - where I: Iterator +where + I: Iterator, { /// put back value `value` (builder method) pub fn with_value(mut self, value: I::Item) -> Self { @@ -199,21 +272,22 @@ /// Split the `PutBack` into its parts. #[inline] pub fn into_parts(self) -> (Option, I) { - let PutBack{top, iter} = self; + let Self { top, iter } = self; (top, iter) } /// Put back a single value to the front of the iterator. /// - /// If a value is already in the put back slot, it is overwritten. + /// If a value is already in the put back slot, it is returned. #[inline] - pub fn put_back(&mut self, x: I::Item) { - self.top = Some(x); + pub fn put_back(&mut self, x: I::Item) -> Option { + self.top.replace(x) } } impl Iterator for PutBack - where I: Iterator +where + I: Iterator, { type Item = I::Item; #[inline] @@ -252,7 +326,8 @@ } fn all(&mut self, mut f: G) -> bool - where G: FnMut(Self::Item) -> bool + where + G: FnMut(Self::Item) -> bool, { if let Some(elt) = self.top.take() { if !f(elt) { @@ -263,7 +338,8 @@ } fn fold(mut self, init: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, + where + G: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; if let Some(elt) = self.top.take() { @@ -282,10 +358,14 @@ /// See [`.cartesian_product()`](crate::Itertools::cartesian_product) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Product - where I: Iterator +where + I: Iterator, { a: I, - a_cur: Option, + /// `a_cur` is `None` while no item have been taken out of `a` (at definition). + /// Then `a_cur` will be `Some(Some(item))` until `a` is exhausted, + /// in which case `a_cur` will be `Some(None)`. + a_cur: Option>, b: J, b_orig: J, } @@ -293,13 +373,14 @@ /// Create a new cartesian product iterator /// /// Iterator element type is `(I::Item, J::Item)`. -pub fn cartesian_product(mut i: I, j: J) -> Product - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone +pub fn cartesian_product(i: I, j: J) -> Product +where + I: Iterator, + J: Clone + Iterator, + I::Item: Clone, { Product { - a_cur: i.next(), + a_cur: None, a: i, b: j.clone(), b_orig: j, @@ -307,54 +388,69 @@ } impl Iterator for Product - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone +where + I: Iterator, + J: Clone + Iterator, + I::Item: Clone, { type Item = (I::Item, J::Item); fn next(&mut self) -> Option { - let elt_b = match self.b.next() { + let Self { + a, + a_cur, + b, + b_orig, + } = self; + let elt_b = match b.next() { None => { - self.b = self.b_orig.clone(); - match self.b.next() { + *b = b_orig.clone(); + match b.next() { None => return None, Some(x) => { - self.a_cur = self.a.next(); + *a_cur = Some(a.next()); x } } } - Some(x) => x + Some(x) => x, }; - self.a_cur.as_ref().map(|a| (a.clone(), elt_b)) + a_cur + .get_or_insert_with(|| a.next()) + .as_ref() + .map(|a| (a.clone(), elt_b)) } fn size_hint(&self) -> (usize, Option) { - let has_cur = self.a_cur.is_some() as usize; // Not ExactSizeIterator because size may be larger than usize - let (b_min, b_max) = self.b.size_hint(); - // Compute a * b_orig + b for both lower and upper bound - size_hint::add( - size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()), - (b_min * has_cur, b_max.map(move |x| x * has_cur))) + let mut sh = size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()); + if matches!(self.a_cur, Some(Some(_))) { + sh = size_hint::add(sh, self.b.size_hint()); + } + sh } - fn fold(mut self, mut accum: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, + fn fold(self, mut accum: Acc, mut f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, { // use a split loop to handle the loose a_cur as well as avoiding to // clone b_orig at the end. - if let Some(mut a) = self.a_cur.take() { - let mut b = self.b; + let Self { + mut a, + a_cur, + mut b, + b_orig, + } = self; + if let Some(mut elt_a) = a_cur.unwrap_or_else(|| a.next()) { loop { - accum = b.fold(accum, |acc, elt| f(acc, (a.clone(), elt))); + accum = b.fold(accum, |acc, elt| f(acc, (elt_a.clone(), elt))); // we can only continue iterating a if we had a first element; - if let Some(next_a) = self.a.next() { - b = self.b_orig.clone(); - a = next_a; + if let Some(next_elt_a) = a.next() { + b = b_orig.clone(); + elt_a = next_elt_a; } else { break; } @@ -365,15 +461,17 @@ } impl FusedIterator for Product - where I: FusedIterator, - J: Clone + FusedIterator, - I::Item: Clone -{} +where + I: FusedIterator, + J: Clone + FusedIterator, + I::Item: Clone, +{ +} /// A “meta iterator adaptor”. Its closure receives a reference to the iterator /// and may pick off as many elements as it likes, to produce the next iterator element. /// -/// Iterator element type is *X*, if the return type of `F` is *Option\*. +/// Iterator element type is `X` if the return type of `F` is `Option`. /// /// See [`.batching()`](crate::Itertools::batching) for more information. #[derive(Clone)] @@ -383,7 +481,10 @@ iter: I, } -impl fmt::Debug for Batching where I: fmt::Debug { +impl fmt::Debug for Batching +where + I: fmt::Debug, +{ debug_fmt_fields!(Batching, iter); } @@ -393,8 +494,9 @@ } impl Iterator for Batching - where I: Iterator, - F: FnMut(&mut I) -> Option +where + I: Iterator, + F: FnMut(&mut I) -> Option, { type Item = B; #[inline] @@ -403,205 +505,6 @@ } } -/// An iterator adaptor that steps a number elements in the base iterator -/// for each iteration. -/// -/// The iterator steps by yielding the next element from the base iterator, -/// then skipping forward *n-1* elements. -/// -/// See [`.step()`](crate::Itertools::step) for more information. -#[deprecated(note="Use std .step_by() instead", since="0.8.0")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Step { - iter: Fuse, - skip: usize, -} - -/// Create a `Step` iterator. -/// -/// **Panics** if the step is 0. -#[allow(deprecated)] -pub fn step(iter: I, step: usize) -> Step - where I: Iterator -{ - assert!(step != 0); - Step { - iter: iter.fuse(), - skip: step - 1, - } -} - -#[allow(deprecated)] -impl Iterator for Step - where I: Iterator -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option { - let elt = self.iter.next(); - if self.skip > 0 { - self.iter.nth(self.skip - 1); - } - elt - } - - fn size_hint(&self) -> (usize, Option) { - let (low, high) = self.iter.size_hint(); - let div = |x: usize| { - if x == 0 { - 0 - } else { - 1 + (x - 1) / (self.skip + 1) - } - }; - (div(low), high.map(div)) - } -} - -// known size -#[allow(deprecated)] -impl ExactSizeIterator for Step - where I: ExactSizeIterator -{} - -pub trait MergePredicate { - fn merge_pred(&mut self, a: &T, b: &T) -> bool; -} - -#[derive(Clone, Debug)] -pub struct MergeLte; - -impl MergePredicate for MergeLte { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - a <= b - } -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge()`](crate::Itertools::merge_by) for more information. -pub type Merge = MergeBy; - -/// Create an iterator that merges elements in `i` and `j`. -/// -/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge). -/// -/// ``` -/// use itertools::merge; -/// -/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { -/// /* loop body */ -/// } -/// ``` -pub fn merge(i: I, j: J) -> Merge<::IntoIter, ::IntoIter> - where I: IntoIterator, - J: IntoIterator, - I::Item: PartialOrd -{ - merge_by_new(i, j, MergeLte) -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge_by()`](crate::Itertools::merge_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeBy - where I: Iterator, - J: Iterator -{ - a: Peekable, - b: Peekable, - fused: Option, - cmp: F, -} - -impl fmt::Debug for MergeBy - where I: Iterator + fmt::Debug, J: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeBy, a, b); -} - -implbool> MergePredicate for F { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - self(a, b) - } -} - -/// Create a `MergeBy` iterator. -pub fn merge_by_new(a: I, b: J, cmp: F) -> MergeBy - where I: IntoIterator, - J: IntoIterator, - F: MergePredicate, -{ - MergeBy { - a: a.into_iter().peekable(), - b: b.into_iter().peekable(), - fused: None, - cmp, - } -} - -impl Clone for MergeBy - where I: Iterator, - J: Iterator, - Peekable: Clone, - Peekable: Clone, - F: Clone -{ - clone_fields!(a, b, fused, cmp); -} - -impl Iterator for MergeBy - where I: Iterator, - J: Iterator, - F: MergePredicate -{ - type Item = I::Item; - - fn next(&mut self) -> Option { - let less_than = match self.fused { - Some(lt) => lt, - None => match (self.a.peek(), self.b.peek()) { - (Some(a), Some(b)) => self.cmp.merge_pred(a, b), - (Some(_), None) => { - self.fused = Some(true); - true - } - (None, Some(_)) => { - self.fused = Some(false); - false - } - (None, None) => return None, - } - }; - if less_than { - self.a.next() - } else { - self.b.next() - } - } - - fn size_hint(&self) -> (usize, Option) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add(self.a.size_hint(), self.b.size_hint()) - } -} - -impl FusedIterator for MergeBy - where I: FusedIterator, - J: FusedIterator, - F: MergePredicate -{} - /// An iterator adaptor that borrows from a `Clone`-able iterator /// to only pick off elements while the predicate returns `true`. /// @@ -612,22 +515,25 @@ f: F, } -impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F> - where I: Iterator + fmt::Debug, +impl fmt::Debug for TakeWhileRef<'_, I, F> +where + I: Iterator + fmt::Debug, { debug_fmt_fields!(TakeWhileRef, iter); } /// Create a new `TakeWhileRef` from a reference to clonable iterator. pub fn take_while_ref(iter: &mut I, f: F) -> TakeWhileRef - where I: Iterator + Clone +where + I: Iterator + Clone, { TakeWhileRef { iter, f } } -impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F> - where I: Iterator + Clone, - F: FnMut(&I::Item) -> bool +impl Iterator for TakeWhileRef<'_, I, F> +where + I: Iterator + Clone, + F: FnMut(&I::Item) -> bool, { type Item = I::Item; @@ -667,7 +573,8 @@ } impl Iterator for WhileSome - where I: Iterator> +where + I: Iterator>, { type Item = A; @@ -681,6 +588,22 @@ fn size_hint(&self) -> (usize, Option) { (0, self.iter.size_hint().1) } + + fn fold(mut self, acc: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let res = self.iter.try_fold(acc, |acc, item| match item { + Some(item) => Ok(f(acc, item)), + None => Err(acc), + }); + + match res { + Ok(val) => val, + Err(val) => val, + } + } } /// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples @@ -689,10 +612,11 @@ /// See [`.tuple_combinations()`](crate::Itertools::tuple_combinations) for more /// information. #[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[must_use = "this iterator adaptor is not lazy but does nearly nothing unless consumed"] pub struct TupleCombinations - where I: Iterator, - T: HasCombination +where + I: Iterator, + T: HasCombination, { iter: T::Combination, _mi: PhantomData, @@ -704,9 +628,10 @@ /// Create a new `TupleCombinations` from a clonable iterator. pub fn tuple_combinations(iter: I) -> TupleCombinations - where I: Iterator + Clone, - I::Item: Clone, - T: HasCombination, +where + I: Iterator + Clone, + I::Item: Clone, + T: HasCombination, { TupleCombinations { iter: T::Combination::from(iter), @@ -715,20 +640,38 @@ } impl Iterator for TupleCombinations - where I: Iterator, - T: HasCombination, +where + I: Iterator, + T: HasCombination, { type Item = T; fn next(&mut self) -> Option { self.iter.next() } + + fn size_hint(&self) -> SizeHint { + self.iter.size_hint() + } + + fn count(self) -> usize { + self.iter.count() + } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } impl FusedIterator for TupleCombinations - where I: FusedIterator, - T: HasCombination, -{} +where + I: FusedIterator, + T: HasCombination, +{ +} #[derive(Clone, Debug)] pub struct Tuple1Combination { @@ -737,7 +680,7 @@ impl From for Tuple1Combination { fn from(iter: I) -> Self { - Tuple1Combination { iter } + Self { iter } } } @@ -747,6 +690,21 @@ fn next(&mut self) -> Option { self.iter.next().map(|x| (x,)) } + + fn size_hint(&self) -> SizeHint { + self.iter.size_hint() + } + + fn count(self) -> usize { + self.iter.count() + } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.map(|x| (x,)).fold(init, f) + } } impl HasCombination for (I::Item,) { @@ -780,22 +738,67 @@ impl Iterator for $C where I: Iterator + Clone, - I::Item: Clone + A: Clone, { type Item = (A, $(ignore_ident!($X, A)),*); fn next(&mut self) -> Option { - if let Some(($($X),*,)) = self.c.next() { + if let Some(($($X,)*)) = self.c.next() { let z = self.item.clone().unwrap(); Some((z, $($X),*)) } else { self.item = self.iter.next(); self.item.clone().and_then(|z| { self.c = self.iter.clone().into(); - self.c.next().map(|($($X),*,)| (z, $($X),*)) + self.c.next().map(|($($X,)*)| (z, $($X),*)) }) } } + + fn size_hint(&self) -> SizeHint { + const K: usize = 1 + count_ident!($($X)*); + let (mut n_min, mut n_max) = self.iter.size_hint(); + n_min = checked_binomial(n_min, K).unwrap_or(usize::MAX); + n_max = n_max.and_then(|n| checked_binomial(n, K)); + size_hint::add(self.c.size_hint(), (n_min, n_max)) + } + + fn count(self) -> usize { + const K: usize = 1 + count_ident!($($X)*); + let n = self.iter.count(); + checked_binomial(n, K).unwrap() + self.c.count() + } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + // We outline this closure to prevent it from unnecessarily + // capturing the type parameters `I`, `B`, and `F`. Not doing + // so ended up causing exponentially big types during MIR + // inlining when building itertools with optimizations enabled. + // + // This change causes a small improvement to compile times in + // release mode. + type CurrTuple = (A, $(ignore_ident!($X, A)),*); + type PrevTuple = ($(ignore_ident!($X, A),)*); + fn map_fn(z: &A) -> impl FnMut(PrevTuple) -> CurrTuple + '_ { + move |($($X,)*)| (z.clone(), $($X),*) + } + let Self { c, item, mut iter } = self; + if let Some(z) = item.as_ref() { + init = c + .map(map_fn::(z)) + .fold(init, &mut f); + } + while let Some(z) = iter.next() { + let c: $P = iter.clone().into(); + init = c + .map(map_fn::(&z)) + .fold(init, &mut f); + } + init + } } impl HasCombination for (A, $(ignore_ident!($X, A)),*) @@ -831,6 +834,42 @@ impl_tuple_combination!(Tuple11Combination Tuple10Combination; a b c d e f g h i j); impl_tuple_combination!(Tuple12Combination Tuple11Combination; a b c d e f g h i j k); +// https://en.wikipedia.org/wiki/Binomial_coefficient#In_programming_languages +pub(crate) fn checked_binomial(mut n: usize, mut k: usize) -> Option { + if n < k { + return Some(0); + } + // `factorial(n) / factorial(n - k) / factorial(k)` but trying to avoid it overflows: + k = (n - k).min(k); // symmetry + let mut c = 1; + for i in 1..=k { + c = (c / i) + .checked_mul(n)? + .checked_add((c % i).checked_mul(n)? / i)?; + n -= 1; + } + Some(c) +} + +#[test] +fn test_checked_binomial() { + // With the first row: [1, 0, 0, ...] and the first column full of 1s, we check + // row by row the recurrence relation of binomials (which is an equivalent definition). + // For n >= 1 and k >= 1 we have: + // binomial(n, k) == binomial(n - 1, k - 1) + binomial(n - 1, k) + const LIMIT: usize = 500; + let mut row = vec![Some(0); LIMIT + 1]; + row[0] = Some(1); + for n in 0..=LIMIT { + for k in 0..=LIMIT { + assert_eq!(row[k], checked_binomial(n, k)); + } + row = std::iter::once(Some(1)) + .chain((1..=LIMIT).map(|k| row[k - 1]?.checked_add(row[k]?))) + .collect(); + } +} + /// An iterator adapter to filter values within a nested `Result::Ok`. /// /// See [`.filter_ok()`](crate::Itertools::filter_ok) for more information. @@ -838,7 +877,7 @@ #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct FilterOk { iter: I, - f: F + f: F, } impl fmt::Debug for FilterOk @@ -850,33 +889,26 @@ /// Create a new `FilterOk` iterator. pub fn filter_ok(iter: I, f: F) -> FilterOk - where I: Iterator>, - F: FnMut(&T) -> bool, +where + I: Iterator>, + F: FnMut(&T) -> bool, { - FilterOk { - iter, - f, - } + FilterOk { iter, f } } impl Iterator for FilterOk - where I: Iterator>, - F: FnMut(&T) -> bool, +where + I: Iterator>, + F: FnMut(&T) -> bool, { type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if (self.f)(&v) { - return Some(Ok(v)); - } - }, - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find(|res| match res { + Ok(t) => f(t), + _ => true, + }) } fn size_hint(&self) -> (usize, Option) { @@ -884,36 +916,65 @@ } fn fold(self, init: Acc, fold_f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { let mut f = self.f; - self.iter.filter(|v| { - v.as_ref().map(&mut f).unwrap_or(true) - }).fold(init, fold_f) + self.iter + .filter(|v| v.as_ref().map(&mut f).unwrap_or(true)) + .fold(init, fold_f) } fn collect(self) -> C - where C: FromIterator + where + C: FromIterator, { let mut f = self.f; - self.iter.filter(|v| { - v.as_ref().map(&mut f).unwrap_or(true) - }).collect() + self.iter + .filter(|v| v.as_ref().map(&mut f).unwrap_or(true)) + .collect() + } +} + +impl DoubleEndedIterator for FilterOk +where + I: DoubleEndedIterator>, + F: FnMut(&T) -> bool, +{ + fn next_back(&mut self) -> Option { + let f = &mut self.f; + self.iter.rfind(|res| match res { + Ok(t) => f(t), + _ => true, + }) + } + + fn rfold(self, init: Acc, fold_f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter + .filter(|v| v.as_ref().map(&mut f).unwrap_or(true)) + .rfold(init, fold_f) } } impl FusedIterator for FilterOk - where I: FusedIterator>, - F: FnMut(&T) -> bool, -{} +where + I: FusedIterator>, + F: FnMut(&T) -> bool, +{ +} /// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`. /// /// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] pub struct FilterMapOk { iter: I, - f: F + f: F, } impl fmt::Debug for FilterMapOk @@ -933,33 +994,26 @@ /// Create a new `FilterOk` iterator. pub fn filter_map_ok(iter: I, f: F) -> FilterMapOk - where I: Iterator>, - F: FnMut(T) -> Option, +where + I: Iterator>, + F: FnMut(T) -> Option, { - FilterMapOk { - iter, - f, - } + FilterMapOk { iter, f } } impl Iterator for FilterMapOk - where I: Iterator>, - F: FnMut(T) -> Option, +where + I: Iterator>, + F: FnMut(T) -> Option, { type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if let Some(v) = (self.f)(v) { - return Some(Ok(v)); - } - }, - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find_map(|res| match res { + Ok(t) => f(t).map(Ok), + Err(e) => Some(Err(e)), + }) } fn size_hint(&self) -> (usize, Option) { @@ -967,28 +1021,56 @@ } fn fold(self, init: Acc, fold_f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { let mut f = self.f; - self.iter.filter_map(|v| { - transpose_result(v.map(&mut f)) - }).fold(init, fold_f) + self.iter + .filter_map(|v| transpose_result(v.map(&mut f))) + .fold(init, fold_f) } fn collect(self) -> C - where C: FromIterator + where + C: FromIterator, { let mut f = self.f; - self.iter.filter_map(|v| { - transpose_result(v.map(&mut f)) - }).collect() + self.iter + .filter_map(|v| transpose_result(v.map(&mut f))) + .collect() + } +} + +impl DoubleEndedIterator for FilterMapOk +where + I: DoubleEndedIterator>, + F: FnMut(T) -> Option, +{ + fn next_back(&mut self) -> Option { + let f = &mut self.f; + self.iter.by_ref().rev().find_map(|res| match res { + Ok(t) => f(t).map(Ok), + Err(e) => Some(Err(e)), + }) + } + + fn rfold(self, init: Acc, fold_f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter + .filter_map(|v| transpose_result(v.map(&mut f))) + .rfold(init, fold_f) } } impl FusedIterator for FilterMapOk - where I: FusedIterator>, - F: FnMut(T) -> Option, -{} +where + I: FusedIterator>, + F: FnMut(T) -> Option, +{ +} /// An iterator adapter to get the positions of each element that matches a predicate. /// @@ -996,70 +1078,90 @@ #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Positions { - iter: I, + iter: Enumerate, f: F, - count: usize, } impl fmt::Debug for Positions where I: fmt::Debug, { - debug_fmt_fields!(Positions, iter, count); + debug_fmt_fields!(Positions, iter); } /// Create a new `Positions` iterator. pub fn positions(iter: I, f: F) -> Positions - where I: Iterator, - F: FnMut(I::Item) -> bool, +where + I: Iterator, + F: FnMut(I::Item) -> bool, { - Positions { - iter, - f, - count: 0 - } + let iter = iter.enumerate(); + Positions { iter, f } } impl Iterator for Positions - where I: Iterator, - F: FnMut(I::Item) -> bool, +where + I: Iterator, + F: FnMut(I::Item) -> bool, { type Item = usize; fn next(&mut self) -> Option { - while let Some(v) = self.iter.next() { - let i = self.count; - self.count = i + 1; - if (self.f)(v) { - return Some(i); - } - } - None + let f = &mut self.f; + self.iter.find_map(|(count, val)| f(val).then_some(count)) } fn size_hint(&self) -> (usize, Option) { (0, self.iter.size_hint().1) } + + fn fold(self, init: B, mut func: G) -> B + where + G: FnMut(B, Self::Item) -> B, + { + let mut f = self.f; + self.iter.fold(init, |mut acc, (count, val)| { + if f(val) { + acc = func(acc, count); + } + acc + }) + } } impl DoubleEndedIterator for Positions - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(I::Item) -> bool, +where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(I::Item) -> bool, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.next_back() { - if (self.f)(v) { - return Some(self.count + self.iter.len()) + let f = &mut self.f; + self.iter + .by_ref() + .rev() + .find_map(|(count, val)| f(val).then_some(count)) + } + + fn rfold(self, init: B, mut func: G) -> B + where + G: FnMut(B, Self::Item) -> B, + { + let mut f = self.f; + self.iter.rfold(init, |mut acc, (count, val)| { + if f(val) { + acc = func(acc, count); } - } - None + acc + }) } } impl FusedIterator for Positions - where I: FusedIterator, - F: FnMut(I::Item) -> bool, -{} +where + I: FusedIterator, + F: FnMut(I::Item) -> bool, +{ +} /// An iterator adapter to apply a mutating function to each element before yielding it. /// @@ -1108,18 +1210,28 @@ } fn fold(self, init: Acc, mut g: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, + where + G: FnMut(Acc, Self::Item) -> Acc, { let mut f = self.f; - self.iter.fold(init, move |acc, mut v| { f(&mut v); g(acc, v) }) + self.iter.fold(init, move |acc, mut v| { + f(&mut v); + g(acc, v) + }) } // if possible, re-use inner iterator specializations in collect fn collect(self) -> C - where C: FromIterator + where + C: FromIterator, { let mut f = self.f; - self.iter.map(move |mut v| { f(&mut v); v }).collect() + self.iter + .map(move |mut v| { + f(&mut v); + v + }) + .collect() } } @@ -1127,7 +1239,8 @@ where I: ExactSizeIterator, F: FnMut(&mut I::Item), -{} +{ +} impl DoubleEndedIterator for Update where @@ -1148,4 +1261,5 @@ where I: FusedIterator, F: FnMut(&mut I::Item), -{} +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/multi_product.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/multi_product.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/adaptors/multi_product.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/adaptors/multi_product.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,29 +1,52 @@ #![cfg(feature = "use_alloc")] - -use crate::size_hint; -use crate::Itertools; +use Option::{self as State, None as ProductEnded, Some as ProductInProgress}; +use Option::{self as CurrentItems, None as NotYetPopulated, Some as Populated}; use alloc::vec::Vec; +use crate::size_hint; + #[derive(Clone)] /// An iterator adaptor that iterates over the cartesian product of /// multiple iterators of type `I`. /// -/// An iterator element type is `Vec`. +/// An iterator element type is `Vec`. /// /// See [`.multi_cartesian_product()`](crate::Itertools::multi_cartesian_product) /// for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MultiProduct(Vec>) - where I: Iterator + Clone, - I::Item: Clone; +pub struct MultiProduct(State>) +where + I: Iterator + Clone, + I::Item: Clone; + +#[derive(Clone)] +/// Internals for `MultiProduct`. +struct MultiProductInner +where + I: Iterator + Clone, + I::Item: Clone, +{ + /// Holds the iterators. + iters: Vec>, + /// Not populated at the beginning then it holds the current item of each iterator. + cur: CurrentItems>, +} impl std::fmt::Debug for MultiProduct where I: Iterator + Clone + std::fmt::Debug, I::Item: Clone + std::fmt::Debug, { - debug_fmt_fields!(CoalesceBy, 0); + debug_fmt_fields!(MultiProduct, 0); +} + +impl std::fmt::Debug for MultiProductInner +where + I: Iterator + Clone + std::fmt::Debug, + I::Item: Clone + std::fmt::Debug, +{ + debug_fmt_fields!(MultiProductInner, iters, cur); } /// Create a new cartesian product iterator over an arbitrary number @@ -31,200 +54,178 @@ /// /// Iterator element is of type `Vec`. pub fn multi_cartesian_product(iters: H) -> MultiProduct<::IntoIter> - where H: Iterator, - H::Item: IntoIterator, - ::IntoIter: Clone, - ::Item: Clone -{ - MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect()) +where + H: Iterator, + H::Item: IntoIterator, + ::IntoIter: Clone, + ::Item: Clone, +{ + let inner = MultiProductInner { + iters: iters + .map(|i| MultiProductIter::new(i.into_iter())) + .collect(), + cur: NotYetPopulated, + }; + MultiProduct(ProductInProgress(inner)) } #[derive(Clone, Debug)] /// Holds the state of a single iterator within a `MultiProduct`. struct MultiProductIter - where I: Iterator + Clone, - I::Item: Clone +where + I: Iterator + Clone, + I::Item: Clone, { - cur: Option, iter: I, iter_orig: I, } -/// Holds the current state during an iteration of a `MultiProduct`. -#[derive(Debug)] -enum MultiProductIterState { - StartOfIter, - MidIter { on_first_iter: bool }, -} - -impl MultiProduct - where I: Iterator + Clone, - I::Item: Clone -{ - /// Iterates the rightmost iterator, then recursively iterates iterators - /// to the left if necessary. - /// - /// Returns true if the iteration succeeded, else false. - fn iterate_last( - multi_iters: &mut [MultiProductIter], - mut state: MultiProductIterState - ) -> bool { - use self::MultiProductIterState::*; - - if let Some((last, rest)) = multi_iters.split_last_mut() { - let on_first_iter = match state { - StartOfIter => { - let on_first_iter = !last.in_progress(); - state = MidIter { on_first_iter }; - on_first_iter - }, - MidIter { on_first_iter } => on_first_iter - }; - - if !on_first_iter { - last.iterate(); - } - - if last.in_progress() { - true - } else if MultiProduct::iterate_last(rest, state) { - last.reset(); - last.iterate(); - // If iterator is None twice consecutively, then iterator is - // empty; whole product is empty. - last.in_progress() - } else { - false - } - } else { - // Reached end of iterator list. On initialisation, return true. - // At end of iteration (final iterator finishes), finish. - match state { - StartOfIter => false, - MidIter { on_first_iter } => on_first_iter - } - } - } - - /// Returns the unwrapped value of the next iteration. - fn curr_iterator(&self) -> Vec { - self.0.iter().map(|multi_iter| { - multi_iter.cur.clone().unwrap() - }).collect() - } - - /// Returns true if iteration has started and has not yet finished; false - /// otherwise. - fn in_progress(&self) -> bool { - if let Some(last) = self.0.last() { - last.in_progress() - } else { - false - } - } -} - impl MultiProductIter - where I: Iterator + Clone, - I::Item: Clone +where + I: Iterator + Clone, + I::Item: Clone, { fn new(iter: I) -> Self { - MultiProductIter { - cur: None, + Self { iter: iter.clone(), - iter_orig: iter + iter_orig: iter, } } - - /// Iterate the managed iterator. - fn iterate(&mut self) { - self.cur = self.iter.next(); - } - - /// Reset the managed iterator. - fn reset(&mut self) { - self.iter = self.iter_orig.clone(); - } - - /// Returns true if the current iterator has been started and has not yet - /// finished; false otherwise. - fn in_progress(&self) -> bool { - self.cur.is_some() - } } impl Iterator for MultiProduct - where I: Iterator + Clone, - I::Item: Clone +where + I: Iterator + Clone, + I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { - if MultiProduct::iterate_last( - &mut self.0, - MultiProductIterState::StartOfIter - ) { - Some(self.curr_iterator()) - } else { - None + // This fuses the iterator. + let inner = self.0.as_mut()?; + match &mut inner.cur { + Populated(values) => { + debug_assert!(!inner.iters.is_empty()); + // Find (from the right) a non-finished iterator and + // reset the finished ones encountered. + for (iter, item) in inner.iters.iter_mut().zip(values.iter_mut()).rev() { + if let Some(new) = iter.iter.next() { + *item = new; + return Some(values.clone()); + } else { + iter.iter = iter.iter_orig.clone(); + // `cur` is populated so the untouched `iter_orig` can not be empty. + *item = iter.iter.next().unwrap(); + } + } + self.0 = ProductEnded; + None + } + // Only the first time. + NotYetPopulated => { + let next: Option> = inner.iters.iter_mut().map(|i| i.iter.next()).collect(); + if next.is_none() || inner.iters.is_empty() { + // This cartesian product had at most one item to generate and now ends. + self.0 = ProductEnded; + } else { + inner.cur.clone_from(&next); + } + next + } } } fn count(self) -> usize { - if self.0.is_empty() { - return 0; - } - - if !self.in_progress() { - return self.0.into_iter().fold(1, |acc, multi_iter| { - acc * multi_iter.iter.count() - }); + match self.0 { + ProductEnded => 0, + // The iterator is fresh so the count is the product of the length of each iterator: + // - If one of them is empty, stop counting. + // - Less `count()` calls than the general case. + ProductInProgress(MultiProductInner { + iters, + cur: NotYetPopulated, + }) => iters + .into_iter() + .map(|iter| iter.iter_orig.count()) + .try_fold(1, |product, count| { + if count == 0 { + None + } else { + Some(product * count) + } + }) + .unwrap_or_default(), + // The general case. + ProductInProgress(MultiProductInner { + iters, + cur: Populated(_), + }) => iters.into_iter().fold(0, |mut acc, iter| { + if acc != 0 { + acc *= iter.iter_orig.count(); + } + acc + iter.iter.count() + }), } - - self.0.into_iter().fold( - 0, - |acc, MultiProductIter { iter, iter_orig, cur: _ }| { - let total_count = iter_orig.count(); - let cur_count = iter.count(); - acc * total_count + cur_count - } - ) } fn size_hint(&self) -> (usize, Option) { - // Not ExactSizeIterator because size may be larger than usize - if self.0.is_empty() { - return (0, Some(0)); - } - - if !self.in_progress() { - return self.0.iter().fold((1, Some(1)), |acc, multi_iter| { - size_hint::mul(acc, multi_iter.iter.size_hint()) - }); - } - - self.0.iter().fold( - (0, Some(0)), - |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| { - let cur_size = iter.size_hint(); - let total_size = iter_orig.size_hint(); - size_hint::add(size_hint::mul(acc, total_size), cur_size) + match &self.0 { + ProductEnded => (0, Some(0)), + ProductInProgress(MultiProductInner { + iters, + cur: NotYetPopulated, + }) => iters + .iter() + .map(|iter| iter.iter_orig.size_hint()) + .fold((1, Some(1)), size_hint::mul), + ProductInProgress(MultiProductInner { + iters, + cur: Populated(_), + }) => { + if let [first, tail @ ..] = &iters[..] { + tail.iter().fold(first.iter.size_hint(), |mut sh, iter| { + sh = size_hint::mul(sh, iter.iter_orig.size_hint()); + size_hint::add(sh, iter.iter.size_hint()) + }) + } else { + // Since it is populated, this cartesian product has started so `iters` is not empty. + unreachable!() + } } - ) + } } fn last(self) -> Option { - let iter_count = self.0.len(); - - let lasts: Self::Item = self.0.into_iter() - .map(|multi_iter| multi_iter.iter.last()) - .while_some() - .collect(); - - if lasts.len() == iter_count { - Some(lasts) + let MultiProductInner { iters, cur } = self.0?; + // Collect the last item of each iterator of the product. + if let Populated(values) = cur { + let mut count = iters.len(); + let last = iters + .into_iter() + .zip(values) + .map(|(i, value)| { + i.iter.last().unwrap_or_else(|| { + // The iterator is empty, use its current `value`. + count -= 1; + value + }) + }) + .collect(); + if count == 0 { + // `values` was the last item. + None + } else { + Some(last) + } } else { - None + iters.into_iter().map(|i| i.iter.last()).collect() } } } + +impl std::iter::FusedIterator for MultiProduct +where + I: Iterator + Clone, + I::Item: Clone, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/combinations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/combinations.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,61 +1,258 @@ +use core::array; +use core::borrow::BorrowMut; use std::fmt; use std::iter::FusedIterator; use super::lazy_buffer::LazyBuffer; use alloc::vec::Vec; +use crate::adaptors::checked_binomial; + +/// Iterator for `Vec` valued combinations returned by [`.combinations()`](crate::Itertools::combinations) +pub type Combinations = CombinationsGeneric>; +/// Iterator for const generic combinations returned by [`.array_combinations()`](crate::Itertools::array_combinations) +pub type ArrayCombinations = CombinationsGeneric; + +/// Create a new `Combinations` from a clonable iterator. +pub fn combinations(iter: I, k: usize) -> Combinations +where + I::Item: Clone, +{ + Combinations::new(iter, (0..k).collect()) +} + +/// Create a new `ArrayCombinations` from a clonable iterator. +pub fn array_combinations(iter: I) -> ArrayCombinations +where + I::Item: Clone, +{ + ArrayCombinations::new(iter, array::from_fn(|i| i)) +} + /// An iterator to iterate through all the `k`-length combinations in an iterator. /// -/// See [`.combinations()`](crate::Itertools::combinations) for more information. +/// See [`.combinations()`](crate::Itertools::combinations) and [`.array_combinations()`](crate::Itertools::array_combinations) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Combinations { - indices: Vec, +pub struct CombinationsGeneric { + indices: Idx, pool: LazyBuffer, first: bool, } -impl Clone for Combinations - where I: Clone + Iterator, - I::Item: Clone, +/// A type holding indices of elements in a pool or buffer of items from an inner iterator +/// and used to pick out different combinations in a generic way. +pub trait PoolIndex: BorrowMut<[usize]> { + type Item; + + fn extract_item>(&self, pool: &LazyBuffer) -> Self::Item + where + T: Clone; + + fn len(&self) -> usize { + self.borrow().len() + } +} + +impl PoolIndex for Vec { + type Item = Vec; + + fn extract_item>(&self, pool: &LazyBuffer) -> Vec + where + T: Clone, + { + pool.get_at(self) + } +} + +impl PoolIndex for [usize; K] { + type Item = [T; K]; + + fn extract_item>(&self, pool: &LazyBuffer) -> [T; K] + where + T: Clone, + { + pool.get_array(*self) + } +} + +impl Clone for CombinationsGeneric +where + I: Iterator + Clone, + I::Item: Clone, + Idx: Clone, { clone_fields!(indices, pool, first); } -impl fmt::Debug for Combinations - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, +impl fmt::Debug for CombinationsGeneric +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + Idx: fmt::Debug, { debug_fmt_fields!(Combinations, indices, pool, first); } -/// Create a new `Combinations` from a clonable iterator. -pub fn combinations(iter: I, k: usize) -> Combinations - where I: Iterator -{ - let mut pool = LazyBuffer::new(iter); - pool.prefill(k); - - Combinations { - indices: (0..k).collect(), - pool, - first: true, +impl> CombinationsGeneric { + /// Constructor with arguments the inner iterator and the initial state for the indices. + fn new(iter: I, indices: Idx) -> Self { + Self { + indices, + pool: LazyBuffer::new(iter), + first: true, + } } -} -impl Combinations { /// Returns the length of a combination produced by this iterator. #[inline] - pub fn k(&self) -> usize { self.indices.len() } + pub fn k(&self) -> usize { + self.indices.len() + } /// Returns the (current) length of the pool from which combination elements are /// selected. This value can change between invocations of [`next`](Combinations::next). #[inline] - pub fn n(&self) -> usize { self.pool.len() } + pub fn n(&self) -> usize { + self.pool.len() + } + + /// Returns a reference to the source pool. + #[inline] + pub(crate) fn src(&self) -> &LazyBuffer { + &self.pool + } + + /// Return the length of the inner iterator and the count of remaining combinations. + pub(crate) fn n_and_count(self) -> (usize, usize) { + let Self { + indices, + pool, + first, + } = self; + let n = pool.count(); + (n, remaining_for(n, first, indices.borrow()).unwrap()) + } + + /// Initialises the iterator by filling a buffer with elements from the + /// iterator. Returns true if there are no combinations, false otherwise. + fn init(&mut self) -> bool { + self.pool.prefill(self.k()); + let done = self.k() > self.n(); + if !done { + self.first = false; + } + + done + } + + /// Increments indices representing the combination to advance to the next + /// (in lexicographic order by increasing sequence) combination. For example + /// if we have n=4 & k=2 then `[0, 1] -> [0, 2] -> [0, 3] -> [1, 2] -> ...` + /// + /// Returns true if we've run out of combinations, false otherwise. + fn increment_indices(&mut self) -> bool { + // Borrow once instead of noise each time it's indexed + let indices = self.indices.borrow_mut(); + + if indices.is_empty() { + return true; // Done + } + // Scan from the end, looking for an index to increment + let mut i: usize = indices.len() - 1; + + // Check if we need to consume more from the iterator + if indices[i] == self.pool.len() - 1 { + self.pool.get_next(); // may change pool size + } + + while indices[i] == i + self.pool.len() - indices.len() { + if i > 0 { + i -= 1; + } else { + // Reached the last combination + return true; + } + } + + // Increment index, and reset the ones to its right + indices[i] += 1; + for j in i + 1..indices.len() { + indices[j] = indices[j - 1] + 1; + } + // If we've made it this far, we haven't run out of combos + false + } + + /// Returns the n-th item or the number of successful steps. + pub(crate) fn try_nth(&mut self, n: usize) -> Result<::Item, usize> + where + I: Iterator, + I::Item: Clone, + { + let done = if self.first { + self.init() + } else { + self.increment_indices() + }; + if done { + return Err(0); + } + for i in 0..n { + if self.increment_indices() { + return Err(i + 1); + } + } + Ok(self.indices.extract_item(&self.pool)) + } +} + +impl Iterator for CombinationsGeneric +where + I: Iterator, + I::Item: Clone, + Idx: PoolIndex, +{ + type Item = Idx::Item; + fn next(&mut self) -> Option { + let done = if self.first { + self.init() + } else { + self.increment_indices() + }; + + if done { + return None; + } + + Some(self.indices.extract_item(&self.pool)) + } + + fn nth(&mut self, n: usize) -> Option { + self.try_nth(n).ok() + } + + fn size_hint(&self) -> (usize, Option) { + let (mut low, mut upp) = self.pool.size_hint(); + low = remaining_for(low, self.first, self.indices.borrow()).unwrap_or(usize::MAX); + upp = upp.and_then(|upp| remaining_for(upp, self.first, self.indices.borrow())); + (low, upp) + } - /// Returns a reference to the source iterator. #[inline] - pub(crate) fn src(&self) -> &I { &self.pool.it } + fn count(self) -> usize { + self.n_and_count().1 + } +} + +impl FusedIterator for CombinationsGeneric +where + I: Iterator, + I::Item: Clone, + Idx: PoolIndex, +{ +} +impl Combinations { /// Resets this `Combinations` back to an initial state for combinations of length /// `k` over the same pool data source. If `k` is larger than the current length /// of the data pool an attempt is made to prefill the pool so that it holds `k` @@ -68,7 +265,6 @@ for i in 0..k { self.indices[i] = i; } - } else { for i in 0..self.indices.len() { self.indices[i] = i; @@ -79,50 +275,34 @@ } } -impl Iterator for Combinations - where I: Iterator, - I::Item: Clone -{ - type Item = Vec; - fn next(&mut self) -> Option { - if self.first { - if self.k() > self.n() { - return None; - } - self.first = false; - } else if self.indices.is_empty() { - return None; - } else { - // Scan from the end, looking for an index to increment - let mut i: usize = self.indices.len() - 1; - - // Check if we need to consume more from the iterator - if self.indices[i] == self.pool.len() - 1 { - self.pool.get_next(); // may change pool size - } - - while self.indices[i] == i + self.pool.len() - self.indices.len() { - if i > 0 { - i -= 1; - } else { - // Reached the last combination - return None; - } - } - - // Increment index, and reset the ones to its right - self.indices[i] += 1; - for j in i+1..self.indices.len() { - self.indices[j] = self.indices[j - 1] + 1; - } - } - - // Create result vector based on the indices - Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect()) +/// For a given size `n`, return the count of remaining combinations or None if it would overflow. +fn remaining_for(n: usize, first: bool, indices: &[usize]) -> Option { + let k = indices.len(); + if n < k { + Some(0) + } else if first { + checked_binomial(n, k) + } else { + // https://en.wikipedia.org/wiki/Combinatorial_number_system + // http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf + + // The combinations generated after the current one can be counted by counting as follows: + // - The subsequent combinations that differ in indices[0]: + // If subsequent combinations differ in indices[0], then their value for indices[0] + // must be at least 1 greater than the current indices[0]. + // As indices is strictly monotonically sorted, this means we can effectively choose k values + // from (n - 1 - indices[0]), leading to binomial(n - 1 - indices[0], k) possibilities. + // - The subsequent combinations with same indices[0], but differing indices[1]: + // Here we can choose k - 1 values from (n - 1 - indices[1]) values, + // leading to binomial(n - 1 - indices[1], k - 1) possibilities. + // - (...) + // - The subsequent combinations with same indices[0..=i], but differing indices[i]: + // Here we can choose k - i values from (n - 1 - indices[i]) values: binomial(n - 1 - indices[i], k - i). + // Since subsequent combinations can in any index, we must sum up the aforementioned binomial coefficients. + + // Below, `n0` resembles indices[i]. + indices.iter().enumerate().try_fold(0usize, |sum, (i, n0)| { + sum.checked_add(checked_binomial(n - 1 - *n0, k - i)?) + }) } } - -impl FusedIterator for Combinations - where I: Iterator, - I::Item: Clone -{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/combinations_with_replacement.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations_with_replacement.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/combinations_with_replacement.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/combinations_with_replacement.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,20 +1,23 @@ +use alloc::boxed::Box; use alloc::vec::Vec; use std::fmt; use std::iter::FusedIterator; use super::lazy_buffer::LazyBuffer; +use crate::adaptors::checked_binomial; /// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement. /// /// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement) /// for more information. #[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct CombinationsWithReplacement where I: Iterator, I::Item: Clone, { - indices: Vec, + indices: Box<[usize]>, pool: LazyBuffer, first: bool, } @@ -24,18 +27,7 @@ I: Iterator + fmt::Debug, I::Item: fmt::Debug + Clone, { - debug_fmt_fields!(Combinations, indices, pool, first); -} - -impl CombinationsWithReplacement -where - I: Iterator, - I::Item: Clone, -{ - /// Map the current mask over the pool to get an output combination - fn current(&self) -> Vec { - self.indices.iter().map(|i| self.pool[*i].clone()).collect() - } + debug_fmt_fields!(CombinationsWithReplacement, indices, pool, first); } /// Create a new `CombinationsWithReplacement` from a clonable iterator. @@ -44,7 +36,7 @@ I: Iterator, I::Item: Clone, { - let indices: Vec = alloc::vec![0; k]; + let indices = alloc::vec![0; k].into_boxed_slice(); let pool: LazyBuffer = LazyBuffer::new(iter); CombinationsWithReplacement { @@ -54,56 +46,143 @@ } } -impl Iterator for CombinationsWithReplacement +impl CombinationsWithReplacement where I: Iterator, I::Item: Clone, { - type Item = Vec; - fn next(&mut self) -> Option { - // If this is the first iteration, return early - if self.first { - // In empty edge cases, stop iterating immediately - return if !(self.indices.is_empty() || self.pool.get_next()) { - None - // Otherwise, yield the initial state - } else { - self.first = false; - Some(self.current()) - }; - } - + /// Increments indices representing the combination to advance to the next + /// (in lexicographic order by increasing sequence) combination. + /// + /// Returns true if we've run out of combinations, false otherwise. + fn increment_indices(&mut self) -> bool { // Check if we need to consume more from the iterator // This will run while we increment our first index digit self.pool.get_next(); // Work out where we need to update our indices - let mut increment: Option<(usize, usize)> = None; + let mut increment = None; for (i, indices_int) in self.indices.iter().enumerate().rev() { - if *indices_int < self.pool.len()-1 { + if *indices_int < self.pool.len() - 1 { increment = Some((i, indices_int + 1)); break; } } - match increment { // If we can update the indices further Some((increment_from, increment_value)) => { // We need to update the rightmost non-max value // and all those to the right - for indices_index in increment_from..self.indices.len() { - self.indices[indices_index] = increment_value; - } - Some(self.current()) + self.indices[increment_from..].fill(increment_value); + false } // Otherwise, we're done - None => None, + None => true, } } } +impl Iterator for CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + type Item = Vec; + + fn next(&mut self) -> Option { + if self.first { + // In empty edge cases, stop iterating immediately + if !(self.indices.is_empty() || self.pool.get_next()) { + return None; + } + self.first = false; + } else if self.increment_indices() { + return None; + } + Some(self.pool.get_at(&self.indices)) + } + + fn nth(&mut self, n: usize) -> Option { + if self.first { + // In empty edge cases, stop iterating immediately + if !(self.indices.is_empty() || self.pool.get_next()) { + return None; + } + self.first = false; + } else if self.increment_indices() { + return None; + } + for _ in 0..n { + if self.increment_indices() { + return None; + } + } + Some(self.pool.get_at(&self.indices)) + } + + fn size_hint(&self) -> (usize, Option) { + let (mut low, mut upp) = self.pool.size_hint(); + low = remaining_for(low, self.first, &self.indices).unwrap_or(usize::MAX); + upp = upp.and_then(|upp| remaining_for(upp, self.first, &self.indices)); + (low, upp) + } + + fn count(self) -> usize { + let Self { + indices, + pool, + first, + } = self; + let n = pool.count(); + remaining_for(n, first, &indices).unwrap() + } +} + impl FusedIterator for CombinationsWithReplacement where I: Iterator, I::Item: Clone, -{} +{ +} + +/// For a given size `n`, return the count of remaining combinations with replacement or None if it would overflow. +fn remaining_for(n: usize, first: bool, indices: &[usize]) -> Option { + // With a "stars and bars" representation, choose k values with replacement from n values is + // like choosing k out of k + n − 1 positions (hence binomial(k + n - 1, k) possibilities) + // to place k stars and therefore n - 1 bars. + // Example (n=4, k=6): ***|*||** represents [0,0,0,1,3,3]. + let count = |n: usize, k: usize| { + let positions = if n == 0 { + k.saturating_sub(1) + } else { + (n - 1).checked_add(k)? + }; + checked_binomial(positions, k) + }; + let k = indices.len(); + if first { + count(n, k) + } else { + // The algorithm is similar to the one for combinations *without replacement*, + // except we choose values *with replacement* and indices are *non-strictly* monotonically sorted. + + // The combinations generated after the current one can be counted by counting as follows: + // - The subsequent combinations that differ in indices[0]: + // If subsequent combinations differ in indices[0], then their value for indices[0] + // must be at least 1 greater than the current indices[0]. + // As indices is monotonically sorted, this means we can effectively choose k values with + // replacement from (n - 1 - indices[0]), leading to count(n - 1 - indices[0], k) possibilities. + // - The subsequent combinations with same indices[0], but differing indices[1]: + // Here we can choose k - 1 values with replacement from (n - 1 - indices[1]) values, + // leading to count(n - 1 - indices[1], k - 1) possibilities. + // - (...) + // - The subsequent combinations with same indices[0..=i], but differing indices[i]: + // Here we can choose k - i values with replacement from (n - 1 - indices[i]) values: count(n - 1 - indices[i], k - i). + // Since subsequent combinations can in any index, we must sum up the aforementioned binomial coefficients. + + // Below, `n0` resembles indices[i]. + indices.iter().enumerate().try_fold(0usize, |sum, (i, n0)| { + sum.checked_add(count(n - 1 - *n0, k - i)?) + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/concat_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/concat_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/concat_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/concat_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,6 @@ -use crate::Itertools; - /// Combine all an iterator's elements into one element by using [`Extend`]. /// -/// [`IntoIterator`]-enabled version of [`Itertools::concat`]. +/// [`IntoIterator`]-enabled version of [`Itertools::concat`](crate::Itertools::concat). /// /// This combinator will extend the first item with each of the rest of the /// items of the iterator. If the iterator is empty, the default value of @@ -10,14 +8,20 @@ /// /// ```rust /// use itertools::concat; -/// +/// /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; /// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]); /// ``` pub fn concat(iterable: I) -> I::Item - where I: IntoIterator, - I::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default +where + I: IntoIterator, + I::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default, { - #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce` - iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_default() + iterable + .into_iter() + .reduce(|mut a, b| { + a.extend(b); + a + }) + .unwrap_or_default() } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/cons_tuples_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/cons_tuples_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/cons_tuples_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/cons_tuples_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +use crate::adaptors::map::{MapSpecialCase, MapSpecialCaseFn}; macro_rules! impl_cons_iter( ($_A:ident, $_B:ident, ) => (); // stop @@ -5,60 +6,34 @@ ($A:ident, $($B:ident,)*) => ( impl_cons_iter!($($B,)*); #[allow(non_snake_case)] - impl Iterator for ConsTuples - where Iter: Iterator, - { - type Item = ($($B,)* X, ); - fn next(&mut self) -> Option { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - fn fold(self, accum: Acc, mut f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) - } - } - - #[allow(non_snake_case)] - impl DoubleEndedIterator for ConsTuples - where Iter: DoubleEndedIterator, - { - fn next_back(&mut self) -> Option { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) + impl<$($B),*, X> MapSpecialCaseFn<(($($B,)*), X)> for ConsTuplesFn { + type Out = ($($B,)* X, ); + fn call(&mut self, (($($B,)*), X): (($($B,)*), X)) -> Self::Out { + ($($B,)* X, ) } } - ); ); impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,); +#[derive(Debug, Clone)] +pub struct ConsTuplesFn; + /// An iterator that maps an iterator of tuples like /// `((A, B), C)` to an iterator of `(A, B, C)`. /// /// Used by the `iproduct!()` macro. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct ConsTuples - where I: Iterator, -{ - iter: I, -} - -impl Clone for ConsTuples - where I: Clone + Iterator, -{ - clone_fields!(iter); -} +pub type ConsTuples = MapSpecialCase; /// Create an iterator that maps for example iterators of /// `((A, B), C)` to `(A, B, C)`. -pub fn cons_tuples(iterable: I) -> ConsTuples - where I: IntoIterator +pub fn cons_tuples(iterable: I) -> ConsTuples +where + I: IntoIterator, { - ConsTuples { iter: iterable.into_iter() } + ConsTuples { + iter: iterable.into_iter(), + f: ConsTuplesFn, + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/diff.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/diff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/diff.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/diff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,12 @@ //! "Diff"ing iterators for caching elements to sequential collections without requiring the new //! elements' iterator to be `Clone`. //! -//! - [`Diff`] (produced by the [`diff_with`] function) +//! [`Diff`] (produced by the [`diff_with`] function) //! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from //! a lock-step comparison. +use std::fmt; + use crate::free::put_back; use crate::structs::PutBack; @@ -13,8 +15,9 @@ /// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some /// iterator `J`. pub enum Diff - where I: Iterator, - J: Iterator +where + I: Iterator, + J: Iterator, { /// The index of the first non-matching element along with both iterator's remaining elements /// starting with the first mis-match. @@ -25,6 +28,43 @@ Longer(usize, PutBack), } +impl fmt::Debug for Diff +where + I: Iterator, + J: Iterator, + PutBack: fmt::Debug, + PutBack: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::FirstMismatch(idx, i, j) => f + .debug_tuple("FirstMismatch") + .field(idx) + .field(i) + .field(j) + .finish(), + Self::Shorter(idx, i) => f.debug_tuple("Shorter").field(idx).field(i).finish(), + Self::Longer(idx, j) => f.debug_tuple("Longer").field(idx).field(j).finish(), + } + } +} + +impl Clone for Diff +where + I: Iterator, + J: Iterator, + PutBack: Clone, + PutBack: Clone, +{ + fn clone(&self) -> Self { + match self { + Self::FirstMismatch(idx, i, j) => Self::FirstMismatch(*idx, i.clone(), j.clone()), + Self::Shorter(idx, i) => Self::Shorter(*idx, i.clone()), + Self::Longer(idx, j) => Self::Longer(*idx, j.clone()), + } + } +} + /// Compares every element yielded by both `i` and `j` with the given function in lock-step and /// returns a [`Diff`] which describes how `j` differs from `i`. /// @@ -37,11 +77,11 @@ /// /// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with /// the remaining `j` elements will be returned as `Diff::Longer`. -pub fn diff_with(i: I, j: J, is_equal: F) - -> Option> - where I: IntoIterator, - J: IntoIterator, - F: Fn(&I::Item, &J::Item) -> bool +pub fn diff_with(i: I, j: J, mut is_equal: F) -> Option> +where + I: IntoIterator, + J: IntoIterator, + F: FnMut(&I::Item, &J::Item) -> bool, { let mut i = i.into_iter(); let mut j = j.into_iter(); @@ -49,13 +89,16 @@ while let Some(i_elem) = i.next() { match j.next() { None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))), - Some(j_elem) => if !is_equal(&i_elem, &j_elem) { - let remaining_i = put_back(i).with_value(i_elem); - let remaining_j = put_back(j).with_value(j_elem); - return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); - }, + Some(j_elem) => { + if !is_equal(&i_elem, &j_elem) { + let remaining_i = put_back(i).with_value(i_elem); + let remaining_j = put_back(j).with_value(j_elem); + return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); + } + } } idx += 1; } - j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) + j.next() + .map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/duplicates_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/duplicates_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/duplicates_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/duplicates_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,8 +2,8 @@ mod private { use std::collections::HashMap; - use std::hash::Hash; use std::fmt; + use std::hash::Hash; #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -22,7 +22,7 @@ impl DuplicatesBy { pub(crate) fn new(iter: I, key_method: F) -> Self { - DuplicatesBy { + Self { iter, meta: Meta { used: HashMap::new(), @@ -77,7 +77,7 @@ type Item = I::Item; fn next(&mut self) -> Option { - let DuplicatesBy { iter, meta } = self; + let Self { iter, meta } = self; iter.find_map(|v| meta.filter(v)) } @@ -109,7 +109,7 @@ F: KeyMethod, { fn next_back(&mut self) -> Option { - let DuplicatesBy { iter, meta } = self; + let Self { iter, meta } = self; iter.rev().find_map(|v| meta.filter(v)) } } @@ -122,7 +122,7 @@ } /// Apply the identity function to elements before checking them for equality. - #[derive(Debug)] + #[derive(Debug, Clone)] pub struct ById; impl KeyMethod for ById { type Container = JustValue; @@ -133,6 +133,7 @@ } /// Apply a user-supplied function to elements before checking them for equality. + #[derive(Clone)] pub struct ByFn(pub(crate) F); impl fmt::Debug for ByFn { debug_fmt_fields!(ByFn,); @@ -213,4 +214,3 @@ { Duplicates::new(iter, private::ById) } - diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/either_or_both.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/either_or_both.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/either_or_both.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/either_or_both.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,12 @@ +use core::ops::{Deref, DerefMut}; + use crate::EitherOrBoth::*; use either::Either; /// Value that either holds a single A or B, or both. #[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub enum EitherOrBoth { +pub enum EitherOrBoth { /// Both values are present. Both(A, B), /// Only the left value of type `A` is present. @@ -14,7 +16,7 @@ } impl EitherOrBoth { - /// If `Left`, or `Both`, return true, otherwise, return false. + /// If `Left`, or `Both`, return true. Otherwise, return false. pub fn has_left(&self) -> bool { self.as_ref().left().is_some() } @@ -24,31 +26,24 @@ self.as_ref().right().is_some() } - /// If Left, return true otherwise, return false. + /// If `Left`, return true. Otherwise, return false. /// Exclusive version of [`has_left`](EitherOrBoth::has_left). pub fn is_left(&self) -> bool { - match *self { - Left(_) => true, - _ => false, - } + matches!(self, Left(_)) } - /// If Right, return true otherwise, return false. + /// If `Right`, return true. Otherwise, return false. /// Exclusive version of [`has_right`](EitherOrBoth::has_right). pub fn is_right(&self) -> bool { - match *self { - Right(_) => true, - _ => false, - } + matches!(self, Right(_)) } - /// If Right, return true otherwise, return false. - /// Equivalent to `self.as_ref().both().is_some()`. + /// If `Both`, return true. Otherwise, return false. pub fn is_both(&self) -> bool { self.as_ref().both().is_some() } - /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`. + /// If `Left`, or `Both`, return `Some` with the left value. Otherwise, return `None`. pub fn left(self) -> Option { match self { Left(left) | Both(left, _) => Some(left), @@ -56,7 +51,7 @@ } } - /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`. + /// If `Right`, or `Both`, return `Some` with the right value. Otherwise, return `None`. pub fn right(self) -> Option { match self { Right(right) | Both(_, right) => Some(right), @@ -64,7 +59,65 @@ } } - /// If Both, return `Some` tuple containing left and right. + /// Return tuple of options corresponding to the left and right value respectively + /// + /// If `Left` return `(Some(..), None)`, if `Right` return `(None,Some(..))`, else return + /// `(Some(..),Some(..))` + pub fn left_and_right(self) -> (Option, Option) { + self.map_any(Some, Some).or_default() + } + + /// If `Left`, return `Some` with the left value. If `Right` or `Both`, return `None`. + /// + /// # Examples + /// + /// ``` + /// // On the `Left` variant. + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Right, Both}}; + /// let x: EitherOrBoth<_, ()> = Left("bonjour"); + /// assert_eq!(x.just_left(), Some("bonjour")); + /// + /// // On the `Right` variant. + /// let x: EitherOrBoth<(), _> = Right("hola"); + /// assert_eq!(x.just_left(), None); + /// + /// // On the `Both` variant. + /// let x = Both("bonjour", "hola"); + /// assert_eq!(x.just_left(), None); + /// ``` + pub fn just_left(self) -> Option { + match self { + Left(left) => Some(left), + _ => None, + } + } + + /// If `Right`, return `Some` with the right value. If `Left` or `Both`, return `None`. + /// + /// # Examples + /// + /// ``` + /// // On the `Left` variant. + /// # use itertools::{EitherOrBoth::{Left, Right, Both}, EitherOrBoth}; + /// let x: EitherOrBoth<_, ()> = Left("auf wiedersehen"); + /// assert_eq!(x.just_left(), Some("auf wiedersehen")); + /// + /// // On the `Right` variant. + /// let x: EitherOrBoth<(), _> = Right("adios"); + /// assert_eq!(x.just_left(), None); + /// + /// // On the `Both` variant. + /// let x = Both("auf wiedersehen", "adios"); + /// assert_eq!(x.just_left(), None); + /// ``` + pub fn just_right(self) -> Option { + match self { + Right(right) => Some(right), + _ => None, + } + } + + /// If `Both`, return `Some` containing the left and right values. Otherwise, return `None`. pub fn both(self) -> Option<(A, B)> { match self { Both(a, b) => Some((a, b)), @@ -72,6 +125,28 @@ } } + /// If `Left` or `Both`, return the left value. Otherwise, convert the right value and return it. + pub fn into_left(self) -> A + where + B: Into, + { + match self { + Left(a) | Both(a, _) => a, + Right(b) => b.into(), + } + } + + /// If `Right` or `Both`, return the right value. Otherwise, convert the left value and return it. + pub fn into_right(self) -> B + where + A: Into, + { + match self { + Right(b) | Both(_, b) => b, + Left(a) => a.into(), + } + } + /// Converts from `&EitherOrBoth` to `EitherOrBoth<&A, &B>`. pub fn as_ref(&self) -> EitherOrBoth<&A, &B> { match *self { @@ -90,6 +165,32 @@ } } + /// Converts from `&EitherOrBoth` to `EitherOrBoth<&_, &_>` using the [`Deref`] trait. + pub fn as_deref(&self) -> EitherOrBoth<&A::Target, &B::Target> + where + A: Deref, + B: Deref, + { + match *self { + Left(ref left) => Left(left), + Right(ref right) => Right(right), + Both(ref left, ref right) => Both(left, right), + } + } + + /// Converts from `&mut EitherOrBoth` to `EitherOrBoth<&mut _, &mut _>` using the [`DerefMut`] trait. + pub fn as_deref_mut(&mut self) -> EitherOrBoth<&mut A::Target, &mut B::Target> + where + A: DerefMut, + B: DerefMut, + { + match *self { + Left(ref mut left) => Left(left), + Right(ref mut right) => Right(right), + Both(ref mut left, ref mut right) => Both(left, right), + } + } + /// Convert `EitherOrBoth` to `EitherOrBoth`. pub fn flip(self) -> EitherOrBoth { match self { @@ -200,9 +301,9 @@ B: Default, { match self { - EitherOrBoth::Left(l) => (l, B::default()), - EitherOrBoth::Right(r) => (A::default(), r), - EitherOrBoth::Both(l, r) => (l, r), + Left(l) => (l, B::default()), + Right(r) => (A::default(), r), + Both(l, r) => (l, r), } } @@ -227,10 +328,160 @@ Both(inner_l, inner_r) => (inner_l, inner_r), } } + + /// Returns a mutable reference to the left value. If the left value is not present, + /// it is replaced with `val`. + pub fn left_or_insert(&mut self, val: A) -> &mut A { + self.left_or_insert_with(|| val) + } + + /// Returns a mutable reference to the right value. If the right value is not present, + /// it is replaced with `val`. + pub fn right_or_insert(&mut self, val: B) -> &mut B { + self.right_or_insert_with(|| val) + } + + /// If the left value is not present, replace it the value computed by the closure `f`. + /// Returns a mutable reference to the now-present left value. + pub fn left_or_insert_with(&mut self, f: F) -> &mut A + where + F: FnOnce() -> A, + { + match self { + Left(left) | Both(left, _) => left, + Right(_) => self.insert_left(f()), + } + } + + /// If the right value is not present, replace it the value computed by the closure `f`. + /// Returns a mutable reference to the now-present right value. + pub fn right_or_insert_with(&mut self, f: F) -> &mut B + where + F: FnOnce() -> B, + { + match self { + Right(right) | Both(_, right) => right, + Left(_) => self.insert_right(f()), + } + } + + /// Sets the `left` value of this instance, and returns a mutable reference to it. + /// Does not affect the `right` value. + /// + /// # Examples + /// ``` + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Right, Both}}; + /// + /// // Overwriting a pre-existing value. + /// let mut either: EitherOrBoth<_, ()> = Left(0_u32); + /// assert_eq!(*either.insert_left(69), 69); + /// + /// // Inserting a second value. + /// let mut either = Right("no"); + /// assert_eq!(*either.insert_left("yes"), "yes"); + /// assert_eq!(either, Both("yes", "no")); + /// ``` + pub fn insert_left(&mut self, val: A) -> &mut A { + match self { + Left(left) | Both(left, _) => { + *left = val; + left + } + Right(right) => { + // This is like a map in place operation. We move out of the reference, + // change the value, and then move back into the reference. + unsafe { + // SAFETY: We know this pointer is valid for reading since we got it from a reference. + let right = std::ptr::read(right as *mut _); + // SAFETY: Again, we know the pointer is valid since we got it from a reference. + std::ptr::write(self as *mut _, Both(val, right)); + } + + if let Both(left, _) = self { + left + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } + } + } + + /// Sets the `right` value of this instance, and returns a mutable reference to it. + /// Does not affect the `left` value. + /// + /// # Examples + /// ``` + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Both}}; + /// // Overwriting a pre-existing value. + /// let mut either: EitherOrBoth<_, ()> = Left(0_u32); + /// assert_eq!(*either.insert_left(69), 69); + /// + /// // Inserting a second value. + /// let mut either = Left("what's"); + /// assert_eq!(*either.insert_right(9 + 10), 21 - 2); + /// assert_eq!(either, Both("what's", 9+10)); + /// ``` + pub fn insert_right(&mut self, val: B) -> &mut B { + match self { + Right(right) | Both(_, right) => { + *right = val; + right + } + Left(left) => { + // This is like a map in place operation. We move out of the reference, + // change the value, and then move back into the reference. + unsafe { + // SAFETY: We know this pointer is valid for reading since we got it from a reference. + let left = std::ptr::read(left as *mut _); + // SAFETY: Again, we know the pointer is valid since we got it from a reference. + std::ptr::write(self as *mut _, Both(left, val)); + } + if let Both(_, right) = self { + right + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } + } + } + + /// Set `self` to `Both(..)`, containing the specified left and right values, + /// and returns a mutable reference to those values. + pub fn insert_both(&mut self, left: A, right: B) -> (&mut A, &mut B) { + *self = Both(left, right); + if let Both(left, right) = self { + (left, right) + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } } impl EitherOrBoth { - /// Return either value of left, right, or the product of `f` applied where `Both` are present. + /// Return either value of left, right, or apply a function `f` to both values if both are present. + /// The input function has to return the same type as both Right and Left carry. + /// + /// This function can be used to preferrably extract the left resp. right value, + /// but fall back to the other (i.e. right resp. left) if the preferred one is not present. + /// + /// # Examples + /// ``` + /// # use itertools::EitherOrBoth; + /// assert_eq!(EitherOrBoth::Both(3, 7).reduce(u32::max), 7); + /// assert_eq!(EitherOrBoth::Left(3).reduce(u32::max), 3); + /// assert_eq!(EitherOrBoth::Right(7).reduce(u32::max), 7); + /// + /// // Extract the left value if present, fall back to the right otherwise. + /// assert_eq!(EitherOrBoth::Left("left").reduce(|l, _r| l), "left"); + /// assert_eq!(EitherOrBoth::Right("right").reduce(|l, _r| l), "right"); + /// assert_eq!(EitherOrBoth::Both("left", "right").reduce(|l, _r| l), "left"); + /// ``` pub fn reduce(self, f: F) -> T where F: FnOnce(T, T) -> T, @@ -243,12 +494,21 @@ } } -impl Into>> for EitherOrBoth { - fn into(self) -> Option> { - match self { - EitherOrBoth::Left(l) => Some(Either::Left(l)), - EitherOrBoth::Right(r) => Some(Either::Right(r)), - _ => None, +impl From> for Option> { + fn from(value: EitherOrBoth) -> Self { + match value { + Left(l) => Some(Either::Left(l)), + Right(r) => Some(Either::Right(r)), + Both(..) => None, + } + } +} + +impl From> for EitherOrBoth { + fn from(either: Either) -> Self { + match either { + Either::Left(l) => Left(l), + Either::Right(l) => Right(l), } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/exactly_one_err.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/exactly_one_err.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/exactly_one_err.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/exactly_one_err.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,7 +8,7 @@ use crate::size_hint; -/// Iterator returned for the error case of `IterTools::exactly_one()` +/// Iterator returned for the error case of `Itertools::exactly_one()` /// This iterator yields exactly the same elements as the input iterator. /// /// During the execution of `exactly_one` the iterator must be mutated. This wrapper @@ -54,26 +54,37 @@ Some(Either::Left([first, second])) => { self.first_two = Some(Either::Right(second)); Some(first) - }, - Some(Either::Right(second)) => { - Some(second) - } - None => { - self.inner.next() } + Some(Either::Right(second)) => Some(second), + None => self.inner.next(), } } fn size_hint(&self) -> (usize, Option) { size_hint::add_scalar(self.inner.size_hint(), self.additional_len()) } -} + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + match self.first_two { + Some(Either::Left([first, second])) => { + init = f(init, first); + init = f(init, second); + } + Some(Either::Right(second)) => init = f(init, second), + None => {} + } + self.inner.fold(init, f) + } +} impl ExactSizeIterator for ExactlyOneError where I: ExactSizeIterator {} -impl Display for ExactlyOneError - where I: Iterator, +impl Display for ExactlyOneError +where + I: Iterator, { fn fmt(&self, f: &mut Formatter) -> FmtResult { let additional = self.additional_len(); @@ -85,26 +96,30 @@ } } -impl Debug for ExactlyOneError - where I: Iterator + Debug, - I::Item: Debug, +impl Debug for ExactlyOneError +where + I: Iterator + Debug, + I::Item: Debug, { fn fmt(&self, f: &mut Formatter) -> FmtResult { + let mut dbg = f.debug_struct("ExactlyOneError"); match &self.first_two { Some(Either::Left([first, second])) => { - write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner) - }, - Some(Either::Right(second)) => { - write!(f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]", second, self.inner) + dbg.field("first", first).field("second", second); } - None => { - write!(f, "ExactlyOneError[RemainingIter: {:?}]", self.inner) + Some(Either::Right(second)) => { + dbg.field("second", second); } + None => {} } + dbg.field("inner", &self.inner).finish() } } #[cfg(feature = "use_std")] -impl Error for ExactlyOneError where I: Iterator + Debug, I::Item: Debug, {} - - +impl Error for ExactlyOneError +where + I: Iterator + Debug, + I::Item: Debug, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/extrema_set.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/extrema_set.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/extrema_set.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/extrema_set.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +use alloc::{vec, vec::Vec}; use std::cmp::Ordering; /// Implementation guts for `min_set`, `min_set_by`, and `min_set_by_key`. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/flatten_ok.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/flatten_ok.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/flatten_ok.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/flatten_ok.rs 2006-07-24 01:21:28.000000000 +0000 @@ -72,6 +72,29 @@ } } + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + // Front + let mut acc = match self.inner_front { + Some(x) => x.fold(init, |a, o| f(a, Ok(o))), + None => init, + }; + + acc = self.iter.fold(acc, |acc, x| match x { + Ok(it) => it.into_iter().fold(acc, |a, o| f(a, Ok(o))), + Err(e) => f(acc, Err(e)), + }); + + // Back + match self.inner_back { + Some(x) => x.fold(acc, |a, o| f(a, Ok(o))), + None => acc, + } + } + fn size_hint(&self) -> (usize, Option) { let inner_hint = |inner: &Option| { inner @@ -130,6 +153,29 @@ } } } + + fn rfold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + // Back + let mut acc = match self.inner_back { + Some(x) => x.rfold(init, |a, o| f(a, Ok(o))), + None => init, + }; + + acc = self.iter.rfold(acc, |acc, x| match x { + Ok(it) => it.into_iter().rfold(acc, |a, o| f(a, Ok(o))), + Err(e) => f(acc, Err(e)), + }); + + // Front + match self.inner_front { + Some(x) => x.rfold(acc, |a, o| f(a, Ok(o))), + None => acc, + } + } } impl Clone for FlattenOk @@ -147,13 +193,7 @@ T: IntoIterator, T::IntoIter: fmt::Debug, { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FlattenOk") - .field("iter", &self.iter) - .field("inner_front", &self.inner_front) - .field("inner_back", &self.inner_back) - .finish() - } + debug_fmt_fields!(FlattenOk, iter, inner_front, inner_back); } /// Only the iterator being flattened needs to implement [`FusedIterator`]. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/format.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/format.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/format.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/format.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ +use std::cell::Cell; use std::fmt; -use std::cell::RefCell; /// Format all iterator elements lazily, separated by `sep`. /// @@ -7,11 +7,10 @@ /// exhausted. /// /// See [`.format_with()`](crate::Itertools::format_with) for more information. -#[derive(Clone)] pub struct FormatWith<'a, I, F> { sep: &'a str, - /// FormatWith uses interior mutability because Display::fmt takes &self. - inner: RefCell>, + /// `FormatWith` uses interior mutability because `Display::fmt` takes `&self`. + inner: Cell>, } /// Format all iterator elements lazily, separated by `sep`. @@ -21,38 +20,40 @@ /// /// See [`.format()`](crate::Itertools::format) /// for more information. -#[derive(Clone)] pub struct Format<'a, I> { sep: &'a str, - /// Format uses interior mutability because Display::fmt takes &self. - inner: RefCell>, + /// `Format` uses interior mutability because `Display::fmt` takes `&self`. + inner: Cell>, } pub fn new_format(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +where + I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { FormatWith { sep: separator, - inner: RefCell::new(Some((iter, f))), + inner: Cell::new(Some((iter, f))), } } pub fn new_format_default(iter: I, separator: &str) -> Format<'_, I> - where I: Iterator, +where + I: Iterator, { Format { sep: separator, - inner: RefCell::new(Some(iter)), + inner: Cell::new(Some(iter)), } } -impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +impl fmt::Display for FormatWith<'_, I, F> +where + I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (mut iter, mut format) = match self.inner.borrow_mut().take() { + let (mut iter, mut format) = match self.inner.take() { Some(t) => t, None => panic!("FormatWith: was already formatted once"), }; @@ -70,13 +71,26 @@ } } -impl<'a, I> Format<'a, I> - where I: Iterator, +impl fmt::Debug for FormatWith<'_, I, F> +where + I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { - fn format(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result - where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, - { - let mut iter = match self.inner.borrow_mut().take() { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl Format<'_, I> +where + I: Iterator, +{ + fn format( + &self, + f: &mut fmt::Formatter, + cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result, + ) -> fmt::Result { + let mut iter = match self.inner.take() { Some(t) => t, None => panic!("Format: was already formatted once"), }; @@ -109,5 +123,56 @@ } } -impl_format!{Display Debug - UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} +impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} + +impl Clone for FormatWith<'_, I, F> +where + (I, F): Clone, +{ + fn clone(&self) -> Self { + struct PutBackOnDrop<'r, 'a, I, F> { + into: &'r FormatWith<'a, I, F>, + inner: Option<(I, F)>, + } + // This ensures we preserve the state of the original `FormatWith` if `Clone` panics + impl Drop for PutBackOnDrop<'_, '_, I, F> { + fn drop(&mut self) { + self.into.inner.set(self.inner.take()) + } + } + let pbod = PutBackOnDrop { + inner: self.inner.take(), + into: self, + }; + Self { + inner: Cell::new(pbod.inner.clone()), + sep: self.sep, + } + } +} + +impl Clone for Format<'_, I> +where + I: Clone, +{ + fn clone(&self) -> Self { + struct PutBackOnDrop<'r, 'a, I> { + into: &'r Format<'a, I>, + inner: Option, + } + // This ensures we preserve the state of the original `FormatWith` if `Clone` panics + impl Drop for PutBackOnDrop<'_, '_, I> { + fn drop(&mut self) { + self.into.inner.set(self.inner.take()) + } + } + let pbod = PutBackOnDrop { + inner: self.inner.take(), + into: self, + }; + Self { + inner: Cell::new(pbod.inner.clone()), + sep: self.sep, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/free.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/free.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/free.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/free.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,30 +10,24 @@ type VecIntoIter = alloc::vec::IntoIter; #[cfg(feature = "use_alloc")] -use alloc::{ - string::String, -}; +use alloc::string::String; -use crate::Itertools; use crate::intersperse::{Intersperse, IntersperseWith}; +use crate::Itertools; -pub use crate::adaptors::{ - interleave, - merge, - put_back, -}; +pub use crate::adaptors::{interleave, put_back}; #[cfg(feature = "use_alloc")] -pub use crate::put_back_n_impl::put_back_n; +pub use crate::kmerge_impl::kmerge; +pub use crate::merge_join::{merge, merge_join_by}; #[cfg(feature = "use_alloc")] pub use crate::multipeek_impl::multipeek; #[cfg(feature = "use_alloc")] pub use crate::peek_nth::peek_nth; #[cfg(feature = "use_alloc")] -pub use crate::kmerge_impl::kmerge; -pub use crate::zip_eq_impl::zip_eq; -pub use crate::merge_join::merge_join_by; +pub use crate::put_back_n_impl::put_back_n; #[cfg(feature = "use_alloc")] pub use crate::rciter_impl::rciter; +pub use crate::zip_eq_impl::zip_eq; /// Iterate `iterable` with a particular value inserted between each element. /// @@ -42,11 +36,12 @@ /// ``` /// use itertools::intersperse; /// -/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]); +/// itertools::assert_equal(intersperse(0..3, 8), vec![0, 8, 1, 8, 2]); /// ``` pub fn intersperse(iterable: I, element: I::Item) -> Intersperse - where I: IntoIterator, - ::Item: Clone +where + I: IntoIterator, + ::Item: Clone, { Itertools::intersperse(iterable.into_iter(), element) } @@ -60,12 +55,13 @@ /// use itertools::intersperse_with; /// /// let mut i = 10; -/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]); +/// itertools::assert_equal(intersperse_with(0..3, || { i -= 1; i }), vec![0, 9, 1, 8, 2]); /// assert_eq!(i, 8); /// ``` pub fn intersperse_with(iterable: I, element: F) -> IntersperseWith - where I: IntoIterator, - F: FnMut() -> I::Item +where + I: IntoIterator, + F: FnMut() -> I::Item, { Itertools::intersperse_with(iterable.into_iter(), element) } @@ -79,10 +75,12 @@ /// /// for (i, elt) in enumerate(&[1, 2, 3]) { /// /* loop body */ +/// # let _ = (i, elt); /// } /// ``` pub fn enumerate(iterable: I) -> iter::Enumerate - where I: IntoIterator +where + I: IntoIterator, { iterable.into_iter().enumerate() } @@ -96,11 +94,13 @@ /// /// for elt in rev(&[1, 2, 3]) { /// /* loop body */ +/// # let _ = elt; /// } /// ``` pub fn rev(iterable: I) -> iter::Rev - where I: IntoIterator, - I::IntoIter: DoubleEndedIterator +where + I: IntoIterator, + I::IntoIter: DoubleEndedIterator, { iterable.into_iter().rev() } @@ -108,7 +108,7 @@ /// Converts the arguments to iterators and zips them. /// /// [`IntoIterator`] enabled version of [`Iterator::zip`]. -/// +/// /// ## Example /// /// ``` @@ -121,23 +121,26 @@ /// } /// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]); /// ``` -#[deprecated(note="Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead", since="0.10.4")] +#[deprecated( + note = "Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead", + since = "0.10.4" +)] pub fn zip(i: I, j: J) -> Zip - where I: IntoIterator, - J: IntoIterator +where + I: IntoIterator, + J: IntoIterator, { i.into_iter().zip(j) } - -/// Takes two iterables and creates a new iterator over both in sequence. +/// Takes two iterables and creates a new iterator over both in sequence. /// /// [`IntoIterator`] enabled version of [`Iterator::chain`]. /// /// ## Example /// ``` /// use itertools::chain; -/// +/// /// let mut result:Vec = Vec::new(); /// /// for element in chain(&[1, 2, 3], &[4]) { @@ -145,14 +148,18 @@ /// } /// assert_eq!(result, vec![1, 2, 3, 4]); /// ``` -pub fn chain(i: I, j: J) -> iter::Chain<::IntoIter, ::IntoIter> - where I: IntoIterator, - J: IntoIterator +pub fn chain( + i: I, + j: J, +) -> iter::Chain<::IntoIter, ::IntoIter> +where + I: IntoIterator, + J: IntoIterator, { i.into_iter().chain(j) } -/// Create an iterator that clones each element from &T to T +/// Create an iterator that clones each element from `&T` to `T`. /// /// [`IntoIterator`] enabled version of [`Iterator::cloned`]. /// @@ -161,9 +168,10 @@ /// /// assert_eq!(cloned(b"abc").next(), Some(b'a')); /// ``` -pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned - where I: IntoIterator, - T: Clone, +pub fn cloned<'a, I, T>(iterable: I) -> iter::Cloned +where + I: IntoIterator, + T: Clone + 'a, { iterable.into_iter().cloned() } @@ -178,8 +186,9 @@ /// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.); /// ``` pub fn fold(iterable: I, init: B, f: F) -> B - where I: IntoIterator, - F: FnMut(B, I::Item) -> B +where + I: IntoIterator, + F: FnMut(B, I::Item) -> B, { iterable.into_iter().fold(init, f) } @@ -194,8 +203,9 @@ /// assert!(all(&[1, 2, 3], |elt| *elt > 0)); /// ``` pub fn all(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool +where + I: IntoIterator, + F: FnMut(I::Item) -> bool, { iterable.into_iter().all(f) } @@ -210,8 +220,9 @@ /// assert!(any(&[0, -1, 2], |elt| *elt > 0)); /// ``` pub fn any(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool +where + I: IntoIterator, + F: FnMut(I::Item) -> bool, { iterable.into_iter().any(f) } @@ -226,8 +237,9 @@ /// assert_eq!(max(0..10), Some(9)); /// ``` pub fn max(iterable: I) -> Option - where I: IntoIterator, - I::Item: Ord +where + I: IntoIterator, + I::Item: Ord, { iterable.into_iter().max() } @@ -242,14 +254,14 @@ /// assert_eq!(min(0..10), Some(0)); /// ``` pub fn min(iterable: I) -> Option - where I: IntoIterator, - I::Item: Ord +where + I: IntoIterator, + I::Item: Ord, { iterable.into_iter().min() } - -/// Combine all iterator elements into one String, separated by `sep`. +/// Combine all iterator elements into one `String`, separated by `sep`. /// /// [`IntoIterator`] enabled version of [`Itertools::join`]. /// @@ -260,8 +272,9 @@ /// ``` #[cfg(feature = "use_alloc")] pub fn join(iterable: I, sep: &str) -> String - where I: IntoIterator, - I::Item: Display +where + I: IntoIterator, + I::Item: Display, { iterable.into_iter().join(sep) } @@ -278,9 +291,29 @@ /// ``` #[cfg(feature = "use_alloc")] pub fn sorted(iterable: I) -> VecIntoIter - where I: IntoIterator, - I::Item: Ord +where + I: IntoIterator, + I::Item: Ord, { iterable.into_iter().sorted() } +/// Sort all iterator elements into a new iterator in ascending order. +/// This sort is unstable (i.e., may reorder equal elements). +/// +/// [`IntoIterator`] enabled version of [`Itertools::sorted_unstable`]. +/// +/// ``` +/// use itertools::sorted_unstable; +/// use itertools::assert_equal; +/// +/// assert_equal(sorted_unstable("rust".chars()), "rstu".chars()); +/// ``` +#[cfg(feature = "use_alloc")] +pub fn sorted_unstable(iterable: I) -> VecIntoIter +where + I: IntoIterator, + I::Item: Ord, +{ + iterable.into_iter().sorted_unstable() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/group_map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/group_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/group_map.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/group_map.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,8 +9,9 @@ /// See [`.into_group_map()`](crate::Itertools::into_group_map) /// for more information. pub fn into_group_map(iter: I) -> HashMap> - where I: Iterator, - K: Hash + Eq, +where + I: Iterator, + K: Hash + Eq, { let mut lookup = HashMap::new(); @@ -21,12 +22,11 @@ lookup } -pub fn into_group_map_by(iter: I, f: impl Fn(&V) -> K) -> HashMap> - where - I: Iterator, - K: Hash + Eq, +pub fn into_group_map_by(iter: I, mut f: F) -> HashMap> +where + I: Iterator, + K: Hash + Eq, + F: FnMut(&V) -> K, { - into_group_map( - iter.map(|v| (f(&v), v)) - ) + into_group_map(iter.map(|v| (f(&v), v))) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/groupbylazy.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/groupbylazy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/groupbylazy.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/groupbylazy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,15 @@ -use std::cell::{Cell, RefCell}; use alloc::vec::{self, Vec}; +use std::cell::{Cell, RefCell}; -/// A trait to unify `FnMut` for `GroupBy` with the chunk key in `IntoChunks` +/// A trait to unify `FnMut` for `ChunkBy` with the chunk key in `IntoChunks` trait KeyFunction { type Key; fn call_mut(&mut self, arg: A) -> Self::Key; } -impl KeyFunction for F - where F: FnMut(A) -> K +impl KeyFunction for F +where + F: FnMut(A) -> K + ?Sized, { type Key = K; #[inline] @@ -17,9 +18,8 @@ } } - /// `ChunkIndex` acts like the grouping key function for `IntoChunks` -#[derive(Debug)] +#[derive(Debug, Clone)] struct ChunkIndex { size: usize, index: usize, @@ -29,7 +29,7 @@ impl ChunkIndex { #[inline(always)] fn new(size: usize) -> Self { - ChunkIndex { + Self { size, index: 0, key: 0, @@ -50,9 +50,10 @@ } } - +#[derive(Clone)] struct GroupInner - where I: Iterator +where + I: Iterator, { key: F, iter: I, @@ -65,19 +66,21 @@ /// Least index for which we still have elements buffered oldest_buffered_group: usize, /// Group index for `buffer[0]` -- the slots - /// bottom_group..oldest_buffered_group are unused and will be erased when + /// `bottom_group..oldest_buffered_group` are unused and will be erased when /// that range is large enough. bottom_group: usize, /// Buffered groups, from `bottom_group` (index 0) to `top_group`. buffer: Vec>, - /// index of last group iter that was dropped, usize::MAX == none + /// index of last group iter that was dropped, + /// `usize::MAX` initially when no group was dropped dropped_group: usize, } impl GroupInner - where I: Iterator, - F: for<'a> KeyFunction<&'a I::Item, Key=K>, - K: PartialEq, +where + I: Iterator, + F: for<'a> KeyFunction<&'a I::Item, Key = K>, + K: PartialEq, { /// `client`: Index of group that requests next element #[inline(always)] @@ -90,9 +93,8 @@ */ if client < self.oldest_buffered_group { None - } else if client < self.top_group || - (client == self.top_group && - self.buffer.len() > self.top_group - self.bottom_group) + } else if client < self.top_group + || (client == self.top_group && self.buffer.len() > self.top_group - self.bottom_group) { self.lookup_buffer(client) } else if self.done { @@ -118,8 +120,10 @@ // `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it. self.oldest_buffered_group += 1; // skip forward further empty queues too - while self.buffer.get(self.oldest_buffered_group - self.bottom_group) - .map_or(false, |buf| buf.len() == 0) + while self + .buffer + .get(self.oldest_buffered_group - self.bottom_group) + .map_or(false, |buf| buf.len() == 0) { self.oldest_buffered_group += 1; } @@ -144,12 +148,14 @@ fn next_element(&mut self) -> Option { debug_assert!(!self.done); match self.iter.next() { - None => { self.done = true; None } + None => { + self.done = true; + None + } otherwise => otherwise, } } - #[inline(never)] fn step_buffering(&mut self, client: usize) -> Option { // requested a later group -- walk through the current group up to @@ -171,11 +177,13 @@ let key = self.key.call_mut(&elt); match self.current_key.take() { None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - first_elt = Some(elt); - break; - }, + Some(old_key) => { + if old_key != key { + self.current_key = Some(key); + first_elt = Some(elt); + break; + } + } } self.current_key = Some(key); if self.top_group != self.dropped_group { @@ -220,12 +228,14 @@ let key = self.key.call_mut(&elt); match self.current_key.take() { None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - self.current_elt = Some(elt); - self.top_group += 1; - return None; - }, + Some(old_key) => { + if old_key != key { + self.current_key = Some(key); + self.current_elt = Some(elt); + self.top_group += 1; + return None; + } + } } self.current_key = Some(key); Some(elt) @@ -261,7 +271,8 @@ } impl GroupInner - where I: Iterator, +where + I: Iterator, { /// Called when a group is dropped fn drop_group(&mut self, client: usize) { @@ -272,10 +283,14 @@ } } -/// `GroupBy` is the storage for the lazy grouping operation. +#[deprecated(note = "Use `ChunkBy` instead", since = "0.13.0")] +/// See [`ChunkBy`](crate::structs::ChunkBy). +pub type GroupBy = ChunkBy; + +/// `ChunkBy` is the storage for the lazy grouping operation. /// /// If the groups are consumed in their original order, or if each -/// group is dropped without keeping it around, then `GroupBy` uses +/// group is dropped without keeping it around, then `ChunkBy` uses /// no allocations. It needs allocations only if several group iterators /// are alive at the same time. /// @@ -284,10 +299,11 @@ /// value. It should be stored in a local variable or temporary and /// iterated. /// -/// See [`.group_by()`](crate::Itertools::group_by) for more information. +/// See [`.chunk_by()`](crate::Itertools::chunk_by) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct GroupBy - where I: Iterator, +pub struct ChunkBy +where + I: Iterator, { inner: RefCell>, // the group iterator's current index. Keep this in the main value @@ -296,11 +312,12 @@ } /// Create a new -pub fn new(iter: J, f: F) -> GroupBy - where J: IntoIterator, - F: FnMut(&J::Item) -> K, +pub fn new(iter: J, f: F) -> ChunkBy +where + J: IntoIterator, + F: FnMut(&J::Item) -> K, { - GroupBy { + ChunkBy { inner: RefCell::new(GroupInner { key: f, iter: iter.into_iter(), @@ -317,13 +334,15 @@ } } -impl GroupBy - where I: Iterator, +impl ChunkBy +where + I: Iterator, { /// `client`: Index of group that requests next element fn step(&self, client: usize) -> Option - where F: FnMut(&I::Item) -> K, - K: PartialEq, + where + F: FnMut(&I::Item) -> K, + K: PartialEq, { self.inner.borrow_mut().step(client) } @@ -334,11 +353,12 @@ } } -impl<'a, K, I, F> IntoIterator for &'a GroupBy - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq +impl<'a, K, I, F> IntoIterator for &'a ChunkBy +where + I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq, { type Item = (K, Group<'a, K, I, F>); type IntoIter = Groups<'a, K, I, F>; @@ -348,26 +368,29 @@ } } - /// An iterator that yields the Group iterators. /// /// Iterator element type is `(K, Group)`: /// the group's key `K` and the group's iterator. /// -/// See [`.group_by()`](crate::Itertools::group_by) for more information. +/// See [`.chunk_by()`](crate::Itertools::chunk_by) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Groups<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a +pub struct Groups<'a, K, I, F> +where + I: Iterator + 'a, + I::Item: 'a, + K: 'a, + F: 'a, { - parent: &'a GroupBy, + parent: &'a ChunkBy, } impl<'a, K, I, F> Iterator for Groups<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq +where + I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq, { type Item = (K, Group<'a, K, I, F>); @@ -378,11 +401,14 @@ let inner = &mut *self.parent.inner.borrow_mut(); inner.step(index).map(|elt| { let key = inner.group_key(index); - (key, Group { - parent: self.parent, - index, - first: Some(elt), - }) + ( + key, + Group { + parent: self.parent, + index, + first: Some(elt), + }, + ) }) } } @@ -390,18 +416,22 @@ /// An iterator for the elements in a single group. /// /// Iterator element type is `I::Item`. -pub struct Group<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a, +pub struct Group<'a, K, I, F> +where + I: Iterator + 'a, + I::Item: 'a, + K: 'a, + F: 'a, { - parent: &'a GroupBy, + parent: &'a ChunkBy, index: usize, first: Option, } impl<'a, K, I, F> Drop for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, +where + I: Iterator, + I::Item: 'a, { fn drop(&mut self) { self.parent.drop_group(self.index); @@ -409,10 +439,11 @@ } impl<'a, K, I, F> Iterator for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq, +where + I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq, { type Item = I::Item; #[inline] @@ -428,7 +459,8 @@ /// Create a new pub fn new_chunks(iter: J, size: usize) -> IntoChunks - where J: IntoIterator, +where + J: IntoIterator, { IntoChunks { inner: RefCell::new(GroupInner { @@ -447,10 +479,9 @@ } } - /// `ChunkLazy` is the storage for a lazy chunking operation. /// -/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and +/// `IntoChunks` behaves just like `ChunkBy`: it is iterable, and /// it only buffers if several chunk iterators are alive at the same time. /// /// This type implements [`IntoIterator`] (it is **not** an iterator @@ -463,7 +494,8 @@ /// See [`.chunks()`](crate::Itertools::chunks) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct IntoChunks - where I: Iterator, +where + I: Iterator, { inner: RefCell>, // the chunk iterator's current index. Keep this in the main value @@ -471,9 +503,17 @@ index: Cell, } +impl Clone for IntoChunks +where + I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(inner, index); +} impl IntoChunks - where I: Iterator, +where + I: Iterator, { /// `client`: Index of chunk that requests next element fn step(&self, client: usize) -> Option { @@ -487,36 +527,37 @@ } impl<'a, I> IntoIterator for &'a IntoChunks - where I: Iterator, - I::Item: 'a, +where + I: Iterator, + I::Item: 'a, { type Item = Chunk<'a, I>; type IntoIter = Chunks<'a, I>; fn into_iter(self) -> Self::IntoIter { - Chunks { - parent: self, - } + Chunks { parent: self } } } - /// An iterator that yields the Chunk iterators. /// /// Iterator element type is `Chunk`. /// /// See [`.chunks()`](crate::Itertools::chunks) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Chunks<'a, I: 'a> - where I: Iterator, - I::Item: 'a, +#[derive(Clone)] +pub struct Chunks<'a, I> +where + I: Iterator + 'a, + I::Item: 'a, { parent: &'a IntoChunks, } impl<'a, I> Iterator for Chunks<'a, I> - where I: Iterator, - I::Item: 'a, +where + I: Iterator, + I::Item: 'a, { type Item = Chunk<'a, I>; @@ -525,12 +566,10 @@ let index = self.parent.index.get(); self.parent.index.set(index + 1); let inner = &mut *self.parent.inner.borrow_mut(); - inner.step(index).map(|elt| { - Chunk { - parent: self.parent, - index, - first: Some(elt), - } + inner.step(index).map(|elt| Chunk { + parent: self.parent, + index, + first: Some(elt), }) } } @@ -538,9 +577,10 @@ /// An iterator for the elements in a single chunk. /// /// Iterator element type is `I::Item`. -pub struct Chunk<'a, I: 'a> - where I: Iterator, - I::Item: 'a, +pub struct Chunk<'a, I> +where + I: Iterator + 'a, + I::Item: 'a, { parent: &'a IntoChunks, index: usize, @@ -548,8 +588,9 @@ } impl<'a, I> Drop for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, +where + I: Iterator, + I::Item: 'a, { fn drop(&mut self) { self.parent.drop_group(self.index); @@ -557,8 +598,9 @@ } impl<'a, I> Iterator for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, +where + I: Iterator, + I::Item: 'a, { type Item = I::Item; #[inline] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/grouping_map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/grouping_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/grouping_map.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/grouping_map.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,50 +1,58 @@ -#![cfg(feature = "use_std")] - -use crate::MinMaxResult; -use std::collections::HashMap; +use crate::{ + adaptors::map::{MapSpecialCase, MapSpecialCaseFn}, + MinMaxResult, +}; use std::cmp::Ordering; +use std::collections::HashMap; use std::hash::Hash; use std::iter::Iterator; use std::ops::{Add, Mul}; /// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by) -#[derive(Clone, Debug)] -pub struct MapForGrouping(I, F); +pub type MapForGrouping = MapSpecialCase>; -impl MapForGrouping { - pub(crate) fn new(iter: I, key_mapper: F) -> Self { - Self(iter, key_mapper) +#[derive(Clone)] +pub struct GroupingMapFn(F); + +impl std::fmt::Debug for GroupingMapFn { + debug_fmt_fields!(GroupingMapFn,); +} + +impl K> MapSpecialCaseFn for GroupingMapFn { + type Out = (K, V); + fn call(&mut self, v: V) -> Self::Out { + ((self.0)(&v), v) } } -impl Iterator for MapForGrouping - where I: Iterator, - K: Hash + Eq, - F: FnMut(&V) -> K, -{ - type Item = (K, V); - fn next(&mut self) -> Option { - self.0.next().map(|val| ((self.1)(&val), val)) +pub(crate) fn new_map_for_grouping K>( + iter: I, + key_mapper: F, +) -> MapForGrouping { + MapSpecialCase { + iter, + f: GroupingMapFn(key_mapper), } } /// Creates a new `GroupingMap` from `iter` pub fn new(iter: I) -> GroupingMap - where I: Iterator, - K: Hash + Eq, +where + I: Iterator, + K: Hash + Eq, { GroupingMap { iter } } /// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations. -/// +/// /// See [`GroupingMap`] for more informations. pub type GroupingMapBy = GroupingMap>; /// `GroupingMap` is an intermediate struct for efficient group-and-fold operations. /// It groups elements by their key and at the same time fold each group /// using some aggregating operation. -/// +/// /// No method on this struct performs temporary allocations. #[derive(Clone, Debug)] #[must_use = "GroupingMap is lazy and do nothing unless consumed"] @@ -53,13 +61,14 @@ } impl GroupingMap - where I: Iterator, - K: Hash + Eq, +where + I: Iterator, + K: Hash + Eq, { /// This is the generic way to perform any operation on a `GroupingMap`. /// It's suggested to use this method only to implement custom operations /// when the already provided ones are not enough. - /// + /// /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements /// of each group sequentially, passing the previously accumulated value, a reference to the key /// and the current element as arguments, and stores the results in an `HashMap`. @@ -68,17 +77,17 @@ /// - the current value of the accumulator of the group if there is currently one; /// - a reference to the key of the group this element belongs to; /// - the element from the source being aggregated; - /// + /// /// If `operation` returns `Some(element)` then the accumulator is updated with `element`, /// otherwise the previous accumulation is discarded. /// /// Return a `HashMap` associating the key of each group with the result of aggregation of /// that group's elements. If the aggregation of the last element of a group discards the /// accumulator then there won't be an entry associated to that group's key. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10]; /// let lookup = data.into_iter() /// .into_grouping_map_by(|&n| n % 4) @@ -89,7 +98,7 @@ /// Some(acc.unwrap_or(0) + val) /// } /// }); - /// + /// /// assert_eq!(lookup[&0], 4); // 0 resets the accumulator so only 4 is summed /// assert_eq!(lookup[&1], 5 + 9); /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward @@ -97,7 +106,8 @@ /// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2 /// ``` pub fn aggregate(self, mut operation: FO) -> HashMap - where FO: FnMut(Option, &K, V) -> Option, + where + FO: FnMut(Option, &K, V) -> Option, { let mut destination_map = HashMap::new(); @@ -115,6 +125,50 @@ /// of each group sequentially, passing the previously accumulated value, a reference to the key /// and the current element as arguments, and stores the results in a new map. /// + /// `init` is called to obtain the initial value of each accumulator. + /// + /// `operation` is a function that is invoked on each element with the following parameters: + /// - the current value of the accumulator of the group; + /// - a reference to the key of the group this element belongs to; + /// - the element from the source being accumulated. + /// + /// Return a `HashMap` associating the key of each group with the result of folding that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// #[derive(Debug, Default)] + /// struct Accumulator { + /// acc: usize, + /// } + /// + /// let lookup = (1..=7) + /// .into_grouping_map_by(|&n| n % 3) + /// .fold_with(|_key, _val| Default::default(), |Accumulator { acc }, _key, val| { + /// let acc = acc + val; + /// Accumulator { acc } + /// }); + /// + /// assert_eq!(lookup[&0].acc, 3 + 6); + /// assert_eq!(lookup[&1].acc, 1 + 4 + 7); + /// assert_eq!(lookup[&2].acc, 2 + 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn fold_with(self, mut init: FI, mut operation: FO) -> HashMap + where + FI: FnMut(&K, &V) -> R, + FO: FnMut(R, &K, V) -> R, + { + self.aggregate(|acc, key, val| { + let acc = acc.unwrap_or_else(|| init(key, &val)); + Some(operation(acc, key, val)) + }) + } + + /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements + /// of each group sequentially, passing the previously accumulated value, a reference to the key + /// and the current element as arguments, and stores the results in a new map. + /// /// `init` is the value from which will be cloned the initial value of each accumulator. /// /// `operation` is a function that is invoked on each element with the following parameters: @@ -123,27 +177,25 @@ /// - the element from the source being accumulated. /// /// Return a `HashMap` associating the key of each group with the result of folding that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = (1..=7) /// .into_grouping_map_by(|&n| n % 3) /// .fold(0, |acc, _key, val| acc + val); - /// + /// /// assert_eq!(lookup[&0], 3 + 6); /// assert_eq!(lookup[&1], 1 + 4 + 7); /// assert_eq!(lookup[&2], 2 + 5); /// assert_eq!(lookup.len(), 3); /// ``` - pub fn fold(self, init: R, mut operation: FO) -> HashMap - where R: Clone, - FO: FnMut(R, &K, V) -> R, + pub fn fold(self, init: R, operation: FO) -> HashMap + where + R: Clone, + FO: FnMut(R, &K, V) -> R, { - self.aggregate(|acc, key, val| { - let acc = acc.unwrap_or_else(|| init.clone()); - Some(operation(acc, key, val)) - }) + self.fold_with(|_, _| init.clone(), operation) } /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements @@ -158,23 +210,24 @@ /// - the element from the source being accumulated. /// /// Return a `HashMap` associating the key of each group with the result of folding that group's elements. - /// + /// /// [`fold`]: GroupingMap::fold - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = (1..=7) /// .into_grouping_map_by(|&n| n % 3) - /// .fold_first(|acc, _key, val| acc + val); - /// + /// .reduce(|acc, _key, val| acc + val); + /// /// assert_eq!(lookup[&0], 3 + 6); /// assert_eq!(lookup[&1], 1 + 4 + 7); /// assert_eq!(lookup[&2], 2 + 5); /// assert_eq!(lookup.len(), 3); /// ``` - pub fn fold_first(self, mut operation: FO) -> HashMap - where FO: FnMut(V, &K, V) -> V, + pub fn reduce(self, mut operation: FO) -> HashMap + where + FO: FnMut(V, &K, V) -> V, { self.aggregate(|acc, key, val| { Some(match acc { @@ -184,250 +237,271 @@ }) } + /// See [`.reduce()`](GroupingMap::reduce). + #[deprecated(note = "Use .reduce() instead", since = "0.13.0")] + pub fn fold_first(self, operation: FO) -> HashMap + where + FO: FnMut(V, &K, V) -> V, + { + self.reduce(operation) + } + /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in - /// an instance of `C`. The iteration order is preserved when inserting elements. - /// + /// an instance of `C`. The iteration order is preserved when inserting elements. + /// /// Return a `HashMap` associating the key of each group with the collection containing that group's elements. - /// + /// /// ``` /// use itertools::Itertools; /// use std::collections::HashSet; - /// + /// /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .collect::>(); - /// + /// /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect::>()); /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect::>()); /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect::>()); /// assert_eq!(lookup.len(), 3); /// ``` pub fn collect(self) -> HashMap - where C: Default + Extend, + where + C: Default + Extend, { let mut destination_map = HashMap::new(); self.iter.for_each(|(key, val)| { - destination_map.entry(key).or_insert_with(C::default).extend(Some(val)); + destination_map + .entry(key) + .or_insert_with(C::default) + .extend(Some(val)); }); destination_map } /// Groups elements from the `GroupingMap` source by key and finds the maximum of each group. - /// + /// /// If several elements are equally maximum, the last element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .max(); - /// + /// /// assert_eq!(lookup[&0], 12); /// assert_eq!(lookup[&1], 7); /// assert_eq!(lookup[&2], 8); /// assert_eq!(lookup.len(), 3); /// ``` pub fn max(self) -> HashMap - where V: Ord, + where + V: Ord, { self.max_by(|_, v1, v2| V::cmp(v1, v2)) } /// Groups elements from the `GroupingMap` source by key and finds the maximum of each group /// with respect to the specified comparison function. - /// + /// /// If several elements are equally maximum, the last element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .max_by(|_key, x, y| y.cmp(x)); - /// + /// /// assert_eq!(lookup[&0], 3); /// assert_eq!(lookup[&1], 1); /// assert_eq!(lookup[&2], 5); /// assert_eq!(lookup.len(), 3); /// ``` pub fn max_by(self, mut compare: F) -> HashMap - where F: FnMut(&K, &V, &V) -> Ordering, + where + F: FnMut(&K, &V, &V) -> Ordering, { - self.fold_first(|acc, key, val| match compare(key, &acc, &val) { + self.reduce(|acc, key, val| match compare(key, &acc, &val) { Ordering::Less | Ordering::Equal => val, - Ordering::Greater => acc + Ordering::Greater => acc, }) } /// Groups elements from the `GroupingMap` source by key and finds the element of each group /// that gives the maximum from the specified function. - /// + /// /// If several elements are equally maximum, the last element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .max_by_key(|_key, &val| val % 4); - /// + /// /// assert_eq!(lookup[&0], 3); /// assert_eq!(lookup[&1], 7); /// assert_eq!(lookup[&2], 5); /// assert_eq!(lookup.len(), 3); /// ``` pub fn max_by_key(self, mut f: F) -> HashMap - where F: FnMut(&K, &V) -> CK, - CK: Ord, + where + F: FnMut(&K, &V) -> CK, + CK: Ord, { self.max_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) } /// Groups elements from the `GroupingMap` source by key and finds the minimum of each group. - /// + /// /// If several elements are equally minimum, the first element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .min(); - /// + /// /// assert_eq!(lookup[&0], 3); /// assert_eq!(lookup[&1], 1); /// assert_eq!(lookup[&2], 5); /// assert_eq!(lookup.len(), 3); /// ``` pub fn min(self) -> HashMap - where V: Ord, + where + V: Ord, { self.min_by(|_, v1, v2| V::cmp(v1, v2)) } /// Groups elements from the `GroupingMap` source by key and finds the minimum of each group /// with respect to the specified comparison function. - /// + /// /// If several elements are equally minimum, the first element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .min_by(|_key, x, y| y.cmp(x)); - /// + /// /// assert_eq!(lookup[&0], 12); /// assert_eq!(lookup[&1], 7); /// assert_eq!(lookup[&2], 8); /// assert_eq!(lookup.len(), 3); /// ``` pub fn min_by(self, mut compare: F) -> HashMap - where F: FnMut(&K, &V, &V) -> Ordering, + where + F: FnMut(&K, &V, &V) -> Ordering, { - self.fold_first(|acc, key, val| match compare(key, &acc, &val) { + self.reduce(|acc, key, val| match compare(key, &acc, &val) { Ordering::Less | Ordering::Equal => acc, - Ordering::Greater => val + Ordering::Greater => val, }) } /// Groups elements from the `GroupingMap` source by key and finds the element of each group /// that gives the minimum from the specified function. - /// + /// /// If several elements are equally minimum, the first element is picked. - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .min_by_key(|_key, &val| val % 4); - /// + /// /// assert_eq!(lookup[&0], 12); /// assert_eq!(lookup[&1], 4); /// assert_eq!(lookup[&2], 8); /// assert_eq!(lookup.len(), 3); /// ``` pub fn min_by_key(self, mut f: F) -> HashMap - where F: FnMut(&K, &V) -> CK, - CK: Ord, + where + F: FnMut(&K, &V) -> CK, + CK: Ord, { self.min_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) } /// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of /// each group. - /// + /// /// If several elements are equally maximum, the last element is picked. /// If several elements are equally minimum, the first element is picked. - /// - /// See [.minmax()](crate::Itertools::minmax) for the non-grouping version. - /// + /// + /// See [`Itertools::minmax`](crate::Itertools::minmax) for the non-grouping version. + /// /// Differences from the non grouping version: /// - It never produces a `MinMaxResult::NoElements` /// - It doesn't have any speedup - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; /// use itertools::MinMaxResult::{OneElement, MinMax}; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .minmax(); - /// + /// /// assert_eq!(lookup[&0], MinMax(3, 12)); /// assert_eq!(lookup[&1], MinMax(1, 7)); /// assert_eq!(lookup[&2], OneElement(5)); /// assert_eq!(lookup.len(), 3); /// ``` pub fn minmax(self) -> HashMap> - where V: Ord, + where + V: Ord, { self.minmax_by(|_, v1, v2| V::cmp(v1, v2)) } /// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of /// each group with respect to the specified comparison function. - /// + /// /// If several elements are equally maximum, the last element is picked. /// If several elements are equally minimum, the first element is picked. - /// + /// /// It has the same differences from the non-grouping version as `minmax`. - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; /// use itertools::MinMaxResult::{OneElement, MinMax}; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .minmax_by(|_key, x, y| y.cmp(x)); - /// + /// /// assert_eq!(lookup[&0], MinMax(12, 3)); /// assert_eq!(lookup[&1], MinMax(7, 1)); /// assert_eq!(lookup[&2], OneElement(5)); /// assert_eq!(lookup.len(), 3); /// ``` pub fn minmax_by(self, mut compare: F) -> HashMap> - where F: FnMut(&K, &V, &V) -> Ordering, + where + F: FnMut(&K, &V, &V) -> Ordering, { self.aggregate(|acc, key, val| { Some(match acc { @@ -455,81 +529,84 @@ /// Groups elements from the `GroupingMap` source by key and find the elements of each group /// that gives the minimum and maximum from the specified function. - /// + /// /// If several elements are equally maximum, the last element is picked. /// If several elements are equally minimum, the first element is picked. - /// + /// /// It has the same differences from the non-grouping version as `minmax`. - /// + /// /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; /// use itertools::MinMaxResult::{OneElement, MinMax}; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .minmax_by_key(|_key, &val| val % 4); - /// + /// /// assert_eq!(lookup[&0], MinMax(12, 3)); /// assert_eq!(lookup[&1], MinMax(4, 7)); /// assert_eq!(lookup[&2], OneElement(5)); /// assert_eq!(lookup.len(), 3); /// ``` pub fn minmax_by_key(self, mut f: F) -> HashMap> - where F: FnMut(&K, &V) -> CK, - CK: Ord, + where + F: FnMut(&K, &V) -> CK, + CK: Ord, { self.minmax_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) } - + /// Groups elements from the `GroupingMap` source by key and sums them. - /// - /// This is just a shorthand for `self.fold_first(|acc, _, val| acc + val)`. + /// + /// This is just a shorthand for `self.reduce(|acc, _, val| acc + val)`. /// It is more limited than `Iterator::sum` since it doesn't use the `Sum` trait. - /// + /// /// Returns a `HashMap` associating the key of each group with the sum of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .sum(); - /// + /// /// assert_eq!(lookup[&0], 3 + 9 + 12); /// assert_eq!(lookup[&1], 1 + 4 + 7); /// assert_eq!(lookup[&2], 5 + 8); /// assert_eq!(lookup.len(), 3); /// ``` pub fn sum(self) -> HashMap - where V: Add + where + V: Add, { - self.fold_first(|acc, _, val| acc + val) + self.reduce(|acc, _, val| acc + val) } /// Groups elements from the `GroupingMap` source by key and multiply them. - /// - /// This is just a shorthand for `self.fold_first(|acc, _, val| acc * val)`. + /// + /// This is just a shorthand for `self.reduce(|acc, _, val| acc * val)`. /// It is more limited than `Iterator::product` since it doesn't use the `Product` trait. - /// + /// /// Returns a `HashMap` associating the key of each group with the product of that group's elements. - /// + /// /// ``` /// use itertools::Itertools; - /// + /// /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() /// .into_grouping_map_by(|&n| n % 3) /// .product(); - /// + /// /// assert_eq!(lookup[&0], 3 * 9 * 12); /// assert_eq!(lookup[&1], 1 * 4 * 7); /// assert_eq!(lookup[&2], 5 * 8); /// assert_eq!(lookup.len(), 3); /// ``` pub fn product(self) -> HashMap - where V: Mul, + where + V: Mul, { - self.fold_first(|acc, _, val| acc * val) + self.reduce(|acc, _, val| acc * val) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/impl_macros.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/impl_macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/impl_macros.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/impl_macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -//! +//! //! Implementation's internal macros macro_rules! debug_fmt_fields { @@ -27,3 +27,8 @@ macro_rules! ignore_ident{ ($id:ident, $($t:tt)*) => {$($t)*}; } + +macro_rules! count_ident { + () => {0}; + ($i0:ident $($i:ident)*) => {1 + count_ident!($($i)*)}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/intersperse.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/intersperse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/intersperse.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/intersperse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -use std::iter::{Fuse, FusedIterator}; use super::size_hint; +use std::iter::{Fuse, FusedIterator}; pub trait IntersperseElement { fn generate(&mut self) -> Item; @@ -26,12 +26,13 @@ /// Create a new Intersperse iterator pub fn intersperse(iter: I, elt: I::Item) -> Intersperse - where I: Iterator, +where + I: Iterator, { intersperse_with(iter, IntersperseElementSimple(elt)) } -implItem> IntersperseElement for F { +impl Item> IntersperseElement for F { fn generate(&mut self) -> Item { self() } @@ -48,71 +49,94 @@ #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pub struct IntersperseWith - where I: Iterator, +where + I: Iterator, { element: ElemF, iter: Fuse, - peek: Option, + /// `peek` is None while no item have been taken out of `iter` (at definition). + /// Then `peek` will alternatively be `Some(None)` and `Some(Some(item))`, + /// where `None` indicates it's time to generate from `element` (unless `iter` is empty). + peek: Option>, } /// Create a new `IntersperseWith` iterator pub fn intersperse_with(iter: I, elt: ElemF) -> IntersperseWith - where I: Iterator, +where + I: Iterator, { - let mut iter = iter.fuse(); IntersperseWith { - peek: iter.next(), - iter, + peek: None, + iter: iter.fuse(), element: elt, } } impl Iterator for IntersperseWith - where I: Iterator, - ElemF: IntersperseElement +where + I: Iterator, + ElemF: IntersperseElement, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - if self.peek.is_some() { - self.peek.take() - } else { - self.peek = self.iter.next(); - if self.peek.is_some() { - Some(self.element.generate()) - } else { - None + let Self { + element, + iter, + peek, + } = self; + match peek { + Some(item @ Some(_)) => item.take(), + Some(None) => match iter.next() { + new @ Some(_) => { + *peek = Some(new); + Some(element.generate()) + } + None => None, + }, + None => { + *peek = Some(None); + iter.next() } } } fn size_hint(&self) -> (usize, Option) { - // 2 * SH + { 1 or 0 } - let has_peek = self.peek.is_some() as usize; - let sh = self.iter.size_hint(); - size_hint::add_scalar(size_hint::add(sh, sh), has_peek) + let mut sh = self.iter.size_hint(); + sh = size_hint::add(sh, sh); + match self.peek { + Some(Some(_)) => size_hint::add_scalar(sh, 1), + Some(None) => sh, + None => size_hint::sub_scalar(sh, 1), + } } - fn fold(mut self, init: B, mut f: F) -> B where - Self: Sized, F: FnMut(B, Self::Item) -> B, + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, { + let Self { + mut element, + mut iter, + peek, + } = self; let mut accum = init; - if let Some(x) = self.peek.take() { + if let Some(x) = peek.unwrap_or_else(|| iter.next()) { accum = f(accum, x); } - let element = &mut self.element; - - self.iter.fold(accum, - |accum, x| { - let accum = f(accum, element.generate()); - f(accum, x) + iter.fold(accum, |accum, x| { + let accum = f(accum, element.generate()); + f(accum, x) }) } } impl FusedIterator for IntersperseWith - where I: Iterator, - ElemF: IntersperseElement -{} +where + I: Iterator, + ElemF: IntersperseElement, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/iter_index.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/iter_index.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/iter_index.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/iter_index.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,116 @@ +use core::iter::{Skip, Take}; +use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; + +#[cfg(doc)] +use crate::Itertools; + +mod private_iter_index { + use core::ops; + + pub trait Sealed {} + + impl Sealed for ops::Range {} + impl Sealed for ops::RangeInclusive {} + impl Sealed for ops::RangeTo {} + impl Sealed for ops::RangeToInclusive {} + impl Sealed for ops::RangeFrom {} + impl Sealed for ops::RangeFull {} +} + +/// Used by [`Itertools::get`] to know which iterator +/// to turn different ranges into. +pub trait IteratorIndex: private_iter_index::Sealed +where + I: Iterator, +{ + /// The type returned for this type of index. + type Output: Iterator; + + /// Returns an adapted iterator for the current index. + /// + /// Prefer calling [`Itertools::get`] instead + /// of calling this directly. + fn index(self, from: I) -> Self::Output; +} + +impl IteratorIndex for Range +where + I: Iterator, +{ + type Output = Skip>; + + fn index(self, iter: I) -> Self::Output { + iter.take(self.end).skip(self.start) + } +} + +impl IteratorIndex for RangeInclusive +where + I: Iterator, +{ + type Output = Take>; + + fn index(self, iter: I) -> Self::Output { + // end - start + 1 without overflowing if possible + let length = if *self.end() == usize::MAX { + assert_ne!(*self.start(), 0); + self.end() - self.start() + 1 + } else { + (self.end() + 1).saturating_sub(*self.start()) + }; + iter.skip(*self.start()).take(length) + } +} + +impl IteratorIndex for RangeTo +where + I: Iterator, +{ + type Output = Take; + + fn index(self, iter: I) -> Self::Output { + iter.take(self.end) + } +} + +impl IteratorIndex for RangeToInclusive +where + I: Iterator, +{ + type Output = Take; + + fn index(self, iter: I) -> Self::Output { + assert_ne!(self.end, usize::MAX); + iter.take(self.end + 1) + } +} + +impl IteratorIndex for RangeFrom +where + I: Iterator, +{ + type Output = Skip; + + fn index(self, iter: I) -> Self::Output { + iter.skip(self.start) + } +} + +impl IteratorIndex for RangeFull +where + I: Iterator, +{ + type Output = I; + + fn index(self, iter: I) -> Self::Output { + iter + } +} + +pub fn get(iter: I, index: R) -> R::Output +where + I: IntoIterator, + R: IteratorIndex, +{ + index.index(iter.into_iter()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/k_smallest.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/k_smallest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/k_smallest.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/k_smallest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,20 +1,138 @@ -use alloc::collections::BinaryHeap; -use core::cmp::Ord; +use alloc::vec::Vec; +use core::cmp::Ordering; -pub(crate) fn k_smallest>(mut iter: I, k: usize) -> BinaryHeap { - if k == 0 { return BinaryHeap::new(); } +/// Consumes a given iterator, returning the minimum elements in **ascending** order. +pub(crate) fn k_smallest_general(iter: I, k: usize, mut comparator: F) -> Vec +where + I: Iterator, + F: FnMut(&I::Item, &I::Item) -> Ordering, +{ + /// Sift the element currently at `origin` away from the root until it is properly ordered. + /// + /// This will leave **larger** elements closer to the root of the heap. + fn sift_down(heap: &mut [T], is_less_than: &mut F, mut origin: usize) + where + F: FnMut(&T, &T) -> bool, + { + #[inline] + fn children_of(n: usize) -> (usize, usize) { + (2 * n + 1, 2 * n + 2) + } + + while origin < heap.len() { + let (left_idx, right_idx) = children_of(origin); + if left_idx >= heap.len() { + return; + } + + let replacement_idx = + if right_idx < heap.len() && is_less_than(&heap[left_idx], &heap[right_idx]) { + right_idx + } else { + left_idx + }; + + if is_less_than(&heap[origin], &heap[replacement_idx]) { + heap.swap(origin, replacement_idx); + origin = replacement_idx; + } else { + return; + } + } + } + + if k == 0 { + iter.last(); + return Vec::new(); + } + if k == 1 { + return iter.min_by(comparator).into_iter().collect(); + } + let mut iter = iter.fuse(); + let mut storage: Vec = iter.by_ref().take(k).collect(); + + let mut is_less_than = move |a: &_, b: &_| comparator(a, b) == Ordering::Less; + + // Rearrange the storage into a valid heap by reordering from the second-bottom-most layer up to the root. + // Slightly faster than ordering on each insert, but only by a factor of lg(k). + // The resulting heap has the **largest** item on top. + for i in (0..=(storage.len() / 2)).rev() { + sift_down(&mut storage, &mut is_less_than, i); + } + + iter.for_each(|val| { + debug_assert_eq!(storage.len(), k); + if is_less_than(&val, &storage[0]) { + // Treating this as an push-and-pop saves having to write a sift-up implementation. + // https://en.wikipedia.org/wiki/Binary_heap#Insert_then_extract + storage[0] = val; + // We retain the smallest items we've seen so far, but ordered largest first so we can drop the largest efficiently. + sift_down(&mut storage, &mut is_less_than, 0); + } + }); - let mut heap = iter.by_ref().take(k).collect::>(); + // Ultimately the items need to be in least-first, strict order, but the heap is currently largest-first. + // To achieve this, repeatedly, + // 1) "pop" the largest item off the heap into the tail slot of the underlying storage, + // 2) shrink the logical size of the heap by 1, + // 3) restore the heap property over the remaining items. + let mut heap = &mut storage[..]; + while heap.len() > 1 { + let last_idx = heap.len() - 1; + heap.swap(0, last_idx); + // Sifting over a truncated slice means that the sifting will not disturb already popped elements. + heap = &mut heap[..last_idx]; + sift_down(heap, &mut is_less_than, 0); + } - iter.for_each(|i| { - debug_assert_eq!(heap.len(), k); - // Equivalent to heap.push(min(i, heap.pop())) but more efficient. - // This should be done with a single `.peek_mut().unwrap()` but - // `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior. - if *heap.peek().unwrap() > i { - *heap.peek_mut().unwrap() = i; + storage +} + +pub(crate) fn k_smallest_relaxed_general(iter: I, k: usize, mut comparator: F) -> Vec +where + I: Iterator, + F: FnMut(&I::Item, &I::Item) -> Ordering, +{ + if k == 0 { + iter.last(); + return Vec::new(); + } + + let mut iter = iter.fuse(); + let mut buf = iter.by_ref().take(2 * k).collect::>(); + + if buf.len() < k { + buf.sort_unstable_by(&mut comparator); + return buf; + } + + buf.select_nth_unstable_by(k - 1, &mut comparator); + buf.truncate(k); + + iter.for_each(|val| { + if comparator(&val, &buf[k - 1]) != Ordering::Less { + return; + } + + assert_ne!(buf.len(), buf.capacity()); + buf.push(val); + + if buf.len() == 2 * k { + buf.select_nth_unstable_by(k - 1, &mut comparator); + buf.truncate(k); } }); - heap + buf.sort_unstable_by(&mut comparator); + buf.truncate(k); + buf +} + +#[inline] +pub(crate) fn key_to_cmp(mut key: F) -> impl FnMut(&T, &T) -> Ordering +where + F: FnMut(&T) -> K, + K: Ord, +{ + move |a, b| key(a).cmp(&key(b)) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/kmerge_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/kmerge_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/kmerge_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/kmerge_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,9 @@ use crate::size_hint; -use crate::Itertools; use alloc::vec::Vec; +use std::fmt; use std::iter::FusedIterator; use std::mem::replace; -use std::fmt; /// Head element and Tail iterator pair /// @@ -15,24 +14,21 @@ /// `KMerge` into a min-heap. #[derive(Debug)] struct HeadTail - where I: Iterator +where + I: Iterator, { head: I::Item, tail: I, } impl HeadTail - where I: Iterator +where + I: Iterator, { /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty. - fn new(mut it: I) -> Option> { + fn new(mut it: I) -> Option { let head = it.next(); - head.map(|h| { - HeadTail { - head: h, - tail: it, - } - }) + head.map(|h| Self { head: h, tail: it }) } /// Get the next element and update `head`, returning the old head in `Some`. @@ -53,15 +49,17 @@ } impl Clone for HeadTail - where I: Iterator + Clone, - I::Item: Clone +where + I: Iterator + Clone, + I::Item: Clone, { clone_fields!(head, tail); } /// Make `data` a heap (min-heap w.r.t the sorting). fn heapify(data: &mut [T], mut less_than: S) - where S: FnMut(&T, &T) -> bool +where + S: FnMut(&T, &T) -> bool, { for i in (0..data.len() / 2).rev() { sift_down(data, i, &mut less_than); @@ -70,7 +68,8 @@ /// Sift down element at `index` (`heap` is a min-heap wrt the ordering) fn sift_down(heap: &mut [T], index: usize, mut less_than: S) - where S: FnMut(&T, &T) -> bool +where + S: FnMut(&T, &T) -> bool, { debug_assert!(index <= heap.len()); let mut pos = index; @@ -81,7 +80,7 @@ while child + 1 < heap.len() { // pick the smaller of the two children // use arithmetic to avoid an unpredictable branch - child += less_than(&heap[child+1], &heap[child]) as usize; + child += less_than(&heap[child + 1], &heap[child]) as usize; // sift down is done if we are already in order if !less_than(&heap[child], &heap[pos]) { @@ -119,7 +118,7 @@ } } -implbool> KMergePredicate for F { +impl bool> KMergePredicate for F { fn kmerge_pred(&mut self, a: &T, b: &T) -> bool { self(a, b) } @@ -128,19 +127,21 @@ /// Create an iterator that merges elements of the contained iterators using /// the ordering function. /// -/// [`IntoIterator`] enabled version of [`Itertools::kmerge`]. +/// [`IntoIterator`] enabled version of [`Itertools::kmerge`](crate::Itertools::kmerge). /// /// ``` /// use itertools::kmerge; /// /// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) { /// /* loop body */ +/// # let _ = elt; /// } /// ``` pub fn kmerge(iterable: I) -> KMerge<::IntoIter> - where I: IntoIterator, - I::Item: IntoIterator, - <::Item as IntoIterator>::Item: PartialOrd +where + I: IntoIterator, + I::Item: IntoIterator, + <::Item as IntoIterator>::Item: PartialOrd, { kmerge_by(iterable, KMergeByLt) } @@ -152,29 +153,34 @@ /// /// See [`.kmerge_by()`](crate::Itertools::kmerge_by) for more /// information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[must_use = "this iterator adaptor is not lazy but does nearly nothing unless consumed"] pub struct KMergeBy - where I: Iterator, +where + I: Iterator, { heap: Vec>, less_than: F, } impl fmt::Debug for KMergeBy - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, { debug_fmt_fields!(KMergeBy, heap); } /// Create an iterator that merges elements of the contained iterators. /// -/// [`IntoIterator`] enabled version of [`Itertools::kmerge_by`]. -pub fn kmerge_by(iterable: I, mut less_than: F) - -> KMergeBy<::IntoIter, F> - where I: IntoIterator, - I::Item: IntoIterator, - F: KMergePredicate<<::Item as IntoIterator>::Item>, +/// [`IntoIterator`] enabled version of [`Itertools::kmerge_by`](crate::Itertools::kmerge_by). +pub fn kmerge_by( + iterable: I, + mut less_than: F, +) -> KMergeBy<::IntoIter, F> +where + I: IntoIterator, + I::Item: IntoIterator, + F: KMergePredicate<<::Item as IntoIterator>::Item>, { let iter = iterable.into_iter(); let (lower, _) = iter.size_hint(); @@ -185,16 +191,18 @@ } impl Clone for KMergeBy - where I: Iterator + Clone, - I::Item: Clone, - F: Clone, +where + I: Iterator + Clone, + I::Item: Clone, + F: Clone, { clone_fields!(heap, less_than); } impl Iterator for KMergeBy - where I: Iterator, - F: KMergePredicate +where + I: Iterator, + F: KMergePredicate, { type Item = I::Item; @@ -208,20 +216,24 @@ self.heap.swap_remove(0).head }; let less_than = &mut self.less_than; - sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head)); + sift_down(&mut self.heap, 0, |a, b| { + less_than.kmerge_pred(&a.head, &b.head) + }); Some(result) } fn size_hint(&self) -> (usize, Option) { - #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce` - self.heap.iter() - .map(|i| i.size_hint()) - .fold1(size_hint::add) - .unwrap_or((0, Some(0))) + self.heap + .iter() + .map(|i| i.size_hint()) + .reduce(size_hint::add) + .unwrap_or((0, Some(0))) } } impl FusedIterator for KMergeBy - where I: Iterator, - F: KMergePredicate -{} +where + I: Iterator, + F: KMergePredicate, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/lazy_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lazy_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/lazy_buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lazy_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,12 @@ -use std::ops::Index; use alloc::vec::Vec; +use std::iter::Fuse; +use std::ops::Index; + +use crate::size_hint::{self, SizeHint}; #[derive(Debug, Clone)] pub struct LazyBuffer { - pub it: I, - done: bool, + it: Fuse, buffer: Vec, } @@ -12,10 +14,9 @@ where I: Iterator, { - pub fn new(it: I) -> LazyBuffer { - LazyBuffer { - it, - done: false, + pub fn new(it: I) -> Self { + Self { + it: it.fuse(), buffer: Vec::new(), } } @@ -24,36 +25,51 @@ self.buffer.len() } + pub fn size_hint(&self) -> SizeHint { + size_hint::add_scalar(self.it.size_hint(), self.len()) + } + + pub fn count(self) -> usize { + self.len() + self.it.count() + } + pub fn get_next(&mut self) -> bool { - if self.done { - return false; - } if let Some(x) = self.it.next() { self.buffer.push(x); true } else { - self.done = true; false } } pub fn prefill(&mut self, len: usize) { let buffer_len = self.buffer.len(); - - if !self.done && len > buffer_len { + if len > buffer_len { let delta = len - buffer_len; - self.buffer.extend(self.it.by_ref().take(delta)); - self.done = self.buffer.len() < len; } } } +impl LazyBuffer +where + I: Iterator, + I::Item: Clone, +{ + pub fn get_at(&self, indices: &[usize]) -> Vec { + indices.iter().map(|i| self.buffer[*i].clone()).collect() + } + + pub fn get_array(&self, indices: [usize; K]) -> [I::Item; K] { + indices.map(|i| self.buffer[i].clone()) + } +} + impl Index for LazyBuffer where I: Iterator, I::Item: Sized, - Vec: Index + Vec: Index, { type Output = as Index>::Output; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ -#![warn(missing_docs)] -#![crate_name="itertools"] +#![warn(missing_docs, clippy::default_numeric_fallback)] +#![crate_name = "itertools"] #![cfg_attr(not(feature = "use_std"), no_std)] +#![doc(test(attr(deny(warnings), allow(deprecated, unstable_name_collisions))))] //! Extra iterator adaptors, functions and macros. //! @@ -8,6 +9,7 @@ //! the [`Itertools`] trait: //! //! ``` +//! # #[allow(unused_imports)] //! use itertools::Itertools; //! ``` //! @@ -29,6 +31,7 @@ //! //! for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { //! /* loop body */ +//! # let _ = elt; //! } //! ``` //! @@ -37,13 +40,16 @@ //! - `use_std` //! - Enabled by default. //! - Disable to compile itertools using `#![no_std]`. This disables -//! any items that depend on collections (like `group_by`, `unique`, +//! any item that depend on allocations (see the `use_alloc` feature) +//! and hash maps (like `unique`, `counts`, `into_grouping_map` and more). +//! - `use_alloc` +//! - Enabled by default. +//! - Enables any item that depend on allocations (like `chunk_by`, //! `kmerge`, `join` and many more). //! //! ## Rust Version //! -//! This version of itertools requires Rust 1.32 or later. -#![doc(html_root_url="https://docs.rs/itertools/0.8/")] +//! This version of itertools requires Rust 1.63.0 or later. #[cfg(not(feature = "use_std"))] extern crate core as std; @@ -52,28 +58,26 @@ extern crate alloc; #[cfg(feature = "use_alloc")] -use alloc::{ - string::String, - vec::Vec, -}; +use alloc::{collections::VecDeque, string::String, vec::Vec}; pub use either::Either; use core::borrow::Borrow; +use std::cmp::Ordering; #[cfg(feature = "use_std")] use std::collections::HashMap; -use std::iter::{IntoIterator, once}; -use std::cmp::Ordering; -use std::fmt; #[cfg(feature = "use_std")] use std::collections::HashSet; +use std::fmt; +#[cfg(feature = "use_alloc")] +use std::fmt::Write; #[cfg(feature = "use_std")] use std::hash::Hash; +use std::iter::{once, IntoIterator}; #[cfg(feature = "use_alloc")] -use std::fmt::Write; +type VecDequeIntoIter = alloc::collections::vec_deque::IntoIter; #[cfg(feature = "use_alloc")] type VecIntoIter = alloc::vec::IntoIter; -#[cfg(feature = "use_alloc")] use std::iter::FromIterator; #[macro_use] @@ -85,72 +89,56 @@ /// The concrete iterator types. pub mod structs { - pub use crate::adaptors::{ - Dedup, - DedupBy, - DedupWithCount, - DedupByWithCount, - Interleave, - InterleaveShortest, - FilterMapOk, - FilterOk, - Product, - PutBack, - Batching, - MapInto, - MapOk, - Merge, - MergeBy, - TakeWhileRef, - WhileSome, - Coalesce, - TupleCombinations, - Positions, - Update, - }; - #[allow(deprecated)] - pub use crate::adaptors::{MapResults, Step}; #[cfg(feature = "use_alloc")] pub use crate::adaptors::MultiProduct; + pub use crate::adaptors::{ + Batching, Coalesce, Dedup, DedupBy, DedupByWithCount, DedupWithCount, FilterMapOk, + FilterOk, Interleave, InterleaveShortest, MapInto, MapOk, Positions, Product, PutBack, + TakeWhileRef, TupleCombinations, Update, WhileSome, + }; #[cfg(feature = "use_alloc")] - pub use crate::combinations::Combinations; + pub use crate::combinations::{ArrayCombinations, Combinations}; #[cfg(feature = "use_alloc")] pub use crate::combinations_with_replacement::CombinationsWithReplacement; pub use crate::cons_tuples_impl::ConsTuples; + #[cfg(feature = "use_std")] + pub use crate::duplicates_impl::{Duplicates, DuplicatesBy}; pub use crate::exactly_one_err::ExactlyOneError; - pub use crate::format::{Format, FormatWith}; pub use crate::flatten_ok::FlattenOk; + pub use crate::format::{Format, FormatWith}; + #[allow(deprecated)] + #[cfg(feature = "use_alloc")] + pub use crate::groupbylazy::GroupBy; + #[cfg(feature = "use_alloc")] + pub use crate::groupbylazy::{Chunk, ChunkBy, Chunks, Group, Groups, IntoChunks}; #[cfg(feature = "use_std")] pub use crate::grouping_map::{GroupingMap, GroupingMapBy}; - #[cfg(feature = "use_alloc")] - pub use crate::groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; pub use crate::intersperse::{Intersperse, IntersperseWith}; #[cfg(feature = "use_alloc")] pub use crate::kmerge_impl::{KMerge, KMergeBy}; - pub use crate::merge_join::MergeJoinBy; + pub use crate::merge_join::{Merge, MergeBy, MergeJoinBy}; #[cfg(feature = "use_alloc")] pub use crate::multipeek_impl::MultiPeek; + pub use crate::pad_tail::PadUsing; #[cfg(feature = "use_alloc")] pub use crate::peek_nth::PeekNth; - pub use crate::pad_tail::PadUsing; pub use crate::peeking_take_while::PeekingTakeWhile; #[cfg(feature = "use_alloc")] pub use crate::permutations::Permutations; - pub use crate::process_results_impl::ProcessResults; #[cfg(feature = "use_alloc")] pub use crate::powerset::Powerset; + pub use crate::process_results_impl::ProcessResults; #[cfg(feature = "use_alloc")] pub use crate::put_back_n_impl::PutBackN; #[cfg(feature = "use_alloc")] pub use crate::rciter_impl::RcIter; pub use crate::repeatn::RepeatN; #[allow(deprecated)] - pub use crate::sources::{RepeatCall, Unfold, Iterate}; + pub use crate::sources::{Iterate, Unfold}; + pub use crate::take_while_inclusive::TakeWhileInclusive; #[cfg(feature = "use_alloc")] pub use crate::tee::Tee; - pub use crate::tuple_impl::{TupleBuffer, TupleWindows, CircularTupleWindows, Tuples}; - #[cfg(feature = "use_std")] - pub use crate::duplicates_impl::{Duplicates, DuplicatesBy}; + pub use crate::tuple_impl::{CircularTupleWindows, TupleBuffer, TupleWindows, Tuples}; #[cfg(feature = "use_std")] pub use crate::unique_impl::{Unique, UniqueBy}; pub use crate::with_position::WithPosition; @@ -161,25 +149,26 @@ /// Traits helpful for using certain `Itertools` methods in generic contexts. pub mod traits { + pub use crate::iter_index::IteratorIndex; pub use crate::tuple_impl::HomogeneousTuple; } -#[allow(deprecated)] -pub use crate::structs::*; pub use crate::concat_impl::concat; pub use crate::cons_tuples_impl::cons_tuples; pub use crate::diff::diff_with; pub use crate::diff::Diff; #[cfg(feature = "use_alloc")] -pub use crate::kmerge_impl::{kmerge_by}; +pub use crate::kmerge_impl::kmerge_by; pub use crate::minmax::MinMaxResult; pub use crate::peeking_take_while::PeekingNext; pub use crate::process_results_impl::process_results; pub use crate::repeatn::repeat_n; #[allow(deprecated)] -pub use crate::sources::{repeat_call, unfold, iterate}; -pub use crate::with_position::Position; +pub use crate::sources::{iterate, unfold}; +#[allow(deprecated)] +pub use crate::structs::*; pub use crate::unziptuple::{multiunzip, MultiUnzip}; +pub use crate::with_position::Position; pub use crate::ziptuple::multizip; mod adaptors; mod either_or_both; @@ -188,25 +177,28 @@ pub mod free; #[doc(inline)] pub use crate::free::*; -mod concat_impl; -mod cons_tuples_impl; #[cfg(feature = "use_alloc")] mod combinations; #[cfg(feature = "use_alloc")] mod combinations_with_replacement; -mod exactly_one_err; +mod concat_impl; +mod cons_tuples_impl; mod diff; -mod flatten_ok; #[cfg(feature = "use_std")] +mod duplicates_impl; +mod exactly_one_err; +#[cfg(feature = "use_alloc")] mod extrema_set; +mod flatten_ok; mod format; -#[cfg(feature = "use_std")] -mod grouping_map; #[cfg(feature = "use_alloc")] mod group_map; #[cfg(feature = "use_alloc")] mod groupbylazy; +#[cfg(feature = "use_std")] +mod grouping_map; mod intersperse; +mod iter_index; #[cfg(feature = "use_alloc")] mod k_smallest; #[cfg(feature = "use_alloc")] @@ -217,6 +209,7 @@ mod minmax; #[cfg(feature = "use_alloc")] mod multipeek_impl; +mod next_array; mod pad_tail; #[cfg(feature = "use_alloc")] mod peek_nth; @@ -233,12 +226,11 @@ mod repeatn; mod size_hint; mod sources; +mod take_while_inclusive; #[cfg(feature = "use_alloc")] mod tee; mod tuple_impl; #[cfg(feature = "use_std")] -mod duplicates_impl; -#[cfg(feature = "use_std")] mod unique_impl; mod unziptuple; mod with_position; @@ -260,6 +252,7 @@ /// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) /// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { /// // .. +/// # let _ = (i, j, k); /// } /// # } /// ``` @@ -270,13 +263,22 @@ (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( $crate::iproduct!(@flatten $crate::cons_tuples($crate::iproduct!($I, $J)), $($K,)*) ); - ($I:expr) => ( - $crate::__std_iter::IntoIterator::into_iter($I) + () => ( + $crate::__std_iter::once(()) ); - ($I:expr, $J:expr) => ( - $crate::Itertools::cartesian_product($crate::iproduct!($I), $crate::iproduct!($J)) + ($I:expr $(,)?) => ( + $crate::__std_iter::Iterator::map( + $crate::__std_iter::IntoIterator::into_iter($I), + |elt| (elt,) + ) ); - ($I:expr, $J:expr, $($K:expr),+) => ( + ($I:expr, $J:expr $(,)?) => ( + $crate::Itertools::cartesian_product( + $crate::__std_iter::IntoIterator::into_iter($I), + $crate::__std_iter::IntoIterator::into_iter($J), + ) + ); + ($I:expr, $J:expr, $($K:expr),+ $(,)?) => ( $crate::iproduct!(@flatten $crate::iproduct!($I, $J), $($K,)+) ); } @@ -336,19 +338,24 @@ // binary ($first:expr, $second:expr $(,)*) => { - $crate::izip!($first) - .zip($second) + $crate::__std_iter::Iterator::zip( + $crate::__std_iter::IntoIterator::into_iter($first), + $second, + ) }; // n-ary where n > 2 ( $first:expr $( , $rest:expr )* $(,)* ) => { - $crate::izip!($first) + { + let iter = $crate::__std_iter::IntoIterator::into_iter($first); $( - .zip($rest) + let iter = $crate::__std_iter::Iterator::zip(iter, $rest); )* - .map( + $crate::__std_iter::Iterator::map( + iter, $crate::izip!(@closure a => (a) $( , $rest )*) ) + } }; } @@ -373,16 +380,16 @@ /// /// Invocations of `chain!` with one argument expand to [`arg.into_iter()`](IntoIterator): /// ``` -/// use std::{ops::Range, slice}; +/// use std::ops::Range; /// use itertools::chain; -/// let _: as IntoIterator>::IntoIter = chain!((2..6),); // trailing comma optional! +/// let _: as IntoIterator>::IntoIter = chain!(2..6,); // trailing comma optional! /// let _: <&[_] as IntoIterator>::IntoIter = chain!(&[2, 3, 4]); /// ``` /// /// Invocations of `chain!` with multiple arguments [`.into_iter()`](IntoIterator) each /// argument, and then [`chain`] them together: /// ``` -/// use std::{iter::*, ops::Range, slice}; +/// use std::{iter::*, slice}; /// use itertools::{assert_equal, chain}; /// /// // e.g., this: @@ -399,16 +406,16 @@ /// ``` macro_rules! chain { () => { - core::iter::empty() + $crate::__std_iter::empty() }; ($first:expr $(, $rest:expr )* $(,)?) => { { - let iter = core::iter::IntoIterator::into_iter($first); + let iter = $crate::__std_iter::IntoIterator::into_iter($first); $( let iter = - core::iter::Iterator::chain( + $crate::__std_iter::Iterator::chain( iter, - core::iter::IntoIterator::into_iter($rest)); + $crate::__std_iter::IntoIterator::into_iter($rest)); )* iter } @@ -421,14 +428,14 @@ /// This trait defines a number of methods. They are divided into two groups: /// /// * *Adaptors* take an iterator and parameter as input, and return -/// a new iterator value. These are listed first in the trait. An example -/// of an adaptor is [`.interleave()`](Itertools::interleave) +/// a new iterator value. These are listed first in the trait. An example +/// of an adaptor is [`.interleave()`](Itertools::interleave) /// /// * *Regular methods* are those that don't return iterators and instead -/// return a regular value of some other kind. -/// [`.next_tuple()`](Itertools::next_tuple) is an example and the first regular -/// method in the list. -pub trait Itertools : Iterator { +/// return a regular value of some other kind. +/// [`.next_tuple()`](Itertools::next_tuple) is an example and the first regular +/// method in the list. +pub trait Itertools: Iterator { // adaptors /// Alternate elements from two iterators until both have run out. @@ -444,8 +451,9 @@ /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); /// ``` fn interleave(self, other: J) -> Interleave - where J: IntoIterator, - Self: Sized + where + J: IntoIterator, + Self: Sized, { interleave(self, other) } @@ -462,8 +470,9 @@ /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); /// ``` fn interleave_shortest(self, other: J) -> InterleaveShortest - where J: IntoIterator, - Self: Sized + where + J: IntoIterator, + Self: Sized, { adaptors::interleave_shortest(self, other.into_iter()) } @@ -481,8 +490,9 @@ /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); /// ``` fn intersperse(self, element: Self::Item) -> Intersperse - where Self: Sized, - Self::Item: Clone + where + Self: Sized, + Self::Item: Clone, { intersperse::intersperse(self, element) } @@ -502,12 +512,63 @@ /// assert_eq!(i, 8); /// ``` fn intersperse_with(self, element: F) -> IntersperseWith - where Self: Sized, - F: FnMut() -> Self::Item + where + Self: Sized, + F: FnMut() -> Self::Item, { intersperse::intersperse_with(self, element) } + /// Returns an iterator over a subsection of the iterator. + /// + /// Works similarly to [`slice::get`](https://doc.rust-lang.org/std/primitive.slice.html#method.get). + /// + /// **Panics** for ranges `..=usize::MAX` and `0..=usize::MAX`. + /// + /// It's a generalisation of [`Iterator::take`] and [`Iterator::skip`], + /// and uses these under the hood. + /// Therefore, the resulting iterator is: + /// - [`ExactSizeIterator`] if the adapted iterator is [`ExactSizeIterator`]. + /// - [`DoubleEndedIterator`] if the adapted iterator is [`DoubleEndedIterator`] and [`ExactSizeIterator`]. + /// + /// # Unspecified Behavior + /// The result of indexing with an exhausted [`core::ops::RangeInclusive`] is unspecified. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let vec = vec![3, 1, 4, 1, 5]; + /// + /// let mut range: Vec<_> = + /// vec.iter().get(1..=3).copied().collect(); + /// assert_eq!(&range, &[1, 4, 1]); + /// + /// // It works with other types of ranges, too + /// range = vec.iter().get(..2).copied().collect(); + /// assert_eq!(&range, &[3, 1]); + /// + /// range = vec.iter().get(0..1).copied().collect(); + /// assert_eq!(&range, &[3]); + /// + /// range = vec.iter().get(2..).copied().collect(); + /// assert_eq!(&range, &[4, 1, 5]); + /// + /// range = vec.iter().get(..=2).copied().collect(); + /// assert_eq!(&range, &[3, 1, 4]); + /// + /// range = vec.iter().get(..).copied().collect(); + /// assert_eq!(range, vec); + /// ``` + fn get(self, index: R) -> R::Output + where + Self: Sized, + R: traits::IteratorIndex, + { + iter_index::get(self, index) + } + /// Create an iterator which iterates over both this and the specified /// iterator simultaneously, yielding pairs of two optional elements. /// @@ -536,8 +597,9 @@ /// ``` #[inline] fn zip_longest(self, other: J) -> ZipLongest - where J: IntoIterator, - Self: Sized + where + J: IntoIterator, + Self: Sized, { zip_longest::zip_longest(self, other.into_iter()) } @@ -549,8 +611,9 @@ /// lengths. #[inline] fn zip_eq(self, other: J) -> ZipEq - where J: IntoIterator, - Self: Sized + where + J: IntoIterator, + Self: Sized, { zip_eq(self, other) } @@ -579,8 +642,9 @@ /// ``` /// fn batching(self, f: F) -> Batching - where F: FnMut(&mut Self) -> Option, - Self: Sized + where + F: FnMut(&mut Self) -> Option, + Self: Sized, { adaptors::batching(self, f) } @@ -589,10 +653,10 @@ /// Consecutive elements that map to the same key (“runs”), are assigned /// to the same group. /// - /// `GroupBy` is the storage for the lazy grouping operation. + /// `ChunkBy` is the storage for the lazy grouping operation. /// /// If the groups are consumed in order, or if each group's iterator is - /// dropped without keeping it around, then `GroupBy` uses no + /// dropped without keeping it around, then `ChunkBy` uses no /// allocations. It needs allocations only if several group iterators /// are alive at the same time. /// @@ -607,34 +671,47 @@ /// ``` /// use itertools::Itertools; /// - /// // group data into runs of larger than zero or not. + /// // chunk data into runs of larger than zero or not. /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; - /// // groups: |---->|------>|--------->| + /// // chunks: |---->|------>|--------->| /// - /// // Note: The `&` is significant here, `GroupBy` is iterable + /// // Note: The `&` is significant here, `ChunkBy` is iterable /// // only by reference. You can also call `.into_iter()` explicitly. /// let mut data_grouped = Vec::new(); - /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { - /// data_grouped.push((key, group.collect())); + /// for (key, chunk) in &data.into_iter().chunk_by(|elt| *elt >= 0) { + /// data_grouped.push((key, chunk.collect())); /// } /// assert_eq!(data_grouped, vec![(true, vec![1, 3]), (false, vec![-2, -2]), (true, vec![1, 0, 1, 2])]); /// ``` #[cfg(feature = "use_alloc")] - fn group_by(self, key: F) -> GroupBy - where Self: Sized, - F: FnMut(&Self::Item) -> K, - K: PartialEq, + fn chunk_by(self, key: F) -> ChunkBy + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: PartialEq, { groupbylazy::new(self, key) } + /// See [`.chunk_by()`](Itertools::chunk_by). + #[deprecated(note = "Use .chunk_by() instead", since = "0.13.0")] + #[cfg(feature = "use_alloc")] + fn group_by(self, key: F) -> ChunkBy + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: PartialEq, + { + self.chunk_by(key) + } + /// Return an *iterable* that can chunk the iterator. /// /// Yield subiterators (chunks) that each yield a fixed number elements, /// determined by `size`. The last chunk will be shorter if there aren't /// enough elements. /// - /// `IntoChunks` is based on `GroupBy`: it is iterable (implements + /// `IntoChunks` is based on `ChunkBy`: it is iterable (implements /// `IntoIterator`, **not** `Iterator`), and it only buffers if several /// chunk iterators are alive at the same time. /// @@ -657,7 +734,8 @@ /// ``` #[cfg(feature = "use_alloc")] fn chunks(self, size: usize) -> IntoChunks - where Self: Sized, + where + Self: Sized, { assert!(size != 0); groupbylazy::new_chunks(self, size) @@ -697,9 +775,10 @@ /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); /// ``` fn tuple_windows(self) -> TupleWindows - where Self: Sized + Iterator, - T: traits::HomogeneousTuple, - T::Item: Clone + where + Self: Sized + Iterator, + T: traits::HomogeneousTuple, + T::Item: Clone, { tuple_impl::tuple_windows(self) } @@ -732,9 +811,10 @@ /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4), (3, 4, 1), (4, 1, 2)]); /// ``` fn circular_tuple_windows(self) -> CircularTupleWindows - where Self: Sized + Clone + Iterator + ExactSizeIterator, - T: tuple_impl::TupleCollect + Clone, - T::Item: Clone + where + Self: Sized + Clone + Iterator + ExactSizeIterator, + T: tuple_impl::TupleCollect + Clone, + T::Item: Clone, { tuple_impl::circular_tuple_windows(self) } @@ -770,8 +850,9 @@ /// /// See also [`Tuples::into_buffer`]. fn tuples(self) -> Tuples - where Self: Sized + Iterator, - T: traits::HomogeneousTuple + where + Self: Sized + Iterator, + T: traits::HomogeneousTuple, { tuple_impl::tuples(self) } @@ -795,36 +876,13 @@ /// ``` #[cfg(feature = "use_alloc")] fn tee(self) -> (Tee, Tee) - where Self: Sized, - Self::Item: Clone + where + Self: Sized, + Self::Item: Clone, { tee::new(self) } - /// Return an iterator adaptor that steps `n` elements in the base iterator - /// for each iteration. - /// - /// The iterator steps by yielding the next element from the base iterator, - /// then skipping forward `n - 1` elements. - /// - /// Iterator element type is `Self::Item`. - /// - /// **Panics** if the step is 0. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..8).step(3); - /// itertools::assert_equal(it, vec![0, 3, 6]); - /// ``` - #[deprecated(note="Use std .step_by() instead", since="0.8.0")] - #[allow(deprecated)] - fn step(self, n: usize) -> Step - where Self: Sized - { - adaptors::step(self, n) - } - /// Convert each item of the iterator using the [`Into`] trait. /// /// ```rust @@ -833,21 +891,13 @@ /// (1i32..42i32).map_into::().collect_vec(); /// ``` fn map_into(self) -> MapInto - where Self: Sized, - Self::Item: Into, + where + Self: Sized, + Self::Item: Into, { adaptors::map_into(self) } - /// See [`.map_ok()`](Itertools::map_ok). - #[deprecated(note="Use .map_ok() instead", since="0.10.0")] - fn map_results(self, f: F) -> MapOk - where Self: Iterator> + Sized, - F: FnMut(T) -> U, - { - self.map_ok(f) - } - /// Return an iterator adaptor that applies the provided closure /// to every `Result::Ok` value. `Result::Err` values are /// unchanged. @@ -860,8 +910,9 @@ /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); /// ``` fn map_ok(self, f: F) -> MapOk - where Self: Iterator> + Sized, - F: FnMut(T) -> U, + where + Self: Iterator> + Sized, + F: FnMut(T) -> U, { adaptors::map_ok(self, f) } @@ -878,8 +929,9 @@ /// itertools::assert_equal(it, vec![Ok(22), Err(false)]); /// ``` fn filter_ok(self, f: F) -> FilterOk - where Self: Iterator> + Sized, - F: FnMut(&T) -> bool, + where + Self: Iterator> + Sized, + F: FnMut(&T) -> bool, { adaptors::filter_ok(self, f) } @@ -896,15 +948,16 @@ /// itertools::assert_equal(it, vec![Ok(44), Err(false)]); /// ``` fn filter_map_ok(self, f: F) -> FilterMapOk - where Self: Iterator> + Sized, - F: FnMut(T) -> Option, + where + Self: Iterator> + Sized, + F: FnMut(T) -> Option, { adaptors::filter_map_ok(self, f) } /// Return an iterator adaptor that flattens every `Result::Ok` value into /// a series of `Result::Ok` values. `Result::Err` values are unchanged. - /// + /// /// This is useful when you have some common error type for your crate and /// need to propagate it upwards, but the `Result::Ok` case needs to be flattened. /// @@ -914,18 +967,57 @@ /// let input = vec![Ok(0..2), Err(false), Ok(2..4)]; /// let it = input.iter().cloned().flatten_ok(); /// itertools::assert_equal(it.clone(), vec![Ok(0), Ok(1), Err(false), Ok(2), Ok(3)]); - /// + /// /// // This can also be used to propagate errors when collecting. /// let output_result: Result, bool> = it.collect(); /// assert_eq!(output_result, Err(false)); /// ``` fn flatten_ok(self) -> FlattenOk - where Self: Iterator> + Sized, - T: IntoIterator + where + Self: Iterator> + Sized, + T: IntoIterator, { flatten_ok::flatten_ok(self) } + /// “Lift” a function of the values of the current iterator so as to process + /// an iterator of `Result` values instead. + /// + /// `processor` is a closure that receives an adapted version of the iterator + /// as the only argument — the adapted iterator produces elements of type `T`, + /// as long as the original iterator produces `Ok` values. + /// + /// If the original iterable produces an error at any point, the adapted + /// iterator ends and it will return the error iself. + /// + /// Otherwise, the return value from the closure is returned wrapped + /// inside `Ok`. + /// + /// # Example + /// + /// ``` + /// use itertools::Itertools; + /// + /// type Item = Result; + /// + /// let first_values: Vec = vec![Ok(1), Ok(0), Ok(3)]; + /// let second_values: Vec = vec![Ok(2), Ok(1), Err("overflow")]; + /// + /// // “Lift” the iterator .max() method to work on the Ok-values. + /// let first_max = first_values.into_iter().process_results(|iter| iter.max().unwrap_or(0)); + /// let second_max = second_values.into_iter().process_results(|iter| iter.max().unwrap_or(0)); + /// + /// assert_eq!(first_max, Ok(3)); + /// assert!(second_max.is_err()); + /// ``` + fn process_results(self, processor: F) -> Result + where + Self: Iterator> + Sized, + F: FnOnce(ProcessResults) -> R, + { + process_results(self, processor) + } + /// Return an iterator adaptor that merges the two base iterators in /// ascending order. If both base iterators are sorted (ascending), the /// result is sorted. @@ -935,15 +1027,16 @@ /// ``` /// use itertools::Itertools; /// - /// let a = (0..11).step(3); - /// let b = (0..11).step(5); + /// let a = (0..11).step_by(3); + /// let b = (0..11).step_by(5); /// let it = a.merge(b); /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); /// ``` fn merge(self, other: J) -> Merge - where Self: Sized, - Self::Item: PartialOrd, - J: IntoIterator + where + Self: Sized, + Self::Item: PartialOrd, + J: IntoIterator, { merge(self, other) } @@ -963,19 +1056,22 @@ /// let it = a.merge_by(b, |x, y| x.1 <= y.1); /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); /// ``` - fn merge_by(self, other: J, is_first: F) -> MergeBy - where Self: Sized, - J: IntoIterator, - F: FnMut(&Self::Item, &Self::Item) -> bool + where + Self: Sized, + J: IntoIterator, + F: FnMut(&Self::Item, &Self::Item) -> bool, { - adaptors::merge_by_new(self, other.into_iter(), is_first) + merge_join::merge_by_new(self, other, is_first) } /// Create an iterator that merges items from both this and the specified /// iterator in ascending order. /// - /// It chooses whether to pair elements based on the `Ordering` returned by the + /// The function can either return an `Ordering` variant or a boolean. + /// + /// If `cmp_fn` returns `Ordering`, + /// it chooses whether to pair elements based on the `Ordering` returned by the /// specified compare function. At any point, inspecting the tip of the /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type /// `J::Item` respectively, the resulting iterator will: @@ -991,19 +1087,50 @@ /// use itertools::Itertools; /// use itertools::EitherOrBoth::{Left, Right, Both}; /// - /// let multiples_of_2 = (0..10).step(2); - /// let multiples_of_3 = (0..10).step(3); + /// let a = vec![0, 2, 4, 6, 1].into_iter(); + /// let b = (0..10).step_by(3); + /// + /// itertools::assert_equal( + /// // This performs a diff in the style of the Unix command comm(1), + /// // generalized to arbitrary types rather than text. + /// a.merge_join_by(b, Ord::cmp), + /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(1), Right(9)] + /// ); + /// ``` + /// + /// If `cmp_fn` returns `bool`, + /// it chooses whether to pair elements based on the boolean returned by the + /// specified function. At any point, inspecting the tip of the + /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type + /// `J::Item` respectively, the resulting iterator will: + /// + /// - Emit `Either::Left(i)` when `true`, + /// and remove `i` from its source iterator + /// - Emit `Either::Right(j)` when `false`, + /// and remove `j` from its source iterator + /// + /// It is similar to the `Ordering` case if the first argument is considered + /// "less" than the second argument. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::Either::{Left, Right}; + /// + /// let a = vec![0, 2, 4, 6, 1].into_iter(); + /// let b = (0..10).step_by(3); /// /// itertools::assert_equal( - /// multiples_of_2.merge_join_by(multiples_of_3, |i, j| i.cmp(j)), - /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(8), Right(9)] + /// a.merge_join_by(b, |i, j| i <= j), + /// vec![Left(0), Right(0), Left(2), Right(3), Left(4), Left(6), Left(1), Right(6), Right(9)] /// ); /// ``` #[inline] - fn merge_join_by(self, other: J, cmp_fn: F) -> MergeJoinBy - where J: IntoIterator, - F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, - Self: Sized + #[doc(alias = "comm")] + fn merge_join_by(self, other: J, cmp_fn: F) -> MergeJoinBy + where + J: IntoIterator, + F: FnMut(&Self::Item, &J::Item) -> T, + Self: Sized, { merge_join_by(self, other, cmp_fn) } @@ -1018,17 +1145,18 @@ /// ``` /// use itertools::Itertools; /// - /// let a = (0..6).step(3); - /// let b = (1..6).step(3); - /// let c = (2..6).step(3); + /// let a = (0..6).step_by(3); + /// let b = (1..6).step_by(3); + /// let c = (2..6).step_by(3); /// let it = vec![a, b, c].into_iter().kmerge(); /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); /// ``` #[cfg(feature = "use_alloc")] fn kmerge(self) -> KMerge<::IntoIter> - where Self: Sized, - Self::Item: IntoIterator, - ::Item: PartialOrd, + where + Self: Sized, + Self::Item: IntoIterator, + ::Item: PartialOrd, { kmerge(self) } @@ -1054,12 +1182,11 @@ /// assert_eq!(it.last(), Some(-7.)); /// ``` #[cfg(feature = "use_alloc")] - fn kmerge_by(self, first: F) - -> KMergeBy<::IntoIter, F> - where Self: Sized, - Self::Item: IntoIterator, - F: FnMut(&::Item, - &::Item) -> bool + fn kmerge_by(self, first: F) -> KMergeBy<::IntoIter, F> + where + Self: Sized, + Self::Item: IntoIterator, + F: FnMut(&::Item, &::Item) -> bool, { kmerge_by(self, first) } @@ -1076,10 +1203,11 @@ /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); /// ``` fn cartesian_product(self, other: J) -> Product - where Self: Sized, - Self::Item: Clone, - J: IntoIterator, - J::IntoIter: Clone + where + Self: Sized, + Self::Item: Clone, + J: IntoIterator, + J::IntoIter: Clone, { adaptors::cartesian_product(self, other.into_iter()) } @@ -1091,10 +1219,11 @@ /// the product of iterators yielding multiple types, use the /// [`iproduct`] macro instead. /// - /// /// The iterator element type is `Vec`, where `T` is the iterator element /// of the subiterators. /// + /// Note that the iterator is fused. + /// /// ``` /// use itertools::Itertools; /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) @@ -1109,12 +1238,23 @@ /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); /// assert_eq!(multi_prod.next(), None); /// ``` + /// + /// If the adapted iterator is empty, the result is an iterator yielding a single empty vector. + /// This is known as the [nullary cartesian product](https://en.wikipedia.org/wiki/Empty_product#Nullary_Cartesian_product). + /// + /// ``` + /// use itertools::Itertools; + /// let mut nullary_cartesian_product = (0..0).map(|i| (i * 2)..(i * 2 + 2)).multi_cartesian_product(); + /// assert_eq!(nullary_cartesian_product.next(), Some(vec![])); + /// assert_eq!(nullary_cartesian_product.next(), None); + /// ``` #[cfg(feature = "use_alloc")] fn multi_cartesian_product(self) -> MultiProduct<::IntoIter> - where Self: Sized, - Self::Item: IntoIterator, - ::IntoIter: Clone, - ::Item: Clone + where + Self: Sized, + Self::Item: IntoIterator, + ::IntoIter: Clone, + ::Item: Clone, { adaptors::multi_cartesian_product(self) } @@ -1148,9 +1288,9 @@ /// vec![-6., 4., -1.]); /// ``` fn coalesce(self, f: F) -> Coalesce - where Self: Sized, - F: FnMut(Self::Item, Self::Item) - -> Result + where + Self: Sized, + F: FnMut(Self::Item, Self::Item) -> Result, { adaptors::coalesce(self, f) } @@ -1170,8 +1310,9 @@ /// vec![1., 2., 3., 2.]); /// ``` fn dedup(self) -> Dedup - where Self: Sized, - Self::Item: PartialEq, + where + Self: Sized, + Self::Item: PartialEq, { adaptors::dedup(self) } @@ -1192,8 +1333,9 @@ /// vec![(0, 1.), (0, 2.), (0, 3.), (1, 2.)]); /// ``` fn dedup_by(self, cmp: Cmp) -> DedupBy - where Self: Sized, - Cmp: FnMut(&Self::Item, &Self::Item)->bool, + where + Self: Sized, + Cmp: FnMut(&Self::Item, &Self::Item) -> bool, { adaptors::dedup_by(self, cmp) } @@ -1260,8 +1402,9 @@ /// ``` #[cfg(feature = "use_std")] fn duplicates(self) -> Duplicates - where Self: Sized, - Self::Item: Eq + Hash + where + Self: Sized, + Self::Item: Eq + Hash, { duplicates_impl::duplicates(self) } @@ -1285,9 +1428,10 @@ /// ``` #[cfg(feature = "use_std")] fn duplicates_by(self, f: F) -> DuplicatesBy - where Self: Sized, - V: Eq + Hash, - F: FnMut(&Self::Item) -> V + where + Self: Sized, + V: Eq + Hash, + F: FnMut(&Self::Item) -> V, { duplicates_impl::duplicates_by(self, f) } @@ -1312,8 +1456,9 @@ /// ``` #[cfg(feature = "use_std")] fn unique(self) -> Unique - where Self: Sized, - Self::Item: Clone + Eq + Hash + where + Self: Sized, + Self::Item: Clone + Eq + Hash, { unique_impl::unique(self) } @@ -1338,9 +1483,10 @@ /// ``` #[cfg(feature = "use_std")] fn unique_by(self, f: F) -> UniqueBy - where Self: Sized, - V: Eq + Hash, - F: FnMut(&Self::Item) -> V + where + Self: Sized, + V: Eq + Hash, + F: FnMut(&Self::Item) -> V, { unique_impl::unique_by(self, f) } @@ -1358,8 +1504,9 @@ /// See also [`.take_while_ref()`](Itertools::take_while_ref) /// which is a similar adaptor. fn peeking_take_while(&mut self, accept: F) -> PeekingTakeWhile - where Self: Sized + PeekingNext, - F: FnMut(&Self::Item) -> bool, + where + Self: Sized + PeekingNext, + F: FnMut(&Self::Item) -> bool, { peeking_take_while::peeking_take_while(self, accept) } @@ -1383,12 +1530,82 @@ /// /// ``` fn take_while_ref(&mut self, accept: F) -> TakeWhileRef - where Self: Clone, - F: FnMut(&Self::Item) -> bool + where + Self: Clone, + F: FnMut(&Self::Item) -> bool, { adaptors::take_while_ref(self, accept) } + /// Returns an iterator adaptor that consumes elements while the given + /// predicate is `true`, *including* the element for which the predicate + /// first returned `false`. + /// + /// The [`.take_while()`][std::iter::Iterator::take_while] adaptor is useful + /// when you want items satisfying a predicate, but to know when to stop + /// taking elements, we have to consume that first element that doesn't + /// satisfy the predicate. This adaptor includes that element where + /// [`.take_while()`][std::iter::Iterator::take_while] would drop it. + /// + /// The [`.take_while_ref()`][crate::Itertools::take_while_ref] adaptor + /// serves a similar purpose, but this adaptor doesn't require [`Clone`]ing + /// the underlying elements. + /// + /// ```rust + /// # use itertools::Itertools; + /// let items = vec![1, 2, 3, 4, 5]; + /// let filtered: Vec<_> = items + /// .into_iter() + /// .take_while_inclusive(|&n| n % 3 != 0) + /// .collect(); + /// + /// assert_eq!(filtered, vec![1, 2, 3]); + /// ``` + /// + /// ```rust + /// # use itertools::Itertools; + /// let items = vec![1, 2, 3, 4, 5]; + /// + /// let take_while_inclusive_result: Vec<_> = items + /// .iter() + /// .copied() + /// .take_while_inclusive(|&n| n % 3 != 0) + /// .collect(); + /// let take_while_result: Vec<_> = items + /// .into_iter() + /// .take_while(|&n| n % 3 != 0) + /// .collect(); + /// + /// assert_eq!(take_while_inclusive_result, vec![1, 2, 3]); + /// assert_eq!(take_while_result, vec![1, 2]); + /// // both iterators have the same items remaining at this point---the 3 + /// // is lost from the `take_while` vec + /// ``` + /// + /// ```rust + /// # use itertools::Itertools; + /// #[derive(Debug, PartialEq)] + /// struct NoCloneImpl(i32); + /// + /// let non_clonable_items: Vec<_> = vec![1, 2, 3, 4, 5] + /// .into_iter() + /// .map(NoCloneImpl) + /// .collect(); + /// let filtered: Vec<_> = non_clonable_items + /// .into_iter() + /// .take_while_inclusive(|n| n.0 % 3 != 0) + /// .collect(); + /// let expected: Vec<_> = vec![1, 2, 3].into_iter().map(NoCloneImpl).collect(); + /// assert_eq!(filtered, expected); + #[doc(alias = "take_until")] + fn take_while_inclusive(self, accept: F) -> TakeWhileInclusive + where + Self: Sized, + F: FnMut(&Self::Item) -> bool, + { + take_while_inclusive::TakeWhileInclusive::new(self, accept) + } + /// Return an iterator adaptor that filters `Option` iterator elements /// and produces `A`. Stops on the first `None` encountered. /// @@ -1404,7 +1621,8 @@ /// /// ``` fn while_some(self) -> WhileSome - where Self: Sized + Iterator> + where + Self: Sized + Iterator>, { adaptors::while_some(self) } @@ -1415,6 +1633,11 @@ /// Iterator element can be any homogeneous tuple of type `Self::Item` with /// size up to 12. /// + /// # Guarantees + /// + /// If the adapted iterator is deterministic, + /// this iterator adapter yields items in a reliable order. + /// /// ``` /// use itertools::Itertools; /// @@ -1443,19 +1666,72 @@ /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); /// ``` fn tuple_combinations(self) -> TupleCombinations - where Self: Sized + Clone, - Self::Item: Clone, - T: adaptors::HasCombination, + where + Self: Sized + Clone, + Self::Item: Clone, + T: adaptors::HasCombination, { adaptors::tuple_combinations(self) } + /// Return an iterator adaptor that iterates over the combinations of the + /// elements from an iterator. + /// + /// Iterator element type is [Self::Item; K]. The iterator produces a new + /// array per iteration, and clones the iterator elements. + /// + /// # Guarantees + /// + /// If the adapted iterator is deterministic, + /// this iterator adapter yields items in a reliable order. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut v = Vec::new(); + /// for [a, b] in (1..5).array_combinations() { + /// v.push([a, b]); + /// } + /// assert_eq!(v, vec![[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]); + /// + /// let mut it = (1..5).array_combinations(); + /// assert_eq!(Some([1, 2, 3]), it.next()); + /// assert_eq!(Some([1, 2, 4]), it.next()); + /// assert_eq!(Some([1, 3, 4]), it.next()); + /// assert_eq!(Some([2, 3, 4]), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).array_combinations::<3>(); + /// itertools::assert_equal(it, vec![[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]); + /// + /// // you can also specify the complete type + /// use itertools::ArrayCombinations; + /// use std::ops::Range; + /// + /// let it: ArrayCombinations, 3> = (1..5).array_combinations(); + /// itertools::assert_equal(it, vec![[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]); + /// ``` + #[cfg(feature = "use_alloc")] + fn array_combinations(self) -> ArrayCombinations + where + Self: Sized + Clone, + Self::Item: Clone, + { + combinations::array_combinations(self) + } + /// Return an iterator adaptor that iterates over the `k`-length combinations of /// the elements from an iterator. /// - /// Iterator element type is `Vec`. The iterator produces a new Vec per iteration, + /// Iterator element type is `Vec`. The iterator produces a new `Vec` per iteration, /// and clones the iterator elements. /// + /// # Guarantees + /// + /// If the adapted iterator is deterministic, + /// this iterator adapter yields items in a reliable order. + /// /// ``` /// use itertools::Itertools; /// @@ -1481,8 +1757,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn combinations(self, k: usize) -> Combinations - where Self: Sized, - Self::Item: Clone + where + Self: Sized, + Self::Item: Clone, { combinations::combinations(self, k) } @@ -1490,7 +1767,7 @@ /// Return an iterator that iterates over the `k`-length combinations of /// the elements from an iterator, with replacement. /// - /// Iterator element type is `Vec`. The iterator produces a new Vec per iteration, + /// Iterator element type is `Vec`. The iterator produces a new `Vec` per iteration, /// and clones the iterator elements. /// /// ``` @@ -1519,11 +1796,14 @@ /// elements from an iterator. /// /// Iterator element type is `Vec` with length `k`. The iterator - /// produces a new Vec per iteration, and clones the iterator elements. + /// produces a new `Vec` per iteration, and clones the iterator elements. /// /// If `k` is greater than the length of the input iterator, the resultant /// iterator adaptor will be empty. /// + /// If you are looking for permutations with replacements, + /// use `repeat_n(iter, k).multi_cartesian_product()` instead. + /// /// ``` /// use itertools::Itertools; /// @@ -1554,8 +1834,9 @@ /// re-iterated if the permutations adaptor is completed and re-iterated. #[cfg(feature = "use_alloc")] fn permutations(self, k: usize) -> Permutations - where Self: Sized, - Self::Item: Clone + where + Self: Sized, + Self::Item: Clone, { permutations::permutations(self, k) } @@ -1590,8 +1871,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn powerset(self) -> Powerset - where Self: Sized, - Self::Item: Clone, + where + Self: Sized, + Self::Item: Clone, { powerset::powerset(self) } @@ -1614,33 +1896,35 @@ /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); /// ``` fn pad_using(self, min: usize, f: F) -> PadUsing - where Self: Sized, - F: FnMut(usize) -> Self::Item + where + Self: Sized, + F: FnMut(usize) -> Self::Item, { pad_tail::pad_using(self, min, f) } - /// Return an iterator adaptor that wraps each element in a `Position` to + /// Return an iterator adaptor that combines each element with a `Position` to /// ease special-case handling of the first or last elements. /// /// Iterator element type is - /// [`Position`](Position) + /// [`(Position, Self::Item)`](Position) /// /// ``` /// use itertools::{Itertools, Position}; /// /// let it = (0..4).with_position(); /// itertools::assert_equal(it, - /// vec![Position::First(0), - /// Position::Middle(1), - /// Position::Middle(2), - /// Position::Last(3)]); + /// vec![(Position::First, 0), + /// (Position::Middle, 1), + /// (Position::Middle, 2), + /// (Position::Last, 3)]); /// /// let it = (0..1).with_position(); - /// itertools::assert_equal(it, vec![Position::Only(0)]); + /// itertools::assert_equal(it, vec![(Position::Only, 0)]); /// ``` fn with_position(self) -> WithPosition - where Self: Sized, + where + Self: Sized, { with_position::with_position(self) } @@ -1648,7 +1932,7 @@ /// Return an iterator adaptor that yields the indices of all elements /// satisfying a predicate, counted from the start of the iterator. /// - /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. + /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(*v)).map(|(i, _)| i)`. /// /// ``` /// use itertools::Itertools; @@ -1659,8 +1943,9 @@ /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); /// ``` fn positions

(self, predicate: P) -> Positions - where Self: Sized, - P: FnMut(Self::Item) -> bool, + where + Self: Sized, + P: FnMut(Self::Item) -> bool, { adaptors::positions(self, predicate) } @@ -1672,17 +1957,62 @@ /// use itertools::Itertools; /// /// let input = vec![vec![1], vec![3, 2, 1]]; - /// let it = input.into_iter().update(|mut v| v.push(0)); + /// let it = input.into_iter().update(|v| v.push(0)); /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); /// ``` fn update(self, updater: F) -> Update - where Self: Sized, - F: FnMut(&mut Self::Item), + where + Self: Sized, + F: FnMut(&mut Self::Item), { adaptors::update(self, updater) } // non-adaptor methods + /// Advances the iterator and returns the next items grouped in an array of + /// a specific size. + /// + /// If there are enough elements to be grouped in an array, then the array + /// is returned inside `Some`, otherwise `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = 1..5; + /// + /// assert_eq!(Some([1, 2]), iter.next_array()); + /// ``` + fn next_array(&mut self) -> Option<[Self::Item; N]> + where + Self: Sized, + { + next_array::next_array(self) + } + + /// Collects all items from the iterator into an array of a specific size. + /// + /// If the number of elements inside the iterator is **exactly** equal to + /// the array size, then the array is returned inside `Some`, otherwise + /// `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let iter = 1..3; + /// + /// if let Some([x, y]) = iter.collect_array() { + /// assert_eq!([x, y], [1, 2]) + /// } else { + /// panic!("Expected two elements") + /// } + /// ``` + fn collect_array(mut self) -> Option<[Self::Item; N]> + where + Self: Sized, + { + self.next_array().filter(|_| self.next().is_none()) + } + /// Advances the iterator and returns the next items grouped in a tuple of /// a specific size (up to 12). /// @@ -1697,8 +2027,9 @@ /// assert_eq!(Some((1, 2)), iter.next_tuple()); /// ``` fn next_tuple(&mut self) -> Option - where Self: Sized + Iterator, - T: traits::HomogeneousTuple + where + Self: Sized + Iterator, + T: traits::HomogeneousTuple, { T::collect_from_iter_no_buf(self) } @@ -1722,19 +2053,19 @@ /// } /// ``` fn collect_tuple(mut self) -> Option - where Self: Sized + Iterator, - T: traits::HomogeneousTuple + where + Self: Sized + Iterator, + T: traits::HomogeneousTuple, { match self.next_tuple() { elt @ Some(_) => match self.next() { Some(_) => None, None => elt, }, - _ => None + _ => None, } } - /// Find the position and value of the first element satisfying a predicate. /// /// The iterator is not advanced past the first element found. @@ -1746,14 +2077,10 @@ /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); /// ``` fn find_position

(&mut self, mut pred: P) -> Option<(usize, Self::Item)> - where P: FnMut(&Self::Item) -> bool + where + P: FnMut(&Self::Item) -> bool, { - for (index, elt) in self.enumerate() { - if pred(&elt) { - return Some((index, elt)); - } - } - None + self.enumerate().find(|(_, elt)| pred(elt)) } /// Find the value of the first element satisfying a predicate or return the last element, if any. /// @@ -1766,14 +2093,31 @@ /// assert_eq!(numbers.iter().find_or_last(|&&x| x > 5), Some(&4)); /// assert_eq!(numbers.iter().find_or_last(|&&x| x > 2), Some(&3)); /// assert_eq!(std::iter::empty::().find_or_last(|&x| x > 5), None); + /// + /// // An iterator of Results can return the first Ok or the last Err: + /// let input = vec![Err(()), Ok(11), Err(()), Ok(22)]; + /// assert_eq!(input.into_iter().find_or_last(Result::is_ok), Some(Ok(11))); + /// + /// let input: Vec> = vec![Err(11), Err(22)]; + /// assert_eq!(input.into_iter().find_or_last(Result::is_ok), Some(Err(22))); + /// + /// assert_eq!(std::iter::empty::>().find_or_last(Result::is_ok), None); /// ``` fn find_or_last

(mut self, mut predicate: P) -> Option - where Self: Sized, - P: FnMut(&Self::Item) -> bool, + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, { let mut prev = None; - self.find_map(|x| if predicate(&x) { Some(x) } else { prev = Some(x); None }) - .or(prev) + self.find_map(|x| { + if predicate(&x) { + Some(x) + } else { + prev = Some(x); + None + } + }) + .or(prev) } /// Find the value of the first element satisfying a predicate or return the first element, if any. /// @@ -1786,10 +2130,20 @@ /// assert_eq!(numbers.iter().find_or_first(|&&x| x > 5), Some(&1)); /// assert_eq!(numbers.iter().find_or_first(|&&x| x > 2), Some(&3)); /// assert_eq!(std::iter::empty::().find_or_first(|&x| x > 5), None); + /// + /// // An iterator of Results can return the first Ok or the first Err: + /// let input = vec![Err(()), Ok(11), Err(()), Ok(22)]; + /// assert_eq!(input.into_iter().find_or_first(Result::is_ok), Some(Ok(11))); + /// + /// let input: Vec> = vec![Err(11), Err(22)]; + /// assert_eq!(input.into_iter().find_or_first(Result::is_ok), Some(Err(11))); + /// + /// assert_eq!(std::iter::empty::>().find_or_first(Result::is_ok), None); /// ``` fn find_or_first

(mut self, mut predicate: P) -> Option - where Self: Sized, - P: FnMut(&Self::Item) -> bool, + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, { let first = self.next()?; Some(if predicate(&first) { @@ -1810,14 +2164,14 @@ /// /// #[derive(PartialEq, Debug)] /// enum Enum { A, B, C, D, E, } - /// + /// /// let mut iter = vec![Enum::A, Enum::B, Enum::C, Enum::D].into_iter(); - /// + /// /// // search `iter` for `B` /// assert_eq!(iter.contains(&Enum::B), true); /// // `B` was found, so the iterator now rests at the item after `B` (i.e, `C`). /// assert_eq!(iter.next(), Some(Enum::C)); - /// + /// /// // search `iter` for `E` /// assert_eq!(iter.contains(&Enum::E), false); /// // `E` wasn't found, so `iter` is now exhausted @@ -1827,7 +2181,7 @@ where Self: Sized, Self::Item: Borrow, - Q: PartialEq, + Q: PartialEq + ?Sized, { self.any(|x| x.borrow() == query) } @@ -1849,8 +2203,9 @@ /// assert!(data.into_iter().all_equal()); /// ``` fn all_equal(&mut self) -> bool - where Self: Sized, - Self::Item: PartialEq, + where + Self: Sized, + Self::Item: PartialEq, { match self.next() { None => true, @@ -1858,6 +2213,38 @@ } } + /// If there are elements and they are all equal, return a single copy of that element. + /// If there are no elements, return an Error containing None. + /// If there are elements and they are not all equal, return a tuple containing the first + /// two non-equal elements found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; + /// assert_eq!(data.iter().all_equal_value(), Err(Some((&1, &2)))); + /// assert_eq!(data[0..3].iter().all_equal_value(), Ok(&1)); + /// assert_eq!(data[3..5].iter().all_equal_value(), Ok(&2)); + /// assert_eq!(data[5..8].iter().all_equal_value(), Ok(&3)); + /// + /// let data : Option = None; + /// assert_eq!(data.into_iter().all_equal_value(), Err(None)); + /// ``` + #[allow(clippy::type_complexity)] + fn all_equal_value(&mut self) -> Result> + where + Self: Sized, + Self::Item: PartialEq, + { + let first = self.next().ok_or(None)?; + let other = self.find(|x| x != &first); + if let Some(other) = other { + Err(Some((first, other))) + } else { + Ok(first) + } + } + /// Check whether all elements are unique (non equal). /// /// Empty iterators are considered to have unique elements: @@ -1875,8 +2262,9 @@ /// ``` #[cfg(feature = "use_std")] fn all_unique(&mut self) -> bool - where Self: Sized, - Self::Item: Eq + Hash + where + Self: Sized, + Self::Item: Eq + Hash, { let mut used = HashSet::new(); self.all(move |elt| used.insert(elt)) @@ -1885,20 +2273,21 @@ /// Consume the first `n` elements from the iterator eagerly, /// and return the same iterator again. /// - /// It works similarly to *.skip(* `n` *)* except it is eager and + /// It works similarly to `.skip(n)` except it is eager and /// preserves the iterator type. /// /// ``` /// use itertools::Itertools; /// - /// let mut iter = "αβγ".chars().dropping(2); + /// let iter = "αβγ".chars().dropping(2); /// itertools::assert_equal(iter, "γ".chars()); /// ``` /// /// *Fusing notes: if the iterator is exhausted by dropping, /// the result of calling `.next()` again depends on the iterator implementation.* fn dropping(mut self, n: usize) -> Self - where Self: Sized + where + Self: Sized, { if n > 0 { self.nth(n - 1); @@ -1922,8 +2311,8 @@ /// itertools::assert_equal(init, vec![0, 3, 6]); /// ``` fn dropping_back(mut self, n: usize) -> Self - where Self: Sized, - Self: DoubleEndedIterator + where + Self: Sized + DoubleEndedIterator, { if n > 0 { (&mut self).rev().nth(n - 1); @@ -1931,31 +2320,6 @@ self } - /// Run the closure `f` eagerly on each element of the iterator. - /// - /// Consumes the iterator until its end. - /// - /// ``` - /// use std::sync::mpsc::channel; - /// use itertools::Itertools; - /// - /// let (tx, rx) = channel(); - /// - /// // use .foreach() to apply a function to each value -- sending it - /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); - /// - /// drop(tx); - /// - /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); - /// ``` - #[deprecated(note="Use .for_each() instead", since="0.8.0")] - fn foreach(self, f: F) - where F: FnMut(Self::Item), - Self: Sized, - { - self.for_each(f); - } - /// Combine all an iterator's elements into one element by using [`Extend`]. /// /// This combinator will extend the first item with each of the rest of the @@ -1970,8 +2334,10 @@ /// vec![1, 2, 3, 4, 5, 6]); /// ``` fn concat(self) -> Self::Item - where Self: Sized, - Self::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default + where + Self: Sized, + Self::Item: + Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default, { concat(self) } @@ -1980,7 +2346,8 @@ /// for convenience. #[cfg(feature = "use_alloc")] fn collect_vec(self) -> Vec - where Self: Sized + where + Self: Sized, { self.collect() } @@ -1996,16 +2363,18 @@ /// /// fn process_dir_entries(entries: &[fs::DirEntry]) { /// // ... + /// # let _ = entries; /// } /// - /// fn do_stuff() -> std::io::Result<()> { + /// fn do_stuff() -> io::Result<()> { /// let entries: Vec<_> = fs::read_dir(".")?.try_collect()?; /// process_dir_entries(&entries); /// /// Ok(()) /// } + /// + /// # let _ = do_stuff; /// ``` - #[cfg(feature = "use_alloc")] fn try_collect(self) -> Result where Self: Sized + Iterator>, @@ -2031,21 +2400,17 @@ /// ``` #[inline] fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize - where Self: Iterator, - J: IntoIterator + where + Self: Iterator, + J: IntoIterator, { - let mut count = 0; - for elt in from { - match self.next() { - None => break, - Some(ptr) => *ptr = elt, - } - count += 1; - } - count + from.into_iter() + .zip(self) + .map(|(new, old)| *old = new) + .count() } - /// Combine all iterator elements into one String, separated by `sep`. + /// Combine all iterator elements into one `String`, separated by `sep`. /// /// Use the `Display` implementation of each element. /// @@ -2057,7 +2422,8 @@ /// ``` #[cfg(feature = "use_alloc")] fn join(&mut self, sep: &str) -> String - where Self::Item: std::fmt::Display + where + Self::Item: std::fmt::Display, { match self.next() { None => String::new(), @@ -2091,7 +2457,8 @@ /// "1.10, 2.72, -3.00"); /// ``` fn format(self, sep: &str) -> Format - where Self: Sized, + where + Self: Sized, { format::new_format_default(self, sep) } @@ -2129,21 +2496,13 @@ /// /// ``` fn format_with(self, sep: &str, format: F) -> FormatWith - where Self: Sized, - F: FnMut(Self::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, + where + Self: Sized, + F: FnMut(Self::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { format::new_format(self, sep, format) } - /// See [`.fold_ok()`](Itertools::fold_ok). - #[deprecated(note="Use .fold_ok() instead", since="0.10.0")] - fn fold_results(&mut self, start: B, f: F) -> Result - where Self: Iterator>, - F: FnMut(B, A) -> B - { - self.fold_ok(start, f) - } - /// Fold `Result` values from an iterator. /// /// Only `Ok` values are folded. If no error is encountered, the folded @@ -2158,11 +2517,14 @@ /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a /// computation like this: /// - /// ```ignore + /// ```no_run + /// # let start = 0; + /// # let f = |x, y| x + y; /// let mut accum = start; /// accum = f(accum, 1); /// accum = f(accum, 2); /// accum = f(accum, 3); + /// # let _ = accum; /// ``` /// /// With a `start` value of 0 and an addition as folding function, @@ -2187,8 +2549,9 @@ /// ); /// ``` fn fold_ok(&mut self, mut start: B, mut f: F) -> Result - where Self: Iterator>, - F: FnMut(B, A) -> B + where + Self: Iterator>, + F: FnMut(B, A) -> B, { for elt in self { match elt { @@ -2219,8 +2582,9 @@ /// assert_eq!(more_values.next().unwrap(), Some(0)); /// ``` fn fold_options(&mut self, mut start: B, mut f: F) -> Option - where Self: Iterator>, - F: FnMut(B, A) -> B + where + Self: Iterator>, + F: FnMut(B, A) -> B, { for elt in self { match elt { @@ -2243,10 +2607,14 @@ /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); /// assert_eq!((0..0).fold1(|x, y| x * y), None); /// ``` - #[deprecated(since = "0.10.2", note = "Use `Iterator::reduce` instead")] + #[deprecated( + note = "Use [`Iterator::reduce`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.reduce) instead", + since = "0.10.2" + )] fn fold1(mut self, f: F) -> Option - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, + where + F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, { self.next().map(move |x| self.fold(x, f)) } @@ -2279,65 +2647,110 @@ /// └─f─f─f─f─f─f /// ``` /// - /// If `f` is associative, prefer the normal [`Iterator::reduce`] instead. + /// If `f` is associative you should also decide carefully: + /// + /// For an iterator producing `n` elements, both [`Iterator::reduce`] and `tree_reduce` will + /// call `f` `n - 1` times. However, `tree_reduce` will call `f` on earlier intermediate + /// results, which is beneficial for `f` that allocate and produce longer results for longer + /// arguments. For example if `f` combines arguments using `format!`, then `tree_reduce` will + /// operate on average on shorter arguments resulting in less bytes being allocated overall. + /// + /// Moreover, the output of `tree_reduce` is preferable to that of [`Iterator::reduce`] in + /// certain cases. For example, building a binary search tree using `tree_reduce` will result in + /// a balanced tree with height `O(ln(n))`, while [`Iterator::reduce`] will output a tree with + /// height `O(n)`, essentially a linked list. + /// + /// If `f` does not benefit from such a reordering, like `u32::wrapping_add`, prefer the + /// normal [`Iterator::reduce`] instead since it will most likely result in the generation of + /// simpler code because the compiler is able to optimize it. /// /// ``` /// use itertools::Itertools; /// + /// let f = |a: String, b: String| { + /// format!("f({a}, {b})") + /// }; + /// /// // The same tree as above - /// let num_strings = (1..8).map(|x| x.to_string()); - /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), - /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); - /// - /// // Like fold1, an empty iterator produces None - /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); - /// - /// // tree_fold1 matches fold1 for associative operations... - /// assert_eq!((0..10).tree_fold1(|x, y| x + y), - /// (0..10).fold1(|x, y| x + y)); + /// assert_eq!((1..8).map(|x| x.to_string()).tree_reduce(f), + /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); + /// + /// // Like reduce, an empty iterator produces None + /// assert_eq!((0..0).tree_reduce(|x, y| x * y), None); + /// + /// // tree_reduce matches reduce for associative operations... + /// assert_eq!((0..10).tree_reduce(|x, y| x + y), + /// (0..10).reduce(|x, y| x + y)); + /// /// // ...but not for non-associative ones - /// assert_ne!((0..10).tree_fold1(|x, y| x - y), - /// (0..10).fold1(|x, y| x - y)); + /// assert_ne!((0..10).tree_reduce(|x, y| x - y), + /// (0..10).reduce(|x, y| x - y)); + /// + /// let mut total_len_reduce = 0; + /// let reduce_res = (1..100).map(|x| x.to_string()) + /// .reduce(|a, b| { + /// let r = f(a, b); + /// total_len_reduce += r.len(); + /// r + /// }) + /// .unwrap(); + /// + /// let mut total_len_tree_reduce = 0; + /// let tree_reduce_res = (1..100).map(|x| x.to_string()) + /// .tree_reduce(|a, b| { + /// let r = f(a, b); + /// total_len_tree_reduce += r.len(); + /// r + /// }) + /// .unwrap(); + /// + /// assert_eq!(total_len_reduce, 33299); + /// assert_eq!(total_len_tree_reduce, 4228); + /// assert_eq!(reduce_res.len(), tree_reduce_res.len()); /// ``` - fn tree_fold1(mut self, mut f: F) -> Option - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, + fn tree_reduce(mut self, mut f: F) -> Option + where + F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, { type State = Result>; fn inner0(it: &mut II, f: &mut FF) -> State - where - II: Iterator, - FF: FnMut(T, T) -> T + where + II: Iterator, + FF: FnMut(T, T) -> T, { // This function could be replaced with `it.next().ok_or(None)`, - // but half the useful tree_fold1 work is combining adjacent items, + // but half the useful tree_reduce work is combining adjacent items, // so put that in a form that LLVM is more likely to optimize well. - let a = - if let Some(v) = it.next() { v } - else { return Err(None) }; - let b = - if let Some(v) = it.next() { v } - else { return Err(Some(a)) }; + let a = if let Some(v) = it.next() { + v + } else { + return Err(None); + }; + let b = if let Some(v) = it.next() { + v + } else { + return Err(Some(a)); + }; Ok(f(a, b)) } fn inner(stop: usize, it: &mut II, f: &mut FF) -> State - where - II: Iterator, - FF: FnMut(T, T) -> T + where + II: Iterator, + FF: FnMut(T, T) -> T, { let mut x = inner0(it, f)?; for height in 0..stop { // Try to get another tree the same size with which to combine it, // creating a new tree that's twice as big for next time around. - let next = - if height == 0 { - inner0(it, f) - } else { - inner(height, it, f) - }; + let next = if height == 0 { + inner0(it, f) + } else { + inner(height, it, f) + }; match next { Ok(y) => x = f(x, y), @@ -2352,12 +2765,22 @@ Ok(x) } - match inner(usize::max_value(), &mut self, &mut f) { + match inner(usize::MAX, &mut self, &mut f) { Err(x) => x, _ => unreachable!(), } } + /// See [`.tree_reduce()`](Itertools::tree_reduce). + #[deprecated(note = "Use .tree_reduce() instead", since = "0.13.0")] + fn tree_fold1(self, f: F) -> Option + where + F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + self.tree_reduce(f) + } + /// An iterator method that applies a function, producing a single, final value. /// /// `fold_while()` is basically equivalent to [`Iterator::fold`] but with additional support for @@ -2398,19 +2821,19 @@ /// `fold()` called the provided closure for every item of the callee iterator, /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. fn fold_while(&mut self, init: B, mut f: F) -> FoldWhile - where Self: Sized, - F: FnMut(B, Self::Item) -> FoldWhile + where + Self: Sized, + F: FnMut(B, Self::Item) -> FoldWhile, { - use Result::{ - Ok as Continue, - Err as Break, - }; - - let result = self.try_fold(init, #[inline(always)] |acc, v| - match f(acc, v) { - FoldWhile::Continue(acc) => Continue(acc), - FoldWhile::Done(acc) => Break(acc), - } + use Result::{Err as Break, Ok as Continue}; + + let result = self.try_fold( + init, + #[inline(always)] + |acc, v| match f(acc, v) { + FoldWhile::Continue(acc) => Continue(acc), + FoldWhile::Done(acc) => Break(acc), + }, ); match result { @@ -2441,11 +2864,11 @@ /// assert_eq!(nonempty_sum, Some(55)); /// ``` fn sum1(mut self) -> Option - where Self: Sized, - S: std::iter::Sum, + where + Self: Sized, + S: std::iter::Sum, { - self.next() - .map(|first| once(first).chain(self).sum()) + self.next().map(|first| once(first).chain(self).sum()) } /// Iterate over the entire iterator and multiply all the elements. @@ -2469,11 +2892,11 @@ /// assert_eq!(nonempty_product, Some(3628800)); /// ``` fn product1

(mut self) -> Option

- where Self: Sized, - P: std::iter::Product, + where + Self: Sized, + P: std::iter::Product, { - self.next() - .map(|first| once(first).chain(self).product()) + self.next().map(|first| once(first).chain(self).product()) } /// Sort all iterator elements into a new iterator in ascending order. @@ -2482,6 +2905,8 @@ /// [`slice::sort_unstable`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is unstable (i.e., may reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2495,8 +2920,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted_unstable(self) -> VecIntoIter - where Self: Sized, - Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { // Use .sort_unstable() directly since it is not quite identical with // .sort_by(Ord::cmp) @@ -2511,6 +2937,8 @@ /// [`slice::sort_unstable_by`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is unstable (i.e., may reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2530,8 +2958,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted_unstable_by(self, cmp: F) -> VecIntoIter - where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { let mut v = Vec::from_iter(self); v.sort_unstable_by(cmp); @@ -2544,6 +2973,8 @@ /// [`slice::sort_unstable_by_key`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is unstable (i.e., may reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2563,9 +2994,10 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted_unstable_by_key(self, f: F) -> VecIntoIter - where Self: Sized, - K: Ord, - F: FnMut(&Self::Item) -> K, + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { let mut v = Vec::from_iter(self); v.sort_unstable_by_key(f); @@ -2578,6 +3010,8 @@ /// [`slice::sort`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is stable (i.e., does not reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2591,8 +3025,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted(self) -> VecIntoIter - where Self: Sized, - Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { // Use .sort() directly since it is not quite identical with // .sort_by(Ord::cmp) @@ -2607,6 +3042,8 @@ /// [`slice::sort_by`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is stable (i.e., does not reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2614,7 +3051,7 @@ /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2626,8 +3063,9 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted_by(self, cmp: F) -> VecIntoIter - where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { let mut v = Vec::from_iter(self); v.sort_by(cmp); @@ -2640,6 +3078,8 @@ /// [`slice::sort_by_key`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is stable (i.e., does not reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2647,7 +3087,7 @@ /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2659,9 +3099,10 @@ /// ``` #[cfg(feature = "use_alloc")] fn sorted_by_key(self, f: F) -> VecIntoIter - where Self: Sized, - K: Ord, - F: FnMut(&Self::Item) -> K, + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { let mut v = Vec::from_iter(self); v.sort_by_key(f); @@ -2675,6 +3116,8 @@ /// [`slice::sort_by_cached_key`] method and returns the result as a new /// iterator that owns its elements. /// + /// This sort is stable (i.e., does not reorder equal elements). + /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. /// @@ -2682,7 +3125,7 @@ /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2733,12 +3176,440 @@ /// ``` #[cfg(feature = "use_alloc")] fn k_smallest(self, k: usize) -> VecIntoIter - where Self: Sized, - Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, + { + // The stdlib heap has optimised handling of "holes", which is not included in our heap implementation in k_smallest_general. + // While the difference is unlikely to have practical impact unless `Self::Item` is very large, this method uses the stdlib structure + // to maintain performance compared to previous versions of the crate. + use alloc::collections::BinaryHeap; + + if k == 0 { + self.last(); + return Vec::new().into_iter(); + } + if k == 1 { + return self.min().into_iter().collect_vec().into_iter(); + } + + let mut iter = self.fuse(); + let mut heap: BinaryHeap<_> = iter.by_ref().take(k).collect(); + + iter.for_each(|i| { + debug_assert_eq!(heap.len(), k); + // Equivalent to heap.push(min(i, heap.pop())) but more efficient. + // This should be done with a single `.peek_mut().unwrap()` but + // `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior. + if *heap.peek().unwrap() > i { + *heap.peek_mut().unwrap() = i; + } + }); + + heap.into_sorted_vec().into_iter() + } + + /// Sort the k smallest elements into a new iterator using the provided comparison. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// This corresponds to `self.sorted_by(cmp).take(k)` in the same way that + /// [`k_smallest`](Itertools::k_smallest) corresponds to `self.sorted().take(k)`, + /// in both semantics and complexity. + /// + /// Particularly, a custom heap implementation ensures the comparison is not cloned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b))); + /// + /// itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest_by(self, k: usize, cmp: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + k_smallest::k_smallest_general(self, k, cmp).into_iter() + } + + /// Return the elements producing the k smallest outputs of the provided function. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// This corresponds to `self.sorted_by_key(key).take(k)` in the same way that + /// [`k_smallest`](Itertools::k_smallest) corresponds to `self.sorted().take(k)`, + /// in both semantics and complexity. + /// + /// Particularly, a custom heap implementation ensures the comparison is not cloned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest_by_key(5, |n| (n % 7, *n)); + /// + /// itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest_by_key(self, k: usize, key: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: Ord, + { + self.k_smallest_by(k, k_smallest::key_to_cmp(key)) + } + + /// Sort the k smallest elements into a new iterator, in ascending order, relaxing the amount of memory required. + /// + /// **Note:** This consumes the entire iterator, and returns the result + /// as a new iterator that owns its elements. If the input contains + /// less than k elements, the result is equivalent to `self.sorted()`. + /// + /// This is guaranteed to use `2 * k * sizeof(Self::Item) + O(1)` memory + /// and `O(n + k log k)` time, with `n` the number of elements in the input, + /// meaning it uses more memory than the minimum obtained by [`k_smallest`](Itertools::k_smallest) + /// but achieves linear time in the number of elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// **Note:** This is functionally-equivalent to `self.sorted().take(k)` + /// but much more efficient. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest_relaxed(5); + /// + /// itertools::assert_equal(five_smallest, 0..5); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest_relaxed(self, k: usize) -> VecIntoIter + where + Self: Sized, + Self::Item: Ord, + { + self.k_smallest_relaxed_by(k, Ord::cmp) + } + + /// Sort the k smallest elements into a new iterator using the provided comparison, relaxing the amount of memory required. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// This corresponds to `self.sorted_by(cmp).take(k)` in the same way that + /// [`k_smallest_relaxed`](Itertools::k_smallest_relaxed) corresponds to `self.sorted().take(k)`, + /// in both semantics and complexity. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest_relaxed_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b))); + /// + /// itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest_relaxed_by(self, k: usize, cmp: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - crate::k_smallest::k_smallest(self, k) - .into_sorted_vec() - .into_iter() + k_smallest::k_smallest_relaxed_general(self, k, cmp).into_iter() + } + + /// Return the elements producing the k smallest outputs of the provided function, relaxing the amount of memory required. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// This corresponds to `self.sorted_by_key(key).take(k)` in the same way that + /// [`k_smallest_relaxed`](Itertools::k_smallest_relaxed) corresponds to `self.sorted().take(k)`, + /// in both semantics and complexity. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest_relaxed_by_key(5, |n| (n % 7, *n)); + /// + /// itertools::assert_equal(five_smallest, vec![0, 7, 14, 1, 8]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest_relaxed_by_key(self, k: usize, key: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: Ord, + { + self.k_smallest_relaxed_by(k, k_smallest::key_to_cmp(key)) + } + + /// Sort the k largest elements into a new iterator, in descending order. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// It is semantically equivalent to [`k_smallest`](Itertools::k_smallest) + /// with a reversed `Ord`. + /// However, this is implemented with a custom binary heap which does not + /// have the same performance characteristics for very large `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest(5); + /// + /// itertools::assert_equal(five_largest, vec![14, 13, 12, 11, 10]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest(self, k: usize) -> VecIntoIter + where + Self: Sized, + Self::Item: Ord, + { + self.k_largest_by(k, Self::Item::cmp) + } + + /// Sort the k largest elements into a new iterator using the provided comparison. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// Functionally equivalent to [`k_smallest_by`](Itertools::k_smallest_by) + /// with a reversed `Ord`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b))); + /// + /// itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest_by(self, k: usize, mut cmp: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.k_smallest_by(k, move |a, b| cmp(b, a)) + } + + /// Return the elements producing the k largest outputs of the provided function. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// Functionally equivalent to [`k_smallest_by_key`](Itertools::k_smallest_by_key) + /// with a reversed `Ord`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest_by_key(5, |n| (n % 7, *n)); + /// + /// itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest_by_key(self, k: usize, key: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: Ord, + { + self.k_largest_by(k, k_smallest::key_to_cmp(key)) + } + + /// Sort the k largest elements into a new iterator, in descending order, relaxing the amount of memory required. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// It is semantically equivalent to [`k_smallest_relaxed`](Itertools::k_smallest_relaxed) + /// with a reversed `Ord`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest_relaxed(5); + /// + /// itertools::assert_equal(five_largest, vec![14, 13, 12, 11, 10]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest_relaxed(self, k: usize) -> VecIntoIter + where + Self: Sized, + Self::Item: Ord, + { + self.k_largest_relaxed_by(k, Self::Item::cmp) + } + + /// Sort the k largest elements into a new iterator using the provided comparison, relaxing the amount of memory required. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// Functionally equivalent to [`k_smallest_relaxed_by`](Itertools::k_smallest_relaxed_by) + /// with a reversed `Ord`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest_relaxed_by(5, |a, b| (a % 7).cmp(&(b % 7)).then(a.cmp(b))); + /// + /// itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest_relaxed_by(self, k: usize, mut cmp: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.k_smallest_relaxed_by(k, move |a, b| cmp(b, a)) + } + + /// Return the elements producing the k largest outputs of the provided function, relaxing the amount of memory required. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// Functionally equivalent to [`k_smallest_relaxed_by_key`](Itertools::k_smallest_relaxed_by_key) + /// with a reversed `Ord`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_largest = numbers + /// .into_iter() + /// .k_largest_relaxed_by_key(5, |n| (n % 7, *n)); + /// + /// itertools::assert_equal(five_largest, vec![13, 6, 12, 5, 11]); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_largest_relaxed_by_key(self, k: usize, key: F) -> VecIntoIter + where + Self: Sized, + F: FnMut(&Self::Item) -> K, + K: Ord, + { + self.k_largest_relaxed_by(k, k_smallest::key_to_cmp(key)) + } + + /// Consumes the iterator and return an iterator of the last `n` elements. + /// + /// The iterator, if directly collected to a `VecDeque`, is converted + /// without any extra copying or allocation cost. + /// If directly collected to a `Vec`, it may need some data movement + /// but no re-allocation. + /// + /// ``` + /// use itertools::{assert_equal, Itertools}; + /// + /// let v = vec![5, 9, 8, 4, 2, 12, 0]; + /// assert_equal(v.iter().tail(3), &[2, 12, 0]); + /// assert_equal(v.iter().tail(10), &v); + /// + /// assert_equal(v.iter().tail(1), v.iter().last()); + /// + /// assert_equal((0..100).tail(10), 90..100); + /// + /// assert_equal((0..100).filter(|x| x % 3 == 0).tail(10), (72..100).step_by(3)); + /// ``` + /// + /// For double ended iterators without side-effects, you might prefer + /// `.rev().take(n).rev()` to have a similar result (lazy and non-allocating) + /// without consuming the entire iterator. + #[cfg(feature = "use_alloc")] + fn tail(self, n: usize) -> VecDequeIntoIter + where + Self: Sized, + { + match n { + 0 => { + self.last(); + VecDeque::new() + } + 1 => self.last().into_iter().collect(), + _ => { + // Skip the starting part of the iterator if possible. + let (low, _) = self.size_hint(); + let mut iter = self.fuse().skip(low.saturating_sub(n)); + // TODO: If VecDeque has a more efficient method than + // `.pop_front();.push_back(val)` in the future then maybe revisit this. + let mut data: Vec<_> = iter.by_ref().take(n).collect(); + // Update `data` cyclically. + let idx = iter.fold(0, |i, val| { + debug_assert_eq!(data.len(), n); + data[i] = val; + if i + 1 == n { + 0 + } else { + i + 1 + } + }); + // Respect the insertion order, efficiently. + let mut data = VecDeque::from(data); + data.rotate_left(idx); + data + } + } + .into_iter() } /// Collect all iterator elements into one of two @@ -2763,10 +3634,11 @@ /// assert_eq!(failures, [false, true]); /// ``` fn partition_map(self, mut predicate: F) -> (A, B) - where Self: Sized, - F: FnMut(Self::Item) -> Either, - A: Default + Extend, - B: Default + Extend, + where + Self: Sized, + F: FnMut(Self::Item) -> Either, + A: Default + Extend, + B: Default + Extend, { let mut left = A::default(); let mut right = B::default(); @@ -2795,10 +3667,10 @@ /// assert_eq!(failures, [false, true]); /// ``` fn partition_result(self) -> (A, B) - where - Self: Iterator> + Sized, - A: Default + Extend, - B: Default + Extend, + where + Self: Iterator> + Sized, + A: Default + Extend, + B: Default + Extend, { self.partition_map(|r| match r { Ok(v) => Either::Left(v), @@ -2824,14 +3696,15 @@ /// ``` #[cfg(feature = "use_std")] fn into_group_map(self) -> HashMap> - where Self: Iterator + Sized, - K: Hash + Eq, + where + Self: Iterator + Sized, + K: Hash + Eq, { group_map::into_group_map(self) } - /// Return an `Iterator` on a `HashMap`. Keys mapped to `Vec`s of values. The key is specified - /// in the closure. + /// Return a `HashMap` of keys mapped to `Vec`s of values. The key is specified + /// in the closure. The values are taken from the input iterator. /// /// Essentially a shorthand for `.into_grouping_map_by(f).collect::>()`. /// @@ -2843,7 +3716,7 @@ /// let lookup: HashMap> = /// data.clone().into_iter().into_group_map_by(|a| a.0); /// - /// assert_eq!(lookup[&0], vec![(0,10),(0,20)]); + /// assert_eq!(lookup[&0], vec![(0,10), (0,20)]); /// assert_eq!(lookup.get(&1), None); /// assert_eq!(lookup[&2], vec![(2,12), (2,42)]); /// assert_eq!(lookup[&3], vec![(3,13), (3,33)]); @@ -2859,46 +3732,48 @@ /// ``` #[cfg(feature = "use_std")] fn into_group_map_by(self, f: F) -> HashMap> - where - Self: Iterator + Sized, - K: Hash + Eq, - F: Fn(&V) -> K, + where + Self: Iterator + Sized, + K: Hash + Eq, + F: FnMut(&V) -> K, { group_map::into_group_map_by(self, f) } - /// Constructs a `GroupingMap` to be used later with one of the efficient + /// Constructs a `GroupingMap` to be used later with one of the efficient /// group-and-fold operations it allows to perform. - /// + /// /// The input iterator must yield item in the form of `(K, V)` where the /// value of type `K` will be used as key to identify the groups and the /// value of type `V` as value for the folding operation. - /// + /// /// See [`GroupingMap`] for more informations /// on what operations are available. #[cfg(feature = "use_std")] fn into_grouping_map(self) -> GroupingMap - where Self: Iterator + Sized, - K: Hash + Eq, + where + Self: Iterator + Sized, + K: Hash + Eq, { grouping_map::new(self) } - /// Constructs a `GroupingMap` to be used later with one of the efficient + /// Constructs a `GroupingMap` to be used later with one of the efficient /// group-and-fold operations it allows to perform. - /// + /// /// The values from this iterator will be used as values for the folding operation /// while the keys will be obtained from the values by calling `key_mapper`. - /// + /// /// See [`GroupingMap`] for more informations /// on what operations are available. #[cfg(feature = "use_std")] fn into_grouping_map_by(self, key_mapper: F) -> GroupingMapBy - where Self: Iterator + Sized, - K: Hash + Eq, - F: FnMut(&V) -> K + where + Self: Iterator + Sized, + K: Hash + Eq, + F: FnMut(&V) -> K, { - grouping_map::new(grouping_map::MapForGrouping::new(self, key_mapper)) + grouping_map::new(grouping_map::new_map_for_grouping(self, key_mapper)) } /// Return all minimum elements of an iterator. @@ -2923,9 +3798,11 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn min_set(self) -> Vec - where Self: Sized, Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { extrema_set::min_set_impl(self, |_| (), |x, y, _, _| x.cmp(y)) } @@ -2954,15 +3831,13 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn min_set_by(self, mut compare: F) -> Vec - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - extrema_set::min_set_impl( - self, - |_| (), - |x, y, _, _| compare(x, y) - ) + extrema_set::min_set_impl(self, |_| (), |x, y, _, _| compare(x, y)) } /// Return all minimum elements of an iterator, as determined by @@ -2988,9 +3863,12 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn min_set_by_key(self, key: F) -> Vec - where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { extrema_set::min_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky)) } @@ -3017,9 +3895,11 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn max_set(self) -> Vec - where Self: Sized, Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { extrema_set::max_set_impl(self, |_| (), |x, y, _, _| x.cmp(y)) } @@ -3048,18 +3928,16 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn max_set_by(self, mut compare: F) -> Vec - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - extrema_set::max_set_impl( - self, - |_| (), - |x, y, _, _| compare(x, y) - ) + extrema_set::max_set_impl(self, |_| (), |x, y, _, _| compare(x, y)) } - /// Return all minimum elements of an iterator, as determined by + /// Return all maximum elements of an iterator, as determined by /// the specified function. /// /// # Examples @@ -3082,9 +3960,12 @@ /// /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. - #[cfg(feature = "use_std")] + #[cfg(feature = "use_alloc")] fn max_set_by_key(self, key: F) -> Vec - where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { extrema_set::max_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky)) } @@ -3125,7 +4006,9 @@ /// The elements can be floats but no particular result is guaranteed /// if an element is NaN. fn minmax(self) -> MinMaxResult - where Self: Sized, Self::Item: PartialOrd + where + Self: Sized, + Self::Item: PartialOrd, { minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) } @@ -3142,7 +4025,10 @@ /// The keys can be floats but no particular result is guaranteed /// if a key is NaN. fn minmax_by_key(self, key: F) -> MinMaxResult - where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: PartialOrd, + F: FnMut(&Self::Item) -> K, { minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) } @@ -3156,13 +4042,11 @@ /// the last maximal element wins. This matches the behavior of the standard /// [`Iterator::min`] and [`Iterator::max`] methods. fn minmax_by(self, mut compare: F) -> MinMaxResult - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - minmax::minmax_impl( - self, - |_| (), - |x, y, _, _| Ordering::Less == compare(x, y) - ) + minmax::minmax_impl(self, |_| (), |x, y, _, _| Ordering::Less == compare(x, y)) } /// Return the position of the maximum element in the iterator. @@ -3185,7 +4069,9 @@ /// assert_eq!(a.iter().position_max(), Some(1)); /// ``` fn position_max(self) -> Option - where Self: Sized, Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { self.enumerate() .max_by(|x, y| Ord::cmp(&x.1, &y.1)) @@ -3213,7 +4099,10 @@ /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(3)); /// ``` fn position_max_by_key(self, mut key: F) -> Option - where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { self.enumerate() .max_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) @@ -3241,7 +4130,9 @@ /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(1)); /// ``` fn position_max_by(self, mut compare: F) -> Option - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { self.enumerate() .max_by(|x, y| compare(&x.1, &y.1)) @@ -3268,7 +4159,9 @@ /// assert_eq!(a.iter().position_min(), Some(2)); /// ``` fn position_min(self) -> Option - where Self: Sized, Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { self.enumerate() .min_by(|x, y| Ord::cmp(&x.1, &y.1)) @@ -3296,7 +4189,10 @@ /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(0)); /// ``` fn position_min_by_key(self, mut key: F) -> Option - where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, { self.enumerate() .min_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) @@ -3324,7 +4220,9 @@ /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(2)); /// ``` fn position_min_by(self, mut compare: F) -> Option - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { self.enumerate() .min_by(|x, y| compare(&x.1, &y.1)) @@ -3374,9 +4272,11 @@ /// assert_eq!(a.iter().position_minmax(), MinMax(2, 1)); /// ``` fn position_minmax(self) -> MinMaxResult - where Self: Sized, Self::Item: PartialOrd + where + Self: Sized, + Self::Item: PartialOrd, { - use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + use crate::MinMaxResult::{MinMax, NoElements, OneElement}; match minmax::minmax_impl(self.enumerate(), |_| (), |x, y, _, _| x.1 < y.1) { NoElements => NoElements, OneElement(x) => OneElement(x.0), @@ -3419,9 +4319,12 @@ /// /// [`position_minmax`]: Self::position_minmax fn position_minmax_by_key(self, mut key: F) -> MinMaxResult - where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K + where + Self: Sized, + K: PartialOrd, + F: FnMut(&Self::Item) -> K, { - use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + use crate::MinMaxResult::{MinMax, NoElements, OneElement}; match self.enumerate().minmax_by_key(|e| key(&e.1)) { NoElements => NoElements, OneElement(x) => OneElement(x.0), @@ -3461,9 +4364,11 @@ /// /// [`position_minmax`]: Self::position_minmax fn position_minmax_by(self, mut compare: F) -> MinMaxResult - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + use crate::MinMaxResult::{MinMax, NoElements, OneElement}; match self.enumerate().minmax_by(|x, y| compare(&x.1, &y.1)) { NoElements => NoElements, OneElement(x) => OneElement(x.0), @@ -3493,21 +4398,18 @@ Self: Sized, { match self.next() { - Some(first) => { - match self.next() { - Some(second) => { - Err(ExactlyOneError::new(Some(Either::Left([first, second])), self)) - } - None => { - Ok(first) - } - } - } + Some(first) => match self.next() { + Some(second) => Err(ExactlyOneError::new( + Some(Either::Left([first, second])), + self, + )), + None => Ok(first), + }, None => Err(ExactlyOneError::new(None, self)), } } - /// If the iterator yields no elements, Ok(None) will be returned. If the iterator yields + /// If the iterator yields no elements, `Ok(None)` will be returned. If the iterator yields /// exactly one element, that element will be returned, otherwise an error will be returned /// containing an iterator that has the same output as the input iterator. /// @@ -3529,16 +4431,13 @@ Self: Sized, { match self.next() { - Some(first) => { - match self.next() { - Some(second) => { - Err(ExactlyOneError::new(Some(Either::Left([first, second])), self)) - } - None => { - Ok(Some(first)) - } - } - } + Some(first) => match self.next() { + Some(second) => Err(ExactlyOneError::new( + Some(Either::Left([first, second])), + self, + )), + None => Ok(Some(first)), + }, None => Ok(None), } } @@ -3572,7 +4471,7 @@ /// # Examples /// ``` /// # use itertools::Itertools; - /// let counts = [1, 1, 1, 3, 3, 5].into_iter().counts(); + /// let counts = [1, 1, 1, 3, 3, 5].iter().counts(); /// assert_eq!(counts[&1], 3); /// assert_eq!(counts[&3], 2); /// assert_eq!(counts[&5], 1); @@ -3598,9 +4497,10 @@ /// # use itertools::Itertools; /// struct Character { /// first_name: &'static str, + /// # #[allow(dead_code)] /// last_name: &'static str, /// } - /// + /// /// let characters = /// vec![ /// Character { first_name: "Amy", last_name: "Pond" }, @@ -3611,12 +4511,12 @@ /// Character { first_name: "James", last_name: "Norington" }, /// Character { first_name: "James", last_name: "Kirk" }, /// ]; - /// - /// let first_name_frequency = + /// + /// let first_name_frequency = /// characters /// .into_iter() /// .counts_by(|c| c.first_name); - /// + /// /// assert_eq!(first_name_frequency["Amy"], 3); /// assert_eq!(first_name_frequency["James"], 4); /// assert_eq!(first_name_frequency.contains_key("Asha"), false); @@ -3633,11 +4533,11 @@ /// Converts an iterator of tuples into a tuple of containers. /// - /// `unzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each + /// It consumes an entire iterator of n-ary tuples, producing `n` collections, one for each /// column. /// /// This function is, in some sense, the opposite of [`multizip`]. - /// + /// /// ``` /// use itertools::Itertools; /// @@ -3657,9 +4557,33 @@ { MultiUnzip::multiunzip(self) } + + /// Returns the length of the iterator if one exists. + /// Otherwise return `self.size_hint()`. + /// + /// Fallible [`ExactSizeIterator::len`]. + /// + /// Inherits guarantees and restrictions from [`Iterator::size_hint`]. + /// + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!([0; 10].iter().try_len(), Ok(10)); + /// assert_eq!((10..15).try_len(), Ok(5)); + /// assert_eq!((15..10).try_len(), Ok(0)); + /// assert_eq!((10..).try_len(), Err((usize::MAX, None))); + /// assert_eq!((10..15).filter(|x| x % 2 == 0).try_len(), Err((0, Some(5)))); + /// ``` + fn try_len(&self) -> Result { + let sh = self.size_hint(); + match sh { + (lo, Some(hi)) if lo == hi => Ok(lo), + _ => Err(sh), + } + } } -impl Itertools for T where T: Iterator { } +impl Itertools for T where T: Iterator + ?Sized {} /// Return `true` if both iterables produce equal sequences /// (elements pairwise equal and sequences of the same length), @@ -3672,9 +4596,10 @@ /// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); /// ``` pub fn equal(a: I, b: J) -> bool - where I: IntoIterator, - J: IntoIterator, - I::Item: PartialEq +where + I: IntoIterator, + J: IntoIterator, + I::Item: PartialEq, { a.into_iter().eq(b) } @@ -3683,31 +4608,39 @@ /// semantics as [`equal(a, b)`](equal). /// /// **Panics** on assertion failure with a message that shows the -/// two iteration elements. +/// two different elements and the iteration index. /// -/// ```ignore +/// ```should_panic +/// # use itertools::assert_equal; /// assert_equal("exceed".split('c'), "excess".split('c')); -/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', +/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1'. /// ``` +#[track_caller] pub fn assert_equal(a: I, b: J) - where I: IntoIterator, - J: IntoIterator, - I::Item: fmt::Debug + PartialEq, - J::Item: fmt::Debug, +where + I: IntoIterator, + J: IntoIterator, + I::Item: fmt::Debug + PartialEq, + J::Item: fmt::Debug, { let mut ia = a.into_iter(); let mut ib = b.into_iter(); - let mut i = 0; + let mut i: usize = 0; loop { match (ia.next(), ib.next()) { (None, None) => return, (a, b) => { let equal = match (&a, &b) { - (&Some(ref a), &Some(ref b)) => a == b, + (Some(a), Some(b)) => a == b, _ => false, }; - assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", - i=i, a=a, b=b); + assert!( + equal, + "Failed assertion {a:?} == {b:?} for iteration {i}", + i = i, + a = a, + b = b + ); i += 1; } } @@ -3732,22 +4665,18 @@ /// assert_eq!(split_index, 3); /// ``` pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize - where I: IntoIterator, - I::IntoIter: DoubleEndedIterator, - F: FnMut(&A) -> bool +where + I: IntoIterator, + I::IntoIter: DoubleEndedIterator, + F: FnMut(&A) -> bool, { let mut split_index = 0; let mut iter = iter.into_iter(); - 'main: while let Some(front) = iter.next() { + while let Some(front) = iter.next() { if !pred(front) { - loop { - match iter.next_back() { - Some(back) => if pred(back) { - std::mem::swap(front, back); - break; - }, - None => break 'main, - } + match iter.rfind(|back| pred(back)) { + Some(back) => std::mem::swap(front, back), + None => break, } } split_index += 1; @@ -3770,15 +4699,15 @@ /// Return the value in the continue or done. pub fn into_inner(self) -> T { match self { - FoldWhile::Continue(x) | FoldWhile::Done(x) => x, + Self::Continue(x) | Self::Done(x) => x, } } /// Return true if `self` is `Done`, false if it is `Continue`. pub fn is_done(&self) -> bool { match *self { - FoldWhile::Continue(_) => false, - FoldWhile::Done(_) => true, + Self::Continue(_) => false, + Self::Done(_) => true, } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/merge_join.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/merge_join.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/merge_join.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/merge_join.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,151 +1,315 @@ use std::cmp::Ordering; -use std::iter::Fuse; use std::fmt; +use std::iter::{Fuse, FusedIterator}; +use std::marker::PhantomData; -use super::adaptors::{PutBack, put_back}; +use either::Either; + +use super::adaptors::{put_back, PutBack}; use crate::either_or_both::EitherOrBoth; +use crate::size_hint::{self, SizeHint}; #[cfg(doc)] use crate::Itertools; +#[derive(Clone, Debug)] +pub struct MergeLte; + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge()`](crate::Itertools::merge_by) for more information. +pub type Merge = MergeBy; + +/// Create an iterator that merges elements in `i` and `j`. +/// +/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge). +/// +/// ``` +/// use itertools::merge; +/// +/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { +/// /* loop body */ +/// # let _ = elt; +/// } +/// ``` +pub fn merge( + i: I, + j: J, +) -> Merge<::IntoIter, ::IntoIter> +where + I: IntoIterator, + J: IntoIterator, + I::Item: PartialOrd, +{ + merge_by_new(i, j, MergeLte) +} + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge_by()`](crate::Itertools::merge_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MergeBy { + left: PutBack>, + right: PutBack>, + cmp_fn: F, +} + +/// Create a `MergeBy` iterator. +pub fn merge_by_new(a: I, b: J, cmp: F) -> MergeBy +where + I: IntoIterator, + J: IntoIterator, +{ + MergeBy { + left: put_back(a.into_iter().fuse()), + right: put_back(b.into_iter().fuse()), + cmp_fn: cmp, + } +} + /// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. /// /// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`]. -pub fn merge_join_by(left: I, right: J, cmp_fn: F) - -> MergeJoinBy - where I: IntoIterator, - J: IntoIterator, - F: FnMut(&I::Item, &J::Item) -> Ordering +pub fn merge_join_by( + left: I, + right: J, + cmp_fn: F, +) -> MergeJoinBy +where + I: IntoIterator, + J: IntoIterator, + F: FnMut(&I::Item, &J::Item) -> T, { - MergeJoinBy { + MergeBy { left: put_back(left.into_iter().fuse()), right: put_back(right.into_iter().fuse()), - cmp_fn, + cmp_fn: MergeFuncLR(cmp_fn, PhantomData), } } /// An iterator adaptor that merge-joins items from the two base iterators in ascending order. /// /// See [`.merge_join_by()`](crate::Itertools::merge_join_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeJoinBy { - left: PutBack>, - right: PutBack>, - cmp_fn: F +pub type MergeJoinBy = + MergeBy::Item, ::Item>>::T>>; + +#[derive(Clone, Debug)] +pub struct MergeFuncLR(F, PhantomData); + +pub trait FuncLR { + type T; } -impl Clone for MergeJoinBy - where I: Iterator, - J: Iterator, - PutBack>: Clone, - PutBack>: Clone, - F: Clone, +impl T> FuncLR for F { + type T = T; +} + +pub trait OrderingOrBool { + type MergeResult; + fn left(left: L) -> Self::MergeResult; + fn right(right: R) -> Self::MergeResult; + // "merge" never returns (Some(...), Some(...), ...) so Option> + // is appealing but it is always followed by two put_backs, so we think the compiler is + // smart enough to optimize it. Or we could move put_backs into "merge". + fn merge(&mut self, left: L, right: R) -> (Option>, Self::MergeResult); + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint; +} + +impl Ordering> OrderingOrBool for MergeFuncLR { + type MergeResult = EitherOrBoth; + fn left(left: L) -> Self::MergeResult { + EitherOrBoth::Left(left) + } + fn right(right: R) -> Self::MergeResult { + EitherOrBoth::Right(right) + } + fn merge(&mut self, left: L, right: R) -> (Option>, Self::MergeResult) { + match self.0(&left, &right) { + Ordering::Equal => (None, EitherOrBoth::Both(left, right)), + Ordering::Less => (Some(Either::Right(right)), EitherOrBoth::Left(left)), + Ordering::Greater => (Some(Either::Left(left)), EitherOrBoth::Right(right)), + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + let (a_lower, a_upper) = left; + let (b_lower, b_upper) = right; + let lower = ::std::cmp::max(a_lower, b_lower); + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + (lower, upper) + } +} + +impl bool> OrderingOrBool for MergeFuncLR { + type MergeResult = Either; + fn left(left: L) -> Self::MergeResult { + Either::Left(left) + } + fn right(right: R) -> Self::MergeResult { + Either::Right(right) + } + fn merge(&mut self, left: L, right: R) -> (Option>, Self::MergeResult) { + if self.0(&left, &right) { + (Some(Either::Right(right)), Either::Left(left)) + } else { + (Some(Either::Left(left)), Either::Right(right)) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } +} + +impl bool> OrderingOrBool for F { + type MergeResult = T; + fn left(left: T) -> Self::MergeResult { + left + } + fn right(right: T) -> Self::MergeResult { + right + } + fn merge(&mut self, left: T, right: T) -> (Option>, Self::MergeResult) { + if self(&left, &right) { + (Some(Either::Right(right)), left) + } else { + (Some(Either::Left(left)), right) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } +} + +impl OrderingOrBool for MergeLte { + type MergeResult = T; + fn left(left: T) -> Self::MergeResult { + left + } + fn right(right: T) -> Self::MergeResult { + right + } + fn merge(&mut self, left: T, right: T) -> (Option>, Self::MergeResult) { + if left <= right { + (Some(Either::Right(right)), left) + } else { + (Some(Either::Left(left)), right) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } +} + +impl Clone for MergeBy +where + I: Iterator, + J: Iterator, + PutBack>: Clone, + PutBack>: Clone, + F: Clone, { clone_fields!(left, right, cmp_fn); } -impl fmt::Debug for MergeJoinBy - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, - J: Iterator + fmt::Debug, - J::Item: fmt::Debug, +impl fmt::Debug for MergeBy +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + J: Iterator + fmt::Debug, + J::Item: fmt::Debug, { - debug_fmt_fields!(MergeJoinBy, left, right); + debug_fmt_fields!(MergeBy, left, right); } -impl Iterator for MergeJoinBy - where I: Iterator, - J: Iterator, - F: FnMut(&I::Item, &J::Item) -> Ordering +impl Iterator for MergeBy +where + I: Iterator, + J: Iterator, + F: OrderingOrBool, { - type Item = EitherOrBoth; + type Item = F::MergeResult; fn next(&mut self) -> Option { match (self.left.next(), self.right.next()) { (None, None) => None, - (Some(left), None) => - Some(EitherOrBoth::Left(left)), - (None, Some(right)) => - Some(EitherOrBoth::Right(right)), + (Some(left), None) => Some(F::left(left)), + (None, Some(right)) => Some(F::right(right)), (Some(left), Some(right)) => { - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => - Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - }, - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) + let (not_next, next) = self.cmp_fn.merge(left, right); + match not_next { + Some(Either::Left(l)) => { + self.left.put_back(l); + } + Some(Either::Right(r)) => { + self.right.put_back(r); } + None => (), } + + Some(next) } } } - fn size_hint(&self) -> (usize, Option) { - let (a_lower, a_upper) = self.left.size_hint(); - let (b_lower, b_upper) = self.right.size_hint(); - - let lower = ::std::cmp::max(a_lower, b_lower); + fn fold(mut self, init: B, mut f: G) -> B + where + Self: Sized, + G: FnMut(B, Self::Item) -> B, + { + let mut acc = init; + let mut left = self.left.next(); + let mut right = self.right.next(); - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None, - }; - - (lower, upper) - } - - fn count(mut self) -> usize { - let mut count = 0; loop { - match (self.left.next(), self.right.next()) { - (None, None) => break count, - (Some(_left), None) => break count + 1 + self.left.into_parts().1.count(), - (None, Some(_right)) => break count + 1 + self.right.into_parts().1.count(), - (Some(left), Some(right)) => { - count += 1; - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => {} - Ordering::Less => self.right.put_back(right), - Ordering::Greater => self.left.put_back(left), + match (left, right) { + (Some(l), Some(r)) => match self.cmp_fn.merge(l, r) { + (Some(Either::Right(r)), x) => { + acc = f(acc, x); + left = self.left.next(); + right = Some(r); } + (Some(Either::Left(l)), x) => { + acc = f(acc, x); + left = Some(l); + right = self.right.next(); + } + (None, x) => { + acc = f(acc, x); + left = self.left.next(); + right = self.right.next(); + } + }, + (Some(l), None) => { + self.left.put_back(l); + acc = self.left.fold(acc, |acc, x| f(acc, F::left(x))); + break; } - } - } - } - - fn last(mut self) -> Option { - let mut previous_element = None; - loop { - match (self.left.next(), self.right.next()) { - (None, None) => break previous_element, - (Some(left), None) => { - break Some(EitherOrBoth::Left( - self.left.into_parts().1.last().unwrap_or(left), - )) - } - (None, Some(right)) => { - break Some(EitherOrBoth::Right( - self.right.into_parts().1.last().unwrap_or(right), - )) + (None, Some(r)) => { + self.right.put_back(r); + acc = self.right.fold(acc, |acc, x| f(acc, F::right(x))); + break; } - (Some(left), Some(right)) => { - previous_element = match (self.cmp_fn)(&left, &right) { - Ordering::Equal => Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - } - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) - } - } + (None, None) => { + break; } } } + + acc + } + + fn size_hint(&self) -> SizeHint { + F::size_hint(self.left.size_hint(), self.right.size_hint()) } fn nth(&mut self, mut n: usize) -> Option { @@ -156,14 +320,29 @@ n -= 1; match (self.left.next(), self.right.next()) { (None, None) => break None, - (Some(_left), None) => break self.left.nth(n).map(EitherOrBoth::Left), - (None, Some(_right)) => break self.right.nth(n).map(EitherOrBoth::Right), - (Some(left), Some(right)) => match (self.cmp_fn)(&left, &right) { - Ordering::Equal => {} - Ordering::Less => self.right.put_back(right), - Ordering::Greater => self.left.put_back(left), - }, + (Some(_left), None) => break self.left.nth(n).map(F::left), + (None, Some(_right)) => break self.right.nth(n).map(F::right), + (Some(left), Some(right)) => { + let (not_next, _) = self.cmp_fn.merge(left, right); + match not_next { + Some(Either::Left(l)) => { + self.left.put_back(l); + } + Some(Either::Right(r)) => { + self.right.put_back(r); + } + None => (), + } + } } } } } + +impl FusedIterator for MergeBy +where + I: Iterator, + J: Iterator, + F: OrderingOrBool, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/minmax.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/minmax.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/minmax.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/minmax.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,7 @@ - /// `MinMaxResult` is an enum returned by `minmax`. /// /// See [`.minmax()`](crate::Itertools::minmax) for more detail. -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum MinMaxResult { /// Empty iterator NoElements, @@ -12,7 +11,7 @@ /// More than one element in the iterator, the first element is not larger /// than the second - MinMax(T, T) + MinMax(T, T), } impl MinMaxResult { @@ -36,34 +35,36 @@ /// let r = MinMax(1, 2); /// assert_eq!(r.into_option(), Some((1, 2))); /// ``` - pub fn into_option(self) -> Option<(T,T)> { + pub fn into_option(self) -> Option<(T, T)> { match self { - MinMaxResult::NoElements => None, - MinMaxResult::OneElement(x) => Some((x.clone(), x)), - MinMaxResult::MinMax(x, y) => Some((x, y)) + Self::NoElements => None, + Self::OneElement(x) => Some((x.clone(), x)), + Self::MinMax(x, y) => Some((x, y)), } } } /// Implementation guts for `minmax` and `minmax_by_key`. -pub fn minmax_impl(mut it: I, mut key_for: F, - mut lt: L) -> MinMaxResult - where I: Iterator, - F: FnMut(&I::Item) -> K, - L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, +pub fn minmax_impl(mut it: I, mut key_for: F, mut lt: L) -> MinMaxResult +where + I: Iterator, + F: FnMut(&I::Item) -> K, + L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, { let (mut min, mut max, mut min_key, mut max_key) = match it.next() { None => return MinMaxResult::NoElements, - Some(x) => { - match it.next() { - None => return MinMaxResult::OneElement(x), - Some(y) => { - let xk = key_for(&x); - let yk = key_for(&y); - if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} + Some(x) => match it.next() { + None => return MinMaxResult::OneElement(x), + Some(y) => { + let xk = key_for(&x); + let yk = key_for(&y); + if !lt(&y, &x, &yk, &xk) { + (x, y, xk, yk) + } else { + (y, x, yk, xk) } } - } + }, }; loop { @@ -74,7 +75,7 @@ // for 2 elements. let first = match it.next() { None => break, - Some(x) => x + Some(x) => x, }; let second = match it.next() { None => { @@ -86,7 +87,7 @@ } break; } - Some(x) => x + Some(x) => x, }; let first_key = key_for(&first); let second_key = key_for(&second); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/multipeek_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/multipeek_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/multipeek_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/multipeek_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,16 @@ -use std::iter::Fuse; -use alloc::collections::VecDeque; use crate::size_hint; -use crate::PeekingNext; #[cfg(doc)] use crate::Itertools; +use crate::PeekingNext; +use alloc::collections::VecDeque; +use std::iter::Fuse; /// See [`multipeek()`] for more information. #[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct MultiPeek - where I: Iterator +where + I: Iterator, { iter: Fuse, buf: VecDeque, @@ -20,7 +22,8 @@ /// /// [`IntoIterator`] enabled version of [`Itertools::multipeek`]. pub fn multipeek(iterable: I) -> MultiPeek - where I: IntoIterator +where + I: IntoIterator, { MultiPeek { iter: iterable.into_iter().fuse(), @@ -30,7 +33,8 @@ } impl MultiPeek - where I: Iterator +where + I: Iterator, { /// Reset the peeking “cursor” pub fn reset_peek(&mut self) { @@ -62,24 +66,31 @@ } impl PeekingNext for MultiPeek - where I: Iterator, +where + I: Iterator, { fn peeking_next(&mut self, accept: F) -> Option - where F: FnOnce(&Self::Item) -> bool + where + F: FnOnce(&Self::Item) -> bool, { if self.buf.is_empty() { if let Some(r) = self.peek() { - if !accept(r) { return None } + if !accept(r) { + return None; + } + } + } else if let Some(r) = self.buf.front() { + if !accept(r) { + return None; } - } else if let Some(r) = self.buf.get(0) { - if !accept(r) { return None } } self.next() } } impl Iterator for MultiPeek - where I: Iterator +where + I: Iterator, { type Item = I::Item; @@ -91,11 +102,15 @@ fn size_hint(&self) -> (usize, Option) { size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + init = self.buf.into_iter().fold(init, &mut f); + self.iter.fold(init, f) + } } // Same size -impl ExactSizeIterator for MultiPeek - where I: ExactSizeIterator -{} - - +impl ExactSizeIterator for MultiPeek where I: ExactSizeIterator {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/next_array.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/next_array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/next_array.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/next_array.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,269 @@ +use core::mem::{self, MaybeUninit}; + +/// An array of at most `N` elements. +struct ArrayBuilder { + /// The (possibly uninitialized) elements of the `ArrayBuilder`. + /// + /// # Safety + /// + /// The elements of `arr[..len]` are valid `T`s. + arr: [MaybeUninit; N], + + /// The number of leading elements of `arr` that are valid `T`s, len <= N. + len: usize, +} + +impl ArrayBuilder { + /// Initializes a new, empty `ArrayBuilder`. + pub fn new() -> Self { + // SAFETY: The safety invariant of `arr` trivially holds for `len = 0`. + Self { + arr: [(); N].map(|_| MaybeUninit::uninit()), + len: 0, + } + } + + /// Pushes `value` onto the end of the array. + /// + /// # Panics + /// + /// This panics if `self.len >= N`. + #[inline(always)] + pub fn push(&mut self, value: T) { + // PANICS: This will panic if `self.len >= N`. + let place = &mut self.arr[self.len]; + // SAFETY: The safety invariant of `self.arr` applies to elements at + // indices `0..self.len` — not to the element at `self.len`. Writing to + // the element at index `self.len` therefore does not violate the safety + // invariant of `self.arr`. Even if this line panics, we have not + // created any intermediate invalid state. + *place = MaybeUninit::new(value); + // Lemma: `self.len < N`. By invariant, `self.len <= N`. Above, we index + // into `self.arr`, which has size `N`, at index `self.len`. If `self.len == N` + // at that point, that index would be out-of-bounds, and the index + // operation would panic. Thus, `self.len != N`, and since `self.len <= N`, + // that means that `self.len < N`. + // + // PANICS: Since `self.len < N`, and since `N <= usize::MAX`, + // `self.len + 1 <= usize::MAX`, and so `self.len += 1` will not + // overflow. Overflow is the only panic condition of `+=`. + // + // SAFETY: + // - We are required to uphold the invariant that `self.len <= N`. + // Since, by the preceding lemma, `self.len < N` at this point in the + // code, `self.len += 1` results in `self.len <= N`. + // - We are required to uphold the invariant that `self.arr[..self.len]` + // are valid instances of `T`. Since this invariant already held when + // this method was called, and since we only increment `self.len` + // by 1 here, we only need to prove that the element at + // `self.arr[self.len]` (using the value of `self.len` before incrementing) + // is valid. Above, we construct `place` to point to `self.arr[self.len]`, + // and then initialize `*place` to `MaybeUninit::new(value)`, which is + // a valid `T` by construction. + self.len += 1; + } + + /// Consumes the elements in the `ArrayBuilder` and returns them as an array + /// `[T; N]`. + /// + /// If `self.len() < N`, this returns `None`. + pub fn take(&mut self) -> Option<[T; N]> { + if self.len == N { + // SAFETY: Decreasing the value of `self.len` cannot violate the + // safety invariant on `self.arr`. + self.len = 0; + + // SAFETY: Since `self.len` is 0, `self.arr` may safely contain + // uninitialized elements. + let arr = mem::replace(&mut self.arr, [(); N].map(|_| MaybeUninit::uninit())); + + Some(arr.map(|v| { + // SAFETY: We know that all elements of `arr` are valid because + // we checked that `len == N`. + unsafe { v.assume_init() } + })) + } else { + None + } + } +} + +impl AsMut<[T]> for ArrayBuilder { + fn as_mut(&mut self) -> &mut [T] { + let valid = &mut self.arr[..self.len]; + // SAFETY: By invariant on `self.arr`, the elements of `self.arr` at + // indices `0..self.len` are in a valid state. Since `valid` references + // only these elements, the safety precondition of + // `slice_assume_init_mut` is satisfied. + unsafe { slice_assume_init_mut(valid) } + } +} + +impl Drop for ArrayBuilder { + // We provide a non-trivial `Drop` impl, because the trivial impl would be a + // no-op; `MaybeUninit` has no innate awareness of its own validity, and + // so it can only forget its contents. By leveraging the safety invariant of + // `self.arr`, we do know which elements of `self.arr` are valid, and can + // selectively run their destructors. + fn drop(&mut self) { + // SAFETY: + // - by invariant on `&mut [T]`, `self.as_mut()` is: + // - valid for reads and writes + // - properly aligned + // - non-null + // - the dropped `T` are valid for dropping; they do not have any + // additional library invariants that we've violated + // - no other pointers to `valid` exist (since we're in the context of + // `drop`) + unsafe { core::ptr::drop_in_place(self.as_mut()) } + } +} + +/// Assuming all the elements are initialized, get a mutable slice to them. +/// +/// # Safety +/// +/// The caller guarantees that the elements `T` referenced by `slice` are in a +/// valid state. +unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &mut [T] { + // SAFETY: Casting `&mut [MaybeUninit]` to `&mut [T]` is sound, because + // `MaybeUninit` is guaranteed to have the same size, alignment and ABI + // as `T`, and because the caller has guaranteed that `slice` is in the + // valid state. + unsafe { &mut *(slice as *mut [MaybeUninit] as *mut [T]) } +} + +/// Equivalent to `it.next_array()`. +pub(crate) fn next_array(it: &mut I) -> Option<[I::Item; N]> +where + I: Iterator, +{ + let mut builder = ArrayBuilder::new(); + for _ in 0..N { + builder.push(it.next()?); + } + builder.take() +} + +#[cfg(test)] +mod test { + use super::ArrayBuilder; + + #[test] + fn zero_len_take() { + let mut builder = ArrayBuilder::<(), 0>::new(); + let taken = builder.take(); + assert_eq!(taken, Some([(); 0])); + } + + #[test] + #[should_panic] + fn zero_len_push() { + let mut builder = ArrayBuilder::<(), 0>::new(); + builder.push(()); + } + + #[test] + fn push_4() { + let mut builder = ArrayBuilder::<(), 4>::new(); + assert_eq!(builder.take(), None); + + builder.push(()); + assert_eq!(builder.take(), None); + + builder.push(()); + assert_eq!(builder.take(), None); + + builder.push(()); + assert_eq!(builder.take(), None); + + builder.push(()); + assert_eq!(builder.take(), Some([(); 4])); + } + + #[test] + fn tracked_drop() { + use std::panic::{catch_unwind, AssertUnwindSafe}; + use std::sync::atomic::{AtomicU16, Ordering}; + + static DROPPED: AtomicU16 = AtomicU16::new(0); + + #[derive(Debug, PartialEq)] + struct TrackedDrop; + + impl Drop for TrackedDrop { + fn drop(&mut self) { + DROPPED.fetch_add(1, Ordering::Relaxed); + } + } + + { + let builder = ArrayBuilder::::new(); + assert_eq!(DROPPED.load(Ordering::Relaxed), 0); + drop(builder); + assert_eq!(DROPPED.load(Ordering::Relaxed), 0); + } + + { + let mut builder = ArrayBuilder::::new(); + builder.push(TrackedDrop); + assert_eq!(builder.take(), None); + assert_eq!(DROPPED.load(Ordering::Relaxed), 0); + drop(builder); + assert_eq!(DROPPED.swap(0, Ordering::Relaxed), 1); + } + + { + let mut builder = ArrayBuilder::::new(); + builder.push(TrackedDrop); + builder.push(TrackedDrop); + assert!(matches!(builder.take(), Some(_))); + assert_eq!(DROPPED.swap(0, Ordering::Relaxed), 2); + drop(builder); + assert_eq!(DROPPED.load(Ordering::Relaxed), 0); + } + + { + let mut builder = ArrayBuilder::::new(); + + builder.push(TrackedDrop); + builder.push(TrackedDrop); + + assert!(catch_unwind(AssertUnwindSafe(|| { + builder.push(TrackedDrop); + })) + .is_err()); + + assert_eq!(DROPPED.load(Ordering::Relaxed), 1); + + drop(builder); + + assert_eq!(DROPPED.swap(0, Ordering::Relaxed), 3); + } + + { + let mut builder = ArrayBuilder::::new(); + + builder.push(TrackedDrop); + builder.push(TrackedDrop); + + assert!(catch_unwind(AssertUnwindSafe(|| { + builder.push(TrackedDrop); + })) + .is_err()); + + assert_eq!(DROPPED.load(Ordering::Relaxed), 1); + + assert!(matches!(builder.take(), Some(_))); + + assert_eq!(DROPPED.load(Ordering::Relaxed), 3); + + builder.push(TrackedDrop); + builder.push(TrackedDrop); + + assert!(matches!(builder.take(), Some(_))); + + assert_eq!(DROPPED.swap(0, Ordering::Relaxed), 5); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/pad_tail.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/pad_tail.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/pad_tail.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/pad_tail.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -use std::iter::{Fuse, FusedIterator}; use crate::size_hint; +use std::iter::{Fuse, FusedIterator}; /// An iterator adaptor that pads a sequence to a minimum length by filling /// missing elements using a closure. @@ -25,8 +25,9 @@ /// Create a new `PadUsing` iterator. pub fn pad_using(iter: I, min: usize, filler: F) -> PadUsing - where I: Iterator, - F: FnMut(usize) -> I::Item +where + I: Iterator, + F: FnMut(usize) -> I::Item, { PadUsing { iter: iter.fuse(), @@ -37,8 +38,9 @@ } impl Iterator for PadUsing - where I: Iterator, - F: FnMut(usize) -> I::Item +where + I: Iterator, + F: FnMut(usize) -> I::Item, { type Item = I::Item; @@ -53,7 +55,7 @@ } else { None } - }, + } e => { self.pos += 1; e @@ -65,11 +67,24 @@ let tail = self.min.saturating_sub(self.pos); size_hint::max(self.iter.size_hint(), (tail, Some(tail))) } + + fn fold(self, mut init: B, mut f: G) -> B + where + G: FnMut(B, Self::Item) -> B, + { + let mut pos = self.pos; + init = self.iter.fold(init, |acc, item| { + pos += 1; + f(acc, item) + }); + (pos..self.min).map(self.filler).fold(init, f) + } } impl DoubleEndedIterator for PadUsing - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(usize) -> I::Item +where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(usize) -> I::Item, { fn next_back(&mut self) -> Option { if self.min == 0 { @@ -82,15 +97,28 @@ Some((self.filler)(self.min)) } } + + fn rfold(self, mut init: B, mut f: G) -> B + where + G: FnMut(B, Self::Item) -> B, + { + init = (self.iter.len()..self.min) + .map(self.filler) + .rfold(init, &mut f); + self.iter.rfold(init, f) + } } impl ExactSizeIterator for PadUsing - where I: ExactSizeIterator, - F: FnMut(usize) -> I::Item -{} - +where + I: ExactSizeIterator, + F: FnMut(usize) -> I::Item, +{ +} impl FusedIterator for PadUsing - where I: FusedIterator, - F: FnMut(usize) -> I::Item -{} +where + I: FusedIterator, + F: FnMut(usize) -> I::Item, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/peek_nth.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peek_nth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/peek_nth.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peek_nth.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,6 +5,7 @@ /// See [`peek_nth()`] for more information. #[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct PeekNth where I: Iterator, @@ -34,30 +35,35 @@ where I: Iterator, { - /// Works exactly like the `peek` method in `std::iter::Peekable` + /// Works exactly like the `peek` method in [`std::iter::Peekable`]. pub fn peek(&mut self) -> Option<&I::Item> { self.peek_nth(0) } + /// Works exactly like the `peek_mut` method in [`std::iter::Peekable`]. + pub fn peek_mut(&mut self) -> Option<&mut I::Item> { + self.peek_nth_mut(0) + } + /// Returns a reference to the `nth` value without advancing the iterator. /// /// # Examples /// /// Basic usage: /// - /// ```rust + /// ``` /// use itertools::peek_nth; /// - /// let xs = vec![1,2,3]; - /// let mut iter = peek_nth(xs.iter()); + /// let xs = vec![1, 2, 3]; + /// let mut iter = peek_nth(xs.into_iter()); /// - /// assert_eq!(iter.peek_nth(0), Some(&&1)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.peek_nth(0), Some(&1)); + /// assert_eq!(iter.next(), Some(1)); /// /// // The iterator does not advance even if we call `peek_nth` multiple times - /// assert_eq!(iter.peek_nth(0), Some(&&2)); - /// assert_eq!(iter.peek_nth(1), Some(&&3)); - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.peek_nth(0), Some(&2)); + /// assert_eq!(iter.peek_nth(1), Some(&3)); + /// assert_eq!(iter.next(), Some(2)); /// /// // Calling `peek_nth` past the end of the iterator will return `None` /// assert_eq!(iter.peek_nth(1), None); @@ -69,6 +75,68 @@ self.buf.get(n) } + + /// Returns a mutable reference to the `nth` value without advancing the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use itertools::peek_nth; + /// + /// let xs = vec![1, 2, 3, 4, 5]; + /// let mut iter = peek_nth(xs.into_iter()); + /// + /// assert_eq!(iter.peek_nth_mut(0), Some(&mut 1)); + /// assert_eq!(iter.next(), Some(1)); + /// + /// // The iterator does not advance even if we call `peek_nth_mut` multiple times + /// assert_eq!(iter.peek_nth_mut(0), Some(&mut 2)); + /// assert_eq!(iter.peek_nth_mut(1), Some(&mut 3)); + /// assert_eq!(iter.next(), Some(2)); + /// + /// // Peek into the iterator and set the value behind the mutable reference. + /// if let Some(p) = iter.peek_nth_mut(1) { + /// assert_eq!(*p, 4); + /// *p = 9; + /// } + /// + /// // The value we put in reappears as the iterator continues. + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(9)); + /// + /// // Calling `peek_nth_mut` past the end of the iterator will return `None` + /// assert_eq!(iter.peek_nth_mut(1), None); + /// ``` + pub fn peek_nth_mut(&mut self, n: usize) -> Option<&mut I::Item> { + let unbuffered_items = (n + 1).saturating_sub(self.buf.len()); + + self.buf.extend(self.iter.by_ref().take(unbuffered_items)); + + self.buf.get_mut(n) + } + + /// Works exactly like the `next_if` method in [`std::iter::Peekable`]. + pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option { + match self.next() { + Some(item) if func(&item) => Some(item), + Some(item) => { + self.buf.push_front(item); + None + } + _ => None, + } + } + + /// Works exactly like the `next_if_eq` method in [`std::iter::Peekable`]. + pub fn next_if_eq(&mut self, expected: &T) -> Option + where + T: ?Sized, + I::Item: PartialEq, + { + self.next_if(|next| next == expected) + } } impl Iterator for PeekNth @@ -84,6 +152,14 @@ fn size_hint(&self) -> (usize, Option) { size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + init = self.buf.into_iter().fold(init, &mut f); + self.iter.fold(init, f) + } } impl ExactSizeIterator for PeekNth where I: ExactSizeIterator {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/peeking_take_while.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peeking_take_while.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/peeking_take_while.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/peeking_take_while.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,8 @@ -use std::iter::Peekable; use crate::PutBack; #[cfg(feature = "use_alloc")] use crate::PutBackN; +use crate::RepeatN; +use std::iter::Peekable; /// An iterator that allows peeking at an element before deciding to accept it. /// @@ -10,20 +11,36 @@ /// /// This is implemented by peeking adaptors like peekable and put back, /// but also by a few iterators that can be peeked natively, like the slice’s -/// by reference iterator (`std::slice::Iter`). -pub trait PeekingNext : Iterator { +/// by reference iterator ([`std::slice::Iter`]). +pub trait PeekingNext: Iterator { /// Pass a reference to the next iterator element to the closure `accept`; - /// if `accept` returns true, return it as the next element, - /// else None. + /// if `accept` returns `true`, return it as the next element, + /// else `None`. fn peeking_next(&mut self, accept: F) -> Option - where F: FnOnce(&Self::Item) -> bool; + where + Self: Sized, + F: FnOnce(&Self::Item) -> bool; +} + +impl PeekingNext for &mut I +where + I: PeekingNext, +{ + fn peeking_next(&mut self, accept: F) -> Option + where + F: FnOnce(&Self::Item) -> bool, + { + (*self).peeking_next(accept) + } } impl PeekingNext for Peekable - where I: Iterator, +where + I: Iterator, { fn peeking_next(&mut self, accept: F) -> Option - where F: FnOnce(&Self::Item) -> bool + where + F: FnOnce(&Self::Item) -> bool, { if let Some(r) = self.peek() { if !accept(r) { @@ -35,10 +52,12 @@ } impl PeekingNext for PutBack - where I: Iterator, +where + I: Iterator, { fn peeking_next(&mut self, accept: F) -> Option - where F: FnOnce(&Self::Item) -> bool + where + F: FnOnce(&Self::Item) -> bool, { if let Some(r) = self.next() { if !accept(&r) { @@ -54,10 +73,12 @@ #[cfg(feature = "use_alloc")] impl PeekingNext for PutBackN - where I: Iterator, +where + I: Iterator, { fn peeking_next(&mut self, accept: F) -> Option - where F: FnOnce(&Self::Item) -> bool + where + F: FnOnce(&Self::Item) -> bool, { if let Some(r) = self.next() { if !accept(&r) { @@ -71,39 +92,51 @@ } } +impl PeekingNext for RepeatN { + fn peeking_next(&mut self, accept: F) -> Option + where + F: FnOnce(&Self::Item) -> bool, + { + let r = self.elt.as_ref()?; + if !accept(r) { + return None; + } + self.next() + } +} + /// An iterator adaptor that takes items while a closure returns `true`. /// /// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while) /// for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct PeekingTakeWhile<'a, I: 'a, F> - where I: Iterator, +pub struct PeekingTakeWhile<'a, I, F> +where + I: Iterator + 'a, { iter: &'a mut I, f: F, } -impl<'a, I: 'a, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F> +impl<'a, I, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F> where - I: Iterator + std::fmt::Debug, + I: Iterator + std::fmt::Debug + 'a, { debug_fmt_fields!(PeekingTakeWhile, iter); } /// Create a `PeekingTakeWhile` pub fn peeking_take_while(iter: &mut I, f: F) -> PeekingTakeWhile - where I: Iterator, +where + I: Iterator, { - PeekingTakeWhile { - iter, - f, - } + PeekingTakeWhile { iter, f } } -impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> - where I: PeekingNext, - F: FnMut(&I::Item) -> bool, - +impl Iterator for PeekingTakeWhile<'_, I, F> +where + I: PeekingNext, + F: FnMut(&I::Item) -> bool, { type Item = I::Item; fn next(&mut self) -> Option { @@ -115,6 +148,20 @@ } } +impl PeekingNext for PeekingTakeWhile<'_, I, F> +where + I: PeekingNext, + F: FnMut(&I::Item) -> bool, +{ + fn peeking_next(&mut self, g: G) -> Option + where + G: FnOnce(&Self::Item) -> bool, + { + let f = &mut self.f; + self.iter.peeking_next(|r| f(r) && g(r)) + } +} + // Some iterators are so lightweight we can simply clone them to save their // state and use that for peeking. macro_rules! peeking_next_by_clone { @@ -151,4 +198,4 @@ // cloning a Rev has no extra overhead; peekable and put backs are never DEI. peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator] - ::std::iter::Rev } +::std::iter::Rev } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/permutations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/permutations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/permutations.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/permutations.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,11 @@ +use alloc::boxed::Box; use alloc::vec::Vec; use std::fmt; use std::iter::once; +use std::iter::FusedIterator; use super::lazy_buffer::LazyBuffer; +use crate::size_hint::{self, SizeHint}; /// An iterator adaptor that iterates through all the `k`-permutations of the /// elements from an iterator. @@ -16,262 +19,168 @@ } impl Clone for Permutations - where I: Clone + Iterator, - I::Item: Clone, +where + I: Clone + Iterator, + I::Item: Clone, { clone_fields!(vals, state); } #[derive(Clone, Debug)] enum PermutationState { - StartUnknownLen { - k: usize, - }, - OngoingUnknownLen { - k: usize, - min_n: usize, - }, - Complete(CompleteState), - Empty, -} - -#[derive(Clone, Debug)] -enum CompleteState { - Start { - n: usize, - k: usize, + /// No permutation generated yet. + Start { k: usize }, + /// Values from the iterator are not fully loaded yet so `n` is still unknown. + Buffered { k: usize, min_n: usize }, + /// All values from the iterator are known so `n` is known. + Loaded { + indices: Box<[usize]>, + cycles: Box<[usize]>, }, - Ongoing { - indices: Vec, - cycles: Vec, - } -} - -enum CompleteStateRemaining { - Known(usize), - Overflow, + /// No permutation left to generate. + End, } impl fmt::Debug for Permutations - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, { debug_fmt_fields!(Permutations, vals, state); } pub fn permutations(iter: I, k: usize) -> Permutations { - let mut vals = LazyBuffer::new(iter); - - if k == 0 { - // Special case, yields single empty vec; `n` is irrelevant - let state = PermutationState::Complete(CompleteState::Start { n: 0, k: 0 }); - - return Permutations { - vals, - state - }; - } - - let mut enough_vals = true; - - while vals.len() < k { - if !vals.get_next() { - enough_vals = false; - break; - } - } - - let state = if enough_vals { - PermutationState::StartUnknownLen { k } - } else { - PermutationState::Empty - }; - Permutations { - vals, - state + vals: LazyBuffer::new(iter), + state: PermutationState::Start { k }, } } impl Iterator for Permutations where I: Iterator, - I::Item: Clone + I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { - self.advance(); - - let &mut Permutations { ref vals, ref state } = self; - - match *state { - PermutationState::StartUnknownLen { .. } => panic!("unexpected iterator state"), - PermutationState::OngoingUnknownLen { k, min_n } => { - let latest_idx = min_n - 1; - let indices = (0..(k - 1)).chain(once(latest_idx)); - - Some(indices.map(|i| vals[i].clone()).collect()) + let Self { vals, state } = self; + match state { + PermutationState::Start { k: 0 } => { + *state = PermutationState::End; + Some(Vec::new()) + } + &mut PermutationState::Start { k } => { + vals.prefill(k); + if vals.len() != k { + *state = PermutationState::End; + return None; + } + *state = PermutationState::Buffered { k, min_n: k }; + Some(vals[0..k].to_vec()) + } + PermutationState::Buffered { ref k, min_n } => { + if vals.get_next() { + let item = (0..*k - 1) + .chain(once(*min_n)) + .map(|i| vals[i].clone()) + .collect(); + *min_n += 1; + Some(item) + } else { + let n = *min_n; + let prev_iteration_count = n - *k + 1; + let mut indices: Box<[_]> = (0..n).collect(); + let mut cycles: Box<[_]> = (n - k..n).rev().collect(); + // Advance the state to the correct point. + for _ in 0..prev_iteration_count { + if advance(&mut indices, &mut cycles) { + *state = PermutationState::End; + return None; + } + } + let item = vals.get_at(&indices[0..*k]); + *state = PermutationState::Loaded { indices, cycles }; + Some(item) + } } - PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => { + PermutationState::Loaded { indices, cycles } => { + if advance(indices, cycles) { + *state = PermutationState::End; + return None; + } let k = cycles.len(); - Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect()) - }, - PermutationState::Complete(CompleteState::Start { .. }) | PermutationState::Empty => None + Some(vals.get_at(&indices[0..k])) + } + PermutationState::End => None, } } fn count(self) -> usize { - fn from_complete(complete_state: CompleteState) -> usize { - match complete_state.remaining() { - CompleteStateRemaining::Known(count) => count, - CompleteStateRemaining::Overflow => { - panic!("Iterator count greater than usize::MAX"); - } - } - } - - let Permutations { vals, state } = self; - match state { - PermutationState::StartUnknownLen { k } => { - let n = vals.len() + vals.it.count(); - let complete_state = CompleteState::Start { n, k }; - - from_complete(complete_state) - } - PermutationState::OngoingUnknownLen { k, min_n } => { - let prev_iteration_count = min_n - k + 1; - let n = vals.len() + vals.it.count(); - let complete_state = CompleteState::Start { n, k }; - - from_complete(complete_state) - prev_iteration_count - }, - PermutationState::Complete(state) => from_complete(state), - PermutationState::Empty => 0 - } + let Self { vals, state } = self; + let n = vals.count(); + state.size_hint_for(n).1.unwrap() } - fn size_hint(&self) -> (usize, Option) { - match self.state { - PermutationState::StartUnknownLen { .. } | - PermutationState::OngoingUnknownLen { .. } => (0, None), // TODO can we improve this lower bound? - PermutationState::Complete(ref state) => match state.remaining() { - CompleteStateRemaining::Known(count) => (count, Some(count)), - CompleteStateRemaining::Overflow => (::std::usize::MAX, None) - } - PermutationState::Empty => (0, Some(0)) - } + fn size_hint(&self) -> SizeHint { + let (mut low, mut upp) = self.vals.size_hint(); + low = self.state.size_hint_for(low).0; + upp = upp.and_then(|n| self.state.size_hint_for(n).1); + (low, upp) } } -impl Permutations +impl FusedIterator for Permutations where I: Iterator, - I::Item: Clone + I::Item: Clone, { - fn advance(&mut self) { - let &mut Permutations { ref mut vals, ref mut state } = self; - - *state = match *state { - PermutationState::StartUnknownLen { k } => { - PermutationState::OngoingUnknownLen { k, min_n: k } - } - PermutationState::OngoingUnknownLen { k, min_n } => { - if vals.get_next() { - PermutationState::OngoingUnknownLen { k, min_n: min_n + 1 } - } else { - let n = min_n; - let prev_iteration_count = n - k + 1; - let mut complete_state = CompleteState::Start { n, k }; - - // Advance the complete-state iterator to the correct point - for _ in 0..(prev_iteration_count + 1) { - complete_state.advance(); - } - - PermutationState::Complete(complete_state) - } - } - PermutationState::Complete(ref mut state) => { - state.advance(); - - return; - } - PermutationState::Empty => { return; } - }; - } } -impl CompleteState { - fn advance(&mut self) { - *self = match *self { - CompleteState::Start { n, k } => { - let indices = (0..n).collect(); - let cycles = ((n - k)..n).rev().collect(); - - CompleteState::Ongoing { - cycles, - indices - } - }, - CompleteState::Ongoing { ref mut indices, ref mut cycles } => { - let n = indices.len(); - let k = cycles.len(); - - for i in (0..k).rev() { - if cycles[i] == 0 { - cycles[i] = n - i - 1; - - let to_push = indices.remove(i); - indices.push(to_push); - } else { - let swap_index = n - cycles[i]; - indices.swap(i, swap_index); - - cycles[i] -= 1; - return; - } - } - - CompleteState::Start { n, k } - } - } - } - - fn remaining(&self) -> CompleteStateRemaining { - use self::CompleteStateRemaining::{Known, Overflow}; - +fn advance(indices: &mut [usize], cycles: &mut [usize]) -> bool { + let n = indices.len(); + let k = cycles.len(); + // NOTE: if `cycles` are only zeros, then we reached the last permutation. + for i in (0..k).rev() { + if cycles[i] == 0 { + cycles[i] = n - i - 1; + indices[i..].rotate_left(1); + } else { + let swap_index = n - cycles[i]; + indices.swap(i, swap_index); + cycles[i] -= 1; + return false; + } + } + true +} + +impl PermutationState { + fn size_hint_for(&self, n: usize) -> SizeHint { + // At the beginning, there are `n!/(n-k)!` items to come. + let at_start = |n, k| { + debug_assert!(n >= k); + let total = (n - k + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i)); + (total.unwrap_or(usize::MAX), total) + }; match *self { - CompleteState::Start { n, k } => { - if n < k { - return Known(0); - } - - let count: Option = (n - k + 1..n + 1).fold(Some(1), |acc, i| { - acc.and_then(|acc| acc.checked_mul(i)) + Self::Start { k } if n < k => (0, Some(0)), + Self::Start { k } => at_start(n, k), + Self::Buffered { k, min_n } => { + // Same as `Start` minus the previously generated items. + size_hint::sub_scalar(at_start(n, k), min_n - k + 1) + } + Self::Loaded { + ref indices, + ref cycles, + } => { + let count = cycles.iter().enumerate().try_fold(0usize, |acc, (i, &c)| { + acc.checked_mul(indices.len() - i) + .and_then(|count| count.checked_add(c)) }); - - match count { - Some(count) => Known(count), - None => Overflow - } - } - CompleteState::Ongoing { ref indices, ref cycles } => { - let mut count: usize = 0; - - for (i, &c) in cycles.iter().enumerate() { - let radix = indices.len() - i; - let next_count = count.checked_mul(radix) - .and_then(|count| count.checked_add(c)); - - count = match next_count { - Some(count) => count, - None => { return Overflow; } - }; - } - - Known(count) + (count.unwrap_or(usize::MAX), count) } + Self::End => (0, Some(0)), } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/powerset.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/powerset.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/powerset.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/powerset.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,10 @@ +use alloc::vec::Vec; use std::fmt; use std::iter::FusedIterator; -use std::usize; -use alloc::vec::Vec; -use super::combinations::{Combinations, combinations}; -use super::size_hint; +use super::combinations::{combinations, Combinations}; +use crate::adaptors::checked_binomial; +use crate::size_hint::{self, SizeHint}; /// An iterator to iterate through the powerset of the elements from an iterator. /// @@ -13,78 +13,119 @@ #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Powerset { combs: Combinations, - // Iterator `position` (equal to count of yielded elements). - pos: usize, } impl Clone for Powerset - where I: Clone + Iterator, - I::Item: Clone, +where + I: Clone + Iterator, + I::Item: Clone, { - clone_fields!(combs, pos); + clone_fields!(combs); } impl fmt::Debug for Powerset - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, { - debug_fmt_fields!(Powerset, combs, pos); + debug_fmt_fields!(Powerset, combs); } /// Create a new `Powerset` from a clonable iterator. pub fn powerset(src: I) -> Powerset - where I: Iterator, - I::Item: Clone, +where + I: Iterator, + I::Item: Clone, { Powerset { combs: combinations(src, 0), - pos: 0, + } +} + +impl Powerset { + /// Returns true if `k` has been incremented, false otherwise. + fn increment_k(&mut self) -> bool { + if self.combs.k() < self.combs.n() || self.combs.k() == 0 { + self.combs.reset(self.combs.k() + 1); + true + } else { + false + } } } impl Iterator for Powerset - where - I: Iterator, - I::Item: Clone, +where + I: Iterator, + I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { if let Some(elt) = self.combs.next() { - self.pos = self.pos.saturating_add(1); Some(elt) - } else if self.combs.k() < self.combs.n() - || self.combs.k() == 0 - { - self.combs.reset(self.combs.k() + 1); - self.combs.next().map(|elt| { - self.pos = self.pos.saturating_add(1); - elt - }) + } else if self.increment_k() { + self.combs.next() } else { None } } - fn size_hint(&self) -> (usize, Option) { + fn nth(&mut self, mut n: usize) -> Option { + loop { + match self.combs.try_nth(n) { + Ok(item) => return Some(item), + Err(steps) => { + if !self.increment_k() { + return None; + } + n -= steps; + } + } + } + } + + fn size_hint(&self) -> SizeHint { + let k = self.combs.k(); // Total bounds for source iterator. - let src_total = size_hint::add_scalar(self.combs.src().size_hint(), self.combs.n()); + let (n_min, n_max) = self.combs.src().size_hint(); + let low = remaining_for(n_min, k).unwrap_or(usize::MAX); + let upp = n_max.and_then(|n| remaining_for(n, k)); + size_hint::add(self.combs.size_hint(), (low, upp)) + } - // Total bounds for self ( length(powerset(set) == 2 ^ length(set) ) - let self_total = size_hint::pow_scalar_base(2, src_total); + fn count(self) -> usize { + let k = self.combs.k(); + let (n, combs_count) = self.combs.n_and_count(); + combs_count + remaining_for(n, k).unwrap() + } - if self.pos < usize::MAX { - // Subtract count of elements already yielded from total. - size_hint::sub_scalar(self_total, self.pos) - } else { - // Fallback: self.pos is saturated and no longer reliable. - (0, self_total.1) + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut it = self.combs; + if it.k() == 0 { + init = it.by_ref().fold(init, &mut f); + it.reset(1); + } + init = it.by_ref().fold(init, &mut f); + // n is now known for sure because k >= 1 and all k-combinations have been generated. + for k in it.k() + 1..=it.n() { + it.reset(k); + init = it.by_ref().fold(init, &mut f); } + init } } impl FusedIterator for Powerset - where - I: Iterator, - I::Item: Clone, -{} +where + I: Iterator, + I::Item: Clone, +{ +} + +fn remaining_for(n: usize, k: usize) -> Option { + (k + 1..=n).try_fold(0usize, |sum, i| sum.checked_add(checked_binomial(n, i)?)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/process_results_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/process_results_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/process_results_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/process_results_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,5 @@ +#[cfg(doc)] +use crate::Itertools; /// An iterator that produces only the `T` values as long as the /// inner iterator produces `Ok(T)`. @@ -11,13 +13,10 @@ iter: I, } -impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> - where I: Iterator> -{ - type Item = T; - - fn next(&mut self) -> Option { - match self.iter.next() { +impl ProcessResults<'_, I, E> { + #[inline(always)] + fn next_body(&mut self, item: Option>) -> Option { + match item { Some(Ok(x)) => Some(x), Some(Err(e)) => { *self.error = Err(e); @@ -26,6 +25,18 @@ None => None, } } +} + +impl Iterator for ProcessResults<'_, I, E> +where + I: Iterator>, +{ + type Item = T; + + fn next(&mut self) -> Option { + let item = self.iter.next(); + self.next_body(item) + } fn size_hint(&self) -> (usize, Option) { (0, self.iter.size_hint().1) @@ -49,49 +60,49 @@ } } +impl DoubleEndedIterator for ProcessResults<'_, I, E> +where + I: Iterator>, + I: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + let item = self.iter.next_back(); + self.next_body(item) + } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let error = self.error; + self.iter + .try_rfold(init, |acc, opt| match opt { + Ok(x) => Ok(f(acc, x)), + Err(e) => { + *error = Err(e); + Err(acc) + } + }) + .unwrap_or_else(|e| e) + } +} + /// “Lift” a function of the values of an iterator so that it can process /// an iterator of `Result` values instead. /// -/// `iterable` is an iterator or iterable with `Result` elements, where -/// `T` is the value type and `E` the error type. -/// -/// `processor` is a closure that receives an adapted version of the iterable -/// as the only argument — the adapted iterator produces elements of type `T`, -/// as long as the original iterator produces `Ok` values. -/// -/// If the original iterable produces an error at any point, the adapted -/// iterator ends and the `process_results` function will return the -/// error iself. -/// -/// Otherwise, the return value from the closure is returned wrapped -/// inside `Ok`. -/// -/// # Example -/// -/// ``` -/// use itertools::process_results; -/// -/// type R = Result; -/// -/// let first_values: Vec = vec![Ok(1), Ok(0), Ok(3)]; -/// let second_values: Vec = vec![Ok(2), Ok(1), Err("overflow")]; -/// -/// // “Lift” the iterator .max() method to work on the values in Results using process_results -/// -/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); -/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); -/// -/// assert_eq!(first_max, Ok(3)); -/// assert!(second_max.is_err()); -/// ``` +/// [`IntoIterator`] enabled version of [`Itertools::process_results`]. pub fn process_results(iterable: I, processor: F) -> Result - where I: IntoIterator>, - F: FnOnce(ProcessResults) -> R +where + I: IntoIterator>, + F: FnOnce(ProcessResults) -> R, { let iter = iterable.into_iter(); let mut error = Ok(()); - let result = processor(ProcessResults { error: &mut error, iter }); + let result = processor(ProcessResults { + error: &mut error, + iter, + }); error.map(|_| result) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/put_back_n_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/put_back_n_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/put_back_n_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/put_back_n_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,6 +7,7 @@ /// /// Iterator element type is `I::Item`. #[derive(Debug, Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct PutBackN { top: Vec, iter: I, @@ -17,7 +18,8 @@ /// /// Iterator element type is `I::Item`. pub fn put_back_n(iterable: I) -> PutBackN - where I: IntoIterator +where + I: IntoIterator, { PutBackN { top: Vec::new(), @@ -26,7 +28,8 @@ } impl PutBackN { - /// Puts x in front of the iterator. + /// Puts `x` in front of the iterator. + /// /// The values are yielded in order of the most recently put back /// values first. /// @@ -57,5 +60,12 @@ fn size_hint(&self) -> (usize, Option) { size_hint::add_scalar(self.iter.size_hint(), self.top.len()) } -} + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + init = self.top.into_iter().rfold(init, &mut f); + self.iter.fold(init, f) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/rciter_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/rciter_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/rciter_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/rciter_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,10 @@ - -use std::iter::{FusedIterator, IntoIterator}; use alloc::rc::Rc; use std::cell::RefCell; +use std::iter::{FusedIterator, IntoIterator}; /// A wrapper for `Rc>`, that implements the `Iterator` trait. #[derive(Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct RcIter { /// The boxed iterator. pub rciter: Rc>, @@ -45,9 +45,12 @@ /// `.next()`, i.e. if it somehow participates in an “iterator knot” /// where it is an adaptor of itself. pub fn rciter(iterable: I) -> RcIter - where I: IntoIterator +where + I: IntoIterator, { - RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) } + RcIter { + rciter: Rc::new(RefCell::new(iterable.into_iter())), + } } impl Clone for RcIter { @@ -55,7 +58,8 @@ } impl Iterator for RcIter - where I: Iterator +where + I: Iterator, { type Item = A; #[inline] @@ -73,7 +77,8 @@ } impl DoubleEndedIterator for RcIter - where I: DoubleEndedIterator +where + I: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { @@ -82,8 +87,9 @@ } /// Return an iterator from `&RcIter` (by simply cloning it). -impl<'a, I> IntoIterator for &'a RcIter - where I: Iterator +impl IntoIterator for &RcIter +where + I: Iterator, { type Item = I::Item; type IntoIter = RcIter; @@ -93,7 +99,4 @@ } } - -impl FusedIterator for RcIter - where I: FusedIterator -{} +impl FusedIterator for RcIter where I: FusedIterator {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/repeatn.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/repeatn.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/repeatn.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/repeatn.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,23 +6,28 @@ #[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pub struct RepeatN { - elt: Option, + pub(crate) elt: Option, n: usize, } /// Create an iterator that produces `n` repetitions of `element`. pub fn repeat_n(element: A, n: usize) -> RepeatN - where A: Clone, +where + A: Clone, { if n == 0 { - RepeatN { elt: None, n, } + RepeatN { elt: None, n } } else { - RepeatN { elt: Some(element), n, } + RepeatN { + elt: Some(element), + n, + } } } impl Iterator for RepeatN - where A: Clone +where + A: Clone, { type Item = A; @@ -39,21 +44,40 @@ fn size_hint(&self) -> (usize, Option) { (self.n, Some(self.n)) } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + match self { + Self { elt: Some(elt), n } => { + debug_assert!(n > 0); + init = (1..n).map(|_| elt.clone()).fold(init, &mut f); + f(init, elt) + } + _ => init, + } + } } impl DoubleEndedIterator for RepeatN - where A: Clone +where + A: Clone, { #[inline] fn next_back(&mut self) -> Option { self.next() } + + #[inline] + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.fold(init, f) + } } -impl ExactSizeIterator for RepeatN - where A: Clone -{} - -impl FusedIterator for RepeatN - where A: Clone -{} +impl ExactSizeIterator for RepeatN where A: Clone {} + +impl FusedIterator for RepeatN where A: Clone {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/size_hint.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/size_hint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/size_hint.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/size_hint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,7 @@ //! Arithmetic on `Iterator.size_hint()` values. //! -use std::usize; use std::cmp; -use std::u32; /// `SizeHint` is the return type of `Iterator::size_hint()`. pub type SizeHint = (usize, Option); @@ -31,7 +29,6 @@ /// Subtract `x` correctly from a `SizeHint`. #[inline] -#[allow(dead_code)] pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { let (mut low, mut hi) = sh; low = low.saturating_sub(x); @@ -39,22 +36,7 @@ (low, hi) } - /// Multiply `SizeHint` correctly -/// -/// ```ignore -/// use std::usize; -/// use itertools::size_hint; -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))), -/// (9, Some(16))); -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)), -/// (usize::MAX, None)); -/// -/// assert_eq!(size_hint::mul((3, None), (0, Some(0))), -/// (0, Some(0))); -/// ``` #[inline] pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint { let low = a.0.saturating_mul(b.0); @@ -75,20 +57,6 @@ (low, hi) } -/// Raise `base` correctly by a `SizeHint` exponent. -#[inline] -pub fn pow_scalar_base(base: usize, exp: SizeHint) -> SizeHint { - let exp_low = cmp::min(exp.0, u32::MAX as usize) as u32; - let low = base.saturating_pow(exp_low); - - let hi = exp.1.and_then(|exp| { - let exp_hi = cmp::min(exp, u32::MAX as usize) as u32; - base.checked_pow(exp_hi) - }); - - (low, hi) -} - /// Return the maximum #[inline] pub fn max(a: SizeHint, b: SizeHint) -> SizeHint { @@ -117,3 +85,10 @@ }; (lower, upper) } + +#[test] +fn mul_size_hints() { + assert_eq!(mul((3, Some(4)), (3, Some(4))), (9, Some(16))); + assert_eq!(mul((3, Some(4)), (usize::MAX, None)), (usize::MAX, None)); + assert_eq!(mul((3, None), (0, Some(0))), (0, Some(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/sources.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/sources.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/sources.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/sources.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,62 +5,6 @@ use std::fmt; use std::mem; -/// See [`repeat_call`](crate::repeat_call) for more information. -#[derive(Clone)] -#[deprecated(note="Use std repeat_with() instead", since="0.8.0")] -pub struct RepeatCall { - f: F, -} - -impl fmt::Debug for RepeatCall -{ - debug_fmt_fields!(RepeatCall, ); -} - -/// An iterator source that produces elements indefinitely by calling -/// a given closure. -/// -/// Iterator element type is the return type of the closure. -/// -/// ``` -/// use itertools::repeat_call; -/// use itertools::Itertools; -/// use std::collections::BinaryHeap; -/// -/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); -/// -/// // extract each element in sorted order -/// for element in repeat_call(|| heap.pop()).while_some() { -/// print!("{}", element); -/// } -/// -/// itertools::assert_equal( -/// repeat_call(|| 1).take(5), -/// vec![1, 1, 1, 1, 1] -/// ); -/// ``` -#[deprecated(note="Use std repeat_with() instead", since="0.8.0")] -pub fn repeat_call(function: F) -> RepeatCall - where F: FnMut() -> A -{ - RepeatCall { f: function } -} - -impl Iterator for RepeatCall - where F: FnMut() -> A -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - Some((self.f)()) - } - - fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) - } -} - /// Creates a new unfold source with the specified closure as the "iterator /// function" and an initial state to eventually pass to the closure /// @@ -97,8 +41,13 @@ /// vec![1, 1, 2, 3, 5, 8, 13, 21]); /// assert_eq!(fibonacci.last(), Some(2_971_215_073)) /// ``` +#[deprecated( + note = "Use [std::iter::from_fn](https://doc.rust-lang.org/std/iter/fn.from_fn.html) instead", + since = "0.13.0" +)] pub fn unfold(initial_state: St, f: F) -> Unfold - where F: FnMut(&mut St) -> Option +where + F: FnMut(&mut St) -> Option, { Unfold { f, @@ -107,7 +56,8 @@ } impl fmt::Debug for Unfold - where St: fmt::Debug, +where + St: fmt::Debug, { debug_fmt_fields!(Unfold, state); } @@ -115,6 +65,10 @@ /// See [`unfold`](crate::unfold) for more information. #[derive(Clone)] #[must_use = "iterators are lazy and do nothing unless consumed"] +#[deprecated( + note = "Use [std::iter::FromFn](https://doc.rust-lang.org/std/iter/struct.FromFn.html) instead", + since = "0.13.0" +)] pub struct Unfold { f: F, /// Internal state that will be passed to the closure on the next iteration @@ -122,7 +76,8 @@ } impl Iterator for Unfold - where F: FnMut(&mut St) -> Option +where + F: FnMut(&mut St) -> Option, { type Item = A; @@ -144,13 +99,15 @@ } impl fmt::Debug for Iterate - where St: fmt::Debug, +where + St: fmt::Debug, { debug_fmt_fields!(Iterate, state); } impl Iterator for Iterate - where F: FnMut(&St) -> St +where + F: FnMut(&St) -> St, { type Item = St; @@ -162,7 +119,7 @@ #[inline] fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) + (usize::MAX, None) } } @@ -171,10 +128,23 @@ /// ``` /// use itertools::iterate; /// -/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); +/// itertools::assert_equal(iterate(1, |i| i % 3 + 1).take(5), vec![1, 2, 3, 1, 2]); /// ``` +/// +/// **Panics** if compute the next value does. +/// +/// ```should_panic +/// # use itertools::iterate; +/// let mut it = iterate(25u32, |x| x - 10).take_while(|&x| x > 10); +/// assert_eq!(it.next(), Some(25)); // `Iterate` holds 15. +/// assert_eq!(it.next(), Some(15)); // `Iterate` holds 5. +/// it.next(); // `5 - 10` overflows. +/// ``` +/// +/// You can alternatively use [`core::iter::successors`] as it better describes a finite iterator. pub fn iterate(initial_value: St, f: F) -> Iterate - where F: FnMut(&St) -> St +where + F: FnMut(&St) -> St, { Iterate { state: initial_value, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/take_while_inclusive.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/take_while_inclusive.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/take_while_inclusive.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/take_while_inclusive.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +use core::iter::FusedIterator; +use std::fmt; + +/// An iterator adaptor that consumes elements while the given predicate is +/// `true`, including the element for which the predicate first returned +/// `false`. +/// +/// See [`.take_while_inclusive()`](crate::Itertools::take_while_inclusive) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct TakeWhileInclusive { + iter: I, + predicate: F, + done: bool, +} + +impl TakeWhileInclusive +where + I: Iterator, + F: FnMut(&I::Item) -> bool, +{ + /// Create a new [`TakeWhileInclusive`] from an iterator and a predicate. + pub(crate) fn new(iter: I, predicate: F) -> Self { + Self { + iter, + predicate, + done: false, + } + } +} + +impl fmt::Debug for TakeWhileInclusive +where + I: Iterator + fmt::Debug, +{ + debug_fmt_fields!(TakeWhileInclusive, iter, done); +} + +impl Iterator for TakeWhileInclusive +where + I: Iterator, + F: FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + if self.done { + None + } else { + self.iter.next().map(|item| { + if !(self.predicate)(&item) { + self.done = true; + } + item + }) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.done { + (0, Some(0)) + } else { + (0, self.iter.size_hint().1) + } + } + + fn fold(mut self, init: B, mut f: Fold) -> B + where + Fold: FnMut(B, Self::Item) -> B, + { + if self.done { + init + } else { + let predicate = &mut self.predicate; + self.iter + .try_fold(init, |mut acc, item| { + let is_ok = predicate(&item); + acc = f(acc, item); + if is_ok { + Ok(acc) + } else { + Err(acc) + } + }) + .unwrap_or_else(|err| err) + } + } +} + +impl FusedIterator for TakeWhileInclusive +where + I: Iterator, + F: FnMut(&I::Item) -> bool, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/tee.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tee.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/tee.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tee.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,8 @@ use super::size_hint; -use std::cell::RefCell; use alloc::collections::VecDeque; use alloc::rc::Rc; +use std::cell::RefCell; /// Common buffer object for the two tee halves #[derive(Debug)] @@ -19,24 +19,37 @@ #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug)] pub struct Tee - where I: Iterator +where + I: Iterator, { rcbuffer: Rc>>, id: bool, } pub fn new(iter: I) -> (Tee, Tee) - where I: Iterator +where + I: Iterator, { - let buffer = TeeBuffer{backlog: VecDeque::new(), iter, owner: false}; - let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true}; - let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false}; + let buffer = TeeBuffer { + backlog: VecDeque::new(), + iter, + owner: false, + }; + let t1 = Tee { + rcbuffer: Rc::new(RefCell::new(buffer)), + id: true, + }; + let t2 = Tee { + rcbuffer: t1.rcbuffer.clone(), + id: false, + }; (t1, t2) } impl Iterator for Tee - where I: Iterator, - I::Item: Clone +where + I: Iterator, + I::Item: Clone, { type Item = I::Item; fn next(&mut self) -> Option { @@ -73,6 +86,8 @@ } impl ExactSizeIterator for Tee - where I: ExactSizeIterator, - I::Item: Clone -{} +where + I: ExactSizeIterator, + I::Item: Clone, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/tuple_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tuple_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/tuple_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/tuple_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,10 @@ //! Some iterator that produces tuples +use std::iter::Cycle; use std::iter::Fuse; use std::iter::FusedIterator; -use std::iter::Take; -use std::iter::Cycle; -use std::marker::PhantomData; + +use crate::size_hint; // `HomogeneousTuple` is a public facade for `TupleCollect`, allowing // tuple-related methods to be used by clients in generic contexts, while @@ -12,9 +12,7 @@ // See https://github.com/rust-itertools/itertools/issues/387 /// Implemented for homogeneous tuples of size up to 12. -pub trait HomogeneousTuple - : TupleCollect -{} +pub trait HomogeneousTuple: TupleCollect {} impl HomogeneousTuple for T {} @@ -24,25 +22,25 @@ /// [`Tuples::into_buffer()`]. #[derive(Clone, Debug)] pub struct TupleBuffer - where T: HomogeneousTuple +where + T: HomogeneousTuple, { cur: usize, buf: T::Buffer, } impl TupleBuffer - where T: HomogeneousTuple +where + T: HomogeneousTuple, { fn new(buf: T::Buffer) -> Self { - TupleBuffer { - cur: 0, - buf, - } + Self { cur: 0, buf } } } impl Iterator for TupleBuffer - where T: HomogeneousTuple +where + T: HomogeneousTuple, { type Item = T::Item; @@ -61,18 +59,16 @@ let len = if buffer.is_empty() { 0 } else { - buffer.iter() - .position(|x| x.is_none()) - .unwrap_or_else(|| buffer.len()) + buffer + .iter() + .position(|x| x.is_none()) + .unwrap_or(buffer.len()) }; (len, Some(len)) } } -impl ExactSizeIterator for TupleBuffer - where T: HomogeneousTuple -{ -} +impl ExactSizeIterator for TupleBuffer where T: HomogeneousTuple {} /// An iterator that groups the items in tuples of a specific size. /// @@ -80,8 +76,9 @@ #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Tuples - where I: Iterator, - T: HomogeneousTuple +where + I: Iterator, + T: HomogeneousTuple, { iter: Fuse, buf: T::Buffer, @@ -89,8 +86,9 @@ /// Create a new tuples iterator. pub fn tuples(iter: I) -> Tuples - where I: Iterator, - T: HomogeneousTuple +where + I: Iterator, + T: HomogeneousTuple, { Tuples { iter: iter.fuse(), @@ -99,19 +97,50 @@ } impl Iterator for Tuples - where I: Iterator, - T: HomogeneousTuple +where + I: Iterator, + T: HomogeneousTuple, { type Item = T; fn next(&mut self) -> Option { T::collect_from_iter(&mut self.iter, &mut self.buf) } + + fn size_hint(&self) -> (usize, Option) { + // The number of elts we've drawn from the underlying iterator, but have + // not yet produced as a tuple. + let buffered = T::buffer_len(&self.buf); + // To that, we must add the size estimates of the underlying iterator. + let (unbuffered_lo, unbuffered_hi) = self.iter.size_hint(); + // The total low estimate is the sum of the already-buffered elements, + // plus the low estimate of remaining unbuffered elements, divided by + // the tuple size. + let total_lo = add_then_div(unbuffered_lo, buffered, T::num_items()).unwrap_or(usize::MAX); + // And likewise for the total high estimate, but using the high estimate + // of the remaining unbuffered elements. + let total_hi = unbuffered_hi.and_then(|hi| add_then_div(hi, buffered, T::num_items())); + (total_lo, total_hi) + } +} + +/// `(n + a) / d` avoiding overflow when possible, returns `None` if it overflows. +fn add_then_div(n: usize, a: usize, d: usize) -> Option { + debug_assert_ne!(d, 0); + (n / d).checked_add(a / d)?.checked_add((n % d + a % d) / d) +} + +impl ExactSizeIterator for Tuples +where + I: ExactSizeIterator, + T: HomogeneousTuple, +{ } impl Tuples - where I: Iterator, - T: HomogeneousTuple +where + I: Iterator, + T: HomogeneousTuple, { /// Return a buffer with the produced items that was not enough to be grouped in a tuple. /// @@ -128,7 +157,6 @@ } } - /// An iterator over all contiguous windows that produces tuples of a specific size. /// /// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more @@ -136,125 +164,167 @@ #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pub struct TupleWindows - where I: Iterator, - T: HomogeneousTuple +where + I: Iterator, + T: HomogeneousTuple, { iter: I, last: Option, } /// Create a new tuple windows iterator. -pub fn tuple_windows(mut iter: I) -> TupleWindows - where I: Iterator, - T: HomogeneousTuple, - T::Item: Clone -{ - use std::iter::once; - - let mut last = None; - if T::num_items() != 1 { - // put in a duplicate item in front of the tuple; this simplifies - // .next() function. - if let Some(item) = iter.next() { - let iter = once(item.clone()).chain(once(item)).chain(&mut iter); - last = T::collect_from_iter_no_buf(iter); - } - } - - TupleWindows { - iter, - last, - } +pub fn tuple_windows(iter: I) -> TupleWindows +where + I: Iterator, + T: HomogeneousTuple, + T::Item: Clone, +{ + TupleWindows { last: None, iter } } impl Iterator for TupleWindows - where I: Iterator, - T: HomogeneousTuple + Clone, - T::Item: Clone +where + I: Iterator, + T: HomogeneousTuple + Clone, + T::Item: Clone, { type Item = T; fn next(&mut self) -> Option { if T::num_items() == 1 { - return T::collect_from_iter_no_buf(&mut self.iter) + return T::collect_from_iter_no_buf(&mut self.iter); } - if let Some(ref mut last) = self.last { - if let Some(new) = self.iter.next() { + if let Some(new) = self.iter.next() { + if let Some(ref mut last) = self.last { last.left_shift_push(new); - return Some(last.clone()); + Some(last.clone()) + } else { + use std::iter::once; + let iter = once(new).chain(&mut self.iter); + self.last = T::collect_from_iter_no_buf(iter); + self.last.clone() } + } else { + None } - None } + + fn size_hint(&self) -> (usize, Option) { + let mut sh = self.iter.size_hint(); + // Adjust the size hint at the beginning + // OR when `num_items == 1` (but it does not change the size hint). + if self.last.is_none() { + sh = size_hint::sub_scalar(sh, T::num_items() - 1); + } + sh + } +} + +impl ExactSizeIterator for TupleWindows +where + I: ExactSizeIterator, + T: HomogeneousTuple + Clone, + T::Item: Clone, +{ } impl FusedIterator for TupleWindows - where I: FusedIterator, - T: HomogeneousTuple + Clone, - T::Item: Clone -{} +where + I: FusedIterator, + T: HomogeneousTuple + Clone, + T::Item: Clone, +{ +} -/// An iterator over all windows,wrapping back to the first elements when the +/// An iterator over all windows, wrapping back to the first elements when the /// window would otherwise exceed the length of the iterator, producing tuples /// of a specific size. /// /// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more /// information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct CircularTupleWindows - where I: Iterator + Clone, - T: TupleCollect + Clone +#[derive(Debug, Clone)] +pub struct CircularTupleWindows +where + I: Iterator + Clone, + T: TupleCollect + Clone, { - iter: Take, T>>, - phantom_data: PhantomData + iter: TupleWindows, T>, + len: usize, } pub fn circular_tuple_windows(iter: I) -> CircularTupleWindows - where I: Iterator + Clone + ExactSizeIterator, - T: TupleCollect + Clone, - T::Item: Clone +where + I: Iterator + Clone + ExactSizeIterator, + T: TupleCollect + Clone, + T::Item: Clone, { let len = iter.len(); - let iter = tuple_windows(iter.cycle()).take(len); + let iter = tuple_windows(iter.cycle()); - CircularTupleWindows { - iter, - phantom_data: PhantomData{} - } + CircularTupleWindows { iter, len } } impl Iterator for CircularTupleWindows - where I: Iterator + Clone, - T: TupleCollect + Clone, - T::Item: Clone +where + I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone, { type Item = T; fn next(&mut self) -> Option { - self.iter.next() + if self.len != 0 { + self.len -= 1; + self.iter.next() + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) } } +impl ExactSizeIterator for CircularTupleWindows +where + I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone, +{ +} + +impl FusedIterator for CircularTupleWindows +where + I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone, +{ +} + pub trait TupleCollect: Sized { type Item; type Buffer: Default + AsRef<[Option]> + AsMut<[Option]>; + fn buffer_len(buf: &Self::Buffer) -> usize { + let s = buf.as_ref(); + s.iter().position(Option::is_none).unwrap_or(s.len()) + } + fn collect_from_iter(iter: I, buf: &mut Self::Buffer) -> Option - where I: IntoIterator; + where + I: IntoIterator; fn collect_from_iter_no_buf(iter: I) -> Option - where I: IntoIterator; + where + I: IntoIterator; fn num_items() -> usize; fn left_shift_push(&mut self, item: Self::Item); } -macro_rules! count_ident{ - () => {0}; - ($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)}; -} macro_rules! rev_for_each_ident{ ($m:ident, ) => {}; ($m:ident, $i0:ident, $($i:ident,)*) => { @@ -269,7 +339,7 @@ impl_tuple_collect!($($Y,)*); impl TupleCollect for ($(ignore_ident!($Y, A),)*) { type Item = A; - type Buffer = [Option; count_ident!($($Y,)*) - 1]; + type Buffer = [Option; count_ident!($($Y)*) - 1]; #[allow(unused_assignments, unused_mut)] fn collect_from_iter(iter: I, buf: &mut Self::Buffer) -> Option @@ -312,7 +382,7 @@ } fn num_items() -> usize { - count_ident!($($Y,)*) + count_ident!($($Y)*) } fn left_shift_push(&mut self, mut item: A) { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/unique_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unique_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/unique_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unique_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ -use std::collections::HashMap; use std::collections::hash_map::Entry; -use std::hash::Hash; +use std::collections::HashMap; use std::fmt; +use std::hash::Hash; use std::iter::FusedIterator; /// An iterator adapter to filter out duplicate elements. @@ -19,17 +19,19 @@ } impl fmt::Debug for UniqueBy - where I: Iterator + fmt::Debug, - V: fmt::Debug + Hash + Eq, +where + I: Iterator + fmt::Debug, + V: fmt::Debug + Hash + Eq, { debug_fmt_fields!(UniqueBy, iter, used); } /// Create a new `UniqueBy` iterator. pub fn unique_by(iter: I, f: F) -> UniqueBy - where V: Eq + Hash, - F: FnMut(&I::Item) -> V, - I: Iterator, +where + V: Eq + Hash, + F: FnMut(&I::Item) -> V, + I: Iterator, { UniqueBy { iter, @@ -40,8 +42,9 @@ // count the number of new unique keys in iterable (`used` is the set already seen) fn count_new_keys(mut used: HashMap, iterable: I) -> usize - where I: IntoIterator, - K: Hash + Eq, +where + I: IntoIterator, + K: Hash + Eq, { let iter = iterable.into_iter(); let current_used = used.len(); @@ -50,20 +53,16 @@ } impl Iterator for UniqueBy - where I: Iterator, - V: Eq + Hash, - F: FnMut(&I::Item) -> V +where + I: Iterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V, { type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.next() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.find(|v| used.insert(f(v), ()).is_none()) } #[inline] @@ -79,42 +78,42 @@ } impl DoubleEndedIterator for UniqueBy - where I: DoubleEndedIterator, - V: Eq + Hash, - F: FnMut(&I::Item) -> V +where + I: DoubleEndedIterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.next_back() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.rfind(|v| used.insert(f(v), ()).is_none()) } } impl FusedIterator for UniqueBy - where I: FusedIterator, - V: Eq + Hash, - F: FnMut(&I::Item) -> V -{} +where + I: FusedIterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V, +{ +} impl Iterator for Unique - where I: Iterator, - I::Item: Eq + Hash + Clone +where + I: Iterator, + I::Item: Eq + Hash + Clone, { type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.iter.next() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } #[inline] @@ -129,51 +128,61 @@ } impl DoubleEndedIterator for Unique - where I: DoubleEndedIterator, - I::Item: Eq + Hash + Clone +where + I: DoubleEndedIterator, + I::Item: Eq + Hash + Clone, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.iter.next_back() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.rev().find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } } impl FusedIterator for Unique - where I: FusedIterator, - I::Item: Eq + Hash + Clone -{} +where + I: FusedIterator, + I::Item: Eq + Hash + Clone, +{ +} /// An iterator adapter to filter out duplicate elements. /// /// See [`.unique()`](crate::Itertools::unique) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Unique { +pub struct Unique +where + I: Iterator, + I::Item: Eq + Hash + Clone, +{ iter: UniqueBy, } impl fmt::Debug for Unique - where I: Iterator + fmt::Debug, - I::Item: Hash + Eq + fmt::Debug, +where + I: Iterator + fmt::Debug, + I::Item: Hash + Eq + fmt::Debug + Clone, { debug_fmt_fields!(Unique, iter); } pub fn unique(iter: I) -> Unique - where I: Iterator, - I::Item: Eq + Hash, +where + I: Iterator, + I::Item: Eq + Hash + Clone, { Unique { iter: UniqueBy { iter, used: HashMap::new(), f: (), - } + }, } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/unziptuple.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unziptuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/unziptuple.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/unziptuple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,6 @@ /// Converts an iterator of tuples into a tuple of containers. /// -/// `unzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each +/// `multiunzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each /// column. /// /// This function is, in some sense, the opposite of [`multizip`]. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/with_position.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/with_position.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/with_position.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/with_position.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,28 +1,40 @@ -use std::iter::{Fuse,Peekable, FusedIterator}; +use std::fmt; +use std::iter::{Fuse, FusedIterator, Peekable}; /// An iterator adaptor that wraps each element in an [`Position`]. /// -/// Iterator element type is `Position`. +/// Iterator element type is `(Position, I::Item)`. /// /// See [`.with_position()`](crate::Itertools::with_position) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct WithPosition - where I: Iterator, +where + I: Iterator, { handled_first: bool, peekable: Peekable>, } +impl fmt::Debug for WithPosition +where + I: Iterator, + Peekable>: fmt::Debug, +{ + debug_fmt_fields!(WithPosition, handled_first, peekable); +} + impl Clone for WithPosition - where I: Clone + Iterator, - I::Item: Clone, +where + I: Clone + Iterator, + I::Item: Clone, { clone_fields!(handled_first, peekable); } /// Create a new `WithPosition` iterator. pub fn with_position(iter: I) -> WithPosition - where I: Iterator, +where + I: Iterator, { WithPosition { handled_first: false, @@ -30,36 +42,24 @@ } } -/// A value yielded by `WithPosition`. +/// The first component of the value yielded by `WithPosition`. /// Indicates the position of this element in the iterator results. /// /// See [`.with_position()`](crate::Itertools::with_position) for more information. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Position { +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Position { /// This is the first element. - First(T), + First, /// This is neither the first nor the last element. - Middle(T), + Middle, /// This is the last element. - Last(T), + Last, /// This is the only element. - Only(T), -} - -impl Position { - /// Return the inner value. - pub fn into_inner(self) -> T { - match self { - Position::First(x) | - Position::Middle(x) | - Position::Last(x) | - Position::Only(x) => x, - } - } + Only, } impl Iterator for WithPosition { - type Item = Position; + type Item = (Position, I::Item); fn next(&mut self) -> Option { match self.peekable.next() { @@ -70,15 +70,15 @@ // Peek to see if this is also the last item, // in which case tag it as `Only`. match self.peekable.peek() { - Some(_) => Some(Position::First(item)), - None => Some(Position::Only(item)), + Some(_) => Some((Position::First, item)), + None => Some((Position::Only, item)), } } else { // Have seen the first item, and there's something left. // Peek to see if this is the last item. match self.peekable.peek() { - Some(_) => Some(Position::Middle(item)), - None => Some(Position::Last(item)), + Some(_) => Some((Position::Middle, item)), + None => Some((Position::Last, item)), } } } @@ -90,11 +90,35 @@ fn size_hint(&self) -> (usize, Option) { self.peekable.size_hint() } + + fn fold(mut self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + if let Some(mut head) = self.peekable.next() { + if !self.handled_first { + // The current head is `First` or `Only`, + // it depends if there is another item or not. + match self.peekable.next() { + Some(second) => { + let first = std::mem::replace(&mut head, second); + init = f(init, (Position::First, first)); + } + None => return f(init, (Position::Only, head)), + } + } + // Have seen the first item, and there's something left. + init = self.peekable.fold(init, |acc, mut item| { + std::mem::swap(&mut head, &mut item); + f(acc, (Position::Middle, item)) + }); + // The "head" is now the last item. + init = f(init, (Position::Last, head)); + } + init + } } -impl ExactSizeIterator for WithPosition - where I: ExactSizeIterator, -{ } +impl ExactSizeIterator for WithPosition where I: ExactSizeIterator {} -impl FusedIterator for WithPosition -{} +impl FusedIterator for WithPosition {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/zip_eq_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_eq_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/zip_eq_impl.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_eq_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ use super::size_hint; /// An iterator which iterates two other iterators simultaneously +/// and panic if they have different lengths. /// /// See [`.zip_eq()`](crate::Itertools::zip_eq) for more information. #[derive(Clone, Debug)] @@ -10,9 +11,7 @@ b: J, } -/// Iterate `i` and `j` in lock step. -/// -/// **Panics** if the iterators are not of the same length. +/// Zips two iterators but **panics** if they are not of the same length. /// /// [`IntoIterator`] enabled version of [`Itertools::zip_eq`](crate::Itertools::zip_eq). /// @@ -22,11 +21,13 @@ /// let data = [1, 2, 3, 4, 5]; /// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { /// /* loop body */ +/// # let _ = (a, b); /// } /// ``` pub fn zip_eq(i: I, j: J) -> ZipEq - where I: IntoIterator, - J: IntoIterator +where + I: IntoIterator, + J: IntoIterator, { ZipEq { a: i.into_iter(), @@ -35,8 +36,9 @@ } impl Iterator for ZipEq - where I: Iterator, - J: Iterator +where + I: Iterator, + J: Iterator, { type Item = (I::Item, J::Item); @@ -44,8 +46,9 @@ match (self.a.next(), self.b.next()) { (None, None) => None, (Some(a), Some(b)) => Some((a, b)), - (None, Some(_)) | (Some(_), None) => - panic!("itertools: .zip_eq() reached end of one iterator before the other") + (None, Some(_)) | (Some(_), None) => { + panic!("itertools: .zip_eq() reached end of one iterator before the other") + } } } @@ -55,6 +58,8 @@ } impl ExactSizeIterator for ZipEq - where I: ExactSizeIterator, - J: ExactSizeIterator -{} +where + I: ExactSizeIterator, + J: ExactSizeIterator, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/zip_longest.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_longest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/zip_longest.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/zip_longest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -use std::cmp::Ordering::{Equal, Greater, Less}; use super::size_hint; +use std::cmp::Ordering::{Equal, Greater, Less}; use std::iter::{Fuse, FusedIterator}; use crate::either_or_both::EitherOrBoth; @@ -8,6 +8,7 @@ // and dedicated to itertools https://github.com/rust-lang/rust/pull/19283 /// An iterator which iterates two other iterators simultaneously +/// and wraps the elements in [`EitherOrBoth`]. /// /// This iterator is *fused*. /// @@ -21,8 +22,9 @@ /// Create a new `ZipLongest` iterator. pub fn zip_longest(a: T, b: U) -> ZipLongest - where T: Iterator, - U: Iterator +where + T: Iterator, + U: Iterator, { ZipLongest { a: a.fuse(), @@ -31,8 +33,9 @@ } impl Iterator for ZipLongest - where T: Iterator, - U: Iterator +where + T: Iterator, + U: Iterator, { type Item = EitherOrBoth; @@ -50,11 +53,29 @@ fn size_hint(&self) -> (usize, Option) { size_hint::max(self.a.size_hint(), self.b.size_hint()) } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let Self { mut a, mut b } = self; + let res = a.try_fold(init, |init, a| match b.next() { + Some(b) => Ok(f(init, EitherOrBoth::Both(a, b))), + None => Err(f(init, EitherOrBoth::Left(a))), + }); + match res { + Ok(acc) => b.map(EitherOrBoth::Right).fold(acc, f), + Err(acc) => a.map(EitherOrBoth::Left).fold(acc, f), + } + } } impl DoubleEndedIterator for ZipLongest - where T: DoubleEndedIterator + ExactSizeIterator, - U: DoubleEndedIterator + ExactSizeIterator +where + T: DoubleEndedIterator + ExactSizeIterator, + U: DoubleEndedIterator + ExactSizeIterator, { #[inline] fn next_back(&mut self) -> Option { @@ -70,14 +91,49 @@ Less => self.b.next_back().map(EitherOrBoth::Right), } } + + fn rfold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let Self { mut a, mut b } = self; + let a_len = a.len(); + let b_len = b.len(); + match a_len.cmp(&b_len) { + Equal => {} + Greater => { + init = a + .by_ref() + .rev() + .take(a_len - b_len) + .map(EitherOrBoth::Left) + .fold(init, &mut f) + } + Less => { + init = b + .by_ref() + .rev() + .take(b_len - a_len) + .map(EitherOrBoth::Right) + .fold(init, &mut f) + } + } + a.rfold(init, |acc, item_a| { + f(acc, EitherOrBoth::Both(item_a, b.next_back().unwrap())) + }) + } } impl ExactSizeIterator for ZipLongest - where T: ExactSizeIterator, - U: ExactSizeIterator -{} +where + T: ExactSizeIterator, + U: ExactSizeIterator, +{ +} impl FusedIterator for ZipLongest - where T: Iterator, - U: Iterator -{} +where + T: Iterator, + U: Iterator, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/ziptuple.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/ziptuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/src/ziptuple.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/src/ziptuple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,7 +7,7 @@ t: T, } -/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. +/// An iterator that generalizes `.zip()` and allows running multiple iterators in lockstep. /// /// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that /// implement [`IntoIterator`]) and yields elements @@ -16,11 +16,11 @@ /// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the /// element types of the subiterator. /// -/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J, +/// **Note:** The result of this function is a value of a named type (`Zip<(I, J, /// ..)>` of each component iterator `I, J, ...`) if each component iterator is /// nameable. /// -/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the +/// Prefer [`izip!()`](crate::izip) over `multizip` for the performance benefits of using the /// standard library `.zip()`. Prefer `multizip` if a nameable type is needed. /// /// ``` @@ -36,10 +36,9 @@ /// /// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); /// ``` -/// [`izip!()`]: crate::izip pub fn multizip(t: U) -> Zip - where Zip: From, - Zip: Iterator, +where + Zip: From + Iterator, { Zip::from(t) } @@ -82,7 +81,7 @@ fn size_hint(&self) -> (usize, Option) { - let sh = (::std::usize::MAX, None); + let sh = (usize::MAX, None); let ($(ref $B,)*) = self.t; $( let sh = size_hint::min($B.size_hint(), sh); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/adaptors_no_collect.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/adaptors_no_collect.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/adaptors_no_collect.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/adaptors_no_collect.rs 2006-07-24 01:21:28.000000000 +0000 @@ -22,9 +22,14 @@ } fn no_collect_test(to_adaptor: T) - where A: Iterator, T: Fn(PanickingCounter) -> A +where + A: Iterator, + T: Fn(PanickingCounter) -> A, { - let counter = PanickingCounter { curr: 0, max: 10_000 }; + let counter = PanickingCounter { + curr: 0, + max: 10_000, + }; let adaptor = to_adaptor(counter); for _ in adaptor.take(5) {} @@ -43,4 +48,4 @@ #[test] fn combinations_with_replacement_no_collect() { no_collect_test(|iter| iter.combinations_with_replacement(5)) -} \ No newline at end of file +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/laziness.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/laziness.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/laziness.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/laziness.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,283 @@ +#![allow(unstable_name_collisions)] + +use itertools::Itertools; + +#[derive(Debug, Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +struct Panicking; + +impl Iterator for Panicking { + type Item = u8; + + fn next(&mut self) -> Option { + panic!("iterator adaptor is not lazy") + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +impl ExactSizeIterator for Panicking {} + +/// ## Usage example +/// ```compile_fail +/// must_use_tests! { +/// name { +/// Panicking.name(); // Add `let _ =` only if required (encountered error). +/// } +/// // ... +/// } +/// ``` +/// +/// **TODO:** test missing `must_use` attributes better, maybe with a new lint. +macro_rules! must_use_tests { + ($($(#[$attr:meta])* $name:ident $body:block)*) => { + $( + /// `#[deny(unused_must_use)]` should force us to ignore the resulting iterators + /// by adding `let _ = ...;` on every iterator. + /// If it does not, then a `must_use` attribute is missing on the associated struct. + /// + /// However, it's only helpful if we don't add `let _ =` before seeing if there is an error or not. + /// And it does not protect us against removed `must_use` attributes. + /// There is no simple way to test this yet. + #[deny(unused_must_use)] + #[test] + $(#[$attr])* + fn $name() $body + )* + }; +} + +must_use_tests! { + // Itertools trait: + interleave { + let _ = Panicking.interleave(Panicking); + } + interleave_shortest { + let _ = Panicking.interleave_shortest(Panicking); + } + intersperse { + let _ = Panicking.intersperse(0); + } + intersperse_with { + let _ = Panicking.intersperse_with(|| 0); + } + get { + let _ = Panicking.get(1..4); + let _ = Panicking.get(1..=4); + let _ = Panicking.get(1..); + let _ = Panicking.get(..4); + let _ = Panicking.get(..=4); + let _ = Panicking.get(..); + } + zip_longest { + let _ = Panicking.zip_longest(Panicking); + } + zip_eq { + let _ = Panicking.zip_eq(Panicking); + } + batching { + let _ = Panicking.batching(Iterator::next); + } + chunk_by { + // ChunkBy + let _ = Panicking.chunk_by(|x| *x); + // Groups + let _ = Panicking.chunk_by(|x| *x).into_iter(); + } + chunks { + // IntoChunks + let _ = Panicking.chunks(1); + let _ = Panicking.chunks(2); + // Chunks + let _ = Panicking.chunks(1).into_iter(); + let _ = Panicking.chunks(2).into_iter(); + } + tuple_windows { + let _ = Panicking.tuple_windows::<(_,)>(); + let _ = Panicking.tuple_windows::<(_, _)>(); + let _ = Panicking.tuple_windows::<(_, _, _)>(); + } + circular_tuple_windows { + let _ = Panicking.circular_tuple_windows::<(_,)>(); + let _ = Panicking.circular_tuple_windows::<(_, _)>(); + let _ = Panicking.circular_tuple_windows::<(_, _, _)>(); + } + tuples { + let _ = Panicking.tuples::<(_,)>(); + let _ = Panicking.tuples::<(_, _)>(); + let _ = Panicking.tuples::<(_, _, _)>(); + } + tee { + let _ = Panicking.tee(); + } + map_into { + let _ = Panicking.map_into::(); + } + map_ok { + let _ = Panicking.map(Ok::).map_ok(|x| x + 1); + } + filter_ok { + let _ = Panicking.map(Ok::).filter_ok(|x| x % 2 == 0); + } + filter_map_ok { + let _ = Panicking.map(Ok::).filter_map_ok(|x| { + if x % 2 == 0 { + Some(x + 1) + } else { + None + } + }); + } + flatten_ok { + let _ = Panicking.map(|x| Ok::<_, ()>([x])).flatten_ok(); + } + merge { + let _ = Panicking.merge(Panicking); + } + merge_by { + let _ = Panicking.merge_by(Panicking, |_, _| true); + } + merge_join_by { + let _ = Panicking.merge_join_by(Panicking, |_, _| true); + let _ = Panicking.merge_join_by(Panicking, Ord::cmp); + } + #[should_panic] + kmerge { + let _ = Panicking.map(|_| Panicking).kmerge(); + } + #[should_panic] + kmerge_by { + let _ = Panicking.map(|_| Panicking).kmerge_by(|_, _| true); + } + cartesian_product { + let _ = Panicking.cartesian_product(Panicking); + } + multi_cartesian_product { + let _ = vec![Panicking, Panicking, Panicking].into_iter().multi_cartesian_product(); + } + coalesce { + let _ = Panicking.coalesce(|x, y| if x == y { Ok(x) } else { Err((x, y)) }); + } + dedup { + let _ = Panicking.dedup(); + } + dedup_by { + let _ = Panicking.dedup_by(|_, _| true); + } + dedup_with_count { + let _ = Panicking.dedup_with_count(); + } + dedup_by_with_count { + let _ = Panicking.dedup_by_with_count(|_, _| true); + } + duplicates { + let _ = Panicking.duplicates(); + } + duplicates_by { + let _ = Panicking.duplicates_by(|x| *x); + } + unique { + let _ = Panicking.unique(); + } + unique_by { + let _ = Panicking.unique_by(|x| *x); + } + peeking_take_while { + let _ = Panicking.peekable().peeking_take_while(|x| x % 2 == 0); + } + take_while_ref { + let _ = Panicking.take_while_ref(|x| x % 2 == 0); + } + take_while_inclusive { + let _ = Panicking.take_while_inclusive(|x| x % 2 == 0); + } + while_some { + let _ = Panicking.map(Some).while_some(); + } + tuple_combinations1 { + let _ = Panicking.tuple_combinations::<(_,)>(); + } + #[should_panic] + tuple_combinations2 { + let _ = Panicking.tuple_combinations::<(_, _)>(); + } + #[should_panic] + tuple_combinations3 { + let _ = Panicking.tuple_combinations::<(_, _, _)>(); + } + combinations { + let _ = Panicking.combinations(0); + let _ = Panicking.combinations(1); + let _ = Panicking.combinations(2); + } + combinations_with_replacement { + let _ = Panicking.combinations_with_replacement(0); + let _ = Panicking.combinations_with_replacement(1); + let _ = Panicking.combinations_with_replacement(2); + } + permutations { + let _ = Panicking.permutations(0); + let _ = Panicking.permutations(1); + let _ = Panicking.permutations(2); + } + powerset { + let _ = Panicking.powerset(); + } + pad_using { + let _ = Panicking.pad_using(25, |_| 10); + } + with_position { + let _ = Panicking.with_position(); + } + positions { + let _ = Panicking.positions(|v| v % 2 == 0); + } + update { + let _ = Panicking.update(|n| *n += 1); + } + multipeek { + let _ = Panicking.multipeek(); + } + // Not iterator themselves but still lazy. + into_grouping_map { + let _ = Panicking.map(|x| (x, x + 1)).into_grouping_map(); + } + into_grouping_map_by { + let _ = Panicking.into_grouping_map_by(|x| *x); + } + // Macros: + iproduct { + let _ = itertools::iproduct!(Panicking); + let _ = itertools::iproduct!(Panicking, Panicking); + let _ = itertools::iproduct!(Panicking, Panicking, Panicking); + } + izip { + let _ = itertools::izip!(Panicking); + let _ = itertools::izip!(Panicking, Panicking); + let _ = itertools::izip!(Panicking, Panicking, Panicking); + } + chain { + let _ = itertools::chain!(Panicking); + let _ = itertools::chain!(Panicking, Panicking); + let _ = itertools::chain!(Panicking, Panicking, Panicking); + } + // Free functions: + multizip { + let _ = itertools::multizip((Panicking, Panicking)); + } + put_back { + let _ = itertools::put_back(Panicking); + let _ = itertools::put_back(Panicking).with_value(15); + } + peek_nth { + let _ = itertools::peek_nth(Panicking); + } + put_back_n { + let _ = itertools::put_back_n(Panicking); + } + rciter { + let _ = itertools::rciter(Panicking); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/macros_hygiene.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/macros_hygiene.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/macros_hygiene.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/macros_hygiene.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,11 @@ +mod alloc {} +mod core {} +mod either {} +mod std {} + #[test] fn iproduct_hygiene() { + let _ = itertools::iproduct!(); let _ = itertools::iproduct!(0..6); let _ = itertools::iproduct!(0..6, 0..9); let _ = itertools::iproduct!(0..6, 0..9, 0..12); @@ -11,3 +17,11 @@ let _ = itertools::izip!(0..6, 0..9); let _ = itertools::izip!(0..6, 0..9, 0..12); } + +#[test] +fn chain_hygiene() { + let _: ::std::iter::Empty = itertools::chain!(); + let _ = itertools::chain!(0..6); + let _ = itertools::chain!(0..6, 0..9); + let _ = itertools::chain!(0..6, 0..9, 0..12); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/merge_join.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/merge_join.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/merge_join.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/merge_join.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,108 +1,101 @@ -use itertools::EitherOrBoth; use itertools::free::merge_join_by; +use itertools::EitherOrBoth; #[test] fn empty() { let left: Vec = vec![]; let right: Vec = vec![]; - let expected_result: Vec> = vec![]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let expected_result: Vec> = vec![]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn left_only() { - let left: Vec = vec![1,2,3]; + let left: Vec = vec![1, 2, 3]; let right: Vec = vec![]; - let expected_result: Vec> = vec![ + let expected_result: Vec> = vec![ EitherOrBoth::Left(1), EitherOrBoth::Left(2), - EitherOrBoth::Left(3) + EitherOrBoth::Left(3), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn right_only() { let left: Vec = vec![]; - let right: Vec = vec![1,2,3]; - let expected_result: Vec> = vec![ + let right: Vec = vec![1, 2, 3]; + let expected_result: Vec> = vec![ EitherOrBoth::Right(1), EitherOrBoth::Right(2), - EitherOrBoth::Right(3) + EitherOrBoth::Right(3), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn first_left_then_right() { - let left: Vec = vec![1,2,3]; - let right: Vec = vec![4,5,6]; - let expected_result: Vec> = vec![ + let left: Vec = vec![1, 2, 3]; + let right: Vec = vec![4, 5, 6]; + let expected_result: Vec> = vec![ EitherOrBoth::Left(1), EitherOrBoth::Left(2), EitherOrBoth::Left(3), EitherOrBoth::Right(4), EitherOrBoth::Right(5), - EitherOrBoth::Right(6) + EitherOrBoth::Right(6), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn first_right_then_left() { - let left: Vec = vec![4,5,6]; - let right: Vec = vec![1,2,3]; - let expected_result: Vec> = vec![ + let left: Vec = vec![4, 5, 6]; + let right: Vec = vec![1, 2, 3]; + let expected_result: Vec> = vec![ EitherOrBoth::Right(1), EitherOrBoth::Right(2), EitherOrBoth::Right(3), EitherOrBoth::Left(4), EitherOrBoth::Left(5), - EitherOrBoth::Left(6) + EitherOrBoth::Left(6), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn interspersed_left_and_right() { - let left: Vec = vec![1,3,5]; - let right: Vec = vec![2,4,6]; - let expected_result: Vec> = vec![ + let left: Vec = vec![1, 3, 5]; + let right: Vec = vec![2, 4, 6]; + let expected_result: Vec> = vec![ EitherOrBoth::Left(1), EitherOrBoth::Right(2), EitherOrBoth::Left(3), EitherOrBoth::Right(4), EitherOrBoth::Left(5), - EitherOrBoth::Right(6) + EitherOrBoth::Right(6), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } #[test] fn overlapping_left_and_right() { - let left: Vec = vec![1,3,4,6]; - let right: Vec = vec![2,3,4,5]; - let expected_result: Vec> = vec![ + let left: Vec = vec![1, 3, 4, 6]; + let right: Vec = vec![2, 3, 4, 5]; + let expected_result: Vec> = vec![ EitherOrBoth::Left(1), EitherOrBoth::Right(2), EitherOrBoth::Both(3, 3), EitherOrBoth::Both(4, 4), EitherOrBoth::Right(5), - EitherOrBoth::Left(6) + EitherOrBoth::Left(6), ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::>(); + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)).collect::>(); assert_eq!(expected_result, actual_result); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/peeking_take_while.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/peeking_take_while.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/peeking_take_while.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/peeking_take_while.rs 2006-07-24 01:21:28.000000000 +0000 @@ -48,3 +48,22 @@ r.peeking_take_while(|_| true).count(); assert_eq!(r.next(), None); } + +#[test] +fn peeking_take_while_nested() { + let mut xs = (0..10).peekable(); + let ys: Vec<_> = xs + .peeking_take_while(|x| *x < 6) + .peeking_take_while(|x| *x != 3) + .collect(); + assert_eq!(ys, vec![0, 1, 2]); + assert_eq!(xs.next(), Some(3)); + + let mut xs = (4..10).peekable(); + let ys: Vec<_> = xs + .peeking_take_while(|x| *x != 3) + .peeking_take_while(|x| *x < 6) + .collect(); + assert_eq!(ys, vec![4, 5]); + assert_eq!(xs.next(), Some(6)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/quick.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/quick.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/quick.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/quick.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,35 +2,28 @@ //! and adaptors. //! //! In particular we test the tedious size_hint and exact size correctness. +//! +//! **NOTE:** Due to performance limitations, these tests are not run with miri! +//! They cannot be relied upon to discover soundness issues. + +#![cfg(not(miri))] +#![allow(deprecated, unstable_name_collisions)] +use itertools::free::{ + cloned, enumerate, multipeek, peek_nth, put_back, put_back_n, rciter, zip, zip_eq, +}; +use itertools::Itertools; +use itertools::{iproduct, izip, multizip, EitherOrBoth}; use quickcheck as qc; +use std::cmp::{max, min, Ordering}; +use std::collections::{HashMap, HashSet}; use std::default::Default; use std::num::Wrapping; use std::ops::Range; -use std::cmp::{max, min, Ordering}; -use std::collections::{HashMap, HashSet}; -use itertools::Itertools; -use itertools::{ - multizip, - EitherOrBoth, - iproduct, - izip, -}; -use itertools::free::{ - cloned, - enumerate, - multipeek, - peek_nth, - put_back, - put_back_n, - rciter, - zip, - zip_eq, -}; -use rand::Rng; -use rand::seq::SliceRandom; use quickcheck::TestResult; +use rand::seq::SliceRandom; +use rand::Rng; /// Trait for size hint modifier types trait HintKind: Copy + Send + qc::Arbitrary { @@ -49,7 +42,7 @@ impl qc::Arbitrary for Exact { fn arbitrary(_: &mut G) -> Self { - Exact {} + Self {} } } @@ -66,8 +59,10 @@ impl HintKind for Inexact { fn loosen_bounds(&self, org_hint: (usize, Option)) -> (usize, Option) { let (org_lower, org_upper) = org_hint; - (org_lower.saturating_sub(self.underestimate), - org_upper.and_then(move |x| x.checked_add(self.overestimate))) + ( + org_lower.saturating_sub(self.underestimate), + org_upper.and_then(move |x| x.checked_add(self.overestimate)), + ) } } @@ -76,27 +71,23 @@ let ue_value = usize::arbitrary(g); let oe_value = usize::arbitrary(g); // Compensate for quickcheck using extreme values too rarely - let ue_choices = &[0, ue_value, usize::max_value()]; - let oe_choices = &[0, oe_value, usize::max_value()]; - Inexact { + let ue_choices = &[0, ue_value, usize::MAX]; + let oe_choices = &[0, oe_value, usize::MAX]; + Self { underestimate: *ue_choices.choose(g).unwrap(), overestimate: *oe_choices.choose(g).unwrap(), } } - fn shrink(&self) -> Box> { + fn shrink(&self) -> Box> { let underestimate_value = self.underestimate; let overestimate_value = self.overestimate; - Box::new( - underestimate_value.shrink().flat_map(move |ue_value| - overestimate_value.shrink().map(move |oe_value| - Inexact { - underestimate: ue_value, - overestimate: oe_value, - } - ) - ) - ) + Box::new(underestimate_value.shrink().flat_map(move |ue_value| { + overestimate_value.shrink().map(move |oe_value| Self { + underestimate: ue_value, + overestimate: oe_value, + }) + })) } } @@ -116,10 +107,12 @@ hint_kind: SK, } -impl Iter where HK: HintKind +impl Iter +where + HK: HintKind, { fn new(it: Range, hint_kind: HK) -> Self { - Iter { + Self { iterator: it, fuse_flag: 0, hint_kind, @@ -128,64 +121,66 @@ } impl Iterator for Iter - where Range: Iterator, - as Iterator>::Item: Default, - HK: HintKind, +where + Range: Iterator, + as Iterator>::Item: Default, + HK: HintKind, { type Item = as Iterator>::Item; - fn next(&mut self) -> Option - { + fn next(&mut self) -> Option { let elt = self.iterator.next(); if elt.is_none() { self.fuse_flag += 1; // check fuse flag if self.fuse_flag == 2 { - return Some(Default::default()) + return Some(Default::default()); } } elt } - fn size_hint(&self) -> (usize, Option) - { + fn size_hint(&self) -> (usize, Option) { let org_hint = self.iterator.size_hint(); self.hint_kind.loosen_bounds(org_hint) } } impl DoubleEndedIterator for Iter - where Range: DoubleEndedIterator, - as Iterator>::Item: Default, - HK: HintKind +where + Range: DoubleEndedIterator, + as Iterator>::Item: Default, + HK: HintKind, { - fn next_back(&mut self) -> Option { self.iterator.next_back() } + fn next_back(&mut self) -> Option { + self.iterator.next_back() + } } -impl ExactSizeIterator for Iter where Range: ExactSizeIterator, +impl ExactSizeIterator for Iter +where + Range: ExactSizeIterator, as Iterator>::Item: Default, -{ } +{ +} impl qc::Arbitrary for Iter - where T: qc::Arbitrary, - HK: HintKind, +where + T: qc::Arbitrary, + HK: HintKind, { - fn arbitrary(g: &mut G) -> Self - { - Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) + fn arbitrary(g: &mut G) -> Self { + Self::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) } - fn shrink(&self) -> Box>> - { + fn shrink(&self) -> Box> { let r = self.iterator.clone(); let hint_kind = self.hint_kind; - Box::new( - r.start.shrink().flat_map(move |a| - r.end.shrink().map(move |b| - Iter::new(a.clone()..b, hint_kind) - ) - ) - ) + Box::new(r.start.shrink().flat_map(move |a| { + r.end + .shrink() + .map(move |b| Self::new(a.clone()..b, hint_kind)) + })) } } @@ -201,7 +196,10 @@ hint_kind: HK, } -impl Iterator for ShiftRange where HK: HintKind { +impl Iterator for ShiftRange +where + HK: HintKind, +{ type Item = Iter; fn next(&mut self) -> Option { @@ -219,10 +217,11 @@ } } -impl ExactSizeIterator for ShiftRange { } +impl ExactSizeIterator for ShiftRange {} impl qc::Arbitrary for ShiftRange - where HK: HintKind +where + HK: HintKind, { fn arbitrary(g: &mut G) -> Self { const MAX_STARTING_RANGE_DIFF: i32 = 32; @@ -236,7 +235,7 @@ let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1); let hint_kind = qc::Arbitrary::arbitrary(g); - ShiftRange { + Self { range_start, range_end, start_step, @@ -250,7 +249,7 @@ fn correct_count(get_it: F) -> bool where I: Iterator, - F: Fn() -> I + F: Fn() -> I, { let mut counts = vec![get_it().count()]; @@ -258,7 +257,6 @@ let mut it = get_it(); for _ in 0..(counts.len() - 1) { - #[allow(clippy::manual_assert)] if it.next().is_none() { panic!("Iterator shouldn't be finished, may not be deterministic"); } @@ -276,7 +274,10 @@ for (i, returned_count) in counts.into_iter().enumerate() { let actual_count = total_actual_count - i; if actual_count != returned_count { - println!("Total iterations: {} True count: {} returned count: {}", i, actual_count, returned_count); + println!( + "Total iterations: {} True count: {} returned count: {}", + i, actual_count, returned_count + ); return false; } @@ -299,12 +300,10 @@ // check all the size hints for &(low, hi) in &hints { true_count -= 1; - if low > true_count || - (hi.is_some() && hi.unwrap() < true_count) - { + if low > true_count || (hi.is_some() && hi.unwrap() < true_count) { println!("True size: {:?}, size hint: {:?}", true_count, (low, hi)); //println!("All hints: {:?}", hints); - return false + return false; } } true @@ -313,13 +312,19 @@ fn exact_size(mut it: I) -> bool { // check every iteration let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } + if Some(low) != hi { + return false; + } while let Some(_) = it.next() { let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } + if low != xlow + 1 { + return false; + } low = xlow; hi = xhi; - if Some(low) != hi { return false; } + if Some(low) != hi { + return false; + } } let (low, hi) = it.size_hint(); low == 0 && hi == Some(0) @@ -329,13 +334,19 @@ fn exact_size_for_this(mut it: I) -> bool { // check every iteration let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } + if Some(low) != hi { + return false; + } while let Some(_) = it.next() { let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } + if low != xlow + 1 { + return false; + } low = xlow; hi = xhi; - if Some(low) != hi { return false; } + if Some(low) != hi { + return false; + } } let (low, hi) = it.size_hint(); low == 0 && hi == Some(0) @@ -442,43 +453,10 @@ assert_eq!(answer.into_iter().last(), a.multi_cartesian_product().last()); } - #[allow(deprecated)] - fn size_step(a: Iter, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let filt = a.clone().dedup(); - correct_size_hint(filt.step(s)) && - exact_size(a.step(s)) - } - - #[allow(deprecated)] - fn equal_step(a: Iter, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.clone().step(s), a.filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) - } - - #[allow(deprecated)] - fn equal_step_vec(a: Vec, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.iter().step(s), a.iter().filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) + fn correct_empty_multi_product() -> () { + let empty = Vec::>::new().into_iter().multi_cartesian_product(); + assert!(correct_size_hint(empty.clone())); + itertools::assert_equal(empty, std::iter::once(Vec::new())) } fn size_multipeek(a: Iter, s: u8) -> bool { @@ -596,6 +574,20 @@ let b = &b[..len]; itertools::equal(zip_eq(a, b), zip(a, b)) } + + #[should_panic] + fn zip_eq_panics(a: Vec, b: Vec) -> TestResult { + if a.len() == b.len() { return TestResult::discard(); } + zip_eq(a.iter(), b.iter()).for_each(|_| {}); + TestResult::passed() // won't come here + } + + fn equal_positions(a: Vec) -> bool { + let with_pos = a.iter().positions(|v| v % 2 == 0); + let without = a.iter().enumerate().filter(|(_, v)| *v % 2 == 0).map(|(i, _)| i); + itertools::equal(with_pos.clone(), without.clone()) + && itertools::equal(with_pos.rev(), without.rev()) + } fn size_zip_longest(a: Iter, b: Iter) -> bool { let filt = a.clone().dedup(); let filt2 = b.clone().dedup(); @@ -751,6 +743,56 @@ } quickcheck! { + fn correct_peek_nth(mut a: Vec) -> () { + let mut it = peek_nth(a.clone()); + for start_pos in 0..a.len() + 2 { + for real_idx in start_pos..a.len() + 2 { + let peek_idx = real_idx - start_pos; + assert_eq!(it.peek_nth(peek_idx), a.get(real_idx)); + assert_eq!(it.peek_nth_mut(peek_idx), a.get_mut(real_idx)); + } + assert_eq!(it.next(), a.get(start_pos).copied()); + } + } + + fn peek_nth_mut_replace(a: Vec, b: Vec) -> () { + let mut it = peek_nth(a.iter()); + for (i, m) in b.iter().enumerate().take(a.len().min(b.len())) { + *it.peek_nth_mut(i).unwrap() = m; + } + for (i, m) in a.iter().enumerate() { + assert_eq!(it.next().unwrap(), b.get(i).unwrap_or(m)); + } + assert_eq!(it.next(), None); + assert_eq!(it.next(), None); + } + + fn peek_nth_next_if(a: Vec) -> () { + let mut it = peek_nth(a.clone()); + for (idx, mut value) in a.iter().copied().enumerate() { + let should_be_none = it.next_if(|x| x != &value); + assert_eq!(should_be_none, None); + if value % 5 == 0 { + // Sometimes, peek up to 3 further. + let n = value as usize % 3; + let nth = it.peek_nth(n); + assert_eq!(nth, a.get(idx + n)); + } else if value % 5 == 1 { + // Sometimes, peek next element mutably. + if let Some(v) = it.peek_mut() { + *v = v.wrapping_sub(1); + let should_be_none = it.next_if_eq(&value); + assert_eq!(should_be_none, None); + value = value.wrapping_sub(1); + } + } + let eq = it.next_if_eq(&value); + assert_eq!(eq, Some(value)); + } + } +} + +quickcheck! { fn dedup_via_coalesce(a: Vec) -> bool { let mut b = a.clone(); b.dedup(); @@ -811,9 +853,8 @@ quickcheck! { fn size_put_back(a: Vec, x: Option) -> bool { let mut it = put_back(a.into_iter()); - match x { - Some(t) => it.put_back(t), - None => {} + if let Some(t) = x { + it.put_back(t); } correct_size_hint(it) } @@ -830,6 +871,31 @@ } quickcheck! { + fn merge_join_by_ordering_vs_bool(a: Vec, b: Vec) -> bool { + use either::Either; + use itertools::free::merge_join_by; + let mut has_equal = false; + let it_ord = merge_join_by(a.clone(), b.clone(), Ord::cmp).flat_map(|v| match v { + EitherOrBoth::Both(l, r) => { + has_equal = true; + vec![Either::Left(l), Either::Right(r)] + } + EitherOrBoth::Left(l) => vec![Either::Left(l)], + EitherOrBoth::Right(r) => vec![Either::Right(r)], + }); + let it_bool = merge_join_by(a, b, PartialOrd::le); + itertools::equal(it_ord, it_bool) || has_equal + } + fn merge_join_by_bool_unwrapped_is_merge_by(a: Vec, b: Vec) -> bool { + use either::Either; + use itertools::free::merge_join_by; + let it = a.clone().into_iter().merge_by(b.clone(), PartialOrd::ge); + let it_join = merge_join_by(a, b, PartialOrd::ge).map(Either::into_inner); + itertools::equal(it, it_join) + } +} + +quickcheck! { fn size_tee(a: Vec) -> bool { let (mut t1, mut t2) = a.iter().tee(); t1.next(); @@ -870,8 +936,31 @@ } quickcheck! { - fn size_combinations(it: Iter) -> bool { - correct_size_hint(it.tuple_combinations::<(_, _)>()) + fn size_combinations(a: Iter) -> bool { + let it = a.clone().tuple_combinations::<(_, _)>(); + correct_size_hint(it.clone()) && it.count() == binomial(a.count(), 2) + } + + fn exact_size_combinations_1(a: Vec) -> bool { + let it = a.iter().tuple_combinations::<(_,)>(); + exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 1) + } + fn exact_size_combinations_2(a: Vec) -> bool { + let it = a.iter().tuple_combinations::<(_, _)>(); + exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 2) + } + fn exact_size_combinations_3(mut a: Vec) -> bool { + a.truncate(15); + let it = a.iter().tuple_combinations::<(_, _, _)>(); + exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 3) + } +} + +fn binomial(n: usize, k: usize) -> usize { + if k > n { + 0 + } else { + (n - k + 1..=n).product::() / (1..=k).product::() } } @@ -887,7 +976,7 @@ } } } - cmb.next() == None + cmb.next().is_none() } } @@ -936,64 +1025,75 @@ } quickcheck! { - fn fuzz_group_by_lazy_1(it: Iter) -> bool { + fn fuzz_chunk_by_lazy_1(it: Iter) -> bool { let jt = it.clone(); - let groups = it.group_by(|k| *k); - itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x)) + let chunks = it.chunk_by(|k| *k); + itertools::equal(jt, chunks.into_iter().flat_map(|(_, x)| x)) } } quickcheck! { - fn fuzz_group_by_lazy_2(data: Vec) -> bool { - let groups = data.iter().group_by(|k| *k / 10); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + fn fuzz_chunk_by_lazy_2(data: Vec) -> bool { + let chunks = data.iter().chunk_by(|k| *k / 10); + let res = itertools::equal(data.iter(), chunks.into_iter().flat_map(|(_, x)| x)); res } } quickcheck! { - fn fuzz_group_by_lazy_3(data: Vec) -> bool { - let grouper = data.iter().group_by(|k| *k / 10); - let groups = grouper.into_iter().collect_vec(); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + fn fuzz_chunk_by_lazy_3(data: Vec) -> bool { + let grouper = data.iter().chunk_by(|k| *k / 10); + let chunks = grouper.into_iter().collect_vec(); + let res = itertools::equal(data.iter(), chunks.into_iter().flat_map(|(_, x)| x)); res } } quickcheck! { - fn fuzz_group_by_lazy_duo(data: Vec, order: Vec<(bool, bool)>) -> bool { - let grouper = data.iter().group_by(|k| *k / 3); - let mut groups1 = grouper.into_iter(); - let mut groups2 = grouper.into_iter(); + fn fuzz_chunk_by_lazy_duo(data: Vec, order: Vec<(bool, bool)>) -> bool { + let grouper = data.iter().chunk_by(|k| *k / 3); + let mut chunks1 = grouper.into_iter(); + let mut chunks2 = grouper.into_iter(); let mut elts = Vec::<&u8>::new(); - let mut old_groups = Vec::new(); + let mut old_chunks = Vec::new(); let tup1 = |(_, b)| b; for &(ord, consume_now) in &order { - let iter = &mut [&mut groups1, &mut groups2][ord as usize]; + let iter = &mut [&mut chunks1, &mut chunks2][ord as usize]; match iter.next() { Some((_, gr)) => if consume_now { - for og in old_groups.drain(..) { + for og in old_chunks.drain(..) { elts.extend(og); } elts.extend(gr); } else { - old_groups.push(gr); + old_chunks.push(gr); }, None => break, } } - for og in old_groups.drain(..) { + for og in old_chunks.drain(..) { elts.extend(og); } - for gr in groups1.map(&tup1) { elts.extend(gr); } - for gr in groups2.map(&tup1) { elts.extend(gr); } + for gr in chunks1.map(&tup1) { elts.extend(gr); } + for gr in chunks2.map(&tup1) { elts.extend(gr); } itertools::assert_equal(&data, elts); true } } quickcheck! { + fn chunk_clone_equal(a: Vec, size: u8) -> () { + let mut size = size; + if size == 0 { + size += 1; + } + let it = a.chunks(size as usize); + itertools::assert_equal(it.clone(), it); + } +} + +quickcheck! { fn equal_chunks_lazy(a: Vec, size: u8) -> bool { let mut size = size; if size == 0 { @@ -1010,7 +1110,75 @@ } } +// tuple iterators quickcheck! { + fn equal_circular_tuple_windows_1(a: Vec) -> bool { + let x = a.iter().map(|e| (e,) ); + let y = a.iter().circular_tuple_windows::<(_,)>(); + itertools::assert_equal(x,y); + true + } + + fn equal_circular_tuple_windows_2(a: Vec) -> bool { + let x = (0..a.len()).map(|start_idx| ( + &a[start_idx], + &a[(start_idx + 1) % a.len()], + )); + let y = a.iter().circular_tuple_windows::<(_, _)>(); + itertools::assert_equal(x,y); + true + } + + fn equal_circular_tuple_windows_3(a: Vec) -> bool { + let x = (0..a.len()).map(|start_idx| ( + &a[start_idx], + &a[(start_idx + 1) % a.len()], + &a[(start_idx + 2) % a.len()], + )); + let y = a.iter().circular_tuple_windows::<(_, _, _)>(); + itertools::assert_equal(x,y); + true + } + + fn equal_circular_tuple_windows_4(a: Vec) -> bool { + let x = (0..a.len()).map(|start_idx| ( + &a[start_idx], + &a[(start_idx + 1) % a.len()], + &a[(start_idx + 2) % a.len()], + &a[(start_idx + 3) % a.len()], + )); + let y = a.iter().circular_tuple_windows::<(_, _, _, _)>(); + itertools::assert_equal(x,y); + true + } + + fn equal_cloned_circular_tuple_windows(a: Vec) -> bool { + let x = a.iter().circular_tuple_windows::<(_, _, _, _)>(); + let y = x.clone(); + itertools::assert_equal(x,y); + true + } + + fn equal_cloned_circular_tuple_windows_noninitial(a: Vec) -> bool { + let mut x = a.iter().circular_tuple_windows::<(_, _, _, _)>(); + let _ = x.next(); + let y = x.clone(); + itertools::assert_equal(x,y); + true + } + + fn equal_cloned_circular_tuple_windows_complete(a: Vec) -> bool { + let mut x = a.iter().circular_tuple_windows::<(_, _, _, _)>(); + for _ in x.by_ref() {} + let y = x.clone(); + itertools::assert_equal(x,y); + true + } + + fn circular_tuple_windows_exact_size(a: Vec) -> bool { + exact_size(a.iter().circular_tuple_windows::<(_, _, _, _)>()) + } + fn equal_tuple_windows_1(a: Vec) -> bool { let x = a.windows(1).map(|s| (&s[0], )); let y = a.iter().tuple_windows::<(_,)>(); @@ -1035,6 +1203,14 @@ itertools::equal(x, y) } + fn tuple_windows_exact_size_1(a: Vec) -> bool { + exact_size(a.iter().tuple_windows::<(_,)>()) + } + + fn tuple_windows_exact_size_4(a: Vec) -> bool { + exact_size(a.iter().tuple_windows::<(_, _, _, _)>()) + } + fn equal_tuples_1(a: Vec) -> bool { let x = a.chunks(1).map(|s| (&s[0], )); let y = a.iter().tuples::<(_,)>(); @@ -1066,6 +1242,18 @@ assert_eq!(buffer.len(), a.len() % 4); exact_size(buffer) } + + fn tuples_size_hint_inexact(a: Iter) -> bool { + correct_size_hint(a.clone().tuples::<(_,)>()) + && correct_size_hint(a.clone().tuples::<(_, _)>()) + && correct_size_hint(a.tuples::<(_, _, _, _)>()) + } + + fn tuples_size_hint_exact(a: Iter) -> bool { + exact_size(a.clone().tuples::<(_,)>()) + && exact_size(a.clone().tuples::<(_, _)>()) + && exact_size(a.tuples::<(_, _, _, _)>()) + } } // with_position @@ -1097,14 +1285,14 @@ #[derive(Clone, Debug, PartialEq, Eq)] struct Val(u32, u32); -impl PartialOrd for Val { - fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) +impl PartialOrd for Val { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) } } @@ -1112,10 +1300,10 @@ impl qc::Arbitrary for Val { fn arbitrary(g: &mut G) -> Self { let (x, y) = <(u32, u32)>::arbitrary(g); - Val(x, y) + Self(x, y) } fn shrink(&self) -> Box> { - Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y))) + Box::new((self.0, self.1).shrink().map(|(x, y)| Self(x, y))) } } @@ -1157,13 +1345,12 @@ } quickcheck! { - #[allow(deprecated)] - fn tree_fold1_f64(mut a: Vec) -> TestResult { + fn tree_reduce_f64(mut a: Vec) -> TestResult { fn collapse_adjacent(x: Vec, mut f: F) -> Vec where F: FnMut(f64, f64) -> f64 { let mut out = Vec::new(); - for i in (0..x.len()).step(2) { + for i in (0..x.len()).step_by(2) { if i == x.len()-1 { out.push(x[i]) } else { @@ -1177,7 +1364,7 @@ return TestResult::discard(); } - let actual = a.iter().cloned().tree_fold1(f64::atan2); + let actual = a.iter().cloned().tree_reduce(f64::atan2); while a.len() > 1 { a = collapse_adjacent(a, f64::atan2); @@ -1202,7 +1389,7 @@ fn at_most_one_i32(a: Vec) -> TestResult { let ret = a.iter().cloned().at_most_one(); match a.len() { - 0 => TestResult::from_bool(ret.unwrap() == None), + 0 => TestResult::from_bool(ret.unwrap().is_none()), 1 => TestResult::from_bool(ret.unwrap() == Some(a[0])), _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())), } @@ -1232,7 +1419,7 @@ Some(acc.unwrap_or(0) + val) } }); - + let group_map_lookup = a.iter() .map(|&b| b as u64) .map(|i| (i % modulo, i)) @@ -1252,7 +1439,7 @@ for m in 0..modulo { assert_eq!( - lookup.get(&m).copied(), + lookup.get(&m).copied(), a.iter() .map(|&b| b as u64) .filter(|&val| val % modulo == m) @@ -1267,6 +1454,35 @@ } } + fn correct_grouping_map_by_fold_with_modulo_key(a: Vec, modulo: u8) -> () { + #[derive(Debug, Default, PartialEq)] + struct Accumulator { + acc: u64, + } + + let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` + let lookup = a.iter().map(|&b| b as u64) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .fold_with(|_key, _val| Default::default(), |Accumulator { acc }, &key, val| { + assert!(val % modulo == key); + let acc = acc + val; + Accumulator { acc } + }); + + let group_map_lookup = a.iter() + .map(|&b| b as u64) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().sum())).map(|(key, acc)| (key,Accumulator { acc })) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &Accumulator { acc: sum }) in lookup.iter() { + assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::()); + } + } + fn correct_grouping_map_by_fold_modulo_key(a: Vec, modulo: u8) -> () { let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` let lookup = a.iter().map(|&b| b as u64) // Avoid overflows @@ -1290,22 +1506,21 @@ } } - fn correct_grouping_map_by_fold_first_modulo_key(a: Vec, modulo: u8) -> () { + fn correct_grouping_map_by_reduce_modulo_key(a: Vec, modulo: u8) -> () { let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` let lookup = a.iter().map(|&b| b as u64) // Avoid overflows .into_grouping_map_by(|i| i % modulo) - .fold_first(|acc, &key, val| { + .reduce(|acc, &key, val| { assert!(val % modulo == key); acc + val }); - // TODO: Swap `fold1` with stdlib's `fold_first` when it's stabilized let group_map_lookup = a.iter() .map(|&b| b as u64) .map(|i| (i % modulo, i)) .into_group_map() .into_iter() - .map(|(key, vals)| (key, vals.into_iter().fold1(|acc, val| acc + val).unwrap())) + .map(|(key, vals)| (key, vals.into_iter().reduce(|acc, val| acc + val).unwrap())) .collect::>(); assert_eq!(lookup, group_map_lookup); @@ -1372,7 +1587,7 @@ assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by_key(|&val| val)); } } - + fn correct_grouping_map_by_min_modulo_key(a: Vec, modulo: u8) -> () { let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min(); @@ -1423,7 +1638,7 @@ assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by_key(|&val| val)); } } - + fn correct_grouping_map_by_minmax_modulo_key(a: Vec, modulo: u8) -> () { let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax(); @@ -1536,7 +1751,7 @@ .min_by(|_, _, _| Ordering::Equal); assert_eq!(lookup[&0], 0); - + let lookup = (0..=10) .into_grouping_map_by(|_| 0) .minmax_by(|_, _, _| Ordering::Equal); @@ -1594,12 +1809,10 @@ } } - -fn is_fused(mut it: I) -> bool -{ +fn is_fused(mut it: I) -> bool { for _ in it.by_ref() {} - for _ in 0..10{ - if it.next().is_some(){ + for _ in 0..10 { + if it.next().is_some() { return false; } } @@ -1640,7 +1853,7 @@ !is_fused(a.clone().interleave_shortest(b.clone())) && is_fused(a.fuse().interleave_shortest(b.fuse())) } - + fn fused_product(a: Iter, b: Iter) -> bool { is_fused(a.fuse().cartesian_product(b.fuse())) @@ -1746,4 +1959,11 @@ result_set.is_empty() } } + + fn tail(v: Vec, n: u8) -> bool { + let n = n as usize; + let result = &v[v.len().saturating_sub(n)..]; + itertools::equal(v.iter().tail(n), result) + && itertools::equal(v.iter().filter(|_| true).tail(n), result) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/specializations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/specializations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/specializations.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/specializations.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,20 @@ +//! Test specializations of methods with default impls match the behavior of the +//! default impls. +//! +//! **NOTE:** Due to performance limitations, these tests are not run with miri! +//! They cannot be relied upon to discover soundness issues. + +#![cfg(not(miri))] +#![allow(unstable_name_collisions)] + use itertools::Itertools; +use quickcheck::Arbitrary; +use quickcheck::{quickcheck, TestResult}; +use rand::Rng; use std::fmt::Debug; -use quickcheck::quickcheck; struct Unspecialized(I); + impl Iterator for Unspecialized where I: Iterator, @@ -15,30 +27,41 @@ } } -macro_rules! check_specialized { - ($src:expr, |$it:pat| $closure:expr) => { - let $it = $src.clone(); - let v1 = $closure; - - let $it = Unspecialized($src.clone()); - let v2 = $closure; - - assert_eq!(v1, v2); +impl DoubleEndedIterator for Unspecialized +where + I: DoubleEndedIterator, +{ + #[inline(always)] + fn next_back(&mut self) -> Option { + self.0.next_back() } } -fn test_specializations( - it: &Iter, -) where - IterItem: Eq + Debug + Clone, - Iter: Iterator + Clone, +fn test_specializations(it: &I) +where + I::Item: Eq + Debug + Clone, + I: Iterator + Clone, { + macro_rules! check_specialized { + ($src:expr, |$it:pat| $closure:expr) => { + // Many iterators special-case the first elements, so we test specializations for iterators that have already been advanced. + let mut src = $src.clone(); + for _ in 0..5 { + let $it = src.clone(); + let v1 = $closure; + let $it = Unspecialized(src.clone()); + let v2 = $closure; + assert_eq!(v1, v2); + src.next(); + } + } + } check_specialized!(it, |i| i.count()); check_specialized!(it, |i| i.last()); check_specialized!(it, |i| i.collect::>()); check_specialized!(it, |i| { let mut parameters_from_fold = vec![]; - let fold_result = i.fold(vec![], |mut acc, v: IterItem| { + let fold_result = i.fold(vec![], |mut acc, v: I::Item| { parameters_from_fold.push((acc.clone(), v.clone())); acc.push(v); acc @@ -50,7 +73,7 @@ let first = i.next(); let all_result = i.all(|x| { parameters_from_all.push(x.clone()); - Some(x)==first + Some(x) == first }); (parameters_from_all, all_result) }); @@ -72,10 +95,270 @@ } } +fn test_double_ended_specializations(it: &I) +where + I::Item: Eq + Debug + Clone, + I: DoubleEndedIterator + Clone, +{ + macro_rules! check_specialized { + ($src:expr, |$it:pat| $closure:expr) => { + // Many iterators special-case the first elements, so we test specializations for iterators that have already been advanced. + let mut src = $src.clone(); + for step in 0..8 { + let $it = src.clone(); + let v1 = $closure; + let $it = Unspecialized(src.clone()); + let v2 = $closure; + assert_eq!(v1, v2); + if step % 2 == 0 { + src.next(); + } else { + src.next_back(); + } + } + } + } + check_specialized!(it, |i| { + let mut parameters_from_rfold = vec![]; + let rfold_result = i.rfold(vec![], |mut acc, v: I::Item| { + parameters_from_rfold.push((acc.clone(), v.clone())); + acc.push(v); + acc + }); + (parameters_from_rfold, rfold_result) + }); + let size = it.clone().count(); + for n in 0..size + 2 { + check_specialized!(it, |mut i| i.nth_back(n)); + } +} + quickcheck! { + fn interleave(v: Vec, w: Vec) -> () { + test_specializations(&v.iter().interleave(w.iter())); + } + + fn interleave_shortest(v: Vec, w: Vec) -> () { + test_specializations(&v.iter().interleave_shortest(w.iter())); + } + + fn batching(v: Vec) -> () { + test_specializations(&v.iter().batching(Iterator::next)); + } + + fn tuple_windows(v: Vec) -> () { + test_specializations(&v.iter().tuple_windows::<(_,)>()); + test_specializations(&v.iter().tuple_windows::<(_, _)>()); + test_specializations(&v.iter().tuple_windows::<(_, _, _)>()); + } + + fn circular_tuple_windows(v: Vec) -> () { + test_specializations(&v.iter().circular_tuple_windows::<(_,)>()); + test_specializations(&v.iter().circular_tuple_windows::<(_, _)>()); + test_specializations(&v.iter().circular_tuple_windows::<(_, _, _)>()); + } + + fn tuples(v: Vec) -> () { + test_specializations(&v.iter().tuples::<(_,)>()); + test_specializations(&v.iter().tuples::<(_, _)>()); + test_specializations(&v.iter().tuples::<(_, _, _)>()); + } + + fn cartesian_product(a: Vec, b: Vec) -> TestResult { + if a.len() * b.len() > 100 { + return TestResult::discard(); + } + test_specializations(&a.iter().cartesian_product(&b)); + TestResult::passed() + } + + fn multi_cartesian_product(a: Vec, b: Vec, c: Vec) -> TestResult { + if a.len() * b.len() * c.len() > 100 { + return TestResult::discard(); + } + test_specializations(&vec![a, b, c].into_iter().multi_cartesian_product()); + TestResult::passed() + } + + fn coalesce(v: Vec) -> () { + test_specializations(&v.iter().coalesce(|x, y| if x == y { Ok(x) } else { Err((x, y)) })) + } + + fn dedup(v: Vec) -> () { + test_specializations(&v.iter().dedup()) + } + + fn dedup_by(v: Vec) -> () { + test_specializations(&v.iter().dedup_by(PartialOrd::ge)) + } + + fn dedup_with_count(v: Vec) -> () { + test_specializations(&v.iter().dedup_with_count()) + } + + fn dedup_by_with_count(v: Vec) -> () { + test_specializations(&v.iter().dedup_by_with_count(PartialOrd::ge)) + } + + fn duplicates(v: Vec) -> () { + let it = v.iter().duplicates(); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn duplicates_by(v: Vec) -> () { + let it = v.iter().duplicates_by(|x| *x % 10); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn unique(v: Vec) -> () { + let it = v.iter().unique(); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn unique_by(v: Vec) -> () { + let it = v.iter().unique_by(|x| *x % 50); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn take_while_inclusive(v: Vec) -> () { + test_specializations(&v.iter().copied().take_while_inclusive(|&x| x < 100)); + } + + fn while_some(v: Vec) -> () { + test_specializations(&v.iter().map(|&x| if x < 100 { Some(2 * x) } else { None }).while_some()); + } + + fn pad_using(v: Vec) -> () { + use std::convert::TryFrom; + let it = v.iter().copied().pad_using(10, |i| u8::try_from(5 * i).unwrap_or(u8::MAX)); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn with_position(v: Vec) -> () { + test_specializations(&v.iter().with_position()); + } + + fn positions(v: Vec) -> () { + let it = v.iter().positions(|x| x % 5 == 0); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn update(v: Vec) -> () { + let it = v.iter().copied().update(|x| *x = x.wrapping_mul(7)); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn tuple_combinations(v: Vec) -> TestResult { + if v.len() > 10 { + return TestResult::discard(); + } + test_specializations(&v.iter().tuple_combinations::<(_,)>()); + test_specializations(&v.iter().tuple_combinations::<(_, _)>()); + test_specializations(&v.iter().tuple_combinations::<(_, _, _)>()); + TestResult::passed() + } + fn intersperse(v: Vec) -> () { test_specializations(&v.into_iter().intersperse(0)); } + + fn intersperse_with(v: Vec) -> () { + test_specializations(&v.into_iter().intersperse_with(|| 0)); + } + + fn array_combinations(v: Vec) -> TestResult { + if v.len() > 10 { + return TestResult::discard(); + } + test_specializations(&v.iter().array_combinations::<1>()); + test_specializations(&v.iter().array_combinations::<2>()); + test_specializations(&v.iter().array_combinations::<3>()); + TestResult::passed() + } + + fn combinations(a: Vec, n: u8) -> TestResult { + if n > 3 || a.len() > 8 { + return TestResult::discard(); + } + test_specializations(&a.iter().combinations(n as usize)); + TestResult::passed() + } + + fn combinations_with_replacement(a: Vec, n: u8) -> TestResult { + if n > 3 || a.len() > 7 { + return TestResult::discard(); + } + test_specializations(&a.iter().combinations_with_replacement(n as usize)); + TestResult::passed() + } + + fn permutations(a: Vec, n: u8) -> TestResult { + if n > 3 || a.len() > 8 { + return TestResult::discard(); + } + test_specializations(&a.iter().permutations(n as usize)); + TestResult::passed() + } + + fn powerset(a: Vec) -> TestResult { + if a.len() > 6 { + return TestResult::discard(); + } + test_specializations(&a.iter().powerset()); + TestResult::passed() + } + + fn zip_longest(a: Vec, b: Vec) -> () { + let it = a.into_iter().zip_longest(b); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn zip_eq(a: Vec) -> () { + test_specializations(&a.iter().zip_eq(a.iter().rev())) + } + + fn multizip(a: Vec) -> () { + let it = itertools::multizip((a.iter(), a.iter().rev(), a.iter().take(50))); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn izip(a: Vec, b: Vec) -> () { + test_specializations(&itertools::izip!(b.iter(), a, b.iter().rev())); + } + + fn iproduct(a: Vec, b: Vec, c: Vec) -> TestResult { + if a.len() * b.len() * c.len() > 200 { + return TestResult::discard(); + } + test_specializations(&itertools::iproduct!(a, b.iter(), c)); + TestResult::passed() + } + + fn repeat_n(element: i8, n: u8) -> () { + let it = itertools::repeat_n(element, n as usize); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn exactly_one_error(v: Vec) -> TestResult { + // Use `at_most_one` would be similar. + match v.iter().exactly_one() { + Ok(_) => TestResult::discard(), + Err(it) => { + test_specializations(&it); + TestResult::passed() + } + } + } } quickcheck! { @@ -85,32 +368,128 @@ pb.put_back(1); test_specializations(&pb); } + + fn put_back_n(v: Vec, n: u8) -> () { + let mut it = itertools::put_back_n(v); + for k in 0..n { + it.put_back(k); + } + test_specializations(&it); + } + + fn multipeek(v: Vec, n: u8) -> () { + let mut it = v.into_iter().multipeek(); + for _ in 0..n { + it.peek(); + } + test_specializations(&it); + } + + fn peek_nth_with_peek(v: Vec, n: u8) -> () { + let mut it = itertools::peek_nth(v); + for _ in 0..n { + it.peek(); + } + test_specializations(&it); + } + + fn peek_nth_with_peek_nth(v: Vec, n: u8) -> () { + let mut it = itertools::peek_nth(v); + it.peek_nth(n as usize); + test_specializations(&it); + } + + fn peek_nth_with_peek_mut(v: Vec, n: u8) -> () { + let mut it = itertools::peek_nth(v); + for _ in 0..n { + if let Some(x) = it.peek_mut() { + *x = x.wrapping_add(50); + } + } + test_specializations(&it); + } + + fn peek_nth_with_peek_nth_mut(v: Vec, n: u8) -> () { + let mut it = itertools::peek_nth(v); + if let Some(x) = it.peek_nth_mut(n as usize) { + *x = x.wrapping_add(50); + } + test_specializations(&it); + } } quickcheck! { - fn merge_join_by_qc(i1: Vec, i2: Vec) -> () { - test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp)); + fn merge(a: Vec, b: Vec) -> () { + test_specializations(&a.into_iter().merge(b)) + } + + fn merge_by(a: Vec, b: Vec) -> () { + test_specializations(&a.into_iter().merge_by(b, PartialOrd::ge)) + } + + fn merge_join_by_ordering(i1: Vec, i2: Vec) -> () { + test_specializations(&i1.into_iter().merge_join_by(i2, Ord::cmp)); + } + + fn merge_join_by_bool(i1: Vec, i2: Vec) -> () { + test_specializations(&i1.into_iter().merge_join_by(i2, PartialOrd::ge)); + } + + fn kmerge(a: Vec, b: Vec, c: Vec) -> () { + test_specializations(&vec![a, b, c] + .into_iter() + .map(|v| v.into_iter().sorted()) + .kmerge()); + } + + fn kmerge_by(a: Vec, b: Vec, c: Vec) -> () { + test_specializations(&vec![a, b, c] + .into_iter() + .map(|v| v.into_iter().sorted_by_key(|a| a.abs())) + .kmerge_by(|a, b| a.abs() < b.abs())); } } quickcheck! { fn map_into(v: Vec) -> () { - test_specializations(&v.into_iter().map_into::()); + let it = v.into_iter().map_into::(); + test_specializations(&it); + test_double_ended_specializations(&it); } -} -quickcheck! { fn map_ok(v: Vec>) -> () { - test_specializations(&v.into_iter().map_ok(|u| u.checked_add(1))); + let it = v.into_iter().map_ok(|u| u.checked_add(1)); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn filter_ok(v: Vec>) -> () { + let it = v.into_iter().filter_ok(|&i| i < 20); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + fn filter_map_ok(v: Vec>) -> () { + let it = v.into_iter().filter_map_ok(|i| if i < 20 { Some(i * 2) } else { None }); + test_specializations(&it); + test_double_ended_specializations(&it); + } + + // `SmallIter2` because `Vec` is too slow and we get bad coverage from a singleton like Option + fn flatten_ok(v: Vec, char>>) -> () { + let it = v.into_iter().flatten_ok(); + test_specializations(&it); + test_double_ended_specializations(&it); } } quickcheck! { + // TODO Replace this function by a normal call to test_specializations fn process_results(v: Vec>) -> () { helper(v.iter().copied()); helper(v.iter().copied().filter(Result::is_ok)); - fn helper(it: impl Iterator> + Clone) { + fn helper(it: impl DoubleEndedIterator> + Clone) { macro_rules! check_results_specialized { ($src:expr, |$it:pat| $closure:expr) => { assert_eq!( @@ -126,6 +505,7 @@ check_results_specialized!(it, |i| i.count()); check_results_specialized!(it, |i| i.last()); check_results_specialized!(it, |i| i.collect::>()); + check_results_specialized!(it, |i| i.rev().collect::>()); check_results_specialized!(it, |i| { let mut parameters_from_fold = vec![]; let fold_result = i.fold(vec![], |mut acc, v| { @@ -135,6 +515,15 @@ }); (parameters_from_fold, fold_result) }); + check_results_specialized!(it, |i| { + let mut parameters_from_rfold = vec![]; + let rfold_result = i.rfold(vec![], |mut acc, v| { + parameters_from_rfold.push((acc.clone(), v)); + acc.push(v); + acc + }); + (parameters_from_rfold, rfold_result) + }); check_results_specialized!(it, |mut i| { let mut parameters_from_all = vec![]; let first = i.next(); @@ -148,6 +537,67 @@ for n in 0..size + 2 { check_results_specialized!(it, |mut i| i.nth(n)); } + for n in 0..size + 2 { + check_results_specialized!(it, |mut i| i.nth_back(n)); + } + } + } +} + +/// Like `VecIntoIter` with maximum 2 elements. +#[derive(Debug, Clone, Default)] +enum SmallIter2 { + #[default] + Zero, + One(T), + Two(T, T), +} + +impl Arbitrary for SmallIter2 { + fn arbitrary(g: &mut G) -> Self { + match g.gen_range(0u8, 3) { + 0 => Self::Zero, + 1 => Self::One(T::arbitrary(g)), + 2 => Self::Two(T::arbitrary(g), T::arbitrary(g)), + _ => unreachable!(), + } + } + // maybe implement shrink too, maybe not +} + +impl Iterator for SmallIter2 { + type Item = T; + + fn next(&mut self) -> Option { + match std::mem::take(self) { + Self::Zero => None, + Self::One(val) => Some(val), + Self::Two(val, second) => { + *self = Self::One(second); + Some(val) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = match self { + Self::Zero => 0, + Self::One(_) => 1, + Self::Two(_, _) => 2, + }; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for SmallIter2 { + fn next_back(&mut self) -> Option { + match std::mem::take(self) { + Self::Zero => None, + Self::One(val) => Some(val), + Self::Two(first, val) => { + *self = Self::One(first); + Some(val) + } } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/test_core.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_core.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/test_core.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_core.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,18 +4,71 @@ //! option. This file may not be copied, modified, or distributed //! except according to those terms. #![no_std] +#![allow(deprecated)] -use core::iter; -use itertools as it; -use crate::it::Itertools; +use crate::it::chain; +use crate::it::free::put_back; use crate::it::interleave; use crate::it::intersperse; use crate::it::intersperse_with; -use crate::it::multizip; -use crate::it::free::put_back; use crate::it::iproduct; use crate::it::izip; -use crate::it::chain; +use crate::it::multizip; +use crate::it::Itertools; +use core::iter; +use itertools as it; + +#[allow(dead_code)] +fn get_esi_then_esi(it: I) { + fn is_esi(_: impl ExactSizeIterator) {} + is_esi(it.clone().get(1..4)); + is_esi(it.clone().get(1..=4)); + is_esi(it.clone().get(1..)); + is_esi(it.clone().get(..4)); + is_esi(it.clone().get(..=4)); + is_esi(it.get(..)); +} + +#[allow(dead_code)] +fn get_dei_esi_then_dei_esi(it: I) { + fn is_dei_esi(_: impl DoubleEndedIterator + ExactSizeIterator) {} + is_dei_esi(it.clone().get(1..4)); + is_dei_esi(it.clone().get(1..=4)); + is_dei_esi(it.clone().get(1..)); + is_dei_esi(it.clone().get(..4)); + is_dei_esi(it.clone().get(..=4)); + is_dei_esi(it.get(..)); +} + +#[test] +fn get_1_max() { + let mut it = (0..5).get(1..=usize::MAX); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next_back(), Some(4)); +} + +#[test] +#[should_panic] +fn get_full_range_inclusive() { + let _it = (0..5).get(0..=usize::MAX); +} + +#[test] +fn product0() { + let mut prod = iproduct!(); + assert_eq!(prod.next(), Some(())); + assert!(prod.next().is_none()); +} + +#[test] +fn iproduct1() { + let s = "αβ"; + + let mut prod = iproduct!(s.chars()); + assert_eq!(prod.next(), Some(('α',))); + assert_eq!(prod.next(), Some(('β',))); + assert!(prod.next().is_none()); +} #[test] fn product2() { @@ -26,7 +79,7 @@ assert!(prod.next() == Some(('α', 1))); assert!(prod.next() == Some(('β', 0))); assert!(prod.next() == Some(('β', 1))); - assert!(prod.next() == None); + assert!(prod.next().is_none()); } #[test] @@ -34,13 +87,12 @@ for (_x, _y, _z) in iproduct!( [0, 1, 2].iter().cloned(), [0, 1, 2].iter().cloned(), - [0, 1, 2].iter().cloned()) - { + [0, 1, 2].iter().cloned() + ) { // ok } } - #[test] fn izip_macro() { let mut zip = izip!(2..3); @@ -61,7 +113,7 @@ #[test] fn izip2() { let _zip1: iter::Zip<_, _> = izip!(1.., 2..); - let _zip2: iter::Zip<_, _> = izip!(1.., 2.., ); + let _zip2: iter::Zip<_, _> = izip!(1.., 2..,); } #[test] @@ -109,7 +161,7 @@ #[test] fn chain2() { let _ = chain!(1.., 2..); - let _ = chain!(1.., 2.., ); + let _ = chain!(1.., 2..,); } #[test] @@ -127,7 +179,7 @@ #[test] fn test_interleave() { - let xs: [u8; 0] = []; + let xs: [u8; 0] = []; let ys = [7u8, 9, 8, 10]; let zs = [2u8, 77]; let it = interleave(xs.iter(), ys.iter()); @@ -155,15 +207,6 @@ it::assert_equal(it, ys.iter()); } -#[allow(deprecated)] -#[test] -fn foreach() { - let xs = [1i32, 2, 3]; - let mut sum = 0; - xs.iter().foreach(|elt| sum += *elt); - assert!(sum == 6); -} - #[test] fn dropping() { let xs = [1, 2, 3]; @@ -197,21 +240,11 @@ it::assert_equal(pb, xs.iter().cloned()); } -#[allow(deprecated)] -#[test] -fn step() { - it::assert_equal((0..10).step(1), 0..10); - it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0)); - it::assert_equal((0..10).step(10), 0..1); -} - -#[allow(deprecated)] #[test] fn merge() { - it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10); + it::assert_equal((0..10).step_by(2).merge((1..10).step_by(2)), 0..10); } - #[test] fn repeatn() { let s = "α"; @@ -231,29 +264,33 @@ use core::cell::Cell; #[derive(PartialEq, Debug)] struct Foo { - n: Cell + n: Cell, } - impl Clone for Foo - { - fn clone(&self) -> Self - { + impl Clone for Foo { + fn clone(&self) -> Self { let n = self.n.get(); self.n.set(n + 1); - Foo { n: Cell::new(n + 1) } + Self { + n: Cell::new(n + 1), + } } } - for n in 0..10 { - let f = Foo{n: Cell::new(0)}; + let f = Foo { n: Cell::new(0) }; let it = it::repeat_n(f, n); // drain it let last = it.last(); if n == 0 { assert_eq!(last, None); } else { - assert_eq!(last, Some(Foo{n: Cell::new(n - 1)})); + assert_eq!( + last, + Some(Foo { + n: Cell::new(n - 1) + }) + ); } } } @@ -276,25 +313,45 @@ } #[test] -fn tree_fold1() { +fn tree_reduce() { for i in 0..100 { - assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); + assert_eq!((0..i).tree_reduce(|x, y| x + y), (0..i).fold1(|x, y| x + y)); } } #[test] fn exactly_one() { assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); - assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); - assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); - assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); + assert!((0..10) + .filter(|&x| x > 1 && x < 4) + .exactly_one() + .unwrap_err() + .eq(2..4)); + assert!((0..10) + .filter(|&x| x > 1 && x < 5) + .exactly_one() + .unwrap_err() + .eq(2..5)); + assert!((0..10) + .filter(|&_| false) + .exactly_one() + .unwrap_err() + .eq(0..0)); } #[test] fn at_most_one() { assert_eq!((0..10).filter(|&x| x == 2).at_most_one().unwrap(), Some(2)); - assert!((0..10).filter(|&x| x > 1 && x < 4).at_most_one().unwrap_err().eq(2..4)); - assert!((0..10).filter(|&x| x > 1 && x < 5).at_most_one().unwrap_err().eq(2..5)); + assert!((0..10) + .filter(|&x| x > 1 && x < 4) + .at_most_one() + .unwrap_err() + .eq(2..4)); + assert!((0..10) + .filter(|&x| x > 1 && x < 5) + .at_most_one() + .unwrap_err() + .eq(2..5)); assert_eq!((0..10).filter(|&_| false).at_most_one().unwrap(), None); } @@ -315,3 +372,28 @@ assert_eq!(v[1..3].iter().cloned().product1::(), Some(2)); assert_eq!(v[1..5].iter().cloned().product1::(), Some(24)); } + +#[test] +fn next_array() { + let v = [1, 2, 3, 4, 5]; + let mut iter = v.iter(); + assert_eq!(iter.next_array(), Some([])); + assert_eq!(iter.next_array().map(|[&x, &y]| [x, y]), Some([1, 2])); + assert_eq!(iter.next_array().map(|[&x, &y]| [x, y]), Some([3, 4])); + assert_eq!(iter.next_array::<2>(), None); +} + +#[test] +fn collect_array() { + let v = [1, 2]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_array(), Some([1, 2])); + + let v = [1]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_array::<2>(), None); + + let v = [1, 2, 3]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_array::<2>(), None); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/test_std.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/test_std.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/test_std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,26 @@ -use quickcheck as qc; -use rand::{distributions::{Distribution, Standard}, Rng, SeedableRng, rngs::StdRng}; -use rand::{seq::SliceRandom, thread_rng}; -use std::{cmp::min, fmt::Debug, marker::PhantomData}; -use itertools as it; -use crate::it::Itertools; -use crate::it::ExactlyOneError; -use crate::it::multizip; -use crate::it::multipeek; -use crate::it::peek_nth; -use crate::it::free::rciter; -use crate::it::free::put_back_n; -use crate::it::FoldWhile; +#![allow(unstable_name_collisions)] + use crate::it::cloned; +use crate::it::free::put_back_n; +use crate::it::free::rciter; use crate::it::iproduct; use crate::it::izip; +use crate::it::multipeek; +use crate::it::multizip; +use crate::it::peek_nth; +use crate::it::repeat_n; +use crate::it::ExactlyOneError; +use crate::it::FoldWhile; +use crate::it::Itertools; +use itertools as it; +use quickcheck as qc; +use rand::{ + distributions::{Distribution, Standard}, + rngs::StdRng, + Rng, SeedableRng, +}; +use rand::{seq::SliceRandom, thread_rng}; +use std::{cmp::min, fmt::Debug, marker::PhantomData}; #[test] fn product3() { @@ -27,28 +34,26 @@ } } } - for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { - /* test compiles */ - } + for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { /* test compiles */ } } #[test] fn interleave_shortest() { let v0: Vec = vec![0, 2, 4]; let v1: Vec = vec![1, 3, 5, 7]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); + let it = v0.into_iter().interleave_shortest(v1); assert_eq!(it.size_hint(), (6, Some(6))); assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); let v0: Vec = vec![0, 2, 4, 6, 8]; let v1: Vec = vec![1, 3, 5]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); + let it = v0.into_iter().interleave_shortest(v1); assert_eq!(it.size_hint(), (7, Some(7))); assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); let i0 = ::std::iter::repeat(0); let v1: Vec<_> = vec![1, 3, 5]; - let it = i0.interleave_shortest(v1.into_iter()); + let it = i0.interleave_shortest(v1); assert_eq!(it.size_hint(), (7, Some(7))); let v0: Vec<_> = vec![0, 2, 4]; @@ -62,9 +67,15 @@ let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; let ys = ["aa", "bbbb", "cccc"]; it::assert_equal(ys.iter(), xs.iter().duplicates_by(|x| x[..2].to_string())); - it::assert_equal(ys.iter(), xs.iter().rev().duplicates_by(|x| x[..2].to_string()).rev()); + it::assert_equal( + ys.iter(), + xs.iter().rev().duplicates_by(|x| x[..2].to_string()).rev(), + ); let ys_rev = ["ccc", "aa", "bbbbb"]; - it::assert_equal(ys_rev.iter(), xs.iter().duplicates_by(|x| x[..2].to_string()).rev()); + it::assert_equal( + ys_rev.iter(), + xs.iter().duplicates_by(|x| x[..2].to_string()).rev(), + ); } #[test] @@ -83,10 +94,13 @@ let ys_rev = [1, 0]; it::assert_equal(ys_rev.iter(), xs.iter().duplicates().rev()); - let xs = vec![0, 1, 2, 1, 2]; + let xs = [0, 1, 2, 1, 2]; let ys = vec![1, 2]; assert_eq!(ys, xs.iter().duplicates().cloned().collect_vec()); - assert_eq!(ys, xs.iter().rev().duplicates().rev().cloned().collect_vec()); + assert_eq!( + ys, + xs.iter().rev().duplicates().rev().cloned().collect_vec() + ); let ys_rev = vec![2, 1]; assert_eq!(ys_rev, xs.iter().duplicates().rev().cloned().collect_vec()); } @@ -96,9 +110,15 @@ let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; let ys = ["aaa", "bbbbb", "ccc"]; it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); - it::assert_equal(ys.iter(), xs.iter().rev().unique_by(|x| x[..2].to_string()).rev()); + it::assert_equal( + ys.iter(), + xs.iter().rev().unique_by(|x| x[..2].to_string()).rev(), + ); let ys_rev = ["cccc", "aaaaa", "bbbb"]; - it::assert_equal(ys_rev.iter(), xs.iter().unique_by(|x| x[..2].to_string()).rev()); + it::assert_equal( + ys_rev.iter(), + xs.iter().unique_by(|x| x[..2].to_string()).rev(), + ); } #[test] @@ -127,7 +147,7 @@ let ys = [0, 1, 2, 3]; let mut it = ys[..0].iter().copied().intersperse(1); - assert!(it.next() == None); + assert!(it.next().is_none()); } #[test] @@ -148,14 +168,14 @@ #[test] fn coalesce() { - let data = vec![-1., -2., -3., 3., 1., 0., -1.]; - let it = data.iter().cloned().coalesce(|x, y| + let data = [-1., -2., -3., 3., 1., 0., -1.]; + let it = data.iter().cloned().coalesce(|x, y| { if (x >= 0.) == (y >= 0.) { Ok(x + y) } else { Err((x, y)) } - ); + }); itertools::assert_equal(it.clone(), vec![-6., 4., -1.]); assert_eq!( it.fold(vec![], |mut v, n| { @@ -168,17 +188,37 @@ #[test] fn dedup_by() { - let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; + let xs = [ + (0, 0), + (0, 1), + (1, 1), + (2, 1), + (0, 2), + (3, 1), + (0, 3), + (1, 3), + ]; let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; - it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.1==y.1)); + it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.1 == y.1)); let xs = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]; let ys = [(0, 1)]; - it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.0==y.0)); + it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.0 == y.0)); - let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; + let xs = [ + (0, 0), + (0, 1), + (1, 1), + (2, 1), + (0, 2), + (3, 1), + (0, 3), + (1, 3), + ]; let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; let mut xs_d = Vec::new(); - xs.iter().dedup_by(|x, y| x.1==y.1).fold((), |(), &elt| xs_d.push(elt)); + xs.iter() + .dedup_by(|x, y| x.1 == y.1) + .fold((), |(), &elt| xs_d.push(elt)); assert_eq!(&xs_d, &ys); } @@ -195,18 +235,38 @@ it::assert_equal(ys.iter().cloned(), xs.iter().dedup_with_count()); } - #[test] fn dedup_by_with_count() { - let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; - let ys = [(1, &(0, 0)), (3, &(0, 1)), (1, &(0, 2)), (1, &(3, 1)), (2, &(0, 3))]; + let xs = [ + (0, 0), + (0, 1), + (1, 1), + (2, 1), + (0, 2), + (3, 1), + (0, 3), + (1, 3), + ]; + let ys = [ + (1, &(0, 0)), + (3, &(0, 1)), + (1, &(0, 2)), + (1, &(3, 1)), + (2, &(0, 3)), + ]; - it::assert_equal(ys.iter().cloned(), xs.iter().dedup_by_with_count(|x, y| x.1==y.1)); + it::assert_equal( + ys.iter().cloned(), + xs.iter().dedup_by_with_count(|x, y| x.1 == y.1), + ); let xs = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]; - let ys = [( 5, &(0, 1))]; + let ys = [(5, &(0, 1))]; - it::assert_equal(ys.iter().cloned(), xs.iter().dedup_by_with_count(|x, y| x.0==y.0)); + it::assert_equal( + ys.iter().cloned(), + xs.iter().dedup_by_with_count(|x, y| x.0 == y.0), + ); } #[test] @@ -215,12 +275,28 @@ assert!("A".chars().all_equal()); assert!(!"AABBCCC".chars().all_equal()); assert!("AAAAAAA".chars().all_equal()); - for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) { + for (_key, mut sub) in &"AABBCCC".chars().chunk_by(|&x| x) { assert!(sub.all_equal()); } } #[test] +fn all_equal_value() { + assert_eq!("".chars().all_equal_value(), Err(None)); + assert_eq!("A".chars().all_equal_value(), Ok('A')); + assert_eq!("AABBCCC".chars().all_equal_value(), Err(Some(('A', 'B')))); + assert_eq!("AAAAAAA".chars().all_equal_value(), Ok('A')); + { + let mut it = [1, 2, 3].iter().copied(); + let result = it.all_equal_value(); + assert_eq!(result, Err(Some((1, 2)))); + let remaining = it.next(); + assert_eq!(remaining, Some(3)); + assert!(it.next().is_none()); + } +} + +#[test] fn all_unique() { assert!("ABCDEFGH".chars().all_unique()); assert!(!"ABCDEFGA".chars().all_unique()); @@ -240,7 +316,7 @@ #[test] fn tee() { - let xs = [0, 1, 2, 3]; + let xs = [0, 1, 2, 3]; let (mut t1, mut t2) = xs.iter().cloned().tee(); assert_eq!(t1.next(), Some(0)); assert_eq!(t2.next(), Some(0)); @@ -264,7 +340,6 @@ it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned())); } - #[test] fn test_rciter() { let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6]; @@ -285,26 +360,24 @@ assert_eq!(z.next(), Some((0, 1))); } -#[allow(deprecated)] #[test] fn trait_pointers() { - struct ByRef<'r, I: ?Sized>(&'r mut I) ; + struct ByRef<'r, I: ?Sized>(&'r mut I); - impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where - I: 'r + Iterator + impl<'r, X, I> Iterator for ByRef<'r, I> + where + I: ?Sized + 'r + Iterator, { type Item = X; - fn next(&mut self) -> Option - { + fn next(&mut self) -> Option { self.0.next() } } - let mut it = Box::new(0..10) as Box>; + let mut it = Box::new(0..10) as Box>; assert_eq!(it.next(), Some(0)); { - /* make sure foreach works on non-Sized */ let jt: &mut dyn Iterator = &mut *it; assert_eq!(jt.next(), Some(1)); @@ -314,15 +387,22 @@ } assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4))); - jt.foreach(|_| ()); + jt.for_each(|_| ()); } } #[test] fn merge_by() { - let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; - let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; - let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")]; + let odd: Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; + let even = [(2, "foo"), (4, "bar"), (6, "baz")]; + let expected = [ + (1, "hello"), + (2, "foo"), + (3, "world"), + (4, "bar"), + (5, "!"), + (6, "baz"), + ]; let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0); it::assert_equal(results, expected.iter()); } @@ -336,23 +416,21 @@ let mut bt2 = BTreeMap::new(); bt2.insert("foo", 2); bt2.insert("bar", 4); - let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 ); + let results = bt1.into_iter().merge_by(bt2, |a, b| a.0 <= b.0); let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; - it::assert_equal(results, expected.into_iter()); + it::assert_equal(results, expected); } -#[allow(deprecated)] #[test] fn kmerge() { - let its = (0..4).map(|s| (s..10).step(4)); + let its = (0..4).map(|s| (s..10).step_by(4)); it::assert_equal(its.kmerge(), 0..10); } -#[allow(deprecated)] #[test] fn kmerge_2() { - let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4)); + let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step_by(4)); it::assert_equal(its.kmerge(), 0..10); } @@ -378,19 +456,17 @@ #[test] fn join() { let many = [1, 2, 3]; - let one = [1]; + let one = [1]; let none: Vec = vec![]; assert_eq!(many.iter().join(", "), "1, 2, 3"); - assert_eq!( one.iter().join(", "), "1"); + assert_eq!(one.iter().join(", "), "1"); assert_eq!(none.iter().join(", "), ""); } #[test] fn sorted_unstable_by() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { - a.cmp(&b) - }); + let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| a.cmp(&b)); it::assert_equal(sc, vec![1, 2, 3, 4]); let v = (0..5).sorted_unstable_by(|&a, &b| a.cmp(&b).reverse()); @@ -408,33 +484,85 @@ #[test] fn sorted_by() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { - a.cmp(&b) - }); + let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| a.cmp(&b)); it::assert_equal(sc, vec![1, 2, 3, 4]); let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse()); it::assert_equal(v, vec![4, 3, 2, 1, 0]); } +#[cfg(not(miri))] qc::quickcheck! { - fn k_smallest_range(n: u64, m: u16, k: u16) -> () { + fn k_smallest_range(n: i64, m: u16, k: u16) -> () { // u16 is used to constrain k and m to 0..2¹⁶, // otherwise the test could use too much memory. - let (k, m) = (k as u64, m as u64); + let (k, m) = (k as usize, m as u64); + let mut v: Vec<_> = (n..n.saturating_add(m as _)).collect(); // Generate a random permutation of n..n+m - let i = { - let mut v: Vec = (n..n.saturating_add(m)).collect(); - v.shuffle(&mut thread_rng()); - v.into_iter() - }; + v.shuffle(&mut thread_rng()); - // Check that taking the k smallest elements yields n..n+min(k, m) - it::assert_equal( - i.k_smallest(k as usize), - n..n.saturating_add(min(k, m)) - ); + // Construct the right answers for the top and bottom elements + let mut sorted = v.clone(); + sorted.sort(); + // how many elements are we checking + let num_elements = min(k, m as _); + + // Compute the top and bottom k in various combinations + let sorted_smallest = sorted[..num_elements].iter().cloned(); + let smallest = v.iter().cloned().k_smallest(k); + let smallest_by = v.iter().cloned().k_smallest_by(k, Ord::cmp); + let smallest_by_key = v.iter().cloned().k_smallest_by_key(k, |&x| x); + + let sorted_largest = sorted[sorted.len() - num_elements..].iter().rev().cloned(); + let largest = v.iter().cloned().k_largest(k); + let largest_by = v.iter().cloned().k_largest_by(k, Ord::cmp); + let largest_by_key = v.iter().cloned().k_largest_by_key(k, |&x| x); + + // Check the variations produce the same answers and that they're right + it::assert_equal(smallest, sorted_smallest.clone()); + it::assert_equal(smallest_by, sorted_smallest.clone()); + it::assert_equal(smallest_by_key, sorted_smallest); + + it::assert_equal(largest, sorted_largest.clone()); + it::assert_equal(largest_by, sorted_largest.clone()); + it::assert_equal(largest_by_key, sorted_largest); + } + + fn k_smallest_relaxed_range(n: i64, m: u16, k: u16) -> () { + // u16 is used to constrain k and m to 0..2¹⁶, + // otherwise the test could use too much memory. + let (k, m) = (k as usize, m as u64); + + let mut v: Vec<_> = (n..n.saturating_add(m as _)).collect(); + // Generate a random permutation of n..n+m + v.shuffle(&mut thread_rng()); + + // Construct the right answers for the top and bottom elements + let mut sorted = v.clone(); + sorted.sort(); + // how many elements are we checking + let num_elements = min(k, m as _); + + // Compute the top and bottom k in various combinations + let sorted_smallest = sorted[..num_elements].iter().cloned(); + let smallest = v.iter().cloned().k_smallest_relaxed(k); + let smallest_by = v.iter().cloned().k_smallest_relaxed_by(k, Ord::cmp); + let smallest_by_key = v.iter().cloned().k_smallest_relaxed_by_key(k, |&x| x); + + let sorted_largest = sorted[sorted.len() - num_elements..].iter().rev().cloned(); + let largest = v.iter().cloned().k_largest_relaxed(k); + let largest_by = v.iter().cloned().k_largest_relaxed_by(k, Ord::cmp); + let largest_by_key = v.iter().cloned().k_largest_relaxed_by_key(k, |&x| x); + + // Check the variations produce the same answers and that they're right + it::assert_equal(smallest, sorted_smallest.clone()); + it::assert_equal(smallest_by, sorted_smallest.clone()); + it::assert_equal(smallest_by_key, sorted_smallest); + + it::assert_equal(largest, sorted_largest.clone()); + it::assert_equal(largest_by, sorted_largest.clone()); + it::assert_equal(largest_by_key, sorted_largest); } } @@ -443,11 +571,13 @@ idx: usize, len: usize, rng: R, - _t: PhantomData + _t: PhantomData, } impl Iterator for RandIter -where Standard: Distribution { +where + Standard: Distribution, +{ type Item = T; fn next(&mut self) -> Option { if self.idx == self.len { @@ -461,11 +591,11 @@ impl qc::Arbitrary for RandIter { fn arbitrary(g: &mut G) -> Self { - RandIter { + Self { idx: 0, len: g.size(), rng: R::seed_from_u64(g.next_u64()), - _t : PhantomData{}, + _t: PhantomData {}, } } } @@ -478,11 +608,25 @@ I::Item: Ord + Debug, { let j = i.clone(); + let i1 = i.clone(); + let j1 = i.clone(); let k = k as usize; - it::assert_equal( - i.k_smallest(k), - j.sorted().take(k) - ) + it::assert_equal(i.k_smallest(k), j.sorted().take(k)); + it::assert_equal(i1.k_smallest_relaxed(k), j1.sorted().take(k)); +} + +// Similar to `k_smallest_sort` but for our custom heap implementation. +fn k_smallest_by_sort(i: I, k: u16) +where + I: Iterator + Clone, + I::Item: Ord + Debug, +{ + let j = i.clone(); + let i1 = i.clone(); + let j1 = i.clone(); + let k = k as usize; + it::assert_equal(i.k_smallest_by(k, Ord::cmp), j.sorted().take(k)); + it::assert_equal(i1.k_smallest_relaxed_by(k, Ord::cmp), j1.sorted().take(k)); } macro_rules! generic_test { @@ -497,7 +641,10 @@ }; } +#[cfg(not(miri))] generic_test!(k_smallest_sort, u8, u16, u32, u64, i8, i16, i32, i64); +#[cfg(not(miri))] +generic_test!(k_smallest_by_sort, u8, u16, u32, u64, i8, i16, i32, i64); #[test] fn sorted_by_key() { @@ -534,7 +681,7 @@ #[test] fn test_multipeek() { - let nums = vec![1u8,2,3,4,5]; + let nums = vec![1u8, 2, 3, 4, 5]; let mp = multipeek(nums.iter().copied()); assert_eq!(nums, mp.collect::>()); @@ -575,7 +722,7 @@ #[test] fn test_multipeek_peeking_next() { use crate::it::PeekingNext; - let nums = vec![1u8,2,3,4,5,6,7]; + let nums = [1u8, 2, 3, 4, 5, 6, 7]; let mut mp = multipeek(nums.iter().copied()); assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); @@ -599,8 +746,23 @@ } #[test] +fn test_repeat_n_peeking_next() { + use crate::it::PeekingNext; + let mut rn = repeat_n(0, 5); + assert_eq!(rn.peeking_next(|&x| x != 0), None); + assert_eq!(rn.peeking_next(|&x| x <= 0), Some(0)); + assert_eq!(rn.next(), Some(0)); + assert_eq!(rn.peeking_next(|&x| x <= 0), Some(0)); + assert_eq!(rn.peeking_next(|&x| x != 0), None); + assert_eq!(rn.peeking_next(|&x| x >= 0), Some(0)); + assert_eq!(rn.next(), Some(0)); + assert_eq!(rn.peeking_next(|&x| x <= 0), None); + assert_eq!(rn.next(), None); +} + +#[test] fn test_peek_nth() { - let nums = vec![1u8,2,3,4,5]; + let nums = vec![1u8, 2, 3, 4, 5]; let iter = peek_nth(nums.iter().copied()); assert_eq!(nums, iter.collect::>()); @@ -635,7 +797,7 @@ #[test] fn test_peek_nth_peeking_next() { use it::PeekingNext; - let nums = vec![1u8,2,3,4,5,6,7]; + let nums = [1u8, 2, 3, 4, 5, 6, 7]; let mut iter = peek_nth(nums.iter().copied()); assert_eq!(iter.peeking_next(|&x| x != 0), Some(1)); @@ -663,6 +825,35 @@ } #[test] +fn test_peek_nth_next_if() { + let nums = [1u8, 2, 3, 4, 5, 6, 7]; + let mut iter = peek_nth(nums.iter().copied()); + + assert_eq!(iter.next_if(|&x| x != 0), Some(1)); + assert_eq!(iter.next(), Some(2)); + + assert_eq!(iter.peek_nth(0), Some(&3)); + assert_eq!(iter.peek_nth(1), Some(&4)); + assert_eq!(iter.next_if_eq(&3), Some(3)); + assert_eq!(iter.peek(), Some(&4)); + + assert_eq!(iter.next_if(|&x| x != 4), None); + assert_eq!(iter.next_if_eq(&4), Some(4)); + assert_eq!(iter.peek_nth(0), Some(&5)); + assert_eq!(iter.peek_nth(1), Some(&6)); + + assert_eq!(iter.next_if(|&x| x != 5), None); + assert_eq!(iter.peek(), Some(&5)); + + assert_eq!(iter.next_if(|&x| x % 2 == 1), Some(5)); + assert_eq!(iter.next_if_eq(&6), Some(6)); + assert_eq!(iter.peek_nth(0), Some(&7)); + assert_eq!(iter.peek_nth(1), None); + assert_eq!(iter.next(), Some(7)); + assert_eq!(iter.peek(), None); +} + +#[test] fn pad_using() { it::assert_equal((0..0).pad_using(1, |_| 1), 1..2); @@ -676,14 +867,14 @@ } #[test] -fn group_by() { - for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) { +fn chunk_by() { + for (ch1, sub) in &"AABBCCC".chars().chunk_by(|&x| x) { for ch2 in sub { assert_eq!(ch1, ch2); } } - for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) { + for (ch1, sub) in &"AAABBBCCCCDDDD".chars().chunk_by(|&x| x) { for ch2 in sub { assert_eq!(ch1, ch2); if ch1 == 'C' { @@ -696,24 +887,24 @@ // try all possible orderings for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) { - let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper); - let mut subs = groups.into_iter().collect_vec(); + let chunks = "AaaBbbccCcDDDD".chars().chunk_by(&toupper); + let mut subs = chunks.into_iter().collect_vec(); for &idx in &indices[..] { let (key, text) = match idx { - 0 => ('A', "Aaa".chars()), - 1 => ('B', "Bbb".chars()), - 2 => ('C', "ccCc".chars()), - 3 => ('D', "DDDD".chars()), - _ => unreachable!(), + 0 => ('A', "Aaa".chars()), + 1 => ('B', "Bbb".chars()), + 2 => ('C', "ccCc".chars()), + 3 => ('D', "DDDD".chars()), + _ => unreachable!(), }; assert_eq!(key, subs[idx].0); it::assert_equal(&mut subs[idx].1, text); } } - let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x); - let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec(); + let chunks = "AAABBBCCCCDDDD".chars().chunk_by(|&x| x); + let mut subs = chunks.into_iter().map(|(_, g)| g).collect_vec(); let sd = subs.pop().unwrap(); let sc = subs.pop().unwrap(); @@ -730,9 +921,11 @@ { let mut ntimes = 0; let text = "AABCCC"; - for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) { - for _ in sub { - } + for (_, sub) in &text.chars().chunk_by(|&x| { + ntimes += 1; + x + }) { + for _ in sub {} } assert_eq!(ntimes, text.len()); } @@ -740,91 +933,95 @@ { let mut ntimes = 0; let text = "AABCCC"; - for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) { - } + for _ in &text.chars().chunk_by(|&x| { + ntimes += 1; + x + }) {} assert_eq!(ntimes, text.len()); } { let text = "ABCCCDEEFGHIJJKK"; - let gr = text.chars().group_by(|&x| x); + let gr = text.chars().chunk_by(|&x| x); it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars()); } } #[test] -fn group_by_lazy_2() { - let data = vec![0, 1]; - let groups = data.iter().group_by(|k| *k); - let gs = groups.into_iter().collect_vec(); +fn chunk_by_lazy_2() { + let data = [0, 1]; + let chunks = data.iter().chunk_by(|k| *k); + let gs = chunks.into_iter().collect_vec(); it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); - let data = vec![0, 1, 1, 0, 0]; - let groups = data.iter().group_by(|k| *k); - let mut gs = groups.into_iter().collect_vec(); + let data = [0, 1, 1, 0, 0]; + let chunks = data.iter().chunk_by(|k| *k); + let mut gs = chunks.into_iter().collect_vec(); gs[1..].reverse(); it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g)); - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (k, group) in &grouper { + let grouper = data.iter().chunk_by(|k| *k); + let mut chunks = Vec::new(); + for (k, chunk) in &grouper { if *k == 1 { - groups.push(group); + chunks.push(chunk); } } - it::assert_equal(&mut groups[0], &[1, 1]); + it::assert_equal(&mut chunks[0], &[1, 1]); - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (i, (_, group)) in grouper.into_iter().enumerate() { + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let grouper = data.iter().chunk_by(|k| *k); + let mut chunks = Vec::new(); + for (i, (_, chunk)) in grouper.into_iter().enumerate() { if i < 2 { - groups.push(group); + chunks.push(chunk); } else if i < 4 { - for _ in group { - } + for _ in chunk {} } else { - groups.push(group); + chunks.push(chunk); } } - it::assert_equal(&mut groups[0], &[0, 0, 0]); - it::assert_equal(&mut groups[1], &[1, 1]); - it::assert_equal(&mut groups[2], &[3, 3]); + it::assert_equal(&mut chunks[0], &[0, 0, 0]); + it::assert_equal(&mut chunks[1], &[1, 1]); + it::assert_equal(&mut chunks[2], &[3, 3]); - // use groups as chunks - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; let mut i = 0; - let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k }); - for (i, group) in &grouper { + let grouper = data.iter().chunk_by(move |_| { + let k = i / 3; + i += 1; + k + }); + for (i, chunk) in &grouper { match i { - 0 => it::assert_equal(group, &[0, 0, 0]), - 1 => it::assert_equal(group, &[1, 1, 0]), - 2 => it::assert_equal(group, &[0, 2, 2]), - 3 => it::assert_equal(group, &[3, 3]), + 0 => it::assert_equal(chunk, &[0, 0, 0]), + 1 => it::assert_equal(chunk, &[1, 1, 0]), + 2 => it::assert_equal(chunk, &[0, 2, 2]), + 3 => it::assert_equal(chunk, &[3, 3]), _ => unreachable!(), } } } #[test] -fn group_by_lazy_3() { - // test consuming each group on the lap after it was produced - let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; - let grouper = data.iter().group_by(|elt| *elt); +fn chunk_by_lazy_3() { + // test consuming each chunk on the lap after it was produced + let data = [0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; + let grouper = data.iter().chunk_by(|elt| *elt); let mut last = None; - for (key, group) in &grouper { + for (key, chunk) in &grouper { if let Some(gr) = last.take() { for elt in gr { assert!(elt != key && i32::abs(elt - key) == 1); } } - last = Some(group); + last = Some(chunk); } } #[test] fn chunks() { - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; let grouper = data.iter().chunks(3); for (i, chunk) in grouper.into_iter().enumerate() { match i { @@ -845,8 +1042,8 @@ #[test] fn concat_non_empty() { - let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]]; - assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9]) + let data = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]; + assert_eq!(data.into_iter().concat(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9]) } #[test] @@ -854,19 +1051,20 @@ assert!((1..3).combinations(5).next().is_none()); let it = (1..3).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - ]); + it::assert_equal(it, vec![vec![1, 2]]); let it = (1..5).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - vec![1, 3], - vec![1, 4], - vec![2, 3], - vec![2, 4], - vec![3, 4], - ]); + it::assert_equal( + it, + vec![ + vec![1, 2], + vec![1, 3], + vec![1, 4], + vec![2, 3], + vec![2, 4], + vec![3, 4], + ], + ); it::assert_equal((0..0).tuple_combinations::<(_, _)>(), >::new()); it::assert_equal((0..1).tuple_combinations::<(_, _)>(), >::new()); @@ -886,13 +1084,88 @@ } } - #[test] fn combinations_zero() { it::assert_equal((1..3).combinations(0), vec![vec![]]); it::assert_equal((0..0).combinations(0), vec![vec![]]); } +fn binomial(n: usize, k: usize) -> usize { + if k > n { + 0 + } else { + (n - k + 1..=n).product::() / (1..=k).product::() + } +} + +#[test] +fn combinations_range_count() { + for n in 0..=7 { + for k in 0..=7 { + let len = binomial(n, k); + let mut it = (0..n).combinations(k); + assert_eq!(len, it.clone().count()); + assert_eq!(len, it.size_hint().0); + assert_eq!(Some(len), it.size_hint().1); + for count in (0..len).rev() { + let elem = it.next(); + assert!(elem.is_some()); + assert_eq!(count, it.clone().count()); + assert_eq!(count, it.size_hint().0); + assert_eq!(Some(count), it.size_hint().1); + } + let should_be_none = it.next(); + assert!(should_be_none.is_none()); + } + } +} + +#[test] +fn combinations_inexact_size_hints() { + for k in 0..=7 { + let mut numbers = (0..18).filter(|i| i % 2 == 0); // 9 elements + let mut it = numbers.clone().combinations(k); + let real_n = numbers.clone().count(); + let len = binomial(real_n, k); + assert_eq!(len, it.clone().count()); + + let mut nb_loaded = 0; + let sh = numbers.size_hint(); + assert_eq!(binomial(sh.0 + nb_loaded, k), it.size_hint().0); + assert_eq!(sh.1.map(|n| binomial(n + nb_loaded, k)), it.size_hint().1); + + for next_count in 1..=len { + let elem = it.next(); + assert!(elem.is_some()); + assert_eq!(len - next_count, it.clone().count()); + if next_count == 1 { + // The very first time, the lazy buffer is prefilled. + nb_loaded = numbers.by_ref().take(k).count(); + } else { + // Then it loads one item each time until exhausted. + let nb = numbers.next(); + if nb.is_some() { + nb_loaded += 1; + } + } + let sh = numbers.size_hint(); + if next_count > real_n - k + 1 { + assert_eq!(0, sh.0); + assert_eq!(Some(0), sh.1); + assert_eq!(real_n, nb_loaded); + // Once it's fully loaded, size hints of `it` are exacts. + } + assert_eq!(binomial(sh.0 + nb_loaded, k) - next_count, it.size_hint().0); + assert_eq!( + sh.1.map(|n| binomial(n + nb_loaded, k) - next_count), + it.size_hint().1 + ); + } + let should_be_none = it.next(); + assert!(should_be_none.is_none()); + } +} + #[test] fn permutations_zero() { it::assert_equal((1..3).permutations(0), vec![vec![]]); @@ -900,6 +1173,41 @@ } #[test] +fn permutations_range_count() { + for n in 0..=4 { + for k in 0..=4 { + let len = if k <= n { (n - k + 1..=n).product() } else { 0 }; + let mut it = (0..n).permutations(k); + assert_eq!(len, it.clone().count()); + assert_eq!(len, it.size_hint().0); + assert_eq!(Some(len), it.size_hint().1); + for count in (0..len).rev() { + let elem = it.next(); + assert!(elem.is_some()); + assert_eq!(count, it.clone().count()); + assert_eq!(count, it.size_hint().0); + assert_eq!(Some(count), it.size_hint().1); + } + let should_be_none = it.next(); + assert!(should_be_none.is_none()); + } + } +} + +#[test] +fn permutations_overflowed_size_hints() { + let mut it = std::iter::repeat(()).permutations(2); + assert_eq!(it.size_hint().0, usize::MAX); + assert_eq!(it.size_hint().1, None); + for nb_generated in 1..=1000 { + it.next(); + assert!(it.size_hint().0 >= usize::MAX - nb_generated); + assert_eq!(it.size_hint().1, None); + } +} + +#[test] +#[cfg(not(miri))] fn combinations_with_replacement() { // Pool smaller than n it::assert_equal((0..1).combinations_with_replacement(2), vec![vec![0, 0]]); @@ -916,15 +1224,9 @@ ], ); // Zero size - it::assert_equal( - (0..3).combinations_with_replacement(0), - vec![vec![]], - ); + it::assert_equal((0..3).combinations_with_replacement(0), vec![vec![]]); // Zero size on empty pool - it::assert_equal( - (0..0).combinations_with_replacement(0), - vec![vec![]], - ); + it::assert_equal((0..0).combinations_with_replacement(0), vec![vec![]]); // Empty pool it::assert_equal( (0..0).combinations_with_replacement(2), @@ -933,25 +1235,74 @@ } #[test] +fn combinations_with_replacement_range_count() { + for n in 0..=4 { + for k in 0..=4 { + let len = binomial(usize::saturating_sub(n + k, 1), k); + let mut it = (0..n).combinations_with_replacement(k); + assert_eq!(len, it.clone().count()); + assert_eq!(len, it.size_hint().0); + assert_eq!(Some(len), it.size_hint().1); + for count in (0..len).rev() { + let elem = it.next(); + assert!(elem.is_some()); + assert_eq!(count, it.clone().count()); + assert_eq!(count, it.size_hint().0); + assert_eq!(Some(count), it.size_hint().1); + } + let should_be_none = it.next(); + assert!(should_be_none.is_none()); + } + } +} + +#[test] fn powerset() { it::assert_equal((0..0).powerset(), vec![vec![]]); it::assert_equal((0..1).powerset(), vec![vec![], vec![0]]); - it::assert_equal((0..2).powerset(), vec![vec![], vec![0], vec![1], vec![0, 1]]); - it::assert_equal((0..3).powerset(), vec![ - vec![], - vec![0], vec![1], vec![2], - vec![0, 1], vec![0, 2], vec![1, 2], - vec![0, 1, 2] - ]); + it::assert_equal( + (0..2).powerset(), + vec![vec![], vec![0], vec![1], vec![0, 1]], + ); + it::assert_equal( + (0..3).powerset(), + vec![ + vec![], + vec![0], + vec![1], + vec![2], + vec![0, 1], + vec![0, 2], + vec![1, 2], + vec![0, 1, 2], + ], + ); assert_eq!((0..4).powerset().count(), 1 << 4); assert_eq!((0..8).powerset().count(), 1 << 8); assert_eq!((0..16).powerset().count(), 1 << 16); + + for n in 0..=4 { + let mut it = (0..n).powerset(); + let len = 2_usize.pow(n); + assert_eq!(len, it.clone().count()); + assert_eq!(len, it.size_hint().0); + assert_eq!(Some(len), it.size_hint().1); + for count in (0..len).rev() { + let elem = it.next(); + assert!(elem.is_some()); + assert_eq!(count, it.clone().count()); + assert_eq!(count, it.size_hint().0); + assert_eq!(Some(count), it.size_hint().1); + } + let should_be_none = it.next(); + assert!(should_be_none.is_none()); + } } #[test] fn diff_mismatch() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 5.0, 3.0, 4.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); @@ -965,21 +1316,20 @@ #[test] fn diff_longer() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); assert!(match diff { - Some(it::Diff::Longer(_, remaining)) => - remaining.collect::>() == vec![5, 6], + Some(it::Diff::Longer(_, remaining)) => remaining.collect::>() == vec![5, 6], _ => false, }); } #[test] fn diff_shorter() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 2.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); @@ -999,14 +1349,14 @@ #[derive(Clone, Debug, PartialEq, Eq)] struct Val(u32, u32); - impl PartialOrd for Val { - fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) + impl PartialOrd for Val { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) } } @@ -1017,7 +1367,7 @@ assert_eq!(Some(1u32).iter().min_set(), vec![&1]); assert_eq!(Some(1u32).iter().max_set(), vec![&1]); - let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; + let data = [Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; let min_set = data.iter().min_set(); assert_eq!(min_set, vec![&Val(0, 1), &Val(0, 2)]); @@ -1040,31 +1390,34 @@ #[test] fn minmax() { - use std::cmp::Ordering; use crate::it::MinMaxResult; + use std::cmp::Ordering; // A peculiar type: Equality compares both tuple items, but ordering only the // first item. This is so we can check the stability property easily. #[derive(Clone, Debug, PartialEq, Eq)] struct Val(u32, u32); - impl PartialOrd for Val { - fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) + impl PartialOrd for Val { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) } } - assert_eq!(None::>.iter().minmax(), MinMaxResult::NoElements); + assert_eq!( + None::>.iter().minmax(), + MinMaxResult::NoElements + ); assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1)); - let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; + let data = [Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; let minmax = data.iter().minmax(); assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1))); @@ -1073,7 +1426,11 @@ assert_eq!(min, &Val(2, 0)); assert_eq!(max, &Val(0, 2)); - let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap(); + let (min, max) = data + .iter() + .minmax_by(|x, y| x.1.cmp(&y.1)) + .into_option() + .unwrap(); assert_eq!(min, &Val(2, 0)); assert_eq!(max, &Val(0, 2)); } @@ -1096,31 +1453,34 @@ #[test] fn while_some() { - let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None }) - .while_some(); + let ns = (1..10) + .map(|x| if x % 5 != 0 { Some(x) } else { None }) + .while_some(); it::assert_equal(ns, vec![1, 2, 3, 4]); } -#[allow(deprecated)] #[test] fn fold_while() { let mut iterations = 0; let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let sum = vec.into_iter().fold_while(0, |acc, item| { - iterations += 1; - let new_sum = acc + item; - if new_sum <= 20 { - FoldWhile::Continue(new_sum) - } else { - FoldWhile::Done(acc) - } - }).into_inner(); + let sum = vec + .into_iter() + .fold_while(0, |acc, item| { + iterations += 1; + let new_sum = acc + item; + if new_sum <= 20 { + FoldWhile::Continue(new_sum) + } else { + FoldWhile::Done(acc) + } + }) + .into_inner(); assert_eq!(iterations, 6); assert_eq!(sum, 15); } #[test] -fn tree_fold1() { +fn tree_reduce() { let x = [ "", "0", @@ -1141,9 +1501,13 @@ "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x", ]; for (i, &s) in x.iter().enumerate() { - let expected = if s.is_empty() { None } else { Some(s.to_string()) }; + let expected = if s.is_empty() { + None + } else { + Some(s.to_string()) + }; let num_strings = (0..i).map(|x| x.to_string()); - let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); + let actual = num_strings.tree_reduce(|a, b| format!("{} {} x", a, b)); assert_eq!(actual, expected); } } @@ -1153,16 +1517,53 @@ exactly_one_question_mark_return().unwrap_err(); } -fn exactly_one_question_mark_return() -> Result<(), ExactlyOneError>> { +fn exactly_one_question_mark_return() -> Result<(), ExactlyOneError>> +{ [].iter().exactly_one()?; Ok(()) } #[test] fn multiunzip() { - let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2), (3, 4, 5), (6, 7, 8)].iter().cloned().multiunzip(); + let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2), (3, 4, 5), (6, 7, 8)] + .iter() + .cloned() + .multiunzip(); assert_eq!((a, b, c), (vec![0, 3, 6], vec![1, 4, 7], vec![2, 5, 8])); let (): () = [(), (), ()].iter().cloned().multiunzip(); - let t: (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)].iter().cloned().multiunzip(); - assert_eq!(t, (vec![0], vec![1], vec![2], vec![3], vec![4], vec![5], vec![6], vec![7], vec![8], vec![9], vec![10], vec![11])); + #[allow(clippy::type_complexity)] + let t: ( + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + Vec<_>, + ) = [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)] + .iter() + .cloned() + .multiunzip(); + assert_eq!( + t, + ( + vec![0], + vec![1], + vec![2], + vec![3], + vec![4], + vec![5], + vec![6], + vec![7], + vec![8], + vec![9], + vec![10], + vec![11] + ) + ); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/zip.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/zip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/tests/zip.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/tests/zip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,17 +1,17 @@ -use itertools::Itertools; -use itertools::EitherOrBoth::{Both, Left, Right}; -use itertools::free::zip_eq; use itertools::multizip; +use itertools::EitherOrBoth::{Both, Left, Right}; +use itertools::Itertools; #[test] fn zip_longest_fused() { let a = [Some(1), None, Some(3), Some(4)]; let b = [1, 2, 3]; - let unfused = a.iter().batching(|it| *it.next().unwrap()) + let unfused = a + .iter() + .batching(|it| *it.next().unwrap()) .zip_longest(b.iter().cloned()); - itertools::assert_equal(unfused, - vec![Both(1, 1), Right(2), Right(3)]); + itertools::assert_equal(unfused, vec![Both(1, 1), Right(2), Right(3)]); } #[test] @@ -20,7 +20,7 @@ let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; - assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None)); + assert_eq!(c.zip_longest(v.iter()).size_hint(), (usize::MAX, None)); assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10))); } @@ -54,24 +54,3 @@ assert_eq!(it.next_back(), Some((1, 1))); assert_eq!(it.next_back(), None); } - - -#[should_panic] -#[test] -fn zip_eq_panic1() -{ - let a = [1, 2]; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} - -#[should_panic] -#[test] -fn zip_eq_panic2() -{ - let a: [i32; 0] = []; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"adeaad614a4b04c9aae97f73dbfee65d2c68691af5558ce5728c502851bc436b",".github/workflows/ci.yml":"72323d4f127a8737e459649c77b713317697f3f4ebc8a9688fb6a41043bfbb39",".rustfmt.toml":"632c6d2b0cf3e1d5d66df70843fb0e726b7f10bc7c3a4bf958756e834347422e","CHANGELOG.md":"ed6c781d541c40d4a19eaecd794cadebb94b3f4d51e32367803542c88f0457ee","Cargo.toml":"6dcbab25126c0cdf64f5089156de0d4346914c6d47c557d370b8e20e039ca7d3","Cargo.toml.orig":"d984a1d0f6382ccb2b06179b206855380673a6ddc6f0381cd0ebe971826ccdae","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"3acfeb07424200ae70bf571ef63a96bae954c298bddf447c9bea0ea9394825cc","benches/bench1.rs":"bb06f39db0544b1380cd4929139ccf521a9eecab7ca3f910b9499f965ec0a047","benches/combinations.rs":"51523ee1ca438a56f14711f0b04ee943895062d35859fbe23a2714d2fca3289d","benches/combinations_with_replacement.rs":"11f29160652a2d90ce7ca4b1c339c4457888ab6867e2456ce1c62e3adf9be737","benches/extra/mod.rs":"6ca290d72302a1945078621610b5788060b0de29639decebbdc557a80044aa97","benches/extra/zipslices.rs":"40e9f68a7c00f8429193fca463caef18851fa49b33355cc136bad3ccc840d655","benches/fold_specialization.rs":"5a517bbe29d366a15f6f751660e17ab1aa3e7b21552a1983048c662e34f0d69e","benches/powerset.rs":"6fd9d69a3483b37dc2411f99fb4efa6131577696f2dbdc8d1de9e4d7642fe3a3","benches/tree_fold1.rs":"539232e74f9aaea295a42069ac5af707811e90dc1c71c6e0a9064ffc731999de","benches/tuple_combinations.rs":"16366158743307a0289fc1df423a3cec45009807d410a9fe9922d5b6f8b7d002","benches/tuples.rs":"5a620783ae203e9ff9623d10d2c7fe9911d8b6c811cbad7613afa30e390c759d","clippy.toml":"33ffb83bbddb772575b3aa565b7136a8158ee386c216ffc2588fed9e83fa3826","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"1b465ed6a417180913104bc95a545fd9d1a3d67d121871ab737ad87e31b8be37","src/adaptors/coalesce.rs":"a0073325d40f297d29101538d18a267aef81889a999338dc09cb43a31cb4ec8b","src/adaptors/map.rs":"241971e856e468d71323071fb4a09867fbcedb83877320be132dc03516fe60e8","src/adaptors/mod.rs":"7f3bd7d011a348ce5e4bea486ef2e6346b64c7fe27540334d56d3f147f981d59","src/adaptors/multi_product.rs":"bb43e6dce68c815c21006d5b01c56e038d54b0c3bb8ee6bb8a4de11e2952c7ad","src/combinations.rs":"fb25babb459389093f886721016c72bf9f00e51d02735f638d871bb3a447ffd0","src/combinations_with_replacement.rs":"463011a574facbdd84278386b533a90e4dd517f0417e05adb82d182049db1f50","src/concat_impl.rs":"03b1ed61cbed242c286c3c4c5c848dbd57e02ab83fcef264f3a592b58107f324","src/cons_tuples_impl.rs":"c253d03b861831c01d62cacc57b49715ee62f6171e69f6886bb5a6ca0863bc3a","src/diff.rs":"a7800e9ce7a87b53ebe2338481335751fb43d44fa6a1ca719aceaaab40e5c8fe","src/duplicates_impl.rs":"f62fe4b642f501f785721ce5a505cf622a771e457210726dd0fb8b30be7ebbbc","src/either_or_both.rs":"76b13fbfac6bc959b4c1d8b7c99ce51726e95f994ca5429477e523a3d3950e4a","src/exactly_one_err.rs":"aa50081f6a31b5109b30e3ed305e3ec2413c6908dedc8990ec5378a99cee2b39","src/extrema_set.rs":"2a25b0b86eed2fd5d05622d591a3085cab823973d450816c2c3b8cb76e9c187e","src/flatten_ok.rs":"fe209fd886ecd9cb98d99625aa0c7274af7e644eff4a10de15b4dec8bbbc934a","src/format.rs":"a8192d85c0f9de8e633c202456e3cde0f3bc50f19b6bd8a4b2cfa3ef5123de1a","src/free.rs":"dfc57b7f56a08d4986a96b679018b41346576a7a34b668e008cc01109e728750","src/group_map.rs":"f7b02c964f63505d3e36280cfdc1755e05287714201efe983dacf702eee61434","src/groupbylazy.rs":"4f2181c022a45ff8444597708861fc6863eceb6f7555ea81cf3eeba19b492971","src/grouping_map.rs":"cbc45ac563345c96f3ac50c78f73c83d870523436a7ab88c1c9a685d204461d3","src/impl_macros.rs":"4f829b458873bed556f1aff2ae4e88dbd576766e2b5bcc07ff3ac8756758e6f4","src/intersperse.rs":"b9717242495846a4a979c95d93d5681caccb7c07a0d889eab763ad3d49a46125","src/k_smallest.rs":"603eb34314c01769ff7f6def2a24cf7a7b38507e6f3658b7aafc23a3b2e9b322","src/kmerge_impl.rs":"a347b0f6fa7715afd8a54d85ce139ed5b14c9e58a16c2b3648f5b288fdb5375f","src/lazy_buffer.rs":"834f6ef7fdf9f00c8a6329beb38eaefb706847ceeec309c221dce705c2c1e05b","src/lib.rs":"fadb0045279aafe8e8cccb45fadc383c7b358197b83c9c38fba87ada4cb2f84a","src/merge_join.rs":"1016113f6c983a9498bae5dc0570190437e1357b3333f6e19ea95c88599a1225","src/minmax.rs":"96d3897c28c8c63284d4729becc9ada6855e0953cac6e1bd35cf6f38c50b0ec0","src/multipeek_impl.rs":"35162bca4456bfa20a08e8d40e4d1cc6783dc662778789fdcded60371e975122","src/pad_tail.rs":"04be2ca73abb85815b06b5524c99d6feb2919180c486a4646f9cc6c87462f67b","src/peek_nth.rs":"6a0a51f2f373ce14d3d58595c46464878a14976bf00841a7396c03f9f9ab07ac","src/peeking_take_while.rs":"2b1b77c8882be32cfd76e973d303aa62f73370efd470c60764add0cdcca524d5","src/permutations.rs":"97831e7e26904c3cae68c97e74f7c6981ceb2fb2f2217282a0e5e54083a565fc","src/powerset.rs":"e0ee6b1316b4dd314c1e81502b90ae8113e1cda12168322520c5a65410e584b2","src/process_results_impl.rs":"9ed7fa46c8316238272ef47577387a386c1a109b50377dd3caf4291b6587cb73","src/put_back_n_impl.rs":"821e047fecd6ca0036290029f4febe7638a3abf1faa05e1e747a3bf9d80ff464","src/rciter_impl.rs":"5b156082ef2d25a94a4ad01d94cba2813c4b3e72e212515a8ad0fc8588f8045d","src/repeatn.rs":"bfc8f9145c9d8a3ea651f012b7d5a8d2fbbcbefdee76eafd098d02e7c54cda90","src/size_hint.rs":"021e57aad7df8f1e70ef588e9e9b8a1695aab183b1098f1848561f96c5dc9bcb","src/sources.rs":"61637f32c2cea2290ecfc1980c0b2d0f68463839ac09bd81006f8258ab8ecaae","src/tee.rs":"665832aa547389a420c3441470ff2494249f0ed2841be0c6a578367fe9dbd381","src/tuple_impl.rs":"00a9b61942425fb477b9691c3348646c0f9f534ff94f6321027f38c61ce2478c","src/unique_impl.rs":"3b89cdd668b74cc0a0eabb1522489e2305a0d2d8da25d6a1884e8626bbdb5959","src/unziptuple.rs":"84b50e5d29b9ddbf21a46a1cc2fd7877729c7f7da9bdc8ae1966dbaf2d2f6f60","src/with_position.rs":"c8a9b3476b3b90986b004a8877c19ff54b4c6800c5ac7ca1458d914036dacfe9","src/zip_eq_impl.rs":"4a41dc6dfe99359585d50ce648bdc85f15276c602048872b1d152e90841d8cad","src/zip_longest.rs":"f7cf5fffc3ca053ee80b410a05b27de1a475021f6de3181aea981010d7e8453f","src/ziptuple.rs":"7f9df12bf6556f382bbd4ad8cf17eb8b60c1c47fadbce016141133ba0f3384a1","tests/adaptors_no_collect.rs":"f459f36d54f5d475b2b2e83f5a1c98109c15062756ae822fa379486f3eeed666","tests/flatten_ok.rs":"b7894874132918b8229c7150b2637511d8e3e14197d8eeb9382d46b2a514efa2","tests/macros_hygiene.rs":"522afa0106e3f11a5149e9218f89c2329e405546d2ef0ea756d6a27e8a0e9ca3","tests/merge_join.rs":"b08c4ee6529d234c68d411a413b8781455d18a1eab17872d1828bb75a4fcf79b","tests/peeking_take_while.rs":"4b1c394e44a9ef9bc0de707ae080b45803db722f79834c20f15b826d7c3f1f2e","tests/quick.rs":"6fcc0649b9270f024b169b1f499dd4cc7fecb0c9aec0dfc155b264916cc626e7","tests/specializations.rs":"fdd16dc663330033fedcc478609b393d4aa369dc07dc8cda31a75219fb793087","tests/test_core.rs":"32576ba90aa8e5db985b6e6ffe30e3046bc6a11d392db8f6b4bdd2ba48d9b24d","tests/test_std.rs":"f28a78a1912c950e7c37be1e82867e70dc585d60afecdebc7a97965194eee8e6","tests/tuples.rs":"014e4da776174bfe923270e2a359cd9c95b372fce4b952b8138909d6e2c52762","tests/zip.rs":"99af365fe6054ef1c6089d3e604e34da8fea66e55861ae4be9e7336ec8de4b56"},"package":"b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "d61d12e808c8691eb0a672d3f9b65560be970a44" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.github/workflows/ci.yml 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,40 @@ +name: CI + +on: + pull_request: + push: + branches: + - staging + - trying + +jobs: + msrv: + name: Rust MSRV + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@1.36.0 + - run: cargo check --no-default-features + - run: cargo check --no-default-features --features "use_alloc" + - run: cargo check + + stable: + name: Rust Stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@stable + - run: cargo check --no-default-features + - run: cargo check --no-default-features --features "use_alloc" + - run: cargo test + + # https://github.com/rust-lang/crater/blob/9ab6f9697c901c4a44025cf0a39b73ad5b37d198/.github/workflows/bors.yml#L125-L149 + end-success: + name: bors build finished + if: success() + runs-on: ubuntu-latest + needs: [msrv,stable] + + steps: + - name: Mark the job as successful + run: exit 0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/.rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/.rustfmt.toml 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,3 @@ +# Temporarily disable rustfmt completely to avoid conflicts of newly formatted +# code with old PRs. +ignore = ["/"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/CHANGELOG.md 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,380 @@ +# Changelog + +## 0.10.4 + - Add `EitherOrBoth::or` and `EitherOrBoth::or_else` (#593) + - Add `min_set`, `max_set` et al. (#613, #323) + - Use `either/use_std` (#628) + - Documentation fixes (#612, #625, #632, #633, #634, #638) + - Code maintenance (#623, #624, #627, #630) + +## 0.10.2 + - Add `Itertools::multiunzip` (#362, #565) + - Add `intersperse` and `intersperse_with` free functions (#555) + - Add `Itertools::sorted_by_cached_key` (#424, #575) + - Specialize `ProcessResults::fold` (#563) + - Fix subtraction overflow in `DuplicatesBy::size_hint` (#552) + - Fix specialization tests (#574) + - More `Debug` impls (#573) + - Deprecate `fold1` (use `reduce` instead) (#580) + - Documentation fixes (`HomogenousTuple`, `into_group_map`, `into_group_map_by`, `MultiPeek::peek`) (#543 et al.) + +## 0.10.1 + - Add `Itertools::contains` (#514) + - Add `Itertools::counts_by` (#515) + - Add `Itertools::partition_result` (#511) + - Add `Itertools::all_unique` (#241) + - Add `Itertools::duplicates` and `Itertools::duplicates_by` (#502) + - Add `chain!` (#525) + - Add `Itertools::at_most_one` (#523) + - Add `Itertools::flatten_ok` (#527) + - Add `EitherOrBoth::or_default` (#583) + - Add `Itertools::find_or_last` and `Itertools::find_or_first` (#535) + - Implement `FusedIterator` for `FilterOk`, `FilterMapOk`, `InterleaveShortest`, `KMergeBy`, `MergeBy`, `PadUsing`, `Positions`, `Product` , `RcIter`, `TupleWindows`, `Unique`, `UniqueBy`, `Update`, `WhileSome`, `Combinations`, `CombinationsWithReplacement`, `Powerset`, `RepeatN`, and `WithPosition` (#550) + - Implement `FusedIterator` for `Interleave`, `IntersperseWith`, and `ZipLongest` (#548) + +## 0.10.0 + - **Increase minimum supported Rust version to 1.32.0** + - Improve macro hygiene (#507) + - Add `Itertools::powerset` (#335) + - Add `Itertools::sorted_unstable`, `Itertools::sorted_unstable_by`, and `Itertools::sorted_unstable_by_key` (#494) + - Implement `Error` for `ExactlyOneError` (#484) + - Undeprecate `Itertools::fold_while` (#476) + - Tuple-related adapters work for tuples of arity up to 12 (#475) + - `use_alloc` feature for users who have `alloc`, but not `std` (#474) + - Add `Itertools::k_smallest` (#473) + - Add `Itertools::into_grouping_map` and `GroupingMap` (#465) + - Add `Itertools::into_grouping_map_by` and `GroupingMapBy` (#465) + - Add `Itertools::counts` (#468) + - Add implementation of `DoubleEndedIterator` for `Unique` (#442) + - Add implementation of `DoubleEndedIterator` for `UniqueBy` (#442) + - Add implementation of `DoubleEndedIterator` for `Zip` (#346) + - Add `Itertools::multipeek` (#435) + - Add `Itertools::dedup_with_count` and `DedupWithCount` (#423) + - Add `Itertools::dedup_by_with_count` and `DedupByWithCount` (#423) + - Add `Itertools::intersperse_with` and `IntersperseWith` (#381) + - Add `Itertools::filter_ok` and `FilterOk` (#377) + - Add `Itertools::filter_map_ok` and `FilterMapOk` (#377) + - Deprecate `Itertools::fold_results`, use `Itertools::fold_ok` instead (#377) + - Deprecate `Itertools::map_results`, use `Itertools::map_ok` instead (#377) + - Deprecate `FoldResults`, use `FoldOk` instead (#377) + - Deprecate `MapResults`, use `MapOk` instead (#377) + - Add `Itertools::circular_tuple_windows` and `CircularTupleWindows` (#350) + - Add `peek_nth` and `PeekNth` (#303) + +## 0.9.0 + - Fix potential overflow in `MergeJoinBy::size_hint` (#385) + - Add `derive(Clone)` where possible (#382) + - Add `try_collect` method (#394) + - Add `HomogeneousTuple` trait (#389) + - Fix `combinations(0)` and `combinations_with_replacement(0)` (#383) + - Don't require `ParitalEq` to the `Item` of `DedupBy` (#397) + - Implement missing specializations on the `PutBack` adaptor and on the `MergeJoinBy` iterator (#372) + - Add `position_*` methods (#412) + - Derive `Hash` for `EitherOrBoth` (#417) + - Increase minimum supported Rust version to 1.32.0 + +## 0.8.2 + - Use `slice::iter` instead of `into_iter` to avoid future breakage (#378, by @LukasKalbertodt) +## 0.8.1 + - Added a [`.exactly_one()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.exactly_one) iterator method that, on success, extracts the single value of an iterator ; by @Xaeroxe + - Added combinatory iterator adaptors: + - [`.permutations(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.permutations): + + `[0, 1, 2].iter().permutations(2)` yields + + ```rust + [ + vec![0, 1], + vec![0, 2], + vec![1, 0], + vec![1, 2], + vec![2, 0], + vec![2, 1], + ] + ``` + + ; by @tobz1000 + + - [`.combinations_with_replacement(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations_with_replacement): + + `[0, 1, 2].iter().combinations_with_replacement(2)` yields + + ```rust + [ + vec![0, 0], + vec![0, 1], + vec![0, 2], + vec![1, 1], + vec![1, 2], + vec![2, 2], + ] + ``` + + ; by @tommilligan + + - For reference, these methods join the already existing [`.combinations(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations): + + `[0, 1, 2].iter().combinations(2)` yields + + ```rust + [ + vec![0, 1], + vec![0, 2], + vec![1, 2], + ] + ``` + + - Improved the performance of [`.fold()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.fold)-based internal iteration for the [`.intersperse()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.intersperse) iterator ; by @jswrenn + - Added [`.dedup_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup_by), [`.merge_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge_by) and [`.kmerge_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge_by) adaptors that work like [`.dedup()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup), [`.merge()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge) and [`.kmerge()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge), but taking an additional custom comparison closure parameter. ; by @phimuemue + - Improved the performance of [`.all_equal()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.all_equal) ; by @fyrchik + - Loosened the bounds on [`.partition_map()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.partition_map) to take just a `FnMut` closure rather than a `Fn` closure, and made its implementation use internal iteration for better performance ; by @danielhenrymantilla + - Added convenience methods to [`EitherOrBoth`](https://docs.rs/itertools/0.8.1/itertools/enum.EitherOrBoth.html) elements yielded from the [`.zip_longest()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.zip_longest) iterator adaptor ; by @Avi-D-coder + - Added [`.sum1()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.sum1) and [`.product1()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.product1) iterator methods that respectively try to return the sum and the product of the elements of an iterator **when it is not empty**, otherwise they return `None` ; by @Emerentius +## 0.8.0 + - Added new adaptor `.map_into()` for conversions using `Into` by @vorner + - Improved `Itertools` docs by @JohnHeitmann + - The return type of `.sorted_by_by_key()` is now an iterator, not a Vec. + - The return type of the `izip!(x, y)` macro with exactly two arguments is now the usual `Iterator::zip`. + - Remove `.flatten()` in favour of std's `.flatten()` + - Deprecate `.foreach()` in favour of std's `.for_each()` + - Deprecate `.step()` in favour of std's `.step_by()` + - Deprecate `repeat_call` in favour of std's `repeat_with` + - Deprecate `.fold_while()` in favour of std's `.try_fold()` + - Require Rust 1.24 as minimal version. +## 0.7.11 + - Add convenience methods to `EitherOrBoth`, making it more similar to `Option` and `Either` by @jethrogb +## 0.7.10 + - No changes. +## 0.7.9 + - New inclusion policy: See the readme about suggesting features for std before accepting them in itertools. + - The `FoldWhile` type now implements `Eq` and `PartialEq` by @jturner314 +## 0.7.8 + - Add new iterator method `.tree_fold1()` which is like `.fold1()` except items are combined in a tree structure (see its docs). By @scottmcm + - Add more `Debug` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, ZipLongest, ZipEq, Zip. +## 0.7.7 + - Add new iterator method `.into_group_map() -> HashMap>` which turns an iterator of `(K, V)` elements into such a hash table, where values are grouped by key. By @tobz1000 + - Add new free function `flatten` for the `.flatten()` adaptor. **NOTE:** recent Rust nightlies have `Iterator::flatten` and thus a clash with our flatten adaptor. One workaround is to use the itertools `flatten` free function. +## 0.7.6 + - Add new adaptor `.multi_cartesian_product()` which is an n-ary product iterator by @tobz1000 + - Add new method `.sorted_by_key()` by @Xion + - Provide simpler and faster `.count()` for `.unique()` and `.unique_by()` +## 0.7.5 + - `.multipeek()` now implements `PeekingNext`, by @nicopap. +## 0.7.4 + - Add new adaptor `.update()` by @lucasem; this adaptor is used to modify an element before passing it on in an iterator chain. +## 0.7.3 + - Add new method `.collect_tuple()` by @matklad; it makes a tuple out of the iterator's elements if the number of them matches **exactly**. + - Implement `fold` and `collect` for `.map_results()` which means it reuses the code of the standard `.map()` for these methods. +## 0.7.2 + - Add new adaptor `.merge_join_by` by @srijs; a heterogeneous merge join for two ordered sequences. +## 0.7.1 + - Iterator adaptors and iterators in itertools now use the same `must_use` reminder that the standard library adaptors do, by @matematikaedit and @bluss *“iterator adaptors are lazy and do nothing unless consumed”*. +## 0.7.0 + - Faster `izip!()` by @krdln + - `izip!()` is now a wrapper for repeated regular `.zip()` and a single `.map()`. This means it optimizes as well as the standard library `.zip()` it uses. **Note:** `multizip` and `izip!()` are now different! The former has a named type but the latter optimizes better. + - Faster `.unique()` + - `no_std` support, which is opt-in! + - Many lovable features are still there without std, like `izip!()` or `.format()` or `.merge()`, but not those that use collections. + - Trait bounds were required up front instead of just on the type: `group_by`'s `PartialEq` by @Phlosioneer and `repeat_call`'s `FnMut`. + - Removed deprecated constructor `Zip::new` — use `izip!()` or `multizip()` +## 0.6.5 + - Fix bug in `.cartesian_product()`'s fold (which only was visible for unfused iterators). +## 0.6.4 + - Add specific `fold` implementations for `.cartesian_product()` and `cons_tuples()`, which improves their performance in fold, foreach, and iterator consumers derived from them. +## 0.6.3 + - Add iterator adaptor `.positions(predicate)` by @tmccombs +## 0.6.2 + - Add function `process_results` which can “lift” a function of the regular values of an iterator so that it can process the `Ok` values from an iterator of `Results` instead, by @shepmaster + - Add iterator method `.concat()` which combines all iterator elements into a single collection using the `Extend` trait, by @srijs +## 0.6.1 + - Better size hint testing and subsequent size hint bugfixes by @rkarp. Fixes bugs in product, `interleave_shortest` size hints. + - New iterator method `.all_equal()` by @phimuemue +## 0.6.0 + - Deprecated names were removed in favour of their replacements + - `.flatten()` does not implement double ended iteration anymore + - `.fold_while()` uses `&mut self` and returns `FoldWhile`, for composability #168 + - `.foreach()` and `.fold1()` use `self`, like `.fold()` does. + - `.combinations(0)` now produces a single empty vector. #174 +## 0.5.10 + - Add itertools method `.kmerge_by()` (and corresponding free function) + - Relaxed trait requirement of `.kmerge()` and `.minmax()` to PartialOrd. +## 0.5.9 + - Add multipeek method `.reset_peek()` + - Add categories +## 0.5.8 + - Add iterator adaptor `.peeking_take_while()` and its trait `PeekingNext`. +## 0.5.7 + - Add iterator adaptor `.with_position()` + - Fix multipeek's performance for long peeks by using `VecDeque`. +## 0.5.6 + - Add `.map_results()` +## 0.5.5 + - Many more adaptors now implement `Debug` + - Add free function constructor `repeat_n`. `RepeatN::new` is now deprecated. +## 0.5.4 + - Add infinite generator function `iterate`, that takes a seed and a closure. +## 0.5.3 + - Special-cased `.fold()` for flatten and put back. `.foreach()` now uses fold on the iterator, to pick up any iterator specific loop implementation. + - `.combinations(n)` asserts up front that `n != 0`, instead of running into an error on the second iterator element. +## 0.5.2 + - Add `.tuples::()` that iterates by two, three or four elements at a time (where `T` is a tuple type). + - Add `.tuple_windows::()` that iterates using a window of the two, three or four most recent elements. + - Add `.next_tuple::()` method, that picks the next two, three or four elements in one go. + - `.interleave()` now has an accurate size hint. +## 0.5.1 + - Workaround module/function name clash that made racer crash on completing itertools. Only internal changes needed. +## 0.5.0 + - [Release announcement](https://bluss.github.io/rust/2016/09/26/itertools-0.5.0/) + - Renamed: + - `combinations` is now `tuple_combinations` + - `combinations_n` to `combinations` + - `group_by_lazy`, `chunks_lazy` to `group_by`, `chunks` + - `Unfold::new` to `unfold()` + - `RepeatCall::new` to `repeat_call()` + - `Zip::new` to `multizip` + - `PutBack::new`, `PutBackN::new` to `put_back`, `put_back_n` + - `PutBack::with_value` is now a builder setter, not a constructor + - `MultiPeek::new`, `.multipeek()` to `multipeek()` + - `format` to `format_with` and `format_default` to `format` + - `.into_rc()` to `rciter` + - `Partition` enum is now `Either` + - Module reorganization: + - All iterator structs are under `itertools::structs` but also reexported to the top level, for backwards compatibility + - All free functions are reexported at the root, `itertools::free` will be removed in the next version + - Removed: + - `ZipSlices`, use `.zip()` instead + - `.enumerate_from()`, `ZipTrusted`, due to being unstable + - `.mend_slices()`, moved to crate `odds` + - Stride, StrideMut, moved to crate `odds` + - `linspace()`, moved to crate `itertools-num` + - `.sort_by()`, use `.sorted_by()` + - `.is_empty_hint()`, use `.size_hint()` + - `.dropn()`, use `.dropping()` + - `.map_fn()`, use `.map()` + - `.slice()`, use `.take()` / `.skip()` + - helper traits in `misc` + - `new` constructors on iterator structs, use `Itertools` trait or free functions instead + - `itertools::size_hint` is now private + - Behaviour changes: + - `format` and `format_with` helpers now panic if you try to format them more than once. + - `repeat_call` is not double ended anymore + - New features: + - tuple flattening iterator is constructible with `cons_tuples` + - itertools reexports `Either` from the `either` crate. `Either` is an iterator when `L, R` are. + - `MinMaxResult` now implements `Copy` and `Clone` + - `tuple_combinations` supports 1-4 tuples of combinations (previously just 2) +## 0.4.19 + - Add `.minmax_by()` + - Add `itertools::free::cloned` + - Add `itertools::free::rciter` + - Improve `.step(n)` slightly to take advantage of specialized Fuse better. +## 0.4.18 + - Only changes related to the "unstable" crate feature. This feature is more or less deprecated. + - Use deprecated warnings when unstable is enabled. `.enumerate_from()` will be removed imminently since it's using a deprecated libstd trait. +## 0.4.17 + - Fix bug in `.kmerge()` that caused it to often produce the wrong order #134 +## 0.4.16 + - Improve precision of the `interleave_shortest` adaptor's size hint (it is now computed exactly when possible). +## 0.4.15 + - Fixup on top of the workaround in 0.4.14. A function in `itertools::free` was removed by mistake and now it is added back again. +## 0.4.14 + - Workaround an upstream regression in a Rust nightly build that broke compilation of of `itertools::free::{interleave, merge}` +## 0.4.13 + - Add `.minmax()` and `.minmax_by_key()`, iterator methods for finding both minimum and maximum in one scan. + - Add `.format_default()`, a simpler version of `.format()` (lazy formatting for iterators). +## 0.4.12 + - Add `.zip_eq()`, an adaptor like `.zip()` except it ensures iterators of inequal length don't pass silently (instead it panics). + - Add `.fold_while()`, an iterator method that is a fold that can short-circuit. + - Add `.partition_map()`, an iterator method that can separate elements into two collections. +## 0.4.11 + - Add `.get()` for `Stride{,Mut}` and `.get_mut()` for `StrideMut` +## 0.4.10 + - Improve performance of `.kmerge()` +## 0.4.9 + - Add k-ary merge adaptor `.kmerge()` + - Fix a bug in `.islice()` with ranges `a..b` where a `> b`. +## 0.4.8 + - Implement `Clone`, `Debug` for `Linspace` +## 0.4.7 + - Add function `diff_with()` that compares two iterators + - Add `.combinations_n()`, an n-ary combinations iterator + - Add methods `PutBack::with_value` and `PutBack::into_parts`. +## 0.4.6 + - Add method `.sorted()` + - Add module `itertools::free` with free function variants of common iterator adaptors and methods. For example `enumerate(iterable)`, `rev(iterable)`, and so on. +## 0.4.5 + - Add `.flatten()` +## 0.4.4 + - Allow composing `ZipSlices` with itself +## 0.4.3 + - Write `iproduct!()` as a single expression; this allows temporary values in its arguments. +## 0.4.2 + - Add `.fold_options()` + - Require Rust 1.1 or later +## 0.4.1 + - Update `.dropping()` to take advantage of `.nth()` +## 0.4.0 + - `.merge()`, `.unique()` and `.dedup()` now perform better due to not using function pointers + - Add free functions `enumerate()` and `rev()` + - Breaking changes: + - Return types of `.merge()` and `.merge_by()` renamed and changed + - Method `Merge::new` removed + - `.merge_by()` now takes a closure that returns bool. + - Return type of `.dedup()` changed + - Return type of `.mend_slices()` changed + - Return type of `.unique()` changed + - Removed function `times()`, struct `Times`: use a range instead + - Removed deprecated macro `icompr!()` + - Removed deprecated `FnMap` and method `.fn_map()`: use `.map_fn()` + - `.interleave_shortest()` is no longer guaranteed to act like fused +## 0.3.25 + - Rename `.sort_by()` to `.sorted_by()`. Old name is deprecated. + - Fix well-formedness warnings from RFC 1214, no user visible impact +## 0.3.24 + - Improve performance of `.merge()`'s ordering function slightly +## 0.3.23 + - Added `.chunks()`, similar to (and based on) `.group_by_lazy()`. + - Tweak linspace to match numpy.linspace and make it double ended. +## 0.3.22 + - Added `ZipSlices`, a fast zip for slices +## 0.3.21 + - Remove `Debug` impl for `Format`, it will have different use later +## 0.3.20 + - Optimize `.group_by_lazy()` +## 0.3.19 + - Added `.group_by_lazy()`, a possibly nonallocating group by + - Added `.format()`, a nonallocating formatting helper for iterators + - Remove uses of `RandomAccessIterator` since it has been deprecated in Rust. +## 0.3.17 + - Added (adopted) `Unfold` from Rust +## 0.3.16 + - Added adaptors `.unique()`, `.unique_by()` +## 0.3.15 + - Added method `.sort_by()` +## 0.3.14 + - Added adaptor `.while_some()` +## 0.3.13 + - Added adaptor `.interleave_shortest()` + - Added adaptor `.pad_using()` +## 0.3.11 + - Added `assert_equal` function +## 0.3.10 + - Bugfix `.combinations()` `size_hint`. +## 0.3.8 + - Added source `RepeatCall` +## 0.3.7 + - Added adaptor `PutBackN` + - Added adaptor `.combinations()` +## 0.3.6 + - Added `itertools::partition`, partition a sequence in place based on a predicate. + - Deprecate `icompr!()` with no replacement. +## 0.3.5 + - `.map_fn()` replaces deprecated `.fn_map()`. +## 0.3.4 + - `.take_while_ref()` *by-ref adaptor* + - `.coalesce()` *adaptor* + - `.mend_slices()` *adaptor* +## 0.3.3 + - `.dropping_back()` *method* + - `.fold1()` *method* + - `.is_empty_hint()` *method* diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "itertools" +version = "0.10.5" +authors = ["bluss"] +exclude = ["/bors.toml"] +description = "Extra iterator adaptors, iterator methods, free functions, and macros." +documentation = "https://docs.rs/itertools/" +readme = "README.md" +keywords = ["iterator", "data-structure", "zip", "product", "group-by"] +categories = ["algorithms", "rust-patterns"] +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-itertools/itertools" +[package.metadata.release] +no-dev-version = true +[profile.bench] +debug = true + +[lib] +test = false +bench = false + +[[bench]] +name = "tuple_combinations" +harness = false + +[[bench]] +name = "tuples" +harness = false + +[[bench]] +name = "fold_specialization" +harness = false + +[[bench]] +name = "combinations_with_replacement" +harness = false + +[[bench]] +name = "tree_fold1" +harness = false + +[[bench]] +name = "bench1" +harness = false + +[[bench]] +name = "combinations" +harness = false + +[[bench]] +name = "powerset" +harness = false +[dependencies.either] +version = "1.0" +default-features = false +[dev-dependencies.criterion] +version = "=0" + +[dev-dependencies.paste] +version = "1.0.0" + +[dev-dependencies.permutohedron] +version = "0.2" + +[dev-dependencies.quickcheck] +version = "0.9" +default-features = false + +[dev-dependencies.rand] +version = "0.7" + +[features] +default = ["use_std"] +use_alloc = [] +use_std = ["use_alloc", "either/use_std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/Cargo.toml.orig 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,79 @@ +[package] +name = "itertools" +version = "0.10.5" + +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-itertools/itertools" +documentation = "https://docs.rs/itertools/" +authors = ["bluss"] +readme = "README.md" + +description = "Extra iterator adaptors, iterator methods, free functions, and macros." + +keywords = ["iterator", "data-structure", "zip", "product", "group-by"] +categories = ["algorithms", "rust-patterns"] +exclude = ["/bors.toml"] + +edition = "2018" + +[package.metadata.release] +no-dev-version = true + +[lib] +bench = false +test = false + +[dependencies] +either = { version = "1.0", default-features = false } + +[dev-dependencies] +rand = "0.7" +criterion = "=0" # TODO how could this work with our minimum supported Rust version? +paste = "1.0.0" # Used in test_std to instantiate generic tests + +[dev-dependencies.quickcheck] +version = "0.9" +default-features = false + +[dev-dependencies.permutohedron] +version = "0.2" + +[features] +default = ["use_std"] +use_std = ["use_alloc", "either/use_std"] +use_alloc = [] + +[profile] +bench = { debug = true } + +[[bench]] +name = "tuple_combinations" +harness = false + +[[bench]] +name = "tuples" +harness = false + +[[bench]] +name = "fold_specialization" +harness = false + +[[bench]] +name = "combinations_with_replacement" +harness = false + +[[bench]] +name = "tree_fold1" +harness = false + +[[bench]] +name = "bench1" +harness = false + +[[bench]] +name = "combinations" +harness = false + +[[bench]] +name = "powerset" +harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-APACHE 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/LICENSE-MIT 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2015 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/README.md clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/README.md 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,44 @@ +# Itertools + +Extra iterator adaptors, functions and macros. + +Please read the [API documentation here](https://docs.rs/itertools/). + +[![build_status](https://github.com/rust-itertools/itertools/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-itertools/itertools/actions) +[![crates.io](https://img.shields.io/crates/v/itertools.svg)](https://crates.io/crates/itertools) + +How to use with Cargo: + +```toml +[dependencies] +itertools = "0.10.5" +``` + +How to use in your crate: + +```rust +use itertools::Itertools; +``` + +## How to contribute + +- Fix a bug or implement a new thing +- Include tests for your new feature, preferably a QuickCheck test +- Make a Pull Request + +For new features, please first consider filing a PR to [rust-lang/rust](https://github.com/rust-lang/rust), +adding your new feature to the `Iterator` trait of the standard library, if you believe it is reasonable. +If it isn't accepted there, proposing it for inclusion in ``itertools`` is a good idea. +The reason for doing is this is so that we avoid future breakage as with ``.flatten()``. +However, if your feature involves heap allocation, such as storing elements in a ``Vec``, +then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead. + +## License + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +https://www.apache.org/licenses/LICENSE-2.0 or the MIT license +https://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/bench1.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/bench1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/bench1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/bench1.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,877 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use itertools::Itertools; +use itertools::free::cloned; +use itertools::iproduct; + +use std::iter::repeat; +use std::cmp; +use std::ops::{Add, Range}; + +mod extra; + +use crate::extra::ZipSlices; + +fn slice_iter(c: &mut Criterion) { + let xs: Vec<_> = repeat(1i32).take(20).collect(); + + c.bench_function("slice iter", move |b| { + b.iter(|| for elt in xs.iter() { + black_box(elt); + }) + }); +} + +fn slice_iter_rev(c: &mut Criterion) { + let xs: Vec<_> = repeat(1i32).take(20).collect(); + + c.bench_function("slice iter rev", move |b| { + b.iter(|| for elt in xs.iter().rev() { + black_box(elt); + }) + }); +} + +fn zip_default_zip(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zip default zip", move |b| { + b.iter(|| { + for (&x, &y) in xs.iter().zip(&ys) { + black_box(x); + black_box(y); + } + }) + }); +} + +fn zipdot_i32_default_zip(c: &mut Criterion) { + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot i32 default zip", move |b| { + b.iter(|| { + let mut s = 0; + for (&x, &y) in xs.iter().zip(&ys) { + s += x * y; + } + s + }) + }); +} + +fn zipdot_f32_default_zip(c: &mut Criterion) { + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot f32 default zip", move |b| { + b.iter(|| { + let mut s = 0.; + for (&x, &y) in xs.iter().zip(&ys) { + s += x * y; + } + s + }) + }); +} + +fn zip_default_zip3(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let zs = vec![0; 766]; + let xs = black_box(xs); + let ys = black_box(ys); + let zs = black_box(zs); + + c.bench_function("zip default zip3", move |b| { + b.iter(|| { + for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) { + black_box(x); + black_box(y); + black_box(z); + } + }) + }); +} + +fn zip_slices_ziptuple(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + + c.bench_function("zip slices ziptuple", move |b| { + b.iter(|| { + let xs = black_box(&xs); + let ys = black_box(&ys); + for (&x, &y) in itertools::multizip((xs, ys)) { + black_box(x); + black_box(y); + } + }) + }); +} + +fn zipslices(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipslices", move |b| { + b.iter(|| { + for (&x, &y) in ZipSlices::new(&xs, &ys) { + black_box(x); + black_box(y); + } + }) + }); +} + +fn zipslices_mut(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let mut ys = black_box(ys); + + c.bench_function("zipslices mut", move |b| { + b.iter(|| { + for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { + black_box(x); + black_box(y); + } + }) + }); +} + +fn zipdot_i32_zipslices(c: &mut Criterion) { + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot i32 zipslices", move |b| { + b.iter(|| { + let mut s = 0i32; + for (&x, &y) in ZipSlices::new(&xs, &ys) { + s += x * y; + } + s + }) + }); +} + +fn zipdot_f32_zipslices(c: &mut Criterion) { + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot f32 zipslices", move |b| { + b.iter(|| { + let mut s = 0.; + for (&x, &y) in ZipSlices::new(&xs, &ys) { + s += x * y; + } + s + }) + }); +} + +fn zip_checked_counted_loop(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zip checked counted loop", move |b| { + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + for i in 0..len { + let x = xs[i]; + let y = ys[i]; + black_box(x); + black_box(y); + } + }) + }); +} + +fn zipdot_i32_checked_counted_loop(c: &mut Criterion) { + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot i32 checked counted loop", move |b| { + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + let mut s = 0i32; + + for i in 0..len { + s += xs[i] * ys[i]; + } + s + }) + }); +} + +fn zipdot_f32_checked_counted_loop(c: &mut Criterion) { + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot f32 checked counted loop", move |b| { + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + let mut s = 0.; + + for i in 0..len { + s += xs[i] * ys[i]; + } + s + }) + }); +} + +fn zipdot_f32_checked_counted_unrolled_loop(c: &mut Criterion) { + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot f32 checked counted unrolled loop", move |b| { + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let mut xs = &xs[..len]; + let mut ys = &ys[..len]; + + let mut s = 0.; + let (mut p0, mut p1, mut p2, mut p3, mut p4, mut p5, mut p6, mut p7) = + (0., 0., 0., 0., 0., 0., 0., 0.); + + // how to unroll and have bounds checks eliminated (by cristicbz) + // split sum into eight parts to enable vectorization (by bluss) + while xs.len() >= 8 { + p0 += xs[0] * ys[0]; + p1 += xs[1] * ys[1]; + p2 += xs[2] * ys[2]; + p3 += xs[3] * ys[3]; + p4 += xs[4] * ys[4]; + p5 += xs[5] * ys[5]; + p6 += xs[6] * ys[6]; + p7 += xs[7] * ys[7]; + + xs = &xs[8..]; + ys = &ys[8..]; + } + s += p0 + p4; + s += p1 + p5; + s += p2 + p6; + s += p3 + p7; + + for i in 0..xs.len() { + s += xs[i] * ys[i]; + } + s + }) + }); +} + +fn zip_unchecked_counted_loop(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zip unchecked counted loop", move |b| { + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + black_box(x); + black_box(y); + } + } + }) + }); +} + +fn zipdot_i32_unchecked_counted_loop(c: &mut Criterion) { + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot i32 unchecked counted loop", move |b| { + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + let mut s = 0i32; + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; + } + } + s + }) + }); +} + +fn zipdot_f32_unchecked_counted_loop(c: &mut Criterion) { + let xs = vec![2.; 1024]; + let ys = vec![2.; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + c.bench_function("zipdot f32 unchecked counted loop", move |b| { + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + let mut s = 0f32; + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; + } + } + s + }) + }); +} + +fn zip_unchecked_counted_loop3(c: &mut Criterion) { + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let zs = vec![0; 766]; + let xs = black_box(xs); + let ys = black_box(ys); + let zs = black_box(zs); + + c.bench_function("zip unchecked counted loop3", move |b| { + b.iter(|| { + let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + let z = *zs.get_unchecked(i); + black_box(x); + black_box(y); + black_box(z); + } + } + }) + }); +} + +fn group_by_lazy_1(c: &mut Criterion) { + let mut data = vec![0; 1024]; + for (index, elt) in data.iter_mut().enumerate() { + *elt = index / 10; + } + + let data = black_box(data); + + c.bench_function("group by lazy 1", move |b| { + b.iter(|| { + for (_key, group) in &data.iter().group_by(|elt| **elt) { + for elt in group { + black_box(elt); + } + } + }) + }); +} + +fn group_by_lazy_2(c: &mut Criterion) { + let mut data = vec![0; 1024]; + for (index, elt) in data.iter_mut().enumerate() { + *elt = index / 2; + } + + let data = black_box(data); + + c.bench_function("group by lazy 2", move |b| { + b.iter(|| { + for (_key, group) in &data.iter().group_by(|elt| **elt) { + for elt in group { + black_box(elt); + } + } + }) + }); +} + +fn slice_chunks(c: &mut Criterion) { + let data = vec![0; 1024]; + + let data = black_box(data); + let sz = black_box(10); + + c.bench_function("slice chunks", move |b| { + b.iter(|| { + for group in data.chunks(sz) { + for elt in group { + black_box(elt); + } + } + }) + }); +} + +fn chunks_lazy_1(c: &mut Criterion) { + let data = vec![0; 1024]; + + let data = black_box(data); + let sz = black_box(10); + + c.bench_function("chunks lazy 1", move |b| { + b.iter(|| { + for group in &data.iter().chunks(sz) { + for elt in group { + black_box(elt); + } + } + }) + }); +} + +fn equal(c: &mut Criterion) { + let data = vec![7; 1024]; + let l = data.len(); + let alpha = black_box(&data[1..]); + let beta = black_box(&data[..l - 1]); + + c.bench_function("equal", move |b| { + b.iter(|| { + itertools::equal(alpha, beta) + }) + }); +} + +fn merge_default(c: &mut Criterion) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = black_box(data1); + let data2 = black_box(data2); + + c.bench_function("merge default", move |b| { + b.iter(|| { + data1.iter().merge(&data2).count() + }) + }); +} + +fn merge_by_cmp(c: &mut Criterion) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = black_box(data1); + let data2 = black_box(data2); + + c.bench_function("merge by cmp", move |b| { + b.iter(|| { + data1.iter().merge_by(&data2, PartialOrd::le).count() + }) + }); +} + +fn merge_by_lt(c: &mut Criterion) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = black_box(data1); + let data2 = black_box(data2); + + c.bench_function("merge by lt", move |b| { + b.iter(|| { + data1.iter().merge_by(&data2, |a, b| a <= b).count() + }) + }); +} + +fn kmerge_default(c: &mut Criterion) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = black_box(data1); + let data2 = black_box(data2); + let its = &[data1.iter(), data2.iter()]; + + c.bench_function("kmerge default", move |b| { + b.iter(|| { + its.iter().cloned().kmerge().count() + }) + }); +} + +fn kmerge_tenway(c: &mut Criterion) { + let mut data = vec![0; 10240]; + + let mut state = 1729u16; + fn rng(state: &mut u16) -> u16 { + let new = state.wrapping_mul(31421) + 6927; + *state = new; + new + } + + for elt in &mut data { + *elt = rng(&mut state); + } + + let mut chunks = Vec::new(); + let mut rest = &mut data[..]; + while rest.len() > 0 { + let chunk_len = 1 + rng(&mut state) % 512; + let chunk_len = cmp::min(rest.len(), chunk_len as usize); + let (fst, tail) = {rest}.split_at_mut(chunk_len); + fst.sort(); + chunks.push(fst.iter().cloned()); + rest = tail; + } + + // println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len()))); + + c.bench_function("kmerge tenway", move |b| { + b.iter(|| { + chunks.iter().cloned().kmerge().count() + }) + }); +} + +fn fast_integer_sum(iter: I) -> I::Item + where I: IntoIterator, + I::Item: Default + Add +{ + iter.into_iter().fold(<_>::default(), |x, y| x + y) +} + +fn step_vec_2(c: &mut Criterion) { + let v = vec![0; 1024]; + + c.bench_function("step vec 2", move |b| { + b.iter(|| { + fast_integer_sum(cloned(v.iter().step_by(2))) + }) + }); +} + +fn step_vec_10(c: &mut Criterion) { + let v = vec![0; 1024]; + + c.bench_function("step vec 10", move |b| { + b.iter(|| { + fast_integer_sum(cloned(v.iter().step_by(10))) + }) + }); +} + +fn step_range_2(c: &mut Criterion) { + let v = black_box(0..1024); + + c.bench_function("step range 2", move |b| { + b.iter(|| { + fast_integer_sum(v.clone().step_by(2)) + }) + }); +} + +fn step_range_10(c: &mut Criterion) { + let v = black_box(0..1024); + + c.bench_function("step range 10", move |b| { + b.iter(|| { + fast_integer_sum(v.clone().step_by(10)) + }) + }); +} + +fn cartesian_product_iterator(c: &mut Criterion) { + let xs = vec![0; 16]; + + c.bench_function("cartesian product iterator", move |b| { + b.iter(|| { + let mut sum = 0; + for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) { + sum += x; + sum += y; + sum += z; + } + sum + }) + }); +} + +fn cartesian_product_fold(c: &mut Criterion) { + let xs = vec![0; 16]; + + c.bench_function("cartesian product fold", move |b| { + b.iter(|| { + let mut sum = 0; + iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| { + sum += x; + sum += y; + sum += z; + }); + sum + }) + }); +} + +fn multi_cartesian_product_iterator(c: &mut Criterion) { + let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; + + c.bench_function("multi cartesian product iterator", move |b| { + b.iter(|| { + let mut sum = 0; + for x in xs.iter().multi_cartesian_product() { + sum += x[0]; + sum += x[1]; + sum += x[2]; + } + sum + }) + }); +} + +fn multi_cartesian_product_fold(c: &mut Criterion) { + let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; + + c.bench_function("multi cartesian product fold", move |b| { + b.iter(|| { + let mut sum = 0; + xs.iter().multi_cartesian_product().fold((), |(), x| { + sum += x[0]; + sum += x[1]; + sum += x[2]; + }); + sum + }) + }); +} + +fn cartesian_product_nested_for(c: &mut Criterion) { + let xs = vec![0; 16]; + + c.bench_function("cartesian product nested for", move |b| { + b.iter(|| { + let mut sum = 0; + for &x in &xs { + for &y in &xs { + for &z in &xs { + sum += x; + sum += y; + sum += z; + } + } + } + sum + }) + }); +} + +fn all_equal(c: &mut Criterion) { + let mut xs = vec![0; 5_000_000]; + xs.extend(vec![1; 5_000_000]); + + c.bench_function("all equal", move |b| { + b.iter(|| xs.iter().all_equal()) + }); +} + +fn all_equal_for(c: &mut Criterion) { + let mut xs = vec![0; 5_000_000]; + xs.extend(vec![1; 5_000_000]); + + c.bench_function("all equal for", move |b| { + b.iter(|| { + for &x in &xs { + if x != xs[0] { + return false; + } + } + true + }) + }); +} + +fn all_equal_default(c: &mut Criterion) { + let mut xs = vec![0; 5_000_000]; + xs.extend(vec![1; 5_000_000]); + + c.bench_function("all equal default", move |b| { + b.iter(|| xs.iter().dedup().nth(1).is_none()) + }); +} + +const PERM_COUNT: usize = 6; + +fn permutations_iter(c: &mut Criterion) { + struct NewIterator(Range); + + impl Iterator for NewIterator { + type Item = usize; + + fn next(&mut self) -> Option { + self.0.next() + } + } + + c.bench_function("permutations iter", move |b| { + b.iter(|| { + for _ in NewIterator(0..PERM_COUNT).permutations(PERM_COUNT) { + + } + }) + }); +} + +fn permutations_range(c: &mut Criterion) { + c.bench_function("permutations range", move |b| { + b.iter(|| { + for _ in (0..PERM_COUNT).permutations(PERM_COUNT) { + + } + }) + }); +} + +fn permutations_slice(c: &mut Criterion) { + let v = (0..PERM_COUNT).collect_vec(); + + c.bench_function("permutations slice", move |b| { + b.iter(|| { + for _ in v.as_slice().iter().permutations(PERM_COUNT) { + + } + }) + }); +} + +criterion_group!( + benches, + slice_iter, + slice_iter_rev, + zip_default_zip, + zipdot_i32_default_zip, + zipdot_f32_default_zip, + zip_default_zip3, + zip_slices_ziptuple, + zipslices, + zipslices_mut, + zipdot_i32_zipslices, + zipdot_f32_zipslices, + zip_checked_counted_loop, + zipdot_i32_checked_counted_loop, + zipdot_f32_checked_counted_loop, + zipdot_f32_checked_counted_unrolled_loop, + zip_unchecked_counted_loop, + zipdot_i32_unchecked_counted_loop, + zipdot_f32_unchecked_counted_loop, + zip_unchecked_counted_loop3, + group_by_lazy_1, + group_by_lazy_2, + slice_chunks, + chunks_lazy_1, + equal, + merge_default, + merge_by_cmp, + merge_by_lt, + kmerge_default, + kmerge_tenway, + step_vec_2, + step_vec_10, + step_range_2, + step_range_10, + cartesian_product_iterator, + cartesian_product_fold, + multi_cartesian_product_iterator, + multi_cartesian_product_fold, + cartesian_product_nested_for, + all_equal, + all_equal_for, + all_equal_default, + permutations_iter, + permutations_range, + permutations_slice, +); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,125 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +// approximate 100_000 iterations for each combination +const N1: usize = 100_000; +const N2: usize = 448; +const N3: usize = 86; +const N4: usize = 41; +const N14: usize = 21; + +fn comb_for1(c: &mut Criterion) { + c.bench_function("comb for1", move |b| { + b.iter(|| { + for i in 0..N1 { + black_box(vec![i]); + } + }) + }); +} + +fn comb_for2(c: &mut Criterion) { + c.bench_function("comb for2", move |b| { + b.iter(|| { + for i in 0..N2 { + for j in (i + 1)..N2 { + black_box(vec![i, j]); + } + } + }) + }); +} + +fn comb_for3(c: &mut Criterion) { + c.bench_function("comb for3", move |b| { + b.iter(|| { + for i in 0..N3 { + for j in (i + 1)..N3 { + for k in (j + 1)..N3 { + black_box(vec![i, j, k]); + } + } + } + }) + }); +} + +fn comb_for4(c: &mut Criterion) { + c.bench_function("comb for4", move |b| { + b.iter(|| { + for i in 0..N4 { + for j in (i + 1)..N4 { + for k in (j + 1)..N4 { + for l in (k + 1)..N4 { + black_box(vec![i, j, k, l]); + } + } + } + } + }) + }); +} + +fn comb_c1(c: &mut Criterion) { + c.bench_function("comb c1", move |b| { + b.iter(|| { + for combo in (0..N1).combinations(1) { + black_box(combo); + } + }) + }); +} + +fn comb_c2(c: &mut Criterion) { + c.bench_function("comb c2", move |b| { + b.iter(|| { + for combo in (0..N2).combinations(2) { + black_box(combo); + } + }) + }); +} + +fn comb_c3(c: &mut Criterion) { + c.bench_function("comb c3", move |b| { + b.iter(|| { + for combo in (0..N3).combinations(3) { + black_box(combo); + } + }) + }); +} + +fn comb_c4(c: &mut Criterion) { + c.bench_function("comb c4", move |b| { + b.iter(|| { + for combo in (0..N4).combinations(4) { + black_box(combo); + } + }) + }); +} + +fn comb_c14(c: &mut Criterion) { + c.bench_function("comb c14", move |b| { + b.iter(|| { + for combo in (0..N14).combinations(14) { + black_box(combo); + } + }) + }); +} + +criterion_group!( + benches, + comb_for1, + comb_for2, + comb_for3, + comb_for4, + comb_c1, + comb_c2, + comb_c3, + comb_c4, + comb_c14, +); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations_with_replacement.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations_with_replacement.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations_with_replacement.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/combinations_with_replacement.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,40 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +fn comb_replacement_n10_k5(c: &mut Criterion) { + c.bench_function("comb replacement n10k5", move |b| { + b.iter(|| { + for i in (0..10).combinations_with_replacement(5) { + black_box(i); + } + }) + }); +} + +fn comb_replacement_n5_k10(c: &mut Criterion) { + c.bench_function("comb replacement n5 k10", move |b| { + b.iter(|| { + for i in (0..5).combinations_with_replacement(10) { + black_box(i); + } + }) + }); +} + +fn comb_replacement_n10_k10(c: &mut Criterion) { + c.bench_function("comb replacement n10 k10", move |b| { + b.iter(|| { + for i in (0..10).combinations_with_replacement(10) { + black_box(i); + } + }) + }); +} + +criterion_group!( + benches, + comb_replacement_n10_k5, + comb_replacement_n5_k10, + comb_replacement_n10_k10, +); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/mod.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,2 @@ +pub use self::zipslices::ZipSlices; +mod zipslices; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/zipslices.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/zipslices.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/zipslices.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/extra/zipslices.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,188 @@ +use std::cmp; + +// Note: There are different ways to implement ZipSlices. +// This version performed the best in benchmarks. +// +// I also implemented a version with three pointers (tptr, tend, uptr), +// that mimiced slice::Iter and only checked bounds by using tptr == tend, +// but that was inferior to this solution. + +/// An iterator which iterates two slices simultaneously. +/// +/// `ZipSlices` acts like a double-ended `.zip()` iterator. +/// +/// It was intended to be more efficient than `.zip()`, and it was, then +/// rustc changed how it optimizes so it can not promise improved performance +/// at this time. +/// +/// Note that elements past the end of the shortest of the two slices are ignored. +/// +/// Iterator element type for `ZipSlices` is `(T::Item, U::Item)`. For example, +/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`. +#[derive(Clone)] +pub struct ZipSlices { + t: T, + u: U, + len: usize, + index: usize, +} + +impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> { + /// Create a new `ZipSlices` from slices `a` and `b`. + /// + /// Act like a double-ended `.zip()` iterator, but more efficiently. + /// + /// Note that elements past the end of the shortest of the two slices are ignored. + #[inline(always)] + pub fn new(a: &'a [A], b: &'b [B]) -> Self { + let minl = cmp::min(a.len(), b.len()); + ZipSlices { + t: a, + u: b, + len: minl, + index: 0, + } + } +} + +impl ZipSlices + where T: Slice, + U: Slice +{ + /// Create a new `ZipSlices` from slices `a` and `b`. + /// + /// Act like a double-ended `.zip()` iterator, but more efficiently. + /// + /// Note that elements past the end of the shortest of the two slices are ignored. + #[inline(always)] + pub fn from_slices(a: T, b: U) -> Self { + let minl = cmp::min(a.len(), b.len()); + ZipSlices { + t: a, + u: b, + len: minl, + index: 0, + } + } +} + +impl Iterator for ZipSlices + where T: Slice, + U: Slice +{ + type Item = (T::Item, U::Item); + + #[inline(always)] + fn next(&mut self) -> Option { + unsafe { + if self.index >= self.len { + None + } else { + let i = self.index; + self.index += 1; + Some(( + self.t.get_unchecked(i), + self.u.get_unchecked(i))) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len - self.index; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for ZipSlices + where T: Slice, + U: Slice +{ + #[inline(always)] + fn next_back(&mut self) -> Option { + unsafe { + if self.index >= self.len { + None + } else { + self.len -= 1; + let i = self.len; + Some(( + self.t.get_unchecked(i), + self.u.get_unchecked(i))) + } + } + } +} + +impl ExactSizeIterator for ZipSlices + where T: Slice, + U: Slice +{} + +unsafe impl Slice for ZipSlices + where T: Slice, + U: Slice +{ + type Item = (T::Item, U::Item); + + fn len(&self) -> usize { + self.len - self.index + } + + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + (self.t.get_unchecked(i), + self.u.get_unchecked(i)) + } +} + +/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. +/// +/// Unsafe trait because: +/// +/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. +pub unsafe trait Slice { + /// The type of a reference to the slice's elements + type Item; + #[doc(hidden)] + fn len(&self) -> usize; + #[doc(hidden)] + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; +} + +unsafe impl<'a, T> Slice for &'a [T] { + type Item = &'a T; + #[inline(always)] + fn len(&self) -> usize { (**self).len() } + #[inline(always)] + unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { + debug_assert!(i < self.len()); + (**self).get_unchecked(i) + } +} + +unsafe impl<'a, T> Slice for &'a mut [T] { + type Item = &'a mut T; + #[inline(always)] + fn len(&self) -> usize { (**self).len() } + #[inline(always)] + unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { + debug_assert!(i < self.len()); + // override the lifetime constraints of &mut &'a mut [T] + (*(*self as *mut [T])).get_unchecked_mut(i) + } +} + +#[test] +fn zipslices() { + + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys)); + + let xs = [1, 2, 3, 4, 5, 6]; + let mut ys = [0; 6]; + for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { + *y = *x; + } + ::itertools::assert_equal(&xs, &ys); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/fold_specialization.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/fold_specialization.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/fold_specialization.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/fold_specialization.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,73 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +struct Unspecialized(I); + +impl Iterator for Unspecialized +where I: Iterator +{ + type Item = I::Item; + + #[inline(always)] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +mod specialization { + use super::*; + + pub mod intersperse { + use super::*; + + pub fn external(c: &mut Criterion) + { + let arr = [1; 1024]; + + c.bench_function("external", move |b| { + b.iter(|| { + let mut sum = 0; + for &x in arr.iter().intersperse(&0) { + sum += x; + } + sum + }) + }); + } + + pub fn internal_specialized(c: &mut Criterion) + { + let arr = [1; 1024]; + + c.bench_function("internal specialized", move |b| { + b.iter(|| { + arr.iter().intersperse(&0).fold(0, |acc, x| acc + x) + }) + }); + } + + pub fn internal_unspecialized(c: &mut Criterion) + { + let arr = [1; 1024]; + + c.bench_function("internal unspecialized", move |b| { + b.iter(|| { + Unspecialized(arr.iter().intersperse(&0)).fold(0, |acc, x| acc + x) + }) + }); + } + } +} + +criterion_group!( + benches, + specialization::intersperse::external, + specialization::intersperse::internal_specialized, + specialization::intersperse::internal_unspecialized, +); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/powerset.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/powerset.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/powerset.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/powerset.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,44 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +// Keep aggregate generated elements the same, regardless of powerset length. +const TOTAL_ELEMENTS: usize = 1 << 12; +const fn calc_iters(n: usize) -> usize { + TOTAL_ELEMENTS / (1 << n) +} + +fn powerset_n(c: &mut Criterion, n: usize) { + let id = format!("powerset {}", n); + c.bench_function(id.as_str(), move |b| { + b.iter(|| { + for _ in 0..calc_iters(n) { + for elt in (0..n).powerset() { + black_box(elt); + } + } + }) + }); +} + +fn powerset_0(c: &mut Criterion) { powerset_n(c, 0); } + +fn powerset_1(c: &mut Criterion) { powerset_n(c, 1); } + +fn powerset_2(c: &mut Criterion) { powerset_n(c, 2); } + +fn powerset_4(c: &mut Criterion) { powerset_n(c, 4); } + +fn powerset_8(c: &mut Criterion) { powerset_n(c, 8); } + +fn powerset_12(c: &mut Criterion) { powerset_n(c, 12); } + +criterion_group!( + benches, + powerset_0, + powerset_1, + powerset_2, + powerset_4, + powerset_8, + powerset_12, +); +criterion_main!(benches); \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tree_fold1.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tree_fold1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tree_fold1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tree_fold1.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,144 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use itertools::{Itertools, cloned}; + +trait IterEx : Iterator { + // Another efficient implementation against which to compare, + // but needs `std` so is less desirable. + fn tree_fold1_vec(self, mut f: F) -> Option + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + let hint = self.size_hint().0; + let cap = std::mem::size_of::() * 8 - hint.leading_zeros() as usize; + let mut stack = Vec::with_capacity(cap); + self.enumerate().for_each(|(mut i, mut x)| { + while (i & 1) != 0 { + x = f(stack.pop().unwrap(), x); + i >>= 1; + } + stack.push(x); + }); + stack.into_iter().fold1(f) + } +} +impl IterEx for T {} + +macro_rules! def_benchs { + ($N:expr, + $FUN:ident, + $BENCH_NAME:ident, + ) => ( + mod $BENCH_NAME { + use super::*; + + pub fn sum(c: &mut Criterion) { + let v: Vec = (0.. $N).collect(); + + c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " sum"), move |b| { + b.iter(|| { + cloned(&v).$FUN(|x, y| x + y) + }) + }); + } + + pub fn complex_iter(c: &mut Criterion) { + let u = (3..).take($N / 2); + let v = (5..).take($N / 2); + let it = u.chain(v); + + c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " complex iter"), move |b| { + b.iter(|| { + it.clone().map(|x| x as f32).$FUN(f32::atan2) + }) + }); + } + + pub fn string_format(c: &mut Criterion) { + // This goes quadratic with linear `fold1`, so use a smaller + // size to not waste too much time in travis. The allocations + // in here are so expensive anyway that it'll still take + // way longer per iteration than the other two benchmarks. + let v: Vec = (0.. ($N/4)).collect(); + + c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " string format"), move |b| { + b.iter(|| { + cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) + }) + }); + } + } + + criterion_group!( + $BENCH_NAME, + $BENCH_NAME::sum, + $BENCH_NAME::complex_iter, + $BENCH_NAME::string_format, + ); + ) +} + +def_benchs!{ + 10_000, + fold1, + fold1_10k, +} + +def_benchs!{ + 10_000, + tree_fold1, + tree_fold1_stack_10k, +} + +def_benchs!{ + 10_000, + tree_fold1_vec, + tree_fold1_vec_10k, +} + +def_benchs!{ + 100, + fold1, + fold1_100, +} + +def_benchs!{ + 100, + tree_fold1, + tree_fold1_stack_100, +} + +def_benchs!{ + 100, + tree_fold1_vec, + tree_fold1_vec_100, +} + +def_benchs!{ + 8, + fold1, + fold1_08, +} + +def_benchs!{ + 8, + tree_fold1, + tree_fold1_stack_08, +} + +def_benchs!{ + 8, + tree_fold1_vec, + tree_fold1_vec_08, +} + +criterion_main!( + fold1_10k, + tree_fold1_stack_10k, + tree_fold1_vec_10k, + fold1_100, + tree_fold1_stack_100, + tree_fold1_vec_100, + fold1_08, + tree_fold1_stack_08, + tree_fold1_vec_08, +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuple_combinations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuple_combinations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuple_combinations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuple_combinations.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,113 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +// approximate 100_000 iterations for each combination +const N1: usize = 100_000; +const N2: usize = 448; +const N3: usize = 86; +const N4: usize = 41; + +fn tuple_comb_for1(c: &mut Criterion) { + c.bench_function("tuple comb for1", move |b| { + b.iter(|| { + for i in 0..N1 { + black_box(i); + } + }) + }); +} + +fn tuple_comb_for2(c: &mut Criterion) { + c.bench_function("tuple comb for2", move |b| { + b.iter(|| { + for i in 0..N2 { + for j in (i + 1)..N2 { + black_box(i + j); + } + } + }) + }); +} + +fn tuple_comb_for3(c: &mut Criterion) { + c.bench_function("tuple comb for3", move |b| { + b.iter(|| { + for i in 0..N3 { + for j in (i + 1)..N3 { + for k in (j + 1)..N3 { + black_box(i + j + k); + } + } + } + }) + }); +} + +fn tuple_comb_for4(c: &mut Criterion) { + c.bench_function("tuple comb for4", move |b| { + b.iter(|| { + for i in 0..N4 { + for j in (i + 1)..N4 { + for k in (j + 1)..N4 { + for l in (k + 1)..N4 { + black_box(i + j + k + l); + } + } + } + } + }) + }); +} + +fn tuple_comb_c1(c: &mut Criterion) { + c.bench_function("tuple comb c1", move |b| { + b.iter(|| { + for (i,) in (0..N1).tuple_combinations() { + black_box(i); + } + }) + }); +} + +fn tuple_comb_c2(c: &mut Criterion) { + c.bench_function("tuple comb c2", move |b| { + b.iter(|| { + for (i, j) in (0..N2).tuple_combinations() { + black_box(i + j); + } + }) + }); +} + +fn tuple_comb_c3(c: &mut Criterion) { + c.bench_function("tuple comb c3", move |b| { + b.iter(|| { + for (i, j, k) in (0..N3).tuple_combinations() { + black_box(i + j + k); + } + }) + }); +} + +fn tuple_comb_c4(c: &mut Criterion) { + c.bench_function("tuple comb c4", move |b| { + b.iter(|| { + for (i, j, k, l) in (0..N4).tuple_combinations() { + black_box(i + j + k + l); + } + }) + }); +} + +criterion_group!( + benches, + tuple_comb_for1, + tuple_comb_for2, + tuple_comb_for3, + tuple_comb_for4, + tuple_comb_c1, + tuple_comb_c2, + tuple_comb_c3, + tuple_comb_c4, +); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuples.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuples.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuples.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/benches/tuples.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,213 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use itertools::Itertools; + +fn s1(a: u32) -> u32 { + a +} + +fn s2(a: u32, b: u32) -> u32 { + a + b +} + +fn s3(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} + +fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 { + a + b + c + d +} + +fn sum_s1(s: &[u32]) -> u32 { + s1(s[0]) +} + +fn sum_s2(s: &[u32]) -> u32 { + s2(s[0], s[1]) +} + +fn sum_s3(s: &[u32]) -> u32 { + s3(s[0], s[1], s[2]) +} + +fn sum_s4(s: &[u32]) -> u32 { + s4(s[0], s[1], s[2], s[3]) +} + +fn sum_t1(s: &(&u32, )) -> u32 { + s1(*s.0) +} + +fn sum_t2(s: &(&u32, &u32)) -> u32 { + s2(*s.0, *s.1) +} + +fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 { + s3(*s.0, *s.1, *s.2) +} + +fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 { + s4(*s.0, *s.1, *s.2, *s.3) +} + +macro_rules! def_benchs { + ($N:expr; + $BENCH_GROUP:ident, + $TUPLE_FUN:ident, + $TUPLES:ident, + $TUPLE_WINDOWS:ident; + $SLICE_FUN:ident, + $CHUNKS:ident, + $WINDOWS:ident; + $FOR_CHUNKS:ident, + $FOR_WINDOWS:ident + ) => ( + fn $FOR_CHUNKS(c: &mut Criterion) { + let v: Vec = (0.. $N * 1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($FOR_CHUNKS).replace('_', " "), move |b| { + b.iter(|| { + let mut j = 0; + for _ in 0..1_000 { + s += $SLICE_FUN(&v[j..(j + $N)]); + j += $N; + } + s + }) + }); + } + + fn $FOR_WINDOWS(c: &mut Criterion) { + let v: Vec = (0..1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($FOR_WINDOWS).replace('_', " "), move |b| { + b.iter(|| { + for i in 0..(1_000 - $N) { + s += $SLICE_FUN(&v[i..(i + $N)]); + } + s + }) + }); + } + + fn $TUPLES(c: &mut Criterion) { + let v: Vec = (0.. $N * 1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($TUPLES).replace('_', " "), move |b| { + b.iter(|| { + for x in v.iter().tuples() { + s += $TUPLE_FUN(&x); + } + s + }) + }); + } + + fn $CHUNKS(c: &mut Criterion) { + let v: Vec = (0.. $N * 1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($CHUNKS).replace('_', " "), move |b| { + b.iter(|| { + for x in v.chunks($N) { + s += $SLICE_FUN(x); + } + s + }) + }); + } + + fn $TUPLE_WINDOWS(c: &mut Criterion) { + let v: Vec = (0..1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($TUPLE_WINDOWS).replace('_', " "), move |b| { + b.iter(|| { + for x in v.iter().tuple_windows() { + s += $TUPLE_FUN(&x); + } + s + }) + }); + } + + fn $WINDOWS(c: &mut Criterion) { + let v: Vec = (0..1_000).collect(); + let mut s = 0; + c.bench_function(&stringify!($WINDOWS).replace('_', " "), move |b| { + b.iter(|| { + for x in v.windows($N) { + s += $SLICE_FUN(x); + } + s + }) + }); + } + + criterion_group!( + $BENCH_GROUP, + $FOR_CHUNKS, + $FOR_WINDOWS, + $TUPLES, + $CHUNKS, + $TUPLE_WINDOWS, + $WINDOWS, + ); + ) +} + +def_benchs!{ + 1; + benches_1, + sum_t1, + tuple_chunks_1, + tuple_windows_1; + sum_s1, + slice_chunks_1, + slice_windows_1; + for_chunks_1, + for_windows_1 +} + +def_benchs!{ + 2; + benches_2, + sum_t2, + tuple_chunks_2, + tuple_windows_2; + sum_s2, + slice_chunks_2, + slice_windows_2; + for_chunks_2, + for_windows_2 +} + +def_benchs!{ + 3; + benches_3, + sum_t3, + tuple_chunks_3, + tuple_windows_3; + sum_s3, + slice_chunks_3, + slice_windows_3; + for_chunks_3, + for_windows_3 +} + +def_benchs!{ + 4; + benches_4, + sum_t4, + tuple_chunks_4, + tuple_windows_4; + sum_s4, + slice_chunks_4, + slice_windows_4; + for_chunks_4, + for_windows_4 +} + +criterion_main!( + benches_1, + benches_2, + benches_3, + benches_4, +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/clippy.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/clippy.toml 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1 @@ +msrv = "1.36.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.data clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.data --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.data 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.data 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,150 @@ +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3.0,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5.0,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5.0,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3.0,1.4,0.1,Iris-setosa +4.3,3.0,1.1,0.1,Iris-setosa +5.8,4.0,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1.0,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5.0,3.0,1.6,0.2,Iris-setosa +5.0,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.0,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3.0,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5.0,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5.0,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3.0,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5.0,3.3,1.4,0.2,Iris-setosa +7.0,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4.0,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1.0,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5.0,2.0,3.5,1.0,Iris-versicolor +5.9,3.0,4.2,1.5,Iris-versicolor +6.0,2.2,4.0,1.0,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3.0,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1.0,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4.0,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3.0,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3.0,5.0,1.7,Iris-versicolor +6.0,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1.0,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1.0,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6.0,2.7,5.1,1.6,Iris-versicolor +5.4,3.0,4.5,1.5,Iris-versicolor +6.0,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3.0,4.1,1.3,Iris-versicolor +5.5,2.5,4.0,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3.0,4.6,1.4,Iris-versicolor +5.8,2.6,4.0,1.2,Iris-versicolor +5.0,2.3,3.3,1.0,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3.0,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3.0,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6.0,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3.0,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3.0,5.8,2.2,Iris-virginica +7.6,3.0,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2.0,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3.0,5.5,2.1,Iris-virginica +5.7,2.5,5.0,2.0,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3.0,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6.0,2.2,5.0,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2.0,Iris-virginica +7.7,2.8,6.7,2.0,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6.0,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3.0,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3.0,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2.0,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3.0,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6.0,3.0,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3.0,5.2,2.3,Iris-virginica +6.3,2.5,5.0,1.9,Iris-virginica +6.5,3.0,5.2,2.0,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3.0,5.1,1.8,Iris-virginica diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/examples/iris.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,137 @@ +/// +/// This example parses, sorts and groups the iris dataset +/// and does some simple manipulations. +/// +/// Iterators and itertools functionality are used throughout. + +use itertools::Itertools; +use std::collections::HashMap; +use std::iter::repeat; +use std::num::ParseFloatError; +use std::str::FromStr; + +static DATA: &'static str = include_str!("iris.data"); + +#[derive(Clone, Debug)] +struct Iris { + name: String, + data: [f32; 4], +} + +#[derive(Clone, Debug)] +enum ParseError { + Numeric(ParseFloatError), + Other(&'static str), +} + +impl From for ParseError { + fn from(err: ParseFloatError) -> Self { + ParseError::Numeric(err) + } +} + +/// Parse an Iris from a comma-separated line +impl FromStr for Iris { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + let mut iris = Iris { name: "".into(), data: [0.; 4] }; + let mut parts = s.split(",").map(str::trim); + + // using Iterator::by_ref() + for (index, part) in parts.by_ref().take(4).enumerate() { + iris.data[index] = part.parse::()?; + } + if let Some(name) = parts.next() { + iris.name = name.into(); + } else { + return Err(ParseError::Other("Missing name")) + } + Ok(iris) + } +} + +fn main() { + // using Itertools::fold_results to create the result of parsing + let irises = DATA.lines() + .map(str::parse) + .fold_ok(Vec::new(), |mut v, iris: Iris| { + v.push(iris); + v + }); + let mut irises = match irises { + Err(e) => { + println!("Error parsing: {:?}", e); + std::process::exit(1); + } + Ok(data) => data, + }; + + // Sort them and group them + irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name)); + + // using Iterator::cycle() + let mut plot_symbols = "+ox".chars().cycle(); + let mut symbolmap = HashMap::new(); + + // using Itertools::group_by + for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) { + // assign a plot symbol + symbolmap.entry(species).or_insert_with(|| { + plot_symbols.next().unwrap() + }); + println!("{} (symbol={})", species, symbolmap[species]); + + for iris in species_group { + // using Itertools::format for lazy formatting + println!("{:>3.1}", iris.data.iter().format(", ")); + } + + } + + // Look at all combinations of the four columns + // + // See https://en.wikipedia.org/wiki/Iris_flower_data_set + // + let n = 30; // plot size + let mut plot = vec![' '; n * n]; + + // using Itertools::tuple_combinations + for (a, b) in (0..4).tuple_combinations() { + println!("Column {} vs {}:", a, b); + + // Clear plot + // + // using std::iter::repeat; + // using Itertools::set_from + plot.iter_mut().set_from(repeat(' ')); + + // using Itertools::minmax + let min_max = |data: &[Iris], col| { + data.iter() + .map(|iris| iris.data[col]) + .minmax() + .into_option() + .expect("Can't find min/max of empty iterator") + }; + let (min_x, max_x) = min_max(&irises, a); + let (min_y, max_y) = min_max(&irises, b); + + // Plot the data points + let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize; + let flip = |ix| n - 1 - ix; // reverse axis direction + + for iris in &irises { + let ix = round_to_grid(iris.data[a], min_x, max_x); + let iy = flip(round_to_grid(iris.data[b], min_y, max_y)); + plot[n * iy + ix] = symbolmap[&iris.name]; + } + + // render plot + // + // using Itertools::join + for line in plot.chunks(n) { + println!("{}", line.iter().join(" ")) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/coalesce.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/coalesce.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/coalesce.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/coalesce.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,235 @@ +use std::fmt; +use std::iter::FusedIterator; + +use crate::size_hint; + +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct CoalesceBy +where + I: Iterator, +{ + iter: I, + last: Option, + f: F, +} + +impl Clone for CoalesceBy +where + I: Iterator, +{ + clone_fields!(last, iter, f); +} + +impl fmt::Debug for CoalesceBy +where + I: Iterator + fmt::Debug, + T: fmt::Debug, +{ + debug_fmt_fields!(CoalesceBy, iter); +} + +pub trait CoalescePredicate { + fn coalesce_pair(&mut self, t: T, item: Item) -> Result; +} + +impl Iterator for CoalesceBy +where + I: Iterator, + F: CoalescePredicate, +{ + type Item = T; + + fn next(&mut self) -> Option { + // this fuses the iterator + let last = self.last.take()?; + + let self_last = &mut self.last; + let self_f = &mut self.f; + Some( + self.iter + .try_fold(last, |last, next| match self_f.coalesce_pair(last, next) { + Ok(joined) => Ok(joined), + Err((last_, next_)) => { + *self_last = Some(next_); + Err(last_) + } + }) + .unwrap_or_else(|x| x), + ) + } + + fn size_hint(&self) -> (usize, Option) { + let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), self.last.is_some() as usize); + ((low > 0) as usize, hi) + } + + fn fold(self, acc: Acc, mut fn_acc: FnAcc) -> Acc + where + FnAcc: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(last) = self.last { + let mut f = self.f; + let (last, acc) = self.iter.fold((last, acc), |(last, acc), elt| { + match f.coalesce_pair(last, elt) { + Ok(joined) => (joined, acc), + Err((last_, next_)) => (next_, fn_acc(acc, last_)), + } + }); + fn_acc(acc, last) + } else { + acc + } + } +} + +impl, T> FusedIterator for CoalesceBy {} + +/// An iterator adaptor that may join together adjacent elements. +/// +/// See [`.coalesce()`](crate::Itertools::coalesce) for more information. +pub type Coalesce = CoalesceBy::Item>; + +impl CoalescePredicate for F +where + F: FnMut(T, Item) -> Result, +{ + fn coalesce_pair(&mut self, t: T, item: Item) -> Result { + self(t, item) + } +} + +/// Create a new `Coalesce`. +pub fn coalesce(mut iter: I, f: F) -> Coalesce +where + I: Iterator, +{ + Coalesce { + last: iter.next(), + iter, + f, + } +} + +/// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function. +/// +/// See [`.dedup_by()`](crate::Itertools::dedup_by) or [`.dedup()`](crate::Itertools::dedup) for more information. +pub type DedupBy = CoalesceBy, ::Item>; + +#[derive(Clone)] +pub struct DedupPred2CoalescePred(DP); + +impl fmt::Debug for DedupPred2CoalescePred { + debug_fmt_fields!(DedupPred2CoalescePred,); +} + +pub trait DedupPredicate { + // TODO replace by Fn(&T, &T)->bool once Rust supports it + fn dedup_pair(&mut self, a: &T, b: &T) -> bool; +} + +impl CoalescePredicate for DedupPred2CoalescePred +where + DP: DedupPredicate, +{ + fn coalesce_pair(&mut self, t: T, item: T) -> Result { + if self.0.dedup_pair(&t, &item) { + Ok(t) + } else { + Err((t, item)) + } + } +} + +#[derive(Clone, Debug)] +pub struct DedupEq; + +impl DedupPredicate for DedupEq { + fn dedup_pair(&mut self, a: &T, b: &T) -> bool { + a == b + } +} + +impl bool> DedupPredicate for F { + fn dedup_pair(&mut self, a: &T, b: &T) -> bool { + self(a, b) + } +} + +/// Create a new `DedupBy`. +pub fn dedup_by(mut iter: I, dedup_pred: Pred) -> DedupBy +where + I: Iterator, +{ + DedupBy { + last: iter.next(), + iter, + f: DedupPred2CoalescePred(dedup_pred), + } +} + +/// An iterator adaptor that removes repeated duplicates. +/// +/// See [`.dedup()`](crate::Itertools::dedup) for more information. +pub type Dedup = DedupBy; + +/// Create a new `Dedup`. +pub fn dedup(iter: I) -> Dedup +where + I: Iterator, +{ + dedup_by(iter, DedupEq) +} + +/// An iterator adaptor that removes repeated duplicates, while keeping a count of how many +/// repeated elements were present. This will determine equality using a comparison function. +/// +/// See [`.dedup_by_with_count()`](crate::Itertools::dedup_by_with_count) or +/// [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information. +pub type DedupByWithCount = + CoalesceBy, (usize, ::Item)>; + +#[derive(Clone, Debug)] +pub struct DedupPredWithCount2CoalescePred(DP); + +impl CoalescePredicate for DedupPredWithCount2CoalescePred +where + DP: DedupPredicate, +{ + fn coalesce_pair( + &mut self, + (c, t): (usize, T), + item: T, + ) -> Result<(usize, T), ((usize, T), (usize, T))> { + if self.0.dedup_pair(&t, &item) { + Ok((c + 1, t)) + } else { + Err(((c, t), (1, item))) + } + } +} + +/// An iterator adaptor that removes repeated duplicates, while keeping a count of how many +/// repeated elements were present. +/// +/// See [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information. +pub type DedupWithCount = DedupByWithCount; + +/// Create a new `DedupByWithCount`. +pub fn dedup_by_with_count(mut iter: I, dedup_pred: Pred) -> DedupByWithCount +where + I: Iterator, +{ + DedupByWithCount { + last: iter.next().map(|v| (1, v)), + iter, + f: DedupPredWithCount2CoalescePred(dedup_pred), + } +} + +/// Create a new `DedupWithCount`. +pub fn dedup_with_count(iter: I) -> DedupWithCount +where + I: Iterator, +{ + dedup_by_with_count(iter, DedupEq) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/map.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/map.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,124 @@ +use std::iter::FromIterator; +use std::marker::PhantomData; + +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MapSpecialCase { + iter: I, + f: F, +} + +pub trait MapSpecialCaseFn { + type Out; + fn call(&mut self, t: T) -> Self::Out; +} + +impl Iterator for MapSpecialCase +where + I: Iterator, + R: MapSpecialCaseFn, +{ + type Item = R::Out; + + fn next(&mut self) -> Option { + self.iter.next().map(|i| self.f.call(i)) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn fold(self, init: Acc, mut fold_f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, v| fold_f(acc, f.call(v))) + } + + fn collect(self) -> C + where + C: FromIterator, + { + let mut f = self.f; + self.iter.map(move |v| f.call(v)).collect() + } +} + +impl DoubleEndedIterator for MapSpecialCase +where + I: DoubleEndedIterator, + R: MapSpecialCaseFn, +{ + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|i| self.f.call(i)) + } +} + +impl ExactSizeIterator for MapSpecialCase +where + I: ExactSizeIterator, + R: MapSpecialCaseFn, +{ +} + +/// An iterator adapter to apply a transformation within a nested `Result::Ok`. +/// +/// See [`.map_ok()`](crate::Itertools::map_ok) for more information. +pub type MapOk = MapSpecialCase>; + +/// See [`MapOk`]. +#[deprecated(note = "Use MapOk instead", since = "0.10.0")] +pub type MapResults = MapOk; + +impl MapSpecialCaseFn> for MapSpecialCaseFnOk +where + F: FnMut(T) -> U, +{ + type Out = Result; + fn call(&mut self, t: Result) -> Self::Out { + t.map(|v| self.0(v)) + } +} + +#[derive(Clone)] +pub struct MapSpecialCaseFnOk(F); + +impl std::fmt::Debug for MapSpecialCaseFnOk { + debug_fmt_fields!(MapSpecialCaseFnOk,); +} + +/// Create a new `MapOk` iterator. +pub fn map_ok(iter: I, f: F) -> MapOk +where + I: Iterator>, + F: FnMut(T) -> U, +{ + MapSpecialCase { + iter, + f: MapSpecialCaseFnOk(f), + } +} + +/// An iterator adapter to apply `Into` conversion to each element. +/// +/// See [`.map_into()`](crate::Itertools::map_into) for more information. +pub type MapInto = MapSpecialCase>; + +impl, U> MapSpecialCaseFn for MapSpecialCaseFnInto { + type Out = U; + fn call(&mut self, t: T) -> Self::Out { + t.into() + } +} + +#[derive(Clone, Debug)] +pub struct MapSpecialCaseFnInto(PhantomData); + +/// Create a new [`MapInto`] iterator. +pub fn map_into(iter: I) -> MapInto { + MapSpecialCase { + iter, + f: MapSpecialCaseFnInto(PhantomData), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/mod.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,1151 @@ +//! Licensed under the Apache License, Version 2.0 +//! or the MIT license +//! , at your +//! option. This file may not be copied, modified, or distributed +//! except according to those terms. + +mod coalesce; +mod map; +mod multi_product; +pub use self::coalesce::*; +pub use self::map::{map_into, map_ok, MapInto, MapOk}; +#[allow(deprecated)] +pub use self::map::MapResults; +#[cfg(feature = "use_alloc")] +pub use self::multi_product::*; + +use std::fmt; +use std::iter::{Fuse, Peekable, FromIterator, FusedIterator}; +use std::marker::PhantomData; +use crate::size_hint; + +/// An iterator adaptor that alternates elements from two iterators until both +/// run out. +/// +/// This iterator is *fused*. +/// +/// See [`.interleave()`](crate::Itertools::interleave) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Interleave { + a: Fuse, + b: Fuse, + flag: bool, +} + +/// Create an iterator that interleaves elements in `i` and `j`. +/// +/// [`IntoIterator`] enabled version of `[Itertools::interleave]`. +pub fn interleave(i: I, j: J) -> Interleave<::IntoIter, ::IntoIter> + where I: IntoIterator, + J: IntoIterator +{ + Interleave { + a: i.into_iter().fuse(), + b: j.into_iter().fuse(), + flag: false, + } +} + +impl Iterator for Interleave + where I: Iterator, + J: Iterator +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + self.flag = !self.flag; + if self.flag { + match self.a.next() { + None => self.b.next(), + r => r, + } + } else { + match self.b.next() { + None => self.a.next(), + r => r, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + size_hint::add(self.a.size_hint(), self.b.size_hint()) + } +} + +impl FusedIterator for Interleave + where I: Iterator, + J: Iterator +{} + +/// An iterator adaptor that alternates elements from the two iterators until +/// one of them runs out. +/// +/// This iterator is *fused*. +/// +/// See [`.interleave_shortest()`](crate::Itertools::interleave_shortest) +/// for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct InterleaveShortest + where I: Iterator, + J: Iterator +{ + it0: I, + it1: J, + phase: bool, // false ==> it0, true ==> it1 +} + +/// Create a new `InterleaveShortest` iterator. +pub fn interleave_shortest(a: I, b: J) -> InterleaveShortest + where I: Iterator, + J: Iterator +{ + InterleaveShortest { + it0: a, + it1: b, + phase: false, + } +} + +impl Iterator for InterleaveShortest + where I: Iterator, + J: Iterator +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + let e = if self.phase { self.it1.next() } else { self.it0.next() }; + if e.is_some() { + self.phase = !self.phase; + } + e + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (curr_hint, next_hint) = { + let it0_hint = self.it0.size_hint(); + let it1_hint = self.it1.size_hint(); + if self.phase { + (it1_hint, it0_hint) + } else { + (it0_hint, it1_hint) + } + }; + let (curr_lower, curr_upper) = curr_hint; + let (next_lower, next_upper) = next_hint; + let (combined_lower, combined_upper) = + size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); + let lower = + if curr_lower > next_lower { + combined_lower + 1 + } else { + combined_lower + }; + let upper = { + let extra_elem = match (curr_upper, next_upper) { + (_, None) => false, + (None, Some(_)) => true, + (Some(curr_max), Some(next_max)) => curr_max > next_max, + }; + if extra_elem { + combined_upper.and_then(|x| x.checked_add(1)) + } else { + combined_upper + } + }; + (lower, upper) + } +} + +impl FusedIterator for InterleaveShortest + where I: FusedIterator, + J: FusedIterator +{} + +#[derive(Clone, Debug)] +/// An iterator adaptor that allows putting back a single +/// item to the front of the iterator. +/// +/// Iterator element type is `I::Item`. +pub struct PutBack + where I: Iterator +{ + top: Option, + iter: I, +} + +/// Create an iterator where you can put back a single item +pub fn put_back(iterable: I) -> PutBack + where I: IntoIterator +{ + PutBack { + top: None, + iter: iterable.into_iter(), + } +} + +impl PutBack + where I: Iterator +{ + /// put back value `value` (builder method) + pub fn with_value(mut self, value: I::Item) -> Self { + self.put_back(value); + self + } + + /// Split the `PutBack` into its parts. + #[inline] + pub fn into_parts(self) -> (Option, I) { + let PutBack{top, iter} = self; + (top, iter) + } + + /// Put back a single value to the front of the iterator. + /// + /// If a value is already in the put back slot, it is overwritten. + #[inline] + pub fn put_back(&mut self, x: I::Item) { + self.top = Some(x); + } +} + +impl Iterator for PutBack + where I: Iterator +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + match self.top { + None => self.iter.next(), + ref mut some => some.take(), + } + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize) + } + + fn count(self) -> usize { + self.iter.count() + (self.top.is_some() as usize) + } + + fn last(self) -> Option { + self.iter.last().or(self.top) + } + + fn nth(&mut self, n: usize) -> Option { + match self.top { + None => self.iter.nth(n), + ref mut some => { + if n == 0 { + some.take() + } else { + *some = None; + self.iter.nth(n - 1) + } + } + } + } + + fn all(&mut self, mut f: G) -> bool + where G: FnMut(Self::Item) -> bool + { + if let Some(elt) = self.top.take() { + if !f(elt) { + return false; + } + } + self.iter.all(f) + } + + fn fold(mut self, init: Acc, mut f: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + if let Some(elt) = self.top.take() { + accum = f(accum, elt); + } + self.iter.fold(accum, f) + } +} + +#[derive(Debug, Clone)] +/// An iterator adaptor that iterates over the cartesian product of +/// the element sets of two iterators `I` and `J`. +/// +/// Iterator element type is `(I::Item, J::Item)`. +/// +/// See [`.cartesian_product()`](crate::Itertools::cartesian_product) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Product + where I: Iterator +{ + a: I, + a_cur: Option, + b: J, + b_orig: J, +} + +/// Create a new cartesian product iterator +/// +/// Iterator element type is `(I::Item, J::Item)`. +pub fn cartesian_product(mut i: I, j: J) -> Product + where I: Iterator, + J: Clone + Iterator, + I::Item: Clone +{ + Product { + a_cur: i.next(), + a: i, + b: j.clone(), + b_orig: j, + } +} + +impl Iterator for Product + where I: Iterator, + J: Clone + Iterator, + I::Item: Clone +{ + type Item = (I::Item, J::Item); + + fn next(&mut self) -> Option { + let elt_b = match self.b.next() { + None => { + self.b = self.b_orig.clone(); + match self.b.next() { + None => return None, + Some(x) => { + self.a_cur = self.a.next(); + x + } + } + } + Some(x) => x + }; + self.a_cur.as_ref().map(|a| (a.clone(), elt_b)) + } + + fn size_hint(&self) -> (usize, Option) { + let has_cur = self.a_cur.is_some() as usize; + // Not ExactSizeIterator because size may be larger than usize + let (b_min, b_max) = self.b.size_hint(); + + // Compute a * b_orig + b for both lower and upper bound + size_hint::add( + size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()), + (b_min * has_cur, b_max.map(move |x| x * has_cur))) + } + + fn fold(mut self, mut accum: Acc, mut f: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + // use a split loop to handle the loose a_cur as well as avoiding to + // clone b_orig at the end. + if let Some(mut a) = self.a_cur.take() { + let mut b = self.b; + loop { + accum = b.fold(accum, |acc, elt| f(acc, (a.clone(), elt))); + + // we can only continue iterating a if we had a first element; + if let Some(next_a) = self.a.next() { + b = self.b_orig.clone(); + a = next_a; + } else { + break; + } + } + } + accum + } +} + +impl FusedIterator for Product + where I: FusedIterator, + J: Clone + FusedIterator, + I::Item: Clone +{} + +/// A “meta iterator adaptor”. Its closure receives a reference to the iterator +/// and may pick off as many elements as it likes, to produce the next iterator element. +/// +/// Iterator element type is *X*, if the return type of `F` is *Option\*. +/// +/// See [`.batching()`](crate::Itertools::batching) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Batching { + f: F, + iter: I, +} + +impl fmt::Debug for Batching where I: fmt::Debug { + debug_fmt_fields!(Batching, iter); +} + +/// Create a new Batching iterator. +pub fn batching(iter: I, f: F) -> Batching { + Batching { f, iter } +} + +impl Iterator for Batching + where I: Iterator, + F: FnMut(&mut I) -> Option +{ + type Item = B; + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.iter) + } +} + +/// An iterator adaptor that steps a number elements in the base iterator +/// for each iteration. +/// +/// The iterator steps by yielding the next element from the base iterator, +/// then skipping forward *n-1* elements. +/// +/// See [`.step()`](crate::Itertools::step) for more information. +#[deprecated(note="Use std .step_by() instead", since="0.8.0")] +#[allow(deprecated)] +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Step { + iter: Fuse, + skip: usize, +} + +/// Create a `Step` iterator. +/// +/// **Panics** if the step is 0. +#[allow(deprecated)] +pub fn step(iter: I, step: usize) -> Step + where I: Iterator +{ + assert!(step != 0); + Step { + iter: iter.fuse(), + skip: step - 1, + } +} + +#[allow(deprecated)] +impl Iterator for Step + where I: Iterator +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + let elt = self.iter.next(); + if self.skip > 0 { + self.iter.nth(self.skip - 1); + } + elt + } + + fn size_hint(&self) -> (usize, Option) { + let (low, high) = self.iter.size_hint(); + let div = |x: usize| { + if x == 0 { + 0 + } else { + 1 + (x - 1) / (self.skip + 1) + } + }; + (div(low), high.map(div)) + } +} + +// known size +#[allow(deprecated)] +impl ExactSizeIterator for Step + where I: ExactSizeIterator +{} + +pub trait MergePredicate { + fn merge_pred(&mut self, a: &T, b: &T) -> bool; +} + +#[derive(Clone, Debug)] +pub struct MergeLte; + +impl MergePredicate for MergeLte { + fn merge_pred(&mut self, a: &T, b: &T) -> bool { + a <= b + } +} + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge()`](crate::Itertools::merge_by) for more information. +pub type Merge = MergeBy; + +/// Create an iterator that merges elements in `i` and `j`. +/// +/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge). +/// +/// ``` +/// use itertools::merge; +/// +/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { +/// /* loop body */ +/// } +/// ``` +pub fn merge(i: I, j: J) -> Merge<::IntoIter, ::IntoIter> + where I: IntoIterator, + J: IntoIterator, + I::Item: PartialOrd +{ + merge_by_new(i, j, MergeLte) +} + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge_by()`](crate::Itertools::merge_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MergeBy + where I: Iterator, + J: Iterator +{ + a: Peekable, + b: Peekable, + fused: Option, + cmp: F, +} + +impl fmt::Debug for MergeBy + where I: Iterator + fmt::Debug, J: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(MergeBy, a, b); +} + +implbool> MergePredicate for F { + fn merge_pred(&mut self, a: &T, b: &T) -> bool { + self(a, b) + } +} + +/// Create a `MergeBy` iterator. +pub fn merge_by_new(a: I, b: J, cmp: F) -> MergeBy + where I: IntoIterator, + J: IntoIterator, + F: MergePredicate, +{ + MergeBy { + a: a.into_iter().peekable(), + b: b.into_iter().peekable(), + fused: None, + cmp, + } +} + +impl Clone for MergeBy + where I: Iterator, + J: Iterator, + Peekable: Clone, + Peekable: Clone, + F: Clone +{ + clone_fields!(a, b, fused, cmp); +} + +impl Iterator for MergeBy + where I: Iterator, + J: Iterator, + F: MergePredicate +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + let less_than = match self.fused { + Some(lt) => lt, + None => match (self.a.peek(), self.b.peek()) { + (Some(a), Some(b)) => self.cmp.merge_pred(a, b), + (Some(_), None) => { + self.fused = Some(true); + true + } + (None, Some(_)) => { + self.fused = Some(false); + false + } + (None, None) => return None, + } + }; + if less_than { + self.a.next() + } else { + self.b.next() + } + } + + fn size_hint(&self) -> (usize, Option) { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(self.a.size_hint(), self.b.size_hint()) + } +} + +impl FusedIterator for MergeBy + where I: FusedIterator, + J: FusedIterator, + F: MergePredicate +{} + +/// An iterator adaptor that borrows from a `Clone`-able iterator +/// to only pick off elements while the predicate returns `true`. +/// +/// See [`.take_while_ref()`](crate::Itertools::take_while_ref) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct TakeWhileRef<'a, I: 'a, F> { + iter: &'a mut I, + f: F, +} + +impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F> + where I: Iterator + fmt::Debug, +{ + debug_fmt_fields!(TakeWhileRef, iter); +} + +/// Create a new `TakeWhileRef` from a reference to clonable iterator. +pub fn take_while_ref(iter: &mut I, f: F) -> TakeWhileRef + where I: Iterator + Clone +{ + TakeWhileRef { iter, f } +} + +impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F> + where I: Iterator + Clone, + F: FnMut(&I::Item) -> bool +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + let old = self.iter.clone(); + match self.iter.next() { + None => None, + Some(elt) => { + if (self.f)(&elt) { + Some(elt) + } else { + *self.iter = old; + None + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +/// An iterator adaptor that filters `Option` iterator elements +/// and produces `A`. Stops on the first `None` encountered. +/// +/// See [`.while_some()`](crate::Itertools::while_some) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct WhileSome { + iter: I, +} + +/// Create a new `WhileSome`. +pub fn while_some(iter: I) -> WhileSome { + WhileSome { iter } +} + +impl Iterator for WhileSome + where I: Iterator> +{ + type Item = A; + + fn next(&mut self) -> Option { + match self.iter.next() { + None | Some(None) => None, + Some(elt) => elt, + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +/// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples +/// of a specific size. +/// +/// See [`.tuple_combinations()`](crate::Itertools::tuple_combinations) for more +/// information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct TupleCombinations + where I: Iterator, + T: HasCombination +{ + iter: T::Combination, + _mi: PhantomData, +} + +pub trait HasCombination: Sized { + type Combination: From + Iterator; +} + +/// Create a new `TupleCombinations` from a clonable iterator. +pub fn tuple_combinations(iter: I) -> TupleCombinations + where I: Iterator + Clone, + I::Item: Clone, + T: HasCombination, +{ + TupleCombinations { + iter: T::Combination::from(iter), + _mi: PhantomData, + } +} + +impl Iterator for TupleCombinations + where I: Iterator, + T: HasCombination, +{ + type Item = T; + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +impl FusedIterator for TupleCombinations + where I: FusedIterator, + T: HasCombination, +{} + +#[derive(Clone, Debug)] +pub struct Tuple1Combination { + iter: I, +} + +impl From for Tuple1Combination { + fn from(iter: I) -> Self { + Tuple1Combination { iter } + } +} + +impl Iterator for Tuple1Combination { + type Item = (I::Item,); + + fn next(&mut self) -> Option { + self.iter.next().map(|x| (x,)) + } +} + +impl HasCombination for (I::Item,) { + type Combination = Tuple1Combination; +} + +macro_rules! impl_tuple_combination { + ($C:ident $P:ident ; $($X:ident)*) => ( + #[derive(Clone, Debug)] + pub struct $C { + item: Option, + iter: I, + c: $P, + } + + impl From for $C { + fn from(mut iter: I) -> Self { + Self { + item: iter.next(), + iter: iter.clone(), + c: iter.into(), + } + } + } + + impl From for $C> { + fn from(iter: I) -> Self { + Self::from(iter.fuse()) + } + } + + impl Iterator for $C + where I: Iterator + Clone, + I::Item: Clone + { + type Item = (A, $(ignore_ident!($X, A)),*); + + fn next(&mut self) -> Option { + if let Some(($($X),*,)) = self.c.next() { + let z = self.item.clone().unwrap(); + Some((z, $($X),*)) + } else { + self.item = self.iter.next(); + self.item.clone().and_then(|z| { + self.c = self.iter.clone().into(); + self.c.next().map(|($($X),*,)| (z, $($X),*)) + }) + } + } + } + + impl HasCombination for (A, $(ignore_ident!($X, A)),*) + where I: Iterator + Clone, + I::Item: Clone + { + type Combination = $C>; + } + ) +} + +// This snippet generates the twelve `impl_tuple_combination!` invocations: +// use core::iter; +// use itertools::Itertools; +// +// for i in 2..=12 { +// println!("impl_tuple_combination!(Tuple{arity}Combination Tuple{prev}Combination; {idents});", +// arity = i, +// prev = i - 1, +// idents = ('a'..'z').take(i - 1).join(" "), +// ); +// } +// It could probably be replaced by a bit more macro cleverness. +impl_tuple_combination!(Tuple2Combination Tuple1Combination; a); +impl_tuple_combination!(Tuple3Combination Tuple2Combination; a b); +impl_tuple_combination!(Tuple4Combination Tuple3Combination; a b c); +impl_tuple_combination!(Tuple5Combination Tuple4Combination; a b c d); +impl_tuple_combination!(Tuple6Combination Tuple5Combination; a b c d e); +impl_tuple_combination!(Tuple7Combination Tuple6Combination; a b c d e f); +impl_tuple_combination!(Tuple8Combination Tuple7Combination; a b c d e f g); +impl_tuple_combination!(Tuple9Combination Tuple8Combination; a b c d e f g h); +impl_tuple_combination!(Tuple10Combination Tuple9Combination; a b c d e f g h i); +impl_tuple_combination!(Tuple11Combination Tuple10Combination; a b c d e f g h i j); +impl_tuple_combination!(Tuple12Combination Tuple11Combination; a b c d e f g h i j k); + +/// An iterator adapter to filter values within a nested `Result::Ok`. +/// +/// See [`.filter_ok()`](crate::Itertools::filter_ok) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct FilterOk { + iter: I, + f: F +} + +impl fmt::Debug for FilterOk +where + I: fmt::Debug, +{ + debug_fmt_fields!(FilterOk, iter); +} + +/// Create a new `FilterOk` iterator. +pub fn filter_ok(iter: I, f: F) -> FilterOk + where I: Iterator>, + F: FnMut(&T) -> bool, +{ + FilterOk { + iter, + f, + } +} + +impl Iterator for FilterOk + where I: Iterator>, + F: FnMut(&T) -> bool, +{ + type Item = Result; + + fn next(&mut self) -> Option { + loop { + match self.iter.next() { + Some(Ok(v)) => { + if (self.f)(&v) { + return Some(Ok(v)); + } + }, + Some(Err(e)) => return Some(Err(e)), + None => return None, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } + + fn fold(self, init: Acc, fold_f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.filter(|v| { + v.as_ref().map(&mut f).unwrap_or(true) + }).fold(init, fold_f) + } + + fn collect(self) -> C + where C: FromIterator + { + let mut f = self.f; + self.iter.filter(|v| { + v.as_ref().map(&mut f).unwrap_or(true) + }).collect() + } +} + +impl FusedIterator for FilterOk + where I: FusedIterator>, + F: FnMut(&T) -> bool, +{} + +/// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`. +/// +/// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct FilterMapOk { + iter: I, + f: F +} + +impl fmt::Debug for FilterMapOk +where + I: fmt::Debug, +{ + debug_fmt_fields!(FilterMapOk, iter); +} + +fn transpose_result(result: Result, E>) -> Option> { + match result { + Ok(Some(v)) => Some(Ok(v)), + Ok(None) => None, + Err(e) => Some(Err(e)), + } +} + +/// Create a new `FilterOk` iterator. +pub fn filter_map_ok(iter: I, f: F) -> FilterMapOk + where I: Iterator>, + F: FnMut(T) -> Option, +{ + FilterMapOk { + iter, + f, + } +} + +impl Iterator for FilterMapOk + where I: Iterator>, + F: FnMut(T) -> Option, +{ + type Item = Result; + + fn next(&mut self) -> Option { + loop { + match self.iter.next() { + Some(Ok(v)) => { + if let Some(v) = (self.f)(v) { + return Some(Ok(v)); + } + }, + Some(Err(e)) => return Some(Err(e)), + None => return None, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } + + fn fold(self, init: Acc, fold_f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.filter_map(|v| { + transpose_result(v.map(&mut f)) + }).fold(init, fold_f) + } + + fn collect(self) -> C + where C: FromIterator + { + let mut f = self.f; + self.iter.filter_map(|v| { + transpose_result(v.map(&mut f)) + }).collect() + } +} + +impl FusedIterator for FilterMapOk + where I: FusedIterator>, + F: FnMut(T) -> Option, +{} + +/// An iterator adapter to get the positions of each element that matches a predicate. +/// +/// See [`.positions()`](crate::Itertools::positions) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Positions { + iter: I, + f: F, + count: usize, +} + +impl fmt::Debug for Positions +where + I: fmt::Debug, +{ + debug_fmt_fields!(Positions, iter, count); +} + +/// Create a new `Positions` iterator. +pub fn positions(iter: I, f: F) -> Positions + where I: Iterator, + F: FnMut(I::Item) -> bool, +{ + Positions { + iter, + f, + count: 0 + } +} + +impl Iterator for Positions + where I: Iterator, + F: FnMut(I::Item) -> bool, +{ + type Item = usize; + + fn next(&mut self) -> Option { + while let Some(v) = self.iter.next() { + let i = self.count; + self.count = i + 1; + if (self.f)(v) { + return Some(i); + } + } + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +impl DoubleEndedIterator for Positions + where I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(I::Item) -> bool, +{ + fn next_back(&mut self) -> Option { + while let Some(v) = self.iter.next_back() { + if (self.f)(v) { + return Some(self.count + self.iter.len()) + } + } + None + } +} + +impl FusedIterator for Positions + where I: FusedIterator, + F: FnMut(I::Item) -> bool, +{} + +/// An iterator adapter to apply a mutating function to each element before yielding it. +/// +/// See [`.update()`](crate::Itertools::update) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Update { + iter: I, + f: F, +} + +impl fmt::Debug for Update +where + I: fmt::Debug, +{ + debug_fmt_fields!(Update, iter); +} + +/// Create a new `Update` iterator. +pub fn update(iter: I, f: F) -> Update +where + I: Iterator, + F: FnMut(&mut I::Item), +{ + Update { iter, f } +} + +impl Iterator for Update +where + I: Iterator, + F: FnMut(&mut I::Item), +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + if let Some(mut v) = self.iter.next() { + (self.f)(&mut v); + Some(v) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn fold(self, init: Acc, mut g: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, mut v| { f(&mut v); g(acc, v) }) + } + + // if possible, re-use inner iterator specializations in collect + fn collect(self) -> C + where C: FromIterator + { + let mut f = self.f; + self.iter.map(move |mut v| { f(&mut v); v }).collect() + } +} + +impl ExactSizeIterator for Update +where + I: ExactSizeIterator, + F: FnMut(&mut I::Item), +{} + +impl DoubleEndedIterator for Update +where + I: DoubleEndedIterator, + F: FnMut(&mut I::Item), +{ + fn next_back(&mut self) -> Option { + if let Some(mut v) = self.iter.next_back() { + (self.f)(&mut v); + Some(v) + } else { + None + } + } +} + +impl FusedIterator for Update +where + I: FusedIterator, + F: FnMut(&mut I::Item), +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/multi_product.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/multi_product.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/multi_product.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/adaptors/multi_product.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,230 @@ +#![cfg(feature = "use_alloc")] + +use crate::size_hint; +use crate::Itertools; + +use alloc::vec::Vec; + +#[derive(Clone)] +/// An iterator adaptor that iterates over the cartesian product of +/// multiple iterators of type `I`. +/// +/// An iterator element type is `Vec`. +/// +/// See [`.multi_cartesian_product()`](crate::Itertools::multi_cartesian_product) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MultiProduct(Vec>) + where I: Iterator + Clone, + I::Item: Clone; + +impl std::fmt::Debug for MultiProduct +where + I: Iterator + Clone + std::fmt::Debug, + I::Item: Clone + std::fmt::Debug, +{ + debug_fmt_fields!(CoalesceBy, 0); +} + +/// Create a new cartesian product iterator over an arbitrary number +/// of iterators of the same type. +/// +/// Iterator element is of type `Vec`. +pub fn multi_cartesian_product(iters: H) -> MultiProduct<::IntoIter> + where H: Iterator, + H::Item: IntoIterator, + ::IntoIter: Clone, + ::Item: Clone +{ + MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect()) +} + +#[derive(Clone, Debug)] +/// Holds the state of a single iterator within a `MultiProduct`. +struct MultiProductIter + where I: Iterator + Clone, + I::Item: Clone +{ + cur: Option, + iter: I, + iter_orig: I, +} + +/// Holds the current state during an iteration of a `MultiProduct`. +#[derive(Debug)] +enum MultiProductIterState { + StartOfIter, + MidIter { on_first_iter: bool }, +} + +impl MultiProduct + where I: Iterator + Clone, + I::Item: Clone +{ + /// Iterates the rightmost iterator, then recursively iterates iterators + /// to the left if necessary. + /// + /// Returns true if the iteration succeeded, else false. + fn iterate_last( + multi_iters: &mut [MultiProductIter], + mut state: MultiProductIterState + ) -> bool { + use self::MultiProductIterState::*; + + if let Some((last, rest)) = multi_iters.split_last_mut() { + let on_first_iter = match state { + StartOfIter => { + let on_first_iter = !last.in_progress(); + state = MidIter { on_first_iter }; + on_first_iter + }, + MidIter { on_first_iter } => on_first_iter + }; + + if !on_first_iter { + last.iterate(); + } + + if last.in_progress() { + true + } else if MultiProduct::iterate_last(rest, state) { + last.reset(); + last.iterate(); + // If iterator is None twice consecutively, then iterator is + // empty; whole product is empty. + last.in_progress() + } else { + false + } + } else { + // Reached end of iterator list. On initialisation, return true. + // At end of iteration (final iterator finishes), finish. + match state { + StartOfIter => false, + MidIter { on_first_iter } => on_first_iter + } + } + } + + /// Returns the unwrapped value of the next iteration. + fn curr_iterator(&self) -> Vec { + self.0.iter().map(|multi_iter| { + multi_iter.cur.clone().unwrap() + }).collect() + } + + /// Returns true if iteration has started and has not yet finished; false + /// otherwise. + fn in_progress(&self) -> bool { + if let Some(last) = self.0.last() { + last.in_progress() + } else { + false + } + } +} + +impl MultiProductIter + where I: Iterator + Clone, + I::Item: Clone +{ + fn new(iter: I) -> Self { + MultiProductIter { + cur: None, + iter: iter.clone(), + iter_orig: iter + } + } + + /// Iterate the managed iterator. + fn iterate(&mut self) { + self.cur = self.iter.next(); + } + + /// Reset the managed iterator. + fn reset(&mut self) { + self.iter = self.iter_orig.clone(); + } + + /// Returns true if the current iterator has been started and has not yet + /// finished; false otherwise. + fn in_progress(&self) -> bool { + self.cur.is_some() + } +} + +impl Iterator for MultiProduct + where I: Iterator + Clone, + I::Item: Clone +{ + type Item = Vec; + + fn next(&mut self) -> Option { + if MultiProduct::iterate_last( + &mut self.0, + MultiProductIterState::StartOfIter + ) { + Some(self.curr_iterator()) + } else { + None + } + } + + fn count(self) -> usize { + if self.0.is_empty() { + return 0; + } + + if !self.in_progress() { + return self.0.into_iter().fold(1, |acc, multi_iter| { + acc * multi_iter.iter.count() + }); + } + + self.0.into_iter().fold( + 0, + |acc, MultiProductIter { iter, iter_orig, cur: _ }| { + let total_count = iter_orig.count(); + let cur_count = iter.count(); + acc * total_count + cur_count + } + ) + } + + fn size_hint(&self) -> (usize, Option) { + // Not ExactSizeIterator because size may be larger than usize + if self.0.is_empty() { + return (0, Some(0)); + } + + if !self.in_progress() { + return self.0.iter().fold((1, Some(1)), |acc, multi_iter| { + size_hint::mul(acc, multi_iter.iter.size_hint()) + }); + } + + self.0.iter().fold( + (0, Some(0)), + |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| { + let cur_size = iter.size_hint(); + let total_size = iter_orig.size_hint(); + size_hint::add(size_hint::mul(acc, total_size), cur_size) + } + ) + } + + fn last(self) -> Option { + let iter_count = self.0.len(); + + let lasts: Self::Item = self.0.into_iter() + .map(|multi_iter| multi_iter.iter.last()) + .while_some() + .collect(); + + if lasts.len() == iter_count { + Some(lasts) + } else { + None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,128 @@ +use std::fmt; +use std::iter::FusedIterator; + +use super::lazy_buffer::LazyBuffer; +use alloc::vec::Vec; + +/// An iterator to iterate through all the `k`-length combinations in an iterator. +/// +/// See [`.combinations()`](crate::Itertools::combinations) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Combinations { + indices: Vec, + pool: LazyBuffer, + first: bool, +} + +impl Clone for Combinations + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(indices, pool, first); +} + +impl fmt::Debug for Combinations + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Combinations, indices, pool, first); +} + +/// Create a new `Combinations` from a clonable iterator. +pub fn combinations(iter: I, k: usize) -> Combinations + where I: Iterator +{ + let mut pool = LazyBuffer::new(iter); + pool.prefill(k); + + Combinations { + indices: (0..k).collect(), + pool, + first: true, + } +} + +impl Combinations { + /// Returns the length of a combination produced by this iterator. + #[inline] + pub fn k(&self) -> usize { self.indices.len() } + + /// Returns the (current) length of the pool from which combination elements are + /// selected. This value can change between invocations of [`next`](Combinations::next). + #[inline] + pub fn n(&self) -> usize { self.pool.len() } + + /// Returns a reference to the source iterator. + #[inline] + pub(crate) fn src(&self) -> &I { &self.pool.it } + + /// Resets this `Combinations` back to an initial state for combinations of length + /// `k` over the same pool data source. If `k` is larger than the current length + /// of the data pool an attempt is made to prefill the pool so that it holds `k` + /// elements. + pub(crate) fn reset(&mut self, k: usize) { + self.first = true; + + if k < self.indices.len() { + self.indices.truncate(k); + for i in 0..k { + self.indices[i] = i; + } + + } else { + for i in 0..self.indices.len() { + self.indices[i] = i; + } + self.indices.extend(self.indices.len()..k); + self.pool.prefill(k); + } + } +} + +impl Iterator for Combinations + where I: Iterator, + I::Item: Clone +{ + type Item = Vec; + fn next(&mut self) -> Option { + if self.first { + if self.k() > self.n() { + return None; + } + self.first = false; + } else if self.indices.is_empty() { + return None; + } else { + // Scan from the end, looking for an index to increment + let mut i: usize = self.indices.len() - 1; + + // Check if we need to consume more from the iterator + if self.indices[i] == self.pool.len() - 1 { + self.pool.get_next(); // may change pool size + } + + while self.indices[i] == i + self.pool.len() - self.indices.len() { + if i > 0 { + i -= 1; + } else { + // Reached the last combination + return None; + } + } + + // Increment index, and reset the ones to its right + self.indices[i] += 1; + for j in i+1..self.indices.len() { + self.indices[j] = self.indices[j - 1] + 1; + } + } + + // Create result vector based on the indices + Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect()) + } +} + +impl FusedIterator for Combinations + where I: Iterator, + I::Item: Clone +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations_with_replacement.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations_with_replacement.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations_with_replacement.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/combinations_with_replacement.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,109 @@ +use alloc::vec::Vec; +use std::fmt; +use std::iter::FusedIterator; + +use super::lazy_buffer::LazyBuffer; + +/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement. +/// +/// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement) +/// for more information. +#[derive(Clone)] +pub struct CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + indices: Vec, + pool: LazyBuffer, + first: bool, +} + +impl fmt::Debug for CombinationsWithReplacement +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug + Clone, +{ + debug_fmt_fields!(Combinations, indices, pool, first); +} + +impl CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + /// Map the current mask over the pool to get an output combination + fn current(&self) -> Vec { + self.indices.iter().map(|i| self.pool[*i].clone()).collect() + } +} + +/// Create a new `CombinationsWithReplacement` from a clonable iterator. +pub fn combinations_with_replacement(iter: I, k: usize) -> CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + let indices: Vec = alloc::vec![0; k]; + let pool: LazyBuffer = LazyBuffer::new(iter); + + CombinationsWithReplacement { + indices, + pool, + first: true, + } +} + +impl Iterator for CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + type Item = Vec; + fn next(&mut self) -> Option { + // If this is the first iteration, return early + if self.first { + // In empty edge cases, stop iterating immediately + return if !(self.indices.is_empty() || self.pool.get_next()) { + None + // Otherwise, yield the initial state + } else { + self.first = false; + Some(self.current()) + }; + } + + // Check if we need to consume more from the iterator + // This will run while we increment our first index digit + self.pool.get_next(); + + // Work out where we need to update our indices + let mut increment: Option<(usize, usize)> = None; + for (i, indices_int) in self.indices.iter().enumerate().rev() { + if *indices_int < self.pool.len()-1 { + increment = Some((i, indices_int + 1)); + break; + } + } + + match increment { + // If we can update the indices further + Some((increment_from, increment_value)) => { + // We need to update the rightmost non-max value + // and all those to the right + for indices_index in increment_from..self.indices.len() { + self.indices[indices_index] = increment_value; + } + Some(self.current()) + } + // Otherwise, we're done + None => None, + } + } +} + +impl FusedIterator for CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/concat_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/concat_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/concat_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/concat_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,23 @@ +use crate::Itertools; + +/// Combine all an iterator's elements into one element by using [`Extend`]. +/// +/// [`IntoIterator`]-enabled version of [`Itertools::concat`]. +/// +/// This combinator will extend the first item with each of the rest of the +/// items of the iterator. If the iterator is empty, the default value of +/// `I::Item` is returned. +/// +/// ```rust +/// use itertools::concat; +/// +/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; +/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]); +/// ``` +pub fn concat(iterable: I) -> I::Item + where I: IntoIterator, + I::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default +{ + #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce` + iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_default() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/cons_tuples_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/cons_tuples_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/cons_tuples_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/cons_tuples_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,64 @@ + +macro_rules! impl_cons_iter( + ($_A:ident, $_B:ident, ) => (); // stop + + ($A:ident, $($B:ident,)*) => ( + impl_cons_iter!($($B,)*); + #[allow(non_snake_case)] + impl Iterator for ConsTuples + where Iter: Iterator, + { + type Item = ($($B,)* X, ); + fn next(&mut self) -> Option { + self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + fn fold(self, accum: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) + } + } + + #[allow(non_snake_case)] + impl DoubleEndedIterator for ConsTuples + where Iter: DoubleEndedIterator, + { + fn next_back(&mut self) -> Option { + self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) + } + } + + ); +); + +impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,); + +/// An iterator that maps an iterator of tuples like +/// `((A, B), C)` to an iterator of `(A, B, C)`. +/// +/// Used by the `iproduct!()` macro. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct ConsTuples + where I: Iterator, +{ + iter: I, +} + +impl Clone for ConsTuples + where I: Clone + Iterator, +{ + clone_fields!(iter); +} + +/// Create an iterator that maps for example iterators of +/// `((A, B), C)` to `(A, B, C)`. +pub fn cons_tuples(iterable: I) -> ConsTuples + where I: IntoIterator +{ + ConsTuples { iter: iterable.into_iter() } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/diff.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/diff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/diff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/diff.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,61 @@ +//! "Diff"ing iterators for caching elements to sequential collections without requiring the new +//! elements' iterator to be `Clone`. +//! +//! - [`Diff`] (produced by the [`diff_with`] function) +//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from +//! a lock-step comparison. + +use crate::free::put_back; +use crate::structs::PutBack; + +/// A type returned by the [`diff_with`] function. +/// +/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some +/// iterator `J`. +pub enum Diff + where I: Iterator, + J: Iterator +{ + /// The index of the first non-matching element along with both iterator's remaining elements + /// starting with the first mis-match. + FirstMismatch(usize, PutBack, PutBack), + /// The total number of elements that were in `J` along with the remaining elements of `I`. + Shorter(usize, PutBack), + /// The total number of elements that were in `I` along with the remaining elements of `J`. + Longer(usize, PutBack), +} + +/// Compares every element yielded by both `i` and `j` with the given function in lock-step and +/// returns a [`Diff`] which describes how `j` differs from `i`. +/// +/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`, +/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as +/// `Diff::Shorter`. +/// +/// If the two elements of a step differ, the index of those elements along with the remaining +/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`. +/// +/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with +/// the remaining `j` elements will be returned as `Diff::Longer`. +pub fn diff_with(i: I, j: J, is_equal: F) + -> Option> + where I: IntoIterator, + J: IntoIterator, + F: Fn(&I::Item, &J::Item) -> bool +{ + let mut i = i.into_iter(); + let mut j = j.into_iter(); + let mut idx = 0; + while let Some(i_elem) = i.next() { + match j.next() { + None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))), + Some(j_elem) => if !is_equal(&i_elem, &j_elem) { + let remaining_i = put_back(i).with_value(i_elem); + let remaining_j = put_back(j).with_value(j_elem); + return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); + }, + } + idx += 1; + } + j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/duplicates_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/duplicates_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/duplicates_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/duplicates_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,216 @@ +use std::hash::Hash; + +mod private { + use std::collections::HashMap; + use std::hash::Hash; + use std::fmt; + + #[derive(Clone)] + #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] + pub struct DuplicatesBy { + pub(crate) iter: I, + pub(crate) meta: Meta, + } + + impl fmt::Debug for DuplicatesBy + where + I: Iterator + fmt::Debug, + V: fmt::Debug + Hash + Eq, + { + debug_fmt_fields!(DuplicatesBy, iter, meta.used); + } + + impl DuplicatesBy { + pub(crate) fn new(iter: I, key_method: F) -> Self { + DuplicatesBy { + iter, + meta: Meta { + used: HashMap::new(), + pending: 0, + key_method, + }, + } + } + } + + #[derive(Clone)] + pub struct Meta { + used: HashMap, + pending: usize, + key_method: F, + } + + impl Meta + where + Key: Eq + Hash, + { + /// Takes an item and returns it back to the caller if it's the second time we see it. + /// Otherwise the item is consumed and None is returned + #[inline(always)] + fn filter(&mut self, item: I) -> Option + where + F: KeyMethod, + { + let kv = self.key_method.make(item); + match self.used.get_mut(kv.key_ref()) { + None => { + self.used.insert(kv.key(), false); + self.pending += 1; + None + } + Some(true) => None, + Some(produced) => { + *produced = true; + self.pending -= 1; + Some(kv.value()) + } + } + } + } + + impl Iterator for DuplicatesBy + where + I: Iterator, + Key: Eq + Hash, + F: KeyMethod, + { + type Item = I::Item; + + fn next(&mut self) -> Option { + let DuplicatesBy { iter, meta } = self; + iter.find_map(|v| meta.filter(v)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, hi) = self.iter.size_hint(); + let hi = hi.map(|hi| { + if hi <= self.meta.pending { + // fewer or equally many iter-remaining elements than pending elements + // => at most, each iter-remaining element is matched + hi + } else { + // fewer pending elements than iter-remaining elements + // => at most: + // * each pending element is matched + // * the other iter-remaining elements come in pairs + self.meta.pending + (hi - self.meta.pending) / 2 + } + }); + // The lower bound is always 0 since we might only get unique items from now on + (0, hi) + } + } + + impl DoubleEndedIterator for DuplicatesBy + where + I: DoubleEndedIterator, + Key: Eq + Hash, + F: KeyMethod, + { + fn next_back(&mut self) -> Option { + let DuplicatesBy { iter, meta } = self; + iter.rev().find_map(|v| meta.filter(v)) + } + } + + /// A keying method for use with `DuplicatesBy` + pub trait KeyMethod { + type Container: KeyXorValue; + + fn make(&mut self, value: V) -> Self::Container; + } + + /// Apply the identity function to elements before checking them for equality. + #[derive(Debug)] + pub struct ById; + impl KeyMethod for ById { + type Container = JustValue; + + fn make(&mut self, v: V) -> Self::Container { + JustValue(v) + } + } + + /// Apply a user-supplied function to elements before checking them for equality. + pub struct ByFn(pub(crate) F); + impl fmt::Debug for ByFn { + debug_fmt_fields!(ByFn,); + } + impl KeyMethod for ByFn + where + F: FnMut(&V) -> K, + { + type Container = KeyValue; + + fn make(&mut self, v: V) -> Self::Container { + KeyValue((self.0)(&v), v) + } + } + + // Implementors of this trait can hold onto a key and a value but only give access to one of them + // at a time. This allows the key and the value to be the same value internally + pub trait KeyXorValue { + fn key_ref(&self) -> &K; + fn key(self) -> K; + fn value(self) -> V; + } + + #[derive(Debug)] + pub struct KeyValue(K, V); + impl KeyXorValue for KeyValue { + fn key_ref(&self) -> &K { + &self.0 + } + fn key(self) -> K { + self.0 + } + fn value(self) -> V { + self.1 + } + } + + #[derive(Debug)] + pub struct JustValue(V); + impl KeyXorValue for JustValue { + fn key_ref(&self) -> &V { + &self.0 + } + fn key(self) -> V { + self.0 + } + fn value(self) -> V { + self.0 + } + } +} + +/// An iterator adapter to filter for duplicate elements. +/// +/// See [`.duplicates_by()`](crate::Itertools::duplicates_by) for more information. +pub type DuplicatesBy = private::DuplicatesBy>; + +/// Create a new `DuplicatesBy` iterator. +pub fn duplicates_by(iter: I, f: F) -> DuplicatesBy +where + Key: Eq + Hash, + F: FnMut(&I::Item) -> Key, + I: Iterator, +{ + DuplicatesBy::new(iter, private::ByFn(f)) +} + +/// An iterator adapter to filter out duplicate elements. +/// +/// See [`.duplicates()`](crate::Itertools::duplicates) for more information. +pub type Duplicates = private::DuplicatesBy::Item, private::ById>; + +/// Create a new `Duplicates` iterator. +pub fn duplicates(iter: I) -> Duplicates +where + I: Iterator, + I::Item: Eq + Hash, +{ + Duplicates::new(iter, private::ById) +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/either_or_both.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/either_or_both.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/either_or_both.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/either_or_both.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,254 @@ +use crate::EitherOrBoth::*; + +use either::Either; + +/// Value that either holds a single A or B, or both. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum EitherOrBoth { + /// Both values are present. + Both(A, B), + /// Only the left value of type `A` is present. + Left(A), + /// Only the right value of type `B` is present. + Right(B), +} + +impl EitherOrBoth { + /// If `Left`, or `Both`, return true, otherwise, return false. + pub fn has_left(&self) -> bool { + self.as_ref().left().is_some() + } + + /// If `Right`, or `Both`, return true, otherwise, return false. + pub fn has_right(&self) -> bool { + self.as_ref().right().is_some() + } + + /// If Left, return true otherwise, return false. + /// Exclusive version of [`has_left`](EitherOrBoth::has_left). + pub fn is_left(&self) -> bool { + match *self { + Left(_) => true, + _ => false, + } + } + + /// If Right, return true otherwise, return false. + /// Exclusive version of [`has_right`](EitherOrBoth::has_right). + pub fn is_right(&self) -> bool { + match *self { + Right(_) => true, + _ => false, + } + } + + /// If Right, return true otherwise, return false. + /// Equivalent to `self.as_ref().both().is_some()`. + pub fn is_both(&self) -> bool { + self.as_ref().both().is_some() + } + + /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`. + pub fn left(self) -> Option { + match self { + Left(left) | Both(left, _) => Some(left), + _ => None, + } + } + + /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`. + pub fn right(self) -> Option { + match self { + Right(right) | Both(_, right) => Some(right), + _ => None, + } + } + + /// If Both, return `Some` tuple containing left and right. + pub fn both(self) -> Option<(A, B)> { + match self { + Both(a, b) => Some((a, b)), + _ => None, + } + } + + /// Converts from `&EitherOrBoth` to `EitherOrBoth<&A, &B>`. + pub fn as_ref(&self) -> EitherOrBoth<&A, &B> { + match *self { + Left(ref left) => Left(left), + Right(ref right) => Right(right), + Both(ref left, ref right) => Both(left, right), + } + } + + /// Converts from `&mut EitherOrBoth` to `EitherOrBoth<&mut A, &mut B>`. + pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> { + match *self { + Left(ref mut left) => Left(left), + Right(ref mut right) => Right(right), + Both(ref mut left, ref mut right) => Both(left, right), + } + } + + /// Convert `EitherOrBoth` to `EitherOrBoth`. + pub fn flip(self) -> EitherOrBoth { + match self { + Left(a) => Right(a), + Right(b) => Left(b), + Both(a, b) => Both(b, a), + } + } + + /// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is + /// present rewrapping the result in `self`'s original variant. + pub fn map_left(self, f: F) -> EitherOrBoth + where + F: FnOnce(A) -> M, + { + match self { + Both(a, b) => Both(f(a), b), + Left(a) => Left(f(a)), + Right(b) => Right(b), + } + } + + /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants. + /// If it is present rewrapping the result in `self`'s original variant. + pub fn map_right(self, f: F) -> EitherOrBoth + where + F: FnOnce(B) -> M, + { + match self { + Left(a) => Left(a), + Right(b) => Right(f(b)), + Both(a, b) => Both(a, f(b)), + } + } + + /// Apply the functions `f` and `g` on the value `a` and `b` respectively; + /// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants. + /// The Result is rewrapped `self`'s original variant. + pub fn map_any(self, f: F, g: G) -> EitherOrBoth + where + F: FnOnce(A) -> L, + G: FnOnce(B) -> R, + { + match self { + Left(a) => Left(f(a)), + Right(b) => Right(g(b)), + Both(a, b) => Both(f(a), g(b)), + } + } + + /// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, _)` variants if it is + /// present. + pub fn left_and_then(self, f: F) -> EitherOrBoth + where + F: FnOnce(A) -> EitherOrBoth, + { + match self { + Left(a) | Both(a, _) => f(a), + Right(b) => Right(b), + } + } + + /// Apply the function `f` on the value `b` + /// in `Right(b)` or `Both(_, b)` variants if it is present. + pub fn right_and_then(self, f: F) -> EitherOrBoth + where + F: FnOnce(B) -> EitherOrBoth, + { + match self { + Left(a) => Left(a), + Right(b) | Both(_, b) => f(b), + } + } + + /// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present. + /// Otherwise, returns the wrapped value for the present element, and the supplied + /// value for the other. The first (`l`) argument is used for a missing `Left` + /// value. The second (`r`) argument is used for a missing `Right` value. + /// + /// Arguments passed to `or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`or_else`], + /// which is lazily evaluated. + /// + /// [`or_else`]: EitherOrBoth::or_else + /// + /// # Examples + /// + /// ``` + /// # use itertools::EitherOrBoth; + /// assert_eq!(EitherOrBoth::Both("tree", 1).or("stone", 5), ("tree", 1)); + /// assert_eq!(EitherOrBoth::Left("tree").or("stone", 5), ("tree", 5)); + /// assert_eq!(EitherOrBoth::Right(1).or("stone", 5), ("stone", 1)); + /// ``` + pub fn or(self, l: A, r: B) -> (A, B) { + match self { + Left(inner_l) => (inner_l, r), + Right(inner_r) => (l, inner_r), + Both(inner_l, inner_r) => (inner_l, inner_r), + } + } + + /// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present. + /// Otherwise, returns the wrapped value for the present element, and the [`default`](Default::default) + /// for the other. + pub fn or_default(self) -> (A, B) + where + A: Default, + B: Default, + { + match self { + EitherOrBoth::Left(l) => (l, B::default()), + EitherOrBoth::Right(r) => (A::default(), r), + EitherOrBoth::Both(l, r) => (l, r), + } + } + + /// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present. + /// Otherwise, returns the wrapped value for the present element, and computes the + /// missing value with the supplied closure. The first argument (`l`) is used for a + /// missing `Left` value. The second argument (`r`) is used for a missing `Right` value. + /// + /// # Examples + /// + /// ``` + /// # use itertools::EitherOrBoth; + /// let k = 10; + /// assert_eq!(EitherOrBoth::Both("tree", 1).or_else(|| "stone", || 2 * k), ("tree", 1)); + /// assert_eq!(EitherOrBoth::Left("tree").or_else(|| "stone", || 2 * k), ("tree", 20)); + /// assert_eq!(EitherOrBoth::Right(1).or_else(|| "stone", || 2 * k), ("stone", 1)); + /// ``` + pub fn or_else A, R: FnOnce() -> B>(self, l: L, r: R) -> (A, B) { + match self { + Left(inner_l) => (inner_l, r()), + Right(inner_r) => (l(), inner_r), + Both(inner_l, inner_r) => (inner_l, inner_r), + } + } +} + +impl EitherOrBoth { + /// Return either value of left, right, or the product of `f` applied where `Both` are present. + pub fn reduce(self, f: F) -> T + where + F: FnOnce(T, T) -> T, + { + match self { + Left(a) => a, + Right(b) => b, + Both(a, b) => f(a, b), + } + } +} + +impl Into>> for EitherOrBoth { + fn into(self) -> Option> { + match self { + EitherOrBoth::Left(l) => Some(Either::Left(l)), + EitherOrBoth::Right(r) => Some(Either::Right(r)), + _ => None, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/exactly_one_err.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/exactly_one_err.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/exactly_one_err.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/exactly_one_err.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,110 @@ +#[cfg(feature = "use_std")] +use std::error::Error; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; + +use std::iter::ExactSizeIterator; + +use either::Either; + +use crate::size_hint; + +/// Iterator returned for the error case of `IterTools::exactly_one()` +/// This iterator yields exactly the same elements as the input iterator. +/// +/// During the execution of `exactly_one` the iterator must be mutated. This wrapper +/// effectively "restores" the state of the input iterator when it's handed back. +/// +/// This is very similar to `PutBackN` except this iterator only supports 0-2 elements and does not +/// use a `Vec`. +#[derive(Clone)] +pub struct ExactlyOneError +where + I: Iterator, +{ + first_two: Option>, + inner: I, +} + +impl ExactlyOneError +where + I: Iterator, +{ + /// Creates a new `ExactlyOneErr` iterator. + pub(crate) fn new(first_two: Option>, inner: I) -> Self { + Self { first_two, inner } + } + + fn additional_len(&self) -> usize { + match self.first_two { + Some(Either::Left(_)) => 2, + Some(Either::Right(_)) => 1, + None => 0, + } + } +} + +impl Iterator for ExactlyOneError +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + match self.first_two.take() { + Some(Either::Left([first, second])) => { + self.first_two = Some(Either::Right(second)); + Some(first) + }, + Some(Either::Right(second)) => { + Some(second) + } + None => { + self.inner.next() + } + } + } + + fn size_hint(&self) -> (usize, Option) { + size_hint::add_scalar(self.inner.size_hint(), self.additional_len()) + } +} + + +impl ExactSizeIterator for ExactlyOneError where I: ExactSizeIterator {} + +impl Display for ExactlyOneError + where I: Iterator, +{ + fn fmt(&self, f: &mut Formatter) -> FmtResult { + let additional = self.additional_len(); + if additional > 0 { + write!(f, "got at least 2 elements when exactly one was expected") + } else { + write!(f, "got zero elements when exactly one was expected") + } + } +} + +impl Debug for ExactlyOneError + where I: Iterator + Debug, + I::Item: Debug, +{ + fn fmt(&self, f: &mut Formatter) -> FmtResult { + match &self.first_two { + Some(Either::Left([first, second])) => { + write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner) + }, + Some(Either::Right(second)) => { + write!(f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]", second, self.inner) + } + None => { + write!(f, "ExactlyOneError[RemainingIter: {:?}]", self.inner) + } + } + } +} + +#[cfg(feature = "use_std")] +impl Error for ExactlyOneError where I: Iterator + Debug, I::Item: Debug, {} + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/extrema_set.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/extrema_set.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/extrema_set.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/extrema_set.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,48 @@ +use std::cmp::Ordering; + +/// Implementation guts for `min_set`, `min_set_by`, and `min_set_by_key`. +pub fn min_set_impl( + mut it: I, + mut key_for: F, + mut compare: Compare, +) -> Vec +where + I: Iterator, + F: FnMut(&I::Item) -> K, + Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering, +{ + match it.next() { + None => Vec::new(), + Some(element) => { + let mut current_key = key_for(&element); + let mut result = vec![element]; + it.for_each(|element| { + let key = key_for(&element); + match compare(&element, &result[0], &key, ¤t_key) { + Ordering::Less => { + result.clear(); + result.push(element); + current_key = key; + } + Ordering::Equal => { + result.push(element); + } + Ordering::Greater => {} + } + }); + result + } + } +} + +/// Implementation guts for `ax_set`, `max_set_by`, and `max_set_by_key`. +pub fn max_set_impl(it: I, key_for: F, mut compare: Compare) -> Vec +where + I: Iterator, + F: FnMut(&I::Item) -> K, + Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering, +{ + min_set_impl(it, key_for, |it1, it2, key1, key2| { + compare(it2, it1, key2, key1) + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/flatten_ok.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/flatten_ok.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/flatten_ok.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/flatten_ok.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,165 @@ +use crate::size_hint; +use std::{ + fmt, + iter::{DoubleEndedIterator, FusedIterator}, +}; + +pub fn flatten_ok(iter: I) -> FlattenOk +where + I: Iterator>, + T: IntoIterator, +{ + FlattenOk { + iter, + inner_front: None, + inner_back: None, + } +} + +/// An iterator adaptor that flattens `Result::Ok` values and +/// allows `Result::Err` values through unchanged. +/// +/// See [`.flatten_ok()`](crate::Itertools::flatten_ok) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct FlattenOk +where + I: Iterator>, + T: IntoIterator, +{ + iter: I, + inner_front: Option, + inner_back: Option, +} + +impl Iterator for FlattenOk +where + I: Iterator>, + T: IntoIterator, +{ + type Item = Result; + + fn next(&mut self) -> Option { + loop { + // Handle the front inner iterator. + if let Some(inner) = &mut self.inner_front { + if let Some(item) = inner.next() { + return Some(Ok(item)); + } + + // This is necessary for the iterator to implement `FusedIterator` + // with only the original iterator being fused. + self.inner_front = None; + } + + match self.iter.next() { + Some(Ok(ok)) => self.inner_front = Some(ok.into_iter()), + Some(Err(e)) => return Some(Err(e)), + None => { + // Handle the back inner iterator. + if let Some(inner) = &mut self.inner_back { + if let Some(item) = inner.next() { + return Some(Ok(item)); + } + + // This is necessary for the iterator to implement `FusedIterator` + // with only the original iterator being fused. + self.inner_back = None; + } else { + return None; + } + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let inner_hint = |inner: &Option| { + inner + .as_ref() + .map(Iterator::size_hint) + .unwrap_or((0, Some(0))) + }; + let inner_front = inner_hint(&self.inner_front); + let inner_back = inner_hint(&self.inner_back); + // The outer iterator `Ok` case could be (0, None) as we don't know its size_hint yet. + let outer = match self.iter.size_hint() { + (0, Some(0)) => (0, Some(0)), + _ => (0, None), + }; + + size_hint::add(size_hint::add(inner_front, inner_back), outer) + } +} + +impl DoubleEndedIterator for FlattenOk +where + I: DoubleEndedIterator>, + T: IntoIterator, + T::IntoIter: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + loop { + // Handle the back inner iterator. + if let Some(inner) = &mut self.inner_back { + if let Some(item) = inner.next_back() { + return Some(Ok(item)); + } + + // This is necessary for the iterator to implement `FusedIterator` + // with only the original iterator being fused. + self.inner_back = None; + } + + match self.iter.next_back() { + Some(Ok(ok)) => self.inner_back = Some(ok.into_iter()), + Some(Err(e)) => return Some(Err(e)), + None => { + // Handle the front inner iterator. + if let Some(inner) = &mut self.inner_front { + if let Some(item) = inner.next_back() { + return Some(Ok(item)); + } + + // This is necessary for the iterator to implement `FusedIterator` + // with only the original iterator being fused. + self.inner_front = None; + } else { + return None; + } + } + } + } + } +} + +impl Clone for FlattenOk +where + I: Iterator> + Clone, + T: IntoIterator, + T::IntoIter: Clone, +{ + clone_fields!(iter, inner_front, inner_back); +} + +impl fmt::Debug for FlattenOk +where + I: Iterator> + fmt::Debug, + T: IntoIterator, + T::IntoIter: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FlattenOk") + .field("iter", &self.iter) + .field("inner_front", &self.inner_front) + .field("inner_back", &self.inner_back) + .finish() + } +} + +/// Only the iterator being flattened needs to implement [`FusedIterator`]. +impl FusedIterator for FlattenOk +where + I: FusedIterator>, + T: IntoIterator, +{ +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/format.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/format.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/format.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/format.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,113 @@ +use std::fmt; +use std::cell::RefCell; + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format_with()`](crate::Itertools::format_with) for more information. +#[derive(Clone)] +pub struct FormatWith<'a, I, F> { + sep: &'a str, + /// FormatWith uses interior mutability because Display::fmt takes &self. + inner: RefCell>, +} + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format()`](crate::Itertools::format) +/// for more information. +#[derive(Clone)] +pub struct Format<'a, I> { + sep: &'a str, + /// Format uses interior mutability because Display::fmt takes &self. + inner: RefCell>, +} + +pub fn new_format(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +{ + FormatWith { + sep: separator, + inner: RefCell::new(Some((iter, f))), + } +} + +pub fn new_format_default(iter: I, separator: &str) -> Format<'_, I> + where I: Iterator, +{ + Format { + sep: separator, + inner: RefCell::new(Some(iter)), + } +} + +impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (mut iter, mut format) = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("FormatWith: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?; + iter.try_for_each(|elt| { + if !self.sep.is_empty() { + f.write_str(self.sep)?; + } + format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f)) + })?; + } + Ok(()) + } +} + +impl<'a, I> Format<'a, I> + where I: Iterator, +{ + fn format(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result + where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, + { + let mut iter = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("Format: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + cb(&fst, f)?; + iter.try_for_each(|elt| { + if !self.sep.is_empty() { + f.write_str(self.sep)?; + } + cb(&elt, f) + })?; + } + Ok(()) + } +} + +macro_rules! impl_format { + ($($fmt_trait:ident)*) => { + $( + impl<'a, I> fmt::$fmt_trait for Format<'a, I> + where I: Iterator, + I::Item: fmt::$fmt_trait, + { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f, fmt::$fmt_trait::fmt) + } + } + )* + } +} + +impl_format!{Display Debug + UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/free.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/free.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/free.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/free.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,286 @@ +//! Free functions that create iterator adaptors or call iterator methods. +//! +//! The benefit of free functions is that they accept any [`IntoIterator`] as +//! argument, so the resulting code may be easier to read. + +#[cfg(feature = "use_alloc")] +use std::fmt::Display; +use std::iter::{self, Zip}; +#[cfg(feature = "use_alloc")] +type VecIntoIter = alloc::vec::IntoIter; + +#[cfg(feature = "use_alloc")] +use alloc::{ + string::String, +}; + +use crate::Itertools; +use crate::intersperse::{Intersperse, IntersperseWith}; + +pub use crate::adaptors::{ + interleave, + merge, + put_back, +}; +#[cfg(feature = "use_alloc")] +pub use crate::put_back_n_impl::put_back_n; +#[cfg(feature = "use_alloc")] +pub use crate::multipeek_impl::multipeek; +#[cfg(feature = "use_alloc")] +pub use crate::peek_nth::peek_nth; +#[cfg(feature = "use_alloc")] +pub use crate::kmerge_impl::kmerge; +pub use crate::zip_eq_impl::zip_eq; +pub use crate::merge_join::merge_join_by; +#[cfg(feature = "use_alloc")] +pub use crate::rciter_impl::rciter; + +/// Iterate `iterable` with a particular value inserted between each element. +/// +/// [`IntoIterator`] enabled version of [`Iterator::intersperse`]. +/// +/// ``` +/// use itertools::intersperse; +/// +/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]); +/// ``` +pub fn intersperse(iterable: I, element: I::Item) -> Intersperse + where I: IntoIterator, + ::Item: Clone +{ + Itertools::intersperse(iterable.into_iter(), element) +} + +/// Iterate `iterable` with a particular value created by a function inserted +/// between each element. +/// +/// [`IntoIterator`] enabled version of [`Iterator::intersperse_with`]. +/// +/// ``` +/// use itertools::intersperse_with; +/// +/// let mut i = 10; +/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]); +/// assert_eq!(i, 8); +/// ``` +pub fn intersperse_with(iterable: I, element: F) -> IntersperseWith + where I: IntoIterator, + F: FnMut() -> I::Item +{ + Itertools::intersperse_with(iterable.into_iter(), element) +} + +/// Iterate `iterable` with a running index. +/// +/// [`IntoIterator`] enabled version of [`Iterator::enumerate`]. +/// +/// ``` +/// use itertools::enumerate; +/// +/// for (i, elt) in enumerate(&[1, 2, 3]) { +/// /* loop body */ +/// } +/// ``` +pub fn enumerate(iterable: I) -> iter::Enumerate + where I: IntoIterator +{ + iterable.into_iter().enumerate() +} + +/// Iterate `iterable` in reverse. +/// +/// [`IntoIterator`] enabled version of [`Iterator::rev`]. +/// +/// ``` +/// use itertools::rev; +/// +/// for elt in rev(&[1, 2, 3]) { +/// /* loop body */ +/// } +/// ``` +pub fn rev(iterable: I) -> iter::Rev + where I: IntoIterator, + I::IntoIter: DoubleEndedIterator +{ + iterable.into_iter().rev() +} + +/// Converts the arguments to iterators and zips them. +/// +/// [`IntoIterator`] enabled version of [`Iterator::zip`]. +/// +/// ## Example +/// +/// ``` +/// use itertools::zip; +/// +/// let mut result: Vec<(i32, char)> = Vec::new(); +/// +/// for (a, b) in zip(&[1, 2, 3, 4, 5], &['a', 'b', 'c']) { +/// result.push((*a, *b)); +/// } +/// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]); +/// ``` +#[deprecated(note="Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead", since="0.10.4")] +pub fn zip(i: I, j: J) -> Zip + where I: IntoIterator, + J: IntoIterator +{ + i.into_iter().zip(j) +} + + +/// Takes two iterables and creates a new iterator over both in sequence. +/// +/// [`IntoIterator`] enabled version of [`Iterator::chain`]. +/// +/// ## Example +/// ``` +/// use itertools::chain; +/// +/// let mut result:Vec = Vec::new(); +/// +/// for element in chain(&[1, 2, 3], &[4]) { +/// result.push(*element); +/// } +/// assert_eq!(result, vec![1, 2, 3, 4]); +/// ``` +pub fn chain(i: I, j: J) -> iter::Chain<::IntoIter, ::IntoIter> + where I: IntoIterator, + J: IntoIterator +{ + i.into_iter().chain(j) +} + +/// Create an iterator that clones each element from &T to T +/// +/// [`IntoIterator`] enabled version of [`Iterator::cloned`]. +/// +/// ``` +/// use itertools::cloned; +/// +/// assert_eq!(cloned(b"abc").next(), Some(b'a')); +/// ``` +pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned + where I: IntoIterator, + T: Clone, +{ + iterable.into_iter().cloned() +} + +/// Perform a fold operation over the iterable. +/// +/// [`IntoIterator`] enabled version of [`Iterator::fold`]. +/// +/// ``` +/// use itertools::fold; +/// +/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.); +/// ``` +pub fn fold(iterable: I, init: B, f: F) -> B + where I: IntoIterator, + F: FnMut(B, I::Item) -> B +{ + iterable.into_iter().fold(init, f) +} + +/// Test whether the predicate holds for all elements in the iterable. +/// +/// [`IntoIterator`] enabled version of [`Iterator::all`]. +/// +/// ``` +/// use itertools::all; +/// +/// assert!(all(&[1, 2, 3], |elt| *elt > 0)); +/// ``` +pub fn all(iterable: I, f: F) -> bool + where I: IntoIterator, + F: FnMut(I::Item) -> bool +{ + iterable.into_iter().all(f) +} + +/// Test whether the predicate holds for any elements in the iterable. +/// +/// [`IntoIterator`] enabled version of [`Iterator::any`]. +/// +/// ``` +/// use itertools::any; +/// +/// assert!(any(&[0, -1, 2], |elt| *elt > 0)); +/// ``` +pub fn any(iterable: I, f: F) -> bool + where I: IntoIterator, + F: FnMut(I::Item) -> bool +{ + iterable.into_iter().any(f) +} + +/// Return the maximum value of the iterable. +/// +/// [`IntoIterator`] enabled version of [`Iterator::max`]. +/// +/// ``` +/// use itertools::max; +/// +/// assert_eq!(max(0..10), Some(9)); +/// ``` +pub fn max(iterable: I) -> Option + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().max() +} + +/// Return the minimum value of the iterable. +/// +/// [`IntoIterator`] enabled version of [`Iterator::min`]. +/// +/// ``` +/// use itertools::min; +/// +/// assert_eq!(min(0..10), Some(0)); +/// ``` +pub fn min(iterable: I) -> Option + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().min() +} + + +/// Combine all iterator elements into one String, separated by `sep`. +/// +/// [`IntoIterator`] enabled version of [`Itertools::join`]. +/// +/// ``` +/// use itertools::join; +/// +/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3"); +/// ``` +#[cfg(feature = "use_alloc")] +pub fn join(iterable: I, sep: &str) -> String + where I: IntoIterator, + I::Item: Display +{ + iterable.into_iter().join(sep) +} + +/// Sort all iterator elements into a new iterator in ascending order. +/// +/// [`IntoIterator`] enabled version of [`Itertools::sorted`]. +/// +/// ``` +/// use itertools::sorted; +/// use itertools::assert_equal; +/// +/// assert_equal(sorted("rust".chars()), "rstu".chars()); +/// ``` +#[cfg(feature = "use_alloc")] +pub fn sorted(iterable: I) -> VecIntoIter + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().sorted() +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/group_map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/group_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/group_map.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/group_map.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,32 @@ +#![cfg(feature = "use_std")] + +use std::collections::HashMap; +use std::hash::Hash; +use std::iter::Iterator; + +/// Return a `HashMap` of keys mapped to a list of their corresponding values. +/// +/// See [`.into_group_map()`](crate::Itertools::into_group_map) +/// for more information. +pub fn into_group_map(iter: I) -> HashMap> + where I: Iterator, + K: Hash + Eq, +{ + let mut lookup = HashMap::new(); + + iter.for_each(|(key, val)| { + lookup.entry(key).or_insert_with(Vec::new).push(val); + }); + + lookup +} + +pub fn into_group_map_by(iter: I, f: impl Fn(&V) -> K) -> HashMap> + where + I: Iterator, + K: Hash + Eq, +{ + into_group_map( + iter.map(|v| (f(&v), v)) + ) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/groupbylazy.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/groupbylazy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/groupbylazy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/groupbylazy.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,571 @@ +use std::cell::{Cell, RefCell}; +use alloc::vec::{self, Vec}; + +/// A trait to unify `FnMut` for `GroupBy` with the chunk key in `IntoChunks` +trait KeyFunction { + type Key; + fn call_mut(&mut self, arg: A) -> Self::Key; +} + +impl KeyFunction for F + where F: FnMut(A) -> K +{ + type Key = K; + #[inline] + fn call_mut(&mut self, arg: A) -> Self::Key { + (*self)(arg) + } +} + + +/// `ChunkIndex` acts like the grouping key function for `IntoChunks` +#[derive(Debug)] +struct ChunkIndex { + size: usize, + index: usize, + key: usize, +} + +impl ChunkIndex { + #[inline(always)] + fn new(size: usize) -> Self { + ChunkIndex { + size, + index: 0, + key: 0, + } + } +} + +impl KeyFunction for ChunkIndex { + type Key = usize; + #[inline(always)] + fn call_mut(&mut self, _arg: A) -> Self::Key { + if self.index == self.size { + self.key += 1; + self.index = 0; + } + self.index += 1; + self.key + } +} + + +struct GroupInner + where I: Iterator +{ + key: F, + iter: I, + current_key: Option, + current_elt: Option, + /// flag set if iterator is exhausted + done: bool, + /// Index of group we are currently buffering or visiting + top_group: usize, + /// Least index for which we still have elements buffered + oldest_buffered_group: usize, + /// Group index for `buffer[0]` -- the slots + /// bottom_group..oldest_buffered_group are unused and will be erased when + /// that range is large enough. + bottom_group: usize, + /// Buffered groups, from `bottom_group` (index 0) to `top_group`. + buffer: Vec>, + /// index of last group iter that was dropped, usize::MAX == none + dropped_group: usize, +} + +impl GroupInner + where I: Iterator, + F: for<'a> KeyFunction<&'a I::Item, Key=K>, + K: PartialEq, +{ + /// `client`: Index of group that requests next element + #[inline(always)] + fn step(&mut self, client: usize) -> Option { + /* + println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]", + client, self.bottom_group, self.oldest_buffered_group, + self.top_group, + self.buffer.iter().map(|elt| elt.len()).format(", ")); + */ + if client < self.oldest_buffered_group { + None + } else if client < self.top_group || + (client == self.top_group && + self.buffer.len() > self.top_group - self.bottom_group) + { + self.lookup_buffer(client) + } else if self.done { + None + } else if self.top_group == client { + self.step_current() + } else { + self.step_buffering(client) + } + } + + #[inline(never)] + fn lookup_buffer(&mut self, client: usize) -> Option { + // if `bufidx` doesn't exist in self.buffer, it might be empty + let bufidx = client - self.bottom_group; + if client < self.oldest_buffered_group { + return None; + } + let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next()); + if elt.is_none() && client == self.oldest_buffered_group { + // FIXME: VecDeque is unfortunately not zero allocation when empty, + // so we do this job manually. + // `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it. + self.oldest_buffered_group += 1; + // skip forward further empty queues too + while self.buffer.get(self.oldest_buffered_group - self.bottom_group) + .map_or(false, |buf| buf.len() == 0) + { + self.oldest_buffered_group += 1; + } + + let nclear = self.oldest_buffered_group - self.bottom_group; + if nclear > 0 && nclear >= self.buffer.len() / 2 { + let mut i = 0; + self.buffer.retain(|buf| { + i += 1; + debug_assert!(buf.len() == 0 || i > nclear); + i > nclear + }); + self.bottom_group = self.oldest_buffered_group; + } + } + elt + } + + /// Take the next element from the iterator, and set the done + /// flag if exhausted. Must not be called after done. + #[inline(always)] + fn next_element(&mut self) -> Option { + debug_assert!(!self.done); + match self.iter.next() { + None => { self.done = true; None } + otherwise => otherwise, + } + } + + + #[inline(never)] + fn step_buffering(&mut self, client: usize) -> Option { + // requested a later group -- walk through the current group up to + // the requested group index, and buffer the elements (unless + // the group is marked as dropped). + // Because the `Groups` iterator is always the first to request + // each group index, client is the next index efter top_group. + debug_assert!(self.top_group + 1 == client); + let mut group = Vec::new(); + + if let Some(elt) = self.current_elt.take() { + if self.top_group != self.dropped_group { + group.push(elt); + } + } + let mut first_elt = None; // first element of the next group + + while let Some(elt) = self.next_element() { + let key = self.key.call_mut(&elt); + match self.current_key.take() { + None => {} + Some(old_key) => if old_key != key { + self.current_key = Some(key); + first_elt = Some(elt); + break; + }, + } + self.current_key = Some(key); + if self.top_group != self.dropped_group { + group.push(elt); + } + } + + if self.top_group != self.dropped_group { + self.push_next_group(group); + } + if first_elt.is_some() { + self.top_group += 1; + debug_assert!(self.top_group == client); + } + first_elt + } + + fn push_next_group(&mut self, group: Vec) { + // When we add a new buffered group, fill up slots between oldest_buffered_group and top_group + while self.top_group - self.bottom_group > self.buffer.len() { + if self.buffer.is_empty() { + self.bottom_group += 1; + self.oldest_buffered_group += 1; + } else { + self.buffer.push(Vec::new().into_iter()); + } + } + self.buffer.push(group.into_iter()); + debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len()); + } + + /// This is the immediate case, where we use no buffering + #[inline] + fn step_current(&mut self) -> Option { + debug_assert!(!self.done); + if let elt @ Some(..) = self.current_elt.take() { + return elt; + } + match self.next_element() { + None => None, + Some(elt) => { + let key = self.key.call_mut(&elt); + match self.current_key.take() { + None => {} + Some(old_key) => if old_key != key { + self.current_key = Some(key); + self.current_elt = Some(elt); + self.top_group += 1; + return None; + }, + } + self.current_key = Some(key); + Some(elt) + } + } + } + + /// Request the just started groups' key. + /// + /// `client`: Index of group + /// + /// **Panics** if no group key is available. + fn group_key(&mut self, client: usize) -> K { + // This can only be called after we have just returned the first + // element of a group. + // Perform this by simply buffering one more element, grabbing the + // next key. + debug_assert!(!self.done); + debug_assert!(client == self.top_group); + debug_assert!(self.current_key.is_some()); + debug_assert!(self.current_elt.is_none()); + let old_key = self.current_key.take().unwrap(); + if let Some(elt) = self.next_element() { + let key = self.key.call_mut(&elt); + if old_key != key { + self.top_group += 1; + } + self.current_key = Some(key); + self.current_elt = Some(elt); + } + old_key + } +} + +impl GroupInner + where I: Iterator, +{ + /// Called when a group is dropped + fn drop_group(&mut self, client: usize) { + // It's only useful to track the maximal index + if self.dropped_group == !0 || client > self.dropped_group { + self.dropped_group = client; + } + } +} + +/// `GroupBy` is the storage for the lazy grouping operation. +/// +/// If the groups are consumed in their original order, or if each +/// group is dropped without keeping it around, then `GroupBy` uses +/// no allocations. It needs allocations only if several group iterators +/// are alive at the same time. +/// +/// This type implements [`IntoIterator`] (it is **not** an iterator +/// itself), because the group iterators need to borrow from this +/// value. It should be stored in a local variable or temporary and +/// iterated. +/// +/// See [`.group_by()`](crate::Itertools::group_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct GroupBy + where I: Iterator, +{ + inner: RefCell>, + // the group iterator's current index. Keep this in the main value + // so that simultaneous iterators all use the same state. + index: Cell, +} + +/// Create a new +pub fn new(iter: J, f: F) -> GroupBy + where J: IntoIterator, + F: FnMut(&J::Item) -> K, +{ + GroupBy { + inner: RefCell::new(GroupInner { + key: f, + iter: iter.into_iter(), + current_key: None, + current_elt: None, + done: false, + top_group: 0, + oldest_buffered_group: 0, + bottom_group: 0, + buffer: Vec::new(), + dropped_group: !0, + }), + index: Cell::new(0), + } +} + +impl GroupBy + where I: Iterator, +{ + /// `client`: Index of group that requests next element + fn step(&self, client: usize) -> Option + where F: FnMut(&I::Item) -> K, + K: PartialEq, + { + self.inner.borrow_mut().step(client) + } + + /// `client`: Index of group + fn drop_group(&self, client: usize) { + self.inner.borrow_mut().drop_group(client); + } +} + +impl<'a, K, I, F> IntoIterator for &'a GroupBy + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq +{ + type Item = (K, Group<'a, K, I, F>); + type IntoIter = Groups<'a, K, I, F>; + + fn into_iter(self) -> Self::IntoIter { + Groups { parent: self } + } +} + + +/// An iterator that yields the Group iterators. +/// +/// Iterator element type is `(K, Group)`: +/// the group's key `K` and the group's iterator. +/// +/// See [`.group_by()`](crate::Itertools::group_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Groups<'a, K: 'a, I: 'a, F: 'a> + where I: Iterator, + I::Item: 'a +{ + parent: &'a GroupBy, +} + +impl<'a, K, I, F> Iterator for Groups<'a, K, I, F> + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq +{ + type Item = (K, Group<'a, K, I, F>); + + #[inline] + fn next(&mut self) -> Option { + let index = self.parent.index.get(); + self.parent.index.set(index + 1); + let inner = &mut *self.parent.inner.borrow_mut(); + inner.step(index).map(|elt| { + let key = inner.group_key(index); + (key, Group { + parent: self.parent, + index, + first: Some(elt), + }) + }) + } +} + +/// An iterator for the elements in a single group. +/// +/// Iterator element type is `I::Item`. +pub struct Group<'a, K: 'a, I: 'a, F: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a GroupBy, + index: usize, + first: Option, +} + +impl<'a, K, I, F> Drop for Group<'a, K, I, F> + where I: Iterator, + I::Item: 'a, +{ + fn drop(&mut self) { + self.parent.drop_group(self.index); + } +} + +impl<'a, K, I, F> Iterator for Group<'a, K, I, F> + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq, +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + if let elt @ Some(..) = self.first.take() { + return elt; + } + self.parent.step(self.index) + } +} + +///// IntoChunks ///// + +/// Create a new +pub fn new_chunks(iter: J, size: usize) -> IntoChunks + where J: IntoIterator, +{ + IntoChunks { + inner: RefCell::new(GroupInner { + key: ChunkIndex::new(size), + iter: iter.into_iter(), + current_key: None, + current_elt: None, + done: false, + top_group: 0, + oldest_buffered_group: 0, + bottom_group: 0, + buffer: Vec::new(), + dropped_group: !0, + }), + index: Cell::new(0), + } +} + + +/// `ChunkLazy` is the storage for a lazy chunking operation. +/// +/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and +/// it only buffers if several chunk iterators are alive at the same time. +/// +/// This type implements [`IntoIterator`] (it is **not** an iterator +/// itself), because the chunk iterators need to borrow from this +/// value. It should be stored in a local variable or temporary and +/// iterated. +/// +/// Iterator element type is `Chunk`, each chunk's iterator. +/// +/// See [`.chunks()`](crate::Itertools::chunks) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct IntoChunks + where I: Iterator, +{ + inner: RefCell>, + // the chunk iterator's current index. Keep this in the main value + // so that simultaneous iterators all use the same state. + index: Cell, +} + + +impl IntoChunks + where I: Iterator, +{ + /// `client`: Index of chunk that requests next element + fn step(&self, client: usize) -> Option { + self.inner.borrow_mut().step(client) + } + + /// `client`: Index of chunk + fn drop_group(&self, client: usize) { + self.inner.borrow_mut().drop_group(client); + } +} + +impl<'a, I> IntoIterator for &'a IntoChunks + where I: Iterator, + I::Item: 'a, +{ + type Item = Chunk<'a, I>; + type IntoIter = Chunks<'a, I>; + + fn into_iter(self) -> Self::IntoIter { + Chunks { + parent: self, + } + } +} + + +/// An iterator that yields the Chunk iterators. +/// +/// Iterator element type is `Chunk`. +/// +/// See [`.chunks()`](crate::Itertools::chunks) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Chunks<'a, I: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a IntoChunks, +} + +impl<'a, I> Iterator for Chunks<'a, I> + where I: Iterator, + I::Item: 'a, +{ + type Item = Chunk<'a, I>; + + #[inline] + fn next(&mut self) -> Option { + let index = self.parent.index.get(); + self.parent.index.set(index + 1); + let inner = &mut *self.parent.inner.borrow_mut(); + inner.step(index).map(|elt| { + Chunk { + parent: self.parent, + index, + first: Some(elt), + } + }) + } +} + +/// An iterator for the elements in a single chunk. +/// +/// Iterator element type is `I::Item`. +pub struct Chunk<'a, I: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a IntoChunks, + index: usize, + first: Option, +} + +impl<'a, I> Drop for Chunk<'a, I> + where I: Iterator, + I::Item: 'a, +{ + fn drop(&mut self) { + self.parent.drop_group(self.index); + } +} + +impl<'a, I> Iterator for Chunk<'a, I> + where I: Iterator, + I::Item: 'a, +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + if let elt @ Some(..) = self.first.take() { + return elt; + } + self.parent.step(self.index) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/grouping_map.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/grouping_map.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/grouping_map.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/grouping_map.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,535 @@ +#![cfg(feature = "use_std")] + +use crate::MinMaxResult; +use std::collections::HashMap; +use std::cmp::Ordering; +use std::hash::Hash; +use std::iter::Iterator; +use std::ops::{Add, Mul}; + +/// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by) +#[derive(Clone, Debug)] +pub struct MapForGrouping(I, F); + +impl MapForGrouping { + pub(crate) fn new(iter: I, key_mapper: F) -> Self { + Self(iter, key_mapper) + } +} + +impl Iterator for MapForGrouping + where I: Iterator, + K: Hash + Eq, + F: FnMut(&V) -> K, +{ + type Item = (K, V); + fn next(&mut self) -> Option { + self.0.next().map(|val| ((self.1)(&val), val)) + } +} + +/// Creates a new `GroupingMap` from `iter` +pub fn new(iter: I) -> GroupingMap + where I: Iterator, + K: Hash + Eq, +{ + GroupingMap { iter } +} + +/// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations. +/// +/// See [`GroupingMap`] for more informations. +pub type GroupingMapBy = GroupingMap>; + +/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations. +/// It groups elements by their key and at the same time fold each group +/// using some aggregating operation. +/// +/// No method on this struct performs temporary allocations. +#[derive(Clone, Debug)] +#[must_use = "GroupingMap is lazy and do nothing unless consumed"] +pub struct GroupingMap { + iter: I, +} + +impl GroupingMap + where I: Iterator, + K: Hash + Eq, +{ + /// This is the generic way to perform any operation on a `GroupingMap`. + /// It's suggested to use this method only to implement custom operations + /// when the already provided ones are not enough. + /// + /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements + /// of each group sequentially, passing the previously accumulated value, a reference to the key + /// and the current element as arguments, and stores the results in an `HashMap`. + /// + /// The `operation` function is invoked on each element with the following parameters: + /// - the current value of the accumulator of the group if there is currently one; + /// - a reference to the key of the group this element belongs to; + /// - the element from the source being aggregated; + /// + /// If `operation` returns `Some(element)` then the accumulator is updated with `element`, + /// otherwise the previous accumulation is discarded. + /// + /// Return a `HashMap` associating the key of each group with the result of aggregation of + /// that group's elements. If the aggregation of the last element of a group discards the + /// accumulator then there won't be an entry associated to that group's key. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10]; + /// let lookup = data.into_iter() + /// .into_grouping_map_by(|&n| n % 4) + /// .aggregate(|acc, _key, val| { + /// if val == 0 || val == 10 { + /// None + /// } else { + /// Some(acc.unwrap_or(0) + val) + /// } + /// }); + /// + /// assert_eq!(lookup[&0], 4); // 0 resets the accumulator so only 4 is summed + /// assert_eq!(lookup[&1], 5 + 9); + /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward + /// assert_eq!(lookup[&3], 7); + /// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2 + /// ``` + pub fn aggregate(self, mut operation: FO) -> HashMap + where FO: FnMut(Option, &K, V) -> Option, + { + let mut destination_map = HashMap::new(); + + self.iter.for_each(|(key, val)| { + let acc = destination_map.remove(&key); + if let Some(op_res) = operation(acc, &key, val) { + destination_map.insert(key, op_res); + } + }); + + destination_map + } + + /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements + /// of each group sequentially, passing the previously accumulated value, a reference to the key + /// and the current element as arguments, and stores the results in a new map. + /// + /// `init` is the value from which will be cloned the initial value of each accumulator. + /// + /// `operation` is a function that is invoked on each element with the following parameters: + /// - the current value of the accumulator of the group; + /// - a reference to the key of the group this element belongs to; + /// - the element from the source being accumulated. + /// + /// Return a `HashMap` associating the key of each group with the result of folding that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = (1..=7) + /// .into_grouping_map_by(|&n| n % 3) + /// .fold(0, |acc, _key, val| acc + val); + /// + /// assert_eq!(lookup[&0], 3 + 6); + /// assert_eq!(lookup[&1], 1 + 4 + 7); + /// assert_eq!(lookup[&2], 2 + 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn fold(self, init: R, mut operation: FO) -> HashMap + where R: Clone, + FO: FnMut(R, &K, V) -> R, + { + self.aggregate(|acc, key, val| { + let acc = acc.unwrap_or_else(|| init.clone()); + Some(operation(acc, key, val)) + }) + } + + /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements + /// of each group sequentially, passing the previously accumulated value, a reference to the key + /// and the current element as arguments, and stores the results in a new map. + /// + /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group. + /// + /// `operation` is a function that is invoked on each element with the following parameters: + /// - the current value of the accumulator of the group; + /// - a reference to the key of the group this element belongs to; + /// - the element from the source being accumulated. + /// + /// Return a `HashMap` associating the key of each group with the result of folding that group's elements. + /// + /// [`fold`]: GroupingMap::fold + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = (1..=7) + /// .into_grouping_map_by(|&n| n % 3) + /// .fold_first(|acc, _key, val| acc + val); + /// + /// assert_eq!(lookup[&0], 3 + 6); + /// assert_eq!(lookup[&1], 1 + 4 + 7); + /// assert_eq!(lookup[&2], 2 + 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn fold_first(self, mut operation: FO) -> HashMap + where FO: FnMut(V, &K, V) -> V, + { + self.aggregate(|acc, key, val| { + Some(match acc { + Some(acc) => operation(acc, key, val), + None => val, + }) + }) + } + + /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in + /// an instance of `C`. The iteration order is preserved when inserting elements. + /// + /// Return a `HashMap` associating the key of each group with the collection containing that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// use std::collections::HashSet; + /// + /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .collect::>(); + /// + /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect::>()); + /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect::>()); + /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect::>()); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn collect(self) -> HashMap + where C: Default + Extend, + { + let mut destination_map = HashMap::new(); + + self.iter.for_each(|(key, val)| { + destination_map.entry(key).or_insert_with(C::default).extend(Some(val)); + }); + + destination_map + } + + /// Groups elements from the `GroupingMap` source by key and finds the maximum of each group. + /// + /// If several elements are equally maximum, the last element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .max(); + /// + /// assert_eq!(lookup[&0], 12); + /// assert_eq!(lookup[&1], 7); + /// assert_eq!(lookup[&2], 8); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn max(self) -> HashMap + where V: Ord, + { + self.max_by(|_, v1, v2| V::cmp(v1, v2)) + } + + /// Groups elements from the `GroupingMap` source by key and finds the maximum of each group + /// with respect to the specified comparison function. + /// + /// If several elements are equally maximum, the last element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .max_by(|_key, x, y| y.cmp(x)); + /// + /// assert_eq!(lookup[&0], 3); + /// assert_eq!(lookup[&1], 1); + /// assert_eq!(lookup[&2], 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn max_by(self, mut compare: F) -> HashMap + where F: FnMut(&K, &V, &V) -> Ordering, + { + self.fold_first(|acc, key, val| match compare(key, &acc, &val) { + Ordering::Less | Ordering::Equal => val, + Ordering::Greater => acc + }) + } + + /// Groups elements from the `GroupingMap` source by key and finds the element of each group + /// that gives the maximum from the specified function. + /// + /// If several elements are equally maximum, the last element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .max_by_key(|_key, &val| val % 4); + /// + /// assert_eq!(lookup[&0], 3); + /// assert_eq!(lookup[&1], 7); + /// assert_eq!(lookup[&2], 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn max_by_key(self, mut f: F) -> HashMap + where F: FnMut(&K, &V) -> CK, + CK: Ord, + { + self.max_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) + } + + /// Groups elements from the `GroupingMap` source by key and finds the minimum of each group. + /// + /// If several elements are equally minimum, the first element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .min(); + /// + /// assert_eq!(lookup[&0], 3); + /// assert_eq!(lookup[&1], 1); + /// assert_eq!(lookup[&2], 5); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn min(self) -> HashMap + where V: Ord, + { + self.min_by(|_, v1, v2| V::cmp(v1, v2)) + } + + /// Groups elements from the `GroupingMap` source by key and finds the minimum of each group + /// with respect to the specified comparison function. + /// + /// If several elements are equally minimum, the first element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .min_by(|_key, x, y| y.cmp(x)); + /// + /// assert_eq!(lookup[&0], 12); + /// assert_eq!(lookup[&1], 7); + /// assert_eq!(lookup[&2], 8); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn min_by(self, mut compare: F) -> HashMap + where F: FnMut(&K, &V, &V) -> Ordering, + { + self.fold_first(|acc, key, val| match compare(key, &acc, &val) { + Ordering::Less | Ordering::Equal => acc, + Ordering::Greater => val + }) + } + + /// Groups elements from the `GroupingMap` source by key and finds the element of each group + /// that gives the minimum from the specified function. + /// + /// If several elements are equally minimum, the first element is picked. + /// + /// Returns a `HashMap` associating the key of each group with the minimum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .min_by_key(|_key, &val| val % 4); + /// + /// assert_eq!(lookup[&0], 12); + /// assert_eq!(lookup[&1], 4); + /// assert_eq!(lookup[&2], 8); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn min_by_key(self, mut f: F) -> HashMap + where F: FnMut(&K, &V) -> CK, + CK: Ord, + { + self.min_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) + } + + /// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of + /// each group. + /// + /// If several elements are equally maximum, the last element is picked. + /// If several elements are equally minimum, the first element is picked. + /// + /// See [.minmax()](crate::Itertools::minmax) for the non-grouping version. + /// + /// Differences from the non grouping version: + /// - It never produces a `MinMaxResult::NoElements` + /// - It doesn't have any speedup + /// + /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{OneElement, MinMax}; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .minmax(); + /// + /// assert_eq!(lookup[&0], MinMax(3, 12)); + /// assert_eq!(lookup[&1], MinMax(1, 7)); + /// assert_eq!(lookup[&2], OneElement(5)); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn minmax(self) -> HashMap> + where V: Ord, + { + self.minmax_by(|_, v1, v2| V::cmp(v1, v2)) + } + + /// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of + /// each group with respect to the specified comparison function. + /// + /// If several elements are equally maximum, the last element is picked. + /// If several elements are equally minimum, the first element is picked. + /// + /// It has the same differences from the non-grouping version as `minmax`. + /// + /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{OneElement, MinMax}; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .minmax_by(|_key, x, y| y.cmp(x)); + /// + /// assert_eq!(lookup[&0], MinMax(12, 3)); + /// assert_eq!(lookup[&1], MinMax(7, 1)); + /// assert_eq!(lookup[&2], OneElement(5)); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn minmax_by(self, mut compare: F) -> HashMap> + where F: FnMut(&K, &V, &V) -> Ordering, + { + self.aggregate(|acc, key, val| { + Some(match acc { + Some(MinMaxResult::OneElement(e)) => { + if compare(key, &val, &e) == Ordering::Less { + MinMaxResult::MinMax(val, e) + } else { + MinMaxResult::MinMax(e, val) + } + } + Some(MinMaxResult::MinMax(min, max)) => { + if compare(key, &val, &min) == Ordering::Less { + MinMaxResult::MinMax(val, max) + } else if compare(key, &val, &max) != Ordering::Less { + MinMaxResult::MinMax(min, val) + } else { + MinMaxResult::MinMax(min, max) + } + } + None => MinMaxResult::OneElement(val), + Some(MinMaxResult::NoElements) => unreachable!(), + }) + }) + } + + /// Groups elements from the `GroupingMap` source by key and find the elements of each group + /// that gives the minimum and maximum from the specified function. + /// + /// If several elements are equally maximum, the last element is picked. + /// If several elements are equally minimum, the first element is picked. + /// + /// It has the same differences from the non-grouping version as `minmax`. + /// + /// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{OneElement, MinMax}; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .minmax_by_key(|_key, &val| val % 4); + /// + /// assert_eq!(lookup[&0], MinMax(12, 3)); + /// assert_eq!(lookup[&1], MinMax(4, 7)); + /// assert_eq!(lookup[&2], OneElement(5)); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn minmax_by_key(self, mut f: F) -> HashMap> + where F: FnMut(&K, &V) -> CK, + CK: Ord, + { + self.minmax_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2))) + } + + /// Groups elements from the `GroupingMap` source by key and sums them. + /// + /// This is just a shorthand for `self.fold_first(|acc, _, val| acc + val)`. + /// It is more limited than `Iterator::sum` since it doesn't use the `Sum` trait. + /// + /// Returns a `HashMap` associating the key of each group with the sum of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .sum(); + /// + /// assert_eq!(lookup[&0], 3 + 9 + 12); + /// assert_eq!(lookup[&1], 1 + 4 + 7); + /// assert_eq!(lookup[&2], 5 + 8); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn sum(self) -> HashMap + where V: Add + { + self.fold_first(|acc, _, val| acc + val) + } + + /// Groups elements from the `GroupingMap` source by key and multiply them. + /// + /// This is just a shorthand for `self.fold_first(|acc, _, val| acc * val)`. + /// It is more limited than `Iterator::product` since it doesn't use the `Product` trait. + /// + /// Returns a `HashMap` associating the key of each group with the product of that group's elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter() + /// .into_grouping_map_by(|&n| n % 3) + /// .product(); + /// + /// assert_eq!(lookup[&0], 3 * 9 * 12); + /// assert_eq!(lookup[&1], 1 * 4 * 7); + /// assert_eq!(lookup[&2], 5 * 8); + /// assert_eq!(lookup.len(), 3); + /// ``` + pub fn product(self) -> HashMap + where V: Mul, + { + self.fold_first(|acc, _, val| acc * val) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/impl_macros.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/impl_macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/impl_macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/impl_macros.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,29 @@ +//! +//! Implementation's internal macros + +macro_rules! debug_fmt_fields { + ($tyname:ident, $($($field:tt/*TODO ideally we would accept ident or tuple element here*/).+),*) => { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(stringify!($tyname)) + $( + .field(stringify!($($field).+), &self.$($field).+) + )* + .finish() + } + } +} + +macro_rules! clone_fields { + ($($field:ident),*) => { + #[inline] // TODO is this sensible? + fn clone(&self) -> Self { + Self { + $($field: self.$field.clone(),)* + } + } + } +} + +macro_rules! ignore_ident{ + ($id:ident, $($t:tt)*) => {$($t)*}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/intersperse.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/intersperse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/intersperse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/intersperse.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,118 @@ +use std::iter::{Fuse, FusedIterator}; +use super::size_hint; + +pub trait IntersperseElement { + fn generate(&mut self) -> Item; +} + +#[derive(Debug, Clone)] +pub struct IntersperseElementSimple(Item); + +impl IntersperseElement for IntersperseElementSimple { + fn generate(&mut self) -> Item { + self.0.clone() + } +} + +/// An iterator adaptor to insert a particular value +/// between each element of the adapted iterator. +/// +/// Iterator element type is `I::Item` +/// +/// This iterator is *fused*. +/// +/// See [`.intersperse()`](crate::Itertools::intersperse) for more information. +pub type Intersperse = IntersperseWith::Item>>; + +/// Create a new Intersperse iterator +pub fn intersperse(iter: I, elt: I::Item) -> Intersperse + where I: Iterator, +{ + intersperse_with(iter, IntersperseElementSimple(elt)) +} + +implItem> IntersperseElement for F { + fn generate(&mut self) -> Item { + self() + } +} + +/// An iterator adaptor to insert a particular value created by a function +/// between each element of the adapted iterator. +/// +/// Iterator element type is `I::Item` +/// +/// This iterator is *fused*. +/// +/// See [`.intersperse_with()`](crate::Itertools::intersperse_with) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct IntersperseWith + where I: Iterator, +{ + element: ElemF, + iter: Fuse, + peek: Option, +} + +/// Create a new `IntersperseWith` iterator +pub fn intersperse_with(iter: I, elt: ElemF) -> IntersperseWith + where I: Iterator, +{ + let mut iter = iter.fuse(); + IntersperseWith { + peek: iter.next(), + iter, + element: elt, + } +} + +impl Iterator for IntersperseWith + where I: Iterator, + ElemF: IntersperseElement +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + if self.peek.is_some() { + self.peek.take() + } else { + self.peek = self.iter.next(); + if self.peek.is_some() { + Some(self.element.generate()) + } else { + None + } + } + } + + fn size_hint(&self) -> (usize, Option) { + // 2 * SH + { 1 or 0 } + let has_peek = self.peek.is_some() as usize; + let sh = self.iter.size_hint(); + size_hint::add_scalar(size_hint::add(sh, sh), has_peek) + } + + fn fold(mut self, init: B, mut f: F) -> B where + Self: Sized, F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + + if let Some(x) = self.peek.take() { + accum = f(accum, x); + } + + let element = &mut self.element; + + self.iter.fold(accum, + |accum, x| { + let accum = f(accum, element.generate()); + f(accum, x) + }) + } +} + +impl FusedIterator for IntersperseWith + where I: Iterator, + ElemF: IntersperseElement +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/k_smallest.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/k_smallest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/k_smallest.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/k_smallest.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,20 @@ +use alloc::collections::BinaryHeap; +use core::cmp::Ord; + +pub(crate) fn k_smallest>(mut iter: I, k: usize) -> BinaryHeap { + if k == 0 { return BinaryHeap::new(); } + + let mut heap = iter.by_ref().take(k).collect::>(); + + iter.for_each(|i| { + debug_assert_eq!(heap.len(), k); + // Equivalent to heap.push(min(i, heap.pop())) but more efficient. + // This should be done with a single `.peek_mut().unwrap()` but + // `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior. + if *heap.peek().unwrap() > i { + *heap.peek_mut().unwrap() = i; + } + }); + + heap +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/kmerge_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/kmerge_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/kmerge_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/kmerge_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,227 @@ +use crate::size_hint; +use crate::Itertools; + +use alloc::vec::Vec; +use std::iter::FusedIterator; +use std::mem::replace; +use std::fmt; + +/// Head element and Tail iterator pair +/// +/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on +/// first items (which are guaranteed to exist). +/// +/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in +/// `KMerge` into a min-heap. +#[derive(Debug)] +struct HeadTail + where I: Iterator +{ + head: I::Item, + tail: I, +} + +impl HeadTail + where I: Iterator +{ + /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty. + fn new(mut it: I) -> Option> { + let head = it.next(); + head.map(|h| { + HeadTail { + head: h, + tail: it, + } + }) + } + + /// Get the next element and update `head`, returning the old head in `Some`. + /// + /// Returns `None` when the tail is exhausted (only `head` then remains). + fn next(&mut self) -> Option { + if let Some(next) = self.tail.next() { + Some(replace(&mut self.head, next)) + } else { + None + } + } + + /// Hints at the size of the sequence, same as the `Iterator` method. + fn size_hint(&self) -> (usize, Option) { + size_hint::add_scalar(self.tail.size_hint(), 1) + } +} + +impl Clone for HeadTail + where I: Iterator + Clone, + I::Item: Clone +{ + clone_fields!(head, tail); +} + +/// Make `data` a heap (min-heap w.r.t the sorting). +fn heapify(data: &mut [T], mut less_than: S) + where S: FnMut(&T, &T) -> bool +{ + for i in (0..data.len() / 2).rev() { + sift_down(data, i, &mut less_than); + } +} + +/// Sift down element at `index` (`heap` is a min-heap wrt the ordering) +fn sift_down(heap: &mut [T], index: usize, mut less_than: S) + where S: FnMut(&T, &T) -> bool +{ + debug_assert!(index <= heap.len()); + let mut pos = index; + let mut child = 2 * pos + 1; + // Require the right child to be present + // This allows to find the index of the smallest child without a branch + // that wouldn't be predicted if present + while child + 1 < heap.len() { + // pick the smaller of the two children + // use arithmetic to avoid an unpredictable branch + child += less_than(&heap[child+1], &heap[child]) as usize; + + // sift down is done if we are already in order + if !less_than(&heap[child], &heap[pos]) { + return; + } + heap.swap(pos, child); + pos = child; + child = 2 * pos + 1; + } + // Check if the last (left) child was an only child + // if it is then it has to be compared with the parent + if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) { + heap.swap(pos, child); + } +} + +/// An iterator adaptor that merges an abitrary number of base iterators in ascending order. +/// If all base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.kmerge()`](crate::Itertools::kmerge) for more information. +pub type KMerge = KMergeBy; + +pub trait KMergePredicate { + fn kmerge_pred(&mut self, a: &T, b: &T) -> bool; +} + +#[derive(Clone, Debug)] +pub struct KMergeByLt; + +impl KMergePredicate for KMergeByLt { + fn kmerge_pred(&mut self, a: &T, b: &T) -> bool { + a < b + } +} + +implbool> KMergePredicate for F { + fn kmerge_pred(&mut self, a: &T, b: &T) -> bool { + self(a, b) + } +} + +/// Create an iterator that merges elements of the contained iterators using +/// the ordering function. +/// +/// [`IntoIterator`] enabled version of [`Itertools::kmerge`]. +/// +/// ``` +/// use itertools::kmerge; +/// +/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) { +/// /* loop body */ +/// } +/// ``` +pub fn kmerge(iterable: I) -> KMerge<::IntoIter> + where I: IntoIterator, + I::Item: IntoIterator, + <::Item as IntoIterator>::Item: PartialOrd +{ + kmerge_by(iterable, KMergeByLt) +} + +/// An iterator adaptor that merges an abitrary number of base iterators +/// according to an ordering function. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.kmerge_by()`](crate::Itertools::kmerge_by) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct KMergeBy + where I: Iterator, +{ + heap: Vec>, + less_than: F, +} + +impl fmt::Debug for KMergeBy + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(KMergeBy, heap); +} + +/// Create an iterator that merges elements of the contained iterators. +/// +/// [`IntoIterator`] enabled version of [`Itertools::kmerge_by`]. +pub fn kmerge_by(iterable: I, mut less_than: F) + -> KMergeBy<::IntoIter, F> + where I: IntoIterator, + I::Item: IntoIterator, + F: KMergePredicate<<::Item as IntoIterator>::Item>, +{ + let iter = iterable.into_iter(); + let (lower, _) = iter.size_hint(); + let mut heap: Vec<_> = Vec::with_capacity(lower); + heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); + heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head)); + KMergeBy { heap, less_than } +} + +impl Clone for KMergeBy + where I: Iterator + Clone, + I::Item: Clone, + F: Clone, +{ + clone_fields!(heap, less_than); +} + +impl Iterator for KMergeBy + where I: Iterator, + F: KMergePredicate +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + if self.heap.is_empty() { + return None; + } + let result = if let Some(next) = self.heap[0].next() { + next + } else { + self.heap.swap_remove(0).head + }; + let less_than = &mut self.less_than; + sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head)); + Some(result) + } + + fn size_hint(&self) -> (usize, Option) { + #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce` + self.heap.iter() + .map(|i| i.size_hint()) + .fold1(size_hint::add) + .unwrap_or((0, Some(0))) + } +} + +impl FusedIterator for KMergeBy + where I: Iterator, + F: KMergePredicate +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/lazy_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lazy_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/lazy_buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lazy_buffer.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,63 @@ +use std::ops::Index; +use alloc::vec::Vec; + +#[derive(Debug, Clone)] +pub struct LazyBuffer { + pub it: I, + done: bool, + buffer: Vec, +} + +impl LazyBuffer +where + I: Iterator, +{ + pub fn new(it: I) -> LazyBuffer { + LazyBuffer { + it, + done: false, + buffer: Vec::new(), + } + } + + pub fn len(&self) -> usize { + self.buffer.len() + } + + pub fn get_next(&mut self) -> bool { + if self.done { + return false; + } + if let Some(x) = self.it.next() { + self.buffer.push(x); + true + } else { + self.done = true; + false + } + } + + pub fn prefill(&mut self, len: usize) { + let buffer_len = self.buffer.len(); + + if !self.done && len > buffer_len { + let delta = len - buffer_len; + + self.buffer.extend(self.it.by_ref().take(delta)); + self.done = self.buffer.len() < len; + } + } +} + +impl Index for LazyBuffer +where + I: Iterator, + I::Item: Sized, + Vec: Index +{ + type Output = as Index>::Output; + + fn index(&self, index: J) -> &Self::Output { + self.buffer.index(index) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/lib.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,3784 @@ +#![warn(missing_docs)] +#![crate_name="itertools"] +#![cfg_attr(not(feature = "use_std"), no_std)] + +//! Extra iterator adaptors, functions and macros. +//! +//! To extend [`Iterator`] with methods in this crate, import +//! the [`Itertools`] trait: +//! +//! ``` +//! use itertools::Itertools; +//! ``` +//! +//! Now, new methods like [`interleave`](Itertools::interleave) +//! are available on all iterators: +//! +//! ``` +//! use itertools::Itertools; +//! +//! let it = (1..3).interleave(vec![-1, -2]); +//! itertools::assert_equal(it, vec![1, -1, 2, -2]); +//! ``` +//! +//! Most iterator methods are also provided as functions (with the benefit +//! that they convert parameters using [`IntoIterator`]): +//! +//! ``` +//! use itertools::interleave; +//! +//! for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { +//! /* loop body */ +//! } +//! ``` +//! +//! ## Crate Features +//! +//! - `use_std` +//! - Enabled by default. +//! - Disable to compile itertools using `#![no_std]`. This disables +//! any items that depend on collections (like `group_by`, `unique`, +//! `kmerge`, `join` and many more). +//! +//! ## Rust Version +//! +//! This version of itertools requires Rust 1.32 or later. +#![doc(html_root_url="https://docs.rs/itertools/0.8/")] + +#[cfg(not(feature = "use_std"))] +extern crate core as std; + +#[cfg(feature = "use_alloc")] +extern crate alloc; + +#[cfg(feature = "use_alloc")] +use alloc::{ + string::String, + vec::Vec, +}; + +pub use either::Either; + +use core::borrow::Borrow; +#[cfg(feature = "use_std")] +use std::collections::HashMap; +use std::iter::{IntoIterator, once}; +use std::cmp::Ordering; +use std::fmt; +#[cfg(feature = "use_std")] +use std::collections::HashSet; +#[cfg(feature = "use_std")] +use std::hash::Hash; +#[cfg(feature = "use_alloc")] +use std::fmt::Write; +#[cfg(feature = "use_alloc")] +type VecIntoIter = alloc::vec::IntoIter; +#[cfg(feature = "use_alloc")] +use std::iter::FromIterator; + +#[macro_use] +mod impl_macros; + +// for compatibility with no std and macros +#[doc(hidden)] +pub use std::iter as __std_iter; + +/// The concrete iterator types. +pub mod structs { + pub use crate::adaptors::{ + Dedup, + DedupBy, + DedupWithCount, + DedupByWithCount, + Interleave, + InterleaveShortest, + FilterMapOk, + FilterOk, + Product, + PutBack, + Batching, + MapInto, + MapOk, + Merge, + MergeBy, + TakeWhileRef, + WhileSome, + Coalesce, + TupleCombinations, + Positions, + Update, + }; + #[allow(deprecated)] + pub use crate::adaptors::{MapResults, Step}; + #[cfg(feature = "use_alloc")] + pub use crate::adaptors::MultiProduct; + #[cfg(feature = "use_alloc")] + pub use crate::combinations::Combinations; + #[cfg(feature = "use_alloc")] + pub use crate::combinations_with_replacement::CombinationsWithReplacement; + pub use crate::cons_tuples_impl::ConsTuples; + pub use crate::exactly_one_err::ExactlyOneError; + pub use crate::format::{Format, FormatWith}; + pub use crate::flatten_ok::FlattenOk; + #[cfg(feature = "use_std")] + pub use crate::grouping_map::{GroupingMap, GroupingMapBy}; + #[cfg(feature = "use_alloc")] + pub use crate::groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; + pub use crate::intersperse::{Intersperse, IntersperseWith}; + #[cfg(feature = "use_alloc")] + pub use crate::kmerge_impl::{KMerge, KMergeBy}; + pub use crate::merge_join::MergeJoinBy; + #[cfg(feature = "use_alloc")] + pub use crate::multipeek_impl::MultiPeek; + #[cfg(feature = "use_alloc")] + pub use crate::peek_nth::PeekNth; + pub use crate::pad_tail::PadUsing; + pub use crate::peeking_take_while::PeekingTakeWhile; + #[cfg(feature = "use_alloc")] + pub use crate::permutations::Permutations; + pub use crate::process_results_impl::ProcessResults; + #[cfg(feature = "use_alloc")] + pub use crate::powerset::Powerset; + #[cfg(feature = "use_alloc")] + pub use crate::put_back_n_impl::PutBackN; + #[cfg(feature = "use_alloc")] + pub use crate::rciter_impl::RcIter; + pub use crate::repeatn::RepeatN; + #[allow(deprecated)] + pub use crate::sources::{RepeatCall, Unfold, Iterate}; + #[cfg(feature = "use_alloc")] + pub use crate::tee::Tee; + pub use crate::tuple_impl::{TupleBuffer, TupleWindows, CircularTupleWindows, Tuples}; + #[cfg(feature = "use_std")] + pub use crate::duplicates_impl::{Duplicates, DuplicatesBy}; + #[cfg(feature = "use_std")] + pub use crate::unique_impl::{Unique, UniqueBy}; + pub use crate::with_position::WithPosition; + pub use crate::zip_eq_impl::ZipEq; + pub use crate::zip_longest::ZipLongest; + pub use crate::ziptuple::Zip; +} + +/// Traits helpful for using certain `Itertools` methods in generic contexts. +pub mod traits { + pub use crate::tuple_impl::HomogeneousTuple; +} + +#[allow(deprecated)] +pub use crate::structs::*; +pub use crate::concat_impl::concat; +pub use crate::cons_tuples_impl::cons_tuples; +pub use crate::diff::diff_with; +pub use crate::diff::Diff; +#[cfg(feature = "use_alloc")] +pub use crate::kmerge_impl::{kmerge_by}; +pub use crate::minmax::MinMaxResult; +pub use crate::peeking_take_while::PeekingNext; +pub use crate::process_results_impl::process_results; +pub use crate::repeatn::repeat_n; +#[allow(deprecated)] +pub use crate::sources::{repeat_call, unfold, iterate}; +pub use crate::with_position::Position; +pub use crate::unziptuple::{multiunzip, MultiUnzip}; +pub use crate::ziptuple::multizip; +mod adaptors; +mod either_or_both; +pub use crate::either_or_both::EitherOrBoth; +#[doc(hidden)] +pub mod free; +#[doc(inline)] +pub use crate::free::*; +mod concat_impl; +mod cons_tuples_impl; +#[cfg(feature = "use_alloc")] +mod combinations; +#[cfg(feature = "use_alloc")] +mod combinations_with_replacement; +mod exactly_one_err; +mod diff; +mod flatten_ok; +#[cfg(feature = "use_std")] +mod extrema_set; +mod format; +#[cfg(feature = "use_std")] +mod grouping_map; +#[cfg(feature = "use_alloc")] +mod group_map; +#[cfg(feature = "use_alloc")] +mod groupbylazy; +mod intersperse; +#[cfg(feature = "use_alloc")] +mod k_smallest; +#[cfg(feature = "use_alloc")] +mod kmerge_impl; +#[cfg(feature = "use_alloc")] +mod lazy_buffer; +mod merge_join; +mod minmax; +#[cfg(feature = "use_alloc")] +mod multipeek_impl; +mod pad_tail; +#[cfg(feature = "use_alloc")] +mod peek_nth; +mod peeking_take_while; +#[cfg(feature = "use_alloc")] +mod permutations; +#[cfg(feature = "use_alloc")] +mod powerset; +mod process_results_impl; +#[cfg(feature = "use_alloc")] +mod put_back_n_impl; +#[cfg(feature = "use_alloc")] +mod rciter_impl; +mod repeatn; +mod size_hint; +mod sources; +#[cfg(feature = "use_alloc")] +mod tee; +mod tuple_impl; +#[cfg(feature = "use_std")] +mod duplicates_impl; +#[cfg(feature = "use_std")] +mod unique_impl; +mod unziptuple; +mod with_position; +mod zip_eq_impl; +mod zip_longest; +mod ziptuple; + +#[macro_export] +/// Create an iterator over the “cartesian product” of iterators. +/// +/// Iterator element type is like `(A, B, ..., E)` if formed +/// from iterators `(I, J, ..., M)` with element types `I::Item = A`, `J::Item = B`, etc. +/// +/// ``` +/// # use itertools::iproduct; +/// # +/// # fn main() { +/// // Iterate over the coordinates of a 4 x 4 x 4 grid +/// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) +/// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { +/// // .. +/// } +/// # } +/// ``` +macro_rules! iproduct { + (@flatten $I:expr,) => ( + $I + ); + (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( + $crate::iproduct!(@flatten $crate::cons_tuples($crate::iproduct!($I, $J)), $($K,)*) + ); + ($I:expr) => ( + $crate::__std_iter::IntoIterator::into_iter($I) + ); + ($I:expr, $J:expr) => ( + $crate::Itertools::cartesian_product($crate::iproduct!($I), $crate::iproduct!($J)) + ); + ($I:expr, $J:expr, $($K:expr),+) => ( + $crate::iproduct!(@flatten $crate::iproduct!($I, $J), $($K,)+) + ); +} + +#[macro_export] +/// Create an iterator running multiple iterators in lockstep. +/// +/// The `izip!` iterator yields elements until any subiterator +/// returns `None`. +/// +/// This is a version of the standard ``.zip()`` that's supporting more than +/// two iterators. The iterator element type is a tuple with one element +/// from each of the input iterators. Just like ``.zip()``, the iteration stops +/// when the shortest of the inputs reaches its end. +/// +/// **Note:** The result of this macro is in the general case an iterator +/// composed of repeated `.zip()` and a `.map()`; it has an anonymous type. +/// The special cases of one and two arguments produce the equivalent of +/// `$a.into_iter()` and `$a.into_iter().zip($b)` respectively. +/// +/// Prefer this macro `izip!()` over [`multizip`] for the performance benefits +/// of using the standard library `.zip()`. +/// +/// ``` +/// # use itertools::izip; +/// # +/// # fn main() { +/// +/// // iterate over three sequences side-by-side +/// let mut results = [0, 0, 0, 0]; +/// let inputs = [3, 7, 9, 6]; +/// +/// for (r, index, input) in izip!(&mut results, 0..10, &inputs) { +/// *r = index * 10 + input; +/// } +/// +/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); +/// # } +/// ``` +macro_rules! izip { + // @closure creates a tuple-flattening closure for .map() call. usage: + // @closure partial_pattern => partial_tuple , rest , of , iterators + // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee ) + ( @closure $p:pat => $tup:expr ) => { + |$p| $tup + }; + + // The "b" identifier is a different identifier on each recursion level thanks to hygiene. + ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => { + $crate::izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*) + }; + + // unary + ($first:expr $(,)*) => { + $crate::__std_iter::IntoIterator::into_iter($first) + }; + + // binary + ($first:expr, $second:expr $(,)*) => { + $crate::izip!($first) + .zip($second) + }; + + // n-ary where n > 2 + ( $first:expr $( , $rest:expr )* $(,)* ) => { + $crate::izip!($first) + $( + .zip($rest) + )* + .map( + $crate::izip!(@closure a => (a) $( , $rest )*) + ) + }; +} + +#[macro_export] +/// [Chain][`chain`] zero or more iterators together into one sequence. +/// +/// The comma-separated arguments must implement [`IntoIterator`]. +/// The final argument may be followed by a trailing comma. +/// +/// [`chain`]: Iterator::chain +/// +/// # Examples +/// +/// Empty invocations of `chain!` expand to an invocation of [`std::iter::empty`]: +/// ``` +/// use std::iter; +/// use itertools::chain; +/// +/// let _: iter::Empty<()> = chain!(); +/// let _: iter::Empty = chain!(); +/// ``` +/// +/// Invocations of `chain!` with one argument expand to [`arg.into_iter()`](IntoIterator): +/// ``` +/// use std::{ops::Range, slice}; +/// use itertools::chain; +/// let _: as IntoIterator>::IntoIter = chain!((2..6),); // trailing comma optional! +/// let _: <&[_] as IntoIterator>::IntoIter = chain!(&[2, 3, 4]); +/// ``` +/// +/// Invocations of `chain!` with multiple arguments [`.into_iter()`](IntoIterator) each +/// argument, and then [`chain`] them together: +/// ``` +/// use std::{iter::*, ops::Range, slice}; +/// use itertools::{assert_equal, chain}; +/// +/// // e.g., this: +/// let with_macro: Chain, Take>>, slice::Iter<_>> = +/// chain![once(&0), repeat(&1).take(2), &[2, 3, 5],]; +/// +/// // ...is equivalent to this: +/// let with_method: Chain, Take>>, slice::Iter<_>> = +/// once(&0) +/// .chain(repeat(&1).take(2)) +/// .chain(&[2, 3, 5]); +/// +/// assert_equal(with_macro, with_method); +/// ``` +macro_rules! chain { + () => { + core::iter::empty() + }; + ($first:expr $(, $rest:expr )* $(,)?) => { + { + let iter = core::iter::IntoIterator::into_iter($first); + $( + let iter = + core::iter::Iterator::chain( + iter, + core::iter::IntoIterator::into_iter($rest)); + )* + iter + } + }; +} + +/// An [`Iterator`] blanket implementation that provides extra adaptors and +/// methods. +/// +/// This trait defines a number of methods. They are divided into two groups: +/// +/// * *Adaptors* take an iterator and parameter as input, and return +/// a new iterator value. These are listed first in the trait. An example +/// of an adaptor is [`.interleave()`](Itertools::interleave) +/// +/// * *Regular methods* are those that don't return iterators and instead +/// return a regular value of some other kind. +/// [`.next_tuple()`](Itertools::next_tuple) is an example and the first regular +/// method in the list. +pub trait Itertools : Iterator { + // adaptors + + /// Alternate elements from two iterators until both have run out. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..7).interleave(vec![-1, -2]); + /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); + /// ``` + fn interleave(self, other: J) -> Interleave + where J: IntoIterator, + Self: Sized + { + interleave(self, other) + } + + /// Alternate elements from two iterators until at least one of them has run + /// out. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..7).interleave_shortest(vec![-1, -2]); + /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); + /// ``` + fn interleave_shortest(self, other: J) -> InterleaveShortest + where J: IntoIterator, + Self: Sized + { + adaptors::interleave_shortest(self, other.into_iter()) + } + + /// An iterator adaptor to insert a particular value + /// between each element of the adapted iterator. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); + /// ``` + fn intersperse(self, element: Self::Item) -> Intersperse + where Self: Sized, + Self::Item: Clone + { + intersperse::intersperse(self, element) + } + + /// An iterator adaptor to insert a particular value created by a function + /// between each element of the adapted iterator. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut i = 10; + /// itertools::assert_equal((0..3).intersperse_with(|| { i -= 1; i }), vec![0, 9, 1, 8, 2]); + /// assert_eq!(i, 8); + /// ``` + fn intersperse_with(self, element: F) -> IntersperseWith + where Self: Sized, + F: FnMut() -> Self::Item + { + intersperse::intersperse_with(self, element) + } + + /// Create an iterator which iterates over both this and the specified + /// iterator simultaneously, yielding pairs of two optional elements. + /// + /// This iterator is *fused*. + /// + /// As long as neither input iterator is exhausted yet, it yields two values + /// via `EitherOrBoth::Both`. + /// + /// When the parameter iterator is exhausted, it only yields a value from the + /// `self` iterator via `EitherOrBoth::Left`. + /// + /// When the `self` iterator is exhausted, it only yields a value from the + /// parameter iterator via `EitherOrBoth::Right`. + /// + /// When both iterators return `None`, all further invocations of `.next()` + /// will return `None`. + /// + /// Iterator element type is + /// [`EitherOrBoth`](EitherOrBoth). + /// + /// ```rust + /// use itertools::EitherOrBoth::{Both, Right}; + /// use itertools::Itertools; + /// let it = (0..1).zip_longest(1..3); + /// itertools::assert_equal(it, vec![Both(0, 1), Right(2)]); + /// ``` + #[inline] + fn zip_longest(self, other: J) -> ZipLongest + where J: IntoIterator, + Self: Sized + { + zip_longest::zip_longest(self, other.into_iter()) + } + + /// Create an iterator which iterates over both this and the specified + /// iterator simultaneously, yielding pairs of elements. + /// + /// **Panics** if the iterators reach an end and they are not of equal + /// lengths. + #[inline] + fn zip_eq(self, other: J) -> ZipEq + where J: IntoIterator, + Self: Sized + { + zip_eq(self, other) + } + + /// A “meta iterator adaptor”. Its closure receives a reference to the + /// iterator and may pick off as many elements as it likes, to produce the + /// next iterator element. + /// + /// Iterator element type is `B`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // An adaptor that gathers elements in pairs + /// let pit = (0..4).batching(|it| { + /// match it.next() { + /// None => None, + /// Some(x) => match it.next() { + /// None => None, + /// Some(y) => Some((x, y)), + /// } + /// } + /// }); + /// + /// itertools::assert_equal(pit, vec![(0, 1), (2, 3)]); + /// ``` + /// + fn batching(self, f: F) -> Batching + where F: FnMut(&mut Self) -> Option, + Self: Sized + { + adaptors::batching(self, f) + } + + /// Return an *iterable* that can group iterator elements. + /// Consecutive elements that map to the same key (“runs”), are assigned + /// to the same group. + /// + /// `GroupBy` is the storage for the lazy grouping operation. + /// + /// If the groups are consumed in order, or if each group's iterator is + /// dropped without keeping it around, then `GroupBy` uses no + /// allocations. It needs allocations only if several group iterators + /// are alive at the same time. + /// + /// This type implements [`IntoIterator`] (it is **not** an iterator + /// itself), because the group iterators need to borrow from this + /// value. It should be stored in a local variable or temporary and + /// iterated. + /// + /// Iterator element type is `(K, Group)`: the group's key and the + /// group iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // group data into runs of larger than zero or not. + /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; + /// // groups: |---->|------>|--------->| + /// + /// // Note: The `&` is significant here, `GroupBy` is iterable + /// // only by reference. You can also call `.into_iter()` explicitly. + /// let mut data_grouped = Vec::new(); + /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { + /// data_grouped.push((key, group.collect())); + /// } + /// assert_eq!(data_grouped, vec![(true, vec![1, 3]), (false, vec![-2, -2]), (true, vec![1, 0, 1, 2])]); + /// ``` + #[cfg(feature = "use_alloc")] + fn group_by(self, key: F) -> GroupBy + where Self: Sized, + F: FnMut(&Self::Item) -> K, + K: PartialEq, + { + groupbylazy::new(self, key) + } + + /// Return an *iterable* that can chunk the iterator. + /// + /// Yield subiterators (chunks) that each yield a fixed number elements, + /// determined by `size`. The last chunk will be shorter if there aren't + /// enough elements. + /// + /// `IntoChunks` is based on `GroupBy`: it is iterable (implements + /// `IntoIterator`, **not** `Iterator`), and it only buffers if several + /// chunk iterators are alive at the same time. + /// + /// Iterator element type is `Chunk`, each chunk's iterator. + /// + /// **Panics** if `size` is 0. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 2, -2, 6, 0, 3, 1]; + /// //chunk size=3 |------->|-------->|--->| + /// + /// // Note: The `&` is significant here, `IntoChunks` is iterable + /// // only by reference. You can also call `.into_iter()` explicitly. + /// for chunk in &data.into_iter().chunks(3) { + /// // Check that the sum of each chunk is 4. + /// assert_eq!(4, chunk.sum()); + /// } + /// ``` + #[cfg(feature = "use_alloc")] + fn chunks(self, size: usize) -> IntoChunks + where Self: Sized, + { + assert!(size != 0); + groupbylazy::new_chunks(self, size) + } + + /// Return an iterator over all contiguous windows producing tuples of + /// a specific size (up to 12). + /// + /// `tuple_windows` clones the iterator elements so that they can be + /// part of successive windows, this makes it most suited for iterators + /// of references and other values that are cheap to copy. + /// + /// ``` + /// use itertools::Itertools; + /// let mut v = Vec::new(); + /// + /// // pairwise iteration + /// for (a, b) in (1..5).tuple_windows() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]); + /// + /// let mut it = (1..5).tuple_windows(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((2, 3, 4)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).tuple_windows::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); + /// + /// // you can also specify the complete type + /// use itertools::TupleWindows; + /// use std::ops::Range; + /// + /// let it: TupleWindows, (u32, u32, u32)> = (1..5).tuple_windows(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); + /// ``` + fn tuple_windows(self) -> TupleWindows + where Self: Sized + Iterator, + T: traits::HomogeneousTuple, + T::Item: Clone + { + tuple_impl::tuple_windows(self) + } + + /// Return an iterator over all windows, wrapping back to the first + /// elements when the window would otherwise exceed the length of the + /// iterator, producing tuples of a specific size (up to 12). + /// + /// `circular_tuple_windows` clones the iterator elements so that they can be + /// part of successive windows, this makes it most suited for iterators + /// of references and other values that are cheap to copy. + /// + /// ``` + /// use itertools::Itertools; + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).circular_tuple_windows() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4), (4, 1)]); + /// + /// let mut it = (1..5).circular_tuple_windows(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((2, 3, 4)), it.next()); + /// assert_eq!(Some((3, 4, 1)), it.next()); + /// assert_eq!(Some((4, 1, 2)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).circular_tuple_windows::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4), (3, 4, 1), (4, 1, 2)]); + /// ``` + fn circular_tuple_windows(self) -> CircularTupleWindows + where Self: Sized + Clone + Iterator + ExactSizeIterator, + T: tuple_impl::TupleCollect + Clone, + T::Item: Clone + { + tuple_impl::circular_tuple_windows(self) + } + /// Return an iterator that groups the items in tuples of a specific size + /// (up to 12). + /// + /// See also the method [`.next_tuple()`](Itertools::next_tuple). + /// + /// ``` + /// use itertools::Itertools; + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).tuples() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (3, 4)]); + /// + /// let mut it = (1..7).tuples(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((4, 5, 6)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..7).tuples::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); + /// + /// // you can also specify the complete type + /// use itertools::Tuples; + /// use std::ops::Range; + /// + /// let it: Tuples, (u32, u32, u32)> = (1..7).tuples(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); + /// ``` + /// + /// See also [`Tuples::into_buffer`]. + fn tuples(self) -> Tuples + where Self: Sized + Iterator, + T: traits::HomogeneousTuple + { + tuple_impl::tuples(self) + } + + /// Split into an iterator pair that both yield all elements from + /// the original iterator. + /// + /// **Note:** If the iterator is clonable, prefer using that instead + /// of using this method. Cloning is likely to be more efficient. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// let xs = vec![0, 1, 2, 3]; + /// + /// let (mut t1, t2) = xs.into_iter().tee(); + /// itertools::assert_equal(t1.next(), Some(0)); + /// itertools::assert_equal(t2, 0..4); + /// itertools::assert_equal(t1, 1..4); + /// ``` + #[cfg(feature = "use_alloc")] + fn tee(self) -> (Tee, Tee) + where Self: Sized, + Self::Item: Clone + { + tee::new(self) + } + + /// Return an iterator adaptor that steps `n` elements in the base iterator + /// for each iteration. + /// + /// The iterator steps by yielding the next element from the base iterator, + /// then skipping forward `n - 1` elements. + /// + /// Iterator element type is `Self::Item`. + /// + /// **Panics** if the step is 0. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..8).step(3); + /// itertools::assert_equal(it, vec![0, 3, 6]); + /// ``` + #[deprecated(note="Use std .step_by() instead", since="0.8.0")] + #[allow(deprecated)] + fn step(self, n: usize) -> Step + where Self: Sized + { + adaptors::step(self, n) + } + + /// Convert each item of the iterator using the [`Into`] trait. + /// + /// ```rust + /// use itertools::Itertools; + /// + /// (1i32..42i32).map_into::().collect_vec(); + /// ``` + fn map_into(self) -> MapInto + where Self: Sized, + Self::Item: Into, + { + adaptors::map_into(self) + } + + /// See [`.map_ok()`](Itertools::map_ok). + #[deprecated(note="Use .map_ok() instead", since="0.10.0")] + fn map_results(self, f: F) -> MapOk + where Self: Iterator> + Sized, + F: FnMut(T) -> U, + { + self.map_ok(f) + } + + /// Return an iterator adaptor that applies the provided closure + /// to every `Result::Ok` value. `Result::Err` values are + /// unchanged. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![Ok(41), Err(false), Ok(11)]; + /// let it = input.into_iter().map_ok(|i| i + 1); + /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); + /// ``` + fn map_ok(self, f: F) -> MapOk + where Self: Iterator> + Sized, + F: FnMut(T) -> U, + { + adaptors::map_ok(self, f) + } + + /// Return an iterator adaptor that filters every `Result::Ok` + /// value with the provided closure. `Result::Err` values are + /// unchanged. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![Ok(22), Err(false), Ok(11)]; + /// let it = input.into_iter().filter_ok(|&i| i > 20); + /// itertools::assert_equal(it, vec![Ok(22), Err(false)]); + /// ``` + fn filter_ok(self, f: F) -> FilterOk + where Self: Iterator> + Sized, + F: FnMut(&T) -> bool, + { + adaptors::filter_ok(self, f) + } + + /// Return an iterator adaptor that filters and transforms every + /// `Result::Ok` value with the provided closure. `Result::Err` + /// values are unchanged. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![Ok(22), Err(false), Ok(11)]; + /// let it = input.into_iter().filter_map_ok(|i| if i > 20 { Some(i * 2) } else { None }); + /// itertools::assert_equal(it, vec![Ok(44), Err(false)]); + /// ``` + fn filter_map_ok(self, f: F) -> FilterMapOk + where Self: Iterator> + Sized, + F: FnMut(T) -> Option, + { + adaptors::filter_map_ok(self, f) + } + + /// Return an iterator adaptor that flattens every `Result::Ok` value into + /// a series of `Result::Ok` values. `Result::Err` values are unchanged. + /// + /// This is useful when you have some common error type for your crate and + /// need to propagate it upwards, but the `Result::Ok` case needs to be flattened. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![Ok(0..2), Err(false), Ok(2..4)]; + /// let it = input.iter().cloned().flatten_ok(); + /// itertools::assert_equal(it.clone(), vec![Ok(0), Ok(1), Err(false), Ok(2), Ok(3)]); + /// + /// // This can also be used to propagate errors when collecting. + /// let output_result: Result, bool> = it.collect(); + /// assert_eq!(output_result, Err(false)); + /// ``` + fn flatten_ok(self) -> FlattenOk + where Self: Iterator> + Sized, + T: IntoIterator + { + flatten_ok::flatten_ok(self) + } + + /// Return an iterator adaptor that merges the two base iterators in + /// ascending order. If both base iterators are sorted (ascending), the + /// result is sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..11).step(3); + /// let b = (0..11).step(5); + /// let it = a.merge(b); + /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); + /// ``` + fn merge(self, other: J) -> Merge + where Self: Sized, + Self::Item: PartialOrd, + J: IntoIterator + { + merge(self, other) + } + + /// Return an iterator adaptor that merges the two base iterators in order. + /// This is much like [`.merge()`](Itertools::merge) but allows for a custom ordering. + /// + /// This can be especially useful for sequences of tuples. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..).zip("bc".chars()); + /// let b = (0..).zip("ad".chars()); + /// let it = a.merge_by(b, |x, y| x.1 <= y.1); + /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); + /// ``` + + fn merge_by(self, other: J, is_first: F) -> MergeBy + where Self: Sized, + J: IntoIterator, + F: FnMut(&Self::Item, &Self::Item) -> bool + { + adaptors::merge_by_new(self, other.into_iter(), is_first) + } + + /// Create an iterator that merges items from both this and the specified + /// iterator in ascending order. + /// + /// It chooses whether to pair elements based on the `Ordering` returned by the + /// specified compare function. At any point, inspecting the tip of the + /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type + /// `J::Item` respectively, the resulting iterator will: + /// + /// - Emit `EitherOrBoth::Left(i)` when `i < j`, + /// and remove `i` from its source iterator + /// - Emit `EitherOrBoth::Right(j)` when `i > j`, + /// and remove `j` from its source iterator + /// - Emit `EitherOrBoth::Both(i, j)` when `i == j`, + /// and remove both `i` and `j` from their respective source iterators + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::EitherOrBoth::{Left, Right, Both}; + /// + /// let multiples_of_2 = (0..10).step(2); + /// let multiples_of_3 = (0..10).step(3); + /// + /// itertools::assert_equal( + /// multiples_of_2.merge_join_by(multiples_of_3, |i, j| i.cmp(j)), + /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(8), Right(9)] + /// ); + /// ``` + #[inline] + fn merge_join_by(self, other: J, cmp_fn: F) -> MergeJoinBy + where J: IntoIterator, + F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, + Self: Sized + { + merge_join_by(self, other, cmp_fn) + } + + /// Return an iterator adaptor that flattens an iterator of iterators by + /// merging them in ascending order. + /// + /// If all base iterators are sorted (ascending), the result is sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..6).step(3); + /// let b = (1..6).step(3); + /// let c = (2..6).step(3); + /// let it = vec![a, b, c].into_iter().kmerge(); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); + /// ``` + #[cfg(feature = "use_alloc")] + fn kmerge(self) -> KMerge<::IntoIter> + where Self: Sized, + Self::Item: IntoIterator, + ::Item: PartialOrd, + { + kmerge(self) + } + + /// Return an iterator adaptor that flattens an iterator of iterators by + /// merging them according to the given closure. + /// + /// The closure `first` is called with two elements *a*, *b* and should + /// return `true` if *a* is ordered before *b*. + /// + /// If all base iterators are sorted according to `first`, the result is + /// sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = vec![-1f64, 2., 3., -5., 6., -7.]; + /// let b = vec![0., 2., -4.]; + /// let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs()); + /// assert_eq!(it.next(), Some(0.)); + /// assert_eq!(it.last(), Some(-7.)); + /// ``` + #[cfg(feature = "use_alloc")] + fn kmerge_by(self, first: F) + -> KMergeBy<::IntoIter, F> + where Self: Sized, + Self::Item: IntoIterator, + F: FnMut(&::Item, + &::Item) -> bool + { + kmerge_by(self, first) + } + + /// Return an iterator adaptor that iterates over the cartesian product of + /// the element sets of two iterators `self` and `J`. + /// + /// Iterator element type is `(Self::Item, J::Item)`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..2).cartesian_product("αβ".chars()); + /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); + /// ``` + fn cartesian_product(self, other: J) -> Product + where Self: Sized, + Self::Item: Clone, + J: IntoIterator, + J::IntoIter: Clone + { + adaptors::cartesian_product(self, other.into_iter()) + } + + /// Return an iterator adaptor that iterates over the cartesian product of + /// all subiterators returned by meta-iterator `self`. + /// + /// All provided iterators must yield the same `Item` type. To generate + /// the product of iterators yielding multiple types, use the + /// [`iproduct`] macro instead. + /// + /// + /// The iterator element type is `Vec`, where `T` is the iterator element + /// of the subiterators. + /// + /// ``` + /// use itertools::Itertools; + /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) + /// .multi_cartesian_product(); + /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); + /// assert_eq!(multi_prod.next(), None); + /// ``` + #[cfg(feature = "use_alloc")] + fn multi_cartesian_product(self) -> MultiProduct<::IntoIter> + where Self: Sized, + Self::Item: IntoIterator, + ::IntoIter: Clone, + ::Item: Clone + { + adaptors::multi_cartesian_product(self) + } + + /// Return an iterator adaptor that uses the passed-in closure to + /// optionally merge together consecutive elements. + /// + /// The closure `f` is passed two elements, `previous` and `current` and may + /// return either (1) `Ok(combined)` to merge the two values or + /// (2) `Err((previous', current'))` to indicate they can't be merged. + /// In (2), the value `previous'` is emitted by the iterator. + /// Either (1) `combined` or (2) `current'` becomes the previous value + /// when coalesce continues with the next pair of elements to merge. The + /// value that remains at the end is also emitted by the iterator. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sum same-sign runs together + /// let data = vec![-1., -2., -3., 3., 1., 0., -1.]; + /// itertools::assert_equal(data.into_iter().coalesce(|x, y| + /// if (x >= 0.) == (y >= 0.) { + /// Ok(x + y) + /// } else { + /// Err((x, y)) + /// }), + /// vec![-6., 4., -1.]); + /// ``` + fn coalesce(self, f: F) -> Coalesce + where Self: Sized, + F: FnMut(Self::Item, Self::Item) + -> Result + { + adaptors::coalesce(self, f) + } + + /// Remove duplicates from sections of consecutive identical elements. + /// If the iterator is sorted, all elements will be unique. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; + /// itertools::assert_equal(data.into_iter().dedup(), + /// vec![1., 2., 3., 2.]); + /// ``` + fn dedup(self) -> Dedup + where Self: Sized, + Self::Item: PartialEq, + { + adaptors::dedup(self) + } + + /// Remove duplicates from sections of consecutive identical elements, + /// determining equality using a comparison function. + /// If the iterator is sorted, all elements will be unique. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![(0, 1.), (1, 1.), (0, 2.), (0, 3.), (1, 3.), (1, 2.), (2, 2.)]; + /// itertools::assert_equal(data.into_iter().dedup_by(|x, y| x.1 == y.1), + /// vec![(0, 1.), (0, 2.), (0, 3.), (1, 2.)]); + /// ``` + fn dedup_by(self, cmp: Cmp) -> DedupBy + where Self: Sized, + Cmp: FnMut(&Self::Item, &Self::Item)->bool, + { + adaptors::dedup_by(self, cmp) + } + + /// Remove duplicates from sections of consecutive identical elements, while keeping a count of + /// how many repeated elements were present. + /// If the iterator is sorted, all elements will be unique. + /// + /// Iterator element type is `(usize, Self::Item)`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec!['a', 'a', 'b', 'c', 'c', 'b', 'b']; + /// itertools::assert_equal(data.into_iter().dedup_with_count(), + /// vec![(2, 'a'), (1, 'b'), (2, 'c'), (2, 'b')]); + /// ``` + fn dedup_with_count(self) -> DedupWithCount + where + Self: Sized, + { + adaptors::dedup_with_count(self) + } + + /// Remove duplicates from sections of consecutive identical elements, while keeping a count of + /// how many repeated elements were present. + /// This will determine equality using a comparison function. + /// If the iterator is sorted, all elements will be unique. + /// + /// Iterator element type is `(usize, Self::Item)`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![(0, 'a'), (1, 'a'), (0, 'b'), (0, 'c'), (1, 'c'), (1, 'b'), (2, 'b')]; + /// itertools::assert_equal(data.into_iter().dedup_by_with_count(|x, y| x.1 == y.1), + /// vec![(2, (0, 'a')), (1, (0, 'b')), (2, (0, 'c')), (2, (1, 'b'))]); + /// ``` + fn dedup_by_with_count(self, cmp: Cmp) -> DedupByWithCount + where + Self: Sized, + Cmp: FnMut(&Self::Item, &Self::Item) -> bool, + { + adaptors::dedup_by_with_count(self, cmp) + } + + /// Return an iterator adaptor that produces elements that appear more than once during the + /// iteration. Duplicates are detected using hash and equality. + /// + /// The iterator is stable, returning the duplicate items in the order in which they occur in + /// the adapted iterator. Each duplicate item is returned exactly once. If an item appears more + /// than twice, the second item is the item retained and the rest are discarded. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![10, 20, 30, 20, 40, 10, 50]; + /// itertools::assert_equal(data.into_iter().duplicates(), + /// vec![20, 10]); + /// ``` + #[cfg(feature = "use_std")] + fn duplicates(self) -> Duplicates + where Self: Sized, + Self::Item: Eq + Hash + { + duplicates_impl::duplicates(self) + } + + /// Return an iterator adaptor that produces elements that appear more than once during the + /// iteration. Duplicates are detected using hash and equality. + /// + /// Duplicates are detected by comparing the key they map to with the keying function `f` by + /// hash and equality. The keys are stored in a hash map in the iterator. + /// + /// The iterator is stable, returning the duplicate items in the order in which they occur in + /// the adapted iterator. Each duplicate item is returned exactly once. If an item appears more + /// than twice, the second item is the item retained and the rest are discarded. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec!["a", "bb", "aa", "c", "ccc"]; + /// itertools::assert_equal(data.into_iter().duplicates_by(|s| s.len()), + /// vec!["aa", "c"]); + /// ``` + #[cfg(feature = "use_std")] + fn duplicates_by(self, f: F) -> DuplicatesBy + where Self: Sized, + V: Eq + Hash, + F: FnMut(&Self::Item) -> V + { + duplicates_impl::duplicates_by(self, f) + } + + /// Return an iterator adaptor that filters out elements that have + /// already been produced once during the iteration. Duplicates + /// are detected using hash and equality. + /// + /// Clones of visited elements are stored in a hash set in the + /// iterator. + /// + /// The iterator is stable, returning the non-duplicate items in the order + /// in which they occur in the adapted iterator. In a set of duplicate + /// items, the first item encountered is the item retained. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![10, 20, 30, 20, 40, 10, 50]; + /// itertools::assert_equal(data.into_iter().unique(), + /// vec![10, 20, 30, 40, 50]); + /// ``` + #[cfg(feature = "use_std")] + fn unique(self) -> Unique + where Self: Sized, + Self::Item: Clone + Eq + Hash + { + unique_impl::unique(self) + } + + /// Return an iterator adaptor that filters out elements that have + /// already been produced once during the iteration. + /// + /// Duplicates are detected by comparing the key they map to + /// with the keying function `f` by hash and equality. + /// The keys are stored in a hash set in the iterator. + /// + /// The iterator is stable, returning the non-duplicate items in the order + /// in which they occur in the adapted iterator. In a set of duplicate + /// items, the first item encountered is the item retained. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec!["a", "bb", "aa", "c", "ccc"]; + /// itertools::assert_equal(data.into_iter().unique_by(|s| s.len()), + /// vec!["a", "bb", "ccc"]); + /// ``` + #[cfg(feature = "use_std")] + fn unique_by(self, f: F) -> UniqueBy + where Self: Sized, + V: Eq + Hash, + F: FnMut(&Self::Item) -> V + { + unique_impl::unique_by(self, f) + } + + /// Return an iterator adaptor that borrows from this iterator and + /// takes items while the closure `accept` returns `true`. + /// + /// This adaptor can only be used on iterators that implement `PeekingNext` + /// like `.peekable()`, `put_back` and a few other collection iterators. + /// + /// The last and rejected element (first `false`) is still available when + /// `peeking_take_while` is done. + /// + /// + /// See also [`.take_while_ref()`](Itertools::take_while_ref) + /// which is a similar adaptor. + fn peeking_take_while(&mut self, accept: F) -> PeekingTakeWhile + where Self: Sized + PeekingNext, + F: FnMut(&Self::Item) -> bool, + { + peeking_take_while::peeking_take_while(self, accept) + } + + /// Return an iterator adaptor that borrows from a `Clone`-able iterator + /// to only pick off elements while the predicate `accept` returns `true`. + /// + /// It uses the `Clone` trait to restore the original iterator so that the + /// last and rejected element (first `false`) is still available when + /// `take_while_ref` is done. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut hexadecimals = "0123456789abcdef".chars(); + /// + /// let decimals = hexadecimals.take_while_ref(|c| c.is_numeric()) + /// .collect::(); + /// assert_eq!(decimals, "0123456789"); + /// assert_eq!(hexadecimals.next(), Some('a')); + /// + /// ``` + fn take_while_ref(&mut self, accept: F) -> TakeWhileRef + where Self: Clone, + F: FnMut(&Self::Item) -> bool + { + adaptors::take_while_ref(self, accept) + } + + /// Return an iterator adaptor that filters `Option` iterator elements + /// and produces `A`. Stops on the first `None` encountered. + /// + /// Iterator element type is `A`, the unwrapped element. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // List all hexadecimal digits + /// itertools::assert_equal( + /// (0..).map(|i| std::char::from_digit(i, 16)).while_some(), + /// "0123456789abcdef".chars()); + /// + /// ``` + fn while_some(self) -> WhileSome + where Self: Sized + Iterator> + { + adaptors::while_some(self) + } + + /// Return an iterator adaptor that iterates over the combinations of the + /// elements from an iterator. + /// + /// Iterator element can be any homogeneous tuple of type `Self::Item` with + /// size up to 12. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).tuple_combinations() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]); + /// + /// let mut it = (1..5).tuple_combinations(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((1, 2, 4)), it.next()); + /// assert_eq!(Some((1, 3, 4)), it.next()); + /// assert_eq!(Some((2, 3, 4)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).tuple_combinations::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); + /// + /// // you can also specify the complete type + /// use itertools::TupleCombinations; + /// use std::ops::Range; + /// + /// let it: TupleCombinations, (u32, u32, u32)> = (1..5).tuple_combinations(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); + /// ``` + fn tuple_combinations(self) -> TupleCombinations + where Self: Sized + Clone, + Self::Item: Clone, + T: adaptors::HasCombination, + { + adaptors::tuple_combinations(self) + } + + /// Return an iterator adaptor that iterates over the `k`-length combinations of + /// the elements from an iterator. + /// + /// Iterator element type is `Vec`. The iterator produces a new Vec per iteration, + /// and clones the iterator elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..5).combinations(3); + /// itertools::assert_equal(it, vec![ + /// vec![1, 2, 3], + /// vec![1, 2, 4], + /// vec![1, 3, 4], + /// vec![2, 3, 4], + /// ]); + /// ``` + /// + /// Note: Combinations does not take into account the equality of the iterated values. + /// ``` + /// use itertools::Itertools; + /// + /// let it = vec![1, 2, 2].into_iter().combinations(2); + /// itertools::assert_equal(it, vec![ + /// vec![1, 2], // Note: these are the same + /// vec![1, 2], // Note: these are the same + /// vec![2, 2], + /// ]); + /// ``` + #[cfg(feature = "use_alloc")] + fn combinations(self, k: usize) -> Combinations + where Self: Sized, + Self::Item: Clone + { + combinations::combinations(self, k) + } + + /// Return an iterator that iterates over the `k`-length combinations of + /// the elements from an iterator, with replacement. + /// + /// Iterator element type is `Vec`. The iterator produces a new Vec per iteration, + /// and clones the iterator elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..4).combinations_with_replacement(2); + /// itertools::assert_equal(it, vec![ + /// vec![1, 1], + /// vec![1, 2], + /// vec![1, 3], + /// vec![2, 2], + /// vec![2, 3], + /// vec![3, 3], + /// ]); + /// ``` + #[cfg(feature = "use_alloc")] + fn combinations_with_replacement(self, k: usize) -> CombinationsWithReplacement + where + Self: Sized, + Self::Item: Clone, + { + combinations_with_replacement::combinations_with_replacement(self, k) + } + + /// Return an iterator adaptor that iterates over all k-permutations of the + /// elements from an iterator. + /// + /// Iterator element type is `Vec` with length `k`. The iterator + /// produces a new Vec per iteration, and clones the iterator elements. + /// + /// If `k` is greater than the length of the input iterator, the resultant + /// iterator adaptor will be empty. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let perms = (5..8).permutations(2); + /// itertools::assert_equal(perms, vec![ + /// vec![5, 6], + /// vec![5, 7], + /// vec![6, 5], + /// vec![6, 7], + /// vec![7, 5], + /// vec![7, 6], + /// ]); + /// ``` + /// + /// Note: Permutations does not take into account the equality of the iterated values. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = vec![2, 2].into_iter().permutations(2); + /// itertools::assert_equal(it, vec![ + /// vec![2, 2], // Note: these are the same + /// vec![2, 2], // Note: these are the same + /// ]); + /// ``` + /// + /// Note: The source iterator is collected lazily, and will not be + /// re-iterated if the permutations adaptor is completed and re-iterated. + #[cfg(feature = "use_alloc")] + fn permutations(self, k: usize) -> Permutations + where Self: Sized, + Self::Item: Clone + { + permutations::permutations(self, k) + } + + /// Return an iterator that iterates through the powerset of the elements from an + /// iterator. + /// + /// Iterator element type is `Vec`. The iterator produces a new `Vec` + /// per iteration, and clones the iterator elements. + /// + /// The powerset of a set contains all subsets including the empty set and the full + /// input set. A powerset has length _2^n_ where _n_ is the length of the input + /// set. + /// + /// Each `Vec` produced by this iterator represents a subset of the elements + /// produced by the source iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let sets = (1..4).powerset().collect::>(); + /// itertools::assert_equal(sets, vec![ + /// vec![], + /// vec![1], + /// vec![2], + /// vec![3], + /// vec![1, 2], + /// vec![1, 3], + /// vec![2, 3], + /// vec![1, 2, 3], + /// ]); + /// ``` + #[cfg(feature = "use_alloc")] + fn powerset(self) -> Powerset + where Self: Sized, + Self::Item: Clone, + { + powerset::powerset(self) + } + + /// Return an iterator adaptor that pads the sequence to a minimum length of + /// `min` by filling missing elements using a closure `f`. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..5).pad_using(10, |i| 2*i); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]); + /// + /// let it = (0..10).pad_using(5, |i| 2*i); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// let it = (0..5).pad_using(10, |i| 2*i).rev(); + /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); + /// ``` + fn pad_using(self, min: usize, f: F) -> PadUsing + where Self: Sized, + F: FnMut(usize) -> Self::Item + { + pad_tail::pad_using(self, min, f) + } + + /// Return an iterator adaptor that wraps each element in a `Position` to + /// ease special-case handling of the first or last elements. + /// + /// Iterator element type is + /// [`Position`](Position) + /// + /// ``` + /// use itertools::{Itertools, Position}; + /// + /// let it = (0..4).with_position(); + /// itertools::assert_equal(it, + /// vec![Position::First(0), + /// Position::Middle(1), + /// Position::Middle(2), + /// Position::Last(3)]); + /// + /// let it = (0..1).with_position(); + /// itertools::assert_equal(it, vec![Position::Only(0)]); + /// ``` + fn with_position(self) -> WithPosition + where Self: Sized, + { + with_position::with_position(self) + } + + /// Return an iterator adaptor that yields the indices of all elements + /// satisfying a predicate, counted from the start of the iterator. + /// + /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 2, 3, 3, 4, 6, 7, 9]; + /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]); + /// + /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); + /// ``` + fn positions

(self, predicate: P) -> Positions + where Self: Sized, + P: FnMut(Self::Item) -> bool, + { + adaptors::positions(self, predicate) + } + + /// Return an iterator adaptor that applies a mutating function + /// to each element before yielding it. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![vec![1], vec![3, 2, 1]]; + /// let it = input.into_iter().update(|mut v| v.push(0)); + /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); + /// ``` + fn update(self, updater: F) -> Update + where Self: Sized, + F: FnMut(&mut Self::Item), + { + adaptors::update(self, updater) + } + + // non-adaptor methods + /// Advances the iterator and returns the next items grouped in a tuple of + /// a specific size (up to 12). + /// + /// If there are enough elements to be grouped in a tuple, then the tuple is + /// returned inside `Some`, otherwise `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = 1..5; + /// + /// assert_eq!(Some((1, 2)), iter.next_tuple()); + /// ``` + fn next_tuple(&mut self) -> Option + where Self: Sized + Iterator, + T: traits::HomogeneousTuple + { + T::collect_from_iter_no_buf(self) + } + + /// Collects all items from the iterator into a tuple of a specific size + /// (up to 12). + /// + /// If the number of elements inside the iterator is **exactly** equal to + /// the tuple size, then the tuple is returned inside `Some`, otherwise + /// `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let iter = 1..3; + /// + /// if let Some((x, y)) = iter.collect_tuple() { + /// assert_eq!((x, y), (1, 2)) + /// } else { + /// panic!("Expected two elements") + /// } + /// ``` + fn collect_tuple(mut self) -> Option + where Self: Sized + Iterator, + T: traits::HomogeneousTuple + { + match self.next_tuple() { + elt @ Some(_) => match self.next() { + Some(_) => None, + None => elt, + }, + _ => None + } + } + + + /// Find the position and value of the first element satisfying a predicate. + /// + /// The iterator is not advanced past the first element found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let text = "Hα"; + /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); + /// ``` + fn find_position

(&mut self, mut pred: P) -> Option<(usize, Self::Item)> + where P: FnMut(&Self::Item) -> bool + { + for (index, elt) in self.enumerate() { + if pred(&elt) { + return Some((index, elt)); + } + } + None + } + /// Find the value of the first element satisfying a predicate or return the last element, if any. + /// + /// The iterator is not advanced past the first element found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let numbers = [1, 2, 3, 4]; + /// assert_eq!(numbers.iter().find_or_last(|&&x| x > 5), Some(&4)); + /// assert_eq!(numbers.iter().find_or_last(|&&x| x > 2), Some(&3)); + /// assert_eq!(std::iter::empty::().find_or_last(|&x| x > 5), None); + /// ``` + fn find_or_last

(mut self, mut predicate: P) -> Option + where Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + let mut prev = None; + self.find_map(|x| if predicate(&x) { Some(x) } else { prev = Some(x); None }) + .or(prev) + } + /// Find the value of the first element satisfying a predicate or return the first element, if any. + /// + /// The iterator is not advanced past the first element found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let numbers = [1, 2, 3, 4]; + /// assert_eq!(numbers.iter().find_or_first(|&&x| x > 5), Some(&1)); + /// assert_eq!(numbers.iter().find_or_first(|&&x| x > 2), Some(&3)); + /// assert_eq!(std::iter::empty::().find_or_first(|&x| x > 5), None); + /// ``` + fn find_or_first

(mut self, mut predicate: P) -> Option + where Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + let first = self.next()?; + Some(if predicate(&first) { + first + } else { + self.find(|x| predicate(x)).unwrap_or(first) + }) + } + /// Returns `true` if the given item is present in this iterator. + /// + /// This method is short-circuiting. If the given item is present in this + /// iterator, this method will consume the iterator up-to-and-including + /// the item. If the given item is not present in this iterator, the + /// iterator will be exhausted. + /// + /// ``` + /// use itertools::Itertools; + /// + /// #[derive(PartialEq, Debug)] + /// enum Enum { A, B, C, D, E, } + /// + /// let mut iter = vec![Enum::A, Enum::B, Enum::C, Enum::D].into_iter(); + /// + /// // search `iter` for `B` + /// assert_eq!(iter.contains(&Enum::B), true); + /// // `B` was found, so the iterator now rests at the item after `B` (i.e, `C`). + /// assert_eq!(iter.next(), Some(Enum::C)); + /// + /// // search `iter` for `E` + /// assert_eq!(iter.contains(&Enum::E), false); + /// // `E` wasn't found, so `iter` is now exhausted + /// assert_eq!(iter.next(), None); + /// ``` + fn contains(&mut self, query: &Q) -> bool + where + Self: Sized, + Self::Item: Borrow, + Q: PartialEq, + { + self.any(|x| x.borrow() == query) + } + + /// Check whether all elements compare equal. + /// + /// Empty iterators are considered to have equal elements: + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; + /// assert!(!data.iter().all_equal()); + /// assert!(data[0..3].iter().all_equal()); + /// assert!(data[3..5].iter().all_equal()); + /// assert!(data[5..8].iter().all_equal()); + /// + /// let data : Option = None; + /// assert!(data.into_iter().all_equal()); + /// ``` + fn all_equal(&mut self) -> bool + where Self: Sized, + Self::Item: PartialEq, + { + match self.next() { + None => true, + Some(a) => self.all(|x| a == x), + } + } + + /// Check whether all elements are unique (non equal). + /// + /// Empty iterators are considered to have unique elements: + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 2, 3, 4, 1, 5]; + /// assert!(!data.iter().all_unique()); + /// assert!(data[0..4].iter().all_unique()); + /// assert!(data[1..6].iter().all_unique()); + /// + /// let data : Option = None; + /// assert!(data.into_iter().all_unique()); + /// ``` + #[cfg(feature = "use_std")] + fn all_unique(&mut self) -> bool + where Self: Sized, + Self::Item: Eq + Hash + { + let mut used = HashSet::new(); + self.all(move |elt| used.insert(elt)) + } + + /// Consume the first `n` elements from the iterator eagerly, + /// and return the same iterator again. + /// + /// It works similarly to *.skip(* `n` *)* except it is eager and + /// preserves the iterator type. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = "αβγ".chars().dropping(2); + /// itertools::assert_equal(iter, "γ".chars()); + /// ``` + /// + /// *Fusing notes: if the iterator is exhausted by dropping, + /// the result of calling `.next()` again depends on the iterator implementation.* + fn dropping(mut self, n: usize) -> Self + where Self: Sized + { + if n > 0 { + self.nth(n - 1); + } + self + } + + /// Consume the last `n` elements from the iterator eagerly, + /// and return the same iterator again. + /// + /// This is only possible on double ended iterators. `n` may be + /// larger than the number of elements. + /// + /// Note: This method is eager, dropping the back elements immediately and + /// preserves the iterator type. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let init = vec![0, 3, 6, 9].into_iter().dropping_back(1); + /// itertools::assert_equal(init, vec![0, 3, 6]); + /// ``` + fn dropping_back(mut self, n: usize) -> Self + where Self: Sized, + Self: DoubleEndedIterator + { + if n > 0 { + (&mut self).rev().nth(n - 1); + } + self + } + + /// Run the closure `f` eagerly on each element of the iterator. + /// + /// Consumes the iterator until its end. + /// + /// ``` + /// use std::sync::mpsc::channel; + /// use itertools::Itertools; + /// + /// let (tx, rx) = channel(); + /// + /// // use .foreach() to apply a function to each value -- sending it + /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); + /// + /// drop(tx); + /// + /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); + /// ``` + #[deprecated(note="Use .for_each() instead", since="0.8.0")] + fn foreach(self, f: F) + where F: FnMut(Self::Item), + Self: Sized, + { + self.for_each(f); + } + + /// Combine all an iterator's elements into one element by using [`Extend`]. + /// + /// This combinator will extend the first item with each of the rest of the + /// items of the iterator. If the iterator is empty, the default value of + /// `I::Item` is returned. + /// + /// ```rust + /// use itertools::Itertools; + /// + /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; + /// assert_eq!(input.into_iter().concat(), + /// vec![1, 2, 3, 4, 5, 6]); + /// ``` + fn concat(self) -> Self::Item + where Self: Sized, + Self::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default + { + concat(self) + } + + /// `.collect_vec()` is simply a type specialization of [`Iterator::collect`], + /// for convenience. + #[cfg(feature = "use_alloc")] + fn collect_vec(self) -> Vec + where Self: Sized + { + self.collect() + } + + /// `.try_collect()` is more convenient way of writing + /// `.collect::>()` + /// + /// # Example + /// + /// ``` + /// use std::{fs, io}; + /// use itertools::Itertools; + /// + /// fn process_dir_entries(entries: &[fs::DirEntry]) { + /// // ... + /// } + /// + /// fn do_stuff() -> std::io::Result<()> { + /// let entries: Vec<_> = fs::read_dir(".")?.try_collect()?; + /// process_dir_entries(&entries); + /// + /// Ok(()) + /// } + /// ``` + #[cfg(feature = "use_alloc")] + fn try_collect(self) -> Result + where + Self: Sized + Iterator>, + Result: FromIterator>, + { + self.collect() + } + + /// Assign to each reference in `self` from the `from` iterator, + /// stopping at the shortest of the two iterators. + /// + /// The `from` iterator is queried for its next element before the `self` + /// iterator, and if either is exhausted the method is done. + /// + /// Return the number of elements written. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut xs = [0; 4]; + /// xs.iter_mut().set_from(1..); + /// assert_eq!(xs, [1, 2, 3, 4]); + /// ``` + #[inline] + fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize + where Self: Iterator, + J: IntoIterator + { + let mut count = 0; + for elt in from { + match self.next() { + None => break, + Some(ptr) => *ptr = elt, + } + count += 1; + } + count + } + + /// Combine all iterator elements into one String, separated by `sep`. + /// + /// Use the `Display` implementation of each element. + /// + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c"); + /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3"); + /// ``` + #[cfg(feature = "use_alloc")] + fn join(&mut self, sep: &str) -> String + where Self::Item: std::fmt::Display + { + match self.next() { + None => String::new(), + Some(first_elt) => { + // estimate lower bound of capacity needed + let (lower, _) = self.size_hint(); + let mut result = String::with_capacity(sep.len() * lower); + write!(&mut result, "{}", first_elt).unwrap(); + self.for_each(|elt| { + result.push_str(sep); + write!(&mut result, "{}", elt).unwrap(); + }); + result + } + } + } + + /// Format all iterator elements, separated by `sep`. + /// + /// All elements are formatted (any formatting trait) + /// with `sep` inserted between each element. + /// + /// **Panics** if the formatter helper is formatted more than once. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = [1.1, 2.71828, -3.]; + /// assert_eq!( + /// format!("{:.2}", data.iter().format(", ")), + /// "1.10, 2.72, -3.00"); + /// ``` + fn format(self, sep: &str) -> Format + where Self: Sized, + { + format::new_format_default(self, sep) + } + + /// Format all iterator elements, separated by `sep`. + /// + /// This is a customizable version of [`.format()`](Itertools::format). + /// + /// The supplied closure `format` is called once per iterator element, + /// with two arguments: the element and a callback that takes a + /// `&Display` value, i.e. any reference to type that implements `Display`. + /// + /// Using `&format_args!(...)` is the most versatile way to apply custom + /// element formatting. The callback can be called multiple times if needed. + /// + /// **Panics** if the formatter helper is formatted more than once. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = [1.1, 2.71828, -3.]; + /// let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt))); + /// assert_eq!(format!("{}", data_formatter), + /// "1.10, 2.72, -3.00"); + /// + /// // .format_with() is recursively composable + /// let matrix = [[1., 2., 3.], + /// [4., 5., 6.]]; + /// let matrix_formatter = matrix.iter().format_with("\n", |row, f| { + /// f(&row.iter().format_with(", ", |elt, g| g(&elt))) + /// }); + /// assert_eq!(format!("{}", matrix_formatter), + /// "1, 2, 3\n4, 5, 6"); + /// + /// + /// ``` + fn format_with(self, sep: &str, format: F) -> FormatWith + where Self: Sized, + F: FnMut(Self::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, + { + format::new_format(self, sep, format) + } + + /// See [`.fold_ok()`](Itertools::fold_ok). + #[deprecated(note="Use .fold_ok() instead", since="0.10.0")] + fn fold_results(&mut self, start: B, f: F) -> Result + where Self: Iterator>, + F: FnMut(B, A) -> B + { + self.fold_ok(start, f) + } + + /// Fold `Result` values from an iterator. + /// + /// Only `Ok` values are folded. If no error is encountered, the folded + /// value is returned inside `Ok`. Otherwise, the operation terminates + /// and returns the first `Err` value it encounters. No iterator elements are + /// consumed after the first error. + /// + /// The first accumulator value is the `start` parameter. + /// Each iteration passes the accumulator value and the next value inside `Ok` + /// to the fold function `f` and its return value becomes the new accumulator value. + /// + /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a + /// computation like this: + /// + /// ```ignore + /// let mut accum = start; + /// accum = f(accum, 1); + /// accum = f(accum, 2); + /// accum = f(accum, 3); + /// ``` + /// + /// With a `start` value of 0 and an addition as folding function, + /// this effectively results in *((0 + 1) + 2) + 3* + /// + /// ``` + /// use std::ops::Add; + /// use itertools::Itertools; + /// + /// let values = [1, 2, -2, -1, 2, 1]; + /// assert_eq!( + /// values.iter() + /// .map(Ok::<_, ()>) + /// .fold_ok(0, Add::add), + /// Ok(3) + /// ); + /// assert!( + /// values.iter() + /// .map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") }) + /// .fold_ok(0, Add::add) + /// .is_err() + /// ); + /// ``` + fn fold_ok(&mut self, mut start: B, mut f: F) -> Result + where Self: Iterator>, + F: FnMut(B, A) -> B + { + for elt in self { + match elt { + Ok(v) => start = f(start, v), + Err(u) => return Err(u), + } + } + Ok(start) + } + + /// Fold `Option` values from an iterator. + /// + /// Only `Some` values are folded. If no `None` is encountered, the folded + /// value is returned inside `Some`. Otherwise, the operation terminates + /// and returns `None`. No iterator elements are consumed after the `None`. + /// + /// This is the `Option` equivalent to [`fold_ok`](Itertools::fold_ok). + /// + /// ``` + /// use std::ops::Add; + /// use itertools::Itertools; + /// + /// let mut values = vec![Some(1), Some(2), Some(-2)].into_iter(); + /// assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2)); + /// + /// let mut more_values = vec![Some(2), None, Some(0)].into_iter(); + /// assert!(more_values.fold_options(0, Add::add).is_none()); + /// assert_eq!(more_values.next().unwrap(), Some(0)); + /// ``` + fn fold_options(&mut self, mut start: B, mut f: F) -> Option + where Self: Iterator>, + F: FnMut(B, A) -> B + { + for elt in self { + match elt { + Some(v) => start = f(start, v), + None => return None, + } + } + Some(start) + } + + /// Accumulator of the elements in the iterator. + /// + /// Like `.fold()`, without a base case. If the iterator is + /// empty, return `None`. With just one element, return it. + /// Otherwise elements are accumulated in sequence using the closure `f`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); + /// assert_eq!((0..0).fold1(|x, y| x * y), None); + /// ``` + #[deprecated(since = "0.10.2", note = "Use `Iterator::reduce` instead")] + fn fold1(mut self, f: F) -> Option + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + self.next().map(move |x| self.fold(x, f)) + } + + /// Accumulate the elements in the iterator in a tree-like manner. + /// + /// You can think of it as, while there's more than one item, repeatedly + /// combining adjacent items. It does so in bottom-up-merge-sort order, + /// however, so that it needs only logarithmic stack space. + /// + /// This produces a call tree like the following (where the calls under + /// an item are done after reading that item): + /// + /// ```text + /// 1 2 3 4 5 6 7 + /// │ │ │ │ │ │ │ + /// └─f └─f └─f │ + /// │ │ │ │ + /// └───f └─f + /// │ │ + /// └─────f + /// ``` + /// + /// Which, for non-associative functions, will typically produce a different + /// result than the linear call tree used by [`Iterator::reduce`]: + /// + /// ```text + /// 1 2 3 4 5 6 7 + /// │ │ │ │ │ │ │ + /// └─f─f─f─f─f─f + /// ``` + /// + /// If `f` is associative, prefer the normal [`Iterator::reduce`] instead. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // The same tree as above + /// let num_strings = (1..8).map(|x| x.to_string()); + /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), + /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); + /// + /// // Like fold1, an empty iterator produces None + /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); + /// + /// // tree_fold1 matches fold1 for associative operations... + /// assert_eq!((0..10).tree_fold1(|x, y| x + y), + /// (0..10).fold1(|x, y| x + y)); + /// // ...but not for non-associative ones + /// assert_ne!((0..10).tree_fold1(|x, y| x - y), + /// (0..10).fold1(|x, y| x - y)); + /// ``` + fn tree_fold1(mut self, mut f: F) -> Option + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + type State = Result>; + + fn inner0(it: &mut II, f: &mut FF) -> State + where + II: Iterator, + FF: FnMut(T, T) -> T + { + // This function could be replaced with `it.next().ok_or(None)`, + // but half the useful tree_fold1 work is combining adjacent items, + // so put that in a form that LLVM is more likely to optimize well. + + let a = + if let Some(v) = it.next() { v } + else { return Err(None) }; + let b = + if let Some(v) = it.next() { v } + else { return Err(Some(a)) }; + Ok(f(a, b)) + } + + fn inner(stop: usize, it: &mut II, f: &mut FF) -> State + where + II: Iterator, + FF: FnMut(T, T) -> T + { + let mut x = inner0(it, f)?; + for height in 0..stop { + // Try to get another tree the same size with which to combine it, + // creating a new tree that's twice as big for next time around. + let next = + if height == 0 { + inner0(it, f) + } else { + inner(height, it, f) + }; + match next { + Ok(y) => x = f(x, y), + + // If we ran out of items, combine whatever we did manage + // to get. It's better combined with the current value + // than something in a parent frame, because the tree in + // the parent is always as least as big as this one. + Err(None) => return Err(Some(x)), + Err(Some(y)) => return Err(Some(f(x, y))), + } + } + Ok(x) + } + + match inner(usize::max_value(), &mut self, &mut f) { + Err(x) => x, + _ => unreachable!(), + } + } + + /// An iterator method that applies a function, producing a single, final value. + /// + /// `fold_while()` is basically equivalent to [`Iterator::fold`] but with additional support for + /// early exit via short-circuiting. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::FoldWhile::{Continue, Done}; + /// + /// let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// + /// let mut result = 0; + /// + /// // for loop: + /// for i in &numbers { + /// if *i > 5 { + /// break; + /// } + /// result = result + i; + /// } + /// + /// // fold: + /// let result2 = numbers.iter().fold(0, |acc, x| { + /// if *x > 5 { acc } else { acc + x } + /// }); + /// + /// // fold_while: + /// let result3 = numbers.iter().fold_while(0, |acc, x| { + /// if *x > 5 { Done(acc) } else { Continue(acc + x) } + /// }).into_inner(); + /// + /// // they're the same + /// assert_eq!(result, result2); + /// assert_eq!(result2, result3); + /// ``` + /// + /// The big difference between the computations of `result2` and `result3` is that while + /// `fold()` called the provided closure for every item of the callee iterator, + /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. + fn fold_while(&mut self, init: B, mut f: F) -> FoldWhile + where Self: Sized, + F: FnMut(B, Self::Item) -> FoldWhile + { + use Result::{ + Ok as Continue, + Err as Break, + }; + + let result = self.try_fold(init, #[inline(always)] |acc, v| + match f(acc, v) { + FoldWhile::Continue(acc) => Continue(acc), + FoldWhile::Done(acc) => Break(acc), + } + ); + + match result { + Continue(acc) => FoldWhile::Continue(acc), + Break(acc) => FoldWhile::Done(acc), + } + } + + /// Iterate over the entire iterator and add all the elements. + /// + /// An empty iterator returns `None`, otherwise `Some(sum)`. + /// + /// # Panics + /// + /// When calling `sum1()` and a primitive integer type is being returned, this + /// method will panic if the computation overflows and debug assertions are + /// enabled. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let empty_sum = (1..1).sum1::(); + /// assert_eq!(empty_sum, None); + /// + /// let nonempty_sum = (1..11).sum1::(); + /// assert_eq!(nonempty_sum, Some(55)); + /// ``` + fn sum1(mut self) -> Option + where Self: Sized, + S: std::iter::Sum, + { + self.next() + .map(|first| once(first).chain(self).sum()) + } + + /// Iterate over the entire iterator and multiply all the elements. + /// + /// An empty iterator returns `None`, otherwise `Some(product)`. + /// + /// # Panics + /// + /// When calling `product1()` and a primitive integer type is being returned, + /// method will panic if the computation overflows and debug assertions are + /// enabled. + /// + /// # Examples + /// ``` + /// use itertools::Itertools; + /// + /// let empty_product = (1..1).product1::(); + /// assert_eq!(empty_product, None); + /// + /// let nonempty_product = (1..11).product1::(); + /// assert_eq!(nonempty_product, Some(3628800)); + /// ``` + fn product1

(mut self) -> Option

+ where Self: Sized, + P: std::iter::Product, + { + self.next() + .map(|first| once(first).chain(self).product()) + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_unstable`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort the letters of the text in ascending order + /// let text = "bdacfe"; + /// itertools::assert_equal(text.chars().sorted_unstable(), + /// "abcdef".chars()); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_unstable(self) -> VecIntoIter + where Self: Sized, + Self::Item: Ord + { + // Use .sort_unstable() directly since it is not quite identical with + // .sort_by(Ord::cmp) + let mut v = Vec::from_iter(self); + v.sort_unstable(); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_unstable_by`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_unstable_by(|a, b| Ord::cmp(&b.1, &a.1)) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_unstable_by(self, cmp: F) -> VecIntoIter + where Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + let mut v = Vec::from_iter(self); + v.sort_unstable_by(cmp); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_unstable_by_key`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_unstable_by_key(|x| -x.1) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_unstable_by_key(self, f: F) -> VecIntoIter + where Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, + { + let mut v = Vec::from_iter(self); + v.sort_unstable_by_key(f); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort the letters of the text in ascending order + /// let text = "bdacfe"; + /// itertools::assert_equal(text.chars().sorted(), + /// "abcdef".chars()); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted(self) -> VecIntoIter + where Self: Sized, + Self::Item: Ord + { + // Use .sort() directly since it is not quite identical with + // .sort_by(Ord::cmp) + let mut v = Vec::from_iter(self); + v.sort(); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_by`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_by(self, cmp: F) -> VecIntoIter + where Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + let mut v = Vec::from_iter(self); + v.sort_by(cmp); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_by_key`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by_key(|x| -x.1) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_by_key(self, f: F) -> VecIntoIter + where Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, + { + let mut v = Vec::from_iter(self); + v.sort_by_key(f); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. The key function is + /// called exactly once per key. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_by_cached_key`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by_cached_key(|x| -x.1) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_by_cached_key(self, f: F) -> VecIntoIter + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, + { + let mut v = Vec::from_iter(self); + v.sort_by_cached_key(f); + v.into_iter() + } + + /// Sort the k smallest elements into a new iterator, in ascending order. + /// + /// **Note:** This consumes the entire iterator, and returns the result + /// as a new iterator that owns its elements. If the input contains + /// less than k elements, the result is equivalent to `self.sorted()`. + /// + /// This is guaranteed to use `k * sizeof(Self::Item) + O(1)` memory + /// and `O(n log k)` time, with `n` the number of elements in the input. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// **Note:** This is functionally-equivalent to `self.sorted().take(k)` + /// but much more efficient. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // A random permutation of 0..15 + /// let numbers = vec![6, 9, 1, 14, 0, 4, 8, 7, 11, 2, 10, 3, 13, 12, 5]; + /// + /// let five_smallest = numbers + /// .into_iter() + /// .k_smallest(5); + /// + /// itertools::assert_equal(five_smallest, 0..5); + /// ``` + #[cfg(feature = "use_alloc")] + fn k_smallest(self, k: usize) -> VecIntoIter + where Self: Sized, + Self::Item: Ord + { + crate::k_smallest::k_smallest(self, k) + .into_sorted_vec() + .into_iter() + } + + /// Collect all iterator elements into one of two + /// partitions. Unlike [`Iterator::partition`], each partition may + /// have a distinct type. + /// + /// ``` + /// use itertools::{Itertools, Either}; + /// + /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; + /// + /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures + /// .into_iter() + /// .partition_map(|r| { + /// match r { + /// Ok(v) => Either::Left(v), + /// Err(v) => Either::Right(v), + /// } + /// }); + /// + /// assert_eq!(successes, [1, 2]); + /// assert_eq!(failures, [false, true]); + /// ``` + fn partition_map(self, mut predicate: F) -> (A, B) + where Self: Sized, + F: FnMut(Self::Item) -> Either, + A: Default + Extend, + B: Default + Extend, + { + let mut left = A::default(); + let mut right = B::default(); + + self.for_each(|val| match predicate(val) { + Either::Left(v) => left.extend(Some(v)), + Either::Right(v) => right.extend(Some(v)), + }); + + (left, right) + } + + /// Partition a sequence of `Result`s into one list of all the `Ok` elements + /// and another list of all the `Err` elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; + /// + /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures + /// .into_iter() + /// .partition_result(); + /// + /// assert_eq!(successes, [1, 2]); + /// assert_eq!(failures, [false, true]); + /// ``` + fn partition_result(self) -> (A, B) + where + Self: Iterator> + Sized, + A: Default + Extend, + B: Default + Extend, + { + self.partition_map(|r| match r { + Ok(v) => Either::Left(v), + Err(v) => Either::Right(v), + }) + } + + /// Return a `HashMap` of keys mapped to `Vec`s of values. Keys and values + /// are taken from `(Key, Value)` tuple pairs yielded by the input iterator. + /// + /// Essentially a shorthand for `.into_grouping_map().collect::>()`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; + /// let lookup = data.into_iter().into_group_map(); + /// + /// assert_eq!(lookup[&0], vec![10, 20]); + /// assert_eq!(lookup.get(&1), None); + /// assert_eq!(lookup[&2], vec![12, 42]); + /// assert_eq!(lookup[&3], vec![13, 33]); + /// ``` + #[cfg(feature = "use_std")] + fn into_group_map(self) -> HashMap> + where Self: Iterator + Sized, + K: Hash + Eq, + { + group_map::into_group_map(self) + } + + /// Return an `Iterator` on a `HashMap`. Keys mapped to `Vec`s of values. The key is specified + /// in the closure. + /// + /// Essentially a shorthand for `.into_grouping_map_by(f).collect::>()`. + /// + /// ``` + /// use itertools::Itertools; + /// use std::collections::HashMap; + /// + /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; + /// let lookup: HashMap> = + /// data.clone().into_iter().into_group_map_by(|a| a.0); + /// + /// assert_eq!(lookup[&0], vec![(0,10),(0,20)]); + /// assert_eq!(lookup.get(&1), None); + /// assert_eq!(lookup[&2], vec![(2,12), (2,42)]); + /// assert_eq!(lookup[&3], vec![(3,13), (3,33)]); + /// + /// assert_eq!( + /// data.into_iter() + /// .into_group_map_by(|x| x.0) + /// .into_iter() + /// .map(|(key, values)| (key, values.into_iter().fold(0,|acc, (_,v)| acc + v ))) + /// .collect::>()[&0], + /// 30, + /// ); + /// ``` + #[cfg(feature = "use_std")] + fn into_group_map_by(self, f: F) -> HashMap> + where + Self: Iterator + Sized, + K: Hash + Eq, + F: Fn(&V) -> K, + { + group_map::into_group_map_by(self, f) + } + + /// Constructs a `GroupingMap` to be used later with one of the efficient + /// group-and-fold operations it allows to perform. + /// + /// The input iterator must yield item in the form of `(K, V)` where the + /// value of type `K` will be used as key to identify the groups and the + /// value of type `V` as value for the folding operation. + /// + /// See [`GroupingMap`] for more informations + /// on what operations are available. + #[cfg(feature = "use_std")] + fn into_grouping_map(self) -> GroupingMap + where Self: Iterator + Sized, + K: Hash + Eq, + { + grouping_map::new(self) + } + + /// Constructs a `GroupingMap` to be used later with one of the efficient + /// group-and-fold operations it allows to perform. + /// + /// The values from this iterator will be used as values for the folding operation + /// while the keys will be obtained from the values by calling `key_mapper`. + /// + /// See [`GroupingMap`] for more informations + /// on what operations are available. + #[cfg(feature = "use_std")] + fn into_grouping_map_by(self, key_mapper: F) -> GroupingMapBy + where Self: Iterator + Sized, + K: Hash + Eq, + F: FnMut(&V) -> K + { + grouping_map::new(grouping_map::MapForGrouping::new(self, key_mapper)) + } + + /// Return all minimum elements of an iterator. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().min_set(), Vec::<&i32>::new()); + /// + /// let a = [1]; + /// assert_eq!(a.iter().min_set(), vec![&1]); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().min_set(), vec![&1]); + /// + /// let a = [1, 1, 1, 1]; + /// assert_eq!(a.iter().min_set(), vec![&1, &1, &1, &1]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn min_set(self) -> Vec + where Self: Sized, Self::Item: Ord + { + extrema_set::min_set_impl(self, |_| (), |x, y, _, _| x.cmp(y)) + } + + /// Return all minimum elements of an iterator, as determined by + /// the specified function. + /// + /// # Examples + /// + /// ``` + /// # use std::cmp::Ordering; + /// use itertools::Itertools; + /// + /// let a: [(i32, i32); 0] = []; + /// assert_eq!(a.iter().min_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new()); + /// + /// let a = [(1, 2)]; + /// assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]); + /// + /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)]; + /// assert_eq!(a.iter().min_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(1, 2), &(2, 2)]); + /// + /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)]; + /// assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn min_set_by(self, mut compare: F) -> Vec + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + extrema_set::min_set_impl( + self, + |_| (), + |x, y, _, _| compare(x, y) + ) + } + + /// Return all minimum elements of an iterator, as determined by + /// the specified function. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [(i32, i32); 0] = []; + /// assert_eq!(a.iter().min_set_by_key(|_| ()), Vec::<&(i32, i32)>::new()); + /// + /// let a = [(1, 2)]; + /// assert_eq!(a.iter().min_set_by_key(|&&(k,_)| k), vec![&(1, 2)]); + /// + /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)]; + /// assert_eq!(a.iter().min_set_by_key(|&&(_, k)| k), vec![&(1, 2), &(2, 2)]); + /// + /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)]; + /// assert_eq!(a.iter().min_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn min_set_by_key(self, key: F) -> Vec + where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + { + extrema_set::min_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky)) + } + + /// Return all maximum elements of an iterator. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().max_set(), Vec::<&i32>::new()); + /// + /// let a = [1]; + /// assert_eq!(a.iter().max_set(), vec![&1]); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().max_set(), vec![&5]); + /// + /// let a = [1, 1, 1, 1]; + /// assert_eq!(a.iter().max_set(), vec![&1, &1, &1, &1]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn max_set(self) -> Vec + where Self: Sized, Self::Item: Ord + { + extrema_set::max_set_impl(self, |_| (), |x, y, _, _| x.cmp(y)) + } + + /// Return all maximum elements of an iterator, as determined by + /// the specified function. + /// + /// # Examples + /// + /// ``` + /// # use std::cmp::Ordering; + /// use itertools::Itertools; + /// + /// let a: [(i32, i32); 0] = []; + /// assert_eq!(a.iter().max_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new()); + /// + /// let a = [(1, 2)]; + /// assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]); + /// + /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)]; + /// assert_eq!(a.iter().max_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(3, 9), &(5, 9)]); + /// + /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)]; + /// assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn max_set_by(self, mut compare: F) -> Vec + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + extrema_set::max_set_impl( + self, + |_| (), + |x, y, _, _| compare(x, y) + ) + } + + /// Return all minimum elements of an iterator, as determined by + /// the specified function. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [(i32, i32); 0] = []; + /// assert_eq!(a.iter().max_set_by_key(|_| ()), Vec::<&(i32, i32)>::new()); + /// + /// let a = [(1, 2)]; + /// assert_eq!(a.iter().max_set_by_key(|&&(k,_)| k), vec![&(1, 2)]); + /// + /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)]; + /// assert_eq!(a.iter().max_set_by_key(|&&(_, k)| k), vec![&(3, 9), &(5, 9)]); + /// + /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)]; + /// assert_eq!(a.iter().max_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + #[cfg(feature = "use_std")] + fn max_set_by_key(self, key: F) -> Vec + where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + { + extrema_set::max_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky)) + } + + /// Return the minimum and maximum elements in the iterator. + /// + /// The return type `MinMaxResult` is an enum of three variants: + /// + /// - `NoElements` if the iterator is empty. + /// - `OneElement(x)` if the iterator has exactly one element. + /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two + /// values are equal if and only if there is more than one + /// element in the iterator and all elements are equal. + /// + /// On an iterator of length `n`, `minmax` does `1.5 * n` comparisons, + /// and so is faster than calling `min` and `max` separately which does + /// `2 * n` comparisons. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().minmax(), NoElements); + /// + /// let a = [1]; + /// assert_eq!(a.iter().minmax(), OneElement(&1)); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().minmax(), MinMax(&1, &5)); + /// + /// let a = [1, 1, 1, 1]; + /// assert_eq!(a.iter().minmax(), MinMax(&1, &1)); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + fn minmax(self) -> MinMaxResult + where Self: Sized, Self::Item: PartialOrd + { + minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) + } + + /// Return the minimum and maximum element of an iterator, as determined by + /// the specified function. + /// + /// The return value is a variant of [`MinMaxResult`] like for [`.minmax()`](Itertools::minmax). + /// + /// For the minimum, the first minimal element is returned. For the maximum, + /// the last maximal element wins. This matches the behavior of the standard + /// [`Iterator::min`] and [`Iterator::max`] methods. + /// + /// The keys can be floats but no particular result is guaranteed + /// if a key is NaN. + fn minmax_by_key(self, key: F) -> MinMaxResult + where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K + { + minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) + } + + /// Return the minimum and maximum element of an iterator, as determined by + /// the specified comparison function. + /// + /// The return value is a variant of [`MinMaxResult`] like for [`.minmax()`](Itertools::minmax). + /// + /// For the minimum, the first minimal element is returned. For the maximum, + /// the last maximal element wins. This matches the behavior of the standard + /// [`Iterator::min`] and [`Iterator::max`] methods. + fn minmax_by(self, mut compare: F) -> MinMaxResult + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + minmax::minmax_impl( + self, + |_| (), + |x, y, _, _| Ordering::Less == compare(x, y) + ) + } + + /// Return the position of the maximum element in the iterator. + /// + /// If several elements are equally maximum, the position of the + /// last of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_max(), None); + /// + /// let a = [-3, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_max(), Some(3)); + /// + /// let a = [1, 1, -1, -1]; + /// assert_eq!(a.iter().position_max(), Some(1)); + /// ``` + fn position_max(self) -> Option + where Self: Sized, Self::Item: Ord + { + self.enumerate() + .max_by(|x, y| Ord::cmp(&x.1, &y.1)) + .map(|x| x.0) + } + + /// Return the position of the maximum element in the iterator, as + /// determined by the specified function. + /// + /// If several elements are equally maximum, the position of the + /// last of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), None); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(4)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_max_by_key(|x| x.abs()), Some(3)); + /// ``` + fn position_max_by_key(self, mut key: F) -> Option + where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + { + self.enumerate() + .max_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) + .map(|x| x.0) + } + + /// Return the position of the maximum element in the iterator, as + /// determined by the specified comparison function. + /// + /// If several elements are equally maximum, the position of the + /// last of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), None); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(3)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_max_by(|x, y| x.cmp(y)), Some(1)); + /// ``` + fn position_max_by(self, mut compare: F) -> Option + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + self.enumerate() + .max_by(|x, y| compare(&x.1, &y.1)) + .map(|x| x.0) + } + + /// Return the position of the minimum element in the iterator. + /// + /// If several elements are equally minimum, the position of the + /// first of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_min(), None); + /// + /// let a = [-3, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_min(), Some(4)); + /// + /// let a = [1, 1, -1, -1]; + /// assert_eq!(a.iter().position_min(), Some(2)); + /// ``` + fn position_min(self) -> Option + where Self: Sized, Self::Item: Ord + { + self.enumerate() + .min_by(|x, y| Ord::cmp(&x.1, &y.1)) + .map(|x| x.0) + } + + /// Return the position of the minimum element in the iterator, as + /// determined by the specified function. + /// + /// If several elements are equally minimum, the position of the + /// first of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), None); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(1)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_min_by_key(|x| x.abs()), Some(0)); + /// ``` + fn position_min_by_key(self, mut key: F) -> Option + where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K + { + self.enumerate() + .min_by(|x, y| Ord::cmp(&key(&x.1), &key(&y.1))) + .map(|x| x.0) + } + + /// Return the position of the minimum element in the iterator, as + /// determined by the specified comparison function. + /// + /// If several elements are equally minimum, the position of the + /// first of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), None); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(4)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_min_by(|x, y| x.cmp(y)), Some(2)); + /// ``` + fn position_min_by(self, mut compare: F) -> Option + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + self.enumerate() + .min_by(|x, y| compare(&x.1, &y.1)) + .map(|x| x.0) + } + + /// Return the positions of the minimum and maximum elements in + /// the iterator. + /// + /// The return type [`MinMaxResult`] is an enum of three variants: + /// + /// - `NoElements` if the iterator is empty. + /// - `OneElement(xpos)` if the iterator has exactly one element. + /// - `MinMax(xpos, ypos)` is returned otherwise, where the + /// element at `xpos` ≤ the element at `ypos`. While the + /// referenced elements themselves may be equal, `xpos` cannot + /// be equal to `ypos`. + /// + /// On an iterator of length `n`, `position_minmax` does `1.5 * n` + /// comparisons, and so is faster than calling `position_min` and + /// `position_max` separately which does `2 * n` comparisons. + /// + /// For the minimum, if several elements are equally minimum, the + /// position of the first of them is returned. For the maximum, if + /// several elements are equally maximum, the position of the last + /// of them is returned. + /// + /// The elements can be floats but no particular result is + /// guaranteed if an element is NaN. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_minmax(), NoElements); + /// + /// let a = [10]; + /// assert_eq!(a.iter().position_minmax(), OneElement(0)); + /// + /// let a = [-3, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_minmax(), MinMax(4, 3)); + /// + /// let a = [1, 1, -1, -1]; + /// assert_eq!(a.iter().position_minmax(), MinMax(2, 1)); + /// ``` + fn position_minmax(self) -> MinMaxResult + where Self: Sized, Self::Item: PartialOrd + { + use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + match minmax::minmax_impl(self.enumerate(), |_| (), |x, y, _, _| x.1 < y.1) { + NoElements => NoElements, + OneElement(x) => OneElement(x.0), + MinMax(x, y) => MinMax(x.0, y.0), + } + } + + /// Return the postions of the minimum and maximum elements of an + /// iterator, as determined by the specified function. + /// + /// The return value is a variant of [`MinMaxResult`] like for + /// [`position_minmax`]. + /// + /// For the minimum, if several elements are equally minimum, the + /// position of the first of them is returned. For the maximum, if + /// several elements are equally maximum, the position of the last + /// of them is returned. + /// + /// The keys can be floats but no particular result is guaranteed + /// if a key is NaN. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), NoElements); + /// + /// let a = [10_i32]; + /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), OneElement(0)); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(1, 4)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_minmax_by_key(|x| x.abs()), MinMax(0, 3)); + /// ``` + /// + /// [`position_minmax`]: Self::position_minmax + fn position_minmax_by_key(self, mut key: F) -> MinMaxResult + where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K + { + use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + match self.enumerate().minmax_by_key(|e| key(&e.1)) { + NoElements => NoElements, + OneElement(x) => OneElement(x.0), + MinMax(x, y) => MinMax(x.0, y.0), + } + } + + /// Return the postions of the minimum and maximum elements of an + /// iterator, as determined by the specified comparison function. + /// + /// The return value is a variant of [`MinMaxResult`] like for + /// [`position_minmax`]. + /// + /// For the minimum, if several elements are equally minimum, the + /// position of the first of them is returned. For the maximum, if + /// several elements are equally maximum, the position of the last + /// of them is returned. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), NoElements); + /// + /// let a = [10_i32]; + /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), OneElement(0)); + /// + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(4, 3)); + /// + /// let a = [1_i32, 1, -1, -1]; + /// assert_eq!(a.iter().position_minmax_by(|x, y| x.cmp(y)), MinMax(2, 1)); + /// ``` + /// + /// [`position_minmax`]: Self::position_minmax + fn position_minmax_by(self, mut compare: F) -> MinMaxResult + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + use crate::MinMaxResult::{NoElements, OneElement, MinMax}; + match self.enumerate().minmax_by(|x, y| compare(&x.1, &y.1)) { + NoElements => NoElements, + OneElement(x) => OneElement(x.0), + MinMax(x, y) => MinMax(x.0, y.0), + } + } + + /// If the iterator yields exactly one element, that element will be returned, otherwise + /// an error will be returned containing an iterator that has the same output as the input + /// iterator. + /// + /// This provides an additional layer of validation over just calling `Iterator::next()`. + /// If your assumption that there should only be one element yielded is false this provides + /// the opportunity to detect and handle that, preventing errors at a distance. + /// + /// # Examples + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); + /// assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); + /// assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); + /// assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); + /// ``` + fn exactly_one(mut self) -> Result> + where + Self: Sized, + { + match self.next() { + Some(first) => { + match self.next() { + Some(second) => { + Err(ExactlyOneError::new(Some(Either::Left([first, second])), self)) + } + None => { + Ok(first) + } + } + } + None => Err(ExactlyOneError::new(None, self)), + } + } + + /// If the iterator yields no elements, Ok(None) will be returned. If the iterator yields + /// exactly one element, that element will be returned, otherwise an error will be returned + /// containing an iterator that has the same output as the input iterator. + /// + /// This provides an additional layer of validation over just calling `Iterator::next()`. + /// If your assumption that there should be at most one element yielded is false this provides + /// the opportunity to detect and handle that, preventing errors at a distance. + /// + /// # Examples + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!((0..10).filter(|&x| x == 2).at_most_one().unwrap(), Some(2)); + /// assert!((0..10).filter(|&x| x > 1 && x < 4).at_most_one().unwrap_err().eq(2..4)); + /// assert!((0..10).filter(|&x| x > 1 && x < 5).at_most_one().unwrap_err().eq(2..5)); + /// assert_eq!((0..10).filter(|&_| false).at_most_one().unwrap(), None); + /// ``` + fn at_most_one(mut self) -> Result, ExactlyOneError> + where + Self: Sized, + { + match self.next() { + Some(first) => { + match self.next() { + Some(second) => { + Err(ExactlyOneError::new(Some(Either::Left([first, second])), self)) + } + None => { + Ok(Some(first)) + } + } + } + None => Ok(None), + } + } + + /// An iterator adaptor that allows the user to peek at multiple `.next()` + /// values without advancing the base iterator. + /// + /// # Examples + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = (0..10).multipeek(); + /// assert_eq!(iter.peek(), Some(&0)); + /// assert_eq!(iter.peek(), Some(&1)); + /// assert_eq!(iter.peek(), Some(&2)); + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.peek(), Some(&1)); + /// ``` + #[cfg(feature = "use_alloc")] + fn multipeek(self) -> MultiPeek + where + Self: Sized, + { + multipeek_impl::multipeek(self) + } + + /// Collect the items in this iterator and return a `HashMap` which + /// contains each item that appears in the iterator and the number + /// of times it appears. + /// + /// # Examples + /// ``` + /// # use itertools::Itertools; + /// let counts = [1, 1, 1, 3, 3, 5].into_iter().counts(); + /// assert_eq!(counts[&1], 3); + /// assert_eq!(counts[&3], 2); + /// assert_eq!(counts[&5], 1); + /// assert_eq!(counts.get(&0), None); + /// ``` + #[cfg(feature = "use_std")] + fn counts(self) -> HashMap + where + Self: Sized, + Self::Item: Eq + Hash, + { + let mut counts = HashMap::new(); + self.for_each(|item| *counts.entry(item).or_default() += 1); + counts + } + + /// Collect the items in this iterator and return a `HashMap` which + /// contains each item that appears in the iterator and the number + /// of times it appears, + /// determining identity using a keying function. + /// + /// ``` + /// # use itertools::Itertools; + /// struct Character { + /// first_name: &'static str, + /// last_name: &'static str, + /// } + /// + /// let characters = + /// vec![ + /// Character { first_name: "Amy", last_name: "Pond" }, + /// Character { first_name: "Amy", last_name: "Wong" }, + /// Character { first_name: "Amy", last_name: "Santiago" }, + /// Character { first_name: "James", last_name: "Bond" }, + /// Character { first_name: "James", last_name: "Sullivan" }, + /// Character { first_name: "James", last_name: "Norington" }, + /// Character { first_name: "James", last_name: "Kirk" }, + /// ]; + /// + /// let first_name_frequency = + /// characters + /// .into_iter() + /// .counts_by(|c| c.first_name); + /// + /// assert_eq!(first_name_frequency["Amy"], 3); + /// assert_eq!(first_name_frequency["James"], 4); + /// assert_eq!(first_name_frequency.contains_key("Asha"), false); + /// ``` + #[cfg(feature = "use_std")] + fn counts_by(self, f: F) -> HashMap + where + Self: Sized, + K: Eq + Hash, + F: FnMut(Self::Item) -> K, + { + self.map(f).counts() + } + + /// Converts an iterator of tuples into a tuple of containers. + /// + /// `unzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each + /// column. + /// + /// This function is, in some sense, the opposite of [`multizip`]. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let inputs = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; + /// + /// let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = inputs + /// .into_iter() + /// .multiunzip(); + /// + /// assert_eq!(a, vec![1, 4, 7]); + /// assert_eq!(b, vec![2, 5, 8]); + /// assert_eq!(c, vec![3, 6, 9]); + /// ``` + fn multiunzip(self) -> FromI + where + Self: Sized + MultiUnzip, + { + MultiUnzip::multiunzip(self) + } +} + +impl Itertools for T where T: Iterator { } + +/// Return `true` if both iterables produce equal sequences +/// (elements pairwise equal and sequences of the same length), +/// `false` otherwise. +/// +/// [`IntoIterator`] enabled version of [`Iterator::eq`]. +/// +/// ``` +/// assert!(itertools::equal(vec![1, 2, 3], 1..4)); +/// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); +/// ``` +pub fn equal(a: I, b: J) -> bool + where I: IntoIterator, + J: IntoIterator, + I::Item: PartialEq +{ + a.into_iter().eq(b) +} + +/// Assert that two iterables produce equal sequences, with the same +/// semantics as [`equal(a, b)`](equal). +/// +/// **Panics** on assertion failure with a message that shows the +/// two iteration elements. +/// +/// ```ignore +/// assert_equal("exceed".split('c'), "excess".split('c')); +/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', +/// ``` +pub fn assert_equal(a: I, b: J) + where I: IntoIterator, + J: IntoIterator, + I::Item: fmt::Debug + PartialEq, + J::Item: fmt::Debug, +{ + let mut ia = a.into_iter(); + let mut ib = b.into_iter(); + let mut i = 0; + loop { + match (ia.next(), ib.next()) { + (None, None) => return, + (a, b) => { + let equal = match (&a, &b) { + (&Some(ref a), &Some(ref b)) => a == b, + _ => false, + }; + assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", + i=i, a=a, b=b); + i += 1; + } + } + } +} + +/// Partition a sequence using predicate `pred` so that elements +/// that map to `true` are placed before elements which map to `false`. +/// +/// The order within the partitions is arbitrary. +/// +/// Return the index of the split point. +/// +/// ``` +/// use itertools::partition; +/// +/// # // use repeated numbers to not promise any ordering +/// let mut data = [7, 1, 1, 7, 1, 1, 7]; +/// let split_index = partition(&mut data, |elt| *elt >= 3); +/// +/// assert_eq!(data, [7, 7, 7, 1, 1, 1, 1]); +/// assert_eq!(split_index, 3); +/// ``` +pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize + where I: IntoIterator, + I::IntoIter: DoubleEndedIterator, + F: FnMut(&A) -> bool +{ + let mut split_index = 0; + let mut iter = iter.into_iter(); + 'main: while let Some(front) = iter.next() { + if !pred(front) { + loop { + match iter.next_back() { + Some(back) => if pred(back) { + std::mem::swap(front, back); + break; + }, + None => break 'main, + } + } + } + split_index += 1; + } + split_index +} + +/// An enum used for controlling the execution of `fold_while`. +/// +/// See [`.fold_while()`](Itertools::fold_while) for more information. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum FoldWhile { + /// Continue folding with this value + Continue(T), + /// Fold is complete and will return this value + Done(T), +} + +impl FoldWhile { + /// Return the value in the continue or done. + pub fn into_inner(self) -> T { + match self { + FoldWhile::Continue(x) | FoldWhile::Done(x) => x, + } + } + + /// Return true if `self` is `Done`, false if it is `Continue`. + pub fn is_done(&self) -> bool { + match *self { + FoldWhile::Continue(_) => false, + FoldWhile::Done(_) => true, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/merge_join.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/merge_join.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/merge_join.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/merge_join.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,169 @@ +use std::cmp::Ordering; +use std::iter::Fuse; +use std::fmt; + +use super::adaptors::{PutBack, put_back}; +use crate::either_or_both::EitherOrBoth; +#[cfg(doc)] +use crate::Itertools; + +/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. +/// +/// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`]. +pub fn merge_join_by(left: I, right: J, cmp_fn: F) + -> MergeJoinBy + where I: IntoIterator, + J: IntoIterator, + F: FnMut(&I::Item, &J::Item) -> Ordering +{ + MergeJoinBy { + left: put_back(left.into_iter().fuse()), + right: put_back(right.into_iter().fuse()), + cmp_fn, + } +} + +/// An iterator adaptor that merge-joins items from the two base iterators in ascending order. +/// +/// See [`.merge_join_by()`](crate::Itertools::merge_join_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MergeJoinBy { + left: PutBack>, + right: PutBack>, + cmp_fn: F +} + +impl Clone for MergeJoinBy + where I: Iterator, + J: Iterator, + PutBack>: Clone, + PutBack>: Clone, + F: Clone, +{ + clone_fields!(left, right, cmp_fn); +} + +impl fmt::Debug for MergeJoinBy + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + J: Iterator + fmt::Debug, + J::Item: fmt::Debug, +{ + debug_fmt_fields!(MergeJoinBy, left, right); +} + +impl Iterator for MergeJoinBy + where I: Iterator, + J: Iterator, + F: FnMut(&I::Item, &J::Item) -> Ordering +{ + type Item = EitherOrBoth; + + fn next(&mut self) -> Option { + match (self.left.next(), self.right.next()) { + (None, None) => None, + (Some(left), None) => + Some(EitherOrBoth::Left(left)), + (None, Some(right)) => + Some(EitherOrBoth::Right(right)), + (Some(left), Some(right)) => { + match (self.cmp_fn)(&left, &right) { + Ordering::Equal => + Some(EitherOrBoth::Both(left, right)), + Ordering::Less => { + self.right.put_back(right); + Some(EitherOrBoth::Left(left)) + }, + Ordering::Greater => { + self.left.put_back(left); + Some(EitherOrBoth::Right(right)) + } + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.left.size_hint(); + let (b_lower, b_upper) = self.right.size_hint(); + + let lower = ::std::cmp::max(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + + (lower, upper) + } + + fn count(mut self) -> usize { + let mut count = 0; + loop { + match (self.left.next(), self.right.next()) { + (None, None) => break count, + (Some(_left), None) => break count + 1 + self.left.into_parts().1.count(), + (None, Some(_right)) => break count + 1 + self.right.into_parts().1.count(), + (Some(left), Some(right)) => { + count += 1; + match (self.cmp_fn)(&left, &right) { + Ordering::Equal => {} + Ordering::Less => self.right.put_back(right), + Ordering::Greater => self.left.put_back(left), + } + } + } + } + } + + fn last(mut self) -> Option { + let mut previous_element = None; + loop { + match (self.left.next(), self.right.next()) { + (None, None) => break previous_element, + (Some(left), None) => { + break Some(EitherOrBoth::Left( + self.left.into_parts().1.last().unwrap_or(left), + )) + } + (None, Some(right)) => { + break Some(EitherOrBoth::Right( + self.right.into_parts().1.last().unwrap_or(right), + )) + } + (Some(left), Some(right)) => { + previous_element = match (self.cmp_fn)(&left, &right) { + Ordering::Equal => Some(EitherOrBoth::Both(left, right)), + Ordering::Less => { + self.right.put_back(right); + Some(EitherOrBoth::Left(left)) + } + Ordering::Greater => { + self.left.put_back(left); + Some(EitherOrBoth::Right(right)) + } + } + } + } + } + } + + fn nth(&mut self, mut n: usize) -> Option { + loop { + if n == 0 { + break self.next(); + } + n -= 1; + match (self.left.next(), self.right.next()) { + (None, None) => break None, + (Some(_left), None) => break self.left.nth(n).map(EitherOrBoth::Left), + (None, Some(_right)) => break self.right.nth(n).map(EitherOrBoth::Right), + (Some(left), Some(right)) => match (self.cmp_fn)(&left, &right) { + Ordering::Equal => {} + Ordering::Less => self.right.put_back(right), + Ordering::Greater => self.left.put_back(left), + }, + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/minmax.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/minmax.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/minmax.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/minmax.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,115 @@ + +/// `MinMaxResult` is an enum returned by `minmax`. +/// +/// See [`.minmax()`](crate::Itertools::minmax) for more detail. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum MinMaxResult { + /// Empty iterator + NoElements, + + /// Iterator with one element, so the minimum and maximum are the same + OneElement(T), + + /// More than one element in the iterator, the first element is not larger + /// than the second + MinMax(T, T) +} + +impl MinMaxResult { + /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` + /// has variant `None` if and only if the `MinMaxResult` has variant + /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. + /// If the `MinMaxResult` has variant `OneElement(x)`, performing this + /// operation will make one clone of `x`. + /// + /// # Examples + /// + /// ``` + /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; + /// + /// let r: MinMaxResult = NoElements; + /// assert_eq!(r.into_option(), None); + /// + /// let r = OneElement(1); + /// assert_eq!(r.into_option(), Some((1, 1))); + /// + /// let r = MinMax(1, 2); + /// assert_eq!(r.into_option(), Some((1, 2))); + /// ``` + pub fn into_option(self) -> Option<(T,T)> { + match self { + MinMaxResult::NoElements => None, + MinMaxResult::OneElement(x) => Some((x.clone(), x)), + MinMaxResult::MinMax(x, y) => Some((x, y)) + } + } +} + +/// Implementation guts for `minmax` and `minmax_by_key`. +pub fn minmax_impl(mut it: I, mut key_for: F, + mut lt: L) -> MinMaxResult + where I: Iterator, + F: FnMut(&I::Item) -> K, + L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, +{ + let (mut min, mut max, mut min_key, mut max_key) = match it.next() { + None => return MinMaxResult::NoElements, + Some(x) => { + match it.next() { + None => return MinMaxResult::OneElement(x), + Some(y) => { + let xk = key_for(&x); + let yk = key_for(&y); + if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} + } + } + } + }; + + loop { + // `first` and `second` are the two next elements we want to look + // at. We first compare `first` and `second` (#1). The smaller one + // is then compared to current minimum (#2). The larger one is + // compared to current maximum (#3). This way we do 3 comparisons + // for 2 elements. + let first = match it.next() { + None => break, + Some(x) => x + }; + let second = match it.next() { + None => { + let first_key = key_for(&first); + if lt(&first, &min, &first_key, &min_key) { + min = first; + } else if !lt(&first, &max, &first_key, &max_key) { + max = first; + } + break; + } + Some(x) => x + }; + let first_key = key_for(&first); + let second_key = key_for(&second); + if !lt(&second, &first, &second_key, &first_key) { + if lt(&first, &min, &first_key, &min_key) { + min = first; + min_key = first_key; + } + if !lt(&second, &max, &second_key, &max_key) { + max = second; + max_key = second_key; + } + } else { + if lt(&second, &min, &second_key, &min_key) { + min = second; + min_key = second_key; + } + if !lt(&first, &max, &first_key, &max_key) { + max = first; + max_key = first_key; + } + } + } + + MinMaxResult::MinMax(min, max) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/multipeek_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/multipeek_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/multipeek_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/multipeek_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,101 @@ +use std::iter::Fuse; +use alloc::collections::VecDeque; +use crate::size_hint; +use crate::PeekingNext; +#[cfg(doc)] +use crate::Itertools; + +/// See [`multipeek()`] for more information. +#[derive(Clone, Debug)] +pub struct MultiPeek + where I: Iterator +{ + iter: Fuse, + buf: VecDeque, + index: usize, +} + +/// An iterator adaptor that allows the user to peek at multiple `.next()` +/// values without advancing the base iterator. +/// +/// [`IntoIterator`] enabled version of [`Itertools::multipeek`]. +pub fn multipeek(iterable: I) -> MultiPeek + where I: IntoIterator +{ + MultiPeek { + iter: iterable.into_iter().fuse(), + buf: VecDeque::new(), + index: 0, + } +} + +impl MultiPeek + where I: Iterator +{ + /// Reset the peeking “cursor” + pub fn reset_peek(&mut self) { + self.index = 0; + } +} + +impl MultiPeek { + /// Works exactly like `.next()` with the only difference that it doesn't + /// advance itself. `.peek()` can be called multiple times, to peek + /// further ahead. + /// When `.next()` is called, reset the peeking “cursor”. + pub fn peek(&mut self) -> Option<&I::Item> { + let ret = if self.index < self.buf.len() { + Some(&self.buf[self.index]) + } else { + match self.iter.next() { + Some(x) => { + self.buf.push_back(x); + Some(&self.buf[self.index]) + } + None => return None, + } + }; + + self.index += 1; + ret + } +} + +impl PeekingNext for MultiPeek + where I: Iterator, +{ + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool + { + if self.buf.is_empty() { + if let Some(r) = self.peek() { + if !accept(r) { return None } + } + } else if let Some(r) = self.buf.get(0) { + if !accept(r) { return None } + } + self.next() + } +} + +impl Iterator for MultiPeek + where I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + self.index = 0; + self.buf.pop_front().or_else(|| self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) + } +} + +// Same size +impl ExactSizeIterator for MultiPeek + where I: ExactSizeIterator +{} + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/pad_tail.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/pad_tail.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/pad_tail.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/pad_tail.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,96 @@ +use std::iter::{Fuse, FusedIterator}; +use crate::size_hint; + +/// An iterator adaptor that pads a sequence to a minimum length by filling +/// missing elements using a closure. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.pad_using()`](crate::Itertools::pad_using) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct PadUsing { + iter: Fuse, + min: usize, + pos: usize, + filler: F, +} + +impl std::fmt::Debug for PadUsing +where + I: std::fmt::Debug, +{ + debug_fmt_fields!(PadUsing, iter, min, pos); +} + +/// Create a new `PadUsing` iterator. +pub fn pad_using(iter: I, min: usize, filler: F) -> PadUsing + where I: Iterator, + F: FnMut(usize) -> I::Item +{ + PadUsing { + iter: iter.fuse(), + min, + pos: 0, + filler, + } +} + +impl Iterator for PadUsing + where I: Iterator, + F: FnMut(usize) -> I::Item +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + None => { + if self.pos < self.min { + let e = Some((self.filler)(self.pos)); + self.pos += 1; + e + } else { + None + } + }, + e => { + self.pos += 1; + e + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let tail = self.min.saturating_sub(self.pos); + size_hint::max(self.iter.size_hint(), (tail, Some(tail))) + } +} + +impl DoubleEndedIterator for PadUsing + where I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(usize) -> I::Item +{ + fn next_back(&mut self) -> Option { + if self.min == 0 { + self.iter.next_back() + } else if self.iter.len() >= self.min { + self.min -= 1; + self.iter.next_back() + } else { + self.min -= 1; + Some((self.filler)(self.min)) + } + } +} + +impl ExactSizeIterator for PadUsing + where I: ExactSizeIterator, + F: FnMut(usize) -> I::Item +{} + + +impl FusedIterator for PadUsing + where I: FusedIterator, + F: FnMut(usize) -> I::Item +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/peek_nth.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peek_nth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/peek_nth.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peek_nth.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,102 @@ +use crate::size_hint; +use crate::PeekingNext; +use alloc::collections::VecDeque; +use std::iter::Fuse; + +/// See [`peek_nth()`] for more information. +#[derive(Clone, Debug)] +pub struct PeekNth +where + I: Iterator, +{ + iter: Fuse, + buf: VecDeque, +} + +/// A drop-in replacement for [`std::iter::Peekable`] which adds a `peek_nth` +/// method allowing the user to `peek` at a value several iterations forward +/// without advancing the base iterator. +/// +/// This differs from `multipeek` in that subsequent calls to `peek` or +/// `peek_nth` will always return the same value until `next` is called +/// (making `reset_peek` unnecessary). +pub fn peek_nth(iterable: I) -> PeekNth +where + I: IntoIterator, +{ + PeekNth { + iter: iterable.into_iter().fuse(), + buf: VecDeque::new(), + } +} + +impl PeekNth +where + I: Iterator, +{ + /// Works exactly like the `peek` method in `std::iter::Peekable` + pub fn peek(&mut self) -> Option<&I::Item> { + self.peek_nth(0) + } + + /// Returns a reference to the `nth` value without advancing the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```rust + /// use itertools::peek_nth; + /// + /// let xs = vec![1,2,3]; + /// let mut iter = peek_nth(xs.iter()); + /// + /// assert_eq!(iter.peek_nth(0), Some(&&1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// // The iterator does not advance even if we call `peek_nth` multiple times + /// assert_eq!(iter.peek_nth(0), Some(&&2)); + /// assert_eq!(iter.peek_nth(1), Some(&&3)); + /// assert_eq!(iter.next(), Some(&2)); + /// + /// // Calling `peek_nth` past the end of the iterator will return `None` + /// assert_eq!(iter.peek_nth(1), None); + /// ``` + pub fn peek_nth(&mut self, n: usize) -> Option<&I::Item> { + let unbuffered_items = (n + 1).saturating_sub(self.buf.len()); + + self.buf.extend(self.iter.by_ref().take(unbuffered_items)); + + self.buf.get(n) + } +} + +impl Iterator for PeekNth +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + self.buf.pop_front().or_else(|| self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) + } +} + +impl ExactSizeIterator for PeekNth where I: ExactSizeIterator {} + +impl PeekingNext for PeekNth +where + I: Iterator, +{ + fn peeking_next(&mut self, accept: F) -> Option + where + F: FnOnce(&Self::Item) -> bool, + { + self.peek().filter(|item| accept(item))?; + self.next() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/peeking_take_while.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peeking_take_while.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/peeking_take_while.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/peeking_take_while.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,154 @@ +use std::iter::Peekable; +use crate::PutBack; +#[cfg(feature = "use_alloc")] +use crate::PutBackN; + +/// An iterator that allows peeking at an element before deciding to accept it. +/// +/// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while) +/// for more information. +/// +/// This is implemented by peeking adaptors like peekable and put back, +/// but also by a few iterators that can be peeked natively, like the slice’s +/// by reference iterator (`std::slice::Iter`). +pub trait PeekingNext : Iterator { + /// Pass a reference to the next iterator element to the closure `accept`; + /// if `accept` returns true, return it as the next element, + /// else None. + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool; +} + +impl PeekingNext for Peekable + where I: Iterator, +{ + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.peek() { + if !accept(r) { + return None; + } + } + self.next() + } +} + +impl PeekingNext for PutBack + where I: Iterator, +{ + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.next() { + if !accept(&r) { + self.put_back(r); + return None; + } + Some(r) + } else { + None + } + } +} + +#[cfg(feature = "use_alloc")] +impl PeekingNext for PutBackN + where I: Iterator, +{ + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.next() { + if !accept(&r) { + self.put_back(r); + return None; + } + Some(r) + } else { + None + } + } +} + +/// An iterator adaptor that takes items while a closure returns `true`. +/// +/// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct PeekingTakeWhile<'a, I: 'a, F> + where I: Iterator, +{ + iter: &'a mut I, + f: F, +} + +impl<'a, I: 'a, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F> +where + I: Iterator + std::fmt::Debug, +{ + debug_fmt_fields!(PeekingTakeWhile, iter); +} + +/// Create a `PeekingTakeWhile` +pub fn peeking_take_while(iter: &mut I, f: F) -> PeekingTakeWhile + where I: Iterator, +{ + PeekingTakeWhile { + iter, + f, + } +} + +impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> + where I: PeekingNext, + F: FnMut(&I::Item) -> bool, + +{ + type Item = I::Item; + fn next(&mut self) -> Option { + self.iter.peeking_next(&mut self.f) + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +// Some iterators are so lightweight we can simply clone them to save their +// state and use that for peeking. +macro_rules! peeking_next_by_clone { + ([$($typarm:tt)*] $type_:ty) => { + impl<$($typarm)*> PeekingNext for $type_ { + fn peeking_next(&mut self, accept: F) -> Option + where F: FnOnce(&Self::Item) -> bool + { + let saved_state = self.clone(); + if let Some(r) = self.next() { + if !accept(&r) { + *self = saved_state; + } else { + return Some(r) + } + } + None + } + } + } +} + +peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> } +peeking_next_by_clone! { ['a] ::std::str::Chars<'a> } +peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> } +peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> } +peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> } +peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> } +peeking_next_by_clone! { [T] ::std::iter::Empty } +#[cfg(feature = "use_alloc")] +peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> } +#[cfg(feature = "use_alloc")] +peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> } + +// cloning a Rev has no extra overhead; peekable and put backs are never DEI. +peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator] + ::std::iter::Rev } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/permutations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/permutations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/permutations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/permutations.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,277 @@ +use alloc::vec::Vec; +use std::fmt; +use std::iter::once; + +use super::lazy_buffer::LazyBuffer; + +/// An iterator adaptor that iterates through all the `k`-permutations of the +/// elements from an iterator. +/// +/// See [`.permutations()`](crate::Itertools::permutations) for +/// more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Permutations { + vals: LazyBuffer, + state: PermutationState, +} + +impl Clone for Permutations + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(vals, state); +} + +#[derive(Clone, Debug)] +enum PermutationState { + StartUnknownLen { + k: usize, + }, + OngoingUnknownLen { + k: usize, + min_n: usize, + }, + Complete(CompleteState), + Empty, +} + +#[derive(Clone, Debug)] +enum CompleteState { + Start { + n: usize, + k: usize, + }, + Ongoing { + indices: Vec, + cycles: Vec, + } +} + +enum CompleteStateRemaining { + Known(usize), + Overflow, +} + +impl fmt::Debug for Permutations + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Permutations, vals, state); +} + +pub fn permutations(iter: I, k: usize) -> Permutations { + let mut vals = LazyBuffer::new(iter); + + if k == 0 { + // Special case, yields single empty vec; `n` is irrelevant + let state = PermutationState::Complete(CompleteState::Start { n: 0, k: 0 }); + + return Permutations { + vals, + state + }; + } + + let mut enough_vals = true; + + while vals.len() < k { + if !vals.get_next() { + enough_vals = false; + break; + } + } + + let state = if enough_vals { + PermutationState::StartUnknownLen { k } + } else { + PermutationState::Empty + }; + + Permutations { + vals, + state + } +} + +impl Iterator for Permutations +where + I: Iterator, + I::Item: Clone +{ + type Item = Vec; + + fn next(&mut self) -> Option { + self.advance(); + + let &mut Permutations { ref vals, ref state } = self; + + match *state { + PermutationState::StartUnknownLen { .. } => panic!("unexpected iterator state"), + PermutationState::OngoingUnknownLen { k, min_n } => { + let latest_idx = min_n - 1; + let indices = (0..(k - 1)).chain(once(latest_idx)); + + Some(indices.map(|i| vals[i].clone()).collect()) + } + PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => { + let k = cycles.len(); + Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect()) + }, + PermutationState::Complete(CompleteState::Start { .. }) | PermutationState::Empty => None + } + } + + fn count(self) -> usize { + fn from_complete(complete_state: CompleteState) -> usize { + match complete_state.remaining() { + CompleteStateRemaining::Known(count) => count, + CompleteStateRemaining::Overflow => { + panic!("Iterator count greater than usize::MAX"); + } + } + } + + let Permutations { vals, state } = self; + match state { + PermutationState::StartUnknownLen { k } => { + let n = vals.len() + vals.it.count(); + let complete_state = CompleteState::Start { n, k }; + + from_complete(complete_state) + } + PermutationState::OngoingUnknownLen { k, min_n } => { + let prev_iteration_count = min_n - k + 1; + let n = vals.len() + vals.it.count(); + let complete_state = CompleteState::Start { n, k }; + + from_complete(complete_state) - prev_iteration_count + }, + PermutationState::Complete(state) => from_complete(state), + PermutationState::Empty => 0 + } + } + + fn size_hint(&self) -> (usize, Option) { + match self.state { + PermutationState::StartUnknownLen { .. } | + PermutationState::OngoingUnknownLen { .. } => (0, None), // TODO can we improve this lower bound? + PermutationState::Complete(ref state) => match state.remaining() { + CompleteStateRemaining::Known(count) => (count, Some(count)), + CompleteStateRemaining::Overflow => (::std::usize::MAX, None) + } + PermutationState::Empty => (0, Some(0)) + } + } +} + +impl Permutations +where + I: Iterator, + I::Item: Clone +{ + fn advance(&mut self) { + let &mut Permutations { ref mut vals, ref mut state } = self; + + *state = match *state { + PermutationState::StartUnknownLen { k } => { + PermutationState::OngoingUnknownLen { k, min_n: k } + } + PermutationState::OngoingUnknownLen { k, min_n } => { + if vals.get_next() { + PermutationState::OngoingUnknownLen { k, min_n: min_n + 1 } + } else { + let n = min_n; + let prev_iteration_count = n - k + 1; + let mut complete_state = CompleteState::Start { n, k }; + + // Advance the complete-state iterator to the correct point + for _ in 0..(prev_iteration_count + 1) { + complete_state.advance(); + } + + PermutationState::Complete(complete_state) + } + } + PermutationState::Complete(ref mut state) => { + state.advance(); + + return; + } + PermutationState::Empty => { return; } + }; + } +} + +impl CompleteState { + fn advance(&mut self) { + *self = match *self { + CompleteState::Start { n, k } => { + let indices = (0..n).collect(); + let cycles = ((n - k)..n).rev().collect(); + + CompleteState::Ongoing { + cycles, + indices + } + }, + CompleteState::Ongoing { ref mut indices, ref mut cycles } => { + let n = indices.len(); + let k = cycles.len(); + + for i in (0..k).rev() { + if cycles[i] == 0 { + cycles[i] = n - i - 1; + + let to_push = indices.remove(i); + indices.push(to_push); + } else { + let swap_index = n - cycles[i]; + indices.swap(i, swap_index); + + cycles[i] -= 1; + return; + } + } + + CompleteState::Start { n, k } + } + } + } + + fn remaining(&self) -> CompleteStateRemaining { + use self::CompleteStateRemaining::{Known, Overflow}; + + match *self { + CompleteState::Start { n, k } => { + if n < k { + return Known(0); + } + + let count: Option = (n - k + 1..n + 1).fold(Some(1), |acc, i| { + acc.and_then(|acc| acc.checked_mul(i)) + }); + + match count { + Some(count) => Known(count), + None => Overflow + } + } + CompleteState::Ongoing { ref indices, ref cycles } => { + let mut count: usize = 0; + + for (i, &c) in cycles.iter().enumerate() { + let radix = indices.len() - i; + let next_count = count.checked_mul(radix) + .and_then(|count| count.checked_add(c)); + + count = match next_count { + Some(count) => count, + None => { return Overflow; } + }; + } + + Known(count) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/powerset.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/powerset.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/powerset.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/powerset.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,90 @@ +use std::fmt; +use std::iter::FusedIterator; +use std::usize; +use alloc::vec::Vec; + +use super::combinations::{Combinations, combinations}; +use super::size_hint; + +/// An iterator to iterate through the powerset of the elements from an iterator. +/// +/// See [`.powerset()`](crate::Itertools::powerset) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Powerset { + combs: Combinations, + // Iterator `position` (equal to count of yielded elements). + pos: usize, +} + +impl Clone for Powerset + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(combs, pos); +} + +impl fmt::Debug for Powerset + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Powerset, combs, pos); +} + +/// Create a new `Powerset` from a clonable iterator. +pub fn powerset(src: I) -> Powerset + where I: Iterator, + I::Item: Clone, +{ + Powerset { + combs: combinations(src, 0), + pos: 0, + } +} + +impl Iterator for Powerset + where + I: Iterator, + I::Item: Clone, +{ + type Item = Vec; + + fn next(&mut self) -> Option { + if let Some(elt) = self.combs.next() { + self.pos = self.pos.saturating_add(1); + Some(elt) + } else if self.combs.k() < self.combs.n() + || self.combs.k() == 0 + { + self.combs.reset(self.combs.k() + 1); + self.combs.next().map(|elt| { + self.pos = self.pos.saturating_add(1); + elt + }) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + // Total bounds for source iterator. + let src_total = size_hint::add_scalar(self.combs.src().size_hint(), self.combs.n()); + + // Total bounds for self ( length(powerset(set) == 2 ^ length(set) ) + let self_total = size_hint::pow_scalar_base(2, src_total); + + if self.pos < usize::MAX { + // Subtract count of elements already yielded from total. + size_hint::sub_scalar(self_total, self.pos) + } else { + // Fallback: self.pos is saturated and no longer reliable. + (0, self_total.1) + } + } +} + +impl FusedIterator for Powerset + where + I: Iterator, + I::Item: Clone, +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/process_results_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/process_results_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/process_results_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/process_results_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,97 @@ + +/// An iterator that produces only the `T` values as long as the +/// inner iterator produces `Ok(T)`. +/// +/// Used by [`process_results`](crate::process_results), see its docs +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct ProcessResults<'a, I, E: 'a> { + error: &'a mut Result<(), E>, + iter: I, +} + +impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> + where I: Iterator> +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Ok(x)) => Some(x), + Some(Err(e)) => { + *self.error = Err(e); + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } + + fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let error = self.error; + self.iter + .try_fold(init, |acc, opt| match opt { + Ok(x) => Ok(f(acc, x)), + Err(e) => { + *error = Err(e); + Err(acc) + } + }) + .unwrap_or_else(|e| e) + } +} + +/// “Lift” a function of the values of an iterator so that it can process +/// an iterator of `Result` values instead. +/// +/// `iterable` is an iterator or iterable with `Result` elements, where +/// `T` is the value type and `E` the error type. +/// +/// `processor` is a closure that receives an adapted version of the iterable +/// as the only argument — the adapted iterator produces elements of type `T`, +/// as long as the original iterator produces `Ok` values. +/// +/// If the original iterable produces an error at any point, the adapted +/// iterator ends and the `process_results` function will return the +/// error iself. +/// +/// Otherwise, the return value from the closure is returned wrapped +/// inside `Ok`. +/// +/// # Example +/// +/// ``` +/// use itertools::process_results; +/// +/// type R = Result; +/// +/// let first_values: Vec = vec![Ok(1), Ok(0), Ok(3)]; +/// let second_values: Vec = vec![Ok(2), Ok(1), Err("overflow")]; +/// +/// // “Lift” the iterator .max() method to work on the values in Results using process_results +/// +/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); +/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); +/// +/// assert_eq!(first_max, Ok(3)); +/// assert!(second_max.is_err()); +/// ``` +pub fn process_results(iterable: I, processor: F) -> Result + where I: IntoIterator>, + F: FnOnce(ProcessResults) -> R +{ + let iter = iterable.into_iter(); + let mut error = Ok(()); + + let result = processor(ProcessResults { error: &mut error, iter }); + + error.map(|_| result) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/put_back_n_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/put_back_n_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/put_back_n_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/put_back_n_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,61 @@ +use alloc::vec::Vec; + +use crate::size_hint; + +/// An iterator adaptor that allows putting multiple +/// items in front of the iterator. +/// +/// Iterator element type is `I::Item`. +#[derive(Debug, Clone)] +pub struct PutBackN { + top: Vec, + iter: I, +} + +/// Create an iterator where you can put back multiple values to the front +/// of the iteration. +/// +/// Iterator element type is `I::Item`. +pub fn put_back_n(iterable: I) -> PutBackN + where I: IntoIterator +{ + PutBackN { + top: Vec::new(), + iter: iterable.into_iter(), + } +} + +impl PutBackN { + /// Puts x in front of the iterator. + /// The values are yielded in order of the most recently put back + /// values first. + /// + /// ```rust + /// use itertools::put_back_n; + /// + /// let mut it = put_back_n(1..5); + /// it.next(); + /// it.put_back(1); + /// it.put_back(0); + /// + /// assert!(itertools::equal(it, 0..5)); + /// ``` + #[inline] + pub fn put_back(&mut self, x: I::Item) { + self.top.push(x); + } +} + +impl Iterator for PutBackN { + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + self.top.pop().or_else(|| self.iter.next()) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + size_hint::add_scalar(self.iter.size_hint(), self.top.len()) + } +} + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/rciter_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/rciter_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/rciter_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/rciter_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,99 @@ + +use std::iter::{FusedIterator, IntoIterator}; +use alloc::rc::Rc; +use std::cell::RefCell; + +/// A wrapper for `Rc>`, that implements the `Iterator` trait. +#[derive(Debug)] +pub struct RcIter { + /// The boxed iterator. + pub rciter: Rc>, +} + +/// Return an iterator inside a `Rc>` wrapper. +/// +/// The returned `RcIter` can be cloned, and each clone will refer back to the +/// same original iterator. +/// +/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with +/// itself, at the cost of runtime borrow checking which may have a performance +/// penalty. +/// +/// Iterator element type is `Self::Item`. +/// +/// ``` +/// use itertools::rciter; +/// use itertools::zip; +/// +/// // In this example a range iterator is created and we iterate it using +/// // three separate handles (two of them given to zip). +/// // We also use the IntoIterator implementation for `&RcIter`. +/// +/// let mut iter = rciter(0..9); +/// let mut z = zip(&iter, &iter); +/// +/// assert_eq!(z.next(), Some((0, 1))); +/// assert_eq!(z.next(), Some((2, 3))); +/// assert_eq!(z.next(), Some((4, 5))); +/// assert_eq!(iter.next(), Some(6)); +/// assert_eq!(z.next(), Some((7, 8))); +/// assert_eq!(z.next(), None); +/// ``` +/// +/// **Panics** in iterator methods if a borrow error is encountered in the +/// iterator methods. It can only happen if the `RcIter` is reentered in +/// `.next()`, i.e. if it somehow participates in an “iterator knot” +/// where it is an adaptor of itself. +pub fn rciter(iterable: I) -> RcIter + where I: IntoIterator +{ + RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) } +} + +impl Clone for RcIter { + clone_fields!(rciter); +} + +impl Iterator for RcIter + where I: Iterator +{ + type Item = A; + #[inline] + fn next(&mut self) -> Option { + self.rciter.borrow_mut().next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + // To work sanely with other API that assume they own an iterator, + // so it can't change in other places, we can't guarantee as much + // in our size_hint. Other clones may drain values under our feet. + (0, self.rciter.borrow().size_hint().1) + } +} + +impl DoubleEndedIterator for RcIter + where I: DoubleEndedIterator +{ + #[inline] + fn next_back(&mut self) -> Option { + self.rciter.borrow_mut().next_back() + } +} + +/// Return an iterator from `&RcIter` (by simply cloning it). +impl<'a, I> IntoIterator for &'a RcIter + where I: Iterator +{ + type Item = I::Item; + type IntoIter = RcIter; + + fn into_iter(self) -> RcIter { + self.clone() + } +} + + +impl FusedIterator for RcIter + where I: FusedIterator +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/repeatn.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/repeatn.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/repeatn.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/repeatn.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,59 @@ +use std::iter::FusedIterator; + +/// An iterator that produces *n* repetitions of an element. +/// +/// See [`repeat_n()`](crate::repeat_n) for more information. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct RepeatN { + elt: Option, + n: usize, +} + +/// Create an iterator that produces `n` repetitions of `element`. +pub fn repeat_n(element: A, n: usize) -> RepeatN + where A: Clone, +{ + if n == 0 { + RepeatN { elt: None, n, } + } else { + RepeatN { elt: Some(element), n, } + } +} + +impl Iterator for RepeatN + where A: Clone +{ + type Item = A; + + fn next(&mut self) -> Option { + if self.n > 1 { + self.n -= 1; + self.elt.as_ref().cloned() + } else { + self.n = 0; + self.elt.take() + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.n, Some(self.n)) + } +} + +impl DoubleEndedIterator for RepeatN + where A: Clone +{ + #[inline] + fn next_back(&mut self) -> Option { + self.next() + } +} + +impl ExactSizeIterator for RepeatN + where A: Clone +{} + +impl FusedIterator for RepeatN + where A: Clone +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/size_hint.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/size_hint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/size_hint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/size_hint.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,119 @@ +//! Arithmetic on `Iterator.size_hint()` values. +//! + +use std::usize; +use std::cmp; +use std::u32; + +/// `SizeHint` is the return type of `Iterator::size_hint()`. +pub type SizeHint = (usize, Option); + +/// Add `SizeHint` correctly. +#[inline] +pub fn add(a: SizeHint, b: SizeHint) -> SizeHint { + let min = a.0.saturating_add(b.0); + let max = match (a.1, b.1) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + + (min, max) +} + +/// Add `x` correctly to a `SizeHint`. +#[inline] +pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_add(x); + hi = hi.and_then(|elt| elt.checked_add(x)); + (low, hi) +} + +/// Subtract `x` correctly from a `SizeHint`. +#[inline] +#[allow(dead_code)] +pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_sub(x); + hi = hi.map(|elt| elt.saturating_sub(x)); + (low, hi) +} + + +/// Multiply `SizeHint` correctly +/// +/// ```ignore +/// use std::usize; +/// use itertools::size_hint; +/// +/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))), +/// (9, Some(16))); +/// +/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)), +/// (usize::MAX, None)); +/// +/// assert_eq!(size_hint::mul((3, None), (0, Some(0))), +/// (0, Some(0))); +/// ``` +#[inline] +pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint { + let low = a.0.saturating_mul(b.0); + let hi = match (a.1, b.1) { + (Some(x), Some(y)) => x.checked_mul(y), + (Some(0), None) | (None, Some(0)) => Some(0), + _ => None, + }; + (low, hi) +} + +/// Multiply `x` correctly with a `SizeHint`. +#[inline] +pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_mul(x); + hi = hi.and_then(|elt| elt.checked_mul(x)); + (low, hi) +} + +/// Raise `base` correctly by a `SizeHint` exponent. +#[inline] +pub fn pow_scalar_base(base: usize, exp: SizeHint) -> SizeHint { + let exp_low = cmp::min(exp.0, u32::MAX as usize) as u32; + let low = base.saturating_pow(exp_low); + + let hi = exp.1.and_then(|exp| { + let exp_hi = cmp::min(exp, u32::MAX as usize) as u32; + base.checked_pow(exp_hi) + }); + + (low, hi) +} + +/// Return the maximum +#[inline] +pub fn max(a: SizeHint, b: SizeHint) -> SizeHint { + let (a_lower, a_upper) = a; + let (b_lower, b_upper) = b; + + let lower = cmp::max(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::max(x, y)), + _ => None, + }; + + (lower, upper) +} + +/// Return the minimum +#[inline] +pub fn min(a: SizeHint, b: SizeHint) -> SizeHint { + let (a_lower, a_upper) = a; + let (b_lower, b_upper) = b; + let lower = cmp::min(a_lower, b_lower); + let upper = match (a_upper, b_upper) { + (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)), + _ => a_upper.or(b_upper), + }; + (lower, upper) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/sources.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/sources.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/sources.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/sources.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,183 @@ +//! Iterators that are sources (produce elements from parameters, +//! not from another iterator). +#![allow(deprecated)] + +use std::fmt; +use std::mem; + +/// See [`repeat_call`](crate::repeat_call) for more information. +#[derive(Clone)] +#[deprecated(note="Use std repeat_with() instead", since="0.8.0")] +pub struct RepeatCall { + f: F, +} + +impl fmt::Debug for RepeatCall +{ + debug_fmt_fields!(RepeatCall, ); +} + +/// An iterator source that produces elements indefinitely by calling +/// a given closure. +/// +/// Iterator element type is the return type of the closure. +/// +/// ``` +/// use itertools::repeat_call; +/// use itertools::Itertools; +/// use std::collections::BinaryHeap; +/// +/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); +/// +/// // extract each element in sorted order +/// for element in repeat_call(|| heap.pop()).while_some() { +/// print!("{}", element); +/// } +/// +/// itertools::assert_equal( +/// repeat_call(|| 1).take(5), +/// vec![1, 1, 1, 1, 1] +/// ); +/// ``` +#[deprecated(note="Use std repeat_with() instead", since="0.8.0")] +pub fn repeat_call(function: F) -> RepeatCall + where F: FnMut() -> A +{ + RepeatCall { f: function } +} + +impl Iterator for RepeatCall + where F: FnMut() -> A +{ + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + Some((self.f)()) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} + +/// Creates a new unfold source with the specified closure as the "iterator +/// function" and an initial state to eventually pass to the closure +/// +/// `unfold` is a general iterator builder: it has a mutable state value, +/// and a closure with access to the state that produces the next value. +/// +/// This more or less equivalent to a regular struct with an [`Iterator`] +/// implementation, and is useful for one-off iterators. +/// +/// ``` +/// // an iterator that yields sequential Fibonacci numbers, +/// // and stops at the maximum representable value. +/// +/// use itertools::unfold; +/// +/// let mut fibonacci = unfold((1u32, 1u32), |(x1, x2)| { +/// // Attempt to get the next Fibonacci number +/// let next = x1.saturating_add(*x2); +/// +/// // Shift left: ret <- x1 <- x2 <- next +/// let ret = *x1; +/// *x1 = *x2; +/// *x2 = next; +/// +/// // If addition has saturated at the maximum, we are finished +/// if ret == *x1 && ret > 1 { +/// None +/// } else { +/// Some(ret) +/// } +/// }); +/// +/// itertools::assert_equal(fibonacci.by_ref().take(8), +/// vec![1, 1, 2, 3, 5, 8, 13, 21]); +/// assert_eq!(fibonacci.last(), Some(2_971_215_073)) +/// ``` +pub fn unfold(initial_state: St, f: F) -> Unfold + where F: FnMut(&mut St) -> Option +{ + Unfold { + f, + state: initial_state, + } +} + +impl fmt::Debug for Unfold + where St: fmt::Debug, +{ + debug_fmt_fields!(Unfold, state); +} + +/// See [`unfold`](crate::unfold) for more information. +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Unfold { + f: F, + /// Internal state that will be passed to the closure on the next iteration + pub state: St, +} + +impl Iterator for Unfold + where F: FnMut(&mut St) -> Option +{ + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } +} + +/// An iterator that infinitely applies function to value and yields results. +/// +/// This `struct` is created by the [`iterate()`](crate::iterate) function. +/// See its documentation for more. +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Iterate { + state: St, + f: F, +} + +impl fmt::Debug for Iterate + where St: fmt::Debug, +{ + debug_fmt_fields!(Iterate, state); +} + +impl Iterator for Iterate + where F: FnMut(&St) -> St +{ + type Item = St; + + #[inline] + fn next(&mut self) -> Option { + let next_state = (self.f)(&self.state); + Some(mem::replace(&mut self.state, next_state)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} + +/// Creates a new iterator that infinitely applies function to value and yields results. +/// +/// ``` +/// use itertools::iterate; +/// +/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); +/// ``` +pub fn iterate(initial_value: St, f: F) -> Iterate + where F: FnMut(&St) -> St +{ + Iterate { + state: initial_value, + f, + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/tee.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tee.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/tee.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tee.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,78 @@ +use super::size_hint; + +use std::cell::RefCell; +use alloc::collections::VecDeque; +use alloc::rc::Rc; + +/// Common buffer object for the two tee halves +#[derive(Debug)] +struct TeeBuffer { + backlog: VecDeque, + iter: I, + /// The owner field indicates which id should read from the backlog + owner: bool, +} + +/// One half of an iterator pair where both return the same elements. +/// +/// See [`.tee()`](crate::Itertools::tee) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct Tee + where I: Iterator +{ + rcbuffer: Rc>>, + id: bool, +} + +pub fn new(iter: I) -> (Tee, Tee) + where I: Iterator +{ + let buffer = TeeBuffer{backlog: VecDeque::new(), iter, owner: false}; + let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true}; + let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false}; + (t1, t2) +} + +impl Iterator for Tee + where I: Iterator, + I::Item: Clone +{ + type Item = I::Item; + fn next(&mut self) -> Option { + // .borrow_mut may fail here -- but only if the user has tied some kind of weird + // knot where the iterator refers back to itself. + let mut buffer = self.rcbuffer.borrow_mut(); + if buffer.owner == self.id { + match buffer.backlog.pop_front() { + None => {} + some_elt => return some_elt, + } + } + match buffer.iter.next() { + None => None, + Some(elt) => { + buffer.backlog.push_back(elt.clone()); + buffer.owner = !self.id; + Some(elt) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let buffer = self.rcbuffer.borrow(); + let sh = buffer.iter.size_hint(); + + if buffer.owner == self.id { + let log_len = buffer.backlog.len(); + size_hint::add_scalar(sh, log_len) + } else { + sh + } + } +} + +impl ExactSizeIterator for Tee + where I: ExactSizeIterator, + I::Item: Clone +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/tuple_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tuple_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/tuple_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/tuple_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,331 @@ +//! Some iterator that produces tuples + +use std::iter::Fuse; +use std::iter::FusedIterator; +use std::iter::Take; +use std::iter::Cycle; +use std::marker::PhantomData; + +// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing +// tuple-related methods to be used by clients in generic contexts, while +// hiding the implementation details of `TupleCollect`. +// See https://github.com/rust-itertools/itertools/issues/387 + +/// Implemented for homogeneous tuples of size up to 12. +pub trait HomogeneousTuple + : TupleCollect +{} + +impl HomogeneousTuple for T {} + +/// An iterator over a incomplete tuple. +/// +/// See [`.tuples()`](crate::Itertools::tuples) and +/// [`Tuples::into_buffer()`]. +#[derive(Clone, Debug)] +pub struct TupleBuffer + where T: HomogeneousTuple +{ + cur: usize, + buf: T::Buffer, +} + +impl TupleBuffer + where T: HomogeneousTuple +{ + fn new(buf: T::Buffer) -> Self { + TupleBuffer { + cur: 0, + buf, + } + } +} + +impl Iterator for TupleBuffer + where T: HomogeneousTuple +{ + type Item = T::Item; + + fn next(&mut self) -> Option { + let s = self.buf.as_mut(); + if let Some(ref mut item) = s.get_mut(self.cur) { + self.cur += 1; + item.take() + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let buffer = &self.buf.as_ref()[self.cur..]; + let len = if buffer.is_empty() { + 0 + } else { + buffer.iter() + .position(|x| x.is_none()) + .unwrap_or_else(|| buffer.len()) + }; + (len, Some(len)) + } +} + +impl ExactSizeIterator for TupleBuffer + where T: HomogeneousTuple +{ +} + +/// An iterator that groups the items in tuples of a specific size. +/// +/// See [`.tuples()`](crate::Itertools::tuples) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Tuples + where I: Iterator, + T: HomogeneousTuple +{ + iter: Fuse, + buf: T::Buffer, +} + +/// Create a new tuples iterator. +pub fn tuples(iter: I) -> Tuples + where I: Iterator, + T: HomogeneousTuple +{ + Tuples { + iter: iter.fuse(), + buf: Default::default(), + } +} + +impl Iterator for Tuples + where I: Iterator, + T: HomogeneousTuple +{ + type Item = T; + + fn next(&mut self) -> Option { + T::collect_from_iter(&mut self.iter, &mut self.buf) + } +} + +impl Tuples + where I: Iterator, + T: HomogeneousTuple +{ + /// Return a buffer with the produced items that was not enough to be grouped in a tuple. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = (0..5).tuples(); + /// assert_eq!(Some((0, 1, 2)), iter.next()); + /// assert_eq!(None, iter.next()); + /// itertools::assert_equal(vec![3, 4], iter.into_buffer()); + /// ``` + pub fn into_buffer(self) -> TupleBuffer { + TupleBuffer::new(self.buf) + } +} + + +/// An iterator over all contiguous windows that produces tuples of a specific size. +/// +/// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct TupleWindows + where I: Iterator, + T: HomogeneousTuple +{ + iter: I, + last: Option, +} + +/// Create a new tuple windows iterator. +pub fn tuple_windows(mut iter: I) -> TupleWindows + where I: Iterator, + T: HomogeneousTuple, + T::Item: Clone +{ + use std::iter::once; + + let mut last = None; + if T::num_items() != 1 { + // put in a duplicate item in front of the tuple; this simplifies + // .next() function. + if let Some(item) = iter.next() { + let iter = once(item.clone()).chain(once(item)).chain(&mut iter); + last = T::collect_from_iter_no_buf(iter); + } + } + + TupleWindows { + iter, + last, + } +} + +impl Iterator for TupleWindows + where I: Iterator, + T: HomogeneousTuple + Clone, + T::Item: Clone +{ + type Item = T; + + fn next(&mut self) -> Option { + if T::num_items() == 1 { + return T::collect_from_iter_no_buf(&mut self.iter) + } + if let Some(ref mut last) = self.last { + if let Some(new) = self.iter.next() { + last.left_shift_push(new); + return Some(last.clone()); + } + } + None + } +} + +impl FusedIterator for TupleWindows + where I: FusedIterator, + T: HomogeneousTuple + Clone, + T::Item: Clone +{} + +/// An iterator over all windows,wrapping back to the first elements when the +/// window would otherwise exceed the length of the iterator, producing tuples +/// of a specific size. +/// +/// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct CircularTupleWindows + where I: Iterator + Clone, + T: TupleCollect + Clone +{ + iter: Take, T>>, + phantom_data: PhantomData +} + +pub fn circular_tuple_windows(iter: I) -> CircularTupleWindows + where I: Iterator + Clone + ExactSizeIterator, + T: TupleCollect + Clone, + T::Item: Clone +{ + let len = iter.len(); + let iter = tuple_windows(iter.cycle()).take(len); + + CircularTupleWindows { + iter, + phantom_data: PhantomData{} + } +} + +impl Iterator for CircularTupleWindows + where I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone +{ + type Item = T; + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +pub trait TupleCollect: Sized { + type Item; + type Buffer: Default + AsRef<[Option]> + AsMut<[Option]>; + + fn collect_from_iter(iter: I, buf: &mut Self::Buffer) -> Option + where I: IntoIterator; + + fn collect_from_iter_no_buf(iter: I) -> Option + where I: IntoIterator; + + fn num_items() -> usize; + + fn left_shift_push(&mut self, item: Self::Item); +} + +macro_rules! count_ident{ + () => {0}; + ($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)}; +} +macro_rules! rev_for_each_ident{ + ($m:ident, ) => {}; + ($m:ident, $i0:ident, $($i:ident,)*) => { + rev_for_each_ident!($m, $($i,)*); + $m!($i0); + }; +} + +macro_rules! impl_tuple_collect { + ($dummy:ident,) => {}; // stop + ($dummy:ident, $($Y:ident,)*) => ( + impl_tuple_collect!($($Y,)*); + impl TupleCollect for ($(ignore_ident!($Y, A),)*) { + type Item = A; + type Buffer = [Option; count_ident!($($Y,)*) - 1]; + + #[allow(unused_assignments, unused_mut)] + fn collect_from_iter(iter: I, buf: &mut Self::Buffer) -> Option + where I: IntoIterator + { + let mut iter = iter.into_iter(); + $( + let mut $Y = None; + )* + + loop { + $( + $Y = iter.next(); + if $Y.is_none() { + break + } + )* + return Some(($($Y.unwrap()),*,)) + } + + let mut i = 0; + let mut s = buf.as_mut(); + $( + if i < s.len() { + s[i] = $Y; + i += 1; + } + )* + return None; + } + + fn collect_from_iter_no_buf(iter: I) -> Option + where I: IntoIterator + { + let mut iter = iter.into_iter(); + + Some(($( + { let $Y = iter.next()?; $Y }, + )*)) + } + + fn num_items() -> usize { + count_ident!($($Y,)*) + } + + fn left_shift_push(&mut self, mut item: A) { + use std::mem::replace; + + let &mut ($(ref mut $Y),*,) = self; + macro_rules! replace_item{($i:ident) => { + item = replace($i, item); + }} + rev_for_each_ident!(replace_item, $($Y,)*); + drop(item); + } + } + ) +} +impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/unique_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unique_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/unique_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unique_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,179 @@ +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use std::hash::Hash; +use std::fmt; +use std::iter::FusedIterator; + +/// An iterator adapter to filter out duplicate elements. +/// +/// See [`.unique_by()`](crate::Itertools::unique) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct UniqueBy { + iter: I, + // Use a Hashmap for the Entry API in order to prevent hashing twice. + // This can maybe be replaced with a HashSet once `get_or_insert_with` + // or a proper Entry API for Hashset is stable and meets this msrv + used: HashMap, + f: F, +} + +impl fmt::Debug for UniqueBy + where I: Iterator + fmt::Debug, + V: fmt::Debug + Hash + Eq, +{ + debug_fmt_fields!(UniqueBy, iter, used); +} + +/// Create a new `UniqueBy` iterator. +pub fn unique_by(iter: I, f: F) -> UniqueBy + where V: Eq + Hash, + F: FnMut(&I::Item) -> V, + I: Iterator, +{ + UniqueBy { + iter, + used: HashMap::new(), + f, + } +} + +// count the number of new unique keys in iterable (`used` is the set already seen) +fn count_new_keys(mut used: HashMap, iterable: I) -> usize + where I: IntoIterator, + K: Hash + Eq, +{ + let iter = iterable.into_iter(); + let current_used = used.len(); + used.extend(iter.map(|key| (key, ()))); + used.len() - current_used +} + +impl Iterator for UniqueBy + where I: Iterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + while let Some(v) = self.iter.next() { + let key = (self.f)(&v); + if self.used.insert(key, ()).is_none() { + return Some(v); + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (low, hi) = self.iter.size_hint(); + ((low > 0 && self.used.is_empty()) as usize, hi) + } + + fn count(self) -> usize { + let mut key_f = self.f; + count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) + } +} + +impl DoubleEndedIterator for UniqueBy + where I: DoubleEndedIterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V +{ + fn next_back(&mut self) -> Option { + while let Some(v) = self.iter.next_back() { + let key = (self.f)(&v); + if self.used.insert(key, ()).is_none() { + return Some(v); + } + } + None + } +} + +impl FusedIterator for UniqueBy + where I: FusedIterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V +{} + +impl Iterator for Unique + where I: Iterator, + I::Item: Eq + Hash + Clone +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + while let Some(v) = self.iter.iter.next() { + if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let elt = entry.key().clone(); + entry.insert(()); + return Some(elt); + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (low, hi) = self.iter.iter.size_hint(); + ((low > 0 && self.iter.used.is_empty()) as usize, hi) + } + + fn count(self) -> usize { + count_new_keys(self.iter.used, self.iter.iter) + } +} + +impl DoubleEndedIterator for Unique + where I: DoubleEndedIterator, + I::Item: Eq + Hash + Clone +{ + fn next_back(&mut self) -> Option { + while let Some(v) = self.iter.iter.next_back() { + if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let elt = entry.key().clone(); + entry.insert(()); + return Some(elt); + } + } + None + } +} + +impl FusedIterator for Unique + where I: FusedIterator, + I::Item: Eq + Hash + Clone +{} + +/// An iterator adapter to filter out duplicate elements. +/// +/// See [`.unique()`](crate::Itertools::unique) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Unique { + iter: UniqueBy, +} + +impl fmt::Debug for Unique + where I: Iterator + fmt::Debug, + I::Item: Hash + Eq + fmt::Debug, +{ + debug_fmt_fields!(Unique, iter); +} + +pub fn unique(iter: I) -> Unique + where I: Iterator, + I::Item: Eq + Hash, +{ + Unique { + iter: UniqueBy { + iter, + used: HashMap::new(), + f: (), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/unziptuple.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unziptuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/unziptuple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/unziptuple.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,80 @@ +/// Converts an iterator of tuples into a tuple of containers. +/// +/// `unzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each +/// column. +/// +/// This function is, in some sense, the opposite of [`multizip`]. +/// +/// ``` +/// use itertools::multiunzip; +/// +/// let inputs = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; +/// +/// let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(inputs); +/// +/// assert_eq!(a, vec![1, 4, 7]); +/// assert_eq!(b, vec![2, 5, 8]); +/// assert_eq!(c, vec![3, 6, 9]); +/// ``` +/// +/// [`multizip`]: crate::multizip +pub fn multiunzip(i: I) -> FromI +where + I: IntoIterator, + I::IntoIter: MultiUnzip, +{ + i.into_iter().multiunzip() +} + +/// An iterator that can be unzipped into multiple collections. +/// +/// See [`.multiunzip()`](crate::Itertools::multiunzip) for more information. +pub trait MultiUnzip: Iterator { + /// Unzip this iterator into multiple collections. + fn multiunzip(self) -> FromI; +} + +macro_rules! impl_unzip_iter { + ($($T:ident => $FromT:ident),*) => ( + #[allow(non_snake_case)] + impl, $($T, $FromT: Default + Extend<$T>),* > MultiUnzip<($($FromT,)*)> for IT { + fn multiunzip(self) -> ($($FromT,)*) { + // This implementation mirrors the logic of Iterator::unzip resp. Extend for (A, B) as close as possible. + // Unfortunately a lot of the used api there is still unstable (https://github.com/rust-lang/rust/issues/72631). + // + // Iterator::unzip: https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2825-2865 + // Extend for (A, B): https://doc.rust-lang.org/src/core/iter/traits/collect.rs.html#370-411 + + let mut res = ($($FromT::default(),)*); + let ($($FromT,)*) = &mut res; + + // Still unstable #72631 + // let (lower_bound, _) = self.size_hint(); + // if lower_bound > 0 { + // $($FromT.extend_reserve(lower_bound);)* + // } + + self.fold((), |(), ($($T,)*)| { + // Still unstable #72631 + // $( $FromT.extend_one($T); )* + $( $FromT.extend(std::iter::once($T)); )* + }); + res + } + } + ); +} + +impl_unzip_iter!(); +impl_unzip_iter!(A => FromA); +impl_unzip_iter!(A => FromA, B => FromB); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK, L => FromL); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/with_position.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/with_position.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/with_position.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/with_position.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,100 @@ +use std::iter::{Fuse,Peekable, FusedIterator}; + +/// An iterator adaptor that wraps each element in an [`Position`]. +/// +/// Iterator element type is `Position`. +/// +/// See [`.with_position()`](crate::Itertools::with_position) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct WithPosition + where I: Iterator, +{ + handled_first: bool, + peekable: Peekable>, +} + +impl Clone for WithPosition + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(handled_first, peekable); +} + +/// Create a new `WithPosition` iterator. +pub fn with_position(iter: I) -> WithPosition + where I: Iterator, +{ + WithPosition { + handled_first: false, + peekable: iter.fuse().peekable(), + } +} + +/// A value yielded by `WithPosition`. +/// Indicates the position of this element in the iterator results. +/// +/// See [`.with_position()`](crate::Itertools::with_position) for more information. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Position { + /// This is the first element. + First(T), + /// This is neither the first nor the last element. + Middle(T), + /// This is the last element. + Last(T), + /// This is the only element. + Only(T), +} + +impl Position { + /// Return the inner value. + pub fn into_inner(self) -> T { + match self { + Position::First(x) | + Position::Middle(x) | + Position::Last(x) | + Position::Only(x) => x, + } + } +} + +impl Iterator for WithPosition { + type Item = Position; + + fn next(&mut self) -> Option { + match self.peekable.next() { + Some(item) => { + if !self.handled_first { + // Haven't seen the first item yet, and there is one to give. + self.handled_first = true; + // Peek to see if this is also the last item, + // in which case tag it as `Only`. + match self.peekable.peek() { + Some(_) => Some(Position::First(item)), + None => Some(Position::Only(item)), + } + } else { + // Have seen the first item, and there's something left. + // Peek to see if this is the last item. + match self.peekable.peek() { + Some(_) => Some(Position::Middle(item)), + None => Some(Position::Last(item)), + } + } + } + // Iterator is finished. + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + self.peekable.size_hint() + } +} + +impl ExactSizeIterator for WithPosition + where I: ExactSizeIterator, +{ } + +impl FusedIterator for WithPosition +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_eq_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_eq_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_eq_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_eq_impl.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,60 @@ +use super::size_hint; + +/// An iterator which iterates two other iterators simultaneously +/// +/// See [`.zip_eq()`](crate::Itertools::zip_eq) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct ZipEq { + a: I, + b: J, +} + +/// Iterate `i` and `j` in lock step. +/// +/// **Panics** if the iterators are not of the same length. +/// +/// [`IntoIterator`] enabled version of [`Itertools::zip_eq`](crate::Itertools::zip_eq). +/// +/// ``` +/// use itertools::zip_eq; +/// +/// let data = [1, 2, 3, 4, 5]; +/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { +/// /* loop body */ +/// } +/// ``` +pub fn zip_eq(i: I, j: J) -> ZipEq + where I: IntoIterator, + J: IntoIterator +{ + ZipEq { + a: i.into_iter(), + b: j.into_iter(), + } +} + +impl Iterator for ZipEq + where I: Iterator, + J: Iterator +{ + type Item = (I::Item, J::Item); + + fn next(&mut self) -> Option { + match (self.a.next(), self.b.next()) { + (None, None) => None, + (Some(a), Some(b)) => Some((a, b)), + (None, Some(_)) | (Some(_), None) => + panic!("itertools: .zip_eq() reached end of one iterator before the other") + } + } + + fn size_hint(&self) -> (usize, Option) { + size_hint::min(self.a.size_hint(), self.b.size_hint()) + } +} + +impl ExactSizeIterator for ZipEq + where I: ExactSizeIterator, + J: ExactSizeIterator +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_longest.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_longest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_longest.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/zip_longest.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,83 @@ +use std::cmp::Ordering::{Equal, Greater, Less}; +use super::size_hint; +use std::iter::{Fuse, FusedIterator}; + +use crate::either_or_both::EitherOrBoth; + +// ZipLongest originally written by SimonSapin, +// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283 + +/// An iterator which iterates two other iterators simultaneously +/// +/// This iterator is *fused*. +/// +/// See [`.zip_longest()`](crate::Itertools::zip_longest) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct ZipLongest { + a: Fuse, + b: Fuse, +} + +/// Create a new `ZipLongest` iterator. +pub fn zip_longest(a: T, b: U) -> ZipLongest + where T: Iterator, + U: Iterator +{ + ZipLongest { + a: a.fuse(), + b: b.fuse(), + } +} + +impl Iterator for ZipLongest + where T: Iterator, + U: Iterator +{ + type Item = EitherOrBoth; + + #[inline] + fn next(&mut self) -> Option { + match (self.a.next(), self.b.next()) { + (None, None) => None, + (Some(a), None) => Some(EitherOrBoth::Left(a)), + (None, Some(b)) => Some(EitherOrBoth::Right(b)), + (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + size_hint::max(self.a.size_hint(), self.b.size_hint()) + } +} + +impl DoubleEndedIterator for ZipLongest + where T: DoubleEndedIterator + ExactSizeIterator, + U: DoubleEndedIterator + ExactSizeIterator +{ + #[inline] + fn next_back(&mut self) -> Option { + match self.a.len().cmp(&self.b.len()) { + Equal => match (self.a.next_back(), self.b.next_back()) { + (None, None) => None, + (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), + // These can only happen if .len() is inconsistent with .next_back() + (Some(a), None) => Some(EitherOrBoth::Left(a)), + (None, Some(b)) => Some(EitherOrBoth::Right(b)), + }, + Greater => self.a.next_back().map(EitherOrBoth::Left), + Less => self.b.next_back().map(EitherOrBoth::Right), + } + } +} + +impl ExactSizeIterator for ZipLongest + where T: ExactSizeIterator, + U: ExactSizeIterator +{} + +impl FusedIterator for ZipLongest + where T: Iterator, + U: Iterator +{} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/ziptuple.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/ziptuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/src/ziptuple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/src/ziptuple.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,138 @@ +use super::size_hint; + +/// See [`multizip`] for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Zip { + t: T, +} + +/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. +/// +/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that +/// implement [`IntoIterator`]) and yields elements +/// until any of the subiterators yields `None`. +/// +/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the +/// element types of the subiterator. +/// +/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J, +/// ..)>` of each component iterator `I, J, ...`) if each component iterator is +/// nameable. +/// +/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the +/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed. +/// +/// ``` +/// use itertools::multizip; +/// +/// // iterate over three sequences side-by-side +/// let mut results = [0, 0, 0, 0]; +/// let inputs = [3, 7, 9, 6]; +/// +/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) { +/// *r = index * 10 + input; +/// } +/// +/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); +/// ``` +/// [`izip!()`]: crate::izip +pub fn multizip(t: U) -> Zip + where Zip: From, + Zip: Iterator, +{ + Zip::from(t) +} + +macro_rules! impl_zip_iter { + ($($B:ident),*) => ( + #[allow(non_snake_case)] + impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> { + fn from(t: ($($B,)*)) -> Self { + let ($($B,)*) = t; + Zip { t: ($($B.into_iter(),)*) } + } + } + + #[allow(non_snake_case)] + #[allow(unused_assignments)] + impl<$($B),*> Iterator for Zip<($($B,)*)> + where + $( + $B: Iterator, + )* + { + type Item = ($($B::Item,)*); + + fn next(&mut self) -> Option + { + let ($(ref mut $B,)*) = self.t; + + // NOTE: Just like iter::Zip, we check the iterators + // for None in order. We may finish unevenly (some + // iterators gave n + 1 elements, some only n). + $( + let $B = match $B.next() { + None => return None, + Some(elt) => elt + }; + )* + Some(($($B,)*)) + } + + fn size_hint(&self) -> (usize, Option) + { + let sh = (::std::usize::MAX, None); + let ($(ref $B,)*) = self.t; + $( + let sh = size_hint::min($B.size_hint(), sh); + )* + sh + } + } + + #[allow(non_snake_case)] + impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where + $( + $B: ExactSizeIterator, + )* + { } + + #[allow(non_snake_case)] + impl<$($B),*> DoubleEndedIterator for Zip<($($B,)*)> where + $( + $B: DoubleEndedIterator + ExactSizeIterator, + )* + { + #[inline] + fn next_back(&mut self) -> Option { + let ($(ref mut $B,)*) = self.t; + let size = *[$( $B.len(), )*].iter().min().unwrap(); + + $( + if $B.len() != size { + for _ in 0..$B.len() - size { $B.next_back(); } + } + )* + + match ($($B.next_back(),)*) { + ($(Some($B),)*) => Some(($($B,)*)), + _ => None, + } + } + } + ); +} + +impl_zip_iter!(A); +impl_zip_iter!(A, B); +impl_zip_iter!(A, B, C); +impl_zip_iter!(A, B, C, D); +impl_zip_iter!(A, B, C, D, E); +impl_zip_iter!(A, B, C, D, E, F); +impl_zip_iter!(A, B, C, D, E, F, G); +impl_zip_iter!(A, B, C, D, E, F, G, H); +impl_zip_iter!(A, B, C, D, E, F, G, H, I); +impl_zip_iter!(A, B, C, D, E, F, G, H, I, J); +impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K); +impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K, L); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/adaptors_no_collect.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/adaptors_no_collect.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/adaptors_no_collect.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/adaptors_no_collect.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,46 @@ +use itertools::Itertools; + +struct PanickingCounter { + curr: usize, + max: usize, +} + +impl Iterator for PanickingCounter { + type Item = (); + + fn next(&mut self) -> Option { + self.curr += 1; + + assert_ne!( + self.curr, self.max, + "Input iterator reached maximum of {} suggesting collection by adaptor", + self.max + ); + + Some(()) + } +} + +fn no_collect_test(to_adaptor: T) + where A: Iterator, T: Fn(PanickingCounter) -> A +{ + let counter = PanickingCounter { curr: 0, max: 10_000 }; + let adaptor = to_adaptor(counter); + + for _ in adaptor.take(5) {} +} + +#[test] +fn permutations_no_collect() { + no_collect_test(|iter| iter.permutations(5)) +} + +#[test] +fn combinations_no_collect() { + no_collect_test(|iter| iter.combinations(5)) +} + +#[test] +fn combinations_with_replacement_no_collect() { + no_collect_test(|iter| iter.combinations_with_replacement(5)) +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/flatten_ok.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/flatten_ok.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/flatten_ok.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/flatten_ok.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,76 @@ +use itertools::{assert_equal, Itertools}; +use std::{ops::Range, vec::IntoIter}; + +fn mix_data() -> IntoIter, bool>> { + vec![Ok(0..2), Err(false), Ok(2..4), Err(true), Ok(4..6)].into_iter() +} + +fn ok_data() -> IntoIter, bool>> { + vec![Ok(0..2), Ok(2..4), Ok(4..6)].into_iter() +} + +#[test] +fn flatten_ok_mixed_expected_forward() { + assert_equal( + mix_data().flatten_ok(), + vec![ + Ok(0), + Ok(1), + Err(false), + Ok(2), + Ok(3), + Err(true), + Ok(4), + Ok(5), + ], + ); +} + +#[test] +fn flatten_ok_mixed_expected_reverse() { + assert_equal( + mix_data().flatten_ok().rev(), + vec![ + Ok(5), + Ok(4), + Err(true), + Ok(3), + Ok(2), + Err(false), + Ok(1), + Ok(0), + ], + ); +} + +#[test] +fn flatten_ok_collect_mixed_forward() { + assert_eq!( + mix_data().flatten_ok().collect::, _>>(), + Err(false) + ); +} + +#[test] +fn flatten_ok_collect_mixed_reverse() { + assert_eq!( + mix_data().flatten_ok().rev().collect::, _>>(), + Err(true) + ); +} + +#[test] +fn flatten_ok_collect_ok_forward() { + assert_eq!( + ok_data().flatten_ok().collect::, _>>(), + Ok((0..6).collect()) + ); +} + +#[test] +fn flatten_ok_collect_ok_reverse() { + assert_eq!( + ok_data().flatten_ok().rev().collect::, _>>(), + Ok((0..6).rev().collect()) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/macros_hygiene.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/macros_hygiene.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/macros_hygiene.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/macros_hygiene.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,13 @@ +#[test] +fn iproduct_hygiene() { + let _ = itertools::iproduct!(0..6); + let _ = itertools::iproduct!(0..6, 0..9); + let _ = itertools::iproduct!(0..6, 0..9, 0..12); +} + +#[test] +fn izip_hygiene() { + let _ = itertools::izip!(0..6); + let _ = itertools::izip!(0..6, 0..9); + let _ = itertools::izip!(0..6, 0..9, 0..12); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/merge_join.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/merge_join.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/merge_join.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/merge_join.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,108 @@ +use itertools::EitherOrBoth; +use itertools::free::merge_join_by; + +#[test] +fn empty() { + let left: Vec = vec![]; + let right: Vec = vec![]; + let expected_result: Vec> = vec![]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn left_only() { + let left: Vec = vec![1,2,3]; + let right: Vec = vec![]; + let expected_result: Vec> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Left(2), + EitherOrBoth::Left(3) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn right_only() { + let left: Vec = vec![]; + let right: Vec = vec![1,2,3]; + let expected_result: Vec> = vec![ + EitherOrBoth::Right(1), + EitherOrBoth::Right(2), + EitherOrBoth::Right(3) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn first_left_then_right() { + let left: Vec = vec![1,2,3]; + let right: Vec = vec![4,5,6]; + let expected_result: Vec> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Left(2), + EitherOrBoth::Left(3), + EitherOrBoth::Right(4), + EitherOrBoth::Right(5), + EitherOrBoth::Right(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn first_right_then_left() { + let left: Vec = vec![4,5,6]; + let right: Vec = vec![1,2,3]; + let expected_result: Vec> = vec![ + EitherOrBoth::Right(1), + EitherOrBoth::Right(2), + EitherOrBoth::Right(3), + EitherOrBoth::Left(4), + EitherOrBoth::Left(5), + EitherOrBoth::Left(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn interspersed_left_and_right() { + let left: Vec = vec![1,3,5]; + let right: Vec = vec![2,4,6]; + let expected_result: Vec> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Right(2), + EitherOrBoth::Left(3), + EitherOrBoth::Right(4), + EitherOrBoth::Left(5), + EitherOrBoth::Right(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn overlapping_left_and_right() { + let left: Vec = vec![1,3,4,6]; + let right: Vec = vec![2,3,4,5]; + let expected_result: Vec> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Right(2), + EitherOrBoth::Both(3, 3), + EitherOrBoth::Both(4, 4), + EitherOrBoth::Right(5), + EitherOrBoth::Left(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::>(); + assert_eq!(expected_result, actual_result); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/peeking_take_while.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/peeking_take_while.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/peeking_take_while.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/peeking_take_while.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,50 @@ +use itertools::Itertools; +use itertools::{put_back, put_back_n}; + +#[test] +fn peeking_take_while_peekable() { + let mut r = (0..10).peekable(); + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); +} + +#[test] +fn peeking_take_while_put_back() { + let mut r = put_back(0..10); + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_put_back_n() { + let mut r = put_back_n(6..10); + for elt in (0..6).rev() { + r.put_back(elt); + } + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_slice_iter() { + let v = [1, 2, 3, 4, 5, 6]; + let mut r = v.iter(); + r.peeking_take_while(|x| **x <= 3).count(); + assert_eq!(r.next(), Some(&4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_slice_iter_rev() { + let v = [1, 2, 3, 4, 5, 6]; + let mut r = v.iter().rev(); + r.peeking_take_while(|x| **x >= 3).count(); + assert_eq!(r.next(), Some(&2)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/quick.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/quick.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/quick.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/quick.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,1749 @@ +//! The purpose of these tests is to cover corner cases of iterators +//! and adaptors. +//! +//! In particular we test the tedious size_hint and exact size correctness. + +use quickcheck as qc; +use std::default::Default; +use std::num::Wrapping; +use std::ops::Range; +use std::cmp::{max, min, Ordering}; +use std::collections::{HashMap, HashSet}; +use itertools::Itertools; +use itertools::{ + multizip, + EitherOrBoth, + iproduct, + izip, +}; +use itertools::free::{ + cloned, + enumerate, + multipeek, + peek_nth, + put_back, + put_back_n, + rciter, + zip, + zip_eq, +}; + +use rand::Rng; +use rand::seq::SliceRandom; +use quickcheck::TestResult; + +/// Trait for size hint modifier types +trait HintKind: Copy + Send + qc::Arbitrary { + fn loosen_bounds(&self, org_hint: (usize, Option)) -> (usize, Option); +} + +/// Exact size hint variant that leaves hints unchanged +#[derive(Clone, Copy, Debug)] +struct Exact {} + +impl HintKind for Exact { + fn loosen_bounds(&self, org_hint: (usize, Option)) -> (usize, Option) { + org_hint + } +} + +impl qc::Arbitrary for Exact { + fn arbitrary(_: &mut G) -> Self { + Exact {} + } +} + +/// Inexact size hint variant to simulate imprecise (but valid) size hints +/// +/// Will always decrease the lower bound and increase the upper bound +/// of the size hint by set amounts. +#[derive(Clone, Copy, Debug)] +struct Inexact { + underestimate: usize, + overestimate: usize, +} + +impl HintKind for Inexact { + fn loosen_bounds(&self, org_hint: (usize, Option)) -> (usize, Option) { + let (org_lower, org_upper) = org_hint; + (org_lower.saturating_sub(self.underestimate), + org_upper.and_then(move |x| x.checked_add(self.overestimate))) + } +} + +impl qc::Arbitrary for Inexact { + fn arbitrary(g: &mut G) -> Self { + let ue_value = usize::arbitrary(g); + let oe_value = usize::arbitrary(g); + // Compensate for quickcheck using extreme values too rarely + let ue_choices = &[0, ue_value, usize::max_value()]; + let oe_choices = &[0, oe_value, usize::max_value()]; + Inexact { + underestimate: *ue_choices.choose(g).unwrap(), + overestimate: *oe_choices.choose(g).unwrap(), + } + } + + fn shrink(&self) -> Box> { + let underestimate_value = self.underestimate; + let overestimate_value = self.overestimate; + Box::new( + underestimate_value.shrink().flat_map(move |ue_value| + overestimate_value.shrink().map(move |oe_value| + Inexact { + underestimate: ue_value, + overestimate: oe_value, + } + ) + ) + ) + } +} + +/// Our base iterator that we can impl Arbitrary for +/// +/// By default we'll return inexact bounds estimates for size_hint +/// to make tests harder to pass. +/// +/// NOTE: Iter is tricky and is not fused, to help catch bugs. +/// At the end it will return None once, then return Some(0), +/// then return None again. +#[derive(Clone, Debug)] +struct Iter { + iterator: Range, + // fuse/done flag + fuse_flag: i32, + hint_kind: SK, +} + +impl Iter where HK: HintKind +{ + fn new(it: Range, hint_kind: HK) -> Self { + Iter { + iterator: it, + fuse_flag: 0, + hint_kind, + } + } +} + +impl Iterator for Iter + where Range: Iterator, + as Iterator>::Item: Default, + HK: HintKind, +{ + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option + { + let elt = self.iterator.next(); + if elt.is_none() { + self.fuse_flag += 1; + // check fuse flag + if self.fuse_flag == 2 { + return Some(Default::default()) + } + } + elt + } + + fn size_hint(&self) -> (usize, Option) + { + let org_hint = self.iterator.size_hint(); + self.hint_kind.loosen_bounds(org_hint) + } +} + +impl DoubleEndedIterator for Iter + where Range: DoubleEndedIterator, + as Iterator>::Item: Default, + HK: HintKind +{ + fn next_back(&mut self) -> Option { self.iterator.next_back() } +} + +impl ExactSizeIterator for Iter where Range: ExactSizeIterator, + as Iterator>::Item: Default, +{ } + +impl qc::Arbitrary for Iter + where T: qc::Arbitrary, + HK: HintKind, +{ + fn arbitrary(g: &mut G) -> Self + { + Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) + } + + fn shrink(&self) -> Box>> + { + let r = self.iterator.clone(); + let hint_kind = self.hint_kind; + Box::new( + r.start.shrink().flat_map(move |a| + r.end.shrink().map(move |b| + Iter::new(a.clone()..b, hint_kind) + ) + ) + ) + } +} + +/// A meta-iterator which yields `Iter`s whose start/endpoints are +/// increased or decreased linearly on each iteration. +#[derive(Clone, Debug)] +struct ShiftRange { + range_start: i32, + range_end: i32, + start_step: i32, + end_step: i32, + iter_count: u32, + hint_kind: HK, +} + +impl Iterator for ShiftRange where HK: HintKind { + type Item = Iter; + + fn next(&mut self) -> Option { + if self.iter_count == 0 { + return None; + } + + let iter = Iter::new(self.range_start..self.range_end, self.hint_kind); + + self.range_start += self.start_step; + self.range_end += self.end_step; + self.iter_count -= 1; + + Some(iter) + } +} + +impl ExactSizeIterator for ShiftRange { } + +impl qc::Arbitrary for ShiftRange + where HK: HintKind +{ + fn arbitrary(g: &mut G) -> Self { + const MAX_STARTING_RANGE_DIFF: i32 = 32; + const MAX_STEP_MODULO: i32 = 8; + const MAX_ITER_COUNT: u32 = 3; + + let range_start = qc::Arbitrary::arbitrary(g); + let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1); + let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); + let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); + let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1); + let hint_kind = qc::Arbitrary::arbitrary(g); + + ShiftRange { + range_start, + range_end, + start_step, + end_step, + iter_count, + hint_kind, + } + } +} + +fn correct_count(get_it: F) -> bool +where + I: Iterator, + F: Fn() -> I +{ + let mut counts = vec![get_it().count()]; + + 'outer: loop { + let mut it = get_it(); + + for _ in 0..(counts.len() - 1) { + #[allow(clippy::manual_assert)] + if it.next().is_none() { + panic!("Iterator shouldn't be finished, may not be deterministic"); + } + } + + if it.next().is_none() { + break 'outer; + } + + counts.push(it.count()); + } + + let total_actual_count = counts.len() - 1; + + for (i, returned_count) in counts.into_iter().enumerate() { + let actual_count = total_actual_count - i; + if actual_count != returned_count { + println!("Total iterations: {} True count: {} returned count: {}", i, actual_count, returned_count); + + return false; + } + } + + true +} + +fn correct_size_hint(mut it: I) -> bool { + // record size hint at each iteration + let initial_hint = it.size_hint(); + let mut hints = Vec::with_capacity(initial_hint.0 + 1); + hints.push(initial_hint); + while let Some(_) = it.next() { + hints.push(it.size_hint()) + } + + let mut true_count = hints.len(); // start off +1 too much + + // check all the size hints + for &(low, hi) in &hints { + true_count -= 1; + if low > true_count || + (hi.is_some() && hi.unwrap() < true_count) + { + println!("True size: {:?}, size hint: {:?}", true_count, (low, hi)); + //println!("All hints: {:?}", hints); + return false + } + } + true +} + +fn exact_size(mut it: I) -> bool { + // check every iteration + let (mut low, mut hi) = it.size_hint(); + if Some(low) != hi { return false; } + while let Some(_) = it.next() { + let (xlow, xhi) = it.size_hint(); + if low != xlow + 1 { return false; } + low = xlow; + hi = xhi; + if Some(low) != hi { return false; } + } + let (low, hi) = it.size_hint(); + low == 0 && hi == Some(0) +} + +// Exact size for this case, without ExactSizeIterator +fn exact_size_for_this(mut it: I) -> bool { + // check every iteration + let (mut low, mut hi) = it.size_hint(); + if Some(low) != hi { return false; } + while let Some(_) = it.next() { + let (xlow, xhi) = it.size_hint(); + if low != xlow + 1 { return false; } + low = xlow; + hi = xhi; + if Some(low) != hi { return false; } + } + let (low, hi) = it.size_hint(); + low == 0 && hi == Some(0) +} + +/* + * NOTE: Range is broken! + * (all signed ranges are) +#[quickcheck] +fn size_range_i8(a: Iter) -> bool { + exact_size(a) +} + +#[quickcheck] +fn size_range_i16(a: Iter) -> bool { + exact_size(a) +} + +#[quickcheck] +fn size_range_u8(a: Iter) -> bool { + exact_size(a) +} + */ + +macro_rules! quickcheck { + // accept several property function definitions + // The property functions can use pattern matching and `mut` as usual + // in the function arguments, but the functions can not be generic. + {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => ( + $( + #[test] + $(#$attr)* + fn $fn_name() { + fn prop($($arg)*) -> $ret { + $($code)* + } + ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*)); + } + )* + ); + // parse argument list (with patterns allowed) into prop as fn(_, _) -> _ + (@fn $f:ident [$($t:tt)*]) => { + $f as fn($($t),*) -> _ + }; + (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => { + quickcheck!(@fn $f [$($p)* _] $($tail)*) + }; + (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => { + quickcheck!(@fn $f [$($p)*] $($tail)*) + }; +} + +quickcheck! { + + fn size_product(a: Iter, b: Iter) -> bool { + correct_size_hint(a.cartesian_product(b)) + } + fn size_product3(a: Iter, b: Iter, c: Iter) -> bool { + correct_size_hint(iproduct!(a, b, c)) + } + + fn correct_cartesian_product3(a: Iter, b: Iter, c: Iter, + take_manual: usize) -> () + { + // test correctness of iproduct through regular iteration (take) + // and through fold. + let ac = a.clone(); + let br = &b.clone(); + let cr = &c.clone(); + let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect(); + let mut product_iter = iproduct!(a, b, c); + let mut actual = Vec::new(); + + actual.extend((&mut product_iter).take(take_manual)); + if actual.len() == take_manual { + product_iter.fold((), |(), elt| actual.push(elt)); + } + assert_eq!(answer, actual); + } + + fn size_multi_product(a: ShiftRange) -> bool { + correct_size_hint(a.multi_cartesian_product()) + } + fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () { + // Fix no. of iterators at 3 + let a = ShiftRange { iter_count: 3, ..a }; + + // test correctness of MultiProduct through regular iteration (take) + // and through fold. + let mut iters = a.clone(); + let i0 = iters.next().unwrap(); + let i1r = &iters.next().unwrap(); + let i2r = &iters.next().unwrap(); + let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect(); + let mut multi_product = a.clone().multi_cartesian_product(); + let mut actual = Vec::new(); + + actual.extend((&mut multi_product).take(take_manual)); + if actual.len() == take_manual { + multi_product.fold((), |(), elt| actual.push(elt)); + } + assert_eq!(answer, actual); + + assert_eq!(answer.into_iter().last(), a.multi_cartesian_product().last()); + } + + #[allow(deprecated)] + fn size_step(a: Iter, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let filt = a.clone().dedup(); + correct_size_hint(filt.step(s)) && + exact_size(a.step(s)) + } + + #[allow(deprecated)] + fn equal_step(a: Iter, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let mut i = 0; + itertools::equal(a.clone().step(s), a.filter(|_| { + let keep = i % s == 0; + i += 1; + keep + })) + } + + #[allow(deprecated)] + fn equal_step_vec(a: Vec, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let mut i = 0; + itertools::equal(a.iter().step(s), a.iter().filter(|_| { + let keep = i % s == 0; + i += 1; + keep + })) + } + + fn size_multipeek(a: Iter, s: u8) -> bool { + let mut it = multipeek(a); + // peek a few times + for _ in 0..s { + it.peek(); + } + exact_size(it) + } + + fn size_peek_nth(a: Iter, s: u8) -> bool { + let mut it = peek_nth(a); + // peek a few times + for n in 0..s { + it.peek_nth(n as usize); + } + exact_size(it) + } + + fn equal_merge(mut a: Vec, mut b: Vec) -> bool { + a.sort(); + b.sort(); + let mut merged = a.clone(); + merged.extend(b.iter().cloned()); + merged.sort(); + itertools::equal(&merged, a.iter().merge(&b)) + } + fn size_merge(a: Iter, b: Iter) -> bool { + correct_size_hint(a.merge(b)) + } + fn size_zip(a: Iter, b: Iter, c: Iter) -> bool { + let filt = a.clone().dedup(); + correct_size_hint(multizip((filt, b.clone(), c.clone()))) && + exact_size(multizip((a, b, c))) + } + fn size_zip_rc(a: Iter, b: Iter) -> bool { + let rc = rciter(a); + correct_size_hint(multizip((&rc, &rc, b))) + } + + fn size_zip_macro(a: Iter, b: Iter, c: Iter) -> bool { + let filt = a.clone().dedup(); + correct_size_hint(izip!(filt, b.clone(), c.clone())) && + exact_size(izip!(a, b, c)) + } + fn equal_kmerge(mut a: Vec, mut b: Vec, mut c: Vec) -> bool { + use itertools::free::kmerge; + a.sort(); + b.sort(); + c.sort(); + let mut merged = a.clone(); + merged.extend(b.iter().cloned()); + merged.extend(c.iter().cloned()); + merged.sort(); + itertools::equal(merged.into_iter(), kmerge(vec![a, b, c])) + } + + // Any number of input iterators + fn equal_kmerge_2(mut inputs: Vec>) -> bool { + use itertools::free::kmerge; + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), kmerge(inputs)) + } + + // Any number of input iterators + fn equal_kmerge_by_ge(mut inputs: Vec>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + input.reverse(); + } + let mut merged = inputs.concat(); + merged.sort(); + merged.reverse(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x >= y)) + } + + // Any number of input iterators + fn equal_kmerge_by_lt(mut inputs: Vec>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x < y)) + } + + // Any number of input iterators + fn equal_kmerge_by_le(mut inputs: Vec>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x <= y)) + } + fn size_kmerge(a: Iter, b: Iter, c: Iter) -> bool { + use itertools::free::kmerge; + correct_size_hint(kmerge(vec![a, b, c])) + } + fn equal_zip_eq(a: Vec, b: Vec) -> bool { + let len = std::cmp::min(a.len(), b.len()); + let a = &a[..len]; + let b = &b[..len]; + itertools::equal(zip_eq(a, b), zip(a, b)) + } + fn size_zip_longest(a: Iter, b: Iter) -> bool { + let filt = a.clone().dedup(); + let filt2 = b.clone().dedup(); + correct_size_hint(filt.zip_longest(b.clone())) && + correct_size_hint(a.clone().zip_longest(filt2)) && + exact_size(a.zip_longest(b)) + } + fn size_2_zip_longest(a: Iter, b: Iter) -> bool { + let it = a.clone().zip_longest(b.clone()); + let jt = a.clone().zip_longest(b.clone()); + itertools::equal(a, + it.filter_map(|elt| match elt { + EitherOrBoth::Both(x, _) => Some(x), + EitherOrBoth::Left(x) => Some(x), + _ => None, + } + )) + && + itertools::equal(b, + jt.filter_map(|elt| match elt { + EitherOrBoth::Both(_, y) => Some(y), + EitherOrBoth::Right(y) => Some(y), + _ => None, + } + )) + } + fn size_interleave(a: Iter, b: Iter) -> bool { + correct_size_hint(a.interleave(b)) + } + fn exact_interleave(a: Iter, b: Iter) -> bool { + exact_size_for_this(a.interleave(b)) + } + fn size_interleave_shortest(a: Iter, b: Iter) -> bool { + correct_size_hint(a.interleave_shortest(b)) + } + fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool { + exact_size_for_this(a.iter().interleave_shortest(&b)) + } + fn size_intersperse(a: Iter, x: i16) -> bool { + correct_size_hint(a.intersperse(x)) + } + fn equal_intersperse(a: Vec, x: i32) -> bool { + let mut inter = false; + let mut i = 0; + for elt in a.iter().cloned().intersperse(x) { + if inter { + if elt != x { return false } + } else { + if elt != a[i] { return false } + i += 1; + } + inter = !inter; + } + true + } + + fn equal_combinations_2(a: Vec) -> bool { + let mut v = Vec::new(); + for (i, x) in enumerate(&a) { + for y in &a[i + 1..] { + v.push((x, y)); + } + } + itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v) + } + + fn collect_tuple_matches_size(a: Iter) -> bool { + let size = a.clone().count(); + a.collect_tuple::<(_, _, _)>().is_some() == (size == 3) + } + + fn correct_permutations(vals: HashSet, k: usize) -> () { + // Test permutations only on iterators of distinct integers, to prevent + // false positives. + + const MAX_N: usize = 5; + + let n = min(vals.len(), MAX_N); + let vals: HashSet = vals.into_iter().take(n).collect(); + + let perms = vals.iter().permutations(k); + + let mut actual = HashSet::new(); + + for perm in perms { + assert_eq!(perm.len(), k); + + let all_items_valid = perm.iter().all(|p| vals.contains(p)); + assert!(all_items_valid, "perm contains value not from input: {:?}", perm); + + // Check that all perm items are distinct + let distinct_len = { + let perm_set: HashSet<_> = perm.iter().collect(); + perm_set.len() + }; + assert_eq!(perm.len(), distinct_len); + + // Check that the perm is new + assert!(actual.insert(perm.clone()), "perm already encountered: {:?}", perm); + } + } + + fn permutations_lexic_order(a: usize, b: usize) -> () { + let a = a % 6; + let b = b % 6; + + let n = max(a, b); + let k = min (a, b); + + let expected_first: Vec = (0..k).collect(); + let expected_last: Vec = ((n - k)..n).rev().collect(); + + let mut perms = (0..n).permutations(k); + + let mut curr_perm = match perms.next() { + Some(p) => p, + None => { return; } + }; + + assert_eq!(expected_first, curr_perm); + + for next_perm in perms { + assert!( + next_perm > curr_perm, + "next perm isn't greater-than current; next_perm={:?} curr_perm={:?} n={}", + next_perm, curr_perm, n + ); + + curr_perm = next_perm; + } + + assert_eq!(expected_last, curr_perm); + + } + + fn permutations_count(n: usize, k: usize) -> bool { + let n = n % 6; + + correct_count(|| (0..n).permutations(k)) + } + + fn permutations_size(a: Iter, k: usize) -> bool { + correct_size_hint(a.take(5).permutations(k)) + } + + fn permutations_k0_yields_once(n: usize) -> () { + let k = 0; + let expected: Vec> = vec![vec![]]; + let actual = (0..n).permutations(k).collect_vec(); + + assert_eq!(expected, actual); + } +} + +quickcheck! { + fn dedup_via_coalesce(a: Vec) -> bool { + let mut b = a.clone(); + b.dedup(); + itertools::equal( + &b, + a + .iter() + .coalesce(|x, y| { + if x==y { + Ok(x) + } else { + Err((x, y)) + } + }) + .fold(vec![], |mut v, n| { + v.push(n); + v + }) + ) + } +} + +quickcheck! { + fn equal_dedup(a: Vec) -> bool { + let mut b = a.clone(); + b.dedup(); + itertools::equal(&b, a.iter().dedup()) + } +} + +quickcheck! { + fn equal_dedup_by(a: Vec<(i32, i32)>) -> bool { + let mut b = a.clone(); + b.dedup_by(|x, y| x.0==y.0); + itertools::equal(&b, a.iter().dedup_by(|x, y| x.0==y.0)) + } +} + +quickcheck! { + fn size_dedup(a: Vec) -> bool { + correct_size_hint(a.iter().dedup()) + } +} + +quickcheck! { + fn size_dedup_by(a: Vec<(i32, i32)>) -> bool { + correct_size_hint(a.iter().dedup_by(|x, y| x.0==y.0)) + } +} + +quickcheck! { + fn exact_repeatn((n, x): (usize, i32)) -> bool { + let it = itertools::repeat_n(x, n); + exact_size(it) + } +} + +quickcheck! { + fn size_put_back(a: Vec, x: Option) -> bool { + let mut it = put_back(a.into_iter()); + match x { + Some(t) => it.put_back(t), + None => {} + } + correct_size_hint(it) + } +} + +quickcheck! { + fn size_put_backn(a: Vec, b: Vec) -> bool { + let mut it = put_back_n(a.into_iter()); + for elt in b { + it.put_back(elt) + } + correct_size_hint(it) + } +} + +quickcheck! { + fn size_tee(a: Vec) -> bool { + let (mut t1, mut t2) = a.iter().tee(); + t1.next(); + t1.next(); + t2.next(); + exact_size(t1) && exact_size(t2) + } +} + +quickcheck! { + fn size_tee_2(a: Vec) -> bool { + let (mut t1, mut t2) = a.iter().dedup().tee(); + t1.next(); + t1.next(); + t2.next(); + correct_size_hint(t1) && correct_size_hint(t2) + } +} + +quickcheck! { + fn size_take_while_ref(a: Vec, stop: u8) -> bool { + correct_size_hint(a.iter().take_while_ref(|x| **x != stop)) + } +} + +quickcheck! { + fn equal_partition(a: Vec) -> bool { + let mut a = a; + let mut ap = a.clone(); + let split_index = itertools::partition(&mut ap, |x| *x >= 0); + let parted = (0..split_index).all(|i| ap[i] >= 0) && + (split_index..a.len()).all(|i| ap[i] < 0); + + a.sort(); + ap.sort(); + parted && (a == ap) + } +} + +quickcheck! { + fn size_combinations(it: Iter) -> bool { + correct_size_hint(it.tuple_combinations::<(_, _)>()) + } +} + +quickcheck! { + fn equal_combinations(it: Iter) -> bool { + let values = it.clone().collect_vec(); + let mut cmb = it.tuple_combinations(); + for i in 0..values.len() { + for j in i+1..values.len() { + let pair = (values[i], values[j]); + if pair != cmb.next().unwrap() { + return false; + } + } + } + cmb.next() == None + } +} + +quickcheck! { + fn size_pad_tail(it: Iter, pad: u8) -> bool { + correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) && + correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0)) + } +} + +quickcheck! { + fn size_pad_tail2(it: Iter, pad: u8) -> bool { + exact_size(it.pad_using(pad as usize, |_| 0)) + } +} + +quickcheck! { + fn size_powerset(it: Iter) -> bool { + // Powerset cardinality gets large very quickly, limit input to keep test fast. + correct_size_hint(it.take(12).powerset()) + } +} + +quickcheck! { + fn size_duplicates(it: Iter) -> bool { + correct_size_hint(it.duplicates()) + } +} + +quickcheck! { + fn size_unique(it: Iter) -> bool { + correct_size_hint(it.unique()) + } + + fn count_unique(it: Vec, take_first: u8) -> () { + let answer = { + let mut v = it.clone(); + v.sort(); v.dedup(); + v.len() + }; + let mut iter = cloned(&it).unique(); + let first_count = (&mut iter).take(take_first as usize).count(); + let rest_count = iter.count(); + assert_eq!(answer, first_count + rest_count); + } +} + +quickcheck! { + fn fuzz_group_by_lazy_1(it: Iter) -> bool { + let jt = it.clone(); + let groups = it.group_by(|k| *k); + itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x)) + } +} + +quickcheck! { + fn fuzz_group_by_lazy_2(data: Vec) -> bool { + let groups = data.iter().group_by(|k| *k / 10); + let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + res + } +} + +quickcheck! { + fn fuzz_group_by_lazy_3(data: Vec) -> bool { + let grouper = data.iter().group_by(|k| *k / 10); + let groups = grouper.into_iter().collect_vec(); + let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + res + } +} + +quickcheck! { + fn fuzz_group_by_lazy_duo(data: Vec, order: Vec<(bool, bool)>) -> bool { + let grouper = data.iter().group_by(|k| *k / 3); + let mut groups1 = grouper.into_iter(); + let mut groups2 = grouper.into_iter(); + let mut elts = Vec::<&u8>::new(); + let mut old_groups = Vec::new(); + + let tup1 = |(_, b)| b; + for &(ord, consume_now) in &order { + let iter = &mut [&mut groups1, &mut groups2][ord as usize]; + match iter.next() { + Some((_, gr)) => if consume_now { + for og in old_groups.drain(..) { + elts.extend(og); + } + elts.extend(gr); + } else { + old_groups.push(gr); + }, + None => break, + } + } + for og in old_groups.drain(..) { + elts.extend(og); + } + for gr in groups1.map(&tup1) { elts.extend(gr); } + for gr in groups2.map(&tup1) { elts.extend(gr); } + itertools::assert_equal(&data, elts); + true + } +} + +quickcheck! { + fn equal_chunks_lazy(a: Vec, size: u8) -> bool { + let mut size = size; + if size == 0 { + size += 1; + } + let chunks = a.iter().chunks(size as usize); + let it = a.chunks(size as usize); + for (a, b) in chunks.into_iter().zip(it) { + if !itertools::equal(a, b) { + return false; + } + } + true + } +} + +quickcheck! { + fn equal_tuple_windows_1(a: Vec) -> bool { + let x = a.windows(1).map(|s| (&s[0], )); + let y = a.iter().tuple_windows::<(_,)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_2(a: Vec) -> bool { + let x = a.windows(2).map(|s| (&s[0], &s[1])); + let y = a.iter().tuple_windows::<(_, _)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_3(a: Vec) -> bool { + let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2])); + let y = a.iter().tuple_windows::<(_, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_4(a: Vec) -> bool { + let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3])); + let y = a.iter().tuple_windows::<(_, _, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_1(a: Vec) -> bool { + let x = a.chunks(1).map(|s| (&s[0], )); + let y = a.iter().tuples::<(_,)>(); + itertools::equal(x, y) + } + + fn equal_tuples_2(a: Vec) -> bool { + let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1])); + let y = a.iter().tuples::<(_, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_3(a: Vec) -> bool { + let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2])); + let y = a.iter().tuples::<(_, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_4(a: Vec) -> bool { + let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3])); + let y = a.iter().tuples::<(_, _, _, _)>(); + itertools::equal(x, y) + } + + fn exact_tuple_buffer(a: Vec) -> bool { + let mut iter = a.iter().tuples::<(_, _, _, _)>(); + (&mut iter).last(); + let buffer = iter.into_buffer(); + assert_eq!(buffer.len(), a.len() % 4); + exact_size(buffer) + } +} + +// with_position +quickcheck! { + fn with_position_exact_size_1(a: Vec) -> bool { + exact_size_for_this(a.iter().with_position()) + } + fn with_position_exact_size_2(a: Iter) -> bool { + exact_size_for_this(a.with_position()) + } +} + +quickcheck! { + fn correct_group_map_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let count = a.len(); + let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map(); + + assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count); + + for (&key, vals) in lookup.iter() { + assert!(vals.iter().all(|&val| val % modulo == key)); + } + } +} + +/// A peculiar type: Equality compares both tuple items, but ordering only the +/// first item. This is so we can check the stability property easily. +#[derive(Clone, Debug, PartialEq, Eq)] +struct Val(u32, u32); + +impl PartialOrd for Val { + fn partial_cmp(&self, other: &Val) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl Ord for Val { + fn cmp(&self, other: &Val) -> Ordering { + self.0.cmp(&other.0) + } +} + +impl qc::Arbitrary for Val { + fn arbitrary(g: &mut G) -> Self { + let (x, y) = <(u32, u32)>::arbitrary(g); + Val(x, y) + } + fn shrink(&self) -> Box> { + Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y))) + } +} + +quickcheck! { + fn minmax(a: Vec) -> bool { + use itertools::MinMaxResult; + + + let minmax = a.iter().minmax(); + let expected = match a.len() { + 0 => MinMaxResult::NoElements, + 1 => MinMaxResult::OneElement(&a[0]), + _ => MinMaxResult::MinMax(a.iter().min().unwrap(), + a.iter().max().unwrap()), + }; + minmax == expected + } +} + +quickcheck! { + fn minmax_f64(a: Vec) -> TestResult { + use itertools::MinMaxResult; + + if a.iter().any(|x| x.is_nan()) { + return TestResult::discard(); + } + + let min = cloned(&a).fold1(f64::min); + let max = cloned(&a).fold1(f64::max); + + let minmax = cloned(&a).minmax(); + let expected = match a.len() { + 0 => MinMaxResult::NoElements, + 1 => MinMaxResult::OneElement(min.unwrap()), + _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()), + }; + TestResult::from_bool(minmax == expected) + } +} + +quickcheck! { + #[allow(deprecated)] + fn tree_fold1_f64(mut a: Vec) -> TestResult { + fn collapse_adjacent(x: Vec, mut f: F) -> Vec + where F: FnMut(f64, f64) -> f64 + { + let mut out = Vec::new(); + for i in (0..x.len()).step(2) { + if i == x.len()-1 { + out.push(x[i]) + } else { + out.push(f(x[i], x[i+1])); + } + } + out + } + + if a.iter().any(|x| x.is_nan()) { + return TestResult::discard(); + } + + let actual = a.iter().cloned().tree_fold1(f64::atan2); + + while a.len() > 1 { + a = collapse_adjacent(a, f64::atan2); + } + let expected = a.pop(); + + TestResult::from_bool(actual == expected) + } +} + +quickcheck! { + fn exactly_one_i32(a: Vec) -> TestResult { + let ret = a.iter().cloned().exactly_one(); + match a.len() { + 1 => TestResult::from_bool(ret.unwrap() == a[0]), + _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())), + } + } +} + +quickcheck! { + fn at_most_one_i32(a: Vec) -> TestResult { + let ret = a.iter().cloned().at_most_one(); + match a.len() { + 0 => TestResult::from_bool(ret.unwrap() == None), + 1 => TestResult::from_bool(ret.unwrap() == Some(a[0])), + _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())), + } + } +} + +quickcheck! { + fn consistent_grouping_map_with_by(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + + let lookup_grouping_map = a.iter().copied().map(|i| (i % modulo, i)).into_grouping_map().collect::>(); + let lookup_grouping_map_by = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::>(); + + assert_eq!(lookup_grouping_map, lookup_grouping_map_by); + } + + fn correct_grouping_map_by_aggregate_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo < 2 { 2 } else { modulo } as u64; // Avoid `% 0` + let lookup = a.iter() + .map(|&b| b as u64) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .aggregate(|acc, &key, val| { + assert!(val % modulo == key); + if val % (modulo - 1) == 0 { + None + } else { + Some(acc.unwrap_or(0) + val) + } + }); + + let group_map_lookup = a.iter() + .map(|&b| b as u64) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .filter_map(|(key, vals)| { + vals.into_iter().fold(None, |acc, val| { + if val % (modulo - 1) == 0 { + None + } else { + Some(acc.unwrap_or(0) + val) + } + }).map(|new_val| (key, new_val)) + }) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for m in 0..modulo { + assert_eq!( + lookup.get(&m).copied(), + a.iter() + .map(|&b| b as u64) + .filter(|&val| val % modulo == m) + .fold(None, |acc, val| { + if val % (modulo - 1) == 0 { + None + } else { + Some(acc.unwrap_or(0) + val) + } + }) + ); + } + } + + fn correct_grouping_map_by_fold_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` + let lookup = a.iter().map(|&b| b as u64) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .fold(0u64, |acc, &key, val| { + assert!(val % modulo == key); + acc + val + }); + + let group_map_lookup = a.iter() + .map(|&b| b as u64) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().sum())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &sum) in lookup.iter() { + assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::()); + } + } + + fn correct_grouping_map_by_fold_first_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` + let lookup = a.iter().map(|&b| b as u64) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .fold_first(|acc, &key, val| { + assert!(val % modulo == key); + acc + val + }); + + // TODO: Swap `fold1` with stdlib's `fold_first` when it's stabilized + let group_map_lookup = a.iter() + .map(|&b| b as u64) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().fold1(|acc, val| acc + val).unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &sum) in lookup.iter() { + assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::()); + } + } + + fn correct_grouping_map_by_collect_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup_grouping_map = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::>(); + let lookup_group_map = a.iter().copied().map(|i| (i % modulo, i)).into_group_map(); + + assert_eq!(lookup_grouping_map, lookup_group_map); + } + + fn correct_grouping_map_by_max_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max(); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().max().unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &max) in lookup.iter() { + assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max()); + } + } + + fn correct_grouping_map_by_max_by_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by(|_, v1, v2| v1.cmp(v2)); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().max_by(|v1, v2| v1.cmp(v2)).unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &max) in lookup.iter() { + assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by(|v1, v2| v1.cmp(v2))); + } + } + + fn correct_grouping_map_by_max_by_key_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by_key(|_, &val| val); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().max_by_key(|&val| val).unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &max) in lookup.iter() { + assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by_key(|&val| val)); + } + } + + fn correct_grouping_map_by_min_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min(); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().min().unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &min) in lookup.iter() { + assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min()); + } + } + + fn correct_grouping_map_by_min_by_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by(|_, v1, v2| v1.cmp(v2)); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().min_by(|v1, v2| v1.cmp(v2)).unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &min) in lookup.iter() { + assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by(|v1, v2| v1.cmp(v2))); + } + } + + fn correct_grouping_map_by_min_by_key_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by_key(|_, &val| val); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().min_by_key(|&val| val).unwrap())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &min) in lookup.iter() { + assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by_key(|&val| val)); + } + } + + fn correct_grouping_map_by_minmax_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax(); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().minmax())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &minmax) in lookup.iter() { + assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax()); + } + } + + fn correct_grouping_map_by_minmax_by_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by(|_, v1, v2| v1.cmp(v2)); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().minmax_by(|v1, v2| v1.cmp(v2)))) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &minmax) in lookup.iter() { + assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by(|v1, v2| v1.cmp(v2))); + } + } + + fn correct_grouping_map_by_minmax_by_key_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by_key(|_, &val| val); + + let group_map_lookup = a.iter().copied() + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().minmax_by_key(|&val| val))) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &minmax) in lookup.iter() { + assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by_key(|&val| val)); + } + } + + fn correct_grouping_map_by_sum_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0` + let lookup = a.iter().map(|&b| b as u64) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .sum(); + + let group_map_lookup = a.iter().map(|&b| b as u64) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().sum())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &sum) in lookup.iter() { + assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::()); + } + } + + fn correct_grouping_map_by_product_modulo_key(a: Vec, modulo: u8) -> () { + let modulo = Wrapping(if modulo == 0 { 1 } else { modulo } as u64); // Avoid `% 0` + let lookup = a.iter().map(|&b| Wrapping(b as u64)) // Avoid overflows + .into_grouping_map_by(|i| i % modulo) + .product(); + + let group_map_lookup = a.iter().map(|&b| Wrapping(b as u64)) + .map(|i| (i % modulo, i)) + .into_group_map() + .into_iter() + .map(|(key, vals)| (key, vals.into_iter().product::>())) + .collect::>(); + assert_eq!(lookup, group_map_lookup); + + for (&key, &prod) in lookup.iter() { + assert_eq!( + prod, + a.iter() + .map(|&b| Wrapping(b as u64)) + .filter(|&val| val % modulo == key) + .product::>() + ); + } + } + + // This should check that if multiple elements are equally minimum or maximum + // then `max`, `min` and `minmax` pick the first minimum and the last maximum. + // This is to be consistent with `std::iter::max` and `std::iter::min`. + fn correct_grouping_map_by_min_max_minmax_order_modulo_key() -> () { + use itertools::MinMaxResult; + + let lookup = (0..=10) + .into_grouping_map_by(|_| 0) + .max_by(|_, _, _| Ordering::Equal); + + assert_eq!(lookup[&0], 10); + + let lookup = (0..=10) + .into_grouping_map_by(|_| 0) + .min_by(|_, _, _| Ordering::Equal); + + assert_eq!(lookup[&0], 0); + + let lookup = (0..=10) + .into_grouping_map_by(|_| 0) + .minmax_by(|_, _, _| Ordering::Equal); + + assert_eq!(lookup[&0], MinMaxResult::MinMax(0, 10)); + } +} + +quickcheck! { + fn counts(nums: Vec) -> TestResult { + let counts = nums.iter().counts(); + for (&item, &count) in counts.iter() { + #[allow(clippy::absurd_extreme_comparisons)] + if count <= 0 { + return TestResult::failed(); + } + if count != nums.iter().filter(|&x| x == item).count() { + return TestResult::failed(); + } + } + for item in nums.iter() { + if !counts.contains_key(item) { + return TestResult::failed(); + } + } + TestResult::passed() + } +} + +quickcheck! { + fn test_double_ended_zip_2(a: Vec, b: Vec) -> TestResult { + let mut x = + multizip((a.clone().into_iter(), b.clone().into_iter())) + .collect_vec(); + x.reverse(); + + let y = + multizip((a.into_iter(), b.into_iter())) + .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec }); + + TestResult::from_bool(itertools::equal(x, y)) + } + + fn test_double_ended_zip_3(a: Vec, b: Vec, c: Vec) -> TestResult { + let mut x = + multizip((a.clone().into_iter(), b.clone().into_iter(), c.clone().into_iter())) + .collect_vec(); + x.reverse(); + + let y = + multizip((a.into_iter(), b.into_iter(), c.into_iter())) + .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec }); + + TestResult::from_bool(itertools::equal(x, y)) + } +} + + +fn is_fused(mut it: I) -> bool +{ + for _ in it.by_ref() {} + for _ in 0..10{ + if it.next().is_some(){ + return false; + } + } + true +} + +quickcheck! { + fn fused_combination(a: Iter) -> bool + { + is_fused(a.clone().combinations(1)) && + is_fused(a.combinations(3)) + } + + fn fused_combination_with_replacement(a: Iter) -> bool + { + is_fused(a.clone().combinations_with_replacement(1)) && + is_fused(a.combinations_with_replacement(3)) + } + + fn fused_tuple_combination(a: Iter) -> bool + { + is_fused(a.clone().fuse().tuple_combinations::<(_,)>()) && + is_fused(a.fuse().tuple_combinations::<(_,_,_)>()) + } + + fn fused_unique(a: Iter) -> bool + { + is_fused(a.fuse().unique()) + } + + fn fused_unique_by(a: Iter) -> bool + { + is_fused(a.fuse().unique_by(|x| x % 100)) + } + + fn fused_interleave_shortest(a: Iter, b: Iter) -> bool + { + !is_fused(a.clone().interleave_shortest(b.clone())) && + is_fused(a.fuse().interleave_shortest(b.fuse())) + } + + fn fused_product(a: Iter, b: Iter) -> bool + { + is_fused(a.fuse().cartesian_product(b.fuse())) + } + + fn fused_merge(a: Iter, b: Iter) -> bool + { + is_fused(a.fuse().merge(b.fuse())) + } + + fn fused_filter_ok(a: Iter) -> bool + { + is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} ) + .filter_ok(|x| x % 3 == 0) + .fuse()) + } + + fn fused_filter_map_ok(a: Iter) -> bool + { + is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} ) + .filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None}) + .fuse()) + } + + fn fused_positions(a: Iter) -> bool + { + !is_fused(a.clone().positions(|x|x%2==0)) && + is_fused(a.fuse().positions(|x|x%2==0)) + } + + fn fused_update(a: Iter) -> bool + { + !is_fused(a.clone().update(|x|*x+=1)) && + is_fused(a.fuse().update(|x|*x+=1)) + } + + fn fused_tuple_windows(a: Iter) -> bool + { + is_fused(a.fuse().tuple_windows::<(_,_)>()) + } + + fn fused_pad_using(a: Iter) -> bool + { + is_fused(a.fuse().pad_using(100,|_|0)) + } +} + +quickcheck! { + fn min_set_contains_min(a: Vec<(usize, char)>) -> bool { + let result_set = a.iter().min_set(); + if let Some(result_element) = a.iter().min() { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } + + fn min_set_by_contains_min(a: Vec<(usize, char)>) -> bool { + let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1); + let result_set = a.iter().min_set_by(compare); + if let Some(result_element) = a.iter().min_by(compare) { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } + + fn min_set_by_key_contains_min(a: Vec<(usize, char)>) -> bool { + let key = |x: &&(usize, char)| x.1; + let result_set = a.iter().min_set_by_key(&key); + if let Some(result_element) = a.iter().min_by_key(&key) { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } + + fn max_set_contains_max(a: Vec<(usize, char)>) -> bool { + let result_set = a.iter().max_set(); + if let Some(result_element) = a.iter().max() { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } + + fn max_set_by_contains_max(a: Vec<(usize, char)>) -> bool { + let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1); + let result_set = a.iter().max_set_by(compare); + if let Some(result_element) = a.iter().max_by(compare) { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } + + fn max_set_by_key_contains_max(a: Vec<(usize, char)>) -> bool { + let key = |x: &&(usize, char)| x.1; + let result_set = a.iter().max_set_by_key(&key); + if let Some(result_element) = a.iter().max_by_key(&key) { + result_set.contains(&result_element) + } else { + result_set.is_empty() + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/specializations.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/specializations.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/specializations.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/specializations.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,153 @@ +use itertools::Itertools; +use std::fmt::Debug; +use quickcheck::quickcheck; + +struct Unspecialized(I); +impl Iterator for Unspecialized +where + I: Iterator, +{ + type Item = I::Item; + + #[inline(always)] + fn next(&mut self) -> Option { + self.0.next() + } +} + +macro_rules! check_specialized { + ($src:expr, |$it:pat| $closure:expr) => { + let $it = $src.clone(); + let v1 = $closure; + + let $it = Unspecialized($src.clone()); + let v2 = $closure; + + assert_eq!(v1, v2); + } +} + +fn test_specializations( + it: &Iter, +) where + IterItem: Eq + Debug + Clone, + Iter: Iterator + Clone, +{ + check_specialized!(it, |i| i.count()); + check_specialized!(it, |i| i.last()); + check_specialized!(it, |i| i.collect::>()); + check_specialized!(it, |i| { + let mut parameters_from_fold = vec![]; + let fold_result = i.fold(vec![], |mut acc, v: IterItem| { + parameters_from_fold.push((acc.clone(), v.clone())); + acc.push(v); + acc + }); + (parameters_from_fold, fold_result) + }); + check_specialized!(it, |mut i| { + let mut parameters_from_all = vec![]; + let first = i.next(); + let all_result = i.all(|x| { + parameters_from_all.push(x.clone()); + Some(x)==first + }); + (parameters_from_all, all_result) + }); + let size = it.clone().count(); + for n in 0..size + 2 { + check_specialized!(it, |mut i| i.nth(n)); + } + // size_hint is a bit harder to check + let mut it_sh = it.clone(); + for n in 0..size + 2 { + let len = it_sh.clone().count(); + let (min, max) = it_sh.size_hint(); + assert_eq!(size - n.min(size), len); + assert!(min <= len); + if let Some(max) = max { + assert!(len <= max); + } + it_sh.next(); + } +} + +quickcheck! { + fn intersperse(v: Vec) -> () { + test_specializations(&v.into_iter().intersperse(0)); + } +} + +quickcheck! { + fn put_back_qc(test_vec: Vec) -> () { + test_specializations(&itertools::put_back(test_vec.iter())); + let mut pb = itertools::put_back(test_vec.into_iter()); + pb.put_back(1); + test_specializations(&pb); + } +} + +quickcheck! { + fn merge_join_by_qc(i1: Vec, i2: Vec) -> () { + test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp)); + } +} + +quickcheck! { + fn map_into(v: Vec) -> () { + test_specializations(&v.into_iter().map_into::()); + } +} + +quickcheck! { + fn map_ok(v: Vec>) -> () { + test_specializations(&v.into_iter().map_ok(|u| u.checked_add(1))); + } +} + +quickcheck! { + fn process_results(v: Vec>) -> () { + helper(v.iter().copied()); + helper(v.iter().copied().filter(Result::is_ok)); + + fn helper(it: impl Iterator> + Clone) { + macro_rules! check_results_specialized { + ($src:expr, |$it:pat| $closure:expr) => { + assert_eq!( + itertools::process_results($src.clone(), |$it| $closure), + itertools::process_results($src.clone(), |i| { + let $it = Unspecialized(i); + $closure + }), + ) + } + } + + check_results_specialized!(it, |i| i.count()); + check_results_specialized!(it, |i| i.last()); + check_results_specialized!(it, |i| i.collect::>()); + check_results_specialized!(it, |i| { + let mut parameters_from_fold = vec![]; + let fold_result = i.fold(vec![], |mut acc, v| { + parameters_from_fold.push((acc.clone(), v)); + acc.push(v); + acc + }); + (parameters_from_fold, fold_result) + }); + check_results_specialized!(it, |mut i| { + let mut parameters_from_all = vec![]; + let first = i.next(); + let all_result = i.all(|x| { + parameters_from_all.push(x); + Some(x)==first + }); + (parameters_from_all, all_result) + }); + let size = it.clone().count(); + for n in 0..size + 2 { + check_results_specialized!(it, |mut i| i.nth(n)); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_core.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_core.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_core.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_core.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,317 @@ +//! Licensed under the Apache License, Version 2.0 +//! https://www.apache.org/licenses/LICENSE-2.0 or the MIT license +//! https://opensource.org/licenses/MIT, at your +//! option. This file may not be copied, modified, or distributed +//! except according to those terms. +#![no_std] + +use core::iter; +use itertools as it; +use crate::it::Itertools; +use crate::it::interleave; +use crate::it::intersperse; +use crate::it::intersperse_with; +use crate::it::multizip; +use crate::it::free::put_back; +use crate::it::iproduct; +use crate::it::izip; +use crate::it::chain; + +#[test] +fn product2() { + let s = "αβ"; + + let mut prod = iproduct!(s.chars(), 0..2); + assert!(prod.next() == Some(('α', 0))); + assert!(prod.next() == Some(('α', 1))); + assert!(prod.next() == Some(('β', 0))); + assert!(prod.next() == Some(('β', 1))); + assert!(prod.next() == None); +} + +#[test] +fn product_temporary() { + for (_x, _y, _z) in iproduct!( + [0, 1, 2].iter().cloned(), + [0, 1, 2].iter().cloned(), + [0, 1, 2].iter().cloned()) + { + // ok + } +} + + +#[test] +fn izip_macro() { + let mut zip = izip!(2..3); + assert!(zip.next() == Some(2)); + assert!(zip.next().is_none()); + + let mut zip = izip!(0..3, 0..2, 0..2i8); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); + + let xs: [isize; 0] = []; + let mut zip = izip!(0..3, 0..2, 0..2i8, &xs); + assert!(zip.next().is_none()); +} + +#[test] +fn izip2() { + let _zip1: iter::Zip<_, _> = izip!(1.., 2..); + let _zip2: iter::Zip<_, _> = izip!(1.., 2.., ); +} + +#[test] +fn izip3() { + let mut zip: iter::Map, _> = izip!(0..3, 0..2, 0..2i8); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); +} + +#[test] +fn multizip3() { + let mut zip = multizip((0..3, 0..2, 0..2i8)); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); + + let xs: [isize; 0] = []; + let mut zip = multizip((0..3, 0..2, 0..2i8, xs.iter())); + assert!(zip.next().is_none()); + + for (_, _, _, _, _) in multizip((0..3, 0..2, xs.iter(), &xs, xs.to_vec())) { + /* test compiles */ + } +} + +#[test] +fn chain_macro() { + let mut chain = chain!(2..3); + assert!(chain.next() == Some(2)); + assert!(chain.next().is_none()); + + let mut chain = chain!(0..2, 2..3, 3..5i8); + for i in 0..5i8 { + assert_eq!(Some(i), chain.next()); + } + assert!(chain.next().is_none()); + + let mut chain = chain!(); + assert_eq!(chain.next(), Option::<()>::None); +} + +#[test] +fn chain2() { + let _ = chain!(1.., 2..); + let _ = chain!(1.., 2.., ); +} + +#[test] +fn write_to() { + let xs = [7, 9, 8]; + let mut ys = [0; 5]; + let cnt = ys.iter_mut().set_from(xs.iter().copied()); + assert!(cnt == xs.len()); + assert!(ys == [7, 9, 8, 0, 0]); + + let cnt = ys.iter_mut().set_from(0..10); + assert!(cnt == ys.len()); + assert!(ys == [0, 1, 2, 3, 4]); +} + +#[test] +fn test_interleave() { + let xs: [u8; 0] = []; + let ys = [7u8, 9, 8, 10]; + let zs = [2u8, 77]; + let it = interleave(xs.iter(), ys.iter()); + it::assert_equal(it, ys.iter()); + + let rs = [7u8, 2, 9, 77, 8, 10]; + let it = interleave(ys.iter(), zs.iter()); + it::assert_equal(it, rs.iter()); +} + +#[test] +fn test_intersperse() { + let xs = [1u8, 2, 3]; + let ys = [1u8, 0, 2, 0, 3]; + let it = intersperse(&xs, &0); + it::assert_equal(it, ys.iter()); +} + +#[test] +fn test_intersperse_with() { + let xs = [1u8, 2, 3]; + let ys = [1u8, 10, 2, 10, 3]; + let i = 10; + let it = intersperse_with(&xs, || &i); + it::assert_equal(it, ys.iter()); +} + +#[allow(deprecated)] +#[test] +fn foreach() { + let xs = [1i32, 2, 3]; + let mut sum = 0; + xs.iter().foreach(|elt| sum += *elt); + assert!(sum == 6); +} + +#[test] +fn dropping() { + let xs = [1, 2, 3]; + let mut it = xs.iter().dropping(2); + assert_eq!(it.next(), Some(&3)); + assert!(it.next().is_none()); + let mut it = xs.iter().dropping(5); + assert!(it.next().is_none()); +} + +#[test] +fn batching() { + let xs = [0, 1, 2, 1, 3]; + let ys = [(0, 1), (2, 1)]; + + // An iterator that gathers elements up in pairs + let pit = xs + .iter() + .cloned() + .batching(|it| it.next().and_then(|x| it.next().map(|y| (x, y)))); + it::assert_equal(pit, ys.iter().cloned()); +} + +#[test] +fn test_put_back() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let mut pb = put_back(xs.iter().cloned()); + pb.next(); + pb.put_back(1); + pb.put_back(0); + it::assert_equal(pb, xs.iter().cloned()); +} + +#[allow(deprecated)] +#[test] +fn step() { + it::assert_equal((0..10).step(1), 0..10); + it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0)); + it::assert_equal((0..10).step(10), 0..1); +} + +#[allow(deprecated)] +#[test] +fn merge() { + it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10); +} + + +#[test] +fn repeatn() { + let s = "α"; + let mut it = it::repeat_n(s, 3); + assert_eq!(it.len(), 3); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn count_clones() { + // Check that RepeatN only clones N - 1 times. + + use core::cell::Cell; + #[derive(PartialEq, Debug)] + struct Foo { + n: Cell + } + + impl Clone for Foo + { + fn clone(&self) -> Self + { + let n = self.n.get(); + self.n.set(n + 1); + Foo { n: Cell::new(n + 1) } + } + } + + + for n in 0..10 { + let f = Foo{n: Cell::new(0)}; + let it = it::repeat_n(f, n); + // drain it + let last = it.last(); + if n == 0 { + assert_eq!(last, None); + } else { + assert_eq!(last, Some(Foo{n: Cell::new(n - 1)})); + } + } +} + +#[test] +fn part() { + let mut data = [7, 1, 1, 9, 1, 1, 3]; + let i = it::partition(&mut data, |elt| *elt >= 3); + assert_eq!(i, 3); + assert_eq!(data, [7, 3, 9, 1, 1, 1, 1]); + + let i = it::partition(&mut data, |elt| *elt == 1); + assert_eq!(i, 4); + assert_eq!(data, [1, 1, 1, 1, 9, 3, 7]); + + let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let i = it::partition(&mut data, |elt| *elt % 3 == 0); + assert_eq!(i, 3); + assert_eq!(data, [9, 6, 3, 4, 5, 2, 7, 8, 1]); +} + +#[test] +fn tree_fold1() { + for i in 0..100 { + assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); + } +} + +#[test] +fn exactly_one() { + assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); + assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); + assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); + assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); +} + +#[test] +fn at_most_one() { + assert_eq!((0..10).filter(|&x| x == 2).at_most_one().unwrap(), Some(2)); + assert!((0..10).filter(|&x| x > 1 && x < 4).at_most_one().unwrap_err().eq(2..4)); + assert!((0..10).filter(|&x| x > 1 && x < 5).at_most_one().unwrap_err().eq(2..5)); + assert_eq!((0..10).filter(|&_| false).at_most_one().unwrap(), None); +} + +#[test] +fn sum1() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v[..0].iter().cloned().sum1::(), None); + assert_eq!(v[1..2].iter().cloned().sum1::(), Some(1)); + assert_eq!(v[1..3].iter().cloned().sum1::(), Some(3)); + assert_eq!(v.iter().cloned().sum1::(), Some(55)); +} + +#[test] +fn product1() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v[..0].iter().cloned().product1::(), None); + assert_eq!(v[..1].iter().cloned().product1::(), Some(0)); + assert_eq!(v[1..3].iter().cloned().product1::(), Some(2)); + assert_eq!(v[1..5].iter().cloned().product1::(), Some(24)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_std.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/test_std.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,1168 @@ +use quickcheck as qc; +use rand::{distributions::{Distribution, Standard}, Rng, SeedableRng, rngs::StdRng}; +use rand::{seq::SliceRandom, thread_rng}; +use std::{cmp::min, fmt::Debug, marker::PhantomData}; +use itertools as it; +use crate::it::Itertools; +use crate::it::ExactlyOneError; +use crate::it::multizip; +use crate::it::multipeek; +use crate::it::peek_nth; +use crate::it::free::rciter; +use crate::it::free::put_back_n; +use crate::it::FoldWhile; +use crate::it::cloned; +use crate::it::iproduct; +use crate::it::izip; + +#[test] +fn product3() { + let prod = iproduct!(0..3, 0..2, 0..2); + assert_eq!(prod.size_hint(), (12, Some(12))); + let v = prod.collect_vec(); + for i in 0..3 { + for j in 0..2 { + for k in 0..2 { + assert!((i, j, k) == v[(i * 2 * 2 + j * 2 + k) as usize]); + } + } + } + for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { + /* test compiles */ + } +} + +#[test] +fn interleave_shortest() { + let v0: Vec = vec![0, 2, 4]; + let v1: Vec = vec![1, 3, 5, 7]; + let it = v0.into_iter().interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); + + let v0: Vec = vec![0, 2, 4, 6, 8]; + let v1: Vec = vec![1, 3, 5]; + let it = v0.into_iter().interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); + + let i0 = ::std::iter::repeat(0); + let v1: Vec<_> = vec![1, 3, 5]; + let it = i0.interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (7, Some(7))); + + let v0: Vec<_> = vec![0, 2, 4]; + let i1 = ::std::iter::repeat(1); + let it = v0.into_iter().interleave_shortest(i1); + assert_eq!(it.size_hint(), (6, Some(6))); +} + +#[test] +fn duplicates_by() { + let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; + let ys = ["aa", "bbbb", "cccc"]; + it::assert_equal(ys.iter(), xs.iter().duplicates_by(|x| x[..2].to_string())); + it::assert_equal(ys.iter(), xs.iter().rev().duplicates_by(|x| x[..2].to_string()).rev()); + let ys_rev = ["ccc", "aa", "bbbbb"]; + it::assert_equal(ys_rev.iter(), xs.iter().duplicates_by(|x| x[..2].to_string()).rev()); +} + +#[test] +fn duplicates() { + let xs = [0, 1, 2, 3, 2, 1, 3]; + let ys = [2, 1, 3]; + it::assert_equal(ys.iter(), xs.iter().duplicates()); + it::assert_equal(ys.iter(), xs.iter().rev().duplicates().rev()); + let ys_rev = [3, 2, 1]; + it::assert_equal(ys_rev.iter(), xs.iter().duplicates().rev()); + + let xs = [0, 1, 0, 1]; + let ys = [0, 1]; + it::assert_equal(ys.iter(), xs.iter().duplicates()); + it::assert_equal(ys.iter(), xs.iter().rev().duplicates().rev()); + let ys_rev = [1, 0]; + it::assert_equal(ys_rev.iter(), xs.iter().duplicates().rev()); + + let xs = vec![0, 1, 2, 1, 2]; + let ys = vec![1, 2]; + assert_eq!(ys, xs.iter().duplicates().cloned().collect_vec()); + assert_eq!(ys, xs.iter().rev().duplicates().rev().cloned().collect_vec()); + let ys_rev = vec![2, 1]; + assert_eq!(ys_rev, xs.iter().duplicates().rev().cloned().collect_vec()); +} + +#[test] +fn unique_by() { + let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; + let ys = ["aaa", "bbbbb", "ccc"]; + it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); + it::assert_equal(ys.iter(), xs.iter().rev().unique_by(|x| x[..2].to_string()).rev()); + let ys_rev = ["cccc", "aaaaa", "bbbb"]; + it::assert_equal(ys_rev.iter(), xs.iter().unique_by(|x| x[..2].to_string()).rev()); +} + +#[test] +fn unique() { + let xs = [0, 1, 2, 3, 2, 1, 3]; + let ys = [0, 1, 2, 3]; + it::assert_equal(ys.iter(), xs.iter().unique()); + it::assert_equal(ys.iter(), xs.iter().rev().unique().rev()); + let ys_rev = [3, 1, 2, 0]; + it::assert_equal(ys_rev.iter(), xs.iter().unique().rev()); + + let xs = [0, 1]; + let ys = [0, 1]; + it::assert_equal(ys.iter(), xs.iter().unique()); + it::assert_equal(ys.iter(), xs.iter().rev().unique().rev()); + let ys_rev = [1, 0]; + it::assert_equal(ys_rev.iter(), xs.iter().unique().rev()); +} + +#[test] +fn intersperse() { + let xs = ["a", "", "b", "c"]; + let v: Vec<&str> = xs.iter().cloned().intersperse(", ").collect(); + let text: String = v.concat(); + assert_eq!(text, "a, , b, c".to_string()); + + let ys = [0, 1, 2, 3]; + let mut it = ys[..0].iter().copied().intersperse(1); + assert!(it.next() == None); +} + +#[test] +fn dedup() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let ys = [0, 1, 2, 1, 3]; + it::assert_equal(ys.iter(), xs.iter().dedup()); + let xs = [0, 0, 0, 0, 0]; + let ys = [0]; + it::assert_equal(ys.iter(), xs.iter().dedup()); + + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let ys = [0, 1, 2, 1, 3]; + let mut xs_d = Vec::new(); + xs.iter().dedup().fold((), |(), &elt| xs_d.push(elt)); + assert_eq!(&xs_d, &ys); +} + +#[test] +fn coalesce() { + let data = vec![-1., -2., -3., 3., 1., 0., -1.]; + let it = data.iter().cloned().coalesce(|x, y| + if (x >= 0.) == (y >= 0.) { + Ok(x + y) + } else { + Err((x, y)) + } + ); + itertools::assert_equal(it.clone(), vec![-6., 4., -1.]); + assert_eq!( + it.fold(vec![], |mut v, n| { + v.push(n); + v + }), + vec![-6., 4., -1.] + ); +} + +#[test] +fn dedup_by() { + let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; + let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; + it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.1==y.1)); + let xs = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]; + let ys = [(0, 1)]; + it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.0==y.0)); + + let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; + let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; + let mut xs_d = Vec::new(); + xs.iter().dedup_by(|x, y| x.1==y.1).fold((), |(), &elt| xs_d.push(elt)); + assert_eq!(&xs_d, &ys); +} + +#[test] +fn dedup_with_count() { + let xs: [i32; 8] = [0, 1, 1, 1, 2, 1, 3, 3]; + let ys: [(usize, &i32); 5] = [(1, &0), (3, &1), (1, &2), (1, &1), (2, &3)]; + + it::assert_equal(ys.iter().cloned(), xs.iter().dedup_with_count()); + + let xs: [i32; 5] = [0, 0, 0, 0, 0]; + let ys: [(usize, &i32); 1] = [(5, &0)]; + + it::assert_equal(ys.iter().cloned(), xs.iter().dedup_with_count()); +} + + +#[test] +fn dedup_by_with_count() { + let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; + let ys = [(1, &(0, 0)), (3, &(0, 1)), (1, &(0, 2)), (1, &(3, 1)), (2, &(0, 3))]; + + it::assert_equal(ys.iter().cloned(), xs.iter().dedup_by_with_count(|x, y| x.1==y.1)); + + let xs = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]; + let ys = [( 5, &(0, 1))]; + + it::assert_equal(ys.iter().cloned(), xs.iter().dedup_by_with_count(|x, y| x.0==y.0)); +} + +#[test] +fn all_equal() { + assert!("".chars().all_equal()); + assert!("A".chars().all_equal()); + assert!(!"AABBCCC".chars().all_equal()); + assert!("AAAAAAA".chars().all_equal()); + for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) { + assert!(sub.all_equal()); + } +} + +#[test] +fn all_unique() { + assert!("ABCDEFGH".chars().all_unique()); + assert!(!"ABCDEFGA".chars().all_unique()); + assert!(::std::iter::empty::().all_unique()); +} + +#[test] +fn test_put_back_n() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let mut pb = put_back_n(xs.iter().cloned()); + pb.next(); + pb.next(); + pb.put_back(1); + pb.put_back(0); + it::assert_equal(pb, xs.iter().cloned()); +} + +#[test] +fn tee() { + let xs = [0, 1, 2, 3]; + let (mut t1, mut t2) = xs.iter().cloned().tee(); + assert_eq!(t1.next(), Some(0)); + assert_eq!(t2.next(), Some(0)); + assert_eq!(t1.next(), Some(1)); + assert_eq!(t1.next(), Some(2)); + assert_eq!(t1.next(), Some(3)); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), Some(1)); + assert_eq!(t2.next(), Some(2)); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), Some(3)); + assert_eq!(t2.next(), None); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), None); + + let (t1, t2) = xs.iter().cloned().tee(); + it::assert_equal(t1, xs.iter().cloned()); + it::assert_equal(t2, xs.iter().cloned()); + + let (t1, t2) = xs.iter().cloned().tee(); + it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned())); +} + + +#[test] +fn test_rciter() { + let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6]; + + let mut r1 = rciter(xs.iter().cloned()); + let mut r2 = r1.clone(); + assert_eq!(r1.next(), Some(0)); + assert_eq!(r2.next(), Some(1)); + let mut z = r1.zip(r2); + assert_eq!(z.next(), Some((1, 1))); + assert_eq!(z.next(), Some((2, 1))); + assert_eq!(z.next(), Some((3, 5))); + assert_eq!(z.next(), None); + + // test intoiterator + let r1 = rciter(0..5); + let mut z = izip!(&r1, r1); + assert_eq!(z.next(), Some((0, 1))); +} + +#[allow(deprecated)] +#[test] +fn trait_pointers() { + struct ByRef<'r, I: ?Sized>(&'r mut I) ; + + impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where + I: 'r + Iterator + { + type Item = X; + fn next(&mut self) -> Option + { + self.0.next() + } + } + + let mut it = Box::new(0..10) as Box>; + assert_eq!(it.next(), Some(0)); + + { + /* make sure foreach works on non-Sized */ + let jt: &mut dyn Iterator = &mut *it; + assert_eq!(jt.next(), Some(1)); + + { + let mut r = ByRef(jt); + assert_eq!(r.next(), Some(2)); + } + + assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4))); + jt.foreach(|_| ()); + } +} + +#[test] +fn merge_by() { + let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; + let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; + let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")]; + let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0); + it::assert_equal(results, expected.iter()); +} + +#[test] +fn merge_by_btree() { + use std::collections::BTreeMap; + let mut bt1 = BTreeMap::new(); + bt1.insert("hello", 1); + bt1.insert("world", 3); + let mut bt2 = BTreeMap::new(); + bt2.insert("foo", 2); + bt2.insert("bar", 4); + let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 ); + let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; + it::assert_equal(results, expected.into_iter()); +} + +#[allow(deprecated)] +#[test] +fn kmerge() { + let its = (0..4).map(|s| (s..10).step(4)); + + it::assert_equal(its.kmerge(), 0..10); +} + +#[allow(deprecated)] +#[test] +fn kmerge_2() { + let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4)); + + it::assert_equal(its.kmerge(), 0..10); +} + +#[test] +fn kmerge_empty() { + let its = (0..4).map(|_| 0..0); + assert_eq!(its.kmerge().next(), None); +} + +#[test] +fn kmerge_size_hint() { + let its = (0..5).map(|_| (0..10)); + assert_eq!(its.kmerge().size_hint(), (50, Some(50))); +} + +#[test] +fn kmerge_empty_size_hint() { + let its = (0..5).map(|_| (0..0)); + assert_eq!(its.kmerge().size_hint(), (0, Some(0))); +} + +#[test] +fn join() { + let many = [1, 2, 3]; + let one = [1]; + let none: Vec = vec![]; + + assert_eq!(many.iter().join(", "), "1, 2, 3"); + assert_eq!( one.iter().join(", "), "1"); + assert_eq!(none.iter().join(", "), ""); +} + +#[test] +fn sorted_unstable_by() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { + a.cmp(&b) + }); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_unstable_by(|&a, &b| a.cmp(&b).reverse()); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +#[test] +fn sorted_unstable_by_key() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_unstable_by_key(|&x| x); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_unstable_by_key(|&x| -x); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +#[test] +fn sorted_by() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { + a.cmp(&b) + }); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse()); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +qc::quickcheck! { + fn k_smallest_range(n: u64, m: u16, k: u16) -> () { + // u16 is used to constrain k and m to 0..2¹⁶, + // otherwise the test could use too much memory. + let (k, m) = (k as u64, m as u64); + + // Generate a random permutation of n..n+m + let i = { + let mut v: Vec = (n..n.saturating_add(m)).collect(); + v.shuffle(&mut thread_rng()); + v.into_iter() + }; + + // Check that taking the k smallest elements yields n..n+min(k, m) + it::assert_equal( + i.k_smallest(k as usize), + n..n.saturating_add(min(k, m)) + ); + } +} + +#[derive(Clone, Debug)] +struct RandIter { + idx: usize, + len: usize, + rng: R, + _t: PhantomData +} + +impl Iterator for RandIter +where Standard: Distribution { + type Item = T; + fn next(&mut self) -> Option { + if self.idx == self.len { + None + } else { + self.idx += 1; + Some(self.rng.gen()) + } + } +} + +impl qc::Arbitrary for RandIter { + fn arbitrary(g: &mut G) -> Self { + RandIter { + idx: 0, + len: g.size(), + rng: R::seed_from_u64(g.next_u64()), + _t : PhantomData{}, + } + } +} + +// Check that taking the k smallest is the same as +// sorting then taking the k first elements +fn k_smallest_sort(i: I, k: u16) +where + I: Iterator + Clone, + I::Item: Ord + Debug, +{ + let j = i.clone(); + let k = k as usize; + it::assert_equal( + i.k_smallest(k), + j.sorted().take(k) + ) +} + +macro_rules! generic_test { + ($f:ident, $($t:ty),+) => { + $(paste::item! { + qc::quickcheck! { + fn [< $f _ $t >](i: RandIter<$t>, k: u16) -> () { + $f(i, k) + } + } + })+ + }; +} + +generic_test!(k_smallest_sort, u8, u16, u32, u64, i8, i16, i32, i64); + +#[test] +fn sorted_by_key() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_by_key(|&x| x); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_by_key(|&x| -x); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +#[test] +fn sorted_by_cached_key() { + // Track calls to key function + let mut ncalls = 0; + + let sorted = [3, 4, 1, 2].iter().cloned().sorted_by_cached_key(|&x| { + ncalls += 1; + x.to_string() + }); + it::assert_equal(sorted, vec![1, 2, 3, 4]); + // Check key function called once per element + assert_eq!(ncalls, 4); + + let mut ncalls = 0; + + let sorted = (0..5).sorted_by_cached_key(|&x| { + ncalls += 1; + -x + }); + it::assert_equal(sorted, vec![4, 3, 2, 1, 0]); + // Check key function called once per element + assert_eq!(ncalls, 5); +} + +#[test] +fn test_multipeek() { + let nums = vec![1u8,2,3,4,5]; + + let mp = multipeek(nums.iter().copied()); + assert_eq!(nums, mp.collect::>()); + + let mut mp = multipeek(nums.iter().copied()); + assert_eq!(mp.peek(), Some(&1)); + assert_eq!(mp.next(), Some(1)); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.next(), Some(2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(3)); + assert_eq!(mp.next(), Some(4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(5)); + assert_eq!(mp.next(), None); + assert_eq!(mp.peek(), None); +} + +#[test] +fn test_multipeek_reset() { + let data = [1, 2, 3, 4]; + + let mut mp = multipeek(cloned(&data)); + assert_eq!(mp.peek(), Some(&1)); + assert_eq!(mp.next(), Some(1)); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.peek(), Some(&3)); + mp.reset_peek(); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.next(), Some(2)); +} + +#[test] +fn test_multipeek_peeking_next() { + use crate::it::PeekingNext; + let nums = vec![1u8,2,3,4,5,6,7]; + + let mut mp = multipeek(nums.iter().copied()); + assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); + assert_eq!(mp.next(), Some(2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peeking_next(|&x| x == 3), Some(3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peeking_next(|&x| x != 4), None); + assert_eq!(mp.peeking_next(|&x| x == 4), Some(4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), Some(&6)); + assert_eq!(mp.peeking_next(|&x| x != 5), None); + assert_eq!(mp.peek(), Some(&7)); + assert_eq!(mp.peeking_next(|&x| x == 5), Some(5)); + assert_eq!(mp.peeking_next(|&x| x == 6), Some(6)); + assert_eq!(mp.peek(), Some(&7)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(7)); + assert_eq!(mp.peek(), None); +} + +#[test] +fn test_peek_nth() { + let nums = vec![1u8,2,3,4,5]; + + let iter = peek_nth(nums.iter().copied()); + assert_eq!(nums, iter.collect::>()); + + let mut iter = peek_nth(nums.iter().copied()); + + assert_eq!(iter.peek_nth(0), Some(&1)); + assert_eq!(iter.peek_nth(0), Some(&1)); + assert_eq!(iter.next(), Some(1)); + + assert_eq!(iter.peek_nth(0), Some(&2)); + assert_eq!(iter.peek_nth(1), Some(&3)); + assert_eq!(iter.next(), Some(2)); + + assert_eq!(iter.peek_nth(0), Some(&3)); + assert_eq!(iter.peek_nth(1), Some(&4)); + assert_eq!(iter.peek_nth(2), Some(&5)); + assert_eq!(iter.peek_nth(3), None); + + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), Some(4)); + + assert_eq!(iter.peek_nth(0), Some(&5)); + assert_eq!(iter.peek_nth(1), None); + assert_eq!(iter.next(), Some(5)); + assert_eq!(iter.next(), None); + + assert_eq!(iter.peek_nth(0), None); + assert_eq!(iter.peek_nth(1), None); +} + +#[test] +fn test_peek_nth_peeking_next() { + use it::PeekingNext; + let nums = vec![1u8,2,3,4,5,6,7]; + let mut iter = peek_nth(nums.iter().copied()); + + assert_eq!(iter.peeking_next(|&x| x != 0), Some(1)); + assert_eq!(iter.next(), Some(2)); + + assert_eq!(iter.peek_nth(0), Some(&3)); + assert_eq!(iter.peek_nth(1), Some(&4)); + assert_eq!(iter.peeking_next(|&x| x == 3), Some(3)); + assert_eq!(iter.peek(), Some(&4)); + + assert_eq!(iter.peeking_next(|&x| x != 4), None); + assert_eq!(iter.peeking_next(|&x| x == 4), Some(4)); + assert_eq!(iter.peek_nth(0), Some(&5)); + assert_eq!(iter.peek_nth(1), Some(&6)); + + assert_eq!(iter.peeking_next(|&x| x != 5), None); + assert_eq!(iter.peek(), Some(&5)); + + assert_eq!(iter.peeking_next(|&x| x == 5), Some(5)); + assert_eq!(iter.peeking_next(|&x| x == 6), Some(6)); + assert_eq!(iter.peek_nth(0), Some(&7)); + assert_eq!(iter.peek_nth(1), None); + assert_eq!(iter.next(), Some(7)); + assert_eq!(iter.peek(), None); +} + +#[test] +fn pad_using() { + it::assert_equal((0..0).pad_using(1, |_| 1), 1..2); + + let v: Vec = vec![0, 1, 2]; + let r = v.into_iter().pad_using(5, |n| n); + it::assert_equal(r, vec![0, 1, 2, 3, 4]); + + let v: Vec = vec![0, 1, 2]; + let r = v.into_iter().pad_using(1, |_| panic!()); + it::assert_equal(r, vec![0, 1, 2]); +} + +#[test] +fn group_by() { + for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) { + for ch2 in sub { + assert_eq!(ch1, ch2); + } + } + + for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) { + for ch2 in sub { + assert_eq!(ch1, ch2); + if ch1 == 'C' { + break; + } + } + } + + let toupper = |ch: &char| ch.to_uppercase().next().unwrap(); + + // try all possible orderings + for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) { + let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper); + let mut subs = groups.into_iter().collect_vec(); + + for &idx in &indices[..] { + let (key, text) = match idx { + 0 => ('A', "Aaa".chars()), + 1 => ('B', "Bbb".chars()), + 2 => ('C', "ccCc".chars()), + 3 => ('D', "DDDD".chars()), + _ => unreachable!(), + }; + assert_eq!(key, subs[idx].0); + it::assert_equal(&mut subs[idx].1, text); + } + } + + let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x); + let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec(); + + let sd = subs.pop().unwrap(); + let sc = subs.pop().unwrap(); + let sb = subs.pop().unwrap(); + let sa = subs.pop().unwrap(); + for (a, b, c, d) in multizip((sa, sb, sc, sd)) { + assert_eq!(a, 'A'); + assert_eq!(b, 'B'); + assert_eq!(c, 'C'); + assert_eq!(d, 'D'); + } + + // check that the key closure is called exactly n times + { + let mut ntimes = 0; + let text = "AABCCC"; + for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) { + for _ in sub { + } + } + assert_eq!(ntimes, text.len()); + } + + { + let mut ntimes = 0; + let text = "AABCCC"; + for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) { + } + assert_eq!(ntimes, text.len()); + } + + { + let text = "ABCCCDEEFGHIJJKK"; + let gr = text.chars().group_by(|&x| x); + it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars()); + } +} + +#[test] +fn group_by_lazy_2() { + let data = vec![0, 1]; + let groups = data.iter().group_by(|k| *k); + let gs = groups.into_iter().collect_vec(); + it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); + + let data = vec![0, 1, 1, 0, 0]; + let groups = data.iter().group_by(|k| *k); + let mut gs = groups.into_iter().collect_vec(); + gs[1..].reverse(); + it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g)); + + let grouper = data.iter().group_by(|k| *k); + let mut groups = Vec::new(); + for (k, group) in &grouper { + if *k == 1 { + groups.push(group); + } + } + it::assert_equal(&mut groups[0], &[1, 1]); + + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let grouper = data.iter().group_by(|k| *k); + let mut groups = Vec::new(); + for (i, (_, group)) in grouper.into_iter().enumerate() { + if i < 2 { + groups.push(group); + } else if i < 4 { + for _ in group { + } + } else { + groups.push(group); + } + } + it::assert_equal(&mut groups[0], &[0, 0, 0]); + it::assert_equal(&mut groups[1], &[1, 1]); + it::assert_equal(&mut groups[2], &[3, 3]); + + // use groups as chunks + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let mut i = 0; + let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k }); + for (i, group) in &grouper { + match i { + 0 => it::assert_equal(group, &[0, 0, 0]), + 1 => it::assert_equal(group, &[1, 1, 0]), + 2 => it::assert_equal(group, &[0, 2, 2]), + 3 => it::assert_equal(group, &[3, 3]), + _ => unreachable!(), + } + } +} + +#[test] +fn group_by_lazy_3() { + // test consuming each group on the lap after it was produced + let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; + let grouper = data.iter().group_by(|elt| *elt); + let mut last = None; + for (key, group) in &grouper { + if let Some(gr) = last.take() { + for elt in gr { + assert!(elt != key && i32::abs(elt - key) == 1); + } + } + last = Some(group); + } +} + +#[test] +fn chunks() { + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let grouper = data.iter().chunks(3); + for (i, chunk) in grouper.into_iter().enumerate() { + match i { + 0 => it::assert_equal(chunk, &[0, 0, 0]), + 1 => it::assert_equal(chunk, &[1, 1, 0]), + 2 => it::assert_equal(chunk, &[0, 2, 2]), + 3 => it::assert_equal(chunk, &[3, 3]), + _ => unreachable!(), + } + } +} + +#[test] +fn concat_empty() { + let data: Vec> = Vec::new(); + assert_eq!(data.into_iter().concat(), Vec::new()) +} + +#[test] +fn concat_non_empty() { + let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]]; + assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9]) +} + +#[test] +fn combinations() { + assert!((1..3).combinations(5).next().is_none()); + + let it = (1..3).combinations(2); + it::assert_equal(it, vec![ + vec![1, 2], + ]); + + let it = (1..5).combinations(2); + it::assert_equal(it, vec![ + vec![1, 2], + vec![1, 3], + vec![1, 4], + vec![2, 3], + vec![2, 4], + vec![3, 4], + ]); + + it::assert_equal((0..0).tuple_combinations::<(_, _)>(), >::new()); + it::assert_equal((0..1).tuple_combinations::<(_, _)>(), >::new()); + it::assert_equal((0..2).tuple_combinations::<(_, _)>(), vec![(0, 1)]); + + it::assert_equal((0..0).combinations(2), >>::new()); + it::assert_equal((0..1).combinations(1), vec![vec![0]]); + it::assert_equal((0..2).combinations(1), vec![vec![0], vec![1]]); + it::assert_equal((0..2).combinations(2), vec![vec![0, 1]]); +} + +#[test] +fn combinations_of_too_short() { + for i in 1..10 { + assert!((0..0).combinations(i).next().is_none()); + assert!((0..i - 1).combinations(i).next().is_none()); + } +} + + +#[test] +fn combinations_zero() { + it::assert_equal((1..3).combinations(0), vec![vec![]]); + it::assert_equal((0..0).combinations(0), vec![vec![]]); +} + +#[test] +fn permutations_zero() { + it::assert_equal((1..3).permutations(0), vec![vec![]]); + it::assert_equal((0..0).permutations(0), vec![vec![]]); +} + +#[test] +fn combinations_with_replacement() { + // Pool smaller than n + it::assert_equal((0..1).combinations_with_replacement(2), vec![vec![0, 0]]); + // Pool larger than n + it::assert_equal( + (0..3).combinations_with_replacement(2), + vec![ + vec![0, 0], + vec![0, 1], + vec![0, 2], + vec![1, 1], + vec![1, 2], + vec![2, 2], + ], + ); + // Zero size + it::assert_equal( + (0..3).combinations_with_replacement(0), + vec![vec![]], + ); + // Zero size on empty pool + it::assert_equal( + (0..0).combinations_with_replacement(0), + vec![vec![]], + ); + // Empty pool + it::assert_equal( + (0..0).combinations_with_replacement(2), + >>::new(), + ); +} + +#[test] +fn powerset() { + it::assert_equal((0..0).powerset(), vec![vec![]]); + it::assert_equal((0..1).powerset(), vec![vec![], vec![0]]); + it::assert_equal((0..2).powerset(), vec![vec![], vec![0], vec![1], vec![0, 1]]); + it::assert_equal((0..3).powerset(), vec![ + vec![], + vec![0], vec![1], vec![2], + vec![0, 1], vec![0, 2], vec![1, 2], + vec![0, 1, 2] + ]); + + assert_eq!((0..4).powerset().count(), 1 << 4); + assert_eq!((0..8).powerset().count(), 1 << 8); + assert_eq!((0..16).powerset().count(), 1 << 16); +} + +#[test] +fn diff_mismatch() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 5.0, 3.0, 4.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::FirstMismatch(1, _, from_diff)) => + from_diff.collect::>() == vec![5, 3, 4], + _ => false, + }); +} + +#[test] +fn diff_longer() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::Longer(_, remaining)) => + remaining.collect::>() == vec![5, 6], + _ => false, + }); +} + +#[test] +fn diff_shorter() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 2.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::Shorter(len, _)) => len == 2, + _ => false, + }); +} + +#[test] +fn extrema_set() { + use std::cmp::Ordering; + + // A peculiar type: Equality compares both tuple items, but ordering only the + // first item. Used to distinguish equal elements. + #[derive(Clone, Debug, PartialEq, Eq)] + struct Val(u32, u32); + + impl PartialOrd for Val { + fn partial_cmp(&self, other: &Val) -> Option { + self.0.partial_cmp(&other.0) + } + } + + impl Ord for Val { + fn cmp(&self, other: &Val) -> Ordering { + self.0.cmp(&other.0) + } + } + + assert_eq!(None::.iter().min_set(), Vec::<&u32>::new()); + assert_eq!(None::.iter().max_set(), Vec::<&u32>::new()); + + assert_eq!(Some(1u32).iter().min_set(), vec![&1]); + assert_eq!(Some(1u32).iter().max_set(), vec![&1]); + + let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; + + let min_set = data.iter().min_set(); + assert_eq!(min_set, vec![&Val(0, 1), &Val(0, 2)]); + + let min_set_by_key = data.iter().min_set_by_key(|v| v.1); + assert_eq!(min_set_by_key, vec![&Val(2, 0), &Val(1, 0)]); + + let min_set_by = data.iter().min_set_by(|x, y| x.1.cmp(&y.1)); + assert_eq!(min_set_by, vec![&Val(2, 0), &Val(1, 0)]); + + let max_set = data.iter().max_set(); + assert_eq!(max_set, vec![&Val(2, 0), &Val(2, 1)]); + + let max_set_by_key = data.iter().max_set_by_key(|v| v.1); + assert_eq!(max_set_by_key, vec![&Val(0, 2)]); + + let max_set_by = data.iter().max_set_by(|x, y| x.1.cmp(&y.1)); + assert_eq!(max_set_by, vec![&Val(0, 2)]); +} + +#[test] +fn minmax() { + use std::cmp::Ordering; + use crate::it::MinMaxResult; + + // A peculiar type: Equality compares both tuple items, but ordering only the + // first item. This is so we can check the stability property easily. + #[derive(Clone, Debug, PartialEq, Eq)] + struct Val(u32, u32); + + impl PartialOrd for Val { + fn partial_cmp(&self, other: &Val) -> Option { + self.0.partial_cmp(&other.0) + } + } + + impl Ord for Val { + fn cmp(&self, other: &Val) -> Ordering { + self.0.cmp(&other.0) + } + } + + assert_eq!(None::>.iter().minmax(), MinMaxResult::NoElements); + + assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1)); + + let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; + + let minmax = data.iter().minmax(); + assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1))); + + let (min, max) = data.iter().minmax_by_key(|v| v.1).into_option().unwrap(); + assert_eq!(min, &Val(2, 0)); + assert_eq!(max, &Val(0, 2)); + + let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap(); + assert_eq!(min, &Val(2, 0)); + assert_eq!(max, &Val(0, 2)); +} + +#[test] +fn format() { + let data = [0, 1, 2, 3]; + let ans1 = "0, 1, 2, 3"; + let ans2 = "0--1--2--3"; + + let t1 = format!("{}", data.iter().format(", ")); + assert_eq!(t1, ans1); + let t2 = format!("{:?}", data.iter().format("--")); + assert_eq!(t2, ans2); + + let dataf = [1.1, 5.71828, -22.]; + let t3 = format!("{:.2e}", dataf.iter().format(", ")); + assert_eq!(t3, "1.10e0, 5.72e0, -2.20e1"); +} + +#[test] +fn while_some() { + let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None }) + .while_some(); + it::assert_equal(ns, vec![1, 2, 3, 4]); +} + +#[allow(deprecated)] +#[test] +fn fold_while() { + let mut iterations = 0; + let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let sum = vec.into_iter().fold_while(0, |acc, item| { + iterations += 1; + let new_sum = acc + item; + if new_sum <= 20 { + FoldWhile::Continue(new_sum) + } else { + FoldWhile::Done(acc) + } + }).into_inner(); + assert_eq!(iterations, 6); + assert_eq!(sum, 15); +} + +#[test] +fn tree_fold1() { + let x = [ + "", + "0", + "0 1 x", + "0 1 x 2 x", + "0 1 x 2 3 x x", + "0 1 x 2 3 x x 4 x", + "0 1 x 2 3 x x 4 5 x x", + "0 1 x 2 3 x x 4 5 x 6 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x", + ]; + for (i, &s) in x.iter().enumerate() { + let expected = if s.is_empty() { None } else { Some(s.to_string()) }; + let num_strings = (0..i).map(|x| x.to_string()); + let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); + assert_eq!(actual, expected); + } +} + +#[test] +fn exactly_one_question_mark_syntax_works() { + exactly_one_question_mark_return().unwrap_err(); +} + +fn exactly_one_question_mark_return() -> Result<(), ExactlyOneError>> { + [].iter().exactly_one()?; + Ok(()) +} + +#[test] +fn multiunzip() { + let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2), (3, 4, 5), (6, 7, 8)].iter().cloned().multiunzip(); + assert_eq!((a, b, c), (vec![0, 3, 6], vec![1, 4, 7], vec![2, 5, 8])); + let (): () = [(), (), ()].iter().cloned().multiunzip(); + let t: (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)].iter().cloned().multiunzip(); + assert_eq!(t, (vec![0], vec![1], vec![2], vec![3], vec![4], vec![5], vec![6], vec![7], vec![8], vec![9], vec![10], vec![11])); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/tuples.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/tuples.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/tuples.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/tuples.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,86 @@ +use itertools::Itertools; + +#[test] +fn tuples() { + let v = [1, 2, 3, 4, 5]; + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1,)), iter.next()); + assert_eq!(Some((2,)), iter.next()); + assert_eq!(Some((3,)), iter.next()); + assert_eq!(Some((4,)), iter.next()); + assert_eq!(Some((5,)), iter.next()); + assert_eq!(None, iter.next()); + assert_eq!(None, iter.into_buffer().next()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2)), iter.next()); + assert_eq!(Some((3, 4)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![5], iter.into_buffer()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2, 3)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![4, 5], iter.into_buffer()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2, 3, 4)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![5], iter.into_buffer()); +} + +#[test] +fn tuple_windows() { + let v = [1, 2, 3, 4, 5]; + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1,)), iter.next()); + assert_eq!(Some((2,)), iter.next()); + assert_eq!(Some((3,)), iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2)), iter.next()); + assert_eq!(Some((2, 3)), iter.next()); + assert_eq!(Some((3, 4)), iter.next()); + assert_eq!(Some((4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2, 3)), iter.next()); + assert_eq!(Some((2, 3, 4)), iter.next()); + assert_eq!(Some((3, 4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2, 3, 4)), iter.next()); + assert_eq!(Some((2, 3, 4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let v = [1, 2, 3]; + let mut iter = v.iter().cloned().tuple_windows::<(_, _, _, _)>(); + assert_eq!(None, iter.next()); +} + +#[test] +fn next_tuple() { + let v = [1, 2, 3, 4, 5]; + let mut iter = v.iter(); + assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((1, 2))); + assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((3, 4))); + assert_eq!(iter.next_tuple::<(_, _)>(), None); +} + +#[test] +fn collect_tuple() { + let v = [1, 2]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple(), Some((1, 2))); + + let v = [1]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple::<(_, _)>(), None); + + let v = [1, 2, 3]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple::<(_, _)>(), None); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/zip.rs clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/zip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/itertools-0.10.5/tests/zip.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools-0.10.5/tests/zip.rs 2022-09-20 14:25:21.000000000 +0000 @@ -0,0 +1,77 @@ +use itertools::Itertools; +use itertools::EitherOrBoth::{Both, Left, Right}; +use itertools::free::zip_eq; +use itertools::multizip; + +#[test] +fn zip_longest_fused() { + let a = [Some(1), None, Some(3), Some(4)]; + let b = [1, 2, 3]; + + let unfused = a.iter().batching(|it| *it.next().unwrap()) + .zip_longest(b.iter().cloned()); + itertools::assert_equal(unfused, + vec![Both(1, 1), Right(2), Right(3)]); +} + +#[test] +fn test_zip_longest_size_hint() { + let c = (1..10).cycle(); + let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10, 11, 12]; + + assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None)); + + assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10))); +} + +#[test] +fn test_double_ended_zip_longest() { + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + let a = xs.iter().copied(); + let b = ys.iter().copied(); + let mut it = a.zip_longest(b); + assert_eq!(it.next(), Some(Both(1, 1))); + assert_eq!(it.next(), Some(Both(2, 2))); + assert_eq!(it.next_back(), Some(Left(6))); + assert_eq!(it.next_back(), Some(Left(5))); + assert_eq!(it.next_back(), Some(Both(4, 7))); + assert_eq!(it.next(), Some(Both(3, 3))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_double_ended_zip() { + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + let a = xs.iter().copied(); + let b = ys.iter().copied(); + let mut it = multizip((a, b)); + assert_eq!(it.next_back(), Some((4, 7))); + assert_eq!(it.next_back(), Some((3, 3))); + assert_eq!(it.next_back(), Some((2, 2))); + assert_eq!(it.next_back(), Some((1, 1))); + assert_eq!(it.next_back(), None); +} + + +#[should_panic] +#[test] +fn zip_eq_panic1() +{ + let a = [1, 2]; + let b = [1, 2, 3]; + + zip_eq(&a, &b).count(); +} + +#[should_panic] +#[test] +fn zip_eq_panic2() +{ + let a: [i32; 0] = []; + let b = [1, 2, 3]; + + zip_eq(&a, &b).count(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itoa/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/itoa/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"4b12156f19f1d3a10516ba0177197325f072340e40de4b6a376732fcef3105b2","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"48573443063fa4e0786c3b46f42b6efd1f171c6b73408a64afc1b34de89f31fe","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"22f02b06399d4c6849dac5a1b517d3e5736dd33edc3955101ee0be6afc8376eb","src/udiv128.rs":"d28c1872c37ee2185931babcb20a221b8706a5aa8abc4963419763888023ff17","tests/test.rs":"aa1e910573a1d847d39773b4a2e4c597a8d3810070332673df0f6864cab24807"},"package":"49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"23987c15e4e7a411a165da7ee28476ab875eda5ae6d3aaae5536ba019cdb21e7",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"3bff86b0f8f86d09c2787c7d62facf70525b175f1a1ac2d352f0b9bb905cd7e6","Cargo.toml":"4b12156f19f1d3a10516ba0177197325f072340e40de4b6a376732fcef3105b2","Cargo.toml.orig":"a37b4f8dfbd47e418e132fca3d3d74599023fe32fa4d421b2055c9f9af0a3421","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"48573443063fa4e0786c3b46f42b6efd1f171c6b73408a64afc1b34de89f31fe","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"22f02b06399d4c6849dac5a1b517d3e5736dd33edc3955101ee0be6afc8376eb","src/udiv128.rs":"d28c1872c37ee2185931babcb20a221b8706a5aa8abc4963419763888023ff17","tests/test.rs":"aa1e910573a1d847d39773b4a2e4c597a8d3810070332673df0f6864cab24807"},"package":"49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itoa/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/itoa/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itoa/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8f392032fadf15b5e6b9b7b6add21875575d67af" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itoa/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itoa/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itoa/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itoa/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itoa/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,108 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.36.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo build + - run: cargo test + - run: cargo test --release + - run: cargo build --no-default-features + - run: cargo test --tests --no-default-features + - run: cargo test --tests --no-default-features --release + - run: cargo build --tests --features no-panic --release + if: matrix.rust == 'nightly' + - run: cargo bench --no-run + if: matrix.rust == 'nightly' + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test --all-targets # exclude doctests https://github.com/rust-lang/miri/issues/3404 + env: + MIRIFLAGS: -Zmiri-strict-provenance + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests --benches -- -Dclippy::all -Dclippy::pedantic + + fuzz: + name: Fuzz + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz check + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itoa/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/itoa/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/itoa/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itoa/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "itoa" +version = "1.0.11" +authors = ["David Tolnay "] +categories = ["value-formatting", "no-std", "no-std::no-alloc"] +description = "Fast integer primitive to string conversion" +documentation = "https://docs.rs/itoa" +edition = "2018" +exclude = ["performance.png", "chart/**"] +keywords = ["integer"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/itoa" +rust-version = "1.36" + +[dependencies] +no-panic = { version = "0.1", optional = true } + +[lib] +doc-scrape-examples = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"467e63a9440b50b390ef75457d70933c7bc57d1c2b71004467a4632de92e53b9",".github/actions/compile-make/action.yml":"1650fff1ddb637401788b44e83b2a4878ecd932274ce1b728ca9d3000ba3d32e",".github/dependabot.yml":"d04c9b0253b2bbae886b59a11399ea260397b460cd9f5712d692d1c85f8ec090",".github/workflows/main.yml":"b0a2a1e908cad2afc050a60c9e678ceedaa5496abfa7ccbe2443225b7cefef6e",".github/workflows/publish.yml":"825add0fd18d256191ba3fd242c24ec5c878a435b4c07836e18addfc8b13b602","Cargo.toml":"9eb074df6c05dd3b88b3bd5b68312da8552b116e148d9270ce474840408cf93f","Cargo.toml.orig":"eca1442173a4a853e804a1712b9d82e9c822cd6450bcde1271be551310e7a379","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"de412b60535de63bd312ab0df197f72b89d6aaeab166ed090f58a26dcda72bcf","src/error.rs":"f947d858ba95a9a08d16325d163b61fdf0ce40ec95b7fb08cc47c9876de9c8dc","src/lib.rs":"9b82f32a87deae5bd5a0ed36cdab3a195f9419c6befa9f77a682f262b9158722","src/unix.rs":"92c2afb1307e50339817a9d5dd70a2457ab15b87699297b889b4d8652a3a1778","src/wasm.rs":"74db7bd1441b7b4d1b53cd83e23097a2b976faf4d18d3f42f583048d27611d4d","src/windows.rs":"a636019813f2ca2236706e6fe4c88166dddf8aa050555941167ff8e55c848cf1","tests/client-of-myself.rs":"ca09bf398f69df4bac1730999e954dbbc3faf3c6512678c136e0938e7e9cd0ab","tests/client.rs":"5d9b3606356c0fed0c9f5bf372f0fa09f922f93ffe910a1a9a474898d5ec9fa2","tests/helper.rs":"7b8d9eb8484ccf1e656ed235a23f62c2756045e3a6604121aee5493d8a5b1ede","tests/make-as-a-client.rs":"8be1f3fef1e9e65c7904dbaa04364bf0f44e9deab84a2a247a5a94b5cf0df9bc","tests/server.rs":"da15bf12e1df1883f660892b996c9e0d92485aace3f7b50ee70c4a8e6deae8da"},"package":"48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f494d826e436a7027f40affa504cb8777923d108" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/actions/compile-make/action.yml clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/actions/compile-make/action.yml --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/actions/compile-make/action.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/actions/compile-make/action.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +name: Compile make +description: compile-make +inputs: + version: + description: make version + required: true + workaround: + description: enable workaround for _alloc bug + required: false + default: "false" + +runs: + using: composite + steps: + - name: Cache make compiled + if: ${{ !startsWith(runner.os, 'windows') }} + id: cache-maka + uses: actions/cache@v4 + with: + path: /usr/local/bin/make-${{ inputs.version }} + key: v1-${{ runner.os }}-make-${{ inputs.version }} + + - name: Make GNU Make from source + if: ${{ !startsWith(runner.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }} + env: + VERSION: ${{ inputs.version }} + WORKAROUND: ${{ inputs.workaround }} + shell: bash + run: | + curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz + pushd "make-${VERSION}" + ./configure + [[ "$WORKAROUND" = "true" ]] && sed -i 's/#if !defined __alloca \&\& !defined __GNU_LIBRARY__/#if !defined __alloca \&\& defined __GNU_LIBRARY__/g; s/#ifndef __GNU_LIBRARY__/#ifdef __GNU_LIBRARY__/g' "./glob/glob.c" + make -j 4 + popd + cp -p "make-${VERSION}/make" "/usr/local/bin/make-${VERSION}" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily + time: "08:00" + open-pull-requests-limit: 10 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/main.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +name: CI +on: [push, pull_request] + +env: + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + rust: [stable, beta, nightly] + os: [ubuntu-latest, macos-14, windows-latest] + steps: + - uses: actions/checkout@master + - name: Install Rust (rustup) + run: | + rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal + rustup default ${{ matrix.rust }} + shell: bash + + - uses: Swatinem/rust-cache@v2 + + - run: cargo test --locked + + - name: Compile make 4.4.1 + uses: ./.github/actions/compile-make + with: + version: 4.4.1 + + - name: Test against GNU Make 4.4.1 + if: ${{ !startsWith(matrix.os, 'windows') }} + shell: bash + run: cargo test --locked + env: + MAKE: /usr/local/bin/make-4.4.1 + + - name: Ensure wasm32-unknown-unknown be buildable + if: matrix.os == 'ubuntu-latest' + shell: bash + run: | + rustup target add wasm32-unknown-unknown + cargo build --locked --target wasm32-unknown-unknown + + test_musl: + name: Test (stable, alpine-latest) + container: rust:alpine + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + + - name: Install make dependencies + run: apk add musl-dev bash curl make tar + + - uses: Swatinem/rust-cache@v2 + + - name: Compile make 4.4.1 + uses: ./.github/actions/compile-make + with: + version: 4.4.1 + + - name: Test against GNU Make 4.4.1 + shell: bash + run: cargo test --locked + env: + MAKE: /usr/local/bin/make-4.4.1 + + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: rustup update stable && rustup default stable && rustup component add rustfmt + - run: cargo fmt -- --check + + publish_docs: + name: Publish Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: rustup update stable && rustup default stable + - name: Build documentation + run: cargo doc --no-deps --all-features + - name: Publish documentation + run: | + cd target/doc + git init + git add . + git -c user.name='ci' -c user.email='ci' commit -m init + git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages + if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' + + msrv: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-14, windows-latest] + steps: + - uses: actions/checkout@master + - name: Install Rust (rustup) + run: rustup toolchain install nightly --no-self-update --profile minimal + shell: bash + + - uses: taiki-e/install-action@cargo-hack + - uses: Swatinem/rust-cache@v2 + + - run: cargo hack check --lib --rust-version --ignore-private --locked diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/workflows/publish.yml clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/publish.yml --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/.github/workflows/publish.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/.github/workflows/publish.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +on: + push: + tags: + - "*" + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Publish to crates.io + run: | + cargo publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,58 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63" +name = "jobserver" +version = "0.1.32" +authors = ["Alex Crichton "] +description = """ +An implementation of the GNU Make jobserver for Rust. +""" +homepage = "https://github.com/rust-lang/jobserver-rs" +documentation = "https://docs.rs/jobserver" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/jobserver-rs" + +[[test]] +name = "client" +path = "tests/client.rs" +harness = false + +[[test]] +name = "server" +path = "tests/server.rs" + +[[test]] +name = "client-of-myself" +path = "tests/client-of-myself.rs" +harness = false + +[[test]] +name = "make-as-a-client" +path = "tests/make-as-a-client.rs" +harness = false + +[[test]] +name = "helper" +path = "tests/helper.rs" + +[dev-dependencies.tempfile] +version = "3.10.1" + +[target."cfg(unix)".dependencies.libc] +version = "0.2.87" + +[target."cfg(unix)".dev-dependencies.nix] +version = "0.28.0" +features = ["fs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +[package] +name = "jobserver" +version = "0.1.32" +authors = ["Alex Crichton "] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/jobserver-rs" +homepage = "https://github.com/rust-lang/jobserver-rs" +documentation = "https://docs.rs/jobserver" +description = """ +An implementation of the GNU Make jobserver for Rust. +""" +edition = "2021" +rust-version = "1.63" + +[target.'cfg(unix)'.dependencies] +libc = "0.2.87" + +[target.'cfg(unix)'.dev-dependencies] +nix = { version = "0.28.0", features = ["fs"] } + +[dev-dependencies] +tempfile = "3.10.1" + +[[test]] +name = "client" +harness = false +path = "tests/client.rs" + +[[test]] +name = "server" +path = "tests/server.rs" + +[[test]] +name = "client-of-myself" +path = "tests/client-of-myself.rs" +harness = false + +[[test]] +name = "make-as-a-client" +path = "tests/make-as-a-client.rs" +harness = false + +[[test]] +name = "helper" +path = "tests/helper.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/README.md clamav-1.4.6+dfsg/.cargo/vendor/jobserver/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +# jobserver-rs + +An implementation of the GNU Make jobserver for Rust. + +[![crates.io](https://img.shields.io/crates/v/jobserver.svg?maxAge=2592000)](https://crates.io/crates/jobserver) + +[Documentation](https://docs.rs/jobserver) + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +jobserver = "0.1" +``` + +# License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + https://opensource.org/license/mit) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in jobserver-rs by you, as defined in the Apache-2.0 license, +shall be dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +#[cfg(unix)] +type RawFd = std::os::unix::io::RawFd; +#[cfg(not(unix))] +type RawFd = std::convert::Infallible; + +/// Error type for [`Client::from_env_ext`] function. +/// +/// [`Client::from_env_ext`]: crate::Client::from_env_ext +#[derive(Debug)] +pub struct FromEnvError { + pub(crate) inner: FromEnvErrorInner, +} + +/// Kind of an error returned from [`Client::from_env_ext`] function. +/// +/// [`Client::from_env_ext`]: crate::Client::from_env_ext +#[derive(Debug)] +#[non_exhaustive] +pub enum FromEnvErrorKind { + /// There is no environment variable that describes jobserver to inherit. + NoEnvVar, + /// There is no jobserver in the environment variable. + /// Variables associated with Make can be used for passing data other than jobserver info. + NoJobserver, + /// Cannot parse jobserver environment variable value, incorrect format. + CannotParse, + /// Cannot open path or name from the jobserver environment variable value. + CannotOpenPath, + /// Cannot open file descriptor from the jobserver environment variable value. + CannotOpenFd, + /// The jobserver style is a simple pipe, but at least one of the file descriptors + /// is negative, which means it is disabled for this process + /// ([GNU `make` manual: POSIX Jobserver Interaction](https://www.gnu.org/software/make/manual/make.html#POSIX-Jobserver)). + NegativeFd, + /// File descriptor from the jobserver environment variable value is not a pipe. + NotAPipe, + /// Jobserver inheritance is not supported on this platform. + Unsupported, +} + +impl FromEnvError { + /// Get the error kind. + pub fn kind(&self) -> FromEnvErrorKind { + match self.inner { + FromEnvErrorInner::NoEnvVar => FromEnvErrorKind::NoEnvVar, + FromEnvErrorInner::NoJobserver => FromEnvErrorKind::NoJobserver, + FromEnvErrorInner::CannotParse(_) => FromEnvErrorKind::CannotParse, + FromEnvErrorInner::CannotOpenPath(..) => FromEnvErrorKind::CannotOpenPath, + FromEnvErrorInner::CannotOpenFd(..) => FromEnvErrorKind::CannotOpenFd, + FromEnvErrorInner::NegativeFd(..) => FromEnvErrorKind::NegativeFd, + FromEnvErrorInner::NotAPipe(..) => FromEnvErrorKind::NotAPipe, + FromEnvErrorInner::Unsupported => FromEnvErrorKind::Unsupported, + } + } +} + +impl std::fmt::Display for FromEnvError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.inner { + FromEnvErrorInner::NoEnvVar => write!(f, "there is no environment variable that describes jobserver to inherit"), + FromEnvErrorInner::NoJobserver => write!(f, "there is no `--jobserver-fds=` or `--jobserver-auth=` in the environment variable"), + FromEnvErrorInner::CannotParse(s) => write!(f, "cannot parse jobserver environment variable value: {s}"), + FromEnvErrorInner::CannotOpenPath(s, err) => write!(f, "cannot open path or name {s} from the jobserver environment variable value: {err}"), + FromEnvErrorInner::CannotOpenFd(fd, err) => write!(f, "cannot open file descriptor {fd} from the jobserver environment variable value: {err}"), + FromEnvErrorInner::NegativeFd(fd) => write!(f, "file descriptor {fd} from the jobserver environment variable value is negative"), + FromEnvErrorInner::NotAPipe(fd, None) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe"), + FromEnvErrorInner::NotAPipe(fd, Some(err)) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe: {err}"), + FromEnvErrorInner::Unsupported => write!(f, "jobserver inheritance is not supported on this platform"), + } + } +} +impl std::error::Error for FromEnvError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match &self.inner { + FromEnvErrorInner::CannotOpenPath(_, err) => Some(err), + FromEnvErrorInner::NotAPipe(_, Some(err)) | FromEnvErrorInner::CannotOpenFd(_, err) => { + Some(err) + } + _ => None, + } + } +} + +#[allow(dead_code)] +#[derive(Debug)] +pub(crate) enum FromEnvErrorInner { + NoEnvVar, + NoJobserver, + CannotParse(String), + CannotOpenPath(String, std::io::Error), + CannotOpenFd(RawFd, std::io::Error), + NegativeFd(RawFd), + NotAPipe(RawFd, Option), + Unsupported, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,704 @@ +//! An implementation of the GNU make jobserver. +//! +//! This crate is an implementation, in Rust, of the GNU `make` jobserver for +//! CLI tools that are interoperating with make or otherwise require some form +//! of parallelism limiting across process boundaries. This was originally +//! written for usage in Cargo to both (a) work when `cargo` is invoked from +//! `make` (using `make`'s jobserver) and (b) work when `cargo` invokes build +//! scripts, exporting a jobserver implementation for `make` processes to +//! transitively use. +//! +//! The jobserver implementation can be found in [detail online][docs] but +//! basically boils down to a cross-process semaphore. On Unix this is +//! implemented with the `pipe` syscall and read/write ends of a pipe and on +//! Windows this is implemented literally with IPC semaphores. Starting from +//! GNU `make` version 4.4, named pipe becomes the default way in communication +//! on Unix. This crate also supports that feature in the sense of inheriting +//! and forwarding the correct environment. +//! +//! The jobserver protocol in `make` also dictates when tokens are acquired to +//! run child work, and clients using this crate should take care to implement +//! such details to ensure correct interoperation with `make` itself. +//! +//! ## Examples +//! +//! Connect to a jobserver that was set up by `make` or a different process: +//! +//! ```no_run +//! use jobserver::Client; +//! +//! // See API documentation for why this is `unsafe` +//! let client = match unsafe { Client::from_env() } { +//! Some(client) => client, +//! None => panic!("client not configured"), +//! }; +//! ``` +//! +//! Acquire and release token from a jobserver: +//! +//! ```no_run +//! use jobserver::Client; +//! +//! let client = unsafe { Client::from_env().unwrap() }; +//! let token = client.acquire().unwrap(); // blocks until it is available +//! drop(token); // releases the token when the work is done +//! ``` +//! +//! Create a new jobserver and configure a child process to have access: +//! +//! ``` +//! use std::process::Command; +//! use jobserver::Client; +//! +//! let client = Client::new(4).expect("failed to create jobserver"); +//! let mut cmd = Command::new("make"); +//! client.configure(&mut cmd); +//! ``` +//! +//! ## Caveats +//! +//! This crate makes no attempt to release tokens back to a jobserver on +//! abnormal exit of a process. If a process which acquires a token is killed +//! with ctrl-c or some similar signal then tokens will not be released and the +//! jobserver may be in a corrupt state. +//! +//! Note that this is typically ok as ctrl-c means that an entire build process +//! is being torn down, but it's worth being aware of at least! +//! +//! ## Windows caveats +//! +//! There appear to be two implementations of `make` on Windows. On MSYS2 one +//! typically comes as `mingw32-make` and the other as `make` itself. I'm not +//! personally too familiar with what's going on here, but for jobserver-related +//! information the `mingw32-make` implementation uses Windows semaphores +//! whereas the `make` program does not. The `make` program appears to use file +//! descriptors and I'm not really sure how it works, so this crate is not +//! compatible with `make` on Windows. It is, however, compatible with +//! `mingw32-make`. +//! +//! [docs]: https://make.mad-scientist.net/papers/jobserver-implementation/ + +#![deny(missing_docs, missing_debug_implementations)] +#![doc(html_root_url = "https://docs.rs/jobserver/0.1")] + +use std::env; +use std::ffi::OsString; +use std::io; +use std::process::Command; +use std::sync::{Arc, Condvar, Mutex, MutexGuard}; + +mod error; +#[cfg(unix)] +#[path = "unix.rs"] +mod imp; +#[cfg(windows)] +#[path = "windows.rs"] +mod imp; +#[cfg(not(any(unix, windows)))] +#[path = "wasm.rs"] +mod imp; + +/// A client of a jobserver +/// +/// This structure is the main type exposed by this library, and is where +/// interaction to a jobserver is configured through. Clients are either created +/// from scratch in which case the internal semphore is initialied on the spot, +/// or a client is created from the environment to connect to a jobserver +/// already created. +/// +/// Some usage examples can be found in the crate documentation for using a +/// client. +/// +/// Note that a [`Client`] implements the [`Clone`] trait, and all instances of +/// a [`Client`] refer to the same jobserver instance. +#[derive(Clone, Debug)] +pub struct Client { + inner: Arc, +} + +/// An acquired token from a jobserver. +/// +/// This token will be released back to the jobserver when it is dropped and +/// otherwise represents the ability to spawn off another thread of work. +#[derive(Debug)] +pub struct Acquired { + client: Arc, + data: imp::Acquired, + disabled: bool, +} + +impl Acquired { + /// This drops the [`Acquired`] token without releasing the associated token. + /// + /// This is not generally useful, but can be helpful if you do not have the + /// ability to store an Acquired token but need to not yet release it. + /// + /// You'll typically want to follow this up with a call to + /// [`Client::release_raw`] or similar to actually release the token later on. + pub fn drop_without_releasing(mut self) { + self.disabled = true; + } +} + +#[derive(Default, Debug)] +struct HelperState { + lock: Mutex, + cvar: Condvar, +} + +#[derive(Default, Debug)] +struct HelperInner { + requests: usize, + producer_done: bool, + consumer_done: bool, +} + +use error::FromEnvErrorInner; +pub use error::{FromEnvError, FromEnvErrorKind}; + +/// Return type for [`Client::from_env_ext`] function. +#[derive(Debug)] +pub struct FromEnv { + /// Result of trying to get jobserver client from env. + pub client: Result, + /// Name and value of the environment variable. + /// `None` if no relevant environment variable is found. + pub var: Option<(&'static str, OsString)>, +} + +impl FromEnv { + fn new_ok(client: Client, var_name: &'static str, var_value: OsString) -> FromEnv { + FromEnv { + client: Ok(client), + var: Some((var_name, var_value)), + } + } + fn new_err(kind: FromEnvErrorInner, var_name: &'static str, var_value: OsString) -> FromEnv { + FromEnv { + client: Err(FromEnvError { inner: kind }), + var: Some((var_name, var_value)), + } + } +} + +impl Client { + /// Creates a new jobserver initialized with the given parallelism limit. + /// + /// A client to the jobserver created will be returned. This client will + /// allow at most `limit` tokens to be acquired from it in parallel. More + /// calls to [`Client::acquire`] will cause the calling thread to block. + /// + /// Note that the created [`Client`] is not automatically inherited into + /// spawned child processes from this program. Manual usage of the + /// [`Client::configure`] function is required for a child process to have + /// access to a job server. + /// + /// # Examples + /// + /// ``` + /// use jobserver::Client; + /// + /// let client = Client::new(4).expect("failed to create jobserver"); + /// ``` + /// + /// # Errors + /// + /// Returns an error if any I/O error happens when attempting to create the + /// jobserver client. + pub fn new(limit: usize) -> io::Result { + Ok(Client { + inner: Arc::new(imp::Client::new(limit)?), + }) + } + + /// Attempts to connect to the jobserver specified in this process's + /// environment. + /// + /// When the a `make` executable calls a child process it will configure the + /// environment of the child to ensure that it has handles to the jobserver + /// it's passing down. This function will attempt to look for these details + /// and connect to the jobserver. + /// + /// Note that the created [`Client`] is not automatically inherited into + /// spawned child processes from this program. Manual usage of the + /// [`Client::configure`] function is required for a child process to have + /// access to a job server. + /// + /// # Return value + /// + /// [`FromEnv`] contains result and relevant environment variable. + /// If a jobserver was found in the environment and it looks correct then + /// result with the connected client will be returned. In other cases + /// result will contain `Err(FromEnvErr)`. + /// + /// Additionally on Unix this function will configure the file descriptors + /// with `CLOEXEC` so they're not automatically inherited by spawned + /// children. + /// + /// On unix if `check_pipe` enabled this function will check if provided + /// files are actually pipes. + /// + /// # Safety + /// + /// This function is `unsafe` to call on Unix specifically as it + /// transitively requires usage of the `from_raw_fd` function, which is + /// itself unsafe in some circumstances. + /// + /// It's recommended to call this function very early in the lifetime of a + /// program before any other file descriptors are opened. That way you can + /// make sure to take ownership properly of the file descriptors passed + /// down, if any. + /// + /// It is ok to call this function any number of times. + pub unsafe fn from_env_ext(check_pipe: bool) -> FromEnv { + let (env, var_os) = match ["CARGO_MAKEFLAGS", "MAKEFLAGS", "MFLAGS"] + .iter() + .map(|&env| env::var_os(env).map(|var| (env, var))) + .find_map(|p| p) + { + Some((env, var_os)) => (env, var_os), + None => return FromEnv::new_err(FromEnvErrorInner::NoEnvVar, "", Default::default()), + }; + + let var = match var_os.to_str() { + Some(var) => var, + None => { + let err = FromEnvErrorInner::CannotParse("not valid UTF-8".to_string()); + return FromEnv::new_err(err, env, var_os); + } + }; + + let s = match find_jobserver_auth(var) { + Some(s) => s, + None => return FromEnv::new_err(FromEnvErrorInner::NoJobserver, env, var_os), + }; + match imp::Client::open(s, check_pipe) { + Ok(c) => FromEnv::new_ok(Client { inner: Arc::new(c) }, env, var_os), + Err(err) => FromEnv::new_err(err, env, var_os), + } + } + + /// Attempts to connect to the jobserver specified in this process's + /// environment. + /// + /// Wraps [`Client::from_env_ext`] and discards error details. + /// + /// # Safety + /// + /// This function is `unsafe` to call on Unix specifically as it + /// transitively requires usage of the `from_raw_fd` function, which is + /// itself unsafe in some circumstances. + /// + /// It's recommended to call this function very early in the lifetime of a + /// program before any other file descriptors are opened. That way you can + /// make sure to take ownership properly of the file descriptors passed + /// down, if any. + /// + /// It is ok to call this function any number of times. + pub unsafe fn from_env() -> Option { + Self::from_env_ext(false).client.ok() + } + + /// Acquires a token from this jobserver client. + /// + /// This function will block the calling thread until a new token can be + /// acquired from the jobserver. + /// + /// # Return value + /// + /// On successful acquisition of a token an instance of [`Acquired`] is + /// returned. This structure, when dropped, will release the token back to + /// the jobserver. It's recommended to avoid leaking this value. + /// + /// # Errors + /// + /// If an I/O error happens while acquiring a token then this function will + /// return immediately with the error. If an error is returned then a token + /// was not acquired. + pub fn acquire(&self) -> io::Result { + let data = self.inner.acquire()?; + Ok(Acquired { + client: self.inner.clone(), + data, + disabled: false, + }) + } + + /// Acquires a token from this jobserver client in a non-blocking way. + /// + /// # Return value + /// + /// On successful acquisition of a token an instance of [`Acquired`] is + /// returned. This structure, when dropped, will release the token back to + /// the jobserver. It's recommended to avoid leaking this value. + /// + /// # Errors + /// + /// If an I/O error happens while acquiring a token then this function will + /// return immediately with the error. If an error is returned then a token + /// was not acquired. + /// + /// If non-blocking acquire is not supported, the return error will have its `kind()` + /// set to [`io::ErrorKind::Unsupported`]. + pub fn try_acquire(&self) -> io::Result> { + let ret = self.inner.try_acquire()?; + + Ok(ret.map(|data| Acquired { + client: self.inner.clone(), + data, + disabled: false, + })) + } + + /// Returns amount of tokens in the read-side pipe. + /// + /// # Return value + /// + /// Number of bytes available to be read from the jobserver pipe + /// + /// # Errors + /// + /// Underlying errors from the ioctl will be passed up. + pub fn available(&self) -> io::Result { + self.inner.available() + } + + /// Configures a child process to have access to this client's jobserver as + /// well. + /// + /// This function is required to be called to ensure that a jobserver is + /// properly inherited to a child process. If this function is *not* called + /// then this [`Client`] will not be accessible in the child process. In + /// other words, if not called, then [`Client::from_env`] will return `None` + /// in the child process (or the equivalent of [`Client::from_env`] that + /// `make` uses). + /// + /// ## Platform-specific behavior + /// + /// On Unix and Windows this will clobber the `CARGO_MAKEFLAGS` environment + /// variables for the child process, and on Unix this will also allow the + /// two file descriptors for this client to be inherited to the child. + /// + /// On platforms other than Unix and Windows this panics. + pub fn configure(&self, cmd: &mut Command) { + cmd.env("CARGO_MAKEFLAGS", &self.mflags_env()); + self.inner.configure(cmd); + } + + /// Configures a child process to have access to this client's jobserver as + /// well. + /// + /// This function is required to be called to ensure that a jobserver is + /// properly inherited to a child process. If this function is *not* called + /// then this [`Client`] will not be accessible in the child process. In + /// other words, if not called, then [`Client::from_env`] will return `None` + /// in the child process (or the equivalent of [`Client::from_env`] that + /// `make` uses). + /// + /// ## Platform-specific behavior + /// + /// On Unix and Windows this will clobber the `CARGO_MAKEFLAGS`, + /// `MAKEFLAGS` and `MFLAGS` environment variables for the child process, + /// and on Unix this will also allow the two file descriptors for + /// this client to be inherited to the child. + /// + /// On platforms other than Unix and Windows this panics. + pub fn configure_make(&self, cmd: &mut Command) { + let value = self.mflags_env(); + cmd.env("CARGO_MAKEFLAGS", &value); + cmd.env("MAKEFLAGS", &value); + cmd.env("MFLAGS", &value); + self.inner.configure(cmd); + } + + fn mflags_env(&self) -> String { + let arg = self.inner.string_arg(); + // Older implementations of make use `--jobserver-fds` and newer + // implementations use `--jobserver-auth`, pass both to try to catch + // both implementations. + format!("-j --jobserver-fds={0} --jobserver-auth={0}", arg) + } + + /// Converts this [`Client`] into a helper thread to deal with a blocking + /// [`Client::acquire`] function a little more easily. + /// + /// The fact that the [`Client::acquire`] isn't always the easiest to work + /// with. Typically you're using a jobserver to manage running other events + /// in parallel! This means that you need to either (a) wait for an existing + /// job to finish or (b) wait for a new token to become available. + /// + /// Unfortunately the blocking in [`Client::acquire`] happens at the + /// implementation layer of jobservers. On Unix this requires a blocking + /// call to `read` and on Windows this requires one of the `WaitFor*` + /// functions. Both of these situations aren't the easiest to deal with: + /// + /// * On Unix there's basically only one way to wake up a `read` early, and + /// that's through a signal. This is what the `make` implementation + /// itself uses, relying on `SIGCHLD` to wake up a blocking acquisition + /// of a new job token. Unfortunately nonblocking I/O is not an option + /// here, so it means that "waiting for one of two events" means that + /// the latter event must generate a signal! This is not always the case + /// on unix for all jobservers. + /// + /// * On Windows you'd have to basically use the `WaitForMultipleObjects` + /// which means that you've got to canonicalize all your event sources + /// into a `HANDLE` which also isn't the easiest thing to do + /// unfortunately. + /// + /// This function essentially attempts to ease these limitations by + /// converting this [`Client`] into a helper thread spawned into this + /// process. The application can then request that the helper thread + /// acquires tokens and the provided closure will be invoked for each token + /// acquired. + /// + /// The intention is that this function can be used to translate the event + /// of a token acquisition into an arbitrary user-defined event. + /// + /// # Arguments + /// + /// This function will consume the [`Client`] provided to be transferred to + /// the helper thread that is spawned. Additionally a closure `f` is + /// provided to be invoked whenever a token is acquired. + /// + /// This closure is only invoked after calls to + /// [`HelperThread::request_token`] have been made and a token itself has + /// been acquired. If an error happens while acquiring the token then + /// an error will be yielded to the closure as well. + /// + /// # Return Value + /// + /// This function will return an instance of the [`HelperThread`] structure + /// which is used to manage the helper thread associated with this client. + /// Through the [`HelperThread`] you'll request that tokens are acquired. + /// When acquired, the closure provided here is invoked. + /// + /// When the [`HelperThread`] structure is returned it will be gracefully + /// torn down, and the calling thread will be blocked until the thread is + /// torn down (which should be prompt). + /// + /// # Errors + /// + /// This function may fail due to creation of the helper thread or + /// auxiliary I/O objects to manage the helper thread. In any of these + /// situations the error is propagated upwards. + /// + /// # Platform-specific behavior + /// + /// On Windows this function behaves pretty normally as expected, but on + /// Unix the implementation is... a little heinous. As mentioned above + /// we're forced into blocking I/O for token acquisition, namely a blocking + /// call to `read`. We must be able to unblock this, however, to tear down + /// the helper thread gracefully! + /// + /// Essentially what happens is that we'll send a signal to the helper + /// thread spawned and rely on `EINTR` being returned to wake up the helper + /// thread. This involves installing a global `SIGUSR1` handler that does + /// nothing along with sending signals to that thread. This may cause + /// odd behavior in some applications, so it's recommended to review and + /// test thoroughly before using this. + pub fn into_helper_thread(self, f: F) -> io::Result + where + F: FnMut(io::Result) + Send + 'static, + { + let state = Arc::new(HelperState::default()); + Ok(HelperThread { + inner: Some(imp::spawn_helper(self, state.clone(), Box::new(f))?), + state, + }) + } + + /// Blocks the current thread until a token is acquired. + /// + /// This is the same as [`Client::acquire`], except that it doesn't return + /// an RAII helper. If successful the process will need to guarantee that + /// [`Client::release_raw`] is called in the future. + pub fn acquire_raw(&self) -> io::Result<()> { + self.inner.acquire()?; + Ok(()) + } + + /// Releases a jobserver token back to the original jobserver. + /// + /// This is intended to be paired with [`Client::acquire_raw`] if it was + /// called, but in some situations it could also be called to relinquish a + /// process's implicit token temporarily which is then re-acquired later. + pub fn release_raw(&self) -> io::Result<()> { + self.inner.release(None)?; + Ok(()) + } +} + +impl Drop for Acquired { + fn drop(&mut self) { + if !self.disabled { + drop(self.client.release(Some(&self.data))); + } + } +} + +/// Structure returned from [`Client::into_helper_thread`] to manage the lifetime +/// of the helper thread returned, see those associated docs for more info. +#[derive(Debug)] +pub struct HelperThread { + inner: Option, + state: Arc, +} + +impl HelperThread { + /// Request that the helper thread acquires a token, eventually calling the + /// original closure with a token when it's available. + /// + /// For more information, see the docs on [`Client::into_helper_thread`]. + pub fn request_token(&self) { + // Indicate that there's one more request for a token and then wake up + // the helper thread if it's sleeping. + self.state.lock().requests += 1; + self.state.cvar.notify_one(); + } +} + +impl Drop for HelperThread { + fn drop(&mut self) { + // Flag that the producer half is done so the helper thread should exit + // quickly if it's waiting. Wake it up if it's actually waiting + self.state.lock().producer_done = true; + self.state.cvar.notify_one(); + + // ... and afterwards perform any thread cleanup logic + self.inner.take().unwrap().join(); + } +} + +impl HelperState { + fn lock(&self) -> MutexGuard<'_, HelperInner> { + self.lock.lock().unwrap_or_else(|e| e.into_inner()) + } + + /// Executes `f` for each request for a token, where `f` is expected to + /// block and then provide the original closure with a token once it's + /// acquired. + /// + /// This is an infinite loop until the helper thread is dropped, at which + /// point everything should get interrupted. + fn for_each_request(&self, mut f: impl FnMut(&HelperState)) { + let mut lock = self.lock(); + + // We only execute while we could receive requests, but as soon as + // that's `false` we're out of here. + while !lock.producer_done { + // If no one's requested a token then we wait for someone to + // request a token. + if lock.requests == 0 { + lock = self.cvar.wait(lock).unwrap_or_else(|e| e.into_inner()); + continue; + } + + // Consume the request for a token, and then actually acquire a + // token after unlocking our lock (not that acquisition happens in + // `f`). This ensures that we don't actually hold the lock if we + // wait for a long time for a token. + lock.requests -= 1; + drop(lock); + f(self); + lock = self.lock(); + } + lock.consumer_done = true; + self.cvar.notify_one(); + } +} + +/// Finds and returns the value of `--jobserver-auth=` in the given +/// environment variable. +/// +/// Precedence rules: +/// +/// * The last instance wins [^1]. +/// * `--jobserver-fds=` as a fallback when no `--jobserver-auth=` is present [^2]. +/// +/// [^1]: See ["GNU `make` manual: Sharing Job Slots with GNU `make`"](https://www.gnu.org/software/make/manual/make.html#Job-Slots) +/// _"Be aware that the `MAKEFLAGS` variable may contain multiple instances of +/// the `--jobserver-auth=` option. Only the last instance is relevant."_ +/// +/// [^2]: Refer to [the release announcement](https://git.savannah.gnu.org/cgit/make.git/tree/NEWS?h=4.2#n31) +/// of GNU Make 4.2, which states that `--jobserver-fds` was initially an +/// internal-only flag and was later renamed to `--jobserver-auth`. +fn find_jobserver_auth(var: &str) -> Option<&str> { + ["--jobserver-auth=", "--jobserver-fds="] + .iter() + .find_map(|&arg| var.rsplit_once(arg).map(|(_, s)| s)) + .and_then(|s| s.split(' ').next()) +} + +#[cfg(test)] +mod test { + use super::*; + + pub(super) fn run_named_fifo_try_acquire_tests(client: &Client) { + assert!(client.try_acquire().unwrap().is_none()); + client.release_raw().unwrap(); + + let acquired = client.try_acquire().unwrap().unwrap(); + assert!(client.try_acquire().unwrap().is_none()); + + drop(acquired); + client.try_acquire().unwrap().unwrap(); + } + + #[cfg(windows)] + #[test] + fn test_try_acquire() { + let client = Client::new(0).unwrap(); + + run_named_fifo_try_acquire_tests(&client); + } + + #[test] + fn no_helper_deadlock() { + let x = crate::Client::new(32).unwrap(); + let _y = x.clone(); + std::mem::drop(x.into_helper_thread(|_| {}).unwrap()); + } + + #[test] + fn test_find_jobserver_auth() { + let cases = [ + ("", None), + ("-j2", None), + ("-j2 --jobserver-auth=3,4", Some("3,4")), + ("--jobserver-auth=3,4 -j2", Some("3,4")), + ("--jobserver-auth=3,4", Some("3,4")), + ("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")), + ("--jobserver-auth=", Some("")), + ("--jobserver-auth", None), + ("--jobserver-fds=3,4", Some("3,4")), + ("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")), + ("--jobserver-fds=", Some("")), + ("--jobserver-fds", None), + ( + "--jobserver-auth=auth-a --jobserver-auth=auth-b", + Some("auth-b"), + ), + ( + "--jobserver-auth=auth-b --jobserver-auth=auth-a", + Some("auth-a"), + ), + ("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")), + ("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")), + ( + "--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b", + Some("auth-b"), + ), + ( + "--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b", + Some("auth-a"), + ), + ]; + for (var, expected) in cases { + let actual = find_jobserver_auth(var); + assert_eq!( + actual, expected, + "expect {expected:?}, got {actual:?}, input `{var:?}`" + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/unix.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/unix.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/unix.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/unix.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,651 @@ +use libc::c_int; + +use crate::FromEnvErrorInner; +use std::fs::{File, OpenOptions}; +use std::io::{self, Read, Write}; +use std::mem; +use std::mem::MaybeUninit; +use std::os::unix::prelude::*; +use std::path::Path; +use std::process::Command; +use std::ptr; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Once, +}; +use std::thread::{self, Builder, JoinHandle}; +use std::time::Duration; + +#[derive(Debug)] +/// This preserves the `--jobserver-auth` type at creation time, +/// so auth type will be passed down to and inherit from sub-Make processes correctly. +/// +/// See for details. +enum ClientCreationArg { + Fds { read: c_int, write: c_int }, + Fifo(Box), +} + +#[derive(Debug)] +pub struct Client { + read: File, + write: File, + creation_arg: ClientCreationArg, + /// It is set to `None` if the pipe is shared with other processes, so it + /// cannot support non-blocking mode. + /// + /// If it is set to `Some`, then it can only go from + /// `Some(false)` -> `Some(true)` but not the other way around, + /// since that could cause a race condition. + is_non_blocking: Option, +} + +#[derive(Debug)] +pub struct Acquired { + byte: u8, +} + +impl Client { + pub fn new(mut limit: usize) -> io::Result { + let client = unsafe { Client::mk()? }; + + // I don't think the character written here matters, but I could be + // wrong! + const BUFFER: [u8; 128] = [b'|'; 128]; + + let mut write = &client.write; + + set_nonblocking(write.as_raw_fd(), true)?; + + while limit > 0 { + let n = limit.min(BUFFER.len()); + + write.write_all(&BUFFER[..n])?; + limit -= n; + } + + set_nonblocking(write.as_raw_fd(), false)?; + + Ok(client) + } + + unsafe fn mk() -> io::Result { + let mut pipes = [0; 2]; + + // Attempt atomically-create-with-cloexec if we can on Linux, + // detected by using the `syscall` function in `libc` to try to work + // with as many kernels/glibc implementations as possible. + #[cfg(target_os = "linux")] + { + static PIPE2_AVAILABLE: AtomicBool = AtomicBool::new(true); + if PIPE2_AVAILABLE.load(Ordering::SeqCst) { + match libc::syscall(libc::SYS_pipe2, pipes.as_mut_ptr(), libc::O_CLOEXEC) { + -1 => { + let err = io::Error::last_os_error(); + if err.raw_os_error() == Some(libc::ENOSYS) { + PIPE2_AVAILABLE.store(false, Ordering::SeqCst); + } else { + return Err(err); + } + } + _ => return Ok(Client::from_fds(pipes[0], pipes[1])), + } + } + } + + cvt(libc::pipe(pipes.as_mut_ptr()))?; + drop(set_cloexec(pipes[0], true)); + drop(set_cloexec(pipes[1], true)); + Ok(Client::from_fds(pipes[0], pipes[1])) + } + + pub(crate) unsafe fn open(s: &str, check_pipe: bool) -> Result { + if let Some(client) = Self::from_fifo(s)? { + return Ok(client); + } + if let Some(client) = Self::from_pipe(s, check_pipe)? { + return Ok(client); + } + Err(FromEnvErrorInner::CannotParse(format!( + "expected `fifo:PATH` or `R,W`, found `{s}`" + ))) + } + + /// `--jobserver-auth=fifo:PATH` + fn from_fifo(s: &str) -> Result, FromEnvErrorInner> { + let mut parts = s.splitn(2, ':'); + if parts.next().unwrap() != "fifo" { + return Ok(None); + } + let path_str = parts.next().ok_or_else(|| { + FromEnvErrorInner::CannotParse("expected a path after `fifo:`".to_string()) + })?; + let path = Path::new(path_str); + + let open_file = || { + // Opening with read write is necessary, since opening with + // read-only or write-only could block the thread until another + // thread opens it with write-only or read-only (or RDWR) + // correspondingly. + OpenOptions::new() + .read(true) + .write(true) + .open(path) + .map_err(|err| FromEnvErrorInner::CannotOpenPath(path_str.to_string(), err)) + }; + + Ok(Some(Client { + read: open_file()?, + write: open_file()?, + creation_arg: ClientCreationArg::Fifo(path.into()), + is_non_blocking: Some(AtomicBool::new(false)), + })) + } + + /// `--jobserver-auth=R,W` + unsafe fn from_pipe(s: &str, check_pipe: bool) -> Result, FromEnvErrorInner> { + let mut parts = s.splitn(2, ','); + let read = parts.next().unwrap(); + let write = match parts.next() { + Some(w) => w, + None => return Ok(None), + }; + let read = read + .parse() + .map_err(|e| FromEnvErrorInner::CannotParse(format!("cannot parse `read` fd: {e}")))?; + let write = write + .parse() + .map_err(|e| FromEnvErrorInner::CannotParse(format!("cannot parse `write` fd: {e}")))?; + + // If either or both of these file descriptors are negative, + // it means the jobserver is disabled for this process. + if read < 0 { + return Err(FromEnvErrorInner::NegativeFd(read)); + } + if write < 0 { + return Err(FromEnvErrorInner::NegativeFd(write)); + } + + let creation_arg = ClientCreationArg::Fds { read, write }; + + // Ok so we've got two integers that look like file descriptors, but + // for extra sanity checking let's see if they actually look like + // valid files and instances of a pipe if feature enabled before we + // return the client. + // + // If we're called from `make` *without* the leading + on our rule + // then we'll have `MAKEFLAGS` env vars but won't actually have + // access to the file descriptors. + // + // `NotAPipe` is a worse error, return it if it's reported for any of the two fds. + match (fd_check(read, check_pipe), fd_check(write, check_pipe)) { + (read_err @ Err(FromEnvErrorInner::NotAPipe(..)), _) => read_err?, + (_, write_err @ Err(FromEnvErrorInner::NotAPipe(..))) => write_err?, + (read_err, write_err) => { + read_err?; + write_err?; + + // Optimization: Try converting it to a fifo by using /dev/fd + // + // On linux, opening `/dev/fd/$fd` returns a fd with a new file description, + // so we can set `O_NONBLOCK` on it without affecting other processes. + // + // On macOS, opening `/dev/fd/$fd` seems to be the same as `File::try_clone`. + // + // I tested this on macOS 14 and Linux 6.5.13 + #[cfg(target_os = "linux")] + if let (Ok(read), Ok(write)) = ( + File::open(format!("/dev/fd/{}", read)), + OpenOptions::new() + .write(true) + .open(format!("/dev/fd/{}", write)), + ) { + return Ok(Some(Client { + read, + write, + creation_arg, + is_non_blocking: Some(AtomicBool::new(false)), + })); + } + } + } + + Ok(Some(Client { + read: clone_fd_and_set_cloexec(read)?, + write: clone_fd_and_set_cloexec(write)?, + creation_arg, + is_non_blocking: None, + })) + } + + unsafe fn from_fds(read: c_int, write: c_int) -> Client { + Client { + read: File::from_raw_fd(read), + write: File::from_raw_fd(write), + creation_arg: ClientCreationArg::Fds { read, write }, + is_non_blocking: None, + } + } + + pub fn acquire(&self) -> io::Result { + // Ignore interrupts and keep trying if that happens + loop { + if let Some(token) = self.acquire_allow_interrupts()? { + return Ok(token); + } + } + } + + /// Block waiting for a token, returning `None` if we're interrupted with + /// EINTR. + fn acquire_allow_interrupts(&self) -> io::Result> { + // We don't actually know if the file descriptor here is set in + // blocking or nonblocking mode. AFAIK all released versions of + // `make` use blocking fds for the jobserver, but the unreleased + // version of `make` doesn't. In the unreleased version jobserver + // fds are set to nonblocking and combined with `pselect` + // internally. + // + // Here we try to be compatible with both strategies. We optimistically + // try to read from the file descriptor which then may block, return + // a token or indicate that polling is needed. + // Blocking reads (if possible) allows the kernel to be more selective + // about which readers to wake up when a token is written to the pipe. + // + // We use `poll` here to block this thread waiting for read + // readiness, and then afterwards we perform the `read` itself. If + // the `read` returns that it would block then we start over and try + // again. + // + // Also note that we explicitly don't handle EINTR here. That's used + // to shut us down, so we otherwise punt all errors upwards. + unsafe { + let mut fd: libc::pollfd = mem::zeroed(); + let mut read = &self.read; + fd.fd = read.as_raw_fd(); + fd.events = libc::POLLIN; + loop { + let mut buf = [0]; + match read.read(&mut buf) { + Ok(1) => return Ok(Some(Acquired { byte: buf[0] })), + Ok(_) => { + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "early EOF on jobserver pipe", + )); + } + Err(e) => match e.kind() { + io::ErrorKind::WouldBlock => { /* fall through to polling */ } + io::ErrorKind::Interrupted => return Ok(None), + _ => return Err(e), + }, + } + + loop { + fd.revents = 0; + if libc::poll(&mut fd, 1, -1) == -1 { + let e = io::Error::last_os_error(); + return match e.kind() { + io::ErrorKind::Interrupted => Ok(None), + _ => Err(e), + }; + } + if fd.revents != 0 { + break; + } + } + } + } + } + + pub fn try_acquire(&self) -> io::Result> { + let mut buf = [0]; + let mut fifo = &self.read; + + if let Some(is_non_blocking) = self.is_non_blocking.as_ref() { + if !is_non_blocking.load(Ordering::Relaxed) { + set_nonblocking(fifo.as_raw_fd(), true)?; + is_non_blocking.store(true, Ordering::Relaxed); + } + } else { + return Err(io::ErrorKind::Unsupported.into()); + } + + loop { + match fifo.read(&mut buf) { + Ok(1) => break Ok(Some(Acquired { byte: buf[0] })), + Ok(_) => { + break Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "early EOF on jobserver pipe", + )) + } + + Err(e) if e.kind() == io::ErrorKind::WouldBlock => break Ok(None), + Err(e) if e.kind() == io::ErrorKind::Interrupted => continue, + + Err(err) => break Err(err), + } + } + } + + pub fn release(&self, data: Option<&Acquired>) -> io::Result<()> { + // Note that the fd may be nonblocking but we're going to go ahead + // and assume that the writes here are always nonblocking (we can + // always quickly release a token). If that turns out to not be the + // case we'll get an error anyway! + let byte = data.map(|d| d.byte).unwrap_or(b'+'); + match (&self.write).write(&[byte])? { + 1 => Ok(()), + _ => Err(io::Error::new( + io::ErrorKind::Other, + "failed to write token back to jobserver", + )), + } + } + + pub fn string_arg(&self) -> String { + match &self.creation_arg { + ClientCreationArg::Fifo(path) => format!("fifo:{}", path.display()), + ClientCreationArg::Fds { read, write } => format!("{},{}", read, write), + } + } + + pub fn available(&self) -> io::Result { + let mut len = MaybeUninit::::uninit(); + cvt(unsafe { libc::ioctl(self.read.as_raw_fd(), libc::FIONREAD, len.as_mut_ptr()) })?; + Ok(unsafe { len.assume_init() } as usize) + } + + pub fn configure(&self, cmd: &mut Command) { + if matches!(self.creation_arg, ClientCreationArg::Fifo { .. }) { + // We `File::open`ed it when inheriting from environment, + // so no need to set cloexec for fifo. + return; + } + // Here we basically just want to say that in the child process + // we'll configure the read/write file descriptors to *not* be + // cloexec, so they're inherited across the exec and specified as + // integers through `string_arg` above. + let read = self.read.as_raw_fd(); + let write = self.write.as_raw_fd(); + unsafe { + cmd.pre_exec(move || { + set_cloexec(read, false)?; + set_cloexec(write, false)?; + Ok(()) + }); + } + } +} + +#[derive(Debug)] +pub struct Helper { + thread: JoinHandle<()>, + state: Arc, +} + +pub(crate) fn spawn_helper( + client: crate::Client, + state: Arc, + mut f: Box) + Send>, +) -> io::Result { + static USR1_INIT: Once = Once::new(); + let mut err = None; + USR1_INIT.call_once(|| unsafe { + let mut new: libc::sigaction = mem::zeroed(); + #[cfg(target_os = "aix")] + { + new.sa_union.__su_sigaction = sigusr1_handler; + } + #[cfg(not(target_os = "aix"))] + { + new.sa_sigaction = sigusr1_handler as usize; + } + new.sa_flags = libc::SA_SIGINFO as _; + if libc::sigaction(libc::SIGUSR1, &new, ptr::null_mut()) != 0 { + err = Some(io::Error::last_os_error()); + } + }); + + if let Some(e) = err.take() { + return Err(e); + } + + let state2 = state.clone(); + let thread = Builder::new().spawn(move || { + state2.for_each_request(|helper| loop { + match client.inner.acquire_allow_interrupts() { + Ok(Some(data)) => { + break f(Ok(crate::Acquired { + client: client.inner.clone(), + data, + disabled: false, + })); + } + Err(e) => break f(Err(e)), + Ok(None) if helper.lock().producer_done => break, + Ok(None) => {} + } + }); + })?; + + Ok(Helper { thread, state }) +} + +impl Helper { + pub fn join(self) { + let dur = Duration::from_millis(10); + let mut state = self.state.lock(); + debug_assert!(state.producer_done); + + // We need to join our helper thread, and it could be blocked in one + // of two locations. First is the wait for a request, but the + // initial drop of `HelperState` will take care of that. Otherwise + // it may be blocked in `client.acquire()`. We actually have no way + // of interrupting that, so resort to `pthread_kill` as a fallback. + // This signal should interrupt any blocking `read` call with + // `io::ErrorKind::Interrupt` and cause the thread to cleanly exit. + // + // Note that we don't do this forever though since there's a chance + // of bugs, so only do this opportunistically to make a best effort + // at clearing ourselves up. + for _ in 0..100 { + if state.consumer_done { + break; + } + unsafe { + // Ignore the return value here of `pthread_kill`, + // apparently on OSX if you kill a dead thread it will + // return an error, but on other platforms it may not. In + // that sense we don't actually know if this will succeed or + // not! + libc::pthread_kill(self.thread.as_pthread_t() as _, libc::SIGUSR1); + } + state = self + .state + .cvar + .wait_timeout(state, dur) + .unwrap_or_else(|e| e.into_inner()) + .0; + thread::yield_now(); // we really want the other thread to run + } + + // If we managed to actually see the consumer get done, then we can + // definitely wait for the thread. Otherwise it's... off in the ether + // I guess? + if state.consumer_done { + drop(self.thread.join()); + } + } +} + +unsafe fn fcntl_check(fd: c_int) -> Result<(), FromEnvErrorInner> { + match libc::fcntl(fd, libc::F_GETFD) { + -1 => Err(FromEnvErrorInner::CannotOpenFd( + fd, + io::Error::last_os_error(), + )), + _ => Ok(()), + } +} + +unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner> { + if check_pipe { + let mut stat = mem::zeroed(); + if libc::fstat(fd, &mut stat) == -1 { + let last_os_error = io::Error::last_os_error(); + fcntl_check(fd)?; + Err(FromEnvErrorInner::NotAPipe(fd, Some(last_os_error))) + } else { + // On android arm and i686 mode_t is u16 and st_mode is u32, + // this generates a type mismatch when S_IFIFO (declared as mode_t) + // is used in operations with st_mode, so we use this workaround + // to get the value of S_IFIFO with the same type of st_mode. + #[allow(unused_assignments)] + let mut s_ififo = stat.st_mode; + s_ififo = libc::S_IFIFO as _; + if stat.st_mode & s_ififo == s_ififo { + return Ok(()); + } + Err(FromEnvErrorInner::NotAPipe(fd, None)) + } + } else { + fcntl_check(fd) + } +} + +fn clone_fd_and_set_cloexec(fd: c_int) -> Result { + // Safety: fd is a valid fd dand it remains open until returns + unsafe { BorrowedFd::borrow_raw(fd) } + .try_clone_to_owned() + .map(File::from) + .map_err(|err| FromEnvErrorInner::CannotOpenFd(fd, err)) +} + +fn set_cloexec(fd: c_int, set: bool) -> io::Result<()> { + unsafe { + let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?; + let new = if set { + previous | libc::FD_CLOEXEC + } else { + previous & !libc::FD_CLOEXEC + }; + if new != previous { + cvt(libc::fcntl(fd, libc::F_SETFD, new))?; + } + Ok(()) + } +} + +fn set_nonblocking(fd: c_int, set: bool) -> io::Result<()> { + let status_flag = if set { libc::O_NONBLOCK } else { 0 }; + + unsafe { + cvt(libc::fcntl(fd, libc::F_SETFL, status_flag))?; + } + + Ok(()) +} + +fn cvt(t: c_int) -> io::Result { + if t == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} + +extern "C" fn sigusr1_handler( + _signum: c_int, + _info: *mut libc::siginfo_t, + _ptr: *mut libc::c_void, +) { + // nothing to do +} + +#[cfg(test)] +mod test { + use super::Client as ClientImp; + + use crate::{test::run_named_fifo_try_acquire_tests, Client}; + + use std::{ + fs::File, + io::{self, Write}, + os::unix::io::AsRawFd, + sync::Arc, + }; + + fn from_imp_client(imp: ClientImp) -> Client { + Client { + inner: Arc::new(imp), + } + } + + fn new_client_from_fifo() -> (Client, String) { + let file = tempfile::NamedTempFile::new().unwrap(); + let fifo_path = file.path().to_owned(); + file.close().unwrap(); // Remove the NamedTempFile to create fifo + + nix::unistd::mkfifo(&fifo_path, nix::sys::stat::Mode::S_IRWXU).unwrap(); + + let arg = format!("fifo:{}", fifo_path.to_str().unwrap()); + + ( + ClientImp::from_fifo(&arg) + .unwrap() + .map(from_imp_client) + .unwrap(), + arg, + ) + } + + fn new_client_from_pipe() -> (Client, String) { + let (read, write) = nix::unistd::pipe().unwrap(); + let read = File::from(read); + let mut write = File::from(write); + + write.write_all(b"1").unwrap(); + + let arg = format!("{},{}", read.as_raw_fd(), write.as_raw_fd()); + + ( + unsafe { ClientImp::from_pipe(&arg, true) } + .unwrap() + .map(from_imp_client) + .unwrap(), + arg, + ) + } + + #[test] + fn test_try_acquire_named_fifo() { + run_named_fifo_try_acquire_tests(&new_client_from_fifo().0); + } + + #[test] + fn test_try_acquire_annoymous_pipe_linux_specific_optimization() { + #[cfg(not(target_os = "linux"))] + assert_eq!( + new_client_from_pipe().0.try_acquire().unwrap_err().kind(), + io::ErrorKind::Unsupported + ); + + #[cfg(target_os = "linux")] + { + let client = new_client_from_pipe().0; + client.acquire().unwrap().drop_without_releasing(); + run_named_fifo_try_acquire_tests(&client); + } + } + + #[test] + fn test_string_arg() { + let (client, arg) = new_client_from_fifo(); + assert_eq!(client.inner.string_arg(), arg); + + let (client, arg) = new_client_from_pipe(); + assert_eq!(client.inner.string_arg(), arg); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/wasm.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/wasm.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/wasm.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/wasm.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,106 @@ +use crate::FromEnvErrorInner; +use std::io; +use std::process::Command; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread::{Builder, JoinHandle}; + +#[derive(Debug)] +pub struct Client { + inner: Arc, +} + +#[derive(Debug)] +struct Inner { + count: Mutex, + cvar: Condvar, +} + +#[derive(Debug)] +pub struct Acquired(()); + +impl Client { + pub fn new(limit: usize) -> io::Result { + Ok(Client { + inner: Arc::new(Inner { + count: Mutex::new(limit), + cvar: Condvar::new(), + }), + }) + } + + pub(crate) unsafe fn open(_s: &str, _check_pipe: bool) -> Result { + Err(FromEnvErrorInner::Unsupported) + } + + pub fn acquire(&self) -> io::Result { + let mut lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + while *lock == 0 { + lock = self + .inner + .cvar + .wait(lock) + .unwrap_or_else(|e| e.into_inner()); + } + *lock -= 1; + Ok(Acquired(())) + } + + pub fn try_acquire(&self) -> io::Result> { + let mut lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + if *lock == 0 { + Ok(None) + } else { + *lock -= 1; + Ok(Some(Acquired(()))) + } + } + + pub fn release(&self, _data: Option<&Acquired>) -> io::Result<()> { + let mut lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + *lock += 1; + drop(lock); + self.inner.cvar.notify_one(); + Ok(()) + } + + pub fn string_arg(&self) -> String { + panic!( + "On this platform there is no cross process jobserver support, + so Client::configure is not supported." + ); + } + + pub fn available(&self) -> io::Result { + let lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + Ok(*lock) + } + + pub fn configure(&self, _cmd: &mut Command) { + unreachable!(); + } +} + +#[derive(Debug)] +pub struct Helper { + thread: JoinHandle<()>, +} + +pub(crate) fn spawn_helper( + client: crate::Client, + state: Arc, + mut f: Box) + Send>, +) -> io::Result { + let thread = Builder::new().spawn(move || { + state.for_each_request(|_| f(client.acquire())); + })?; + + Ok(Helper { thread }) +} + +impl Helper { + pub fn join(self) { + // TODO: this is not correct if the thread is blocked in + // `client.acquire()`. + drop(self.thread.join()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/windows.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/windows.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/src/windows.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/src/windows.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,290 @@ +use crate::FromEnvErrorInner; +use std::ffi::CString; +use std::io; +use std::process::Command; +use std::ptr; +use std::sync::Arc; +use std::thread::{Builder, JoinHandle}; + +#[derive(Debug)] +pub struct Client { + sem: Handle, + name: String, +} + +#[derive(Debug)] +pub struct Acquired; + +#[allow(clippy::upper_case_acronyms)] +type BOOL = i32; +#[allow(clippy::upper_case_acronyms)] +type DWORD = u32; +#[allow(clippy::upper_case_acronyms)] +type HANDLE = *mut u8; +#[allow(clippy::upper_case_acronyms)] +type LONG = i32; + +const ERROR_ALREADY_EXISTS: DWORD = 183; +const FALSE: BOOL = 0; +const INFINITE: DWORD = 0xffffffff; +const SEMAPHORE_MODIFY_STATE: DWORD = 0x2; +const SYNCHRONIZE: DWORD = 0x00100000; +const TRUE: BOOL = 1; + +const WAIT_ABANDONED: DWORD = 128u32; +const WAIT_FAILED: DWORD = 4294967295u32; +const WAIT_OBJECT_0: DWORD = 0u32; +const WAIT_TIMEOUT: DWORD = 258u32; + +extern "system" { + fn CloseHandle(handle: HANDLE) -> BOOL; + fn SetEvent(hEvent: HANDLE) -> BOOL; + fn WaitForMultipleObjects( + ncount: DWORD, + lpHandles: *const HANDLE, + bWaitAll: BOOL, + dwMilliseconds: DWORD, + ) -> DWORD; + fn CreateEventA( + lpEventAttributes: *mut u8, + bManualReset: BOOL, + bInitialState: BOOL, + lpName: *const i8, + ) -> HANDLE; + fn ReleaseSemaphore( + hSemaphore: HANDLE, + lReleaseCount: LONG, + lpPreviousCount: *mut LONG, + ) -> BOOL; + fn CreateSemaphoreA( + lpEventAttributes: *mut u8, + lInitialCount: LONG, + lMaximumCount: LONG, + lpName: *const i8, + ) -> HANDLE; + fn OpenSemaphoreA(dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: *const i8) -> HANDLE; + fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; + #[link_name = "SystemFunction036"] + fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: u32) -> u8; +} + +// Note that we ideally would use the `getrandom` crate, but unfortunately +// that causes build issues when this crate is used in rust-lang/rust (see +// rust-lang/rust#65014 for more information). As a result we just inline +// the pretty simple Windows-specific implementation of generating +// randomness. +fn getrandom(dest: &mut [u8]) -> io::Result<()> { + // Prevent overflow of u32 + for chunk in dest.chunks_mut(u32::MAX as usize) { + let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr(), chunk.len() as u32) }; + if ret == 0 { + return Err(io::Error::new( + io::ErrorKind::Other, + "failed to generate random bytes", + )); + } + } + Ok(()) +} + +impl Client { + pub fn new(limit: usize) -> io::Result { + // Try a bunch of random semaphore names until we get a unique one, + // but don't try for too long. + // + // Note that `limit == 0` is a valid argument above but Windows + // won't let us create a semaphore with 0 slots available to it. Get + // `limit == 0` working by creating a semaphore instead with one + // slot and then immediately acquire it (without ever releaseing it + // back). + for _ in 0..100 { + let mut bytes = [0; 4]; + getrandom(&mut bytes)?; + let mut name = format!("__rust_jobserver_semaphore_{}\0", u32::from_ne_bytes(bytes)); + unsafe { + let create_limit = if limit == 0 { 1 } else { limit }; + let r = CreateSemaphoreA( + ptr::null_mut(), + create_limit as LONG, + create_limit as LONG, + name.as_ptr() as *const _, + ); + if r.is_null() { + return Err(io::Error::last_os_error()); + } + let handle = Handle(r); + + let err = io::Error::last_os_error(); + if err.raw_os_error() == Some(ERROR_ALREADY_EXISTS as i32) { + continue; + } + name.pop(); // chop off the trailing nul + let client = Client { sem: handle, name }; + if create_limit != limit { + client.acquire()?; + } + return Ok(client); + } + } + + Err(io::Error::new( + io::ErrorKind::Other, + "failed to find a unique name for a semaphore", + )) + } + + pub(crate) unsafe fn open(s: &str, _check_pipe: bool) -> Result { + let name = match CString::new(s) { + Ok(s) => s, + Err(e) => return Err(FromEnvErrorInner::CannotParse(e.to_string())), + }; + + let sem = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, name.as_ptr()); + if sem.is_null() { + Err(FromEnvErrorInner::CannotOpenPath( + s.to_string(), + io::Error::last_os_error(), + )) + } else { + Ok(Client { + sem: Handle(sem), + name: s.to_string(), + }) + } + } + + pub fn acquire(&self) -> io::Result { + unsafe { + let r = WaitForSingleObject(self.sem.0, INFINITE); + if r == WAIT_OBJECT_0 { + Ok(Acquired) + } else { + Err(io::Error::last_os_error()) + } + } + } + + pub fn try_acquire(&self) -> io::Result> { + match unsafe { WaitForSingleObject(self.sem.0, 0) } { + WAIT_OBJECT_0 => Ok(Some(Acquired)), + WAIT_TIMEOUT => Ok(None), + WAIT_FAILED => Err(io::Error::last_os_error()), + // We believe this should be impossible for a semaphore, but still + // check the error code just in case it happens. + WAIT_ABANDONED => Err(io::Error::new( + io::ErrorKind::Other, + "Wait on jobserver semaphore returned WAIT_ABANDONED", + )), + _ => unreachable!("Unexpected return value from WaitForSingleObject"), + } + } + + pub fn release(&self, _data: Option<&Acquired>) -> io::Result<()> { + unsafe { + let r = ReleaseSemaphore(self.sem.0, 1, ptr::null_mut()); + if r != 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + } + } + } + + pub fn string_arg(&self) -> String { + self.name.clone() + } + + pub fn available(&self) -> io::Result { + // Can't read value of a semaphore on Windows, so + // try to acquire without sleeping, since we can find out the + // old value on release. If acquisiton fails, then available is 0. + unsafe { + let r = WaitForSingleObject(self.sem.0, 0); + if r != WAIT_OBJECT_0 { + Ok(0) + } else { + let mut prev: LONG = 0; + let r = ReleaseSemaphore(self.sem.0, 1, &mut prev); + if r != 0 { + Ok(prev as usize + 1) + } else { + Err(io::Error::last_os_error()) + } + } + } + } + + pub fn configure(&self, _cmd: &mut Command) { + // nothing to do here, we gave the name of our semaphore to the + // child above + } +} + +#[derive(Debug)] +struct Handle(HANDLE); +// HANDLE is a raw ptr, but we're send/sync +unsafe impl Sync for Handle {} +unsafe impl Send for Handle {} + +impl Drop for Handle { + fn drop(&mut self) { + unsafe { + CloseHandle(self.0); + } + } +} + +#[derive(Debug)] +pub struct Helper { + event: Arc, + thread: JoinHandle<()>, +} + +pub(crate) fn spawn_helper( + client: crate::Client, + state: Arc, + mut f: Box) + Send>, +) -> io::Result { + let event = unsafe { + let r = CreateEventA(ptr::null_mut(), TRUE, FALSE, ptr::null()); + if r.is_null() { + return Err(io::Error::last_os_error()); + } else { + Handle(r) + } + }; + let event = Arc::new(event); + let event2 = event.clone(); + let thread = Builder::new().spawn(move || { + let objects = [event2.0, client.inner.sem.0]; + state.for_each_request(|_| { + const WAIT_OBJECT_1: u32 = WAIT_OBJECT_0 + 1; + match unsafe { WaitForMultipleObjects(2, objects.as_ptr(), FALSE, INFINITE) } { + WAIT_OBJECT_0 => {} + WAIT_OBJECT_1 => f(Ok(crate::Acquired { + client: client.inner.clone(), + data: Acquired, + disabled: false, + })), + _ => f(Err(io::Error::last_os_error())), + } + }); + })?; + Ok(Helper { thread, event }) +} + +impl Helper { + pub fn join(self) { + // Unlike unix this logic is much easier. If our thread was blocked + // in waiting for requests it should already be woken up and + // exiting. Otherwise it's waiting for a token, so we wake it up + // with a different event that it's also waiting on here. After + // these two we should be guaranteed the thread is on its way out, + // so we can safely `join`. + let r = unsafe { SetEvent(self.event.0) }; + if r == 0 { + panic!("failed to set event: {}", io::Error::last_os_error()); + } + drop(self.thread.join()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/client-of-myself.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client-of-myself.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/client-of-myself.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client-of-myself.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +use std::env; +use std::io::prelude::*; +use std::io::BufReader; +use std::process::{Command, Stdio}; +use std::sync::mpsc; +use std::thread; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +fn main() { + if env::var("I_AM_THE_CLIENT").is_ok() { + client(); + } else { + server(); + } +} + +fn server() { + let me = t!(env::current_exe()); + let client = t!(Client::new(1)); + let mut cmd = Command::new(me); + cmd.env("I_AM_THE_CLIENT", "1").stdout(Stdio::piped()); + client.configure(&mut cmd); + let acq = client.acquire().unwrap(); + let mut child = t!(cmd.spawn()); + let stdout = child.stdout.take().unwrap(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + for line in BufReader::new(stdout).lines() { + tx.send(t!(line)).unwrap(); + } + }); + + for _ in 0..100 { + assert!(rx.try_recv().is_err()); + } + + drop(acq); + assert_eq!(rx.recv().unwrap(), "hello!"); + t.join().unwrap(); + assert!(rx.recv().is_err()); + client.acquire().unwrap(); +} + +fn client() { + let client = unsafe { Client::from_env().unwrap() }; + let acq = client.acquire().unwrap(); + println!("hello!"); + drop(acq); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/client.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/client.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/client.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,192 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; +use std::sync::Arc; +use std::thread; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +struct Test { + name: &'static str, + f: &'static (dyn Fn() + Send + Sync), + make_args: &'static [&'static str], + rule: &'static (dyn Fn(&str) -> String + Send + Sync), +} + +const TESTS: &[Test] = &[ + Test { + name: "no j args", + make_args: &[], + rule: &|me| me.to_string(), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "no j args with plus", + make_args: &[], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_none() }); + }, + }, + Test { + name: "j args with plus", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + assert!(unsafe { Client::from_env().is_some() }); + }, + }, + Test { + name: "acquire", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + drop(c.acquire().unwrap()); + drop(c.acquire().unwrap()); + }, + }, + Test { + name: "acquire3", + make_args: &["-j3"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let b = c.acquire().unwrap(); + drop((a, b)); + }, + }, + Test { + name: "acquire blocks", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + let a = c.acquire().unwrap(); + let hit = Arc::new(AtomicBool::new(false)); + let hit2 = hit.clone(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + tx.send(()).unwrap(); + let _b = c.acquire().unwrap(); + hit2.store(true, Ordering::SeqCst); + }); + rx.recv().unwrap(); + assert!(!hit.load(Ordering::SeqCst)); + drop(a); + t.join().unwrap(); + assert!(hit.load(Ordering::SeqCst)); + }, + }, + Test { + name: "acquire_raw", + make_args: &["-j2"], + rule: &|me| format!("+{}", me), + f: &|| { + let c = unsafe { Client::from_env().unwrap() }; + c.acquire_raw().unwrap(); + c.release_raw().unwrap(); + }, + }, +]; + +fn main() { + if let Ok(test) = env::var("TEST_TO_RUN") { + return (TESTS.iter().find(|t| t.name == test).unwrap().f)(); + } + + let me = t!(env::current_exe()); + let me = me.to_str().unwrap(); + let filter = env::args().nth(1); + + let join_handles = TESTS + .iter() + .filter(|test| match filter { + Some(ref s) => test.name.contains(s), + None => true, + }) + .map(|test| { + let td = t!(tempfile::tempdir()); + let makefile = format!( + "\ +all: export TEST_TO_RUN={} +all: +\t{} +", + test.name, + (test.rule)(me) + ); + t!(t!(File::create(td.path().join("Makefile"))).write_all(makefile.as_bytes())); + thread::spawn(move || { + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); + let mut cmd = Command::new(prog); + cmd.args(test.make_args); + cmd.current_dir(td.path()); + + (test, cmd.output().unwrap()) + }) + }) + .collect::>(); + + println!("\nrunning {} tests\n", join_handles.len()); + + let failures = join_handles + .into_iter() + .filter_map(|join_handle| { + let (test, output) = join_handle.join().unwrap(); + + if output.status.success() { + println!("test {} ... ok", test.name); + None + } else { + println!("test {} ... FAIL", test.name); + Some((test, output)) + } + }) + .collect::>(); + + if failures.is_empty() { + println!("\ntest result: ok\n"); + return; + } + + println!("\n----------- failures"); + + for (test, output) in failures { + println!("test {}", test.name); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + + println!("\texit status: {}", output.status); + if !stdout.is_empty() { + println!("\tstdout ==="); + for line in stdout.lines() { + println!("\t\t{}", line); + } + } + + if !stderr.is_empty() { + println!("\tstderr ==="); + for line in stderr.lines() { + println!("\t\t{}", line); + } + } + } + + std::process::exit(4); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/helper.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/helper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/helper.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/helper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +use jobserver::Client; +use std::sync::atomic::*; +use std::sync::*; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +#[test] +fn helper_smoke() { + let client = t!(Client::new(1)); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.into_helper_thread(|_| ()).unwrap()); +} + +#[test] +fn acquire() { + let (tx, rx) = mpsc::channel(); + let client = t!(Client::new(1)); + let helper = client + .into_helper_thread(move |a| drop(tx.send(a))) + .unwrap(); + assert!(rx.try_recv().is_err()); + helper.request_token(); + rx.recv().unwrap().unwrap(); + helper.request_token(); + rx.recv().unwrap().unwrap(); + + helper.request_token(); + helper.request_token(); + rx.recv().unwrap().unwrap(); + rx.recv().unwrap().unwrap(); + + helper.request_token(); + helper.request_token(); + drop(helper); +} + +#[test] +fn prompt_shutdown() { + for _ in 0..100 { + let client = jobserver::Client::new(4).unwrap(); + let count = Arc::new(AtomicU32::new(0)); + let count2 = count.clone(); + let tokens = Arc::new(Mutex::new(Vec::new())); + let helper = client + .into_helper_thread(move |token| { + tokens.lock().unwrap().push(token); + count2.fetch_add(1, Ordering::SeqCst); + }) + .unwrap(); + + // Request more tokens than what are available. + for _ in 0..5 { + helper.request_token(); + } + // Wait for at least some of the requests to finish. + while count.load(Ordering::SeqCst) < 3 { + std::thread::yield_now(); + } + // Drop helper + let t = std::time::Instant::now(); + drop(helper); + let d = t.elapsed(); + assert!(d.as_secs_f64() < 0.5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/make-as-a-client.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/make-as-a-client.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/make-as-a-client.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/make-as-a-client.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::net::{TcpListener, TcpStream}; +use std::process::Command; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +fn main() { + if env::var("_DO_THE_TEST").is_ok() { + std::process::exit( + Command::new(env::var_os("MAKE").unwrap()) + .env("MAKEFLAGS", env::var_os("CARGO_MAKEFLAGS").unwrap()) + .env_remove("_DO_THE_TEST") + .args(&env::args_os().skip(1).collect::>()) + .status() + .unwrap() + .code() + .unwrap_or(1), + ); + } + + if let Ok(s) = env::var("TEST_ADDR") { + let mut contents = Vec::new(); + t!(t!(TcpStream::connect(&s)).read_to_end(&mut contents)); + return; + } + + let c = t!(Client::new(1)); + let td = tempfile::tempdir().unwrap(); + + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); + + let me = t!(env::current_exe()); + let me = me.to_str().unwrap(); + + let mut cmd = Command::new(&me); + cmd.current_dir(td.path()); + cmd.env("MAKE", prog); + cmd.env("_DO_THE_TEST", "1"); + + t!(t!(File::create(td.path().join("Makefile"))).write_all( + format!( + "\ +all: foo bar +foo: +\t{0} +bar: +\t{0} +", + me + ) + .as_bytes() + )); + + // We're leaking one extra token to `make` sort of violating the makefile + // jobserver protocol. It has the desired effect though. + c.configure(&mut cmd); + + let listener = t!(TcpListener::bind("127.0.0.1:0")); + let addr = t!(listener.local_addr()); + cmd.env("TEST_ADDR", addr.to_string()); + let mut child = t!(cmd.spawn()); + + // We should get both connections as the two programs should be run + // concurrently. + let a = t!(listener.accept()); + let b = t!(listener.accept()); + drop((a, b)); + + assert!(t!(child.wait()).success()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/server.rs clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/server.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jobserver/tests/server.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jobserver/tests/server.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,181 @@ +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; +use std::sync::Arc; +use std::thread; + +use jobserver::Client; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +#[test] +fn server_smoke() { + let c = t!(Client::new(1)); + drop(c.acquire().unwrap()); + drop(c.acquire().unwrap()); +} + +#[test] +fn server_multiple() { + let c = t!(Client::new(2)); + let a = c.acquire().unwrap(); + let b = c.acquire().unwrap(); + drop((a, b)); +} + +#[test] +fn server_available() { + let c = t!(Client::new(10)); + assert_eq!(c.available().unwrap(), 10); + let a = c.acquire().unwrap(); + assert_eq!(c.available().unwrap(), 9); + drop(a); + assert_eq!(c.available().unwrap(), 10); +} + +#[test] +fn server_none_available() { + let c = t!(Client::new(2)); + assert_eq!(c.available().unwrap(), 2); + let a = c.acquire().unwrap(); + assert_eq!(c.available().unwrap(), 1); + let b = c.acquire().unwrap(); + assert_eq!(c.available().unwrap(), 0); + drop(a); + assert_eq!(c.available().unwrap(), 1); + drop(b); + assert_eq!(c.available().unwrap(), 2); +} + +#[test] +fn server_blocks() { + let c = t!(Client::new(1)); + let a = c.acquire().unwrap(); + let hit = Arc::new(AtomicBool::new(false)); + let hit2 = hit.clone(); + let (tx, rx) = mpsc::channel(); + let t = thread::spawn(move || { + tx.send(()).unwrap(); + let _b = c.acquire().unwrap(); + hit2.store(true, Ordering::SeqCst); + }); + rx.recv().unwrap(); + assert!(!hit.load(Ordering::SeqCst)); + drop(a); + t.join().unwrap(); + assert!(hit.load(Ordering::SeqCst)); +} + +#[test] +fn make_as_a_single_thread_client() { + let c = t!(Client::new(1)); + let td = tempfile::tempdir().unwrap(); + + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); + let mut cmd = Command::new(prog); + cmd.current_dir(td.path()); + + t!(t!(File::create(td.path().join("Makefile"))).write_all( + b" +all: foo bar +foo: +\techo foo +bar: +\techo bar +" + )); + + // The jobserver protocol means that the `make` process itself "runs with a + // token", so we acquire our one token to drain the jobserver, and this + // should mean that `make` itself never has a second token available to it. + let _a = c.acquire(); + c.configure(&mut cmd); + let output = t!(cmd.output()); + println!( + "\n\t=== stderr\n\t\t{}", + String::from_utf8_lossy(&output.stderr).replace("\n", "\n\t\t") + ); + println!( + "\t=== stdout\n\t\t{}", + String::from_utf8_lossy(&output.stdout).replace("\n", "\n\t\t") + ); + + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + + let stdout = String::from_utf8_lossy(&output.stdout).replace("\r\n", "\n"); + let a = "\ +echo foo +foo +echo bar +bar +"; + let b = "\ +echo bar +bar +echo foo +foo +"; + + assert!(stdout == a || stdout == b); +} + +#[test] +fn make_as_a_multi_thread_client() { + let c = t!(Client::new(1)); + let td = tempfile::tempdir().unwrap(); + + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); + let mut cmd = Command::new(prog); + cmd.current_dir(td.path()); + + t!(t!(File::create(td.path().join("Makefile"))).write_all( + b" +all: foo bar +foo: +\techo foo +bar: +\techo bar +" + )); + + // We're leaking one extra token to `make` sort of violating the makefile + // jobserver protocol. It has the desired effect though. + c.configure(&mut cmd); + let output = t!(cmd.output()); + println!( + "\n\t=== stderr\n\t\t{}", + String::from_utf8_lossy(&output.stderr).replace("\n", "\n\t\t") + ); + println!( + "\t=== stdout\n\t\t{}", + String::from_utf8_lossy(&output.stdout).replace("\n", "\n\t\t") + ); + + assert!(output.status.success()); +} + +#[test] +fn zero_client() { + let client = t!(Client::new(0)); + let (tx, rx) = mpsc::channel(); + let helper = client + .into_helper_thread(move |a| drop(tx.send(a))) + .unwrap(); + helper.request_token(); + helper.request_token(); + + for _ in 0..1000 { + assert!(rx.try_recv().is_err()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"1d85e40ad5fc34544db636cb1b30bab5bf177fae0a7b276d1e9e68bb67fdea12","Cargo.lock":"736c5aeaecc36298ee8afaf266e8e3d73fb6b9c605720226c90efc363ec9cf92","Cargo.toml":"ad3f76b5f47bccb6a409d56b95bf7b02217618fe35b6c0521eef2ed92a18f20b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"22b83fb92a50418c7df9564b9c179fa2a0e74f293bc58b72dd7e218fc0902143","README.md":"cb72ab0179d2c2578d2840bc2bdf96935833178d34466fb5c1982f9f6be9547f","appveyor.yml":"5861c1d97075d4a09aea38b0ade35c0a03498f41cdc4f8754122b3793ddb6493","benches/decoding_benchmark.rs":"8a0f2cd1cee342493bee575e9938f0d077eb970dac8d76fe2c3ef9b71105e387","benches/large_image.jpg":"4cd902020e963fffd23e3a0d0be71207efe665265518fe5a3809ba77699a5fd0","benches/large_image.rs":"5c45235e625879dd8bbc8bd513864fba6aab513918a79114f4c3bf0fdd801cc0","benches/tower.jpg":"40b5ae0df66540ba3ac60edf2840b4b8edd0500706105f3b63083e3a8993119a","benches/tower_grayscale.jpg":"90519862a5bc59ca5702ff802a2f16e8cdcd28b124f891bb03556b920742d94e","benches/tower_progressive.jpg":"e87bac231e2c11b1aef6981358189ad5c51f67069a43131b1512ed823a7607c6","examples/decode.rs":"73cb3cdb03f02b7ace7860143d7ead659cd3f04a7e3d35c73450930f651326fb","rust-toolchain":"b37685c6d7646baf7933322dcbdadf302fa6d575cf2be7c6c3a2402424453113","src/arch/mod.rs":"d7484cefbc186c887e926fa5ea2950c412f95326152e6bc7a19484d3eb3e63b9","src/arch/neon.rs":"9ee5fbebb8621b69e2031162a61269cd0784883fbe574974250ac2a23b66dd74","src/arch/ssse3.rs":"c470868f692ecad6428c5dc113c6fa3261cd3c23ce5158c5a8c7174e12298c65","src/arch/wasm.rs":"c3aea9d15b722fa2a57ae9c3b09bf5b3bd4b86d48efa6440e00a9f8688190489","src/decoder.rs":"07680c94bf754329c00a3ca9f1c3a38c964296cd528ff8954597365e02a864da","src/decoder/lossless.rs":"e1249764347a2b1fc3de955e3e822c7dddd29418e3049990fe036259d10df488","src/error.rs":"7c0deaa7c58b4f1c00a42616ce0b8b37c1040ac85fcdade36ca20aa0c2435a61","src/huffman.rs":"80df6386478375e99614c4639af004aede2927763645b0a49df6b6d083eef5f0","src/idct.rs":"255d74922aedcb287f368b74d1ee3e2bb5d64d959100269eab0224234c94d94f","src/lib.rs":"f8fc7484fa5e66728f248377eef89477b16ae0891850bdb8640a15566ca82cf1","src/marker.rs":"e68c3ffc47bfb16b2f08ed169abde7d95369e1a887ba3a6edd3d453ba0e1e2af","src/parser.rs":"b63541da7b218ea472b86a396f9408279d4452e70ca56f69182e409ae5a23961","src/upsampler.rs":"234e6f479cd90166b1db19884ef9ec21c50bf7c838c2bd646e6ee563eafd3f0f","src/worker/immediate.rs":"7677d198b0eab4cda943a0f60f21f42f9c7c9163dcfe32a77fa50d0b47e90be0","src/worker/mod.rs":"98275ba202d4acd3f5c9568f404c9fd1412668240490e0d2f70e9654f7753b44","src/worker/multithreaded.rs":"6d5bb0d3ed09bf179bee4a0b3c625d497b3b35535545cf780b2497d333c8fdd9","src/worker/rayon.rs":"7ae36b76d8de63c009f3990e085c46691438a081aeb564fe277cfec68e5bbfe1","tests/lib.rs":"577139e54a05e0ad47e8f936a22642cc9a22df1582ad9f66111d01f31d9e7e67","tests/rayon-0.rs":"09cd6f6f4cc6cb23e629a53801cbd981e4c84ce380b0206892ee2b7907edc004","tests/rayon-1.rs":"48c65a31da2d3891ac52191813351293907588d1f10549f53a649b287af15784","tests/rayon-2.rs":"85c50e208788b731fc8d66d9e0efaf4c1bf12dc223ac2a7e90f4289fd49c07fa","tests/rayon.rs":"fc3688f55a39a07cb54fe615bc4beb468d61bc3e0ef1bb87b5ca01c7b3d85d7e"},"package":"f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## v0.3.1 (2024-01-13) - -- Added a WASM SIMD implementation. -- Allow reading the XMP packet. -- Admit more precision values in JPEG Lossless. - -## v0.3.0 (2022-10-17) - -- The MSRV policy is now managed by the `rust-version` field in `Cargo.toml`. -- The color transform can now be overridden as well as hinted with - `Decoder::set_color_transform`. - -## v0.2.6 (2022-05-09) - -- Another fix to allow usage in WASM target. -- Decoding in the WASM target is now actively tested in CI. - -## v0.2.5 (2022-05-02) - -- Fix single threaded usage in WASM target. - -## v0.2.4 (2022-04-01) - -- Corrects minimal version requirements of dependency `rayon`. - -## v0.2.3 (2022-02-14) - -- Added `Decoder::set_max_decoding_buffer_size` which limits the bytes - allocated for the output of the decoding process. -- Added Arm64-Neon intrinsic implementation of idct and color conversion. This - depends on a Rust nightly compiler feature ([`aarch64_target_feature`]) and - it must be explicitly enabled. As soon as the minimum supported Rust version - includes the stabilization of this feature, the code will be enabled by - default and the feature changed to do nothing. - -[`aarch64_target_feature`]: https://github.com/rust-lang/rust/issues/90620 - -## v0.2.2 (2022-02-12) - -- Added and SSE3-specific SIMD intrinsic implementation for idct and color - conversion. It will run if applicable targets are detect at _runtime_. -- The SIMD implementation is not bit-for-bit compatible with non-SIMD output. - You can enable the `platform_independent` feature, to ensure that only - bit-for-bit equivalent code runs and output is the same on all platforms. -- Improved performance some more by avoiding bounds checks with array types. -- Multithreading is now used more frequently, without the rayon target, except - on an explicit list of unsupported platforms. - -## v0.2.1 (2022-12-09) - -- Fix decoding error due to conflict of lossless with some spectral selections. - -## v0.2.0 (2021-12-04) - -- Added Lossless JPEG support -- Added support for EXIF and ICC data -- Minimum supported rust version changed to 1.48 and no formal policy for bump releases for now -- Minor stability fixes on invalid jpeg images - -## v0.1.22 (2021-01-27) - -- Fix panic on jpeg without frames. - -## v0.1.21 (2021-01-23) - -- Fix incorrect order of MCUs in non-interleaved streams -- DCT Progressive images with incomplete coefficient blocks are now rendered -- Fix a panic on invalid dimensions -- Reduce allocations and runtime of decoding -- Rework multi-threading to run a thread per component - -## v0.1.20 (2020-07-04) - -- Fix decoding of some progressive images failing -- Several more performance improvements -- Add `PixelFormat::pixel_bytes` to determine the size of pixels -- Cleanup and clarification of the 8x8 idct implementation -- Updated fuzzing harnesses and helpers - -## v0.1.19 (2020-04-27) -- Fix decoding returning too much image data -- Fix recognizing padding in marker segments -- Several decode performance improvements -- Remove use of deprecated `Error::description` - -## v0.1.18 (2019-12-10) -- Fix two bugs causing panics introduced in 0.1.17. - -## v0.1.17 (2019-12-08) -- Minimum supported rust version changed to 1.34 -- Fix clippy::into_iter_on_array warning -- Ignore extraneous bytes after SOS -- Support IDCT Scaling - -## v0.1.16 (2019-08-25) -- Minimum supported rust version changed to 1.28 -- Allow zero length DHT segments - -## v0.1.15 (2018-06-10) -- Added support for WebAssembly and asm.js (thanks @CryZe!) -- Bugfix for images with APP14 segments longer than 12 bytes. - -## v0.1.14 (2018-02-15) -- Updated `rayon` to 1.0. - -## v0.1.13 (2017-06-14) -- Updated `rayon` to 0.8. - -## v0.1.12 (2017-04-07) -- Fixed an integer overflow in `derive_huffman_codes`. -- Updated `rayon` to 0.7. - -## v0.1.11 (2017-01-09) -- Fixed an integer overflow. -- Updated `byteorder` to 1.0. - -## v0.1.10 (2016-12-23) -- Updated `rayon` to 0.6 - -## v0.1.9 (2016-12-12) -- Added a generic integer upsampler, which brings support for some unusual subsampling schemes, e.g. 4:1:1 (thanks @iamrohit7!) -- Made rayon optional through the `rayon` cargo feature (thanks @jackpot51!) - -## v0.1.8 (2016-11-05) -* Updated rayon to version 0.5. - -## v0.1.7 (2016-10-04) -- Added `UnsupportedFeature::NonIntegerSubsamplingRatio` error -- Fixed a bug which could cause certain images to fail decoding -- Fixed decoding of JPEGs which has a final RST marker in their entropy-coded data -- Avoid allocating coefficients when calling `read_info()` on progressive JPEGs - -## v0.1.6 (2016-07-12) -- Added support for 16-bit quantization tables (even though the JPEG spec explicitly - states "An 8-bit DCT-based process shall not use a 16-bit precision quantization table", - but since libjpeg allows it there is little choice...) -- Added support for decoding files with extraneous data (this violates the JPEG spec, but libjpeg allows it) -- Fixed panic when decoding files without SOF -- Fixed bug which caused files with certain APP marker segments to fail decoding - -## v0.1.5 (2016-06-22) -- Removed `euclid` and `num-rational` dependencies -- Updated `rayon` to 0.4 - -## v0.1.4 (2016-04-20) -- Replaced `num` with `num-rational` - -## v0.1.3 (2016-04-06) -- Updated `byteorder` to 0.5 - -## v0.1.2 (2016-03-08) -- Fixed a bug which was causing some progressive JPEGs to fail decoding -- Performance improvements - -## v0.1.1 (2016-02-29) -- Performance improvements - -## v0.1.0 (2016-02-13) -- Initial release diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 @@ -1,661 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap", - "unicode-width", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "csv" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -dependencies = [ - "criterion", - "png", - "rayon", - "walkdir", - "wasm-bindgen", - "wasm-bindgen-test", -] - -[[package]] -name = "js-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "png" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" -dependencies = [ - "bitflags", - "crc32fast", - "deflate", - "miniz_oxide", -] - -[[package]] -name = "proc-macro2" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "serde" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "serde_json" -version = "1.0.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" - -[[package]] -name = "wasm-bindgen-test" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" -dependencies = [ - "console_error_panic_hook", - "js-sys", - "scoped-tls", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -rust-version = "1.61.0" -name = "jpeg-decoder" -version = "0.3.1" -authors = ["The image-rs Developers"] -exclude = [ - "/tests/*", - "!/tests/*.rs", -] -description = "JPEG decoder" -documentation = "https://docs.rs/jpeg-decoder" -readme = "README.md" -keywords = [ - "jpeg", - "jpg", - "decoder", - "image", -] -license = "MIT OR Apache-2.0" -repository = "https://github.com/image-rs/jpeg-decoder" - -[[test]] -name = "rayon" -required-features = ["rayon"] - -[[test]] -name = "rayon-0" -required-features = ["rayon"] - -[[test]] -name = "rayon-1" -required-features = ["rayon"] - -[[test]] -name = "rayon-2" -required-features = ["rayon"] - -[[bench]] -name = "decoding_benchmark" -harness = false - -[[bench]] -name = "large_image" -harness = false - -[dependencies.rayon] -version = "1.5.1" -optional = true - -[dev-dependencies.criterion] -version = "0.3" - -[dev-dependencies.png] -version = "0.16" - -[dev-dependencies.walkdir] -version = "2.0" - -[dev-dependencies.wasm-bindgen] -version = "=0.2.83" - -[dev-dependencies.wasm-bindgen-test] -version = "0.3" - -[features] -default = ["rayon"] -nightly_aarch64_neon = [] -platform_independent = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-APACHE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -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 - - http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-MIT 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 The jpeg-decoder Developers - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/README.md clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -**WARNING: This crate is in maintenance mode as _image-rs_ seeks to move over to the zune-jpeg crate. However, since other Rust JPEG crates do not support lossless mode, we will continue to welcome PRs related to that functionality.** - ---- -# jpeg-decoder - -[![Rust CI](https://github.com/image-rs/jpeg-decoder/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/jpeg-decoder/actions) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/k65rrkd0f8yb4o9w/branch/master?svg=true)](https://ci.appveyor.com/project/kaksmet/jpeg-decoder/branch/master) -[![crates.io](https://img.shields.io/crates/v/jpeg-decoder.svg)](https://crates.io/crates/jpeg-decoder) - -A Rust library for decoding JPEGs. - -[Documentation](https://docs.rs/jpeg-decoder) - -## Example - -Cargo.toml: -```toml -[dependencies] -jpeg-decoder = "0.3" -``` - -main.rs: -```rust -extern crate jpeg_decoder as jpeg; - -use std::fs::File; -use std::io::BufReader; - -fn main() { - let file = File::open("hello_world.jpg").expect("failed to open file"); - let mut decoder = jpeg::Decoder::new(BufReader::new(file)); - let pixels = decoder.decode().expect("failed to decode image"); - let metadata = decoder.info().unwrap(); -} -``` - -## Requirements - -This crate compiles with Rust >= 1.61. Minimum supported Rust version: -- All releases `0.1.*` compile with Rust >= 1.36. -- All releases `0.2.*` compile with Rust >= 1.48. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/appveyor.yml clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/appveyor.yml --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/appveyor.yml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - - TARGET: i686-pc-windows-msvc - - TARGET: i686-pc-windows-gnu - -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - SET PATH=%PATH%;C:\MinGW\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo build --verbose - - cargo test --tests --benches - - cargo bench --bench decoding_benchmark --no-default-features --features "$FEATURES" -- --warm-up-time 1 --measurement-time 1 --sample-size 25 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/decoding_benchmark.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/decoding_benchmark.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/decoding_benchmark.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/decoding_benchmark.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -extern crate criterion; -extern crate jpeg_decoder; - -use criterion::{black_box, Criterion}; - -use jpeg_decoder as jpeg; -use jpeg_decoder::ImageInfo; - -fn read_image(image: &[u8]) -> Vec { - jpeg::Decoder::new(black_box(image)).decode().unwrap() -} - -fn read_metadata(image: &[u8]) -> ImageInfo { - let mut decoder = jpeg::Decoder::new(black_box(image)); - decoder.read_info().unwrap(); - decoder.info().unwrap() -} - -fn main() { - let mut c = Criterion::default().configure_from_args(); - c.bench_function("decode a 512x512 JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower.jpg")) - })); - - c.bench_function("decode a 512x512 progressive JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower_progressive.jpg")) - })); - - c.bench_function("decode a 512x512 grayscale JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower_grayscale.jpg")) - })); - - c.bench_function("extract metadata from an image", |b| b.iter(|| { - read_metadata(include_bytes!("tower.jpg")) - })); - - c.bench_function("decode a 3072x2048 RGB Lossless JPEG", |b| b.iter(|| { - read_image(include_bytes!("../tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.jpg")) - })); - c.final_summary(); -} \ No newline at end of file Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.jpg differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/large_image.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -extern crate criterion; -extern crate jpeg_decoder; - -use criterion::{black_box, Criterion}; - -use jpeg_decoder as jpeg; - -fn read_image(image: &[u8]) -> Vec { - jpeg::Decoder::new(black_box(image)).decode().unwrap() -} - -fn main() { - let mut c = Criterion::default().configure_from_args(); - c.bench_function("decode a 2268x1512 JPEG", |b| { - b.iter(|| read_image(include_bytes!("large_image.jpg"))) - }); - c.final_summary(); -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/tower.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower.jpg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_grayscale.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_grayscale.jpg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_progressive.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/benches/tower_progressive.jpg differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/examples/decode.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/examples/decode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/examples/decode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/examples/decode.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -extern crate jpeg_decoder as jpeg; -extern crate png; - -use std::env; -use std::fs::File; -use std::io::{self, BufReader, Write}; -use std::process; - -fn usage() -> ! { - write!(io::stderr(), "usage: decode image.jpg image.png").unwrap(); - process::exit(1) -} - -fn main() { - let mut args = env::args().skip(1); - let input_path = args.next().unwrap_or_else(|| usage()); - let output_path = args.next().unwrap_or_else(|| usage()); - - let input_file = File::open(input_path).expect("The specified input file could not be opened"); - let mut decoder = jpeg::Decoder::new(BufReader::new(input_file)); - let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder"); - let info = decoder.info().unwrap(); - - eprintln!("{:?}", info); - eprintln!("Exif: {}", decoder.exif_data().is_some()); - eprintln!("XMP: {}", decoder.xmp_data().is_some()); - eprintln!("ICC: {}", decoder.icc_profile().is_some()); - - let output_file = File::create(output_path).unwrap(); - let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32); - - match info.pixel_format { - jpeg::PixelFormat::L16 => { - encoder.set_depth(png::BitDepth::Sixteen); - encoder.set_color(png::ColorType::Grayscale); - }, - jpeg::PixelFormat::RGB24 => { - encoder.set_depth(png::BitDepth::Eight); - encoder.set_color(png::ColorType::RGB); - }, - jpeg::PixelFormat::CMYK32 => { - data = cmyk_to_rgb(&mut data); - encoder.set_depth(png::BitDepth::Eight); - encoder.set_color(png::ColorType::RGB) - }, - jpeg::PixelFormat::L8 => { - encoder.set_depth(png::BitDepth::Eight); - encoder.set_color(png::ColorType::Grayscale); - }, - } - - encoder.write_header() - .expect("writing png header failed") - .write_image_data(&data) - .expect("png encoding failed"); -} - -fn cmyk_to_rgb(input: &[u8]) -> Vec { - let size = input.len() - input.len() / 4; - let mut output = Vec::with_capacity(size); - - for pixel in input.chunks(4) { - let c = pixel[0] as f32 / 255.0; - let m = pixel[1] as f32 / 255.0; - let y = pixel[2] as f32 / 255.0; - let k = pixel[3] as f32 / 255.0; - - // CMYK -> CMY - let c = c * (1.0 - k) + k; - let m = m * (1.0 - k) + k; - let y = y * (1.0 - k) + k; - - // CMY -> RGB - let r = (1.0 - c) * 255.0; - let g = (1.0 - m) * 255.0; - let b = (1.0 - y) * 255.0; - - output.push(r as u8); - output.push(g as u8); - output.push(b as u8); - } - - output -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/rust-toolchain clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/rust-toolchain --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/rust-toolchain 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/rust-toolchain 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -1.61.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/mod.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -#![allow(unsafe_code)] - -mod neon; -mod ssse3; -mod wasm; - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -use std::is_x86_feature_detected; - -/// Arch-specific implementation of YCbCr conversion. Returns the number of pixels that were -/// converted. -#[allow(clippy::type_complexity)] -pub fn get_color_convert_line_ycbcr() -> Option usize> -{ - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[allow(unsafe_code)] - { - if is_x86_feature_detected!("ssse3") { - return Some(ssse3::color_convert_line_ycbcr); - } - } - // Runtime detection is not needed on aarch64. - #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] - { - return Some(neon::color_convert_line_ycbcr); - } - #[cfg(all(target_feature = "simd128", target_arch = "wasm32"))] - { - return Some(wasm::color_convert_line_ycbcr); - } - #[allow(unreachable_code)] - None -} - -/// Arch-specific implementation of 8x8 IDCT. -#[allow(clippy::type_complexity)] -pub fn get_dequantize_and_idct_block_8x8( -) -> Option { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[allow(unsafe_code)] - { - if is_x86_feature_detected!("ssse3") { - return Some(ssse3::dequantize_and_idct_block_8x8); - } - } - // Runtime detection is not needed on aarch64. - #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] - { - return Some(neon::dequantize_and_idct_block_8x8); - } - #[cfg(all(target_feature = "simd128", target_arch = "wasm32"))] - { - return Some(wasm::dequantize_and_idct_block_8x8); - } - #[allow(unreachable_code)] - None -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/neon.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/neon.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/neon.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -#[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] -use core::arch::aarch64::*; - -#[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] -#[target_feature(enable = "neon")] -unsafe fn idct8(data: &mut [int16x8_t; 8]) { - // The fixed-point constants here are obtained by taking the fractional part of the constants - // from the non-SIMD implementation and scaling them up by 1<<15. This is because - // vqrdmulhq_n_s16(a, b) is effectively equivalent to (a*b)>>15 (except for possibly some - // slight differences in rounding). - - // The code here is effectively equivalent to the calls to "kernel" in idct.rs, except that it - // doesn't apply any further scaling and fixed point constants have a different precision. - - let p2 = data[2]; - let p3 = data[6]; - let p1 = vqrdmulhq_n_s16(vqaddq_s16(p2, p3), 17734); // 0.5411961 - let t2 = vqsubq_s16( - vqsubq_s16(p1, p3), - vqrdmulhq_n_s16(p3, 27779), // 0.847759065 - ); - let t3 = vqaddq_s16(p1, vqrdmulhq_n_s16(p2, 25079)); // 0.765366865 - - let p2 = data[0]; - let p3 = data[4]; - let t0 = vqaddq_s16(p2, p3); - let t1 = vqsubq_s16(p2, p3); - - let x0 = vqaddq_s16(t0, t3); - let x3 = vqsubq_s16(t0, t3); - let x1 = vqaddq_s16(t1, t2); - let x2 = vqsubq_s16(t1, t2); - - let t0 = data[7]; - let t1 = data[5]; - let t2 = data[3]; - let t3 = data[1]; - - let p3 = vqaddq_s16(t0, t2); - let p4 = vqaddq_s16(t1, t3); - let p1 = vqaddq_s16(t0, t3); - let p2 = vqaddq_s16(t1, t2); - let p5 = vqaddq_s16(p3, p4); - let p5 = vqaddq_s16(p5, vqrdmulhq_n_s16(p5, 5763)); // 0.175875602 - - let t0 = vqrdmulhq_n_s16(t0, 9786); // 0.298631336 - let t1 = vqaddq_s16( - vqaddq_s16(t1, t1), - vqrdmulhq_n_s16(t1, 1741), // 0.053119869 - ); - let t2 = vqaddq_s16( - vqaddq_s16(t2, vqaddq_s16(t2, t2)), - vqrdmulhq_n_s16(t2, 2383), // 0.072711026 - ); - let t3 = vqaddq_s16(t3, vqrdmulhq_n_s16(t3, 16427)); // 0.501321110 - - let p1 = vqsubq_s16(p5, vqrdmulhq_n_s16(p1, 29490)); // 0.899976223 - let p2 = vqsubq_s16( - vqsubq_s16(vqsubq_s16(p5, p2), p2), - vqrdmulhq_n_s16(p2, 18446), // 0.562915447 - ); - - let p3 = vqsubq_s16( - vqrdmulhq_n_s16(p3, -31509), // -0.961570560 - p3, - ); - let p4 = vqrdmulhq_n_s16(p4, -12785); // -0.390180644 - - let t3 = vqaddq_s16(vqaddq_s16(p1, p4), t3); - let t2 = vqaddq_s16(vqaddq_s16(p2, p3), t2); - let t1 = vqaddq_s16(vqaddq_s16(p2, p4), t1); - let t0 = vqaddq_s16(vqaddq_s16(p1, p3), t0); - - data[0] = vqaddq_s16(x0, t3); - data[7] = vqsubq_s16(x0, t3); - data[1] = vqaddq_s16(x1, t2); - data[6] = vqsubq_s16(x1, t2); - data[2] = vqaddq_s16(x2, t1); - data[5] = vqsubq_s16(x2, t1); - data[3] = vqaddq_s16(x3, t0); - data[4] = vqsubq_s16(x3, t0); -} - -#[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] -#[target_feature(enable = "neon")] -unsafe fn transpose8(data: &mut [int16x8_t; 8]) { - // Use NEON's 2x2 matrix transposes (vtrn) to do the transposition in each 4x4 block, then - // combine the 4x4 blocks. - let a01 = vtrnq_s16(data[0], data[1]); - let a23 = vtrnq_s16(data[2], data[3]); - - let four0 = vtrnq_s32(vreinterpretq_s32_s16(a01.0), vreinterpretq_s32_s16(a23.0)); - let four1 = vtrnq_s32(vreinterpretq_s32_s16(a01.1), vreinterpretq_s32_s16(a23.1)); - - let a45 = vtrnq_s16(data[4], data[5]); - let a67 = vtrnq_s16(data[6], data[7]); - - let four2 = vtrnq_s32(vreinterpretq_s32_s16(a45.0), vreinterpretq_s32_s16(a67.0)); - let four3 = vtrnq_s32(vreinterpretq_s32_s16(a45.1), vreinterpretq_s32_s16(a67.1)); - - data[0] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four0.0), vget_low_s32(four2.0))); - data[1] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four1.0), vget_low_s32(four3.0))); - data[2] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four0.1), vget_low_s32(four2.1))); - data[3] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four1.1), vget_low_s32(four3.1))); - data[4] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four0.0), vget_high_s32(four2.0))); - data[5] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four1.0), vget_high_s32(four3.0))); - data[6] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four0.1), vget_high_s32(four2.1))); - data[7] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four1.1), vget_high_s32(four3.1))); -} - -#[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] -#[target_feature(enable = "neon")] -pub unsafe fn dequantize_and_idct_block_8x8( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - // The loop below will write to positions [output_linestride * i, output_linestride * i + 8) - // for 0<=i<8. Thus, the last accessed position is at an offset of output_linestrade * 7 + 7, - // and if that position is in-bounds, so are all other accesses. - assert!( - output.len() - > output_linestride - .checked_mul(7) - .unwrap() - .checked_add(7) - .unwrap() - ); - - const SHIFT: i32 = 3; - - // Read the DCT coefficients, scale them up and dequantize them. - let mut data = [vdupq_n_s16(0); 8]; - for i in 0..8 { - data[i] = vshlq_n_s16( - vmulq_s16( - vld1q_s16(coefficients.as_ptr().wrapping_add(i * 8)), - vreinterpretq_s16_u16(vld1q_u16(quantization_table.as_ptr().wrapping_add(i * 8))), - ), - SHIFT, - ); - } - - // Usual column IDCT - transpose - column IDCT - transpose approach. - idct8(&mut data); - transpose8(&mut data); - idct8(&mut data); - transpose8(&mut data); - - for i in 0..8 { - // The two passes of the IDCT algorithm give us a factor of 8, so the shift here is - // increased by 3. - // As values will be stored in a u8, they need to be 128-centered and not 0-centered. - // We add 128 with the appropriate shift for that purpose. - const OFFSET: i16 = 128 << (SHIFT + 3); - // We want rounding right shift, so we should add (1/2) << (SHIFT+3) before shifting. - const ROUNDING_BIAS: i16 = (1 << (SHIFT + 3)) >> 1; - - let data_with_offset = vqaddq_s16(data[i], vdupq_n_s16(OFFSET + ROUNDING_BIAS)); - - vst1_u8( - output.as_mut_ptr().wrapping_add(output_linestride * i), - vqshrun_n_s16(data_with_offset, SHIFT + 3), - ); - } -} - -#[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] -#[target_feature(enable = "neon")] -pub unsafe fn color_convert_line_ycbcr(y: &[u8], cb: &[u8], cr: &[u8], output: &mut [u8]) -> usize { - assert!(output.len() % 3 == 0); - let num = output.len() / 3; - assert!(num <= y.len()); - assert!(num <= cb.len()); - assert!(num <= cr.len()); - let num_vecs = num / 8; - - for i in 0..num_vecs { - const SHIFT: i32 = 6; - // Load. - let y = vld1_u8(y.as_ptr().wrapping_add(i * 8)); - let cb = vld1_u8(cb.as_ptr().wrapping_add(i * 8)); - let cr = vld1_u8(cr.as_ptr().wrapping_add(i * 8)); - - // Convert to 16 bit and shift. - let y = vreinterpretq_s16_u16(vshll_n_u8(y, SHIFT)); - let cb = vreinterpretq_s16_u16(vshll_n_u8(cb, SHIFT)); - let cr = vreinterpretq_s16_u16(vshll_n_u8(cr, SHIFT)); - - // Add offsets - let y = vqaddq_s16(y, vdupq_n_s16((1 << SHIFT) >> 1)); - let c128 = vdupq_n_s16(128 << SHIFT); - let cb = vqsubq_s16(cb, c128); - let cr = vqsubq_s16(cr, c128); - - // Compute cr * 1.402, cb * 0.34414, cr * 0.71414, cb * 1.772 - let cr_140200 = vqaddq_s16(vqrdmulhq_n_s16(cr, 13173), cr); - let cb_034414 = vqrdmulhq_n_s16(cb, 11276); - let cr_071414 = vqrdmulhq_n_s16(cr, 23401); - let cb_177200 = vqaddq_s16(vqrdmulhq_n_s16(cb, 25297), cb); - - // Last conversion step. - let r = vqaddq_s16(y, cr_140200); - let g = vqsubq_s16(y, vqaddq_s16(cb_034414, cr_071414)); - let b = vqaddq_s16(y, cb_177200); - - // Shift back and convert to u8. - let r = vqshrun_n_s16(r, SHIFT); - let g = vqshrun_n_s16(g, SHIFT); - let b = vqshrun_n_s16(b, SHIFT); - - // Shuffle + store. - vst3_u8( - output.as_mut_ptr().wrapping_add(24 * i), - uint8x8x3_t(r, g, b), - ); - } - - num_vecs * 8 -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/ssse3.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/ssse3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/ssse3.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/ssse3.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,288 +0,0 @@ -#[cfg(target_arch = "x86")] -use std::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use std::arch::x86_64::*; - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[target_feature(enable = "ssse3")] -unsafe fn idct8(data: &mut [__m128i; 8]) { - // The fixed-point constants here are obtained by taking the fractional part of the constants - // from the non-SIMD implementation and scaling them up by 1<<15. This is because - // _mm_mulhrs_epi16(a, b) is effectively equivalent to (a*b)>>15 (except for possibly some - // slight differences in rounding). - - // The code here is effectively equivalent to the calls to "kernel" in idct.rs, except that it - // doesn't apply any further scaling and fixed point constants have a different precision. - - let p2 = data[2]; - let p3 = data[6]; - let p1 = _mm_mulhrs_epi16(_mm_adds_epi16(p2, p3), _mm_set1_epi16(17734)); // 0.5411961 - let t2 = _mm_subs_epi16( - _mm_subs_epi16(p1, p3), - _mm_mulhrs_epi16(p3, _mm_set1_epi16(27779)), // 0.847759065 - ); - let t3 = _mm_adds_epi16(p1, _mm_mulhrs_epi16(p2, _mm_set1_epi16(25079))); // 0.765366865 - - let p2 = data[0]; - let p3 = data[4]; - let t0 = _mm_adds_epi16(p2, p3); - let t1 = _mm_subs_epi16(p2, p3); - - let x0 = _mm_adds_epi16(t0, t3); - let x3 = _mm_subs_epi16(t0, t3); - let x1 = _mm_adds_epi16(t1, t2); - let x2 = _mm_subs_epi16(t1, t2); - - let t0 = data[7]; - let t1 = data[5]; - let t2 = data[3]; - let t3 = data[1]; - - let p3 = _mm_adds_epi16(t0, t2); - let p4 = _mm_adds_epi16(t1, t3); - let p1 = _mm_adds_epi16(t0, t3); - let p2 = _mm_adds_epi16(t1, t2); - let p5 = _mm_adds_epi16(p3, p4); - let p5 = _mm_adds_epi16(p5, _mm_mulhrs_epi16(p5, _mm_set1_epi16(5763))); // 0.175875602 - - let t0 = _mm_mulhrs_epi16(t0, _mm_set1_epi16(9786)); // 0.298631336 - let t1 = _mm_adds_epi16( - _mm_adds_epi16(t1, t1), - _mm_mulhrs_epi16(t1, _mm_set1_epi16(1741)), // 0.053119869 - ); - let t2 = _mm_adds_epi16( - _mm_adds_epi16(t2, _mm_adds_epi16(t2, t2)), - _mm_mulhrs_epi16(t2, _mm_set1_epi16(2383)), // 0.072711026 - ); - let t3 = _mm_adds_epi16(t3, _mm_mulhrs_epi16(t3, _mm_set1_epi16(16427))); // 0.501321110 - - let p1 = _mm_subs_epi16(p5, _mm_mulhrs_epi16(p1, _mm_set1_epi16(29490))); // 0.899976223 - let p2 = _mm_subs_epi16( - _mm_subs_epi16(_mm_subs_epi16(p5, p2), p2), - _mm_mulhrs_epi16(p2, _mm_set1_epi16(18446)), // 0.562915447 - ); - - let p3 = _mm_subs_epi16( - _mm_mulhrs_epi16(p3, _mm_set1_epi16(-31509)), // -0.961570560 - p3, - ); - let p4 = _mm_mulhrs_epi16(p4, _mm_set1_epi16(-12785)); // -0.390180644 - - let t3 = _mm_adds_epi16(_mm_adds_epi16(p1, p4), t3); - let t2 = _mm_adds_epi16(_mm_adds_epi16(p2, p3), t2); - let t1 = _mm_adds_epi16(_mm_adds_epi16(p2, p4), t1); - let t0 = _mm_adds_epi16(_mm_adds_epi16(p1, p3), t0); - - data[0] = _mm_adds_epi16(x0, t3); - data[7] = _mm_subs_epi16(x0, t3); - data[1] = _mm_adds_epi16(x1, t2); - data[6] = _mm_subs_epi16(x1, t2); - data[2] = _mm_adds_epi16(x2, t1); - data[5] = _mm_subs_epi16(x2, t1); - data[3] = _mm_adds_epi16(x3, t0); - data[4] = _mm_subs_epi16(x3, t0); -} - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[target_feature(enable = "ssse3")] -unsafe fn transpose8(data: &mut [__m128i; 8]) { - // Transpose a 8x8 matrix with a sequence of interleaving operations. - // Naming: dABl contains elements from the *l*ower halves of vectors A and B, interleaved, i.e. - // A0 B0 A1 B1 ... - // dABCDll contains elements from the lower quarter (ll) of vectors A, B, C, D, interleaved - - // A0 B0 C0 D0 A1 B1 C1 D1 ... - let d01l = _mm_unpacklo_epi16(data[0], data[1]); - let d23l = _mm_unpacklo_epi16(data[2], data[3]); - let d45l = _mm_unpacklo_epi16(data[4], data[5]); - let d67l = _mm_unpacklo_epi16(data[6], data[7]); - let d01h = _mm_unpackhi_epi16(data[0], data[1]); - let d23h = _mm_unpackhi_epi16(data[2], data[3]); - let d45h = _mm_unpackhi_epi16(data[4], data[5]); - let d67h = _mm_unpackhi_epi16(data[6], data[7]); - // Operating on 32-bits will interleave *consecutive pairs* of 16-bit integers. - let d0123ll = _mm_unpacklo_epi32(d01l, d23l); - let d0123lh = _mm_unpackhi_epi32(d01l, d23l); - let d4567ll = _mm_unpacklo_epi32(d45l, d67l); - let d4567lh = _mm_unpackhi_epi32(d45l, d67l); - let d0123hl = _mm_unpacklo_epi32(d01h, d23h); - let d0123hh = _mm_unpackhi_epi32(d01h, d23h); - let d4567hl = _mm_unpacklo_epi32(d45h, d67h); - let d4567hh = _mm_unpackhi_epi32(d45h, d67h); - // Operating on 64-bits will interleave *consecutive quadruples* of 16-bit integers. - data[0] = _mm_unpacklo_epi64(d0123ll, d4567ll); - data[1] = _mm_unpackhi_epi64(d0123ll, d4567ll); - data[2] = _mm_unpacklo_epi64(d0123lh, d4567lh); - data[3] = _mm_unpackhi_epi64(d0123lh, d4567lh); - data[4] = _mm_unpacklo_epi64(d0123hl, d4567hl); - data[5] = _mm_unpackhi_epi64(d0123hl, d4567hl); - data[6] = _mm_unpacklo_epi64(d0123hh, d4567hh); - data[7] = _mm_unpackhi_epi64(d0123hh, d4567hh); -} - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[target_feature(enable = "ssse3")] -pub unsafe fn dequantize_and_idct_block_8x8( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - // The loop below will write to positions [output_linestride * i, output_linestride * i + 8) - // for 0<=i<8. Thus, the last accessed position is at an offset of output_linestrade * 7 + 7, - // and if that position is in-bounds, so are all other accesses. - assert!( - output.len() - > output_linestride - .checked_mul(7) - .unwrap() - .checked_add(7) - .unwrap() - ); - - #[cfg(target_arch = "x86")] - use std::arch::x86::*; - #[cfg(target_arch = "x86_64")] - use std::arch::x86_64::*; - - const SHIFT: i32 = 3; - - // Read the DCT coefficients, scale them up and dequantize them. - let mut data = [_mm_setzero_si128(); 8]; - for (i, item) in data.iter_mut().enumerate() { - *item = _mm_slli_epi16( - _mm_mullo_epi16( - _mm_loadu_si128(coefficients.as_ptr().wrapping_add(i * 8) as *const _), - _mm_loadu_si128(quantization_table.as_ptr().wrapping_add(i * 8) as *const _), - ), - SHIFT, - ); - } - - // Usual column IDCT - transpose - column IDCT - transpose approach. - idct8(&mut data); - transpose8(&mut data); - idct8(&mut data); - transpose8(&mut data); - - for (i, item) in data.iter_mut().enumerate() { - let mut buf = [0u8; 16]; - // The two passes of the IDCT algorithm give us a factor of 8, so the shift here is - // increased by 3. - // As values will be stored in a u8, they need to be 128-centered and not 0-centered. - // We add 128 with the appropriate shift for that purpose. - const OFFSET: i16 = 128 << (SHIFT + 3); - // We want rounding right shift, so we should add (1/2) << (SHIFT+3) before shifting. - const ROUNDING_BIAS: i16 = (1 << (SHIFT + 3)) >> 1; - - let data_with_offset = _mm_adds_epi16(*item, _mm_set1_epi16(OFFSET + ROUNDING_BIAS)); - - _mm_storeu_si128( - buf.as_mut_ptr() as *mut _, - _mm_packus_epi16( - _mm_srai_epi16(data_with_offset, SHIFT + 3), - _mm_setzero_si128(), - ), - ); - std::ptr::copy_nonoverlapping::( - buf.as_ptr(), - output.as_mut_ptr().wrapping_add(output_linestride * i) as *mut _, - 8, - ); - } -} - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[target_feature(enable = "ssse3")] -pub unsafe fn color_convert_line_ycbcr(y: &[u8], cb: &[u8], cr: &[u8], output: &mut [u8]) -> usize { - assert!(output.len() % 3 == 0); - let num = output.len() / 3; - assert!(num <= y.len()); - assert!(num <= cb.len()); - assert!(num <= cr.len()); - // _mm_loadu_si64 generates incorrect code for Rust <1.58. To circumvent this, we use a full - // 128-bit load, but that requires leaving an extra vector of border to the scalar code. - // From Rust 1.58 on, the _mm_loadu_si128 can be replaced with _mm_loadu_si64 and this - // .saturating_sub() can be removed. - let num_vecs = (num / 8).saturating_sub(1); - - for i in 0..num_vecs { - const SHIFT: i32 = 6; - // Load. - let y = _mm_loadu_si128(y.as_ptr().wrapping_add(i * 8) as *const _); - let cb = _mm_loadu_si128(cb.as_ptr().wrapping_add(i * 8) as *const _); - let cr = _mm_loadu_si128(cr.as_ptr().wrapping_add(i * 8) as *const _); - - // Convert to 16 bit. - let shuf16 = _mm_setr_epi8( - 0, -0x7F, 1, -0x7F, 2, -0x7F, 3, -0x7F, 4, -0x7F, 5, -0x7F, 6, -0x7F, 7, -0x7F, - ); - let y = _mm_slli_epi16(_mm_shuffle_epi8(y, shuf16), SHIFT); - let cb = _mm_slli_epi16(_mm_shuffle_epi8(cb, shuf16), SHIFT); - let cr = _mm_slli_epi16(_mm_shuffle_epi8(cr, shuf16), SHIFT); - - // Add offsets - let c128 = _mm_set1_epi16(128 << SHIFT); - let y = _mm_adds_epi16(y, _mm_set1_epi16((1 << SHIFT) >> 1)); - let cb = _mm_subs_epi16(cb, c128); - let cr = _mm_subs_epi16(cr, c128); - - // Compute cr * 1.402, cb * 0.34414, cr * 0.71414, cb * 1.772 - let cr_140200 = _mm_adds_epi16(_mm_mulhrs_epi16(cr, _mm_set1_epi16(13173)), cr); - let cb_034414 = _mm_mulhrs_epi16(cb, _mm_set1_epi16(11276)); - let cr_071414 = _mm_mulhrs_epi16(cr, _mm_set1_epi16(23401)); - let cb_177200 = _mm_adds_epi16(_mm_mulhrs_epi16(cb, _mm_set1_epi16(25297)), cb); - - // Last conversion step. - let r = _mm_adds_epi16(y, cr_140200); - let g = _mm_subs_epi16(y, _mm_adds_epi16(cb_034414, cr_071414)); - let b = _mm_adds_epi16(y, cb_177200); - - // Shift back and convert to u8. - let zero = _mm_setzero_si128(); - let r = _mm_packus_epi16(_mm_srai_epi16(r, SHIFT), zero); - let g = _mm_packus_epi16(_mm_srai_epi16(g, SHIFT), zero); - let b = _mm_packus_epi16(_mm_srai_epi16(b, SHIFT), zero); - - // Shuffle rrrrrrrrggggggggbbbbbbbb to rgbrgbrgb... - - // Control vectors for _mm_shuffle_epi8. -0x7F is selected so that the resulting position - // after _mm_shuffle_epi8 will be filled with 0, so that the r, g, and b vectors can then - // be OR-ed together. - let shufr = _mm_setr_epi8( - 0, -0x7F, -0x7F, 1, -0x7F, -0x7F, 2, -0x7F, -0x7F, 3, -0x7F, -0x7F, 4, -0x7F, -0x7F, 5, - ); - let shufg = _mm_setr_epi8( - -0x7F, 0, -0x7F, -0x7F, 1, -0x7F, -0x7F, 2, -0x7F, -0x7F, 3, -0x7F, -0x7F, 4, -0x7F, - -0x7F, - ); - let shufb = _mm_alignr_epi8(shufg, shufg, 15); - - let rgb_low = _mm_or_si128( - _mm_shuffle_epi8(r, shufr), - _mm_or_si128(_mm_shuffle_epi8(g, shufg), _mm_shuffle_epi8(b, shufb)), - ); - - // For the next part of the rgb vectors, we need to select R values from 6 up, G and B from - // 5 up. The highest bit of -0x7F + 6 is still set, so the corresponding location will - // still be 0. - let shufr1 = _mm_add_epi8(shufb, _mm_set1_epi8(6)); - let shufg1 = _mm_add_epi8(shufr, _mm_set1_epi8(5)); - let shufb1 = _mm_add_epi8(shufg, _mm_set1_epi8(5)); - - let rgb_hi = _mm_or_si128( - _mm_shuffle_epi8(r, shufr1), - _mm_or_si128(_mm_shuffle_epi8(g, shufg1), _mm_shuffle_epi8(b, shufb1)), - ); - - let mut data = [0u8; 32]; - _mm_storeu_si128(data.as_mut_ptr() as *mut _, rgb_low); - _mm_storeu_si128(data.as_mut_ptr().wrapping_add(16) as *mut _, rgb_hi); - std::ptr::copy_nonoverlapping::( - data.as_ptr(), - output.as_mut_ptr().wrapping_add(24 * i), - 24, - ); - } - - num_vecs * 8 -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/wasm.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/wasm.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/arch/wasm.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/arch/wasm.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,277 +0,0 @@ -#[cfg(target_arch = "wasm32")] -use std::arch::wasm32::*; - -#[cfg(target_arch = "wasm32")] -#[target_feature(enable = "simd128")] -fn idct8(data: &mut [v128; 8]) { - // The fixed-point constants here are obtained by taking the fractional part of the constants - // from the non-SIMD implementation and scaling them up by 1<<15. This is because - // i16x8_q15mulr_sat(a, b) is effectively equivalent to (a*b)>>15 (except for possibly some - // slight differences in rounding). - - // The code here is effectively equivalent to the calls to "kernel" in idct.rs, except that it - // doesn't apply any further scaling and fixed point constants have a different precision. - - let p2 = data[2]; - let p3 = data[6]; - let p1 = i16x8_q15mulr_sat(i16x8_add_sat(p2, p3), i16x8_splat(17734)); // 0.5411961 - let t2 = i16x8_sub_sat( - i16x8_sub_sat(p1, p3), - i16x8_q15mulr_sat(p3, i16x8_splat(27779)), // 0.847759065 - ); - let t3 = i16x8_add_sat(p1, i16x8_q15mulr_sat(p2, i16x8_splat(25079))); // 0.765366865 - - let p2 = data[0]; - let p3 = data[4]; - let t0 = i16x8_add_sat(p2, p3); - let t1 = i16x8_sub_sat(p2, p3); - - let x0 = i16x8_add_sat(t0, t3); - let x3 = i16x8_sub_sat(t0, t3); - let x1 = i16x8_add_sat(t1, t2); - let x2 = i16x8_sub_sat(t1, t2); - - let t0 = data[7]; - let t1 = data[5]; - let t2 = data[3]; - let t3 = data[1]; - - let p3 = i16x8_add_sat(t0, t2); - let p4 = i16x8_add_sat(t1, t3); - let p1 = i16x8_add_sat(t0, t3); - let p2 = i16x8_add_sat(t1, t2); - let p5 = i16x8_add_sat(p3, p4); - let p5 = i16x8_add_sat(p5, i16x8_q15mulr_sat(p5, i16x8_splat(5763))); // 0.175875602 - - let t0 = i16x8_q15mulr_sat(t0, i16x8_splat(9786)); // 0.298631336 - let t1 = i16x8_add_sat( - i16x8_add_sat(t1, t1), - i16x8_q15mulr_sat(t1, i16x8_splat(1741)), // 0.053119869 - ); - let t2 = i16x8_add_sat( - i16x8_add_sat(t2, i16x8_add_sat(t2, t2)), - i16x8_q15mulr_sat(t2, i16x8_splat(2383)), // 0.072711026 - ); - let t3 = i16x8_add_sat(t3, i16x8_q15mulr_sat(t3, i16x8_splat(16427))); // 0.501321110 - - let p1 = i16x8_sub_sat(p5, i16x8_q15mulr_sat(p1, i16x8_splat(29490))); // 0.899976223 - let p2 = i16x8_sub_sat( - i16x8_sub_sat(i16x8_sub_sat(p5, p2), p2), - i16x8_q15mulr_sat(p2, i16x8_splat(18446)), // 0.562915447 - ); - - let p3 = i16x8_sub_sat( - i16x8_q15mulr_sat(p3, i16x8_splat(-31509)), // -0.961570560 - p3, - ); - let p4 = i16x8_q15mulr_sat(p4, i16x8_splat(-12785)); // -0.390180644 - - let t3 = i16x8_add_sat(i16x8_add_sat(p1, p4), t3); - let t2 = i16x8_add_sat(i16x8_add_sat(p2, p3), t2); - let t1 = i16x8_add_sat(i16x8_add_sat(p2, p4), t1); - let t0 = i16x8_add_sat(i16x8_add_sat(p1, p3), t0); - - data[0] = i16x8_add_sat(x0, t3); - data[7] = i16x8_sub_sat(x0, t3); - data[1] = i16x8_add_sat(x1, t2); - data[6] = i16x8_sub_sat(x1, t2); - data[2] = i16x8_add_sat(x2, t1); - data[5] = i16x8_sub_sat(x2, t1); - data[3] = i16x8_add_sat(x3, t0); - data[4] = i16x8_sub_sat(x3, t0); -} - -#[cfg(target_arch = "wasm32")] -#[target_feature(enable = "simd128")] -fn transpose8(data: &mut [v128; 8]) { - // Transpose a 8x8 matrix with a sequence of interleaving operations. - // Naming: dABl contains elements from the *l*ower halves of vectors A and B, interleaved, i.e. - // A0 B0 A1 B1 ... - // dABCDll contains elements from the lower quarter (ll) of vectors A, B, C, D, interleaved - - // A0 B0 C0 D0 A1 B1 C1 D1 ... - let d01l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[0], data[1]); - let d23l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[2], data[3]); - let d45l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[4], data[5]); - let d67l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[6], data[7]); - let d01h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[0], data[1]); - let d23h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[2], data[3]); - let d45h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[4], data[5]); - let d67h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[6], data[7]); - - // Operating on 32-bits will interleave *consecutive pairs* of 16-bit integers. - let d0123ll = i32x4_shuffle::<0, 4, 1, 5>(d01l, d23l); - let d0123lh = i32x4_shuffle::<2, 6, 3, 7>(d01l, d23l); - let d4567ll = i32x4_shuffle::<0, 4, 1, 5>(d45l, d67l); - let d4567lh = i32x4_shuffle::<2, 6, 3, 7>(d45l, d67l); - let d0123hl = i32x4_shuffle::<0, 4, 1, 5>(d01h, d23h); - let d0123hh = i32x4_shuffle::<2, 6, 3, 7>(d01h, d23h); - let d4567hl = i32x4_shuffle::<0, 4, 1, 5>(d45h, d67h); - let d4567hh = i32x4_shuffle::<2, 6, 3, 7>(d45h, d67h); - - // Operating on 64-bits will interleave *consecutive quadruples* of 16-bit integers. - data[0] = i64x2_shuffle::<0, 2>(d0123ll, d4567ll); - data[1] = i64x2_shuffle::<1, 3>(d0123ll, d4567ll); - data[2] = i64x2_shuffle::<0, 2>(d0123lh, d4567lh); - data[3] = i64x2_shuffle::<1, 3>(d0123lh, d4567lh); - data[4] = i64x2_shuffle::<0, 2>(d0123hl, d4567hl); - data[5] = i64x2_shuffle::<1, 3>(d0123hl, d4567hl); - data[6] = i64x2_shuffle::<0, 2>(d0123hh, d4567hh); - data[7] = i64x2_shuffle::<1, 3>(d0123hh, d4567hh); -} - -#[cfg(target_arch = "wasm32")] -#[target_feature(enable = "simd128")] -pub fn dequantize_and_idct_block_8x8( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - // The loop below will write to positions [output_linestride * i, output_linestride * i + 8) - // for 0<=i<8. Thus, the last accessed position is at an offset of output_linestrade * 7 + 7, - // and if that position is in-bounds, so are all other accesses. - assert!( - output.len() - > output_linestride - .checked_mul(7) - .unwrap() - .checked_add(7) - .unwrap() - ); - - const SHIFT: u32 = 3; - - // Read the DCT coefficients, scale them up and dequantize them. - let mut data = [i16x8_splat(0); 8]; - unsafe { - for i in 0..8 { - data[i] = i16x8_shl( - i16x8_mul( - v128_load(coefficients.as_ptr().wrapping_add(i * 8) as *const _), - v128_load(quantization_table.as_ptr().wrapping_add(i * 8) as *const _), - ), - SHIFT, - ); - } - } - - // Usual column IDCT - transpose - column IDCT - transpose approach. - idct8(&mut data); - transpose8(&mut data); - idct8(&mut data); - transpose8(&mut data); - - for i in 0..8 { - // The two passes of the IDCT algorithm give us a factor of 8, so the shift here is - // increased by 3. - // As values will be stored in a u8, they need to be 128-centered and not 0-centered. - // We add 128 with the appropriate shift for that purpose. - const OFFSET: i16 = 128 << (SHIFT + 3); - // We want rounding right shift, so we should add (1/2) << (SHIFT+3) before shifting. - const ROUNDING_BIAS: i16 = (1 << (SHIFT + 3)) >> 1; - - let data_with_offset = i16x8_add_sat(data[i], i16x8_splat(OFFSET + ROUNDING_BIAS)); - - // SAFETY: the assert at the start of this function ensures - // `output_linestride * i + 7` < output.len(), so all accesses are in-bounds. - unsafe { - v128_store64_lane::<0>( - u8x16_narrow_i16x8( - i16x8_shr(data_with_offset, SHIFT + 3), - i16x8_splat(0), - ), - output.as_mut_ptr().wrapping_add(output_linestride * i) as *mut _, - ); - } - } -} - -#[cfg(target_arch = "wasm32")] -#[target_feature(enable = "simd128")] -pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8], output: &mut [u8]) -> usize { - - assert!(output.len() % 3 == 0); - let num = output.len() / 3; - assert!(num <= y_slice.len()); - assert!(num <= cb_slice.len()); - assert!(num <= cr_slice.len()); - - let num_vecs = num / 8; - - for i in 0..num_vecs { - const SHIFT: u32 = 6; - // Load. - let y: v128; - let cb: v128; - let cr: v128; - // SAFETY: i is at most `num / 8 - 8`, so the highest v128_load64_zero reads from - // [num - 8, num). The above asserts ensure this is in-bounds. - unsafe { - y = v128_load64_zero(y_slice.as_ptr().wrapping_add(i * 8) as *const _); - cb = v128_load64_zero(cb_slice.as_ptr().wrapping_add(i * 8) as *const _); - cr = v128_load64_zero(cr_slice.as_ptr().wrapping_add(i * 8) as *const _); - } - - // Convert to 16 bit. - let y = i16x8_shl(i16x8_extend_low_u8x16(y), SHIFT); - let cb = i16x8_shl(i16x8_extend_low_u8x16(cb), SHIFT); - let cr = i16x8_shl(i16x8_extend_low_u8x16(cr), SHIFT); - - // Add offsets - let c128 = i16x8_splat(128 << SHIFT); - let y = i16x8_add_sat(y, i16x8_splat((1 << SHIFT) >> 1)); - let cb = i16x8_sub_sat(cb, c128); - let cr = i16x8_sub_sat(cr, c128); - - // Compute cr * 1.402, cb * 0.34414, cr * 0.71414, cb * 1.772 - let cr_140200 = i16x8_add_sat(i16x8_q15mulr_sat(cr, i16x8_splat(13173)), cr); - let cb_034414 = i16x8_q15mulr_sat(cb, i16x8_splat(11276)); - let cr_071414 = i16x8_q15mulr_sat(cr, i16x8_splat(23401)); - let cb_177200 = i16x8_add_sat(i16x8_q15mulr_sat(cb, i16x8_splat(25297)), cb); - - // Last conversion step. - let r = i16x8_add_sat(y, cr_140200); - let g = i16x8_sub_sat(y, i16x8_add_sat(cb_034414, cr_071414)); - let b = i16x8_add_sat(y, cb_177200); - - // Shift back and convert to u8. - let zero = u8x16_splat(0); - let r = u8x16_narrow_i16x8(i16x8_shr(r, SHIFT), zero); - let g = u8x16_narrow_i16x8(i16x8_shr(g, SHIFT), zero); - let b = u8x16_narrow_i16x8(i16x8_shr(b, SHIFT), zero); - - // Shuffle rrrrrrrrggggggggbbbbbbbb to rgbrgbrgb... - - let rg_lanes = i8x16_shuffle::<0, 16, - 1, 17, - 2, 18, - 3, 19, - 4, 20, - 5, 21, - 6, 22, - 7, 23>(r, g); - - let rgb_low = i8x16_shuffle::<0, 1, 16, // r0, g0, b0 - 2, 3, 17, // r1, g1, b1 - 4, 5, 18, // r2, g2, b2 - 6, 7, 19, // r3, g3, b3 - 8, 9, 20, // r4, g4, b4 - 10>(rg_lanes, b); // r5 - - let rgb_hi = i8x16_shuffle::<11, 21, 12, // g5, b5, r6 - 13, 22, 14, // g6, b6, r7 - 15, 23, 0, // g7, b7, -- - 0, 0, 0, // --, --, -- - 0, 0, 0, // --, --, -- - 0>(rg_lanes, b); // -- - - // SAFETY: i is at most `output.len() / 24 - 1` so the highest possible write is to - // `output.len() - 1`. - unsafe { - v128_store(output.as_mut_ptr().wrapping_add(24 * i) as *mut _, rgb_low); - v128_store64_lane::<0>(rgb_hi, output.as_mut_ptr().wrapping_add(24 * i + 16) as *mut _); - } - } - - num_vecs * 8 -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/decoder/lossless.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder/lossless.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/decoder/lossless.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder/lossless.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,260 +0,0 @@ -use crate::decoder::{Decoder, MAX_COMPONENTS}; -use crate::error::{Error, Result}; -use crate::huffman::HuffmanDecoder; -use crate::marker::Marker; -use crate::parser::Predictor; -use crate::parser::{Component, FrameInfo, ScanInfo}; -use std::io::Read; - -impl Decoder { - /// decode_scan_lossless - pub fn decode_scan_lossless( - &mut self, - frame: &FrameInfo, - scan: &ScanInfo, - ) -> Result<(Option, Vec>)> { - let ncomp = scan.component_indices.len(); - let npixel = frame.image_size.height as usize * frame.image_size.width as usize; - assert!(ncomp <= MAX_COMPONENTS); - let mut results = vec![vec![0u16; npixel]; ncomp]; - - let components: Vec = scan - .component_indices - .iter() - .map(|&i| frame.components[i].clone()) - .collect(); - - // Verify that all required huffman tables has been set. - if scan - .dc_table_indices - .iter() - .any(|&i| self.dc_huffman_tables[i].is_none()) - { - return Err(Error::Format( - "scan makes use of unset dc huffman table".to_owned(), - )); - } - - let mut huffman = HuffmanDecoder::new(); - let reader = &mut self.reader; - let mut mcus_left_until_restart = self.restart_interval; - let mut expected_rst_num = 0; - let mut ra = [0u16; MAX_COMPONENTS]; - let mut rb = [0u16; MAX_COMPONENTS]; - let mut rc = [0u16; MAX_COMPONENTS]; - - let width = frame.image_size.width as usize; - let height = frame.image_size.height as usize; - - let mut differences = vec![Vec::with_capacity(npixel); ncomp]; - for _mcu_y in 0..height { - for _mcu_x in 0..width { - if self.restart_interval > 0 { - if mcus_left_until_restart == 0 { - match huffman.take_marker(reader)? { - Some(Marker::RST(n)) => { - if n != expected_rst_num { - return Err(Error::Format(format!( - "found RST{} where RST{} was expected", - n, expected_rst_num - ))); - } - - huffman.reset(); - - expected_rst_num = (expected_rst_num + 1) % 8; - mcus_left_until_restart = self.restart_interval; - } - Some(marker) => { - return Err(Error::Format(format!( - "found marker {:?} inside scan where RST{} was expected", - marker, expected_rst_num - ))) - } - None => { - return Err(Error::Format(format!( - "no marker found where RST{} was expected", - expected_rst_num - ))) - } - } - } - - mcus_left_until_restart -= 1; - } - - for (i, _component) in components.iter().enumerate() { - let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]] - .as_ref() - .unwrap(); - let value = huffman.decode(reader, dc_table)?; - let diff = match value { - 0 => 0, - 1..=15 => huffman.receive_extend(reader, value)? as i32, - 16 => 32768, - _ => { - // Section F.1.2.1.1 - // Table F.1 - return Err(Error::Format( - "invalid DC difference magnitude category".to_owned(), - )); - } - }; - differences[i].push(diff); - } - } - } - - if scan.predictor_selection == Predictor::Ra { - for (i, _component) in components.iter().enumerate() { - // calculate the top left pixel - let diff = differences[i][0]; - let prediction = 1 << (frame.precision - scan.point_transform - 1) as i32; - let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 - let result = result << scan.point_transform; - results[i][0] = result; - - // calculate leftmost column, using top pixel as predictor - let mut previous = result; - for mcu_y in 1..height { - let diff = differences[i][mcu_y * width]; - let prediction = previous as i32; - let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 - let result = result << scan.point_transform; - results[i][mcu_y * width] = result; - previous = result; - } - - // calculate rows, using left pixel as predictor - for mcu_y in 0..height { - for mcu_x in 1..width { - let diff = differences[i][mcu_y * width + mcu_x]; - let prediction = results[i][mcu_y * width + mcu_x - 1] as i32; - let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 - let result = result << scan.point_transform; - results[i][mcu_y * width + mcu_x] = result; - } - } - } - } else { - for mcu_y in 0..height { - for mcu_x in 0..width { - for (i, _component) in components.iter().enumerate() { - let diff = differences[i][mcu_y * width + mcu_x]; - - // The following lines could be further optimized, e.g. moving the checks - // and updates of the previous values into the prediction function or - // iterating such that diagonals with mcu_x + mcu_y = const are computed at - // the same time to exploit independent predictions in this case - if mcu_x > 0 { - ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1]; - } - if mcu_y > 0 { - rb[i] = - results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x]; - if mcu_x > 0 { - rc[i] = results[i] - [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)]; - } - } - let prediction = predict( - ra[i] as i32, - rb[i] as i32, - rc[i] as i32, - scan.predictor_selection, - scan.point_transform, - frame.precision, - mcu_x, - mcu_y, - self.restart_interval > 0 - && mcus_left_until_restart == self.restart_interval - 1, - ); - let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 - results[i][mcu_y * width + mcu_x] = result << scan.point_transform; - } - } - } - } - - let mut marker = huffman.take_marker(&mut self.reader)?; - while let Some(Marker::RST(_)) = marker { - marker = self.read_marker().ok(); - } - Ok((marker, results)) - } -} - -/// H.1.2.1 -#[allow(clippy::too_many_arguments)] -fn predict( - ra: i32, - rb: i32, - rc: i32, - predictor: Predictor, - point_transform: u8, - input_precision: u8, - ix: usize, - iy: usize, - restart: bool, -) -> i32 { - if (ix == 0 && iy == 0) || restart { - // start of first line or restart - if input_precision > 1 + point_transform { - 1 << (input_precision - point_transform - 1) - } else { - 0 - } - } else if iy == 0 { - // rest of first line - ra - } else if ix == 0 { - // start of other line - rb - } else { - // use predictor Table H.1 - match predictor { - Predictor::NoPrediction => 0, - Predictor::Ra => ra, - Predictor::Rb => rb, - Predictor::Rc => rc, - Predictor::RaRbRc1 => ra + rb - rc, - Predictor::RaRbRc2 => ra + ((rb - rc) >> 1), - Predictor::RaRbRc3 => rb + ((ra - rc) >> 1), - Predictor::RaRb => (ra + rb) / 2, - } - } -} - -pub fn compute_image_lossless(frame: &FrameInfo, mut data: Vec>) -> Result> { - if data.is_empty() || data.iter().any(Vec::is_empty) { - return Err(Error::Format("not all components have data".to_owned())); - } - let output_size = frame.output_size; - let components = &frame.components; - let ncomp = components.len(); - - if ncomp == 1 { - let decoded = convert_to_u8(frame, data.remove(0)); - Ok(decoded) - } else { - let mut decoded: Vec = - vec![0u16; ncomp * output_size.width as usize * output_size.height as usize]; - for (x, chunk) in decoded.chunks_mut(ncomp).enumerate() { - for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() { - chunk[i] = component_data[x]; - } - } - let decoded = convert_to_u8(frame, decoded); - Ok(decoded) - } -} - -fn convert_to_u8(frame: &FrameInfo, data: Vec) -> Vec { - if frame.precision == 8 { - data.iter().map(|x| *x as u8).collect() - } else { - // we output native endian, which is the standard for image-rs - let ne_bytes: Vec<_> = data.iter().map(|x| x.to_ne_bytes()).collect(); - ne_bytes.concat() - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1508 +0,0 @@ -use crate::error::{Error, Result, UnsupportedFeature}; -use crate::huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable}; -use crate::marker::Marker; -use crate::parser::{ - parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos, - AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo, - IccChunk, ScanInfo, -}; -use crate::read_u8; -use crate::upsampler::Upsampler; -use crate::worker::{compute_image_parallel, PreferWorkerKind, RowData, Worker, WorkerScope}; -use alloc::borrow::ToOwned; -use alloc::sync::Arc; -use alloc::vec::Vec; -use alloc::{format, vec}; -use core::cmp; -use core::mem; -use core::ops::Range; -use std::io::Read; - -pub const MAX_COMPONENTS: usize = 4; - -mod lossless; -use self::lossless::compute_image_lossless; - -#[rustfmt::skip] -static UNZIGZAG: [u8; 64] = [ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, -]; - -/// An enumeration over combinations of color spaces and bit depths a pixel can have. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum PixelFormat { - /// Luminance (grayscale), 8 bits - L8, - /// Luminance (grayscale), 16 bits - L16, - /// RGB, 8 bits per channel - RGB24, - /// CMYK, 8 bits per channel - CMYK32, -} - -impl PixelFormat { - /// Determine the size in bytes of each pixel in this format - pub fn pixel_bytes(&self) -> usize { - match self { - PixelFormat::L8 => 1, - PixelFormat::L16 => 2, - PixelFormat::RGB24 => 3, - PixelFormat::CMYK32 => 4, - } - } -} - -/// Represents metadata of an image. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct ImageInfo { - /// The width of the image, in pixels. - pub width: u16, - /// The height of the image, in pixels. - pub height: u16, - /// The pixel format of the image. - pub pixel_format: PixelFormat, - /// The coding process of the image. - pub coding_process: CodingProcess, -} - -/// Describes the colour transform to apply before binary data is returned -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ColorTransform { - /// No transform should be applied and the data is returned as-is. - None, - /// Unknown colour transformation - Unknown, - /// Grayscale transform should be applied (expects 1 channel) - Grayscale, - /// RGB transform should be applied. - RGB, - /// YCbCr transform should be applied. - YCbCr, - /// CMYK transform should be applied. - CMYK, - /// YCCK transform should be applied. - YCCK, - /// big gamut Y/Cb/Cr, bg-sYCC - JcsBgYcc, - /// big gamut red/green/blue, bg-sRGB - JcsBgRgb, -} - -/// JPEG decoder -pub struct Decoder { - reader: R, - - frame: Option, - dc_huffman_tables: Vec>, - ac_huffman_tables: Vec>, - quantization_tables: [Option>; 4], - - restart_interval: u16, - - adobe_color_transform: Option, - color_transform: Option, - - is_jfif: bool, - is_mjpeg: bool, - - icc_markers: Vec, - - exif_data: Option>, - xmp_data: Option>, - psir_data: Option>, - - // Used for progressive JPEGs. - coefficients: Vec>, - // Bitmask of which coefficients has been completely decoded. - coefficients_finished: [u64; MAX_COMPONENTS], - - // Maximum allowed size of decoded image buffer - decoding_buffer_size_limit: usize, -} - -impl Decoder { - /// Creates a new `Decoder` using the reader `reader`. - pub fn new(reader: R) -> Decoder { - Decoder { - reader, - frame: None, - dc_huffman_tables: vec![None, None, None, None], - ac_huffman_tables: vec![None, None, None, None], - quantization_tables: [None, None, None, None], - restart_interval: 0, - adobe_color_transform: None, - color_transform: None, - is_jfif: false, - is_mjpeg: false, - icc_markers: Vec::new(), - exif_data: None, - xmp_data: None, - psir_data: None, - coefficients: Vec::new(), - coefficients_finished: [0; MAX_COMPONENTS], - decoding_buffer_size_limit: usize::MAX, - } - } - - /// Colour transform to use when decoding the image. App segments relating to colour transforms - /// will be ignored. - pub fn set_color_transform(&mut self, transform: ColorTransform) { - self.color_transform = Some(transform); - } - - /// Set maximum buffer size allowed for decoded images - pub fn set_max_decoding_buffer_size(&mut self, max: usize) { - self.decoding_buffer_size_limit = max; - } - - /// Returns metadata about the image. - /// - /// The returned value will be `None` until a call to either `read_info` or `decode` has - /// returned `Ok`. - pub fn info(&self) -> Option { - match self.frame { - Some(ref frame) => { - let pixel_format = match frame.components.len() { - 1 => match frame.precision { - 2..=8 => PixelFormat::L8, - 9..=16 => PixelFormat::L16, - _ => panic!(), - }, - 3 => PixelFormat::RGB24, - 4 => PixelFormat::CMYK32, - _ => panic!(), - }; - - Some(ImageInfo { - width: frame.output_size.width, - height: frame.output_size.height, - pixel_format, - coding_process: frame.coding_process, - }) - } - None => None, - } - } - - /// Returns raw exif data, starting at the TIFF header, if the image contains any. - /// - /// The returned value will be `None` until a call to `decode` has returned `Ok`. - pub fn exif_data(&self) -> Option<&[u8]> { - self.exif_data.as_deref() - } - - /// Returns the raw XMP packet if there is any. - /// - /// The returned value will be `None` until a call to `decode` has returned `Ok`. - pub fn xmp_data(&self) -> Option<&[u8]> { - self.xmp_data.as_deref() - } - - /// Returns the embeded icc profile if the image contains one. - pub fn icc_profile(&self) -> Option> { - let mut marker_present: [Option<&IccChunk>; 256] = [None; 256]; - let num_markers = self.icc_markers.len(); - if num_markers == 0 || num_markers >= 255 { - return None; - } - // check the validity of the markers - for chunk in &self.icc_markers { - if usize::from(chunk.num_markers) != num_markers { - // all the lengths must match - return None; - } - if chunk.seq_no == 0 { - return None; - } - if marker_present[usize::from(chunk.seq_no)].is_some() { - // duplicate seq_no - return None; - } else { - marker_present[usize::from(chunk.seq_no)] = Some(chunk); - } - } - - // assemble them together by seq_no failing if any are missing - let mut data = Vec::new(); - // seq_no's start at 1 - for &chunk in marker_present.get(1..=num_markers)? { - data.extend_from_slice(&chunk?.data); - } - Some(data) - } - - /// Heuristic to avoid starting thread, synchronization if we expect a small amount of - /// parallelism to be utilized. - fn select_worker(frame: &FrameInfo, worker_preference: PreferWorkerKind) -> PreferWorkerKind { - const PARALLELISM_THRESHOLD: u64 = 128 * 128; - - match worker_preference { - PreferWorkerKind::Immediate => PreferWorkerKind::Immediate, - PreferWorkerKind::Multithreaded => { - let width: u64 = frame.output_size.width.into(); - let height: u64 = frame.output_size.width.into(); - if width * height > PARALLELISM_THRESHOLD { - PreferWorkerKind::Multithreaded - } else { - PreferWorkerKind::Immediate - } - } - } - } - - /// Tries to read metadata from the image without decoding it. - /// - /// If successful, the metadata can be obtained using the `info` method. - pub fn read_info(&mut self) -> Result<()> { - WorkerScope::with(|worker| self.decode_internal(true, worker)).map(|_| ()) - } - - /// Configure the decoder to scale the image during decoding. - /// - /// This efficiently scales the image by the smallest supported scale - /// factor that produces an image larger than or equal to the requested - /// size in at least one axis. The currently implemented scale factors - /// are 1/8, 1/4, 1/2 and 1. - /// - /// To generate a thumbnail of an exact size, pass the desired size and - /// then scale to the final size using a traditional resampling algorithm. - pub fn scale(&mut self, requested_width: u16, requested_height: u16) -> Result<(u16, u16)> { - self.read_info()?; - let frame = self.frame.as_mut().unwrap(); - let idct_size = crate::idct::choose_idct_size( - frame.image_size, - Dimensions { - width: requested_width, - height: requested_height, - }, - ); - frame.update_idct_size(idct_size)?; - Ok((frame.output_size.width, frame.output_size.height)) - } - - /// Decodes the image and returns the decoded pixels if successful. - pub fn decode(&mut self) -> Result> { - WorkerScope::with(|worker| self.decode_internal(false, worker)) - } - - fn decode_internal( - &mut self, - stop_after_metadata: bool, - worker_scope: &WorkerScope, - ) -> Result> { - if stop_after_metadata && self.frame.is_some() { - // The metadata has already been read. - return Ok(Vec::new()); - } else if self.frame.is_none() - && (read_u8(&mut self.reader)? != 0xFF - || Marker::from_u8(read_u8(&mut self.reader)?) != Some(Marker::SOI)) - { - return Err(Error::Format( - "first two bytes are not an SOI marker".to_owned(), - )); - } - - let mut previous_marker = Marker::SOI; - let mut pending_marker = None; - let mut scans_processed = 0; - let mut planes = vec![ - Vec::::new(); - self.frame - .as_ref() - .map_or(0, |frame| frame.components.len()) - ]; - let mut planes_u16 = vec![ - Vec::::new(); - self.frame - .as_ref() - .map_or(0, |frame| frame.components.len()) - ]; - - loop { - let marker = match pending_marker.take() { - Some(m) => m, - None => self.read_marker()?, - }; - - match marker { - // Frame header - Marker::SOF(..) => { - // Section 4.10 - // "An image contains only one frame in the cases of sequential and - // progressive coding processes; an image contains multiple frames for the - // hierarchical mode." - if self.frame.is_some() { - return Err(Error::Unsupported(UnsupportedFeature::Hierarchical)); - } - - let frame = parse_sof(&mut self.reader, marker)?; - let component_count = frame.components.len(); - - if frame.is_differential { - return Err(Error::Unsupported(UnsupportedFeature::Hierarchical)); - } - if frame.entropy_coding == EntropyCoding::Arithmetic { - return Err(Error::Unsupported( - UnsupportedFeature::ArithmeticEntropyCoding, - )); - } - if frame.precision != 8 && frame.coding_process != CodingProcess::Lossless { - return Err(Error::Unsupported(UnsupportedFeature::SamplePrecision( - frame.precision, - ))); - } - if !(2..=16).contains(&frame.precision) { - return Err(Error::Unsupported(UnsupportedFeature::SamplePrecision( - frame.precision, - ))); - } - if component_count != 1 && component_count != 3 && component_count != 4 { - return Err(Error::Unsupported(UnsupportedFeature::ComponentCount( - component_count as u8, - ))); - } - - // Make sure we support the subsampling ratios used. - let _ = Upsampler::new( - &frame.components, - frame.image_size.width, - frame.image_size.height, - )?; - - self.frame = Some(frame); - - if stop_after_metadata { - return Ok(Vec::new()); - } - - planes = vec![Vec::new(); component_count]; - planes_u16 = vec![Vec::new(); component_count]; - } - - // Scan header - Marker::SOS => { - if self.frame.is_none() { - return Err(Error::Format("scan encountered before frame".to_owned())); - } - - let frame = self.frame.clone().unwrap(); - let scan = parse_sos(&mut self.reader, &frame)?; - - if frame.coding_process == CodingProcess::DctProgressive - && self.coefficients.is_empty() - { - self.coefficients = frame - .components - .iter() - .map(|c| { - let block_count = - c.block_size.width as usize * c.block_size.height as usize; - vec![0; block_count * 64] - }) - .collect(); - } - - if frame.coding_process == CodingProcess::Lossless { - let (marker, data) = self.decode_scan_lossless(&frame, &scan)?; - - for (i, plane) in data - .into_iter() - .enumerate() - .filter(|(_, plane)| !plane.is_empty()) - { - planes_u16[i] = plane; - } - pending_marker = marker; - } else { - // This was previously buggy, so let's explain the log here a bit. When a - // progressive frame is encoded then the coefficients (DC, AC) of each - // component (=color plane) can be split amongst scans. In particular it can - // happen or at least occurs in the wild that a scan contains coefficient 0 of - // all components. If now one but not all components had all other coefficients - // delivered in previous scans then such a scan contains all components but - // completes only some of them! (This is technically NOT permitted for all - // other coefficients as the standard dictates that scans with coefficients - // other than the 0th must only contain ONE component so we would either - // complete it or not. We may want to detect and error in case more component - // are part of a scan than allowed.) What a weird edge case. - // - // But this means we track precisely which components get completed here. - let mut finished = [false; MAX_COMPONENTS]; - - if scan.successive_approximation_low == 0 { - for (&i, component_finished) in - scan.component_indices.iter().zip(&mut finished) - { - if self.coefficients_finished[i] == !0 { - continue; - } - for j in scan.spectral_selection.clone() { - self.coefficients_finished[i] |= 1 << j; - } - if self.coefficients_finished[i] == !0 { - *component_finished = true; - } - } - } - - let preference = - Self::select_worker(&frame, PreferWorkerKind::Multithreaded); - - let (marker, data) = worker_scope - .get_or_init_worker(preference, |worker| { - self.decode_scan(&frame, &scan, worker, &finished) - })?; - - if let Some(data) = data { - for (i, plane) in data - .into_iter() - .enumerate() - .filter(|(_, plane)| !plane.is_empty()) - { - if self.coefficients_finished[i] == !0 { - planes[i] = plane; - } - } - } - - pending_marker = marker; - } - - scans_processed += 1; - } - - // Table-specification and miscellaneous markers - // Quantization table-specification - Marker::DQT => { - let tables = parse_dqt(&mut self.reader)?; - - for (i, &table) in tables.iter().enumerate() { - if let Some(table) = table { - let mut unzigzagged_table = [0u16; 64]; - - for j in 0..64 { - unzigzagged_table[UNZIGZAG[j] as usize] = table[j]; - } - - self.quantization_tables[i] = Some(Arc::new(unzigzagged_table)); - } - } - } - // Huffman table-specification - Marker::DHT => { - let is_baseline = self.frame.as_ref().map(|frame| frame.is_baseline); - let (dc_tables, ac_tables) = parse_dht(&mut self.reader, is_baseline)?; - - let current_dc_tables = mem::take(&mut self.dc_huffman_tables); - self.dc_huffman_tables = dc_tables - .into_iter() - .zip(current_dc_tables) - .map(|(a, b)| a.or(b)) - .collect(); - - let current_ac_tables = mem::take(&mut self.ac_huffman_tables); - self.ac_huffman_tables = ac_tables - .into_iter() - .zip(current_ac_tables) - .map(|(a, b)| a.or(b)) - .collect(); - } - // Arithmetic conditioning table-specification - Marker::DAC => { - return Err(Error::Unsupported( - UnsupportedFeature::ArithmeticEntropyCoding, - )) - } - // Restart interval definition - Marker::DRI => self.restart_interval = parse_dri(&mut self.reader)?, - // Comment - Marker::COM => { - let _comment = parse_com(&mut self.reader)?; - } - // Application data - Marker::APP(..) => { - if let Some(data) = parse_app(&mut self.reader, marker)? { - match data { - AppData::Adobe(color_transform) => { - self.adobe_color_transform = Some(color_transform) - } - AppData::Jfif => { - // From the JFIF spec: - // "The APP0 marker is used to identify a JPEG FIF file. - // The JPEG FIF APP0 marker is mandatory right after the SOI marker." - // Some JPEGs in the wild does not follow this though, so we allow - // JFIF headers anywhere APP0 markers are allowed. - /* - if previous_marker != Marker::SOI { - return Err(Error::Format("the JFIF APP0 marker must come right after the SOI marker".to_owned())); - } - */ - - self.is_jfif = true; - } - AppData::Avi1 => self.is_mjpeg = true, - AppData::Icc(icc) => self.icc_markers.push(icc), - AppData::Exif(data) => self.exif_data = Some(data), - AppData::Xmp(data) => self.xmp_data = Some(data), - AppData::Psir(data) => self.psir_data = Some(data), - } - } - } - // Restart - Marker::RST(..) => { - // Some encoders emit a final RST marker after entropy-coded data, which - // decode_scan does not take care of. So if we encounter one, we ignore it. - if previous_marker != Marker::SOS { - return Err(Error::Format( - "RST found outside of entropy-coded data".to_owned(), - )); - } - } - - // Define number of lines - Marker::DNL => { - // Section B.2.1 - // "If a DNL segment (see B.2.5) is present, it shall immediately follow the first scan." - if previous_marker != Marker::SOS || scans_processed != 1 { - return Err(Error::Format( - "DNL is only allowed immediately after the first scan".to_owned(), - )); - } - - return Err(Error::Unsupported(UnsupportedFeature::DNL)); - } - - // Hierarchical mode markers - Marker::DHP | Marker::EXP => { - return Err(Error::Unsupported(UnsupportedFeature::Hierarchical)) - } - - // End of image - Marker::EOI => break, - - _ => { - return Err(Error::Format(format!( - "{:?} marker found where not allowed", - marker - ))) - } - } - - previous_marker = marker; - } - - if self.frame.is_none() { - return Err(Error::Format( - "end of image encountered before frame".to_owned(), - )); - } - - let frame = self.frame.as_ref().unwrap(); - let preference = Self::select_worker(frame, PreferWorkerKind::Multithreaded); - - worker_scope.get_or_init_worker(preference, |worker| { - self.decode_planes(worker, planes, planes_u16) - }) - } - - fn decode_planes( - &mut self, - worker: &mut dyn Worker, - mut planes: Vec>, - planes_u16: Vec>, - ) -> Result> { - if self.frame.is_none() { - return Err(Error::Format( - "end of image encountered before frame".to_owned(), - )); - } - - let frame = self.frame.as_ref().unwrap(); - - if frame - .components - .len() - .checked_mul(frame.output_size.width.into()) - .and_then(|m| m.checked_mul(frame.output_size.height.into())) - .map_or(true, |m| self.decoding_buffer_size_limit < m) - { - return Err(Error::Format( - "size of decoded image exceeds maximum allowed size".to_owned(), - )); - } - - // If we're decoding a progressive jpeg and a component is unfinished, render what we've got - if frame.coding_process == CodingProcess::DctProgressive - && self.coefficients.len() == frame.components.len() - { - for (i, component) in frame.components.iter().enumerate() { - // Only dealing with unfinished components - if self.coefficients_finished[i] == !0 { - continue; - } - - let quantization_table = - match self.quantization_tables[component.quantization_table_index].clone() { - Some(quantization_table) => quantization_table, - None => continue, - }; - - // Get the worker prepared - let row_data = RowData { - index: i, - component: component.clone(), - quantization_table, - }; - worker.start(row_data)?; - - // Send the rows over to the worker and collect the result - let coefficients_per_mcu_row = usize::from(component.block_size.width) - * usize::from(component.vertical_sampling_factor) - * 64; - - let mut tasks = (0..frame.mcu_size.height).map(|mcu_y| { - let offset = usize::from(mcu_y) * coefficients_per_mcu_row; - let row_coefficients = - self.coefficients[i][offset..offset + coefficients_per_mcu_row].to_vec(); - (i, row_coefficients) - }); - - // FIXME: additional potential work stealing opportunities for rayon case if we - // also internally can parallelize over components. - worker.append_rows(&mut tasks)?; - planes[i] = worker.get_result(i)?; - } - } - - if frame.coding_process == CodingProcess::Lossless { - compute_image_lossless(frame, planes_u16) - } else { - compute_image( - &frame.components, - planes, - frame.output_size, - self.determine_color_transform(), - ) - } - } - - fn determine_color_transform(&self) -> ColorTransform { - if let Some(color_transform) = self.color_transform { - return color_transform; - } - - let frame = self.frame.as_ref().unwrap(); - - if frame.components.len() == 1 { - return ColorTransform::Grayscale; - } - - // Using logic for determining colour as described here: https://entropymine.wordpress.com/2018/10/22/how-is-a-jpeg-images-color-type-determined/ - - if frame.components.len() == 3 { - match ( - frame.components[0].identifier, - frame.components[1].identifier, - frame.components[2].identifier, - ) { - (1, 2, 3) => { - return ColorTransform::YCbCr; - } - (1, 34, 35) => { - return ColorTransform::JcsBgYcc; - } - (82, 71, 66) => { - return ColorTransform::RGB; - } - (114, 103, 98) => { - return ColorTransform::JcsBgRgb; - } - _ => {} - } - - if self.is_jfif { - return ColorTransform::YCbCr; - } - } - - if let Some(colour_transform) = self.adobe_color_transform { - match colour_transform { - AdobeColorTransform::Unknown => { - if frame.components.len() == 3 { - return ColorTransform::RGB; - } else if frame.components.len() == 4 { - return ColorTransform::CMYK; - } - } - AdobeColorTransform::YCbCr => { - return ColorTransform::YCbCr; - } - AdobeColorTransform::YCCK => { - return ColorTransform::YCCK; - } - } - } else if frame.components.len() == 4 { - return ColorTransform::CMYK; - } - - if frame.components.len() == 4 { - ColorTransform::YCCK - } else if frame.components.len() == 3 { - ColorTransform::YCbCr - } else { - ColorTransform::Unknown - } - } - - fn read_marker(&mut self) -> Result { - loop { - // This should be an error as the JPEG spec doesn't allow extraneous data between marker segments. - // libjpeg allows this though and there are images in the wild utilising it, so we are - // forced to support this behavior. - // Sony Ericsson P990i is an example of a device which produce this sort of JPEGs. - while read_u8(&mut self.reader)? != 0xFF {} - - // Section B.1.1.2 - // All markers are assigned two-byte codes: an X’FF’ byte followed by a - // byte which is not equal to 0 or X’FF’ (see Table B.1). Any marker may - // optionally be preceded by any number of fill bytes, which are bytes - // assigned code X’FF’. - let mut byte = read_u8(&mut self.reader)?; - - // Section B.1.1.2 - // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code X’FF’." - while byte == 0xFF { - byte = read_u8(&mut self.reader)?; - } - - if byte != 0x00 && byte != 0xFF { - return Ok(Marker::from_u8(byte).unwrap()); - } - } - } - -#[allow(clippy::type_complexity)] - fn decode_scan( - &mut self, - frame: &FrameInfo, - scan: &ScanInfo, - worker: &mut dyn Worker, - finished: &[bool; MAX_COMPONENTS], - ) -> Result<(Option, Option>>)> { - assert!(scan.component_indices.len() <= MAX_COMPONENTS); - - let components: Vec = scan - .component_indices - .iter() - .map(|&i| frame.components[i].clone()) - .collect(); - - // Verify that all required quantization tables has been set. - if components - .iter() - .any(|component| self.quantization_tables[component.quantization_table_index].is_none()) - { - return Err(Error::Format("use of unset quantization table".to_owned())); - } - - if self.is_mjpeg { - fill_default_mjpeg_tables( - scan, - &mut self.dc_huffman_tables, - &mut self.ac_huffman_tables, - ); - } - - // Verify that all required huffman tables has been set. - if scan.spectral_selection.start == 0 - && scan - .dc_table_indices - .iter() - .any(|&i| self.dc_huffman_tables[i].is_none()) - { - return Err(Error::Format( - "scan makes use of unset dc huffman table".to_owned(), - )); - } - if scan.spectral_selection.end > 1 - && scan - .ac_table_indices - .iter() - .any(|&i| self.ac_huffman_tables[i].is_none()) - { - return Err(Error::Format( - "scan makes use of unset ac huffman table".to_owned(), - )); - } - - // Prepare the worker thread for the work to come. - for (i, component) in components.iter().enumerate() { - if finished[i] { - let row_data = RowData { - index: i, - component: component.clone(), - quantization_table: self.quantization_tables - [component.quantization_table_index] - .clone() - .unwrap(), - }; - - worker.start(row_data)?; - } - } - - let is_progressive = frame.coding_process == CodingProcess::DctProgressive; - let is_interleaved = components.len() > 1; - let mut dummy_block = [0i16; 64]; - let mut huffman = HuffmanDecoder::new(); - let mut dc_predictors = [0i16; MAX_COMPONENTS]; - let mut mcus_left_until_restart = self.restart_interval; - let mut expected_rst_num = 0; - let mut eob_run = 0; - let mut mcu_row_coefficients = vec![vec![]; components.len()]; - - if !is_progressive { - for (i, component) in components.iter().enumerate().filter(|&(i, _)| finished[i]) { - let coefficients_per_mcu_row = component.block_size.width as usize - * component.vertical_sampling_factor as usize - * 64; - mcu_row_coefficients[i] = vec![0i16; coefficients_per_mcu_row]; - } - } - - // 4.8.2 - // When reading from the stream, if the data is non-interleaved then an MCU consists of - // exactly one block (effectively a 1x1 sample). - let (mcu_horizontal_samples, mcu_vertical_samples) = if is_interleaved { - let horizontal = components - .iter() - .map(|component| component.horizontal_sampling_factor as u16) - .collect::>(); - let vertical = components - .iter() - .map(|component| component.vertical_sampling_factor as u16) - .collect::>(); - (horizontal, vertical) - } else { - (vec![1], vec![1]) - }; - - // This also affects how many MCU values we read from stream. If it's a non-interleaved stream, - // the MCUs will be exactly the block count. - let (max_mcu_x, max_mcu_y) = if is_interleaved { - (frame.mcu_size.width, frame.mcu_size.height) - } else { - ( - components[0].block_size.width, - components[0].block_size.height, - ) - }; - - for mcu_y in 0..max_mcu_y { - if mcu_y * 8 >= frame.image_size.height { - break; - } - - for mcu_x in 0..max_mcu_x { - if mcu_x * 8 >= frame.image_size.width { - break; - } - - if self.restart_interval > 0 { - if mcus_left_until_restart == 0 { - match huffman.take_marker(&mut self.reader)? { - Some(Marker::RST(n)) => { - if n != expected_rst_num { - return Err(Error::Format(format!( - "found RST{} where RST{} was expected", - n, expected_rst_num - ))); - } - - huffman.reset(); - // Section F.2.1.3.1 - dc_predictors = [0i16; MAX_COMPONENTS]; - // Section G.1.2.2 - eob_run = 0; - - expected_rst_num = (expected_rst_num + 1) % 8; - mcus_left_until_restart = self.restart_interval; - } - Some(marker) => { - return Err(Error::Format(format!( - "found marker {:?} inside scan where RST{} was expected", - marker, expected_rst_num - ))) - } - None => { - return Err(Error::Format(format!( - "no marker found where RST{} was expected", - expected_rst_num - ))) - } - } - } - - mcus_left_until_restart -= 1; - } - - for (i, component) in components.iter().enumerate() { - for v_pos in 0..mcu_vertical_samples[i] { - for h_pos in 0..mcu_horizontal_samples[i] { - let coefficients = if is_progressive { - let block_y = (mcu_y * mcu_vertical_samples[i] + v_pos) as usize; - let block_x = (mcu_x * mcu_horizontal_samples[i] + h_pos) as usize; - let block_offset = - (block_y * component.block_size.width as usize + block_x) * 64; - &mut self.coefficients[scan.component_indices[i]] - [block_offset..block_offset + 64] - } else if finished[i] { - // Because the worker thread operates in batches as if we were always interleaved, we - // need to distinguish between a single-shot buffer and one that's currently in process - // (for a non-interleaved) stream - let mcu_batch_current_row = if is_interleaved { - 0 - } else { - mcu_y % component.vertical_sampling_factor as u16 - }; - - let block_y = (mcu_batch_current_row * mcu_vertical_samples[i] - + v_pos) as usize; - let block_x = (mcu_x * mcu_horizontal_samples[i] + h_pos) as usize; - let block_offset = - (block_y * component.block_size.width as usize + block_x) * 64; - &mut mcu_row_coefficients[i][block_offset..block_offset + 64] - } else { - &mut dummy_block[..64] - } - .try_into() - .unwrap(); - - if scan.successive_approximation_high == 0 { - decode_block( - &mut self.reader, - coefficients, - &mut huffman, - self.dc_huffman_tables[scan.dc_table_indices[i]].as_ref(), - self.ac_huffman_tables[scan.ac_table_indices[i]].as_ref(), - scan.spectral_selection.clone(), - scan.successive_approximation_low, - &mut eob_run, - &mut dc_predictors[i], - )?; - } else { - decode_block_successive_approximation( - &mut self.reader, - coefficients, - &mut huffman, - self.ac_huffman_tables[scan.ac_table_indices[i]].as_ref(), - scan.spectral_selection.clone(), - scan.successive_approximation_low, - &mut eob_run, - )?; - } - } - } - } - } - - // Send the coefficients from this MCU row to the worker thread for dequantization and idct. - for (i, component) in components.iter().enumerate() { - if finished[i] { - // In the event of non-interleaved streams, if we're still building the buffer out, - // keep going; don't send it yet. We also need to ensure we don't skip over the last - // row(s) of the image. - if !is_interleaved - && (mcu_y + 1) * 8 < frame.image_size.height - && (mcu_y + 1) % component.vertical_sampling_factor as u16 > 0 - { - continue; - } - - let coefficients_per_mcu_row = component.block_size.width as usize - * component.vertical_sampling_factor as usize - * 64; - - let row_coefficients = if is_progressive { - // Because non-interleaved streams will have multiple MCU rows concatenated together, - // the row for calculating the offset is different. - let worker_mcu_y = if is_interleaved { - mcu_y - } else { - // Explicitly doing floor-division here - mcu_y / component.vertical_sampling_factor as u16 - }; - - let offset = worker_mcu_y as usize * coefficients_per_mcu_row; - self.coefficients[scan.component_indices[i]] - [offset..offset + coefficients_per_mcu_row] - .to_vec() - } else { - mem::replace( - &mut mcu_row_coefficients[i], - vec![0i16; coefficients_per_mcu_row], - ) - }; - - // FIXME: additional potential work stealing opportunities for rayon case if we - // also internally can parallelize over components. - worker.append_row((i, row_coefficients))?; - } - } - } - - let mut marker = huffman.take_marker(&mut self.reader)?; - while let Some(Marker::RST(_)) = marker { - marker = self.read_marker().ok(); - } - - if finished.iter().any(|&c| c) { - // Retrieve all the data from the worker thread. - let mut data = vec![Vec::new(); frame.components.len()]; - - for (i, &component_index) in scan.component_indices.iter().enumerate() { - if finished[i] { - data[component_index] = worker.get_result(i)?; - } - } - - Ok((marker, Some(data))) - } else { - Ok((marker, None)) - } - } -} - -#[allow(clippy::too_many_arguments)] -fn decode_block( - reader: &mut R, - coefficients: &mut [i16; 64], - huffman: &mut HuffmanDecoder, - dc_table: Option<&HuffmanTable>, - ac_table: Option<&HuffmanTable>, - spectral_selection: Range, - successive_approximation_low: u8, - eob_run: &mut u16, - dc_predictor: &mut i16, -) -> Result<()> { - debug_assert_eq!(coefficients.len(), 64); - - if spectral_selection.start == 0 { - // Section F.2.2.1 - // Figure F.12 - let value = huffman.decode(reader, dc_table.unwrap())?; - let diff = match value { - 0 => 0, - 1..=11 => huffman.receive_extend(reader, value)?, - _ => { - // Section F.1.2.1.1 - // Table F.1 - return Err(Error::Format( - "invalid DC difference magnitude category".to_owned(), - )); - } - }; - - // Malicious JPEG files can cause this add to overflow, therefore we use wrapping_add. - // One example of such a file is tests/crashtest/images/dc-predictor-overflow.jpg - *dc_predictor = dc_predictor.wrapping_add(diff); - coefficients[0] = *dc_predictor << successive_approximation_low; - } - - let mut index = cmp::max(spectral_selection.start, 1); - - if index < spectral_selection.end && *eob_run > 0 { - *eob_run -= 1; - return Ok(()); - } - - // Section F.1.2.2.1 - while index < spectral_selection.end { - if let Some((value, run)) = huffman.decode_fast_ac(reader, ac_table.unwrap())? { - index += run; - - if index >= spectral_selection.end { - break; - } - - coefficients[UNZIGZAG[index as usize] as usize] = value << successive_approximation_low; - index += 1; - } else { - let byte = huffman.decode(reader, ac_table.unwrap())?; - let r = byte >> 4; - let s = byte & 0x0f; - - if s == 0 { - match r { - 15 => index += 16, // Run length of 16 zero coefficients. - _ => { - *eob_run = (1 << r) - 1; - - if r > 0 { - *eob_run += huffman.get_bits(reader, r)?; - } - - break; - } - } - } else { - index += r; - - if index >= spectral_selection.end { - break; - } - - coefficients[UNZIGZAG[index as usize] as usize] = - huffman.receive_extend(reader, s)? << successive_approximation_low; - index += 1; - } - } - } - - Ok(()) -} - -fn decode_block_successive_approximation( - reader: &mut R, - coefficients: &mut [i16; 64], - huffman: &mut HuffmanDecoder, - ac_table: Option<&HuffmanTable>, - spectral_selection: Range, - successive_approximation_low: u8, - eob_run: &mut u16, -) -> Result<()> { - debug_assert_eq!(coefficients.len(), 64); - - let bit = 1 << successive_approximation_low; - - if spectral_selection.start == 0 { - // Section G.1.2.1 - - if huffman.get_bits(reader, 1)? == 1 { - coefficients[0] |= bit; - } - } else { - // Section G.1.2.3 - - if *eob_run > 0 { - *eob_run -= 1; - refine_non_zeroes(reader, coefficients, huffman, spectral_selection, 64, bit)?; - return Ok(()); - } - - let mut index = spectral_selection.start; - - while index < spectral_selection.end { - let byte = huffman.decode(reader, ac_table.unwrap())?; - let r = byte >> 4; - let s = byte & 0x0f; - - let mut zero_run_length = r; - let mut value = 0; - - match s { - 0 => { - match r { - 15 => { - // Run length of 16 zero coefficients. - // We don't need to do anything special here, zero_run_length is 15 - // and then value (which is zero) gets written, resulting in 16 - // zero coefficients. - } - _ => { - *eob_run = (1 << r) - 1; - - if r > 0 { - *eob_run += huffman.get_bits(reader, r)?; - } - - // Force end of block. - zero_run_length = 64; - } - } - } - 1 => { - if huffman.get_bits(reader, 1)? == 1 { - value = bit; - } else { - value = -bit; - } - } - _ => return Err(Error::Format("unexpected huffman code".to_owned())), - } - - let range = Range { - start: index, - end: spectral_selection.end, - }; - index = refine_non_zeroes(reader, coefficients, huffman, range, zero_run_length, bit)?; - - if value != 0 { - coefficients[UNZIGZAG[index as usize] as usize] = value; - } - - index += 1; - } - } - - Ok(()) -} - -fn refine_non_zeroes( - reader: &mut R, - coefficients: &mut [i16; 64], - huffman: &mut HuffmanDecoder, - range: Range, - zrl: u8, - bit: i16, -) -> Result { - debug_assert_eq!(coefficients.len(), 64); - - let last = range.end - 1; - let mut zero_run_length = zrl; - - for i in range { - let index = UNZIGZAG[i as usize] as usize; - - let coefficient = &mut coefficients[index]; - - if *coefficient == 0 { - if zero_run_length == 0 { - return Ok(i); - } - - zero_run_length -= 1; - } else if huffman.get_bits(reader, 1)? == 1 && *coefficient & bit == 0 { - if *coefficient > 0 { - *coefficient = coefficient - .checked_add(bit) - .ok_or_else(|| Error::Format("Coefficient overflow".to_owned()))?; - } else { - *coefficient = coefficient - .checked_sub(bit) - .ok_or_else(|| Error::Format("Coefficient overflow".to_owned()))?; - } - } - } - - Ok(last) -} - -fn compute_image( - components: &[Component], - mut data: Vec>, - output_size: Dimensions, - color_transform: ColorTransform, -) -> Result> { - if data.is_empty() || data.iter().any(Vec::is_empty) { - return Err(Error::Format("not all components have data".to_owned())); - } - - if components.len() == 1 { - let component = &components[0]; - let mut decoded: Vec = data.remove(0); - - let width = component.size.width as usize; - let height = component.size.height as usize; - let size = width * height; - let line_stride = component.block_size.width as usize * component.dct_scale; - - // if the image width is a multiple of the block size, - // then we don't have to move bytes in the decoded data - if usize::from(output_size.width) != line_stride { - // The first line already starts at index 0, so we need to move only lines 1..height - // We move from the top down because all lines are being moved backwards. - for y in 1..height { - let destination_idx = y * width; - let source_idx = y * line_stride; - let end = source_idx + width; - decoded.copy_within(source_idx..end, destination_idx); - } - } - decoded.resize(size, 0); - Ok(decoded) - } else { - compute_image_parallel(components, data, output_size, color_transform) - } -} - -#[allow(clippy::type_complexity)] -pub(crate) fn choose_color_convert_func( - component_count: usize, - color_transform: ColorTransform, -) -> Result], &mut [u8])> { - match component_count { - 3 => match color_transform { - ColorTransform::None => Ok(color_no_convert), - ColorTransform::Grayscale => Err(Error::Format( - "Invalid number of channels (3) for Grayscale data".to_string(), - )), - ColorTransform::RGB => Ok(color_convert_line_rgb), - ColorTransform::YCbCr => Ok(color_convert_line_ycbcr), - ColorTransform::CMYK => Err(Error::Format( - "Invalid number of channels (3) for CMYK data".to_string(), - )), - ColorTransform::YCCK => Err(Error::Format( - "Invalid number of channels (3) for YCCK data".to_string(), - )), - ColorTransform::JcsBgYcc => Err(Error::Unsupported( - UnsupportedFeature::ColorTransform(ColorTransform::JcsBgYcc), - )), - ColorTransform::JcsBgRgb => Err(Error::Unsupported( - UnsupportedFeature::ColorTransform(ColorTransform::JcsBgRgb), - )), - ColorTransform::Unknown => Err(Error::Format("Unknown colour transform".to_string())), - }, - 4 => match color_transform { - ColorTransform::None => Ok(color_no_convert), - ColorTransform::Grayscale => Err(Error::Format( - "Invalid number of channels (4) for Grayscale data".to_string(), - )), - ColorTransform::RGB => Err(Error::Format( - "Invalid number of channels (4) for RGB data".to_string(), - )), - ColorTransform::YCbCr => Err(Error::Format( - "Invalid number of channels (4) for YCbCr data".to_string(), - )), - ColorTransform::CMYK => Ok(color_convert_line_cmyk), - ColorTransform::YCCK => Ok(color_convert_line_ycck), - - ColorTransform::JcsBgYcc => Err(Error::Unsupported( - UnsupportedFeature::ColorTransform(ColorTransform::JcsBgYcc), - )), - ColorTransform::JcsBgRgb => Err(Error::Unsupported( - UnsupportedFeature::ColorTransform(ColorTransform::JcsBgRgb), - )), - ColorTransform::Unknown => Err(Error::Format("Unknown colour transform".to_string())), - }, - _ => panic!(), - } -} - -fn color_convert_line_rgb(data: &[Vec], output: &mut [u8]) { - assert!(data.len() == 3, "wrong number of components for rgb"); - let [r, g, b]: &[Vec; 3] = data.try_into().unwrap(); - for (((chunk, r), g), b) in output - .chunks_exact_mut(3) - .zip(r.iter()) - .zip(g.iter()) - .zip(b.iter()) - { - chunk[0] = *r; - chunk[1] = *g; - chunk[2] = *b; - } -} - -fn color_convert_line_ycbcr(data: &[Vec], output: &mut [u8]) { - assert!(data.len() == 3, "wrong number of components for ycbcr"); - let [y, cb, cr]: &[_; 3] = data.try_into().unwrap(); - - #[cfg(not(feature = "platform_independent"))] - let arch_specific_pixels = { - if let Some(ycbcr) = crate::arch::get_color_convert_line_ycbcr() { - #[allow(unsafe_code)] - unsafe { - ycbcr(y, cb, cr, output) - } - } else { - 0 - } - }; - - #[cfg(feature = "platform_independent")] - let arch_specific_pixels = 0; - - for (((chunk, y), cb), cr) in output - .chunks_exact_mut(3) - .zip(y.iter()) - .zip(cb.iter()) - .zip(cr.iter()) - .skip(arch_specific_pixels) - { - let (r, g, b) = ycbcr_to_rgb(*y, *cb, *cr); - chunk[0] = r; - chunk[1] = g; - chunk[2] = b; - } -} - -fn color_convert_line_ycck(data: &[Vec], output: &mut [u8]) { - assert!(data.len() == 4, "wrong number of components for ycck"); - let [c, m, y, k]: &[Vec; 4] = data.try_into().unwrap(); - - for ((((chunk, c), m), y), k) in output - .chunks_exact_mut(4) - .zip(c.iter()) - .zip(m.iter()) - .zip(y.iter()) - .zip(k.iter()) - { - let (r, g, b) = ycbcr_to_rgb(*c, *m, *y); - chunk[0] = r; - chunk[1] = g; - chunk[2] = b; - chunk[3] = 255 - *k; - } -} - -fn color_convert_line_cmyk(data: &[Vec], output: &mut [u8]) { - assert!(data.len() == 4, "wrong number of components for cmyk"); - let [c, m, y, k]: &[Vec; 4] = data.try_into().unwrap(); - - for ((((chunk, c), m), y), k) in output - .chunks_exact_mut(4) - .zip(c.iter()) - .zip(m.iter()) - .zip(y.iter()) - .zip(k.iter()) - { - chunk[0] = 255 - c; - chunk[1] = 255 - m; - chunk[2] = 255 - y; - chunk[3] = 255 - k; - } -} - -fn color_no_convert(data: &[Vec], output: &mut [u8]) { - let mut output_iter = output.iter_mut(); - - for pixel in data { - for d in pixel { - *(output_iter.next().unwrap()) = *d; - } - } -} - -const FIXED_POINT_OFFSET: i32 = 20; -const HALF: i32 = (1 << FIXED_POINT_OFFSET) / 2; - -// ITU-R BT.601 -// Based on libjpeg-turbo's jdcolext.c -fn ycbcr_to_rgb(y: u8, cb: u8, cr: u8) -> (u8, u8, u8) { - let y = y as i32 * (1 << FIXED_POINT_OFFSET) + HALF; - let cb = cb as i32 - 128; - let cr = cr as i32 - 128; - - let r = clamp_fixed_point(y + stbi_f2f(1.40200) * cr); - let g = clamp_fixed_point(y - stbi_f2f(0.34414) * cb - stbi_f2f(0.71414) * cr); - let b = clamp_fixed_point(y + stbi_f2f(1.77200) * cb); - (r, g, b) -} - -fn stbi_f2f(x: f32) -> i32 { - (x * ((1 << FIXED_POINT_OFFSET) as f32) + 0.5) as i32 -} - -fn clamp_fixed_point(value: i32) -> u8 { - (value >> FIXED_POINT_OFFSET).min(255).max(0) as u8 -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/error.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -use alloc::boxed::Box; -use alloc::fmt; -use alloc::string::String; -use core::result; -use std::error::Error as StdError; -use std::io::Error as IoError; - -use crate::ColorTransform; - -pub type Result = result::Result; - -/// An enumeration over JPEG features (currently) unsupported by this library. -/// -/// Support for features listed here may be included in future versions of this library. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum UnsupportedFeature { - /// Hierarchical JPEG. - Hierarchical, - /// JPEG using arithmetic entropy coding instead of Huffman coding. - ArithmeticEntropyCoding, - /// Sample precision in bits. 8 bit sample precision is what is currently supported in non-lossless coding process. - SamplePrecision(u8), - /// Number of components in an image. 1, 3 and 4 components are currently supported. - ComponentCount(u8), - /// An image can specify a zero height in the frame header and use the DNL (Define Number of - /// Lines) marker at the end of the first scan to define the number of lines in the frame. - DNL, - /// Subsampling ratio. - SubsamplingRatio, - /// A subsampling ratio not representable as an integer. - NonIntegerSubsamplingRatio, - /// Colour transform - ColorTransform(ColorTransform), -} - -/// Errors that can occur while decoding a JPEG image. -#[derive(Debug)] -pub enum Error { - /// The image is not formatted properly. The string contains detailed information about the - /// error. - Format(String), - /// The image makes use of a JPEG feature not (currently) supported by this library. - Unsupported(UnsupportedFeature), - /// An I/O error occurred while decoding the image. - Io(IoError), - /// An internal error occurred while decoding the image. - Internal(Box), //TODO: not used, can be removed with the next version bump -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Format(ref desc) => write!(f, "invalid JPEG format: {}", desc), - Error::Unsupported(ref feat) => write!(f, "unsupported JPEG feature: {:?}", feat), - Error::Io(ref err) => err.fmt(f), - Error::Internal(ref err) => err.fmt(f), - } - } -} - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match *self { - Error::Io(ref err) => Some(err), - Error::Internal(ref err) => Some(&**err), - _ => None, - } - } -} - -impl From for Error { - fn from(err: IoError) -> Error { - Error::Io(err) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/huffman.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/huffman.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,346 +0,0 @@ -use alloc::borrow::ToOwned; -use alloc::vec; -use alloc::vec::Vec; -use core::iter; -use std::io::Read; -use crate::read_u8; -use crate::error::{Error, Result}; -use crate::marker::Marker; -use crate::parser::ScanInfo; - -const LUT_BITS: u8 = 8; - -#[derive(Debug)] -pub struct HuffmanDecoder { - bits: u64, - num_bits: u8, - marker: Option, -} - -impl HuffmanDecoder { - pub fn new() -> HuffmanDecoder { - HuffmanDecoder { - bits: 0, - num_bits: 0, - marker: None, - } - } - - // Section F.2.2.3 - // Figure F.16 - pub fn decode(&mut self, reader: &mut R, table: &HuffmanTable) -> Result { - if self.num_bits < 16 { - self.read_bits(reader)?; - } - - let (value, size) = table.lut[self.peek_bits(LUT_BITS) as usize]; - - if size > 0 { - self.consume_bits(size); - Ok(value) - } - else { - let bits = self.peek_bits(16); - - for i in LUT_BITS .. 16 { - let code = (bits >> (15 - i)) as i32; - - if code <= table.maxcode[i as usize] { - self.consume_bits(i + 1); - - let index = (code + table.delta[i as usize]) as usize; - return Ok(table.values[index]); - } - } - - Err(Error::Format("failed to decode huffman code".to_owned())) - } - } - - pub fn decode_fast_ac(&mut self, reader: &mut R, table: &HuffmanTable) -> Result> { - if let Some(ref ac_lut) = table.ac_lut { - if self.num_bits < LUT_BITS { - self.read_bits(reader)?; - } - - let (value, run_size) = ac_lut[self.peek_bits(LUT_BITS) as usize]; - - if run_size != 0 { - let run = run_size >> 4; - let size = run_size & 0x0f; - - self.consume_bits(size); - return Ok(Some((value, run))); - } - } - - Ok(None) - } - - #[inline] - pub fn get_bits(&mut self, reader: &mut R, count: u8) -> Result { - if self.num_bits < count { - self.read_bits(reader)?; - } - - let bits = self.peek_bits(count); - self.consume_bits(count); - - Ok(bits) - } - - #[inline] - pub fn receive_extend(&mut self, reader: &mut R, count: u8) -> Result { - let value = self.get_bits(reader, count)?; - Ok(extend(value, count)) - } - - pub fn reset(&mut self) { - self.bits = 0; - self.num_bits = 0; - } - - pub fn take_marker(&mut self, reader: &mut R) -> Result> { - self.read_bits(reader).map(|_| self.marker.take()) - } - - #[inline] - fn peek_bits(&mut self, count: u8) -> u16 { - debug_assert!(count <= 16); - debug_assert!(self.num_bits >= count); - - ((self.bits >> (64 - count)) & ((1 << count) - 1)) as u16 - } - - #[inline] - fn consume_bits(&mut self, count: u8) { - debug_assert!(self.num_bits >= count); - - self.bits <<= count as usize; - self.num_bits -= count; - } - - fn read_bits(&mut self, reader: &mut R) -> Result<()> { - while self.num_bits <= 56 { - // Fill with zero bits if we have reached the end. - let byte = match self.marker { - Some(_) => 0, - None => read_u8(reader)?, - }; - - if byte == 0xFF { - let mut next_byte = read_u8(reader)?; - - // Check for byte stuffing. - if next_byte != 0x00 { - // We seem to have reached the end of entropy-coded data and encountered a - // marker. Since we can't put data back into the reader, we have to continue - // reading to identify the marker so we can pass it on. - - // Section B.1.1.2 - // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code X’FF’." - while next_byte == 0xFF { - next_byte = read_u8(reader)?; - } - - match next_byte { - 0x00 => return Err(Error::Format("FF 00 found where marker was expected".to_owned())), - _ => self.marker = Some(Marker::from_u8(next_byte).unwrap()), - } - - continue; - } - } - - self.bits |= (byte as u64) << (56 - self.num_bits); - self.num_bits += 8; - } - - Ok(()) - } -} - -// Section F.2.2.1 -// Figure F.12 -fn extend(value: u16, count: u8) -> i16 { - let vt = 1 << (count as u16 - 1); - - if value < vt { - value as i16 + (-1 << count as i16) + 1 - } else { - value as i16 - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum HuffmanTableClass { - DC, - AC, -} - -pub struct HuffmanTable { - values: Vec, - delta: [i32; 16], - maxcode: [i32; 16], - - lut: [(u8, u8); 1 << LUT_BITS], - ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>, -} - -impl HuffmanTable { - pub fn new(bits: &[u8; 16], values: &[u8], class: HuffmanTableClass) -> Result { - let (huffcode, huffsize) = derive_huffman_codes(bits)?; - - // Section F.2.2.3 - // Figure F.15 - // delta[i] is set to VALPTR(I) - MINCODE(I) - let mut delta = [0i32; 16]; - let mut maxcode = [-1i32; 16]; - let mut j = 0; - - for i in 0 .. 16 { - if bits[i] != 0 { - delta[i] = j as i32 - huffcode[j] as i32; - j += bits[i] as usize; - maxcode[i] = huffcode[j - 1] as i32; - } - } - - // Build a lookup table for faster decoding. - let mut lut = [(0u8, 0u8); 1 << LUT_BITS]; - - for (i, &size) in huffsize.iter().enumerate().filter(|&(_, &size)| size <= LUT_BITS) { - let bits_remaining = LUT_BITS - size; - let start = (huffcode[i] << bits_remaining) as usize; - - let val = (values[i], size); - for b in &mut lut[start..][..1 << bits_remaining] { - *b = val; - } - } - - // Build a lookup table for small AC coefficients which both decodes the value and does the - // equivalent of receive_extend. - let ac_lut = match class { - HuffmanTableClass::DC => None, - HuffmanTableClass::AC => { - let mut table = [(0i16, 0u8); 1 << LUT_BITS]; - - for (i, &(value, size)) in lut.iter().enumerate() { - let run_length = value >> 4; - let magnitude_category = value & 0x0f; - - if magnitude_category > 0 && size + magnitude_category <= LUT_BITS { - let unextended_ac_value = (((i << size) & ((1 << LUT_BITS) - 1)) >> (LUT_BITS - magnitude_category)) as u16; - let ac_value = extend(unextended_ac_value, magnitude_category); - - table[i] = (ac_value, (run_length << 4) | (size + magnitude_category)); - } - } - - Some(table) - }, - }; - - Ok(HuffmanTable { - values: values.to_vec(), - delta, - maxcode, - lut, - ac_lut, - }) - } -} - -// Section C.2 -fn derive_huffman_codes(bits: &[u8; 16]) -> Result<(Vec, Vec)> { - // Figure C.1 - let huffsize = bits.iter() - .enumerate() - .fold(Vec::new(), |mut acc, (i, &value)| { - acc.extend(iter::repeat((i + 1) as u8).take(value as usize)); - acc - }); - - // Figure C.2 - let mut huffcode = vec![0u16; huffsize.len()]; - let mut code_size = huffsize[0]; - let mut code = 0u32; - - for (i, &size) in huffsize.iter().enumerate() { - while code_size < size { - code <<= 1; - code_size += 1; - } - - if code >= (1u32 << size) { - return Err(Error::Format("bad huffman code length".to_owned())); - } - - huffcode[i] = code as u16; - code += 1; - } - - Ok((huffcode, huffsize)) -} - -// https://www.loc.gov/preservation/digital/formats/fdd/fdd000063.shtml -// "Avery Lee, writing in the rec.video.desktop newsgroup in 2001, commented that "MJPEG, or at -// least the MJPEG in AVIs having the MJPG fourcc, is restricted JPEG with a fixed -- and -// *omitted* -- Huffman table. The JPEG must be YCbCr colorspace, it must be 4:2:2, and it must -// use basic Huffman encoding, not arithmetic or progressive.... You can indeed extract the -// MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT -// segment to them, or else the decoder won't have any idea how to decompress the data. -// The exact table necessary is given in the OpenDML spec."" -pub fn fill_default_mjpeg_tables(scan: &ScanInfo, - dc_huffman_tables: &mut[Option], - ac_huffman_tables: &mut[Option]) { - // Section K.3.3 - - if dc_huffman_tables[0].is_none() && scan.dc_table_indices.iter().any(|&i| i == 0) { - // Table K.3 - dc_huffman_tables[0] = Some(HuffmanTable::new( - &[0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], - &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], HuffmanTableClass::DC).unwrap()); - } - if dc_huffman_tables[1].is_none() && scan.dc_table_indices.iter().any(|&i| i == 1) { - // Table K.4 - dc_huffman_tables[1] = Some(HuffmanTable::new( - &[0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], - &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], HuffmanTableClass::DC).unwrap()); - } - if ac_huffman_tables[0].is_none() && scan.ac_table_indices.iter().any(|&i| i == 0) { - // Table K.5 - ac_huffman_tables[0] = Some(HuffmanTable::new( - &[0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D], - &[0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, - 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA - ], HuffmanTableClass::AC).unwrap()); - } - if ac_huffman_tables[1].is_none() && scan.ac_table_indices.iter().any(|&i| i == 1) { - // Table K.6 - ac_huffman_tables[1] = Some(HuffmanTable::new( - &[0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77], - &[0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, - 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, - 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, - 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, - 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, - 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA - ], HuffmanTableClass::AC).unwrap()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/idct.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/idct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/idct.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/idct.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,657 +0,0 @@ -// Malicious JPEG files can cause operations in the idct to overflow. -// One example is tests/crashtest/images/imagetestsuite/b0b8914cc5f7a6eff409f16d8cc236c5.jpg -// That's why wrapping operators are needed. - -// Note: we have many values that are straight from a reference. -// Do not warn on them or try to automatically change them. -#![allow(clippy::excessive_precision)] -// Note: consistency for unrolled, scaled offset loops -#![allow(clippy::erasing_op)] -#![allow(clippy::identity_op)] -use crate::parser::Dimensions; -use core::num::Wrapping; - -pub(crate) fn choose_idct_size(full_size: Dimensions, requested_size: Dimensions) -> usize { - fn scaled(len: u16, scale: usize) -> u16 { - ((len as u32 * scale as u32 - 1) / 8 + 1) as u16 - } - - for &scale in &[1, 2, 4] { - if scaled(full_size.width, scale) >= requested_size.width - || scaled(full_size.height, scale) >= requested_size.height - { - return scale; - } - } - - 8 -} - -#[test] -fn test_choose_idct_size() { - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 200, - height: 200 - } - ), - 1 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 500, - height: 500 - } - ), - 1 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 684, - height: 456 - } - ), - 1 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 999, - height: 456 - } - ), - 1 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 684, - height: 999 - } - ), - 1 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 500, - height: 333 - }, - Dimensions { - width: 63, - height: 42 - } - ), - 1 - ); - - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 685, - height: 999 - } - ), - 2 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 1000, - height: 1000 - } - ), - 2 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 1400, - height: 1400 - } - ), - 4 - ); - - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 5472, - height: 3648 - } - ), - 8 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 16384, - height: 16384 - } - ), - 8 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 1, - height: 1 - }, - Dimensions { - width: 65535, - height: 65535 - } - ), - 8 - ); - assert_eq!( - choose_idct_size( - Dimensions { - width: 5472, - height: 3648 - }, - Dimensions { - width: 16384, - height: 16384 - } - ), - 8 - ); -} - -pub(crate) fn dequantize_and_idct_block( - scale: usize, - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - match scale { - 8 => dequantize_and_idct_block_8x8( - coefficients, - quantization_table, - output_linestride, - output, - ), - 4 => dequantize_and_idct_block_4x4( - coefficients, - quantization_table, - output_linestride, - output, - ), - 2 => dequantize_and_idct_block_2x2( - coefficients, - quantization_table, - output_linestride, - output, - ), - 1 => dequantize_and_idct_block_1x1( - coefficients, - quantization_table, - output_linestride, - output, - ), - _ => panic!("Unsupported IDCT scale {scale}/8"), - } -} - -pub fn dequantize_and_idct_block_8x8( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - #[cfg(not(feature = "platform_independent"))] - if let Some(idct) = crate::arch::get_dequantize_and_idct_block_8x8() { - #[allow(unsafe_code)] - unsafe { - return idct(coefficients, quantization_table, output_linestride, output); - } - } - - let output = output.chunks_mut(output_linestride); - dequantize_and_idct_block_8x8_inner(coefficients, quantization_table, output) -} - -// This is based on stb_image's 'stbi__idct_block'. -fn dequantize_and_idct_block_8x8_inner<'a, I>( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output: I, -) where - I: IntoIterator, - I::IntoIter: ExactSizeIterator, -{ - let output = output.into_iter(); - debug_assert!( - output.len() >= 8, - "Output iterator has the wrong length: {}", - output.len() - ); - - let mut temp = [Wrapping(0); 64]; - - // columns - for i in 0..8 { - if coefficients[i + 8] == 0 - && coefficients[i + 16] == 0 - && coefficients[i + 24] == 0 - && coefficients[i + 32] == 0 - && coefficients[i + 40] == 0 - && coefficients[i + 48] == 0 - && coefficients[i + 56] == 0 - { - let dcterm = dequantize(coefficients[i], quantization_table[i]) << 2; - temp[i] = dcterm; - temp[i + 8] = dcterm; - temp[i + 16] = dcterm; - temp[i + 24] = dcterm; - temp[i + 32] = dcterm; - temp[i + 40] = dcterm; - temp[i + 48] = dcterm; - temp[i + 56] = dcterm; - } else { - let s0 = dequantize(coefficients[i], quantization_table[i]); - let s1 = dequantize(coefficients[i + 8], quantization_table[i + 8]); - let s2 = dequantize(coefficients[i + 16], quantization_table[i + 16]); - let s3 = dequantize(coefficients[i + 24], quantization_table[i + 24]); - let s4 = dequantize(coefficients[i + 32], quantization_table[i + 32]); - let s5 = dequantize(coefficients[i + 40], quantization_table[i + 40]); - let s6 = dequantize(coefficients[i + 48], quantization_table[i + 48]); - let s7 = dequantize(coefficients[i + 56], quantization_table[i + 56]); - - let Kernel { - xs: [x0, x1, x2, x3], - ts: [t0, t1, t2, t3], - } = kernel( - [s0, s1, s2, s3, s4, s5, s6, s7], - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - 512, - ); - - temp[i] = (x0 + t3) >> 10; - temp[i + 56] = (x0 - t3) >> 10; - temp[i + 8] = (x1 + t2) >> 10; - temp[i + 48] = (x1 - t2) >> 10; - temp[i + 16] = (x2 + t1) >> 10; - temp[i + 40] = (x2 - t1) >> 10; - temp[i + 24] = (x3 + t0) >> 10; - temp[i + 32] = (x3 - t0) >> 10; - } - } - - for (chunk, output_chunk) in temp.chunks_exact(8).zip(output) { - let chunk = <&[_; 8]>::try_from(chunk).unwrap(); - - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - // so we want to round that, which means adding 0.5 * 1<<17, - // aka 65536. Also, we'll end up with -128 to 127 that we want - // to encode as 0..255 by adding 128, so we'll add that before the shift - const X_SCALE: i32 = 65536 + (128 << 17); - - // eliminate downstream bounds checks - let output_chunk = &mut output_chunk[..8]; - - // TODO When the minimum rust version supports it - // let [s0, rest @ ..] = chunk; - let (s0, rest) = chunk.split_first().unwrap(); - if *rest == [Wrapping(0); 7] { - let dcterm = stbi_clamp((stbi_fsh(*s0) + Wrapping(X_SCALE)) >> 17); - output_chunk[0] = dcterm; - output_chunk[1] = dcterm; - output_chunk[2] = dcterm; - output_chunk[3] = dcterm; - output_chunk[4] = dcterm; - output_chunk[5] = dcterm; - output_chunk[6] = dcterm; - output_chunk[7] = dcterm; - } else { - let Kernel { - xs: [x0, x1, x2, x3], - ts: [t0, t1, t2, t3], - } = kernel(*chunk, X_SCALE); - - output_chunk[0] = stbi_clamp((x0 + t3) >> 17); - output_chunk[7] = stbi_clamp((x0 - t3) >> 17); - output_chunk[1] = stbi_clamp((x1 + t2) >> 17); - output_chunk[6] = stbi_clamp((x1 - t2) >> 17); - output_chunk[2] = stbi_clamp((x2 + t1) >> 17); - output_chunk[5] = stbi_clamp((x2 - t1) >> 17); - output_chunk[3] = stbi_clamp((x3 + t0) >> 17); - output_chunk[4] = stbi_clamp((x3 - t0) >> 17); - } - } -} - -struct Kernel { - xs: [Wrapping; 4], - ts: [Wrapping; 4], -} - -#[inline] -fn kernel_x([s0, s2, s4, s6]: [Wrapping; 4], x_scale: i32) -> [Wrapping; 4] { - // Even `chunk` indicies - let (t2, t3); - { - let p2 = s2; - let p3 = s6; - - let p1 = (p2 + p3) * stbi_f2f(0.5411961); - t2 = p1 + p3 * stbi_f2f(-1.847759065); - t3 = p1 + p2 * stbi_f2f(0.765366865); - } - - let (t0, t1); - { - let p2 = s0; - let p3 = s4; - - t0 = stbi_fsh(p2 + p3); - t1 = stbi_fsh(p2 - p3); - } - - let x0 = t0 + t3; - let x3 = t0 - t3; - let x1 = t1 + t2; - let x2 = t1 - t2; - - let x_scale = Wrapping(x_scale); - - [x0 + x_scale, x1 + x_scale, x2 + x_scale, x3 + x_scale] -} - -#[inline] -fn kernel_t([s1, s3, s5, s7]: [Wrapping; 4]) -> [Wrapping; 4] { - // Odd `chunk` indicies - let mut t0 = s7; - let mut t1 = s5; - let mut t2 = s3; - let mut t3 = s1; - - let p3 = t0 + t2; - let p4 = t1 + t3; - let p1 = t0 + t3; - let p2 = t1 + t2; - let p5 = (p3 + p4) * stbi_f2f(1.175875602); - - t0 *= stbi_f2f(0.298631336); - t1 *= stbi_f2f(2.053119869); - t2 *= stbi_f2f(3.072711026); - t3 *= stbi_f2f(1.501321110); - - let p1 = p5 + p1 * stbi_f2f(-0.899976223); - let p2 = p5 + p2 * stbi_f2f(-2.562915447); - let p3 = p3 * stbi_f2f(-1.961570560); - let p4 = p4 * stbi_f2f(-0.390180644); - - t3 += p1 + p4; - t2 += p2 + p3; - t1 += p2 + p4; - t0 += p1 + p3; - - [t0, t1, t2, t3] -} - -#[inline] -fn kernel([s0, s1, s2, s3, s4, s5, s6, s7]: [Wrapping; 8], x_scale: i32) -> Kernel { - Kernel { - xs: kernel_x([s0, s2, s4, s6], x_scale), - ts: kernel_t([s1, s3, s5, s7]), - } -} - -#[inline(always)] -fn dequantize(c: i16, q: u16) -> Wrapping { - Wrapping(i32::from(c) * i32::from(q)) -} - -// 4x4 and 2x2 IDCT based on Rakesh Dugad and Narendra Ahuja: "A Fast Scheme for Image Size Change in the Compressed Domain" (2001). -// http://sylvana.net/jpegcrop/jidctred/ -fn dequantize_and_idct_block_4x4( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - debug_assert_eq!(coefficients.len(), 64); - let mut temp = [Wrapping(0i32); 4 * 4]; - - const CONST_BITS: usize = 12; - const PASS1_BITS: usize = 2; - const FINAL_BITS: usize = CONST_BITS + PASS1_BITS + 3; - - // columns - for i in 0..4 { - let s0 = Wrapping(coefficients[i + 8 * 0] as i32 * quantization_table[i + 8 * 0] as i32); - let s1 = Wrapping(coefficients[i + 8 * 1] as i32 * quantization_table[i + 8 * 1] as i32); - let s2 = Wrapping(coefficients[i + 8 * 2] as i32 * quantization_table[i + 8 * 2] as i32); - let s3 = Wrapping(coefficients[i + 8 * 3] as i32 * quantization_table[i + 8 * 3] as i32); - - let x0 = (s0 + s2) << PASS1_BITS; - let x2 = (s0 - s2) << PASS1_BITS; - - let p1 = (s1 + s3) * stbi_f2f(0.541196100); - let t0 = (p1 + s3 * stbi_f2f(-1.847759065) + Wrapping(512)) >> (CONST_BITS - PASS1_BITS); - let t2 = (p1 + s1 * stbi_f2f(0.765366865) + Wrapping(512)) >> (CONST_BITS - PASS1_BITS); - - temp[i + 4 * 0] = x0 + t2; - temp[i + 4 * 3] = x0 - t2; - temp[i + 4 * 1] = x2 + t0; - temp[i + 4 * 2] = x2 - t0; - } - - for i in 0..4 { - let s0 = temp[i * 4 + 0]; - let s1 = temp[i * 4 + 1]; - let s2 = temp[i * 4 + 2]; - let s3 = temp[i * 4 + 3]; - - let x0 = (s0 + s2) << CONST_BITS; - let x2 = (s0 - s2) << CONST_BITS; - - let p1 = (s1 + s3) * stbi_f2f(0.541196100); - let t0 = p1 + s3 * stbi_f2f(-1.847759065); - let t2 = p1 + s1 * stbi_f2f(0.765366865); - - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - // so we want to round that, which means adding 0.5 * 1<<17, - // aka 65536. Also, we'll end up with -128 to 127 that we want - // to encode as 0..255 by adding 128, so we'll add that before the shift - let x0 = x0 + Wrapping(1 << (FINAL_BITS - 1)) + Wrapping(128 << FINAL_BITS); - let x2 = x2 + Wrapping(1 << (FINAL_BITS - 1)) + Wrapping(128 << FINAL_BITS); - - let output = &mut output[i * output_linestride..][..4]; - output[0] = stbi_clamp((x0 + t2) >> FINAL_BITS); - output[3] = stbi_clamp((x0 - t2) >> FINAL_BITS); - output[1] = stbi_clamp((x2 + t0) >> FINAL_BITS); - output[2] = stbi_clamp((x2 - t0) >> FINAL_BITS); - } -} - -fn dequantize_and_idct_block_2x2( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - output_linestride: usize, - output: &mut [u8], -) { - debug_assert_eq!(coefficients.len(), 64); - - const SCALE_BITS: usize = 3; - - // Column 0 - let s00 = Wrapping(coefficients[8 * 0] as i32 * quantization_table[8 * 0] as i32); - let s10 = Wrapping(coefficients[8 * 1] as i32 * quantization_table[8 * 1] as i32); - - let x0 = s00 + s10; - let x2 = s00 - s10; - - // Column 1 - let s01 = Wrapping(coefficients[8 * 0 + 1] as i32 * quantization_table[8 * 0 + 1] as i32); - let s11 = Wrapping(coefficients[8 * 1 + 1] as i32 * quantization_table[8 * 1 + 1] as i32); - - let x1 = s01 + s11; - let x3 = s01 - s11; - - let x0 = x0 + Wrapping(1 << (SCALE_BITS - 1)) + Wrapping(128 << SCALE_BITS); - let x2 = x2 + Wrapping(1 << (SCALE_BITS - 1)) + Wrapping(128 << SCALE_BITS); - - // Row 0 - output[0] = stbi_clamp((x0 + x1) >> SCALE_BITS); - output[1] = stbi_clamp((x0 - x1) >> SCALE_BITS); - - // Row 1 - output[output_linestride + 0] = stbi_clamp((x2 + x3) >> SCALE_BITS); - output[output_linestride + 1] = stbi_clamp((x2 - x3) >> SCALE_BITS); -} - -fn dequantize_and_idct_block_1x1( - coefficients: &[i16; 64], - quantization_table: &[u16; 64], - _output_linestride: usize, - output: &mut [u8], -) { - debug_assert_eq!(coefficients.len(), 64); - - let s0 = (Wrapping(coefficients[0] as i32 * quantization_table[0] as i32) + Wrapping(128 * 8)) / Wrapping(8); - output[0] = stbi_clamp(s0); -} - -// take a -128..127 value and stbi__clamp it and convert to 0..255 -fn stbi_clamp(x: Wrapping) -> u8 { - x.0.max(0).min(255) as u8 -} - -fn stbi_f2f(x: f32) -> Wrapping { - Wrapping((x * 4096.0 + 0.5) as i32) -} - -fn stbi_fsh(x: Wrapping) -> Wrapping { - x << 12 -} - -#[test] -fn test_dequantize_and_idct_block_8x8() { - #[rustfmt::skip] - let coefficients: [i16; 8 * 8] = [ - -14, -39, 58, -2, 3, 3, 0, 1, - 11, 27, 4, -3, 3, 0, 1, 0, - -6, -13, -9, -1, -2, -1, 0, 0, - -4, 0, -1, -2, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, - -3, -2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - ]; - - #[rustfmt::skip] - let quantization_table: [u16; 8 * 8] = [ - 8, 6, 5, 8, 12, 20, 26, 31, - 6, 6, 7, 10, 13, 29, 30, 28, - 7, 7, 8, 12, 20, 29, 35, 28, - 7, 9, 11, 15, 26, 44, 40, 31, - 9, 11, 19, 28, 34, 55, 52, 39, - 12, 18, 28, 32, 41, 52, 57, 46, - 25, 32, 39, 44, 52, 61, 60, 51, - 36, 46, 48, 49, 56, 50, 52, 50 - ]; - let output_linestride: usize = 8; - let mut output = [0u8; 8 * 8]; - dequantize_and_idct_block_8x8( - &coefficients, - &quantization_table, - output_linestride, - &mut output, - ); - #[rustfmt::skip] - let expected_output = [ - 118, 92, 110, 83, 77, 93, 144, 198, - 172, 116, 114, 87, 78, 93, 146, 191, - 194, 107, 91, 76, 71, 93, 160, 198, - 196, 100, 80, 74, 67, 92, 174, 209, - 182, 104, 88, 81, 68, 89, 178, 206, - 105, 64, 59, 59, 63, 94, 183, 201, - 35, 27, 28, 37, 72, 121, 203, 204, - 37, 45, 41, 47, 98, 154, 223, 208 - ]; - for i in 0..64 { - assert!((output[i] as i16 - expected_output[i] as i16).abs() <= 1); - } -} - -#[test] -fn test_dequantize_and_idct_block_8x8_all_zero() { - let mut output = [0u8; 8 * 8]; - dequantize_and_idct_block_8x8(&[0; 8 * 8], &[666; 8 * 8], 8, &mut output); - assert_eq!(&output[..], &[128; 8 * 8][..]); -} - -#[test] -fn test_dequantize_and_idct_block_8x8_saturated() { - // Arch-specific IDCT implementations need not handle i16::MAX values. - #[cfg(not(feature = "platform_independent"))] - if crate::arch::get_dequantize_and_idct_block_8x8().is_some() { - return; - } - let mut output = [0u8; 8 * 8]; - dequantize_and_idct_block_8x8(&[i16::MAX; 8 * 8], &[u16::MAX; 8 * 8], 8, &mut output); - #[rustfmt::skip] - let expected = [ - 0, 0, 0, 255, 255, 0, 0, 255, - 0, 0, 215, 0, 0, 255, 255, 0, - 255, 255, 255, 255, 255, 0, 0, 255, - 0, 0, 255, 0, 255, 0, 255, 255, - 0, 0, 255, 255, 0, 255, 0, 0, - 255, 255, 0, 255, 255, 255, 170, 0, - 0, 255, 0, 0, 0, 0, 0, 255, - 255, 255, 0, 255, 0, 255, 0, 0 - ]; - assert_eq!(&output[..], &expected[..]); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -//! This crate contains a JPEG decoder. -//! -//! # Examples -//! -//! ``` -//! use jpeg_decoder::Decoder; -//! use std::fs::File; -//! use std::io::BufReader; -//! -//! let file = File::open("tests/reftest/images/extraneous-data.jpg").expect("failed to open file"); -//! let mut decoder = Decoder::new(BufReader::new(file)); -//! let pixels = decoder.decode().expect("failed to decode image"); -//! let metadata = decoder.info().unwrap(); -//! ``` -//! -//! Get metadata from a file without decoding it: -//! -//! ``` -//! use jpeg_decoder::Decoder; -//! use std::fs::File; -//! use std::io::BufReader; -//! -//! let file = File::open("tests/reftest/images/extraneous-data.jpg").expect("failed to open file"); -//! let mut decoder = Decoder::new(BufReader::new(file)); -//! decoder.read_info().expect("failed to read metadata"); -//! let metadata = decoder.info().unwrap(); -//! ``` - -#![deny(missing_docs)] -#![deny(unsafe_code)] -#![cfg_attr(feature = "platform_independent", forbid(unsafe_code))] - -extern crate alloc; -extern crate core; - -#[cfg(feature = "rayon")] -extern crate rayon; - -pub use decoder::{ColorTransform, Decoder, ImageInfo, PixelFormat}; -pub use error::{Error, UnsupportedFeature}; -pub use parser::CodingProcess; - -use std::io; - -#[cfg(not(feature = "platform_independent"))] -mod arch; -mod decoder; -mod error; -mod huffman; -mod idct; -mod marker; -mod parser; -mod upsampler; -mod worker; - -fn read_u8(reader: &mut R) -> io::Result { - let mut buf = [0]; - reader.read_exact(&mut buf)?; - Ok(buf[0]) -} - -fn read_u16_from_be(reader: &mut R) -> io::Result { - let mut buf = [0, 0]; - reader.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf)) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/marker.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/marker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/marker.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/marker.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -// Table B.1 -#[derive(Clone, Copy, Debug, PartialEq)] -// Note: Established names. -#[allow(clippy::upper_case_acronyms)] -pub enum Marker { - /// Start Of Frame markers - /// - /// - SOF(0): Baseline DCT (Huffman coding) - /// - SOF(1): Extended sequential DCT (Huffman coding) - /// - SOF(2): Progressive DCT (Huffman coding) - /// - SOF(3): Lossless (sequential) (Huffman coding) - /// - SOF(5): Differential sequential DCT (Huffman coding) - /// - SOF(6): Differential progressive DCT (Huffman coding) - /// - SOF(7): Differential lossless (sequential) (Huffman coding) - /// - SOF(9): Extended sequential DCT (arithmetic coding) - /// - SOF(10): Progressive DCT (arithmetic coding) - /// - SOF(11): Lossless (sequential) (arithmetic coding) - /// - SOF(13): Differential sequential DCT (arithmetic coding) - /// - SOF(14): Differential progressive DCT (arithmetic coding) - /// - SOF(15): Differential lossless (sequential) (arithmetic coding) - SOF(u8), - /// Reserved for JPEG extensions - JPG, - /// Define Huffman table(s) - DHT, - /// Define arithmetic coding conditioning(s) - DAC, - /// Restart with modulo 8 count `m` - RST(u8), - /// Start of image - SOI, - /// End of image - EOI, - /// Start of scan - SOS, - /// Define quantization table(s) - DQT, - /// Define number of lines - DNL, - /// Define restart interval - DRI, - /// Define hierarchical progression - DHP, - /// Expand reference component(s) - EXP, - /// Reserved for application segments - APP(u8), - /// Reserved for JPEG extensions - JPGn(u8), - /// Comment - COM, - /// For temporary private use in arithmetic coding - TEM, - /// Reserved - RES, -} - -impl Marker { - pub fn has_length(self) -> bool { - use self::Marker::*; - ! matches!(self, RST(..) | SOI | EOI | TEM) - } - - pub fn from_u8(n: u8) -> Option { - use self::Marker::*; - match n { - 0x00 => None, // Byte stuffing - 0x01 => Some(TEM), - 0x02 ..= 0xBF => Some(RES), - 0xC0 => Some(SOF(0)), - 0xC1 => Some(SOF(1)), - 0xC2 => Some(SOF(2)), - 0xC3 => Some(SOF(3)), - 0xC4 => Some(DHT), - 0xC5 => Some(SOF(5)), - 0xC6 => Some(SOF(6)), - 0xC7 => Some(SOF(7)), - 0xC8 => Some(JPG), - 0xC9 => Some(SOF(9)), - 0xCA => Some(SOF(10)), - 0xCB => Some(SOF(11)), - 0xCC => Some(DAC), - 0xCD => Some(SOF(13)), - 0xCE => Some(SOF(14)), - 0xCF => Some(SOF(15)), - 0xD0 => Some(RST(0)), - 0xD1 => Some(RST(1)), - 0xD2 => Some(RST(2)), - 0xD3 => Some(RST(3)), - 0xD4 => Some(RST(4)), - 0xD5 => Some(RST(5)), - 0xD6 => Some(RST(6)), - 0xD7 => Some(RST(7)), - 0xD8 => Some(SOI), - 0xD9 => Some(EOI), - 0xDA => Some(SOS), - 0xDB => Some(DQT), - 0xDC => Some(DNL), - 0xDD => Some(DRI), - 0xDE => Some(DHP), - 0xDF => Some(EXP), - 0xE0 => Some(APP(0)), - 0xE1 => Some(APP(1)), - 0xE2 => Some(APP(2)), - 0xE3 => Some(APP(3)), - 0xE4 => Some(APP(4)), - 0xE5 => Some(APP(5)), - 0xE6 => Some(APP(6)), - 0xE7 => Some(APP(7)), - 0xE8 => Some(APP(8)), - 0xE9 => Some(APP(9)), - 0xEA => Some(APP(10)), - 0xEB => Some(APP(11)), - 0xEC => Some(APP(12)), - 0xED => Some(APP(13)), - 0xEE => Some(APP(14)), - 0xEF => Some(APP(15)), - 0xF0 => Some(JPGn(0)), - 0xF1 => Some(JPGn(1)), - 0xF2 => Some(JPGn(2)), - 0xF3 => Some(JPGn(3)), - 0xF4 => Some(JPGn(4)), - 0xF5 => Some(JPGn(5)), - 0xF6 => Some(JPGn(6)), - 0xF7 => Some(JPGn(7)), - 0xF8 => Some(JPGn(8)), - 0xF9 => Some(JPGn(9)), - 0xFA => Some(JPGn(10)), - 0xFB => Some(JPGn(11)), - 0xFC => Some(JPGn(12)), - 0xFD => Some(JPGn(13)), - 0xFE => Some(COM), - 0xFF => None, // Fill byte - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/parser.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/parser.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/parser.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/parser.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,704 +0,0 @@ -use alloc::borrow::ToOwned; -use alloc::{format, vec}; -use alloc::vec::Vec; -use core::ops::{self, Range}; -use std::io::{self, Read}; -use crate::{read_u16_from_be, read_u8}; -use crate::error::{Error, Result, UnsupportedFeature}; -use crate::huffman::{HuffmanTable, HuffmanTableClass}; -use crate::marker::Marker; -use crate::marker::Marker::*; - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Dimensions { - pub width: u16, - pub height: u16, -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum EntropyCoding { - Huffman, - Arithmetic, -} - -/// Represents the coding process of an image. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum CodingProcess { - /// Sequential Discrete Cosine Transform - DctSequential, - /// Progressive Discrete Cosine Transform - DctProgressive, - /// Lossless - Lossless, -} - -// Table H.1 -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Predictor { - NoPrediction, - Ra, - Rb, - Rc, - RaRbRc1, // Ra + Rb - Rc - RaRbRc2, // Ra + ((Rb - Rc) >> 1) - RaRbRc3, // Rb + ((Ra - Rb) >> 1) - RaRb, // (Ra + Rb)/2 -} - - -#[derive(Clone)] -pub struct FrameInfo { - pub is_baseline: bool, - pub is_differential: bool, - pub coding_process: CodingProcess, - pub entropy_coding: EntropyCoding, - pub precision: u8, - - pub image_size: Dimensions, - pub output_size: Dimensions, - pub mcu_size: Dimensions, - pub components: Vec, -} - -#[derive(Debug)] -pub struct ScanInfo { - pub component_indices: Vec, - pub dc_table_indices: Vec, - pub ac_table_indices: Vec, - - pub spectral_selection: Range, - pub predictor_selection: Predictor, // for lossless - pub successive_approximation_high: u8, - pub successive_approximation_low: u8, - pub point_transform: u8, // for lossless -} - -#[derive(Clone, Debug)] -pub struct Component { - pub identifier: u8, - - pub horizontal_sampling_factor: u8, - pub vertical_sampling_factor: u8, - - pub quantization_table_index: usize, - - pub dct_scale: usize, - - pub size: Dimensions, - pub block_size: Dimensions, -} - -#[derive(Debug)] -pub enum AppData { - Adobe(AdobeColorTransform), - Jfif, - Avi1, - Icc(IccChunk), - Exif(Vec), - Xmp(Vec), - Psir(Vec), -} - -// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe -#[allow(clippy::upper_case_acronyms)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum AdobeColorTransform { - // RGB or CMYK - Unknown, - YCbCr, - // YCbCrK - YCCK, -} -#[derive(Debug)] -pub struct IccChunk { - pub num_markers: u8, - pub seq_no: u8, - pub data: Vec, -} - -impl FrameInfo { - pub(crate) fn update_idct_size(&mut self, idct_size: usize) -> Result<()> { - for component in &mut self.components { - component.dct_scale = idct_size; - } - - update_component_sizes(self.image_size, &mut self.components)?; - - self.output_size = Dimensions { - width: (self.image_size.width as f32 * idct_size as f32 / 8.0).ceil() as u16, - height: (self.image_size.height as f32 * idct_size as f32 / 8.0).ceil() as u16 - }; - - Ok(()) - } -} - -fn read_length(reader: &mut R, marker: Marker) -> Result { - assert!(marker.has_length()); - - // length is including itself. - let length = usize::from(read_u16_from_be(reader)?); - - if length < 2 { - return Err(Error::Format(format!("encountered {:?} with invalid length {}", marker, length))); - } - - Ok(length - 2) -} - -fn skip_bytes(reader: &mut R, length: usize) -> Result<()> { - let length = length as u64; - let to_skip = &mut reader.by_ref().take(length); - let copied = io::copy(to_skip, &mut io::sink())?; - if copied < length { - Err(Error::Io(io::ErrorKind::UnexpectedEof.into())) - } else { - Ok(()) - } -} - -// Section B.2.2 -pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { - let length = read_length(reader, marker)?; - - if length <= 6 { - return Err(Error::Format("invalid length in SOF".to_owned())); - } - - let is_baseline = marker == SOF(0); - let is_differential = match marker { - SOF(0 ..= 3) | SOF(9 ..= 11) => false, - SOF(5 ..= 7) | SOF(13 ..= 15) => true, - _ => panic!(), - }; - let coding_process = match marker { - SOF(0) | SOF(1) | SOF(5) | SOF(9) | SOF(13) => CodingProcess::DctSequential, - SOF(2) | SOF(6) | SOF(10) | SOF(14) => CodingProcess::DctProgressive, - SOF(3) | SOF(7) | SOF(11) | SOF(15) => CodingProcess::Lossless, - _ => panic!(), - }; - let entropy_coding = match marker { - SOF(0 ..= 3) | SOF(5 ..= 7) => EntropyCoding::Huffman, - SOF(9 ..= 11) | SOF(13 ..= 15) => EntropyCoding::Arithmetic, - _ => panic!(), - }; - - let precision = read_u8(reader)?; - - match precision { - 8 => {}, - 12 => { - if is_baseline { - return Err(Error::Format("12 bit sample precision is not allowed in baseline".to_owned())); - } - }, - _ => { - if coding_process != CodingProcess::Lossless || precision > 16 { - return Err(Error::Format(format!("invalid precision {} in frame header", precision))) - } - }, - } - - let height = read_u16_from_be(reader)?; - let width = read_u16_from_be(reader)?; - - // height: - // "Value 0 indicates that the number of lines shall be defined by the DNL marker and - // parameters at the end of the first scan (see B.2.5)." - if height == 0 { - return Err(Error::Unsupported(UnsupportedFeature::DNL)); - } - - if width == 0 { - return Err(Error::Format("zero width in frame header".to_owned())); - } - - let component_count = read_u8(reader)?; - - if component_count == 0 { - return Err(Error::Format("zero component count in frame header".to_owned())); - } - if coding_process == CodingProcess::DctProgressive && component_count > 4 { - return Err(Error::Format("progressive frame with more than 4 components".to_owned())); - } - - if length != 6 + 3 * component_count as usize { - return Err(Error::Format("invalid length in SOF".to_owned())); - } - - let mut components: Vec = Vec::with_capacity(component_count as usize); - - for _ in 0 .. component_count { - let identifier = read_u8(reader)?; - - // Each component's identifier must be unique. - if components.iter().any(|c| c.identifier == identifier) { - return Err(Error::Format(format!("duplicate frame component identifier {}", identifier))); - } - - let byte = read_u8(reader)?; - let horizontal_sampling_factor = byte >> 4; - let vertical_sampling_factor = byte & 0x0f; - - if horizontal_sampling_factor == 0 || horizontal_sampling_factor > 4 { - return Err(Error::Format(format!("invalid horizontal sampling factor {}", horizontal_sampling_factor))); - } - if vertical_sampling_factor == 0 || vertical_sampling_factor > 4 { - return Err(Error::Format(format!("invalid vertical sampling factor {}", vertical_sampling_factor))); - } - - let quantization_table_index = read_u8(reader)?; - - if quantization_table_index > 3 || (coding_process == CodingProcess::Lossless && quantization_table_index != 0) { - return Err(Error::Format(format!("invalid quantization table index {}", quantization_table_index))); - } - - components.push(Component { - identifier, - horizontal_sampling_factor, - vertical_sampling_factor, - quantization_table_index: quantization_table_index as usize, - dct_scale: 8, - size: Dimensions {width: 0, height: 0}, - block_size: Dimensions {width: 0, height: 0}, - }); - } - - let mcu_size = update_component_sizes(Dimensions { width, height }, &mut components)?; - - Ok(FrameInfo { - is_baseline, - is_differential, - coding_process, - entropy_coding, - precision, - image_size: Dimensions { width, height }, - output_size: Dimensions { width, height }, - mcu_size, - components, - }) -} - -/// Returns ceil(x/y), requires x>0 -fn ceil_div(x: u32, y: u32) -> Result { - if x == 0 || y == 0 { - // TODO Determine how this error is reached. Can we validate input - // earlier and error out then? - return Err(Error::Format("invalid dimensions".to_owned())); - } - Ok((1 + ((x - 1) / y)) as u16) -} - -fn update_component_sizes(size: Dimensions, components: &mut [Component]) -> Result { - let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap() as u32; - let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap() as u32; - - let mcu_size = Dimensions { - width: ceil_div(size.width as u32, h_max * 8)?, - height: ceil_div(size.height as u32, v_max * 8)?, - }; - - for component in components { - component.size.width = ceil_div(size.width as u32 * component.horizontal_sampling_factor as u32 * component.dct_scale as u32, h_max * 8)?; - component.size.height = ceil_div(size.height as u32 * component.vertical_sampling_factor as u32 * component.dct_scale as u32, v_max * 8)?; - - component.block_size.width = mcu_size.width * component.horizontal_sampling_factor as u16; - component.block_size.height = mcu_size.height * component.vertical_sampling_factor as u16; - } - - Ok(mcu_size) -} - -#[test] -fn test_update_component_sizes() { - let mut components = [Component { - identifier: 1, - horizontal_sampling_factor: 2, - vertical_sampling_factor: 2, - quantization_table_index: 0, - dct_scale: 8, - size: Dimensions { width: 0, height: 0 }, - block_size: Dimensions { width: 0, height: 0 }, - }]; - let mcu = update_component_sizes( - Dimensions { width: 800, height: 280 }, - &mut components).unwrap(); - assert_eq!(mcu, Dimensions { width: 50, height: 18 }); - assert_eq!(components[0].block_size, Dimensions { width: 100, height: 36 }); - assert_eq!(components[0].size, Dimensions { width: 800, height: 280 }); -} - -// Section B.2.3 -pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result { - let length = read_length(reader, SOS)?; - if 0 == length { - return Err(Error::Format("zero length in SOS".to_owned())); - } - - let component_count = read_u8(reader)?; - - if component_count == 0 || component_count > 4 { - return Err(Error::Format(format!("invalid component count {} in scan header", component_count))); - } - - if length != 4 + 2 * component_count as usize { - return Err(Error::Format("invalid length in SOS".to_owned())); - } - - let mut component_indices = Vec::with_capacity(component_count as usize); - let mut dc_table_indices = Vec::with_capacity(component_count as usize); - let mut ac_table_indices = Vec::with_capacity(component_count as usize); - - for _ in 0 .. component_count { - let identifier = read_u8(reader)?; - - let component_index = match frame.components.iter().position(|c| c.identifier == identifier) { - Some(value) => value, - None => return Err(Error::Format(format!("scan component identifier {} does not match any of the component identifiers defined in the frame", identifier))), - }; - - // Each of the scan's components must be unique. - if component_indices.contains(&component_index) { - return Err(Error::Format(format!("duplicate scan component identifier {}", identifier))); - } - - // "... the ordering in the scan header shall follow the ordering in the frame header." - if component_index < *component_indices.iter().max().unwrap_or(&0) { - return Err(Error::Format("the scan component order does not follow the order in the frame header".to_owned())); - } - - let byte = read_u8(reader)?; - let dc_table_index = byte >> 4; - let ac_table_index = byte & 0x0f; - - if dc_table_index > 3 || (frame.is_baseline && dc_table_index > 1) { - return Err(Error::Format(format!("invalid dc table index {}", dc_table_index))); - } - if ac_table_index > 3 || (frame.is_baseline && ac_table_index > 1) { - return Err(Error::Format(format!("invalid ac table index {}", ac_table_index))); - } - - component_indices.push(component_index); - dc_table_indices.push(dc_table_index as usize); - ac_table_indices.push(ac_table_index as usize); - } - - let blocks_per_mcu = component_indices.iter().map(|&i| { - frame.components[i].horizontal_sampling_factor as u32 * frame.components[i].vertical_sampling_factor as u32 - }).fold(0, ops::Add::add); - - if component_count > 1 && blocks_per_mcu > 10 { - return Err(Error::Format("scan with more than one component and more than 10 blocks per MCU".to_owned())); - } - - // Also utilized as 'Predictor' in lossless coding, as MEAN in JPEG-LS etc. - let spectral_selection_start = read_u8(reader)?; - // Also utilized as ILV parameter in JPEG-LS. - let mut spectral_selection_end = read_u8(reader)?; - - let byte = read_u8(reader)?; - let successive_approximation_high = byte >> 4; - let successive_approximation_low = byte & 0x0f; - - // The Differential Pulse-Mode prediction used (similar to png). Only utilized in Lossless - // coding. Don't confuse with the JPEG-LS parameter coded using the same scan info portion. - let predictor_selection; - let point_transform = successive_approximation_low; - - if frame.coding_process == CodingProcess::DctProgressive { - predictor_selection = Predictor::NoPrediction; - if spectral_selection_end > 63 || spectral_selection_start > spectral_selection_end || - (spectral_selection_start == 0 && spectral_selection_end != 0) { - return Err(Error::Format(format!("invalid spectral selection parameters: ss={}, se={}", spectral_selection_start, spectral_selection_end))); - } - if spectral_selection_start != 0 && component_count != 1 { - return Err(Error::Format("spectral selection scan with AC coefficients can't have more than one component".to_owned())); - } - - if successive_approximation_high > 13 || successive_approximation_low > 13 { - return Err(Error::Format(format!("invalid successive approximation parameters: ah={}, al={}", successive_approximation_high, successive_approximation_low))); - } - - // Section G.1.1.1.2 - // "Each scan which follows the first scan for a given band progressively improves - // the precision of the coefficients by one bit, until full precision is reached." - if successive_approximation_high != 0 && successive_approximation_high != successive_approximation_low + 1 { - return Err(Error::Format("successive approximation scan with more than one bit of improvement".to_owned())); - } - } - else if frame.coding_process == CodingProcess::Lossless { - if spectral_selection_end != 0 { - return Err(Error::Format("spectral selection end shall be zero in lossless scan".to_owned())); - } - if successive_approximation_high != 0 { - return Err(Error::Format("successive approximation high shall be zero in lossless scan".to_owned())); - } - predictor_selection = match spectral_selection_start { - 0 => Predictor::NoPrediction, - 1 => Predictor::Ra, - 2 => Predictor::Rb, - 3 => Predictor::Rc, - 4 => Predictor::RaRbRc1, - 5 => Predictor::RaRbRc2, - 6 => Predictor::RaRbRc3, - 7 => Predictor::RaRb, - _ => { - return Err(Error::Format(format!("invalid predictor selection value: {}", spectral_selection_start))); - }, - }; - } - else { - predictor_selection = Predictor::NoPrediction; - if spectral_selection_end == 0 { - spectral_selection_end = 63; - } - if spectral_selection_start != 0 || spectral_selection_end != 63 { - return Err(Error::Format("spectral selection is not allowed in non-progressive scan".to_owned())); - } - if successive_approximation_high != 0 || successive_approximation_low != 0 { - return Err(Error::Format("successive approximation is not allowed in non-progressive scan".to_owned())); - } - } - - Ok(ScanInfo { - component_indices, - dc_table_indices, - ac_table_indices, - spectral_selection: Range { - start: spectral_selection_start, - end: spectral_selection_end + 1, - }, - predictor_selection, - successive_approximation_high, - successive_approximation_low, - point_transform, - }) -} - -// Section B.2.4.1 -pub fn parse_dqt(reader: &mut R) -> Result<[Option<[u16; 64]>; 4]> { - let mut length = read_length(reader, DQT)?; - let mut tables = [None; 4]; - - // Each DQT segment may contain multiple quantization tables. - while length > 0 { - let byte = read_u8(reader)?; - let precision = (byte >> 4) as usize; - let index = (byte & 0x0f) as usize; - - // The combination of 8-bit sample precision and 16-bit quantization tables is explicitly - // disallowed by the JPEG spec: - // "An 8-bit DCT-based process shall not use a 16-bit precision quantization table." - // "Pq: Quantization table element precision – Specifies the precision of the Qk - // values. Value 0 indicates 8-bit Qk values; value 1 indicates 16-bit Qk values. Pq - // shall be zero for 8 bit sample precision P (see B.2.2)." - // libjpeg allows this behavior though, and there are images in the wild using it. So to - // match libjpeg's behavior we are deviating from the JPEG spec here. - if precision > 1 { - return Err(Error::Format(format!("invalid precision {} in DQT", precision))); - } - if index > 3 { - return Err(Error::Format(format!("invalid destination identifier {} in DQT", index))); - } - if length < 65 + 64 * precision { - return Err(Error::Format("invalid length in DQT".to_owned())); - } - - let mut table = [0u16; 64]; - - for item in table.iter_mut() { - *item = match precision { - 0 => u16::from(read_u8(reader)?), - 1 => read_u16_from_be(reader)?, - _ => unreachable!(), - }; - } - - if table.iter().any(|&val| val == 0) { - return Err(Error::Format("quantization table contains element with a zero value".to_owned())); - } - - tables[index] = Some(table); - length -= 65 + 64 * precision; - } - - Ok(tables) -} - -// Section B.2.4.2 -#[allow(clippy::type_complexity)] -pub fn parse_dht(reader: &mut R, is_baseline: Option) -> Result<(Vec>, Vec>)> { - let mut length = read_length(reader, DHT)?; - let mut dc_tables = vec![None, None, None, None]; - let mut ac_tables = vec![None, None, None, None]; - - // Each DHT segment may contain multiple huffman tables. - while length > 17 { - let byte = read_u8(reader)?; - let class = byte >> 4; - let index = (byte & 0x0f) as usize; - - if class != 0 && class != 1 { - return Err(Error::Format(format!("invalid class {} in DHT", class))); - } - if is_baseline == Some(true) && index > 1 { - return Err(Error::Format("a maximum of two huffman tables per class are allowed in baseline".to_owned())); - } - if index > 3 { - return Err(Error::Format(format!("invalid destination identifier {} in DHT", index))); - } - - let mut counts = [0u8; 16]; - reader.read_exact(&mut counts)?; - - let size = counts.iter().map(|&val| val as usize).fold(0, ops::Add::add); - - if size == 0 { - return Err(Error::Format("encountered table with zero length in DHT".to_owned())); - } - else if size > 256 { - return Err(Error::Format("encountered table with excessive length in DHT".to_owned())); - } - else if size > length - 17 { - return Err(Error::Format("invalid length in DHT".to_owned())); - } - - let mut values = vec![0u8; size]; - reader.read_exact(&mut values)?; - - match class { - 0 => dc_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::DC)?), - 1 => ac_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::AC)?), - _ => unreachable!(), - } - - length -= 17 + size; - } - - if length != 0 { - return Err(Error::Format("invalid length in DHT".to_owned())); - } - - Ok((dc_tables, ac_tables)) -} - -// Section B.2.4.4 -pub fn parse_dri(reader: &mut R) -> Result { - let length = read_length(reader, DRI)?; - - if length != 2 { - return Err(Error::Format("DRI with invalid length".to_owned())); - } - - Ok(read_u16_from_be(reader)?) -} - -// Section B.2.4.5 -pub fn parse_com(reader: &mut R) -> Result> { - let length = read_length(reader, COM)?; - let mut buffer = vec![0u8; length]; - - reader.read_exact(&mut buffer)?; - - Ok(buffer) -} - -// Section B.2.4.6 -pub fn parse_app(reader: &mut R, marker: Marker) -> Result> { - let length = read_length(reader, marker)?; - let mut bytes_read = 0; - let mut result = None; - - match marker { - APP(0) => { - if length >= 5 { - let mut buffer = [0u8; 5]; - reader.read_exact(&mut buffer)?; - bytes_read = buffer.len(); - - // http://www.w3.org/Graphics/JPEG/jfif3.pdf - if buffer[0..5] == *b"JFIF\0" { - result = Some(AppData::Jfif); - // https://sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#AVI1 - } else if buffer[0..5] == *b"AVI1\0" { - result = Some(AppData::Avi1); - } - } - } - APP(1) => { - let mut buffer = vec![0u8; length]; - reader.read_exact(&mut buffer)?; - bytes_read = buffer.len(); - - // https://web.archive.org/web/20190624045241if_/http://www.cipa.jp:80/std/documents/e/DC-008-Translation-2019-E.pdf - // 4.5.4 Basic Structure of JPEG Compressed Data - if length >= 6 && buffer[0..6] == *b"Exif\x00\x00" { - result = Some(AppData::Exif(buffer[6..].to_vec())); - } - // XMP packet - // https://github.com/adobe/XMP-Toolkit-SDK/blob/main/docs/XMPSpecificationPart3.pdf - else if length >= 29 && buffer[0..29] == *b"http://ns.adobe.com/xap/1.0/\0" { - result = Some(AppData::Xmp(buffer[29..].to_vec())); - } - } - APP(2) => { - if length > 14 { - let mut buffer = [0u8; 14]; - reader.read_exact(&mut buffer)?; - bytes_read = buffer.len(); - - // http://www.color.org/ICC_Minor_Revision_for_Web.pdf - // B.4 Embedding ICC profiles in JFIF files - if buffer[0..12] == *b"ICC_PROFILE\0" { - let mut data = vec![0; length - bytes_read]; - reader.read_exact(&mut data)?; - bytes_read += data.len(); - result = Some(AppData::Icc(IccChunk { - seq_no: buffer[12], - num_markers: buffer[13], - data, - })); - } - } - } - APP(13) => { - if length >= 14 { - let mut buffer = [0u8; 14]; - reader.read_exact(&mut buffer)?; - bytes_read = buffer.len(); - - // PSIR (Photoshop) - // https://github.com/adobe/XMP-Toolkit-SDK/blob/main/docs/XMPSpecificationPart3.pdf - if buffer[0..14] == *b"Photoshop 3.0\0" { - let mut data = vec![0; length - bytes_read]; - reader.read_exact(&mut data)?; - bytes_read += data.len(); - result = Some(AppData::Psir(data)); - } - } - } - APP(14) => { - if length >= 12 { - let mut buffer = [0u8; 12]; - reader.read_exact(&mut buffer)?; - bytes_read = buffer.len(); - - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe - if buffer[0 .. 6] == *b"Adobe\0" { - let color_transform = match buffer[11] { - 0 => AdobeColorTransform::Unknown, - 1 => AdobeColorTransform::YCbCr, - 2 => AdobeColorTransform::YCCK, - _ => return Err(Error::Format("invalid color transform in adobe app segment".to_owned())), - }; - - result = Some(AppData::Adobe(color_transform)); - } - } - }, - _ => {}, - } - - skip_bytes(reader, length - bytes_read)?; - Ok(result) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/upsampler.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/upsampler.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/upsampler.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/upsampler.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -use alloc::boxed::Box; -use alloc::vec; -use alloc::vec::Vec; -use crate::error::{Error, Result, UnsupportedFeature}; -use crate::parser::Component; - -pub struct Upsampler { - components: Vec, - line_buffer_size: usize -} - -struct UpsamplerComponent { - upsampler: Box, - width: usize, - height: usize, - row_stride: usize, -} - -impl Upsampler { - pub fn new(components: &[Component], output_width: u16, output_height: u16) -> Result { - let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap(); - let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap(); - let mut upsampler_components = Vec::with_capacity(components.len()); - - for component in components { - let upsampler = choose_upsampler((component.horizontal_sampling_factor, - component.vertical_sampling_factor), - (h_max, v_max), - output_width, - output_height)?; - upsampler_components.push(UpsamplerComponent { - upsampler, - width: component.size.width as usize, - height: component.size.height as usize, - row_stride: component.block_size.width as usize * component.dct_scale, - }); - } - - let buffer_size = components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize; - - Ok(Upsampler { - components: upsampler_components, - line_buffer_size: buffer_size - }) - } - - pub fn upsample_and_interleave_row(&self, component_data: &[Vec], row: usize, output_width: usize, output: &mut [u8], color_convert: fn(&[Vec], &mut [u8])) { - let component_count = component_data.len(); - let mut line_buffers = vec![vec![0u8; self.line_buffer_size]; component_count]; - - debug_assert_eq!(component_count, self.components.len()); - - for (i, component) in self.components.iter().enumerate() { - component.upsampler.upsample_row(&component_data[i], - component.width, - component.height, - component.row_stride, - row, - output_width, - &mut line_buffers[i]); - } - color_convert(&line_buffers, output); - } -} - -struct UpsamplerH1V1; -struct UpsamplerH2V1; -struct UpsamplerH1V2; -struct UpsamplerH2V2; - -struct UpsamplerGeneric { - horizontal_scaling_factor: u8, - vertical_scaling_factor: u8 -} - -fn choose_upsampler(sampling_factors: (u8, u8), - max_sampling_factors: (u8, u8), - output_width: u16, - output_height: u16) -> Result> { - let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1; - let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1; - let h2 = sampling_factors.0 * 2 == max_sampling_factors.0; - let v2 = sampling_factors.1 * 2 == max_sampling_factors.1; - - if h1 && v1 { - Ok(Box::new(UpsamplerH1V1)) - } else if h2 && v1 { - Ok(Box::new(UpsamplerH2V1)) - } else if h1 && v2 { - Ok(Box::new(UpsamplerH1V2)) - } else if h2 && v2 { - Ok(Box::new(UpsamplerH2V2)) - } else if max_sampling_factors.0 % sampling_factors.0 != 0 - || max_sampling_factors.1 % sampling_factors.1 != 0 - { - Err(Error::Unsupported( - UnsupportedFeature::NonIntegerSubsamplingRatio, - )) - } else { - Ok(Box::new(UpsamplerGeneric { - horizontal_scaling_factor: max_sampling_factors.0 / sampling_factors.0, - vertical_scaling_factor: max_sampling_factors.1 / sampling_factors.1, - })) - } -} - -#[allow(clippy::too_many_arguments)] -trait Upsample { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]); -} - -impl Upsample for UpsamplerH1V1 { - fn upsample_row(&self, - input: &[u8], - _input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]) { - let input = &input[row * row_stride ..]; - - output[..output_width].copy_from_slice(&input[..output_width]); - } -} - -impl Upsample for UpsamplerH2V1 { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { - let input = &input[row * row_stride ..]; - - if input_width == 1 { - output[0] = input[0]; - output[1] = input[0]; - return; - } - - output[0] = input[0]; - output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8; - - for i in 1 .. input_width - 1 { - let sample = 3 * input[i] as u32 + 2; - output[i * 2] = ((sample + input[i - 1] as u32) >> 2) as u8; - output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8; - } - - output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8; - output[(input_width - 1) * 2 + 1] = input[input_width - 1]; - } -} - -impl Upsample for UpsamplerH1V2 { - fn upsample_row(&self, - input: &[u8], - _input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]) { - let row_near = row as f32 / 2.0; - // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we - // want it to be the next row. - let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); - - let input_near = &input[row_near as usize * row_stride ..]; - let input_far = &input[row_far as usize * row_stride ..]; - - let output = &mut output[..output_width]; - let input_near = &input_near[..output_width]; - let input_far = &input_far[..output_width]; - for i in 0..output_width { - output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8; - } - } -} - -impl Upsample for UpsamplerH2V2 { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { - let row_near = row as f32 / 2.0; - // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we - // want it to be the next row. - let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); - - let input_near = &input[row_near as usize * row_stride ..]; - let input_far = &input[row_far as usize * row_stride ..]; - - if input_width == 1 { - let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8; - output[0] = value; - output[1] = value; - return; - } - - let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32; - output[0] = ((t1 + 2) >> 2) as u8; - - for i in 1 .. input_width { - let t0 = t1; - t1 = 3 * input_near[i] as u32 + input_far[i] as u32; - - output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8; - output[i * 2] = ((3 * t1 + t0 + 8) >> 4) as u8; - } - - output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8; - } -} - -impl Upsample for UpsamplerGeneric { - // Uses nearest neighbor sampling - fn upsample_row(&self, - input: &[u8], - input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { - let mut index = 0; - let start = (row / self.vertical_scaling_factor as usize) * row_stride; - let input = &input[start..(start + input_width)]; - for val in input { - for _ in 0..self.horizontal_scaling_factor { - output[index] = *val; - index += 1; - } - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/immediate.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/immediate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/immediate.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/immediate.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -use alloc::vec; -use alloc::vec::Vec; -use core::mem; -use crate::decoder::MAX_COMPONENTS; -use crate::error::Result; -use crate::idct::dequantize_and_idct_block; -use crate::alloc::sync::Arc; -use crate::parser::Component; -use super::{RowData, Worker}; - -pub struct ImmediateWorker { - offsets: [usize; MAX_COMPONENTS], - results: Vec>, - components: Vec>, - quantization_tables: Vec>>, -} - -impl Default for ImmediateWorker { - fn default() -> Self { - ImmediateWorker { - offsets: [0; MAX_COMPONENTS], - results: vec![Vec::new(); MAX_COMPONENTS], - components: vec![None; MAX_COMPONENTS], - quantization_tables: vec![None; MAX_COMPONENTS], - } - } -} - -impl ImmediateWorker { - pub fn start_immediate(&mut self, data: RowData) { - assert!(self.results[data.index].is_empty()); - - self.offsets[data.index] = 0; - self.results[data.index].resize(data.component.block_size.width as usize * data.component.block_size.height as usize * data.component.dct_scale * data.component.dct_scale, 0u8); - self.components[data.index] = Some(data.component); - self.quantization_tables[data.index] = Some(data.quantization_table); - } - - pub fn append_row_immediate(&mut self, (index, data): (usize, Vec)) { - // Convert coefficients from a MCU row to samples. - - let component = self.components[index].as_ref().unwrap(); - let quantization_table = self.quantization_tables[index].as_ref().unwrap(); - let block_count = component.block_size.width as usize * component.vertical_sampling_factor as usize; - let line_stride = component.block_size.width as usize * component.dct_scale; - - assert_eq!(data.len(), block_count * 64); - - for i in 0..block_count { - let x = (i % component.block_size.width as usize) * component.dct_scale; - let y = (i / component.block_size.width as usize) * component.dct_scale; - - let coefficients = data[i * 64..(i + 1) * 64].try_into().unwrap(); - let output = &mut self.results[index][self.offsets[index] + y * line_stride + x..]; - - dequantize_and_idct_block(component.dct_scale, coefficients, quantization_table, line_stride, output); - } - - self.offsets[index] += block_count * component.dct_scale * component.dct_scale; - } - - pub fn get_result_immediate(&mut self, index: usize) -> Vec { - mem::take(&mut self.results[index]) - } -} - -impl Worker for ImmediateWorker { - fn start(&mut self, data: RowData) -> Result<()> { - self.start_immediate(data); - Ok(()) - } - fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { - self.append_row_immediate(row); - Ok(()) - } - fn get_result(&mut self, index: usize) -> Result> { - Ok(self.get_result_immediate(index)) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/mod.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -mod immediate; -mod multithreaded; -#[cfg(all( - not(any(target_arch = "asmjs", target_arch = "wasm32")), - feature = "rayon" -))] -mod rayon; - -use crate::decoder::{choose_color_convert_func, ColorTransform}; -use crate::error::Result; -use crate::parser::{Component, Dimensions}; -use crate::upsampler::Upsampler; - -use alloc::sync::Arc; -use alloc::vec::Vec; -use core::cell::RefCell; - -pub struct RowData { - pub index: usize, - pub component: Component, - pub quantization_table: Arc<[u16; 64]>, -} - -pub trait Worker { - fn start(&mut self, row_data: RowData) -> Result<()>; - fn append_row(&mut self, row: (usize, Vec)) -> Result<()>; - fn get_result(&mut self, index: usize) -> Result>; - /// Default implementation for spawning multiple tasks. - fn append_rows(&mut self, row: &mut dyn Iterator)>) -> Result<()> { - for item in row { - self.append_row(item)?; - } - Ok(()) - } -} - -#[allow(dead_code)] -pub enum PreferWorkerKind { - Immediate, - Multithreaded, -} - -#[derive(Default)] -pub struct WorkerScope { - inner: core::cell::RefCell>, -} - -enum WorkerScopeInner { - #[cfg(all( - not(any(target_arch = "asmjs", target_arch = "wasm32")), - feature = "rayon" - ))] - Rayon(Box), - #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] - Multithreaded(multithreaded::MpscWorker), - Immediate(immediate::ImmediateWorker), -} - -impl WorkerScope { - pub fn with(with: impl FnOnce(&Self) -> T) -> T { - with(&WorkerScope { - inner: RefCell::default(), - }) - } - - pub fn get_or_init_worker( - &self, - prefer: PreferWorkerKind, - f: impl FnOnce(&mut dyn Worker) -> T, - ) -> T { - let mut inner = self.inner.borrow_mut(); - let inner = inner.get_or_insert_with(move || match prefer { - #[cfg(all( - not(any(target_arch = "asmjs", target_arch = "wasm32")), - feature = "rayon" - ))] - PreferWorkerKind::Multithreaded => WorkerScopeInner::Rayon(Default::default()), - #[allow(unreachable_patterns)] - #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] - PreferWorkerKind::Multithreaded => WorkerScopeInner::Multithreaded(Default::default()), - _ => WorkerScopeInner::Immediate(Default::default()), - }); - - f(match &mut *inner { - #[cfg(all( - not(any(target_arch = "asmjs", target_arch = "wasm32")), - feature = "rayon" - ))] - WorkerScopeInner::Rayon(worker) => worker.as_mut(), - #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] - WorkerScopeInner::Multithreaded(worker) => worker, - WorkerScopeInner::Immediate(worker) => worker, - }) - } -} - -pub fn compute_image_parallel( - components: &[Component], - data: Vec>, - output_size: Dimensions, - color_transform: ColorTransform, -) -> Result> { - #[cfg(all( - not(any(target_arch = "asmjs", target_arch = "wasm32")), - feature = "rayon" - ))] - return rayon::compute_image_parallel(components, data, output_size, color_transform); - - #[allow(unreachable_code)] - { - let color_convert_func = choose_color_convert_func(components.len(), color_transform)?; - let upsampler = Upsampler::new(components, output_size.width, output_size.height)?; - let line_size = output_size.width as usize * components.len(); - let mut image = vec![0u8; line_size * output_size.height as usize]; - - for (row, line) in image.chunks_mut(line_size).enumerate() { - upsampler.upsample_and_interleave_row( - &data, - row, - output_size.width as usize, - line, - color_convert_func, - ); - } - - Ok(image) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/multithreaded.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/multithreaded.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/multithreaded.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/multithreaded.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -//! This module implements per-component parallelism. -//! It should be possible to implement per-row parallelism as well, -//! which should also boost performance of grayscale images -//! and allow scaling to more cores. -//! However, that would be more complex, so we use this as a starting point. - -use super::immediate::ImmediateWorker; -use super::{RowData, Worker}; -use crate::decoder::MAX_COMPONENTS; -use crate::error::Result; -use std::{ - mem, - sync::mpsc::{self, Receiver, Sender}, -}; - -enum WorkerMsg { - Start(RowData), - AppendRow(Vec), - GetResult(Sender>), -} - -#[derive(Default)] -pub struct MpscWorker { - senders: [Option>; MAX_COMPONENTS], -} - -impl MpscWorker { - fn start_with( - &mut self, - row_data: RowData, - spawn_worker: impl FnOnce(usize) -> Result>, - ) -> Result<()> { - // if there is no worker thread for this component yet, start one - let component = row_data.index; - if self.senders[component].is_none() { - let sender = spawn_worker(component)?; - self.senders[component] = Some(sender); - } - - // we do the "take out value and put it back in once we're done" dance here - // and in all other message-passing methods because there's not that many rows - // and this should be cheaper than spawning MAX_COMPONENTS many threads up front - let sender = self.senders[component].as_mut().unwrap(); - sender - .send(WorkerMsg::Start(row_data)) - .expect("jpeg-decoder worker thread error"); - Ok(()) - } - - fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { - let component = row.0; - let sender = self.senders[component].as_mut().unwrap(); - sender - .send(WorkerMsg::AppendRow(row.1)) - .expect("jpeg-decoder worker thread error"); - Ok(()) - } - - fn get_result_with( - &mut self, - index: usize, - collect: impl FnOnce(Receiver>) -> Vec, - ) -> Result> { - let (tx, rx) = mpsc::channel(); - let sender = mem::take(&mut self.senders[index]).unwrap(); - sender - .send(WorkerMsg::GetResult(tx)) - .expect("jpeg-decoder worker thread error"); - Ok(collect(rx)) - } -} - -impl Worker for MpscWorker { - fn start(&mut self, row_data: RowData) -> Result<()> { - self.start_with(row_data, spawn_worker_thread) - } - fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { - MpscWorker::append_row(self, row) - } - fn get_result(&mut self, index: usize) -> Result> { - self.get_result_with(index, collect_worker_thread) - } -} - -fn create_worker() -> (Sender, impl FnOnce() + 'static) { - let (tx, rx) = mpsc::channel(); - let closure = move || { - let mut worker = ImmediateWorker::default(); - - while let Ok(message) = rx.recv() { - match message { - WorkerMsg::Start(mut data) => { - // we always set component index to 0 for worker threads - // because they only ever handle one per thread and we don't want them - // to attempt to access nonexistent components - data.index = 0; - worker.start_immediate(data); - } - WorkerMsg::AppendRow(row) => { - worker.append_row_immediate((0, row)); - } - WorkerMsg::GetResult(chan) => { - let _ = chan.send(worker.get_result_immediate(0)); - break; - } - } - } - }; - - (tx, closure) -} - -fn spawn_worker_thread(component: usize) -> Result> { - let (tx, worker) = create_worker(); - let thread_builder = - std::thread::Builder::new().name(format!("worker thread for component {}", component)); - thread_builder.spawn(worker)?; - Ok(tx) -} - -fn collect_worker_thread(rx: Receiver>) -> Vec { - rx.recv().expect("jpeg-decoder worker thread error") -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/rayon.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/rayon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/src/worker/rayon.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/src/worker/rayon.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -use rayon::iter::{IndexedParallelIterator, ParallelIterator}; -use rayon::slice::ParallelSliceMut; - -use crate::decoder::{choose_color_convert_func, ColorTransform}; -use crate::error::Result; -use crate::idct::dequantize_and_idct_block; -use crate::parser::Component; -use crate::upsampler::Upsampler; -use crate::{decoder::MAX_COMPONENTS, parser::Dimensions}; - -use std::sync::Arc; - -use super::{RowData, Worker}; - -/// Technically similar to `immediate::ImmediateWorker` but we copy it since we may prefer -/// different style of managing the memory allocation, something that multiple actors can access in -/// parallel. -#[derive(Default)] -struct ImmediateWorker { - offsets: [usize; MAX_COMPONENTS], - results: [Vec; MAX_COMPONENTS], - components: [Option; MAX_COMPONENTS], - quantization_tables: [Option>; MAX_COMPONENTS], -} - -#[derive(Clone, Copy)] -struct ComponentMetadata { - block_width: usize, - block_count: usize, - line_stride: usize, - dct_scale: usize, -} - -#[derive(Default)] -pub struct Scoped { - inner: ImmediateWorker, -} - -impl ImmediateWorker { - pub fn start_immediate(&mut self, data: RowData) { - let elements = data.component.block_size.width as usize - * data.component.block_size.height as usize - * data.component.dct_scale - * data.component.dct_scale; - self.offsets[data.index] = 0; - self.results[data.index].resize(elements, 0u8); - self.components[data.index] = Some(data.component); - self.quantization_tables[data.index] = Some(data.quantization_table); - } - - pub fn get_result_immediate(&mut self, index: usize) -> Vec { - core::mem::take(&mut self.results[index]) - } - - pub fn component_metadata(&self, index: usize) -> Option { - let component = self.components[index].as_ref()?; - let block_size = component.block_size; - let block_width = block_size.width as usize; - let block_count = block_size.width as usize * component.vertical_sampling_factor as usize; - let line_stride = block_size.width as usize * component.dct_scale; - let dct_scale = component.dct_scale; - - Some(ComponentMetadata { - block_width, - block_count, - line_stride, - dct_scale, - }) - } - - pub fn append_row_locked( - quantization_table: Arc<[u16; 64]>, - metadata: ComponentMetadata, - data: Vec, - result_block: &mut [u8], - ) { - // Convert coefficients from a MCU row to samples. - let ComponentMetadata { - block_count, - line_stride, - block_width, - dct_scale, - } = metadata; - - assert_eq!(data.len(), block_count * 64); - - let mut output_buffer = [0; 64]; - for i in 0..block_count { - let x = (i % block_width) * dct_scale; - let y = (i / block_width) * dct_scale; - - let coefficients: &[i16; 64] = &data[i * 64..(i + 1) * 64].try_into().unwrap(); - - // Write to a temporary intermediate buffer, a 8x8 'image'. - dequantize_and_idct_block( - dct_scale, - coefficients, - &quantization_table, - 8, - &mut output_buffer, - ); - - let write_back = &mut result_block[y * line_stride + x..]; - - let buffered_lines = output_buffer.chunks_mut(8); - let back_lines = write_back.chunks_mut(line_stride); - - for (buf, back) in buffered_lines.zip(back_lines).take(dct_scale) { - back[..dct_scale].copy_from_slice(&buf[..dct_scale]); - } - } - } -} - -impl Worker for Scoped { - fn start(&mut self, row_data: RowData) -> Result<()> { - self.inner.start_immediate(row_data); - Ok(()) - } - - fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { - let inner = &mut self.inner; - let (index, data) = row; - - let quantization_table = inner.quantization_tables[index].as_ref().unwrap().clone(); - let metadata = inner.component_metadata(index).unwrap(); - let result_block = &mut inner.results[index][inner.offsets[index]..]; - inner.offsets[index] += metadata.bytes_used(); - - ImmediateWorker::append_row_locked(quantization_table, metadata, data, result_block); - Ok(()) - } - - fn get_result(&mut self, index: usize) -> Result> { - let result = self.inner.get_result_immediate(index); - Ok(result) - } - - // Magic sauce, these _may_ run in parallel. - fn append_rows(&mut self, iter: &mut dyn Iterator)>) -> Result<()> { - let inner = &mut self.inner; - rayon::in_place_scope(|scope| { - let metadatas = [ - inner.component_metadata(0), - inner.component_metadata(1), - inner.component_metadata(2), - inner.component_metadata(3), - ]; - - let [res0, res1, res2, res3] = &mut inner.results; - - // Lazily get the blocks. Note: if we've already collected results from a component - // then the result vector has already been deallocated/taken. But no more tasks should - // be created for it. - let mut result_blocks = [ - res0.get_mut(inner.offsets[0]..).unwrap_or(&mut []), - res1.get_mut(inner.offsets[1]..).unwrap_or(&mut []), - res2.get_mut(inner.offsets[2]..).unwrap_or(&mut []), - res3.get_mut(inner.offsets[3]..).unwrap_or(&mut []), - ]; - - // First we schedule everything, making sure their index is right etc. - for (index, data) in iter { - let metadata = metadatas[index].unwrap(); - let quantization_table = inner.quantization_tables[index].as_ref().unwrap().clone(); - - inner.offsets[index] += metadata.bytes_used(); - let (result_block, tail) = - core::mem::take(&mut result_blocks[index]).split_at_mut(metadata.bytes_used()); - result_blocks[index] = tail; - - scope.spawn(move |_| { - ImmediateWorker::append_row_locked( - quantization_table, - metadata, - data, - result_block, - ) - }); - } - }); - - Ok(()) - } -} - -impl ComponentMetadata { - fn bytes_used(&self) -> usize { - self.block_count * self.dct_scale * self.dct_scale - } -} - -pub fn compute_image_parallel( - components: &[Component], - data: Vec>, - output_size: Dimensions, - color_transform: ColorTransform, -) -> Result> { - let color_convert_func = choose_color_convert_func(components.len(), color_transform)?; - let upsampler = Upsampler::new(components, output_size.width, output_size.height)?; - let line_size = output_size.width as usize * components.len(); - let mut image = vec![0u8; line_size * output_size.height as usize]; - - image - .par_chunks_mut(line_size) - .with_max_len(1) - .enumerate() - .for_each(|(row, line)| { - upsampler.upsample_and_interleave_row( - &data, - row, - output_size.width as usize, - line, - color_convert_func, - ); - }); - - Ok(image) -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/tests/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/tests/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ -extern crate jpeg_decoder as jpeg; -extern crate png; -extern crate walkdir; - -use std::path::Path; -use std::fs::File; - -mod common; -mod crashtest; -mod reftest; - -#[test] -#[cfg(all(target_family="wasm", target_os="unknown"))] -#[wasm_bindgen_test::wasm_bindgen_test] -fn included_file() { - const FILE: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/reftest/images/mozilla/jpg-progressive.jpg")); - - let mut data = FILE; - let mut decoder = jpeg::Decoder::new(&mut data); - let ref_data = decoder.decode().unwrap(); - let ref_info = decoder.info().unwrap(); - - let mut data = FILE; - decoder = jpeg::Decoder::new(&mut data); - decoder.read_info().unwrap(); - let info = decoder.info().unwrap(); - let data = decoder.decode().unwrap(); - - assert_eq!(info, decoder.info().unwrap()); - assert_eq!(info, ref_info); - assert_eq!(data, ref_data); -} - -#[test] -fn read_info() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - let ref_data = decoder.decode().unwrap(); - let ref_info = decoder.info().unwrap(); - - decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.read_info().unwrap(); - let info = decoder.info().unwrap(); - let data = decoder.decode().unwrap(); - - assert_eq!(info, decoder.info().unwrap()); - assert_eq!(info, ref_info); - assert_eq!(data, ref_data); -} - -#[test] -fn read_icc_profile() { - let path = Path::new("tests") - .join("reftest") - .join("images") - .join("mozilla") - .join("jpg-srgb-icc.jpg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile().unwrap(); - // "acsp" is a mandatory string in ICC profile headers. - assert_eq!(&profile[36..40], b"acsp"); -} - -// Test if chunks are concatenated in the correct order -#[test] -fn read_icc_profile_random_order() { - let path = Path::new("tests") - .join("icc") - .join("icc_chunk_order.jpeg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile().unwrap(); - - assert_eq!(profile.len(), 254); - - for i in 1..=254 { - assert_eq!(profile[i - 1], i as u8); - } -} - -// Check if ICC profiles with invalid chunk number 0 are discarded -#[test] -fn read_icc_profile_seq_no_0() { - let path = Path::new("tests") - .join("icc") - .join("icc_chunk_seq_no_0.jpeg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile(); - assert!(profile.is_none()); -} - -// Check if ICC profiles with multiple chunks with the same number are discarded -#[test] -fn read_icc_profile_double_seq_no() { - let path = Path::new("tests") - .join("icc") - .join("icc_chunk_double_seq_no.jpeg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile(); - assert!(profile.is_none()); -} - -// Check if ICC profiles with mismatching number of chunks and total chunk count are discarded -#[test] -fn read_icc_profile_chunk_count_mismatch() { - let path = Path::new("tests") - .join("icc") - .join("icc_chunk_count_mismatch.jpeg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile(); - assert!(profile.is_none()); -} - -// Check if ICC profiles with missing chunk are discarded -#[test] -fn read_icc_profile_missing_chunk() { - let path = Path::new("tests") - .join("icc") - .join("icc_missing_chunk.jpeg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let profile = decoder.icc_profile(); - assert!(profile.is_none()); -} - -#[test] -fn read_exif_data() { - let path = Path::new("tests") - .join("reftest") - .join("images") - .join("ycck.jpg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let exif_data = decoder.exif_data().unwrap(); - // exif data start as a TIFF header - assert_eq!(&exif_data[0..8], b"\x49\x49\x2A\x00\x08\x00\x00\x00"); -} - -#[test] -fn read_xmp_data() { - let path = Path::new("tests") - .join("reftest") - .join("images") - .join("ycck.jpg"); - - let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); - decoder.decode().unwrap(); - - let xmp_data = decoder.xmp_data().unwrap(); - assert_eq!(&xmp_data[0..9], b" = (0..1024) - .map(|_| { - std::thread::spawn(move || { - let mut decoder = Decoder::new(File::open(&path).unwrap()); - let _ = decoder.decode().unwrap(); - }); - }).collect(); -} - diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon.rs clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/jpeg-decoder/tests/rayon.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -use std::{fs::File, path::Path}; -use jpeg_decoder::Decoder; - -#[test] -fn decoding_in_limited_threadpool_does_not_deadlock() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); - - let pool = rayon::ThreadPoolBuilder::new() - .num_threads(1) - .build() - .unwrap(); - pool.install(|| { - let mut decoder = Decoder::new(File::open(&path).unwrap()); - let _ = decoder.decode().unwrap(); - }); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/js-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/js-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/js-sys/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/js-sys/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"ced47935f0bc7bb95d90a38fe37cf78ee6e81cb40635fb556012752dc9583e7a","Cargo.toml":"2f9b98f8fbd0282aa20d8b561257bf2c0f715f537d385d97557bc7629f970448","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"de73c6d7a9d9eac0674770fde362175700676be0dfaee0b22d4c75fdc28b068e","src/Temporal.rs":"6c3745bf5cbfbbaee3fabecd870c50669f7a4f1ee65fc96e2baa8f3e440cfe86","src/lib.rs":"f08573a6871547e8bc457767a547c902aeb9e7cd6a014f27874ab0d4723efafa","tests/headless.js":"dc0fdafb377cd6aa1415897083bbbf3d53c0ca39fc1691cc1f1fa7c528190491","tests/headless.rs":"f9eb68e88cc40fc81b7afad881fbdf2243d574f4417705226aa2102a71187e60","tests/wasm/Array.js":"c21d3d69f388ed4574fa7670c4a41240d0cfa2a374ed29f32f93069983138c72","tests/wasm/Array.rs":"a72124c18addf94bd5a8c96c2f5ee59ba6f387dff404576a5295b52dda96879d","tests/wasm/ArrayBuffer.rs":"a465e7cf7114e7466eb843f6612e22f00eb070dda15759bf8c62a1a3147a8c8d","tests/wasm/ArrayIterator.rs":"d849e50fbb8ebf6979e962c89210cf278176b15198c37f59cb15337e9c30ffa0","tests/wasm/BigInt.rs":"55a8070545f477acea07aebccad1bfd36bac88202923c357f894d6721046f53e","tests/wasm/Boolean.rs":"a7ce23aac1cb7abb83ad92dfaec751cd89f8e5047043667f6cc37d36bbd8cfc3","tests/wasm/DataView.rs":"31c672e3771a9ab17da801c8cd83650d7c1dd8598bb42fbcb78ea42ad5ab8c77","tests/wasm/Date.rs":"4de15246207a5f4c961f448dd18c743aa4ae45950571c9e4ec948272677bf584","tests/wasm/Error.rs":"3d593bdce1dee56fa2c35c290d499d687cc7f08971f89f7aa5f9b52d73af1546","tests/wasm/EvalError.rs":"638641bdd06bb43cffee89d37cd39ee615fe98d44d4c8278756a798a6593111f","tests/wasm/Function.js":"6c5876f74cf2838823470c4c007089baa17e2b28e4f602b65a4b2bc67073b9d7","tests/wasm/Function.rs":"2ccfd94e301b569d70face86d31843d095380973673a811302fb67d8d58378fe","tests/wasm/Generator.js":"7be85b1acbc2de5c3d9d8d64a396baf8c5a5b111905759315b3b395a22ea49e2","tests/wasm/Generator.rs":"860e51ccd01a06076b713445a2eff27244f5b349211a322aa9e3e8df2e76c8ce","tests/wasm/Intl.rs":"93ffd147882daca4f482aaa6d18d013c854dfd0bd3d7631e6128c91e88612cc2","tests/wasm/Iterator.js":"525d29257a508e0cfcf4aa01dddd522d1dda6f8f968f271802ebd703e6f347d6","tests/wasm/Iterator.rs":"b2ac023d150179c0c3cd54f27f9b2775f62ad519111dc233e9ebbad5e9983193","tests/wasm/JSON.rs":"a8bf63aa9cbc64448ad320d88224f435cd2980f980b1c0da3ff1c8c3a935399e","tests/wasm/JsString.js":"931aedd837c316bd7e1e2d52142a92d663e36b79995e2dde6d91c9d762095c13","tests/wasm/JsString.rs":"6aa441665ee43d84b13ec0b021d4544b5b0bdbe2cee2329cfb8a00770964390b","tests/wasm/Map.rs":"022b4c26387190e36726b493615f9852ce40ed0c86a97db85bcf06e9086925f2","tests/wasm/MapIterator.rs":"ed0405dbc9a74885fc3c3614d08d5b7c9da2ad14e4b8d3c5f392ad03e12c61cc","tests/wasm/Math.rs":"0604f28481ac122ee88a5198c2b4f234e3f25e266f73c8e455973d486bcf4768","tests/wasm/Number.js":"a0b161084686deee75588a01834dea2bc12fde317d96bd3a0b73c825db71180f","tests/wasm/Number.rs":"aa97c60d5b6b35ec0679053510e7eb9a240ea2b9d801f03b3ddf89acaf616b7f","tests/wasm/Object.js":"a8ab74505388012de784b2f62f00a57058632e02a3e4bf70f33fa0e5332ff384","tests/wasm/Object.rs":"c8010cd257ba0a49dc864936104cb19c59f9e7801f5b296d909b772aa1f29fb3","tests/wasm/Promise.rs":"8c62a5c08cb43c60391f94e2d697d8925ba47069e19318a30fa64062ef372c8b","tests/wasm/Proxy.js":"63baac7050190339ed772fed09e4bd1845f34bcc36d7aa40ab2ecf93e9db786a","tests/wasm/Proxy.rs":"02d5ec8e5b781e12cdd96b38e643a4d0f6b725c0c904cc614bc83d829d501035","tests/wasm/RangeError.rs":"00a75d29880f53704c1ede81fb0f5c80efa8528a7c9f75b9f64d25234f74c3a4","tests/wasm/ReferenceError.rs":"47b60df993231f4631de2b9317bc1ac0a968976747f05d9b655dc61bcf2a58b4","tests/wasm/Reflect.js":"e5c43d410802ed45f38bffe60d0313dfcb978ac29a748258e889fbb3efa6d64a","tests/wasm/Reflect.rs":"f8bd8876b6bc1740652d51b6bad948eac7eb49541a08e2fe32a85043f9e0aa65","tests/wasm/RegExp.rs":"f91a9c838921832299185582900df6132dd5263fdcce4cc5342b6a1575d727b7","tests/wasm/Set.rs":"ccd68d9240f52d5129169f999a2d782c29c3e00d77f47521c9c4c3158d4f41cd","tests/wasm/SetIterator.rs":"0ad63f4852adcd91a40ffc1d95bb269e23bc338666acdc85a9516c492d5e1561","tests/wasm/SharedArrayBuffer.js":"6d30cec14dfc5890c8303cd1b81da235bce8a37d730232fc8b0d050f0e1db1b2","tests/wasm/SharedArrayBuffer.rs":"fadefea98f3c61aa5ab04f7f5f182a5f73c3436da39c35e9b48e95e7f57a5100","tests/wasm/Symbol.js":"76c6c15f9fd34ffb7efddc90e898e12be074e9c98e066076a2b46f0554754de2","tests/wasm/Symbol.rs":"ae91d396b867bdfd9fd0c66b8863fb8e5c569886eeec98ae6cbd0ffad1a952a8","tests/wasm/SyntaxError.rs":"526ae9168f4979594e9d44f456e6b2816e38860ebf5937c2c905577aae5be7c0","tests/wasm/Temporal.js":"83312c76bdaa0893b7a6d638ccedb5a3d35f9beeb36977e608a739a81a2f4460","tests/wasm/Temporal.rs":"36423a29a94c0d1a218fe2f34384ddb5ec30c8a812ce8a4635579f0d61496b17","tests/wasm/TypeError.rs":"618530b6556daad348106bd1c48c6dd808f54fe4efb344b15238db4ec3254d9f","tests/wasm/TypedArray.rs":"daaa2eb6336ad3868db6cc27846f2c1c7bac542585236efaee23defb20818002","tests/wasm/UriError.rs":"2e695b4823e8875aa72c41aa6679e4d3f924adf47b763cb4462cf96ecdacfda6","tests/wasm/WeakMap.rs":"930498b116924eda0d40ea11c73adbfc049ffd0f11e259f1faf29e090eeea853","tests/wasm/WeakSet.rs":"59c80b6ac0f60fe8499884ee4842b8a4f12039c6c29c58a329e85c187d42c94c","tests/wasm/WebAssembly.js":"5870c3811c8c17bab0b0e14c5ed62af987b8fa52382572a27cf704cded30f061","tests/wasm/WebAssembly.rs":"7d1ed7efb9fc8d052eea2c589a5f3e22f93933c67987b312bbf7eeac0a3afa43","tests/wasm/global_fns.rs":"34e12bfd548b8710297087920599d97e31971d142a8b0c4acb5712f71f1213d3","tests/wasm/main.rs":"e07b9a62897df33dba3d0962f403b19574d5cd99cd2e08e316be364c7a73d7e7"},"package":"29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"} \ No newline at end of file +{"files":{"CHANGELOG.md":"ced47935f0bc7bb95d90a38fe37cf78ee6e81cb40635fb556012752dc9583e7a","Cargo.toml":"2f9b98f8fbd0282aa20d8b561257bf2c0f715f537d385d97557bc7629f970448","Cargo.toml.orig":"9bcf95dcd930e301f898113c7a932031d2d47531f5c8afb7a7d5f37f5fafba22","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"de73c6d7a9d9eac0674770fde362175700676be0dfaee0b22d4c75fdc28b068e","src/Temporal.rs":"6c3745bf5cbfbbaee3fabecd870c50669f7a4f1ee65fc96e2baa8f3e440cfe86","src/lib.rs":"f08573a6871547e8bc457767a547c902aeb9e7cd6a014f27874ab0d4723efafa","tests/headless.js":"dc0fdafb377cd6aa1415897083bbbf3d53c0ca39fc1691cc1f1fa7c528190491","tests/headless.rs":"f9eb68e88cc40fc81b7afad881fbdf2243d574f4417705226aa2102a71187e60","tests/wasm/Array.js":"c21d3d69f388ed4574fa7670c4a41240d0cfa2a374ed29f32f93069983138c72","tests/wasm/Array.rs":"a72124c18addf94bd5a8c96c2f5ee59ba6f387dff404576a5295b52dda96879d","tests/wasm/ArrayBuffer.rs":"a465e7cf7114e7466eb843f6612e22f00eb070dda15759bf8c62a1a3147a8c8d","tests/wasm/ArrayIterator.rs":"d849e50fbb8ebf6979e962c89210cf278176b15198c37f59cb15337e9c30ffa0","tests/wasm/BigInt.rs":"55a8070545f477acea07aebccad1bfd36bac88202923c357f894d6721046f53e","tests/wasm/Boolean.rs":"a7ce23aac1cb7abb83ad92dfaec751cd89f8e5047043667f6cc37d36bbd8cfc3","tests/wasm/DataView.rs":"31c672e3771a9ab17da801c8cd83650d7c1dd8598bb42fbcb78ea42ad5ab8c77","tests/wasm/Date.rs":"4de15246207a5f4c961f448dd18c743aa4ae45950571c9e4ec948272677bf584","tests/wasm/Error.rs":"3d593bdce1dee56fa2c35c290d499d687cc7f08971f89f7aa5f9b52d73af1546","tests/wasm/EvalError.rs":"638641bdd06bb43cffee89d37cd39ee615fe98d44d4c8278756a798a6593111f","tests/wasm/Function.js":"6c5876f74cf2838823470c4c007089baa17e2b28e4f602b65a4b2bc67073b9d7","tests/wasm/Function.rs":"2ccfd94e301b569d70face86d31843d095380973673a811302fb67d8d58378fe","tests/wasm/Generator.js":"7be85b1acbc2de5c3d9d8d64a396baf8c5a5b111905759315b3b395a22ea49e2","tests/wasm/Generator.rs":"860e51ccd01a06076b713445a2eff27244f5b349211a322aa9e3e8df2e76c8ce","tests/wasm/Intl.rs":"93ffd147882daca4f482aaa6d18d013c854dfd0bd3d7631e6128c91e88612cc2","tests/wasm/Iterator.js":"525d29257a508e0cfcf4aa01dddd522d1dda6f8f968f271802ebd703e6f347d6","tests/wasm/Iterator.rs":"b2ac023d150179c0c3cd54f27f9b2775f62ad519111dc233e9ebbad5e9983193","tests/wasm/JSON.rs":"a8bf63aa9cbc64448ad320d88224f435cd2980f980b1c0da3ff1c8c3a935399e","tests/wasm/JsString.js":"931aedd837c316bd7e1e2d52142a92d663e36b79995e2dde6d91c9d762095c13","tests/wasm/JsString.rs":"6aa441665ee43d84b13ec0b021d4544b5b0bdbe2cee2329cfb8a00770964390b","tests/wasm/Map.rs":"022b4c26387190e36726b493615f9852ce40ed0c86a97db85bcf06e9086925f2","tests/wasm/MapIterator.rs":"ed0405dbc9a74885fc3c3614d08d5b7c9da2ad14e4b8d3c5f392ad03e12c61cc","tests/wasm/Math.rs":"0604f28481ac122ee88a5198c2b4f234e3f25e266f73c8e455973d486bcf4768","tests/wasm/Number.js":"a0b161084686deee75588a01834dea2bc12fde317d96bd3a0b73c825db71180f","tests/wasm/Number.rs":"aa97c60d5b6b35ec0679053510e7eb9a240ea2b9d801f03b3ddf89acaf616b7f","tests/wasm/Object.js":"a8ab74505388012de784b2f62f00a57058632e02a3e4bf70f33fa0e5332ff384","tests/wasm/Object.rs":"c8010cd257ba0a49dc864936104cb19c59f9e7801f5b296d909b772aa1f29fb3","tests/wasm/Promise.rs":"8c62a5c08cb43c60391f94e2d697d8925ba47069e19318a30fa64062ef372c8b","tests/wasm/Proxy.js":"63baac7050190339ed772fed09e4bd1845f34bcc36d7aa40ab2ecf93e9db786a","tests/wasm/Proxy.rs":"02d5ec8e5b781e12cdd96b38e643a4d0f6b725c0c904cc614bc83d829d501035","tests/wasm/RangeError.rs":"00a75d29880f53704c1ede81fb0f5c80efa8528a7c9f75b9f64d25234f74c3a4","tests/wasm/ReferenceError.rs":"47b60df993231f4631de2b9317bc1ac0a968976747f05d9b655dc61bcf2a58b4","tests/wasm/Reflect.js":"e5c43d410802ed45f38bffe60d0313dfcb978ac29a748258e889fbb3efa6d64a","tests/wasm/Reflect.rs":"f8bd8876b6bc1740652d51b6bad948eac7eb49541a08e2fe32a85043f9e0aa65","tests/wasm/RegExp.rs":"f91a9c838921832299185582900df6132dd5263fdcce4cc5342b6a1575d727b7","tests/wasm/Set.rs":"ccd68d9240f52d5129169f999a2d782c29c3e00d77f47521c9c4c3158d4f41cd","tests/wasm/SetIterator.rs":"0ad63f4852adcd91a40ffc1d95bb269e23bc338666acdc85a9516c492d5e1561","tests/wasm/SharedArrayBuffer.js":"6d30cec14dfc5890c8303cd1b81da235bce8a37d730232fc8b0d050f0e1db1b2","tests/wasm/SharedArrayBuffer.rs":"fadefea98f3c61aa5ab04f7f5f182a5f73c3436da39c35e9b48e95e7f57a5100","tests/wasm/Symbol.js":"76c6c15f9fd34ffb7efddc90e898e12be074e9c98e066076a2b46f0554754de2","tests/wasm/Symbol.rs":"ae91d396b867bdfd9fd0c66b8863fb8e5c569886eeec98ae6cbd0ffad1a952a8","tests/wasm/SyntaxError.rs":"526ae9168f4979594e9d44f456e6b2816e38860ebf5937c2c905577aae5be7c0","tests/wasm/Temporal.js":"83312c76bdaa0893b7a6d638ccedb5a3d35f9beeb36977e608a739a81a2f4460","tests/wasm/Temporal.rs":"36423a29a94c0d1a218fe2f34384ddb5ec30c8a812ce8a4635579f0d61496b17","tests/wasm/TypeError.rs":"618530b6556daad348106bd1c48c6dd808f54fe4efb344b15238db4ec3254d9f","tests/wasm/TypedArray.rs":"daaa2eb6336ad3868db6cc27846f2c1c7bac542585236efaee23defb20818002","tests/wasm/UriError.rs":"2e695b4823e8875aa72c41aa6679e4d3f924adf47b763cb4462cf96ecdacfda6","tests/wasm/WeakMap.rs":"930498b116924eda0d40ea11c73adbfc049ffd0f11e259f1faf29e090eeea853","tests/wasm/WeakSet.rs":"59c80b6ac0f60fe8499884ee4842b8a4f12039c6c29c58a329e85c187d42c94c","tests/wasm/WebAssembly.js":"5870c3811c8c17bab0b0e14c5ed62af987b8fa52382572a27cf704cded30f061","tests/wasm/WebAssembly.rs":"7d1ed7efb9fc8d052eea2c589a5f3e22f93933c67987b312bbf7eeac0a3afa43","tests/wasm/global_fns.rs":"34e12bfd548b8710297087920599d97e31971d142a8b0c4acb5712f71f1213d3","tests/wasm/main.rs":"e07b9a62897df33dba3d0962f403b19574d5cd99cd2e08e316be364c7a73d7e7"},"package":"29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/js-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/js-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/js-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/js-sys/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "js-sys" +version = "0.3.69" +authors = ["The wasm-bindgen Developers"] +readme = "./README.md" +categories = ["wasm"] +repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys" +homepage = "https://rustwasm.github.io/wasm-bindgen/" +documentation = "https://docs.rs/js-sys" +description = """ +Bindings for all JS global objects and functions in all JS environments like +Node.js and browsers, built on `#[wasm_bindgen]` using the `wasm-bindgen` crate. +""" +license = "MIT OR Apache-2.0" +edition = "2018" +rust-version = "1.57" + +[lib] +test = false +doctest = false + +[dependencies] +wasm-bindgen = { path = "../..", version = "0.2.92" } + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = { path = '../test', version = '=0.3.42' } +wasm-bindgen-futures = { path = '../futures', version = '0.4.42' } +web-sys = { path = "../web-sys", version = "0.3.69", features = ["Headers", "Response", "ResponseInit"] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"05e37a4e63dc4a495998bb5133252a51d671c4e99061a6342089ed6eab43978a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"e2effacb5bbd7c01523f9a9e4a6a59c0f9b8698753b210fec5742408498197df","src/core_lazy.rs":"6b9fb6a4f553058e240756125b6b9ca43a83ed1fb72964343038ea0ea2e1af10","src/inline_lazy.rs":"f6184afbca4b477616f270790edc180263be806aa92ef0a9de681b4aac9e88c4","src/lib.rs":"99096a5d3089c0d86646f0805d1455befe2cb09683704af29c5c9d99ecab2683","tests/no_std.rs":"d68b149ee51ef5ae2b2906c0c94f5a9812d3b02811b13365c5a35e2ef90d25cf","tests/test.rs":"b3f7d805375dc5af7a2aa4b869944ad2ab4fc982b35ad718ea58f6914dc0a698"},"package":"e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"d7c54c472631d968eaaedcd54589acf63ac40101d1c0b98dcec38771c5e5f027","Cargo.toml":"05e37a4e63dc4a495998bb5133252a51d671c4e99061a6342089ed6eab43978a","Cargo.toml.orig":"8c79fc616944dae6ddf0af733443cc8ef3ca7cfde7b90db3a350abde745497fd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"e2effacb5bbd7c01523f9a9e4a6a59c0f9b8698753b210fec5742408498197df","src/core_lazy.rs":"6b9fb6a4f553058e240756125b6b9ca43a83ed1fb72964343038ea0ea2e1af10","src/inline_lazy.rs":"f6184afbca4b477616f270790edc180263be806aa92ef0a9de681b4aac9e88c4","src/lib.rs":"99096a5d3089c0d86646f0805d1455befe2cb09683704af29c5c9d99ecab2683","tests/no_std.rs":"d68b149ee51ef5ae2b2906c0c94f5a9812d3b02811b13365c5a35e2ef90d25cf","tests/test.rs":"b3f7d805375dc5af7a2aa4b869944ad2ab4fc982b35ad718ea58f6914dc0a698"},"package":"e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "421669662b35fcb455f2902daed2e20bbbba79b6" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/lazy_static/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazy_static/Cargo.toml.orig 2019-08-26 00:54:26.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +name = "lazy_static" +# NB: When modifying, also modify html_root_url in lib.rs +version = "1.4.0" +authors = ["Marvin Löbel "] +license = "MIT/Apache-2.0" + +description = "A macro for declaring lazily evaluated statics in Rust." +readme = "README.md" +documentation = "https://docs.rs/lazy_static" + +repository = "https://github.com/rust-lang-nursery/lazy-static.rs" +keywords = ["macro", "lazy", "static"] +categories = [ "no-std", "rust-patterns", "memory-management" ] +exclude = ["/.travis.yml", "/appveyor.yml"] + +[dependencies.spin] +version = "0.5.0" +optional = true + +[features] +spin_no_std = ["spin"] + +[dev-dependencies] +doc-comment = "0.3.1" + +[badges] +appveyor = { repository = "rust-lang-nursery/lazy-static.rs" } +travis-ci = { repository = "rust-lang-nursery/lazy-static.rs" } + +is-it-maintained-issue-resolution = { repository = "rust-lang-nursery/lazy-static.rs" } +is-it-maintained-open-issues = { repository = "rust-lang-nursery/lazy-static.rs" } + +maintenance = { status = "passively-maintained" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazycell/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/lazycell/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"54036052985525a153f9e6c9dda6a143b7494a477908fb28f5705f92dd387059","Cargo.toml":"79f5da117603f75361b9a7309f102a9ab70b66d5c1c269a30f66fdea58ccc657","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"03f6ccb4e6040abccf12b31551bbbd1800a5069a17950bbd6db850d85744800f","README.md":"26e4440387d4fc898f377eb5394f3432f8625ed8aa46e02ffb61aac8b2032967","src/lib.rs":"3fcef569bd4feb760925e34aef0e66739a0827cbc1b26ae033f57e322c3a2515","src/serde_impl.rs":"4903fb722748e91bdc4b481c7f3309e79e962f75c9717e7e13edcccd0242a52d"},"package":"830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"675899157e670f9255f66a51dd82d9da6d102ec7e94801bd9d7645af80184412","CHANGELOG.md":"54036052985525a153f9e6c9dda6a143b7494a477908fb28f5705f92dd387059","Cargo.toml":"79f5da117603f75361b9a7309f102a9ab70b66d5c1c269a30f66fdea58ccc657","Cargo.toml.orig":"a79c778e1f766defb6a3cd72d293bd769ae60fa2fcf1c2fcf64a636c6f2e492c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"03f6ccb4e6040abccf12b31551bbbd1800a5069a17950bbd6db850d85744800f","README.md":"26e4440387d4fc898f377eb5394f3432f8625ed8aa46e02ffb61aac8b2032967","src/lib.rs":"3fcef569bd4feb760925e34aef0e66739a0827cbc1b26ae033f57e322c3a2515","src/serde_impl.rs":"4903fb722748e91bdc4b481c7f3309e79e962f75c9717e7e13edcccd0242a52d"},"package":"830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazycell/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/lazycell/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazycell/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "b78f3f10c0d005b81d97011fd7f98fc3cdff5982" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lazycell/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/lazycell/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/lazycell/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lazycell/Cargo.toml.orig 2020-08-12 01:08:17.000000000 +0000 @@ -0,0 +1,27 @@ +[package] +name = "lazycell" +version = "1.3.0" +authors = ["Alex Crichton ", + "Nikita Pekin "] +description = "A library providing a lazily filled Cell struct" +repository = "https://github.com/indiv0/lazycell" +documentation = "http://indiv0.github.io/lazycell/lazycell/" +readme = "README.md" +keywords = ["lazycell", "lazy", "cell", "library"] +license = "MIT/Apache-2.0" +include = [ + "CHANGELOG.md", + "Cargo.toml", + "LICENSE-MIT", + "LICENSE-APACHE", + "README.md", + "src/**/*.rs", +] + +[dependencies] +clippy = { version = "0.0", optional = true } +serde = { version = "^1", optional = true } + +[features] +nightly = [] +nightly-testing = ["clippy", "nightly"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lebe/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/lebe/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"365b393a87b2706f0eb52139c1ce3909e47ca4e1226cf7bdcae4e4c1d0f386b5","LICENSE-BSD-3-Clause":"f1b2855ae21da69e0a02499e13f57f3be92db7abbbffe9a89f33e04e9e21ec81","README.md":"d9f3a595b28433de13f0c88ae049a73af3d88068f08dd8364d45504224651448","benches/benches.rs":"a73feca65ddde13e082121cc2268318fc72a87029f2d7106f939a4356af3e232","src/lib.rs":"72567c8ad6ae8e59d59ce2e9ffcfa8f013bb24f104b128d92a52f034f592b777","tests/tests.rs":"76b860f51bef80c4223f06998fbed540d9bcd0ddc4fa1ed0f0c0964e3d58bdcc"},"package":"03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3718d92767415279f2b4f3b4bc30f614ce70e661eb2a1f643bc555d1f88eb12c",".github/workflows/rust.yml":"bbc292d2de331b5c9836f16246e15dacd8002709ed396148e6a31beade28f900","Cargo.toml":"365b393a87b2706f0eb52139c1ce3909e47ca4e1226cf7bdcae4e4c1d0f386b5","Cargo.toml.orig":"64b02e6a3cd5effad6ed87ec61125b96522f558c605feb090b700e6461fbac39","LICENSE-BSD-3-Clause":"f1b2855ae21da69e0a02499e13f57f3be92db7abbbffe9a89f33e04e9e21ec81","README.md":"d9f3a595b28433de13f0c88ae049a73af3d88068f08dd8364d45504224651448","benches/benches.rs":"a73feca65ddde13e082121cc2268318fc72a87029f2d7106f939a4356af3e232","src/lib.rs":"72567c8ad6ae8e59d59ce2e9ffcfa8f013bb24f104b128d92a52f034f592b777","tests/tests.rs":"76b860f51bef80c4223f06998fbed540d9bcd0ddc4fa1ed0f0c0964e3d58bdcc"},"package":"03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lebe/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/lebe/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lebe/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "65f45436514fadcdee8b1b1ddb59b402cbe293eb" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lebe/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/lebe/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/lebe/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lebe/.github/workflows/rust.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lebe/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/lebe/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/lebe/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lebe/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,42 @@ +[package] +name = "lebe" +version = "0.5.2" +authors = ["johannesvollmer "] +edition = "2018" + +description = "Tiny, dead simple, high performance endianness conversions with a generic API" +repository = "https://github.com/johannesvollmer/lebe" +documentation = "https://docs.rs/crate/lebe/" +readme = "README.md" +license = "BSD-3-Clause" +keywords = ["endianness", "binary", "io", "byteorder", "endian"] +categories = ["encoding", "filesystem", "algorithms"] + +[lib] +path = "src/lib.rs" +test = true +doctest = true +bench = true +doc = true +plugin = false +proc-macro = false + + +[badges] +maintenance = { status = "actively-developed" } + +[features] +# simd = [] + +[dev-dependencies] +bencher = "0.1.5" +byteorder = "1.4.3" + +[[bench]] +name = "benches" +harness = false + +[profile.bench] +lto = true +debug = true + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/libc/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"a93fcda0a76e1975fcfb0aa2ba00c9b1864f9ae6062704a294d81a3688898e10","Cargo.toml":"a4fd0b57f9e9365869b9c6030ffa4ca30d84c43deda5883aa5a58d8775877ff9","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"4da2919bb509f3f06163778478494f780ca6627cb79ccab5d2c828c8d88dc133","build.rs":"c26a84b1e50468025002c5e7201b9c104e7e7aec167def54f811b68c0e94a644","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"893fcec48142d273063ffd814dca33fbec92205fd39ada97075f85201d803996","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"07410f511835da540e5bdc55f7384c71cd7836fe63bbca6be547de825f823c03","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/riscv64.rs":"617cd75e79e0e20f664db764a4dc2a396d9fd11a4d95371acd91ed4811293b11","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"2d04cfa0d55dc0a2e36fdc4a45819b9d3722af19bb1932778b44feb4c2f81036","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"9d7030ba3e21064a0f3a8e79927c70d5a95a0026be61be084f3ab021e243e503","src/macros.rs":"5f985b3de7b18833f866bf832b8ffb0430f0f70aa9a468b6a2c855c1bf9d33e4","src/psp.rs":"0a7d5121a8cc2903009f586c00e4ae2d6126d24eb90531dafaba6f59823aa6b2","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/teeos/mod.rs":"eb664b3e94bcd44d8c8147b56c2187139d01bf8402ee0bb81967a5a50a3e927f","src/unix/aix/mod.rs":"a1ed0ae0164eb783297e185908f6c61c67d5ac82d4f6ab9c559c4d7e0fea51c3","src/unix/aix/powerpc64.rs":"cf374d81139d45f9d77c6a764f640bfbf7e0a5903689652c8296f8e10d55169b","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/long_array.rs":"3cf1f19b812e6d093c819dc65ce55b13491963e0780eda0d0bd1577603e81948","src/unix/bsd/apple/mod.rs":"e8ed82a15cc3a21337894a123bf8d3cbc9b176224a6709bf6b602a266ff97651","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"2777f94909a798df1b8030fb86d02e2118d0ac3e49e9a542df54a569ca5ae2f9","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"e243ae0e89623d4fa9f85afe14369cc5fd5f2028ea715773dbec722ba80dac1f","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"bef9fae288a4f29e941ea369be1cd20b170040e60665a4d49a4a9e79009b72d8","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"88be47524b28b6635ccb1e85ea511bf17337be0af7e9baa740c341ac9e83a6f7","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"6ddc6abf6d5ccaea0d8cccf521e8ca6457efcad3086af4155628d5d06d672346","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs":"93115c1a9faa43ebf58b7dee3582aed5a54291b284764e370e7f649b2e6a9565","src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/mod.rs":"9fb4dd76676d9a91cf1e10e48dad2f010c03bb40ee3c1da863a98b7a2245d4cb","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"6766e2ce85e187b306cd3b0b8d7e15b8f4042c5cff81d89b3af69ecc99c70ab0","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"dca41da072ffb96ba9fd96cefdf629937284a850dd933949cb7f7c5930f3ac54","src/unix/bsd/mod.rs":"1cd730c416c4a00457e5e159ef7d3631966ac5326e15c7a853e03c7d66a90307","src/unix/bsd/netbsdlike/mod.rs":"ea60540aa4edd4e43136749d5df497b1dc072b9912b6030dd1ab794a6d1c3c3c","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"057ee877db7193ba0dc10801b9a6563ac6dbdb78376d6851a84cb12b30841759","src/unix/bsd/netbsdlike/netbsd/arm.rs":"949b55e4dee1c8c511f4f061a6a57ac876a6c0eabfaf5cc20e9ab40d8f41b2e0","src/unix/bsd/netbsdlike/netbsd/mips.rs":"88be18ac43ba224c77e78e4179b6761debc5e6c30a258fac56263809c7af4fbc","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b8d6f089fc8eb2cb59e45335a26c9ce871b846216c9859b553c6b91982f8de33","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/riscv64.rs":"1cbe2e5ed681cb1054b699da37daaf6c714267df7d332c90fc2a589b11579625","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"532b76199d6c71ff996eade9f906c55a72c9aff489595d25a21e21878cfd740b","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"7b93b5b24b3c72a79b2de19b47ac2f56b29d87e9fc8f4c721a63d1e87ec83fcc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1fe3332dc705a13e6242219970f5449d6d7a73e2e6c8537ab8e421d8a6f2e3ff","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"a97c51465d706e0dea8a7e2850d927c4ed78a7aa6603468d8b8df59ae1f2d296","src/unix/haiku/native.rs":"3bbf42c3e3e437e8b626be67c72b6adcec60646eb5dd4bf8471a603cbbb5e5a4","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hurd/align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/hurd/b32.rs":"2ba90ed973f90366c36a6387833a3df42abfee9622d4a0352635937d4a89eaf4","src/unix/hurd/b64.rs":"d919b4aec9b3080ad24c125c57b2c8b2e483d72045f1554c429d14560355846f","src/unix/hurd/mod.rs":"6a2f0db80a3cd34b55ef82e357da4d453d5d190a2dd4501bfa5d0bb9bca0de4f","src/unix/hurd/no_align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/linux_like/android/b32/arm.rs":"ce582de7e983a33d3bfad13075c53aac9016cee35f06ad8653ee9072c3ec2564","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"e6d107efbcd37b5b85dfa18f683300cbf768ffa0237997a9fa52b184a53323ac","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"873af67c4a9757ead56bc797d04efcecd311ecbf0084ebdd198fb690463ef299","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"19d4bf2237c47127eba9144e0b82e995bc079315e719179a91813b0ae7b0e49d","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"4ec2de11a9b65c4325b7b991f0b99a414975e0e61ba8668caca5d921e9b314d1","src/unix/linux_like/android/mod.rs":"d68feed235b945ff6e32a8d5c8b659b04966f42a7a77722b454dce2b54561cbd","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/lfs64.rs":"3776af30a758d765a88920ec4fde442ab89040da13d3b3625c7fbcb8a958559f","src/unix/linux_like/emscripten/mod.rs":"70d4591730a731ee32788a9d8d2de379592844ec36b7d1723514179605587713","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"bc5abcd38e2320171e0981e773c9c5fe3e0d5a66fdff049228f6a1acad80ef8b","src/unix/linux_like/linux/arch/generic/mod.rs":"3ab533349696d24505adb6bb9183d73fd5e3b17e2f90dd21478af2a47b4d6fa8","src/unix/linux_like/linux/arch/mips/mod.rs":"ca3db0e3ae852abf18f3588e40d5d64707fcc1829e08ddc5da1080e1a92c8851","src/unix/linux_like/linux/arch/mod.rs":"5bd5361f8a6ab4e18bbba6da9f92c164ae252b15a0ed10064812544aa1fdf198","src/unix/linux_like/linux/arch/powerpc/mod.rs":"0bc2d2667a00eca81f4abeb6d613a90848a947f51224103f83268928b8197629","src/unix/linux_like/linux/arch/sparc/mod.rs":"5e6777863e74a9e2aa9dc487f1059783dd211babc2b32d6bf676f311e49c55d6","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"f68ec59b6407f9d4e326f3e71a41ec21f19ecfc703edf9a93e496f661fed5506","src/unix/linux_like/linux/gnu/b32/csky/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/csky/mod.rs":"8729b68e433e94c2128e51a7db4fd555938e4be4dc64584c352b24a20d9c8e91","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"80956d3fef163ecf248828a6f38782dd8ae856d86b1bb5aac2de36032dbd8ea0","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"96e22350d5d132d917c743d6560464500652c67b52c3d0e8474494487df3365d","src/unix/linux_like/linux/gnu/b32/mod.rs":"b56625dd20dd48a8699034d349ef089c540c0ddcbf8a3481d598d101f8b40b78","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"20fc3cc4fe1ef6617b63b61b897f782ceb9c2842fc718f504a1840537229bf47","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"887288a0a1cfff319d0e15edcdc4fcb31fd643ff41715ec5244c8f2413624169","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"cc4342b949e4d796f304acd9dfe3f721a1c2f37fec16b42d3bb27dc94723af37","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"06d4db4ee8352f62a0a5ead0c4d6ea0a78feff522f19b9bc5772f6dd920ffd80","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"fdf1c72375a2167699157e0dd825422690bb6719f7bc69515a2e5846d0431d7c","src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs":"832e7487249c1c0bb6e9911ce3f7d32ca22378e42392ab83c56915cbc59d8be3","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"bf4611b737813deef6787babf6c01698605f3b75482269b8546318667bc68e29","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"11a950697fdda0258c6e37c6b13993348c8de4134105ed4faa79358e53175072","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"8202614484da36c388d2ffdd2554c56bb4f9db8e5bd621f8c36114cdcfeec644","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"10f025edecebc6e0ed8fdae4736ebe7564189741d5b910433f07c21fc12a94d8","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"73532be4b5775acf9524c77feeefe1f6d1936ceffef908d01dd2586986520f2d","src/unix/linux_like/linux/gnu/b64/mod.rs":"6a160ef25439c4fecdb0e3bd0b818742263c791364da874d4febd3aa644ec8e2","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a90c2641616c620e9d1fea87695ce046e14f9da2282bb93f761eeb4077c74741","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"dec86883731f7b8419bff35b125b40eefc927090c1510f6daf931726f7965c0b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"1ea9e39432ce6bf68779d33546dacd7d39477a9f8fc3da4f4f339e4538cb74c3","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"bed381c44cec2a5b50125f7e548ab487d4c829006c971d152a611b7141760052","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"332846e4a5920d7e6b05df0448a2333c5dd00fb27cb33654648f507ee89dbec5","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"38f74ce15d9662ce4818815a2b87be1618d5e45f190f7e4db84ff3285b4421fb","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"b20218a11364a6dec87f96d6c0d8b19e660697ab09ad5ee0e9b3a9dafedaaebb","src/unix/linux_like/linux/gnu/mod.rs":"78ce3d4fe6dcb9dc90210526023a1421502e341a7c39d769fd385001c1eb3b8d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"efdc36b0e95a87b45093756e766cded003bac6fbd9493cd1af158f7476b2d3e2","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"af10147d7c3661751750a58ffad089d5d18d180cd18303c653aef126c07ccd91","src/unix/linux_like/linux/musl/b32/hexagon.rs":"d079cab42529f7dab699334d43168c74ff4aa0282f11040a8b7d274b65767a7a","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"e44043766f7cd26de7ffa4232654afb6feb03e58dbd5890717970887bd003151","src/unix/linux_like/linux/musl/b32/mod.rs":"31677597fd9544c4b1ec1477628288f6273fabbc06e38f33da862ad55f019ce1","src/unix/linux_like/linux/musl/b32/powerpc.rs":"3dae56a4e7789bcc5314e419fea5e4b2495367b4f1a49d1c9477c60225d65eef","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"3ee845d272f91a1908d5f421d7c353e1f14681bbdfef64410e408f4c14365a91","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"f2b53ae0034c833244b7cdb8c670349bf8272a03abf04152eba65cf62810484d","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"45ce6897afcc960267bb7505702b639daf94dc69428a213bf1aefd367ca32adc","src/unix/linux_like/linux/musl/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs":"3d9ef92e682a1789544a2bd20cad5a5623db9d7d9f5d0a3692bb0230af034165","src/unix/linux_like/linux/musl/b64/mips64.rs":"a968ef9c54fa22293085f318c8472c1754482df92cc500568dc33bd807d71ea6","src/unix/linux_like/linux/musl/b64/mod.rs":"20ceaf90a03c24a2eb154a5dffbfc9a538348404db5b554a3d8126021ba45509","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"140e579800a67315f4cb8a42b22aa8157eae34ffe626e77e421b43c53c23b34d","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"c5944526d7e19cd43e9d14d119a1d98f8780db7ecbcc79e69d7b9348e596b520","src/unix/linux_like/linux/musl/b64/s390x.rs":"8557b3477ca8cefef7fce764a3c25441929a54e50ead4091f6f7823c427cd728","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"a91c4f18027c9958037f78ae48f6352d23cb4e6f2995b2cc8de7dce0e5759470","src/unix/linux_like/linux/musl/lfs64.rs":"3e4fb381f3a0756520bde0f1692d4fa45e4ae8133bf7d7c64b0e3fdd512f235f","src/unix/linux_like/linux/musl/mod.rs":"ac8ccdb25116ecdfa44eacaffefb21329aa286713c44a12dbe2c1614f2a2748a","src/unix/linux_like/linux/no_align.rs":"62cdca0e011937aaf09a51ca86d9f0ee0fdb05f61ec3c058e6a5d5fa6357d784","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"50288ff9e411ab0966da24838f2c2a5618021bc19c422a04f577b2979ef4081e","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d0c4434e2bf813372c418a8f516c706cdccc9f7be2f0921b2207b0afdb66fe81","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"3f38ee6a4690b9d7594be20d216467a34d955f7653c2c8ce1e6147daeb53f1e0","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"a048fce1c2d9b1ad57305642e8ad05ca0f0c7e4753267a2e2d6b4fee5db3b072","src/unix/linux_like/linux/uclibc/mod.rs":"193a03fa4aa5345394e39d2115c9427e806c9f28b0fde685719119e1c90ca08a","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"8485b9182b7c67f7344fab377e7cc2a72afefd9ab63837c860514abba9728d76","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"196d03affbefb85716937c15904831e731eb222ee906e05e42102d639a8152ea","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"863f628cbaa864911ffebc58e9fb788b6c6a9651955fc401ac1f40f20eb62505","src/unix/mod.rs":"e3a98b62b83a1e42675e968c05b2281d612a66cdc09c4e3b4c16921c31a9e254","src/unix/newlib/aarch64/mod.rs":"964c096288da836b53c0c71d7f3a97048d177da220a69314c5ce93ba330d72af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cf754f8b1197489fca01e881a4b4b146e814998e4b365f116fa1a102c00e6a4e","src/unix/newlib/espidf/mod.rs":"689e29a9fff5a263e5ab8410d0a8919f77fa64aa12f4d71f71085a6f07f19f67","src/unix/newlib/generic.rs":"5f0b5d07ddb5a5d60580f9561fdb05e9218d9751d4068c4aadad2ba6b950aabf","src/unix/newlib/horizon/mod.rs":"3a521d22bf932fc01c1d26d1f9bff20f11b1855b03c8236a8eb18310f6cab5a8","src/unix/newlib/mod.rs":"e5d5faf27a6336b9f1c02b8726427801d906a14dae766852b4e85c1a92df06c8","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"cc9e188711b9bf614323ad6c48e0d2e1a1ecc5d3bc64961ba451f29c6c22d2d8","src/unix/newlib/vita/mod.rs":"ff1caf74bb0696fe15d60dbac598db4520cd538aa0f5989713d97d008eee6ad8","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"07268897fc8810f2fed22ab56f87757f71c73ba401abd848bccca6b183a13b02","src/unix/nto/neutrino.rs":"799bff4ab01a6424db6c5a2b76aa5679826d41495f9d13c63485bf13bc80026b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"e75a319975472fe9e0873244fb07c5d2004672b7a4cf7a3cb01532d6d394cb8a","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"3e550d95419169febf094c425451ca86b12821fa17839b4b0ba7520b145a5820","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"4105a2e6a6c9908fc1f2a770ede052bb0d6a5d9d49e32d815f557081efc49860","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"d4147353537d7556076ff1a1c4cb96cc2dae9416a5d176ba8a077ad55ab7ec18","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"9fdc5e1c62c441abef7bc62a7343efb2041edc24db9ac0efc0f74df55b69e249","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","src/xous.rs":"eb0675f25ba01f73072d2b70907fb8abb1148facefe5a20756c49250f3d65fae","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"1d67e314a29c372fa818cdb26ff5bb54633f1b77e6094e10ff76993cdb0cc3ae","CONTRIBUTING.md":"a93fcda0a76e1975fcfb0aa2ba00c9b1864f9ae6062704a294d81a3688898e10","Cargo.toml":"a4fd0b57f9e9365869b9c6030ffa4ca30d84c43deda5883aa5a58d8775877ff9","Cargo.toml.orig":"65b80781556fa70e191be91f13398c6ac5905f175f53fa22820a3cd3d1ad3401","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"4da2919bb509f3f06163778478494f780ca6627cb79ccab5d2c828c8d88dc133","build.rs":"c26a84b1e50468025002c5e7201b9c104e7e7aec167def54f811b68c0e94a644","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"893fcec48142d273063ffd814dca33fbec92205fd39ada97075f85201d803996","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"07410f511835da540e5bdc55f7384c71cd7836fe63bbca6be547de825f823c03","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/riscv64.rs":"617cd75e79e0e20f664db764a4dc2a396d9fd11a4d95371acd91ed4811293b11","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"2d04cfa0d55dc0a2e36fdc4a45819b9d3722af19bb1932778b44feb4c2f81036","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"9d7030ba3e21064a0f3a8e79927c70d5a95a0026be61be084f3ab021e243e503","src/macros.rs":"5f985b3de7b18833f866bf832b8ffb0430f0f70aa9a468b6a2c855c1bf9d33e4","src/psp.rs":"0a7d5121a8cc2903009f586c00e4ae2d6126d24eb90531dafaba6f59823aa6b2","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/teeos/mod.rs":"eb664b3e94bcd44d8c8147b56c2187139d01bf8402ee0bb81967a5a50a3e927f","src/unix/aix/mod.rs":"a1ed0ae0164eb783297e185908f6c61c67d5ac82d4f6ab9c559c4d7e0fea51c3","src/unix/aix/powerpc64.rs":"cf374d81139d45f9d77c6a764f640bfbf7e0a5903689652c8296f8e10d55169b","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/long_array.rs":"3cf1f19b812e6d093c819dc65ce55b13491963e0780eda0d0bd1577603e81948","src/unix/bsd/apple/mod.rs":"e8ed82a15cc3a21337894a123bf8d3cbc9b176224a6709bf6b602a266ff97651","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"2777f94909a798df1b8030fb86d02e2118d0ac3e49e9a542df54a569ca5ae2f9","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"e243ae0e89623d4fa9f85afe14369cc5fd5f2028ea715773dbec722ba80dac1f","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"bef9fae288a4f29e941ea369be1cd20b170040e60665a4d49a4a9e79009b72d8","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"88be47524b28b6635ccb1e85ea511bf17337be0af7e9baa740c341ac9e83a6f7","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"6ddc6abf6d5ccaea0d8cccf521e8ca6457efcad3086af4155628d5d06d672346","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs":"93115c1a9faa43ebf58b7dee3582aed5a54291b284764e370e7f649b2e6a9565","src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/mod.rs":"9fb4dd76676d9a91cf1e10e48dad2f010c03bb40ee3c1da863a98b7a2245d4cb","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"6766e2ce85e187b306cd3b0b8d7e15b8f4042c5cff81d89b3af69ecc99c70ab0","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"dca41da072ffb96ba9fd96cefdf629937284a850dd933949cb7f7c5930f3ac54","src/unix/bsd/mod.rs":"1cd730c416c4a00457e5e159ef7d3631966ac5326e15c7a853e03c7d66a90307","src/unix/bsd/netbsdlike/mod.rs":"ea60540aa4edd4e43136749d5df497b1dc072b9912b6030dd1ab794a6d1c3c3c","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"057ee877db7193ba0dc10801b9a6563ac6dbdb78376d6851a84cb12b30841759","src/unix/bsd/netbsdlike/netbsd/arm.rs":"949b55e4dee1c8c511f4f061a6a57ac876a6c0eabfaf5cc20e9ab40d8f41b2e0","src/unix/bsd/netbsdlike/netbsd/mips.rs":"88be18ac43ba224c77e78e4179b6761debc5e6c30a258fac56263809c7af4fbc","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b8d6f089fc8eb2cb59e45335a26c9ce871b846216c9859b553c6b91982f8de33","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/riscv64.rs":"1cbe2e5ed681cb1054b699da37daaf6c714267df7d332c90fc2a589b11579625","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"532b76199d6c71ff996eade9f906c55a72c9aff489595d25a21e21878cfd740b","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"7b93b5b24b3c72a79b2de19b47ac2f56b29d87e9fc8f4c721a63d1e87ec83fcc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1fe3332dc705a13e6242219970f5449d6d7a73e2e6c8537ab8e421d8a6f2e3ff","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"a97c51465d706e0dea8a7e2850d927c4ed78a7aa6603468d8b8df59ae1f2d296","src/unix/haiku/native.rs":"3bbf42c3e3e437e8b626be67c72b6adcec60646eb5dd4bf8471a603cbbb5e5a4","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hurd/align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/hurd/b32.rs":"2ba90ed973f90366c36a6387833a3df42abfee9622d4a0352635937d4a89eaf4","src/unix/hurd/b64.rs":"d919b4aec9b3080ad24c125c57b2c8b2e483d72045f1554c429d14560355846f","src/unix/hurd/mod.rs":"6a2f0db80a3cd34b55ef82e357da4d453d5d190a2dd4501bfa5d0bb9bca0de4f","src/unix/hurd/no_align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/linux_like/android/b32/arm.rs":"ce582de7e983a33d3bfad13075c53aac9016cee35f06ad8653ee9072c3ec2564","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"e6d107efbcd37b5b85dfa18f683300cbf768ffa0237997a9fa52b184a53323ac","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"873af67c4a9757ead56bc797d04efcecd311ecbf0084ebdd198fb690463ef299","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"19d4bf2237c47127eba9144e0b82e995bc079315e719179a91813b0ae7b0e49d","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"4ec2de11a9b65c4325b7b991f0b99a414975e0e61ba8668caca5d921e9b314d1","src/unix/linux_like/android/mod.rs":"d68feed235b945ff6e32a8d5c8b659b04966f42a7a77722b454dce2b54561cbd","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/lfs64.rs":"3776af30a758d765a88920ec4fde442ab89040da13d3b3625c7fbcb8a958559f","src/unix/linux_like/emscripten/mod.rs":"70d4591730a731ee32788a9d8d2de379592844ec36b7d1723514179605587713","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"bc5abcd38e2320171e0981e773c9c5fe3e0d5a66fdff049228f6a1acad80ef8b","src/unix/linux_like/linux/arch/generic/mod.rs":"3ab533349696d24505adb6bb9183d73fd5e3b17e2f90dd21478af2a47b4d6fa8","src/unix/linux_like/linux/arch/mips/mod.rs":"ca3db0e3ae852abf18f3588e40d5d64707fcc1829e08ddc5da1080e1a92c8851","src/unix/linux_like/linux/arch/mod.rs":"5bd5361f8a6ab4e18bbba6da9f92c164ae252b15a0ed10064812544aa1fdf198","src/unix/linux_like/linux/arch/powerpc/mod.rs":"0bc2d2667a00eca81f4abeb6d613a90848a947f51224103f83268928b8197629","src/unix/linux_like/linux/arch/sparc/mod.rs":"5e6777863e74a9e2aa9dc487f1059783dd211babc2b32d6bf676f311e49c55d6","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"f68ec59b6407f9d4e326f3e71a41ec21f19ecfc703edf9a93e496f661fed5506","src/unix/linux_like/linux/gnu/b32/csky/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/csky/mod.rs":"8729b68e433e94c2128e51a7db4fd555938e4be4dc64584c352b24a20d9c8e91","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"80956d3fef163ecf248828a6f38782dd8ae856d86b1bb5aac2de36032dbd8ea0","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"96e22350d5d132d917c743d6560464500652c67b52c3d0e8474494487df3365d","src/unix/linux_like/linux/gnu/b32/mod.rs":"b56625dd20dd48a8699034d349ef089c540c0ddcbf8a3481d598d101f8b40b78","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"20fc3cc4fe1ef6617b63b61b897f782ceb9c2842fc718f504a1840537229bf47","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"887288a0a1cfff319d0e15edcdc4fcb31fd643ff41715ec5244c8f2413624169","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"cc4342b949e4d796f304acd9dfe3f721a1c2f37fec16b42d3bb27dc94723af37","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"06d4db4ee8352f62a0a5ead0c4d6ea0a78feff522f19b9bc5772f6dd920ffd80","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"fdf1c72375a2167699157e0dd825422690bb6719f7bc69515a2e5846d0431d7c","src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs":"832e7487249c1c0bb6e9911ce3f7d32ca22378e42392ab83c56915cbc59d8be3","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"bf4611b737813deef6787babf6c01698605f3b75482269b8546318667bc68e29","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"11a950697fdda0258c6e37c6b13993348c8de4134105ed4faa79358e53175072","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"8202614484da36c388d2ffdd2554c56bb4f9db8e5bd621f8c36114cdcfeec644","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"10f025edecebc6e0ed8fdae4736ebe7564189741d5b910433f07c21fc12a94d8","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"73532be4b5775acf9524c77feeefe1f6d1936ceffef908d01dd2586986520f2d","src/unix/linux_like/linux/gnu/b64/mod.rs":"6a160ef25439c4fecdb0e3bd0b818742263c791364da874d4febd3aa644ec8e2","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a90c2641616c620e9d1fea87695ce046e14f9da2282bb93f761eeb4077c74741","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"dec86883731f7b8419bff35b125b40eefc927090c1510f6daf931726f7965c0b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"1ea9e39432ce6bf68779d33546dacd7d39477a9f8fc3da4f4f339e4538cb74c3","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"bed381c44cec2a5b50125f7e548ab487d4c829006c971d152a611b7141760052","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"332846e4a5920d7e6b05df0448a2333c5dd00fb27cb33654648f507ee89dbec5","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"38f74ce15d9662ce4818815a2b87be1618d5e45f190f7e4db84ff3285b4421fb","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"b20218a11364a6dec87f96d6c0d8b19e660697ab09ad5ee0e9b3a9dafedaaebb","src/unix/linux_like/linux/gnu/mod.rs":"78ce3d4fe6dcb9dc90210526023a1421502e341a7c39d769fd385001c1eb3b8d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"efdc36b0e95a87b45093756e766cded003bac6fbd9493cd1af158f7476b2d3e2","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"af10147d7c3661751750a58ffad089d5d18d180cd18303c653aef126c07ccd91","src/unix/linux_like/linux/musl/b32/hexagon.rs":"d079cab42529f7dab699334d43168c74ff4aa0282f11040a8b7d274b65767a7a","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"e44043766f7cd26de7ffa4232654afb6feb03e58dbd5890717970887bd003151","src/unix/linux_like/linux/musl/b32/mod.rs":"31677597fd9544c4b1ec1477628288f6273fabbc06e38f33da862ad55f019ce1","src/unix/linux_like/linux/musl/b32/powerpc.rs":"3dae56a4e7789bcc5314e419fea5e4b2495367b4f1a49d1c9477c60225d65eef","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"3ee845d272f91a1908d5f421d7c353e1f14681bbdfef64410e408f4c14365a91","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"f2b53ae0034c833244b7cdb8c670349bf8272a03abf04152eba65cf62810484d","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"45ce6897afcc960267bb7505702b639daf94dc69428a213bf1aefd367ca32adc","src/unix/linux_like/linux/musl/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs":"3d9ef92e682a1789544a2bd20cad5a5623db9d7d9f5d0a3692bb0230af034165","src/unix/linux_like/linux/musl/b64/mips64.rs":"a968ef9c54fa22293085f318c8472c1754482df92cc500568dc33bd807d71ea6","src/unix/linux_like/linux/musl/b64/mod.rs":"20ceaf90a03c24a2eb154a5dffbfc9a538348404db5b554a3d8126021ba45509","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"140e579800a67315f4cb8a42b22aa8157eae34ffe626e77e421b43c53c23b34d","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"c5944526d7e19cd43e9d14d119a1d98f8780db7ecbcc79e69d7b9348e596b520","src/unix/linux_like/linux/musl/b64/s390x.rs":"8557b3477ca8cefef7fce764a3c25441929a54e50ead4091f6f7823c427cd728","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"a91c4f18027c9958037f78ae48f6352d23cb4e6f2995b2cc8de7dce0e5759470","src/unix/linux_like/linux/musl/lfs64.rs":"3e4fb381f3a0756520bde0f1692d4fa45e4ae8133bf7d7c64b0e3fdd512f235f","src/unix/linux_like/linux/musl/mod.rs":"ac8ccdb25116ecdfa44eacaffefb21329aa286713c44a12dbe2c1614f2a2748a","src/unix/linux_like/linux/no_align.rs":"62cdca0e011937aaf09a51ca86d9f0ee0fdb05f61ec3c058e6a5d5fa6357d784","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"50288ff9e411ab0966da24838f2c2a5618021bc19c422a04f577b2979ef4081e","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d0c4434e2bf813372c418a8f516c706cdccc9f7be2f0921b2207b0afdb66fe81","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"3f38ee6a4690b9d7594be20d216467a34d955f7653c2c8ce1e6147daeb53f1e0","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"a048fce1c2d9b1ad57305642e8ad05ca0f0c7e4753267a2e2d6b4fee5db3b072","src/unix/linux_like/linux/uclibc/mod.rs":"193a03fa4aa5345394e39d2115c9427e806c9f28b0fde685719119e1c90ca08a","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"8485b9182b7c67f7344fab377e7cc2a72afefd9ab63837c860514abba9728d76","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"196d03affbefb85716937c15904831e731eb222ee906e05e42102d639a8152ea","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"863f628cbaa864911ffebc58e9fb788b6c6a9651955fc401ac1f40f20eb62505","src/unix/mod.rs":"e3a98b62b83a1e42675e968c05b2281d612a66cdc09c4e3b4c16921c31a9e254","src/unix/newlib/aarch64/mod.rs":"964c096288da836b53c0c71d7f3a97048d177da220a69314c5ce93ba330d72af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cf754f8b1197489fca01e881a4b4b146e814998e4b365f116fa1a102c00e6a4e","src/unix/newlib/espidf/mod.rs":"689e29a9fff5a263e5ab8410d0a8919f77fa64aa12f4d71f71085a6f07f19f67","src/unix/newlib/generic.rs":"5f0b5d07ddb5a5d60580f9561fdb05e9218d9751d4068c4aadad2ba6b950aabf","src/unix/newlib/horizon/mod.rs":"3a521d22bf932fc01c1d26d1f9bff20f11b1855b03c8236a8eb18310f6cab5a8","src/unix/newlib/mod.rs":"e5d5faf27a6336b9f1c02b8726427801d906a14dae766852b4e85c1a92df06c8","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"cc9e188711b9bf614323ad6c48e0d2e1a1ecc5d3bc64961ba451f29c6c22d2d8","src/unix/newlib/vita/mod.rs":"ff1caf74bb0696fe15d60dbac598db4520cd538aa0f5989713d97d008eee6ad8","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"07268897fc8810f2fed22ab56f87757f71c73ba401abd848bccca6b183a13b02","src/unix/nto/neutrino.rs":"799bff4ab01a6424db6c5a2b76aa5679826d41495f9d13c63485bf13bc80026b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"e75a319975472fe9e0873244fb07c5d2004672b7a4cf7a3cb01532d6d394cb8a","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"3e550d95419169febf094c425451ca86b12821fa17839b4b0ba7520b145a5820","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"4105a2e6a6c9908fc1f2a770ede052bb0d6a5d9d49e32d815f557081efc49860","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"d4147353537d7556076ff1a1c4cb96cc2dae9416a5d176ba8a077ad55ab7ec18","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"9fdc5e1c62c441abef7bc62a7343efb2041edc24db9ac0efc0f74df55b69e249","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","src/xous.rs":"eb0675f25ba01f73072d2b70907fb8abb1148facefe5a20756c49250f3d65fae","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/libc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7df63bd7f61bf3408344673cf0ba08e7ff0df134" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/libc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/libc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libc/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,146 @@ +[package] +name = "libc" +version = "0.2.155" +authors = ["The Rust Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-lang/libc" +homepage = "https://github.com/rust-lang/libc" +documentation = "https://docs.rs/libc/" +keywords = ["libc", "ffi", "bindings", "operating", "system"] +categories = ["external-ffi-bindings", "no-std", "os"] +build = "build.rs" +exclude = ["/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml"] +description = """ +Raw FFI bindings to platform libraries like libc. +""" + +[package.metadata.docs.rs] +features = ["const-extern-fn", "extra_traits"] +default-target = "x86_64-unknown-linux-gnu" +targets = [ + "aarch64-apple-darwin", + "aarch64-apple-ios", + "aarch64-linux-android", + "aarch64-pc-windows-msvc", + "aarch64-unknown-freebsd", + "aarch64-unknown-fuchsia", + "aarch64-unknown-hermit", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "aarch64-unknown-netbsd", + "aarch64-unknown-openbsd", + "aarch64-wrs-vxworks", + "arm-linux-androideabi", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "arm-unknown-linux-musleabi", + "arm-unknown-linux-musleabihf", + "armebv7r-none-eabi", + "armebv7r-none-eabihf", + "armv5te-unknown-linux-gnueabi", + "armv5te-unknown-linux-musleabi", + "armv7-linux-androideabi", + "armv7-unknown-linux-gnueabihf", + "armv7-unknown-linux-musleabihf", + "armv7-wrs-vxworks-eabihf", + "armv7r-none-eabi", + "armv7r-none-eabihf", + "hexagon-unknown-linux-musl", + "i586-pc-windows-msvc", + "i586-unknown-linux-gnu", + "i586-unknown-linux-musl", + "i686-linux-android", + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-pc-windows-msvc", + "i686-unknown-freebsd", + "i686-unknown-haiku", + "i686-unknown-linux-gnu", + "i686-unknown-linux-musl", + "i686-unknown-netbsd", + "i686-unknown-openbsd", + "i686-wrs-vxworks", + "mips-unknown-linux-gnu", + "mips-unknown-linux-musl", + "mips64-unknown-linux-gnuabi64", + "mips64-unknown-linux-muslabi64", + "mips64el-unknown-linux-gnuabi64", + "mips64el-unknown-linux-muslabi64", + "mipsel-sony-psp", + "mipsel-unknown-linux-gnu", + "mipsel-unknown-linux-musl", + "nvptx64-nvidia-cuda", + "powerpc-unknown-linux-gnu", + "powerpc-unknown-linux-gnuspe", + "powerpc-unknown-netbsd", + "powerpc-wrs-vxworks", + "powerpc-wrs-vxworks-spe", + "powerpc64-unknown-freebsd", + "powerpc64-unknown-linux-gnu", + "powerpc64-wrs-vxworks", + "powerpc64le-unknown-linux-gnu", + "riscv32gc-unknown-linux-gnu", + "riscv32i-unknown-none-elf", + "riscv32imac-unknown-none-elf", + "riscv32imc-unknown-none-elf", + "riscv64gc-unknown-freebsd", + "riscv64gc-unknown-hermit", + "riscv64gc-unknown-linux-gnu", + "riscv64gc-unknown-linux-musl", + "riscv64gc-unknown-none-elf", + "riscv64imac-unknown-none-elf", + "s390x-unknown-linux-gnu", + "s390x-unknown-linux-musl", + "sparc-unknown-linux-gnu", + "sparc64-unknown-linux-gnu", + "sparc64-unknown-netbsd", + "sparcv9-sun-solaris", + "thumbv6m-none-eabi", + "thumbv7em-none-eabi", + "thumbv7em-none-eabihf", + "thumbv7m-none-eabi", + "thumbv7neon-linux-androideabi", + "thumbv7neon-unknown-linux-gnueabihf", + "wasm32-unknown-emscripten", + "wasm32-unknown-unknown", + "wasm32-wasi", + "x86_64-apple-darwin", + "x86_64-apple-ios", + "x86_64-fortanix-unknown-sgx", + "x86_64-linux-android", + "x86_64-pc-solaris", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + "x86_64-unknown-dragonfly", + "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", + "x86_64-unknown-haiku", + "x86_64-unknown-hermit", + "x86_64-unknown-illumos", + "x86_64-unknown-l4re-uclibc", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-gnux32", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", + "x86_64-unknown-openbsd", + "x86_64-unknown-redox", + "x86_64-wrs-vxworks" +] +cargo-args = ["-Zbuild-std=core"] + +[dependencies] +rustc-std-workspace-core = { version = "1.0.0", optional = true } + +[features] +default = ["std"] +std = [] +align = [] +rustc-dep-of-std = ['align', 'rustc-std-workspace-core'] +extra_traits = [] +const-extern-fn = [] +# use_std is deprecated, use `std` instead +use_std = ['std'] + +[workspace] +members = ["libc-test"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"6f53fbd2eaea310b988d395b7a70efb4ac94081dcdc33b805a9f3dce18555614",".github/workflows/rust.yml":"24bf91e4b89062cc53616e73cc9fac853d3487f09cfa5a39a8e8d757090b06f5","CHANGELOG.md":"d300b7242c274eef8f7d6991684bf14f4f0db6f96aecd4160cbe275520d8214f","Cargo.lock":"ab85391a9563056506c56944c5c7087e171cb1110bb0dcc29616e67def15c3a6","Cargo.toml":"a2ff81429756c110ec76d5deeefec2db2921374d55c21089086a8161b502b557","Cargo.toml.orig":"22f25599cd70587aceeee83a345a64d5251c1a94f21a939e7c5010217886042d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"b6e88d9c44d6587b548a0f565bdff0e70b656b0f02a4402b0ca9a9dbaa96d102","build.rs":"57a85fc231913df7ec8c3c0f26df68f13e2cac9343e88c06fbaa1ca6b18cbfa6","ci/script.sh":"f2ebb1ef2e1fe9eb1466f89e32276e4f0e161dda59712e91cf62d827f35bd9b3","libfuzzer/CMakeLists.txt":"902c8c0d4f7323a0645f0037d47a46f25aa07e214d68df982661b77960b758b6","libfuzzer/FuzzerBuiltins.h":"766b0c57707d1ec953034a852b152b3f0daa35ee705bed8952b501705f0799cf","libfuzzer/FuzzerBuiltinsMsvc.h":"e1af98f02bd5aa07c90ef761ae2a04d8c8119ceedf221f0bc4d535c65c091e00","libfuzzer/FuzzerCommand.h":"dcebaec18fc8d3040974748e47294d4e86972eebcc42e75380f9ce39e959e485","libfuzzer/FuzzerCorpus.h":"d534bab9a22b14b4fe6eb1bf807649644a06262876a29a348fa345474a70d3ff","libfuzzer/FuzzerCrossOver.cpp":"5bf910d4c8aea8a888eebddfb68250e521d0aba30c9f22bedc8624bcb3cd30c6","libfuzzer/FuzzerDataFlowTrace.cpp":"bf49c6ba68be1eeb43cf4a8fc535efaaad29060ed97f281910cfcac23e35ca07","libfuzzer/FuzzerDataFlowTrace.h":"8398d7a7370fc908ea13c9e683a081c8c9835337e758a4cb717f3998088bf175","libfuzzer/FuzzerDefs.h":"2117821633a53c435a40aad1b4fb13598b3c755b2cd34f1eef8b3529d551aab8","libfuzzer/FuzzerDictionary.h":"8cec4d9cacd1d23d0b08b6629b913c88cbeaf067b056b8d366e429abab0b7ead","libfuzzer/FuzzerDriver.cpp":"1901494ab4853774414ed964a07955e2c74fb4cb14f3815c9213f3ea993b0c4d","libfuzzer/FuzzerExtFunctions.def":"679fa9342b62966b48d78e39fbcbbfe9f7d1048c8d2083469a5630298ea0c796","libfuzzer/FuzzerExtFunctions.h":"f8c5e034004e5c4dc2adf4ad5053f93614802f3489b0510ae4bf447bfa3e480b","libfuzzer/FuzzerExtFunctionsDlsym.cpp":"1f778d077c895651956fe8923f2f7601395d5c5cfd1d5bce0054db5a77a7e0fc","libfuzzer/FuzzerExtFunctionsWeak.cpp":"2decf5d7713268ba720101c2387e31147a69e3ed0d3918cbe02aa5d8b80c94f2","libfuzzer/FuzzerExtFunctionsWindows.cpp":"7237190be7e0f17dd88e8651bbac65dc3d91eecde5cf8873e8e7a7f769d05788","libfuzzer/FuzzerExtraCounters.cpp":"bb7aa6b0319a2756a146ae2f8b8b4be78a1942e7b67cdaec727c6d3b978dccc5","libfuzzer/FuzzerExtraCountersDarwin.cpp":"ad2e4ba43dbbc5b584771d4fc4df013498a8c8b28c4db7b4263e7b7b46aa6539","libfuzzer/FuzzerExtraCountersWindows.cpp":"e4e6bca52b76046676f0d8db6305f649a525cc3812bfb0fcf1410d5b837f801c","libfuzzer/FuzzerFlags.def":"bdb4d32ceb4829f6607d1235a23669c4fb763842fbdb33ddc25077366917d161","libfuzzer/FuzzerFork.cpp":"f4c53e469aefef482f0614cf59a0b818e77cfacc4c4f43b80f58cb3c61ab39d2","libfuzzer/FuzzerFork.h":"94c5a6ceedd1922784999a7e36a08c7d044425b4b5c5c04602d570b6e094764a","libfuzzer/FuzzerIO.cpp":"ab62b3b4c2af6ca8126deed6481f3edb55d69e95007c761ed5797d2bc8d30814","libfuzzer/FuzzerIO.h":"872b100d87f28ef136eed1f19e1f2435ee625223e5ab6fc7ca132418301513d7","libfuzzer/FuzzerIOPosix.cpp":"796f1a322a4e8f430388b81f6e58a1c99a05a59a1e53419de7a00375ed5c3043","libfuzzer/FuzzerIOWindows.cpp":"464a596346443ec5b3abe55080a8efc4ef07cab4dd834cbe02bba64d16559a31","libfuzzer/FuzzerInterceptors.cpp":"9f6a427e5eb498416a969dcffa65e53205615e0a69cb115227f46fd437b36b66","libfuzzer/FuzzerInterface.h":"79d35cc74761177495f1c9490f86cc394895c51d10442f7ba8fd3658d34d1f46","libfuzzer/FuzzerInternal.h":"12a6a94d51e34096f165babe341354ba5e3831a3bfb384c67c048e4d361d1734","libfuzzer/FuzzerLoop.cpp":"464afa54a29b9f782b959ae3352b5d552c6ea1473023df55c35696440a958256","libfuzzer/FuzzerMain.cpp":"273d432cac2fb564ca05760ee776503e26bfa35d0f06f263a4fb2493ad1d58be","libfuzzer/FuzzerMerge.cpp":"4866a3a40c17772dcc02bdbe985c8bb9e4a780b03dd2278e56d5bb20f6e8b4ae","libfuzzer/FuzzerMerge.h":"957b1fd91416eec6f66fb5da0306b13bd91934582e9bd2ece77af4e6f05d599b","libfuzzer/FuzzerMutate.cpp":"508c8c36fe2d1dae1788c02cf06a23a3ba96e7385c524e84bcea97456de73d04","libfuzzer/FuzzerMutate.h":"5355d2d89d3ae68e829d16d358c8e65c11c842ab4c3b17baed8ef2c7053a2a4b","libfuzzer/FuzzerOptions.h":"7f6c002fcba533f5ae24d04c3240d6c8c89c072999d1f0bf48eb19591e58b8cf","libfuzzer/FuzzerPlatform.h":"2d76795e56398779dcde4d3bcd85d835141ab471eab2c46fcc70a33f82a75094","libfuzzer/FuzzerRandom.h":"bb759a8f0af5aac9df09446736817095eb3b448c5b40e5d74faad7c691c5888d","libfuzzer/FuzzerSHA1.cpp":"18296f57c7342d6952d37266031b60036220645db8dbb0c70f6b1e602c97150f","libfuzzer/FuzzerSHA1.h":"29334b9aca30a5a51bcd0f8f958ac6bbabd5984235bf53bca24eac87bedc5fe8","libfuzzer/FuzzerTracePC.cpp":"d62d00a40d690a0b2eb66c2c9b9ff20ac845dcc9d68fa0fdc0239e6f47a74d96","libfuzzer/FuzzerTracePC.h":"f076d558a97ff07e9f782ea3b74d7b1f8e4c944155b55ea5465cf24bf6a95bd1","libfuzzer/FuzzerUtil.cpp":"cf0e9217539c77117a739e47e9e9f35e43141db291ab6167deae365b3ef496be","libfuzzer/FuzzerUtil.h":"e2efd3959787d1c21780881b3c6c318cd84626fa55bae3841e56b3b9846770d2","libfuzzer/FuzzerUtilDarwin.cpp":"a47741b0a0aa90b3232eb955cacbb9340f79301a82709ea8249cc1888b762f01","libfuzzer/FuzzerUtilFuchsia.cpp":"f10fd71767084dc68320fbb003bf553c4479fce280b612c59b404eb7fec99491","libfuzzer/FuzzerUtilLinux.cpp":"5885dd9462a62d09e9cf5c627b68d80b53a694d0f69e380d607058a13fa1a4ec","libfuzzer/FuzzerUtilPosix.cpp":"7428e637aa21f46319e61c971f83ef36d94b00b3efd81cf233ebb5ef3874c230","libfuzzer/FuzzerUtilWindows.cpp":"1986d2f90a8989ec095c27a7a2af0921062421fc13915e47fb8bf8a5d0502bfc","libfuzzer/FuzzerValueBitMap.h":"785a4131a3ff36c455469375092a87efc165eb926b53dad9851b53cc034a09e9","libfuzzer/README.txt":"f1d3f05793b5ea2993be318f882afba3d4035442ed8fdffee841603ae3ea944d","libfuzzer/afl/afl_driver.cpp":"9bd8a0213c2e57edc8b3940c02f45dee724fe3d0f5f4f225a17d7c139fc5d975","libfuzzer/build.sh":"caf4aeec34fc19b141e797861f9c1022d9267858e2dda86133a91d211933f642","libfuzzer/dataflow/DataFlow.cpp":"2401b8d16c784c7c2d2ece598b13084125e0227515d126b32bf31c9f693e1068","libfuzzer/dataflow/DataFlow.h":"62ba10dec5ab8451e9a35a91565a4fa20e2fa2fa8c1992bd2de2f490a846d578","libfuzzer/dataflow/DataFlowCallbacks.cpp":"cb2cdd57ceefdfc90086a73b6b6ac7eeb44e9b272ca1b5aa607560e6fa372d9e","libfuzzer/scripts/unbalanced_allocs.py":"f3660b42e151f4de6a332eb63bc847490fc5afb331ae7b347ea9ecaea4ee6822","libfuzzer/standalone/StandaloneFuzzTargetMain.c":"4c385730c2d961a5d25e1e57b3760fb36a88e7b53e48a8a42994b4d25e097382","libfuzzer/tests/CMakeLists.txt":"f94e33f589253a5d8abc9571dd4fcd2f7cdcad99bd8e11d9dfc0319b0713fca9","libfuzzer/tests/FuzzedDataProviderUnittest.cpp":"ceae621f1d2c29c15e00292cb2064d1bce409202ed12751e1749786cf2fa31c5","libfuzzer/tests/FuzzerUnittest.cpp":"03880b4acf2cb843f73ce01251914c09999aea15a086349674bb28f7569e85d3","rust-toolchain":"58bea07cb6d97f9cfcd5c8f98b1feca0fb81cce5b0bf29a8e70ed2641956e9a6","src/lib.rs":"68eba320b86a38c6a0219264a0c1741f45f567dceca135017d3755d1635bc835","update-libfuzzer.sh":"19f681bdf3f33503f175e679f3e44a65a62fd875be2108d8332f0a426b7e16db"},"package":"5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "217dc97fb5943c700530d4559d897040f27db93d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +name: Rust + +on: [push, pull_request] + +jobs: + check_libfuzzer_checkout: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Re-vendor libfuzzer + run: ./update-libfuzzer.sh + - name: Check that nothing changed + run: git diff --exit-code + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install nightly Rust + run: | + rustup toolchain install nightly + rustup default nightly + + - name: Check rustfmt + run: | + rustup component add rustfmt --toolchain stable + cargo +stable fmt --all -- --check + + - run: cargo install cargo-fuzz + + - name: Run tests + run: ./ci/script.sh diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,292 @@ +## Unreleased + +Released YYYY-MM-DD. + +### Added + +* TODO (or remove section if none) + +### Changed + +* TODO (or remove section if none) + +### Deprecated + +* TODO (or remove section if none) + +### Removed + +* TODO (or remove section if none) + +### Fixed + +* TODO (or remove section if none) + +### Security + +* TODO (or remove section if none) + +-------------------------------------------------------------------------------- + +## 0.4.10 + +Released 2025-07-03. + +### Changed + +* Updated to `libFuzzer` commit `6146a88f6049` (`release/20.x`). +* Fuzz targets taking raw byte slice inputs can now return `Corpus` results. + +-------------------------------------------------------------------------------- + +## 0.4.9 + +Released 2025-01-28. + +### Added + +* The `example_init` demonstrates how to pass an initialization code block to + the `fuzz_target!` macro. + +### Changed + +* The `fuzz_target!` macro now supports the generation of `LLVMFuzzerInitialize` + to execute initialization code once before running the fuzzer. This change is + not breaking and is completely backward compatible. + +-------------------------------------------------------------------------------- + +## 0.4.8 + +Released 2024-11-07. + +### Added + +* Bindings to `LLVMFuzzerCustomCrossOver` through the `fuzz_crossover` + macro. See the `example_crossover` directory in this crate's repo for a + complete example. + +### Changed + +* Updated to `libFuzzer` commit `ab51eccf88f5321e7c60591c5546b254b6afab99` + (`release/19.x`). + +-------------------------------------------------------------------------------- + +## 0.4.7 + +Released 2023-08-10. + +### Added + +* Added the `link_libfuzzer` cargo feature. This feature is on by default and + preserves the existing behavior of statically linking libfuzzer. You can + disable it if you are linking your own version of libfuzzer some other way, or + another library that provides the same ABI as libfuzzer. + +-------------------------------------------------------------------------------- + +## 0.4.6 + +Released 2023-01-26. + +### Fixed + +* Fixed a potential name conflict in functions generated by the `fuzz_target!` + macro. +* Fixed potential stale builds when updating custom libfuzzers to link against. + +-------------------------------------------------------------------------------- + +## 0.4.5 + +Released 2022-10-18. + +### Added + +* Added the ability to tell libfuzzer whether to keep files inputs in the corpus + or not. See the `Corpus` type and extended documentation for the + `fuzz_target!` macro for details. + +### Changed + +* Ensured that there is always at least one inline-never frame on the stack per + fuzz target. This helps prevent oss-fuzz from "deduplicating" different bugs + from different fuzz targets into the same bug. + +-------------------------------------------------------------------------------- + +## 0.4.4 + +Released 2022-09-01. + +### Changed + +* Updated to `libFuzzer` commit `df90d22` (`release/15.x`). +* LLVM 16's [upcoming change][llvm_cxx17] to build requirements to C++17 + necessitate reflecting those changes. (`libFuzzer` updates contain C++14 code) +* Drastically reduce build times by using parallel C++ compilation jobs +* Updated `rand` dependency from 0.8.3 to 0.8.5 +* Updated `flate2` dependency from 1.0.20 to 1.0.24 + +[llvm_cxx17]: https://llvm.org/docs/ReleaseNotes.html#update-on-required-toolchains-to-build-llvm + +-------------------------------------------------------------------------------- + +## 0.4.3 + +Released 2020-03-03. + +### Changed + +* Updated to `libFuzzer` commit `60e32a1`. + +### Fixed + +* Fixed an issue where the `fuzz_target!` macro would sometimes expand to + versions of itself that were not `$crate` prefixed and would result in "error: + cannot find macro `fuzz_target` in this scope" if the caller didn't import the + macro but used the qualified version of it instead. + +-------------------------------------------------------------------------------- + +## 0.4.2 + +Released 2020-05-26. + +### Changed + +* Improved performance of checking for whether `cargo fuzz` is requesting the + `std::fmt::Debug` output of an input or not. This is always false during + regular fuzzing, so making this check faster should give slightly better + fuzzing throughput. + +-------------------------------------------------------------------------------- + +## 0.4.1 + +Released 2020-05-13. + +### Added + +* Added support for defining custom mutators. See [the documentation for the + `fuzz_mutator!` + macro](https://docs.rs/libfuzzer-sys/0.4.1/libfuzzer_sys/macro.fuzz_mutator.html) + for details. + +### Changed + +* Upgraded libfuzzer to llvm/llvm-project's 70cbc6d. + +-------------------------------------------------------------------------------- + +## 0.4.0 + +Released 2021-02-24. + +### Changed + +* The public `arbitrary` dependency was updated to version 1.0. + +-------------------------------------------------------------------------------- + +## 0.3.5 + +Released 2020-11-18. + +### Changed + +* [Upgrade libfuzzer to 7bf89c2](https://github.com/rust-fuzz/libfuzzer/pull/68) + +-------------------------------------------------------------------------------- + +## 0.3.4 + +Released 2020-08-22. + +### Changed + +* Updated `arbitrary` dependency to 0.4.6 + +-------------------------------------------------------------------------------- + +## 0.3.3 + +Released 2020-07-27. + +### Changed + +* Upgraded libfuzzer to commit + [4a4cafa](https://github.com/llvm/llvm-project/commit/4a4cafabc9067fced5890a245b03ef5897ad988b). + + Notably, this pulls in [the new Entropic engine for + libFuzzer](https://mboehme.github.io/paper/FSE20.Entropy.pdf), which should + boost fuzzing efficiency when enabled. You can enable Entropic by passing + `-entropic=1` to your built fuzz targets (although, note that it is still + labeled "experimental"). + +-------------------------------------------------------------------------------- + +## 0.3.2 + +Released 2020-03-18. + +### Changed + +* Upgraded the `arbitrary` dependency re-export to version 0.4.1. + +-------------------------------------------------------------------------------- + +## 0.3.1 + +Released 2020-02-27. + +### Changed + +* Fixed a fuzzing performance issue where libfuzzer could unnecessarily spend + time exploring all the ways that an `Arbitrary` implementation could fail to + construct an instance of itself because the fuzzer provided too few bytes. See + https://github.com/rust-fuzz/libfuzzer/issues/59 for details. + +-------------------------------------------------------------------------------- + +## 0.3.0 + +Released 2019-01-22. + +### Changed + +* Now works with and re-exports `arbitrary` versions 0.4.x. + +-------------------------------------------------------------------------------- + +## 0.2.1 + +Released 2019-01-16. + +### Added + +* Added support for the `CUSTOM_LIBFUZZER_STD_CXX=` environment variable + during builds that already use a custom libFuzzer checkout with + `CUSTOM_LIBFUZZER_PATH`. This allows you to explicitly choose to link LLVM or + GNU C++ standard libraries. + +-------------------------------------------------------------------------------- + +## 0.2.0 + +Released 2020-01-14. + +### Changed + +* Using `arbitrary` 0.3.x now. It is re-exported as `libfuzzer_sys::arbitrary`. + +### Added + +* You can enable support for `#[derive(Arbitrary)]` with the + `"arbitrary-derive"` cargo feature. This is a synonym for the `arbitrary` + crate's `"derive"` cargo feature. + +-------------------------------------------------------------------------------- + +## 0.1.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "arbitrary" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "cc" +version = "1.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "derive_arbitrary" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df89dd0d075dea5cc5fdd6d5df6b8a61172a710b3efac1d6bdb9dd8b78f82c1a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.10" +dependencies = [ + "arbitrary", + "cc", + "flate2", + "rand", +] + +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "libfuzzer-sys" +version = "0.4.10" +authors = ["The rust-fuzz Project Developers"] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A wrapper around LLVM's libFuzzer runtime." +readme = "README.md" +license = "(MIT OR Apache-2.0) AND NCSA" +repository = "https://github.com/rust-fuzz/libfuzzer" + +[features] +arbitrary-derive = ["arbitrary/derive"] +default = ["link_libfuzzer"] +link_libfuzzer = [] + +[lib] +name = "libfuzzer_sys" +path = "src/lib.rs" + +[dependencies.arbitrary] +version = "1" + +[dev-dependencies.flate2] +version = "1.0.24" + +[dev-dependencies.rand] +version = "0.8.5" + +[build-dependencies.cc] +version = "1.0.83" +features = ["parallel"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +[package] +authors = ["The rust-fuzz Project Developers"] +description = "A wrapper around LLVM's libFuzzer runtime." +edition = "2018" +license = "(MIT OR Apache-2.0) AND NCSA" +name = "libfuzzer-sys" +readme = "./README.md" +repository = "https://github.com/rust-fuzz/libfuzzer" +version = "0.4.10" + +[dependencies] +arbitrary = "1" + +[build-dependencies] +cc = { version = "1.0.83", features = ["parallel"] } + +[features] +default = ["link_libfuzzer"] +link_libfuzzer = [] +arbitrary-derive = ["arbitrary/derive"] + +[workspace] +members = [ + "./example/fuzz", + "./example_arbitrary/fuzz", + "./example_crossover/fuzz", + "./example_init/fuzz", + "./example_mutator/fuzz", +] + +[dev-dependencies] +flate2 = "1.0.24" +rand = "0.8.5" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2010 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/README.md clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +# The `libfuzzer-sys` Crate + +Barebones wrapper around LLVM's libFuzzer runtime library. + +The CPP parts are extracted from compiler-rt git repository with `git filter-branch`. + +libFuzzer relies on LLVM sanitizer support. The Rust compiler has built-in support for LLVM sanitizer support, for now, it's limited to Linux. As a result, `libfuzzer-sys` only works on Linux. + +## Usage + +### Use `cargo fuzz`! + +[The recommended way to use this crate with `cargo fuzz`!][cargo-fuzz]. + +[cargo-fuzz]: https://github.com/rust-fuzz/cargo-fuzz + +### Manual Usage + +This crate can also be used manually as following: + +First create a new cargo project: + +``` +$ cargo new --bin fuzzed +$ cd fuzzed +``` + +Then add a dependency on the `fuzzer-sys` crate and your own crate: + +```toml +[dependencies] +libfuzzer-sys = "0.4.0" +your_crate = { path = "../path/to/your/crate" } +``` + +Change the `fuzzed/src/main.rs` to fuzz your code: + +```rust +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + // code to fuzz goes here +}); +``` + +Build by running the following command: + +```sh +$ cargo rustc -- \ + -C passes='sancov-module' \ + -C llvm-args='-sanitizer-coverage-level=3' \ + -C llvm-args='-sanitizer-coverage-inline-8bit-counters' \ + -Z sanitizer=address +``` + +And finally, run the fuzzer: + +```sh +$ ./target/debug/fuzzed +``` + +### Linking to a local libfuzzer + +When using `libfuzzer-sys`, you can provide your own `libfuzzer` runtime in two ways. + +If you are developing a fuzzer, you can set the `CUSTOM_LIBFUZZER_PATH` environment variable to the path of your local +`libfuzzer` runtime, which will then be linked instead of building libfuzzer as part of the build stage of `libfuzzer-sys`. +For an example, to link to a prebuilt LLVM 16 `libfuzzer`, you could use: + +```bash +$ export CUSTOM_LIBFUZZER_PATH=/usr/lib64/clang/16/lib/libclang_rt.fuzzer-x86_64.a +$ cargo fuzz run ... +``` + +Alternatively, you may also disable the default `link_libfuzzer` feature: + +In `Cargo.toml`: +```toml +[dependencies] +libfuzzer-sys = { path = "../../libfuzzer", default-features = false } +``` + +Then link to your own runtime in your `build.rs`. + +## Updating libfuzzer from upstream + +* Update the `COMMIT=...` variable in `./update-libfuzzer.sh` with the new + commit hash from [llvm-mirror/llvm-project](github.com/llvm-mirror/llvm-project) + that you are vendoring. + +* Re-run the script: + + ``` + $ ./update-libfuzzer.sh + ``` + +## License + +All files in the `libfuzzer` directory are licensed NCSA. + +Everything else is dual-licensed Apache 2.0 and MIT. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/build.rs clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +fn build_and_link_libfuzzer() { + println!("cargo:rerun-if-env-changed=CUSTOM_LIBFUZZER_PATH"); + if let Ok(custom) = ::std::env::var("CUSTOM_LIBFUZZER_PATH") { + println!("cargo:rerun-if-changed={custom}"); + + let custom_lib_path = ::std::path::PathBuf::from(&custom); + let custom_lib_dir = custom_lib_path.parent().unwrap().to_string_lossy(); + + let custom_lib_name = custom_lib_path.file_stem().unwrap().to_string_lossy(); + let custom_lib_name = custom_lib_name + .strip_prefix("lib") + .unwrap_or(custom_lib_name.as_ref()); + + println!("cargo:rustc-link-search=native={}", custom_lib_dir); + println!("cargo:rustc-link-lib=static={}", custom_lib_name); + + match std::env::var("CUSTOM_LIBFUZZER_STD_CXX") { + // Default behavior for backwards compat. + Err(_) => println!("cargo:rustc-link-lib=stdc++"), + Ok(s) if s == "none" => (), + Ok(s) => println!("cargo:rustc-link-lib={}", s), + } + } else { + let mut build = cc::Build::new(); + let sources = ::std::fs::read_dir("libfuzzer") + .expect("listable source directory") + .map(|de| de.expect("file in directory").path()) + .filter(|p| p.extension().map(|ext| ext == "cpp") == Some(true)) + .collect::>(); + for source in sources.iter() { + println!("cargo:rerun-if-changed={}", source.display()); + build.file(source.to_str().unwrap()); + } + build.cpp(true); + build.std("c++17"); + build.force_frame_pointer(true); + build.warnings(false); + build.compile("libfuzzer.a"); + } +} + +fn main() { + if cfg!(feature = "link_libfuzzer") { + build_and_link_libfuzzer(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/ci/script.sh clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/ci/script.sh --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/ci/script.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/ci/script.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +set -eux +cd $(dirname $0)/.. + +export CARGO_TARGET_DIR=$(pwd)/target + +cargo test --doc + +pushd ./example +cargo fuzz build +cargo fuzz build --dev +(! cargo fuzz run bananas -- -runs=100000) +popd + +pushd ./example_arbitrary +cargo fuzz build +cargo fuzz build --dev +(! cargo fuzz run rgb -- -runs=10000000) +RUST_LIBFUZZER_DEBUG_PATH=$(pwd)/debug_output \ + cargo fuzz run rgb \ + $(ls ./fuzz/artifacts/rgb/crash-* | head -n 1) +cat $(pwd)/debug_output +grep -q Rgb $(pwd)/debug_output +popd + +pushd ./example_mutator +cargo fuzz build +cargo fuzz build --dev +(! cargo fuzz run boom -- -runs=10000000) +popd + +pushd ./example_crossover +cargo fuzz build +cargo fuzz build --dev +(! cargo fuzz run --release boom -- -runs=10000000) +popd + +pushd ./example_init +cargo fuzz build +cargo fuzz build --dev +(! cargo fuzz run --release bigbang -- -runs=10000000) +popd + +echo "All good!" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/CMakeLists.txt clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/CMakeLists.txt --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/CMakeLists.txt 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,182 @@ +set(LIBFUZZER_SOURCES + FuzzerCrossOver.cpp + FuzzerDataFlowTrace.cpp + FuzzerDriver.cpp + FuzzerExtFunctionsDlsym.cpp + FuzzerExtFunctionsWeak.cpp + FuzzerExtFunctionsWindows.cpp + FuzzerExtraCounters.cpp + FuzzerExtraCountersDarwin.cpp + FuzzerExtraCountersWindows.cpp + FuzzerFork.cpp + FuzzerIO.cpp + FuzzerIOPosix.cpp + FuzzerIOWindows.cpp + FuzzerLoop.cpp + FuzzerMerge.cpp + FuzzerMutate.cpp + FuzzerSHA1.cpp + FuzzerTracePC.cpp + FuzzerUtil.cpp + FuzzerUtilDarwin.cpp + FuzzerUtilFuchsia.cpp + FuzzerUtilLinux.cpp + FuzzerUtilPosix.cpp + FuzzerUtilWindows.cpp) + +set(LIBFUZZER_HEADERS + FuzzerBuiltins.h + FuzzerBuiltinsMsvc.h + FuzzerCommand.h + FuzzerCorpus.h + FuzzerDataFlowTrace.h + FuzzerDefs.h + FuzzerDictionary.h + FuzzerExtFunctions.def + FuzzerExtFunctions.h + FuzzerFlags.def + FuzzerFork.h + FuzzerIO.h + FuzzerInterface.h + FuzzerInternal.h + FuzzerMerge.h + FuzzerMutate.h + FuzzerOptions.h + FuzzerRandom.h + FuzzerSHA1.h + FuzzerTracePC.h + FuzzerUtil.h + FuzzerValueBitMap.h) + +include_directories(../../include) + +CHECK_CXX_SOURCE_COMPILES(" + static thread_local int blah; + int main() { + return 0; + } + " HAS_THREAD_LOCAL) + +set(LIBFUZZER_CFLAGS ${COMPILER_RT_COMMON_CFLAGS}) + +if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND + COMPILER_RT_LIBCXX_PATH AND + COMPILER_RT_LIBCXXABI_PATH) + list(APPEND LIBFUZZER_CFLAGS -D_LIBCPP_ABI_VERSION=Fuzzer) + append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ LIBFUZZER_CFLAGS) +elseif(TARGET cxx-headers OR HAVE_LIBCXX) + # libFuzzer uses C++ standard library headers. + list(APPEND LIBFUZZER_CFLAGS ${COMPILER_RT_CXX_CFLAGS}) + set(LIBFUZZER_DEPS cxx-headers) +endif() + +append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) + +if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") + list(APPEND LIBFUZZER_CFLAGS -fsanitize-coverage=0) +endif() + +if(MSVC) + # Silence warnings by turning off exceptions in MSVC headers and avoid an + # error by unnecessarily defining thread_local when it isn't even used on + # Windows. + list(APPEND LIBFUZZER_CFLAGS -D_HAS_EXCEPTIONS=0) +else() + if(NOT HAS_THREAD_LOCAL) + list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread) + endif() +endif() + +add_compiler_rt_component(fuzzer) + +add_compiler_rt_object_libraries(RTfuzzer + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + SOURCES ${LIBFUZZER_SOURCES} + ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS} + CFLAGS ${LIBFUZZER_CFLAGS} + DEPS ${LIBFUZZER_DEPS}) + +add_compiler_rt_object_libraries(RTfuzzer_main + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + SOURCES FuzzerMain.cpp + CFLAGS ${LIBFUZZER_CFLAGS} + DEPS ${LIBFUZZER_DEPS}) + +add_compiler_rt_object_libraries(RTfuzzer_interceptors + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + SOURCES FuzzerInterceptors.cpp + CFLAGS ${LIBFUZZER_CFLAGS} + DEPS ${LIBFUZZER_DEPS}) + +add_compiler_rt_runtime(clang_rt.fuzzer + STATIC + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + OBJECT_LIBS RTfuzzer RTfuzzer_main + CFLAGS ${LIBFUZZER_CFLAGS} + PARENT_TARGET fuzzer) + +add_compiler_rt_runtime(clang_rt.fuzzer_no_main + STATIC + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + OBJECT_LIBS RTfuzzer + CFLAGS ${LIBFUZZER_CFLAGS} + PARENT_TARGET fuzzer) + +add_compiler_rt_runtime(clang_rt.fuzzer_interceptors + STATIC + OS ${FUZZER_SUPPORTED_OS} + ARCHS ${FUZZER_SUPPORTED_ARCH} + OBJECT_LIBS RTfuzzer_interceptors + CFLAGS ${LIBFUZZER_CFLAGS} + PARENT_TARGET fuzzer) + +if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND + COMPILER_RT_LIBCXX_PATH AND + COMPILER_RT_LIBCXXABI_PATH) + macro(partially_link_libcxx name dir arch) + get_target_flags_for_arch(${arch} target_cflags) + if(CMAKE_CXX_COMPILER_ID MATCHES Clang) + get_compiler_rt_target(${arch} target) + set(target_cflags --target=${target} ${target_cflags}) + endif() + set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") + file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) + add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD + COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$" -Wl,--no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o + COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o + COMMAND ${CMAKE_COMMAND} -E remove "$" + COMMAND ${CMAKE_AR} qcs "$" ${name}.o + WORKING_DIRECTORY ${cxx_${arch}_merge_dir} + ) + endmacro() + + foreach(arch ${FUZZER_SUPPORTED_ARCH}) + get_target_flags_for_arch(${arch} TARGET_CFLAGS) + set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) + add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} + CFLAGS ${TARGET_CFLAGS} + CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF + -DLIBCXX_ABI_NAMESPACE=__Fuzzer + -DLIBCXX_ENABLE_EXCEPTIONS=OFF) + target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) + add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-install-cmake326-workaround) + target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) + add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-install-cmake326-workaround) + target_compile_options(RTfuzzer_interceptors.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) + add_dependencies(RTfuzzer_interceptors.${arch} libcxx_fuzzer_${arch}-install-cmake326-workaround) + partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch}) + partially_link_libcxx(fuzzer_interceptors ${LIBCXX_${arch}_PREFIX} ${arch}) + partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch}) + endforeach() +endif() + +if(COMPILER_RT_INCLUDE_TESTS) + add_subdirectory(tests) +endif() diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltins.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltins.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltins.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltins.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Wrapper functions and marcos around builtin functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_BUILTINS_H +#define LLVM_FUZZER_BUILTINS_H + +#include "FuzzerPlatform.h" + +#if !LIBFUZZER_MSVC +#include + +#define GET_CALLER_PC() __builtin_return_address(0) + +namespace fuzzer { + +inline uint8_t Bswap(uint8_t x) { return x; } +inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } +inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } +inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } + +inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); } +inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); } + +} // namespace fuzzer + +#endif // !LIBFUZZER_MSVC +#endif // LLVM_FUZZER_BUILTINS_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltinsMsvc.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltinsMsvc.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltinsMsvc.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerBuiltinsMsvc.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,67 @@ +//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Wrapper functions and marcos that use intrinsics instead of builtin functions +// which cannot be compiled by MSVC. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_BUILTINS_MSVC_H +#define LLVM_FUZZER_BUILTINS_MSVC_H + +#include "FuzzerPlatform.h" + +#if LIBFUZZER_MSVC +#include +#include +#include + +// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent +// from +#define GET_CALLER_PC() _ReturnAddress() + +namespace fuzzer { + +inline uint8_t Bswap(uint8_t x) { return x; } +// Use alternatives to __builtin functions from and on +// Windows since the builtins are not supported by MSVC. +inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } +inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } +inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } + +// The functions below were mostly copied from +// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used +// outside of Windows. +inline uint32_t Clzll(uint64_t X) { + unsigned long LeadZeroIdx = 0; + +#if !defined(_M_ARM) && !defined(_M_X64) + // Scan the high 32 bits. + if (_BitScanReverse(&LeadZeroIdx, static_cast(X >> 32))) + return static_cast( + 63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. + // Scan the low 32 bits. + if (_BitScanReverse(&LeadZeroIdx, static_cast(X))) + return static_cast(63 - LeadZeroIdx); + +#else + if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; +#endif + return 64; +} + +inline int Popcountll(unsigned long long X) { +#if !defined(_M_ARM) && !defined(_M_X64) + return __popcnt(X) + __popcnt(X >> 32); +#else + return __popcnt64(X); +#endif +} + +} // namespace fuzzer + +#endif // LIBFUZER_MSVC +#endif // LLVM_FUZZER_BUILTINS_MSVC_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCommand.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCommand.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCommand.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCommand.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,179 @@ +//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// FuzzerCommand represents a command to run in a subprocess. It allows callers +// to manage command line arguments and output and error streams. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_COMMAND_H +#define LLVM_FUZZER_COMMAND_H + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" + +#include +#include +#include +#include +#include + +namespace fuzzer { + +class Command final { +public: + // This command line flag is used to indicate that the remaining command line + // is immutable, meaning this flag effectively marks the end of the mutable + // argument list. + static inline const char *ignoreRemainingArgs() { + return "-ignore_remaining_args=1"; + } + + Command() : CombinedOutAndErr(false) {} + + explicit Command(const std::vector &ArgsToAdd) + : Args(ArgsToAdd), CombinedOutAndErr(false) {} + + explicit Command(const Command &Other) + : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr), + OutputFile(Other.OutputFile) {} + + Command &operator=(const Command &Other) { + Args = Other.Args; + CombinedOutAndErr = Other.CombinedOutAndErr; + OutputFile = Other.OutputFile; + return *this; + } + + ~Command() {} + + // Returns true if the given Arg is present in Args. Only checks up to + // "-ignore_remaining_args=1". + bool hasArgument(const std::string &Arg) const { + auto i = endMutableArgs(); + return std::find(Args.begin(), i, Arg) != i; + } + + // Gets all of the current command line arguments, **including** those after + // "-ignore-remaining-args=1". + const std::vector &getArguments() const { return Args; } + + // Adds the given argument before "-ignore_remaining_args=1", or at the end + // if that flag isn't present. + void addArgument(const std::string &Arg) { + Args.insert(endMutableArgs(), Arg); + } + + // Adds all given arguments before "-ignore_remaining_args=1", or at the end + // if that flag isn't present. + void addArguments(const std::vector &ArgsToAdd) { + Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end()); + } + + // Removes the given argument from the command argument list. Ignores any + // occurrences after "-ignore_remaining_args=1", if present. + void removeArgument(const std::string &Arg) { + auto i = endMutableArgs(); + Args.erase(std::remove(Args.begin(), i, Arg), i); + } + + // Like hasArgument, but checks for "-[Flag]=...". + bool hasFlag(const std::string &Flag) const { + std::string Arg("-" + Flag + "="); + auto IsMatch = [&](const std::string &Other) { + return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; + }; + return std::any_of(Args.begin(), endMutableArgs(), IsMatch); + } + + // Returns the value of the first instance of a given flag, or an empty string + // if the flag isn't present. Ignores any occurrences after + // "-ignore_remaining_args=1", if present. + std::string getFlagValue(const std::string &Flag) const { + std::string Arg("-" + Flag + "="); + auto IsMatch = [&](const std::string &Other) { + return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; + }; + auto i = endMutableArgs(); + auto j = std::find_if(Args.begin(), i, IsMatch); + std::string result; + if (j != i) { + result = j->substr(Arg.length()); + } + return result; + } + + // Like AddArgument, but adds "-[Flag]=[Value]". + void addFlag(const std::string &Flag, const std::string &Value) { + addArgument("-" + Flag + "=" + Value); + } + + // Like RemoveArgument, but removes "-[Flag]=...". + void removeFlag(const std::string &Flag) { + std::string Arg("-" + Flag + "="); + auto IsMatch = [&](const std::string &Other) { + return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; + }; + auto i = endMutableArgs(); + Args.erase(std::remove_if(Args.begin(), i, IsMatch), i); + } + + // Returns whether the command's stdout is being written to an output file. + bool hasOutputFile() const { return !OutputFile.empty(); } + + // Returns the currently set output file. + const std::string &getOutputFile() const { return OutputFile; } + + // Configures the command to redirect its output to the name file. + void setOutputFile(const std::string &FileName) { OutputFile = FileName; } + + // Returns whether the command's stderr is redirected to stdout. + bool isOutAndErrCombined() const { return CombinedOutAndErr; } + + // Sets whether to redirect the command's stderr to its stdout. + void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; } + + // Returns a string representation of the command. On many systems this will + // be the equivalent command line. + std::string toString() const { + std::stringstream SS; + for (const auto &arg : getArguments()) + SS << arg << " "; + if (hasOutputFile()) + SS << ">" << getOutputFile() << " "; + if (isOutAndErrCombined()) + SS << "2>&1 "; + std::string result = SS.str(); + if (!result.empty()) + result = result.substr(0, result.length() - 1); + return result; + } + +private: + Command(Command &&Other) = delete; + Command &operator=(Command &&Other) = delete; + + std::vector::iterator endMutableArgs() { + return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); + } + + std::vector::const_iterator endMutableArgs() const { + return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); + } + + // The command arguments. Args[0] is the command name. + std::vector Args; + + // True indicates stderr is redirected to stdout. + bool CombinedOutAndErr; + + // If not empty, stdout is redirected to the named file. + std::string OutputFile; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_COMMAND_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCorpus.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCorpus.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCorpus.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCorpus.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,592 @@ +//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::InputCorpus +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_CORPUS +#define LLVM_FUZZER_CORPUS + +#include "FuzzerDataFlowTrace.h" +#include "FuzzerDefs.h" +#include "FuzzerIO.h" +#include "FuzzerRandom.h" +#include "FuzzerSHA1.h" +#include "FuzzerTracePC.h" +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +struct InputInfo { + Unit U; // The actual input data. + std::chrono::microseconds TimeOfUnit; + uint8_t Sha1[kSHA1NumBytes]; // Checksum. + // Number of features that this input has and no smaller input has. + size_t NumFeatures = 0; + size_t Tmp = 0; // Used by ValidateFeatureSet. + // Stats. + size_t NumExecutedMutations = 0; + size_t NumSuccessfullMutations = 0; + bool NeverReduce = false; + bool MayDeleteFile = false; + bool Reduced = false; + bool HasFocusFunction = false; + std::vector UniqFeatureSet; + std::vector DataFlowTraceForFocusFunction; + // Power schedule. + bool NeedsEnergyUpdate = false; + double Energy = 0.0; + double SumIncidence = 0.0; + std::vector> FeatureFreqs; + + // Delete feature Idx and its frequency from FeatureFreqs. + bool DeleteFeatureFreq(uint32_t Idx) { + if (FeatureFreqs.empty()) + return false; + + // Binary search over local feature frequencies sorted by index. + auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(), + std::pair(Idx, 0)); + + if (Lower != FeatureFreqs.end() && Lower->first == Idx) { + FeatureFreqs.erase(Lower); + return true; + } + return false; + } + + // Assign more energy to a high-entropy seed, i.e., that reveals more + // information about the globally rare features in the neighborhood of the + // seed. Since we do not know the entropy of a seed that has never been + // executed we assign fresh seeds maximum entropy and let II->Energy approach + // the true entropy from above. If ScalePerExecTime is true, the computed + // entropy is scaled based on how fast this input executes compared to the + // average execution time of inputs. The faster an input executes, the more + // energy gets assigned to the input. + void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime, + std::chrono::microseconds AverageUnitExecutionTime) { + Energy = 0.0; + SumIncidence = 0.0; + + // Apply add-one smoothing to locally discovered features. + for (const auto &F : FeatureFreqs) { + double LocalIncidence = F.second + 1; + Energy -= LocalIncidence * log(LocalIncidence); + SumIncidence += LocalIncidence; + } + + // Apply add-one smoothing to locally undiscovered features. + // PreciseEnergy -= 0; // since log(1.0) == 0) + SumIncidence += + static_cast(GlobalNumberOfFeatures - FeatureFreqs.size()); + + // Add a single locally abundant feature apply add-one smoothing. + double AbdIncidence = static_cast(NumExecutedMutations + 1); + Energy -= AbdIncidence * log(AbdIncidence); + SumIncidence += AbdIncidence; + + // Normalize. + if (SumIncidence != 0) + Energy = Energy / SumIncidence + log(SumIncidence); + + if (ScalePerExecTime) { + // Scaling to favor inputs with lower execution time. + uint32_t PerfScore = 100; + if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 10) + PerfScore = 10; + else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 4) + PerfScore = 25; + else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 2) + PerfScore = 50; + else if (TimeOfUnit.count() * 3 > AverageUnitExecutionTime.count() * 4) + PerfScore = 75; + else if (TimeOfUnit.count() * 4 < AverageUnitExecutionTime.count()) + PerfScore = 300; + else if (TimeOfUnit.count() * 3 < AverageUnitExecutionTime.count()) + PerfScore = 200; + else if (TimeOfUnit.count() * 2 < AverageUnitExecutionTime.count()) + PerfScore = 150; + + Energy *= PerfScore; + } + } + + // Increment the frequency of the feature Idx. + void UpdateFeatureFrequency(uint32_t Idx) { + NeedsEnergyUpdate = true; + + // The local feature frequencies is an ordered vector of pairs. + // If there are no local feature frequencies, push_back preserves order. + // Set the feature frequency for feature Idx32 to 1. + if (FeatureFreqs.empty()) { + FeatureFreqs.push_back(std::pair(Idx, 1)); + return; + } + + // Binary search over local feature frequencies sorted by index. + auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(), + std::pair(Idx, 0)); + + // If feature Idx32 already exists, increment its frequency. + // Otherwise, insert a new pair right after the next lower index. + if (Lower != FeatureFreqs.end() && Lower->first == Idx) { + Lower->second++; + } else { + FeatureFreqs.insert(Lower, std::pair(Idx, 1)); + } + } +}; + +struct EntropicOptions { + bool Enabled; + size_t NumberOfRarestFeatures; + size_t FeatureFrequencyThreshold; + bool ScalePerExecTime; +}; + +class InputCorpus { + static const uint32_t kFeatureSetSize = 1 << 21; + static const uint8_t kMaxMutationFactor = 20; + static const size_t kSparseEnergyUpdates = 100; + + size_t NumExecutedMutations = 0; + + EntropicOptions Entropic; + +public: + InputCorpus(const std::string &OutputCorpus, EntropicOptions Entropic) + : Entropic(Entropic), OutputCorpus(OutputCorpus) { + memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature)); + memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature)); + } + ~InputCorpus() { + for (auto II : Inputs) + delete II; + } + size_t size() const { return Inputs.size(); } + size_t SizeInBytes() const { + size_t Res = 0; + for (auto II : Inputs) + Res += II->U.size(); + return Res; + } + size_t NumActiveUnits() const { + size_t Res = 0; + for (auto II : Inputs) + Res += !II->U.empty(); + return Res; + } + size_t MaxInputSize() const { + size_t Res = 0; + for (auto II : Inputs) + Res = std::max(Res, II->U.size()); + return Res; + } + void IncrementNumExecutedMutations() { NumExecutedMutations++; } + + size_t NumInputsThatTouchFocusFunction() { + return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) { + return II->HasFocusFunction; + }); + } + + size_t NumInputsWithDataFlowTrace() { + return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) { + return !II->DataFlowTraceForFocusFunction.empty(); + }); + } + + bool empty() const { return Inputs.empty(); } + const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; } + InputInfo *AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile, + bool HasFocusFunction, bool NeverReduce, + std::chrono::microseconds TimeOfUnit, + const std::vector &FeatureSet, + const DataFlowTrace &DFT, const InputInfo *BaseII) { + assert(!U.empty()); + if (FeatureDebug) + Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures); + // Inputs.size() is cast to uint32_t below. + assert(Inputs.size() < std::numeric_limits::max()); + Inputs.push_back(new InputInfo()); + InputInfo &II = *Inputs.back(); + II.U = U; + II.NumFeatures = NumFeatures; + II.NeverReduce = NeverReduce; + II.TimeOfUnit = TimeOfUnit; + II.MayDeleteFile = MayDeleteFile; + II.UniqFeatureSet = FeatureSet; + II.HasFocusFunction = HasFocusFunction; + // Assign maximal energy to the new seed. + II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size()); + II.SumIncidence = static_cast(RareFeatures.size()); + II.NeedsEnergyUpdate = false; + std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end()); + ComputeSHA1(U.data(), U.size(), II.Sha1); + auto Sha1Str = Sha1ToString(II.Sha1); + Hashes.insert(Sha1Str); + if (HasFocusFunction) + if (auto V = DFT.Get(Sha1Str)) + II.DataFlowTraceForFocusFunction = *V; + // This is a gross heuristic. + // Ideally, when we add an element to a corpus we need to know its DFT. + // But if we don't, we'll use the DFT of its base input. + if (II.DataFlowTraceForFocusFunction.empty() && BaseII) + II.DataFlowTraceForFocusFunction = BaseII->DataFlowTraceForFocusFunction; + DistributionNeedsUpdate = true; + PrintCorpus(); + // ValidateFeatureSet(); + return &II; + } + + // Debug-only + void PrintUnit(const Unit &U) { + if (!FeatureDebug) return; + for (uint8_t C : U) { + if (C != 'F' && C != 'U' && C != 'Z') + C = '.'; + Printf("%c", C); + } + } + + // Debug-only + void PrintFeatureSet(const std::vector &FeatureSet) { + if (!FeatureDebug) return; + Printf("{"); + for (uint32_t Feature: FeatureSet) + Printf("%u,", Feature); + Printf("}"); + } + + // Debug-only + void PrintCorpus() { + if (!FeatureDebug) return; + Printf("======= CORPUS:\n"); + int i = 0; + for (auto II : Inputs) { + if (std::find(II->U.begin(), II->U.end(), 'F') != II->U.end()) { + Printf("[%2d] ", i); + Printf("%s sz=%zd ", Sha1ToString(II->Sha1).c_str(), II->U.size()); + PrintUnit(II->U); + Printf(" "); + PrintFeatureSet(II->UniqFeatureSet); + Printf("\n"); + } + i++; + } + } + + void Replace(InputInfo *II, const Unit &U, + std::chrono::microseconds TimeOfUnit) { + assert(II->U.size() > U.size()); + Hashes.erase(Sha1ToString(II->Sha1)); + DeleteFile(*II); + ComputeSHA1(U.data(), U.size(), II->Sha1); + Hashes.insert(Sha1ToString(II->Sha1)); + II->U = U; + II->Reduced = true; + II->TimeOfUnit = TimeOfUnit; + DistributionNeedsUpdate = true; + } + + bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); } + bool HasUnit(const std::string &H) { return Hashes.count(H); } + InputInfo &ChooseUnitToMutate(Random &Rand) { + InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)]; + assert(!II.U.empty()); + return II; + } + + InputInfo &ChooseUnitToCrossOverWith(Random &Rand, bool UniformDist) { + if (!UniformDist) { + return ChooseUnitToMutate(Rand); + } + InputInfo &II = *Inputs[Rand(Inputs.size())]; + assert(!II.U.empty()); + return II; + } + + // Returns an index of random unit from the corpus to mutate. + size_t ChooseUnitIdxToMutate(Random &Rand) { + UpdateCorpusDistribution(Rand); + size_t Idx = static_cast(CorpusDistribution(Rand)); + assert(Idx < Inputs.size()); + return Idx; + } + + void PrintStats() { + for (size_t i = 0; i < Inputs.size(); i++) { + const auto &II = *Inputs[i]; + Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i, + Sha1ToString(II.Sha1).c_str(), II.U.size(), + II.NumExecutedMutations, II.NumSuccessfullMutations, + II.HasFocusFunction); + } + } + + void PrintFeatureSet() { + for (size_t i = 0; i < kFeatureSetSize; i++) { + if(size_t Sz = GetFeature(i)) + Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz); + } + Printf("\n\t"); + for (size_t i = 0; i < Inputs.size(); i++) + if (size_t N = Inputs[i]->NumFeatures) + Printf(" %zd=>%zd ", i, N); + Printf("\n"); + } + + void DeleteFile(const InputInfo &II) { + if (!OutputCorpus.empty() && II.MayDeleteFile) + RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1))); + } + + void DeleteInput(size_t Idx) { + InputInfo &II = *Inputs[Idx]; + DeleteFile(II); + Unit().swap(II.U); + II.Energy = 0.0; + II.NeedsEnergyUpdate = false; + DistributionNeedsUpdate = true; + if (FeatureDebug) + Printf("EVICTED %zd\n", Idx); + } + + void AddRareFeature(uint32_t Idx) { + // Maintain *at least* TopXRarestFeatures many rare features + // and all features with a frequency below ConsideredRare. + // Remove all other features. + while (RareFeatures.size() > Entropic.NumberOfRarestFeatures && + FreqOfMostAbundantRareFeature > Entropic.FeatureFrequencyThreshold) { + + // Find most and second most abbundant feature. + uint32_t MostAbundantRareFeatureIndices[2] = {RareFeatures[0], + RareFeatures[0]}; + size_t Delete = 0; + for (size_t i = 0; i < RareFeatures.size(); i++) { + uint32_t Idx2 = RareFeatures[i]; + if (GlobalFeatureFreqs[Idx2] >= + GlobalFeatureFreqs[MostAbundantRareFeatureIndices[0]]) { + MostAbundantRareFeatureIndices[1] = MostAbundantRareFeatureIndices[0]; + MostAbundantRareFeatureIndices[0] = Idx2; + Delete = i; + } + } + + // Remove most abundant rare feature. + IsRareFeature[Delete] = false; + RareFeatures[Delete] = RareFeatures.back(); + RareFeatures.pop_back(); + + for (auto II : Inputs) { + if (II->DeleteFeatureFreq(MostAbundantRareFeatureIndices[0])) + II->NeedsEnergyUpdate = true; + } + + // Set 2nd most abundant as the new most abundant feature count. + FreqOfMostAbundantRareFeature = + GlobalFeatureFreqs[MostAbundantRareFeatureIndices[1]]; + } + + // Add rare feature, handle collisions, and update energy. + RareFeatures.push_back(Idx); + IsRareFeature[Idx] = true; + GlobalFeatureFreqs[Idx] = 0; + for (auto II : Inputs) { + II->DeleteFeatureFreq(Idx); + + // Apply add-one smoothing to this locally undiscovered feature. + // Zero energy seeds will never be fuzzed and remain zero energy. + if (II->Energy > 0.0) { + II->SumIncidence += 1; + II->Energy += log(II->SumIncidence) / II->SumIncidence; + } + } + + DistributionNeedsUpdate = true; + } + + bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) { + assert(NewSize); + Idx = Idx % kFeatureSetSize; + uint32_t OldSize = GetFeature(Idx); + if (OldSize == 0 || (Shrink && OldSize > NewSize)) { + if (OldSize > 0) { + size_t OldIdx = SmallestElementPerFeature[Idx]; + InputInfo &II = *Inputs[OldIdx]; + assert(II.NumFeatures > 0); + II.NumFeatures--; + if (II.NumFeatures == 0) + DeleteInput(OldIdx); + } else { + NumAddedFeatures++; + if (Entropic.Enabled) + AddRareFeature((uint32_t)Idx); + } + NumUpdatedFeatures++; + if (FeatureDebug) + Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize); + // Inputs.size() is guaranteed to be less than UINT32_MAX by AddToCorpus. + SmallestElementPerFeature[Idx] = static_cast(Inputs.size()); + InputSizesPerFeature[Idx] = NewSize; + return true; + } + return false; + } + + // Increment frequency of feature Idx globally and locally. + void UpdateFeatureFrequency(InputInfo *II, size_t Idx) { + uint32_t Idx32 = Idx % kFeatureSetSize; + + // Saturated increment. + if (GlobalFeatureFreqs[Idx32] == 0xFFFF) + return; + uint16_t Freq = GlobalFeatureFreqs[Idx32]++; + + // Skip if abundant. + if (Freq > FreqOfMostAbundantRareFeature || !IsRareFeature[Idx32]) + return; + + // Update global frequencies. + if (Freq == FreqOfMostAbundantRareFeature) + FreqOfMostAbundantRareFeature++; + + // Update local frequencies. + if (II) + II->UpdateFeatureFrequency(Idx32); + } + + size_t NumFeatures() const { return NumAddedFeatures; } + size_t NumFeatureUpdates() const { return NumUpdatedFeatures; } + +private: + + static const bool FeatureDebug = false; + + uint32_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; } + + void ValidateFeatureSet() { + if (FeatureDebug) + PrintFeatureSet(); + for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) + if (GetFeature(Idx)) + Inputs[SmallestElementPerFeature[Idx]]->Tmp++; + for (auto II: Inputs) { + if (II->Tmp != II->NumFeatures) + Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures); + assert(II->Tmp == II->NumFeatures); + II->Tmp = 0; + } + } + + // Updates the probability distribution for the units in the corpus. + // Must be called whenever the corpus or unit weights are changed. + // + // Hypothesis: inputs that maximize information about globally rare features + // are interesting. + void UpdateCorpusDistribution(Random &Rand) { + // Skip update if no seeds or rare features were added/deleted. + // Sparse updates for local change of feature frequencies, + // i.e., randomly do not skip. + if (!DistributionNeedsUpdate && + (!Entropic.Enabled || Rand(kSparseEnergyUpdates))) + return; + + DistributionNeedsUpdate = false; + + size_t N = Inputs.size(); + assert(N); + Intervals.resize(N + 1); + Weights.resize(N); + std::iota(Intervals.begin(), Intervals.end(), 0); + + std::chrono::microseconds AverageUnitExecutionTime(0); + for (auto II : Inputs) { + AverageUnitExecutionTime += II->TimeOfUnit; + } + AverageUnitExecutionTime /= N; + + bool VanillaSchedule = true; + if (Entropic.Enabled) { + for (auto II : Inputs) { + if (II->NeedsEnergyUpdate && II->Energy != 0.0) { + II->NeedsEnergyUpdate = false; + II->UpdateEnergy(RareFeatures.size(), Entropic.ScalePerExecTime, + AverageUnitExecutionTime); + } + } + + for (size_t i = 0; i < N; i++) { + + if (Inputs[i]->NumFeatures == 0) { + // If the seed doesn't represent any features, assign zero energy. + Weights[i] = 0.; + } else if (Inputs[i]->NumExecutedMutations / kMaxMutationFactor > + NumExecutedMutations / Inputs.size()) { + // If the seed was fuzzed a lot more than average, assign zero energy. + Weights[i] = 0.; + } else { + // Otherwise, simply assign the computed energy. + Weights[i] = Inputs[i]->Energy; + } + + // If energy for all seeds is zero, fall back to vanilla schedule. + if (Weights[i] > 0.0) + VanillaSchedule = false; + } + } + + if (VanillaSchedule) { + for (size_t i = 0; i < N; i++) + Weights[i] = + Inputs[i]->NumFeatures + ? static_cast((i + 1) * + (Inputs[i]->HasFocusFunction ? 1000 : 1)) + : 0.; + } + + if (FeatureDebug) { + for (size_t i = 0; i < N; i++) + Printf("%zd ", Inputs[i]->NumFeatures); + Printf("SCORE\n"); + for (size_t i = 0; i < N; i++) + Printf("%f ", Weights[i]); + Printf("Weights\n"); + } + CorpusDistribution = std::piecewise_constant_distribution( + Intervals.begin(), Intervals.end(), Weights.begin()); + } + std::piecewise_constant_distribution CorpusDistribution; + + std::vector Intervals; + std::vector Weights; + + std::unordered_set Hashes; + std::vector Inputs; + + size_t NumAddedFeatures = 0; + size_t NumUpdatedFeatures = 0; + uint32_t InputSizesPerFeature[kFeatureSetSize]; + uint32_t SmallestElementPerFeature[kFeatureSetSize]; + + bool DistributionNeedsUpdate = true; + uint16_t FreqOfMostAbundantRareFeature = 0; + uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {}; + std::vector RareFeatures; + std::bitset IsRareFeature; + + std::string OutputCorpus; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_CORPUS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCrossOver.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCrossOver.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCrossOver.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerCrossOver.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Cross over test inputs. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include + +namespace fuzzer { + +// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. +size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize) { + assert(Size1 || Size2); + MaxOutSize = Rand(MaxOutSize) + 1; + size_t OutPos = 0; + size_t Pos1 = 0; + size_t Pos2 = 0; + size_t *InPos = &Pos1; + size_t InSize = Size1; + const uint8_t *Data = Data1; + bool CurrentlyUsingFirstData = true; + while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { + // Merge a part of Data into Out. + size_t OutSizeLeft = MaxOutSize - OutPos; + if (*InPos < InSize) { + size_t InSizeLeft = InSize - *InPos; + size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); + size_t ExtraSize = Rand(MaxExtraSize) + 1; + memcpy(Out + OutPos, Data + *InPos, ExtraSize); + OutPos += ExtraSize; + (*InPos) += ExtraSize; + } + // Use the other input data on the next iteration. + InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; + InSize = CurrentlyUsingFirstData ? Size2 : Size1; + Data = CurrentlyUsingFirstData ? Data2 : Data1; + CurrentlyUsingFirstData = !CurrentlyUsingFirstData; + } + return OutPos; +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,288 @@ +//===- FuzzerDataFlowTrace.cpp - DataFlowTrace ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::DataFlowTrace +//===----------------------------------------------------------------------===// + +#include "FuzzerDataFlowTrace.h" + +#include "FuzzerCommand.h" +#include "FuzzerIO.h" +#include "FuzzerRandom.h" +#include "FuzzerSHA1.h" +#include "FuzzerUtil.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { +static const char *kFunctionsTxt = "functions.txt"; + +bool BlockCoverage::AppendCoverage(const std::string &S) { + std::stringstream SS(S); + return AppendCoverage(SS); +} + +// Coverage lines have this form: +// CN X Y Z T +// where N is the number of the function, T is the total number of instrumented +// BBs, and X,Y,Z, if present, are the indices of covered BB. +// BB #0, which is the entry block, is not explicitly listed. +bool BlockCoverage::AppendCoverage(std::istream &IN) { + std::string L; + while (std::getline(IN, L, '\n')) { + if (L.empty()) + continue; + std::stringstream SS(L.c_str() + 1); + size_t FunctionId = 0; + SS >> FunctionId; + if (L[0] == 'F') { + FunctionsWithDFT.insert(FunctionId); + continue; + } + if (L[0] != 'C') continue; + std::vector CoveredBlocks; + while (true) { + uint32_t BB = 0; + SS >> BB; + if (!SS) break; + CoveredBlocks.push_back(BB); + } + if (CoveredBlocks.empty()) return false; + // Ensures no CoverageVector is longer than UINT32_MAX. + uint32_t NumBlocks = CoveredBlocks.back(); + CoveredBlocks.pop_back(); + for (auto BB : CoveredBlocks) + if (BB >= NumBlocks) return false; + auto It = Functions.find(FunctionId); + auto &Counters = + It == Functions.end() + ? Functions.insert({FunctionId, std::vector(NumBlocks)}) + .first->second + : It->second; + + if (Counters.size() != NumBlocks) return false; // wrong number of blocks. + + Counters[0]++; + for (auto BB : CoveredBlocks) + Counters[BB]++; + } + return true; +} + +// Assign weights to each function. +// General principles: +// * any uncovered function gets weight 0. +// * a function with lots of uncovered blocks gets bigger weight. +// * a function with a less frequently executed code gets bigger weight. +std::vector BlockCoverage::FunctionWeights(size_t NumFunctions) const { + std::vector Res(NumFunctions); + for (const auto &It : Functions) { + auto FunctionID = It.first; + auto Counters = It.second; + assert(FunctionID < NumFunctions); + auto &Weight = Res[FunctionID]; + // Give higher weight if the function has a DFT. + Weight = FunctionsWithDFT.count(FunctionID) ? 1000. : 1; + // Give higher weight to functions with less frequently seen basic blocks. + Weight /= SmallestNonZeroCounter(Counters); + // Give higher weight to functions with the most uncovered basic blocks. + Weight *= NumberOfUncoveredBlocks(Counters) + 1; + } + return Res; +} + +void DataFlowTrace::ReadCoverage(const std::string &DirPath) { + std::vector Files; + GetSizedFilesFromDir(DirPath, &Files); + for (auto &SF : Files) { + auto Name = Basename(SF.File); + if (Name == kFunctionsTxt) continue; + if (!CorporaHashes.count(Name)) continue; + std::ifstream IF(SF.File); + Coverage.AppendCoverage(IF); + } +} + +static void DFTStringAppendToVector(std::vector *DFT, + const std::string &DFTString) { + assert(DFT->size() == DFTString.size()); + for (size_t I = 0, Len = DFT->size(); I < Len; I++) + (*DFT)[I] = DFTString[I] == '1'; +} + +// converts a string of '0' and '1' into a std::vector +static std::vector DFTStringToVector(const std::string &DFTString) { + std::vector DFT(DFTString.size()); + DFTStringAppendToVector(&DFT, DFTString); + return DFT; +} + +static bool ParseError(const char *Err, const std::string &Line) { + Printf("DataFlowTrace: parse error: %s: Line: %s\n", Err, Line.c_str()); + return false; +} + +// TODO(metzman): replace std::string with std::string_view for +// better performance. Need to figure our how to use string_view on Windows. +static bool ParseDFTLine(const std::string &Line, size_t *FunctionNum, + std::string *DFTString) { + if (!Line.empty() && Line[0] != 'F') + return false; // Ignore coverage. + size_t SpacePos = Line.find(' '); + if (SpacePos == std::string::npos) + return ParseError("no space in the trace line", Line); + if (Line.empty() || Line[0] != 'F') + return ParseError("the trace line doesn't start with 'F'", Line); + *FunctionNum = std::atol(Line.c_str() + 1); + const char *Beg = Line.c_str() + SpacePos + 1; + const char *End = Line.c_str() + Line.size(); + assert(Beg < End); + size_t Len = End - Beg; + for (size_t I = 0; I < Len; I++) { + if (Beg[I] != '0' && Beg[I] != '1') + return ParseError("the trace should contain only 0 or 1", Line); + } + *DFTString = Beg; + return true; +} + +bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, + std::vector &CorporaFiles, Random &Rand) { + if (DirPath.empty()) return false; + Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); + std::vector Files; + GetSizedFilesFromDir(DirPath, &Files); + std::string L; + size_t FocusFuncIdx = SIZE_MAX; + std::vector FunctionNames; + + // Collect the hashes of the corpus files. + for (auto &SF : CorporaFiles) + CorporaHashes.insert(Hash(FileToVector(SF.File))); + + // Read functions.txt + std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt)); + size_t NumFunctions = 0; + while (std::getline(IF, L, '\n')) { + FunctionNames.push_back(L); + NumFunctions++; + if (*FocusFunction == L) + FocusFuncIdx = NumFunctions - 1; + } + if (!NumFunctions) + return false; + + if (*FocusFunction == "auto") { + // AUTOFOCUS works like this: + // * reads the coverage data from the DFT files. + // * assigns weights to functions based on coverage. + // * chooses a random function according to the weights. + ReadCoverage(DirPath); + auto Weights = Coverage.FunctionWeights(NumFunctions); + std::vector Intervals(NumFunctions + 1); + std::iota(Intervals.begin(), Intervals.end(), 0); + auto Distribution = std::piecewise_constant_distribution( + Intervals.begin(), Intervals.end(), Weights.begin()); + FocusFuncIdx = static_cast(Distribution(Rand)); + *FocusFunction = FunctionNames[FocusFuncIdx]; + assert(FocusFuncIdx < NumFunctions); + Printf("INFO: AUTOFOCUS: %zd %s\n", FocusFuncIdx, + FunctionNames[FocusFuncIdx].c_str()); + for (size_t i = 0; i < NumFunctions; i++) { + if (Weights[i] == 0.0) + continue; + Printf(" [%zd] W %g\tBB-tot %u\tBB-cov %u\tEntryFreq %u:\t%s\n", i, + Weights[i], Coverage.GetNumberOfBlocks(i), + Coverage.GetNumberOfCoveredBlocks(i), Coverage.GetCounter(i, 0), + FunctionNames[i].c_str()); + } + } + + if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1) + return false; + + // Read traces. + size_t NumTraceFiles = 0; + size_t NumTracesWithFocusFunction = 0; + for (auto &SF : Files) { + auto Name = Basename(SF.File); + if (Name == kFunctionsTxt) continue; + if (!CorporaHashes.count(Name)) continue; // not in the corpus. + NumTraceFiles++; + // Printf("=== %s\n", Name.c_str()); + std::ifstream IF(SF.File); + while (std::getline(IF, L, '\n')) { + size_t FunctionNum = 0; + std::string DFTString; + if (ParseDFTLine(L, &FunctionNum, &DFTString) && + FunctionNum == FocusFuncIdx) { + NumTracesWithFocusFunction++; + + if (FunctionNum >= NumFunctions) + return ParseError("N is greater than the number of functions", L); + Traces[Name] = DFTStringToVector(DFTString); + // Print just a few small traces. + if (NumTracesWithFocusFunction <= 3 && DFTString.size() <= 16) + Printf("%s => |%s|\n", Name.c_str(), std::string(DFTString).c_str()); + break; // No need to parse the following lines. + } + } + } + Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, " + "%zd traces with focus function\n", + NumTraceFiles, NumFunctions, NumTracesWithFocusFunction); + return NumTraceFiles > 0; +} + +int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, + const std::vector &CorporaFiles) { + Printf("INFO: collecting data flow: bin: %s dir: %s files: %zd\n", + DFTBinary.c_str(), DirPath.c_str(), CorporaFiles.size()); + if (CorporaFiles.empty()) { + Printf("ERROR: can't collect data flow without corpus provided."); + return 1; + } + + static char DFSanEnv[] = "DFSAN_OPTIONS=warn_unimplemented=0"; + putenv(DFSanEnv); + MkDir(DirPath); + for (auto &F : CorporaFiles) { + // For every input F we need to collect the data flow and the coverage. + // Data flow collection may fail if we request too many DFSan tags at once. + // So, we start from requesting all tags in range [0,Size) and if that fails + // we then request tags in [0,Size/2) and [Size/2, Size), and so on. + // Function number => DFT. + auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File))); + std::unordered_map> DFTMap; + std::unordered_set Cov; + Command Cmd; + Cmd.addArgument(DFTBinary); + Cmd.addArgument(F.File); + Cmd.addArgument(OutPath); + Printf("CMD: %s\n", Cmd.toString().c_str()); + ExecuteCommand(Cmd); + } + // Write functions.txt if it's currently empty or doesn't exist. + auto FunctionsTxtPath = DirPlusFile(DirPath, kFunctionsTxt); + if (FileToString(FunctionsTxtPath).empty()) { + Command Cmd; + Cmd.addArgument(DFTBinary); + Cmd.setOutputFile(FunctionsTxtPath); + ExecuteCommand(Cmd); + } + return 0; +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDataFlowTrace.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,137 @@ +//===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::DataFlowTrace; reads and handles a data-flow trace. +// +// A data flow trace is generated by e.g. dataflow/DataFlow.cpp +// and is stored on disk in a separate directory. +// +// The trace dir contains a file 'functions.txt' which lists function names, +// oner per line, e.g. +// ==> functions.txt <== +// Func2 +// LLVMFuzzerTestOneInput +// Func1 +// +// All other files in the dir are the traces, see dataflow/DataFlow.cpp. +// The name of the file is sha1 of the input used to generate the trace. +// +// Current status: +// the data is parsed and the summary is printed, but the data is not yet +// used in any other way. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_DATA_FLOW_TRACE +#define LLVM_FUZZER_DATA_FLOW_TRACE + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" + +#include +#include +#include +#include + +namespace fuzzer { + +int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, + const std::vector &CorporaFiles); + +class BlockCoverage { +public: + // These functions guarantee no CoverageVector is longer than UINT32_MAX. + bool AppendCoverage(std::istream &IN); + bool AppendCoverage(const std::string &S); + + size_t NumCoveredFunctions() const { return Functions.size(); } + + uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) { + auto It = Functions.find(FunctionId); + if (It == Functions.end()) + return 0; + const auto &Counters = It->second; + if (BasicBlockId < Counters.size()) + return Counters[BasicBlockId]; + return 0; + } + + uint32_t GetNumberOfBlocks(size_t FunctionId) { + auto It = Functions.find(FunctionId); + if (It == Functions.end()) return 0; + const auto &Counters = It->second; + return static_cast(Counters.size()); + } + + uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) { + auto It = Functions.find(FunctionId); + if (It == Functions.end()) return 0; + const auto &Counters = It->second; + uint32_t Result = 0; + for (auto Cnt: Counters) + if (Cnt) + Result++; + return Result; + } + + std::vector FunctionWeights(size_t NumFunctions) const; + void clear() { Functions.clear(); } + +private: + typedef std::vector CoverageVector; + + uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { + uint32_t Res = 0; + for (auto Cnt : Counters) + if (Cnt) + Res++; + return Res; + } + + uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const { + return static_cast(Counters.size()) - + NumberOfCoveredBlocks(Counters); + } + + uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const { + assert(!Counters.empty()); + uint32_t Res = Counters[0]; + for (auto Cnt : Counters) + if (Cnt) + Res = Min(Res, Cnt); + assert(Res); + return Res; + } + + // Function ID => vector of counters. + // Each counter represents how many input files trigger the given basic block. + std::unordered_map Functions; + // Functions that have DFT entry. + std::unordered_set FunctionsWithDFT; +}; + +class DataFlowTrace { + public: + void ReadCoverage(const std::string &DirPath); + bool Init(const std::string &DirPath, std::string *FocusFunction, + std::vector &CorporaFiles, Random &Rand); + void Clear() { Traces.clear(); } + const std::vector *Get(const std::string &InputSha1) const { + auto It = Traces.find(InputSha1); + if (It != Traces.end()) + return &It->second; + return nullptr; + } + + private: + // Input's sha1 => DFT for the FocusFunction. + std::unordered_map> Traces; + BlockCoverage Coverage; + std::unordered_set CorporaHashes; +}; +} // namespace fuzzer + +#endif // LLVM_FUZZER_DATA_FLOW_TRACE diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDefs.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDefs.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDefs.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDefs.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Basic definitions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_DEFS_H +#define LLVM_FUZZER_DEFS_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace fuzzer { + +template T Min(T a, T b) { return a < b ? a : b; } +template T Max(T a, T b) { return a > b ? a : b; } + +class Random; +class Dictionary; +class DictionaryEntry; +class MutationDispatcher; +struct FuzzingOptions; +class InputCorpus; +struct InputInfo; +struct ExternalFunctions; + +// Global interface to functions that may or may not be available. +extern ExternalFunctions *EF; + +typedef std::vector Unit; +typedef std::vector UnitVector; +typedef int (*UserCallback)(const uint8_t *Data, size_t Size); + +int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); + +uint8_t *ExtraCountersBegin(); +uint8_t *ExtraCountersEnd(); +void ClearExtraCounters(); + +extern bool RunningUserCallback; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_DEFS_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDictionary.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDictionary.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDictionary.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDictionary.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::Dictionary +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_DICTIONARY_H +#define LLVM_FUZZER_DICTIONARY_H + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" +#include "FuzzerUtil.h" +#include +#include + +namespace fuzzer { +// A simple POD sized array of bytes. +template class FixedWord { +public: + static const size_t kMaxSize = kMaxSizeT; + FixedWord() {} + FixedWord(const uint8_t *B, size_t S) { Set(B, S); } + + void Set(const uint8_t *B, size_t S) { + static_assert(kMaxSizeT <= std::numeric_limits::max(), + "FixedWord::kMaxSizeT cannot fit in a uint8_t."); + assert(S <= kMaxSize); + // memcpy cannot take null pointer arguments even if Size is 0. + if (S) + memcpy(Data, B, S); + Size = static_cast(S); + } + + bool operator==(const FixedWord &w) const { + return Size == w.Size && 0 == memcmp(Data, w.Data, Size); + } + + static size_t GetMaxSize() { return kMaxSize; } + const uint8_t *data() const { return Data; } + uint8_t size() const { return Size; } + +private: + uint8_t Size = 0; + uint8_t Data[kMaxSize]; +}; + +typedef FixedWord<64> Word; + +class DictionaryEntry { + public: + DictionaryEntry() {} + DictionaryEntry(Word W) : W(W) {} + DictionaryEntry(Word W, size_t PositionHint) + : W(W), PositionHint(PositionHint) {} + const Word &GetW() const { return W; } + + bool HasPositionHint() const { + return PositionHint != std::numeric_limits::max(); + } + size_t GetPositionHint() const { + assert(HasPositionHint()); + return PositionHint; + } + void IncUseCount() { UseCount++; } + void IncSuccessCount() { SuccessCount++; } + size_t GetUseCount() const { return UseCount; } + size_t GetSuccessCount() const {return SuccessCount; } + + void Print(const char *PrintAfter = "\n") { + PrintASCII(W.data(), W.size()); + if (HasPositionHint()) + Printf("@%zd", GetPositionHint()); + Printf("%s", PrintAfter); + } + +private: + Word W; + size_t PositionHint = std::numeric_limits::max(); + size_t UseCount = 0; + size_t SuccessCount = 0; +}; + +class Dictionary { + public: + static const size_t kMaxDictSize = 1 << 14; + + bool ContainsWord(const Word &W) const { + return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { + return DE.GetW() == W; + }); + } + const DictionaryEntry *begin() const { return &DE[0]; } + const DictionaryEntry *end() const { return begin() + Size; } + DictionaryEntry & operator[] (size_t Idx) { + assert(Idx < Size); + return DE[Idx]; + } + void push_back(DictionaryEntry DE) { + if (Size < kMaxDictSize) + this->DE[Size++] = DE; + } + void clear() { Size = 0; } + bool empty() const { return Size == 0; } + size_t size() const { return Size; } + +private: + DictionaryEntry DE[kMaxDictSize]; + size_t Size = 0; +}; + +// Parses one dictionary entry. +// If successful, writes the entry to Unit and returns true, +// otherwise returns false. +bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); +// Parses the dictionary file, fills Units, returns true iff all lines +// were parsed successfully. +bool ParseDictionaryFile(const std::string &Text, std::vector *Units); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_DICTIONARY_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDriver.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDriver.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDriver.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerDriver.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,934 @@ +//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// FuzzerDriver and flag parsing. +//===----------------------------------------------------------------------===// + +#include "FuzzerCommand.h" +#include "FuzzerCorpus.h" +#include "FuzzerFork.h" +#include "FuzzerIO.h" +#include "FuzzerInterface.h" +#include "FuzzerInternal.h" +#include "FuzzerMerge.h" +#include "FuzzerMutate.h" +#include "FuzzerPlatform.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This function should be present in the libFuzzer so that the client +// binary can test for its existence. +#if LIBFUZZER_MSVC +extern "C" void __libfuzzer_is_present() {} +#if defined(_M_IX86) || defined(__i386__) +#pragma comment(linker, "/include:___libfuzzer_is_present") +#else +#pragma comment(linker, "/include:__libfuzzer_is_present") +#endif +#else +extern "C" __attribute__((used)) void __libfuzzer_is_present() {} +#endif // LIBFUZZER_MSVC + +namespace fuzzer { + +// Program arguments. +struct FlagDescription { + const char *Name; + const char *Description; + int Default; + int *IntFlag; + const char **StrFlag; + unsigned int *UIntFlag; +}; + +struct { +#define FUZZER_DEPRECATED_FLAG(Name) +#define FUZZER_FLAG_INT(Name, Default, Description) int Name; +#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name; +#define FUZZER_FLAG_STRING(Name, Description) const char *Name; +#include "FuzzerFlags.def" +#undef FUZZER_DEPRECATED_FLAG +#undef FUZZER_FLAG_INT +#undef FUZZER_FLAG_UNSIGNED +#undef FUZZER_FLAG_STRING +} Flags; + +static const FlagDescription FlagDescriptions [] { +#define FUZZER_DEPRECATED_FLAG(Name) \ + {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr}, +#define FUZZER_FLAG_INT(Name, Default, Description) \ + {#Name, Description, Default, &Flags.Name, nullptr, nullptr}, +#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ + {#Name, Description, static_cast(Default), \ + nullptr, nullptr, &Flags.Name}, +#define FUZZER_FLAG_STRING(Name, Description) \ + {#Name, Description, 0, nullptr, &Flags.Name, nullptr}, +#include "FuzzerFlags.def" +#undef FUZZER_DEPRECATED_FLAG +#undef FUZZER_FLAG_INT +#undef FUZZER_FLAG_UNSIGNED +#undef FUZZER_FLAG_STRING +}; + +static const size_t kNumFlags = + sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); + +static std::vector *Inputs; +static std::string *ProgName; + +static void PrintHelp() { + Printf("Usage:\n"); + auto Prog = ProgName->c_str(); + Printf("\nTo run fuzzing pass 0 or more directories.\n"); + Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog); + + Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n"); + Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog); + + Printf("\nFlags: (strictly in form -flag=value)\n"); + size_t MaxFlagLen = 0; + for (size_t F = 0; F < kNumFlags; F++) + MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen); + + for (size_t F = 0; F < kNumFlags; F++) { + const auto &D = FlagDescriptions[F]; + if (strstr(D.Description, "internal flag") == D.Description) continue; + Printf(" %s", D.Name); + for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) + Printf(" "); + Printf("\t"); + Printf("%d\t%s\n", D.Default, D.Description); + } + Printf("\nFlags starting with '--' will be ignored and " + "will be passed verbatim to subprocesses.\n"); +} + +static const char *FlagValue(const char *Param, const char *Name) { + size_t Len = strlen(Name); + if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 && + Param[Len + 1] == '=') + return &Param[Len + 2]; + return nullptr; +} + +// Avoid calling stol as it triggers a bug in clang/glibc build. +static long MyStol(const char *Str) { + long Res = 0; + long Sign = 1; + if (*Str == '-') { + Str++; + Sign = -1; + } + for (size_t i = 0; Str[i]; i++) { + char Ch = Str[i]; + if (Ch < '0' || Ch > '9') + return Res; + Res = Res * 10 + (Ch - '0'); + } + return Res * Sign; +} + +static bool ParseOneFlag(const char *Param) { + if (Param[0] != '-') return false; + if (Param[1] == '-') { + static bool PrintedWarning = false; + if (!PrintedWarning) { + PrintedWarning = true; + Printf("INFO: libFuzzer ignores flags that start with '--'\n"); + } + for (size_t F = 0; F < kNumFlags; F++) + if (FlagValue(Param + 1, FlagDescriptions[F].Name)) + Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1); + return true; + } + for (size_t F = 0; F < kNumFlags; F++) { + const char *Name = FlagDescriptions[F].Name; + const char *Str = FlagValue(Param, Name); + if (Str) { + if (FlagDescriptions[F].IntFlag) { + auto Val = MyStol(Str); + *FlagDescriptions[F].IntFlag = static_cast(Val); + if (Flags.verbosity >= 2) + Printf("Flag: %s %d\n", Name, Val); + return true; + } else if (FlagDescriptions[F].UIntFlag) { + auto Val = std::stoul(Str); + *FlagDescriptions[F].UIntFlag = static_cast(Val); + if (Flags.verbosity >= 2) + Printf("Flag: %s %u\n", Name, Val); + return true; + } else if (FlagDescriptions[F].StrFlag) { + *FlagDescriptions[F].StrFlag = Str; + if (Flags.verbosity >= 2) + Printf("Flag: %s %s\n", Name, Str); + return true; + } else { // Deprecated flag. + Printf("Flag: %s: deprecated, don't use\n", Name); + return true; + } + } + } + Printf("\n\nWARNING: unrecognized flag '%s'; " + "use -help=1 to list all flags\n\n", Param); + return true; +} + +// We don't use any library to minimize dependencies. +static void ParseFlags(const std::vector &Args, + const ExternalFunctions *EF) { + for (size_t F = 0; F < kNumFlags; F++) { + if (FlagDescriptions[F].IntFlag) + *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default; + if (FlagDescriptions[F].UIntFlag) + *FlagDescriptions[F].UIntFlag = + static_cast(FlagDescriptions[F].Default); + if (FlagDescriptions[F].StrFlag) + *FlagDescriptions[F].StrFlag = nullptr; + } + + // Disable len_control by default, if LLVMFuzzerCustomMutator is used. + if (EF->LLVMFuzzerCustomMutator) { + Flags.len_control = 0; + Printf("INFO: found LLVMFuzzerCustomMutator (%p). " + "Disabling -len_control by default.\n", EF->LLVMFuzzerCustomMutator); + } + + Inputs = new std::vector; + for (size_t A = 1; A < Args.size(); A++) { + if (ParseOneFlag(Args[A].c_str())) { + if (Flags.ignore_remaining_args) + break; + continue; + } + Inputs->push_back(Args[A]); + } +} + +static std::mutex Mu; + +static void PulseThread() { + while (true) { + SleepSeconds(600); + std::lock_guard Lock(Mu); + Printf("pulse...\n"); + } +} + +static void WorkerThread(const Command &BaseCmd, std::atomic *Counter, + unsigned NumJobs, std::atomic *HasErrors) { + ScopedDisableMsanInterceptorChecks S; + while (true) { + unsigned C = (*Counter)++; + if (C >= NumJobs) break; + std::string Log = "fuzz-" + std::to_string(C) + ".log"; + Command Cmd(BaseCmd); + Cmd.setOutputFile(Log); + Cmd.combineOutAndErr(); + if (Flags.verbosity) { + std::string CommandLine = Cmd.toString(); + Printf("%s\n", CommandLine.c_str()); + } + int ExitCode = ExecuteCommand(Cmd); + if (ExitCode != 0) + *HasErrors = true; + std::lock_guard Lock(Mu); + Printf("================== Job %u exited with exit code %d ============\n", + C, ExitCode); + fuzzer::CopyFileToErr(Log); + } +} + +static void ValidateDirectoryExists(const std::string &Path, + bool CreateDirectory) { + if (Path.empty()) { + Printf("ERROR: Provided directory path is an empty string\n"); + exit(1); + } + + if (IsDirectory(Path)) + return; + + if (CreateDirectory) { + if (!MkDirRecursive(Path)) { + Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str()); + exit(1); + } + return; + } + + Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str()); + exit(1); +} + +std::string CloneArgsWithoutX(const std::vector &Args, + const char *X1, const char *X2) { + std::string Cmd; + for (auto &S : Args) { + if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) + continue; + Cmd += S + " "; + } + return Cmd; +} + +static int RunInMultipleProcesses(const std::vector &Args, + unsigned NumWorkers, unsigned NumJobs) { + std::atomic Counter(0); + std::atomic HasErrors(false); + Command Cmd(Args); + Cmd.removeFlag("jobs"); + Cmd.removeFlag("workers"); + std::vector V; + std::thread Pulse(PulseThread); + Pulse.detach(); + V.resize(NumWorkers); + for (unsigned i = 0; i < NumWorkers; i++) { + V[i] = std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, + &HasErrors); + SetThreadName(V[i], "FuzzerWorker"); + } + for (auto &T : V) + T.join(); + return HasErrors ? 1 : 0; +} + +static void RssThread(Fuzzer *F, size_t RssLimitMb) { + while (true) { + SleepSeconds(1); + size_t Peak = GetPeakRSSMb(); + if (Peak > RssLimitMb) + F->RssLimitCallback(); + } +} + +static void StartRssThread(Fuzzer *F, size_t RssLimitMb) { + if (!RssLimitMb) + return; + std::thread T(RssThread, F, RssLimitMb); + T.detach(); +} + +int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { + Unit U = FileToVector(InputFilePath); + if (MaxLen && MaxLen < U.size()) + U.resize(MaxLen); + F->ExecuteCallback(U.data(), U.size()); + if (Flags.print_full_coverage) { + // Leak detection is not needed when collecting full coverage data. + F->TPCUpdateObservedPCs(); + } else { + F->TryDetectingAMemoryLeak(U.data(), U.size(), true); + } + return 0; +} + +static bool AllInputsAreFiles() { + if (Inputs->empty()) return false; + for (auto &Path : *Inputs) + if (!IsFile(Path)) + return false; + return true; +} + +static std::string GetDedupTokenFromCmdOutput(const std::string &S) { + auto Beg = S.find("DEDUP_TOKEN:"); + if (Beg == std::string::npos) + return ""; + auto End = S.find('\n', Beg); + if (End == std::string::npos) + return ""; + return S.substr(Beg, End - Beg); +} + +int CleanseCrashInput(const std::vector &Args, + const FuzzingOptions &Options) { + if (Inputs->size() != 1 || !Flags.exact_artifact_path) { + Printf("ERROR: -cleanse_crash should be given one input file and" + " -exact_artifact_path\n"); + exit(1); + } + std::string InputFilePath = Inputs->at(0); + std::string OutputFilePath = Flags.exact_artifact_path; + Command Cmd(Args); + Cmd.removeFlag("cleanse_crash"); + + assert(Cmd.hasArgument(InputFilePath)); + Cmd.removeArgument(InputFilePath); + + auto TmpFilePath = TempPath("CleanseCrashInput", ".repro"); + Cmd.addArgument(TmpFilePath); + Cmd.setOutputFile(getDevNull()); + Cmd.combineOutAndErr(); + + std::string CurrentFilePath = InputFilePath; + auto U = FileToVector(CurrentFilePath); + size_t Size = U.size(); + + const std::vector ReplacementBytes = {' ', 0xff}; + for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) { + bool Changed = false; + for (size_t Idx = 0; Idx < Size; Idx++) { + Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts, + Idx, Size); + uint8_t OriginalByte = U[Idx]; + if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(), + ReplacementBytes.end(), + OriginalByte)) + continue; + for (auto NewByte : ReplacementBytes) { + U[Idx] = NewByte; + WriteToFile(U, TmpFilePath); + auto ExitCode = ExecuteCommand(Cmd); + RemoveFile(TmpFilePath); + if (!ExitCode) { + U[Idx] = OriginalByte; + } else { + Changed = true; + Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte); + WriteToFile(U, OutputFilePath); + break; + } + } + } + if (!Changed) break; + } + return 0; +} + +int MinimizeCrashInput(const std::vector &Args, + const FuzzingOptions &Options) { + if (Inputs->size() != 1) { + Printf("ERROR: -minimize_crash should be given one input file\n"); + exit(1); + } + std::string InputFilePath = Inputs->at(0); + Command BaseCmd(Args); + BaseCmd.removeFlag("minimize_crash"); + BaseCmd.removeFlag("exact_artifact_path"); + assert(BaseCmd.hasArgument(InputFilePath)); + BaseCmd.removeArgument(InputFilePath); + if (Flags.runs <= 0 && Flags.max_total_time == 0) { + Printf("INFO: you need to specify -runs=N or " + "-max_total_time=N with -minimize_crash=1\n" + "INFO: defaulting to -max_total_time=600\n"); + BaseCmd.addFlag("max_total_time", "600"); + } + + BaseCmd.combineOutAndErr(); + + std::string CurrentFilePath = InputFilePath; + while (true) { + Unit U = FileToVector(CurrentFilePath); + Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n", + CurrentFilePath.c_str(), U.size()); + + Command Cmd(BaseCmd); + Cmd.addArgument(CurrentFilePath); + + Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str()); + std::string CmdOutput; + bool Success = ExecuteCommand(Cmd, &CmdOutput); + if (Success) { + Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str()); + exit(1); + } + Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " + "it further\n", + CurrentFilePath.c_str(), U.size()); + auto DedupToken1 = GetDedupTokenFromCmdOutput(CmdOutput); + if (!DedupToken1.empty()) + Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str()); + + std::string ArtifactPath = + Flags.exact_artifact_path + ? Flags.exact_artifact_path + : Options.ArtifactPrefix + "minimized-from-" + Hash(U); + Cmd.addFlag("minimize_crash_internal_step", "1"); + Cmd.addFlag("exact_artifact_path", ArtifactPath); + Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str()); + CmdOutput.clear(); + Success = ExecuteCommand(Cmd, &CmdOutput); + Printf("%s", CmdOutput.c_str()); + if (Success) { + if (Flags.exact_artifact_path) { + CurrentFilePath = Flags.exact_artifact_path; + WriteToFile(U, CurrentFilePath); + } + Printf("CRASH_MIN: failed to minimize beyond %s (%zu bytes), exiting\n", + CurrentFilePath.c_str(), U.size()); + break; + } + auto DedupToken2 = GetDedupTokenFromCmdOutput(CmdOutput); + if (!DedupToken2.empty()) + Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str()); + + if (DedupToken1 != DedupToken2) { + if (Flags.exact_artifact_path) { + CurrentFilePath = Flags.exact_artifact_path; + WriteToFile(U, CurrentFilePath); + } + Printf("CRASH_MIN: mismatch in dedup tokens" + " (looks like a different bug). Won't minimize further\n"); + break; + } + + CurrentFilePath = ArtifactPath; + Printf("*********************************\n"); + } + return 0; +} + +int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { + assert(Inputs->size() == 1); + std::string InputFilePath = Inputs->at(0); + Unit U = FileToVector(InputFilePath); + Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size()); + if (U.size() < 2) { + Printf("INFO: The input is small enough, exiting\n"); + exit(0); + } + F->SetMaxInputLen(U.size()); + F->SetMaxMutationLen(U.size() - 1); + F->MinimizeCrashLoop(U); + Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n"); + exit(0); +} + +void Merge(Fuzzer *F, FuzzingOptions &Options, + const std::vector &Args, + const std::vector &Corpora, const char *CFPathOrNull) { + if (Corpora.size() < 2) { + Printf("INFO: Merge requires two or more corpus dirs\n"); + exit(0); + } + + std::vector OldCorpus, NewCorpus; + GetSizedFilesFromDir(Corpora[0], &OldCorpus); + for (size_t i = 1; i < Corpora.size(); i++) + GetSizedFilesFromDir(Corpora[i], &NewCorpus); + std::sort(OldCorpus.begin(), OldCorpus.end()); + std::sort(NewCorpus.begin(), NewCorpus.end()); + + std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath("Merge", ".txt"); + std::vector NewFiles; + std::set NewFeatures, NewCov; + CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures, + {}, &NewCov, CFPath, true, Flags.set_cover_merge); + for (auto &Path : NewFiles) + F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); + // We are done, delete the control file if it was a temporary one. + if (!Flags.merge_control_file) + RemoveFile(CFPath); + + exit(0); +} + +int AnalyzeDictionary(Fuzzer *F, const std::vector &Dict, + UnitVector &Corpus) { + Printf("Started dictionary minimization (up to %zu tests)\n", + Dict.size() * Corpus.size() * 2); + + // Scores and usage count for each dictionary unit. + std::vector Scores(Dict.size()); + std::vector Usages(Dict.size()); + + std::vector InitialFeatures; + std::vector ModifiedFeatures; + for (auto &C : Corpus) { + // Get coverage for the testcase without modifications. + F->ExecuteCallback(C.data(), C.size()); + InitialFeatures.clear(); + TPC.CollectFeatures([&](size_t Feature) { + InitialFeatures.push_back(Feature); + }); + + for (size_t i = 0; i < Dict.size(); ++i) { + std::vector Data = C; + auto StartPos = std::search(Data.begin(), Data.end(), + Dict[i].begin(), Dict[i].end()); + // Skip dictionary unit, if the testcase does not contain it. + if (StartPos == Data.end()) + continue; + + ++Usages[i]; + while (StartPos != Data.end()) { + // Replace all occurrences of dictionary unit in the testcase. + auto EndPos = StartPos + Dict[i].size(); + for (auto It = StartPos; It != EndPos; ++It) + *It ^= 0xFF; + + StartPos = std::search(EndPos, Data.end(), + Dict[i].begin(), Dict[i].end()); + } + + // Get coverage for testcase with masked occurrences of dictionary unit. + F->ExecuteCallback(Data.data(), Data.size()); + ModifiedFeatures.clear(); + TPC.CollectFeatures([&](size_t Feature) { + ModifiedFeatures.push_back(Feature); + }); + + if (InitialFeatures == ModifiedFeatures) + --Scores[i]; + else + Scores[i] += 2; + } + } + + Printf("###### Useless dictionary elements. ######\n"); + for (size_t i = 0; i < Dict.size(); ++i) { + // Dictionary units with positive score are treated as useful ones. + if (Scores[i] > 0) + continue; + + Printf("\""); + PrintASCII(Dict[i].data(), Dict[i].size(), "\""); + Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]); + } + Printf("###### End of useless dictionary elements. ######\n"); + return 0; +} + +std::vector ParseSeedInuts(const char *seed_inputs) { + // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file + std::vector Files; + if (!seed_inputs) return Files; + std::string SeedInputs; + if (Flags.seed_inputs[0] == '@') + SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list. + else + SeedInputs = Flags.seed_inputs; // seed_inputs contains the list. + if (SeedInputs.empty()) { + Printf("seed_inputs is empty or @file does not exist.\n"); + exit(1); + } + // Parse SeedInputs. + size_t comma_pos = 0; + while ((comma_pos = SeedInputs.find_last_of(',')) != std::string::npos) { + Files.push_back(SeedInputs.substr(comma_pos + 1)); + SeedInputs = SeedInputs.substr(0, comma_pos); + } + Files.push_back(SeedInputs); + return Files; +} + +static std::vector +ReadCorpora(const std::vector &CorpusDirs, + const std::vector &ExtraSeedFiles) { + std::vector SizedFiles; + size_t LastNumFiles = 0; + for (auto &Dir : CorpusDirs) { + GetSizedFilesFromDir(Dir, &SizedFiles); + Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles, + Dir.c_str()); + LastNumFiles = SizedFiles.size(); + } + for (auto &File : ExtraSeedFiles) + if (auto Size = FileSize(File)) + SizedFiles.push_back({File, Size}); + return SizedFiles; +} + +int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { + using namespace fuzzer; + assert(argc && argv && "Argument pointers cannot be nullptr"); + std::string Argv0((*argv)[0]); + EF = new ExternalFunctions(); + if (EF->LLVMFuzzerInitialize) + EF->LLVMFuzzerInitialize(argc, argv); + if (EF->__msan_scoped_disable_interceptor_checks) + EF->__msan_scoped_disable_interceptor_checks(); + const std::vector Args(*argv, *argv + *argc); + assert(!Args.empty()); + ProgName = new std::string(Args[0]); + if (Argv0 != *ProgName) { + Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n"); + exit(1); + } + ParseFlags(Args, EF); + if (Flags.help) { + PrintHelp(); + return 0; + } + + if (Flags.close_fd_mask & 2) + DupAndCloseStderr(); + if (Flags.close_fd_mask & 1) + CloseStdout(); + + if (Flags.jobs > 0 && Flags.workers == 0) { + Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs); + if (Flags.workers > 1) + Printf("Running %u workers\n", Flags.workers); + } + + if (Flags.workers > 0 && Flags.jobs > 0) + return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); + + FuzzingOptions Options; + Options.Verbosity = Flags.verbosity; + Options.MaxLen = Flags.max_len; + Options.LenControl = Flags.len_control; + Options.KeepSeed = Flags.keep_seed; + Options.UnitTimeoutSec = Flags.timeout; + Options.ErrorExitCode = Flags.error_exitcode; + Options.TimeoutExitCode = Flags.timeout_exitcode; + Options.IgnoreTimeouts = Flags.ignore_timeouts; + Options.IgnoreOOMs = Flags.ignore_ooms; + Options.IgnoreCrashes = Flags.ignore_crashes; + Options.MaxTotalTimeSec = Flags.max_total_time; + Options.DoCrossOver = Flags.cross_over; + Options.CrossOverUniformDist = Flags.cross_over_uniform_dist; + Options.MutateDepth = Flags.mutate_depth; + Options.ReduceDepth = Flags.reduce_depth; + Options.UseCounters = Flags.use_counters; + Options.UseMemmem = Flags.use_memmem; + Options.UseCmp = Flags.use_cmp; + Options.UseValueProfile = Flags.use_value_profile; + Options.Shrink = Flags.shrink; + Options.ReduceInputs = Flags.reduce_inputs; + Options.ShuffleAtStartUp = Flags.shuffle; + Options.PreferSmall = Flags.prefer_small; + Options.ReloadIntervalSec = Flags.reload; + Options.OnlyASCII = Flags.only_ascii; + Options.DetectLeaks = Flags.detect_leaks; + Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval; + Options.TraceMalloc = Flags.trace_malloc; + Options.RssLimitMb = Flags.rss_limit_mb; + Options.MallocLimitMb = Flags.malloc_limit_mb; + if (!Options.MallocLimitMb) + Options.MallocLimitMb = Options.RssLimitMb; + if (Flags.runs >= 0) + Options.MaxNumberOfRuns = Flags.runs; + if (!Inputs->empty() && !Flags.minimize_crash_internal_step) { + // Ensure output corpus assumed to be the first arbitrary argument input + // is not a path to an existing file. + std::string OutputCorpusDir = (*Inputs)[0]; + if (!IsFile(OutputCorpusDir)) { + Options.OutputCorpus = OutputCorpusDir; + ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs); + } + } + Options.ReportSlowUnits = Flags.report_slow_units; + if (Flags.artifact_prefix) { + Options.ArtifactPrefix = Flags.artifact_prefix; + + // Since the prefix could be a full path to a file name prefix, assume + // that if the path ends with the platform's separator that a directory + // is desired + std::string ArtifactPathDir = Options.ArtifactPrefix; + if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) { + ArtifactPathDir = DirName(ArtifactPathDir); + } + ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs); + } + if (Flags.exact_artifact_path) { + Options.ExactArtifactPath = Flags.exact_artifact_path; + ValidateDirectoryExists(DirName(Options.ExactArtifactPath), + Flags.create_missing_dirs); + } + std::vector Dictionary; + if (Flags.dict) + if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) + return 1; + if (Flags.verbosity > 0 && !Dictionary.empty()) + Printf("Dictionary: %zd entries\n", Dictionary.size()); + bool RunIndividualFiles = AllInputsAreFiles(); + Options.SaveArtifacts = + !RunIndividualFiles || Flags.minimize_crash_internal_step; + Options.PrintNewCovPcs = Flags.print_pcs; + Options.PrintNewCovFuncs = Flags.print_funcs; + Options.PrintFinalStats = Flags.print_final_stats; + Options.PrintCorpusStats = Flags.print_corpus_stats; + Options.PrintCoverage = Flags.print_coverage; + Options.PrintFullCoverage = Flags.print_full_coverage; + if (Flags.exit_on_src_pos) + Options.ExitOnSrcPos = Flags.exit_on_src_pos; + if (Flags.exit_on_item) + Options.ExitOnItem = Flags.exit_on_item; + if (Flags.focus_function) + Options.FocusFunction = Flags.focus_function; + if (Flags.data_flow_trace) + Options.DataFlowTrace = Flags.data_flow_trace; + if (Flags.features_dir) { + Options.FeaturesDir = Flags.features_dir; + ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs); + } + if (Flags.mutation_graph_file) + Options.MutationGraphFile = Flags.mutation_graph_file; + if (Flags.collect_data_flow) + Options.CollectDataFlow = Flags.collect_data_flow; + if (Flags.stop_file) + Options.StopFile = Flags.stop_file; + Options.Entropic = Flags.entropic; + Options.EntropicFeatureFrequencyThreshold = + (size_t)Flags.entropic_feature_frequency_threshold; + Options.EntropicNumberOfRarestFeatures = + (size_t)Flags.entropic_number_of_rarest_features; + Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time; + if (!Options.FocusFunction.empty()) + Options.Entropic = false; // FocusFunction overrides entropic scheduling. + if (Options.Entropic) + Printf("INFO: Running with entropic power schedule (0x%zX, %zu).\n", + Options.EntropicFeatureFrequencyThreshold, + Options.EntropicNumberOfRarestFeatures); + struct EntropicOptions Entropic; + Entropic.Enabled = Options.Entropic; + Entropic.FeatureFrequencyThreshold = + Options.EntropicFeatureFrequencyThreshold; + Entropic.NumberOfRarestFeatures = Options.EntropicNumberOfRarestFeatures; + Entropic.ScalePerExecTime = Options.EntropicScalePerExecTime; + + unsigned Seed = Flags.seed; + // Initialize Seed. + if (Seed == 0) + Seed = static_cast( + std::chrono::system_clock::now().time_since_epoch().count() + GetPid()); + if (Flags.verbosity) + Printf("INFO: Seed: %u\n", Seed); + + if (Flags.collect_data_flow && Flags.data_flow_trace && !Flags.fork && + !(Flags.merge || Flags.set_cover_merge)) { + if (RunIndividualFiles) + return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, + ReadCorpora({}, *Inputs)); + else + return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, + ReadCorpora(*Inputs, {})); + } + + Random Rand(Seed); + auto *MD = new MutationDispatcher(Rand, Options); + auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic); + auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); + + for (auto &U: Dictionary) + if (U.size() <= Word::GetMaxSize()) + MD->AddWordToManualDictionary(Word(U.data(), U.size())); + + // Threads are only supported by Chrome. Don't use them with emscripten + // for now. +#if !LIBFUZZER_EMSCRIPTEN + StartRssThread(F, Flags.rss_limit_mb); +#endif // LIBFUZZER_EMSCRIPTEN + + Options.HandleAbrt = Flags.handle_abrt; + Options.HandleAlrm = !Flags.minimize_crash; + Options.HandleBus = Flags.handle_bus; + Options.HandleFpe = Flags.handle_fpe; + Options.HandleIll = Flags.handle_ill; + Options.HandleInt = Flags.handle_int; + Options.HandleSegv = Flags.handle_segv; + Options.HandleTerm = Flags.handle_term; + Options.HandleXfsz = Flags.handle_xfsz; + Options.HandleUsr1 = Flags.handle_usr1; + Options.HandleUsr2 = Flags.handle_usr2; + Options.HandleWinExcept = Flags.handle_winexcept; + + SetSignalHandler(Options); + + std::atexit(Fuzzer::StaticExitCallback); + + if (Flags.minimize_crash) + return MinimizeCrashInput(Args, Options); + + if (Flags.minimize_crash_internal_step) + return MinimizeCrashInputInternalStep(F, Corpus); + + if (Flags.cleanse_crash) + return CleanseCrashInput(Args, Options); + + if (RunIndividualFiles) { + Options.SaveArtifacts = false; + int Runs = std::max(1, Flags.runs); + Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(), + Inputs->size(), Runs); + for (auto &Path : *Inputs) { + auto StartTime = system_clock::now(); + Printf("Running: %s\n", Path.c_str()); + for (int Iter = 0; Iter < Runs; Iter++) + RunOneTest(F, Path.c_str(), Options.MaxLen); + auto StopTime = system_clock::now(); + auto MS = duration_cast(StopTime - StartTime).count(); + Printf("Executed %s in %ld ms\n", Path.c_str(), (long)MS); + } + Printf("***\n" + "*** NOTE: fuzzing was not performed, you have only\n" + "*** executed the target code on a fixed set of inputs.\n" + "***\n"); + F->PrintFinalStats(); + exit(0); + } + + Options.ForkCorpusGroups = Flags.fork_corpus_groups; + if (Flags.fork) + FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork); + + if (Flags.merge || Flags.set_cover_merge) + Merge(F, Options, Args, *Inputs, Flags.merge_control_file); + + if (Flags.merge_inner) { + const size_t kDefaultMaxMergeLen = 1 << 20; + if (Options.MaxLen == 0) + F->SetMaxInputLen(kDefaultMaxMergeLen); + assert(Flags.merge_control_file); + F->CrashResistantMergeInternalStep(Flags.merge_control_file, + !strncmp(Flags.merge_inner, "2", 1)); + exit(0); + } + + if (Flags.analyze_dict) { + size_t MaxLen = INT_MAX; // Large max length. + UnitVector InitialCorpus; + for (auto &Inp : *Inputs) { + Printf("Loading corpus dir: %s\n", Inp.c_str()); + ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr, + MaxLen, /*ExitOnError=*/false); + } + + if (Dictionary.empty() || Inputs->empty()) { + Printf("ERROR: can't analyze dict without dict and corpus provided\n"); + return 1; + } + if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) { + Printf("Dictionary analysis failed\n"); + exit(1); + } + Printf("Dictionary analysis succeeded\n"); + exit(0); + } + + auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs)); + F->Loop(CorporaFiles); + + if (Flags.verbosity) + Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(), + F->secondsSinceProcessStartUp()); + F->PrintFinalStats(); + + exit(0); // Don't let F destroy itself. +} + +extern "C" ATTRIBUTE_INTERFACE int +LLVMFuzzerRunDriver(int *argc, char ***argv, + int (*UserCb)(const uint8_t *Data, size_t Size)) { + return FuzzerDriver(argc, argv, UserCb); +} + +// Storage for global ExternalFunctions object. +ExternalFunctions *EF = nullptr; + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.def clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.def --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.def 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.def 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This defines the external function pointers that +// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The +// EXT_FUNC macro must be defined at the point of inclusion. The signature of +// the macro is: +// +// EXT_FUNC(, , , ) +//===----------------------------------------------------------------------===// + +// Optional user functions +EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); +EXT_FUNC(LLVMFuzzerCustomMutator, size_t, + (uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed), + false); +EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, + (const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize, unsigned int Seed), + false); + +// Sanitizer functions +EXT_FUNC(__lsan_enable, void, (), false); +EXT_FUNC(__lsan_disable, void, (), false); +EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false); +EXT_FUNC(__sanitizer_acquire_crash_state, int, (), true); +EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int, + (void (*malloc_hook)(const volatile void *, size_t), + void (*free_hook)(const volatile void *)), + false); +EXT_FUNC(__sanitizer_log_write, void, (const char *buf, size_t len), false); +EXT_FUNC(__sanitizer_purge_allocator, void, (), false); +EXT_FUNC(__sanitizer_print_memory_profile, void, (size_t, size_t), false); +EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); +EXT_FUNC(__sanitizer_symbolize_pc, void, + (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); +EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, + (void *pc, char *module_path, + size_t module_path_len,void **pc_offset), false); +EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); +EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); +EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false); +EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false); +EXT_FUNC(__msan_unpoison, void, (const volatile void *, size_t size), false); +EXT_FUNC(__msan_unpoison_param, void, (size_t n), false); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctions.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Defines an interface to (possibly optional) functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H +#define LLVM_FUZZER_EXT_FUNCTIONS_H + +#include +#include + +namespace fuzzer { + +struct ExternalFunctions { + // Initialize function pointers. Functions that are not available will be set + // to nullptr. Do not call this constructor before ``main()`` has been + // entered. + ExternalFunctions(); + +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE(*NAME) FUNC_SIG = nullptr + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +}; +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsDlsym.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsDlsym.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsDlsym.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsDlsym.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Implementation for operating systems that support dlsym(). We only use it on +// Apple platforms for now. We don't use this approach on Linux because it +// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker. +// That is a complication we don't wish to expose to clients right now. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_APPLE + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include + +using namespace fuzzer; + +template +static T GetFnPtr(const char *FnName, bool WarnIfMissing) { + dlerror(); // Clear any previous errors. + void *Fn = dlsym(RTLD_DEFAULT, FnName); + if (Fn == nullptr) { + if (WarnIfMissing) { + const char *ErrorMsg = dlerror(); + Printf("WARNING: Failed to find function \"%s\".", FnName); + if (ErrorMsg) + Printf(" Reason %s.", ErrorMsg); + Printf("\n"); + } + } + return reinterpret_cast(Fn); +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr(#NAME, WARN) + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_APPLE diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWeak.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWeak.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWeak.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWeak.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Implementation for Linux. This relies on the linker's support for weak +// symbols. We don't use this approach on Apple platforms because it requires +// clients of LibFuzzer to pass ``-U _`` to the linker to allow +// weak symbols to be undefined. That is a complication we don't want to expose +// to clients right now. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \ + LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" + +extern "C" { +// Declare these symbols as weak to allow them to be optionally defined. +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +using namespace fuzzer; + +static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) { + if (FnPtr == nullptr && WarnIfMissing) { + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + } +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = ::NAME; \ + CheckFnPtr(reinterpret_cast(reinterpret_cast(::NAME)), \ + #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWindows.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWindows.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWindows.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtFunctionsWindows.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,83 @@ +//=== FuzzerExtWindows.cpp - Interface to external functions --------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when +// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately +// the method each compiler supports is not supported by the other. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_WINDOWS + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include + +using namespace fuzzer; + +// Intermediate macro to ensure the parameter is expanded before stringified. +#define STRINGIFY_(A) #A +#define STRINGIFY(A) STRINGIFY_(A) + +#if LIBFUZZER_MSVC +#define GET_FUNCTION_ADDRESS(fn) &fn +#else +#define GET_FUNCTION_ADDRESS(fn) __builtin_function_start(fn) +#endif // LIBFUZER_MSVC + +// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h +#if defined(_M_IX86) || defined(__i386__) +#define WIN_SYM_PREFIX "_" +#else +#define WIN_SYM_PREFIX +#endif + +// Declare external functions as having alternativenames, so that we can +// determine if they are not defined. +#define EXTERNAL_FUNC(Name, Default) \ + __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ + Name) "=" WIN_SYM_PREFIX STRINGIFY(Default))) + +extern "C" { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE NAME##Def FUNC_SIG { \ + Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ + exit(1); \ + } \ + EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +template +static T *GetFnPtr(void *Fun, void *FunDef, const char *FnName, + bool WarnIfMissing) { + if (Fun == FunDef) { + if (WarnIfMissing) + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + return nullptr; + } + return (T *)Fun; +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr(GET_FUNCTION_ADDRESS(::NAME), \ + GET_FUNCTION_ADDRESS(::NAME##Def), \ + #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCounters.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCounters.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCounters.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCounters.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Extra coverage counters defined by user code. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" +#include + +#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ + LIBFUZZER_FUCHSIA || LIBFUZZER_EMSCRIPTEN +__attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters; +__attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters; + +namespace fuzzer { +uint8_t *ExtraCountersBegin() { return &__start___libfuzzer_extra_counters; } +uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } +ATTRIBUTE_NO_SANITIZE_ALL +void ClearExtraCounters() { // hand-written memset, don't asan-ify. + uintptr_t *Beg = reinterpret_cast(ExtraCountersBegin()); + uintptr_t *End = reinterpret_cast(ExtraCountersEnd()); + for (; Beg < End; Beg++) { + *Beg = 0; + __asm__ __volatile__("" : : : "memory"); + } +} + +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersDarwin.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersDarwin.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersDarwin.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersDarwin.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +//===- FuzzerExtraCountersDarwin.cpp - Extra coverage counters for Darwin -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Extra coverage counters defined by user code for Darwin. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" +#include + +#if LIBFUZZER_APPLE + +namespace fuzzer { +uint8_t *ExtraCountersBegin() { return nullptr; } +uint8_t *ExtraCountersEnd() { return nullptr; } +void ClearExtraCounters() {} +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersWindows.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersWindows.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersWindows.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerExtraCountersWindows.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +//===- FuzzerExtraCountersWindows.cpp - Extra coverage counters for Win32 -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Extra coverage counters defined by user code for Windows. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" +#include + +#if LIBFUZZER_WINDOWS +#include + +namespace fuzzer { + +// +// The __start___libfuzzer_extra_counters variable is align 16, size 16 to +// ensure the padding between it and the next variable in this section (either +// __libfuzzer_extra_counters or __stop___libfuzzer_extra_counters) will be +// located at (__start___libfuzzer_extra_counters + +// sizeof(__start___libfuzzer_extra_counters)). Otherwise, the calculation of +// (stop - (start + sizeof(start))) might be skewed. +// +// The section name, __libfuzzer_extra_countaaa ends with "aaa", so it sorts +// before __libfuzzer_extra_counters alphabetically. We want the start symbol to +// be placed in the section just before the user supplied counters (if present). +// +#pragma section(".data$__libfuzzer_extra_countaaa") +ATTRIBUTE_ALIGNED(16) +__declspec(allocate(".data$__libfuzzer_extra_countaaa")) uint8_t + __start___libfuzzer_extra_counters[16] = {0}; + +// +// Example of what the user-supplied counters should look like. First, the +// pragma to create the section name. It will fall alphabetically between +// ".data$__libfuzzer_extra_countaaa" and ".data$__libfuzzer_extra_countzzz". +// Next, the declspec to allocate the variable inside the specified section. +// Finally, some array, struct, whatever that is used to track the counter data. +// The size of this variable is computed at runtime by finding the difference of +// __stop___libfuzzer_extra_counters and __start___libfuzzer_extra_counters + +// sizeof(__start___libfuzzer_extra_counters). +// + +// +// #pragma section(".data$__libfuzzer_extra_counters") +// __declspec(allocate(".data$__libfuzzer_extra_counters")) +// uint8_t any_name_variable[64 * 1024]; +// + +// +// Here, the section name, __libfuzzer_extra_countzzz ends with "zzz", so it +// sorts after __libfuzzer_extra_counters alphabetically. We want the stop +// symbol to be placed in the section just after the user supplied counters (if +// present). Align to 1 so there isn't any padding placed between this and the +// previous variable. +// +#pragma section(".data$__libfuzzer_extra_countzzz") +ATTRIBUTE_ALIGNED(1) +__declspec(allocate(".data$__libfuzzer_extra_countzzz")) uint8_t + __stop___libfuzzer_extra_counters = 0; + +uint8_t *ExtraCountersBegin() { + return __start___libfuzzer_extra_counters + + sizeof(__start___libfuzzer_extra_counters); +} + +uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } + +ATTRIBUTE_NO_SANITIZE_ALL +void ClearExtraCounters() { + uint8_t *Beg = ExtraCountersBegin(); + SecureZeroMemory(Beg, ExtraCountersEnd() - Beg); +} + +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFlags.def clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFlags.def --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFlags.def 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFlags.def 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Flags. FUZZER_FLAG_INT/FUZZER_FLAG_STRING macros should be defined at the +// point of inclusion. We are not using any flag parsing library for better +// portability and independence. +//===----------------------------------------------------------------------===// +FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.") +FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.") +FUZZER_FLAG_INT(runs, -1, + "Number of individual test runs (-1 for infinite runs).") +FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. " + "Contents of corpus files are going to be truncated to this value. " + "If 0, libFuzzer tries to guess a good value based on the corpus " + "and reports it.") +FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, " + "then try larger inputs over time. Specifies the rate at which the length " + "limit is increased (smaller == faster). If 0, immediately try inputs with " + "size up to max_len. Default value is 0, if LLVMFuzzerCustomMutator is used.") +FUZZER_FLAG_STRING(seed_inputs, "A comma-separated list of input files " + "to use as an additional seed corpus. Alternatively, an \"@\" followed by " + "the name of a file containing the comma-separated list.") +FUZZER_FLAG_INT(keep_seed, 0, "If 1, keep seed inputs in the corpus even if " + "they do not produce new coverage. When used with |reduce_inputs==1|, the " + "seed inputs will never be reduced. This option can be useful when seeds are" + "not properly formed for the fuzz target but still have useful snippets.") +FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.") +FUZZER_FLAG_INT(cross_over_uniform_dist, 0, "Experimental. If 1, use a " + "uniform probability distribution when choosing inputs to cross over with. " + "Some of the inputs in the corpus may never get chosen for mutation " + "depending on the input mutation scheduling policy. With this flag, all " + "inputs, regardless of the input mutation scheduling policy, can be chosen " + "as an input to cross over with. This can be particularly useful with " + "|keep_seed==1|; all the initial seed inputs, even though they do not " + "increase coverage because they are not properly formed, will still be " + "chosen as an input to cross over with.") + +FUZZER_FLAG_INT(mutate_depth, 5, + "Apply this number of consecutive mutations to each input.") +FUZZER_FLAG_INT(reduce_depth, 0, "Experimental/internal. " + "Reduce depth if mutations lose unique features") +FUZZER_FLAG_INT(shuffle, 1, "Shuffle inputs at startup") +FUZZER_FLAG_INT(prefer_small, 1, + "If 1, always prefer smaller inputs during the corpus shuffle.") +FUZZER_FLAG_INT( + timeout, 1200, + "Timeout in seconds (if positive). " + "If one unit runs more than this number of seconds the process will abort.") +FUZZER_FLAG_INT(error_exitcode, 77, "When libFuzzer itself reports a bug " + "this exit code will be used.") +FUZZER_FLAG_INT(timeout_exitcode, 70, "When libFuzzer reports a timeout " + "this exit code will be used.") +FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total " + "time in seconds to run the fuzzer.") +FUZZER_FLAG_INT(help, 0, "Print help.") +FUZZER_FLAG_INT(fork, 0, "Experimental mode where fuzzing happens " + "in a subprocess") +FUZZER_FLAG_INT(fork_corpus_groups, 0, "For fork mode, enable the corpus-group " + "strategy, The main corpus will be grouped according to size, " + "and each sub-process will randomly select seeds from different " + "groups as the sub-corpus.") +FUZZER_FLAG_INT(ignore_timeouts, 1, "Ignore timeouts in fork mode") +FUZZER_FLAG_INT(ignore_ooms, 1, "Ignore OOMs in fork mode") +FUZZER_FLAG_INT(ignore_crashes, 0, "Ignore crashes in fork mode") +FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " + "merged into the 1-st corpus. Only interesting units will be taken. " + "This flag can be used to minimize a corpus.") +FUZZER_FLAG_INT(set_cover_merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " + "merged into the 1-st corpus. Same as the 'merge' flag, but uses the " + "standard greedy algorithm for the set cover problem to " + "compute an approximation of the minimum set of testcases that " + "provide the same coverage as the initial corpora") +FUZZER_FLAG_STRING(stop_file, "Stop fuzzing ASAP if this file exists") +FUZZER_FLAG_STRING(merge_inner, "internal flag") +FUZZER_FLAG_STRING(merge_control_file, + "Specify a control file used for the merge process. " + "If a merge process gets killed it tries to leave this file " + "in a state suitable for resuming the merge. " + "By default a temporary file will be used." + "The same file can be used for multistep merge process.") +FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided" + " crash input. Use with -runs=N or -max_total_time=N to limit " + "the number attempts." + " Use with -exact_artifact_path to specify the output." + " Combine with ASAN_OPTIONS=dedup_token_length=3 (or similar) to ensure that" + " the minimized input triggers the same crash." + ) +FUZZER_FLAG_INT(cleanse_crash, 0, "If 1, tries to cleanse the provided" + " crash input to make it contain fewer original bytes." + " Use with -exact_artifact_path to specify the output." + ) +FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag") +FUZZER_FLAG_STRING(features_dir, "internal flag. Used to dump feature sets on disk." + "Every time a new input is added to the corpus, a corresponding file in the features_dir" + " is created containing the unique features of that input." + " Features are stored in binary format.") +FUZZER_FLAG_STRING(mutation_graph_file, "Saves a graph (in DOT format) to" + " mutation_graph_file. The graph contains a vertex for each input that has" + " unique coverage; directed edges are provided between parents and children" + " where the child has unique coverage, and are recorded with the type of" + " mutation that caused the child.") +FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters") +FUZZER_FLAG_INT(use_memmem, 1, + "Use hints from intercepting memmem, strstr, etc") +FUZZER_FLAG_INT(use_value_profile, 0, + "Experimental. Use value profile to guide fuzzing.") +FUZZER_FLAG_INT(use_cmp, 1, "Use CMP traces to guide mutations") +FUZZER_FLAG_INT(shrink, 0, "Experimental. Try to shrink corpus inputs.") +FUZZER_FLAG_INT(reduce_inputs, 1, + "Try to reduce the size of inputs while preserving their full feature sets") +FUZZER_FLAG_UNSIGNED(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn" + " this number of jobs in separate worker processes" + " with stdout/stderr redirected to fuzz-JOB.log.") +FUZZER_FLAG_UNSIGNED(workers, 0, + "Number of simultaneous worker processes to run the jobs." + " If zero, \"min(jobs,NumberOfCpuCores()/2)\" is used.") +FUZZER_FLAG_INT(reload, 1, + "Reload the main corpus every seconds to get new units" + " discovered by other processes. If 0, disabled") +FUZZER_FLAG_INT(report_slow_units, 10, + "Report slowest units if they run for more than this number of seconds.") +FUZZER_FLAG_INT(only_ascii, 0, + "If 1, generate only ASCII (isprint+isspace) inputs.") +FUZZER_FLAG_STRING(dict, "Experimental. Use the dictionary file.") +FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, " + "timeout, or slow inputs) as " + "$(artifact_prefix)file") +FUZZER_FLAG_STRING(exact_artifact_path, + "Write the single artifact on failure (crash, timeout) " + "as $(exact_artifact_path). This overrides -artifact_prefix " + "and will not use checksum in the file name. Do not " + "use the same path for several parallel processes.") +FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.") +FUZZER_FLAG_INT(print_funcs, 2, "If >=1, print out at most this number of " + "newly covered functions.") +FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.") +FUZZER_FLAG_INT(print_corpus_stats, 0, + "If 1, print statistics on corpus elements at exit.") +FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text" + " at exit.") +FUZZER_FLAG_INT(print_full_coverage, 0, "If 1, print full coverage information " + "(all branches) as text at exit.") +FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated.") +FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") +FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.") +FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.") +FUZZER_FLAG_INT(handle_ill, 1, "If 1, try to intercept SIGILL.") +FUZZER_FLAG_INT(handle_fpe, 1, "If 1, try to intercept SIGFPE.") +FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.") +FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.") +FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.") +FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.") +FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.") +FUZZER_FLAG_INT(handle_winexcept, 1, "If 1, try to intercept uncaught Windows " + "Visual C++ Exceptions.") +FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; " + "if 2, close stderr; if 3, close both. " + "Be careful, this will also close e.g. stderr of asan.") +FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled " + "try to detect memory leaks during fuzzing (i.e. not only at shut down).") +FUZZER_FLAG_INT(purge_allocator_interval, 1, "Purge allocator caches and " + "quarantines every seconds. When rss_limit_mb is specified (>0), " + "purging starts when RSS exceeds 50% of rss_limit_mb. Pass " + "purge_allocator_interval=-1 to disable this functionality.") +FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. " + "If >= 2 will also print stack traces.") +FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon " + "reaching this limit of RSS memory usage.") +FUZZER_FLAG_INT(malloc_limit_mb, 0, "If non-zero, the fuzzer will exit " + "if the target tries to allocate this number of Mb with one malloc call. " + "If zero (default) same limit as rss_limit_mb is applied.") +FUZZER_FLAG_STRING(exit_on_src_pos, "Exit if a newly found PC originates" + " from the given source location. Example: -exit_on_src_pos=foo.cc:123. " + "Used primarily for testing libFuzzer itself.") +FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum" + " was added to the corpus. " + "Used primarily for testing libFuzzer itself.") +FUZZER_FLAG_INT(ignore_remaining_args, 0, "If 1, ignore all arguments passed " + "after this one. Useful for fuzzers that need to do their own " + "argument parsing.") +FUZZER_FLAG_STRING(focus_function, "Experimental. " + "Fuzzing will focus on inputs that trigger calls to this function. " + "If -focus_function=auto and -data_flow_trace is used, libFuzzer " + "will choose the focus functions automatically. Disables -entropic when " + "specified.") +FUZZER_FLAG_INT(entropic, 1, "Enables entropic power schedule.") +FUZZER_FLAG_INT(entropic_feature_frequency_threshold, 0xFF, "Experimental. If " + "entropic is enabled, all features which are observed less often than " + "the specified value are considered as rare.") +FUZZER_FLAG_INT(entropic_number_of_rarest_features, 100, "Experimental. If " + "entropic is enabled, we keep track of the frequencies only for the " + "Top-X least abundant features (union features that are considered as " + "rare).") +FUZZER_FLAG_INT(entropic_scale_per_exec_time, 0, "Experimental. If 1, " + "the Entropic power schedule gets scaled based on the input execution " + "time. Inputs with lower execution time get scheduled more (up to 30x). " + "Note that, if 1, fuzzer stops from being deterministic even if a " + "non-zero random seed is given.") + +FUZZER_FLAG_INT(analyze_dict, 0, "Experimental") +FUZZER_DEPRECATED_FLAG(use_clang_coverage) +FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace") +FUZZER_FLAG_STRING(collect_data_flow, + "Experimental: collect the data flow trace") + +FUZZER_FLAG_INT(create_missing_dirs, 0, "Automatically attempt to create " + "directories for arguments that would normally expect them to already " + "exist (i.e. artifact_prefix, exact_artifact_path, features_dir, corpus)") diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,494 @@ +//===- FuzzerFork.cpp - run fuzzing in separate subprocesses --------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Spawn and orchestrate separate fuzzing processes. +//===----------------------------------------------------------------------===// + +#include "FuzzerCommand.h" +#include "FuzzerFork.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include "FuzzerMerge.h" +#include "FuzzerSHA1.h" +#include "FuzzerTracePC.h" +#include "FuzzerUtil.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +struct Stats { + size_t number_of_executed_units = 0; + size_t peak_rss_mb = 0; + size_t average_exec_per_sec = 0; +}; + +static Stats ParseFinalStatsFromLog(const std::string &LogPath) { + std::ifstream In(LogPath); + std::string Line; + Stats Res; + struct { + const char *Name; + size_t *Var; + } NameVarPairs[] = { + {"stat::number_of_executed_units:", &Res.number_of_executed_units}, + {"stat::peak_rss_mb:", &Res.peak_rss_mb}, + {"stat::average_exec_per_sec:", &Res.average_exec_per_sec}, + {nullptr, nullptr}, + }; + while (std::getline(In, Line, '\n')) { + if (Line.find("stat::") != 0) continue; + std::istringstream ISS(Line); + std::string Name; + size_t Val; + ISS >> Name >> Val; + for (size_t i = 0; NameVarPairs[i].Name; i++) + if (Name == NameVarPairs[i].Name) + *NameVarPairs[i].Var = Val; + } + return Res; +} + +struct FuzzJob { + // Inputs. + Command Cmd; + std::string CorpusDir; + std::string FeaturesDir; + std::string LogPath; + std::string SeedListPath; + std::string CFPath; + size_t JobId; + + int DftTimeInSeconds = 0; + + // Fuzzing Outputs. + int ExitCode; + + ~FuzzJob() { + RemoveFile(CFPath); + RemoveFile(LogPath); + RemoveFile(SeedListPath); + RmDirRecursive(CorpusDir); + RmDirRecursive(FeaturesDir); + } +}; + +struct GlobalEnv { + std::vector Args; + std::vector CorpusDirs; + std::string MainCorpusDir; + std::string TempDir; + std::string DFTDir; + std::string DataFlowBinary; + std::set Features, Cov; + std::set FilesWithDFT; + std::vector Files; + std::vector FilesSizes; + Random *Rand; + std::chrono::system_clock::time_point ProcessStartTime; + int Verbosity = 0; + int Group = 0; + int NumCorpuses = 8; + + size_t NumTimeouts = 0; + size_t NumOOMs = 0; + size_t NumCrashes = 0; + + + size_t NumRuns = 0; + + std::string StopFile() { return DirPlusFile(TempDir, "STOP"); } + + size_t secondsSinceProcessStartUp() const { + return std::chrono::duration_cast( + std::chrono::system_clock::now() - ProcessStartTime) + .count(); + } + + FuzzJob *CreateNewJob(size_t JobId) { + Command Cmd(Args); + Cmd.removeFlag("fork"); + Cmd.removeFlag("runs"); + Cmd.removeFlag("collect_data_flow"); + for (auto &C : CorpusDirs) // Remove all corpora from the args. + Cmd.removeArgument(C); + Cmd.addFlag("reload", "0"); // working in an isolated dir, no reload. + Cmd.addFlag("print_final_stats", "1"); + Cmd.addFlag("print_funcs", "0"); // no need to spend time symbolizing. + Cmd.addFlag("max_total_time", std::to_string(std::min((size_t)300, JobId))); + Cmd.addFlag("stop_file", StopFile()); + if (!DataFlowBinary.empty()) { + Cmd.addFlag("data_flow_trace", DFTDir); + if (!Cmd.hasFlag("focus_function")) + Cmd.addFlag("focus_function", "auto"); + } + auto Job = new FuzzJob; + std::string Seeds; + if (size_t CorpusSubsetSize = + std::min(Files.size(), (size_t)sqrt(Files.size() + 2))) { + auto Time1 = std::chrono::system_clock::now(); + if (Group) { // whether to group the corpus. + size_t AverageCorpusSize = Files.size() / NumCorpuses + 1; + size_t StartIndex = ((JobId - 1) % NumCorpuses) * AverageCorpusSize; + for (size_t i = 0; i < CorpusSubsetSize; i++) { + size_t RandNum = (*Rand)(AverageCorpusSize); + size_t Index = RandNum + StartIndex; + Index = Index < Files.size() ? Index + : Rand->SkewTowardsLast(Files.size()); + auto &SF = Files[Index]; + Seeds += (Seeds.empty() ? "" : ",") + SF; + CollectDFT(SF); + } + } else { + for (size_t i = 0; i < CorpusSubsetSize; i++) { + auto &SF = Files[Rand->SkewTowardsLast(Files.size())]; + Seeds += (Seeds.empty() ? "" : ",") + SF; + CollectDFT(SF); + } + } + auto Time2 = std::chrono::system_clock::now(); + auto DftTimeInSeconds = duration_cast(Time2 - Time1).count(); + assert(DftTimeInSeconds < std::numeric_limits::max()); + Job->DftTimeInSeconds = static_cast(DftTimeInSeconds); + } + if (!Seeds.empty()) { + Job->SeedListPath = + DirPlusFile(TempDir, std::to_string(JobId) + ".seeds"); + WriteToFile(Seeds, Job->SeedListPath); + Cmd.addFlag("seed_inputs", "@" + Job->SeedListPath); + } + Job->LogPath = DirPlusFile(TempDir, std::to_string(JobId) + ".log"); + Job->CorpusDir = DirPlusFile(TempDir, "C" + std::to_string(JobId)); + Job->FeaturesDir = DirPlusFile(TempDir, "F" + std::to_string(JobId)); + Job->CFPath = DirPlusFile(TempDir, std::to_string(JobId) + ".merge"); + Job->JobId = JobId; + + + Cmd.addArgument(Job->CorpusDir); + Cmd.addFlag("features_dir", Job->FeaturesDir); + + for (auto &D : {Job->CorpusDir, Job->FeaturesDir}) { + RmDirRecursive(D); + MkDir(D); + } + + Cmd.setOutputFile(Job->LogPath); + Cmd.combineOutAndErr(); + + Job->Cmd = Cmd; + + if (Verbosity >= 2) + Printf("Job %zd/%p Created: %s\n", JobId, Job, + Job->Cmd.toString().c_str()); + // Start from very short runs and gradually increase them. + return Job; + } + + void RunOneMergeJob(FuzzJob *Job) { + auto Stats = ParseFinalStatsFromLog(Job->LogPath); + NumRuns += Stats.number_of_executed_units; + + std::vector TempFiles, MergeCandidates; + // Read all newly created inputs and their feature sets. + // Choose only those inputs that have new features. + GetSizedFilesFromDir(Job->CorpusDir, &TempFiles); + std::sort(TempFiles.begin(), TempFiles.end()); + for (auto &F : TempFiles) { + auto FeatureFile = F.File; + FeatureFile.replace(0, Job->CorpusDir.size(), Job->FeaturesDir); + auto FeatureBytes = FileToVector(FeatureFile, 0, false); + assert((FeatureBytes.size() % sizeof(uint32_t)) == 0); + std::vector NewFeatures(FeatureBytes.size() / sizeof(uint32_t)); + memcpy(NewFeatures.data(), FeatureBytes.data(), FeatureBytes.size()); + for (auto Ft : NewFeatures) { + if (!Features.count(Ft)) { + MergeCandidates.push_back(F); + break; + } + } + } + // if (!FilesToAdd.empty() || Job->ExitCode != 0) + Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s: %zd " + "oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n", + NumRuns, Cov.size(), Features.size(), Files.size(), + Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, + secondsSinceProcessStartUp(), Job->JobId, Job->DftTimeInSeconds); + + if (MergeCandidates.empty()) return; + + std::vector FilesToAdd; + std::set NewFeatures, NewCov; + bool IsSetCoverMerge = + !Job->Cmd.getFlagValue("set_cover_merge").compare("1"); + CrashResistantMerge(Args, {}, MergeCandidates, &FilesToAdd, Features, + &NewFeatures, Cov, &NewCov, Job->CFPath, false, + IsSetCoverMerge); + for (auto &Path : FilesToAdd) { + auto U = FileToVector(Path); + auto NewPath = DirPlusFile(MainCorpusDir, Hash(U)); + WriteToFile(U, NewPath); + if (Group) { // Insert the queue according to the size of the seed. + size_t UnitSize = U.size(); + auto Idx = + std::upper_bound(FilesSizes.begin(), FilesSizes.end(), UnitSize) - + FilesSizes.begin(); + FilesSizes.insert(FilesSizes.begin() + Idx, UnitSize); + Files.insert(Files.begin() + Idx, NewPath); + } else { + Files.push_back(NewPath); + } + } + Features.insert(NewFeatures.begin(), NewFeatures.end()); + Cov.insert(NewCov.begin(), NewCov.end()); + for (auto Idx : NewCov) + if (auto *TE = TPC.PCTableEntryByIdx(Idx)) + if (TPC.PcIsFuncEntry(TE)) + PrintPC(" NEW_FUNC: %p %F %L\n", "", + TPC.GetNextInstructionPc(TE->PC)); + } + + void CollectDFT(const std::string &InputPath) { + if (DataFlowBinary.empty()) return; + if (!FilesWithDFT.insert(InputPath).second) return; + Command Cmd(Args); + Cmd.removeFlag("fork"); + Cmd.removeFlag("runs"); + Cmd.addFlag("data_flow_trace", DFTDir); + Cmd.addArgument(InputPath); + for (auto &C : CorpusDirs) // Remove all corpora from the args. + Cmd.removeArgument(C); + Cmd.setOutputFile(DirPlusFile(TempDir, "dft.log")); + Cmd.combineOutAndErr(); + // Printf("CollectDFT: %s\n", Cmd.toString().c_str()); + ExecuteCommand(Cmd); + } + +}; + +struct JobQueue { + std::queue Qu; + std::mutex Mu; + std::condition_variable Cv; + + void Push(FuzzJob *Job) { + { + std::lock_guard Lock(Mu); + Qu.push(Job); + } + Cv.notify_one(); + } + FuzzJob *Pop() { + std::unique_lock Lk(Mu); + // std::lock_guard Lock(Mu); + Cv.wait(Lk, [&]{return !Qu.empty();}); + assert(!Qu.empty()); + auto Job = Qu.front(); + Qu.pop(); + return Job; + } +}; + +void WorkerThread(JobQueue *FuzzQ, JobQueue *MergeQ) { + while (auto Job = FuzzQ->Pop()) { + // Printf("WorkerThread: job %p\n", Job); + Job->ExitCode = ExecuteCommand(Job->Cmd); + MergeQ->Push(Job); + } +} + +// This is just a skeleton of an experimental -fork=1 feature. +void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, + const std::vector &Args, + const std::vector &CorpusDirs, int NumJobs) { + Printf("INFO: -fork=%d: fuzzing in separate process(s)\n", NumJobs); + + GlobalEnv Env; + Env.Args = Args; + Env.CorpusDirs = CorpusDirs; + Env.Rand = &Rand; + Env.Verbosity = Options.Verbosity; + Env.ProcessStartTime = std::chrono::system_clock::now(); + Env.DataFlowBinary = Options.CollectDataFlow; + Env.Group = Options.ForkCorpusGroups; + + std::vector SeedFiles; + for (auto &Dir : CorpusDirs) + GetSizedFilesFromDir(Dir, &SeedFiles); + std::sort(SeedFiles.begin(), SeedFiles.end()); + Env.TempDir = TempPath("FuzzWithFork", ".dir"); + Env.DFTDir = DirPlusFile(Env.TempDir, "DFT"); + RmDirRecursive(Env.TempDir); // in case there is a leftover from old runs. + MkDir(Env.TempDir); + MkDir(Env.DFTDir); + + + if (CorpusDirs.empty()) + MkDir(Env.MainCorpusDir = DirPlusFile(Env.TempDir, "C")); + else + Env.MainCorpusDir = CorpusDirs[0]; + + if (Options.KeepSeed) { + for (auto &File : SeedFiles) + Env.Files.push_back(File.File); + } else { + auto CFPath = DirPlusFile(Env.TempDir, "merge.txt"); + std::set NewFeatures, NewCov; + CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, Env.Features, + &NewFeatures, Env.Cov, &NewCov, CFPath, + /*Verbose=*/false, /*IsSetCoverMerge=*/false); + Env.Features.insert(NewFeatures.begin(), NewFeatures.end()); + Env.Cov.insert(NewCov.begin(), NewCov.end()); + RemoveFile(CFPath); + } + + if (Env.Group) { + for (auto &path : Env.Files) + Env.FilesSizes.push_back(FileSize(path)); + } + + Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs, + Env.Files.size(), Env.TempDir.c_str()); + + int ExitCode = 0; + + JobQueue FuzzQ, MergeQ; + + auto StopJobs = [&]() { + for (int i = 0; i < NumJobs; i++) + FuzzQ.Push(nullptr); + MergeQ.Push(nullptr); + WriteToFile(Unit({1}), Env.StopFile()); + }; + + size_t MergeCycle = 20; + size_t JobExecuted = 0; + size_t JobId = 1; + std::vector Threads; + for (int t = 0; t < NumJobs; t++) { + Threads.push_back(std::thread(WorkerThread, &FuzzQ, &MergeQ)); + FuzzQ.Push(Env.CreateNewJob(JobId++)); + } + + while (true) { + std::unique_ptr Job(MergeQ.Pop()); + if (!Job) + break; + ExitCode = Job->ExitCode; + if (ExitCode == Options.InterruptExitCode) { + Printf("==%lu== libFuzzer: a child was interrupted; exiting\n", GetPid()); + StopJobs(); + break; + } + Fuzzer::MaybeExitGracefully(); + + Env.RunOneMergeJob(Job.get()); + + // merge the corpus . + JobExecuted++; + if (Env.Group && JobExecuted >= MergeCycle) { + std::vector CurrentSeedFiles; + for (auto &Dir : CorpusDirs) + GetSizedFilesFromDir(Dir, &CurrentSeedFiles); + std::sort(CurrentSeedFiles.begin(), CurrentSeedFiles.end()); + + auto CFPath = DirPlusFile(Env.TempDir, "merge.txt"); + std::set TmpNewFeatures, TmpNewCov; + std::set TmpFeatures, TmpCov; + Env.Files.clear(); + Env.FilesSizes.clear(); + CrashResistantMerge(Env.Args, {}, CurrentSeedFiles, &Env.Files, + TmpFeatures, &TmpNewFeatures, TmpCov, &TmpNewCov, + CFPath, /*Verbose=*/false, /*IsSetCoverMerge=*/false); + for (auto &path : Env.Files) + Env.FilesSizes.push_back(FileSize(path)); + RemoveFile(CFPath); + JobExecuted = 0; + MergeCycle += 5; + } + + // Since the number of corpus seeds will gradually increase, in order to + // control the number in each group to be about three times the number of + // seeds selected each time, the number of groups is dynamically adjusted. + if (Env.Files.size() < 2000) + Env.NumCorpuses = 12; + else if (Env.Files.size() < 6000) + Env.NumCorpuses = 20; + else if (Env.Files.size() < 12000) + Env.NumCorpuses = 32; + else if (Env.Files.size() < 16000) + Env.NumCorpuses = 40; + else if (Env.Files.size() < 24000) + Env.NumCorpuses = 60; + else + Env.NumCorpuses = 80; + + // Continue if our crash is one of the ignored ones. + if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode) + Env.NumTimeouts++; + else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode) + Env.NumOOMs++; + else if (ExitCode != 0) { + Env.NumCrashes++; + if (Options.IgnoreCrashes) { + std::ifstream In(Job->LogPath); + std::string Line; + while (std::getline(In, Line, '\n')) + if (Line.find("ERROR:") != Line.npos || + Line.find("runtime error:") != Line.npos) + Printf("%s\n", Line.c_str()); + } else { + // And exit if we don't ignore this crash. + Printf("INFO: log from the inner process:\n%s", + FileToString(Job->LogPath).c_str()); + StopJobs(); + break; + } + } + + // Stop if we are over the time budget. + // This is not precise, since other threads are still running + // and we will wait while joining them. + // We also don't stop instantly: other jobs need to finish. + if (Options.MaxTotalTimeSec > 0 && + Env.secondsSinceProcessStartUp() >= (size_t)Options.MaxTotalTimeSec) { + Printf("INFO: fuzzed for %zd seconds, wrapping up soon\n", + Env.secondsSinceProcessStartUp()); + StopJobs(); + break; + } + if (Env.NumRuns >= Options.MaxNumberOfRuns) { + Printf("INFO: fuzzed for %zd iterations, wrapping up soon\n", + Env.NumRuns); + StopJobs(); + break; + } + + FuzzQ.Push(Env.CreateNewJob(JobId++)); + } + + for (auto &T : Threads) + T.join(); + + // The workers have terminated. Don't try to remove the directory before they + // terminate to avoid a race condition preventing cleanup on Windows. + RmDirRecursive(Env.TempDir); + + // Use the exit code from the last child process. + Printf("INFO: exiting: %d time: %zds\n", ExitCode, + Env.secondsSinceProcessStartUp()); + exit(ExitCode); +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerFork.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +//===- FuzzerFork.h - run fuzzing in sub-processes --------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_FORK_H +#define LLVM_FUZZER_FORK_H + +#include "FuzzerDefs.h" +#include "FuzzerOptions.h" +#include "FuzzerRandom.h" + +#include + +namespace fuzzer { +void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, + const std::vector &Args, + const std::vector &CorpusDirs, int NumJobs); +} // namespace fuzzer + +#endif // LLVM_FUZZER_FORK_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,220 @@ +//===- FuzzerIO.cpp - IO utils. -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// IO functions. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include "FuzzerUtil.h" +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static FILE *OutputFile = stderr; + +FILE *GetOutputFile() { + return OutputFile; +} + +void SetOutputFile(FILE *NewOutputFile) { + OutputFile = NewOutputFile; +} + +long GetEpoch(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return 0; // Can't stat, be conservative. + return St.st_mtime; +} + +Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { + std::ifstream T(Path, std::ios::binary); + if (ExitOnError && !T) { + Printf("No such directory: %s; exiting\n", Path.c_str()); + exit(1); + } + + T.seekg(0, T.end); + auto EndPos = T.tellg(); + if (EndPos < 0) return {}; + size_t FileLen = EndPos; + if (MaxSize) + FileLen = std::min(FileLen, MaxSize); + + T.seekg(0, T.beg); + Unit Res(FileLen); + T.read(reinterpret_cast(Res.data()), FileLen); + return Res; +} + +std::string FileToString(const std::string &Path) { + std::ifstream T(Path, std::ios::binary); + return std::string((std::istreambuf_iterator(T)), + std::istreambuf_iterator()); +} + +void CopyFileToErr(const std::string &Path) { + Puts(FileToString(Path).c_str()); +} + +void WriteToFile(const Unit &U, const std::string &Path) { + WriteToFile(U.data(), U.size(), Path); +} + +void WriteToFile(const std::string &Data, const std::string &Path) { + WriteToFile(reinterpret_cast(Data.c_str()), Data.size(), + Path); +} + +void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) { + // Use raw C interface because this function may be called from a sig handler. + FILE *Out = fopen(Path.c_str(), "wb"); + if (!Out) return; + fwrite(Data, sizeof(Data[0]), Size, Out); + fclose(Out); +} + +void AppendToFile(const std::string &Data, const std::string &Path) { + AppendToFile(reinterpret_cast(Data.data()), Data.size(), + Path); +} + +void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) { + FILE *Out = fopen(Path.c_str(), "a"); + if (!Out) + return; + fwrite(Data, sizeof(Data[0]), Size, Out); + fclose(Out); +} + +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, + size_t MaxSize, bool ExitOnError, + std::vector *VPaths) { + long E = Epoch ? *Epoch : 0; + std::vector Files; + ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); + size_t NumLoaded = 0; + for (size_t i = 0; i < Files.size(); i++) { + auto &X = Files[i]; + if (Epoch && GetEpoch(X) < E) continue; + NumLoaded++; + if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) + Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); + auto S = FileToVector(X, MaxSize, ExitOnError); + if (!S.empty()) { + V->push_back(S); + if (VPaths) + VPaths->push_back(X); + } + } +} + +void GetSizedFilesFromDir(const std::string &Dir, std::vector *V) { + std::vector Files; + ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); + for (auto &File : Files) + if (size_t Size = FileSize(File)) + V->push_back({File, Size}); +} + +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName) { + return DirPath + GetSeparator() + FileName; +} + +void DupAndCloseStderr() { + int OutputFd = DuplicateFile(2); + if (OutputFd >= 0) { + FILE *NewOutputFile = OpenFile(OutputFd, "w"); + if (NewOutputFile) { + OutputFile = NewOutputFile; + if (EF->__sanitizer_set_report_fd) + EF->__sanitizer_set_report_fd( + reinterpret_cast(GetHandleFromFd(OutputFd))); + DiscardOutput(2); + } + } +} + +void CloseStdout() { + DiscardOutput(1); +} + +void Puts(const char *Str) { + fputs(Str, OutputFile); + fflush(OutputFile); +} + +void Printf(const char *Fmt, ...) { + va_list ap; + va_start(ap, Fmt); + vfprintf(OutputFile, Fmt, ap); + va_end(ap); + fflush(OutputFile); +} + +void VPrintf(bool Verbose, const char *Fmt, ...) { + if (!Verbose) return; + va_list ap; + va_start(ap, Fmt); + vfprintf(OutputFile, Fmt, ap); + va_end(ap); + fflush(OutputFile); +} + +static bool MkDirRecursiveInner(const std::string &Leaf) { + // Prevent chance of potential infinite recursion + if (Leaf == ".") + return true; + + const std::string &Dir = DirName(Leaf); + + if (IsDirectory(Dir)) { + MkDir(Leaf); + return IsDirectory(Leaf); + } + + bool ret = MkDirRecursiveInner(Dir); + if (!ret) { + // Give up early if a previous MkDir failed + return ret; + } + + MkDir(Leaf); + return IsDirectory(Leaf); +} + +bool MkDirRecursive(const std::string &Dir) { + if (Dir.empty()) + return false; + + if (IsDirectory(Dir)) + return true; + + return MkDirRecursiveInner(Dir); +} + +void RmDirRecursive(const std::string &Dir) { + IterateDirRecursive( + Dir, [](const std::string &Path) {}, + [](const std::string &Path) { RmDir(Path); }, + [](const std::string &Path) { RemoveFile(Path); }); +} + +std::string TempPath(const char *Prefix, const char *Extension) { + return DirPlusFile(TmpDir(), std::string("libFuzzerTemp.") + Prefix + + std::to_string(GetPid()) + Extension); +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIO.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,118 @@ +//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// IO interface. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_IO_H +#define LLVM_FUZZER_IO_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +long GetEpoch(const std::string &Path); + +Unit FileToVector(const std::string &Path, size_t MaxSize = 0, + bool ExitOnError = true); + +std::string FileToString(const std::string &Path); + +void CopyFileToErr(const std::string &Path); + +void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path); +// Write Data.c_str() to the file without terminating null character. +void WriteToFile(const std::string &Data, const std::string &Path); +void WriteToFile(const Unit &U, const std::string &Path); + +void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path); +void AppendToFile(const std::string &Data, const std::string &Path); + +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, + size_t MaxSize, bool ExitOnError, + std::vector *VPaths = 0); + +// Returns "Dir/FileName" or equivalent for the current OS. +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName); + +// Returns the name of the dir, similar to the 'dirname' utility. +std::string DirName(const std::string &FileName); + +// Returns path to a TmpDir. +std::string TmpDir(); + +std::string TempPath(const char *Prefix, const char *Extension); + +bool IsInterestingCoverageFile(const std::string &FileName); + +void DupAndCloseStderr(); + +void CloseStdout(); + +// For testing. +FILE *GetOutputFile(); +void SetOutputFile(FILE *NewOutputFile); + +void Puts(const char *Str); +void Printf(const char *Fmt, ...); +void VPrintf(bool Verbose, const char *Fmt, ...); + +// Print using raw syscalls, useful when printing at early init stages. +void RawPrint(const char *Str); + +// Platform specific functions: +bool IsFile(const std::string &Path); +bool IsDirectory(const std::string &Path); +size_t FileSize(const std::string &Path); + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir); + +bool MkDirRecursive(const std::string &Dir); +void RmDirRecursive(const std::string &Dir); + +// Iterate files and dirs inside Dir, recursively. +// Call DirPreCallback/DirPostCallback on dirs before/after +// calling FileCallback on files. +void IterateDirRecursive(const std::string &Dir, + void (*DirPreCallback)(const std::string &Dir), + void (*DirPostCallback)(const std::string &Dir), + void (*FileCallback)(const std::string &Dir)); + +struct SizedFile { + std::string File; + size_t Size; + bool operator<(const SizedFile &B) const { return Size < B.Size; } +}; + +void GetSizedFilesFromDir(const std::string &Dir, std::vector *V); + +char GetSeparator(); +bool IsSeparator(char C); +// Similar to the basename utility: returns the file name w/o the dir prefix. +std::string Basename(const std::string &Path); + +FILE* OpenFile(int Fd, const char *Mode); + +int CloseFile(int Fd); + +int DuplicateFile(int Fd); + +void RemoveFile(const std::string &Path); +void RenameFile(const std::string &OldPath, const std::string &NewPath); + +intptr_t GetHandleFromFd(int fd); + +void MkDir(const std::string &Path); +void RmDir(const std::string &Path); + +const std::string &getDevNull(); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_IO_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOPosix.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOPosix.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOPosix.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOPosix.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,179 @@ +//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// IO functions implementation using Posix API. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +bool IsFile(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return false; + return S_ISREG(St.st_mode); +} + +bool IsDirectory(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return false; + return S_ISDIR(St.st_mode); +} + +size_t FileSize(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return 0; + return St.st_size; +} + +std::string Basename(const std::string &Path) { + size_t Pos = Path.rfind(GetSeparator()); + if (Pos == std::string::npos) return Path; + assert(Pos < Path.size()); + return Path.substr(Pos + 1); +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + DIR *D = opendir(Dir.c_str()); + if (!D) { + Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); + exit(1); + } + while (auto E = readdir(D)) { + std::string Path = DirPlusFile(Dir, E->d_name); + if (E->d_type == DT_REG || E->d_type == DT_LNK || + (E->d_type == DT_UNKNOWN && IsFile(Path))) + V->push_back(Path); + else if ((E->d_type == DT_DIR || + (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && + *E->d_name != '.') + ListFilesInDirRecursive(Path, Epoch, V, false); + } + closedir(D); + if (Epoch && TopDir) + *Epoch = E; +} + +void IterateDirRecursive(const std::string &Dir, + void (*DirPreCallback)(const std::string &Dir), + void (*DirPostCallback)(const std::string &Dir), + void (*FileCallback)(const std::string &Dir)) { + DirPreCallback(Dir); + DIR *D = opendir(Dir.c_str()); + if (!D) return; + while (auto E = readdir(D)) { + std::string Path = DirPlusFile(Dir, E->d_name); + if (E->d_type == DT_REG || E->d_type == DT_LNK || + (E->d_type == DT_UNKNOWN && IsFile(Path))) + FileCallback(Path); + else if ((E->d_type == DT_DIR || + (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && + *E->d_name != '.') + IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); + } + closedir(D); + DirPostCallback(Dir); +} + +char GetSeparator() { + return '/'; +} + +bool IsSeparator(char C) { + return C == '/'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return fdopen(Fd, Mode); +} + +int CloseFile(int fd) { + return close(fd); +} + +int DuplicateFile(int Fd) { + return dup(Fd); +} + +void RemoveFile(const std::string &Path) { + unlink(Path.c_str()); +} + +void RenameFile(const std::string &OldPath, const std::string &NewPath) { + rename(OldPath.c_str(), NewPath.c_str()); +} + +intptr_t GetHandleFromFd(int fd) { + return static_cast(fd); +} + +std::string DirName(const std::string &FileName) { + char *Tmp = new char[FileName.size() + 1]; + memcpy(Tmp, FileName.c_str(), FileName.size() + 1); + std::string Res = dirname(Tmp); + delete [] Tmp; + return Res; +} + +std::string TmpDir() { + if (auto Env = getenv("TMPDIR")) + return Env; + return "/tmp"; +} + +bool IsInterestingCoverageFile(const std::string &FileName) { + if (FileName.find("compiler-rt/lib/") != std::string::npos) + return false; // sanitizer internal. + if (FileName.find("/usr/lib/") != std::string::npos) + return false; + if (FileName.find("/usr/include/") != std::string::npos) + return false; + if (FileName == "") + return false; + return true; +} + +void RawPrint(const char *Str) { + (void)write(2, Str, strlen(Str)); +} + +void MkDir(const std::string &Path) { + mkdir(Path.c_str(), 0700); +} + +void RmDir(const std::string &Path) { + rmdir(Path.c_str()); +} + +const std::string &getDevNull() { + static const std::string devNull = "/dev/null"; + return devNull; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_POSIX diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOWindows.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOWindows.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOWindows.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerIOWindows.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,423 @@ +//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// IO functions implementation for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_WINDOWS + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static bool IsFile(const std::string &Path, const DWORD &FileAttributes) { + + if (FileAttributes & FILE_ATTRIBUTE_NORMAL) + return true; + + if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) + return false; + + HANDLE FileHandle( + CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0)); + + if (FileHandle == INVALID_HANDLE_VALUE) { + Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + return false; + } + + DWORD FileType = GetFileType(FileHandle); + + if (FileType == FILE_TYPE_UNKNOWN) { + Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + CloseHandle(FileHandle); + return false; + } + + if (FileType != FILE_TYPE_DISK) { + CloseHandle(FileHandle); + return false; + } + + CloseHandle(FileHandle); + return true; +} + +bool IsFile(const std::string &Path) { + DWORD Att = GetFileAttributesA(Path.c_str()); + + if (Att == INVALID_FILE_ATTRIBUTES) { + Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", + Path.c_str(), GetLastError()); + return false; + } + + return IsFile(Path, Att); +} + +static bool IsDir(DWORD FileAttrs) { + if (FileAttrs == INVALID_FILE_ATTRIBUTES) return false; + return FileAttrs & FILE_ATTRIBUTE_DIRECTORY; +} + +bool IsDirectory(const std::string &Path) { + DWORD Att = GetFileAttributesA(Path.c_str()); + + if (Att == INVALID_FILE_ATTRIBUTES) { + Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", + Path.c_str(), GetLastError()); + return false; + } + + return IsDir(Att); +} + +std::string Basename(const std::string &Path) { + size_t Pos = Path.find_last_of("/\\"); + if (Pos == std::string::npos) return Path; + assert(Pos < Path.size()); + return Path.substr(Pos + 1); +} + +size_t FileSize(const std::string &Path) { + WIN32_FILE_ATTRIBUTE_DATA attr; + if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) { + DWORD LastError = GetLastError(); + if (LastError != ERROR_FILE_NOT_FOUND) + Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n", + Path.c_str(), LastError); + return 0; + } + ULARGE_INTEGER size; + size.HighPart = attr.nFileSizeHigh; + size.LowPart = attr.nFileSizeLow; + return size.QuadPart; +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + std::string Path(Dir); + assert(!Path.empty()); + if (Path.back() != '\\') + Path.push_back('\\'); + Path.push_back('*'); + + // Get the first directory entry. + WIN32_FIND_DATAA FindInfo; + HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo)); + if (FindHandle == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + return; + Printf("No such file or directory: %s; exiting\n", Dir.c_str()); + exit(1); + } + + do { + std::string FileName = DirPlusFile(Dir, FindInfo.cFileName); + + if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + size_t FilenameLen = strlen(FindInfo.cFileName); + if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') || + (FilenameLen == 2 && FindInfo.cFileName[0] == '.' && + FindInfo.cFileName[1] == '.')) + continue; + + ListFilesInDirRecursive(FileName, Epoch, V, false); + } + else if (IsFile(FileName, FindInfo.dwFileAttributes)) + V->push_back(FileName); + } while (FindNextFileA(FindHandle, &FindInfo)); + + DWORD LastError = GetLastError(); + if (LastError != ERROR_NO_MORE_FILES) + Printf("FindNextFileA failed (Error code: %lu).\n", LastError); + + FindClose(FindHandle); + + if (Epoch && TopDir) + *Epoch = E; +} + +void IterateDirRecursive(const std::string &Dir, + void (*DirPreCallback)(const std::string &Dir), + void (*DirPostCallback)(const std::string &Dir), + void (*FileCallback)(const std::string &Dir)) { + // TODO(metzman): Implement ListFilesInDirRecursive via this function. + DirPreCallback(Dir); + + DWORD DirAttrs = GetFileAttributesA(Dir.c_str()); + if (!IsDir(DirAttrs)) return; + + std::string TargetDir(Dir); + assert(!TargetDir.empty()); + if (TargetDir.back() != '\\') TargetDir.push_back('\\'); + TargetDir.push_back('*'); + + WIN32_FIND_DATAA FindInfo; + // Find the directory's first file. + HANDLE FindHandle = FindFirstFileA(TargetDir.c_str(), &FindInfo); + if (FindHandle == INVALID_HANDLE_VALUE) { + DWORD LastError = GetLastError(); + if (LastError != ERROR_FILE_NOT_FOUND) { + // If the directory isn't empty, then something abnormal is going on. + Printf("FindFirstFileA failed for %s (Error code: %lu).\n", Dir.c_str(), + LastError); + } + return; + } + + do { + std::string Path = DirPlusFile(Dir, FindInfo.cFileName); + DWORD PathAttrs = FindInfo.dwFileAttributes; + if (IsDir(PathAttrs)) { + // Is Path the current directory (".") or the parent ("..")? + if (strcmp(FindInfo.cFileName, ".") == 0 || + strcmp(FindInfo.cFileName, "..") == 0) + continue; + IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); + } else if (PathAttrs != INVALID_FILE_ATTRIBUTES) { + FileCallback(Path); + } + } while (FindNextFileA(FindHandle, &FindInfo)); + + DWORD LastError = GetLastError(); + if (LastError != ERROR_NO_MORE_FILES) + Printf("FindNextFileA failed for %s (Error code: %lu).\n", Dir.c_str(), + LastError); + + FindClose(FindHandle); + DirPostCallback(Dir); +} + +char GetSeparator() { + return '\\'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return _fdopen(Fd, Mode); +} + +int CloseFile(int Fd) { + return _close(Fd); +} + +int DuplicateFile(int Fd) { + return _dup(Fd); +} + +void RemoveFile(const std::string &Path) { + _unlink(Path.c_str()); +} + +void RenameFile(const std::string &OldPath, const std::string &NewPath) { + rename(OldPath.c_str(), NewPath.c_str()); +} + +intptr_t GetHandleFromFd(int fd) { + return _get_osfhandle(fd); +} + +bool IsSeparator(char C) { + return C == '\\' || C == '/'; +} + +// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:". +// Returns number of characters considered if successful. +static size_t ParseDrive(const std::string &FileName, const size_t Offset, + bool Relative = true) { + if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':') + return 0; + if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) { + if (!Relative) // Accept relative path? + return 0; + else + return 2; + } + return 3; +} + +// Parse a file name, like: SomeFile.txt +// Returns number of characters considered if successful. +static size_t ParseFileName(const std::string &FileName, const size_t Offset) { + size_t Pos = Offset; + const size_t End = FileName.size(); + for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) + ; + return Pos - Offset; +} + +// Parse a directory ending in separator, like: `SomeDir\` +// Returns number of characters considered if successful. +static size_t ParseDir(const std::string &FileName, const size_t Offset) { + size_t Pos = Offset; + const size_t End = FileName.size(); + if (Pos >= End || IsSeparator(FileName[Pos])) + return 0; + for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) + ; + if (Pos >= End) + return 0; + ++Pos; // Include separator. + return Pos - Offset; +} + +// Parse a servername and share, like: `SomeServer\SomeShare\` +// Returns number of characters considered if successful. +static size_t ParseServerAndShare(const std::string &FileName, + const size_t Offset) { + size_t Pos = Offset, Res; + if (!(Res = ParseDir(FileName, Pos))) + return 0; + Pos += Res; + if (!(Res = ParseDir(FileName, Pos))) + return 0; + Pos += Res; + return Pos - Offset; +} + +// Parse the given Ref string from the position Offset, to exactly match the +// given string Patt. Returns number of characters considered if successful. +static size_t ParseCustomString(const std::string &Ref, size_t Offset, + const char *Patt) { + size_t Len = strlen(Patt); + if (Offset + Len > Ref.size()) + return 0; + return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0; +} + +// Parse a location, like: +// \\?\UNC\Server\Share\ \\?\C:\ \\Server\Share\ \ C:\ C: +// Returns number of characters considered if successful. +static size_t ParseLocation(const std::string &FileName) { + size_t Pos = 0, Res; + + if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) { + Pos += Res; + if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) { + Pos += Res; + if ((Res = ParseServerAndShare(FileName, Pos))) + return Pos + Res; + return 0; + } + if ((Res = ParseDrive(FileName, Pos, false))) + return Pos + Res; + return 0; + } + + if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { + ++Pos; + if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { + ++Pos; + if ((Res = ParseServerAndShare(FileName, Pos))) + return Pos + Res; + return 0; + } + return Pos; + } + + if ((Res = ParseDrive(FileName, Pos))) + return Pos + Res; + + return Pos; +} + +std::string DirName(const std::string &FileName) { + size_t LocationLen = ParseLocation(FileName); + size_t DirLen = 0, Res; + while ((Res = ParseDir(FileName, LocationLen + DirLen))) + DirLen += Res; + size_t FileLen = ParseFileName(FileName, LocationLen + DirLen); + + if (LocationLen + DirLen + FileLen != FileName.size()) { + Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str()); + exit(1); + } + + if (DirLen) { + --DirLen; // Remove trailing separator. + if (!FileLen) { // Path ended in separator. + assert(DirLen); + // Remove file name from Dir. + while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1])) + --DirLen; + if (DirLen) // Remove trailing separator. + --DirLen; + } + } + + if (!LocationLen) { // Relative path. + if (!DirLen) + return "."; + return std::string(".\\").append(FileName, 0, DirLen); + } + + return FileName.substr(0, LocationLen + DirLen); +} + +std::string TmpDir() { + std::string Tmp; + Tmp.resize(MAX_PATH + 1); + DWORD Size = GetTempPathA(Tmp.size(), &Tmp[0]); + if (Size == 0) { + Printf("Couldn't get Tmp path.\n"); + exit(1); + } + Tmp.resize(Size); + return Tmp; +} + +bool IsInterestingCoverageFile(const std::string &FileName) { + if (FileName.find("Program Files") != std::string::npos) + return false; + if (FileName.find("compiler-rt\\lib\\") != std::string::npos) + return false; // sanitizer internal. + if (FileName == "") + return false; + return true; +} + +void RawPrint(const char *Str) { + _write(2, Str, strlen(Str)); +} + +void MkDir(const std::string &Path) { + if (CreateDirectoryA(Path.c_str(), nullptr)) return; + Printf("CreateDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(), + GetLastError()); +} + +void RmDir(const std::string &Path) { + if (RemoveDirectoryA(Path.c_str())) return; + Printf("RemoveDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(), + GetLastError()); +} + +const std::string &getDevNull() { + static const std::string devNull = "NUL"; + return devNull; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterceptors.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterceptors.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterceptors.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterceptors.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +//===-- FuzzerInterceptors.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Intercept certain libc functions to aid fuzzing. +// Linked only when other RTs that define their own interceptors are not linked. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" + +#if LIBFUZZER_LINUX + +#define GET_CALLER_PC() __builtin_return_address(0) + +#define PTR_TO_REAL(x) real_##x +#define REAL(x) __interception::PTR_TO_REAL(x) +#define FUNC_TYPE(x) x##_type +#define DEFINE_REAL(ret_type, func, ...) \ + typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ + namespace __interception { \ + FUNC_TYPE(func) PTR_TO_REAL(func); \ + } + +#include +#include // for size_t +#include +#include // for dlsym() + +static void *getFuncAddr(const char *name, uintptr_t wrapper_addr) { + void *addr = dlsym(RTLD_NEXT, name); + if (!addr) { + // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is + // later in the library search order than the DSO that we are trying to + // intercept, which means that we cannot intercept this function. We still + // want the address of the real definition, though, so look it up using + // RTLD_DEFAULT. + addr = dlsym(RTLD_DEFAULT, name); + + // In case `name' is not loaded, dlsym ends up finding the actual wrapper. + // We don't want to intercept the wrapper and have it point to itself. + if (reinterpret_cast(addr) == wrapper_addr) + addr = nullptr; + } + return addr; +} + +static int FuzzerInited = 0; +static bool FuzzerInitIsRunning; + +static void fuzzerInit(); + +static void ensureFuzzerInited() { + assert(!FuzzerInitIsRunning); + if (!FuzzerInited) { + fuzzerInit(); + } +} + +static int internal_strcmp_strncmp(const char *s1, const char *s2, bool strncmp, + size_t n) { + size_t i = 0; + while (true) { + if (strncmp) { + if (i == n) + break; + i++; + } + unsigned c1 = *s1; + unsigned c2 = *s2; + if (c1 != c2) + return (c1 < c2) ? -1 : 1; + if (c1 == 0) + break; + s1++; + s2++; + } + return 0; +} + +static int internal_strncmp(const char *s1, const char *s2, size_t n) { + return internal_strcmp_strncmp(s1, s2, true, n); +} + +static int internal_strcmp(const char *s1, const char *s2) { + return internal_strcmp_strncmp(s1, s2, false, 0); +} + +static int internal_memcmp(const void *s1, const void *s2, size_t n) { + const uint8_t *t1 = static_cast(s1); + const uint8_t *t2 = static_cast(s2); + for (size_t i = 0; i < n; ++i, ++t1, ++t2) + if (*t1 != *t2) + return *t1 < *t2 ? -1 : 1; + return 0; +} + +static size_t internal_strlen(const char *s) { + size_t i = 0; + while (s[i]) + i++; + return i; +} + +static char *internal_strstr(const char *haystack, const char *needle) { + // This is O(N^2), but we are not using it in hot places. + size_t len1 = internal_strlen(haystack); + size_t len2 = internal_strlen(needle); + if (len1 < len2) + return nullptr; + for (size_t pos = 0; pos <= len1 - len2; pos++) { + if (internal_memcmp(haystack + pos, needle, len2) == 0) + return const_cast(haystack) + pos; + } + return nullptr; +} + +extern "C" { + +// Weak hooks forward-declared to avoid dependency on +// . +void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1, + const void *s2, size_t n, int result); +void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result); +void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result); +void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1, + const char *s2, int result); +void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, + const char *s2, int result); +void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result); +void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, + const char *s2, char *result); +void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, + const void *s2, size_t len2, void *result); + +DEFINE_REAL(int, bcmp, const void *, const void *, size_t) +DEFINE_REAL(int, memcmp, const void *, const void *, size_t) +DEFINE_REAL(int, strncmp, const char *, const char *, size_t) +DEFINE_REAL(int, strcmp, const char *, const char *) +DEFINE_REAL(int, strncasecmp, const char *, const char *, size_t) +DEFINE_REAL(int, strcasecmp, const char *, const char *) +DEFINE_REAL(char *, strstr, const char *, const char *) +DEFINE_REAL(char *, strcasestr, const char *, const char *) +DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t) + +ATTRIBUTE_INTERFACE int bcmp(const char *s1, const char *s2, size_t n) { + if (!FuzzerInited) + return internal_memcmp(s1, s2, n); + int result = REAL(bcmp)(s1, s2, n); + __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result); + return result; +} + +ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) { + if (!FuzzerInited) + return internal_memcmp(s1, s2, n); + int result = REAL(memcmp)(s1, s2, n); + __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result); + return result; +} + +ATTRIBUTE_INTERFACE int strncmp(const char *s1, const char *s2, size_t n) { + if (!FuzzerInited) + return internal_strncmp(s1, s2, n); + int result = REAL(strncmp)(s1, s2, n); + __sanitizer_weak_hook_strncmp(GET_CALLER_PC(), s1, s2, n, result); + return result; +} + +ATTRIBUTE_INTERFACE int strcmp(const char *s1, const char *s2) { + if (!FuzzerInited) + return internal_strcmp(s1, s2); + int result = REAL(strcmp)(s1, s2); + __sanitizer_weak_hook_strcmp(GET_CALLER_PC(), s1, s2, result); + return result; +} + +ATTRIBUTE_INTERFACE int strncasecmp(const char *s1, const char *s2, size_t n) { + ensureFuzzerInited(); + int result = REAL(strncasecmp)(s1, s2, n); + __sanitizer_weak_hook_strncasecmp(GET_CALLER_PC(), s1, s2, n, result); + return result; +} + +ATTRIBUTE_INTERFACE int strcasecmp(const char *s1, const char *s2) { + ensureFuzzerInited(); + int result = REAL(strcasecmp)(s1, s2); + __sanitizer_weak_hook_strcasecmp(GET_CALLER_PC(), s1, s2, result); + return result; +} + +ATTRIBUTE_INTERFACE char *strstr(const char *s1, const char *s2) { + if (!FuzzerInited) + return internal_strstr(s1, s2); + char *result = REAL(strstr)(s1, s2); + __sanitizer_weak_hook_strstr(GET_CALLER_PC(), s1, s2, result); + return result; +} + +ATTRIBUTE_INTERFACE char *strcasestr(const char *s1, const char *s2) { + ensureFuzzerInited(); + char *result = REAL(strcasestr)(s1, s2); + __sanitizer_weak_hook_strcasestr(GET_CALLER_PC(), s1, s2, result); + return result; +} + +ATTRIBUTE_INTERFACE +void *memmem(const void *s1, size_t len1, const void *s2, size_t len2) { + ensureFuzzerInited(); + void *result = REAL(memmem)(s1, len1, s2, len2); + __sanitizer_weak_hook_memmem(GET_CALLER_PC(), s1, len1, s2, len2, result); + return result; +} + +__attribute__((section(".preinit_array"), + used)) static void (*__local_fuzzer_preinit)(void) = fuzzerInit; + +} // extern "C" + +static void fuzzerInit() { + assert(!FuzzerInitIsRunning); + if (FuzzerInited) + return; + FuzzerInitIsRunning = true; + + REAL(bcmp) = reinterpret_cast( + getFuncAddr("bcmp", reinterpret_cast(&bcmp))); + REAL(memcmp) = reinterpret_cast( + getFuncAddr("memcmp", reinterpret_cast(&memcmp))); + REAL(strncmp) = reinterpret_cast( + getFuncAddr("strncmp", reinterpret_cast(&strncmp))); + REAL(strcmp) = reinterpret_cast( + getFuncAddr("strcmp", reinterpret_cast(&strcmp))); + REAL(strncasecmp) = reinterpret_cast( + getFuncAddr("strncasecmp", reinterpret_cast(&strncasecmp))); + REAL(strcasecmp) = reinterpret_cast( + getFuncAddr("strcasecmp", reinterpret_cast(&strcasecmp))); + REAL(strstr) = reinterpret_cast( + getFuncAddr("strstr", reinterpret_cast(&strstr))); + REAL(strcasestr) = reinterpret_cast( + getFuncAddr("strcasestr", reinterpret_cast(&strcasestr))); + REAL(memmem) = reinterpret_cast( + getFuncAddr("memmem", reinterpret_cast(&memmem))); + + FuzzerInitIsRunning = false; + FuzzerInited = 1; +} + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterface.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterface.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInterface.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Define the interface between libFuzzer and the library being tested. +//===----------------------------------------------------------------------===// + +// NOTE: the libFuzzer interface is thin and in the majority of cases +// you should not include this file into your target. In 95% of cases +// all you need is to define the following function in your file: +// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +// WARNING: keep the interface in C. + +#ifndef LLVM_FUZZER_INTERFACE_H +#define LLVM_FUZZER_INTERFACE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Define FUZZER_INTERFACE_VISIBILITY to set default visibility in a way that +// doesn't break MSVC. +#if defined(_WIN32) +#define FUZZER_INTERFACE_VISIBILITY __declspec(dllexport) +#else +#define FUZZER_INTERFACE_VISIBILITY __attribute__((visibility("default"))) +#endif + +// Mandatory user-provided target function. +// Executes the code under test with [Data, Data+Size) as the input. +// libFuzzer will invoke this function *many* times with different inputs. +// Must return 0. +FUZZER_INTERFACE_VISIBILITY int +LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +// Optional user-provided initialization function. +// If provided, this function will be called by libFuzzer once at startup. +// It may read and modify argc/argv. +// Must return 0. +FUZZER_INTERFACE_VISIBILITY int LLVMFuzzerInitialize(int *argc, char ***argv); + +// Optional user-provided custom mutator. +// Mutates raw data in [Data, Data+Size) inplace. +// Returns the new size, which is not greater than MaxSize. +// Given the same Seed produces the same mutation. +FUZZER_INTERFACE_VISIBILITY size_t +LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, + unsigned int Seed); + +// Optional user-provided custom cross-over function. +// Combines pieces of Data1 & Data2 together into Out. +// Returns the new size, which is not greater than MaxOutSize. +// Should produce the same mutation given the same Seed. +FUZZER_INTERFACE_VISIBILITY size_t +LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, uint8_t *Out, + size_t MaxOutSize, unsigned int Seed); + +// Experimental, may go away in future. +// libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator. +// Mutates raw data in [Data, Data+Size) inplace. +// Returns the new size, which is not greater than MaxSize. +FUZZER_INTERFACE_VISIBILITY size_t +LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); + +#undef FUZZER_INTERFACE_VISIBILITY + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // LLVM_FUZZER_INTERFACE_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInternal.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInternal.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInternal.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerInternal.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,178 @@ +//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Define the main class fuzzer::Fuzzer and most functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_INTERNAL_H +#define LLVM_FUZZER_INTERNAL_H + +#include "FuzzerDataFlowTrace.h" +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerInterface.h" +#include "FuzzerOptions.h" +#include "FuzzerSHA1.h" +#include "FuzzerValueBitMap.h" +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +using namespace std::chrono; + +class Fuzzer final { +public: + Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, + const FuzzingOptions &Options); + ~Fuzzer() = delete; + void Loop(std::vector &CorporaFiles); + void ReadAndExecuteSeedCorpora(std::vector &CorporaFiles); + void MinimizeCrashLoop(const Unit &U); + void RereadOutputCorpus(size_t MaxSize); + + size_t secondsSinceProcessStartUp() { + return duration_cast(system_clock::now() - ProcessStartTime) + .count(); + } + + bool TimedOut() { + return Options.MaxTotalTimeSec > 0 && + secondsSinceProcessStartUp() > + static_cast(Options.MaxTotalTimeSec); + } + + size_t execPerSec() { + size_t Seconds = secondsSinceProcessStartUp(); + return Seconds ? TotalNumberOfRuns / Seconds : 0; + } + + size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } + + static void StaticAlarmCallback(); + static void StaticCrashSignalCallback(); + static void StaticExitCallback(); + static void StaticInterruptCallback(); + static void StaticFileSizeExceedCallback(); + static void StaticGracefulExitCallback(); + + // Executes the target callback on {Data, Size} once. + // Returns false if the input was rejected by the target (target returned -1), + // and true otherwise. + bool ExecuteCallback(const uint8_t *Data, size_t Size); + bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, + InputInfo *II = nullptr, bool ForceAddToCorpus = false, + bool *FoundUniqFeatures = nullptr); + void TPCUpdateObservedPCs(); + + // Merge Corpora[1:] into Corpora[0]. + void Merge(const std::vector &Corpora); + void CrashResistantMergeInternalStep(const std::string &ControlFilePath, + bool IsSetCoverMerge); + MutationDispatcher &GetMD() { return MD; } + void PrintFinalStats(); + void SetMaxInputLen(size_t MaxInputLen); + void SetMaxMutationLen(size_t MaxMutationLen); + void RssLimitCallback(); + + bool InFuzzingThread() const { return IsMyThread; } + size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; + void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, + bool DuringInitialCorpusExecution); + + void HandleMalloc(size_t Size); + static void MaybeExitGracefully(); + static int InterruptExitCode(); + std::string WriteToOutputCorpus(const Unit &U); + +private: + void AlarmCallback(); + void CrashCallback(); + void ExitCallback(); + void CrashOnOverwrittenData(); + void InterruptCallback(); + void MutateAndTestOne(); + void PurgeAllocator(); + void ReportNewCoverage(InputInfo *II, const Unit &U); + void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); + void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); + void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, + size_t Features = 0); + void PrintStatusForNewUnit(const Unit &U, const char *Text); + void CheckExitOnSrcPosOrItem(); + + static void StaticDeathCallback(); + void DumpCurrentUnit(const char *Prefix); + void DeathCallback(); + + void AllocateCurrentUnitData(); + uint8_t *CurrentUnitData = nullptr; + std::atomic CurrentUnitSize; + uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. + + bool GracefulExitRequested = false; + + size_t TotalNumberOfRuns = 0; + size_t NumberOfNewUnitsAdded = 0; + + size_t LastCorpusUpdateRun = 0; + + bool HasMoreMallocsThanFrees = false; + size_t NumberOfLeakDetectionAttempts = 0; + + system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); + + UserCallback CB; + InputCorpus &Corpus; + MutationDispatcher &MD; + FuzzingOptions Options; + DataFlowTrace DFT; + + system_clock::time_point ProcessStartTime = system_clock::now(); + system_clock::time_point UnitStartTime, UnitStopTime; + long TimeOfLongestUnitInSeconds = 0; + long EpochOfLastReadOfOutputCorpus = 0; + + size_t MaxInputLen = 0; + size_t MaxMutationLen = 0; + size_t TmpMaxMutationLen = 0; + + std::vector UniqFeatureSetTmp; + + // Need to know our own thread. + static thread_local bool IsMyThread; +}; + +struct ScopedEnableMsanInterceptorChecks { + ScopedEnableMsanInterceptorChecks() { + if (EF->__msan_scoped_enable_interceptor_checks) + EF->__msan_scoped_enable_interceptor_checks(); + } + ~ScopedEnableMsanInterceptorChecks() { + if (EF->__msan_scoped_disable_interceptor_checks) + EF->__msan_scoped_disable_interceptor_checks(); + } +}; + +struct ScopedDisableMsanInterceptorChecks { + ScopedDisableMsanInterceptorChecks() { + if (EF->__msan_scoped_disable_interceptor_checks) + EF->__msan_scoped_disable_interceptor_checks(); + } + ~ScopedDisableMsanInterceptorChecks() { + if (EF->__msan_scoped_enable_interceptor_checks) + EF->__msan_scoped_enable_interceptor_checks(); + } +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_INTERNAL_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerLoop.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerLoop.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerLoop.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerLoop.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,946 @@ +//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Fuzzer's main loop. +//===----------------------------------------------------------------------===// + +#include "FuzzerCorpus.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include "FuzzerMutate.h" +#include "FuzzerPlatform.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include +#include +#include +#include +#include + +#if defined(__has_include) +#if __has_include() +#include +#endif +#endif + +#define NO_SANITIZE_MEMORY +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#undef NO_SANITIZE_MEMORY +#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#endif +#endif + +namespace fuzzer { +static const size_t kMaxUnitSizeToPrint = 256; + +thread_local bool Fuzzer::IsMyThread; + +bool RunningUserCallback = false; + +// Only one Fuzzer per process. +static Fuzzer *F; + +// Leak detection is expensive, so we first check if there were more mallocs +// than frees (using the sanitizer malloc hooks) and only then try to call lsan. +struct MallocFreeTracer { + void Start(int TraceLevel) { + this->TraceLevel = TraceLevel; + if (TraceLevel) + Printf("MallocFreeTracer: START\n"); + Mallocs = 0; + Frees = 0; + } + // Returns true if there were more mallocs than frees. + bool Stop() { + if (TraceLevel) + Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(), + Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT"); + bool Result = Mallocs > Frees; + Mallocs = 0; + Frees = 0; + TraceLevel = 0; + return Result; + } + std::atomic Mallocs; + std::atomic Frees; + int TraceLevel = 0; + + std::recursive_mutex TraceMutex; + bool TraceDisabled = false; +}; + +static MallocFreeTracer AllocTracer; + +// Locks printing and avoids nested hooks triggered from mallocs/frees in +// sanitizer. +class TraceLock { +public: + TraceLock() : Lock(AllocTracer.TraceMutex) { + AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; + } + ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; } + + bool IsDisabled() const { + // This is already inverted value. + return !AllocTracer.TraceDisabled; + } + +private: + std::lock_guard Lock; +}; + +ATTRIBUTE_NO_SANITIZE_MEMORY +void MallocHook(const volatile void *ptr, size_t size) { + size_t N = AllocTracer.Mallocs++; + F->HandleMalloc(size); + if (int TraceLevel = AllocTracer.TraceLevel) { + TraceLock Lock; + if (Lock.IsDisabled()) + return; + Printf("MALLOC[%zd] %p %zd\n", N, ptr, size); + if (TraceLevel >= 2 && EF) + PrintStackTrace(); + } +} + +ATTRIBUTE_NO_SANITIZE_MEMORY +void FreeHook(const volatile void *ptr) { + size_t N = AllocTracer.Frees++; + if (int TraceLevel = AllocTracer.TraceLevel) { + TraceLock Lock; + if (Lock.IsDisabled()) + return; + Printf("FREE[%zd] %p\n", N, ptr); + if (TraceLevel >= 2 && EF) + PrintStackTrace(); + } +} + +// Crash on a single malloc that exceeds the rss limit. +void Fuzzer::HandleMalloc(size_t Size) { + if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb) + return; + Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), + Size); + Printf(" To change the out-of-memory limit use -rss_limit_mb=\n\n"); + PrintStackTrace(); + DumpCurrentUnit("oom-"); + Printf("SUMMARY: libFuzzer: out-of-memory\n"); + PrintFinalStats(); + _Exit(Options.OOMExitCode); // Stop right now. +} + +Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, + const FuzzingOptions &Options) + : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { + if (EF->__sanitizer_set_death_callback) + EF->__sanitizer_set_death_callback(StaticDeathCallback); + assert(!F); + F = this; + TPC.ResetMaps(); + IsMyThread = true; + if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) + EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); + TPC.SetUseCounters(Options.UseCounters); + TPC.SetUseValueProfileMask(Options.UseValueProfile); + + if (Options.Verbosity) + TPC.PrintModuleInfo(); + if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec) + EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); + MaxInputLen = MaxMutationLen = Options.MaxLen; + TmpMaxMutationLen = 0; // Will be set once we load the corpus. + AllocateCurrentUnitData(); + CurrentUnitSize = 0; + memset(BaseSha1, 0, sizeof(BaseSha1)); +} + +void Fuzzer::AllocateCurrentUnitData() { + if (CurrentUnitData || MaxInputLen == 0) + return; + CurrentUnitData = new uint8_t[MaxInputLen]; +} + +void Fuzzer::StaticDeathCallback() { + assert(F); + F->DeathCallback(); +} + +void Fuzzer::DumpCurrentUnit(const char *Prefix) { + if (!CurrentUnitData) + return; // Happens when running individual inputs. + ScopedDisableMsanInterceptorChecks S; + MD.PrintMutationSequence(); + Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); + size_t UnitSize = CurrentUnitSize; + if (UnitSize <= kMaxUnitSizeToPrint) { + PrintHexArray(CurrentUnitData, UnitSize, "\n"); + PrintASCII(CurrentUnitData, UnitSize, "\n"); + } + WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, + Prefix); +} + +NO_SANITIZE_MEMORY +void Fuzzer::DeathCallback() { + DumpCurrentUnit("crash-"); + PrintFinalStats(); +} + +void Fuzzer::StaticAlarmCallback() { + assert(F); + F->AlarmCallback(); +} + +void Fuzzer::StaticCrashSignalCallback() { + assert(F); + F->CrashCallback(); +} + +void Fuzzer::StaticExitCallback() { + assert(F); + F->ExitCallback(); +} + +void Fuzzer::StaticInterruptCallback() { + assert(F); + F->InterruptCallback(); +} + +void Fuzzer::StaticGracefulExitCallback() { + assert(F); + F->GracefulExitRequested = true; + Printf("INFO: signal received, trying to exit gracefully\n"); +} + +void Fuzzer::StaticFileSizeExceedCallback() { + Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid()); + exit(1); +} + +void Fuzzer::CrashCallback() { + if (EF->__sanitizer_acquire_crash_state && + !EF->__sanitizer_acquire_crash_state()) + return; + Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); + PrintStackTrace(); + Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" + " Combine libFuzzer with AddressSanitizer or similar for better " + "crash reports.\n"); + Printf("SUMMARY: libFuzzer: deadly signal\n"); + DumpCurrentUnit("crash-"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // Stop right now. +} + +void Fuzzer::ExitCallback() { + if (!RunningUserCallback) + return; // This exit did not come from the user callback + if (EF->__sanitizer_acquire_crash_state && + !EF->__sanitizer_acquire_crash_state()) + return; + Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid()); + PrintStackTrace(); + Printf("SUMMARY: libFuzzer: fuzz target exited\n"); + DumpCurrentUnit("crash-"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); +} + +void Fuzzer::MaybeExitGracefully() { + if (!F->GracefulExitRequested) return; + Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); + RmDirRecursive(TempPath("FuzzWithFork", ".dir")); + F->PrintFinalStats(); + _Exit(0); +} + +int Fuzzer::InterruptExitCode() { + assert(F); + return F->Options.InterruptExitCode; +} + +void Fuzzer::InterruptCallback() { + Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); + PrintFinalStats(); + ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir(). + RmDirRecursive(TempPath("FuzzWithFork", ".dir")); + // Stop right now, don't perform any at-exit actions. + _Exit(Options.InterruptExitCode); +} + +NO_SANITIZE_MEMORY +void Fuzzer::AlarmCallback() { + assert(Options.UnitTimeoutSec > 0); + // In Windows and Fuchsia, Alarm callback is executed by a different thread. + // NetBSD's current behavior needs this change too. +#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA + if (!InFuzzingThread()) + return; +#endif + if (!RunningUserCallback) + return; // We have not started running units yet. + size_t Seconds = + duration_cast(system_clock::now() - UnitStartTime).count(); + if (Seconds == 0) + return; + if (Options.Verbosity >= 2) + Printf("AlarmCallback %zd\n", Seconds); + if (Seconds >= (size_t)Options.UnitTimeoutSec) { + if (EF->__sanitizer_acquire_crash_state && + !EF->__sanitizer_acquire_crash_state()) + return; + Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); + Printf(" and the timeout value is %d (use -timeout=N to change)\n", + Options.UnitTimeoutSec); + DumpCurrentUnit("timeout-"); + Printf("==%lu== ERROR: libFuzzer: timeout after %zu seconds\n", GetPid(), + Seconds); + PrintStackTrace(); + Printf("SUMMARY: libFuzzer: timeout\n"); + PrintFinalStats(); + _Exit(Options.TimeoutExitCode); // Stop right now. + } +} + +void Fuzzer::RssLimitCallback() { + if (EF->__sanitizer_acquire_crash_state && + !EF->__sanitizer_acquire_crash_state()) + return; + Printf("==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %dMb)\n", + GetPid(), GetPeakRSSMb(), Options.RssLimitMb); + Printf(" To change the out-of-memory limit use -rss_limit_mb=\n\n"); + PrintMemoryProfile(); + DumpCurrentUnit("oom-"); + Printf("SUMMARY: libFuzzer: out-of-memory\n"); + PrintFinalStats(); + _Exit(Options.OOMExitCode); // Stop right now. +} + +void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units, + size_t Features) { + size_t ExecPerSec = execPerSec(); + if (!Options.Verbosity) + return; + Printf("#%zd\t%s", TotalNumberOfRuns, Where); + if (size_t N = TPC.GetTotalPCCoverage()) + Printf(" cov: %zd", N); + if (size_t N = Features ? Features : Corpus.NumFeatures()) + Printf(" ft: %zd", N); + if (!Corpus.empty()) { + Printf(" corp: %zd", Corpus.NumActiveUnits()); + if (size_t N = Corpus.SizeInBytes()) { + if (N < (1 << 14)) + Printf("/%zdb", N); + else if (N < (1 << 24)) + Printf("/%zdKb", N >> 10); + else + Printf("/%zdMb", N >> 20); + } + if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) + Printf(" focus: %zd", FF); + } + if (TmpMaxMutationLen) + Printf(" lim: %zd", TmpMaxMutationLen); + if (Units) + Printf(" units: %zd", Units); + + Printf(" exec/s: %zd", ExecPerSec); + Printf(" rss: %zdMb", GetPeakRSSMb()); + Printf("%s", End); +} + +void Fuzzer::PrintFinalStats() { + if (Options.PrintFullCoverage) + TPC.PrintCoverage(/*PrintAllCounters=*/true); + if (Options.PrintCoverage) + TPC.PrintCoverage(/*PrintAllCounters=*/false); + if (Options.PrintCorpusStats) + Corpus.PrintStats(); + if (!Options.PrintFinalStats) + return; + size_t ExecPerSec = execPerSec(); + Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); + Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); + Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); + Printf("stat::slowest_unit_time_sec: %ld\n", TimeOfLongestUnitInSeconds); + Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); +} + +void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { + assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. + assert(MaxInputLen); + this->MaxInputLen = MaxInputLen; + this->MaxMutationLen = MaxInputLen; + AllocateCurrentUnitData(); + Printf("INFO: -max_len is not provided; " + "libFuzzer will not generate inputs larger than %zd bytes\n", + MaxInputLen); +} + +void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { + assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); + this->MaxMutationLen = MaxMutationLen; +} + +void Fuzzer::CheckExitOnSrcPosOrItem() { + if (!Options.ExitOnSrcPos.empty()) { + static auto *PCsSet = new std::set; + auto HandlePC = [&](const TracePC::PCTableEntry *TE) { + if (!PCsSet->insert(TE->PC).second) + return; + std::string Descr = DescribePC("%F %L", TE->PC + 1); + if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { + Printf("INFO: found line matching '%s', exiting.\n", + Options.ExitOnSrcPos.c_str()); + _Exit(0); + } + }; + TPC.ForEachObservedPC(HandlePC); + } + if (!Options.ExitOnItem.empty()) { + if (Corpus.HasUnit(Options.ExitOnItem)) { + Printf("INFO: found item with checksum '%s', exiting.\n", + Options.ExitOnItem.c_str()); + _Exit(0); + } + } +} + +void Fuzzer::RereadOutputCorpus(size_t MaxSize) { + if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) + return; + std::vector AdditionalCorpus; + std::vector AdditionalCorpusPaths; + ReadDirToVectorOfUnits( + Options.OutputCorpus.c_str(), &AdditionalCorpus, + &EpochOfLastReadOfOutputCorpus, MaxSize, + /*ExitOnError*/ false, + (Options.Verbosity >= 2 ? &AdditionalCorpusPaths : nullptr)); + if (Options.Verbosity >= 2) + Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); + bool Reloaded = false; + for (size_t i = 0; i != AdditionalCorpus.size(); ++i) { + auto &U = AdditionalCorpus[i]; + if (U.size() > MaxSize) + U.resize(MaxSize); + if (!Corpus.HasUnit(U)) { + if (RunOne(U.data(), U.size())) { + CheckExitOnSrcPosOrItem(); + Reloaded = true; + if (Options.Verbosity >= 2) + Printf("Reloaded %s\n", AdditionalCorpusPaths[i].c_str()); + } + } + } + if (Reloaded) + PrintStats("RELOAD"); +} + +void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { + auto TimeOfUnit = + duration_cast(UnitStopTime - UnitStartTime).count(); + if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && + secondsSinceProcessStartUp() >= 2) + PrintStats("pulse "); + auto Threshhold = + static_cast(static_cast(TimeOfLongestUnitInSeconds) * 1.1); + if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) { + TimeOfLongestUnitInSeconds = TimeOfUnit; + Printf("Slowest unit: %ld s:\n", TimeOfLongestUnitInSeconds); + WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); + } +} + +static void WriteFeatureSetToFile(const std::string &FeaturesDir, + const std::string &FileName, + const std::vector &FeatureSet) { + if (FeaturesDir.empty() || FeatureSet.empty()) return; + WriteToFile(reinterpret_cast(FeatureSet.data()), + FeatureSet.size() * sizeof(FeatureSet[0]), + DirPlusFile(FeaturesDir, FileName)); +} + +static void RenameFeatureSetFile(const std::string &FeaturesDir, + const std::string &OldFile, + const std::string &NewFile) { + if (FeaturesDir.empty()) return; + RenameFile(DirPlusFile(FeaturesDir, OldFile), + DirPlusFile(FeaturesDir, NewFile)); +} + +static void WriteEdgeToMutationGraphFile(const std::string &MutationGraphFile, + const InputInfo *II, + const InputInfo *BaseII, + const std::string &MS) { + if (MutationGraphFile.empty()) + return; + + std::string Sha1 = Sha1ToString(II->Sha1); + + std::string OutputString; + + // Add a new vertex. + OutputString.append("\""); + OutputString.append(Sha1); + OutputString.append("\"\n"); + + // Add a new edge if there is base input. + if (BaseII) { + std::string BaseSha1 = Sha1ToString(BaseII->Sha1); + OutputString.append("\""); + OutputString.append(BaseSha1); + OutputString.append("\" -> \""); + OutputString.append(Sha1); + OutputString.append("\" [label=\""); + OutputString.append(MS); + OutputString.append("\"];\n"); + } + + AppendToFile(OutputString, MutationGraphFile); +} + +bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, + InputInfo *II, bool ForceAddToCorpus, + bool *FoundUniqFeatures) { + if (!Size) + return false; + // Largest input length should be INT_MAX. + assert(Size < std::numeric_limits::max()); + + if(!ExecuteCallback(Data, Size)) return false; + auto TimeOfUnit = duration_cast(UnitStopTime - UnitStartTime); + + UniqFeatureSetTmp.clear(); + size_t FoundUniqFeaturesOfII = 0; + size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); + TPC.CollectFeatures([&](uint32_t Feature) { + if (Corpus.AddFeature(Feature, static_cast(Size), Options.Shrink)) + UniqFeatureSetTmp.push_back(Feature); + if (Options.Entropic) + Corpus.UpdateFeatureFrequency(II, Feature); + if (Options.ReduceInputs && II && !II->NeverReduce) + if (std::binary_search(II->UniqFeatureSet.begin(), + II->UniqFeatureSet.end(), Feature)) + FoundUniqFeaturesOfII++; + }); + if (FoundUniqFeatures) + *FoundUniqFeatures = FoundUniqFeaturesOfII; + PrintPulseAndReportSlowInput(Data, Size); + size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; + if (NumNewFeatures || ForceAddToCorpus) { + TPC.UpdateObservedPCs(); + auto NewII = + Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, + TPC.ObservedFocusFunction(), ForceAddToCorpus, + TimeOfUnit, UniqFeatureSetTmp, DFT, II); + WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1), + NewII->UniqFeatureSet); + WriteEdgeToMutationGraphFile(Options.MutationGraphFile, NewII, II, + MD.MutationSequence()); + return true; + } + if (II && FoundUniqFeaturesOfII && + II->DataFlowTraceForFocusFunction.empty() && + FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && + II->U.size() > Size) { + auto OldFeaturesFile = Sha1ToString(II->Sha1); + Corpus.Replace(II, {Data, Data + Size}, TimeOfUnit); + RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, + Sha1ToString(II->Sha1)); + return true; + } + return false; +} + +void Fuzzer::TPCUpdateObservedPCs() { TPC.UpdateObservedPCs(); } + +size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { + assert(InFuzzingThread()); + *Data = CurrentUnitData; + return CurrentUnitSize; +} + +void Fuzzer::CrashOnOverwrittenData() { + Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n", + GetPid()); + PrintStackTrace(); + Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); + DumpCurrentUnit("crash-"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // Stop right now. +} + +// Compare two arrays, but not all bytes if the arrays are large. +static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { + const size_t Limit = 64; + // memcmp cannot take null pointer arguments even if Size is 0. + if (!Size) + return true; + if (Size <= 64) + return !memcmp(A, B, Size); + // Compare first and last Limit/2 bytes. + return !memcmp(A, B, Limit / 2) && + !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); +} + +// This method is not inlined because it would cause a test to fail where it +// is part of the stack unwinding. See D97975 for details. +ATTRIBUTE_NOINLINE bool Fuzzer::ExecuteCallback(const uint8_t *Data, + size_t Size) { + TPC.RecordInitialStack(); + TotalNumberOfRuns++; + assert(InFuzzingThread()); + // We copy the contents of Unit into a separate heap buffer + // so that we reliably find buffer overflows in it. + uint8_t *DataCopy = new uint8_t[Size]; + // memcpy cannot take null pointer arguments even if Size is 0. + if (Size) + memcpy(DataCopy, Data, Size); + if (EF->__msan_unpoison) + EF->__msan_unpoison(DataCopy, Size); + if (EF->__msan_unpoison_param) + EF->__msan_unpoison_param(2); + if (CurrentUnitData && CurrentUnitData != Data) + memcpy(CurrentUnitData, Data, Size); + CurrentUnitSize = Size; + int CBRes = 0; + { + ScopedEnableMsanInterceptorChecks S; + AllocTracer.Start(Options.TraceMalloc); + UnitStartTime = system_clock::now(); + TPC.ResetMaps(); + RunningUserCallback = true; + CBRes = CB(DataCopy, Size); + RunningUserCallback = false; + UnitStopTime = system_clock::now(); + assert(CBRes == 0 || CBRes == -1); + HasMoreMallocsThanFrees = AllocTracer.Stop(); + } + if (!LooseMemeq(DataCopy, Data, Size)) + CrashOnOverwrittenData(); + CurrentUnitSize = 0; + delete[] DataCopy; + return CBRes == 0; +} + +std::string Fuzzer::WriteToOutputCorpus(const Unit &U) { + if (Options.OnlyASCII) + assert(IsASCII(U)); + if (Options.OutputCorpus.empty()) + return ""; + std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); + WriteToFile(U, Path); + if (Options.Verbosity >= 2) + Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); + return Path; +} + +void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { + if (!Options.SaveArtifacts) + return; + std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); + if (!Options.ExactArtifactPath.empty()) + Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. + WriteToFile(U, Path); + Printf("artifact_prefix='%s'; Test unit written to %s\n", + Options.ArtifactPrefix.c_str(), Path.c_str()); + if (U.size() <= kMaxUnitSizeToPrint) + Printf("Base64: %s\n", Base64(U).c_str()); +} + +void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { + if (!Options.PrintNEW) + return; + PrintStats(Text, ""); + if (Options.Verbosity) { + Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); + MD.PrintMutationSequence(Options.Verbosity >= 2); + Printf("\n"); + } +} + +void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { + II->NumSuccessfullMutations++; + MD.RecordSuccessfulMutationSequence(); + PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); + WriteToOutputCorpus(U); + NumberOfNewUnitsAdded++; + CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. + LastCorpusUpdateRun = TotalNumberOfRuns; +} + +// Tries detecting a memory leak on the particular input that we have just +// executed before calling this function. +void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, + bool DuringInitialCorpusExecution) { + if (!HasMoreMallocsThanFrees) + return; // mallocs==frees, a leak is unlikely. + if (!Options.DetectLeaks) + return; + if (!DuringInitialCorpusExecution && + TotalNumberOfRuns >= Options.MaxNumberOfRuns) + return; + if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || + !(EF->__lsan_do_recoverable_leak_check)) + return; // No lsan. + // Run the target once again, but with lsan disabled so that if there is + // a real leak we do not report it twice. + EF->__lsan_disable(); + ExecuteCallback(Data, Size); + EF->__lsan_enable(); + if (!HasMoreMallocsThanFrees) + return; // a leak is unlikely. + if (NumberOfLeakDetectionAttempts++ > 1000) { + Options.DetectLeaks = false; + Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" + " Most likely the target function accumulates allocated\n" + " memory in a global state w/o actually leaking it.\n" + " You may try running this binary with -trace_malloc=[12]" + " to get a trace of mallocs and frees.\n" + " If LeakSanitizer is enabled in this process it will still\n" + " run on the process shutdown.\n"); + return; + } + // Now perform the actual lsan pass. This is expensive and we must ensure + // we don't call it too often. + if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. + if (DuringInitialCorpusExecution) + Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); + Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); + CurrentUnitSize = Size; + DumpCurrentUnit("leak-"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. + } +} + +void Fuzzer::MutateAndTestOne() { + MD.StartMutationSequence(); + + auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); + if (Options.DoCrossOver) { + auto &CrossOverII = Corpus.ChooseUnitToCrossOverWith( + MD.GetRand(), Options.CrossOverUniformDist); + MD.SetCrossOverWith(&CrossOverII.U); + } + const auto &U = II.U; + memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); + assert(CurrentUnitData); + size_t Size = U.size(); + assert(Size <= MaxInputLen && "Oversized Unit"); + memcpy(CurrentUnitData, U.data(), Size); + + assert(MaxMutationLen > 0); + + size_t CurrentMaxMutationLen = + Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); + assert(CurrentMaxMutationLen > 0); + + for (int i = 0; i < Options.MutateDepth; i++) { + if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) + break; + MaybeExitGracefully(); + size_t NewSize = 0; + if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && + Size <= CurrentMaxMutationLen) + NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, + II.DataFlowTraceForFocusFunction); + + // If MutateWithMask either failed or wasn't called, call default Mutate. + if (!NewSize) + NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); + assert(NewSize > 0 && "Mutator returned empty unit"); + assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); + Size = NewSize; + II.NumExecutedMutations++; + Corpus.IncrementNumExecutedMutations(); + + bool FoundUniqFeatures = false; + bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, + /*ForceAddToCorpus*/ false, &FoundUniqFeatures); + TryDetectingAMemoryLeak(CurrentUnitData, Size, + /*DuringInitialCorpusExecution*/ false); + if (NewCov) { + ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); + break; // We will mutate this input more in the next rounds. + } + if (Options.ReduceDepth && !FoundUniqFeatures) + break; + } + + II.NeedsEnergyUpdate = true; +} + +void Fuzzer::PurgeAllocator() { + if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) + return; + if (duration_cast(system_clock::now() - + LastAllocatorPurgeAttemptTime) + .count() < Options.PurgeAllocatorIntervalSec) + return; + + if (Options.RssLimitMb <= 0 || + GetPeakRSSMb() > static_cast(Options.RssLimitMb) / 2) + EF->__sanitizer_purge_allocator(); + + LastAllocatorPurgeAttemptTime = system_clock::now(); +} + +void Fuzzer::ReadAndExecuteSeedCorpora(std::vector &CorporaFiles) { + const size_t kMaxSaneLen = 1 << 20; + const size_t kMinDefaultLen = 4096; + size_t MaxSize = 0; + size_t MinSize = -1; + size_t TotalSize = 0; + for (auto &File : CorporaFiles) { + MaxSize = Max(File.Size, MaxSize); + MinSize = Min(File.Size, MinSize); + TotalSize += File.Size; + } + if (Options.MaxLen == 0) + SetMaxInputLen(std::clamp(MaxSize, kMinDefaultLen, kMaxSaneLen)); + assert(MaxInputLen > 0); + + // Test the callback with empty input and never try it again. + uint8_t dummy = 0; + ExecuteCallback(&dummy, 0); + + if (CorporaFiles.empty()) { + Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); + Unit U({'\n'}); // Valid ASCII input. + RunOne(U.data(), U.size()); + } else { + Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" + " rss: %zdMb\n", + CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); + if (Options.ShuffleAtStartUp) + std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand()); + + if (Options.PreferSmall) { + std::stable_sort(CorporaFiles.begin(), CorporaFiles.end()); + assert(CorporaFiles.front().Size <= CorporaFiles.back().Size); + } + + // Load and execute inputs one by one. + for (auto &SF : CorporaFiles) { + auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); + assert(U.size() <= MaxInputLen); + RunOne(U.data(), U.size(), /*MayDeleteFile*/ false, /*II*/ nullptr, + /*ForceAddToCorpus*/ Options.KeepSeed, + /*FoundUniqFeatures*/ nullptr); + CheckExitOnSrcPosOrItem(); + TryDetectingAMemoryLeak(U.data(), U.size(), + /*DuringInitialCorpusExecution*/ true); + } + } + + PrintStats("INITED"); + if (!Options.FocusFunction.empty()) { + Printf("INFO: %zd/%zd inputs touch the focus function\n", + Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); + if (!Options.DataFlowTrace.empty()) + Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", + Corpus.NumInputsWithDataFlowTrace(), + Corpus.NumInputsThatTouchFocusFunction()); + } + + if (Corpus.empty() && Options.MaxNumberOfRuns) { + Printf("WARNING: no interesting inputs were found so far. " + "Is the code instrumented for coverage?\n" + "This may also happen if the target rejected all inputs we tried so " + "far\n"); + // The remaining logic requires that the corpus is not empty, + // so we add one fake input to the in-memory corpus. + Corpus.AddToCorpus({'\n'}, /*NumFeatures=*/1, /*MayDeleteFile=*/true, + /*HasFocusFunction=*/false, /*NeverReduce=*/false, + /*TimeOfUnit=*/duration_cast(0s), {0}, DFT, + /*BaseII*/ nullptr); + } +} + +void Fuzzer::Loop(std::vector &CorporaFiles) { + auto FocusFunctionOrAuto = Options.FocusFunction; + DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, + MD.GetRand()); + TPC.SetFocusFunction(FocusFunctionOrAuto); + ReadAndExecuteSeedCorpora(CorporaFiles); + DFT.Clear(); // No need for DFT any more. + TPC.SetPrintNewPCs(Options.PrintNewCovPcs); + TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); + system_clock::time_point LastCorpusReload = system_clock::now(); + + TmpMaxMutationLen = + Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize())); + + while (true) { + auto Now = system_clock::now(); + if (!Options.StopFile.empty() && + !FileToVector(Options.StopFile, 1, false).empty()) + break; + if (duration_cast(Now - LastCorpusReload).count() >= + Options.ReloadIntervalSec) { + RereadOutputCorpus(MaxInputLen); + LastCorpusReload = system_clock::now(); + } + if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) + break; + if (TimedOut()) + break; + + // Update TmpMaxMutationLen + if (Options.LenControl) { + if (TmpMaxMutationLen < MaxMutationLen && + TotalNumberOfRuns - LastCorpusUpdateRun > + Options.LenControl * Log(TmpMaxMutationLen)) { + TmpMaxMutationLen = + Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); + LastCorpusUpdateRun = TotalNumberOfRuns; + } + } else { + TmpMaxMutationLen = MaxMutationLen; + } + + // Perform several mutations and runs. + MutateAndTestOne(); + + PurgeAllocator(); + } + + PrintStats("DONE ", "\n"); + MD.PrintRecommendedDictionary(); +} + +void Fuzzer::MinimizeCrashLoop(const Unit &U) { + if (U.size() <= 1) + return; + while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { + MD.StartMutationSequence(); + memcpy(CurrentUnitData, U.data(), U.size()); + for (int i = 0; i < Options.MutateDepth; i++) { + size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); + assert(NewSize > 0 && NewSize <= MaxMutationLen); + ExecuteCallback(CurrentUnitData, NewSize); + PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); + TryDetectingAMemoryLeak(CurrentUnitData, NewSize, + /*DuringInitialCorpusExecution*/ false); + } + } +} + +} // namespace fuzzer + +extern "C" { + +ATTRIBUTE_INTERFACE size_t +LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { + assert(fuzzer::F); + return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); +} + +} // extern "C" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMain.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMain.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMain.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMain.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +//===- FuzzerMain.cpp - main() function and flags -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// main() and flags. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#include "FuzzerPlatform.h" + +extern "C" { +// This function should be defined by the user. +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +} // extern "C" + +ATTRIBUTE_INTERFACE int main(int argc, char **argv) { + return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,539 @@ +//===- FuzzerMerge.cpp - merging corpora ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Merging corpora. +//===----------------------------------------------------------------------===// + +#include "FuzzerCommand.h" +#include "FuzzerMerge.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include "FuzzerTracePC.h" +#include "FuzzerUtil.h" + +#include +#include +#include +#include +#include + +namespace fuzzer { + +bool Merger::Parse(const std::string &Str, bool ParseCoverage) { + std::istringstream SS(Str); + return Parse(SS, ParseCoverage); +} + +void Merger::ParseOrExit(std::istream &IS, bool ParseCoverage) { + if (!Parse(IS, ParseCoverage)) { + Printf("MERGE: failed to parse the control file (unexpected error)\n"); + exit(1); + } +} + +// The control file example: +// +// 3 # The number of inputs +// 1 # The number of inputs in the first corpus, <= the previous number +// file0 +// file1 +// file2 # One file name per line. +// STARTED 0 123 # FileID, file size +// FT 0 1 4 6 8 # FileID COV1 COV2 ... +// COV 0 7 8 9 # FileID COV1 COV1 +// STARTED 1 456 # If FT is missing, the input crashed while processing. +// STARTED 2 567 +// FT 2 8 9 +// COV 2 11 12 +bool Merger::Parse(std::istream &IS, bool ParseCoverage) { + LastFailure.clear(); + std::string Line; + + // Parse NumFiles. + if (!std::getline(IS, Line, '\n')) return false; + std::istringstream L1(Line); + size_t NumFiles = 0; + L1 >> NumFiles; + if (NumFiles == 0 || NumFiles > 10000000) return false; + + // Parse NumFilesInFirstCorpus. + if (!std::getline(IS, Line, '\n')) return false; + std::istringstream L2(Line); + NumFilesInFirstCorpus = NumFiles + 1; + L2 >> NumFilesInFirstCorpus; + if (NumFilesInFirstCorpus > NumFiles) return false; + + // Parse file names. + Files.resize(NumFiles); + for (size_t i = 0; i < NumFiles; i++) + if (!std::getline(IS, Files[i].Name, '\n')) + return false; + + // Parse STARTED, FT, and COV lines. + size_t ExpectedStartMarker = 0; + const size_t kInvalidStartMarker = -1; + size_t LastSeenStartMarker = kInvalidStartMarker; + bool HaveFtMarker = true; + std::vector TmpFeatures; + std::set PCs; + while (std::getline(IS, Line, '\n')) { + std::istringstream ISS1(Line); + std::string Marker; + uint32_t N; + if (!(ISS1 >> Marker) || !(ISS1 >> N)) + return false; + if (Marker == "STARTED") { + // STARTED FILE_ID FILE_SIZE + if (ExpectedStartMarker != N) + return false; + ISS1 >> Files[ExpectedStartMarker].Size; + LastSeenStartMarker = ExpectedStartMarker; + assert(ExpectedStartMarker < Files.size()); + ExpectedStartMarker++; + HaveFtMarker = false; + } else if (Marker == "FT") { + // FT FILE_ID COV1 COV2 COV3 ... + size_t CurrentFileIdx = N; + if (CurrentFileIdx != LastSeenStartMarker) + return false; + HaveFtMarker = true; + if (ParseCoverage) { + TmpFeatures.clear(); // use a vector from outer scope to avoid resizes. + while (ISS1 >> N) + TmpFeatures.push_back(N); + std::sort(TmpFeatures.begin(), TmpFeatures.end()); + Files[CurrentFileIdx].Features = TmpFeatures; + } + } else if (Marker == "COV") { + size_t CurrentFileIdx = N; + if (CurrentFileIdx != LastSeenStartMarker) + return false; + if (ParseCoverage) + while (ISS1 >> N) + if (PCs.insert(N).second) + Files[CurrentFileIdx].Cov.push_back(N); + } else { + return false; + } + } + if (!HaveFtMarker && LastSeenStartMarker != kInvalidStartMarker) + LastFailure = Files[LastSeenStartMarker].Name; + + FirstNotProcessedFile = ExpectedStartMarker; + return true; +} + +size_t Merger::ApproximateMemoryConsumption() const { + size_t Res = 0; + for (const auto &F: Files) + Res += sizeof(F) + F.Features.size() * sizeof(F.Features[0]); + return Res; +} + +// Decides which files need to be merged (add those to NewFiles). +// Returns the number of new features added. +size_t Merger::Merge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles) { + NewFiles->clear(); + NewFeatures->clear(); + NewCov->clear(); + assert(NumFilesInFirstCorpus <= Files.size()); + std::set AllFeatures = InitialFeatures; + + // What features are in the initial corpus? + for (size_t i = 0; i < NumFilesInFirstCorpus; i++) { + auto &Cur = Files[i].Features; + AllFeatures.insert(Cur.begin(), Cur.end()); + } + // Remove all features that we already know from all other inputs. + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { + auto &Cur = Files[i].Features; + std::vector Tmp; + std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(), + AllFeatures.end(), std::inserter(Tmp, Tmp.begin())); + Cur.swap(Tmp); + } + + // Sort. Give preference to + // * smaller files + // * files with more features. + std::sort(Files.begin() + NumFilesInFirstCorpus, Files.end(), + [&](const MergeFileInfo &a, const MergeFileInfo &b) -> bool { + if (a.Size != b.Size) + return a.Size < b.Size; + return a.Features.size() > b.Features.size(); + }); + + // One greedy pass: add the file's features to AllFeatures. + // If new features were added, add this file to NewFiles. + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { + auto &Cur = Files[i].Features; + // Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(), + // Files[i].Size, Cur.size()); + bool FoundNewFeatures = false; + for (auto Fe: Cur) { + if (AllFeatures.insert(Fe).second) { + FoundNewFeatures = true; + NewFeatures->insert(Fe); + } + } + if (FoundNewFeatures) + NewFiles->push_back(Files[i].Name); + for (auto Cov : Files[i].Cov) + if (InitialCov.find(Cov) == InitialCov.end()) + NewCov->insert(Cov); + } + return NewFeatures->size(); +} + +std::set Merger::AllFeatures() const { + std::set S; + for (auto &File : Files) + S.insert(File.Features.begin(), File.Features.end()); + return S; +} + +// Inner process. May crash if the target crashes. +void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath, + bool IsSetCoverMerge) { + Printf("MERGE-INNER: using the control file '%s'\n", CFPath.c_str()); + Merger M; + std::ifstream IF(CFPath); + M.ParseOrExit(IF, false); + IF.close(); + if (!M.LastFailure.empty()) + Printf("MERGE-INNER: '%s' caused a failure at the previous merge step\n", + M.LastFailure.c_str()); + + Printf("MERGE-INNER: %zd total files;" + " %zd processed earlier; will process %zd files now\n", + M.Files.size(), M.FirstNotProcessedFile, + M.Files.size() - M.FirstNotProcessedFile); + + std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app); + std::set AllFeatures; + auto PrintStatsWrapper = [this, &AllFeatures](const char* Where) { + this->PrintStats(Where, "\n", 0, AllFeatures.size()); + }; + std::set AllPCs; + for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) { + Fuzzer::MaybeExitGracefully(); + auto U = FileToVector(M.Files[i].Name); + if (U.size() > MaxInputLen) { + U.resize(MaxInputLen); + U.shrink_to_fit(); + } + + // Write the pre-run marker. + OF << "STARTED " << i << " " << U.size() << "\n"; + OF.flush(); // Flush is important since Command::Execute may crash. + // Run. + TPC.ResetMaps(); + ExecuteCallback(U.data(), U.size()); + // Collect coverage. We are iterating over the files in this order: + // * First, files in the initial corpus ordered by size, smallest first. + // * Then, all other files, smallest first. + std::set Features; + if (IsSetCoverMerge) + TPC.CollectFeatures([&](size_t Feature) { Features.insert(Feature); }); + else + TPC.CollectFeatures([&](size_t Feature) { + if (AllFeatures.insert(Feature).second) + Features.insert(Feature); + }); + TPC.UpdateObservedPCs(); + // Show stats. + if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))) + PrintStatsWrapper("pulse "); + if (TotalNumberOfRuns == M.NumFilesInFirstCorpus) + PrintStatsWrapper("LOADED"); + // Write the post-run marker and the coverage. + OF << "FT " << i; + for (size_t F : Features) + OF << " " << F; + OF << "\n"; + OF << "COV " << i; + TPC.ForEachObservedPC([&](const TracePC::PCTableEntry *TE) { + if (AllPCs.insert(TE).second) + OF << " " << TPC.PCTableEntryIdx(TE); + }); + OF << "\n"; + OF.flush(); + } + PrintStatsWrapper("DONE "); +} + +// Merges all corpora into the first corpus. A file is added into +// the first corpus only if it adds new features. Unlike `Merger::Merge`, +// this implementation calculates an approximation of the minimum set +// of corpora files, that cover all known features (set cover problem). +// Generally, this means that files with more features are preferred for +// merge into the first corpus. When two files have the same number of +// features, the smaller one is preferred. +size_t Merger::SetCoverMerge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles) { + assert(NumFilesInFirstCorpus <= Files.size()); + NewFiles->clear(); + NewFeatures->clear(); + NewCov->clear(); + std::set AllFeatures; + // 1 << 21 - 1 is the maximum feature index. + // See 'kFeatureSetSize' in 'FuzzerCorpus.h'. + const uint32_t kFeatureSetSize = 1 << 21; + std::vector Covered(kFeatureSetSize, false); + size_t NumCovered = 0; + + std::set ExistingFeatures = InitialFeatures; + for (size_t i = 0; i < NumFilesInFirstCorpus; ++i) + ExistingFeatures.insert(Files[i].Features.begin(), Files[i].Features.end()); + + // Mark the existing features as covered. + for (const auto &F : ExistingFeatures) { + if (!Covered[F % kFeatureSetSize]) { + ++NumCovered; + Covered[F % kFeatureSetSize] = true; + } + // Calculate an underestimation of the set of covered features + // since the `Covered` bitvector is smaller than the feature range. + AllFeatures.insert(F % kFeatureSetSize); + } + + std::set RemainingFiles; + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); ++i) { + // Construct an incremental sequence which represent the + // indices to all files (excluding those in the initial corpus). + // RemainingFiles = range(NumFilesInFirstCorpus..Files.size()). + RemainingFiles.insert(i); + // Insert this file's unique features to all features. + for (const auto &F : Files[i].Features) + AllFeatures.insert(F % kFeatureSetSize); + } + + // Integrate files into Covered until set is complete. + while (NumCovered != AllFeatures.size()) { + // Index to file with largest number of unique features. + size_t MaxFeaturesIndex = NumFilesInFirstCorpus; + // Indices to remove from RemainingFiles. + std::set RemoveIndices; + // Running max unique feature count. + // Updated upon finding a file with more features. + size_t MaxNumFeatures = 0; + + // Iterate over all files not yet integrated into Covered, + // to find the file which has the largest number of + // features that are not already in Covered. + for (const auto &i : RemainingFiles) { + const auto &File = Files[i]; + size_t CurrentUnique = 0; + // Count number of features in this file + // which are not yet in Covered. + for (const auto &F : File.Features) + if (!Covered[F % kFeatureSetSize]) + ++CurrentUnique; + + if (CurrentUnique == 0) { + // All features in this file are already in Covered: skip next time. + RemoveIndices.insert(i); + } else if (CurrentUnique > MaxNumFeatures || + (CurrentUnique == MaxNumFeatures && + File.Size < Files[MaxFeaturesIndex].Size)) { + // Update the max features file based on unique features + // Break ties by selecting smaller files. + MaxNumFeatures = CurrentUnique; + MaxFeaturesIndex = i; + } + } + // Must be a valid index/ + assert(MaxFeaturesIndex < Files.size()); + // Remove any feature-less files found. + for (const auto &i : RemoveIndices) + RemainingFiles.erase(i); + if (MaxNumFeatures == 0) { + // Did not find a file that adds unique features. + // This means that we should have no remaining files. + assert(RemainingFiles.size() == 0); + assert(NumCovered == AllFeatures.size()); + break; + } + + // MaxFeaturesIndex must be an element of Remaining. + assert(RemainingFiles.find(MaxFeaturesIndex) != RemainingFiles.end()); + // Remove the file with the most features from Remaining. + RemainingFiles.erase(MaxFeaturesIndex); + const auto &MaxFeatureFile = Files[MaxFeaturesIndex]; + // Add the features of the max feature file to Covered. + for (const auto &F : MaxFeatureFile.Features) { + if (!Covered[F % kFeatureSetSize]) { + ++NumCovered; + Covered[F % kFeatureSetSize] = true; + NewFeatures->insert(F); + } + } + // Add the index to this file to the result. + NewFiles->push_back(MaxFeatureFile.Name); + // Update NewCov with the additional coverage + // that MaxFeatureFile provides. + for (const auto &C : MaxFeatureFile.Cov) + if (InitialCov.find(C) == InitialCov.end()) + NewCov->insert(C); + } + + return NewFeatures->size(); +} + +static size_t +WriteNewControlFile(const std::string &CFPath, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + const std::vector &KnownFiles) { + std::unordered_set FilesToSkip; + for (auto &SF: KnownFiles) + FilesToSkip.insert(SF.Name); + + std::vector FilesToUse; + auto MaybeUseFile = [=, &FilesToUse](std::string Name) { + if (FilesToSkip.find(Name) == FilesToSkip.end()) + FilesToUse.push_back(Name); + }; + for (auto &SF: OldCorpus) + MaybeUseFile(SF.File); + auto FilesToUseFromOldCorpus = FilesToUse.size(); + for (auto &SF: NewCorpus) + MaybeUseFile(SF.File); + + RemoveFile(CFPath); + std::ofstream ControlFile(CFPath); + ControlFile << FilesToUse.size() << "\n"; + ControlFile << FilesToUseFromOldCorpus << "\n"; + for (auto &FN: FilesToUse) + ControlFile << FN << "\n"; + + if (!ControlFile) { + Printf("MERGE-OUTER: failed to write to the control file: %s\n", + CFPath.c_str()); + exit(1); + } + + return FilesToUse.size(); +} + +// Outer process. Does not call the target code and thus should not fail. +void CrashResistantMerge(const std::vector &Args, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + std::vector *NewFiles, + const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, const std::string &CFPath, + bool V, /*Verbose*/ + bool IsSetCoverMerge) { + if (NewCorpus.empty() && OldCorpus.empty()) return; // Nothing to merge. + size_t NumAttempts = 0; + std::vector KnownFiles; + if (FileSize(CFPath)) { + VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n", + CFPath.c_str()); + Merger M; + std::ifstream IF(CFPath); + if (M.Parse(IF, /*ParseCoverage=*/true)) { + VPrintf(V, "MERGE-OUTER: control file ok, %zd files total," + " first not processed file %zd\n", + M.Files.size(), M.FirstNotProcessedFile); + if (!M.LastFailure.empty()) + VPrintf(V, "MERGE-OUTER: '%s' will be skipped as unlucky " + "(merge has stumbled on it the last time)\n", + M.LastFailure.c_str()); + if (M.FirstNotProcessedFile >= M.Files.size()) { + // Merge has already been completed with the given merge control file. + if (M.Files.size() == OldCorpus.size() + NewCorpus.size()) { + VPrintf( + V, + "MERGE-OUTER: nothing to do, merge has been completed before\n"); + exit(0); + } + + // Number of input files likely changed, start merge from scratch, but + // reuse coverage information from the given merge control file. + VPrintf( + V, + "MERGE-OUTER: starting merge from scratch, but reusing coverage " + "information from the given control file\n"); + KnownFiles = M.Files; + } else { + // There is a merge in progress, continue. + NumAttempts = M.Files.size() - M.FirstNotProcessedFile; + } + } else { + VPrintf(V, "MERGE-OUTER: bad control file, will overwrite it\n"); + } + } + + if (!NumAttempts) { + // The supplied control file is empty or bad, create a fresh one. + VPrintf(V, "MERGE-OUTER: " + "%zd files, %zd in the initial corpus, %zd processed earlier\n", + OldCorpus.size() + NewCorpus.size(), OldCorpus.size(), + KnownFiles.size()); + NumAttempts = WriteNewControlFile(CFPath, OldCorpus, NewCorpus, KnownFiles); + } + + // Execute the inner process until it passes. + // Every inner process should execute at least one input. + Command BaseCmd(Args); + BaseCmd.removeFlag("merge"); + BaseCmd.removeFlag("set_cover_merge"); + BaseCmd.removeFlag("fork"); + BaseCmd.removeFlag("collect_data_flow"); + for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { + Fuzzer::MaybeExitGracefully(); + VPrintf(V, "MERGE-OUTER: attempt %zd\n", Attempt); + Command Cmd(BaseCmd); + Cmd.addFlag("merge_control_file", CFPath); + // If we are going to use the set cover implementation for + // minimization add the merge_inner=2 internal flag. + Cmd.addFlag("merge_inner", IsSetCoverMerge ? "2" : "1"); + if (!V) { + Cmd.setOutputFile(getDevNull()); + Cmd.combineOutAndErr(); + } + auto ExitCode = ExecuteCommand(Cmd); + if (!ExitCode) { + VPrintf(V, "MERGE-OUTER: successful in %zd attempt(s)\n", Attempt); + break; + } + } + // Read the control file and do the merge. + Merger M; + std::ifstream IF(CFPath); + IF.seekg(0, IF.end); + VPrintf(V, "MERGE-OUTER: the control file has %zd bytes\n", + (size_t)IF.tellg()); + IF.seekg(0, IF.beg); + M.ParseOrExit(IF, true); + IF.close(); + VPrintf(V, + "MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n", + M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb()); + + M.Files.insert(M.Files.end(), KnownFiles.begin(), KnownFiles.end()); + if (IsSetCoverMerge) + M.SetCoverMerge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); + else + M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); + VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added; " + "%zd new coverage edges\n", + NewFiles->size(), NewFeatures->size(), NewCov->size()); +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMerge.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,93 @@ +//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Merging Corpora. +// +// The task: +// Take the existing corpus (possibly empty) and merge new inputs into +// it so that only inputs with new coverage ('features') are added. +// The process should tolerate the crashes, OOMs, leaks, etc. +// +// Algorithm: +// The outer process collects the set of files and writes their names +// into a temporary "control" file, then repeatedly launches the inner +// process until all inputs are processed. +// The outer process does not actually execute the target code. +// +// The inner process reads the control file and sees a) list of all the inputs +// and b) the last processed input. Then it starts processing the inputs one +// by one. Before processing every input it writes one line to control file: +// STARTED INPUT_ID INPUT_SIZE +// After processing an input it writes the following lines: +// FT INPUT_ID Feature1 Feature2 Feature3 ... +// COV INPUT_ID Coverage1 Coverage2 Coverage3 ... +// If a crash happens while processing an input the last line in the control +// file will be "STARTED INPUT_ID" and so the next process will know +// where to resume. +// +// Once all inputs are processed by the inner process(es) the outer process +// reads the control files and does the merge based entirely on the contents +// of control file. +// It uses a single pass greedy algorithm choosing first the smallest inputs +// within the same size the inputs that have more new features. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_MERGE_H +#define LLVM_FUZZER_MERGE_H + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" + +#include +#include +#include +#include + +namespace fuzzer { + +struct MergeFileInfo { + std::string Name; + size_t Size = 0; + std::vector Features, Cov; +}; + +struct Merger { + std::vector Files; + size_t NumFilesInFirstCorpus = 0; + size_t FirstNotProcessedFile = 0; + std::string LastFailure; + + bool Parse(std::istream &IS, bool ParseCoverage); + bool Parse(const std::string &Str, bool ParseCoverage); + void ParseOrExit(std::istream &IS, bool ParseCoverage); + size_t Merge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, std::set *NewCov, + std::vector *NewFiles); + size_t SetCoverMerge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles); + size_t ApproximateMemoryConsumption() const; + std::set AllFeatures() const; +}; + +void CrashResistantMerge(const std::vector &Args, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + std::vector *NewFiles, + const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, const std::string &CFPath, + bool Verbose, bool IsSetCoverMerge); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_MERGE_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,596 @@ +//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Mutate a test input. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include "FuzzerMutate.h" +#include "FuzzerOptions.h" +#include "FuzzerTracePC.h" + +namespace fuzzer { + +const size_t Dictionary::kMaxDictSize; +static const size_t kMaxMutationsToPrint = 10; + +static void PrintASCII(const Word &W, const char *PrintAfter) { + PrintASCII(W.data(), W.size(), PrintAfter); +} + +MutationDispatcher::MutationDispatcher(Random &Rand, + const FuzzingOptions &Options) + : Rand(Rand), Options(Options) { + DefaultMutators.insert( + DefaultMutators.begin(), + { + {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"}, + {&MutationDispatcher::Mutate_InsertByte, "InsertByte"}, + {&MutationDispatcher::Mutate_InsertRepeatedBytes, + "InsertRepeatedBytes"}, + {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"}, + {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, + {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, + {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, + {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"}, + {&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, + {&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, + {&MutationDispatcher::Mutate_AddWordFromManualDictionary, + "ManualDict"}, + {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary, + "PersAutoDict"}, + }); + if(Options.UseCmp) + DefaultMutators.push_back( + {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"}); + + if (EF->LLVMFuzzerCustomMutator) + Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"}); + else + Mutators = DefaultMutators; + + if (EF->LLVMFuzzerCustomCrossOver) + Mutators.push_back( + {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"}); +} + +static char RandCh(Random &Rand) { + if (Rand.RandBool()) + return static_cast(Rand(256)); + const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; + return Special[Rand(sizeof(Special) - 1)]; +} + +size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (EF->__msan_unpoison) + EF->__msan_unpoison(Data, Size); + if (EF->__msan_unpoison_param) + EF->__msan_unpoison_param(4); + return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, + Rand.Rand()); +} + +size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size == 0) + return 0; + if (!CrossOverWith) return 0; + const Unit &Other = *CrossOverWith; + if (Other.empty()) + return 0; + CustomCrossOverInPlaceHere.resize(MaxSize); + auto &U = CustomCrossOverInPlaceHere; + + if (EF->__msan_unpoison) { + EF->__msan_unpoison(Data, Size); + EF->__msan_unpoison(Other.data(), Other.size()); + EF->__msan_unpoison(U.data(), U.size()); + } + if (EF->__msan_unpoison_param) + EF->__msan_unpoison_param(7); + size_t NewSize = EF->LLVMFuzzerCustomCrossOver( + Data, Size, Other.data(), Other.size(), U.data(), U.size(), + Rand.Rand()); + + if (!NewSize) + return 0; + assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit"); + memcpy(Data, U.data(), NewSize); + return NewSize; +} + +size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize || Size == 0) return 0; + size_t ShuffleAmount = + Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size. + size_t ShuffleStart = Rand(Size - ShuffleAmount); + assert(ShuffleStart + ShuffleAmount <= Size); + std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size <= 1) return 0; + size_t N = Rand(Size / 2) + 1; + assert(N < Size); + size_t Idx = Rand(Size - N + 1); + // Erase Data[Idx:Idx+N]. + memmove(Data + Idx, Data + Idx + N, Size - Idx - N); + // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx); + return Size - N; +} + +size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size >= MaxSize) return 0; + size_t Idx = Rand(Size + 1); + // Insert new value at Data[Idx]. + memmove(Data + Idx + 1, Data + Idx, Size - Idx); + Data[Idx] = RandCh(Rand); + return Size + 1; +} + +size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data, + size_t Size, + size_t MaxSize) { + const size_t kMinBytesToInsert = 3; + if (Size + kMinBytesToInsert >= MaxSize) return 0; + size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128); + size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert; + assert(Size + N <= MaxSize && N); + size_t Idx = Rand(Size + 1); + // Insert new values at Data[Idx]. + memmove(Data + Idx + N, Data + Idx, Size - Idx); + // Give preference to 0x00 and 0xff. + uint8_t Byte = static_cast( + Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255)); + for (size_t i = 0; i < N; i++) + Data[Idx + i] = Byte; + return Size + N; +} + +size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t Idx = Rand(Size); + Data[Idx] = RandCh(Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t Idx = Rand(Size); + Data[Idx] ^= 1 << Rand(8); + return Size; +} + +size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, + size_t Size, + size_t MaxSize) { + return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize); +} + +size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size, + size_t MaxSize, + DictionaryEntry &DE) { + const Word &W = DE.GetW(); + bool UsePositionHint = DE.HasPositionHint() && + DE.GetPositionHint() + W.size() < Size && + Rand.RandBool(); + if (Rand.RandBool()) { // Insert W. + if (Size + W.size() > MaxSize) return 0; + size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1); + memmove(Data + Idx + W.size(), Data + Idx, Size - Idx); + memcpy(Data + Idx, W.data(), W.size()); + Size += W.size(); + } else { // Overwrite some bytes with W. + if (W.size() > Size) return 0; + size_t Idx = + UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size()); + memcpy(Data + Idx, W.data(), W.size()); + } + return Size; +} + +// Somewhere in the past we have observed a comparison instructions +// with arguments Arg1 Arg2. This function tries to guess a dictionary +// entry that will satisfy that comparison. +// It first tries to find one of the arguments (possibly swapped) in the +// input and if it succeeds it creates a DE with a position hint. +// Otherwise it creates a DE with one of the arguments w/o a position hint. +DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( + const void *Arg1, const void *Arg2, + const void *Arg1Mutation, const void *Arg2Mutation, + size_t ArgSize, const uint8_t *Data, + size_t Size) { + bool HandleFirst = Rand.RandBool(); + const void *ExistingBytes, *DesiredBytes; + Word W; + const uint8_t *End = Data + Size; + for (int Arg = 0; Arg < 2; Arg++) { + ExistingBytes = HandleFirst ? Arg1 : Arg2; + DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation; + HandleFirst = !HandleFirst; + W.Set(reinterpret_cast(DesiredBytes), ArgSize); + const size_t kMaxNumPositions = 8; + size_t Positions[kMaxNumPositions]; + size_t NumPositions = 0; + for (const uint8_t *Cur = Data; + Cur < End && NumPositions < kMaxNumPositions; Cur++) { + Cur = + (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize); + if (!Cur) break; + Positions[NumPositions++] = Cur - Data; + } + if (!NumPositions) continue; + return DictionaryEntry(W, Positions[Rand(NumPositions)]); + } + DictionaryEntry DE(W); + return DE; +} + + +template +DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( + T Arg1, T Arg2, const uint8_t *Data, size_t Size) { + if (Rand.RandBool()) Arg1 = Bswap(Arg1); + if (Rand.RandBool()) Arg2 = Bswap(Arg2); + T Arg1Mutation = static_cast(Arg1 + Rand(-1, 1)); + T Arg2Mutation = static_cast(Arg2 + Rand(-1, 1)); + return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation, + sizeof(Arg1), Data, Size); +} + +DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( + const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) { + return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(), + Arg2.data(), Arg1.size(), Data, Size); +} + +size_t MutationDispatcher::Mutate_AddWordFromTORC( + uint8_t *Data, size_t Size, size_t MaxSize) { + Word W; + DictionaryEntry DE; + switch (Rand(4)) { + case 0: { + auto X = TPC.TORC8.Get(Rand.Rand()); + DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); + } break; + case 1: { + auto X = TPC.TORC4.Get(Rand.Rand()); + if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool()) + DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size); + else + DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); + } break; + case 2: { + auto X = TPC.TORCW.Get(Rand.Rand()); + DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); + } break; + case 3: if (Options.UseMemmem) { + auto X = TPC.MMT.Get(Rand.Rand()); + DE = DictionaryEntry(X); + } break; + default: + assert(0); + } + if (!DE.GetW().size()) return 0; + Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); + if (!Size) return 0; + DictionaryEntry &DERef = + CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ % + kCmpDictionaryEntriesDequeSize]; + DERef = DE; + CurrentDictionaryEntrySequence.push_back(&DERef); + return Size; +} + +size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary( + uint8_t *Data, size_t Size, size_t MaxSize) { + return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize); +} + +size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data, + size_t Size, size_t MaxSize) { + if (Size > MaxSize) return 0; + if (D.empty()) return 0; + DictionaryEntry &DE = D[Rand(D.size())]; + Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); + if (!Size) return 0; + DE.IncUseCount(); + CurrentDictionaryEntrySequence.push_back(&DE); + return Size; +} + +// Overwrites part of To[0,ToSize) with a part of From[0,FromSize). +// Returns ToSize. +size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize, + uint8_t *To, size_t ToSize) { + // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize). + size_t ToBeg = Rand(ToSize); + size_t CopySize = Rand(ToSize - ToBeg) + 1; + assert(ToBeg + CopySize <= ToSize); + CopySize = std::min(CopySize, FromSize); + size_t FromBeg = Rand(FromSize - CopySize + 1); + assert(FromBeg + CopySize <= FromSize); + memmove(To + ToBeg, From + FromBeg, CopySize); + return ToSize; +} + +// Inserts part of From[0,ToSize) into To. +// Returns new size of To on success or 0 on failure. +size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize, + uint8_t *To, size_t ToSize, + size_t MaxToSize) { + if (ToSize >= MaxToSize) return 0; + size_t AvailableSpace = MaxToSize - ToSize; + size_t MaxCopySize = std::min(AvailableSpace, FromSize); + size_t CopySize = Rand(MaxCopySize) + 1; + size_t FromBeg = Rand(FromSize - CopySize + 1); + assert(FromBeg + CopySize <= FromSize); + size_t ToInsertPos = Rand(ToSize + 1); + assert(ToInsertPos + CopySize <= MaxToSize); + size_t TailSize = ToSize - ToInsertPos; + if (To == From) { + MutateInPlaceHere.resize(MaxToSize); + memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize); + memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); + memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize); + } else { + memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); + memmove(To + ToInsertPos, From + FromBeg, CopySize); + } + return ToSize + CopySize; +} + +size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize || Size == 0) return 0; + // If Size == MaxSize, `InsertPartOf(...)` will + // fail so there's no point using it in this case. + if (Size == MaxSize || Rand.RandBool()) + return CopyPartOf(Data, Size, Data, Size); + else + return InsertPartOf(Data, Size, Data, Size, MaxSize); +} + +size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t B = Rand(Size); + while (B < Size && !isdigit(Data[B])) B++; + if (B == Size) return 0; + size_t E = B; + while (E < Size && isdigit(Data[E])) E++; + assert(B < E); + // now we have digits in [B, E). + // strtol and friends don't accept non-zero-teminated data, parse it manually. + uint64_t Val = Data[B] - '0'; + for (size_t i = B + 1; i < E; i++) + Val = Val * 10 + Data[i] - '0'; + + // Mutate the integer value. + switch(Rand(5)) { + case 0: Val++; break; + case 1: Val--; break; + case 2: Val /= 2; break; + case 3: Val *= 2; break; + case 4: Val = Rand(Val * Val); break; + default: assert(0); + } + // Just replace the bytes with the new ones, don't bother moving bytes. + for (size_t i = B; i < E; i++) { + size_t Idx = E + B - i - 1; + assert(Idx >= B && Idx < E); + Data[Idx] = (Val % 10) + '0'; + Val /= 10; + } + return Size; +} + +template +size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) { + if (Size < sizeof(T)) return 0; + size_t Off = Rand(Size - sizeof(T) + 1); + assert(Off + sizeof(T) <= Size); + T Val; + if (Off < 64 && !Rand(4)) { + Val = static_cast(Size); + if (Rand.RandBool()) + Val = Bswap(Val); + } else { + memcpy(&Val, Data + Off, sizeof(Val)); + T Add = static_cast(Rand(21)); + Add -= 10; + if (Rand.RandBool()) + Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. + else + Val = Val + Add; // Add assuming current endiannes. + if (Add == 0 || Rand.RandBool()) // Maybe negate. + Val = -Val; + } + memcpy(Data + Off, &Val, sizeof(Val)); + return Size; +} + +size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data, + size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + switch (Rand(4)) { + case 3: return ChangeBinaryInteger(Data, Size, Rand); + case 2: return ChangeBinaryInteger(Data, Size, Rand); + case 1: return ChangeBinaryInteger(Data, Size, Rand); + case 0: return ChangeBinaryInteger(Data, Size, Rand); + default: assert(0); + } + return 0; +} + +size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + if (Size == 0) return 0; + if (!CrossOverWith) return 0; + const Unit &O = *CrossOverWith; + if (O.empty()) return 0; + size_t NewSize = 0; + switch(Rand(3)) { + case 0: + MutateInPlaceHere.resize(MaxSize); + NewSize = CrossOver(Data, Size, O.data(), O.size(), + MutateInPlaceHere.data(), MaxSize); + memcpy(Data, MutateInPlaceHere.data(), NewSize); + break; + case 1: + NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize); + if (!NewSize) + NewSize = CopyPartOf(O.data(), O.size(), Data, Size); + break; + case 2: + NewSize = CopyPartOf(O.data(), O.size(), Data, Size); + break; + default: assert(0); + } + assert(NewSize > 0 && "CrossOver returned empty unit"); + assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); + return NewSize; +} + +void MutationDispatcher::StartMutationSequence() { + CurrentMutatorSequence.clear(); + CurrentDictionaryEntrySequence.clear(); +} + +// Copy successful dictionary entries to PersistentAutoDictionary. +void MutationDispatcher::RecordSuccessfulMutationSequence() { + for (auto DE : CurrentDictionaryEntrySequence) { + // PersistentAutoDictionary.AddWithSuccessCountOne(DE); + DE->IncSuccessCount(); + assert(DE->GetW().size()); + // Linear search is fine here as this happens seldom. + if (!PersistentAutoDictionary.ContainsWord(DE->GetW())) + PersistentAutoDictionary.push_back(*DE); + } +} + +void MutationDispatcher::PrintRecommendedDictionary() { + std::vector V; + for (auto &DE : PersistentAutoDictionary) + if (!ManualDictionary.ContainsWord(DE.GetW())) + V.push_back(DE); + if (V.empty()) return; + Printf("###### Recommended dictionary. ######\n"); + for (auto &DE: V) { + assert(DE.GetW().size()); + Printf("\""); + PrintASCII(DE.GetW(), "\""); + Printf(" # Uses: %zd\n", DE.GetUseCount()); + } + Printf("###### End of recommended dictionary. ######\n"); +} + +void MutationDispatcher::PrintMutationSequence(bool Verbose) { + Printf("MS: %zd ", CurrentMutatorSequence.size()); + size_t EntriesToPrint = + Verbose ? CurrentMutatorSequence.size() + : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size()); + for (size_t i = 0; i < EntriesToPrint; i++) + Printf("%s-", CurrentMutatorSequence[i].Name); + if (!CurrentDictionaryEntrySequence.empty()) { + Printf(" DE: "); + EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size() + : std::min(kMaxMutationsToPrint, + CurrentDictionaryEntrySequence.size()); + for (size_t i = 0; i < EntriesToPrint; i++) { + Printf("\""); + PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-"); + } + } +} + +std::string MutationDispatcher::MutationSequence() { + std::string MS; + for (const auto &M : CurrentMutatorSequence) { + MS += M.Name; + MS += "-"; + } + return MS; +} + +size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { + return MutateImpl(Data, Size, MaxSize, Mutators); +} + +size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, + size_t MaxSize) { + return MutateImpl(Data, Size, MaxSize, DefaultMutators); +} + +// Mutates Data in place, returns new size. +size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, + size_t MaxSize, + std::vector &Mutators) { + assert(MaxSize > 0); + // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize), + // in which case they will return 0. + // Try several times before returning un-mutated data. + for (int Iter = 0; Iter < 100; Iter++) { + auto M = Mutators[Rand(Mutators.size())]; + size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); + if (NewSize && NewSize <= MaxSize) { + if (Options.OnlyASCII) + ToASCII(Data, NewSize); + CurrentMutatorSequence.push_back(M); + return NewSize; + } + } + *Data = ' '; + return 1; // Fallback, should not happen frequently. +} + +// Mask represents the set of Data bytes that are worth mutating. +size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size, + size_t MaxSize, + const std::vector &Mask) { + size_t MaskedSize = std::min(Size, Mask.size()); + // * Copy the worthy bytes into a temporary array T + // * Mutate T + // * Copy T back. + // This is totally unoptimized. + auto &T = MutateWithMaskTemp; + if (T.size() < Size) + T.resize(Size); + size_t OneBits = 0; + for (size_t I = 0; I < MaskedSize; I++) + if (Mask[I]) + T[OneBits++] = Data[I]; + + if (!OneBits) return 0; + assert(!T.empty()); + size_t NewSize = Mutate(T.data(), OneBits, OneBits); + assert(NewSize <= OneBits); + (void)NewSize; + // Even if NewSize < OneBits we still use all OneBits bytes. + for (size_t I = 0, J = 0; I < MaskedSize; I++) + if (Mask[I]) + Data[I] = T[J++]; + return Size; +} + +void MutationDispatcher::AddWordToManualDictionary(const Word &W) { + ManualDictionary.push_back( + {W, std::numeric_limits::max()}); +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerMutate.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,156 @@ +//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::MutationDispatcher +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_MUTATE_H +#define LLVM_FUZZER_MUTATE_H + +#include "FuzzerDefs.h" +#include "FuzzerDictionary.h" +#include "FuzzerOptions.h" +#include "FuzzerRandom.h" + +namespace fuzzer { + +class MutationDispatcher { +public: + MutationDispatcher(Random &Rand, const FuzzingOptions &Options); + ~MutationDispatcher() {} + /// Indicate that we are about to start a new sequence of mutations. + void StartMutationSequence(); + /// Print the current sequence of mutations. Only prints the full sequence + /// when Verbose is true. + void PrintMutationSequence(bool Verbose = true); + /// Return the current sequence of mutations. + std::string MutationSequence(); + /// Indicate that the current sequence of mutations was successful. + void RecordSuccessfulMutationSequence(); + /// Mutates data by invoking user-provided mutator. + size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by invoking user-provided crossover. + size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by shuffling bytes. + size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by erasing bytes. + size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by inserting a byte. + size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by inserting several repeated bytes. + size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by changing one byte. + size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by changing one bit. + size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by copying/inserting a part of data into a different place. + size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Mutates data by adding a word from the manual dictionary. + size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, + size_t MaxSize); + + /// Mutates data by adding a word from the TORC. + size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Mutates data by adding a word from the persistent automatic dictionary. + size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, + size_t MaxSize); + + /// Tries to find an ASCII integer in Data, changes it to another ASCII int. + size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); + /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways. + size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize); + + /// CrossOver Data with CrossOverWith. + size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Applies one of the configured mutations. + /// Returns the new size of data which could be up to MaxSize. + size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Applies one of the configured mutations to the bytes of Data + /// that have '1' in Mask. + /// Mask.size() should be >= Size. + size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, + const std::vector &Mask); + + /// Applies one of the default mutations. Provided as a service + /// to mutation authors. + size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Creates a cross-over of two pieces of Data, returns its size. + size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, + size_t Size2, uint8_t *Out, size_t MaxOutSize); + + void AddWordToManualDictionary(const Word &W); + + void PrintRecommendedDictionary(); + + void SetCrossOverWith(const Unit *U) { CrossOverWith = U; } + + Random &GetRand() { return Rand; } + + private: + struct Mutator { + size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); + const char *Name; + }; + + size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, + size_t MaxSize); + size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, + std::vector &Mutators); + + size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, + size_t ToSize, size_t MaxToSize); + size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, + size_t ToSize); + size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, + DictionaryEntry &DE); + + template + DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, + const uint8_t *Data, size_t Size); + DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2, + const uint8_t *Data, size_t Size); + DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2, + const void *Arg1Mutation, + const void *Arg2Mutation, + size_t ArgSize, + const uint8_t *Data, size_t Size); + + Random &Rand; + const FuzzingOptions Options; + + // Dictionary provided by the user via -dict=DICT_FILE. + Dictionary ManualDictionary; + // Persistent dictionary modified by the fuzzer, consists of + // entries that led to successful discoveries in the past mutations. + Dictionary PersistentAutoDictionary; + + std::vector CurrentDictionaryEntrySequence; + + static const size_t kCmpDictionaryEntriesDequeSize = 16; + DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; + size_t CmpDictionaryEntriesDequeIdx = 0; + + const Unit *CrossOverWith = nullptr; + std::vector MutateInPlaceHere; + std::vector MutateWithMaskTemp; + // CustomCrossOver needs its own buffer as a custom implementation may call + // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere. + std::vector CustomCrossOverInPlaceHere; + + std::vector Mutators; + std::vector DefaultMutators; + std::vector CurrentMutatorSequence; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_MUTATE_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerOptions.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerOptions.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerOptions.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerOptions.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,93 @@ +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::FuzzingOptions +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_OPTIONS_H +#define LLVM_FUZZER_OPTIONS_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +struct FuzzingOptions { + int Verbosity = 1; + size_t MaxLen = 0; + size_t LenControl = 1000; + bool KeepSeed = false; + int UnitTimeoutSec = 300; + int TimeoutExitCode = 70; + int OOMExitCode = 71; + int InterruptExitCode = 72; + int ErrorExitCode = 77; + bool IgnoreTimeouts = true; + bool IgnoreOOMs = true; + bool IgnoreCrashes = false; + int MaxTotalTimeSec = 0; + int RssLimitMb = 0; + int MallocLimitMb = 0; + bool DoCrossOver = true; + bool CrossOverUniformDist = false; + int MutateDepth = 5; + bool ReduceDepth = false; + bool UseCounters = false; + bool UseMemmem = true; + bool UseCmp = false; + int UseValueProfile = false; + bool Shrink = false; + bool ReduceInputs = false; + int ReloadIntervalSec = 1; + bool ShuffleAtStartUp = true; + bool PreferSmall = true; + size_t MaxNumberOfRuns = -1L; + int ReportSlowUnits = 10; + bool OnlyASCII = false; + bool Entropic = true; + bool ForkCorpusGroups = false; + size_t EntropicFeatureFrequencyThreshold = 0xFF; + size_t EntropicNumberOfRarestFeatures = 100; + bool EntropicScalePerExecTime = false; + std::string OutputCorpus; + std::string ArtifactPrefix = "./"; + std::string ExactArtifactPath; + std::string ExitOnSrcPos; + std::string ExitOnItem; + std::string FocusFunction; + std::string DataFlowTrace; + std::string CollectDataFlow; + std::string FeaturesDir; + std::string MutationGraphFile; + std::string StopFile; + bool SaveArtifacts = true; + bool PrintNEW = true; // Print a status line when new units are found; + bool PrintNewCovPcs = false; + int PrintNewCovFuncs = 0; + bool PrintFinalStats = false; + bool PrintCorpusStats = false; + bool PrintCoverage = false; + bool PrintFullCoverage = false; + bool DumpCoverage = false; + bool DetectLeaks = true; + int PurgeAllocatorIntervalSec = 1; + int TraceMalloc = 0; + bool HandleAbrt = false; + bool HandleAlrm = false; + bool HandleBus = false; + bool HandleFpe = false; + bool HandleIll = false; + bool HandleInt = false; + bool HandleSegv = false; + bool HandleTerm = false; + bool HandleXfsz = false; + bool HandleUsr1 = false; + bool HandleUsr2 = false; + bool HandleWinExcept = false; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_OPTIONS_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerPlatform.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerPlatform.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerPlatform.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerPlatform.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +//===-- FuzzerPlatform.h --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Common platform macros. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_PLATFORM_H +#define LLVM_FUZZER_PLATFORM_H + +// Platform detection. +#ifdef __linux__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif __APPLE__ +#define LIBFUZZER_APPLE 1 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif __NetBSD__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 1 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif __FreeBSD__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 1 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif _WIN32 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 1 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif __Fuchsia__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 1 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 0 +#elif __EMSCRIPTEN__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_FUCHSIA 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#define LIBFUZZER_WINDOWS 0 +#define LIBFUZZER_EMSCRIPTEN 1 +#else +#error "Support for your platform has not been implemented" +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +// MSVC compiler is being used. +#define LIBFUZZER_MSVC 1 +#else +#define LIBFUZZER_MSVC 0 +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#define LIBFUZZER_POSIX \ + (LIBFUZZER_APPLE || LIBFUZZER_LINUX || LIBFUZZER_NETBSD || \ + LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN) + +#ifdef __x86_64 +#if __has_attribute(target) +#define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) +#else +#define ATTRIBUTE_TARGET_POPCNT +#endif +#else +#define ATTRIBUTE_TARGET_POPCNT +#endif + +#ifdef __clang__ // avoid gcc warning. +#if __has_attribute(no_sanitize) +#define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +#else +#define ATTRIBUTE_NO_SANITIZE_MEMORY +#endif +#define ALWAYS_INLINE __attribute__((always_inline)) +#else +#define ATTRIBUTE_NO_SANITIZE_MEMORY +#define ALWAYS_INLINE +#endif // __clang__ + +#if LIBFUZZER_WINDOWS +#define ATTRIBUTE_NO_SANITIZE_ADDRESS +#else +#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#endif + +#if LIBFUZZER_WINDOWS +#define ATTRIBUTE_ALIGNED(X) __declspec(align(X)) +#define ATTRIBUTE_INTERFACE __declspec(dllexport) +// This is used for __sancov_lowest_stack which is needed for +// -fsanitize-coverage=stack-depth. That feature is not yet available on +// Windows, so make the symbol static to avoid linking errors. +#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC static +#define ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define ATTRIBUTE_ALIGNED(X) __attribute__((aligned(X))) +#define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) +#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ + ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local + +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) +#endif + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_ADDRESS +#elif __has_feature(memory_sanitizer) +#define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_MEMORY +#else +#define ATTRIBUTE_NO_SANITIZE_ALL +#endif +#else +#define ATTRIBUTE_NO_SANITIZE_ALL +#endif + +#endif // LLVM_FUZZER_PLATFORM_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerRandom.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerRandom.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerRandom.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerRandom.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::Random +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_RANDOM_H +#define LLVM_FUZZER_RANDOM_H + +#include + +namespace fuzzer { +class Random : public std::minstd_rand { + public: + Random(unsigned int seed) : std::minstd_rand(seed) {} + result_type operator()() { return this->std::minstd_rand::operator()(); } + template + typename std::enable_if::value, T>::type Rand() { + return static_cast(this->operator()()); + } + size_t RandBool() { return this->operator()() % 2; } + size_t SkewTowardsLast(size_t n) { + size_t T = this->operator()(n * n); + size_t Res = static_cast(sqrt(T)); + return Res; + } + template + typename std::enable_if::value, T>::type operator()(T n) { + return n ? Rand() % n : 0; + } + template + typename std::enable_if::value, T>::type + operator()(T From, T To) { + assert(From < To); + auto RangeSize = static_cast(To) - + static_cast(From) + 1; + return static_cast(this->operator()(RangeSize) + From); + } +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_RANDOM_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This code is taken from public domain +// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) +// and modified by adding anonymous namespace, adding an interface +// function fuzzer::ComputeSHA1() and removing unnecessary code. +// +// lib/Fuzzer can not use SHA1 implementation from openssl because +// openssl may not be available and because we may be fuzzing openssl itself. +// For the same reason we do not want to depend on SHA1 from LLVM tree. +//===----------------------------------------------------------------------===// + +#include "FuzzerSHA1.h" +#include "FuzzerDefs.h" +#include "FuzzerPlatform.h" + +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#include +#include +#include +#include + +namespace { // Added for LibFuzzer + +#ifdef __BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +// Windows is always little endian and MSVC doesn't have +#elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS +/* override */ +#elif defined __BYTE_ORDER +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +# endif +#else // ! defined __LITTLE_ENDIAN__ +# include // machine/endian.h +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +# endif +#endif + + +/* header */ + +#define HASH_LENGTH 20 +#define BLOCK_LENGTH 64 + +typedef struct sha1nfo { + uint32_t buffer[BLOCK_LENGTH/4]; + uint32_t state[HASH_LENGTH/4]; + uint32_t byteCount; + uint8_t bufferOffset; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[HASH_LENGTH]; +} sha1nfo; + +/* public API - prototypes - TODO: doxygen*/ + +/** + */ +void sha1_init(sha1nfo *s); +/** + */ +void sha1_writebyte(sha1nfo *s, uint8_t data); +/** + */ +void sha1_write(sha1nfo *s, const char *data, size_t len); +/** + */ +uint8_t* sha1_result(sha1nfo *s); + + +/* code */ +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +void sha1_init(sha1nfo *s) { + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->byteCount = 0; + s->bufferOffset = 0; +} + +uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + return ((number << bits) | (number >> (32-bits))); +} + +void sha1_hashBlock(sha1nfo *s) { + uint8_t i; + uint32_t a,b,c,d,e,t; + + a=s->state[0]; + b=s->state[1]; + c=s->state[2]; + d=s->state[3]; + e=s->state[4]; + for (i=0; i<80; i++) { + if (i>=16) { + t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; + s->buffer[i&15] = sha1_rol32(t,1); + } + if (i<20) { + t = (d ^ (b & (c ^ d))) + SHA1_K0; + } else if (i<40) { + t = (b ^ c ^ d) + SHA1_K20; + } else if (i<60) { + t = ((b & c) | (d & (b | c))) + SHA1_K40; + } else { + t = (b ^ c ^ d) + SHA1_K60; + } + t+=sha1_rol32(a,5) + e + s->buffer[i&15]; + e=d; + d=c; + c=sha1_rol32(b,30); + b=a; + a=t; + } + s->state[0] += a; + s->state[1] += b; + s->state[2] += c; + s->state[3] += d; + s->state[4] += e; +} + +// Adds the least significant byte of |data|. +void sha1_addUncounted(sha1nfo *s, uint32_t data) { + uint8_t *const b = (uint8_t *)s->buffer; +#ifdef SHA_BIG_ENDIAN + b[s->bufferOffset] = static_cast(data); +#else + b[s->bufferOffset ^ 3] = static_cast(data); +#endif + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + sha1_hashBlock(s); + s->bufferOffset = 0; + } +} + +void sha1_writebyte(sha1nfo *s, uint8_t data) { + ++s->byteCount; + sha1_addUncounted(s, data); +} + +void sha1_write(sha1nfo *s, const char *data, size_t len) { + for (;len--;) sha1_writebyte(s, (uint8_t) *data++); +} + +void sha1_pad(sha1nfo *s) { + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); +} + +uint8_t* sha1_result(sha1nfo *s) { + // Pad to complete the last block + sha1_pad(s); + +#ifndef SHA_BIG_ENDIAN + // Swap byte order back + int i; + for (i=0; i<5; i++) { + s->state[i]= + (((s->state[i])<<24)& 0xff000000) + | (((s->state[i])<<8) & 0x00ff0000) + | (((s->state[i])>>8) & 0x0000ff00) + | (((s->state[i])>>24)& 0x000000ff); + } +#endif + + // Return pointer to hash (20 characters) + return (uint8_t*) s->state; +} + +} // namespace; Added for LibFuzzer + +namespace fuzzer { + +// The rest is added for LibFuzzer +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { + sha1nfo s; + sha1_init(&s); + sha1_write(&s, (const char*)Data, Len); + memcpy(Out, sha1_result(&s), HASH_LENGTH); +} + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { + std::stringstream SS; + for (int i = 0; i < kSHA1NumBytes; i++) + SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; + return SS.str(); +} + +std::string Hash(const Unit &U) { + uint8_t Hash[kSHA1NumBytes]; + ComputeSHA1(U.data(), U.size(), Hash); + return Sha1ToString(Hash); +} + +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerSHA1.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// SHA1 utils. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_SHA1_H +#define LLVM_FUZZER_SHA1_H + +#include "FuzzerDefs.h" +#include +#include + +namespace fuzzer { + +// Private copy of SHA1 implementation. +static const int kSHA1NumBytes = 20; + +// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); + +std::string Hash(const Unit &U); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_SHA1_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,685 @@ +//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Trace PCs. +// This module implements __sanitizer_cov_trace_pc_guard[_init], +// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation. +// +//===----------------------------------------------------------------------===// + +#include "FuzzerTracePC.h" +#include "FuzzerBuiltins.h" +#include "FuzzerBuiltinsMsvc.h" +#include "FuzzerCorpus.h" +#include "FuzzerDefs.h" +#include "FuzzerDictionary.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include "FuzzerPlatform.h" +#include "FuzzerUtil.h" +#include "FuzzerValueBitMap.h" +#include + +// Used by -fsanitize-coverage=stack-depth to track stack depth +ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack; + +namespace fuzzer { + +TracePC TPC; + +size_t TracePC::GetTotalPCCoverage() { + return ObservedPCs.size(); +} + + +void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { + if (Start == Stop) return; + if (NumModules && + Modules[NumModules - 1].Start() == Start) + return; + assert(NumModules < + sizeof(Modules) / sizeof(Modules[0])); + auto &M = Modules[NumModules++]; + uint8_t *AlignedStart = RoundUpByPage(Start); + uint8_t *AlignedStop = RoundDownByPage(Stop); + size_t NumFullPages = AlignedStop > AlignedStart ? + (AlignedStop - AlignedStart) / PageSize() : 0; + bool NeedFirst = Start < AlignedStart || !NumFullPages; + bool NeedLast = Stop > AlignedStop && AlignedStop >= AlignedStart; + M.NumRegions = NumFullPages + NeedFirst + NeedLast;; + assert(M.NumRegions > 0); + M.Regions = new Module::Region[M.NumRegions]; + assert(M.Regions); + size_t R = 0; + if (NeedFirst) + M.Regions[R++] = {Start, std::min(Stop, AlignedStart), true, false}; + for (uint8_t *P = AlignedStart; P < AlignedStop; P += PageSize()) + M.Regions[R++] = {P, P + PageSize(), true, true}; + if (NeedLast) + M.Regions[R++] = {AlignedStop, Stop, true, false}; + assert(R == M.NumRegions); + assert(M.Size() == (size_t)(Stop - Start)); + assert(M.Stop() == Stop); + assert(M.Start() == Start); + NumInline8bitCounters += M.Size(); +} + +void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) { + const PCTableEntry *B = reinterpret_cast(Start); + const PCTableEntry *E = reinterpret_cast(Stop); + if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return; + assert(NumPCTables < sizeof(ModulePCTable) / sizeof(ModulePCTable[0])); + ModulePCTable[NumPCTables++] = {B, E}; + NumPCsInPCTables += E - B; +} + +void TracePC::PrintModuleInfo() { + if (NumModules) { + Printf("INFO: Loaded %zd modules (%zd inline 8-bit counters): ", + NumModules, NumInline8bitCounters); + for (size_t i = 0; i < NumModules; i++) + Printf("%zd [%p, %p), ", Modules[i].Size(), Modules[i].Start(), + Modules[i].Stop()); + Printf("\n"); + } + if (NumPCTables) { + Printf("INFO: Loaded %zd PC tables (%zd PCs): ", NumPCTables, + NumPCsInPCTables); + for (size_t i = 0; i < NumPCTables; i++) { + Printf("%zd [%p,%p), ", ModulePCTable[i].Stop - ModulePCTable[i].Start, + ModulePCTable[i].Start, ModulePCTable[i].Stop); + } + Printf("\n"); + + if (NumInline8bitCounters && NumInline8bitCounters != NumPCsInPCTables) { + Printf("ERROR: The size of coverage PC tables does not match the\n" + "number of instrumented PCs. This might be a compiler bug,\n" + "please contact the libFuzzer developers.\n" + "Also check https://bugs.llvm.org/show_bug.cgi?id=34636\n" + "for possible workarounds (tl;dr: don't use the old GNU ld)\n"); + _Exit(1); + } + } + if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin()) + Printf("INFO: %zd Extra Counters\n", NumExtraCounters); + + size_t MaxFeatures = CollectFeatures([](uint32_t) {}); + if (MaxFeatures > std::numeric_limits::max()) + Printf("WARNING: The coverage PC tables may produce up to %zu features.\n" + "This exceeds the maximum 32-bit value. Some features may be\n" + "ignored, and fuzzing may become less precise. If possible,\n" + "consider refactoring the fuzzer into several smaller fuzzers\n" + "linked against only a portion of the current target.\n", + MaxFeatures); +} + +ATTRIBUTE_NO_SANITIZE_ALL +void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { + const uintptr_t kBits = 12; + const uintptr_t kMask = (1 << kBits) - 1; + uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits); + ValueProfileMap.AddValueModPrime(Idx); +} + +/// \return the address of the previous instruction. +/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h` +inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) { +#if defined(__arm__) + // T32 (Thumb) branch instructions might be 16 or 32 bit long, + // so we return (pc-2) in that case in order to be safe. + // For A32 mode we return (pc-4) because all instructions are 32 bit long. + return (PC - 3) & (~1); +#elif defined(__sparc__) || defined(__mips__) + return PC - 8; +#elif defined(__riscv__) + return PC - 2; +#elif defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) + return PC - 1; +#else + return PC - 4; +#endif +} + +/// \return the address of the next instruction. +/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cpp` +ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) { +#if defined(__mips__) + return PC + 8; +#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \ + defined(__aarch64__) || defined(__loongarch__) + return PC + 4; +#else + return PC + 1; +#endif +} + +void TracePC::UpdateObservedPCs() { + std::vector CoveredFuncs; + auto ObservePC = [&](const PCTableEntry *TE) { + if (ObservedPCs.insert(TE).second && DoPrintNewPCs) { + PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", + GetNextInstructionPc(TE->PC)); + Printf("\n"); + } + }; + + auto Observe = [&](const PCTableEntry *TE) { + if (PcIsFuncEntry(TE)) + if (++ObservedFuncs[TE->PC] == 1 && NumPrintNewFuncs) + CoveredFuncs.push_back(TE->PC); + ObservePC(TE); + }; + + if (NumPCsInPCTables) { + if (NumInline8bitCounters == NumPCsInPCTables) { + for (size_t i = 0; i < NumModules; i++) { + auto &M = Modules[i]; + assert(M.Size() == + (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); + for (size_t r = 0; r < M.NumRegions; r++) { + auto &R = M.Regions[r]; + if (!R.Enabled) continue; + for (uint8_t *P = R.Start; P < R.Stop; P++) + if (*P) + Observe(&ModulePCTable[i].Start[M.Idx(P)]); + } + } + } + } + + for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N; + i++) { + Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size()); + PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i])); + Printf("\n"); + } +} + +uintptr_t TracePC::PCTableEntryIdx(const PCTableEntry *TE) { + size_t TotalTEs = 0; + for (size_t i = 0; i < NumPCTables; i++) { + auto &M = ModulePCTable[i]; + if (TE >= M.Start && TE < M.Stop) + return TotalTEs + TE - M.Start; + TotalTEs += M.Stop - M.Start; + } + assert(0); + return 0; +} + +const TracePC::PCTableEntry *TracePC::PCTableEntryByIdx(uintptr_t Idx) { + for (size_t i = 0; i < NumPCTables; i++) { + auto &M = ModulePCTable[i]; + size_t Size = M.Stop - M.Start; + if (Idx < Size) return &M.Start[Idx]; + Idx -= Size; + } + return nullptr; +} + +static std::string GetModuleName(uintptr_t PC) { + char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++? + void *OffsetRaw = nullptr; + if (!EF->__sanitizer_get_module_and_offset_for_pc( + reinterpret_cast(PC), ModulePathRaw, + sizeof(ModulePathRaw), &OffsetRaw)) + return ""; + return ModulePathRaw; +} + +template +void TracePC::IterateCoveredFunctions(CallBack CB) { + for (size_t i = 0; i < NumPCTables; i++) { + auto &M = ModulePCTable[i]; + assert(M.Start < M.Stop); + auto ModuleName = GetModuleName(M.Start->PC); + for (auto NextFE = M.Start; NextFE < M.Stop; ) { + auto FE = NextFE; + assert(PcIsFuncEntry(FE) && "Not a function entry point"); + do { + NextFE++; + } while (NextFE < M.Stop && !(PcIsFuncEntry(NextFE))); + CB(FE, NextFE, ObservedFuncs[FE->PC]); + } + } +} + +void TracePC::SetFocusFunction(const std::string &FuncName) { + // This function should be called once. + assert(!FocusFunctionCounterPtr); + // "auto" is not a valid function name. If this function is called with "auto" + // that means the auto focus functionality failed. + if (FuncName.empty() || FuncName == "auto") + return; + for (size_t M = 0; M < NumModules; M++) { + auto &PCTE = ModulePCTable[M]; + size_t N = PCTE.Stop - PCTE.Start; + for (size_t I = 0; I < N; I++) { + if (!(PcIsFuncEntry(&PCTE.Start[I]))) continue; // not a function entry. + auto Name = DescribePC("%F", GetNextInstructionPc(PCTE.Start[I].PC)); + if (Name[0] == 'i' && Name[1] == 'n' && Name[2] == ' ') + Name = Name.substr(3, std::string::npos); + if (FuncName != Name) continue; + Printf("INFO: Focus function is set to '%s'\n", Name.c_str()); + FocusFunctionCounterPtr = Modules[M].Start() + I; + return; + } + } + + Printf("ERROR: Failed to set focus function. Make sure the function name is " + "valid (%s) and symbolization is enabled.\n", FuncName.c_str()); + exit(1); +} + +bool TracePC::ObservedFocusFunction() { + return FocusFunctionCounterPtr && *FocusFunctionCounterPtr; +} + +void TracePC::PrintCoverage(bool PrintAllCounters) { + if (!EF->__sanitizer_symbolize_pc || + !EF->__sanitizer_get_module_and_offset_for_pc) { + Printf("INFO: __sanitizer_symbolize_pc or " + "__sanitizer_get_module_and_offset_for_pc is not available," + " not printing coverage\n"); + return; + } + Printf(PrintAllCounters ? "FULL COVERAGE:\n" : "COVERAGE:\n"); + auto CoveredFunctionCallback = [&](const PCTableEntry *First, + const PCTableEntry *Last, + uintptr_t Counter) { + assert(First < Last); + auto VisualizePC = GetNextInstructionPc(First->PC); + std::string FileStr = DescribePC("%s", VisualizePC); + if (!IsInterestingCoverageFile(FileStr)) + return; + std::string FunctionStr = DescribePC("%F", VisualizePC); + if (FunctionStr.find("in ") == 0) + FunctionStr = FunctionStr.substr(3); + std::string LineStr = DescribePC("%l", VisualizePC); + size_t NumEdges = Last - First; + std::vector UncoveredPCs; + std::vector CoveredPCs; + for (auto TE = First; TE < Last; TE++) + if (!ObservedPCs.count(TE)) + UncoveredPCs.push_back(TE->PC); + else + CoveredPCs.push_back(TE->PC); + + if (PrintAllCounters) { + Printf("U"); + for (auto PC : UncoveredPCs) + Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str()); + Printf("\n"); + + Printf("C"); + for (auto PC : CoveredPCs) + Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str()); + Printf("\n"); + } else { + Printf("%sCOVERED_FUNC: hits: %zd", Counter ? "" : "UN", Counter); + Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges); + Printf(" %s %s:%s\n", FunctionStr.c_str(), FileStr.c_str(), + LineStr.c_str()); + if (Counter) + for (auto PC : UncoveredPCs) + Printf(" UNCOVERED_PC: %s\n", + DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str()); + } + }; + + IterateCoveredFunctions(CoveredFunctionCallback); +} + +// Value profile. +// We keep track of various values that affect control flow. +// These values are inserted into a bit-set-based hash map. +// Every new bit in the map is treated as a new coverage. +// +// For memcmp/strcmp/etc the interesting value is the length of the common +// prefix of the parameters. +// For cmp instructions the interesting value is a XOR of the parameters. +// The interesting value is mixed up with the PC and is then added to the map. + +ATTRIBUTE_NO_SANITIZE_ALL +void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, + size_t n, bool StopAtZero) { + if (!n) return; + size_t Len = std::min(n, Word::GetMaxSize()); + const uint8_t *A1 = reinterpret_cast(s1); + const uint8_t *A2 = reinterpret_cast(s2); + uint8_t B1[Word::kMaxSize]; + uint8_t B2[Word::kMaxSize]; + // Copy the data into locals in this non-msan-instrumented function + // to avoid msan complaining further. + size_t Hash = 0; // Compute some simple hash of both strings. + for (size_t i = 0; i < Len; i++) { + B1[i] = A1[i]; + B2[i] = A2[i]; + size_t T = B1[i]; + Hash ^= (T << 8) | B2[i]; + } + size_t I = 0; + uint8_t HammingDistance = 0; + for (; I < Len; I++) { + if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) { + HammingDistance = static_cast(Popcountll(B1[I] ^ B2[I])); + break; + } + } + size_t PC = reinterpret_cast(caller_pc); + size_t Idx = (PC & 4095) | (I << 12); + Idx += HammingDistance; + ValueProfileMap.AddValue(Idx); + TORCW.Insert(Idx ^ Hash, Word(B1, Len), Word(B2, Len)); +} + +template +ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE +ATTRIBUTE_NO_SANITIZE_ALL +void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) { + uint64_t ArgXor = Arg1 ^ Arg2; + if (sizeof(T) == 4) + TORC4.Insert(ArgXor, Arg1, Arg2); + else if (sizeof(T) == 8) + TORC8.Insert(ArgXor, Arg1, Arg2); + uint64_t HammingDistance = Popcountll(ArgXor); // [0,64] + uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1); + ValueProfileMap.AddValue(PC * 128 + HammingDistance); + ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); +} + +ATTRIBUTE_NO_SANITIZE_MEMORY +static size_t InternalStrnlen(const char *S, size_t MaxLen) { + size_t Len = 0; + for (; Len < MaxLen && S[Len]; Len++) {} + return Len; +} + +// Finds min of (strlen(S1), strlen(S2)). +// Needed because one of these strings may actually be non-zero terminated. +ATTRIBUTE_NO_SANITIZE_MEMORY +static size_t InternalStrnlen2(const char *S1, const char *S2) { + size_t Len = 0; + for (; S1[Len] && S2[Len]; Len++) {} + return Len; +} + +void TracePC::ClearInlineCounters() { + IterateCounterRegions([](const Module::Region &R){ + if (R.Enabled) + memset(R.Start, 0, R.Stop - R.Start); + }); +} + +ATTRIBUTE_NO_SANITIZE_ALL +void TracePC::RecordInitialStack() { + int stack; + __sancov_lowest_stack = InitialStack = reinterpret_cast(&stack); +} + +uintptr_t TracePC::GetMaxStackOffset() const { + return InitialStack - __sancov_lowest_stack; // Stack grows down +} + +void WarnAboutDeprecatedInstrumentation(const char *flag) { + // Use RawPrint because Printf cannot be used on Windows before OutputFile is + // initialized. + RawPrint(flag); + RawPrint( + " is no longer supported by libFuzzer.\n" + "Please either migrate to a compiler that supports -fsanitize=fuzzer\n" + "or use an older version of libFuzzer\n"); + exit(1); +} + +} // namespace fuzzer + +extern "C" { +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { + fuzzer::WarnAboutDeprecatedInstrumentation( + "-fsanitize-coverage=trace-pc-guard"); +} + +// Best-effort support for -fsanitize-coverage=trace-pc, which is available +// in both Clang and GCC. +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +void __sanitizer_cov_trace_pc() { + fuzzer::WarnAboutDeprecatedInstrumentation("-fsanitize-coverage=trace-pc"); +} + +ATTRIBUTE_INTERFACE +void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { + fuzzer::WarnAboutDeprecatedInstrumentation( + "-fsanitize-coverage=trace-pc-guard"); +} + +ATTRIBUTE_INTERFACE +void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) { + fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop); +} + +ATTRIBUTE_INTERFACE +void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, + const uintptr_t *pcs_end) { + fuzzer::TPC.HandlePCsInit(pcs_beg, pcs_end); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCallerCallee(PC, Callee); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +// Now the __sanitizer_cov_trace_const_cmp[1248] callbacks just mimic +// the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however, +// should be changed later to make full use of instrumentation. +void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { + uint64_t N = Cases[0]; + uint64_t ValSizeInBits = Cases[1]; + uint64_t *Vals = Cases + 2; + // Skip the most common and the most boring case: all switch values are small. + // We may want to skip this at compile-time, but it will make the + // instrumentation less general. + if (Vals[N - 1] < 256) + return; + // Also skip small inputs values, they won't give good signal. + if (Val < 256) + return; + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + size_t i; + uint64_t Smaller = 0; + uint64_t Larger = ~(uint64_t)0; + // Find two switch values such that Smaller < Val < Larger. + // Use 0 and 0xfff..f as the defaults. + for (i = 0; i < N; i++) { + if (Val < Vals[i]) { + Larger = Vals[i]; + break; + } + if (Val > Vals[i]) Smaller = Vals[i]; + } + + // Apply HandleCmp to {Val,Smaller} and {Val, Larger}, + // use i as the PC modifier for HandleCmp. + if (ValSizeInBits == 16) { + fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast(Val), + (uint16_t)(Smaller)); + fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast(Val), + (uint16_t)(Larger)); + } else if (ValSizeInBits == 32) { + fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast(Val), + (uint32_t)(Smaller)); + fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast(Val), + (uint32_t)(Larger)); + } else { + fuzzer::TPC.HandleCmp(PC + 2*i, Val, Smaller); + fuzzer::TPC.HandleCmp(PC + 2*i + 1, Val, Larger); + } +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_div4(uint32_t Val) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_div8(uint64_t Val) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0); +} + +ATTRIBUTE_INTERFACE +ATTRIBUTE_NO_SANITIZE_ALL +ATTRIBUTE_TARGET_POPCNT +void __sanitizer_cov_trace_gep(uintptr_t Idx) { + uintptr_t PC = reinterpret_cast(GET_CALLER_PC()); + fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, + const void *s2, size_t n, int result) { + if (!fuzzer::RunningUserCallback) return; + if (result == 0) return; // No reason to mutate. + if (n <= 1) return; // Not interesting. + fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, + const char *s2, size_t n, int result) { + if (!fuzzer::RunningUserCallback) return; + if (result == 0) return; // No reason to mutate. + size_t Len1 = fuzzer::InternalStrnlen(s1, n); + size_t Len2 = fuzzer::InternalStrnlen(s2, n); + n = std::min(n, Len1); + n = std::min(n, Len2); + if (n <= 1) return; // Not interesting. + fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, + const char *s2, int result) { + if (!fuzzer::RunningUserCallback) return; + if (result == 0) return; // No reason to mutate. + size_t N = fuzzer::InternalStrnlen2(s1, s2); + if (N <= 1) return; // Not interesting. + fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result) { + if (!fuzzer::RunningUserCallback) return; + return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, + const char *s2, int result) { + if (!fuzzer::RunningUserCallback) return; + return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result) { + if (!fuzzer::RunningUserCallback) return; + fuzzer::TPC.MMT.Add(reinterpret_cast(s2), strlen(s2)); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, + const char *s2, char *result) { + if (!fuzzer::RunningUserCallback) return; + fuzzer::TPC.MMT.Add(reinterpret_cast(s2), strlen(s2)); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, + const void *s2, size_t len2, void *result) { + if (!fuzzer::RunningUserCallback) return; + fuzzer::TPC.MMT.Add(reinterpret_cast(s2), len2); +} +} // extern "C" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerTracePC.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,298 @@ +//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// fuzzer::TracePC +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_TRACE_PC +#define LLVM_FUZZER_TRACE_PC + +#include "FuzzerDefs.h" +#include "FuzzerDictionary.h" +#include "FuzzerValueBitMap.h" + +#include +#include + +namespace fuzzer { + +// TableOfRecentCompares (TORC) remembers the most recently performed +// comparisons of type T. +// We record the arguments of CMP instructions in this table unconditionally +// because it seems cheaper this way than to compute some expensive +// conditions inside __sanitizer_cov_trace_cmp*. +// After the unit has been executed we may decide to use the contents of +// this table to populate a Dictionary. +template +struct TableOfRecentCompares { + static const size_t kSize = kSizeT; + struct Pair { + T A, B; + }; + ATTRIBUTE_NO_SANITIZE_ALL + void Insert(size_t Idx, const T &Arg1, const T &Arg2) { + Idx = Idx % kSize; + Table[Idx].A = Arg1; + Table[Idx].B = Arg2; + } + + Pair Get(size_t I) { return Table[I % kSize]; } + + Pair Table[kSize]; +}; + +template +struct MemMemTable { + static const size_t kSize = kSizeT; + Word MemMemWords[kSize]; + Word EmptyWord; + + void Add(const uint8_t *Data, size_t Size) { + if (Size <= 2) return; + Size = std::min(Size, Word::GetMaxSize()); + auto Idx = SimpleFastHash(Data, Size) % kSize; + MemMemWords[Idx].Set(Data, Size); + } + const Word &Get(size_t Idx) { + for (size_t i = 0; i < kSize; i++) { + const Word &W = MemMemWords[(Idx + i) % kSize]; + if (W.size()) return W; + } + EmptyWord.Set(nullptr, 0); + return EmptyWord; + } +}; + +class TracePC { + public: + void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop); + void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop); + void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); + template void HandleCmp(uintptr_t PC, T Arg1, T Arg2); + size_t GetTotalPCCoverage(); + void SetUseCounters(bool UC) { UseCounters = UC; } + void SetUseValueProfileMask(uint32_t VPMask) { UseValueProfileMask = VPMask; } + void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; } + void SetPrintNewFuncs(size_t P) { NumPrintNewFuncs = P; } + void UpdateObservedPCs(); + template size_t CollectFeatures(Callback CB) const; + + void ResetMaps() { + ValueProfileMap.Reset(); + ClearExtraCounters(); + ClearInlineCounters(); + } + + void ClearInlineCounters(); + + void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize); + void PrintFeatureSet(); + + void PrintModuleInfo(); + + void PrintCoverage(bool PrintAllCounters); + + template + void IterateCoveredFunctions(CallBack CB); + + void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, + size_t n, bool StopAtZero); + + TableOfRecentCompares TORC4; + TableOfRecentCompares TORC8; + TableOfRecentCompares TORCW; + MemMemTable<1024> MMT; + + void RecordInitialStack(); + uintptr_t GetMaxStackOffset() const; + + template + void ForEachObservedPC(CallBack CB) { + for (auto PC : ObservedPCs) + CB(PC); + } + + void SetFocusFunction(const std::string &FuncName); + bool ObservedFocusFunction(); + + struct PCTableEntry { + uintptr_t PC, PCFlags; + }; + + uintptr_t PCTableEntryIdx(const PCTableEntry *TE); + const PCTableEntry *PCTableEntryByIdx(uintptr_t Idx); + static uintptr_t GetNextInstructionPc(uintptr_t PC); + bool PcIsFuncEntry(const PCTableEntry *TE) { return TE->PCFlags & 1; } + +private: + bool UseCounters = false; + uint32_t UseValueProfileMask = false; + bool DoPrintNewPCs = false; + size_t NumPrintNewFuncs = 0; + + // Module represents the array of 8-bit counters split into regions + // such that every region, except maybe the first and the last one, is one + // full page. + struct Module { + struct Region { + uint8_t *Start, *Stop; + bool Enabled; + bool OneFullPage; + }; + Region *Regions; + size_t NumRegions; + uint8_t *Start() { return Regions[0].Start; } + uint8_t *Stop() { return Regions[NumRegions - 1].Stop; } + size_t Size() { return Stop() - Start(); } + size_t Idx(uint8_t *P) { + assert(P >= Start() && P < Stop()); + return P - Start(); + } + }; + + Module Modules[4096]; + size_t NumModules; // linker-initialized. + size_t NumInline8bitCounters; + + template + void IterateCounterRegions(Callback CB) { + for (size_t m = 0; m < NumModules; m++) + for (size_t r = 0; r < Modules[m].NumRegions; r++) + CB(Modules[m].Regions[r]); + } + + struct { const PCTableEntry *Start, *Stop; } ModulePCTable[4096]; + size_t NumPCTables; + size_t NumPCsInPCTables; + + std::set ObservedPCs; + std::unordered_map ObservedFuncs; // PC => Counter. + + uint8_t *FocusFunctionCounterPtr = nullptr; + + ValueBitMap ValueProfileMap; + uintptr_t InitialStack; +}; + +template +// void Callback(size_t FirstFeature, size_t Idx, uint8_t Value); +ATTRIBUTE_NO_SANITIZE_ALL +size_t ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End, + size_t FirstFeature, Callback Handle8bitCounter) { + typedef uintptr_t LargeType; + const size_t Step = sizeof(LargeType) / sizeof(uint8_t); + const size_t StepMask = Step - 1; + auto P = Begin; + // Iterate by 1 byte until either the alignment boundary or the end. + for (; reinterpret_cast(P) & StepMask && P < End; P++) + if (uint8_t V = *P) + Handle8bitCounter(FirstFeature, P - Begin, V); + + // Iterate by Step bytes at a time. + for (; P + Step <= End; P += Step) + if (LargeType Bundle = *reinterpret_cast(P)) { + Bundle = HostToLE(Bundle); + for (size_t I = 0; I < Step; I++, Bundle >>= 8) + if (uint8_t V = Bundle & 0xff) + Handle8bitCounter(FirstFeature, P - Begin + I, V); + } + + // Iterate by 1 byte until the end. + for (; P < End; P++) + if (uint8_t V = *P) + Handle8bitCounter(FirstFeature, P - Begin, V); + return End - Begin; +} + +// Given a non-zero Counter returns a number in the range [0,7]. +template +unsigned CounterToFeature(T Counter) { + // Returns a feature number by placing Counters into buckets as illustrated + // below. + // + // Counter bucket: [1] [2] [3] [4-7] [8-15] [16-31] [32-127] [128+] + // Feature number: 0 1 2 3 4 5 6 7 + // + // This is a heuristic taken from AFL (see + // http://lcamtuf.coredump.cx/afl/technical_details.txt). + // + // This implementation may change in the future so clients should + // not rely on it. + assert(Counter); + unsigned Bit = 0; + /**/ if (Counter >= 128) Bit = 7; + else if (Counter >= 32) Bit = 6; + else if (Counter >= 16) Bit = 5; + else if (Counter >= 8) Bit = 4; + else if (Counter >= 4) Bit = 3; + else if (Counter >= 3) Bit = 2; + else if (Counter >= 2) Bit = 1; + return Bit; +} + +template // void Callback(uint32_t Feature) +ATTRIBUTE_NO_SANITIZE_ADDRESS ATTRIBUTE_NOINLINE size_t +TracePC::CollectFeatures(Callback HandleFeature) const { + auto Handle8bitCounter = [&](size_t FirstFeature, + size_t Idx, uint8_t Counter) { + if (UseCounters) + HandleFeature(static_cast(FirstFeature + Idx * 8 + + CounterToFeature(Counter))); + else + HandleFeature(static_cast(FirstFeature + Idx)); + }; + + size_t FirstFeature = 0; + + for (size_t i = 0; i < NumModules; i++) { + for (size_t r = 0; r < Modules[i].NumRegions; r++) { + if (!Modules[i].Regions[r].Enabled) continue; + FirstFeature += 8 * ForEachNonZeroByte(Modules[i].Regions[r].Start, + Modules[i].Regions[r].Stop, + FirstFeature, Handle8bitCounter); + } + } + + FirstFeature += + 8 * ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), + FirstFeature, Handle8bitCounter); + + if (UseValueProfileMask) { + ValueProfileMap.ForEach([&](size_t Idx) { + HandleFeature(static_cast(FirstFeature + Idx)); + }); + FirstFeature += ValueProfileMap.SizeInBits(); + } + + // Step function, grows similar to 8 * Log_2(A). + auto StackDepthStepFunction = [](size_t A) -> size_t { + if (!A) + return A; + auto Log2 = Log(A); + if (Log2 < 3) + return A; + Log2 -= 3; + return (Log2 + 1) * 8 + ((A >> Log2) & 7); + }; + assert(StackDepthStepFunction(1024) == 64); + assert(StackDepthStepFunction(1024 * 4) == 80); + assert(StackDepthStepFunction(1024 * 1024) == 144); + + if (auto MaxStackOffset = GetMaxStackOffset()) { + HandleFeature(static_cast( + FirstFeature + StackDepthStepFunction(MaxStackOffset / 8))); + FirstFeature += StackDepthStepFunction(std::numeric_limits::max()); + } + + return FirstFeature; +} + +extern TracePC TPC; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_TRACE_PC diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,237 @@ +//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils. +//===----------------------------------------------------------------------===// + +#include "FuzzerUtil.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +void PrintHexArray(const uint8_t *Data, size_t Size, + const char *PrintAfter) { + for (size_t i = 0; i < Size; i++) + Printf("0x%x,", (unsigned)Data[i]); + Printf("%s", PrintAfter); +} + +void Print(const Unit &v, const char *PrintAfter) { + PrintHexArray(v.data(), v.size(), PrintAfter); +} + +void PrintASCIIByte(uint8_t Byte) { + if (Byte == '\\') + Printf("\\\\"); + else if (Byte == '"') + Printf("\\\""); + else if (Byte >= 32 && Byte < 127) + Printf("%c", Byte); + else + Printf("\\%03o", Byte); +} + +void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { + for (size_t i = 0; i < Size; i++) + PrintASCIIByte(Data[i]); + Printf("%s", PrintAfter); +} + +void PrintASCII(const Unit &U, const char *PrintAfter) { + PrintASCII(U.data(), U.size(), PrintAfter); +} + +bool ToASCII(uint8_t *Data, size_t Size) { + bool Changed = false; + for (size_t i = 0; i < Size; i++) { + uint8_t &X = Data[i]; + auto NewX = X; + NewX &= 127; + if (!isspace(NewX) && !isprint(NewX)) + NewX = ' '; + Changed |= NewX != X; + X = NewX; + } + return Changed; +} + +bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } + +bool IsASCII(const uint8_t *Data, size_t Size) { + for (size_t i = 0; i < Size; i++) + if (!(isprint(Data[i]) || isspace(Data[i]))) return false; + return true; +} + +bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { + U->clear(); + if (Str.empty()) return false; + size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. + // Skip spaces from both sides. + while (L < R && isspace(Str[L])) L++; + while (R > L && isspace(Str[R])) R--; + if (R - L < 2) return false; + // Check the closing " + if (Str[R] != '"') return false; + R--; + // Find the opening " + while (L < R && Str[L] != '"') L++; + if (L >= R) return false; + assert(Str[L] == '\"'); + L++; + assert(L <= R); + for (size_t Pos = L; Pos <= R; Pos++) { + uint8_t V = (uint8_t)Str[Pos]; + if (!isprint(V) && !isspace(V)) return false; + if (V =='\\') { + // Handle '\\' + if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { + U->push_back(Str[Pos + 1]); + Pos++; + continue; + } + // Handle '\xAB' + if (Pos + 3 <= R && Str[Pos + 1] == 'x' + && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { + char Hex[] = "0xAA"; + Hex[2] = Str[Pos + 2]; + Hex[3] = Str[Pos + 3]; + U->push_back(static_cast(strtol(Hex, nullptr, 16))); + Pos += 3; + continue; + } + return false; // Invalid escape. + } else { + // Any other character. + U->push_back(V); + } + } + return true; +} + +bool ParseDictionaryFile(const std::string &Text, std::vector *Units) { + if (Text.empty()) { + Printf("ParseDictionaryFile: file does not exist or is empty\n"); + return false; + } + std::istringstream ISS(Text); + Units->clear(); + Unit U; + int LineNo = 0; + std::string S; + while (std::getline(ISS, S, '\n')) { + LineNo++; + size_t Pos = 0; + while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. + if (Pos == S.size()) continue; // Empty line. + if (S[Pos] == '#') continue; // Comment line. + if (ParseOneDictionaryEntry(S, &U)) { + Units->push_back(U); + } else { + Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, + S.c_str()); + return false; + } + } + return true; +} + +// Code duplicated (and tested) in llvm/include/llvm/Support/Base64.h +std::string Base64(const Unit &U) { + static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + std::string Buffer; + Buffer.resize(((U.size() + 2) / 3) * 4); + + size_t i = 0, j = 0; + for (size_t n = U.size() / 3 * 3; i < n; i += 3, j += 4) { + uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8) | + (unsigned char)U[i + 2]; + Buffer[j + 0] = Table[(x >> 18) & 63]; + Buffer[j + 1] = Table[(x >> 12) & 63]; + Buffer[j + 2] = Table[(x >> 6) & 63]; + Buffer[j + 3] = Table[x & 63]; + } + if (i + 1 == U.size()) { + uint32_t x = ((unsigned char)U[i] << 16); + Buffer[j + 0] = Table[(x >> 18) & 63]; + Buffer[j + 1] = Table[(x >> 12) & 63]; + Buffer[j + 2] = '='; + Buffer[j + 3] = '='; + } else if (i + 2 == U.size()) { + uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8); + Buffer[j + 0] = Table[(x >> 18) & 63]; + Buffer[j + 1] = Table[(x >> 12) & 63]; + Buffer[j + 2] = Table[(x >> 6) & 63]; + Buffer[j + 3] = '='; + } + return Buffer; +} + +static std::mutex SymbolizeMutex; + +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { + std::unique_lock l(SymbolizeMutex, std::try_to_lock); + if (!EF->__sanitizer_symbolize_pc || !l.owns_lock()) + return ""; + char PcDescr[1024] = {}; + EF->__sanitizer_symbolize_pc(reinterpret_cast(PC), + SymbolizedFMT, PcDescr, sizeof(PcDescr)); + PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case. + return PcDescr; +} + +void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) { + if (EF->__sanitizer_symbolize_pc) + Printf("%s", DescribePC(SymbolizedFMT, PC).c_str()); + else + Printf(FallbackFMT, PC); +} + +void PrintStackTrace() { + std::unique_lock l(SymbolizeMutex, std::try_to_lock); + if (EF->__sanitizer_print_stack_trace && l.owns_lock()) + EF->__sanitizer_print_stack_trace(); +} + +void PrintMemoryProfile() { + std::unique_lock l(SymbolizeMutex, std::try_to_lock); + if (EF->__sanitizer_print_memory_profile && l.owns_lock()) + EF->__sanitizer_print_memory_profile(95, 8); +} + +unsigned NumberOfCpuCores() { + unsigned N = std::thread::hardware_concurrency(); + if (!N) { + Printf("WARNING: std::thread::hardware_concurrency not well defined for " + "your platform. Assuming CPU count of 1.\n"); + N = 1; + } + return N; +} + +uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial) { + uint64_t Res = Initial; + const uint8_t *Bytes = static_cast(Data); + for (size_t i = 0; i < Size; i++) + Res = Res * 11 + Bytes[i]; + return Res; +} + +} // namespace fuzzer diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtil.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,122 @@ +//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Util functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_UTIL_H +#define LLVM_FUZZER_UTIL_H + +#include "FuzzerBuiltins.h" +#include "FuzzerBuiltinsMsvc.h" +#include "FuzzerCommand.h" +#include "FuzzerDefs.h" + +namespace fuzzer { + +void PrintHexArray(const Unit &U, const char *PrintAfter = ""); + +void PrintHexArray(const uint8_t *Data, size_t Size, + const char *PrintAfter = ""); + +void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); + +void PrintASCII(const Unit &U, const char *PrintAfter = ""); + +// Changes U to contain only ASCII (isprint+isspace) characters. +// Returns true iff U has been changed. +bool ToASCII(uint8_t *Data, size_t Size); + +bool IsASCII(const Unit &U); + +bool IsASCII(const uint8_t *Data, size_t Size); + +std::string Base64(const Unit &U); + +void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); + +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); + +void PrintStackTrace(); + +void PrintMemoryProfile(); + +unsigned NumberOfCpuCores(); + +// Platform specific functions. +void SetSignalHandler(const FuzzingOptions& Options); + +void SleepSeconds(int Seconds); + +unsigned long GetPid(); + +size_t GetPeakRSSMb(); + +int ExecuteCommand(const Command &Cmd); +bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput); + +void SetThreadName(std::thread &thread, const std::string &name); + +// Fuchsia does not have popen/pclose. +FILE *OpenProcessPipe(const char *Command, const char *Mode); +int CloseProcessPipe(FILE *F); + +const void *SearchMemory(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + +std::string CloneArgsWithoutX(const std::vector &Args, + const char *X1, const char *X2); + +inline std::string CloneArgsWithoutX(const std::vector &Args, + const char *X) { + return CloneArgsWithoutX(Args, X, X); +} + +inline std::pair SplitBefore(std::string X, + std::string S) { + auto Pos = S.find(X); + if (Pos == std::string::npos) + return std::make_pair(S, ""); + return std::make_pair(S.substr(0, Pos), S.substr(Pos)); +} + +void DiscardOutput(int Fd); + +std::string DisassembleCmd(const std::string &FileName); + +std::string SearchRegexCmd(const std::string &Regex); + +uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial = 0); + +inline size_t Log(size_t X) { + return static_cast((sizeof(unsigned long long) * 8) - Clzll(X) - 1); +} + +size_t PageSize(); + +inline uint8_t *RoundUpByPage(uint8_t *P) { + uintptr_t X = reinterpret_cast(P); + size_t Mask = PageSize() - 1; + X = (X + Mask) & ~Mask; + return reinterpret_cast(X); +} +inline uint8_t *RoundDownByPage(uint8_t *P) { + uintptr_t X = reinterpret_cast(P); + size_t Mask = PageSize() - 1; + X = X & ~Mask; + return reinterpret_cast(X); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +template T HostToLE(T X) { return X; } +#else +template T HostToLE(T X) { return Bswap(X); } +#endif + +} // namespace fuzzer + +#endif // LLVM_FUZZER_UTIL_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilDarwin.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilDarwin.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilDarwin.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilDarwin.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,175 @@ +//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils for Darwin. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_APPLE +#include "FuzzerCommand.h" +#include "FuzzerIO.h" +#include +#include +#include +#include +#include +#include +#include + +// There is no header for this on macOS so declare here +extern "C" char **environ; + +namespace fuzzer { + +static std::mutex SignalMutex; +// Global variables used to keep track of how signal handling should be +// restored. They should **not** be accessed without holding `SignalMutex`. +static int ActiveThreadCount = 0; +static struct sigaction OldSigIntAction; +static struct sigaction OldSigQuitAction; +static sigset_t OldBlockedSignalsSet; + +// This is a reimplementation of Libc's `system()`. On Darwin the Libc +// implementation contains a mutex which prevents it from being used +// concurrently. This implementation **can** be used concurrently. It sets the +// signal handlers when the first thread enters and restores them when the last +// thread finishes execution of the function and ensures this is not racey by +// using a mutex. +int ExecuteCommand(const Command &Cmd) { + std::string CmdLine = Cmd.toString(); + posix_spawnattr_t SpawnAttributes; + if (posix_spawnattr_init(&SpawnAttributes)) + return -1; + // Block and ignore signals of the current process when the first thread + // enters. + { + std::lock_guard Lock(SignalMutex); + if (ActiveThreadCount == 0) { + static struct sigaction IgnoreSignalAction; + sigset_t BlockedSignalsSet; + memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction)); + IgnoreSignalAction.sa_handler = SIG_IGN; + + if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) { + Printf("Failed to ignore SIGINT\n"); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) { + Printf("Failed to ignore SIGQUIT\n"); + // Try our best to restore the signal handlers. + (void)sigaction(SIGINT, &OldSigIntAction, NULL); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + + (void)sigemptyset(&BlockedSignalsSet); + (void)sigaddset(&BlockedSignalsSet, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) == + -1) { + Printf("Failed to block SIGCHLD\n"); + // Try our best to restore the signal handlers. + (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL); + (void)sigaction(SIGINT, &OldSigIntAction, NULL); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + } + ++ActiveThreadCount; + } + + // NOTE: Do not introduce any new `return` statements past this + // point. It is important that `ActiveThreadCount` always be decremented + // when leaving this function. + + // Make sure the child process uses the default handlers for the + // following signals rather than inheriting what the parent has. + sigset_t DefaultSigSet; + (void)sigemptyset(&DefaultSigSet); + (void)sigaddset(&DefaultSigSet, SIGQUIT); + (void)sigaddset(&DefaultSigSet, SIGINT); + (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet); + // Make sure the child process doesn't block SIGCHLD + (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet); + short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags); + + pid_t Pid; + char **Environ = environ; // Read from global + const char *CommandCStr = CmdLine.c_str(); + char *const Argv[] = { + strdup("sh"), + strdup("-c"), + strdup(CommandCStr), + NULL + }; + int ErrorCode = 0, ProcessStatus = 0; + // FIXME: We probably shouldn't hardcode the shell path. + ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes, + Argv, Environ); + (void)posix_spawnattr_destroy(&SpawnAttributes); + if (!ErrorCode) { + pid_t SavedPid = Pid; + do { + // Repeat until call completes uninterrupted. + Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0); + } while (Pid == -1 && errno == EINTR); + if (Pid == -1) { + // Fail for some other reason. + ProcessStatus = -1; + } + } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) { + // Fork failure. + ProcessStatus = -1; + } else { + // Shell execution failure. + ProcessStatus = W_EXITCODE(127, 0); + } + for (unsigned i = 0, n = sizeof(Argv) / sizeof(Argv[0]); i < n; ++i) + free(Argv[i]); + + // Restore the signal handlers of the current process when the last thread + // using this function finishes. + { + std::lock_guard Lock(SignalMutex); + --ActiveThreadCount; + if (ActiveThreadCount == 0) { + bool FailedRestore = false; + if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) { + Printf("Failed to restore SIGINT handling\n"); + FailedRestore = true; + } + if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) { + Printf("Failed to restore SIGQUIT handling\n"); + FailedRestore = true; + } + if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) { + Printf("Failed to unblock SIGCHLD\n"); + FailedRestore = true; + } + if (FailedRestore) + ProcessStatus = -1; + } + } + return ProcessStatus; +} + +void DiscardOutput(int Fd) { + FILE* Temp = fopen("/dev/null", "w"); + if (!Temp) + return; + dup2(fileno(Temp), Fd); + fclose(Temp); +} + +void SetThreadName(std::thread &thread, const std::string &name) { + // TODO ? + // Darwin allows to set the name only on the current thread it seems +} + +} // namespace fuzzer + +#endif // LIBFUZZER_APPLE diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilFuchsia.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilFuchsia.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilFuchsia.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilFuchsia.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,619 @@ +//===- FuzzerUtilFuchsia.cpp - Misc utils for Fuchsia. --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils implementation using Fuchsia/Zircon APIs. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" + +#if LIBFUZZER_FUCHSIA + +#include "FuzzerInternal.h" +#include "FuzzerUtil.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace fuzzer { + +// Given that Fuchsia doesn't have the POSIX signals that libFuzzer was written +// around, the general approach is to spin up dedicated threads to watch for +// each requested condition (alarm, interrupt, crash). Of these, the crash +// handler is the most involved, as it requires resuming the crashed thread in +// order to invoke the sanitizers to get the needed state. + +// Forward declaration of assembly trampoline needed to resume crashed threads. +// This appears to have external linkage to C++, which is why it's not in the +// anonymous namespace. The assembly definition inside MakeTrampoline() +// actually defines the symbol with internal linkage only. +void CrashTrampolineAsm() __asm__("CrashTrampolineAsm"); + +namespace { + +// The signal handler thread uses Zircon exceptions to resume crashed threads +// into libFuzzer's POSIX signal handlers. The associated event is used to +// signal when the thread is running, and when it should stop. +std::thread SignalHandler; +zx_handle_t SignalHandlerEvent = ZX_HANDLE_INVALID; + +// Helper function to handle Zircon syscall failures. +void ExitOnErr(zx_status_t Status, const char *Syscall) { + if (Status != ZX_OK) { + Printf("libFuzzer: %s failed: %s\n", Syscall, + _zx_status_get_string(Status)); + exit(1); + } +} + +void AlarmHandler(int Seconds) { + while (true) { + SleepSeconds(Seconds); + Fuzzer::StaticAlarmCallback(); + } +} + +// For the crash handler, we need to call Fuzzer::StaticCrashSignalCallback +// without POSIX signal handlers. To achieve this, we use an assembly function +// to add the necessary CFI unwinding information and a C function to bridge +// from that back into C++. + +// FIXME: This works as a short-term solution, but this code really shouldn't be +// architecture dependent. A better long term solution is to implement remote +// unwinding and expose the necessary APIs through sanitizer_common and/or ASAN +// to allow the exception handling thread to gather the crash state directly. +// +// Alternatively, Fuchsia may in future actually implement basic signal +// handling for the machine trap signals. +#if defined(__x86_64__) + +#define FOREACH_REGISTER(OP_REG, OP_NUM) \ + OP_REG(rax) \ + OP_REG(rbx) \ + OP_REG(rcx) \ + OP_REG(rdx) \ + OP_REG(rsi) \ + OP_REG(rdi) \ + OP_REG(rbp) \ + OP_REG(rsp) \ + OP_REG(r8) \ + OP_REG(r9) \ + OP_REG(r10) \ + OP_REG(r11) \ + OP_REG(r12) \ + OP_REG(r13) \ + OP_REG(r14) \ + OP_REG(r15) \ + OP_REG(rip) + +#elif defined(__aarch64__) + +#define FOREACH_REGISTER(OP_REG, OP_NUM) \ + OP_NUM(0) \ + OP_NUM(1) \ + OP_NUM(2) \ + OP_NUM(3) \ + OP_NUM(4) \ + OP_NUM(5) \ + OP_NUM(6) \ + OP_NUM(7) \ + OP_NUM(8) \ + OP_NUM(9) \ + OP_NUM(10) \ + OP_NUM(11) \ + OP_NUM(12) \ + OP_NUM(13) \ + OP_NUM(14) \ + OP_NUM(15) \ + OP_NUM(16) \ + OP_NUM(17) \ + OP_NUM(18) \ + OP_NUM(19) \ + OP_NUM(20) \ + OP_NUM(21) \ + OP_NUM(22) \ + OP_NUM(23) \ + OP_NUM(24) \ + OP_NUM(25) \ + OP_NUM(26) \ + OP_NUM(27) \ + OP_NUM(28) \ + OP_NUM(29) \ + OP_REG(sp) + +#elif defined(__riscv) + +#define FOREACH_REGISTER(OP_REG, OP_NUM) \ + OP_REG(ra) \ + OP_REG(sp) \ + OP_REG(gp) \ + OP_REG(tp) \ + OP_REG(t0) \ + OP_REG(t1) \ + OP_REG(t2) \ + OP_REG(s0) \ + OP_REG(s1) \ + OP_REG(a0) \ + OP_REG(a1) \ + OP_REG(a2) \ + OP_REG(a3) \ + OP_REG(a4) \ + OP_REG(a5) \ + OP_REG(a6) \ + OP_REG(a7) \ + OP_REG(s2) \ + OP_REG(s3) \ + OP_REG(s4) \ + OP_REG(s5) \ + OP_REG(s6) \ + OP_REG(s7) \ + OP_REG(s8) \ + OP_REG(s9) \ + OP_REG(s10) \ + OP_REG(s11) \ + OP_REG(t3) \ + OP_REG(t4) \ + OP_REG(t5) \ + OP_REG(t6) \ + +#else +#error "Unsupported architecture for fuzzing on Fuchsia" +#endif + +// Produces a CFI directive for the named or numbered register. +// The value used refers to an assembler immediate operand with the same name +// as the register (see ASM_OPERAND_REG). +#define CFI_OFFSET_REG(reg) ".cfi_offset " #reg ", %c[" #reg "]\n" +#define CFI_OFFSET_NUM(num) CFI_OFFSET_REG(x##num) + +// Produces an assembler immediate operand for the named or numbered register. +// This operand contains the offset of the register relative to the CFA. +#define ASM_OPERAND_REG(reg) \ + [reg] "i"(offsetof(zx_thread_state_general_regs_t, reg)), +#define ASM_OPERAND_NUM(num) \ + [x##num] "i"(offsetof(zx_thread_state_general_regs_t, r[num])), + +// Trampoline to bridge from the assembly below to the static C++ crash +// callback. +__attribute__((noreturn)) +static void StaticCrashHandler() { + Fuzzer::StaticCrashSignalCallback(); + for (;;) { + _Exit(1); + } +} + +// This trampoline function has the necessary CFI information to unwind +// and get a backtrace: +// * The stack contains a copy of all the registers at the point of crash, +// the code has CFI directives specifying how to restore them. +// * A call to StaticCrashHandler, which will print the stacktrace and exit +// the fuzzer, generating a crash artifact. +// +// The __attribute__((used)) is necessary because the function +// is never called; it's just a container around the assembly to allow it to +// use operands for compile-time computed constants. +__attribute__((used)) +void MakeTrampoline() { + __asm__( + ".cfi_endproc\n" + ".pushsection .text.CrashTrampolineAsm\n" + ".type CrashTrampolineAsm,STT_FUNC\n" + "CrashTrampolineAsm:\n" + ".cfi_startproc simple\n" + ".cfi_signal_frame\n" +#if defined(__x86_64__) + ".cfi_return_column rip\n" + ".cfi_def_cfa rsp, 0\n" + FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) + "call %c[StaticCrashHandler]\n" + "ud2\n" +#elif defined(__aarch64__) + ".cfi_return_column 33\n" + ".cfi_def_cfa sp, 0\n" + FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) + ".cfi_offset 33, %c[pc]\n" + ".cfi_offset 30, %c[lr]\n" + "bl %c[StaticCrashHandler]\n" + "brk 1\n" +#elif defined(__riscv) + ".cfi_return_column 64\n" + ".cfi_def_cfa sp, 0\n" + ".cfi_offset 64, %[pc]\n" + FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) + "call %c[StaticCrashHandler]\n" + "unimp\n" +#else +#error "Unsupported architecture for fuzzing on Fuchsia" +#endif + ".cfi_endproc\n" + ".size CrashTrampolineAsm, . - CrashTrampolineAsm\n" + ".popsection\n" + ".cfi_startproc\n" + : // No outputs + : FOREACH_REGISTER(ASM_OPERAND_REG, ASM_OPERAND_NUM) +#if defined(__aarch64__) || defined(__riscv) + ASM_OPERAND_REG(pc) +#endif +#if defined(__aarch64__) + ASM_OPERAND_REG(lr) +#endif + [StaticCrashHandler] "i"(StaticCrashHandler)); +} + +void CrashHandler() { + assert(SignalHandlerEvent != ZX_HANDLE_INVALID); + + // This structure is used to ensure we close handles to objects we create in + // this handler. + struct ScopedHandle { + ~ScopedHandle() { _zx_handle_close(Handle); } + zx_handle_t Handle = ZX_HANDLE_INVALID; + }; + + // Create the exception channel. We need to claim to be a "debugger" so the + // kernel will allow us to modify and resume dying threads (see below). Once + // the channel is set, we can signal the main thread to continue and wait + // for the exception to arrive. + ScopedHandle Channel; + zx_handle_t Self = _zx_process_self(); + ExitOnErr(_zx_task_create_exception_channel( + Self, ZX_EXCEPTION_CHANNEL_DEBUGGER, &Channel.Handle), + "_zx_task_create_exception_channel"); + + ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0), + "_zx_object_signal"); + + // This thread lives as long as the process in order to keep handling + // crashes. In practice, the first crashed thread to reach the end of the + // StaticCrashHandler will end the process. + while (true) { + zx_wait_item_t WaitItems[] = { + { + .handle = SignalHandlerEvent, + .waitfor = ZX_USER_SIGNAL_1, + .pending = 0, + }, + { + .handle = Channel.Handle, + .waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, + .pending = 0, + }, + }; + auto Status = _zx_object_wait_many( + WaitItems, sizeof(WaitItems) / sizeof(WaitItems[0]), ZX_TIME_INFINITE); + if (Status != ZX_OK || (WaitItems[1].pending & ZX_CHANNEL_READABLE) == 0) { + break; + } + + zx_exception_info_t ExceptionInfo; + ScopedHandle Exception; + ExitOnErr(_zx_channel_read(Channel.Handle, 0, &ExceptionInfo, + &Exception.Handle, sizeof(ExceptionInfo), 1, + nullptr, nullptr), + "_zx_channel_read"); + + // Ignore informational synthetic exceptions. + if (ZX_EXCP_THREAD_STARTING == ExceptionInfo.type || + ZX_EXCP_THREAD_EXITING == ExceptionInfo.type || + ZX_EXCP_PROCESS_STARTING == ExceptionInfo.type) { + continue; + } + + // At this point, we want to get the state of the crashing thread, but + // libFuzzer and the sanitizers assume this will happen from that same + // thread via a POSIX signal handler. "Resurrecting" the thread in the + // middle of the appropriate callback is as simple as forcibly setting the + // instruction pointer/program counter, provided we NEVER EVER return from + // that function (since otherwise our stack will not be valid). + ScopedHandle Thread; + ExitOnErr(_zx_exception_get_thread(Exception.Handle, &Thread.Handle), + "_zx_exception_get_thread"); + + zx_thread_state_general_regs_t GeneralRegisters; + ExitOnErr(_zx_thread_read_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS, + &GeneralRegisters, + sizeof(GeneralRegisters)), + "_zx_thread_read_state"); + + // To unwind properly, we need to push the crashing thread's register state + // onto the stack and jump into a trampoline with CFI instructions on how + // to restore it. +#if defined(__x86_64__) + + uintptr_t StackPtr = + (GeneralRegisters.rsp - (128 + sizeof(GeneralRegisters))) & + -(uintptr_t)16; + __unsanitized_memcpy(reinterpret_cast(StackPtr), &GeneralRegisters, + sizeof(GeneralRegisters)); + GeneralRegisters.rsp = StackPtr; + GeneralRegisters.rip = reinterpret_cast(CrashTrampolineAsm); + +#elif defined(__aarch64__) || defined(__riscv) + + uintptr_t StackPtr = + (GeneralRegisters.sp - sizeof(GeneralRegisters)) & -(uintptr_t)16; + __unsanitized_memcpy(reinterpret_cast(StackPtr), &GeneralRegisters, + sizeof(GeneralRegisters)); + GeneralRegisters.sp = StackPtr; + GeneralRegisters.pc = reinterpret_cast(CrashTrampolineAsm); + +#else +#error "Unsupported architecture for fuzzing on Fuchsia" +#endif + + // Now force the crashing thread's state. + ExitOnErr( + _zx_thread_write_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS, + &GeneralRegisters, sizeof(GeneralRegisters)), + "_zx_thread_write_state"); + + // Set the exception to HANDLED so it resumes the thread on close. + uint32_t ExceptionState = ZX_EXCEPTION_STATE_HANDLED; + ExitOnErr(_zx_object_set_property(Exception.Handle, ZX_PROP_EXCEPTION_STATE, + &ExceptionState, sizeof(ExceptionState)), + "zx_object_set_property"); + } +} + +void StopSignalHandler() { + _zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_1); + if (SignalHandler.joinable()) { + SignalHandler.join(); + } + _zx_handle_close(SignalHandlerEvent); +} + +} // namespace + +// Platform specific functions. +void SetSignalHandler(const FuzzingOptions &Options) { + // Make sure information from libFuzzer and the sanitizers are easy to + // reassemble. `__sanitizer_log_write` has the added benefit of ensuring the + // DSO map is always available for the symbolizer. + // A uint64_t fits in 20 chars, so 64 is plenty. + char Buf[64]; + memset(Buf, 0, sizeof(Buf)); + snprintf(Buf, sizeof(Buf), "==%lu== INFO: libFuzzer starting.\n", GetPid()); + if (EF->__sanitizer_log_write) + __sanitizer_log_write(Buf, sizeof(Buf)); + Printf("%s", Buf); + + // Set up alarm handler if needed. + if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) { + std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1); + T.detach(); + } + + // Options.HandleInt and Options.HandleTerm are not supported on Fuchsia + + // Early exit if no crash handler needed. + if (!Options.HandleSegv && !Options.HandleBus && !Options.HandleIll && + !Options.HandleFpe && !Options.HandleAbrt) + return; + + // Set up the crash handler and wait until it is ready before proceeding. + ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create"); + + SignalHandler = std::thread(CrashHandler); + zx_status_t Status = _zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0, + ZX_TIME_INFINITE, nullptr); + ExitOnErr(Status, "_zx_object_wait_one"); + + std::atexit(StopSignalHandler); +} + +void SleepSeconds(int Seconds) { + _zx_nanosleep(_zx_deadline_after(ZX_SEC(Seconds))); +} + +unsigned long GetPid() { + zx_status_t rc; + zx_info_handle_basic_t Info; + if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, + sizeof(Info), NULL, NULL)) != ZX_OK) { + Printf("libFuzzer: unable to get info about self: %s\n", + _zx_status_get_string(rc)); + exit(1); + } + return Info.koid; +} + +size_t GetPeakRSSMb() { + zx_status_t rc; + zx_info_task_stats_t Info; + if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_TASK_STATS, &Info, + sizeof(Info), NULL, NULL)) != ZX_OK) { + Printf("libFuzzer: unable to get info about self: %s\n", + _zx_status_get_string(rc)); + exit(1); + } + return (Info.mem_private_bytes + Info.mem_shared_bytes) >> 20; +} + +template +class RunOnDestruction { + public: + explicit RunOnDestruction(Fn fn) : fn_(fn) {} + ~RunOnDestruction() { fn_(); } + + private: + Fn fn_; +}; + +template +RunOnDestruction at_scope_exit(Fn fn) { + return RunOnDestruction(fn); +} + +static fdio_spawn_action_t clone_fd_action(int localFd, int targetFd) { + return { + .action = FDIO_SPAWN_ACTION_CLONE_FD, + .fd = + { + .local_fd = localFd, + .target_fd = targetFd, + }, + }; +} + +int ExecuteCommand(const Command &Cmd) { + zx_status_t rc; + + // Convert arguments to C array + auto Args = Cmd.getArguments(); + size_t Argc = Args.size(); + assert(Argc != 0); + std::unique_ptr Argv(new const char *[Argc + 1]); + for (size_t i = 0; i < Argc; ++i) + Argv[i] = Args[i].c_str(); + Argv[Argc] = nullptr; + + // Determine output. On Fuchsia, the fuzzer is typically run as a component + // that lacks a mutable working directory. Fortunately, when this is the case + // a mutable output directory must be specified using "-artifact_prefix=...", + // so write the log file(s) there. + // However, we don't want to apply this logic for absolute paths. + int FdOut = STDOUT_FILENO; + bool discardStdout = false; + bool discardStderr = false; + + if (Cmd.hasOutputFile()) { + std::string Path = Cmd.getOutputFile(); + if (Path == getDevNull()) { + // On Fuchsia, there's no "/dev/null" like-file, so we + // just don't copy the FDs into the spawned process. + discardStdout = true; + } else { + bool IsAbsolutePath = Path.length() > 1 && Path[0] == '/'; + if (!IsAbsolutePath && Cmd.hasFlag("artifact_prefix")) + Path = Cmd.getFlagValue("artifact_prefix") + "/" + Path; + + FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0); + if (FdOut == -1) { + Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(), + strerror(errno)); + return ZX_ERR_IO; + } + } + } + auto CloseFdOut = at_scope_exit([FdOut]() { + if (FdOut != STDOUT_FILENO) + close(FdOut); + }); + + // Determine stderr + int FdErr = STDERR_FILENO; + if (Cmd.isOutAndErrCombined()) { + FdErr = FdOut; + if (discardStdout) + discardStderr = true; + } + + // Clone the file descriptors into the new process + std::vector SpawnActions; + SpawnActions.push_back(clone_fd_action(STDIN_FILENO, STDIN_FILENO)); + + if (!discardStdout) + SpawnActions.push_back(clone_fd_action(FdOut, STDOUT_FILENO)); + if (!discardStderr) + SpawnActions.push_back(clone_fd_action(FdErr, STDERR_FILENO)); + + // Start the process. + char ErrorMsg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; + zx_handle_t ProcessHandle = ZX_HANDLE_INVALID; + rc = fdio_spawn_etc(ZX_HANDLE_INVALID, + FDIO_SPAWN_CLONE_ALL & (~FDIO_SPAWN_CLONE_STDIO), Argv[0], + Argv.get(), nullptr, SpawnActions.size(), + SpawnActions.data(), &ProcessHandle, ErrorMsg); + + if (rc != ZX_OK) { + Printf("libFuzzer: failed to launch '%s': %s, %s\n", Argv[0], ErrorMsg, + _zx_status_get_string(rc)); + return rc; + } + auto CloseHandle = at_scope_exit([&]() { _zx_handle_close(ProcessHandle); }); + + // Now join the process and return the exit status. + if ((rc = _zx_object_wait_one(ProcessHandle, ZX_PROCESS_TERMINATED, + ZX_TIME_INFINITE, nullptr)) != ZX_OK) { + Printf("libFuzzer: failed to join '%s': %s\n", Argv[0], + _zx_status_get_string(rc)); + return rc; + } + + zx_info_process_t Info; + if ((rc = _zx_object_get_info(ProcessHandle, ZX_INFO_PROCESS, &Info, + sizeof(Info), nullptr, nullptr)) != ZX_OK) { + Printf("libFuzzer: unable to get return code from '%s': %s\n", Argv[0], + _zx_status_get_string(rc)); + return rc; + } + + return static_cast(Info.return_code); +} + +bool ExecuteCommand(const Command &BaseCmd, std::string *CmdOutput) { + auto LogFilePath = TempPath("SimPopenOut", ".txt"); + Command Cmd(BaseCmd); + Cmd.setOutputFile(LogFilePath); + int Ret = ExecuteCommand(Cmd); + *CmdOutput = FileToString(LogFilePath); + RemoveFile(LogFilePath); + return Ret == 0; +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + return memmem(Data, DataLen, Patt, PattLen); +} + +// In fuchsia, accessing /dev/null is not supported. There's nothing +// similar to a file that discards everything that is written to it. +// The way of doing something similar in fuchsia is by using +// fdio_null_create and binding that to a file descriptor. +void DiscardOutput(int Fd) { + fdio_t *fdio_null = fdio_null_create(); + if (fdio_null == nullptr) return; + int nullfd = fdio_bind_to_fd(fdio_null, -1, 0); + if (nullfd < 0) return; + dup2(nullfd, Fd); +} + +size_t PageSize() { + static size_t PageSizeCached = _zx_system_get_page_size(); + return PageSizeCached; +} + +void SetThreadName(std::thread &thread, const std::string &name) { + if (zx_status_t s = zx_object_set_property( + thread.native_handle(), ZX_PROP_NAME, name.data(), name.size()); + s != ZX_OK) + Printf("SetThreadName for name %s failed: %s", name.c_str(), + zx_status_get_string(s)); +} + +} // namespace fuzzer + +#endif // LIBFUZZER_FUCHSIA diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilLinux.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilLinux.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilLinux.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilLinux.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils for Linux. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ + LIBFUZZER_EMSCRIPTEN +#include "FuzzerCommand.h" +#include "FuzzerInternal.h" + +#include +#include +#include +#include +#include + + +namespace fuzzer { + +int ExecuteCommand(const Command &Cmd) { + std::string CmdLine = Cmd.toString(); + int exit_code = system(CmdLine.c_str()); + if (WIFEXITED(exit_code)) + return WEXITSTATUS(exit_code); + if (WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGINT) + return Fuzzer::InterruptExitCode(); + return exit_code; +} + +void DiscardOutput(int Fd) { + FILE* Temp = fopen("/dev/null", "w"); + if (!Temp) + return; + dup2(fileno(Temp), Fd); + fclose(Temp); +} + +void SetThreadName(std::thread &thread, const std::string &name) { +#if LIBFUZZER_LINUX || LIBFUZZER_FREEBSD + (void)pthread_setname_np(thread.native_handle(), name.c_str()); +#elif LIBFUZZER_NETBSD + (void)pthread_setname_np(thread.native_handle(), "%s", const_cast(name.c_str())); +#endif +} + +} // namespace fuzzer + +#endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilPosix.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilPosix.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilPosix.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilPosix.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils implementation using Posix API. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_POSIX +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include "FuzzerTracePC.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static void AlarmHandler(int, siginfo_t *, void *) { + Fuzzer::StaticAlarmCallback(); +} + +static void (*upstream_segv_handler)(int, siginfo_t *, void *); + +static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { + assert(si->si_signo == SIGSEGV); + if (upstream_segv_handler) + return upstream_segv_handler(sig, si, ucontext); + Fuzzer::StaticCrashSignalCallback(); +} + +static void CrashHandler(int, siginfo_t *, void *) { + Fuzzer::StaticCrashSignalCallback(); +} + +static void InterruptHandler(int, siginfo_t *, void *) { + Fuzzer::StaticInterruptCallback(); +} + +static void GracefulExitHandler(int, siginfo_t *, void *) { + Fuzzer::StaticGracefulExitCallback(); +} + +static void FileSizeExceedHandler(int, siginfo_t *, void *) { + Fuzzer::StaticFileSizeExceedCallback(); +} + +static void SetSigaction(int signum, + void (*callback)(int, siginfo_t *, void *)) { + struct sigaction sigact = {}; + if (sigaction(signum, nullptr, &sigact)) { + Printf("libFuzzer: sigaction failed with %d\n", errno); + exit(1); + } + if (sigact.sa_flags & SA_SIGINFO) { + if (sigact.sa_sigaction) { + if (signum != SIGSEGV) + return; + upstream_segv_handler = sigact.sa_sigaction; + } + } else { + if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && + sigact.sa_handler != SIG_ERR) + return; + } + + struct sigaction new_sigact = {}; + // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a + // dedicated stack) in order to be able to detect stack overflows; keep the + // flag if it's set. + new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK); + new_sigact.sa_sigaction = callback; + if (sigaction(signum, &new_sigact, nullptr)) { + Printf("libFuzzer: sigaction failed with %d\n", errno); + exit(1); + } +} + +// Return true on success, false otherwise. +bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { + FILE *Pipe = popen(Cmd.toString().c_str(), "r"); + if (!Pipe) + return false; + + if (CmdOutput) { + char TmpBuffer[128]; + while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) + CmdOutput->append(TmpBuffer); + } + return pclose(Pipe) == 0; +} + +void SetTimer(int Seconds) { + struct itimerval T { + {Seconds, 0}, { Seconds, 0 } + }; + if (setitimer(ITIMER_REAL, &T, nullptr)) { + Printf("libFuzzer: setitimer failed with %d\n", errno); + exit(1); + } + SetSigaction(SIGALRM, AlarmHandler); +} + +void SetSignalHandler(const FuzzingOptions& Options) { + // setitimer is not implemented in emscripten. + if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) + SetTimer(Options.UnitTimeoutSec / 2 + 1); + if (Options.HandleInt) + SetSigaction(SIGINT, InterruptHandler); + if (Options.HandleTerm) + SetSigaction(SIGTERM, InterruptHandler); + if (Options.HandleSegv) + SetSigaction(SIGSEGV, SegvHandler); + if (Options.HandleBus) + SetSigaction(SIGBUS, CrashHandler); + if (Options.HandleAbrt) + SetSigaction(SIGABRT, CrashHandler); + if (Options.HandleIll) + SetSigaction(SIGILL, CrashHandler); + if (Options.HandleFpe) + SetSigaction(SIGFPE, CrashHandler); + if (Options.HandleXfsz) + SetSigaction(SIGXFSZ, FileSizeExceedHandler); + if (Options.HandleUsr1) + SetSigaction(SIGUSR1, GracefulExitHandler); + if (Options.HandleUsr2) + SetSigaction(SIGUSR2, GracefulExitHandler); +} + +void SleepSeconds(int Seconds) { + sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. +} + +unsigned long GetPid() { return (unsigned long)getpid(); } + +size_t GetPeakRSSMb() { + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage)) + return 0; + if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || + LIBFUZZER_EMSCRIPTEN) { + // ru_maxrss is in KiB + return usage.ru_maxrss >> 10; + } else if (LIBFUZZER_APPLE) { + // ru_maxrss is in bytes + return usage.ru_maxrss >> 20; + } + assert(0 && "GetPeakRSSMb() is not implemented for your platform"); + return 0; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return popen(Command, Mode); +} + +int CloseProcessPipe(FILE *F) { + return pclose(F); +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + return memmem(Data, DataLen, Patt, PattLen); +} + +std::string DisassembleCmd(const std::string &FileName) { + return "objdump -d " + FileName; +} + +std::string SearchRegexCmd(const std::string &Regex) { + return "grep '" + Regex + "'"; +} + +size_t PageSize() { + static size_t PageSizeCached = sysconf(_SC_PAGESIZE); + return PageSizeCached; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_POSIX diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilWindows.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilWindows.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilWindows.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerUtilWindows.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,266 @@ +//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Misc utils implementation for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerPlatform.h" +#if LIBFUZZER_WINDOWS +#include "FuzzerCommand.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +// clang-format off +#include +// These must be included after windows.h. +// archicture need to be set before including +// libloaderapi +#include +#include +#include +// clang-format on + +namespace fuzzer { + +static const FuzzingOptions* HandlerOpt = nullptr; + +static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + case EXCEPTION_STACK_OVERFLOW: + if (HandlerOpt->HandleSegv) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + case EXCEPTION_IN_PAGE_ERROR: + if (HandlerOpt->HandleBus) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_PRIV_INSTRUCTION: + if (HandlerOpt->HandleIll) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_INT_OVERFLOW: + if (HandlerOpt->HandleFpe) + Fuzzer::StaticCrashSignalCallback(); + break; + // This is an undocumented exception code corresponding to a Visual C++ + // Exception. + // + // See: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273 + case 0xE06D7363: + if (HandlerOpt->HandleWinExcept) + Fuzzer::StaticCrashSignalCallback(); + break; + // TODO: Handle (Options.HandleXfsz) + } + return EXCEPTION_CONTINUE_SEARCH; +} + +BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { + switch (dwCtrlType) { + case CTRL_C_EVENT: + if (HandlerOpt->HandleInt) + Fuzzer::StaticInterruptCallback(); + return TRUE; + case CTRL_BREAK_EVENT: + if (HandlerOpt->HandleTerm) + Fuzzer::StaticInterruptCallback(); + return TRUE; + } + return FALSE; +} + +void CALLBACK AlarmHandler(PVOID, BOOLEAN) { + Fuzzer::StaticAlarmCallback(); +} + +class TimerQ { + HANDLE TimerQueue; + public: + TimerQ() : TimerQueue(NULL) {} + ~TimerQ() { + if (TimerQueue) + DeleteTimerQueueEx(TimerQueue, NULL); + } + void SetTimer(int Seconds) { + if (!TimerQueue) { + TimerQueue = CreateTimerQueue(); + if (!TimerQueue) { + Printf("libFuzzer: CreateTimerQueue failed.\n"); + exit(1); + } + } + HANDLE Timer; + if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, + Seconds*1000, Seconds*1000, 0)) { + Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); + exit(1); + } + } +}; + +static TimerQ Timer; + +static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } + +void SetSignalHandler(const FuzzingOptions& Options) { + HandlerOpt = &Options; + + if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) + Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); + + if (Options.HandleInt || Options.HandleTerm) + if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { + DWORD LastError = GetLastError(); + Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", + LastError); + exit(1); + } + + if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || + Options.HandleFpe || Options.HandleWinExcept) + SetUnhandledExceptionFilter(ExceptionHandler); + + if (Options.HandleAbrt) + if (SIG_ERR == signal(SIGABRT, CrashHandler)) { + Printf("libFuzzer: signal failed with %d\n", errno); + exit(1); + } +} + +void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } + +unsigned long GetPid() { return GetCurrentProcessId(); } + +size_t GetPeakRSSMb() { + PROCESS_MEMORY_COUNTERS info; + if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) + return 0; + return info.PeakWorkingSetSize >> 20; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return _popen(Command, Mode); +} + +int CloseProcessPipe(FILE *F) { + return _pclose(F); +} + +int ExecuteCommand(const Command &Cmd) { + std::string CmdLine = Cmd.toString(); + return system(CmdLine.c_str()); +} + +bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { + FILE *Pipe = _popen(Cmd.toString().c_str(), "r"); + if (!Pipe) + return false; + + if (CmdOutput) { + char TmpBuffer[128]; + while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) + CmdOutput->append(TmpBuffer); + } + return _pclose(Pipe) == 0; +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + // TODO: make this implementation more efficient. + const char *Cdata = (const char *)Data; + const char *Cpatt = (const char *)Patt; + + if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) + return NULL; + + if (PattLen == 1) + return memchr(Data, *Cpatt, DataLen); + + const char *End = Cdata + DataLen - PattLen + 1; + + for (const char *It = Cdata; It < End; ++It) + if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) + return It; + + return NULL; +} + +std::string DisassembleCmd(const std::string &FileName) { + std::vector command_vector; + command_vector.push_back("dumpbin /summary > nul"); + if (ExecuteCommand(Command(command_vector)) == 0) + return "dumpbin /disasm " + FileName; + Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n"); + exit(1); +} + +std::string SearchRegexCmd(const std::string &Regex) { + return "findstr /r \"" + Regex + "\""; +} + +void DiscardOutput(int Fd) { + FILE* Temp = fopen("nul", "w"); + if (!Temp) + return; + _dup2(_fileno(Temp), Fd); + fclose(Temp); +} + +size_t PageSize() { + static size_t PageSizeCached = []() -> size_t { + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; + }(); + return PageSizeCached; +} + +void SetThreadName(std::thread &thread, const std::string &name) { +#ifndef __MINGW32__ + // Not setting the thread name in MinGW environments. MinGW C++ standard + // libraries can either use native Windows threads or pthreads, so we + // don't know with certainty what kind of thread handle we're getting + // from thread.native_handle() here. + typedef HRESULT(WINAPI * proc)(HANDLE, PCWSTR); + HMODULE kbase = GetModuleHandleA("KernelBase.dll"); + proc ThreadNameProc = reinterpret_cast( + (void *)GetProcAddress(kbase, "SetThreadDescription")); + if (ThreadNameProc) { + std::wstring buf; + auto sz = MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, nullptr, 0); + if (sz > 0) { + buf.resize(sz); + if (MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, &buf[0], sz) > 0) { + (void)ThreadNameProc(thread.native_handle(), buf.c_str()); + } + } + } +#endif +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerValueBitMap.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerValueBitMap.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerValueBitMap.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/FuzzerValueBitMap.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,73 @@ +//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// ValueBitMap. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H +#define LLVM_FUZZER_VALUE_BIT_MAP_H + +#include "FuzzerPlatform.h" +#include + +namespace fuzzer { + +// A bit map containing kMapSizeInWords bits. +struct ValueBitMap { + static const size_t kMapSizeInBits = 1 << 16; + static const size_t kMapPrimeMod = 65371; // Largest Prime < kMapSizeInBits; + static const size_t kBitsInWord = (sizeof(uintptr_t) * 8); + static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord; + public: + + // Clears all bits. + void Reset() { memset(Map, 0, sizeof(Map)); } + + // Computes a hash function of Value and sets the corresponding bit. + // Returns true if the bit was changed from 0 to 1. + ATTRIBUTE_NO_SANITIZE_ALL + inline bool AddValue(uintptr_t Value) { + uintptr_t Idx = Value % kMapSizeInBits; + uintptr_t WordIdx = Idx / kBitsInWord; + uintptr_t BitIdx = Idx % kBitsInWord; + uintptr_t Old = Map[WordIdx]; + uintptr_t New = Old | (1ULL << BitIdx); + Map[WordIdx] = New; + return New != Old; + } + + ATTRIBUTE_NO_SANITIZE_ALL + inline bool AddValueModPrime(uintptr_t Value) { + return AddValue(Value % kMapPrimeMod); + } + + inline bool Get(uintptr_t Idx) { + assert(Idx < kMapSizeInBits); + uintptr_t WordIdx = Idx / kBitsInWord; + uintptr_t BitIdx = Idx % kBitsInWord; + return Map[WordIdx] & (1ULL << BitIdx); + } + + size_t SizeInBits() const { return kMapSizeInBits; } + + template + ATTRIBUTE_NO_SANITIZE_ALL + void ForEach(Callback CB) const { + for (size_t i = 0; i < kMapSizeInWords; i++) + if (uintptr_t M = Map[i]) + for (size_t j = 0; j < sizeof(M) * 8; j++) + if (M & ((uintptr_t)1 << j)) + CB(i * sizeof(M) * 8 + j); + } + + private: + ATTRIBUTE_ALIGNED(512) uintptr_t Map[kMapSizeInWords]; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_VALUE_BIT_MAP_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/README.txt clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/README.txt --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/README.txt 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/README.txt 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +See http://llvm.org/docs/LibFuzzer.html diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/afl/afl_driver.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/afl/afl_driver.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/afl/afl_driver.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/afl/afl_driver.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,267 @@ +//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +/* This file allows to fuzz libFuzzer-style target functions + (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. + +Usage: +################################################################################ +cat << EOF > test_fuzzer.cc +#include +#include +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > 0 && data[0] == 'H') + if (size > 1 && data[1] == 'I') + if (size > 2 && data[2] == '!') + __builtin_trap(); + return 0; +} +EOF +# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. +clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c +# Build afl-llvm-rt.o.c from the AFL distribution. +clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c +# Build this file, link it with afl-llvm-rt.o.o and the target code. +clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o +# Run AFL: +rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; +$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out +################################################################################ +AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file +specified. If the file does not exist, it is created. This is useful for getting +stack traces (when using ASAN for example) or original error messages on hard +to reproduce bugs. Note that any content written to stderr will be written to +this file instead of stderr's usual location. + +AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option. +If 1, close stdout at startup. If 2 close stderr; if 3 close both. + +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// Platform detection. Copied from FuzzerInternal.h +#ifdef __linux__ +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#elif __APPLE__ +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_APPLE 1 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 0 +#elif __NetBSD__ +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_NETBSD 1 +#define LIBFUZZER_FREEBSD 0 +#elif __FreeBSD__ +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_NETBSD 0 +#define LIBFUZZER_FREEBSD 1 +#else +#error "Support for your platform has not been implemented" +#endif + +// libFuzzer interface is thin, so we don't include any libFuzzer headers. +extern "C" { +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); +} + +// Notify AFL about persistent mode. +static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; +extern "C" int __afl_persistent_loop(unsigned int); +static volatile char suppress_warning2 = AFL_PERSISTENT[0]; + +// Notify AFL about deferred forkserver. +static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; +extern "C" void __afl_manual_init(); +static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; + +// Input buffer. +static const size_t kMaxAflInputSize = 1 << 20; +static uint8_t AflInputBuf[kMaxAflInputSize]; + +// Use this optionally defined function to output sanitizer messages even if +// user asks to close stderr. +extern "C" __attribute__((weak)) void __sanitizer_set_report_fd(void *); + +// Keep track of where stderr content is being written to, so that +// dup_and_close_stderr can use the correct one. +static FILE *output_file = stderr; + +// Experimental feature to use afl_driver without AFL's deferred mode. +// Needs to run before __afl_auto_init. +__attribute__((constructor(0))) static void __decide_deferred_forkserver(void) { + if (getenv("AFL_DRIVER_DONT_DEFER")) { + if (unsetenv("__AFL_DEFER_FORKSRV")) { + perror("Failed to unset __AFL_DEFER_FORKSRV"); + abort(); + } + } +} + +// If the user asks us to duplicate stderr, then do it. +static void maybe_duplicate_stderr() { + char *stderr_duplicate_filename = + getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); + + if (!stderr_duplicate_filename) + return; + + FILE *stderr_duplicate_stream = + freopen(stderr_duplicate_filename, "a+", stderr); + + if (!stderr_duplicate_stream) { + fprintf( + stderr, + "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); + abort(); + } + output_file = stderr_duplicate_stream; +} + +// Most of these I/O functions were inspired by/copied from libFuzzer's code. +static void discard_output(int fd) { + FILE *temp = fopen("/dev/null", "w"); + if (!temp) + abort(); + dup2(fileno(temp), fd); + fclose(temp); +} + +static void close_stdout() { discard_output(STDOUT_FILENO); } + +// Prevent the targeted code from writing to "stderr" but allow sanitizers and +// this driver to do so. +static void dup_and_close_stderr() { + int output_fileno = fileno(output_file); + int output_fd = dup(output_fileno); + if (output_fd <= 0) + abort(); + FILE *new_output_file = fdopen(output_fd, "w"); + if (!new_output_file) + abort(); + if (!__sanitizer_set_report_fd) + return; + __sanitizer_set_report_fd(reinterpret_cast(output_fd)); + discard_output(output_fileno); +} + +static void Printf(const char *Fmt, ...) { + va_list ap; + va_start(ap, Fmt); + vfprintf(output_file, Fmt, ap); + va_end(ap); + fflush(output_file); +} + +// Close stdout and/or stderr if user asks for it. +static void maybe_close_fd_mask() { + char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK"); + if (!fd_mask_str) + return; + int fd_mask = atoi(fd_mask_str); + if (fd_mask & 2) + dup_and_close_stderr(); + if (fd_mask & 1) + close_stdout(); +} + +// Define LLVMFuzzerMutate to avoid link failures for targets that use it +// with libFuzzer's LLVMFuzzerCustomMutator. +extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { + assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); + return 0; +} + +// Execute any files provided as parameters. +static int ExecuteFilesOnyByOne(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + std::ifstream in(argv[i], std::ios::binary); + in.seekg(0, in.end); + size_t length = in.tellg(); + in.seekg (0, in.beg); + std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; + // Allocate exactly length bytes so that we reliably catch buffer overflows. + std::vector bytes(length); + in.read(bytes.data(), bytes.size()); + assert(in); + LLVMFuzzerTestOneInput(reinterpret_cast(bytes.data()), + bytes.size()); + std::cout << "Execution successful" << std::endl; + } + return 0; +} + +int main(int argc, char **argv) { + Printf( + "======================= INFO =========================\n" + "This binary is built for AFL-fuzz.\n" + "To run the target function on individual input(s) execute this:\n" + " %s < INPUT_FILE\n" + "or\n" + " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" + "To fuzz with afl-fuzz execute this:\n" + " afl-fuzz [afl-flags] %s [-N]\n" + "afl-fuzz will run N iterations before " + "re-spawning the process (default: 1000)\n" + "======================================================\n", + argv[0], argv[0], argv[0]); + + maybe_duplicate_stderr(); + maybe_close_fd_mask(); + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + // Do any other expensive one-time initialization here. + + if (!getenv("AFL_DRIVER_DONT_DEFER")) + __afl_manual_init(); + + int N = 1000; + if (argc == 2 && argv[1][0] == '-') + N = atoi(argv[1] + 1); + else if(argc == 2 && (N = atoi(argv[1])) > 0) + Printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); + else if (argc > 1) + return ExecuteFilesOnyByOne(argc, argv); + + assert(N > 0); + + // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization + // on the first execution of LLVMFuzzerTestOneInput is ignored. + uint8_t dummy_input[1] = {0}; + LLVMFuzzerTestOneInput(dummy_input, 1); + + int num_runs = 0; + while (__afl_persistent_loop(N)) { + ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); + if (n_read > 0) { + // Copy AflInputBuf into a separate buffer to let asan find buffer + // overflows. Don't use unique_ptr/etc to avoid extra dependencies. + uint8_t *copy = new uint8_t[n_read]; + memcpy(copy, AflInputBuf, n_read); + num_runs++; + LLVMFuzzerTestOneInput(copy, n_read); + delete[] copy; + } + } + Printf("%s: successfully executed %d input(s)\n", argv[0], num_runs); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/build.sh clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/build.sh --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/build.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/build.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +#!/bin/sh +LIBFUZZER_SRC_DIR=$(dirname $0) +CXX="${CXX:-clang}" +for f in $LIBFUZZER_SRC_DIR/*.cpp; do + $CXX -g -O2 -fno-omit-frame-pointer -std=c++17 $f -c & +done +wait +rm -f libFuzzer.a +ar r libFuzzer.a Fuzzer*.o +rm -f Fuzzer*.o + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,205 @@ +/*===- DataFlow.cpp - a standalone DataFlow tracer -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// An experimental data-flow tracer for fuzz targets. +// It is based on DFSan and SanitizerCoverage. +// https://clang.llvm.org/docs/DataFlowSanitizer.html +// https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow +// +// It executes the fuzz target on the given input while monitoring the +// data flow for every instrumented comparison instruction. +// +// The output shows which functions depend on which bytes of the input, +// and also provides basic-block coverage for every input. +// +// Build: +// 1. Compile this file (DataFlow.cpp) with -fsanitize=dataflow and -O2. +// 2. Compile DataFlowCallbacks.cpp with -O2 -fPIC. +// 3. Build the fuzz target with -g -fsanitize=dataflow +// -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp +// 4. Link those together with -fsanitize=dataflow +// +// -fsanitize-coverage=trace-cmp inserts callbacks around every comparison +// instruction, DFSan modifies the calls to pass the data flow labels. +// The callbacks update the data flow label for the current function. +// See e.g. __dfsw___sanitizer_cov_trace_cmp1 below. +// +// -fsanitize-coverage=trace-pc-guard,pc-table,bb instruments function +// entries so that the comparison callback knows that current function. +// -fsanitize-coverage=...,bb also allows to collect basic block coverage. +// +// +// Run: +// # Collect data flow and coverage for INPUT_FILE +// # write to OUTPUT_FILE (default: stdout) +// export DFSAN_OPTIONS=warn_unimplemented=0 +// ./a.out INPUT_FILE [OUTPUT_FILE] +// +// # Print all instrumented functions. llvm-symbolizer must be present in PATH +// ./a.out +// +// Example output: +// =============== +// F0 11111111111111 +// F1 10000000000000 +// C0 1 2 3 4 5 +// C1 8 +// =============== +// "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on. +// "CN X Y Z T": tells that a function N has basic blocks X, Y, and Z covered +// in addition to the function's entry block, out of T total instrumented +// blocks. +// +//===----------------------------------------------------------------------===*/ + +#include +#include +#include +#include +#include + +#include // backtrace_symbols_fd + +#include "DataFlow.h" + +extern "C" { +extern int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); +} // extern "C" + +CallbackData __dft; +static size_t InputLen; +static size_t NumIterations; +static dfsan_label **FuncLabelsPerIter; // NumIterations x NumFuncs; + +static inline bool BlockIsEntry(size_t BlockIdx) { + return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY; +} + +const int kNumLabels = 8; + +// Prints all instrumented functions. +static int PrintFunctions() { + // We don't have the symbolizer integrated with dfsan yet. + // So use backtrace_symbols_fd and pipe it through llvm-symbolizer. + // TODO(kcc): this is pretty ugly and may break in lots of ways. + // We'll need to make a proper in-process symbolizer work with DFSan. + FILE *Pipe = popen("sed 's/(+/ /g; s/).*//g' " + "| llvm-symbolizer " + "| grep '\\.dfsan' " + "| sed 's/\\.dfsan//g' " + "| c++filt", + "w"); + for (size_t I = 0; I < __dft.NumGuards; I++) { + uintptr_t PC = __dft.PCsBeg[I * 2]; + if (!BlockIsEntry(I)) continue; + void *const Buf[1] = {(void*)PC}; + backtrace_symbols_fd(Buf, 1, fileno(Pipe)); + } + pclose(Pipe); + return 0; +} + +static void PrintBinary(FILE *Out, dfsan_label L, size_t Len) { + char buf[kNumLabels + 1]; + assert(Len <= kNumLabels); + for (int i = 0; i < kNumLabels; i++) + buf[i] = (L & (1 << i)) ? '1' : '0'; + buf[Len] = 0; + fprintf(Out, "%s", buf); +} + +static void PrintDataFlow(FILE *Out) { + for (size_t Func = 0; Func < __dft.NumFuncs; Func++) { + bool HasAny = false; + for (size_t Iter = 0; Iter < NumIterations; Iter++) + if (FuncLabelsPerIter[Iter][Func]) + HasAny = true; + if (!HasAny) + continue; + fprintf(Out, "F%zd ", Func); + size_t LenOfLastIteration = kNumLabels; + if (auto Tail = InputLen % kNumLabels) + LenOfLastIteration = Tail; + for (size_t Iter = 0; Iter < NumIterations; Iter++) + PrintBinary(Out, FuncLabelsPerIter[Iter][Func], + Iter == NumIterations - 1 ? LenOfLastIteration : kNumLabels); + fprintf(Out, "\n"); + } +} + +static void PrintCoverage(FILE *Out) { + ssize_t CurrentFuncGuard = -1; + ssize_t CurrentFuncNum = -1; + ssize_t NumBlocksInCurrentFunc = -1; + for (size_t FuncBeg = 0; FuncBeg < __dft.NumGuards;) { + CurrentFuncNum++; + assert(BlockIsEntry(FuncBeg)); + size_t FuncEnd = FuncBeg + 1; + for (; FuncEnd < __dft.NumGuards && !BlockIsEntry(FuncEnd); FuncEnd++) + ; + if (__dft.BBExecuted[FuncBeg]) { + fprintf(Out, "C%zd", CurrentFuncNum); + for (size_t I = FuncBeg + 1; I < FuncEnd; I++) + if (__dft.BBExecuted[I]) + fprintf(Out, " %zd", I - FuncBeg); + fprintf(Out, " %zd\n", FuncEnd - FuncBeg); + } + FuncBeg = FuncEnd; + } +} + +int main(int argc, char **argv) { + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + if (argc == 1) + return PrintFunctions(); + assert(argc == 2 || argc == 3); + + const char *Input = argv[1]; + fprintf(stderr, "INFO: reading '%s'\n", Input); + FILE *In = fopen(Input, "r"); + assert(In); + fseek(In, 0, SEEK_END); + InputLen = ftell(In); + fseek(In, 0, SEEK_SET); + unsigned char *Buf = (unsigned char*)malloc(InputLen); + size_t NumBytesRead = fread(Buf, 1, InputLen, In); + assert(NumBytesRead == InputLen); + fclose(In); + + NumIterations = (NumBytesRead + kNumLabels - 1) / kNumLabels; + FuncLabelsPerIter = + (dfsan_label **)calloc(NumIterations, sizeof(dfsan_label *)); + for (size_t Iter = 0; Iter < NumIterations; Iter++) + FuncLabelsPerIter[Iter] = + (dfsan_label *)calloc(__dft.NumFuncs, sizeof(dfsan_label)); + + for (size_t Iter = 0; Iter < NumIterations; Iter++) { + fprintf(stderr, "INFO: running '%s' %zd/%zd\n", Input, Iter, NumIterations); + dfsan_flush(); + dfsan_set_label(0, Buf, InputLen); + __dft.FuncLabels = FuncLabelsPerIter[Iter]; + + size_t BaseIdx = Iter * kNumLabels; + size_t LastIdx = BaseIdx + kNumLabels < NumBytesRead ? BaseIdx + kNumLabels + : NumBytesRead; + assert(BaseIdx < LastIdx); + for (size_t Idx = BaseIdx; Idx < LastIdx; Idx++) + dfsan_set_label(1 << (Idx - BaseIdx), Buf + Idx, 1); + LLVMFuzzerTestOneInput(Buf, InputLen); + } + free(Buf); + + bool OutIsStdout = argc == 2; + fprintf(stderr, "INFO: writing dataflow to %s\n", + OutIsStdout ? "" : argv[2]); + FILE *Out = OutIsStdout ? stdout : fopen(argv[2], "w"); + PrintDataFlow(Out); + PrintCoverage(Out); + if (!OutIsStdout) fclose(Out); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.h clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.h --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlow.h 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +/*===- DataFlow.h - a standalone DataFlow trace -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Internal header file to connect DataFlow.cpp and DataFlowCallbacks.cpp. +//===----------------------------------------------------------------------===*/ + +#ifndef __LIBFUZZER_DATAFLOW_H +#define __LIBFUZZER_DATAFLOW_H + +#include +#include +#include + +// This data is shared between DataFlowCallbacks.cpp and DataFlow.cpp. +struct CallbackData { + size_t NumFuncs, NumGuards; + const uintptr_t *PCsBeg, *PCsEnd; + dfsan_label *FuncLabels; // Array of NumFuncs elements. + bool *BBExecuted; // Array of NumGuards elements. +}; + +extern CallbackData __dft; + +enum { + PCFLAG_FUNC_ENTRY = 1, +}; + +#endif // __LIBFUZZER_DATAFLOW_H diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlowCallbacks.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlowCallbacks.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlowCallbacks.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/dataflow/DataFlowCallbacks.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +/*===- DataFlowCallbacks.cpp - a standalone DataFlow trace -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Instrumentation callbacks for DataFlow.cpp. +// These functions should not be instrumented by DFSan, so we +// keep them in a separate file and compile it w/o DFSan. +//===----------------------------------------------------------------------===*/ +#include "DataFlow.h" + +#include +#include +#include + +static __thread size_t CurrentFunc; +static uint32_t *GuardsBeg, *GuardsEnd; +static inline bool BlockIsEntry(size_t BlockIdx) { + return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY; +} + +extern "C" { + +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, + uint32_t *stop) { + assert(__dft.NumFuncs == 0 && "This tool does not support DSOs"); + assert(start < stop && "The code is not instrumented for coverage"); + if (start == stop || *start) return; // Initialize only once. + GuardsBeg = start; + GuardsEnd = stop; +} + +void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, + const uintptr_t *pcs_end) { + if (__dft.NumGuards) return; // Initialize only once. + __dft.NumGuards = GuardsEnd - GuardsBeg; + __dft.PCsBeg = pcs_beg; + __dft.PCsEnd = pcs_end; + assert(__dft.NumGuards == (__dft.PCsEnd - __dft.PCsBeg) / 2); + for (size_t i = 0; i < __dft.NumGuards; i++) { + if (BlockIsEntry(i)) { + __dft.NumFuncs++; + GuardsBeg[i] = __dft.NumFuncs; + } + } + __dft.BBExecuted = (bool*)calloc(__dft.NumGuards, sizeof(bool)); + fprintf(stderr, "INFO: %zd instrumented function(s) observed " + "and %zd basic blocks\n", __dft.NumFuncs, __dft.NumGuards); +} + +void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused. + +void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { + size_t GuardIdx = guard - GuardsBeg; + // assert(GuardIdx < __dft.NumGuards); + __dft.BBExecuted[GuardIdx] = true; + if (!*guard) return; // not a function entry. + uint32_t FuncNum = *guard - 1; // Guards start from 1. + // assert(FuncNum < __dft.NumFuncs); + CurrentFunc = FuncNum; +} + +void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, + dfsan_label L1, dfsan_label UnusedL) { + assert(CurrentFunc < __dft.NumFuncs); + __dft.FuncLabels[CurrentFunc] |= L1; +} + +#define HOOK(Name, Type) \ + void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \ + __dft.FuncLabels[CurrentFunc] |= L1 | L2; \ + } + //assert(CurrentFunc < __dft.NumFuncs); + +HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t) +HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t) +HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t) +HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t) +HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t) +HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t) +HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t) +HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t) + +} // extern "C" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/scripts/unbalanced_allocs.py clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/scripts/unbalanced_allocs.py --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/scripts/unbalanced_allocs.py 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/scripts/unbalanced_allocs.py 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# ===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===------------------------------------------------------------------------===# +# +# Post-process -trace_malloc=2 output and printout only allocations and frees +# unbalanced inside of fuzzer runs. +# Usage: +# my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5 +# +# ===------------------------------------------------------------------------===# + +import argparse +import sys + +_skip = 0 + + +def PrintStack(line, stack): + global _skip + if _skip > 0: + return + print("Unbalanced " + line.rstrip()) + for l in stack: + print(l.rstrip()) + + +def ProcessStack(line, f): + stack = [] + while line and line.startswith(" #"): + stack += [line] + line = f.readline() + return line, stack + + +def ProcessFree(line, f, allocs): + if not line.startswith("FREE["): + return f.readline() + + addr = int(line.split()[1], 16) + next_line, stack = ProcessStack(f.readline(), f) + if addr in allocs: + del allocs[addr] + else: + PrintStack(line, stack) + return next_line + + +def ProcessMalloc(line, f, allocs): + if not line.startswith("MALLOC["): + return ProcessFree(line, f, allocs) + + addr = int(line.split()[1], 16) + assert not addr in allocs + + next_line, stack = ProcessStack(f.readline(), f) + allocs[addr] = (line, stack) + return next_line + + +def ProcessRun(line, f): + if not line.startswith("MallocFreeTracer: START"): + return ProcessMalloc(line, f, {}) + + allocs = {} + print(line.rstrip()) + line = f.readline() + while line: + if line.startswith("MallocFreeTracer: STOP"): + global _skip + _skip = _skip - 1 + for _, (l, s) in allocs.items(): + PrintStack(l, s) + print(line.rstrip()) + return f.readline() + line = ProcessMalloc(line, f, allocs) + return line + + +def ProcessFile(f): + line = f.readline() + while line: + line = ProcessRun(line, f) + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument("--skip", default=0, help="number of runs to ignore") + args = parser.parse_args() + global _skip + _skip = int(args.skip) + 1 + ProcessFile(sys.stdin) + + +if __name__ == "__main__": + main(sys.argv) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/standalone/StandaloneFuzzTargetMain.c clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/standalone/StandaloneFuzzTargetMain.c --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/standalone/StandaloneFuzzTargetMain.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/standalone/StandaloneFuzzTargetMain.c 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This main() function can be linked to a fuzz target (i.e. a library +// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) +// instead of libFuzzer. This main() function will not perform any fuzzing +// but will simply feed all input files one by one to the fuzz target. +// +// Use this file to provide reproducers for bugs when linking against libFuzzer +// or other fuzzing engine is undesirable. +//===----------------------------------------------------------------------===*/ +#include +#include +#include + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); +int main(int argc, char **argv) { + fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + for (int i = 1; i < argc; i++) { + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char*)malloc(len); + size_t n_read = fread(buf, 1, len, f); + fclose(f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/CMakeLists.txt clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/CMakeLists.txt --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/CMakeLists.txt 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +include(CompilerRTCompile) + +set(LIBFUZZER_UNITTEST_CFLAGS + ${COMPILER_RT_UNITTEST_CFLAGS} + ${COMPILER_RT_GTEST_CFLAGS} + -I${COMPILER_RT_SOURCE_DIR}/lib/fuzzer + -fno-rtti + -O2) + +if (APPLE) + set(FUZZER_SUPPORTED_OS osx) +endif() + +add_custom_target(FuzzerUnitTests) +set_target_properties(FuzzerUnitTests PROPERTIES FOLDER "Compiler-RT/Tests") + +add_custom_target(FuzzedDataProviderUnitTests) +set_target_properties(FuzzedDataProviderUnitTests PROPERTIES FOLDER "Compiler-RT/Tests") + +set(LIBFUZZER_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS}) +list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS --driver-mode=g++) + +if(MSVC) + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -Wl,-defaultlib:libcmt,-defaultlib:oldnames) +else() + if (APPLE) + list(APPEND LIBFUZZER_UNITTEST_CFLAGS -isysroot ${DARWIN_osx_SYSROOT}) + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -isysroot ${DARWIN_osx_SYSROOT}) + endif() + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lpthread) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND + COMPILER_RT_LIBCXX_PATH AND + COMPILER_RT_LIBCXXABI_PATH) + list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++ -fno-exceptions) + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -nostdlib++ -fno-exceptions) +endif() + +if ("-fvisibility=hidden" IN_LIST LIBFUZZER_CFLAGS) + # Match visibility settings. + list(APPEND LIBFUZZER_UNITTEST_CFLAGS "-fvisibility=hidden") +endif() + +if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) + # libFuzzer unit tests are only run on the host machine. + set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) + + set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch}) + if(APPLE) + set(LIBFUZZER_TEST_RUNTIME_OBJECTS + $) + else() + set(LIBFUZZER_TEST_RUNTIME_OBJECTS + $) + endif() + add_library(${LIBFUZZER_TEST_RUNTIME} STATIC + ${LIBFUZZER_TEST_RUNTIME_OBJECTS}) + set_target_properties(${LIBFUZZER_TEST_RUNTIME} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + FOLDER "Compiler-RT/Tests/Runtime") + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND + COMPILER_RT_LIBCXX_PATH AND + COMPILER_RT_LIBCXXABI_PATH) + file(GLOB libfuzzer_headers ../*.h) + set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}-install-cmake326-workaround ${libfuzzer_headers}) + set(LIBFUZZER_TEST_RUNTIME_CFLAGS -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) + set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS ${LIBCXX_${arch}_PREFIX}/lib/libc++.a) + endif() + + set(FuzzerTestObjects) + generate_compiler_rt_tests(FuzzerTestObjects + FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} + SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} + RUNTIME ${LIBFUZZER_TEST_RUNTIME} + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} + CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} + LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) + set_target_properties(FuzzerUnitTests PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + set(FuzzedDataProviderTestObjects) + generate_compiler_rt_tests(FuzzedDataProviderTestObjects + FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} + SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h + CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} + LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) + set_target_properties(FuzzedDataProviderUnitTests PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +endif() diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzedDataProviderUnittest.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzedDataProviderUnittest.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzedDataProviderUnittest.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzedDataProviderUnittest.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,450 @@ +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "gtest/gtest.h" +#include +#include + +#include + +// The test is intentionally extensive, as behavior of |FuzzedDataProvider| must +// not be broken, given than many fuzz targets depend on it. Changing the +// behavior might invalidate existing corpora and make the fuzz targets using +// |FuzzedDataProvider| to lose code coverage accumulated over time. + +/* A random 1KB buffer generated by: +$ python -c "import os; print ',\n'.join([', '.join(['0x%02X' % ord(i) for i \ + in list(os.urandom(8))]) for _ in xrange(128)])" +*/ +const uint8_t Data[] = { + 0x8A, 0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, 0x9B, 0xAA, 0xF3, 0xDA, + 0xAA, 0x88, 0xF2, 0x9B, 0x6C, 0xBA, 0xBE, 0xB1, 0xF2, 0xCF, 0x13, 0xB8, + 0xAC, 0x1A, 0x7F, 0x1C, 0xC9, 0x90, 0xD0, 0xD9, 0x5C, 0x42, 0xB3, 0xFD, + 0xE3, 0x05, 0xA4, 0x03, 0x37, 0x49, 0x50, 0x4B, 0xBC, 0x39, 0xA2, 0x09, + 0x6C, 0x2F, 0xAF, 0xD1, 0xB5, 0x47, 0xBF, 0x92, 0xBD, 0x79, 0xE5, 0xC5, + 0x6E, 0x51, 0xA4, 0xED, 0xE9, 0xBD, 0x40, 0x4A, 0xFC, 0x25, 0x7A, 0x27, + 0xC8, 0x92, 0xF7, 0x30, 0xDE, 0x40, 0x66, 0x66, 0xE8, 0x5F, 0x65, 0x39, + 0x7E, 0x9E, 0x80, 0x2B, 0x01, 0x71, 0x2A, 0xFF, 0xD3, 0x0A, 0xAC, 0x6E, + 0x49, 0x32, 0x79, 0x10, 0x6A, 0x6F, 0x97, 0x96, 0x70, 0x7E, 0x50, 0x65, + 0xC9, 0x1D, 0xBD, 0x4E, 0x17, 0x04, 0x1E, 0xBA, 0x26, 0xAC, 0x1F, 0xE3, + 0x37, 0x1C, 0x15, 0x43, 0x60, 0x41, 0x2A, 0x7C, 0xCA, 0x70, 0xCE, 0xAB, + 0x20, 0x24, 0xF8, 0xD9, 0x1F, 0x14, 0x7C, 0x5C, 0xDD, 0x6F, 0xB3, 0xD7, + 0x8B, 0x63, 0x10, 0xB7, 0xDA, 0x99, 0xAF, 0x99, 0x01, 0x21, 0xE6, 0xE1, + 0x86, 0x27, 0xBE, 0x8D, 0xDF, 0x1E, 0xEA, 0x80, 0x0B, 0x8A, 0x60, 0xC3, + 0x3A, 0x85, 0x33, 0x53, 0x59, 0xE1, 0xB5, 0xF1, 0x62, 0xA6, 0x7B, 0x24, + 0x94, 0xE3, 0x8C, 0x10, 0x93, 0xF8, 0x6E, 0xC2, 0x00, 0x91, 0x90, 0x0B, + 0x5D, 0x52, 0x4F, 0x21, 0xE3, 0x40, 0x3A, 0x6E, 0xB6, 0x32, 0x15, 0xDB, + 0x5D, 0x01, 0x86, 0x63, 0x83, 0x24, 0xC5, 0xDE, 0xAB, 0x31, 0x84, 0xAA, + 0xE5, 0x64, 0x02, 0x8D, 0x23, 0x82, 0x86, 0x14, 0x16, 0x18, 0x9F, 0x3D, + 0x31, 0xBE, 0x3B, 0xF0, 0x6C, 0x26, 0x42, 0x9A, 0x67, 0xFE, 0x28, 0xEC, + 0x28, 0xDB, 0x01, 0xB4, 0x52, 0x41, 0x81, 0x7C, 0x54, 0xD3, 0xC8, 0x00, + 0x01, 0x66, 0xB0, 0x2C, 0x3F, 0xBC, 0xAF, 0xAC, 0x87, 0xCD, 0x83, 0xCF, + 0x23, 0xFC, 0xC8, 0x97, 0x8C, 0x71, 0x32, 0x8B, 0xBF, 0x70, 0xC0, 0x48, + 0x31, 0x92, 0x18, 0xFE, 0xE5, 0x33, 0x48, 0x82, 0x98, 0x1E, 0x30, 0xCC, + 0xAD, 0x5D, 0x97, 0xC4, 0xB4, 0x39, 0x7C, 0xCD, 0x39, 0x44, 0xF1, 0xA9, + 0xD0, 0xF4, 0x27, 0xB7, 0x78, 0x85, 0x9E, 0x72, 0xFC, 0xCC, 0xEE, 0x98, + 0x25, 0x3B, 0x69, 0x6B, 0x0C, 0x11, 0xEA, 0x22, 0xB6, 0xD0, 0xCD, 0xBF, + 0x6D, 0xBE, 0x12, 0xDE, 0xFE, 0x78, 0x2E, 0x54, 0xCB, 0xBA, 0xD7, 0x2E, + 0x54, 0x25, 0x14, 0x84, 0xFE, 0x1A, 0x10, 0xCE, 0xCC, 0x20, 0xE6, 0xE2, + 0x7F, 0xE0, 0x5F, 0xDB, 0xA7, 0xF3, 0xE2, 0x4C, 0x52, 0x82, 0xFC, 0x0B, + 0xA0, 0xBD, 0x34, 0x21, 0xF7, 0xEB, 0x1C, 0x5B, 0x67, 0xD0, 0xAF, 0x22, + 0x15, 0xA1, 0xFF, 0xC2, 0x68, 0x25, 0x5B, 0xB2, 0x13, 0x3F, 0xFF, 0x98, + 0x53, 0x25, 0xC5, 0x58, 0x39, 0xD0, 0x43, 0x86, 0x6C, 0x5B, 0x57, 0x8E, + 0x83, 0xBA, 0xB9, 0x09, 0x09, 0x14, 0x0C, 0x9E, 0x99, 0x83, 0x88, 0x53, + 0x79, 0xFD, 0xF7, 0x49, 0xE9, 0x2C, 0xCE, 0xE6, 0x7B, 0xF5, 0xC2, 0x27, + 0x5E, 0x56, 0xB5, 0xB4, 0x46, 0x90, 0x91, 0x7F, 0x99, 0x88, 0xA7, 0x23, + 0xC1, 0x80, 0xB8, 0x2D, 0xCD, 0xF7, 0x6F, 0x9A, 0xEC, 0xBD, 0x16, 0x9F, + 0x7D, 0x87, 0x1E, 0x15, 0x51, 0xC4, 0x96, 0xE2, 0xBF, 0x61, 0x66, 0xB5, + 0xFD, 0x01, 0x67, 0xD6, 0xFF, 0xD2, 0x14, 0x20, 0x98, 0x8E, 0xEF, 0xF3, + 0x22, 0xDB, 0x7E, 0xCE, 0x70, 0x2D, 0x4C, 0x06, 0x5A, 0xA0, 0x4F, 0xC8, + 0xB0, 0x4D, 0xA6, 0x52, 0xB2, 0xD6, 0x2F, 0xD8, 0x57, 0xE5, 0xEF, 0xF9, + 0xEE, 0x52, 0x0F, 0xEC, 0xC4, 0x90, 0x33, 0xAD, 0x25, 0xDA, 0xCD, 0x12, + 0x44, 0x5F, 0x32, 0xF6, 0x6F, 0xEF, 0x85, 0xB8, 0xDC, 0x3C, 0x01, 0x48, + 0x28, 0x5D, 0x2D, 0x9C, 0x9B, 0xC0, 0x49, 0x36, 0x1E, 0x6A, 0x0A, 0x0C, + 0xB0, 0x6E, 0x81, 0x89, 0xCB, 0x0A, 0x89, 0xCF, 0x73, 0xC6, 0x63, 0x3D, + 0x8E, 0x13, 0x57, 0x91, 0x4E, 0xA3, 0x93, 0x8C, 0x61, 0x67, 0xFD, 0x13, + 0xE0, 0x14, 0x72, 0xB3, 0xE4, 0x23, 0x45, 0x08, 0x4E, 0x4E, 0xF5, 0xA7, + 0xA8, 0xEE, 0x30, 0xFD, 0x81, 0x80, 0x1F, 0xF3, 0x4F, 0xD7, 0xE7, 0xF2, + 0x16, 0xC0, 0xD6, 0x15, 0x6A, 0x0F, 0x89, 0x15, 0xA9, 0xCF, 0x35, 0x50, + 0x6B, 0x49, 0x3E, 0x12, 0x4A, 0x72, 0xE4, 0x59, 0x9D, 0xD7, 0xDB, 0xD2, + 0xD1, 0x61, 0x7D, 0x52, 0x4A, 0x36, 0xF6, 0xBA, 0x0E, 0xFA, 0x88, 0x6F, + 0x3C, 0x82, 0x16, 0xF0, 0xD5, 0xED, 0x4D, 0x78, 0xEF, 0x38, 0x17, 0x90, + 0xEA, 0x28, 0x32, 0xA9, 0x79, 0x40, 0xFF, 0xAA, 0xE6, 0xF5, 0xC7, 0x96, + 0x56, 0x65, 0x61, 0x83, 0x3D, 0xBD, 0xD7, 0xED, 0xD6, 0xB6, 0xC0, 0xED, + 0x34, 0xAA, 0x60, 0xA9, 0xE8, 0x82, 0x78, 0xEA, 0x69, 0xF6, 0x47, 0xAF, + 0x39, 0xAB, 0x11, 0xDB, 0xE9, 0xFB, 0x68, 0x0C, 0xFE, 0xDF, 0x97, 0x9F, + 0x3A, 0xF4, 0xF3, 0x32, 0x27, 0x30, 0x57, 0x0E, 0xF7, 0xB2, 0xEE, 0xFB, + 0x1E, 0x98, 0xA8, 0xA3, 0x25, 0x45, 0xE4, 0x6D, 0x2D, 0xAE, 0xFE, 0xDA, + 0xB3, 0x32, 0x9B, 0x5D, 0xF5, 0x32, 0x74, 0xEA, 0xE5, 0x02, 0x30, 0x53, + 0x95, 0x13, 0x7A, 0x23, 0x1F, 0x10, 0x30, 0xEA, 0x78, 0xE4, 0x36, 0x1D, + 0x92, 0x96, 0xB9, 0x91, 0x2D, 0xFA, 0x43, 0xAB, 0xE6, 0xEF, 0x14, 0x14, + 0xC9, 0xBC, 0x46, 0xC6, 0x05, 0x7C, 0xC6, 0x11, 0x23, 0xCF, 0x3D, 0xC8, + 0xBE, 0xEC, 0xA3, 0x58, 0x31, 0x55, 0x65, 0x14, 0xA7, 0x94, 0x93, 0xDD, + 0x2D, 0x76, 0xC9, 0x66, 0x06, 0xBD, 0xF5, 0xE7, 0x30, 0x65, 0x42, 0x52, + 0xA2, 0x50, 0x9B, 0xE6, 0x40, 0xA2, 0x4B, 0xEC, 0xA6, 0xB7, 0x39, 0xAA, + 0xD7, 0x61, 0x2C, 0xBF, 0x37, 0x5A, 0xDA, 0xB3, 0x5D, 0x2F, 0x5D, 0x11, + 0x82, 0x97, 0x32, 0x8A, 0xC1, 0xA1, 0x13, 0x20, 0x17, 0xBD, 0xA2, 0x91, + 0x94, 0x2A, 0x4E, 0xBE, 0x3E, 0x77, 0x63, 0x67, 0x5C, 0x0A, 0xE1, 0x22, + 0x0A, 0x4F, 0x63, 0xE2, 0x84, 0xE9, 0x9F, 0x14, 0x86, 0xE2, 0x4B, 0x20, + 0x9F, 0x50, 0xB3, 0x56, 0xED, 0xDE, 0x39, 0xD8, 0x75, 0x64, 0x45, 0x54, + 0xE5, 0x34, 0x57, 0x8C, 0x3B, 0xF2, 0x0E, 0x94, 0x1B, 0x10, 0xA2, 0xA2, + 0x38, 0x76, 0x21, 0x8E, 0x2A, 0x57, 0x64, 0x58, 0x0A, 0x27, 0x6D, 0x4C, + 0xD0, 0xB5, 0xC1, 0xFC, 0x75, 0xD0, 0x01, 0x86, 0x66, 0xA8, 0xF1, 0x98, + 0x58, 0xFB, 0xFC, 0x64, 0xD2, 0x31, 0x77, 0xAD, 0x0E, 0x46, 0x87, 0xCC, + 0x9B, 0x86, 0x90, 0xFF, 0xB6, 0x64, 0x35, 0xA5, 0x5D, 0x9E, 0x44, 0x51, + 0x87, 0x9E, 0x1E, 0xEE, 0xF3, 0x3B, 0x5C, 0xDD, 0x94, 0x03, 0xAA, 0x18, + 0x2C, 0xB7, 0xC4, 0x37, 0xD5, 0x53, 0x28, 0x60, 0xEF, 0x77, 0xEF, 0x3B, + 0x9E, 0xD2, 0xCE, 0xE9, 0x53, 0x2D, 0xF5, 0x19, 0x7E, 0xBB, 0xB5, 0x46, + 0xE2, 0xF7, 0xD6, 0x4D, 0x6D, 0x5B, 0x81, 0x56, 0x6B, 0x12, 0x55, 0x63, + 0xC3, 0xAB, 0x08, 0xBB, 0x2E, 0xD5, 0x11, 0xBC, 0x18, 0xCB, 0x8B, 0x12, + 0x2E, 0x3E, 0x75, 0x32, 0x98, 0x8A, 0xDE, 0x3C, 0xEA, 0x33, 0x46, 0xE7, + 0x7A, 0xA5, 0x12, 0x09, 0x26, 0x7E, 0x7E, 0x03, 0x4F, 0xFD, 0xC0, 0xFD, + 0xEA, 0x4F, 0x83, 0x85, 0x39, 0x62, 0xFB, 0xA2, 0x33, 0xD9, 0x2D, 0xB1, + 0x30, 0x6F, 0x88, 0xAB, 0x61, 0xCB, 0x32, 0xEB, 0x30, 0xF9, 0x51, 0xF6, + 0x1F, 0x3A, 0x11, 0x4D, 0xFD, 0x54, 0xD6, 0x3D, 0x43, 0x73, 0x39, 0x16, + 0xCF, 0x3D, 0x29, 0x4A}; + +TEST(FuzzedDataProvider, ConsumeBytes) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::vector(1, 0x8A), + DataProv.ConsumeBytes(1)); + EXPECT_EQ(std::vector( + {0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, 0x9B, 0xAA, 0xF3}), + DataProv.ConsumeBytes(10)); + + std::vector UChars = DataProv.ConsumeBytes(24); + EXPECT_EQ(std::vector({0xDA, 0xAA, 0x88, 0xF2, 0x9B, 0x6C, + 0xBA, 0xBE, 0xB1, 0xF2, 0xCF, 0x13, + 0xB8, 0xAC, 0x1A, 0x7F, 0x1C, 0xC9, + 0x90, 0xD0, 0xD9, 0x5C, 0x42, 0xB3}), + UChars); + + EXPECT_EQ(std::vector(Data + 1 + 10 + 24, Data + sizeof(Data)), + DataProv.ConsumeBytes(31337)); +} + +TEST(FuzzedDataProvider, ConsumeBytesWithTerminator) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::vector({0x8A, 0x00}), + DataProv.ConsumeBytesWithTerminator(1)); + EXPECT_EQ(std::vector({0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, + 0x9B, 0xAA, 0xF3, 111}), + DataProv.ConsumeBytesWithTerminator(10, 111)); + + std::vector UChars = + DataProv.ConsumeBytesWithTerminator(24); + EXPECT_EQ(std::vector( + {0xDA, 0xAA, 0x88, 0xF2, 0x9B, 0x6C, 0xBA, 0xBE, 0xB1, + 0xF2, 0xCF, 0x13, 0xB8, 0xAC, 0x1A, 0x7F, 0x1C, 0xC9, + 0x90, 0xD0, 0xD9, 0x5C, 0x42, 0xB3, 0x00}), + UChars); + + std::vector Expected(Data + 1 + 10 + 24, Data + sizeof(Data)); + Expected.push_back(65); + EXPECT_EQ(Expected, + DataProv.ConsumeBytesWithTerminator(31337, 65)); +} + +TEST(FuzzedDataProvider, ConsumeBytesAsString) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::string("\x8A\x19\x0D\x44\x37\x0D\x38\x5E\x9B\xAA\xF3\xDA"), + DataProv.ConsumeBytesAsString(12)); + EXPECT_EQ(std::string(Data + 12, Data + sizeof(Data)), + DataProv.ConsumeBytesAsString(31337)); +} + +TEST(FuzzedDataProvider, ConsumeIntegralInRange) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(int32_t(21), DataProv.ConsumeIntegralInRange(10, 30)); + EXPECT_EQ(int32_t(1337), + DataProv.ConsumeIntegralInRange(1337, 1337)); + EXPECT_EQ(int8_t(-59), DataProv.ConsumeIntegralInRange(-100, 100)); + EXPECT_EQ(uint16_t(15823), + DataProv.ConsumeIntegralInRange(0, 65535)); + EXPECT_EQ((signed char)(-101), + DataProv.ConsumeIntegralInRange(-123, 123)); + EXPECT_EQ(int64_t(-53253077544), DataProv.ConsumeIntegralInRange( + -99999999999, 99999999999)); + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(1014), String.length()); + EXPECT_EQ(uint64_t(123456789), + DataProv.ConsumeIntegralInRange(123456789, 987654321)); +} + +TEST(FuzzedDataProvider, ConsumeRandomLengthString) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ( + std::string( + "\x8A\x19\x0D\x44\x37\x0D\x38\x5E\x9B\xAA\xF3\xDA\xAA\x88\xF2\x9B\x6C" + "\xBA\xBE\xB1\xF2\xCF\x13\xB8\xAC\x1A\x7F\x1C\xC9\x90\xD0\xD9"), + DataProv.ConsumeRandomLengthString(1337)); + EXPECT_EQ(std::string( + "\xB3\xFD\xE3\x05\xA4\x03\x37\x49\x50\x4B\xBC\x39\xA2\x09\x6C" + "\x2F\xAF\xD1\xB5\x47\xBF\x92\xBD\x79\xE5\xC5\x6E\x51\xA4\xED" + "\xE9\xBD\x40\x4A\xFC\x25\x7A\x27\xC8\x92\xF7\x30\xDE\x40\x66" + "\x66\xE8\x5F\x65\x39\x7E\x9E\x80\x2B\x01\x71\x2A\xFF\xD3\x0A" + "\xAC\x6E\x49\x32\x79\x10\x6A\x6F\x97\x96\x70\x7E\x50\x65\xC9" + "\x1D\xBD\x4E\x17\x04\x1E\xBA\x26\xAC\x1F\xE3\x37\x1C\x15\x43" + "\x60\x41\x2A\x7C\xCA\x70\xCE\xAB\x20\x24\xF8\xD9\x1F\x14\x7C"), + DataProv.ConsumeRandomLengthString(31337)); + size_t Offset = 141; + EXPECT_EQ(std::string(Data + Offset, Data + Offset + 5), + DataProv.ConsumeRandomLengthString(5)); + Offset += 5; + EXPECT_EQ(std::string(Data + Offset, Data + Offset + 2), + DataProv.ConsumeRandomLengthString(2)); + Offset += 2; + + // Call the overloaded method without arguments (uses max length available). + EXPECT_EQ(std::string(Data + Offset, Data + Offset + 664), + DataProv.ConsumeRandomLengthString()); + Offset += 664 + 2; // +2 because of '\' character followed by any other byte. + + EXPECT_EQ(std::string(Data + Offset, Data + Offset + 92), + DataProv.ConsumeRandomLengthString()); + Offset += 92 + 2; + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(116), String.length()); + EXPECT_EQ(std::string(), DataProv.ConsumeRandomLengthString(1)); +} + +TEST(FuzzedDataProvider, ConsumeRemainingBytes) { + { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::vector(Data, Data + sizeof(Data)), + DataProv.ConsumeRemainingBytes()); + EXPECT_EQ(std::vector(), + DataProv.ConsumeRemainingBytes()); + } + + { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::vector(Data, Data + 123), + DataProv.ConsumeBytes(123)); + EXPECT_EQ(std::vector(Data + 123, Data + sizeof(Data)), + DataProv.ConsumeRemainingBytes()); + } +} + +TEST(FuzzedDataProvider, ConsumeRemainingBytesAsString) { + { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::string(Data, Data + sizeof(Data)), + DataProv.ConsumeRemainingBytesAsString()); + EXPECT_EQ(std::string(""), DataProv.ConsumeRemainingBytesAsString()); + } + + { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(std::vector(Data, Data + 123), + DataProv.ConsumeBytes(123)); + EXPECT_EQ(std::string(Data + 123, Data + sizeof(Data)), + DataProv.ConsumeRemainingBytesAsString()); + } +} + +TEST(FuzzedDataProvider, ConsumeIntegral) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(int32_t(-903266865), DataProv.ConsumeIntegral()); + EXPECT_EQ(uint32_t(372863811), DataProv.ConsumeIntegral()); + EXPECT_EQ(uint8_t(61), DataProv.ConsumeIntegral()); + EXPECT_EQ(int16_t(22100), DataProv.ConsumeIntegral()); + EXPECT_EQ(uint64_t(18252263806144500217u), + DataProv.ConsumeIntegral()); + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(1005), String.length()); + EXPECT_EQ(std::numeric_limits::min(), + DataProv.ConsumeIntegral()); +} + +TEST(FuzzedDataProvider, ConsumeBool) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(false, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(false, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(true, DataProv.ConsumeBool()); + EXPECT_EQ(false, DataProv.ConsumeBool()); + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(1014), String.length()); + EXPECT_EQ(false, DataProv.ConsumeBool()); +} + +TEST(FuzzedDataProvider, PickValueInStdArray) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + const std::array Array = {1, 2, 3, 4, 5}; + EXPECT_EQ(5, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(1, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); +} + +TEST(FuzzedDataProvider, PickValueInArray) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + const int Array[] = {1, 2, 3, 4, 5}; + EXPECT_EQ(5, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(1, DataProv.PickValueInArray(Array)); + EXPECT_EQ(3, DataProv.PickValueInArray(Array)); + EXPECT_EQ(2, DataProv.PickValueInArray(Array)); + + EXPECT_EQ(uint8_t(0x9D), DataProv.PickValueInArray(Data)); + EXPECT_EQ(uint8_t(0xBA), DataProv.PickValueInArray(Data)); + EXPECT_EQ(uint8_t(0x69), DataProv.PickValueInArray(Data)); + EXPECT_EQ(uint8_t(0xD6), DataProv.PickValueInArray(Data)); + + EXPECT_EQ(uint32_t(777), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(uint32_t(777), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(uint64_t(1337), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(size_t(777), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(int16_t(1337), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(int32_t(777), DataProv.PickValueInArray({1337, 777})); + EXPECT_EQ(int64_t(777), DataProv.PickValueInArray({1337, 777})); + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(1000), String.length()); + EXPECT_EQ(uint8_t(0x8A), DataProv.PickValueInArray(Data)); +} + +TEST(FuzzedDataProvider, ConsumeEnum) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + enum class Enum { + Zero, + One, + Two, + Three, + Four, + Five, + Six, + Seven, + kMaxValue = Seven + }; + EXPECT_EQ(Enum::Two, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::One, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Five, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Seven, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Six, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::One, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Three, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Three, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Five, DataProv.ConsumeEnum()); + EXPECT_EQ(Enum::Six, DataProv.ConsumeEnum()); + + // Exhaust the buffer. + auto String = DataProv.ConsumeBytesAsString(31337); + EXPECT_EQ(size_t(1014), String.length()); + EXPECT_EQ(Enum::Zero, DataProv.ConsumeEnum()); +} + +TEST(FuzzedDataProvider, remaining_bytes) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + EXPECT_EQ(size_t(1024), DataProv.remaining_bytes()); + EXPECT_EQ(false, DataProv.ConsumeBool()); + EXPECT_EQ(size_t(1024 - 1), DataProv.remaining_bytes()); + EXPECT_EQ(std::vector(Data, Data + 8), + DataProv.ConsumeBytes(8)); + EXPECT_EQ(size_t(1024 - 1 - 8), DataProv.remaining_bytes()); + + // Exhaust the buffer. + EXPECT_EQ(std::vector(Data + 8, Data + sizeof(Data) - 1), + DataProv.ConsumeRemainingBytes()); + EXPECT_EQ(size_t(0), DataProv.remaining_bytes()); +} + +TEST(FuzzedDataProvider, ConsumeProbability) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + ASSERT_FLOAT_EQ(float(0.28969181), DataProv.ConsumeProbability()); + ASSERT_DOUBLE_EQ(double(0.086814121166605432), + DataProv.ConsumeProbability()); + ASSERT_FLOAT_EQ(float(0.30104411), DataProv.ConsumeProbability()); + ASSERT_DOUBLE_EQ(double(0.96218831486039413), + DataProv.ConsumeProbability()); + ASSERT_FLOAT_EQ(float(0.67005056), DataProv.ConsumeProbability()); + ASSERT_DOUBLE_EQ(double(0.69210584173832279), + DataProv.ConsumeProbability()); + + // Exhaust the buffer. + EXPECT_EQ(std::vector(Data, Data + sizeof(Data) - 36), + DataProv.ConsumeRemainingBytes()); + ASSERT_FLOAT_EQ(float(0.0), DataProv.ConsumeProbability()); +} + +TEST(FuzzedDataProvider, ConsumeFloatingPoint) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + ASSERT_FLOAT_EQ(float(-2.8546307e+38), + DataProv.ConsumeFloatingPoint()); + ASSERT_DOUBLE_EQ(double(8.0940194040236032e+307), + DataProv.ConsumeFloatingPoint()); + ASSERT_FLOAT_EQ(float(271.49084), + DataProv.ConsumeFloatingPointInRange(123.0, 777.0)); + ASSERT_DOUBLE_EQ(double(30.859126145478349), + DataProv.ConsumeFloatingPointInRange(13.37, 31.337)); + ASSERT_FLOAT_EQ( + float(-903.47729), + DataProv.ConsumeFloatingPointInRange(-999.9999, -777.77)); + ASSERT_DOUBLE_EQ( + double(24.561393182922771), + DataProv.ConsumeFloatingPointInRange(-13.37, 31.337)); + ASSERT_FLOAT_EQ(float(1.0), + DataProv.ConsumeFloatingPointInRange(1.0, 1.0)); + ASSERT_DOUBLE_EQ(double(-1.0), + DataProv.ConsumeFloatingPointInRange(-1.0, -1.0)); + + // Exhaust the buffer. + EXPECT_EQ((std::vector(Data, Data + sizeof(Data) - 50)).size(), + DataProv.ConsumeRemainingBytes().size()); + ASSERT_FLOAT_EQ(float(0.0), DataProv.ConsumeProbability()); + ASSERT_NEAR(std::numeric_limits::lowest(), + DataProv.ConsumeFloatingPoint(), 1e-10); + ASSERT_FLOAT_EQ(float(123.0), + DataProv.ConsumeFloatingPointInRange(123.0, 777.0)); + ASSERT_DOUBLE_EQ(double(-13.37), DataProv.ConsumeFloatingPointInRange( + -13.37, 31.337)); +} + +TEST(FuzzedDataProvider, ConsumeData) { + FuzzedDataProvider DataProv(Data, sizeof(Data)); + uint8_t Buffer[10] = {}; + EXPECT_EQ(sizeof(Buffer), DataProv.ConsumeData(Buffer, sizeof(Buffer))); + std::vector Expected(Data, Data + sizeof(Buffer)); + EXPECT_EQ(Expected, std::vector(Buffer, Buffer + sizeof(Buffer))); + + EXPECT_EQ(size_t(2), DataProv.ConsumeData(Buffer, 2)); + Expected[0] = Data[sizeof(Buffer)]; + Expected[1] = Data[sizeof(Buffer) + 1]; + EXPECT_EQ(Expected, std::vector(Buffer, Buffer + sizeof(Buffer))); + + // Exhaust the buffer. + EXPECT_EQ(std::vector(Data + 12, Data + sizeof(Data)), + DataProv.ConsumeRemainingBytes()); + EXPECT_EQ(size_t(0), DataProv.ConsumeData(Buffer, sizeof(Buffer))); + EXPECT_EQ(Expected, std::vector(Buffer, Buffer + sizeof(Buffer))); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzerUnittest.cpp clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzerUnittest.cpp --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzerUnittest.cpp 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/libfuzzer/tests/FuzzerUnittest.cpp 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1430 @@ +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Avoid ODR violations (LibFuzzer is built without ASan and this test is built +// with ASan) involving C++ standard library types when using libcxx. +#define _LIBCPP_HAS_NO_ASAN + +// Do not attempt to use LLVM ostream etc from gtest. +#define GTEST_NO_LLVM_SUPPORT 1 + +#include "FuzzerCorpus.h" +#include "FuzzerDictionary.h" +#include "FuzzerInternal.h" +#include "FuzzerMerge.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include "gtest/gtest.h" +#include +#include +#include + +using namespace fuzzer; + +// For now, have LLVMFuzzerTestOneInput just to make it link. +// Later we may want to make unittests that actually call +// LLVMFuzzerTestOneInput. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + abort(); +} + +TEST(Fuzzer, Basename) { + EXPECT_EQ(Basename("foo/bar"), "bar"); + EXPECT_EQ(Basename("bar"), "bar"); + EXPECT_EQ(Basename("/bar"), "bar"); + EXPECT_EQ(Basename("foo/x"), "x"); + EXPECT_EQ(Basename("foo/"), ""); +#if LIBFUZZER_WINDOWS + EXPECT_EQ(Basename("foo\\bar"), "bar"); + EXPECT_EQ(Basename("foo\\bar/baz"), "baz"); + EXPECT_EQ(Basename("\\bar"), "bar"); + EXPECT_EQ(Basename("foo\\x"), "x"); + EXPECT_EQ(Basename("foo\\"), ""); +#endif +} + +TEST(Fuzzer, CrossOver) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + Unit A({0, 1, 2}), B({5, 6, 7}); + Unit C; + Unit Expected[] = { + { 0 }, + { 0, 1 }, + { 0, 5 }, + { 0, 1, 2 }, + { 0, 1, 5 }, + { 0, 5, 1 }, + { 0, 5, 6 }, + { 0, 1, 2, 5 }, + { 0, 1, 5, 2 }, + { 0, 1, 5, 6 }, + { 0, 5, 1, 2 }, + { 0, 5, 1, 6 }, + { 0, 5, 6, 1 }, + { 0, 5, 6, 7 }, + { 0, 1, 2, 5, 6 }, + { 0, 1, 5, 2, 6 }, + { 0, 1, 5, 6, 2 }, + { 0, 1, 5, 6, 7 }, + { 0, 5, 1, 2, 6 }, + { 0, 5, 1, 6, 2 }, + { 0, 5, 1, 6, 7 }, + { 0, 5, 6, 1, 2 }, + { 0, 5, 6, 1, 7 }, + { 0, 5, 6, 7, 1 }, + { 0, 1, 2, 5, 6, 7 }, + { 0, 1, 5, 2, 6, 7 }, + { 0, 1, 5, 6, 2, 7 }, + { 0, 1, 5, 6, 7, 2 }, + { 0, 5, 1, 2, 6, 7 }, + { 0, 5, 1, 6, 2, 7 }, + { 0, 5, 1, 6, 7, 2 }, + { 0, 5, 6, 1, 2, 7 }, + { 0, 5, 6, 1, 7, 2 }, + { 0, 5, 6, 7, 1, 2 } + }; + for (size_t Len = 1; Len < 8; Len++) { + std::set FoundUnits, ExpectedUnitsWitThisLength; + for (int Iter = 0; Iter < 3000; Iter++) { + C.resize(Len); + size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(), + C.data(), C.size()); + C.resize(NewSize); + FoundUnits.insert(C); + } + for (const Unit &U : Expected) + if (U.size() <= Len) + ExpectedUnitsWitThisLength.insert(U); + EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits); + } +} + +TEST(Fuzzer, Hash) { + uint8_t A[] = {'a', 'b', 'c'}; + fuzzer::Unit U(A, A + sizeof(A)); + EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U)); + U.push_back('d'); + EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U)); +} + +typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, + size_t MaxSize); + +void TestEraseBytes(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77}; + uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77}; + uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77}; + uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; + uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77}; + + uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77}; + + + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T)); + if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4; + if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5; + if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6; + if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7; + + if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8; + if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9; + if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10; + + if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11; + if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12; + if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13; + } + EXPECT_EQ(FoundMask, (1 << 14) - 1); +} + +TEST(FuzzerMutate, EraseBytes1) { + TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200); +} +TEST(FuzzerMutate, EraseBytes2) { + TestEraseBytes(&MutationDispatcher::Mutate, 2000); +} + +void TestInsertByte(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66}; + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66}; + uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (*MD.*M)(T, 7, 8); + if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, InsertByte1) { + TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15); +} +TEST(FuzzerMutate, InsertByte2) { + TestInsertByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestInsertRepeatedBytes(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'}; + uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33}; + uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33}; + uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33}; + uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33}; + + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33}; + uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33}; + uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33}; + uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33}; + size_t NewSize = (*MD.*M)(T, 4, 8); + if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4; + + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8; + if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9; + + } + EXPECT_EQ(FoundMask, (1 << 10) - 1); +} + +TEST(FuzzerMutate, InsertRepeatedBytes1) { + TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, + 10000); +} +TEST(FuzzerMutate, InsertRepeatedBytes2) { + TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000); +} + +void TestChangeByte(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (*MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeByte1) { + TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15); +} +TEST(FuzzerMutate, ChangeByte2) { + TestChangeByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestChangeBit(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (*MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBit1) { + TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16); +} +TEST(FuzzerMutate, ChangeBit2) { + TestChangeBit(&MutationDispatcher::Mutate, 1 << 18); +} + +void TestShuffleBytes(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33}; + uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (*MD.*M)(T, 7, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ShuffleBytes1) { + TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17); +} +TEST(FuzzerMutate, ShuffleBytes2) { + TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20); +} + +void TestCopyPart(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11}; + uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66}; + uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (*MD.*M)(T, 7, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22}; + uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44}; + uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (*MD.*M)(T, 5, 8); + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8; + if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9; + } + + EXPECT_EQ(FoundMask, 1023); +} + +TEST(FuzzerMutate, CopyPart1) { + TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10); +} +TEST(FuzzerMutate, CopyPart2) { + TestCopyPart(&MutationDispatcher::Mutate, 1 << 13); +} +TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) { + // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an + // insert on an input of size `MaxSize`. Performing an insert in this case + // will lead to the mutation failing. + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22}; + size_t MaxSize = sizeof(Data); + for (int count = 0; count < (1 << 18); ++count) { + size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize); + ASSERT_EQ(NewSize, MaxSize); + } +} + +void TestAddWordFromDictionary(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD}; + uint8_t Word2[3] = {0xFF, 0xEE, 0xEF}; + MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1))); + MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2))); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD}; + uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22}; + uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22}; + uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22}; + uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF}; + uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22}; + uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22}; + uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22}; + size_t NewSize = (*MD.*M)(T, 3, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4; + if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5; + if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6; + if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, AddWordFromDictionary1) { + TestAddWordFromDictionary( + &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15); +} + +TEST(FuzzerMutate, AddWordFromDictionary2) { + TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15); +} + +void TestChangeASCIIInteger(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + + uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'}; + uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'}; + uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'}; + uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'}; + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'}; + size_t NewSize = (*MD.*M)(T, 8, 8); + /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + else if (NewSize == 8) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ChangeASCIIInteger1) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger, + 1 << 15); +} + +TEST(FuzzerMutate, ChangeASCIIInteger2) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15); +} + +void TestChangeBinaryInteger(Mutator M, int NumIter) { + std::unique_ptr t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + std::unique_ptr MD(new MutationDispatcher(Rand, {})); + + uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79}; + uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77}; + uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size + uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size) + + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (*MD.*M)(T, 8, 8); + /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBinaryInteger1) { + TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger, + 1 << 12); +} + +TEST(FuzzerMutate, ChangeBinaryInteger2) { + TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15); +} + + +TEST(FuzzerDictionary, ParseOneDictionaryEntry) { + Unit U; + EXPECT_FALSE(ParseOneDictionaryEntry("", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U)); + EXPECT_EQ(U, Unit({'a'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U)); + EXPECT_EQ(U, Unit({'\\'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U)); + EXPECT_EQ(U, Unit({0xAB})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U)); + EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U)); + EXPECT_EQ(U, Unit({'#'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U)); + EXPECT_EQ(U, Unit({'"'})); +} + +TEST(FuzzerDictionary, ParseDictionaryFile) { + std::vector Units; + EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units)); + EXPECT_FALSE(ParseDictionaryFile("", &Units)); + EXPECT_TRUE(ParseDictionaryFile("\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units)); + EXPECT_EQ(Units, std::vector({Unit({'a', 'a'})})); + EXPECT_TRUE( + ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units)); + EXPECT_EQ(Units, + std::vector({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); +} + +TEST(FuzzerUtil, Base64) { + EXPECT_EQ("", Base64({})); + EXPECT_EQ("YQ==", Base64({'a'})); + EXPECT_EQ("eA==", Base64({'x'})); + EXPECT_EQ("YWI=", Base64({'a', 'b'})); + EXPECT_EQ("eHk=", Base64({'x', 'y'})); + EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'})); + EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'})); + EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'})); + EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); + EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); +} + +#ifdef __GLIBC__ +class PrintfCapture { + public: + PrintfCapture() { + OldOutputFile = GetOutputFile(); + SetOutputFile(open_memstream(&Buffer, &Size)); + } + ~PrintfCapture() { + fclose(GetOutputFile()); + SetOutputFile(OldOutputFile); + free(Buffer); + } + std::string str() { return std::string(Buffer, Size); } + + private: + char *Buffer; + size_t Size; + FILE *OldOutputFile; +}; + +TEST(FuzzerUtil, PrintASCII) { + auto f = [](const char *Str, const char *PrintAfter = "") { + PrintfCapture Capture; + PrintASCII(reinterpret_cast(Str), strlen(Str), PrintAfter); + return Capture.str(); + }; + EXPECT_EQ("hello", f("hello")); + EXPECT_EQ("c:\\\\", f("c:\\")); + EXPECT_EQ("\\\"hi\\\"", f("\"hi\"")); + EXPECT_EQ("\\011a", f("\ta")); + EXPECT_EQ("\\0111", f("\t1")); + EXPECT_EQ("hello\\012", f("hello\n")); + EXPECT_EQ("hello\n", f("hello", "\n")); +} +#endif + +TEST(Corpus, Distribution) { + DataFlowTrace DFT; + Random Rand(0); + struct EntropicOptions Entropic = {false, 0xFF, 100, false}; + std::unique_ptr C(new InputCorpus("", Entropic)); + size_t N = 10; + size_t TriesPerUnit = 1<<16; + for (size_t i = 0; i < N; i++) + C->AddToCorpus(Unit{static_cast(i)}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(0), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + + std::vector Hist(N); + for (size_t i = 0; i < N * TriesPerUnit; i++) { + Hist[C->ChooseUnitIdxToMutate(Rand)]++; + } + for (size_t i = 0; i < N; i++) { + // A weak sanity check that every unit gets invoked. + EXPECT_GT(Hist[i], TriesPerUnit / N / 3); + } +} + +TEST(Corpus, Replace) { + DataFlowTrace DFT; + struct EntropicOptions Entropic = {false, 0xFF, 100, false}; + std::unique_ptr C( + new InputCorpus(/*OutputCorpus*/ "", Entropic)); + InputInfo *FirstII = + C->AddToCorpus(Unit{0x01, 0x00}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(1234), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + InputInfo *SecondII = + C->AddToCorpus(Unit{0x02}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(5678), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + Unit ReplacedU = Unit{0x03}; + + C->Replace(FirstII, ReplacedU, + /*TimeOfUnit*/ std::chrono::microseconds(321)); + + // FirstII should be replaced. + EXPECT_EQ(FirstII->U, Unit{0x03}); + EXPECT_EQ(FirstII->Reduced, true); + EXPECT_EQ(FirstII->TimeOfUnit, std::chrono::microseconds(321)); + std::vector ExpectedSha1(kSHA1NumBytes); + ComputeSHA1(ReplacedU.data(), ReplacedU.size(), ExpectedSha1.data()); + std::vector IISha1(FirstII->Sha1, FirstII->Sha1 + kSHA1NumBytes); + EXPECT_EQ(IISha1, ExpectedSha1); + + // SecondII should not be replaced. + EXPECT_EQ(SecondII->U, Unit{0x02}); + EXPECT_EQ(SecondII->Reduced, false); + EXPECT_EQ(SecondII->TimeOfUnit, std::chrono::microseconds(5678)); +} + +template +void EQ(const std::vector &A, const std::vector &B) { + EXPECT_EQ(A, B); +} + +template void EQ(const std::set &A, const std::vector &B) { + EXPECT_EQ(A, std::set(B.begin(), B.end())); +} + +void EQ(const std::vector &A, + const std::vector &B) { + std::set a; + for (const auto &File : A) + a.insert(File.Name); + std::set b(B.begin(), B.end()); + EXPECT_EQ(a, b); +} + +#define TRACED_EQ(A, ...) \ + { \ + SCOPED_TRACE(#A); \ + EQ(A, __VA_ARGS__); \ + } + +TEST(Merger, Parse) { + Merger M; + + const char *kInvalidInputs[] = { + // Bad file numbers + "", + "x", + "0\n0", + "3\nx", + "2\n3", + "2\n2", + // Bad file names + "2\n2\nA\n", + "2\n2\nA\nB\nC\n", + // Unknown markers + "2\n1\nA\nSTARTED 0\nBAD 0 0x0", + // Bad file IDs + "1\n1\nA\nSTARTED 1", + "2\n1\nA\nSTARTED 0\nFT 1 0x0", + }; + for (auto S : kInvalidInputs) { + SCOPED_TRACE(S); + EXPECT_FALSE(M.Parse(S, false)); + } + + // Parse initial control file + EXPECT_TRUE(M.Parse("1\n0\nAA\n", false)); + ASSERT_EQ(M.Files.size(), 1U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 0U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_TRUE(M.LastFailure.empty()); + EXPECT_EQ(M.FirstNotProcessedFile, 0U); + + // Parse control file that failed on first attempt + EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false)); + ASSERT_EQ(M.Files.size(), 2U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_EQ(M.Files[1].Name, "BB"); + EXPECT_EQ(M.LastFailure, "AA"); + EXPECT_EQ(M.FirstNotProcessedFile, 1U); + + // Parse control file that failed on later attempt + EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "", + true)); + ASSERT_EQ(M.Files.size(), 3U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_EQ(M.Files[0].Size, 1000U); + EXPECT_EQ(M.Files[1].Name, "BB"); + EXPECT_EQ(M.Files[1].Size, 1001U); + EXPECT_EQ(M.Files[2].Name, "C"); + EXPECT_EQ(M.Files[2].Size, 1002U); + EXPECT_EQ(M.LastFailure, "C"); + EXPECT_EQ(M.FirstNotProcessedFile, 3U); + TRACED_EQ(M.Files[0].Features, {1, 2, 3}); + TRACED_EQ(M.Files[1].Features, {4, 5, 6}); + + // Parse control file without features or PCs + EXPECT_TRUE(M.Parse("2\n0\nAA\nBB\n" + "STARTED 0 1000\n" + "FT 0\n" + "COV 0\n" + "STARTED 1 1001\n" + "FT 1\n" + "COV 1\n" + "", + true)); + ASSERT_EQ(M.Files.size(), 2U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 0U); + EXPECT_TRUE(M.LastFailure.empty()); + EXPECT_EQ(M.FirstNotProcessedFile, 2U); + EXPECT_TRUE(M.Files[0].Features.empty()); + EXPECT_TRUE(M.Files[0].Cov.empty()); + EXPECT_TRUE(M.Files[1].Features.empty()); + EXPECT_TRUE(M.Files[1].Cov.empty()); + + // Parse features and PCs + EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "COV 0 11 12 13\n" + "STARTED 1 1001\n" + "FT 1 4 5 6\n" + "COV 1 7 8 9\n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "COV 2 16 11 13\n" + "", + true)); + ASSERT_EQ(M.Files.size(), 3U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 2U); + EXPECT_TRUE(M.LastFailure.empty()); + EXPECT_EQ(M.FirstNotProcessedFile, 3U); + TRACED_EQ(M.Files[0].Features, {1, 2, 3}); + TRACED_EQ(M.Files[0].Cov, {11, 12, 13}); + TRACED_EQ(M.Files[1].Features, {4, 5, 6}); + TRACED_EQ(M.Files[1].Cov, {7, 8, 9}); + TRACED_EQ(M.Files[2].Features, {1, 3, 6}); + TRACED_EQ(M.Files[2].Cov, {16}); +} + +TEST(Merger, Merge) { + Merger M; + std::set Features, NewFeatures; + std::set Cov, NewCov; + std::vector NewFiles; + + // Adds new files and features + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"A", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + // Doesn't return features or files in the initial corpus. + EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + + // No new features, so no new files + EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 0U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {}); + TRACED_EQ(NewFeatures, {}); + + // Can pass initial features and coverage. + Features = {1, 2, 3}; + Cov = {}; + EXPECT_TRUE(M.Parse("2\n0\nA\nB\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6\n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U); + TRACED_EQ(M.Files, {"A", "B"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + Features.clear(); + Cov.clear(); + + // Parse smaller files first + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 2000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3 \n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U); + TRACED_EQ(M.Files, {"B", "C", "A"}); + TRACED_EQ(NewFiles, {"B", "C", "A"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 1 2 3\n" + "STARTED 1 1101\n" + "FT 1 4 5 6 \n" + "STARTED 2 1102\n" + "FT 2 6 1 3 100 \n" + "STARTED 3 1000\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 7U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"D", "B", "C", "A"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6, 100}); + + // For same sized file, parse more features first + EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 4 5 6 7 8\n" + "STARTED 1 1100\n" + "FT 1 1 2 3 \n" + "STARTED 2 1100\n" + "FT 2 2 3 \n" + "STARTED 3 1000\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"D", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3}); +} + +TEST(Merger, SetCoverMerge) { + Merger M; + std::set Features, NewFeatures; + std::set Cov, NewCov; + std::vector NewFiles; + + // Adds new files and features + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 6U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"A", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + // Doesn't return features or files in the initial corpus. + EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + + // No new features, so no new files + EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 0U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {}); + TRACED_EQ(NewFeatures, {}); + + // Can pass initial features and coverage. + Features = {1, 2, 3}; + Cov = {}; + EXPECT_TRUE(M.Parse("2\n0\nA\nB\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + Features.clear(); + Cov.clear(); + + // Prefer files with a lot of features first (C has 4 features) + // Then prefer B over A due to the smaller size. After choosing C and B, + // A and D have no new features to contribute. + EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 3 5 6\n" + "STARTED 1 1000\n" + "FT 1 4 5 6 \n" + "STARTED 2 1000\n" + "FT 2 1 2 3 4 \n" + "STARTED 3 500\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 6U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"C", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + // Only 1 file covers all features. + EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 4 5 6 7 8\n" + "STARTED 1 1100\n" + "FT 1 1 2 3 \n" + "STARTED 2 1100\n" + "FT 2 2 3 \n" + "STARTED 3 1000\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {1, 2, 3}); + + // A Feature has a value greater than (1 << 21) and hence + // there are collisions in the underlying `covered features` + // bitvector. + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 2000\n" + "FT 0 1 2 3\n" + "STARTED 1 1000\n" + "FT 1 3 4 5 \n" + "STARTED 2 1000\n" + "FT 2 3 2097153 \n" // Last feature is (2^21 + 1). + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 5U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + // File 'C' is not added because it's last feature is considered + // covered due to collision with feature 1. + TRACED_EQ(NewFiles, {"B", "A"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5}); +} + +#undef TRACED_EQ + +TEST(DFT, BlockCoverage) { + BlockCoverage Cov; + // Assuming C0 has 5 instrumented blocks, + // C1: 7 blocks, C2: 4, C3: 9, C4 never covered, C5: 15, + + // Add C0 + EXPECT_TRUE(Cov.AppendCoverage("C0 5\n")); + EXPECT_EQ(Cov.GetCounter(0, 0), 1U); + EXPECT_EQ(Cov.GetCounter(0, 1), 0U); // not seen this BB yet. + EXPECT_EQ(Cov.GetCounter(0, 5), 0U); // BB ID out of bounds. + EXPECT_EQ(Cov.GetCounter(1, 0), 0U); // not seen this function yet. + + EXPECT_EQ(Cov.GetNumberOfBlocks(0), 5U); + EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 1U); + EXPECT_EQ(Cov.GetNumberOfBlocks(1), 0U); + + // Various errors. + EXPECT_FALSE(Cov.AppendCoverage("C0\n")); // No total number. + EXPECT_FALSE(Cov.AppendCoverage("C0 7\n")); // No total number. + EXPECT_FALSE(Cov.AppendCoverage("CZ\n")); // Wrong function number. + EXPECT_FALSE(Cov.AppendCoverage("C1 7 7")); // BB ID is too big. + EXPECT_FALSE(Cov.AppendCoverage("C1 100 7")); // BB ID is too big. + + // Add C0 more times. + EXPECT_TRUE(Cov.AppendCoverage("C0 5\n")); + EXPECT_EQ(Cov.GetCounter(0, 0), 2U); + EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 5\n")); + EXPECT_EQ(Cov.GetCounter(0, 0), 3U); + EXPECT_EQ(Cov.GetCounter(0, 1), 1U); + EXPECT_EQ(Cov.GetCounter(0, 2), 1U); + EXPECT_EQ(Cov.GetCounter(0, 3), 0U); + EXPECT_EQ(Cov.GetCounter(0, 4), 0U); + EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 3U); + EXPECT_TRUE(Cov.AppendCoverage("C0 1 3 4 5\n")); + EXPECT_EQ(Cov.GetCounter(0, 0), 4U); + EXPECT_EQ(Cov.GetCounter(0, 1), 2U); + EXPECT_EQ(Cov.GetCounter(0, 2), 1U); + EXPECT_EQ(Cov.GetCounter(0, 3), 1U); + EXPECT_EQ(Cov.GetCounter(0, 4), 1U); + EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 5U); + + EXPECT_TRUE(Cov.AppendCoverage("C1 7\nC2 4\nC3 9\nC5 15\nC0 5\n")); + EXPECT_EQ(Cov.GetCounter(0, 0), 5U); + EXPECT_EQ(Cov.GetCounter(1, 0), 1U); + EXPECT_EQ(Cov.GetCounter(2, 0), 1U); + EXPECT_EQ(Cov.GetCounter(3, 0), 1U); + EXPECT_EQ(Cov.GetCounter(4, 0), 0U); + EXPECT_EQ(Cov.GetCounter(5, 0), 1U); + + EXPECT_TRUE(Cov.AppendCoverage("C3 4 5 9\nC5 11 12 15")); + EXPECT_EQ(Cov.GetCounter(0, 0), 5U); + EXPECT_EQ(Cov.GetCounter(1, 0), 1U); + EXPECT_EQ(Cov.GetCounter(2, 0), 1U); + EXPECT_EQ(Cov.GetCounter(3, 0), 2U); + EXPECT_EQ(Cov.GetCounter(3, 4), 1U); + EXPECT_EQ(Cov.GetCounter(3, 5), 1U); + EXPECT_EQ(Cov.GetCounter(3, 6), 0U); + EXPECT_EQ(Cov.GetCounter(4, 0), 0U); + EXPECT_EQ(Cov.GetCounter(5, 0), 2U); + EXPECT_EQ(Cov.GetCounter(5, 10), 0U); + EXPECT_EQ(Cov.GetCounter(5, 11), 1U); + EXPECT_EQ(Cov.GetCounter(5, 12), 1U); +} + +TEST(DFT, FunctionWeights) { + BlockCoverage Cov; + // unused function gets zero weight. + EXPECT_TRUE(Cov.AppendCoverage("C0 5\n")); + auto Weights = Cov.FunctionWeights(2); + EXPECT_GT(Weights[0], 0.); + EXPECT_EQ(Weights[1], 0.); + + // Less frequently used function gets less weight. + Cov.clear(); + EXPECT_TRUE(Cov.AppendCoverage("C0 5\nC1 5\nC1 5\n")); + Weights = Cov.FunctionWeights(2); + EXPECT_GT(Weights[0], Weights[1]); + + // A function with more uncovered blocks gets more weight. + Cov.clear(); + EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 3 5\nC1 2 4\n")); + Weights = Cov.FunctionWeights(2); + EXPECT_GT(Weights[1], Weights[0]); + + // A function with DFT gets more weight than the function w/o DFT. + Cov.clear(); + EXPECT_TRUE(Cov.AppendCoverage("F1 111\nC0 3\nC1 1 2 3\n")); + Weights = Cov.FunctionWeights(2); + EXPECT_GT(Weights[1], Weights[0]); +} + + +TEST(Fuzzer, ForEachNonZeroByte) { + const size_t N = 64; + alignas(64) uint8_t Ar[N + 8] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, + 9, 9, 9, 9, 9, 9, 9, 9, + }; + typedef std::vector> Vec; + Vec Res, Expected; + auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) { + Res.push_back({FirstFeature + Idx, V}); + }; + ForEachNonZeroByte(Ar, Ar + N, 100, CB); + Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4}, + {135, 5}, {137, 6}, {146, 7}, {163, 8}}; + EXPECT_EQ(Res, Expected); + + Res.clear(); + ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB); + Expected = { {109, 2}, {118, 3}, {120, 4}, + {135, 5}, {137, 6}, {146, 7}, {163, 8}}; + EXPECT_EQ(Res, Expected); + + Res.clear(); + ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB); + Expected = { {109, 2}, {118, 3}, {120, 4}, + {135, 5}, {137, 6}, {146, 7}}; + EXPECT_EQ(Res, Expected); +} + +// FuzzerCommand unit tests. The arguments in the two helper methods below must +// match. +static void makeCommandArgs(std::vector *ArgsToAdd) { + assert(ArgsToAdd); + ArgsToAdd->clear(); + ArgsToAdd->push_back("foo"); + ArgsToAdd->push_back("-bar=baz"); + ArgsToAdd->push_back("qux"); + ArgsToAdd->push_back(Command::ignoreRemainingArgs()); + ArgsToAdd->push_back("quux"); + ArgsToAdd->push_back("-grault=garply"); +} + +static std::string makeCmdLine(const char *separator, const char *suffix) { + std::string CmdLine("foo -bar=baz qux "); + if (strlen(separator) != 0) { + CmdLine += separator; + CmdLine += " "; + } + CmdLine += Command::ignoreRemainingArgs(); + CmdLine += " quux -grault=garply"; + if (strlen(suffix) != 0) { + CmdLine += " "; + CmdLine += suffix; + } + return CmdLine; +} + +TEST(FuzzerCommand, Create) { + std::string CmdLine; + + // Default constructor + Command DefaultCmd; + + CmdLine = DefaultCmd.toString(); + EXPECT_EQ(CmdLine, ""); + + // Explicit constructor + std::vector ArgsToAdd; + makeCommandArgs(&ArgsToAdd); + Command InitializedCmd(ArgsToAdd); + + CmdLine = InitializedCmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); + + // Compare each argument + auto InitializedArgs = InitializedCmd.getArguments(); + auto i = ArgsToAdd.begin(); + auto j = InitializedArgs.begin(); + while (i != ArgsToAdd.end() && j != InitializedArgs.end()) { + EXPECT_EQ(*i++, *j++); + } + EXPECT_EQ(i, ArgsToAdd.end()); + EXPECT_EQ(j, InitializedArgs.end()); + + // Copy constructor + Command CopiedCmd(InitializedCmd); + + CmdLine = CopiedCmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); + + // Assignment operator + Command AssignedCmd; + AssignedCmd = CopiedCmd; + + CmdLine = AssignedCmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); +} + +TEST(FuzzerCommand, ModifyArguments) { + std::vector ArgsToAdd; + makeCommandArgs(&ArgsToAdd); + Command Cmd; + std::string CmdLine; + + Cmd.addArguments(ArgsToAdd); + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); + + Cmd.addArgument("waldo"); + EXPECT_TRUE(Cmd.hasArgument("waldo")); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("waldo", "")); + + Cmd.removeArgument("waldo"); + EXPECT_FALSE(Cmd.hasArgument("waldo")); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); +} + +TEST(FuzzerCommand, ModifyFlags) { + std::vector ArgsToAdd; + makeCommandArgs(&ArgsToAdd); + Command Cmd(ArgsToAdd); + std::string Value, CmdLine; + ASSERT_FALSE(Cmd.hasFlag("fred")); + + Value = Cmd.getFlagValue("fred"); + EXPECT_EQ(Value, ""); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); + + Cmd.addFlag("fred", "plugh"); + EXPECT_TRUE(Cmd.hasFlag("fred")); + + Value = Cmd.getFlagValue("fred"); + EXPECT_EQ(Value, "plugh"); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("-fred=plugh", "")); + + Cmd.removeFlag("fred"); + EXPECT_FALSE(Cmd.hasFlag("fred")); + + Value = Cmd.getFlagValue("fred"); + EXPECT_EQ(Value, ""); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "")); +} + +TEST(FuzzerCommand, SetOutput) { + std::vector ArgsToAdd; + makeCommandArgs(&ArgsToAdd); + Command Cmd(ArgsToAdd); + std::string CmdLine; + ASSERT_FALSE(Cmd.hasOutputFile()); + ASSERT_FALSE(Cmd.isOutAndErrCombined()); + + Cmd.combineOutAndErr(true); + EXPECT_TRUE(Cmd.isOutAndErrCombined()); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", "2>&1")); + + Cmd.combineOutAndErr(false); + EXPECT_FALSE(Cmd.isOutAndErrCombined()); + + Cmd.setOutputFile("xyzzy"); + EXPECT_TRUE(Cmd.hasOutputFile()); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", ">xyzzy")); + + Cmd.setOutputFile("thud"); + EXPECT_TRUE(Cmd.hasOutputFile()); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", ">thud")); + + Cmd.combineOutAndErr(); + EXPECT_TRUE(Cmd.isOutAndErrCombined()); + + CmdLine = Cmd.toString(); + EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1")); +} + +TEST(Entropic, UpdateFrequency) { + const size_t One = 1, Two = 2; + const size_t FeatIdx1 = 0, FeatIdx2 = 42, FeatIdx3 = 12, FeatIdx4 = 26; + size_t Index; + // Create input corpus with default entropic configuration + struct EntropicOptions Entropic = {true, 0xFF, 100, false}; + std::unique_ptr C(new InputCorpus("", Entropic)); + std::unique_ptr II(new InputInfo()); + + C->AddRareFeature(FeatIdx1); + C->UpdateFeatureFrequency(II.get(), FeatIdx1); + EXPECT_EQ(II->FeatureFreqs.size(), One); + C->AddRareFeature(FeatIdx2); + C->UpdateFeatureFrequency(II.get(), FeatIdx1); + C->UpdateFeatureFrequency(II.get(), FeatIdx2); + EXPECT_EQ(II->FeatureFreqs.size(), Two); + EXPECT_EQ(II->FeatureFreqs[0].second, 2); + EXPECT_EQ(II->FeatureFreqs[1].second, 1); + + C->AddRareFeature(FeatIdx3); + C->AddRareFeature(FeatIdx4); + C->UpdateFeatureFrequency(II.get(), FeatIdx3); + C->UpdateFeatureFrequency(II.get(), FeatIdx3); + C->UpdateFeatureFrequency(II.get(), FeatIdx3); + C->UpdateFeatureFrequency(II.get(), FeatIdx4); + + for (Index = 1; Index < II->FeatureFreqs.size(); Index++) + EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first); + + II->DeleteFeatureFreq(FeatIdx3); + for (Index = 1; Index < II->FeatureFreqs.size(); Index++) + EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first); +} + +double SubAndSquare(double X, double Y) { + double R = X - Y; + R = R * R; + return R; +} + +TEST(Entropic, ComputeEnergy) { + const double Precision = 0.01; + struct EntropicOptions Entropic = {true, 0xFF, 100, false}; + std::unique_ptr C(new InputCorpus("", Entropic)); + std::unique_ptr II(new InputInfo()); + std::vector> FeatureFreqs = { + {1, 3}, {2, 3}, {3, 3}}; + II->FeatureFreqs = FeatureFreqs; + II->NumExecutedMutations = 0; + II->UpdateEnergy(4, false, std::chrono::microseconds(0)); + EXPECT_LT(SubAndSquare(II->Energy, 1.450805), Precision); + + II->NumExecutedMutations = 9; + II->UpdateEnergy(5, false, std::chrono::microseconds(0)); + EXPECT_LT(SubAndSquare(II->Energy, 1.525496), Precision); + + II->FeatureFreqs[0].second++; + II->FeatureFreqs.push_back(std::pair(42, 6)); + II->NumExecutedMutations = 20; + II->UpdateEnergy(10, false, std::chrono::microseconds(0)); + EXPECT_LT(SubAndSquare(II->Energy, 1.792831), Precision); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/rust-toolchain clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/rust-toolchain --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/rust-toolchain 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/rust-toolchain 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +nightly diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,749 @@ +//! Bindings to [libFuzzer](http://llvm.org/docs/LibFuzzer.html): a runtime for +//! coverage-guided fuzzing. +//! +//! See [the `cargo-fuzz` +//! guide](https://rust-fuzz.github.io/book/cargo-fuzz.html) for a usage +//! tutorial. +//! +//! The main export of this crate is [the `fuzz_target!` +//! macro](./macro.fuzz_target.html), which allows you to define targets for +//! libFuzzer to exercise. + +#![deny(missing_docs, missing_debug_implementations)] + +pub use arbitrary; +use std::sync::OnceLock; + +/// Indicates whether the input should be kept in the corpus or rejected. This +/// should be returned by your fuzz target. If your fuzz target does not return +/// a value (i.e., returns `()`), then the input will be kept in the corpus. +#[derive(Debug)] +pub enum Corpus { + /// Keep the input in the corpus. + Keep, + + /// Reject the input and do not keep it in the corpus. + Reject, +} + +impl From<()> for Corpus { + fn from(_: ()) -> Self { + Self::Keep + } +} + +impl Corpus { + #[doc(hidden)] + /// Convert this Corpus result into the [integer codes used by + /// `libFuzzer`](https://llvm.org/docs/LibFuzzer.html#rejecting-unwanted-inputs). + /// This is -1 for reject, 0 for keep. + pub fn to_libfuzzer_code(self) -> i32 { + match self { + Corpus::Keep => 0, + Corpus::Reject => -1, + } + } +} + +extern "C" { + // We do not actually cross the FFI bound here. + #[allow(improper_ctypes)] + fn rust_fuzzer_test_input(input: &[u8]) -> i32; + + fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize) -> usize; +} + +/// Do not use; only for LibFuzzer's consumption. +#[doc(hidden)] +#[export_name = "LLVMFuzzerTestOneInput"] +pub unsafe fn test_input_wrap(data: *const u8, size: usize) -> i32 { + let test_input = ::std::panic::catch_unwind(|| { + let data_slice = ::std::slice::from_raw_parts(data, size); + rust_fuzzer_test_input(data_slice) + }); + + match test_input { + Ok(i) => i, + Err(_) => { + // hopefully the custom panic hook will be called before and abort the + // process before the stack frames are unwinded. + ::std::process::abort(); + } + } +} + +#[doc(hidden)] +pub fn rust_libfuzzer_debug_path() -> &'static Option { + static RUST_LIBFUZZER_DEBUG_PATH: OnceLock> = OnceLock::new(); + RUST_LIBFUZZER_DEBUG_PATH.get_or_init(|| std::env::var("RUST_LIBFUZZER_DEBUG_PATH").ok()) +} + +#[doc(hidden)] +pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize { + // Registers a panic hook that aborts the process before unwinding. + // It is useful to abort before unwinding so that the fuzzer will then be + // able to analyse the process stack frames to tell different bugs appart. + // + // HACK / FIXME: it would be better to use `-C panic=abort` but it's currently + // impossible to build code using compiler plugins with this flag. + // We will be able to remove this code when + // https://github.com/rust-lang/cargo/issues/5423 is fixed. + let default_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |panic_info| { + default_hook(panic_info); + std::process::abort(); + })); + 0 +} + +/// Define a fuzz target. +/// +/// ## Example +/// +/// This example takes a `&[u8]` slice and attempts to parse it. The parsing +/// might fail and return an `Err`, but it shouldn't ever panic or segfault. +/// +/// ```no_run +/// #![no_main] +/// +/// use libfuzzer_sys::fuzz_target; +/// +/// // Note: `|input|` is short for `|input: &[u8]|`. +/// fuzz_target!(|input| { +/// let _result: Result<_, _> = my_crate::parse(input); +/// }); +/// # mod my_crate { pub fn parse(_: &[u8]) -> Result<(), ()> { unimplemented!() } } +/// ``` +/// +/// ## Rejecting Inputs +/// +/// It may be desirable to reject some inputs, i.e. to not add them to the +/// corpus. +/// +/// For example, when fuzzing an API consisting of parsing and other logic, +/// one may want to allow only those inputs into the corpus that parse +/// successfully. To indicate whether an input should be kept in or rejected +/// from the corpus, return either [Corpus::Keep] or [Corpus::Reject] from your +/// fuzz target. The default behavior (e.g. if `()` is returned) is to keep the +/// input in the corpus. +/// +/// For example: +/// +/// ```no_run +/// #![no_main] +/// +/// use libfuzzer_sys::{Corpus, fuzz_target}; +/// +/// fuzz_target!(|input: String| -> Corpus { +/// let parts: Vec<&str> = input.splitn(2, '=').collect(); +/// if parts.len() != 2 { +/// return Corpus::Reject; +/// } +/// +/// let key = parts[0]; +/// let value = parts[1]; +/// let _result: Result<_, _> = my_crate::parse(key, value); +/// Corpus::Keep +/// }); +/// # mod my_crate { pub fn parse(_key: &str, _value: &str) -> Result<(), ()> { unimplemented!() } } +/// ``` +/// +/// ## Arbitrary Input Types +/// +/// The input is a `&[u8]` slice by default, but you can take arbitrary input +/// types, as long as the type implements [the `arbitrary` crate's `Arbitrary` +/// trait](https://docs.rs/arbitrary/*/arbitrary/trait.Arbitrary.html) (which is +/// also re-exported as `libfuzzer_sys::arbitrary::Arbitrary` for convenience). +/// +/// For example, if you wanted to take an arbitrary RGB color, you could do the +/// following: +/// +/// ```no_run +/// #![no_main] +/// # mod foo { +/// +/// use libfuzzer_sys::{arbitrary::{Arbitrary, Error, Unstructured}, fuzz_target}; +/// +/// #[derive(Debug)] +/// pub struct Rgb { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// +/// impl<'a> Arbitrary<'a> for Rgb { +/// fn arbitrary(raw: &mut Unstructured<'a>) -> Result { +/// let mut buf = [0; 3]; +/// raw.fill_buffer(&mut buf)?; +/// let r = buf[0]; +/// let g = buf[1]; +/// let b = buf[2]; +/// Ok(Rgb { r, g, b }) +/// } +/// } +/// +/// // Write a fuzz target that works with RGB colors instead of raw bytes. +/// fuzz_target!(|color: Rgb| { +/// my_crate::convert_color(color); +/// }); +/// # mod my_crate { +/// # use super::Rgb; +/// # pub fn convert_color(_: Rgb) {} +/// # } +/// # } +/// ``` +/// +/// You can also enable the `arbitrary` crate's custom derive via this crate's +/// `"arbitrary-derive"` cargo feature. +/// +/// ## Init Code +/// +/// Init code to the fuzz target by using the `init` keyword. This is called once before the fuzzer starts. +/// Supports short |input| or |input: | syntax. +/// +/// ```no_run +/// #![no_main] +/// +/// use libfuzzer_sys::fuzz_target; +/// use std::collections::HashSet; +/// use std::sync::OnceLock; +/// +/// static DICTIONARY: OnceLock> = OnceLock::new(); +/// +/// fuzz_target!( +/// init: { +/// let read_dictionary = |_| unimplemented!(); +/// let dictionary = read_dictionary("/usr/share/dict/words"); +/// DICTIONARY.set(dictionary).unwrap(); +/// }, +/// |input| { +/// // Use the initialized `DICTIONARY` here... +/// } +/// ); +/// ``` +/// +#[macro_export] +macro_rules! fuzz_target { + (|$bytes:ident| $body:expr) => { + $crate::fuzz_target!(init: (), |$bytes: &[u8]| -> () { $body }); + }; + + (|$bytes:ident: &[u8]| $body:expr) => { + $crate::fuzz_target!(init: (), |$bytes: &[u8]| -> () { $body }); + }; + + (|$bytes:ident: &[u8]| -> $rty:ty $body:block) => { + $crate::fuzz_target!(init: (), |$bytes: &[u8]| -> $rty { $body }); + }; + + (init: $init:expr, |$bytes:ident| $body:expr) => { + $crate::fuzz_target!(init: $init, |$bytes: &[u8]| -> () { $body }); + }; + + (init: $init:expr, |$bytes:ident: &[u8]| $body:expr) => { + $crate::fuzz_target!(init: $init, |$bytes: &[u8]| -> () { $body }); + }; + + (init: $init:expr, |$bytes:ident: &[u8]| -> $rty:ty $body:block) => { + const _: () = { + /// Auto-generated functions + /// LLVMFuzzerInitialize is called once before the fuzzer starts. + #[no_mangle] + pub extern "C" fn LLVMFuzzerInitialize(_argc: *const isize, _argv: *const *const *const u8) -> isize { + $crate::initialize(_argc, _argv); + + // Supplied init code + $init; + 0 + } + + #[no_mangle] + pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) -> i32 { + // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug + // formatting of the input to that file. This is only intended for + // `cargo fuzz`'s use! + + // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization. + if let Some(path) = $crate::rust_libfuzzer_debug_path() { + use std::io::Write; + let mut file = std::fs::File::create(path) + .expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file"); + writeln!(&mut file, "{:?}", bytes) + .expect("failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file"); + return 0; + } + + let result = ::libfuzzer_sys::Corpus::from(__libfuzzer_sys_run(bytes)); + result.to_libfuzzer_code() + } + + // Split out the actual fuzzer into a separate function which is + // tagged as never being inlined. This ensures that if the fuzzer + // panics there's at least one stack frame which is named uniquely + // according to this specific fuzzer that this is embedded within. + // + // Systems like oss-fuzz try to deduplicate crashes and without this + // panics in separate fuzzers can accidentally appear the same + // because each fuzzer will have a function called + // `rust_fuzzer_test_input`. By using a normal Rust function here + // it's named something like `the_fuzzer_name::_::__libfuzzer_sys_run` which should + // ideally help prevent oss-fuzz from deduplicate fuzz bugs across + // distinct targets accidentally. + #[inline(never)] + fn __libfuzzer_sys_run($bytes: &[u8]) -> $rty { + $body + } + }; + }; + + (|$data:ident: $dty:ty| $body:expr) => { + $crate::fuzz_target!(init: (), |$data: $dty| -> () { $body }); + }; + + (|$data:ident: $dty:ty| -> $rty:ty $body:block) => { + $crate::fuzz_target!(init: (), |$data: $dty| -> $rty { $body }); + }; + + (init: $init:expr, |$data:ident: $dty:ty| $body:expr) => { + $crate::fuzz_target!(init: $init, |$data: $dty| -> () { $body }); + }; + + (init: $init:expr, |$data:ident: $dty:ty| -> $rty:ty $body:block) => { + const _: () = { + /// Auto-generated functions + /// LLVMFuzzerInitialize is called once before the fuzzer starts. + #[no_mangle] + pub extern "C" fn LLVMFuzzerInitialize(_argc: *const isize, _argv: *const *const *const u8) -> isize { + $crate::initialize(_argc, _argv); + + // Supplied init code + $init; + 0 + } + + #[no_mangle] + pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) -> i32 { + use $crate::arbitrary::{Arbitrary, Unstructured}; + + // Early exit if we don't have enough bytes for the `Arbitrary` + // implementation. This helps the fuzzer avoid exploring all the + // different not-enough-input-bytes paths inside the `Arbitrary` + // implementation. Additionally, it exits faster, letting the fuzzer + // get to longer inputs that actually lead to interesting executions + // quicker. + if bytes.len() < <$dty as Arbitrary>::size_hint(0).0 { + return -1; + } + + let mut u = Unstructured::new(bytes); + let data = <$dty as Arbitrary>::arbitrary_take_rest(u); + + // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug + // formatting of the input to that file. This is only intended for + // `cargo fuzz`'s use! + + // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization. + if let Some(path) = $crate::rust_libfuzzer_debug_path() { + use std::io::Write; + let mut file = std::fs::File::create(path) + .expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file"); + (match data { + Ok(data) => writeln!(&mut file, "{:#?}", data), + Err(err) => writeln!(&mut file, "Arbitrary Error: {}", err), + }) + .expect("failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file"); + return -1; + } + + let data = match data { + Ok(d) => d, + Err(_) => return -1, + }; + + let result = ::libfuzzer_sys::Corpus::from(__libfuzzer_sys_run(data)); + result.to_libfuzzer_code() + } + // See above for why this is split to a separate function. + #[inline(never)] + fn __libfuzzer_sys_run($data: $dty) -> $rty { + $body + } + }; + }; +} + +/// Define a custom mutator. +/// +/// This is optional, and libFuzzer will use its own, default mutation strategy +/// if this is not provided. +/// +/// You might consider using a custom mutator when your fuzz target is very +/// particular about the shape of its input: +/// +/// * You want to fuzz "deeper" than just the parser. +/// * The input contains checksums that have to match the hash of some subset of +/// the data or else the whole thing is invalid, and therefore mutating any of +/// that subset means you need to recompute the checksums. +/// * Small random changes to the input buffer make it invalid. +/// +/// That is, a custom mutator is useful in similar situations where [a `T: +/// Arbitrary` input type](macro.fuzz_target.html#arbitrary-input-types) is +/// useful. Note that the two approaches are not mutually exclusive; you can use +/// whichever is easier for your problem domain or both! +/// +/// ## Implementation Contract +/// +/// The original, unmodified input is given in `data[..size]`. +/// +/// You must modify the data in place and return the new size. +/// +/// The new size should not be greater than `max_size`. If this is not the case, +/// then the `data` will be truncated to fit within `max_size`. Note that +/// `max_size < size` is possible when shrinking test cases. +/// +/// You must produce the same mutation given the same `seed`. Generally, when +/// choosing what kind of mutation to make or where to mutate, you should start +/// by creating a random number generator (RNG) that is seeded with the given +/// `seed` and then consult the RNG whenever making a decision: +/// +/// ```no_run +/// #![no_main] +/// +/// use rand::{rngs::StdRng, Rng, SeedableRng}; +/// +/// libfuzzer_sys::fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| { +/// let mut rng = StdRng::seed_from_u64(seed as u64); +/// +/// # let first_mutation = |_, _, _, _| todo!(); +/// # let second_mutation = |_, _, _, _| todo!(); +/// # let third_mutation = |_, _, _, _| todo!(); +/// # let fourth_mutation = |_, _, _, _| todo!(); +/// // Choose which of our four supported kinds of mutations we want to make. +/// match rng.gen_range(0..4) { +/// 0 => first_mutation(rng, data, size, max_size), +/// 1 => second_mutation(rng, data, size, max_size), +/// 2 => third_mutation(rng, data, size, max_size), +/// 3 => fourth_mutation(rng, data, size, max_size), +/// _ => unreachable!() +/// } +/// }); +/// ``` +/// +/// ## Example: Compression +/// +/// Consider a simple fuzz target that takes compressed data as input, +/// decompresses it, and then asserts that the decompressed data doesn't begin +/// with "boom". It is difficult for `libFuzzer` (or any other fuzzer) to crash +/// this fuzz target because nearly all mutations it makes will invalidate the +/// compression format. Therefore, we use a custom mutator that decompresses the +/// raw input, mutates the decompressed data, and then recompresses it. This +/// allows `libFuzzer` to quickly discover crashing inputs. +/// +/// ```no_run +/// #![no_main] +/// +/// use flate2::{read::GzDecoder, write::GzEncoder, Compression}; +/// use libfuzzer_sys::{fuzz_mutator, fuzz_target}; +/// use std::io::{Read, Write}; +/// +/// fuzz_target!(|data: &[u8]| { +/// // Decompress the input data and crash if it starts with "boom". +/// if let Some(data) = decompress(data) { +/// if data.starts_with(b"boom") { +/// panic!(); +/// } +/// } +/// }); +/// +/// fuzz_mutator!( +/// |data: &mut [u8], size: usize, max_size: usize, _seed: u32| { +/// // Decompress the input data. If that fails, use a dummy value. +/// let mut decompressed = decompress(&data[..size]).unwrap_or_else(|| b"hi".to_vec()); +/// +/// // Mutate the decompressed data with `libFuzzer`'s default mutator. Make +/// // the `decompressed` vec's extra capacity available for insertion +/// // mutations via `resize`. +/// let len = decompressed.len(); +/// let cap = decompressed.capacity(); +/// decompressed.resize(cap, 0); +/// let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len, cap); +/// +/// // Recompress the mutated data. +/// let compressed = compress(&decompressed[..new_decompressed_size]); +/// +/// // Copy the recompressed mutated data into `data` and return the new size. +/// let new_size = std::cmp::min(max_size, compressed.len()); +/// data[..new_size].copy_from_slice(&compressed[..new_size]); +/// new_size +/// } +/// ); +/// +/// fn decompress(compressed_data: &[u8]) -> Option> { +/// let mut decoder = GzDecoder::new(compressed_data); +/// let mut decompressed = Vec::new(); +/// if decoder.read_to_end(&mut decompressed).is_ok() { +/// Some(decompressed) +/// } else { +/// None +/// } +/// } +/// +/// fn compress(data: &[u8]) -> Vec { +/// let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); +/// encoder +/// .write_all(data) +/// .expect("writing into a vec is infallible"); +/// encoder.finish().expect("writing into a vec is infallible") +/// } +/// ``` +/// +/// This example is inspired by [a similar example from the official `libFuzzer` +/// docs](https://github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md#example-compression). +/// +/// ## More Example Ideas +/// +/// * A PNG custom mutator that decodes a PNG, mutates the image, and then +/// re-encodes the mutated image as a new PNG. +/// +/// * A [`serde`](https://serde.rs/) custom mutator that deserializes your +/// structure, mutates it, and then reserializes it. +/// +/// * A Wasm binary custom mutator that inserts, replaces, and removes a +/// bytecode instruction in a function's body. +/// +/// * An HTTP request custom mutator that inserts, replaces, and removes a +/// header from an HTTP request. +#[macro_export] +macro_rules! fuzz_mutator { + ( + | + $data:ident : &mut [u8] , + $size:ident : usize , + $max_size:ident : usize , + $seed:ident : u32 $(,)* + | + $body:block + ) => { + /// Auto-generated function. Do not use; only for LibFuzzer's + /// consumption. + #[export_name = "LLVMFuzzerCustomMutator"] + #[doc(hidden)] + pub unsafe fn rust_fuzzer_custom_mutator( + $data: *mut u8, + $size: usize, + $max_size: usize, + $seed: std::os::raw::c_uint, + ) -> usize { + // Depending on if we are growing or shrinking the test case, `size` + // might be larger or smaller than `max_size`. The `data`'s capacity + // is the maximum of the two. + let len = std::cmp::max($max_size, $size); + let $data: &mut [u8] = std::slice::from_raw_parts_mut($data, len); + + // `unsigned int` is generally a `u32`, but not on all targets. Do + // an infallible (and potentially lossy, but that's okay because it + // preserves determinism) conversion. + let $seed = $seed as u32; + + // Define and invoke a new, safe function so that the body doesn't + // inherit `unsafe`. + fn custom_mutator( + $data: &mut [u8], + $size: usize, + $max_size: usize, + $seed: u32, + ) -> usize { + $body + } + let new_size = custom_mutator($data, $size, $max_size, $seed); + + // Truncate the new size if it is larger than the max. + std::cmp::min(new_size, $max_size) + } + }; +} + +/// The default `libFuzzer` mutator. +/// +/// You generally don't have to use this at all unless you're defining a +/// custom mutator with [the `fuzz_mutator!` macro][crate::fuzz_mutator]. +/// +/// Mutates `data[..size]` in place such that the mutated data is no larger than +/// `max_size` and returns the new size of the mutated data. +/// +/// To only allow shrinking mutations, make `max_size < size`. +/// +/// To additionally allow mutations that grow the size of the data, make +/// `max_size > size`. +/// +/// Both `size` and `max_size` must be less than or equal to `data.len()`. +/// +/// # Example +/// +/// ```no_run +/// // Create some data in a buffer. +/// let mut data = vec![0; 128]; +/// data[..b"hello".len()].copy_from_slice(b"hello"); +/// +/// // Ask `libFuzzer` to mutate the data. By setting `max_size` to our buffer's +/// // full length, we are allowing `libFuzzer` to perform mutations that grow +/// // the size of the data, such as insertions. +/// let size = b"hello".len(); +/// let max_size = data.len(); +/// let new_size = libfuzzer_sys::fuzzer_mutate(&mut data, size, max_size); +/// +/// // Get the mutated data out of the buffer. +/// let mutated_data = &data[..new_size]; +/// ``` +pub fn fuzzer_mutate(data: &mut [u8], size: usize, max_size: usize) -> usize { + assert!(size <= data.len()); + assert!(max_size <= data.len()); + let new_size = unsafe { LLVMFuzzerMutate(data.as_mut_ptr(), size, max_size) }; + assert!(new_size <= data.len()); + new_size +} + +/// Define a custom cross-over function to combine test cases. +/// +/// This is optional, and libFuzzer will use its own, default cross-over strategy +/// if this is not provided. (As of the time of writing, this default strategy +/// takes alternating byte sequences from the two test cases, to construct the +/// new one) (see `FuzzerCrossOver.cpp`) +/// +/// This could potentially be useful if your input is, for instance, a +/// sequence of fixed sized, multi-byte values and the crossover could then +/// merge discrete values rather than joining parts of a value. +/// +/// ## Implementation Contract +/// +/// The original, read-only inputs are given in the full slices of `data1`, and +/// `data2` (as opposed to the, potentially, partial slice of `data` in +/// [the `fuzz_mutator!` macro][crate::fuzz_mutator]). +/// +/// You must place the new input merged from the two existing inputs' data +/// into `out` and return the size of the relevant data written to that slice. +/// +/// The deterministic requirements from [the `fuzz_mutator!` macro][crate::fuzz_mutator] +/// apply as well to the `seed` parameter +/// +/// ## Example: Floating-Point Sum NaN +/// +/// ```no_run +/// #![no_main] +/// +/// use libfuzzer_sys::{fuzz_crossover, fuzz_mutator, fuzz_target, fuzzer_mutate}; +/// use rand::{rngs::StdRng, Rng, SeedableRng}; +/// use std::mem::size_of; +/// +/// fuzz_target!(|data: &[u8]| { +/// let (_, floats, _) = unsafe { data.align_to::() }; +/// +/// let res = floats +/// .iter() +/// .fold(0.0, |a, b| if b.is_nan() { a } else { a + b }); +/// +/// assert!( +/// !res.is_nan(), +/// "The sum of the following floats resulted in a NaN: {floats:?}" +/// ); +/// }); +/// +/// // Inject some ...potentially problematic values to make the example close +/// // more quickly. +/// fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| { +/// let mut gen = StdRng::seed_from_u64(seed.into()); +/// +/// let (_, floats, _) = unsafe { data[..size].align_to_mut::() }; +/// +/// let x = gen.gen_range(0..=1000); +/// if x == 0 && !floats.is_empty() { +/// floats[0] = f64::INFINITY; +/// } else if x == 1000 && floats.len() > 1 { +/// floats[1] = f64::NEG_INFINITY; +/// } else { +/// return fuzzer_mutate(data, size, max_size); +/// } +/// +/// size +/// }); +/// +/// fuzz_crossover!(|data1: &[u8], data2: &[u8], out: &mut [u8], _seed: u32| { +/// // Decode each source to see how many floats we can pull with proper +/// // alignment, and destination as to how many will fit with proper alignment +/// // +/// // Keep track of the unaligned prefix to `out`, as we will need to remember +/// // that those bytes will remain prepended to the actual floats that we +/// // write into the out buffer. +/// let (out_pref, out_floats, _) = unsafe { out.align_to_mut::() }; +/// let (_, d1_floats, _) = unsafe { data1.align_to::() }; +/// let (_, d2_floats, _) = unsafe { data2.align_to::() }; +/// +/// // Put into the destination, floats first from data1 then from data2, ...if +/// // possible given the size of `out` +/// let mut i: usize = 0; +/// for float in d1_floats.iter().chain(d2_floats).take(out_floats.len()) { +/// out_floats[i] = *float; +/// i += 1; +/// } +/// +/// // Now that we have written the true floats, report back to the fuzzing +/// // engine that we left the unaligned `out` prefix bytes at the beginning of +/// // `out` and also then the floats that we wrote into the aligned float +/// // section. +/// out_pref.len() * size_of::() + i * size_of::() +/// }); +/// ``` +/// +/// This example is a minimized version of [Erik Rigtorp's floating point +/// summation fuzzing example][1]. A more detailed version of this experiment +/// can be found in the `example_crossover` directory. +/// +/// [1]: https://rigtorp.se/fuzzing-floating-point-code/ +#[macro_export] +macro_rules! fuzz_crossover { + ( + | + $data1:ident : &[u8] , + $data2:ident : &[u8] , + $out:ident : &mut [u8] , + $seed:ident : u32 $(,)* + | + $body:block + ) => { + /// Auto-generated function. Do not use; only for LibFuzzer's + /// consumption. + #[export_name = "LLVMFuzzerCustomCrossOver"] + #[doc(hidden)] + pub unsafe fn rust_fuzzer_custom_crossover( + $data1: *const u8, + size1: usize, + $data2: *const u8, + size2: usize, + $out: *mut u8, + max_out_size: usize, + $seed: std::os::raw::c_uint, + ) -> usize { + let $data1: &[u8] = std::slice::from_raw_parts($data1, size1); + let $data2: &[u8] = std::slice::from_raw_parts($data2, size2); + let $out: &mut [u8] = std::slice::from_raw_parts_mut($out, max_out_size); + + // `unsigned int` is generally a `u32`, but not on all targets. Do + // an infallible (and potentially lossy, but that's okay because it + // preserves determinism) conversion. + let $seed = $seed as u32; + + // Define and invoke a new, safe function so that the body doesn't + // inherit `unsafe`. + fn custom_crossover( + $data1: &[u8], + $data2: &[u8], + $out: &mut [u8], + $seed: u32, + ) -> usize { + $body + } + + custom_crossover($data1, $data2, $out, $seed) + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/update-libfuzzer.sh clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/update-libfuzzer.sh --- clamav-1.4.3+dfsg/.cargo/vendor/libfuzzer-sys/update-libfuzzer.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libfuzzer-sys/update-libfuzzer.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +#!/bin/bash -ex + +# Usage: +# +# $ ./update-libfuzzer.sh + +set -ex + +# The LLVM commit from which we are vendoring libfuzzer. This must be a commit +# hash from https://github.com/llvm/llvm-project +COMMIT=6146a88f60492b520a36f8f8f3231e15f3cc6082 + +cd "$(dirname $0)" +project_dir="$(pwd)" + +tmp_dir="$(mktemp -d)" +cd "$tmp_dir" + +git init +git remote add llvm https://github.com/llvm/llvm-project.git +git sparse-checkout set compiler-rt/lib/fuzzer + +git fetch --depth 1 llvm "$COMMIT" --filter=blob:none +git checkout "$COMMIT" + +rm -rf "$project_dir/libfuzzer/" +mv "$tmp_dir/compiler-rt/lib/fuzzer/" "$project_dir/libfuzzer/" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libloading/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/libloading/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"d97d9cdce69985cab52ba027b089854906d4cf653d581e9742530a536b4599fc","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"707e1cae9fa4b691ce5cb8a3976573158fc60b67cb89948f8f5d51c5908bd0a8","src/changelog.rs":"e7c18ebb9be9624b64bcca3f39d714084cbbaa2ffbc35bfc033967b81be1af66","src/error.rs":"488004e68022adba1002c95d1c8f568fdf1f7bc88aedb6a0f5e31a3dab6f8509","src/lib.rs":"0142a630bb27d1443a8a79d1d5559ea10e859d587442c596d2be7d837507afa0","src/os/mod.rs":"6c59ef8c1120953ae6b6c32f27766c643ca90d85075c49c3545d2fe1ed82cedd","src/os/unix/consts.rs":"a1f98372a58acc6d00a1df19550e0593ede60a53f2aa3ff26cf678cf1015594c","src/os/unix/mod.rs":"15e284c70b61c2728cdf312c2c8740d1671a53dbc7161d8ad5c8a909416644cc","src/os/windows/mod.rs":"8a8792569d43140d982edd6d401abb82023894eb02f2eeba321ee9887568cf3b","src/safe.rs":"b0dc1cb5c8e0216e365063b5e84218b2377bb7a62714fca9a6215a22a7bc58b8","src/test_helpers.rs":"201403e143e5b3204864124cd38067cf8813d5273dc1a9099288a9dc4bdd15b6","src/util.rs":"0b6dcfb9eafff2d87966460ef6b1b99980f888813037e787ed92deee602f8c2b","tests/constants.rs":"4778c062605ed22238c1bed16de4c076d0857282f090f36e6d985dafb7b4544d","tests/functions.rs":"c3d4770704de40e9592cfd109cf506e6b04f0738d8a1ee02ec858b4fa4632a2b","tests/library_filename.rs":"b1481f0bb374687c5f24e25113426d2a95f08a45fb8bc41a41e8702bd5a7b4bf","tests/markers.rs":"0ebc8f807b92e39452d35732988012cdca7ce96231c57eaac9c3f4217225ad39","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"35584a46658b305cd539712d3ba3c21fe7a130fd693aa1389e4886a67625d532"},"package":"0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ebbfcf8175cd4fb9552cdbc0c46ac7ce77de70bc96b035484337b318adb47249",".github/workflows/libloading.yml":"30406311c09374078d1c770a641d352563837813406ffd41083d6e62ed20a72d","Cargo.toml":"d97d9cdce69985cab52ba027b089854906d4cf653d581e9742530a536b4599fc","Cargo.toml.orig":"3c0333137944267dfa8d747bd62e7629f9c328ac9fa158bf688ad3e1cb692f4c","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"707e1cae9fa4b691ce5cb8a3976573158fc60b67cb89948f8f5d51c5908bd0a8","src/changelog.rs":"e7c18ebb9be9624b64bcca3f39d714084cbbaa2ffbc35bfc033967b81be1af66","src/error.rs":"488004e68022adba1002c95d1c8f568fdf1f7bc88aedb6a0f5e31a3dab6f8509","src/lib.rs":"0142a630bb27d1443a8a79d1d5559ea10e859d587442c596d2be7d837507afa0","src/os/mod.rs":"6c59ef8c1120953ae6b6c32f27766c643ca90d85075c49c3545d2fe1ed82cedd","src/os/unix/consts.rs":"a1f98372a58acc6d00a1df19550e0593ede60a53f2aa3ff26cf678cf1015594c","src/os/unix/mod.rs":"15e284c70b61c2728cdf312c2c8740d1671a53dbc7161d8ad5c8a909416644cc","src/os/windows/mod.rs":"8a8792569d43140d982edd6d401abb82023894eb02f2eeba321ee9887568cf3b","src/safe.rs":"b0dc1cb5c8e0216e365063b5e84218b2377bb7a62714fca9a6215a22a7bc58b8","src/test_helpers.rs":"201403e143e5b3204864124cd38067cf8813d5273dc1a9099288a9dc4bdd15b6","src/util.rs":"0b6dcfb9eafff2d87966460ef6b1b99980f888813037e787ed92deee602f8c2b","tests/constants.rs":"4778c062605ed22238c1bed16de4c076d0857282f090f36e6d985dafb7b4544d","tests/functions.rs":"c3d4770704de40e9592cfd109cf506e6b04f0738d8a1ee02ec858b4fa4632a2b","tests/library_filename.rs":"b1481f0bb374687c5f24e25113426d2a95f08a45fb8bc41a41e8702bd5a7b4bf","tests/markers.rs":"0ebc8f807b92e39452d35732988012cdca7ce96231c57eaac9c3f4217225ad39","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"35584a46658b305cd539712d3ba3c21fe7a130fd693aa1389e4886a67625d532"},"package":"0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libloading/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/libloading/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libloading/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "dc8664fd23a34b16e240c1bd48acbe3596cb8eef" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libloading/.github/workflows/libloading.yml clamav-1.4.6+dfsg/.cargo/vendor/libloading/.github/workflows/libloading.yml --- clamav-1.4.3+dfsg/.cargo/vendor/libloading/.github/workflows/libloading.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libloading/.github/workflows/libloading.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,105 @@ +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: [master] + paths-ignore: ['*.mkd', 'LICENSE'] + pull_request: + types: [opened, reopened, synchronize] + +jobs: + native-test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + rust_toolchain: [nightly, stable, 1.56.0] + os: [ubuntu-latest, windows-latest, macOS-latest] + timeout-minutes: 20 + steps: + - uses: actions/checkout@v2 + - run: rustup install ${{ matrix.rust_toolchain }} --profile=minimal + - run: rustup default ${{ matrix.rust_toolchain }} + - run: rustup component add clippy + - run: cargo clippy + - run: cargo test -- --nocapture + - run: cargo test --release -- --nocapture + - run: cargo rustdoc -Zunstable-options --config 'build.rustdocflags=["--cfg", "libloading_docs", "-D", "rustdoc::broken_intra_doc_links"]' + if: ${{ matrix.rust_toolchain == 'nightly' }} + # pwsh.exe drops quotes kekw. https://stackoverflow.com/a/59036879 + shell: bash + + windows-test: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + rust_toolchain: [nightly, stable] + rust_target: + - x86_64-pc-windows-gnu + - i686-pc-windows-gnu + include: + - rust_target: x86_64-pc-windows-gnu + mingw_path: C:/msys64/mingw64/bin + package: mingw-w64-x86_64-gcc + - rust_target: i686-pc-windows-gnu + mingw_path: C:/msys64/mingw32/bin + package: mingw-w64-i686-gcc + steps: + - uses: actions/checkout@v2 + - run: rustup install ${{ matrix.rust_toolchain }} --profile=minimal + - run: rustup default ${{ matrix.rust_toolchain }} + - run: rustup target add ${{ matrix.rust_target }} + - uses: msys2/setup-msys2@v2 + with: + release: false + install: ${{ matrix.package }} + - run: echo "c:/msys64/bin" | Out-File -FilePath $env:GITHUB_PATH -Append + - run: echo "${{ matrix.mingw_path }}" | Out-File -FilePath $env:GITHUB_PATH -Append + if: ${{ matrix.mingw_path }}" + - run: cargo test --target ${{ matrix.rust_target }} + env: + TARGET: ${{ matrix.rust_target}} + + bare-cross-build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust_toolchain: [nightly] + rust_target: + # BSDs: could be tested with full system emulation + # - x86_64-unknown-dragonfly + # - x86_64-unknown-freebsd + - x86_64-unknown-haiku + # - x86_64-unknown-netbsd + - x86_64-unknown-openbsd + - x86_64-unknown-redox + - x86_64-fuchsia + - wasm32-unknown-unknown + timeout-minutes: 20 + steps: + - uses: actions/checkout@v2 + - run: rustup install ${{ matrix.rust_toolchain }} --profile=minimal + - run: rustup default ${{ matrix.rust_toolchain }} + - run: rustup component add rust-src --toolchain nightly --target ${{ matrix.rust_target }} + - run: cargo build --target ${{ matrix.rust_target }} -Zbuild-std + + cross-ios-build: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + rust_toolchain: [nightly, stable] + rust_target: + - aarch64-apple-ios + - x86_64-apple-ios + timeout-minutes: 20 + steps: + - uses: actions/checkout@v2 + - run: rustup install ${{ matrix.rust_toolchain }} --profile=minimal + - run: rustup default ${{ matrix.rust_toolchain }} + - run: rustup target add ${{ matrix.rust_target }} + - run: cargo build --target=${{ matrix.rust_target }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/libloading/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/libloading/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/libloading/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/libloading/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +[package] +name = "libloading" +# When bumping +# * Don’t forget to add an entry to `src/changelog.rs` +# * If bumping to an incompatible version, adjust the documentation in `src/lib.rs` +version = "0.8.3" +authors = ["Simonas Kazlauskas "] +license = "ISC" +repository = "https://github.com/nagisa/rust_libloading/" +documentation = "https://docs.rs/libloading/" +readme = "README.mkd" +description = "Bindings around the platform's dynamic library loading primitives with greatly improved memory safety." +keywords = ["dlopen", "load", "shared", "dylib"] +categories = ["api-bindings"] +rust-version = "1.56.0" + +[target.'cfg(windows)'.dependencies.windows-targets] +version = ">=0.48, <0.53" + +[target.'cfg(windows)'.dev-dependencies.windows-sys] +version = "0.52" +features = ["Win32_Foundation"] + +[target.'cfg(unix)'.dependencies.cfg-if] +version = "1" + +[dev-dependencies] +libc = "0.2" +static_assertions = "1.1" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "libloading_docs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CODE_OF_CONDUCT.md":"ccd9e538ce44713a2486cc8e4c01b8c8b846d1ccff15de728d8d6fa9a7f846cd","COPYRIGHT":"3290ae0fbc9ddb77d2239121d710f0bb9d31b3b4744e6d97fe01e652b4c1870b","Cargo.toml":"79db455f0f60a19369addc51b65e686d1f9ec0d2fac3017f50a8a1f1668342f5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-Apache-2.0_WITH_LLVM-exception":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","ORG_CODE_OF_CONDUCT.md":"a62b69bf86e605ee1bcbb2f0a12ba79e4cebb6983a7b6491949750aecc4f2178","README.md":"3d4ae2ec9429adfd329b4506f7ca6faa84dca30d1c3b416f8f4e6f57bdb3aa96","src/aarch64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/aarch64/general.rs":"0cc1ed00b1ef7efb16a7109138acdf679d591325458938cee150b221af063822","src/aarch64/if_ether.rs":"f558bfec1f5e80235db79f507e4afd3120647a5caddf17a87b7ad5540e5c1462","src/aarch64/if_packet.rs":"78c1154790a6a8bbe14b0ff08465fa2e090cbf5f6528b5526053b5d8ff568133","src/aarch64/io_uring.rs":"9ce4c9005b5b99e041b9d58be6866367605e4bee1e30a7096235cb234ed73e1b","src/aarch64/ioctl.rs":"4ec2865dd9d66287b741ed5d68ffbbd9ef65b4010abb4f9ff7e7024e1a202dfc","src/aarch64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/aarch64/net.rs":"53279ed39ebe891b02824ccb380083f8fa1c6cd92b03195d1c680e1bcfcab0a1","src/aarch64/netlink.rs":"f6642310b8bd37b5775ba1a52cfe638beddd7c880f8dfacab62c3180255fb75f","src/aarch64/prctl.rs":"a80e2f89aa978210d980538e1d9c5b922bb073d118ee51b1f14c1f397c7cd576","src/aarch64/system.rs":"851a95c0d1b76782970a28c373a313954eea0db35f6ebce562e6047095f587c4","src/aarch64/xdp.rs":"8602704977fdf3c9721c88866dfb77ec31b949f7b44d287c41fb6616a08fbaaf","src/arm/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/arm/general.rs":"bdbb40ba5630044c9555fe38a3640638f3ff7f437d94f82428e2bedad32e180f","src/arm/if_ether.rs":"3873beb1f57bdcc52da345608c5deda5937d7b92b114b414ce6161784173b925","src/arm/if_packet.rs":"45e401c44d540bde6f7b2a5c4b67adf99353639bd7d82829480b34a6a174f4ca","src/arm/io_uring.rs":"5e2e254d5853ed30568e17fab184f8cc458607465d19dcee6c87ca1b565d6d2d","src/arm/ioctl.rs":"3f470208ae7e26b356a182a8396b8e4e7522e52d280a0b220c0b79b90ec8fb75","src/arm/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/arm/net.rs":"0b2addcd77882d71155bbe6e501ab2927ddca878effb4e8a6d4bce4d02ee6fef","src/arm/netlink.rs":"2f98b8c0349c2d3d538164e4d06c28fa1fb9308f7691aa097526ce2fb3ac176f","src/arm/prctl.rs":"5477c74fec958d9f9d2028f58e95657840ead28445956e53fe0894e45922f8a5","src/arm/system.rs":"9aca94a4a553e09e6d2d43741fb8c120c05a193822e850951dc469bbd89cc703","src/arm/xdp.rs":"a4ae33a218d9967b56b3c70d3c1c1180df49379b05044e3a5c7534b542b4a529","src/csky/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/csky/general.rs":"94aba82d2a76a9ca272b4766f8d2f5f14e10bc2166e03d695a5b8b5d207e6755","src/csky/if_ether.rs":"aac7a069000195b9b18c6d25b2d7c338efb1062347a84e31cda7c93de374b3c6","src/csky/if_packet.rs":"f88c8926dea84c835ad156b389ad29f50f9e8cb453cdfb5aece6d9fc9be681b6","src/csky/io_uring.rs":"bb7541d82f627cb681ea11f4e5c4162b0d0616ca08fcc6d31bcf22ef813f754d","src/csky/ioctl.rs":"54ee7b43b78b1920159fd924a1110a1c77d072113bb28b29991eacac9bff1a93","src/csky/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/csky/net.rs":"508650776f6a282e9a1d5109e08ff0d1678d86d1068fe43a9870f37787755166","src/csky/netlink.rs":"9fc99e88df0efc15d39b397c9d653c32b4729e31a2434e730435fbdfcb362da4","src/csky/prctl.rs":"8df2f33387d5b4865d9417f796cc4d43b3cf549cfa41d7ce7d41dd367ed8b6c9","src/csky/system.rs":"a2913685b359e60bbfae413b89a6fd37ea38fa448f980ffadef42d227b33ada5","src/csky/xdp.rs":"2138939b87c7c75d2b3ee499507142e2a5abeecd40783c297dd3c555285b3a54","src/elf.rs":"441bcf378b5603f957e053369d18d95c1efe981665846c220bca82123c04843a","src/lib.rs":"be5d81f17a8d15b2f631e362cf87b2ee3217fda06457cfc319b25ecb5c6732eb","src/loongarch64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/loongarch64/general.rs":"fadd5884c6ad645300540dd30150984857819a986772fca4eba1e1fc0c3f4f1e","src/loongarch64/if_ether.rs":"a7b0918afc9dbf8e79490f83a809e4bd563af20ab2b3432d58b763ff31418daf","src/loongarch64/if_packet.rs":"25e69ec7b16d27befb2b64c8540011563f3c02991588489b258febbbcf7c45d0","src/loongarch64/io_uring.rs":"ef851913c86bc2d629048e781edc76b59c63e659f8bd4bcd7fa7ff982186ed6d","src/loongarch64/ioctl.rs":"6f631e0ac37f2c2398168683a1523d1559b85369ffe4cdcc284ffe7455672c18","src/loongarch64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/loongarch64/net.rs":"af6d52d44def3ebdb01e047c588f353a9a3e6d20c6c57be5a846270a4505235b","src/loongarch64/netlink.rs":"789357343b94276e6f8fc8f3a32f06f3d3efd464c7850b2568dc609a49d1f305","src/loongarch64/prctl.rs":"624e4d3b8f3b4f1d6dcb1540c124ed03ce47f0580aa3425c0baed431dcd267ea","src/loongarch64/system.rs":"4cfcd4c28481b9ff5fc0330d5c713d637d3615c0184830d3a4391882eaed68f5","src/loongarch64/xdp.rs":"2270c2b3cce1cf55922ed685c6cb7197a3932d756763f7528ab36c034609d856","src/mips/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips/general.rs":"1c16f4e0a015eaf27e9a30f4b74ec824220798f47c535d3aaf322ad799c054ab","src/mips/if_ether.rs":"1ecdc654cb3eda633bb7192829b1001a0a5ae5a126110b4208bbee5b41f87f5e","src/mips/if_packet.rs":"222bec433d7773de2d576f6341ab1f37a72df7ca39c5214a6e0fff380700930f","src/mips/io_uring.rs":"c69479bb1f862febe78e0989745c202146aaef7e8ceaa0d7bf291af584748992","src/mips/ioctl.rs":"8d4bcd3cd6aa7e87267430bc7b102df012bafa8b0ea4b24a3cfa490447431ef9","src/mips/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips/net.rs":"553750bad3660aff2efb5b2a828860792d76eddf7cb4913d3be98b34901f6a83","src/mips/netlink.rs":"5045dece259abaa5b5974500a20a9325e4cd6eb87c344dd7448056dff469994f","src/mips/prctl.rs":"cd59615adf6f561ef6c542df59cf25f75877693ca1c4c489f5e460eb7e798d4d","src/mips/system.rs":"acbc69a1fe7299860f8bd142bc2ff5595a410e1528994139062fc680d1a87e71","src/mips/xdp.rs":"0dc8bed8c75615fc119bf4cc4231ce22639515b1165911dc0b7f6d5a07dbcd44","src/mips32r6/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips32r6/general.rs":"1c16f4e0a015eaf27e9a30f4b74ec824220798f47c535d3aaf322ad799c054ab","src/mips32r6/if_ether.rs":"1ecdc654cb3eda633bb7192829b1001a0a5ae5a126110b4208bbee5b41f87f5e","src/mips32r6/if_packet.rs":"222bec433d7773de2d576f6341ab1f37a72df7ca39c5214a6e0fff380700930f","src/mips32r6/io_uring.rs":"c69479bb1f862febe78e0989745c202146aaef7e8ceaa0d7bf291af584748992","src/mips32r6/ioctl.rs":"8d4bcd3cd6aa7e87267430bc7b102df012bafa8b0ea4b24a3cfa490447431ef9","src/mips32r6/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips32r6/net.rs":"553750bad3660aff2efb5b2a828860792d76eddf7cb4913d3be98b34901f6a83","src/mips32r6/netlink.rs":"5045dece259abaa5b5974500a20a9325e4cd6eb87c344dd7448056dff469994f","src/mips32r6/prctl.rs":"cd59615adf6f561ef6c542df59cf25f75877693ca1c4c489f5e460eb7e798d4d","src/mips32r6/system.rs":"acbc69a1fe7299860f8bd142bc2ff5595a410e1528994139062fc680d1a87e71","src/mips32r6/xdp.rs":"0dc8bed8c75615fc119bf4cc4231ce22639515b1165911dc0b7f6d5a07dbcd44","src/mips64/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips64/general.rs":"700b52614c604ce58aa8a5bb1ebd46221c0106ec2d8d6600d681d1594a89118a","src/mips64/if_ether.rs":"6d24518acba5bc8fa2a775d039ed9594de8349d6028621134626ccaa8ea18bcd","src/mips64/if_packet.rs":"04ddeec1897afb84f5905e5122617d5436842aecb0480b6f36e6d0a46e7ab9c0","src/mips64/io_uring.rs":"18bd5d96c53aff44f4a37a71f16fa12c11b7c934b395bf841e47d98283146a50","src/mips64/ioctl.rs":"f0059994ece12ced8e4040aa68ccd58850119b5746d87000f8f538af8bd6359c","src/mips64/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips64/net.rs":"a5bd6d654ea16c02f6f85b969bfc2177a88603d38a9a52f09685ca4114f6e199","src/mips64/netlink.rs":"18f139573337be18fb9bd56de4d0bd8af5c80828cdf68ef68751c18dcb39c761","src/mips64/prctl.rs":"a8d9ae240ce582d7b66e13937b99df73c7247ce9f69bfdd12109903d7c6dfb0e","src/mips64/system.rs":"95805c533a8eb8f53c28f138e6a2d12064681cc9db55d3042ee748c655a5d7cd","src/mips64/xdp.rs":"19fdf2b824b95184dabd5c8960d9482788ab8ef027e23acaae9e7992be8eb4e4","src/mips64r6/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips64r6/general.rs":"700b52614c604ce58aa8a5bb1ebd46221c0106ec2d8d6600d681d1594a89118a","src/mips64r6/if_ether.rs":"6d24518acba5bc8fa2a775d039ed9594de8349d6028621134626ccaa8ea18bcd","src/mips64r6/if_packet.rs":"04ddeec1897afb84f5905e5122617d5436842aecb0480b6f36e6d0a46e7ab9c0","src/mips64r6/io_uring.rs":"18bd5d96c53aff44f4a37a71f16fa12c11b7c934b395bf841e47d98283146a50","src/mips64r6/ioctl.rs":"f0059994ece12ced8e4040aa68ccd58850119b5746d87000f8f538af8bd6359c","src/mips64r6/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips64r6/net.rs":"a5bd6d654ea16c02f6f85b969bfc2177a88603d38a9a52f09685ca4114f6e199","src/mips64r6/netlink.rs":"18f139573337be18fb9bd56de4d0bd8af5c80828cdf68ef68751c18dcb39c761","src/mips64r6/prctl.rs":"a8d9ae240ce582d7b66e13937b99df73c7247ce9f69bfdd12109903d7c6dfb0e","src/mips64r6/system.rs":"95805c533a8eb8f53c28f138e6a2d12064681cc9db55d3042ee748c655a5d7cd","src/mips64r6/xdp.rs":"19fdf2b824b95184dabd5c8960d9482788ab8ef027e23acaae9e7992be8eb4e4","src/powerpc/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/powerpc/general.rs":"7940ad742585d501f4742af51c6310ecf651863a8aaa0305193e9c8ee07aca90","src/powerpc/if_ether.rs":"56ab5fbf8c9d0dd0654412fabdca6759cbb421a876e5cebe2fec10e25728b55c","src/powerpc/if_packet.rs":"b7f556f37ba3b5e97d10065e028c4158a821b0d135893a9b4871d0d477b5ef98","src/powerpc/io_uring.rs":"38ead79180c96e8af69929dacbc36e8cfbccec96875c61f094e531e6860639db","src/powerpc/ioctl.rs":"1fabc6c3481d6710b343aa27bf9331e81d16c3cdf86eb76eac61b19839d9b2f4","src/powerpc/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/powerpc/net.rs":"d1c6c36e71354ef35f64ae1195eff75c73f0a4b90fa8a4070cab9e79b81f8b78","src/powerpc/netlink.rs":"4f10870fbd23de17efd4cba6d5a40ba85564effc5d0b71f9d7f928a42cb77b20","src/powerpc/prctl.rs":"f236987bc8ae993ab2b0e88b2eacbae51eee4da170ac075552070a76c717d803","src/powerpc/system.rs":"3e01e5e145adb87263f04c9e053faac0c0758689fd32917d2c7c2eec1d89f9e6","src/powerpc/xdp.rs":"9f04a2ef343109f1bb5ac5bc7ef66cb3c1c966744653a70a79b91f04b9609d07","src/powerpc64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/powerpc64/general.rs":"7862eb3dfac845331b624b3322bdeb3441bb86e914719e125dd5dc7b3860db43","src/powerpc64/if_ether.rs":"15e12d56b1367cb5c9d8fd1b9995acf1429a923bf603698bd732efe1acc30cd6","src/powerpc64/if_packet.rs":"272be02b20e65330c89b87ee0a642eeafdbc40b830d54d6eef041fd9eab9ec77","src/powerpc64/io_uring.rs":"50018e504d78c584beaec3b1a6d477d30d566d25cb1a40b0a2adfb23d726674f","src/powerpc64/ioctl.rs":"1fabc6c3481d6710b343aa27bf9331e81d16c3cdf86eb76eac61b19839d9b2f4","src/powerpc64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/powerpc64/net.rs":"706e58efa77918ac96f20fa33afd5f498e2e118507084c1ae9db93483103ab32","src/powerpc64/netlink.rs":"352a06995f7de6e4fc1c2ff54c1eccb93a3d833a923e834ec75c6a4d30ea5051","src/powerpc64/prctl.rs":"1fcccc5b6dac472a30b7701b5c9e436c238410077cfe158d600b51d55bcc074a","src/powerpc64/system.rs":"500116b7613a504ebad028cec1ba37323310e29864d885ae62191ccb1f86d333","src/powerpc64/xdp.rs":"baad88c60c08fc79dc3c223c0e8d9adef4462728b6e46e5143ce10f6ce5e32bd","src/riscv32/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/riscv32/general.rs":"16ffe747a8f75ac6594dc7afddef4fbb89735da50af9f19f152fd2f04b509463","src/riscv32/if_ether.rs":"aac7a069000195b9b18c6d25b2d7c338efb1062347a84e31cda7c93de374b3c6","src/riscv32/if_packet.rs":"1834cbc6b60973021393a52c88aaff0310f2dcfc1786a9d7ae13c2705752a7e0","src/riscv32/io_uring.rs":"5c67dde8fdb3641407d4ebd744171606b82596176343fe6766afd3220eda2ab1","src/riscv32/ioctl.rs":"6f631e0ac37f2c2398168683a1523d1559b85369ffe4cdcc284ffe7455672c18","src/riscv32/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/riscv32/net.rs":"508650776f6a282e9a1d5109e08ff0d1678d86d1068fe43a9870f37787755166","src/riscv32/netlink.rs":"9fc99e88df0efc15d39b397c9d653c32b4729e31a2434e730435fbdfcb362da4","src/riscv32/prctl.rs":"8df2f33387d5b4865d9417f796cc4d43b3cf549cfa41d7ce7d41dd367ed8b6c9","src/riscv32/system.rs":"a2913685b359e60bbfae413b89a6fd37ea38fa448f980ffadef42d227b33ada5","src/riscv32/xdp.rs":"2138939b87c7c75d2b3ee499507142e2a5abeecd40783c297dd3c555285b3a54","src/riscv64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/riscv64/general.rs":"8ec4907ac81b62e21451731a468e5f4fe7a37a46d80c56b33e0969d2d059d442","src/riscv64/if_ether.rs":"a7b0918afc9dbf8e79490f83a809e4bd563af20ab2b3432d58b763ff31418daf","src/riscv64/if_packet.rs":"25e69ec7b16d27befb2b64c8540011563f3c02991588489b258febbbcf7c45d0","src/riscv64/io_uring.rs":"ef851913c86bc2d629048e781edc76b59c63e659f8bd4bcd7fa7ff982186ed6d","src/riscv64/ioctl.rs":"9c4645f03ac8bdfba148aed2d123688c3638e8b742aa69e03f9f886e4dc0132c","src/riscv64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/riscv64/net.rs":"af6d52d44def3ebdb01e047c588f353a9a3e6d20c6c57be5a846270a4505235b","src/riscv64/netlink.rs":"789357343b94276e6f8fc8f3a32f06f3d3efd464c7850b2568dc609a49d1f305","src/riscv64/prctl.rs":"624e4d3b8f3b4f1d6dcb1540c124ed03ce47f0580aa3425c0baed431dcd267ea","src/riscv64/system.rs":"4cfcd4c28481b9ff5fc0330d5c713d637d3615c0184830d3a4391882eaed68f5","src/riscv64/xdp.rs":"2270c2b3cce1cf55922ed685c6cb7197a3932d756763f7528ab36c034609d856","src/s390x/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/s390x/general.rs":"687f6e3d4502d31aaec08a41335b6a368f0949049875d939065a66df86e06b8a","src/s390x/if_ether.rs":"2a6b2132be1aebe126eb64ea230a82c2ab18433ece37226c9dacd81392ad6ca2","src/s390x/if_packet.rs":"718a17518e3eea871f5e6536d13496cd4ea3172f163a461f7ab2e114468b3560","src/s390x/io_uring.rs":"57790b4ce46a4a2a87a329ff935033dfb430117bcc2154fa066c5d681f115319","src/s390x/ioctl.rs":"0aa7214e5a0fe1159a13afb0fa185505e5bcebb7bc8ba8abd7b210bc8c63c47a","src/s390x/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/s390x/net.rs":"792ef0d83c1e7640e5c6e15a96d3bc9d90f4fc96740f076792ce203c31db9a09","src/s390x/netlink.rs":"c3c11102a55d15dfb534d748c8bc8ece58c9d56170b6afe07d1f2cc783fd6372","src/s390x/prctl.rs":"6fe9f5349f9a694b391f309f208235c1d4669430d3f051ef64467576e91df7a1","src/s390x/system.rs":"f68e8afbd02bc87a8fec2cae4e367f296873f2c1a651032da4ccc4f1c0ed4670","src/s390x/xdp.rs":"fc298028f317486df5e28595c3a5ee0802b7b4dc1e113231332982ae8226b8cb","src/sparc/errno.rs":"b3c5e1a6c8378d613c6ef3dd44e2199ea7455da65e83d6bb19582a79de880f80","src/sparc/general.rs":"a38a371e8ceeecc4384999b4cc8ee6d65a35a20542c96c62e04c24b2b2953858","src/sparc/if_ether.rs":"c574c6d1ea11a8bb213b18928fe2d342c897d8ff04458991a5192eb401fbbc57","src/sparc/if_packet.rs":"c3e8bce80c279fb92c9d7f6f4a593ea9f61180f728224c60dd1efa9b2950b297","src/sparc/io_uring.rs":"d813aabc93f383c8522773ed431209627d810c78bcdb4dae931a702aae55e09f","src/sparc/ioctl.rs":"b2a4c7d649b18a4d2a1142400de687d48c195dcf8a86b58ac261413c33809d7b","src/sparc/mempolicy.rs":"4b03f870283b21150e322f00d8bab5088189b0a1189a6a8dc6b93da7d647f629","src/sparc/net.rs":"9c2f69c2d2bb193f5ff1b5f54d1f992555157d7d2af8d4cdee32a45c12ff4ee6","src/sparc/netlink.rs":"0f176c24de7b2b19ac16dd95625947b8047d48bc7b871e12a3acd31f8e97c6f5","src/sparc/prctl.rs":"5f5686fe04d8cc5e746d789340331095044f244c123ecf1468dcb089bbb931cd","src/sparc/system.rs":"6f1f8ce9978693845621880031ac4805f00027315a691cfe1d466703c7a96e8d","src/sparc/xdp.rs":"f62496e93ea3230b914d3c7263957f9377c0b9c87cfc6e85e9779433d1a4747a","src/sparc64/errno.rs":"b3c5e1a6c8378d613c6ef3dd44e2199ea7455da65e83d6bb19582a79de880f80","src/sparc64/general.rs":"d4138f0e663833811365fdc2e1008525df0f21044b5e31ab80d97d63fcb9f45f","src/sparc64/if_ether.rs":"e51661cb54922c3c01853617a61b3d141768adf5b94162c4aefb326d31ef55f5","src/sparc64/if_packet.rs":"4944db85104ae65eb61af6df4e6c37a1037d849b1056f33ffcc56f7daa8da5ed","src/sparc64/io_uring.rs":"688f4678c259eb940aa0216c0183843d436b918d214e13bed56a38ddb55132db","src/sparc64/ioctl.rs":"b2a4c7d649b18a4d2a1142400de687d48c195dcf8a86b58ac261413c33809d7b","src/sparc64/mempolicy.rs":"4b03f870283b21150e322f00d8bab5088189b0a1189a6a8dc6b93da7d647f629","src/sparc64/net.rs":"629b4860c128d4ebb2249f43fd733dea87ca65d3ded5ea8123b43d08a73ba080","src/sparc64/netlink.rs":"7cec2a77af7ec17cad96d63027fd4a9164f0e6503f2e6cc2a99e79aa1bba3147","src/sparc64/prctl.rs":"ff897312b99274ce4eefecccc9797e34accc69efce1299712ab631e9542cb8ca","src/sparc64/system.rs":"becb2e706ed6df77860a2a3884b28181dca606db22fcd604a8a1803f937e8baf","src/sparc64/xdp.rs":"5e1ea3534a0a81f56ea35ea38eddc3bab420bab57d5b34b3f6fafffd43c51a47","src/x32/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x32/general.rs":"c2aeaf3096d559a86d3f72e0ec4a91245edfce35e85c51b50d13e115ec357974","src/x32/if_ether.rs":"859047581be4a3ae923b88516e86230a4f9a447a5203285dd8bcc539038c5c4f","src/x32/if_packet.rs":"e9846f5a713ba4b13efcdbaa7499121857347f5fb7b5b8cf137ee84aeba8d768","src/x32/io_uring.rs":"40834d29cf819e43a23f9a2e075e2ea0c001be817f7200aa059c24eae6d29123","src/x32/ioctl.rs":"f2b8a984878ecc004089ef138b00d78ab7747cce45d3bb9b60b46e35f49f3ec7","src/x32/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x32/net.rs":"e6f5f56160ead3ce9d39be3477a4bfb33a1adbc5fba53575304336a6ff1b5370","src/x32/netlink.rs":"f74042f6cf0eabccfa6b8008a89ee7ab347fb7eaa89499757a786b13b2403982","src/x32/prctl.rs":"2d1eb6873dc5b72a8252f12e695d98a045e01026f730302a6515f53a394bba7c","src/x32/system.rs":"69c125aea6b21f2c4981f3386602283a691524671fef1da7d67de3b67fffdc42","src/x32/xdp.rs":"955fb2683206fce1e5c763060c8a5b1f930ad82d127f330f72e91bba56adbc8b","src/x86/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x86/general.rs":"a9b002ea136dabb9fd1c489c999cd1bfeca62490202aab095221fc70c2b6e30e","src/x86/if_ether.rs":"3873beb1f57bdcc52da345608c5deda5937d7b92b114b414ce6161784173b925","src/x86/if_packet.rs":"33e3e967a2f52b9796205f48867a38b87c7f77424f9ed4a765def5ee4037c528","src/x86/io_uring.rs":"3f60400dfc11a5eafa5a54466f7f9ca74a63219feda2278c388529bf40c0a6a3","src/x86/ioctl.rs":"11e753119d8491145a6b2af6fff2041ba3c49d61f7ee130d9737c4b3e40ee41d","src/x86/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x86/net.rs":"0b2addcd77882d71155bbe6e501ab2927ddca878effb4e8a6d4bce4d02ee6fef","src/x86/netlink.rs":"2f98b8c0349c2d3d538164e4d06c28fa1fb9308f7691aa097526ce2fb3ac176f","src/x86/prctl.rs":"5477c74fec958d9f9d2028f58e95657840ead28445956e53fe0894e45922f8a5","src/x86/system.rs":"9aca94a4a553e09e6d2d43741fb8c120c05a193822e850951dc469bbd89cc703","src/x86/xdp.rs":"a4ae33a218d9967b56b3c70d3c1c1180df49379b05044e3a5c7534b542b4a529","src/x86_64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x86_64/general.rs":"f0c763abb8d7e7bd594c674d2774b272844829ecee4e3ed42932004616a2380e","src/x86_64/if_ether.rs":"feb5362d90fbd5113b6f1f22fcc77a7b3bb7c8f5081be7eacb2e270d2f24a293","src/x86_64/if_packet.rs":"102801c066a4372a7bb67f91af78de4a99fa7f99dffe3a015799ed16409e0b4d","src/x86_64/io_uring.rs":"6c008c59b6905b7872b788e30d546efa3b5bb03a0fe17e33b90bfc8beec23f29","src/x86_64/ioctl.rs":"f2b8a984878ecc004089ef138b00d78ab7747cce45d3bb9b60b46e35f49f3ec7","src/x86_64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x86_64/net.rs":"65f921d16a2380b95496db75169b0ef97048e3226a295740cc1e237f817deb9b","src/x86_64/netlink.rs":"d47b8b117007b1c29db325dad68ed1b92562b98f90916b1b192f57a935a98038","src/x86_64/prctl.rs":"6d0f63fff8d76cc2f4678f38e40a68d072d7da4094d5217ce92872370bb4df9b","src/x86_64/system.rs":"6a415f104e7dd34829b36c19ad89e0cfcfbc69a846c87f81e202411386d46966","src/x86_64/xdp.rs":"20776ba35015ad659b5bb8fb47a7d10fc1aee5530ffe650f2f4e10ec653d7857"},"package":"01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"1e2f7b6bc41c6c34ee366a5e41c6da5d129dbe0ec79dbf69aa228db37f6e7d3e","CODE_OF_CONDUCT.md":"ccd9e538ce44713a2486cc8e4c01b8c8b846d1ccff15de728d8d6fa9a7f846cd","COPYRIGHT":"3290ae0fbc9ddb77d2239121d710f0bb9d31b3b4744e6d97fe01e652b4c1870b","Cargo.toml":"79db455f0f60a19369addc51b65e686d1f9ec0d2fac3017f50a8a1f1668342f5","Cargo.toml.orig":"3685990fc3286201d3a1b0664870451073cd69417a43339aef7aaf1b242264ce","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-Apache-2.0_WITH_LLVM-exception":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","ORG_CODE_OF_CONDUCT.md":"a62b69bf86e605ee1bcbb2f0a12ba79e4cebb6983a7b6491949750aecc4f2178","README.md":"3d4ae2ec9429adfd329b4506f7ca6faa84dca30d1c3b416f8f4e6f57bdb3aa96","src/aarch64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/aarch64/general.rs":"0cc1ed00b1ef7efb16a7109138acdf679d591325458938cee150b221af063822","src/aarch64/if_ether.rs":"f558bfec1f5e80235db79f507e4afd3120647a5caddf17a87b7ad5540e5c1462","src/aarch64/if_packet.rs":"78c1154790a6a8bbe14b0ff08465fa2e090cbf5f6528b5526053b5d8ff568133","src/aarch64/io_uring.rs":"9ce4c9005b5b99e041b9d58be6866367605e4bee1e30a7096235cb234ed73e1b","src/aarch64/ioctl.rs":"4ec2865dd9d66287b741ed5d68ffbbd9ef65b4010abb4f9ff7e7024e1a202dfc","src/aarch64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/aarch64/net.rs":"53279ed39ebe891b02824ccb380083f8fa1c6cd92b03195d1c680e1bcfcab0a1","src/aarch64/netlink.rs":"f6642310b8bd37b5775ba1a52cfe638beddd7c880f8dfacab62c3180255fb75f","src/aarch64/prctl.rs":"a80e2f89aa978210d980538e1d9c5b922bb073d118ee51b1f14c1f397c7cd576","src/aarch64/system.rs":"851a95c0d1b76782970a28c373a313954eea0db35f6ebce562e6047095f587c4","src/aarch64/xdp.rs":"8602704977fdf3c9721c88866dfb77ec31b949f7b44d287c41fb6616a08fbaaf","src/arm/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/arm/general.rs":"bdbb40ba5630044c9555fe38a3640638f3ff7f437d94f82428e2bedad32e180f","src/arm/if_ether.rs":"3873beb1f57bdcc52da345608c5deda5937d7b92b114b414ce6161784173b925","src/arm/if_packet.rs":"45e401c44d540bde6f7b2a5c4b67adf99353639bd7d82829480b34a6a174f4ca","src/arm/io_uring.rs":"5e2e254d5853ed30568e17fab184f8cc458607465d19dcee6c87ca1b565d6d2d","src/arm/ioctl.rs":"3f470208ae7e26b356a182a8396b8e4e7522e52d280a0b220c0b79b90ec8fb75","src/arm/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/arm/net.rs":"0b2addcd77882d71155bbe6e501ab2927ddca878effb4e8a6d4bce4d02ee6fef","src/arm/netlink.rs":"2f98b8c0349c2d3d538164e4d06c28fa1fb9308f7691aa097526ce2fb3ac176f","src/arm/prctl.rs":"5477c74fec958d9f9d2028f58e95657840ead28445956e53fe0894e45922f8a5","src/arm/system.rs":"9aca94a4a553e09e6d2d43741fb8c120c05a193822e850951dc469bbd89cc703","src/arm/xdp.rs":"a4ae33a218d9967b56b3c70d3c1c1180df49379b05044e3a5c7534b542b4a529","src/csky/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/csky/general.rs":"94aba82d2a76a9ca272b4766f8d2f5f14e10bc2166e03d695a5b8b5d207e6755","src/csky/if_ether.rs":"aac7a069000195b9b18c6d25b2d7c338efb1062347a84e31cda7c93de374b3c6","src/csky/if_packet.rs":"f88c8926dea84c835ad156b389ad29f50f9e8cb453cdfb5aece6d9fc9be681b6","src/csky/io_uring.rs":"bb7541d82f627cb681ea11f4e5c4162b0d0616ca08fcc6d31bcf22ef813f754d","src/csky/ioctl.rs":"54ee7b43b78b1920159fd924a1110a1c77d072113bb28b29991eacac9bff1a93","src/csky/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/csky/net.rs":"508650776f6a282e9a1d5109e08ff0d1678d86d1068fe43a9870f37787755166","src/csky/netlink.rs":"9fc99e88df0efc15d39b397c9d653c32b4729e31a2434e730435fbdfcb362da4","src/csky/prctl.rs":"8df2f33387d5b4865d9417f796cc4d43b3cf549cfa41d7ce7d41dd367ed8b6c9","src/csky/system.rs":"a2913685b359e60bbfae413b89a6fd37ea38fa448f980ffadef42d227b33ada5","src/csky/xdp.rs":"2138939b87c7c75d2b3ee499507142e2a5abeecd40783c297dd3c555285b3a54","src/elf.rs":"441bcf378b5603f957e053369d18d95c1efe981665846c220bca82123c04843a","src/lib.rs":"be5d81f17a8d15b2f631e362cf87b2ee3217fda06457cfc319b25ecb5c6732eb","src/loongarch64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/loongarch64/general.rs":"fadd5884c6ad645300540dd30150984857819a986772fca4eba1e1fc0c3f4f1e","src/loongarch64/if_ether.rs":"a7b0918afc9dbf8e79490f83a809e4bd563af20ab2b3432d58b763ff31418daf","src/loongarch64/if_packet.rs":"25e69ec7b16d27befb2b64c8540011563f3c02991588489b258febbbcf7c45d0","src/loongarch64/io_uring.rs":"ef851913c86bc2d629048e781edc76b59c63e659f8bd4bcd7fa7ff982186ed6d","src/loongarch64/ioctl.rs":"6f631e0ac37f2c2398168683a1523d1559b85369ffe4cdcc284ffe7455672c18","src/loongarch64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/loongarch64/net.rs":"af6d52d44def3ebdb01e047c588f353a9a3e6d20c6c57be5a846270a4505235b","src/loongarch64/netlink.rs":"789357343b94276e6f8fc8f3a32f06f3d3efd464c7850b2568dc609a49d1f305","src/loongarch64/prctl.rs":"624e4d3b8f3b4f1d6dcb1540c124ed03ce47f0580aa3425c0baed431dcd267ea","src/loongarch64/system.rs":"4cfcd4c28481b9ff5fc0330d5c713d637d3615c0184830d3a4391882eaed68f5","src/loongarch64/xdp.rs":"2270c2b3cce1cf55922ed685c6cb7197a3932d756763f7528ab36c034609d856","src/mips/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips/general.rs":"1c16f4e0a015eaf27e9a30f4b74ec824220798f47c535d3aaf322ad799c054ab","src/mips/if_ether.rs":"1ecdc654cb3eda633bb7192829b1001a0a5ae5a126110b4208bbee5b41f87f5e","src/mips/if_packet.rs":"222bec433d7773de2d576f6341ab1f37a72df7ca39c5214a6e0fff380700930f","src/mips/io_uring.rs":"c69479bb1f862febe78e0989745c202146aaef7e8ceaa0d7bf291af584748992","src/mips/ioctl.rs":"8d4bcd3cd6aa7e87267430bc7b102df012bafa8b0ea4b24a3cfa490447431ef9","src/mips/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips/net.rs":"553750bad3660aff2efb5b2a828860792d76eddf7cb4913d3be98b34901f6a83","src/mips/netlink.rs":"5045dece259abaa5b5974500a20a9325e4cd6eb87c344dd7448056dff469994f","src/mips/prctl.rs":"cd59615adf6f561ef6c542df59cf25f75877693ca1c4c489f5e460eb7e798d4d","src/mips/system.rs":"acbc69a1fe7299860f8bd142bc2ff5595a410e1528994139062fc680d1a87e71","src/mips/xdp.rs":"0dc8bed8c75615fc119bf4cc4231ce22639515b1165911dc0b7f6d5a07dbcd44","src/mips32r6/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips32r6/general.rs":"1c16f4e0a015eaf27e9a30f4b74ec824220798f47c535d3aaf322ad799c054ab","src/mips32r6/if_ether.rs":"1ecdc654cb3eda633bb7192829b1001a0a5ae5a126110b4208bbee5b41f87f5e","src/mips32r6/if_packet.rs":"222bec433d7773de2d576f6341ab1f37a72df7ca39c5214a6e0fff380700930f","src/mips32r6/io_uring.rs":"c69479bb1f862febe78e0989745c202146aaef7e8ceaa0d7bf291af584748992","src/mips32r6/ioctl.rs":"8d4bcd3cd6aa7e87267430bc7b102df012bafa8b0ea4b24a3cfa490447431ef9","src/mips32r6/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips32r6/net.rs":"553750bad3660aff2efb5b2a828860792d76eddf7cb4913d3be98b34901f6a83","src/mips32r6/netlink.rs":"5045dece259abaa5b5974500a20a9325e4cd6eb87c344dd7448056dff469994f","src/mips32r6/prctl.rs":"cd59615adf6f561ef6c542df59cf25f75877693ca1c4c489f5e460eb7e798d4d","src/mips32r6/system.rs":"acbc69a1fe7299860f8bd142bc2ff5595a410e1528994139062fc680d1a87e71","src/mips32r6/xdp.rs":"0dc8bed8c75615fc119bf4cc4231ce22639515b1165911dc0b7f6d5a07dbcd44","src/mips64/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips64/general.rs":"700b52614c604ce58aa8a5bb1ebd46221c0106ec2d8d6600d681d1594a89118a","src/mips64/if_ether.rs":"6d24518acba5bc8fa2a775d039ed9594de8349d6028621134626ccaa8ea18bcd","src/mips64/if_packet.rs":"04ddeec1897afb84f5905e5122617d5436842aecb0480b6f36e6d0a46e7ab9c0","src/mips64/io_uring.rs":"18bd5d96c53aff44f4a37a71f16fa12c11b7c934b395bf841e47d98283146a50","src/mips64/ioctl.rs":"f0059994ece12ced8e4040aa68ccd58850119b5746d87000f8f538af8bd6359c","src/mips64/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips64/net.rs":"a5bd6d654ea16c02f6f85b969bfc2177a88603d38a9a52f09685ca4114f6e199","src/mips64/netlink.rs":"18f139573337be18fb9bd56de4d0bd8af5c80828cdf68ef68751c18dcb39c761","src/mips64/prctl.rs":"a8d9ae240ce582d7b66e13937b99df73c7247ce9f69bfdd12109903d7c6dfb0e","src/mips64/system.rs":"95805c533a8eb8f53c28f138e6a2d12064681cc9db55d3042ee748c655a5d7cd","src/mips64/xdp.rs":"19fdf2b824b95184dabd5c8960d9482788ab8ef027e23acaae9e7992be8eb4e4","src/mips64r6/errno.rs":"9ab1ed2bf371a27401745c2a6f9692f7e66dfd481d032cb40a354826d394ea8e","src/mips64r6/general.rs":"700b52614c604ce58aa8a5bb1ebd46221c0106ec2d8d6600d681d1594a89118a","src/mips64r6/if_ether.rs":"6d24518acba5bc8fa2a775d039ed9594de8349d6028621134626ccaa8ea18bcd","src/mips64r6/if_packet.rs":"04ddeec1897afb84f5905e5122617d5436842aecb0480b6f36e6d0a46e7ab9c0","src/mips64r6/io_uring.rs":"18bd5d96c53aff44f4a37a71f16fa12c11b7c934b395bf841e47d98283146a50","src/mips64r6/ioctl.rs":"f0059994ece12ced8e4040aa68ccd58850119b5746d87000f8f538af8bd6359c","src/mips64r6/mempolicy.rs":"1bb5200d678b4ffeb06eb1728bd391742bc300b363421bb24b8dea340b991594","src/mips64r6/net.rs":"a5bd6d654ea16c02f6f85b969bfc2177a88603d38a9a52f09685ca4114f6e199","src/mips64r6/netlink.rs":"18f139573337be18fb9bd56de4d0bd8af5c80828cdf68ef68751c18dcb39c761","src/mips64r6/prctl.rs":"a8d9ae240ce582d7b66e13937b99df73c7247ce9f69bfdd12109903d7c6dfb0e","src/mips64r6/system.rs":"95805c533a8eb8f53c28f138e6a2d12064681cc9db55d3042ee748c655a5d7cd","src/mips64r6/xdp.rs":"19fdf2b824b95184dabd5c8960d9482788ab8ef027e23acaae9e7992be8eb4e4","src/powerpc/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/powerpc/general.rs":"7940ad742585d501f4742af51c6310ecf651863a8aaa0305193e9c8ee07aca90","src/powerpc/if_ether.rs":"56ab5fbf8c9d0dd0654412fabdca6759cbb421a876e5cebe2fec10e25728b55c","src/powerpc/if_packet.rs":"b7f556f37ba3b5e97d10065e028c4158a821b0d135893a9b4871d0d477b5ef98","src/powerpc/io_uring.rs":"38ead79180c96e8af69929dacbc36e8cfbccec96875c61f094e531e6860639db","src/powerpc/ioctl.rs":"1fabc6c3481d6710b343aa27bf9331e81d16c3cdf86eb76eac61b19839d9b2f4","src/powerpc/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/powerpc/net.rs":"d1c6c36e71354ef35f64ae1195eff75c73f0a4b90fa8a4070cab9e79b81f8b78","src/powerpc/netlink.rs":"4f10870fbd23de17efd4cba6d5a40ba85564effc5d0b71f9d7f928a42cb77b20","src/powerpc/prctl.rs":"f236987bc8ae993ab2b0e88b2eacbae51eee4da170ac075552070a76c717d803","src/powerpc/system.rs":"3e01e5e145adb87263f04c9e053faac0c0758689fd32917d2c7c2eec1d89f9e6","src/powerpc/xdp.rs":"9f04a2ef343109f1bb5ac5bc7ef66cb3c1c966744653a70a79b91f04b9609d07","src/powerpc64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/powerpc64/general.rs":"7862eb3dfac845331b624b3322bdeb3441bb86e914719e125dd5dc7b3860db43","src/powerpc64/if_ether.rs":"15e12d56b1367cb5c9d8fd1b9995acf1429a923bf603698bd732efe1acc30cd6","src/powerpc64/if_packet.rs":"272be02b20e65330c89b87ee0a642eeafdbc40b830d54d6eef041fd9eab9ec77","src/powerpc64/io_uring.rs":"50018e504d78c584beaec3b1a6d477d30d566d25cb1a40b0a2adfb23d726674f","src/powerpc64/ioctl.rs":"1fabc6c3481d6710b343aa27bf9331e81d16c3cdf86eb76eac61b19839d9b2f4","src/powerpc64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/powerpc64/net.rs":"706e58efa77918ac96f20fa33afd5f498e2e118507084c1ae9db93483103ab32","src/powerpc64/netlink.rs":"352a06995f7de6e4fc1c2ff54c1eccb93a3d833a923e834ec75c6a4d30ea5051","src/powerpc64/prctl.rs":"1fcccc5b6dac472a30b7701b5c9e436c238410077cfe158d600b51d55bcc074a","src/powerpc64/system.rs":"500116b7613a504ebad028cec1ba37323310e29864d885ae62191ccb1f86d333","src/powerpc64/xdp.rs":"baad88c60c08fc79dc3c223c0e8d9adef4462728b6e46e5143ce10f6ce5e32bd","src/riscv32/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/riscv32/general.rs":"16ffe747a8f75ac6594dc7afddef4fbb89735da50af9f19f152fd2f04b509463","src/riscv32/if_ether.rs":"aac7a069000195b9b18c6d25b2d7c338efb1062347a84e31cda7c93de374b3c6","src/riscv32/if_packet.rs":"1834cbc6b60973021393a52c88aaff0310f2dcfc1786a9d7ae13c2705752a7e0","src/riscv32/io_uring.rs":"5c67dde8fdb3641407d4ebd744171606b82596176343fe6766afd3220eda2ab1","src/riscv32/ioctl.rs":"6f631e0ac37f2c2398168683a1523d1559b85369ffe4cdcc284ffe7455672c18","src/riscv32/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/riscv32/net.rs":"508650776f6a282e9a1d5109e08ff0d1678d86d1068fe43a9870f37787755166","src/riscv32/netlink.rs":"9fc99e88df0efc15d39b397c9d653c32b4729e31a2434e730435fbdfcb362da4","src/riscv32/prctl.rs":"8df2f33387d5b4865d9417f796cc4d43b3cf549cfa41d7ce7d41dd367ed8b6c9","src/riscv32/system.rs":"a2913685b359e60bbfae413b89a6fd37ea38fa448f980ffadef42d227b33ada5","src/riscv32/xdp.rs":"2138939b87c7c75d2b3ee499507142e2a5abeecd40783c297dd3c555285b3a54","src/riscv64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/riscv64/general.rs":"8ec4907ac81b62e21451731a468e5f4fe7a37a46d80c56b33e0969d2d059d442","src/riscv64/if_ether.rs":"a7b0918afc9dbf8e79490f83a809e4bd563af20ab2b3432d58b763ff31418daf","src/riscv64/if_packet.rs":"25e69ec7b16d27befb2b64c8540011563f3c02991588489b258febbbcf7c45d0","src/riscv64/io_uring.rs":"ef851913c86bc2d629048e781edc76b59c63e659f8bd4bcd7fa7ff982186ed6d","src/riscv64/ioctl.rs":"9c4645f03ac8bdfba148aed2d123688c3638e8b742aa69e03f9f886e4dc0132c","src/riscv64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/riscv64/net.rs":"af6d52d44def3ebdb01e047c588f353a9a3e6d20c6c57be5a846270a4505235b","src/riscv64/netlink.rs":"789357343b94276e6f8fc8f3a32f06f3d3efd464c7850b2568dc609a49d1f305","src/riscv64/prctl.rs":"624e4d3b8f3b4f1d6dcb1540c124ed03ce47f0580aa3425c0baed431dcd267ea","src/riscv64/system.rs":"4cfcd4c28481b9ff5fc0330d5c713d637d3615c0184830d3a4391882eaed68f5","src/riscv64/xdp.rs":"2270c2b3cce1cf55922ed685c6cb7197a3932d756763f7528ab36c034609d856","src/s390x/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/s390x/general.rs":"687f6e3d4502d31aaec08a41335b6a368f0949049875d939065a66df86e06b8a","src/s390x/if_ether.rs":"2a6b2132be1aebe126eb64ea230a82c2ab18433ece37226c9dacd81392ad6ca2","src/s390x/if_packet.rs":"718a17518e3eea871f5e6536d13496cd4ea3172f163a461f7ab2e114468b3560","src/s390x/io_uring.rs":"57790b4ce46a4a2a87a329ff935033dfb430117bcc2154fa066c5d681f115319","src/s390x/ioctl.rs":"0aa7214e5a0fe1159a13afb0fa185505e5bcebb7bc8ba8abd7b210bc8c63c47a","src/s390x/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/s390x/net.rs":"792ef0d83c1e7640e5c6e15a96d3bc9d90f4fc96740f076792ce203c31db9a09","src/s390x/netlink.rs":"c3c11102a55d15dfb534d748c8bc8ece58c9d56170b6afe07d1f2cc783fd6372","src/s390x/prctl.rs":"6fe9f5349f9a694b391f309f208235c1d4669430d3f051ef64467576e91df7a1","src/s390x/system.rs":"f68e8afbd02bc87a8fec2cae4e367f296873f2c1a651032da4ccc4f1c0ed4670","src/s390x/xdp.rs":"fc298028f317486df5e28595c3a5ee0802b7b4dc1e113231332982ae8226b8cb","src/sparc/errno.rs":"b3c5e1a6c8378d613c6ef3dd44e2199ea7455da65e83d6bb19582a79de880f80","src/sparc/general.rs":"a38a371e8ceeecc4384999b4cc8ee6d65a35a20542c96c62e04c24b2b2953858","src/sparc/if_ether.rs":"c574c6d1ea11a8bb213b18928fe2d342c897d8ff04458991a5192eb401fbbc57","src/sparc/if_packet.rs":"c3e8bce80c279fb92c9d7f6f4a593ea9f61180f728224c60dd1efa9b2950b297","src/sparc/io_uring.rs":"d813aabc93f383c8522773ed431209627d810c78bcdb4dae931a702aae55e09f","src/sparc/ioctl.rs":"b2a4c7d649b18a4d2a1142400de687d48c195dcf8a86b58ac261413c33809d7b","src/sparc/mempolicy.rs":"4b03f870283b21150e322f00d8bab5088189b0a1189a6a8dc6b93da7d647f629","src/sparc/net.rs":"9c2f69c2d2bb193f5ff1b5f54d1f992555157d7d2af8d4cdee32a45c12ff4ee6","src/sparc/netlink.rs":"0f176c24de7b2b19ac16dd95625947b8047d48bc7b871e12a3acd31f8e97c6f5","src/sparc/prctl.rs":"5f5686fe04d8cc5e746d789340331095044f244c123ecf1468dcb089bbb931cd","src/sparc/system.rs":"6f1f8ce9978693845621880031ac4805f00027315a691cfe1d466703c7a96e8d","src/sparc/xdp.rs":"f62496e93ea3230b914d3c7263957f9377c0b9c87cfc6e85e9779433d1a4747a","src/sparc64/errno.rs":"b3c5e1a6c8378d613c6ef3dd44e2199ea7455da65e83d6bb19582a79de880f80","src/sparc64/general.rs":"d4138f0e663833811365fdc2e1008525df0f21044b5e31ab80d97d63fcb9f45f","src/sparc64/if_ether.rs":"e51661cb54922c3c01853617a61b3d141768adf5b94162c4aefb326d31ef55f5","src/sparc64/if_packet.rs":"4944db85104ae65eb61af6df4e6c37a1037d849b1056f33ffcc56f7daa8da5ed","src/sparc64/io_uring.rs":"688f4678c259eb940aa0216c0183843d436b918d214e13bed56a38ddb55132db","src/sparc64/ioctl.rs":"b2a4c7d649b18a4d2a1142400de687d48c195dcf8a86b58ac261413c33809d7b","src/sparc64/mempolicy.rs":"4b03f870283b21150e322f00d8bab5088189b0a1189a6a8dc6b93da7d647f629","src/sparc64/net.rs":"629b4860c128d4ebb2249f43fd733dea87ca65d3ded5ea8123b43d08a73ba080","src/sparc64/netlink.rs":"7cec2a77af7ec17cad96d63027fd4a9164f0e6503f2e6cc2a99e79aa1bba3147","src/sparc64/prctl.rs":"ff897312b99274ce4eefecccc9797e34accc69efce1299712ab631e9542cb8ca","src/sparc64/system.rs":"becb2e706ed6df77860a2a3884b28181dca606db22fcd604a8a1803f937e8baf","src/sparc64/xdp.rs":"5e1ea3534a0a81f56ea35ea38eddc3bab420bab57d5b34b3f6fafffd43c51a47","src/x32/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x32/general.rs":"c2aeaf3096d559a86d3f72e0ec4a91245edfce35e85c51b50d13e115ec357974","src/x32/if_ether.rs":"859047581be4a3ae923b88516e86230a4f9a447a5203285dd8bcc539038c5c4f","src/x32/if_packet.rs":"e9846f5a713ba4b13efcdbaa7499121857347f5fb7b5b8cf137ee84aeba8d768","src/x32/io_uring.rs":"40834d29cf819e43a23f9a2e075e2ea0c001be817f7200aa059c24eae6d29123","src/x32/ioctl.rs":"f2b8a984878ecc004089ef138b00d78ab7747cce45d3bb9b60b46e35f49f3ec7","src/x32/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x32/net.rs":"e6f5f56160ead3ce9d39be3477a4bfb33a1adbc5fba53575304336a6ff1b5370","src/x32/netlink.rs":"f74042f6cf0eabccfa6b8008a89ee7ab347fb7eaa89499757a786b13b2403982","src/x32/prctl.rs":"2d1eb6873dc5b72a8252f12e695d98a045e01026f730302a6515f53a394bba7c","src/x32/system.rs":"69c125aea6b21f2c4981f3386602283a691524671fef1da7d67de3b67fffdc42","src/x32/xdp.rs":"955fb2683206fce1e5c763060c8a5b1f930ad82d127f330f72e91bba56adbc8b","src/x86/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x86/general.rs":"a9b002ea136dabb9fd1c489c999cd1bfeca62490202aab095221fc70c2b6e30e","src/x86/if_ether.rs":"3873beb1f57bdcc52da345608c5deda5937d7b92b114b414ce6161784173b925","src/x86/if_packet.rs":"33e3e967a2f52b9796205f48867a38b87c7f77424f9ed4a765def5ee4037c528","src/x86/io_uring.rs":"3f60400dfc11a5eafa5a54466f7f9ca74a63219feda2278c388529bf40c0a6a3","src/x86/ioctl.rs":"11e753119d8491145a6b2af6fff2041ba3c49d61f7ee130d9737c4b3e40ee41d","src/x86/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x86/net.rs":"0b2addcd77882d71155bbe6e501ab2927ddca878effb4e8a6d4bce4d02ee6fef","src/x86/netlink.rs":"2f98b8c0349c2d3d538164e4d06c28fa1fb9308f7691aa097526ce2fb3ac176f","src/x86/prctl.rs":"5477c74fec958d9f9d2028f58e95657840ead28445956e53fe0894e45922f8a5","src/x86/system.rs":"9aca94a4a553e09e6d2d43741fb8c120c05a193822e850951dc469bbd89cc703","src/x86/xdp.rs":"a4ae33a218d9967b56b3c70d3c1c1180df49379b05044e3a5c7534b542b4a529","src/x86_64/errno.rs":"db283e5ea7fb63e0f57acb241e6471a951b4218660c01ca37b80be9a53629b92","src/x86_64/general.rs":"f0c763abb8d7e7bd594c674d2774b272844829ecee4e3ed42932004616a2380e","src/x86_64/if_ether.rs":"feb5362d90fbd5113b6f1f22fcc77a7b3bb7c8f5081be7eacb2e270d2f24a293","src/x86_64/if_packet.rs":"102801c066a4372a7bb67f91af78de4a99fa7f99dffe3a015799ed16409e0b4d","src/x86_64/io_uring.rs":"6c008c59b6905b7872b788e30d546efa3b5bb03a0fe17e33b90bfc8beec23f29","src/x86_64/ioctl.rs":"f2b8a984878ecc004089ef138b00d78ab7747cce45d3bb9b60b46e35f49f3ec7","src/x86_64/mempolicy.rs":"fc2d0688a67779b521762ae850605f754be487560f888bd5c0bce80c426dfc35","src/x86_64/net.rs":"65f921d16a2380b95496db75169b0ef97048e3226a295740cc1e237f817deb9b","src/x86_64/netlink.rs":"d47b8b117007b1c29db325dad68ed1b92562b98f90916b1b192f57a935a98038","src/x86_64/prctl.rs":"6d0f63fff8d76cc2f4678f38e40a68d072d7da4094d5217ce92872370bb4df9b","src/x86_64/system.rs":"6a415f104e7dd34829b36c19ad89e0cfcfbc69a846c87f81e202411386d46966","src/x86_64/xdp.rs":"20776ba35015ad659b5bb8fb47a7d10fc1aee5530ffe650f2f4e10ec653d7857"},"package":"01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ad726d4998270502f292e1ab9a580217878b674a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/linux-raw-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/linux-raw-sys/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +[package] +name = "linux-raw-sys" +version = "0.4.13" +authors = ["Dan Gohman "] +description = "Generated bindings for Linux's userspace API" +documentation = "https://docs.rs/linux-raw-sys" +license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" +repository = "https://github.com/sunfishcode/linux-raw-sys" +edition = "2021" +keywords = ["linux", "uapi", "ffi"] +categories = ["external-ffi-bindings"] +exclude = ["/gen", "/.*"] +rust-version = "1.63" + +[dependencies] +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +compiler_builtins = { version = '0.1.49', optional = true } + +[dev-dependencies] +static_assertions = "1.1.0" +libc = "0.2.100" + +[package.metadata.docs.rs] +features = ["default", "ioctl", "netlink", "io_uring", "if_ether", "net", "prctl", "elf", "xdp", "mempolicy", "system"] +targets = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"] + +# The rest of this file is auto-generated! +[features] +errno = [] +general = [] +if_ether = [] +if_packet = [] +io_uring = [] +ioctl = [] +mempolicy = [] +net = [] +netlink = [] +prctl = [] +system = [] +xdp = [] +default = ["std", "general", "errno"] +std = [] +no_std = [] +elf = [] +rustc-dep-of-std = ["core", "compiler_builtins", "no_std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/lock_api/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"873bc09c121a5620950ddeb7e63487e3336f849fa50e6d87129fdbae9ac38ad9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"af84139c71d151adead0b4398c394a7dd16087bb2db44b14a0ed970ce868a6c6","src/lib.rs":"52d42521f3229969f9726a74f90f72bfabf7276574d363596dfdfdda96611bbf","src/mutex.rs":"2f7bc61bd4bc7dd4ab18d57fa27fee04c96ee7be2e26e2d857ac1df385bb23c5","src/remutex.rs":"309d8e4f9ce1f0fdce0f9b6f4845e4685c8bad23340c0237ffa526d488e2df45","src/rwlock.rs":"940af2991247a3f84bdba177f54a326da86345f8bd99c9445d2235473ae3f62a"},"package":"07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/lock_api/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -rust-version = "1.56.0" -name = "lock_api" -version = "0.4.12" -authors = ["Amanieu d'Antras "] -description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." -keywords = [ - "mutex", - "rwlock", - "lock", - "no_std", -] -categories = [ - "concurrency", - "no-std", -] -license = "MIT OR Apache-2.0" -repository = "https://github.com/Amanieu/parking_lot" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", - "--generate-link-to-definition", -] - -[dependencies.owning_ref] -version = "0.4.1" -optional = true - -[dependencies.scopeguard] -version = "1.1.0" -default-features = false - -[dependencies.serde] -version = "1.0.126" -optional = true -default-features = false - -[build-dependencies.autocfg] -version = "1.1.0" - -[features] -arc_lock = [] -atomic_usize = [] -default = ["atomic_usize"] -nightly = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/LICENSE-APACHE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -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 - - http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/LICENSE-MIT 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Copyright (c) 2016 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/build.rs clamav-1.4.6+dfsg/.cargo/vendor/lock_api/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/build.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/build.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -fn main() { - let cfg = autocfg::new(); - - if cfg.probe_rustc_version(1, 61) { - println!("cargo:rustc-cfg=has_const_fn_trait_bound"); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -// Copyright 2018 Amanieu d'Antras -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -//! This library provides type-safe and fully-featured [`Mutex`] and [`RwLock`] -//! types which wrap a simple raw mutex or rwlock type. This has several -//! benefits: not only does it eliminate a large portion of the work in -//! implementing custom lock types, it also allows users to write code which is -//! generic with regards to different lock implementations. -//! -//! Basic usage of this crate is very straightforward: -//! -//! 1. Create a raw lock type. This should only contain the lock state, not any -//! data protected by the lock. -//! 2. Implement the `RawMutex` trait for your custom lock type. -//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and -//! your mutex guard as a type alias for `lock_api::MutexGuard`. -//! See the [example](#example) below for details. -//! -//! This process is similar for [`RwLock`]s, except that two guards need to be -//! exported instead of one. (Or 3 guards if your type supports upgradable read -//! locks, see [extension traits](#extension-traits) below for details) -//! -//! # Example -//! -//! ``` -//! use lock_api::{RawMutex, Mutex, GuardSend}; -//! use std::sync::atomic::{AtomicBool, Ordering}; -//! -//! // 1. Define our raw lock type -//! pub struct RawSpinlock(AtomicBool); -//! -//! // 2. Implement RawMutex for this type -//! unsafe impl RawMutex for RawSpinlock { -//! const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false)); -//! -//! // A spinlock guard can be sent to another thread and unlocked there -//! type GuardMarker = GuardSend; -//! -//! fn lock(&self) { -//! // Note: This isn't the best way of implementing a spinlock, but it -//! // suffices for the sake of this example. -//! while !self.try_lock() {} -//! } -//! -//! fn try_lock(&self) -> bool { -//! self.0 -//! .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) -//! .is_ok() -//! } -//! -//! unsafe fn unlock(&self) { -//! self.0.store(false, Ordering::Release); -//! } -//! } -//! -//! // 3. Export the wrappers. This are the types that your users will actually use. -//! pub type Spinlock = lock_api::Mutex; -//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>; -//! ``` -//! -//! # Extension traits -//! -//! In addition to basic locking & unlocking functionality, you have the option -//! of exposing additional functionality in your lock types by implementing -//! additional traits for it. Examples of extension features include: -//! -//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`) -//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`) -//! - Downgradable write locks (`RawRwLockDowngradable`) -//! - Recursive read locks (`RawRwLockRecursive`) -//! - Upgradable read locks (`RawRwLockUpgrade`) -//! -//! The `Mutex` and `RwLock` wrappers will automatically expose this additional -//! functionality if the raw lock type implements these extension traits. -//! -//! # Cargo features -//! -//! This crate supports three cargo features: -//! -//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate. -//! - `arc_lock`: Enables locking from an `Arc`. This enables types such as `ArcMutexGuard`. Note that this -//! requires the `alloc` crate to be present. - -#![no_std] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![warn(missing_docs)] -#![warn(rust_2018_idioms)] - -#[macro_use] -extern crate scopeguard; - -#[cfg(feature = "arc_lock")] -extern crate alloc; - -/// Marker type which indicates that the Guard type for a lock is `Send`. -pub struct GuardSend(()); - -/// Marker type which indicates that the Guard type for a lock is not `Send`. -pub struct GuardNoSend(*mut ()); - -unsafe impl Sync for GuardNoSend {} - -mod mutex; -pub use crate::mutex::*; - -#[cfg(feature = "atomic_usize")] -mod remutex; -#[cfg(feature = "atomic_usize")] -pub use crate::remutex::*; - -mod rwlock; -pub use crate::rwlock::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/mutex.rs clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/mutex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/mutex.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/mutex.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,964 +0,0 @@ -// Copyright 2018 Amanieu d'Antras -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -use core::cell::UnsafeCell; -use core::fmt; -use core::marker::PhantomData; -use core::mem; -use core::ops::{Deref, DerefMut}; - -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - -#[cfg(feature = "owning_ref")] -use owning_ref::StableAddress; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -/// Basic operations for a mutex. -/// -/// Types implementing this trait can be used by `Mutex` to form a safe and -/// fully-functioning mutex type. -/// -/// # Safety -/// -/// Implementations of this trait must ensure that the mutex is actually -/// exclusive: a lock can't be acquired while the mutex is already locked. -pub unsafe trait RawMutex { - /// Initial value for an unlocked mutex. - // A “non-constant” const item is a legacy way to supply an initialized value to downstream - // static items. Can hopefully be replaced with `const fn new() -> Self` at some point. - #[allow(clippy::declare_interior_mutable_const)] - const INIT: Self; - - /// Marker type which determines whether a lock guard should be `Send`. Use - /// one of the `GuardSend` or `GuardNoSend` helper types here. - type GuardMarker; - - /// Acquires this mutex, blocking the current thread until it is able to do so. - fn lock(&self); - - /// Attempts to acquire this mutex without blocking. Returns `true` - /// if the lock was successfully acquired and `false` otherwise. - fn try_lock(&self) -> bool; - - /// Unlocks this mutex. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held in the current context, i.e. it must - /// be paired with a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`]. - /// - /// [`lock`]: RawMutex::lock - /// [`try_lock`]: RawMutex::try_lock - /// [`try_lock_for`]: RawMutexTimed::try_lock_for - /// [`try_lock_until`]: RawMutexTimed::try_lock_until - unsafe fn unlock(&self); - - /// Checks whether the mutex is currently locked. - #[inline] - fn is_locked(&self) -> bool { - let acquired_lock = self.try_lock(); - if acquired_lock { - // Safety: The lock has been successfully acquired above. - unsafe { - self.unlock(); - } - } - !acquired_lock - } -} - -/// Additional methods for mutexes which support fair unlocking. -/// -/// Fair unlocking means that a lock is handed directly over to the next waiting -/// thread if there is one, without giving other threads the opportunity to -/// "steal" the lock in the meantime. This is typically slower than unfair -/// unlocking, but may be necessary in certain circumstances. -pub unsafe trait RawMutexFair: RawMutex { - /// Unlocks this mutex using a fair unlock protocol. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held in the current context, see - /// the documentation of [`unlock`](RawMutex::unlock). - unsafe fn unlock_fair(&self); - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `lock`, however it can be much more efficient in the case where there - /// are no waiting threads. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held in the current context, see - /// the documentation of [`unlock`](RawMutex::unlock). - unsafe fn bump(&self) { - self.unlock_fair(); - self.lock(); - } -} - -/// Additional methods for mutexes which support locking with timeouts. -/// -/// The `Duration` and `Instant` types are specified as associated types so that -/// this trait is usable even in `no_std` environments. -pub unsafe trait RawMutexTimed: RawMutex { - /// Duration type used for `try_lock_for`. - type Duration; - - /// Instant type used for `try_lock_until`. - type Instant; - - /// Attempts to acquire this lock until a timeout is reached. - fn try_lock_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to acquire this lock until a timeout is reached. - fn try_lock_until(&self, timeout: Self::Instant) -> bool; -} - -/// A mutual exclusion primitive useful for protecting shared data -/// -/// This mutex will block threads waiting for the lock to become available. The -/// mutex can also be statically initialized or created via a `new` -/// constructor. Each mutex has a type parameter which represents the data that -/// it is protecting. The data can only be accessed through the RAII guards -/// returned from `lock` and `try_lock`, which guarantees that the data is only -/// ever accessed when the mutex is locked. -pub struct Mutex { - raw: R, - data: UnsafeCell, -} - -unsafe impl Send for Mutex {} -unsafe impl Sync for Mutex {} - -impl Mutex { - /// Creates a new mutex in an unlocked state ready for use. - #[cfg(has_const_fn_trait_bound)] - #[inline] - pub const fn new(val: T) -> Mutex { - Mutex { - raw: R::INIT, - data: UnsafeCell::new(val), - } - } - - /// Creates a new mutex in an unlocked state ready for use. - #[cfg(not(has_const_fn_trait_bound))] - #[inline] - pub fn new(val: T) -> Mutex { - Mutex { - raw: R::INIT, - data: UnsafeCell::new(val), - } - } - - /// Consumes this mutex, returning the underlying data. - #[inline] - pub fn into_inner(self) -> T { - self.data.into_inner() - } -} - -impl Mutex { - /// Creates a new mutex based on a pre-existing raw mutex. - #[inline] - pub const fn from_raw(raw_mutex: R, val: T) -> Mutex { - Mutex { - raw: raw_mutex, - data: UnsafeCell::new(val), - } - } - - /// Creates a new mutex based on a pre-existing raw mutex. - /// - /// This allows creating a mutex in a constant context on stable Rust. - /// - /// This method is a legacy alias for [`from_raw`](Self::from_raw). - #[inline] - pub const fn const_new(raw_mutex: R, val: T) -> Mutex { - Self::from_raw(raw_mutex, val) - } -} - -impl Mutex { - /// Creates a new `MutexGuard` without checking if the mutex is locked. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds the lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[inline] - pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> { - MutexGuard { - mutex: self, - marker: PhantomData, - } - } - - /// Acquires a mutex, blocking the current thread until it is able to do so. - /// - /// This function will block the local thread until it is available to acquire - /// the mutex. Upon returning, the thread is the only thread with the mutex - /// held. An RAII guard is returned to allow scoped unlock of the lock. When - /// the guard goes out of scope, the mutex will be unlocked. - /// - /// Attempts to lock a mutex in the thread which already holds the lock will - /// result in a deadlock. - #[inline] - pub fn lock(&self) -> MutexGuard<'_, R, T> { - self.raw.lock(); - // SAFETY: The lock is held, as required. - unsafe { self.make_guard_unchecked() } - } - - /// Attempts to acquire this lock. - /// - /// If the lock could not be acquired at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned. The lock will be unlocked when the - /// guard is dropped. - /// - /// This function does not block. - #[inline] - pub fn try_lock(&self) -> Option> { - if self.raw.try_lock() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the `Mutex` mutably, no actual locking needs to - /// take place---the mutable borrow statically guarantees no locks exist. - #[inline] - pub fn get_mut(&mut self) -> &mut T { - unsafe { &mut *self.data.get() } - } - - /// Checks whether the mutex is currently locked. - #[inline] - pub fn is_locked(&self) -> bool { - self.raw.is_locked() - } - - /// Forcibly unlocks the mutex. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `MutexGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `MutexGuard` but that guard has been discarded using `mem::forget`. - /// Behavior is undefined if a mutex is unlocked when not locked. - #[inline] - pub unsafe fn force_unlock(&self) { - self.raw.unlock(); - } - - /// Returns the underlying raw mutex object. - /// - /// Note that you will most likely need to import the `RawMutex` trait from - /// `lock_api` to be able to call functions on the raw mutex. - /// - /// # Safety - /// - /// This method is unsafe because it allows unlocking a mutex while - /// still holding a reference to a `MutexGuard`. - #[inline] - pub unsafe fn raw(&self) -> &R { - &self.raw - } - - /// Returns a raw pointer to the underlying data. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `MutexGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// You must ensure that there are no data races when dereferencing the - /// returned pointer, for example if the current thread logically owns - /// a `MutexGuard` but that guard has been discarded using `mem::forget`. - #[inline] - pub fn data_ptr(&self) -> *mut T { - self.data.get() - } - - /// Creates a new `ArcMutexGuard` without checking if the mutex is locked. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds the lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[cfg(feature = "arc_lock")] - #[inline] - unsafe fn make_arc_guard_unchecked(self: &Arc) -> ArcMutexGuard { - ArcMutexGuard { - mutex: self.clone(), - marker: PhantomData, - } - } - - /// Acquires a lock through an `Arc`. - /// - /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc` - /// and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn lock_arc(self: &Arc) -> ArcMutexGuard { - self.raw.lock(); - // SAFETY: the locking guarantee is upheld - unsafe { self.make_arc_guard_unchecked() } - } - - /// Attempts to acquire a lock through an `Arc`. - /// - /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc(self: &Arc) -> Option> { - if self.raw.try_lock() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl Mutex { - /// Forcibly unlocks the mutex using a fair unlock protocol. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `MutexGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `MutexGuard` but that guard has been discarded using `mem::forget`. - /// Behavior is undefined if a mutex is unlocked when not locked. - #[inline] - pub unsafe fn force_unlock_fair(&self) { - self.raw.unlock_fair(); - } -} - -impl Mutex { - /// Attempts to acquire this lock until a timeout is reached. - /// - /// If the lock could not be acquired before the timeout expired, then - /// `None` is returned. Otherwise, an RAII guard is returned. The lock will - /// be unlocked when the guard is dropped. - #[inline] - pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { - if self.raw.try_lock_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock until a timeout is reached. - /// - /// If the lock could not be acquired before the timeout expired, then - /// `None` is returned. Otherwise, an RAII guard is returned. The lock will - /// be unlocked when the guard is dropped. - #[inline] - pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { - if self.raw.try_lock_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock through an `Arc` until a timeout is reached. - /// - /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_for(self: &Arc, timeout: R::Duration) -> Option> { - if self.raw.try_lock_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock through an `Arc` until a timeout is reached. - /// - /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of - /// an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl Default for Mutex { - #[inline] - fn default() -> Mutex { - Mutex::new(Default::default()) - } -} - -impl From for Mutex { - #[inline] - fn from(t: T) -> Mutex { - Mutex::new(t) - } -} - -impl fmt::Debug for Mutex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.try_lock() { - Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), - None => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - - f.debug_struct("Mutex") - .field("data", &LockedPlaceholder) - .finish() - } - } - } -} - -// Copied and modified from serde -#[cfg(feature = "serde")] -impl Serialize for Mutex -where - R: RawMutex, - T: Serialize + ?Sized, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.lock().serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de, R, T> Deserialize<'de> for Mutex -where - R: RawMutex, - T: Deserialize<'de> + ?Sized, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Deserialize::deserialize(deserializer).map(Mutex::new) - } -} - -/// An RAII implementation of a "scoped lock" of a mutex. When this structure is -/// dropped (falls out of scope), the lock will be unlocked. -/// -/// The data protected by the mutex can be accessed through this guard via its -/// `Deref` and `DerefMut` implementations. -#[clippy::has_significant_drop] -#[must_use = "if unused the Mutex will immediately unlock"] -pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> { - mutex: &'a Mutex, - marker: PhantomData<(&'a mut T, R::GuardMarker)>, -} - -unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { - /// Returns a reference to the original `Mutex` object. - pub fn mutex(s: &Self) -> &'a Mutex { - s.mutex - } - - /// Makes a new `MappedMutexGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `MutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MutexGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedMutexGuard<'a, R, U> - where - F: FnOnce(&mut T) -> &mut U, - { - let raw = &s.mutex.raw; - let data = f(unsafe { &mut *s.mutex.data.get() }); - mem::forget(s); - MappedMutexGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedMutexGuard` for a component of the - /// locked data. The original guard is returned if the closure returns `None`. - /// - /// This operation cannot fail as the `MutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&mut T) -> Option<&mut U>, - { - let raw = &s.mutex.raw; - let data = match f(unsafe { &mut *s.mutex.data.get() }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedMutexGuard { - raw, - data, - marker: PhantomData, - }) - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock(); - } - defer!(s.mutex.raw.lock()); - f() - } - - /// Leaks the mutex guard and returns a mutable reference to the data - /// protected by the mutex. - /// - /// This will leave the `Mutex` in a locked state. - #[inline] - pub fn leak(s: Self) -> &'a mut T { - let r = unsafe { &mut *s.mutex.data.get() }; - mem::forget(s); - r - } -} - -impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// By default, mutexes are unfair and allow the current thread to re-lock - /// the mutex before another has the chance to acquire the lock, even if - /// that thread has been blocked on the mutex for a long time. This is the - /// default because it allows much higher throughput as it avoids forcing a - /// context switch on every mutex unlock. This can result in one thread - /// acquiring a mutex many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `MutexGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - mem::forget(s); - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// The mutex is unlocked using a fair unlock protocol. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - defer!(s.mutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `lock`, however it can be much more efficient in the case where there - /// are no waiting threads. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.bump(); - } - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.mutex.data.get() } - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.mutex.data.get() } - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - self.mutex.raw.unlock(); - } - } -} - -impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} - -/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`. -/// -/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it -/// uses an `Arc`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[clippy::has_significant_drop] -#[must_use = "if unused the Mutex will immediately unlock"] -pub struct ArcMutexGuard { - mutex: Arc>, - marker: PhantomData<*const ()>, -} - -#[cfg(feature = "arc_lock")] -unsafe impl Send for ArcMutexGuard where - R::GuardMarker: Send -{ -} -#[cfg(feature = "arc_lock")] -unsafe impl Sync for ArcMutexGuard where - R::GuardMarker: Sync -{ -} - -#[cfg(feature = "arc_lock")] -impl ArcMutexGuard { - /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`. - #[inline] - pub fn mutex(s: &Self) -> &Arc> { - &s.mutex - } - - /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`]. - #[inline] - pub fn into_arc(s: Self) -> Arc> { - // Safety: Skip our Drop impl and manually unlock the mutex. - let arc = unsafe { ptr::read(&s.mutex) }; - mem::forget(s); - unsafe { - arc.raw.unlock(); - } - arc - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock(); - } - defer!(s.mutex.raw.lock()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl ArcMutexGuard { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - - // SAFETY: make sure the Arc gets it reference decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.mutex) }; - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`]. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.unlock_fair(); - } - defer!(s.mutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This is functionally identical to the `bump` method on [`MutexGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.mutex.raw.bump(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl Deref for ArcMutexGuard { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.mutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl DerefMut for ArcMutexGuard { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.mutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl Drop for ArcMutexGuard { - #[inline] - fn drop(&mut self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - self.mutex.raw.unlock(); - } - } -} - -/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a -/// subfield of the protected data. -/// -/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the -/// former doesn't support temporarily unlocking and re-locking, since that -/// could introduce soundness issues if the locked object is modified by another -/// thread. -#[clippy::has_significant_drop] -#[must_use = "if unused the Mutex will immediately unlock"] -pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> { - raw: &'a R, - data: *mut T, - marker: PhantomData<&'a mut T>, -} - -unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync - for MappedMutexGuard<'a, R, T> -{ -} -unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where - R::GuardMarker: Send -{ -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { - /// Makes a new `MappedMutexGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `MappedMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedMutexGuard<'a, R, U> - where - F: FnOnce(&mut T) -> &mut U, - { - let raw = s.raw; - let data = f(unsafe { &mut *s.data }); - mem::forget(s); - MappedMutexGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedMutexGuard` for a component of the - /// locked data. The original guard is returned if the closure returns `None`. - /// - /// This operation cannot fail as the `MappedMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&mut T) -> Option<&mut U>, - { - let raw = s.raw; - let data = match f(unsafe { &mut *s.data }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedMutexGuard { - raw, - data, - marker: PhantomData, - }) - } -} - -impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// By default, mutexes are unfair and allow the current thread to re-lock - /// the mutex before another has the chance to acquire the lock, even if - /// that thread has been blocked on the mutex for a long time. This is the - /// default because it allows much higher throughput as it avoids forcing a - /// context switch on every mutex unlock. This can result in one thread - /// acquiring a mutex many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `MutexGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MutexGuard always holds the lock. - unsafe { - s.raw.unlock_fair(); - } - mem::forget(s); - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.data } - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.data } - } -} - -impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: A MappedMutexGuard always holds the lock. - unsafe { - self.raw.unlock(); - } - } -} - -impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for MappedMutexGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/remutex.rs clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/remutex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/remutex.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/remutex.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1057 +0,0 @@ -// Copyright 2018 Amanieu d'Antras -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -use crate::{ - mutex::{RawMutex, RawMutexFair, RawMutexTimed}, - GuardNoSend, -}; -use core::{ - cell::{Cell, UnsafeCell}, - fmt, - marker::PhantomData, - mem, - num::NonZeroUsize, - ops::Deref, - sync::atomic::{AtomicUsize, Ordering}, -}; - -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - -#[cfg(feature = "owning_ref")] -use owning_ref::StableAddress; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -/// Helper trait which returns a non-zero thread ID. -/// -/// The simplest way to implement this trait is to return the address of a -/// thread-local variable. -/// -/// # Safety -/// -/// Implementations of this trait must ensure that no two active threads share -/// the same thread ID. However the ID of a thread that has exited can be -/// re-used since that thread is no longer active. -pub unsafe trait GetThreadId { - /// Initial value. - // A “non-constant” const item is a legacy way to supply an initialized value to downstream - // static items. Can hopefully be replaced with `const fn new() -> Self` at some point. - #[allow(clippy::declare_interior_mutable_const)] - const INIT: Self; - - /// Returns a non-zero thread ID which identifies the current thread of - /// execution. - fn nonzero_thread_id(&self) -> NonZeroUsize; -} - -/// A raw mutex type that wraps another raw mutex to provide reentrancy. -/// -/// Although this has the same methods as the [`RawMutex`] trait, it does -/// not implement it, and should not be used in the same way, since this -/// mutex can successfully acquire a lock multiple times in the same thread. -/// Only use this when you know you want a raw mutex that can be locked -/// reentrantly; you probably want [`ReentrantMutex`] instead. -pub struct RawReentrantMutex { - owner: AtomicUsize, - lock_count: Cell, - mutex: R, - get_thread_id: G, -} - -unsafe impl Send for RawReentrantMutex {} -unsafe impl Sync for RawReentrantMutex {} - -impl RawReentrantMutex { - /// Initial value for an unlocked mutex. - #[allow(clippy::declare_interior_mutable_const)] - pub const INIT: Self = RawReentrantMutex { - owner: AtomicUsize::new(0), - lock_count: Cell::new(0), - mutex: R::INIT, - get_thread_id: G::INIT, - }; - - #[inline] - fn lock_internal bool>(&self, try_lock: F) -> bool { - let id = self.get_thread_id.nonzero_thread_id().get(); - if self.owner.load(Ordering::Relaxed) == id { - self.lock_count.set( - self.lock_count - .get() - .checked_add(1) - .expect("ReentrantMutex lock count overflow"), - ); - } else { - if !try_lock() { - return false; - } - self.owner.store(id, Ordering::Relaxed); - debug_assert_eq!(self.lock_count.get(), 0); - self.lock_count.set(1); - } - true - } - - /// Acquires this mutex, blocking if it's held by another thread. - #[inline] - pub fn lock(&self) { - self.lock_internal(|| { - self.mutex.lock(); - true - }); - } - - /// Attempts to acquire this mutex without blocking. Returns `true` - /// if the lock was successfully acquired and `false` otherwise. - #[inline] - pub fn try_lock(&self) -> bool { - self.lock_internal(|| self.mutex.try_lock()) - } - - /// Unlocks this mutex. The inner mutex may not be unlocked if - /// this mutex was acquired previously in the current thread. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held by the current thread. - #[inline] - pub unsafe fn unlock(&self) { - let lock_count = self.lock_count.get() - 1; - self.lock_count.set(lock_count); - if lock_count == 0 { - self.owner.store(0, Ordering::Relaxed); - self.mutex.unlock(); - } - } - - /// Checks whether the mutex is currently locked. - #[inline] - pub fn is_locked(&self) -> bool { - self.mutex.is_locked() - } - - /// Checks whether the mutex is currently held by the current thread. - #[inline] - pub fn is_owned_by_current_thread(&self) -> bool { - let id = self.get_thread_id.nonzero_thread_id().get(); - self.owner.load(Ordering::Relaxed) == id - } -} - -impl RawReentrantMutex { - /// Unlocks this mutex using a fair unlock protocol. The inner mutex - /// may not be unlocked if this mutex was acquired previously in the - /// current thread. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held by the current thread. - #[inline] - pub unsafe fn unlock_fair(&self) { - let lock_count = self.lock_count.get() - 1; - self.lock_count.set(lock_count); - if lock_count == 0 { - self.owner.store(0, Ordering::Relaxed); - self.mutex.unlock_fair(); - } - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `lock`, however it can be much more efficient in the case where there - /// are no waiting threads. - /// - /// # Safety - /// - /// This method may only be called if the mutex is held by the current thread. - #[inline] - pub unsafe fn bump(&self) { - if self.lock_count.get() == 1 { - let id = self.owner.load(Ordering::Relaxed); - self.owner.store(0, Ordering::Relaxed); - self.lock_count.set(0); - self.mutex.bump(); - self.owner.store(id, Ordering::Relaxed); - self.lock_count.set(1); - } - } -} - -impl RawReentrantMutex { - /// Attempts to acquire this lock until a timeout is reached. - #[inline] - pub fn try_lock_until(&self, timeout: R::Instant) -> bool { - self.lock_internal(|| self.mutex.try_lock_until(timeout)) - } - - /// Attempts to acquire this lock until a timeout is reached. - #[inline] - pub fn try_lock_for(&self, timeout: R::Duration) -> bool { - self.lock_internal(|| self.mutex.try_lock_for(timeout)) - } -} - -/// A mutex which can be recursively locked by a single thread. -/// -/// This type is identical to `Mutex` except for the following points: -/// -/// - Locking multiple times from the same thread will work correctly instead of -/// deadlocking. -/// - `ReentrantMutexGuard` does not give mutable references to the locked data. -/// Use a `RefCell` if you need this. -/// -/// See [`Mutex`](crate::Mutex) for more details about the underlying mutex -/// primitive. -pub struct ReentrantMutex { - raw: RawReentrantMutex, - data: UnsafeCell, -} - -unsafe impl Send - for ReentrantMutex -{ -} -unsafe impl Sync - for ReentrantMutex -{ -} - -impl ReentrantMutex { - /// Creates a new reentrant mutex in an unlocked state ready for use. - #[cfg(has_const_fn_trait_bound)] - #[inline] - pub const fn new(val: T) -> ReentrantMutex { - ReentrantMutex { - data: UnsafeCell::new(val), - raw: RawReentrantMutex { - owner: AtomicUsize::new(0), - lock_count: Cell::new(0), - mutex: R::INIT, - get_thread_id: G::INIT, - }, - } - } - - /// Creates a new reentrant mutex in an unlocked state ready for use. - #[cfg(not(has_const_fn_trait_bound))] - #[inline] - pub fn new(val: T) -> ReentrantMutex { - ReentrantMutex { - data: UnsafeCell::new(val), - raw: RawReentrantMutex { - owner: AtomicUsize::new(0), - lock_count: Cell::new(0), - mutex: R::INIT, - get_thread_id: G::INIT, - }, - } - } - - /// Consumes this mutex, returning the underlying data. - #[inline] - pub fn into_inner(self) -> T { - self.data.into_inner() - } -} - -impl ReentrantMutex { - /// Creates a new reentrant mutex based on a pre-existing raw mutex and a - /// helper to get the thread ID. - #[inline] - pub const fn from_raw(raw_mutex: R, get_thread_id: G, val: T) -> ReentrantMutex { - ReentrantMutex { - data: UnsafeCell::new(val), - raw: RawReentrantMutex { - owner: AtomicUsize::new(0), - lock_count: Cell::new(0), - mutex: raw_mutex, - get_thread_id, - }, - } - } - - /// Creates a new reentrant mutex based on a pre-existing raw mutex and a - /// helper to get the thread ID. - /// - /// This allows creating a reentrant mutex in a constant context on stable - /// Rust. - /// - /// This method is a legacy alias for [`from_raw`](Self::from_raw). - #[inline] - pub const fn const_new(raw_mutex: R, get_thread_id: G, val: T) -> ReentrantMutex { - Self::from_raw(raw_mutex, get_thread_id, val) - } -} - -impl ReentrantMutex { - /// Creates a new `ReentrantMutexGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds the lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[inline] - pub unsafe fn make_guard_unchecked(&self) -> ReentrantMutexGuard<'_, R, G, T> { - ReentrantMutexGuard { - remutex: &self, - marker: PhantomData, - } - } - - /// Acquires a reentrant mutex, blocking the current thread until it is able - /// to do so. - /// - /// If the mutex is held by another thread then this function will block the - /// local thread until it is available to acquire the mutex. If the mutex is - /// already held by the current thread then this function will increment the - /// lock reference count and return immediately. Upon returning, - /// the thread is the only thread with the mutex held. An RAII guard is - /// returned to allow scoped unlock of the lock. When the guard goes out of - /// scope, the mutex will be unlocked. - #[inline] - pub fn lock(&self) -> ReentrantMutexGuard<'_, R, G, T> { - self.raw.lock(); - // SAFETY: The lock is held, as required. - unsafe { self.make_guard_unchecked() } - } - - /// Attempts to acquire this lock. - /// - /// If the lock could not be acquired at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned. The lock will be unlocked when the - /// guard is dropped. - /// - /// This function does not block. - #[inline] - pub fn try_lock(&self) -> Option> { - if self.raw.try_lock() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the `ReentrantMutex` mutably, no actual locking needs to - /// take place---the mutable borrow statically guarantees no locks exist. - #[inline] - pub fn get_mut(&mut self) -> &mut T { - unsafe { &mut *self.data.get() } - } - - /// Checks whether the mutex is currently locked. - #[inline] - pub fn is_locked(&self) -> bool { - self.raw.is_locked() - } - - /// Checks whether the mutex is currently held by the current thread. - #[inline] - pub fn is_owned_by_current_thread(&self) -> bool { - self.raw.is_owned_by_current_thread() - } - - /// Forcibly unlocks the mutex. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `ReentrantMutexGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `ReentrantMutexGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a mutex is unlocked when not locked. - #[inline] - pub unsafe fn force_unlock(&self) { - self.raw.unlock(); - } - - /// Returns the underlying raw mutex object. - /// - /// Note that you will most likely need to import the `RawMutex` trait from - /// `lock_api` to be able to call functions on the raw mutex. - /// - /// # Safety - /// - /// This method is unsafe because it allows unlocking a mutex while - /// still holding a reference to a `ReentrantMutexGuard`. - #[inline] - pub unsafe fn raw(&self) -> &R { - &self.raw.mutex - } - - /// Returns a raw pointer to the underlying data. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `ReentrantMutexGuard` object alive, for example - /// when dealing with FFI. - /// - /// # Safety - /// - /// You must ensure that there are no data races when dereferencing the - /// returned pointer, for example if the current thread logically owns a - /// `ReentrantMutexGuard` but that guard has been discarded using - /// `mem::forget`. - #[inline] - pub fn data_ptr(&self) -> *mut T { - self.data.get() - } - - /// Creates a new `ArcReentrantMutexGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds the lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[cfg(feature = "arc_lock")] - #[inline] - pub unsafe fn make_arc_guard_unchecked(self: &Arc) -> ArcReentrantMutexGuard { - ArcReentrantMutexGuard { - remutex: self.clone(), - marker: PhantomData, - } - } - - /// Acquires a reentrant mutex through an `Arc`. - /// - /// This method is similar to the `lock` method; however, it requires the `ReentrantMutex` to be inside of an - /// `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn lock_arc(self: &Arc) -> ArcReentrantMutexGuard { - self.raw.lock(); - // SAFETY: locking guarantee is upheld - unsafe { self.make_arc_guard_unchecked() } - } - - /// Attempts to acquire a reentrant mutex through an `Arc`. - /// - /// This method is similar to the `try_lock` method; however, it requires the `ReentrantMutex` to be inside - /// of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc(self: &Arc) -> Option> { - if self.raw.try_lock() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl ReentrantMutex { - /// Forcibly unlocks the mutex using a fair unlock protocol. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `ReentrantMutexGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `ReentrantMutexGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a mutex is unlocked when not locked. - #[inline] - pub unsafe fn force_unlock_fair(&self) { - self.raw.unlock_fair(); - } -} - -impl ReentrantMutex { - /// Attempts to acquire this lock until a timeout is reached. - /// - /// If the lock could not be acquired before the timeout expired, then - /// `None` is returned. Otherwise, an RAII guard is returned. The lock will - /// be unlocked when the guard is dropped. - #[inline] - pub fn try_lock_for(&self, timeout: R::Duration) -> Option> { - if self.raw.try_lock_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock until a timeout is reached. - /// - /// If the lock could not be acquired before the timeout expired, then - /// `None` is returned. Otherwise, an RAII guard is returned. The lock will - /// be unlocked when the guard is dropped. - #[inline] - pub fn try_lock_until(&self, timeout: R::Instant) -> Option> { - if self.raw.try_lock_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_lock_for` method; however, it requires the `ReentrantMutex` to be - /// inside of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_for( - self: &Arc, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this lock until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_lock_until` method; however, it requires the `ReentrantMutex` to be - /// inside of an `Arc` and the resulting mutex guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_lock_arc_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl Default for ReentrantMutex { - #[inline] - fn default() -> ReentrantMutex { - ReentrantMutex::new(Default::default()) - } -} - -impl From for ReentrantMutex { - #[inline] - fn from(t: T) -> ReentrantMutex { - ReentrantMutex::new(t) - } -} - -impl fmt::Debug for ReentrantMutex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.try_lock() { - Some(guard) => f - .debug_struct("ReentrantMutex") - .field("data", &&*guard) - .finish(), - None => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - - f.debug_struct("ReentrantMutex") - .field("data", &LockedPlaceholder) - .finish() - } - } - } -} - -// Copied and modified from serde -#[cfg(feature = "serde")] -impl Serialize for ReentrantMutex -where - R: RawMutex, - G: GetThreadId, - T: Serialize + ?Sized, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.lock().serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de, R, G, T> Deserialize<'de> for ReentrantMutex -where - R: RawMutex, - G: GetThreadId, - T: Deserialize<'de> + ?Sized, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Deserialize::deserialize(deserializer).map(ReentrantMutex::new) - } -} - -/// An RAII implementation of a "scoped lock" of a reentrant mutex. When this structure -/// is dropped (falls out of scope), the lock will be unlocked. -/// -/// The data protected by the mutex can be accessed through this guard via its -/// `Deref` implementation. -#[clippy::has_significant_drop] -#[must_use = "if unused the ReentrantMutex will immediately unlock"] -pub struct ReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { - remutex: &'a ReentrantMutex, - marker: PhantomData<(&'a T, GuardNoSend)>, -} - -unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync - for ReentrantMutexGuard<'a, R, G, T> -{ -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGuard<'a, R, G, T> { - /// Returns a reference to the original `ReentrantMutex` object. - pub fn remutex(s: &Self) -> &'a ReentrantMutex { - s.remutex - } - - /// Makes a new `MappedReentrantMutexGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `ReentrantMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedReentrantMutexGuard<'a, R, G, U> - where - F: FnOnce(&T) -> &U, - { - let raw = &s.remutex.raw; - let data = f(unsafe { &*s.remutex.data.get() }); - mem::forget(s); - MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedReentrantMutexGuard` for a component of the - /// locked data. The original guard is return if the closure returns `None`. - /// - /// This operation cannot fail as the `ReentrantMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `ReentrantMutexGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map( - s: Self, - f: F, - ) -> Result, Self> - where - F: FnOnce(&T) -> Option<&U>, - { - let raw = &s.remutex.raw; - let data = match f(unsafe { &*s.remutex.data.get() }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - }) - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - s.remutex.raw.unlock(); - } - defer!(s.remutex.raw.lock()); - f() - } -} - -impl<'a, R: RawMutexFair + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> - ReentrantMutexGuard<'a, R, G, T> -{ - /// Unlocks the mutex using a fair unlock protocol. - /// - /// By default, mutexes are unfair and allow the current thread to re-lock - /// the mutex before another has the chance to acquire the lock, even if - /// that thread has been blocked on the mutex for a long time. This is the - /// default because it allows much higher throughput as it avoids forcing a - /// context switch on every mutex unlock. This can result in one thread - /// acquiring a mutex many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `ReentrantMutexGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - mem::forget(s); - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// The mutex is unlocked a fair unlock protocol. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - defer!(s.remutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `lock`, however it can be much more efficient in the case where there - /// are no waiting threads. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.bump(); - } - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Deref - for ReentrantMutexGuard<'a, R, G, T> -{ - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.remutex.data.get() } - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop - for ReentrantMutexGuard<'a, R, G, T> -{ - #[inline] - fn drop(&mut self) { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - self.remutex.raw.unlock(); - } - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug - for ReentrantMutexGuard<'a, R, G, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for ReentrantMutexGuard<'a, R, G, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress - for ReentrantMutexGuard<'a, R, G, T> -{ -} - -/// An RAII mutex guard returned by the `Arc` locking operations on `ReentrantMutex`. -/// -/// This is similar to the `ReentrantMutexGuard` struct, except instead of using a reference to unlock the -/// `Mutex` it uses an `Arc`. This has several advantages, most notably that it has an `'static` -/// lifetime. -#[cfg(feature = "arc_lock")] -#[clippy::has_significant_drop] -#[must_use = "if unused the ReentrantMutex will immediately unlock"] -pub struct ArcReentrantMutexGuard { - remutex: Arc>, - marker: PhantomData, -} - -#[cfg(feature = "arc_lock")] -impl ArcReentrantMutexGuard { - /// Returns a reference to the `ReentrantMutex` this object is guarding, contained in its `Arc`. - pub fn remutex(s: &Self) -> &Arc> { - &s.remutex - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the mutex. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - s.remutex.raw.unlock(); - } - defer!(s.remutex.raw.lock()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl ArcReentrantMutexGuard { - /// Unlocks the mutex using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - - // SAFETY: ensure that the Arc's refcount is decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.remutex) }; - } - - /// Temporarily unlocks the mutex to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.unlock_fair(); - } - defer!(s.remutex.raw.lock()); - f() - } - - /// Temporarily yields the mutex to a waiting thread if there is one. - /// - /// This is functionally equivalent to the `bump` method on [`ReentrantMutexGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: A ReentrantMutexGuard always holds the lock - unsafe { - s.remutex.raw.bump(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl Deref for ArcReentrantMutexGuard { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.remutex.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl Drop for ArcReentrantMutexGuard { - #[inline] - fn drop(&mut self) { - // Safety: A ReentrantMutexGuard always holds the lock. - unsafe { - self.remutex.raw.unlock(); - } - } -} - -/// An RAII mutex guard returned by `ReentrantMutexGuard::map`, which can point to a -/// subfield of the protected data. -/// -/// The main difference between `MappedReentrantMutexGuard` and `ReentrantMutexGuard` is that the -/// former doesn't support temporarily unlocking and re-locking, since that -/// could introduce soundness issues if the locked object is modified by another -/// thread. -#[clippy::has_significant_drop] -#[must_use = "if unused the ReentrantMutex will immediately unlock"] -pub struct MappedReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { - raw: &'a RawReentrantMutex, - data: *const T, - marker: PhantomData<&'a T>, -} - -unsafe impl<'a, R: RawMutex + Sync + 'a, G: GetThreadId + Sync + 'a, T: ?Sized + Sync + 'a> Sync - for MappedReentrantMutexGuard<'a, R, G, T> -{ -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> - MappedReentrantMutexGuard<'a, R, G, T> -{ - /// Makes a new `MappedReentrantMutexGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `MappedReentrantMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MappedReentrantMutexGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedReentrantMutexGuard<'a, R, G, U> - where - F: FnOnce(&T) -> &U, - { - let raw = s.raw; - let data = f(unsafe { &*s.data }); - mem::forget(s); - MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedReentrantMutexGuard` for a component of the - /// locked data. The original guard is return if the closure returns `None`. - /// - /// This operation cannot fail as the `MappedReentrantMutexGuard` passed - /// in already locked the mutex. - /// - /// This is an associated function that needs to be - /// used as `MappedReentrantMutexGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map( - s: Self, - f: F, - ) -> Result, Self> - where - F: FnOnce(&T) -> Option<&U>, - { - let raw = s.raw; - let data = match f(unsafe { &*s.data }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedReentrantMutexGuard { - raw, - data, - marker: PhantomData, - }) - } -} - -impl<'a, R: RawMutexFair + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> - MappedReentrantMutexGuard<'a, R, G, T> -{ - /// Unlocks the mutex using a fair unlock protocol. - /// - /// By default, mutexes are unfair and allow the current thread to re-lock - /// the mutex before another has the chance to acquire the lock, even if - /// that thread has been blocked on the mutex for a long time. This is the - /// default because it allows much higher throughput as it avoids forcing a - /// context switch on every mutex unlock. This can result in one thread - /// acquiring a mutex many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `ReentrantMutexGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MappedReentrantMutexGuard always holds the lock - unsafe { - s.raw.unlock_fair(); - } - mem::forget(s); - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Deref - for MappedReentrantMutexGuard<'a, R, G, T> -{ - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.data } - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> Drop - for MappedReentrantMutexGuard<'a, R, G, T> -{ - #[inline] - fn drop(&mut self) { - // Safety: A MappedReentrantMutexGuard always holds the lock. - unsafe { - self.raw.unlock(); - } - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug - for MappedReentrantMutexGuard<'a, R, G, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for MappedReentrantMutexGuard<'a, R, G, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAddress - for MappedReentrantMutexGuard<'a, R, G, T> -{ -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/rwlock.rs clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/rwlock.rs --- clamav-1.4.3+dfsg/.cargo/vendor/lock_api/src/rwlock.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/lock_api/src/rwlock.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2886 +0,0 @@ -// Copyright 2016 Amanieu d'Antras -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -use core::cell::UnsafeCell; -use core::fmt; -use core::marker::PhantomData; -use core::mem; -use core::ops::{Deref, DerefMut}; - -#[cfg(feature = "arc_lock")] -use alloc::sync::Arc; -#[cfg(feature = "arc_lock")] -use core::mem::ManuallyDrop; -#[cfg(feature = "arc_lock")] -use core::ptr; - -#[cfg(feature = "owning_ref")] -use owning_ref::StableAddress; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -/// Basic operations for a reader-writer lock. -/// -/// Types implementing this trait can be used by `RwLock` to form a safe and -/// fully-functioning `RwLock` type. -/// -/// # Safety -/// -/// Implementations of this trait must ensure that the `RwLock` is actually -/// exclusive: an exclusive lock can't be acquired while an exclusive or shared -/// lock exists, and a shared lock can't be acquire while an exclusive lock -/// exists. -pub unsafe trait RawRwLock { - /// Initial value for an unlocked `RwLock`. - // A “non-constant” const item is a legacy way to supply an initialized value to downstream - // static items. Can hopefully be replaced with `const fn new() -> Self` at some point. - #[allow(clippy::declare_interior_mutable_const)] - const INIT: Self; - - /// Marker type which determines whether a lock guard should be `Send`. Use - /// one of the `GuardSend` or `GuardNoSend` helper types here. - type GuardMarker; - - /// Acquires a shared lock, blocking the current thread until it is able to do so. - fn lock_shared(&self); - - /// Attempts to acquire a shared lock without blocking. - fn try_lock_shared(&self) -> bool; - - /// Releases a shared lock. - /// - /// # Safety - /// - /// This method may only be called if a shared lock is held in the current context. - unsafe fn unlock_shared(&self); - - /// Acquires an exclusive lock, blocking the current thread until it is able to do so. - fn lock_exclusive(&self); - - /// Attempts to acquire an exclusive lock without blocking. - fn try_lock_exclusive(&self) -> bool; - - /// Releases an exclusive lock. - /// - /// # Safety - /// - /// This method may only be called if an exclusive lock is held in the current context. - unsafe fn unlock_exclusive(&self); - - /// Checks if this `RwLock` is currently locked in any way. - #[inline] - fn is_locked(&self) -> bool { - let acquired_lock = self.try_lock_exclusive(); - if acquired_lock { - // Safety: A lock was successfully acquired above. - unsafe { - self.unlock_exclusive(); - } - } - !acquired_lock - } - - /// Check if this `RwLock` is currently exclusively locked. - fn is_locked_exclusive(&self) -> bool { - let acquired_lock = self.try_lock_shared(); - if acquired_lock { - // Safety: A shared lock was successfully acquired above. - unsafe { - self.unlock_shared(); - } - } - !acquired_lock - } -} - -/// Additional methods for `RwLock`s which support fair unlocking. -/// -/// Fair unlocking means that a lock is handed directly over to the next waiting -/// thread if there is one, without giving other threads the opportunity to -/// "steal" the lock in the meantime. This is typically slower than unfair -/// unlocking, but may be necessary in certain circumstances. -pub unsafe trait RawRwLockFair: RawRwLock { - /// Releases a shared lock using a fair unlock protocol. - /// - /// # Safety - /// - /// This method may only be called if a shared lock is held in the current context. - unsafe fn unlock_shared_fair(&self); - - /// Releases an exclusive lock using a fair unlock protocol. - /// - /// # Safety - /// - /// This method may only be called if an exclusive lock is held in the current context. - unsafe fn unlock_exclusive_fair(&self); - - /// Temporarily yields a shared lock to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_shared_fair` followed - /// by `lock_shared`, however it can be much more efficient in the case where there - /// are no waiting threads. - /// - /// # Safety - /// - /// This method may only be called if a shared lock is held in the current context. - unsafe fn bump_shared(&self) { - self.unlock_shared_fair(); - self.lock_shared(); - } - - /// Temporarily yields an exclusive lock to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_exclusive_fair` followed - /// by `lock_exclusive`, however it can be much more efficient in the case where there - /// are no waiting threads. - /// - /// # Safety - /// - /// This method may only be called if an exclusive lock is held in the current context. - unsafe fn bump_exclusive(&self) { - self.unlock_exclusive_fair(); - self.lock_exclusive(); - } -} - -/// Additional methods for `RwLock`s which support atomically downgrading an -/// exclusive lock to a shared lock. -pub unsafe trait RawRwLockDowngrade: RawRwLock { - /// Atomically downgrades an exclusive lock into a shared lock without - /// allowing any thread to take an exclusive lock in the meantime. - /// - /// # Safety - /// - /// This method may only be called if an exclusive lock is held in the current context. - unsafe fn downgrade(&self); -} - -/// Additional methods for `RwLock`s which support locking with timeouts. -/// -/// The `Duration` and `Instant` types are specified as associated types so that -/// this trait is usable even in `no_std` environments. -pub unsafe trait RawRwLockTimed: RawRwLock { - /// Duration type used for `try_lock_for`. - type Duration; - - /// Instant type used for `try_lock_until`. - type Instant; - - /// Attempts to acquire a shared lock until a timeout is reached. - fn try_lock_shared_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to acquire a shared lock until a timeout is reached. - fn try_lock_shared_until(&self, timeout: Self::Instant) -> bool; - - /// Attempts to acquire an exclusive lock until a timeout is reached. - fn try_lock_exclusive_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to acquire an exclusive lock until a timeout is reached. - fn try_lock_exclusive_until(&self, timeout: Self::Instant) -> bool; -} - -/// Additional methods for `RwLock`s which support recursive read locks. -/// -/// These are guaranteed to succeed without blocking if -/// another read lock is held at the time of the call. This allows a thread -/// to recursively lock a `RwLock`. However using this method can cause -/// writers to starve since readers no longer block if a writer is waiting -/// for the lock. -pub unsafe trait RawRwLockRecursive: RawRwLock { - /// Acquires a shared lock without deadlocking in case of a recursive lock. - fn lock_shared_recursive(&self); - - /// Attempts to acquire a shared lock without deadlocking in case of a recursive lock. - fn try_lock_shared_recursive(&self) -> bool; -} - -/// Additional methods for `RwLock`s which support recursive read locks and timeouts. -pub unsafe trait RawRwLockRecursiveTimed: RawRwLockRecursive + RawRwLockTimed { - /// Attempts to acquire a shared lock until a timeout is reached, without - /// deadlocking in case of a recursive lock. - fn try_lock_shared_recursive_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to acquire a shared lock until a timeout is reached, without - /// deadlocking in case of a recursive lock. - fn try_lock_shared_recursive_until(&self, timeout: Self::Instant) -> bool; -} - -/// Additional methods for `RwLock`s which support atomically upgrading a shared -/// lock to an exclusive lock. -/// -/// This requires acquiring a special "upgradable read lock" instead of a -/// normal shared lock. There may only be one upgradable lock at any time, -/// otherwise deadlocks could occur when upgrading. -pub unsafe trait RawRwLockUpgrade: RawRwLock { - /// Acquires an upgradable lock, blocking the current thread until it is able to do so. - fn lock_upgradable(&self); - - /// Attempts to acquire an upgradable lock without blocking. - fn try_lock_upgradable(&self) -> bool; - - /// Releases an upgradable lock. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn unlock_upgradable(&self); - - /// Upgrades an upgradable lock to an exclusive lock. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn upgrade(&self); - - /// Attempts to upgrade an upgradable lock to an exclusive lock without - /// blocking. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn try_upgrade(&self) -> bool; -} - -/// Additional methods for `RwLock`s which support upgradable locks and fair -/// unlocking. -pub unsafe trait RawRwLockUpgradeFair: RawRwLockUpgrade + RawRwLockFair { - /// Releases an upgradable lock using a fair unlock protocol. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn unlock_upgradable_fair(&self); - - /// Temporarily yields an upgradable lock to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_upgradable_fair` followed - /// by `lock_upgradable`, however it can be much more efficient in the case where there - /// are no waiting threads. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn bump_upgradable(&self) { - self.unlock_upgradable_fair(); - self.lock_upgradable(); - } -} - -/// Additional methods for `RwLock`s which support upgradable locks and lock -/// downgrading. -pub unsafe trait RawRwLockUpgradeDowngrade: RawRwLockUpgrade + RawRwLockDowngrade { - /// Downgrades an upgradable lock to a shared lock. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn downgrade_upgradable(&self); - - /// Downgrades an exclusive lock to an upgradable lock. - /// - /// # Safety - /// - /// This method may only be called if an exclusive lock is held in the current context. - unsafe fn downgrade_to_upgradable(&self); -} - -/// Additional methods for `RwLock`s which support upgradable locks and locking -/// with timeouts. -pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed { - /// Attempts to acquire an upgradable lock until a timeout is reached. - fn try_lock_upgradable_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to acquire an upgradable lock until a timeout is reached. - fn try_lock_upgradable_until(&self, timeout: Self::Instant) -> bool; - - /// Attempts to upgrade an upgradable lock to an exclusive lock until a - /// timeout is reached. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn try_upgrade_for(&self, timeout: Self::Duration) -> bool; - - /// Attempts to upgrade an upgradable lock to an exclusive lock until a - /// timeout is reached. - /// - /// # Safety - /// - /// This method may only be called if an upgradable lock is held in the current context. - unsafe fn try_upgrade_until(&self, timeout: Self::Instant) -> bool; -} - -/// A reader-writer lock -/// -/// This type of lock allows a number of readers or at most one writer at any -/// point in time. The write portion of this lock typically allows modification -/// of the underlying data (exclusive access) and the read portion of this lock -/// typically allows for read-only access (shared access). -/// -/// The type parameter `T` represents the data that this lock protects. It is -/// required that `T` satisfies `Send` to be shared across threads and `Sync` to -/// allow concurrent access through readers. The RAII guards returned from the -/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) -/// to allow access to the contained of the lock. -pub struct RwLock { - raw: R, - data: UnsafeCell, -} - -// Copied and modified from serde -#[cfg(feature = "serde")] -impl Serialize for RwLock -where - R: RawRwLock, - T: Serialize + ?Sized, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.read().serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de, R, T> Deserialize<'de> for RwLock -where - R: RawRwLock, - T: Deserialize<'de> + ?Sized, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Deserialize::deserialize(deserializer).map(RwLock::new) - } -} - -unsafe impl Send for RwLock {} -unsafe impl Sync for RwLock {} - -impl RwLock { - /// Creates a new instance of an `RwLock` which is unlocked. - #[cfg(has_const_fn_trait_bound)] - #[inline] - pub const fn new(val: T) -> RwLock { - RwLock { - data: UnsafeCell::new(val), - raw: R::INIT, - } - } - - /// Creates a new instance of an `RwLock` which is unlocked. - #[cfg(not(has_const_fn_trait_bound))] - #[inline] - pub fn new(val: T) -> RwLock { - RwLock { - data: UnsafeCell::new(val), - raw: R::INIT, - } - } - - /// Consumes this `RwLock`, returning the underlying data. - #[inline] - #[allow(unused_unsafe)] - pub fn into_inner(self) -> T { - unsafe { self.data.into_inner() } - } -} - -impl RwLock { - /// Creates a new new instance of an `RwLock` based on a pre-existing - /// `RawRwLock`. - #[inline] - pub const fn from_raw(raw_rwlock: R, val: T) -> RwLock { - RwLock { - data: UnsafeCell::new(val), - raw: raw_rwlock, - } - } - - /// Creates a new new instance of an `RwLock` based on a pre-existing - /// `RawRwLock`. - /// - /// This allows creating a `RwLock` in a constant context on stable - /// Rust. - /// - /// This method is a legacy alias for [`from_raw`](Self::from_raw). - #[inline] - pub const fn const_new(raw_rwlock: R, val: T) -> RwLock { - Self::from_raw(raw_rwlock, val) - } -} - -impl RwLock { - /// Creates a new `RwLockReadGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds a read lock. - /// - /// This function does not increment the read count of the lock. Calling this function when a - /// guard has already been produced is undefined behaviour unless the guard was forgotten - /// with `mem::forget`. - #[inline] - pub unsafe fn make_read_guard_unchecked(&self) -> RwLockReadGuard<'_, R, T> { - RwLockReadGuard { - rwlock: self, - marker: PhantomData, - } - } - - /// Creates a new `RwLockReadGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds a write lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[inline] - pub unsafe fn make_write_guard_unchecked(&self) -> RwLockWriteGuard<'_, R, T> { - RwLockWriteGuard { - rwlock: self, - marker: PhantomData, - } - } - - /// Locks this `RwLock` with shared read access, blocking the current thread - /// until it can be acquired. - /// - /// The calling thread will be blocked until there are no more writers which - /// hold the lock. There may be other readers currently inside the lock when - /// this method returns. - /// - /// Note that attempts to recursively acquire a read lock on a `RwLock` when - /// the current thread already holds one may result in a deadlock. - /// - /// Returns an RAII guard which will release this thread's shared access - /// once it is dropped. - #[inline] - pub fn read(&self) -> RwLockReadGuard<'_, R, T> { - self.raw.lock_shared(); - // SAFETY: The lock is held, as required. - unsafe { self.make_read_guard_unchecked() } - } - - /// Attempts to acquire this `RwLock` with shared read access. - /// - /// If the access could not be granted at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned which will release the shared access - /// when it is dropped. - /// - /// This function does not block. - #[inline] - pub fn try_read(&self) -> Option> { - if self.raw.try_lock_shared() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Locks this `RwLock` with exclusive write access, blocking the current - /// thread until it can be acquired. - /// - /// This function will not return while other writers or other readers - /// currently have access to the lock. - /// - /// Returns an RAII guard which will drop the write access of this `RwLock` - /// when dropped. - #[inline] - pub fn write(&self) -> RwLockWriteGuard<'_, R, T> { - self.raw.lock_exclusive(); - // SAFETY: The lock is held, as required. - unsafe { self.make_write_guard_unchecked() } - } - - /// Attempts to lock this `RwLock` with exclusive write access. - /// - /// If the lock could not be acquired at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned which will release the lock when - /// it is dropped. - /// - /// This function does not block. - #[inline] - pub fn try_write(&self) -> Option> { - if self.raw.try_lock_exclusive() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_write_guard_unchecked() }) - } else { - None - } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the `RwLock` mutably, no actual locking needs to - /// take place---the mutable borrow statically guarantees no locks exist. - #[inline] - pub fn get_mut(&mut self) -> &mut T { - unsafe { &mut *self.data.get() } - } - - /// Checks whether this `RwLock` is currently locked in any way. - #[inline] - pub fn is_locked(&self) -> bool { - self.raw.is_locked() - } - - /// Check if this `RwLock` is currently exclusively locked. - #[inline] - pub fn is_locked_exclusive(&self) -> bool { - self.raw.is_locked_exclusive() - } - - /// Forcibly unlocks a read lock. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `RwLockReadGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a rwlock is read-unlocked when not read-locked. - #[inline] - pub unsafe fn force_unlock_read(&self) { - self.raw.unlock_shared(); - } - - /// Forcibly unlocks a write lock. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `RwLockWriteGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a rwlock is write-unlocked when not write-locked. - #[inline] - pub unsafe fn force_unlock_write(&self) { - self.raw.unlock_exclusive(); - } - - /// Returns the underlying raw reader-writer lock object. - /// - /// Note that you will most likely need to import the `RawRwLock` trait from - /// `lock_api` to be able to call functions on the raw - /// reader-writer lock. - /// - /// # Safety - /// - /// This method is unsafe because it allows unlocking a mutex while - /// still holding a reference to a lock guard. - pub unsafe fn raw(&self) -> &R { - &self.raw - } - - /// Returns a raw pointer to the underlying data. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `RwLockReadGuard` or `RwLockWriteGuard` object - /// alive, for example when dealing with FFI. - /// - /// # Safety - /// - /// You must ensure that there are no data races when dereferencing the - /// returned pointer, for example if the current thread logically owns a - /// `RwLockReadGuard` or `RwLockWriteGuard` but that guard has been discarded - /// using `mem::forget`. - #[inline] - pub fn data_ptr(&self) -> *mut T { - self.data.get() - } - - /// Creates a new `RwLockReadGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds a read lock. - /// - /// This function does not increment the read count of the lock. Calling this function when a - /// guard has already been produced is undefined behaviour unless the guard was forgotten - /// with `mem::forget`.` - #[cfg(feature = "arc_lock")] - #[inline] - pub unsafe fn make_arc_read_guard_unchecked(self: &Arc) -> ArcRwLockReadGuard { - ArcRwLockReadGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// Creates a new `RwLockWriteGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds a write lock. - /// - /// Calling this function when a guard has already been produced is undefined behaviour unless - /// the guard was forgotten with `mem::forget`. - #[cfg(feature = "arc_lock")] - #[inline] - pub unsafe fn make_arc_write_guard_unchecked(self: &Arc) -> ArcRwLockWriteGuard { - ArcRwLockWriteGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// Locks this `RwLock` with read access, through an `Arc`. - /// - /// This method is similar to the `read` method; however, it requires the `RwLock` to be inside of an `Arc` - /// and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn read_arc(self: &Arc) -> ArcRwLockReadGuard { - self.raw.lock_shared(); - // SAFETY: locking guarantee is upheld - unsafe { self.make_arc_read_guard_unchecked() } - } - - /// Attempts to lock this `RwLock` with read access, through an `Arc`. - /// - /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc(self: &Arc) -> Option> { - if self.raw.try_lock_shared() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } - - /// Locks this `RwLock` with write access, through an `Arc`. - /// - /// This method is similar to the `write` method; however, it requires the `RwLock` to be inside of an `Arc` - /// and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn write_arc(self: &Arc) -> ArcRwLockWriteGuard { - self.raw.lock_exclusive(); - // SAFETY: locking guarantee is upheld - unsafe { self.make_arc_write_guard_unchecked() } - } - - /// Attempts to lock this `RwLock` with writ access, through an `Arc`. - /// - /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc(self: &Arc) -> Option> { - if self.raw.try_lock_exclusive() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_write_guard_unchecked() }) - } else { - None - } - } -} - -impl RwLock { - /// Forcibly unlocks a read lock using a fair unlock protocol. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `RwLockReadGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a rwlock is read-unlocked when not read-locked. - #[inline] - pub unsafe fn force_unlock_read_fair(&self) { - self.raw.unlock_shared_fair(); - } - - /// Forcibly unlocks a write lock using a fair unlock protocol. - /// - /// This is useful when combined with `mem::forget` to hold a lock without - /// the need to maintain a `RwLockWriteGuard` object alive, for example when - /// dealing with FFI. - /// - /// # Safety - /// - /// This method must only be called if the current thread logically owns a - /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`. - /// Behavior is undefined if a rwlock is write-unlocked when not write-locked. - #[inline] - pub unsafe fn force_unlock_write_fair(&self) { - self.raw.unlock_exclusive_fair(); - } -} - -impl RwLock { - /// Attempts to acquire this `RwLock` with shared read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - #[inline] - pub fn try_read_for(&self, timeout: R::Duration) -> Option> { - if self.raw.try_lock_shared_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with shared read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - #[inline] - pub fn try_read_until(&self, timeout: R::Instant) -> Option> { - if self.raw.try_lock_shared_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with exclusive write access until a - /// timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the exclusive access when it is dropped. - #[inline] - pub fn try_write_for(&self, timeout: R::Duration) -> Option> { - if self.raw.try_lock_exclusive_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_write_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with exclusive write access until a - /// timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the exclusive access when it is dropped. - #[inline] - pub fn try_write_until(&self, timeout: R::Instant) -> Option> { - if self.raw.try_lock_exclusive_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_write_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_for` method; however, it requires the `RwLock` to be inside of an - /// `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_for( - self: &Arc, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_shared_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_until` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_shared_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with write access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_write_for` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting write guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc_for( - self: &Arc, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_exclusive_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_write_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_write_until` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_write_arc_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_exclusive_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_write_guard_unchecked() }) - } else { - None - } - } -} - -impl RwLock { - /// Locks this `RwLock` with shared read access, blocking the current thread - /// until it can be acquired. - /// - /// The calling thread will be blocked until there are no more writers which - /// hold the lock. There may be other readers currently inside the lock when - /// this method returns. - /// - /// Unlike `read`, this method is guaranteed to succeed without blocking if - /// another read lock is held at the time of the call. This allows a thread - /// to recursively lock a `RwLock`. However using this method can cause - /// writers to starve since readers no longer block if a writer is waiting - /// for the lock. - /// - /// Returns an RAII guard which will release this thread's shared access - /// once it is dropped. - #[inline] - pub fn read_recursive(&self) -> RwLockReadGuard<'_, R, T> { - self.raw.lock_shared_recursive(); - // SAFETY: The lock is held, as required. - unsafe { self.make_read_guard_unchecked() } - } - - /// Attempts to acquire this `RwLock` with shared read access. - /// - /// If the access could not be granted at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned which will release the shared access - /// when it is dropped. - /// - /// This method is guaranteed to succeed if another read lock is held at the - /// time of the call. See the documentation for `read_recursive` for details. - /// - /// This function does not block. - #[inline] - pub fn try_read_recursive(&self) -> Option> { - if self.raw.try_lock_shared_recursive() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Locks this `RwLock` with shared read access, through an `Arc`. - /// - /// This method is similar to the `read_recursive` method; however, it requires the `RwLock` to be inside of - /// an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn read_arc_recursive(self: &Arc) -> ArcRwLockReadGuard { - self.raw.lock_shared_recursive(); - // SAFETY: locking guarantee is upheld - unsafe { self.make_arc_read_guard_unchecked() } - } - - /// Attempts to lock this `RwLock` with shared read access, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive` method; however, it requires the `RwLock` to be inside - /// of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_recursive_arc(self: &Arc) -> Option> { - if self.raw.try_lock_shared_recursive() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } -} - -impl RwLock { - /// Attempts to acquire this `RwLock` with shared read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - /// - /// This method is guaranteed to succeed without blocking if another read - /// lock is held at the time of the call. See the documentation for - /// `read_recursive` for details. - #[inline] - pub fn try_read_recursive_for( - &self, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_shared_recursive_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with shared read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - #[inline] - pub fn try_read_recursive_until( - &self, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_shared_recursive_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive_for` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_recursive_for( - self: &Arc, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_shared_recursive_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_read_recursive_until` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_read_arc_recursive_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_shared_recursive_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_arc_read_guard_unchecked() }) - } else { - None - } - } -} - -impl RwLock { - /// Creates a new `RwLockUpgradableReadGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds an upgradable read lock. - /// - /// This function does not increment the read count of the lock. Calling this function when a - /// guard has already been produced is undefined behaviour unless the guard was forgotten - /// with `mem::forget`. - #[inline] - pub unsafe fn make_upgradable_guard_unchecked(&self) -> RwLockUpgradableReadGuard<'_, R, T> { - RwLockUpgradableReadGuard { - rwlock: self, - marker: PhantomData, - } - } - - /// Locks this `RwLock` with upgradable read access, blocking the current thread - /// until it can be acquired. - /// - /// The calling thread will be blocked until there are no more writers or other - /// upgradable reads which hold the lock. There may be other readers currently - /// inside the lock when this method returns. - /// - /// Returns an RAII guard which will release this thread's shared access - /// once it is dropped. - #[inline] - pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<'_, R, T> { - self.raw.lock_upgradable(); - // SAFETY: The lock is held, as required. - unsafe { self.make_upgradable_guard_unchecked() } - } - - /// Attempts to acquire this `RwLock` with upgradable read access. - /// - /// If the access could not be granted at this time, then `None` is returned. - /// Otherwise, an RAII guard is returned which will release the shared access - /// when it is dropped. - /// - /// This function does not block. - #[inline] - pub fn try_upgradable_read(&self) -> Option> { - if self.raw.try_lock_upgradable() { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_upgradable_guard_unchecked() }) - } else { - None - } - } - - /// Creates a new `ArcRwLockUpgradableReadGuard` without checking if the lock is held. - /// - /// # Safety - /// - /// This method must only be called if the thread logically holds an upgradable read lock. - /// - /// This function does not increment the read count of the lock. Calling this function when a - /// guard has already been produced is undefined behaviour unless the guard was forgotten - /// with `mem::forget`.` - #[cfg(feature = "arc_lock")] - #[inline] - pub unsafe fn make_upgradable_arc_guard_unchecked( - self: &Arc, - ) -> ArcRwLockUpgradableReadGuard { - ArcRwLockUpgradableReadGuard { - rwlock: self.clone(), - marker: PhantomData, - } - } - - /// Locks this `RwLock` with upgradable read access, through an `Arc`. - /// - /// This method is similar to the `upgradable_read` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn upgradable_read_arc(self: &Arc) -> ArcRwLockUpgradableReadGuard { - self.raw.lock_upgradable(); - // SAFETY: locking guarantee is upheld - unsafe { self.make_upgradable_arc_guard_unchecked() } - } - - /// Attempts to lock this `RwLock` with upgradable read access, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc(self: &Arc) -> Option> { - if self.raw.try_lock_upgradable() { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_upgradable_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl RwLock { - /// Attempts to acquire this `RwLock` with upgradable read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - #[inline] - pub fn try_upgradable_read_for( - &self, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_upgradable_for(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_upgradable_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to acquire this `RwLock` with upgradable read access until a timeout - /// is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. Otherwise, an RAII guard is returned which will - /// release the shared access when it is dropped. - #[inline] - pub fn try_upgradable_read_until( - &self, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_upgradable_until(timeout) { - // SAFETY: The lock is held, as required. - Some(unsafe { self.make_upgradable_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read_for` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc_for( - self: &Arc, - timeout: R::Duration, - ) -> Option> { - if self.raw.try_lock_upgradable_for(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_upgradable_arc_guard_unchecked() }) - } else { - None - } - } - - /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`. - /// - /// This method is similar to the `try_upgradable_read_until` method; however, it requires the `RwLock` to be - /// inside of an `Arc` and the resulting read guard has no lifetime requirements. - #[cfg(feature = "arc_lock")] - #[inline] - pub fn try_upgradable_read_arc_until( - self: &Arc, - timeout: R::Instant, - ) -> Option> { - if self.raw.try_lock_upgradable_until(timeout) { - // SAFETY: locking guarantee is upheld - Some(unsafe { self.make_upgradable_arc_guard_unchecked() }) - } else { - None - } - } -} - -impl Default for RwLock { - #[inline] - fn default() -> RwLock { - RwLock::new(Default::default()) - } -} - -impl From for RwLock { - #[inline] - fn from(t: T) -> RwLock { - RwLock::new(t) - } -} - -impl fmt::Debug for RwLock { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut d = f.debug_struct("RwLock"); - match self.try_read() { - Some(guard) => d.field("data", &&*guard), - None => { - // Additional format_args! here is to remove quotes around in debug output. - d.field("data", &format_args!("")) - } - }; - d.finish() - } -} - -/// RAII structure used to release the shared read access of a lock when -/// dropped. -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { - rwlock: &'a RwLock, - marker: PhantomData<(&'a T, R::GuardMarker)>, -} - -unsafe impl Sync for RwLockReadGuard<'_, R, T> {} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { - /// Returns a reference to the original reader-writer lock object. - pub fn rwlock(s: &Self) -> &'a RwLock { - s.rwlock - } - - /// Make a new `MappedRwLockReadGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `RwLockReadGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U> - where - F: FnOnce(&T) -> &U, - { - let raw = &s.rwlock.raw; - let data = f(unsafe { &*s.rwlock.data.get() }); - mem::forget(s); - MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedRwLockReadGuard` for a component of the - /// locked data. Returns the original guard if the closure returns `None`. - /// - /// This operation cannot fail as the `RwLockReadGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `RwLockReadGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&T) -> Option<&U>, - { - let raw = &s.rwlock.raw; - let data = match f(unsafe { &*s.rwlock.data.get() }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - }) - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } -} - -impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// By default, `RwLock` is unfair and allow the current thread to re-lock - /// the `RwLock` before another has the chance to acquire the lock, even if - /// that thread has been blocked on the `RwLock` for a long time. This is - /// the default because it allows much higher throughput as it avoids - /// forcing a context switch on every `RwLock` unlock. This can result in one - /// thread acquiring a `RwLock` many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `RwLockReadGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - mem::forget(s); - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// The `RwLock` is unlocked a fair unlock protocol. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `read`, however it can be much more efficient in the case where there - /// are no waiting threads. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.bump_shared(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockReadGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - self.rwlock.raw.unlock_shared(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockReadGuard<'a, R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for RwLockReadGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {} - -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// -/// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock` -/// it uses an `Arc`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockReadGuard { - rwlock: Arc>, - marker: PhantomData, -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockReadGuard { - /// Returns a reference to the rwlock, contained in its `Arc`. - pub fn rwlock(s: &Self) -> &Arc> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockReadGuard { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - - // SAFETY: ensure the Arc has its refcount decremented - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked_fair` method on [`RwLockReadGuard`]. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_shared_fair(); - } - defer!(s.rwlock.raw.lock_shared()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This is functionally identical to the `bump` method on [`RwLockReadGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.bump_shared(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl Deref for ArcRwLockReadGuard { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl Drop for ArcRwLockReadGuard { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - self.rwlock.raw.unlock_shared(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Debug for ArcRwLockReadGuard { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Display for ArcRwLockReadGuard { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -/// RAII structure used to release the exclusive write access of a lock when -/// dropped. -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { - rwlock: &'a RwLock, - marker: PhantomData<(&'a mut T, R::GuardMarker)>, -} - -unsafe impl Sync for RwLockWriteGuard<'_, R, T> {} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { - /// Returns a reference to the original reader-writer lock object. - pub fn rwlock(s: &Self) -> &'a RwLock { - s.rwlock - } - - /// Make a new `MappedRwLockWriteGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `RwLockWriteGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> - where - F: FnOnce(&mut T) -> &mut U, - { - let raw = &s.rwlock.raw; - let data = f(unsafe { &mut *s.rwlock.data.get() }); - mem::forget(s); - MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the - /// locked data. The original guard is return if the closure returns `None`. - /// - /// This operation cannot fail as the `RwLockWriteGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `RwLockWriteGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&mut T) -> Option<&mut U>, - { - let raw = &s.rwlock.raw; - let data = match f(unsafe { &mut *s.rwlock.data.get() }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - }) - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockReadGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_exclusive(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } -} - -impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { - /// Atomically downgrades a write lock into a read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// Note that if there are any writers currently waiting to take the lock - /// then other readers may not be able to acquire the lock even if it was - /// downgraded. - pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade(); - } - let rwlock = s.rwlock; - mem::forget(s); - RwLockReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { - /// Atomically downgrades a write lock into an upgradable read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// Note that if there are any writers currently waiting to take the lock - /// then other readers may not be able to acquire the lock even if it was - /// downgraded. - pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, R, T> { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade_to_upgradable(); - } - let rwlock = s.rwlock; - mem::forget(s); - RwLockUpgradableReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// By default, `RwLock` is unfair and allow the current thread to re-lock - /// the `RwLock` before another has the chance to acquire the lock, even if - /// that thread has been blocked on the `RwLock` for a long time. This is - /// the default because it allows much higher throughput as it avoids - /// forcing a context switch on every `RwLock` unlock. This can result in one - /// thread acquiring a `RwLock` many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `RwLockWriteGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - mem::forget(s); - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// The `RwLock` is unlocked a fair unlock protocol. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `write`, however it can be much more efficient in the case where there - /// are no waiting threads. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.bump_exclusive(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockWriteGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for RwLockWriteGuard<'a, R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.rwlock.data.get() } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - self.rwlock.raw.unlock_exclusive(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockWriteGuard<'a, R, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for RwLockWriteGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {} - -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock` -/// it uses an `Arc`. This has several advantages, most notably that it has an `'static` lifetime. -#[cfg(feature = "arc_lock")] -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockWriteGuard { - rwlock: Arc>, - marker: PhantomData, -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockWriteGuard { - /// Returns a reference to the rwlock, contained in its `Arc`. - pub fn rwlock(s: &Self) -> &Arc> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockWriteGuard always holds a shared lock. - unsafe { - s.rwlock.raw.unlock_exclusive(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockWriteGuard { - /// Atomically downgrades a write lock into a read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// This is functionally equivalent to the `downgrade` method on [`RwLockWriteGuard`]. - pub fn downgrade(s: Self) -> ArcRwLockReadGuard { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade(); - } - - // SAFETY: prevent the arc's refcount from changing using ManuallyDrop and ptr::read - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockWriteGuard { - /// Atomically downgrades a write lock into an upgradable read lock without allowing any - /// writers to take exclusive access of the lock in the meantime. - /// - /// This is functionally identical to the `downgrade_to_upgradable` method on [`RwLockWriteGuard`]. - pub fn downgrade_to_upgradable(s: Self) -> ArcRwLockUpgradableReadGuard { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.downgrade_to_upgradable(); - } - - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockUpgradableReadGuard { - rwlock, - marker: PhantomData, - } - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockWriteGuard { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally equivalent to the `unlock_fair` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - - // SAFETY: prevent the Arc from leaking memory - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockWriteGuard`]. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.unlock_exclusive_fair(); - } - defer!(s.rwlock.raw.lock_exclusive()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - s.rwlock.raw.bump_exclusive(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl Deref for ArcRwLockWriteGuard { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl DerefMut for ArcRwLockWriteGuard { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl Drop for ArcRwLockWriteGuard { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockWriteGuard always holds an exclusive lock. - unsafe { - self.rwlock.raw.unlock_exclusive(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Debug for ArcRwLockWriteGuard { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Display for ArcRwLockWriteGuard { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -/// RAII structure used to release the upgradable read access of a lock when -/// dropped. -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> { - rwlock: &'a RwLock, - marker: PhantomData<(&'a T, R::GuardMarker)>, -} - -unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + Sync + 'a> Sync - for RwLockUpgradableReadGuard<'a, R, T> -{ -} - -impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { - /// Returns a reference to the original reader-writer lock object. - pub fn rwlock(s: &Self) -> &'a RwLock { - s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Atomically upgrades an upgradable read lock lock into an exclusive write lock, - /// blocking the current thread until it can be acquired. - pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.upgrade(); - } - let rwlock = s.rwlock; - mem::forget(s); - RwLockWriteGuard { - rwlock, - marker: PhantomData, - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock. - /// - /// If the access could not be granted at this time, then the current guard is returned. - pub fn try_upgrade(s: Self) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade() } { - let rwlock = s.rwlock; - mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// By default, `RwLock` is unfair and allow the current thread to re-lock - /// the `RwLock` before another has the chance to acquire the lock, even if - /// that thread has been blocked on the `RwLock` for a long time. This is - /// the default because it allows much higher throughput as it avoids - /// forcing a context switch on every `RwLock` unlock. This can result in one - /// thread acquiring a `RwLock` many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `RwLockUpgradableReadGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - mem::forget(s); - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// The `RwLock` is unlocked a fair unlock protocol. - /// - /// This is safe because `&mut` guarantees that there exist no other - /// references to the data protected by the `RwLock`. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `unlock_fair` followed - /// by `upgradable_read`, however it can be much more efficient in the case where there - /// are no waiting threads. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.bump_upgradable(); - } - } -} - -impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { - /// Atomically downgrades an upgradable read lock lock into a shared read lock - /// without allowing any writers to take exclusive access of the lock in the - /// meantime. - /// - /// Note that if there are any writers currently waiting to take the lock - /// then other readers may not be able to acquire the lock even if it was - /// downgraded. - pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.downgrade_upgradable(); - } - let rwlock = s.rwlock; - mem::forget(s); - RwLockReadGuard { - rwlock, - marker: PhantomData, - } - } - - /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock, - /// blocking the current thread until it can be acquired. - /// - /// Then, calls the provided closure with an exclusive reference to the lock's data. - /// - /// Finally, atomically downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `upgrade` which takes the guard by value. - pub fn with_upgraded Ret>(&mut self, f: F) -> Ret { - unsafe { - self.rwlock.raw.upgrade(); - } - - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - f(unsafe { &mut *self.rwlock.data.get() }) - } - - /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock. - /// - /// If the access could not be granted at this time, then `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade` which takes the guard by value. - pub fn try_with_upgraded Ret>(&mut self, f: F) -> Option { - if unsafe { self.rwlock.raw.try_upgrade() } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } -} - -impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - pub fn try_upgrade_for( - s: Self, - timeout: R::Duration, - ) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } { - let rwlock = s.rwlock; - mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - #[inline] - pub fn try_upgrade_until( - s: Self, - timeout: R::Instant, - ) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } { - let rwlock = s.rwlock; - mem::forget(s); - Ok(RwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -impl<'a, R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> - RwLockUpgradableReadGuard<'a, R, T> -{ - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade_for` which takes the guard by value. - pub fn try_with_upgraded_for Ret>( - &mut self, - timeout: R::Duration, - f: F, - ) -> Option { - if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade_until` which takes the guard by value. - pub fn try_with_upgraded_until Ret>( - &mut self, - timeout: R::Instant, - f: F, - ) -> Option { - if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } -} - -impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableReadGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - self.rwlock.raw.unlock_upgradable(); - } - } -} - -impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug - for RwLockUpgradableReadGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for RwLockUpgradableReadGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress - for RwLockUpgradableReadGuard<'a, R, T> -{ -} - -/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`. -/// This is similar to the `RwLockUpgradableReadGuard` struct, except instead of using a reference to unlock the -/// `RwLock` it uses an `Arc`. This has several advantages, most notably that it has an `'static` -/// lifetime. -#[cfg(feature = "arc_lock")] -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct ArcRwLockUpgradableReadGuard { - rwlock: Arc>, - marker: PhantomData, -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockUpgradableReadGuard { - /// Returns a reference to the rwlock, contained in its original `Arc`. - pub fn rwlock(s: &Self) -> &Arc> { - &s.rwlock - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally identical to the `unlocked` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlocked(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Atomically upgrades an upgradable read lock lock into an exclusive write lock, - /// blocking the current thread until it can be acquired. - pub fn upgrade(s: Self) -> ArcRwLockWriteGuard { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.upgrade(); - } - - // SAFETY: avoid incrementing or decrementing the refcount using ManuallyDrop and reading the Arc out - // of the struct - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock. - /// - /// If the access could not be granted at this time, then the current guard is returned. - pub fn try_upgrade(s: Self) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade() } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockUpgradableReadGuard { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// This is functionally identical to the `unlock_fair` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - - // SAFETY: make sure we decrement the refcount properly - let mut s = ManuallyDrop::new(s); - unsafe { ptr::drop_in_place(&mut s.rwlock) }; - } - - /// Temporarily unlocks the `RwLock` to execute the given function. - /// - /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn unlocked_fair(s: &mut Self, f: F) -> U - where - F: FnOnce() -> U, - { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.unlock_upgradable_fair(); - } - defer!(s.rwlock.raw.lock_upgradable()); - f() - } - - /// Temporarily yields the `RwLock` to a waiting thread if there is one. - /// - /// This method is functionally equivalent to calling `bump` on [`RwLockUpgradableReadGuard`]. - #[inline] - pub fn bump(s: &mut Self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.bump_upgradable(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockUpgradableReadGuard { - /// Atomically downgrades an upgradable read lock lock into a shared read lock - /// without allowing any writers to take exclusive access of the lock in the - /// meantime. - /// - /// Note that if there are any writers currently waiting to take the lock - /// then other readers may not be able to acquire the lock even if it was - /// downgraded. - pub fn downgrade(s: Self) -> ArcRwLockReadGuard { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - s.rwlock.raw.downgrade_upgradable(); - } - - // SAFETY: use ManuallyDrop and ptr::read to ensure the refcount is not changed - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - ArcRwLockReadGuard { - rwlock, - marker: PhantomData, - } - } - - /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock, - /// blocking the current thread until it can be acquired. - /// - /// Then, calls the provided closure with an exclusive reference to the lock's data. - /// - /// Finally, atomically downgrades the lock back to an upgradable read lock. - /// The closure's return value is returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `upgrade` which takes the guard by value. - pub fn with_upgraded Ret>(&mut self, f: F) -> Ret { - unsafe { - self.rwlock.raw.upgrade(); - } - - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - f(unsafe { &mut *self.rwlock.data.get() }) - } - - /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock. - /// - /// If the access could not be granted at this time, then `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade` which takes the guard by value. - pub fn try_with_upgraded Ret>(&mut self, f: F) -> Option { - if unsafe { self.rwlock.raw.try_upgrade() } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } -} - -#[cfg(feature = "arc_lock")] -impl ArcRwLockUpgradableReadGuard { - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - pub fn try_upgrade_for( - s: Self, - timeout: R::Duration, - ) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// the current guard is returned. - #[inline] - pub fn try_upgrade_until( - s: Self, - timeout: R::Instant, - ) -> Result, Self> { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } { - // SAFETY: same as above - let s = ManuallyDrop::new(s); - let rwlock = unsafe { ptr::read(&s.rwlock) }; - - Ok(ArcRwLockWriteGuard { - rwlock, - marker: PhantomData, - }) - } else { - Err(s) - } - } -} - -#[cfg(feature = "arc_lock")] -impl - ArcRwLockUpgradableReadGuard -{ - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade_for` which takes the guard by value. - pub fn try_with_upgraded_for Ret>( - &mut self, - timeout: R::Duration, - f: F, - ) -> Option { - if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } - - /// Tries to atomically upgrade an upgradable read lock into an exclusive - /// write lock, until a timeout is reached. - /// - /// If the access could not be granted before the timeout expires, then - /// `None` is returned. - /// - /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, - /// and finally downgrades the lock back to an upgradable read lock. - /// The closure's return value is wrapped in `Some` and returned. - /// - /// This function only requires a mutable reference to the guard, unlike - /// `try_upgrade_until` which takes the guard by value. - pub fn try_with_upgraded_until Ret>( - &mut self, - timeout: R::Instant, - f: F, - ) -> Option { - if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } { - // Safety: We just upgraded the lock, so we have mutable access to the data. - // This will restore the state the lock was in at the start of the function. - defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() }); - - // Safety: We upgraded the lock, so we have mutable access to the data. - // When this function returns, whether by drop or panic, - // the drop guard will downgrade it back to an upgradeable lock. - Some(f(unsafe { &mut *self.rwlock.data.get() })) - } else { - None - } - } -} - -#[cfg(feature = "arc_lock")] -impl Deref for ArcRwLockUpgradableReadGuard { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.rwlock.data.get() } - } -} - -#[cfg(feature = "arc_lock")] -impl Drop for ArcRwLockUpgradableReadGuard { - #[inline] - fn drop(&mut self) { - // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. - unsafe { - self.rwlock.raw.unlock_upgradable(); - } - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Debug - for ArcRwLockUpgradableReadGuard -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[cfg(feature = "arc_lock")] -impl fmt::Display - for ArcRwLockUpgradableReadGuard -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -/// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a -/// subfield of the protected data. -/// -/// The main difference between `MappedRwLockReadGuard` and `RwLockReadGuard` is that the -/// former doesn't support temporarily unlocking and re-locking, since that -/// could introduce soundness issues if the locked object is modified by another -/// thread. -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { - raw: &'a R, - data: *const T, - marker: PhantomData<&'a T>, -} - -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockReadGuard<'a, R, T> {} -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Send for MappedRwLockReadGuard<'a, R, T> where - R::GuardMarker: Send -{ -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { - /// Make a new `MappedRwLockReadGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `MappedRwLockReadGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U> - where - F: FnOnce(&T) -> &U, - { - let raw = s.raw; - let data = f(unsafe { &*s.data }); - mem::forget(s); - MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedRwLockReadGuard` for a component of the - /// locked data. The original guard is return if the closure returns `None`. - /// - /// This operation cannot fail as the `MappedRwLockReadGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `MappedRwLockReadGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&T) -> Option<&U>, - { - let raw = s.raw; - let data = match f(unsafe { &*s.data }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedRwLockReadGuard { - raw, - data, - marker: PhantomData, - }) - } -} - -impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// By default, `RwLock` is unfair and allow the current thread to re-lock - /// the `RwLock` before another has the chance to acquire the lock, even if - /// that thread has been blocked on the `RwLock` for a long time. This is - /// the default because it allows much higher throughput as it avoids - /// forcing a context switch on every `RwLock` unlock. This can result in one - /// thread acquiring a `RwLock` many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `MappedRwLockReadGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MappedRwLockReadGuard always holds a shared lock. - unsafe { - s.raw.unlock_shared_fair(); - } - mem::forget(s); - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockReadGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.data } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: A MappedRwLockReadGuard always holds a shared lock. - unsafe { - self.raw.unlock_shared(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug - for MappedRwLockReadGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for MappedRwLockReadGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress - for MappedRwLockReadGuard<'a, R, T> -{ -} - -/// An RAII write lock guard returned by `RwLockWriteGuard::map`, which can point to a -/// subfield of the protected data. -/// -/// The main difference between `MappedRwLockWriteGuard` and `RwLockWriteGuard` is that the -/// former doesn't support temporarily unlocking and re-locking, since that -/// could introduce soundness issues if the locked object is modified by another -/// thread. -#[clippy::has_significant_drop] -#[must_use = "if unused the RwLock will immediately unlock"] -pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { - raw: &'a R, - data: *mut T, - marker: PhantomData<&'a mut T>, -} - -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync - for MappedRwLockWriteGuard<'a, R, T> -{ -} -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Send + 'a> Send for MappedRwLockWriteGuard<'a, R, T> where - R::GuardMarker: Send -{ -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { - /// Make a new `MappedRwLockWriteGuard` for a component of the locked data. - /// - /// This operation cannot fail as the `MappedRwLockWriteGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn map(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U> - where - F: FnOnce(&mut T) -> &mut U, - { - let raw = s.raw; - let data = f(unsafe { &mut *s.data }); - mem::forget(s); - MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - } - } - - /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the - /// locked data. The original guard is return if the closure returns `None`. - /// - /// This operation cannot fail as the `MappedRwLockWriteGuard` passed - /// in already locked the data. - /// - /// This is an associated function that needs to be - /// used as `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with methods of - /// the same name on the contents of the locked data. - #[inline] - pub fn try_map(s: Self, f: F) -> Result, Self> - where - F: FnOnce(&mut T) -> Option<&mut U>, - { - let raw = s.raw; - let data = match f(unsafe { &mut *s.data }) { - Some(data) => data, - None => return Err(s), - }; - mem::forget(s); - Ok(MappedRwLockWriteGuard { - raw, - data, - marker: PhantomData, - }) - } -} - -impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> { - /// Unlocks the `RwLock` using a fair unlock protocol. - /// - /// By default, `RwLock` is unfair and allow the current thread to re-lock - /// the `RwLock` before another has the chance to acquire the lock, even if - /// that thread has been blocked on the `RwLock` for a long time. This is - /// the default because it allows much higher throughput as it avoids - /// forcing a context switch on every `RwLock` unlock. This can result in one - /// thread acquiring a `RwLock` many more times than other threads. - /// - /// However in some cases it can be beneficial to ensure fairness by forcing - /// the lock to pass on to a waiting thread if there is one. This is done by - /// using this method instead of dropping the `MappedRwLockWriteGuard` normally. - #[inline] - pub fn unlock_fair(s: Self) { - // Safety: A MappedRwLockWriteGuard always holds an exclusive lock. - unsafe { - s.raw.unlock_exclusive_fair(); - } - mem::forget(s); - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockWriteGuard<'a, R, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - unsafe { &*self.data } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for MappedRwLockWriteGuard<'a, R, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.data } - } -} - -impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, R, T> { - #[inline] - fn drop(&mut self) { - // Safety: A MappedRwLockWriteGuard always holds an exclusive lock. - unsafe { - self.raw.unlock_exclusive(); - } - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug - for MappedRwLockWriteGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display - for MappedRwLockWriteGuard<'a, R, T> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -#[cfg(feature = "owning_ref")] -unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress - for MappedRwLockWriteGuard<'a, R, T> -{ -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/log/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/log/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"5291aac813a5af29d49cc9e624abcb6f16d49b40cb8b19c171ae05b0f0fb2c51","Cargo.toml":"dff834f0cd9f79ee49305bedabdae4d4c1217f8aee8fb39690ad4bdc2401368c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"4fcd79a808300bfce99e68749f33f305a446c7bc48789810530a4b3f57a449c6","benches/value.rs":"b613ff353d3cf0ef8cb98e4ca461ea929b8ba553fe299f2eb2942d77a5b1b6a0","src/__private_api.rs":"fe9e5959840af6767e17e6d0e27985156839eef2ee3263f74990e571c640df62","src/kv/error.rs":"6dae12424164c33b93915f5e70bd6d99d616c969c8bfb543806721dd9b423981","src/kv/key.rs":"9439e91c3ab3f9574a6a11a0347c7b63fdf1652384a6b28411136e4373de2970","src/kv/mod.rs":"3521a5bcfd7f92dcfac6c3c948020d686fee696596c566333a27edbbcc8a4ea8","src/kv/source.rs":"911e480fe2719230c13b083717737d42c5d22882844cf0172798f50601442015","src/kv/value.rs":"0aade52b8e3523a17d6114f8b664793862032a94ea1ee2a4f12a20dd729b92d4","src/lib.rs":"6adbad6a28da344fef36b63e81786a94e5cfe7426f7c5eb73df0c467eb078222","src/macros.rs":"9a748a1fb6e097219561e809d30b51d1354478556f507c1d7db3d239cd4a008b","src/serde.rs":"35f520f62fdba0216ccee33e5b66ad8f81dee3af5b65b824f1816180c9350df5","triagebot.toml":"a135e10c777cd13459559bdf74fb704c1379af7c9b0f70bc49fa6f5a837daa81"},"package":"90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5f156aa0916f6d1562839e19152896bd451f7025136efa424cd4c3047884d76a",".github/workflows/main.yml":"1c765dde80804e646db2fdf47a2628898ff4a2527f61958ba5876c331fed4f8e","CHANGELOG.md":"5291aac813a5af29d49cc9e624abcb6f16d49b40cb8b19c171ae05b0f0fb2c51","Cargo.toml":"dff834f0cd9f79ee49305bedabdae4d4c1217f8aee8fb39690ad4bdc2401368c","Cargo.toml.orig":"ebb7c1f61c66d4076a1d63ca3b32906a1bab61764b890cd71b4463de1d5499b6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"4fcd79a808300bfce99e68749f33f305a446c7bc48789810530a4b3f57a449c6","benches/value.rs":"b613ff353d3cf0ef8cb98e4ca461ea929b8ba553fe299f2eb2942d77a5b1b6a0","src/__private_api.rs":"fe9e5959840af6767e17e6d0e27985156839eef2ee3263f74990e571c640df62","src/kv/error.rs":"6dae12424164c33b93915f5e70bd6d99d616c969c8bfb543806721dd9b423981","src/kv/key.rs":"9439e91c3ab3f9574a6a11a0347c7b63fdf1652384a6b28411136e4373de2970","src/kv/mod.rs":"3521a5bcfd7f92dcfac6c3c948020d686fee696596c566333a27edbbcc8a4ea8","src/kv/source.rs":"911e480fe2719230c13b083717737d42c5d22882844cf0172798f50601442015","src/kv/value.rs":"0aade52b8e3523a17d6114f8b664793862032a94ea1ee2a4f12a20dd729b92d4","src/lib.rs":"6adbad6a28da344fef36b63e81786a94e5cfe7426f7c5eb73df0c467eb078222","src/macros.rs":"9a748a1fb6e097219561e809d30b51d1354478556f507c1d7db3d239cd4a008b","src/serde.rs":"35f520f62fdba0216ccee33e5b66ad8f81dee3af5b65b824f1816180c9350df5","triagebot.toml":"a135e10c777cd13459559bdf74fb704c1379af7c9b0f70bc49fa6f5a837daa81"},"package":"90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/log/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/log/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/log/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "3ccdc286fef3076747fe18a2a93658ea4d4ae012" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/log/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/log/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/log/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/log/.github/workflows/main.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,153 @@ +name: CI +on: [push, pull_request] + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: [stable, beta, nightly, macos, win32, win64, mingw] + include: + - build: stable + os: ubuntu-latest + rust: stable + - build: beta + os: ubuntu-latest + rust: beta + - build: nightly + os: ubuntu-latest + rust: nightly + - build: macos + os: macos-latest + rust: stable + - build: win32 + os: windows-latest + rust: stable-i686-pc-windows-msvc + - build: win64 + os: windows-latest + rust: stable-x86_64-pc-windows-msvc + - build: mingw + os: windows-latest + rust: stable-x86_64-pc-windows-gnu + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update ${{ matrix.rust }} --no-self-update + rustup default ${{ matrix.rust }} + - run: cargo test --verbose + - run: cargo test --verbose --no-default-features + - run: cargo test --verbose --all-features + - run: cargo test --verbose --features serde + - run: cargo test --verbose --features std + - run: cargo test --verbose --features kv + - run: cargo test --verbose --features kv_sval + - run: cargo test --verbose --features kv_serde + - run: cargo test --verbose --features "kv kv_std kv_sval kv_serde" + - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml + - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release + + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add rustfmt + # log repo does not use Cargo workspaces, so `cargo fmt` will not check all the code + # perhaps this should be changed in the future + - run: cargo fmt -- --check + - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check + - run: cargo fmt --manifest-path tests/Cargo.toml -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add clippy + - run: cargo clippy --verbose + - run: cargo clippy --verbose --manifest-path test_max_level_features/Cargo.toml + - run: cargo clippy --verbose --manifest-path tests/Cargo.toml + + doc: + name: Check Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add rust-docs + - name: Run rustdoc + run: RUSTDOCFLAGS="-D warnings" cargo doc --verbose --all-features + + features: + name: Feature check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: cargo build --verbose -Z avoid-dev-deps --features kv + - run: cargo build --verbose -Z avoid-dev-deps --features "kv std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_serde" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval kv_serde" + + minimalv: + name: Minimal versions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: cargo build --verbose -Z minimal-versions --features kv + - run: cargo build --verbose -Z minimal-versions --features "kv std" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_serde" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_std" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval kv_serde" + + msrv: + name: MSRV + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update 1.60.0 --no-self-update + rustup default 1.60.0 + - run: | + cargo test --verbose --manifest-path tests/Cargo.toml + cargo test --verbose --manifest-path tests/Cargo.toml --features kv + + embedded: + name: Embedded + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + - run: rustup target add thumbv6m-none-eabi riscv32imc-unknown-none-elf + - run: cargo build --verbose --target=thumbv6m-none-eabi + - run: cargo build --verbose --target=riscv32imc-unknown-none-elf diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/log/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/log/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/log/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/log/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +[package] + +name = "log" +version = "0.4.21" # remember to update html_root_url +authors = ["The Rust Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-lang/log" +documentation = "https://docs.rs/log" +description = """ +A lightweight logging facade for Rust +""" +categories = ["development-tools::debugging"] +keywords = ["logging"] +exclude = ["rfcs/**/*"] +rust-version = "1.60.0" +edition = "2021" + +[package.metadata.docs.rs] +features = ["std", "serde", "kv_std", "kv_sval", "kv_serde"] + +[[test]] +name = "filters" +path = "tests/filters.rs" +harness = false + +[[test]] +name = "macros" +path = "tests/macros.rs" +harness = true + +[features] +max_level_off = [] +max_level_error = [] +max_level_warn = [] +max_level_info = [] +max_level_debug = [] +max_level_trace = [] + +release_max_level_off = [] +release_max_level_error = [] +release_max_level_warn = [] +release_max_level_info = [] +release_max_level_debug = [] +release_max_level_trace = [] + +std = [] + +kv = [] +kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] +kv_std = ["std", "kv", "value-bag/error"] +kv_serde = ["kv_std", "value-bag/serde", "serde"] + +# Deprecated: use `kv_*` instead +# These `*_unstable` features will be removed in a future release +kv_unstable = ["kv", "value-bag"] +kv_unstable_sval = ["kv_sval", "kv_unstable"] +kv_unstable_std = ["kv_std", "kv_unstable"] +kv_unstable_serde = ["kv_serde", "kv_unstable_std"] + +[dependencies] +serde = { version = "1.0", optional = true, default-features = false } +sval = { version = "2.1", optional = true, default-features = false } +sval_ref = { version = "2.1", optional = true, default-features = false } +value-bag = { version = "1.7", optional = true, default-features = false, features = ["inline-i128"] } + +[dev-dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +serde_test = "1.0" +sval = { version = "2.1" } +sval_derive = { version = "2.1" } +value-bag = { version = "1.7", features = ["test"] } + +# NOTE: log doesn't actually depent on this crate. However our dependencies, +# serde and sval, dependent on version 1.0 of the crate, which has problem fixed +# in 1.0.60, specifically in the following commit +# https://github.com/dtolnay/proc-macro2/commit/e31d61910049e097afdd3d27c37786309082bdcb. +# By defining the crate as direct dependency we can increase it's minimal +# version making the minimal (crate) version CI happy. +proc-macro2 = { version = "1.0.63", default-features = false } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"25b5d96a5af67c8bfcf23d939f991c61e062d8a2a104aec4dddac8463798c287","Cargo.toml":"42b262e95777c3bcc3331ad39f229be0a0eeb72c862ab486a74fd1cd08a05c02","Cargo.toml.orig":"1ab5fb7fa9b930f5fcfdfbc47d74bb20fd049bcdccfa23278c34718f06a1c63c","LICENSE":"af8a1cdcbe552c0378784bdb3e2d427bdfd6fca5d3af58df875c5cafa7c5a58b","README.md":"f1491765595d8a814fbf68dcb66f2090cd8b9e58274a3e5a0ef01845a2a826f4","src/lib.rs":"fb3578b3d02bbe1fec7e5489ea05c23933351beb2596dd268031a8cb131b9294"},"package":"0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "58b83d7363be260f9b46745b4b3f5eac79d98d3f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "loop9" +version = "0.1.5" +authors = ["Kornel "] +description = "Tiny helper function to visit every pixel in the image together with its neighboring pixels. Duplicates pixels on the edges." +homepage = "https://lib.rs/crates/loop9" +readme = "README.md" +keywords = [ + "convolve", + "blur", + "iterate", + "convolution", +] +categories = ["graphics"] +license = "MIT" +repository = "https://gitlab.com/kornelski/loop9.git" + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.imgref] +version = "1.7.0" + +[badges.maintenance] +status = "passively-maintained" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[package] +authors = ["Kornel "] +description = "Tiny helper function to visit every pixel in the image together with its neighboring pixels. Duplicates pixels on the edges." +license = "MIT" +name = "loop9" +readme = "README.md" +version = "0.1.5" +edition = "2021" +homepage = "https://lib.rs/crates/loop9" +categories = ["graphics"] +keywords = ["convolve", "blur", "iterate", "convolution"] +repository = "https://gitlab.com/kornelski/loop9.git" + +[dependencies] +imgref = "1.7.0" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] + +[badges] +maintenance = { status = "passively-maintained" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/loop9/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +© Kornel Lesiński + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/README.md clamav-1.4.6+dfsg/.cargo/vendor/loop9/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +# 9 neighboring pixels iterator + +Tiny helper function to visit every pixel in the image together with its neighboring pixels. Duplicates pixels on the edges. + +Ideal for implementing small image convolutions like blur, sharpening or edge detection. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/loop9/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/loop9/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/loop9/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/loop9/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,187 @@ +use core::ops::Deref; +use imgref::ImgRef; + +/// Previous, current, and next pixel or row +#[derive(Copy,Clone,Debug,Eq,PartialEq)] +#[repr(C)] +pub struct Triple { + pub prev: T, + pub curr: T, + pub next: T, +} + +impl Triple { + #[must_use] + #[inline(always)] + pub fn new(prev: T, curr: T, next: T) -> Self { + Triple { prev, curr, next } + } +} + +impl AsRef<[T]> for Triple { + #[inline(always)] + fn as_ref(&self) -> &[T] { + unsafe { + std::slice::from_raw_parts(self as *const Triple as *const T, 3) + } + } +} + +impl Deref for Triple { + type Target = [T]; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + self.as_ref() + } +} + +impl Triple { + /// Add the next item, and shift others (prev is gone, prev = current) + /// If the item is `None`, it'll copy the last one instead. + #[must_use] + #[inline(always)] + pub fn advance(self, next: Option) -> Self { + Triple { + prev: self.curr, + curr: self.next, + next: next.unwrap_or(self.next), + } + } +} + +/// Loop over 9 neighboring pixels in the image described by [`ImgRef`] (`Img.as_ref()`) +/// +/// The callback is: (`x`, `y`, `previous_row`, `current_row`, `next_row`) +/// +/// This function will never panic, if your callback doesn't panic. +#[inline(always)] +pub fn loop9_img(img: ImgRef<'_, Pixel>, cb: Callback) + where Pixel: Copy, Callback: FnMut(usize, usize, Triple,Triple,Triple) +{ + loop9(img, 0, 0, img.width(), img.height(), cb); +} + +/// Loop over 9 neighboring pixels in the left/top/width/height fragment of the image described by [`ImgRef`] (`Img.as_ref()`) +/// +/// The callback is: (`x`, `y`, `previous_row`, `current_row`, `next_row`) +/// +/// This function will never panic, if your callback doesn't panic. +pub fn loop9(img: ImgRef<'_, Pixel>, left: usize, top: usize, width: usize, height: usize, mut cb: Callback) + where Pixel: Copy, Callback: FnMut(usize, usize, Triple,Triple,Triple) +{ + let max_width = img.width(); + let max_height = img.height(); + let stride = img.stride(); + if stride == 0 || max_height == 0 || max_width == 0 { + return; + } + let data = img.buf(); + let t = top.min(max_height-1) * stride; + let start_row = if let Some(r) = data.get(t..t+max_width) { r } else { return }; + if start_row.is_empty() { return; } + let mut row = Triple { + prev: start_row, + curr: start_row, + next: start_row, + }; + for y in top..top+height { + row = row.advance({ + let t = (y+1) * stride; + data.get(t..t+max_width) + }); + if row.prev.is_empty() || row.curr.is_empty() || row.next.is_empty() { + return; + } + let mut tp; + let mut tn = row.prev[left.min(row.prev.len()-1)]; + let mut tc = row.prev[left.saturating_sub(1).min(row.prev.len()-1)]; + let mut mp; + let mut mn = row.curr[left.min(row.curr.len()-1)]; + let mut mc = row.curr[left.saturating_sub(1).min(row.curr.len()-1)]; + let mut bp; + let mut bn = row.next[left.min(row.next.len()-1)]; + let mut bc = row.next[left.saturating_sub(1).min(row.next.len()-1)]; + for x in left..left+width { + tp = tc; + tc = tn; + tn = row.prev.get(x+1).copied().unwrap_or(tc); + mp = mc; + mc = mn; + mn = row.curr.get(x+1).copied().unwrap_or(mc); + bp = bc; + bc = bn; + bn = row.next.get(x+1).copied().unwrap_or(bc); + cb(x-left, y-top, Triple::new(tp, tc, tn), Triple::new(mp, mc, mn), Triple::new(bp, bc, bn)); + } + } +} + + +#[test] +fn test_oob() { + use imgref::Img; + let img = Img::new(vec![0; 5*4], 5, 4); + for w in 1..8 { + for h in 1..8 { + for x in 0..8 { + for y in 0..8 { + let mut n = 0; + loop9(img.as_ref(), x,y,w,h, |_x,_y,_top,_mid,_bot| { n += 1 }); + assert_eq!(n, w*h, "{x},{y},{w},{h}"); + } + } + } + } +} + +#[test] +fn test_loop9() { + use imgref::Img; + + let src = vec![ + 1, 2, 3, 4, 0, + 5, 6, 7, 8, 0, + 9,10,11,12, 0, + 13,14,15,16, 0, + ]; + let img = Img::new_stride(src.clone(), 4, 4, 5); + assert_eq!(4, img.width()); + assert_eq!(5, img.stride()); + assert_eq!(4, img.height()); + + let check = |l,t,w,h,exp: &[_]|{ + let mut res = Vec::new(); + loop9(img.as_ref(), l,t,w,h, |_x,_y,_top,mid,_bot| res.push(mid.curr)); + assert_eq!(exp, res); + }; + + check(0,0,4,4, &[ + 1, 2, 3, 4, + 5, 6, 7, 8, + 9,10,11,12, + 13,14,15,16, + ]); + + check(0,0,4,1, &[1, 2, 3, 4]); + + check(0,3,4,1, &[13,14,15,16]); + + check(0,0,3,3, &[ + 1, 2, 3, + 5, 6, 7, + 9,10,11, + ]); + + check(0,0,1,1, &[1]); + check(1,0,1,1, &[2]); + check(2,0,1,1, &[3]); + check(3,0,1,1, &[4]); + + check(1,0,3,4,&[ + 2, 3, 4, + 6, 7, 8, + 10,11,12, + 14,15,16, + ]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"89b02d2661f8b5c1248c761a9409fda8e08e6c83a8278876aab10ab8087b1b9c","CHANGELOG.md":"a5740a460ba8a4c3de24dbe7a98b26381fe480c665fda762e4b999a008ea1d18","Cargo.toml":"d1dde2cd83fa0ef3655cd168e01a267fe2271082efff7f70667f7adcec304cc0","Cargo.toml.orig":"78c27f4c9e7fc819124528e923d1820f4e6a4ce8a54586b556a69e8227f9a1b8","LICENSE":"3b2dbf86845042813be71eecfea49de557bb4ea908b9b15f5b285259714fa183","rustfmt.toml":"6536373c45afd6d429ba32aa35b865f2286fe7d2181341c8ef6d7d8d864b73f6","src/lib.rs":"06a316ff5d8f05549ecb40f08ff97ba9e569c937bc25c82ddfefcb121a145e76"},"package":"8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "73128cfb26624d9ceef7d0796e868904841f611d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +## Version 0.1.1 + +- Use `Infallible` instead of `Result` +- Always inline passthrough methods to guarantee zero overhead diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "maybe-rayon" +version = "0.1.1" +description = "Either acts as rayon or creates a single-threaded facade" +homepage = "https://github.com/shssoichiro/maybe-rayon" +license = "MIT" +repository = "https://github.com/shssoichiro/maybe-rayon" + +[dependencies.cfg-if] +version = "1.0" + +[dependencies.rayon] +version = "1.0" +optional = true + +[features] +default = ["threads"] +threads = ["rayon"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +[package] +name = "maybe-rayon" +version = "0.1.1" +edition = "2021" +license = "MIT" +description = "Either acts as rayon or creates a single-threaded facade" +homepage = "https://github.com/shssoichiro/maybe-rayon" +repository = "https://github.com/shssoichiro/maybe-rayon" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cfg-if = "1.0" +rayon = { optional = true, version = "1.0" } + +[features] +default = ["threads"] +threads = ["rayon"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Joshua Holmer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +unstable_features = true +imports_layout = "HorizontalVertical" +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +format_strings = true \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/maybe-rayon/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/maybe-rayon/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +#![warn(clippy::all)] + +cfg_if::cfg_if! { + if #[cfg(any(not(feature = "threads"), all(target_arch="wasm32", not(target_feature = "atomics"))))] { + #[derive(Default)] + pub struct ThreadPoolBuilder (); + impl ThreadPoolBuilder { + #[inline(always)] + pub fn new() -> ThreadPoolBuilder { + ThreadPoolBuilder() + } + + #[inline(always)] + pub fn build(self) -> Result { + Ok(ThreadPool()) + } + + #[inline(always)] + pub fn num_threads(self, _num_threads: usize) -> ThreadPoolBuilder { + ThreadPoolBuilder() + } + } + #[derive(Debug)] + pub struct ThreadPool (); + impl ThreadPool { + #[inline(always)] + pub fn install(&self, op: OP) -> R where + OP: FnOnce() -> R + Send, + R: Send, { + op() + } + } + + pub mod iter { + pub trait IntoParallelIterator { + type Iter: Iterator; + type Item: Send; + + fn into_par_iter(self) -> Self::Iter; + } + + impl IntoParallelIterator for I where + I::Item : Send { + type Item = I::Item; + type Iter = I::IntoIter; + + #[inline(always)] + fn into_par_iter(self) -> I::IntoIter { + self.into_iter() + } + } + + pub trait IntoParallelRefMutIterator<'data> { + type Iter: IntoParallelIterator; + type Item: Send + 'data; + + fn par_iter_mut(&'data mut self) -> Self::Iter; + } + + impl<'data, I: 'data + ?Sized> IntoParallelRefMutIterator<'data> for I + where + &'data mut I: IntoParallelIterator, + { + type Iter = <&'data mut I as IntoParallelIterator>::Iter; + type Item = <&'data mut I as IntoParallelIterator>::Item; + + #[inline(always)] + fn par_iter_mut(&'data mut self) -> Self::Iter { + self.into_par_iter() + } + } + + pub trait ParallelIterator: Iterator { + #[inline(always)] + fn flat_map_iter(self, f: F) -> std::iter::FlatMap + where + Self: Sized, + U: IntoIterator, + F: FnMut(::Item) -> U, + { + self.flat_map(f) + } + } + + impl ParallelIterator for I {} + } + pub mod slice { + pub trait ParallelSlice { + fn par_chunks_exact( + &self, chunk_size: usize, + ) -> std::slice::ChunksExact<'_, T>; + } + + impl ParallelSlice for [T] { + #[inline(always)] + fn par_chunks_exact( + &self, chunk_size: usize, + ) -> std::slice::ChunksExact<'_, T> { + self.chunks_exact(chunk_size) + } + } + } + + pub mod prelude { + pub use super::iter::*; + pub use super::slice::*; + } + + #[inline(always)] + pub fn join(oper_a: A, oper_b: B) -> (RA, RB) + where + A: FnOnce() -> RA + Send, + B: FnOnce() -> RB + Send, + RA: Send, + RB: Send { + (oper_a(), oper_b()) + } + + use std::marker::PhantomData; + + pub struct Scope<'scope>{ + #[allow(clippy::type_complexity)] + marker: PhantomData) + Send + Sync + 'scope>>, + } + + impl<'scope> Scope<'scope> { + #[inline(always)] + pub fn spawn(&self, body: BODY) + where BODY: FnOnce(&Scope<'scope>) + Send + 'scope + { + body(self) + } + } + + #[inline(always)] + pub fn scope<'scope, OP, R>(op: OP) -> R + where OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send, R: Send, + { + op(&Scope { marker: PhantomData }) + } + } else { + pub use rayon::*; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/memchr/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/memchr/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"f1f0f38e21c6ee1e15878248f8651c09ba74451b3fc73ac619a8996373e4c4ad","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"92a74aaffe011bdaa06fbc34a01686a6eba58ca1322e976759417a547fddf734","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/arch/aarch64/memchr.rs":"5bb70f915084e629d940dbc322f5b9096b2e658cf63fea8a2f6e7550412e73a0","src/arch/aarch64/mod.rs":"44cd1a614bd66f1e66fc86c541d3c3b8d3a14a644c13e8bf816df3f555eac2d4","src/arch/aarch64/neon/memchr.rs":"e8c00b8fb2c7e2711832ae3cedefe59f32ebedd7dfa4d0ec6de2a566c979daea","src/arch/aarch64/neon/mod.rs":"eab6d56c2b2354db4ee395f40282cd49f97e2ab853547be5de6e65fbe1b2f634","src/arch/aarch64/neon/packedpair.rs":"fbdfdbfaf7b76b234db261fbe55a55c4479d32cdc65a654d60417c2d1c237849","src/arch/all/memchr.rs":"f6c51e50309f80e749887572297aa5efc19a3c7e5434b4404a101b3e6b152be1","src/arch/all/mod.rs":"05f3fc2b069682eb1545fc6366d167bb620a454365dac8b8dd6cde6cd64de18a","src/arch/all/packedpair/default_rank.rs":"abffd1b5b8b7a3be95c03dd1105b905c246a379854dc56f1e846ea7c4408f2c7","src/arch/all/packedpair/mod.rs":"292b66042c5b5c78bba33db6526aeae6904db803d601fcdd29032b87b3eb3754","src/arch/all/rabinkarp.rs":"236f69c04b90c14c253ae6c8d9b78150b4a56df75bb50af6d63b15145668b7cc","src/arch/all/shiftor.rs":"0d79117f52a1e4795843603a3bb0b45397df4ad5e4184bbc923658dab9dc3b5f","src/arch/all/twoway.rs":"47c97a265bfbafde90a618946643d3e97dfd9a85f01aa4ac758cd4c1573a450d","src/arch/generic/memchr.rs":"88290761bab740878401e914d71866da6501cdcef53d1249ec6fda4c7f9c12ae","src/arch/generic/mod.rs":"1dd75f61e0ea2563b8205a08aaa7b55500130aa331d18b9e9f995724b66c7a39","src/arch/generic/packedpair.rs":"a4a6efb29877ced9cf4c4e5ae9f36a79f019a16b831f2b9424899a1513d458ad","src/arch/mod.rs":"ca3960b7e2ed28d1b3c121710a870430531aad792f64d4dcb4ca4709d6cbda30","src/arch/wasm32/memchr.rs":"d88ac79f891d8530f505f5035062d3da274a05d66c611480c75430d52709d052","src/arch/wasm32/mod.rs":"a20377aa8fe07d68594879101dc73061e4f51d9c8d812b593b1f376e3c8add79","src/arch/wasm32/simd128/memchr.rs":"bac2c4c43fe710c83a6f2b1118fede043be89dd821d4b532907f129f09fdb5cf","src/arch/wasm32/simd128/mod.rs":"c157b373faedbfd65323be432e25bc411d97aa1b7bc58e76048614c7b2bf3bf6","src/arch/wasm32/simd128/packedpair.rs":"288ba6e5eee6a7a8e5e45c64cff1aa5d72d996c2a6bc228be372c75789f08e45","src/arch/x86_64/avx2/memchr.rs":"576ec0c30f49874f7fd9f6caeb490d56132c0fbbaa4d877b1aa532cafce19323","src/arch/x86_64/avx2/mod.rs":"0033d1b712d0b10f0f273ef9aa8caa53e05e49f4c56a64f39af0b9df97eec584","src/arch/x86_64/avx2/packedpair.rs":"87b69cb4301815906127db4f6370f572c7c5d5dad35c0946c00ad888dbcaec8c","src/arch/x86_64/memchr.rs":"99a1dbe4156d498e6f910d06d3d3b31e7f6d06dff7d13a4c51b33a02b7e2fba9","src/arch/x86_64/mod.rs":"61b2aa876942fd3e78714c2ae21e356c8634545c06995020f443fa50218df027","src/arch/x86_64/sse2/memchr.rs":"68fc3b8f9eddf82192979c3aa11e5141f085cbb993c49c340558719a904679dc","src/arch/x86_64/sse2/mod.rs":"38b70ae52a64ec974dbb91d04d6ca8013d9e06d1fe4af852206bbc2faf1c59aa","src/arch/x86_64/sse2/packedpair.rs":"241ea981d8eea6024769f1c9375f726a9bb9700160c5857781d4befd9f5ef55d","src/cow.rs":"34eddd02cb82cc2d5a2c640891d64efe332dabcc1eea5115764200d8f46b66f7","src/ext.rs":"210f89d1e32211bc64414cbd56e97b4f56ce8a8832d321d77a9fe519634e27ea","src/lib.rs":"614f778a41e88a29ea0ceb8e92c839dbb6b5a61c967f8bfd962975e18f932c71","src/macros.rs":"3e4b39252bfa471fad384160a43f113ebfec7bec46a85d16f006622881dd2081","src/memchr.rs":"6ae779ec5d00f443075316e0105edf30b489a38e2e96325bec14ccecd014145b","src/memmem/mod.rs":"1b0a9d6a681fd0887c677c4fc8d4c8f9719ddde250bdd5ea545365c1a7fb9094","src/memmem/searcher.rs":"7763472d43c66df596ca0697c07db0b4666d38a6a14f64f9f298aaf756c4a715","src/tests/memchr/mod.rs":"269f8e4b4f7f5ea458f27a3c174eb1020ffb2484eeba9464170beb51747df69b","src/tests/memchr/naive.rs":"6a0bee033e5edfb5b1d5769a5fa1c78388f7e9ff7bb91cb67f0ad029289e00e7","src/tests/memchr/prop.rs":"7bf7435087fbf08c5014c216b76575349735590d6b1d0e448921a1dc17bc0ea7","src/tests/mod.rs":"7cec8f809e279310a465c6a7725087970f219a676cc76c83de30c695bb490740","src/tests/packedpair.rs":"b02ec4fbb61a8653cb5f2268c31bc9168b8043347f2abdcc74081acf83b98e15","src/tests/substring/mod.rs":"c7660d10749363ac4687e7da2b5fda60768230425df8ba416c0c28b8d56a5c74","src/tests/substring/naive.rs":"df6f55d165382b8a53762ba4c324926cac13ebc62cde1805f4ce08740b326483","src/tests/substring/prop.rs":"38c15992609b5681a95d838ae6f2933e00a1219f2c971bfba245f96e0729fcdc","src/vector.rs":"24e8620d52da38b051c446864089cdfaba6fa3afc27e16a716aa36a716f6636f"},"package":"6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a45c206fe2db69a8e44550e3d29f2da60b6085f3a52550a822f241bc6d1e6df9",".ignore":"ae8b19032d4fc418b99ccae9e7cc3996b1386665d0bd5edc5634a158e7d2f6a2",".vim/coc-settings.json":"cdc5e2b88bddbdbd1b85f21389c4d882720e4c4488ad566c43fccd9124f2e3bf","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"f1f0f38e21c6ee1e15878248f8651c09ba74451b3fc73ac619a8996373e4c4ad","Cargo.toml.orig":"47aa4961f5938e75bfcda560649a368af0f6397e98ff75909032ec3a06ec34df","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"92a74aaffe011bdaa06fbc34a01686a6eba58ca1322e976759417a547fddf734","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/arch/aarch64/memchr.rs":"5bb70f915084e629d940dbc322f5b9096b2e658cf63fea8a2f6e7550412e73a0","src/arch/aarch64/mod.rs":"44cd1a614bd66f1e66fc86c541d3c3b8d3a14a644c13e8bf816df3f555eac2d4","src/arch/aarch64/neon/memchr.rs":"e8c00b8fb2c7e2711832ae3cedefe59f32ebedd7dfa4d0ec6de2a566c979daea","src/arch/aarch64/neon/mod.rs":"eab6d56c2b2354db4ee395f40282cd49f97e2ab853547be5de6e65fbe1b2f634","src/arch/aarch64/neon/packedpair.rs":"fbdfdbfaf7b76b234db261fbe55a55c4479d32cdc65a654d60417c2d1c237849","src/arch/all/memchr.rs":"f6c51e50309f80e749887572297aa5efc19a3c7e5434b4404a101b3e6b152be1","src/arch/all/mod.rs":"05f3fc2b069682eb1545fc6366d167bb620a454365dac8b8dd6cde6cd64de18a","src/arch/all/packedpair/default_rank.rs":"abffd1b5b8b7a3be95c03dd1105b905c246a379854dc56f1e846ea7c4408f2c7","src/arch/all/packedpair/mod.rs":"292b66042c5b5c78bba33db6526aeae6904db803d601fcdd29032b87b3eb3754","src/arch/all/rabinkarp.rs":"236f69c04b90c14c253ae6c8d9b78150b4a56df75bb50af6d63b15145668b7cc","src/arch/all/shiftor.rs":"0d79117f52a1e4795843603a3bb0b45397df4ad5e4184bbc923658dab9dc3b5f","src/arch/all/twoway.rs":"47c97a265bfbafde90a618946643d3e97dfd9a85f01aa4ac758cd4c1573a450d","src/arch/generic/memchr.rs":"88290761bab740878401e914d71866da6501cdcef53d1249ec6fda4c7f9c12ae","src/arch/generic/mod.rs":"1dd75f61e0ea2563b8205a08aaa7b55500130aa331d18b9e9f995724b66c7a39","src/arch/generic/packedpair.rs":"a4a6efb29877ced9cf4c4e5ae9f36a79f019a16b831f2b9424899a1513d458ad","src/arch/mod.rs":"ca3960b7e2ed28d1b3c121710a870430531aad792f64d4dcb4ca4709d6cbda30","src/arch/wasm32/memchr.rs":"d88ac79f891d8530f505f5035062d3da274a05d66c611480c75430d52709d052","src/arch/wasm32/mod.rs":"a20377aa8fe07d68594879101dc73061e4f51d9c8d812b593b1f376e3c8add79","src/arch/wasm32/simd128/memchr.rs":"bac2c4c43fe710c83a6f2b1118fede043be89dd821d4b532907f129f09fdb5cf","src/arch/wasm32/simd128/mod.rs":"c157b373faedbfd65323be432e25bc411d97aa1b7bc58e76048614c7b2bf3bf6","src/arch/wasm32/simd128/packedpair.rs":"288ba6e5eee6a7a8e5e45c64cff1aa5d72d996c2a6bc228be372c75789f08e45","src/arch/x86_64/avx2/memchr.rs":"576ec0c30f49874f7fd9f6caeb490d56132c0fbbaa4d877b1aa532cafce19323","src/arch/x86_64/avx2/mod.rs":"0033d1b712d0b10f0f273ef9aa8caa53e05e49f4c56a64f39af0b9df97eec584","src/arch/x86_64/avx2/packedpair.rs":"87b69cb4301815906127db4f6370f572c7c5d5dad35c0946c00ad888dbcaec8c","src/arch/x86_64/memchr.rs":"99a1dbe4156d498e6f910d06d3d3b31e7f6d06dff7d13a4c51b33a02b7e2fba9","src/arch/x86_64/mod.rs":"61b2aa876942fd3e78714c2ae21e356c8634545c06995020f443fa50218df027","src/arch/x86_64/sse2/memchr.rs":"68fc3b8f9eddf82192979c3aa11e5141f085cbb993c49c340558719a904679dc","src/arch/x86_64/sse2/mod.rs":"38b70ae52a64ec974dbb91d04d6ca8013d9e06d1fe4af852206bbc2faf1c59aa","src/arch/x86_64/sse2/packedpair.rs":"241ea981d8eea6024769f1c9375f726a9bb9700160c5857781d4befd9f5ef55d","src/cow.rs":"34eddd02cb82cc2d5a2c640891d64efe332dabcc1eea5115764200d8f46b66f7","src/ext.rs":"210f89d1e32211bc64414cbd56e97b4f56ce8a8832d321d77a9fe519634e27ea","src/lib.rs":"614f778a41e88a29ea0ceb8e92c839dbb6b5a61c967f8bfd962975e18f932c71","src/macros.rs":"3e4b39252bfa471fad384160a43f113ebfec7bec46a85d16f006622881dd2081","src/memchr.rs":"6ae779ec5d00f443075316e0105edf30b489a38e2e96325bec14ccecd014145b","src/memmem/mod.rs":"1b0a9d6a681fd0887c677c4fc8d4c8f9719ddde250bdd5ea545365c1a7fb9094","src/memmem/searcher.rs":"7763472d43c66df596ca0697c07db0b4666d38a6a14f64f9f298aaf756c4a715","src/tests/memchr/mod.rs":"269f8e4b4f7f5ea458f27a3c174eb1020ffb2484eeba9464170beb51747df69b","src/tests/memchr/naive.rs":"6a0bee033e5edfb5b1d5769a5fa1c78388f7e9ff7bb91cb67f0ad029289e00e7","src/tests/memchr/prop.rs":"7bf7435087fbf08c5014c216b76575349735590d6b1d0e448921a1dc17bc0ea7","src/tests/mod.rs":"7cec8f809e279310a465c6a7725087970f219a676cc76c83de30c695bb490740","src/tests/packedpair.rs":"b02ec4fbb61a8653cb5f2268c31bc9168b8043347f2abdcc74081acf83b98e15","src/tests/substring/mod.rs":"c7660d10749363ac4687e7da2b5fda60768230425df8ba416c0c28b8d56a5c74","src/tests/substring/naive.rs":"df6f55d165382b8a53762ba4c324926cac13ebc62cde1805f4ce08740b326483","src/tests/substring/prop.rs":"38c15992609b5681a95d838ae6f2933e00a1219f2c971bfba245f96e0729fcdc","src/vector.rs":"24e8620d52da38b051c446864089cdfaba6fa3afc27e16a716aa36a716f6636f"},"package":"6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/memchr/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/memchr/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/memchr/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "20ef11fa92d8b393735f10906c436a8ce6e792a4" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/memchr/.ignore clamav-1.4.6+dfsg/.cargo/vendor/memchr/.ignore --- clamav-1.4.3+dfsg/.cargo/vendor/memchr/.ignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/memchr/.ignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +!.github diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/memchr/.vim/coc-settings.json clamav-1.4.6+dfsg/.cargo/vendor/memchr/.vim/coc-settings.json --- clamav-1.4.3+dfsg/.cargo/vendor/memchr/.vim/coc-settings.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/memchr/.vim/coc-settings.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +{ + "rust-analyzer.cargo.allFeatures": false, + "rust-analyzer.linkedProjects": [ + "benchmarks/engines/libc/Cargo.toml", + "benchmarks/engines/rust-bytecount/Cargo.toml", + "benchmarks/engines/rust-jetscii/Cargo.toml", + "benchmarks/engines/rust-memchr/Cargo.toml", + "benchmarks/engines/rust-memchrold/Cargo.toml", + "benchmarks/engines/rust-sliceslice/Cargo.toml", + "benchmarks/engines/rust-std/Cargo.toml", + "benchmarks/engines/stringzilla/Cargo.toml", + "benchmarks/shared/Cargo.toml", + "fuzz/Cargo.toml", + "Cargo.toml" + ] +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/memchr/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/memchr/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/memchr/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/memchr/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +[package] +name = "memchr" +version = "2.7.2" #:version +authors = ["Andrew Gallant ", "bluss"] +description = """ +Provides extremely fast (uses SIMD on x86_64, aarch64 and wasm32) routines for +1, 2 or 3 byte search and single substring search. +""" +documentation = "https://docs.rs/memchr/" +homepage = "https://github.com/BurntSushi/memchr" +repository = "https://github.com/BurntSushi/memchr" +readme = "README.md" +keywords = ["memchr", "memmem", "substring", "find", "search"] +license = "Unlicense OR MIT" +exclude = ["/.github", "/benchmarks", "/fuzz", "/scripts", "/tmp"] +edition = "2021" +rust-version = "1.61" + +[lib] +name = "memchr" +bench = false + +[features] +default = ["std"] + +# The 'std' feature permits the memchr crate to use the standard library. This +# permits this crate to use runtime CPU feature detection to automatically +# accelerate searching via vector instructions. Without the standard library, +# this automatic detection is not possible. +std = ["alloc"] + +# The 'alloc' feature enables some APIs that require allocation, such as +# 'Finder::into_owned'. Note that this feature does not enable runtime CPU +# feature detection. That still requires 'std'. +alloc = [] + +# When enabled (it's disabled by default), the `log` crate will be used to +# emit a spattering of log messages. For the most part, the log messages are +# meant to indicate what strategies are being employed. For example, whether +# a vector or a scalar algorithm is used for substring search. This can be +# useful when debugging performance problems. +# +# This is disabled by default. +logging = ["dep:log"] + +# The 'use_std' feature is DEPRECATED. It will be removed in memchr 3. Until +# then, it is alias for the 'std' feature. +use_std = ["std"] + +# The 'libc' feature has been DEPRECATED and no longer has any effect. +libc = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core', 'compiler_builtins'] + +[dependencies] +# Only used when the `logging` feature is enabled (disabled by default). +log = { version = "0.4.20", optional = true } +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +compiler_builtins = { version = '0.1.2', optional = true } + +[dev-dependencies] +quickcheck = { version = "1.0.3", default-features = false } + +[profile.release] +debug = true + +[profile.bench] +debug = true + +[profile.test] +opt-level = 3 +debug = true + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG":"55ebcf7ee0fd10987829a98fb9757cbc6f68c62198bc70122384bedc08de9915","CODE_OF_CONDUCT.md":"0bd67c62d204ec67cb29969aaf5aac337a77c84b318937bc2d9dc7e3fcbcdcaa","Cargo.toml":"6c485fa605a0d3de6ec0af125b67c55224515354034f990334b1a1a86988c632","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE.md":"dbe1fff0fb1314b6af94f161511406275cf01c5a32441fbf24528a57a051d599","README.md":"00d521d93124e88edf58d42b3114786c0daaf437e73118eed27b3c716b7514ad","clippy.toml":"8d3aafbcf358ccf45cc148cd705f5fe71e777dabc391ed9a2bae32af73291fe8","rustfmt.toml":"ae46c79a84842907e151ca5d07e36b8d1932b61c6989465500c0f706507f42cc","src/bellerophon.rs":"bbabeccfa7a70ec314a894d968b424d1162df1b9e5e659baa1fd3a37d985fe75","src/bigint.rs":"93d3332d01bb7745bc569bc6b242c6c71c75eb78835b6a05bad91952b989daf0","src/extended_float.rs":"6040bdd49c03f11f8607b2da1703e1b7b5f57ddac9b02322c6958f9c1684496f","src/fpu.rs":"72d63bac2bbfc545128aa59dc35cfad3c553bac64bf575880775b3c4ace415bc","src/heapvec.rs":"836a49d40e5da90d195508e963d869afd78aaf9adb9cd60a0cb8f92b4e105c4f","src/lemire.rs":"100f3cb293deed0b0d1e7ca6b23152ba160f92f887f8924620b28c9ab77326db","src/lib.rs":"626dfc61992c42d4996dddcbfff5775ff2ffae44d116d2d70f6564a3209c0a9a","src/libm.rs":"ed5a3856eaa44a8a05aa123e27c2048b92ff42e4af1ef3f9fa1aff2a50190f4a","src/mask.rs":"63bcda92d14169a55ac54798f45365cef64a1aecd9625c3c3bc3deae202b2a07","src/num.rs":"dbcab14a5fe8e40e381829426dd75a7db672882592b5c4a08897a2fb6d2ae7ea","src/number.rs":"49d0880a99816ecf904fb88f607a821d6770ec270825b96e800a297ab1a01d78","src/parse.rs":"19559db67eddd17d331274cf87d6c4beeb0724dcdf859de9b8ab5995c4b8e682","src/rounding.rs":"8ba42d31618db1e6a381f8b60ffe1f9d216aaccb931b8fac5f279d8465e35cb7","src/slow.rs":"f096e7f83e8372e71568ec1724bc1c9d2c67ca39b80290ba062e60ae94b1f8d1","src/stackvec.rs":"0c921eb3adbd42cbe7be0f363e08ac85b6d5f1dabd4a7b077becddeff731da16","src/table.rs":"e4288891e9b1d8ba60dcc73edc639754cc2351d3219df8c625e694f3f0e58c5a","src/table_bellerophon.rs":"a2102292b27223a81e60a8a6607c42587efde3424526156921167742a0d5937c","src/table_lemire.rs":"c101c353c38b594f5b8987263b759927095b5dcd72e65607cc1c6a7de0bfd0c8","src/table_small.rs":"61b00e13eb3945622bf8bed374c88e29c63dfedb7384b31b35dd4e543cbe62c1","tests/bellerophon.rs":"b17b87b8963ebcd71f684e4d48c1ce619964e4fb719a5875b0ce4514ed528674","tests/bellerophon_tests.rs":"76b71efa2f4cec56a79535e2d292788a5e1b443c901ec7a234800782f36ddb68","tests/integration_tests.rs":"ed1a1fc46fc239eb4ea718057ad6e9869f633797ef72fc6f05b1757ab80e1641","tests/lemire_tests.rs":"6213bcd9b44def655b44a6b760cee0c0ad82d3bb494f48c2ff100698da34625b","tests/libm_tests.rs":"6941e74d7d0adf021edc93b9919275e82810687ff33147a10361613073b22669","tests/mask_tests.rs":"8c2a3daf434815389b6bf88837e3f382d74d97250104b925d70779366bd3d537","tests/number_tests.rs":"df4b4f0c65478f2f6193bd918fa4aad7163e40598c58df44547c4559e4a8b0c7","tests/parse_tests.rs":"bc0066b9257368f0365276fcffa2662c4699a033eaf9a4a7d6faa0e9b915094a","tests/rounding_tests.rs":"99f38b768ad15e726559c446825f9f1bad67935cdd28ffcc1cbcd3e031a901ea","tests/slow_tests.rs":"36c4c2538d2f5a1c1af5deb26ec4eba47f19f9a3c280a13d10704267a16d3b3f","tests/stackvec.rs":"f040611995bcd1bd2cb47694e74aa02ff4fabdffe007f712c9bb788d82dfb8a7","tests/vec_tests.rs":"09b561160df3b1385876db452bb5a67ef2c9fd2cc36b5687e1dfaf8c58947782"},"package":"68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e819b814dde0c854395882e9f65856c3196961ceced92eeab6ade4d350e7cccc",".github/ISSUE_TEMPLATE/bug_report.md":"cce60fa26d7e6afb7aa84755d6bc6431afe1f390823033545ac3ac9d94740b19",".github/ISSUE_TEMPLATE/custom.md":"b52f73fd67ebd71d43f36d5d1a2f3a53d1f32e126f70ccf0126900ff9f2aec3c",".github/ISSUE_TEMPLATE/documentation.md":"986b9a1421dc15af628bdff8691eeb39d92e36bedb7742d2a4d8327f6cb921a3",".github/ISSUE_TEMPLATE/feature_request.md":"e7861c6047eb39fb4dead4198c141817215839fddb43d16cb6e679417428a73e",".github/ISSUE_TEMPLATE/question.md":"75d3de186382ff882e26e1aba65b4b207cbd3822b9491cd92886fa7987a6ba23",".github/PULL_REQUEST_TEMPLATE/bug_fix.md":"8d7bfb13212e583b9cb717ec39ac2d2070d85470bdf81a32f89e91796a14efcc",".github/PULL_REQUEST_TEMPLATE/custom.md":"88e332c54fe5a52842abdc33e129fa12b0b39c1aaa78da16bc3e1ccce0f3e643",".github/PULL_REQUEST_TEMPLATE/documentation.md":"ac8bae6001c6822dc6d2334c085018c38a8f121f0c580b33b770357170a59c76",".github/workflows/Cross.yml":"51cd10949a21f4aa734a45c06021b53f81cebddcde6723e69caf39d6b7a53cc7",".github/workflows/Features.yml":"4b7182995976d3872853555e989d49be03cfacf92a6807317c01623a1de59742",".github/workflows/OSX.yml":"1ffe8ad7703afb4bc67caf52550b53095861f7290e9b1cbd9f7f7e62de82b3b4",".github/workflows/Simple.yml":"6c681d49afdf74a85757fca4d6bfce076daebbb8816409f42345c2782ba5408d",".github/workflows/Valgrind.yml":"5beae6618e643ef75a6cdc6622bb64a586f3bc956401551920716564d4f3c1fe",".gitmodules":"6976207a02c7160a3a1d076c5fae10fe4b78f58cdc0aa66ae47f3855b3c392fb","CHANGELOG":"55ebcf7ee0fd10987829a98fb9757cbc6f68c62198bc70122384bedc08de9915","CODE_OF_CONDUCT.md":"0bd67c62d204ec67cb29969aaf5aac337a77c84b318937bc2d9dc7e3fcbcdcaa","Cargo.toml":"6c485fa605a0d3de6ec0af125b67c55224515354034f990334b1a1a86988c632","Cargo.toml.orig":"8f0cdacc663b3e6a07f803c2c436d18254a9ad55057782ff350aaf4bfb2121e2","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE.md":"dbe1fff0fb1314b6af94f161511406275cf01c5a32441fbf24528a57a051d599","README.md":"00d521d93124e88edf58d42b3114786c0daaf437e73118eed27b3c716b7514ad","clippy.toml":"8d3aafbcf358ccf45cc148cd705f5fe71e777dabc391ed9a2bae32af73291fe8","rustfmt.toml":"ae46c79a84842907e151ca5d07e36b8d1932b61c6989465500c0f706507f42cc","src/bellerophon.rs":"bbabeccfa7a70ec314a894d968b424d1162df1b9e5e659baa1fd3a37d985fe75","src/bigint.rs":"93d3332d01bb7745bc569bc6b242c6c71c75eb78835b6a05bad91952b989daf0","src/extended_float.rs":"6040bdd49c03f11f8607b2da1703e1b7b5f57ddac9b02322c6958f9c1684496f","src/fpu.rs":"72d63bac2bbfc545128aa59dc35cfad3c553bac64bf575880775b3c4ace415bc","src/heapvec.rs":"836a49d40e5da90d195508e963d869afd78aaf9adb9cd60a0cb8f92b4e105c4f","src/lemire.rs":"100f3cb293deed0b0d1e7ca6b23152ba160f92f887f8924620b28c9ab77326db","src/lib.rs":"626dfc61992c42d4996dddcbfff5775ff2ffae44d116d2d70f6564a3209c0a9a","src/libm.rs":"ed5a3856eaa44a8a05aa123e27c2048b92ff42e4af1ef3f9fa1aff2a50190f4a","src/mask.rs":"63bcda92d14169a55ac54798f45365cef64a1aecd9625c3c3bc3deae202b2a07","src/num.rs":"dbcab14a5fe8e40e381829426dd75a7db672882592b5c4a08897a2fb6d2ae7ea","src/number.rs":"49d0880a99816ecf904fb88f607a821d6770ec270825b96e800a297ab1a01d78","src/parse.rs":"19559db67eddd17d331274cf87d6c4beeb0724dcdf859de9b8ab5995c4b8e682","src/rounding.rs":"8ba42d31618db1e6a381f8b60ffe1f9d216aaccb931b8fac5f279d8465e35cb7","src/slow.rs":"f096e7f83e8372e71568ec1724bc1c9d2c67ca39b80290ba062e60ae94b1f8d1","src/stackvec.rs":"0c921eb3adbd42cbe7be0f363e08ac85b6d5f1dabd4a7b077becddeff731da16","src/table.rs":"e4288891e9b1d8ba60dcc73edc639754cc2351d3219df8c625e694f3f0e58c5a","src/table_bellerophon.rs":"a2102292b27223a81e60a8a6607c42587efde3424526156921167742a0d5937c","src/table_lemire.rs":"c101c353c38b594f5b8987263b759927095b5dcd72e65607cc1c6a7de0bfd0c8","src/table_small.rs":"61b00e13eb3945622bf8bed374c88e29c63dfedb7384b31b35dd4e543cbe62c1","tests/bellerophon.rs":"b17b87b8963ebcd71f684e4d48c1ce619964e4fb719a5875b0ce4514ed528674","tests/bellerophon_tests.rs":"76b71efa2f4cec56a79535e2d292788a5e1b443c901ec7a234800782f36ddb68","tests/integration_tests.rs":"ed1a1fc46fc239eb4ea718057ad6e9869f633797ef72fc6f05b1757ab80e1641","tests/lemire_tests.rs":"6213bcd9b44def655b44a6b760cee0c0ad82d3bb494f48c2ff100698da34625b","tests/libm_tests.rs":"6941e74d7d0adf021edc93b9919275e82810687ff33147a10361613073b22669","tests/mask_tests.rs":"8c2a3daf434815389b6bf88837e3f382d74d97250104b925d70779366bd3d537","tests/number_tests.rs":"df4b4f0c65478f2f6193bd918fa4aad7163e40598c58df44547c4559e4a8b0c7","tests/parse_tests.rs":"bc0066b9257368f0365276fcffa2662c4699a033eaf9a4a7d6faa0e9b915094a","tests/rounding_tests.rs":"99f38b768ad15e726559c446825f9f1bad67935cdd28ffcc1cbcd3e031a901ea","tests/slow_tests.rs":"36c4c2538d2f5a1c1af5deb26ec4eba47f19f9a3c280a13d10704267a16d3b3f","tests/stackvec.rs":"f040611995bcd1bd2cb47694e74aa02ff4fabdffe007f712c9bb788d82dfb8a7","tests/vec_tests.rs":"09b561160df3b1385876db452bb5a67ef2c9fd2cc36b5687e1dfaf8c58947782"},"package":"68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "e997c46656ebe83e696b866bd954da1fa3f64eef" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/bug_report.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/bug_report.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/bug_report.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/bug_report.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: "[BUG]" +labels: bug +assignees: Alexhuszagh + +--- + +## Description + +Please include a clear and concise description of the bug. If the bug includes a security vulnerability, you may also privately report the issue to the [maintainer](mailto:ahuszagh@gmail.com). + +## Prerequisites + +Here are a few things you should provide to help me understand the issue: + +- Rust version: `rustc -V` +- minimal-lexical version: + +## Test case + +Please provide a short, complete (with crate import, etc) test case for +the issue, showing clearly the expected and obtained results. + +Example test case: + +``` +#[macro_use] +extern crate minimal_Lexical; + +fn main() { + let integer = b"1"; + let fraction = b"2345"; + let float: f64 = minimal_lexical::parse_float(integer.iter(), fraction.iter(), 0); + assert_eq!(value, 1.2345); +} +``` + +## Additional Context +Add any other context about the problem here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/custom.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/custom.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/custom.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/custom.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,21 @@ +--- +name: Custom issue template +about: Issue template for miscellaneous issues. +title: "[OTHER]" +labels: '' +assignees: Alexhuszagh + +--- + +## Prerequisites + +If applicable to the issue, here are a few things you should provide to help me understand the issue: + +- Rust version: `rustc -V` +- minimal-lexical version: + +## Description +Please include a clear and concise description of the issue. + +## Additional Context +Add any other context or screenshots about the issue here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/documentation.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/documentation.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/documentation.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/documentation.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,16 @@ +--- +name: Documentation +about: Update the project's documentation. +title: "[DOC]" +labels: documentation +assignees: Alexhuszagh + +--- + +## Description +Please include a clear and concise description of the issue. + +Ex: Documentation for `parse_float` contains a typo. + +## Additional Context +Add any other context or screenshots about the issue here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/feature_request.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/feature_request.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/feature_request.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/feature_request.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,27 @@ +--- +name: Feature request +about: Suggest an idea for this project. +title: "[FEATURE]" +labels: enhancement +assignees: Alexhuszagh + +--- + +## Problem +A clear and concise description of what the problem is. Ex. minimal-lexical does not parse standard-conforming JSON numbers. + +## Solution +A clear and concise description of what you want to happen. + +## Prerequisites + +If applicable to the feature request, here are a few things you should provide to help me understand the issue: + +- Rust version: `rustc -V` +- minimal-lexical version: + +## Alternatives +A clear and concise description of any alternative solutions or features you've considered. + +## Additional Context +Add any other context or screenshots about the feature request here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/question.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/question.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/question.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/ISSUE_TEMPLATE/question.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,11 @@ +--- +name: Question +about: Have a question how to use minimal-lexical? +title: "[QUESTION]" +labels: question +assignees: Alexhuszagh + +--- + +## Question +A clear and concise description of what the question is. Ex. how do I use minimal-lexical without a system allocator? diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/bug_fix.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/bug_fix.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/bug_fix.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/bug_fix.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,27 @@ +--- +name: Bug fix +about: Fix a bug in minimal-lexical. +title: "[BUG]" +labels: bug +assignees: Alexhuszagh + +--- + +**NOTE:** +- If you have made non-trivial changes to the code, please make sure to run unittests prior to committing. +- If you have made any changes to parsing algorithms, please run at least `test-parse-golang` or `test-parse-unittests` with `feature = +comprehensive_float_test"` enabled prior to committing, to ensure there are no regressions. +- Please run `cargo fmt` on nightly prior to committing. + +## Optional Debugging Information + +If applicable to the issue, here are a few things you should provide to help me understand the issue: + +- Rust version: `rustc -V` +- minimal-lexical version: + +## Description +Please include a clear and concise description of the changes made. + +## Additional Context +Add any other context or screenshots about the bug fix here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/custom.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/custom.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/custom.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/custom.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,22 @@ +--- +name: Custom pull request template +about: Pull request template for miscellaneous changes. +title: "[OTHER]" +labels: '' +assignees: Alexhuszagh + +--- + +**NOTE:** +- If you have made non-trivial changes to the code, please make sure to run unittests prior to committing. +- Please run `cargo fmt` on nightly prior to committing. + +## Optional Debugging Information + +If applicable to the issue, here are a few things you should provide to help me understand the issue: + +- Rust version: `rustc -V` +- minimal-lexical version: + +## Description +Please include a clear and concise description of the changes. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/documentation.md clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/documentation.md --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/documentation.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/PULL_REQUEST_TEMPLATE/documentation.md 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,21 @@ +--- +name: Documentation +about: Update the project's documentation. +title: "[DOC]" +labels: documentation +assignees: Alexhuszagh + +--- + +**NOTE:** +- If you have made any changes to doc comments, please run `cargo fmt` on nightly prior to committing. + +## Description +Please include a clear and concise description of fixes made to the documentation. + +Ex: Fixed a backtick leading to improper formatting in README. +Ex: Fixed code sample for `parse_partial` in README. +Ex: Updated outdated doc comments in `parse_float`. + +## Additional Context +Add any other context or screenshots about the issue here. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Cross.yml clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Cross.yml --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Cross.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Cross.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,90 @@ +name: Cross + +on: + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + cross: + name: Rust ${{matrix.target}} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + # Android + - aarch64-linux-android + - arm-linux-androideabi + - armv7-linux-androideabi + - i686-linux-android + - x86_64-linux-android + + # Linux + - aarch64-unknown-linux-gnu + - arm-unknown-linux-gnueabi + - armv7-unknown-linux-gnueabihf + - i686-unknown-linux-gnu + - i686-unknown-linux-musl + - mips-unknown-linux-gnu + - mips64-unknown-linux-gnuabi64 + - mips64el-unknown-linux-gnuabi64 + - mipsel-unknown-linux-gnu + - powerpc64le-unknown-linux-gnu + - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl + + # Windows + - x86_64-pc-windows-gnu + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{matrix.target}} + override: true + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: check + args: --target ${{matrix.target}} + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: test + args: --target ${{matrix.target}} + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: test + args: --target ${{matrix.target}} --features=compact + + notest: + name: Rust ${{matrix.target}} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + # Linux + - powerpc64-unknown-linux-gnu + - s390x-unknown-linux-gnu + + # FreeBSD + - i686-unknown-freebsd + - x86_64-unknown-freebsd + - x86_64-unknown-netbsd + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{matrix.target}} + override: true + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: check + args: --target ${{matrix.target}} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Features.yml clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Features.yml --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Features.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Features.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,23 @@ +name: Features + +on: + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + features: + name: Test Feature Combinations + runs-on: ubuntu-latest + strategy: + fail-fast: true + steps: + - uses: actions/checkout@v2 + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy + - run: ci/test.sh + - run: NIGHTLY=1 NO_STD=1 ci/test.sh diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/OSX.yml clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/OSX.yml --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/OSX.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/OSX.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,40 @@ +name: OSX + +on: + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + cross: + name: Rust ${{matrix.target}} + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + target: + # iOS targets don't work, since rust-embedded doesn't provide images. + - x86_64-apple-darwin + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{matrix.target}} + override: true + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: check + args: --target ${{matrix.target}} + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: test + args: --target ${{matrix.target}} + - uses: actions-rs/cargo@v1 + with: + use-cross: true + command: test + args: --target ${{matrix.target}} --features=compact diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Simple.yml clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Simple.yml --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Simple.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Simple.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,41 @@ +name: Simple + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: Rust ${{matrix.rust}} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [1.36.0, 1.41.0, 1.46.0, 1.51.0, stable, beta, nightly] + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - run: cargo check + - run: cargo test + - run: cargo test --features=compact + + check: + name: Lint code + runs-on: ubuntu-latest + strategy: + fail-fast: true + steps: + - uses: actions/checkout@v2 + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy + - run: ci/check.sh diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Valgrind.yml clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Valgrind.yml --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Valgrind.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.github/workflows/Valgrind.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,24 @@ +name: Valgrind + +on: + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + valgrind: + name: Valgrind Tests + runs-on: ubuntu-latest + strategy: + fail-fast: true + steps: + - uses: actions/checkout@v2 + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + - run: sudo apt-get install valgrind + - run: cargo +nightly install cargo-valgrind + - run: cargo +nightly valgrind test --release + - run: cargo +nightly valgrind test --all-features --release diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.gitmodules clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.gitmodules --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/.gitmodules 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/.gitmodules 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,4 @@ +[submodule "data/test-parse-golang/parse-number-fxx-test-data"] + path = data/test-parse-golang/parse-number-fxx-test-data + url = https://github.com/nigeltao/parse-number-fxx-test-data + shallow = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/minimal-lexical/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/minimal-lexical/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,37 @@ +[package] +authors = ["Alex Huszagh "] +autoexamples = false +categories = ["parsing", "no-std"] +description = "Fast float parsing conversion routines." +documentation = "https://docs.rs/minimal-lexical" +edition = "2018" +keywords = ["parsing", "no_std"] +license = "MIT/Apache-2.0" +name = "minimal-lexical" +readme = "README.md" +repository = "https://github.com/Alexhuszagh/minimal-lexical" +version = "0.2.1" +exclude = [ + "assets/*", + "ci/*", + "docs/*", + "etc/*", + "fuzz/*", + "examples/*", + "scripts/*" +] + +[features] +default = ["std"] +# Use the standard library. +std = [] +# Reduce code size at the cost of performance. +compact = [] +# Use the system allocator. +alloc = [] +# Add support for nightly-only features. +nightly = [] + +# Internal only features. +# Enable the lint checks. +lint = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"91ed52171eba4f7a6135c45a1e95b3dd017a9c04341b66e4cce22897feedc05d","LICENSE":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-APACHE.md":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT.md":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-ZLIB.md":"c89bcc058da12a0fb24402b8ea4542a21515dd1da2e8c67bba4ed9bd269f1c96","Readme.md":"7fa378234ce02b4e14e9ac7dde0c1563e60e466118687d40a3246e6834d16313","src/deflate/buffer.rs":"76bcca4e79bef412eeebdd06d2d0a4348ed9ee17edbdaa6d451d8bf03b1cde85","src/deflate/core.rs":"f4edaa33a0db11f38f8db00577276bffb7a4f52a32d0cbffc148467103295524","src/deflate/mod.rs":"a2022c7b2d78d0cca85bb3e4143bdfc0a9c919b9aa9fb74344014d9029359ddf","src/deflate/stream.rs":"016c82b09a989492c8c8ea89027d339fcf59a5ca2155e7026ac094ca74344712","src/inflate/core.rs":"805e35b133793abc835b7d67402d9558391a7b9a2e6e8f245f0d015e8f56f988","src/inflate/mod.rs":"facd4d970392d0de38446ed94852e72efebe84fd9aaeef2184e0b7bbecdb9187","src/inflate/output_buffer.rs":"1ae90d03ba8c9d667fe248b6066731774afdf93cc79cd3bf90e0711b963b0b72","src/inflate/stream.rs":"a37ce395b9245eaa824786ee12cc67b641748f3d614bd824dbf4ecdc05753dd1","src/lib.rs":"91c4f4d7c5b4d5278d48a4d76f149b178e719877db6dce47f114c4dbfe14c474","src/shared.rs":"a8c47fcb566591e39fcd50d44f3b4d0f567318b8ca36c8d732ee0d8c99a14906"},"package":"9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"63ec91898b26d8ad1c575376009d0dedc8e81dba4fc6a312ed21be764bbbe524","Cargo.lock":"cbb9f38749859d59171bc231b62c446ac1c037e567db4e9ea5cdd9ccd65adaf8","Cargo.toml":"f0d2683434f1c0d3cd9b8080031e82aa5089c9be1779cc5101e065883258d77d","Cargo.toml.orig":"cd14ac8745b43145dab0cbbfa9e425f4778eb30d521a71d6c535fdcd9f00d3ca","LICENSE":"4108245a1f2df9d4e94df8abed5b4ba0759bb2f9b40a6b939f1be141077ae50b","LICENSE-APACHE.md":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT.md":"799e9ca9d179295ef372f25d3769cdda7d25bb2668add6a6a1e22d1e4c678b8d","LICENSE-ZLIB.md":"0a54e647fe54104658b5e563c04c6f9edf251710e47bce692e0bd990a4ddaa39","Readme.md":"223adc19e791c521f7cbc160c6f77959c74a86c58450855fead310461839fdd9","src/deflate/buffer.rs":"6078f2cb24ad3245a78c013c5f86060801e5f7d4c6ab7259e441ac7336444f2c","src/deflate/core.rs":"78f8f7d9a5a58c7e53d2053496942fc9c4e9d783fa317e7a3ddebf716675149b","src/deflate/mod.rs":"a306d53b2cbc3b33eabd84edbf118b4e02cd3dbdfe82967398b05246deb41d2c","src/deflate/stored.rs":"726db3ea000b8552b752142c99656d3c51b00b2f64de99b35739abe2a5622f5a","src/deflate/stream.rs":"016c82b09a989492c8c8ea89027d339fcf59a5ca2155e7026ac094ca74344712","src/deflate/zlib.rs":"ec6565b1ec04003690cfc1c73eb4d379bbb27f8cddfbde66a0283780bb55ad43","src/inflate/core.rs":"59611659879c2b2bd70f840565fe618602a64650901b20ee7246a7aea8491d08","src/inflate/mod.rs":"27766db858d6a29d040843c17538ff8e648bae20f8cd896fc4197f21a601ee3e","src/inflate/output_buffer.rs":"e93b924ae4ffd289b74cb7f91be0c71af0f30ac672c88e25f713f58c85cf125d","src/inflate/stream.rs":"c7ae319dff661e0ebc2f47562012c889264b14b6ad7afc9b64c4375c023915bc","src/lib.rs":"04b23e8d8e83bb42114222ff3631d10cd9f936f489bd4000a633e5d8b44e433e","src/serde/big_array.rs":"63dab5ebc958bc346a237d062833db6e2e16184a2e9cc06e160ed16edeabc320","src/serde/mod.rs":"a93e69079dfbc22412ae7502d248cbb4c29c9e4f3167f0847ae9ea3e7186f616","src/shared.rs":"511f1d9a603ded80a91c59da2d6a092b7a3d2f9b43b26b8cfa00fb5ebe9541ff"},"package":"1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "44e43c7786e379b2b1a7fde4aa0e63be719e583d" + }, + "path_in_vcs": "miniz_oxide" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15acab2bb4fe4dad1f1e31f3d9e714f50ef561a0f87dd8a9da004f14d455e1a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +dependencies = [ + "adler2", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "serde", + "simd-adler32", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -10,17 +10,24 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" name = "miniz_oxide" -version = "0.7.2" +version = "0.8.9" authors = [ "Frommi ", "oyvindln ", + "Rich Geldreich richgel99@gmail.com", ] +build = false exclude = [ "benches/*", "tests/*", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" homepage = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" documentation = "https://docs.rs/miniz_oxide" @@ -34,12 +41,26 @@ categories = ["compression"] license = "MIT OR Zlib OR Apache-2.0" repository = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +resolver = "1" + +[features] +block-boundary = [] +default = ["with-alloc"] +rustc-dep-of-std = [ + "core", + "alloc", + "adler2/rustc-dep-of-std", +] +simd = ["simd-adler32"] +std = [] +with-alloc = [] [lib] name = "miniz_oxide" +path = "src/lib.rs" -[dependencies.adler] -version = "1.0" +[dependencies.adler2] +version = "2.0" default-features = false [dependencies.alloc] @@ -47,28 +68,24 @@ optional = true package = "rustc-std-workspace-alloc" -[dependencies.compiler_builtins] -version = "0.1.2" -optional = true - [dependencies.core] version = "1.0.0" optional = true package = "rustc-std-workspace-core" +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + [dependencies.simd-adler32] -version = "0.3" +version = "0.3.3" optional = true default-features = false -[features] -default = ["with-alloc"] -rustc-dep-of-std = [ - "core", - "alloc", - "compiler_builtins", - "adler/rustc-dep-of-std", -] -simd = ["simd-adler32"] -std = [] -with-alloc = [] +[dev-dependencies] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(fuzzing)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +[package] +name = "miniz_oxide" +authors = ["Frommi ", "oyvindln ", "Rich Geldreich richgel99@gmail.com"] +version = "0.8.9" +license = "MIT OR Zlib OR Apache-2.0" +readme = "Readme.md" +keywords = ["zlib", "miniz", "deflate", "encoding"] +categories = ["compression"] +repository = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +homepage = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +documentation = "https://docs.rs/miniz_oxide" +description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" +edition = "2021" +exclude = ["benches/*", "tests/*"] + +[lib] +name = "miniz_oxide" + +[dependencies] +adler2 = { version = "2.0", default-features = false } +simd-adler32 = { version = "0.3.3", default-features = false, optional = true } +serde = { version = "1.0", features = ["derive"], optional = true } + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +alloc = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-alloc' } + + +[dev-dependencies] +## Messes with minimum rust version and drags in deps just for running tests +## so just comment out for now and enable manually when needed for enabling benches +# criterion = "0.5" + +[[bench]] +name = "benchmark" +harness = false + +[features] +default = ["with-alloc"] +with-alloc = [] +std = [] +block-boundary = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core', 'alloc', 'adler2/rustc-dep-of-std'] + +simd = ['simd-adler32'] + +# Disable unexpected cfg name warning from to !cfg(fuzzing) - compiler is not aware of the fuzzing feature since it comes from the environment +# see https://github.com/rust-fuzz/cargo-fuzz/issues/372 +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,10 @@ MIT License +Copyright 2013-2014 RAD Game Tools and Valve Software +Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC Copyright (c) 2017 Frommi +Copyright (c) 2017-2024 oyvindln + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE-MIT.md clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-MIT.md --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE-MIT.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-MIT.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,9 @@ MIT License +Copyright 2013-2014 RAD Game Tools and Valve Software +Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC Copyright (c) 2017 Frommi +Copyright (c) 2017-2024 oyvindln Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE-ZLIB.md clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-ZLIB.md --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/LICENSE-ZLIB.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/LICENSE-ZLIB.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,7 @@ +Copyright 2013-2014 RAD Game Tools and Valve Software +Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC Copyright (c) 2020 Frommi +Copyright (c) 2017-2024 oyvindln This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Readme.md clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Readme.md --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/Readme.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/Readme.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,6 @@ # miniz_oxide -A fully safe, pure rust replacement for the [miniz](https://github.com/richgel999/miniz) DEFLATE/zlib encoder/decoder. -The main intention of this crate is to be used as a back-end for the [flate2](https://github.com/alexcrichton/flate2-rs), but it can also be used on its own. Using flate2 with the ```rust_backend``` feature provides an easy to use streaming API for miniz_oxide. +A fully safe, pure rust port and replacement for the [miniz](https://github.com/richgel999/miniz) DEFLATE/zlib encoder/decoder originally written by Rich Geldreich. The main intention of this crate is to be used as a back-end for the [flate2](https://github.com/rust-lang/flate2-rs), but it can also be used on its own. Using flate2 with the default ```rust_backend``` feature provides an easy to use streaming API for miniz_oxide. The library is fully [no_std](https://docs.rust-embedded.org/book/intro/no-std.html). By default, the `with-alloc` feature is enabled, which requires the use of the `alloc` and `collection` crates as it allocates memory. @@ -14,18 +13,26 @@ - The `deflate` module is removed completely - Some `inflate` functions which return a `Vec` are removed -miniz_oxide 0.5.x and 0.6.x Requires at least rust 1.40.0 0.3.x requires at least rust 0.36.0. +miniz_oxide 0.8.x currently requires at least Rust 1.56.0, though to leave some room for future internal improvements the minimum version might be raised in the future though it never be made incompatible with anything more recent than the last 4 rust versions and in all likelyhood not require anything even remotely that recent unless there is a very good reason for it. + +IMPORTANT! Versions prior to 0.8.4 have a [massive](https://github.com/Frommi/miniz_oxide/issues/163) regression in compression performance in versions of rust 1.81 and newer due to a upstream regression. If miniz_oxide is part of your dependencies, please update to the latest version to avoid performance regressions! miniz_oxide features no use of unsafe code. -miniz_oxide can optionally be made to use a simd-accelerated version of adler32 via the [simd-adler32](https://crates.io/crates/simd-adler32) crate by enabling the 'simd' feature. This is not enabled by default as due to the use of simd intrinsics, the simd-adler32 has to use unsafe. The default setup uses the [adler](https://crates.io/crates/adler) crate which features no unsafe code. +miniz_oxide can optionally be made to use a simd-accelerated version of adler32 via the [simd-adler32](https://crates.io/crates/simd-adler32) crate by enabling the 'simd' feature which will give a noticeable speedup on decoding, and a smaller speedup during encoding, if the data is encoded with a zlib header. Due to the increase in performance this is recommended, though not enabled by default for compatability reasons. Additionally, due to the use of simd intrinsics, the simd-adler32 has to use unsafe. (Due to limitations in the rust standard library simd-adler32 only has explicit SIMD implementations on stable rust for x86 platforms currently but this may change in the future.) + +simd-adler32 requires std support (and it's 'std' feature to be enabled, which it is by default) for runtime feature detection to work though this does *not* require the 'std' feature in miniz_oxide to be enabled. + +The default setup uses the [adler2](https://crates.io/crates/adler2) crate which features no unsafe code. (a fork of the [adler](https://github.com/jonas-schievink/adler) crate as that crate is archived and no longer maintained.) + +The 'serde' feature enables serialization of the decompressor struct, or a subset of it at block boundaries, allowing compression to be suspended and resumed. This is still an experimental feature that may be expanded in the future the format may still change. ## Usage Simple compression/decompression: ```rust use miniz_oxide::deflate::compress_to_vec; -use miniz_oxide::inflate::decompress_to_vec; +use miniz_oxide::inflate::decompress_to_vec_with_limit; fn roundtrip(data: &[u8]) { // Compress the input @@ -41,4 +48,4 @@ } ``` -These simple functions will do everything in one go and are thus not recommended for use cases outside of prototyping/testing as real world data can have any size and thus result in very large memory allocations for the output Vector. Consider using miniz_oxide via [flate2](https://github.com/alexcrichton/flate2-rs) which makes it easy to do streaming (de)compression or the low-level streaming functions instead. +These simple functions will do everything in one go and are thus not recommended for use cases outside of prototyping/testing as real world data can have any size and thus result in very large memory allocations for the output Vector. Consider using miniz_oxide via [flate2](https://github.com/rust-lang/flate2-rs) which makes it easy to do streaming (de)compression or the low-level streaming functions instead. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,9 +3,12 @@ //! static length info. use crate::deflate::core::{LZ_DICT_SIZE, MAX_MATCH_LEN}; +use alloc::boxed::Box; +use alloc::vec; /// Size of the buffer of lz77 encoded data. pub const LZ_CODE_BUF_SIZE: usize = 64 * 1024; +pub const LZ_CODE_BUF_MASK: usize = LZ_CODE_BUF_SIZE - 1; /// Size of the output buffer. pub const OUT_BUF_SIZE: usize = (LZ_CODE_BUF_SIZE * 13) / 10; pub const LZ_DICT_FULL_SIZE: usize = LZ_DICT_SIZE + MAX_MATCH_LEN - 1 + 1; @@ -18,29 +21,34 @@ pub const LZ_HASH_SIZE: usize = 1 << LZ_HASH_BITS; #[inline] -pub fn update_hash(current_hash: u16, byte: u8) -> u16 { - ((current_hash << LZ_HASH_SHIFT) ^ u16::from(byte)) & (LZ_HASH_SIZE as u16 - 1) +pub const fn update_hash(current_hash: u16, byte: u8) -> u16 { + ((current_hash << LZ_HASH_SHIFT) ^ byte as u16) & (LZ_HASH_SIZE as u16 - 1) } pub struct HashBuffers { - pub dict: [u8; LZ_DICT_FULL_SIZE], - pub next: [u16; LZ_DICT_SIZE], - pub hash: [u16; LZ_DICT_SIZE], + pub dict: Box<[u8; LZ_DICT_FULL_SIZE]>, + pub next: Box<[u16; LZ_DICT_SIZE]>, + pub hash: Box<[u16; LZ_DICT_SIZE]>, } impl HashBuffers { #[inline] pub fn reset(&mut self) { - *self = HashBuffers::default(); + self.dict.fill(0); + self.next.fill(0); + self.hash.fill(0); } } impl Default for HashBuffers { fn default() -> HashBuffers { HashBuffers { - dict: [0; LZ_DICT_FULL_SIZE], - next: [0; LZ_DICT_SIZE], - hash: [0; LZ_DICT_SIZE], + dict: vec![0; LZ_DICT_FULL_SIZE] + .into_boxed_slice() + .try_into() + .unwrap(), + next: vec![0; LZ_DICT_SIZE].into_boxed_slice().try_into().unwrap(), + hash: vec![0; LZ_DICT_SIZE].into_boxed_slice().try_into().unwrap(), } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/core.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/core.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/core.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/core.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,42 +8,44 @@ use super::deflate_flags::*; use super::CompressionLevel; use crate::deflate::buffer::{ - update_hash, HashBuffers, LocalBuf, LZ_CODE_BUF_SIZE, LZ_DICT_FULL_SIZE, LZ_HASH_BITS, - LZ_HASH_SHIFT, LZ_HASH_SIZE, OUT_BUF_SIZE, + update_hash, HashBuffers, LocalBuf, LZ_CODE_BUF_MASK, LZ_CODE_BUF_SIZE, LZ_DICT_FULL_SIZE, + LZ_HASH_BITS, LZ_HASH_SHIFT, LZ_HASH_SIZE, OUT_BUF_SIZE, }; +use crate::deflate::stored::compress_stored; +use crate::deflate::zlib; use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER, MZ_ADLER32_INIT}; use crate::DataFormat; // Currently not bubbled up outside this module, so can fill in with more // context eventually if needed. type Result = core::result::Result; -struct Error {} +pub(crate) struct Error {} -const MAX_PROBES_MASK: i32 = 0xFFF; +pub(crate) const MAX_PROBES_MASK: u32 = 0xFFF; -const MAX_SUPPORTED_HUFF_CODESIZE: usize = 32; +const MAX_SUPPORTED_HUFF_CODESIZE: usize = 15; -/// Length code for length values. -#[rustfmt::skip] -const LEN_SYM: [u16; 256] = [ - 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, - 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, - 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, - 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285 +// Length code for length values - 256. +// We use an offset to help with bound check avoidance as we can mask values to 32 +// and it also saves some memory as we can use a u8 instead of a u16. +// Conventiently our table is large enough that we can get away with using an +// offset of 256 which results in very efficient code. +const LEN_SYM: [u8; 256] = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, ]; +const LEN_SYM_OFFSET: usize = 256; + /// Number of extra bits for length values. #[rustfmt::skip] const LEN_EXTRA: [u8; 256] = [ @@ -157,7 +159,7 @@ /// The maximum number of checks for matches in the hash table the compressor will make for each /// compression level. -const NUM_PROBES: [u32; 11] = [0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500]; +pub(crate) const NUM_PROBES: [u16; 11] = [0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500]; #[derive(Copy, Clone)] struct SymFreq { @@ -206,6 +208,13 @@ Fixed = 4, } +impl From for i32 { + #[inline(always)] + fn from(value: CompressionStrategy) -> Self { + value as i32 + } +} + /// A list of deflate flush types. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TDEFLFlush { @@ -240,7 +249,7 @@ } impl TDEFLFlush { - pub fn new(flush: i32) -> Result { + pub const fn new(flush: i32) -> Result { match flush { 0 => Ok(TDEFLFlush::None), 2 => Ok(TDEFLFlush::Sync), @@ -290,111 +299,13 @@ /// Size of the chained hash table. pub(crate) const LZ_DICT_SIZE: usize = 32_768; /// Mask used when stepping through the hash chains. -const LZ_DICT_SIZE_MASK: usize = (LZ_DICT_SIZE as u32 - 1) as usize; +pub(crate) const LZ_DICT_SIZE_MASK: usize = (LZ_DICT_SIZE as u32 - 1) as usize; /// The minimum length of a match. -const MIN_MATCH_LEN: u8 = 3; +pub(crate) const MIN_MATCH_LEN: u8 = 3; /// The maximum length of a match. pub(crate) const MAX_MATCH_LEN: usize = 258; -const DEFAULT_FLAGS: u32 = NUM_PROBES[4] | TDEFL_WRITE_ZLIB_HEADER; - -mod zlib { - const DEFAULT_CM: u8 = 8; - const DEFAULT_CINFO: u8 = 7 << 4; - const _DEFAULT_FDICT: u8 = 0; - const DEFAULT_CMF: u8 = DEFAULT_CM | DEFAULT_CINFO; - /// The 16-bit value consisting of CMF and FLG must be divisible by this to be valid. - const FCHECK_DIVISOR: u8 = 31; - - /// Generate FCHECK from CMF and FLG (without FCKECH )so that they are correct according to the - /// specification, i.e (CMF*256 + FCHK) % 31 = 0. - /// Returns flg with the FCHKECK bits added (any existing FCHECK bits are ignored). - fn add_fcheck(cmf: u8, flg: u8) -> u8 { - let rem = ((usize::from(cmf) * 256) + usize::from(flg)) % usize::from(FCHECK_DIVISOR); - - // Clear existing FCHECK if any - let flg = flg & 0b11100000; - - // Casting is safe as rem can't overflow since it is a value mod 31 - // We can simply add the value to flg as (31 - rem) will never be above 2^5 - flg + (FCHECK_DIVISOR - rem as u8) - } - - fn zlib_level_from_flags(flags: u32) -> u8 { - use super::NUM_PROBES; - - let num_probes = flags & (super::MAX_PROBES_MASK as u32); - if flags & super::TDEFL_GREEDY_PARSING_FLAG != 0 { - if num_probes <= 1 { - 0 - } else { - 1 - } - } else if num_probes >= NUM_PROBES[9] { - 3 - } else { - 2 - } - } - - /// Get the zlib header for the level using the default window size and no - /// dictionary. - fn header_from_level(level: u8) -> [u8; 2] { - let cmf = DEFAULT_CMF; - [cmf, add_fcheck(cmf, level << 6)] - } - - /// Create a zlib header from the given compression flags. - /// Only level is considered. - pub fn header_from_flags(flags: u32) -> [u8; 2] { - let level = zlib_level_from_flags(flags); - header_from_level(level) - } - - #[cfg(test)] - mod test { - #[test] - fn zlib() { - use super::super::*; - use super::*; - - let test_level = |level, expected| { - let flags = create_comp_flags_from_zip_params( - level, - MZ_DEFAULT_WINDOW_BITS, - CompressionStrategy::Default as i32, - ); - assert_eq!(zlib_level_from_flags(flags), expected); - }; - - assert_eq!(zlib_level_from_flags(DEFAULT_FLAGS), 2); - test_level(0, 0); - test_level(1, 0); - test_level(2, 1); - test_level(3, 1); - for i in 4..=8 { - test_level(i, 2) - } - test_level(9, 3); - test_level(10, 3); - } - - #[test] - fn test_header() { - let header = super::header_from_level(3); - assert_eq!( - ((usize::from(header[0]) * 256) + usize::from(header[1])) % 31, - 0 - ); - } - } -} - -fn memset(slice: &mut [T], val: T) { - for x in slice { - *x = val - } -} +pub(crate) const DEFAULT_FLAGS: u32 = NUM_PROBES[4] as u32 | TDEFL_WRITE_ZLIB_HEADER; #[cfg(test)] #[inline] @@ -404,20 +315,20 @@ } // Read the two bytes starting at pos and interpret them as an u16. -#[inline] -const fn read_u16_le(slice: &[u8], pos: usize) -> u16 { +#[inline(always)] +const fn read_u16_le(slice: &[u8; N], pos: usize) -> u16 { // The compiler is smart enough to optimize this into an unaligned load. slice[pos] as u16 | ((slice[pos + 1] as u16) << 8) } /// Main compression struct. pub struct CompressorOxide { - lz: LZOxide, - params: ParamsOxide, + pub(crate) lz: LZOxide, + pub(crate) params: ParamsOxide, /// Put HuffmanOxide on the heap with default trick to avoid /// excessive stack copies. - huff: Box, - dict: DictOxide, + pub(crate) huff: Box, + pub(crate) dict: DictOxide, } impl CompressorOxide { @@ -454,7 +365,7 @@ } /// Returns whether the compressor is wrapping the data in a zlib format or not. - pub fn data_format(&self) -> DataFormat { + pub const fn data_format(&self) -> DataFormat { if (self.params.flags & TDEFL_WRITE_ZLIB_HEADER) != 0 { DataFormat::Zlib } else { @@ -532,7 +443,7 @@ pub put_buf_func: &'a mut dyn FnMut(&[u8]) -> bool, } -impl<'a> CallbackFunc<'a> { +impl CallbackFunc<'_> { fn flush_output( &mut self, saved_output: SavedOutputBufferOxide, @@ -556,7 +467,7 @@ pub out_buf: &'a mut [u8], } -impl<'a> CallbackBuf<'a> { +impl CallbackBuf<'_> { fn flush_output( &mut self, saved_output: SavedOutputBufferOxide, @@ -585,7 +496,7 @@ Buf(CallbackBuf<'a>), } -impl<'a> CallbackOut<'a> { +impl CallbackOut<'_> { fn new_output_buffer<'b>( &'b mut self, local_buf: &'b mut [u8], @@ -614,7 +525,7 @@ } } -struct CallbackOxide<'a> { +pub(crate) struct CallbackOxide<'a> { in_buf: Option<&'a [u8]>, in_buf_size: Option<&'a mut usize>, out_buf_size: Option<&'a mut usize>, @@ -665,6 +576,10 @@ CallbackOut::Buf(ref mut cb) => cb.flush_output(saved_output, params), } } + + pub(crate) fn buf(&mut self) -> Option<&'a [u8]> { + self.in_buf + } } struct OutputBufferOxide<'a> { @@ -676,11 +591,17 @@ pub bits_in: u32, } -impl<'a> OutputBufferOxide<'a> { +impl OutputBufferOxide<'_> { + /// Write bits to the bit buffer and flushes + /// the bit buffer so any whole bytes are output + /// to the underlying buffer. fn put_bits(&mut self, bits: u32, len: u32) { + // TODO: Removing this assertion worsens performance + // Need to figure out why assert!(bits <= ((1u32 << len) - 1u32)); self.bit_buffer |= bits << self.bits_in; self.bits_in += len; + while self.bits_in >= 8 { self.inner[self.inner_pos] = self.bit_buffer as u8; self.inner_pos += 1; @@ -689,6 +610,14 @@ } } + #[inline] + /// Write the provided bits to the bit buffer without flushing + /// anything. Does not check if there is actually space for it. + fn put_bits_no_flush(&mut self, bits: u32, len: u32) { + self.bit_buffer |= bits << self.bits_in; + self.bits_in += len; + } + const fn save(&self) -> SavedOutputBufferOxide { SavedOutputBufferOxide { pos: self.inner_pos, @@ -705,12 +634,22 @@ self.local = saved.local; } + #[inline] + /// Pad the bit buffer to a whole byte with + /// zeroes and write that byte to the output buffer. fn pad_to_bytes(&mut self) { if self.bits_in != 0 { let len = 8 - self.bits_in; self.put_bits(0, len); } } + + #[inline] + fn write_bytes(&mut self, bytes: &[u8]) { + debug_assert_eq!(self.bits_in, 0); + self.inner[self.inner_pos..self.inner_pos + bytes.len()].copy_from_slice(bytes); + self.inner_pos += bytes.len(); + } } struct SavedOutputBufferOxide { @@ -754,7 +693,7 @@ /// NOTE: Only the literal/lengths have enough symbols to actually use /// the full array. It's unclear why it's defined like this in miniz, /// it could be for cache/alignment reasons. -struct HuffmanOxide { +pub(crate) struct HuffmanOxide { /// Number of occurrences of each symbol. pub count: [[u16; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], /// The bits of the huffman code assigned to the symbol @@ -773,7 +712,7 @@ /// Status of RLE encoding of huffman code lengths. struct Rle { pub z_count: u32, - pub repeat_count: u32, + pub repeat_count: u16, pub prev_code_size: u8, } @@ -789,7 +728,7 @@ if self.repeat_count != 0 { if self.repeat_count < 3 { counts[self.prev_code_size as usize] = - counts[self.prev_code_size as usize].wrapping_add(self.repeat_count as u16); + counts[self.prev_code_size as usize].wrapping_add(self.repeat_count); let code = self.prev_code_size; write(&[code, code, code][..self.repeat_count as usize])?; } else { @@ -974,7 +913,7 @@ code_size_limit: usize, static_table: bool, ) { - let mut num_codes = [0i32; MAX_SUPPORTED_HUFF_CODESIZE + 1]; + let mut num_codes = [0i32; 32 + 1]; let mut next_code = [0u32; MAX_SUPPORTED_HUFF_CODESIZE + 1]; if static_table { @@ -1014,8 +953,8 @@ Self::enforce_max_code_size(&mut num_codes, num_used_symbols, code_size_limit); - memset(&mut self.code_sizes[table_num][..], 0); - memset(&mut self.codes[table_num][..], 0); + self.code_sizes[table_num].fill(0); + self.codes[table_num].fill(0); let mut last = num_used_symbols; for (i, &num_item) in num_codes @@ -1048,25 +987,23 @@ continue; } - let mut code = next_code[code_size as usize]; + let code = next_code[code_size as usize]; + next_code[code_size as usize] += 1; - let mut rev_code = 0; - for _ in 0..code_size { - rev_code = (rev_code << 1) | (code & 1); - code >>= 1; - } - *huff_code = rev_code as u16; + let rev_code = (code as u16).reverse_bits() >> (16 - code_size); + + *huff_code = rev_code; } } fn start_static_block(&mut self, output: &mut OutputBufferOxide) { - memset(&mut self.code_sizes[LITLEN_TABLE][0..144], 8); - memset(&mut self.code_sizes[LITLEN_TABLE][144..256], 9); - memset(&mut self.code_sizes[LITLEN_TABLE][256..280], 7); - memset(&mut self.code_sizes[LITLEN_TABLE][280..288], 8); + self.code_sizes[LITLEN_TABLE][0..144].fill(8); + self.code_sizes[LITLEN_TABLE][144..256].fill(9); + self.code_sizes[LITLEN_TABLE][256..280].fill(7); + self.code_sizes[LITLEN_TABLE][280..288].fill(8); - memset(&mut self.code_sizes[DIST_TABLE][..32], 5); + self.code_sizes[DIST_TABLE][..32].fill(5); self.optimize_table(LITLEN_TABLE, 288, 15, true); self.optimize_table(DIST_TABLE, 32, 15, true); @@ -1111,7 +1048,7 @@ prev_code_size: 0xFF, }; - memset(&mut self.count[HUFF_CODES_TABLE][..MAX_HUFF_SYMBOLS_2], 0); + self.count[HUFF_CODES_TABLE][..MAX_HUFF_SYMBOLS_2].fill(0); let mut packed_pos = 0; for &code_size in &code_sizes_to_pack[..total_code_sizes_to_pack] { @@ -1146,10 +1083,10 @@ self.optimize_table(2, MAX_HUFF_SYMBOLS_2, 7, false); - output.put_bits(2, 2); + output.put_bits_no_flush(2, 2); - output.put_bits((num_lit_codes - 257) as u32, 5); - output.put_bits((num_dist_codes - 1) as u32, 5); + output.put_bits_no_flush((num_lit_codes - 257) as u32, 5); + output.put_bits_no_flush((num_dist_codes - 1) as u32, 5); let mut num_bit_lengths = 18 - HUFFMAN_LENGTH_ORDER @@ -1189,18 +1126,19 @@ } } -struct DictOxide { +pub(crate) struct DictOxide { /// The maximum number of checks in the hash chain, for the initial, /// and the lazy match respectively. pub max_probes: [u32; 2], /// Buffer of input data. /// Padded with 1 byte to simplify matching code in `compress_fast`. - pub b: Box, + pub b: HashBuffers, pub code_buf_dict_pos: usize, pub lookahead_size: usize, pub lookahead_pos: usize, pub size: usize, + loop_len: u8, } const fn probes_from_flags(flags: u32) -> [u32; 2] { @@ -1214,11 +1152,12 @@ fn new(flags: u32) -> Self { DictOxide { max_probes: probes_from_flags(flags), - b: Box::default(), + b: HashBuffers::default(), code_buf_dict_pos: 0, lookahead_size: 0, lookahead_pos: 0, size: 0, + loop_len: 32, } } @@ -1242,6 +1181,8 @@ let pos = pos & LZ_DICT_SIZE_MASK; let end = pos + 4; // Somehow this assertion makes things faster. + // TODO: as of may 2024 this does not seem to make any difference + // so consider removing. assert!(end < LZ_DICT_FULL_SIZE); let bytes: [u8; 4] = self.b.dict[pos..end].try_into().unwrap(); @@ -1252,17 +1193,14 @@ /// type T. #[inline] fn read_unaligned_u64(&self, pos: usize) -> u64 { + // Help evade bounds/panic code check by masking the position value + // This provides a small speedup at the cost of an instruction or two instead of + // having to use unsafe. + let pos = pos & LZ_DICT_SIZE_MASK; let bytes: [u8; 8] = self.b.dict[pos..pos + 8].try_into().unwrap(); u64::from_le_bytes(bytes) } - /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of - /// type T. - #[inline] - fn read_as_u16(&self, pos: usize) -> u16 { - read_u16_le(&self.b.dict[..], pos) - } - /// Try to find a match for the data at lookahead_pos in the dictionary that is /// longer than `match_len`. /// Returns a tuple containing (match_distance, match_length). Will be equal to the input @@ -1283,20 +1221,24 @@ let max_match_len = cmp::min(MAX_MATCH_LEN as u32, max_match_len); match_len = cmp::max(match_len, 1); - let pos = lookahead_pos & LZ_DICT_SIZE_MASK; - let mut probe_pos = pos; - // Number of probes into the hash chains. - let mut num_probes_left = self.max_probes[(match_len >= 32) as usize]; - // If we already have a match of the full length don't bother searching for another one. if max_match_len <= match_len { return (match_dist, match_len); } + let pos = lookahead_pos & LZ_DICT_SIZE_MASK; + let mut probe_pos = pos; + // Number of probes into the hash chains. + let mut num_probes_left = if match_len < 32 { + self.max_probes[0] + } else { + self.max_probes[1] + }; + // Read the last byte of the current match, and the next one, used to compare matches. - let mut c01: u16 = self.read_as_u16(pos + match_len as usize - 1); + let mut c01: u16 = read_u16_le(&self.b.dict, pos + match_len as usize - 1); // Read the two bytes at the end position of the current match. - let s01: u16 = self.read_as_u16(pos); + let s01: u16 = read_u16_le(&self.b.dict, pos); 'outer: loop { let mut dist; @@ -1312,7 +1254,20 @@ let next_probe_pos = self.b.next[probe_pos] as usize; dist = (lookahead_pos - next_probe_pos) & 0xFFFF; - if next_probe_pos == 0 || dist > max_dist { + // Optimization: The last condition should never be hit but helps the compiler by avoiding + // doing the bounds check in the read_u16_le call and adding the extra instructions + // for branching to a panic after that and instead just adds the extra instruction here + // instead saving some instructions and thus improving performance a bit. + // May want to investigate whether we can avoid it entirely but as of now the compiler + // isn't able to deduce that match_len - 1 is bounded to [1-257] + // Disable clippy lint as it needs to be written in this specific way + // rather than MAX_MATCH_LEN to work + // because the compiler isn't super smart.... + #[allow(clippy::int_plus_one)] + if next_probe_pos == 0 + || dist > max_dist + || match_len as usize - 1 >= MAX_MATCH_LEN + { // We reached the end of the hash chain, or the next value is further away // than the maximum allowed distance, so return the best match we found, if // any. @@ -1323,7 +1278,7 @@ // position to match against. probe_pos = next_probe_pos & LZ_DICT_SIZE_MASK; - if self.read_as_u16(probe_pos + match_len as usize - 1) == c01 { + if read_u16_le(&self.b.dict, probe_pos + match_len as usize - 1) == c01 { break 'found; } } @@ -1336,14 +1291,17 @@ } // Check if the two first bytes match. - if self.read_as_u16(probe_pos) != s01 { + if read_u16_le(&self.b.dict, probe_pos) != s01 { continue; } let mut p = pos + 2; let mut q = probe_pos + 2; // The first two bytes matched, so check the full length of the match. - for _ in 0..32 { + // TODO: This is a workaround for an upstream issue introduced after a LLVM upgrade in rust 1.82. + // the compiler is too smart and ends up unrolling the loop which causes the performance to get worse + // Using a variable instead of a constant here to prevent it seems to at least get back some of the performance loss. + for _ in 0..self.loop_len as i32 { let p_data: u64 = self.read_unaligned_u64(p); let q_data: u64 = self.read_unaligned_u64(q); // Compare of 8 bytes at a time by using unaligned loads of 64-bit integers. @@ -1359,14 +1317,18 @@ if probe_len > match_len as usize { match_dist = dist as u32; match_len = cmp::min(max_match_len, probe_len as u32); - if match_len == max_match_len { + if match_len >= max_match_len { // We found a match that had the maximum allowed length, // so there is now point searching further. return (match_dist, match_len); } // We found a better match, so save the last two bytes for further match // comparisons. - c01 = self.read_as_u16(pos + match_len as usize - 1) + // Optimization: use saturating_sub makes the compiler able to evade the bounds check + // at the cost of some extra instructions since it avoids any possibility of wraparound. + // need to see if we can find a better way to do this since this is still a bit costly. + c01 = + read_u16_le(&self.b.dict, (pos + match_len as usize).saturating_sub(1)); } continue 'outer; } @@ -1377,7 +1339,7 @@ } } -struct ParamsOxide { +pub(crate) struct ParamsOxide { pub flags: u32, pub greedy_parsing: bool, pub block_index: u32, @@ -1452,13 +1414,12 @@ } } -struct LZOxide { +pub(crate) struct LZOxide { pub codes: [u8; LZ_CODE_BUF_SIZE], pub code_position: usize, pub flag_position: usize, // The total number of bytes in the current block. - // (Could maybe use usize, but it's not possible to exceed a block size of ) pub total_bytes: u32, pub num_flags_left: u32, } @@ -1475,7 +1436,9 @@ } fn write_code(&mut self, val: u8) { - self.codes[self.code_position] = val; + // Perf - go via u16 to help evade bounds check + // TODO: see if we can use u16 for flag_position in general. + self.codes[usize::from(self.code_position as u16)] = val; self.code_position += 1; } @@ -1489,7 +1452,9 @@ } fn get_flag(&mut self) -> &mut u8 { - &mut self.codes[self.flag_position] + // Perf - go via u16 to help evade bounds check + // TODO: see if we can use u16 for flag_position in general. + &mut self.codes[usize::from(self.flag_position as u16)] } fn plant_flag(&mut self) { @@ -1509,7 +1474,8 @@ fn compress_lz_codes( huff: &HuffmanOxide, output: &mut OutputBufferOxide, - lz_code_buf: &[u8], + lz_code_buf: &[u8; LZ_CODE_BUF_SIZE], + lz_code_buf_used_len: usize, ) -> Result { let mut flags = 1; let mut bb = BitBuffer { @@ -1517,8 +1483,12 @@ bits_in: output.bits_in, }; + // Help out the compiler know this variable won't be larger than + // the buffer length since the constants won't propagate through the function call. + let lz_code_buf_used_len = cmp::min(lz_code_buf.len(), lz_code_buf_used_len); + let mut i: usize = 0; - while i < lz_code_buf.len() { + while i < lz_code_buf_used_len { if flags == 1 { flags = u32::from(lz_code_buf[i]) | 0x100; i += 1; @@ -1531,19 +1501,22 @@ let sym; let num_extra_bits; - let match_len = lz_code_buf[i] as usize; + let match_len = lz_code_buf[i & LZ_CODE_BUF_MASK] as usize; - let match_dist = read_u16_le(lz_code_buf, i + 1); + let match_dist = lz_code_buf[(i + 1) & LZ_CODE_BUF_MASK] as u16 + | ((lz_code_buf[(i + 2) & LZ_CODE_BUF_MASK] as u16) << 8); i += 3; - debug_assert!(huff.code_sizes[0][LEN_SYM[match_len] as usize] != 0); + debug_assert!(huff.code_sizes[0][LEN_SYM[match_len] as usize + LEN_SYM_OFFSET] != 0); + let len_sym = (LEN_SYM[match_len] & 31) as usize + LEN_SYM_OFFSET; + bb.put_fast( - u64::from(huff.codes[0][LEN_SYM[match_len] as usize]), - u32::from(huff.code_sizes[0][LEN_SYM[match_len] as usize]), + u64::from(huff.codes[0][len_sym]), + u32::from(huff.code_sizes[0][len_sym]), ); bb.put_fast( - match_len as u64 & u64::from(BITMASKS[LEN_EXTRA[match_len] as usize]), + match_len as u64 & u64::from(BITMASKS[(LEN_EXTRA[match_len] & 7) as usize]), u32::from(LEN_EXTRA[match_len]), ); @@ -1561,14 +1534,14 @@ u32::from(huff.code_sizes[1][sym]), ); bb.put_fast( - u64::from(match_dist) & u64::from(BITMASKS[num_extra_bits]), + u64::from(match_dist) & u64::from(BITMASKS[num_extra_bits & 15]), num_extra_bits as u32, ); } else { // The lz code was a literal for _ in 0..3 { flags >>= 1; - let lit = lz_code_buf[i]; + let lit = lz_code_buf[i & LZ_CODE_BUF_MASK]; i += 1; debug_assert!(huff.code_sizes[0][lit as usize] != 0); @@ -1577,7 +1550,7 @@ u32::from(huff.code_sizes[0][lit as usize]), ); - if flags & 1 == 1 || i >= lz_code_buf.len() { + if flags & 1 == 1 || i >= lz_code_buf_used_len { break; } } @@ -1616,10 +1589,10 @@ huff.start_dynamic_block(output)?; } - compress_lz_codes(huff, output, &lz.codes[..lz.code_position]) + compress_lz_codes(huff, output, &lz.codes, lz.code_position) } -fn flush_block( +pub(crate) fn flush_block( d: &mut CompressorOxide, callback: &mut CallbackOxide, flush: TDEFLFlush, @@ -1632,8 +1605,13 @@ output.bit_buffer = d.params.saved_bit_buffer; output.bits_in = d.params.saved_bits_in; + // TODO: Don't think this second condition should be here but need to verify. let use_raw_block = (d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0) && (d.dict.lookahead_pos - d.dict.code_buf_dict_pos) <= d.dict.size; + debug_assert_eq!( + use_raw_block, + d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0 + ); assert!(d.params.flush_remaining == 0); d.params.flush_ofs = 0; @@ -1644,7 +1622,7 @@ // If we are at the start of the stream, write the zlib header if requested. if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 && d.params.block_index == 0 { let header = zlib::header_from_flags(d.params.flags); - output.put_bits(header[0].into(), 8); + output.put_bits_no_flush(header[0].into(), 8); output.put_bits(header[1].into(), 8); } @@ -1680,7 +1658,7 @@ // Block header. output.put_bits(0, 2); - // Block length has to start on a byte boundary, s opad. + // Block length has to start on a byte boundary, so pad. output.pad_to_bytes(); // Block length and ones complement of block length. @@ -1688,9 +1666,16 @@ output.put_bits(!d.lz.total_bytes & 0xFFFF, 16); // Write the actual bytes. - for i in 0..d.lz.total_bytes { - let pos = (d.dict.code_buf_dict_pos + i as usize) & LZ_DICT_SIZE_MASK; - output.put_bits(u32::from(d.dict.b.dict[pos]), 8); + let start = d.dict.code_buf_dict_pos & LZ_DICT_SIZE_MASK; + let end = (d.dict.code_buf_dict_pos + d.lz.total_bytes as usize) & LZ_DICT_SIZE_MASK; + let dict = &mut d.dict.b.dict; + if start < end { + // The data does not wrap around. + output.write_bytes(&dict[start..end]); + } else if d.lz.total_bytes > 0 { + // The data wraps around and the input was not 0 bytes. + output.write_bytes(&dict[start..LZ_DICT_SIZE]); + output.write_bytes(&dict[..end]); } } else if !comp_success { output.load(saved_buffer); @@ -1717,9 +1702,10 @@ } } - memset(&mut d.huff.count[0][..MAX_HUFF_SYMBOLS_0], 0); - memset(&mut d.huff.count[1][..MAX_HUFF_SYMBOLS_1], 0); + d.huff.count[0][..MAX_HUFF_SYMBOLS_0].fill(0); + d.huff.count[1][..MAX_HUFF_SYMBOLS_1].fill(0); + // Clear LZ buffer for the next block. d.lz.code_position = 1; d.lz.flag_position = 0; d.lz.num_flags_left = 8; @@ -1736,7 +1722,7 @@ Ok(callback.flush_output(saved_buffer, &mut d.params)) } -fn record_literal(h: &mut HuffmanOxide, lz: &mut LZOxide, lit: u8) { +pub(crate) fn record_literal(h: &mut HuffmanOxide, lz: &mut LZOxide, lit: u8) { lz.total_bytes += 1; lz.write_code(lit); @@ -1746,15 +1732,15 @@ h.count[0][lit as usize] += 1; } -fn record_match(h: &mut HuffmanOxide, lz: &mut LZOxide, mut match_len: u32, mut match_dist: u32) { - assert!(match_len >= MIN_MATCH_LEN.into()); - assert!(match_dist >= 1); - assert!(match_dist as usize <= LZ_DICT_SIZE); +fn record_match(h: &mut HuffmanOxide, lz: &mut LZOxide, match_len: u32, mut match_dist: u32) { + debug_assert!(match_len >= MIN_MATCH_LEN.into()); + debug_assert!(match_dist >= 1); + debug_assert!(match_dist as usize <= LZ_DICT_SIZE); lz.total_bytes += match_len; match_dist -= 1; - match_len -= u32::from(MIN_MATCH_LEN); - lz.write_code(match_len as u8); + let match_len = (match_len - u32::from(MIN_MATCH_LEN)) as u8; + lz.write_code(match_len); lz.write_code(match_dist as u8); lz.write_code((match_dist >> 8) as u8); @@ -1768,16 +1754,18 @@ LARGE_DIST_SYM[((match_dist >> 8) & 127) as usize] } as usize; h.count[1][symbol] += 1; - h.count[0][LEN_SYM[match_len as usize] as usize] += 1; + // Mask the values from LEN_SYM here as the compiler isn't quite smart enough to infer + // that it only contains values smaller than 32. + h.count[0][(LEN_SYM[match_len as usize] as usize & 31) + LEN_SYM_OFFSET] += 1; } fn compress_normal(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool { - let mut src_pos = d.params.src_pos; let in_buf = match callback.in_buf { None => return true, Some(in_buf) => in_buf, }; + let mut src_pos = d.params.src_pos; let mut lookahead_size = d.dict.lookahead_size; let mut lookahead_pos = d.dict.lookahead_pos; let mut saved_lit = d.params.saved_lit; @@ -1818,6 +1806,7 @@ dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK; ins_pos += 1; } + src_pos += num_bytes_to_process; } else { let dictb = &mut d.dict.b; @@ -1859,9 +1848,9 @@ u32::from(MIN_MATCH_LEN) - 1 }; let cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK; - if d.params.flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS) != 0 { + if d.params.flags & TDEFL_RLE_MATCHES != 0 { // If TDEFL_RLE_MATCHES is set, we only look for repeating sequences of the current byte. - if d.dict.size != 0 && d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS == 0 { + if d.dict.size != 0 { let c = d.dict.b.dict[(cur_pos.wrapping_sub(1)) & LZ_DICT_SIZE_MASK]; cur_match_len = d.dict.b.dict[cur_pos..(cur_pos + lookahead_size)] .iter() @@ -1936,11 +1925,10 @@ d.dict.size = cmp::min(d.dict.size + len_to_move, LZ_DICT_SIZE); let lz_buf_tight = d.lz.code_position > LZ_CODE_BUF_SIZE - 8; - let raw = d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0; let fat = ((d.lz.code_position * 115) >> 7) >= d.lz.total_bytes as usize; - let fat_or_raw = (d.lz.total_bytes > 31 * 1024) && (fat || raw); + let buf_fat = (d.lz.total_bytes > 31 * 1024) && fat; - if lz_buf_tight || fat_or_raw { + if lz_buf_tight || buf_fat { d.params.src_pos = src_pos; // These values are used in flush_block, so we need to write them back here. d.dict.lookahead_size = lookahead_size; @@ -2064,6 +2052,7 @@ // that ends after the end of the input data. cur_match_len = cmp::min(cur_match_len, lookahead_size as u32); debug_assert!(cur_match_len >= MIN_MATCH_LEN.into()); + debug_assert!(cur_match_len <= MAX_MATCH_LEN as u32); debug_assert!(cur_match_dist >= 1); debug_assert!(cur_match_dist as usize <= LZ_DICT_SIZE); cur_match_dist -= 1; @@ -2081,8 +2070,11 @@ [LARGE_DIST_SYM[(cur_match_dist >> 8) as usize] as usize] += 1; } - d.huff.count[0][LEN_SYM[(cur_match_len - u32::from(MIN_MATCH_LEN)) as usize] - as usize] += 1; + d.huff.count[0][(LEN_SYM + [(cur_match_len - u32::from(MIN_MATCH_LEN)) as usize & 255] + as usize + & 31) + + LEN_SYM_OFFSET] += 1; } } else { d.lz.write_code(first_trigram as u8); @@ -2265,13 +2257,15 @@ return res; } - let one_probe = d.params.flags & MAX_PROBES_MASK as u32 == 1; + let one_probe = d.params.flags & MAX_PROBES_MASK == 1; let greedy = d.params.flags & TDEFL_GREEDY_PARSING_FLAG != 0; - let filter_or_rle_or_raw = d.params.flags - & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES) - != 0; + let filter_or_rle = d.params.flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS) != 0; - let compress_success = if one_probe && greedy && !filter_or_rle_or_raw { + let raw = d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0; + + let compress_success = if raw { + compress_stored(d, callback) + } else if one_probe && greedy && !filter_or_rle { compress_fast(d, callback) } else { compress_normal(d, callback) @@ -2315,8 +2309,8 @@ _ => { d.params.finished = d.params.flush == TDEFLFlush::Finish; if d.params.flush == TDEFLFlush::Full { - memset(&mut d.dict.b.hash[..], 0); - memset(&mut d.dict.b.next[..], 0); + d.dict.b.hash.fill(0); + d.dict.b.next.fill(0); d.dict.size = 0; } } @@ -2352,7 +2346,7 @@ } else { 0 }; - let mut comp_flags = NUM_PROBES[num_probes] | greedy; + let mut comp_flags = u32::from(NUM_PROBES[num_probes]) | greedy; if window_bits > 0 { comp_flags |= TDEFL_WRITE_ZLIB_HEADER; @@ -2363,7 +2357,7 @@ } else if strategy == CompressionStrategy::Filtered as i32 { comp_flags |= TDEFL_FILTER_MATCHES; } else if strategy == CompressionStrategy::HuffmanOnly as i32 { - comp_flags &= !MAX_PROBES_MASK as u32; + comp_flags &= !MAX_PROBES_MASK; } else if strategy == CompressionStrategy::Fixed as i32 { comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; } else if strategy == CompressionStrategy::RLE as i32 { @@ -2392,8 +2386,8 @@ #[test] fn u16_from_slice() { - let mut slice = [208, 7]; - assert_eq!(read_u16_le(&mut slice, 0), 2000); + let slice = [208, 7]; + assert_eq!(read_u16_le(&slice, 0), 2000); } #[test] @@ -2453,4 +2447,45 @@ let decoded = decompress_to_vec(&encoded[..]).unwrap(); assert_eq!(&decoded[..], &slice[..]); } + + #[test] + fn zlib_window_bits() { + use crate::inflate::stream::{inflate, InflateState}; + use crate::DataFormat; + use alloc::boxed::Box; + let slice = [ + 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 6, 1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 3, 35, 22, 22, 2, + 6, 2, 6, + ]; + let mut encoded = vec![]; + let flags = create_comp_flags_from_zip_params(2, 1, CompressionStrategy::RLE.into()); + let mut d = CompressorOxide::new(flags); + let (status, in_consumed) = + compress_to_output(&mut d, &slice, TDEFLFlush::Finish, |out: &[u8]| { + encoded.extend_from_slice(out); + true + }); + + assert_eq!(status, TDEFLStatus::Done); + assert_eq!(in_consumed, slice.len()); + + let mut output = vec![0; slice.len()]; + + let mut decompressor = Box::new(InflateState::new(DataFormat::Zlib)); + + let mut out_slice = output.as_mut_slice(); + // Feed 1 byte at a time and no back buffer to test that RLE encoding has been used. + for i in 0..encoded.len() { + let result = inflate( + &mut decompressor, + &encoded[i..i + 1], + out_slice, + crate::MZFlush::None, + ); + out_slice = &mut out_slice[result.bytes_written..]; + } + let cmf = decompressor.decompressor().zlib_header().0; + assert_eq!(cmf, 8); + assert_eq!(output, slice) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,7 +5,9 @@ mod buffer; pub mod core; +mod stored; pub mod stream; +mod zlib; use self::core::*; /// How much processing the compressor should do to compress the data. @@ -187,6 +189,15 @@ let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!"); assert_eq!(test_data, d.as_slice()); } + + #[test] + fn compress_rle() { + let test_data = b"Deflate late"; + + let res = compress_to_vec_inner(test_data, 1, 0, CompressionStrategy::RLE as i32); + let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!"); + assert_eq!(test_data, d.as_slice()); + } /// Test that a raw block compresses fine. #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/stored.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/stored.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/stored.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/stored.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,305 @@ +use crate::deflate::buffer::{update_hash, LZ_HASH_SHIFT, LZ_HASH_SIZE}; +use crate::deflate::core::{ + flush_block, CallbackOxide, CompressorOxide, TDEFLFlush, TDEFLStatus, LZ_DICT_SIZE, + LZ_DICT_SIZE_MASK, MAX_MATCH_LEN, MIN_MATCH_LEN, +}; +use core::cmp; + +pub(crate) fn compress_stored(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool { + let in_buf = match callback.buf() { + None => return true, + Some(in_buf) => in_buf, + }; + + // Make sure this is cleared in case compression level is switched later. + // TODO: It's possible we don't need this or could do this elsewhere later + // but just do this here to avoid causing issues for now. + d.params.saved_match_len = 0; + let mut bytes_written = d.lz.total_bytes; + let mut src_pos = d.params.src_pos; + let mut lookahead_size = d.dict.lookahead_size; + let mut lookahead_pos = d.dict.lookahead_pos; + + while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size != 0) { + let src_buf_left = in_buf.len() - src_pos; + let num_bytes_to_process = cmp::min(src_buf_left, MAX_MATCH_LEN - lookahead_size); + + if lookahead_size + d.dict.size >= usize::from(MIN_MATCH_LEN) - 1 + && num_bytes_to_process > 0 + { + let dictb = &mut d.dict.b; + + let mut dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + let mut ins_pos = lookahead_pos + lookahead_size - 2; + // Start the hash value from the first two bytes + let mut hash = update_hash( + u16::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]), + dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK], + ); + + lookahead_size += num_bytes_to_process; + + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + // Add byte to input buffer. + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + // Generate hash from the current byte, + hash = update_hash(hash, c); + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + // and insert it into the hash chain. + dictb.hash[hash as usize] = ins_pos as u16; + dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK; + ins_pos += 1; + } + src_pos += num_bytes_to_process; + } else { + let dictb = &mut d.dict.b; + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + let dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + lookahead_size += 1; + if lookahead_size + d.dict.size >= MIN_MATCH_LEN.into() { + let ins_pos = lookahead_pos + lookahead_size - 3; + let hash = ((u32::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]) + << (LZ_HASH_SHIFT * 2)) + ^ ((u32::from(dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK]) + << LZ_HASH_SHIFT) + ^ u32::from(c))) + & (LZ_HASH_SIZE as u32 - 1); + + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + dictb.hash[hash as usize] = ins_pos as u16; + } + } + + src_pos += num_bytes_to_process; + } + + d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size); + if d.params.flush == TDEFLFlush::None && lookahead_size < MAX_MATCH_LEN { + break; + } + + let len_to_move = 1; + + bytes_written += 1; + + lookahead_pos += len_to_move; + assert!(lookahead_size >= len_to_move); + lookahead_size -= len_to_move; + d.dict.size = cmp::min(d.dict.size + len_to_move, LZ_DICT_SIZE); + + if bytes_written > 31 * 1024 { + d.lz.total_bytes = bytes_written; + + d.params.src_pos = src_pos; + // These values are used in flush_block, so we need to write them back here. + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + + let n = flush_block(d, callback, TDEFLFlush::None) + .unwrap_or(TDEFLStatus::PutBufFailed as i32); + if n != 0 { + return n > 0; + } + bytes_written = d.lz.total_bytes; + } + } + + d.lz.total_bytes = bytes_written; + d.params.src_pos = src_pos; + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + true +} + +/* +fn compress_rle(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool { + let mut src_pos = d.params.src_pos; + let in_buf = match callback.in_buf { + None => return true, + Some(in_buf) => in_buf, + }; + + let mut lookahead_size = d.dict.lookahead_size; + let mut lookahead_pos = d.dict.lookahead_pos; + let mut saved_lit = d.params.saved_lit; + let mut saved_match_dist = d.params.saved_match_dist; + let mut saved_match_len = d.params.saved_match_len; + + while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size != 0) { + let src_buf_left = in_buf.len() - src_pos; + let num_bytes_to_process = cmp::min(src_buf_left, MAX_MATCH_LEN - lookahead_size); + + if lookahead_size + d.dict.size >= usize::from(MIN_MATCH_LEN) - 1 + && num_bytes_to_process > 0 + { + let dictb = &mut d.dict.b; + + let mut dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + let mut ins_pos = lookahead_pos + lookahead_size - 2; + // Start the hash value from the first two bytes + let mut hash = update_hash( + u16::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]), + dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK], + ); + + lookahead_size += num_bytes_to_process; + + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + // Add byte to input buffer. + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + // Generate hash from the current byte, + hash = update_hash(hash, c); + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + // and insert it into the hash chain. + dictb.hash[hash as usize] = ins_pos as u16; + dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK; + ins_pos += 1; + } + src_pos += num_bytes_to_process; + } else { + let dictb = &mut d.dict.b; + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + let dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + lookahead_size += 1; + if lookahead_size + d.dict.size >= MIN_MATCH_LEN.into() { + let ins_pos = lookahead_pos + lookahead_size - 3; + let hash = ((u32::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]) + << (LZ_HASH_SHIFT * 2)) + ^ ((u32::from(dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK]) + << LZ_HASH_SHIFT) + ^ u32::from(c))) + & (LZ_HASH_SIZE as u32 - 1); + + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + dictb.hash[hash as usize] = ins_pos as u16; + } + } + + src_pos += num_bytes_to_process; + } + + d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size); + if d.params.flush == TDEFLFlush::None && lookahead_size < MAX_MATCH_LEN { + break; + } + + let mut len_to_move = 1; + let mut cur_match_dist = 0; + let mut cur_match_len = if saved_match_len != 0 { + saved_match_len + } else { + u32::from(MIN_MATCH_LEN) - 1 + }; + let cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK; + // If TDEFL_RLE_MATCHES is set, we only look for repeating sequences of the current byte. + if d.dict.size != 0 && d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS == 0 { + let c = d.dict.b.dict[(cur_pos.wrapping_sub(1)) & LZ_DICT_SIZE_MASK]; + cur_match_len = d.dict.b.dict[cur_pos..(cur_pos + lookahead_size)] + .iter() + .take_while(|&x| *x == c) + .count() as u32; + if cur_match_len < MIN_MATCH_LEN.into() { + cur_match_len = 0 + } else { + cur_match_dist = 1 + } + } + + + let far_and_small = cur_match_len == MIN_MATCH_LEN.into() && cur_match_dist >= 8 * 1024; + let filter_small = d.params.flags & TDEFL_FILTER_MATCHES != 0 && cur_match_len <= 5; + if far_and_small || filter_small || cur_pos == cur_match_dist as usize { + cur_match_dist = 0; + cur_match_len = 0; + } + + if saved_match_len != 0 { + if cur_match_len > saved_match_len { + record_literal(&mut d.huff, &mut d.lz, saved_lit); + if cur_match_len >= 128 { + record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist); + saved_match_len = 0; + len_to_move = cur_match_len as usize; + } else { + saved_lit = d.dict.b.dict[cur_pos]; + saved_match_dist = cur_match_dist; + saved_match_len = cur_match_len; + } + } else { + record_match(&mut d.huff, &mut d.lz, saved_match_len, saved_match_dist); + len_to_move = (saved_match_len - 1) as usize; + saved_match_len = 0; + } + } else if cur_match_dist == 0 { + record_literal( + &mut d.huff, + &mut d.lz, + d.dict.b.dict[cmp::min(cur_pos, d.dict.b.dict.len() - 1)], + ); + } else if d.params.greedy_parsing + || (d.params.flags & TDEFL_RLE_MATCHES != 0) + || cur_match_len >= 128 + { + // If we are using lazy matching, check for matches at the next byte if the current + // match was shorter than 128 bytes. + record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist); + len_to_move = cur_match_len as usize; + } else { + saved_lit = d.dict.b.dict[cmp::min(cur_pos, d.dict.b.dict.len() - 1)]; + saved_match_dist = cur_match_dist; + saved_match_len = cur_match_len; + } + + lookahead_pos += len_to_move; + assert!(lookahead_size >= len_to_move); + lookahead_size -= len_to_move; + d.dict.size = cmp::min(d.dict.size + len_to_move, LZ_DICT_SIZE); + + let lz_buf_tight = d.lz.code_position > LZ_CODE_BUF_SIZE - 8; + let raw = d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0; + let fat = ((d.lz.code_position * 115) >> 7) >= d.lz.total_bytes as usize; + let fat_or_raw = (d.lz.total_bytes > 31 * 1024) && (fat || raw); + + if lz_buf_tight || fat_or_raw { + d.params.src_pos = src_pos; + // These values are used in flush_block, so we need to write them back here. + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + + let n = flush_block(d, callback, TDEFLFlush::None) + .unwrap_or(TDEFLStatus::PutBufFailed as i32); + if n != 0 { + d.params.saved_lit = saved_lit; + d.params.saved_match_dist = saved_match_dist; + d.params.saved_match_len = saved_match_len; + return n > 0; + } + } + } + + d.params.src_pos = src_pos; + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + d.params.saved_lit = saved_lit; + d.params.saved_match_dist = saved_match_dist; + d.params.saved_match_len = saved_match_len; + true +}*/ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/zlib.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/zlib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/deflate/zlib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/deflate/zlib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,112 @@ +use crate::deflate::core::deflate_flags::{ + TDEFL_FORCE_ALL_RAW_BLOCKS, TDEFL_GREEDY_PARSING_FLAG, TDEFL_RLE_MATCHES, +}; + +const DEFAULT_CM: u8 = 8; +const DEFAULT_CINFO: u8 = 7 << 4; +const _DEFAULT_FDICT: u8 = 0; +const DEFAULT_CMF: u8 = DEFAULT_CM | DEFAULT_CINFO; +// CMF used for RLE (technically it uses a window size of 0 but the lowest that can +// be specified in the header corresponds to a window size of 1 << (0 + 8) aka 256. +const MIN_CMF: u8 = DEFAULT_CM; // | 0 +/// The 16-bit value consisting of CMF and FLG must be divisible by this to be valid. +const FCHECK_DIVISOR: u8 = 31; + +/// Generate FCHECK from CMF and FLG (without FCKECH )so that they are correct according to the +/// specification, i.e (CMF*256 + FCHK) % 31 = 0. +/// Returns flg with the FCHKECK bits added (any existing FCHECK bits are ignored). +#[inline] +fn add_fcheck(cmf: u8, flg: u8) -> u8 { + let rem = ((usize::from(cmf) * 256) + usize::from(flg)) % usize::from(FCHECK_DIVISOR); + + // Clear existing FCHECK if any + let flg = flg & 0b11100000; + + // Casting is safe as rem can't overflow since it is a value mod 31 + // We can simply add the value to flg as (31 - rem) will never be above 2^5 + flg + (FCHECK_DIVISOR - rem as u8) +} + +#[inline] +const fn zlib_level_from_flags(flags: u32) -> u8 { + use crate::deflate::core::NUM_PROBES; + + let num_probes = flags & super::MAX_PROBES_MASK; + if (flags & TDEFL_GREEDY_PARSING_FLAG != 0) || (flags & TDEFL_RLE_MATCHES != 0) { + if num_probes <= 1 { + 0 + } else { + 1 + } + } else if num_probes >= NUM_PROBES[9] as u32 { + 3 + } else { + 2 + } +} + +#[inline] +const fn cmf_from_flags(flags: u32) -> u8 { + if (flags & TDEFL_RLE_MATCHES == 0) && (flags & TDEFL_FORCE_ALL_RAW_BLOCKS == 0) { + DEFAULT_CMF + // If we are using RLE encoding or no compression the window bits can be set as the + // minimum. + } else { + MIN_CMF + } +} + +/// Get the zlib header for the level using the default window size and no +/// dictionary. +#[inline] +fn header_from_level(level: u8, flags: u32) -> [u8; 2] { + let cmf = cmf_from_flags(flags); + [cmf, add_fcheck(cmf, level << 6)] +} + +/// Create a zlib header from the given compression flags. +/// Only level is considered. +#[inline] +pub fn header_from_flags(flags: u32) -> [u8; 2] { + let level = zlib_level_from_flags(flags); + header_from_level(level, flags) +} + +#[cfg(test)] +mod test { + use crate::shared::MZ_DEFAULT_WINDOW_BITS; + #[test] + fn zlib() { + use super::super::*; + use super::*; + + let test_level = |level, expected| { + let flags = create_comp_flags_from_zip_params( + level, + MZ_DEFAULT_WINDOW_BITS, + CompressionStrategy::Default as i32, + ); + assert_eq!(zlib_level_from_flags(flags), expected); + }; + + assert_eq!(zlib_level_from_flags(DEFAULT_FLAGS), 2); + test_level(0, 0); + test_level(1, 0); + test_level(2, 1); + test_level(3, 1); + for i in 4..=8 { + test_level(i, 2) + } + test_level(9, 3); + test_level(10, 3); + } + + #[test] + fn test_header() { + let header = super::header_from_level(3, 0); + assert_eq!( + ((usize::from(header[0]) * 256) + usize::from(header[1])) % 31, + 0 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/core.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/core.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/core.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/core.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,32 +4,38 @@ use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER}; use ::core::cell::Cell; +use ::core::cmp; use ::core::convert::TryInto; -use ::core::{cmp, slice}; -use self::output_buffer::OutputBuffer; +use self::output_buffer::{InputWrapper, OutputBuffer}; + +#[cfg(feature = "serde")] +use crate::serde::big_array::BigArray; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; pub const TINFL_LZ_DICT_SIZE: usize = 32_768; /// A struct containing huffman code lengths and the huffman code tree used by the decompressor. +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Clone))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] struct HuffmanTable { - /// Length of the code at each index. - pub code_size: [u8; MAX_HUFF_SYMBOLS_0], /// Fast lookup table for shorter huffman codes. /// /// See `HuffmanTable::fast_lookup`. + #[cfg_attr(feature = "serde", serde(with = "BigArray"))] pub look_up: [i16; FAST_LOOKUP_SIZE as usize], /// Full huffman tree. /// /// Positive values are edge nodes/symbols, negative values are /// parent nodes/references to other nodes. + #[cfg_attr(feature = "serde", serde(with = "BigArray"))] pub tree: [i16; MAX_HUFF_TREE_SIZE], } impl HuffmanTable { const fn new() -> HuffmanTable { HuffmanTable { - code_size: [0; MAX_HUFF_SYMBOLS_0], look_up: [0; FAST_LOOKUP_SIZE as usize], tree: [0; MAX_HUFF_TREE_SIZE], } @@ -46,7 +52,7 @@ /// Get the symbol and the code length from the huffman tree. #[inline] - fn tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u32) -> (i32, u32) { + fn tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u8) -> (i32, u32) { let mut symbol = fast_symbol; // We step through the tree until we encounter a positive value, which indicates a // symbol. @@ -54,17 +60,21 @@ // symbol here indicates the position of the left (0) node, if the next bit is 1 // we add 1 to the lookup position to get the right node. let tree_index = (!symbol + ((bit_buf >> code_len) & 1) as i32) as usize; + + // Use get here to avoid generatic panic code. + // The init_tree code should prevent this from actually going out of bounds + // but if there were somehow a bug with that + // we would at worst end up with corrupted output in release mode. debug_assert!(tree_index < self.tree.len()); - if tree_index >= self.tree.len() { - break; - } - symbol = i32::from(self.tree[tree_index]); + symbol = i32::from(self.tree.get(tree_index).copied().unwrap_or(i16::MAX)); code_len += 1; if symbol >= 0 { break; } } - (symbol, code_len) + // Note: Using a u8 for code_len inside this function seems to improve performance, but changing it + // in localvars seems to worsen things so we convert it to a u32 here. + (symbol, u32::from(code_len)) } #[inline] @@ -75,18 +85,14 @@ /// /// It's possible we could avoid checking for 0 if we can guarantee a sane table. /// TODO: Check if a smaller type for code_len helps performance. - fn lookup(&self, bit_buf: BitBuffer) -> Option<(i32, u32)> { + fn lookup(&self, bit_buf: BitBuffer) -> (i32, u32) { let symbol = self.fast_lookup(bit_buf).into(); if symbol >= 0 { - if (symbol >> 9) as u32 != 0 { - Some((symbol, (symbol >> 9) as u32)) - } else { - // Zero-length code. - None - } + let length = (symbol >> 9) as u32; + (symbol, length) } else { // We didn't get a symbol from the fast lookup table, so check the tree instead. - Some(self.tree_lookup(symbol, bit_buf, FAST_LOOKUP_BITS.into())) + self.tree_lookup(symbol, bit_buf, FAST_LOOKUP_BITS) } } } @@ -98,15 +104,17 @@ /// The length of the second (distance) huffman table. const MAX_HUFF_SYMBOLS_1: usize = 32; /// The length of the last (huffman code length) huffman table. -const _MAX_HUFF_SYMBOLS_2: usize = 19; +const MAX_HUFF_SYMBOLS_2: usize = 19; /// The maximum length of a code that can be looked up in the fast lookup table. const FAST_LOOKUP_BITS: u8 = 10; /// The size of the fast lookup table. -const FAST_LOOKUP_SIZE: u32 = 1 << FAST_LOOKUP_BITS; +const FAST_LOOKUP_SIZE: u16 = 1 << FAST_LOOKUP_BITS; const MAX_HUFF_TREE_SIZE: usize = MAX_HUFF_SYMBOLS_0 * 2; const LITLEN_TABLE: usize = 0; const DIST_TABLE: usize = 1; const HUFFLEN_TABLE: usize = 2; +const LEN_CODES_SIZE: usize = 512; +const LEN_CODES_MASK: usize = LEN_CODES_SIZE - 1; /// Flags to [`decompress()`] to control how inflation works. /// @@ -152,6 +160,12 @@ /// this will result in checksum failure (outside the unlikely event where the checksum happens /// to match anyway). pub const TINFL_FLAG_IGNORE_ADLER32: u32 = 64; + + /// Return [`TINFLStatus::BlockBoundary`][super::TINFLStatus::BlockBoundary] + /// on reaching the boundary between deflate blocks. Calling [`decompress()`][super::decompress] + /// again will resume decompression of the next block. + #[cfg(feature = "block-boundary")] + pub const TINFL_FLAG_STOP_ON_BLOCK_BOUNDARY: u32 = 128; } use self::inflate_flags::*; @@ -164,8 +178,61 @@ #[cfg(not(target_pointer_width = "64"))] type BitBuffer = u32; +/* +enum HuffmanTableType { + LiteralLength = 0, + Dist = 1, + Huffman = 2, +}*/ + +/// Minimal data representing the [`DecompressorOxide`] state when it is between deflate blocks +/// (i.e. [`decompress()`] has returned [`TINFLStatus::BlockBoundary`]). +/// This can be serialized along with the last 32KiB of the output buffer, then passed to +/// [`DecompressorOxide::from_block_boundary_state()`] to resume decompression from the same point. +/// +/// The Zlib/Adler32 fields can be ignored if you aren't using those features +/// ([`TINFL_FLAG_PARSE_ZLIB_HEADER`], [`TINFL_FLAG_COMPUTE_ADLER32`]). +/// When deserializing, you can reconstruct `bit_buf` from the previous byte in the input file +/// (if you still have access to it), so `num_bits` is the only field that is always required. +#[derive(Clone)] +#[cfg(feature = "block-boundary")] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct BlockBoundaryState { + /// The number of bits from the last byte of input consumed, + /// that are needed for decoding the next deflate block. + /// Value is in range `0..=7` + pub num_bits: u8, + + /// The `num_bits` MSBs from the last byte of input consumed, + /// that are needed for decoding the next deflate block. + /// Stored in the LSBs of this field. + pub bit_buf: u8, + + /// Zlib CMF + pub z_header0: u32, + /// Zlib FLG + pub z_header1: u32, + /// Adler32 checksum of the data decompressed so far + pub check_adler32: u32, +} + +#[cfg(feature = "block-boundary")] +impl Default for BlockBoundaryState { + fn default() -> Self { + BlockBoundaryState { + num_bits: 0, + bit_buf: 0, + z_header0: 0, + z_header1: 0, + check_adler32: 1, + } + } +} + /// Main decompression struct. /// +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Clone))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct DecompressorOxide { /// Current state of the decompressor. state: core::State, @@ -178,9 +245,11 @@ /// Adler32 checksum from the zlib header. z_adler32: u32, /// 1 if the current block is the last block, 0 otherwise. - finish: u32, + finish: u8, /// The type of the current block. - block_type: u32, + /// or if in a dynamic block, which huffman table we are currently + // initializing. + block_type: u8, /// 1 if the adler32 value should be checked. check_adler32: u32, /// Last match distance. @@ -188,17 +257,25 @@ /// Variable used for match length, symbols, and a number of other things. counter: u32, /// Number of extra bits for the last length or distance code. - num_extra: u32, + num_extra: u8, /// Number of entries in each huffman table. - table_sizes: [u32; MAX_HUFF_TABLES], + table_sizes: [u16; MAX_HUFF_TABLES], /// Buffer of input data. bit_buf: BitBuffer, /// Huffman tables. tables: [HuffmanTable; MAX_HUFF_TABLES], + + #[cfg_attr(feature = "serde", serde(with = "BigArray"))] + code_size_literal: [u8; MAX_HUFF_SYMBOLS_0], + code_size_dist: [u8; MAX_HUFF_SYMBOLS_1], + code_size_huffman: [u8; MAX_HUFF_SYMBOLS_2], /// Raw block header. raw_header: [u8; 4], /// Huffman length codes. - len_codes: [u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137], + #[cfg_attr(feature = "serde", serde(with = "BigArray"))] + // MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137 + // Extended to 512 to allow masking to help evade bounds checks. + len_codes: [u8; LEN_CODES_SIZE], } impl DecompressorOxide { @@ -217,6 +294,7 @@ /// Returns the adler32 checksum of the currently decompressed data. /// Note: Will return Some(1) if decompressing zlib but ignoring adler32. #[inline] + #[cfg(not(feature = "rustc-dep-of-std"))] pub fn adler32(&self) -> Option { if self.state != State::Start && !self.state.is_failure() && self.z_header0 != 0 { Some(self.check_adler32) @@ -227,6 +305,7 @@ /// Returns the adler32 that was read from the zlib header if it exists. #[inline] + #[cfg(not(feature = "rustc-dep-of-std"))] pub fn adler32_header(&self) -> Option { if self.state != State::Start && self.state != State::BadZlibHeader && self.z_header0 != 0 { Some(self.z_adler32) @@ -234,6 +313,63 @@ None } } + + // Get zlib header for tests + // Only for tests for now, may provide a proper function for this for later. + #[cfg(all(test, feature = "with-alloc"))] + pub(crate) const fn zlib_header(&self) -> (u32, u32) { + (self.z_header0, self.z_header1) + } + + /*fn code_size_table(&mut self, table_num: u8) -> &mut [u8] { + match table_num { + 0 => &mut self.code_size_literal, + 1 => &mut self.code_size_dist, + _ => &mut self.code_size_huffman, + } + }*/ + + /// Returns the current [`BlockBoundaryState`]. Should only be called when + /// [`decompress()`] has returned [`TINFLStatus::BlockBoundary`]; + /// otherwise this will return `None`. + #[cfg(feature = "block-boundary")] + pub fn block_boundary_state(&self) -> Option { + if self.state == core::State::ReadBlockHeader { + // If we're in this state, undo_bytes should have emptied + // bit_buf of any whole bytes + assert!(self.num_bits < 8); + + Some(BlockBoundaryState { + num_bits: self.num_bits as u8, + bit_buf: self.bit_buf as u8, + z_header0: self.z_header0, + z_header1: self.z_header1, + check_adler32: self.check_adler32, + }) + } else { + None + } + } + + /// Creates a new `DecompressorOxide` from the state returned by + /// `block_boundary_state()`. + /// + /// When calling [`decompress()`], the 32KiB of `out` preceding `out_pos` must be + /// initialized with the same data that it contained when `block_boundary_state()` + /// was called. + #[cfg(feature = "block-boundary")] + pub fn from_block_boundary_state(st: &BlockBoundaryState) -> Self { + DecompressorOxide { + state: core::State::ReadBlockHeader, + num_bits: st.num_bits as u32, + bit_buf: st.bit_buf as BitBuffer, + z_header0: st.z_header0, + z_header1: st.z_header1, + z_adler32: 1, + check_adler32: st.check_adler32, + ..DecompressorOxide::default() + } + } } impl Default for DecompressorOxide { @@ -260,13 +396,17 @@ HuffmanTable::new(), HuffmanTable::new(), ], + code_size_literal: [0; MAX_HUFF_SYMBOLS_0], + code_size_dist: [0; MAX_HUFF_SYMBOLS_1], + code_size_huffman: [0; MAX_HUFF_SYMBOLS_2], raw_header: [0; 4], - len_codes: [0; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137], + len_codes: [0; LEN_CODES_SIZE], } } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[non_exhaustive] enum State { Start = 0, @@ -307,24 +447,24 @@ BadCodeSizeDistPrevLookup, InvalidLitlen, InvalidDist, - InvalidCodeLen, } impl State { - fn is_failure(self) -> bool { - match self { - BlockTypeUnexpected => true, - BadCodeSizeSum => true, - BadDistOrLiteralTableLength => true, - BadTotalSymbols => true, - BadZlibHeader => true, - DistanceOutOfBounds => true, - BadRawLength => true, - BadCodeSizeDistPrevLookup => true, - InvalidLitlen => true, - InvalidDist => true, - _ => false, - } + #[cfg(not(feature = "rustc-dep-of-std"))] + const fn is_failure(self) -> bool { + matches!( + self, + BlockTypeUnexpected + | BadCodeSizeSum + | BadDistOrLiteralTableLength + | BadTotalSymbols + | BadZlibHeader + | DistanceOutOfBounds + | BadRawLength + | BadCodeSizeDistPrevLookup + | InvalidLitlen + | InvalidDist + ) } #[inline] @@ -335,7 +475,6 @@ use self::State::*; -// Not sure why miniz uses 32-bit values for these, maybe alignment/cache again? // # Optimization // We add a extra value at the end and make the tables 32 elements long // so we can use a mask to avoid bounds checks. @@ -360,56 +499,37 @@ /// Base length for each distance code. #[rustfmt::skip] -const DIST_BASE: [u16; 32] = [ +const DIST_BASE: [u16; 30] = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, - 2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577, 32_768, 32_768 + 2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577 ]; -/// Number of extra bits for each distance code. -#[rustfmt::skip] -const DIST_EXTRA: [u8; 32] = [ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13 -]; +/// Get the number of extra bits used for a distance code. +/// (Code numbers above `NUM_DISTANCE_CODES` will give some garbage +/// value.) +#[inline(always)] +const fn num_extra_bits_for_distance_code(code: u8) -> u8 { + // TODO: Need to verify that this is faster on all platforms. + // This can be easily calculated without a lookup. + let c = code >> 1; + c.saturating_sub(1) +} /// The mask used when indexing the base/extra arrays. const BASE_EXTRA_MASK: usize = 32 - 1; -/// Sets the value of all the elements of the slice to `val`. -#[inline] -fn memset(slice: &mut [T], val: T) { - for x in slice { - *x = val - } -} - /// Read an le u16 value from the slice iterator. /// /// # Panics /// Panics if there are less than two bytes left. #[inline] -fn read_u16_le(iter: &mut slice::Iter) -> u16 { +fn read_u16_le(iter: &mut InputWrapper) -> u16 { let ret = { - let two_bytes = iter.as_ref()[..2].try_into().unwrap(); + let two_bytes = iter.as_slice()[..2].try_into().unwrap_or_default(); u16::from_le_bytes(two_bytes) }; - iter.nth(1); - ret -} - -/// Read an le u32 value from the slice iterator. -/// -/// # Panics -/// Panics if there are less than four bytes left. -#[inline(always)] -#[cfg(target_pointer_width = "64")] -fn read_u32_le(iter: &mut slice::Iter) -> u32 { - let ret = { - let four_bytes: [u8; 4] = iter.as_ref()[..4].try_into().unwrap(); - u32::from_le_bytes(four_bytes) - }; - iter.nth(3); + iter.advance(2); ret } @@ -420,10 +540,10 @@ /// This function assumes that there is at least 4 bytes left in the input buffer. #[inline(always)] #[cfg(target_pointer_width = "64")] -fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter) { +fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut InputWrapper) { // Read four bytes into the buffer at once. if l.num_bits < 30 { - l.bit_buf |= BitBuffer::from(read_u32_le(in_iter)) << l.num_bits; + l.bit_buf |= BitBuffer::from(in_iter.read_u32_le()) << l.num_bits; l.num_bits += 32; } } @@ -432,7 +552,7 @@ /// Ensures at least 16 bits are present, requires at least 2 bytes in the in buffer. #[inline(always)] #[cfg(not(target_pointer_width = "64"))] -fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter) { +fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut InputWrapper) { // If the buffer is 32-bit wide, read 2 bytes instead. if l.num_bits < 15 { l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits; @@ -445,7 +565,7 @@ /// /// See https://tools.ietf.org/html/rfc1950 #[inline] -fn validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action { +const fn validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action { let mut failed = // cmf + flg should be divisible by 31. (((cmf * 256) + flg) % 31 != 0) || @@ -488,7 +608,7 @@ l: &mut LocalVars, table: usize, flags: u32, - in_iter: &mut slice::Iter, + in_iter: &mut InputWrapper, f: F, ) -> Action where @@ -498,7 +618,7 @@ // ready in the bit buffer to start decoding the next huffman code. if l.num_bits < 15 { // First, make sure there is enough data in the bit buffer to decode a huffman code. - if in_iter.len() < 2 { + if in_iter.bytes_left() < 2 { // If there is less than 2 bytes left in the input buffer, we try to look up // the huffman code with what's available, and return if that doesn't succeed. // Original explanation in miniz: @@ -513,9 +633,9 @@ // /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */ loop { let mut temp = i32::from(r.tables[table].fast_lookup(l.bit_buf)); - if temp >= 0 { let code_len = (temp >> 9) as u32; + // TODO: Is there any point to check for code_len != 0 here still? if (code_len != 0) && (l.num_bits >= code_len) { break; } @@ -578,15 +698,11 @@ // Mask out the length value. symbol &= 511; } else { - let res = r.tables[table].tree_lookup(symbol, l.bit_buf, u32::from(FAST_LOOKUP_BITS)); + let res = r.tables[table].tree_lookup(symbol, l.bit_buf, FAST_LOOKUP_BITS); symbol = res.0; code_len = res.1; }; - if code_len == 0 { - return Action::Jump(InvalidCodeLen); - } - l.bit_buf >>= code_len; l.num_bits -= code_len; f(r, l, symbol) @@ -596,13 +712,13 @@ /// returning the result. /// If reading fails, `Action::End is returned` #[inline] -fn read_byte(in_iter: &mut slice::Iter, flags: u32, f: F) -> Action +fn read_byte(in_iter: &mut InputWrapper, flags: u32, f: F) -> Action where F: FnOnce(u8) -> Action, { - match in_iter.next() { + match in_iter.read_byte() { None => end_of_input(flags), - Some(&byte) => f(byte), + Some(byte) => f(byte), } } @@ -615,7 +731,7 @@ fn read_bits( l: &mut LocalVars, amount: u32, - in_iter: &mut slice::Iter, + in_iter: &mut InputWrapper, flags: u32, f: F, ) -> Action @@ -625,15 +741,15 @@ // Clippy gives a false positive warning here due to the closure. // Read enough bytes from the input iterator to cover the number of bits we want. while l.num_bits < amount { - match read_byte(in_iter, flags, |byte| { + let action = read_byte(in_iter, flags, |byte| { l.bit_buf |= BitBuffer::from(byte) << l.num_bits; l.num_bits += 8; Action::None - }) { - Action::None => (), - // If there are not enough bytes in the input iterator, return and signal that we need - // more. - action => return action, + }); + + // If there are not enough bytes in the input iterator, return and signal that we need more. + if !matches!(action, Action::None) { + return action; } } @@ -644,7 +760,7 @@ } #[inline] -fn pad_to_bytes(l: &mut LocalVars, in_iter: &mut slice::Iter, flags: u32, f: F) -> Action +fn pad_to_bytes(l: &mut LocalVars, in_iter: &mut InputWrapper, flags: u32, f: F) -> Action where F: FnOnce(&mut LocalVars) -> Action, { @@ -653,7 +769,7 @@ } #[inline] -fn end_of_input(flags: u32) -> Action { +const fn end_of_input(flags: u32) -> Action { Action::End(if flags & TINFL_FLAG_HAS_MORE_INPUT != 0 { TINFLStatus::NeedsMoreInput } else { @@ -671,43 +787,103 @@ fn start_static_table(r: &mut DecompressorOxide) { r.table_sizes[LITLEN_TABLE] = 288; r.table_sizes[DIST_TABLE] = 32; - memset(&mut r.tables[LITLEN_TABLE].code_size[0..144], 8); - memset(&mut r.tables[LITLEN_TABLE].code_size[144..256], 9); - memset(&mut r.tables[LITLEN_TABLE].code_size[256..280], 7); - memset(&mut r.tables[LITLEN_TABLE].code_size[280..288], 8); - memset(&mut r.tables[DIST_TABLE].code_size[0..32], 5); + r.code_size_literal[0..144].fill(8); + r.code_size_literal[144..256].fill(9); + r.code_size_literal[256..280].fill(7); + r.code_size_literal[280..288].fill(8); + r.code_size_dist[0..32].fill(5); } -static REVERSED_BITS_LOOKUP: [u32; 1024] = { - let mut table = [0; 1024]; +#[cfg(any( + feature = "rustc-dep-of-std", + not(feature = "with-alloc"), + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "loongarch64" +))] +#[inline] +const fn reverse_bits(n: u16) -> u16 { + // Lookup is not used when building as part of std to avoid wasting space + // for lookup table in every rust binary + // as it's only used for backtraces in the cold path + // - see #152 + + // armv7 and newer, and loongarch have a cpu instruction for bit reversal so + // it's preferable to just use that on those architectures. + + // Also disable lookup table when not using the alloc feature as + // we probably don't want to waste space for a lookup table in an environment + // without an allocator. + n.reverse_bits() +} + +#[cfg(all( + not(any( + feature = "rustc-dep-of-std", + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "loongarch64" + )), + feature = "with-alloc" +))] +fn reverse_bits(n: u16) -> u16 { + static REVERSED_BITS_LOOKUP: [u16; 512] = { + let mut table = [0; 512]; + + let mut i = 0; + while i < 512 { + table[i] = (i as u16).reverse_bits(); + i += 1; + } - let mut i = 0; - while i < 1024 { - table[i] = (i as u32).reverse_bits(); - i += 1; - } + table + }; - table -}; + REVERSED_BITS_LOOKUP[n as usize] +} fn init_tree(r: &mut DecompressorOxide, l: &mut LocalVars) -> Option { loop { let bt = r.block_type as usize; - if bt >= r.tables.len() { - return None; - } + + let code_sizes = match bt { + LITLEN_TABLE => &mut r.code_size_literal[..], + DIST_TABLE => &mut r.code_size_dist, + HUFFLEN_TABLE => &mut r.code_size_huffman, + _ => return None, + }; let table = &mut r.tables[bt]; + + let mut total_symbols = [0u16; 16]; + // Next code - we use the odd length here to simplify a loop later. + let mut next_code = [0u32; 17]; + const INVALID_CODE: i16 = (1 << 9) | 286; + // Set the values in the fast table to return a + // non-zero length and an invalid symbol instead of zero + // so that we do not have to have a check for a zero + // code length in the hot code path later + // and can instead error out on the invalid symbol check + // on bogus input. + table.look_up.fill(INVALID_CODE); + // If we are initializing the huffman code length we can skip + // this since these codes can't be longer than 3 bits + // and thus only use the fast table and this table won't be accessed so + // there is no point clearing it. + // TODO: Avoid creating this table at all. + if bt != HUFFLEN_TABLE { + table.tree.fill(0); + } + let table_size = r.table_sizes[bt] as usize; - if table_size > table.code_size.len() { + if table_size > code_sizes.len() { return None; } - let mut total_symbols = [0u32; 16]; - let mut next_code = [0u32; 17]; - memset(&mut table.look_up[..], 0); - memset(&mut table.tree[..], 0); - for &code_size in &table.code_size[..table_size] { + for &code_size in &code_sizes[..table_size] { let cs = code_size as usize; + // Code sizes are limited to max 15 according to the + // deflate spec. + // If it is larger than this, something has gone wrong... if cs >= total_symbols.len() { return None; } @@ -715,45 +891,56 @@ } let mut used_symbols = 0; - let mut total = 0; - for (ts, next) in total_symbols - .iter() - .copied() - .zip(next_code.iter_mut().skip(1)) - .skip(1) - { + let mut total = 0u32; + // Count up the total number of used lengths and check that the table is not under or over-subscribed. + for (&ts, next) in total_symbols.iter().zip(next_code[1..].iter_mut()).skip(1) { used_symbols += ts; - total += ts; + total += u32::from(ts); total <<= 1; *next = total; } - if total != 65_536 && used_symbols > 1 { + // + // While it's not explicitly stated in the spec, a hufflen table + // with a single length (or none) would be invalid as there needs to be + // at minimum a length for both a non-zero length huffman code for the end of block symbol + // and one of the codes to represent 0 to make sense - so just reject that here as well. + // + // The distance table is allowed to have a single distance code though according to the spect it is + // supposed to be accompanied by a second dummy code. It can also be empty indicating no used codes. + // + // The literal/length table can not be empty as there has to be an end of block symbol, + // The standard doesn't specify that there should be a dummy code in case of a single + // symbol (i.e an empty block). Normally that's not an issue though the code will have + // to take that into account later on in case of malformed input. + if total != 65_536 && (used_symbols > 1 || bt == HUFFLEN_TABLE) { return Some(Action::Jump(BadTotalSymbols)); } let mut tree_next = -1; for symbol_index in 0..table_size { - let mut rev_code = 0; - let code_size = table.code_size[symbol_index]; - if code_size == 0 || usize::from(code_size) >= next_code.len() { + // Code sizes are limited to 15 according to the spec + // It's already checked earlier but the compiler might not be smart enough to know that. + let code_size = code_sizes[symbol_index] & 15; + if code_size == 0 { continue; } - let mut cur_code = next_code[code_size as usize]; + let cur_code = next_code[code_size as usize]; next_code[code_size as usize] += 1; - let n = cur_code & (u32::MAX >> (32 - code_size)); + let n = (cur_code & (u32::MAX >> (32 - code_size))) as u16; - let mut rev_code = if n < 1024 { - REVERSED_BITS_LOOKUP[n as usize] >> (32 - code_size) + let mut rev_code = if n < 512 { + // Using a lookup table + // for a small speedup here, + // Seems to only really make a difference on very short + // inputs however. + // 512 seems to be around a sweet spot. + reverse_bits(n) } else { - for _ in 0..code_size { - rev_code = (rev_code << 1) | (cur_code & 1); - cur_code >>= 1; - } - rev_code - }; + n.reverse_bits() + } >> (16 - code_size); if code_size <= FAST_LOOKUP_BITS { let k = (i16::from(code_size) << 9) | symbol_index as i16; @@ -765,7 +952,7 @@ } let mut tree_cur = table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize]; - if tree_cur == 0 { + if tree_cur == INVALID_CODE { table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize] = tree_next; tree_cur = tree_next; tree_next -= 2; @@ -797,18 +984,19 @@ table.tree[tree_index] = symbol_index as i16; } - if r.block_type == 2 { + if r.block_type == HUFFLEN_TABLE as u8 { l.counter = 0; return Some(Action::Jump(ReadLitlenDistTablesCodeSize)); } - if r.block_type == 0 { + if r.block_type == LITLEN_TABLE as u8 { break; } r.block_type -= 1; } l.counter = 0; + Some(Action::Jump(DecodeLitlen)) } @@ -837,7 +1025,7 @@ pub num_bits: u32, pub dist: u32, pub counter: u32, - pub num_extra: u32, + pub num_extra: u8, } #[inline] @@ -856,23 +1044,40 @@ } else { out_pos - source_pos }; - if out_buf_size_mask == usize::MAX && source_diff == 1 && out_pos > source_pos { - let init = out_slice[out_pos - 1]; - let end = (match_len >> 2) * 4 + out_pos; + // The last 3 bytes can wrap as those are dealt with separately at the end. + // Use wrapping_sub rather than saturating for performance reasons here as + // if source_pos + match_len is < 3 we just want to jump to the end + // condition anyhow. + let not_wrapping = (out_buf_size_mask == usize::MAX) + || ((source_pos + match_len).wrapping_sub(3) < out_slice.len()); + + let end_pos = ((match_len >> 2) * 4) + out_pos; + if not_wrapping && source_diff == 1 && out_pos > source_pos { + let end = (match_len >> 2) * 4 + out_pos; + let init = out_slice[out_pos - 1]; out_slice[out_pos..end].fill(init); out_pos = end; source_pos = end - 1; - // if the difference between `source_pos` and `out_pos` is greater than 3, we + // if the difference between `source_pos` and `out_pos` is greater than 3, + // and we are not wrapping, we // can do slightly better than the naive case by copying everything at once - } else if out_buf_size_mask == usize::MAX && source_diff >= 4 && out_pos > source_pos { - for _ in 0..match_len >> 2 { + } else if not_wrapping && out_pos > source_pos && (out_pos - source_pos >= 4) { + let end_pos = cmp::min(end_pos, out_slice.len().saturating_sub(3)); + while out_pos < end_pos { out_slice.copy_within(source_pos..=source_pos + 3, out_pos); source_pos += 4; out_pos += 4; } } else { - for _ in 0..match_len >> 2 { + let end_pos = cmp::min(end_pos, out_slice.len().saturating_sub(3)); + while out_pos < end_pos { + // Placing these assertions moves some bounds check before the accesses which + // makes the compiler able to optimize better. + // Ideally we would find a safe way to remove them entirely. + assert!(out_pos + 3 < out_slice.len()); + assert!((source_pos + 3) & out_buf_size_mask < out_slice.len()); + out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask]; @@ -886,10 +1091,14 @@ 0 => (), 1 => out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask], 2 => { + assert!(out_pos + 1 < out_slice.len()); + assert!((source_pos + 1) & out_buf_size_mask < out_slice.len()); out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; } 3 => { + assert!(out_pos + 2 < out_slice.len()); + assert!((source_pos + 2) & out_buf_size_mask < out_slice.len()); out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask]; @@ -932,7 +1141,9 @@ } if cfg!(not(any(target_arch = "x86", target_arch = "x86_64"))) { - // We are not on x86 so copy manually. + // The copy from slice code seems to not give any added performance at least on + // armv7 so transfer manually + // Need to test on other platforms. transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask); return; } @@ -941,6 +1152,9 @@ transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask); } else if match_len <= dist && source_pos + match_len < out_slice.len() { // Destination and source segments does not intersect and source does not wrap. + // TODO: An invalid before start of data wrapping match reached here before + // it was fixed (it wrapped around and ended overlapping again)- need + // to check that we are not wrapping here. if source_pos < out_pos { let (from_slice, to_slice) = out_slice.split_at_mut(out_pos); to_slice[..match_len].copy_from_slice(&from_slice[source_pos..source_pos + match_len]); @@ -964,7 +1178,7 @@ /// and already improves decompression speed a fair bit. fn decompress_fast( r: &mut DecompressorOxide, - in_iter: &mut slice::Iter, + in_iter: &mut InputWrapper, out_buf: &mut OutputBuffer, flags: u32, local_vars: &mut LocalVars, @@ -984,50 +1198,42 @@ // + 29 + 32 (left in bit buf, including last 13 dist extra) = 111 bits < 14 bytes // We need the one extra byte as we may write one length and one full match // before checking again. - if out_buf.bytes_left() < 259 || in_iter.len() < 14 { + if out_buf.bytes_left() < 259 || in_iter.bytes_left() < 14 { state = State::DecodeLitlen; break 'o TINFLStatus::Done; } fill_bit_buffer(&mut l, in_iter); - if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { - l.counter = symbol as u32; + let (symbol, code_len) = r.tables[LITLEN_TABLE].lookup(l.bit_buf); + l.counter = symbol as u32; + l.bit_buf >>= code_len; + l.num_bits -= code_len; + + if (l.counter & 256) != 0 { + // The symbol is not a literal. + break; + } else { + // If we have a 32-bit buffer we need to read another two bytes now + // to have enough bits to keep going. + if cfg!(not(target_pointer_width = "64")) { + fill_bit_buffer(&mut l, in_iter); + } + + let (symbol, code_len) = r.tables[LITLEN_TABLE].lookup(l.bit_buf); l.bit_buf >>= code_len; l.num_bits -= code_len; - - if (l.counter & 256) != 0 { - // The symbol is not a literal. + // The previous symbol was a literal, so write it directly and check + // the next one. + out_buf.write_byte(l.counter as u8); + if (symbol & 256) != 0 { + l.counter = symbol as u32; + // The symbol is a length value. break; } else { - // If we have a 32-bit buffer we need to read another two bytes now - // to have enough bits to keep going. - if cfg!(not(target_pointer_width = "64")) { - fill_bit_buffer(&mut l, in_iter); - } - - if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { - l.bit_buf >>= code_len; - l.num_bits -= code_len; - // The previous symbol was a literal, so write it directly and check - // the next one. - out_buf.write_byte(l.counter as u8); - if (symbol & 256) != 0 { - l.counter = symbol as u32; - // The symbol is a length value. - break; - } else { - // The symbol is a literal, so write it directly and continue. - out_buf.write_byte(symbol as u8); - } - } else { - state.begin(InvalidCodeLen); - break 'o TINFLStatus::Failed; - } + // The symbol is a literal, so write it directly and continue. + out_buf.write_byte(symbol as u8); } - } else { - state.begin(InvalidCodeLen); - break 'o TINFLStatus::Failed; } } @@ -1046,18 +1252,19 @@ // The symbol was a length code. // # Optimization // Mask the value to avoid bounds checks - // We could use get_unchecked later if can statically verify that - // this will never go out of bounds. - l.num_extra = u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + // While the maximum is checked, the compiler isn't able to know that the + // value won't wrap around here. + l.num_extra = LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]; l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]); // Length and distance codes have a number of extra bits depending on // the base, which together with the base gives us the exact value. + // We need to make sure we have at least 33 (so min 5 bytes) bits in the buffer at this spot. fill_bit_buffer(&mut l, in_iter); if l.num_extra != 0 { let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1); l.bit_buf >>= l.num_extra; - l.num_bits -= l.num_extra; + l.num_bits -= u32::from(l.num_extra); l.counter += extra_bits as u32; } @@ -1067,33 +1274,30 @@ fill_bit_buffer(&mut l, in_iter); } - if let Some((mut symbol, code_len)) = r.tables[DIST_TABLE].lookup(l.bit_buf) { - symbol &= 511; - l.bit_buf >>= code_len; - l.num_bits -= code_len; - if symbol > 29 { - state.begin(InvalidDist); - break 'o TINFLStatus::Failed; - } - - l.num_extra = u32::from(DIST_EXTRA[symbol as usize]); - l.dist = u32::from(DIST_BASE[symbol as usize]); - } else { - state.begin(InvalidCodeLen); + let (mut symbol, code_len) = r.tables[DIST_TABLE].lookup(l.bit_buf); + symbol &= 511; + l.bit_buf >>= code_len; + l.num_bits -= code_len; + if symbol > 29 { + state.begin(InvalidDist); break 'o TINFLStatus::Failed; } + l.num_extra = num_extra_bits_for_distance_code(symbol as u8); + l.dist = u32::from(DIST_BASE[symbol as usize]); + if l.num_extra != 0 { fill_bit_buffer(&mut l, in_iter); let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1); l.bit_buf >>= l.num_extra; - l.num_bits -= l.num_extra; + l.num_bits -= u32::from(l.num_extra); l.dist += extra_bits as u32; } let position = out_buf.position(); - if l.dist as usize > out_buf.position() - && (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0) + if (l.dist as usize > out_buf.position() + && (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)) + || (l.dist as usize > out_buf.get_ref().len()) { // We encountered a distance that refers a position before // the start of the decoded data, so we can't continue. @@ -1133,26 +1337,24 @@ /// /// * The offset given by `out_pos` indicates where in the output buffer slice writing should start. /// * If [`TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF`] is not set, the output buffer is used in a -/// wrapping manner, and it's size is required to be a power of 2. +/// wrapping manner, and it's size is required to be a power of 2. /// * The decompression function normally needs access to 32KiB of the previously decompressed data -///(or to the beginning of the decompressed data if less than 32KiB has been decompressed.) +/// (or to the beginning of the decompressed data if less than 32KiB has been decompressed.) /// - If this data is not available, decompression may fail. /// - Some deflate compressors allow specifying a window size which limits match distances to -/// less than this, or alternatively an RLE mode where matches will only refer to the previous byte -/// and thus allows a smaller output buffer. The window size can be specified in the zlib -/// header structure, however, the header data should not be relied on to be correct. +/// less than this, or alternatively an RLE mode where matches will only refer to the previous byte +/// and thus allows a smaller output buffer. The window size can be specified in the zlib +/// header structure, however, the header data should not be relied on to be correct. /// /// `flags` indicates settings and status to the decompression function. /// * The [`TINFL_FLAG_HAS_MORE_INPUT`] has to be specified if more compressed data is to be provided -/// in a subsequent call to this function. +/// in a subsequent call to this function. /// * See the the [`inflate_flags`] module for details on other flags. /// /// # Returns /// /// Returns a tuple containing the status of the compressor, the number of input bytes read, and the /// number of bytes output to `out`. -/// -/// This function shouldn't panic pending any bugs. pub fn decompress( r: &mut DecompressorOxide, in_buf: &[u8], @@ -1161,7 +1363,7 @@ flags: u32, ) -> (TINFLStatus, usize, usize) { let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 { - usize::max_value() + usize::MAX } else { // In the case of zero len, any attempt to write would produce HasMoreOutput, // so to gracefully process the case of there really being no output, @@ -1177,7 +1379,7 @@ return (TINFLStatus::BadParam, 0, 0); } - let mut in_iter = in_buf.iter(); + let mut in_iter = InputWrapper::from_slice(in_buf); let mut state = r.state; @@ -1228,8 +1430,8 @@ // Read the block header and jump to the relevant section depending on the block type. ReadBlockHeader => generate_state!(state, 'state_machine, { read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| { - r.finish = (bits & 1) as u32; - r.block_type = (bits >> 1) as u32 & 3; + r.finish = (bits & 1) as u8; + r.block_type = ((bits >> 1) & 3) as u8; match r.block_type { 0 => Action::Jump(BlockTypeNoCompression), 1 => { @@ -1334,20 +1536,20 @@ }), RawMemcpy2 => generate_state!(state, 'state_machine, { - if in_iter.len() > 0 { + if in_iter.bytes_left() > 0 { // Copy as many raw bytes as possible from the input to the output using memcpy. // Raw block lengths are limited to 64 * 1024, so casting through usize and u32 // is not an issue. let space_left = out_buf.bytes_left(); let bytes_to_copy = cmp::min(cmp::min( space_left, - in_iter.len()), + in_iter.bytes_left()), l.counter as usize ); out_buf.write_slice(&in_iter.as_slice()[..bytes_to_copy]); - in_iter.nth(bytes_to_copy - 1); + in_iter.advance(bytes_to_copy); l.counter -= bytes_to_copy as u32; Action::Jump(RawMemcpy1) } else { @@ -1361,12 +1563,12 @@ let num_bits = [5, 5, 4][l.counter as usize]; read_bits(&mut l, num_bits, &mut in_iter, flags, |l, bits| { r.table_sizes[l.counter as usize] = - bits as u32 + u32::from(MIN_TABLE_SIZES[l.counter as usize]); + bits as u16 + MIN_TABLE_SIZES[l.counter as usize]; l.counter += 1; Action::None }) } else { - memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0); + r.code_size_huffman.fill(0); l.counter = 0; // Check that the litlen and distance are within spec. // litlen table should be <=286 acc to the RFC and @@ -1386,51 +1588,58 @@ // Read the 3-bit lengths of the huffman codes describing the huffman code lengths used // to decode the lengths of the main tables. ReadHufflenTableCodeSize => generate_state!(state, 'state_machine, { - if l.counter < r.table_sizes[HUFFLEN_TABLE] { + if l.counter < r.table_sizes[HUFFLEN_TABLE].into() { read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| { // These lengths are not stored in a normal ascending order, but rather one // specified by the deflate specification intended to put the most used // values at the front as trailing zero lengths do not have to be stored. - r.tables[HUFFLEN_TABLE] - .code_size[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] = + r.code_size_huffman[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] = bits as u8; l.counter += 1; Action::None }) } else { - r.table_sizes[HUFFLEN_TABLE] = 19; + r.table_sizes[HUFFLEN_TABLE] = MAX_HUFF_SYMBOLS_2 as u16; init_tree(r, &mut l).unwrap_or(Action::End(TINFLStatus::Failed)) } }), ReadLitlenDistTablesCodeSize => generate_state!(state, 'state_machine, { - if l.counter < r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] { + if l.counter < u32::from(r.table_sizes[LITLEN_TABLE]) + u32::from(r.table_sizes[DIST_TABLE]) { decode_huffman_code( r, &mut l, HUFFLEN_TABLE, flags, &mut in_iter, |r, l, symbol| { l.dist = symbol as u32; if l.dist < 16 { - r.len_codes[l.counter as usize] = l.dist as u8; + r.len_codes[l.counter as usize & LEN_CODES_MASK] = l.dist as u8; l.counter += 1; Action::None } else if l.dist == 16 && l.counter == 0 { Action::Jump(BadCodeSizeDistPrevLookup) } else { - l.num_extra = [2, 3, 7][l.dist as usize - 16]; + // Last value is a dummy to allow mask. + l.num_extra = [2, 3, 7, 0][(l.dist as usize - 16) & 3]; Action::Jump(ReadExtraBitsCodeSize) } } ) - } else if l.counter != r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] { + } else if l.counter != u32::from(r.table_sizes[LITLEN_TABLE]) + u32::from(r.table_sizes[DIST_TABLE]) { Action::Jump(BadCodeSizeSum) } else { - r.tables[LITLEN_TABLE].code_size[..r.table_sizes[LITLEN_TABLE] as usize] - .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize]); + + r.code_size_literal[..r.table_sizes[LITLEN_TABLE] as usize] + .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize & LEN_CODES_MASK]); let dist_table_start = r.table_sizes[LITLEN_TABLE] as usize; + debug_assert!(dist_table_start < r.len_codes.len()); let dist_table_end = (r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE]) as usize; - r.tables[DIST_TABLE].code_size[..r.table_sizes[DIST_TABLE] as usize] + let code_size_dist_end = r.table_sizes[DIST_TABLE] as usize; + debug_assert!(dist_table_end < r.len_codes.len()); + debug_assert!(code_size_dist_end < r.code_size_dist.len()); + let dist_table_start = dist_table_start & LEN_CODES_MASK; + let dist_table_end = dist_table_end & LEN_CODES_MASK; + r.code_size_dist[..code_size_dist_end & (MAX_HUFF_SYMBOLS_1 - 1)] .copy_from_slice(&r.len_codes[dist_table_start..dist_table_end]); r.block_type -= 1; @@ -1439,29 +1648,33 @@ }), ReadExtraBitsCodeSize => generate_state!(state, 'state_machine, { - let num_extra = l.num_extra; + let num_extra = l.num_extra.into(); read_bits(&mut l, num_extra, &mut in_iter, flags, |l, mut extra_bits| { // Mask to avoid a bounds check. - extra_bits += [3, 3, 11][(l.dist as usize - 16) & 3]; + // We can use 2 since the 2 first values are the same. + extra_bits += [3, 3, 11][(l.dist as usize - 16) & 2]; let val = if l.dist == 16 { - r.len_codes[l.counter as usize - 1] + debug_assert!(l.counter as usize - 1 < r.len_codes.len()); + r.len_codes[(l.counter as usize - 1) & LEN_CODES_MASK] } else { 0 }; - memset( - &mut r.len_codes[ - l.counter as usize..l.counter as usize + extra_bits as usize - ], - val, - ); + let fill_start = l.counter as usize; + let fill_end = l.counter as usize + extra_bits as usize; + debug_assert!(fill_start < r.len_codes.len()); + debug_assert!(fill_end < r.len_codes.len()); + + r.len_codes[ + fill_start & LEN_CODES_MASK..fill_end & LEN_CODES_MASK + ].fill(val); l.counter += extra_bits as u32; Action::Jump(ReadLitlenDistTablesCodeSize) }) }), DecodeLitlen => generate_state!(state, 'state_machine, { - if in_iter.len() < 4 || out_buf.bytes_left() < 2 { + if in_iter.bytes_left() < 4 || out_buf.bytes_left() < 2 { // See if we can decode a literal with the data we have left. // Jumps to next state (WriteSymbol) if successful. decode_huffman_code( @@ -1479,7 +1692,7 @@ // If there is enough space, use the fast inner decompression // function. out_buf.bytes_left() >= 259 && - in_iter.len() >= 14 + in_iter.bytes_left() >= 14 { let (status, new_state) = decompress_fast( r, @@ -1499,7 +1712,7 @@ } else { fill_bit_buffer(&mut l, &mut in_iter); - if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + let (symbol, code_len) = r.tables[LITLEN_TABLE].lookup(l.bit_buf); l.counter = symbol as u32; l.bit_buf >>= code_len; @@ -1515,7 +1728,7 @@ fill_bit_buffer(&mut l, &mut in_iter); } - if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + let (symbol, code_len) = r.tables[LITLEN_TABLE].lookup(l.bit_buf); l.bit_buf >>= code_len; l.num_bits -= code_len; @@ -1531,13 +1744,9 @@ out_buf.write_byte(symbol as u8); Action::None } - } else { - Action::Jump(InvalidCodeLen) - } - } - } else { - Action::Jump(InvalidCodeLen) + } + } }), @@ -1570,7 +1779,7 @@ // We could use get_unchecked later if can statically verify that // this will never go out of bounds. l.num_extra = - u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]; l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]); // Length and distance codes have a number of extra bits depending on // the base, which together with the base gives us the exact value. @@ -1583,7 +1792,7 @@ }), ReadExtraBitsLitlen => generate_state!(state, 'state_machine, { - let num_extra = l.num_extra; + let num_extra = l.num_extra.into(); read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| { l.counter += extra_bits as u32; Action::Jump(DecodeDistance) @@ -1594,16 +1803,19 @@ // Try to read a huffman code from the input buffer and look up what // length code the decoded symbol refers to. decode_huffman_code(r, &mut l, DIST_TABLE, flags, &mut in_iter, |_r, l, symbol| { + // # Optimizaton - transform the value into usize here before the check so + // the compiler can optimize the bounds check later - ideally it should + // know that the value can't be negative from earlier in the + // decode_huffman_code function but it seems it may not be able + // to make the assumption that it can't be negative and thus + // overflow if it's converted after the check. + let symbol = symbol as usize; if symbol > 29 { // Invalid distance code. return Action::Jump(InvalidDist) } - // # Optimization - // Mask the value to avoid bounds checks - // We could use get_unchecked later if can statically verify that - // this will never go out of bounds. - l.num_extra = u32::from(DIST_EXTRA[symbol as usize & BASE_EXTRA_MASK]); - l.dist = u32::from(DIST_BASE[symbol as usize & BASE_EXTRA_MASK]); + l.num_extra = num_extra_bits_for_distance_code(symbol as u8); + l.dist = u32::from(DIST_BASE[symbol]); if l.num_extra != 0 { // ReadEXTRA_BITS_DISTACNE Action::Jump(ReadExtraBitsDistance) @@ -1614,7 +1826,7 @@ }), ReadExtraBitsDistance => generate_state!(state, 'state_machine, { - let num_extra = l.num_extra; + let num_extra = l.num_extra.into(); read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| { l.dist += extra_bits as u32; Action::Jump(HuffDecodeOuterLoop2) @@ -1622,8 +1834,8 @@ }), HuffDecodeOuterLoop2 => generate_state!(state, 'state_machine, { - if l.dist as usize > out_buf.position() && - (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0) + if (l.dist as usize > out_buf.position() && + (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)) || (l.dist as usize > out_buf.get_ref().len()) { // We encountered a distance that refers a position before // the start of the decoded data, so we can't continue. @@ -1690,9 +1902,9 @@ if r.finish != 0 { pad_to_bytes(&mut l, &mut in_iter, flags, |_| Action::None); - let in_consumed = in_buf.len() - in_iter.len(); + let in_consumed = in_buf.len() - in_iter.bytes_left(); let undo = undo_bytes(&mut l, in_consumed as u32) as usize; - in_iter = in_buf[in_consumed - undo..].iter(); + in_iter = InputWrapper::from_slice(in_buf[in_consumed - undo..].iter().as_slice()); l.bit_buf &= ((1 as BitBuffer) << l.num_bits) - 1; debug_assert_eq!(l.num_bits, 0); @@ -1704,7 +1916,16 @@ Action::Jump(DoneForever) } } else { - Action::Jump(ReadBlockHeader) + #[cfg(feature = "block-boundary")] + if flags & TINFL_FLAG_STOP_ON_BLOCK_BOUNDARY != 0 { + Action::End(TINFLStatus::BlockBoundary) + } else { + Action::Jump(ReadBlockHeader) + } + #[cfg(not(feature = "block-boundary"))] + { + Action::Jump(ReadBlockHeader) + } } }), @@ -1745,11 +1966,17 @@ let in_undo = if status != TINFLStatus::NeedsMoreInput && status != TINFLStatus::FailedCannotMakeProgress { - undo_bytes(&mut l, (in_buf.len() - in_iter.len()) as u32) as usize + undo_bytes(&mut l, (in_buf.len() - in_iter.bytes_left()) as u32) as usize } else { 0 }; + // If we're returning after completing a block, prepare for the next block when called again. + #[cfg(feature = "block-boundary")] + if status == TINFLStatus::BlockBoundary { + state = State::ReadBlockHeader; + } + // Make sure HasMoreOutput overrides NeedsMoreInput if the output buffer is full. // (Unless the missing input is the adler32 value in which case we don't need to write anything.) // TODO: May want to see if we can do this in a better way. @@ -1796,7 +2023,7 @@ ( status, - in_buf.len() - in_iter.len() - in_undo, + in_buf.len() - in_iter.bytes_left() - in_undo, out_buf.position() - out_pos, ) } @@ -1831,7 +2058,7 @@ // This should fail with the out buffer being to small. let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], &mut b_buf, flags); - assert_eq!(b_status.0, TINFLStatus::Failed); + assert!(b_status.0 == TINFLStatus::Failed); let flags = flags | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; @@ -1841,7 +2068,7 @@ let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], &mut b_buf, flags); assert_eq!(b_buf[..b_status.2], b"Hello, zlib!"[..]); - assert_eq!(b_status.0, TINFLStatus::Done); + assert!(b_status.0 == TINFLStatus::Done); } #[cfg(feature = "with-alloc")] @@ -1877,7 +2104,7 @@ } fn masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32) { - let ret = table.lookup(bit_buf).unwrap(); + let ret = table.lookup(bit_buf); (ret.0 & 511, ret.1) } @@ -2019,7 +2246,7 @@ // Check that we handle an empty buffer properly and not panicking. // https://github.com/Frommi/miniz_oxide/issues/23 let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags); - assert_eq!(res, (TINFLStatus::HasMoreOutput, 4, 0)); + assert!(res == (TINFLStatus::HasMoreOutput, 4, 0)); } #[test] @@ -2033,6 +2260,59 @@ // Check that we handle an empty buffer properly and not panicking. // https://github.com/Frommi/miniz_oxide/issues/23 let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags); - assert_eq!(res, (TINFLStatus::HasMoreOutput, 2, 0)); + assert!(res == (TINFLStatus::HasMoreOutput, 2, 0)); + } + + #[test] + fn dist_extra_bits() { + use self::num_extra_bits_for_distance_code; + // Number of extra bits for each distance code. + const DIST_EXTRA: [u8; 29] = [ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, + 12, 13, + ]; + + for (i, &dist) in DIST_EXTRA.iter().enumerate() { + assert_eq!(dist, num_extra_bits_for_distance_code(i as u8)); + } + } + + #[test] + fn check_tree() { + let mut r = DecompressorOxide::new(); + let mut l = LocalVars { + bit_buf: 0, + num_bits: 0, + dist: 0, + counter: 0, + num_extra: 0, + }; + + r.code_size_huffman[0] = 1; + r.code_size_huffman[1] = 1; + //r.code_size_huffman[2] = 3; + //r.code_size_huffman[3] = 3; + //r.code_size_huffman[1] = 4; + r.block_type = HUFFLEN_TABLE as u8; + r.table_sizes[HUFFLEN_TABLE] = 4; + let res = init_tree(&mut r, &mut l).unwrap(); + + let status = match res { + Action::Jump(s) => s, + _ => { + //println!("issue"); + return; + } + }; + //println!("status {:?}", status); + assert!(status != BadTotalSymbols); + } + + #[test] + fn reverse_bits_lookup() { + use super::reverse_bits; + for i in 0..512 { + assert_eq!(reverse_bits(i), i.reverse_bits()); + } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,13 +2,14 @@ #[cfg(feature = "with-alloc")] use crate::alloc::{boxed::Box, vec, vec::Vec}; -use ::core::usize; #[cfg(all(feature = "std", feature = "with-alloc"))] use std::error::Error; pub mod core; mod output_buffer; +#[cfg(not(feature = "rustc-dep-of-std"))] pub mod stream; +#[cfg(not(feature = "rustc-dep-of-std"))] use self::core::*; const TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS: i32 = -4; @@ -18,10 +19,13 @@ const TINFL_STATUS_DONE: i32 = 0; const TINFL_STATUS_NEEDS_MORE_INPUT: i32 = 1; const TINFL_STATUS_HAS_MORE_OUTPUT: i32 = 2; +#[cfg(feature = "block-boundary")] +const TINFL_STATUS_BLOCK_BOUNDARY: i32 = 3; /// Return status codes. #[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Hash, Debug))] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum TINFLStatus { /// More input data was expected, but the caller indicated that there was no more data, so the /// input stream is likely truncated. @@ -60,6 +64,18 @@ /// There is still pending data that didn't fit in the output buffer. HasMoreOutput = TINFL_STATUS_HAS_MORE_OUTPUT as i8, + + /// Reached the end of a deflate block, and the start of the next block. + /// + /// At this point, you can suspend decompression and later resume with a new `DecompressorOxide`. + /// The only state that must be preserved is [`DecompressorOxide::block_boundary_state()`], + /// plus the last 32KiB of the output buffer (or less if you know the stream was compressed with + /// a smaller window size). + /// + /// This is only returned if you use the + /// [`TINFL_FLAG_STOP_ON_BLOCK_BOUNDARY`][core::inflate_flags::TINFL_FLAG_STOP_ON_BLOCK_BOUNDARY] flag. + #[cfg(feature = "block-boundary")] + BlockBoundary = TINFL_STATUS_BLOCK_BOUNDARY as i8, } impl TINFLStatus { @@ -73,6 +89,8 @@ TINFL_STATUS_DONE => Some(Done), TINFL_STATUS_NEEDS_MORE_INPUT => Some(NeedsMoreInput), TINFL_STATUS_HAS_MORE_OUTPUT => Some(HasMoreOutput), + #[cfg(feature = "block-boundary")] + TINFL_STATUS_BLOCK_BOUNDARY => Some(BlockBoundary), _ => None, } } @@ -100,6 +118,8 @@ TINFLStatus::Done => "", // Unreachable TINFLStatus::NeedsMoreInput => "Truncated input stream", TINFLStatus::HasMoreOutput => "Output size exceeded the specified limit", + #[cfg(feature = "block-boundary")] + TINFLStatus::BlockBoundary => "Reached end of a deflate block", }) } } @@ -123,7 +143,7 @@ #[inline] #[cfg(feature = "with-alloc")] pub fn decompress_to_vec(input: &[u8]) -> Result, DecompressError> { - decompress_to_vec_inner(input, 0, usize::max_value()) + decompress_to_vec_inner(input, 0, usize::MAX) } /// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector. @@ -139,7 +159,7 @@ decompress_to_vec_inner( input, inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER, - usize::max_value(), + usize::MAX, ) } @@ -241,6 +261,7 @@ /// * `zlib_header` if the first slice out of the iterator is expected to have a /// Zlib header. Otherwise the slices are assumed to be the deflate data only. /// * `ignore_adler32` if the adler32 checksum should be calculated or not. +#[cfg(not(feature = "rustc-dep-of-std"))] pub fn decompress_slice_iter_to_slice<'out, 'inp>( out: &'out mut [u8], it: impl Iterator, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/output_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/output_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/output_buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/output_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -14,12 +14,12 @@ OutputBuffer { slice, position } } - #[inline] + #[inline(always)] pub const fn position(&self) -> usize { self.position } - #[inline] + #[inline(always)] pub fn set_position(&mut self, position: usize) { self.position = position; } @@ -48,13 +48,64 @@ self.slice.len() - self.position } - #[inline] + #[inline(always)] pub const fn get_ref(&self) -> &[u8] { self.slice } - #[inline] + #[inline(always)] pub fn get_mut(&mut self) -> &mut [u8] { self.slice } } + +/// A wrapper for the output slice used when decompressing. +/// +/// Using this rather than `Cursor` lets us implement the writing methods directly on +/// the buffer and lets us use a usize rather than u64 for the position which helps with +/// performance on 32-bit systems. +#[derive(Copy, Clone)] +pub struct InputWrapper<'a> { + slice: &'a [u8], +} + +impl<'a> InputWrapper<'a> { + #[inline(always)] + pub const fn as_slice(&self) -> &[u8] { + self.slice + } + + #[inline(always)] + pub const fn from_slice(slice: &'a [u8]) -> InputWrapper<'a> { + InputWrapper { slice } + } + + #[inline(always)] + pub fn advance(&mut self, steps: usize) { + self.slice = &self.slice[steps..]; + } + + #[inline] + pub fn read_byte(&mut self) -> Option { + self.slice.first().map(|n| { + self.advance(1); + *n + }) + } + + #[inline] + #[cfg(target_pointer_width = "64")] + pub fn read_u32_le(&mut self) -> u32 { + let ret = { + let four_bytes: [u8; 4] = self.slice[..4].try_into().unwrap_or_default(); + u32::from_le_bytes(four_bytes) + }; + self.advance(4); + ret + } + + #[inline(always)] + pub const fn bytes_left(&self) -> usize { + self.slice.len() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/stream.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/stream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/inflate/stream.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/inflate/stream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -57,6 +57,7 @@ /// A struct that compbines a decompressor with extra data for streaming decompression. /// +#[derive(Clone)] pub struct InflateState { /// Inner decompressor struct decomp: DecompressorOxide, @@ -226,6 +227,9 @@ if (flush == MZFlush::Finish) && first_call { decomp_flags |= inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + // The caller is indicating that they want to finish the compression and this is the first call with the current stream + // so we can simply write directly to the output buffer. + // If there is not enough space for all of the decompressed data we will end up with a failure regardless. let status = decompress(&mut state.decomp, next_in, next_out, 0, decomp_flags); let in_bytes = status.1; let out_bytes = status.2; @@ -321,8 +325,12 @@ state.dict_avail = out_bytes; *total_out += push_dict_out(state, next_out); + // Finish was requested but we didn't end on an end block. + if status == TINFLStatus::FailedCannotMakeProgress { + return Err(MZError::Buf); + } // The stream was corrupted, and decompression failed. - if (status as i32) < 0 { + else if (status as i32) < 0 { return Err(MZError::Data); } @@ -420,4 +428,78 @@ // Should still have the checksum read from the header file. assert_eq!(state.decompressor().adler32_header(), Some(459605011)) } + + #[test] + fn test_partial_continue() { + let encoded = [ + 120u8, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, + 19, + ]; + + // Feed input bytes one at a time to the decompressor + let mut out = vec![0; 50]; + let mut state = InflateState::new_boxed(DataFormat::Zlib); + let mut part_in = 0; + let mut part_out = 0; + for i in 1..=encoded.len() { + let res = inflate( + &mut state, + &encoded[part_in..i], + &mut out[part_out..], + MZFlush::None, + ); + let status = res.status.expect("Failed to decompress!"); + if i == encoded.len() { + assert_eq!(status, MZStatus::StreamEnd); + } else { + assert_eq!(status, MZStatus::Ok); + } + part_out += res.bytes_written as usize; + part_in += res.bytes_consumed; + } + + assert_eq!(out[..part_out as usize], b"Hello, zlib!"[..]); + assert_eq!(part_in, encoded.len()); + assert_eq!(state.decompressor().adler32(), Some(459605011)); + } + + // Inflate part of a stream and clone the inflate state. + // Discard the original state and resume the stream from the clone. + #[test] + fn test_rewind_and_resume() { + let encoded = [ + 120u8, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, + 19, + ]; + let decoded = b"Hello, zlib!"; + + // Feed partial input bytes to the decompressor + let mut out = vec![0; 50]; + let mut state = InflateState::new_boxed(DataFormat::Zlib); + let res1 = inflate(&mut state, &encoded[..10], &mut out, MZFlush::None); + let status = res1.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::Ok); + + // Clone the state and discard the original + let mut resume = state.clone(); + drop(state); + + // Resume the stream using the cloned state + let res2 = inflate( + &mut resume, + &encoded[res1.bytes_consumed..], + &mut out[res1.bytes_written..], + MZFlush::Finish, + ); + let status = res2.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::StreamEnd); + + assert_eq!(res1.bytes_consumed + res2.bytes_consumed, encoded.len()); + assert_eq!(res1.bytes_written + res2.bytes_written, decoded.len()); + assert_eq!( + &out[..res1.bytes_written + res2.bytes_written as usize], + decoded + ); + assert_eq!(resume.decompressor().adler32(), Some(459605011)); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -23,7 +23,7 @@ "## )] #![forbid(unsafe_code)] -#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(all(not(feature = "std"), not(feature = "serde")), no_std)] #[cfg(feature = "with-alloc")] extern crate alloc; @@ -31,6 +31,8 @@ #[cfg(feature = "with-alloc")] pub mod deflate; pub mod inflate; +#[cfg(feature = "serde")] +pub mod serde; mod shared; pub use crate::shared::update_adler32 as mz_adler32_oxide; @@ -40,7 +42,8 @@ /// /// See for more in-depth info. #[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Hash, Debug))] pub enum MZFlush { /// Don't force any flushing. /// Used when more input data is expected. @@ -82,7 +85,8 @@ /// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from /// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. #[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Hash, Debug))] pub enum MZStatus { /// Operation succeeded. /// @@ -106,7 +110,8 @@ /// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from /// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. #[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Hash, Debug))] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum MZError { /// Unused ErrNo = -1, @@ -144,7 +149,8 @@ } /// How compressed data is wrapped. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(not(feature = "rustc-dep-of-std"), derive(Hash, Debug))] #[non_exhaustive] pub enum DataFormat { /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format. @@ -156,6 +162,7 @@ Raw, } +#[cfg(not(feature = "rustc-dep-of-std"))] impl DataFormat { pub fn from_window_bits(window_bits: i32) -> DataFormat { if window_bits > 0 { @@ -177,6 +184,7 @@ pub type MZResult = Result; /// A structure containing the result of a call to the inflate or deflate streaming functions. +#[cfg(not(feature = "rustc-dep-of-std"))] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct StreamResult { /// The number of bytes consumed from the input slice. @@ -187,6 +195,7 @@ pub status: MZResult, } +#[cfg(not(feature = "rustc-dep-of-std"))] impl StreamResult { #[inline] pub const fn error(error: MZError) -> StreamResult { @@ -198,12 +207,14 @@ } } +#[cfg(not(feature = "rustc-dep-of-std"))] impl core::convert::From for MZResult { fn from(res: StreamResult) -> Self { res.status } } +#[cfg(not(feature = "rustc-dep-of-std"))] impl core::convert::From<&StreamResult> for MZResult { fn from(res: &StreamResult) -> Self { res.status diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/serde/big_array.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/big_array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/serde/big_array.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/big_array.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor}; +use serde::ser::{Serialize, SerializeTuple, Serializer}; +use std::fmt; +use std::marker::PhantomData; + +pub trait BigArray<'de>: Sized { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer; + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>; +} + +macro_rules! big_array { + ($($len:expr,)+) => { + $( + impl<'de, T> BigArray<'de> for [T; $len] + where T: Default + Copy + Serialize + Deserialize<'de> + { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + let mut seq = serializer.serialize_tuple(self.len())?; + for elem in &self[..] { + seq.serialize_element(elem)?; + } + seq.end() + } + + fn deserialize(deserializer: D) -> Result<[T; $len], D::Error> + where D: Deserializer<'de> + { + struct ArrayVisitor { + element: PhantomData, + } + + impl<'de, T> Visitor<'de> for ArrayVisitor + where T: Default + Copy + Deserialize<'de> + { + type Value = [T; $len]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("an array of length ", $len)) + } + + fn visit_seq(self, mut seq: A) -> Result<[T; $len], A::Error> + where A: SeqAccess<'de> + { + let mut arr = [T::default(); $len]; + for i in 0..$len { + arr[i] = seq.next_element()? + .ok_or_else(|| Error::invalid_length(i, &self))?; + } + Ok(arr) + } + } + + let visitor = ArrayVisitor { element: PhantomData }; + deserializer.deserialize_tuple($len, visitor) + } + } + )+ + } +} + +big_array! { + 288, 512, + 576, 1024, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/serde/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/serde/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/serde/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +pub mod big_array; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/shared.rs clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/shared.rs --- clamav-1.4.3+dfsg/.cargo/vendor/miniz_oxide/src/shared.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/miniz_oxide/src/shared.rs 2006-07-24 01:21:28.000000000 +0000 @@ -11,7 +11,7 @@ #[doc(hidden)] #[cfg(not(feature = "simd"))] pub fn update_adler32(adler: u32, data: &[u8]) -> u32 { - let mut hash = adler::Adler32::from_checksum(adler); + let mut hash = adler2::Adler32::from_checksum(adler); hash.write_slice(data); hash.checksum() } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"33cf1d31d7510756e7a26b072b90a9554dd0b35f9fd21408e542c4524d4cd233",".github/FUNDING.yml":"aad2b3814ead253be4240f2d1b061ecd6113db29763f98b311acafd0284b831b",".github/workflows/build_push.yml":"da722f33e432c7174e4791038cdf6118abc88aaf2c5b7a0599a5cff54a4cb41e",".github/workflows/nightly_fuzzing.yml":"9de559dff08bce62ea55ccd10bb4f36d8caf033ed2961fdf2a19aade40b4003a",".github/workflows/no-response.yml":"a9402b96305e460df442f0783aad91d6a35426ec9fb7f025a762f3f5a1e3e545",".github/workflows/publish_release.yml":"638cb7012b699d35d01474d74ea4b8bb638b1338267434e71ae3024049a83c49","Cargo.lock":"b5b23d474cba83d07bb9b284a4cac120adcd08ed5f0591218bd89f61c04791c7","Cargo.toml":"3249b9483e7ff639b0b21fe5f8647a5de97c1fe0ae580e584ec09334e4570cb8","Cargo.toml.orig":"cf22bd39fc4c4a05b8dbf5197a3ceca80a7aa5c778a985808eb129d5a8997f3b","LICENSE-APACHE.md":"90bf2d659c43045111b65c733ab2a6d4cbcb422a098368c8c58a9ba3db4ed0c5","LICENSE.md":"2aa92cada6431e75615e3fe6cb1a9082c98f777d48ae1c087c0da0e37f7b8bff","README.md":"e35a91bcd3bdd2a0f01ade3b481c38b83e4bdca6dcc960adfd20c4b59d15063e","src/chad.rs":"39fad161ddf6f581561af2b4736832977ba781526778a6153a01435d70eac7e7","src/chromaticity.rs":"f97f4094a0e5cfe02319e122357b347853ca406c0146dd275eb3aa6525d25cfb","src/cicp.rs":"8e2e539a0f3a50118be5c15fc4a64021ce97a3d69c5b74ad6f226c9ec7687e1f","src/conversions/avx/interpolator.rs":"2aa75787e5ee4e355d83a459ff98122b59e6f6c48fd4163b7e34264d2f94cbc5","src/conversions/avx/interpolator_q0_15.rs":"86369df6b2e961c73a57932bd5f0cdc40c8eaff0a8cce34fc7efb2bda9c04188","src/conversions/avx/lut4_to_3.rs":"bab811b632a9b445363f1f7c4af7cb067c3acf844670e7af076aead65a5a8b85","src/conversions/avx/lut4_to_3_q0_15.rs":"aabd319e5ba1a638a97f893a01e91dc5d45a5b930077819fb148db72f215c01b","src/conversions/avx/mod.rs":"f485e65751f302bbf6655e93179363c3811c2ba03b46a58af6b26207cf67e84e","src/conversions/avx/rgb_xyz.rs":"42eabec99b042b95fb635d83b1f2a39373c86a56e86f34ccdc830257d63639ca","src/conversions/avx/rgb_xyz_opt.rs":"873f78631aaf67e4973bdeef66df92fc60aac8584124fbbd3829bfd292af27dc","src/conversions/avx/rgb_xyz_q2_13.rs":"5fb39937338784b05850caa04bc73b2575bd93f947ad0b3742b9f5a60e8e908c","src/conversions/avx/rgb_xyz_q2_13_opt.rs":"d4f302b61362abf46056db38fd384a253b8a1b6219c17fd72d6dfdfa28282b05","src/conversions/avx/t_lut3_to_3.rs":"50f62fdb08b65fc254760c6e66fc59c3e01168a916565cdb5b8572e66a5e720f","src/conversions/avx/t_lut3_to_3_q0_15.rs":"b99149297d841d04037eeacb7835aded140cb9c21c5f25ebfdf44339154f0fd9","src/conversions/avx512/mod.rs":"0d1d91dbfa7b1f0398ac2ab966332969bfb805f855b3bb205ccb704a13651251","src/conversions/avx512/rgb_xyz_opt.rs":"76691d7c13df91ad632654700d557510296fd4c62123ab659530717762a9311e","src/conversions/avx512/rgb_xyz_q2_13_opt.rs":"ecb993210440b3fb07435331dad136c7b044336da132815111edb74cd6f76cc2","src/conversions/bpc.rs":"4f7c1e53ae1e4c45babe6500d67166d516e5e9e43e85ed0f334d89a51d2815d9","src/conversions/gray2rgb.rs":"65bb3c238c38895a2dc1c72639573e46a201969995bcdfafb7e63454e55b23cc","src/conversions/gray2rgb_extended.rs":"e5b7df1ceb833ed99bf7e58bb52dbb630030b645d00852428556f725c40e4f3c","src/conversions/interpolator.rs":"e1cec94c7673af4081d0462a9993b79b52899e56afa7616b073c8c8a714f68b2","src/conversions/katana/finalizers.rs":"5eaae52a3d685cfd7653d6431d047b3dba8b04ad61830f6c05da43df69f8baad","src/conversions/katana/md3x3.rs":"da78b608a2989b4ba60fce2d70643a6810398ff4d5e19f2a778e723bac377206","src/conversions/katana/md4x3.rs":"5e22646ba9e77fc5121db7b762e247dda4184f17c9d02a2d031df3b665aaffc0","src/conversions/katana/md_3xn.rs":"9ab96a00c69446411115c5b0791bb01857772d86a76b6c4d615ab78adde4b0e9","src/conversions/katana/md_nx3.rs":"bf02e4a0a91b9675054d253ac8bc60eab2883ec966728b0758a349723504fc1d","src/conversions/katana/md_pipeline.rs":"f3e5c8cb6d1636ed401e3721bd95af3bf32020d58c930f627b1823a9836cad48","src/conversions/katana/mod.rs":"ecc4fe75b30e89eed5a78020628df0e1bb6703231a24ea8d97f5801640028c90","src/conversions/katana/pcs_stages.rs":"07bc11d242856079b10b2084f8d5291dea3c79544da153de3a94182247773929","src/conversions/katana/rgb_xyz.rs":"e01b22e37ffce2374941e8307f74a40fc747be08bd2b531a9a6982bf36dc3d0e","src/conversions/katana/stages.rs":"663f6576068b7e3940f62ea9ce4aff23e34aa4e529a7ee315d275b49e2db7cae","src/conversions/katana/xyz_lab.rs":"0977cd6d42796740a538b8a0104973c1a792027f83e806622d5d06a6b30260bc","src/conversions/katana/xyz_rgb.rs":"104356b20f35b613f740468b0cab361a5a0d60b1645b195c22d3312771c8b747","src/conversions/lut3x3.rs":"fbea7063c2c012da66df320f0b14c040c1ce618ae0d1a8692bfff535b39b70d5","src/conversions/lut3x4.rs":"e3428178611ae7ff6faee56bfd605f481e23de5cb9221b0cdc6e9efc0a251fef","src/conversions/lut4.rs":"1f1bf5702bcff280b7dd539ea84515a49ba502e75e27f3b8bc79c612921b951b","src/conversions/lut_transforms.rs":"8c6f0d26a74dad07075bc0cf7ddac6a55d62331a6ad6c13fab7de78e8411ea17","src/conversions/mab.rs":"d1747d6d72dfee1dfac1fcf584534a7d9583bdb50d8fdcbbe16ec7c7c70a7571","src/conversions/mab4x3.rs":"24e298187404e76c37c02389ef67567c7368fa3b7b7251a12b361c13fcaeedd9","src/conversions/mba3x4.rs":"7eccc73fbe2660d67253bf43b6eed8e12d83992a06dd7197d3b11a43370f17c5","src/conversions/md_lut.rs":"fb4425ede9bf6dc3054df9fd10c7743b77c088b5bc21a9ad47a3804d9c2c9b83","src/conversions/md_luts_factory.rs":"697de3440407586dcb823c2b2daa5ce01b8d4184f48ee0ea2b14c3b0b58446e6","src/conversions/mod.rs":"5efeb0e4e8c99927b81bbddb14cc6badd027c3bc216630f74fd0ca572c981814","src/conversions/neon/interpolator.rs":"8ed38be5cc6b2778989caf927f5718856f49c074e069342b0ccd332b41a14e6a","src/conversions/neon/interpolator_q0_15.rs":"76cfb2181fb04261a723df7777ce8cf6f15bb0dc1b978e08aca204005ad2b58f","src/conversions/neon/lut4_to_3.rs":"ea57fda6ff94120f449e9d5731d13d2b720a3340624442a71f4b94df38338732","src/conversions/neon/lut4_to_3_q0_15.rs":"02d6cb8436e25af24919418e12da77d29d7a85d31a2b432a43ff35cce64c4fda","src/conversions/neon/mod.rs":"d8606550bb55f468888f7b5f8d29b34eac6e6329034616c5453eea5ae27c50ef","src/conversions/neon/rgb_xyz.rs":"79e5647d0d94a832712f3d76e2599900b88aea29a8c241875c7070c9bf3008a9","src/conversions/neon/rgb_xyz_opt.rs":"c25613ce80cab33a62a48c14e57da5a485cea8dceb8cff32026c2c4854b74e2f","src/conversions/neon/rgb_xyz_q1_30_opt.rs":"543a64f19dc051d869a43ec70d187e371579dcea7cb7b657a8a782908c7a7ac2","src/conversions/neon/rgb_xyz_q2_13.rs":"206e0629c58275eb5afe3a3e9aa4a9177bff642ea0d2ae8b25511a233885316e","src/conversions/neon/rgb_xyz_q2_13_opt.rs":"202fd7482d9662a0c6c3ee2cc0c2928001165c60c8877ee0beb3fa703e1b716c","src/conversions/neon/t_lut3_to_3.rs":"1b6fd449ec5ae0928e9dc6774b1d497788c56ce74a32b7e1e303c7cc505389de","src/conversions/neon/t_lut3_to_3_q0_15.rs":"007e1d90d9f9a46fa3272f548748fe2dec00dfd40c47f7a382d8937fc9ae7d86","src/conversions/prelude_lut_xyz_rgb.rs":"d5266e9affea4262db4c1b221109145f75fc7ec1cc2c7fefd23d8c2dbb160828","src/conversions/rgb2gray.rs":"a981293e963a9c3a1a66972b51efcd86b9892d59814d73ecb240c3805f36ba7f","src/conversions/rgb2gray_extended.rs":"537cc068e9985d8f91b4693ef4c07418ab5340f820345a43785f39567f97d28b","src/conversions/rgb_xyz_factory.rs":"bed0a0f0f2deca097a27a6e6f3c707eacdd1605d955765345078a91b8f7b94a5","src/conversions/rgbxyz.rs":"34f34e93b8372f67f1782bd9962e1baa76c0ca953f65f7b1a2c6d611e82d3f2f","src/conversions/rgbxyz_fixed.rs":"7c7b1879816011657319530e25dbba0e715b603527d175bd636490020ed3cf3d","src/conversions/rgbxyz_float.rs":"3321e755928dab046e91eec28ead313ecce7a3cfbb9b23b0c59bc6bee2ac15d5","src/conversions/sse/interpolator.rs":"1429e33240f938c7255ad3f856b3274ef80bf3d0d85297471c1420972b46378a","src/conversions/sse/interpolator_q0_15.rs":"14a8c0a658a8a065acf8e9941781ed9a92d43ef31eccb04748f31c3038ca71fb","src/conversions/sse/lut4_to_3.rs":"63dacabce2e6a8d8a4f5333380a88245431fc6c08d807689a381a59359e9c9c7","src/conversions/sse/lut4_to_3_q0_15.rs":"ffaa0ae3dfb5e694f8ba7a239ebeb883db5ad466aebdd3425fa04235745b412c","src/conversions/sse/mod.rs":"079822d6c753ba75ae1934c41d6d2964a6863e6ed25546405b6910a123403e6b","src/conversions/sse/rgb_xyz.rs":"50511e7b5094a12f93a8215701999deb60075ce33014e0433f9b1980c4bfd81e","src/conversions/sse/rgb_xyz_opt.rs":"eb3639e1394a6a83b2c425fe6c6d48e746c0f7f4e008e1973d709f6f700e8b28","src/conversions/sse/rgb_xyz_q2_13.rs":"a3cbd25eef7bb8330c7934b1f0092d029620be5aa8072bc855d29e0f7d628a84","src/conversions/sse/rgb_xyz_q2_13_opt.rs":"12dc332dd9b3f1ad0226edca4b38f15dc237bb374f65049acdfc740baca1c019","src/conversions/sse/t_lut3_to_3.rs":"0d9c762a91778a45450893036f301806bacc8050a6ed0a5b349c2b04e27a7d74","src/conversions/sse/t_lut3_to_3_q0_15.rs":"51c8497f82ac9ee871165d95dcf9d14c16dd54c2f54821e25dedb6030659af68","src/conversions/transform_lut3_to_3.rs":"b4152af8de7c648712ba9bcd0b67320c450d775f13760bd016eb87125168c8dc","src/conversions/transform_lut3_to_4.rs":"76c0e2bbe0ff45a0f4a5d7e3790239cd1230b61411ad4dc637ca1cb72eeca0c7","src/conversions/transform_lut4_to_3.rs":"909c52f096355fb37ad92d89f5aa5173b973fea298fd418e0f33891256417693","src/conversions/xyz_lab.rs":"ba56babf48851351890f0d1c6ad557c817052c3a4acd533e805d8e02b1c0a942","src/dat.rs":"faf755124e2093c6e3f5be1fc9eabc04b261cf16d85518942ac9c06864c49926","src/defaults.rs":"a0a14438a37e53ed4d97097149e66d78e33078b96c9f17788bb0a61e6babceff","src/dt_ucs.rs":"a5af6e0a60a13f5aee7956cf89aa0311a770c3e3a8a28e1f650261c242f92940","src/err.rs":"277e1242b1fbdb1bdd79da1f5fff74dd37eee1aeade55180f8eb6f9c5ecd48aa","src/gamma.rs":"deec5a81c82fcedf80da50b3cf2b26cfbf27c315ae848f1405e0bd6bc0bc2d6a","src/gamut.rs":"5741bdc39476f1cfb319558a57d820b9d6405f4dd2da070bde1b8f613c038193","src/helpers.rs":"fd1f64339a140a38e0c1ab1f2e07040dc16aeae865e43b692e9af8175bb4045c","src/ictcp.rs":"816e05a0e8d62076d59a75ad27b5acaf2702c5484a6b63e3d7e29ed04553a8ad","src/jzazbz.rs":"a0b4b9a227263064c1699fcb32f57e95c0e826fd34b17993a9b305e05b42b0da","src/jzczhz.rs":"bc15fc5fa095dc948470b5a9d701d8f4aa25b18f2ca32abcfedc5c82d296d183","src/lab.rs":"578fc6cd1120213c185f85fcd0520fed218f23955252b235aff4ef2c556a5177","src/lib.rs":"7a90c435b312967b341d15d818fed7a9ea45cb1317ac14c969c6267af1b44e16","src/lut_hint.rs":"c8b2caef486dd7ecc48c6c2c5f98c5b6305278795c67d97af55fcc12dbc34e9b","src/luv.rs":"377aef287589ef938d85306a0d90d0dfabcf18220c4c17effca192afa4280c27","src/matan/curve_shape.rs":"0cee38d1ffc4954e869e1ab886c7f4fe32600fe051c7e15a839ab18656ebcccd","src/matan/degeneration.rs":"436bf56643ebacd9ef4544b79085fd6bfed04f20ec775928d8e65b792c404039","src/matan/discontinuity.rs":"f18d47dd3caa86fce10e09d0a39d3de912714e7415cbc2eb5d977cfa85713b59","src/matan/mod.rs":"b1c97e478e2406378f05c532be35a5bcae3f49531c190d2c0139591647076bf0","src/matan/monotonic.rs":"ff28a0d7b1fde3d9f79d59de753fe16418b1378160182face39d1cf7bdb219de","src/matan/slope_limit.rs":"5c53c03a2204d6158a2c3398df2da580d21dfb4fd899c2aac788c81071680cbf","src/math/mod.rs":"8ae6fc36efce4fe760117f585142dbd04e65e8da58d12a445c160a0424f1432e","src/matrix.rs":"cfba8cb3c7f7b204ee85f052cf4b95609aad376ba9f4e81af83ccd9e0241d38d","src/mlaf.rs":"882b04ed0a63c9192518ae3e82a3f11318e9ed6e38144128a435789d8603dbd3","src/nd_array.rs":"b9ee85cf4b417e2125b320d3995629065318735471a80ccdbb44878975a4ee0f","src/oklab.rs":"975a614c7102ba97348baa82280f9ddbf5f33ed6cf631c6de9f5cdbbe1b30ed3","src/oklch.rs":"bf69a60068871f8c9c3951455f9ee0e54eacb1d43808b00fc1ad6f261807cbd0","src/profile.rs":"5380b566fbff6b675b0528fdeca9ebcb973c215e6cccf66b528d32da18a4925c","src/reader.rs":"a2427fbc321c3156bb8a590936ae534266b74532a3cc3d0040d267c6712f3f3b","src/rgb.rs":"9f45ccff02830f478742a50d113570e7f8f793498815d2d1b56a3abd8fbd8816","src/safe_math.rs":"e5d303af3bddb60ad4efe3a62f579974e70d5b123a5385340b3f730b5219f3f2","src/srlab2.rs":"3d63f4e66215e1110bd8c0933fdb45473db6c7c02985e9cdc29413018a1666c1","src/tag.rs":"230ac5476fb5c8e9e707da2eb472885c9be68feca0f0d94fa66286f87df6f431","src/transform.rs":"051bade6cc930dd426ea6be38b0281b17d2b17780d9e038fb70808c69d5d7ba7","src/trc.rs":"b235688af3ad3befd0b0ab2b872704d93d6a5ba794986209bcfe45604df84c64","src/writer.rs":"9c2fb751e8d750a7ed6f87d844e2079d47b79d8e35043a0e79790efe6a1c1347","src/xyy.rs":"693cb9dcd93909391b2e5a09f592a4d2d0ec7b774849337d2189155bba2bc6ec","src/yrg.rs":"7ecd673a3f9a0320abf853d6ed7a6217deb31a1094772404e2d21b39567ba09a"},"package":"ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ce70195bb0f4a911671eea2695f9298d3e77ebe7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: awxkee diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/build_push.yml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/build_push.yml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/build_push.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/build_push.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +name: Build + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - 'master' + - '!ci_test_*' + tags-ignore: + - '*' + pull_request: + branches: + - 'master' + +jobs: + build: + name: Build + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [ "1.85.0", stable ] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + - run: rustup target add aarch64-unknown-linux-gnu x86_64-unknown-linux-gnu i686-unknown-linux-gnu powerpc-unknown-linux-gnu wasm32-unknown-unknown + - run: RUSTFLAGS="-C target-feature=+neon" cargo build --target aarch64-unknown-linux-gnu + - run: RUSTFLAGS="-C target-feature=+neon" cargo build --target aarch64-unknown-linux-gnu --no-default-features + - run: RUSTFLAGS="-C target-feature=+avx2" cargo build --target i686-unknown-linux-gnu + - run: cargo build --target powerpc-unknown-linux-gnu + - run: RUSTFLAGS="-C target-feature=+avx2" cargo build --target x86_64-unknown-linux-gnu + - run: RUSTFLAGS="-C target-feature=+avx2" cargo build --target x86_64-unknown-linux-gnu --no-default-features --features avx + - run: RUSTFLAGS="-C target-feature=+avx2" cargo build --target x86_64-unknown-linux-gnu --no-default-features --features sse + - run: RUSTFLAGS="-C target-feature=+avx2" cargo +nightly build --target x86_64-unknown-linux-gnu --no-default-features --features avx,avx512 + - run: RUSTFLAGS="-C target-feature=+simd128" cargo build --target wasm32-unknown-unknown + + tests_arm: + name: Tests + strategy: + matrix: + features: [ "", neon ] + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo test --no-default-features --features "${{ matrix.features }}" + + tests_x86: + name: Tests + strategy: + matrix: + features: [ "", sse, avx ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo test --no-default-features --features "${{ matrix.features }}" + + clippy_x86: + name: Clippy x86 Stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo clippy --features avx,sse,neon,options -- -D warnings + + clippy_x86_nightly: + name: Clippy x86 Nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: rustup component add clippy + - run: cargo clippy --all-features -- -D warnings + + clippy_arm: + name: Clippy ARM + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo clippy -- -D warnings + + fuzz_arm: + name: Fuzzing ARM + runs-on: macos-latest + strategy: + matrix: + feature: [ neon ] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo install cargo-fuzz + - run: cargo fuzz run unsafe --no-default-features --features ${{ matrix.feature }} -- -max_total_time=10 + - run: cargo fuzz run lut --no-default-features --features ${{ matrix.feature }} -- -max_total_time=12 + + fuzz_x86_64: + name: Fuzzing x86_64 + runs-on: ubuntu-latest + strategy: + matrix: + feature: [ sse, avx ] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo install cargo-fuzz + - run: cargo fuzz run unsafe --no-default-features --features ${{ matrix.feature }} -- -max_total_time=12 + - run: cargo fuzz run lut --no-default-features --features ${{ matrix.feature }} -- -max_total_time=12 + + fuzz_reader: + name: Fuzzing Reader + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo install cargo-fuzz + - run: cargo fuzz run safe_read --no-default-features -- -max_total_time=20 -max_len=512000 + - run: cargo fuzz run safe_read_create --no-default-features -- -max_total_time=20 -max_len=512000 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/nightly_fuzzing.yml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/nightly_fuzzing.yml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/nightly_fuzzing.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/nightly_fuzzing.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +name: Nightly Fuzzing + +on: + schedule: + - cron: '0 2 * * *' # every day at 2:00 UTC + workflow_dispatch: + +jobs: + fuzz_reader: + name: Fuzzing Reader + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo install cargo-fuzz + - run: cargo fuzz run safe_read --no-default-features -- -max_total_time=300 -max_len=512000 + - run: cargo fuzz run safe_read_create --no-default-features -- -max_total_time=300 -max_len=512000 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/no-response.yml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/no-response.yml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/no-response.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/no-response.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +name: no-response + +on: + schedule: + - cron: '0 0 * * *' # Runs daily at midnight + workflow_dispatch: + +jobs: + noResponse: + permissions: + issues: write + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ github.token }} + days-before-stale: -1 + days-before-close: 14 + only-labels: 'waiting for author' + stale-issue-label: 'waiting for author' + stale-pr-label: 'waiting for author' + remove-stale-when-updated: true + ignore-updates: false + close-issue-message: This issue has been automatically closed due to inactivity. We requested additional information but have not received a response from the original author. Without the requested details, we cannot proceed. If you have or find the information needed, please comment so we can reopen the issue. + close-pr-message: This pull request has been automatically closed due to inactivity. We requested additional information but have not received a response from the original author. Without the requested details, we cannot proceed. If you have the needed information or updates, please reopen the PR or comment so we can continue the review. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/publish_release.yml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/publish_release.yml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/.github/workflows/publish_release.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/.github/workflows/publish_release.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +name: Create Release + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + tags: + - '*' + +jobs: + build_and_publish: + name: Build + runs-on: ubuntu-latest + environment: Cargo + steps: + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Make a release + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }} + run: cargo publish --manifest-path Cargo.toml \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,174 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "moxcms" +version = "0.7.11" +dependencies = [ + "num-traits", + "pxfm", + "rand", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +rust-version = "1.85.0" +name = "moxcms" +version = "0.7.11" +authors = ["Radzivon Bartoshyk"] +build = false +exclude = [ + "*.jpg", + "../../assets/*", + "*.png", + "*.icc", + "./assets/*", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Simple Color Management in Rust" +homepage = "https://github.com/awxkee/moxcms" +documentation = "https://github.com/awxkee/moxcms" +readme = "README.md" +keywords = [ + "icc", + "cms", + "color", + "cmyk", +] +categories = ["multimedia::images"] +license = "BSD-3-Clause OR Apache-2.0" +repository = "https://github.com/awxkee/moxcms.git" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +avx = [] +avx512 = [] +default = [ + "avx", + "sse", + "neon", +] +neon = [] +options = [] +sse = [] + +[lib] +name = "moxcms" +path = "src/lib.rs" + +[dependencies.num-traits] +version = "0.2" + +[dependencies.pxfm] +version = "^0.1.1" + +[dev-dependencies.rand] +version = "0.9" + +[profile.profiling] +debug = 2 +inherits = "release" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +workspace = { members = ["app", "fuzz"] } + +[package] +name = "moxcms" +version = "0.7.11" +edition = "2024" +description = "Simple Color Management in Rust" +readme = "./README.md" +keywords = ["icc", "cms", "color", "cmyk"] +license = "BSD-3-Clause OR Apache-2.0" +authors = ["Radzivon Bartoshyk"] +documentation = "https://github.com/awxkee/moxcms" +categories = ["multimedia::images"] +homepage = "https://github.com/awxkee/moxcms" +repository = "https://github.com/awxkee/moxcms.git" +exclude = ["*.jpg", "../../assets/*", "*.png", "*.icc", "./assets/*"] +rust-version = "1.85.0" + +[dependencies] +num-traits = "0.2" +pxfm = "^0.1.1" + +[dev-dependencies] +rand = "0.9" + +[features] +# If no unsafe intrinsics active then `forbid(unsafe)` will be used. +default = ["avx", "sse", "neon"] +# Enables AVX2 acceleration where possible +avx = [] +# Enables SSE4.1 acceleration where possible +sse = [] +# Enables NEON intrinsics where possible +neon = [] +# Enables AVX-512 acceleration where possible. This will work only from 1.89 on stable. +avx512 = [] +# Allows configuring interpolation methods and LUT weights precision. +# Disabled by default to prevent binary bloat. +options = [] + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --no-deps --open --manifest-path ./Cargo.toml +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[profile.profiling] +inherits = "release" +debug = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/LICENSE-APACHE.md clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE-APACHE.md --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/LICENSE-APACHE.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE-APACHE.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Radzivon Bartoshyk + + 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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/LICENSE.md clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE.md --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/LICENSE.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/LICENSE.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright (c) Radzivon Bartoshyk. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/README.md clamav-1.4.6+dfsg/.cargo/vendor/moxcms/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +# Rust ICC Management + +Fast and safe conversion between ICC profiles; in pure Rust. + +Supports CMYK⬌RGBX, RGBX⬌RGBX, RGBX⬌GRAY, LAB⬌RGBX and CMYK⬌LAB, GRAY⬌RGB, any 3/4 color profiles to RGB and vice versa. Also supports almost any to any Display Class ICC profiles up to 16 inks. + +## Example + +```rust +let f_str = "./assets/dci_p3_profile.jpeg"; +let file = File::open(f_str).expect("Failed to open file"); + +let img = image::ImageReader::open(f_str).unwrap().decode().unwrap(); +let rgb = img.to_rgb8(); + +let mut decoder = JpegDecoder::new(BufReader::new(file)).unwrap(); +let icc = decoder.icc_profile().unwrap().unwrap(); +let color_profile = ColorProfile::new_from_slice(&icc).unwrap(); +let dest_profile = ColorProfile::new_srgb(); +let transform = color_profile + .create_transform_8bit(&dest_profile, Layout::Rgb8, TransformOptions::default()) + .unwrap(); +let mut dst = vec![0u8; rgb.len()]; + +for (src, dst) in rgb + .chunks_exact(img.width() as usize * 3) + .zip(dst.chunks_exact_mut(img.dimensions().0 as usize * 3)) +{ + transform + .transform( + &src[..img.dimensions().0 as usize * 3], + &mut dst[..img.dimensions().0 as usize * 3], + ) + .unwrap(); +} +image::save_buffer( + "v1.jpg", + &dst, + img.dimensions().0, + img.dimensions().1, + image::ExtendedColorType::Rgb8, +) + .unwrap(); +``` + +## Benchmarks + +### ICC Transform 8-Bit + +Tests were ran with a 1997×1331 resolution image. + +| Conversion | time(NEON) | Time(AVX2) | +|--------------------|:----------:|:----------:| +| moxcms RGB⮕RGB | 2.68ms | 4.52ms | +| moxcms LUT RGB⮕RGB | 7.18ms | 17.50ms | +| moxcms RGBA⮕RGBA | 2.96ms | 4.83ms | +| moxcms CMYK⮕RGBA | 11.86ms | 27.98ms | +| lcms2 RGB⮕RGB | 13.1ms | 27.73ms | +| lcms2 LUT RGB⮕RGB | 27.60ms | 58.26ms | +| lcms2 RGBA⮕RGBA | 21.97ms | 35.70ms | +| lcms2 CMYK⮕RGBA | 39.71ms | 79.40ms | +| qcms RGB⮕RGB | 6.47ms | 4.59ms | +| qcms LUT RGB⮕RGB | 26.72ms | 60.80ms | +| qcms RGBA⮕RGBA | 6.83ms | 4.99ms | +| qcms CMYK⮕RGBA | 25.97ms | 61.54ms | + +## License + +This project is licensed under either of + +- BSD-3-Clause License (see [LICENSE](LICENSE.md)) +- Apache License, Version 2.0 (see [LICENSE](LICENSE-APACHE.md)) + +at your option. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/chad.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chad.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/chad.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chad.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::matrix::{Matrix3f, Vector3f, Xyz}; +use crate::{Chromaticity, Matrix3d, Vector3d, XyY}; + +pub(crate) const BRADFORD_D: Matrix3d = Matrix3d { + v: [ + [0.8951, 0.2664, -0.1614], + [-0.7502, 1.7135, 0.0367], + [0.0389, -0.0685, 1.0296], + ], +}; + +pub(crate) const BRADFORD_F: Matrix3f = BRADFORD_D.to_f32(); + +#[inline] +pub(crate) const fn compute_chromatic_adaption( + source_white_point: Xyz, + dest_white_point: Xyz, + chad: Matrix3f, +) -> Matrix3f { + let cone_source_xyz = Vector3f { + v: [ + source_white_point.x, + source_white_point.y, + source_white_point.z, + ], + }; + let cone_source_rgb = chad.mul_vector(cone_source_xyz); + + let cone_dest_xyz = Vector3f { + v: [dest_white_point.x, dest_white_point.y, dest_white_point.z], + }; + let cone_dest_rgb = chad.mul_vector(cone_dest_xyz); + + let cone = Matrix3f { + v: [ + [cone_dest_rgb.v[0] / cone_source_rgb.v[0], 0., 0.], + [0., cone_dest_rgb.v[1] / cone_source_rgb.v[1], 0.], + [0., 0., cone_dest_rgb.v[2] / cone_source_rgb.v[2]], + ], + }; + + let chad_inv = chad.inverse(); + + let p0 = cone.mat_mul_const(chad); + chad_inv.mat_mul_const(p0) +} + +#[inline] +pub(crate) const fn compute_chromatic_adaption_d( + source_white_point: Xyz, + dest_white_point: Xyz, + chad: Matrix3d, +) -> Matrix3d { + let cone_source_xyz = Vector3d { + v: [ + source_white_point.x as f64, + source_white_point.y as f64, + source_white_point.z as f64, + ], + }; + let cone_source_rgb = chad.mul_vector(cone_source_xyz); + + let cone_dest_xyz = Vector3d { + v: [ + dest_white_point.x as f64, + dest_white_point.y as f64, + dest_white_point.z as f64, + ], + }; + let cone_dest_rgb = chad.mul_vector(cone_dest_xyz); + + let cone = Matrix3d { + v: [ + [cone_dest_rgb.v[0] / cone_source_rgb.v[0], 0., 0.], + [0., cone_dest_rgb.v[1] / cone_source_rgb.v[1], 0.], + [0., 0., cone_dest_rgb.v[2] / cone_source_rgb.v[2]], + ], + }; + + let chad_inv = chad.inverse(); + + let p0 = cone.mat_mul_const(chad); + chad_inv.mat_mul_const(p0) +} + +pub const fn adaption_matrix(source_illumination: Xyz, target_illumination: Xyz) -> Matrix3f { + compute_chromatic_adaption(source_illumination, target_illumination, BRADFORD_F) +} + +pub const fn adaption_matrix_d(source_illumination: Xyz, target_illumination: Xyz) -> Matrix3d { + compute_chromatic_adaption_d(source_illumination, target_illumination, BRADFORD_D) +} + +pub const fn adapt_to_d50(r: Matrix3f, source_white_pt: XyY) -> Matrix3f { + adapt_to_illuminant(r, source_white_pt, Chromaticity::D50.to_xyz()) +} + +pub const fn adapt_to_d50_d(r: Matrix3d, source_white_pt: XyY) -> Matrix3d { + adapt_to_illuminant_d(r, source_white_pt, Chromaticity::D50.to_xyz()) +} + +pub const fn adapt_to_illuminant( + r: Matrix3f, + source_white_pt: XyY, + illuminant_xyz: Xyz, +) -> Matrix3f { + let bradford = adaption_matrix(source_white_pt.to_xyz(), illuminant_xyz); + bradford.mat_mul_const(r) +} + +pub const fn adapt_to_illuminant_d( + r: Matrix3d, + source_white_pt: XyY, + illuminant_xyz: Xyz, +) -> Matrix3d { + let bradford = adaption_matrix_d(source_white_pt.to_xyz(), illuminant_xyz); + bradford.mat_mul_const(r) +} + +pub const fn adapt_to_illuminant_xyz( + r: Matrix3f, + source_white_pt: Xyz, + illuminant_xyz: Xyz, +) -> Matrix3f { + if source_white_pt.y == 0.0 { + return r; + } + + let bradford = adaption_matrix(source_white_pt, illuminant_xyz); + bradford.mat_mul_const(r) +} + +pub const fn adapt_to_illuminant_xyz_d( + r: Matrix3d, + source_white_pt: Xyz, + illuminant_xyz: Xyz, +) -> Matrix3d { + if source_white_pt.y == 0.0 { + return r; + } + + let bradford = adaption_matrix_d(source_white_pt, illuminant_xyz); + bradford.mat_mul_const(r) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/chromaticity.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chromaticity.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/chromaticity.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/chromaticity.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::{CmsError, XyY, XyYRepresentable, Xyz, Xyzd}; + +#[derive(Clone, Debug, Copy)] +#[repr(C)] +pub struct Chromaticity { + pub x: f32, + pub y: f32, +} + +impl Chromaticity { + #[inline] + pub const fn new(x: f32, y: f32) -> Self { + Self { x, y } + } + + /// Converts this chromaticity (`x`, `y`) to a tristimulus [`Xyz`] value, + /// normalized such that `y = 1.0`. + #[inline] + pub const fn to_xyz(&self) -> Xyz { + let reciprocal = if self.y != 0. { 1. / self.y } else { 0. }; + Xyz { + x: self.x * reciprocal, + y: 1f32, + z: (1f32 - self.x - self.y) * reciprocal, + } + } + + /// Get the color representation with component sum `1`. + /// + /// In contrast to the XYZ representation defined through setting `Y` to a known + /// value (such as `1` in [`Self::to_xyz`]) this representation can be uniquely + /// derived from the `xy` coordinates with no ambiguities. It is scaled from the + /// original XYZ color by diving by `X + Y + Z`. Note that, in particular, this + /// method is well-defined even if the original color had pure chromamatic + /// information with no luminance (Y = `0`) and will preserve that information, + /// whereas [`Self::to_xyz`] is ill-defined and returns an incorrect value. + #[inline] + pub const fn to_scaled_xyzd(&self) -> Xyzd { + let z = 1.0 - self.x as f64 - self.y as f64; + Xyzd::new(self.x as f64, self.y as f64, z) + } + + /// Get the color representation with component sum `1`. + /// + /// In contrast to the XYZ representation defined through setting `Y` to a known + /// value (such as `1` in [`Self::to_xyz`]) this representation can be uniquely + /// derived from the `xy` coordinates with no ambiguities. It is scaled from the + /// original XYZ color by diving by `X + Y + Z`. Note that, in particular, this + /// method is well-defined even if the original color had pure chromamatic + /// information with no luminance (Y = `0`) and will preserve that information, + /// whereas [`Self::to_xyz`] is ill-defined and returns an incorrect value. + #[inline] + pub const fn to_scaled_xyz(&self) -> Xyz { + let z = 1.0 - self.x - self.y; + Xyz::new(self.x, self.y, z) + } + + #[inline] + pub const fn to_xyzd(&self) -> Xyzd { + let reciprocal = if self.y != 0. { 1. / self.y } else { 0. }; + Xyzd { + x: self.x as f64 * reciprocal as f64, + y: 1f64, + z: (1f64 - self.x as f64 - self.y as f64) * reciprocal as f64, + } + } + + #[inline] + pub const fn to_xyyb(&self) -> XyY { + XyY { + x: self.x as f64, + y: self.y as f64, + yb: 1., + } + } + + pub const D65: Chromaticity = Chromaticity { + x: 0.31272, + y: 0.32903, + }; + + pub const D50: Chromaticity = Chromaticity { + x: 0.34567, + y: 0.35850, + }; +} + +impl XyYRepresentable for Chromaticity { + fn to_xyy(self) -> XyY { + self.to_xyyb() + } +} + +impl TryFrom for Chromaticity { + type Error = CmsError; + + #[inline] + fn try_from(xyz: Xyz) -> Result { + let sum = xyz.x + xyz.y + xyz.z; + + // Avoid division by zero or invalid XYZ values + if sum == 0.0 { + return Err(CmsError::DivisionByZero); + } + let rec = 1f32 / sum; + + let chromaticity_x = xyz.x * rec; + let chromaticity_y = xyz.y * rec; + + Ok(Chromaticity { + x: chromaticity_x, + y: chromaticity_y, + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/cicp.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/cicp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/cicp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/cicp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,642 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::gamma::{ + bt1361_to_linear, hlg_to_linear, iec61966_to_linear, log100_sqrt10_to_linear, log100_to_linear, + pq_to_linear, smpte240_to_linear, smpte428_to_linear, +}; +use crate::{ + Chromaticity, ColorProfile, Matrix3d, Matrix3f, XyYRepresentable, + err::CmsError, + trc::{ToneReprCurve, build_trc_table, curve_from_gamma}, +}; +use std::convert::TryFrom; + +/// See [Rec. ITU-T H.273 (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en) Table 2 +/// Values 0, 3, 13–21, 23–255 are all reserved so all map to the same variant +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum CicpColorPrimaries { + /// For future use by ITU-T | ISO/IEC + Reserved, + /// Rec. ITU-R BT.709-6
+ /// Rec. ITU-R BT.1361-0 conventional colour gamut system and extended colour gamut system (historical)
+ /// IEC 61966-2-1 sRGB or sYCC IEC 61966-2-4
+ /// Society of Motion Picture and Television Engineers (MPTE) RP 177 (1993) Annex B
+ Bt709 = 1, + /// Unspecified
+ /// Image characteristics are unknown or are determined by the application. + Unspecified = 2, + /// Rec. ITU-R BT.470-6 System M (historical)
+ /// United States National Television System Committee 1953 Recommendation for transmission standards for color television
+ /// United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
+ Bt470M = 4, + /// Rec. ITU-R BT.470-6 System B, G (historical) Rec. ITU-R BT.601-7 625
+ /// Rec. ITU-R BT.1358-0 625 (historical)
+ /// Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
+ Bt470Bg = 5, + /// Rec. ITU-R BT.601-7 525
+ /// Rec. ITU-R BT.1358-1 525 or 625 (historical) Rec. ITU-R BT.1700-0 NTSC
+ /// SMPTE 170M (2004)
+ /// (functionally the same as the value 7)
+ Bt601 = 6, + /// SMPTE 240M (1999) (historical) (functionally the same as the value 6)
+ Smpte240 = 7, + /// Generic film (colour filters using Illuminant C)
+ GenericFilm = 8, + /// Rec. ITU-R BT.2020-2
+ /// Rec. ITU-R BT.2100-0
+ Bt2020 = 9, + /// SMPTE ST 428-1
+ /// (CIE 1931 XYZ as in ISO 11664-1)
+ Xyz = 10, + /// SMPTE RP 431-2 (2011)
+ Smpte431 = 11, + /// SMPTE EG 432-1 (2010)
+ Smpte432 = 12, + /// EBU Tech. 3213-E (1975)
+ Ebu3213 = 22, +} + +impl TryFrom for CicpColorPrimaries { + type Error = CmsError; + + #[allow(unreachable_patterns)] + fn try_from(value: u8) -> Result { + match value { + // Values 0, 3, 13–21, 23–255 are all reserved so all map to the + // same variant. + 0 | 3 | 13..=21 | 23..=255 => Ok(Self::Reserved), + 1 => Ok(Self::Bt709), + 2 => Ok(Self::Unspecified), + 4 => Ok(Self::Bt470M), + 5 => Ok(Self::Bt470Bg), + 6 => Ok(Self::Bt601), + 7 => Ok(Self::Smpte240), + 8 => Ok(Self::GenericFilm), + 9 => Ok(Self::Bt2020), + 10 => Ok(Self::Xyz), + 11 => Ok(Self::Smpte431), + 12 => Ok(Self::Smpte432), + 22 => Ok(Self::Ebu3213), + _ => Err(CmsError::InvalidCicp), + } + } +} + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct ColorPrimaries { + pub red: Chromaticity, + pub green: Chromaticity, + pub blue: Chromaticity, +} + +/// See [Rec. ITU-T H.273 (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en) Table 2. +impl ColorPrimaries { + /// [ACEScg](https://en.wikipedia.org/wiki/Academy_Color_Encoding_System#ACEScg). + pub const ACES_CG: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.713, y: 0.293 }, + green: Chromaticity { x: 0.165, y: 0.830 }, + blue: Chromaticity { x: 0.128, y: 0.044 }, + }; + + /// [ACES2065-1](https://en.wikipedia.org/wiki/Academy_Color_Encoding_System#ACES2065-1). + pub const ACES_2065_1: ColorPrimaries = ColorPrimaries { + red: Chromaticity { + x: 0.7347, + y: 0.2653, + }, + green: Chromaticity { + x: 0.0000, + y: 1.0000, + }, + blue: Chromaticity { + x: 0.0001, + y: -0.0770, + }, + }; + + /// [Adobe RGB](https://en.wikipedia.org/wiki/Adobe_RGB_color_space) (1998). + pub const ADOBE_RGB: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.64, y: 0.33 }, + green: Chromaticity { x: 0.21, y: 0.71 }, + blue: Chromaticity { x: 0.15, y: 0.06 }, + }; + + /// [DCI P3](https://en.wikipedia.org/wiki/DCI-P3#DCI_P3). + /// + /// This is the same as [`DISPLAY_P3`](Self::DISPLAY_P3), + /// [`SMPTE_431`](Self::SMPTE_431) and [`SMPTE_432`](Self::SMPTE_432). + pub const DCI_P3: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.680, y: 0.320 }, + green: Chromaticity { x: 0.265, y: 0.690 }, + blue: Chromaticity { x: 0.150, y: 0.060 }, + }; + + /// [Diplay P3](https://en.wikipedia.org/wiki/DCI-P3#Display_P3). + /// + /// This is the same as [`DCI_P3`](Self::DCI_P3), + /// [`SMPTE_431`](Self::SMPTE_431) and [`SMPTE_432`](Self::SMPTE_432). + pub const DISPLAY_P3: ColorPrimaries = Self::DCI_P3; + + /// SMPTE RP 431-2 (2011). + /// + /// This is the same as [`DCI_P3`](Self::DCI_P3), + /// [`DISPLAY_P3`](Self::DISPLAY_P3) and [`SMPTE_432`](Self::SMPTE_432). + pub const SMPTE_431: ColorPrimaries = Self::DCI_P3; + + /// SMPTE EG 432-1 (2010). + /// + /// This is the same as [`DCI_P3`](Self::DCI_P3), + /// [`DISPLAY_P3`](Self::DISPLAY_P3) and [`SMPTE_431`](Self::SMPTE_431). + pub const SMPTE_432: ColorPrimaries = Self::DCI_P3; + + /// [ProPhoto RGB](https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space). + pub const PRO_PHOTO_RGB: ColorPrimaries = ColorPrimaries { + red: Chromaticity { + x: 0.734699, + y: 0.265301, + }, + green: Chromaticity { + x: 0.159597, + y: 0.840403, + }, + blue: Chromaticity { + x: 0.036598, + y: 0.000105, + }, + }; + + /// Rec. ITU-R BT.709-6 + /// + /// Rec. ITU-R BT.1361-0 conventional colour gamut system and extended + /// colour gamut system (historical). + /// + /// IEC 61966-2-1 sRGB or sYCC IEC 61966-2-4). + /// + /// Society of Motion Picture and Television Engineers (MPTE) RP 177 (1993) Annex B. + pub const BT_709: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.64, y: 0.33 }, + green: Chromaticity { x: 0.30, y: 0.60 }, + blue: Chromaticity { x: 0.15, y: 0.06 }, + }; + + /// Rec. ITU-R BT.470-6 System M (historical). + /// + /// United States National Television System Committee 1953 Recommendation + /// for transmission standards for color television. + /// + /// United States Federal Communications Commission (2003) Title 47 Code of + /// Federal Regulations 73.682 (a) (20). + pub const BT_470M: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.67, y: 0.33 }, + green: Chromaticity { x: 0.21, y: 0.71 }, + blue: Chromaticity { x: 0.14, y: 0.08 }, + }; + + /// Rec. ITU-R BT.470-6 System B, G (historical) Rec. ITU-R BT.601-7 625. + /// + /// Rec. ITU-R BT.1358-0 625 (historical). + /// Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM. + pub const BT_470BG: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.64, y: 0.33 }, + green: Chromaticity { x: 0.29, y: 0.60 }, + blue: Chromaticity { x: 0.15, y: 0.06 }, + }; + + /// Rec. ITU-R BT.601-7 525. + /// + /// Rec. ITU-R BT.1358-1 525 or 625 (historical) Rec. ITU-R BT.1700-0 NTSC. + /// + /// SMPTE 170M (2004) (functionally the same as the [`SMPTE_240`](Self::SMPTE_240)). + pub const BT_601: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.630, y: 0.340 }, + green: Chromaticity { x: 0.310, y: 0.595 }, + blue: Chromaticity { x: 0.155, y: 0.070 }, + }; + + /// SMPTE 240M (1999) (historical) (functionally the same as [`BT_601`](Self::BT_601)). + pub const SMPTE_240: ColorPrimaries = Self::BT_601; + + /// Generic film (colour filters using Illuminant C). + pub const GENERIC_FILM: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.681, y: 0.319 }, + green: Chromaticity { x: 0.243, y: 0.692 }, + blue: Chromaticity { x: 0.145, y: 0.049 }, + }; + + /// Rec. ITU-R BT.2020-2. + /// + /// Rec. ITU-R BT.2100-0. + pub const BT_2020: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.708, y: 0.292 }, + green: Chromaticity { x: 0.170, y: 0.797 }, + blue: Chromaticity { x: 0.131, y: 0.046 }, + }; + + /// SMPTE ST 428-1 (CIE 1931 XYZ as in ISO 11664-1). + pub const XYZ: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 1.0, y: 0.0 }, + green: Chromaticity { x: 0.0, y: 1.0 }, + blue: Chromaticity { x: 0.0, y: 0.0 }, + }; + + /// EBU Tech. 3213-E (1975). + pub const EBU_3213: ColorPrimaries = ColorPrimaries { + red: Chromaticity { x: 0.630, y: 0.340 }, + green: Chromaticity { x: 0.295, y: 0.605 }, + blue: Chromaticity { x: 0.155, y: 0.077 }, + }; +} + +impl ColorPrimaries { + /// Returns RGB -> XYZ conversion matrix + /// + /// # Arguments + /// + /// * `white_point`: [Chromaticity] or [crate::XyY] or any item conforming [XyYRepresentable] + /// + /// returns: [Matrix3d] + pub fn transform_to_xyz_d(self, white_point: impl XyYRepresentable) -> Matrix3d { + let red_xyz = self.red.to_scaled_xyzd(); + let green_xyz = self.green.to_scaled_xyzd(); + let blue_xyz = self.blue.to_scaled_xyzd(); + + let xyz_matrix = Matrix3d { + v: [ + [red_xyz.x, green_xyz.x, blue_xyz.x], + [red_xyz.y, green_xyz.y, blue_xyz.y], + [red_xyz.z, green_xyz.z, blue_xyz.z], + ], + }; + ColorProfile::rgb_to_xyz_d(xyz_matrix, white_point.to_xyy().to_xyzd()) + } + + /// Returns RGB -> XYZ conversion matrix + /// + /// # Arguments + /// + /// * `white_point`: [Chromaticity] or [crate::XyY] or any item conforming [XyYRepresentable] + /// + /// returns: [Matrix3f] + pub fn transform_to_xyz(self, white_point: impl XyYRepresentable) -> Matrix3f { + let red_xyz = self.red.to_scaled_xyz(); + let green_xyz = self.green.to_scaled_xyz(); + let blue_xyz = self.blue.to_scaled_xyz(); + + let xyz_matrix = Matrix3f { + v: [ + [red_xyz.x, green_xyz.x, blue_xyz.x], + [red_xyz.y, green_xyz.y, blue_xyz.y], + [red_xyz.z, green_xyz.z, blue_xyz.z], + ], + }; + ColorProfile::rgb_to_xyz_static(xyz_matrix, white_point.to_xyy().to_xyz()) + } +} + +/// See [Rec. ITU-T H.273 (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en) Table 3 +/// Values 0, 3, 19–255 are all reserved so all map to the same variant +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum TransferCharacteristics { + /// For future use by ITU-T | ISO/IEC + Reserved, + /// Rec. ITU-R BT.709-6
+ /// Rec. ITU-R BT.1361-0 conventional colour gamut system (historical)
+ /// (functionally the same as the values 6, 14 and 15)
+ Bt709 = 1, + /// Image characteristics are unknown or are determined by the application.
+ Unspecified = 2, + /// Rec. ITU-R BT.470-6 System M (historical)
+ /// United States National Television System Committee 1953 Recommendation for transmission standards for color television
+ /// United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
+ /// Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
+ Bt470M = 4, + /// Rec. ITU-R BT.470-6 System B, G (historical)
+ Bt470Bg = 5, + /// Rec. ITU-R BT.601-7 525 or 625
+ /// Rec. ITU-R BT.1358-1 525 or 625 (historical)
+ /// Rec. ITU-R BT.1700-0 NTSC SMPTE 170M (2004)
+ /// (functionally the same as the values 1, 14 and 15)
+ Bt601 = 6, + /// SMPTE 240M (1999) (historical)
+ Smpte240 = 7, + /// Linear transfer characteristics
+ Linear = 8, + /// Logarithmic transfer characteristic (100:1 range)
+ Log100 = 9, + /// Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range)
+ Log100sqrt10 = 10, + /// IEC 61966-2-4
+ Iec61966 = 11, + /// Rec. ITU-R BT.1361-0 extended colour gamut system (historical)
+ Bt1361 = 12, + /// IEC 61966-2-1 sRGB or sYCC
+ Srgb = 13, + /// Rec. ITU-R BT.2020-2 (10-bit system)
+ /// (functionally the same as the values 1, 6 and 15)
+ Bt202010bit = 14, + /// Rec. ITU-R BT.2020-2 (12-bit system)
+ /// (functionally the same as the values 1, 6 and 14)
+ Bt202012bit = 15, + /// SMPTE ST 2084 for 10-, 12-, 14- and 16-bitsystems
+ /// Rec. ITU-R BT.2100-0 perceptual quantization (PQ) system
+ Smpte2084 = 16, + /// SMPTE ST 428-1
+ Smpte428 = 17, + /// ARIB STD-B67
+ /// Rec. ITU-R BT.2100-0 hybrid log- gamma (HLG) system
+ Hlg = 18, +} + +impl TryFrom for TransferCharacteristics { + type Error = CmsError; + + #[allow(unreachable_patterns)] + fn try_from(value: u8) -> Result { + match value { + 0 | 3 | 19..=255 => Ok(Self::Reserved), + 1 => Ok(Self::Bt709), + 2 => Ok(Self::Unspecified), + 4 => Ok(Self::Bt470M), + 5 => Ok(Self::Bt470Bg), + 6 => Ok(Self::Bt601), + 7 => Ok(Self::Smpte240), // unimplemented + 8 => Ok(Self::Linear), + 9 => Ok(Self::Log100), + 10 => Ok(Self::Log100sqrt10), + 11 => Ok(Self::Iec61966), // unimplemented + 12 => Ok(Self::Bt1361), // unimplemented + 13 => Ok(Self::Srgb), + 14 => Ok(Self::Bt202010bit), + 15 => Ok(Self::Bt202012bit), + 16 => Ok(Self::Smpte2084), + 17 => Ok(Self::Smpte428), // unimplemented + 18 => Ok(Self::Hlg), + _ => Err(CmsError::InvalidCicp), + } + } +} + +impl CicpColorPrimaries { + pub(crate) const fn has_chromaticity(self) -> bool { + self as u8 != Self::Reserved as u8 && self as u8 != Self::Unspecified as u8 + } + + pub(crate) const fn white_point(self) -> Result { + Ok(match self { + Self::Reserved => return Err(CmsError::UnsupportedColorPrimaries(self as u8)), + Self::Bt709 + | Self::Bt470Bg + | Self::Bt601 + | Self::Smpte240 + | Self::Bt2020 + | Self::Smpte432 + | Self::Ebu3213 => Chromaticity::D65, + Self::Unspecified => return Err(CmsError::UnsupportedColorPrimaries(self as u8)), + Self::Bt470M => Chromaticity { x: 0.310, y: 0.316 }, + Self::GenericFilm => Chromaticity { x: 0.310, y: 0.316 }, + Self::Xyz => Chromaticity { + x: 1. / 3., + y: 1. / 3., + }, + Self::Smpte431 => Chromaticity { x: 0.314, y: 0.351 }, + }) + } +} + +impl TryFrom for ColorPrimaries { + type Error = CmsError; + + fn try_from(value: CicpColorPrimaries) -> Result { + match value { + CicpColorPrimaries::Reserved => Err(CmsError::UnsupportedColorPrimaries(value as u8)), + CicpColorPrimaries::Bt709 => Ok(ColorPrimaries::BT_709), + CicpColorPrimaries::Unspecified => { + Err(CmsError::UnsupportedColorPrimaries(value as u8)) + } + CicpColorPrimaries::Bt470M => Ok(ColorPrimaries::BT_470M), + CicpColorPrimaries::Bt470Bg => Ok(ColorPrimaries::BT_470BG), + CicpColorPrimaries::Bt601 | CicpColorPrimaries::Smpte240 => Ok(ColorPrimaries::BT_601), + CicpColorPrimaries::GenericFilm => Ok(ColorPrimaries::GENERIC_FILM), + CicpColorPrimaries::Bt2020 => Ok(ColorPrimaries::BT_2020), + CicpColorPrimaries::Xyz => Ok(ColorPrimaries::XYZ), + // These two share primaries, but have distinct white points + CicpColorPrimaries::Smpte431 | CicpColorPrimaries::Smpte432 => { + Ok(ColorPrimaries::SMPTE_431) + } + CicpColorPrimaries::Ebu3213 => Ok(ColorPrimaries::EBU_3213), + } + } +} + +impl TransferCharacteristics { + pub(crate) fn has_transfer_curve(self) -> bool { + self != Self::Reserved && self != Self::Unspecified + } +} + +pub(crate) fn create_rec709_parametric() -> [f32; 5] { + const POW_EXP: f32 = 0.45; + + const G: f32 = 1. / POW_EXP; + const B: f32 = (0.09929682680944f64 / 1.09929682680944f64) as f32; + const C: f32 = 1f32 / 4.5f32; + const D: f32 = (4.5f64 * 0.018053968510807f64) as f32; + const A: f32 = (1. / 1.09929682680944f64) as f32; + + [G, A, B, C, D] +} + +impl TryFrom for ToneReprCurve { + type Error = CmsError; + /// See [ICC.1:2010](https://www.color.org/specification/ICC1v43_2010-12.pdf) + /// See [Rec. ITU-R BT.2100-2](https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-E.pdf) + fn try_from(value: TransferCharacteristics) -> Result { + const NUM_TRC_TABLE_ENTRIES: i32 = 1024; + + Ok(match value { + TransferCharacteristics::Reserved => { + return Err(CmsError::UnsupportedTrc(value as u8)); + } + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => { + // The opto-electronic transfer characteristic function (OETF) + // as defined in ITU-T H.273 table 3, row 1: + // + // V = (α * Lc^0.45) − (α − 1) for 1 >= Lc >= β + // V = 4.500 * Lc for β > Lc >= 0 + // + // Inverting gives the electro-optical transfer characteristic + // function (EOTF) which can be represented as ICC + // parametricCurveType with 4 parameters (ICC.1:2010 Table 5). + // Converting between the two (Lc ↔︎ Y, V ↔︎ X): + // + // Y = (a * X + b)^g for (X >= d) + // Y = c * X for (X < d) + // + // g, a, b, c, d can then be defined in terms of α and β: + // + // g = 1 / 0.45 + // a = 1 / α + // b = 1 - α + // c = 1 / 4.500 + // d = 4.500 * β + // + // α and β are determined by solving the piecewise equations to + // ensure continuity of both value and slope at the value β. + // We use the values specified for 10-bit systems in + // https://www.itu.int/rec/R-REC-BT.2020-2-201510-I Table 4 + // since this results in the similar values as available ICC + // profiles after converting to s15Fixed16Number, providing us + // good test coverage. + + ToneReprCurve::Parametric(create_rec709_parametric().to_vec()) + } + TransferCharacteristics::Unspecified => { + return Err(CmsError::UnsupportedTrc(value as u8)); + } + TransferCharacteristics::Bt470M => curve_from_gamma(2.2), + TransferCharacteristics::Bt470Bg => curve_from_gamma(2.8), + TransferCharacteristics::Smpte240 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, smpte240_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Linear => curve_from_gamma(1.), + TransferCharacteristics::Log100 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, log100_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Log100sqrt10 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, log100_sqrt10_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Iec61966 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, iec61966_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Bt1361 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, bt1361_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Srgb => { + ToneReprCurve::Parametric(vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]) + } + TransferCharacteristics::Smpte2084 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, pq_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Smpte428 => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, smpte428_to_linear); + ToneReprCurve::Lut(table) + } + TransferCharacteristics::Hlg => { + let table = build_trc_table(NUM_TRC_TABLE_ENTRIES, hlg_to_linear); + ToneReprCurve::Lut(table) + } + }) + } +} + +/// Matrix Coefficients Enum (from ISO/IEC 23091-4 / MPEG CICP) +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C)] +pub enum MatrixCoefficients { + Identity = 0, // RGB (Identity matrix) + Bt709 = 1, // Rec. 709 + Unspecified = 2, // Unspecified + Reserved = 3, // Reserved + Fcc = 4, // FCC + Bt470Bg = 5, // BT.470BG / BT.601-625 + Smpte170m = 6, // SMPTE 170M / BT.601-525 + Smpte240m = 7, // SMPTE 240M + YCgCo = 8, // YCgCo + Bt2020Ncl = 9, // BT.2020 (non-constant luminance) + Bt2020Cl = 10, // BT.2020 (constant luminance) + Smpte2085 = 11, // SMPTE ST 2085 + ChromaticityDerivedNCL = 12, // Chromaticity-derived non-constant luminance + ChromaticityDerivedCL = 13, // Chromaticity-derived constant luminance + ICtCp = 14, // ICtCp +} + +impl TryFrom for MatrixCoefficients { + type Error = CmsError; + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(MatrixCoefficients::Identity), + 1 => Ok(MatrixCoefficients::Bt709), + 2 => Ok(MatrixCoefficients::Unspecified), + 3 => Ok(MatrixCoefficients::Reserved), + 4 => Ok(MatrixCoefficients::Fcc), + 5 => Ok(MatrixCoefficients::Bt470Bg), + 6 => Ok(MatrixCoefficients::Smpte170m), + 7 => Ok(MatrixCoefficients::Smpte240m), + 8 => Ok(MatrixCoefficients::YCgCo), + 9 => Ok(MatrixCoefficients::Bt2020Ncl), + 10 => Ok(MatrixCoefficients::Bt2020Cl), + 11 => Ok(MatrixCoefficients::Smpte2085), + 12 => Ok(MatrixCoefficients::ChromaticityDerivedNCL), + 13 => Ok(MatrixCoefficients::ChromaticityDerivedCL), + 14 => Ok(MatrixCoefficients::ICtCp), + _ => Err(CmsError::InvalidCicp), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::WHITE_POINT_D65; + + #[test] + fn test_to_xyz_using_absolute_coordinates() { + let conversion_matrix = ColorPrimaries::BT_709.transform_to_xyz_d(WHITE_POINT_D65); + assert!((conversion_matrix.v[0][0] - 0.4121524015214193).abs() < 1e-14); + assert!((conversion_matrix.v[1][1] - 0.7153537403945436).abs() < 1e-14); + assert!((conversion_matrix.v[2][2] - 0.9497138466283235).abs() < 1e-14); + } + + #[test] + fn test_to_xyz_using_absolute_coordinates_xyz() { + let conversion_matrix = ColorPrimaries::XYZ.transform_to_xyz_d(WHITE_POINT_D65); + assert!((conversion_matrix.v[0][0] - 0.95015469385536477).abs() < 1e-14); + assert!((conversion_matrix.v[1][1] - 1.0).abs() < 1e-14); + assert!((conversion_matrix.v[2][2] - 1.0882590676722474).abs() < 1e-14); + } + + #[test] + fn test_to_xyz_using_absolute_coordinates_f() { + let conversion_matrix = ColorPrimaries::BT_709.transform_to_xyz(WHITE_POINT_D65); + assert!((conversion_matrix.v[0][0] - 0.4121524015214193).abs() < 1e-5); + assert!((conversion_matrix.v[1][1] - 0.7153537403945436).abs() < 1e-5); + assert!((conversion_matrix.v[2][2] - 0.9497138466283235).abs() < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1037 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::BarycentricWeight; +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use std::arch::x86_64::*; +use std::ops::{Add, Mul, Sub}; + +#[repr(align(16), C)] +pub(crate) struct SseAlignedF32(pub(crate) [f32; 4]); + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralAvxFma {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalAvxFma {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticAvxFma {} + +pub(crate) struct TrilinearAvxFma {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticAvxFmaDouble {} + +pub(crate) struct TrilinearAvxFmaDouble {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidAvxFmaDouble {} + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralAvxFmaDouble {} + +pub(crate) trait AvxMdInterpolationDouble { + fn inter3_sse( + &self, + table0: &[SseAlignedF32], + table1: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorSse, AvxVectorSse); +} + +pub(crate) trait AvxMdInterpolation { + fn inter3_sse( + &self, + table: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> AvxVectorSse; +} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct AvxVectorSse { + pub(crate) v: __m128, +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct AvxVector { + pub(crate) v: __m256, +} + +impl AvxVector { + #[inline(always)] + pub(crate) fn from_sse(lo: AvxVectorSse, hi: AvxVectorSse) -> AvxVector { + unsafe { + AvxVector { + v: _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(lo.v), hi.v), + } + } + } + + #[inline(always)] + pub(crate) fn split(self) -> (AvxVectorSse, AvxVectorSse) { + unsafe { + ( + AvxVectorSse { + v: _mm256_castps256_ps128(self.v), + }, + AvxVectorSse { + v: _mm256_extractf128_ps::<1>(self.v), + }, + ) + } + } +} + +impl From for AvxVectorSse { + #[inline(always)] + fn from(v: f32) -> Self { + AvxVectorSse { + v: unsafe { _mm_set1_ps(v) }, + } + } +} + +impl From for AvxVector { + #[inline(always)] + fn from(v: f32) -> Self { + AvxVector { + v: unsafe { _mm256_set1_ps(v) }, + } + } +} + +impl Sub for AvxVectorSse { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: AvxVectorSse) -> Self::Output { + AvxVectorSse { + v: unsafe { _mm_sub_ps(self.v, rhs.v) }, + } + } +} + +impl Sub for AvxVector { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: AvxVector) -> Self::Output { + AvxVector { + v: unsafe { _mm256_sub_ps(self.v, rhs.v) }, + } + } +} + +impl Add for AvxVectorSse { + type Output = Self; + #[inline(always)] + fn add(self, rhs: AvxVectorSse) -> Self::Output { + AvxVectorSse { + v: unsafe { _mm_add_ps(self.v, rhs.v) }, + } + } +} + +impl Mul for AvxVectorSse { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: AvxVectorSse) -> Self::Output { + AvxVectorSse { + v: unsafe { _mm_mul_ps(self.v, rhs.v) }, + } + } +} + +impl AvxVector { + #[inline(always)] + pub(crate) fn neg_mla(self, b: AvxVector, c: AvxVector) -> Self { + Self { + v: unsafe { _mm256_fnmadd_ps(b.v, c.v, self.v) }, + } + } +} + +impl FusedMultiplyNegAdd for AvxVectorSse { + #[inline(always)] + fn neg_mla(&self, b: AvxVectorSse, c: AvxVectorSse) -> Self { + Self { + v: unsafe { _mm_fnmadd_ps(b.v, c.v, self.v) }, + } + } +} + +impl Add for AvxVector { + type Output = Self; + #[inline(always)] + fn add(self, rhs: AvxVector) -> Self::Output { + AvxVector { + v: unsafe { _mm256_add_ps(self.v, rhs.v) }, + } + } +} + +impl Mul for AvxVector { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: AvxVector) -> Self::Output { + AvxVector { + v: unsafe { _mm256_mul_ps(self.v, rhs.v) }, + } + } +} + +impl FusedMultiplyAdd for AvxVectorSse { + #[inline(always)] + fn mla(&self, b: AvxVectorSse, c: AvxVectorSse) -> AvxVectorSse { + AvxVectorSse { + v: unsafe { _mm_fmadd_ps(b.v, c.v, self.v) }, + } + } +} + +impl FusedMultiplyAdd for AvxVector { + #[inline(always)] + fn mla(&self, b: AvxVector, c: AvxVector) -> AvxVector { + AvxVector { + v: unsafe { _mm256_fmadd_ps(b.v, c.v, self.v) }, + } + } +} + +struct TetrahedralAvxSseFetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [SseAlignedF32], +} + +struct TetrahedralAvxFetchVector<'a, const GRID_SIZE: usize> { + cube0: &'a [SseAlignedF32], + cube1: &'a [SseAlignedF32], +} + +impl Fetcher for TetrahedralAvxFetchVector<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> AvxVector { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx0 = unsafe { self.cube0.get_unchecked(offset..) }; + let jx1 = unsafe { self.cube1.get_unchecked(offset..) }; + AvxVector { + v: unsafe { + _mm256_insertf128_ps::<1>( + _mm256_castps128_ps256(_mm_load_ps(jx0.as_ptr() as *const f32)), + _mm_load_ps(jx1.as_ptr() as *const f32), + ) + }, + } + } +} + +impl Fetcher for TetrahedralAvxSseFetchVector<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> AvxVectorSse { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + AvxVectorSse { + v: unsafe { _mm_load_ps(jx.as_ptr() as *const f32) }, + } + } +} + +#[cfg(feature = "options")] +impl TetrahedralAvxFma { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorSse { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, AvxVectorSse::from(rx)); + let s1 = s0.mla(c2, AvxVectorSse::from(ry)); + s1.mla(c3, AvxVectorSse::from(rz)) + } +} + +macro_rules! define_interp_avx { + ($interpolator: ident) => { + impl AvxMdInterpolation for $interpolator { + fn inter3_sse( + &self, + table: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> AvxVectorSse { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxSseFetchVector:: { cube: table }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +macro_rules! define_interp_avx_d { + ($interpolator: ident) => { + impl AvxMdInterpolationDouble for $interpolator { + fn inter3_sse( + &self, + table0: &[SseAlignedF32], + table1: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorSse, AvxVectorSse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxSseFetchVector:: { cube: table0 }, + TetrahedralAvxSseFetchVector:: { cube: table1 }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +define_interp_avx!(TetrahedralAvxFma); +#[cfg(feature = "options")] +define_interp_avx!(PyramidalAvxFma); +#[cfg(feature = "options")] +define_interp_avx!(PrismaticAvxFma); +define_interp_avx!(TrilinearAvxFma); +#[cfg(feature = "options")] +define_interp_avx_d!(PrismaticAvxFmaDouble); +#[cfg(feature = "options")] +define_interp_avx_d!(PyramidAvxFmaDouble); + +#[cfg(feature = "options")] +impl AvxMdInterpolationDouble for TetrahedralAvxFmaDouble { + fn inter3_sse( + &self, + table0: &[SseAlignedF32], + table1: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorSse, AvxVectorSse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxFetchVector:: { + cube0: table0, + cube1: table1, + }, + ) + } + } +} + +impl AvxMdInterpolationDouble for TrilinearAvxFmaDouble { + fn inter3_sse( + &self, + table0: &[SseAlignedF32], + table1: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorSse, AvxVectorSse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxFetchVector:: { + cube0: table0, + cube1: table1, + }, + ) + } + } +} + +#[cfg(feature = "options")] +impl PyramidalAvxFma { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorSse { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = AvxVectorSse::from(db); + let w1 = AvxVectorSse::from(dr); + let w2 = AvxVectorSse::from(dg); + + if dr > db && dg > db { + let w3 = AvxVectorSse::from(dr * dg); + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else if db > dr && dg > dr { + let w3 = AvxVectorSse::from(dg * db); + + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else { + let w3 = AvxVectorSse::from(db * dr); + + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticAvxFma { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorSse { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = AvxVectorSse::from(db); + let w1 = AvxVectorSse::from(dr); + let w2 = AvxVectorSse::from(dg); + let w3 = AvxVectorSse::from(dg * db); + let w4 = AvxVectorSse::from(dr * dg); + + if db > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticAvxFmaDouble { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r0: impl Fetcher, + r1: impl Fetcher, + ) -> (AvxVectorSse, AvxVectorSse) { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0_0 = r0.fetch(x, y, z); + let c0_1 = r0.fetch(x, y, z); + + let w0 = AvxVector::from(db); + let w1 = AvxVector::from(dr); + let w2 = AvxVector::from(dg); + let w3 = AvxVector::from(dg * db); + let w4 = AvxVector::from(dr * dg); + + let c0 = AvxVector::from_sse(c0_0, c0_1); + + if db > dr { + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y, z_n); + let x2_0 = r0.fetch(x, y_n, z); + let x3_0 = r0.fetch(x, y_n, z_n); + let x4_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y, z_n); + let x2_1 = r1.fetch(x, y_n, z); + let x3_1 = r1.fetch(x, y_n, z_n); + let x4_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVector::from_sse(x0_0, x0_1); + let x1 = AvxVector::from_sse(x1_0, x1_1); + let x2 = AvxVector::from_sse(x2_0, x2_1); + let x3 = AvxVector::from_sse(x3_0, x3_1); + let x4 = AvxVector::from_sse(x4_0, x4_1); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } else { + let x0_0 = r0.fetch(x_n, y, z); + let x1_0 = r0.fetch(x_n, y, z_n); + let x2_0 = r0.fetch(x, y_n, z); + let x3_0 = r0.fetch(x_n, y_n, z); + let x4_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x_n, y, z); + let x1_1 = r1.fetch(x_n, y, z_n); + let x2_1 = r1.fetch(x, y_n, z); + let x3_1 = r1.fetch(x_n, y_n, z); + let x4_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVector::from_sse(x0_0, x0_1); + let x1 = AvxVector::from_sse(x1_0, x1_1); + let x2 = AvxVector::from_sse(x2_0, x2_1); + let x3 = AvxVector::from_sse(x3_0, x3_1); + let x4 = AvxVector::from_sse(x4_0, x4_1); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } + } +} + +#[cfg(feature = "options")] +impl PyramidAvxFmaDouble { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r0: impl Fetcher, + r1: impl Fetcher, + ) -> (AvxVectorSse, AvxVectorSse) { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0_0 = r0.fetch(x, y, z); + let c0_1 = r1.fetch(x, y, z); + + let w0 = AvxVector::from(db); + let w1 = AvxVector::from(dr); + let w2 = AvxVector::from(dg); + + let c0 = AvxVector::from_sse(c0_0, c0_1); + + if dr > db && dg > db { + let w3 = AvxVector::from(dr * dg); + + let x0_0 = r0.fetch(x_n, y_n, z_n); + let x1_0 = r0.fetch(x_n, y_n, z); + let x2_0 = r0.fetch(x_n, y, z); + let x3_0 = r0.fetch(x, y_n, z); + + let x0_1 = r1.fetch(x_n, y_n, z_n); + let x1_1 = r1.fetch(x_n, y_n, z); + let x2_1 = r1.fetch(x_n, y, z); + let x3_1 = r1.fetch(x, y_n, z); + + let x0 = AvxVector::from_sse(x0_0, x0_1); + let x1 = AvxVector::from_sse(x1_0, x1_1); + let x2 = AvxVector::from_sse(x2_0, x2_1); + let x3 = AvxVector::from_sse(x3_0, x3_1); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else if db > dr && dg > dr { + let w3 = AvxVector::from(dg * db); + + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y_n, z_n); + let x2_0 = r0.fetch(x, y_n, z_n); + let x3_0 = r0.fetch(x, y_n, z); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y_n, z_n); + let x2_1 = r1.fetch(x, y_n, z_n); + let x3_1 = r1.fetch(x, y_n, z); + + let x0 = AvxVector::from_sse(x0_0, x0_1); + let x1 = AvxVector::from_sse(x1_0, x1_1); + let x2 = AvxVector::from_sse(x2_0, x2_1); + let x3 = AvxVector::from_sse(x3_0, x3_1); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else { + let w3 = AvxVector::from(db * dr); + + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y, z); + let x2_0 = r0.fetch(x_n, y, z_n); + let x3_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y, z); + let x2_1 = r1.fetch(x_n, y, z_n); + let x3_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVector::from_sse(x0_0, x0_1); + let x1 = AvxVector::from_sse(x1_0, x1_1); + let x2 = AvxVector::from_sse(x2_0, x2_1); + let x3 = AvxVector::from_sse(x3_0, x3_1); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } + } +} + +#[cfg(feature = "options")] +impl TetrahedralAvxFmaDouble { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (AvxVectorSse, AvxVectorSse) { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = rv.fetch(x, y, z); + + let w0 = AvxVector::from(rx); + let w1 = AvxVector::from(ry); + let w2 = AvxVector::from(rz); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = rv.fetch(x_n, y, z) - c0; + c2 = rv.fetch(x_n, y_n, z) - rv.fetch(x_n, y, z); + c3 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = rv.fetch(x_n, y, z) - c0; + c2 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y, z_n); + c3 = rv.fetch(x_n, y, z_n) - rv.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = rv.fetch(x_n, y, z_n) - rv.fetch(x, y, z_n); + c2 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y, z_n); + c3 = rv.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = rv.fetch(x_n, y_n, z) - rv.fetch(x, y_n, z); + c2 = rv.fetch(x, y_n, z) - c0; + c3 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x, y_n, z_n); + c2 = rv.fetch(x, y_n, z) - c0; + c3 = rv.fetch(x, y_n, z_n) - rv.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x, y_n, z_n); + c2 = rv.fetch(x, y_n, z_n) - rv.fetch(x, y, z_n); + c3 = rv.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + s1.mla(c3, w2).split() + } +} + +impl TrilinearAvxFmaDouble { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (AvxVectorSse, AvxVectorSse) { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let w0 = AvxVector::from(rx); + let w1 = AvxVector::from(ry); + let w2 = AvxVector::from(rz); + + let c000 = rv.fetch(x, y, z); + let c100 = rv.fetch(x_n, y, z); + let c010 = rv.fetch(x, y_n, z); + let c110 = rv.fetch(x_n, y_n, z); + let c001 = rv.fetch(x, y, z_n); + let c101 = rv.fetch(x_n, y, z_n); + let c011 = rv.fetch(x, y_n, z_n); + let c111 = rv.fetch(x_n, y_n, z_n); + + let dx = AvxVector::from(rx); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = AvxVector::from(ry); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = AvxVector::from(rz); + + c0.neg_mla(c0, dz).mla(c1, w2).split() + } +} + +impl TrilinearAvxFma { + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorSse { + let lut_r = unsafe { lut.get_unchecked(in_r) }; + let lut_g = unsafe { lut.get_unchecked(in_g) }; + let lut_b = unsafe { lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = AvxVector::from(dr); + let w1 = AvxVector::from(dg); + let w2 = AvxVectorSse::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let x000 = AvxVector::from_sse(c000, c001); + let x010 = AvxVector::from_sse(c010, c011); + let x011 = AvxVector::from_sse(c100, c101); + let x111 = AvxVector::from_sse(c110, c111); + + let c00 = x000.neg_mla(x000, w0).mla(x011, w0); + let c10 = x010.neg_mla(x010, w0).mla(x111, w0); + + let z0 = c00.neg_mla(c00, w1).mla(c10, w1); + + let (c0, c1) = z0.split(); + + c0.neg_mla(c0, w2).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/interpolator_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1030 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::BarycentricWeight; +use crate::math::FusedMultiplyAdd; +use std::arch::x86_64::*; +use std::ops::{Add, Mul, Sub}; + +#[repr(align(8), C)] +pub(crate) struct AvxAlignedI16(pub(crate) [i16; 4]); + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralAvxQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalAvxQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticAvxQ0_15 {} + +pub(crate) struct TrilinearAvxQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticAvxQ0_15Double {} + +pub(crate) struct TrilinearAvxQ0_15Double {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidAvxFmaQ0_15Double {} + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralAvxQ0_15Double {} + +pub(crate) trait AvxMdInterpolationQ0_15Double { + fn inter3_sse( + &self, + table0: &[AvxAlignedI16], + table1: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse); +} + +pub(crate) trait AvxMdInterpolationQ0_15 { + fn inter3_sse( + &self, + table: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> AvxVectorQ0_15Sse; +} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct AvxVectorQ0_15Sse { + pub(crate) v: __m128i, +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct AvxVectorQ0_15 { + pub(crate) v: __m256i, +} + +impl AvxVectorQ0_15 { + #[inline(always)] + pub(crate) fn from_sse(lo: AvxVectorQ0_15Sse, hi: AvxVectorQ0_15Sse) -> AvxVectorQ0_15 { + unsafe { + AvxVectorQ0_15 { + v: _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(lo.v), hi.v), + } + } + } + + #[inline(always)] + pub(crate) fn split(self) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + unsafe { + ( + AvxVectorQ0_15Sse { + v: _mm256_castsi256_si128(self.v), + }, + AvxVectorQ0_15Sse { + v: _mm256_extracti128_si256::<1>(self.v), + }, + ) + } + } +} + +impl From for AvxVectorQ0_15Sse { + #[inline(always)] + fn from(v: i16) -> Self { + AvxVectorQ0_15Sse { + v: unsafe { _mm_set1_epi16(v) }, + } + } +} + +impl From for AvxVectorQ0_15 { + #[inline(always)] + fn from(v: i16) -> Self { + AvxVectorQ0_15 { + v: unsafe { _mm256_set1_epi16(v) }, + } + } +} + +impl Sub for AvxVectorQ0_15Sse { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: AvxVectorQ0_15Sse) -> Self::Output { + AvxVectorQ0_15Sse { + v: unsafe { _mm_sub_epi16(self.v, rhs.v) }, + } + } +} + +impl Sub for AvxVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: AvxVectorQ0_15) -> Self::Output { + AvxVectorQ0_15 { + v: unsafe { _mm256_sub_epi16(self.v, rhs.v) }, + } + } +} + +impl Add for AvxVectorQ0_15Sse { + type Output = Self; + #[inline(always)] + fn add(self, rhs: AvxVectorQ0_15Sse) -> Self::Output { + AvxVectorQ0_15Sse { + v: unsafe { _mm_add_epi16(self.v, rhs.v) }, + } + } +} + +impl Mul for AvxVectorQ0_15Sse { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: AvxVectorQ0_15Sse) -> Self::Output { + AvxVectorQ0_15Sse { + v: unsafe { _mm_mulhrs_epi16(self.v, rhs.v) }, + } + } +} + +impl Add for AvxVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn add(self, rhs: AvxVectorQ0_15) -> Self::Output { + AvxVectorQ0_15 { + v: unsafe { _mm256_add_epi16(self.v, rhs.v) }, + } + } +} + +impl Mul for AvxVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: AvxVectorQ0_15) -> Self::Output { + AvxVectorQ0_15 { + v: unsafe { _mm256_mulhrs_epi16(self.v, rhs.v) }, + } + } +} + +impl FusedMultiplyAdd for AvxVectorQ0_15Sse { + #[inline(always)] + fn mla(&self, b: AvxVectorQ0_15Sse, c: AvxVectorQ0_15Sse) -> AvxVectorQ0_15Sse { + AvxVectorQ0_15Sse { + v: unsafe { _mm_add_epi16(_mm_mulhrs_epi16(b.v, c.v), self.v) }, + } + } +} + +impl FusedMultiplyAdd for AvxVectorQ0_15 { + #[inline(always)] + fn mla(&self, b: AvxVectorQ0_15, c: AvxVectorQ0_15) -> AvxVectorQ0_15 { + AvxVectorQ0_15 { + v: unsafe { _mm256_add_epi16(_mm256_mulhrs_epi16(b.v, c.v), self.v) }, + } + } +} + +struct TetrahedralAvxSseFetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [AvxAlignedI16], +} + +struct TetrahedralAvxFetchVector<'a, const GRID_SIZE: usize> { + cube0: &'a [AvxAlignedI16], + cube1: &'a [AvxAlignedI16], +} + +impl Fetcher for TetrahedralAvxFetchVector<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> AvxVectorQ0_15 { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx0 = unsafe { self.cube0.get_unchecked(offset..) }; + let jx1 = unsafe { self.cube1.get_unchecked(offset..) }; + AvxVectorQ0_15 { + v: unsafe { + _mm256_inserti128_si256::<1>( + _mm256_castsi128_si256(_mm_loadu_si64(jx0.as_ptr() as *const _)), + _mm_loadu_si64(jx1.as_ptr() as *const _), + ) + }, + } + } +} + +impl Fetcher + for TetrahedralAvxSseFetchVector<'_, GRID_SIZE> +{ + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> AvxVectorQ0_15Sse { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + AvxVectorQ0_15Sse { + v: unsafe { _mm_loadu_si64(jx.as_ptr() as *const _) }, + } + } +} + +#[cfg(feature = "options")] +impl TetrahedralAvxQ0_15 { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorQ0_15Sse { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, AvxVectorQ0_15Sse::from(rx)); + let s1 = s0.mla(c2, AvxVectorQ0_15Sse::from(ry)); + s1.mla(c3, AvxVectorQ0_15Sse::from(rz)) + } +} + +macro_rules! define_interp_avx { + ($interpolator: ident) => { + impl AvxMdInterpolationQ0_15 for $interpolator { + fn inter3_sse( + &self, + table: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> AvxVectorQ0_15Sse { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxSseFetchVector:: { cube: table }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +macro_rules! define_interp_avx_d { + ($interpolator: ident) => { + impl AvxMdInterpolationQ0_15Double for $interpolator { + fn inter3_sse( + &self, + table0: &[AvxAlignedI16], + table1: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxSseFetchVector:: { cube: table0 }, + TetrahedralAvxSseFetchVector:: { cube: table1 }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +define_interp_avx!(TetrahedralAvxQ0_15); +#[cfg(feature = "options")] +define_interp_avx!(PyramidalAvxQ0_15); +#[cfg(feature = "options")] +define_interp_avx!(PrismaticAvxQ0_15); +define_interp_avx!(TrilinearAvxQ0_15); +#[cfg(feature = "options")] +define_interp_avx_d!(PrismaticAvxQ0_15Double); +#[cfg(feature = "options")] +define_interp_avx_d!(PyramidAvxFmaQ0_15Double); + +#[cfg(feature = "options")] +impl AvxMdInterpolationQ0_15Double + for TetrahedralAvxQ0_15Double +{ + fn inter3_sse( + &self, + table0: &[AvxAlignedI16], + table1: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxFetchVector:: { + cube0: table0, + cube1: table1, + }, + ) + } + } +} + +impl AvxMdInterpolationQ0_15Double for TrilinearAvxQ0_15Double { + fn inter3_sse( + &self, + table0: &[AvxAlignedI16], + table1: &[AvxAlignedI16], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralAvxFetchVector:: { + cube0: table0, + cube1: table1, + }, + ) + } + } +} + +#[cfg(feature = "options")] +impl PyramidalAvxQ0_15 { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorQ0_15Sse { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = AvxVectorQ0_15Sse::from(db); + let w1 = AvxVectorQ0_15Sse::from(dr); + let w2 = AvxVectorQ0_15Sse::from(dg); + + if dr > db && dg > db { + let w3 = AvxVectorQ0_15Sse::from(dr) * AvxVectorQ0_15Sse::from(dg); + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else if db > dr && dg > dr { + let w3 = AvxVectorQ0_15Sse::from(dg) * AvxVectorQ0_15Sse::from(db); + + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else { + let w3 = AvxVectorQ0_15Sse::from(db) * AvxVectorQ0_15Sse::from(dr); + + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticAvxQ0_15 { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorQ0_15Sse { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = AvxVectorQ0_15Sse::from(db); + let w1 = AvxVectorQ0_15Sse::from(dr); + let w2 = AvxVectorQ0_15Sse::from(dg); + let w3 = AvxVectorQ0_15Sse::from(dg) * AvxVectorQ0_15Sse::from(db); + let w4 = AvxVectorQ0_15Sse::from(dr) * AvxVectorQ0_15Sse::from(dg); + + if db > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticAvxQ0_15Double { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r0: impl Fetcher, + r1: impl Fetcher, + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0_0 = r0.fetch(x, y, z); + let c0_1 = r0.fetch(x, y, z); + + let w0 = AvxVectorQ0_15::from(db); + let w1 = AvxVectorQ0_15::from(dr); + let w2 = AvxVectorQ0_15::from(dg); + let w3 = AvxVectorQ0_15::from(dg) * AvxVectorQ0_15::from(db); + let w4 = AvxVectorQ0_15::from(dr) * AvxVectorQ0_15::from(dg); + + let c0 = AvxVectorQ0_15::from_sse(c0_0, c0_1); + + if db > dr { + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y, z_n); + let x2_0 = r0.fetch(x, y_n, z); + let x3_0 = r0.fetch(x, y_n, z_n); + let x4_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y, z_n); + let x2_1 = r1.fetch(x, y_n, z); + let x3_1 = r1.fetch(x, y_n, z_n); + let x4_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVectorQ0_15::from_sse(x0_0, x0_1); + let x1 = AvxVectorQ0_15::from_sse(x1_0, x1_1); + let x2 = AvxVectorQ0_15::from_sse(x2_0, x2_1); + let x3 = AvxVectorQ0_15::from_sse(x3_0, x3_1); + let x4 = AvxVectorQ0_15::from_sse(x4_0, x4_1); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } else { + let x0_0 = r0.fetch(x_n, y, z); + let x1_0 = r0.fetch(x_n, y, z_n); + let x2_0 = r0.fetch(x, y_n, z); + let x3_0 = r0.fetch(x_n, y_n, z); + let x4_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x_n, y, z); + let x1_1 = r1.fetch(x_n, y, z_n); + let x2_1 = r1.fetch(x, y_n, z); + let x3_1 = r1.fetch(x_n, y_n, z); + let x4_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVectorQ0_15::from_sse(x0_0, x0_1); + let x1 = AvxVectorQ0_15::from_sse(x1_0, x1_1); + let x2 = AvxVectorQ0_15::from_sse(x2_0, x2_1); + let x3 = AvxVectorQ0_15::from_sse(x3_0, x3_1); + let x4 = AvxVectorQ0_15::from_sse(x4_0, x4_1); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } + } +} + +#[cfg(feature = "options")] +impl PyramidAvxFmaQ0_15Double { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r0: impl Fetcher, + r1: impl Fetcher, + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0_0 = r0.fetch(x, y, z); + let c0_1 = r1.fetch(x, y, z); + + let w0 = AvxVectorQ0_15::from(db); + let w1 = AvxVectorQ0_15::from(dr); + let w2 = AvxVectorQ0_15::from(dg); + + let c0 = AvxVectorQ0_15::from_sse(c0_0, c0_1); + + if dr > db && dg > db { + let w3 = AvxVectorQ0_15::from(dr) * AvxVectorQ0_15::from(dg); + + let x0_0 = r0.fetch(x_n, y_n, z_n); + let x1_0 = r0.fetch(x_n, y_n, z); + let x2_0 = r0.fetch(x_n, y, z); + let x3_0 = r0.fetch(x, y_n, z); + + let x0_1 = r1.fetch(x_n, y_n, z_n); + let x1_1 = r1.fetch(x_n, y_n, z); + let x2_1 = r1.fetch(x_n, y, z); + let x3_1 = r1.fetch(x, y_n, z); + + let x0 = AvxVectorQ0_15::from_sse(x0_0, x0_1); + let x1 = AvxVectorQ0_15::from_sse(x1_0, x1_1); + let x2 = AvxVectorQ0_15::from_sse(x2_0, x2_1); + let x3 = AvxVectorQ0_15::from_sse(x3_0, x3_1); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else if db > dr && dg > dr { + let w3 = AvxVectorQ0_15::from(dg) * AvxVectorQ0_15::from(db); + + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y_n, z_n); + let x2_0 = r0.fetch(x, y_n, z_n); + let x3_0 = r0.fetch(x, y_n, z); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y_n, z_n); + let x2_1 = r1.fetch(x, y_n, z_n); + let x3_1 = r1.fetch(x, y_n, z); + + let x0 = AvxVectorQ0_15::from_sse(x0_0, x0_1); + let x1 = AvxVectorQ0_15::from_sse(x1_0, x1_1); + let x2 = AvxVectorQ0_15::from_sse(x2_0, x2_1); + let x3 = AvxVectorQ0_15::from_sse(x3_0, x3_1); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else { + let w3 = AvxVectorQ0_15::from(db) * AvxVectorQ0_15::from(dr); + + let x0_0 = r0.fetch(x, y, z_n); + let x1_0 = r0.fetch(x_n, y, z); + let x2_0 = r0.fetch(x_n, y, z_n); + let x3_0 = r0.fetch(x_n, y_n, z_n); + + let x0_1 = r1.fetch(x, y, z_n); + let x1_1 = r1.fetch(x_n, y, z); + let x2_1 = r1.fetch(x_n, y, z_n); + let x3_1 = r1.fetch(x_n, y_n, z_n); + + let x0 = AvxVectorQ0_15::from_sse(x0_0, x0_1); + let x1 = AvxVectorQ0_15::from_sse(x1_0, x1_1); + let x2 = AvxVectorQ0_15::from_sse(x2_0, x2_1); + let x3 = AvxVectorQ0_15::from_sse(x3_0, x3_1); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } + } +} + +#[cfg(feature = "options")] +impl TetrahedralAvxQ0_15Double { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = rv.fetch(x, y, z); + + let w0 = AvxVectorQ0_15::from(rx); + let w1 = AvxVectorQ0_15::from(ry); + let w2 = AvxVectorQ0_15::from(rz); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = rv.fetch(x_n, y, z) - c0; + c2 = rv.fetch(x_n, y_n, z) - rv.fetch(x_n, y, z); + c3 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = rv.fetch(x_n, y, z) - c0; + c2 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y, z_n); + c3 = rv.fetch(x_n, y, z_n) - rv.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = rv.fetch(x_n, y, z_n) - rv.fetch(x, y, z_n); + c2 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y, z_n); + c3 = rv.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = rv.fetch(x_n, y_n, z) - rv.fetch(x, y_n, z); + c2 = rv.fetch(x, y_n, z) - c0; + c3 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x, y_n, z_n); + c2 = rv.fetch(x, y_n, z) - c0; + c3 = rv.fetch(x, y_n, z_n) - rv.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = rv.fetch(x_n, y_n, z_n) - rv.fetch(x, y_n, z_n); + c2 = rv.fetch(x, y_n, z_n) - rv.fetch(x, y, z_n); + c3 = rv.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + s1.mla(c3, w2).split() + } +} + +impl TrilinearAvxQ0_15Double { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (AvxVectorQ0_15Sse, AvxVectorQ0_15Sse) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + const Q_MAX: i16 = ((1i32 << 15i32) - 1) as i16; + + let q_max = AvxVectorQ0_15::from(Q_MAX); + let w0 = AvxVectorQ0_15::from(rx); + let w1 = AvxVectorQ0_15::from(ry); + let w2 = AvxVectorQ0_15::from(rz); + let dx = q_max - w0; + let dy = q_max - w1; + let dz = q_max - w2; + + let c000 = rv.fetch(x, y, z); + let c100 = rv.fetch(x_n, y, z); + let c010 = rv.fetch(x, y_n, z); + let c110 = rv.fetch(x_n, y_n, z); + let c001 = rv.fetch(x, y, z_n); + let c101 = rv.fetch(x_n, y, z_n); + let c011 = rv.fetch(x, y_n, z_n); + let c111 = rv.fetch(x_n, y_n, z_n); + + let c00 = (c000 * dx).mla(c100, w0); + let c10 = (c010 * dx).mla(c110, w0); + let c01 = (c001 * dx).mla(c101, w0); + let c11 = (c011 * dx).mla(c111, w0); + + let c0 = (c00 * dy).mla(c10, w1); + let c1 = (c01 * dy).mla(c11, w1); + + (c0 * dz).mla(c1, w2).split() + } +} + +impl TrilinearAvxQ0_15 { + #[target_feature(enable = "avx2")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> AvxVectorQ0_15Sse { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + const Q_MAX: i16 = ((1i32 << 15i32) - 1) as i16; + + let q_max = AvxVectorQ0_15Sse::from(Q_MAX); + let q_max_avx = AvxVectorQ0_15::from(Q_MAX); + let w0 = AvxVectorQ0_15::from(dr); + let w1 = AvxVectorQ0_15::from(dg); + let w2 = AvxVectorQ0_15Sse::from(db); + let dx = q_max_avx - w0; + let dy = q_max_avx - w1; + let dz = q_max - w2; + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let x000 = AvxVectorQ0_15::from_sse(c000, c001); + let x010 = AvxVectorQ0_15::from_sse(c010, c011); + let x011 = AvxVectorQ0_15::from_sse(c100, c101); + let x111 = AvxVectorQ0_15::from_sse(c110, c111); + + let c00 = (x000 * dx).mla(x011, w0); + let c10 = (x010 * dx).mla(x111, w0); + + let c0 = (c00 * dy).mla(c10, w1); + + let (c0, c1) = c0.split(); + + (c0 * dz).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,350 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::avx::interpolator::*; +use crate::conversions::avx::interpolator_q0_15::AvxAlignedI16; +use crate::conversions::avx::lut4_to_3_q0_15::TransformLut4To3AvxQ0_15; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut4x3Factory; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; +use std::marker::PhantomData; + +struct TransformLut4To3Avx< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3Avx +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let value_scale = unsafe { _mm_set1_ps(((1 << BIT_DEPTH) - 1) as f32) }; + let max_value = ((1 << BIT_DEPTH) - 1u32).as_(); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + let t: f32 = k_weights.w; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let v = interpolator.inter3_sse( + table1, + table2, + c.as_(), + m.as_(), + y.as_(), + self.weights.as_slice(), + ); + let (a0, b0) = (v.0.v, v.1.v); + + if T::FINITE { + unsafe { + let t0 = _mm_set1_ps(t); + let hp = _mm_fnmadd_ps(a0, t0, a0); + let mut v = _mm_fmadd_ps(b0, t0, hp); + v = _mm_max_ps(v, _mm_setzero_ps()); + v = _mm_mul_ps(v, value_scale); + v = _mm_min_ps(v, value_scale); + let jvz = _mm_cvtps_epi32(v); + + let x = _mm_extract_epi32::<0>(jvz); + let y = _mm_extract_epi32::<1>(jvz); + let z = _mm_extract_epi32::<2>(jvz); + + dst[cn.r_i()] = (x as u32).as_(); + dst[cn.g_i()] = (y as u32).as_(); + dst[cn.b_i()] = (z as u32).as_(); + } + } else { + unsafe { + let t0 = _mm_set1_ps(t); + let hp = _mm_fnmadd_ps(a0, t0, a0); + let v = _mm_fmadd_ps(b0, t0, hp); + dst[cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(v) as u32).as_(); + dst[cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(v) as u32).as_(); + dst[cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(v) as u32).as_(); + } + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3Avx +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearAvxFmaDouble:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralAvxFmaDouble:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk( + src, + dst, + Box::new(PyramidAvxFmaDouble:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk( + src, + dst, + Box::new(PrismaticAvxFmaDouble:: {}), + ); + } + InterpolationMethod::Linear => { + self.transform_chunk( + src, + dst, + Box::new(TrilinearAvxFmaDouble:: {}), + ); + } + } + } + } + + Ok(()) + } +} + +pub(crate) struct AvxLut4x3Factory {} + +impl Lut4x3Factory for AvxLut4x3Factory { + fn make_transform_4x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point && BIT_DEPTH < 16 { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + AvxAlignedI16([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut4To3AvxQ0_15::< + T, + u8, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut4To3AvxQ0_15::< + T, + u16, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }), + }; + } + assert!( + std::arch::is_x86_feature_detected!("fma"), + "Internal configuration error, this feature might not be called without `fma` feature" + ); + let lut = lut + .chunks_exact(3) + .map(|x| SseAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => { + Box::new( + TransformLut4To3Avx:: { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }, + ) + } + #[cfg(feature = "options")] + BarycentricWeightScale::High => { + Box::new( + TransformLut4To3Avx:: { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }, + ) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/lut4_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,230 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::avx::interpolator_q0_15::*; +use crate::conversions::interpolator::BarycentricWeight; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut4To3AvxQ0_15< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3AvxQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "avx2")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let f_value_scale = _mm_set1_ps(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + _mm_set1_epi16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + _mm_set1_epi16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + const Q: i16 = ((1i32 << 15) - 1) as i16; + let t: i16 = k_weights.w; + let t_n: i16 = Q - t; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let v = interpolator.inter3_sse( + table1, + table2, + c.as_(), + m.as_(), + y.as_(), + self.weights.as_slice(), + ); + let (a0, b0) = (v.0.v, v.1.v); + + let hp = _mm_mulhrs_epi16(_mm_set1_epi16(t_n), a0); + let v = _mm_add_epi16(hp, _mm_mulhrs_epi16(b0, _mm_set1_epi16(t))); + + if T::FINITE { + let mut o = _mm_max_epi16(v, _mm_setzero_si128()); + o = _mm_min_epi16(o, v_max_scale); + let x = _mm_extract_epi16::<0>(o); + let y = _mm_extract_epi16::<1>(o); + let z = _mm_extract_epi16::<2>(o); + + dst[cn.r_i()] = (x as u32).as_(); + dst[cn.g_i()] = (y as u32).as_(); + dst[cn.b_i()] = (z as u32).as_(); + } else { + let mut r = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(v)); + r = _mm_mul_ps(r, f_value_scale); + dst[cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(r) as u32).as_(); + dst[cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(r) as u32).as_(); + dst[cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(r) as u32).as_(); + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3AvxQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearAvxQ0_15Double:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralAvxQ0_15Double:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk( + src, + dst, + Box::new(PyramidAvxFmaQ0_15Double:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk( + src, + dst, + Box::new(PrismaticAvxQ0_15Double:: {}), + ); + } + InterpolationMethod::Linear => { + self.transform_chunk( + src, + dst, + Box::new(TrilinearAvxQ0_15Double:: {}), + ); + } + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod interpolator; +mod interpolator_q0_15; +mod lut4_to_3; +mod lut4_to_3_q0_15; +mod rgb_xyz; +mod rgb_xyz_opt; +mod rgb_xyz_q2_13; +mod rgb_xyz_q2_13_opt; +mod t_lut3_to_3; +mod t_lut3_to_3_q0_15; + +pub(crate) use lut4_to_3::AvxLut4x3Factory; +pub(crate) use rgb_xyz::TransformShaperRgbAvx; +pub(crate) use rgb_xyz_opt::TransformShaperRgbOptAvx; +pub(crate) use rgb_xyz_q2_13::TransformShaperRgbQ2_13Avx; +pub(crate) use rgb_xyz_q2_13_opt::TransformShaperRgbQ2_13OptAvx; +pub(crate) use t_lut3_to_3::AvxLut3x3Factory; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,311 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::TransformMatrixShaper; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +#[repr(align(32), C)] +#[derive(Debug)] +pub(crate) struct AvxAlignedU16(pub(crate) [u16; 16]); + +pub(crate) struct TransformShaperRgbAvx< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + // deleting linear cap is in effective here + const LINEAR_CAP: usize, +> { + pub(crate) profile: TransformMatrixShaper, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformShaperRgbAvx +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn transform_impl( + &self, + src: &[T], + dst: &mut [T], + ) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = AvxAlignedU16([0; 16]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + unsafe { + let m0 = _mm256_setr_ps( + t.v[0][0], t.v[0][1], t.v[0][2], 0., t.v[0][0], t.v[0][1], t.v[0][2], 0., + ); + let m1 = _mm256_setr_ps( + t.v[1][0], t.v[1][1], t.v[1][2], 0., t.v[1][0], t.v[1][1], t.v[1][2], 0., + ); + let m2 = _mm256_setr_ps( + t.v[2][0], t.v[2][1], t.v[2][2], 0., t.v[2][0], t.v[2][1], t.v[2][2], 0., + ); + + let zeros = _mm_setzero_ps(); + + let v_scale = _mm256_set1_ps(scale); + + let mut src = src; + let mut dst = dst; + + let mut src_iter = src.chunks_exact(src_channels * 2); + let dst_iter = dst.chunks_exact_mut(dst_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + + if let Some(src) = src_iter.next() { + r0 = _mm_broadcast_ss(&self.profile.r_linear[src[src_cn.r_i()]._as_usize()]); + g0 = _mm_broadcast_ss(&self.profile.g_linear[src[src_cn.g_i()]._as_usize()]); + b0 = _mm_broadcast_ss(&self.profile.b_linear[src[src_cn.b_i()]._as_usize()]); + r1 = _mm_broadcast_ss( + &self.profile.r_linear[src[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _mm_broadcast_ss( + &self.profile.g_linear[src[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _mm_broadcast_ss( + &self.profile.b_linear[src[src_cn.b_i() + src_channels]._as_usize()], + ); + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_ps(); + g0 = _mm_setzero_ps(); + b0 = _mm_setzero_ps(); + a0 = max_colors; + r1 = _mm_setzero_ps(); + g1 = _mm_setzero_ps(); + b1 = _mm_setzero_ps(); + a1 = max_colors; + } + + for (src, dst) in src_iter.zip(dst_iter) { + let r = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let g = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let b = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let mut v = if FMA { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_fmadd_ps(g, m1, v0); + _mm256_fmadd_ps(b, m2, v1) + } else { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_mul_ps(g, m1); + let v2 = _mm256_mul_ps(b, m2); + + _mm256_add_ps(_mm256_add_ps(v0, v1), v2) + }; + + v = _mm256_max_ps(v, _mm256_setzero_ps()); + v = _mm256_mul_ps(v, v_scale); + v = _mm256_min_ps(v, v_scale); + + let zx = _mm256_cvtps_epi32(v); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx); + + r0 = _mm_broadcast_ss(&self.profile.r_linear[src[src_cn.r_i()]._as_usize()]); + g0 = _mm_broadcast_ss(&self.profile.g_linear[src[src_cn.g_i()]._as_usize()]); + b0 = _mm_broadcast_ss(&self.profile.b_linear[src[src_cn.b_i()]._as_usize()]); + r1 = _mm_broadcast_ss( + &self.profile.r_linear[src[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _mm_broadcast_ss( + &self.profile.g_linear[src[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _mm_broadcast_ss( + &self.profile.b_linear[src[src_cn.b_i() + src_channels]._as_usize()], + ); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.r_gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.g_gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.b_gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let Some(dst) = dst.chunks_exact_mut(dst_channels * 2).last() { + let r = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let g = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let b = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let mut v = if FMA { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_fmadd_ps(g, m1, v0); + _mm256_fmadd_ps(b, m2, v1) + } else { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_mul_ps(g, m1); + let v2 = _mm256_mul_ps(b, m2); + + _mm256_add_ps(_mm256_add_ps(v0, v1), v2) + }; + + v = _mm256_max_ps(v, _mm256_setzero_ps()); + v = _mm256_mul_ps(v, v_scale); + v = _mm256_min_ps(v, v_scale); + + let zx = _mm256_cvtps_epi32(v); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.r_gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.g_gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.b_gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + } + + src = src.chunks_exact(src_channels * 2).remainder(); + dst = dst.chunks_exact_mut(dst_channels * 2).into_remainder(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = _mm_broadcast_ss(&self.profile.r_linear[src[src_cn.r_i()]._as_usize()]); + let g = _mm_broadcast_ss(&self.profile.g_linear[src[src_cn.g_i()]._as_usize()]); + let b = _mm_broadcast_ss(&self.profile.b_linear[src[src_cn.b_i()]._as_usize()]); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let mut v = if FMA { + let v0 = _mm_mul_ps(r, _mm256_castps256_ps128(m0)); + let v1 = _mm_fmadd_ps(g, _mm256_castps256_ps128(m1), v0); + _mm_fmadd_ps(b, _mm256_castps256_ps128(m2), v1) + } else { + let v0 = _mm_mul_ps(r, _mm256_castps256_ps128(m0)); + let v1 = _mm_mul_ps(g, _mm256_castps256_ps128(m1)); + let v2 = _mm_mul_ps(b, _mm256_castps256_ps128(m2)); + + _mm_add_ps(_mm_add_ps(v0, v1), v2) + }; + + v = _mm_max_ps(v, zeros); + v = _mm_mul_ps(v, _mm256_castps256_ps128(v_scale)); + v = _mm_min_ps(v, _mm256_castps256_ps128(v_scale)); + + let zx = _mm_cvtps_epi32(v); + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformShaperRgbAvx +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { + assert!(std::arch::is_x86_feature_detected!("fma")); + self.transform_impl::(src, dst) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::avx::rgb_xyz::AvxAlignedU16; +use crate::conversions::rgbxyz::TransformMatrixShaperOptimizedV; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbOptAvx< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> { + pub(crate) profile: TransformMatrixShaperOptimizedV, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformShaperRgbOptAvx +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn transform_impl( + &self, + src: &[T], + dst: &mut [T], + ) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = AvxAlignedU16([0; 16]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + unsafe { + let m0 = _mm256_setr_ps( + t.v[0][0], t.v[0][1], t.v[0][2], 0., t.v[0][0], t.v[0][1], t.v[0][2], 0., + ); + let m1 = _mm256_setr_ps( + t.v[1][0], t.v[1][1], t.v[1][2], 0., t.v[1][0], t.v[1][1], t.v[1][2], 0., + ); + let m2 = _mm256_setr_ps( + t.v[2][0], t.v[2][1], t.v[2][2], 0., t.v[2][0], t.v[2][1], t.v[2][2], 0., + ); + + let zeros = _mm_setzero_ps(); + + let v_scale = _mm256_set1_ps(scale); + + let mut src = src; + let mut dst = dst; + + let mut src_iter = src.chunks_exact(src_channels * 2); + let dst_iter = dst.chunks_exact_mut(dst_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + + if let Some(src) = src_iter.next() { + r0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + g0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + b0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + r1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.b_i() + src_channels]._as_usize()), + ); + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_ps(); + g0 = _mm_setzero_ps(); + b0 = _mm_setzero_ps(); + a0 = max_colors; + r1 = _mm_setzero_ps(); + g1 = _mm_setzero_ps(); + b1 = _mm_setzero_ps(); + a1 = max_colors; + } + + for (src, dst) in src_iter.zip(dst_iter) { + let r = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let g = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let b = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let mut v = if FMA { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_fmadd_ps(g, m1, v0); + _mm256_fmadd_ps(b, m2, v1) + } else { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_mul_ps(g, m1); + let v2 = _mm256_mul_ps(b, m2); + + _mm256_add_ps(_mm256_add_ps(v0, v1), v2) + }; + + v = _mm256_max_ps(v, _mm256_setzero_ps()); + v = _mm256_mul_ps(v, v_scale); + v = _mm256_min_ps(v, v_scale); + + let zx = _mm256_cvtps_epi32(v); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx); + + r0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + g0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + b0 = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + r1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _mm_broadcast_ss( + lut_lin.get_unchecked(src[src_cn.b_i() + src_channels]._as_usize()), + ); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let Some(dst) = dst.chunks_exact_mut(dst_channels * 2).last() { + let r = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let g = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let b = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let mut v = if FMA { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_fmadd_ps(g, m1, v0); + _mm256_fmadd_ps(b, m2, v1) + } else { + let v0 = _mm256_mul_ps(r, m0); + let v1 = _mm256_mul_ps(g, m1); + let v2 = _mm256_mul_ps(b, m2); + + _mm256_add_ps(_mm256_add_ps(v0, v1), v2) + }; + + v = _mm256_max_ps(v, _mm256_setzero_ps()); + v = _mm256_mul_ps(v, v_scale); + v = _mm256_min_ps(v, v_scale); + + let zx = _mm256_cvtps_epi32(v); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + } + + src = src.chunks_exact(src_channels * 2).remainder(); + dst = dst.chunks_exact_mut(dst_channels * 2).into_remainder(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + let g = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + let b = _mm_broadcast_ss(lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let mut v = if FMA { + let v0 = _mm_mul_ps(r, _mm256_castps256_ps128(m0)); + let v1 = _mm_fmadd_ps(g, _mm256_castps256_ps128(m1), v0); + _mm_fmadd_ps(b, _mm256_castps256_ps128(m2), v1) + } else { + let v0 = _mm_mul_ps(r, _mm256_castps256_ps128(m0)); + let v1 = _mm_mul_ps(g, _mm256_castps256_ps128(m1)); + let v2 = _mm_mul_ps(b, _mm256_castps256_ps128(m2)); + + _mm_add_ps(_mm_add_ps(v0, v1), v2) + }; + + v = _mm_max_ps(v, zeros); + v = _mm_mul_ps(v, _mm256_castps256_ps128(v_scale)); + v = _mm_min_ps(v, _mm256_castps256_ps128(v_scale)); + + let zx = _mm_cvtps_epi32(v); + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperRgbOptAvx +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { + assert!(std::arch::is_x86_feature_detected!("fma")); + self.transform_impl::(src, dst) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::avx::rgb_xyz::AvxAlignedU16; +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFp; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbQ2_13Avx< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFp, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +#[inline(always)] +pub(crate) unsafe fn _xmm_broadcast_epi32(f: &i32) -> __m128i { + let float_ref: &f32 = unsafe { &*(f as *const i32 as *const f32) }; + unsafe { _mm_castps_si128(_mm_broadcast_ss(float_ref)) } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformShaperRgbQ2_13Avx +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx2")] + unsafe fn transform_avx2(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = AvxAlignedU16([0; 16]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let max_colors = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.r_linear.len() >= cap); + assert!(self.profile.g_linear.len() >= cap); + assert!(self.profile.b_linear.len() >= cap); + } else { + assert!(self.profile.r_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.g_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.b_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let r_lin = &self.profile.r_linear; + let g_lin = &self.profile.g_linear; + let b_lin = &self.profile.b_linear; + + unsafe { + let m0 = _mm256_setr_epi16( + t.v[0][0], t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, t.v[0][0], + t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, + ); + let m2 = _mm256_setr_epi16( + t.v[2][0], 1, t.v[2][1], 1, t.v[2][2], 1, 0, 0, t.v[2][0], 1, t.v[2][1], 1, + t.v[2][2], 1, 0, 0, + ); + + let rnd_val = ((1i32 << (PRECISION - 1)) as i16).to_ne_bytes(); + let rnd = _mm256_set1_epi32(i32::from_ne_bytes([0, 0, rnd_val[0], rnd_val[1]])); + + let zeros = _mm256_setzero_si256(); + + let v_max_value = _mm256_set1_epi32(self.gamma_lut as i32 - 1); + + let mut src = src; + let mut dst = dst; + + let mut src_iter = src.chunks_exact(src_channels * 2); + let dst_iter = dst.chunks_exact_mut(dst_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + + if let Some(src) = src_iter.next() { + r0 = _xmm_broadcast_epi32(r_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + g0 = _xmm_broadcast_epi32(g_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + b0 = _xmm_broadcast_epi32(b_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + r1 = _xmm_broadcast_epi32( + r_lin.get_unchecked(src[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _xmm_broadcast_epi32( + g_lin.get_unchecked(src[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _xmm_broadcast_epi32( + b_lin.get_unchecked(src[src_cn.b_i() + src_channels]._as_usize()), + ); + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_si128(); + g0 = _mm_setzero_si128(); + b0 = _mm_setzero_si128(); + a0 = max_colors; + r1 = _mm_setzero_si128(); + g1 = _mm_setzero_si128(); + b1 = _mm_setzero_si128(); + a1 = max_colors; + } + + for (src, dst) in src_iter.zip(dst_iter) { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + + r0 = _xmm_broadcast_epi32(r_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + g0 = _xmm_broadcast_epi32(g_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + b0 = _xmm_broadcast_epi32(b_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + r1 = _xmm_broadcast_epi32( + r_lin.get_unchecked(src[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _xmm_broadcast_epi32( + g_lin.get_unchecked(src[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _xmm_broadcast_epi32( + b_lin.get_unchecked(src[src_cn.b_i() + src_channels]._as_usize()), + ); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.r_gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.g_gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.b_gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let Some(dst) = dst.chunks_exact_mut(dst_channels * 2).last() { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.r_gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.g_gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.b_gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + } + + src = src.chunks_exact(src_channels * 2).remainder(); + dst = dst.chunks_exact_mut(dst_channels * 2).into_remainder(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = _xmm_broadcast_epi32(r_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + let mut g = + _xmm_broadcast_epi32(g_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + let b = _xmm_broadcast_epi32(b_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + + g = _mm_slli_epi32::<16>(g); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let zrg0 = _mm_or_si128(r, g); + let zbz0 = _mm_or_si128(b, _mm256_castsi256_si128(rnd)); + + let v0 = _mm_madd_epi16(zrg0, _mm256_castsi256_si128(m0)); + let v1 = _mm_madd_epi16(zbz0, _mm256_castsi256_si128(m2)); + + let mut v = _mm_add_epi32(v0, v1); + + v = _mm_srai_epi32::(v); + v = _mm_max_epi32(v, _mm_setzero_si128()); + v = _mm_min_epi32(v, _mm256_castsi256_si128(v_max_value)); + + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, v); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperRgbQ2_13Avx +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_avx2(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/rgb_xyz_q2_13_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,302 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::avx::rgb_xyz::AvxAlignedU16; +use crate::conversions::avx::rgb_xyz_q2_13::_xmm_broadcast_epi32; +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFpOptVec; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbQ2_13OptAvx< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFpOptVec, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Copy + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformShaperRgbQ2_13OptAvx +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx2")] + unsafe fn transform_avx2(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = AvxAlignedU16([0; 16]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let max_colors = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + unsafe { + let m0 = _mm256_setr_epi16( + t.v[0][0], t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, t.v[0][0], + t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, + ); + let m2 = _mm256_setr_epi16( + t.v[2][0], 1, t.v[2][1], 1, t.v[2][2], 1, 0, 0, t.v[2][0], 1, t.v[2][1], 1, + t.v[2][2], 1, 0, 0, + ); + + let rnd_val = ((1i32 << (PRECISION - 1)) as i16).to_ne_bytes(); + let rnd = _mm256_set1_epi32(i32::from_ne_bytes([0, 0, rnd_val[0], rnd_val[1]])); + + let zeros = _mm256_setzero_si256(); + + let v_max_value = _mm256_set1_epi32(self.gamma_lut as i32 - 1); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + + let mut src_iter = src.chunks_exact(src_channels * 2); + + if let Some(src0) = src_iter.next() { + r0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src0[src_cn.r_i()]._as_usize())); + g0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src0[src_cn.g_i()]._as_usize())); + b0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src0[src_cn.b_i()]._as_usize())); + + r1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()), + ); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_si128(); + g0 = _mm_setzero_si128(); + b0 = _mm_setzero_si128(); + a0 = max_colors; + r1 = _mm_setzero_si128(); + g1 = _mm_setzero_si128(); + b1 = _mm_setzero_si128(); + a1 = max_colors; + } + + for (src, dst) in src_iter.zip(dst.chunks_exact_mut(dst_channels * 2)) { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + + r0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + g0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + b0 = _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + + r1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src[src_cn.r_i() + src_channels]._as_usize()), + ); + g1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src[src_cn.g_i() + src_channels]._as_usize()), + ); + b1 = _xmm_broadcast_epi32( + lut_lin.get_unchecked(src[src_cn.b_i() + src_channels]._as_usize()), + ); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let Some(dst) = dst.chunks_exact_mut(dst_channels * 2).last() { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a0; + } + + dst[dst_cn.r_i() + dst_channels] = self.profile.gamma[temporary0.0[8] as usize]; + dst[dst_cn.g_i() + dst_channels] = self.profile.gamma[temporary0.0[10] as usize]; + dst[dst_cn.b_i() + dst_channels] = self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i() + dst_channels] = a1; + } + } + + let src = src.chunks_exact(src_channels * 2).remainder(); + let dst = dst.chunks_exact_mut(dst_channels * 2).into_remainder(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize())); + let mut g = + _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize())); + let b = _xmm_broadcast_epi32(lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize())); + + g = _mm_slli_epi32::<16>(g); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let zrg0 = _mm_or_si128(r, g); + let zbz0 = _mm_or_si128(b, _mm256_castsi256_si128(rnd)); + + let v0 = _mm_madd_epi16(zrg0, _mm256_castsi256_si128(m0)); + let v1 = _mm_madd_epi16(zbz0, _mm256_castsi256_si128(m2)); + + let mut v = _mm_add_epi32(v0, v1); + + v = _mm_srai_epi32::(v); + v = _mm_max_epi32(v, _mm_setzero_si128()); + v = _mm_min_epi32(v, _mm256_castsi256_si128(v_max_value)); + + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, v); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperRgbQ2_13OptAvx +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_avx2(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,350 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::avx::interpolator::*; +use crate::conversions::avx::interpolator_q0_15::AvxAlignedI16; +use crate::conversions::avx::t_lut3_to_3_q0_15::TransformLut3x3AvxQ0_15; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut3x3Factory; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; +use std::marker::PhantomData; + +struct TransformLut3x3AvxFma< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut3x3AvxFma +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "avx2", enable = "fma")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let value_scale = unsafe { _mm_set1_ps(((1 << BIT_DEPTH) - 1) as f32) }; + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_sse( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + unsafe { + let mut r = _mm_mul_ps(v.v, value_scale); + r = _mm_max_ps(r, _mm_setzero_ps()); + r = _mm_min_ps(r, value_scale); + let jvz = _mm_cvtps_epi32(r); + + let x = _mm_extract_epi32::<0>(jvz); + let y = _mm_extract_epi32::<1>(jvz); + let z = _mm_extract_epi32::<2>(jvz); + + dst[dst_cn.r_i()] = (x as u32).as_(); + dst[dst_cn.g_i()] = (y as u32).as_(); + dst[dst_cn.b_i()] = (z as u32).as_(); + } + } else { + unsafe { + dst[dst_cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(v.v) as u32).as_(); + dst[dst_cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(v.v) as u32).as_(); + dst[dst_cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(v.v) as u32).as_(); + } + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3AvxFma< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearAvxFma:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk(src, dst, Box::new(TetrahedralAvxFma:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalAvxFma:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticAvxFma:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearAvxFma:: {})); + } + } + } + } + Ok(()) + } +} + +pub(crate) struct AvxLut3x3Factory {} + +impl Lut3x3Factory for AvxLut3x3Factory { + fn make_transform_3x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point && BIT_DEPTH < 16 { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + AvxAlignedI16([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3AvxQ0_15::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3AvxQ0_15::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }; + } + assert!( + std::arch::is_x86_feature_detected!("fma"), + "Internal configuration error, this might not be called without `fma` feature" + ); + let lut = lut + .chunks_exact(3) + .map(|x| SseAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3AvxFma::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3AvxFma::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx/t_lut3_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::avx::interpolator_q0_15::*; +use crate::conversions::interpolator::BarycentricWeight; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut3x3AvxQ0_15< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom2: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> + TransformLut3x3AvxQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "avx2")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let f_value_scale = _mm_set1_ps(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + _mm_set1_epi16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + _mm_set1_epi16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_sse( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + let mut o = _mm_max_epi16(v.v, _mm_setzero_si128()); + o = _mm_min_epi16(o, v_max_scale); + let x = _mm_extract_epi16::<0>(o); + let y = _mm_extract_epi16::<1>(o); + let z = _mm_extract_epi16::<2>(o); + + dst[dst_cn.r_i()] = (x as u32).as_(); + dst[dst_cn.g_i()] = (y as u32).as_(); + dst[dst_cn.b_i()] = (z as u32).as_(); + } else { + let mut r = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(v.v)); + r = _mm_mul_ps(r, f_value_scale); + dst[dst_cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(r) as u32).as_(); + dst[dst_cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(r) as u32).as_(); + dst[dst_cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(r) as u32).as_(); + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3AvxQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearAvxQ0_15:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralAvxQ0_15:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalAvxQ0_15:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticAvxQ0_15:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearAvxQ0_15:: {})); + } + } + } + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 5/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod rgb_xyz_opt; +mod rgb_xyz_q2_13_opt; + +pub(crate) use rgb_xyz_opt::TransformShaperRgbOptAvx512; +pub(crate) use rgb_xyz_q2_13_opt::TransformShaperRgbQ2_13OptAvx512; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,417 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 5/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::TransformMatrixShaperOptimized; +use crate::conversions::avx512::rgb_xyz_q2_13_opt::{ + AvxAlignedU16, split_by_twos, split_by_twos_mut, +}; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbOptAvx512< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> { + pub(crate) profile: TransformMatrixShaperOptimized, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformShaperRgbOptAvx512 +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx512bw", enable = "avx512vl", enable = "fma")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + let mut temporary0 = AvxAlignedU16([0; 16]); + let mut temporary1 = AvxAlignedU16([0; 16]); + + unsafe { + let m0 = _mm256_setr_ps( + t.v[0][0], t.v[0][1], t.v[0][2], 0f32, t.v[0][0], t.v[0][1], t.v[0][2], 0f32, + ); + let m1 = _mm256_setr_ps( + t.v[1][0], t.v[1][1], t.v[1][2], 0f32, t.v[1][0], t.v[1][1], t.v[1][2], 0f32, + ); + let m2 = _mm256_setr_ps( + t.v[2][0], t.v[2][1], t.v[2][2], 0f32, t.v[2][0], t.v[2][1], t.v[2][2], 0f32, + ); + + let zeros = _mm_setzero_ps(); + + let v_scale = _mm256_set1_ps(scale); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + r0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.r_i()]._as_usize()]); + g0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.g_i()]._as_usize()]); + b0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.b_i()]._as_usize()]); + + r1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.b_i() + src_channels]._as_usize()], + ); + + r2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.r_i()]._as_usize()]); + g2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.g_i()]._as_usize()]); + b2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.b_i()]._as_usize()]); + + r3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.r_i() + src_channels]._as_usize()], + ); + g3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.g_i() + src_channels]._as_usize()], + ); + b3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.b_i() + src_channels]._as_usize()], + ); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_ps(); + g0 = _mm_setzero_ps(); + b0 = _mm_setzero_ps(); + a0 = max_colors; + r1 = _mm_setzero_ps(); + g1 = _mm_setzero_ps(); + b1 = _mm_setzero_ps(); + a1 = max_colors; + r2 = _mm_setzero_ps(); + g2 = _mm_setzero_ps(); + b2 = _mm_setzero_ps(); + a2 = max_colors; + r3 = _mm_setzero_ps(); + g3 = _mm_setzero_ps(); + b3 = _mm_setzero_ps(); + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let rz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let gz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let bz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let rz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r2), r3); + let gz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g2), g3); + let bz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b2), b3); + + let v0 = _mm256_mul_ps(rz0, m0); + let v1 = _mm256_fmadd_ps(gz0, m1, v0); + let mut vz0 = _mm256_fmadd_ps(bz0, m2, v1); + + let v2 = _mm256_mul_ps(rz1, m0); + let v3 = _mm256_fmadd_ps(gz1, m1, v2); + let mut vz1 = _mm256_fmadd_ps(bz1, m2, v3); + + vz0 = _mm256_max_ps(vz0, _mm256_setzero_ps()); + vz0 = _mm256_mul_ps(vz0, v_scale); + vz0 = _mm256_min_ps(vz0, v_scale); + + vz1 = _mm256_max_ps(vz1, _mm256_setzero_ps()); + vz1 = _mm256_mul_ps(vz1, v_scale); + vz1 = _mm256_min_ps(vz1, v_scale); + + let zx0 = _mm256_cvtps_epi32(vz0); + let zx1 = _mm256_cvtps_epi32(vz1); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx0); + _mm256_store_si256(temporary1.0.as_mut_ptr() as *mut _, zx1); + + r0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.r_i()]._as_usize()]); + g0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.g_i()]._as_usize()]); + b0 = _mm_broadcast_ss(&self.profile.linear[src0[src_cn.b_i()]._as_usize()]); + r1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _mm_broadcast_ss( + &self.profile.linear[src0[src_cn.b_i() + src_channels]._as_usize()], + ); + + r2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.r_i()]._as_usize()]); + g2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.g_i()]._as_usize()]); + b2 = _mm_broadcast_ss(&self.profile.linear[src1[src_cn.b_i()]._as_usize()]); + + r3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.r_i() + src_channels]._as_usize()], + ); + g3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.g_i() + src_channels]._as_usize()], + ); + b3 = _mm_broadcast_ss( + &self.profile.linear[src1[src_cn.b_i() + src_channels]._as_usize()], + ); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary0.0[8] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary0.0[10] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary1.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary1.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[8] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[10] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[12] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let rz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r0), r1); + let gz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g0), g1); + let bz0 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b0), b1); + + let rz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(r2), r3); + let gz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(g2), g3); + let bz1 = _mm256_insertf128_ps::<1>(_mm256_castps128_ps256(b2), b3); + + let v0 = _mm256_mul_ps(rz0, m0); + let v1 = _mm256_fmadd_ps(gz0, m1, v0); + let mut vz0 = _mm256_fmadd_ps(bz0, m2, v1); + + let v2 = _mm256_mul_ps(rz1, m0); + let v3 = _mm256_fmadd_ps(gz1, m1, v2); + let mut vz1 = _mm256_fmadd_ps(bz1, m2, v3); + + vz0 = _mm256_max_ps(vz0, _mm256_setzero_ps()); + vz0 = _mm256_mul_ps(vz0, v_scale); + vz0 = _mm256_min_ps(vz0, v_scale); + + vz1 = _mm256_max_ps(vz1, _mm256_setzero_ps()); + vz1 = _mm256_mul_ps(vz1, v_scale); + vz1 = _mm256_min_ps(vz1, v_scale); + + let zx0 = _mm256_cvtps_epi32(vz0); + let zx1 = _mm256_cvtps_epi32(vz1); + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, zx0); + _mm256_store_si256(temporary1.0.as_mut_ptr() as *mut _, zx1); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary0.0[8] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary0.0[10] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary1.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary1.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[8] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[10] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[12] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let r = _mm_broadcast_ss(&self.profile.linear[src[src_cn.r_i()]._as_usize()]); + let g = _mm_broadcast_ss(&self.profile.linear[src[src_cn.g_i()]._as_usize()]); + let b = _mm_broadcast_ss(&self.profile.linear[src[src_cn.b_i()]._as_usize()]); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = _mm_mul_ps(r, _mm256_castps256_ps128(m0)); + let v1 = _mm_fmadd_ps(g, _mm256_castps256_ps128(m1), v0); + let mut v = _mm_fmadd_ps(b, _mm256_castps256_ps128(m2), v1); + + v = _mm_max_ps(v, zeros); + v = _mm_mul_ps(v, _mm256_castps256_ps128(v_scale)); + v = _mm_min_ps(v, _mm256_castps256_ps128(v_scale)); + + let zx = _mm_cvtps_epi32(v); + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformShaperRgbOptAvx512 +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_q2_13_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_q2_13_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_q2_13_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/avx512/rgb_xyz_q2_13_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,467 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFixedPointOpt; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbQ2_13OptAvx512< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFixedPointOpt, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +#[inline(always)] +pub(crate) unsafe fn _xmm_broadcast_epi32(f: &i32) -> __m128i { + let float_ref: &f32 = unsafe { &*(f as *const i32 as *const f32) }; + unsafe { _mm_castps_si128(_mm_broadcast_ss(float_ref)) } +} + +#[repr(align(32), C)] +#[derive(Debug)] +pub(crate) struct AvxAlignedU16(pub(crate) [u16; 16]); + +#[inline] +pub(crate) fn split_by_twos(data: &[T], channels: usize) -> (&[T], &[T]) { + let len = data.len() / (channels * 4); + let split_point = len * 4; + data.split_at(split_point * channels) +} +#[inline] +pub(crate) fn split_by_twos_mut(data: &mut [T], channels: usize) -> (&mut [T], &mut [T]) { + let len = data.len() / (channels * 4); + let split_point = len * 4; + data.split_at_mut(split_point * channels) +} + +impl< + T: Copy + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> TransformShaperRgbQ2_13OptAvx512 +where + u32: AsPrimitive, +{ + #[target_feature(enable = "avx512bw", enable = "avx512vl")] + unsafe fn transform_avx512(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let max_colors = ((1 << self.bit_depth) - 1).as_(); + + // If precision changed in another place it should be also changed here + assert_eq!(PRECISION, 13); + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + let mut temporary0 = AvxAlignedU16([0; 16]); + let mut temporary1 = AvxAlignedU16([0; 16]); + + unsafe { + let m0 = _mm256_set_epi16( + 0, 0, t.v[1][2], t.v[0][2], t.v[1][1], t.v[0][1], t.v[1][0], t.v[0][0], 0, 0, + t.v[1][2], t.v[0][2], t.v[1][1], t.v[0][1], t.v[1][0], t.v[0][0], + ); + let m2 = _mm256_set_epi16( + 0, 0, 1, t.v[2][2], 1, t.v[2][1], 1, t.v[2][0], 0, 0, 1, t.v[2][2], 1, t.v[2][1], + 1, t.v[2][0], + ); + + let rnd_val = ((1i32 << (PRECISION - 1)) as i16).to_ne_bytes(); + let rnd = _mm256_set1_epi32(i32::from_ne_bytes([0, 0, rnd_val[0], rnd_val[1]])); + + let zeros = _mm256_setzero_si256(); + + let v_max_value = _mm256_set1_epi32(self.gamma_lut as i32 - 1); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + r0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.r_i()]._as_usize()]); + g0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.g_i()]._as_usize()]); + b0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.b_i()]._as_usize()]); + + r1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.b_i() + src_channels]._as_usize()], + ); + + r2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.r_i()]._as_usize()]); + g2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.g_i()]._as_usize()]); + b2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.b_i()]._as_usize()]); + + r3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.r_i() + src_channels]._as_usize()], + ); + g3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.g_i() + src_channels]._as_usize()], + ); + b3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.b_i() + src_channels]._as_usize()], + ); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = _mm_setzero_si128(); + g0 = _mm_setzero_si128(); + b0 = _mm_setzero_si128(); + a0 = max_colors; + r1 = _mm_setzero_si128(); + g1 = _mm_setzero_si128(); + b1 = _mm_setzero_si128(); + a1 = max_colors; + r2 = _mm_setzero_si128(); + g2 = _mm_setzero_si128(); + b2 = _mm_setzero_si128(); + a2 = max_colors; + r3 = _mm_setzero_si128(); + g3 = _mm_setzero_si128(); + b3 = _mm_setzero_si128(); + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zr1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r2), r3); + let mut zg1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g2), g3); + let zb1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b2), b3); + zg1 = _mm256_slli_epi32::<16>(zg1); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let zrg1 = _mm256_or_si256(zr1, zg1); + let zbz1 = _mm256_or_si256(zb1, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let va2 = _mm256_madd_epi16(zrg1, m0); + let va3 = _mm256_madd_epi16(zbz1, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + let mut v1 = _mm256_add_epi32(va2, va3); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + v1 = _mm256_srai_epi32::(v1); + v1 = _mm256_max_epi32(v1, zeros); + v1 = _mm256_min_epi32(v1, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + _mm256_store_si256(temporary1.0.as_mut_ptr() as *mut _, v1); + + r0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.r_i()]._as_usize()]); + g0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.g_i()]._as_usize()]); + b0 = _xmm_broadcast_epi32(&self.profile.linear[src0[src_cn.b_i()]._as_usize()]); + + r1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.r_i() + src_channels]._as_usize()], + ); + g1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.g_i() + src_channels]._as_usize()], + ); + b1 = _xmm_broadcast_epi32( + &self.profile.linear[src0[src_cn.b_i() + src_channels]._as_usize()], + ); + + r2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.r_i()]._as_usize()]); + g2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.g_i()]._as_usize()]); + b2 = _xmm_broadcast_epi32(&self.profile.linear[src1[src_cn.b_i()]._as_usize()]); + + r3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.r_i() + src_channels]._as_usize()], + ); + g3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.g_i() + src_channels]._as_usize()], + ); + b3 = _xmm_broadcast_epi32( + &self.profile.linear[src1[src_cn.b_i() + src_channels]._as_usize()], + ); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary0.0[8] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary0.0[10] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary1.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary1.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[8] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[10] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[12] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let zr0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r0), r1); + let mut zg0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g0), g1); + let zb0 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b0), b1); + zg0 = _mm256_slli_epi32::<16>(zg0); + + let zr1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(r2), r3); + let mut zg1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(g2), g3); + let zb1 = _mm256_inserti128_si256::<1>(_mm256_castsi128_si256(b2), b3); + zg1 = _mm256_slli_epi32::<16>(zg1); + + let zrg0 = _mm256_or_si256(zr0, zg0); + let zbz0 = _mm256_or_si256(zb0, rnd); + + let zrg1 = _mm256_or_si256(zr1, zg1); + let zbz1 = _mm256_or_si256(zb1, rnd); + + let va0 = _mm256_madd_epi16(zrg0, m0); + let va1 = _mm256_madd_epi16(zbz0, m2); + + let va2 = _mm256_madd_epi16(zrg1, m0); + let va3 = _mm256_madd_epi16(zbz1, m2); + + let mut v0 = _mm256_add_epi32(va0, va1); + let mut v1 = _mm256_add_epi32(va2, va3); + + v0 = _mm256_srai_epi32::(v0); + v0 = _mm256_max_epi32(v0, zeros); + v0 = _mm256_min_epi32(v0, v_max_value); + + v1 = _mm256_srai_epi32::(v1); + v1 = _mm256_max_epi32(v1, zeros); + v1 = _mm256_min_epi32(v1, v_max_value); + + _mm256_store_si256(temporary0.0.as_mut_ptr() as *mut _, v0); + _mm256_store_si256(temporary1.0.as_mut_ptr() as *mut _, v1); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary0.0[8] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary0.0[10] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary0.0[12] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary1.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary1.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[8] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[10] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[12] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let r = _xmm_broadcast_epi32(&self.profile.linear[src[src_cn.r_i()]._as_usize()]); + let mut g = + _xmm_broadcast_epi32(&self.profile.linear[src[src_cn.g_i()]._as_usize()]); + let b = _xmm_broadcast_epi32(&self.profile.linear[src[src_cn.b_i()]._as_usize()]); + + g = _mm_slli_epi32::<16>(g); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let zrg0 = _mm_or_si128(r, g); + let zbz0 = _mm_or_si128(b, _mm256_castsi256_si128(rnd)); + + let v0 = _mm_madd_epi16(zrg0, _mm256_castsi256_si128(m0)); + let v1 = _mm_madd_epi16(zbz0, _mm256_castsi256_si128(m2)); + + let mut v = _mm_add_epi32(v0, v1); + + v = _mm_srai_epi32::(v); + v = _mm_max_epi32(v, _mm_setzero_si128()); + v = _mm_min_epi32(v, _mm256_castsi256_si128(v_max_value)); + + _mm_store_si128(temporary0.0.as_mut_ptr() as *mut _, v); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> TransformExecutor + for TransformShaperRgbQ2_13OptAvx512 +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_avx512(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/bpc.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/bpc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/bpc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/bpc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// +// use crate::conversions::interpolator::{MultidimensionalInterpolation, Tetrahedral}; +// use crate::conversions::transform_lut4_to_4::{NonFiniteVector3fLerp, Vector3fCmykLerp}; +// use crate::mlaf::mlaf; +// use crate::{Chromaticity, ColorProfile, DataColorSpace, Lab, Xyz}; +// +// impl ColorProfile { +// #[inline] +// pub(crate) fn detect_black_point(&self, lut: &[f32]) -> Option { +// if self.color_space == DataColorSpace::Cmyk { +// // if let Some(mut bp) = self.black_point { +// // if let Some(wp) = self.media_white_point.map(|x| x.normalize()) { +// // if wp != Chromaticity::D50.to_xyz() { +// // let ad = adaption_matrix(wp, Chromaticity::D50.to_xyz()); +// // let v = ad.mul_vector(bp.to_vector()); +// // bp = Xyz { +// // x: v.v[0], +// // y: v.v[1], +// // z: v.v[2], +// // }; +// // } +// // } +// // let mut lab = Lab::from_xyz(bp); +// // lab.a = 0.; +// // lab.b = 0.; +// // if lab.l > 50. { +// // lab.l = 50.; +// // } +// // bp = lab.to_xyz(); +// // return Some(bp); +// // } +// let c = 65535; +// let m = 65535; +// let y = 65535; +// let k = 65535; +// +// let linear_k: f32 = k as f32 * (1. / 65535.); +// let w: i32 = k * (GRID_SIZE as i32 - 1) / 65535; +// let w_n: i32 = (w + 1).min(GRID_SIZE as i32 - 1); +// let t: f32 = linear_k * (GRID_SIZE as i32 - 1) as f32 - w as f32; +// +// let grid_size = GRID_SIZE as i32; +// let grid_size3 = grid_size * grid_size * grid_size; +// +// let table1 = &lut[(w * grid_size3 * 3) as usize..]; +// let table2 = &lut[(w_n * grid_size3 * 3) as usize..]; +// +// let tetrahedral1 = Tetrahedral::::new(table1); +// let tetrahedral2 = Tetrahedral::::new(table2); +// let r1 = tetrahedral1.inter3(c, m, y); +// let r2 = tetrahedral2.inter3(c, m, y); +// let r = NonFiniteVector3fLerp::interpolate(r1, r2, t, 1.0); +// +// let mut lab = Lab::from_xyz(Xyz { +// x: r.v[0], +// y: r.v[1], +// z: r.v[2], +// }); +// lab.a = 0.; +// lab.b = 0.; +// if lab.l > 50. { +// lab.l = 50.; +// } +// let bp = lab.to_xyz(); +// +// return Some(bp); +// } +// if self.color_space == DataColorSpace::Rgb { +// return Some(Xyz::new(0.0, 0.0, 0.0)); +// } +// None +// } +// } +// +// pub(crate) fn compensate_bpc_in_lut(lut_xyz: &mut [f32], src_bp: Xyz, dst_bp: Xyz) { +// const WP_50: Xyz = Chromaticity::D50.to_xyz(); +// let tx = src_bp.x - WP_50.x; +// let ty = src_bp.y - WP_50.y; +// let tz = src_bp.z - WP_50.z; +// let ax = (dst_bp.x - WP_50.x) / tx; +// let ay = (dst_bp.y - WP_50.y) / ty; +// let az = (dst_bp.z - WP_50.z) / tz; +// +// let bx = -WP_50.x * (dst_bp.x - src_bp.x) / tx; +// let by = -WP_50.y * (dst_bp.y - src_bp.y) / ty; +// let bz = -WP_50.z * (dst_bp.z - src_bp.z) / tz; +// +// for dst in lut_xyz.chunks_exact_mut(3) { +// dst[0] = mlaf(bx, dst[0], ax); +// dst[1] = mlaf(by, dst[1], ay); +// dst[2] = mlaf(bz, dst[2], az); +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,388 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; + +#[derive(Clone)] +struct TransformGray2RgbFusedExecutor { + fused_gamma: Box<[T; 65536]>, + bit_depth: usize, +} + +pub(crate) fn make_gray_to_x< + T: Copy + Default + PointeeSizeExpressible + 'static + Send + Sync, + const BUCKET: usize, +>( + src_layout: Layout, + dst_layout: Layout, + gray_linear: &[f32; BUCKET], + gray_gamma: &[T; 65536], + bit_depth: usize, + gamma_lut: usize, +) -> Result + Sync + Send>, CmsError> +where + u32: AsPrimitive, +{ + if src_layout != Layout::Gray && src_layout != Layout::GrayAlpha { + return Err(CmsError::UnsupportedProfileConnection); + } + + let mut fused_gamma = Box::new([T::default(); 65536]); + let max_lut_size = (gamma_lut - 1) as f32; + for (&src, dst) in gray_linear.iter().zip(fused_gamma.iter_mut()) { + let possible_value = ((src * max_lut_size).round() as u32).min(max_lut_size as u32) as u16; + *dst = gray_gamma[possible_value as usize]; + } + + match src_layout { + Layout::Gray => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgb as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + fused_gamma, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::GrayAlpha => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + fused_gamma, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGray2RgbFusedExecutor::< + T, + { Layout::GrayAlpha as u8 }, + { Layout::GrayAlpha as u8 }, + > { + fused_gamma, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformGray2RgbFusedExecutor +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let is_gray_alpha = src_cn == Layout::GrayAlpha; + + let max_value: T = ((1u32 << self.bit_depth as u32) - 1u32).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let g = self.fused_gamma[src[0]._as_usize()]; + let a = if is_gray_alpha { src[1] } else { max_value }; + + dst[0] = g; + if dst_cn == Layout::GrayAlpha { + dst[1] = a; + } else if dst_cn == Layout::Rgb { + dst[1] = g; + dst[2] = g; + } else if dst_cn == Layout::Rgba { + dst[1] = g; + dst[2] = g; + dst[3] = a; + } + } + + Ok(()) + } +} + +#[derive(Clone)] +struct TransformGrayToRgbExecutor { + gray_linear: Box<[f32; 65536]>, + red_gamma: Box<[T; 65536]>, + green_gamma: Box<[T; 65536]>, + blue_gamma: Box<[T; 65536]>, + bit_depth: usize, + gamma_lut: usize, +} + +#[allow(clippy::too_many_arguments)] +pub(crate) fn make_gray_to_unfused< + T: Copy + Default + PointeeSizeExpressible + 'static + Send + Sync, + const BUCKET: usize, +>( + src_layout: Layout, + dst_layout: Layout, + gray_linear: Box<[f32; 65536]>, + red_gamma: Box<[T; 65536]>, + green_gamma: Box<[T; 65536]>, + blue_gamma: Box<[T; 65536]>, + bit_depth: usize, + gamma_lut: usize, +) -> Result + Sync + Send>, CmsError> +where + u32: AsPrimitive, +{ + if src_layout != Layout::Gray && src_layout != Layout::GrayAlpha { + return Err(CmsError::UnsupportedProfileConnection); + } + if dst_layout != Layout::Rgb && dst_layout != Layout::Rgba { + return Err(CmsError::UnsupportedProfileConnection); + } + match src_layout { + Layout::Gray => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgb as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::Rgba => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::Gray => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::GrayAlpha => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::Rgba => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::Gray => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayToRgbExecutor::< + T, + { Layout::GrayAlpha as u8 }, + { Layout::GrayAlpha as u8 }, + > { + gray_linear, + red_gamma, + green_gamma, + blue_gamma, + bit_depth, + gamma_lut, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformGrayToRgbExecutor +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let is_gray_alpha = src_cn == Layout::GrayAlpha; + + let max_value: T = ((1u32 << self.bit_depth as u32) - 1u32).as_(); + let max_lut_size = (self.gamma_lut - 1) as f32; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let g = self.gray_linear[src[0]._as_usize()]; + let a = if is_gray_alpha { src[1] } else { max_value }; + + let possible_value = ((g * max_lut_size).round() as u16) as usize; + let red_value = self.red_gamma[possible_value]; + let green_value = self.green_gamma[possible_value]; + let blue_value = self.blue_gamma[possible_value]; + + if dst_cn == Layout::Rgb { + dst[0] = red_value; + dst[1] = green_value; + dst[2] = blue_value; + } else if dst_cn == Layout::Rgba { + dst[0] = red_value; + dst[1] = green_value; + dst[2] = blue_value; + dst[3] = a; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb_extended.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb_extended.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb_extended.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/gray2rgb_extended.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,383 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::transform::PointeeSizeExpressible; +use crate::trc::ToneCurveEvaluator; +use crate::{CmsError, Layout, Rgb, TransformExecutor}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +struct TransformGrayOneToOneExecutor { + linear_eval: Box, + gamma_eval: Box, + _phantom: PhantomData, + bit_depth: usize, +} + +pub(crate) fn make_gray_to_one_trc_extended< + T: Copy + Default + PointeeSizeExpressible + 'static + Send + Sync + AsPrimitive, +>( + src_layout: Layout, + dst_layout: Layout, + linear_eval: Box, + gamma_eval: Box, + bit_depth: usize, +) -> Result + Sync + Send>, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + if src_layout != Layout::Gray && src_layout != Layout::GrayAlpha { + return Err(CmsError::UnsupportedProfileConnection); + } + + match src_layout { + Layout::Gray => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgb as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::GrayAlpha => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayOneToOneExecutor::< + T, + { Layout::GrayAlpha as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static + AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformGrayOneToOneExecutor +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let is_gray_alpha = src_cn == Layout::GrayAlpha; + + let max_value: T = ((1u32 << self.bit_depth as u32) - 1u32).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let linear_value = self.linear_eval.evaluate_value(src[0].as_()); + let g = self.gamma_eval.evaluate_value(linear_value).as_(); + let a = if is_gray_alpha { src[1] } else { max_value }; + + dst[0] = g; + if dst_cn == Layout::GrayAlpha { + dst[1] = a; + } else if dst_cn == Layout::Rgb { + dst[1] = g; + dst[2] = g; + } else if dst_cn == Layout::Rgba { + dst[1] = g; + dst[2] = g; + dst[3] = a; + } + } + + Ok(()) + } +} + +struct TransformGrayToRgbExtendedExecutor { + linear_eval: Box, + gamma_eval: Box, + _phantom: PhantomData, + bit_depth: usize, +} + +pub(crate) fn make_gray_to_rgb_extended< + T: Copy + Default + PointeeSizeExpressible + 'static + Send + Sync + AsPrimitive, +>( + src_layout: Layout, + dst_layout: Layout, + linear_eval: Box, + gamma_eval: Box, + bit_depth: usize, +) -> Result + Sync + Send>, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + if src_layout != Layout::Gray && src_layout != Layout::GrayAlpha { + return Err(CmsError::UnsupportedProfileConnection); + } + if dst_layout != Layout::Rgb && dst_layout != Layout::Rgba { + return Err(CmsError::UnsupportedProfileConnection); + } + match src_layout { + Layout::Gray => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgb as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::GrayAlpha => match dst_layout { + Layout::Rgb => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Rgba => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Rgba as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::Gray => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::Gray as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformGrayToRgbExtendedExecutor::< + T, + { Layout::GrayAlpha as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static + AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformGrayToRgbExtendedExecutor +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let is_gray_alpha = src_cn == Layout::GrayAlpha; + + let max_value: T = ((1u32 << self.bit_depth as u32) - 1u32).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let linear_value = self.linear_eval.evaluate_value(src[0].as_()); + let a = if is_gray_alpha { src[1] } else { max_value }; + + let tristimulus = self.gamma_eval.evaluate_tristimulus(Rgb::new( + linear_value, + linear_value, + linear_value, + )); + + let red_value = tristimulus.r.as_(); + let green_value = tristimulus.g.as_(); + let blue_value = tristimulus.b.as_(); + + if dst_cn == Layout::Rgb { + dst[0] = red_value; + dst[1] = green_value; + dst[2] = blue_value; + } else if dst_cn == Layout::Rgba { + dst[0] = red_value; + dst[1] = green_value; + dst[2] = blue_value; + dst[3] = a; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/interpolator.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/interpolator.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/interpolator.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/interpolator.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,599 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] +use crate::conversions::lut_transforms::LUT_SAMPLING; +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use crate::{Vector3f, Vector4f}; +use std::ops::{Add, Mul, Sub}; + +#[cfg(feature = "options")] +pub(crate) struct Tetrahedral {} + +#[cfg(feature = "options")] +pub(crate) struct Pyramidal {} + +#[cfg(feature = "options")] +pub(crate) struct Prismatic {} + +pub(crate) struct Trilinear {} + +#[derive(Debug, Copy, Clone, Default)] +pub(crate) struct BarycentricWeight { + pub x: i32, + pub x_n: i32, + pub w: V, +} + +impl BarycentricWeight { + pub(crate) fn create_ranged_256() -> Box<[BarycentricWeight; 256]> + { + let mut weights = Box::new([BarycentricWeight::default(); 256]); + for (index, weight) in weights.iter_mut().enumerate() { + const SCALE: f32 = 1.0 / LUT_SAMPLING as f32; + let x: i32 = index as i32 * (GRID_SIZE as i32 - 1) / LUT_SAMPLING as i32; + + let x_n: i32 = (x + 1).min(GRID_SIZE as i32 - 1); + + let scale = (GRID_SIZE as i32 - 1) as f32 * SCALE; + + let dr = index as f32 * scale - x as f32; + *weight = BarycentricWeight { x, x_n, w: dr }; + } + weights + } + + #[cfg(feature = "options")] + pub(crate) fn create_binned() + -> Box<[BarycentricWeight; 65536]> { + let mut weights = Box::new([BarycentricWeight::::default(); 65536]); + let b_scale: f32 = 1.0 / (BINS - 1) as f32; + for (index, weight) in weights.iter_mut().enumerate().take(BINS) { + let x: i32 = (index as f32 * (GRID_SIZE as i32 - 1) as f32 * b_scale).floor() as i32; + + let x_n: i32 = (x + 1).min(GRID_SIZE as i32 - 1); + + let scale = (GRID_SIZE as i32 - 1) as f32 * b_scale; + + let dr = index as f32 * scale - x as f32; + *weight = BarycentricWeight { x, x_n, w: dr }; + } + weights + } +} + +#[allow(dead_code)] +impl BarycentricWeight { + pub(crate) fn create_ranged_256() -> Box<[BarycentricWeight; 256]> + { + let mut weights = Box::new([BarycentricWeight::default(); 256]); + for (index, weight) in weights.iter_mut().enumerate() { + const SCALE: f32 = 1.0 / LUT_SAMPLING as f32; + let x: i32 = index as i32 * (GRID_SIZE as i32 - 1) / LUT_SAMPLING as i32; + + let x_n: i32 = (x + 1).min(GRID_SIZE as i32 - 1); + + let scale = (GRID_SIZE as i32 - 1) as f32 * SCALE; + + const Q: f32 = ((1i32 << 15) - 1) as f32; + + let dr = ((index as f32 * scale - x as f32) * Q) + .round() + .min(i16::MAX as f32) + .max(-i16::MAX as f32) as i16; + *weight = BarycentricWeight { x, x_n, w: dr }; + } + weights + } + + #[cfg(feature = "options")] + pub(crate) fn create_binned() + -> Box<[BarycentricWeight; 65536]> { + let mut weights = Box::new([BarycentricWeight::::default(); 65536]); + let b_scale: f32 = 1.0 / (BINS - 1) as f32; + for (index, weight) in weights.iter_mut().enumerate().take(BINS) { + let x: i32 = (index as f32 * (GRID_SIZE as i32 - 1) as f32 * b_scale).floor() as i32; + + let x_n: i32 = (x + 1).min(GRID_SIZE as i32 - 1); + + let scale = (GRID_SIZE as i32 - 1) as f32 * b_scale; + + const Q: f32 = ((1i32 << 15) - 1) as f32; + + let dr = ((index as f32 * scale - x as f32) * Q) + .round() + .min(i16::MAX as f32) + .max(-i16::MAX as f32) as i16; + *weight = BarycentricWeight { x, x_n, w: dr }; + } + weights + } +} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +struct TetrahedralFetchVector3f<'a, const GRID_SIZE: usize> { + cube: &'a [f32], +} + +pub(crate) trait MultidimensionalInterpolation { + fn inter3( + &self, + cube: &[f32], + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + ) -> Vector3f; + fn inter4( + &self, + cube: &[f32], + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + ) -> Vector4f; +} + +impl Fetcher for TetrahedralFetchVector3f<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> Vector3f { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize + * 3; + let jx = &self.cube[offset..offset + 3]; + Vector3f { + v: [jx[0], jx[1], jx[2]], + } + } +} + +struct TetrahedralFetchVector4f<'a, const GRID_SIZE: usize> { + cube: &'a [f32], +} + +impl Fetcher for TetrahedralFetchVector4f<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> Vector4f { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize + * 4; + let jx = &self.cube[offset..offset + 4]; + Vector4f { + v: [jx[0], jx[1], jx[2], jx[3]], + } + } +} + +#[cfg(feature = "options")] +impl Tetrahedral { + #[inline] + fn interpolate< + T: Copy + + Sub + + Mul + + Mul + + Add + + From + + FusedMultiplyAdd, + >( + &self, + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + r: impl Fetcher, + ) -> T { + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, T::from(rx)); + let s1 = s0.mla(c2, T::from(ry)); + s1.mla(c3, T::from(rz)) + } +} + +macro_rules! define_md_inter { + ($interpolator: ident) => { + impl MultidimensionalInterpolation for $interpolator { + fn inter3( + &self, + cube: &[f32], + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + ) -> Vector3f { + self.interpolate::( + lut_r, + lut_g, + lut_b, + TetrahedralFetchVector3f:: { cube }, + ) + } + + fn inter4( + &self, + cube: &[f32], + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + ) -> Vector4f { + self.interpolate::( + lut_r, + lut_g, + lut_b, + TetrahedralFetchVector4f:: { cube }, + ) + } + } + }; +} + +#[cfg(feature = "options")] +define_md_inter!(Tetrahedral); +#[cfg(feature = "options")] +define_md_inter!(Pyramidal); +#[cfg(feature = "options")] +define_md_inter!(Prismatic); +define_md_inter!(Trilinear); + +#[cfg(feature = "options")] +impl Pyramidal { + #[inline] + fn interpolate< + T: Copy + + Sub + + Mul + + Mul + + Add + + From + + FusedMultiplyAdd, + >( + &self, + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + r: impl Fetcher, + ) -> T { + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dg * db)) + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(db * dr)) + } + } +} + +#[cfg(feature = "options")] +impl Prismatic { + #[inline(always)] + fn interpolate< + T: Copy + + Sub + + Mul + + Mul + + Add + + From + + FusedMultiplyAdd, + >( + &self, + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + r: impl Fetcher, + ) -> T { + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if db >= dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } + } +} + +impl Trilinear { + #[inline(always)] + fn interpolate< + T: Copy + + Sub + + Mul + + Mul + + Add + + From + + FusedMultiplyAdd + + FusedMultiplyNegAdd, + >( + &self, + lut_r: &BarycentricWeight, + lut_g: &BarycentricWeight, + lut_b: &BarycentricWeight, + r: impl Fetcher, + ) -> T { + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = T::from(dr); + let w1 = T::from(dg); + let w2 = T::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = T::from(dr); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = T::from(dg); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = T::from(db); + + c0.neg_mla(c0, dz).mla(c1, w2) + } +} + +pub(crate) trait LutBarycentricReduction { + fn reduce(v: T) -> U; +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: u8) -> u8 { + v + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: u8) -> u16 { + if BINS == 65536 { + return u16::from_ne_bytes([v, v]); + } + if BINS == 16384 { + return u16::from_ne_bytes([v, v]) >> 2; + } + unimplemented!() + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: f32) -> u8 { + (v * 255.).round().min(255.).max(0.) as u8 + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: f32) -> u16 { + let scale = (BINS - 1) as f32; + (v * scale).round().min(scale).max(0.) as u16 + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: f64) -> u8 { + (v * 255.).round().min(255.).max(0.) as u8 + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: f64) -> u16 { + let scale = (BINS - 1) as f64; + (v * scale).round().min(scale).max(0.) as u16 + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: u16) -> u16 { + let src_scale = 1. / ((1 << SRC_BP) - 1) as f32; + let scale = src_scale * (BINS - 1) as f32; + (v as f32 * scale).round().min(scale).max(0.) as u16 + } +} + +impl LutBarycentricReduction for () { + #[inline(always)] + fn reduce(v: u16) -> u8 { + let shift = SRC_BP as u16 - 8; + if SRC_BP == 16 { + (v >> 8) as u8 + } else { + (v >> shift).min(255) as u8 + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/finalizers.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/finalizers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/finalizers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/finalizers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaPostFinalizationStage; +use crate::{CmsError, DataColorSpace, Layout, PointeeSizeExpressible}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) struct InjectAlphaStage { + pub(crate) dst_layout: Layout, + pub(crate) target_color_space: DataColorSpace, + pub(crate) _phantom: PhantomData, + pub(crate) bit_depth: usize, +} + +pub(crate) struct CopyAlphaStage { + pub(crate) src_layout: Layout, + pub(crate) dst_layout: Layout, + pub(crate) target_color_space: DataColorSpace, + pub(crate) _phantom: PhantomData, +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaPostFinalizationStage for InjectAlphaStage +where + f32: AsPrimitive, +{ + fn finalize(&self, _: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let norm_value: T = (if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }) + .as_(); + if self.dst_layout == Layout::Rgba && self.target_color_space == DataColorSpace::Rgb { + for dst in dst.chunks_exact_mut(self.dst_layout.channels()) { + dst[3] = norm_value; + } + } else if self.dst_layout == Layout::GrayAlpha + && self.target_color_space == DataColorSpace::Gray + { + for dst in dst.chunks_exact_mut(self.dst_layout.channels()) { + dst[1] = norm_value; + } + } + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaPostFinalizationStage for CopyAlphaStage +where + f32: AsPrimitive, +{ + fn finalize(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + if self.dst_layout == Layout::Rgba && self.target_color_space == DataColorSpace::Rgb { + if self.src_layout == Layout::Rgba { + for (src, dst) in src + .chunks_exact(self.src_layout.channels()) + .zip(dst.chunks_exact_mut(self.dst_layout.channels())) + { + dst[3] = src[3]; + } + } else if self.src_layout == Layout::GrayAlpha { + for (src, dst) in src + .chunks_exact(self.src_layout.channels()) + .zip(dst.chunks_exact_mut(self.dst_layout.channels())) + { + dst[3] = src[1]; + } + } + } else if self.dst_layout == Layout::GrayAlpha + && self.target_color_space == DataColorSpace::Gray + { + if self.src_layout == Layout::Rgba { + for (src, dst) in src + .chunks_exact(self.src_layout.channels()) + .zip(dst.chunks_exact_mut(self.dst_layout.channels())) + { + dst[1] = src[3]; + } + } else if self.src_layout == Layout::GrayAlpha { + for (src, dst) in src + .chunks_exact(self.src_layout.channels()) + .zip(dst.chunks_exact_mut(self.dst_layout.channels())) + { + dst[1] = src[1]; + } + } + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md3x3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md3x3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md3x3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md3x3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,483 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::{KatanaFinalStage, KatanaInitialStage}; +use crate::mlaf::mlaf; +use crate::safe_math::SafeMul; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, Cube, DataColorSpace, InterpolationMethod, LutMultidimensionalType, MalformedSize, + Matrix3d, Matrix3f, PointeeSizeExpressible, TransformOptions, Vector3d, Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] +pub(crate) enum MultidimensionalDirection { + DeviceToPcs, + PcsToDevice, +} + +struct Multidimensional3x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +> { + a_curves: Option; 3]>>, + m_curves: Option; 3]>>, + b_curves: Option; 3]>>, + clut: Option>, + matrix: Matrix3f, + bias: Vector3f, + direction: MultidimensionalDirection, + options: TransformOptions, + pcs: DataColorSpace, + grid_size: [u8; 3], + _phantom: PhantomData, + bit_depth: usize, +} + +impl + PointeeSizeExpressible + Send + Sync> + Multidimensional3x3 +{ + fn execute_matrix_stage(&self, dst: &mut [f32]) { + let m = self.matrix; + let b = self.bias; + + if !m.test_equality(Matrix3f::IDENTITY) || !b.eq(&Vector3f::default()) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(mlaf(b.v[0], x, m.v[0][0]), y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(mlaf(b.v[1], x, m.v[1][0]), y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(mlaf(b.v[2], x, m.v[2][0]), y, m.v[2][1]), z, m.v[2][2]); + } + } + } + + fn execute_simple_curves(&self, dst: &mut [f32], curves: &[Vec; 3]) { + let curve0 = &curves[0]; + let curve1 = &curves[1]; + let curve2 = &curves[2]; + + for dst in dst.chunks_exact_mut(3) { + let a0 = dst[0]; + let a1 = dst[1]; + let a2 = dst[2]; + let b0 = lut_interp_linear_float(a0, curve0); + let b1 = lut_interp_linear_float(a1, curve1); + let b2 = lut_interp_linear_float(a2, curve2); + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + } + } + + fn to_pcs_impl Vector3f>( + &self, + input: &[T], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let norm_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + assert_eq!( + self.direction, + MultidimensionalDirection::DeviceToPcs, + "PCS to device cannot be used on `to pcs` stage" + ); + + // A -> B + // OR B - A A - curves stage + + if let (Some(a_curves), Some(clut)) = (self.a_curves.as_ref(), self.clut.as_ref()) { + if !clut.is_empty() { + let curve0 = &a_curves[0]; + let curve1 = &a_curves[1]; + let curve2 = &a_curves[2]; + for (src, dst) in input.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + let b0 = lut_interp_linear_float(src[0].as_() * norm_value, curve0); + let b1 = lut_interp_linear_float(src[1].as_() * norm_value, curve1); + let b2 = lut_interp_linear_float(src[2].as_() * norm_value, curve2); + let interpolated = fetch(b0, b1, b2); + dst[0] = interpolated.v[0]; + dst[1] = interpolated.v[1]; + dst[2] = interpolated.v[2]; + } + } else { + for (src, dst) in input.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + dst[0] = src[0].as_() * norm_value; + dst[1] = src[1].as_() * norm_value; + dst[2] = src[2].as_() * norm_value; + } + } + } else { + for (src, dst) in input.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + dst[0] = src[0].as_() * norm_value; + dst[1] = src[1].as_() * norm_value; + dst[2] = src[2].as_() * norm_value; + } + } + + // Matrix stage + + if let Some(m_curves) = self.m_curves.as_ref() { + self.execute_simple_curves(dst, m_curves); + self.execute_matrix_stage(dst); + } + + // B-curves is mandatory + if let Some(b_curves) = &self.b_curves.as_ref() { + self.execute_simple_curves(dst, b_curves); + } + + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaInitialStage for Multidimensional3x3 +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + if input.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let fixed_new_clut = Vec::new(); + let new_clut = self.clut.as_ref().unwrap_or(&fixed_new_clut); + let lut = Cube::new_checked_cube(new_clut, self.grid_size, 3)?; + + let mut new_dst = vec![0f32; input.len()]; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + self.to_pcs_impl(input, &mut new_dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + return Ok(new_dst); + } + + match self.options.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z| lut.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z| lut.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z| lut.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + } + } + Ok(new_dst) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + Multidimensional3x3 +where + f32: AsPrimitive, +{ + fn to_output_impl Vector3f>( + &self, + src: &mut [f32], + dst: &mut [T], + fetch: Fetch, + ) -> Result<(), CmsError> { + let norm_value = if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + assert_eq!( + self.direction, + MultidimensionalDirection::PcsToDevice, + "Device to PCS cannot be used on `to output` stage" + ); + + if let Some(b_curves) = &self.b_curves.as_ref() { + self.execute_simple_curves(src, b_curves); + } + + // Matrix stage + + if let Some(m_curves) = self.m_curves.as_ref() { + self.execute_matrix_stage(src); + self.execute_simple_curves(src, m_curves); + } + + if let (Some(a_curves), Some(clut)) = (self.a_curves.as_ref(), self.clut.as_ref()) { + if !clut.is_empty() { + let curve0 = &a_curves[0]; + let curve1 = &a_curves[1]; + let curve2 = &a_curves[2]; + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + let b0 = lut_interp_linear_float(src[0], curve0); + let b1 = lut_interp_linear_float(src[1], curve1); + let b2 = lut_interp_linear_float(src[2], curve2); + let interpolated = fetch(b0, b1, b2); + if T::FINITE { + dst[0] = (interpolated.v[0] * norm_value) + .round() + .max(0.0) + .min(norm_value) + .as_(); + dst[1] = (interpolated.v[1] * norm_value) + .round() + .max(0.0) + .min(norm_value) + .as_(); + dst[2] = (interpolated.v[2] * norm_value) + .round() + .max(0.0) + .min(norm_value) + .as_(); + } else { + dst[0] = interpolated.v[0].as_(); + dst[1] = interpolated.v[1].as_(); + dst[2] = interpolated.v[2].as_(); + } + } + } else { + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + if T::FINITE { + dst[0] = (src[0] * norm_value).round().max(0.0).min(norm_value).as_(); + dst[1] = (src[1] * norm_value).round().max(0.0).min(norm_value).as_(); + dst[2] = (src[2] * norm_value).round().max(0.0).min(norm_value).as_(); + } else { + dst[0] = src[0].as_(); + dst[1] = src[1].as_(); + dst[2] = src[2].as_(); + } + } + } + } else { + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + if T::FINITE { + dst[0] = (src[0] * norm_value).round().max(0.0).min(norm_value).as_(); + dst[1] = (src[1] * norm_value).round().max(0.0).min(norm_value).as_(); + dst[2] = (src[2] * norm_value).round().max(0.0).min(norm_value).as_(); + } else { + dst[0] = src[0].as_(); + dst[1] = src[1].as_(); + dst[2] = src[2].as_(); + } + } + } + + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaFinalStage for Multidimensional3x3 +where + f32: AsPrimitive, +{ + fn to_output(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if src.len() != dst.len() { + return Err(CmsError::LaneSizeMismatch); + } + let fixed_new_clut = Vec::new(); + let new_clut = self.clut.as_ref().unwrap_or(&fixed_new_clut); + let lut = Cube::new_checked_cube(new_clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.to_output_impl(src, dst, |x, y, z| lut.trilinear_vec3(x, y, z)); + } + + match self.options.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_output_impl(src, dst, |x, y, z| lut.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_output_impl(src, dst, |x, y, z| lut.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_output_impl(src, dst, |x, y, z| lut.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.to_output_impl(src, dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + } + } + Ok(()) + } +} + +fn make_multidimensional_3x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + direction: MultidimensionalDirection, + bit_depth: usize, +) -> Result, CmsError> { + if mab.num_input_channels != 3 && mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + if mab.b_curves.is_empty() || mab.b_curves.len() != 3 { + return Err(CmsError::InvalidAtoBLut); + } + + let grid_size = [mab.grid_points[0], mab.grid_points[1], mab.grid_points[2]]; + + let clut: Option> = if mab.a_curves.len() == 3 && mab.clut.is_some() { + let clut = mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + Some(clut) + } else { + None + }; + + let a_curves: Option; 3]>> = if mab.a_curves.len() == 3 && mab.clut.is_some() { + let mut arr = Box::<[Vec; 3]>::default(); + for (a_curve, dst) in mab.a_curves.iter().zip(arr.iter_mut()) { + *dst = a_curve.to_clut()?; + } + Some(arr) + } else { + None + }; + + let b_curves: Option; 3]>> = if mab.b_curves.len() == 3 { + let mut arr = Box::<[Vec; 3]>::default(); + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if all_curves_linear { + None + } else { + for (c_curve, dst) in mab.b_curves.iter().zip(arr.iter_mut()) { + *dst = c_curve.to_clut()?; + } + Some(arr) + } + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let matrix = mab.matrix.to_f32(); + + let m_curves: Option; 3]>> = if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let mut arr = Box::<[Vec; 3]>::default(); + for (curve, dst) in mab.m_curves.iter().zip(arr.iter_mut()) { + *dst = curve.to_clut()?; + } + Some(arr) + } else { + None + } + } else { + None + }; + + let bias = mab.bias.cast(); + + let transform = Multidimensional3x3:: { + a_curves, + b_curves, + m_curves, + matrix, + direction, + options, + clut, + pcs, + grid_size, + bias, + _phantom: PhantomData, + bit_depth, + }; + + Ok(transform) +} + +pub(crate) fn multi_dimensional_3x3_to_pcs< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> { + let transform = make_multidimensional_3x3::( + mab, + options, + pcs, + MultidimensionalDirection::DeviceToPcs, + bit_depth, + )?; + Ok(Box::new(transform)) +} + +pub(crate) fn multi_dimensional_3x3_to_device< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, +{ + let transform = make_multidimensional_3x3::( + mab, + options, + pcs, + MultidimensionalDirection::PcsToDevice, + bit_depth, + )?; + Ok(Box::new(transform)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md4x3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md4x3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md4x3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md4x3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,321 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaInitialStage; +use crate::conversions::katana::md3x3::MultidimensionalDirection; +use crate::mlaf::mlaf; +use crate::safe_math::SafeMul; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, DataColorSpace, Hypercube, InterpolationMethod, LutMultidimensionalType, + MalformedSize, Matrix3d, Matrix3f, PointeeSizeExpressible, TransformOptions, Vector3d, + Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) fn execute_simple_curves3(dst: &mut [f32], curves: &[Vec; 3]) { + let curve0 = &curves[0]; + let curve1 = &curves[1]; + let curve2 = &curves[2]; + + for dst in dst.chunks_exact_mut(3) { + let a0 = dst[0]; + let a1 = dst[1]; + let a2 = dst[2]; + let b0 = lut_interp_linear_float(a0, curve0); + let b1 = lut_interp_linear_float(a1, curve1); + let b2 = lut_interp_linear_float(a2, curve2); + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + } +} + +pub(crate) fn execute_matrix_stage3(matrix: Matrix3f, bias: Vector3f, dst: &mut [f32]) { + let m = matrix; + let b = bias; + + if !m.test_equality(Matrix3f::IDENTITY) || !b.eq(&Vector3f::default()) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(mlaf(b.v[0], x, m.v[0][0]), y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(mlaf(b.v[1], x, m.v[1][0]), y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(mlaf(b.v[2], x, m.v[2][0]), y, m.v[2][1]), z, m.v[2][2]); + } + } +} + +struct Multidimensional4x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +> { + a_curves: Option; 4]>>, + m_curves: Option; 3]>>, + b_curves: Option; 3]>>, + clut: Option>, + matrix: Matrix3f, + bias: Vector3f, + direction: MultidimensionalDirection, + options: TransformOptions, + pcs: DataColorSpace, + grid_size: [u8; 4], + _phantom: PhantomData, + bit_depth: usize, +} + +impl + PointeeSizeExpressible + Send + Sync> + Multidimensional4x3 +{ + fn to_pcs_impl Vector3f>( + &self, + input: &[T], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let norm_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + assert_eq!( + self.direction, + MultidimensionalDirection::DeviceToPcs, + "PCS to device cannot be used on `to pcs` stage" + ); + + // A -> B + // OR B - A A - curves stage + + if let (Some(a_curves), Some(clut)) = (self.a_curves.as_ref(), self.clut.as_ref()) { + if !clut.is_empty() { + let curve0 = &a_curves[0]; + let curve1 = &a_curves[1]; + let curve2 = &a_curves[2]; + let curve3 = &a_curves[3]; + for (src, dst) in input.chunks_exact(4).zip(dst.chunks_exact_mut(3)) { + let b0 = lut_interp_linear_float(src[0].as_() * norm_value, curve0); + let b1 = lut_interp_linear_float(src[1].as_() * norm_value, curve1); + let b2 = lut_interp_linear_float(src[2].as_() * norm_value, curve2); + let b3 = lut_interp_linear_float(src[3].as_() * norm_value, curve3); + let interpolated = fetch(b0, b1, b2, b3); + dst[0] = interpolated.v[0]; + dst[1] = interpolated.v[1]; + dst[2] = interpolated.v[2]; + } + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + // Matrix stage + + if let Some(m_curves) = self.m_curves.as_ref() { + execute_simple_curves3(dst, m_curves); + execute_matrix_stage3(self.matrix, self.bias, dst); + } + + // B-curves is mandatory + if let Some(b_curves) = &self.b_curves.as_ref() { + execute_simple_curves3(dst, b_curves); + } + + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaInitialStage for Multidimensional4x3 +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + if input.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let fixed_new_clut = Vec::new(); + let new_clut = self.clut.as_ref().unwrap_or(&fixed_new_clut); + let lut = Hypercube::new_checked_hypercube(new_clut, self.grid_size, 3)?; + + let mut new_dst = vec![0f32; (input.len() / 4) * 3]; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + self.to_pcs_impl(input, &mut new_dst, |x, y, z, w| { + lut.quadlinear_vec3(x, y, z, w) + })?; + return Ok(new_dst); + } + + match self.options.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z, w| lut.tetra_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z, w| { + lut.pyramid_vec3(x, y, z, w) + })?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z, w| lut.prism_vec3(x, y, z, w))?; + } + InterpolationMethod::Linear => { + self.to_pcs_impl(input, &mut new_dst, |x, y, z, w| { + lut.quadlinear_vec3(x, y, z, w) + })?; + } + } + Ok(new_dst) + } +} + +fn make_multidimensional_4x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + direction: MultidimensionalDirection, + bit_depth: usize, +) -> Result, CmsError> { + if mab.num_input_channels != 4 && mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + if mab.b_curves.is_empty() || mab.b_curves.len() != 3 { + return Err(CmsError::InvalidAtoBLut); + } + + let grid_size = [ + mab.grid_points[0], + mab.grid_points[1], + mab.grid_points[2], + mab.grid_points[3], + ]; + + let clut: Option> = if mab.a_curves.len() == 4 && mab.clut.is_some() { + let clut = mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.grid_points[3] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + Some(clut) + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let a_curves: Option; 4]>> = if mab.a_curves.len() == 4 && mab.clut.is_some() { + let mut arr = Box::<[Vec; 4]>::default(); + for (a_curve, dst) in mab.a_curves.iter().zip(arr.iter_mut()) { + *dst = a_curve.to_clut()?; + } + Some(arr) + } else { + None + }; + + let b_curves: Option; 3]>> = if mab.b_curves.len() == 3 { + let mut arr = Box::<[Vec; 3]>::default(); + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if all_curves_linear { + None + } else { + for (c_curve, dst) in mab.b_curves.iter().zip(arr.iter_mut()) { + *dst = c_curve.to_clut()?; + } + Some(arr) + } + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let matrix = mab.matrix.to_f32(); + + let m_curves: Option; 3]>> = if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let mut arr = Box::<[Vec; 3]>::default(); + for (curve, dst) in mab.m_curves.iter().zip(arr.iter_mut()) { + *dst = curve.to_clut()?; + } + Some(arr) + } else { + None + } + } else { + None + }; + + let bias = mab.bias.cast(); + + let transform = Multidimensional4x3:: { + a_curves, + b_curves, + m_curves, + matrix, + direction, + options, + clut, + pcs, + grid_size, + bias, + _phantom: PhantomData, + bit_depth, + }; + + Ok(transform) +} + +pub(crate) fn multi_dimensional_4x3_to_pcs< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> { + let transform = make_multidimensional_4x3::( + mab, + options, + pcs, + MultidimensionalDirection::DeviceToPcs, + bit_depth, + )?; + Ok(Box::new(transform)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_3xn.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_3xn.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_3xn.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_3xn.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,284 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaFinalStage; +use crate::conversions::katana::md3x3::MultidimensionalDirection; +use crate::conversions::katana::md4x3::{execute_matrix_stage3, execute_simple_curves3}; +use crate::conversions::md_lut::{MultidimensionalLut, tetra_3i_to_any_vec}; +use crate::safe_math::SafeMul; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, DataColorSpace, Layout, LutMultidimensionalType, MalformedSize, Matrix3d, Matrix3f, + PointeeSizeExpressible, TransformOptions, Vector3d, Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +struct Multidimensional3xN< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +> { + a_curves: Option>>, + m_curves: Option; 3]>>, + b_curves: Option; 3]>>, + clut: Option>, + matrix: Matrix3f, + bias: Vector3f, + direction: MultidimensionalDirection, + grid_size: [u8; 16], + output_inks: usize, + _phantom: PhantomData, + dst_layout: Layout, + bit_depth: usize, +} + +impl + PointeeSizeExpressible + Send + Sync> + Multidimensional3xN +where + f32: AsPrimitive, +{ + fn to_output_impl(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + let norm_value = if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + assert_eq!( + self.direction, + MultidimensionalDirection::PcsToDevice, + "PCS to device cannot be used on `to pcs` stage" + ); + + // B-curves is mandatory + if let Some(b_curves) = &self.b_curves.as_ref() { + execute_simple_curves3(src, b_curves); + } + + // Matrix stage + + if let Some(m_curves) = self.m_curves.as_ref() { + execute_matrix_stage3(self.matrix, self.bias, src); + execute_simple_curves3(src, m_curves); + } + + if let (Some(a_curves), Some(clut)) = (self.a_curves.as_ref(), self.clut.as_ref()) { + let mut inks = vec![0.; self.output_inks]; + + if clut.is_empty() { + return Err(CmsError::InvalidAtoBLut); + } + + let md_lut = MultidimensionalLut::new(self.grid_size, 3, self.output_inks); + + for (src, dst) in src + .chunks_exact(3) + .zip(dst.chunks_exact_mut(self.dst_layout.channels())) + { + tetra_3i_to_any_vec( + &md_lut, + clut, + src[0], + src[1], + src[2], + &mut inks, + self.output_inks, + ); + + for (ink, curve) in inks.iter_mut().zip(a_curves.iter()) { + *ink = lut_interp_linear_float(*ink, curve); + } + + if T::FINITE { + for (dst, ink) in dst.iter_mut().zip(inks.iter()) { + *dst = (*ink * norm_value).round().max(0.).min(norm_value).as_(); + } + } else { + for (dst, ink) in dst.iter_mut().zip(inks.iter()) { + *dst = (*ink * norm_value).as_(); + } + } + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaFinalStage for Multidimensional3xN +where + f32: AsPrimitive, +{ + fn to_output(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % self.output_inks != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + self.to_output_impl(src, dst)?; + Ok(()) + } +} + +fn make_multidimensional_nx3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + dst_layout: Layout, + mab: &LutMultidimensionalType, + _: TransformOptions, + pcs: DataColorSpace, + direction: MultidimensionalDirection, + bit_depth: usize, +) -> Result, CmsError> { + let real_inks = if pcs == DataColorSpace::Rgb { + 3 + } else { + dst_layout.channels() + }; + + if mab.num_output_channels != real_inks as u8 { + return Err(CmsError::UnsupportedProfileConnection); + } + + if mab.b_curves.is_empty() || mab.b_curves.len() != 3 { + return Err(CmsError::InvalidAtoBLut); + } + + let clut: Option> = + if mab.a_curves.len() == mab.num_output_channels as usize && mab.clut.is_some() { + let clut = mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let mut lut_grid = 1usize; + for grid in mab.grid_points.iter().take(mab.num_input_channels as usize) { + lut_grid = lut_grid.safe_mul(*grid as usize)?; + } + let lut_grid = lut_grid.safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + Some(clut) + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let a_curves: Option>> = + if mab.a_curves.len() == mab.num_output_channels as usize && mab.clut.is_some() { + let mut arr = Vec::new(); + for a_curve in mab.a_curves.iter() { + arr.push(a_curve.to_clut()?); + } + Some(arr) + } else { + None + }; + + let b_curves: Option; 3]>> = if mab.b_curves.len() == 3 { + let mut arr = Box::<[Vec; 3]>::default(); + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if all_curves_linear { + None + } else { + for (c_curve, dst) in mab.b_curves.iter().zip(arr.iter_mut()) { + *dst = c_curve.to_clut()?; + } + Some(arr) + } + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let matrix = mab.matrix.to_f32(); + + let m_curves: Option; 3]>> = if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let mut arr = Box::<[Vec; 3]>::default(); + for (curve, dst) in mab.m_curves.iter().zip(arr.iter_mut()) { + *dst = curve.to_clut()?; + } + Some(arr) + } else { + None + } + } else { + None + }; + + let bias = mab.bias.cast(); + + let transform = Multidimensional3xN:: { + a_curves, + b_curves, + m_curves, + matrix, + direction, + clut, + grid_size: mab.grid_points, + bias, + dst_layout, + output_inks: real_inks, + _phantom: PhantomData, + bit_depth, + }; + + Ok(transform) +} + +pub(crate) fn katana_multi_dimensional_3xn_to_device< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + dst_layout: Layout, + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, +{ + if mab.num_input_channels == 0 { + return Err(CmsError::UnsupportedProfileConnection); + } + let transform = make_multidimensional_nx3::( + dst_layout, + mab, + options, + pcs, + MultidimensionalDirection::PcsToDevice, + bit_depth, + )?; + Ok(Box::new(transform)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_nx3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_nx3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_nx3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_nx3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,294 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaInitialStage; +use crate::conversions::katana::md3x3::MultidimensionalDirection; +use crate::conversions::katana::md4x3::{execute_matrix_stage3, execute_simple_curves3}; +use crate::conversions::md_lut::{ + MultidimensionalLut, NVector, linear_1i_vec3f, linear_2i_vec3f_direct, linear_3i_vec3f_direct, + linear_4i_vec3f, linear_5i_vec3f, linear_6i_vec3f, linear_7i_vec3f, linear_8i_vec3f, + linear_9i_vec3f, linear_10i_vec3f, linear_11i_vec3f, linear_12i_vec3f, linear_13i_vec3f, + linear_14i_vec3f, linear_15i_vec3f, +}; +use crate::safe_math::SafeMul; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, DataColorSpace, Layout, LutMultidimensionalType, MalformedSize, Matrix3d, Matrix3f, + PointeeSizeExpressible, TransformOptions, Vector3d, Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +struct MultidimensionalNx3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +> { + a_curves: Option>>, + m_curves: Option; 3]>>, + b_curves: Option; 3]>>, + clut: Option>, + matrix: Matrix3f, + bias: Vector3f, + direction: MultidimensionalDirection, + grid_size: [u8; 16], + input_inks: usize, + _phantom: PhantomData, + bit_depth: usize, +} + +#[inline(never)] +pub(crate) fn interpolate_out_function( + layout: Layout, +) -> fn(lut: &MultidimensionalLut, arr: &[f32], inputs: &[f32]) -> NVector { + const OUT: usize = 3; + match layout { + Layout::Rgb => linear_3i_vec3f_direct::, + Layout::Rgba => linear_4i_vec3f::, + Layout::Gray => linear_1i_vec3f::, + Layout::GrayAlpha => linear_2i_vec3f_direct::, + Layout::Inks5 => linear_5i_vec3f::, + Layout::Inks6 => linear_6i_vec3f::, + Layout::Inks7 => linear_7i_vec3f::, + Layout::Inks8 => linear_8i_vec3f::, + Layout::Inks9 => linear_9i_vec3f::, + Layout::Inks10 => linear_10i_vec3f::, + Layout::Inks11 => linear_11i_vec3f::, + Layout::Inks12 => linear_12i_vec3f::, + Layout::Inks13 => linear_13i_vec3f::, + Layout::Inks14 => linear_14i_vec3f::, + Layout::Inks15 => linear_15i_vec3f::, + } +} + +impl + PointeeSizeExpressible + Send + Sync> + MultidimensionalNx3 +{ + fn to_pcs_impl(&self, input: &[T], dst: &mut [f32]) -> Result<(), CmsError> { + let norm_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + assert_eq!( + self.direction, + MultidimensionalDirection::DeviceToPcs, + "PCS to device cannot be used on `to pcs` stage" + ); + + // A -> B + // OR B - A A - curves stage + + if let (Some(a_curves), Some(clut)) = (self.a_curves.as_ref(), self.clut.as_ref()) { + let layout = Layout::from_inks(self.input_inks); + + let mut inks = vec![0.; self.input_inks]; + + if clut.is_empty() { + return Err(CmsError::InvalidAtoBLut); + } + + let fetcher = interpolate_out_function(layout); + + let md_lut = MultidimensionalLut::new(self.grid_size, self.input_inks, 3); + + for (src, dst) in input + .chunks_exact(layout.channels()) + .zip(dst.chunks_exact_mut(3)) + { + for ((ink, src_ink), curve) in inks.iter_mut().zip(src).zip(a_curves.iter()) { + *ink = lut_interp_linear_float(src_ink.as_() * norm_value, curve); + } + + let interpolated = fetcher(&md_lut, clut, &inks); + + dst[0] = interpolated.v[0]; + dst[1] = interpolated.v[1]; + dst[2] = interpolated.v[2]; + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + // Matrix stage + + if let Some(m_curves) = self.m_curves.as_ref() { + execute_simple_curves3(dst, m_curves); + execute_matrix_stage3(self.matrix, self.bias, dst); + } + + // B-curves is mandatory + if let Some(b_curves) = &self.b_curves.as_ref() { + execute_simple_curves3(dst, b_curves); + } + + Ok(()) + } +} + +impl + PointeeSizeExpressible + Send + Sync> + KatanaInitialStage for MultidimensionalNx3 +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + if input.len() % self.input_inks != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let mut new_dst = vec![0f32; (input.len() / self.input_inks) * 3]; + + self.to_pcs_impl(input, &mut new_dst)?; + Ok(new_dst) + } +} + +fn make_multidimensional_nx3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + mab: &LutMultidimensionalType, + _: TransformOptions, + _: DataColorSpace, + direction: MultidimensionalDirection, + bit_depth: usize, +) -> Result, CmsError> { + if mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + if mab.b_curves.is_empty() || mab.b_curves.len() != 3 { + return Err(CmsError::InvalidAtoBLut); + } + + let clut: Option> = + if mab.a_curves.len() == mab.num_input_channels as usize && mab.clut.is_some() { + let clut = mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let mut lut_grid = 1usize; + for grid in mab.grid_points.iter().take(mab.num_input_channels as usize) { + lut_grid = lut_grid.safe_mul(*grid as usize)?; + } + let lut_grid = lut_grid.safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + Some(clut) + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let a_curves: Option>> = + if mab.a_curves.len() == mab.num_input_channels as usize && mab.clut.is_some() { + let mut arr = Vec::new(); + for a_curve in mab.a_curves.iter() { + arr.push(a_curve.to_clut()?); + } + Some(arr) + } else { + None + }; + + let b_curves: Option; 3]>> = if mab.b_curves.len() == 3 { + let mut arr = Box::<[Vec; 3]>::default(); + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if all_curves_linear { + None + } else { + for (c_curve, dst) in mab.b_curves.iter().zip(arr.iter_mut()) { + *dst = c_curve.to_clut()?; + } + Some(arr) + } + } else { + return Err(CmsError::InvalidAtoBLut); + }; + + let matrix = mab.matrix.to_f32(); + + let m_curves: Option; 3]>> = if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let mut arr = Box::<[Vec; 3]>::default(); + for (curve, dst) in mab.m_curves.iter().zip(arr.iter_mut()) { + *dst = curve.to_clut()?; + } + Some(arr) + } else { + None + } + } else { + None + }; + + let bias = mab.bias.cast(); + + let transform = MultidimensionalNx3:: { + a_curves, + b_curves, + m_curves, + matrix, + direction, + clut, + grid_size: mab.grid_points, + bias, + input_inks: mab.num_input_channels as usize, + _phantom: PhantomData, + bit_depth, + }; + + Ok(transform) +} + +pub(crate) fn katana_multi_dimensional_nx3_to_pcs< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + src_layout: Layout, + mab: &LutMultidimensionalType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> { + if pcs == DataColorSpace::Rgb { + if mab.num_input_channels != 3 { + return Err(CmsError::InvalidAtoBLut); + } + if src_layout != Layout::Rgba && src_layout != Layout::Rgb { + return Err(CmsError::InvalidInksCountForProfile); + } + } else if mab.num_input_channels != src_layout.channels() as u8 { + return Err(CmsError::InvalidInksCountForProfile); + } + let transform = make_multidimensional_nx3::( + mab, + options, + pcs, + MultidimensionalDirection::DeviceToPcs, + bit_depth, + )?; + Ok(Box::new(transform)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_pipeline.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_pipeline.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_pipeline.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/md_pipeline.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,393 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::md_nx3::interpolate_out_function; +use crate::conversions::katana::{KatanaFinalStage, KatanaInitialStage}; +use crate::conversions::md_lut::{MultidimensionalLut, tetra_3i_to_any_vec}; +use crate::profile::LutDataType; +use crate::safe_math::{SafeMul, SafePowi}; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, DataColorSpace, Layout, MalformedSize, PointeeSizeExpressible, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::array::from_fn; +use std::marker::PhantomData; + +#[derive(Default)] +struct KatanaLutNx3 { + linearization: Vec>, + clut: Vec, + grid_size: u8, + input_inks: usize, + output: [Vec; 3], + _phantom: PhantomData, + bit_depth: usize, +} + +struct KatanaLut3xN { + linearization: [Vec; 3], + clut: Vec, + grid_size: u8, + output_inks: usize, + output: Vec>, + dst_layout: Layout, + target_color_space: DataColorSpace, + _phantom: PhantomData, + bit_depth: usize, +} + +impl> KatanaLutNx3 { + fn to_pcs_impl(&self, input: &[T]) -> Result, CmsError> { + if input.len() % self.input_inks != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let norm_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + + let grid_sizes: [u8; 16] = from_fn(|i| { + if i < self.input_inks { + self.grid_size + } else { + 0 + } + }); + + let md_lut = MultidimensionalLut::new(grid_sizes, self.input_inks, 3); + + let layout = Layout::from_inks(self.input_inks); + + let mut inks = vec![0.; self.input_inks]; + + let mut dst = vec![0.; (input.len() / layout.channels()) * 3]; + + let fetcher = interpolate_out_function(layout); + + for (dest, src) in dst + .chunks_exact_mut(3) + .zip(input.chunks_exact(layout.channels())) + { + for ((ink, src_ink), curve) in inks.iter_mut().zip(src).zip(self.linearization.iter()) { + *ink = lut_interp_linear_float(src_ink.as_() * norm_value, curve); + } + + let clut = fetcher(&md_lut, &self.clut, &inks); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.output[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.output[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.output[2]); + + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + } + Ok(dst) + } +} + +impl> KatanaInitialStage + for KatanaLutNx3 +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + if input.len() % self.input_inks != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + self.to_pcs_impl(input) + } +} + +impl> KatanaFinalStage + for KatanaLut3xN +where + f32: AsPrimitive, +{ + fn to_output(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let grid_sizes: [u8; 16] = from_fn(|i| { + if i < self.output_inks { + self.grid_size + } else { + 0 + } + }); + + let md_lut = MultidimensionalLut::new(grid_sizes, 3, self.output_inks); + + let scale_value = if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + + let mut working = vec![0.; self.output_inks]; + + for (dest, src) in dst + .chunks_exact_mut(self.dst_layout.channels()) + .zip(src.chunks_exact(3)) + { + let x = lut_interp_linear_float(src[0], &self.linearization[0]); + let y = lut_interp_linear_float(src[1], &self.linearization[1]); + let z = lut_interp_linear_float(src[2], &self.linearization[2]); + + tetra_3i_to_any_vec(&md_lut, &self.clut, x, y, z, &mut working, self.output_inks); + + for (ink, curve) in working.iter_mut().zip(self.output.iter()) { + *ink = lut_interp_linear_float(*ink, curve); + } + + if T::FINITE { + for (dst, ink) in dest.iter_mut().zip(working.iter()) { + *dst = (*ink * scale_value).round().max(0.).min(scale_value).as_(); + } + } else { + for (dst, ink) in dest.iter_mut().zip(working.iter()) { + *dst = (*ink * scale_value).as_(); + } + } + } + + if self.dst_layout == Layout::Rgba && self.target_color_space == DataColorSpace::Rgb { + for dst in dst.chunks_exact_mut(self.dst_layout.channels()) { + dst[3] = scale_value.as_(); + } + } + + Ok(()) + } +} + +fn katana_make_lut_nx3>( + inks: usize, + lut: &LutDataType, + _: TransformOptions, + _: DataColorSpace, + bit_depth: usize, +) -> Result, CmsError> { + if inks != lut.num_input_channels as usize { + return Err(CmsError::UnsupportedProfileConnection); + } + if lut.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + let clut_length: usize = (lut.num_clut_grid_points as usize) + .safe_powi(lut.num_input_channels as u32)? + .safe_mul(lut.num_output_channels as usize)?; + + let clut_table = lut.clut_table.to_clut_f32(); + if clut_table.len() != clut_length { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut_table.len(), + expected: clut_length, + })); + } + + let linearization_table = lut.input_table.to_clut_f32(); + + if linearization_table.len() < lut.num_input_table_entries as usize * inks { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: linearization_table.len(), + expected: lut.num_input_table_entries as usize * inks, + })); + } + + let linearization = (0..inks) + .map(|x| { + linearization_table[x * lut.num_input_table_entries as usize + ..(x + 1) * lut.num_input_table_entries as usize] + .to_vec() + }) + .collect::<_>(); + + let gamma_table = lut.output_table.to_clut_f32(); + + if gamma_table.len() < lut.num_output_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: gamma_table.len(), + expected: lut.num_output_table_entries as usize * 3, + })); + } + + let gamma_curve0 = gamma_table[..lut.num_output_table_entries as usize].to_vec(); + let gamma_curve1 = gamma_table + [lut.num_output_table_entries as usize..lut.num_output_table_entries as usize * 2] + .to_vec(); + let gamma_curve2 = gamma_table + [lut.num_output_table_entries as usize * 2..lut.num_output_table_entries as usize * 3] + .to_vec(); + + let transform = KatanaLutNx3:: { + linearization, + clut: clut_table, + grid_size: lut.num_clut_grid_points, + output: [gamma_curve0, gamma_curve1, gamma_curve2], + input_inks: inks, + _phantom: PhantomData, + bit_depth, + }; + Ok(transform) +} + +fn katana_make_lut_3xn>( + inks: usize, + dst_layout: Layout, + lut: &LutDataType, + _: TransformOptions, + target_color_space: DataColorSpace, + bit_depth: usize, +) -> Result, CmsError> { + if lut.num_input_channels as usize != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + if target_color_space == DataColorSpace::Rgb { + if lut.num_output_channels != 3 || lut.num_output_channels != 4 { + return Err(CmsError::InvalidInksCountForProfile); + } + if dst_layout != Layout::Rgb || dst_layout != Layout::Rgba { + return Err(CmsError::InvalidInksCountForProfile); + } + } else if lut.num_output_channels as usize != dst_layout.channels() { + return Err(CmsError::InvalidInksCountForProfile); + } + let clut_length: usize = (lut.num_clut_grid_points as usize) + .safe_powi(lut.num_input_channels as u32)? + .safe_mul(lut.num_output_channels as usize)?; + + let clut_table = lut.clut_table.to_clut_f32(); + if clut_table.len() != clut_length { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut_table.len(), + expected: clut_length, + })); + } + + let linearization_table = lut.input_table.to_clut_f32(); + + if linearization_table.len() < lut.num_input_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: linearization_table.len(), + expected: lut.num_input_table_entries as usize * 3, + })); + } + + let linear_curve0 = linearization_table[..lut.num_input_table_entries as usize].to_vec(); + let linear_curve1 = linearization_table + [lut.num_input_table_entries as usize..lut.num_input_table_entries as usize * 2] + .to_vec(); + let linear_curve2 = linearization_table + [lut.num_input_table_entries as usize * 2..lut.num_input_table_entries as usize * 3] + .to_vec(); + + let gamma_table = lut.output_table.to_clut_f32(); + + if gamma_table.len() < lut.num_output_table_entries as usize * inks { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: gamma_table.len(), + expected: lut.num_output_table_entries as usize * inks, + })); + } + + let gamma = (0..inks) + .map(|x| { + gamma_table[x * lut.num_output_table_entries as usize + ..(x + 1) * lut.num_output_table_entries as usize] + .to_vec() + }) + .collect::<_>(); + + let transform = KatanaLut3xN:: { + linearization: [linear_curve0, linear_curve1, linear_curve2], + clut: clut_table, + grid_size: lut.num_clut_grid_points, + output: gamma, + output_inks: inks, + _phantom: PhantomData, + target_color_space, + dst_layout, + bit_depth, + }; + Ok(transform) +} + +pub(crate) fn katana_input_make_lut_nx3< + T: Copy + PointeeSizeExpressible + AsPrimitive + Send + Sync, +>( + src_layout: Layout, + inks: usize, + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> { + if pcs == DataColorSpace::Rgb { + if lut.num_input_channels != 3 { + return Err(CmsError::InvalidAtoBLut); + } + if src_layout != Layout::Rgba && src_layout != Layout::Rgb { + return Err(CmsError::InvalidInksCountForProfile); + } + } else if lut.num_input_channels != src_layout.channels() as u8 { + return Err(CmsError::InvalidInksCountForProfile); + } + let z0 = katana_make_lut_nx3::(inks, lut, options, pcs, bit_depth)?; + Ok(Box::new(z0)) +} + +pub(crate) fn katana_output_make_lut_3xn< + T: Copy + PointeeSizeExpressible + AsPrimitive + Send + Sync, +>( + dst_layout: Layout, + lut: &LutDataType, + options: TransformOptions, + target_color_space: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, +{ + let real_inks = if target_color_space == DataColorSpace::Rgb { + 3 + } else { + dst_layout.channels() + }; + let z0 = katana_make_lut_3xn::( + real_inks, + dst_layout, + lut, + options, + target_color_space, + bit_depth, + )?; + Ok(Box::new(z0)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod finalizers; +mod md3x3; +mod md4x3; +mod md_3xn; +mod md_nx3; +mod md_pipeline; +mod pcs_stages; +mod rgb_xyz; +mod stages; +mod xyz_lab; +mod xyz_rgb; + +pub(crate) use finalizers::{CopyAlphaStage, InjectAlphaStage}; +pub(crate) use md_3xn::katana_multi_dimensional_3xn_to_device; +pub(crate) use md_nx3::katana_multi_dimensional_nx3_to_pcs; +pub(crate) use md_pipeline::{katana_input_make_lut_nx3, katana_output_make_lut_3xn}; +pub(crate) use md3x3::{multi_dimensional_3x3_to_device, multi_dimensional_3x3_to_pcs}; +pub(crate) use md4x3::multi_dimensional_4x3_to_pcs; +pub(crate) use pcs_stages::{ + KatanaDefaultIntermediate, katana_pcs_lab_v2_to_v4, katana_pcs_lab_v4_to_v2, +}; +pub(crate) use rgb_xyz::katana_create_rgb_lin_lut; +pub(crate) use stages::{ + Katana, KatanaFinalStage, KatanaInitialStage, KatanaIntermediateStage, + KatanaPostFinalizationStage, +}; +pub(crate) use xyz_lab::{KatanaStageLabToXyz, KatanaStageXyzToLab}; +pub(crate) use xyz_rgb::katana_prepare_inverse_lut_rgb_xyz; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/pcs_stages.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/pcs_stages.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/pcs_stages.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/pcs_stages.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaIntermediateStage; +use crate::conversions::katana::stages::BlackholeIntermediateStage; +use crate::mlaf::mlaf; +use crate::{CmsError, ColorProfile, DataColorSpace, Matrix3f, ProfileVersion}; +use std::marker::PhantomData; + +pub(crate) struct KatanaMatrixStage { + pub(crate) matrices: Vec, +} + +impl KatanaMatrixStage { + pub(crate) fn new(matrix: Matrix3f) -> Self { + Self { + matrices: vec![matrix], + } + } +} + +pub(crate) type KatanaDefaultIntermediate = dyn KatanaIntermediateStage + Send + Sync; + +impl KatanaIntermediateStage for KatanaMatrixStage { + fn stage(&self, input: &mut Vec) -> Result, CmsError> { + if input.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + for m in self.matrices.iter() { + for dst in input.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + Ok(std::mem::take(input)) + } +} + +pub(crate) fn katana_pcs_lab_v4_to_v2(profile: &ColorProfile) -> Box { + if profile.pcs == DataColorSpace::Lab && profile.version_internal <= ProfileVersion::V4_0 { + let v_mat = vec![Matrix3f { + v: [ + [65280.0 / 65535.0, 0., 0.], + [0., 65280.0 / 65535.0, 0.], + [0., 0., 65280.0 / 65535.0], + ], + }]; + return Box::new(KatanaMatrixStage { matrices: v_mat }); + } + Box::new(BlackholeIntermediateStage { + _phantom: PhantomData, + }) +} + +pub(crate) fn katana_pcs_lab_v2_to_v4(profile: &ColorProfile) -> Box { + if profile.pcs == DataColorSpace::Lab && profile.version_internal <= ProfileVersion::V4_0 { + let v_mat = vec![Matrix3f { + v: [ + [65535.0 / 65280.0, 0., 0.], + [0., 65535.0 / 65280.0, 0.], + [0., 0., 65535.0 / 65280.0], + ], + }]; + return Box::new(KatanaMatrixStage { matrices: v_mat }); + } + Box::new(BlackholeIntermediateStage { + _phantom: PhantomData, + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/rgb_xyz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/rgb_xyz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/rgb_xyz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/rgb_xyz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,162 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::pcs_stages::KatanaMatrixStage; +use crate::conversions::katana::{KatanaInitialStage, KatanaIntermediateStage}; +use crate::err::try_vec; +use crate::{CmsError, ColorProfile, Layout, Matrix3f, PointeeSizeExpressible, TransformOptions}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +struct KatanaRgbLinearizationStage { + r_lin: Box<[f32; LINEAR_CAP]>, + g_lin: Box<[f32; LINEAR_CAP]>, + b_lin: Box<[f32; LINEAR_CAP]>, + linear_cap: usize, + bit_depth: usize, + _phantom: PhantomData, +} + +impl< + T: Clone + AsPrimitive + PointeeSizeExpressible, + const LAYOUT: u8, + const LINEAR_CAP: usize, +> KatanaInitialStage for KatanaRgbLinearizationStage +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + let src_layout = Layout::from(LAYOUT); + if input.len() % src_layout.channels() != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let mut dst = try_vec![0.; input.len() / src_layout.channels() * 3]; + + let scale = if T::FINITE { + (self.linear_cap as f32 - 1.) / ((1 << self.bit_depth) - 1) as f32 + } else { + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 + }; + + let cap_value = if T::FINITE { + ((1 << self.bit_depth) - 1) as f32 + } else { + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 + }; + + for (src, dst) in input + .chunks_exact(src_layout.channels()) + .zip(dst.chunks_exact_mut(3)) + { + let j_r = src[0].as_() * scale; + let j_g = src[1].as_() * scale; + let j_b = src[2].as_() * scale; + dst[0] = self.r_lin[(j_r.round().min(cap_value).max(0.) as u16) as usize]; + dst[1] = self.g_lin[(j_g.round().min(cap_value).max(0.) as u16) as usize]; + dst[2] = self.b_lin[(j_b.round().min(cap_value).max(0.) as u16) as usize]; + } + Ok(dst) + } +} + +pub(crate) struct KatanaRgbLinearizationState { + pub(crate) stages: Vec + Send + Sync>>, + pub(crate) initial_stage: Box + Send + Sync>, +} + +pub(crate) fn katana_create_rgb_lin_lut< + T: Copy + Default + AsPrimitive + Send + Sync + AsPrimitive + PointeeSizeExpressible, + const BIT_DEPTH: usize, + const LINEAR_CAP: usize, +>( + layout: Layout, + source: &ColorProfile, + opts: TransformOptions, +) -> Result, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + let lin_r = + source.build_r_linearize_table::(opts.allow_use_cicp_transfer)?; + let lin_g = + source.build_g_linearize_table::(opts.allow_use_cicp_transfer)?; + let lin_b = + source.build_b_linearize_table::(opts.allow_use_cicp_transfer)?; + + let lin_stage: Box + Send + Sync> = match layout { + Layout::Rgb => { + Box::new( + KatanaRgbLinearizationStage:: { + r_lin: lin_r, + g_lin: lin_g, + b_lin: lin_b, + bit_depth: BIT_DEPTH, + linear_cap: LINEAR_CAP, + _phantom: PhantomData, + }, + ) + } + Layout::Rgba => { + Box::new( + KatanaRgbLinearizationStage:: { + r_lin: lin_r, + g_lin: lin_g, + b_lin: lin_b, + bit_depth: BIT_DEPTH, + linear_cap: LINEAR_CAP, + _phantom: PhantomData, + }, + ) + } + Layout::Gray => return Err(CmsError::UnsupportedProfileConnection), + Layout::GrayAlpha => { + return Err(CmsError::UnsupportedProfileConnection); + } + _ => return Err(CmsError::UnsupportedProfileConnection), + }; + + let xyz_to_rgb = source.rgb_to_xyz_matrix(); + + let matrices: Vec + Send + Sync>> = + vec![Box::new(KatanaMatrixStage { + matrices: vec![ + xyz_to_rgb.to_f32(), + Matrix3f { + v: [ + [32768.0 / 65535.0, 0.0, 0.0], + [0.0, 32768.0 / 65535.0, 0.0], + [0.0, 0.0, 32768.0 / 65535.0], + ], + }, + ], + })]; + + Ok(KatanaRgbLinearizationState { + stages: matrices, + initial_stage: lin_stage, + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/stages.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/stages.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/stages.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/stages.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::{CmsError, TransformExecutor}; +use std::marker::PhantomData; + +/// W storage working data type +/// I input/output data type +pub(crate) trait KatanaInitialStage { + fn to_pcs(&self, input: &[I]) -> Result, CmsError>; +} + +/// W storage working data type +/// I input/output data type +pub(crate) trait KatanaFinalStage { + fn to_output(&self, src: &mut [W], dst: &mut [I]) -> Result<(), CmsError>; +} + +/// W storage working data type +pub(crate) trait KatanaIntermediateStage { + fn stage(&self, input: &mut Vec) -> Result, CmsError>; +} + +pub(crate) struct BlackholeIntermediateStage { + pub(crate) _phantom: PhantomData, +} + +impl KatanaIntermediateStage for BlackholeIntermediateStage { + fn stage(&self, input: &mut Vec) -> Result, CmsError> { + Ok(std::mem::take(input)) + } +} + +/// I input/output data type +pub(crate) trait KatanaPostFinalizationStage { + fn finalize(&self, src: &[I], dst: &mut [I]) -> Result<(), CmsError>; +} + +/// W storage working data type +/// I input/output data type +pub(crate) struct Katana { + pub(crate) initial_stage: Box + Send + Sync>, + pub(crate) final_stage: Box + Sync + Send>, + pub(crate) stages: Vec + Send + Sync>>, + pub(crate) post_finalization: Vec + Send + Sync>>, +} + +impl TransformExecutor for Katana { + fn transform(&self, src: &[I], dst: &mut [I]) -> Result<(), CmsError> { + let mut working_vec = self.initial_stage.to_pcs(src)?; + for stage in self.stages.iter() { + working_vec = stage.stage(&mut working_vec)?; + } + self.final_stage.to_output(&mut working_vec, dst)?; + for finalization in self.post_finalization.iter() { + finalization.finalize(src, dst)?; + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_lab.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_lab.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_lab.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_lab.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaIntermediateStage; +use crate::{CmsError, Lab, Xyz}; + +#[derive(Default)] +pub(crate) struct KatanaStageLabToXyz {} + +impl KatanaIntermediateStage for KatanaStageLabToXyz { + fn stage(&self, input: &mut Vec) -> Result, CmsError> { + for dst in input.chunks_exact_mut(3) { + let lab = Lab::new(dst[0], dst[1], dst[2]); + let xyz = lab.to_pcs_xyz(); + dst[0] = xyz.x; + dst[1] = xyz.y; + dst[2] = xyz.z; + } + Ok(std::mem::take(input)) + } +} + +#[derive(Default)] +pub(crate) struct KatanaStageXyzToLab {} + +impl KatanaIntermediateStage for KatanaStageXyzToLab { + fn stage(&self, input: &mut Vec) -> Result, CmsError> { + for dst in input.chunks_exact_mut(3) { + let xyz = Xyz::new(dst[0], dst[1], dst[2]); + let lab = Lab::from_pcs_xyz(xyz); + dst[0] = lab.l; + dst[1] = lab.a; + dst[2] = lab.b; + } + Ok(std::mem::take(input)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/katana/xyz_rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::pcs_stages::KatanaMatrixStage; +use crate::conversions::katana::{ + KatanaDefaultIntermediate, KatanaFinalStage, KatanaIntermediateStage, +}; +use crate::mlaf::mlaf; +use crate::{ + CmsError, ColorProfile, GammaLutInterpolate, Layout, Matrix3f, PointeeSizeExpressible, + RenderingIntent, Rgb, TransformOptions, filmlike_clip, +}; +use num_traits::AsPrimitive; + +pub(crate) struct KatanaXyzToRgbStage { + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) intent: RenderingIntent, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl + PointeeSizeExpressible, const LAYOUT: u8> + KatanaFinalStage for KatanaXyzToRgbStage +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn to_output(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + let dst_cn = Layout::from(LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 3; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + let max_colors: T = (if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }) + .as_(); + let lut_cap = (self.gamma_lut - 1) as f32; + + if self.intent != RenderingIntent::AbsoluteColorimetric { + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(dst_channels)) { + let mut rgb = Rgb::new(src[0], src[1], src[2]); + if rgb.is_out_of_gamut() { + rgb = filmlike_clip(rgb); + } + let r = mlaf(0.5, rgb.r, lut_cap).min(lut_cap).max(0.) as u16; + let g = mlaf(0.5, rgb.g, lut_cap).min(lut_cap).max(0.) as u16; + let b = mlaf(0.5, rgb.b, lut_cap).min(lut_cap).max(0.) as u16; + + dst[0] = self.r_gamma[r as usize]; + dst[1] = self.g_gamma[g as usize]; + dst[2] = self.b_gamma[b as usize]; + if dst_cn == Layout::Rgba { + dst[3] = max_colors; + } + } + } else { + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(dst_channels)) { + let rgb = Rgb::new(src[0], src[1], src[2]); + let r = mlaf(0.5, rgb.r, lut_cap).min(lut_cap).max(0.) as u16; + let g = mlaf(0.5, rgb.g, lut_cap).min(lut_cap).max(0.) as u16; + let b = mlaf(0.5, rgb.b, lut_cap).min(lut_cap).max(0.) as u16; + + dst[0] = self.r_gamma[r as usize]; + dst[1] = self.g_gamma[g as usize]; + dst[2] = self.b_gamma[b as usize]; + if dst_cn == Layout::Rgba { + dst[3] = max_colors; + } + } + } + + Ok(()) + } +} + +pub(crate) struct KatanaXyzRgbState { + pub(crate) stages: Vec + Send + Sync>>, + pub(crate) final_stage: Box + Send + Sync>, +} + +pub(crate) fn katana_prepare_inverse_lut_rgb_xyz< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible + + GammaLutInterpolate, + const BIT_DEPTH: usize, + const GAMMA_LUT: usize, +>( + dest: &ColorProfile, + dest_layout: Layout, + options: TransformOptions, +) -> Result, CmsError> +where + f32: AsPrimitive, + u32: AsPrimitive, +{ + // if !T::FINITE { + // if let Some(extended_gamma) = dest.try_extended_gamma_evaluator() { + // let xyz_to_rgb = dest.rgb_to_xyz_matrix().inverse(); + // + // let mut matrices = vec![Matrix3f { + // v: [ + // [65535.0 / 32768.0, 0.0, 0.0], + // [0.0, 65535.0 / 32768.0, 0.0], + // [0.0, 0.0, 65535.0 / 32768.0], + // ], + // }]; + // + // matrices.push(xyz_to_rgb.to_f32()); + // let xyz_to_rgb_stage = XyzToRgbStageExtended:: { + // gamma_evaluator: extended_gamma, + // matrices, + // phantom_data: PhantomData, + // }; + // xyz_to_rgb_stage.transform(lut)?; + // return Ok(()); + // } + // } + let gamma_map_r = dest.build_gamma_table::( + &dest.red_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_map_g = dest.build_gamma_table::( + &dest.green_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_map_b = dest.build_gamma_table::( + &dest.blue_trc, + options.allow_use_cicp_transfer, + )?; + + let xyz_to_rgb = dest.rgb_to_xyz_matrix().inverse(); + + let mut matrices: Vec> = + vec![Box::new(KatanaMatrixStage::new(Matrix3f { + v: [ + [65535.0 / 32768.0, 0.0, 0.0], + [0.0, 65535.0 / 32768.0, 0.0], + [0.0, 0.0, 65535.0 / 32768.0], + ], + }))]; + + matrices.push(Box::new(KatanaMatrixStage::new(xyz_to_rgb.to_f32()))); + match dest_layout { + Layout::Rgb => { + let xyz_to_rgb_stage = KatanaXyzToRgbStage:: { + r_gamma: gamma_map_r, + g_gamma: gamma_map_g, + b_gamma: gamma_map_b, + intent: options.rendering_intent, + bit_depth: BIT_DEPTH, + gamma_lut: GAMMA_LUT, + }; + Ok(KatanaXyzRgbState { + stages: matrices, + final_stage: Box::new(xyz_to_rgb_stage), + }) + } + Layout::Rgba => { + let xyz_to_rgb_stage = KatanaXyzToRgbStage:: { + r_gamma: gamma_map_r, + g_gamma: gamma_map_g, + b_gamma: gamma_map_b, + intent: options.rendering_intent, + bit_depth: BIT_DEPTH, + gamma_lut: GAMMA_LUT, + }; + Ok(KatanaXyzRgbState { + stages: matrices, + final_stage: Box::new(xyz_to_rgb_stage), + }) + } + Layout::Gray => unreachable!("Gray layout must not be called on Rgb/Rgba path"), + Layout::GrayAlpha => unreachable!("Gray layout must not be called on Rgb/Rgba path"), + _ => unreachable!( + "layout {:?} should not be called on xyz->rgb path", + dest_layout + ), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,428 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::{KatanaFinalStage, KatanaInitialStage}; +use crate::err::{MalformedSize, try_vec}; +use crate::profile::LutDataType; +use crate::safe_math::{SafeMul, SafePowi}; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, Cube, DataColorSpace, InterpolationMethod, PointeeSizeExpressible, Stage, + TransformOptions, Vector3f, +}; +use num_traits::AsPrimitive; + +#[derive(Default)] +struct Lut3x3 { + input: [Vec; 3], + clut: Vec, + grid_size: u8, + gamma: [Vec; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +#[derive(Default)] +struct KatanaLut3x3 { + input: [Vec; 3], + clut: Vec, + grid_size: u8, + gamma: [Vec; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + _phantom: std::marker::PhantomData, + bit_depth: usize, +} + +fn make_lut_3x3( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result { + let clut_length: usize = (lut.num_clut_grid_points as usize) + .safe_powi(lut.num_input_channels as u32)? + .safe_mul(lut.num_output_channels as usize)?; + + let lin_table = lut.input_table.to_clut_f32(); + + if lin_table.len() < lut.num_input_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: lin_table.len(), + expected: lut.num_input_table_entries as usize * 3, + })); + } + + let lin_curve0 = lin_table[..lut.num_input_table_entries as usize].to_vec(); + let lin_curve1 = lin_table + [lut.num_input_table_entries as usize..lut.num_input_table_entries as usize * 2] + .to_vec(); + let lin_curve2 = lin_table + [lut.num_input_table_entries as usize * 2..lut.num_input_table_entries as usize * 3] + .to_vec(); + + let clut_table = lut.clut_table.to_clut_f32(); + if clut_table.len() != clut_length { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut_table.len(), + expected: clut_length, + })); + } + + let gamma_curves = lut.output_table.to_clut_f32(); + + if gamma_curves.len() < lut.num_output_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: gamma_curves.len(), + expected: lut.num_output_table_entries as usize * 3, + })); + } + + let gamma_curve0 = gamma_curves[..lut.num_output_table_entries as usize].to_vec(); + let gamma_curve1 = gamma_curves + [lut.num_output_table_entries as usize..lut.num_output_table_entries as usize * 2] + .to_vec(); + let gamma_curve2 = gamma_curves + [lut.num_output_table_entries as usize * 2..lut.num_output_table_entries as usize * 3] + .to_vec(); + + let transform = Lut3x3 { + input: [lin_curve0, lin_curve1, lin_curve2], + gamma: [gamma_curve0, gamma_curve1, gamma_curve2], + interpolation_method: options.interpolation_method, + clut: clut_table, + grid_size: lut.num_clut_grid_points, + pcs, + }; + + Ok(transform) +} + +fn stage_lut_3x3( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + let lut = make_lut_3x3(lut, options, pcs)?; + + let transform = Lut3x3 { + input: lut.input, + gamma: lut.gamma, + interpolation_method: lut.interpolation_method, + clut: lut.clut, + grid_size: lut.grid_size, + pcs: lut.pcs, + }; + + Ok(Box::new(transform)) +} + +pub(crate) fn katana_input_stage_lut_3x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, +{ + let lut = make_lut_3x3(lut, options, pcs)?; + + let transform = KatanaLut3x3:: { + input: lut.input, + gamma: lut.gamma, + interpolation_method: lut.interpolation_method, + clut: lut.clut, + grid_size: lut.grid_size, + pcs: lut.pcs, + _phantom: std::marker::PhantomData, + bit_depth, + }; + + Ok(Box::new(transform)) +} + +pub(crate) fn katana_output_stage_lut_3x3< + T: Copy + Default + AsPrimitive + PointeeSizeExpressible + Send + Sync, +>( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, +{ + let lut = make_lut_3x3(lut, options, pcs)?; + + let transform = KatanaLut3x3:: { + input: lut.input, + gamma: lut.gamma, + interpolation_method: lut.interpolation_method, + clut: lut.clut, + grid_size: lut.grid_size, + pcs: lut.pcs, + _phantom: std::marker::PhantomData, + bit_depth, + }; + + Ok(Box::new(transform)) +} + +impl Lut3x3 { + fn transform_impl Vector3f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let linearization_0 = &self.input[0]; + let linearization_1 = &self.input[1]; + let linearization_2 = &self.input[2]; + for (dest, src) in dst.chunks_exact_mut(3).zip(src.chunks_exact(3)) { + debug_assert!(self.grid_size as i32 >= 1); + let linear_x = lut_interp_linear_float(src[0], linearization_0); + let linear_y = lut_interp_linear_float(src[1], linearization_1); + let linear_z = lut_interp_linear_float(src[2], linearization_2); + + let clut = fetch(linear_x, linear_y, linear_z); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.gamma[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.gamma[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.gamma[2]); + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + } + Ok(()) + } +} + +impl Stage for Lut3x3 { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let l_tbl = Cube::new_checked(&self.clut, self.grid_size as usize, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z| l_tbl.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z| l_tbl.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z| l_tbl.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z| l_tbl.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z| l_tbl.trilinear_vec3(x, y, z))?; + } + } + Ok(()) + } +} + +impl> KatanaLut3x3 +where + f32: AsPrimitive, +{ + fn to_pcs_impl Vector3f>( + &self, + input: &[T], + fetch: Fetch, + ) -> Result, CmsError> { + if input.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let normalizing_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + let mut dst = try_vec![0.; input.len()]; + let linearization_0 = &self.input[0]; + let linearization_1 = &self.input[1]; + let linearization_2 = &self.input[2]; + for (dest, src) in dst.chunks_exact_mut(3).zip(input.chunks_exact(3)) { + let linear_x = + lut_interp_linear_float(src[0].as_() * normalizing_value, linearization_0); + let linear_y = + lut_interp_linear_float(src[1].as_() * normalizing_value, linearization_1); + let linear_z = + lut_interp_linear_float(src[2].as_() * normalizing_value, linearization_2); + + let clut = fetch(linear_x, linear_y, linear_z); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.gamma[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.gamma[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.gamma[2]); + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + } + Ok(dst) + } + + fn to_output Vector3f>( + &self, + src: &[f32], + dst: &mut [T], + fetch: Fetch, + ) -> Result<(), CmsError> { + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() != src.len() { + return Err(CmsError::LaneSizeMismatch); + } + let norm_value = if T::FINITE { + ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + + let linearization_0 = &self.input[0]; + let linearization_1 = &self.input[1]; + let linearization_2 = &self.input[2]; + for (dest, src) in dst.chunks_exact_mut(3).zip(src.chunks_exact(3)) { + let linear_x = lut_interp_linear_float(src[0], linearization_0); + let linear_y = lut_interp_linear_float(src[1], linearization_1); + let linear_z = lut_interp_linear_float(src[2], linearization_2); + + let clut = fetch(linear_x, linear_y, linear_z); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.gamma[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.gamma[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.gamma[2]); + + if T::FINITE { + dest[0] = (pcs_x * norm_value).round().max(0.0).min(norm_value).as_(); + dest[1] = (pcs_y * norm_value).round().max(0.0).min(norm_value).as_(); + dest[2] = (pcs_z * norm_value).round().max(0.0).min(norm_value).as_(); + } else { + dest[0] = pcs_x.as_(); + dest[1] = pcs_y.as_(); + dest[2] = pcs_z.as_(); + } + } + Ok(()) + } +} + +impl> KatanaInitialStage + for KatanaLut3x3 +where + f32: AsPrimitive, +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + let l_tbl = Cube::new_checked(&self.clut, self.grid_size as usize, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.to_pcs_impl(input, |x, y, z| l_tbl.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_pcs_impl(input, |x, y, z| l_tbl.tetra_vec3(x, y, z)) + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_pcs_impl(input, |x, y, z| l_tbl.pyramid_vec3(x, y, z)) + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_pcs_impl(input, |x, y, z| l_tbl.prism_vec3(x, y, z)) + } + InterpolationMethod::Linear => { + self.to_pcs_impl(input, |x, y, z| l_tbl.trilinear_vec3(x, y, z)) + } + } + } +} + +impl> KatanaFinalStage + for KatanaLut3x3 +where + f32: AsPrimitive, +{ + fn to_output(&self, src: &mut [f32], dst: &mut [T]) -> Result<(), CmsError> { + let l_tbl = Cube::new_checked(&self.clut, self.grid_size as usize, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.to_output(src, dst, |x, y, z| l_tbl.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_output(src, dst, |x, y, z| l_tbl.tetra_vec3(x, y, z)) + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_output(src, dst, |x, y, z| l_tbl.pyramid_vec3(x, y, z)) + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_output(src, dst, |x, y, z| l_tbl.prism_vec3(x, y, z)) + } + InterpolationMethod::Linear => { + self.to_output(src, dst, |x, y, z| l_tbl.trilinear_vec3(x, y, z)) + } + } + } +} + +pub(crate) fn create_lut3x3( + lut: &LutDataType, + src: &[f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + if lut.num_input_channels != 3 || lut.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + + let mut dest = try_vec![0.; src.len()]; + + let lut_stage = stage_lut_3x3(lut, options, pcs)?; + lut_stage.transform(src, &mut dest)?; + Ok(dest) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x4.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut3x4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::err::try_vec; +use crate::profile::LutDataType; +use crate::safe_math::{SafeMul, SafePowi}; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, Cube, DataColorSpace, InterpolationMethod, MalformedSize, Stage, TransformOptions, + Vector4f, +}; +use num_traits::AsPrimitive; + +#[derive(Default)] +struct Lut3x4 { + input: [Vec; 3], + clut: Vec, + grid_size: u8, + gamma: [Vec; 4], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +fn make_lut_3x4( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result { + let clut_length: usize = (lut.num_clut_grid_points as usize) + .safe_powi(lut.num_input_channels as u32)? + .safe_mul(lut.num_output_channels as usize)?; + + let clut_table = lut.clut_table.to_clut_f32(); + if clut_table.len() != clut_length { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut_table.len(), + expected: clut_length, + })); + } + + let linearization_table = lut.input_table.to_clut_f32(); + + if linearization_table.len() < lut.num_input_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: linearization_table.len(), + expected: lut.num_input_table_entries as usize * 3, + })); + } + + let linear_curve0 = linearization_table[..lut.num_input_table_entries as usize].to_vec(); + let linear_curve1 = linearization_table + [lut.num_input_table_entries as usize..lut.num_input_table_entries as usize * 2] + .to_vec(); + let linear_curve2 = linearization_table + [lut.num_input_table_entries as usize * 2..lut.num_input_table_entries as usize * 3] + .to_vec(); + + let gamma_table = lut.output_table.to_clut_f32(); + + if gamma_table.len() < lut.num_output_table_entries as usize * 4 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: gamma_table.len(), + expected: lut.num_output_table_entries as usize * 4, + })); + } + + let gamma_curve0 = gamma_table[..lut.num_output_table_entries as usize].to_vec(); + let gamma_curve1 = gamma_table + [lut.num_output_table_entries as usize..lut.num_output_table_entries as usize * 2] + .to_vec(); + let gamma_curve2 = gamma_table + [lut.num_output_table_entries as usize * 2..lut.num_output_table_entries as usize * 3] + .to_vec(); + let gamma_curve3 = gamma_table + [lut.num_output_table_entries as usize * 3..lut.num_output_table_entries as usize * 4] + .to_vec(); + + let transform = Lut3x4 { + input: [linear_curve0, linear_curve1, linear_curve2], + interpolation_method: options.interpolation_method, + clut: clut_table, + grid_size: lut.num_clut_grid_points, + pcs, + gamma: [gamma_curve0, gamma_curve1, gamma_curve2, gamma_curve3], + }; + Ok(transform) +} + +fn stage_lut_3x4( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + let lut = make_lut_3x4(lut, options, pcs)?; + + let transform = Lut3x4 { + input: lut.input, + interpolation_method: lut.interpolation_method, + clut: lut.clut, + grid_size: lut.grid_size, + pcs: lut.pcs, + gamma: lut.gamma, + }; + Ok(Box::new(transform)) +} + +impl Lut3x4 { + fn transform_impl Vector4f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let linearization_0 = &self.input[0]; + let linearization_1 = &self.input[1]; + let linearization_2 = &self.input[2]; + for (dest, src) in dst.chunks_exact_mut(4).zip(src.chunks_exact(3)) { + debug_assert!(self.grid_size as i32 >= 1); + let linear_x = lut_interp_linear_float(src[0], linearization_0); + let linear_y = lut_interp_linear_float(src[1], linearization_1); + let linear_z = lut_interp_linear_float(src[2], linearization_2); + + let clut = fetch(linear_x, linear_y, linear_z); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.gamma[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.gamma[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.gamma[2]); + let pcs_w = lut_interp_linear_float(clut.v[3], &self.gamma[3]); + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + dest[3] = pcs_w; + } + Ok(()) + } +} + +impl Stage for Lut3x4 { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let l_tbl = Cube::new_checked(&self.clut, self.grid_size as usize, 4)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z| l_tbl.trilinear_vec4(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z| l_tbl.tetra_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z| l_tbl.pyramid_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z| l_tbl.prism_vec4(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z| l_tbl.trilinear_vec4(x, y, z))?; + } + } + Ok(()) + } +} + +pub(crate) fn create_lut3_samples() -> Vec +where + u32: AsPrimitive, +{ + let lut_size: u32 = (3 * SAMPLES * SAMPLES * SAMPLES) as u32; + + assert!(SAMPLES >= 1); + + let mut src = Vec::with_capacity(lut_size as usize); + for x in 0..SAMPLES as u32 { + for y in 0..SAMPLES as u32 { + for z in 0..SAMPLES as u32 { + src.push(x.as_()); + src.push(y.as_()); + src.push(z.as_()); + } + } + } + src +} + +pub(crate) fn create_lut3_samples_norm() -> Vec { + let lut_size: u32 = (3 * SAMPLES * SAMPLES * SAMPLES) as u32; + + assert!(SAMPLES >= 1); + + let scale = 1. / (SAMPLES as f32 - 1.0); + + let mut src = Vec::with_capacity(lut_size as usize); + for x in 0..SAMPLES as u32 { + for y in 0..SAMPLES as u32 { + for z in 0..SAMPLES as u32 { + src.push(x as f32 * scale); + src.push(y as f32 * scale); + src.push(z as f32 * scale); + } + } + } + src +} + +pub(crate) fn create_lut3x4( + lut: &LutDataType, + src: &[f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + if lut.num_input_channels != 3 || lut.num_output_channels != 4 { + return Err(CmsError::UnsupportedProfileConnection); + } + + let mut dest = try_vec![0.; (src.len() / 3) * 4]; + + let lut_stage = stage_lut_3x4(lut, options, pcs)?; + lut_stage.transform(src, &mut dest)?; + Ok(dest) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut4.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,360 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::katana::KatanaInitialStage; +use crate::err::try_vec; +use crate::profile::LutDataType; +use crate::safe_math::{SafeMul, SafePowi}; +use crate::trc::lut_interp_linear_float; +use crate::{ + CmsError, DataColorSpace, Hypercube, InterpolationMethod, MalformedSize, + PointeeSizeExpressible, Stage, TransformOptions, Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +#[allow(unused)] +#[derive(Default)] +struct Lut4x3 { + linearization: [Vec; 4], + clut: Vec, + grid_size: u8, + output: [Vec; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +#[allow(unused)] +#[derive(Default)] +struct KatanaLut4x3> { + linearization: [Vec; 4], + clut: Vec, + grid_size: u8, + output: [Vec; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + _phantom: PhantomData, + bit_depth: usize, +} + +#[allow(unused)] +impl Lut4x3 { + fn transform_impl Vector3f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let linearization_0 = &self.linearization[0]; + let linearization_1 = &self.linearization[1]; + let linearization_2 = &self.linearization[2]; + let linearization_3 = &self.linearization[3]; + for (dest, src) in dst.chunks_exact_mut(3).zip(src.chunks_exact(4)) { + debug_assert!(self.grid_size as i32 >= 1); + let linear_x = lut_interp_linear_float(src[0], linearization_0); + let linear_y = lut_interp_linear_float(src[1], linearization_1); + let linear_z = lut_interp_linear_float(src[2], linearization_2); + let linear_w = lut_interp_linear_float(src[3], linearization_3); + + let clut = fetch(linear_x, linear_y, linear_z, linear_w); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.output[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.output[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.output[2]); + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + } + Ok(()) + } +} + +macro_rules! define_lut4_dispatch { + ($dispatcher: ident) => { + impl Stage for $dispatcher { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let l_tbl = Hypercube::new_checked(&self.clut, self.grid_size as usize, 3)?; + + // If Source PCS is LAB trilinear should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self + .transform_impl(src, dst, |x, y, z, w| l_tbl.quadlinear_vec3(x, y, z, w)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z, w| l_tbl.tetra_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z, w| l_tbl.pyramid_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z, w| l_tbl.prism_vec3(x, y, z, w))? + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z, w| { + l_tbl.quadlinear_vec3(x, y, z, w) + })? + } + } + Ok(()) + } + } + }; +} + +impl> KatanaLut4x3 { + fn to_pcs_impl Vector3f>( + &self, + input: &[T], + fetch: Fetch, + ) -> Result, CmsError> { + if input.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let norm_value = if T::FINITE { + 1.0 / ((1u32 << self.bit_depth) - 1) as f32 + } else { + 1.0 + }; + let mut dst = try_vec![0.; (input.len() / 4) * 3]; + let linearization_0 = &self.linearization[0]; + let linearization_1 = &self.linearization[1]; + let linearization_2 = &self.linearization[2]; + let linearization_3 = &self.linearization[3]; + for (dest, src) in dst.chunks_exact_mut(3).zip(input.chunks_exact(4)) { + let linear_x = lut_interp_linear_float(src[0].as_() * norm_value, linearization_0); + let linear_y = lut_interp_linear_float(src[1].as_() * norm_value, linearization_1); + let linear_z = lut_interp_linear_float(src[2].as_() * norm_value, linearization_2); + let linear_w = lut_interp_linear_float(src[3].as_() * norm_value, linearization_3); + + let clut = fetch(linear_x, linear_y, linear_z, linear_w); + + let pcs_x = lut_interp_linear_float(clut.v[0], &self.output[0]); + let pcs_y = lut_interp_linear_float(clut.v[1], &self.output[1]); + let pcs_z = lut_interp_linear_float(clut.v[2], &self.output[2]); + dest[0] = pcs_x; + dest[1] = pcs_y; + dest[2] = pcs_z; + } + Ok(dst) + } +} + +impl> KatanaInitialStage + for KatanaLut4x3 +{ + fn to_pcs(&self, input: &[T]) -> Result, CmsError> { + if input.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let l_tbl = Hypercube::new_checked(&self.clut, self.grid_size as usize, 3)?; + + // If Source PCS is LAB trilinear should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.to_pcs_impl(input, |x, y, z, w| l_tbl.quadlinear_vec3(x, y, z, w)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.to_pcs_impl(input, |x, y, z, w| l_tbl.tetra_vec3(x, y, z, w)) + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.to_pcs_impl(input, |x, y, z, w| l_tbl.pyramid_vec3(x, y, z, w)) + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.to_pcs_impl(input, |x, y, z, w| l_tbl.prism_vec3(x, y, z, w)) + } + InterpolationMethod::Linear => { + self.to_pcs_impl(input, |x, y, z, w| l_tbl.quadlinear_vec3(x, y, z, w)) + } + } + } +} + +define_lut4_dispatch!(Lut4x3); + +fn make_lut_4x3( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result { + // There is 4 possible cases: + // - All curves are non-linear + // - Linearization curves are non-linear, but gamma is linear + // - Gamma curves are non-linear, but linearization is linear + // - All curves linear + let clut_length: usize = (lut.num_clut_grid_points as usize) + .safe_powi(lut.num_input_channels as u32)? + .safe_mul(lut.num_output_channels as usize)?; + + let clut_table = lut.clut_table.to_clut_f32(); + if clut_table.len() != clut_length { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut_table.len(), + expected: clut_length, + })); + } + + let linearization_table = lut.input_table.to_clut_f32(); + + if linearization_table.len() < lut.num_input_table_entries as usize * 4 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: linearization_table.len(), + expected: lut.num_input_table_entries as usize * 4, + })); + } + + let lin_curve0 = linearization_table[0..lut.num_input_table_entries as usize].to_vec(); + let lin_curve1 = linearization_table + [lut.num_input_table_entries as usize..lut.num_input_table_entries as usize * 2] + .to_vec(); + let lin_curve2 = linearization_table + [lut.num_input_table_entries as usize * 2..lut.num_input_table_entries as usize * 3] + .to_vec(); + let lin_curve3 = linearization_table + [lut.num_input_table_entries as usize * 3..lut.num_input_table_entries as usize * 4] + .to_vec(); + + let gamma_table = lut.output_table.to_clut_f32(); + + if gamma_table.len() < lut.num_output_table_entries as usize * 3 { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: gamma_table.len(), + expected: lut.num_output_table_entries as usize * 3, + })); + } + + let gamma_curve0 = gamma_table[..lut.num_output_table_entries as usize].to_vec(); + let gamma_curve1 = gamma_table + [lut.num_output_table_entries as usize..lut.num_output_table_entries as usize * 2] + .to_vec(); + let gamma_curve2 = gamma_table + [lut.num_output_table_entries as usize * 2..lut.num_output_table_entries as usize * 3] + .to_vec(); + + let transform = Lut4x3 { + linearization: [lin_curve0, lin_curve1, lin_curve2, lin_curve3], + interpolation_method: options.interpolation_method, + pcs, + clut: clut_table, + grid_size: lut.num_clut_grid_points, + output: [gamma_curve0, gamma_curve1, gamma_curve2], + }; + Ok(transform) +} + +fn stage_lut_4x3( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + let lut = make_lut_4x3(lut, options, pcs)?; + let transform = Lut4x3 { + linearization: lut.linearization, + interpolation_method: lut.interpolation_method, + pcs: lut.pcs, + clut: lut.clut, + grid_size: lut.grid_size, + output: lut.output, + }; + Ok(Box::new(transform)) +} + +pub(crate) fn katana_input_stage_lut_4x3< + T: Copy + PointeeSizeExpressible + AsPrimitive + Send + Sync, +>( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> { + // There is 4 possible cases: + // - All curves are non-linear + // - Linearization curves are non-linear, but gamma is linear + // - Gamma curves are non-linear, but linearization is linear + // - All curves linear + let lut = make_lut_4x3(lut, options, pcs)?; + + let transform = KatanaLut4x3:: { + linearization: lut.linearization, + interpolation_method: lut.interpolation_method, + pcs: lut.pcs, + clut: lut.clut, + grid_size: lut.grid_size, + output: lut.output, + _phantom: PhantomData, + bit_depth, + }; + Ok(Box::new(transform)) +} + +pub(crate) fn create_lut4_norm_samples() -> Vec { + let lut_size: u32 = (4 * SAMPLES * SAMPLES * SAMPLES * SAMPLES) as u32; + + let mut src = Vec::with_capacity(lut_size as usize); + + let recpeq = 1f32 / (SAMPLES - 1) as f32; + for k in 0..SAMPLES { + for c in 0..SAMPLES { + for m in 0..SAMPLES { + for y in 0..SAMPLES { + src.push(c as f32 * recpeq); + src.push(m as f32 * recpeq); + src.push(y as f32 * recpeq); + src.push(k as f32 * recpeq); + } + } + } + } + src +} + +pub(crate) fn create_lut4( + lut: &LutDataType, + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + if lut.num_input_channels != 4 { + return Err(CmsError::UnsupportedProfileConnection); + } + let lut_size: u32 = (4 * SAMPLES * SAMPLES * SAMPLES * SAMPLES) as u32; + + let src = create_lut4_norm_samples::(); + let mut dest = try_vec![0.; (lut_size as usize) / 4 * 3]; + + let lut_stage = stage_lut_4x3(lut, options, pcs)?; + lut_stage.transform(&src, &mut dest)?; + Ok(dest) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut_transforms.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut_transforms.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/lut_transforms.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/lut_transforms.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,802 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::lut3x3::{ + create_lut3x3, katana_input_stage_lut_3x3, katana_output_stage_lut_3x3, +}; +use crate::conversions::lut3x4::{create_lut3_samples_norm, create_lut3x4}; +use crate::conversions::lut4::{create_lut4, create_lut4_norm_samples, katana_input_stage_lut_4x3}; +use crate::conversions::mab::{prepare_mab_3x3, prepare_mba_3x3}; +use crate::conversions::transform_lut3_to_4::make_transform_3x4; +use crate::mlaf::mlaf; +use crate::{ + CmsError, ColorProfile, DataColorSpace, InPlaceStage, Layout, LutWarehouse, Matrix3f, + ProfileVersion, TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; + +pub(crate) struct MatrixStage { + pub(crate) matrices: Vec, +} + +impl InPlaceStage for MatrixStage { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + if !self.matrices.is_empty() { + let m = self.matrices[0]; + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + for m in self.matrices.iter().skip(1) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + Ok(()) + } +} + +pub(crate) const LUT_SAMPLING: u16 = 255; + +pub(crate) trait Lut3x3Factory { + fn make_transform_3x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction; +} + +pub(crate) trait Lut4x3Factory { + fn make_transform_4x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Sync + Send> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction; +} + +fn pcs_lab_v4_to_v2(profile: &ColorProfile, lut: &mut [f32]) { + if profile.pcs == DataColorSpace::Lab + && profile.version_internal < ProfileVersion::V4_0 + && lut.len() % 3 == 0 + { + assert_eq!( + lut.len() % 3, + 0, + "Lut {:?} is not a multiple of 3, this should not happen for lab", + lut.len() + ); + let v_mat = vec![Matrix3f { + v: [ + [65280.0 / 65535.0, 0f32, 0f32], + [0f32, 65280.0 / 65535.0, 0f32], + [0f32, 0f32, 65280.0 / 65535.0f32], + ], + }]; + let stage = MatrixStage { matrices: v_mat }; + stage.transform(lut).unwrap(); + } +} + +fn pcs_lab_v2_to_v4(profile: &ColorProfile, lut: &mut [f32]) { + if profile.pcs == DataColorSpace::Lab + && profile.version_internal < ProfileVersion::V4_0 + && lut.len() % 3 == 0 + { + assert_eq!( + lut.len() % 3, + 0, + "Lut {:?} is not a multiple of 3, this should not happen for lab", + lut.len() + ); + let v_mat = vec![Matrix3f { + v: [ + [65535.0 / 65280.0f32, 0f32, 0f32], + [0f32, 65535.0f32 / 65280.0f32, 0f32], + [0f32, 0f32, 65535.0f32 / 65280.0f32], + ], + }]; + let stage = MatrixStage { matrices: v_mat }; + stage.transform(lut).unwrap(); + } +} + +macro_rules! make_transform_3x3_fn { + ($method_name: ident, $exec_impl: ident) => { + fn $method_name< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + match src_layout { + Layout::Rgb => match dst_layout { + Layout::Rgb => $exec_impl::make_transform_3x3::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, color_space, is_linear), + Layout::Rgba => $exec_impl::make_transform_3x3::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, color_space, is_linear), + _ => unimplemented!(), + }, + Layout::Rgba => match dst_layout { + Layout::Rgb => $exec_impl::make_transform_3x3::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, color_space, is_linear), + Layout::Rgba => $exec_impl::make_transform_3x3::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, color_space, is_linear), + _ => unimplemented!(), + }, + _ => unimplemented!(), + } + } + }; +} + +macro_rules! make_transform_4x3_fn { + ($method_name: ident, $exec_name: ident) => { + fn $method_name< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + dst_layout: Layout, + lut: Vec, + options: TransformOptions, + data_color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + match dst_layout { + Layout::Rgb => $exec_name::make_transform_4x3::< + T, + { Layout::Rgb as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, data_color_space, is_linear), + Layout::Rgba => $exec_name::make_transform_4x3::< + T, + { Layout::Rgba as u8 }, + GRID_SIZE, + BIT_DEPTH, + >(lut, options, data_color_space, is_linear), + _ => unimplemented!(), + } + } + }; +} + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +use crate::conversions::neon::NeonLut3x3Factory; +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +make_transform_3x3_fn!(make_transformer_3x3, NeonLut3x3Factory); + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +use crate::conversions::transform_lut3_to_3::DefaultLut3x3Factory; +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +make_transform_3x3_fn!(make_transformer_3x3, DefaultLut3x3Factory); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +use crate::conversions::avx::AvxLut3x3Factory; +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +make_transform_3x3_fn!(make_transformer_3x3_avx_fma, AvxLut3x3Factory); + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +use crate::conversions::sse::SseLut3x3Factory; +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +make_transform_3x3_fn!(make_transformer_3x3_sse41, SseLut3x3Factory); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +use crate::conversions::avx::AvxLut4x3Factory; +use crate::conversions::interpolator::LutBarycentricReduction; +use crate::conversions::katana::{ + Katana, KatanaDefaultIntermediate, KatanaInitialStage, KatanaPostFinalizationStage, + KatanaStageLabToXyz, KatanaStageXyzToLab, katana_create_rgb_lin_lut, katana_pcs_lab_v2_to_v4, + katana_pcs_lab_v4_to_v2, katana_prepare_inverse_lut_rgb_xyz, multi_dimensional_3x3_to_device, + multi_dimensional_3x3_to_pcs, multi_dimensional_4x3_to_pcs, +}; +use crate::conversions::mab4x3::prepare_mab_4x3; +use crate::conversions::mba3x4::prepare_mba_3x4; +use crate::conversions::md_luts_factory::{do_any_to_any, prepare_alpha_finalizer}; +// use crate::conversions::bpc::compensate_bpc_in_lut; + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +make_transform_4x3_fn!(make_transformer_4x3_avx_fma, AvxLut4x3Factory); + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +use crate::conversions::sse::SseLut4x3Factory; +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +make_transform_4x3_fn!(make_transformer_4x3_sse41, SseLut4x3Factory); + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +use crate::conversions::transform_lut4_to_3::DefaultLut4x3Factory; + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +make_transform_4x3_fn!(make_transformer_4x3, DefaultLut4x3Factory); + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +use crate::conversions::neon::NeonLut4x3Factory; +use crate::conversions::prelude_lut_xyz_rgb::{create_rgb_lin_lut, prepare_inverse_lut_rgb_xyz}; +use crate::conversions::xyz_lab::{StageLabToXyz, StageXyzToLab}; +use crate::transform::PointeeSizeExpressible; +use crate::trc::GammaLutInterpolate; + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +make_transform_4x3_fn!(make_transformer_4x3, NeonLut4x3Factory); + +#[inline(never)] +#[cold] +pub(crate) fn make_lut_transform< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible + + GammaLutInterpolate, + const BIT_DEPTH: usize, + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, +>( + src_layout: Layout, + source: &ColorProfile, + dst_layout: Layout, + dest: &ColorProfile, + options: TransformOptions, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, +{ + if (source.color_space == DataColorSpace::Cmyk || source.color_space == DataColorSpace::Color4) + && (dest.color_space == DataColorSpace::Rgb || dest.color_space == DataColorSpace::Lab) + { + source.color_space.check_layout(src_layout)?; + dest.color_space.check_layout(dst_layout)?; + if source.pcs != DataColorSpace::Xyz && source.pcs != DataColorSpace::Lab { + return Err(CmsError::UnsupportedProfileConnection); + } + if dest.pcs != DataColorSpace::Lab && dest.pcs != DataColorSpace::Xyz { + return Err(CmsError::UnsupportedProfileConnection); + } + + const GRID_SIZE: usize = 17; + + let is_katana_required_for_source = source + .get_device_to_pcs(options.rendering_intent) + .ok_or(CmsError::UnsupportedLutRenderingIntent( + source.rendering_intent, + )) + .map(|x| x.is_katana_required())?; + + let is_katana_required_for_destination = + if dest.is_matrix_shaper() || dest.pcs == DataColorSpace::Xyz { + false + } else if dest.pcs == DataColorSpace::Lab { + dest.get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection) + .map(|x| x.is_katana_required())? + } else { + return Err(CmsError::UnsupportedProfileConnection); + }; + + if is_katana_required_for_source || is_katana_required_for_destination { + let initial_stage: Box + Send + Sync> = + match source.get_device_to_pcs(options.rendering_intent).ok_or( + CmsError::UnsupportedLutRenderingIntent(source.rendering_intent), + )? { + LutWarehouse::Lut(lut) => { + katana_input_stage_lut_4x3::(lut, options, source.pcs, BIT_DEPTH)? + } + LutWarehouse::Multidimensional(mab) => { + multi_dimensional_4x3_to_pcs::(mab, options, source.pcs, BIT_DEPTH)? + } + }; + + let mut stages = Vec::new(); + + stages.push(katana_pcs_lab_v2_to_v4(source)); + if source.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageLabToXyz::default())); + } + if dest.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageXyzToLab::default())); + } + stages.push(katana_pcs_lab_v4_to_v2(dest)); + + let final_stage = if dest.has_pcs_to_device_lut() { + let pcs_to_device = dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + match pcs_to_device { + LutWarehouse::Lut(lut) => { + katana_output_stage_lut_3x3::(lut, options, dest.pcs, BIT_DEPTH)? + } + LutWarehouse::Multidimensional(mab) => { + multi_dimensional_3x3_to_device::(mab, options, dest.pcs, BIT_DEPTH)? + } + } + } else if dest.is_matrix_shaper() { + let state = katana_prepare_inverse_lut_rgb_xyz::( + dest, dst_layout, options, + )?; + stages.extend(state.stages); + state.final_stage + } else { + return Err(CmsError::UnsupportedProfileConnection); + }; + + let mut post_finalization: Vec + Send + Sync>> = + Vec::new(); + if let Some(stage) = + prepare_alpha_finalizer::(src_layout, source, dst_layout, dest, BIT_DEPTH) + { + post_finalization.push(stage); + } + + return Ok(Box::new(Katana:: { + initial_stage, + final_stage, + stages, + post_finalization, + })); + } + + let mut lut = match source.get_device_to_pcs(options.rendering_intent).ok_or( + CmsError::UnsupportedLutRenderingIntent(source.rendering_intent), + )? { + LutWarehouse::Lut(lut) => create_lut4::(lut, options, source.pcs)?, + LutWarehouse::Multidimensional(m_curves) => { + let mut samples = create_lut4_norm_samples::(); + prepare_mab_4x3(m_curves, &mut samples, options, source.pcs)? + } + }; + + pcs_lab_v2_to_v4(source, &mut lut); + + if source.pcs == DataColorSpace::Lab { + let lab_to_xyz_stage = StageLabToXyz::default(); + lab_to_xyz_stage.transform(&mut lut)?; + } + + // if source.color_space == DataColorSpace::Cmyk + // && (options.rendering_intent == RenderingIntent::Perceptual + // || options.rendering_intent == RenderingIntent::RelativeColorimetric) + // && options.black_point_compensation + // { + // if let (Some(src_bp), Some(dst_bp)) = ( + // source.detect_black_point::(&lut), + // dest.detect_black_point::(&lut), + // ) { + // compensate_bpc_in_lut(&mut lut, src_bp, dst_bp); + // } + // } + + if dest.pcs == DataColorSpace::Lab { + let lab_to_xyz_stage = StageXyzToLab::default(); + lab_to_xyz_stage.transform(&mut lut)?; + } + + pcs_lab_v4_to_v2(dest, &mut lut); + + if dest.pcs == DataColorSpace::Xyz { + if dest.is_matrix_shaper() { + prepare_inverse_lut_rgb_xyz::(dest, &mut lut, options)?; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + } else if dest.pcs == DataColorSpace::Lab { + let pcs_to_device = dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + match pcs_to_device { + LutWarehouse::Lut(lut_data_type) => { + lut = create_lut3x3(lut_data_type, &lut, options, dest.pcs)? + } + LutWarehouse::Multidimensional(mab) => { + prepare_mba_3x3(mab, &mut lut, options, dest.pcs)? + } + } + } + + let is_dest_linear_profile = dest.color_space == DataColorSpace::Rgb + && dest.is_matrix_shaper() + && dest.is_linear_matrix_shaper(); + + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + if std::arch::is_x86_feature_detected!("avx2") && std::arch::is_x86_feature_detected!("fma") + { + return Ok(make_transformer_4x3_avx_fma::( + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )); + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + if std::arch::is_x86_feature_detected!("sse4.1") { + return Ok(make_transformer_4x3_sse41::( + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )); + } + + Ok(make_transformer_4x3::( + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )) + } else if (source.color_space == DataColorSpace::Rgb + || source.color_space == DataColorSpace::Lab) + && (dest.color_space == DataColorSpace::Cmyk || dest.color_space == DataColorSpace::Color4) + { + source.color_space.check_layout(src_layout)?; + dest.color_space.check_layout(dst_layout)?; + + if source.pcs != DataColorSpace::Xyz && source.pcs != DataColorSpace::Lab { + return Err(CmsError::UnsupportedProfileConnection); + } + + const GRID_SIZE: usize = 33; + + let mut lut: Vec; + + if source.has_device_to_pcs_lut() { + let device_to_pcs = source + .get_device_to_pcs(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + lut = create_lut3_samples_norm::(); + + match device_to_pcs { + LutWarehouse::Lut(lut_data_type) => { + lut = create_lut3x3(lut_data_type, &lut, options, source.pcs)?; + } + LutWarehouse::Multidimensional(mab) => { + prepare_mab_3x3(mab, &mut lut, options, source.pcs)? + } + } + } else if source.is_matrix_shaper() { + lut = create_rgb_lin_lut::(source, options)?; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + + pcs_lab_v2_to_v4(source, &mut lut); + + if source.pcs == DataColorSpace::Xyz && dest.pcs == DataColorSpace::Lab { + let xyz_to_lab = StageXyzToLab::default(); + xyz_to_lab.transform(&mut lut)?; + } else if source.pcs == DataColorSpace::Lab && dest.pcs == DataColorSpace::Xyz { + let lab_to_xyz_stage = StageLabToXyz::default(); + lab_to_xyz_stage.transform(&mut lut)?; + } + + pcs_lab_v4_to_v2(dest, &mut lut); + + let lut = match dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)? + { + LutWarehouse::Lut(lut_type) => create_lut3x4(lut_type, &lut, options, dest.pcs)?, + LutWarehouse::Multidimensional(m_curves) => { + prepare_mba_3x4(m_curves, &mut lut, options, dest.pcs)? + } + }; + + let is_dest_linear_profile = dest.color_space == DataColorSpace::Rgb + && dest.is_matrix_shaper() + && dest.is_linear_matrix_shaper(); + + Ok(make_transform_3x4::( + src_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )) + } else if (source.color_space.is_three_channels()) && (dest.color_space.is_three_channels()) { + source.color_space.check_layout(src_layout)?; + dest.color_space.check_layout(dst_layout)?; + + const GRID_SIZE: usize = 33; + + let is_katana_required_for_source = if source.is_matrix_shaper() { + false + } else { + source + .get_device_to_pcs(options.rendering_intent) + .ok_or(CmsError::UnsupportedLutRenderingIntent( + source.rendering_intent, + )) + .map(|x| x.is_katana_required())? + }; + + let is_katana_required_for_destination = + if source.is_matrix_shaper() || dest.pcs == DataColorSpace::Xyz { + false + } else if dest.pcs == DataColorSpace::Lab { + dest.get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection) + .map(|x| x.is_katana_required())? + } else { + return Err(CmsError::UnsupportedProfileConnection); + }; + + let mut stages: Vec> = Vec::new(); + + // Slow and accurate fallback if anything not acceptable is detected by curve analysis + if is_katana_required_for_source || is_katana_required_for_destination { + let source_stage: Box + Send + Sync> = + if source.is_matrix_shaper() { + let state = katana_create_rgb_lin_lut::( + src_layout, source, options, + )?; + stages.extend(state.stages); + state.initial_stage + } else { + match source.get_device_to_pcs(options.rendering_intent).ok_or( + CmsError::UnsupportedLutRenderingIntent(source.rendering_intent), + )? { + LutWarehouse::Lut(lut) => { + katana_input_stage_lut_3x3::(lut, options, source.pcs, BIT_DEPTH)? + } + LutWarehouse::Multidimensional(mab) => { + multi_dimensional_3x3_to_pcs::(mab, options, source.pcs, BIT_DEPTH)? + } + } + }; + + stages.push(katana_pcs_lab_v2_to_v4(source)); + if source.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageLabToXyz::default())); + } + if dest.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageXyzToLab::default())); + } + stages.push(katana_pcs_lab_v4_to_v2(dest)); + + let final_stage = if dest.has_pcs_to_device_lut() { + let pcs_to_device = dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + match pcs_to_device { + LutWarehouse::Lut(lut) => { + katana_output_stage_lut_3x3::(lut, options, dest.pcs, BIT_DEPTH)? + } + LutWarehouse::Multidimensional(mab) => { + multi_dimensional_3x3_to_device::(mab, options, dest.pcs, BIT_DEPTH)? + } + } + } else if dest.is_matrix_shaper() { + let state = katana_prepare_inverse_lut_rgb_xyz::( + dest, dst_layout, options, + )?; + stages.extend(state.stages); + state.final_stage + } else { + return Err(CmsError::UnsupportedProfileConnection); + }; + + let mut post_finalization: Vec + Send + Sync>> = + Vec::new(); + if let Some(stage) = + prepare_alpha_finalizer::(src_layout, source, dst_layout, dest, BIT_DEPTH) + { + post_finalization.push(stage); + } + + return Ok(Box::new(Katana:: { + initial_stage: source_stage, + final_stage, + stages, + post_finalization, + })); + } + + let mut lut: Vec; + + if source.has_device_to_pcs_lut() { + let device_to_pcs = source + .get_device_to_pcs(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + lut = create_lut3_samples_norm::(); + + match device_to_pcs { + LutWarehouse::Lut(lut_data_type) => { + lut = create_lut3x3(lut_data_type, &lut, options, source.pcs)?; + } + LutWarehouse::Multidimensional(mab) => { + prepare_mab_3x3(mab, &mut lut, options, source.pcs)? + } + } + } else if source.is_matrix_shaper() { + lut = create_rgb_lin_lut::(source, options)?; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + + pcs_lab_v2_to_v4(source, &mut lut); + + if source.pcs == DataColorSpace::Xyz && dest.pcs == DataColorSpace::Lab { + let xyz_to_lab = StageXyzToLab::default(); + xyz_to_lab.transform(&mut lut)?; + } else if source.pcs == DataColorSpace::Lab && dest.pcs == DataColorSpace::Xyz { + let lab_to_xyz_stage = StageLabToXyz::default(); + lab_to_xyz_stage.transform(&mut lut)?; + } + + pcs_lab_v4_to_v2(dest, &mut lut); + + if dest.has_pcs_to_device_lut() { + let pcs_to_device = dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + match pcs_to_device { + LutWarehouse::Lut(lut_data_type) => { + lut = create_lut3x3(lut_data_type, &lut, options, dest.pcs)?; + } + LutWarehouse::Multidimensional(mab) => { + prepare_mba_3x3(mab, &mut lut, options, dest.pcs)? + } + } + } else if dest.is_matrix_shaper() { + prepare_inverse_lut_rgb_xyz::(dest, &mut lut, options)?; + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + + let is_dest_linear_profile = dest.color_space == DataColorSpace::Rgb + && dest.is_matrix_shaper() + && dest.is_linear_matrix_shaper(); + + #[cfg(all(feature = "avx", target_arch = "x86_64"))] + if std::arch::is_x86_feature_detected!("avx2") && std::is_x86_feature_detected!("fma") { + return Ok(make_transformer_3x3_avx_fma::( + src_layout, + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )); + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + if std::arch::is_x86_feature_detected!("sse4.1") { + return Ok(make_transformer_3x3_sse41::( + src_layout, + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )); + } + + Ok(make_transformer_3x3::( + src_layout, + dst_layout, + lut, + options, + dest.color_space, + is_dest_linear_profile, + )) + } else { + do_any_to_any::( + src_layout, source, dst_layout, dest, options, + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mab.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mab.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,559 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::mlaf; +use crate::safe_math::SafeMul; +use crate::{ + CmsError, Cube, DataColorSpace, InPlaceStage, InterpolationMethod, LutMultidimensionalType, + MalformedSize, Matrix3d, Matrix3f, TransformOptions, Vector3d, Vector3f, +}; + +#[allow(unused)] +struct ACurves3<'a> { + curve0: Box<[f32; 65536]>, + curve1: Box<[f32; 65536]>, + curve2: Box<[f32; 65536]>, + clut: &'a [f32], + grid_size: [u8; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + depth: usize, +} + +#[allow(unused)] +struct ACurves3Optimized<'a> { + clut: &'a [f32], + grid_size: [u8; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +#[allow(unused)] +impl ACurves3<'_> { + fn transform_impl Vector3f>( + &self, + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let scale_value = (self.depth - 1) as f32; + + for dst in dst.chunks_exact_mut(3) { + let a0 = (dst[0] * scale_value).round().min(scale_value) as u16; + let a1 = (dst[1] * scale_value).round().min(scale_value) as u16; + let a2 = (dst[2] * scale_value).round().min(scale_value) as u16; + let b0 = self.curve0[a0 as usize]; + let b1 = self.curve1[a1 as usize]; + let b2 = self.curve2[a2 as usize]; + let interpolated = fetch(b0, b1, b2); + dst[0] = interpolated.v[0]; + dst[1] = interpolated.v[1]; + dst[2] = interpolated.v[2]; + } + Ok(()) + } +} + +#[allow(unused)] +impl ACurves3Optimized<'_> { + fn transform_impl Vector3f>( + &self, + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + for dst in dst.chunks_exact_mut(3) { + let a0 = dst[0]; + let a1 = dst[1]; + let a2 = dst[2]; + let interpolated = fetch(a0, a1, a2); + dst[0] = interpolated.v[0]; + dst[1] = interpolated.v[1]; + dst[2] = interpolated.v[2]; + } + Ok(()) + } +} + +impl InPlaceStage for ACurves3<'_> { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Cube::new_checked_cube(self.clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(dst, |x, y, z| lut.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(dst, |x, y, z| lut.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(dst, |x, y, z| lut.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + } + } + Ok(()) + } +} + +impl InPlaceStage for ACurves3Optimized<'_> { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Cube::new_checked_cube(self.clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab { + return self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(dst, |x, y, z| lut.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(dst, |x, y, z| lut.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(dst, |x, y, z| lut.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + } + } + Ok(()) + } +} + +#[allow(unused)] +struct ACurves3Inverse<'a> { + curve0: Box<[f32; 65536]>, + curve1: Box<[f32; 65536]>, + curve2: Box<[f32; 65536]>, + clut: &'a [f32], + grid_size: [u8; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + depth: usize, +} + +#[allow(unused)] +impl ACurves3Inverse<'_> { + fn transform_impl Vector3f>( + &self, + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let scale_value = (self.depth as u32 - 1u32) as f32; + + for dst in dst.chunks_exact_mut(3) { + let interpolated = fetch(dst[0], dst[1], dst[2]); + let a0 = (interpolated.v[0] * scale_value).round().min(scale_value) as u16; + let a1 = (interpolated.v[1] * scale_value).round().min(scale_value) as u16; + let a2 = (interpolated.v[2] * scale_value).round().min(scale_value) as u16; + let b0 = self.curve0[a0 as usize]; + let b1 = self.curve1[a1 as usize]; + let b2 = self.curve2[a2 as usize]; + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + } + Ok(()) + } +} + +impl InPlaceStage for ACurves3Inverse<'_> { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Cube::new_checked_cube(self.clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(dst, |x, y, z| lut.tetra_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(dst, |x, y, z| lut.pyramid_vec3(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(dst, |x, y, z| lut.prism_vec3(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(dst, |x, y, z| lut.trilinear_vec3(x, y, z))?; + } + } + Ok(()) + } +} + +pub(crate) struct MCurves3 { + pub(crate) curve0: Box<[f32; 65536]>, + pub(crate) curve1: Box<[f32; 65536]>, + pub(crate) curve2: Box<[f32; 65536]>, + pub(crate) matrix: Matrix3f, + pub(crate) bias: Vector3f, + pub(crate) inverse: bool, + pub(crate) depth: usize, +} + +impl MCurves3 { + fn execute_matrix_stage(&self, dst: &mut [f32]) { + let m = self.matrix; + let b = self.bias; + + if !m.test_equality(Matrix3f::IDENTITY) || !b.eq(&Vector3f::default()) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(mlaf(b.v[0], x, m.v[0][0]), y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(mlaf(b.v[1], x, m.v[1][0]), y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(mlaf(b.v[2], x, m.v[2][0]), y, m.v[2][1]), z, m.v[2][2]); + } + } + } +} + +impl InPlaceStage for MCurves3 { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + let scale_value = (self.depth - 1) as f32; + + if self.inverse { + self.execute_matrix_stage(dst); + } + + for dst in dst.chunks_exact_mut(3) { + let a0 = (dst[0] * scale_value).round().min(scale_value) as u16; + let a1 = (dst[1] * scale_value).round().min(scale_value) as u16; + let a2 = (dst[2] * scale_value).round().min(scale_value) as u16; + let b0 = self.curve0[a0 as usize]; + let b1 = self.curve1[a1 as usize]; + let b2 = self.curve2[a2 as usize]; + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + } + + if !self.inverse { + self.execute_matrix_stage(dst); + } + + Ok(()) + } +} + +pub(crate) struct BCurves3 { + pub(crate) curve0: Box<[f32; 65536]>, + pub(crate) curve1: Box<[f32; 65536]>, + pub(crate) curve2: Box<[f32; 65536]>, +} + +impl InPlaceStage for BCurves3 { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + let scale_value = (DEPTH - 1) as f32; + + for dst in dst.chunks_exact_mut(3) { + let a0 = (dst[0] * scale_value).round().min(scale_value) as u16; + let a1 = (dst[1] * scale_value).round().min(scale_value) as u16; + let a2 = (dst[2] * scale_value).round().min(scale_value) as u16; + let b0 = self.curve0[a0 as usize]; + let b1 = self.curve1[a1 as usize]; + let b2 = self.curve2[a2 as usize]; + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + } + + Ok(()) + } +} + +pub(crate) fn prepare_mab_3x3( + mab: &LutMultidimensionalType, + lut: &mut [f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result<(), CmsError> { + const LERP_DEPTH: usize = 65536; + const BP: usize = 13; + const DEPTH: usize = 8192; + + if mab.num_input_channels != 3 || mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + if mab.a_curves.len() == 3 && mab.clut.is_some() { + let clut = &mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + + let all_curves_linear = mab.a_curves.iter().all(|curve| curve.is_linear()); + let grid_size = [mab.grid_points[0], mab.grid_points[1], mab.grid_points[2]]; + + if all_curves_linear { + let l = ACurves3Optimized { + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + }; + l.transform(lut)?; + } else { + let curves: Result, _> = mab + .a_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let l = ACurves3 { + curve0, + curve1, + curve2, + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + depth: DEPTH, + }; + l.transform(lut)?; + } + } + + if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let curves: Result, _> = mab + .m_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let matrix = mab.matrix.to_f32(); + let bias: Vector3f = mab.bias.cast(); + let m_curves = MCurves3 { + curve0, + curve1, + curve2, + matrix, + bias, + inverse: false, + depth: DEPTH, + }; + m_curves.transform(lut)?; + } + } + + if mab.b_curves.len() == 3 { + const LERP_DEPTH: usize = 65536; + const BP: usize = 13; + const DEPTH: usize = 8192; + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear { + let curves: Result, _> = mab + .b_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + + let b_curves = BCurves3:: { + curve0, + curve1, + curve2, + }; + b_curves.transform(lut)?; + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + Ok(()) +} + +pub(crate) fn prepare_mba_3x3( + mab: &LutMultidimensionalType, + lut: &mut [f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result<(), CmsError> { + if mab.num_input_channels != 3 || mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + const LERP_DEPTH: usize = 65536; + const BP: usize = 13; + const DEPTH: usize = 8192; + + if mab.b_curves.len() == 3 { + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear { + let curves: Result, _> = mab + .b_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let b_curves = BCurves3:: { + curve0, + curve1, + curve2, + }; + b_curves.transform(lut)?; + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let curves: Result, _> = mab + .m_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + + let matrix = mab.matrix.to_f32(); + let bias: Vector3f = mab.bias.cast(); + let m_curves = MCurves3 { + curve0, + curve1, + curve2, + matrix, + bias, + inverse: true, + depth: DEPTH, + }; + m_curves.transform(lut)?; + } + } + + if mab.a_curves.len() == 3 && mab.clut.is_some() { + let clut = &mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedCurveLutTable(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + + let all_curves_linear = mab.a_curves.iter().all(|curve| curve.is_linear()); + let grid_size = [mab.grid_points[0], mab.grid_points[1], mab.grid_points[2]]; + + if all_curves_linear { + let l = ACurves3Optimized { + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + }; + l.transform(lut)?; + } else { + let curves: Result, _> = mab + .a_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let l = ACurves3Inverse { + curve0, + curve1, + curve2, + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + depth: DEPTH, + }; + l.transform(lut)?; + } + } + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mab4x3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab4x3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mab4x3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mab4x3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,307 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::mab::{BCurves3, MCurves3}; +use crate::err::try_vec; +use crate::safe_math::SafeMul; +use crate::{ + CmsError, DataColorSpace, Hypercube, InPlaceStage, InterpolationMethod, + LutMultidimensionalType, MalformedSize, Matrix3d, Stage, TransformOptions, Vector3d, Vector3f, +}; + +#[allow(dead_code)] +struct ACurves4x3<'a> { + curve0: Box<[f32; 65536]>, + curve1: Box<[f32; 65536]>, + curve2: Box<[f32; 65536]>, + curve3: Box<[f32; 65536]>, + clut: &'a [f32], + grid_size: [u8; 4], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + depth: usize, +} + +#[allow(dead_code)] +struct ACurves4x3Optimized<'a> { + clut: &'a [f32], + grid_size: [u8; 4], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +#[allow(dead_code)] +impl ACurves4x3<'_> { + fn transform_impl Vector3f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let scale_value = (self.depth - 1) as f32; + + assert_eq!(src.len() / 4, dst.len() / 3); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(3)) { + let a0 = (src[0] * scale_value).round().min(scale_value) as u16; + let a1 = (src[1] * scale_value).round().min(scale_value) as u16; + let a2 = (src[2] * scale_value).round().min(scale_value) as u16; + let a3 = (src[3] * scale_value).round().min(scale_value) as u16; + let c = self.curve0[a0 as usize]; + let m = self.curve1[a1 as usize]; + let y = self.curve2[a2 as usize]; + let k = self.curve3[a3 as usize]; + + let r = fetch(c, m, y, k); + dst[0] = r.v[0]; + dst[1] = r.v[1]; + dst[2] = r.v[2]; + } + Ok(()) + } +} + +#[allow(dead_code)] +impl ACurves4x3Optimized<'_> { + fn transform_impl Vector3f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + assert_eq!(src.len() / 4, dst.len() / 3); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(3)) { + let c = src[0]; + let m = src[1]; + let y = src[2]; + let k = src[3]; + + let r = fetch(c, m, y, k); + dst[0] = r.v[0]; + dst[1] = r.v[1]; + dst[2] = r.v[2]; + } + Ok(()) + } +} + +impl Stage for ACurves4x3<'_> { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Hypercube::new_checked_hypercube(self.clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z, w| lut.quadlinear_vec3(x, y, z, w)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z, w| lut.tetra_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z, w| lut.pyramid_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z, w| lut.prism_vec3(x, y, z, w))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z, w| lut.quadlinear_vec3(x, y, z, w))?; + } + } + Ok(()) + } +} + +impl Stage for ACurves4x3Optimized<'_> { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Hypercube::new_checked_hypercube(self.clut, self.grid_size, 3)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z, w| lut.quadlinear_vec3(x, y, z, w)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z, w| lut.tetra_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z, w| lut.pyramid_vec3(x, y, z, w))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z, w| lut.prism_vec3(x, y, z, w))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z, w| lut.quadlinear_vec3(x, y, z, w))?; + } + } + Ok(()) + } +} + +pub(crate) fn prepare_mab_4x3( + mab: &LutMultidimensionalType, + lut: &mut [f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + const LERP_DEPTH: usize = 65536; + const BP: usize = 13; + const DEPTH: usize = 8192; + if mab.num_input_channels != 4 || mab.num_output_channels != 3 { + return Err(CmsError::UnsupportedProfileConnection); + } + let mut new_lut = try_vec![0f32; (lut.len() / 4) * 3]; + if mab.a_curves.len() == 4 && mab.clut.is_some() { + let clut = &mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.grid_points[3] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + + let all_curves_linear = mab.a_curves.iter().all(|curve| curve.is_linear()); + let grid_size = [ + mab.grid_points[0], + mab.grid_points[1], + mab.grid_points[2], + mab.grid_points[3], + ]; + + if all_curves_linear { + let l = ACurves4x3Optimized { + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + }; + l.transform(lut, &mut new_lut)?; + } else { + let curves: Result, _> = mab + .a_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2, curve3] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let l = ACurves4x3 { + curve0, + curve1, + curve2, + curve3, + clut, + grid_size, + interpolation_method: options.interpolation_method, + pcs, + depth: DEPTH, + }; + l.transform(lut, &mut new_lut)?; + } + } else { + // Not supported + return Err(CmsError::UnsupportedProfileConnection); + } + + if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let curves: Result, _> = mab + .m_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + + let matrix = mab.matrix.to_f32(); + let bias: Vector3f = mab.bias.cast(); + let m_curves = MCurves3 { + curve0, + curve1, + curve2, + matrix, + bias, + inverse: false, + depth: DEPTH, + }; + m_curves.transform(&mut new_lut)?; + } + } + + if mab.b_curves.len() == 3 { + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear { + let curves: Result, _> = mab + .b_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let b_curves = BCurves3:: { + curve0, + curve1, + curve2, + }; + b_curves.transform(&mut new_lut)?; + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + Ok(new_lut) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mba3x4.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mba3x4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mba3x4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mba3x4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,302 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::mab::{BCurves3, MCurves3}; +use crate::err::try_vec; +use crate::safe_math::SafeMul; +use crate::{ + CmsError, Cube, DataColorSpace, InPlaceStage, InterpolationMethod, LutMultidimensionalType, + MalformedSize, Matrix3d, Stage, TransformOptions, Vector3d, Vector4f, +}; + +struct ACurves3x4Inverse<'a> { + curve0: Box<[f32; 65536]>, + curve1: Box<[f32; 65536]>, + curve2: Box<[f32; 65536]>, + curve3: Box<[f32; 65536]>, + clut: &'a [f32], + grid_size: [u8; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, + depth: usize, +} + +struct ACurves3x4InverseOptimized<'a> { + clut: &'a [f32], + grid_size: [u8; 3], + interpolation_method: InterpolationMethod, + pcs: DataColorSpace, +} + +impl ACurves3x4Inverse<'_> { + fn transform_impl Vector4f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + let scale_value = (self.depth as u32 - 1u32) as f32; + + assert_eq!(src.len() / 3, dst.len() / 4); + + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(4)) { + let interpolated = fetch(src[0], src[1], src[2]); + let a0 = (interpolated.v[0] * scale_value).round().min(scale_value) as u16; + let a1 = (interpolated.v[1] * scale_value).round().min(scale_value) as u16; + let a2 = (interpolated.v[2] * scale_value).round().min(scale_value) as u16; + let a3 = (interpolated.v[3] * scale_value).round().min(scale_value) as u16; + let b0 = self.curve0[a0 as usize]; + let b1 = self.curve1[a1 as usize]; + let b2 = self.curve2[a2 as usize]; + let b3 = self.curve3[a3 as usize]; + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + dst[3] = b3; + } + Ok(()) + } +} + +impl ACurves3x4InverseOptimized<'_> { + fn transform_impl Vector4f>( + &self, + src: &[f32], + dst: &mut [f32], + fetch: Fetch, + ) -> Result<(), CmsError> { + assert_eq!(src.len() / 3, dst.len() / 4); + + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(4)) { + let interpolated = fetch(src[0], src[1], src[2]); + let b0 = interpolated.v[0]; + let b1 = interpolated.v[1]; + let b2 = interpolated.v[2]; + let b3 = interpolated.v[3]; + dst[0] = b0; + dst[1] = b1; + dst[2] = b2; + dst[3] = b3; + } + Ok(()) + } +} + +impl Stage for ACurves3x4Inverse<'_> { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Cube::new_checked_cube(self.clut, self.grid_size, 4)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z| lut.trilinear_vec4(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z| lut.tetra_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z| lut.pyramid_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z| lut.prism_vec4(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z| lut.trilinear_vec4(x, y, z))?; + } + } + Ok(()) + } +} + +impl Stage for ACurves3x4InverseOptimized<'_> { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError> { + let lut = Cube::new_checked_cube(self.clut, self.grid_size, 4)?; + + // If PCS is LAB then linear interpolation should be used + if self.pcs == DataColorSpace::Lab || self.pcs == DataColorSpace::Xyz { + return self.transform_impl(src, dst, |x, y, z| lut.trilinear_vec4(x, y, z)); + } + + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_impl(src, dst, |x, y, z| lut.tetra_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_impl(src, dst, |x, y, z| lut.pyramid_vec4(x, y, z))?; + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_impl(src, dst, |x, y, z| lut.prism_vec4(x, y, z))?; + } + InterpolationMethod::Linear => { + self.transform_impl(src, dst, |x, y, z| lut.trilinear_vec4(x, y, z))?; + } + } + Ok(()) + } +} + +pub(crate) fn prepare_mba_3x4( + mab: &LutMultidimensionalType, + lut: &mut [f32], + options: TransformOptions, + pcs: DataColorSpace, +) -> Result, CmsError> { + if mab.num_input_channels != 3 || mab.num_output_channels != 4 { + return Err(CmsError::UnsupportedProfileConnection); + } + + const LERP_DEPTH: usize = 65536; + const BP: usize = 13; + const DEPTH: usize = 8192; + + if mab.b_curves.len() == 3 { + let all_curves_linear = mab.b_curves.iter().all(|curve| curve.is_linear()); + + if !all_curves_linear { + let curves: Result, _> = mab + .b_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + let b_curves = BCurves3:: { + curve0, + curve1, + curve2, + }; + b_curves.transform(lut)?; + } + } else { + return Err(CmsError::InvalidAtoBLut); + } + + if mab.m_curves.len() == 3 { + let all_curves_linear = mab.m_curves.iter().all(|curve| curve.is_linear()); + if !all_curves_linear + || !mab.matrix.test_equality(Matrix3d::IDENTITY) + || mab.bias.ne(&Vector3d::default()) + { + let curves: Result, _> = mab + .m_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + + let matrix = mab.matrix.to_f32(); + let bias = mab.bias.cast(); + let m_curves = MCurves3 { + curve0, + curve1, + curve2, + matrix, + bias, + inverse: true, + depth: DEPTH, + }; + m_curves.transform(lut)?; + } + } + + let mut new_lut = try_vec![0f32; (lut.len() / 3) * 4]; + + if mab.a_curves.len() == 4 && mab.clut.is_some() { + let clut = &mab.clut.as_ref().map(|x| x.to_clut_f32()).unwrap(); + + let lut_grid = (mab.grid_points[0] as usize) + .safe_mul(mab.grid_points[1] as usize)? + .safe_mul(mab.grid_points[2] as usize)? + .safe_mul(mab.num_output_channels as usize)?; + if clut.len() != lut_grid { + return Err(CmsError::MalformedClut(MalformedSize { + size: clut.len(), + expected: lut_grid, + })); + } + + let grid_size = [mab.grid_points[0], mab.grid_points[1], mab.grid_points[2]]; + + let all_curves_linear = mab.a_curves.iter().all(|curve| curve.is_linear()); + + if all_curves_linear { + let a_curves = ACurves3x4InverseOptimized { + clut, + grid_size: [mab.grid_points[0], mab.grid_points[1], mab.grid_points[2]], + interpolation_method: options.interpolation_method, + pcs, + }; + a_curves.transform(lut, &mut new_lut)?; + } else { + let curves: Result, _> = mab + .a_curves + .iter() + .map(|c| { + c.build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve) + }) + .collect(); + + let [curve0, curve1, curve2, curve3] = + curves?.try_into().map_err(|_| CmsError::InvalidTrcCurve)?; + + let a_curves = ACurves3x4Inverse { + curve0, + curve1, + curve2, + curve3, + clut, + grid_size, + interpolation_method: options.interpolation_method, + depth: DEPTH, + pcs, + }; + a_curves.transform(lut, &mut new_lut)?; + } + } else { + return Err(CmsError::UnsupportedProfileConnection); + } + + Ok(new_lut) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/md_lut.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_lut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/md_lut.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_lut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,728 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use crate::mlaf::{mlaf, neg_mlaf}; +use crate::nd_array::{ArrayFetch, lerp}; +use crate::{Vector3f, Vector3i}; +use num_traits::MulAdd; +use std::array::from_fn; +use std::marker::PhantomData; +use std::ops::{Add, Mul, Neg, Sub}; + +pub(crate) struct MultidimensionalLut { + pub(crate) grid_strides: [u32; 16], + pub(crate) grid_filling_size: [u32; 16], + pub(crate) grid_scale: [f32; 16], + pub(crate) output_inks: usize, +} + +struct FastCube> { + fetch: F, + _phantom: PhantomData, +} + +struct ArrayFetchVectorN<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, + z_stride: u32, + output_inks: usize, +} + +#[repr(transparent)] +#[derive(Copy, Clone, Debug)] +pub(crate) struct NVector { + pub(crate) v: [T; N], +} + +impl NVector { + pub(crate) fn from_slice(v: &[T; N]) -> Self { + Self { v: *v } + } +} + +impl From for NVector { + #[inline] + fn from(value: T) -> Self { + Self { v: [value; N] } + } +} + +impl + Mul + MulAdd, const N: usize> + FusedMultiplyAdd> for NVector +{ + #[inline] + fn mla(&self, b: NVector, c: NVector) -> NVector { + Self { + v: from_fn(|i| mlaf(self.v[i], b.v[i], c.v[i])), + } + } +} + +impl< + T: Copy + Add + Mul + MulAdd + Neg, + const N: usize, +> FusedMultiplyNegAdd> for NVector +{ + #[inline] + fn neg_mla(&self, b: NVector, c: NVector) -> NVector { + Self { + v: from_fn(|i| neg_mlaf(self.v[i], b.v[i], c.v[i])), + } + } +} + +impl + Default + Copy, const N: usize> Sub> for NVector { + type Output = Self; + + #[inline] + fn sub(self, rhs: NVector) -> Self::Output { + Self { + v: from_fn(|i| self.v[i] - rhs.v[i]), + } + } +} + +impl + Default + Copy, const N: usize> Add> for NVector { + type Output = Self; + + #[inline] + fn add(self, rhs: NVector) -> Self::Output { + Self { + v: from_fn(|i| self.v[i] + rhs.v[i]), + } + } +} + +impl + Default + Copy, const N: usize> Mul> for NVector { + type Output = Self; + + #[inline] + fn mul(self, rhs: NVector) -> Self::Output { + Self { + v: from_fn(|i| self.v[i] * rhs.v[i]), + } + } +} + +impl ArrayFetch> for ArrayFetchVectorN<'_> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> NVector { + let start = (x as u32 * self.x_stride + y as u32 * self.y_stride + z as u32 * self.z_stride) + as usize + * self.output_inks; + let k = &self.array[start..start + N]; + NVector::::from_slice(k.try_into().unwrap()) + } +} + +impl> FastCube +where + T: Copy + + From + + Sub + + Mul + + Add + + FusedMultiplyNegAdd + + FusedMultiplyAdd, +{ + #[inline(never)] + fn tetra(&self, src: Vector3i, src_next: Vector3i, w: Vector3f) -> T { + let x = src.v[0]; + let y = src.v[1]; + let z = src.v[2]; + + let x_n = src_next.v[0]; + let y_n = src_next.v[1]; + let z_n = src_next.v[2]; + + let rx = w.v[0]; + let ry = w.v[1]; + let rz = w.v[2]; + + let c0 = self.fetch.fetch(x, y, z); + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = self.fetch.fetch(x_n, y, z) - c0; + c2 = self.fetch.fetch(x_n, y_n, z) - self.fetch.fetch(x_n, y, z); + c3 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = self.fetch.fetch(x_n, y, z) - c0; + c2 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x_n, y, z_n); + c3 = self.fetch.fetch(x_n, y, z_n) - self.fetch.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = self.fetch.fetch(x_n, y, z_n) - self.fetch.fetch(x, y, z_n); + c2 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x_n, y, z_n); + c3 = self.fetch.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = self.fetch.fetch(x_n, y_n, z) - self.fetch.fetch(x, y_n, z); + c2 = self.fetch.fetch(x, y_n, z) - c0; + c3 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x, y_n, z_n); + c2 = self.fetch.fetch(x, y_n, z) - c0; + c3 = self.fetch.fetch(x, y_n, z_n) - self.fetch.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = self.fetch.fetch(x_n, y_n, z_n) - self.fetch.fetch(x, y_n, z_n); + c2 = self.fetch.fetch(x, y_n, z_n) - self.fetch.fetch(x, y, z_n); + c3 = self.fetch.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, T::from(rx)); + let s1 = s0.mla(c2, T::from(ry)); + s1.mla(c3, T::from(rz)) + } +} + +impl MultidimensionalLut { + pub(crate) fn new(grid_size: [u8; 16], input_inks: usize, output_inks: usize) -> Self { + assert!(input_inks <= 16); + let mut grid_strides = [1u32; 16]; + let mut grid_filling_size = [1u32; 16]; + + for (ink, dst_stride) in grid_strides.iter_mut().take(input_inks - 1).enumerate() { + let mut stride = 1u32; + let how_many = input_inks.saturating_sub(ink).saturating_sub(1); + for &grid_stride in grid_size.iter().take(how_many) { + stride *= grid_stride as u32; + } + *dst_stride = stride; + } + + for (ink, dst_stride) in grid_filling_size.iter_mut().take(input_inks).enumerate() { + let mut stride = output_inks as u32; + let how_many = input_inks.saturating_sub(ink).saturating_sub(1); + for &grid_stride in grid_size.iter().take(how_many) { + stride *= grid_stride as u32; + } + *dst_stride = stride; + } + + let mut grid_strides_f = [0f32; 16]; + + for (dst, src) in grid_strides_f + .iter_mut() + .zip(grid_size.iter()) + .take(input_inks) + { + *dst = (*src - 1) as f32; + } + + Self { + grid_strides, + grid_scale: grid_strides_f, + grid_filling_size, + output_inks, + } + } +} + +pub(crate) fn linear_4i_vec3f_direct( + lut: &MultidimensionalLut, + arr: &[f32], + lx: f32, + ly: f32, + lz: f32, + lw: f32, +) -> NVector { + let lin_x = lx.max(0.0).min(1.0); + let lin_y = ly.max(0.0).min(1.0); + let lin_z = lz.max(0.0).min(1.0); + let lin_w = lw.max(0.0).min(1.0); + + let scale_x = lut.grid_scale[0]; + let scale_y = lut.grid_scale[1]; + let scale_z = lut.grid_scale[2]; + let scale_w = lut.grid_scale[3]; + + let lx = lin_x * scale_x; + let ly = lin_y * scale_y; + let lz = lin_z * scale_z; + let lw = lin_w * scale_w; + + let x = lx.floor() as i32; + let y = ly.floor() as i32; + let z = lz.floor() as i32; + let w = lw.floor() as i32; + + let src_x = Vector3i { v: [x, y, z] }; + + let x_n = lx.ceil() as i32; + let y_n = ly.ceil() as i32; + let z_n = lz.ceil() as i32; + let w_n = lw.ceil() as i32; + + let src_next = Vector3i { v: [x_n, y_n, z_n] }; + + let x_w = lx - x as f32; + let y_w = ly - y as f32; + let z_w = lz - z as f32; + let w_w = lw - w as f32; + + let weights = Vector3f { v: [x_w, y_w, z_w] }; + + let cube0 = &arr[(w as usize * lut.grid_filling_size[3] as usize)..]; + let cube1 = &arr[(w_n as usize * lut.grid_filling_size[3] as usize)..]; + + let fast_cube0 = FastCube { + fetch: ArrayFetchVectorN { + array: cube0, + x_stride: lut.grid_strides[0], + y_stride: lut.grid_strides[1], + z_stride: lut.grid_strides[2], + output_inks: lut.output_inks, + }, + _phantom: PhantomData, + }; + let fast_cube1 = FastCube { + fetch: ArrayFetchVectorN { + array: cube1, + x_stride: lut.grid_strides[0], + y_stride: lut.grid_strides[1], + z_stride: lut.grid_strides[2], + output_inks: lut.output_inks, + }, + _phantom: PhantomData, + }; + let w0 = fast_cube0.tetra(src_x, src_next, weights); + let w1 = fast_cube1.tetra(src_x, src_next, weights); + lerp(w0, w1, NVector::::from(w_w)) +} + +pub(crate) fn linear_3i_vec3f_direct( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + linear_3i_vec3f(lut, arr, inputs[0], inputs[1], inputs[2]) +} + +fn linear_3i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + x: f32, + y: f32, + z: f32, +) -> NVector { + let lin_x = x.max(0.0).min(1.0); + let lin_y = y.max(0.0).min(1.0); + let lin_z = z.max(0.0).min(1.0); + + let scale_x = lut.grid_scale[0]; + let scale_y = lut.grid_scale[1]; + let scale_z = lut.grid_scale[2]; + + let lx = lin_x * scale_x; + let ly = lin_y * scale_y; + let lz = lin_z * scale_z; + + let x = lx.floor() as i32; + let y = ly.floor() as i32; + let z = lz.floor() as i32; + + let src_x = Vector3i { v: [x, y, z] }; + + let x_n = lx.ceil() as i32; + let y_n = ly.ceil() as i32; + let z_n = lz.ceil() as i32; + + let src_next = Vector3i { v: [x_n, y_n, z_n] }; + + let x_w = lx - x as f32; + let y_w = ly - y as f32; + let z_w = lz - z as f32; + + let weights = Vector3f { v: [x_w, y_w, z_w] }; + + let fast_cube = FastCube { + fetch: ArrayFetchVectorN { + array: arr, + x_stride: lut.grid_strides[0], + y_stride: lut.grid_strides[1], + z_stride: lut.grid_strides[2], + output_inks: lut.output_inks, + }, + _phantom: PhantomData, + }; + + fast_cube.tetra(src_x, src_next, weights) +} + +pub(crate) fn linear_1i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let lin_x = inputs[0].max(0.0).min(1.0); + + let scale_x = lut.grid_scale[0]; + + let lx = lin_x * scale_x; + + let x = lx.floor() as i32; + + let x_n = lx.ceil() as i32; + + let x_w = lx - x as f32; + + let x_stride = lut.grid_strides[0]; + + let offset = |xi: i32| -> usize { (xi as u32 * x_stride) as usize * lut.output_inks }; + + // Sample 2 corners + let a = NVector::::from_slice(&arr[offset(x)..][..N].try_into().unwrap()); + let b = NVector::::from_slice(&arr[offset(x_n)..][..N].try_into().unwrap()); + + a * NVector::::from(1.0 - x_w) + b * NVector::::from(x_w) +} + +pub(crate) fn linear_2i_vec3f_direct( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + linear_2i_vec3f(lut, arr, inputs[0], inputs[1]) +} + +fn linear_2i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + x: f32, + y: f32, +) -> NVector { + let lin_x = x.max(0.0).min(1.0); + let lin_y = y.max(0.0).min(1.0); + + let scale_x = lut.grid_scale[0]; + let scale_y = lut.grid_scale[1]; + + let lx = lin_x * scale_x; + let ly = lin_y * scale_y; + + let x = lx.floor() as i32; + let y = ly.floor() as i32; + + let x_n = lx.ceil() as i32; + let y_n = ly.ceil() as i32; + + let x_w = lx - x as f32; + let y_w = ly - y as f32; + + let x_stride = lut.grid_strides[0]; + let y_stride = lut.grid_strides[1]; + + let offset = |xi: i32, yi: i32| -> usize { + (xi as u32 * x_stride + yi as u32 * y_stride) as usize * lut.output_inks + }; + + // Sample 4 corners + let a = NVector::::from_slice(&arr[offset(x, y)..][..N].try_into().unwrap()); + let b = NVector::::from_slice(&arr[offset(x_n, y)..][..N].try_into().unwrap()); + let c = NVector::::from_slice(&arr[offset(x, y_n)..][..N].try_into().unwrap()); + let d = NVector::::from_slice(&arr[offset(x_n, y_n)..][..N].try_into().unwrap()); + + let ab = a * NVector::::from(1.0 - x_w) + b * NVector::::from(x_w); + let cd = c * NVector::::from(1.0 - x_w) + d * NVector::::from(x_w); + + ab * NVector::::from(1.0 - y_w) + cd * NVector::::from(y_w) +} + +pub(crate) fn linear_4i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + linear_4i_vec3f_direct(lut, arr, inputs[0], inputs[1], inputs[2], inputs[3]) +} + +type FHandle = fn(&MultidimensionalLut, &[f32], &[f32]) -> NVector; + +#[inline(never)] +pub(crate) fn linear_n_i_vec3f< + const N: usize, + const I: usize, + Handle: Fn(&MultidimensionalLut, &[f32], &[f32]) -> NVector, +>( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], + handle: Handle, +) -> NVector { + let lin_w = inputs[I]; + + let w_c = lin_w.max(0.).min(1.); + let scale_p = lut.grid_scale[I]; + let wf = w_c * scale_p; + let w0 = wf.min(scale_p) as usize; + let w1 = (wf + 1.).min(scale_p) as usize; + let w = wf - w0 as f32; + + let cube0 = &arr[(w0 * lut.grid_filling_size[I] as usize)..]; + let cube1 = &arr[(w1 * lut.grid_filling_size[I] as usize)..]; + + let inputs_sliced = &inputs[0..I]; + let w0 = handle(lut, cube0, inputs_sliced); + let w1 = handle(lut, cube1, inputs_sliced); + lerp(w0, w1, NVector::::from(w)) +} + +#[inline(never)] +pub(crate) fn linear_5i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let lin_w = inputs[4]; + + let w_c = lin_w.max(0.).min(1.); + let scale_p = lut.grid_scale[4]; + let wf = w_c * scale_p; + let w0 = wf.min(scale_p) as usize; + let w1 = (wf + 1.).min(scale_p) as usize; + let w = wf - w0 as f32; + + let cube0 = &arr[(w0 * lut.grid_filling_size[4] as usize)..]; + let cube1 = &arr[(w1 * lut.grid_filling_size[4] as usize)..]; + + let w0 = linear_4i_vec3f_direct(lut, cube0, inputs[0], inputs[1], inputs[2], inputs[3]); + let w1 = linear_4i_vec3f_direct(lut, cube1, inputs[0], inputs[1], inputs[2], inputs[3]); + lerp(w0, w1, NVector::::from(w)) +} + +#[inline(never)] +pub(crate) fn linear_6i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_5i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_7i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_6i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_8i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_7i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_9i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_8i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_10i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_9i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_11i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_10i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_12i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_11i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_13i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_12i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_14i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_13i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn linear_15i_vec3f( + lut: &MultidimensionalLut, + arr: &[f32], + inputs: &[f32], +) -> NVector { + let f = linear_14i_vec3f::; + linear_n_i_vec3f::>(lut, arr, inputs, f) +} + +#[inline(never)] +pub(crate) fn tetra_3i_to_any_vec( + lut: &MultidimensionalLut, + arr: &[f32], + x: f32, + y: f32, + z: f32, + dst: &mut [f32], + inks: usize, +) { + match inks { + 1 => { + let vec3 = linear_3i_vec3f::<1>(lut, arr, x, y, z); + dst[0] = vec3.v[0]; + } + 2 => { + let vec3 = linear_3i_vec3f::<2>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 3 => { + let vec3 = linear_3i_vec3f::<3>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 4 => { + let vec3 = linear_3i_vec3f::<4>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 5 => { + let vec3 = linear_3i_vec3f::<5>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 6 => { + let vec3 = linear_3i_vec3f::<6>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 7 => { + let vec3 = linear_3i_vec3f::<7>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 8 => { + let vec3 = linear_3i_vec3f::<8>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 9 => { + let vec3 = linear_3i_vec3f::<9>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 10 => { + let vec3 = linear_3i_vec3f::<10>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 11 => { + let vec3 = linear_3i_vec3f::<11>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 12 => { + let vec3 = linear_3i_vec3f::<12>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 13 => { + let vec3 = linear_3i_vec3f::<13>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 14 => { + let vec3 = linear_3i_vec3f::<14>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + 15 => { + let vec3 = linear_3i_vec3f::<15>(lut, arr, x, y, z); + for (dst, src) in dst.iter_mut().zip(vec3.v.iter()) { + *dst = *src; + } + } + _ => unreachable!(), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/md_luts_factory.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_luts_factory.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/md_luts_factory.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/md_luts_factory.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,188 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::katana::{ + CopyAlphaStage, InjectAlphaStage, Katana, KatanaInitialStage, KatanaIntermediateStage, + KatanaPostFinalizationStage, KatanaStageLabToXyz, KatanaStageXyzToLab, + katana_create_rgb_lin_lut, katana_input_make_lut_nx3, katana_multi_dimensional_3xn_to_device, + katana_multi_dimensional_nx3_to_pcs, katana_output_make_lut_3xn, katana_pcs_lab_v2_to_v4, + katana_pcs_lab_v4_to_v2, katana_prepare_inverse_lut_rgb_xyz, +}; +use crate::{ + CmsError, ColorProfile, DataColorSpace, GammaLutInterpolate, Layout, LutWarehouse, + PointeeSizeExpressible, TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; + +pub(crate) fn do_any_to_any< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible + + GammaLutInterpolate, + const BIT_DEPTH: usize, + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, +>( + src_layout: Layout, + source: &ColorProfile, + dst_layout: Layout, + dest: &ColorProfile, + options: TransformOptions, +) -> Result + Send + Sync>, CmsError> +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, +{ + let mut stages: Vec + Send + Sync>> = Vec::new(); + + let initial_stage: Box + Send + Sync> = match source + .is_matrix_shaper() + { + true => { + let state = + katana_create_rgb_lin_lut::(src_layout, source, options)?; + stages.extend(state.stages); + state.initial_stage + } + false => match source.get_device_to_pcs(options.rendering_intent).ok_or( + CmsError::UnsupportedLutRenderingIntent(source.rendering_intent), + )? { + LutWarehouse::Lut(lut) => katana_input_make_lut_nx3::( + src_layout, + src_layout.channels(), + lut, + options, + source.pcs, + BIT_DEPTH, + )?, + LutWarehouse::Multidimensional(mab) => katana_multi_dimensional_nx3_to_pcs::( + src_layout, mab, options, source.pcs, BIT_DEPTH, + )?, + }, + }; + + stages.push(katana_pcs_lab_v2_to_v4(source)); + if source.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageLabToXyz::default())); + } + if dest.pcs == DataColorSpace::Lab { + stages.push(Box::new(KatanaStageXyzToLab::default())); + } + stages.push(katana_pcs_lab_v4_to_v2(dest)); + + let final_stage = if dest.has_pcs_to_device_lut() { + let pcs_to_device = dest + .get_pcs_to_device(options.rendering_intent) + .ok_or(CmsError::UnsupportedProfileConnection)?; + match pcs_to_device { + LutWarehouse::Lut(lut) => katana_output_make_lut_3xn::( + dst_layout, + lut, + options, + dest.color_space, + BIT_DEPTH, + )?, + LutWarehouse::Multidimensional(mab) => katana_multi_dimensional_3xn_to_device::( + dst_layout, mab, options, dest.pcs, BIT_DEPTH, + )?, + } + } else if dest.is_matrix_shaper() { + let state = katana_prepare_inverse_lut_rgb_xyz::( + dest, dst_layout, options, + )?; + stages.extend(state.stages); + state.final_stage + } else { + return Err(CmsError::UnsupportedProfileConnection); + }; + + let mut post_finalization: Vec + Send + Sync>> = + Vec::new(); + if let Some(stage) = + prepare_alpha_finalizer::(src_layout, source, dst_layout, dest, BIT_DEPTH) + { + post_finalization.push(stage); + } + + Ok(Box::new(Katana:: { + initial_stage, + final_stage, + stages, + post_finalization, + })) +} + +pub(crate) fn prepare_alpha_finalizer< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible + + GammaLutInterpolate, +>( + src_layout: Layout, + source: &ColorProfile, + dst_layout: Layout, + dest: &ColorProfile, + bit_depth: usize, +) -> Option + Send + Sync>> +where + f32: AsPrimitive, +{ + if (dst_layout == Layout::GrayAlpha && dest.color_space == DataColorSpace::Gray) + || (dst_layout == Layout::Rgba || dest.color_space == DataColorSpace::Rgb) + { + return if (src_layout == Layout::GrayAlpha && source.color_space == DataColorSpace::Gray) + || (src_layout == Layout::Rgba || source.color_space == DataColorSpace::Rgb) + { + Some(Box::new(CopyAlphaStage { + src_layout, + dst_layout, + target_color_space: dest.color_space, + _phantom: Default::default(), + })) + } else { + Some(Box::new(InjectAlphaStage { + dst_layout, + target_color_space: dest.color_space, + _phantom: Default::default(), + bit_depth, + })) + }; + } + None +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +mod avx; +#[cfg(all(target_arch = "x86_64", feature = "avx512"))] +mod avx512; +mod bpc; +mod gray2rgb; +mod gray2rgb_extended; +mod interpolator; +mod katana; +mod lut3x3; +mod lut3x4; +mod lut4; +mod lut_transforms; +mod mab; +mod mab4x3; +mod mba3x4; +mod md_lut; +mod md_luts_factory; +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +mod neon; +mod prelude_lut_xyz_rgb; +mod rgb2gray; +mod rgb2gray_extended; +mod rgb_xyz_factory; +mod rgbxyz; +mod rgbxyz_fixed; +mod rgbxyz_float; +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +mod sse; +mod transform_lut3_to_3; +mod transform_lut3_to_4; +mod transform_lut4_to_3; +mod xyz_lab; + +pub(crate) use gray2rgb::{make_gray_to_unfused, make_gray_to_x}; +pub(crate) use gray2rgb_extended::{make_gray_to_one_trc_extended, make_gray_to_rgb_extended}; +pub(crate) use interpolator::LutBarycentricReduction; +pub(crate) use lut_transforms::make_lut_transform; +pub(crate) use rgb_xyz_factory::{RgbXyzFactory, RgbXyzFactoryOpt}; +pub(crate) use rgb2gray::{ToneReproductionRgbToGray, make_rgb_to_gray}; +pub(crate) use rgb2gray_extended::make_rgb_to_gray_extended; +pub(crate) use rgbxyz::{TransformMatrixShaper, TransformMatrixShaperOptimized}; +pub(crate) use rgbxyz_float::{ + TransformShaperFloatInOut, TransformShaperRgbFloat, make_rgb_xyz_rgb_transform_float, + make_rgb_xyz_rgb_transform_float_in_out, +}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,869 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::neon::rgb_xyz::NeonAlignedF32; +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use std::arch::aarch64::*; +use std::ops::{Add, Mul, Sub}; + +pub(crate) struct TetrahedralNeon {} + +pub(crate) struct PyramidalNeon {} + +pub(crate) struct TrilinearNeon {} + +pub(crate) struct PyramidalNeonDouble {} + +pub(crate) struct PrismaticNeonDouble {} + +pub(crate) struct TrilinearNeonDouble {} + +pub(crate) struct TetrahedralNeonDouble {} + +pub(crate) struct PrismaticNeon {} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +struct TetrahedralNeonFetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [NeonAlignedF32], +} + +struct TetrahedralNeonFetchVectorDouble<'a, const GRID_SIZE: usize> { + cube0: &'a [NeonAlignedF32], + cube1: &'a [NeonAlignedF32], +} + +#[derive(Copy, Clone)] +pub(crate) struct NeonVector { + pub(crate) v: float32x4_t, +} + +#[derive(Copy, Clone)] +pub(crate) struct NeonVectorDouble { + pub(crate) v0: float32x4_t, + pub(crate) v1: float32x4_t, +} + +impl From for NeonVector { + #[inline(always)] + fn from(v: f32) -> Self { + NeonVector { + v: unsafe { vdupq_n_f32(v) }, + } + } +} + +impl From for NeonVectorDouble { + #[inline(always)] + fn from(v: f32) -> Self { + NeonVectorDouble { + v0: unsafe { vdupq_n_f32(v) }, + v1: unsafe { vdupq_n_f32(v) }, + } + } +} + +impl Sub for NeonVector { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: NeonVector) -> Self::Output { + NeonVector { + v: unsafe { vsubq_f32(self.v, rhs.v) }, + } + } +} + +impl Mul for NeonVector { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: NeonVector) -> Self::Output { + NeonVector { + v: unsafe { vmulq_f32(self.v, rhs.v) }, + } + } +} + +impl Sub for NeonVectorDouble { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: NeonVectorDouble) -> Self::Output { + NeonVectorDouble { + v0: unsafe { vsubq_f32(self.v0, rhs.v0) }, + v1: unsafe { vsubq_f32(self.v1, rhs.v1) }, + } + } +} + +impl Mul for NeonVectorDouble { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: NeonVectorDouble) -> Self::Output { + NeonVectorDouble { + v0: unsafe { vmulq_f32(self.v0, rhs.v0) }, + v1: unsafe { vmulq_f32(self.v1, rhs.v1) }, + } + } +} + +impl Add for NeonVector { + type Output = Self; + #[inline(always)] + fn add(self, rhs: NeonVector) -> Self::Output { + NeonVector { + v: unsafe { vaddq_f32(self.v, rhs.v) }, + } + } +} + +impl Add for NeonVectorDouble { + type Output = Self; + #[inline(always)] + fn add(self, rhs: NeonVectorDouble) -> Self::Output { + NeonVectorDouble { + v0: unsafe { vaddq_f32(self.v0, rhs.v0) }, + v1: unsafe { vaddq_f32(self.v1, rhs.v1) }, + } + } +} + +impl FusedMultiplyAdd for NeonVector { + #[inline(always)] + fn mla(&self, b: NeonVector, c: NeonVector) -> NeonVector { + NeonVector { + v: unsafe { vfmaq_f32(self.v, b.v, c.v) }, + } + } +} + +impl FusedMultiplyNegAdd for NeonVector { + #[inline(always)] + fn neg_mla(&self, b: NeonVector, c: NeonVector) -> NeonVector { + NeonVector { + v: unsafe { vfmsq_f32(self.v, b.v, c.v) }, + } + } +} + +impl NeonVectorDouble { + #[inline(always)] + fn neg_mla(&self, b: NeonVectorDouble, c: NeonVectorDouble) -> NeonVectorDouble { + NeonVectorDouble { + v0: unsafe { vfmsq_f32(self.v0, b.v0, c.v0) }, + v1: unsafe { vfmsq_f32(self.v1, b.v1, c.v1) }, + } + } +} + +impl NeonVectorDouble { + #[inline(always)] + fn mla(&self, b: NeonVectorDouble, c: NeonVector) -> NeonVectorDouble { + NeonVectorDouble { + v0: unsafe { vfmaq_f32(self.v0, b.v0, c.v) }, + v1: unsafe { vfmaq_f32(self.v1, b.v1, c.v) }, + } + } + + #[inline(always)] + pub(crate) fn split(self) -> (NeonVector, NeonVector) { + (NeonVector { v: self.v0 }, NeonVector { v: self.v1 }) + } +} + +impl Fetcher for TetrahedralNeonFetchVector<'_, GRID_SIZE> { + fn fetch(&self, x: i32, y: i32, z: i32) -> NeonVector { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + NeonVector { + v: unsafe { vld1q_f32(jx.as_ptr() as *const f32) }, + } + } +} + +impl Fetcher + for TetrahedralNeonFetchVectorDouble<'_, GRID_SIZE> +{ + fn fetch(&self, x: i32, y: i32, z: i32) -> NeonVectorDouble { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx0 = unsafe { self.cube0.get_unchecked(offset..) }; + let jx1 = unsafe { self.cube1.get_unchecked(offset..) }; + NeonVectorDouble { + v0: unsafe { vld1q_f32(jx0.as_ptr() as *const f32) }, + v1: unsafe { vld1q_f32(jx1.as_ptr() as *const f32) }, + } + } +} + +pub(crate) trait NeonMdInterpolation { + fn inter3_neon( + &self, + cube: &[NeonAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> NeonVector; +} + +pub(crate) trait NeonMdInterpolationDouble { + fn inter3_neon( + &self, + table0: &[NeonAlignedF32], + table1: &[NeonAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (NeonVector, NeonVector); +} + +impl TetrahedralNeon { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, NeonVector::from(rx)); + let s1 = s0.mla(c2, NeonVector::from(ry)); + s1.mla(c3, NeonVector::from(rz)) + } +} + +impl TetrahedralNeonDouble { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVector, NeonVector) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, NeonVector::from(rx)); + let s1 = s0.mla(c2, NeonVector::from(ry)); + s1.mla(c3, NeonVector::from(rz)).split() + } +} + +macro_rules! define_md_inter_neon { + ($interpolator: ident) => { + impl NeonMdInterpolation for $interpolator { + fn inter3_neon( + &self, + cube: &[NeonAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> NeonVector { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralNeonFetchVector:: { cube }, + ) + } + } + }; +} + +macro_rules! define_md_inter_neon_d { + ($interpolator: ident) => { + impl NeonMdInterpolationDouble for $interpolator { + fn inter3_neon( + &self, + table0: &[NeonAlignedF32], + table1: &[NeonAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (NeonVector, NeonVector) { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralNeonFetchVectorDouble:: { + cube0: table0, + cube1: table1, + }, + ) + } + } + }; +} + +define_md_inter_neon!(TetrahedralNeon); +define_md_inter_neon!(PyramidalNeon); +define_md_inter_neon!(PrismaticNeon); +define_md_inter_neon!(TrilinearNeon); +define_md_inter_neon_d!(PrismaticNeonDouble); +define_md_inter_neon_d!(PyramidalNeonDouble); +define_md_inter_neon_d!(TetrahedralNeonDouble); +define_md_inter_neon_d!(TrilinearNeonDouble); + +impl PyramidalNeon { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, NeonVector::from(db)); + let s1 = s0.mla(c2, NeonVector::from(dr)); + let s2 = s1.mla(c3, NeonVector::from(dg)); + s2.mla(c4, NeonVector::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, NeonVector::from(db)); + let s1 = s0.mla(c2, NeonVector::from(dr)); + let s2 = s1.mla(c3, NeonVector::from(dg)); + s2.mla(c4, NeonVector::from(dg * db)) + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, NeonVector::from(db)); + let s1 = s0.mla(c2, NeonVector::from(dr)); + let s2 = s1.mla(c3, NeonVector::from(dg)); + s2.mla(c4, NeonVector::from(db * dr)) + } + } +} + +impl PyramidalNeonDouble { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVector, NeonVector) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = NeonVector::from(db); + let w1 = NeonVector::from(dr); + let w2 = NeonVector::from(dg); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let w3 = NeonVector::from(dr * dg); + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let w3 = NeonVector::from(dg * db); + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let w3 = NeonVector::from(db * dr); + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } + } +} + +impl PrismaticNeon { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if db > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, NeonVector::from(db)); + let s1 = s0.mla(c2, NeonVector::from(dr)); + let s2 = s1.mla(c3, NeonVector::from(dg)); + let s3 = s2.mla(c4, NeonVector::from(dg * db)); + s3.mla(c5, NeonVector::from(dr * dg)) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, NeonVector::from(db)); + let s1 = s0.mla(c2, NeonVector::from(dr)); + let s2 = s1.mla(c3, NeonVector::from(dg)); + let s3 = s2.mla(c4, NeonVector::from(dg * db)); + s3.mla(c5, NeonVector::from(dr * dg)) + } + } +} + +impl PrismaticNeonDouble { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (NeonVector, NeonVector) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = rv.fetch(x, y, z); + + let w0 = NeonVector::from(db); + let w1 = NeonVector::from(dr); + let w2 = NeonVector::from(dg); + let w3 = NeonVector::from(dg * db); + let w4 = NeonVector::from(dr * dg); + + if db > dr { + let x0 = rv.fetch(x, y, z_n); + let x1 = rv.fetch(x_n, y, z_n); + let x2 = rv.fetch(x, y_n, z); + let x3 = rv.fetch(x, y_n, z_n); + let x4 = rv.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } else { + let x0 = rv.fetch(x_n, y, z); + let x1 = rv.fetch(x_n, y, z_n); + let x2 = rv.fetch(x, y_n, z); + let x3 = rv.fetch(x_n, y_n, z); + let x4 = rv.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } + } +} + +impl TrilinearNeonDouble { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVector, NeonVector) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = NeonVector::from(dr); + let w1 = NeonVector::from(dg); + let w2 = NeonVector::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = NeonVectorDouble::from(dr); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = NeonVectorDouble::from(dg); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = NeonVectorDouble::from(db); + + c0.neg_mla(c0, dz).mla(c1, w2).split() + } +} + +impl TrilinearNeon { + #[inline] + fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = NeonVector::from(dr); + let w1 = NeonVector::from(dg); + let w2 = NeonVector::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = NeonVector::from(dr); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = NeonVector::from(dg); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = NeonVector::from(db); + + c0.neg_mla(c0, dz).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/interpolator_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,915 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::BarycentricWeight; +use crate::math::FusedMultiplyAdd; +use std::arch::aarch64::*; +use std::ops::{Add, Mul, Sub}; + +#[repr(align(8), C)] +pub(crate) struct NeonAlignedI16x4(pub(crate) [i16; 4]); + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralNeonQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalNeonQ0_15 {} + +pub(crate) struct TrilinearNeonQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticNeonQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalNeonQ0_15Double {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticNeonQ0_15Double {} + +pub(crate) struct TrilinearNeonQ0_15Double {} + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralNeonQ0_15Double {} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +struct TetrahedralNeonQ0_15FetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [NeonAlignedI16x4], +} + +struct TetrahedralNeonQ0_15FetchVectorDouble<'a, const GRID_SIZE: usize> { + cube0: &'a [NeonAlignedI16x4], + cube1: &'a [NeonAlignedI16x4], +} + +#[derive(Copy, Clone)] +pub(crate) struct NeonVectorQ0_15 { + pub(crate) v: int16x4_t, +} + +#[derive(Copy, Clone)] +pub(crate) struct NeonVectorQ0_15Double { + pub(crate) v: int16x8_t, +} + +impl From for NeonVectorQ0_15 { + #[inline(always)] + fn from(v: i16) -> Self { + NeonVectorQ0_15 { + v: unsafe { vdup_n_s16(v) }, + } + } +} + +impl From for NeonVectorQ0_15Double { + #[inline(always)] + fn from(v: i16) -> Self { + NeonVectorQ0_15Double { + v: unsafe { vdupq_n_s16(v) }, + } + } +} + +impl Sub for NeonVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: NeonVectorQ0_15) -> Self::Output { + NeonVectorQ0_15 { + v: unsafe { vsub_s16(self.v, rhs.v) }, + } + } +} + +impl Mul for NeonVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: NeonVectorQ0_15) -> Self::Output { + NeonVectorQ0_15 { + v: unsafe { vqrdmulh_s16(self.v, rhs.v) }, + } + } +} + +impl Sub for NeonVectorQ0_15Double { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: NeonVectorQ0_15Double) -> Self::Output { + NeonVectorQ0_15Double { + v: unsafe { vsubq_s16(self.v, rhs.v) }, + } + } +} + +impl Mul for NeonVectorQ0_15Double { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: NeonVectorQ0_15Double) -> Self::Output { + NeonVectorQ0_15Double { + v: unsafe { vqrdmulhq_s16(self.v, rhs.v) }, + } + } +} + +impl Add for NeonVectorQ0_15 { + type Output = Self; + #[inline(always)] + fn add(self, rhs: NeonVectorQ0_15) -> Self::Output { + NeonVectorQ0_15 { + v: unsafe { vadd_s16(self.v, rhs.v) }, + } + } +} + +impl Add for NeonVectorQ0_15Double { + type Output = Self; + #[inline(always)] + fn add(self, rhs: NeonVectorQ0_15Double) -> Self::Output { + NeonVectorQ0_15Double { + v: unsafe { vaddq_s16(self.v, rhs.v) }, + } + } +} + +impl FusedMultiplyAdd for NeonVectorQ0_15 { + #[inline(always)] + fn mla(&self, b: NeonVectorQ0_15, c: NeonVectorQ0_15) -> NeonVectorQ0_15 { + NeonVectorQ0_15 { + v: unsafe { vqrdmlah_s16(self.v, b.v, c.v) }, + } + } +} + +impl NeonVectorQ0_15 { + #[inline(always)] + fn neg_mla(&self, b: NeonVectorQ0_15, c: NeonVectorQ0_15) -> NeonVectorQ0_15 { + NeonVectorQ0_15 { + v: unsafe { vqrdmlsh_s16(self.v, b.v, c.v) }, + } + } +} + +impl NeonVectorQ0_15Double { + #[inline(always)] + fn neg_mla(&self, b: NeonVectorQ0_15Double, c: NeonVectorQ0_15Double) -> NeonVectorQ0_15Double { + NeonVectorQ0_15Double { + v: unsafe { vqrdmlshq_s16(self.v, b.v, c.v) }, + } + } +} + +impl NeonVectorQ0_15Double { + #[inline(always)] + fn mla(&self, b: NeonVectorQ0_15Double, c: NeonVectorQ0_15) -> NeonVectorQ0_15Double { + NeonVectorQ0_15Double { + v: unsafe { vqrdmlahq_s16(self.v, b.v, vcombine_s16(c.v, c.v)) }, + } + } + + #[inline(always)] + pub(crate) fn split(self) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + unsafe { + ( + NeonVectorQ0_15 { + v: vget_low_s16(self.v), + }, + NeonVectorQ0_15 { + v: vget_high_s16(self.v), + }, + ) + } + } +} + +impl Fetcher + for TetrahedralNeonQ0_15FetchVector<'_, GRID_SIZE> +{ + fn fetch(&self, x: i32, y: i32, z: i32) -> NeonVectorQ0_15 { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + NeonVectorQ0_15 { + v: unsafe { vld1_s16(jx.as_ptr() as *const i16) }, + } + } +} + +impl Fetcher + for TetrahedralNeonQ0_15FetchVectorDouble<'_, GRID_SIZE> +{ + fn fetch(&self, x: i32, y: i32, z: i32) -> NeonVectorQ0_15Double { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx0 = unsafe { self.cube0.get_unchecked(offset..) }; + let jx1 = unsafe { self.cube1.get_unchecked(offset..) }; + NeonVectorQ0_15Double { + v: unsafe { + vcombine_s16( + vld1_s16(jx0.as_ptr() as *const i16), + vld1_s16(jx1.as_ptr() as *const i16), + ) + }, + } + } +} + +pub(crate) trait NeonMdInterpolationQ0_15 { + fn inter3_neon( + &self, + cube: &[NeonAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> NeonVectorQ0_15; +} + +pub(crate) trait NeonMdInterpolationQ0_15Double { + fn inter3_neon( + &self, + table0: &[NeonAlignedI16x4], + table1: &[NeonAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (NeonVectorQ0_15, NeonVectorQ0_15); +} + +#[cfg(feature = "options")] +impl TetrahedralNeonQ0_15 { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVectorQ0_15 { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, NeonVectorQ0_15::from(rx)); + let s1 = s0.mla(c2, NeonVectorQ0_15::from(ry)); + s1.mla(c3, NeonVectorQ0_15::from(rz)) + } +} + +#[cfg(feature = "options")] +impl TetrahedralNeonQ0_15Double { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, NeonVectorQ0_15::from(rx)); + let s1 = s0.mla(c2, NeonVectorQ0_15::from(ry)); + s1.mla(c3, NeonVectorQ0_15::from(rz)).split() + } +} + +macro_rules! define_md_inter_neon { + ($interpolator: ident) => { + impl NeonMdInterpolationQ0_15 for $interpolator { + fn inter3_neon( + &self, + cube: &[NeonAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> NeonVectorQ0_15 { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralNeonQ0_15FetchVector:: { cube }, + ) + } + } + } + }; +} + +macro_rules! define_md_inter_neon_d { + ($interpolator: ident) => { + impl NeonMdInterpolationQ0_15Double for $interpolator { + fn inter3_neon( + &self, + table0: &[NeonAlignedI16x4], + table1: &[NeonAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralNeonQ0_15FetchVectorDouble:: { + cube0: table0, + cube1: table1, + }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +define_md_inter_neon!(TetrahedralNeonQ0_15); +#[cfg(feature = "options")] +define_md_inter_neon!(PyramidalNeonQ0_15); +#[cfg(feature = "options")] +define_md_inter_neon!(PrismaticNeonQ0_15); +define_md_inter_neon!(TrilinearNeonQ0_15); +#[cfg(feature = "options")] +define_md_inter_neon_d!(PrismaticNeonQ0_15Double); +#[cfg(feature = "options")] +define_md_inter_neon_d!(PyramidalNeonQ0_15Double); +#[cfg(feature = "options")] +define_md_inter_neon_d!(TetrahedralNeonQ0_15Double); +define_md_inter_neon_d!(TrilinearNeonQ0_15Double); + +#[cfg(feature = "options")] +impl PyramidalNeonQ0_15 { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVectorQ0_15 { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = NeonVectorQ0_15::from(db); + let w1 = NeonVectorQ0_15::from(dr); + let w2 = NeonVectorQ0_15::from(dg); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let w3 = w1 * w2; + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let w3 = w2 * w0; + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let w3 = w0 * w1; + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3) + } + } +} + +#[cfg(feature = "options")] +impl PyramidalNeonQ0_15Double { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = NeonVectorQ0_15::from(db); + let w1 = NeonVectorQ0_15::from(dr); + let w2 = NeonVectorQ0_15::from(dg); + + if dr > db && dg > db { + let w3 = NeonVectorQ0_15::from(dr) * NeonVectorQ0_15::from(dg); + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else if db > dr && dg > dr { + let w3 = NeonVectorQ0_15::from(dg) * NeonVectorQ0_15::from(db); + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } else { + let w3 = NeonVectorQ0_15::from(db) * NeonVectorQ0_15::from(dr); + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + s2.mla(c4, w3).split() + } + } +} + +#[cfg(feature = "options")] +impl PrismaticNeonQ0_15 { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVectorQ0_15 { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let w0 = NeonVectorQ0_15::from(db); + let w1 = NeonVectorQ0_15::from(dr); + let w2 = NeonVectorQ0_15::from(dg); + + if db > dr { + let w3 = w2 * w0; + let w4 = w1 * w2; + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } else { + let w3 = w2 * w0; + let w4 = w1 * w2; + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticNeonQ0_15Double { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + rv: impl Fetcher, + ) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = rv.fetch(x, y, z); + + let w0 = NeonVectorQ0_15::from(db); + let w1 = NeonVectorQ0_15::from(dr); + let w2 = NeonVectorQ0_15::from(dg); + let w3 = NeonVectorQ0_15::from(dg) * NeonVectorQ0_15::from(db); + let w4 = NeonVectorQ0_15::from(dr) * NeonVectorQ0_15::from(dg); + + if db > dr { + let x0 = rv.fetch(x, y, z_n); + let x1 = rv.fetch(x_n, y, z_n); + let x2 = rv.fetch(x, y_n, z); + let x3 = rv.fetch(x, y_n, z_n); + let x4 = rv.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } else { + let x0 = rv.fetch(x_n, y, z); + let x1 = rv.fetch(x_n, y, z_n); + let x2 = rv.fetch(x, y_n, z); + let x3 = rv.fetch(x_n, y_n, z); + let x4 = rv.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, w0); + let s1 = s0.mla(c2, w1); + let s2 = s1.mla(c3, w2); + let s3 = s2.mla(c4, w3); + s3.mla(c5, w4).split() + } + } +} + +impl TrilinearNeonQ0_15Double { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> (NeonVectorQ0_15, NeonVectorQ0_15) { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = NeonVectorQ0_15::from(dr); + let w1 = NeonVectorQ0_15::from(dg); + let w2 = NeonVectorQ0_15::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = NeonVectorQ0_15Double::from(dr); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = NeonVectorQ0_15Double::from(dg); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = NeonVectorQ0_15Double::from(db); + + c0.neg_mla(c0, dz).mla(c1, w2).split() + } +} + +impl TrilinearNeonQ0_15 { + #[target_feature(enable = "rdm")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> NeonVectorQ0_15 { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = NeonVectorQ0_15::from(dr); + let w1 = NeonVectorQ0_15::from(dg); + let w2 = NeonVectorQ0_15::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = NeonVectorQ0_15::from(dr); + + let c00 = c000.neg_mla(c000, dx).mla(c100, w0); + let c10 = c010.neg_mla(c010, dx).mla(c110, w0); + let c01 = c001.neg_mla(c001, dx).mla(c101, w0); + let c11 = c011.neg_mla(c011, dx).mla(c111, w0); + + let dy = NeonVectorQ0_15::from(dg); + + let c0 = c00.neg_mla(c00, dy).mla(c10, w1); + let c1 = c01.neg_mla(c01, dy).mla(c11, w1); + + let dz = NeonVectorQ0_15::from(db); + + c0.neg_mla(c0, dz).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,329 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut4x3Factory; +use crate::conversions::neon::interpolator::*; +use crate::conversions::neon::interpolator_q0_15::NeonAlignedI16x4; +use crate::conversions::neon::lut4_to_3_q0_15::TransformLut4To3NeonQ0_15; +use crate::conversions::neon::rgb_xyz::NeonAlignedF32; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; +use std::marker::PhantomData; + +struct TransformLut4To3Neon< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3Neon +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[inline(never)] + fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let value_scale = unsafe { vdupq_n_f32(((1 << BIT_DEPTH) - 1) as f32) }; + let max_value = ((1 << BIT_DEPTH) - 1u32).as_(); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + let t: f32 = k_weights.w; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let (a0, b0) = interpolator.inter3_neon( + table1, + table2, + c.as_(), + m.as_(), + y.as_(), + self.weights.as_slice(), + ); + let (a0, b0) = (a0.v, b0.v); + + if T::FINITE { + unsafe { + let t0 = vdupq_n_f32(t); + let hp = vfmsq_f32(a0, a0, t0); + let mut v = vfmaq_f32(hp, b0, t0); + v = vmulq_f32(v, value_scale); + v = vminq_f32(v, value_scale); + + let jvx = vcvtaq_u32_f32(v); + + dst[cn.r_i()] = vgetq_lane_u32::<0>(jvx).as_(); + dst[cn.g_i()] = vgetq_lane_u32::<1>(jvx).as_(); + dst[cn.b_i()] = vgetq_lane_u32::<2>(jvx).as_(); + } + } else { + unsafe { + let t0 = vdupq_n_f32(t); + let hp = vfmsq_f32(a0, a0, t0); + let v = vfmaq_f32(hp, b0, t0); + + dst[cn.r_i()] = vgetq_lane_f32::<0>(v).as_(); + dst[cn.g_i()] = vgetq_lane_f32::<1>(v).as_(); + dst[cn.b_i()] = vgetq_lane_f32::<2>(v).as_(); + } + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3Neon +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearNeonDouble:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk(src, dst, Box::new(TetrahedralNeonDouble:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalNeonDouble:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticNeonDouble:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearNeonDouble:: {})); + } + } + } + + Ok(()) + } +} + +pub(crate) struct NeonLut4x3Factory {} + +impl Lut4x3Factory for NeonLut4x3Factory { + fn make_transform_4x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Sync + Send> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point + && BIT_DEPTH < 16 + && std::arch::is_aarch64_feature_detected!("rdm") + { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + NeonAlignedI16x4([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut4To3NeonQ0_15::< + T, + u8, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut4To3NeonQ0_15::< + T, + u16, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }; + } + let lut = lut + .chunks_exact(3) + .map(|x| NeonAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => { + Box::new( + TransformLut4To3Neon:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }, + ) + } + #[cfg(feature = "options")] + BarycentricWeightScale::High => { + Box::new( + TransformLut4To3Neon:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }, + ) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/lut4_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,226 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::neon::interpolator_q0_15::*; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut4To3NeonQ0_15< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3NeonQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "rdm")] + #[inline(never)] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let f_value_scale = vdupq_n_f32(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + vdup_n_s16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + vdup_n_s16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + let t: i16 = k_weights.w; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let (a0, b0) = interpolator.inter3_neon( + table1, + table2, + c.as_(), + m.as_(), + y.as_(), + self.weights.as_slice(), + ); + let (a0, b0) = (a0.v, b0.v); + + let t0 = vdup_n_s16(t); + let hp = vqrdmlsh_s16(a0, a0, t0); + let mut v = vqrdmlah_s16(hp, b0, t0); + + if T::FINITE { + v = vmax_s16(v, vdup_n_s16(0)); + v = vmin_s16(v, v_max_scale); + dst[cn.r_i()] = (vget_lane_s16::<0>(v) as u32).as_(); + dst[cn.g_i()] = (vget_lane_s16::<1>(v) as u32).as_(); + dst[cn.b_i()] = (vget_lane_s16::<2>(v) as u32).as_(); + } else { + let o = vcvtq_f32_s32(vmovl_s16(v)); + let r = vmulq_f32(o, f_value_scale); + dst[cn.r_i()] = vgetq_lane_f32::<0>(r).as_(); + dst[cn.g_i()] = vgetq_lane_f32::<1>(r).as_(); + dst[cn.b_i()] = vgetq_lane_f32::<2>(r).as_(); + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3NeonQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearNeonQ0_15Double:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralNeonQ0_15Double:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk( + src, + dst, + Box::new(PyramidalNeonQ0_15Double:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk( + src, + dst, + Box::new(PrismaticNeonQ0_15Double:: {}), + ); + } + InterpolationMethod::Linear => { + self.transform_chunk( + src, + dst, + Box::new(TrilinearNeonQ0_15Double:: {}), + ); + } + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod interpolator; +mod interpolator_q0_15; +mod lut4_to_3; +mod lut4_to_3_q0_15; +mod rgb_xyz; +mod rgb_xyz_opt; +mod rgb_xyz_q1_30_opt; +mod rgb_xyz_q2_13; +mod rgb_xyz_q2_13_opt; +mod t_lut3_to_3; +mod t_lut3_to_3_q0_15; + +pub(crate) use lut4_to_3::NeonLut4x3Factory; +pub(crate) use rgb_xyz::TransformShaperRgbNeon; +pub(crate) use rgb_xyz_opt::TransformShaperRgbOptNeon; +pub(crate) use rgb_xyz_q1_30_opt::TransformShaperQ1_30NeonOpt; +pub(crate) use rgb_xyz_q2_13::TransformShaperQ2_13Neon; +pub(crate) use rgb_xyz_q2_13_opt::TransformShaperQ2_13NeonOpt; +pub(crate) use t_lut3_to_3::NeonLut3x3Factory; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,440 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::neon::rgb_xyz_q2_13::{split_by_twos, split_by_twos_mut}; +use crate::conversions::rgbxyz::TransformMatrixShaperV; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; + +#[repr(align(16), C)] +pub(crate) struct NeonAlignedU16(pub(crate) [u16; 8]); + +#[repr(align(16), C)] +pub(crate) struct NeonAlignedF32(pub(crate) [f32; 4]); + +pub(crate) struct TransformShaperRgbNeon< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> { + pub(crate) profile: TransformMatrixShaperV, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperRgbNeon +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = NeonAlignedU16([0; 8]); + let mut temporary1 = NeonAlignedU16([0; 8]); + let mut temporary2 = NeonAlignedU16([0; 8]); + let mut temporary3 = NeonAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.r_linear.len() >= cap); + assert!(self.profile.g_linear.len() >= cap); + assert!(self.profile.b_linear.len() >= cap); + } else { + assert!(self.profile.r_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.g_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.b_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let r_lin = &self.profile.r_linear; + let g_lin = &self.profile.g_linear; + let b_lin = &self.profile.b_linear; + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + unsafe { + let m0 = vld1q_f32([t.v[0][0], t.v[0][1], t.v[0][2], 0.].as_ptr()); + let m1 = vld1q_f32([t.v[1][0], t.v[1][1], t.v[1][2], 0.].as_ptr()); + let m2 = vld1q_f32([t.v[2][0], t.v[2][1], t.v[2][2], 0.].as_ptr()); + + let v_scale = vdupq_n_f32(scale); + + let rnd = vdupq_n_f32(0.5); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + let r0p = r_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = g_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = b_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = r_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = g_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = b_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = r_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = g_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = b_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = r_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = g_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = b_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_f32(r0p); + g0 = vld1q_dup_f32(g0p); + b0 = vld1q_dup_f32(b0p); + + r1 = vld1q_dup_f32(r1p); + g1 = vld1q_dup_f32(g1p); + b1 = vld1q_dup_f32(b1p); + + r2 = vld1q_dup_f32(r2p); + g2 = vld1q_dup_f32(g2p); + b2 = vld1q_dup_f32(b2p); + + r3 = vld1q_dup_f32(r3p); + g3 = vld1q_dup_f32(g3p); + b3 = vld1q_dup_f32(b3p); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = vdupq_n_f32(0.); + g0 = vdupq_n_f32(0.); + b0 = vdupq_n_f32(0.); + r1 = vdupq_n_f32(0.); + g1 = vdupq_n_f32(0.); + b1 = vdupq_n_f32(0.); + r2 = vdupq_n_f32(0.); + g2 = vdupq_n_f32(0.); + b2 = vdupq_n_f32(0.); + r3 = vdupq_n_f32(0.); + g3 = vdupq_n_f32(0.); + b3 = vdupq_n_f32(0.); + a0 = max_colors; + a1 = max_colors; + a2 = max_colors; + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let v0_0 = vmulq_f32(r0, m0); + let v0_1 = vmulq_f32(r1, m0); + let v0_2 = vmulq_f32(r2, m0); + let v0_3 = vmulq_f32(r3, m0); + + let v1_0 = vfmaq_f32(v0_0, g0, m1); + let v1_1 = vfmaq_f32(v0_1, g1, m1); + let v1_2 = vfmaq_f32(v0_2, g2, m1); + let v1_3 = vfmaq_f32(v0_3, g3, m1); + + let mut vr0 = vfmaq_f32(v1_0, b0, m2); + let mut vr1 = vfmaq_f32(v1_1, b1, m2); + let mut vr2 = vfmaq_f32(v1_2, b2, m2); + let mut vr3 = vfmaq_f32(v1_3, b3, m2); + + vr0 = vfmaq_f32(rnd, vr0, v_scale); + vr1 = vfmaq_f32(rnd, vr1, v_scale); + vr2 = vfmaq_f32(rnd, vr2, v_scale); + vr3 = vfmaq_f32(rnd, vr3, v_scale); + + vr0 = vminq_f32(vr0, v_scale); + vr1 = vminq_f32(vr1, v_scale); + vr2 = vminq_f32(vr2, v_scale); + vr3 = vminq_f32(vr3, v_scale); + + let zx0 = vcvtq_u32_f32(vr0); + let zx1 = vcvtq_u32_f32(vr1); + let zx2 = vcvtq_u32_f32(vr2); + let zx3 = vcvtq_u32_f32(vr3); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx0); + vst1q_u32(temporary1.0.as_mut_ptr() as *mut _, zx1); + vst1q_u32(temporary2.0.as_mut_ptr() as *mut _, zx2); + vst1q_u32(temporary3.0.as_mut_ptr() as *mut _, zx3); + + let r0p = r_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = g_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = b_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = r_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = g_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = b_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = r_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = g_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = b_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = r_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = g_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = b_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_f32(r0p); + g0 = vld1q_dup_f32(g0p); + b0 = vld1q_dup_f32(b0p); + + r1 = vld1q_dup_f32(r1p); + g1 = vld1q_dup_f32(g1p); + b1 = vld1q_dup_f32(b1p); + + r2 = vld1q_dup_f32(r2p); + g2 = vld1q_dup_f32(g2p); + b2 = vld1q_dup_f32(b2p); + + r3 = vld1q_dup_f32(r3p); + g3 = vld1q_dup_f32(g3p); + b3 = vld1q_dup_f32(b3p); + + dst0[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[temporary1.0[0] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[temporary1.0[2] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.r_gamma[temporary2.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.g_gamma[temporary2.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.b_gamma[temporary2.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[temporary3.0[0] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[temporary3.0[2] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[temporary3.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let v0_0 = vmulq_f32(r0, m0); + let v0_1 = vmulq_f32(r1, m0); + let v0_2 = vmulq_f32(r2, m0); + let v0_3 = vmulq_f32(r3, m0); + + let v1_0 = vfmaq_f32(v0_0, g0, m1); + let v1_1 = vfmaq_f32(v0_1, g1, m1); + let v1_2 = vfmaq_f32(v0_2, g2, m1); + let v1_3 = vfmaq_f32(v0_3, g3, m1); + + let mut vr0 = vfmaq_f32(v1_0, b0, m2); + let mut vr1 = vfmaq_f32(v1_1, b1, m2); + let mut vr2 = vfmaq_f32(v1_2, b2, m2); + let mut vr3 = vfmaq_f32(v1_3, b3, m2); + + vr0 = vfmaq_f32(rnd, vr0, v_scale); + vr1 = vfmaq_f32(rnd, vr1, v_scale); + vr2 = vfmaq_f32(rnd, vr2, v_scale); + vr3 = vfmaq_f32(rnd, vr3, v_scale); + + vr0 = vminq_f32(vr0, v_scale); + vr1 = vminq_f32(vr1, v_scale); + vr2 = vminq_f32(vr2, v_scale); + vr3 = vminq_f32(vr3, v_scale); + + let zx0 = vcvtq_u32_f32(vr0); + let zx1 = vcvtq_u32_f32(vr1); + let zx2 = vcvtq_u32_f32(vr2); + let zx3 = vcvtq_u32_f32(vr3); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx0); + vst1q_u32(temporary1.0.as_mut_ptr() as *mut _, zx1); + vst1q_u32(temporary2.0.as_mut_ptr() as *mut _, zx2); + vst1q_u32(temporary3.0.as_mut_ptr() as *mut _, zx3); + + dst0[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[temporary1.0[0] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[temporary1.0[2] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.r_gamma[temporary2.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.g_gamma[temporary2.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.b_gamma[temporary2.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[temporary3.0[0] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[temporary3.0[2] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[temporary3.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let rp = r_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = g_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = b_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + let r = vld1q_dup_f32(rp); + let g = vld1q_dup_f32(gp); + let b = vld1q_dup_f32(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = vmulq_f32(r, m0); + let v1 = vfmaq_f32(v0, g, m1); + let mut v = vfmaq_f32(v1, b, m2); + + v = vfmaq_f32(rnd, v, v_scale); + v = vminq_f32(v, v_scale); + + let zx = vcvtq_u32_f32(v); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,429 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::neon::rgb_xyz::NeonAlignedU16; +use crate::conversions::neon::rgb_xyz_q2_13::{split_by_twos, split_by_twos_mut}; +use crate::conversions::rgbxyz::TransformMatrixShaperOptimizedV; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; + +pub(crate) struct TransformShaperRgbOptNeon< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> { + pub(crate) profile: TransformMatrixShaperOptimizedV, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperRgbOptNeon +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary0 = NeonAlignedU16([0; 8]); + let mut temporary1 = NeonAlignedU16([0; 8]); + let mut temporary2 = NeonAlignedU16([0; 8]); + let mut temporary3 = NeonAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + unsafe { + let m0 = vld1q_f32([t.v[0][0], t.v[0][1], t.v[0][2], 0.].as_ptr()); + let m1 = vld1q_f32([t.v[1][0], t.v[1][1], t.v[1][2], 0.].as_ptr()); + let m2 = vld1q_f32([t.v[2][0], t.v[2][1], t.v[2][2], 0.].as_ptr()); + + let v_scale = vdupq_n_f32(scale); + + let rnd = vdupq_n_f32(0.5); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + let r0p = lut_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lut_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lut_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lut_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lut_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lut_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lut_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lut_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lut_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lut_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lut_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lut_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_f32(r0p); + g0 = vld1q_dup_f32(g0p); + b0 = vld1q_dup_f32(b0p); + + r1 = vld1q_dup_f32(r1p); + g1 = vld1q_dup_f32(g1p); + b1 = vld1q_dup_f32(b1p); + + r2 = vld1q_dup_f32(r2p); + g2 = vld1q_dup_f32(g2p); + b2 = vld1q_dup_f32(b2p); + + r3 = vld1q_dup_f32(r3p); + g3 = vld1q_dup_f32(g3p); + b3 = vld1q_dup_f32(b3p); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = vdupq_n_f32(0.); + g0 = vdupq_n_f32(0.); + b0 = vdupq_n_f32(0.); + r1 = vdupq_n_f32(0.); + g1 = vdupq_n_f32(0.); + b1 = vdupq_n_f32(0.); + r2 = vdupq_n_f32(0.); + g2 = vdupq_n_f32(0.); + b2 = vdupq_n_f32(0.); + r3 = vdupq_n_f32(0.); + g3 = vdupq_n_f32(0.); + b3 = vdupq_n_f32(0.); + a0 = max_colors; + a1 = max_colors; + a2 = max_colors; + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let v0_0 = vmulq_f32(r0, m0); + let v0_1 = vmulq_f32(r1, m0); + let v0_2 = vmulq_f32(r2, m0); + let v0_3 = vmulq_f32(r3, m0); + + let v1_0 = vfmaq_f32(v0_0, g0, m1); + let v1_1 = vfmaq_f32(v0_1, g1, m1); + let v1_2 = vfmaq_f32(v0_2, g2, m1); + let v1_3 = vfmaq_f32(v0_3, g3, m1); + + let mut vr0 = vfmaq_f32(v1_0, b0, m2); + let mut vr1 = vfmaq_f32(v1_1, b1, m2); + let mut vr2 = vfmaq_f32(v1_2, b2, m2); + let mut vr3 = vfmaq_f32(v1_3, b3, m2); + + vr0 = vfmaq_f32(rnd, vr0, v_scale); + vr1 = vfmaq_f32(rnd, vr1, v_scale); + vr2 = vfmaq_f32(rnd, vr2, v_scale); + vr3 = vfmaq_f32(rnd, vr3, v_scale); + + vr0 = vminq_f32(vr0, v_scale); + vr1 = vminq_f32(vr1, v_scale); + vr2 = vminq_f32(vr2, v_scale); + vr3 = vminq_f32(vr3, v_scale); + + let zx0 = vcvtq_u32_f32(vr0); + let zx1 = vcvtq_u32_f32(vr1); + let zx2 = vcvtq_u32_f32(vr2); + let zx3 = vcvtq_u32_f32(vr3); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx0); + vst1q_u32(temporary1.0.as_mut_ptr() as *mut _, zx1); + vst1q_u32(temporary2.0.as_mut_ptr() as *mut _, zx2); + vst1q_u32(temporary3.0.as_mut_ptr() as *mut _, zx3); + + let r0p = lut_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lut_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lut_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lut_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lut_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lut_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lut_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lut_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lut_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lut_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lut_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lut_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_f32(r0p); + g0 = vld1q_dup_f32(g0p); + b0 = vld1q_dup_f32(b0p); + + r1 = vld1q_dup_f32(r1p); + g1 = vld1q_dup_f32(g1p); + b1 = vld1q_dup_f32(b1p); + + r2 = vld1q_dup_f32(r2p); + g2 = vld1q_dup_f32(g2p); + b2 = vld1q_dup_f32(b2p); + + r3 = vld1q_dup_f32(r3p); + g3 = vld1q_dup_f32(g3p); + b3 = vld1q_dup_f32(b3p); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[0] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[2] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary2.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary2.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary2.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary3.0[0] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary3.0[2] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary3.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let v0_0 = vmulq_f32(r0, m0); + let v0_1 = vmulq_f32(r1, m0); + let v0_2 = vmulq_f32(r2, m0); + let v0_3 = vmulq_f32(r3, m0); + + let v1_0 = vfmaq_f32(v0_0, g0, m1); + let v1_1 = vfmaq_f32(v0_1, g1, m1); + let v1_2 = vfmaq_f32(v0_2, g2, m1); + let v1_3 = vfmaq_f32(v0_3, g3, m1); + + let mut vr0 = vfmaq_f32(v1_0, b0, m2); + let mut vr1 = vfmaq_f32(v1_1, b1, m2); + let mut vr2 = vfmaq_f32(v1_2, b2, m2); + let mut vr3 = vfmaq_f32(v1_3, b3, m2); + + vr0 = vfmaq_f32(rnd, vr0, v_scale); + vr1 = vfmaq_f32(rnd, vr1, v_scale); + vr2 = vfmaq_f32(rnd, vr2, v_scale); + vr3 = vfmaq_f32(rnd, vr3, v_scale); + + vr0 = vminq_f32(vr0, v_scale); + vr1 = vminq_f32(vr1, v_scale); + vr2 = vminq_f32(vr2, v_scale); + vr3 = vminq_f32(vr3, v_scale); + + let zx0 = vcvtq_u32_f32(vr0); + let zx1 = vcvtq_u32_f32(vr1); + let zx2 = vcvtq_u32_f32(vr2); + let zx3 = vcvtq_u32_f32(vr3); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx0); + vst1q_u32(temporary1.0.as_mut_ptr() as *mut _, zx1); + vst1q_u32(temporary2.0.as_mut_ptr() as *mut _, zx2); + vst1q_u32(temporary3.0.as_mut_ptr() as *mut _, zx3); + + dst0[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary1.0[0] as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary1.0[2] as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary1.0[4] as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[temporary2.0[0] as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[temporary2.0[2] as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[temporary2.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[temporary3.0[0] as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[temporary3.0[2] as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[temporary3.0[4] as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let rp = lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + let r = vld1q_dup_f32(rp); + let g = vld1q_dup_f32(gp); + let b = vld1q_dup_f32(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = vmulq_f32(r, m0); + let v1 = vfmaq_f32(v0, g, m1); + let mut v = vfmaq_f32(v1, b, m2); + + v = vfmaq_f32(rnd, v, v_scale); + v = vminq_f32(v, v_scale); + + let zx = vcvtq_u32_f32(v); + vst1q_u32(temporary0.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary0.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary0.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary0.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q1_30_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q1_30_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q1_30_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q1_30_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,408 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::neon::rgb_xyz_q2_13::{split_by_twos, split_by_twos_mut}; +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFpOptVec; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; + +pub(crate) struct TransformShaperQ1_30NeonOpt { + pub(crate) profile: TransformMatrixShaperFpOptVec, + pub(crate) gamma_lut: usize, + pub(crate) bit_depth: usize, +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformShaperQ1_30NeonOpt +where + u32: AsPrimitive, +{ + #[target_feature(enable = "rdm")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + // safety precondition for linearization table + if T::FINITE { + assert!(self.profile.linear.len() >= (1 << self.bit_depth) - 1); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + unsafe { + let m0 = vld1q_s32([t.v[0][0], t.v[0][1], t.v[0][2], 0].as_ptr()); + let m1 = vld1q_s32([t.v[1][0], t.v[1][1], t.v[1][2], 0].as_ptr()); + let m2 = vld1q_s32([t.v[2][0], t.v[2][1], t.v[2][2], 0].as_ptr()); + + let lin_lut = &self.profile.linear; + + let v_max_value = vdup_n_u16((self.gamma_lut - 1) as u16); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + let r0p = lin_lut.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lin_lut.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lin_lut.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lin_lut.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lin_lut.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lin_lut.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lin_lut.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lin_lut.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lin_lut.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lin_lut.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lin_lut.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lin_lut.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_s32(r0p); + g0 = vld1q_dup_s32(g0p); + b0 = vld1q_dup_s32(b0p); + + r1 = vld1q_dup_s32(r1p); + g1 = vld1q_dup_s32(g1p); + b1 = vld1q_dup_s32(b1p); + + r2 = vld1q_dup_s32(r2p); + g2 = vld1q_dup_s32(g2p); + b2 = vld1q_dup_s32(b2p); + + r3 = vld1q_dup_s32(r3p); + g3 = vld1q_dup_s32(g3p); + b3 = vld1q_dup_s32(b3p); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = vdupq_n_s32(0); + g0 = vdupq_n_s32(0); + b0 = vdupq_n_s32(0); + r1 = vdupq_n_s32(0); + g1 = vdupq_n_s32(0); + b1 = vdupq_n_s32(0); + r2 = vdupq_n_s32(0); + g2 = vdupq_n_s32(0); + b2 = vdupq_n_s32(0); + r3 = vdupq_n_s32(0); + g3 = vdupq_n_s32(0); + b3 = vdupq_n_s32(0); + a0 = max_colors; + a1 = max_colors; + a2 = max_colors; + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let v0_0 = vqrdmulhq_s32(r0, m0); + let v0_1 = vqrdmulhq_s32(r1, m0); + let v0_2 = vqrdmulhq_s32(r2, m0); + let v0_3 = vqrdmulhq_s32(r3, m0); + + let v1_0 = vqrdmlahq_s32(v0_0, g0, m1); + let v1_1 = vqrdmlahq_s32(v0_1, g1, m1); + let v1_2 = vqrdmlahq_s32(v0_2, g2, m1); + let v1_3 = vqrdmlahq_s32(v0_3, g3, m1); + + let vr0 = vqrdmlahq_s32(v1_0, b0, m2); + let vr1 = vqrdmlahq_s32(v1_1, b1, m2); + let vr2 = vqrdmlahq_s32(v1_2, b2, m2); + let vr3 = vqrdmlahq_s32(v1_3, b3, m2); + + let mut vr0 = vqmovun_s32(vr0); + let mut vr1 = vqmovun_s32(vr1); + let mut vr2 = vqmovun_s32(vr2); + let mut vr3 = vqmovun_s32(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + let r0p = lin_lut.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lin_lut.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lin_lut.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lin_lut.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lin_lut.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lin_lut.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lin_lut.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lin_lut.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lin_lut.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lin_lut.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lin_lut.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lin_lut.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1q_dup_s32(r0p); + g0 = vld1q_dup_s32(g0p); + b0 = vld1q_dup_s32(b0p); + + r1 = vld1q_dup_s32(r1p); + g1 = vld1q_dup_s32(g1p); + b1 = vld1q_dup_s32(b1p); + + r2 = vld1q_dup_s32(r2p); + g2 = vld1q_dup_s32(g2p); + b2 = vld1q_dup_s32(b2p); + + r3 = vld1q_dup_s32(r3p); + g3 = vld1q_dup_s32(g3p); + b3 = vld1q_dup_s32(b3p); + + dst0[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let v0_0 = vqrdmulhq_s32(r0, m0); + let v0_1 = vqrdmulhq_s32(r1, m0); + let v0_2 = vqrdmulhq_s32(r2, m0); + let v0_3 = vqrdmulhq_s32(r3, m0); + + let v1_0 = vqrdmlahq_s32(v0_0, g0, m1); + let v1_1 = vqrdmlahq_s32(v0_1, g1, m1); + let v1_2 = vqrdmlahq_s32(v0_2, g2, m1); + let v1_3 = vqrdmlahq_s32(v0_3, g3, m1); + + let vr0 = vqrdmlahq_s32(v1_0, b0, m2); + let vr1 = vqrdmlahq_s32(v1_1, b1, m2); + let vr2 = vqrdmlahq_s32(v1_2, b2, m2); + let vr3 = vqrdmlahq_s32(v1_3, b3, m2); + + let mut vr0 = vqmovun_s32(vr0); + let mut vr1 = vqmovun_s32(vr1); + let mut vr2 = vqmovun_s32(vr2); + let mut vr3 = vqmovun_s32(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + dst0[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let rp = lin_lut.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = lin_lut.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = lin_lut.get_unchecked(src[src_cn.b_i()]._as_usize()); + let r = vld1q_dup_s32(rp); + let g = vld1q_dup_s32(gp); + let b = vld1q_dup_s32(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = vqrdmulhq_s32(r, m0); + let v1 = vqrdmlahq_s32(v0, g, m1); + let v = vqrdmlahq_s32(v1, b, m2); + + let mut vr0 = vqmovun_s32(v); + vr0 = vmin_u16(vr0, v_max_value); + + dst[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperQ1_30NeonOpt +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,424 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFp; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; + +#[allow(dead_code)] +#[inline] +pub(crate) fn split_by_twos(data: &[T], channels: usize) -> (&[T], &[T]) { + let len = data.len() / (channels * 4); + let split_point = len * 4; + data.split_at(split_point * channels) +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn split_by_twos_mut(data: &mut [T], channels: usize) -> (&mut [T], &mut [T]) { + let len = data.len() / (channels * 4); + let split_point = len * 4; + data.split_at_mut(split_point * channels) +} + +pub(crate) struct TransformShaperQ2_13Neon< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFp, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperQ2_13Neon +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.r_linear.len() >= cap); + assert!(self.profile.g_linear.len() >= cap); + assert!(self.profile.b_linear.len() >= cap); + } else { + assert!(self.profile.r_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.g_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.b_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let r_lin = &self.profile.r_linear; + let g_lin = &self.profile.g_linear; + let b_lin = &self.profile.b_linear; + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + unsafe { + let m0 = vld1_s16([t.v[0][0], t.v[0][1], t.v[0][2], 0].as_ptr()); + let m1 = vld1_s16([t.v[1][0], t.v[1][1], t.v[1][2], 0].as_ptr()); + let m2 = vld1_s16([t.v[2][0], t.v[2][1], t.v[2][2], 0].as_ptr()); + + let v_max_value = vdup_n_u16((self.gamma_lut - 1) as u16); + + let rnd = vdupq_n_s32(1 << (PRECISION - 1)); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + let r0p = r_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = g_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = b_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = r_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = g_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = b_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = r_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = g_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = b_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = r_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = g_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = b_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1_dup_s16(r0p); + g0 = vld1_dup_s16(g0p); + b0 = vld1_dup_s16(b0p); + + r1 = vld1_dup_s16(r1p); + g1 = vld1_dup_s16(g1p); + b1 = vld1_dup_s16(b1p); + + r2 = vld1_dup_s16(r2p); + g2 = vld1_dup_s16(g2p); + b2 = vld1_dup_s16(b2p); + + r3 = vld1_dup_s16(r3p); + g3 = vld1_dup_s16(g3p); + b3 = vld1_dup_s16(b3p); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = vdup_n_s16(0); + g0 = vdup_n_s16(0); + b0 = vdup_n_s16(0); + r1 = vdup_n_s16(0); + g1 = vdup_n_s16(0); + b1 = vdup_n_s16(0); + r2 = vdup_n_s16(0); + g2 = vdup_n_s16(0); + b2 = vdup_n_s16(0); + r3 = vdup_n_s16(0); + g3 = vdup_n_s16(0); + b3 = vdup_n_s16(0); + a0 = max_colors; + a1 = max_colors; + a2 = max_colors; + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let v0_0 = vmlal_s16(rnd, r0, m0); + let v0_1 = vmlal_s16(rnd, r1, m0); + let v0_2 = vmlal_s16(rnd, r2, m0); + let v0_3 = vmlal_s16(rnd, r3, m0); + + let v1_0 = vmlal_s16(v0_0, g0, m1); + let v1_1 = vmlal_s16(v0_1, g1, m1); + let v1_2 = vmlal_s16(v0_2, g2, m1); + let v1_3 = vmlal_s16(v0_3, g3, m1); + + let vr0 = vmlal_s16(v1_0, b0, m2); + let vr1 = vmlal_s16(v1_1, b1, m2); + let vr2 = vmlal_s16(v1_2, b2, m2); + let vr3 = vmlal_s16(v1_3, b3, m2); + + let mut vr0 = vqshrun_n_s32::(vr0); + let mut vr1 = vqshrun_n_s32::(vr1); + let mut vr2 = vqshrun_n_s32::(vr2); + let mut vr3 = vqshrun_n_s32::(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + let r0p = r_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = g_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = b_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = r_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = g_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = b_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = r_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = g_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = b_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = r_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = g_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = b_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1_dup_s16(r0p); + g0 = vld1_dup_s16(g0p); + b0 = vld1_dup_s16(b0p); + + r1 = vld1_dup_s16(r1p); + g1 = vld1_dup_s16(g1p); + b1 = vld1_dup_s16(b1p); + + r2 = vld1_dup_s16(r2p); + g2 = vld1_dup_s16(g2p); + b2 = vld1_dup_s16(b2p); + + r3 = vld1_dup_s16(r3p); + g3 = vld1_dup_s16(g3p); + b3 = vld1_dup_s16(b3p); + + dst0[dst_cn.r_i()] = self.profile.r_gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.g_gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.b_gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.r_gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.g_gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.b_gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let v0_0 = vmlal_s16(rnd, r0, m0); + let v0_1 = vmlal_s16(rnd, r1, m0); + let v0_2 = vmlal_s16(rnd, r2, m0); + let v0_3 = vmlal_s16(rnd, r3, m0); + + let v1_0 = vmlal_s16(v0_0, g0, m1); + let v1_1 = vmlal_s16(v0_1, g1, m1); + let v1_2 = vmlal_s16(v0_2, g2, m1); + let v1_3 = vmlal_s16(v0_3, g3, m1); + + let vr0 = vmlal_s16(v1_0, b0, m2); + let vr1 = vmlal_s16(v1_1, b1, m2); + let vr2 = vmlal_s16(v1_2, b2, m2); + let vr3 = vmlal_s16(v1_3, b3, m2); + + let mut vr0 = vqshrun_n_s32::(vr0); + let mut vr1 = vqshrun_n_s32::(vr1); + let mut vr2 = vqshrun_n_s32::(vr2); + let mut vr3 = vqshrun_n_s32::(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + dst0[dst_cn.r_i()] = self.profile.r_gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.g_gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.b_gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.r_gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.g_gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.b_gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.r_gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.g_gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.b_gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let rp = r_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = g_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = b_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + let r = vld1_dup_s16(rp); + let g = vld1_dup_s16(gp); + let b = vld1_dup_s16(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = vmlal_s16(rnd, r, m0); + let v1 = vmlal_s16(v0, g, m1); + let v = vmlal_s16(v1, b, m2); + + let mut vr0 = vqshrun_n_s32::(v); + vr0 = vmin_u16(vr0, v_max_value); + + dst[dst_cn.r_i()] = self.profile.r_gamma[vget_lane_u16::<0>(vr0) as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[vget_lane_u16::<1>(vr0) as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/rgb_xyz_q2_13_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,403 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::neon::rgb_xyz_q2_13::{split_by_twos, split_by_twos_mut}; +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFpOptVec; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; + +pub(crate) struct TransformShaperQ2_13NeonOpt< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFpOptVec, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperQ2_13NeonOpt +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + let (src_chunks, src_remainder) = split_by_twos(src, src_channels); + let (dst_chunks, dst_remainder) = split_by_twos_mut(dst, dst_channels); + + unsafe { + let m0 = vld1_s16([t.v[0][0], t.v[0][1], t.v[0][2], 0].as_ptr()); + let m1 = vld1_s16([t.v[1][0], t.v[1][1], t.v[1][2], 0].as_ptr()); + let m2 = vld1_s16([t.v[2][0], t.v[2][1], t.v[2][2], 0].as_ptr()); + + let v_max_value = vdup_n_u16((self.gamma_lut - 1) as u16); + + let rnd = vdupq_n_s32(1 << (PRECISION - 1)); + + if !src_chunks.is_empty() { + let (src0, src1) = src_chunks.split_at(src_chunks.len() / 2); + let (dst0, dst1) = dst_chunks.split_at_mut(dst_chunks.len() / 2); + let mut src_iter0 = src0.chunks_exact(src_channels * 2); + let mut src_iter1 = src1.chunks_exact(src_channels * 2); + + let (mut r0, mut g0, mut b0, mut a0); + let (mut r1, mut g1, mut b1, mut a1); + let (mut r2, mut g2, mut b2, mut a2); + let (mut r3, mut g3, mut b3, mut a3); + + if let (Some(src0), Some(src1)) = (src_iter0.next(), src_iter1.next()) { + let r0p = lut_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lut_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lut_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lut_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lut_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lut_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lut_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lut_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lut_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lut_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lut_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lut_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1_dup_s16(r0p); + g0 = vld1_dup_s16(g0p); + b0 = vld1_dup_s16(b0p); + + r1 = vld1_dup_s16(r1p); + g1 = vld1_dup_s16(g1p); + b1 = vld1_dup_s16(b1p); + + r2 = vld1_dup_s16(r2p); + g2 = vld1_dup_s16(g2p); + b2 = vld1_dup_s16(b2p); + + r3 = vld1_dup_s16(r3p); + g3 = vld1_dup_s16(g3p); + b3 = vld1_dup_s16(b3p); + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } else { + r0 = vdup_n_s16(0); + g0 = vdup_n_s16(0); + b0 = vdup_n_s16(0); + r1 = vdup_n_s16(0); + g1 = vdup_n_s16(0); + b1 = vdup_n_s16(0); + r2 = vdup_n_s16(0); + g2 = vdup_n_s16(0); + b2 = vdup_n_s16(0); + r3 = vdup_n_s16(0); + g3 = vdup_n_s16(0); + b3 = vdup_n_s16(0); + a0 = max_colors; + a1 = max_colors; + a2 = max_colors; + a3 = max_colors; + } + + for (((src0, src1), dst0), dst1) in src_iter0 + .zip(src_iter1) + .zip(dst0.chunks_exact_mut(dst_channels * 2)) + .zip(dst1.chunks_exact_mut(dst_channels * 2)) + { + let v0_0 = vmlal_s16(rnd, r0, m0); + let v0_1 = vmlal_s16(rnd, r1, m0); + let v0_2 = vmlal_s16(rnd, r2, m0); + let v0_3 = vmlal_s16(rnd, r3, m0); + + let v1_0 = vmlal_s16(v0_0, g0, m1); + let v1_1 = vmlal_s16(v0_1, g1, m1); + let v1_2 = vmlal_s16(v0_2, g2, m1); + let v1_3 = vmlal_s16(v0_3, g3, m1); + + let vr0 = vmlal_s16(v1_0, b0, m2); + let vr1 = vmlal_s16(v1_1, b1, m2); + let vr2 = vmlal_s16(v1_2, b2, m2); + let vr3 = vmlal_s16(v1_3, b3, m2); + + let mut vr0 = vqshrun_n_s32::(vr0); + let mut vr1 = vqshrun_n_s32::(vr1); + let mut vr2 = vqshrun_n_s32::(vr2); + let mut vr3 = vqshrun_n_s32::(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + let r0p = lut_lin.get_unchecked(src0[src_cn.r_i()]._as_usize()); + let g0p = lut_lin.get_unchecked(src0[src_cn.g_i()]._as_usize()); + let b0p = lut_lin.get_unchecked(src0[src_cn.b_i()]._as_usize()); + + let r1p = lut_lin.get_unchecked(src0[src_cn.r_i() + src_channels]._as_usize()); + let g1p = lut_lin.get_unchecked(src0[src_cn.g_i() + src_channels]._as_usize()); + let b1p = lut_lin.get_unchecked(src0[src_cn.b_i() + src_channels]._as_usize()); + + let r2p = lut_lin.get_unchecked(src1[src_cn.r_i()]._as_usize()); + let g2p = lut_lin.get_unchecked(src1[src_cn.g_i()]._as_usize()); + let b2p = lut_lin.get_unchecked(src1[src_cn.b_i()]._as_usize()); + + let r3p = lut_lin.get_unchecked(src1[src_cn.r_i() + src_channels]._as_usize()); + let g3p = lut_lin.get_unchecked(src1[src_cn.g_i() + src_channels]._as_usize()); + let b3p = lut_lin.get_unchecked(src1[src_cn.b_i() + src_channels]._as_usize()); + + r0 = vld1_dup_s16(r0p); + g0 = vld1_dup_s16(g0p); + b0 = vld1_dup_s16(b0p); + + r1 = vld1_dup_s16(r1p); + g1 = vld1_dup_s16(g1p); + b1 = vld1_dup_s16(b1p); + + r2 = vld1_dup_s16(r2p); + g2 = vld1_dup_s16(g2p); + b2 = vld1_dup_s16(b2p); + + r3 = vld1_dup_s16(r3p); + g3 = vld1_dup_s16(g3p); + b3 = vld1_dup_s16(b3p); + + dst0[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + + a0 = if src_channels == 4 { + src0[src_cn.a_i()] + } else { + max_colors + }; + + a1 = if src_channels == 4 { + src0[src_cn.a_i() + src_channels] + } else { + max_colors + }; + + a2 = if src_channels == 4 { + src1[src_cn.a_i()] + } else { + max_colors + }; + + a3 = if src_channels == 4 { + src1[src_cn.a_i() + src_channels] + } else { + max_colors + }; + } + + if let (Some(dst0), Some(dst1)) = ( + dst0.chunks_exact_mut(dst_channels * 2).last(), + dst1.chunks_exact_mut(dst_channels * 2).last(), + ) { + let v0_0 = vmlal_s16(rnd, r0, m0); + let v0_1 = vmlal_s16(rnd, r1, m0); + let v0_2 = vmlal_s16(rnd, r2, m0); + let v0_3 = vmlal_s16(rnd, r3, m0); + + let v1_0 = vmlal_s16(v0_0, g0, m1); + let v1_1 = vmlal_s16(v0_1, g1, m1); + let v1_2 = vmlal_s16(v0_2, g2, m1); + let v1_3 = vmlal_s16(v0_3, g3, m1); + + let vr0 = vmlal_s16(v1_0, b0, m2); + let vr1 = vmlal_s16(v1_1, b1, m2); + let vr2 = vmlal_s16(v1_2, b2, m2); + let vr3 = vmlal_s16(v1_3, b3, m2); + + let mut vr0 = vqshrun_n_s32::(vr0); + let mut vr1 = vqshrun_n_s32::(vr1); + let mut vr2 = vqshrun_n_s32::(vr2); + let mut vr3 = vqshrun_n_s32::(vr3); + + vr0 = vmin_u16(vr0, v_max_value); + vr1 = vmin_u16(vr1, v_max_value); + vr2 = vmin_u16(vr2, v_max_value); + vr3 = vmin_u16(vr3, v_max_value); + + dst0[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst0[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst0[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i()] = a0; + } + + dst0[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr1) as usize]; + dst0[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr1) as usize]; + dst0[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst0[dst_cn.a_i() + dst_channels] = a1; + } + + dst1[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr2) as usize]; + dst1[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr2) as usize]; + dst1[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr2) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i()] = a2; + } + + dst1[dst_cn.r_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<0>(vr3) as usize]; + dst1[dst_cn.g_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<1>(vr3) as usize]; + dst1[dst_cn.b_i() + dst_channels] = + self.profile.gamma[vget_lane_u16::<2>(vr3) as usize]; + if dst_channels == 4 { + dst1[dst_cn.a_i() + dst_channels] = a3; + } + } + } + + for (src, dst) in src_remainder + .chunks_exact(src_channels) + .zip(dst_remainder.chunks_exact_mut(dst_channels)) + { + let rp = lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + let r = vld1_dup_s16(rp); + let g = vld1_dup_s16(gp); + let b = vld1_dup_s16(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let v0 = vmlal_s16(rnd, r, m0); + let v1 = vmlal_s16(v0, g, m1); + let v = vmlal_s16(v1, b, m2); + + let mut vr0 = vqshrun_n_s32::(v); + vr0 = vmin_u16(vr0, v_max_value); + + dst[dst_cn.r_i()] = self.profile.gamma[vget_lane_u16::<0>(vr0) as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[vget_lane_u16::<1>(vr0) as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[vget_lane_u16::<2>(vr0) as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,341 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut3x3Factory; +use crate::conversions::neon::interpolator::*; +use crate::conversions::neon::interpolator_q0_15::NeonAlignedI16x4; +use crate::conversions::neon::rgb_xyz::NeonAlignedF32; +use crate::conversions::neon::t_lut3_to_3_q0_15::TransformLut3x3NeonQ0_15; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; +use std::marker::PhantomData; + +struct TransformLut3x3Neon< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut3x3Neon +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[inline(never)] + fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let value_scale = vdupq_n_f32(((1 << BIT_DEPTH) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_neon( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + let mut r = vfmaq_f32(vdupq_n_f32(0.5f32), v.v, value_scale); + r = vminq_f32(r, value_scale); + let jvx = vcvtaq_u32_f32(r); + + dst[dst_cn.r_i()] = vgetq_lane_u32::<0>(jvx).as_(); + dst[dst_cn.g_i()] = vgetq_lane_u32::<1>(jvx).as_(); + dst[dst_cn.b_i()] = vgetq_lane_u32::<2>(jvx).as_(); + } else { + dst[dst_cn.r_i()] = vgetq_lane_f32::<0>(v.v).as_(); + dst[dst_cn.g_i()] = vgetq_lane_f32::<1>(v.v).as_(); + dst[dst_cn.b_i()] = vgetq_lane_f32::<2>(v.v).as_(); + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3Neon< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearNeon:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk(src, dst, Box::new(TetrahedralNeon:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalNeon:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticNeon:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearNeon:: {})); + } + } + } + + Ok(()) + } +} + +pub(crate) struct NeonLut3x3Factory {} + +impl Lut3x3Factory for NeonLut3x3Factory { + fn make_transform_3x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point + && BIT_DEPTH < 16 + && std::arch::is_aarch64_feature_detected!("rdm") + { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + NeonAlignedI16x4([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3NeonQ0_15::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3NeonQ0_15::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }; + } + let lut = lut + .chunks_exact(3) + .map(|x| NeonAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3Neon::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3Neon::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/neon/t_lut3_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,242 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::neon::interpolator_q0_15::*; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +use std::arch::aarch64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut3x3NeonQ0_15< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> + TransformLut3x3NeonQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[inline(never)] + #[target_feature(enable = "rdm")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let f_value_scale = vdupq_n_f32(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + vdup_n_s16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + vdup_n_s16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_neon( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + let mut o = vmax_s16(v.v, vdup_n_s16(0)); + o = vmin_s16(o, v_max_scale); + dst[dst_cn.r_i()] = (vget_lane_s16::<0>(o) as u32).as_(); + dst[dst_cn.g_i()] = (vget_lane_s16::<1>(o) as u32).as_(); + dst[dst_cn.b_i()] = (vget_lane_s16::<2>(o) as u32).as_(); + } else { + let o = vcvtq_f32_s32(vmovl_s16(v.v)); + let r = vmulq_f32(o, f_value_scale); + dst[dst_cn.r_i()] = vgetq_lane_f32::<0>(r).as_(); + dst[dst_cn.g_i()] = vgetq_lane_f32::<1>(r).as_(); + dst[dst_cn.b_i()] = vgetq_lane_f32::<2>(r).as_(); + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3NeonQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearNeonQ0_15:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralNeonQ0_15:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk( + src, + dst, + Box::new(PyramidalNeonQ0_15:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk( + src, + dst, + Box::new(PrismaticNeonQ0_15:: {}), + ); + } + InterpolationMethod::Linear => { + self.transform_chunk( + src, + dst, + Box::new(TrilinearNeonQ0_15:: {}), + ); + } + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/prelude_lut_xyz_rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/prelude_lut_xyz_rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/prelude_lut_xyz_rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/prelude_lut_xyz_rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,328 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::lut3x4::create_lut3_samples; +use crate::err::try_vec; +use crate::mlaf::mlaf; +use crate::trc::ToneCurveEvaluator; +use crate::{ + CmsError, ColorProfile, GammaLutInterpolate, InPlaceStage, Matrix3f, PointeeSizeExpressible, + RenderingIntent, Rgb, TransformOptions, filmlike_clip, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) struct XyzToRgbStage { + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) matrices: Vec, + pub(crate) intent: RenderingIntent, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl> InPlaceStage for XyzToRgbStage { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + assert!(self.bit_depth > 0); + if !self.matrices.is_empty() { + let m = self.matrices[0]; + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + for m in self.matrices.iter().skip(1) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + let max_colors = (1 << self.bit_depth) - 1; + let color_scale = 1f32 / max_colors as f32; + let lut_cap = (self.gamma_lut - 1) as f32; + + if self.intent != RenderingIntent::AbsoluteColorimetric { + for dst in dst.chunks_exact_mut(3) { + let mut rgb = Rgb::new(dst[0], dst[1], dst[2]); + if rgb.is_out_of_gamut() { + rgb = filmlike_clip(rgb); + } + let r = mlaf(0.5f32, rgb.r, lut_cap).min(lut_cap).max(0f32) as u16; + let g = mlaf(0.5f32, rgb.g, lut_cap).min(lut_cap).max(0f32) as u16; + let b = mlaf(0.5f32, rgb.b, lut_cap).min(lut_cap).max(0f32) as u16; + + dst[0] = self.r_gamma[r as usize].as_() * color_scale; + dst[1] = self.g_gamma[g as usize].as_() * color_scale; + dst[2] = self.b_gamma[b as usize].as_() * color_scale; + } + } else { + for dst in dst.chunks_exact_mut(3) { + let rgb = Rgb::new(dst[0], dst[1], dst[2]); + let r = mlaf(0.5f32, rgb.r, lut_cap).min(lut_cap).max(0f32) as u16; + let g = mlaf(0.5f32, rgb.g, lut_cap).min(lut_cap).max(0f32) as u16; + let b = mlaf(0.5f32, rgb.b, lut_cap).min(lut_cap).max(0f32) as u16; + + dst[0] = self.r_gamma[r as usize].as_() * color_scale; + dst[1] = self.g_gamma[g as usize].as_() * color_scale; + dst[2] = self.b_gamma[b as usize].as_() * color_scale; + } + } + + Ok(()) + } +} + +pub(crate) struct XyzToRgbStageExtended { + pub(crate) gamma_evaluator: Box, + pub(crate) matrices: Vec, + pub(crate) phantom_data: PhantomData, +} + +impl> InPlaceStage for XyzToRgbStageExtended { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + if !self.matrices.is_empty() { + let m = self.matrices[0]; + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + for m in self.matrices.iter().skip(1) { + for dst in dst.chunks_exact_mut(3) { + let x = dst[0]; + let y = dst[1]; + let z = dst[2]; + dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]); + dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]); + dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]); + } + } + + for dst in dst.chunks_exact_mut(3) { + let mut rgb = Rgb::new(dst[0], dst[1], dst[2]); + rgb = self.gamma_evaluator.evaluate_tristimulus(rgb); + dst[0] = rgb.r.as_(); + dst[1] = rgb.g.as_(); + dst[2] = rgb.b.as_(); + } + + Ok(()) + } +} + +struct RgbLinearizationStage { + r_lin: Box<[f32; LINEAR_CAP]>, + g_lin: Box<[f32; LINEAR_CAP]>, + b_lin: Box<[f32; LINEAR_CAP]>, + _phantom: PhantomData, + bit_depth: usize, +} + +impl< + T: Clone + AsPrimitive + PointeeSizeExpressible, + const LINEAR_CAP: usize, + const SAMPLES: usize, +> RgbLinearizationStage +{ + fn transform(&self, src: &[T], dst: &mut [f32]) -> Result<(), CmsError> { + if src.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % 3 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let scale = if T::FINITE { + ((1 << self.bit_depth) - 1) as f32 / (SAMPLES as f32 - 1f32) + } else { + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 / (SAMPLES as f32 - 1f32) + }; + + let capped_value = if T::FINITE { + (1 << self.bit_depth) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + + for (src, dst) in src.chunks_exact(3).zip(dst.chunks_exact_mut(3)) { + let j_r = src[0].as_() as f32 * scale; + let j_g = src[1].as_() as f32 * scale; + let j_b = src[2].as_() as f32 * scale; + dst[0] = self.r_lin[(j_r.round().max(0.0).min(capped_value as f32) as u16) as usize]; + dst[1] = self.g_lin[(j_g.round().max(0.0).min(capped_value as f32) as u16) as usize]; + dst[2] = self.b_lin[(j_b.round().max(0.0).min(capped_value as f32) as u16) as usize]; + } + Ok(()) + } +} + +pub(crate) fn create_rgb_lin_lut< + T: Copy + Default + AsPrimitive + Send + Sync + AsPrimitive + PointeeSizeExpressible, + const BIT_DEPTH: usize, + const LINEAR_CAP: usize, + const GRID_SIZE: usize, +>( + source: &ColorProfile, + opts: TransformOptions, +) -> Result, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + let lut_origins = create_lut3_samples::(); + + let lin_r = + source.build_r_linearize_table::(opts.allow_use_cicp_transfer)?; + let lin_g = + source.build_g_linearize_table::(opts.allow_use_cicp_transfer)?; + let lin_b = + source.build_b_linearize_table::(opts.allow_use_cicp_transfer)?; + + let lin_stage = RgbLinearizationStage:: { + r_lin: lin_r, + g_lin: lin_g, + b_lin: lin_b, + _phantom: PhantomData, + bit_depth: BIT_DEPTH, + }; + + let mut lut = try_vec![0f32; lut_origins.len()]; + lin_stage.transform(&lut_origins, &mut lut)?; + + let xyz_to_rgb = source.rgb_to_xyz_matrix(); + + let matrices = vec![ + xyz_to_rgb.to_f32(), + Matrix3f { + v: [ + [32768.0 / 65535.0, 0.0, 0.0], + [0.0, 32768.0 / 65535.0, 0.0], + [0.0, 0.0, 32768.0 / 65535.0], + ], + }, + ]; + + let matrix_stage = crate::conversions::lut_transforms::MatrixStage { matrices }; + matrix_stage.transform(&mut lut)?; + Ok(lut) +} + +pub(crate) fn prepare_inverse_lut_rgb_xyz< + T: Copy + + Default + + AsPrimitive + + Send + + Sync + + AsPrimitive + + PointeeSizeExpressible + + GammaLutInterpolate, + const BIT_DEPTH: usize, + const GAMMA_LUT: usize, +>( + dest: &ColorProfile, + lut: &mut [f32], + options: TransformOptions, +) -> Result<(), CmsError> +where + f32: AsPrimitive, + u32: AsPrimitive, +{ + if !T::FINITE { + if let Some(extended_gamma) = dest.try_extended_gamma_evaluator() { + let xyz_to_rgb = dest.rgb_to_xyz_matrix().inverse(); + + let mut matrices = vec![Matrix3f { + v: [ + [65535.0 / 32768.0, 0.0, 0.0], + [0.0, 65535.0 / 32768.0, 0.0], + [0.0, 0.0, 65535.0 / 32768.0], + ], + }]; + + matrices.push(xyz_to_rgb.to_f32()); + let xyz_to_rgb_stage = XyzToRgbStageExtended:: { + gamma_evaluator: extended_gamma, + matrices, + phantom_data: PhantomData, + }; + xyz_to_rgb_stage.transform(lut)?; + return Ok(()); + } + } + let gamma_map_r = dest.build_gamma_table::( + &dest.red_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_map_g = dest.build_gamma_table::( + &dest.green_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_map_b = dest.build_gamma_table::( + &dest.blue_trc, + options.allow_use_cicp_transfer, + )?; + + let xyz_to_rgb = dest.rgb_to_xyz_matrix().inverse(); + + let mut matrices = vec![Matrix3f { + v: [ + [65535.0 / 32768.0, 0.0, 0.0], + [0.0, 65535.0 / 32768.0, 0.0], + [0.0, 0.0, 65535.0 / 32768.0], + ], + }]; + + matrices.push(xyz_to_rgb.to_f32()); + let xyz_to_rgb_stage = XyzToRgbStage:: { + r_gamma: gamma_map_r, + g_gamma: gamma_map_g, + b_gamma: gamma_map_b, + matrices, + intent: options.rendering_intent, + gamma_lut: GAMMA_LUT, + bit_depth: BIT_DEPTH, + }; + xyz_to_rgb_stage.transform(lut)?; + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,189 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::mlaf; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor, Vector3f}; +use num_traits::AsPrimitive; + +#[derive(Clone)] +pub(crate) struct ToneReproductionRgbToGray { + pub(crate) r_linear: Box<[f32; BUCKET]>, + pub(crate) g_linear: Box<[f32; BUCKET]>, + pub(crate) b_linear: Box<[f32; BUCKET]>, + pub(crate) gray_gamma: Box<[T; 65536]>, +} + +#[derive(Clone)] +struct TransformRgbToGrayExecutor< + T, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const BUCKET: usize, +> { + trc_box: ToneReproductionRgbToGray, + weights: Vector3f, + bit_depth: usize, + gamma_lut: usize, +} + +pub(crate) fn make_rgb_to_gray< + T: Copy + Default + PointeeSizeExpressible + Send + Sync + 'static, + const BUCKET: usize, +>( + src_layout: Layout, + dst_layout: Layout, + trc: ToneReproductionRgbToGray, + weights: Vector3f, + gamma_lut: usize, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, +{ + match src_layout { + Layout::Rgb => match dst_layout { + Layout::Rgb => Err(CmsError::UnsupportedProfileConnection), + Layout::Rgba => Err(CmsError::UnsupportedProfileConnection), + Layout::Gray => Ok(Box::new(TransformRgbToGrayExecutor::< + T, + { Layout::Rgb as u8 }, + { Layout::Gray as u8 }, + BUCKET, + > { + trc_box: trc, + weights, + bit_depth, + gamma_lut, + })), + Layout::GrayAlpha => Ok(Box::new(TransformRgbToGrayExecutor::< + T, + { Layout::Rgb as u8 }, + { Layout::GrayAlpha as u8 }, + BUCKET, + > { + trc_box: trc, + weights, + bit_depth, + gamma_lut, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::Rgba => match dst_layout { + Layout::Rgb => Err(CmsError::UnsupportedProfileConnection), + Layout::Rgba => Err(CmsError::UnsupportedProfileConnection), + Layout::Gray => Ok(Box::new(TransformRgbToGrayExecutor::< + T, + { Layout::Rgba as u8 }, + { Layout::Gray as u8 }, + BUCKET, + > { + trc_box: trc, + weights, + bit_depth, + gamma_lut, + })), + Layout::GrayAlpha => Ok(Box::new(TransformRgbToGrayExecutor::< + T, + { Layout::Rgba as u8 }, + { Layout::GrayAlpha as u8 }, + BUCKET, + > { + trc_box: trc, + weights, + bit_depth, + gamma_lut, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::Gray => Err(CmsError::UnsupportedProfileConnection), + Layout::GrayAlpha => Err(CmsError::UnsupportedProfileConnection), + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const BUCKET: usize, +> TransformExecutor for TransformRgbToGrayExecutor +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let scale_value = (self.gamma_lut - 1) as f32; + let max_value = ((1u32 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.trc_box.r_linear[src[src_cn.r_i()]._as_usize()]; + let g = self.trc_box.g_linear[src[src_cn.g_i()]._as_usize()]; + let b = self.trc_box.b_linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + let grey = mlaf( + 0.5, + mlaf( + mlaf(self.weights.v[0] * r, self.weights.v[1], g), + self.weights.v[2], + b, + ) + .min(1.) + .max(0.), + scale_value, + ); + dst[0] = self.trc_box.gray_gamma[(grey as u16) as usize]; + if dst_channels == 2 { + dst[1] = a; + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray_extended.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray_extended.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray_extended.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb2gray_extended.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::mlaf; +use crate::transform::PointeeSizeExpressible; +use crate::trc::ToneCurveEvaluator; +use crate::{CmsError, Layout, Rgb, TransformExecutor, Vector3f}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +struct TransformRgbToGrayExtendedExecutor { + linear_eval: Box, + gamma_eval: Box, + weights: Vector3f, + _phantom: PhantomData, + bit_depth: usize, +} + +pub(crate) fn make_rgb_to_gray_extended< + T: Copy + Default + PointeeSizeExpressible + Send + Sync + 'static + AsPrimitive, +>( + src_layout: Layout, + dst_layout: Layout, + linear_eval: Box, + gamma_eval: Box, + weights: Vector3f, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + match src_layout { + Layout::Rgb => match dst_layout { + Layout::Rgb => Err(CmsError::UnsupportedProfileConnection), + Layout::Rgba => Err(CmsError::UnsupportedProfileConnection), + Layout::Gray => Ok(Box::new(TransformRgbToGrayExtendedExecutor::< + T, + { Layout::Rgb as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + weights, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformRgbToGrayExtendedExecutor::< + T, + { Layout::Rgb as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + weights, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::Rgba => match dst_layout { + Layout::Rgb => Err(CmsError::UnsupportedProfileConnection), + Layout::Rgba => Err(CmsError::UnsupportedProfileConnection), + Layout::Gray => Ok(Box::new(TransformRgbToGrayExtendedExecutor::< + T, + { Layout::Rgba as u8 }, + { Layout::Gray as u8 }, + > { + linear_eval, + gamma_eval, + weights, + _phantom: PhantomData, + bit_depth, + })), + Layout::GrayAlpha => Ok(Box::new(TransformRgbToGrayExtendedExecutor::< + T, + { Layout::Rgba as u8 }, + { Layout::GrayAlpha as u8 }, + > { + linear_eval, + gamma_eval, + weights, + _phantom: PhantomData, + bit_depth, + })), + _ => Err(CmsError::UnsupportedProfileConnection), + }, + Layout::Gray => Err(CmsError::UnsupportedProfileConnection), + Layout::GrayAlpha => Err(CmsError::UnsupportedProfileConnection), + _ => Err(CmsError::UnsupportedProfileConnection), + } +} + +impl< + T: Copy + Default + PointeeSizeExpressible + 'static + AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformRgbToGrayExtendedExecutor +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let max_value = ((1u32 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let in_tristimulus = Rgb::::new( + src[src_cn.r_i()].as_(), + src[src_cn.g_i()].as_(), + src[src_cn.b_i()].as_(), + ); + let lin_tristimulus = self.linear_eval.evaluate_tristimulus(in_tristimulus); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + let grey = mlaf( + mlaf( + self.weights.v[0] * lin_tristimulus.r, + self.weights.v[1], + lin_tristimulus.g, + ), + self.weights.v[2], + lin_tristimulus.b, + ) + .min(1.) + .max(0.); + let gamma_value = self.gamma_eval.evaluate_value(grey); + dst[0] = gamma_value.as_(); + if dst_channels == 2 { + dst[1] = a; + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb_xyz_factory.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb_xyz_factory.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgb_xyz_factory.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgb_xyz_factory.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,395 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::TransformMatrixShaper; +use crate::conversions::rgbxyz::{ + TransformMatrixShaperOptimized, make_rgb_xyz_rgb_transform, make_rgb_xyz_rgb_transform_opt, +}; +use crate::conversions::rgbxyz_fixed::{make_rgb_xyz_q2_13, make_rgb_xyz_q2_13_opt}; +use crate::{CmsError, Layout, TransformExecutor, TransformOptions}; +use num_traits::AsPrimitive; + +const FIXED_POINT_SCALE: i32 = 13; // Q2.13; + +pub(crate) trait RgbXyzFactory + Default> { + fn make_transform( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError>; +} + +pub(crate) trait RgbXyzFactoryOpt + Default> { + fn make_optimized_transform< + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError>; +} + +impl RgbXyzFactory for u16 { + fn make_transform( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if BIT_DEPTH < 16 && transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + return make_rgb_xyz_q2_13::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + make_rgb_xyz_rgb_transform::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactory for f32 { + fn make_transform( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + return make_rgb_xyz_q2_13::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + make_rgb_xyz_rgb_transform::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactory for f64 { + fn make_transform( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + _: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + make_rgb_xyz_rgb_transform::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactory for u8 { + fn make_transform( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ); + } + } + make_rgb_xyz_q2_13::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ) + } else { + make_rgb_xyz_rgb_transform::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ) + } + } +} + +// Optimized factories + +impl RgbXyzFactoryOpt for u16 { + fn make_optimized_transform< + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if BIT_DEPTH >= 12 && transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + if std::arch::is_aarch64_feature_detected!("rdm") { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt; + return make_rgb_xyz_q1_30_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + } + if BIT_DEPTH < 16 && transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2_opt::< + u16, + LINEAR_CAP, + FIXED_POINT_SCALE, + >( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH + ); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41_opt::< + u16, + LINEAR_CAP, + FIXED_POINT_SCALE, + >( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH + ); + } + } + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + return make_rgb_xyz_q2_13_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + make_rgb_xyz_rgb_transform_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactoryOpt for f32 { + fn make_optimized_transform< + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2_opt::< + f32, + LINEAR_CAP, + FIXED_POINT_SCALE, + >( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH + ); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41_opt::< + f32, + LINEAR_CAP, + FIXED_POINT_SCALE, + >( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH + ); + } + } + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + return if std::arch::is_aarch64_feature_detected!("rdm") { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt; + make_rgb_xyz_q1_30_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } else { + make_rgb_xyz_q2_13_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + }; + } + } + make_rgb_xyz_rgb_transform_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactoryOpt for f64 { + fn make_optimized_transform< + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + { + if std::arch::is_aarch64_feature_detected!("rdm") { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt; + return make_rgb_xyz_q1_30_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ); + } + } + } + make_rgb_xyz_rgb_transform_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, BIT_DEPTH, + ) + } +} + +impl RgbXyzFactoryOpt for u8 { + fn make_optimized_transform< + const LINEAR_CAP: usize, + const GAMMA_LUT: usize, + const BIT_DEPTH: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + transform_options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> { + if transform_options.prefer_fixed_point { + #[cfg(all(target_arch = "x86_64", feature = "avx512"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx512_opt; + if std::arch::is_x86_feature_detected!("avx512bw") + && std::arch::is_x86_feature_detected!("avx512vl") + { + return make_rgb_xyz_q2_13_transform_avx512_opt::< + u8, + LINEAR_CAP, + FIXED_POINT_SCALE, + >(src_layout, dst_layout, profile, GAMMA_LUT, 8); + } + } + #[cfg(all(target_arch = "x86_64", feature = "avx"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt; + if std::arch::is_x86_feature_detected!("avx2") { + return make_rgb_xyz_q2_13_transform_avx2_opt::< + u8, + LINEAR_CAP, + FIXED_POINT_SCALE, + >(src_layout, dst_layout, profile, GAMMA_LUT, 8); + } + } + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] + { + use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt; + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_q2_13_transform_sse_41_opt::< + u8, + LINEAR_CAP, + FIXED_POINT_SCALE, + >(src_layout, dst_layout, profile, GAMMA_LUT, 8); + } + } + make_rgb_xyz_q2_13_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ) + } else { + make_rgb_xyz_rgb_transform_opt::( + src_layout, dst_layout, profile, GAMMA_LUT, 8, + ) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,899 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::{CmsError, Layout, Matrix3, Matrix3f, TransformExecutor}; +use num_traits::AsPrimitive; + +pub(crate) struct TransformMatrixShaper { + pub(crate) r_linear: Box<[f32; BUCKET]>, + pub(crate) g_linear: Box<[f32; BUCKET]>, + pub(crate) b_linear: Box<[f32; BUCKET]>, + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3f, +} + +impl TransformMatrixShaper { + #[inline(never)] + #[allow(dead_code)] + fn convert_to_v(self) -> TransformMatrixShaperV { + TransformMatrixShaperV { + r_linear: self.r_linear.iter().copied().collect(), + g_linear: self.g_linear.iter().copied().collect(), + b_linear: self.b_linear.iter().copied().collect(), + r_gamma: self.r_gamma, + g_gamma: self.g_gamma, + b_gamma: self.b_gamma, + adaptation_matrix: self.adaptation_matrix, + } + } +} + +#[allow(dead_code)] +pub(crate) struct TransformMatrixShaperV { + pub(crate) r_linear: Vec, + pub(crate) g_linear: Vec, + pub(crate) b_linear: Vec, + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3f, +} + +/// Low memory footprint optimized routine for matrix shaper profiles with the same +/// Gamma and linear curves. +pub(crate) struct TransformMatrixShaperOptimized { + pub(crate) linear: Box<[f32; BUCKET]>, + pub(crate) gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3f, +} + +#[allow(dead_code)] +impl TransformMatrixShaperOptimized { + fn convert_to_v(self) -> TransformMatrixShaperOptimizedV { + TransformMatrixShaperOptimizedV { + linear: self.linear.iter().copied().collect::>(), + gamma: self.gamma, + adaptation_matrix: self.adaptation_matrix, + } + } +} + +/// Low memory footprint optimized routine for matrix shaper profiles with the same +/// Gamma and linear curves. +#[allow(dead_code)] +pub(crate) struct TransformMatrixShaperOptimizedV { + pub(crate) linear: Vec, + pub(crate) gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3f, +} + +impl TransformMatrixShaper { + #[inline(never)] + #[allow(dead_code)] + pub(crate) fn to_q2_13_n< + R: Copy + 'static + Default, + const PRECISION: i32, + const LINEAR_CAP: usize, + >( + &self, + gamma_lut: usize, + bit_depth: usize, + ) -> TransformMatrixShaperFixedPoint + where + f32: AsPrimitive, + { + let linear_scale = if T::FINITE { + let lut_scale = (gamma_lut - 1) as f32 / ((1 << bit_depth) - 1) as f32; + ((1 << bit_depth) - 1) as f32 * lut_scale + } else { + let lut_scale = (gamma_lut - 1) as f32 / (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32; + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 * lut_scale + }; + let mut new_box_r = Box::new([R::default(); BUCKET]); + let mut new_box_g = Box::new([R::default(); BUCKET]); + let mut new_box_b = Box::new([R::default(); BUCKET]); + for (dst, &src) in new_box_r.iter_mut().zip(self.r_linear.iter()) { + *dst = (src * linear_scale).round().as_(); + } + for (dst, &src) in new_box_g.iter_mut().zip(self.g_linear.iter()) { + *dst = (src * linear_scale).round().as_(); + } + for (dst, &src) in new_box_b.iter_mut().zip(self.b_linear.iter()) { + *dst = (src * linear_scale).round().as_(); + } + let scale: f32 = (1i32 << PRECISION) as f32; + let source_matrix = self.adaptation_matrix; + let mut dst_matrix = Matrix3:: { v: [[0i16; 3]; 3] }; + for i in 0..3 { + for j in 0..3 { + dst_matrix.v[i][j] = (source_matrix.v[i][j] * scale) as i16; + } + } + TransformMatrixShaperFixedPoint { + r_linear: new_box_r, + g_linear: new_box_g, + b_linear: new_box_b, + r_gamma: self.r_gamma.clone(), + g_gamma: self.g_gamma.clone(), + b_gamma: self.b_gamma.clone(), + adaptation_matrix: dst_matrix, + } + } + + #[inline(never)] + #[allow(dead_code)] + pub(crate) fn to_q2_13_i( + &self, + gamma_lut: usize, + bit_depth: usize, + ) -> TransformMatrixShaperFp + where + f32: AsPrimitive, + { + let linear_scale = if T::FINITE { + let lut_scale = (gamma_lut - 1) as f32 / ((1 << bit_depth) - 1) as f32; + ((1 << bit_depth) - 1) as f32 * lut_scale + } else { + let lut_scale = (gamma_lut - 1) as f32 / (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32; + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 * lut_scale + }; + let new_box_r = self + .r_linear + .iter() + .map(|&x| (x * linear_scale).round().as_()) + .collect::>(); + let new_box_g = self + .g_linear + .iter() + .map(|&x| (x * linear_scale).round().as_()) + .collect::>(); + let new_box_b = self + .b_linear + .iter() + .map(|&x| (x * linear_scale).round().as_()) + .collect::>(); + let scale: f32 = (1i32 << PRECISION) as f32; + let source_matrix = self.adaptation_matrix; + let mut dst_matrix = Matrix3:: { v: [[0i16; 3]; 3] }; + for i in 0..3 { + for j in 0..3 { + dst_matrix.v[i][j] = (source_matrix.v[i][j] * scale) as i16; + } + } + TransformMatrixShaperFp { + r_linear: new_box_r, + g_linear: new_box_g, + b_linear: new_box_b, + r_gamma: self.r_gamma.clone(), + g_gamma: self.g_gamma.clone(), + b_gamma: self.b_gamma.clone(), + adaptation_matrix: dst_matrix, + } + } +} + +impl + TransformMatrixShaperOptimized +{ + #[allow(dead_code)] + pub(crate) fn to_q2_13_n< + R: Copy + 'static + Default, + const PRECISION: i32, + const LINEAR_CAP: usize, + >( + &self, + gamma_lut: usize, + bit_depth: usize, + ) -> TransformMatrixShaperFixedPointOpt + where + f32: AsPrimitive, + { + let linear_scale = if T::FINITE { + let lut_scale = (gamma_lut - 1) as f32 / ((1 << bit_depth) - 1) as f32; + ((1 << bit_depth) - 1) as f32 * lut_scale + } else { + let lut_scale = (gamma_lut - 1) as f32 / (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32; + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 * lut_scale + }; + let mut new_box_linear = Box::new([R::default(); BUCKET]); + for (dst, src) in new_box_linear.iter_mut().zip(self.linear.iter()) { + *dst = (*src * linear_scale).round().as_(); + } + let scale: f32 = (1i32 << PRECISION) as f32; + let source_matrix = self.adaptation_matrix; + let mut dst_matrix = Matrix3:: { + v: [[i16::default(); 3]; 3], + }; + for i in 0..3 { + for j in 0..3 { + dst_matrix.v[i][j] = (source_matrix.v[i][j] * scale) as i16; + } + } + TransformMatrixShaperFixedPointOpt { + linear: new_box_linear, + gamma: self.gamma.clone(), + adaptation_matrix: dst_matrix, + } + } + + #[allow(dead_code)] + pub(crate) fn to_q2_13_i( + &self, + gamma_lut: usize, + bit_depth: usize, + ) -> TransformMatrixShaperFpOptVec + where + f32: AsPrimitive, + { + let linear_scale = if T::FINITE { + let lut_scale = (gamma_lut - 1) as f32 / ((1 << bit_depth) - 1) as f32; + ((1 << bit_depth) - 1) as f32 * lut_scale + } else { + let lut_scale = (gamma_lut - 1) as f32 / (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32; + (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1) as f32 * lut_scale + }; + let new_box_linear = self + .linear + .iter() + .map(|&x| (x * linear_scale).round().as_()) + .collect::>(); + let scale: f32 = (1i32 << PRECISION) as f32; + let source_matrix = self.adaptation_matrix; + let mut dst_matrix = Matrix3:: { + v: [[i16::default(); 3]; 3], + }; + for i in 0..3 { + for j in 0..3 { + dst_matrix.v[i][j] = (source_matrix.v[i][j] * scale) as i16; + } + } + TransformMatrixShaperFpOptVec { + linear: new_box_linear, + gamma: self.gamma.clone(), + adaptation_matrix: dst_matrix, + } + } + + #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] + pub(crate) fn to_q1_30_n( + &self, + gamma_lut: usize, + bit_depth: usize, + ) -> TransformMatrixShaperFpOptVec + where + f32: AsPrimitive, + f64: AsPrimitive, + { + // It is important to scale 1 bit more to compensate vqrdmlah Q0.31, because we're going to use Q1.30 + let table_size = if T::FINITE { + (1 << bit_depth) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let ext_bp = if T::FINITE { + bit_depth as u32 + 1 + } else { + let bp = (T::NOT_FINITE_LINEAR_TABLE_SIZE - 1).count_ones(); + bp + 1 + }; + let linear_scale = { + let lut_scale = (gamma_lut - 1) as f64 / table_size as f64; + ((1u32 << ext_bp) - 1) as f64 * lut_scale + }; + let new_box_linear = self + .linear + .iter() + .map(|&v| (v as f64 * linear_scale).round().as_()) + .collect::>(); + let scale: f64 = (1i64 << PRECISION) as f64; + let source_matrix = self.adaptation_matrix; + let mut dst_matrix = Matrix3:: { + v: [[i32::default(); 3]; 3], + }; + for i in 0..3 { + for j in 0..3 { + dst_matrix.v[i][j] = (source_matrix.v[i][j] as f64 * scale) as i32; + } + } + TransformMatrixShaperFpOptVec { + linear: new_box_linear, + gamma: self.gamma.clone(), + adaptation_matrix: dst_matrix, + } + } +} + +#[allow(unused)] +struct TransformMatrixShaperScalar< + T: Clone, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> { + pub(crate) profile: TransformMatrixShaper, + pub(crate) gamma_lut: usize, + pub(crate) bit_depth: usize, +} + +#[allow(unused)] +struct TransformMatrixShaperOptScalar< + T: Clone, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> { + pub(crate) profile: TransformMatrixShaperOptimized, + pub(crate) gamma_lut: usize, + pub(crate) bit_depth: usize, +} + +#[cfg(any( + any(target_arch = "x86", target_arch = "x86_64"), + all(target_arch = "aarch64", target_feature = "neon") +))] +#[allow(unused)] +macro_rules! create_rgb_xyz_dependant_executor { + ($dep_name: ident, $dependant: ident, $shaper: ident) => { + pub(crate) fn $dep_name< + T: Clone + Send + Sync + Default + PointeeSizeExpressible + Copy + 'static, + const LINEAR_CAP: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: $shaper, + gamma_lut: usize, + bit_depth: usize, + ) -> Result + Send + Sync>, CmsError> + where + u32: AsPrimitive, + { + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + gamma_lut, + })); + } + Err(CmsError::UnsupportedProfileConnection) + } + }; +} + +#[cfg(any( + any(target_arch = "x86", target_arch = "x86_64"), + all(target_arch = "aarch64", target_feature = "neon") +))] +#[allow(unused)] +macro_rules! create_rgb_xyz_dependant_executor_to_v { + ($dep_name: ident, $dependant: ident, $shaper: ident) => { + pub(crate) fn $dep_name< + T: Clone + Send + Sync + Default + PointeeSizeExpressible + Copy + 'static, + const LINEAR_CAP: usize, + >( + src_layout: Layout, + dst_layout: Layout, + profile: $shaper, + gamma_lut: usize, + bit_depth: usize, + ) -> Result + Send + Sync>, CmsError> + where + u32: AsPrimitive, + { + let profile = profile.convert_to_v(); + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + > { + profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + > { + profile, + bit_depth, + gamma_lut, + })); + } + Err(CmsError::UnsupportedProfileConnection) + } + }; +} + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +use crate::conversions::sse::{TransformShaperRgbOptSse, TransformShaperRgbSse}; + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +use crate::conversions::avx::{TransformShaperRgbAvx, TransformShaperRgbOptAvx}; + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +create_rgb_xyz_dependant_executor!( + make_rgb_xyz_rgb_transform_sse_41, + TransformShaperRgbSse, + TransformMatrixShaper +); + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +create_rgb_xyz_dependant_executor_to_v!( + make_rgb_xyz_rgb_transform_sse_41_opt, + TransformShaperRgbOptSse, + TransformMatrixShaperOptimized +); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +create_rgb_xyz_dependant_executor!( + make_rgb_xyz_rgb_transform_avx2, + TransformShaperRgbAvx, + TransformMatrixShaper +); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +create_rgb_xyz_dependant_executor_to_v!( + make_rgb_xyz_rgb_transform_avx2_opt, + TransformShaperRgbOptAvx, + TransformMatrixShaperOptimized +); + +#[cfg(all(target_arch = "x86_64", feature = "avx512"))] +use crate::conversions::avx512::TransformShaperRgbOptAvx512; + +#[cfg(all(target_arch = "x86_64", feature = "avx512"))] +create_rgb_xyz_dependant_executor!( + make_rgb_xyz_rgb_transform_avx512_opt, + TransformShaperRgbOptAvx512, + TransformMatrixShaperOptimized +); + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +pub(crate) fn make_rgb_xyz_rgb_transform< + T: Clone + Send + Sync + PointeeSizeExpressible + 'static + Copy + Default, + const LINEAR_CAP: usize, +>( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaper, + gamma_lut: usize, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, +{ + #[cfg(all(feature = "avx", target_arch = "x86_64"))] + if std::arch::is_x86_feature_detected!("avx2") && std::arch::is_x86_feature_detected!("fma") { + return make_rgb_xyz_rgb_transform_avx2::( + src_layout, dst_layout, profile, gamma_lut, bit_depth, + ); + } + #[cfg(all(feature = "sse", any(target_arch = "x86", target_arch = "x86_64")))] + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_rgb_transform_sse_41::( + src_layout, dst_layout, profile, gamma_lut, bit_depth, + ); + } + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformMatrixShaperScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformMatrixShaperScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformMatrixShaperScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformMatrixShaperScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } + Err(CmsError::UnsupportedProfileConnection) +} + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +pub(crate) fn make_rgb_xyz_rgb_transform_opt< + T: Clone + Send + Sync + PointeeSizeExpressible + 'static + Copy + Default, + const LINEAR_CAP: usize, +>( + src_layout: Layout, + dst_layout: Layout, + profile: TransformMatrixShaperOptimized, + gamma_lut: usize, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, +{ + #[cfg(all(feature = "avx512", target_arch = "x86_64"))] + if std::arch::is_x86_feature_detected!("avx512bw") + && std::arch::is_x86_feature_detected!("avx512vl") + && std::arch::is_x86_feature_detected!("fma") + { + return make_rgb_xyz_rgb_transform_avx512_opt::( + src_layout, dst_layout, profile, gamma_lut, bit_depth, + ); + } + #[cfg(all(feature = "avx", target_arch = "x86_64"))] + if std::arch::is_x86_feature_detected!("avx2") && std::arch::is_x86_feature_detected!("fma") { + return make_rgb_xyz_rgb_transform_avx2_opt::( + src_layout, dst_layout, profile, gamma_lut, bit_depth, + ); + } + #[cfg(all(feature = "sse", any(target_arch = "x86", target_arch = "x86_64")))] + if std::arch::is_x86_feature_detected!("sse4.1") { + return make_rgb_xyz_rgb_transform_sse_41_opt::( + src_layout, dst_layout, profile, gamma_lut, bit_depth, + ); + } + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformMatrixShaperOptScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformMatrixShaperOptScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformMatrixShaperOptScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformMatrixShaperOptScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + gamma_lut, + bit_depth, + })); + } + Err(CmsError::UnsupportedProfileConnection) +} + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +use crate::conversions::neon::{TransformShaperRgbNeon, TransformShaperRgbOptNeon}; +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFpOptVec; +use crate::conversions::rgbxyz_fixed::{ + TransformMatrixShaperFixedPoint, TransformMatrixShaperFixedPointOpt, TransformMatrixShaperFp, +}; +use crate::transform::PointeeSizeExpressible; + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +create_rgb_xyz_dependant_executor_to_v!( + make_rgb_xyz_rgb_transform, + TransformShaperRgbNeon, + TransformMatrixShaper +); + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +create_rgb_xyz_dependant_executor_to_v!( + make_rgb_xyz_rgb_transform_opt, + TransformShaperRgbOptNeon, + TransformMatrixShaperOptimized +); + +#[allow(unused)] +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformMatrixShaperScalar +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + use crate::mlaf::mlaf; + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.profile.r_linear[src[src_cn.r_i()]._as_usize()]; + let g = self.profile.g_linear[src[src_cn.g_i()]._as_usize()]; + let b = self.profile.b_linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[0][0], g, transform.v[0][1]), + b, + transform.v[0][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + let new_g = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[1][0], g, transform.v[1][1]), + b, + transform.v[1][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + let new_b = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[2][0], g, transform.v[2][1]), + b, + transform.v[2][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + dst[dst_cn.r_i()] = self.profile.r_gamma[(new_r as u16) as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[(new_g as u16) as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[(new_b as u16) as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + + Ok(()) + } +} + +#[allow(unused)] +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformMatrixShaperOptScalar +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + use crate::mlaf::mlaf; + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.profile.linear[src[src_cn.r_i()]._as_usize()]; + let g = self.profile.linear[src[src_cn.g_i()]._as_usize()]; + let b = self.profile.linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[0][0], g, transform.v[0][1]), + b, + transform.v[0][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + let new_g = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[1][0], g, transform.v[1][1]), + b, + transform.v[1][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + let new_b = mlaf( + 0.5f32, + mlaf( + mlaf(r * transform.v[2][0], g, transform.v[2][1]), + b, + transform.v[2][2], + ) + .max(0f32) + .min(1f32), + scale, + ); + + dst[dst_cn.r_i()] = self.profile.gamma[(new_r as u16) as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[(new_g as u16) as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[(new_b as u16) as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_fixed.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_fixed.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_fixed.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_fixed.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,560 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Layout; +use crate::conversions::TransformMatrixShaper; +use crate::matrix::Matrix3; +use crate::{CmsError, TransformExecutor}; +use num_traits::AsPrimitive; + +/// Fixed point conversion Q2.13 +pub(crate) struct TransformMatrixShaperFixedPoint { + pub(crate) r_linear: Box<[R; LINEAR_CAP]>, + pub(crate) g_linear: Box<[R; LINEAR_CAP]>, + pub(crate) b_linear: Box<[R; LINEAR_CAP]>, + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3, +} + +/// Fixed point conversion Q2.13 +#[allow(dead_code)] +pub(crate) struct TransformMatrixShaperFp { + pub(crate) r_linear: Vec, + pub(crate) g_linear: Vec, + pub(crate) b_linear: Vec, + pub(crate) r_gamma: Box<[T; 65536]>, + pub(crate) g_gamma: Box<[T; 65536]>, + pub(crate) b_gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3, +} + +/// Fixed point conversion Q2.13 +/// +/// Optimized routine for *all same curves* matrix shaper. +pub(crate) struct TransformMatrixShaperFixedPointOpt { + pub(crate) linear: Box<[R; LINEAR_CAP]>, + pub(crate) gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3, +} + +/// Fixed point conversion Q2.13 +/// +/// Optimized routine for *all same curves* matrix shaper. +#[allow(dead_code)] +pub(crate) struct TransformMatrixShaperFpOptVec { + pub(crate) linear: Vec, + pub(crate) gamma: Box<[T; 65536]>, + pub(crate) adaptation_matrix: Matrix3, +} + +#[allow(unused)] +struct TransformMatrixShaperQ2_13< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFixedPoint, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +#[allow(unused)] +struct TransformMatrixShaperQ2_13Optimized< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFixedPointOpt, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +#[allow(unused)] +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> TransformExecutor + for TransformMatrixShaperQ2_13 +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let max_colors: T = ((1 << self.bit_depth as u32) - 1u32).as_(); + let rnd: i32 = (1i32 << (PRECISION - 1)); + + let v_gamma_max = self.gamma_lut as i32 - 1; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.profile.r_linear[src[src_cn.r_i()]._as_usize()]; + let g = self.profile.g_linear[src[src_cn.g_i()]._as_usize()]; + let b = self.profile.b_linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = r as i32 * transform.v[0][0] as i32 + + g as i32 * transform.v[0][1] as i32 + + b as i32 * transform.v[0][2] as i32 + + rnd; + + let r_q2_13 = (new_r >> PRECISION).min(v_gamma_max).max(0) as u16; + + let new_g = r as i32 * transform.v[1][0] as i32 + + g as i32 * transform.v[1][1] as i32 + + b as i32 * transform.v[1][2] as i32 + + rnd; + + let g_q2_13 = (new_g >> PRECISION).min(v_gamma_max).max(0) as u16; + + let new_b = r as i32 * transform.v[2][0] as i32 + + g as i32 * transform.v[2][1] as i32 + + b as i32 * transform.v[2][2] as i32 + + rnd; + + let b_q2_13 = (new_b >> PRECISION).min(v_gamma_max).max(0) as u16; + + dst[dst_cn.r_i()] = self.profile.r_gamma[r_q2_13 as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[g_q2_13 as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[b_q2_13 as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + Ok(()) + } +} + +#[allow(unused)] +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, + const PRECISION: i32, +> TransformExecutor + for TransformMatrixShaperQ2_13Optimized +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let max_colors: T = ((1 << self.bit_depth as u32) - 1u32).as_(); + let rnd: i32 = (1i32 << (PRECISION - 1)); + + let v_gamma_max = self.gamma_lut as i32 - 1; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.profile.linear[src[src_cn.r_i()]._as_usize()]; + let g = self.profile.linear[src[src_cn.g_i()]._as_usize()]; + let b = self.profile.linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = r as i32 * transform.v[0][0] as i32 + + g as i32 * transform.v[0][1] as i32 + + b as i32 * transform.v[0][2] as i32 + + rnd; + + let r_q2_13 = (new_r >> PRECISION).min(v_gamma_max).max(0) as u16; + + let new_g = r as i32 * transform.v[1][0] as i32 + + g as i32 * transform.v[1][1] as i32 + + b as i32 * transform.v[1][2] as i32 + + rnd; + + let g_q2_13 = (new_g >> PRECISION).min(v_gamma_max).max(0) as u16; + + let new_b = r as i32 * transform.v[2][0] as i32 + + g as i32 * transform.v[2][1] as i32 + + b as i32 * transform.v[2][2] as i32 + + rnd; + + let b_q2_13 = (new_b >> PRECISION).min(v_gamma_max).max(0) as u16; + + dst[dst_cn.r_i()] = self.profile.gamma[r_q2_13 as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[g_q2_13 as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[b_q2_13 as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + Ok(()) + } +} + +#[allow(unused_macros)] +macro_rules! create_rgb_xyz_dependant_q2_13_executor { + ($dep_name: ident, $dependant: ident, $resolution: ident, $shaper: ident) => { + pub(crate) fn $dep_name< + T: Clone + Send + Sync + AsPrimitive + Default + PointeeSizeExpressible, + const LINEAR_CAP: usize, + const PRECISION: i32, + >( + src_layout: Layout, + dst_layout: Layout, + profile: $shaper, + gamma_lut: usize, + bit_depth: usize, + ) -> Result + Send + Sync>, CmsError> + where + u32: AsPrimitive, + { + let q2_13_profile = + profile.to_q2_13_n::<$resolution, PRECISION, LINEAR_CAP>(gamma_lut, bit_depth); + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } + Err(CmsError::UnsupportedProfileConnection) + } + }; +} + +#[allow(unused_macros)] +macro_rules! create_rgb_xyz_dependant_q2_13_executor_fp { + ($dep_name: ident, $dependant: ident, $resolution: ident, $shaper: ident) => { + pub(crate) fn $dep_name< + T: Clone + Send + Sync + AsPrimitive + Default + PointeeSizeExpressible, + const LINEAR_CAP: usize, + const PRECISION: i32, + >( + src_layout: Layout, + dst_layout: Layout, + profile: $shaper, + gamma_lut: usize, + bit_depth: usize, + ) -> Result + Send + Sync>, CmsError> + where + u32: AsPrimitive, + { + let q2_13_profile = profile.to_q2_13_i::<$resolution, PRECISION>(gamma_lut, bit_depth); + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + PRECISION, + > { + profile: q2_13_profile, + bit_depth, + gamma_lut, + })); + } + Err(CmsError::UnsupportedProfileConnection) + } + }; +} + +#[cfg(all(target_arch = "aarch64", feature = "neon"))] +macro_rules! create_rgb_xyz_dependant_q1_30_executor { + ($dep_name: ident, $dependant: ident, $resolution: ident, $shaper: ident) => { + pub(crate) fn $dep_name< + T: Clone + Send + Sync + AsPrimitive + Default + PointeeSizeExpressible, + const LINEAR_CAP: usize, + const PRECISION: i32, + >( + src_layout: Layout, + dst_layout: Layout, + profile: $shaper, + gamma_lut: usize, + bit_depth: usize, + ) -> Result + Send + Sync>, CmsError> + where + u32: AsPrimitive, + { + let q1_30_profile = profile.to_q1_30_n::<$resolution, PRECISION>(gamma_lut, bit_depth); + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + > { + profile: q1_30_profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + > { + profile: q1_30_profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + > { + profile: q1_30_profile, + gamma_lut, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new($dependant::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + > { + profile: q1_30_profile, + gamma_lut, + bit_depth, + })); + } + Err(CmsError::UnsupportedProfileConnection) + } + }; +} + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +use crate::conversions::neon::{ + TransformShaperQ1_30NeonOpt, TransformShaperQ2_13Neon, TransformShaperQ2_13NeonOpt, +}; + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13, + TransformShaperQ2_13Neon, + i16, + TransformMatrixShaper +); + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13_opt, + TransformShaperQ2_13NeonOpt, + i16, + TransformMatrixShaperOptimized +); + +#[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))] +create_rgb_xyz_dependant_q1_30_executor!( + make_rgb_xyz_q1_30_opt, + TransformShaperQ1_30NeonOpt, + i32, + TransformMatrixShaperOptimized +); + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +create_rgb_xyz_dependant_q2_13_executor!( + make_rgb_xyz_q2_13, + TransformMatrixShaperQ2_13, + i16, + TransformMatrixShaper +); + +#[cfg(not(all(target_arch = "aarch64", target_feature = "neon", feature = "neon")))] +create_rgb_xyz_dependant_q2_13_executor!( + make_rgb_xyz_q2_13_opt, + TransformMatrixShaperQ2_13Optimized, + i16, + TransformMatrixShaperOptimized +); + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +use crate::conversions::sse::{TransformShaperQ2_13OptSse, TransformShaperQ2_13Sse}; + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13_transform_sse_41, + TransformShaperQ2_13Sse, + i32, + TransformMatrixShaper +); + +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13_transform_sse_41_opt, + TransformShaperQ2_13OptSse, + i32, + TransformMatrixShaperOptimized +); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +use crate::conversions::avx::{TransformShaperRgbQ2_13Avx, TransformShaperRgbQ2_13OptAvx}; +use crate::conversions::rgbxyz::TransformMatrixShaperOptimized; +use crate::transform::PointeeSizeExpressible; + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13_transform_avx2, + TransformShaperRgbQ2_13Avx, + i32, + TransformMatrixShaper +); + +#[cfg(all(target_arch = "x86_64", feature = "avx"))] +create_rgb_xyz_dependant_q2_13_executor_fp!( + make_rgb_xyz_q2_13_transform_avx2_opt, + TransformShaperRgbQ2_13OptAvx, + i32, + TransformMatrixShaperOptimized +); + +#[cfg(all(target_arch = "x86_64", feature = "avx512"))] +use crate::conversions::avx512::TransformShaperRgbQ2_13OptAvx512; + +#[cfg(all(target_arch = "x86_64", feature = "avx512"))] +create_rgb_xyz_dependant_q2_13_executor!( + make_rgb_xyz_q2_13_transform_avx512_opt, + TransformShaperRgbQ2_13OptAvx512, + i32, + TransformMatrixShaperOptimized +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_float.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_float.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/rgbxyz_float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::trc::ToneCurveEvaluator; +use crate::{CmsError, Layout, Matrix3f, PointeeSizeExpressible, Rgb, TransformExecutor}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) struct TransformShaperRgbFloat { + pub(crate) r_linear: Box<[f32; BUCKET]>, + pub(crate) g_linear: Box<[f32; BUCKET]>, + pub(crate) b_linear: Box<[f32; BUCKET]>, + pub(crate) gamma_evaluator: Box, + pub(crate) adaptation_matrix: Matrix3f, + pub(crate) phantom_data: PhantomData, +} + +pub(crate) struct TransformShaperFloatInOut { + pub(crate) linear_evaluator: Box, + pub(crate) gamma_evaluator: Box, + pub(crate) adaptation_matrix: Matrix3f, + pub(crate) phantom_data: PhantomData, +} + +struct TransformShaperFloatScalar< + T: Clone, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> { + pub(crate) profile: TransformShaperRgbFloat, + pub(crate) bit_depth: usize, +} + +struct TransformShaperRgbFloatInOut { + pub(crate) profile: TransformShaperFloatInOut, + pub(crate) bit_depth: usize, +} + +pub(crate) fn make_rgb_xyz_rgb_transform_float< + T: Clone + Send + Sync + PointeeSizeExpressible + 'static + Copy + Default, + const LINEAR_CAP: usize, +>( + src_layout: Layout, + dst_layout: Layout, + profile: TransformShaperRgbFloat, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformShaperFloatScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformShaperFloatScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformShaperFloatScalar::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformShaperFloatScalar::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + LINEAR_CAP, + > { + profile, + bit_depth, + })); + } + Err(CmsError::UnsupportedProfileConnection) +} + +pub(crate) fn make_rgb_xyz_rgb_transform_float_in_out< + T: Clone + Send + Sync + PointeeSizeExpressible + 'static + Copy + Default + AsPrimitive, +>( + src_layout: Layout, + dst_layout: Layout, + profile: TransformShaperFloatInOut, + bit_depth: usize, +) -> Result + Send + Sync>, CmsError> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformShaperRgbFloatInOut::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgba as u8 }, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgba) { + return Ok(Box::new(TransformShaperRgbFloatInOut::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgba as u8 }, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgba) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformShaperRgbFloatInOut::< + T, + { Layout::Rgba as u8 }, + { Layout::Rgb as u8 }, + > { + profile, + bit_depth, + })); + } else if (src_layout == Layout::Rgb) && (dst_layout == Layout::Rgb) { + return Ok(Box::new(TransformShaperRgbFloatInOut::< + T, + { Layout::Rgb as u8 }, + { Layout::Rgb as u8 }, + > { + profile, + bit_depth, + })); + } + Err(CmsError::UnsupportedProfileConnection) +} + +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformShaperFloatScalar +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + use crate::mlaf::mlaf; + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let r = self.profile.r_linear[src[src_cn.r_i()]._as_usize()]; + let g = self.profile.g_linear[src[src_cn.g_i()]._as_usize()]; + let b = self.profile.b_linear[src[src_cn.b_i()]._as_usize()]; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = mlaf( + mlaf(r * transform.v[0][0], g, transform.v[0][1]), + b, + transform.v[0][2], + ); + + let new_g = mlaf( + mlaf(r * transform.v[1][0], g, transform.v[1][1]), + b, + transform.v[1][2], + ); + + let new_b = mlaf( + mlaf(r * transform.v[2][0], g, transform.v[2][1]), + b, + transform.v[2][2], + ); + + let mut rgb = Rgb::new(new_r, new_g, new_b); + rgb = self.profile.gamma_evaluator.evaluate_tristimulus(rgb); + + dst[dst_cn.r_i()] = rgb.r.as_(); + dst[dst_cn.g_i()] = rgb.g.as_(); + dst[dst_cn.b_i()] = rgb.b.as_(); + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + + Ok(()) + } +} + +impl< + T: Clone + PointeeSizeExpressible + Copy + Default + 'static + AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperRgbFloatInOut +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + use crate::mlaf::mlaf; + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let transform = self.profile.adaptation_matrix; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let mut src_rgb = Rgb::new( + src[src_cn.r_i()].as_(), + src[src_cn.g_i()].as_(), + src[src_cn.b_i()].as_(), + ); + src_rgb = self.profile.linear_evaluator.evaluate_tristimulus(src_rgb); + let r = src_rgb.r; + let g = src_rgb.g; + let b = src_rgb.b; + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + let new_r = mlaf( + mlaf(r * transform.v[0][0], g, transform.v[0][1]), + b, + transform.v[0][2], + ); + + let new_g = mlaf( + mlaf(r * transform.v[1][0], g, transform.v[1][1]), + b, + transform.v[1][2], + ); + + let new_b = mlaf( + mlaf(r * transform.v[2][0], g, transform.v[2][1]), + b, + transform.v[2][2], + ); + + let mut rgb = Rgb::new(new_r, new_g, new_b); + rgb = self.profile.gamma_evaluator.evaluate_tristimulus(rgb); + + dst[dst_cn.r_i()] = rgb.r.as_(); + dst[dst_cn.g_i()] = rgb.g.as_(); + dst[dst_cn.b_i()] = rgb.b.as_(); + + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,443 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::BarycentricWeight; +use crate::math::FusedMultiplyAdd; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::ops::{Add, Mul, Sub}; + +#[repr(align(16), C)] +pub(crate) struct SseAlignedF32(pub(crate) [f32; 4]); + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralSse {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalSse {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticSse {} + +pub(crate) struct TrilinearSse {} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct SseVector { + pub(crate) v: __m128, +} + +impl From for SseVector { + #[inline(always)] + fn from(v: f32) -> Self { + SseVector { + v: unsafe { _mm_set1_ps(v) }, + } + } +} + +impl Sub for SseVector { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_sub_ps(self.v, rhs.v) }, + } + } +} + +impl Add for SseVector { + type Output = Self; + #[inline(always)] + fn add(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_add_ps(self.v, rhs.v) }, + } + } +} + +impl Mul for SseVector { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_mul_ps(self.v, rhs.v) }, + } + } +} + +impl FusedMultiplyAdd for SseVector { + #[inline(always)] + fn mla(&self, b: SseVector, c: SseVector) -> SseVector { + SseVector { + v: unsafe { _mm_add_ps(self.v, _mm_mul_ps(b.v, c.v)) }, + } + } +} + +struct TetrahedralSseFetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [SseAlignedF32], +} + +impl Fetcher for TetrahedralSseFetchVector<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> SseVector { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + SseVector { + v: unsafe { _mm_load_ps(jx.as_ptr() as *const _) }, + } + } +} + +pub(crate) trait SseMdInterpolation { + fn inter3_sse( + &self, + table: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> SseVector; +} + +#[cfg(feature = "options")] +impl TetrahedralSse { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, SseVector::from(rx)); + let s1 = s0.mla(c2, SseVector::from(ry)); + s1.mla(c3, SseVector::from(rz)) + } +} + +macro_rules! define_inter_sse { + ($interpolator: ident) => { + impl SseMdInterpolation for $interpolator { + fn inter3_sse( + &self, + table: &[SseAlignedF32], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> SseVector { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralSseFetchVector:: { cube: table }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +define_inter_sse!(TetrahedralSse); +#[cfg(feature = "options")] +define_inter_sse!(PyramidalSse); +#[cfg(feature = "options")] +define_inter_sse!(PrismaticSse); +define_inter_sse!(TrilinearSse); + +#[cfg(feature = "options")] +impl PyramidalSse { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(dg * db)) + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(db * dr)) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticSse { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if db > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + let s3 = s2.mla(c4, SseVector::from(dg * db)); + s3.mla(c5, SseVector::from(dr * dg)) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + let s3 = s2.mla(c4, SseVector::from(dg * db)); + s3.mla(c5, SseVector::from(dr * dg)) + } + } +} + +impl TrilinearSse { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let w0 = SseVector::from(dr); + let w1 = SseVector::from(dg); + let w2 = SseVector::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let dx = SseVector::from(1.0 - dr); + + let c00 = (c000 * dx).mla(c100, w0); + let c10 = (c010 * dx).mla(c110, w0); + let c01 = (c001 * dx).mla(c101, w0); + let c11 = (c011 * dx).mla(c111, w0); + + let dy = SseVector::from(1.0 - dg); + + let c0 = (c00 * dy).mla(c10, w1); + let c1 = (c01 * dy).mla(c11, w1); + + let dz = SseVector::from(1.0 - db); + + (c0 * dz).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/interpolator_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,442 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::BarycentricWeight; +use crate::math::FusedMultiplyAdd; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::ops::{Add, Mul, Sub}; + +#[repr(align(8), C)] +pub(crate) struct SseAlignedI16x4(pub(crate) [i16; 4]); + +#[cfg(feature = "options")] +pub(crate) struct TetrahedralSseQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PyramidalSseQ0_15 {} + +#[cfg(feature = "options")] +pub(crate) struct PrismaticSseQ0_15 {} + +pub(crate) struct TrilinearSseQ0_15 {} + +trait Fetcher { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct SseVector { + pub(crate) v: __m128i, +} + +impl From for SseVector { + #[inline(always)] + fn from(v: i16) -> Self { + SseVector { + v: unsafe { _mm_set1_epi16(v) }, + } + } +} + +impl Sub for SseVector { + type Output = Self; + #[inline(always)] + fn sub(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_sub_epi16(self.v, rhs.v) }, + } + } +} + +impl Add for SseVector { + type Output = Self; + #[inline(always)] + fn add(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_add_epi16(self.v, rhs.v) }, + } + } +} + +impl Mul for SseVector { + type Output = Self; + #[inline(always)] + fn mul(self, rhs: SseVector) -> Self::Output { + SseVector { + v: unsafe { _mm_mulhrs_epi16(self.v, rhs.v) }, + } + } +} + +impl FusedMultiplyAdd for SseVector { + #[inline(always)] + fn mla(&self, b: SseVector, c: SseVector) -> SseVector { + SseVector { + v: unsafe { _mm_add_epi16(self.v, _mm_mulhrs_epi16(b.v, c.v)) }, + } + } +} + +struct TetrahedralSseQ0_15FetchVector<'a, const GRID_SIZE: usize> { + cube: &'a [SseAlignedI16x4], +} + +impl Fetcher for TetrahedralSseQ0_15FetchVector<'_, GRID_SIZE> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> SseVector { + let offset = (x as u32 * (GRID_SIZE as u32 * GRID_SIZE as u32) + + y as u32 * GRID_SIZE as u32 + + z as u32) as usize; + let jx = unsafe { self.cube.get_unchecked(offset..) }; + SseVector { + v: unsafe { _mm_loadu_si64(jx.as_ptr() as *const _) }, + } + } +} + +pub(crate) trait SseMdInterpolationQ0_15 { + fn inter3_sse( + &self, + cube: &[SseAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> SseVector; +} + +#[cfg(feature = "options")] +impl TetrahedralSseQ0_15 { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let rx = lut_r.w; + let ry = lut_g.w; + let rz = lut_b.w; + + let c0 = r.fetch(x, y, z); + + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z) - r.fetch(x_n, y, z); + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z) - c0; + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x_n, y, z_n) - r.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n) - r.fetch(x, y, z_n); + c2 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z) - r.fetch(x, y_n, z); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x_n, y_n, z_n) - r.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z) - c0; + c3 = r.fetch(x, y_n, z_n) - r.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n) - r.fetch(x, y_n, z_n); + c2 = r.fetch(x, y_n, z_n) - r.fetch(x, y, z_n); + c3 = r.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, SseVector::from(rx)); + let s1 = s0.mla(c2, SseVector::from(ry)); + s1.mla(c3, SseVector::from(rz)) + } +} + +macro_rules! define_inter_sse { + ($interpolator: ident) => { + impl SseMdInterpolationQ0_15 for $interpolator { + fn inter3_sse( + &self, + table: &[SseAlignedI16x4], + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + ) -> SseVector { + unsafe { + self.interpolate( + in_r, + in_g, + in_b, + lut, + TetrahedralSseQ0_15FetchVector:: { cube: table }, + ) + } + } + } + }; +} + +#[cfg(feature = "options")] +define_inter_sse!(TetrahedralSseQ0_15); +#[cfg(feature = "options")] +define_inter_sse!(PyramidalSseQ0_15); +#[cfg(feature = "options")] +define_inter_sse!(PrismaticSseQ0_15); +define_inter_sse!(TrilinearSseQ0_15); + +#[cfg(feature = "options")] +impl PyramidalSseQ0_15 { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n); + let x1 = r.fetch(x_n, y_n, z); + let x2 = r.fetch(x_n, y, z); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(dr) * SseVector::from(dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y_n, z_n); + let x2 = r.fetch(x, y_n, z_n); + let x3 = r.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(dg) * SseVector::from(db)) + } else { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z); + let x2 = r.fetch(x_n, y, z_n); + let x3 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + s2.mla(c4, SseVector::from(db) * SseVector::from(dr)) + } + } +} + +#[cfg(feature = "options")] +impl PrismaticSseQ0_15 { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + let c0 = r.fetch(x, y, z); + + if db > dr { + let x0 = r.fetch(x, y, z_n); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x, y_n, z_n); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + let s3 = s2.mla(c4, SseVector::from(dg) * SseVector::from(db)); + s3.mla(c5, SseVector::from(dr) * SseVector::from(dg)) + } else { + let x0 = r.fetch(x_n, y, z); + let x1 = r.fetch(x_n, y, z_n); + let x2 = r.fetch(x, y_n, z); + let x3 = r.fetch(x_n, y_n, z); + let x4 = r.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, SseVector::from(db)); + let s1 = s0.mla(c2, SseVector::from(dr)); + let s2 = s1.mla(c3, SseVector::from(dg)); + let s3 = s2.mla(c4, SseVector::from(dg) * SseVector::from(db)); + s3.mla(c5, SseVector::from(dr) * SseVector::from(dg)) + } + } +} + +impl TrilinearSseQ0_15 { + #[target_feature(enable = "sse4.1")] + unsafe fn interpolate( + &self, + in_r: usize, + in_g: usize, + in_b: usize, + lut: &[BarycentricWeight], + r: impl Fetcher, + ) -> SseVector { + let lut_r = unsafe { *lut.get_unchecked(in_r) }; + let lut_g = unsafe { *lut.get_unchecked(in_g) }; + let lut_b = unsafe { *lut.get_unchecked(in_b) }; + + let x: i32 = lut_r.x; + let y: i32 = lut_g.x; + let z: i32 = lut_b.x; + + let x_n: i32 = lut_r.x_n; + let y_n: i32 = lut_g.x_n; + let z_n: i32 = lut_b.x_n; + + let dr = lut_r.w; + let dg = lut_g.w; + let db = lut_b.w; + + const Q_MAX: i16 = ((1i32 << 15i32) - 1) as i16; + let q_max = SseVector::from(Q_MAX); + let w0 = SseVector::from(dr); + let w1 = SseVector::from(dg); + let w2 = SseVector::from(db); + let dx = q_max - SseVector::from(dr); + let dy = q_max - SseVector::from(dg); + let dz = q_max - SseVector::from(db); + + let c000 = r.fetch(x, y, z); + let c100 = r.fetch(x_n, y, z); + let c010 = r.fetch(x, y_n, z); + let c110 = r.fetch(x_n, y_n, z); + let c001 = r.fetch(x, y, z_n); + let c101 = r.fetch(x_n, y, z_n); + let c011 = r.fetch(x, y_n, z_n); + let c111 = r.fetch(x_n, y_n, z_n); + + let c00 = (c000 * dx).mla(c100, w0); + let c10 = (c010 * dx).mla(c110, w0); + let c01 = (c001 * dx).mla(c101, w0); + let c11 = (c011 * dx).mla(c111, w0); + + let c0 = (c00 * dy).mla(c10, w1); + let c1 = (c01 * dy).mla(c11, w1); + + (c0 * dz).mla(c1, w2) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,333 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut4x3Factory; +use crate::conversions::sse::interpolator::*; +use crate::conversions::sse::interpolator_q0_15::SseAlignedI16x4; +use crate::conversions::sse::lut4_to_3_q0_15::TransformLut4To3SseQ0_15; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::marker::PhantomData; + +struct TransformLut4To3Sse< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3Sse +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "sse4.1")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let value_scale = unsafe { _mm_set1_ps(((1 << BIT_DEPTH) - 1) as f32) }; + let max_value = ((1 << BIT_DEPTH) - 1u32).as_(); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + let t: f32 = k_weights.w; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let a0 = interpolator + .inter3_sse(table1, c.as_(), m.as_(), y.as_(), self.weights.as_slice()) + .v; + let b0 = interpolator + .inter3_sse(table2, c.as_(), m.as_(), y.as_(), self.weights.as_slice()) + .v; + + if T::FINITE { + unsafe { + let t0 = _mm_set1_ps(t); + let ones = _mm_set1_ps(1f32); + let hp = _mm_mul_ps(a0, _mm_sub_ps(ones, t0)); + let mut v = _mm_add_ps(_mm_mul_ps(b0, t0), hp); + v = _mm_max_ps(v, _mm_setzero_ps()); + v = _mm_mul_ps(v, value_scale); + v = _mm_min_ps(v, value_scale); + let jvz = _mm_cvtps_epi32(v); + + let x = _mm_extract_epi32::<0>(jvz); + let y = _mm_extract_epi32::<1>(jvz); + let z = _mm_extract_epi32::<2>(jvz); + + dst[cn.r_i()] = (x as u32).as_(); + dst[cn.g_i()] = (y as u32).as_(); + dst[cn.b_i()] = (z as u32).as_(); + } + } else { + unsafe { + let t0 = _mm_set1_ps(t); + let ones = _mm_set1_ps(1f32); + let hp = _mm_mul_ps(a0, _mm_sub_ps(ones, t0)); + let v = _mm_add_ps(_mm_mul_ps(b0, t0), hp); + + dst[cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(v) as u32).as_(); + dst[cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(v) as u32).as_(); + dst[cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(v) as u32).as_(); + } + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3Sse +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearSse:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk(src, dst, Box::new(TetrahedralSse:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalSse:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticSse:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearSse:: {})); + } + } + } + } + + Ok(()) + } +} + +pub(crate) struct SseLut4x3Factory {} + +impl Lut4x3Factory for SseLut4x3Factory { + fn make_transform_4x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Sync + Send> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point && BIT_DEPTH < 16 { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + SseAlignedI16x4([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut4To3SseQ0_15::< + T, + u8, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut4To3SseQ0_15::< + T, + u16, + LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + _phantom: PhantomData, + _phantom1: PhantomData, + color_space, + is_linear, + }), + }; + } + let lut = lut + .chunks_exact(3) + .map(|x| SseAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => { + Box::new( + TransformLut4To3Sse:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }, + ) + } + #[cfg(feature = "options")] + BarycentricWeightScale::High => { + Box::new( + TransformLut4To3Sse:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }, + ) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/lut4_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::sse::interpolator_q0_15::*; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut4To3SseQ0_15< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3SseQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "sse4.1")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let f_value_scale = _mm_set1_ps(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + _mm_set1_epi16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + _mm_set1_epi16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + const Q: i16 = ((1i32 << 15) - 1) as i16; + let t: i16 = k_weights.w; + let t_n: i16 = Q - t; + + let table1 = &self.lut[(w * grid_size3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3) as usize..]; + + let a0 = interpolator + .inter3_sse(table1, c.as_(), m.as_(), y.as_(), self.weights.as_slice()) + .v; + let b0 = interpolator + .inter3_sse(table2, c.as_(), m.as_(), y.as_(), self.weights.as_slice()) + .v; + + let hp = _mm_mulhrs_epi16(_mm_set1_epi16(t_n), a0); + let v = _mm_add_epi16(hp, _mm_mulhrs_epi16(b0, _mm_set1_epi16(t))); + + if T::FINITE { + let mut o = _mm_max_epi16(v, _mm_setzero_si128()); + o = _mm_min_epi16(o, v_max_scale); + + let x = _mm_extract_epi16::<0>(o); + let y = _mm_extract_epi16::<1>(o); + let z = _mm_extract_epi16::<2>(o); + + dst[cn.r_i()] = (x as u32).as_(); + dst[cn.g_i()] = (y as u32).as_(); + dst[cn.b_i()] = (z as u32).as_(); + } else { + let mut r = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(v)); + r = _mm_mul_ps(r, f_value_scale); + dst[cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(r) as u32).as_(); + dst[cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(r) as u32).as_(); + dst[cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(r) as u32).as_(); + } + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3SseQ0_15 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearSseQ0_15:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralSseQ0_15:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalSseQ0_15:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticSseQ0_15:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearSseQ0_15:: {})); + } + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod interpolator; +mod interpolator_q0_15; +mod lut4_to_3; +mod lut4_to_3_q0_15; +mod rgb_xyz; +mod rgb_xyz_opt; +mod rgb_xyz_q2_13; +mod rgb_xyz_q2_13_opt; +mod t_lut3_to_3; +mod t_lut3_to_3_q0_15; + +pub(crate) use lut4_to_3::SseLut4x3Factory; +pub(crate) use rgb_xyz::TransformShaperRgbSse; +pub(crate) use rgb_xyz_opt::TransformShaperRgbOptSse; +pub(crate) use rgb_xyz_q2_13::TransformShaperQ2_13Sse; +pub(crate) use rgb_xyz_q2_13_opt::TransformShaperQ2_13OptSse; +pub(crate) use t_lut3_to_3::SseLut3x3Factory; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,154 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::TransformMatrixShaper; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +#[repr(align(16), C)] +pub(crate) struct SseAlignedU16(pub(crate) [u16; 8]); + +pub(crate) struct TransformShaperRgbSse< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + // deleting linear cap is in effective here + const LINEAR_CAP: usize, +> { + // removing linear cap here is not worth it, at least in previous attempts + pub(crate) profile: TransformMatrixShaper, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformShaperRgbSse +where + u32: AsPrimitive, +{ + #[target_feature(enable = "sse4.1")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary = SseAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + unsafe { + let m0 = _mm_setr_ps(t.v[0][0], t.v[0][1], t.v[0][2], 0f32); + let m1 = _mm_setr_ps(t.v[1][0], t.v[1][1], t.v[1][2], 0f32); + let m2 = _mm_setr_ps(t.v[2][0], t.v[2][1], t.v[2][2], 0f32); + + let zeros = _mm_setzero_ps(); + + let v_scale = _mm_set1_ps(scale); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let rp = &self.profile.r_linear[src[src_cn.r_i()]._as_usize()]; + let gp = &self.profile.g_linear[src[src_cn.g_i()]._as_usize()]; + let bp = &self.profile.b_linear[src[src_cn.b_i()]._as_usize()]; + + let mut r = _mm_load_ss(rp); + let mut g = _mm_load_ss(gp); + let mut b = _mm_load_ss(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + r = _mm_shuffle_ps::<0>(r, r); + g = _mm_shuffle_ps::<0>(g, g); + b = _mm_shuffle_ps::<0>(b, b); + + let v0 = _mm_mul_ps(r, m0); + let v1 = _mm_mul_ps(g, m1); + let v2 = _mm_mul_ps(b, m2); + + let mut v = _mm_add_ps(_mm_add_ps(v0, v1), v2); + v = _mm_max_ps(v, zeros); + v = _mm_mul_ps(v, v_scale); + v = _mm_min_ps(v, v_scale); + + let zx = _mm_cvtps_epi32(v); + _mm_store_si128(temporary.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const LINEAR_CAP: usize, +> TransformExecutor for TransformShaperRgbSse +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,157 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::rgbxyz::TransformMatrixShaperOptimizedV; +use crate::conversions::sse::rgb_xyz::SseAlignedU16; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperRgbOptSse< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> { + pub(crate) profile: TransformMatrixShaperOptimizedV, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformShaperRgbOptSse +where + u32: AsPrimitive, +{ + #[target_feature(enable = "sse4.1")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary = SseAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let scale = (self.gamma_lut - 1) as f32; + let max_colors: T = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + unsafe { + let m0 = _mm_setr_ps(t.v[0][0], t.v[0][1], t.v[0][2], 0f32); + let m1 = _mm_setr_ps(t.v[1][0], t.v[1][1], t.v[1][2], 0f32); + let m2 = _mm_setr_ps(t.v[2][0], t.v[2][1], t.v[2][2], 0f32); + + let zeros = _mm_setzero_ps(); + + let v_scale = _mm_set1_ps(scale); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let rp = lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + + let mut r = _mm_load_ss(rp); + let mut g = _mm_load_ss(gp); + let mut b = _mm_load_ss(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + r = _mm_shuffle_ps::<0>(r, r); + g = _mm_shuffle_ps::<0>(g, g); + b = _mm_shuffle_ps::<0>(b, b); + + let v0 = _mm_mul_ps(r, m0); + let v1 = _mm_mul_ps(g, m1); + let v2 = _mm_mul_ps(b, m2); + + let mut v = _mm_add_ps(_mm_add_ps(v0, v1), v2); + v = _mm_max_ps(v, zeros); + v = _mm_mul_ps(v, v_scale); + v = _mm_min_ps(v, v_scale); + + let zx = _mm_cvtps_epi32(v); + _mm_store_si128(temporary.0.as_mut_ptr() as *mut _, zx); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Clone + Copy + 'static + PointeeSizeExpressible + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, +> TransformExecutor for TransformShaperRgbOptSse +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,177 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFp; +use crate::conversions::sse::rgb_xyz::SseAlignedU16; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperQ2_13Sse< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFp, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +#[inline(always)] +pub(crate) unsafe fn _xmm_load_epi32(f: &i32) -> __m128i { + let float_ref: &f32 = unsafe { &*(f as *const i32 as *const f32) }; + unsafe { _mm_castps_si128(_mm_load_ss(float_ref)) } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformShaperQ2_13Sse +where + u32: AsPrimitive, +{ + #[target_feature(enable = "sse4.1")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary = SseAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let max_colors = ((1 << self.bit_depth) - 1).as_(); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.r_linear.len() >= cap); + assert!(self.profile.g_linear.len() >= cap); + assert!(self.profile.b_linear.len() >= cap); + } else { + assert!(self.profile.r_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.g_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + assert!(self.profile.b_linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let r_lin = &self.profile.r_linear; + let g_lin = &self.profile.g_linear; + let b_lin = &self.profile.b_linear; + + unsafe { + let m0 = _mm_setr_epi16( + t.v[0][0], t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, + ); + let m2 = _mm_setr_epi16(t.v[2][0], 1, t.v[2][1], 1, t.v[2][2], 1, 0, 0); + + let rnd_val = ((1i32 << (PRECISION - 1)) as i16).to_ne_bytes(); + let rnd = _mm_set1_epi32(i32::from_ne_bytes([0, 0, rnd_val[0], rnd_val[1]])); + + let v_max_value = _mm_set1_epi32(self.gamma_lut as i32 - 1); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let rp = r_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = g_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = b_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + + let mut r = _xmm_load_epi32(rp); + let mut g = _xmm_load_epi32(gp); + let mut b = _xmm_load_epi32(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + r = _mm_shuffle_epi32::<0>(r); + g = _mm_shuffle_epi32::<0>(g); + b = _mm_shuffle_epi32::<0>(b); + + g = _mm_slli_epi32::<16>(g); + + let zrg0 = _mm_or_si128(r, g); + let zbz0 = _mm_or_si128(b, rnd); + + let v0 = _mm_madd_epi16(zrg0, m0); + let v1 = _mm_madd_epi16(zbz0, m2); + + let mut v = _mm_add_epi32(v0, v1); + + v = _mm_srai_epi32::(v); + v = _mm_max_epi32(v, _mm_setzero_si128()); + v = _mm_min_epi32(v, v_max_value); + + _mm_store_si128(temporary.0.as_mut_ptr() as *mut _, v); + + dst[dst_cn.r_i()] = self.profile.r_gamma[temporary.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.g_gamma[temporary.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.b_gamma[temporary.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperQ2_13Sse +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13_opt.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13_opt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13_opt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/rgb_xyz_q2_13_opt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::rgbxyz_fixed::TransformMatrixShaperFpOptVec; +use crate::conversions::sse::rgb_xyz::SseAlignedU16; +use crate::conversions::sse::rgb_xyz_q2_13::_xmm_load_epi32; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +pub(crate) struct TransformShaperQ2_13OptSse< + T: Copy, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> { + pub(crate) profile: TransformMatrixShaperFpOptVec, + pub(crate) bit_depth: usize, + pub(crate) gamma_lut: usize, +} + +impl< + T: Copy + PointeeSizeExpressible + 'static, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformShaperQ2_13OptSse +where + u32: AsPrimitive, +{ + #[target_feature(enable = "sse4.1")] + unsafe fn transform_impl(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let dst_cn = Layout::from(DST_LAYOUT); + let src_channels = src_cn.channels(); + let dst_channels = dst_cn.channels(); + + let mut temporary = SseAlignedU16([0; 8]); + + if src.len() / src_channels != dst.len() / dst_channels { + return Err(CmsError::LaneSizeMismatch); + } + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + + let t = self.profile.adaptation_matrix.transpose(); + + let max_colors = ((1 << self.bit_depth) - 1).as_(); + + unsafe { + let m0 = _mm_setr_epi16( + t.v[0][0], t.v[1][0], t.v[0][1], t.v[1][1], t.v[0][2], t.v[1][2], 0, 0, + ); + let m2 = _mm_setr_epi16(t.v[2][0], 1, t.v[2][1], 1, t.v[2][2], 1, 0, 0); + + let rnd_val = ((1i32 << (PRECISION - 1)) as i16).to_ne_bytes(); + let rnd = _mm_set1_epi32(i32::from_ne_bytes([0, 0, rnd_val[0], rnd_val[1]])); + + let v_max_value = _mm_set1_epi32(self.gamma_lut as i32 - 1); + + // safety precondition for linearization table + if T::FINITE { + let cap = (1 << self.bit_depth) - 1; + assert!(self.profile.linear.len() >= cap); + } else { + assert!(self.profile.linear.len() >= T::NOT_FINITE_LINEAR_TABLE_SIZE); + } + + let lut_lin = &self.profile.linear; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let rp = lut_lin.get_unchecked(src[src_cn.r_i()]._as_usize()); + let gp = lut_lin.get_unchecked(src[src_cn.g_i()]._as_usize()); + let bp = lut_lin.get_unchecked(src[src_cn.b_i()]._as_usize()); + + let mut r = _xmm_load_epi32(rp); + let mut g = _xmm_load_epi32(gp); + let mut b = _xmm_load_epi32(bp); + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_colors + }; + + r = _mm_shuffle_epi32::<0>(r); + g = _mm_shuffle_epi32::<0>(g); + b = _mm_shuffle_epi32::<0>(b); + + g = _mm_slli_epi32::<16>(g); + + let zrg0 = _mm_or_si128(r, g); + let zbz0 = _mm_or_si128(b, rnd); + + let v0 = _mm_madd_epi16(zrg0, m0); + let v1 = _mm_madd_epi16(zbz0, m2); + + let mut v = _mm_add_epi32(v0, v1); + + v = _mm_srai_epi32::(v); + v = _mm_max_epi32(v, _mm_setzero_si128()); + v = _mm_min_epi32(v, v_max_value); + + _mm_store_si128(temporary.0.as_mut_ptr() as *mut _, v); + + dst[dst_cn.r_i()] = self.profile.gamma[temporary.0[0] as usize]; + dst[dst_cn.g_i()] = self.profile.gamma[temporary.0[2] as usize]; + dst[dst_cn.b_i()] = self.profile.gamma[temporary.0[4] as usize]; + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + + Ok(()) + } +} + +impl< + T: Copy + PointeeSizeExpressible + 'static + Default, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const PRECISION: i32, +> TransformExecutor for TransformShaperQ2_13OptSse +where + u32: AsPrimitive, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + unsafe { self.transform_impl(src, dst) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::lut_transforms::Lut3x3Factory; +use crate::conversions::sse::interpolator::*; +use crate::conversions::sse::interpolator_q0_15::SseAlignedI16x4; +use crate::conversions::sse::t_lut3_to_3_q0_15::TransformLut3x3SseQ0_15; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::marker::PhantomData; + +struct TransformLut3x3Sse< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut3x3Sse +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "sse4.1")] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let value_scale = unsafe { _mm_set1_ps(((1 << BIT_DEPTH) - 1) as f32) }; + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_sse( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + unsafe { + let mut r = _mm_mul_ps(v.v, value_scale); + r = _mm_max_ps(r, _mm_setzero_ps()); + r = _mm_min_ps(r, value_scale); + let jvz = _mm_cvtps_epi32(r); + + let x = _mm_extract_epi32::<0>(jvz); + let y = _mm_extract_epi32::<1>(jvz); + let z = _mm_extract_epi32::<2>(jvz); + + dst[dst_cn.r_i()] = (x as u32).as_(); + dst[dst_cn.g_i()] = (y as u32).as_(); + dst[dst_cn.b_i()] = (z as u32).as_(); + } + } else { + unsafe { + dst[dst_cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(v.v) as u32).as_(); + dst[dst_cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(v.v) as u32).as_(); + dst[dst_cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(v.v) as u32).as_(); + } + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3Sse< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearSse:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk(src, dst, Box::new(TetrahedralSse:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalSse:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticSse:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearSse:: {})); + } + } + } + } + Ok(()) + } +} + +pub(crate) struct SseLut3x3Factory {} + +impl Lut3x3Factory for SseLut3x3Factory { + fn make_transform_3x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Sync + Send> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if options.prefer_fixed_point && BIT_DEPTH < 16 { + let q: f32 = if T::FINITE { + ((1i32 << BIT_DEPTH as i32) - 1) as f32 + } else { + ((1i32 << 14i32) - 1) as f32 + }; + let lut = lut + .chunks_exact(3) + .map(|x| { + SseAlignedI16x4([ + (x[0] * q).round() as i16, + (x[1] * q).round() as i16, + (x[2] * q).round() as i16, + 0, + ]) + }) + .collect::>(); + return match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3SseQ0_15::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3SseQ0_15::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }; + } + let lut = lut + .chunks_exact(3) + .map(|x| SseAlignedF32([x[0], x[1], x[2], 0f32])) + .collect::>(); + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3Sse::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3Sse::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom2: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3_q0_15.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3_q0_15.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3_q0_15.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/sse/t_lut3_to_3_q0_15.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,236 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::BarycentricWeight; +use crate::conversions::sse::interpolator_q0_15::*; +use crate::transform::PointeeSizeExpressible; +use crate::{CmsError, DataColorSpace, InterpolationMethod, Layout, TransformExecutor}; +use num_traits::AsPrimitive; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::marker::PhantomData; + +pub(crate) struct TransformLut3x3SseQ0_15< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom2: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> + TransformLut3x3SseQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[allow(unused_unsafe)] + #[target_feature(enable = "sse4.1")] + #[inline(never)] + unsafe fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + unsafe { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let f_value_scale = _mm_set1_ps(1. / ((1 << 14i32) - 1) as f32); + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + let v_max_scale = if T::FINITE { + _mm_set1_epi16(((1i32 << BIT_DEPTH) - 1) as i16) + } else { + _mm_set1_epi16(((1i32 << 14i32) - 1) as i16) + }; + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3_sse( + &self.lut, + x.as_(), + y.as_(), + z.as_(), + self.weights.as_slice(), + ); + if T::FINITE { + let mut o = _mm_max_epi16(v.v, _mm_setzero_si128()); + o = _mm_min_epi16(o, v_max_scale); + let x = _mm_extract_epi16::<0>(o); + let y = _mm_extract_epi16::<1>(o); + let z = _mm_extract_epi16::<2>(o); + + dst[dst_cn.r_i()] = (x as u32).as_(); + dst[dst_cn.g_i()] = (y as u32).as_(); + dst[dst_cn.b_i()] = (z as u32).as_(); + } else { + let mut r = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(v.v)); + r = _mm_mul_ps(r, f_value_scale); + dst[dst_cn.r_i()] = f32::from_bits(_mm_extract_ps::<0>(r) as u32).as_(); + dst[dst_cn.g_i()] = f32::from_bits(_mm_extract_ps::<1>(r) as u32).as_(); + dst[dst_cn.b_i()] = f32::from_bits(_mm_extract_ps::<2>(r) as u32).as_(); + } + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3SseQ0_15< + T, + U, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + BINS, + BARYCENTRIC_BINS, + > +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + unsafe { + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + self.transform_chunk(src, dst, Box::new(TrilinearSseQ0_15:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + self.transform_chunk( + src, + dst, + Box::new(TetrahedralSseQ0_15:: {}), + ); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + self.transform_chunk(src, dst, Box::new(PyramidalSseQ0_15:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + self.transform_chunk(src, dst, Box::new(PrismaticSseQ0_15:: {})); + } + InterpolationMethod::Linear => { + self.transform_chunk(src, dst, Box::new(TrilinearSseQ0_15:: {})); + } + } + } + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,266 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::{BarycentricWeight, MultidimensionalInterpolation}; +use crate::conversions::lut_transforms::Lut3x3Factory; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) struct TransformLut3x3< + T, + U, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut3x3 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[inline(never)] + fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + + let value_scale = ((1 << BIT_DEPTH) - 1) as f32; + let max_value = ((1u32 << BIT_DEPTH) - 1).as_(); + + for (src, dst) in src + .chunks_exact(src_channels) + .zip(dst.chunks_exact_mut(dst_channels)) + { + let x = <() as LutBarycentricReduction>::reduce::( + src[src_cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[src_cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[src_cn.b_i()], + ); + + let a = if src_channels == 4 { + src[src_cn.a_i()] + } else { + max_value + }; + + let v = interpolator.inter3( + &self.lut, + &self.weights[x.as_()], + &self.weights[y.as_()], + &self.weights[z.as_()], + ); + if T::FINITE { + let r = v * value_scale + 0.5; + dst[dst_cn.r_i()] = r.v[0].min(value_scale).max(0.).as_(); + dst[dst_cn.g_i()] = r.v[1].min(value_scale).max(0.).as_(); + dst[dst_cn.b_i()] = r.v[2].min(value_scale).max(0.).as_(); + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } else { + dst[dst_cn.r_i()] = v.v[0].as_(); + dst[dst_cn.g_i()] = v.v[1].as_(); + dst[dst_cn.b_i()] = v.v[2].as_(); + if dst_channels == 4 { + dst[dst_cn.a_i()] = a; + } + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x3 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let src_cn = Layout::from(SRC_LAYOUT); + let src_channels = src_cn.channels(); + + let dst_cn = Layout::from(DST_LAYOUT); + let dst_channels = dst_cn.channels(); + if src.len() % src_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % dst_channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / src_channels; + let dst_chunks = dst.len() / dst_channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + use crate::conversions::interpolator::Trilinear; + self.transform_chunk(src, dst, Box::new(Trilinear:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + use crate::conversions::interpolator::Tetrahedral; + self.transform_chunk(src, dst, Box::new(Tetrahedral:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + use crate::conversions::interpolator::Pyramidal; + self.transform_chunk(src, dst, Box::new(Pyramidal:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + use crate::conversions::interpolator::Prismatic; + self.transform_chunk(src, dst, Box::new(Prismatic:: {})); + } + InterpolationMethod::Linear => { + use crate::conversions::interpolator::Trilinear; + self.transform_chunk(src, dst, Box::new(Trilinear:: {})); + } + } + } + + Ok(()) + } +} + +pub(crate) struct DefaultLut3x3Factory {} + +impl Lut3x3Factory for DefaultLut3x3Factory { + fn make_transform_3x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const SRC_LAYOUT: u8, + const DST_LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Send + Sync> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x3::< + T, + u8, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x3::< + T, + u16, + SRC_LAYOUT, + DST_LAYOUT, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_4.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut3_to_4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,274 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::LutBarycentricReduction; +use crate::conversions::interpolator::{BarycentricWeight, MultidimensionalInterpolation}; +use crate::transform::PointeeSizeExpressible; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + TransformExecutor, TransformOptions, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) struct TransformLut3x4< + T, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + pub(crate) lut: Vec, + pub(crate) _phantom: PhantomData, + pub(crate) _phantom1: PhantomData, + pub(crate) interpolation_method: InterpolationMethod, + pub(crate) weights: Box<[BarycentricWeight; BINS]>, + pub(crate) color_space: DataColorSpace, + pub(crate) is_linear: bool, +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut3x4 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[inline(never)] + fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + + let value_scale = ((1 << BIT_DEPTH) - 1) as f32; + + for (src, dst) in src.chunks_exact(channels).zip(dst.chunks_exact_mut(4)) { + let x = <() as LutBarycentricReduction>::reduce::( + src[cn.r_i()], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[cn.g_i()], + ); + let z = <() as LutBarycentricReduction>::reduce::( + src[cn.b_i()], + ); + + let v = interpolator.inter4( + &self.lut, + &self.weights[x.as_()], + &self.weights[y.as_()], + &self.weights[z.as_()], + ); + if T::FINITE { + let r = v * value_scale + 0.5; + dst[0] = r.v[0].min(value_scale).max(0.).as_(); + dst[1] = r.v[1].min(value_scale).max(0.).as_(); + dst[2] = r.v[2].min(value_scale).max(0.).as_(); + dst[3] = r.v[3].min(value_scale).max(0.).as_(); + } else { + dst[0] = v.v[0].as_(); + dst[1] = v.v[1].as_(); + dst[2] = v.v[2].as_(); + dst[3] = v.v[3].as_(); + } + } + } +} + +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut3x4 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / channels; + let dst_chunks = dst.len() / 4; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + use crate::conversions::interpolator::Trilinear; + self.transform_chunk(src, dst, Box::new(Trilinear:: {})); + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + use crate::conversions::interpolator::Tetrahedral; + self.transform_chunk(src, dst, Box::new(Tetrahedral:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + use crate::conversions::interpolator::Pyramidal; + self.transform_chunk(src, dst, Box::new(Pyramidal:: {})); + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + use crate::conversions::interpolator::Prismatic; + self.transform_chunk(src, dst, Box::new(Prismatic:: {})); + } + InterpolationMethod::Linear => { + use crate::conversions::interpolator::Trilinear; + self.transform_chunk(src, dst, Box::new(Trilinear:: {})); + } + } + } + + Ok(()) + } +} + +pub(crate) fn make_transform_3x4< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, +>( + layout: Layout, + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, +) -> Box + Sync + Send> +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, +{ + match layout { + Layout::Rgb => match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x4::< + T, + u8, + { Layout::Rgb as u8 }, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x4::< + T, + u16, + { Layout::Rgb as u8 }, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }, + Layout::Rgba => match options.barycentric_weight_scale { + BarycentricWeightScale::Low => Box::new(TransformLut3x4::< + T, + u8, + { Layout::Rgba as u8 }, + GRID_SIZE, + BIT_DEPTH, + 256, + 256, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }), + #[cfg(feature = "options")] + BarycentricWeightScale::High => Box::new(TransformLut3x4::< + T, + u16, + { Layout::Rgba as u8 }, + GRID_SIZE, + BIT_DEPTH, + 65536, + 65536, + > { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }), + }, + _ => unimplemented!(), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut4_to_3.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut4_to_3.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut4_to_3.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/transform_lut4_to_3.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,351 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::interpolator::*; +use crate::conversions::lut_transforms::Lut4x3Factory; +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd, m_clamp}; +use crate::{ + BarycentricWeightScale, CmsError, DataColorSpace, InterpolationMethod, Layout, + PointeeSizeExpressible, TransformExecutor, TransformOptions, Vector3f, +}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +pub(crate) trait Vector3fCmykLerp { + fn interpolate(a: Vector3f, b: Vector3f, t: f32, scale: f32) -> Vector3f; +} + +#[allow(unused)] +#[derive(Copy, Clone, Default)] +struct DefaultVector3fLerp; + +impl Vector3fCmykLerp for DefaultVector3fLerp { + #[inline(always)] + fn interpolate(a: Vector3f, b: Vector3f, t: f32, scale: f32) -> Vector3f { + let t = Vector3f::from(t); + let inter = a.neg_mla(a, t).mla(b, t); + let mut new_vec = Vector3f::from(0.5).mla(inter, Vector3f::from(scale)); + new_vec.v[0] = m_clamp(new_vec.v[0], 0.0, scale); + new_vec.v[1] = m_clamp(new_vec.v[1], 0.0, scale); + new_vec.v[2] = m_clamp(new_vec.v[2], 0.0, scale); + new_vec + } +} + +#[allow(unused)] +#[derive(Copy, Clone, Default)] +pub(crate) struct NonFiniteVector3fLerp; + +impl Vector3fCmykLerp for NonFiniteVector3fLerp { + #[inline(always)] + fn interpolate(a: Vector3f, b: Vector3f, t: f32, _: f32) -> Vector3f { + let t = Vector3f::from(t); + a.neg_mla(a, t).mla(b, t) + } +} + +#[allow(unused)] +#[derive(Copy, Clone, Default)] +pub(crate) struct NonFiniteVector3fLerpUnbound; + +impl Vector3fCmykLerp for NonFiniteVector3fLerpUnbound { + #[inline(always)] + fn interpolate(a: Vector3f, b: Vector3f, t: f32, _: f32) -> Vector3f { + let t = Vector3f::from(t); + a.neg_mla(a, t).mla(b, t) + } +} + +#[allow(unused)] +struct TransformLut4To3< + T, + U, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> { + lut: Vec, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: InterpolationMethod, + weights: Box<[BarycentricWeight; BINS]>, + color_space: DataColorSpace, + is_linear: bool, +} + +#[allow(unused)] +impl< + T: Copy + AsPrimitive + Default, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformLut4To3 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + #[inline(never)] + fn transform_chunk( + &self, + src: &[T], + dst: &mut [T], + interpolator: Box, + ) { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + let grid_size = GRID_SIZE as i32; + let grid_size3 = grid_size * grid_size * grid_size; + + let value_scale = ((1 << BIT_DEPTH) - 1) as f32; + let max_value = ((1 << BIT_DEPTH) - 1u32).as_(); + + for (src, dst) in src.chunks_exact(4).zip(dst.chunks_exact_mut(channels)) { + let c = <() as LutBarycentricReduction>::reduce::( + src[0], + ); + let m = <() as LutBarycentricReduction>::reduce::( + src[1], + ); + let y = <() as LutBarycentricReduction>::reduce::( + src[2], + ); + let k = <() as LutBarycentricReduction>::reduce::( + src[3], + ); + + let k_weights = self.weights[k.as_()]; + + let w: i32 = k_weights.x; + let w_n: i32 = k_weights.x_n; + let t: f32 = k_weights.w; + + let table1 = &self.lut[(w * grid_size3 * 3) as usize..]; + let table2 = &self.lut[(w_n * grid_size3 * 3) as usize..]; + + let r1 = interpolator.inter3( + table1, + &self.weights[c.as_()], + &self.weights[m.as_()], + &self.weights[y.as_()], + ); + let r2 = interpolator.inter3( + table2, + &self.weights[c.as_()], + &self.weights[m.as_()], + &self.weights[y.as_()], + ); + let r = Interpolation::interpolate(r1, r2, t, value_scale); + dst[cn.r_i()] = r.v[0].as_(); + dst[cn.g_i()] = r.v[1].as_(); + dst[cn.b_i()] = r.v[2].as_(); + if channels == 4 { + dst[cn.a_i()] = max_value; + } + } + } +} + +#[allow(unused)] +impl< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible, + U: AsPrimitive, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + const BINS: usize, + const BARYCENTRIC_BINS: usize, +> TransformExecutor + for TransformLut4To3 +where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, +{ + fn transform(&self, src: &[T], dst: &mut [T]) -> Result<(), CmsError> { + let cn = Layout::from(LAYOUT); + let channels = cn.channels(); + if src.len() % 4 != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + if dst.len() % channels != 0 { + return Err(CmsError::LaneMultipleOfChannels); + } + let src_chunks = src.len() / 4; + let dst_chunks = dst.len() / channels; + if src_chunks != dst_chunks { + return Err(CmsError::LaneSizeMismatch); + } + + if self.color_space == DataColorSpace::Lab + || (self.is_linear && self.color_space == DataColorSpace::Rgb) + || self.color_space == DataColorSpace::Xyz + { + if T::FINITE { + self.transform_chunk::( + src, + dst, + Box::new(Trilinear:: {}), + ); + } else { + self.transform_chunk::( + src, + dst, + Box::new(Trilinear:: {}), + ); + } + } else { + match self.interpolation_method { + #[cfg(feature = "options")] + InterpolationMethod::Tetrahedral => { + if T::FINITE { + self.transform_chunk::( + src, + dst, + Box::new(Tetrahedral:: {}), + ); + } else { + self.transform_chunk::( + src, + dst, + Box::new(Tetrahedral:: {}), + ); + } + } + #[cfg(feature = "options")] + InterpolationMethod::Pyramid => { + if T::FINITE { + self.transform_chunk::( + src, + dst, + Box::new(Pyramidal:: {}), + ); + } else { + self.transform_chunk::( + src, + dst, + Box::new(Pyramidal:: {}), + ); + } + } + #[cfg(feature = "options")] + InterpolationMethod::Prism => { + if T::FINITE { + self.transform_chunk::( + src, + dst, + Box::new(Prismatic:: {}), + ); + } else { + self.transform_chunk::( + src, + dst, + Box::new(Prismatic:: {}), + ); + } + } + InterpolationMethod::Linear => { + if T::FINITE { + self.transform_chunk::( + src, + dst, + Box::new(Trilinear:: {}), + ); + } else { + self.transform_chunk::( + src, + dst, + Box::new(Trilinear:: {}), + ); + } + } + } + } + + Ok(()) + } +} + +#[allow(dead_code)] +pub(crate) struct DefaultLut4x3Factory {} + +#[allow(dead_code)] +impl Lut4x3Factory for DefaultLut4x3Factory { + fn make_transform_4x3< + T: Copy + AsPrimitive + Default + PointeeSizeExpressible + 'static + Send + Sync, + const LAYOUT: u8, + const GRID_SIZE: usize, + const BIT_DEPTH: usize, + >( + lut: Vec, + options: TransformOptions, + color_space: DataColorSpace, + is_linear: bool, + ) -> Box + Sync + Send> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + match options.barycentric_weight_scale { + BarycentricWeightScale::Low => { + Box::new( + TransformLut4To3:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_ranged_256::(), + color_space, + is_linear, + }, + ) + } + #[cfg(feature = "options")] + BarycentricWeightScale::High => { + Box::new( + TransformLut4To3:: { + lut, + _phantom: PhantomData, + _phantom1: PhantomData, + interpolation_method: options.interpolation_method, + weights: BarycentricWeight::::create_binned::(), + color_space, + is_linear, + }, + ) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/xyz_lab.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/xyz_lab.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/conversions/xyz_lab.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/conversions/xyz_lab.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::{CmsError, InPlaceStage, Lab, Xyz}; + +#[derive(Default)] +pub(crate) struct StageLabToXyz {} + +impl InPlaceStage for StageLabToXyz { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + for dst in dst.chunks_exact_mut(3) { + let lab = Lab::new(dst[0], dst[1], dst[2]); + let xyz = lab.to_pcs_xyz(); + dst[0] = xyz.x; + dst[1] = xyz.y; + dst[2] = xyz.z; + } + Ok(()) + } +} + +#[derive(Default)] +pub(crate) struct StageXyzToLab {} + +impl InPlaceStage for StageXyzToLab { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError> { + for dst in dst.chunks_exact_mut(3) { + let xyz = Xyz::new(dst[0], dst[1], dst[2]); + let lab = Lab::from_pcs_xyz(xyz); + dst[0] = lab.l; + dst[1] = lab.a; + dst[2] = lab.b; + } + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/dat.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dat.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/dat.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dat.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,154 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::CmsError; +use crate::writer::write_u16_be; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[repr(C)] +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)] +pub struct ColorDateTime { + pub year: u16, + pub month: u16, + pub day_of_the_month: u16, + pub hours: u16, + pub minutes: u16, + pub seconds: u16, +} + +fn is_leap(year: i32) -> bool { + (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) +} + +fn days_in_month(year: i32, month: i32) -> i32 { + match month { + 1 => 31, + 2 => { + if is_leap(year) { + 29 + } else { + 28 + } + } + 3 => 31, + 4 => 30, + 5 => 31, + 6 => 30, + 7 => 31, + 8 => 31, + 9 => 30, + 10 => 31, + 11 => 30, + 12 => 31, + _ => unreachable!("Unknown month"), + } +} + +impl ColorDateTime { + /// Parses slice for date time + pub fn new_from_slice(slice: &[u8]) -> Result { + if slice.len() != 12 { + return Err(CmsError::InvalidProfile); + } + let year = u16::from_be_bytes([slice[0], slice[1]]); + let month = u16::from_be_bytes([slice[2], slice[3]]); + let day_of_the_month = u16::from_be_bytes([slice[4], slice[5]]); + let hours = u16::from_be_bytes([slice[6], slice[7]]); + let minutes = u16::from_be_bytes([slice[8], slice[9]]); + let seconds = u16::from_be_bytes([slice[10], slice[11]]); + Ok(ColorDateTime { + year, + month, + day_of_the_month, + hours, + minutes, + seconds, + }) + } + + /// Creates a new `ColorDateTime` from the current system time (UTC) + pub fn now() -> Self { + let now = match SystemTime::now().duration_since(UNIX_EPOCH) { + Ok(v) => v, + Err(_) => return Self::default(), + }; + let mut days = (now.as_secs() / 86_400) as i64; + let secs_of_day = (now.as_secs() % 86_400) as i64; + + let mut year = 1970; + loop { + let year_days = if is_leap(year) { 366 } else { 365 }; + if days >= year_days { + days -= year_days; + year += 1; + } else { + break; + } + } + + let mut month = 1; + loop { + let mdays = days_in_month(year, month); + if days >= mdays as i64 { + days -= mdays as i64; + month += 1; + } else { + break; + } + } + let day = days + 1; // days from zero based to 1 base + + let hour = secs_of_day / 3600; + let min = (secs_of_day % 3600) / 60; + let sec = secs_of_day % 60; + Self { + year: year as u16, + month: month as u16, + day_of_the_month: day as u16, + hours: hour as u16, + minutes: min as u16, + seconds: sec as u16, + } + } + + #[inline] + pub(crate) fn encode(&self, into: &mut Vec) { + let year = self.year; + let month = self.month; + let day_of_the_month = self.day_of_the_month; + let hours = self.hours; + let minutes = self.minutes; + let seconds = self.seconds; + write_u16_be(into, year); + write_u16_be(into, month); + write_u16_be(into, day_of_the_month); + write_u16_be(into, hours); + write_u16_be(into, minutes); + write_u16_be(into, seconds); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/defaults.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/defaults.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/defaults.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/defaults.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,604 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::chad::BRADFORD_D; +use crate::cicp::create_rec709_parametric; +use crate::trc::{ToneReprCurve, curve_from_gamma}; +use crate::{ + CicpColorPrimaries, CicpProfile, ColorPrimaries, ColorProfile, DataColorSpace, + LocalizableString, LutMultidimensionalType, LutWarehouse, Matrix3d, MatrixCoefficients, + ProfileClass, ProfileText, RenderingIntent, TransferCharacteristics, Vector3, XyY, +}; +use pxfm::{copysignk, exp, floor, pow}; + +/// From lcms: `cmsWhitePointFromTemp` +/// tempK must be >= 4000. and <= 25000. +/// Invalid values of tempK will return +/// (x,y,Y) = (-1.0, -1.0, -1.0) +/// similar to argyll: `icx_DTEMP2XYZ()` +const fn white_point_from_temperature(temp_k: i32) -> XyY { + let mut white_point = XyY { + x: 0., + y: 0., + yb: 0., + }; + // No optimization provided. + let temp_k = temp_k as f64; // Square + let temp_k2 = temp_k * temp_k; // Cube + let temp_k3 = temp_k2 * temp_k; + // For correlated color temperature (T) between 4000K and 7000K: + let x = if temp_k > 4000.0 && temp_k <= 7000.0 { + -4.6070 * (1E9 / temp_k3) + 2.9678 * (1E6 / temp_k2) + 0.09911 * (1E3 / temp_k) + 0.244063 + } else if temp_k > 7000.0 && temp_k <= 25000.0 { + -2.0064 * (1E9 / temp_k3) + 1.9018 * (1E6 / temp_k2) + 0.24748 * (1E3 / temp_k) + 0.237040 + } else { + // or for correlated color temperature (T) between 7000K and 25000K: + // Invalid tempK + white_point.x = -1.0; + white_point.y = -1.0; + white_point.yb = -1.0; + debug_assert!(false, "invalid temp"); + return white_point; + }; + // Obtain y(x) + let y = -3.000 * (x * x) + 2.870 * x - 0.275; + // wave factors (not used, but here for futures extensions) + // let M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y); + // let M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y); + // Fill white_point struct + white_point.x = x; + white_point.y = y; + white_point.yb = 1.0; + white_point +} + +pub const WHITE_POINT_D50: XyY = white_point_from_temperature(5003); +pub const WHITE_POINT_D60: XyY = white_point_from_temperature(6000); +pub const WHITE_POINT_D65: XyY = white_point_from_temperature(6504); +pub const WHITE_POINT_DCI_P3: XyY = white_point_from_temperature(6300); + +// https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-F.pdf +// Perceptual Quantization / SMPTE standard ST.2084 +#[inline] +const fn pq_curve(x: f64) -> f64 { + const M1: f64 = 2610.0 / 16384.0; + const M2: f64 = (2523.0 / 4096.0) * 128.0; + const C1: f64 = 3424.0 / 4096.0; + const C2: f64 = (2413.0 / 4096.0) * 32.0; + const C3: f64 = (2392.0 / 4096.0) * 32.0; + + if x == 0.0 { + return 0.0; + } + let sign = x; + let x = x.abs(); + + let xpo = pow(x, 1.0 / M2); + let num = (xpo - C1).max(0.0); + let den = C2 - C3 * xpo; + let res = pow(num / den, 1.0 / M1); + + copysignk(res, sign) +} + +pub(crate) const fn build_trc_table_pq() -> [u16; 4096] { + let mut table = [0u16; 4096]; + + const NUM_ENTRIES: usize = 4096; + let mut i = 0usize; + while i < NUM_ENTRIES { + let x: f64 = i as f64 / (NUM_ENTRIES - 1) as f64; + let y: f64 = pq_curve(x); + let mut output: f64; + output = y * 65535.0 + 0.5; + if output > 65535.0 { + output = 65535.0 + } + if output < 0.0 { + output = 0.0 + } + table[i] = floor(output) as u16; + i += 1; + } + table +} + +pub(crate) const fn build_trc_table_hlg() -> [u16; 4096] { + let mut table = [0u16; 4096]; + + const NUM_ENTRIES: usize = 4096; + let mut i = 0usize; + while i < NUM_ENTRIES { + let x: f64 = i as f64 / (NUM_ENTRIES - 1) as f64; + let y: f64 = hlg_curve(x); + let mut output: f64; + output = y * 65535.0 + 0.5; + if output > 65535.0 { + output = 65535.0 + } + if output < 0.0 { + output = 0.0 + } + table[i] = floor(output) as u16; + i += 1; + } + table +} + +// https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-F.pdf +// Hybrid Log-Gamma +const fn hlg_curve(x: f64) -> f64 { + const BETA: f64 = 0.04; + const RA: f64 = 5.591816309728916; // 1.0 / A where A = 0.17883277 + const B: f64 = 0.28466892; // 1.0 - 4.0 * A + const C: f64 = 0.5599107295; // 0,5 –aln(4a) + + let e = (x * (1.0 - BETA) + BETA).max(0.0); + + if e == 0.0 { + return 0.0; + } + + let sign = e.abs(); + + let res = if e <= 0.5 { + e * e / 3.0 + } else { + (exp((e - C) * RA) + B) / 12.0 + }; + + copysignk(res, sign) +} + +/// Perceptual Quantizer Lookup table +pub const PQ_LUT_TABLE: [u16; 4096] = build_trc_table_pq(); +/// Hybrid Log Gamma Lookup table +pub const HLG_LUT_TABLE: [u16; 4096] = build_trc_table_hlg(); + +impl ColorProfile { + const SRGB_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D65, ColorPrimaries::BT_709); + + const DISPLAY_P3_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D65, ColorPrimaries::SMPTE_432); + + const ADOBE_RGB_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D65, ColorPrimaries::ADOBE_RGB); + + const DCI_P3_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_DCI_P3, ColorPrimaries::DCI_P3); + + const PRO_PHOTO_RGB_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D50, ColorPrimaries::PRO_PHOTO_RGB); + + const BT2020_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D65, ColorPrimaries::BT_2020); + + const ACES_2065_1_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D60, ColorPrimaries::ACES_2065_1); + + const ACES_CG_COLORANTS: Matrix3d = + ColorProfile::colorants_matrix(WHITE_POINT_D60, ColorPrimaries::ACES_CG); + + #[inline] + fn basic_rgb_profile() -> ColorProfile { + ColorProfile { + profile_class: ProfileClass::DisplayDevice, + rendering_intent: RenderingIntent::Perceptual, + color_space: DataColorSpace::Rgb, + pcs: DataColorSpace::Xyz, + chromatic_adaptation: Some(BRADFORD_D), + white_point: WHITE_POINT_D50.to_xyzd(), + ..Default::default() + } + } + + /// Creates new profile from CICP + pub fn new_from_cicp(cicp_color_primaries: CicpProfile) -> ColorProfile { + let mut basic = ColorProfile::basic_rgb_profile(); + basic.update_rgb_colorimetry_from_cicp(cicp_color_primaries); + basic + } + + /// Creates new sRGB profile + pub fn new_srgb() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::SRGB_COLORANTS); + + let curve = + ToneReprCurve::Parametric(vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Bt709, + transfer_characteristics: TransferCharacteristics::Srgb, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "sRGB IEC61966-2.1".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Adobe RGB profile + pub fn new_adobe_rgb() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::ADOBE_RGB_COLORANTS); + + let curve = curve_from_gamma(2.19921875f32); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.white_point = WHITE_POINT_D50.to_xyzd(); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Adobe RGB 1998".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Display P3 profile + pub fn new_display_p3() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::DISPLAY_P3_COLORANTS); + + let curve = + ToneReprCurve::Parametric(vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Smpte431, + transfer_characteristics: TransferCharacteristics::Srgb, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Display P3".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Display P3 PQ profile + pub fn new_display_p3_pq() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::DISPLAY_P3_COLORANTS); + + let curve = ToneReprCurve::Lut(PQ_LUT_TABLE.to_vec()); + + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Smpte431, + transfer_characteristics: TransferCharacteristics::Smpte2084, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Display P3 PQ".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new DCI P3 profile + pub fn new_dci_p3() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::DCI_P3_COLORANTS); + + let curve = curve_from_gamma(2.6f32); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_DCI_P3.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Smpte432, + transfer_characteristics: TransferCharacteristics::Srgb, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "DCI P3".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new ProPhoto RGB profile + pub fn new_pro_photo_rgb() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::PRO_PHOTO_RGB_COLORANTS); + + let curve = curve_from_gamma(1.8f32); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D50.to_xyzd()); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "ProPhoto RGB".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Bt.2020 profile + pub fn new_bt2020() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::BT2020_COLORANTS); + + let curve = ToneReprCurve::Parametric(create_rec709_parametric().to_vec()); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Rec.2020".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Bt.2020 PQ profile + pub fn new_bt2020_pq() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::BT2020_COLORANTS); + + let curve = ToneReprCurve::Lut(PQ_LUT_TABLE.to_vec()); + + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Bt2020, + transfer_characteristics: TransferCharacteristics::Smpte2084, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Rec.2020 PQ".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Bt.2020 HLG profile + pub fn new_bt2020_hlg() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::BT2020_COLORANTS); + + let curve = ToneReprCurve::Lut(HLG_LUT_TABLE.to_vec()); + + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D65.to_xyzd()); + profile.cicp = Some(CicpProfile { + color_primaries: CicpColorPrimaries::Bt2020, + transfer_characteristics: TransferCharacteristics::Hlg, + matrix_coefficients: MatrixCoefficients::Bt709, + full_range: false, + }); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Rec.2020 HLG".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Monochrome profile + pub fn new_gray_with_gamma(gamma: f32) -> ColorProfile { + ColorProfile { + gray_trc: Some(curve_from_gamma(gamma)), + profile_class: ProfileClass::DisplayDevice, + rendering_intent: RenderingIntent::Perceptual, + color_space: DataColorSpace::Gray, + media_white_point: Some(WHITE_POINT_D65.to_xyzd()), + white_point: WHITE_POINT_D50.to_xyzd(), + chromatic_adaptation: Some(BRADFORD_D), + copyright: Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])), + ..Default::default() + } + } + + /// Creates new ACES 2065-1/AP0 profile + pub fn new_aces_aces_2065_1_linear() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::ACES_2065_1_COLORANTS); + + let curve = ToneReprCurve::Lut(vec![]); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D60.to_xyzd()); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "ACES 2065-1".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new ACEScg profile + pub fn new_aces_cg_linear() -> ColorProfile { + let mut profile = ColorProfile::basic_rgb_profile(); + profile.update_colorants(ColorProfile::ACES_CG_COLORANTS); + + let curve = ToneReprCurve::Lut(vec![]); + profile.red_trc = Some(curve.clone()); + profile.blue_trc = Some(curve.clone()); + profile.green_trc = Some(curve); + profile.media_white_point = Some(WHITE_POINT_D60.to_xyzd()); + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "ACEScg/AP1".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + profile + } + + /// Creates new Generic CIE LAB profile + pub fn new_lab() -> ColorProfile { + let mut profile = ColorProfile { + profile_class: ProfileClass::DisplayDevice, + rendering_intent: RenderingIntent::Perceptual, + color_space: DataColorSpace::Lab, + pcs: DataColorSpace::Xyz, + chromatic_adaptation: Some(BRADFORD_D), + white_point: WHITE_POINT_D50.to_xyzd(), + media_white_point: Some(WHITE_POINT_D65.to_xyzd()), + ..Default::default() + }; + + let b_to_a_lut = LutWarehouse::Multidimensional(LutMultidimensionalType { + num_input_channels: 3, + num_output_channels: 3, + grid_points: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + clut: None, + b_curves: vec![ + ToneReprCurve::Lut(vec![]), + ToneReprCurve::Lut(vec![]), + ToneReprCurve::Lut(vec![]), + ], + matrix: Matrix3d::IDENTITY, + a_curves: vec![], + m_curves: vec![], + bias: Vector3::default(), + }); + profile.lut_b_to_a_perceptual = Some(b_to_a_lut.clone()); + profile.lut_b_to_a_colorimetric = Some(b_to_a_lut); + + let a_to_b = LutWarehouse::Multidimensional(LutMultidimensionalType { + num_input_channels: 3, + num_output_channels: 3, + grid_points: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + clut: None, + b_curves: vec![ + ToneReprCurve::Lut(vec![]), + ToneReprCurve::Lut(vec![]), + ToneReprCurve::Lut(vec![]), + ], + matrix: Matrix3d::IDENTITY, + a_curves: vec![], + m_curves: vec![], + bias: Vector3::default(), + }); + profile.lut_a_to_b_colorimetric = Some(a_to_b.clone()); + profile.lut_a_to_b_perceptual = Some(a_to_b); + + profile.description = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Generic L*a*b* Profile".to_string(), + )])); + profile.copyright = Some(ProfileText::Localizable(vec![LocalizableString::new( + "en".to_string(), + "US".to_string(), + "Public Domain".to_string(), + )])); + + profile + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/dt_ucs.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dt_ucs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/dt_ucs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/dt_ucs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,359 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Xyz; +use crate::mlaf::mlaf; +use pxfm::{f_atan2f, f_powf, f_sincosf}; + +/// Darktable UCS JCH ( Darktable Uniform Color Space ) +#[derive(Copy, Clone, PartialOrd, PartialEq, Debug)] +pub struct DtUchJch { + pub j: f32, + pub c: f32, + pub h: f32, +} + +/// Darktable UCS HSB ( Darktable Uniform Color Space ) +#[derive(Copy, Clone, PartialOrd, PartialEq, Debug)] +pub struct DtUchHsb { + pub h: f32, + pub s: f32, + pub b: f32, +} + +/// Darktable HCB ( Darktable Uniform Color Space ) +#[derive(Copy, Clone, PartialOrd, PartialEq, Debug)] +pub struct DtUchHcb { + pub h: f32, + pub c: f32, + pub b: f32, +} + +const DT_UCS_L_STAR_RANGE: f32 = 2.098883786377; + +#[inline] +fn y_to_dt_ucs_l_star(y: f32) -> f32 { + let y_hat = f_powf(y, 0.631651345306265); + DT_UCS_L_STAR_RANGE * y_hat / (y_hat + 1.12426773749357) +} + +#[inline] +fn dt_ucs_l_star_to_y(x: f32) -> f32 { + f_powf( + 1.12426773749357 * x / (DT_UCS_L_STAR_RANGE - x), + 1.5831518565279648, + ) +} + +const L_WHITE: f32 = 0.98805060; + +#[inline] +fn dt_ucs_luv_to_ucs_jch( + l_star: f32, + l_white: f32, + u_star_prime: f32, + v_star_prime: f32, +) -> DtUchJch { + let m2: f32 = mlaf(u_star_prime * u_star_prime, v_star_prime, v_star_prime); // square of colorfulness M + + // should be JCH[0] = powf(L_star / L_white), cz) but we treat only the case where cz = 1 + let j = l_star / l_white; + let c = + 15.932993652962535 * f_powf(l_star, 0.6523997524738018) * f_powf(m2, 0.6007557017508491) + / l_white; + let h = f_atan2f(v_star_prime, u_star_prime); + DtUchJch::new(j, c, h) +} + +#[inline] +fn dt_ucs_xy_to_uv(x: f32, y: f32) -> (f32, f32) { + const X_C: [f32; 3] = [-0.783941002840055, 0.745273540913283, 0.318707282433486]; + const Y_C: [f32; 3] = [0.277512987809202, -0.205375866083878, 2.16743692732158]; + const BIAS: [f32; 3] = [0.153836578598858, -0.165478376301988, 0.291320554395942]; + + let mut u_c = mlaf(mlaf(BIAS[0], Y_C[0], y), X_C[0], x); + let mut v_c = mlaf(mlaf(BIAS[1], Y_C[1], y), X_C[1], x); + let d_c = mlaf(mlaf(BIAS[2], Y_C[2], y), X_C[2], x); + + let div = if d_c >= 0.0 { + d_c.max(f32::MIN) + } else { + d_c.min(-f32::MIN) + }; + u_c /= div; + v_c /= div; + + const STAR_C: [f32; 2] = [1.39656225667, 1.4513954287]; + const STAR_HF_C: [f32; 2] = [1.49217352929, 1.52488637914]; + + let u_star = STAR_C[0] * u_c / (u_c.abs() + STAR_HF_C[0]); + let v_star = STAR_C[1] * v_c / (v_c.abs() + STAR_HF_C[1]); + + // The following is equivalent to a 2D matrix product + let u_star_prime = mlaf(-1.124983854323892 * u_star, -0.980483721769325, v_star); + let v_star_prime = mlaf(1.86323315098672 * u_star, 1.971853092390862, v_star); + (u_star_prime, v_star_prime) +} + +impl DtUchJch { + #[inline] + pub fn new(j: f32, c: f32, h: f32) -> DtUchJch { + DtUchJch { j, c, h } + } + + #[inline] + pub fn from_xyz(xyz: Xyz) -> DtUchJch { + DtUchJch::from_xyy(xyz.to_xyy()) + } + + #[inline] + pub fn to_xyz(&self) -> Xyz { + let xyy = self.to_xyy(); + Xyz::from_xyy(xyy) + } + + #[inline] + pub fn from_xyy(xyy: [f32; 3]) -> DtUchJch { + let l_star = y_to_dt_ucs_l_star(xyy[2]); + // let l_white = y_to_dt_ucs_l_star(1.); + + let (u_star_prime, v_star_prime) = dt_ucs_xy_to_uv(xyy[0], xyy[1]); + dt_ucs_luv_to_ucs_jch(l_star, L_WHITE, u_star_prime, v_star_prime) + } + + #[inline] + pub fn to_xyy(&self) -> [f32; 3] { + // let l_white: f32 = y_to_dt_ucs_l_star(1.0); + let l_star = (self.j * L_WHITE).max(0.0).min(2.09885); + let m = if l_star != 0. { + f_powf( + self.c * L_WHITE / (15.932993652962535 * f_powf(l_star, 0.6523997524738018)), + 0.8322850678616855, + ) + } else { + 0. + }; + + let sin_cos_h = f_sincosf(self.h); + let u_star_prime = m * sin_cos_h.1; + let v_star_prime = m * sin_cos_h.0; + + // The following is equivalent to a 2D matrix product + let u_star = mlaf( + -5.037522385190711 * u_star_prime, + -2.504856328185843, + v_star_prime, + ); + let v_star = mlaf( + 4.760029407436461 * u_star_prime, + 2.874012963239247, + v_star_prime, + ); + + const F: [f32; 2] = [1.39656225667, 1.4513954287]; + const HF: [f32; 2] = [1.49217352929, 1.52488637914]; + + let u_c = -HF[0] * u_star / (u_star.abs() - F[0]); + let v_c = -HF[1] * v_star / (v_star.abs() - F[1]); + + const U_C: [f32; 3] = [0.167171472114775, -0.150959086409163, 0.940254742367256]; + const V_C: [f32; 3] = [0.141299802443708, -0.155185060382272, 1.000000000000000]; + const BIAS: [f32; 3] = [ + -0.00801531300850582, + -0.00843312433578007, + -0.0256325967652889, + ]; + + let mut x = mlaf(mlaf(BIAS[0], V_C[0], v_c), U_C[0], u_c); + let mut y = mlaf(mlaf(BIAS[1], V_C[1], v_c), U_C[1], u_c); + let d = mlaf(mlaf(BIAS[2], V_C[2], v_c), U_C[2], u_c); + + let div = if d >= 0.0 { + d.max(f32::MIN) + } else { + d.min(-f32::MIN) + }; + x /= div; + y /= div; + let yb = dt_ucs_l_star_to_y(l_star); + [x, y, yb] + } +} + +impl DtUchHsb { + #[inline] + pub fn new(h: f32, s: f32, b: f32) -> DtUchHsb { + DtUchHsb { h, s, b } + } + + #[inline] + pub fn from_jch(jch: DtUchJch) -> DtUchHsb { + let b = jch.j * (f_powf(jch.c, 1.33654221029386) + 1.); + let s = if b > 0. { jch.c / b } else { 0. }; + let h = jch.h; + DtUchHsb::new(h, s, b) + } + + #[inline] + pub fn to_jch(&self) -> DtUchJch { + let h = self.h; + let c = self.s * self.b; + let j = self.b / (f_powf(c, 1.33654221029386) + 1.); + DtUchJch::new(j, c, h) + } +} + +impl DtUchHcb { + #[inline] + pub fn new(h: f32, c: f32, b: f32) -> DtUchHcb { + DtUchHcb { h, c, b } + } + + #[inline] + pub fn from_jch(jch: DtUchJch) -> DtUchHcb { + let b = jch.j * (f_powf(jch.c, 1.33654221029386) + 1.); + let c = jch.c; + let h = jch.h; + DtUchHcb::new(h, c, b) + } + + #[inline] + pub fn to_jch(&self) -> DtUchJch { + let h = self.h; + let c = self.c; + let j = self.b / (f_powf(self.c, 1.33654221029386) + 1.); + DtUchJch::new(j, c, h) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_darktable_ucs_jch() { + let xyy = [0.4, 0.2, 0.5]; + let ucs = DtUchJch::from_xyy(xyy); + let xyy_rev = ucs.to_xyy(); + assert!( + (xyy[0] - xyy_rev[0]).abs() < 1e-5, + "Expected {}, got {}", + xyy[0], + xyy_rev[0] + ); + assert!( + (xyy[1] - xyy_rev[1]).abs() < 1e-5, + "Expected {}, got {}", + xyy[1], + xyy_rev[1] + ); + assert!( + (xyy[2] - xyy_rev[2]).abs() < 1e-5, + "Expected {}, got {}", + xyy[2], + xyy_rev[2] + ); + } + + #[test] + fn test_darktable_hsb() { + let jch = DtUchJch::new(0.3, 0.6, 0.4); + let hsb = DtUchHsb::from_jch(jch); + let r_jch = hsb.to_jch(); + + assert!( + (r_jch.j - jch.j).abs() < 1e-5, + "Expected {}, got {}", + jch.j, + r_jch.j + ); + assert!( + (r_jch.c - jch.c).abs() < 1e-5, + "Expected {}, got {}", + jch.c, + r_jch.c + ); + assert!( + (r_jch.h - jch.h).abs() < 1e-5, + "Expected {}, got {}", + jch.h, + r_jch.h + ); + } + + #[test] + fn test_darktable_hcb() { + let jch = DtUchJch::new(0.3, 0.6, 0.4); + let hcb = DtUchHcb::from_jch(jch); + let r_jch = hcb.to_jch(); + + assert!( + (r_jch.j - jch.j).abs() < 1e-5, + "Expected {}, got {}", + jch.j, + r_jch.j + ); + assert!( + (r_jch.c - jch.c).abs() < 1e-5, + "Expected {}, got {}", + jch.c, + r_jch.c + ); + assert!( + (r_jch.h - jch.h).abs() < 1e-5, + "Expected {}, got {}", + jch.h, + r_jch.h + ); + } + + #[test] + fn test_darktable_ucs_jch_from_xyz() { + let xyz = Xyz::new(0.4, 0.2, 0.5); + let ucs = DtUchJch::from_xyz(xyz); + let xyy_rev = ucs.to_xyz(); + assert!( + (xyz.x - xyz.x).abs() < 1e-5, + "Expected {}, got {}", + xyz.x, + xyy_rev.x + ); + assert!( + (xyz.y - xyz.y).abs() < 1e-5, + "Expected {}, got {}", + xyz.y, + xyy_rev.y + ); + assert!( + (xyz.z - xyz.z).abs() < 1e-5, + "Expected {}, got {}", + xyz.z, + xyy_rev.z + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/err.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/err.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/err.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/err.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::RenderingIntent; +use std::error::Error; +use std::fmt::Display; + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +pub struct MalformedSize { + pub size: usize, + pub expected: usize, +} + +#[derive(Debug, Clone, PartialOrd, PartialEq)] +pub enum CmsError { + LaneSizeMismatch, + LaneMultipleOfChannels, + InvalidProfile, + InvalidTrcCurve, + InvalidCicp, + CurveLutIsTooLarge, + ParametricCurveZeroDivision, + InvalidRenderingIntent, + DivisionByZero, + UnsupportedColorPrimaries(u8), + UnsupportedTrc(u8), + InvalidLayout, + UnsupportedProfileConnection, + BuildTransferFunction, + UnsupportedChannelConfiguration, + UnknownTag(u32), + UnknownTagTypeDefinition(u32), + UnsupportedLutRenderingIntent(RenderingIntent), + InvalidAtoBLut, + OverflowingError, + LUTTablesInvalidKind, + MalformedClut(MalformedSize), + MalformedCurveLutTable(MalformedSize), + InvalidInksCountForProfile, + MalformedTrcCurve(String), + OutOfMemory(usize), + IncorrectlyFormedLut(String), +} + +impl Display for CmsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CmsError::LaneSizeMismatch => f.write_str("Lanes length must match"), + CmsError::LaneMultipleOfChannels => { + f.write_str("Lane length must not be multiple of channel count") + } + CmsError::InvalidProfile => f.write_str("Invalid ICC profile"), + CmsError::InvalidCicp => { + f.write_str("Invalid Code Independent point (CICP) in ICC profile") + } + CmsError::InvalidTrcCurve => f.write_str("Invalid TRC curve"), + CmsError::CurveLutIsTooLarge => f.write_str("Curve Lut is too large"), + CmsError::ParametricCurveZeroDivision => { + f.write_str("Parametric Curve definition causes division by zero") + } + CmsError::InvalidRenderingIntent => f.write_str("Invalid rendering intent"), + CmsError::DivisionByZero => f.write_str("Division by zero"), + CmsError::UnsupportedColorPrimaries(value) => { + f.write_fmt(format_args!("Unsupported color primaries, {value}")) + } + CmsError::UnsupportedTrc(value) => f.write_fmt(format_args!("Unsupported TRC {value}")), + CmsError::InvalidLayout => f.write_str("Invalid layout"), + CmsError::UnsupportedProfileConnection => f.write_str("Unsupported profile connection"), + CmsError::BuildTransferFunction => f.write_str("Can't reconstruct transfer function"), + CmsError::UnsupportedChannelConfiguration => { + f.write_str("Can't reconstruct channel configuration") + } + CmsError::UnknownTag(t) => f.write_fmt(format_args!("Unknown tag: {t}")), + CmsError::UnknownTagTypeDefinition(t) => { + f.write_fmt(format_args!("Unknown tag type definition: {t}")) + } + CmsError::UnsupportedLutRenderingIntent(intent) => f.write_fmt(format_args!( + "Can't find LUT for rendering intent: {intent:?}" + )), + CmsError::InvalidAtoBLut => f.write_str("Invalid A to B Lut"), + CmsError::OverflowingError => { + f.write_str("Overflowing was happen, that is not allowed") + } + CmsError::LUTTablesInvalidKind => f.write_str("All LUT curves must have same kind"), + CmsError::MalformedClut(size) => { + f.write_fmt(format_args!("Invalid CLUT size: {size:?}")) + } + CmsError::MalformedCurveLutTable(size) => { + f.write_fmt(format_args!("Malformed curve LUT size: {size:?}")) + } + CmsError::InvalidInksCountForProfile => { + f.write_str("Invalid inks count for profile was provided") + } + CmsError::MalformedTrcCurve(str) => f.write_str(str), + CmsError::OutOfMemory(capacity) => f.write_fmt(format_args!( + "There is no enough memory to allocate {capacity} bytes" + )), + CmsError::IncorrectlyFormedLut(str) => f.write_str(str), + } + } +} + +impl Error for CmsError {} + +macro_rules! try_vec { + () => { + Vec::new() + }; + ($elem:expr; $n:expr) => {{ + let mut v = Vec::new(); + v.try_reserve_exact($n) + .map_err(|_| crate::err::CmsError::OutOfMemory($n))?; + v.resize($n, $elem); + v + }}; +} + +pub(crate) use try_vec; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/gamma.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamma.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/gamma.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamma.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1078 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::{fmla, mlaf}; +use crate::transform::PointeeSizeExpressible; +use crate::{Rgb, TransferCharacteristics}; +use num_traits::AsPrimitive; +use pxfm::{ + dirty_powf, f_exp, f_exp10, f_exp10f, f_expf, f_log, f_log10, f_log10f, f_logf, f_pow, f_powf, +}; + +#[inline] +/// Linear transfer function for sRGB +fn srgb_to_linear(gamma: f64) -> f64 { + if gamma < 0f64 { + 0f64 + } else if gamma < 12.92f64 * 0.0030412825601275209f64 { + gamma * (1f64 / 12.92f64) + } else if gamma < 1.0f64 { + f_pow( + (gamma + 0.0550107189475866f64) / 1.0550107189475866f64, + 2.4f64, + ) + } else { + 1.0f64 + } +} + +#[inline] +/// Linear transfer function for sRGB +fn srgb_to_linearf_extended(gamma: f32) -> f32 { + if gamma < 12.92 * 0.0030412825601275209 { + gamma * (1. / 12.92f32) + } else { + dirty_powf((gamma + 0.0550107189475866) / 1.0550107189475866, 2.4) + } +} + +#[inline] +/// Gamma transfer function for sRGB +fn srgb_from_linear(linear: f64) -> f64 { + if linear < 0.0f64 { + 0.0f64 + } else if linear < 0.0030412825601275209f64 { + linear * 12.92f64 + } else if linear < 1.0f64 { + fmla( + 1.0550107189475866f64, + f_pow(linear, 1.0f64 / 2.4f64), + -0.0550107189475866f64, + ) + } else { + 1.0f64 + } +} + +#[inline] +/// Gamma transfer function for sRGB +pub(crate) fn srgb_from_linear_extended(linear: f32) -> f32 { + if linear < 0.0030412825601275209f32 { + linear * 12.92f32 + } else { + fmla( + 1.0550107189475866f32, + dirty_powf(linear, 1.0f32 / 2.4f32), + -0.0550107189475866f32, + ) + } +} + +#[inline] +/// Linear transfer function for Rec.709 +fn rec709_to_linear(gamma: f64) -> f64 { + if gamma < 0.0f64 { + 0.0f64 + } else if gamma < 4.5f64 * 0.018053968510807f64 { + gamma * (1f64 / 4.5f64) + } else if gamma < 1.0f64 { + f_pow( + (gamma + 0.09929682680944f64) / 1.09929682680944f64, + 1.0f64 / 0.45f64, + ) + } else { + 1.0f64 + } +} + +#[inline] +/// Linear transfer function for Rec.709 +fn rec709_to_linearf_extended(gamma: f32) -> f32 { + if gamma < 4.5 * 0.018053968510807 { + gamma * (1. / 4.5) + } else { + f_powf((gamma + 0.09929682680944) / 1.09929682680944, 1.0 / 0.45) + } +} + +#[inline] +/// Gamma transfer function for Rec.709 +fn rec709_from_linear(linear: f64) -> f64 { + if linear < 0.0f64 { + 0.0f64 + } else if linear < 0.018053968510807f64 { + linear * 4.5f64 + } else if linear < 1.0f64 { + fmla( + 1.09929682680944f64, + f_pow(linear, 0.45f64), + -0.09929682680944f64, + ) + } else { + 1.0f64 + } +} + +#[inline] +/// Gamma transfer function for Rec.709 +fn rec709_from_linearf_extended(linear: f32) -> f32 { + if linear < 0.018053968510807 { + linear * 4.5 + } else { + fmla( + 1.09929682680944, + dirty_powf(linear, 0.45), + -0.09929682680944, + ) + } +} + +#[inline] +/// Linear transfer function for Smpte 428 +pub(crate) fn smpte428_to_linear(gamma: f64) -> f64 { + const SCALE: f64 = 1. / 0.91655527974030934f64; + f_pow(gamma.max(0.).min(1f64), 2.6f64) * SCALE +} + +#[inline] +/// Linear transfer function for Smpte 428 +pub(crate) fn smpte428_to_linearf_extended(gamma: f32) -> f32 { + const SCALE: f32 = 1. / 0.91655527974030934; + dirty_powf(gamma.max(0.), 2.6) * SCALE +} + +#[inline] +/// Gamma transfer function for Smpte 428 +fn smpte428_from_linear(linear: f64) -> f64 { + const POWER_VALUE: f64 = 1.0f64 / 2.6f64; + f_pow(0.91655527974030934f64 * linear.max(0.), POWER_VALUE) +} + +#[inline] +/// Gamma transfer function for Smpte 428 +fn smpte428_from_linearf(linear: f32) -> f32 { + const POWER_VALUE: f32 = 1.0 / 2.6; + dirty_powf(0.91655527974030934 * linear.max(0.), POWER_VALUE) +} + +#[inline] +/// Linear transfer function for Smpte 240 +pub(crate) fn smpte240_to_linear(gamma: f64) -> f64 { + if gamma < 0.0 { + 0.0 + } else if gamma < 4.0 * 0.022821585529445 { + gamma / 4.0 + } else if gamma < 1.0 { + f_pow((gamma + 0.111572195921731) / 1.111572195921731, 1.0 / 0.45) + } else { + 1.0 + } +} + +#[inline] +/// Linear transfer function for Smpte 240 +pub(crate) fn smpte240_to_linearf_extended(gamma: f32) -> f32 { + if gamma < 4.0 * 0.022821585529445 { + gamma / 4.0 + } else { + dirty_powf((gamma + 0.111572195921731) / 1.111572195921731, 1.0 / 0.45) + } +} + +#[inline] +/// Gamma transfer function for Smpte 240 +fn smpte240_from_linear(linear: f64) -> f64 { + if linear < 0.0 { + 0.0 + } else if linear < 0.022821585529445 { + linear * 4.0 + } else if linear < 1.0 { + fmla(1.111572195921731, f_pow(linear, 0.45), -0.111572195921731) + } else { + 1.0 + } +} + +#[inline] +/// Gamma transfer function for Smpte 240 +fn smpte240_from_linearf_extended(linear: f32) -> f32 { + if linear < 0.022821585529445 { + linear * 4.0 + } else { + fmla(1.111572195921731, f_powf(linear, 0.45), -0.111572195921731) + } +} + +#[inline] +/// Gamma transfer function for Log100 +fn log100_from_linear(linear: f64) -> f64 { + if linear <= 0.01f64 { + 0. + } else { + 1. + f_log10(linear.min(1.)) / 2.0 + } +} + +#[inline] +/// Gamma transfer function for Log100 +fn log100_from_linearf(linear: f32) -> f32 { + if linear <= 0.01 { + 0. + } else { + 1. + f_log10f(linear.min(1.)) / 2.0 + } +} + +#[inline] +/// Linear transfer function for Log100 +pub(crate) fn log100_to_linear(gamma: f64) -> f64 { + // The function is non-bijective so choose the middle of [0, 0.00316227766f]. + const MID_INTERVAL: f64 = 0.01 / 2.; + if gamma <= 0. { + MID_INTERVAL + } else { + f_exp10(2. * (gamma.min(1.) - 1.)) + } +} + +#[inline] +/// Linear transfer function for Log100 +pub(crate) fn log100_to_linearf(gamma: f32) -> f32 { + // The function is non-bijective so choose the middle of [0, 0.00316227766f]. + const MID_INTERVAL: f32 = 0.01 / 2.; + if gamma <= 0. { + MID_INTERVAL + } else { + f_exp10f(2. * (gamma.min(1.) - 1.)) + } +} + +#[inline] +/// Linear transfer function for Log100Sqrt10 +pub(crate) fn log100_sqrt10_to_linear(gamma: f64) -> f64 { + // The function is non-bijective so choose the middle of [0, 0.00316227766f]. + const MID_INTERVAL: f64 = 0.00316227766 / 2.; + if gamma <= 0. { + MID_INTERVAL + } else { + f_exp10(2.5 * (gamma.min(1.) - 1.)) + } +} + +#[inline] +/// Linear transfer function for Log100Sqrt10 +pub(crate) fn log100_sqrt10_to_linearf(gamma: f32) -> f32 { + // The function is non-bijective so choose the middle of [0, 0.00316227766f]. + const MID_INTERVAL: f32 = 0.00316227766 / 2.; + if gamma <= 0. { + MID_INTERVAL + } else { + f_exp10f(2.5 * (gamma.min(1.) - 1.)) + } +} + +#[inline] +/// Gamma transfer function for Log100Sqrt10 +fn log100_sqrt10_from_linear(linear: f64) -> f64 { + if linear <= 0.00316227766 { + 0.0 + } else { + 1.0 + f_log10(linear.min(1.)) / 2.5 + } +} + +#[inline] +/// Gamma transfer function for Log100Sqrt10 +fn log100_sqrt10_from_linearf(linear: f32) -> f32 { + if linear <= 0.00316227766 { + 0.0 + } else { + 1.0 + f_log10f(linear.min(1.)) / 2.5 + } +} + +#[inline] +/// Gamma transfer function for Bt.1361 +fn bt1361_from_linear(linear: f64) -> f64 { + if linear < -0.25 { + -0.25 + } else if linear < 0.0 { + fmla( + -0.27482420670236, + f_pow(-4.0 * linear, 0.45), + 0.02482420670236, + ) + } else if linear < 0.018053968510807 { + linear * 4.5 + } else if linear < 1.0 { + fmla(1.09929682680944, f_pow(linear, 0.45), -0.09929682680944) + } else { + 1.0 + } +} + +#[inline] +/// Gamma transfer function for Bt.1361 +fn bt1361_from_linearf(linear: f32) -> f32 { + if linear < -0.25 { + -0.25 + } else if linear < 0.0 { + fmla( + -0.27482420670236, + dirty_powf(-4.0 * linear, 0.45), + 0.02482420670236, + ) + } else if linear < 0.018053968510807 { + linear * 4.5 + } else if linear < 1.0 { + fmla( + 1.09929682680944, + dirty_powf(linear, 0.45), + -0.09929682680944, + ) + } else { + 1.0 + } +} + +#[inline] +/// Linear transfer function for Bt.1361 +pub(crate) fn bt1361_to_linear(gamma: f64) -> f64 { + if gamma < -0.25f64 { + -0.25f64 + } else if gamma < 0.0f64 { + f_pow( + (gamma - 0.02482420670236f64) / -0.27482420670236f64, + 1.0f64 / 0.45f64, + ) / -4.0f64 + } else if gamma < 4.5 * 0.018053968510807 { + gamma / 4.5 + } else if gamma < 1.0 { + f_pow((gamma + 0.09929682680944) / 1.09929682680944, 1.0 / 0.45) + } else { + 1.0f64 + } +} + +#[inline] +/// Linear transfer function for Bt.1361 +fn bt1361_to_linearf(gamma: f32) -> f32 { + if gamma < -0.25 { + -0.25 + } else if gamma < 0.0 { + dirty_powf((gamma - 0.02482420670236) / -0.27482420670236, 1.0 / 0.45) / -4.0 + } else if gamma < 4.5 * 0.018053968510807 { + gamma / 4.5 + } else if gamma < 1.0 { + dirty_powf((gamma + 0.09929682680944) / 1.09929682680944, 1.0 / 0.45) + } else { + 1.0 + } +} + +#[inline(always)] +/// Pure gamma transfer function for gamma 2.2 +fn pure_gamma_function(x: f64, gamma: f64) -> f64 { + if x <= 0f64 { + 0f64 + } else if x >= 1f64 { + 1f64 + } else { + f_pow(x, gamma) + } +} + +#[inline(always)] +/// Pure gamma transfer function for gamma 2.2 +fn pure_gamma_function_f(x: f32, gamma: f32) -> f32 { + if x <= 0. { 0. } else { dirty_powf(x, gamma) } +} + +#[inline] +pub(crate) fn iec61966_to_linear(gamma: f64) -> f64 { + if gamma < -4.5f64 * 0.018053968510807f64 { + f_pow( + (-gamma + 0.09929682680944f64) / -1.09929682680944f64, + 1.0 / 0.45, + ) + } else if gamma < 4.5f64 * 0.018053968510807f64 { + gamma / 4.5 + } else { + f_pow( + (gamma + 0.09929682680944f64) / 1.09929682680944f64, + 1.0 / 0.45, + ) + } +} + +#[inline] +fn iec61966_to_linearf(gamma: f32) -> f32 { + if gamma < -4.5 * 0.018053968510807 { + dirty_powf((-gamma + 0.09929682680944) / -1.09929682680944, 1.0 / 0.45) + } else if gamma < 4.5 * 0.018053968510807 { + gamma / 4.5 + } else { + dirty_powf((gamma + 0.09929682680944) / 1.09929682680944, 1.0 / 0.45) + } +} + +#[inline] +fn iec61966_from_linear(v: f64) -> f64 { + if v < -0.018053968510807f64 { + fmla(-1.09929682680944f64, f_pow(-v, 0.45), 0.09929682680944f64) + } else if v < 0.018053968510807f64 { + v * 4.5f64 + } else { + fmla(1.09929682680944f64, f_pow(v, 0.45), -0.09929682680944f64) + } +} + +#[inline] +fn iec61966_from_linearf(v: f32) -> f32 { + if v < -0.018053968510807 { + fmla(-1.09929682680944, dirty_powf(-v, 0.45), 0.09929682680944) + } else if v < 0.018053968510807 { + v * 4.5 + } else { + fmla(1.09929682680944, dirty_powf(v, 0.45), -0.09929682680944) + } +} + +#[inline] +/// Pure gamma transfer function for gamma 2.2 +fn gamma2p2_from_linear(linear: f64) -> f64 { + pure_gamma_function(linear, 1f64 / 2.2f64) +} + +#[inline] +/// Pure gamma transfer function for gamma 2.2 +fn gamma2p2_from_linear_f(linear: f32) -> f32 { + pure_gamma_function_f(linear, 1. / 2.2) +} + +#[inline] +/// Linear transfer function for gamma 2.2 +fn gamma2p2_to_linear(gamma: f64) -> f64 { + pure_gamma_function(gamma, 2.2f64) +} + +#[inline] +/// Linear transfer function for gamma 2.2 +fn gamma2p2_to_linear_f(gamma: f32) -> f32 { + pure_gamma_function_f(gamma, 2.2) +} + +#[inline] +/// Pure gamma transfer function for gamma 2.8 +fn gamma2p8_from_linear(linear: f64) -> f64 { + pure_gamma_function(linear, 1f64 / 2.8f64) +} + +#[inline] +/// Pure gamma transfer function for gamma 2.8 +fn gamma2p8_from_linear_f(linear: f32) -> f32 { + pure_gamma_function_f(linear, 1. / 2.8) +} + +#[inline] +/// Linear transfer function for gamma 2.8 +fn gamma2p8_to_linear(gamma: f64) -> f64 { + pure_gamma_function(gamma, 2.8f64) +} + +#[inline] +/// Linear transfer function for gamma 2.8 +fn gamma2p8_to_linear_f(gamma: f32) -> f32 { + pure_gamma_function_f(gamma, 2.8) +} + +#[inline] +/// Linear transfer function for PQ +pub(crate) fn pq_to_linear(gamma: f64) -> f64 { + if gamma > 0.0 { + let pow_gamma = f_pow(gamma, 1.0 / 78.84375); + let num = (pow_gamma - 0.8359375).max(0.); + let den = mlaf(18.8515625, -18.6875, pow_gamma).max(f64::MIN); + f_pow(num / den, 1.0 / 0.1593017578125) + } else { + 0.0 + } +} + +#[inline] +/// Linear transfer function for PQ +pub(crate) fn pq_to_linearf(gamma: f32) -> f32 { + if gamma > 0.0 { + let pow_gamma = f_powf(gamma, 1.0 / 78.84375); + let num = (pow_gamma - 0.8359375).max(0.); + let den = mlaf(18.8515625, -18.6875, pow_gamma).max(f32::MIN); + f_powf(num / den, 1.0 / 0.1593017578125) + } else { + 0.0 + } +} + +#[inline] +/// Gamma transfer function for PQ +fn pq_from_linear(linear: f64) -> f64 { + if linear > 0.0 { + let linear = linear.clamp(0., 1.); + let pow_linear = f_pow(linear, 0.1593017578125); + let num = fmla(0.1640625, pow_linear, -0.1640625); + let den = mlaf(1.0, 18.6875, pow_linear); + f_pow(1.0 + num / den, 78.84375) + } else { + 0.0 + } +} + +#[inline] +/// Gamma transfer function for PQ +pub(crate) fn pq_from_linearf(linear: f32) -> f32 { + if linear > 0.0 { + let linear = linear.max(0.); + let pow_linear = f_powf(linear, 0.1593017578125); + let num = fmla(0.1640625, pow_linear, -0.1640625); + let den = mlaf(1.0, 18.6875, pow_linear); + f_powf(1.0 + num / den, 78.84375) + } else { + 0.0 + } +} + +#[inline] +/// Linear transfer function for HLG +pub(crate) fn hlg_to_linear(gamma: f64) -> f64 { + if gamma < 0.0 { + return 0.0; + } + if gamma <= 0.5 { + f_pow((gamma * gamma) * (1.0 / 3.0), 1.2) + } else { + f_pow( + (f_exp((gamma - 0.55991073) / 0.17883277) + 0.28466892) / 12.0, + 1.2, + ) + } +} + +#[inline] +/// Linear transfer function for HLG +pub(crate) fn hlg_to_linearf(gamma: f32) -> f32 { + if gamma < 0.0 { + return 0.0; + } + if gamma <= 0.5 { + f_powf((gamma * gamma) * (1.0 / 3.0), 1.2) + } else { + f_powf( + (f_expf((gamma - 0.55991073) / 0.17883277) + 0.28466892) / 12.0, + 1.2, + ) + } +} + +#[inline] +/// Gamma transfer function for HLG +fn hlg_from_linear(linear: f64) -> f64 { + // Scale from extended SDR range to [0.0, 1.0]. + let mut linear = linear.clamp(0., 1.); + // Inverse OOTF followed by OETF see Table 5 and Note 5i in ITU-R BT.2100-2 page 7-8. + linear = f_pow(linear, 1.0 / 1.2); + if linear < 0.0 { + 0.0 + } else if linear <= (1.0 / 12.0) { + (3.0 * linear).sqrt() + } else { + fmla( + 0.17883277, + f_log(fmla(12.0, linear, -0.28466892)), + 0.55991073, + ) + } +} + +#[inline] +/// Gamma transfer function for HLG +fn hlg_from_linearf(linear: f32) -> f32 { + // Scale from extended SDR range to [0.0, 1.0]. + let mut linear = linear.max(0.); + // Inverse OOTF followed by OETF see Table 5 and Note 5i in ITU-R BT.2100-2 page 7-8. + linear = f_powf(linear, 1.0 / 1.2); + if linear < 0.0 { + 0.0 + } else if linear <= (1.0 / 12.0) { + (3.0 * linear).sqrt() + } else { + 0.17883277 * f_logf(12.0 * linear - 0.28466892) + 0.55991073 + } +} + +#[inline] +fn trc_linear(v: f64) -> f64 { + v.min(1.).max(0.) +} + +impl TransferCharacteristics { + #[inline] + pub fn linearize(self, v: f64) -> f64 { + match self { + TransferCharacteristics::Reserved => 0f64, + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => rec709_to_linear(v), + TransferCharacteristics::Unspecified => 0f64, + TransferCharacteristics::Bt470M => gamma2p2_to_linear(v), + TransferCharacteristics::Bt470Bg => gamma2p8_to_linear(v), + TransferCharacteristics::Smpte240 => smpte240_to_linear(v), + TransferCharacteristics::Linear => trc_linear(v), + TransferCharacteristics::Log100 => log100_to_linear(v), + TransferCharacteristics::Log100sqrt10 => log100_sqrt10_to_linear(v), + TransferCharacteristics::Iec61966 => iec61966_to_linear(v), + TransferCharacteristics::Bt1361 => bt1361_to_linear(v), + TransferCharacteristics::Srgb => srgb_to_linear(v), + TransferCharacteristics::Smpte2084 => pq_to_linear(v), + TransferCharacteristics::Smpte428 => smpte428_to_linear(v), + TransferCharacteristics::Hlg => hlg_to_linear(v), + } + } + + #[inline] + pub fn gamma(self, v: f64) -> f64 { + match self { + TransferCharacteristics::Reserved => 0f64, + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => rec709_from_linear(v), + TransferCharacteristics::Unspecified => 0f64, + TransferCharacteristics::Bt470M => gamma2p2_from_linear(v), + TransferCharacteristics::Bt470Bg => gamma2p8_from_linear(v), + TransferCharacteristics::Smpte240 => smpte240_from_linear(v), + TransferCharacteristics::Linear => trc_linear(v), + TransferCharacteristics::Log100 => log100_from_linear(v), + TransferCharacteristics::Log100sqrt10 => log100_sqrt10_from_linear(v), + TransferCharacteristics::Iec61966 => iec61966_from_linear(v), + TransferCharacteristics::Bt1361 => bt1361_from_linear(v), + TransferCharacteristics::Srgb => srgb_from_linear(v), + TransferCharacteristics::Smpte2084 => pq_from_linear(v), + TransferCharacteristics::Smpte428 => smpte428_from_linear(v), + TransferCharacteristics::Hlg => hlg_from_linear(v), + } + } + + pub(crate) fn extended_gamma_tristimulus(self) -> fn(Rgb) -> Rgb { + match self { + TransferCharacteristics::Reserved => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => |x| { + Rgb::new( + rec709_from_linearf_extended(x.r), + rec709_from_linearf_extended(x.g), + rec709_from_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Unspecified => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Bt470M => |x| { + Rgb::new( + gamma2p2_from_linear_f(x.r), + gamma2p2_from_linear_f(x.g), + gamma2p2_from_linear_f(x.b), + ) + }, + TransferCharacteristics::Bt470Bg => |x| { + Rgb::new( + gamma2p8_from_linear_f(x.r), + gamma2p8_from_linear_f(x.g), + gamma2p8_from_linear_f(x.b), + ) + }, + TransferCharacteristics::Smpte240 => |x| { + Rgb::new( + smpte240_from_linearf_extended(x.r), + smpte240_from_linearf_extended(x.g), + smpte240_from_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Linear => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Log100 => |x| { + Rgb::new( + log100_from_linearf(x.r), + log100_from_linearf(x.g), + log100_from_linearf(x.b), + ) + }, + TransferCharacteristics::Log100sqrt10 => |x| { + Rgb::new( + log100_sqrt10_from_linearf(x.r), + log100_sqrt10_from_linearf(x.g), + log100_sqrt10_from_linearf(x.b), + ) + }, + TransferCharacteristics::Iec61966 => |x| { + Rgb::new( + iec61966_from_linearf(x.r), + iec61966_from_linearf(x.g), + iec61966_from_linearf(x.b), + ) + }, + TransferCharacteristics::Bt1361 => |x| { + Rgb::new( + bt1361_from_linearf(x.r), + bt1361_from_linearf(x.g), + bt1361_from_linearf(x.b), + ) + }, + TransferCharacteristics::Srgb => |x| { + Rgb::new( + srgb_from_linear_extended(x.r), + srgb_from_linear_extended(x.g), + srgb_from_linear_extended(x.b), + ) + }, + TransferCharacteristics::Smpte2084 => |x| { + Rgb::new( + pq_from_linearf(x.r), + pq_from_linearf(x.g), + pq_from_linearf(x.b), + ) + }, + TransferCharacteristics::Smpte428 => |x| { + Rgb::new( + smpte428_from_linearf(x.r), + smpte428_from_linearf(x.g), + smpte428_from_linearf(x.b), + ) + }, + TransferCharacteristics::Hlg => |x| { + Rgb::new( + hlg_from_linearf(x.r), + hlg_from_linearf(x.g), + hlg_from_linearf(x.b), + ) + }, + } + } + + pub(crate) fn extended_gamma_single(self) -> fn(f32) -> f32 { + match self { + TransferCharacteristics::Reserved => |x| x, + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => |x| rec709_from_linearf_extended(x), + TransferCharacteristics::Unspecified => |x| x, + TransferCharacteristics::Bt470M => |x| gamma2p2_from_linear_f(x), + TransferCharacteristics::Bt470Bg => |x| gamma2p8_from_linear_f(x), + TransferCharacteristics::Smpte240 => |x| smpte240_from_linearf_extended(x), + TransferCharacteristics::Linear => |x| x, + TransferCharacteristics::Log100 => |x| log100_from_linearf(x), + TransferCharacteristics::Log100sqrt10 => |x| log100_sqrt10_from_linearf(x), + TransferCharacteristics::Iec61966 => |x| iec61966_from_linearf(x), + TransferCharacteristics::Bt1361 => |x| bt1361_from_linearf(x), + TransferCharacteristics::Srgb => |x| srgb_from_linear_extended(x), + TransferCharacteristics::Smpte2084 => |x| pq_from_linearf(x), + TransferCharacteristics::Smpte428 => |x| smpte428_from_linearf(x), + TransferCharacteristics::Hlg => |x| hlg_from_linearf(x), + } + } + + pub(crate) fn extended_linear_tristimulus(self) -> fn(Rgb) -> Rgb { + match self { + TransferCharacteristics::Reserved => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => |x| { + Rgb::new( + rec709_to_linearf_extended(x.r), + rec709_to_linearf_extended(x.g), + rec709_to_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Unspecified => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Bt470M => |x| { + Rgb::new( + gamma2p2_to_linear_f(x.r), + gamma2p2_to_linear_f(x.g), + gamma2p2_to_linear_f(x.b), + ) + }, + TransferCharacteristics::Bt470Bg => |x| { + Rgb::new( + gamma2p8_to_linear_f(x.r), + gamma2p8_to_linear_f(x.g), + gamma2p8_to_linear_f(x.b), + ) + }, + TransferCharacteristics::Smpte240 => |x| { + Rgb::new( + smpte240_to_linearf_extended(x.r), + smpte240_to_linearf_extended(x.g), + smpte240_to_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Linear => |x| Rgb::new(x.r, x.g, x.b), + TransferCharacteristics::Log100 => |x| { + Rgb::new( + log100_to_linearf(x.r), + log100_to_linearf(x.g), + log100_to_linearf(x.b), + ) + }, + TransferCharacteristics::Log100sqrt10 => |x| { + Rgb::new( + log100_sqrt10_to_linearf(x.r), + log100_sqrt10_to_linearf(x.g), + log100_sqrt10_to_linearf(x.b), + ) + }, + TransferCharacteristics::Iec61966 => |x| { + Rgb::new( + iec61966_to_linearf(x.r), + iec61966_to_linearf(x.g), + iec61966_to_linearf(x.b), + ) + }, + TransferCharacteristics::Bt1361 => |x| { + Rgb::new( + bt1361_to_linearf(x.r), + bt1361_to_linearf(x.g), + bt1361_to_linearf(x.b), + ) + }, + TransferCharacteristics::Srgb => |x| { + Rgb::new( + srgb_to_linearf_extended(x.r), + srgb_to_linearf_extended(x.g), + srgb_to_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Smpte2084 => { + |x| Rgb::new(pq_to_linearf(x.r), pq_to_linearf(x.g), pq_to_linearf(x.b)) + } + TransferCharacteristics::Smpte428 => |x| { + Rgb::new( + smpte428_to_linearf_extended(x.r), + smpte428_to_linearf_extended(x.g), + smpte428_to_linearf_extended(x.b), + ) + }, + TransferCharacteristics::Hlg => |x| { + Rgb::new( + hlg_to_linearf(x.r), + hlg_to_linearf(x.g), + hlg_to_linearf(x.b), + ) + }, + } + } + + pub(crate) fn extended_linear_single(self) -> fn(f32) -> f32 { + match self { + TransferCharacteristics::Reserved => |x| x, + TransferCharacteristics::Bt709 + | TransferCharacteristics::Bt601 + | TransferCharacteristics::Bt202010bit + | TransferCharacteristics::Bt202012bit => |x| rec709_to_linearf_extended(x), + TransferCharacteristics::Unspecified => |x| x, + TransferCharacteristics::Bt470M => |x| gamma2p2_to_linear_f(x), + TransferCharacteristics::Bt470Bg => |x| gamma2p8_to_linear_f(x), + TransferCharacteristics::Smpte240 => |x| smpte240_to_linearf_extended(x), + TransferCharacteristics::Linear => |x| x, + TransferCharacteristics::Log100 => |x| log100_to_linearf(x), + TransferCharacteristics::Log100sqrt10 => |x| log100_sqrt10_to_linearf(x), + TransferCharacteristics::Iec61966 => |x| iec61966_to_linearf(x), + TransferCharacteristics::Bt1361 => |x| bt1361_to_linearf(x), + TransferCharacteristics::Srgb => |x| srgb_to_linearf_extended(x), + TransferCharacteristics::Smpte2084 => |x| pq_to_linearf(x), + TransferCharacteristics::Smpte428 => |x| smpte428_to_linearf_extended(x), + TransferCharacteristics::Hlg => |x| hlg_to_linearf(x), + } + } + + pub(crate) fn make_linear_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + ) -> Box<[f32; N]> { + let mut gamma_table = Box::new([0f32; N]); + let max_value = if T::FINITE { + (1 << BIT_DEPTH) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let cap_values = if T::FINITE { + (1u32 << BIT_DEPTH) as usize + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE + }; + assert!(cap_values <= N, "Invalid lut table construction"); + let scale_value = 1f64 / max_value as f64; + for (i, g) in gamma_table.iter_mut().enumerate().take(cap_values) { + *g = self.linearize(i as f64 * scale_value) as f32; + } + gamma_table + } + + pub(crate) fn make_gamma_table< + T: Default + Copy + 'static + PointeeSizeExpressible, + const BUCKET: usize, + const N: usize, + >( + &self, + bit_depth: usize, + ) -> Box<[T; BUCKET]> + where + f32: AsPrimitive, + { + let mut table = Box::new([T::default(); BUCKET]); + let max_range = 1f64 / (N - 1) as f64; + let max_value = ((1 << bit_depth) - 1) as f64; + if T::FINITE { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = ((self.gamma(v as f64 * max_range) * max_value) as f32) + .round() + .as_(); + } + } else { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = (self.gamma(v as f64 * max_range) as f32).as_(); + } + } + table + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn srgb_test() { + let srgb_0 = srgb_to_linear(0.5); + let srgb_1 = srgb_from_linear(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-9f64); + } + + #[test] + fn log100_sqrt10_test() { + let srgb_0 = log100_sqrt10_to_linear(0.5); + let srgb_1 = log100_sqrt10_from_linear(srgb_0); + assert_eq!(0.5, srgb_1); + } + + #[test] + fn log100_test() { + let srgb_0 = log100_to_linear(0.5); + let srgb_1 = log100_from_linear(srgb_0); + assert_eq!(0.5, srgb_1); + } + + #[test] + fn iec61966_test() { + let srgb_0 = iec61966_to_linear(0.5); + let srgb_1 = iec61966_from_linear(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-9f64); + } + + #[test] + fn smpte240_test() { + let srgb_0 = smpte240_to_linear(0.5); + let srgb_1 = smpte240_from_linear(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-9f64); + } + + #[test] + fn smpte428_test() { + let srgb_0 = smpte428_to_linear(0.5); + let srgb_1 = smpte428_from_linear(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-9f64); + } + + #[test] + fn rec709_test() { + let srgb_0 = rec709_to_linear(0.5); + let srgb_1 = rec709_from_linear(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-9f64); + } + + #[test] + fn rec709f_test() { + let srgb_0 = rec709_to_linearf_extended(0.5); + let srgb_1 = rec709_from_linearf_extended(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-5f32); + } + + #[test] + fn srgbf_test() { + let srgb_0 = srgb_to_linearf_extended(0.5); + let srgb_1 = srgb_from_linear_extended(srgb_0); + assert!((0.5 - srgb_1).abs() < 1e-5f32); + } + + #[test] + fn hlg_test() { + let z0 = hlg_to_linear(0.5); + let z1 = hlg_from_linear(z0); + assert!((0.5 - z1).abs() < 1e-5f64); + } + + #[test] + fn pq_test() { + let z0 = pq_to_linear(0.5); + let z1 = pq_from_linear(z0); + assert!((0.5 - z1).abs() < 1e-5f64); + } + + #[test] + fn pqf_test() { + let z0 = pq_to_linearf(0.5); + let z1 = pq_from_linearf(z0); + assert!((0.5 - z1).abs() < 1e-5f32); + } + + #[test] + fn iec_test() { + let z0 = iec61966_to_linear(0.5); + let z1 = iec61966_from_linear(z0); + assert!((0.5 - z1).abs() < 1e-5f64); + } + + #[test] + fn bt1361_test() { + let z0 = bt1361_to_linear(0.5); + let z1 = bt1361_from_linear(z0); + assert!((0.5 - z1).abs() < 1e-5f64); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/gamut.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/gamut.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/gamut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Rgb; + +#[inline] +fn filmlike_clip_rgb_tone(r: &mut f32, g: &mut f32, b: &mut f32, l: f32) { + let new_r = r.min(l); + let new_b = b.min(l); + let new_g = new_b + ((new_r - new_b) * (*g - *b) / (*r - *b)); + *r = new_r; + *g = new_g; + *b = new_b; +} + +/// Soft clipping out-of-bounds values in S-curve +/// +/// Works only on highlights, negative values are skipped +#[inline] +pub fn filmlike_clip(rgb: Rgb) -> Rgb { + const L: f32 = 1.; + let mut rgb = rgb; + if rgb.r >= rgb.g { + if rgb.g > rgb.b { + filmlike_clip_rgb_tone(&mut rgb.r, &mut rgb.g, &mut rgb.b, L); + } else if rgb.b > rgb.r { + filmlike_clip_rgb_tone(&mut rgb.b, &mut rgb.r, &mut rgb.g, L); + } else if rgb.b > rgb.g { + filmlike_clip_rgb_tone(&mut rgb.r, &mut rgb.b, &mut rgb.g, L); + } else { + Rgb::new(rgb.r.min(L), rgb.g.min(L), rgb.g); + } + } else if rgb.r >= rgb.b { + filmlike_clip_rgb_tone(&mut rgb.g, &mut rgb.r, &mut rgb.b, L); + } else if rgb.b > rgb.g { + filmlike_clip_rgb_tone(&mut rgb.b, &mut rgb.g, &mut rgb.r, L); + } else { + filmlike_clip_rgb_tone(&mut rgb.g, &mut rgb.b, &mut rgb.r, L); + } + rgb +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/helpers.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/helpers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/helpers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/helpers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::matan::{ + does_curve_have_discontinuity, is_curve_ascending, is_curve_degenerated, is_curve_descending, + is_curve_linear8, is_curve_linear16, is_curve_monotonic, +}; +use crate::reader::{ + s15_fixed16_number_to_double, uint8_number_to_float_fast, uint16_number_to_float_fast, +}; +use crate::{CmsError, LutStore, Matrix3d, ToneReprCurve, Vector3d}; + +impl LutStore { + pub fn to_clut_f32(&self) -> Vec { + match self { + LutStore::Store8(store) => store + .iter() + .map(|x| uint8_number_to_float_fast(*x)) + .collect(), + LutStore::Store16(store) => store + .iter() + .map(|x| uint16_number_to_float_fast(*x as u32)) + .collect(), + } + } + + pub(crate) fn is_degenerated(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => is_curve_degenerated(&v[start..end]), + LutStore::Store16(v) => is_curve_degenerated(&v[start..end]), + } + } + + pub(crate) fn is_monotonic(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => is_curve_monotonic(&v[start..end]), + LutStore::Store16(v) => is_curve_monotonic(&v[start..end]), + } + } + + pub(crate) fn have_discontinuities(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => does_curve_have_discontinuity(&v[start..end]), + LutStore::Store16(v) => does_curve_have_discontinuity(&v[start..end]), + } + } + + #[allow(dead_code)] + pub(crate) fn is_linear(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => is_curve_linear8(&v[start..end]), + LutStore::Store16(v) => is_curve_linear16(&v[start..end]), + } + } + + #[allow(dead_code)] + pub(crate) fn is_descending(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => is_curve_descending(&v[start..end]), + LutStore::Store16(v) => is_curve_descending(&v[start..end]), + } + } + + #[allow(dead_code)] + pub(crate) fn is_ascending(&self, entries: usize, channel: usize) -> bool { + let start = entries * channel; + let end = start + entries; + + match &self { + LutStore::Store8(v) => is_curve_ascending(&v[start..end]), + LutStore::Store16(v) => is_curve_ascending(&v[start..end]), + } + } +} + +impl ToneReprCurve { + pub(crate) fn is_linear(&self) -> bool { + match &self { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return true; + } + if lut.len() == 1 { + let gamma = 1. / crate::trc::u8_fixed_8number_to_float(lut[0]); + if (gamma - 1.).abs() < 1e-4 { + return true; + } + } + is_curve_linear16(lut) + } + ToneReprCurve::Parametric(parametric) => { + if parametric.is_empty() { + return true; + } + if parametric.len() == 1 && parametric[0] == 1. { + return true; + } + false + } + } + } + + pub(crate) fn is_monotonic(&self) -> bool { + match &self { + ToneReprCurve::Lut(lut) => is_curve_monotonic(lut), + ToneReprCurve::Parametric(_) => true, + } + } + + pub(crate) fn is_degenerated(&self) -> bool { + match &self { + ToneReprCurve::Lut(lut) => is_curve_degenerated(lut), + ToneReprCurve::Parametric(_) => false, + } + } + + pub(crate) fn have_discontinuities(&self) -> bool { + match &self { + ToneReprCurve::Lut(lut) => does_curve_have_discontinuity(lut), + ToneReprCurve::Parametric(_) => false, + } + } +} + +pub(crate) fn read_matrix_3d(arr: &[u8]) -> Result { + if arr.len() < 36 { + return Err(CmsError::InvalidProfile); + } + + let m_tag = &arr[..36]; + + let e00 = i32::from_be_bytes([m_tag[0], m_tag[1], m_tag[2], m_tag[3]]); + let e01 = i32::from_be_bytes([m_tag[4], m_tag[5], m_tag[6], m_tag[7]]); + let e02 = i32::from_be_bytes([m_tag[8], m_tag[9], m_tag[10], m_tag[11]]); + + let e10 = i32::from_be_bytes([m_tag[12], m_tag[13], m_tag[14], m_tag[15]]); + let e11 = i32::from_be_bytes([m_tag[16], m_tag[17], m_tag[18], m_tag[19]]); + let e12 = i32::from_be_bytes([m_tag[20], m_tag[21], m_tag[22], m_tag[23]]); + + let e20 = i32::from_be_bytes([m_tag[24], m_tag[25], m_tag[26], m_tag[27]]); + let e21 = i32::from_be_bytes([m_tag[28], m_tag[29], m_tag[30], m_tag[31]]); + let e22 = i32::from_be_bytes([m_tag[32], m_tag[33], m_tag[34], m_tag[35]]); + + Ok(Matrix3d { + v: [ + [ + s15_fixed16_number_to_double(e00), + s15_fixed16_number_to_double(e01), + s15_fixed16_number_to_double(e02), + ], + [ + s15_fixed16_number_to_double(e10), + s15_fixed16_number_to_double(e11), + s15_fixed16_number_to_double(e12), + ], + [ + s15_fixed16_number_to_double(e20), + s15_fixed16_number_to_double(e21), + s15_fixed16_number_to_double(e22), + ], + ], + }) +} + +pub(crate) fn read_vector_3d(arr: &[u8]) -> Result { + if arr.len() < 12 { + return Err(CmsError::InvalidProfile); + } + + let m_tag = &arr[..12]; + + let b0 = i32::from_be_bytes([m_tag[0], m_tag[1], m_tag[2], m_tag[3]]); + let b1 = i32::from_be_bytes([m_tag[4], m_tag[5], m_tag[6], m_tag[7]]); + let b2 = i32::from_be_bytes([m_tag[8], m_tag[9], m_tag[10], m_tag[11]]); + + Ok(Vector3d { + v: [ + s15_fixed16_number_to_double(b0), + s15_fixed16_number_to_double(b1), + s15_fixed16_number_to_double(b2), + ], + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/ictcp.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/ictcp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/ictcp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/ictcp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::gamma::{pq_from_linearf, pq_to_linearf}; +use crate::{Matrix3f, Rgb, Vector3f, Xyz}; + +const CROSSTALK: Matrix3f = Matrix3f { + v: [[0.92, 0.04, 0.04], [0.04, 0.92, 0.04], [0.04, 0.04, 0.92]], +}; + +const HPE_LMS: Matrix3f = Matrix3f { + v: [ + [0.4002, 0.7076, -0.0808], + [-0.2263, 1.1653, 0.0457], + [0f32, 0f32, 0.9182], + ], +}; + +const XYZ_TO_LMS: Matrix3f = CROSSTALK.mat_mul_const(HPE_LMS); + +const LMS_TO_XYZ: Matrix3f = XYZ_TO_LMS.inverse(); + +const L_LMS_TO_ICTCP: Matrix3f = Matrix3f { + v: [ + [2048. / 4096., 2048. / 4096., 0.], + [6610. / 4096., -13613. / 4096., 7003. / 4096.], + [17933. / 4096., -17390. / 4096., -543. / 4096.], + ], +}; + +const ICTCP_TO_L_LMS: Matrix3f = L_LMS_TO_ICTCP.inverse(); + +#[derive(Copy, Clone, Default, PartialOrd, PartialEq)] +pub struct ICtCp { + /// Lightness + pub i: f32, + /// Tritan + pub ct: f32, + /// Protan + pub cp: f32, +} + +impl ICtCp { + #[inline] + pub const fn new(i: f32, ct: f32, cp: f32) -> ICtCp { + ICtCp { i, ct, cp } + } + + /// Converts XYZ D65 to ICtCp + #[inline] + pub fn from_xyz(xyz: Xyz) -> ICtCp { + let lms = XYZ_TO_LMS.mul_vector(xyz.to_vector()); + let lin_l = pq_from_linearf(lms.v[0]); + let lin_m = pq_from_linearf(lms.v[1]); + let lin_s = pq_from_linearf(lms.v[2]); + let ictcp = L_LMS_TO_ICTCP.mul_vector(Vector3f { + v: [lin_l, lin_m, lin_s], + }); + ICtCp { + i: ictcp.v[0], + ct: ictcp.v[1], + cp: ictcp.v[2], + } + } + + /// Converts to [ICtCp] from linear light [Rgb] + /// + /// Precompute forward matrix by [ICtCp::prepare_to_lms]. + /// D65 white point is assumed. + #[inline] + pub fn from_linear_rgb(rgb: Rgb, matrix: Matrix3f) -> ICtCp { + let lms = matrix.mul_vector(rgb.to_vector()); + let lin_l = pq_from_linearf(lms.v[0]); + let lin_m = pq_from_linearf(lms.v[1]); + let lin_s = pq_from_linearf(lms.v[2]); + let ictcp = L_LMS_TO_ICTCP.mul_vector(Vector3f { + v: [lin_l, lin_m, lin_s], + }); + ICtCp { + i: ictcp.v[0], + ct: ictcp.v[1], + cp: ictcp.v[2], + } + } + + /// Converts [ICtCp] to [Rgb] + /// + /// Precompute forward matrix by [ICtCp::prepare_to_lms] and then inverse it + #[inline] + pub fn to_linear_rgb(&self, matrix: Matrix3f) -> Rgb { + let l_lms = ICTCP_TO_L_LMS.mul_vector(Vector3f { + v: [self.i, self.ct, self.cp], + }); + let gamma_l = pq_to_linearf(l_lms.v[0]); + let gamma_m = pq_to_linearf(l_lms.v[1]); + let gamma_s = pq_to_linearf(l_lms.v[2]); + + let lms = matrix.mul_vector(Vector3f { + v: [gamma_l, gamma_m, gamma_s], + }); + Rgb { + r: lms.v[0], + g: lms.v[1], + b: lms.v[2], + } + } + + /// Converts ICtCp to XYZ D65 + #[inline] + pub fn to_xyz(&self) -> Xyz { + let l_lms = ICTCP_TO_L_LMS.mul_vector(Vector3f { + v: [self.i, self.ct, self.cp], + }); + let gamma_l = pq_to_linearf(l_lms.v[0]); + let gamma_m = pq_to_linearf(l_lms.v[1]); + let gamma_s = pq_to_linearf(l_lms.v[2]); + + let lms = LMS_TO_XYZ.mul_vector(Vector3f { + v: [gamma_l, gamma_m, gamma_s], + }); + Xyz { + x: lms.v[0], + y: lms.v[1], + z: lms.v[2], + } + } + + /// Prepares RGB->LMS matrix + #[inline] + pub const fn prepare_to_lms(rgb_to_xyz: Matrix3f) -> Matrix3f { + XYZ_TO_LMS.mat_mul_const(rgb_to_xyz) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn check_roundtrip() { + let xyz = Xyz::new(0.5, 0.4, 0.3); + let ictcp = ICtCp::from_xyz(xyz); + let r_xyz = ictcp.to_xyz(); + assert!((r_xyz.x - xyz.x).abs() < 1e-4); + assert!((r_xyz.y - xyz.y).abs() < 1e-4); + assert!((r_xyz.z - xyz.z).abs() < 1e-4); + } + + #[test] + fn check_roundtrip_rgb() { + let rgb_to_xyz = Matrix3f { + v: [ + [0.67345345, 0.165661961, 0.125096574], + [0.27903071, 0.675341845, 0.045627553], + [-0.00193137419, 0.0299795717, 0.797140181], + ], + }; + let prepared_matrix = ICtCp::prepare_to_lms(rgb_to_xyz); + let inversed_matrix = prepared_matrix.inverse(); + let rgb = Rgb::new(0.5, 0.4, 0.3); + let ictcp = ICtCp::from_linear_rgb(rgb, prepared_matrix); + let r_xyz = ictcp.to_linear_rgb(inversed_matrix); + assert!((r_xyz.r - rgb.r).abs() < 1e-4); + assert!((r_xyz.g - rgb.g).abs() < 1e-4); + assert!((r_xyz.b - rgb.b).abs() < 1e-4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/jzazbz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzazbz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/jzazbz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzazbz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,434 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Xyz; +use crate::jzczhz::Jzczhz; +use crate::mlaf::mlaf; +use num_traits::Pow; +use pxfm::{dirty_powf, f_cbrtf, f_powf}; +use std::ops::{ + Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, +}; + +#[inline] +fn perceptual_quantizer(x: f32) -> f32 { + if x <= 0. { + return 0.; + } + let xx = dirty_powf(x * 1e-4, 0.1593017578125); + let rs = dirty_powf( + mlaf(0.8359375, 18.8515625, xx) / mlaf(1., 18.6875, xx), + 134.034375, + ); + if rs.is_nan() { + return 0.; + } + rs +} + +#[inline] +fn perceptual_quantizer_inverse(x: f32) -> f32 { + if x <= 0. { + return 0.; + } + let xx = dirty_powf(x, 7.460772656268214e-03); + let rs = 1e4 + * dirty_powf( + (0.8359375 - xx) / mlaf(-18.8515625, 18.6875, xx), + 6.277394636015326, + ); + if rs.is_nan() { + return 0.; + } + rs +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Default)] +/// Represents Jzazbz +pub struct Jzazbz { + /// Jz(lightness) generally expects to be between `0.0..1.0`. + pub jz: f32, + /// Az generally expects to be between `-0.5..0.5`. + pub az: f32, + /// Bz generally expects to be between `-0.5..0.5`. + pub bz: f32, +} + +impl Jzazbz { + /// Constructs new instance + #[inline] + pub fn new(jz: f32, az: f32, bz: f32) -> Jzazbz { + Jzazbz { jz, az, bz } + } + + /// Creates new [Jzazbz] from CIE [Xyz]. + /// + /// JzAzBz is defined in D65 white point, adapt XYZ if needed first. + #[inline] + pub fn from_xyz(xyz: Xyz) -> Jzazbz { + Self::from_xyz_with_display_luminance(xyz, 200.) + } + + /// Creates new [Jzazbz] from CIE [Xyz]. + /// + /// JzAzBz is defined in D65 white point, adapt XYZ if needed first. + #[inline] + pub fn from_xyz_with_display_luminance(xyz: Xyz, display_luminance: f32) -> Jzazbz { + let abs_xyz = xyz * display_luminance; + let lp = perceptual_quantizer(mlaf( + mlaf(0.674207838 * abs_xyz.x, 0.382799340, abs_xyz.y), + -0.047570458, + abs_xyz.z, + )); + let mp = perceptual_quantizer(mlaf( + mlaf(0.149284160 * abs_xyz.x, 0.739628340, abs_xyz.y), + 0.083327300, + abs_xyz.z, + )); + let sp = perceptual_quantizer(mlaf( + mlaf(0.070941080 * abs_xyz.x, 0.174768000, abs_xyz.y), + 0.670970020, + abs_xyz.z, + )); + let iz = 0.5 * (lp + mp); + let az = mlaf(mlaf(3.524000 * lp, -4.066708, mp), 0.542708, sp); + let bz = mlaf(mlaf(0.199076 * lp, 1.096799, mp), -1.295875, sp); + let jz = (0.44 * iz) / mlaf(1., -0.56, iz) - 1.6295499532821566e-11; + Jzazbz::new(jz, az, bz) + } + + /// Converts [Jzazbz] to [Xyz] D65 + #[inline] + pub fn to_xyz(&self, display_luminance: f32) -> Xyz { + let jz = self.jz + 1.6295499532821566e-11; + + let iz = jz / mlaf(0.44f32, 0.56, jz); + let l = perceptual_quantizer_inverse(mlaf( + mlaf(iz, 1.386050432715393e-1, self.az), + 5.804731615611869e-2, + self.bz, + )); + let m = perceptual_quantizer_inverse(mlaf( + mlaf(iz, -1.386050432715393e-1, self.az), + -5.804731615611891e-2, + self.bz, + )); + let s = perceptual_quantizer_inverse(mlaf( + mlaf(iz, -9.601924202631895e-2, self.az), + -8.118918960560390e-1, + self.bz, + )); + let x = mlaf( + mlaf(1.661373055774069e+00 * l, -9.145230923250668e-01, m), + 2.313620767186147e-01, + s, + ); + let y = mlaf( + mlaf(-3.250758740427037e-01 * l, 1.571847038366936e+00, m), + -2.182538318672940e-01, + s, + ); + let z = mlaf( + mlaf(-9.098281098284756e-02 * l, -3.127282905230740e-01, m), + 1.522766561305260e+00, + s, + ); + let rel_luminance = 1f32 / display_luminance; + Xyz::new(x, y, z) * rel_luminance + } + + /// Converts into *Jzczhz* + #[inline] + pub fn to_jzczhz(&self) -> Jzczhz { + Jzczhz::from_jzazbz(*self) + } + + #[inline] + pub fn euclidean_distance(&self, other: Self) -> f32 { + let djz = self.jz - other.jz; + let daz = self.az - other.az; + let dbz = self.bz - other.bz; + (djz * djz + daz * daz + dbz * dbz).sqrt() + } + + #[inline] + pub fn taxicab_distance(&self, other: Self) -> f32 { + let djz = self.jz - other.jz; + let daz = self.az - other.az; + let dbz = self.bz - other.bz; + djz.abs() + daz.abs() + dbz.abs() + } +} + +impl Index for Jzazbz { + type Output = f32; + + #[inline] + fn index(&self, index: usize) -> &f32 { + match index { + 0 => &self.jz, + 1 => &self.az, + 2 => &self.bz, + _ => panic!("Index out of bounds for Jzazbz"), + } + } +} + +impl IndexMut for Jzazbz { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut f32 { + match index { + 0 => &mut self.jz, + 1 => &mut self.az, + 2 => &mut self.bz, + _ => panic!("Index out of bounds for Jzazbz"), + } + } +} + +impl Add for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn add(self, rhs: f32) -> Self::Output { + Jzazbz::new(self.jz + rhs, self.az + rhs, self.bz + rhs) + } +} + +impl Sub for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + Jzazbz::new(self.jz - rhs, self.az - rhs, self.bz - rhs) + } +} + +impl Mul for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + Jzazbz::new(self.jz * rhs, self.az * rhs, self.bz * rhs) + } +} + +impl Div for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + Jzazbz::new(self.jz / rhs, self.az / rhs, self.bz / rhs) + } +} + +impl Add for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn add(self, rhs: Jzazbz) -> Self::Output { + Jzazbz::new(self.jz + rhs.jz, self.az + rhs.az, self.bz + rhs.bz) + } +} + +impl Sub for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn sub(self, rhs: Jzazbz) -> Self::Output { + Jzazbz::new(self.jz - rhs.jz, self.az - rhs.az, self.bz - rhs.bz) + } +} + +impl Mul for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn mul(self, rhs: Jzazbz) -> Self::Output { + Jzazbz::new(self.jz * rhs.jz, self.az * rhs.az, self.bz * rhs.bz) + } +} + +impl Div for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn div(self, rhs: Jzazbz) -> Self::Output { + Jzazbz::new(self.jz / rhs.jz, self.az / rhs.az, self.bz / rhs.bz) + } +} + +impl AddAssign for Jzazbz { + #[inline] + fn add_assign(&mut self, rhs: Jzazbz) { + self.jz += rhs.jz; + self.az += rhs.az; + self.bz += rhs.bz; + } +} + +impl SubAssign for Jzazbz { + #[inline] + fn sub_assign(&mut self, rhs: Jzazbz) { + self.jz -= rhs.jz; + self.az -= rhs.az; + self.bz -= rhs.bz; + } +} + +impl MulAssign for Jzazbz { + #[inline] + fn mul_assign(&mut self, rhs: Jzazbz) { + self.jz *= rhs.jz; + self.az *= rhs.az; + self.bz *= rhs.bz; + } +} + +impl DivAssign for Jzazbz { + #[inline] + fn div_assign(&mut self, rhs: Jzazbz) { + self.jz /= rhs.jz; + self.az /= rhs.az; + self.bz /= rhs.bz; + } +} + +impl AddAssign for Jzazbz { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.jz += rhs; + self.az += rhs; + self.bz += rhs; + } +} + +impl SubAssign for Jzazbz { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.jz -= rhs; + self.az -= rhs; + self.bz -= rhs; + } +} + +impl MulAssign for Jzazbz { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.jz *= rhs; + self.az *= rhs; + self.bz *= rhs; + } +} + +impl DivAssign for Jzazbz { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.jz /= rhs; + self.az /= rhs; + self.bz /= rhs; + } +} + +impl Neg for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn neg(self) -> Self::Output { + Jzazbz::new(-self.jz, -self.az, -self.bz) + } +} + +impl Jzazbz { + #[inline] + pub fn sqrt(&self) -> Jzazbz { + Jzazbz::new(self.jz.sqrt(), self.az.sqrt(), self.bz.sqrt()) + } + + #[inline] + pub fn cbrt(&self) -> Jzazbz { + Jzazbz::new(f_cbrtf(self.jz), f_cbrtf(self.az), f_cbrtf(self.bz)) + } +} + +impl Pow for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + Jzazbz::new( + f_powf(self.jz, rhs), + f_powf(self.az, rhs), + f_powf(self.bz, rhs), + ) + } +} + +impl Pow for Jzazbz { + type Output = Jzazbz; + + #[inline] + fn pow(self, rhs: Jzazbz) -> Self::Output { + Jzazbz::new( + f_powf(self.jz, rhs.jz), + f_powf(self.az, self.az), + f_powf(self.bz, self.bz), + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn jzazbz_round() { + let xyz = Xyz::new(0.5, 0.4, 0.3); + let jzazbz = Jzazbz::from_xyz_with_display_luminance(xyz, 253f32); + let old_xyz = jzazbz.to_xyz(253f32); + assert!( + (xyz.x - old_xyz.x).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + assert!( + (xyz.y - old_xyz.y).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + assert!( + (xyz.z - old_xyz.z).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/jzczhz.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzczhz.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/jzczhz.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/jzczhz.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,375 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Xyz; +use crate::jzazbz::Jzazbz; +use num_traits::Pow; +use pxfm::{f_atan2f, f_cbrtf, f_hypot3f, f_hypotf, f_powf, f_sincosf, f_sinf}; +use std::ops::{ + Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, +}; + +/// Represents Jzazbz in polar coordinates as Jzczhz +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +pub struct Jzczhz { + /// Jz(lightness) generally expects to be between `0.0..1.0`. + pub jz: f32, + /// Cz generally expects to be between `-1.0..1.0`. + pub cz: f32, + /// Hz generally expects to be between `-1.0..1.0`. + pub hz: f32, +} + +impl Jzczhz { + /// Creates new instance of Jzczhz + #[inline] + pub fn new(jz: f32, cz: f32, hz: f32) -> Jzczhz { + Jzczhz { jz, cz, hz } + } + + /// Converts Jzazbz to polar coordinates Jzczhz + #[inline] + pub fn from_jzazbz(jzazbz: Jzazbz) -> Jzczhz { + let cz = f_hypotf(jzazbz.az, jzazbz.bz); + let hz = f_atan2f(jzazbz.bz, jzazbz.az); + Jzczhz::new(jzazbz.jz, cz, hz) + } + + /// Converts Jzczhz into Jzazbz + #[inline] + pub fn to_jzazbz(&self) -> Jzazbz { + let sincos = f_sincosf(self.hz); + let az = self.cz * sincos.1; + let bz = self.cz * sincos.0; + Jzazbz::new(self.jz, az, bz) + } + + /// Converts Jzczhz into Jzazbz + #[inline] + pub fn to_jzazbz_with_luminance(&self) -> Jzazbz { + let sincos = f_sincosf(self.hz); + let az = self.cz * sincos.1; + let bz = self.cz * sincos.0; + Jzazbz::new(self.jz, az, bz) + } + + /// Converts Jzczhz to *Xyz* + #[inline] + pub fn to_xyz(&self, display_luminance: f32) -> Xyz { + let jzazbz = self.to_jzazbz(); + jzazbz.to_xyz(display_luminance) + } + + /// Converts [Xyz] to [Jzczhz] + #[inline] + pub fn from_xyz(xyz: Xyz) -> Jzczhz { + let jzazbz = Jzazbz::from_xyz(xyz); + Jzczhz::from_jzazbz(jzazbz) + } + + /// Converts [Xyz] to [Jzczhz] + #[inline] + pub fn from_xyz_with_display_luminance(xyz: Xyz, luminance: f32) -> Jzczhz { + let jzazbz = Jzazbz::from_xyz_with_display_luminance(xyz, luminance); + Jzczhz::from_jzazbz(jzazbz) + } + + /// Computes distance for *Jzczhz* + #[inline] + pub fn distance(&self, other: Jzczhz) -> f32 { + let djz = self.jz - other.jz; + let dcz = self.cz - other.cz; + let dhz = self.hz - other.hz; + let dh = 2. * (self.cz * other.cz).sqrt() * f_sinf(dhz * 0.5); + f_hypot3f(djz, dcz, dh) + } + + #[inline] + pub fn euclidean_distance(&self, other: Self) -> f32 { + let djz = self.jz - other.jz; + let dhz = self.hz - other.hz; + let dcz = self.cz - other.cz; + (djz * djz + dhz * dhz + dcz * dcz).sqrt() + } + + #[inline] + pub fn taxicab_distance(&self, other: Self) -> f32 { + let djz = self.jz - other.jz; + let dhz = self.hz - other.hz; + let dcz = self.cz - other.cz; + djz.abs() + dhz.abs() + dcz.abs() + } +} + +impl Index for Jzczhz { + type Output = f32; + + #[inline] + fn index(&self, index: usize) -> &f32 { + match index { + 0 => &self.jz, + 1 => &self.cz, + 2 => &self.hz, + _ => panic!("Index out of bounds for Jzczhz"), + } + } +} + +impl IndexMut for Jzczhz { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut f32 { + match index { + 0 => &mut self.jz, + 1 => &mut self.cz, + 2 => &mut self.hz, + _ => panic!("Index out of bounds for Jzczhz"), + } + } +} + +impl Add for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn add(self, rhs: f32) -> Self::Output { + Jzczhz::new(self.jz + rhs, self.cz + rhs, self.hz + rhs) + } +} + +impl Sub for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + Jzczhz::new(self.jz - rhs, self.cz - rhs, self.hz - rhs) + } +} + +impl Mul for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + Jzczhz::new(self.jz * rhs, self.cz * rhs, self.hz * rhs) + } +} + +impl Div for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + Jzczhz::new(self.jz / rhs, self.cz / rhs, self.hz / rhs) + } +} + +impl Add for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn add(self, rhs: Jzczhz) -> Self::Output { + Jzczhz::new(self.jz + rhs.jz, self.cz + rhs.cz, self.hz + rhs.hz) + } +} + +impl Sub for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn sub(self, rhs: Jzczhz) -> Self::Output { + Jzczhz::new(self.jz - rhs.jz, self.cz - rhs.cz, self.hz - rhs.hz) + } +} + +impl Mul for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn mul(self, rhs: Jzczhz) -> Self::Output { + Jzczhz::new(self.jz * rhs.jz, self.cz * rhs.cz, self.hz * rhs.hz) + } +} + +impl Div for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn div(self, rhs: Jzczhz) -> Self::Output { + Jzczhz::new(self.jz / rhs.jz, self.cz / rhs.cz, self.hz / rhs.hz) + } +} + +impl AddAssign for Jzczhz { + #[inline] + fn add_assign(&mut self, rhs: Jzczhz) { + self.jz += rhs.jz; + self.cz += rhs.cz; + self.hz += rhs.hz; + } +} + +impl SubAssign for Jzczhz { + #[inline] + fn sub_assign(&mut self, rhs: Jzczhz) { + self.jz -= rhs.jz; + self.cz -= rhs.cz; + self.hz -= rhs.hz; + } +} + +impl MulAssign for Jzczhz { + #[inline] + fn mul_assign(&mut self, rhs: Jzczhz) { + self.jz *= rhs.jz; + self.cz *= rhs.cz; + self.hz *= rhs.hz; + } +} + +impl DivAssign for Jzczhz { + #[inline] + fn div_assign(&mut self, rhs: Jzczhz) { + self.jz /= rhs.jz; + self.cz /= rhs.cz; + self.hz /= rhs.hz; + } +} + +impl AddAssign for Jzczhz { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.jz += rhs; + self.cz += rhs; + self.hz += rhs; + } +} + +impl SubAssign for Jzczhz { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.jz -= rhs; + self.cz -= rhs; + self.hz -= rhs; + } +} + +impl MulAssign for Jzczhz { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.jz *= rhs; + self.cz *= rhs; + self.hz *= rhs; + } +} + +impl DivAssign for Jzczhz { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.jz /= rhs; + self.cz /= rhs; + self.hz /= rhs; + } +} + +impl Jzczhz { + #[inline] + pub fn sqrt(&self) -> Jzczhz { + Jzczhz::new(self.jz.sqrt(), self.cz.sqrt(), self.hz.sqrt()) + } + + #[inline] + pub fn cbrt(&self) -> Jzczhz { + Jzczhz::new(f_cbrtf(self.jz), f_cbrtf(self.cz), f_cbrtf(self.hz)) + } +} + +impl Pow for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + Jzczhz::new( + f_powf(self.jz, rhs), + f_powf(self.cz, rhs), + f_powf(self.hz, rhs), + ) + } +} + +impl Pow for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn pow(self, rhs: Jzczhz) -> Self::Output { + Jzczhz::new( + f_powf(self.jz, rhs.jz), + f_powf(self.cz, self.cz), + f_powf(self.hz, self.hz), + ) + } +} + +impl Neg for Jzczhz { + type Output = Jzczhz; + + #[inline] + fn neg(self) -> Self::Output { + Jzczhz::new(-self.jz, -self.cz, -self.hz) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn jzczhz_round() { + let xyz = Xyz::new(0.5, 0.4, 0.3); + let jzczhz = Jzczhz::from_xyz_with_display_luminance(xyz, 253.); + let old_xyz = jzczhz.to_xyz(253f32); + assert!( + (xyz.x - old_xyz.x).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + assert!( + (xyz.y - old_xyz.y).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + assert!( + (xyz.z - old_xyz.z).abs() <= 1e-3, + "{:?} != {:?}", + xyz, + old_xyz + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lab.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lab.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lab.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lab.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,240 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::{fmla, mlaf}; +use crate::{Chromaticity, LCh, Xyz}; +use pxfm::f_cbrtf; + +/// Holds CIE LAB values +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialOrd, PartialEq)] +pub struct Lab { + /// `l`: lightness component (0 to 100) + pub l: f32, + /// `a`: green (negative) and red (positive) component. + pub a: f32, + /// `b`: blue (negative) and yellow (positive) component + pub b: f32, +} + +impl Lab { + /// Create a new CIELAB color. + /// + /// # Arguments + /// + /// * `l`: lightness component (0 to 100). + /// * `a`: green (negative) and red (positive) component. + /// * `b`: blue (negative) and yellow (positive) component. + #[inline] + pub const fn new(l: f32, a: f32, b: f32) -> Self { + Self { l, a, b } + } +} + +#[inline(always)] +const fn f_1(t: f32) -> f32 { + if t <= 24.0 / 116.0 { + (108.0 / 841.0) * (t - 16.0 / 116.0) + } else { + t * t * t + } +} + +#[inline(always)] +fn f(t: f32) -> f32 { + if t <= 24. / 116. * (24. / 116.) * (24. / 116.) { + (841. / 108. * t) + 16. / 116. + } else { + f_cbrtf(t) + } +} + +impl Lab { + /// Converts to CIE Lab from CIE XYZ for PCS encoding + #[inline] + pub fn from_pcs_xyz(xyz: Xyz) -> Self { + const WP: Xyz = Chromaticity::D50.to_xyz(); + let device_x = (xyz.x as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.x as f64) as f32; + let device_y = (xyz.y as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.y as f64) as f32; + let device_z = (xyz.z as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.z as f64) as f32; + + let fx = f(device_x); + let fy = f(device_y); + let fz = f(device_z); + + let lb = mlaf(-16.0, 116.0, fy); + let a = 500.0 * (fx - fy); + let b = 200.0 * (fy - fz); + + let l = lb / 100.0; + let a = (a + 128.0) / 255.0; + let b = (b + 128.0) / 255.0; + Self::new(l, a, b) + } + + /// Converts to CIE Lab from CIE XYZ + #[inline] + pub fn from_xyz(xyz: Xyz) -> Self { + const WP: Xyz = Chromaticity::D50.to_xyz(); + let device_x = (xyz.x as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.x as f64) as f32; + let device_y = (xyz.y as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.y as f64) as f32; + let device_z = (xyz.z as f64 * (1.0f64 + 32767.0f64 / 32768.0f64) / WP.z as f64) as f32; + + let fx = f(device_x); + let fy = f(device_y); + let fz = f(device_z); + + let lb = mlaf(-16.0, 116.0, fy); + let a = 500.0 * (fx - fy); + let b = 200.0 * (fy - fz); + + Self::new(lb, a, b) + } + + /// Converts CIE [Lab] into CIE [Xyz] for PCS encoding + #[inline] + pub fn to_pcs_xyz(self) -> Xyz { + let device_l = self.l * 100.0; + let device_a = fmla(self.a, 255.0, -128.0); + let device_b = fmla(self.b, 255.0, -128.0); + + let y = (device_l + 16.0) / 116.0; + + const WP: Xyz = Chromaticity::D50.to_xyz(); + + let x = f_1(mlaf(y, 0.002, device_a)) * WP.x; + let y1 = f_1(y) * WP.y; + let z = f_1(mlaf(y, -0.005, device_b)) * WP.z; + + let x = (x as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + let y = (y1 as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + let z = (z as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + Xyz::new(x, y, z) + } + + /// Converts CIE [Lab] into CIE [Xyz] + #[inline] + pub fn to_xyz(self) -> Xyz { + let device_l = self.l; + let device_a = self.a; + let device_b = self.b; + + let y = (device_l + 16.0) / 116.0; + + const WP: Xyz = Chromaticity::D50.to_xyz(); + + let x = f_1(mlaf(y, 0.002, device_a)) * WP.x; + let y1 = f_1(y) * WP.y; + let z = f_1(mlaf(y, -0.005, device_b)) * WP.z; + + let x = (x as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + let y = (y1 as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + let z = (z as f64 / (1.0f64 + 32767.0f64 / 32768.0f64)) as f32; + Xyz::new(x, y, z) + } + + /// Desaturates out of gamut PCS encoded LAB + pub fn desaturate_pcs(self) -> Lab { + if self.l < 0. { + return Lab::new(0., 0., 0.); + } + + let mut new_lab = self; + if new_lab.l > 1. { + new_lab.l = 1.; + } + + let amax = 1.0; + let amin = 0.0; + let bmin = 0.0; + let bmax = 1.0; + if self.a < amin || self.a > amax || self.b < bmin || self.b > bmax { + if self.a == 0.0 { + // Is hue exactly 90? + // atan will not work, so clamp here + return Lab::new(self.l, self.a, self.b); + } + + let lch = LCh::from_lab(new_lab); + + let slope = new_lab.b / new_lab.a; + let h = lch.h * (180.0 / std::f32::consts::PI); + + // There are 4 zones + if (0. ..45.).contains(&h) || (315. ..=360.).contains(&h) { + // clip by amax + new_lab.a = amax; + new_lab.b = amax * slope; + } else if (45. ..135.).contains(&h) { + // clip by bmax + new_lab.b = bmax; + new_lab.a = bmax / slope; + } else if (135. ..225.).contains(&h) { + // clip by amin + new_lab.a = amin; + new_lab.b = amin * slope; + } else if (225. ..315.).contains(&h) { + // clip by bmin + new_lab.b = bmin; + new_lab.a = bmin / slope; + } + } + new_lab + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip() { + let xyz = Xyz::new(0.1, 0.2, 0.3); + let lab = Lab::from_xyz(xyz); + let rolled_back = lab.to_xyz(); + let dx = (xyz.x - rolled_back.x).abs(); + let dy = (xyz.y - rolled_back.y).abs(); + let dz = (xyz.z - rolled_back.z).abs(); + assert!(dx < 1e-5); + assert!(dy < 1e-5); + assert!(dz < 1e-5); + } + + #[test] + fn round_pcs_trip() { + let xyz = Xyz::new(0.1, 0.2, 0.3); + let lab = Lab::from_pcs_xyz(xyz); + let rolled_back = lab.to_pcs_xyz(); + let dx = (xyz.x - rolled_back.x).abs(); + let dy = (xyz.y - rolled_back.y).abs(); + let dz = (xyz.z - rolled_back.z).abs(); + assert!(dx < 1e-5); + assert!(dy < 1e-5); + assert!(dz < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(clippy::manual_clamp, clippy::excessive_precision)] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(unreachable_pub)] +#![deny( + clippy::print_stdout, + clippy::print_stderr, + clippy::print_literal, + clippy::print_in_format_impl +)] +#![allow(stable_features)] +#![cfg_attr( + not(any(feature = "avx", feature = "sse", feature = "avx512", feature = "neon")), + forbid(unsafe_code) +)] +mod chad; +mod cicp; +mod conversions; +mod dat; +mod defaults; +mod err; +mod gamma; +mod gamut; +mod ictcp; +mod jzazbz; +mod jzczhz; +mod lab; +mod luv; +/// One of main intent is to provide fast math available in const context +/// ULP most of the methods <= 0.5 +mod math; +mod matrix; +mod mlaf; +mod nd_array; +mod oklab; +mod oklch; +mod profile; +mod reader; +mod rgb; +mod safe_math; +mod tag; +mod transform; +mod trc; +mod writer; +mod yrg; +// Simple math analysis module +mod chromaticity; +mod dt_ucs; +mod helpers; +mod lut_hint; +mod matan; +mod srlab2; +mod xyy; + +pub use chad::{ + adapt_to_d50, adapt_to_d50_d, adapt_to_illuminant, adapt_to_illuminant_d, + adapt_to_illuminant_xyz, adapt_to_illuminant_xyz_d, adaption_matrix, adaption_matrix_d, +}; +pub use chromaticity::Chromaticity; +pub use cicp::{CicpColorPrimaries, ColorPrimaries, MatrixCoefficients, TransferCharacteristics}; +pub use dat::ColorDateTime; +pub use defaults::{ + HLG_LUT_TABLE, PQ_LUT_TABLE, WHITE_POINT_D50, WHITE_POINT_D60, WHITE_POINT_D65, + WHITE_POINT_DCI_P3, +}; +pub use dt_ucs::{DtUchHcb, DtUchHsb, DtUchJch}; +pub use err::{CmsError, MalformedSize}; +pub use gamut::filmlike_clip; +pub use ictcp::ICtCp; +pub use jzazbz::Jzazbz; +pub use jzczhz::Jzczhz; +pub use lab::Lab; +pub use luv::{LCh, Luv}; +pub use math::rounding_div_ceil; +pub use matrix::{ + BT2020_MATRIX, DISPLAY_P3_MATRIX, Matrix3, Matrix3d, Matrix3f, Matrix4f, SRGB_MATRIX, Vector3, + Vector3d, Vector3f, Vector3i, Vector3u, Vector4, Vector4d, Vector4f, Vector4i, Xyz, Xyzd, +}; +pub use nd_array::{Cube, Hypercube}; +pub use oklab::Oklab; +pub use oklch::Oklch; +pub use profile::{ + CicpProfile, ColorProfile, DataColorSpace, DescriptionString, LocalizableString, LutDataType, + LutMultidimensionalType, LutStore, LutType, LutWarehouse, Measurement, MeasurementGeometry, + ParsingOptions, ProfileClass, ProfileSignature, ProfileText, ProfileVersion, RenderingIntent, + StandardIlluminant, StandardObserver, TechnologySignatures, ViewingConditions, +}; +pub use rgb::{FusedExp, FusedExp2, FusedExp10, FusedLog, FusedLog2, FusedLog10, FusedPow, Rgb}; +pub use srlab2::Srlab2; +pub use transform::{ + BarycentricWeightScale, InPlaceStage, InterpolationMethod, Layout, PointeeSizeExpressible, + Stage, Transform8BitExecutor, Transform16BitExecutor, TransformExecutor, + TransformF32BitExecutor, TransformF64BitExecutor, TransformOptions, +}; +pub use trc::{GammaLutInterpolate, ToneCurveEvaluator, ToneReprCurve, curve_from_gamma}; +pub use xyy::{XyY, XyYRepresentable}; +pub use yrg::{Ych, Yrg, cie_y_1931_to_cie_y_2006}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lut_hint.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lut_hint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/lut_hint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/lut_hint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::LutWarehouse; + +impl LutWarehouse { + /// Method tests if mathematical fusion on LUT table is allowed. + /// If it's not, full brute-force pass in [Katana] is required. + pub(crate) fn is_katana_required(&self) -> bool { + match self { + LutWarehouse::Lut(lut) => { + let input_entries = lut.num_input_channels as usize; + let output_entries = lut.num_output_channels as usize; + for i in 0..input_entries { + if lut.input_table.is_degenerated(input_entries, i) { + return true; + } + if !lut.input_table.is_monotonic(input_entries, i) { + return true; + } + if lut.input_table.have_discontinuities(input_entries, i) { + return true; + } + } + + for i in 0..output_entries { + if lut.output_table.is_degenerated(output_entries, i) { + return true; + } + if !lut.output_table.is_monotonic(output_entries, i) { + return true; + } + if lut.output_table.have_discontinuities(output_entries, i) { + return true; + } + } + + false + } + LutWarehouse::Multidimensional(mab) => { + for curve in mab.a_curves.iter() { + if curve.is_degenerated() { + return true; + } + if !curve.is_monotonic() { + return true; + } + if curve.have_discontinuities() { + return true; + } + } + + for curve in mab.m_curves.iter() { + if curve.is_degenerated() { + return true; + } + if !curve.is_monotonic() { + return true; + } + if curve.have_discontinuities() { + return true; + } + } + + for curve in mab.b_curves.iter() { + if curve.is_degenerated() { + return true; + } + if !curve.is_monotonic() { + return true; + } + if curve.have_discontinuities() { + return true; + } + } + + false + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/luv.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/luv.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/luv.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/luv.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,698 @@ +/* + * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved. + * // + * // Use of this source code is governed by a BSD-style + * // license that can be found in the LICENSE file. + */ + +//! # Luv +/// Struct representing a color in CIE LUV, a.k.a. L\*u\*v\*, color space +#[repr(C)] +#[derive(Debug, Copy, Clone, Default, PartialOrd)] +pub struct Luv { + /// The L\* value (achromatic luminance) of the colour in 0–100 range. + pub l: f32, + /// The u\* value of the colour. + /// + /// Together with v\* value, it defines chromaticity of the colour. The u\* + /// coordinate represents colour’s position on red-green axis with negative + /// values indicating more red and positive more green colour. Typical + /// values are in -134–220 range (but exact range for ‘valid’ colours + /// depends on luminance and v\* value). + pub u: f32, + /// The u\* value of the colour. + /// + /// Together with u\* value, it defines chromaticity of the colour. The v\* + /// coordinate represents colour’s position on blue-yellow axis with + /// negative values indicating more blue and positive more yellow colour. + /// Typical values are in -140–122 range (but exact range for ‘valid’ + /// colours depends on luminance and u\* value). + pub v: f32, +} + +/// Representing a color in cylindrical CIE LCh(uv) color space +#[repr(C)] +#[derive(Debug, Copy, Clone, Default, PartialOrd)] +pub struct LCh { + /// The L\* value (achromatic luminance) of the colour in 0–100 range. + /// + /// This is the same value as in the [`Luv`] object. + pub l: f32, + /// The C\*_uv value (chroma) of the colour. + /// + /// Together with h_uv, it defines chromaticity of the colour. The typical + /// values of the coordinate go from zero up to around 150 (but exact range + /// for ‘valid’ colours depends on luminance and hue). Zero represents + /// shade of grey. + pub c: f32, + /// The h_uv value (hue) of the colour measured in radians. + /// + /// Together with C\*_uv, it defines chromaticity of the colour. The value + /// represents an angle thus it wraps around τ. Typically, the value will + /// be in the -π–π range. The value is undefined if C\*_uv is zero. + pub h: f32, +} + +use crate::mlaf::mlaf; +use crate::{Chromaticity, Lab, Xyz}; +use num_traits::Pow; +use pxfm::{f_atan2f, f_cbrtf, f_hypotf, f_powf, f_sincosf}; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; + +pub(crate) const LUV_WHITE_U_PRIME: f32 = 4.0f32 * Chromaticity::D50.to_xyz().y + / (Chromaticity::D50.to_xyz().x + + 15.0 * Chromaticity::D50.to_xyz().y + + 3.0 * Chromaticity::D50.to_xyz().z); +pub(crate) const LUV_WHITE_V_PRIME: f32 = 9.0f32 * Chromaticity::D50.to_xyz().y + / (Chromaticity::D50.to_xyz().x + + 15.0 * Chromaticity::D50.to_xyz().y + + 3.0 * Chromaticity::D50.to_xyz().z); + +pub(crate) const LUV_CUTOFF_FORWARD_Y: f32 = (6f32 / 29f32) * (6f32 / 29f32) * (6f32 / 29f32); +pub(crate) const LUV_MULTIPLIER_FORWARD_Y: f32 = (29f32 / 3f32) * (29f32 / 3f32) * (29f32 / 3f32); +pub(crate) const LUV_MULTIPLIER_INVERSE_Y: f32 = (3f32 / 29f32) * (3f32 / 29f32) * (3f32 / 29f32); +impl Luv { + /// Converts CIE XYZ to CIE Luv using D50 white point + #[inline] + #[allow(clippy::manual_clamp)] + pub fn from_xyz(xyz: Xyz) -> Self { + let [x, y, z] = [xyz.x, xyz.y, xyz.z]; + let den = mlaf(mlaf(x, 15.0, y), 3.0, z); + + let l = (if y < LUV_CUTOFF_FORWARD_Y { + LUV_MULTIPLIER_FORWARD_Y * y + } else { + 116. * f_cbrtf(y) - 16. + }) + .min(100.) + .max(0.); + let (u, v); + if den != 0f32 { + let u_prime = 4. * x / den; + let v_prime = 9. * y / den; + u = 13. * l * (u_prime - LUV_WHITE_U_PRIME); + v = 13. * l * (v_prime - LUV_WHITE_V_PRIME); + } else { + u = 0.; + v = 0.; + } + + Luv { l, u, v } + } + + /// To [Xyz] using D50 colorimetry + #[inline] + pub fn to_xyz(&self) -> Xyz { + if self.l <= 0. { + return Xyz::new(0., 0., 0.); + } + let l13 = 1. / (13. * self.l); + let u = mlaf(LUV_WHITE_U_PRIME, self.u, l13); + let v = mlaf(LUV_WHITE_V_PRIME, self.v, l13); + let y = if self.l > 8. { + let jx = (self.l + 16.) / 116.; + jx * jx * jx + } else { + self.l * LUV_MULTIPLIER_INVERSE_Y + }; + let (x, z); + if v != 0. { + let den = 1. / (4. * v); + x = y * 9. * u * den; + z = y * mlaf(mlaf(12.0, -3.0, u), -20., v) * den; + } else { + x = 0.; + z = 0.; + } + + Xyz::new(x, y, z) + } + + #[inline] + pub const fn new(l: f32, u: f32, v: f32) -> Luv { + Luv { l, u, v } + } +} + +impl LCh { + #[inline] + pub const fn new(l: f32, c: f32, h: f32) -> Self { + LCh { l, c, h } + } + + /// Converts Lab to LCh(uv) + #[inline] + pub fn from_luv(luv: Luv) -> Self { + LCh { + l: luv.l, + c: f_hypotf(luv.u, luv.v), + h: f_atan2f(luv.v, luv.u), + } + } + + /// Converts Lab to LCh(ab) + #[inline] + pub fn from_lab(lab: Lab) -> Self { + LCh { + l: lab.l, + c: f_hypotf(lab.a, lab.b), + h: f_atan2f(lab.b, lab.a), + } + } + + /// Computes LCh(uv) + #[inline] + pub fn from_xyz(xyz: Xyz) -> Self { + Self::from_luv(Luv::from_xyz(xyz)) + } + + /// Computes LCh(ab) + #[inline] + pub fn from_xyz_lab(xyz: Xyz) -> Self { + Self::from_lab(Lab::from_xyz(xyz)) + } + + /// Converts LCh(uv) to Luv + #[inline] + pub fn to_xyz(&self) -> Xyz { + self.to_luv().to_xyz() + } + + /// Converts LCh(ab) to Lab + #[inline] + pub fn to_xyz_lab(&self) -> Xyz { + self.to_lab().to_xyz() + } + + #[inline] + pub fn to_luv(&self) -> Luv { + let sincos = f_sincosf(self.h); + Luv { + l: self.l, + u: self.c * sincos.1, + v: self.c * sincos.0, + } + } + + #[inline] + pub fn to_lab(&self) -> Lab { + let sincos = f_sincosf(self.h); + Lab { + l: self.l, + a: self.c * sincos.1, + b: self.c * sincos.0, + } + } +} + +impl PartialEq for Luv { + /// Compares two colours ignoring chromaticity if L\* is zero. + #[inline] + fn eq(&self, other: &Self) -> bool { + if self.l != other.l { + false + } else if self.l == 0.0 { + true + } else { + self.u == other.u && self.v == other.v + } + } +} + +impl PartialEq for LCh { + /// Compares two colors ignoring chromaticity if L\* is zero and hue if C\* + /// is zero. Hues which are τ apart are compared equal. + #[inline] + fn eq(&self, other: &Self) -> bool { + if self.l != other.l { + false + } else if self.l == 0.0 { + true + } else if self.c != other.c { + false + } else if self.c == 0.0 { + true + } else { + use std::f32::consts::TAU; + self.h.rem_euclid(TAU) == other.h.rem_euclid(TAU) + } + } +} + +impl Luv { + #[inline] + pub fn euclidean_distance(&self, other: Luv) -> f32 { + let dl = self.l - other.l; + let du = self.u - other.u; + let dv = self.v - other.v; + (dl * dl + du * du + dv * dv).sqrt() + } +} + +impl LCh { + #[inline] + pub fn euclidean_distance(&self, other: LCh) -> f32 { + let dl = self.l - other.l; + let dc = self.c - other.c; + let dh = self.h - other.h; + (dl * dl + dc * dc + dh * dh).sqrt() + } +} + +impl Luv { + #[inline] + pub const fn taxicab_distance(&self, other: Self) -> f32 { + let dl = self.l - other.l; + let du = self.u - other.u; + let dv = self.v - other.v; + dl.abs() + du.abs() + dv.abs() + } +} + +impl LCh { + #[inline] + pub const fn taxicab_distance(&self, other: Self) -> f32 { + let dl = self.l - other.l; + let dc = self.c - other.c; + let dh = self.h - other.h; + dl.abs() + dc.abs() + dh.abs() + } +} + +impl Add for Luv { + type Output = Luv; + + #[inline] + fn add(self, rhs: Luv) -> Luv { + Luv::new(self.l + rhs.l, self.u + rhs.u, self.v + rhs.v) + } +} + +impl Add for LCh { + type Output = LCh; + + #[inline] + fn add(self, rhs: LCh) -> LCh { + LCh::new(self.l + rhs.l, self.c + rhs.c, self.h + rhs.h) + } +} + +impl Sub for Luv { + type Output = Luv; + + #[inline] + fn sub(self, rhs: Luv) -> Luv { + Luv::new(self.l - rhs.l, self.u - rhs.u, self.v - rhs.v) + } +} + +impl Sub for LCh { + type Output = LCh; + + #[inline] + fn sub(self, rhs: LCh) -> LCh { + LCh::new(self.l - rhs.l, self.c - rhs.c, self.h - rhs.h) + } +} + +impl Mul for Luv { + type Output = Luv; + + #[inline] + fn mul(self, rhs: Luv) -> Luv { + Luv::new(self.l * rhs.l, self.u * rhs.u, self.v * rhs.v) + } +} + +impl Mul for LCh { + type Output = LCh; + + #[inline] + fn mul(self, rhs: LCh) -> LCh { + LCh::new(self.l * rhs.l, self.c * rhs.c, self.h * rhs.h) + } +} + +impl Div for Luv { + type Output = Luv; + + #[inline] + fn div(self, rhs: Luv) -> Luv { + Luv::new(self.l / rhs.l, self.u / rhs.u, self.v / rhs.v) + } +} + +impl Div for LCh { + type Output = LCh; + + #[inline] + fn div(self, rhs: LCh) -> LCh { + LCh::new(self.l / rhs.l, self.c / rhs.c, self.h / rhs.h) + } +} + +impl Add for Luv { + type Output = Luv; + + #[inline] + fn add(self, rhs: f32) -> Self::Output { + Luv::new(self.l + rhs, self.u + rhs, self.v + rhs) + } +} + +impl Add for LCh { + type Output = LCh; + + #[inline] + fn add(self, rhs: f32) -> Self::Output { + LCh::new(self.l + rhs, self.c + rhs, self.h + rhs) + } +} + +impl Sub for Luv { + type Output = Luv; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + Luv::new(self.l - rhs, self.u - rhs, self.v - rhs) + } +} + +impl Sub for LCh { + type Output = LCh; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + LCh::new(self.l - rhs, self.c - rhs, self.h - rhs) + } +} + +impl Mul for Luv { + type Output = Luv; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + Luv::new(self.l * rhs, self.u * rhs, self.v * rhs) + } +} + +impl Mul for LCh { + type Output = LCh; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + LCh::new(self.l * rhs, self.c * rhs, self.h * rhs) + } +} + +impl Div for Luv { + type Output = Luv; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + Luv::new(self.l / rhs, self.u / rhs, self.v / rhs) + } +} + +impl Div for LCh { + type Output = LCh; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + LCh::new(self.l / rhs, self.c / rhs, self.h / rhs) + } +} + +impl AddAssign for Luv { + #[inline] + fn add_assign(&mut self, rhs: Luv) { + self.l += rhs.l; + self.u += rhs.u; + self.v += rhs.v; + } +} + +impl AddAssign for LCh { + #[inline] + fn add_assign(&mut self, rhs: LCh) { + self.l += rhs.l; + self.c += rhs.c; + self.h += rhs.h; + } +} + +impl SubAssign for Luv { + #[inline] + fn sub_assign(&mut self, rhs: Luv) { + self.l -= rhs.l; + self.u -= rhs.u; + self.v -= rhs.v; + } +} + +impl SubAssign for LCh { + #[inline] + fn sub_assign(&mut self, rhs: LCh) { + self.l -= rhs.l; + self.c -= rhs.c; + self.h -= rhs.h; + } +} + +impl MulAssign for Luv { + #[inline] + fn mul_assign(&mut self, rhs: Luv) { + self.l *= rhs.l; + self.u *= rhs.u; + self.v *= rhs.v; + } +} + +impl MulAssign for LCh { + #[inline] + fn mul_assign(&mut self, rhs: LCh) { + self.l *= rhs.l; + self.c *= rhs.c; + self.h *= rhs.h; + } +} + +impl DivAssign for Luv { + #[inline] + fn div_assign(&mut self, rhs: Luv) { + self.l /= rhs.l; + self.u /= rhs.u; + self.v /= rhs.v; + } +} + +impl DivAssign for LCh { + #[inline] + fn div_assign(&mut self, rhs: LCh) { + self.l /= rhs.l; + self.c /= rhs.c; + self.h /= rhs.h; + } +} + +impl AddAssign for Luv { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.l += rhs; + self.u += rhs; + self.v += rhs; + } +} + +impl AddAssign for LCh { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.l += rhs; + self.c += rhs; + self.h += rhs; + } +} + +impl SubAssign for Luv { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.l -= rhs; + self.u -= rhs; + self.v -= rhs; + } +} + +impl SubAssign for LCh { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.l -= rhs; + self.c -= rhs; + self.h -= rhs; + } +} + +impl MulAssign for Luv { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.l *= rhs; + self.u *= rhs; + self.v *= rhs; + } +} + +impl MulAssign for LCh { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.l *= rhs; + self.c *= rhs; + self.h *= rhs; + } +} + +impl DivAssign for Luv { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.l /= rhs; + self.u /= rhs; + self.v /= rhs; + } +} + +impl DivAssign for LCh { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.l /= rhs; + self.c /= rhs; + self.h /= rhs; + } +} + +impl Neg for LCh { + type Output = LCh; + + #[inline] + fn neg(self) -> Self::Output { + LCh::new(-self.l, -self.c, -self.h) + } +} + +impl Neg for Luv { + type Output = Luv; + + #[inline] + fn neg(self) -> Self::Output { + Luv::new(-self.l, -self.u, -self.v) + } +} + +impl Pow for Luv { + type Output = Luv; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + Luv::new( + f_powf(self.l, rhs), + f_powf(self.u, rhs), + f_powf(self.v, rhs), + ) + } +} + +impl Pow for LCh { + type Output = LCh; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + LCh::new( + f_powf(self.l, rhs), + f_powf(self.c, rhs), + f_powf(self.h, rhs), + ) + } +} + +impl Pow for Luv { + type Output = Luv; + + #[inline] + fn pow(self, rhs: Luv) -> Self::Output { + Luv::new( + f_powf(self.l, rhs.l), + f_powf(self.u, rhs.u), + f_powf(self.v, rhs.v), + ) + } +} + +impl Pow for LCh { + type Output = LCh; + + #[inline] + fn pow(self, rhs: LCh) -> Self::Output { + LCh::new( + f_powf(self.l, rhs.l), + f_powf(self.c, rhs.c), + f_powf(self.h, rhs.h), + ) + } +} + +impl Luv { + #[inline] + pub fn sqrt(&self) -> Luv { + Luv::new(self.l.sqrt(), self.u.sqrt(), self.v.sqrt()) + } + + #[inline] + pub fn cbrt(&self) -> Luv { + Luv::new(f_cbrtf(self.l), f_cbrtf(self.u), f_cbrtf(self.v)) + } +} + +impl LCh { + #[inline] + pub fn sqrt(&self) -> LCh { + LCh::new( + if self.l < 0. { 0. } else { self.l.sqrt() }, + if self.c < 0. { 0. } else { self.c.sqrt() }, + if self.h < 0. { 0. } else { self.h.sqrt() }, + ) + } + + #[inline] + pub fn cbrt(&self) -> LCh { + LCh::new(f_cbrtf(self.l), f_cbrtf(self.c), f_cbrtf(self.h)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_luv() { + let xyz = Xyz::new(0.1, 0.2, 0.3); + let lab = Luv::from_xyz(xyz); + let rolled_back = lab.to_xyz(); + let dx = (xyz.x - rolled_back.x).abs(); + let dy = (xyz.y - rolled_back.y).abs(); + let dz = (xyz.z - rolled_back.z).abs(); + assert!(dx < 1e-5); + assert!(dy < 1e-5); + assert!(dz < 1e-5); + } + + #[test] + fn round_trip_lch() { + let xyz = Xyz::new(0.1, 0.2, 0.3); + let luv = Luv::from_xyz(xyz); + let lab = LCh::from_luv(luv); + let rolled_back = lab.to_luv(); + let dx = (luv.l - rolled_back.l).abs(); + let dy = (luv.u - rolled_back.u).abs(); + let dz = (luv.v - rolled_back.v).abs(); + assert!(dx < 1e-4); + assert!(dy < 1e-4); + assert!(dz < 1e-4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/curve_shape.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/curve_shape.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/curve_shape.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/curve_shape.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +pub(crate) fn is_curve_linear16(curve: &[u16]) -> bool { + let scale = 1. / (curve.len() - 1) as f32 * 65535.; + for (index, &value) in curve.iter().enumerate() { + let quantized = (index as f32 * scale).round() as u16; + let diff = (quantized as i32 - value as i32).abs(); + if diff > 0x0f { + return false; + } + } + true +} + +pub(crate) fn is_curve_descending(v: &[T]) -> bool { + if v.is_empty() { + return false; + } + if v.len() == 1 { + return false; + } + v[0] > v[v.len() - 1] +} + +pub(crate) fn is_curve_ascending(v: &[T]) -> bool { + if v.is_empty() { + return false; + } + if v.len() == 1 { + return false; + } + v[0] < v[v.len() - 1] +} + +pub(crate) fn is_curve_linear8(curve: &[u8]) -> bool { + let scale = 1. / (curve.len() - 1) as f32 * 255.; + for (index, &value) in curve.iter().enumerate() { + let quantized = (index as f32 * scale).round() as u16; + let diff = (quantized as i32 - value as i32).abs(); + if diff > 0x03 { + return false; + } + } + true +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/degeneration.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/degeneration.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/degeneration.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/degeneration.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[derive(Copy, Clone, Default, Debug)] +struct DegenerationAmount { + leading: usize, + trailing: usize, +} + +/// Counts amount of duplicates on each side of curve +fn count_leading_trailing_duplicated(lut: &[T]) -> DegenerationAmount { + if lut.is_empty() { + return DegenerationAmount::default(); + } + let first = lut.first().unwrap(); + let last = lut.last().unwrap(); + let leading = lut.iter().take_while(|&v| v.eq(first)).count(); + let trailing = lut.iter().rev().take_while(|&v| v.eq(last)).count(); + DegenerationAmount { leading, trailing } +} + +/// Finds out if curve is degenerated on the sides. +pub(crate) fn is_curve_degenerated(v: &[T]) -> bool { + if v.is_empty() || v.len() < 2 { + return false; + } + let degeneration_amount = count_leading_trailing_duplicated(v); + if degeneration_amount.trailing <= 1 && degeneration_amount.leading <= 1 { + return false; + } + let leading_percentage = degeneration_amount.leading; + let trailing_percentage = degeneration_amount.trailing; + ((leading_percentage / 20) > 0) || ((trailing_percentage / 20) > 0) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/discontinuity.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/discontinuity.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/discontinuity.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/discontinuity.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use num_traits::AsPrimitive; + +pub(crate) trait DiscontinuitySpike { + const SPIKE: f64; +} + +impl DiscontinuitySpike for u8 { + const SPIKE: f64 = 16.0; +} + +impl DiscontinuitySpike for u16 { + const SPIKE: f64 = 2100.; +} + +impl DiscontinuitySpike for f32 { + const SPIKE: f64 = 0.07; +} + +/// Searches LUT curve for discontinuity +pub(crate) fn does_curve_have_discontinuity< + T: Copy + PartialEq + DiscontinuitySpike + AsPrimitive + 'static, +>( + curve: &[T], +) -> bool { + if curve.len() < 2 { + return false; + } + let threshold: f64 = T::SPIKE; + let mut discontinuities = 0u64; + let mut previous_element: f64 = curve[0].as_(); + let diff: f64 = (curve[1].as_() - previous_element).abs(); + if diff > threshold { + discontinuities += 1; + } + for element in curve.iter().skip(1) { + let new_diff: f64 = (element.as_() - previous_element).abs(); + if new_diff > threshold { + discontinuities += 1; + if discontinuities > 3 { + break; + } + } + previous_element = element.as_(); + } + discontinuities > 3 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod curve_shape; +mod degeneration; +mod discontinuity; +mod monotonic; +mod slope_limit; + +pub(crate) use curve_shape::{ + is_curve_ascending, is_curve_descending, is_curve_linear8, is_curve_linear16, +}; +pub(crate) use degeneration::is_curve_degenerated; +pub(crate) use discontinuity::does_curve_have_discontinuity; +pub(crate) use monotonic::is_curve_monotonic; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/monotonic.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/monotonic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/monotonic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/monotonic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::matan::is_curve_ascending; + +/// Finds out if curve is monotonic. +pub(crate) fn is_curve_monotonic(lut: &[T]) -> bool { + if lut.len() < 2 { + return true; + } + let is_ascending = is_curve_ascending(lut); + let mut violations = 0usize; + if is_ascending { + for (current, previous) in lut.iter().skip(1).zip(lut.iter().take(lut.len() - 1)) { + if current.lt(previous) { + violations += 1; + } + } + } else { + for (current, previous) in lut.iter().skip(1).zip(lut.iter().take(lut.len() - 1)) { + if current.gt(previous) { + violations += 1; + } + } + } + (violations as f64 / lut.len() as f64) < 0.05 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/slope_limit.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/slope_limit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matan/slope_limit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matan/slope_limit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] +use crate::PointeeSizeExpressible; +use crate::matan::is_curve_descending; +use num_traits::AsPrimitive; + +pub(crate) fn limit_slope + PartialOrd + PointeeSizeExpressible>( + curve: &mut [T], + value_cap: f32, +) where + f32: AsPrimitive, +{ + let at_begin = (curve.len() as f32 * 0.02 + 0.5).floor() as usize; // Cutoff at 2% + if at_begin == 0 { + return; + } + let at_end = curve.len() - at_begin - 1; // And 98% + let (begin_val, end_val) = if is_curve_descending(curve) { + (value_cap, 0.) + } else { + (0., value_cap) + }; + let val = curve[at_begin].as_(); + let slope = (val - begin_val) / at_begin as f32; + let beta = val - slope * at_begin as f32; + if T::FINITE { + for v in curve.iter_mut().take(at_begin) { + *v = (v.as_() * slope + beta) + .round() + .min(value_cap) + .max(0.0) + .as_(); + } + } else { + for v in curve.iter_mut().take(at_begin) { + *v = (v.as_() * slope + beta).min(value_cap).max(0.0).as_(); + } + } + + let val = curve[at_end].as_(); + let slope = (end_val - val) / at_begin as f32; + let beta = val - slope * at_end as f32; + + if T::FINITE { + for v in curve.iter_mut().skip(at_end) { + *v = (v.as_() * slope + beta) + .round() + .min(value_cap) + .max(0.0) + .as_(); + } + } else { + for v in curve.iter_mut().skip(at_end) { + *v = (v.as_() * slope + beta).min(value_cap).max(0.0).as_(); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/math/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/math/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/math/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/math/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(clippy::approx_constant, clippy::manual_range_contains)] + +use num_traits::Num; + +#[inline(always)] +pub const fn rounding_div_ceil(value: i32, div: i32) -> i32 { + (value + div - 1) / div +} + +// Generic function for max +#[inline(always)] +pub(crate) fn m_max(a: T, b: T) -> T { + if a > b { a } else { b } +} + +// Generic function for min +#[inline(always)] +pub(crate) fn m_min(a: T, b: T) -> T { + if a < b { a } else { b } +} + +#[inline] +pub(crate) fn m_clamp(a: T, min: T, max: T) -> T { + if a > max { + max + } else if a >= min { + a + } else { + // a < min or a is NaN + min + } +} + +pub trait FusedMultiplyAdd { + fn mla(&self, b: T, c: T) -> T; +} + +pub(crate) trait FusedMultiplyNegAdd { + fn neg_mla(&self, b: T, c: T) -> T; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matrix.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matrix.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/matrix.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/matrix.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1272 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use crate::mlaf::{mlaf, neg_mlaf}; +use crate::reader::s15_fixed16_number_to_double; +use num_traits::{AsPrimitive, MulAdd}; +use std::ops::{Add, Div, Mul, Neg, Shr, Sub}; + +/// Vector math helper +#[repr(transparent)] +#[derive(Copy, Clone, Debug, Default)] +pub struct Vector3 { + pub v: [T; 3], +} + +/// Vector math helper +#[repr(transparent)] +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct Vector4 { + pub v: [T; 4], +} + +pub type Vector4f = Vector4; +pub type Vector4d = Vector4; +pub type Vector4i = Vector4; + +pub type Vector3f = Vector3; +pub type Vector3d = Vector3; +pub type Vector3i = Vector3; +pub type Vector3u = Vector3; + +impl PartialEq for Vector3 +where + T: AsPrimitive, +{ + #[inline(always)] + fn eq(&self, other: &Self) -> bool { + const TOLERANCE: f32 = 0.0001f32; + let dx = (self.v[0].as_() - other.v[0].as_()).abs(); + let dy = (self.v[1].as_() - other.v[1].as_()).abs(); + let dz = (self.v[2].as_() - other.v[2].as_()).abs(); + dx < TOLERANCE && dy < TOLERANCE && dz < TOLERANCE + } +} + +impl Vector3 { + #[inline(always)] + pub fn to_(self) -> Vector3 + where + T: AsPrimitive, + { + Vector3 { + v: [self.v[0].as_(), self.v[1].as_(), self.v[2].as_()], + } + } +} + +impl Mul> for Vector3 +where + T: Mul + Copy, +{ + type Output = Vector3; + + #[inline(always)] + fn mul(self, rhs: Vector3) -> Self::Output { + Self { + v: [ + self.v[0] * rhs.v[0], + self.v[1] * rhs.v[1], + self.v[2] * rhs.v[2], + ], + } + } +} + +impl Shr for Vector3 +where + T: Shr, +{ + type Output = Vector3; + fn shr(self, rhs: i32) -> Self::Output { + Self { + v: [self.v[0] >> rhs, self.v[1] >> rhs, self.v[2] >> rhs], + } + } +} + +impl Shr for Vector4 +where + T: Shr, +{ + type Output = Vector4; + fn shr(self, rhs: i32) -> Self::Output { + Self { + v: [ + self.v[0] >> rhs, + self.v[1] >> rhs, + self.v[2] >> rhs, + self.v[3] >> rhs, + ], + } + } +} + +impl Mul> for Vector4 +where + T: Mul + Copy, +{ + type Output = Vector4; + + #[inline(always)] + fn mul(self, rhs: Vector4) -> Self::Output { + Self { + v: [ + self.v[0] * rhs.v[0], + self.v[1] * rhs.v[1], + self.v[2] * rhs.v[2], + self.v[3] * rhs.v[3], + ], + } + } +} + +impl Mul for Vector3 +where + T: Mul + Copy, +{ + type Output = Vector3; + + #[inline(always)] + fn mul(self, rhs: T) -> Self::Output { + Self { + v: [self.v[0] * rhs, self.v[1] * rhs, self.v[2] * rhs], + } + } +} + +impl Vector3 { + #[inline(always)] + const fn const_mul_vector(self, v: Vector3f) -> Vector3f { + Vector3f { + v: [self.v[0] * v.v[0], self.v[1] * v.v[1], self.v[2] * v.v[2]], + } + } +} + +impl Vector3d { + #[inline(always)] + const fn const_mul_vector(self, v: Vector3d) -> Vector3d { + Vector3d { + v: [self.v[0] * v.v[0], self.v[1] * v.v[1], self.v[2] * v.v[2]], + } + } +} + +impl Vector3 { + pub fn cast(&self) -> Vector3 + where + T: AsPrimitive, + { + Vector3:: { + v: [self.v[0].as_(), self.v[1].as_(), self.v[2].as_()], + } + } +} + +impl Mul for Vector4 +where + T: Mul + Copy, +{ + type Output = Vector4; + + #[inline(always)] + fn mul(self, rhs: T) -> Self::Output { + Self { + v: [ + self.v[0] * rhs, + self.v[1] * rhs, + self.v[2] * rhs, + self.v[3] * rhs, + ], + } + } +} + +impl + Add + MulAdd> + FusedMultiplyAdd> for Vector3 +{ + #[inline(always)] + fn mla(&self, b: Vector3, c: Vector3) -> Vector3 { + let x0 = mlaf(self.v[0], b.v[0], c.v[0]); + let x1 = mlaf(self.v[1], b.v[1], c.v[1]); + let x2 = mlaf(self.v[2], b.v[2], c.v[2]); + Vector3 { v: [x0, x1, x2] } + } +} + +impl + Add + MulAdd + Neg> + FusedMultiplyNegAdd> for Vector3 +{ + #[inline(always)] + fn neg_mla(&self, b: Vector3, c: Vector3) -> Vector3 { + let x0 = neg_mlaf(self.v[0], b.v[0], c.v[0]); + let x1 = neg_mlaf(self.v[1], b.v[1], c.v[1]); + let x2 = neg_mlaf(self.v[2], b.v[2], c.v[2]); + Vector3 { v: [x0, x1, x2] } + } +} + +impl + Add + MulAdd> + FusedMultiplyAdd> for Vector4 +{ + #[inline(always)] + fn mla(&self, b: Vector4, c: Vector4) -> Vector4 { + let x0 = mlaf(self.v[0], b.v[0], c.v[0]); + let x1 = mlaf(self.v[1], b.v[1], c.v[1]); + let x2 = mlaf(self.v[2], b.v[2], c.v[2]); + let x3 = mlaf(self.v[3], b.v[3], c.v[3]); + Vector4 { + v: [x0, x1, x2, x3], + } + } +} + +impl + Add + MulAdd + Neg> + FusedMultiplyNegAdd> for Vector4 +{ + #[inline(always)] + fn neg_mla(&self, b: Vector4, c: Vector4) -> Vector4 { + let x0 = neg_mlaf(self.v[0], b.v[0], c.v[0]); + let x1 = neg_mlaf(self.v[1], b.v[1], c.v[1]); + let x2 = neg_mlaf(self.v[2], b.v[2], c.v[2]); + let x3 = neg_mlaf(self.v[3], b.v[3], c.v[3]); + Vector4 { + v: [x0, x1, x2, x3], + } + } +} + +impl From for Vector3 +where + T: Copy, +{ + fn from(value: T) -> Self { + Self { + v: [value, value, value], + } + } +} + +impl From for Vector4 +where + T: Copy, +{ + fn from(value: T) -> Self { + Self { + v: [value, value, value, value], + } + } +} + +impl Add> for Vector3 +where + T: Add + Copy, +{ + type Output = Vector3; + + #[inline(always)] + fn add(self, rhs: Vector3) -> Self::Output { + Self { + v: [ + self.v[0] + rhs.v[0], + self.v[1] + rhs.v[1], + self.v[2] + rhs.v[2], + ], + } + } +} + +impl Add> for Vector4 +where + T: Add + Copy, +{ + type Output = Vector4; + + #[inline(always)] + fn add(self, rhs: Vector4) -> Self::Output { + Self { + v: [ + self.v[0] + rhs.v[0], + self.v[1] + rhs.v[1], + self.v[2] + rhs.v[2], + self.v[3] + rhs.v[3], + ], + } + } +} + +impl Add for Vector3 +where + T: Add + Copy, +{ + type Output = Vector3; + + #[inline(always)] + fn add(self, rhs: T) -> Self::Output { + Self { + v: [self.v[0] + rhs, self.v[1] + rhs, self.v[2] + rhs], + } + } +} + +impl Add for Vector4 +where + T: Add + Copy, +{ + type Output = Vector4; + + #[inline(always)] + fn add(self, rhs: T) -> Self::Output { + Self { + v: [ + self.v[0] + rhs, + self.v[1] + rhs, + self.v[2] + rhs, + self.v[3] + rhs, + ], + } + } +} + +impl Sub> for Vector3 +where + T: Sub + Copy, +{ + type Output = Vector3; + + #[inline(always)] + fn sub(self, rhs: Vector3) -> Self::Output { + Self { + v: [ + self.v[0] - rhs.v[0], + self.v[1] - rhs.v[1], + self.v[2] - rhs.v[2], + ], + } + } +} + +impl Sub> for Vector4 +where + T: Sub + Copy, +{ + type Output = Vector4; + + #[inline(always)] + fn sub(self, rhs: Vector4) -> Self::Output { + Self { + v: [ + self.v[0] - rhs.v[0], + self.v[1] - rhs.v[1], + self.v[2] - rhs.v[2], + self.v[3] - rhs.v[3], + ], + } + } +} + +/// Matrix math helper +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct Matrix3f { + pub v: [[f32; 3]; 3], +} + +/// Matrix math helper +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct Matrix3d { + pub v: [[f64; 3]; 3], +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct Matrix3 { + pub v: [[T; 3]; 3], +} + +impl Matrix3 { + #[inline] + #[allow(dead_code)] + pub(crate) fn transpose(&self) -> Matrix3 { + Matrix3 { + v: [ + [self.v[0][0], self.v[1][0], self.v[2][0]], + [self.v[0][1], self.v[1][1], self.v[2][1]], + [self.v[0][2], self.v[1][2], self.v[2][2]], + ], + } + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default)] +pub struct Matrix4f { + pub v: [[f32; 4]; 4], +} + +pub const SRGB_MATRIX: Matrix3d = Matrix3d { + v: [ + [ + s15_fixed16_number_to_double(0x6FA2), + s15_fixed16_number_to_double(0x6299), + s15_fixed16_number_to_double(0x24A0), + ], + [ + s15_fixed16_number_to_double(0x38F5), + s15_fixed16_number_to_double(0xB785), + s15_fixed16_number_to_double(0x0F84), + ], + [ + s15_fixed16_number_to_double(0x0390), + s15_fixed16_number_to_double(0x18DA), + s15_fixed16_number_to_double(0xB6CF), + ], + ], +}; + +pub const DISPLAY_P3_MATRIX: Matrix3d = Matrix3d { + v: [ + [0.515102, 0.291965, 0.157153], + [0.241182, 0.692236, 0.0665819], + [-0.00104941, 0.0418818, 0.784378], + ], +}; + +pub const BT2020_MATRIX: Matrix3d = Matrix3d { + v: [ + [0.673459, 0.165661, 0.125100], + [0.279033, 0.675338, 0.0456288], + [-0.00193139, 0.0299794, 0.797162], + ], +}; + +impl Matrix4f { + #[inline] + pub fn determinant(&self) -> Option { + let a = self.v[0][0]; + let b = self.v[0][1]; + let c = self.v[0][2]; + let d = self.v[0][3]; + + // Cofactor expansion + + let m11 = Matrix3f { + v: [ + [self.v[1][1], self.v[1][2], self.v[1][3]], + [self.v[2][1], self.v[2][2], self.v[2][3]], + [self.v[3][1], self.v[3][2], self.v[3][3]], + ], + }; + + let m12 = Matrix3f { + v: [ + [self.v[1][0], self.v[1][2], self.v[1][3]], + [self.v[2][0], self.v[2][2], self.v[2][3]], + [self.v[3][0], self.v[3][2], self.v[3][3]], + ], + }; + + let m13 = Matrix3f { + v: [ + [self.v[1][0], self.v[1][1], self.v[1][3]], + [self.v[2][0], self.v[2][1], self.v[2][3]], + [self.v[3][0], self.v[3][1], self.v[3][3]], + ], + }; + + let m14 = Matrix3f { + v: [ + [self.v[1][0], self.v[1][1], self.v[1][2]], + [self.v[2][0], self.v[2][1], self.v[2][2]], + [self.v[3][0], self.v[3][1], self.v[3][2]], + ], + }; + + let m1_det = m11.determinant()?; + let m2_det = m12.determinant()?; + let m3_det = m13.determinant()?; + let m4_det = m14.determinant()?; + + // Apply cofactor expansion on the first row + Some(a * m1_det - b * m2_det + c * m3_det - d * m4_det) + } +} + +impl Matrix3f { + #[inline] + pub fn transpose(&self) -> Matrix3f { + Matrix3f { + v: [ + [self.v[0][0], self.v[1][0], self.v[2][0]], + [self.v[0][1], self.v[1][1], self.v[2][1]], + [self.v[0][2], self.v[1][2], self.v[2][2]], + ], + } + } + + pub const IDENTITY: Matrix3f = Matrix3f { + v: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], + }; + + #[inline] + pub const fn test_equality(&self, other: Matrix3f) -> bool { + const TOLERANCE: f32 = 0.001f32; + let diff_r_x = (self.v[0][0] - other.v[0][0]).abs(); + let diff_r_y = (self.v[0][1] - other.v[0][1]).abs(); + let diff_r_z = (self.v[0][2] - other.v[0][2]).abs(); + + if diff_r_x > TOLERANCE || diff_r_y > TOLERANCE || diff_r_z > TOLERANCE { + return false; + } + + let diff_g_x = (self.v[1][0] - other.v[1][0]).abs(); + let diff_g_y = (self.v[1][1] - other.v[1][1]).abs(); + let diff_g_z = (self.v[1][2] - other.v[1][2]).abs(); + + if diff_g_x > TOLERANCE || diff_g_y > TOLERANCE || diff_g_z > TOLERANCE { + return false; + } + + let diff_b_x = (self.v[2][0] - other.v[2][0]).abs(); + let diff_b_y = (self.v[2][1] - other.v[2][1]).abs(); + let diff_b_z = (self.v[2][2] - other.v[2][2]).abs(); + + if diff_b_x > TOLERANCE || diff_b_y > TOLERANCE || diff_b_z > TOLERANCE { + return false; + } + + true + } + + #[inline] + pub const fn determinant(&self) -> Option { + let v = self.v; + let a0 = v[0][0] * v[1][1] * v[2][2]; + let a1 = v[0][1] * v[1][2] * v[2][0]; + let a2 = v[0][2] * v[1][0] * v[2][1]; + + let s0 = v[0][2] * v[1][1] * v[2][0]; + let s1 = v[0][1] * v[1][0] * v[2][2]; + let s2 = v[0][0] * v[1][2] * v[2][1]; + + let j = a0 + a1 + a2 - s0 - s1 - s2; + if j == 0. { + return None; + } + Some(j) + } + + #[inline] + pub const fn inverse(&self) -> Self { + let v = self.v; + let det = self.determinant(); + match det { + None => Matrix3f::IDENTITY, + Some(determinant) => { + let det = 1. / determinant; + let a = v[0][0]; + let b = v[0][1]; + let c = v[0][2]; + let d = v[1][0]; + let e = v[1][1]; + let f = v[1][2]; + let g = v[2][0]; + let h = v[2][1]; + let i = v[2][2]; + + Matrix3f { + v: [ + [ + (e * i - f * h) * det, + (c * h - b * i) * det, + (b * f - c * e) * det, + ], + [ + (f * g - d * i) * det, + (a * i - c * g) * det, + (c * d - a * f) * det, + ], + [ + (d * h - e * g) * det, + (b * g - a * h) * det, + (a * e - b * d) * det, + ], + ], + } + } + } + } + + #[inline] + pub fn mul_row(&self, rhs: f32) -> Self { + if R == 0 { + Self { + v: [(Vector3f { v: self.v[0] } * rhs).v, self.v[1], self.v[2]], + } + } else if R == 1 { + Self { + v: [self.v[0], (Vector3f { v: self.v[1] } * rhs).v, self.v[2]], + } + } else if R == 2 { + Self { + v: [self.v[0], self.v[1], (Vector3f { v: self.v[2] } * rhs).v], + } + } else { + unimplemented!() + } + } + + #[inline] + pub const fn mul_row_vector(&self, rhs: Vector3f) -> Self { + if R == 0 { + Self { + v: [ + (Vector3f { v: self.v[0] }.const_mul_vector(rhs)).v, + self.v[1], + self.v[2], + ], + } + } else if R == 1 { + Self { + v: [ + self.v[0], + (Vector3f { v: self.v[1] }.const_mul_vector(rhs)).v, + self.v[2], + ], + } + } else if R == 2 { + Self { + v: [ + self.v[0], + self.v[1], + (Vector3f { v: self.v[2] }.const_mul_vector(rhs)).v, + ], + } + } else { + unimplemented!() + } + } + + #[inline] + pub const fn mul_vector(&self, other: Vector3f) -> Vector3f { + let x = self.v[0][1] * other.v[1] + self.v[0][2] * other.v[2] + self.v[0][0] * other.v[0]; + let y = self.v[1][0] * other.v[0] + self.v[1][1] * other.v[1] + self.v[1][2] * other.v[2]; + let z = self.v[2][0] * other.v[0] + self.v[2][1] * other.v[1] + self.v[2][2] * other.v[2]; + Vector3f { v: [x, y, z] } + } + + /// Multiply using FMA + #[inline] + pub fn f_mul_vector(&self, other: Vector3f) -> Vector3f { + let x = mlaf( + mlaf(self.v[0][1] * other.v[1], self.v[0][2], other.v[2]), + self.v[0][0], + other.v[0], + ); + let y = mlaf( + mlaf(self.v[1][0] * other.v[0], self.v[1][1], other.v[1]), + self.v[1][2], + other.v[2], + ); + let z = mlaf( + mlaf(self.v[2][0] * other.v[0], self.v[2][1], other.v[1]), + self.v[2][2], + other.v[2], + ); + Vector3f { v: [x, y, z] } + } + + #[inline] + pub fn mat_mul(&self, other: Matrix3f) -> Self { + let mut result = Matrix3f::default(); + + for i in 0..3 { + for j in 0..3 { + result.v[i][j] = mlaf( + mlaf(self.v[i][0] * other.v[0][j], self.v[i][1], other.v[1][j]), + self.v[i][2], + other.v[2][j], + ); + } + } + + result + } + + #[inline] + pub const fn mat_mul_const(&self, other: Matrix3f) -> Self { + let mut result = Matrix3f { v: [[0f32; 3]; 3] }; + let mut i = 0usize; + while i < 3 { + let mut j = 0usize; + while j < 3 { + result.v[i][j] = self.v[i][0] * other.v[0][j] + + self.v[i][1] * other.v[1][j] + + self.v[i][2] * other.v[2][j]; + j += 1; + } + i += 1; + } + + result + } + + #[inline] + pub const fn to_f64(&self) -> Matrix3d { + Matrix3d { + v: [ + [ + self.v[0][0] as f64, + self.v[0][1] as f64, + self.v[0][2] as f64, + ], + [ + self.v[1][0] as f64, + self.v[1][1] as f64, + self.v[1][2] as f64, + ], + [ + self.v[2][0] as f64, + self.v[2][1] as f64, + self.v[2][2] as f64, + ], + ], + } + } +} + +impl Matrix3d { + #[inline] + pub fn transpose(&self) -> Matrix3d { + Matrix3d { + v: [ + [self.v[0][0], self.v[1][0], self.v[2][0]], + [self.v[0][1], self.v[1][1], self.v[2][1]], + [self.v[0][2], self.v[1][2], self.v[2][2]], + ], + } + } + + pub const IDENTITY: Matrix3d = Matrix3d { + v: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], + }; + + #[inline] + pub const fn test_equality(&self, other: Matrix3d) -> bool { + const TOLERANCE: f64 = 0.001f64; + let diff_r_x = (self.v[0][0] - other.v[0][0]).abs(); + let diff_r_y = (self.v[0][1] - other.v[0][1]).abs(); + let diff_r_z = (self.v[0][2] - other.v[0][2]).abs(); + + if diff_r_x > TOLERANCE || diff_r_y > TOLERANCE || diff_r_z > TOLERANCE { + return false; + } + + let diff_g_x = (self.v[1][0] - other.v[1][0]).abs(); + let diff_g_y = (self.v[1][1] - other.v[1][1]).abs(); + let diff_g_z = (self.v[1][2] - other.v[1][2]).abs(); + + if diff_g_x > TOLERANCE || diff_g_y > TOLERANCE || diff_g_z > TOLERANCE { + return false; + } + + let diff_b_x = (self.v[2][0] - other.v[2][0]).abs(); + let diff_b_y = (self.v[2][1] - other.v[2][1]).abs(); + let diff_b_z = (self.v[2][2] - other.v[2][2]).abs(); + + if diff_b_x > TOLERANCE || diff_b_y > TOLERANCE || diff_b_z > TOLERANCE { + return false; + } + + true + } + + #[inline] + pub const fn determinant(&self) -> Option { + let v = self.v; + let a0 = v[0][0] * v[1][1] * v[2][2]; + let a1 = v[0][1] * v[1][2] * v[2][0]; + let a2 = v[0][2] * v[1][0] * v[2][1]; + + let s0 = v[0][2] * v[1][1] * v[2][0]; + let s1 = v[0][1] * v[1][0] * v[2][2]; + let s2 = v[0][0] * v[1][2] * v[2][1]; + + let j = a0 + a1 + a2 - s0 - s1 - s2; + if j == 0. { + return None; + } + Some(j) + } + + #[inline] + pub const fn inverse(&self) -> Self { + let v = self.v; + let det = self.determinant(); + match det { + None => Matrix3d::IDENTITY, + Some(determinant) => { + let det = 1. / determinant; + let a = v[0][0]; + let b = v[0][1]; + let c = v[0][2]; + let d = v[1][0]; + let e = v[1][1]; + let f = v[1][2]; + let g = v[2][0]; + let h = v[2][1]; + let i = v[2][2]; + + Matrix3d { + v: [ + [ + (e * i - f * h) * det, + (c * h - b * i) * det, + (b * f - c * e) * det, + ], + [ + (f * g - d * i) * det, + (a * i - c * g) * det, + (c * d - a * f) * det, + ], + [ + (d * h - e * g) * det, + (b * g - a * h) * det, + (a * e - b * d) * det, + ], + ], + } + } + } + } + + #[inline] + pub fn mul_row(&self, rhs: f64) -> Self { + if R == 0 { + Self { + v: [(Vector3d { v: self.v[0] } * rhs).v, self.v[1], self.v[2]], + } + } else if R == 1 { + Self { + v: [self.v[0], (Vector3d { v: self.v[1] } * rhs).v, self.v[2]], + } + } else if R == 2 { + Self { + v: [self.v[0], self.v[1], (Vector3d { v: self.v[2] } * rhs).v], + } + } else { + unimplemented!() + } + } + + #[inline] + pub const fn mul_row_vector(&self, rhs: Vector3d) -> Self { + if R == 0 { + Self { + v: [ + (Vector3d { v: self.v[0] }.const_mul_vector(rhs)).v, + self.v[1], + self.v[2], + ], + } + } else if R == 1 { + Self { + v: [ + self.v[0], + (Vector3d { v: self.v[1] }.const_mul_vector(rhs)).v, + self.v[2], + ], + } + } else if R == 2 { + Self { + v: [ + self.v[0], + self.v[1], + (Vector3d { v: self.v[2] }.const_mul_vector(rhs)).v, + ], + } + } else { + unimplemented!() + } + } + + #[inline] + pub const fn mul_vector(&self, other: Vector3d) -> Vector3d { + let x = self.v[0][1] * other.v[1] + self.v[0][2] * other.v[2] + self.v[0][0] * other.v[0]; + let y = self.v[1][0] * other.v[0] + self.v[1][1] * other.v[1] + self.v[1][2] * other.v[2]; + let z = self.v[2][0] * other.v[0] + self.v[2][1] * other.v[1] + self.v[2][2] * other.v[2]; + Vector3:: { v: [x, y, z] } + } + + #[inline] + pub fn mat_mul(&self, other: Matrix3d) -> Self { + let mut result = Matrix3d::default(); + + for i in 0..3 { + for j in 0..3 { + result.v[i][j] = mlaf( + mlaf(self.v[i][0] * other.v[0][j], self.v[i][1], other.v[1][j]), + self.v[i][2], + other.v[2][j], + ); + } + } + + result + } + + #[inline] + pub const fn mat_mul_const(&self, other: Matrix3d) -> Self { + let mut result = Matrix3d { v: [[0.; 3]; 3] }; + let mut i = 0usize; + while i < 3 { + let mut j = 0usize; + while j < 3 { + result.v[i][j] = self.v[i][0] * other.v[0][j] + + self.v[i][1] * other.v[1][j] + + self.v[i][2] * other.v[2][j]; + j += 1; + } + i += 1; + } + + result + } + + #[inline] + pub const fn to_f32(&self) -> Matrix3f { + Matrix3f { + v: [ + [ + self.v[0][0] as f32, + self.v[0][1] as f32, + self.v[0][2] as f32, + ], + [ + self.v[1][0] as f32, + self.v[1][1] as f32, + self.v[1][2] as f32, + ], + [ + self.v[2][0] as f32, + self.v[2][1] as f32, + self.v[2][2] as f32, + ], + ], + } + } +} + +impl Mul for Matrix3f { + type Output = Matrix3f; + + #[inline] + fn mul(self, rhs: Matrix3f) -> Self::Output { + self.mat_mul(rhs) + } +} + +impl Mul for Matrix3d { + type Output = Matrix3d; + + #[inline] + fn mul(self, rhs: Matrix3d) -> Self::Output { + self.mat_mul(rhs) + } +} + +/// Holds CIE XYZ representation +#[repr(C)] +#[derive(Clone, Debug, Copy, Default)] +pub struct Xyz { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Xyz { + #[inline] + pub fn to_xyy(&self) -> [f32; 3] { + let sums = self.x + self.y + self.z; + if sums == 0. { + return [0., 0., self.y]; + } + let x = self.x / sums; + let y = self.y / sums; + let yb = self.y; + [x, y, yb] + } + + #[inline] + pub fn from_xyy(xyy: [f32; 3]) -> Xyz { + let reciprocal = if xyy[1] != 0. { + 1. / xyy[1] * xyy[2] + } else { + 0. + }; + let x = xyy[0] * reciprocal; + let y = xyy[2]; + let z = (1. - xyy[0] - xyy[1]) * reciprocal; + Xyz { x, y, z } + } +} + +/// Holds CIE XYZ representation, in double precision +#[repr(C)] +#[derive(Clone, Debug, Copy, Default)] +pub struct Xyzd { + pub x: f64, + pub y: f64, + pub z: f64, +} + +macro_rules! define_xyz { + ($xyz_name:ident, $im_type: ident, $matrix: ident) => { + impl PartialEq for $xyz_name { + #[inline] + fn eq(&self, other: &Self) -> bool { + const TOLERANCE: $im_type = 0.0001; + let dx = (self.x - other.x).abs(); + let dy = (self.y - other.y).abs(); + let dz = (self.z - other.z).abs(); + dx < TOLERANCE && dy < TOLERANCE && dz < TOLERANCE + } + } + + impl $xyz_name { + #[inline] + pub const fn new(x: $im_type, y: $im_type, z: $im_type) -> Self { + Self { x, y, z } + } + + #[inline] + pub const fn to_vector(self) -> Vector3f { + Vector3f { + v: [self.x as f32, self.y as f32, self.z as f32], + } + } + + #[inline] + pub const fn to_vector_d(self) -> Vector3d { + Vector3d { + v: [self.x as f64, self.y as f64, self.z as f64], + } + } + + #[inline] + pub fn matrix_mul(&self, matrix: $matrix) -> Self { + let x = mlaf( + mlaf(self.x * matrix.v[0][0], self.y, matrix.v[0][1]), + self.z, + matrix.v[0][2], + ); + let y = mlaf( + mlaf(self.x * matrix.v[1][0], self.y, matrix.v[1][1]), + self.z, + matrix.v[1][2], + ); + let z = mlaf( + mlaf(self.x * matrix.v[2][0], self.y, matrix.v[2][1]), + self.z, + matrix.v[2][2], + ); + Self::new(x, y, z) + } + + #[inline] + pub fn from_linear_rgb(rgb: crate::Rgb<$im_type>, rgb_to_xyz: $matrix) -> Self { + let r = rgb.r; + let g = rgb.g; + let b = rgb.b; + + let transform = rgb_to_xyz; + + let new_r = mlaf( + mlaf(r * transform.v[0][0], g, transform.v[0][1]), + b, + transform.v[0][2], + ); + + let new_g = mlaf( + mlaf(r * transform.v[1][0], g, transform.v[1][1]), + b, + transform.v[1][2], + ); + + let new_b = mlaf( + mlaf(r * transform.v[2][0], g, transform.v[2][1]), + b, + transform.v[2][2], + ); + + $xyz_name::new(new_r, new_g, new_b) + } + + #[inline] + pub fn normalize(self) -> Self { + if self.y == 0. { + return Self { + x: 0., + y: 1.0, + z: 0.0, + }; + } + let reciprocal = 1. / self.y; + Self { + x: self.x * reciprocal, + y: 1.0, + z: self.z * reciprocal, + } + } + + #[inline] + pub fn to_linear_rgb(self, rgb_to_xyz: $matrix) -> crate::Rgb<$im_type> { + let x = self.x; + let y = self.y; + let z = self.z; + + let transform = rgb_to_xyz; + + let new_r = mlaf( + mlaf(x * transform.v[0][0], y, transform.v[0][1]), + z, + transform.v[0][2], + ); + + let new_g = mlaf( + mlaf(x * transform.v[1][0], y, transform.v[1][1]), + z, + transform.v[1][2], + ); + + let new_b = mlaf( + mlaf(x * transform.v[2][0], y, transform.v[2][1]), + z, + transform.v[2][2], + ); + + crate::Rgb::<$im_type>::new(new_r, new_g, new_b) + } + } + + impl Mul<$im_type> for $xyz_name { + type Output = $xyz_name; + + #[inline] + fn mul(self, rhs: $im_type) -> Self::Output { + Self { + x: self.x * rhs, + y: self.y * rhs, + z: self.z * rhs, + } + } + } + + impl Mul<$matrix> for $xyz_name { + type Output = $xyz_name; + + #[inline] + fn mul(self, rhs: $matrix) -> Self::Output { + self.matrix_mul(rhs) + } + } + + impl Mul<$xyz_name> for $xyz_name { + type Output = $xyz_name; + + #[inline] + fn mul(self, rhs: $xyz_name) -> Self::Output { + Self { + x: self.x * rhs.x, + y: self.y * rhs.y, + z: self.z * rhs.z, + } + } + } + + impl Div<$xyz_name> for $xyz_name { + type Output = $xyz_name; + + #[inline] + fn div(self, rhs: $xyz_name) -> Self::Output { + Self { + x: self.x / rhs.x, + y: self.y / rhs.y, + z: self.z / rhs.z, + } + } + } + + impl Div<$im_type> for $xyz_name { + type Output = $xyz_name; + + #[inline] + fn div(self, rhs: $im_type) -> Self::Output { + Self { + x: self.x / rhs, + y: self.y / rhs, + z: self.z / rhs, + } + } + } + }; +} + +impl Xyz { + pub fn to_xyzd(self) -> Xyzd { + Xyzd { + x: self.x as f64, + y: self.y as f64, + z: self.z as f64, + } + } +} + +impl Xyzd { + pub fn to_xyz(self) -> Xyz { + Xyz { + x: self.x as f32, + y: self.y as f32, + z: self.z as f32, + } + } + + pub fn to_xyzd(self) -> Xyzd { + Xyzd { + x: self.x, + y: self.y, + z: self.z, + } + } +} + +define_xyz!(Xyz, f32, Matrix3f); +define_xyz!(Xyzd, f64, Matrix3d); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/mlaf.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/mlaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/mlaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/mlaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use num_traits::MulAdd; +use std::ops::{Add, Mul, Neg}; + +#[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + all(target_arch = "aarch64", target_feature = "neon") +))] +#[inline(always)] +pub(crate) fn mlaf + Add + MulAdd>( + acc: T, + a: T, + b: T, +) -> T { + MulAdd::mul_add(a, b, acc) +} + +#[inline(always)] +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + all(target_arch = "aarch64", target_feature = "neon") +)))] +pub(crate) fn mlaf + Add + MulAdd>( + acc: T, + a: T, + b: T, +) -> T { + acc + a * b +} + +#[inline(always)] +pub(crate) fn neg_mlaf< + T: Copy + Mul + Add + MulAdd + Neg, +>( + acc: T, + a: T, + b: T, +) -> T { + mlaf(acc, a, -b) +} + +#[inline(always)] +pub(crate) fn fmla + Add + MulAdd>( + a: T, + b: T, + acc: T, +) -> T { + mlaf(acc, a, b) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/nd_array.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/nd_array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/nd_array.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/nd_array.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1404 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd}; +use crate::mlaf::{mlaf, neg_mlaf}; +use crate::safe_math::{SafeAdd, SafeMul}; +use crate::{CmsError, MalformedSize, Vector3f, Vector4f}; +use std::ops::{Add, Mul, Sub}; + +impl FusedMultiplyAdd for f32 { + #[inline(always)] + fn mla(&self, b: f32, c: f32) -> f32 { + mlaf(*self, b, c) + } +} + +impl FusedMultiplyNegAdd for f32 { + #[inline(always)] + fn neg_mla(&self, b: f32, c: f32) -> f32 { + neg_mlaf(*self, b, c) + } +} + +#[inline(always)] +pub(crate) fn lerp< + T: Mul + + Sub + + Add + + From + + Copy + + FusedMultiplyAdd + + FusedMultiplyNegAdd, +>( + a: T, + b: T, + t: T, +) -> T { + a.neg_mla(a, t).mla(b, t) +} + +/// 4D CLUT helper. +/// +/// Represents hypercube. +pub struct Hypercube<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, + z_stride: u32, + grid_size: [u8; 4], +} + +trait Fetcher4 { + fn fetch(&self, x: i32, y: i32, z: i32, w: i32) -> T; +} + +impl Hypercube<'_> { + pub fn new(array: &[f32], grid_size: usize) -> Hypercube<'_> { + let z_stride = grid_size as u32; + let y_stride = z_stride * z_stride; + let x_stride = z_stride * z_stride * z_stride; + Hypercube { + array, + x_stride, + y_stride, + z_stride, + grid_size: [ + grid_size as u8, + grid_size as u8, + grid_size as u8, + grid_size as u8, + ], + } + } + + pub(crate) fn new_checked( + array: &[f32], + grid_size: usize, + channels: usize, + ) -> Result, CmsError> { + if array.is_empty() || grid_size == 0 { + return Ok(Hypercube { + array, + x_stride: 0, + y_stride: 0, + z_stride: 0, + grid_size: [0, 0, 0, 0], + }); + } + let z_stride = grid_size as u32; + let y_stride = z_stride * z_stride; + let x_stride = z_stride * z_stride * z_stride; + + let last_index = (grid_size - 1) + .safe_mul(x_stride as usize)? + .safe_add((grid_size - 1).safe_mul(y_stride as usize)?)? + .safe_add((grid_size - 1).safe_mul(z_stride as usize)?)? + .safe_add(grid_size - 1)? + .safe_mul(channels)?; + + if last_index >= array.len() { + return Err(CmsError::MalformedClut(MalformedSize { + size: array.len(), + expected: last_index, + })); + } + + Ok(Hypercube { + array, + x_stride, + y_stride, + z_stride, + grid_size: [ + grid_size as u8, + grid_size as u8, + grid_size as u8, + grid_size as u8, + ], + }) + } + + pub(crate) fn new_checked_hypercube( + array: &[f32], + grid_size: [u8; 4], + channels: usize, + ) -> Result, CmsError> { + if array.is_empty() + || grid_size[0] == 0 + || grid_size[1] == 0 + || grid_size[2] == 0 + || grid_size[3] == 0 + { + return Ok(Hypercube { + array, + x_stride: 0, + y_stride: 0, + z_stride: 0, + grid_size, + }); + } + let z_stride = grid_size[2] as u32; + let y_stride = z_stride * grid_size[1] as u32; + let x_stride = y_stride * grid_size[0] as u32; + let last_index = (grid_size[0] as usize - 1) + .safe_mul(x_stride as usize)? + .safe_add((grid_size[1] as usize - 1).safe_mul(y_stride as usize)?)? + .safe_add((grid_size[2] as usize - 1).safe_mul(z_stride as usize)?)? + .safe_add(grid_size[3] as usize - 1)? + .safe_mul(channels)?; + + if last_index >= array.len() { + return Err(CmsError::MalformedClut(MalformedSize { + size: array.len(), + expected: last_index, + })); + } + + Ok(Hypercube { + array, + x_stride, + y_stride, + z_stride, + grid_size, + }) + } + + pub fn new_hypercube(array: &[f32], grid_size: [u8; 4]) -> Hypercube<'_> { + let z_stride = grid_size[2] as u32; + let y_stride = z_stride * grid_size[1] as u32; + let x_stride = y_stride * grid_size[0] as u32; + Hypercube { + array, + x_stride, + y_stride, + z_stride, + grid_size, + } + } +} + +struct Fetch4Vec3<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, + z_stride: u32, +} + +struct Fetch4Vec4<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, + z_stride: u32, +} + +impl Fetcher4 for Fetch4Vec3<'_> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32, w: i32) -> Vector3f { + let start = (x as u32 * self.x_stride + + y as u32 * self.y_stride + + z as u32 * self.z_stride + + w as u32) as usize + * 3; + let k = &self.array[start..start + 3]; + Vector3f { + v: [k[0], k[1], k[2]], + } + } +} + +impl Fetcher4 for Fetch4Vec4<'_> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32, w: i32) -> Vector4f { + let start = (x as u32 * self.x_stride + + y as u32 * self.y_stride + + z as u32 * self.z_stride + + w as u32) as usize + * 4; + let k = &self.array[start..start + 4]; + Vector4f { + v: [k[0], k[1], k[2], k[3]], + } + } +} + +impl Hypercube<'_> { + #[inline(always)] + fn quadlinear< + T: From + + Add + + Mul + + FusedMultiplyAdd + + Sub + + Copy + + FusedMultiplyNegAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + lin_w: f32, + r: impl Fetcher4, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + let lin_w = lin_w.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + let scale_w = (self.grid_size[3] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + let w = (lin_w * scale_w).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + let w_n = (lin_w * scale_w).ceil() as i32; + + let x_d = T::from(lin_x * scale_x - x as f32); + let y_d = T::from(lin_y * scale_y - y as f32); + let z_d = T::from(lin_z * scale_z - z as f32); + let w_d = T::from(lin_w * scale_w - w as f32); + + let r_x1 = lerp(r.fetch(x, y, z, w), r.fetch(x_n, y, z, w), x_d); + let r_x2 = lerp(r.fetch(x, y_n, z, w), r.fetch(x_n, y_n, z, w), x_d); + let r_y1 = lerp(r_x1, r_x2, y_d); + let r_x3 = lerp(r.fetch(x, y, z_n, w), r.fetch(x_n, y, z_n, w), x_d); + let r_x4 = lerp(r.fetch(x, y_n, z_n, w), r.fetch(x_n, y_n, z_n, w), x_d); + let r_y2 = lerp(r_x3, r_x4, y_d); + let r_z1 = lerp(r_y1, r_y2, z_d); + + let r_x1 = lerp(r.fetch(x, y, z, w_n), r.fetch(x_n, y, z, w_n), x_d); + let r_x2 = lerp(r.fetch(x, y_n, z, w_n), r.fetch(x_n, y_n, z, w_n), x_d); + let r_y1 = lerp(r_x1, r_x2, y_d); + let r_x3 = lerp(r.fetch(x, y, z_n, w_n), r.fetch(x_n, y, z_n, w_n), x_d); + let r_x4 = lerp(r.fetch(x, y_n, z_n, w_n), r.fetch(x_n, y_n, z_n, w_n), x_d); + let r_y2 = lerp(r_x3, r_x4, y_d); + let r_z2 = lerp(r_y1, r_y2, z_d); + lerp(r_z1, r_z2, w_d) + } + + #[inline] + pub fn quadlinear_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector3f { + self.quadlinear( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec3 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[inline] + pub fn quadlinear_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector4f { + self.quadlinear( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec4 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline(always)] + fn pyramid< + T: From + + Add + + Mul + + FusedMultiplyAdd + + Sub + + Copy + + FusedMultiplyNegAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + lin_w: f32, + r: impl Fetcher4, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + let lin_w = lin_w.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + let scale_w = (self.grid_size[3] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + let w = (lin_w * scale_w).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + let w_n = (lin_w * scale_w).ceil() as i32; + + let dr = lin_x * scale_x - x as f32; + let dg = lin_y * scale_y - y as f32; + let db = lin_z * scale_z - z as f32; + let dw = lin_w * scale_w - w as f32; + + let c0 = r.fetch(x, y, z, w); + + let w0 = if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n, w); + let x1 = r.fetch(x_n, y_n, z, w); + let x2 = r.fetch(x_n, y, z, w); + let x3 = r.fetch(x, y_n, z, w); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n, w); + let x1 = r.fetch(x_n, y_n, z_n, w); + let x2 = r.fetch(x, y_n, z_n, w); + let x3 = r.fetch(x, y_n, z, w); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dg * db)) + } else { + let x0 = r.fetch(x, y, z_n, w); + let x1 = r.fetch(x_n, y, z, w); + let x2 = r.fetch(x_n, y, z_n, w); + let x3 = r.fetch(x_n, y_n, z_n, w); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(db * dr)) + }; + + let c0 = r.fetch(x, y, z, w_n); + + let w1 = if dr > db && dg > db { + let x0 = r.fetch(x_n, y_n, z_n, w_n); + let x1 = r.fetch(x_n, y_n, z, w_n); + let x2 = r.fetch(x_n, y, z, w_n); + let x3 = r.fetch(x, y_n, z, w_n); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = r.fetch(x, y, z_n, w_n); + let x1 = r.fetch(x_n, y_n, z_n, w_n); + let x2 = r.fetch(x, y_n, z_n, w_n); + let x3 = r.fetch(x, y_n, z, w_n); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dg * db)) + } else { + let x0 = r.fetch(x, y, z_n, w_n); + let x1 = r.fetch(x_n, y, z, w_n); + let x2 = r.fetch(x_n, y, z_n, w_n); + let x3 = r.fetch(x_n, y_n, z_n, w_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(db * dr)) + }; + w0.neg_mla(w0, T::from(dw)).mla(w1, T::from(dw)) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn pyramid_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector3f { + self.pyramid( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec3 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn pyramid_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector4f { + self.pyramid( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec4 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline(always)] + fn prism< + T: From + + Add + + Mul + + FusedMultiplyAdd + + Sub + + Copy + + FusedMultiplyNegAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + lin_w: f32, + r: impl Fetcher4, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + let lin_w = lin_w.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + let scale_w = (self.grid_size[3] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + let w = (lin_w * scale_w).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + let w_n = (lin_w * scale_w).ceil() as i32; + + let dr = lin_x * scale_x - x as f32; + let dg = lin_y * scale_y - y as f32; + let db = lin_z * scale_z - z as f32; + let dw = lin_w * scale_w - w as f32; + + let c0 = r.fetch(x, y, z, w); + + let w0 = if db >= dr { + let x0 = r.fetch(x, y, z_n, w); + let x1 = r.fetch(x_n, y, z_n, w); + let x2 = r.fetch(x, y_n, z, w); + let x3 = r.fetch(x, y_n, z_n, w); + let x4 = r.fetch(x_n, y_n, z_n, w); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } else { + let x0 = r.fetch(x_n, y, z, w); + let x1 = r.fetch(x_n, y, z_n, w); + let x2 = r.fetch(x, y_n, z, w); + let x3 = r.fetch(x_n, y_n, z, w); + let x4 = r.fetch(x_n, y_n, z_n, w); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + }; + + let c0 = r.fetch(x, y, z, w_n); + + let w1 = if db >= dr { + let x0 = r.fetch(x, y, z_n, w_n); + let x1 = r.fetch(x_n, y, z_n, w_n); + let x2 = r.fetch(x, y_n, z, w_n); + let x3 = r.fetch(x, y_n, z_n, w_n); + let x4 = r.fetch(x_n, y_n, z_n, w_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } else { + let x0 = r.fetch(x_n, y, z, w_n); + let x1 = r.fetch(x_n, y, z_n, w_n); + let x2 = r.fetch(x, y_n, z, w_n); + let x3 = r.fetch(x_n, y_n, z, w_n); + let x4 = r.fetch(x_n, y_n, z_n, w_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + }; + w0.neg_mla(w0, T::from(dw)).mla(w1, T::from(dw)) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn prism_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector3f { + self.prism( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec3 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn prism_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector4f { + self.prism( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec4 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline(always)] + fn tetra< + T: From + + Add + + Mul + + FusedMultiplyAdd + + Sub + + Copy + + FusedMultiplyNegAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + lin_w: f32, + r: impl Fetcher4, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + let lin_w = lin_w.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + let scale_w = (self.grid_size[3] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + let w = (lin_w * scale_w).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + let w_n = (lin_w * scale_w).ceil() as i32; + + let rx = lin_x * scale_x - x as f32; + let ry = lin_y * scale_y - y as f32; + let rz = lin_z * scale_z - z as f32; + let rw = lin_w * scale_w - w as f32; + + let c0 = r.fetch(x, y, z, w); + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z, w) - c0; + c2 = r.fetch(x_n, y_n, z, w) - r.fetch(x_n, y, z, w); + c3 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x_n, y_n, z, w); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z, w) - c0; + c2 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x_n, y, z_n, w); + c3 = r.fetch(x_n, y, z_n, w) - r.fetch(x_n, y, z, w); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n, w) - r.fetch(x, y, z_n, w); + c2 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x_n, y, z_n, w); + c3 = r.fetch(x, y, z_n, w) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z, w) - r.fetch(x, y_n, z, w); + c2 = r.fetch(x, y_n, z, w) - c0; + c3 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x_n, y_n, z, w); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x, y_n, z_n, w); + c2 = r.fetch(x, y_n, z, w) - c0; + c3 = r.fetch(x, y_n, z_n, w) - r.fetch(x, y_n, z, w); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n, w) - r.fetch(x, y_n, z_n, w); + c2 = r.fetch(x, y_n, z_n, w) - r.fetch(x, y, z_n, w); + c3 = r.fetch(x, y, z_n, w) - c0; + } + let s0 = c0.mla(c1, T::from(rx)); + let s1 = s0.mla(c2, T::from(ry)); + let w0 = s1.mla(c3, T::from(rz)); + + let c0 = r.fetch(x, y, z, w_n); + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = r.fetch(x_n, y, z, w_n) - c0; + c2 = r.fetch(x_n, y_n, z, w_n) - r.fetch(x_n, y, z, w_n); + c3 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x_n, y_n, z, w_n); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = r.fetch(x_n, y, z, w_n) - c0; + c2 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x_n, y, z_n, w_n); + c3 = r.fetch(x_n, y, z_n, w_n) - r.fetch(x_n, y, z, w_n); + } else { + //rz > rx && rx >= ry + c1 = r.fetch(x_n, y, z_n, w_n) - r.fetch(x, y, z_n, w_n); + c2 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x_n, y, z_n, w_n); + c3 = r.fetch(x, y, z_n, w_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = r.fetch(x_n, y_n, z, w_n) - r.fetch(x, y_n, z, w_n); + c2 = r.fetch(x, y_n, z, w_n) - c0; + c3 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x_n, y_n, z, w_n); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x, y_n, z_n, w_n); + c2 = r.fetch(x, y_n, z, w_n) - c0; + c3 = r.fetch(x, y_n, z_n, w_n) - r.fetch(x, y_n, z, w_n); + } else { + //rz > ry && ry > rx + c1 = r.fetch(x_n, y_n, z_n, w_n) - r.fetch(x, y_n, z_n, w_n); + c2 = r.fetch(x, y_n, z_n, w_n) - r.fetch(x, y, z_n, w_n); + c3 = r.fetch(x, y, z_n, w_n) - c0; + } + let s0 = c0.mla(c1, T::from(rx)); + let s1 = s0.mla(c2, T::from(ry)); + let w1 = s1.mla(c3, T::from(rz)); + w0.neg_mla(w0, T::from(rw)).mla(w1, T::from(rw)) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn tetra_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector3f { + self.tetra( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec3 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + #[inline] + pub fn tetra_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32, lin_w: f32) -> Vector4f { + self.tetra( + lin_x, + lin_y, + lin_z, + lin_w, + Fetch4Vec4 { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + z_stride: self.z_stride, + }, + ) + } +} + +/// 3D CLUT helper +/// +/// Represents hexahedron. +pub struct Cube<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, + grid_size: [u8; 3], +} + +pub(crate) trait ArrayFetch { + fn fetch(&self, x: i32, y: i32, z: i32) -> T; +} + +struct ArrayFetchVector3f<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, +} + +impl ArrayFetch for ArrayFetchVector3f<'_> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> Vector3f { + let start = (x as u32 * self.x_stride + y as u32 * self.y_stride + z as u32) as usize * 3; + let k = &self.array[start..start + 3]; + Vector3f { + v: [k[0], k[1], k[2]], + } + } +} + +struct ArrayFetchVector4f<'a> { + array: &'a [f32], + x_stride: u32, + y_stride: u32, +} + +impl ArrayFetch for ArrayFetchVector4f<'_> { + #[inline(always)] + fn fetch(&self, x: i32, y: i32, z: i32) -> Vector4f { + let start = (x as u32 * self.x_stride + y as u32 * self.y_stride + z as u32) as usize * 4; + let k = &self.array[start..start + 4]; + Vector4f { + v: [k[0], k[1], k[2], k[3]], + } + } +} + +impl Cube<'_> { + pub fn new(array: &[f32], grid_size: usize) -> Cube<'_> { + let y_stride = grid_size; + let x_stride = y_stride * y_stride; + Cube { + array, + x_stride: x_stride as u32, + y_stride: y_stride as u32, + grid_size: [grid_size as u8, grid_size as u8, grid_size as u8], + } + } + + pub(crate) fn new_checked( + array: &[f32], + grid_size: usize, + channels: usize, + ) -> Result, CmsError> { + if array.is_empty() || grid_size == 0 { + return Ok(Cube { + array, + x_stride: 0, + y_stride: 0, + grid_size: [0, 0, 0], + }); + } + let y_stride = grid_size; + let x_stride = y_stride * y_stride; + + let last_index = (grid_size - 1) + .safe_mul(x_stride)? + .safe_add((grid_size - 1).safe_mul(y_stride)?)? + .safe_add(grid_size - 1)? + .safe_mul(channels)?; + + if last_index >= array.len() { + return Err(CmsError::MalformedClut(MalformedSize { + size: array.len(), + expected: last_index, + })); + } + + Ok(Cube { + array, + x_stride: x_stride as u32, + y_stride: y_stride as u32, + grid_size: [grid_size as u8, grid_size as u8, grid_size as u8], + }) + } + + pub fn new_cube(array: &[f32], grid_size: [u8; 3]) -> Cube<'_> { + let y_stride = grid_size[2] as u32; + let x_stride = y_stride * grid_size[1] as u32; + Cube { + array, + x_stride, + y_stride, + grid_size, + } + } + + pub(crate) fn new_checked_cube( + array: &[f32], + grid_size: [u8; 3], + channels: usize, + ) -> Result, CmsError> { + if array.is_empty() || grid_size[0] == 0 || grid_size[1] == 0 || grid_size[2] == 0 { + return Ok(Cube { + array, + x_stride: 0, + y_stride: 0, + grid_size, + }); + } + let y_stride = grid_size[2] as u32; + let x_stride = y_stride * grid_size[1] as u32; + let last_index = (grid_size[0] as usize - 1) + .safe_mul(x_stride as usize)? + .safe_add((grid_size[1] as usize - 1).safe_mul(y_stride as usize)?)? + .safe_add(grid_size[2] as usize - 1)? + .safe_mul(channels)?; + + if last_index >= array.len() { + return Err(CmsError::MalformedClut(MalformedSize { + size: array.len(), + expected: last_index, + })); + } + + Ok(Cube { + array, + x_stride, + y_stride, + grid_size, + }) + } + + #[inline(always)] + fn trilinear< + T: Copy + + From + + Sub + + Mul + + Add + + FusedMultiplyNegAdd + + FusedMultiplyAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + fetch: impl ArrayFetch, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + + let x_d = T::from(lin_x * scale_x - x as f32); + let y_d = T::from(lin_y * scale_y - y as f32); + let z_d = T::from(lin_z * scale_z - z as f32); + + let c000 = fetch.fetch(x, y, z); + let c100 = fetch.fetch(x_n, y, z); + let c010 = fetch.fetch(x, y_n, z); + let c110 = fetch.fetch(x_n, y_n, z); + let c001 = fetch.fetch(x, y, z_n); + let c101 = fetch.fetch(x_n, y, z_n); + let c011 = fetch.fetch(x, y_n, z_n); + let c111 = fetch.fetch(x_n, y_n, z_n); + + let c00 = c000.neg_mla(c000, x_d).mla(c100, x_d); + let c10 = c010.neg_mla(c010, x_d).mla(c110, x_d); + let c01 = c001.neg_mla(c001, x_d).mla(c101, x_d); + let c11 = c011.neg_mla(c011, x_d).mla(c111, x_d); + + let c0 = c00.neg_mla(c00, y_d).mla(c10, y_d); + let c1 = c01.neg_mla(c01, y_d).mla(c11, y_d); + + c0.neg_mla(c0, z_d).mla(c1, z_d) + } + + #[cfg(feature = "options")] + #[inline] + fn pyramid< + T: Copy + + From + + Sub + + Mul + + Add + + FusedMultiplyAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + fetch: impl ArrayFetch, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + + let dr = lin_x * scale_x - x as f32; + let dg = lin_y * scale_y - y as f32; + let db = lin_z * scale_z - z as f32; + + let c0 = fetch.fetch(x, y, z); + + if dr > db && dg > db { + let x0 = fetch.fetch(x_n, y_n, z_n); + let x1 = fetch.fetch(x_n, y_n, z); + let x2 = fetch.fetch(x_n, y, z); + let x3 = fetch.fetch(x, y_n, z); + + let c1 = x0 - x1; + let c2 = x2 - c0; + let c3 = x3 - c0; + let c4 = c0 - x3 - x2 + x1; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dr * dg)) + } else if db > dr && dg > dr { + let x0 = fetch.fetch(x, y, z_n); + let x1 = fetch.fetch(x_n, y_n, z_n); + let x2 = fetch.fetch(x, y_n, z_n); + let x3 = fetch.fetch(x, y_n, z); + + let c1 = x0 - c0; + let c2 = x1 - x2; + let c3 = x3 - c0; + let c4 = c0 - x3 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(dg * db)) + } else { + let x0 = fetch.fetch(x, y, z_n); + let x1 = fetch.fetch(x_n, y, z); + let x2 = fetch.fetch(x_n, y, z_n); + let x3 = fetch.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - c0; + let c3 = x3 - x2; + let c4 = c0 - x1 - x0 + x2; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + s2.mla(c4, T::from(db * dr)) + } + } + + #[cfg(feature = "options")] + #[inline] + fn tetra< + T: Copy + + From + + Sub + + Mul + + Add + + FusedMultiplyAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + fetch: impl ArrayFetch, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + + let rx = lin_x * scale_x - x as f32; + let ry = lin_y * scale_y - y as f32; + let rz = lin_z * scale_z - z as f32; + + let c0 = fetch.fetch(x, y, z); + let c2; + let c1; + let c3; + if rx >= ry { + if ry >= rz { + //rx >= ry && ry >= rz + c1 = fetch.fetch(x_n, y, z) - c0; + c2 = fetch.fetch(x_n, y_n, z) - fetch.fetch(x_n, y, z); + c3 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x_n, y_n, z); + } else if rx >= rz { + //rx >= rz && rz >= ry + c1 = fetch.fetch(x_n, y, z) - c0; + c2 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x_n, y, z_n); + c3 = fetch.fetch(x_n, y, z_n) - fetch.fetch(x_n, y, z); + } else { + //rz > rx && rx >= ry + c1 = fetch.fetch(x_n, y, z_n) - fetch.fetch(x, y, z_n); + c2 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x_n, y, z_n); + c3 = fetch.fetch(x, y, z_n) - c0; + } + } else if rx >= rz { + //ry > rx && rx >= rz + c1 = fetch.fetch(x_n, y_n, z) - fetch.fetch(x, y_n, z); + c2 = fetch.fetch(x, y_n, z) - c0; + c3 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x_n, y_n, z); + } else if ry >= rz { + //ry >= rz && rz > rx + c1 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x, y_n, z_n); + c2 = fetch.fetch(x, y_n, z) - c0; + c3 = fetch.fetch(x, y_n, z_n) - fetch.fetch(x, y_n, z); + } else { + //rz > ry && ry > rx + c1 = fetch.fetch(x_n, y_n, z_n) - fetch.fetch(x, y_n, z_n); + c2 = fetch.fetch(x, y_n, z_n) - fetch.fetch(x, y, z_n); + c3 = fetch.fetch(x, y, z_n) - c0; + } + let s0 = c0.mla(c1, T::from(rx)); + let s1 = s0.mla(c2, T::from(ry)); + s1.mla(c3, T::from(rz)) + } + + #[cfg(feature = "options")] + #[inline] + fn prism< + T: Copy + + From + + Sub + + Mul + + Add + + FusedMultiplyAdd, + >( + &self, + lin_x: f32, + lin_y: f32, + lin_z: f32, + fetch: impl ArrayFetch, + ) -> T { + let lin_x = lin_x.max(0.0).min(1.0); + let lin_y = lin_y.max(0.0).min(1.0); + let lin_z = lin_z.max(0.0).min(1.0); + + let scale_x = (self.grid_size[0] as i32 - 1) as f32; + let scale_y = (self.grid_size[1] as i32 - 1) as f32; + let scale_z = (self.grid_size[2] as i32 - 1) as f32; + + let x = (lin_x * scale_x).floor() as i32; + let y = (lin_y * scale_y).floor() as i32; + let z = (lin_z * scale_z).floor() as i32; + + let x_n = (lin_x * scale_x).ceil() as i32; + let y_n = (lin_y * scale_y).ceil() as i32; + let z_n = (lin_z * scale_z).ceil() as i32; + + let dr = lin_x * scale_x - x as f32; + let dg = lin_y * scale_y - y as f32; + let db = lin_z * scale_z - z as f32; + + let c0 = fetch.fetch(x, y, z); + + if db >= dr { + let x0 = fetch.fetch(x, y, z_n); + let x1 = fetch.fetch(x_n, y, z_n); + let x2 = fetch.fetch(x, y_n, z); + let x3 = fetch.fetch(x, y_n, z_n); + let x4 = fetch.fetch(x_n, y_n, z_n); + + let c1 = x0 - c0; + let c2 = x1 - x0; + let c3 = x2 - c0; + let c4 = c0 - x2 - x0 + x3; + let c5 = x0 - x3 - x1 + x4; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } else { + let x0 = fetch.fetch(x_n, y, z); + let x1 = fetch.fetch(x_n, y, z_n); + let x2 = fetch.fetch(x, y_n, z); + let x3 = fetch.fetch(x_n, y_n, z); + let x4 = fetch.fetch(x_n, y_n, z_n); + + let c1 = x1 - x0; + let c2 = x0 - c0; + let c3 = x2 - c0; + let c4 = x0 - x3 - x1 + x4; + let c5 = c0 - x2 - x0 + x3; + + let s0 = c0.mla(c1, T::from(db)); + let s1 = s0.mla(c2, T::from(dr)); + let s2 = s1.mla(c3, T::from(dg)); + let s3 = s2.mla(c4, T::from(dg * db)); + s3.mla(c5, T::from(dr * dg)) + } + } + + pub fn trilinear_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector3f { + self.trilinear( + lin_x, + lin_y, + lin_z, + ArrayFetchVector3f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + pub fn prism_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector3f { + self.prism( + lin_x, + lin_y, + lin_z, + ArrayFetchVector3f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + pub fn pyramid_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector3f { + self.pyramid( + lin_x, + lin_y, + lin_z, + ArrayFetchVector3f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + pub fn tetra_vec3(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector3f { + self.tetra( + lin_x, + lin_y, + lin_z, + ArrayFetchVector3f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + pub fn trilinear_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector4f { + self.trilinear( + lin_x, + lin_y, + lin_z, + ArrayFetchVector4f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + pub fn tetra_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector4f { + self.tetra( + lin_x, + lin_y, + lin_z, + ArrayFetchVector4f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + pub fn pyramid_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector4f { + self.pyramid( + lin_x, + lin_y, + lin_z, + ArrayFetchVector4f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } + + #[cfg(feature = "options")] + #[cfg_attr(docsrs, doc(cfg(feature = "options")))] + pub fn prism_vec4(&self, lin_x: f32, lin_y: f32, lin_z: f32) -> Vector4f { + self.prism( + lin_x, + lin_y, + lin_z, + ArrayFetchVector4f { + array: self.array, + x_stride: self.x_stride, + y_stride: self.y_stride, + }, + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/oklab.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklab.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/oklab.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklab.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,354 @@ +/* + * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved. + * // + * // Use of this source code is governed by a BSD-style + * // license that can be found in the LICENSE file. + */ +use crate::Rgb; +use crate::mlaf::mlaf; +use num_traits::Pow; +use pxfm::{f_cbrtf, f_powf}; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +/// Struct that represent *Oklab* colorspace +pub struct Oklab { + /// All values in Oklab intended to be normalized \[0; 1\] + pub l: f32, + /// A value range \[-0.5; 0.5\] + pub a: f32, + /// B value range \[-0.5; 0.5\] + pub b: f32, +} + +impl Oklab { + #[inline] + pub const fn new(l: f32, a: f32, b: f32) -> Oklab { + Oklab { l, a, b } + } + + #[inline] + /// Convert Linear Rgb to [Oklab] + pub fn from_linear_rgb(rgb: Rgb) -> Oklab { + Self::linear_rgb_to_oklab(rgb) + } + + #[inline] + fn linear_rgb_to_oklab(rgb: Rgb) -> Oklab { + let l = mlaf( + mlaf(0.4122214708f32 * rgb.r, 0.5363325363f32, rgb.g), + 0.0514459929f32, + rgb.b, + ); + let m = mlaf( + mlaf(0.2119034982f32 * rgb.r, 0.6806995451f32, rgb.g), + 0.1073969566f32, + rgb.b, + ); + let s = mlaf( + mlaf(0.0883024619f32 * rgb.r, 0.2817188376f32, rgb.g), + 0.6299787005f32, + rgb.b, + ); + + let l_cone = f_cbrtf(l); + let m_cone = f_cbrtf(m); + let s_cone = f_cbrtf(s); + + Oklab { + l: mlaf( + mlaf(0.2104542553f32 * l_cone, 0.7936177850f32, m_cone), + -0.0040720468f32, + s_cone, + ), + a: mlaf( + mlaf(1.9779984951f32 * l_cone, -2.4285922050f32, m_cone), + 0.4505937099f32, + s_cone, + ), + b: mlaf( + mlaf(0.0259040371f32 * l_cone, 0.7827717662f32, m_cone), + -0.8086757660f32, + s_cone, + ), + } + } + + #[inline] + /// Converts to linear RGB + pub fn to_linear_rgb(&self) -> Rgb { + let l_ = mlaf( + mlaf(self.l, 0.3963377774f32, self.a), + 0.2158037573f32, + self.b, + ); + let m_ = mlaf( + mlaf(self.l, -0.1055613458f32, self.a), + -0.0638541728f32, + self.b, + ); + let s_ = mlaf( + mlaf(self.l, -0.0894841775f32, self.a), + -1.2914855480f32, + self.b, + ); + + let l = l_ * l_ * l_; + let m = m_ * m_ * m_; + let s = s_ * s_ * s_; + + Rgb::new( + mlaf( + mlaf(4.0767416621f32 * l, -3.3077115913f32, m), + 0.2309699292f32, + s, + ), + mlaf( + mlaf(-1.2684380046f32 * l, 2.6097574011f32, m), + -0.3413193965f32, + s, + ), + mlaf( + mlaf(-0.0041960863f32 * l, -0.7034186147f32, m), + 1.7076147010f32, + s, + ), + ) + } + + #[inline] + pub fn hybrid_distance(&self, other: Self) -> f32 { + let lax = self.l - other.l; + let dax = self.a - other.a; + let bax = self.b - other.b; + (dax * dax + bax * bax).sqrt() + lax.abs() + } +} + +impl Oklab { + pub fn euclidean_distance(&self, other: Self) -> f32 { + let lax = self.l - other.l; + let dax = self.a - other.a; + let bax = self.b - other.b; + (lax * lax + dax * dax + bax * bax).sqrt() + } +} + +impl Oklab { + pub fn taxicab_distance(&self, other: Self) -> f32 { + let lax = self.l - other.l; + let dax = self.a - other.a; + let bax = self.b - other.b; + lax.abs() + dax.abs() + bax.abs() + } +} + +impl Add for Oklab { + type Output = Oklab; + + #[inline] + fn add(self, rhs: Self) -> Oklab { + Oklab::new(self.l + rhs.l, self.a + rhs.a, self.b + rhs.b) + } +} + +impl Add for Oklab { + type Output = Oklab; + + #[inline] + fn add(self, rhs: f32) -> Oklab { + Oklab::new(self.l + rhs, self.a + rhs, self.b + rhs) + } +} + +impl AddAssign for Oklab { + #[inline] + fn add_assign(&mut self, rhs: Oklab) { + self.l += rhs.l; + self.a += rhs.a; + self.b += rhs.b; + } +} + +impl AddAssign for Oklab { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.l += rhs; + self.a += rhs; + self.b += rhs; + } +} + +impl Mul for Oklab { + type Output = Oklab; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + Oklab::new(self.l * rhs, self.a * rhs, self.b * rhs) + } +} + +impl Mul for Oklab { + type Output = Oklab; + + #[inline] + fn mul(self, rhs: Oklab) -> Self::Output { + Oklab::new(self.l * rhs.l, self.a * rhs.a, self.b * rhs.b) + } +} + +impl MulAssign for Oklab { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.l *= rhs; + self.a *= rhs; + self.b *= rhs; + } +} + +impl MulAssign for Oklab { + #[inline] + fn mul_assign(&mut self, rhs: Oklab) { + self.l *= rhs.l; + self.a *= rhs.a; + self.b *= rhs.b; + } +} + +impl Sub for Oklab { + type Output = Oklab; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + Oklab::new(self.l - rhs, self.a - rhs, self.b - rhs) + } +} + +impl Sub for Oklab { + type Output = Oklab; + + #[inline] + fn sub(self, rhs: Oklab) -> Self::Output { + Oklab::new(self.l - rhs.l, self.a - rhs.a, self.b - rhs.b) + } +} + +impl SubAssign for Oklab { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.l -= rhs; + self.a -= rhs; + self.b -= rhs; + } +} + +impl SubAssign for Oklab { + #[inline] + fn sub_assign(&mut self, rhs: Oklab) { + self.l -= rhs.l; + self.a -= rhs.a; + self.b -= rhs.b; + } +} + +impl Div for Oklab { + type Output = Oklab; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + Oklab::new(self.l / rhs, self.a / rhs, self.b / rhs) + } +} + +impl Div for Oklab { + type Output = Oklab; + + #[inline] + fn div(self, rhs: Oklab) -> Self::Output { + Oklab::new(self.l / rhs.l, self.a / rhs.a, self.b / rhs.b) + } +} + +impl DivAssign for Oklab { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.l /= rhs; + self.a /= rhs; + self.b /= rhs; + } +} + +impl DivAssign for Oklab { + #[inline] + fn div_assign(&mut self, rhs: Oklab) { + self.l /= rhs.l; + self.a /= rhs.a; + self.b /= rhs.b; + } +} + +impl Neg for Oklab { + type Output = Oklab; + + #[inline] + fn neg(self) -> Self::Output { + Oklab::new(-self.l, -self.a, -self.b) + } +} + +impl Pow for Oklab { + type Output = Oklab; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + Oklab::new( + f_powf(self.l, rhs), + f_powf(self.a, rhs), + f_powf(self.b, rhs), + ) + } +} + +impl Pow for Oklab { + type Output = Oklab; + + #[inline] + fn pow(self, rhs: Oklab) -> Self::Output { + Oklab::new( + f_powf(self.l, rhs.l), + f_powf(self.a, rhs.a), + f_powf(self.b, rhs.b), + ) + } +} + +impl Oklab { + #[inline] + pub fn sqrt(&self) -> Oklab { + Oklab::new(self.l.sqrt(), self.a.sqrt(), self.b.sqrt()) + } + + #[inline] + pub fn cbrt(&self) -> Oklab { + Oklab::new(f_cbrtf(self.l), f_cbrtf(self.a), f_cbrtf(self.b)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip() { + let xyz = Rgb::new(0.1, 0.2, 0.3); + let lab = Oklab::from_linear_rgb(xyz); + let rolled_back = lab.to_linear_rgb(); + let dx = (xyz.r - rolled_back.r).abs(); + let dy = (xyz.g - rolled_back.g).abs(); + let dz = (xyz.b - rolled_back.b).abs(); + assert!(dx < 1e-5); + assert!(dy < 1e-5); + assert!(dz < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/oklch.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklch.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/oklch.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/oklch.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,294 @@ +/* + * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved. + * // + * // Use of this source code is governed by a BSD-style + * // license that can be found in the LICENSE file. + */ +use crate::{Oklab, Rgb}; +use num_traits::Pow; +use pxfm::{f_atan2f, f_cbrtf, f_hypotf, f_powf, f_sincosf}; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; + +/// Represents *Oklch* colorspace +#[repr(C)] +#[derive(Copy, Clone, PartialOrd, PartialEq)] +pub struct Oklch { + /// Lightness + pub l: f32, + /// Chroma + pub c: f32, + /// Hue + pub h: f32, +} + +impl Oklch { + /// Creates new instance + #[inline] + pub const fn new(l: f32, c: f32, h: f32) -> Oklch { + Oklch { l, c, h } + } + + /// Converts Linear [Rgb] into [Oklch] + /// + /// # Arguments + /// `transfer_function` - Transfer function into linear colorspace and its inverse + #[inline] + pub fn from_linear_rgb(rgb: Rgb) -> Oklch { + let oklab = Oklab::from_linear_rgb(rgb); + Oklch::from_oklab(oklab) + } + + /// Converts [Oklch] into linear [Rgb] + #[inline] + pub fn to_linear_rgb(&self) -> Rgb { + let oklab = self.to_oklab(); + oklab.to_linear_rgb() + } + + /// Converts *Oklab* to *Oklch* + #[inline] + pub fn from_oklab(oklab: Oklab) -> Oklch { + let chroma = f_hypotf(oklab.b, oklab.a); + let hue = f_atan2f(oklab.b, oklab.a); + Oklch::new(oklab.l, chroma, hue) + } + + /// Converts *Oklch* to *Oklab* + #[inline] + pub fn to_oklab(&self) -> Oklab { + let l = self.l; + let sincos = f_sincosf(self.h); + let a = self.c * sincos.1; + let b = self.c * sincos.0; + Oklab::new(l, a, b) + } +} + +impl Oklch { + #[inline] + pub fn euclidean_distance(&self, other: Self) -> f32 { + let dl = self.l - other.l; + let dc = self.c - other.c; + let dh = self.h - other.h; + (dl * dl + dc * dc + dh * dh).sqrt() + } +} + +impl Oklch { + #[inline] + pub fn taxicab_distance(&self, other: Self) -> f32 { + let dl = self.l - other.l; + let dc = self.c - other.c; + let dh = self.h - other.h; + dl.abs() + dc.abs() + dh.abs() + } +} + +impl Add for Oklch { + type Output = Oklch; + + #[inline] + fn add(self, rhs: Self) -> Oklch { + Oklch::new(self.l + rhs.l, self.c + rhs.c, self.h + rhs.h) + } +} + +impl Add for Oklch { + type Output = Oklch; + + #[inline] + fn add(self, rhs: f32) -> Oklch { + Oklch::new(self.l + rhs, self.c + rhs, self.h + rhs) + } +} + +impl AddAssign for Oklch { + #[inline] + fn add_assign(&mut self, rhs: Oklch) { + self.l += rhs.l; + self.c += rhs.c; + self.h += rhs.h; + } +} + +impl AddAssign for Oklch { + #[inline] + fn add_assign(&mut self, rhs: f32) { + self.l += rhs; + self.c += rhs; + self.h += rhs; + } +} + +impl Mul for Oklch { + type Output = Oklch; + + #[inline] + fn mul(self, rhs: f32) -> Self::Output { + Oklch::new(self.l * rhs, self.c * rhs, self.h * rhs) + } +} + +impl Mul for Oklch { + type Output = Oklch; + + #[inline] + fn mul(self, rhs: Oklch) -> Self::Output { + Oklch::new(self.l * rhs.l, self.c * rhs.c, self.h * rhs.h) + } +} + +impl MulAssign for Oklch { + #[inline] + fn mul_assign(&mut self, rhs: f32) { + self.l *= rhs; + self.c *= rhs; + self.h *= rhs; + } +} + +impl MulAssign for Oklch { + #[inline] + fn mul_assign(&mut self, rhs: Oklch) { + self.l *= rhs.l; + self.c *= rhs.c; + self.h *= rhs.h; + } +} + +impl Sub for Oklch { + type Output = Oklch; + + #[inline] + fn sub(self, rhs: f32) -> Self::Output { + Oklch::new(self.l - rhs, self.c - rhs, self.h - rhs) + } +} + +impl Sub for Oklch { + type Output = Oklch; + + #[inline] + fn sub(self, rhs: Oklch) -> Self::Output { + Oklch::new(self.l - rhs.l, self.c - rhs.c, self.h - rhs.h) + } +} + +impl SubAssign for Oklch { + #[inline] + fn sub_assign(&mut self, rhs: f32) { + self.l -= rhs; + self.c -= rhs; + self.h -= rhs; + } +} + +impl SubAssign for Oklch { + #[inline] + fn sub_assign(&mut self, rhs: Oklch) { + self.l -= rhs.l; + self.c -= rhs.c; + self.h -= rhs.h; + } +} + +impl Div for Oklch { + type Output = Oklch; + + #[inline] + fn div(self, rhs: f32) -> Self::Output { + Oklch::new(self.l / rhs, self.c / rhs, self.h / rhs) + } +} + +impl Div for Oklch { + type Output = Oklch; + + #[inline] + fn div(self, rhs: Oklch) -> Self::Output { + Oklch::new(self.l / rhs.l, self.c / rhs.c, self.h / rhs.h) + } +} + +impl DivAssign for Oklch { + #[inline] + fn div_assign(&mut self, rhs: f32) { + self.l /= rhs; + self.c /= rhs; + self.h /= rhs; + } +} + +impl DivAssign for Oklch { + #[inline] + fn div_assign(&mut self, rhs: Oklch) { + self.l /= rhs.l; + self.c /= rhs.c; + self.h /= rhs.h; + } +} + +impl Neg for Oklch { + type Output = Oklch; + + #[inline] + fn neg(self) -> Self::Output { + Oklch::new(-self.l, -self.c, -self.h) + } +} + +impl Pow for Oklch { + type Output = Oklch; + + #[inline] + fn pow(self, rhs: f32) -> Self::Output { + Oklch::new( + f_powf(self.l, rhs), + f_powf(self.c, rhs), + f_powf(self.h, rhs), + ) + } +} + +impl Pow for Oklch { + type Output = Oklch; + + #[inline] + fn pow(self, rhs: Oklch) -> Self::Output { + Oklch::new( + f_powf(self.l, rhs.l), + f_powf(self.c, rhs.c), + f_powf(self.h, rhs.h), + ) + } +} + +impl Oklch { + #[inline] + pub fn sqrt(&self) -> Oklch { + Oklch::new(self.l.sqrt(), self.c.sqrt(), self.h.sqrt()) + } + + #[inline] + pub fn cbrt(&self) -> Oklch { + Oklch::new(f_cbrtf(self.l), f_cbrtf(self.c), f_cbrtf(self.h)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip() { + let xyz = Rgb::new(0.1, 0.2, 0.3); + let lab = Oklch::from_linear_rgb(xyz); + let rolled_back = lab.to_linear_rgb(); + let dx = (xyz.r - rolled_back.r).abs(); + let dy = (xyz.g - rolled_back.g).abs(); + let dz = (xyz.b - rolled_back.b).abs(); + assert!(dx < 1e-5); + assert!(dy < 1e-5); + assert!(dz < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/profile.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/profile.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/profile.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/profile.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1385 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::chad::BRADFORD_D; +use crate::cicp::{ + CicpColorPrimaries, ColorPrimaries, MatrixCoefficients, TransferCharacteristics, +}; +use crate::dat::ColorDateTime; +use crate::err::CmsError; +use crate::matrix::{Matrix3f, Xyz}; +use crate::reader::s15_fixed16_number_to_float; +use crate::safe_math::{SafeAdd, SafeMul}; +use crate::tag::{TAG_SIZE, Tag}; +use crate::trc::ToneReprCurve; +use crate::{Chromaticity, Layout, Matrix3d, Vector3d, XyY, Xyzd, adapt_to_d50_d}; +use std::io::Read; + +const MAX_PROFILE_SIZE: usize = 1024 * 1024 * 10; // 10 MB max, for Fogra39 etc + +#[repr(u32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ProfileSignature { + Acsp, +} + +impl TryFrom for ProfileSignature { + type Error = CmsError; + #[inline] + fn try_from(value: u32) -> Result { + if value == u32::from_ne_bytes(*b"acsp").to_be() { + return Ok(ProfileSignature::Acsp); + } + Err(CmsError::InvalidProfile) + } +} + +impl From for u32 { + #[inline] + fn from(value: ProfileSignature) -> Self { + match value { + ProfileSignature::Acsp => u32::from_ne_bytes(*b"acsp").to_be(), + } + } +} + +#[repr(u32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Ord, PartialOrd)] +pub enum ProfileVersion { + V2_0 = 0x02000000, + V2_1 = 0x02100000, + V2_2 = 0x02200000, + V2_3 = 0x02300000, + V2_4 = 0x02400000, + V4_0 = 0x04000000, + V4_1 = 0x04100000, + V4_2 = 0x04200000, + V4_3 = 0x04300000, + #[default] + V4_4 = 0x04400000, + Unknown, +} + +impl TryFrom for ProfileVersion { + type Error = CmsError; + fn try_from(value: u32) -> Result { + match value { + 0x02000000 => Ok(ProfileVersion::V2_0), + 0x02100000 => Ok(ProfileVersion::V2_1), + 0x02200000 => Ok(ProfileVersion::V2_2), + 0x02300000 => Ok(ProfileVersion::V2_3), + 0x02400000 => Ok(ProfileVersion::V2_4), + 0x04000000 => Ok(ProfileVersion::V4_0), + 0x04100000 => Ok(ProfileVersion::V4_1), + 0x04200000 => Ok(ProfileVersion::V4_2), + 0x04300000 => Ok(ProfileVersion::V4_3), + 0x04400000 => Ok(ProfileVersion::V4_3), + _ => Err(CmsError::InvalidProfile), + } + } +} + +impl From for u32 { + fn from(value: ProfileVersion) -> Self { + match value { + ProfileVersion::V2_0 => 0x02000000, + ProfileVersion::V2_1 => 0x02100000, + ProfileVersion::V2_2 => 0x02200000, + ProfileVersion::V2_3 => 0x02300000, + ProfileVersion::V2_4 => 0x02400000, + ProfileVersion::V4_0 => 0x04000000, + ProfileVersion::V4_1 => 0x04100000, + ProfileVersion::V4_2 => 0x04200000, + ProfileVersion::V4_3 => 0x04300000, + ProfileVersion::V4_4 => 0x04400000, + ProfileVersion::Unknown => 0x02000000, + } + } +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Default, Hash)] +pub enum DataColorSpace { + #[default] + Xyz, + Lab, + Luv, + YCbr, + Yxy, + Rgb, + Gray, + Hsv, + Hls, + Cmyk, + Cmy, + Color2, + Color3, + Color4, + Color5, + Color6, + Color7, + Color8, + Color9, + Color10, + Color11, + Color12, + Color13, + Color14, + Color15, +} + +impl DataColorSpace { + #[inline] + pub fn check_layout(self, layout: Layout) -> Result<(), CmsError> { + let unsupported: bool = match self { + DataColorSpace::Xyz => layout != Layout::Rgb, + DataColorSpace::Lab => layout != Layout::Rgb && layout != Layout::Rgba, + DataColorSpace::Luv => layout != Layout::Rgb, + DataColorSpace::YCbr => layout != Layout::Rgb, + DataColorSpace::Yxy => layout != Layout::Rgb, + DataColorSpace::Rgb => layout != Layout::Rgb && layout != Layout::Rgba, + DataColorSpace::Gray => layout != Layout::Gray && layout != Layout::GrayAlpha, + DataColorSpace::Hsv => layout != Layout::Rgb, + DataColorSpace::Hls => layout != Layout::Rgb, + DataColorSpace::Cmyk => layout != Layout::Rgba, + DataColorSpace::Cmy => layout != Layout::Rgb, + DataColorSpace::Color2 => layout != Layout::GrayAlpha, + DataColorSpace::Color3 => layout != Layout::Rgb, + DataColorSpace::Color4 => layout != Layout::Rgba, + DataColorSpace::Color5 => layout != Layout::Inks5, + DataColorSpace::Color6 => layout != Layout::Inks6, + DataColorSpace::Color7 => layout != Layout::Inks7, + DataColorSpace::Color8 => layout != Layout::Inks8, + DataColorSpace::Color9 => layout != Layout::Inks9, + DataColorSpace::Color10 => layout != Layout::Inks10, + DataColorSpace::Color11 => layout != Layout::Inks11, + DataColorSpace::Color12 => layout != Layout::Inks12, + DataColorSpace::Color13 => layout != Layout::Inks13, + DataColorSpace::Color14 => layout != Layout::Inks14, + DataColorSpace::Color15 => layout != Layout::Inks15, + }; + if unsupported { + Err(CmsError::InvalidLayout) + } else { + Ok(()) + } + } + + pub(crate) fn is_three_channels(self) -> bool { + matches!( + self, + DataColorSpace::Xyz + | DataColorSpace::Lab + | DataColorSpace::Luv + | DataColorSpace::YCbr + | DataColorSpace::Yxy + | DataColorSpace::Rgb + | DataColorSpace::Hsv + | DataColorSpace::Hls + | DataColorSpace::Cmy + | DataColorSpace::Color3 + ) + } +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Default)] +pub enum ProfileClass { + InputDevice, + #[default] + DisplayDevice, + OutputDevice, + DeviceLink, + ColorSpace, + Abstract, + Named, +} + +impl TryFrom for ProfileClass { + type Error = CmsError; + fn try_from(value: u32) -> Result { + if value == u32::from_ne_bytes(*b"scnr").to_be() { + return Ok(ProfileClass::InputDevice); + } else if value == u32::from_ne_bytes(*b"mntr").to_be() { + return Ok(ProfileClass::DisplayDevice); + } else if value == u32::from_ne_bytes(*b"prtr").to_be() { + return Ok(ProfileClass::OutputDevice); + } else if value == u32::from_ne_bytes(*b"link").to_be() { + return Ok(ProfileClass::DeviceLink); + } else if value == u32::from_ne_bytes(*b"spac").to_be() { + return Ok(ProfileClass::ColorSpace); + } else if value == u32::from_ne_bytes(*b"abst").to_be() { + return Ok(ProfileClass::Abstract); + } else if value == u32::from_ne_bytes(*b"nmcl").to_be() { + return Ok(ProfileClass::Named); + } + Err(CmsError::InvalidProfile) + } +} + +impl From for u32 { + fn from(val: ProfileClass) -> Self { + match val { + ProfileClass::InputDevice => u32::from_ne_bytes(*b"scnr").to_be(), + ProfileClass::DisplayDevice => u32::from_ne_bytes(*b"mntr").to_be(), + ProfileClass::OutputDevice => u32::from_ne_bytes(*b"prtr").to_be(), + ProfileClass::DeviceLink => u32::from_ne_bytes(*b"link").to_be(), + ProfileClass::ColorSpace => u32::from_ne_bytes(*b"spac").to_be(), + ProfileClass::Abstract => u32::from_ne_bytes(*b"abst").to_be(), + ProfileClass::Named => u32::from_ne_bytes(*b"nmcl").to_be(), + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum LutStore { + Store8(Vec), + Store16(Vec), +} + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum LutType { + Lut8, + Lut16, + LutMab, + LutMba, +} + +impl TryFrom for LutType { + type Error = CmsError; + fn try_from(value: u32) -> Result { + if value == u32::from_ne_bytes(*b"mft1").to_be() { + return Ok(LutType::Lut8); + } else if value == u32::from_ne_bytes(*b"mft2").to_be() { + return Ok(LutType::Lut16); + } else if value == u32::from_ne_bytes(*b"mAB ").to_be() { + return Ok(LutType::LutMab); + } else if value == u32::from_ne_bytes(*b"mBA ").to_be() { + return Ok(LutType::LutMba); + } + Err(CmsError::InvalidProfile) + } +} + +impl From for u32 { + fn from(val: LutType) -> Self { + match val { + LutType::Lut8 => u32::from_ne_bytes(*b"mft1").to_be(), + LutType::Lut16 => u32::from_ne_bytes(*b"mft2").to_be(), + LutType::LutMab => u32::from_ne_bytes(*b"mAB ").to_be(), + LutType::LutMba => u32::from_ne_bytes(*b"mBA ").to_be(), + } + } +} + +impl TryFrom for DataColorSpace { + type Error = CmsError; + fn try_from(value: u32) -> Result { + if value == u32::from_ne_bytes(*b"XYZ ").to_be() { + return Ok(DataColorSpace::Xyz); + } else if value == u32::from_ne_bytes(*b"Lab ").to_be() { + return Ok(DataColorSpace::Lab); + } else if value == u32::from_ne_bytes(*b"Luv ").to_be() { + return Ok(DataColorSpace::Luv); + } else if value == u32::from_ne_bytes(*b"YCbr").to_be() { + return Ok(DataColorSpace::YCbr); + } else if value == u32::from_ne_bytes(*b"Yxy ").to_be() { + return Ok(DataColorSpace::Yxy); + } else if value == u32::from_ne_bytes(*b"RGB ").to_be() { + return Ok(DataColorSpace::Rgb); + } else if value == u32::from_ne_bytes(*b"GRAY").to_be() { + return Ok(DataColorSpace::Gray); + } else if value == u32::from_ne_bytes(*b"HSV ").to_be() { + return Ok(DataColorSpace::Hsv); + } else if value == u32::from_ne_bytes(*b"HLS ").to_be() { + return Ok(DataColorSpace::Hls); + } else if value == u32::from_ne_bytes(*b"CMYK").to_be() { + return Ok(DataColorSpace::Cmyk); + } else if value == u32::from_ne_bytes(*b"CMY ").to_be() { + return Ok(DataColorSpace::Cmy); + } else if value == u32::from_ne_bytes(*b"2CLR").to_be() { + return Ok(DataColorSpace::Color2); + } else if value == u32::from_ne_bytes(*b"3CLR").to_be() { + return Ok(DataColorSpace::Color3); + } else if value == u32::from_ne_bytes(*b"4CLR").to_be() { + return Ok(DataColorSpace::Color4); + } else if value == u32::from_ne_bytes(*b"5CLR").to_be() { + return Ok(DataColorSpace::Color5); + } else if value == u32::from_ne_bytes(*b"6CLR").to_be() { + return Ok(DataColorSpace::Color6); + } else if value == u32::from_ne_bytes(*b"7CLR").to_be() { + return Ok(DataColorSpace::Color7); + } else if value == u32::from_ne_bytes(*b"8CLR").to_be() { + return Ok(DataColorSpace::Color8); + } else if value == u32::from_ne_bytes(*b"9CLR").to_be() { + return Ok(DataColorSpace::Color9); + } else if value == u32::from_ne_bytes(*b"ACLR").to_be() { + return Ok(DataColorSpace::Color10); + } else if value == u32::from_ne_bytes(*b"BCLR").to_be() { + return Ok(DataColorSpace::Color11); + } else if value == u32::from_ne_bytes(*b"CCLR").to_be() { + return Ok(DataColorSpace::Color12); + } else if value == u32::from_ne_bytes(*b"DCLR").to_be() { + return Ok(DataColorSpace::Color13); + } else if value == u32::from_ne_bytes(*b"ECLR").to_be() { + return Ok(DataColorSpace::Color14); + } else if value == u32::from_ne_bytes(*b"FCLR").to_be() { + return Ok(DataColorSpace::Color15); + } + Err(CmsError::InvalidProfile) + } +} + +impl From for u32 { + fn from(val: DataColorSpace) -> Self { + match val { + DataColorSpace::Xyz => u32::from_ne_bytes(*b"XYZ ").to_be(), + DataColorSpace::Lab => u32::from_ne_bytes(*b"Lab ").to_be(), + DataColorSpace::Luv => u32::from_ne_bytes(*b"Luv ").to_be(), + DataColorSpace::YCbr => u32::from_ne_bytes(*b"YCbr").to_be(), + DataColorSpace::Yxy => u32::from_ne_bytes(*b"Yxy ").to_be(), + DataColorSpace::Rgb => u32::from_ne_bytes(*b"RGB ").to_be(), + DataColorSpace::Gray => u32::from_ne_bytes(*b"GRAY").to_be(), + DataColorSpace::Hsv => u32::from_ne_bytes(*b"HSV ").to_be(), + DataColorSpace::Hls => u32::from_ne_bytes(*b"HLS ").to_be(), + DataColorSpace::Cmyk => u32::from_ne_bytes(*b"CMYK").to_be(), + DataColorSpace::Cmy => u32::from_ne_bytes(*b"CMY ").to_be(), + DataColorSpace::Color2 => u32::from_ne_bytes(*b"2CLR").to_be(), + DataColorSpace::Color3 => u32::from_ne_bytes(*b"3CLR").to_be(), + DataColorSpace::Color4 => u32::from_ne_bytes(*b"4CLR").to_be(), + DataColorSpace::Color5 => u32::from_ne_bytes(*b"5CLR").to_be(), + DataColorSpace::Color6 => u32::from_ne_bytes(*b"6CLR").to_be(), + DataColorSpace::Color7 => u32::from_ne_bytes(*b"7CLR").to_be(), + DataColorSpace::Color8 => u32::from_ne_bytes(*b"8CLR").to_be(), + DataColorSpace::Color9 => u32::from_ne_bytes(*b"9CLR").to_be(), + DataColorSpace::Color10 => u32::from_ne_bytes(*b"ACLR").to_be(), + DataColorSpace::Color11 => u32::from_ne_bytes(*b"BCLR").to_be(), + DataColorSpace::Color12 => u32::from_ne_bytes(*b"CCLR").to_be(), + DataColorSpace::Color13 => u32::from_ne_bytes(*b"DCLR").to_be(), + DataColorSpace::Color14 => u32::from_ne_bytes(*b"ECLR").to_be(), + DataColorSpace::Color15 => u32::from_ne_bytes(*b"FCLR").to_be(), + } + } +} + +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] +pub enum TechnologySignatures { + FilmScanner, + DigitalCamera, + ReflectiveScanner, + InkJetPrinter, + ThermalWaxPrinter, + ElectrophotographicPrinter, + ElectrostaticPrinter, + DyeSublimationPrinter, + PhotographicPaperPrinter, + FilmWriter, + VideoMonitor, + VideoCamera, + ProjectionTelevision, + CathodeRayTubeDisplay, + PassiveMatrixDisplay, + ActiveMatrixDisplay, + LiquidCrystalDisplay, + OrganicLedDisplay, + PhotoCd, + PhotographicImageSetter, + Gravure, + OffsetLithography, + Silkscreen, + Flexography, + MotionPictureFilmScanner, + MotionPictureFilmRecorder, + DigitalMotionPictureCamera, + DigitalCinemaProjector, + Unknown(u32), +} + +impl From for TechnologySignatures { + fn from(value: u32) -> Self { + if value == u32::from_ne_bytes(*b"fscn").to_be() { + return TechnologySignatures::FilmScanner; + } else if value == u32::from_ne_bytes(*b"dcam").to_be() { + return TechnologySignatures::DigitalCamera; + } else if value == u32::from_ne_bytes(*b"rscn").to_be() { + return TechnologySignatures::ReflectiveScanner; + } else if value == u32::from_ne_bytes(*b"ijet").to_be() { + return TechnologySignatures::InkJetPrinter; + } else if value == u32::from_ne_bytes(*b"twax").to_be() { + return TechnologySignatures::ThermalWaxPrinter; + } else if value == u32::from_ne_bytes(*b"epho").to_be() { + return TechnologySignatures::ElectrophotographicPrinter; + } else if value == u32::from_ne_bytes(*b"esta").to_be() { + return TechnologySignatures::ElectrostaticPrinter; + } else if value == u32::from_ne_bytes(*b"dsub").to_be() { + return TechnologySignatures::DyeSublimationPrinter; + } else if value == u32::from_ne_bytes(*b"rpho").to_be() { + return TechnologySignatures::PhotographicPaperPrinter; + } else if value == u32::from_ne_bytes(*b"fprn").to_be() { + return TechnologySignatures::FilmWriter; + } else if value == u32::from_ne_bytes(*b"vidm").to_be() { + return TechnologySignatures::VideoMonitor; + } else if value == u32::from_ne_bytes(*b"vidc").to_be() { + return TechnologySignatures::VideoCamera; + } else if value == u32::from_ne_bytes(*b"pjtv").to_be() { + return TechnologySignatures::ProjectionTelevision; + } else if value == u32::from_ne_bytes(*b"CRT ").to_be() { + return TechnologySignatures::CathodeRayTubeDisplay; + } else if value == u32::from_ne_bytes(*b"PMD ").to_be() { + return TechnologySignatures::PassiveMatrixDisplay; + } else if value == u32::from_ne_bytes(*b"AMD ").to_be() { + return TechnologySignatures::ActiveMatrixDisplay; + } else if value == u32::from_ne_bytes(*b"LCD ").to_be() { + return TechnologySignatures::LiquidCrystalDisplay; + } else if value == u32::from_ne_bytes(*b"OLED").to_be() { + return TechnologySignatures::OrganicLedDisplay; + } else if value == u32::from_ne_bytes(*b"KPCD").to_be() { + return TechnologySignatures::PhotoCd; + } else if value == u32::from_ne_bytes(*b"imgs").to_be() { + return TechnologySignatures::PhotographicImageSetter; + } else if value == u32::from_ne_bytes(*b"grav").to_be() { + return TechnologySignatures::Gravure; + } else if value == u32::from_ne_bytes(*b"offs").to_be() { + return TechnologySignatures::OffsetLithography; + } else if value == u32::from_ne_bytes(*b"silk").to_be() { + return TechnologySignatures::Silkscreen; + } else if value == u32::from_ne_bytes(*b"flex").to_be() { + return TechnologySignatures::Flexography; + } else if value == u32::from_ne_bytes(*b"mpfs").to_be() { + return TechnologySignatures::MotionPictureFilmScanner; + } else if value == u32::from_ne_bytes(*b"mpfr").to_be() { + return TechnologySignatures::MotionPictureFilmRecorder; + } else if value == u32::from_ne_bytes(*b"dmpc").to_be() { + return TechnologySignatures::DigitalMotionPictureCamera; + } else if value == u32::from_ne_bytes(*b"dcpj").to_be() { + return TechnologySignatures::DigitalCinemaProjector; + } + TechnologySignatures::Unknown(value) + } +} + +#[derive(Debug, Clone)] +pub enum LutWarehouse { + Lut(LutDataType), + Multidimensional(LutMultidimensionalType), +} + +impl PartialEq for LutWarehouse { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (LutWarehouse::Lut(a), LutWarehouse::Lut(b)) => a == b, + (LutWarehouse::Multidimensional(a), LutWarehouse::Multidimensional(b)) => a == b, + _ => false, // Different variants are not equal + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct LutDataType { + // used by lut8Type/lut16Type (mft2) only + pub num_input_channels: u8, + pub num_output_channels: u8, + pub num_clut_grid_points: u8, + pub matrix: Matrix3d, + pub num_input_table_entries: u16, + pub num_output_table_entries: u16, + pub input_table: LutStore, + pub clut_table: LutStore, + pub output_table: LutStore, + pub lut_type: LutType, +} + +impl LutDataType { + pub(crate) fn has_same_kind(&self) -> bool { + matches!( + (&self.input_table, &self.clut_table, &self.output_table), + ( + LutStore::Store8(_), + LutStore::Store8(_), + LutStore::Store8(_) + ) | ( + LutStore::Store16(_), + LutStore::Store16(_), + LutStore::Store16(_) + ) + ) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct LutMultidimensionalType { + pub num_input_channels: u8, + pub num_output_channels: u8, + pub grid_points: [u8; 16], + pub clut: Option, + pub a_curves: Vec, + pub b_curves: Vec, + pub m_curves: Vec, + pub matrix: Matrix3d, + pub bias: Vector3d, +} + +#[repr(u32)] +#[derive(Clone, Copy, Debug, Default, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub enum RenderingIntent { + AbsoluteColorimetric = 3, + Saturation = 2, + RelativeColorimetric = 1, + #[default] + Perceptual = 0, +} + +impl TryFrom for RenderingIntent { + type Error = CmsError; + + #[inline] + fn try_from(value: u32) -> Result { + match value { + 0 => Ok(RenderingIntent::Perceptual), + 1 => Ok(RenderingIntent::RelativeColorimetric), + 2 => Ok(RenderingIntent::Saturation), + 3 => Ok(RenderingIntent::AbsoluteColorimetric), + _ => Err(CmsError::InvalidRenderingIntent), + } + } +} + +impl From for u32 { + #[inline] + fn from(value: RenderingIntent) -> Self { + match value { + RenderingIntent::AbsoluteColorimetric => 3, + RenderingIntent::Saturation => 2, + RenderingIntent::RelativeColorimetric => 1, + RenderingIntent::Perceptual => 0, + } + } +} + +/// ICC Header +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub(crate) struct ProfileHeader { + pub size: u32, // Size of the profile (computed) + pub cmm_type: u32, // Preferred CMM type (ignored) + pub version: ProfileVersion, // Version (4.3 or 4.4 if CICP is included) + pub profile_class: ProfileClass, // Display device profile + pub data_color_space: DataColorSpace, // RGB input color space + pub pcs: DataColorSpace, // Profile connection space + pub creation_date_time: ColorDateTime, // Date and time + pub signature: ProfileSignature, // Profile signature + pub platform: u32, // Platform target (ignored) + pub flags: u32, // Flags (not embedded, can be used independently) + pub device_manufacturer: u32, // Device manufacturer (ignored) + pub device_model: u32, // Device model (ignored) + pub device_attributes: [u8; 8], // Device attributes (ignored) + pub rendering_intent: RenderingIntent, // Relative colorimetric rendering intent + pub illuminant: Xyz, // D50 standard illuminant X + pub creator: u32, // Profile creator (ignored) + pub profile_id: [u8; 16], // Profile id checksum (ignored) + pub reserved: [u8; 28], // Reserved (ignored) + pub tag_count: u32, // Technically not part of header, but required +} + +impl ProfileHeader { + #[allow(dead_code)] + pub(crate) fn new(size: u32) -> Self { + Self { + size, + cmm_type: 0, + version: ProfileVersion::V4_3, + profile_class: ProfileClass::DisplayDevice, + data_color_space: DataColorSpace::Rgb, + pcs: DataColorSpace::Xyz, + creation_date_time: ColorDateTime::default(), + signature: ProfileSignature::Acsp, + platform: 0, + flags: 0x00000000, + device_manufacturer: 0, + device_model: 0, + device_attributes: [0; 8], + rendering_intent: RenderingIntent::Perceptual, + illuminant: Chromaticity::D50.to_xyz(), + creator: 0, + profile_id: [0; 16], + reserved: [0; 28], + tag_count: 0, + } + } + + /// Creates profile from the buffer + pub(crate) fn new_from_slice(slice: &[u8]) -> Result { + if slice.len() < size_of::() { + return Err(CmsError::InvalidProfile); + } + let mut cursor = std::io::Cursor::new(slice); + let mut buffer = [0u8; size_of::()]; + cursor + .read_exact(&mut buffer) + .map_err(|_| CmsError::InvalidProfile)?; + + let header = Self { + size: u32::from_be_bytes(buffer[0..4].try_into().unwrap()), + cmm_type: u32::from_be_bytes(buffer[4..8].try_into().unwrap()), + version: ProfileVersion::try_from(u32::from_be_bytes( + buffer[8..12].try_into().unwrap(), + ))?, + profile_class: ProfileClass::try_from(u32::from_be_bytes( + buffer[12..16].try_into().unwrap(), + ))?, + data_color_space: DataColorSpace::try_from(u32::from_be_bytes( + buffer[16..20].try_into().unwrap(), + ))?, + pcs: DataColorSpace::try_from(u32::from_be_bytes(buffer[20..24].try_into().unwrap()))?, + creation_date_time: ColorDateTime::new_from_slice(buffer[24..36].try_into().unwrap())?, + signature: ProfileSignature::try_from(u32::from_be_bytes( + buffer[36..40].try_into().unwrap(), + ))?, + platform: u32::from_be_bytes(buffer[40..44].try_into().unwrap()), + flags: u32::from_be_bytes(buffer[44..48].try_into().unwrap()), + device_manufacturer: u32::from_be_bytes(buffer[48..52].try_into().unwrap()), + device_model: u32::from_be_bytes(buffer[52..56].try_into().unwrap()), + device_attributes: buffer[56..64].try_into().unwrap(), + rendering_intent: RenderingIntent::try_from(u32::from_be_bytes( + buffer[64..68].try_into().unwrap(), + ))?, + illuminant: Xyz::new( + s15_fixed16_number_to_float(i32::from_be_bytes(buffer[68..72].try_into().unwrap())), + s15_fixed16_number_to_float(i32::from_be_bytes(buffer[72..76].try_into().unwrap())), + s15_fixed16_number_to_float(i32::from_be_bytes(buffer[76..80].try_into().unwrap())), + ), + creator: u32::from_be_bytes(buffer[80..84].try_into().unwrap()), + profile_id: buffer[84..100].try_into().unwrap(), + reserved: buffer[100..128].try_into().unwrap(), + tag_count: u32::from_be_bytes(buffer[128..132].try_into().unwrap()), + }; + Ok(header) + } +} + +/// A [Coding Independent Code Point](https://en.wikipedia.org/wiki/Coding-independent_code_points). +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct CicpProfile { + pub color_primaries: CicpColorPrimaries, + pub transfer_characteristics: TransferCharacteristics, + pub matrix_coefficients: MatrixCoefficients, + pub full_range: bool, +} + +#[derive(Debug, Clone)] +pub struct LocalizableString { + /// An ISO 639-1 value is expected; any text w. more than two symbols will be truncated + pub language: String, + /// An ISO 3166-1 value is expected; any text w. more than two symbols will be truncated + pub country: String, + pub value: String, +} + +impl LocalizableString { + /// Creates new localizable string + /// + /// # Arguments + /// + /// * `language`: an ISO 639-1 value is expected, any text more than 2 symbols will be truncated + /// * `country`: an ISO 3166-1 value is expected, any text more than 2 symbols will be truncated + /// * `value`: String value + /// + pub fn new(language: String, country: String, value: String) -> Self { + Self { + language, + country, + value, + } + } +} + +#[derive(Debug, Clone)] +pub struct DescriptionString { + pub ascii_string: String, + pub unicode_language_code: u32, + pub unicode_string: String, + pub script_code_code: i8, + pub mac_string: String, +} + +#[derive(Debug, Clone)] +pub enum ProfileText { + PlainString(String), + Localizable(Vec), + Description(DescriptionString), +} + +impl ProfileText { + pub(crate) fn has_values(&self) -> bool { + match self { + ProfileText::PlainString(_) => true, + ProfileText::Localizable(lc) => !lc.is_empty(), + ProfileText::Description(_) => true, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum StandardObserver { + D50, + D65, + Unknown, +} + +impl From for StandardObserver { + fn from(value: u32) -> Self { + if value == 1 { + return StandardObserver::D50; + } else if value == 2 { + return StandardObserver::D65; + } + StandardObserver::Unknown + } +} + +impl From for u32 { + fn from(value: StandardObserver) -> Self { + match value { + StandardObserver::D50 => 1, + StandardObserver::D65 => 2, + StandardObserver::Unknown => 0, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct ViewingConditions { + pub illuminant: Xyz, + pub surround: Xyz, + pub observer: StandardObserver, +} + +#[derive(Debug, Clone, Copy)] +pub enum MeasurementGeometry { + Unknown, + /// 0°:45° or 45°:0° + D45to45, + /// 0°:d or d:0° + D0to0, +} + +impl From for MeasurementGeometry { + fn from(value: u32) -> Self { + if value == 1 { + Self::D45to45 + } else if value == 2 { + Self::D0to0 + } else { + Self::Unknown + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum StandardIlluminant { + Unknown, + D50, + D65, + D93, + F2, + D55, + A, + EquiPower, + F8, +} + +impl From for StandardIlluminant { + fn from(value: u32) -> Self { + match value { + 1 => StandardIlluminant::D50, + 2 => StandardIlluminant::D65, + 3 => StandardIlluminant::D93, + 4 => StandardIlluminant::F2, + 5 => StandardIlluminant::D55, + 6 => StandardIlluminant::A, + 7 => StandardIlluminant::EquiPower, + 8 => StandardIlluminant::F8, + _ => Self::Unknown, + } + } +} + +impl From for u32 { + fn from(value: StandardIlluminant) -> Self { + match value { + StandardIlluminant::Unknown => 0u32, + StandardIlluminant::D50 => 1u32, + StandardIlluminant::D65 => 2u32, + StandardIlluminant::D93 => 3, + StandardIlluminant::F2 => 4, + StandardIlluminant::D55 => 5, + StandardIlluminant::A => 6, + StandardIlluminant::EquiPower => 7, + StandardIlluminant::F8 => 8, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Measurement { + pub observer: StandardObserver, + pub backing: Xyz, + pub geometry: MeasurementGeometry, + pub flare: f32, + pub illuminant: StandardIlluminant, +} + +/// ICC Profile representation +#[repr(C)] +#[derive(Debug, Clone, Default)] +pub struct ColorProfile { + pub pcs: DataColorSpace, + pub color_space: DataColorSpace, + pub profile_class: ProfileClass, + pub rendering_intent: RenderingIntent, + pub red_colorant: Xyzd, + pub green_colorant: Xyzd, + pub blue_colorant: Xyzd, + pub white_point: Xyzd, + pub black_point: Option, + pub media_white_point: Option, + pub luminance: Option, + pub measurement: Option, + pub red_trc: Option, + pub green_trc: Option, + pub blue_trc: Option, + pub gray_trc: Option, + pub cicp: Option, + pub chromatic_adaptation: Option, + pub lut_a_to_b_perceptual: Option, + pub lut_a_to_b_colorimetric: Option, + pub lut_a_to_b_saturation: Option, + pub lut_b_to_a_perceptual: Option, + pub lut_b_to_a_colorimetric: Option, + pub lut_b_to_a_saturation: Option, + pub gamut: Option, + pub copyright: Option, + pub description: Option, + pub device_manufacturer: Option, + pub device_model: Option, + pub char_target: Option, + pub viewing_conditions: Option, + pub viewing_conditions_description: Option, + pub technology: Option, + pub calibration_date: Option, + /// Version for internal and viewing purposes only. + /// On encoding added value to profile will always be V4. + pub(crate) version_internal: ProfileVersion, +} + +#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Hash)] +pub struct ParsingOptions { + // Maximum allowed profile size in bytes + pub max_profile_size: usize, + // Maximum allowed CLUT size in bytes + pub max_allowed_clut_size: usize, + // Maximum allowed TRC size in elements count + pub max_allowed_trc_size: usize, +} + +impl Default for ParsingOptions { + fn default() -> Self { + Self { + max_profile_size: MAX_PROFILE_SIZE, + max_allowed_clut_size: 10_000_000, + max_allowed_trc_size: 40_000, + } + } +} + +impl ColorProfile { + /// Returns profile version + pub fn version(&self) -> ProfileVersion { + self.version_internal + } + + pub fn new_from_slice(slice: &[u8]) -> Result { + Self::new_from_slice_with_options(slice, Default::default()) + } + + pub fn new_from_slice_with_options( + slice: &[u8], + options: ParsingOptions, + ) -> Result { + let header = ProfileHeader::new_from_slice(slice)?; + let tags_count = header.tag_count as usize; + if slice.len() >= options.max_profile_size { + return Err(CmsError::InvalidProfile); + } + let tags_end = tags_count + .safe_mul(TAG_SIZE)? + .safe_add(size_of::())?; + if slice.len() < tags_end { + return Err(CmsError::InvalidProfile); + } + let tags_slice = &slice[size_of::()..tags_end]; + let mut profile = ColorProfile { + rendering_intent: header.rendering_intent, + pcs: header.pcs, + profile_class: header.profile_class, + color_space: header.data_color_space, + white_point: header.illuminant.to_xyzd(), + version_internal: header.version, + ..Default::default() + }; + let color_space = profile.color_space; + for tag in tags_slice.chunks_exact(TAG_SIZE) { + let tag_value = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let tag_entry = u32::from_be_bytes([tag[4], tag[5], tag[6], tag[7]]); + let tag_size = u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]) as usize; + // Just ignore unknown tags + if let Ok(tag) = Tag::try_from(tag_value) { + match tag { + Tag::RedXyz => { + if color_space == DataColorSpace::Rgb { + profile.red_colorant = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size)?; + } + } + Tag::GreenXyz => { + if color_space == DataColorSpace::Rgb { + profile.green_colorant = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size)?; + } + } + Tag::BlueXyz => { + if color_space == DataColorSpace::Rgb { + profile.blue_colorant = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size)?; + } + } + Tag::RedToneReproduction => { + if color_space == DataColorSpace::Rgb { + profile.red_trc = Self::read_trc_tag_s( + slice, + tag_entry as usize, + tag_size, + &options, + )?; + } + } + Tag::GreenToneReproduction => { + if color_space == DataColorSpace::Rgb { + profile.green_trc = Self::read_trc_tag_s( + slice, + tag_entry as usize, + tag_size, + &options, + )?; + } + } + Tag::BlueToneReproduction => { + if color_space == DataColorSpace::Rgb { + profile.blue_trc = Self::read_trc_tag_s( + slice, + tag_entry as usize, + tag_size, + &options, + )?; + } + } + Tag::GreyToneReproduction => { + if color_space == DataColorSpace::Gray { + profile.gray_trc = Self::read_trc_tag_s( + slice, + tag_entry as usize, + tag_size, + &options, + )?; + } + } + Tag::MediaWhitePoint => { + profile.media_white_point = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size).map(Some)?; + } + Tag::Luminance => { + profile.luminance = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size).map(Some)?; + } + Tag::Measurement => { + profile.measurement = + Self::read_meas_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::CodeIndependentPoints => { + // This tag may be present when the data colour space in the profile header is RGB, YCbCr, or XYZ, and the + // profile class in the profile header is Input or Display. The tag shall not be present for other data colour spaces + // or profile classes indicated in the profile header. + if (profile.profile_class == ProfileClass::InputDevice + || profile.profile_class == ProfileClass::DisplayDevice) + && (profile.color_space == DataColorSpace::Rgb + || profile.color_space == DataColorSpace::YCbr + || profile.color_space == DataColorSpace::Xyz) + { + profile.cicp = + Self::read_cicp_tag(slice, tag_entry as usize, tag_size)?; + } + } + Tag::ChromaticAdaptation => { + profile.chromatic_adaptation = + Self::read_chad_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::BlackPoint => { + profile.black_point = + Self::read_xyz_tag(slice, tag_entry as usize, tag_size).map(Some)? + } + Tag::DeviceToPcsLutPerceptual => { + profile.lut_a_to_b_perceptual = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::DeviceToPcsLutColorimetric => { + profile.lut_a_to_b_colorimetric = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::DeviceToPcsLutSaturation => { + profile.lut_a_to_b_saturation = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::PcsToDeviceLutPerceptual => { + profile.lut_b_to_a_perceptual = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::PcsToDeviceLutColorimetric => { + profile.lut_b_to_a_colorimetric = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::PcsToDeviceLutSaturation => { + profile.lut_b_to_a_saturation = + Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::Gamut => { + profile.gamut = Self::read_lut_tag(slice, tag_entry, tag_size, &options)?; + } + Tag::Copyright => { + profile.copyright = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::ProfileDescription => { + profile.description = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::ViewingConditionsDescription => { + profile.viewing_conditions_description = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::DeviceModel => { + profile.device_model = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::DeviceManufacturer => { + profile.device_manufacturer = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::CharTarget => { + profile.char_target = + Self::read_string_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::Chromaticity => {} + Tag::ObserverConditions => { + profile.viewing_conditions = + Self::read_viewing_conditions(slice, tag_entry as usize, tag_size)?; + } + Tag::Technology => { + profile.technology = + Self::read_tech_tag(slice, tag_entry as usize, tag_size)?; + } + Tag::CalibrationDateTime => { + profile.calibration_date = + Self::read_date_time_tag(slice, tag_entry as usize, tag_size)?; + } + } + } + } + + Ok(profile) + } +} + +impl ColorProfile { + #[inline] + pub fn colorant_matrix(&self) -> Matrix3d { + Matrix3d { + v: [ + [ + self.red_colorant.x, + self.green_colorant.x, + self.blue_colorant.x, + ], + [ + self.red_colorant.y, + self.green_colorant.y, + self.blue_colorant.y, + ], + [ + self.red_colorant.z, + self.green_colorant.z, + self.blue_colorant.z, + ], + ], + } + } + + /// Computes colorants matrix. Returns not transposed matrix. + /// + /// To work on `const` context this method does have restrictions. + /// If invalid values were provided it may return invalid matrix or NaNs. + pub const fn colorants_matrix(white_point: XyY, primaries: ColorPrimaries) -> Matrix3d { + let red_xyz = primaries.red.to_xyzd(); + let green_xyz = primaries.green.to_xyzd(); + let blue_xyz = primaries.blue.to_xyzd(); + + let xyz_matrix = Matrix3d { + v: [ + [red_xyz.x, green_xyz.x, blue_xyz.x], + [red_xyz.y, green_xyz.y, blue_xyz.y], + [red_xyz.z, green_xyz.z, blue_xyz.z], + ], + }; + let colorants = ColorProfile::rgb_to_xyz_d(xyz_matrix, white_point.to_xyzd()); + adapt_to_d50_d(colorants, white_point) + } + + /// Updates RGB triple colorimetry from 3 [Chromaticity] and white point + pub const fn update_rgb_colorimetry(&mut self, white_point: XyY, primaries: ColorPrimaries) { + let red_xyz = primaries.red.to_xyzd(); + let green_xyz = primaries.green.to_xyzd(); + let blue_xyz = primaries.blue.to_xyzd(); + + self.chromatic_adaptation = Some(BRADFORD_D); + self.update_rgb_colorimetry_triplet(white_point, red_xyz, green_xyz, blue_xyz) + } + + /// Updates RGB triple colorimetry from 3 [Xyzd] and white point + /// + /// To work on `const` context this method does have restrictions. + /// If invalid values were provided it may return invalid matrix or NaNs. + pub const fn update_rgb_colorimetry_triplet( + &mut self, + white_point: XyY, + red_xyz: Xyzd, + green_xyz: Xyzd, + blue_xyz: Xyzd, + ) { + let xyz_matrix = Matrix3d { + v: [ + [red_xyz.x, green_xyz.x, blue_xyz.x], + [red_xyz.y, green_xyz.y, blue_xyz.y], + [red_xyz.z, green_xyz.z, blue_xyz.z], + ], + }; + let colorants = ColorProfile::rgb_to_xyz_d(xyz_matrix, white_point.to_xyzd()); + let colorants = adapt_to_d50_d(colorants, white_point); + + self.update_colorants(colorants); + } + + pub(crate) const fn update_colorants(&mut self, colorants: Matrix3d) { + // note: there's a transpose type of operation going on here + self.red_colorant.x = colorants.v[0][0]; + self.red_colorant.y = colorants.v[1][0]; + self.red_colorant.z = colorants.v[2][0]; + self.green_colorant.x = colorants.v[0][1]; + self.green_colorant.y = colorants.v[1][1]; + self.green_colorant.z = colorants.v[2][1]; + self.blue_colorant.x = colorants.v[0][2]; + self.blue_colorant.y = colorants.v[1][2]; + self.blue_colorant.z = colorants.v[2][2]; + } + + /// Updates RGB triple colorimetry from CICP + pub fn update_rgb_colorimetry_from_cicp(&mut self, cicp: CicpProfile) -> bool { + self.cicp = Some(cicp); + if !cicp.color_primaries.has_chromaticity() + || !cicp.transfer_characteristics.has_transfer_curve() + { + return false; + } + let primaries_xy: ColorPrimaries = match cicp.color_primaries.try_into() { + Ok(primaries) => primaries, + Err(_) => return false, + }; + let white_point: Chromaticity = match cicp.color_primaries.white_point() { + Ok(v) => v, + Err(_) => return false, + }; + self.update_rgb_colorimetry(white_point.to_xyyb(), primaries_xy); + + let red_trc: ToneReprCurve = match cicp.transfer_characteristics.try_into() { + Ok(trc) => trc, + Err(_) => return false, + }; + self.green_trc = Some(red_trc.clone()); + self.blue_trc = Some(red_trc.clone()); + self.red_trc = Some(red_trc); + false + } + + pub const fn rgb_to_xyz(&self, xyz_matrix: Matrix3f, wp: Xyz) -> Matrix3f { + let xyz_inverse = xyz_matrix.inverse(); + let s = xyz_inverse.mul_vector(wp.to_vector()); + let mut v = xyz_matrix.mul_row_vector::<0>(s); + v = v.mul_row_vector::<1>(s); + v.mul_row_vector::<2>(s) + } + + ///TODO: make primary instead of [rgb_to_xyz] in the next major version + pub(crate) const fn rgb_to_xyz_static(xyz_matrix: Matrix3f, wp: Xyz) -> Matrix3f { + let xyz_inverse = xyz_matrix.inverse(); + let s = xyz_inverse.mul_vector(wp.to_vector()); + let mut v = xyz_matrix.mul_row_vector::<0>(s); + v = v.mul_row_vector::<1>(s); + v.mul_row_vector::<2>(s) + } + + /// If Primaries is invalid will return invalid matrix on const context. + /// This assumes not transposed matrix and returns not transposed matrix. + pub const fn rgb_to_xyz_d(xyz_matrix: Matrix3d, wp: Xyzd) -> Matrix3d { + let xyz_inverse = xyz_matrix.inverse(); + let s = xyz_inverse.mul_vector(wp.to_vector_d()); + let mut v = xyz_matrix.mul_row_vector::<0>(s); + v = v.mul_row_vector::<1>(s); + v = v.mul_row_vector::<2>(s); + v + } + + pub fn rgb_to_xyz_matrix(&self) -> Matrix3d { + let xyz_matrix = self.colorant_matrix(); + let white_point = Chromaticity::D50.to_xyzd(); + ColorProfile::rgb_to_xyz_d(xyz_matrix, white_point) + } + + /// Computes transform matrix RGB -> XYZ -> RGB + /// Current profile is used as source, other as destination + pub fn transform_matrix(&self, dest: &ColorProfile) -> Matrix3d { + let source = self.rgb_to_xyz_matrix(); + let dst = dest.rgb_to_xyz_matrix(); + let dest_inverse = dst.inverse(); + dest_inverse.mat_mul(source) + } + + /// Returns volume of colors stored in profile + pub fn profile_volume(&self) -> Option { + let red_prim = self.red_colorant; + let green_prim = self.green_colorant; + let blue_prim = self.blue_colorant; + let tetrahedral_vertices = Matrix3d { + v: [ + [red_prim.x, red_prim.y, red_prim.z], + [green_prim.x, green_prim.y, green_prim.z], + [blue_prim.x, blue_prim.y, blue_prim.z], + ], + }; + let det = tetrahedral_vertices.determinant()?; + Some((det / 6.0f64) as f32) + } + + pub(crate) fn has_device_to_pcs_lut(&self) -> bool { + self.lut_a_to_b_perceptual.is_some() + || self.lut_a_to_b_saturation.is_some() + || self.lut_a_to_b_colorimetric.is_some() + } + + pub(crate) fn has_pcs_to_device_lut(&self) -> bool { + self.lut_b_to_a_perceptual.is_some() + || self.lut_b_to_a_saturation.is_some() + || self.lut_b_to_a_colorimetric.is_some() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs; + + #[test] + fn test_gray() { + if let Ok(gray_icc) = fs::read("./assets/Generic Gray Gamma 2.2 Profile.icc") { + let f_p = ColorProfile::new_from_slice(&gray_icc).unwrap(); + assert!(f_p.gray_trc.is_some()); + } + } + + #[test] + fn test_perceptual() { + if let Ok(srgb_perceptual_icc) = fs::read("./assets/srgb_perceptual.icc") { + let f_p = ColorProfile::new_from_slice(&srgb_perceptual_icc).unwrap(); + assert_eq!(f_p.pcs, DataColorSpace::Lab); + assert_eq!(f_p.color_space, DataColorSpace::Rgb); + assert_eq!(f_p.version(), ProfileVersion::V4_2); + assert!(f_p.lut_a_to_b_perceptual.is_some()); + assert!(f_p.lut_b_to_a_perceptual.is_some()); + } + } + + #[test] + fn test_us_swop_coated() { + if let Ok(us_swop_coated) = fs::read("./assets/us_swop_coated.icc") { + let f_p = ColorProfile::new_from_slice(&us_swop_coated).unwrap(); + assert_eq!(f_p.pcs, DataColorSpace::Lab); + assert_eq!(f_p.color_space, DataColorSpace::Cmyk); + assert_eq!(f_p.version(), ProfileVersion::V2_0); + + assert!(f_p.lut_a_to_b_perceptual.is_some()); + assert!(f_p.lut_b_to_a_perceptual.is_some()); + + assert!(f_p.lut_a_to_b_colorimetric.is_some()); + assert!(f_p.lut_b_to_a_colorimetric.is_some()); + + assert!(f_p.gamut.is_some()); + + assert!(f_p.copyright.is_some()); + assert!(f_p.description.is_some()); + } + } + + #[test] + fn test_matrix_shaper() { + if let Ok(matrix_shaper) = fs::read("./assets/Display P3.icc") { + let f_p = ColorProfile::new_from_slice(&matrix_shaper).unwrap(); + assert_eq!(f_p.pcs, DataColorSpace::Xyz); + assert_eq!(f_p.color_space, DataColorSpace::Rgb); + assert_eq!(f_p.version(), ProfileVersion::V4_0); + + assert!(f_p.red_trc.is_some()); + assert!(f_p.blue_trc.is_some()); + assert!(f_p.green_trc.is_some()); + + assert_ne!(f_p.red_colorant, Xyzd::default()); + assert_ne!(f_p.blue_colorant, Xyzd::default()); + assert_ne!(f_p.green_colorant, Xyzd::default()); + + assert!(f_p.copyright.is_some()); + assert!(f_p.description.is_some()); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/reader.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1004 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::err::try_vec; +use crate::helpers::{read_matrix_3d, read_vector_3d}; +use crate::profile::LutDataType; +use crate::safe_math::{SafeAdd, SafeMul, SafePowi}; +use crate::tag::{TAG_SIZE, TagTypeDefinition}; +use crate::{ + CicpColorPrimaries, CicpProfile, CmsError, ColorDateTime, ColorProfile, DescriptionString, + LocalizableString, LutMultidimensionalType, LutStore, LutType, LutWarehouse, Matrix3d, + Matrix3f, MatrixCoefficients, Measurement, MeasurementGeometry, ParsingOptions, ProfileText, + StandardIlluminant, StandardObserver, TechnologySignatures, ToneReprCurve, + TransferCharacteristics, Vector3d, ViewingConditions, Xyz, Xyzd, +}; + +/// Produces the nearest float to `a` with a maximum error of 1/1024 which +/// happens for large values like 0x40000040. +#[inline] +pub(crate) const fn s15_fixed16_number_to_float(a: i32) -> f32 { + a as f32 / 65536. +} + +#[inline] +pub(crate) const fn s15_fixed16_number_to_double(a: i32) -> f64 { + a as f64 / 65536. +} + +#[inline] +pub(crate) const fn uint16_number_to_float(a: u32) -> f32 { + a as f32 / 65536. +} + +#[inline] +pub(crate) const fn uint16_number_to_float_fast(a: u32) -> f32 { + a as f32 * (1. / 65536.) +} + +// #[inline] +// pub(crate) fn uint8_number_to_float(a: u8) -> f32 { +// a as f32 / 255.0 +// } + +#[inline] +pub(crate) fn uint8_number_to_float_fast(a: u8) -> f32 { + a as f32 * (1. / 255.0) +} + +fn utf16be_to_utf16(slice: &[u8]) -> Result, CmsError> { + let mut vec = try_vec![0u16; slice.len() / 2]; + for (dst, chunk) in vec.iter_mut().zip(slice.chunks_exact(2)) { + *dst = u16::from_be_bytes([chunk[0], chunk[1]]); + } + Ok(vec) +} + +impl ColorProfile { + #[inline] + pub(crate) fn read_lut_type( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result { + let tag_size = if tag_size == 0 { TAG_SIZE } else { tag_size }; + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 48 { + return Err(CmsError::InvalidProfile); + } + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + LutType::try_from(tag_type) + } + + #[inline] + pub(crate) fn read_viewing_conditions( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + if tag_size < 36 { + return Ok(None); + } + if slice.len() < entry.safe_add(36)? { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry.safe_add(36)?]; + let tag_type = + TagTypeDefinition::from(u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]])); + // Ignore unknown + if tag_type != TagTypeDefinition::DefViewingConditions { + return Ok(None); + } + let illuminant_x = i32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]); + let illuminant_y = i32::from_be_bytes([tag[12], tag[13], tag[14], tag[15]]); + let illuminant_z = i32::from_be_bytes([tag[16], tag[17], tag[18], tag[19]]); + + let surround_x = i32::from_be_bytes([tag[20], tag[21], tag[22], tag[23]]); + let surround_y = i32::from_be_bytes([tag[24], tag[25], tag[26], tag[27]]); + let surround_z = i32::from_be_bytes([tag[28], tag[29], tag[30], tag[31]]); + + let illuminant_type = u32::from_be_bytes([tag[32], tag[33], tag[34], tag[35]]); + + let illuminant = Xyz::new( + s15_fixed16_number_to_float(illuminant_x), + s15_fixed16_number_to_float(illuminant_y), + s15_fixed16_number_to_float(illuminant_z), + ); + + let surround = Xyz::new( + s15_fixed16_number_to_float(surround_x), + s15_fixed16_number_to_float(surround_y), + s15_fixed16_number_to_float(surround_z), + ); + + let observer = StandardObserver::from(illuminant_type); + + Ok(Some(ViewingConditions { + illuminant, + surround, + observer, + })) + } + + pub(crate) fn read_string_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + let tag_size = if tag_size == 0 { TAG_SIZE } else { tag_size }; + if tag_size < 4 { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 8 { + return Ok(None); + } + let tag_type = + TagTypeDefinition::from(u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]])); + // Ignore unknown + if tag_type == TagTypeDefinition::Text { + let sliced_from_to_end = &tag[8..tag.len()]; + let str = String::from_utf8_lossy(sliced_from_to_end); + return Ok(Some(ProfileText::PlainString(str.to_string()))); + } else if tag_type == TagTypeDefinition::MultiLocalizedUnicode { + if tag.len() < 28 { + return Err(CmsError::InvalidProfile); + } + // let record_size = u32::from_be_bytes([tag[12], tag[13], tag[14], tag[15]]) as usize; + // // Record size is reserved to be 12. + // if record_size != 12 { + // return Err(CmsError::InvalidIcc); + // } + let records_count = u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]) as usize; + let primary_language_code = String::from_utf8_lossy(&[tag[16], tag[17]]).to_string(); + let primary_country_code = String::from_utf8_lossy(&[tag[18], tag[19]]).to_string(); + let first_string_record_length = + u32::from_be_bytes([tag[20], tag[21], tag[22], tag[23]]) as usize; + let first_record_offset = + u32::from_be_bytes([tag[24], tag[25], tag[26], tag[27]]) as usize; + + if tag.len() < first_record_offset.safe_add(first_string_record_length)? { + return Ok(None); + } + + let resliced = + &tag[first_record_offset..first_record_offset + first_string_record_length]; + let cvt = utf16be_to_utf16(resliced)?; + let string_record = String::from_utf16_lossy(&cvt); + + let mut records = vec![LocalizableString { + language: primary_language_code, + country: primary_country_code, + value: string_record, + }]; + + for record in 1..records_count { + // Localizable header must be at least 12 bytes + let localizable_header_offset = if record == 1 { + 28 + } else { + 28 + 12 * (record - 1) + }; + if tag.len() < localizable_header_offset + 12 { + return Err(CmsError::InvalidProfile); + } + let choked = &tag[localizable_header_offset..localizable_header_offset + 12]; + + let language_code = String::from_utf8_lossy(&[choked[0], choked[1]]).to_string(); + let country_code = String::from_utf8_lossy(&[choked[2], choked[3]]).to_string(); + let record_length = + u32::from_be_bytes([choked[4], choked[5], choked[6], choked[7]]) as usize; + let string_offset = + u32::from_be_bytes([choked[8], choked[9], choked[10], choked[11]]) as usize; + + if tag.len() < string_offset.safe_add(record_length)? { + return Ok(None); + } + let resliced = &tag[string_offset..string_offset + record_length]; + let cvt = utf16be_to_utf16(resliced)?; + let string_record = String::from_utf16_lossy(&cvt); + records.push(LocalizableString { + country: country_code, + language: language_code, + value: string_record, + }); + } + + return Ok(Some(ProfileText::Localizable(records))); + } else if tag_type == TagTypeDefinition::Description { + if tag.len() < 12 { + return Err(CmsError::InvalidProfile); + } + let ascii_length = u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]) as usize; + if tag.len() < 12.safe_add(ascii_length)? { + return Err(CmsError::InvalidProfile); + } + let sliced = &tag[12..12 + ascii_length]; + let ascii_string = String::from_utf8_lossy(sliced).to_string(); + + let mut last_position = 12 + ascii_length; + if tag.len() < last_position + 8 { + return Err(CmsError::InvalidProfile); + } + let uc = &tag[last_position..last_position + 8]; + let unicode_code = u32::from_be_bytes([uc[0], uc[1], uc[2], uc[3]]); + let unicode_length = u32::from_be_bytes([uc[4], uc[5], uc[6], uc[7]]) as usize * 2; + if tag.len() < unicode_length.safe_add(8)?.safe_add(last_position)? { + return Ok(None); + } + + last_position += 8; + let uc = &tag[last_position..last_position + unicode_length]; + let wc = utf16be_to_utf16(uc)?; + let unicode_string = String::from_utf16_lossy(&wc).to_string(); + + // last_position += unicode_length; + // + // if tag.len() < last_position + 2 { + // return Err(CmsError::InvalidIcc); + // } + + // let uc = &tag[last_position..last_position + 2]; + // let script_code = uc[0]; + // let mac_length = uc[1] as usize; + // last_position += 2; + // if tag.len() < last_position + mac_length { + // return Err(CmsError::InvalidIcc); + // } + // + // let uc = &tag[last_position..last_position + unicode_length]; + // let wc = utf16be_to_utf16(uc); + // let mac_string = String::from_utf16_lossy(&wc).to_string(); + + return Ok(Some(ProfileText::Description(DescriptionString { + ascii_string, + unicode_language_code: unicode_code, + unicode_string, + mac_string: "".to_string(), + script_code_code: -1, + }))); + } + Ok(None) + } + + #[inline] + fn read_lut_table_f32(table: &[u8], lut_type: LutType) -> Result { + if lut_type == LutType::Lut16 { + let mut clut = try_vec![0u16; table.len() / 2]; + for (src, dst) in table.chunks_exact(2).zip(clut.iter_mut()) { + *dst = u16::from_be_bytes([src[0], src[1]]); + } + Ok(LutStore::Store16(clut)) + } else if lut_type == LutType::Lut8 { + let mut clut = try_vec![0u8; table.len()]; + for (&src, dst) in table.iter().zip(clut.iter_mut()) { + *dst = src; + } + Ok(LutStore::Store8(clut)) + } else { + unreachable!("This should never happen, report to https://github.com/awxkee/moxcms") + } + } + + #[inline] + fn read_nested_tone_curves( + slice: &[u8], + offset: usize, + length: usize, + options: &ParsingOptions, + ) -> Result>, CmsError> { + let mut curve_offset: usize = offset; + let mut curves = Vec::new(); + for _ in 0..length { + if slice.len() < curve_offset.safe_add(12)? { + return Err(CmsError::InvalidProfile); + } + let mut tag_size = 0usize; + let new_curve = Self::read_trc_tag(slice, curve_offset, 0, &mut tag_size, options)?; + match new_curve { + None => return Err(CmsError::InvalidProfile), + Some(curve) => curves.push(curve), + } + curve_offset += tag_size; + // 4 byte aligned + if curve_offset % 4 != 0 { + curve_offset += 4 - curve_offset % 4; + } + } + Ok(Some(curves)) + } + + #[inline] + pub(crate) fn read_lut_abm_type( + slice: &[u8], + entry: usize, + tag_size: usize, + to_pcs: bool, + options: &ParsingOptions, + ) -> Result, CmsError> { + if tag_size < 48 { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 48 { + return Err(CmsError::InvalidProfile); + } + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let tag_type_definition = TagTypeDefinition::from(tag_type); + if tag_type_definition != TagTypeDefinition::MabLut + && tag_type_definition != TagTypeDefinition::MbaLut + { + return Ok(None); + } + let in_channels = tag[8]; + let out_channels = tag[9]; + if in_channels > 4 && out_channels > 4 { + return Ok(None); + } + let a_curve_offset = u32::from_be_bytes([tag[28], tag[29], tag[30], tag[31]]) as usize; + let clut_offset = u32::from_be_bytes([tag[24], tag[25], tag[26], tag[27]]) as usize; + let m_curve_offset = u32::from_be_bytes([tag[20], tag[21], tag[22], tag[23]]) as usize; + let matrix_offset = u32::from_be_bytes([tag[16], tag[17], tag[18], tag[19]]) as usize; + let b_curve_offset = u32::from_be_bytes([tag[12], tag[13], tag[14], tag[15]]) as usize; + + let transform: Matrix3d; + let bias: Vector3d; + if matrix_offset != 0 { + let matrix_end = matrix_offset.safe_add(12 * 4)?; + if tag.len() < matrix_end { + return Err(CmsError::InvalidProfile); + } + + let m_tag = &tag[matrix_offset..matrix_end]; + + bias = read_vector_3d(&m_tag[36..48])?; + transform = read_matrix_3d(m_tag)?; + } else { + transform = Matrix3d::IDENTITY; + bias = Vector3d::default(); + } + + let mut grid_points: [u8; 16] = [0; 16]; + + let clut_table: Option = + if clut_offset != 0 { + // Check if CLUT formed correctly + if clut_offset.safe_add(20)? > tag.len() { + return Err(CmsError::InvalidProfile); + } + + let clut_sizes_slice = &tag[clut_offset..clut_offset.safe_add(16)?]; + for (&s, v) in clut_sizes_slice.iter().zip(grid_points.iter_mut()) { + *v = s; + } + + let mut clut_size = 1u32; + for &i in grid_points.iter().take(in_channels as usize) { + clut_size = clut_size.safe_mul(i as u32)?; + } + clut_size = clut_size.safe_mul(out_channels as u32)?; + + if clut_size == 0 { + return Err(CmsError::IncorrectlyFormedLut( + "Clut size was zero when it shouldn't".to_string(), + )); + } + + if clut_size > 10_000_000 { + return Err(CmsError::IncorrectlyFormedLut( + "Clut size exceeded 10_000_000 points what is too big".to_string(), + )); + } + + // check LUT dimensions + let mut grid_stride: usize = 1usize; + let mut last_index: usize = 0; + for &dim in grid_points.iter().take(in_channels as usize).rev() { + let dim_usize = dim as usize; + if dim_usize == 0 { + return Err(CmsError::IncorrectlyFormedLut( + "One of grid dimensions is zero".to_string(), + )); + } + let l = match dim_usize + .checked_sub(1) + .ok_or(CmsError::OverflowingError)? + .safe_mul(grid_stride) + .and_then(|x| x.safe_add(last_index)) + { + Ok(v) => v, + Err(_) => { + return Err(CmsError::IncorrectlyFormedLut( + "Pointer size overflow on LUT dimensions".to_string(), + )); + } + }; + last_index = l; + + // Multiply stride by next dimension (check for overflow) + grid_stride = grid_stride.checked_mul(dim_usize).ok_or( + CmsError::IncorrectlyFormedLut("Overflow on grid dimensions".to_string()), + )?; + } + + last_index = last_index.checked_mul(out_channels as usize).ok_or( + CmsError::IncorrectlyFormedLut("Overflow on grid dimensions".to_string()), + )?; + if last_index >= clut_size as usize { + return Err(CmsError::IncorrectlyFormedLut(format!( + "Clut size should be at least {last_index}, but it was {last_index}" + ))); + } + + let clut_offset20 = clut_offset.safe_add(20)?; + + let clut_header = &tag[clut_offset..clut_offset20]; + let entry_size = clut_header[16]; + if entry_size != 1 && entry_size != 2 { + return Err(CmsError::InvalidProfile); + } + + let clut_end = + clut_offset20.safe_add(clut_size.safe_mul(entry_size as u32)? as usize)?; + + if tag.len() < clut_end { + return Err(CmsError::InvalidProfile); + } + + let shaped_clut_table = &tag[clut_offset20..clut_end]; + Some(Self::read_lut_table_f32( + shaped_clut_table, + if entry_size == 1 { + LutType::Lut8 + } else { + LutType::Lut16 + }, + )?) + } else { + None + }; + + let a_curves = if a_curve_offset == 0 { + Vec::new() + } else { + Self::read_nested_tone_curves( + tag, + a_curve_offset, + if to_pcs { + in_channels as usize + } else { + out_channels as usize + }, + options, + )? + .ok_or(CmsError::InvalidProfile)? + }; + + let m_curves = if m_curve_offset == 0 { + Vec::new() + } else { + Self::read_nested_tone_curves( + tag, + m_curve_offset, + if to_pcs { + out_channels as usize + } else { + in_channels as usize + }, + options, + )? + .ok_or(CmsError::InvalidProfile)? + }; + + let b_curves = if b_curve_offset == 0 { + Vec::new() + } else { + Self::read_nested_tone_curves( + tag, + b_curve_offset, + if to_pcs { + out_channels as usize + } else { + in_channels as usize + }, + options, + )? + .ok_or(CmsError::InvalidProfile)? + }; + + let wh = LutWarehouse::Multidimensional(LutMultidimensionalType { + num_input_channels: in_channels, + num_output_channels: out_channels, + matrix: transform, + clut: clut_table, + a_curves, + b_curves, + m_curves, + grid_points, + bias, + }); + Ok(Some(wh)) + } + + #[inline] + pub(crate) fn read_lut_a_to_b_type( + slice: &[u8], + entry: usize, + tag_size: usize, + parsing_options: &ParsingOptions, + ) -> Result, CmsError> { + if tag_size < 48 { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 48 { + return Err(CmsError::InvalidProfile); + } + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let lut_type = LutType::try_from(tag_type)?; + assert!(lut_type == LutType::Lut8 || lut_type == LutType::Lut16); + + if lut_type == LutType::Lut16 && tag.len() < 52 { + return Err(CmsError::InvalidProfile); + } + + let num_input_table_entries: u16 = match lut_type { + LutType::Lut8 => 256, + LutType::Lut16 => u16::from_be_bytes([tag[48], tag[49]]), + _ => unreachable!(), + }; + let num_output_table_entries: u16 = match lut_type { + LutType::Lut8 => 256, + LutType::Lut16 => u16::from_be_bytes([tag[50], tag[51]]), + _ => unreachable!(), + }; + + if !(2..=4096).contains(&num_input_table_entries) + || !(2..=4096).contains(&num_output_table_entries) + { + return Err(CmsError::InvalidProfile); + } + + let input_offset: usize = match lut_type { + LutType::Lut8 => 48, + LutType::Lut16 => 52, + _ => unreachable!(), + }; + let entry_size: usize = match lut_type { + LutType::Lut8 => 1, + LutType::Lut16 => 2, + _ => unreachable!(), + }; + + let in_chan = tag[8]; + let out_chan = tag[9]; + let is_3_to_4 = in_chan == 3 || out_chan == 4; + let is_4_to_3 = in_chan == 4 || out_chan == 3; + if !is_3_to_4 && !is_4_to_3 { + return Err(CmsError::InvalidProfile); + } + let grid_points = tag[10]; + let clut_size = (grid_points as u32).safe_powi(in_chan as u32)? as usize; + + if !(1..=parsing_options.max_allowed_clut_size).contains(&clut_size) { + return Err(CmsError::InvalidProfile); + } + + assert!(tag.len() >= 48); + + let transform = read_matrix_3d(&tag[12..48])?; + + let lut_input_size = num_input_table_entries.safe_mul(in_chan as u16)? as usize; + + let linearization_table_end = lut_input_size + .safe_mul(entry_size)? + .safe_add(input_offset)?; + if tag.len() < linearization_table_end { + return Err(CmsError::InvalidProfile); + } + let shaped_input_table = &tag[input_offset..linearization_table_end]; + let linearization_table = Self::read_lut_table_f32(shaped_input_table, lut_type)?; + + let clut_offset = linearization_table_end; + + let clut_data_size = clut_size + .safe_mul(out_chan as usize)? + .safe_mul(entry_size)?; + + if tag.len() < clut_offset.safe_add(clut_data_size)? { + return Err(CmsError::InvalidProfile); + } + + let shaped_clut_table = &tag[clut_offset..clut_offset + clut_data_size]; + let clut_table = Self::read_lut_table_f32(shaped_clut_table, lut_type)?; + + let output_offset = clut_offset.safe_add(clut_data_size)?; + + let output_size = (num_output_table_entries as usize).safe_mul(out_chan as usize)?; + + let shaped_output = output_offset.safe_add(output_size.safe_mul(entry_size)?)?; + if tag.len() < shaped_output { + return Err(CmsError::InvalidProfile); + } + + let shaped_output_table = &tag[output_offset..shaped_output]; + let gamma_table = Self::read_lut_table_f32(shaped_output_table, lut_type)?; + + let wh = LutWarehouse::Lut(LutDataType { + num_input_table_entries, + num_output_table_entries, + num_input_channels: in_chan, + num_output_channels: out_chan, + num_clut_grid_points: grid_points, + matrix: transform, + input_table: linearization_table, + clut_table, + output_table: gamma_table, + lut_type, + }); + Ok(Some(wh)) + } + + pub(crate) fn read_lut_tag( + slice: &[u8], + tag_entry: u32, + tag_size: usize, + parsing_options: &ParsingOptions, + ) -> Result, CmsError> { + let lut_type = Self::read_lut_type(slice, tag_entry as usize, tag_size)?; + Ok(if lut_type == LutType::Lut8 || lut_type == LutType::Lut16 { + Self::read_lut_a_to_b_type(slice, tag_entry as usize, tag_size, parsing_options)? + } else if lut_type == LutType::LutMba || lut_type == LutType::LutMab { + Self::read_lut_abm_type( + slice, + tag_entry as usize, + tag_size, + lut_type == LutType::LutMab, + parsing_options, + )? + } else { + None + }) + } + + pub(crate) fn read_trc_tag_s( + slice: &[u8], + entry: usize, + tag_size: usize, + options: &ParsingOptions, + ) -> Result, CmsError> { + let mut _empty = 0usize; + Self::read_trc_tag(slice, entry, tag_size, &mut _empty, options) + } + + pub(crate) fn read_trc_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + read_size: &mut usize, + options: &ParsingOptions, + ) -> Result, CmsError> { + if slice.len() < entry.safe_add(4)? { + return Ok(None); + } + let small_tag = &slice[entry..entry + 4]; + // We require always recognize tone curves. + let curve_type = TagTypeDefinition::from(u32::from_be_bytes([ + small_tag[0], + small_tag[1], + small_tag[2], + small_tag[3], + ])); + if tag_size != 0 && tag_size < TAG_SIZE { + return Ok(None); + } + let last_tag_offset = if tag_size != 0 { + tag_size + entry + } else { + slice.len() + }; + if last_tag_offset > slice.len() { + return Err(CmsError::MalformedTrcCurve("Data exhausted".to_string())); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < TAG_SIZE { + return Err(CmsError::MalformedTrcCurve("Data exhausted".to_string())); + } + if curve_type == TagTypeDefinition::LutToneCurve { + let entry_count = u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]) as usize; + if entry_count == 0 { + return Ok(Some(ToneReprCurve::Lut(vec![]))); + } + if entry_count > options.max_allowed_trc_size { + return Err(CmsError::CurveLutIsTooLarge); + } + let curve_end = entry_count.safe_mul(size_of::())?.safe_add(12)?; + if tag.len() < curve_end { + return Err(CmsError::MalformedTrcCurve( + "Curve end ends to early".to_string(), + )); + } + let curve_sliced = &tag[12..curve_end]; + let mut curve_values = try_vec![0u16; entry_count]; + for (value, curve_value) in curve_sliced.chunks_exact(2).zip(curve_values.iter_mut()) { + let gamma_s15 = u16::from_be_bytes([value[0], value[1]]); + *curve_value = gamma_s15; + } + *read_size = curve_end; + Ok(Some(ToneReprCurve::Lut(curve_values))) + } else if curve_type == TagTypeDefinition::ParametricToneCurve { + let entry_count = u16::from_be_bytes([tag[8], tag[9]]) as usize; + if entry_count > 4 { + return Err(CmsError::MalformedTrcCurve( + "Parametric curve has unknown entries count".to_string(), + )); + } + + const COUNT_TO_LENGTH: [usize; 5] = [1, 3, 4, 5, 7]; //PARAMETRIC_CURVE_TYPE + + if tag.len() < 12 + COUNT_TO_LENGTH[entry_count] * size_of::() { + return Err(CmsError::MalformedTrcCurve( + "Parametric curve has unknown entries count exhaust data too early".to_string(), + )); + } + let curve_sliced = &tag[12..12 + COUNT_TO_LENGTH[entry_count] * size_of::()]; + let mut params = try_vec![0f32; COUNT_TO_LENGTH[entry_count]]; + for (value, param_value) in curve_sliced.chunks_exact(4).zip(params.iter_mut()) { + let parametric_value = i32::from_be_bytes([value[0], value[1], value[2], value[3]]); + *param_value = s15_fixed16_number_to_float(parametric_value); + } + if entry_count == 1 || entry_count == 2 { + // we have a type 1 or type 2 function that has a division by `a` + let a: f32 = params[1]; + if a == 0.0 { + return Err(CmsError::ParametricCurveZeroDivision); + } + } + *read_size = 12 + COUNT_TO_LENGTH[entry_count] * 4; + Ok(Some(ToneReprCurve::Parametric(params))) + } else { + Err(CmsError::MalformedTrcCurve( + "Unknown parametric curve tag".to_string(), + )) + } + } + + #[inline] + pub(crate) fn read_chad_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + if slice[entry..].len() < 8 { + return Err(CmsError::InvalidProfile); + } + if tag_size < 8 { + return Ok(None); + } + if (tag_size - 8) / 4 != 9 { + return Ok(None); + } + let tag0 = &slice[entry..entry.safe_add(8)?]; + let c_type = + TagTypeDefinition::from(u32::from_be_bytes([tag0[0], tag0[1], tag0[2], tag0[3]])); + if c_type != TagTypeDefinition::S15Fixed16Array { + return Err(CmsError::InvalidProfile); + } + if slice.len() < 9 * size_of::() + 8 { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry + 8..last_tag_offset]; + if tag.len() != size_of::() { + return Err(CmsError::InvalidProfile); + } + let matrix = read_matrix_3d(tag)?; + Ok(Some(matrix)) + } + + #[inline] + pub(crate) fn read_tech_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + if tag_size < TAG_SIZE { + return Err(CmsError::InvalidProfile); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry.safe_add(12)?]; + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let def = TagTypeDefinition::from(tag_type); + if def == TagTypeDefinition::Signature { + let sig = u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]); + let tech_sig = TechnologySignatures::from(sig); + return Ok(Some(tech_sig)); + } + Ok(None) + } + + #[inline] + pub(crate) fn read_date_time_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + if tag_size < 20 { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry.safe_add(20)?]; + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let def = TagTypeDefinition::from(tag_type); + if def == TagTypeDefinition::DateTime { + let tag_value = &slice[8..20]; + let time = ColorDateTime::new_from_slice(tag_value)?; + return Ok(Some(time)); + } + Ok(None) + } + + #[inline] + pub(crate) fn read_meas_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + if tag_size < TAG_SIZE { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry + 12]; + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let def = TagTypeDefinition::from(tag_type); + if def != TagTypeDefinition::Measurement { + return Ok(None); + } + if 36 + entry > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry + 36]; + let observer = + StandardObserver::from(u32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]])); + let q15_16_x = i32::from_be_bytes([tag[12], tag[13], tag[14], tag[15]]); + let q15_16_y = i32::from_be_bytes([tag[16], tag[17], tag[18], tag[19]]); + let q15_16_z = i32::from_be_bytes([tag[20], tag[21], tag[22], tag[23]]); + let x = s15_fixed16_number_to_float(q15_16_x); + let y = s15_fixed16_number_to_float(q15_16_y); + let z = s15_fixed16_number_to_float(q15_16_z); + let xyz = Xyz::new(x, y, z); + let geometry = + MeasurementGeometry::from(u32::from_be_bytes([tag[24], tag[25], tag[26], tag[27]])); + let flare = + uint16_number_to_float(u32::from_be_bytes([tag[28], tag[29], tag[30], tag[31]])); + let illuminant = + StandardIlluminant::from(u32::from_be_bytes([tag[32], tag[33], tag[34], tag[35]])); + Ok(Some(Measurement { + flare, + illuminant, + geometry, + observer, + backing: xyz, + })) + } + + #[inline] + pub(crate) fn read_xyz_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result { + if tag_size < TAG_SIZE { + return Ok(Xyzd::default()); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..entry + 12]; + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let def = TagTypeDefinition::from(tag_type); + if def != TagTypeDefinition::Xyz { + return Ok(Xyzd::default()); + } + + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 20 { + return Err(CmsError::InvalidProfile); + } + let q15_16_x = i32::from_be_bytes([tag[8], tag[9], tag[10], tag[11]]); + let q15_16_y = i32::from_be_bytes([tag[12], tag[13], tag[14], tag[15]]); + let q15_16_z = i32::from_be_bytes([tag[16], tag[17], tag[18], tag[19]]); + let x = s15_fixed16_number_to_double(q15_16_x); + let y = s15_fixed16_number_to_double(q15_16_y); + let z = s15_fixed16_number_to_double(q15_16_z); + Ok(Xyzd { x, y, z }) + } + + #[inline] + pub(crate) fn read_cicp_tag( + slice: &[u8], + entry: usize, + tag_size: usize, + ) -> Result, CmsError> { + if tag_size < TAG_SIZE { + return Ok(None); + } + let last_tag_offset = tag_size.safe_add(entry)?; + if last_tag_offset > slice.len() { + return Err(CmsError::InvalidProfile); + } + let tag = &slice[entry..last_tag_offset]; + if tag.len() < 12 { + return Err(CmsError::InvalidProfile); + } + let tag_type = u32::from_be_bytes([tag[0], tag[1], tag[2], tag[3]]); + let def = TagTypeDefinition::from(tag_type); + if def != TagTypeDefinition::Cicp { + return Ok(None); + } + let primaries = CicpColorPrimaries::try_from(tag[8])?; + let transfer_characteristics = TransferCharacteristics::try_from(tag[9])?; + let matrix_coefficients = MatrixCoefficients::try_from(tag[10])?; + let full_range = tag[11] == 1; + Ok(Some(CicpProfile { + color_primaries: primaries, + transfer_characteristics, + matrix_coefficients, + full_range, + })) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,723 @@ +/* + * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved. + * // + * // Use of this source code is governed by a BSD-style + * // license that can be found in the LICENSE file. + */ +use crate::math::{FusedMultiplyAdd, m_clamp, m_max, m_min}; +use crate::mlaf::mlaf; +use crate::{Matrix3f, Vector3, Xyz}; +use num_traits::{AsPrimitive, Bounded, Float, Num, Pow, Signed}; +use pxfm::{ + f_exp, f_exp2, f_exp2f, f_exp10, f_exp10f, f_expf, f_log, f_log2, f_log2f, f_log10, f_log10f, + f_logf, f_pow, f_powf, +}; +use std::cmp::Ordering; +use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub}; + +#[repr(C)] +#[derive(Debug, PartialOrd, PartialEq, Clone, Copy, Default)] +/// Represents any RGB values +pub struct Rgb { + /// Red component + pub r: T, + /// Green component + pub g: T, + /// Blue component + pub b: T, +} + +impl Rgb { + pub fn new(r: T, g: T, b: T) -> Rgb { + Rgb { r, g, b } + } +} + +impl Rgb +where + T: Copy, +{ + pub fn dup(v: T) -> Rgb { + Rgb { r: v, g: v, b: v } + } + + #[inline] + pub const fn to_vector(self) -> Vector3 { + Vector3 { + v: [self.r, self.g, self.b], + } + } +} + +impl Rgb { + #[inline(always)] + pub fn apply(&self, matrix: Matrix3f) -> Rgb { + let new_r = mlaf( + mlaf(self.r * matrix.v[0][0], self.g, matrix.v[0][1]), + self.b, + matrix.v[0][2], + ); + + let new_g = mlaf( + mlaf(self.r * matrix.v[1][0], self.g, matrix.v[1][1]), + self.b, + matrix.v[1][2], + ); + + let new_b = mlaf( + mlaf(self.r * matrix.v[2][0], self.g, matrix.v[2][1]), + self.b, + matrix.v[2][2], + ); + + Rgb { + r: new_r, + g: new_g, + b: new_b, + } + } + + #[inline(always)] + pub fn to_xyz(&self, matrix: Matrix3f) -> Xyz { + let new_self = self.apply(matrix); + Xyz { + x: new_self.r, + y: new_self.g, + z: new_self.b, + } + } + + #[inline(always)] + pub fn is_out_of_gamut(&self) -> bool { + !(0.0..=1.0).contains(&self.r) + || !(0.0..=1.0).contains(&self.g) + || !(0.0..=1.0).contains(&self.b) + } +} + +impl Index for Rgb { + type Output = T; + + fn index(&self, index: usize) -> &T { + match index { + 0 => &self.r, + 1 => &self.g, + 2 => &self.b, + _ => panic!("Index out of bounds for Rgb"), + } + } +} + +impl IndexMut for Rgb { + fn index_mut(&mut self, index: usize) -> &mut T { + match index { + 0 => &mut self.r, + 1 => &mut self.g, + 2 => &mut self.b, + _ => panic!("Index out of bounds for RGB"), + } + } +} + +macro_rules! generated_float_definition_rgb { + ($T: ty) => { + impl Rgb<$T> { + #[inline] + pub fn zeroed() -> Rgb<$T> { + Rgb::<$T>::new(0., 0., 0.) + } + + #[inline] + pub fn ones() -> Rgb<$T> { + Rgb::<$T>::new(1., 1., 1.) + } + + #[inline] + pub fn white() -> Rgb<$T> { + Rgb::<$T>::ones() + } + + #[inline] + pub fn black() -> Rgb<$T> { + Rgb::<$T>::zeroed() + } + } + }; +} + +generated_float_definition_rgb!(f32); +generated_float_definition_rgb!(f64); + +macro_rules! generated_integral_definition_rgb { + ($T: ty) => { + impl Rgb<$T> { + #[inline] + pub fn zeroed() -> Rgb<$T> { + Rgb::<$T>::new(0, 0, 0) + } + + #[inline] + pub fn capped() -> Rgb<$T> { + Rgb::<$T>::new(<$T>::MAX, <$T>::MAX, <$T>::MAX) + } + + #[inline] + pub fn white() -> Rgb<$T> { + Rgb::<$T>::capped() + } + + #[inline] + pub fn black() -> Rgb<$T> { + Rgb::<$T>::new(0, 0, 0) + } + } + }; +} + +generated_integral_definition_rgb!(u8); +generated_integral_definition_rgb!(u16); +generated_integral_definition_rgb!(i8); +generated_integral_definition_rgb!(i16); +generated_integral_definition_rgb!(i32); +generated_integral_definition_rgb!(u32); + +pub trait FusedPow { + fn f_pow(&self, power: T) -> Self; +} + +pub trait FusedLog2 { + fn f_log2(&self) -> Self; +} + +pub trait FusedLog10 { + fn f_log10(&self) -> Self; +} + +pub trait FusedLog { + fn f_log(&self) -> Self; +} + +pub trait FusedExp { + fn f_exp(&self) -> Self; +} + +pub trait FusedExp2 { + fn f_exp2(&self) -> Self; +} + +pub trait FusedExp10 { + fn f_exp10(&self) -> Self; +} + +impl FusedPow> for Rgb { + fn f_pow(&self, power: Rgb) -> Rgb { + Rgb::new( + f_powf(self.r, power.r), + f_powf(self.g, power.g), + f_powf(self.b, power.b), + ) + } +} + +impl FusedPow> for Rgb { + fn f_pow(&self, power: Rgb) -> Rgb { + Rgb::new( + f_pow(self.r, power.r), + f_pow(self.g, power.g), + f_pow(self.b, power.b), + ) + } +} + +impl FusedLog2> for Rgb { + #[inline] + fn f_log2(&self) -> Rgb { + Rgb::new(f_log2f(self.r), f_log2f(self.g), f_log2f(self.b)) + } +} + +impl FusedLog2> for Rgb { + #[inline] + fn f_log2(&self) -> Rgb { + Rgb::new(f_log2(self.r), f_log2(self.g), f_log2(self.b)) + } +} + +impl FusedLog> for Rgb { + #[inline] + fn f_log(&self) -> Rgb { + Rgb::new(f_logf(self.r), f_logf(self.g), f_logf(self.b)) + } +} + +impl FusedLog> for Rgb { + #[inline] + fn f_log(&self) -> Rgb { + Rgb::new(f_log(self.r), f_log(self.g), f_log(self.b)) + } +} + +impl FusedLog10> for Rgb { + #[inline] + fn f_log10(&self) -> Rgb { + Rgb::new(f_log10f(self.r), f_log10f(self.g), f_log10f(self.b)) + } +} + +impl FusedLog10> for Rgb { + #[inline] + fn f_log10(&self) -> Rgb { + Rgb::new(f_log10(self.r), f_log10(self.g), f_log10(self.b)) + } +} + +impl FusedExp> for Rgb { + #[inline] + fn f_exp(&self) -> Rgb { + Rgb::new(f_expf(self.r), f_expf(self.g), f_expf(self.b)) + } +} + +impl FusedExp> for Rgb { + #[inline] + fn f_exp(&self) -> Rgb { + Rgb::new(f_exp(self.r), f_exp(self.g), f_exp(self.b)) + } +} + +impl FusedExp2> for Rgb { + #[inline] + fn f_exp2(&self) -> Rgb { + Rgb::new(f_exp2f(self.r), f_exp2f(self.g), f_exp2f(self.b)) + } +} + +impl FusedExp2> for Rgb { + #[inline] + fn f_exp2(&self) -> Rgb { + Rgb::new(f_exp2(self.r), f_exp2(self.g), f_exp2(self.b)) + } +} + +impl FusedExp10> for Rgb { + #[inline] + fn f_exp10(&self) -> Rgb { + Rgb::new(f_exp10f(self.r), f_exp10f(self.g), f_exp10f(self.b)) + } +} + +impl FusedExp10> for Rgb { + #[inline] + fn f_exp10(&self) -> Rgb { + Rgb::new(f_exp10(self.r), f_exp10(self.g), f_exp10(self.b)) + } +} + +impl Rgb +where + T: Copy + AsPrimitive, +{ + pub fn euclidean_distance(&self, other: Rgb) -> f32 { + let dr = self.r.as_() - other.r.as_(); + let dg = self.g.as_() - other.g.as_(); + let db = self.b.as_() - other.b.as_(); + (dr * dr + dg * dg + db * db).sqrt() + } +} + +impl Rgb +where + T: Copy + AsPrimitive, +{ + pub fn taxicab_distance(&self, other: Self) -> f32 { + let dr = self.r.as_() - other.r.as_(); + let dg = self.g.as_() - other.g.as_(); + let db = self.b.as_() - other.b.as_(); + dr.abs() + dg.abs() + db.abs() + } +} + +impl Add for Rgb +where + T: Add, +{ + type Output = Rgb; + + #[inline] + fn add(self, rhs: Self) -> Self::Output { + Rgb::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b) + } +} + +impl Sub for Rgb +where + T: Sub, +{ + type Output = Rgb; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + Rgb::new(self.r - rhs.r, self.g - rhs.g, self.b - rhs.b) + } +} + +impl Sub for Rgb +where + T: Sub, +{ + type Output = Rgb; + + #[inline] + fn sub(self, rhs: T) -> Self::Output { + Rgb::new(self.r - rhs, self.g - rhs, self.b - rhs) + } +} + +impl Add for Rgb +where + T: Add, +{ + type Output = Rgb; + + #[inline] + fn add(self, rhs: T) -> Self::Output { + Rgb::new(self.r + rhs, self.g + rhs, self.b + rhs) + } +} + +impl Rgb +where + T: Signed, +{ + #[inline] + pub fn abs(self) -> Self { + Rgb::new(self.r.abs(), self.g.abs(), self.b.abs()) + } +} + +impl Div for Rgb +where + T: Div, +{ + type Output = Rgb; + + #[inline] + fn div(self, rhs: Self) -> Self::Output { + Rgb::new(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b) + } +} + +impl Div for Rgb +where + T: Div, +{ + type Output = Rgb; + + #[inline] + fn div(self, rhs: T) -> Self::Output { + Rgb::new(self.r / rhs, self.g / rhs, self.b / rhs) + } +} + +impl Mul for Rgb +where + T: Mul, +{ + type Output = Rgb; + + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + Rgb::new(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b) + } +} + +impl Mul for Rgb +where + T: Mul, +{ + type Output = Rgb; + + #[inline] + fn mul(self, rhs: T) -> Self::Output { + Rgb::new(self.r * rhs, self.g * rhs, self.b * rhs) + } +} + +impl MulAssign for Rgb +where + T: MulAssign, +{ + #[inline] + fn mul_assign(&mut self, rhs: Self) { + self.r *= rhs.r; + self.g *= rhs.g; + self.b *= rhs.b; + } +} + +macro_rules! generated_mul_assign_definition_rgb { + ($T: ty) => { + impl MulAssign<$T> for Rgb + where + T: MulAssign<$T>, + { + #[inline] + fn mul_assign(&mut self, rhs: $T) { + self.r *= rhs; + self.g *= rhs; + self.b *= rhs; + } + } + }; +} + +generated_mul_assign_definition_rgb!(i8); +generated_mul_assign_definition_rgb!(u8); +generated_mul_assign_definition_rgb!(u16); +generated_mul_assign_definition_rgb!(i16); +generated_mul_assign_definition_rgb!(u32); +generated_mul_assign_definition_rgb!(i32); +generated_mul_assign_definition_rgb!(f32); +generated_mul_assign_definition_rgb!(f64); + +impl AddAssign for Rgb +where + T: AddAssign, +{ + #[inline] + fn add_assign(&mut self, rhs: Self) { + self.r += rhs.r; + self.g += rhs.g; + self.b += rhs.b; + } +} + +macro_rules! generated_add_assign_definition_rgb { + ($T: ty) => { + impl AddAssign<$T> for Rgb + where + T: AddAssign<$T>, + { + #[inline] + fn add_assign(&mut self, rhs: $T) { + self.r += rhs; + self.g += rhs; + self.b += rhs; + } + } + }; +} + +generated_add_assign_definition_rgb!(i8); +generated_add_assign_definition_rgb!(u8); +generated_add_assign_definition_rgb!(u16); +generated_add_assign_definition_rgb!(i16); +generated_add_assign_definition_rgb!(u32); +generated_add_assign_definition_rgb!(i32); +generated_add_assign_definition_rgb!(f32); +generated_add_assign_definition_rgb!(f64); + +impl DivAssign for Rgb +where + T: DivAssign, +{ + #[inline] + fn div_assign(&mut self, rhs: Self) { + self.r /= rhs.r; + self.g /= rhs.g; + self.b /= rhs.b; + } +} + +macro_rules! generated_div_assign_definition_rgb { + ($T: ty) => { + impl DivAssign<$T> for Rgb + where + T: DivAssign<$T>, + { + #[inline] + fn div_assign(&mut self, rhs: $T) { + self.r /= rhs; + self.g /= rhs; + self.b /= rhs; + } + } + }; +} + +generated_div_assign_definition_rgb!(u8); +generated_div_assign_definition_rgb!(i8); +generated_div_assign_definition_rgb!(u16); +generated_div_assign_definition_rgb!(i16); +generated_div_assign_definition_rgb!(u32); +generated_div_assign_definition_rgb!(i32); +generated_div_assign_definition_rgb!(f32); +generated_div_assign_definition_rgb!(f64); + +impl Neg for Rgb +where + T: Neg, +{ + type Output = Rgb; + + #[inline] + fn neg(self) -> Self::Output { + Rgb::new(-self.r, -self.g, -self.b) + } +} + +impl Rgb +where + T: FusedMultiplyAdd, +{ + pub fn mla(&self, b: Rgb, c: Rgb) -> Rgb { + Rgb::new( + self.r.mla(b.r, c.r), + self.g.mla(b.g, c.g), + self.b.mla(b.b, c.b), + ) + } +} + +impl Rgb +where + T: Num + PartialOrd + Copy + Bounded, +{ + /// Clamp function to clamp each channel within a given range + #[inline] + #[allow(clippy::manual_clamp)] + pub fn clamp(&self, min_value: T, max_value: T) -> Rgb { + Rgb::new( + m_clamp(self.r, min_value, max_value), + m_clamp(self.g, min_value, max_value), + m_clamp(self.b, min_value, max_value), + ) + } + + /// Min function to define min + #[inline] + pub fn min(&self, other_min: T) -> Rgb { + Rgb::new( + m_min(self.r, other_min), + m_min(self.g, other_min), + m_min(self.b, other_min), + ) + } + + /// Max function to define max + #[inline] + pub fn max(&self, other_max: T) -> Rgb { + Rgb::new( + m_max(self.r, other_max), + m_max(self.g, other_max), + m_max(self.b, other_max), + ) + } + + /// Clamp function to clamp each channel within a given range + #[inline] + #[allow(clippy::manual_clamp)] + pub fn clamp_p(&self, min_value: Rgb, max_value: Rgb) -> Rgb { + Rgb::new( + m_clamp(self.r, max_value.r, min_value.r), + m_clamp(self.g, max_value.g, min_value.g), + m_clamp(self.b, max_value.b, min_value.b), + ) + } + + /// Min function to define min + #[inline] + pub fn min_p(&self, other_min: Rgb) -> Rgb { + Rgb::new( + m_min(self.r, other_min.r), + m_min(self.g, other_min.g), + m_min(self.b, other_min.b), + ) + } + + /// Max function to define max + #[inline] + pub fn max_p(&self, other_max: Rgb) -> Rgb { + Rgb::new( + m_max(self.r, other_max.r), + m_max(self.g, other_max.g), + m_max(self.b, other_max.b), + ) + } +} + +impl Rgb +where + T: Float + 'static, + f32: AsPrimitive, +{ + #[inline] + pub fn sqrt(&self) -> Rgb { + let zeros = 0f32.as_(); + Rgb::new( + if self.r.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { + 0f32.as_() + } else { + self.r.sqrt() + }, + if self.g.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { + 0f32.as_() + } else { + self.g.sqrt() + }, + if self.b.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { + 0f32.as_() + } else { + self.b.sqrt() + }, + ) + } + + #[inline] + pub fn cbrt(&self) -> Rgb { + Rgb::new(self.r.cbrt(), self.g.cbrt(), self.b.cbrt()) + } +} + +impl Pow for Rgb +where + T: Float, +{ + type Output = Rgb; + + #[inline] + fn pow(self, rhs: T) -> Self::Output { + Rgb::::new(self.r.powf(rhs), self.g.powf(rhs), self.b.powf(rhs)) + } +} + +impl Pow> for Rgb +where + T: Float, +{ + type Output = Rgb; + + #[inline] + fn pow(self, rhs: Rgb) -> Self::Output { + Rgb::::new(self.r.powf(rhs.r), self.g.powf(rhs.g), self.b.powf(rhs.b)) + } +} + +impl Rgb { + pub fn cast(self) -> Rgb + where + T: AsPrimitive, + V: Copy + 'static, + { + Rgb::new(self.r.as_(), self.g.as_(), self.b.as_()) + } +} + +impl Rgb +where + T: Float + 'static, +{ + pub fn round(self) -> Rgb { + Rgb::new(self.r.round(), self.g.round(), self.b.round()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/safe_math.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/safe_math.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/safe_math.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/safe_math.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::CmsError; +use std::ops::Add; + +pub(crate) trait SafeAdd> { + fn safe_add(&self, other: T) -> Result; +} + +pub(crate) trait SafeMul> { + fn safe_mul(&self, other: T) -> Result; +} + +pub(crate) trait SafePowi> { + fn safe_powi(&self, power: u32) -> Result; +} + +macro_rules! safe_add_impl { + ($type_name: ident) => { + impl SafeAdd<$type_name> for $type_name { + #[inline(always)] + fn safe_add(&self, other: $type_name) -> Result<$type_name, CmsError> { + if let Some(result) = self.checked_add(other) { + return Ok(result); + } + Err(CmsError::OverflowingError) + } + } + }; +} + +safe_add_impl!(u16); +safe_add_impl!(u32); +safe_add_impl!(i32); +safe_add_impl!(usize); +safe_add_impl!(isize); + +macro_rules! safe_mul_impl { + ($type_name: ident) => { + impl SafeMul<$type_name> for $type_name { + #[inline(always)] + fn safe_mul(&self, other: $type_name) -> Result<$type_name, CmsError> { + if let Some(result) = self.checked_mul(other) { + return Ok(result); + } + Err(CmsError::OverflowingError) + } + } + }; +} + +safe_mul_impl!(u16); +safe_mul_impl!(u32); +safe_mul_impl!(i32); +safe_mul_impl!(usize); +safe_mul_impl!(isize); + +macro_rules! safe_powi_impl { + ($type_name: ident) => { + impl SafePowi<$type_name> for $type_name { + #[inline(always)] + fn safe_powi(&self, power: u32) -> Result<$type_name, CmsError> { + if let Some(result) = self.checked_pow(power) { + return Ok(result); + } + Err(CmsError::OverflowingError) + } + } + }; +} + +safe_powi_impl!(u8); +safe_powi_impl!(u16); +safe_powi_impl!(u32); +safe_powi_impl!(i32); +safe_powi_impl!(usize); +safe_powi_impl!(isize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/srlab2.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/srlab2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/srlab2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/srlab2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::Xyz; +use crate::mlaf::mlaf; +use pxfm::f_cbrtf; + +#[inline] +fn srlab2_gamma(x: f32) -> f32 { + if x <= 216. / 24389. { + x * (24389. / 2700.) + } else { + 1.16 * f_cbrtf(x) - 0.16 + } +} + +#[inline] +fn srlab2_linearize(x: f32) -> f32 { + if x <= 0.08 { + x * (2700.0 / 24389.0) + } else { + let zx = (x + 0.16) / 1.16; + zx * zx * zx + } +} + +#[derive(Copy, Clone, Debug, Default, PartialOrd, PartialEq)] +pub struct Srlab2 { + pub l: f32, + pub a: f32, + pub b: f32, +} + +impl Srlab2 { + #[inline] + pub const fn new(l: f32, a: f32, b: f32) -> Srlab2 { + Srlab2 { l, a, b } + } + + #[inline] + pub fn from_xyz(xyz: Xyz) -> Srlab2 { + let lx = srlab2_gamma(xyz.x); + let ly = srlab2_gamma(xyz.y); + let lz = srlab2_gamma(xyz.z); + + let l = mlaf(mlaf(0.629054 * ly, -0.000008, lz), 0.37095, lx); + let a = mlaf(mlaf(6.634684 * lx, -7.505078, ly), 0.870328, lz); + let b = mlaf(mlaf(0.639569 * lx, 1.084576, ly), -1.724152, lz); + Srlab2 { l, a, b } + } + + #[inline] + pub fn to_xyz(&self) -> Xyz { + let x = mlaf(mlaf(self.l, 0.09041272, self.a), 0.045634452, self.b); + let y = mlaf(mlaf(self.l, -0.05331593, self.a), -0.026917785, self.b); + let z = mlaf(self.l, -0.58, self.b); + let lx = srlab2_linearize(x); + let ly = srlab2_linearize(y); + let lz = srlab2_linearize(z); + Xyz::new(lx, ly, lz) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_srlab2() { + let xyz = Xyz::new(0.3, 0.65, 0.66); + let srlab2 = Srlab2::from_xyz(xyz); + let r_xyz = srlab2.to_xyz(); + assert!((r_xyz.x - xyz.x).abs() < 1e-5); + assert!((r_xyz.y - xyz.y).abs() < 1e-5); + assert!((r_xyz.z - xyz.z).abs() < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/tag.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/tag.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/tag.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/tag.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,271 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::CmsError; + +pub(crate) const TAG_SIZE: usize = 12; + +#[derive(Debug, Copy, Clone, PartialEq, Ord, PartialOrd, Eq, Hash)] +pub(crate) enum Tag { + RedXyz, + GreenXyz, + BlueXyz, + RedToneReproduction, + GreenToneReproduction, + BlueToneReproduction, + GreyToneReproduction, + MediaWhitePoint, + CodeIndependentPoints, + ChromaticAdaptation, + BlackPoint, + DeviceToPcsLutPerceptual, + DeviceToPcsLutColorimetric, + DeviceToPcsLutSaturation, + PcsToDeviceLutPerceptual, + PcsToDeviceLutColorimetric, + PcsToDeviceLutSaturation, + ProfileDescription, + Copyright, + ViewingConditionsDescription, + DeviceManufacturer, + DeviceModel, + Gamut, + Luminance, + Measurement, + Chromaticity, + ObserverConditions, + CharTarget, + Technology, + CalibrationDateTime, +} + +impl TryFrom for Tag { + type Error = CmsError; + + fn try_from(value: u32) -> Result { + if value == u32::from_ne_bytes(*b"rXYZ").to_be() { + return Ok(Self::RedXyz); + } else if value == u32::from_ne_bytes(*b"gXYZ").to_be() { + return Ok(Self::GreenXyz); + } else if value == u32::from_ne_bytes(*b"bXYZ").to_be() { + return Ok(Self::BlueXyz); + } else if value == u32::from_ne_bytes(*b"rTRC").to_be() { + return Ok(Self::RedToneReproduction); + } else if value == u32::from_ne_bytes(*b"gTRC").to_be() { + return Ok(Self::GreenToneReproduction); + } else if value == u32::from_ne_bytes(*b"bTRC").to_be() { + return Ok(Self::BlueToneReproduction); + } else if value == u32::from_ne_bytes(*b"kTRC").to_be() { + return Ok(Self::GreyToneReproduction); + } else if value == u32::from_ne_bytes(*b"wtpt").to_be() { + return Ok(Self::MediaWhitePoint); + } else if value == u32::from_ne_bytes(*b"cicp").to_be() { + return Ok(Self::CodeIndependentPoints); + } else if value == u32::from_ne_bytes(*b"chad").to_be() { + return Ok(Self::ChromaticAdaptation); + } else if value == u32::from_ne_bytes(*b"bkpt").to_be() { + return Ok(Self::BlackPoint); + } else if value == u32::from_ne_bytes(*b"A2B0").to_be() { + return Ok(Self::DeviceToPcsLutPerceptual); + } else if value == u32::from_ne_bytes(*b"A2B1").to_be() { + return Ok(Self::DeviceToPcsLutColorimetric); + } else if value == u32::from_ne_bytes(*b"A2B2").to_be() { + return Ok(Self::DeviceToPcsLutSaturation); + } else if value == u32::from_ne_bytes(*b"B2A0").to_be() { + return Ok(Self::PcsToDeviceLutPerceptual); + } else if value == u32::from_ne_bytes(*b"B2A1").to_be() { + return Ok(Self::PcsToDeviceLutColorimetric); + } else if value == u32::from_ne_bytes(*b"B2A2").to_be() { + return Ok(Self::PcsToDeviceLutSaturation); + } else if value == u32::from_ne_bytes(*b"desc").to_be() { + return Ok(Self::ProfileDescription); + } else if value == u32::from_ne_bytes(*b"cprt").to_be() { + return Ok(Self::Copyright); + } else if value == u32::from_ne_bytes(*b"vued").to_be() { + return Ok(Self::ViewingConditionsDescription); + } else if value == u32::from_ne_bytes(*b"dmnd").to_be() { + return Ok(Self::DeviceManufacturer); + } else if value == u32::from_ne_bytes(*b"dmdd").to_be() { + return Ok(Self::DeviceModel); + } else if value == u32::from_ne_bytes(*b"gamt").to_be() { + return Ok(Self::Gamut); + } else if value == u32::from_ne_bytes(*b"lumi").to_be() { + return Ok(Self::Luminance); + } else if value == u32::from_ne_bytes(*b"meas").to_be() { + return Ok(Self::Measurement); + } else if value == u32::from_ne_bytes(*b"chrm").to_be() { + return Ok(Self::Chromaticity); + } else if value == u32::from_ne_bytes(*b"view").to_be() { + return Ok(Self::ObserverConditions); + } else if value == u32::from_ne_bytes(*b"targ").to_be() { + return Ok(Self::CharTarget); + } else if value == u32::from_ne_bytes(*b"tech").to_be() { + return Ok(Self::Technology); + } else if value == u32::from_ne_bytes(*b"calt").to_be() { + return Ok(Self::CalibrationDateTime); + } + Err(CmsError::UnknownTag(value)) + } +} + +impl From for u32 { + fn from(value: Tag) -> Self { + match value { + Tag::RedXyz => u32::from_ne_bytes(*b"rXYZ").to_be(), + Tag::GreenXyz => u32::from_ne_bytes(*b"gXYZ").to_be(), + Tag::BlueXyz => u32::from_ne_bytes(*b"bXYZ").to_be(), + Tag::RedToneReproduction => u32::from_ne_bytes(*b"rTRC").to_be(), + Tag::GreenToneReproduction => u32::from_ne_bytes(*b"gTRC").to_be(), + Tag::BlueToneReproduction => u32::from_ne_bytes(*b"bTRC").to_be(), + Tag::GreyToneReproduction => u32::from_ne_bytes(*b"kTRC").to_be(), + Tag::MediaWhitePoint => u32::from_ne_bytes(*b"wtpt").to_be(), + Tag::CodeIndependentPoints => u32::from_ne_bytes(*b"cicp").to_be(), + Tag::ChromaticAdaptation => u32::from_ne_bytes(*b"chad").to_be(), + Tag::BlackPoint => u32::from_ne_bytes(*b"bkpt").to_be(), + Tag::DeviceToPcsLutPerceptual => u32::from_ne_bytes(*b"A2B0").to_be(), + Tag::DeviceToPcsLutColorimetric => u32::from_ne_bytes(*b"A2B1").to_be(), + Tag::DeviceToPcsLutSaturation => u32::from_ne_bytes(*b"A2B2").to_be(), + Tag::PcsToDeviceLutPerceptual => u32::from_ne_bytes(*b"B2A0").to_be(), + Tag::PcsToDeviceLutColorimetric => u32::from_ne_bytes(*b"B2A1").to_be(), + Tag::PcsToDeviceLutSaturation => u32::from_ne_bytes(*b"B2A2").to_be(), + Tag::ProfileDescription => u32::from_ne_bytes(*b"desc").to_be(), + Tag::Copyright => u32::from_ne_bytes(*b"cprt").to_be(), + Tag::ViewingConditionsDescription => u32::from_ne_bytes(*b"vued").to_be(), + Tag::DeviceManufacturer => u32::from_ne_bytes(*b"dmnd").to_be(), + Tag::DeviceModel => u32::from_ne_bytes(*b"dmdd").to_be(), + Tag::Gamut => u32::from_ne_bytes(*b"gamt").to_be(), + Tag::Luminance => u32::from_ne_bytes(*b"lumi").to_be(), + Tag::Measurement => u32::from_ne_bytes(*b"meas").to_be(), + Tag::Chromaticity => u32::from_ne_bytes(*b"chrm").to_be(), + Tag::ObserverConditions => u32::from_ne_bytes(*b"view").to_be(), + Tag::CharTarget => u32::from_ne_bytes(*b"targ").to_be(), + Tag::Technology => u32::from_ne_bytes(*b"tech").to_be(), + Tag::CalibrationDateTime => u32::from_ne_bytes(*b"calt").to_be(), + } + } +} + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub(crate) enum TagTypeDefinition { + Text, + MultiLocalizedUnicode, + Description, + MabLut, + MbaLut, + ParametricToneCurve, + LutToneCurve, + Xyz, + MultiProcessElement, + DefViewingConditions, + Signature, + Cicp, + DateTime, + S15Fixed16Array, + U8Array, + U16Fixed16Array, + U16Array, + U32Array, + U64Array, + Measurement, + NotAllowed, +} + +impl From for TagTypeDefinition { + fn from(value: u32) -> Self { + if value == u32::from_ne_bytes(*b"mluc").to_be() { + return TagTypeDefinition::MultiLocalizedUnicode; + } else if value == u32::from_ne_bytes(*b"desc").to_be() { + return TagTypeDefinition::Description; + } else if value == u32::from_ne_bytes(*b"text").to_be() { + return TagTypeDefinition::Text; + } else if value == u32::from_ne_bytes(*b"mAB ").to_be() { + return TagTypeDefinition::MabLut; + } else if value == u32::from_ne_bytes(*b"mBA ").to_be() { + return TagTypeDefinition::MbaLut; + } else if value == u32::from_ne_bytes(*b"para").to_be() { + return TagTypeDefinition::ParametricToneCurve; + } else if value == u32::from_ne_bytes(*b"curv").to_be() { + return TagTypeDefinition::LutToneCurve; + } else if value == u32::from_ne_bytes(*b"XYZ ").to_be() { + return TagTypeDefinition::Xyz; + } else if value == u32::from_ne_bytes(*b"mpet").to_be() { + return TagTypeDefinition::MultiProcessElement; + } else if value == u32::from_ne_bytes(*b"view").to_be() { + return TagTypeDefinition::DefViewingConditions; + } else if value == u32::from_ne_bytes(*b"sig ").to_be() { + return TagTypeDefinition::Signature; + } else if value == u32::from_ne_bytes(*b"cicp").to_be() { + return TagTypeDefinition::Cicp; + } else if value == u32::from_ne_bytes(*b"dtim").to_be() { + return TagTypeDefinition::DateTime; + } else if value == u32::from_ne_bytes(*b"meas").to_be() { + return TagTypeDefinition::Measurement; + } else if value == u32::from_ne_bytes(*b"sf32").to_be() { + return TagTypeDefinition::S15Fixed16Array; + } else if value == u32::from_ne_bytes(*b"uf32").to_be() { + return TagTypeDefinition::U16Fixed16Array; + } else if value == u32::from_ne_bytes(*b"ui16").to_be() { + return TagTypeDefinition::U16Array; + } else if value == u32::from_ne_bytes(*b"ui32").to_be() { + return TagTypeDefinition::U32Array; + } else if value == u32::from_ne_bytes(*b"ui64").to_be() { + return TagTypeDefinition::U64Array; + } else if value == u32::from_ne_bytes(*b"ui08").to_be() { + return TagTypeDefinition::U8Array; + } + TagTypeDefinition::NotAllowed + } +} + +impl From for u32 { + fn from(value: TagTypeDefinition) -> Self { + match value { + TagTypeDefinition::MultiLocalizedUnicode => u32::from_ne_bytes(*b"mluc").to_be(), + TagTypeDefinition::Description => u32::from_ne_bytes(*b"desc").to_be(), + TagTypeDefinition::Text => u32::from_ne_bytes(*b"text").to_be(), + TagTypeDefinition::MabLut => u32::from_ne_bytes(*b"mAB ").to_be(), + TagTypeDefinition::MbaLut => u32::from_ne_bytes(*b"mBA ").to_be(), + TagTypeDefinition::ParametricToneCurve => u32::from_ne_bytes(*b"para").to_be(), + TagTypeDefinition::LutToneCurve => u32::from_ne_bytes(*b"curv").to_be(), + TagTypeDefinition::Xyz => u32::from_ne_bytes(*b"XYZ ").to_be(), + TagTypeDefinition::MultiProcessElement => u32::from_ne_bytes(*b"mpet").to_be(), + TagTypeDefinition::DefViewingConditions => u32::from_ne_bytes(*b"view").to_be(), + TagTypeDefinition::Signature => u32::from_ne_bytes(*b"sig ").to_be(), + TagTypeDefinition::Cicp => u32::from_ne_bytes(*b"cicp").to_be(), + TagTypeDefinition::DateTime => u32::from_ne_bytes(*b"dtim").to_be(), + TagTypeDefinition::S15Fixed16Array => u32::from_ne_bytes(*b"sf32").to_be(), + TagTypeDefinition::U16Fixed16Array => u32::from_ne_bytes(*b"uf32").to_be(), + TagTypeDefinition::U8Array => u32::from_ne_bytes(*b"ui08").to_be(), + TagTypeDefinition::U16Array => u32::from_ne_bytes(*b"ui16").to_be(), + TagTypeDefinition::U32Array => u32::from_ne_bytes(*b"ui32").to_be(), + TagTypeDefinition::U64Array => u32::from_ne_bytes(*b"ui64").to_be(), + TagTypeDefinition::Measurement => u32::from_ne_bytes(*b"meas").to_be(), + TagTypeDefinition::NotAllowed => 0, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/transform.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/transform.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/transform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1334 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::conversions::{ + LutBarycentricReduction, RgbXyzFactory, RgbXyzFactoryOpt, ToneReproductionRgbToGray, + TransformMatrixShaper, make_gray_to_unfused, make_gray_to_x, make_lut_transform, + make_rgb_to_gray, +}; +use crate::err::CmsError; +use crate::trc::GammaLutInterpolate; +use crate::{ColorProfile, DataColorSpace, LutWarehouse, RenderingIntent, Vector3f, Xyzd}; +use num_traits::AsPrimitive; +use std::marker::PhantomData; + +/// Transformation executor itself +pub trait TransformExecutor { + /// Count of samples always must match. + /// If there is N samples of *Cmyk* source then N samples of *Rgb* is expected as an output. + fn transform(&self, src: &[V], dst: &mut [V]) -> Result<(), CmsError>; +} + +/// Helper for intermediate transformation stages +pub trait Stage { + fn transform(&self, src: &[f32], dst: &mut [f32]) -> Result<(), CmsError>; +} + +/// Helper for intermediate transformation stages +pub trait InPlaceStage { + fn transform(&self, dst: &mut [f32]) -> Result<(), CmsError>; +} + +/// Barycentric interpolation weights size. +/// +/// Bigger weights increases precision. +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)] +pub enum BarycentricWeightScale { + #[default] + /// Low scale weights is enough for common case. + /// + /// However, it might crush dark zones and gradients. + /// Weights increasing costs 5% performance. + Low, + #[cfg(feature = "options")] + High, +} + +/// Declares additional transformation options +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct TransformOptions { + pub rendering_intent: RenderingIntent, + /// If set it will try to use Transfer Characteristics from CICP + /// on transform. This might be more precise and faster. + pub allow_use_cicp_transfer: bool, + /// Prefers fixed point where implemented as default. + /// Most of the applications actually do not need floating point. + /// + /// Do not change it if you're not sure that extreme precision is required, + /// in most cases it is a simple way to spend energy to warming up environment + /// a little. + /// + /// Q2.13 for RGB->XYZ->RGB is used. + /// LUT interpolation use Q0.15. + pub prefer_fixed_point: bool, + /// Interpolation method for 3D LUT + /// + /// This parameter has no effect on LAB/XYZ interpolation and scene linear RGB. + /// + /// Technically, it should be assumed to perform cube dividing interpolation: + /// - Source colorspace is gamma-encoded (discards scene linear RGB and XYZ). + /// - Colorspace is uniform. + /// - Colorspace has linear scaling (discards LAB). + /// - Interpolation doesn't shift hues (discards LAB). + /// + /// For LAB, XYZ and scene linear RGB `trilinear/quadlinear` always in force. + pub interpolation_method: InterpolationMethod, + /// Barycentric weights scale. + /// + /// This value controls LUT weights precision. + pub barycentric_weight_scale: BarycentricWeightScale, + /// For floating points transform, it will try to detect gamma function on *Matrix Shaper* profiles. + /// If gamma function is found, then it will be used instead of LUT table. + /// This allows to work with excellent precision with extended range, + /// at a cost of execution time. + pub allow_extended_range_rgb_xyz: bool, + // pub black_point_compensation: bool, +} + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)] +/// Defines the interpolation method. +/// +/// All methods produce very close results that almost not possible to separate without +/// some automation tools. +/// +/// This implementation chooses the fastest method as default. +pub enum InterpolationMethod { + /// General Tetrahedron interpolation. + /// This is used in lcms2 and others CMS. + #[cfg(feature = "options")] + Tetrahedral, + /// Divides cube into a pyramids and interpolate then in the pyramid. + #[cfg(feature = "options")] + Pyramid, + /// Interpolation by dividing cube into prisms. + #[cfg(feature = "options")] + Prism, + /// Trilinear/Quadlinear interpolation + #[default] + Linear, +} + +impl Default for TransformOptions { + fn default() -> Self { + Self { + rendering_intent: RenderingIntent::default(), + allow_use_cicp_transfer: true, + prefer_fixed_point: true, + interpolation_method: InterpolationMethod::default(), + barycentric_weight_scale: BarycentricWeightScale::default(), + allow_extended_range_rgb_xyz: false, + // black_point_compensation: false, + } + } +} + +pub type Transform8BitExecutor = dyn TransformExecutor + Send + Sync; +pub type Transform16BitExecutor = dyn TransformExecutor + Send + Sync; +pub type TransformF32BitExecutor = dyn TransformExecutor + Send + Sync; +pub type TransformF64BitExecutor = dyn TransformExecutor + Send + Sync; + +/// Layout declares a data layout. +/// For RGB it shows also the channel order. +/// To handle different data bit-depth appropriate executor must be used. +/// Cmyk8 uses the same layout as Rgba8. +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum Layout { + Rgb = 0, + Rgba = 1, + Gray = 2, + GrayAlpha = 3, + Inks5 = 4, + Inks6 = 5, + Inks7 = 6, + Inks8 = 7, + Inks9 = 8, + Inks10 = 9, + Inks11 = 10, + Inks12 = 11, + Inks13 = 12, + Inks14 = 13, + Inks15 = 14, +} + +impl Layout { + /// Returns Red channel index + #[inline(always)] + pub const fn r_i(self) -> usize { + match self { + Layout::Rgb => 0, + Layout::Rgba => 0, + Layout::Gray => unimplemented!(), + Layout::GrayAlpha => unimplemented!(), + _ => unimplemented!(), + } + } + + /// Returns Green channel index + #[inline(always)] + pub const fn g_i(self) -> usize { + match self { + Layout::Rgb => 1, + Layout::Rgba => 1, + Layout::Gray => unimplemented!(), + Layout::GrayAlpha => unimplemented!(), + _ => unimplemented!(), + } + } + + /// Returns Blue channel index + #[inline(always)] + pub const fn b_i(self) -> usize { + match self { + Layout::Rgb => 2, + Layout::Rgba => 2, + Layout::Gray => unimplemented!(), + Layout::GrayAlpha => unimplemented!(), + _ => unimplemented!(), + } + } + + #[inline(always)] + pub const fn a_i(self) -> usize { + match self { + Layout::Rgb => unimplemented!(), + Layout::Rgba => 3, + Layout::Gray => unimplemented!(), + Layout::GrayAlpha => 1, + _ => unimplemented!(), + } + } + + #[inline(always)] + pub const fn has_alpha(self) -> bool { + match self { + Layout::Rgb => false, + Layout::Rgba => true, + Layout::Gray => false, + Layout::GrayAlpha => true, + _ => false, + } + } + + #[inline] + pub const fn channels(self) -> usize { + match self { + Layout::Rgb => 3, + Layout::Rgba => 4, + Layout::Gray => 1, + Layout::GrayAlpha => 2, + Layout::Inks5 => 5, + Layout::Inks6 => 6, + Layout::Inks7 => 7, + Layout::Inks8 => 8, + Layout::Inks9 => 9, + Layout::Inks10 => 10, + Layout::Inks11 => 11, + Layout::Inks12 => 12, + Layout::Inks13 => 13, + Layout::Inks14 => 14, + Layout::Inks15 => 15, + } + } + + pub(crate) fn from_inks(inks: usize) -> Self { + match inks { + 1 => Layout::Gray, + 2 => Layout::GrayAlpha, + 3 => Layout::Rgb, + 4 => Layout::Rgba, + 5 => Layout::Inks5, + 6 => Layout::Inks6, + 7 => Layout::Inks7, + 8 => Layout::Inks8, + 9 => Layout::Inks9, + 10 => Layout::Inks10, + 11 => Layout::Inks11, + 12 => Layout::Inks12, + 13 => Layout::Inks13, + 14 => Layout::Inks14, + 15 => Layout::Inks15, + _ => unreachable!("Impossible amount of inks"), + } + } +} + +impl From for Layout { + fn from(value: u8) -> Self { + match value { + 0 => Layout::Rgb, + 1 => Layout::Rgba, + 2 => Layout::Gray, + 3 => Layout::GrayAlpha, + _ => unimplemented!(), + } + } +} + +impl Layout { + #[inline(always)] + pub const fn resolve(value: u8) -> Self { + match value { + 0 => Layout::Rgb, + 1 => Layout::Rgba, + 2 => Layout::Gray, + 3 => Layout::GrayAlpha, + 4 => Layout::Inks5, + 5 => Layout::Inks6, + 6 => Layout::Inks7, + 7 => Layout::Inks8, + 8 => Layout::Inks9, + 9 => Layout::Inks10, + 10 => Layout::Inks11, + 11 => Layout::Inks12, + 12 => Layout::Inks13, + 13 => Layout::Inks14, + 14 => Layout::Inks15, + _ => unimplemented!(), + } + } +} + +#[doc(hidden)] +pub trait PointeeSizeExpressible { + fn _as_usize(self) -> usize; + const FINITE: bool; + const NOT_FINITE_GAMMA_TABLE_SIZE: usize; + const NOT_FINITE_LINEAR_TABLE_SIZE: usize; + const IS_U8: bool; + const IS_U16: bool; +} + +impl PointeeSizeExpressible for u8 { + #[inline(always)] + fn _as_usize(self) -> usize { + self as usize + } + + const FINITE: bool = true; + const NOT_FINITE_GAMMA_TABLE_SIZE: usize = 1; + const NOT_FINITE_LINEAR_TABLE_SIZE: usize = 1; + const IS_U8: bool = true; + const IS_U16: bool = false; +} + +impl PointeeSizeExpressible for u16 { + #[inline(always)] + fn _as_usize(self) -> usize { + self as usize + } + + const FINITE: bool = true; + + const NOT_FINITE_GAMMA_TABLE_SIZE: usize = 1; + const NOT_FINITE_LINEAR_TABLE_SIZE: usize = 1; + + const IS_U8: bool = false; + const IS_U16: bool = true; +} + +impl PointeeSizeExpressible for f32 { + #[inline(always)] + fn _as_usize(self) -> usize { + const MAX_14_BIT: f32 = ((1 << 14u32) - 1) as f32; + ((self * MAX_14_BIT).max(0f32).min(MAX_14_BIT) as u16) as usize + } + + const FINITE: bool = false; + + const NOT_FINITE_GAMMA_TABLE_SIZE: usize = 32768; + const NOT_FINITE_LINEAR_TABLE_SIZE: usize = 1 << 14u32; + const IS_U8: bool = false; + const IS_U16: bool = false; +} + +impl PointeeSizeExpressible for f64 { + #[inline(always)] + fn _as_usize(self) -> usize { + const MAX_16_BIT: f64 = ((1 << 16u32) - 1) as f64; + ((self * MAX_16_BIT).max(0.).min(MAX_16_BIT) as u16) as usize + } + + const FINITE: bool = false; + + const NOT_FINITE_GAMMA_TABLE_SIZE: usize = 65536; + const NOT_FINITE_LINEAR_TABLE_SIZE: usize = 1 << 16; + const IS_U8: bool = false; + const IS_U16: bool = false; +} + +impl ColorProfile { + /// Checks if profile is valid *Matrix Shaper* profile + pub fn is_matrix_shaper(&self) -> bool { + self.color_space == DataColorSpace::Rgb + && self.red_colorant != Xyzd::default() + && self.green_colorant != Xyzd::default() + && self.blue_colorant != Xyzd::default() + && self.red_trc.is_some() + && self.green_trc.is_some() + && self.blue_trc.is_some() + } + + /// Creates transform between source and destination profile + /// Use for 16 bit-depth data bit-depth only. + pub fn create_transform_16bit( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + /// Creates transform between source and destination profile + /// Use for 12 bit-depth data bit-depth only. + pub fn create_transform_12bit( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + /// Creates transform between source and destination profile + /// Use for 10 bit-depth data bit-depth only. + pub fn create_transform_10bit( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + /// Creates transform between source and destination profile + /// Data has to be normalized into [0, 1] range. + /// ICC profiles and LUT tables do not exist in infinite precision. + /// Thus, this implementation considers `f32` as 14-bit values. + /// Floating point transformer works in extended mode, that means returned data might be negative + /// or more than 1. + pub fn create_transform_f32( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + /// Creates transform between source and destination profile + /// Data has to be normalized into [0, 1] range. + /// ICC profiles and LUT tables do not exist in infinite precision. + /// Thus, this implementation considers `f64` as 16-bit values. + /// Floating point transformer works in extended mode, that means returned data might be negative + /// or more than 1. + pub fn create_transform_f64( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + fn create_transform_nbit< + T: Copy + + Default + + AsPrimitive + + PointeeSizeExpressible + + Send + + Sync + + AsPrimitive + + RgbXyzFactory + + RgbXyzFactoryOpt + + GammaLutInterpolate, + const BIT_DEPTH: usize, + const LINEAR_CAP: usize, + const GAMMA_CAP: usize, + >( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result + Send + Sync>, CmsError> + where + f32: AsPrimitive, + u32: AsPrimitive, + (): LutBarycentricReduction, + (): LutBarycentricReduction, + { + if self.color_space == DataColorSpace::Rgb + && dst_pr.pcs == DataColorSpace::Xyz + && dst_pr.color_space == DataColorSpace::Rgb + && self.pcs == DataColorSpace::Xyz + && self.is_matrix_shaper() + && dst_pr.is_matrix_shaper() + { + if src_layout == Layout::Gray || src_layout == Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + if dst_layout == Layout::Gray || dst_layout == Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + + if self.has_device_to_pcs_lut() || dst_pr.has_pcs_to_device_lut() { + return make_lut_transform::( + src_layout, self, dst_layout, dst_pr, options, + ); + } + + let transform = self.transform_matrix(dst_pr); + + if !T::FINITE && options.allow_extended_range_rgb_xyz { + if let Some(gamma_evaluator) = dst_pr.try_extended_gamma_evaluator() { + if let Some(linear_evaluator) = self.try_extended_linearizing_evaluator() { + use crate::conversions::{ + TransformShaperFloatInOut, make_rgb_xyz_rgb_transform_float_in_out, + }; + let p = TransformShaperFloatInOut { + linear_evaluator, + gamma_evaluator, + adaptation_matrix: transform.to_f32(), + phantom_data: PhantomData, + }; + return make_rgb_xyz_rgb_transform_float_in_out::( + src_layout, dst_layout, p, BIT_DEPTH, + ); + } + + let lin_r = self.build_r_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_g = self.build_g_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_b = self.build_b_linearize_table::( + options.allow_use_cicp_transfer, + )?; + + use crate::conversions::{ + TransformShaperRgbFloat, make_rgb_xyz_rgb_transform_float, + }; + let p = TransformShaperRgbFloat { + r_linear: lin_r, + g_linear: lin_g, + b_linear: lin_b, + gamma_evaluator, + adaptation_matrix: transform.to_f32(), + phantom_data: PhantomData, + }; + return make_rgb_xyz_rgb_transform_float::( + src_layout, dst_layout, p, BIT_DEPTH, + ); + } + } + + if self.are_all_trc_the_same() && dst_pr.are_all_trc_the_same() { + let linear = self.build_r_linearize_table::( + options.allow_use_cicp_transfer, + )?; + + let gamma = dst_pr.build_gamma_table::( + &dst_pr.red_trc, + options.allow_use_cicp_transfer, + )?; + + let profile_transform = crate::conversions::TransformMatrixShaperOptimized { + linear, + gamma, + adaptation_matrix: transform.to_f32(), + }; + + return T::make_optimized_transform::( + src_layout, + dst_layout, + profile_transform, + options, + ); + } + + let lin_r = self.build_r_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_g = self.build_g_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_b = self.build_b_linearize_table::( + options.allow_use_cicp_transfer, + )?; + + let gamma_r = dst_pr.build_gamma_table::( + &dst_pr.red_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_g = dst_pr.build_gamma_table::( + &dst_pr.green_trc, + options.allow_use_cicp_transfer, + )?; + let gamma_b = dst_pr.build_gamma_table::( + &dst_pr.blue_trc, + options.allow_use_cicp_transfer, + )?; + + let profile_transform = TransformMatrixShaper { + r_linear: lin_r, + g_linear: lin_g, + b_linear: lin_b, + r_gamma: gamma_r, + g_gamma: gamma_g, + b_gamma: gamma_b, + adaptation_matrix: transform.to_f32(), + }; + + T::make_transform::( + src_layout, + dst_layout, + profile_transform, + options, + ) + } else if (self.color_space == DataColorSpace::Gray && self.gray_trc.is_some()) + && (dst_pr.color_space == DataColorSpace::Rgb + || (dst_pr.color_space == DataColorSpace::Gray && dst_pr.gray_trc.is_some())) + && self.pcs == DataColorSpace::Xyz + && dst_pr.pcs == DataColorSpace::Xyz + { + if src_layout != Layout::GrayAlpha && src_layout != Layout::Gray { + return Err(CmsError::InvalidLayout); + } + + if self.has_device_to_pcs_lut() || dst_pr.has_pcs_to_device_lut() { + return make_lut_transform::( + src_layout, self, dst_layout, dst_pr, options, + ); + } + + let gray_linear = self.build_gray_linearize_table::()?; + + if dst_pr.color_space == DataColorSpace::Gray { + if !T::FINITE && options.allow_extended_range_rgb_xyz { + if let Some(gamma_evaluator) = dst_pr.try_extended_gamma_evaluator() { + if let Some(linear_evaluator) = self.try_extended_linearizing_evaluator() { + // Gray -> Gray case extended range + use crate::conversions::make_gray_to_one_trc_extended; + return make_gray_to_one_trc_extended::( + src_layout, + dst_layout, + linear_evaluator, + gamma_evaluator, + BIT_DEPTH, + ); + } + } + } + + // Gray -> Gray case + let gray_gamma = dst_pr.build_gamma_table::( + &dst_pr.gray_trc, + options.allow_use_cicp_transfer, + )?; + + make_gray_to_x::( + src_layout, + dst_layout, + &gray_linear, + &gray_gamma, + BIT_DEPTH, + GAMMA_CAP, + ) + } else { + #[allow(clippy::collapsible_if)] + if dst_pr.are_all_trc_the_same() { + if !T::FINITE && options.allow_extended_range_rgb_xyz { + if let Some(gamma_evaluator) = dst_pr.try_extended_gamma_evaluator() { + if let Some(linear_evaluator) = + self.try_extended_linearizing_evaluator() + { + // Gray -> RGB where all TRC is the same with extended range + use crate::conversions::make_gray_to_one_trc_extended; + return make_gray_to_one_trc_extended::( + src_layout, + dst_layout, + linear_evaluator, + gamma_evaluator, + BIT_DEPTH, + ); + } + } + } + + // Gray -> RGB where all TRC is the same + let rgb_gamma = dst_pr.build_gamma_table::( + &dst_pr.red_trc, + options.allow_use_cicp_transfer, + )?; + + make_gray_to_x::( + src_layout, + dst_layout, + &gray_linear, + &rgb_gamma, + BIT_DEPTH, + GAMMA_CAP, + ) + } else { + // Gray -> RGB where all TRC is NOT the same + if !T::FINITE && options.allow_extended_range_rgb_xyz { + if let Some(gamma_evaluator) = dst_pr.try_extended_gamma_evaluator() { + if let Some(linear_evaluator) = + self.try_extended_linearizing_evaluator() + { + // Gray -> RGB where all TRC is NOT the same with extended range + + use crate::conversions::make_gray_to_rgb_extended; + return make_gray_to_rgb_extended::( + src_layout, + dst_layout, + linear_evaluator, + gamma_evaluator, + BIT_DEPTH, + ); + } + } + } + + let red_gamma = dst_pr.build_gamma_table::( + &dst_pr.red_trc, + options.allow_use_cicp_transfer, + )?; + let green_gamma = dst_pr.build_gamma_table::( + &dst_pr.green_trc, + options.allow_use_cicp_transfer, + )?; + let blue_gamma = dst_pr.build_gamma_table::( + &dst_pr.blue_trc, + options.allow_use_cicp_transfer, + )?; + + let mut gray_linear2 = Box::new([0f32; 65536]); + for (dst, src) in gray_linear2.iter_mut().zip(gray_linear.iter()) { + *dst = *src; + } + + make_gray_to_unfused::( + src_layout, + dst_layout, + gray_linear2, + red_gamma, + green_gamma, + blue_gamma, + BIT_DEPTH, + GAMMA_CAP, + ) + } + } + } else if self.color_space == DataColorSpace::Rgb + && (dst_pr.color_space == DataColorSpace::Gray && dst_pr.gray_trc.is_some()) + && dst_pr.pcs == DataColorSpace::Xyz + && self.pcs == DataColorSpace::Xyz + { + if src_layout == Layout::Gray || src_layout == Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + if dst_layout != Layout::Gray && dst_layout != Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + + if self.has_device_to_pcs_lut() || dst_pr.has_pcs_to_device_lut() { + return make_lut_transform::( + src_layout, self, dst_layout, dst_pr, options, + ); + } + + let transform = self.transform_matrix(dst_pr).to_f32(); + + let vector = Vector3f { + v: [transform.v[1][0], transform.v[1][1], transform.v[1][2]], + }; + + if !T::FINITE && options.allow_extended_range_rgb_xyz { + if let Some(gamma_evaluator) = dst_pr.try_extended_gamma_evaluator() { + if let Some(linear_evaluator) = self.try_extended_linearizing_evaluator() { + use crate::conversions::make_rgb_to_gray_extended; + return make_rgb_to_gray_extended::( + src_layout, + dst_layout, + linear_evaluator, + gamma_evaluator, + vector, + BIT_DEPTH, + ); + } + } + } + + let lin_r = self.build_r_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_g = self.build_g_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let lin_b = self.build_b_linearize_table::( + options.allow_use_cicp_transfer, + )?; + let gray_linear = dst_pr.build_gamma_table::( + &dst_pr.gray_trc, + options.allow_use_cicp_transfer, + )?; + + let trc_box = ToneReproductionRgbToGray:: { + r_linear: lin_r, + g_linear: lin_g, + b_linear: lin_b, + gray_gamma: gray_linear, + }; + + make_rgb_to_gray::( + src_layout, dst_layout, trc_box, vector, GAMMA_CAP, BIT_DEPTH, + ) + } else if (self.color_space.is_three_channels() + || self.color_space == DataColorSpace::Cmyk + || self.color_space == DataColorSpace::Color4) + && (dst_pr.color_space.is_three_channels() + || dst_pr.color_space == DataColorSpace::Cmyk + || dst_pr.color_space == DataColorSpace::Color4) + && (dst_pr.pcs == DataColorSpace::Xyz || dst_pr.pcs == DataColorSpace::Lab) + && (self.pcs == DataColorSpace::Xyz || self.pcs == DataColorSpace::Lab) + { + if src_layout == Layout::Gray || src_layout == Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + if dst_layout == Layout::Gray || dst_layout == Layout::GrayAlpha { + return Err(CmsError::InvalidLayout); + } + make_lut_transform::( + src_layout, self, dst_layout, dst_pr, options, + ) + } else { + make_lut_transform::( + src_layout, self, dst_layout, dst_pr, options, + ) + } + } + + /// Creates transform between source and destination profile + /// Only 8 bit is supported. + pub fn create_transform_8bit( + &self, + src_layout: Layout, + dst_pr: &ColorProfile, + dst_layout: Layout, + options: TransformOptions, + ) -> Result, CmsError> { + self.create_transform_nbit::(src_layout, dst_pr, dst_layout, options) + } + + pub(crate) fn get_device_to_pcs(&self, intent: RenderingIntent) -> Option<&LutWarehouse> { + match intent { + RenderingIntent::AbsoluteColorimetric => self.lut_a_to_b_colorimetric.as_ref(), + RenderingIntent::Saturation => self.lut_a_to_b_saturation.as_ref(), + RenderingIntent::RelativeColorimetric => self.lut_a_to_b_colorimetric.as_ref(), + RenderingIntent::Perceptual => self.lut_a_to_b_perceptual.as_ref(), + } + } + + pub(crate) fn get_pcs_to_device(&self, intent: RenderingIntent) -> Option<&LutWarehouse> { + match intent { + RenderingIntent::AbsoluteColorimetric => self.lut_b_to_a_colorimetric.as_ref(), + RenderingIntent::Saturation => self.lut_b_to_a_saturation.as_ref(), + RenderingIntent::RelativeColorimetric => self.lut_b_to_a_colorimetric.as_ref(), + RenderingIntent::Perceptual => self.lut_b_to_a_perceptual.as_ref(), + } + } +} + +#[cfg(test)] +mod tests { + use crate::{ColorProfile, DataColorSpace, Layout, RenderingIntent, TransformOptions}; + use rand::Rng; + + #[test] + fn test_transform_rgb8() { + let mut srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..255); + let transform = bt2020_profile + .create_transform_8bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256 * 3]; + let mut dst = vec![random_point_x; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + + let transform = bt2020_profile + .create_transform_8bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions { + ..TransformOptions::default() + }, + ) + .unwrap(); + transform.transform(&src, &mut dst).unwrap(); + srgb_profile.rendering_intent = RenderingIntent::RelativeColorimetric; + let transform = bt2020_profile + .create_transform_8bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions { + ..TransformOptions::default() + }, + ) + .unwrap(); + transform.transform(&src, &mut dst).unwrap(); + srgb_profile.rendering_intent = RenderingIntent::Saturation; + let transform = bt2020_profile + .create_transform_8bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions { + ..TransformOptions::default() + }, + ) + .unwrap(); + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_rgba8() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..255); + let transform = bt2020_profile + .create_transform_8bit( + Layout::Rgba, + &srgb_profile, + Layout::Rgba, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256 * 4]; + let mut dst = vec![random_point_x; 256 * 256 * 4]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_gray_to_rgb8() { + let gray_profile = ColorProfile::new_gray_with_gamma(2.2f32); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..255); + let transform = gray_profile + .create_transform_8bit( + Layout::Gray, + &bt2020_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256]; + let mut dst = vec![random_point_x; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_gray_to_rgba8() { + let srgb_profile = ColorProfile::new_gray_with_gamma(2.2f32); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..255); + let transform = srgb_profile + .create_transform_8bit( + Layout::Gray, + &bt2020_profile, + Layout::Rgba, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256]; + let mut dst = vec![random_point_x; 256 * 256 * 4]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_gray_to_gray_alpha8() { + let srgb_profile = ColorProfile::new_gray_with_gamma(2.2f32); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..255); + let transform = srgb_profile + .create_transform_8bit( + Layout::Gray, + &bt2020_profile, + Layout::GrayAlpha, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256]; + let mut dst = vec![random_point_x; 256 * 256 * 2]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_rgb10() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..((1 << 10) - 1)); + let transform = bt2020_profile + .create_transform_10bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256 * 3]; + let mut dst = vec![random_point_x; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_rgb12() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..((1 << 12) - 1)); + let transform = bt2020_profile + .create_transform_12bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256 * 3]; + let mut dst = vec![random_point_x; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_rgb16() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let random_point_x = rand::rng().random_range(0..((1u32 << 16u32) - 1u32)) as u16; + let transform = bt2020_profile + .create_transform_16bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let src = vec![random_point_x; 256 * 256 * 3]; + let mut dst = vec![random_point_x; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + } + + #[test] + fn test_transform_round_trip_rgb8() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let transform = srgb_profile + .create_transform_8bit( + Layout::Rgb, + &bt2020_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let mut src = vec![0u8; 256 * 256 * 3]; + for dst in src.chunks_exact_mut(3) { + dst[0] = 175; + dst[1] = 75; + dst[2] = 13; + } + let mut dst = vec![0u8; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + + let transform_inverse = bt2020_profile + .create_transform_8bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + + transform_inverse.transform(&dst, &mut src).unwrap(); + + for src in src.chunks_exact_mut(3) { + let diff0 = (src[0] as i32 - 175).abs(); + let diff1 = (src[1] as i32 - 75).abs(); + let diff2 = (src[2] as i32 - 13).abs(); + assert!( + diff0 < 3, + "On channel 0 difference should be less than 3, but it was {diff0}" + ); + assert!( + diff1 < 3, + "On channel 1 difference should be less than 3, but it was {diff1}" + ); + assert!( + diff2 < 3, + "On channel 2 difference should be less than 3, but it was {diff2}" + ); + } + } + + #[test] + fn test_transform_round_trip_rgb10() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let transform = srgb_profile + .create_transform_10bit( + Layout::Rgb, + &bt2020_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let mut src = vec![0u16; 256 * 256 * 3]; + for dst in src.chunks_exact_mut(3) { + dst[0] = 175; + dst[1] = 256; + dst[2] = 512; + } + let mut dst = vec![0u16; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + + let transform_inverse = bt2020_profile + .create_transform_10bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + + transform_inverse.transform(&dst, &mut src).unwrap(); + + for src in src.chunks_exact_mut(3) { + let diff0 = (src[0] as i32 - 175).abs(); + let diff1 = (src[1] as i32 - 256).abs(); + let diff2 = (src[2] as i32 - 512).abs(); + assert!( + diff0 < 15, + "On channel 0 difference should be less than 15, but it was {diff0}" + ); + assert!( + diff1 < 15, + "On channel 1 difference should be less than 15, but it was {diff1}" + ); + assert!( + diff2 < 15, + "On channel 2 difference should be less than 15, but it was {diff2}" + ); + } + } + + #[test] + fn test_transform_round_trip_rgb12() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let transform = srgb_profile + .create_transform_12bit( + Layout::Rgb, + &bt2020_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let mut src = vec![0u16; 256 * 256 * 3]; + for dst in src.chunks_exact_mut(3) { + dst[0] = 1750; + dst[1] = 2560; + dst[2] = 3143; + } + let mut dst = vec![0u16; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + + let transform_inverse = bt2020_profile + .create_transform_12bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + + transform_inverse.transform(&dst, &mut src).unwrap(); + + for src in src.chunks_exact_mut(3) { + let diff0 = (src[0] as i32 - 1750).abs(); + let diff1 = (src[1] as i32 - 2560).abs(); + let diff2 = (src[2] as i32 - 3143).abs(); + assert!( + diff0 < 25, + "On channel 0 difference should be less than 25, but it was {diff0}" + ); + assert!( + diff1 < 25, + "On channel 1 difference should be less than 25, but it was {diff1}" + ); + assert!( + diff2 < 25, + "On channel 2 difference should be less than 25, but it was {diff2}" + ); + } + } + + #[test] + fn test_transform_round_trip_rgb16() { + let srgb_profile = ColorProfile::new_srgb(); + let bt2020_profile = ColorProfile::new_bt2020(); + let transform = srgb_profile + .create_transform_16bit( + Layout::Rgb, + &bt2020_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + let mut src = vec![0u16; 256 * 256 * 3]; + for dst in src.chunks_exact_mut(3) { + dst[0] = 1760; + dst[1] = 2560; + dst[2] = 5120; + } + let mut dst = vec![0u16; 256 * 256 * 3]; + transform.transform(&src, &mut dst).unwrap(); + + let transform_inverse = bt2020_profile + .create_transform_16bit( + Layout::Rgb, + &srgb_profile, + Layout::Rgb, + TransformOptions::default(), + ) + .unwrap(); + + transform_inverse.transform(&dst, &mut src).unwrap(); + + for src in src.chunks_exact_mut(3) { + let diff0 = (src[0] as i32 - 1760).abs(); + let diff1 = (src[1] as i32 - 2560).abs(); + let diff2 = (src[2] as i32 - 5120).abs(); + assert!( + diff0 < 35, + "On channel 0 difference should be less than 35, but it was {diff0}" + ); + assert!( + diff1 < 35, + "On channel 1 difference should be less than 35, but it was {diff1}" + ); + assert!( + diff2 < 35, + "On channel 2 difference should be less than 35, but it was {diff2}" + ); + } + } + + #[test] + fn test_transform_rgb_to_gray_extended() { + let srgb = ColorProfile::new_srgb(); + let mut gray_profile = ColorProfile::new_gray_with_gamma(1.0); + gray_profile.color_space = DataColorSpace::Gray; + gray_profile.gray_trc = srgb.red_trc.clone(); + let mut test_profile = vec![0.; 4]; + test_profile[2] = 1.; + let mut dst = vec![0.; 1]; + + let mut inverse = vec![0.; 4]; + + let cvt0 = srgb + .create_transform_f32( + Layout::Rgba, + &gray_profile, + Layout::Gray, + TransformOptions { + allow_extended_range_rgb_xyz: true, + ..Default::default() + }, + ) + .unwrap(); + cvt0.transform(&test_profile, &mut dst).unwrap(); + assert!((dst[0] - 0.273046) < 1e-4); + + let cvt_inverse = gray_profile + .create_transform_f32( + Layout::Gray, + &srgb, + Layout::Rgba, + TransformOptions { + allow_extended_range_rgb_xyz: false, + ..Default::default() + }, + ) + .unwrap(); + cvt_inverse.transform(&dst, &mut inverse).unwrap(); + assert!((inverse[0] - 0.273002833) < 1e-4); + + let cvt1 = srgb + .create_transform_f32( + Layout::Rgba, + &gray_profile, + Layout::Gray, + TransformOptions { + allow_extended_range_rgb_xyz: false, + ..Default::default() + }, + ) + .unwrap(); + cvt1.transform(&test_profile, &mut dst).unwrap(); + assert!((dst[0] - 0.27307168) < 1e-5); + + inverse.fill(0.); + + let cvt_inverse = gray_profile + .create_transform_f32( + Layout::Gray, + &srgb, + Layout::Rgba, + TransformOptions { + allow_extended_range_rgb_xyz: true, + ..Default::default() + }, + ) + .unwrap(); + cvt_inverse.transform(&dst, &mut inverse).unwrap(); + assert!((inverse[0] - 0.273002833) < 1e-4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/trc.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/trc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/trc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/trc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1583 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 2/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::cicp::create_rec709_parametric; +use crate::matan::is_curve_linear16; +use crate::math::m_clamp; +use crate::mlaf::{mlaf, neg_mlaf}; +use crate::transform::PointeeSizeExpressible; +use crate::writer::FloatToFixedU8Fixed8; +use crate::{CmsError, ColorProfile, DataColorSpace, Rgb, TransferCharacteristics}; +use num_traits::AsPrimitive; +use pxfm::{dirty_powf, f_pow, f_powf}; + +#[derive(Clone, Debug, PartialEq)] +pub enum ToneReprCurve { + Lut(Vec), + Parametric(Vec), +} + +impl ToneReprCurve { + pub fn inverse(&self) -> Result { + match self { + ToneReprCurve::Lut(lut) => { + let inverse_length = lut.len().max(256); + Ok(ToneReprCurve::Lut(invert_lut(lut, inverse_length))) + } + ToneReprCurve::Parametric(parametric) => ParametricCurve::new(parametric) + .and_then(|x| x.invert()) + .map(|x| ToneReprCurve::Parametric([x.g, x.a, x.b, x.c, x.d, x.e, x.f].to_vec())) + .ok_or(CmsError::BuildTransferFunction), + } + } + + /// Creates tone curve evaluator + pub fn make_linear_evaluator( + &self, + ) -> Result, CmsError> { + match self { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return Ok(Box::new(ToneCurveEvaluatorLinear {})); + } + if lut.len() == 1 { + let gamma = u8_fixed_8number_to_float(lut[0]); + return Ok(Box::new(ToneCurveEvaluatorPureGamma { gamma })); + } + let converted_curve = lut.iter().map(|&x| x as f32 / 65535.0).collect::>(); + Ok(Box::new(ToneCurveLutEvaluator { + lut: converted_curve, + })) + } + ToneReprCurve::Parametric(parametric) => { + let parametric_curve = + ParametricCurve::new(parametric).ok_or(CmsError::BuildTransferFunction)?; + Ok(Box::new(ToneCurveParametricEvaluator { + parametric: parametric_curve, + })) + } + } + } + + /// Creates tone curve evaluator from transfer characteristics + pub fn make_cicp_linear_evaluator( + transfer_characteristics: TransferCharacteristics, + ) -> Result, CmsError> { + if !transfer_characteristics.has_transfer_curve() { + return Err(CmsError::BuildTransferFunction); + } + Ok(Box::new(ToneCurveCicpLinearEvaluator { + trc: transfer_characteristics, + })) + } + + /// Creates tone curve inverse evaluator + pub fn make_gamma_evaluator( + &self, + ) -> Result, CmsError> { + match self { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return Ok(Box::new(ToneCurveEvaluatorLinear {})); + } + if lut.len() == 1 { + let gamma = 1. / u8_fixed_8number_to_float(lut[0]); + return Ok(Box::new(ToneCurveEvaluatorPureGamma { gamma })); + } + let inverted_lut = invert_lut(lut, 16384); + let converted_curve = inverted_lut + .iter() + .map(|&x| x as f32 / 65535.0) + .collect::>(); + Ok(Box::new(ToneCurveLutEvaluator { + lut: converted_curve, + })) + } + ToneReprCurve::Parametric(parametric) => { + let parametric_curve = ParametricCurve::new(parametric) + .and_then(|x| x.invert()) + .ok_or(CmsError::BuildTransferFunction)?; + Ok(Box::new(ToneCurveParametricEvaluator { + parametric: parametric_curve, + })) + } + } + } + + /// Creates tone curve inverse evaluator from transfer characteristics + pub fn make_cicp_gamma_evaluator( + transfer_characteristics: TransferCharacteristics, + ) -> Result, CmsError> { + if !transfer_characteristics.has_transfer_curve() { + return Err(CmsError::BuildTransferFunction); + } + Ok(Box::new(ToneCurveCicpGammaEvaluator { + trc: transfer_characteristics, + })) + } +} + +struct ToneCurveCicpLinearEvaluator { + trc: TransferCharacteristics, +} + +struct ToneCurveCicpGammaEvaluator { + trc: TransferCharacteristics, +} + +impl ToneCurveEvaluator for ToneCurveCicpLinearEvaluator { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + Rgb::new( + self.trc.linearize(rgb.r as f64) as f32, + self.trc.linearize(rgb.g as f64) as f32, + self.trc.linearize(rgb.b as f64) as f32, + ) + } + + fn evaluate_value(&self, value: f32) -> f32 { + self.trc.linearize(value as f64) as f32 + } +} + +impl ToneCurveEvaluator for ToneCurveCicpGammaEvaluator { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + Rgb::new( + self.trc.gamma(rgb.r as f64) as f32, + self.trc.gamma(rgb.g as f64) as f32, + self.trc.gamma(rgb.b as f64) as f32, + ) + } + + fn evaluate_value(&self, value: f32) -> f32 { + self.trc.gamma(value as f64) as f32 + } +} + +struct ToneCurveLutEvaluator { + lut: Vec, +} + +impl ToneCurveEvaluator for ToneCurveLutEvaluator { + fn evaluate_value(&self, value: f32) -> f32 { + lut_interp_linear_float(value, &self.lut) + } + + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + Rgb::new( + lut_interp_linear_float(rgb.r, &self.lut), + lut_interp_linear_float(rgb.g, &self.lut), + lut_interp_linear_float(rgb.b, &self.lut), + ) + } +} + +pub(crate) fn build_trc_table(num_entries: i32, eotf: impl Fn(f64) -> f64) -> Vec { + let mut table = vec![0u16; num_entries as usize]; + + for (i, table_value) in table.iter_mut().enumerate() { + let x: f64 = i as f64 / (num_entries - 1) as f64; + let y: f64 = eotf(x); + let mut output: f64; + output = y * 65535.0 + 0.5; + if output > 65535.0 { + output = 65535.0 + } + if output < 0.0 { + output = 0.0 + } + *table_value = output.floor() as u16; + } + table +} + +/// Creates Tone Reproduction curve from gamma +pub fn curve_from_gamma(gamma: f32) -> ToneReprCurve { + ToneReprCurve::Lut(vec![gamma.to_u8_fixed8()]) +} + +#[derive(Debug)] +struct ParametricCurve { + g: f32, + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, +} + +impl ParametricCurve { + #[allow(clippy::many_single_char_names)] + fn new(params: &[f32]) -> Option { + // convert from the variable number of parameters + // contained in profiles to a unified representation. + let g: f32 = params[0]; + match params[1..] { + [] => Some(ParametricCurve { + g, + a: 1., + b: 0., + c: 1., + d: 0., + e: 0., + f: 0., + }), + [a, b] => Some(ParametricCurve { + g, + a, + b, + c: 0., + d: -b / a, + e: 0., + f: 0., + }), + [a, b, c] => Some(ParametricCurve { + g, + a, + b, + c: 0., + d: -b / a, + e: c, + f: c, + }), + [a, b, c, d] => Some(ParametricCurve { + g, + a, + b, + c, + d, + e: 0., + f: 0., + }), + [a, b, c, d, e, f] => Some(ParametricCurve { + g, + a, + b, + c, + d, + e, + f, + }), + _ => None, + } + } + + fn is_linear(&self) -> bool { + (self.g - 1.0).abs() < 1e-5 + && (self.a - 1.0).abs() < 1e-5 + && self.b.abs() < 1e-5 + && self.c.abs() < 1e-5 + } + + fn eval(&self, x: f32) -> f32 { + if x < self.d { + self.c * x + self.f + } else { + f_powf(self.a * x + self.b, self.g) + self.e + } + } + + #[allow(dead_code)] + #[allow(clippy::many_single_char_names)] + fn invert(&self) -> Option { + // First check if the function is continuous at the cross-over point d. + let d1 = f_powf(self.a * self.d + self.b, self.g) + self.e; + let d2 = self.c * self.d + self.f; + + if (d1 - d2).abs() > 0.1 { + return None; + } + let d = d1; + + // y = (a * x + b)^g + e + // y - e = (a * x + b)^g + // (y - e)^(1/g) = a*x + b + // (y - e)^(1/g) - b = a*x + // (y - e)^(1/g)/a - b/a = x + // ((y - e)/a^g)^(1/g) - b/a = x + // ((1/(a^g)) * y - e/(a^g))^(1/g) - b/a = x + let a = 1. / f_powf(self.a, self.g); + let b = -self.e / f_powf(self.a, self.g); + let g = 1. / self.g; + let e = -self.b / self.a; + + // y = c * x + f + // y - f = c * x + // y/c - f/c = x + let (c, f); + if d <= 0. { + c = 1.; + f = 0.; + } else { + c = 1. / self.c; + f = -self.f / self.c; + } + + // if self.d > 0. and self.c == 0 as is likely with type 1 and 2 parametric function + // then c and f will not be finite. + if !(g.is_finite() + && a.is_finite() + && b.is_finite() + && c.is_finite() + && d.is_finite() + && e.is_finite() + && f.is_finite()) + { + return None; + } + + Some(ParametricCurve { + g, + a, + b, + c, + d, + e, + f, + }) + } +} + +#[inline] +pub(crate) fn u8_fixed_8number_to_float(x: u16) -> f32 { + // 0x0000 = 0. + // 0x0100 = 1. + // 0xffff = 255 + 255/256 + (x as i32 as f64 / 256.0) as f32 +} + +fn passthrough_table() +-> Box<[f32; N]> { + let mut gamma_table = Box::new([0f32; N]); + let max_value = if T::FINITE { + (1 << BIT_DEPTH) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let cap_values = if T::FINITE { + (1u32 << BIT_DEPTH) as usize + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE + }; + assert!(cap_values <= N, "Invalid lut table construction"); + let scale_value = 1f64 / max_value as f64; + for (i, g) in gamma_table.iter_mut().enumerate().take(cap_values) { + *g = (i as f64 * scale_value) as f32; + } + + gamma_table +} + +fn linear_forward_table( + gamma: u16, +) -> Box<[f32; N]> { + let mut gamma_table = Box::new([0f32; N]); + let gamma_float: f32 = u8_fixed_8number_to_float(gamma); + let max_value = if T::FINITE { + (1 << BIT_DEPTH) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let cap_values = if T::FINITE { + (1u32 << BIT_DEPTH) as usize + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE + }; + assert!(cap_values <= N, "Invalid lut table construction"); + let scale_value = 1f64 / max_value as f64; + for (i, g) in gamma_table.iter_mut().enumerate().take(cap_values) { + *g = f_pow(i as f64 * scale_value, gamma_float as f64) as f32; + } + + gamma_table +} + +#[inline(always)] +pub(crate) fn lut_interp_linear_float(x: f32, table: &[f32]) -> f32 { + let value = x.min(1.).max(0.) * (table.len() - 1) as f32; + + let upper: i32 = value.ceil() as i32; + let lower: i32 = value.floor() as i32; + + let diff = upper as f32 - value; + let tu = table[upper as usize]; + mlaf(neg_mlaf(tu, tu, diff), table[lower as usize], diff) +} + +/// Lut interpolation float where values is already clamped +#[inline(always)] +#[allow(dead_code)] +pub(crate) fn lut_interp_linear_float_clamped(x: f32, table: &[f32]) -> f32 { + let value = x * (table.len() - 1) as f32; + + let upper: i32 = value.ceil() as i32; + let lower: i32 = value.floor() as i32; + + let diff = upper as f32 - value; + let tu = table[upper as usize]; + mlaf(neg_mlaf(tu, tu, diff), table[lower as usize], diff) +} + +#[inline] +pub(crate) fn lut_interp_linear(input_value: f64, table: &[u16]) -> f32 { + let mut input_value = input_value; + if table.is_empty() { + return input_value as f32; + } + + input_value *= (table.len() - 1) as f64; + + let upper: i32 = input_value.ceil() as i32; + let lower: i32 = input_value.floor() as i32; + let w0 = table[(upper as usize).min(table.len() - 1)] as f64; + let w1 = 1. - (upper as f64 - input_value); + let w2 = table[(lower as usize).min(table.len() - 1)] as f64; + let w3 = upper as f64 - input_value; + let value: f32 = mlaf(w2 * w3, w0, w1) as f32; + value * (1.0 / 65535.0) +} + +fn linear_lut_interpolate( + table: &[u16], +) -> Box<[f32; N]> { + let mut gamma_table = Box::new([0f32; N]); + let max_value = if T::FINITE { + (1 << BIT_DEPTH) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let cap_values = if T::FINITE { + (1u32 << BIT_DEPTH) as usize + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE + }; + assert!(cap_values <= N, "Invalid lut table construction"); + let scale_value = 1f64 / max_value as f64; + for (i, g) in gamma_table.iter_mut().enumerate().take(cap_values) { + *g = lut_interp_linear(i as f64 * scale_value, table); + } + gamma_table +} + +fn linear_curve_parametric( + params: &[f32], +) -> Option> { + let params = ParametricCurve::new(params)?; + let mut gamma_table = Box::new([0f32; N]); + let max_value = if T::FINITE { + (1 << BIT_DEPTH) - 1 + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE - 1 + }; + let cap_value = if T::FINITE { + 1 << BIT_DEPTH + } else { + T::NOT_FINITE_LINEAR_TABLE_SIZE + }; + let scale_value = 1f32 / max_value as f32; + for (i, g) in gamma_table.iter_mut().enumerate().take(cap_value) { + let x = i as f32 * scale_value; + *g = m_clamp(params.eval(x), 0.0, 1.0); + } + Some(gamma_table) +} + +fn linear_curve_parametric_s(params: &[f32]) -> Option> { + let params = ParametricCurve::new(params)?; + let mut gamma_table = Box::new([0f32; N]); + let scale_value = 1f32 / (N - 1) as f32; + for (i, g) in gamma_table.iter_mut().enumerate().take(N) { + let x = i as f32 * scale_value; + *g = m_clamp(params.eval(x), 0.0, 1.0); + } + Some(gamma_table) +} + +pub(crate) fn make_gamma_linear_table< + T: Default + Copy + 'static + PointeeSizeExpressible, + const BUCKET: usize, + const N: usize, +>( + bit_depth: usize, +) -> Box<[T; BUCKET]> +where + f32: AsPrimitive, +{ + let mut table = Box::new([T::default(); BUCKET]); + let max_range = if T::FINITE { + (1f64 / ((N - 1) as f64 / (1 << bit_depth) as f64)) as f32 + } else { + (1f64 / ((N - 1) as f64)) as f32 + }; + for (v, output) in table.iter_mut().take(N).enumerate() { + if T::FINITE { + *output = (v as f32 * max_range).round().as_(); + } else { + *output = (v as f32 * max_range).as_(); + } + } + table +} + +#[inline] +fn lut_interp_linear_gamma_impl< + T: Default + Copy + 'static + PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, +>( + input_value: u32, + table: &[u16], +) -> T +where + u32: AsPrimitive, +{ + // Start scaling input_value to the length of the array: GAMMA_CAP*(length-1). + // We'll divide out the GAMMA_CAP next + let mut value: u32 = input_value * (table.len() - 1) as u32; + let cap_value = N - 1; + // equivalent to ceil(value/GAMMA_CAP) + let upper: u32 = value.div_ceil(cap_value as u32); + // equivalent to floor(value/GAMMA_CAP) + let lower: u32 = value / cap_value as u32; + // interp is the distance from upper to value scaled to 0..GAMMA_CAP + let interp: u32 = value % cap_value as u32; + let lw_value = table[lower as usize]; + let hw_value = table[upper as usize]; + // the table values range from 0..65535 + value = mlaf( + hw_value as u32 * interp, + lw_value as u32, + (N - 1) as u32 - interp, + ); // 0..(65535*GAMMA_CAP) + + // round and scale + let max_colors = if T::FINITE { (1 << BIT_DEPTH) - 1 } else { 1 }; + value += (cap_value * 65535 / max_colors / 2) as u32; // scale to 0...max_colors + value /= (cap_value * 65535 / max_colors) as u32; + value.as_() +} + +#[inline] +fn lut_interp_linear_gamma_impl_f32< + T: Default + Copy + 'static + PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, +>( + input_value: u32, + table: &[u16], +) -> T +where + f32: AsPrimitive, +{ + // Start scaling input_value to the length of the array: GAMMA_CAP*(length-1). + // We'll divide out the GAMMA_CAP next + let guess: u32 = input_value * (table.len() - 1) as u32; + let cap_value = N - 1; + // equivalent to ceil(value/GAMMA_CAP) + let upper: u32 = guess.div_ceil(cap_value as u32); + // equivalent to floor(value/GAMMA_CAP) + let lower: u32 = guess / cap_value as u32; + // interp is the distance from upper to value scaled to 0..GAMMA_CAP + let interp: u32 = guess % cap_value as u32; + let lw_value = table[lower as usize]; + let hw_value = table[upper as usize]; + // the table values range from 0..65535 + let mut value = mlaf( + hw_value as f32 * interp as f32, + lw_value as f32, + (N - 1) as f32 - interp as f32, + ); // 0..(65535*GAMMA_CAP) + + // round and scale + let max_colors = if T::FINITE { (1 << BIT_DEPTH) - 1 } else { 1 }; + value /= (cap_value * 65535 / max_colors) as f32; + value.as_() +} + +#[doc(hidden)] +pub trait GammaLutInterpolate { + fn gamma_lut_interp< + T: Default + Copy + 'static + PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + input_value: u32, + table: &[u16], + ) -> T + where + u32: AsPrimitive, + f32: AsPrimitive; +} + +macro_rules! gamma_lut_interp_fixed { + ($i_type: ident) => { + impl GammaLutInterpolate for $i_type { + #[inline] + fn gamma_lut_interp< + T: Default + Copy + 'static + PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + input_value: u32, + table: &[u16], + ) -> T + where + u32: AsPrimitive, + { + lut_interp_linear_gamma_impl::(input_value, table) + } + } + }; +} + +gamma_lut_interp_fixed!(u8); +gamma_lut_interp_fixed!(u16); + +macro_rules! gammu_lut_interp_float { + ($f_type: ident) => { + impl GammaLutInterpolate for $f_type { + #[inline] + fn gamma_lut_interp< + T: Default + Copy + 'static + PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + input_value: u32, + table: &[u16], + ) -> T + where + f32: AsPrimitive, + u32: AsPrimitive, + { + lut_interp_linear_gamma_impl_f32::(input_value, table) + } + } + }; +} + +gammu_lut_interp_float!(f32); +gammu_lut_interp_float!(f64); + +pub(crate) fn make_gamma_lut< + T: Default + Copy + 'static + PointeeSizeExpressible + GammaLutInterpolate, + const BUCKET: usize, + const N: usize, + const BIT_DEPTH: usize, +>( + table: &[u16], +) -> Box<[T; BUCKET]> +where + u32: AsPrimitive, + f32: AsPrimitive, +{ + let mut new_table = Box::new([T::default(); BUCKET]); + for (v, output) in new_table.iter_mut().take(N).enumerate() { + *output = T::gamma_lut_interp::(v as u32, table); + } + new_table +} + +#[inline] +pub(crate) fn lut_interp_linear16(input_value: u16, table: &[u16]) -> u16 { + // Start scaling input_value to the length of the array: 65535*(length-1). + // We'll divide out the 65535 next + let mut value: u32 = input_value as u32 * (table.len() as u32 - 1); + let upper: u16 = value.div_ceil(65535) as u16; // equivalent to ceil(value/65535) + let lower: u16 = (value / 65535) as u16; // equivalent to floor(value/65535) + // interp is the distance from upper to value scaled to 0..65535 + let interp: u32 = value % 65535; // 0..65535*65535 + value = (table[upper as usize] as u32 * interp + + table[lower as usize] as u32 * (65535 - interp)) + / 65535; + value as u16 +} + +#[inline] +pub(crate) fn lut_interp_linear16_boxed(input_value: u16, table: &[u16; N]) -> u16 { + // Start scaling input_value to the length of the array: 65535*(length-1). + // We'll divide out the 65535 next + let mut value: u32 = input_value as u32 * (table.len() as u32 - 1); + let upper: u16 = value.div_ceil(65535) as u16; // equivalent to ceil(value/65535) + let lower: u16 = (value / 65535) as u16; // equivalent to floor(value/65535) + // interp is the distance from upper to value scaled to 0..65535 + let interp: u32 = value % 65535; // 0..65535*65535 + value = (table[upper as usize] as u32 * interp + + table[lower as usize] as u32 * (65535 - interp)) + / 65535; + value as u16 +} + +fn make_gamma_pow_table< + T: Default + Copy + 'static + PointeeSizeExpressible, + const BUCKET: usize, + const N: usize, +>( + gamma: f32, + bit_depth: usize, +) -> Box<[T; BUCKET]> +where + f32: AsPrimitive, +{ + let mut table = Box::new([T::default(); BUCKET]); + let scale = 1f32 / (N - 1) as f32; + let cap = ((1 << bit_depth) - 1) as f32; + if T::FINITE { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = (cap * f_powf(v as f32 * scale, gamma)).round().as_(); + } + } else { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = (cap * f_powf(v as f32 * scale, gamma)).as_(); + } + } + table +} + +fn make_gamma_parametric_table< + T: Default + Copy + 'static + PointeeSizeExpressible, + const BUCKET: usize, + const N: usize, + const BIT_DEPTH: usize, +>( + parametric_curve: ParametricCurve, +) -> Box<[T; BUCKET]> +where + f32: AsPrimitive, +{ + let mut table = Box::new([T::default(); BUCKET]); + let scale = 1f32 / (N - 1) as f32; + let cap = ((1 << BIT_DEPTH) - 1) as f32; + if T::FINITE { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = (cap * parametric_curve.eval(v as f32 * scale)) + .round() + .as_(); + } + } else { + for (v, output) in table.iter_mut().take(N).enumerate() { + *output = (cap * parametric_curve.eval(v as f32 * scale)).as_(); + } + } + table +} + +#[inline] +fn compare_parametric(src: &[f32], dst: &[f32]) -> bool { + for (src, dst) in src.iter().zip(dst.iter()) { + if (src - dst).abs() > 1e-4 { + return false; + } + } + true +} + +fn lut_inverse_interp16(value: u16, lut_table: &[u16]) -> u16 { + let mut l: i32 = 1; // 'int' Give spacing for negative values + let mut r: i32 = 0x10000; + let mut x: i32 = 0; + let mut res: i32; + let length = lut_table.len() as i32; + + let mut num_zeroes: i32 = 0; + for &item in lut_table.iter() { + if item == 0 { + num_zeroes += 1 + } else { + break; + } + } + + if num_zeroes == 0 && value as i32 == 0 { + return 0u16; + } + let mut num_of_polys: i32 = 0; + for &item in lut_table.iter().rev() { + if item == 0xffff { + num_of_polys += 1 + } else { + break; + } + } + // Does the curve belong to this case? + if num_zeroes > 1 || num_of_polys > 1 { + let a_0: i32; + let b_0: i32; + // Identify if value fall downto 0 or FFFF zone + if value as i32 == 0 { + return 0u16; + } + // if (Value == 0xFFFF) return 0xFFFF; + // else restrict to valid zone + if num_zeroes > 1 { + a_0 = (num_zeroes - 1) * 0xffff / (length - 1); + l = a_0 - 1 + } + if num_of_polys > 1 { + b_0 = (length - 1 - num_of_polys) * 0xffff / (length - 1); + r = b_0 + 1 + } + } + if r <= l { + // If this happens LutTable is not invertible + return 0u16; + } + + while r > l { + x = (l + r) / 2; + res = lut_interp_linear16((x - 1) as u16, lut_table) as i32; + if res == value as i32 { + // Found exact match. + return (x - 1) as u16; + } + if res > value as i32 { + r = x - 1 + } else { + l = x + 1 + } + } + + // Not found, should we interpolate? + + // Get surrounding nodes + debug_assert!(x >= 1); + + let val2: f64 = (length - 1) as f64 * ((x - 1) as f64 / 65535.0); + let cell0: i32 = val2.floor() as i32; + let cell1: i32 = val2.ceil() as i32; + if cell0 == cell1 { + return x as u16; + } + + let y0: f64 = lut_table[cell0 as usize] as f64; + let x0: f64 = 65535.0 * cell0 as f64 / (length - 1) as f64; + let y1: f64 = lut_table[cell1 as usize] as f64; + let x1: f64 = 65535.0 * cell1 as f64 / (length - 1) as f64; + let a: f64 = (y1 - y0) / (x1 - x0); + let b: f64 = mlaf(y0, -a, x0); + if a.abs() < 0.01f64 { + return x as u16; + } + let f: f64 = (value as i32 as f64 - b) / a; + if f < 0.0 { + return 0u16; + } + if f >= 65535.0 { + return 0xffffu16; + } + (f + 0.5f64).floor() as u16 +} + +fn lut_inverse_interp16_boxed(value: u16, lut_table: &[u16; N]) -> u16 { + let mut l: i32 = 1; // 'int' Give spacing for negative values + let mut r: i32 = 0x10000; + let mut x: i32 = 0; + let mut res: i32; + let length = lut_table.len() as i32; + + let mut num_zeroes: i32 = 0; + for &item in lut_table.iter() { + if item == 0 { + num_zeroes += 1 + } else { + break; + } + } + + if num_zeroes == 0 && value as i32 == 0 { + return 0u16; + } + let mut num_of_polys: i32 = 0; + for &item in lut_table.iter().rev() { + if item == 0xffff { + num_of_polys += 1 + } else { + break; + } + } + // Does the curve belong to this case? + if num_zeroes > 1 || num_of_polys > 1 { + let a_0: i32; + let b_0: i32; + // Identify if value fall downto 0 or FFFF zone + if value as i32 == 0 { + return 0u16; + } + // if (Value == 0xFFFF) return 0xFFFF; + // else restrict to valid zone + if num_zeroes > 1 { + a_0 = (num_zeroes - 1) * 0xffff / (length - 1); + l = a_0 - 1 + } + if num_of_polys > 1 { + b_0 = (length - 1 - num_of_polys) * 0xffff / (length - 1); + r = b_0 + 1 + } + } + if r <= l { + // If this happens LutTable is not invertible + return 0u16; + } + + while r > l { + x = (l + r) / 2; + res = lut_interp_linear16_boxed((x - 1) as u16, lut_table) as i32; + if res == value as i32 { + // Found exact match. + return (x - 1) as u16; + } + if res > value as i32 { + r = x - 1 + } else { + l = x + 1 + } + } + + // Not found, should we interpolate? + + // Get surrounding nodes + debug_assert!(x >= 1); + + let val2: f64 = (length - 1) as f64 * ((x - 1) as f64 / 65535.0); + let cell0: i32 = val2.floor() as i32; + let cell1: i32 = val2.ceil() as i32; + if cell0 == cell1 { + return x as u16; + } + + let y0: f64 = lut_table[cell0 as usize] as f64; + let x0: f64 = 65535.0 * cell0 as f64 / (length - 1) as f64; + let y1: f64 = lut_table[cell1 as usize] as f64; + let x1: f64 = 65535.0 * cell1 as f64 / (length - 1) as f64; + let a: f64 = (y1 - y0) / (x1 - x0); + let b: f64 = mlaf(y0, -a, x0); + if a.abs() < 0.01f64 { + return x as u16; + } + let f: f64 = (value as i32 as f64 - b) / a; + if f < 0.0 { + return 0u16; + } + if f >= 65535.0 { + return 0xffffu16; + } + (f + 0.5f64).floor() as u16 +} + +fn invert_lut(table: &[u16], out_length: usize) -> Vec { + // For now, we invert the lut by creating a lut of size out_length + // and attempting to look up a value for each entry using lut_inverse_interp16 + let mut output = vec![0u16; out_length]; + let scale_value = 65535f64 / (out_length - 1) as f64; + for (i, out) in output.iter_mut().enumerate() { + let x: f64 = i as f64 * scale_value; + let input: u16 = (x + 0.5f64).floor() as u16; + *out = lut_inverse_interp16(input, table); + } + output +} + +fn invert_lut_boxed(table: &[u16; N], out_length: usize) -> Vec { + // For now, we invert the lut by creating a lut of size out_length + // and attempting to look up a value for each entry using lut_inverse_interp16 + let mut output = vec![0u16; out_length]; + let scale_value = 65535f64 / (out_length - 1) as f64; + for (i, out) in output.iter_mut().enumerate() { + let x: f64 = i as f64 * scale_value; + let input: u16 = (x + 0.5f64).floor() as u16; + *out = lut_inverse_interp16_boxed(input, table); + } + output +} + +impl ToneReprCurve { + pub(crate) fn to_clut(&self) -> Result, CmsError> { + match self { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + let passthrough_table = passthrough_table::(); + Ok(passthrough_table.to_vec()) + } else { + Ok(lut + .iter() + .map(|&x| x as f32 * (1. / 65535.)) + .collect::>()) + } + } + ToneReprCurve::Parametric(_) => { + let curve = self + .build_linearize_table::() + .ok_or(CmsError::InvalidTrcCurve)?; + let max_value = f32::NOT_FINITE_LINEAR_TABLE_SIZE - 1; + let sliced = &curve[..max_value]; + Ok(sliced.to_vec()) + } + } + } + + pub(crate) fn build_linearize_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + ) -> Option> { + match self { + ToneReprCurve::Parametric(params) => linear_curve_parametric::(params), + ToneReprCurve::Lut(data) => match data.len() { + 0 => Some(passthrough_table::()), + 1 => Some(linear_forward_table::(data[0])), + _ => Some(linear_lut_interpolate::(data)), + }, + } + } + + pub(crate) fn build_gamma_table< + T: Default + Copy + 'static + PointeeSizeExpressible + GammaLutInterpolate, + const BUCKET: usize, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + ) -> Option> + where + f32: AsPrimitive, + u32: AsPrimitive, + { + match self { + ToneReprCurve::Parametric(params) => { + if params.len() == 5 { + let srgb_params = vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]; + let rec709_params = create_rec709_parametric(); + + let mut lc_params: [f32; 5] = [0.; 5]; + for (dst, src) in lc_params.iter_mut().zip(params.iter()) { + *dst = *src; + } + + if compare_parametric(lc_params.as_slice(), srgb_params.as_slice()) { + return Some( + TransferCharacteristics::Srgb + .make_gamma_table::(BIT_DEPTH), + ); + } + + if compare_parametric(lc_params.as_slice(), rec709_params.as_slice()) { + return Some( + TransferCharacteristics::Bt709 + .make_gamma_table::(BIT_DEPTH), + ); + } + } + + let parametric_curve = ParametricCurve::new(params); + if let Some(v) = parametric_curve? + .invert() + .map(|x| make_gamma_parametric_table::(x)) + { + return Some(v); + } + + let mut gamma_table_uint = Box::new([0; N]); + + let inverted_size: usize = N; + let gamma_table = linear_curve_parametric_s::(params)?; + for (&src, dst) in gamma_table.iter().zip(gamma_table_uint.iter_mut()) { + *dst = (src * 65535f32) as u16; + } + let inverted = invert_lut_boxed(&gamma_table_uint, inverted_size); + Some(make_gamma_lut::(&inverted)) + } + ToneReprCurve::Lut(data) => match data.len() { + 0 => Some(make_gamma_linear_table::(BIT_DEPTH)), + 1 => Some(make_gamma_pow_table::( + 1. / u8_fixed_8number_to_float(data[0]), + BIT_DEPTH, + )), + _ => { + let mut inverted_size = data.len(); + if inverted_size < 256 { + inverted_size = 256 + } + let inverted = invert_lut(data, inverted_size); + Some(make_gamma_lut::(&inverted)) + } + }, + } + } +} + +impl ColorProfile { + /// Produces LUT for 8 bit tone linearization + pub fn build_8bit_lin_table( + &self, + trc: &Option, + ) -> Result, CmsError> { + trc.as_ref() + .and_then(|trc| trc.build_linearize_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Produces LUT for Gray transfer curve with N depth + pub fn build_gray_linearize_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + ) -> Result, CmsError> { + self.gray_trc + .as_ref() + .and_then(|trc| trc.build_linearize_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Produces LUT for Red transfer curve with N depth + pub fn build_r_linearize_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + use_cicp: bool, + ) -> Result, CmsError> { + if use_cicp { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Ok(tc.make_linear_table::()); + } + } + } + self.red_trc + .as_ref() + .and_then(|trc| trc.build_linearize_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Produces LUT for Green transfer curve with N depth + pub fn build_g_linearize_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + use_cicp: bool, + ) -> Result, CmsError> { + if use_cicp { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Ok(tc.make_linear_table::()); + } + } + } + self.green_trc + .as_ref() + .and_then(|trc| trc.build_linearize_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Produces LUT for Blue transfer curve with N depth + pub fn build_b_linearize_table< + T: PointeeSizeExpressible, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + use_cicp: bool, + ) -> Result, CmsError> { + if use_cicp { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Ok(tc.make_linear_table::()); + } + } + } + self.blue_trc + .as_ref() + .and_then(|trc| trc.build_linearize_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Build gamma table for 8 bit depth + /// Only 4092 first bins are used and values scaled in 0..255 + pub fn build_8bit_gamma_table( + &self, + trc: &Option, + use_cicp: bool, + ) -> Result, CmsError> { + self.build_gamma_table::(trc, use_cicp) + } + + /// Build gamma table for 10 bit depth + /// Only 8192 first bins are used and values scaled in 0..1023 + pub fn build_10bit_gamma_table( + &self, + trc: &Option, + use_cicp: bool, + ) -> Result, CmsError> { + self.build_gamma_table::(trc, use_cicp) + } + + /// Build gamma table for 12 bit depth + /// Only 16384 first bins are used and values scaled in 0..4095 + pub fn build_12bit_gamma_table( + &self, + trc: &Option, + use_cicp: bool, + ) -> Result, CmsError> { + self.build_gamma_table::(trc, use_cicp) + } + + /// Build gamma table for 16 bit depth + /// Only 16384 first bins are used and values scaled in 0..65535 + pub fn build_16bit_gamma_table( + &self, + trc: &Option, + use_cicp: bool, + ) -> Result, CmsError> { + self.build_gamma_table::(trc, use_cicp) + } + + /// Builds gamma table checking CICP for Transfer characteristics first. + pub fn build_gamma_table< + T: Default + Copy + 'static + PointeeSizeExpressible + GammaLutInterpolate, + const BUCKET: usize, + const N: usize, + const BIT_DEPTH: usize, + >( + &self, + trc: &Option, + use_cicp: bool, + ) -> Result, CmsError> + where + f32: AsPrimitive, + u32: AsPrimitive, + { + if use_cicp { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Ok(tc.make_gamma_table::(BIT_DEPTH)); + } + } + } + trc.as_ref() + .and_then(|trc| trc.build_gamma_table::()) + .ok_or(CmsError::BuildTransferFunction) + } + + /// Checks if profile gamma can work in extended precision and we have implementation for this + pub(crate) fn try_extended_gamma_evaluator( + &self, + ) -> Option> { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: tc.extended_gamma_tristimulus(), + trc: tc.extended_gamma_single(), + })); + } + } + if !self.are_all_trc_the_same() { + return None; + } + let reference_trc = if self.color_space == DataColorSpace::Gray { + self.gray_trc.as_ref() + } else { + self.red_trc.as_ref() + }; + if let Some(red_trc) = reference_trc { + return Self::make_gamma_evaluator_all_the_same(red_trc); + } + None + } + + fn make_gamma_evaluator_all_the_same( + red_trc: &ToneReprCurve, + ) -> Option> { + match red_trc { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return Some(Box::new(ToneCurveEvaluatorLinear {})); + } + if lut.len() == 1 { + let gamma = 1. / u8_fixed_8number_to_float(lut[0]); + return Some(Box::new(ToneCurveEvaluatorPureGamma { gamma })); + } + None + } + ToneReprCurve::Parametric(params) => { + if params.len() == 5 { + let srgb_params = vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]; + let rec709_params = create_rec709_parametric(); + + let mut lc_params: [f32; 5] = [0.; 5]; + for (dst, src) in lc_params.iter_mut().zip(params.iter()) { + *dst = *src; + } + + if compare_parametric(lc_params.as_slice(), srgb_params.as_slice()) { + return Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: TransferCharacteristics::Srgb.extended_gamma_tristimulus(), + trc: TransferCharacteristics::Srgb.extended_gamma_single(), + })); + } + + if compare_parametric(lc_params.as_slice(), rec709_params.as_slice()) { + return Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: TransferCharacteristics::Bt709.extended_gamma_tristimulus(), + trc: TransferCharacteristics::Bt709.extended_gamma_single(), + })); + } + } + + let parametric_curve = ParametricCurve::new(params); + if let Some(v) = parametric_curve?.invert() { + return Some(Box::new(ToneCurveParametricEvaluator { parametric: v })); + } + None + } + } + } + + /// Check if all TRC are the same + pub(crate) fn are_all_trc_the_same(&self) -> bool { + if self.color_space == DataColorSpace::Gray { + return true; + } + if let (Some(red_trc), Some(green_trc), Some(blue_trc)) = + (&self.red_trc, &self.green_trc, &self.blue_trc) + { + if !matches!( + (red_trc, green_trc, blue_trc), + ( + ToneReprCurve::Lut(_), + ToneReprCurve::Lut(_), + ToneReprCurve::Lut(_), + ) | ( + ToneReprCurve::Parametric(_), + ToneReprCurve::Parametric(_), + ToneReprCurve::Parametric(_) + ) + ) { + return false; + } + if let (ToneReprCurve::Lut(lut0), ToneReprCurve::Lut(lut1), ToneReprCurve::Lut(lut2)) = + (red_trc, green_trc, blue_trc) + { + if lut0 == lut1 || lut1 == lut2 { + return true; + } + } + if let ( + ToneReprCurve::Parametric(lut0), + ToneReprCurve::Parametric(lut1), + ToneReprCurve::Parametric(lut2), + ) = (red_trc, green_trc, blue_trc) + { + if lut0 == lut1 || lut1 == lut2 { + return true; + } + } + } + false + } + + /// Checks if profile is matrix shaper, have same TRC and TRC is linear. + pub(crate) fn is_linear_matrix_shaper(&self) -> bool { + if !self.is_matrix_shaper() { + return false; + } + if !self.are_all_trc_the_same() { + return false; + } + if let Some(red_trc) = &self.red_trc { + return match red_trc { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return true; + } + if is_curve_linear16(lut) { + return true; + } + false + } + ToneReprCurve::Parametric(params) => { + if let Some(curve) = ParametricCurve::new(params) { + return curve.is_linear(); + } + false + } + }; + } + false + } + + /// Checks if profile linearization can work in extended precision and we have implementation for this + pub(crate) fn try_extended_linearizing_evaluator( + &self, + ) -> Option> { + if let Some(tc) = self.cicp.as_ref().map(|c| c.transfer_characteristics) { + if tc.has_transfer_curve() { + return Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: tc.extended_linear_tristimulus(), + trc: tc.extended_linear_single(), + })); + } + } + if !self.are_all_trc_the_same() { + return None; + } + let reference_trc = if self.color_space == DataColorSpace::Gray { + self.gray_trc.as_ref() + } else { + self.red_trc.as_ref() + }; + if let Some(red_trc) = reference_trc { + if let Some(value) = Self::make_linear_curve_evaluator_all_the_same(red_trc) { + return value; + } + } + None + } + + fn make_linear_curve_evaluator_all_the_same( + evaluator_curve: &ToneReprCurve, + ) -> Option>> { + match evaluator_curve { + ToneReprCurve::Lut(lut) => { + if lut.is_empty() { + return Some(Some(Box::new(ToneCurveEvaluatorLinear {}))); + } + if lut.len() == 1 { + let gamma = u8_fixed_8number_to_float(lut[0]); + return Some(Some(Box::new(ToneCurveEvaluatorPureGamma { gamma }))); + } + } + ToneReprCurve::Parametric(params) => { + if params.len() == 5 { + let srgb_params = vec![2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045]; + let rec709_params = create_rec709_parametric(); + + let mut lc_params: [f32; 5] = [0.; 5]; + for (dst, src) in lc_params.iter_mut().zip(params.iter()) { + *dst = *src; + } + + if compare_parametric(lc_params.as_slice(), srgb_params.as_slice()) { + return Some(Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: TransferCharacteristics::Srgb.extended_linear_tristimulus(), + trc: TransferCharacteristics::Srgb.extended_linear_single(), + }))); + } + + if compare_parametric(lc_params.as_slice(), rec709_params.as_slice()) { + return Some(Some(Box::new(ToneCurveCicpEvaluator { + rgb_trc: TransferCharacteristics::Bt709.extended_linear_tristimulus(), + trc: TransferCharacteristics::Bt709.extended_linear_single(), + }))); + } + } + + let parametric_curve = ParametricCurve::new(params); + if let Some(v) = parametric_curve { + return Some(Some(Box::new(ToneCurveParametricEvaluator { + parametric: v, + }))); + } + } + } + None + } +} + +pub(crate) struct ToneCurveCicpEvaluator { + rgb_trc: fn(Rgb) -> Rgb, + trc: fn(f32) -> f32, +} + +pub(crate) struct ToneCurveParametricEvaluator { + parametric: ParametricCurve, +} + +pub(crate) struct ToneCurveEvaluatorPureGamma { + gamma: f32, +} + +pub(crate) struct ToneCurveEvaluatorLinear {} + +impl ToneCurveEvaluator for ToneCurveCicpEvaluator { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + (self.rgb_trc)(rgb) + } + + fn evaluate_value(&self, value: f32) -> f32 { + (self.trc)(value) + } +} + +impl ToneCurveEvaluator for ToneCurveParametricEvaluator { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + Rgb::new( + self.parametric.eval(rgb.r), + self.parametric.eval(rgb.g), + self.parametric.eval(rgb.b), + ) + } + + fn evaluate_value(&self, value: f32) -> f32 { + self.parametric.eval(value) + } +} + +impl ToneCurveEvaluator for ToneCurveEvaluatorPureGamma { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + Rgb::new( + dirty_powf(rgb.r, self.gamma), + dirty_powf(rgb.g, self.gamma), + dirty_powf(rgb.b, self.gamma), + ) + } + + fn evaluate_value(&self, value: f32) -> f32 { + dirty_powf(value, self.gamma) + } +} + +impl ToneCurveEvaluator for ToneCurveEvaluatorLinear { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb { + rgb + } + + fn evaluate_value(&self, value: f32) -> f32 { + value + } +} + +pub trait ToneCurveEvaluator { + fn evaluate_tristimulus(&self, rgb: Rgb) -> Rgb; + fn evaluate_value(&self, value: f32) -> f32; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,925 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::profile::{LutDataType, ProfileHeader}; +use crate::tag::{TAG_SIZE, Tag, TagTypeDefinition}; +use crate::trc::ToneReprCurve; +use crate::{ + CicpProfile, CmsError, ColorDateTime, ColorProfile, DataColorSpace, LocalizableString, + LutMultidimensionalType, LutStore, LutType, LutWarehouse, Matrix3d, ProfileClass, + ProfileSignature, ProfileText, ProfileVersion, Vector3d, ViewingConditions, Xyz, Xyzd, +}; + +pub(crate) trait FloatToFixedS15Fixed16 { + fn to_s15_fixed16(self) -> i32; +} + +pub(crate) trait FloatToFixedU8Fixed8 { + fn to_u8_fixed8(self) -> u16; +} + +// pub(crate) trait FloatToFixedU16 { +// fn to_fixed_u16(self) -> u16; +// } + +// impl FloatToFixedU16 for f32 { +// #[inline] +// fn to_fixed_u16(self) -> u16 { +// const SCALE: f64 = (1 << 16) as f64; +// (self as f64 * SCALE + 0.5) +// .floor() +// .clamp(u16::MIN as f64, u16::MAX as f64) as u16 +// } +// } + +impl FloatToFixedS15Fixed16 for f32 { + #[inline] + fn to_s15_fixed16(self) -> i32 { + const SCALE: f64 = (1 << 16) as f64; + (self as f64 * SCALE + 0.5) + .floor() + .clamp(i32::MIN as f64, i32::MAX as f64) as i32 + } +} + +impl FloatToFixedS15Fixed16 for f64 { + #[inline] + fn to_s15_fixed16(self) -> i32 { + const SCALE: f64 = (1 << 16) as f64; + (self * SCALE + 0.5) + .floor() + .clamp(i32::MIN as f64, i32::MAX as f64) as i32 + } +} + +#[inline] +fn write_u32_be(into: &mut Vec, value: u32) { + let bytes = value.to_be_bytes(); + into.push(bytes[0]); + into.push(bytes[1]); + into.push(bytes[2]); + into.push(bytes[3]); +} + +#[inline] +pub(crate) fn write_u16_be(into: &mut Vec, value: u16) { + let bytes = value.to_be_bytes(); + into.push(bytes[0]); + into.push(bytes[1]); +} + +#[inline] +fn write_i32_be(into: &mut Vec, value: i32) { + let bytes = value.to_be_bytes(); + into.push(bytes[0]); + into.push(bytes[1]); + into.push(bytes[2]); + into.push(bytes[3]); +} + +fn first_two_ascii_bytes(s: &String) -> [u8; 2] { + let bytes = s.as_bytes(); + if bytes.len() >= 2 { + bytes[0..2].try_into().unwrap() + } else if bytes.len() == 1 { + let vec = vec![bytes[0], 0u8]; + vec.try_into().unwrap() + } else { + let vec = vec![0u8, 0u8]; + vec.try_into().unwrap() + } +} + +/// Writes Multi Localized Unicode +#[inline] +fn write_mluc(into: &mut Vec, strings: &[LocalizableString]) -> usize { + assert!(!strings.is_empty()); + let start = into.len(); + let tag_def: u32 = TagTypeDefinition::MultiLocalizedUnicode.into(); + write_u32_be(into, tag_def); + write_u32_be(into, 0); + let number_of_records = strings.len(); + write_u32_be(into, number_of_records as u32); + write_u32_be(into, 12); // Record size, must be 12 + let lang = first_two_ascii_bytes(&strings[0].language); + into.extend_from_slice(&lang); + let country = first_two_ascii_bytes(&strings[0].country); + into.extend_from_slice(&country); + let first_string_len = strings[0].value.len() * 2; + write_u32_be(into, first_string_len as u32); + let mut first_string_offset = 16 + 12 * strings.len(); + write_u32_be(into, first_string_offset as u32); + first_string_offset += first_string_len; + for record in strings.iter().skip(1) { + let lang = first_two_ascii_bytes(&record.language); + into.extend_from_slice(&lang); + let country = first_two_ascii_bytes(&record.country); + into.extend_from_slice(&country); + let first_string_len = record.value.len() * 2; + write_u32_be(into, first_string_len as u32); + write_u32_be(into, first_string_offset as u32); + first_string_offset += first_string_len; + } + for record in strings.iter() { + for chunk in record.value.encode_utf16() { + write_u16_be(into, chunk); + } + } + let end = into.len(); + end - start +} + +#[inline] +fn write_string_value(into: &mut Vec, text: &ProfileText) -> usize { + match text { + ProfileText::PlainString(text) => { + let vec = vec![LocalizableString { + language: "en".to_string(), + country: "US".to_string(), + value: text.clone(), + }]; + write_mluc(into, &vec) + } + ProfileText::Localizable(localizable) => { + if localizable.is_empty() { + return 0; + } + write_mluc(into, localizable) + } + ProfileText::Description(description) => { + let vec = vec![LocalizableString { + language: "en".to_string(), + country: "US".to_string(), + value: description.unicode_string.clone(), + }]; + write_mluc(into, &vec) + } + } +} + +#[inline] +fn write_xyz_tag_value(into: &mut Vec, xyz: Xyzd) { + let tag_definition: u32 = TagTypeDefinition::Xyz.into(); + write_u32_be(into, tag_definition); + write_u32_be(into, 0); + let x_fixed = xyz.x.to_s15_fixed16(); + write_i32_be(into, x_fixed); + let y_fixed = xyz.y.to_s15_fixed16(); + write_i32_be(into, y_fixed); + let z_fixed = xyz.z.to_s15_fixed16(); + write_i32_be(into, z_fixed); +} + +#[inline] +fn write_tag_entry(into: &mut Vec, tag: Tag, tag_entry: usize, tag_size: usize) { + let tag_value: u32 = tag.into(); + write_u32_be(into, tag_value); + write_u32_be(into, tag_entry as u32); + write_u32_be(into, tag_size as u32); +} + +#[inline] +fn write_xyz(into: &mut Vec, xyz: Xyz) { + let x_fixed = xyz.x.to_s15_fixed16(); + write_i32_be(into, x_fixed); + let y_fixed = xyz.y.to_s15_fixed16(); + write_i32_be(into, y_fixed); + let z_fixed = xyz.z.to_s15_fixed16(); + write_i32_be(into, z_fixed); +} + +#[inline] +fn write_viewing_conditions_value( + into: &mut Vec, + viewing_conditions: &ViewingConditions, +) -> usize { + let tag_definition: u32 = TagTypeDefinition::DefViewingConditions.into(); + write_u32_be(into, tag_definition); + write_u32_be(into, 0); + write_xyz(into, viewing_conditions.illuminant); + write_xyz(into, viewing_conditions.surround); + write_u32_be(into, viewing_conditions.observer.into()); + 36 +} + +fn write_trc_entry(into: &mut Vec, trc: &ToneReprCurve) -> Result { + match trc { + ToneReprCurve::Lut(lut) => { + let curv: u32 = TagTypeDefinition::LutToneCurve.into(); + write_u32_be(into, curv); + write_u32_be(into, 0); + write_u32_be(into, lut.len() as u32); + for item in lut.iter() { + write_u16_be(into, *item); + } + Ok(12 + lut.len() * 2) + } + ToneReprCurve::Parametric(parametric_curve) => { + if parametric_curve.len() > 7 + || parametric_curve.len() == 6 + || parametric_curve.len() == 2 + { + return Err(CmsError::InvalidProfile); + } + let para: u32 = TagTypeDefinition::ParametricToneCurve.into(); + write_u32_be(into, para); + write_u32_be(into, 0); + if parametric_curve.len() == 1 { + write_u16_be(into, 0); + } else if parametric_curve.len() == 3 { + write_u16_be(into, 1); + } else if parametric_curve.len() == 4 { + write_u16_be(into, 2); + } else if parametric_curve.len() == 5 { + write_u16_be(into, 3); + } else if parametric_curve.len() == 7 { + write_u16_be(into, 4); + } + write_u16_be(into, 0); + for item in parametric_curve.iter() { + write_i32_be(into, item.to_s15_fixed16()); + } + Ok(12 + 4 * parametric_curve.len()) + } + } +} + +#[inline] +fn write_cicp_entry(into: &mut Vec, cicp: &CicpProfile) { + let cicp_tag: u32 = TagTypeDefinition::Cicp.into(); + write_u32_be(into, cicp_tag); + write_u32_be(into, 0); + into.push(cicp.color_primaries as u8); + into.push(cicp.transfer_characteristics as u8); + into.push(cicp.matrix_coefficients as u8); + into.push(if cicp.full_range { 1 } else { 0 }); +} + +fn write_chad(into: &mut Vec, matrix: Matrix3d) { + let arr_type: u32 = TagTypeDefinition::S15Fixed16Array.into(); + write_u32_be(into, arr_type); + write_u32_be(into, 0); + write_matrix3d(into, matrix); +} + +#[inline] +fn write_matrix3d(into: &mut Vec, v: Matrix3d) { + write_i32_be(into, v.v[0][0].to_s15_fixed16()); + write_i32_be(into, v.v[0][1].to_s15_fixed16()); + write_i32_be(into, v.v[0][2].to_s15_fixed16()); + + write_i32_be(into, v.v[1][0].to_s15_fixed16()); + write_i32_be(into, v.v[1][1].to_s15_fixed16()); + write_i32_be(into, v.v[1][2].to_s15_fixed16()); + + write_i32_be(into, v.v[2][0].to_s15_fixed16()); + write_i32_be(into, v.v[2][1].to_s15_fixed16()); + write_i32_be(into, v.v[2][2].to_s15_fixed16()); +} + +#[inline] +fn write_vector3d(into: &mut Vec, v: Vector3d) { + write_i32_be(into, v.v[0].to_s15_fixed16()); + write_i32_be(into, v.v[1].to_s15_fixed16()); + write_i32_be(into, v.v[2].to_s15_fixed16()); +} + +#[inline] +fn write_lut_entry(into: &mut Vec, lut: &LutDataType) -> Result { + if !lut.has_same_kind() { + return Err(CmsError::InvalidProfile); + } + let start = into.len(); + let lut16_tag: u32 = match &lut.input_table { + LutStore::Store8(_) => LutType::Lut8.into(), + LutStore::Store16(_) => LutType::Lut16.into(), + }; + write_u32_be(into, lut16_tag); + write_u32_be(into, 0); + into.push(lut.num_input_channels); + into.push(lut.num_output_channels); + into.push(lut.num_clut_grid_points); + into.push(0); + write_matrix3d(into, lut.matrix); + write_u16_be(into, lut.num_input_table_entries); + write_u16_be(into, lut.num_output_table_entries); + match &lut.input_table { + LutStore::Store8(input_table) => { + for &item in input_table.iter() { + into.push(item); + } + } + LutStore::Store16(input_table) => { + for &item in input_table.iter() { + write_u16_be(into, item); + } + } + } + match &lut.clut_table { + LutStore::Store8(input_table) => { + for &item in input_table.iter() { + into.push(item); + } + } + LutStore::Store16(input_table) => { + for &item in input_table.iter() { + write_u16_be(into, item); + } + } + } + match &lut.output_table { + LutStore::Store8(input_table) => { + for &item in input_table.iter() { + into.push(item); + } + } + LutStore::Store16(input_table) => { + for &item in input_table.iter() { + write_u16_be(into, item); + } + } + } + let end = into.len(); + Ok(end - start) +} + +#[inline] +fn write_mab_entry( + into: &mut Vec, + lut: &LutMultidimensionalType, + is_a_to_b: bool, +) -> Result { + let start = into.len(); + let lut16_tag: u32 = if is_a_to_b { + LutType::LutMab.into() + } else { + LutType::LutMba.into() + }; + write_u32_be(into, lut16_tag); + write_u32_be(into, 0); + into.push(lut.num_input_channels); + into.push(lut.num_output_channels); + write_u16_be(into, 0); + let mut working_offset = 32usize; + + let mut data = Vec::new(); + + // Offset to "B curves" + if !lut.b_curves.is_empty() { + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + + write_u32_be(into, working_offset as u32); + + for trc in lut.b_curves.iter() { + let curve_size = write_trc_entry(&mut data, trc)?; + working_offset += curve_size; + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + } + } else { + write_u32_be(into, 0); + } + + // Offset to matrix + if !lut.m_curves.is_empty() { + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + + write_u32_be(into, working_offset as u32); + write_matrix3d(&mut data, lut.matrix); + write_vector3d(&mut data, lut.bias); + working_offset += 9 * 4 + 3 * 4; + // Offset to "M curves" + write_u32_be(into, working_offset as u32); + for trc in lut.m_curves.iter() { + let curve_size = write_trc_entry(&mut data, trc)?; + working_offset += curve_size; + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + } + } else { + // Offset to matrix + write_u32_be(into, 0); + // Offset to "M curves" + write_u32_be(into, 0); + } + + let mut clut_start = data.len(); + + // Offset to CLUT + if let Some(clut) = &lut.clut { + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + + clut_start = data.len(); + + write_u32_be(into, working_offset as u32); + + // Writing CLUT + for &pt in lut.grid_points.iter() { + data.push(pt); + } + data.push(match clut { + LutStore::Store8(_) => 1, + LutStore::Store16(_) => 2, + }); // Entry size + data.push(0); + data.push(0); + data.push(0); + match clut { + LutStore::Store8(store) => { + for &element in store.iter() { + data.push(element) + } + } + LutStore::Store16(store) => { + for &element in store.iter() { + write_u16_be(&mut data, element); + } + } + } + } else { + write_u32_be(into, 0); + } + + let clut_size = data.len() - clut_start; + working_offset += clut_size; + + // Offset to "A curves" + if !lut.a_curves.is_empty() { + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + + write_u32_be(into, working_offset as u32); + + for trc in lut.a_curves.iter() { + let curve_size = write_trc_entry(&mut data, trc)?; + working_offset += curve_size; + while working_offset % 4 != 0 { + data.push(0); + working_offset += 1; + } + } + } else { + write_u32_be(into, 0); + } + + into.extend(data); + + let end = into.len(); + Ok(end - start) +} + +fn write_lut(into: &mut Vec, lut: &LutWarehouse, is_a_to_b: bool) -> Result { + match lut { + LutWarehouse::Lut(lut) => Ok(write_lut_entry(into, lut)?), + LutWarehouse::Multidimensional(mab) => write_mab_entry(into, mab, is_a_to_b), + } +} + +impl ProfileHeader { + fn encode(&self) -> Vec { + let mut encoder: Vec = Vec::with_capacity(size_of::()); + write_u32_be(&mut encoder, self.size); // Size + write_u32_be(&mut encoder, 0); // CMM Type + write_u32_be(&mut encoder, self.version.into()); // Version Number Type + write_u32_be(&mut encoder, self.profile_class.into()); // Profile class + write_u32_be(&mut encoder, self.data_color_space.into()); // Data color space + write_u32_be(&mut encoder, self.pcs.into()); // PCS + self.creation_date_time.encode(&mut encoder); // Date time + write_u32_be(&mut encoder, self.signature.into()); // Profile signature + write_u32_be(&mut encoder, self.platform); + write_u32_be(&mut encoder, self.flags); + write_u32_be(&mut encoder, self.device_manufacturer); + write_u32_be(&mut encoder, self.device_model); + for &i in self.device_attributes.iter() { + encoder.push(i); + } + write_u32_be(&mut encoder, self.rendering_intent.into()); + write_i32_be(&mut encoder, self.illuminant.x.to_s15_fixed16()); + write_i32_be(&mut encoder, self.illuminant.y.to_s15_fixed16()); + write_i32_be(&mut encoder, self.illuminant.z.to_s15_fixed16()); + write_u32_be(&mut encoder, self.creator); + for &i in self.profile_id.iter() { + encoder.push(i); + } + for &i in self.reserved.iter() { + encoder.push(i); + } + write_u32_be(&mut encoder, self.tag_count); + encoder + } +} + +impl ColorProfile { + fn writable_tags_count(&self) -> usize { + let mut tags_count = 0usize; + if self.red_colorant != Xyzd::default() { + tags_count += 1; + } + if self.green_colorant != Xyzd::default() { + tags_count += 1; + } + if self.blue_colorant != Xyzd::default() { + tags_count += 1; + } + if self.red_trc.is_some() { + tags_count += 1; + } + if self.green_trc.is_some() { + tags_count += 1; + } + if self.blue_trc.is_some() { + tags_count += 1; + } + if self.gray_trc.is_some() { + tags_count += 1; + } + if self.cicp.is_some() { + tags_count += 1; + } + if self.media_white_point.is_some() { + tags_count += 1; + } + if self.gamut.is_some() { + tags_count += 1; + } + if self.chromatic_adaptation.is_some() { + tags_count += 1; + } + if self.lut_a_to_b_perceptual.is_some() { + tags_count += 1; + } + if self.lut_a_to_b_colorimetric.is_some() { + tags_count += 1; + } + if self.lut_a_to_b_saturation.is_some() { + tags_count += 1; + } + if self.lut_b_to_a_perceptual.is_some() { + tags_count += 1; + } + if self.lut_b_to_a_colorimetric.is_some() { + tags_count += 1; + } + if self.lut_b_to_a_saturation.is_some() { + tags_count += 1; + } + if self.luminance.is_some() { + tags_count += 1; + } + if let Some(description) = &self.description { + if description.has_values() { + tags_count += 1; + } + } + if let Some(copyright) = &self.copyright { + if copyright.has_values() { + tags_count += 1; + } + } + if self.viewing_conditions.is_some() { + tags_count += 1; + } + if let Some(vd) = &self.viewing_conditions_description { + if vd.has_values() { + tags_count += 1; + } + } + if let Some(vd) = &self.device_model { + if vd.has_values() { + tags_count += 1; + } + } + if let Some(vd) = &self.device_manufacturer { + if vd.has_values() { + tags_count += 1; + } + } + tags_count + } + + /// Encodes profile + pub fn encode(&self) -> Result, CmsError> { + let mut entries = Vec::new(); + let tags_count = self.writable_tags_count(); + let mut tags = Vec::with_capacity(TAG_SIZE * tags_count); + let mut base_offset = size_of::() + TAG_SIZE * tags_count; + if self.red_colorant != Xyzd::default() { + write_tag_entry(&mut tags, Tag::RedXyz, base_offset, 20); + write_xyz_tag_value(&mut entries, self.red_colorant); + base_offset += 20; + } + if self.green_colorant != Xyzd::default() { + write_tag_entry(&mut tags, Tag::GreenXyz, base_offset, 20); + write_xyz_tag_value(&mut entries, self.green_colorant); + base_offset += 20; + } + if self.blue_colorant != Xyzd::default() { + write_tag_entry(&mut tags, Tag::BlueXyz, base_offset, 20); + write_xyz_tag_value(&mut entries, self.blue_colorant); + base_offset += 20; + } + if let Some(chad) = self.chromatic_adaptation { + write_tag_entry(&mut tags, Tag::ChromaticAdaptation, base_offset, 8 + 9 * 4); + write_chad(&mut entries, chad); + base_offset += 8 + 9 * 4; + } + if let Some(trc) = &self.red_trc { + let entry_size = write_trc_entry(&mut entries, trc)?; + write_tag_entry(&mut tags, Tag::RedToneReproduction, base_offset, entry_size); + base_offset += entry_size; + } + if let Some(trc) = &self.green_trc { + let entry_size = write_trc_entry(&mut entries, trc)?; + write_tag_entry( + &mut tags, + Tag::GreenToneReproduction, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + if let Some(trc) = &self.blue_trc { + let entry_size = write_trc_entry(&mut entries, trc)?; + write_tag_entry( + &mut tags, + Tag::BlueToneReproduction, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + if let Some(trc) = &self.gray_trc { + let entry_size = write_trc_entry(&mut entries, trc)?; + write_tag_entry( + &mut tags, + Tag::GreyToneReproduction, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(media_wp) = self.media_white_point { + write_tag_entry(&mut tags, Tag::MediaWhitePoint, base_offset, 20); + write_xyz_tag_value(&mut entries, media_wp); + base_offset += 20; + } + + let has_cicp = self.cicp.is_some(); + + // This tag may be present when the data colour space in the profile header is RGB, YCbCr, or XYZ, and the + // profile class in the profile header is Input or Display. The tag shall not be present for other data colour spaces + // or profile classes indicated in the profile header. + + if let Some(cicp) = &self.cicp { + if (self.profile_class == ProfileClass::InputDevice + || self.profile_class == ProfileClass::DisplayDevice) + && (self.color_space == DataColorSpace::Rgb + || self.color_space == DataColorSpace::YCbr + || self.color_space == DataColorSpace::Xyz) + { + write_tag_entry(&mut tags, Tag::CodeIndependentPoints, base_offset, 12); + write_cicp_entry(&mut entries, cicp); + base_offset += 12; + } + } + + if let Some(lut) = &self.lut_a_to_b_perceptual { + let entry_size = write_lut(&mut entries, lut, true)?; + write_tag_entry( + &mut tags, + Tag::DeviceToPcsLutPerceptual, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.lut_a_to_b_colorimetric { + let entry_size = write_lut(&mut entries, lut, true)?; + write_tag_entry( + &mut tags, + Tag::DeviceToPcsLutColorimetric, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.lut_a_to_b_saturation { + let entry_size = write_lut(&mut entries, lut, true)?; + write_tag_entry( + &mut tags, + Tag::DeviceToPcsLutSaturation, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.lut_b_to_a_perceptual { + let entry_size = write_lut(&mut entries, lut, false)?; + write_tag_entry( + &mut tags, + Tag::PcsToDeviceLutPerceptual, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.lut_b_to_a_colorimetric { + let entry_size = write_lut(&mut entries, lut, false)?; + write_tag_entry( + &mut tags, + Tag::PcsToDeviceLutColorimetric, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.lut_b_to_a_saturation { + let entry_size = write_lut(&mut entries, lut, false)?; + write_tag_entry( + &mut tags, + Tag::PcsToDeviceLutSaturation, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + + if let Some(lut) = &self.gamut { + let entry_size = write_lut(&mut entries, lut, false)?; + write_tag_entry(&mut tags, Tag::Gamut, base_offset, entry_size); + base_offset += entry_size; + } + + if let Some(luminance) = self.luminance { + write_tag_entry(&mut tags, Tag::Luminance, base_offset, 20); + write_xyz_tag_value(&mut entries, luminance); + base_offset += 20; + } + + if let Some(description) = &self.description { + if description.has_values() { + let entry_size = write_string_value(&mut entries, description); + write_tag_entry(&mut tags, Tag::ProfileDescription, base_offset, entry_size); + base_offset += entry_size; + } + } + + if let Some(copyright) = &self.copyright { + if copyright.has_values() { + let entry_size = write_string_value(&mut entries, copyright); + write_tag_entry(&mut tags, Tag::Copyright, base_offset, entry_size); + base_offset += entry_size; + } + } + + if let Some(vc) = &self.viewing_conditions { + let entry_size = write_viewing_conditions_value(&mut entries, vc); + write_tag_entry(&mut tags, Tag::ObserverConditions, base_offset, entry_size); + base_offset += entry_size; + } + + if let Some(vd) = &self.viewing_conditions_description { + if vd.has_values() { + let entry_size = write_string_value(&mut entries, vd); + write_tag_entry( + &mut tags, + Tag::ViewingConditionsDescription, + base_offset, + entry_size, + ); + base_offset += entry_size; + } + } + + if let Some(vd) = &self.device_model { + if vd.has_values() { + let entry_size = write_string_value(&mut entries, vd); + write_tag_entry(&mut tags, Tag::DeviceModel, base_offset, entry_size); + base_offset += entry_size; + } + } + + if let Some(vd) = &self.device_manufacturer { + if vd.has_values() { + let entry_size = write_string_value(&mut entries, vd); + write_tag_entry(&mut tags, Tag::DeviceManufacturer, base_offset, entry_size); + // base_offset += entry_size; + } + } + + tags.extend(entries); + + let profile_header = ProfileHeader { + size: size_of::() as u32 + tags.len() as u32, + pcs: self.pcs, + profile_class: self.profile_class, + rendering_intent: self.rendering_intent, + cmm_type: 0, + version: if has_cicp { + ProfileVersion::V4_3 + } else if self.version_internal < ProfileVersion::V4_0 { + ProfileVersion::V4_0 + } else { + self.version_internal + }, + data_color_space: self.color_space, + creation_date_time: ColorDateTime::now(), + signature: ProfileSignature::Acsp, + platform: 0u32, + flags: 0u32, + device_manufacturer: 0u32, + device_model: 0u32, + device_attributes: [0u8; 8], + illuminant: self.white_point.to_xyz(), + creator: 0u32, + profile_id: [0u8; 16], + reserved: [0u8; 28], + tag_count: tags_count as u32, + }; + let mut header = profile_header.encode(); + header.extend(tags); + Ok(header) + } +} + +impl FloatToFixedU8Fixed8 for f32 { + #[inline] + fn to_u8_fixed8(self) -> u16 { + if self > 255.0 + 255.0 / 256f32 { + 0xffffu16 + } else if self < 0.0 { + 0u16 + } else { + (self * 256.0 + 0.5).floor() as u16 + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn to_u8_fixed8() { + assert_eq!(0, 0f32.to_u8_fixed8()); + assert_eq!(0x0100, 1f32.to_u8_fixed8()); + assert_eq!(u16::MAX, (255f32 + (255f32 / 256f32)).to_u8_fixed8()); + } + + #[test] + fn to_s15_fixed16() { + assert_eq!(0x80000000u32 as i32, (-32768f32).to_s15_fixed16()); + assert_eq!(0, 0f32.to_s15_fixed16()); + assert_eq!(0x10000, 1.0f32.to_s15_fixed16()); + assert_eq!( + i32::MAX, + (32767f32 + (65535f32 / 65536f32)).to_s15_fixed16() + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/xyy.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/xyy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/xyy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/xyy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::{Xyz, Xyzd}; + +/// Holds CIE XyY representation +#[derive(Clone, Debug, Copy, Default)] +pub struct XyY { + pub x: f64, + pub y: f64, + pub yb: f64, +} + +pub trait XyYRepresentable { + fn to_xyy(self) -> XyY; +} + +impl XyYRepresentable for XyY { + #[inline] + fn to_xyy(self) -> XyY { + self + } +} + +impl XyY { + #[inline] + pub const fn new(x: f64, y: f64, yb: f64) -> Self { + Self { x, y, yb } + } + + #[inline] + pub const fn to_xyz(self) -> Xyz { + let reciprocal = if self.y != 0. { + 1. / self.y * self.yb + } else { + 0. + }; + Xyz { + x: (self.x * reciprocal) as f32, + y: self.yb as f32, + z: ((1. - self.x - self.y) * reciprocal) as f32, + } + } + + #[inline] + pub const fn to_xyzd(self) -> Xyzd { + let reciprocal = if self.y != 0. { + 1. / self.y * self.yb + } else { + 0. + }; + Xyzd { + x: self.x * reciprocal, + y: self.yb, + z: (1. - self.x - self.y) * reciprocal, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_xyzd_xyy() { + let xyy = XyY::new(0.2, 0.4, 0.5); + let xyy = xyy.to_xyzd(); + let r_xyy = xyy.to_xyzd(); + assert!((r_xyy.x - xyy.x).abs() < 1e-5); + assert!((r_xyy.y - xyy.y).abs() < 1e-5); + assert!((r_xyy.z - xyy.z).abs() < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/yrg.rs clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/yrg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/moxcms/src/yrg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/moxcms/src/yrg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,177 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::mlaf::mlaf; +use crate::{Matrix3f, Vector3f, Xyz}; +use pxfm::{f_atan2f, f_hypotf, f_sincosf}; + +/// Structure for Yrg colorspace +/// +/// Kirk Yrg 2021. +#[repr(C)] +#[derive(Default, Debug, PartialOrd, PartialEq, Copy, Clone)] +pub struct Yrg { + pub y: f32, + pub r: f32, + pub g: f32, +} + +/// Structure for cone form of Yrg colorspace +#[repr(C)] +#[derive(Default, Debug, PartialOrd, PartialEq, Copy, Clone)] +pub struct Ych { + pub y: f32, + pub c: f32, + pub h: f32, +} + +const LMS_TO_XYZ: Matrix3f = Matrix3f { + v: [ + [1.8079466, -1.2997167, 0.34785876], + [0.61783963, 0.39595452, -0.041046873], + [-0.12546961, 0.20478038, 1.7427418], + ], +}; +const XYZ_TO_LMS: Matrix3f = Matrix3f { + v: [ + [0.257085, 0.859943, -0.031061], + [-0.394427, 1.175800, 0.106423], + [0.064856, -0.076250, 0.559067], + ], +}; + +impl Yrg { + #[inline] + pub const fn new(y: f32, r: f32, g: f32) -> Yrg { + Yrg { y, r, g } + } + + /// Convert [Xyz] D65 to [Yrg] + /// + /// Yrg defined in D65 white point. Ensure Xyz values is adapted. + /// Yrg use CIE XYZ 2006, adapt CIE XYZ 1931 by using [cie_y_1931_to_cie_y_2006] at first. + #[inline] + pub fn from_xyz(xyz: Xyz) -> Self { + let lms = XYZ_TO_LMS.f_mul_vector(Vector3f { + v: [xyz.x, xyz.y, xyz.z], + }); + let y = mlaf(0.68990272 * lms.v[0], 0.34832189, lms.v[1]); + + let a = lms.v[0] + lms.v[1] + lms.v[2]; + let l = if a == 0. { 0. } else { lms.v[0] / a }; + let m = if a == 0. { 0. } else { lms.v[1] / a }; + let r = mlaf(mlaf(0.02062, -0.6873, m), 1.0671, l); + let g = mlaf(mlaf(-0.05155, -0.0362, l), 1.7182, m); + Yrg { y, r, g } + } + + #[inline] + pub fn to_xyz(&self) -> Xyz { + let l = mlaf(0.95 * self.r, 0.38, self.g); + let m = mlaf(mlaf(0.03, 0.59, self.g), 0.02, self.r); + let den = mlaf(0.68990272 * l, 0.34832189, m); + let a = if den == 0. { 0. } else { self.y / den }; + let l0 = l * a; + let m0 = m * a; + let s0 = (1f32 - l - m) * a; + let v = Vector3f { v: [l0, m0, s0] }; + let x = LMS_TO_XYZ.f_mul_vector(v); + Xyz { + x: x.v[0], + y: x.v[1], + z: x.v[2], + } + } +} + +impl Ych { + #[inline] + pub const fn new(y: f32, c: f32, h: f32) -> Self { + Ych { y, c, h } + } + + #[inline] + pub fn from_yrg(yrg: Yrg) -> Self { + let y = yrg.y; + // Subtract white point. These are the r, g coordinates of + // sRGB (D50 adapted) (1, 1, 1) taken through + // XYZ D50 -> CAT16 D50->D65 adaptation -> LMS 2006 + // -> grading RGB conversion. + let r = yrg.r - 0.21902143; + let g = yrg.g - 0.54371398; + let c = f_hypotf(g, r); + let h = f_atan2f(g, r); + Self { y, c, h } + } + + #[inline] + pub fn to_yrg(&self) -> Yrg { + let y = self.y; + let c = self.c; + let h = self.h; + let sincos = f_sincosf(h); + let r = mlaf(0.21902143, c, sincos.1); + let g = mlaf(0.54371398, c, sincos.0); + Yrg { y, r, g } + } +} + +// Pipeline and ICC luminance is CIE Y 1931 +// Kirk Ych/Yrg uses CIE Y 2006 +// 1 CIE Y 1931 = 1.05785528 CIE Y 2006, so we need to adjust that. +// This also accounts for the CAT16 D50->D65 adaptation that has to be done +// to go from RGB to CIE LMS 2006. +// Warning: only applies to achromatic pixels. +pub const fn cie_y_1931_to_cie_y_2006(x: f32) -> f32 { + 1.05785528 * (x) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_yrg() { + let xyz = Xyz::new(0.95, 1.0, 1.08); + let yrg = Yrg::from_xyz(xyz); + let yrg_to_xyz = yrg.to_xyz(); + assert!((xyz.x - yrg_to_xyz.x) < 1e-5); + assert!((xyz.y - yrg_to_xyz.y) < 1e-5); + assert!((xyz.z - yrg_to_xyz.z) < 1e-5); + } + + #[test] + fn test_ych() { + let xyz = Yrg::new(0.5, 0.4, 0.3); + let yrg = Ych::from_yrg(xyz); + let yrg_to_xyz = yrg.to_yrg(); + assert!((xyz.y - yrg_to_xyz.y) < 1e-5); + assert!((xyz.r - yrg_to_xyz.r) < 1e-5); + assert!((xyz.g - yrg_to_xyz.g) < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"6786bdb6b634c67c60a14a18d6ea40add943b29ed483bb9e2693b22e28af18d1",".travis.yml":"d91d0d75087934c2d0503a8c04439fea459a19182021bb0b699644d442f5b6fc","Cargo.lock":"b2b94213dc095ad155858adb9342ccee8f5839b30761c77a8c2a1a90c6f28ce2","Cargo.toml":"c89bebeeaf164811c20eca172f592e26a1d21d8d91b3c9a367ad745015eb78e2","Cargo.toml.orig":"3ec7bb009318c1d1a148c1c1a9c12be9279ab73b72615f1edadaa90f9b6856ca","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"614d60e78bd8c3d8172b2650f86d44c703471dab8a35805736861f09158e5501","examples/simple.rs":"f1fac7f8308469568b601218ea03d213584f0a51b779a3bcb78ecb40ede72483","src/lib.rs":"84efbf03c7f7d97e3133ad03da3b9a6941a2c1ea28134a60d82270423f9a807d","tests/check.rs":"85c0af86aa50de966d85c19fb88b47aec8c85532185b63cae0bef9c787baead5"},"package":"650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4b3fa6e0b6d728ed2018690e087a440dd29e7d06" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/.travis.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +language: rust diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "new_debug_unreachable" +version = "1.0.6" +authors = [ + "Matt Brubeck ", + "Jonathan Reem ", +] +description = "panic in debug, intrinsics::unreachable() in release (fork of debug_unreachable)" +documentation = "https://docs.rs/new_debug_unreachable" +readme = "README.md" +keywords = [ + "optimization", + "macro", +] +categories = [ + "rust-patterns", + "no-std", +] +license = "MIT" +repository = "https://github.com/mbrubeck/rust-debug-unreachable" + +[lib] +name = "debug_unreachable" +path = "src/lib.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +[package] +edition = "2021" +name = "new_debug_unreachable" +version = "1.0.6" +authors = ["Matt Brubeck ", "Jonathan Reem "] +repository = "https://github.com/mbrubeck/rust-debug-unreachable" +description = "panic in debug, intrinsics::unreachable() in release (fork of debug_unreachable)" +documentation = "https://docs.rs/new_debug_unreachable" +license = "MIT" +keywords = ["optimization", "macro"] +categories = ["rust-patterns", "no-std"] + +[lib] +name = "debug_unreachable" +path = "src/lib.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2015 Jonathan Reem + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/README.md clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +# new_debug_unreachable + +> unreachable!() in debug, std::intrinsics::unreachable() in release. + +This is a fork of [`debug_unreachable`](https://crates.io/crates/debug_unreachable). + +## [Documentation](https://docs.rs/new_debug_unreachable) + +## Usage + +Use the crates.io repository; add this to your `Cargo.toml` along +with the rest of your dependencies: + +```toml +[dependencies] +new_debug_unreachable = "1.0" +``` + +In your Rust code, the library name is still `debug_unreachable`: + +```rust +use debug_unreachable::debug_unreachable; + +fn main() { + if 0 > 100 { + // Can't happen! + unsafe { debug_unreachable!() } + } else { + println!("Good, 0 <= 100."); + } +} +``` + +## Author + +[Jonathan Reem](https://medium.com/@jreem) is the original author of debug-unreachable. + +[Matt Brubeck](https://limpet.net/mbrubeck/) is the maintainer of this fork. + +## License + +MIT diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/examples/simple.rs clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/examples/simple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/examples/simple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/examples/simple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +use debug_unreachable::debug_unreachable; + +fn main() { + if 0 > 100 { + // Can't happen! + unsafe { debug_unreachable!() } + } else { + println!("Good, 0 <= 100."); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +#![no_std] + +//! `panic!()` in debug builds, optimization hint in release. + +#[doc(hidden)] +pub mod _internal { + pub use core::hint::unreachable_unchecked; +} + +#[macro_export] +/// `panic!()` in debug builds, optimization hint in release. +/// +/// This is equivalent to [`core::unreachable`] in debug builds, +/// and [`core::hint::unreachable_unchecked`] in release builds. +/// +/// Example: +/// +/// ``` +/// use debug_unreachable::debug_unreachable; +/// +/// if 0 > 100 { +/// // Can't happen! +/// unsafe { debug_unreachable!() } +/// } else { +/// println!("Good, 0 <= 100."); +/// } +/// ``` +macro_rules! debug_unreachable { + () => { + debug_unreachable!("entered unreachable code") + }; + ($e:expr) => { + if cfg!(debug_assertions) { + unreachable!($e) + } else { + $crate::_internal::unreachable_unchecked() + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/tests/check.rs clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/tests/check.rs --- clamav-1.4.3+dfsg/.cargo/vendor/new_debug_unreachable/tests/check.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/new_debug_unreachable/tests/check.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +#[test] +#[should_panic] +#[cfg(debug_assertions)] +fn explodes_in_debug() { + use debug_unreachable::debug_unreachable; + unsafe { debug_unreachable!() } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/nom/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"fd79f8ab367d50fd57136744fa2e0a198c279c9707c2a45f00ad1b62d0a637ab","Cargo.lock":"3b95f09a31e1fc281ef890f9623ac84f0a58bc3454a96b652d2f0682963f29b5","Cargo.toml":"9d07fd5cc339d8f7c0c164b2568164b808dee1d441b17631cb7b7d44d39ed778","LICENSE":"4dbda04344456f09a7a588140455413a9ac59b6b26a1ef7cdf9c800c012d87f0","README.md":"3cbdcb07f9ef189ad617f40423a17f1e48ee5aba3f118f261886c139d64d26ae","doc/nom_recipes.md":"a903a6d8f9e5c935f2a4cbd632f67bc46e41934d1cc8517da9b9e7f3840c9955","src/bits/complete.rs":"640bdcad311a05d94e4b3a1a8b2105c540f80864edb75de0a570f03d4055e5ed","src/bits/mod.rs":"1c6aa26887d379384c1c823684e6f8e91b59df72664eefd8ddf0b6ca5517e669","src/bits/streaming.rs":"304cc5d565cfa30075827c1d6cb173b7cb92b101d8ebe9bc50476a00c92fd5dc","src/branch/mod.rs":"dbe1ed1bb0230310adf8e8d15e6afcf8826c7a111f8429e13fe3e9ebd3fbeae0","src/branch/tests.rs":"9a4a7b0c38fc28881d904f8ad6757a23e543f47a4c2d6fd6a9589eeb97209088","src/bytes/complete.rs":"666fa037c63292b1616cbc04c5b414a53c705d0d2ccd8d84399bbe78f573b7e9","src/bytes/mod.rs":"055e264f71a9fa2245be652cc747cfb2c3e34c3c2ba3b75e9611be51fcebea0b","src/bytes/streaming.rs":"e716e6555fbde14bfc2d7358a3edc2191df0522bc55b1f7735f9809ceb235829","src/bytes/tests.rs":"f0d9eb90d72873346e47e5592d30093eb38cbbb5fbf2e769cda776ccfff4f887","src/character/complete.rs":"7eeb5f00baab7aeaf7f392e5872d141d352951a146c0396721dab71e29b4c87b","src/character/mod.rs":"2fc6a3b19b766a3c37328d62eedbc0c9cb9612aa1d38ececd5cc579b61725fa2","src/character/streaming.rs":"de67ec5663475bc5ffa16f12d121ce9181353b16656b90216704197fca3010fc","src/character/tests.rs":"38958a709f96f077f93a72b32d8ded0a2ad6e488d9aadbe3cf1cfd8adaec06c8","src/combinator/mod.rs":"f7b9c35734f10a4b46d2e2ae874628d48fa1fe0bfc9f44325a89a14b3cfaea02","src/combinator/tests.rs":"1e56e2c1263d93bfbd244d24160a0bea41731e5158d57382e69c215427770b94","src/error.rs":"9d9bf87e76b47cfd9170f8ae50b6deeb02ff1c296aac3eb4f71ee1474dc0fba5","src/internal.rs":"5e670e0f5955af13da4b9a98d444fc721d38835b4637fe8170871fefef4e04cb","src/lib.rs":"9e05f2447ef1e5e9418953300c97d297f26f8f33c0528733a7681d8cb458346e","src/macros.rs":"11ac3dee346e5bf61015f328975cf6ea6f438683eb3b8b6c7c8e6383b0c5b7af","src/multi/mod.rs":"6093bd5909ddae76309442eba3a33716d279d219e5933a0dedef977312d6c5f8","src/multi/tests.rs":"806f89f5f347978c22e9b8cc7f8a49ad1d1fe23bff5974725b643a2ceffe8cb0","src/number/complete.rs":"a4f312c200710a446986142d19ebc78727265cf2c3b07b70dd84339051040bdd","src/number/mod.rs":"ba6eb439ee0befcc0872be7ce43b4836622af45c3dc2fc003b0d909ee42d7b20","src/number/streaming.rs":"1c2137235f093857e545069d687f50712ea457fac03961f3f6ac15c0f7e40c2a","src/sequence/mod.rs":"2dff114a950965e321cafdb215a441990f35d28756b12b2891179f348268fca2","src/sequence/tests.rs":"8dc4ca519b274d4e0694b373b2710c2e947e6074d43ec6a738a74113a09379f5","src/str.rs":"f26aa11f43e8a4a300ea0f310d599fab3f809102cfb29033ddf84f299ee8010c","src/traits.rs":"01934f8a61fc3cc5a03438a10751d3b074c89e5f3bcc96df8e43cf6b09be2308","tests/arithmetic.rs":"725efba4fc6cc811f542f3bcc8c7afd52702a66f64319d4f2796225e2e75d0ca","tests/arithmetic_ast.rs":"c7c28c988640405dd250c86045bbda75fc6ead2a769fb05eafbfbe74d97e0485","tests/css.rs":"36a2198e42e601efc611ebd6b3c6861f3ccb6a63525829ae6a2603bcdc4c2b11","tests/custom_errors.rs":"354d5a82a4f5a24b97901a3b411b4eab038c4d034047971956b9cdc12538e50d","tests/escaped.rs":"c25987ea6d9a7dde74d58a49c332d223da3a495569cb79e3fe921bce51729ead","tests/float.rs":"cdac92fb14afb75cba9d6b8f568e272a630b2cfb9f096b76c91909a3cd016869","tests/fnmut.rs":"dc9b6140eb3405d1497b05675fc4d3050785771a2afa81990d684b2edd0c9746","tests/ini.rs":"f0ce38b90057e9e0fd2329819395c420cbf1400457f9c4279414301faa38b19c","tests/ini_str.rs":"4c8f6ce3a2a245e8365837b873c25d2d8f24887313b791e2edd09a76a2d98947","tests/issues.rs":"1322ffc270ba1bedf39b295eb622ead2715ab7d60db0181af5305a0429c7819e","tests/json.rs":"8672fca70b889d6243a2f0f4c99389e22200e4363f253e83a3f26620b92f765e","tests/mp4.rs":"db6568ee9ccad70a7b567295831b961b369011f66dc2dd406851208007588600","tests/multiline.rs":"aef9768beaf5042b8629599b2094712646abb23eb11fa662b5a9bf3dfa432547","tests/overflow.rs":"a249ebeebfc5228faf9bfd5241a54a8181df476c4699ef87bb7d8a2161b9fc72","tests/reborrow_fold.rs":"66230bacd8d36e1559f1dc919ae8eab3515963c4aef85a079ec56218c9a6e676"},"package":"d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e10f44062736af6c6ad421467db3f7d0ccc3c1dc65a2ee1d5e9530e0d793e60c","CHANGELOG.md":"d526d20deb0dd12f2f6e528f786029f4e14c880cb75f2d82ec8807364c74be31","Cargo.lock":"2b4341e0af086bbac33e82e11353047449fd66cc1b86770133bac8007eb5da95","Cargo.toml":"0c4c034419168b542235727a352b8c3d12476d839480a6e933f4fc7966c6a812","Cargo.toml.orig":"74762db5ea3fb7dbb7aed12c1851e05cca0a37c8fd7bfef82e0d5b0d9aef7e95","LICENSE":"4dbda04344456f09a7a588140455413a9ac59b6b26a1ef7cdf9c800c012d87f0","README.md":"f0f855c2c2e4b5a69c7e901440665ee85aca748c6d73ea14f1ca952318a61fbe","doc/nom_recipes.md":"432e837e6b280ad9842868d20076d43d8dcdd9aea9ed6ab32a6e62c2a00c5d38","src/bits/complete.rs":"467122d4056c0e2655fd4ba087f1ee5042fb86453b662ae7ebe2e42c0066a09a","src/bits/mod.rs":"6b8e799f513834da948525002cb0e2a0b5da5f71715c443ede31bdd18424df36","src/bits/streaming.rs":"dfba58d569c1ab89f6cb9e33153775ed19d45385e39d5047eb717c44b07e3cc0","src/branch/mod.rs":"f99d29c4b001b500cc5226ccff5c13a250da06cc7428e76b3bc61125fb11c5d1","src/branch/tests.rs":"fb8198d2a6945bbefc153217634a306d27fe465664472ce29c61421841b3e4a6","src/bytes/complete.rs":"40682a06b92fcbd3f4e7c8b266b12dcfc797b715cc55d5f5c5073616a55efe1b","src/bytes/mod.rs":"219f031a11dab2ae1d2a08b37a1c1a7fc641c7e1338a42826f9809dc7c309510","src/bytes/streaming.rs":"6c1e454839c99fcb19704ee82b1b74b5492073dc71faa364694853d2a564ca11","src/bytes/tests.rs":"6ae0aa7a97daa291ec68aa20cc8635ac7665374194c665251240e3534dab991c","src/character/complete.rs":"1d0c6a7f9cfc97164f17c87e9125981c2a0814904d0de2a7ba6f4019d3d30ca0","src/character/mod.rs":"e713c9a56e5c3e2757b4685048139509fe58e18985c06be9192fbb8bbae3213e","src/character/streaming.rs":"b883f3d745d16b0ec163c5d14feae1e255f2809da540eb507c2d63e0ac146e10","src/character/tests.rs":"faa8053912f374bb5228f5269e9f8aa13e60c23d239d6acae39463892018b348","src/combinator/mod.rs":"a75359d9f86a2494c850d64e7b4dcc4550509ec1fae2dfb49aba5edc9c62e2ab","src/combinator/tests.rs":"46290c938f132a8a01aafd58d6e63e6da851282a22c1db41a430d1d780b4373d","src/error.rs":"4a73ae2a2743b3dd029ad76ebed264af73fef875d061189abdaabf026acb89a8","src/internal.rs":"c3df969cc76196d2f9903d9ff2c0ce8a58c766efbf92216f4797d945a6f980ee","src/lib.rs":"6022ac91a16e3f00f458cac7a198a81fcd6bee5dc9e75903d3438f447eb70fd7","src/macros.rs":"11ac3dee346e5bf61015f328975cf6ea6f438683eb3b8b6c7c8e6383b0c5b7af","src/multi/mod.rs":"6426717e34019ef32c00cc86d8b2683f7c4510e2c056e7762cce7595dab14bce","src/multi/tests.rs":"6107a64f4bb6675fbb93c5835f89992d03252e98fa29a86a44cf8894050c9ab7","src/number/complete.rs":"63ad29969e4f20dcfd7acc6fc08e60f9e3d90b1c3e574267ef274f56468464d7","src/number/mod.rs":"353111b0cadc422ee4b89ac4881262187276a39f5a65d0f391fb3f2df7c9d35b","src/number/streaming.rs":"a18ff0a3aaa79d68956c0dae1ecd6bc997edc0ea2b568208a6a2542acd80bfe5","src/sequence/mod.rs":"6e7e65213283c2fbfa2297fae0ae1d1f02a2fb6ee5e79dde761974054815814c","src/sequence/tests.rs":"2a80de26fd6d8725626c1ae2009b17ca6fda38b1f993426cb2706c05ccb5737a","src/str.rs":"c781cd3f7eb00e3d9d1426302311c7f0594a912391e615af4f36cc84c6d35751","src/traits.rs":"3bcc85e2272c75dfcd915d1be5e68243c3ac3282f36530021b31ce6f02ddca65","tests/arithmetic.rs":"06250fb1f4a6c244962dbf303d4d6013735dcabc39a706bff2046f2e8c6e8c28","tests/arithmetic_ast.rs":"0556e8fddc6897859615ccc36a033e64230d0c95d22e271522daff1513757bc7","tests/css.rs":"38efa43acc5db47a26e38992418ccd90e2700329d6fa2bb0f02a4ee7b9abb888","tests/custom_errors.rs":"70a03680a51491963ce35db88b4b82963645fb93f28330375c4041db53a4d1a3","tests/escaped.rs":"c25987ea6d9a7dde74d58a49c332d223da3a495569cb79e3fe921bce51729ead","tests/expression_ast.rs":"c6ddae04e679c9b7fab38ac791165a9f6b017765be0d687c2f49ec3d1afe174a","tests/float.rs":"8f1726722408d84d73c0c228ec7030b44a7c6dbafdf64aa9c4ced7ebced3b38c","tests/fnmut.rs":"5a7fc3fc894b1f4ebe59c7e4031c12961127141aeab29b9a94a4c013beabb5fc","tests/ini.rs":"f3abce04662afac6a838dd51aa152f227a0f631690f7149f18aa2c869de90fd9","tests/ini_str.rs":"a72dfd595fbffffd3acd70101a72cd60b91155e5fe13c2f5b4e92b51aa7ea2ab","tests/issues.rs":"1362fe74beb28042b25970010e20727ee0ed73082427c34f6e686bcc4ff3fc0e","tests/json.rs":"5f18e41dc7b798c2e2791704ffaefdc63339b8b9d712abe4a4a02e8db129ff05","tests/mp4.rs":"f51615d6e2d0a91f5a8f047f76d022bc6a47a2c2359d92c3e7d65e5e0ed30610","tests/multiline.rs":"d7367add37522a0f6ee51df2f3b22f2cf17d3edf3eb96ec1761d002e1231bd6e","tests/overflow.rs":"cdcb03394274f18af9931fbe391ac39d40d3c8c58b731b5ca90a02663fea131c","tests/reborrow_fold.rs":"bad74bd77d4ea5b485d0a74ffcdb352f11bdde4666bd1706e9d1fa881896d4c3"},"package":"df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/nom/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "2cec1b3e4c9ccac62c902d60c00de6d1549ccbe1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/nom/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,20 +1,75 @@ # Change Log -## [Unreleased][unreleased] +## 8.0.0 2025-01-25 -### Thanks - -### Changed +This versions represents a significant refactoring of nom to reduce the amount of code generated by prsers, and reduce the API surface. As such, it comes with some breaking changes, mostly around the move from closure based combinators to trait based ones. In practice, it means that instead of writing `combinator(arg)(input)`, we now write `combinator(arg).parse(input)`. -## 7.1.3 - 2023-01-15 +This release also marks th introduction of the [nom-language](https://crates.io/crates/nom-language) crate, which will hold tools more focused on language parsing than the rest of nom, like the `VerboseError` type and the newly added precedence parsing combinators. ### Thanks +- @cky +- @5c077m4n +- @epage +- @Fumon +- @jtracey +- @OliveIsAWord +- @Xiretza +- @flier +- @cenodis - @Shadow53 +- @@jmmaa +- @terror +- @zanedp +- @atouchet +- @CMDJojo +- @ackxolotl +- @xmakro +- @tfpk +- @WhyNotHugo +- @brollb +- @smheidrich +- @glittershark +- @GuillaumeGomez +- @LeoDog896 +- @fmiras +- @ttsugriy +- @McDostone +- @superboum +- @rruppy +- @thssuck +- @Chasing1020 +- @thatmarkenglishguy +- @ambiso +- @boxdot +- @krtab +- @code10129 +- @manunio +- @stuarth +- @mindeng +- @JonathanPlasse +- @nabilwadih +- @phoenixr-codes +- @gdennie +- @art049 +- @kstrohbeck -### Fixed +### Added + +- `Parser::map_res` +- `Parser::map_opt` +- `many` and `fold` combinators using ranges +- `many` can collect into other types than `Vec` +- `Error` and `VerboseError` can be converted to owned versions -- panic in `many` and `count` combinators when the output type is zero sized +### Removed + +- `nom::bits::*` is no longer re-exported at the crate root. This export caused frequent confusion, since e.g. `nom::complete::tag` referred to `nom::bits::complete::tag` instead of the much more commonly used `nom::bytes::complete::tag`. To migrate, change any imports of `nom::{complete::*, streaming::*, bits, bytes}` to `nom::bits::[...]`. +- `parse` combinator +- `InputIter`, `InputTakeAtPosition`, `InputLength`, `InputTake` and `Slice` are now merged in the `Input` trait + +### Changed +- `Parser::map` and `Parser::flat_map` now take a `FnMut` as argument ## 7.1.2 - 2023-01-01 @@ -916,7 +971,7 @@ The 2.0 release is one of the biggest yet. It was a good opportunity to clean up some badly named combinators and fix invalid behaviours. -Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented. +Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/rust-bakery/nom/blob/main/doc/archive/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented. This version also adds a lot of interesting features, like the permutation combinator or whitespace separated formats support. @@ -1431,7 +1486,7 @@ ### Added - `peek!` macro: matches the future input but does not consume it - `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser -- benchmarks are available at https://github.com/Geal/nom_benchmarks +- benchmarks are available at https://github.com/rust-bakery/parser_benchmarks - more documentation - **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions. - `named!`, `closure!` and `call!` macros used to support the unnamed syntax @@ -1485,67 +1540,68 @@ ## Compare code -* [unreleased](https://github.com/Geal/nom/compare/7.1.3...HEAD) -* [7.1.2](https://github.com/Geal/nom/compare/7.1.2...7.1.3) -* [7.1.2](https://github.com/Geal/nom/compare/7.1.1...7.1.2) -* [7.1.1](https://github.com/Geal/nom/compare/7.1.0...7.1.1) -* [7.1.0](https://github.com/Geal/nom/compare/7.0.0...7.1.0) -* [7.0.0](https://github.com/Geal/nom/compare/6.2.1...7.0.0) -* [6.2.1](https://github.com/Geal/nom/compare/6.2.0...6.2.1) -* [6.2.0](https://github.com/Geal/nom/compare/6.1.2...6.2.0) -* [6.1.2](https://github.com/Geal/nom/compare/6.1.1...6.1.2) -* [6.1.1](https://github.com/Geal/nom/compare/6.1.0...6.1.1) -* [6.1.0](https://github.com/Geal/nom/compare/6.0.1...6.1.0) -* [6.0.1](https://github.com/Geal/nom/compare/6.0.0...6.0.1) -* [6.0.0](https://github.com/Geal/nom/compare/5.1.1...6.0.0) -* [5.1.1](https://github.com/Geal/nom/compare/5.1.0...5.1.1) -* [5.1.0](https://github.com/Geal/nom/compare/5.0.1...5.1.0) -* [5.0.1](https://github.com/Geal/nom/compare/5.0.0...5.0.1) -* [5.0.0](https://github.com/Geal/nom/compare/4.2.3...5.0.0) -* [4.2.3](https://github.com/Geal/nom/compare/4.2.2...4.2.3) -* [4.2.2](https://github.com/Geal/nom/compare/4.2.1...4.2.2) -* [4.2.1](https://github.com/Geal/nom/compare/4.2.0...4.2.1) -* [4.2.0](https://github.com/Geal/nom/compare/4.1.1...4.2.0) -* [4.1.1](https://github.com/Geal/nom/compare/4.1.0...4.1.1) -* [4.1.0](https://github.com/Geal/nom/compare/4.0.0...4.1.0) -* [4.0.0](https://github.com/Geal/nom/compare/3.2.1...4.0.0) -* [3.2.1](https://github.com/Geal/nom/compare/3.2.0...3.2.1) -* [3.2.0](https://github.com/Geal/nom/compare/3.1.0...3.2.0) -* [3.1.0](https://github.com/Geal/nom/compare/3.0.0...3.1.0) -* [3.0.0](https://github.com/Geal/nom/compare/2.2.1...3.0.0) -* [2.2.1](https://github.com/Geal/nom/compare/2.2.0...2.2.1) -* [2.2.0](https://github.com/Geal/nom/compare/2.1.0...2.2.0) -* [2.1.0](https://github.com/Geal/nom/compare/2.0.1...2.1.0) -* [2.0.1](https://github.com/Geal/nom/compare/2.0.0...2.0.1) -* [2.0.0](https://github.com/Geal/nom/compare/1.2.4...2.0.0) -* [1.2.4](https://github.com/Geal/nom/compare/1.2.3...1.2.4) -* [1.2.3](https://github.com/Geal/nom/compare/1.2.2...1.2.3) -* [1.2.2](https://github.com/Geal/nom/compare/1.2.1...1.2.2) -* [1.2.1](https://github.com/Geal/nom/compare/1.2.0...1.2.1) -* [1.2.0](https://github.com/Geal/nom/compare/1.1.0...1.2.0) -* [1.1.0](https://github.com/Geal/nom/compare/1.0.1...1.1.0) -* [1.0.1](https://github.com/Geal/nom/compare/1.0.0...1.0.1) -* [1.0.0](https://github.com/Geal/nom/compare/0.5.0...1.0.0) -* [0.5.0](https://github.com/geal/nom/compare/0.4.0...0.5.0) -* [0.4.0](https://github.com/geal/nom/compare/0.3.11...0.4.0) -* [0.3.11](https://github.com/geal/nom/compare/0.3.10...0.3.11) -* [0.3.10](https://github.com/geal/nom/compare/0.3.9...0.3.10) -* [0.3.9](https://github.com/geal/nom/compare/0.3.8...0.3.9) -* [0.3.8](https://github.com/Geal/nom/compare/0.3.7...0.3.8) -* [0.3.7](https://github.com/Geal/nom/compare/0.3.6...0.3.7) -* [0.3.6](https://github.com/Geal/nom/compare/0.3.5...0.3.6) -* [0.3.5](https://github.com/Geal/nom/compare/0.3.4...0.3.5) -* [0.3.4](https://github.com/Geal/nom/compare/0.3.3...0.3.4) -* [0.3.3](https://github.com/Geal/nom/compare/0.3.2...0.3.3) -* [0.3.2](https://github.com/Geal/nom/compare/0.3.1...0.3.2) -* [0.3.1](https://github.com/Geal/nom/compare/0.3.0...0.3.1) -* [0.3.0](https://github.com/Geal/nom/compare/0.2.2...0.3.0) -* [0.2.2](https://github.com/Geal/nom/compare/0.2.1...0.2.2) -* [0.2.1](https://github.com/Geal/nom/compare/0.2.0...0.2.1) -* [0.2.0](https://github.com/Geal/nom/compare/0.1.6...0.2.0) -* [0.1.6](https://github.com/Geal/nom/compare/0.1.5...0.1.6) -* [0.1.5](https://github.com/Geal/nom/compare/0.1.4...0.1.5) -* [0.1.4](https://github.com/Geal/nom/compare/0.1.3...0.1.4) -* [0.1.3](https://github.com/Geal/nom/compare/0.1.2...0.1.3) -* [0.1.2](https://github.com/Geal/nom/compare/0.1.1...0.1.2) -* [0.1.1](https://github.com/Geal/nom/compare/0.1.0...0.1.1) +* [unreleased](https://github.com/rust-bakery/nom/compare/8.0.0...HEAD) +* [8.0.0](https://github.com/rust-bakery/nom/compare/7.1.3...8.0.0) +* [7.1.3](https://github.com/rust-bakery/nom/compare/7.1.2...7.1.3) +* [7.1.2](https://github.com/rust-bakery/nom/compare/7.1.1...7.1.2) +* [7.1.1](https://github.com/rust-bakery/nom/compare/7.1.0...7.1.1) +* [7.1.0](https://github.com/rust-bakery/nom/compare/7.0.0...7.1.0) +* [7.0.0](https://github.com/rust-bakery/nom/compare/6.2.1...7.0.0) +* [6.2.1](https://github.com/rust-bakery/nom/compare/6.2.0...6.2.1) +* [6.2.0](https://github.com/rust-bakery/nom/compare/6.1.2...6.2.0) +* [6.1.2](https://github.com/rust-bakery/nom/compare/6.1.1...6.1.2) +* [6.1.1](https://github.com/rust-bakery/nom/compare/6.1.0...6.1.1) +* [6.1.0](https://github.com/rust-bakery/nom/compare/6.0.1...6.1.0) +* [6.0.1](https://github.com/rust-bakery/nom/compare/6.0.0...6.0.1) +* [6.0.0](https://github.com/rust-bakery/nom/compare/5.1.1...6.0.0) +* [5.1.1](https://github.com/rust-bakery/nom/compare/5.1.0...5.1.1) +* [5.1.0](https://github.com/rust-bakery/nom/compare/5.0.1...5.1.0) +* [5.0.1](https://github.com/rust-bakery/nom/compare/5.0.0...5.0.1) +* [5.0.0](https://github.com/rust-bakery/nom/compare/4.2.3...5.0.0) +* [4.2.3](https://github.com/rust-bakery/nom/compare/4.2.2...4.2.3) +* [4.2.2](https://github.com/rust-bakery/nom/compare/4.2.1...4.2.2) +* [4.2.1](https://github.com/rust-bakery/nom/compare/4.2.0...4.2.1) +* [4.2.0](https://github.com/rust-bakery/nom/compare/4.1.1...4.2.0) +* [4.1.1](https://github.com/rust-bakery/nom/compare/4.1.0...4.1.1) +* [4.1.0](https://github.com/rust-bakery/nom/compare/4.0.0...4.1.0) +* [4.0.0](https://github.com/rust-bakery/nom/compare/3.2.1...4.0.0) +* [3.2.1](https://github.com/rust-bakery/nom/compare/3.2.0...3.2.1) +* [3.2.0](https://github.com/rust-bakery/nom/compare/3.1.0...3.2.0) +* [3.1.0](https://github.com/rust-bakery/nom/compare/3.0.0...3.1.0) +* [3.0.0](https://github.com/rust-bakery/nom/compare/2.2.1...3.0.0) +* [2.2.1](https://github.com/rust-bakery/nom/compare/2.2.0...2.2.1) +* [2.2.0](https://github.com/rust-bakery/nom/compare/2.1.0...2.2.0) +* [2.1.0](https://github.com/rust-bakery/nom/compare/2.0.1...2.1.0) +* [2.0.1](https://github.com/rust-bakery/nom/compare/2.0.0...2.0.1) +* [2.0.0](https://github.com/rust-bakery/nom/compare/1.2.4...2.0.0) +* [1.2.4](https://github.com/rust-bakery/nom/compare/1.2.3...1.2.4) +* [1.2.3](https://github.com/rust-bakery/nom/compare/1.2.2...1.2.3) +* [1.2.2](https://github.com/rust-bakery/nom/compare/1.2.1...1.2.2) +* [1.2.1](https://github.com/rust-bakery/nom/compare/1.2.0...1.2.1) +* [1.2.0](https://github.com/rust-bakery/nom/compare/1.1.0...1.2.0) +* [1.1.0](https://github.com/rust-bakery/nom/compare/1.0.1...1.1.0) +* [1.0.1](https://github.com/rust-bakery/nom/compare/1.0.0...1.0.1) +* [1.0.0](https://github.com/rust-bakery/nom/compare/0.5.0...1.0.0) +* [0.5.0](https://github.com/rust-bakery/nom/compare/0.4.0...0.5.0) +* [0.4.0](https://github.com/rust-bakery/nom/compare/0.3.11...0.4.0) +* [0.3.11](https://github.com/rust-bakery/nom/compare/0.3.10...0.3.11) +* [0.3.10](https://github.com/rust-bakery/nom/compare/0.3.9...0.3.10) +* [0.3.9](https://github.com/rust-bakery/nom/compare/0.3.8...0.3.9) +* [0.3.8](https://github.com/rust-bakery/nom/compare/0.3.7...0.3.8) +* [0.3.7](https://github.com/rust-bakery/nom/compare/0.3.6...0.3.7) +* [0.3.6](https://github.com/rust-bakery/nom/compare/0.3.5...0.3.6) +* [0.3.5](https://github.com/rust-bakery/nom/compare/0.3.4...0.3.5) +* [0.3.4](https://github.com/rust-bakery/nom/compare/0.3.3...0.3.4) +* [0.3.3](https://github.com/rust-bakery/nom/compare/0.3.2...0.3.3) +* [0.3.2](https://github.com/rust-bakery/nom/compare/0.3.1...0.3.2) +* [0.3.1](https://github.com/rust-bakery/nom/compare/0.3.0...0.3.1) +* [0.3.0](https://github.com/rust-bakery/nom/compare/0.2.2...0.3.0) +* [0.2.2](https://github.com/rust-bakery/nom/compare/0.2.1...0.2.2) +* [0.2.1](https://github.com/rust-bakery/nom/compare/0.2.0...0.2.1) +* [0.2.0](https://github.com/rust-bakery/nom/compare/0.1.6...0.2.0) +* [0.1.6](https://github.com/rust-bakery/nom/compare/0.1.5...0.1.6) +* [0.1.5](https://github.com/rust-bakery/nom/compare/0.1.4...0.1.5) +* [0.1.4](https://github.com/rust-bakery/nom/compare/0.1.3...0.1.4) +* [0.1.3](https://github.com/rust-bakery/nom/compare/0.1.2...0.1.3) +* [0.1.2](https://github.com/rust-bakery/nom/compare/0.1.1...0.1.2) +* [0.1.1](https://github.com/rust-bakery/nom/compare/0.1.0...0.1.1) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -4,15 +4,15 @@ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -36,6 +36,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -48,6 +54,36 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -55,9 +91,9 @@ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -65,6 +101,32 @@ ] [[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -72,46 +134,45 @@ [[package]] name = "libc" -version = "0.2.106" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] -name = "memchr" -version = "2.4.1" +name = "linux-raw-sys" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "memchr" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "nom" -version = "7.1.3" +version = "8.0.0" dependencies = [ "doc-comment", "memchr", - "minimal-lexical", "proptest", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proptest" @@ -147,14 +208,13 @@ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -169,23 +229,14 @@ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] name = "rand_xorshift" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -196,26 +247,31 @@ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "rustix" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "winapi", + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] @@ -232,16 +288,16 @@ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", - "libc", - "rand", + "fastrand", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys", ] [[package]] @@ -255,28 +311,72 @@ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_msvc" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -10,11 +10,12 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" -rust-version = "1.48" +edition = "2021" +rust-version = "1.65.0" name = "nom" -version = "7.1.3" +version = "8.0.0" authors = ["contact@geoffroycouprie.com"] +build = false include = [ "CHANGELOG.md", "LICENSE", @@ -26,7 +27,10 @@ "tests/*.rs", "doc/nom_recipes.md", ] +autobins = false autoexamples = false +autotests = false +autobenches = false description = "A byte-oriented, zero-copy, parser combinators library" documentation = "https://docs.rs/nom" readme = "README.md" @@ -39,112 +43,107 @@ ] categories = ["parsing"] license = "MIT" -repository = "https://github.com/Geal/nom" +repository = "https://github.com/rust-bakery/nom" [package.metadata.docs.rs] +all-features = true features = [ "alloc", "std", "docsrs", ] -all-features = true +rustdoc-args = ["--generate-link-to-definition"] [profile.bench] lto = true codegen-units = 1 -debug = true - -[[example]] -name = "custom_error" -path = "examples/custom_error.rs" -required-features = ["alloc"] +debug = 2 -[[example]] -name = "json" -path = "examples/json.rs" -required-features = ["alloc"] - -[[example]] -name = "json_iterator" -path = "examples/json_iterator.rs" -required-features = ["alloc"] - -[[example]] -name = "iterator" -path = "examples/iterator.rs" - -[[example]] -name = "s_expression" -path = "examples/s_expression.rs" -required-features = ["alloc"] - -[[example]] -name = "string" -path = "examples/string.rs" -required-features = ["alloc"] +[lib] +name = "nom" +path = "src/lib.rs" [[test]] name = "arithmetic" +path = "tests/arithmetic.rs" [[test]] name = "arithmetic_ast" +path = "tests/arithmetic_ast.rs" required-features = ["alloc"] [[test]] name = "css" +path = "tests/css.rs" [[test]] name = "custom_errors" +path = "tests/custom_errors.rs" + +[[test]] +name = "escaped" +path = "tests/escaped.rs" + +[[test]] +name = "expression_ast" +path = "tests/expression_ast.rs" +required-features = ["alloc"] [[test]] name = "float" +path = "tests/float.rs" + +[[test]] +name = "fnmut" +path = "tests/fnmut.rs" +required-features = ["alloc"] [[test]] name = "ini" +path = "tests/ini.rs" required-features = ["alloc"] [[test]] name = "ini_str" +path = "tests/ini_str.rs" required-features = ["alloc"] [[test]] name = "issues" +path = "tests/issues.rs" required-features = ["alloc"] [[test]] name = "json" +path = "tests/json.rs" [[test]] name = "mp4" +path = "tests/mp4.rs" required-features = ["alloc"] [[test]] name = "multiline" +path = "tests/multiline.rs" required-features = ["alloc"] [[test]] name = "overflow" +path = "tests/overflow.rs" [[test]] name = "reborrow_fold" - -[[test]] -name = "fnmut" -required-features = ["alloc"] +path = "tests/reborrow_fold.rs" [dependencies.memchr] version = "2.3" default-features = false -[dependencies.minimal-lexical] -version = "0.2.0" -default-features = false - [dev-dependencies.doc-comment] version = "0.3" [dev-dependencies.proptest] -version = "1.0.0" +version = "=1.0.0" [features] alloc = [] @@ -153,7 +152,6 @@ std = [ "alloc", "memchr/std", - "minimal-lexical/std", ] [badges.coveralls] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/nom/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,149 @@ +[package] + +name = "nom" +version = "8.0.0" +authors = ["contact@geoffroycouprie.com"] +description = "A byte-oriented, zero-copy, parser combinators library" +license = "MIT" +repository = "https://github.com/rust-bakery/nom" +readme = "README.md" +documentation = "https://docs.rs/nom" +keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"] +categories = ["parsing"] +edition = "2021" +autoexamples = false + +# also update in README.md (badge and "Rust version requirements" section) +rust-version = "1.65.0" + +include = [ + "CHANGELOG.md", + "LICENSE", + "README.md", + ".gitignore", + "Cargo.toml", + "src/*.rs", + "src/*/*.rs", + "tests/*.rs", + "doc/nom_recipes.md", +] + +[features] +alloc = [] +std = ["alloc", "memchr/std"] +default = ["std"] +docsrs = [] + +[dependencies.memchr] +version = "2.3" +default-features = false + +[dev-dependencies] +doc-comment = "0.3" +proptest = "=1.0.0" +nom-language = { path = "./nom-language" } + +[package.metadata.docs.rs] +features = ["alloc", "std", "docsrs"] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[profile.bench] +debug = true +lto = true +codegen-units = 1 + +[[test]] +name = "arithmetic" + +[[test]] +name = "arithmetic_ast" +required-features = ["alloc"] + +[[test]] +name = "css" + +[[test]] +name = "custom_errors" + +[[test]] +name = "expression_ast" +required-features = ["alloc"] + +[[test]] +name = "float" + +[[test]] +name = "ini" +required-features = ["alloc"] + +[[test]] +name = "ini_str" +required-features = ["alloc"] + +[[test]] +name = "issues" +required-features = ["alloc"] + +[[test]] +name = "json" + +[[test]] +name = "mp4" +required-features = ["alloc"] + +[[test]] +name = "multiline" +required-features = ["alloc"] + +[[test]] +name = "overflow" + +[[test]] +name = "reborrow_fold" + +[[test]] +name = "fnmut" +required-features = ["alloc"] + +[[example]] +name = "custom_error" +required-features = ["alloc"] +path = "examples/custom_error.rs" + +[[example]] +name = "json" +required-features = ["alloc"] +path = "examples/json.rs" + +[[example]] +name = "json2" +required-features = ["alloc"] +path = "examples/json2.rs" + +[[example]] +name = "json_iterator" +required-features = ["alloc"] +path = "examples/json_iterator.rs" + +[[example]] +name = "iterator" +path = "examples/iterator.rs" + +[[example]] +name = "s_expression" +path = "examples/s_expression.rs" +required-features = ["alloc"] + +[[example]] +name = "string" +required-features = ["alloc"] +path = "examples/string.rs" + +[badges] +travis-ci = { repository = "Geal/nom" } +coveralls = { repository = "Geal/nom", branch = "main", service = "github" } +maintenance = { status = "actively-developed" } + +[workspace] +members = [".", "benchmarks/", "nom-language"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/README.md clamav-1.4.6+dfsg/.cargo/vendor/nom/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -2,10 +2,10 @@ [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Join the chat at https://gitter.im/Geal/nom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Geal/nom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://github.com/Geal/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/Geal/nom/actions/workflows/ci.yml) -[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=main)](https://coveralls.io/github/Geal/nom?branch=main) -[![Crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom) -[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements-msrv) +[![Build Status](https://github.com/rust-bakery/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-bakery/nom/actions/workflows/ci.yml) +[![Coverage Status](https://coveralls.io/repos/github/rust-bakery/nom/badge.svg?branch=main)](https://coveralls.io/github/rust-bakery/nom?branch=main) +[![crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.56.0+-lightgray.svg)](#rust-version-requirements-msrv) nom is a parser combinators library written in Rust. Its goal is to provide tools to build safe parsers without compromising the speed or memory consumption. To @@ -41,19 +41,19 @@ [Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser: ```rust -extern crate nom; use nom::{ - IResult, bytes::complete::{tag, take_while_m_n}, combinator::map_res, - sequence::tuple + sequence::Tuple, + IResult, + Parser, }; -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct Color { - pub red: u8, + pub red: u8, pub green: u8, - pub blue: u8, + pub blue: u8, } fn from_hex(input: &str) -> Result { @@ -68,35 +68,43 @@ map_res( take_while_m_n(2, 2, is_hex_digit), from_hex - )(input) + ).parse(input) } fn hex_color(input: &str) -> IResult<&str, Color> { let (input, _) = tag("#")(input)?; - let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; - + let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?; Ok((input, Color { red, green, blue })) } -fn main() {} +fn main() { + println!("{:?}", hex_color("#2F14DF")) +} #[test] fn parse_color() { - assert_eq!(hex_color("#2F14DF"), Ok(("", Color { - red: 47, - green: 20, - blue: 223, - }))); + assert_eq!( + hex_color("#2F14DF"), + Ok(( + "", + Color { + red: 47, + green: 20, + blue: 223, + } + )) + ); } ``` ## Documentation - [Reference documentation](https://docs.rs/nom) -- [Various design documents and tutorials](https://github.com/Geal/nom/tree/main/doc) -- [List of combinators and their behaviour](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) +- [The Nominomicon: A Guide To Using Nom](https://tfpk.github.io/nominomicon/) +- [Various design documents and tutorials](https://github.com/rust-bakery/nom/tree/main/doc) +- [List of combinators and their behaviour](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md) -If you need any help developing your parsers, please ping `geal` on IRC (libera, geeknode, oftc), go to `#nom-parsers` on Libera IRC, or on the [Gitter chat room](https://gitter.im/Geal/nom). +If you need any help developing your parsers, please ping `geal` on IRC (Libera, Geeknode, OFTC), go to `#nom-parsers` on Libera IRC, or on the [Gitter chat room](https://gitter.im/Geal/nom). ## Why use nom @@ -132,7 +140,7 @@ Example projects: -- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser) +- [HTTP proxy](https://github.com/sozu-proxy/sozu/blob/main/lib/src/protocol/h2/parser.rs) - [TOML parser](https://github.com/joelself/tomllib) ### Programming language parsers @@ -150,8 +158,7 @@ Example projects: - [PHP VM](https://github.com/tagua-vm/parser) -- eve language prototype -- [xshade shading language](https://github.com/xshade-lang/xshade/) +- [xshade shading language](https://github.com/xshade-lang/xshade) ### Streaming formats @@ -167,8 +174,8 @@ Example projects: -- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser) -- [Using nom with generators](https://github.com/Geal/generator_nom) +- [HTTP proxy](https://github.com/sozu-proxy/sozu/blob/main/lib/src/protocol/h2/parser.rs) +- [Using nom with generators](https://github.com/rust-bakery/generator_nom) ## Parser combinators @@ -203,11 +210,11 @@ - [x] **safe parsing**: nom leverages Rust's safe memory handling and powerful types, and parsers are routinely fuzzed and tested with real world data. So far, the only flaws found by fuzzing were in code written outside of nom - [x] **speed**: Benchmarks have shown that nom parsers often outperform many parser combinators library like Parsec and attoparsec, some regular expression engines and even handwritten C parsers -Some benchmarks are available on [Github](https://github.com/Geal/nom_benchmarks). +Some benchmarks are available on [GitHub](https://github.com/rust-bakery/parser_benchmarks). ## Rust version requirements (MSRV) -The 7.0 series of nom supports **Rustc version 1.48 or greater**. It is known to work properly on Rust 1.41.1 but there is no guarantee it will stay the case through this major release. +The 7.0 series of nom supports **Rustc version 1.56 or greater**. The current policy is that this will only be updated in the next major nom release. @@ -245,40 +252,44 @@ - Text file formats: [Ceph Crush](https://github.com/cholcombe973/crushtool), [Cronenberg](https://github.com/ayrat555/cronenberg), +[Email](https://github.com/deuxfleurs-org/eml-codec), [XFS Runtime Stats](https://github.com/ChrisMacNaughton/xfs-rs), [CSV](https://github.com/GuillaumeGomez/csv-parser), [FASTA](https://github.com/TianyiShi2001/nom-fasta), [FASTQ](https://github.com/elij/fastq.rs), -[INI](https://github.com/Geal/nom/blob/main/tests/ini.rs), +[INI](https://github.com/rust-bakery/nom/blob/main/tests/ini.rs), [ISO 8601 dates](https://github.com/badboy/iso8601), [libconfig-like configuration file format](https://github.com/filipegoncalves/rust-config), [Web archive](https://github.com/sbeckeriv/warc_nom_parser), [PDB](https://github.com/TianyiShi2001/nom-pdb), [proto files](https://github.com/tafia/protobuf-parser), [Fountain screenplay markup](https://github.com/adamchalmers/fountain-rs), -[vimwiki](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki) & [vimwiki_macros](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki_macros) +[vimwiki](https://github.com/chipsenkbeil/vimwiki-rs/tree/master/vimwiki) & [vimwiki_macros](https://github.com/chipsenkbeil/vimwiki-rs/tree/master/vimwiki_macros), +[Kconfig language](https://github.com/Mcdostone/nom-kconfig), [Askama templates](https://crates.io/crates/askama_parser/) - Programming languages: [PHP](https://github.com/tagua-vm/parser), [Basic Calculator](https://github.com/balajisivaraman/basic_calculator_rs), [GLSL](https://github.com/phaazon/glsl), -[Lua](https://github.com/doomrobo/nom-lua53), +[Lua](https://github.com/rozbb/nom-lua53), [Python](https://github.com/ProgVal/rust-python-parser), [SQL](https://github.com/ms705/nom-sql), [Elm](https://github.com/cout970/Elm-interpreter), [SystemVerilog](https://github.com/dalance/sv-parser), [Turtle](https://github.com/vandenoever/rome/tree/master/src/io/turtle), -[CSML](https://github.com/CSML-by-Clevy/csml-interpreter), -[Wasm](https://github.com/Strytyp/wasm-nom), -[Pseudocode](https://github.com/Gungy2/pseudocode) -[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch) +[CSML](https://github.com/CSML-by-Clevy/csml-engine/tree/dev/csml_interpreter), +[Wasm](https://github.com/fabrizio-m/wasm-nom), +[Pseudocode](https://github.com/Gungy2/pseudocod), +[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch), +[PotterScript](https://github.com/fmiras/potterscript) - Interface definition formats: [Thrift](https://github.com/thehydroimpulse/thrust) - Audio, video and image formats: [GIF](https://github.com/Geal/gif.rs), -[MagicaVoxel .vox](https://github.com/davidedmonds/dot_vox), -[midi](https://github.com/derekdreery/nom-midi-rs), +[MagicaVoxel .vox](https://github.com/dust-engine/dot_vox), +[MIDI](https://github.com/derekdreery/nom-midi-rs), [SWF](https://github.com/open-flash/swf-parser), -[WAVE](http://github.com/noise-Labs/wave), -[Matroska (MKV)](https://github.com/rust-av/matroska) +[WAVE](https://github.com/Noise-Labs/wave), +[Matroska (MKV)](https://github.com/rust-av/matroska), +[Exif/Metadata parser for JPEG/HEIF/HEIC/MOV/MP4](https://github.com/mindeng/nom-exif) - Document formats: [TAR](https://github.com/Keruspe/tar-parser.rs), [GZ](https://github.com/nharward/nom-gzip), @@ -291,7 +302,7 @@ [DHCP](https://github.com/rusticata/dhcp-parser), [HTTP](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http), [URI](https://github.com/santifa/rrp/blob/master/src/uri.rs), -[IMAP](https://github.com/djc/tokio-imap), +[IMAP](https://github.com/djc/tokio-imap) ([alt](https://github.com/duesee/imap-codec)), [IRC](https://github.com/Detegr/RBot-parser), [Pcap-NG](https://github.com/richo/pcapng-rs), [Pcap](https://github.com/ithinuel/pcap-rs), @@ -302,23 +313,26 @@ [Kerberos v5](https://github.com/rusticata/kerberos-parser), [DER](https://github.com/rusticata/der-parser), [TLS](https://github.com/rusticata/tls-parser), -[IPFIX / Netflow v10](https://github.com/dominotree/rs-ipfix), +[V5, V7, V9, IPFIX / Netflow v10](https://github.com/mikemiles-dev/netflow_parser), [GTP](https://github.com/fuerstenau/gorrosion-gtp), -[SIP](https://github.com/armatusmiles/sipcore/tree/master/crates/sipmsg), -[Prometheus](https://github.com/timberio/vector/blob/master/lib/prometheus-parser/src/line.rs) +[SIP](https://github.com/kurotych/sipcore/tree/master/crates/sipmsg), +[SMTP](https://github.com/Ekleog/kannader), +[Prometheus](https://github.com/vectordotdev/vector/blob/master/lib/prometheus-parser/src/line.rs), +[DNS](https://github.com/adiSuper94/dns-rs) - Language specifications: -[BNF](https://github.com/snewt/bnf) +[BNF](https://github.com/shnewto/bnf) - Misc formats: -[Gameboy ROM](https://github.com/MarkMcCaskey/gameboy-rom-parser), +[Game Boy ROM](https://github.com/MarkMcCaskey/gameboy-rom-parser), [ANT FIT](https://github.com/stadelmanma/fitparse-rs), [Version Numbers](https://github.com/fosskers/rs-versions), [Telcordia/Bellcore SR-4731 SOR OTDR files](https://github.com/JamesHarrison/otdrs), [MySQL binary log](https://github.com/PrivateRookie/boxercrab), [URI](https://github.com/Skasselbard/nom-uri), [Furigana](https://github.com/sachaarbonel/furigana.rs), -[Wordle Result](https://github.com/Fyko/wordle-stats/tree/main/parser) +[Wordle Result](https://github.com/Fyko/wordle-stats/tree/main/parser), +[NBT](https://github.com/phoenixr-codes/mcnbt) -Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/Geal/nom/issues/14). +Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/rust-bakery/nom/issues/14). Want to add your parser here? Create a pull request for it! @@ -326,6 +340,6 @@ nom is the fruit of the work of many contributors over the years, many thanks for your help! -
- + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/doc/nom_recipes.md clamav-1.4.6+dfsg/.cargo/vendor/nom/doc/nom_recipes.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom/doc/nom_recipes.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/doc/nom_recipes.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -# Nom Recipes +# Common recipes to build nom parsers These are short recipes for accomplishing common tasks with nom. @@ -27,23 +27,21 @@ ```rust use nom::{ IResult, + Parser, error::ParseError, - combinator::value, sequence::delimited, character::complete::multispace0, }; /// A combinator that takes a parser `inner` and produces a parser that also consumes both leading and /// trailing whitespace, returning the output of `inner`. -fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E> - where - F: Fn(&'a str) -> IResult<&'a str, O, E>, +pub fn ws<'a, O, E: ParseError<&'a str>, F>( + inner: F, +) -> impl Parser<&'a str, Output = O, Error = E> +where + F: Parser<&'a str, Output = O, Error = E>, { - delimited( - multispace0, - inner, - multispace0 - ) + delimited(multispace0, inner, multispace0) } ``` @@ -62,6 +60,7 @@ ```rust use nom::{ IResult, + Parser, error::ParseError, combinator::value, sequence::pair, @@ -74,7 +73,7 @@ value( (), // Output is thrown away. pair(char('%'), is_not("\n\r")) - )(i) + ).parse(i) } ``` @@ -86,21 +85,21 @@ ```rust use nom::{ IResult, + Parser, error::ParseError, combinator::value, - sequence::tuple, bytes::complete::{tag, take_until}, }; pub fn pinline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> { value( (), // Output is thrown away. - tuple(( + ( tag("(*"), take_until("*)"), tag("*)") - )) - )(i) + ) + ).parse(i) } ``` @@ -114,6 +113,7 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::many0_count, combinator::recognize, @@ -128,7 +128,7 @@ alt((alpha1, tag("_"))), many0_count(alt((alphanumeric1, tag("_")))) ) - )(input) + ).parse(input) } ``` @@ -142,8 +142,8 @@ ### Escaped Strings -This is [one of the examples](https://github.com/Geal/nom/blob/main/examples/string.rs) in the -examples directory. +This is [one of the examples](https://github.com/rust-bakery/nom/blob/main/examples/string.rs) in +the examples directory. ### Integers @@ -153,7 +153,7 @@ The parsers allow the grouping character `_`, which allows one to group the digits by byte, for example: `0xA4_3F_11_28`. If you prefer to exclude the `_` character, the lambda to convert from a string slice to an integer value is slightly simpler. You can also strip the `_` from the string -slice that is returned, which is demonstrated in the second hexdecimal number parser. +slice that is returned, which is demonstrated in the second hexadecimal number parser. If you wish to limit the number of digits in a valid integer literal, replace `many1` with `many_m_n` in the recipes. @@ -165,6 +165,7 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::{many0, many1}, combinator::recognize, @@ -181,7 +182,7 @@ terminated(one_of("0123456789abcdefABCDEF"), many0(char('_'))) ) ) - )(input) + ).parse(input) } ``` @@ -190,6 +191,7 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::{many0, many1}, combinator::{map_res, recognize}, @@ -209,7 +211,7 @@ ) ), |out: &str| i64::from_str_radix(&str::replace(&out, "_", ""), 16) - )(input) + ).parse(input) } ``` @@ -218,6 +220,7 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::{many0, many1}, combinator::recognize, @@ -234,7 +237,7 @@ terminated(one_of("01234567"), many0(char('_'))) ) ) - )(input) + ).parse(input) } ``` @@ -243,6 +246,7 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::{many0, many1}, combinator::recognize, @@ -259,7 +263,7 @@ terminated(one_of("01"), many0(char('_'))) ) ) - )(input) + ).parse(input) } ``` @@ -268,6 +272,7 @@ ```rust use nom::{ IResult, + Parser, multi::{many0, many1}, combinator::recognize, sequence::terminated, @@ -279,7 +284,7 @@ many1( terminated(one_of("0123456789"), many0(char('_'))) ) - )(input) + ).parse(input) } ``` @@ -290,10 +295,11 @@ ```rust use nom::{ IResult, + Parser, branch::alt, multi::{many0, many1}, combinator::{opt, recognize}, - sequence::{preceded, terminated, tuple}, + sequence::{preceded, terminated}, character::complete::{char, one_of}, }; @@ -301,19 +307,19 @@ alt(( // Case one: .42 recognize( - tuple(( + ( char('.'), decimal, - opt(tuple(( + opt(( one_of("eE"), opt(one_of("+-")), decimal - ))) - )) + )) + ) ) , // Case two: 42e42 and 42.42e42 recognize( - tuple(( + ( decimal, opt(preceded( char('.'), @@ -322,17 +328,17 @@ one_of("eE"), opt(one_of("+-")), decimal - )) + ) ) , // Case three: 42. and 42.42 recognize( - tuple(( + ( decimal, char('.'), opt(decimal) - )) + ) ) - ))(input) + )).parse(input) } fn decimal(input: &str) -> IResult<&str, &str> { @@ -340,7 +346,7 @@ many1( terminated(one_of("0123456789"), many0(char('_'))) ) - )(input) + ).parse(input) } ``` @@ -351,14 +357,14 @@ ```rust use nom::{ - IResult, Finish, error::Error, + IResult, Parser, Finish, error::Error, bytes::complete::{tag, take_while}, }; use std::str::FromStr; // will recognize the name in "Hello, name!" fn parse_name(input: &str) -> IResult<&str, &str> { - let (i, _) = tag("Hello, ")(input)?; + let (i, _) = tag("Hello, ").parse(input)?; let (i, name) = take_while(|c:char| c.is_alphabetic())(i)?; let (i, _) = tag("!")(i)?; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/complete.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,8 +3,8 @@ use crate::error::{ErrorKind, ParseError}; use crate::internal::{Err, IResult}; -use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr}; -use crate::traits::{InputIter, InputLength, Slice, ToUsize}; +use crate::lib::std::ops::{AddAssign, Div, Shl, Shr}; +use crate::traits::{Input, ToUsize}; /// Generates a parser taking `count` bits /// @@ -34,7 +34,7 @@ count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Slice> + InputIter + InputLength, + I: Input, C: ToUsize, O: From + AddAssign + Shl + Shr, { @@ -42,41 +42,39 @@ move |(input, bit_offset): (I, usize)| { if count == 0 { Ok(((input, bit_offset), 0u8.into())) + } else if input.input_len() * 8 < count + bit_offset { + Err(Err::Error(E::from_error_kind( + (input, bit_offset), + ErrorKind::Eof, + ))) } else { let cnt = (count + bit_offset).div(8); - if input.input_len() * 8 < count + bit_offset { - Err(Err::Error(E::from_error_kind( - (input, bit_offset), - ErrorKind::Eof, - ))) - } else { - let mut acc: O = 0_u8.into(); - let mut offset: usize = bit_offset; - let mut remaining: usize = count; - let mut end_offset: usize = 0; - - for byte in input.iter_elements().take(cnt + 1) { - if remaining == 0 { - break; - } - let val: O = if offset == 0 { - byte.into() - } else { - ((byte << offset) as u8 >> offset).into() - }; - - if remaining < 8 - offset { - acc += val >> (8 - offset - remaining); - end_offset = remaining + offset; - break; - } else { - acc += val << (remaining - (8 - offset)); - remaining -= 8 - offset; - offset = 0; - } + let mut acc: O = 0_u8.into(); + let mut offset: usize = bit_offset; + let mut remaining: usize = count; + let mut end_offset: usize = 0; + + for byte in input.iter_elements().take(cnt + 1) { + if remaining == 0 { + break; + } + let val: O = if offset == 0 { + byte.into() + } else { + ((byte << offset) >> offset).into() + }; + + if remaining < 8 - offset { + acc += val >> (8 - offset - remaining); + end_offset = remaining + offset; + break; + } else { + acc += val << (remaining - (8 - offset)); + remaining -= 8 - offset; + offset = 0; } - Ok(((input.slice(cnt..), end_offset), acc)) } + Ok(((input.take_from(cnt), end_offset), acc)) } } } @@ -87,7 +85,7 @@ count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Slice> + InputIter + InputLength + Clone, + I: Input + Clone, C: ToUsize, O: From + AddAssign + Shl + Shr + PartialEq, { @@ -122,7 +120,7 @@ /// ``` pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> where - I: Slice> + InputIter + InputLength, + I: Input, { let (res, bit): (_, u32) = take(1usize)(input)?; Ok((res, bit != 0)) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,8 +6,8 @@ use crate::error::{ErrorKind, ParseError}; use crate::internal::{Err, IResult, Needed, Parser}; -use crate::lib::std::ops::RangeFrom; -use crate::traits::{ErrorConvert, Slice}; +use crate::traits::ErrorConvert; +use crate::Input; /// Converts a byte-level input to a bit-level input, for consumption by a parser that uses bits. /// @@ -18,11 +18,10 @@ /// ``` /// use nom::bits::{bits, streaming::take}; /// use nom::error::Error; -/// use nom::sequence::tuple; /// use nom::IResult; /// /// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8)> { -/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input) +/// bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input) /// } /// /// let input = &[0x12, 0x34, 0xff, 0xff]; @@ -41,8 +40,8 @@ where E1: ParseError<(I, usize)> + ErrorConvert, E2: ParseError, - I: Slice>, - P: Parser<(I, usize), O, E1>, + I: Input, + P: Parser<(I, usize), Output = O, Error = E1>, { move |input: I| match parser.parse((input, 0)) { Ok(((rest, offset), result)) => { @@ -50,7 +49,7 @@ // The parser functions might already slice away all fully read bytes. // That's why `offset / 8` isn't necessarily needed at all times. let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 }; - Ok((rest.slice(remaining_bytes_index..), result)) + Ok((rest.take_from(remaining_bytes_index), result)) } Err(Err::Incomplete(n)) => Err(Err::Incomplete(n.map(|u| u.get() / 8 + 1))), Err(Err::Error(e)) => Err(Err::Error(e.convert())), @@ -68,15 +67,14 @@ /// use nom::bits::{bits, bytes, streaming::take}; /// use nom::combinator::rest; /// use nom::error::Error; -/// use nom::sequence::tuple; /// use nom::IResult; /// /// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8, &[u8])> { -/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple(( +/// bits::<_, _, Error<(&[u8], usize)>, _, _>(( /// take(4usize), /// take(8usize), /// bytes::<_, _, Error<&[u8]>, _, _>(rest) -/// )))(input) +/// ))(input) /// } /// /// let input = &[0x12, 0x34, 0xff, 0xff]; @@ -87,14 +85,14 @@ where E1: ParseError + ErrorConvert, E2: ParseError<(I, usize)>, - I: Slice> + Clone, - P: Parser, + I: Input + Clone, + P: Parser, { move |(input, offset): (I, usize)| { let inner = if offset % 8 != 0 { - input.slice((1 + offset / 8)..) + input.take_from(1 + offset / 8) } else { - input.slice((offset / 8)..) + input.take_from(offset / 8) }; let i = (input, offset); match parser.parse(inner) { @@ -115,7 +113,6 @@ use super::*; use crate::bits::streaming::take; use crate::error::Error; - use crate::sequence::tuple; #[test] /// Take the `bits` function and assert that remaining bytes are correctly returned, if the @@ -125,9 +122,7 @@ // Take 3 bit slices with sizes [4, 8, 4]. let result: IResult<&[u8], (u8, u8, u8)> = - bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize), take(4usize))))( - input, - ); + bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize), take(4usize)))(input); let output = result.expect("We take 2 bytes and the input is longer than 2 bytes"); @@ -150,7 +145,7 @@ // Take bit slices with sizes [4, 8]. let result: IResult<&[u8], (u8, u8)> = - bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input); + bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input); let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes"); @@ -170,7 +165,7 @@ // Take bit slices with sizes [4, 8]. let result: IResult<&[u8], (u8, u8)> = - bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input); + bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input); assert!(result.is_err()); let error = result.err().unwrap(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bits/streaming.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bits/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,15 +3,15 @@ use crate::error::{ErrorKind, ParseError}; use crate::internal::{Err, IResult, Needed}; -use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr}; -use crate::traits::{InputIter, InputLength, Slice, ToUsize}; +use crate::lib::std::ops::{AddAssign, Div, Shl, Shr}; +use crate::traits::{Input, ToUsize}; /// Generates a parser taking `count` bits pub fn take>( count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Slice> + InputIter + InputLength, + I: Input, C: ToUsize, O: From + AddAssign + Shl + Shr, { @@ -22,7 +22,7 @@ } else { let cnt = (count + bit_offset).div(8); if input.input_len() * 8 < count + bit_offset { - Err(Err::Incomplete(Needed::new(count as usize))) + Err(Err::Incomplete(Needed::new(count))) } else { let mut acc: O = 0_u8.into(); let mut offset: usize = bit_offset; @@ -36,7 +36,7 @@ let val: O = if offset == 0 { byte.into() } else { - ((byte << offset) as u8 >> offset).into() + ((byte << offset) >> offset).into() }; if remaining < 8 - offset { @@ -49,7 +49,7 @@ offset = 0; } } - Ok(((input.slice(cnt..), end_offset), acc)) + Ok(((input.take_from(cnt), end_offset), acc)) } } } @@ -61,7 +61,7 @@ count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Slice> + InputIter + InputLength + Clone, + I: Input + Clone, C: ToUsize, O: From + AddAssign + Shl + Shr + PartialEq, { @@ -96,7 +96,7 @@ /// ``` pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> where - I: Slice> + InputIter + InputLength, + I: Input, { let (res, bit): (_, u32) = take(1usize)(input)?; Ok((res, bit != 0)) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/branch/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/branch/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,32 +3,26 @@ #[cfg(test)] mod tests; +use core::marker::PhantomData; + use crate::error::ErrorKind; use crate::error::ParseError; -use crate::internal::{Err, IResult, Parser}; - -/// Helper trait for the [alt()] combinator. -/// -/// This trait is implemented for tuples of up to 21 elements -pub trait Alt { - /// Tests each parser in the tuple and returns the result of the first one that succeeds - fn choice(&mut self, input: I) -> IResult; -} +use crate::internal::{Err, Mode, Parser}; /// Tests a list of parsers one by one until one succeeds. /// -/// It takes as argument a tuple of parsers. There is a maximum of 21 -/// parsers. If you need more, it is possible to nest them in other `alt` calls, -/// like this: `alt(parser_a, alt(parser_b, parser_c))` +/// It takes as argument either a tuple or an array of parsers. If using a +/// tuple, there is a maximum of 21 parsers. If you need more, it is possible to +/// use an array. /// /// ```rust /// # use nom::error_position; -/// # use nom::{Err,error::ErrorKind, Needed, IResult}; +/// # use nom::{Err,error::ErrorKind, Needed, IResult, Parser}; /// use nom::character::complete::{alpha1, digit1}; /// use nom::branch::alt; /// # fn main() { /// fn parser(input: &str) -> IResult<&str, &str> { -/// alt((alpha1, digit1))(input) +/// alt((alpha1, digit1)).parse(input) /// }; /// /// // the first parser, alpha1, recognizes the input @@ -44,18 +38,8 @@ /// /// With a custom error type, it is possible to have alt return the error of the parser /// that went the farthest in the input data -pub fn alt, List: Alt>( - mut l: List, -) -> impl FnMut(I) -> IResult { - move |i: I| l.choice(i) -} - -/// Helper trait for the [permutation()] combinator. -/// -/// This trait is implemented for tuples of up to 21 elements -pub trait Permutation { - /// Tries to apply all parsers in the tuple in various orders until all of them succeed - fn permutation(&mut self, input: I) -> IResult; +pub fn alt(l: List) -> Choice { + Choice { parser: l } } /// Applies a list of parsers in any order. @@ -65,12 +49,12 @@ /// tuple of the parser results. /// /// ```rust -/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::character::complete::{alpha1, digit1}; /// use nom::branch::permutation; /// # fn main() { /// fn parser(input: &str) -> IResult<&str, (&str, &str)> { -/// permutation((alpha1, digit1))(input) +/// permutation((alpha1, digit1)).parse(input) /// } /// /// // permutation recognizes alphabetic characters then digit @@ -87,12 +71,12 @@ /// The parsers are applied greedily: if there are multiple unapplied parsers /// that could parse the next slice of input, the first one is used. /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Parser}; /// use nom::branch::permutation; /// use nom::character::complete::{anychar, char}; /// /// fn parser(input: &str) -> IResult<&str, (char, char)> { -/// permutation((anychar, char('a')))(input) +/// permutation((anychar, char('a'))).parse(input) /// } /// /// // anychar parses 'b', then char('a') parses 'a' @@ -103,10 +87,11 @@ /// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char)))); /// ``` /// -pub fn permutation, List: Permutation>( - mut l: List, -) -> impl FnMut(I) -> IResult { - move |i: I| l.permutation(i) +pub fn permutation, List>(list: List) -> Permutation { + Permutation { + parser: list, + e: PhantomData, + } } macro_rules! alt_trait( @@ -124,17 +109,30 @@ ); ); +/// Wrapping structure for the [alt()] combinator implementation +pub struct Choice { + parser: T, +} + macro_rules! alt_trait_impl( ($($id:ident)+) => ( impl< Input: Clone, Output, Error: ParseError, - $($id: Parser),+ - > Alt for ( $($id),+ ) { - - fn choice(&mut self, input: Input) -> IResult { - match self.0.parse(input.clone()) { + $($id: Parser),+ + > Parser for Choice< ( $($id),+ )> { + type Output = Output; + type Error = Error; + + #[inline(always)] + fn process( + &mut self, + input: Input, + ) -> crate::PResult { + match self.parser.0.process::(input.clone()) { + Ok(res) => Ok(res), + Err(Err::Failure(e))=> Err(Err::Failure(e)), + Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)), Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+), - res => res, } } } @@ -143,27 +141,112 @@ macro_rules! alt_trait_inner( ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => ( - match $self.$it.parse($input.clone()) { + match $self.parser.$it.process::($input.clone()) { + Ok(res) => Ok(res), + Err(Err::Failure(e))=>Err(Err::Failure(e)), + Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)), Err(Err::Error(e)) => { - let err = $err.or(e); - succ!($it, alt_trait_inner!($self, $input, err, $($id)+)) + succ!($it, alt_trait_inner!($self, $input, ::combine($err, e, |e1, e2| e1.or(e2)), $($id)+)) } - res => res, } ); ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => ( - Err(Err::Error(Error::append($input, ErrorKind::Alt, $err))) + Err(Err::Error(::map($err, |err| Error::append($input, ErrorKind::Alt, err)))) ); ); alt_trait!(A B C D E F G H I J K L M N O P Q R S T U); // Manually implement Alt for (A,), the 1-tuple type -impl, A: Parser> - Alt for (A,) +impl, A: Parser> + Parser for Choice<(A,)> { - fn choice(&mut self, input: Input) -> IResult { - self.0.parse(input) + type Output = Output; + type Error = Error; + + #[inline] + fn process( + &mut self, + input: Input, + ) -> crate::PResult { + self.parser.0.process::(input) + } +} + +impl< + const N: usize, + Input: Clone, + Output, + Error: ParseError, + A: Parser, + > Parser for Choice<[A; N]> +{ + type Output = Output; + type Error = Error; + + #[inline] + fn process( + &mut self, + input: Input, + ) -> crate::PResult { + let mut error = None; + + for branch in &mut self.parser { + match branch.process::(input.clone()) { + Err(Err::Error(e)) => match error { + None => error = Some(e), + Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))), + }, + res => return res, + } + } + + match error { + Some(e) => Err(Err::Error(OM::Error::map(e, |err| { + Error::append(input, ErrorKind::Alt, err) + }))), + None => Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::Alt) + }))), + } + } +} + +impl< + Input: Clone, + Output, + Error: ParseError, + A: Parser, + > Parser for Choice<&mut [A]> +{ + type Output = Output; + type Error = Error; + + #[inline] + fn process( + &mut self, + input: Input, + ) -> crate::PResult { + let mut error = None; + + for branch in self.parser.iter_mut() { + match branch.process::(input.clone()) { + Err(Err::Error(e)) => match error { + None => error = Some(e), + Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))), + }, + res => return res, + } + } + + match error { + Some(e) => Err(Err::Error(OM::Error::map(e, |err| { + Error::append(input, ErrorKind::Alt, err) + }))), + None => Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::Alt) + }))), + } } } @@ -187,57 +270,79 @@ ); ); +/// Wrapping structure for the [permutation] combinator implementation +pub struct Permutation { + parser: T, + e: PhantomData, +} + macro_rules! permutation_trait_impl( ($($name:ident $ty:ident $item:ident),+) => ( impl< - Input: Clone, $($ty),+ , Error: ParseError, - $($name: Parser),+ - > Permutation for ( $($name),+ ) { - - fn permutation(&mut self, mut input: Input) -> IResult { - let mut res = ($(Option::<$ty>::None),+); + Input, Error, $($ty),+ , $($name),+ + > Parser for Permutation< ( $($name),+ ), Error> + where + Input: Clone, + Error: ParseError, + $($name: Parser),+ + { + type Output = ( $($ty),+ ); + type Error = Error; + + #[inline(always)] + fn process( + &mut self, + mut input: Input, + ) -> crate::PResult { + let mut res = OM::Output::bind(|| ($(Option::<$ty>::None),+)); + $(let mut $item = false;)+ loop { - let mut err: Option = None; - permutation_trait_inner!(0, self, input, res, err, $($name)+); + let mut err: Option<::Output> = None; + permutation_trait_inner!(0, self, input, res, err, $($item)+); // If we reach here, every iterator has either been applied before, // or errored on the remaining input if let Some(err) = err { // There are remaining parsers, and all errored on the remaining input - return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err))); + return Err(Err::Error(OM::Error::map(err, |err| Error::append(input, ErrorKind::Permutation, err)))); } - // All parsers were applied - match res { - ($(Some($item)),+) => return Ok((input, ($($item),+))), - _ => unreachable!(), - } + return Ok((input,OM::Output::map(res, |res| { + // All parsers were applied + match res { + ($(Some($item)),+) => ($($item),+), + _ => unreachable!(), + } + }))) } } + } ); ); macro_rules! permutation_trait_inner( - ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => ( - if $res.$it.is_none() { - match $self.$it.parse($input.clone()) { + ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($item:ident)*) => ( + if !$head { + + match $self.parser.$it.process::($input.clone()) { Ok((i, o)) => { $input = i; - $res.$it = Some(o); + $res = OM::Output::combine($res, o, |mut res, o | {res.$it = Some(o);res }); + $head = true; continue; } Err(Err::Error(e)) => { $err = Some(match $err { - Some(err) => err.or(e), None => e, + Some(err) => OM::Error::combine(err, e, |err, e| err.or(e)) }); } Err(e) => return Err(e), }; } - succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*)); + succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($item)*)); ); ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => (); ); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/branch/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/branch/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/branch/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,6 +2,7 @@ use crate::bytes::streaming::tag; use crate::error::ErrorKind; use crate::internal::{Err, IResult, Needed}; +use crate::Parser; #[cfg(feature = "alloc")] use crate::{ error::ParseError, @@ -12,7 +13,7 @@ }; #[cfg(feature = "alloc")] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct ErrorStr(String); #[cfg(feature = "alloc")] @@ -46,6 +47,8 @@ #[cfg(feature = "alloc")] #[test] fn alt_test() { + use crate::Parser; + fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { Ok((&b""[..], input)) } @@ -60,13 +63,13 @@ } fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, dont_work))(i) + alt((dont_work, dont_work)).parse(i) } fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, work))(i) + alt((dont_work, work)).parse(i) } fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, dont_work, work2, dont_work))(i) + alt((dont_work, dont_work, work2, dont_work)).parse(i) } //named!(alt1, alt!(dont_work | dont_work)); //named!(alt2, alt!(dont_work | work)); @@ -85,7 +88,7 @@ assert_eq!(alt3(a), Ok((a, &b""[..]))); fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> { - alt((tag("abcd"), tag("efgh")))(i) + alt((tag("abcd"), tag("efgh"))).parse(i) } let b = &b"efgh"[..]; assert_eq!(alt4(a), Ok((&b""[..], a))); @@ -95,7 +98,7 @@ #[test] fn alt_incomplete() { fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> { - alt((tag("a"), tag("bc"), tag("def")))(i) + alt((tag("a"), tag("bc"), tag("def"))).parse(i) } let a = &b""[..]; @@ -113,9 +116,42 @@ } #[test] +fn alt_array() { + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt([tag("a"), tag("bc"), tag("def")]).parse(i) + } + + let a = &b"a"[..]; + assert_eq!(alt1(a), Ok((&b""[..], (&b"a"[..])))); + + let bc = &b"bc"[..]; + assert_eq!(alt1(bc), Ok((&b""[..], (&b"bc"[..])))); + + let defg = &b"defg"[..]; + assert_eq!(alt1(defg), Ok((&b"g"[..], (&b"def"[..])))); +} + +#[test] +fn alt_dynamic_array() { + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt(&mut [tag("a"), tag("bc"), tag("def")][..]).parse(i) + } + + let a = &b"a"[..]; + assert_eq!(alt1(a), Ok((&b""[..], (&b"a"[..])))); + + let bc = &b"bc"[..]; + assert_eq!(alt1(bc), Ok((&b""[..], (&b"bc"[..])))); + + let defg = &b"defg"[..]; + assert_eq!(alt1(defg), Ok((&b"g"[..], (&b"def"[..])))); +} + +#[test] fn permutation_test() { + #[allow(clippy::type_complexity)] fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> { - permutation((tag("abcd"), tag("efg"), tag("hi")))(i) + permutation((tag("abcd"), tag("efg"), tag("hi"))).parse(i) } let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/complete.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,14 @@ //! Parsers recognizing bytes streams, complete input version -use crate::error::ErrorKind; +use core::marker::PhantomData; + use crate::error::ParseError; -use crate::internal::{Err, IResult, Parser}; -use crate::lib::std::ops::RangeFrom; -use crate::lib::std::result::Result::*; -use crate::traits::{ - Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, - InputTakeAtPosition, Slice, ToUsize, -}; +use crate::internal::{IResult, Parser}; +use crate::traits::{Compare, FindSubstring, FindToken, ToUsize}; +use crate::Complete; +use crate::Emit; +use crate::Input; +use crate::OutputM; /// Recognizes a pattern /// @@ -29,24 +29,18 @@ /// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); /// ``` -pub fn tag>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + Compare, - T: InputLength + Clone, -{ - move |i: Input| { - let tag_len = tag.input_len(); - let t = tag.clone(); - let res: IResult<_, _, Error> = match i.compare(t) { - CompareResult::Ok => Ok(i.take_split(tag_len)), - _ => { - let e: ErrorKind = ErrorKind::Tag; - Err(Err::Error(Error::from_error_kind(i, e))) - } +pub fn tag>(tag: T) -> impl Fn(I) -> IResult +where + I: Input + Compare, + T: Input + Clone, +{ + move |i: I| { + let mut parser = super::Tag { + tag: tag.clone(), + e: PhantomData, }; - res + + parser.process::>(i) } } @@ -71,25 +65,18 @@ /// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); /// ``` -pub fn tag_no_case>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + Compare, - T: InputLength + Clone, -{ - move |i: Input| { - let tag_len = tag.input_len(); - let t = tag.clone(); - - let res: IResult<_, _, Error> = match (i).compare_no_case(t) { - CompareResult::Ok => Ok(i.take_split(tag_len)), - _ => { - let e: ErrorKind = ErrorKind::Tag; - Err(Err::Error(Error::from_error_kind(i, e))) - } +pub fn tag_no_case>(tag: T) -> impl Fn(I) -> IResult +where + I: Input + Compare, + T: Input + Clone, +{ + move |i: I| { + let mut parser = super::TagNoCase { + tag: tag.clone(), + e: PhantomData, }; - res + + parser.process::>(i) } } @@ -114,17 +101,14 @@ /// assert_eq!(not_space("Nospace"), Ok(("", "Nospace"))); /// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot)))); /// ``` -pub fn is_not>( - arr: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTakeAtPosition, - T: FindToken<::Item>, -{ - move |i: Input| { - let e: ErrorKind = ErrorKind::IsNot; - i.split_at_position1_complete(|c| arr.find_token(c), e) - } +pub fn is_not>(arr: T) -> impl FnMut(I) -> IResult +where + I: Input, + T: FindToken<::Item>, +{ + let mut parser = super::is_not(arr); + + move |i: I| parser.process::>(i) } /// Returns the longest slice of the matches the pattern. @@ -148,17 +132,14 @@ /// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E"))); /// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA)))); /// ``` -pub fn is_a>( - arr: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTakeAtPosition, - T: FindToken<::Item>, -{ - move |i: Input| { - let e: ErrorKind = ErrorKind::IsA; - i.split_at_position1_complete(|c| !arr.find_token(c), e) - } +pub fn is_a>(arr: T) -> impl FnMut(I) -> IResult +where + I: Input, + T: FindToken<::Item>, +{ + let mut parser = super::is_a(arr); + + move |i: I| parser.process::>(i) } /// Returns the longest input slice (if any) that matches the predicate. @@ -169,10 +150,10 @@ /// ```rust /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::complete::take_while; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while(is_alphabetic)(s) +/// take_while(AsChar::is_alpha)(s) /// } /// /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); @@ -180,14 +161,14 @@ /// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); /// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..]))); /// ``` -pub fn take_while>( - cond: F, -) -> impl Fn(Input) -> IResult +pub fn take_while>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| i.split_at_position_complete(|c| !cond(c)) + let mut parser = super::take_while(cond); + + move |i: I| parser.process::>(i) } /// Returns the longest (at least 1) input slice that matches the predicate. @@ -200,30 +181,27 @@ /// ```rust /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_while1; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while1(is_alphabetic)(s) +/// take_while1(AsChar::is_alpha)(s) /// } /// /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); /// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); /// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); /// ``` -pub fn take_while1>( - cond: F, -) -> impl Fn(Input) -> IResult +pub fn take_while1>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let e: ErrorKind = ErrorKind::TakeWhile1; - i.split_at_position1_complete(|c| !cond(c), e) - } + let mut parser = super::take_while1(cond); + + move |i: I| parser.process::>(i) } -/// Returns the longest (m <= len <= n) input slice that matches the predicate. +/// Returns the longest (m <= len <= n) input slice that matches the predicate. /// /// The parser will return the longest slice that matches the given predicate *(a function that /// takes the input and returns a bool)*. @@ -234,10 +212,10 @@ /// ```rust /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_while_m_n; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while_m_n(3, 6, is_alphabetic)(s) +/// take_while_m_n(3, 6, AsChar::is_alpha)(s) /// } /// /// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); @@ -246,67 +224,18 @@ /// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN)))); /// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); /// ``` -pub fn take_while_m_n>( +pub fn take_while_m_n>( m: usize, n: usize, cond: F, -) -> impl Fn(Input) -> IResult +) -> impl FnMut(I) -> IResult where - Input: InputTake + InputIter + InputLength + Slice>, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let input = i; + let mut parser = super::take_while_m_n(m, n, cond); - match input.position(|c| !cond(c)) { - Some(idx) => { - if idx >= m { - if idx <= n { - let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { - Ok(input.take_split(index)) - } else { - Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))) - }; - res - } else { - let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { - Ok(input.take_split(index)) - } else { - Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))) - }; - res - } - } else { - let e = ErrorKind::TakeWhileMN; - Err(Err::Error(Error::from_error_kind(input, e))) - } - } - None => { - let len = input.input_len(); - if len >= n { - match input.slice_index(n) { - Ok(index) => Ok(input.take_split(index)), - Err(_needed) => Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))), - } - } else if len >= m && len <= n { - let res: IResult<_, _, Error> = Ok((input.slice(len..), input)); - res - } else { - let e = ErrorKind::TakeWhileMN; - Err(Err::Error(Error::from_error_kind(input, e))) - } - } - } - } + move |i: I| parser.process::>(i) } /// Returns the longest input slice (if any) till a predicate is met. @@ -327,14 +256,15 @@ /// assert_eq!(till_colon("12345"), Ok(("", "12345"))); /// assert_eq!(till_colon(""), Ok(("", ""))); /// ``` -pub fn take_till>( - cond: F, -) -> impl Fn(Input) -> IResult +#[allow(clippy::redundant_closure)] +pub fn take_till>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| i.split_at_position_complete(|c| cond(c)) + let mut parser = super::take_till(cond); + + move |i: I| parser.process::>(i) } /// Returns the longest (at least 1) input slice till a predicate is met. @@ -358,17 +288,15 @@ /// assert_eq!(till_colon("12345"), Ok(("", "12345"))); /// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1)))); /// ``` -pub fn take_till1>( - cond: F, -) -> impl Fn(Input) -> IResult +#[allow(clippy::redundant_closure)] +pub fn take_till1>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let e: ErrorKind = ErrorKind::TakeTill1; - i.split_at_position1_complete(|c| cond(c), e) - } + let mut parser = super::take_till1(cond); + + move |i: I| parser.process::>(i) } /// Returns an input slice containing the first N input elements (Input[..N]). @@ -400,18 +328,14 @@ /// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙"))); /// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref()))); /// ``` -pub fn take>( - count: C, -) -> impl Fn(Input) -> IResult +pub fn take>(count: C) -> impl FnMut(I) -> IResult where - Input: InputIter + InputTake, + I: Input, C: ToUsize, { - let c = count.to_usize(); - move |i: Input| match i.slice_index(c) { - Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))), - Ok(index) => Ok(i.take_split(index)), - } + let mut parser = super::take(count); + + move |i: I| parser.process::>(i) } /// Returns the input slice up to the first occurrence of the pattern. @@ -432,21 +356,14 @@ /// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); /// ``` -pub fn take_until>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + FindSubstring, - T: InputLength + Clone, -{ - move |i: Input| { - let t = tag.clone(); - let res: IResult<_, _, Error> = match i.find_substring(t) { - None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), - Some(index) => Ok(i.take_split(index)), - }; - res - } +pub fn take_until>(tag: T) -> impl FnMut(I) -> IResult +where + I: Input + FindSubstring, + T: Input + Clone, +{ + let mut parser = super::take_until(tag); + + move |i: I| parser.process::>(i) } /// Returns the non empty input slice up to the first occurrence of the pattern. @@ -468,22 +385,14 @@ /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); /// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); /// ``` -pub fn take_until1>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + FindSubstring, - T: InputLength + Clone, -{ - move |i: Input| { - let t = tag.clone(); - let res: IResult<_, _, Error> = match i.find_substring(t) { - None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), - Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), - Some(index) => Ok(i.take_split(index)), - }; - res - } +pub fn take_until1>(tag: T) -> impl FnMut(I) -> IResult +where + I: Input + FindSubstring, + T: Input + Clone, +{ + let mut parser = super::take_until1(tag); + + move |i: I| parser.process::>(i) } /// Matches a byte string with escaped characters. @@ -506,85 +415,21 @@ /// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#))); /// ``` /// -pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>( - mut normal: F, +pub fn escaped<'a, I, Error, F, G>( + normal: F, control_char: char, - mut escapable: G, -) -> impl FnMut(Input) -> IResult + escapable: G, +) -> impl FnMut(I) -> IResult where - Input: Clone - + crate::traits::Offset - + InputLength - + InputTake - + InputTakeAtPosition - + Slice> - + InputIter, - ::Item: crate::traits::AsChar, - F: Parser, - G: Parser, - Error: ParseError, -{ - use crate::traits::AsChar; - - move |input: Input| { - let mut i = input.clone(); - - while i.input_len() > 0 { - let current_len = i.input_len(); - - match normal.parse(i.clone()) { - Ok((i2, _)) => { - // return if we consumed everything or if the normal parser - // does not consume anything - if i2.input_len() == 0 { - return Ok((input.slice(input.input_len()..), input)); - } else if i2.input_len() == current_len { - let index = input.offset(&i2); - return Ok(input.take_split(index)); - } else { - i = i2; - } - } - Err(Err::Error(_)) => { - // unwrap() should be safe here since index < $i.input_len() - if i.iter_elements().next().unwrap().as_char() == control_char { - let next = control_char.len_utf8(); - if next >= i.input_len() { - return Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::Escaped, - ))); - } else { - match escapable.parse(i.slice(next..)) { - Ok((i2, _)) => { - if i2.input_len() == 0 { - return Ok((input.slice(input.input_len()..), input)); - } else { - i = i2; - } - } - Err(e) => return Err(e), - } - } - } else { - let index = input.offset(&i); - if index == 0 { - return Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::Escaped, - ))); - } - return Ok(input.take_split(index)); - } - } - Err(e) => { - return Err(e); - } - } - } + I: Clone + crate::traits::Offset + Input + 'a, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + let mut parser = super::escaped(normal, control_char, escapable); - Ok((input.slice(input.input_len()..), input)) - } + move |i: I| parser.process::>(i) } /// Matches a byte string with escaped characters. @@ -620,93 +465,32 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn escaped_transform( - mut normal: F, +pub fn escaped_transform( + normal: F, control_char: char, - mut transform: G, -) -> impl FnMut(Input) -> IResult + transform: G, +) -> impl FnMut(I) -> IResult where - Input: Clone - + crate::traits::Offset - + InputLength - + InputTake - + InputTakeAtPosition - + Slice> - + InputIter, - Input: crate::traits::ExtendInto, + I: Clone + crate::traits::Offset + Input, + I: crate::traits::ExtendInto, O1: crate::traits::ExtendInto, O2: crate::traits::ExtendInto, - ::Item: crate::traits::AsChar, - F: Parser, - G: Parser, - Error: ParseError, -{ - use crate::traits::AsChar; - - move |input: Input| { - let mut index = 0; - let mut res = input.new_builder(); - - let i = input.clone(); - - while index < i.input_len() { - let current_len = i.input_len(); - let remainder = i.slice(index..); - match normal.parse(remainder.clone()) { - Ok((i2, o)) => { - o.extend_into(&mut res); - if i2.input_len() == 0 { - return Ok((i.slice(i.input_len()..), res)); - } else if i2.input_len() == current_len { - return Ok((remainder, res)); - } else { - index = input.offset(&i2); - } - } - Err(Err::Error(_)) => { - // unwrap() should be safe here since index < $i.input_len() - if remainder.iter_elements().next().unwrap().as_char() == control_char { - let next = index + control_char.len_utf8(); - let input_len = input.input_len(); - - if next >= input_len { - return Err(Err::Error(Error::from_error_kind( - remainder, - ErrorKind::EscapedTransform, - ))); - } else { - match transform.parse(i.slice(next..)) { - Ok((i2, o)) => { - o.extend_into(&mut res); - if i2.input_len() == 0 { - return Ok((i.slice(i.input_len()..), res)); - } else { - index = input.offset(&i2); - } - } - Err(e) => return Err(e), - } - } - } else { - if index == 0 { - return Err(Err::Error(Error::from_error_kind( - remainder, - ErrorKind::EscapedTransform, - ))); - } - return Ok((remainder, res)); - } - } - Err(e) => return Err(e), - } - } - Ok((input.slice(index..), res)) - } + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + let mut parser = super::escaped_transform(normal, control_char, transform); + + move |i: I| parser.process::>(i) } #[cfg(test)] mod tests { use super::*; + use crate::error::ErrorKind; + use crate::AsChar; + use crate::Err; #[test] fn complete_take_while_m_n_utf8_all_matching() { @@ -736,7 +520,7 @@ } // issue ##1118 escaped does not work with empty string - fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> { + fn unquote(input: &str) -> IResult<&str, &str> { use crate::bytes::complete::*; use crate::character::complete::*; use crate::combinator::opt; @@ -746,11 +530,37 @@ char('"'), escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), char('"'), - )(input) + ) + .parse(input) } #[test] fn escaped_hang_1118() { assert_eq!(unquote(r#""""#), Ok(("", ""))); } + + // issue #1630 take_while_m_n is invalid for multi-byte UTF-8 characters + #[test] + fn complete_take_while_m_n_multibyte() { + use crate::error::Error; + + fn multi_byte_chars(s: &str, m: usize, n: usize) -> IResult<&str, &str> { + take_while_m_n(m, n, |c: char| c.len() > 1)(s) + } + + assert_eq!(multi_byte_chars("€ latin", 0, 64), Ok((" latin", "€"))); + assert_eq!(multi_byte_chars("𝄠 latin", 0, 1), Ok((" latin", "𝄠"))); + assert_eq!(multi_byte_chars("باب latin", 0, 64), Ok((" latin", "باب"))); + assert_eq!( + multi_byte_chars("💣💢ᾠ latin", 3, 3), + Ok((" latin", "💣💢ᾠ")) + ); + assert_eq!(multi_byte_chars("latin", 0, 64), Ok(("latin", ""))); + assert_eq!(multi_byte_chars("باب", 1, 3), Ok(("", "باب"))); + assert_eq!(multi_byte_chars("باب", 1, 2), Ok(("ب", "با"))); + assert_eq!( + multi_byte_chars("latin", 1, 64), + Err(Err::Error(Error::new("latin", ErrorKind::TakeWhileMN))) + ); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,3 +4,1041 @@ pub mod streaming; #[cfg(test)] mod tests; + +use core::marker::PhantomData; + +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, Needed, Parser}; +use crate::lib::std::result::Result::*; +use crate::traits::{Compare, CompareResult}; +use crate::AsChar; +use crate::Check; +use crate::ExtendInto; +use crate::FindSubstring; +use crate::FindToken; +use crate::Input; +use crate::IsStreaming; +use crate::Mode; +use crate::OutputM; +use crate::OutputMode; +use crate::ToUsize; + +/// Recognizes a pattern. +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::tag; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag("Hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag)))); +/// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4)))); +/// ``` +pub fn tag>(tag: T) -> impl Parser +where + I: Input + Compare, + T: Input + Clone, +{ + Tag { + tag, + e: PhantomData, + } +} + +/// Tag implementation +pub struct Tag { + tag: T, + e: PhantomData, +} + +impl, T> Parser for Tag +where + I: Input + Compare, + T: Input + Clone, +{ + type Output = I; + + type Error = Error; + + fn process(&mut self, i: I) -> crate::PResult { + let tag_len = self.tag.input_len(); + let t = self.tag.clone(); + + match i.compare(t) { + CompareResult::Ok => Ok((i.take_from(tag_len), OM::Output::bind(|| i.take(tag_len)))), + CompareResult::Incomplete => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))) + } else { + Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::Tag; + Error::from_error_kind(i, e) + }))) + } + } + CompareResult::Error => Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::Tag; + Error::from_error_kind(i, e) + }))), + } + } +} + +/// Recognizes a case insensitive pattern. +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument with no regard to case. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::tag_no_case; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag_no_case("hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); +/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5)))); +/// ``` +pub fn tag_no_case>(tag: T) -> impl Parser +where + I: Input + Compare, + T: Input + Clone, +{ + TagNoCase { + tag, + e: PhantomData, + } +} + +/// Case insensitive Tag implementation +pub struct TagNoCase { + tag: T, + e: PhantomData, +} + +impl, T> Parser for TagNoCase +where + I: Input + Compare, + T: Input + Clone, +{ + type Output = I; + + type Error = Error; + + fn process(&mut self, i: I) -> crate::PResult { + let tag_len = self.tag.input_len(); + let t = self.tag.clone(); + + match i.compare_no_case(t) { + CompareResult::Ok => Ok((i.take_from(tag_len), OM::Output::bind(|| i.take(tag_len)))), + CompareResult::Incomplete => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))) + } else { + Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::Tag; + Error::from_error_kind(i, e) + }))) + } + } + CompareResult::Error => Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::Tag; + Error::from_error_kind(i, e) + }))), + } + } +} + +/// Parser wrapper for `split_at_position` +pub struct SplitPosition { + predicate: F, + error: PhantomData, +} + +impl, F> Parser for SplitPosition +where + I: Input, + F: Fn(::Item) -> bool, +{ + type Output = I; + + type Error = Error; + + #[inline(always)] + fn process(&mut self, i: I) -> crate::PResult { + i.split_at_position_mode::(|c| (self.predicate)(c)) + } +} + +/// Parser wrapper for `split_at_position1` +pub struct SplitPosition1 { + e: ErrorKind, + predicate: F, + error: PhantomData, +} + +impl, F> Parser for SplitPosition1 +where + I: Input, + F: Fn(::Item) -> bool, +{ + type Output = I; + + type Error = Error; + + #[inline(always)] + fn process(&mut self, i: I) -> crate::PResult { + i.split_at_position_mode1::(|c| (self.predicate)(c), self.e) + } +} + +/// Parse till certain characters are met. +/// +/// The parser will return the longest slice till one of the characters of the combinator's argument are met. +/// +/// It doesn't consume the matched character. +/// +/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::is_not; +/// +/// fn not_space(s: &str) -> IResult<&str, &str> { +/// is_not(" \t\r\n")(s) +/// } +/// +/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); +/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); +/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace"))); +/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot)))); +/// ``` +pub fn is_not>(arr: T) -> impl Parser +where + I: Input, + T: FindToken<::Item>, +{ + SplitPosition1 { + e: ErrorKind::IsNot, + predicate: move |c| arr.find_token(c), + error: PhantomData, + } +} + +/// Returns the longest slice of the matches the pattern. +/// +/// The parser will return the longest slice consisting of the characters in provided in the +/// combinator's argument. +/// +/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::is_a; +/// +/// fn hex(s: &str) -> IResult<&str, &str> { +/// is_a("1234567890ABCDEF")(s) +/// } +/// +/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); +/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); +/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); +/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E"))); +/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA)))); +/// ``` +pub fn is_a>(arr: T) -> impl Parser +where + I: Input, + T: FindToken<::Item>, +{ + SplitPosition1 { + e: ErrorKind::IsA, + predicate: move |c| !arr.find_token(c), + error: PhantomData, + } +} + +/// Returns the longest input slice (if any) that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::complete::take_while; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); +/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); +/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..]))); +/// ``` +pub fn take_while>(cond: F) -> impl Parser +where + I: Input, + F: Fn(::Item) -> bool, +{ + SplitPosition { + predicate: move |c| !cond(c), + error: PhantomData, + } +} + +/// Returns the longest (at least 1) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input. +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_while1; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while1(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); +/// ``` +pub fn take_while1>(cond: F) -> impl Parser +where + I: Input, + F: Fn(::Item) -> bool, +{ + SplitPosition1 { + e: ErrorKind::TakeWhile1, + predicate: move |c| !cond(c), + error: PhantomData, + } +} + +/// Returns the longest (m <= len <= n) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met. +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short. +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_while_m_n; +/// use nom::character::is_alphabetic; +/// +/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while_m_n(3, 6, is_alphabetic)(s) +/// } +/// +/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); +/// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); +/// ``` +pub fn take_while_m_n>( + m: usize, + n: usize, + predicate: F, +) -> impl Parser +where + I: Input, + F: Fn(::Item) -> bool, +{ + TakeWhileMN { + m, + n, + predicate, + e: PhantomData, + } +} + +/// Parser implementation for [take_while_m_n] +pub struct TakeWhileMN { + m: usize, + n: usize, + predicate: F, + e: PhantomData, +} + +impl, F> Parser for TakeWhileMN +where + I: Input, + F: Fn(::Item) -> bool, +{ + type Output = I; + type Error = Error; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let mut count = 0; + for (i, (index, item)) in input.iter_indices().enumerate() { + if i == self.n { + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } + + if !(self.predicate)(item) { + if i >= self.m { + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } else { + return Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::TakeWhileMN) + }))); + } + } + count += 1; + } + + let input_len = input.input_len(); + if OM::Incomplete::is_streaming() { + let needed = if self.m > input_len { + self.m - input_len + } else { + 1 + }; + Err(Err::Incomplete(Needed::new(needed))) + } else if count >= self.m { + Ok(( + input.take_from(input_len), + OM::Output::bind(|| input.take(input_len)), + )) + } else { + Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::TakeWhileMN) + }))) + } + } +} + +/// Returns the longest input slice (if any) till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::complete::take_till; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed +/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); +/// assert_eq!(till_colon(""), Ok(("", ""))); +/// ``` +#[allow(clippy::redundant_closure)] +pub fn take_till>(cond: F) -> impl Parser +where + I: Input, + F: Fn(::Item) -> bool, +{ + SplitPosition { + predicate: cond, + error: PhantomData, + } +} + +/// Returns the longest (at least 1) input slice till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the +/// end of input or if there was not match. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_till1; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till1(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); +/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[allow(clippy::redundant_closure)] +pub fn take_till1>(cond: F) -> impl Parser +where + I: Input, + F: Fn(::Item) -> bool, +{ + SplitPosition1 { + e: ErrorKind::TakeTill1, + predicate: cond, + error: PhantomData, + } +} + +/// Returns an input slice containing the first N input elements (Input[..N]). +/// +/// # Streaming Specific +/// *Streaming version* if the input has less than N elements, `take` will +/// return a `Err::Incomplete(Needed::new(M))` where M is the number of +/// additional bytes the parser would need to succeed. +/// It is well defined for `&[u8]` as the number of elements is the byte size, +/// but for types like `&str`, we cannot know how many bytes correspond for +/// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)` +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take; +/// +/// fn take6(s: &str) -> IResult<&str, &str> { +/// take(6usize)(s) +/// } +/// +/// assert_eq!(take6("1234567"), Ok(("7", "123456"))); +/// assert_eq!(take6("things"), Ok(("", "things"))); +/// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown))); +/// ``` +pub fn take>(count: C) -> impl Parser +where + I: Input, + C: ToUsize, +{ + Take { + length: count.to_usize(), + e: PhantomData, + } +} + +/// Parser implementation for [take] +pub struct Take { + length: usize, + e: PhantomData, +} + +impl> Parser for Take +where + I: Input, +{ + type Output = I; + type Error = Error; + + fn process(&mut self, i: I) -> crate::PResult { + match i.slice_index(self.length) { + Err(needed) => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(needed)) + } else { + Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::Eof; + Error::from_error_kind(i, e) + }))) + } + } + Ok(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))), + } + } +} + +/// Returns the input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't +/// contain the pattern or if the input is smaller than the pattern. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take_until; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// ``` +pub fn take_until>(tag: T) -> impl Parser +where + I: Input + FindSubstring, + T: Clone, +{ + TakeUntil { + tag, + e: PhantomData, + } +} + +/// Parser implementation for [take_until] +pub struct TakeUntil { + tag: T, + e: PhantomData, +} + +impl> Parser for TakeUntil +where + I: Input + FindSubstring, + T: Clone, +{ + type Output = I; + type Error = Error; + + fn process(&mut self, i: I) -> crate::PResult { + match i.find_substring(self.tag.clone()) { + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::Unknown)) + } else { + Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::TakeUntil; + Error::from_error_kind(i, e) + }))) + } + } + Some(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))), + } + } +} + +/// Returns the non empty input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't +/// contain the pattern or if the input is smaller than the pattern. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_until1; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until1("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); +/// ``` +pub fn take_until1>(tag: T) -> impl Parser +where + I: Input + FindSubstring, + T: Clone, +{ + TakeUntil1 { + tag, + e: PhantomData, + } +} + +/// Parser implementation for take_until1 +pub struct TakeUntil1 { + tag: T, + e: PhantomData, +} + +impl> Parser for TakeUntil1 +where + I: Input + FindSubstring, + T: Clone, +{ + type Output = I; + type Error = Error; + + fn process(&mut self, i: I) -> crate::PResult { + match i.find_substring(self.tag.clone()) { + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::Unknown)) + } else { + Err(Err::Error(OM::Error::bind(|| { + let e: ErrorKind = ErrorKind::TakeUntil; + Error::from_error_kind(i, e) + }))) + } + } + Some(0) => Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(i, ErrorKind::TakeUntil) + }))), + + Some(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))), + } + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not accept the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters +/// # Example +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::character::complete::digit1; +/// use nom::bytes::streaming::escaped; +/// use nom::character::streaming::one_of; +/// +/// fn esc(s: &str) -> IResult<&str, &str> { +/// escaped(digit1, '\\', one_of("\"n\\"))(s) +/// } +/// +/// assert_eq!(esc("123;"), Ok((";", "123"))); +/// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34"))); +/// ``` +/// +pub fn escaped( + normal: F, + control_char: char, + escapable: G, +) -> impl Parser +where + I: Input + Clone + crate::traits::Offset, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + Escaped { + normal, + escapable, + control_char, + e: PhantomData, + } +} + +/// Parser implementation for [escaped] +pub struct Escaped { + normal: F, + escapable: G, + control_char: char, + e: PhantomData, +} + +impl, F, G> Parser for Escaped +where + I: Input + Clone + crate::traits::Offset, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + type Output = I; + type Error = Error; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let mut i = input.clone(); + + while i.input_len() > 0 { + let current_len = i.input_len(); + + match self + .normal + .process::>(i.clone()) + { + Ok((i2, _)) => { + if i2.input_len() == 0 { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + let index = input.input_len(); + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } + } else if i2.input_len() == current_len { + let index = input.offset(&i2); + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } else { + i = i2; + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if i.iter_elements().next().unwrap().as_char() == self.control_char { + let next = self.control_char.len_utf8(); + if next >= i.input_len() { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::new(1))); + } else { + return Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::Escaped) + }))); + } + } else { + match self + .escapable + .process::>(i.take_from(next)) + { + Ok((i2, _)) => { + if i2.input_len() == 0 { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + let index = input.input_len(); + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } + } else { + i = i2; + } + } + Err(e) => return Err(e), + } + } + } else { + let index = input.offset(&i); + if index == 0 { + return Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(input, ErrorKind::Escaped) + }))); + } else { + return Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )); + } + } + } + Err(Err::Failure(e)) => { + return Err(Err::Failure(e)); + } + Err(Err::Incomplete(i)) => { + return Err(Err::Incomplete(i)); + } + } + } + + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::Unknown)) + } else { + let index = input.input_len(); + Ok(( + input.take_from(index), + OM::Output::bind(|| input.take(index)), + )) + } + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not match the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters and transforms them +/// +/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use std::str::from_utf8; +/// use nom::bytes::streaming::{escaped_transform, tag}; +/// use nom::character::streaming::alpha1; +/// use nom::branch::alt; +/// use nom::combinator::value; +/// +/// fn parser(input: &str) -> IResult<&str, String> { +/// escaped_transform( +/// alpha1, +/// '\\', +/// alt(( +/// value("\\", tag("\\")), +/// value("\"", tag("\"")), +/// value("\n", tag("n")), +/// )) +/// )(input) +/// } +/// +/// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd")))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn escaped_transform( + normal: F, + control_char: char, + transform: G, +) -> impl Parser +where + I: Clone + crate::traits::Offset + Input, + I: crate::traits::ExtendInto, + >::Output: crate::traits::ExtendInto, + >::Output: crate::traits::ExtendInto, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + EscapedTransform { + normal, + control_char, + transform, + e: PhantomData, + extend: PhantomData, + o: PhantomData, + } +} + +/// Parser implementation for [escaped_transform] +pub struct EscapedTransform { + normal: F, + transform: G, + control_char: char, + e: PhantomData, + extend: PhantomData, + o: PhantomData, +} + +impl, F, G, ExtendItem, Output> Parser + for EscapedTransform +where + I: Clone + crate::traits::Offset + Input, + I: crate::traits::ExtendInto, + >::Output: crate::traits::ExtendInto, + >::Output: crate::traits::ExtendInto, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + type Output = Output; + type Error = Error; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let mut index = 0; + let mut res = OM::Output::bind(|| input.new_builder()); + + while index < input.input_len() { + let current_len = input.input_len(); + let remainder = input.take_from(index); + match self.normal.process::(remainder.clone()) { + Ok((i2, o)) => { + res = OM::Output::combine(o, res, |o, mut res| { + o.extend_into(&mut res); + res + }); + if i2.input_len() == 0 { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + let index = input.input_len(); + return Ok((input.take_from(index), res)); + } + } else if i2.input_len() == current_len { + return Ok((remainder, res)); + } else { + index = input.offset(&i2); + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if remainder.iter_elements().next().unwrap().as_char() == self.control_char { + let next = index + self.control_char.len_utf8(); + let input_len = input.input_len(); + + if next >= input_len { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + return Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(remainder, ErrorKind::EscapedTransform) + }))); + } + } else { + match self.transform.process::(input.take_from(next)) { + Ok((i2, o)) => { + res = OM::Output::combine(o, res, |o, mut res| { + o.extend_into(&mut res); + res + }); + if i2.input_len() == 0 { + if OM::Incomplete::is_streaming() { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + return Ok((input.take_from(input.input_len()), res)); + } + } else { + index = input.offset(&i2); + } + } + Err(Err::Error(e)) => return Err(Err::Error(e)), + Err(Err::Failure(e)) => { + return Err(Err::Failure(e)); + } + Err(Err::Incomplete(i)) => { + return Err(Err::Incomplete(i)); + } + } + } + } else { + if index == 0 { + return Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(remainder, ErrorKind::EscapedTransform) + }))); + } + return Ok((remainder, res)); + } + } + Err(Err::Failure(e)) => { + return Err(Err::Failure(e)); + } + Err(Err::Incomplete(i)) => { + return Err(Err::Incomplete(i)); + } + } + } + + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::Unknown)) + } else { + Ok((input.take_from(index), res)) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/streaming.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,14 @@ //! Parsers recognizing bytes streams, streaming version -use crate::error::ErrorKind; +use core::marker::PhantomData; + use crate::error::ParseError; -use crate::internal::{Err, IResult, Needed, Parser}; -use crate::lib::std::ops::RangeFrom; -use crate::lib::std::result::Result::*; -use crate::traits::{ - Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, - InputTakeAtPosition, Slice, ToUsize, -}; +use crate::internal::{IResult, Parser}; +use crate::traits::{Compare, FindSubstring, FindToken, ToUsize}; +use crate::Emit; +use crate::Input; +use crate::OutputM; +use crate::Streaming; /// Recognizes a pattern. /// @@ -28,26 +28,18 @@ /// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag)))); /// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4)))); /// ``` -pub fn tag>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + InputLength + Compare, - T: InputLength + Clone, -{ - move |i: Input| { - let tag_len = tag.input_len(); - let t = tag.clone(); - - let res: IResult<_, _, Error> = match i.compare(t) { - CompareResult::Ok => Ok(i.take_split(tag_len)), - CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))), - CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(Err::Error(Error::from_error_kind(i, e))) - } +pub fn tag>(tag: T) -> impl Fn(I) -> IResult +where + I: Input + Compare, + T: Input + Clone, +{ + move |i: I| { + let mut parser = super::Tag { + tag: tag.clone(), + e: PhantomData, }; - res + + parser.process::>(i) } } @@ -70,26 +62,18 @@ /// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5)))); /// ``` -pub fn tag_no_case>( - tag: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTake + InputLength + Compare, - T: InputLength + Clone, -{ - move |i: Input| { - let tag_len = tag.input_len(); - let t = tag.clone(); - - let res: IResult<_, _, Error> = match (i).compare_no_case(t) { - CompareResult::Ok => Ok(i.take_split(tag_len)), - CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))), - CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(Err::Error(Error::from_error_kind(i, e))) - } +pub fn tag_no_case>(tag: T) -> impl Fn(I) -> IResult +where + I: Input + Compare, + T: Input + Clone, +{ + move |i: I| { + let mut parser = super::TagNoCase { + tag: tag.clone(), + e: PhantomData, }; - res + + parser.process::>(i) } } @@ -114,17 +98,14 @@ /// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn is_not>( - arr: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTakeAtPosition, - T: FindToken<::Item>, -{ - move |i: Input| { - let e: ErrorKind = ErrorKind::IsNot; - i.split_at_position1(|c| arr.find_token(c), e) - } +pub fn is_not>(arr: T) -> impl FnMut(I) -> IResult +where + I: Input, + T: FindToken<::Item>, +{ + let mut parser = super::is_not(arr); + + move |i: I| parser.process::>(i) } /// Returns the longest slice of the matches the pattern. @@ -150,17 +131,14 @@ /// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(hex(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn is_a>( - arr: T, -) -> impl Fn(Input) -> IResult -where - Input: InputTakeAtPosition, - T: FindToken<::Item>, -{ - move |i: Input| { - let e: ErrorKind = ErrorKind::IsA; - i.split_at_position1(|c| !arr.find_token(c), e) - } +pub fn is_a>(arr: T) -> impl FnMut(I) -> IResult +where + I: Input, + T: FindToken<::Item>, +{ + let mut parser = super::is_a(arr); + + move |i: I| parser.process::>(i) } /// Returns the longest input slice (if any) that matches the predicate. @@ -174,10 +152,10 @@ /// ```rust /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::take_while; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while(is_alphabetic)(s) +/// take_while(AsChar::is_alpha)(s) /// } /// /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); @@ -185,14 +163,14 @@ /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn take_while>( - cond: F, -) -> impl Fn(Input) -> IResult +pub fn take_while>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| i.split_at_position(|c| !cond(c)) + let mut parser = super::take_while(cond); + + move |i: I| parser.process::>(i) } /// Returns the longest (at least 1) input slice that matches the predicate. @@ -209,27 +187,24 @@ /// ```rust /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_while1; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while1(is_alphabetic)(s) +/// take_while1(AsChar::is_alpha)(s) /// } /// /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); /// ``` -pub fn take_while1>( - cond: F, -) -> impl Fn(Input) -> IResult +pub fn take_while1>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let e: ErrorKind = ErrorKind::TakeWhile1; - i.split_at_position1(|c| !cond(c), e) - } + let mut parser = super::take_while1(cond); + + move |i: I| parser.process::>(i) } /// Returns the longest (m <= len <= n) input slice that matches the predicate. @@ -245,10 +220,10 @@ /// ```rust /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_while_m_n; -/// use nom::character::is_alphabetic; +/// use nom::AsChar; /// /// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// take_while_m_n(3, 6, is_alphabetic)(s) +/// take_while_m_n(3, 6, AsChar::is_alpha)(s) /// } /// /// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); @@ -257,64 +232,18 @@ /// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); /// ``` -pub fn take_while_m_n>( +pub fn take_while_m_n>( m: usize, n: usize, cond: F, -) -> impl Fn(Input) -> IResult +) -> impl FnMut(I) -> IResult where - Input: InputTake + InputIter + InputLength, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let input = i; + let mut parser = super::take_while_m_n(m, n, cond); - match input.position(|c| !cond(c)) { - Some(idx) => { - if idx >= m { - if idx <= n { - let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { - Ok(input.take_split(index)) - } else { - Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))) - }; - res - } else { - let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { - Ok(input.take_split(index)) - } else { - Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))) - }; - res - } - } else { - let e = ErrorKind::TakeWhileMN; - Err(Err::Error(Error::from_error_kind(input, e))) - } - } - None => { - let len = input.input_len(); - if len >= n { - match input.slice_index(n) { - Ok(index) => Ok(input.take_split(index)), - Err(_needed) => Err(Err::Error(Error::from_error_kind( - input, - ErrorKind::TakeWhileMN, - ))), - } - } else { - let needed = if m > len { m - len } else { 1 }; - Err(Err::Incomplete(Needed::new(needed))) - } - } - } - } + move |i: I| parser.process::>(i) } /// Returns the longest input slice (if any) till a predicate is met. @@ -340,14 +269,15 @@ /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn take_till>( - cond: F, -) -> impl Fn(Input) -> IResult +#[allow(clippy::redundant_closure)] +pub fn take_till>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| i.split_at_position(|c| cond(c)) + let mut parser = super::take_till(cond); + + move |i: I| parser.process::>(i) } /// Returns the longest (at least 1) input slice till a predicate is met. @@ -372,17 +302,15 @@ /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn take_till1>( - cond: F, -) -> impl Fn(Input) -> IResult +#[allow(clippy::redundant_closure)] +pub fn take_till1>(cond: F) -> impl FnMut(I) -> IResult where - Input: InputTakeAtPosition, - F: Fn(::Item) -> bool, + I: Input, + F: Fn(::Item) -> bool, { - move |i: Input| { - let e: ErrorKind = ErrorKind::TakeTill1; - i.split_at_position1(|c| cond(c), e) - } + let mut parser = super::take_till1(cond); + + move |i: I| parser.process::>(i) } /// Returns an input slice containing the first N input elements (Input[..N]). @@ -408,18 +336,14 @@ /// assert_eq!(take6("things"), Ok(("", "things"))); /// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown))); /// ``` -pub fn take>( - count: C, -) -> impl Fn(Input) -> IResult +pub fn take>(count: C) -> impl FnMut(I) -> IResult where - Input: InputIter + InputTake + InputLength, + I: Input, C: ToUsize, { - let c = count.to_usize(); - move |i: Input| match i.slice_index(c) { - Err(i) => Err(Err::Incomplete(i)), - Ok(index) => Ok(i.take_split(index)), - } + let mut parser = super::take(count); + + move |i: I| parser.process::>(i) } /// Returns the input slice up to the first occurrence of the pattern. @@ -443,22 +367,14 @@ /// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); /// ``` -pub fn take_until>( - tag: T, -) -> impl Fn(Input) -> IResult +pub fn take_until>(tag: T) -> impl FnMut(I) -> IResult where - Input: InputTake + InputLength + FindSubstring, + I: Input + FindSubstring, T: Clone, { - move |i: Input| { - let t = tag.clone(); + let mut parser = super::take_until(tag); - let res: IResult<_, _, Error> = match i.find_substring(t) { - None => Err(Err::Incomplete(Needed::Unknown)), - Some(index) => Ok(i.take_split(index)), - }; - res - } + move |i: I| parser.process::>(i) } /// Returns the non empty input slice up to the first occurrence of the pattern. @@ -483,23 +399,14 @@ /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); /// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); /// ``` -pub fn take_until1>( - tag: T, -) -> impl Fn(Input) -> IResult +pub fn take_until1>(tag: T) -> impl FnMut(I) -> IResult where - Input: InputTake + InputLength + FindSubstring, + I: Input + FindSubstring, T: Clone, { - move |i: Input| { - let t = tag.clone(); + let mut parser = super::take_until1(tag); - let res: IResult<_, _, Error> = match i.find_substring(t) { - None => Err(Err::Incomplete(Needed::Unknown)), - Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), - Some(index) => Ok(i.take_split(index)), - }; - res - } + move |i: I| parser.process::>(i) } /// Matches a byte string with escaped characters. @@ -522,74 +429,21 @@ /// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34"))); /// ``` /// -pub fn escaped( - mut normal: F, +pub fn escaped( + normal: F, control_char: char, - mut escapable: G, -) -> impl FnMut(Input) -> IResult + escapable: G, +) -> impl FnMut(I) -> IResult where - Input: Clone - + crate::traits::Offset - + InputLength - + InputTake - + InputTakeAtPosition - + Slice> - + InputIter, - ::Item: crate::traits::AsChar, - F: Parser, - G: Parser, - Error: ParseError, -{ - use crate::traits::AsChar; - - move |input: Input| { - let mut i = input.clone(); - - while i.input_len() > 0 { - let current_len = i.input_len(); - - match normal.parse(i.clone()) { - Ok((i2, _)) => { - if i2.input_len() == 0 { - return Err(Err::Incomplete(Needed::Unknown)); - } else if i2.input_len() == current_len { - let index = input.offset(&i2); - return Ok(input.take_split(index)); - } else { - i = i2; - } - } - Err(Err::Error(_)) => { - // unwrap() should be safe here since index < $i.input_len() - if i.iter_elements().next().unwrap().as_char() == control_char { - let next = control_char.len_utf8(); - if next >= i.input_len() { - return Err(Err::Incomplete(Needed::new(1))); - } else { - match escapable.parse(i.slice(next..)) { - Ok((i2, _)) => { - if i2.input_len() == 0 { - return Err(Err::Incomplete(Needed::Unknown)); - } else { - i = i2; - } - } - Err(e) => return Err(e), - } - } - } else { - let index = input.offset(&i); - return Ok(input.take_split(index)); - } - } - Err(e) => { - return Err(e); - } - } - } + I: Input + Clone + crate::traits::Offset, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + let mut parser = super::escaped(normal, control_char, escapable); - Err(Err::Incomplete(Needed::Unknown)) - } + move |i: I| parser.process::>(i) } /// Matches a byte string with escaped characters. @@ -624,77 +478,22 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn escaped_transform( - mut normal: F, +pub fn escaped_transform( + normal: F, control_char: char, - mut transform: G, -) -> impl FnMut(Input) -> IResult + transform: G, +) -> impl FnMut(I) -> IResult where - Input: Clone - + crate::traits::Offset - + InputLength - + InputTake - + InputTakeAtPosition - + Slice> - + InputIter, - Input: crate::traits::ExtendInto, + I: Clone + crate::traits::Offset + Input, + I: crate::traits::ExtendInto, O1: crate::traits::ExtendInto, O2: crate::traits::ExtendInto, - ::Item: crate::traits::AsChar, - F: Parser, - G: Parser, - Error: ParseError, -{ - use crate::traits::AsChar; - - move |input: Input| { - let mut index = 0; - let mut res = input.new_builder(); - - let i = input.clone(); - - while index < i.input_len() { - let current_len = i.input_len(); - let remainder = i.slice(index..); - match normal.parse(remainder.clone()) { - Ok((i2, o)) => { - o.extend_into(&mut res); - if i2.input_len() == 0 { - return Err(Err::Incomplete(Needed::Unknown)); - } else if i2.input_len() == current_len { - return Ok((remainder, res)); - } else { - index = input.offset(&i2); - } - } - Err(Err::Error(_)) => { - // unwrap() should be safe here since index < $i.input_len() - if remainder.iter_elements().next().unwrap().as_char() == control_char { - let next = index + control_char.len_utf8(); - let input_len = input.input_len(); - - if next >= input_len { - return Err(Err::Incomplete(Needed::Unknown)); - } else { - match transform.parse(i.slice(next..)) { - Ok((i2, o)) => { - o.extend_into(&mut res); - if i2.input_len() == 0 { - return Err(Err::Incomplete(Needed::Unknown)); - } else { - index = input.offset(&i2); - } - } - Err(e) => return Err(e), - } - } - } else { - return Ok((remainder, res)); - } - } - Err(e) => return Err(e), - } - } - Err(Err::Incomplete(Needed::Unknown)) - } + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + let mut parser = super::escaped_transform(normal, control_char, transform); + + move |i: I| parser.process::>(i) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/bytes/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/bytes/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,10 +1,11 @@ -use crate::character::is_alphabetic; use crate::character::streaming::{ - alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, - multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, + alpha1 as alpha, alphanumeric1 as alphanumeric, bin_digit1 as bin_digit, digit1 as digit, + hex_digit1 as hex_digit, multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, }; use crate::error::ErrorKind; use crate::internal::{Err, IResult, Needed}; +use crate::AsChar; +use crate::Parser; #[cfg(feature = "alloc")] use crate::{ branch::alt, @@ -146,6 +147,8 @@ #[cfg(feature = "alloc")] #[test] fn escape_transform() { + use crate::Parser; + fn esc(i: &[u8]) -> IResult<&[u8], String> { map( escaped_transform( @@ -158,7 +161,8 @@ )), ), to_s, - )(i) + ) + .parse(i) } assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); @@ -202,7 +206,8 @@ )), ), to_s, - )(i) + ) + .parse(i) } assert_eq!( esc2(&b"abèDEF;"[..]), @@ -300,7 +305,7 @@ use crate::sequence::delimited; fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(delimited(tag("")))(i) + recognize(delimited(tag(""))).parse(i) } let r = x(&b" aaa"[..]); assert_eq!(r, Ok((&b" aaa"[..], &b""[..]))); @@ -308,43 +313,49 @@ let semicolon = &b";"[..]; fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(alpha)(i) + recognize(alpha).parse(i) } let ra = ya(&b"abc;"[..]); assert_eq!(ra, Ok((semicolon, &b"abc"[..]))); fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(digit)(i) + recognize(digit).parse(i) } let rd = yd(&b"123;"[..]); assert_eq!(rd, Ok((semicolon, &b"123"[..]))); fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(hex_digit)(i) + recognize(hex_digit).parse(i) } let rhd = yhd(&b"123abcDEF;"[..]); assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..]))); fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(oct_digit)(i) + recognize(oct_digit).parse(i) } let rod = yod(&b"1234567;"[..]); assert_eq!(rod, Ok((semicolon, &b"1234567"[..]))); + fn ybd(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(bin_digit).parse(i) + } + let rbd = ybd(&b"101010;"[..]); + assert_eq!(rbd, Ok((semicolon, &b"101010"[..]))); + fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(alphanumeric)(i) + recognize(alphanumeric).parse(i) } let ran = yan(&b"123abc;"[..]); assert_eq!(ran, Ok((semicolon, &b"123abc"[..]))); fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(space)(i) + recognize(space).parse(i) } let rs = ys(&b" \t;"[..]); assert_eq!(rs, Ok((semicolon, &b" \t"[..]))); fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(multispace)(i) + recognize(multispace).parse(i) } let rms = yms(&b" \t\r\n;"[..]); assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..]))); @@ -355,7 +366,7 @@ use crate::bytes::streaming::take_while; fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(is_alphabetic)(i) + take_while(AsChar::is_alpha)(i) } let a = b""; let b = b"abcd"; @@ -373,7 +384,7 @@ use crate::bytes::streaming::take_while1; fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while1(is_alphabetic)(i) + take_while1(AsChar::is_alpha)(i) } let a = b""; let b = b"abcd"; @@ -394,7 +405,7 @@ use crate::bytes::streaming::take_while_m_n; fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while_m_n(2, 4, is_alphabetic)(i) + take_while_m_n(2, 4, AsChar::is_alpha)(i) } let a = b""; let b = b"a"; @@ -406,7 +417,7 @@ assert_eq!(x(&a[..]), Err(Err::Incomplete(Needed::new(2)))); assert_eq!(x(&b[..]), Err(Err::Incomplete(Needed::new(1)))); assert_eq!(x(&c[..]), Err(Err::Incomplete(Needed::new(1)))); - assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..]))); + assert_eq!(x(&d[..]), Ok((&b"123"[..], &b"abc"[..]))); assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..]))); assert_eq!( x(&f[..]), @@ -419,7 +430,7 @@ use crate::bytes::streaming::take_till; fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_till(is_alphabetic)(i) + take_till(AsChar::is_alpha)(i) } let a = b""; let b = b"abcd"; @@ -437,7 +448,7 @@ use crate::bytes::streaming::take_till1; fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_till1(is_alphabetic)(i) + take_till1(AsChar::is_alpha)(i) } let a = b""; let b = b"abcd"; @@ -546,14 +557,13 @@ #[cfg(feature = "std")] fn recognize_take_while() { use crate::bytes::streaming::take_while; - use crate::character::is_alphanumeric; use crate::combinator::recognize; fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(is_alphanumeric)(i) + take_while(AsChar::is_alphanum)(i) } fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(x)(i) + recognize(x).parse(i) } assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); println!("X: {:?}", x(&b"ab"[..])); @@ -565,7 +575,7 @@ use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8}; fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - length_data(le_u8)(i) + length_data(le_u8).parse(i) } assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..]))); assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..]))); @@ -574,7 +584,7 @@ fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { let (i, _) = tag("magic")(i)?; - length_data(le_u8)(i) + length_data(le_u8).parse(i) } assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..]))); assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..]))); @@ -612,11 +622,11 @@ assert_eq!(test2("ab"), Err(Err::Incomplete(Needed::new(2)))); assert_eq!( test2("Hello"), - Err(Err::Error(error_position!(&"Hello"[..], ErrorKind::Tag))) + Err(Err::Error(error_position!("Hello", ErrorKind::Tag))) ); assert_eq!( test2("Hel"), - Err(Err::Error(error_position!(&"Hel"[..], ErrorKind::Tag))) + Err(Err::Error(error_position!("Hel", ErrorKind::Tag))) ); } @@ -625,10 +635,10 @@ use crate::bytes::streaming::tag; fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag([0x42])(i) + tag(&[0x42][..])(i) } fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag(&[0x42])(i) + tag(&[0x42][..])(i) } let input = [0x42, 0x00]; assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/complete.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,11 +7,12 @@ use crate::error::ErrorKind; use crate::error::ParseError; use crate::internal::{Err, IResult}; -use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; -use crate::traits::{ - AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice, -}; +use crate::traits::{AsChar, FindToken, Input}; use crate::traits::{Compare, CompareResult}; +use crate::Complete; +use crate::Emit; +use crate::OutputM; +use crate::Parser; /// Recognizes one character. /// @@ -29,18 +30,13 @@ /// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); /// ``` -pub fn char>(c: char) -> impl Fn(I) -> IResult +pub fn char>(c: char) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { - move |i: I| match (i).iter_elements().next().map(|t| { - let b = t.as_char() == c; - (&c, b) - }) { - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - _ => Err(Err::Error(Error::from_char(i, c))), - } + let mut parser = super::char(c); + move |i: I| parser.process::>(i) } /// Recognizes one character and checks that it satisfies a predicate @@ -58,20 +54,14 @@ /// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy)))); /// ``` -pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult +pub fn satisfy>(predicate: F) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar, + I: Input, + ::Item: AsChar, F: Fn(char) -> bool, { - move |i: I| match (i).iter_elements().next().map(|t| { - let c = t.as_char(); - let b = cond(c); - (c, b) - }) { - Some((c, true)) => Ok((i.slice(c.len()..), c)), - _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))), - } + let mut parser = super::satisfy(predicate); + move |i: I| parser.process::>(i) } /// Recognizes one of the provided characters. @@ -86,16 +76,14 @@ /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf)))); /// ``` -pub fn one_of>(list: T) -> impl Fn(I) -> IResult +pub fn one_of>(list: T) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar + Copy, - T: FindToken<::Item>, -{ - move |i: I| match (i).iter_elements().next().map(|c| (c, list.find_token(c))) { - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::OneOf))), - } + I: Input, + ::Item: AsChar, + T: FindToken, +{ + let mut parser = super::one_of(list); + move |i: I| parser.process::>(i) } /// Recognizes a character that is not in the provided characters. @@ -110,16 +98,14 @@ /// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); /// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::NoneOf)))); /// ``` -pub fn none_of>(list: T) -> impl Fn(I) -> IResult +pub fn none_of>(list: T) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar + Copy, - T: FindToken<::Item>, -{ - move |i: I| match (i).iter_elements().next().map(|c| (c, !list.find_token(c))) { - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::NoneOf))), - } + I: Input, + ::Item: AsChar, + T: FindToken, +{ + let mut parser = super::none_of(list); + move |i: I| parser.process::>(i) } /// Recognizes the string "\r\n". @@ -140,13 +126,11 @@ /// ``` pub fn crlf>(input: T) -> IResult where - T: Slice> + Slice>, - T: InputIter, + T: Input, T: Compare<&'static str>, { match input.compare("\r\n") { - //FIXME: is this the right index? - CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + CompareResult::Ok => Ok(input.take_split(2)), _ => { let e: ErrorKind = ErrorKind::CrLf; Err(Err::Error(E::from_error_kind(input, e))) @@ -176,33 +160,31 @@ /// ``` pub fn not_line_ending>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, - T: InputIter + InputLength, + T: Input, T: Compare<&'static str>, - ::Item: AsChar, - ::Item: AsChar, + ::Item: AsChar, { match input.position(|item| { let c = item.as_char(); c == '\r' || c == '\n' }) { - None => Ok((input.slice(input.input_len()..), input)), + None => Ok(input.take_split(input.input_len())), Some(index) => { - let mut it = input.slice(index..).iter_elements(); + let mut it = input.take_from(index).iter_elements(); let nth = it.next().unwrap().as_char(); if nth == '\r' { - let sliced = input.slice(index..); + let sliced = input.take_from(index); let comp = sliced.compare("\r\n"); match comp { //FIXME: calculate the right index - CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))), + CompareResult::Ok => Ok(input.take_split(index)), _ => { let e: ErrorKind = ErrorKind::Tag; Err(Err::Error(E::from_error_kind(input, e))) } } } else { - Ok((input.slice(index..), input.slice(..index))) + Ok(input.take_split(index)) } } } @@ -226,20 +208,16 @@ /// ``` pub fn line_ending>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, - T: InputIter + InputLength, + T: Input, T: Compare<&'static str>, { match input.compare("\n") { - CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))), + CompareResult::Ok => Ok(input.take_split(1)), CompareResult::Incomplete => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), - CompareResult::Error => { - match input.compare("\r\n") { - //FIXME: is this the right index? - CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), - _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), - } - } + CompareResult::Error => match input.compare("\r\n") { + CompareResult::Ok => Ok(input.take_split(2)), + _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), + }, } } @@ -261,8 +239,8 @@ /// ``` pub fn newline>(input: I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { char('\n')(input) } @@ -285,8 +263,8 @@ /// ``` pub fn tab>(input: I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { char('\t')(input) } @@ -308,16 +286,13 @@ /// ``` pub fn anychar>(input: T) -> IResult where - T: InputIter + InputLength + Slice>, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { - let mut it = input.iter_indices(); + let mut it = input.iter_elements(); match it.next() { None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))), - Some((_, c)) => match it.next() { - None => Ok((input.slice(input.input_len()..), c.as_char())), - Some((idx, _)) => Ok((input.slice(idx..), c.as_char())), - }, + Some(c) => Ok((input.take_from(c.len()), c.as_char())), } } @@ -340,8 +315,8 @@ /// ``` pub fn alpha0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| !item.is_alpha()) } @@ -365,8 +340,8 @@ /// ``` pub fn alpha1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete(|item| !item.is_alpha(), ErrorKind::Alpha) } @@ -391,8 +366,8 @@ /// ``` pub fn digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| !item.is_dec_digit()) } @@ -419,11 +394,11 @@ /// You can use `digit1` in combination with [`map_res`] to parse an integer: /// /// ``` -/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed, Parser}; /// # use nom::combinator::map_res; /// # use nom::character::complete::digit1; /// fn parser(input: &str) -> IResult<&str, u32> { -/// map_res(digit1, str::parse)(input) +/// map_res(digit1, str::parse).parse(input) /// } /// /// assert_eq!(parser("416"), Ok(("", 416))); @@ -434,8 +409,8 @@ /// [`map_res`]: crate::combinator::map_res pub fn digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete(|item| !item.is_dec_digit(), ErrorKind::Digit) } @@ -458,8 +433,8 @@ /// ``` pub fn hex_digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| !item.is_hex_digit()) } @@ -482,8 +457,8 @@ /// ``` pub fn hex_digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete(|item| !item.is_hex_digit(), ErrorKind::HexDigit) } @@ -507,8 +482,8 @@ /// ``` pub fn oct_digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| !item.is_oct_digit()) } @@ -532,12 +507,62 @@ /// ``` pub fn oct_digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete(|item| !item.is_oct_digit(), ErrorKind::OctDigit) } +/// Recognizes zero or more binary characters: 0-1 +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non binary +/// digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::bin_digit0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// bin_digit0(input) +/// } +/// +/// assert_eq!(parser("013a"), Ok(("3a", "01"))); +/// assert_eq!(parser("a013"), Ok(("a013", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn bin_digit0>(input: T) -> IResult +where + T: Input, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_bin_digit()) +} + +/// Recognizes one or more binary characters: 0-1 +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non binary digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::bin_digit1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// bin_digit1(input) +/// } +/// +/// assert_eq!(parser("013a"), Ok(("3a", "01"))); +/// assert_eq!(parser("a013"), Err(Err::Error(Error::new("a013", ErrorKind::BinDigit)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::BinDigit)))); +/// ``` +pub fn bin_digit1>(input: T) -> IResult +where + T: Input, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_bin_digit(), ErrorKind::BinDigit) +} + /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z /// /// *Complete version*: Will return the whole input if no terminating token is found (a non @@ -557,8 +582,8 @@ /// ``` pub fn alphanumeric0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| !item.is_alphanum()) } @@ -582,8 +607,8 @@ /// ``` pub fn alphanumeric1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric) } @@ -607,8 +632,8 @@ /// ``` pub fn space0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar + Clone, { input.split_at_position_complete(|item| { let c = item.as_char(); @@ -635,8 +660,8 @@ /// ``` pub fn space1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete( |item| { @@ -666,8 +691,8 @@ /// ``` pub fn multispace0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position_complete(|item| { let c = item.as_char(); @@ -694,8 +719,8 @@ /// ``` pub fn multispace1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position1_complete( |item| { @@ -708,7 +733,7 @@ pub(crate) fn sign>(input: T) -> IResult where - T: Clone + InputTake, + T: Clone + Input, T: for<'a> Compare<&'a [u8]>, { use crate::bytes::complete::tag; @@ -717,7 +742,8 @@ let (i, opt_sign) = opt(alt(( value(false, tag(&b"-"[..])), value(true, tag(&b"+"[..])), - )))(input)?; + ))) + .parse(input)?; let sign = opt_sign.unwrap_or(true); Ok((i, sign)) @@ -732,8 +758,8 @@ /// *Complete version*: can parse until the end of input. pub fn $t>(input: T) -> IResult where - T: InputIter + Slice> + InputLength + InputTake + Clone, - ::Item: AsChar, + T: Input + Clone, + ::Item: AsChar, T: for <'a> Compare<&'a[u8]>, { let (i, sign) = sign(input.clone())?; @@ -744,46 +770,54 @@ let mut value: $t = 0; if sign { - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } } else { - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) { None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } } - Ok((i.slice(i.input_len()..), value)) + Ok((i.take_from(i.input_len()), value)) } )+ } } -ints! { i8 i16 i32 i64 i128 } +ints! { i8 i16 i32 i64 i128 isize } #[doc(hidden)] macro_rules! uints { @@ -794,8 +828,8 @@ /// *Complete version*: can parse until the end of input. pub fn $t>(input: T) -> IResult where - T: InputIter + Slice> + InputLength, - ::Item: AsChar, + T: Input , + ::Item: AsChar, { let i = input; @@ -804,35 +838,40 @@ } let mut value: $t = 0; - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } - Ok((i.slice(i.input_len()..), value)) + Ok((i.take_from(i.input_len()), value)) } )+ } } -uints! { u8 u16 u32 u64 u128 } +uints! { u8 u16 u32 u64 u128 usize } #[cfg(test)] mod tests { use super::*; use crate::internal::Err; use crate::traits::ParseTo; + use crate::Parser; use proptest::prelude::*; macro_rules! assert_parse( @@ -875,6 +914,13 @@ assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); + assert_eq!( + bin_digit1::<_, (_, ErrorKind)>(b), + Ok((&b"234"[..], &b"1"[..])) + ); + assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); @@ -897,8 +943,8 @@ let e = " "; assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Ok((empty, a))); assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); - assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..]))); - assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..]))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], "a"))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); @@ -906,12 +952,16 @@ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a))); assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c))); - assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..]))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", "a"))); assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1::<_, (_, ErrorKind)>(b), Ok(("234", "1"))); + assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); @@ -971,6 +1021,12 @@ } _ => panic!("wrong return type in offset test for oct_digit"), } + match bin_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for bin_digit"), + } } #[test] @@ -994,10 +1050,7 @@ ); let d: &[u8] = b"ab12cd"; - assert_eq!( - not_line_ending::<_, (_, ErrorKind)>(d), - Ok((&[][..], &d[..])) - ); + assert_eq!(not_line_ending::<_, (_, ErrorKind)>(d), Ok((&[][..], d))); } #[test] @@ -1043,18 +1096,18 @@ Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) ); - assert!(crate::character::is_hex_digit(b'0')); - assert!(crate::character::is_hex_digit(b'9')); - assert!(crate::character::is_hex_digit(b'a')); - assert!(crate::character::is_hex_digit(b'f')); - assert!(crate::character::is_hex_digit(b'A')); - assert!(crate::character::is_hex_digit(b'F')); - assert!(!crate::character::is_hex_digit(b'g')); - assert!(!crate::character::is_hex_digit(b'G')); - assert!(!crate::character::is_hex_digit(b'/')); - assert!(!crate::character::is_hex_digit(b':')); - assert!(!crate::character::is_hex_digit(b'@')); - assert!(!crate::character::is_hex_digit(b'\x60')); + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } #[test] @@ -1068,23 +1121,46 @@ Err(Err::Error(error_position!(i, ErrorKind::OctDigit))) ); - assert!(crate::character::is_oct_digit(b'0')); - assert!(crate::character::is_oct_digit(b'7')); - assert!(!crate::character::is_oct_digit(b'8')); - assert!(!crate::character::is_oct_digit(b'9')); - assert!(!crate::character::is_oct_digit(b'a')); - assert!(!crate::character::is_oct_digit(b'A')); - assert!(!crate::character::is_oct_digit(b'/')); - assert!(!crate::character::is_oct_digit(b':')); - assert!(!crate::character::is_oct_digit(b'@')); - assert!(!crate::character::is_oct_digit(b'\x60')); + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); + } + + #[test] + fn bin_digit_test() { + let i = &b"101010;"[..]; + assert_parse!(bin_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"2"[..]; + assert_parse!( + bin_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::BinDigit))) + ); + + assert!(crate::character::is_bin_digit(b'0')); + assert!(crate::character::is_bin_digit(b'1')); + assert!(!crate::character::is_bin_digit(b'8')); + assert!(!crate::character::is_bin_digit(b'9')); + assert!(!crate::character::is_bin_digit(b'a')); + assert!(!crate::character::is_bin_digit(b'A')); + assert!(!crate::character::is_bin_digit(b'/')); + assert!(!crate::character::is_bin_digit(b':')); + assert!(!crate::character::is_bin_digit(b'@')); + assert!(!crate::character::is_bin_digit(b'\x60')); } #[test] fn full_line_windows() { use crate::sequence::pair; fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + pair(not_line_ending, line_ending).parse(i) } let input = b"abc\r\n"; let output = take_full_line(input); @@ -1095,7 +1171,7 @@ fn full_line_unix() { use crate::sequence::pair; fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + pair(not_line_ending, line_ending).parse(i) } let input = b"abc\n"; let output = take_full_line(input); @@ -1131,7 +1207,7 @@ assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); assert_parse!( crlf("\r"), - Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf))) + Err(Err::Error(error_position!("\r", ErrorKind::CrLf))) ); assert_parse!( crlf("\ra"), @@ -1156,7 +1232,7 @@ assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); assert_parse!( line_ending("\r"), - Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf))) + Err(Err::Error(error_position!("\r", ErrorKind::CrLf))) ); assert_parse!( line_ending("\ra"), @@ -1166,7 +1242,7 @@ fn digit_to_i16(input: &str) -> IResult<&str, i16> { let i = input; - let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let (i, opt_sign) = opt(alt((char('+'), char('-')))).parse(i)?; let sign = match opt_sign { Some('+') => true, Some('-') => false, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,115 +2,401 @@ //! //! Functions recognizing specific characters +use core::marker::PhantomData; + +use crate::error::ErrorKind; +use crate::FindToken; +use crate::IsStreaming; +use crate::Mode; +use crate::{error::ParseError, AsChar, Err, IResult, Input, Needed, Parser}; + #[cfg(test)] mod tests; pub mod complete; pub mod streaming; -/// Tests if byte is ASCII alphabetic: A-Z, a-z +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")] +pub fn is_alphabetic(chr: u8) -> bool { + matches!(chr, 0x41..=0x5A | 0x61..=0x7A) +} + +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")] +pub fn is_digit(chr: u8) -> bool { + matches!(chr, 0x30..=0x39) +} + +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")] +pub fn is_hex_digit(chr: u8) -> bool { + matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) +} + +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")] +pub fn is_oct_digit(chr: u8) -> bool { + matches!(chr, 0x30..=0x37) +} + +/// Tests if byte is ASCII binary digit: 0-1 /// /// # Example /// /// ``` -/// # use nom::character::is_alphabetic; -/// assert_eq!(is_alphabetic(b'9'), false); -/// assert_eq!(is_alphabetic(b'a'), true); +/// # use nom::character::is_bin_digit; +/// assert_eq!(is_bin_digit(b'a'), false); +/// assert_eq!(is_bin_digit(b'2'), false); +/// assert_eq!(is_bin_digit(b'0'), true); +/// assert_eq!(is_bin_digit(b'1'), true); /// ``` #[inline] -pub fn is_alphabetic(chr: u8) -> bool { - (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A) +pub fn is_bin_digit(chr: u8) -> bool { + matches!(chr, 0x30..=0x31) } -/// Tests if byte is ASCII digit: 0-9 +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")] +pub fn is_alphanumeric(chr: u8) -> bool { + AsChar::is_alphanum(chr) +} + +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_space`")] +pub fn is_space(chr: u8) -> bool { + chr == b' ' || chr == b'\t' +} + +#[inline] +#[doc(hidden)] +#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_newline`")] +pub fn is_newline(chr: u8) -> bool { + chr == b'\n' +} + +/// Recognizes one character. /// /// # Example /// /// ``` -/// # use nom::character::is_digit; -/// assert_eq!(is_digit(b'a'), false); -/// assert_eq!(is_digit(b'9'), true); -/// ``` -#[inline] -pub fn is_digit(chr: u8) -> bool { - chr >= 0x30 && chr <= 0x39 +/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; +/// # use nom::character::streaming::char; +/// fn parser(i: &str) -> IResult<&str, char> { +/// char('a')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); +/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn char>(c: char) -> impl Parser +where + I: Input, + ::Item: AsChar, +{ + Char { c, e: PhantomData } } -/// Tests if byte is ASCII hex digit: 0-9, A-F, a-f +/// Parser implementation for [char()] +pub struct Char { + c: char, + e: PhantomData, +} + +impl> Parser for Char +where + I: Input, + ::Item: AsChar, +{ + type Output = char; + type Error = Error; + #[inline(always)] + fn process( + &mut self, + i: I, + ) -> crate::PResult { + match (i).iter_elements().next().map(|t| { + let b = t.as_char() == self.c; + (&self.c, b) + }) { + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(self.c.len() - i.input_len()))) + } else { + Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))) + } + } + Some((_, false)) => Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))), + Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), + } + } +} + +/// Recognizes one character and checks that it satisfies a predicate /// /// # Example /// /// ``` -/// # use nom::character::is_hex_digit; -/// assert_eq!(is_hex_digit(b'a'), true); -/// assert_eq!(is_hex_digit(b'9'), true); -/// assert_eq!(is_hex_digit(b'A'), true); -/// assert_eq!(is_hex_digit(b'x'), false); -/// ``` -#[inline] -pub fn is_hex_digit(chr: u8) -> bool { - (chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66) +/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; +/// # use nom::character::complete::satisfy; +/// fn parser(i: &str) -> IResult<&str, char> { +/// satisfy(|c| c == 'a' || c == 'b')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy)))); +/// ``` +pub fn satisfy>( + predicate: F, +) -> impl Parser +where + I: Input, + ::Item: AsChar, + F: Fn(char) -> bool, +{ + Satisfy { + predicate, + make_error: |i: I| Error::from_error_kind(i, ErrorKind::Satisfy), + } +} + +/// Parser implementation for [satisfy] +pub struct Satisfy { + predicate: F, + make_error: MakeError, } -/// Tests if byte is ASCII octal digit: 0-7 +impl, F, MakeError> Parser for Satisfy +where + I: Input, + ::Item: AsChar, + F: Fn(char) -> bool, + MakeError: Fn(I) -> Error, +{ + type Output = char; + type Error = Error; + + #[inline(always)] + fn process( + &mut self, + i: I, + ) -> crate::PResult { + match (i).iter_elements().next().map(|t| { + let c = t.as_char(); + let b = (self.predicate)(c); + (c, b) + }) { + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::Unknown)) + } else { + Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))) + } + } + Some((_, false)) => Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))), + Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), + } + } +} + +/// Recognizes one of the provided characters. /// /// # Example /// /// ``` -/// # use nom::character::is_oct_digit; -/// assert_eq!(is_oct_digit(b'a'), false); -/// assert_eq!(is_oct_digit(b'9'), false); -/// assert_eq!(is_oct_digit(b'6'), true); -/// ``` -#[inline] -pub fn is_oct_digit(chr: u8) -> bool { - chr >= 0x30 && chr <= 0x37 +/// # use nom::{Err, error::ErrorKind}; +/// # use nom::character::complete::one_of; +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("abc")("b"), Ok(("", 'b'))); +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf)))); +/// ``` +pub fn one_of>(list: T) -> impl Parser +where + I: Input, + ::Item: AsChar, + T: FindToken, +{ + Satisfy { + predicate: move |c: char| list.find_token(c), + make_error: move |i| Error::from_error_kind(i, ErrorKind::OneOf), + } } -/// Tests if byte is ASCII alphanumeric: A-Z, a-z, 0-9 +//. Recognizes a character that is not in the provided characters. /// /// # Example /// /// ``` -/// # use nom::character::is_alphanumeric; -/// assert_eq!(is_alphanumeric(b'-'), false); -/// assert_eq!(is_alphanumeric(b'a'), true); -/// assert_eq!(is_alphanumeric(b'9'), true); -/// assert_eq!(is_alphanumeric(b'A'), true); -/// ``` -#[inline] -pub fn is_alphanumeric(chr: u8) -> bool { - is_alphabetic(chr) || is_digit(chr) +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::character::streaming::none_of; +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z'))); +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::Unknown))); +/// ``` +pub fn none_of>(list: T) -> impl Parser +where + I: Input, + ::Item: AsChar, + T: FindToken, +{ + Satisfy { + predicate: move |c: char| !list.find_token(c), + make_error: move |i| Error::from_error_kind(i, ErrorKind::NoneOf), + } } -/// Tests if byte is ASCII space or tab +// Matches one byte as a character. Note that the input type will +/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. /// /// # Example /// /// ``` -/// # use nom::character::is_space; -/// assert_eq!(is_space(b'\n'), false); -/// assert_eq!(is_space(b'\r'), false); -/// assert_eq!(is_space(b' '), true); -/// assert_eq!(is_space(b'\t'), true); -/// ``` -#[inline] -pub fn is_space(chr: u8) -> bool { - chr == b' ' || chr == b'\t' +/// # use nom::{character::complete::anychar, Err, error::{Error, ErrorKind}, IResult}; +/// fn parser(input: &str) -> IResult<&str, char> { +/// anychar(input) +/// } +/// +/// assert_eq!(parser("abc"), Ok(("bc",'a'))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); +/// ``` +pub fn anychar>(input: T) -> IResult +where + T: Input, + ::Item: AsChar, +{ + let mut it = input.iter_elements(); + match it.next() { + None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))), + Some(c) => Ok((input.take_from(c.len()), c.as_char())), + } +} + +/// Parser implementation for char +pub struct AnyChar { + e: PhantomData, } -/// Tests if byte is ASCII newline: \n +impl> Parser for AnyChar +where + I: Input, + ::Item: AsChar, +{ + type Output = char; + type Error = Error; + + fn process( + &mut self, + i: I, + ) -> crate::PResult { + match (i).iter_elements().next() { + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else { + Err(Err::Error(OM::Error::bind(|| { + Error::from_error_kind(i, ErrorKind::Eof) + }))) + } + } + Some(c) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))), + } + } +} + +/// Recognizes one or more ASCII numerical characters: 0-9 /// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non digit character). /// # Example /// /// ``` -/// # use nom::character::is_newline; -/// assert_eq!(is_newline(b'\n'), true); -/// assert_eq!(is_newline(b'\r'), false); -/// assert_eq!(is_newline(b' '), false); -/// assert_eq!(is_newline(b'\t'), false); +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::digit1; +/// assert_eq!(digit1::<_, (_, ErrorKind)>("21c"), Ok(("c", "21"))); +/// assert_eq!(digit1::<_, (_, ErrorKind)>("c1"), Err(Err::Error(("c1", ErrorKind::Digit)))); +/// assert_eq!(digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn digit1>() -> impl Parser +where + T: Input, + ::Item: AsChar, +{ + Digit1 { e: PhantomData } +} + +/// Parser implementation for [digit1] +pub struct Digit1 { + e: PhantomData, +} + +impl> Parser for Digit1 +where + ::Item: AsChar, +{ + type Output = I; + + type Error = E; + + #[inline] + fn process( + &mut self, + input: I, + ) -> crate::PResult { + input.split_at_position_mode1::(|item| !item.is_dec_digit(), ErrorKind::Digit) + } +} + +/// Recognizes zero or more spaces, tabs, carriage returns and line feeds. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non space character). +/// # Example +/// /// ``` -#[inline] -pub fn is_newline(chr: u8) -> bool { - chr == b'\n' +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::multispace0; +/// assert_eq!(multispace0::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); +/// assert_eq!(multispace0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(multispace0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn multispace0>() -> impl Parser +where + T: Input, + ::Item: AsChar, +{ + MultiSpace0 { e: PhantomData } + /*input.split_at_position(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + })*/ +} + +/// Parser implementation for [multispace0()] +pub struct MultiSpace0 { + e: PhantomData, +} + +impl> Parser for MultiSpace0 +where + I: Input, + ::Item: AsChar, +{ + type Output = I; + type Error = Error; + + fn process( + &mut self, + i: I, + ) -> crate::PResult { + i.split_at_position_mode::(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/streaming.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,11 +7,12 @@ use crate::error::ErrorKind; use crate::error::ParseError; use crate::internal::{Err, IResult, Needed}; -use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; -use crate::traits::{ - AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice, -}; +use crate::traits::{AsChar, FindToken, Input}; use crate::traits::{Compare, CompareResult}; +use crate::Emit; +use crate::OutputM; +use crate::Parser; +use crate::Streaming; /// Recognizes one character. /// @@ -28,19 +29,13 @@ /// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` -pub fn char>(c: char) -> impl Fn(I) -> IResult +pub fn char>(c: char) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter + InputLength, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { - move |i: I| match (i).iter_elements().next().map(|t| { - let b = t.as_char() == c; - (&c, b) - }) { - None => Err(Err::Incomplete(Needed::new(c.len() - i.input_len()))), - Some((_, false)) => Err(Err::Error(Error::from_char(i, c))), - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - } + let mut parser = super::char(c); + move |i: I| parser.process::>(i) } /// Recognizes one character and checks that it satisfies a predicate @@ -58,21 +53,14 @@ /// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Unknown))); /// ``` -pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult +pub fn satisfy>(cond: F) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar, + I: Input, + ::Item: AsChar, F: Fn(char) -> bool, { - move |i: I| match (i).iter_elements().next().map(|t| { - let c = t.as_char(); - let b = cond(c); - (c, b) - }) { - None => Err(Err::Incomplete(Needed::Unknown)), - Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))), - Some((c, true)) => Ok((i.slice(c.len()..), c)), - } + let mut parser = super::satisfy(cond); + move |i: I| parser.process::>(i) } /// Recognizes one of the provided characters. @@ -85,19 +73,16 @@ /// # use nom::character::streaming::one_of; /// assert_eq!(one_of::<_, _, (_, ErrorKind)>("abc")("b"), Ok(("", 'b'))); /// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); -/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::Unknown))); /// ``` -pub fn one_of>(list: T) -> impl Fn(I) -> IResult +pub fn one_of>(list: T) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar + Copy, - T: FindToken<::Item>, + I: Input, + ::Item: AsChar, + T: FindToken, { - move |i: I| match (i).iter_elements().next().map(|c| (c, list.find_token(c))) { - None => Err(Err::Incomplete(Needed::new(1))), - Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::OneOf))), - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - } + let mut parser = super::one_of(list); + move |i: I| parser.process::>(i) } /// Recognizes a character that is not in the provided characters. @@ -110,19 +95,16 @@ /// # use nom::character::streaming::none_of; /// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z'))); /// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); -/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::Unknown))); /// ``` -pub fn none_of>(list: T) -> impl Fn(I) -> IResult +pub fn none_of>(list: T) -> impl FnMut(I) -> IResult where - I: Slice> + InputIter, - ::Item: AsChar + Copy, - T: FindToken<::Item>, + I: Input, + ::Item: AsChar, + T: FindToken, { - move |i: I| match (i).iter_elements().next().map(|c| (c, !list.find_token(c))) { - None => Err(Err::Incomplete(Needed::new(1))), - Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::NoneOf))), - Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), - } + let mut parser = super::none_of(list); + move |i: I| parser.process::>(i) } /// Recognizes the string "\r\n". @@ -139,13 +121,12 @@ /// ``` pub fn crlf>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, - T: InputIter, + T: Input, T: Compare<&'static str>, { match input.compare("\r\n") { //FIXME: is this the right index? - CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + CompareResult::Ok => Ok(input.take_split(2)), CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))), CompareResult::Error => { let e: ErrorKind = ErrorKind::CrLf; @@ -170,11 +151,9 @@ /// ``` pub fn not_line_ending>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, - T: InputIter + InputLength, + T: Input, T: Compare<&'static str>, - ::Item: AsChar, - ::Item: AsChar, + ::Item: AsChar, { match input.position(|item| { let c = item.as_char(); @@ -182,10 +161,10 @@ }) { None => Err(Err::Incomplete(Needed::Unknown)), Some(index) => { - let mut it = input.slice(index..).iter_elements(); + let mut it = input.take_from(index).iter_elements(); let nth = it.next().unwrap().as_char(); if nth == '\r' { - let sliced = input.slice(index..); + let sliced = input.take_from(index); let comp = sliced.compare("\r\n"); match comp { //FIXME: calculate the right index @@ -194,10 +173,10 @@ let e: ErrorKind = ErrorKind::Tag; Err(Err::Error(E::from_error_kind(input, e))) } - CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))), + CompareResult::Ok => Ok(input.take_split(index)), } } else { - Ok((input.slice(index..), input.slice(..index))) + Ok(input.take_split(index)) } } } @@ -217,17 +196,16 @@ /// ``` pub fn line_ending>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, - T: InputIter + InputLength, + T: Input, T: Compare<&'static str>, { match input.compare("\n") { - CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))), + CompareResult::Ok => Ok(input.take_split(1)), CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(1))), CompareResult::Error => { match input.compare("\r\n") { //FIXME: is this the right index? - CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + CompareResult::Ok => Ok(input.take_split(2)), CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))), CompareResult::Error => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), } @@ -249,8 +227,8 @@ /// ``` pub fn newline>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { char('\n')(input) } @@ -269,14 +247,13 @@ /// ``` pub fn tab>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, - ::Item: AsChar, + I: Input, + ::Item: AsChar, { char('\t')(input) } -/// Matches one byte as a character. Note that the input type will -/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. +/// Matches one element as a character. /// /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. /// # Example @@ -288,16 +265,13 @@ /// ``` pub fn anychar>(input: T) -> IResult where - T: InputIter + InputLength + Slice>, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { - let mut it = input.iter_indices(); + let mut it = input.iter_elements(); match it.next() { None => Err(Err::Incomplete(Needed::new(1))), - Some((_, c)) => match it.next() { - None => Ok((input.slice(input.input_len()..), c.as_char())), - Some((idx, _)) => Ok((input.slice(idx..), c.as_char())), - }, + Some(c) => Ok((input.take_from(c.len()), c.as_char())), } } @@ -316,8 +290,8 @@ /// ``` pub fn alpha0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| !item.is_alpha()) } @@ -337,8 +311,8 @@ /// ``` pub fn alpha1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1(|item| !item.is_alpha(), ErrorKind::Alpha) } @@ -358,8 +332,8 @@ /// ``` pub fn digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| !item.is_dec_digit()) } @@ -379,8 +353,8 @@ /// ``` pub fn digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1(|item| !item.is_dec_digit(), ErrorKind::Digit) } @@ -400,8 +374,8 @@ /// ``` pub fn hex_digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| !item.is_hex_digit()) } @@ -421,8 +395,8 @@ /// ``` pub fn hex_digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1(|item| !item.is_hex_digit(), ErrorKind::HexDigit) } @@ -442,8 +416,8 @@ /// ``` pub fn oct_digit0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| !item.is_oct_digit()) } @@ -463,12 +437,54 @@ /// ``` pub fn oct_digit1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1(|item| !item.is_oct_digit(), ErrorKind::OctDigit) } +/// Recognizes zero or more binary characters: 0-1 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non binary digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::bin_digit0; +/// assert_eq!(bin_digit0::<_, (_, ErrorKind)>("013a"), Ok(("3a", "01"))); +/// assert_eq!(bin_digit0::<_, (_, ErrorKind)>("a013"), Ok(("a013", ""))); +/// assert_eq!(bin_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn bin_digit0>(input: T) -> IResult +where + T: Input, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_bin_digit()) +} + +/// Recognizes one or more binary characters: 0-1 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non binary digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::bin_digit1; +/// assert_eq!(bin_digit1::<_, (_, ErrorKind)>("013a"), Ok(("3a", "01"))); +/// assert_eq!(bin_digit1::<_, (_, ErrorKind)>("a013"), Err(Err::Error(("a013", ErrorKind::BinDigit)))); +/// assert_eq!(bin_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn bin_digit1>(input: T) -> IResult +where + T: Input, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_bin_digit(), ErrorKind::BinDigit) +} + /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z /// /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, @@ -484,8 +500,8 @@ /// ``` pub fn alphanumeric0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| !item.is_alphanum()) } @@ -505,8 +521,8 @@ /// ``` pub fn alphanumeric1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, { input.split_at_position1(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric) } @@ -526,8 +542,8 @@ /// ``` pub fn space0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| { let c = item.as_char(); @@ -549,8 +565,8 @@ /// ``` pub fn space1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position1( |item| { @@ -576,8 +592,8 @@ /// ``` pub fn multispace0>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position(|item| { let c = item.as_char(); @@ -600,8 +616,8 @@ /// ``` pub fn multispace1>(input: T) -> IResult where - T: InputTakeAtPosition, - ::Item: AsChar + Clone, + T: Input, + ::Item: AsChar, { input.split_at_position1( |item| { @@ -614,7 +630,7 @@ pub(crate) fn sign>(input: T) -> IResult where - T: Clone + InputTake + InputLength, + T: Clone + Input, T: for<'a> Compare<&'a [u8]>, { use crate::bytes::streaming::tag; @@ -623,7 +639,8 @@ let (i, opt_sign) = opt(alt(( value(false, tag(&b"-"[..])), value(true, tag(&b"+"[..])), - )))(input)?; + ))) + .parse(input)?; let sign = opt_sign.unwrap_or(true); Ok((i, sign)) @@ -638,8 +655,8 @@ /// *Complete version*: can parse until the end of input. pub fn $t>(input: T) -> IResult where - T: InputIter + Slice> + InputLength + InputTake + Clone, - ::Item: AsChar, + T: Input + Clone, + ::Item: AsChar, T: for <'a> Compare<&'a[u8]>, { let (i, sign) = sign(input.clone())?; @@ -650,34 +667,42 @@ let mut value: $t = 0; if sign { - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } } else { - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) { None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } @@ -689,7 +714,7 @@ } } -ints! { i8 i16 i32 i64 i128 } +ints! { i8 i16 i32 i64 i128 isize } #[doc(hidden)] macro_rules! uints { @@ -700,8 +725,8 @@ /// *Complete version*: can parse until the end of input. pub fn $t>(input: T) -> IResult where - T: InputIter + Slice> + InputLength, - ::Item: AsChar, + T: Input , + ::Item: AsChar, { let i = input; @@ -710,18 +735,22 @@ } let mut value: $t = 0; - for (pos, c) in i.iter_indices() { + let mut pos = 0; + for c in i.iter_elements() { match c.as_char().to_digit(10) { None => { if pos == 0 { return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); } else { - return Ok((i.slice(pos..), value)); + return Ok((i.take_from(pos), value)); } }, Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))), - Some(v) => value = v, + Some(v) => { + pos += c.len(); + value = v; + }, } } } @@ -732,7 +761,7 @@ } } -uints! { u8 u16 u32 u64 u128 } +uints! { u8 u16 u32 u64 u128 usize } #[cfg(test)] mod tests { @@ -741,6 +770,7 @@ use crate::internal::{Err, Needed}; use crate::sequence::pair; use crate::traits::ParseTo; + use crate::Parser; use proptest::prelude::*; macro_rules! assert_parse( @@ -807,6 +837,17 @@ alphanumeric1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::new(1))) ); + assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); + assert_eq!( + bin_digit1::<_, (_, ErrorKind)>(b), + Ok((&b"234"[..], &b"1"[..])) + ); + assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); assert_eq!( alphanumeric1::<_, (_, ErrorKind)>(c), @@ -836,8 +877,8 @@ Err(Err::Incomplete(Needed::new(1))) ); assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); - assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..]))); - assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..]))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], "a"))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); assert_eq!( digit1::<_, (_, ErrorKind)>(b), @@ -857,7 +898,7 @@ hex_digit1::<_, (_, ErrorKind)>(c), Err(Err::Incomplete(Needed::new(1))) ); - assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..]))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", "a"))); assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); assert_eq!( @@ -866,6 +907,10 @@ ); assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1::<_, (_, ErrorKind)>(b), Ok(("234", "1"))); + assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); + assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); assert_eq!( alphanumeric1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::new(1))) @@ -934,6 +979,12 @@ } _ => panic!("wrong return type in offset test for oct_digit"), } + match bin_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for bin_digit"), + } } #[test] @@ -1009,18 +1060,18 @@ Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) ); - assert!(crate::character::is_hex_digit(b'0')); - assert!(crate::character::is_hex_digit(b'9')); - assert!(crate::character::is_hex_digit(b'a')); - assert!(crate::character::is_hex_digit(b'f')); - assert!(crate::character::is_hex_digit(b'A')); - assert!(crate::character::is_hex_digit(b'F')); - assert!(!crate::character::is_hex_digit(b'g')); - assert!(!crate::character::is_hex_digit(b'G')); - assert!(!crate::character::is_hex_digit(b'/')); - assert!(!crate::character::is_hex_digit(b':')); - assert!(!crate::character::is_hex_digit(b'@')); - assert!(!crate::character::is_hex_digit(b'\x60')); + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } #[test] @@ -1034,22 +1085,45 @@ Err(Err::Error(error_position!(i, ErrorKind::OctDigit))) ); - assert!(crate::character::is_oct_digit(b'0')); - assert!(crate::character::is_oct_digit(b'7')); - assert!(!crate::character::is_oct_digit(b'8')); - assert!(!crate::character::is_oct_digit(b'9')); - assert!(!crate::character::is_oct_digit(b'a')); - assert!(!crate::character::is_oct_digit(b'A')); - assert!(!crate::character::is_oct_digit(b'/')); - assert!(!crate::character::is_oct_digit(b':')); - assert!(!crate::character::is_oct_digit(b'@')); - assert!(!crate::character::is_oct_digit(b'\x60')); + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); + } + + #[test] + fn bin_digit_test() { + let i = &b"01;"[..]; + assert_parse!(bin_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + bin_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::BinDigit))) + ); + + assert!(crate::character::is_bin_digit(b'0')); + assert!(crate::character::is_bin_digit(b'1')); + assert!(!crate::character::is_bin_digit(b'8')); + assert!(!crate::character::is_bin_digit(b'9')); + assert!(!crate::character::is_bin_digit(b'a')); + assert!(!crate::character::is_bin_digit(b'A')); + assert!(!crate::character::is_bin_digit(b'/')); + assert!(!crate::character::is_bin_digit(b':')); + assert!(!crate::character::is_bin_digit(b'@')); + assert!(!crate::character::is_bin_digit(b'\x60')); } #[test] fn full_line_windows() { fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + pair(not_line_ending, line_ending).parse(i) } let input = b"abc\r\n"; let output = take_full_line(input); @@ -1059,7 +1133,7 @@ #[test] fn full_line_unix() { fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + pair(not_line_ending, line_ending).parse(i) } let input = b"abc\n"; let output = take_full_line(input); @@ -1121,7 +1195,7 @@ fn digit_to_i16(input: &str) -> IResult<&str, i16> { let i = input; - let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let (i, opt_sign) = opt(alt((char('+'), char('-')))).parse(i)?; let sign = match opt_sign { Some('+') => true, Some('-') => false, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/character/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/character/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -54,9 +54,9 @@ char('c')(i) } - let a = &"abcd"[..]; + let a = "abcd"; assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char)))); - let b = &"cde"[..]; - assert_eq!(f(b), Ok((&"de"[..], 'c'))); + let b = "cde"; + assert_eq!(f(b), Ok(("de", 'c'))); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/combinator/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/combinator/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,6 +2,8 @@ #![allow(unused_imports)] +use core::marker::PhantomData; + #[cfg(feature = "alloc")] use crate::lib::std::boxed::Box; @@ -13,8 +15,8 @@ use crate::lib::std::fmt::Debug; use crate::lib::std::mem::transmute; use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; -use crate::traits::{AsChar, InputIter, InputLength, InputTakeAtPosition, ParseTo}; -use crate::traits::{Compare, CompareResult, Offset, Slice}; +use crate::traits::{AsChar, Input, ParseTo}; +use crate::traits::{Compare, CompareResult, Offset}; #[cfg(test)] mod tests; @@ -30,10 +32,9 @@ #[inline] pub fn rest>(input: T) -> IResult where - T: Slice>, - T: InputLength, + T: Input, { - Ok((input.slice(input.input_len()..), input)) + Ok(input.take_split(input.input_len())) } /// Return the length of the remaining input. @@ -47,7 +48,7 @@ #[inline] pub fn rest_len>(input: T) -> IResult where - T: InputLength, + T: Input, { let len = input.input_len(); Ok((input, len)) @@ -56,7 +57,7 @@ /// Maps a function on the result of a parser. /// /// ```rust -/// use nom::{Err,error::ErrorKind, IResult,Parser}; +/// use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::character::complete::digit1; /// use nom::combinator::map; /// # fn main() { @@ -70,21 +71,18 @@ /// assert_eq!(parser.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); /// # } /// ``` -pub fn map(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult +pub fn map, F, G>(parser: F, f: G) -> impl Parser where - F: Parser, - G: FnMut(O1) -> O2, + F: Parser, + G: FnMut(>::Output) -> O, { - move |input: I| { - let (input, o1) = parser.parse(input)?; - Ok((input, f(o1))) - } + parser.map(f) } /// Applies a function returning a `Result` over the result of a parser. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::character::complete::digit1; /// use nom::combinator::map_res; /// # fn main() { @@ -92,37 +90,30 @@ /// let mut parse = map_res(digit1, |s: &str| s.parse::()); /// /// // the parser will convert the result of digit1 to a number -/// assert_eq!(parse("123"), Ok(("", 123))); +/// assert_eq!(parse.parse("123"), Ok(("", 123))); /// /// // this will fail if digit1 fails -/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); +/// assert_eq!(parse.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); /// /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) -/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes)))); +/// assert_eq!(parse.parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes)))); /// # } /// ``` -pub fn map_res, E2, F, G>( - mut parser: F, - mut f: G, -) -> impl FnMut(I) -> IResult +pub fn map_res + FromExternalError, E2, F, G>( + parser: F, + f: G, +) -> impl Parser where - F: Parser, - G: FnMut(O1) -> Result, + F: Parser, + G: FnMut(>::Output) -> Result, { - move |input: I| { - let i = input.clone(); - let (input, o1) = parser.parse(input)?; - match f(o1) { - Ok(o2) => Ok((input, o2)), - Err(e) => Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, e))), - } - } + parser.map_res(f) } /// Applies a function returning an `Option` over the result of a parser. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::character::complete::digit1; /// use nom::combinator::map_opt; /// # fn main() { @@ -130,37 +121,30 @@ /// let mut parse = map_opt(digit1, |s: &str| s.parse::().ok()); /// /// // the parser will convert the result of digit1 to a number -/// assert_eq!(parse("123"), Ok(("", 123))); +/// assert_eq!(parse.parse("123"), Ok(("", 123))); /// /// // this will fail if digit1 fails -/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); +/// assert_eq!(parse.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); /// /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) -/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt)))); +/// assert_eq!(parse.parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt)))); /// # } /// ``` -pub fn map_opt, F, G>( - mut parser: F, - mut f: G, -) -> impl FnMut(I) -> IResult +pub fn map_opt, F, G>( + parser: F, + f: G, +) -> impl Parser where - F: Parser, - G: FnMut(O1) -> Option, + F: Parser, + G: FnMut(>::Output) -> Option, { - move |input: I| { - let i = input.clone(); - let (input, o1) = parser.parse(input)?; - match f(o1) { - Some(o2) => Ok((input, o2)), - None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))), - } - } + parser.map_opt(f) } /// Applies a parser over the result of another one. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::character::complete::digit1; /// use nom::bytes::complete::take; /// use nom::combinator::map_parser; @@ -168,30 +152,26 @@ /// /// let mut parse = map_parser(take(5u8), digit1); /// -/// assert_eq!(parse("12345"), Ok(("", "12345"))); -/// assert_eq!(parse("123ab"), Ok(("", "123"))); -/// assert_eq!(parse("123"), Err(Err::Error(("123", ErrorKind::Eof)))); -/// # } -/// ``` -pub fn map_parser, F, G>( - mut parser: F, - mut applied_parser: G, -) -> impl FnMut(I) -> IResult -where - F: Parser, - G: Parser, -{ - move |input: I| { - let (input, o1) = parser.parse(input)?; - let (_, o2) = applied_parser.parse(o1)?; - Ok((input, o2)) - } +/// assert_eq!(parse.parse("12345"), Ok(("", "12345"))); +/// assert_eq!(parse.parse("123ab"), Ok(("", "123"))); +/// assert_eq!(parse.parse("123"), Err(Err::Error(("123", ErrorKind::Eof)))); +/// # } +/// ``` +pub fn map_parser, F, G>( + parser: F, + applied_parser: G, +) -> impl Parser +where + F: Parser, + G: Parser<>::Output, Output = O, Error = E>, +{ + parser.and_then(applied_parser) } /// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::bytes::complete::take; /// use nom::number::complete::u8; /// use nom::combinator::flat_map; @@ -199,23 +179,20 @@ /// /// let mut parse = flat_map(u8, take); /// -/// assert_eq!(parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..]))); -/// assert_eq!(parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof)))); +/// assert_eq!(parse.parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..]))); +/// assert_eq!(parse.parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof)))); /// # } /// ``` -pub fn flat_map, F, G, H>( - mut parser: F, - mut applied_parser: G, -) -> impl FnMut(I) -> IResult -where - F: Parser, - G: FnMut(O1) -> H, - H: Parser, -{ - move |input: I| { - let (input, o1) = parser.parse(input)?; - applied_parser(o1).parse(input) - } +pub fn flat_map, F, G, H>( + parser: F, + applied_parser: G, +) -> impl Parser +where + F: Parser, + G: FnMut(>::Output) -> H, + H: Parser, +{ + parser.flat_map(applied_parser) } /// Optional parser, will return `None` on [`Err::Error`]. @@ -223,29 +200,52 @@ /// To chain an error up, see [`cut`]. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::opt; /// use nom::character::complete::alpha1; /// # fn main() { /// /// fn parser(i: &str) -> IResult<&str, Option<&str>> { -/// opt(alpha1)(i) +/// opt(alpha1).parse(i) /// } /// /// assert_eq!(parser("abcd;"), Ok((";", Some("abcd")))); /// assert_eq!(parser("123;"), Ok(("123;", None))); /// # } /// ``` -pub fn opt, F>(mut f: F) -> impl FnMut(I) -> IResult, E> +pub fn opt, F>( + f: F, +) -> impl Parser>::Output>, Error = E> where - F: Parser, + F: Parser, { - move |input: I| { + Opt { parser: f } +} + +/// Parser implementation for [opt] +pub struct Opt { + parser: F, +} + +impl> Parser for Opt +where + I: Clone, +{ + type Output = Option<>::Output>; + + type Error = >::Error; + + #[inline(always)] + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match f.parse(input) { - Ok((i, o)) => Ok((i, Some(o))), - Err(Err::Error(_)) => Ok((i, None)), - Err(e) => Err(e), + match self + .parser + .process::>(input) + { + Ok((i, o)) => Ok((i, OM::Output::map(o, Some))), + Err(Err::Error(_)) => Ok((i, OM::Output::bind(|| None))), + Err(Err::Failure(e)) => Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), } } } @@ -253,13 +253,13 @@ /// Calls the parser if the condition is met. /// /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Parser}; /// use nom::combinator::cond; /// use nom::character::complete::alpha1; /// # fn main() { /// /// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> { -/// cond(b, alpha1)(i) +/// cond(b, alpha1).parse(i) /// } /// /// assert_eq!(parser(true, "abcd;"), Ok((";", Some("abcd")))); @@ -268,21 +268,36 @@ /// assert_eq!(parser(false, "123;"), Ok(("123;", None))); /// # } /// ``` -pub fn cond, F>( +pub fn cond, F>( b: bool, - mut f: F, -) -> impl FnMut(I) -> IResult, E> + f: F, +) -> impl Parser>::Output>, Error = E> where - F: Parser, + F: Parser, { - move |input: I| { - if b { - match f.parse(input) { - Ok((i, o)) => Ok((i, Some(o))), - Err(e) => Err(e), - } - } else { - Ok((input, None)) + Cond { + parser: if b { Some(f) } else { None }, + } +} + +/// Parser implementation for [cond] +pub struct Cond { + parser: Option, +} + +impl Parser for Cond +where + F: Parser, +{ + type Output = Option<>::Output>; + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { + match &mut self.parser { + None => Ok((input, OM::Output::bind(|| None))), + Some(f) => f + .process::(input) + .map(|(i, o)| (i, OM::Output::map(o, Some))), } } } @@ -290,24 +305,42 @@ /// Tries to apply its parser without consuming the input. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::peek; /// use nom::character::complete::alpha1; /// # fn main() { /// /// let mut parser = peek(alpha1); /// -/// assert_eq!(parser("abcd;"), Ok(("abcd;", "abcd"))); -/// assert_eq!(parser("123;"), Err(Err::Error(("123;", ErrorKind::Alpha)))); +/// assert_eq!(parser.parse("abcd;"), Ok(("abcd;", "abcd"))); +/// assert_eq!(parser.parse("123;"), Err(Err::Error(("123;", ErrorKind::Alpha)))); /// # } /// ``` -pub fn peek, F>(mut f: F) -> impl FnMut(I) -> IResult +pub fn peek( + parser: F, +) -> impl Parser>::Output, Error = >::Error> +where + F: Parser, +{ + Peek { parser } +} + +/// Parsr implementation for [peek] +pub struct Peek { + parser: F, +} + +impl Parser for Peek where - F: Parser, + I: Clone, + F: Parser, { - move |input: I| { + type Output = >::Output; + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match f.parse(input) { + match self.parser.process::(input) { Ok((_, o)) => Ok((i, o)), Err(e) => Err(e), } @@ -330,7 +363,7 @@ /// assert_eq!(parser(""), Ok(("", ""))); /// # } /// ``` -pub fn eof>(input: I) -> IResult { +pub fn eof>(input: I) -> IResult { if input.input_len() == 0 { let clone = input.clone(); Ok((input, clone)) @@ -342,26 +375,51 @@ /// Transforms Incomplete into `Error`. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::bytes::streaming::take; /// use nom::combinator::complete; /// # fn main() { /// /// let mut parser = complete(take(5u8)); /// -/// assert_eq!(parser("abcdefg"), Ok(("fg", "abcde"))); -/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Complete)))); +/// assert_eq!(parser.parse("abcdefg"), Ok(("fg", "abcde"))); +/// assert_eq!(parser.parse("abcd"), Err(Err::Error(("abcd", ErrorKind::Complete)))); /// # } /// ``` -pub fn complete, F>(mut f: F) -> impl FnMut(I) -> IResult +pub fn complete, F>( + parser: F, +) -> impl Parser +where + F: Parser, +{ + MakeComplete { parser } +} + +/// Parser implementation for [complete] +pub struct MakeComplete { + parser: F, +} + +impl Parser for MakeComplete where - F: Parser, + I: Clone, + F: Parser, { - move |input: I| { + type Output = >::Output; + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match f.parse(input) { - Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))), - rest => rest, + + match self + .parser + .process::>(input) + { + Err(Err::Incomplete(_)) => Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::Complete) + }))), + Err(e) => Err(e), + Ok(o) => Ok(o), } } } @@ -369,29 +427,49 @@ /// Succeeds if all the input has been consumed by its child parser. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::all_consuming; /// use nom::character::complete::alpha1; /// # fn main() { /// /// let mut parser = all_consuming(alpha1); /// -/// assert_eq!(parser("abcd"), Ok(("", "abcd"))); -/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Eof)))); -/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// assert_eq!(parser.parse("abcd"), Ok(("", "abcd"))); +/// assert_eq!(parser.parse("abcd;"),Err(Err::Error((";", ErrorKind::Eof)))); +/// assert_eq!(parser.parse("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); /// # } /// ``` -pub fn all_consuming, F>(mut f: F) -> impl FnMut(I) -> IResult +pub fn all_consuming, F>( + parser: F, +) -> impl Parser>::Output, Error = E> where - I: InputLength, - F: Parser, + I: Input, + F: Parser, { - move |input: I| { - let (input, res) = f.parse(input)?; + AllConsuming { parser } +} + +/// Parser implementation for [all_consuming] +pub struct AllConsuming { + parser: F, +} + +impl Parser for AllConsuming +where + I: Input, + F: Parser, +{ + type Output = >::Output; + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { + let (input, res) = self.parser.process::(input)?; if input.input_len() == 0 { Ok((input, res)) } else { - Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))) + Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Eof) + }))) } } } @@ -402,36 +480,65 @@ /// parser. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::verify; /// use nom::character::complete::alpha1; /// # fn main() { /// /// let mut parser = verify(alpha1, |s: &str| s.len() == 4); /// -/// assert_eq!(parser("abcd"), Ok(("", "abcd"))); -/// assert_eq!(parser("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify)))); -/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// assert_eq!(parser.parse("abcd"), Ok(("", "abcd"))); +/// assert_eq!(parser.parse("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify)))); +/// assert_eq!(parser.parse("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); /// # } /// ``` -pub fn verify, F, G>( - mut first: F, +pub fn verify, F, G>( + first: F, second: G, -) -> impl FnMut(I) -> IResult +) -> impl Parser>::Output, Error = E> where - F: Parser, + F: Parser, G: Fn(&O2) -> bool, - O1: Borrow, + >::Output: Borrow, O2: ?Sized, { - move |input: I| { - let i = input.clone(); - let (input, o) = first.parse(input)?; + Verify { + first, + second, + o2: PhantomData, + } +} + +/// Parser iplementation for verify +pub struct Verify { + first: F, + second: G, + o2: PhantomData, +} + +impl, G, O2> Parser for Verify +where + I: Clone, + G: Fn(&O2) -> bool, + >::Output: Borrow, + O2: ?Sized, +{ + type Output = >::Output; + + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { + let (i, o) = self + .first + .process::>(input.clone())?; - if second(o.borrow()) { - Ok((input, o)) + if (self.second)(o.borrow()) { + Ok((i, OM::Output::bind(|| o))) } else { - Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify))) + Err(Err::Error(OM::Error::bind(move || { + let e: ErrorKind = ErrorKind::Verify; + >::Error::from_error_kind(input, e) + }))) } } } @@ -439,50 +546,68 @@ /// Returns the provided value if the child parser succeeds. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::value; /// use nom::character::complete::alpha1; /// # fn main() { /// /// let mut parser = value(1234, alpha1); /// -/// assert_eq!(parser("abcd"), Ok(("", 1234))); -/// assert_eq!(parser("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// assert_eq!(parser.parse("abcd"), Ok(("", 1234))); +/// assert_eq!(parser.parse("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); /// # } /// ``` -pub fn value, F>( +pub fn value, F>( val: O1, - mut parser: F, -) -> impl FnMut(I) -> IResult + parser: F, +) -> impl Parser where - F: Parser, + F: Parser, { - move |input: I| parser.parse(input).map(|(i, _)| (i, val.clone())) + parser.map(move |_| val.clone()) } /// Succeeds if the child parser returns an error. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::not; /// use nom::character::complete::alpha1; /// # fn main() { /// /// let mut parser = not(alpha1); /// -/// assert_eq!(parser("123"), Ok(("123", ()))); -/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Not)))); +/// assert_eq!(parser.parse("123"), Ok(("123", ()))); +/// assert_eq!(parser.parse("abcd"), Err(Err::Error(("abcd", ErrorKind::Not)))); /// # } /// ``` -pub fn not, F>(mut parser: F) -> impl FnMut(I) -> IResult +pub fn not, F>(parser: F) -> impl Parser where - F: Parser, + F: Parser, { - move |input: I| { + Not { parser } +} + +/// Parser implementation for [not] +pub struct Not { + parser: F, +} + +impl Parser for Not +where + I: Clone, + F: Parser, +{ + type Output = (); + type Error = >::Error; + + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match parser.parse(input) { - Ok(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Not))), - Err(Err::Error(_)) => Ok((i, ())), + match self.parser.process::(input) { + Ok(_) => Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::Not) + }))), + Err(Err::Error(_)) => Ok((i, OM::Output::bind(|| ()))), Err(e) => Err(e), } } @@ -491,7 +616,7 @@ /// If the child parser was successful, return the consumed input as produced value. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::recognize; /// use nom::character::complete::{char, alpha1}; /// use nom::sequence::separated_pair; @@ -499,22 +624,42 @@ /// /// let mut parser = recognize(separated_pair(alpha1, char(','), alpha1)); /// -/// assert_eq!(parser("abcd,efgh"), Ok(("", "abcd,efgh"))); -/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); +/// assert_eq!(parser.parse("abcd,efgh"), Ok(("", "abcd,efgh"))); +/// assert_eq!(parser.parse("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); /// # } /// ``` -pub fn recognize>, O, E: ParseError, F>( - mut parser: F, -) -> impl FnMut(I) -> IResult +pub fn recognize, F>( + parser: F, +) -> impl Parser where - F: Parser, + F: Parser, { - move |input: I| { + Recognize { parser } +} + +/// Parser implementation for [recognize] +pub struct Recognize { + parser: F, +} + +impl Parser for Recognize +where + I: Clone + Offset + Input, + F: Parser, +{ + type Output = I; + type Error = >::Error; + + #[inline(always)] + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match parser.parse(i) { + match self + .parser + .process::>(i) + { Ok((i, _)) => { let index = input.offset(&i); - Ok((i, input.slice(..index))) + Ok((i, OM::Output::bind(|| input.take(index)))) } Err(e) => Err(e), } @@ -531,22 +676,22 @@ /// Returned tuple is of the format `(consumed input, produced output)`. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::combinator::{consumed, value, recognize, map}; /// use nom::character::complete::{char, alpha1}; /// use nom::bytes::complete::tag; /// use nom::sequence::separated_pair; /// /// fn inner_parser(input: &str) -> IResult<&str, bool> { -/// value(true, tag("1234"))(input) +/// value(true, tag("1234")).parse(input) /// } /// /// # fn main() { /// /// let mut consumed_parser = consumed(value(true, separated_pair(alpha1, char(','), alpha1))); /// -/// assert_eq!(consumed_parser("abcd,efgh1"), Ok(("1", ("abcd,efgh", true)))); -/// assert_eq!(consumed_parser("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); +/// assert_eq!(consumed_parser.parse("abcd,efgh1"), Ok(("1", ("abcd,efgh", true)))); +/// assert_eq!(consumed_parser.parse("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); /// /// /// // the first output (representing the consumed input) @@ -554,23 +699,48 @@ /// let mut recognize_parser = recognize(inner_parser); /// let mut consumed_parser = map(consumed(inner_parser), |(consumed, output)| consumed); /// -/// assert_eq!(recognize_parser("1234"), consumed_parser("1234")); -/// assert_eq!(recognize_parser("abcd"), consumed_parser("abcd")); +/// assert_eq!(recognize_parser.parse("1234"), consumed_parser.parse("1234")); +/// assert_eq!(recognize_parser.parse("abcd"), consumed_parser.parse("abcd")); /// # } /// ``` -pub fn consumed(mut parser: F) -> impl FnMut(I) -> IResult +pub fn consumed( + parser: F, +) -> impl Parser>::Output), Error = E> where - I: Clone + Offset + Slice>, + I: Clone + Offset + Input, E: ParseError, - F: Parser, + F: Parser, { - move |input: I| { + Consumed { parser } +} + +/// Parser implementation for [consumed] +pub struct Consumed { + parser: F, +} + +impl Parser for Consumed +where + I: Clone + Offset + Input, + F: Parser, +{ + type Output = (I, >::Output); + type Error = >::Error; + + #[inline(always)] + fn process(&mut self, input: I) -> PResult { let i = input.clone(); - match parser.parse(i) { + match self.parser.process::(i) { Ok((remaining, result)) => { let index = input.offset(&remaining); - let consumed = input.slice(..index); - Ok((remaining, (consumed, result))) + + Ok(( + remaining, + OM::Output::map(result, |res| { + let consumed = input.take(index); + (consumed, res) + }), + )) } Err(e) => Err(e), } @@ -586,7 +756,7 @@ /// /// Without `cut`: /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// # use nom::character::complete::{one_of, digit1}; /// # use nom::combinator::rest; /// # use nom::branch::alt; @@ -597,7 +767,7 @@ /// alt(( /// preceded(one_of("+-"), digit1), /// rest -/// ))(input) +/// )).parse(input) /// } /// /// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); @@ -608,7 +778,7 @@ /// /// With `cut`: /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult, error::Error}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser, error::Error}; /// # use nom::character::complete::{one_of, digit1}; /// # use nom::combinator::rest; /// # use nom::branch::alt; @@ -620,7 +790,7 @@ /// alt(( /// preceded(one_of("+-"), cut(digit1)), /// rest -/// ))(input) +/// )).parse(input) /// } /// /// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); @@ -628,13 +798,39 @@ /// assert_eq!(parser("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit }))); /// # } /// ``` -pub fn cut, F>(mut parser: F) -> impl FnMut(I) -> IResult +pub fn cut, F>( + parser: F, +) -> impl Parser>::Output, Error = E> +where + F: Parser, +{ + Cut { parser } +} + +/// Parser implementation for [cut] +pub struct Cut { + parser: F, +} + +impl Parser for Cut where - F: Parser, + F: Parser, { - move |input: I| match parser.parse(input) { - Err(Err::Error(e)) => Err(Err::Failure(e)), - rest => rest, + type Output = >::Output; + + type Error = >::Error; + + #[inline(always)] + fn process(&mut self, input: I) -> PResult { + match self + .parser + .process::>(input) + { + Err(Err::Error(e)) => Err(Err::Failure(e)), + Err(Err::Failure(e)) => Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), + Ok((i, o)) => Ok((i, o)), + } } } @@ -644,37 +840,31 @@ /// as long as the `Into` implementations are available /// /// ```rust -/// # use nom::IResult; +/// # use nom::{IResult, Parser}; /// use nom::combinator::into; /// use nom::character::complete::alpha1; /// # fn main() { /// -/// fn parser1(i: &str) -> IResult<&str, &str> { -/// alpha1(i) -/// } +/// fn parser1(i: &str) -> IResult<&str, &str> { +/// alpha1(i) +/// } /// -/// let mut parser2 = into(parser1); +/// let mut parser2 = into(parser1); /// /// // the parser converts the &str output of the child parser into a Vec -/// let bytes: IResult<&str, Vec> = parser2("abcd"); +/// let bytes: IResult<&str, Vec> = parser2.parse("abcd"); /// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100]))); /// # } /// ``` -pub fn into(mut parser: F) -> impl FnMut(I) -> IResult +pub fn into(parser: F) -> impl Parser where - O1: Into, - E1: Into, + O2: From, + E2: From, E1: ParseError, E2: ParseError, - F: Parser, + F: Parser, { - //map(parser, Into::into) - move |input: I| match parser.parse(input) { - Ok((i, o)) => Ok((i, o.into())), - Err(Err::Error(e)) => Err(Err::Error(e.into())), - Err(Err::Failure(e)) => Err(Err::Failure(e.into())), - Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)), - } + parser.into::() } /// Creates an iterator from input data and a parser. @@ -691,15 +881,15 @@ /// let data = "abc|defg|hijkl|mnopqr|123"; /// let mut it = iterator(data, terminated(alpha1, tag("|"))); /// -/// let parsed = it.map(|v| (v, v.len())).collect::>(); +/// let parsed = it.by_ref().map(|v| (v, v.len())).collect::>(); /// let res: IResult<_,_> = it.finish(); /// /// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect()); /// assert_eq!(res, Ok(("123", ()))); /// ``` -pub fn iterator(input: Input, f: F) -> ParserIterator +pub fn iterator(input: Input, f: F) -> ParserIterator where - F: Parser, + F: Parser, Error: ParseError, { ParserIterator { @@ -727,9 +917,9 @@ } } -impl<'a, Input, Output, Error, F> core::iter::Iterator for &'a mut ParserIterator +impl core::iter::Iterator for ParserIterator where - F: FnMut(Input) -> IResult, + F: Parser, Input: Clone, { type Item = Output; @@ -738,7 +928,7 @@ if let State::Running = self.state.take().unwrap() { let input = self.input.clone(); - match (self.iterator)(input) { + match (self.iterator).parse(input) { Ok((i, o)) => { self.input = i; self.state = Some(State::Running); @@ -776,34 +966,79 @@ /// specify the default case. /// /// ```rust -/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::{Err,error::ErrorKind, IResult, Parser}; /// use nom::branch::alt; /// use nom::combinator::{success, value}; /// use nom::character::complete::char; /// # fn main() { /// /// let mut parser = success::<_,_,(_,ErrorKind)>(10); -/// assert_eq!(parser("xyz"), Ok(("xyz", 10))); +/// assert_eq!(parser.parse("xyz"), Ok(("xyz", 10))); /// /// let mut sign = alt((value(-1, char('-')), value(1, char('+')), success::<_,_,(_,ErrorKind)>(1))); -/// assert_eq!(sign("+10"), Ok(("10", 1))); -/// assert_eq!(sign("-10"), Ok(("10", -1))); -/// assert_eq!(sign("10"), Ok(("10", 1))); +/// assert_eq!(sign.parse("+10"), Ok(("10", 1))); +/// assert_eq!(sign.parse("-10"), Ok(("10", -1))); +/// assert_eq!(sign.parse("10"), Ok(("10", 1))); /// # } /// ``` -pub fn success>(val: O) -> impl Fn(I) -> IResult { - move |input: I| Ok((input, val.clone())) +pub fn success>(val: O) -> impl Parser { + Success { + val, + e: PhantomData, + } +} + +/// Parser implementation for [success] +pub struct Success { + val: O, + e: PhantomData, +} + +impl Parser for Success +where + O: Clone, + E: ParseError, +{ + type Output = O; + type Error = E; + + fn process(&mut self, input: I) -> PResult { + Ok((input, OM::Output::bind(|| self.val.clone()))) + } } /// A parser which always fails. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, IResult}; +/// # use nom::{Err, error::ErrorKind, IResult, Parser}; /// use nom::combinator::fail; /// /// let s = "string"; -/// assert_eq!(fail::<_, &str, _>(s), Err(Err::Error((s, ErrorKind::Fail)))); +/// assert_eq!(fail::<_, &str, _>().parse(s), Err(Err::Error((s, ErrorKind::Fail)))); /// ``` -pub fn fail>(i: I) -> IResult { - Err(Err::Error(E::from_error_kind(i, ErrorKind::Fail))) +pub fn fail>() -> impl Parser { + Fail { + o: PhantomData, + e: PhantomData, + } +} + +/// Parser implementation for [fail] +pub struct Fail { + o: PhantomData, + e: PhantomData, +} + +impl Parser for Fail +where + E: ParseError, +{ + type Output = O; + type Error = E; + + fn process(&mut self, input: I) -> PResult { + Err(Err::Error(OM::Error::bind(|| { + E::from_error_kind(input, ErrorKind::Fail) + }))) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/combinator/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/combinator/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/combinator/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -117,7 +117,7 @@ fn test_flat_map() { let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; assert_parse!( - flat_map(u8, take)(input), + flat_map(u8, take).parse(input), Ok((&[103, 104][..], &[100, 101, 102][..])) ); } @@ -126,11 +126,11 @@ fn test_map_opt() { let input: &[u8] = &[50][..]; assert_parse!( - map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input), + map_opt(u8, |u| if u < 20 { Some(u) } else { None }).parse(input), Err(Err::Error((&[50][..], ErrorKind::MapOpt))) ); assert_parse!( - map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input), + map_opt(u8, |u| if u > 20 { Some(u) } else { None }).parse(input), Ok((&[][..], 50)) ); } @@ -139,7 +139,7 @@ fn test_map_parser() { let input: &[u8] = &[100, 101, 102, 103, 104][..]; assert_parse!( - map_parser(take(4usize), take(2usize))(input), + map_parser(take(4usize), take(2usize)).parse(input), Ok((&[104][..], &[100, 101][..])) ); } @@ -148,11 +148,11 @@ fn test_all_consuming() { let input: &[u8] = &[100, 101, 102][..]; assert_parse!( - all_consuming(take(2usize))(input), + all_consuming(take(2usize)).parse(input), Err(Err::Error((&[102][..], ErrorKind::Eof))) ); assert_parse!( - all_consuming(take(3usize))(input), + all_consuming(take(3usize)).parse(input), Ok((&[][..], &[100, 101, 102][..])) ); } @@ -164,14 +164,14 @@ let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]); - assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..]))); + assert_eq!(parser1.parse(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..]))); assert_eq!( - parser1(&b"defg"[..]), + parser1.parse(&b"defg"[..]), Err(Err::Error((&b"defg"[..], ErrorKind::Verify))) ); fn parser2(i: &[u8]) -> IResult<&[u8], u32> { - verify(crate::number::streaming::be_u32, |val: &u32| *val < 3)(i) + verify(crate::number::streaming::be_u32, |val: &u32| *val < 3).parse(i) } } @@ -183,9 +183,12 @@ s == &b"abc"[..] }); - assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], (&b"abc").to_vec()))); assert_eq!( - parser1(&b"defg"[..]), + parser1.parse(&b"abcd"[..]), + Ok((&b"d"[..], b"abc".to_vec())) + ); + assert_eq!( + parser1.parse(&b"defg"[..]), Err(Err::Error((&b"defg"[..], ErrorKind::Verify))) ); } @@ -200,7 +203,7 @@ }; let mut parser = into(take::<_, _, Error<_>>(3u8)); - let result: IResult<&[u8], Vec> = parser(&b"abcdefg"[..]); + let result: IResult<&[u8], Vec> = parser.parse(&b"abcdefg"[..]); assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); } @@ -208,7 +211,7 @@ #[test] fn opt_test() { fn opt_abcd(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> { - opt(tag("abcd"))(i) + opt(tag("abcd")).parse(i) } let a = &b"abcdef"[..]; @@ -222,7 +225,7 @@ #[test] fn peek_test() { fn peek_tag(i: &[u8]) -> IResult<&[u8], &[u8]> { - peek(tag("abcd"))(i) + peek(tag("abcd")).parse(i) } assert_eq!(peek_tag(&b"abcdef"[..]), Ok((&b"abcdef"[..], &b"abcd"[..]))); @@ -236,7 +239,7 @@ #[test] fn not_test() { fn not_aaa(i: &[u8]) -> IResult<&[u8], ()> { - not(tag("aaa"))(i) + not(tag("aaa")).parse(i) } assert_eq!( @@ -252,7 +255,7 @@ use crate::bytes::streaming::take; fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { - verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i) + verify(take(5u8), |slice: &[u8]| slice[0] == b'a').parse(i) } assert_eq!(test(&b"bcd"[..]), Err(Err::Incomplete(Needed::new(2)))); assert_eq!( @@ -270,6 +273,12 @@ let a = "string"; let b = "another string"; - assert_eq!(fail::<_, &str, _>(a), Err(Err::Error((a, ErrorKind::Fail)))); - assert_eq!(fail::<_, &str, _>(b), Err(Err::Error((b, ErrorKind::Fail)))); + assert_eq!( + fail::<_, &str, _>().parse(a), + Err(Err::Error((a, ErrorKind::Fail))) + ); + assert_eq!( + fail::<_, &str, _>().parse(b), + Err(Err::Error((b, ErrorKind::Fail))) + ); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,13 +3,19 @@ //! Parsers are generic over their error type, requiring that it implements //! the `error::ParseError` trait. -use crate::internal::Parser; +use crate::internal::{Err, Mode, OutputMode, PResult, Parser}; use crate::lib::std::fmt; +#[cfg(feature = "alloc")] +use crate::alloc::borrow::ToOwned; + +#[cfg(feature = "std")] +use crate::internal::IResult; + /// This trait must be implemented by the error type of a nom parser. /// /// There are already implementations of it for `(Input, ErrorKind)` -/// and `VerboseError`. +/// and `Error`. /// /// It provides methods to create an error from some combinators, /// and combine existing errors in combinators like `alt`. @@ -53,8 +59,8 @@ fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self; } -/// default error type, only contains the error' location and code -#[derive(Debug, PartialEq)] +/// default error type, only contains the error's location and code +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Error { /// position of the error in the input data pub input: I, @@ -95,9 +101,73 @@ } } +#[cfg(feature = "alloc")] +impl Error<&I> { + /// Converts `Error<&I>` into `Error` by cloning. + pub fn cloned(self) -> Error { + Error { + input: self.input.to_owned(), + code: self.code, + } + } +} + +#[cfg(feature = "alloc")] +impl Error<&mut I> { + /// Converts `Error<&mut I>` into `Error` by cloning. + pub fn cloned(self) -> Error { + Error { + input: self.input.to_owned(), + code: self.code, + } + } +} + +impl Error<&I> { + /// Converts `Error<&I>` into `Error` by copying. + pub fn copied(self) -> Error { + Error { + input: *self.input, + code: self.code, + } + } +} + +impl Error<&mut I> { + /// Converts `Error<&mut I>` into `Error` by copying. + pub fn copied(self) -> Error { + Error { + input: *self.input, + code: self.code, + } + } +} + #[cfg(feature = "std")] impl std::error::Error for Error {} +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl From> for Error> { + fn from(value: Error<&[u8]>) -> Self { + Error { + input: value.input.to_owned(), + code: value.code, + } + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl From> for Error { + fn from(value: Error<&str>) -> Self { + Error { + input: value.input.to_owned(), + code: value.code, + } + } +} + // for backward compatibility, keep those trait implementations // for the previously used error type impl ParseError for (I, ErrorKind) { @@ -142,221 +212,41 @@ E::append(input, kind, other) } -/// This error type accumulates errors and their position when backtracking -/// through a parse tree. With some post processing (cf `examples/json.rs`), -/// it can be used to display user friendly error messages -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -#[derive(Clone, Debug, PartialEq)] -pub struct VerboseError { - /// List of errors accumulated by `VerboseError`, containing the affected - /// part of input data, and some context - pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>, -} - -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -#[derive(Clone, Debug, PartialEq)] -/// Error context for `VerboseError` -pub enum VerboseErrorKind { - /// Static string added by the `context` function - Context(&'static str), - /// Indicates which character was expected by the `char` function - Char(char), - /// Error kind given by various nom parsers - Nom(ErrorKind), -} - -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -impl ParseError for VerboseError { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - VerboseError { - errors: vec![(input, VerboseErrorKind::Nom(kind))], - } - } - - fn append(input: I, kind: ErrorKind, mut other: Self) -> Self { - other.errors.push((input, VerboseErrorKind::Nom(kind))); - other - } - - fn from_char(input: I, c: char) -> Self { - VerboseError { - errors: vec![(input, VerboseErrorKind::Char(c))], - } - } -} - -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -impl ContextError for VerboseError { - fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self { - other.errors.push((input, VerboseErrorKind::Context(ctx))); - other - } -} - -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -impl FromExternalError for VerboseError { - /// Create a new error from an input position and an external error - fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { - Self::from_error_kind(input, kind) - } -} - -#[cfg(feature = "alloc")] -impl fmt::Display for VerboseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "Parse error:")?; - for (input, error) in &self.errors { - match error { - VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?, - VerboseErrorKind::Char(c) => writeln!(f, "expected '{}' at: {}", c, input)?, - VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?, - } - } - - Ok(()) - } -} - -#[cfg(feature = "std")] -impl std::error::Error for VerboseError {} - -use crate::internal::{Err, IResult}; - /// Create a new error from an input position, a static string and an existing error. /// This is used mainly in the [context] combinator, to add user friendly information /// to errors when backtracking through a parse tree -pub fn context, F, O>( - context: &'static str, - mut f: F, -) -> impl FnMut(I) -> IResult -where - F: Parser, -{ - move |i: I| match f.parse(i.clone()) { - Ok(o) => Ok(o), - Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), - Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))), - Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))), - } +pub fn context(context: &'static str, parser: F) -> Context { + Context { context, parser } } -/// Transforms a `VerboseError` into a trace with input position information -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn convert_error>( - input: I, - e: VerboseError, -) -> crate::lib::std::string::String { - use crate::lib::std::fmt::Write; - use crate::traits::Offset; - - let mut result = crate::lib::std::string::String::new(); - - for (i, (substring, kind)) in e.errors.iter().enumerate() { - let offset = input.offset(substring); - - if input.is_empty() { - match kind { - VerboseErrorKind::Char(c) => { - write!(&mut result, "{}: expected '{}', got empty input\n\n", i, c) - } - VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s), - VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e), - } - } else { - let prefix = &input.as_bytes()[..offset]; +/// Parser implementation for [context] +pub struct Context { + context: &'static str, + parser: F, +} - // Count the number of newlines in the first `offset` bytes of input - let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1; +impl Parser for Context +where + I: Clone, + F: Parser, + >::Error: ContextError, +{ + type Output = >::Output; + type Error = >::Error; - // Find the line that includes the subslice: - // Find the *last* newline before the substring starts - let line_begin = prefix - .iter() - .rev() - .position(|&b| b == b'\n') - .map(|pos| offset - pos) - .unwrap_or(0); - - // Find the full line after that newline - let line = input[line_begin..] - .lines() - .next() - .unwrap_or(&input[line_begin..]) - .trim_end(); - - // The (1-indexed) column number is the offset of our substring into that line - let column_number = line.offset(substring) + 1; - - match kind { - VerboseErrorKind::Char(c) => { - if let Some(actual) = substring.chars().next() { - write!( - &mut result, - "{i}: at line {line_number}:\n\ - {line}\n\ - {caret:>column$}\n\ - expected '{expected}', found {actual}\n\n", - i = i, - line_number = line_number, - line = line, - caret = '^', - column = column_number, - expected = c, - actual = actual, - ) - } else { - write!( - &mut result, - "{i}: at line {line_number}:\n\ - {line}\n\ - {caret:>column$}\n\ - expected '{expected}', got end of input\n\n", - i = i, - line_number = line_number, - line = line, - caret = '^', - column = column_number, - expected = c, - ) - } - } - VerboseErrorKind::Context(s) => write!( - &mut result, - "{i}: at line {line_number}, in {context}:\n\ - {line}\n\ - {caret:>column$}\n\n", - i = i, - line_number = line_number, - context = s, - line = line, - caret = '^', - column = column_number, - ), - VerboseErrorKind::Nom(e) => write!( - &mut result, - "{i}: at line {line_number}, in {nom_err:?}:\n\ - {line}\n\ - {caret:>column$}\n\n", - i = i, - line_number = line_number, - nom_err = e, - line = line, - caret = '^', - column = column_number, - ), - } + fn process(&mut self, input: I) -> PResult { + match self.parser.process::(input.clone()) { + Err(Err::Error(e)) => Err(Err::Error(OM::Error::map(e, |e| { + >::Error::add_context(input, self.context, e) + }))), + Err(Err::Failure(e)) => Err(Err::Failure(>::Error::add_context( + input, + self.context, + e, + ))), + x => x, } - // Because `write!` to a `String` is infallible, this `unwrap` is fine. - .unwrap(); } - - result } /// Indicates which parser returned an error @@ -383,6 +273,7 @@ Digit, HexDigit, OctDigit, + BinDigit, AlphaNumeric, Space, MultiSpace, @@ -417,6 +308,9 @@ Float, Satisfy, Fail, + Many, + Fold, + Precedence, } #[rustfmt::skip] @@ -477,6 +371,10 @@ ErrorKind::Float => 73, ErrorKind::Satisfy => 74, ErrorKind::Fail => 75, + ErrorKind::Many => 76, + ErrorKind::Fold => 77, + ErrorKind::BinDigit => 78, + ErrorKind::Precedence => 79, } } @@ -527,6 +425,7 @@ ErrorKind::ManyMN => "Many(m, n)", ErrorKind::HexDigit => "Hexadecimal Digit", ErrorKind::OctDigit => "Octal digit", + ErrorKind::BinDigit => "Binary digit", ErrorKind::Not => "Negation", ErrorKind::Permutation => "Permutation", ErrorKind::ManyTill => "ManyTill", @@ -539,6 +438,9 @@ ErrorKind::Float => "Float", ErrorKind::Satisfy => "Satisfy", ErrorKind::Fail => "Fail", + ErrorKind::Many => "Many", + ErrorKind::Fold => "Fold", + ErrorKind::Precedence => "Precedence", } } } @@ -548,7 +450,7 @@ #[allow(unused_variables)] #[macro_export(local_inner_macros)] macro_rules! error_position( - ($input:expr, $code:expr) => ({ + ($input:expr, $code:expr $(,)?) => ({ $crate::error::make_error($input, $code) }); ); @@ -559,7 +461,7 @@ #[allow(unused_variables)] #[macro_export(local_inner_macros)] macro_rules! error_node_position( - ($input:expr, $code:expr, $next:expr) => ({ + ($input:expr, $code:expr, $next:expr $(,)?) => ({ $crate::error::append_error($input, $code, $next) }); ); @@ -605,16 +507,85 @@ } #[cfg(test)] -#[cfg(feature = "alloc")] mod tests { use super::*; - use crate::character::complete::char; #[test] - fn convert_error_panic() { - let input = ""; + fn context_test() { + use crate::{character::char, combinator::cut, internal::Needed}; + + #[derive(Debug, PartialEq)] + struct Error { + input: I, + ctx: Option<&'static str>, + } + + impl ParseError for Error { + fn from_error_kind(input: I, _kind: ErrorKind) -> Self { + Self { input, ctx: None } + } + + fn append(input: I, _kind: ErrorKind, other: Self) -> Self { + Self { + input, + ctx: other.ctx, + } + } + } + + impl ContextError for Error { + fn add_context(input: I, ctx: &'static str, _other: Self) -> Self { + Self { + input, + ctx: Some(ctx), + } + } + } + + assert_eq!( + context("ctx", char::<_, Error<_>>('a')).parse("abcd"), + Ok(("bcd", 'a')) + ); + assert_eq!( + context("ctx", char::<_, Error<_>>('a')).parse(""), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + context("ctx", char::<_, Error<_>>('a')).parse_complete(""), + Err(Err::Error(Error { + input: "", + ctx: Some("ctx") + })) + ); + assert_eq!( + context("ctx", cut(char::<_, Error<_>>('a'))).parse("bcd"), + Err(Err::Failure(Error { + input: "bcd", + ctx: Some("ctx") + })) + ); + } + + #[cfg(feature = "alloc")] + #[test] + fn clone_error() { + use crate::lib::std::string::String; + let err = Error { + code: ErrorKind::Eof, + input: "test", + }; + + let _err: Error = err.cloned(); + } + + #[test] + fn copy_error() { + let err = Error { + code: ErrorKind::Eof, + input: &0_u8, + }; - let _result: IResult<_, _, VerboseError<&str>> = char('x')(input); + let _err: Error = err.copied(); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/internal.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/internal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/internal.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/internal.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,9 @@ //! Basic types to build the parsers use self::Needed::*; -use crate::error::{self, ErrorKind}; +use crate::error::{self, ErrorKind, FromExternalError, ParseError}; use crate::lib::std::fmt; +use core::marker::PhantomData; use core::num::NonZeroUsize; /// Holds the result of parsing functions @@ -26,9 +27,9 @@ /// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic. /// - "complete" parsers: It will not be an issue, `Incomplete` is never used /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data - /// for the parser to decide, and you should gather more data before parsing again. - /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`, - /// you can get out of the parsing loop and call `finish()` on the parser's result + /// for the parser to decide, and you should gather more data before parsing again. + /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`, + /// you can get out of the parsing loop and call `finish()` on the parser's result fn finish(self) -> Result<(I, O), E>; } @@ -38,7 +39,7 @@ Ok(res) => Ok(res), Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e), Err(Err::Incomplete(_)) => { - panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead") + panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead") } } } @@ -46,7 +47,6 @@ /// Contains information on needed data if a parser returned `Incomplete` #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub enum Needed { /// Needs more data, but we do not know how much Unknown, @@ -83,36 +83,36 @@ /// It has three cases: /// /// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum -/// can contain how many additional bytes are necessary. If you are sure your parser -/// is working on full data, you can wrap your parser with the `complete` combinator -/// to transform that case in `Error` +/// can contain how many additional bytes are necessary. If you are sure your parser +/// is working on full data, you can wrap your parser with the `complete` combinator +/// to transform that case in `Error` /// * `Error` means some parser did not succeed, but another one might (as an example, -/// when testing different branches of an `alt` combinator) -/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix -/// to decide on the next parser to apply, and that parser fails, you know there's no need -/// to try other parsers, you were already in the right branch, so the data is invalid +/// when testing different branches of an `alt` combinator) +/// * `Failure` indicates an unrecoverable error. For example, when a prefix has been +/// recognised and the next parser has been confirmed, if that parser fails, then the +/// entire process fails; there are no more parsers to try. +/// +/// Distinguishing `Failure` this from `Error` is only relevant inside the parser's code. For +/// external consumers, both mean that parsing failed. +/// +/// See also: [`Finish`]. /// #[derive(Debug, Clone, PartialEq)] -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] -pub enum Err { +pub enum Err { /// There was not enough data Incomplete(Needed), /// The parser had an error (recoverable) - Error(E), + Error(Error), /// The parser had an unrecoverable error: we got to the right /// branch and we know other branches won't work, so backtrack /// as fast as possible - Failure(E), + Failure(Failure), } impl Err { /// Tests if the result is Incomplete pub fn is_incomplete(&self) -> bool { - if let Err::Incomplete(_) = self { - true - } else { - false - } + matches!(self, Err::Incomplete(..)) } /// Applies the given function to the inner error @@ -237,56 +237,247 @@ } } +/// Parser mode: influences how combinators build values +/// +/// the [Parser] trait is generic over types implementing [Mode]. Its method are +/// called to produce and manipulate output values or errors. +/// +/// The main implementations of this trait are: +/// * [Emit]: produce a value +/// * [Check]: apply the parser but do not generate a value +pub trait Mode { + /// The output type that may be generated + type Output; + + /// Produces a value + fn bind T>(f: F) -> Self::Output; + + /// Applies a function over the produced value + fn map U>(x: Self::Output, f: F) -> Self::Output; + + /// Combines two values generated by previous parsers + fn combine V>( + x: Self::Output, + y: Self::Output, + f: F, + ) -> Self::Output; +} + +/// Produces a value. This is the default behaviour for parsers +pub struct Emit; +impl Mode for Emit { + type Output = T; + + #[inline(always)] + fn bind T>(f: F) -> Self::Output { + f() + } + + #[inline(always)] + fn map U>(x: Self::Output, f: F) -> Self::Output { + f(x) + } + + #[inline(always)] + fn combine V>( + x: Self::Output, + y: Self::Output, + f: F, + ) -> Self::Output { + f(x, y) + } +} + +/// Applies the parser, but do not a produce a value +/// +/// This has the effect of greatly reducing the amount of code generated and the +/// parser memory usage. Some combinators check for an error in a child parser but +/// discard the error, and for those, using [Check] makes sure the error is not +/// even generated, only the fact that an error happened remains +pub struct Check; +impl Mode for Check { + type Output = (); + + #[inline(always)] + fn bind T>(_: F) -> Self::Output {} + + #[inline(always)] + fn map U>(_: Self::Output, _: F) -> Self::Output {} + + #[inline(always)] + fn combine V>( + _: Self::Output, + _: Self::Output, + _: F, + ) -> Self::Output { + } +} + +/// Parser result type +/// +/// * `Ok` branch: a tuple of the remaining input data, and the output value. +/// The output value is of the `O` type if the output mode was [Emit], and `()` +/// if the mode was [Check] +/// * `Err` branch: an error of the `E` type if the erroor mode was [Emit], and `()` +/// if the mode was [Check] +pub type PResult = Result< + (I, <::Output as Mode>::Output), + Err::Error as Mode>::Output>, +>; + +/// Trait Defining the parser's execution +/// +/// The same parser implementation can vary in behaviour according to the chosen +/// output mode +pub trait OutputMode { + /// Defines the [Mode] for the output type. [Emit] will generate the value, [Check] will + /// apply the parser but will only generate `()` if successful. This can be used when + /// verifying that the input data conforms to the format without having to generate any + /// output data + type Output: Mode; + /// Defines the [Mode] for the output type. [Emit] will generate the value, [Check] will + /// apply the parser but will only generate `()` if an error happened. [Emit] should be + /// used when we want to handle the error and extract useful information from it. [Check] + /// is used when we just want to know if parsing failed and reject the data quickly. + type Error: Mode; + /// Indicates whether the input data is "complete", ie we already have the entire data in the + /// buffer, or if it is "streaming", where more data can be added later in the buffer. In + /// streaming mode, the parser will understand that a failure may mean that we are missing + /// data, and will return a specific error branch, [Err::Incomplete] to signal it. In complete + /// mode, the parser will generate a normal error + type Incomplete: IsStreaming; +} + +/// Specifies the behaviour when a parser encounters an error that could be due to partial ata +pub trait IsStreaming { + /// called by parsers on partial data errors + /// * `needed` can hold the amount of additional data the parser would need to decide + /// * `err_f`: produces the error when in "complete" mode + fn incomplete E>(needed: Needed, err_f: F) -> Err; + /// Indicates whether the data is in streaming mode or not + fn is_streaming() -> bool; +} + +/// Indicates that the input data is streaming: more data may be available later +pub struct Streaming; + +impl IsStreaming for Streaming { + fn incomplete E>(needed: Needed, _err_f: F) -> Err { + Err::Incomplete(needed) + } + + #[inline] + fn is_streaming() -> bool { + true + } +} + +/// Indicates that the input data is complete: no more data may be added later +pub struct Complete; + +impl IsStreaming for Complete { + fn incomplete E>(_needed: Needed, err_f: F) -> Err { + Err::Error(err_f()) + } + + #[inline] + fn is_streaming() -> bool { + false + } +} + +/// Holds the parser execution modifiers: output [Mode], error [Mode] and +/// streaming behaviour for input data +pub struct OutputM { + m: PhantomData, + em: PhantomData, + s: PhantomData, +} + +impl OutputMode for OutputM { + type Output = M; + type Error = EM; + type Incomplete = S; +} /// All nom parsers implement this trait -pub trait Parser { +pub trait Parser { + /// Type of the produced value + type Output; + /// Error type of this parser + type Error: ParseError; + + /// A parser takes in input type, and returns a `Result` containing + /// either the remaining input and the output value, or an error + #[inline] + fn parse(&mut self, input: Input) -> IResult { + self.process::>(input) + } + + /// A parser takes in input type, and returns a `Result` containing + /// either the remaining input and the output value, or an error + #[inline] + fn parse_complete(&mut self, input: Input) -> IResult { + self.process::>(input) + } + /// A parser takes in input type, and returns a `Result` containing /// either the remaining input and the output value, or an error - fn parse(&mut self, input: I) -> IResult; + fn process( + &mut self, + input: Input, + ) -> PResult; /// Maps a function over the result of a parser - fn map(self, g: G) -> Map + fn map(self, g: G) -> Map where - G: Fn(O) -> O2, + G: FnMut(Self::Output) -> O2, Self: core::marker::Sized, { - Map { - f: self, - g, - phantom: core::marker::PhantomData, - } + Map { f: self, g } + } + + /// Applies a function returning a `Result` over the result of a parser. + fn map_res(self, g: G) -> MapRes + where + G: FnMut(Self::Output) -> Result, + Self::Error: FromExternalError, + Self: core::marker::Sized, + { + MapRes { f: self, g } + } + + /// Applies a function returning an `Option` over the result of a parser. + fn map_opt(self, g: G) -> MapOpt + where + G: FnMut(Self::Output) -> Option, + Self: core::marker::Sized, + { + MapOpt { f: self, g } } /// Creates a second parser from the output of the first one, then apply over the rest of the input - fn flat_map(self, g: G) -> FlatMap + fn flat_map(self, g: G) -> FlatMap where - G: FnMut(O) -> H, - H: Parser, + G: FnMut(Self::Output) -> H, + H: Parser, Self: core::marker::Sized, { - FlatMap { - f: self, - g, - phantom: core::marker::PhantomData, - } + FlatMap { f: self, g } } /// Applies a second parser over the output of the first one - fn and_then(self, g: G) -> AndThen + fn and_then(self, g: G) -> AndThen where - G: Parser, + G: Parser, Self: core::marker::Sized, { - AndThen { - f: self, - g, - phantom: core::marker::PhantomData, - } + AndThen { f: self, g } } /// Applies a second parser after the first one, return their results as a tuple fn and(self, g: G) -> And where - G: Parser, + G: Parser, Self: core::marker::Sized, { And { f: self, g } @@ -295,7 +486,7 @@ /// Applies a second parser over the input if the first one failed fn or(self, g: G) -> Or where - G: Parser, + G: Parser, Self: core::marker::Sized, { Or { f: self, g } @@ -303,122 +494,258 @@ /// automatically converts the parser's output and error values to another type, as long as they /// implement the `From` trait - fn into, E2: From>(self) -> Into + fn into, E2: From>(self) -> Into where Self: core::marker::Sized, { Into { f: self, - phantom_out1: core::marker::PhantomData, - phantom_err1: core::marker::PhantomData, phantom_out2: core::marker::PhantomData, phantom_err2: core::marker::PhantomData, } } } -impl<'a, I, O, E, F> Parser for F +impl, F> Parser for F where - F: FnMut(I) -> IResult + 'a, + F: FnMut(I) -> IResult, { - fn parse(&mut self, i: I) -> IResult { - self(i) + type Output = O; + type Error = E; + + fn process(&mut self, i: I) -> PResult { + let (i, o) = self(i).map_err(|e| match e { + Err::Incomplete(i) => Err::Incomplete(i), + Err::Error(e) => Err::Error(OM::Error::bind(|| e)), + Err::Failure(e) => Err::Failure(e), + })?; + Ok((i, OM::Output::bind(|| o))) } } +macro_rules! impl_parser_for_tuple { + ($($parser:ident $output:ident),+) => ( + #[allow(non_snake_case)] + impl, $($parser),+> Parser for ($($parser),+,) + where + $($parser: Parser),+ + { + type Output = ($($output),+,); + type Error = E; + + #[inline(always)] + fn process(&mut self, i: I) -> PResult { + let ($(ref mut $parser),+,) = *self; + + // FIXME: is there a way to avoid producing the output values? + $(let(i, $output) = $parser.process::>(i)?;)+ + + // ??? + Ok((i, OM::Output::bind(|| ($($output),+,)))) + } + } + ) +} + +macro_rules! impl_parser_for_tuples { + ($parser1:ident $output1:ident, $($parser:ident $output:ident),+) => { + impl_parser_for_tuples!(__impl $parser1 $output1; $($parser $output),+); + }; + (__impl $($parser:ident $output:ident),+; $parser1:ident $output1:ident $(,$parser2:ident $output2:ident)*) => { + impl_parser_for_tuple!($($parser $output),+); + impl_parser_for_tuples!(__impl $($parser $output),+, $parser1 $output1; $($parser2 $output2),*); + }; + (__impl $($parser:ident $output:ident),+;) => { + impl_parser_for_tuple!($($parser $output),+); + } +} + +impl_parser_for_tuples!(P1 O1, P2 O2, P3 O3, P4 O4, P5 O5, P6 O6, P7 O7, P8 O8, P9 O9, P10 O10, P11 O11, P12 O12, P13 O13, P14 O14, P15 O15, P16 O16, P17 O17, P18 O18, P19 O19, P20 O20, P21 O21); + +/* #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "alloc")] -impl<'a, I, O, E> Parser for Box + 'a> { - fn parse(&mut self, input: I) -> IResult { - (**self).parse(input) +impl> Parser for Box> { + type Output = O; + type Error = E; + + fn process(&mut self, input: I) -> PResult { + (**self).process(input) } } - +*/ /// Implementation of `Parser::map` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] -pub struct Map { +pub struct Map { f: F, g: G, - phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> O2> Parser for Map { - fn parse(&mut self, i: I) -> IResult { - match self.f.parse(i) { +impl, F: Parser, G: FnMut(>::Output) -> O2> + Parser for Map +{ + type Output = O2; + type Error = E; + + #[inline(always)] + fn process(&mut self, i: I) -> PResult { + match self.f.process::(i) { Err(e) => Err(e), - Ok((i, o)) => Ok((i, (self.g)(o))), + Ok((i, o)) => Ok((i, OM::Output::map(o, |o| (self.g)(o)))), + } + } +} + +/// Implementation of `Parser::map_res` +pub struct MapRes { + f: F, + g: G, +} + +impl Parser for MapRes +where + I: Clone, + >::Error: FromExternalError, + F: Parser, + G: FnMut(>::Output) -> Result, +{ + type Output = O2; + type Error = >::Error; + + fn process(&mut self, i: I) -> PResult { + let (input, o1) = self + .f + .process::>(i.clone())?; + + match (self.g)(o1) { + Ok(o2) => Ok((input, OM::Output::bind(|| o2))), + Err(e) => Err(Err::Error(OM::Error::bind(|| { + >::Error::from_external_error(i, ErrorKind::MapRes, e) + }))), + } + } +} + +/// Implementation of `Parser::map_opt` +pub struct MapOpt { + f: F, + g: G, +} + +impl Parser for MapOpt +where + I: Clone, + F: Parser, + G: FnMut(>::Output) -> Option, +{ + type Output = O2; + type Error = >::Error; + + fn process(&mut self, i: I) -> PResult { + let (input, o1) = self + .f + .process::>(i.clone())?; + + match (self.g)(o1) { + Some(o2) => Ok((input, OM::Output::bind(|| o2))), + None => Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::MapOpt) + }))), } } } /// Implementation of `Parser::flat_map` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] -pub struct FlatMap { +pub struct FlatMap { f: F, g: G, - phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> H, H: Parser> Parser - for FlatMap +impl< + I, + E: ParseError, + F: Parser, + G: FnMut(>::Output) -> H, + H: Parser, + > Parser for FlatMap { - fn parse(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse(i)?; - (self.g)(o1).parse(i) + type Output = >::Output; + type Error = E; + + fn process(&mut self, i: I) -> PResult { + let (input, o1) = self + .f + .process::>(i)?; + + (self.g)(o1).process::(input) } } /// Implementation of `Parser::and_then` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] -pub struct AndThen { +pub struct AndThen { f: F, g: G, - phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser - for AndThen +impl, G: Parser<>::Output, Error = >::Error>> + Parser for AndThen { - fn parse(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse(i)?; - let (_, o2) = self.g.parse(o1)?; - Ok((i, o2)) + type Output = >::Output>>::Output; + type Error = >::Error; + + fn process(&mut self, i: I) -> PResult { + let (input, o1) = self + .f + .process::>(i)?; + + let (_, o2) = self.g.process::(o1)?; + Ok((input, o2)) } } /// Implementation of `Parser::and` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct And { f: F, g: G, } -impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser +impl, F: Parser, G: Parser> Parser for And { - fn parse(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse(i)?; - let (i, o2) = self.g.parse(i)?; - Ok((i, (o1, o2))) + type Output = (>::Output, >::Output); + type Error = E; + + #[inline(always)] + fn process(&mut self, i: I) -> PResult { + let (i, o1) = self.f.process::(i)?; + let (i, o2) = self.g.process::(i)?; + + Ok((i, OM::Output::combine(o1, o2, |o1, o2| (o1, o2)))) } } /// Implementation of `Parser::or` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Or { f: F, g: G, } -impl<'a, I: Clone, O, E: crate::error::ParseError, F: Parser, G: Parser> - Parser for Or +impl< + I: Clone, + O, + E: ParseError, + F: Parser, + G: Parser, + > Parser for Or { - fn parse(&mut self, i: I) -> IResult { - match self.f.parse(i.clone()) { - Err(Err::Error(e1)) => match self.g.parse(i) { - Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))), + type Output = >::Output; + type Error = >::Error; + + fn process(&mut self, i: I) -> PResult { + match self.f.process::(i.clone()) { + Err(Err::Error(e1)) => match self.g.process::(i) { + Err(Err::Error(e2)) => Err(Err::Error(OM::Error::combine(e1, e2, |e1, e2| e1.or(e2)))), res => res, }, res => res, @@ -427,45 +754,70 @@ } /// Implementation of `Parser::into` -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] -pub struct Into, E1, E2: From> { +pub struct Into { f: F, - phantom_out1: core::marker::PhantomData, - phantom_err1: core::marker::PhantomData, phantom_out2: core::marker::PhantomData, phantom_err2: core::marker::PhantomData, } impl< - 'a, - I: Clone, - O1, - O2: From, - E1, - E2: crate::error::ParseError + From, - F: Parser, - > Parser for Into -{ - fn parse(&mut self, i: I) -> IResult { - match self.f.parse(i) { - Ok((i, o)) => Ok((i, o.into())), - Err(Err::Error(e)) => Err(Err::Error(e.into())), + I, + O2: From<>::Output>, + E2: crate::error::ParseError + From<>::Error>, + F: Parser, + > Parser for Into +{ + type Output = O2; + type Error = E2; + + fn process(&mut self, i: I) -> PResult { + match self.f.process::(i) { + Ok((i, o)) => Ok((i, OM::Output::map(o, |o| o.into()))), + Err(Err::Error(e)) => Err(Err::Error(OM::Error::map(e, |e| e.into()))), Err(Err::Failure(e)) => Err(Err::Failure(e.into())), Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)), } } } +/// Alternate between two Parser implementations with the same result type. +pub(crate) enum Either { + Left(F), + Right(G), +} + +impl< + I, + F: Parser, + G: Parser>::Output, Error = >::Error>, + > Parser for Either +{ + type Output = >::Output; + type Error = >::Error; + + #[inline] + fn process(&mut self, i: I) -> PResult { + match self { + Either::Left(f) => f.process::(i), + Either::Right(g) => g.process::(i), + } + } +} + #[cfg(test)] mod tests { use super::*; use crate::error::ErrorKind; + use crate::bytes::streaming::{tag, take}; + use crate::number::streaming::be_u16; + use crate::sequence::terminated; + #[doc(hidden)] #[macro_export] macro_rules! assert_size ( ($t:ty, $sz:expr) => ( - assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz); + assert_eq!($crate::lib::std::mem::size_of::<$t>(), $sz); ); ); @@ -486,4 +838,22 @@ let e = Err::Error(1); assert_eq!(e.map(|v| v + 1), Err::Error(2)); } + + #[test] + fn native_tuple_test() { + fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8])> { + terminated((be_u16, take(3u8)), tag("fg")).parse(i) + } + + assert_eq!( + tuple_3(&b"abcdefgh"[..]), + Ok((&b"h"[..], (0x6162u16, &b"cde"[..]))) + ); + assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + tuple_3(&b"abcdejk"[..]), + Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag))) + ); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,9 +8,10 @@ //! ```rust //! use nom::{ //! IResult, +//! Parser, //! bytes::complete::{tag, take_while_m_n}, -//! combinator::map_res, -//! sequence::tuple}; +//! combinator::map_res +//! }; //! //! #[derive(Debug,PartialEq)] //! pub struct Color { @@ -31,12 +32,12 @@ //! map_res( //! take_while_m_n(2, 2, is_hex_digit), //! from_hex -//! )(input) +//! ).parse(input) //! } //! //! fn hex_color(input: &str) -> IResult<&str, Color> { //! let (input, _) = tag("#")(input)?; -//! let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; +//! let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?; //! //! Ok((input, Color { red, green, blue })) //! } @@ -50,18 +51,18 @@ //! } //! ``` //! -//! The code is available on [Github](https://github.com/Geal/nom) +//! The code is available on [GitHub](https://github.com/rust-bakery/nom) //! -//! There are a few [guides](https://github.com/Geal/nom/tree/main/doc) with more details -//! about [how to write parsers](https://github.com/Geal/nom/blob/main/doc/making_a_new_parser_from_scratch.md), -//! or the [error management system](https://github.com/Geal/nom/blob/main/doc/error_management.md). +//! There are a few [guides](https://github.com/rust-bakery/nom/tree/main/doc) with more details +//! about [how to write parsers](https://github.com/rust-bakery/nom/blob/main/doc/making_a_new_parser_from_scratch.md), +//! or the [error management system](https://github.com/rust-bakery/nom/blob/main/doc/error_management.md). //! You can also check out the [recipes] module that contains examples of common patterns. //! //! **Looking for a specific combinator? Read the -//! ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)** +//! ["choose a combinator" guide](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md)** //! //! If you are upgrading to nom 5.0, please read the -//! [migration document](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_5.md). +//! [migration document](https://github.com/rust-bakery/nom/blob/main/doc/upgrading_to_nom_5.md). //! //! ## Parser combinators //! @@ -88,6 +89,7 @@ //! ```rust //! use nom::{ //! IResult, +//! Parser, //! sequence::delimited, //! // see the "streaming/complete" paragraph lower for an explanation of these submodules //! character::complete::char, @@ -95,7 +97,7 @@ //! }; //! //! fn parens(input: &str) -> IResult<&str, &str> { -//! delimited(char('('), is_not(")"), char(')'))(input) +//! delimited(char('('), is_not(")"), char(')')).parse(input) //! } //! ``` //! @@ -167,8 +169,8 @@ //! - An error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed //! - An error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: We cannot backtrack and test another parser //! -//! Please refer to the ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers. -//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/main/doc). +//! Please refer to the ["choose a combinator" guide](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers. +//! See also the rest of the documentation [here](https://github.com/rust-bakery/nom/tree/main/doc). //! //! ## Making new parsers with function combinators //! @@ -200,24 +202,24 @@ //! the next, and returns the result of the first parser that succeeds: //! //! ```rust -//! use nom::IResult; +//! use nom::{IResult, Parser}; //! use nom::branch::alt; //! use nom::bytes::complete::tag; //! //! let mut alt_tags = alt((tag("abcd"), tag("efgh"))); //! -//! assert_eq!(alt_tags(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..]))); -//! assert_eq!(alt_tags(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..]))); -//! assert_eq!(alt_tags(&b"ijklxxx"[..]), Err(nom::Err::Error((&b"ijklxxx"[..], nom::error::ErrorKind::Tag)))); +//! assert_eq!(alt_tags.parse(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..]))); +//! assert_eq!(alt_tags.parse(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..]))); +//! assert_eq!(alt_tags.parse(&b"ijklxxx"[..]), Err(nom::Err::Error((&b"ijklxxx"[..], nom::error::ErrorKind::Tag)))); //! ``` //! //! The **`opt`** combinator makes a parser optional. If the child parser returns //! an error, **`opt`** will still succeed and return None: //! //! ```rust -//! use nom::{IResult, combinator::opt, bytes::complete::tag}; +//! use nom::{IResult, Parser, combinator::opt, bytes::complete::tag}; //! fn abcd_opt(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> { -//! opt(tag("abcd"))(i) +//! opt(tag("abcd")).parse(i) //! } //! //! assert_eq!(abcd_opt(&b"abcdxxx"[..]), Ok((&b"xxx"[..], Some(&b"abcd"[..])))); @@ -229,11 +231,11 @@ //! ```rust //! # #[cfg(feature = "alloc")] //! # fn main() { -//! use nom::{IResult, multi::many0, bytes::complete::tag}; +//! use nom::{IResult, Parser, multi::many0, bytes::complete::tag}; //! use std::str; //! //! fn multi(i: &str) -> IResult<&str, Vec<&str>> { -//! many0(tag("abcd"))(i) +//! many0(tag("abcd")).parse(i) //! } //! //! let a = "abcdef"; @@ -253,30 +255,32 @@ //! - **`many0`**: Will apply the parser 0 or more times (if it returns the `O` type, the new parser returns `Vec`) //! - **`many1`**: Will apply the parser 1 or more times //! -//! There are more complex (and more useful) parsers like `tuple`, which is +//! There are more complex (and more useful) parsers like tuples, which are //! used to apply a series of parsers then assemble their results. //! -//! Example with `tuple`: +//! Example with a tuple of parsers: //! //! ```rust //! # fn main() { -//! use nom::{error::ErrorKind, Needed, -//! number::streaming::be_u16, -//! bytes::streaming::{tag, take}, -//! sequence::tuple}; +//! use nom::{ +//! error::ErrorKind, +//! Needed, +//! Parser, +//! number::streaming::be_u16, +//! bytes::streaming::{tag, take}}; //! -//! let mut tpl = tuple((be_u16, take(3u8), tag("fg"))); +//! let mut tpl = (be_u16, take(3u8), tag("fg")); //! //! assert_eq!( -//! tpl(&b"abcdefgh"[..]), +//! tpl.parse(&b"abcdefgh"[..]), //! Ok(( //! &b"h"[..], //! (0x6162u16, &b"cde"[..], &b"fg"[..]) //! )) //! ); -//! assert_eq!(tpl(&b"abcde"[..]), Err(nom::Err::Incomplete(Needed::new(2)))); +//! assert_eq!(tpl.parse(&b"abcde"[..]), Err(nom::Err::Incomplete(Needed::new(2)))); //! let input = &b"abcdejk"[..]; -//! assert_eq!(tpl(input), Err(nom::Err::Error((&input[5..], ErrorKind::Tag)))); +//! assert_eq!(tpl.parse(input), Err(nom::Err::Error((&input[5..], ErrorKind::Tag)))); //! # } //! ``` //! @@ -369,14 +373,12 @@ //! // while the complete version knows that all of the data is there //! assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd"))); //! ``` -//! **Going further:** Read the [guides](https://github.com/Geal/nom/tree/main/doc), +//! **Going further:** Read the [guides](https://github.com/rust-bakery/nom/tree/main/doc), //! check out the [recipes]! #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "cargo-clippy", allow(clippy::doc_markdown))] #![cfg_attr(feature = "docsrs", feature(doc_cfg))] -#![cfg_attr(feature = "docsrs", feature(extended_key_value_attributes))] +#![allow(clippy::doc_markdown)] #![deny(missing_docs)] -#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] #[cfg(feature = "alloc")] #[macro_use] extern crate alloc; @@ -388,12 +390,10 @@ /// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does /// it, albeit there it is not public. -#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] pub mod lib { /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally, /// as well as `core` or `std` #[cfg(not(feature = "std"))] - #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] /// internal std exports for no_std compatibility pub mod std { #[doc(hidden)] @@ -405,7 +405,7 @@ pub use alloc::{borrow, boxed, string, vec}; #[doc(hidden)] - pub use core::{cmp, convert, fmt, iter, mem, ops, option, result, slice, str}; + pub use core::{cmp, convert, fmt, iter, mem, num, ops, option, result, slice, str}; /// internal reproduction of std prelude #[doc(hidden)] @@ -415,13 +415,12 @@ } #[cfg(feature = "std")] - #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] /// internal std exports for no_std compatibility pub mod std { #[doc(hidden)] pub use std::{ - alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, result, - slice, str, string, vec, + alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, num, ops, option, + result, slice, str, string, vec, }; /// internal reproduction of std prelude @@ -432,12 +431,9 @@ } } -pub use self::bits::*; pub use self::internal::*; pub use self::traits::*; -pub use self::str::*; - #[macro_use] mod macros; #[macro_use] @@ -459,6 +455,6 @@ pub mod number; -#[cfg(feature = "docsrs")] -#[cfg_attr(feature = "docsrs", cfg_attr(feature = "docsrs", doc = include_str!("../doc/nom_recipes.md")))] +#[cfg(all(feature = "std", any(doc, doctest, feature = "docsrs")))] +#[cfg_attr(any(doc, doctest, feature = "docsrs"), doc = include_str!("../doc/nom_recipes.md"))] pub mod recipes {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/multi/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/multi/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,13 +3,23 @@ #[cfg(test)] mod tests; +use core::marker::PhantomData; + +use crate::bytes::take; use crate::error::ErrorKind; use crate::error::ParseError; -use crate::internal::{Err, IResult, Needed, Parser}; +use crate::internal::{Err, Needed, Parser}; +use crate::lib::std::num::NonZeroUsize; #[cfg(feature = "alloc")] use crate::lib::std::vec::Vec; -use crate::traits::{InputLength, InputTake, ToUsize}; -use core::num::NonZeroUsize; +use crate::traits::ToUsize; +use crate::Check; +use crate::Emit; +use crate::Input; +use crate::Mode; +use crate::NomRange; +use crate::OutputM; +use crate::OutputMode; /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. /// @@ -35,12 +45,12 @@ /// return an error, to prevent going into an infinite loop /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::many0; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// many0(tag("abc"))(s) +/// many0(tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -50,27 +60,59 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn many0(mut f: F) -> impl FnMut(I) -> IResult, E> +pub fn many0( + f: F, +) -> impl Parser>::Output>, Error = >::Error> where - I: Clone + InputLength, - F: Parser, - E: ParseError, + I: Clone + Input, + F: Parser, +{ + Many0 { parser: f } +} + +#[cfg(feature = "alloc")] +/// Parser implementation for the [many0] combinator +pub struct Many0 { + parser: F, +} + +#[cfg(feature = "alloc")] +impl Parser for Many0 +where + I: Clone + Input, + F: Parser, { - move |mut i: I| { - let mut acc = crate::lib::std::vec::Vec::with_capacity(4); + type Output = crate::lib::std::vec::Vec<>::Output>; + type Error = >::Error; + + fn process( + &mut self, + mut i: I, + ) -> crate::PResult { + let mut acc = OM::Output::bind(|| crate::lib::std::vec::Vec::with_capacity(4)); loop { let len = i.input_len(); - match f.parse(i.clone()) { + match self + .parser + .process::>(i.clone()) + { Err(Err::Error(_)) => return Ok((i, acc)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i1, o)) => { // infinite loop check: the parser must always consume if i1.input_len() == len { - return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many0))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::Many0) + }))); } i = i1; - acc.push(o); + + acc = OM::Output::combine(acc, o, |mut acc, o| { + acc.push(o); + acc + }) } } } @@ -90,12 +132,12 @@ /// to prevent going into an infinite loop. /// /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::many1; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// many1(tag("abc"))(s) +/// many1(tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -105,33 +147,77 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn many1(mut f: F) -> impl FnMut(I) -> IResult, E> +pub fn many1( + parser: F, +) -> impl Parser>::Output>, Error = >::Error> where - I: Clone + InputLength, - F: Parser, - E: ParseError, + I: Clone + Input, + F: Parser, { - move |mut i: I| match f.parse(i.clone()) { - Err(Err::Error(err)) => Err(Err::Error(E::append(i, ErrorKind::Many1, err))), - Err(e) => Err(e), - Ok((i1, o)) => { - let mut acc = crate::lib::std::vec::Vec::with_capacity(4); - acc.push(o); - i = i1; - - loop { - let len = i.input_len(); - match f.parse(i.clone()) { - Err(Err::Error(_)) => return Ok((i, acc)), - Err(e) => return Err(e), - Ok((i1, o)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1))); - } + Many1 { parser } +} - i = i1; - acc.push(o); +#[cfg(feature = "alloc")] +/// Parser implementation for the [many1] combinator +pub struct Many1 { + parser: F, +} + +#[cfg(feature = "alloc")] +impl Parser for Many1 +where + I: Clone + Input, + F: Parser, +{ + type Output = Vec<>::Output>; + type Error = >::Error; + + fn process( + &mut self, + mut i: I, + ) -> crate::PResult { + match self + .parser + .process::>(i.clone()) + { + Err(Err::Error(err)) => Err(Err::Error(OM::Error::bind(|| { + >::Error::append(i, ErrorKind::Many1, err) + }))), + Err(Err::Failure(e)) => Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), + Ok((i1, o)) => { + let mut acc = OM::Output::map(o, |o| { + let mut acc = crate::lib::std::vec::Vec::with_capacity(4); + acc.push(o); + acc + }); + + i = i1; + + loop { + let len = i.input_len(); + match self + .parser + .process::>(i.clone()) + { + Err(Err::Error(_)) => return Ok((i, acc)), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::Many0) + }))); + } + + i = i1; + + acc = OM::Output::combine(acc, o, |mut acc, o| { + acc.push(o); + acc + }) + } } } } @@ -146,12 +232,12 @@ /// `f` keeps going so long as `g` produces [`Err::Error`]. To instead chain an error up, see [`cut`][crate::combinator::cut]. /// /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::many_till; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, (Vec<&str>, &str)> { -/// many_till(tag("abc"), tag("end"))(s) +/// many_till(tag("abc"), tag("end")).parse(s) /// }; /// /// assert_eq!(parser("abcabcend"), Ok(("", (vec!["abc", "abc"], "end")))); @@ -162,38 +248,82 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn many_till( - mut f: F, - mut g: G, -) -> impl FnMut(I) -> IResult, P), E> -where - I: Clone + InputLength, - F: Parser, - G: Parser, +pub fn many_till( + f: F, + g: G, +) -> impl Parser>::Output>, >::Output), Error = E> +where + I: Clone + Input, + F: Parser, + G: Parser, + E: ParseError, +{ + ManyTill { + f, + g, + e: PhantomData, + } +} + +#[cfg(feature = "alloc")] +/// Parser implementation for the [many_till] combinator +pub struct ManyTill { + f: F, + g: G, + e: PhantomData, +} + +#[cfg(feature = "alloc")] +impl Parser for ManyTill +where + I: Clone + Input, + F: Parser, + G: Parser, E: ParseError, { - move |mut i: I| { - let mut res = crate::lib::std::vec::Vec::new(); + type Output = (Vec<>::Output>, >::Output); + type Error = E; + + fn process( + &mut self, + mut i: I, + ) -> crate::PResult { + let mut res = OM::Output::bind(crate::lib::std::vec::Vec::new); loop { let len = i.input_len(); - match g.parse(i.clone()) { - Ok((i1, o)) => return Ok((i1, (res, o))), + match self + .g + .process::>(i.clone()) + { + Ok((i1, o)) => return Ok((i1, OM::Output::combine(res, o, |res, o| (res, o)))), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)), Err(Err::Error(_)) => { - match f.parse(i.clone()) { - Err(Err::Error(err)) => return Err(Err::Error(E::append(i, ErrorKind::ManyTill, err))), - Err(e) => return Err(e), + match self.f.process::(i.clone()) { + Err(Err::Error(err)) => { + return Err(Err::Error(OM::Error::map(err, |err| { + E::append(i, ErrorKind::ManyTill, err) + }))) + } + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i1, o)) => { // infinite loop check: the parser must always consume if i1.input_len() == len { - return Err(Err::Error(E::from_error_kind(i1, ErrorKind::ManyTill))); + return Err(Err::Error(OM::Error::bind(|| { + E::from_error_kind(i, ErrorKind::Many0) + }))); } - res.push(o); i = i1; + + res = OM::Output::combine(res, o, |mut acc, o| { + acc.push(o); + acc + }) } } } - Err(e) => return Err(e), } } } @@ -209,12 +339,12 @@ /// * `f` Parses the elements of the list. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::separated_list0; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// separated_list0(tag("|"), tag("abc"))(s) +/// separated_list0(tag("|"), tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); @@ -225,44 +355,91 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn separated_list0( - mut sep: G, - mut f: F, -) -> impl FnMut(I) -> IResult, E> -where - I: Clone + InputLength, - F: Parser, - G: Parser, +pub fn separated_list0( + sep: G, + f: F, +) -> impl Parser>::Output>, Error = E> +where + I: Clone + Input, + F: Parser, + G: Parser, E: ParseError, { - move |mut i: I| { - let mut res = Vec::new(); + SeparatedList0 { + parser: f, + separator: sep, + } +} + +#[cfg(feature = "alloc")] +/// Parser implementation for the [separated_list0] combinator +pub struct SeparatedList0 { + parser: F, + separator: G, +} - match f.parse(i.clone()) { +#[cfg(feature = "alloc")] +impl, F, G> Parser for SeparatedList0 +where + I: Clone + Input, + F: Parser, + G: Parser, +{ + type Output = Vec<>::Output>; + type Error = >::Error; + + fn process( + &mut self, + mut i: I, + ) -> crate::PResult { + let mut res = OM::Output::bind(crate::lib::std::vec::Vec::new); + + match self + .parser + .process::>(i.clone()) + { Err(Err::Error(_)) => return Ok((i, res)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i1, o)) => { - res.push(o); + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); i = i1; } } loop { let len = i.input_len(); - match sep.parse(i.clone()) { + match self + .separator + .process::>(i.clone()) + { Err(Err::Error(_)) => return Ok((i, res)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i1, _)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList))); - } - - match f.parse(i1.clone()) { + match self + .parser + .process::>(i1.clone()) + { Err(Err::Error(_)) => return Ok((i, res)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i2, o)) => { - res.push(o); + // infinite loop check: the parser must always consume + if i2.input_len() == len { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::SeparatedList) + }))); + } + + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); + i = i2; } } @@ -274,7 +451,7 @@ /// Alternates between two parsers to produce a list of elements until [`Err::Error`]. /// -/// Fails if the element parser does not produce at least one element.$ +/// Fails if the element parser does not produce at least one element. /// /// This stops when either parser returns [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see /// [`cut`][crate::combinator::cut]. @@ -283,12 +460,12 @@ /// * `sep` Parses the separator between list elements. /// * `f` Parses the elements of the list. /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::separated_list1; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// separated_list1(tag("|"), tag("abc"))(s) +/// separated_list1(tag("|"), tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); @@ -299,44 +476,82 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn separated_list1( - mut sep: G, - mut f: F, -) -> impl FnMut(I) -> IResult, E> -where - I: Clone + InputLength, - F: Parser, - G: Parser, +pub fn separated_list1( + separator: G, + parser: F, +) -> impl Parser>::Output>, Error = E> +where + I: Clone + Input, + F: Parser, + G: Parser, E: ParseError, { - move |mut i: I| { - let mut res = Vec::new(); + SeparatedList1 { parser, separator } +} - // Parse the first element - match f.parse(i.clone()) { +#[cfg(feature = "alloc")] +/// Parser implementation for the [separated_list1] combinator +pub struct SeparatedList1 { + parser: F, + separator: G, +} + +#[cfg(feature = "alloc")] +impl, F, G> Parser for SeparatedList1 +where + I: Clone + Input, + F: Parser, + G: Parser, +{ + type Output = Vec<>::Output>; + type Error = >::Error; + + fn process( + &mut self, + mut i: I, + ) -> crate::PResult { + let mut res = OM::Output::bind(crate::lib::std::vec::Vec::new); + + match self.parser.process::(i.clone()) { Err(e) => return Err(e), Ok((i1, o)) => { - res.push(o); + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); i = i1; } } loop { let len = i.input_len(); - match sep.parse(i.clone()) { + match self + .separator + .process::>(i.clone()) + { Err(Err::Error(_)) => return Ok((i, res)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i1, _)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList))); - } - - match f.parse(i1.clone()) { + match self + .parser + .process::>(i1.clone()) + { Err(Err::Error(_)) => return Ok((i, res)), - Err(e) => return Err(e), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), Ok((i2, o)) => { - res.push(o); + // infinite loop check: the parser must always consume + if i2.input_len() == len { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::SeparatedList) + }))); + } + + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); i = i2; } } @@ -361,12 +576,12 @@ /// to prevent going into an infinite loop. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::many_m_n; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// many_m_n(0, 2, tag("abc"))(s) +/// many_m_n(0, 2, tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -377,39 +592,74 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn many_m_n( +pub fn many_m_n( min: usize, max: usize, - mut parse: F, -) -> impl FnMut(I) -> IResult, E> + parser: F, +) -> impl Parser>::Output>, Error = E> where - I: Clone + InputLength, - F: Parser, + I: Clone + Input, + F: Parser, E: ParseError, { - move |mut input: I| { - if min > max { - return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN))); + ManyMN { parser, min, max } +} + +#[cfg(feature = "alloc")] +/// Parser implementation for the [many_m_n] combinator +pub struct ManyMN { + parser: F, + min: usize, + max: usize, +} + +#[cfg(feature = "alloc")] +impl Parser for ManyMN +where + I: Clone + Input, + F: Parser, +{ + type Output = Vec<>::Output>; + type Error = >::Error; + + fn process( + &mut self, + mut input: I, + ) -> crate::PResult { + if self.min > self.max { + return Err(Err::Failure(>::Error::from_error_kind( + input, + ErrorKind::ManyMN, + ))); } - let max_initial_capacity = - MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); - let mut res = crate::lib::std::vec::Vec::with_capacity(min.min(max_initial_capacity)); - for count in 0..max { + let max_initial_capacity = MAX_INITIAL_CAPACITY_BYTES + / crate::lib::std::mem::size_of::<>::Output>().max(1); + let mut res = OM::Output::bind(|| { + crate::lib::std::vec::Vec::with_capacity(self.min.min(max_initial_capacity)) + }); + for count in 0..self.max { let len = input.input_len(); - match parse.parse(input.clone()) { + match self.parser.process::(input.clone()) { Ok((tail, value)) => { // infinite loop check: the parser must always consume if tail.input_len() == len { - return Err(Err::Error(E::from_error_kind(input, ErrorKind::ManyMN))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::ManyMN) + }))); } - res.push(value); + res = OM::Output::combine(res, value, |mut res, value| { + res.push(value); + res + }); input = tail; } Err(Err::Error(e)) => { - if count < min { - return Err(Err::Error(E::append(input, ErrorKind::ManyMN, e))); + if count < self.min { + return Err(Err::Error(OM::Error::map(e, |e| { + >::Error::append(input, ErrorKind::ManyMN, e) + }))); } else { return Ok((input, res)); } @@ -436,12 +686,12 @@ /// return an error, to prevent going into an infinite loop /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::many0_count; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, usize> { -/// many0_count(tag("abc"))(s) +/// many0_count(tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", 2))); @@ -449,33 +699,56 @@ /// assert_eq!(parser("123123"), Ok(("123123", 0))); /// assert_eq!(parser(""), Ok(("", 0))); /// ``` -pub fn many0_count(mut f: F) -> impl FnMut(I) -> IResult +pub fn many0_count(parser: F) -> impl Parser where - I: Clone + InputLength, - F: Parser, + I: Clone + Input, + F: Parser, E: ParseError, { - move |i: I| { - let mut input = i; + Many0Count { parser } +} + +/// Parser implementation for the [many0_count] combinator +pub struct Many0Count { + parser: F, +} + +impl Parser for Many0Count +where + I: Clone + Input, + F: Parser, +{ + type Output = usize; + type Error = >::Error; + + fn process( + &mut self, + mut input: I, + ) -> crate::PResult { let mut count = 0; loop { let input_ = input.clone(); let len = input.input_len(); - match f.parse(input_) { + match self + .parser + .process::>(input_) + { Ok((i, _)) => { // infinite loop check: the parser must always consume if i.input_len() == len { - return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0Count))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Many0Count) + }))); } input = i; count += 1; } - Err(Err::Error(_)) => return Ok((input, count)), - - Err(e) => return Err(e), + Err(Err::Error(_)) => return Ok((input, OM::Output::bind(|| count))), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)), } } } @@ -494,12 +767,12 @@ /// to prevent going into an infinite loop. /// /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::many1_count; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, usize> { -/// many1_count(tag("abc"))(s) +/// many1_count(tag("abc")).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", 2))); @@ -507,36 +780,68 @@ /// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1Count)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1Count)))); /// ``` -pub fn many1_count(mut f: F) -> impl FnMut(I) -> IResult +pub fn many1_count(parser: F) -> impl Parser where - I: Clone + InputLength, - F: Parser, + I: Clone + Input, + F: Parser, E: ParseError, { - move |i: I| { - let i_ = i.clone(); - match f.parse(i_) { - Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count))), - Err(i) => Err(i), - Ok((i1, _)) => { - let mut count = 1; - let mut input = i1; + Many1Count { parser } +} + +/// Parser implementation for the [many1_count] combinator +pub struct Many1Count { + parser: F, +} + +impl Parser for Many1Count +where + I: Clone + Input, + F: Parser, +{ + type Output = usize; + type Error = >::Error; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let mut count = 0; + + match self + .parser + .process::>(input.clone()) + { + Err(Err::Error(_)) => Err(Err::Error(OM::Error::bind(move || { + >::Error::from_error_kind(input, ErrorKind::Many1Count) + }))), + Err(Err::Failure(e)) => Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), + Ok((mut input, _)) => { + count += 1; loop { - let len = input.input_len(); let input_ = input.clone(); - match f.parse(input_) { - Err(Err::Error(_)) => return Ok((input, count)), - Err(e) => return Err(e), + let len = input.input_len(); + match self + .parser + .process::>(input_) + { Ok((i, _)) => { // infinite loop check: the parser must always consume if i.input_len() == len { - return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Many1Count) + }))); } - count += 1; input = i; + count += 1; } + + Err(Err::Error(_)) => return Ok((input, OM::Output::bind(|| count))), + Err(Err::Failure(e)) => return Err(Err::Failure(e)), + Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)), } } } @@ -550,12 +855,12 @@ /// * `f` The parser to apply. /// * `count` How often to apply the parser. /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::count; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, Vec<&str>> { -/// count(tag("abc"), 2)(s) +/// count(tag("abc"), 2).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -566,27 +871,55 @@ /// ``` #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -pub fn count(mut f: F, count: usize) -> impl FnMut(I) -> IResult, E> +pub fn count( + parser: F, + count: usize, +) -> impl Parser>::Output>, Error = >::Error> where - I: Clone + PartialEq, - F: Parser, - E: ParseError, + I: Clone, + F: Parser, +{ + Count { parser, count } +} + +#[cfg(feature = "alloc")] +/// Parser implementation for the [count] combinator +pub struct Count { + parser: F, + count: usize, +} + +#[cfg(feature = "alloc")] +impl Parser for Count +where + I: Clone, + F: Parser, { - move |i: I| { + type Output = Vec<>::Output>; + type Error = >::Error; + + fn process(&mut self, i: I) -> crate::PResult { let mut input = i.clone(); - let max_initial_capacity = - MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); - let mut res = crate::lib::std::vec::Vec::with_capacity(count.min(max_initial_capacity)); + let max_initial_capacity = MAX_INITIAL_CAPACITY_BYTES + / crate::lib::std::mem::size_of::<>::Output>().max(1); + let mut res = OM::Output::bind(|| { + crate::lib::std::vec::Vec::with_capacity(self.count.min(max_initial_capacity)) + }); - for _ in 0..count { + for _ in 0..self.count { let input_ = input.clone(); - match f.parse(input_) { + match self.parser.process::(input_) { Ok((i, o)) => { - res.push(o); + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); input = i; } Err(Err::Error(e)) => { - return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + return Err(Err::Error(OM::Error::map(e, |e| { + >::Error::append(i, ErrorKind::Count, e) + }))); } Err(e) => { return Err(e); @@ -606,13 +939,13 @@ /// * `f` The parser to apply. /// * `buf` The slice to fill /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::fill; /// use nom::bytes::complete::tag; /// /// fn parser(s: &str) -> IResult<&str, [&str; 2]> { /// let mut buf = ["", ""]; -/// let (rest, ()) = fill(tag("abc"), &mut buf)(s)?; +/// let (rest, ()) = fill(tag("abc"), &mut buf).parse(s)?; /// Ok((rest, buf)) /// } /// @@ -622,24 +955,46 @@ /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); /// assert_eq!(parser("abcabcabc"), Ok(("abc", ["abc", "abc"]))); /// ``` -pub fn fill<'a, I, O, E, F>(f: F, buf: &'a mut [O]) -> impl FnMut(I) -> IResult + 'a +pub fn fill<'a, I, E, F>( + parser: F, + buf: &'a mut [>::Output], +) -> impl Parser + 'a where - I: Clone + PartialEq, - F: Fn(I) -> IResult + 'a, + I: Clone, + F: Parser + 'a, E: ParseError, { - move |i: I| { + Fill { parser, buf } +} + +/// Parser implementation for the [fill] combinator +pub struct Fill<'a, F, O> { + parser: F, + buf: &'a mut [O], +} + +impl<'a, I, F, O> Parser for Fill<'a, F, O> +where + I: Clone, + F: Parser, +{ + type Output = (); + type Error = >::Error; + + fn process(&mut self, i: I) -> crate::PResult { let mut input = i.clone(); - for elem in buf.iter_mut() { + for elem in self.buf.iter_mut() { let input_ = input.clone(); - match f(input_) { + match self.parser.process::(input_) { Ok((i, o)) => { - *elem = o; + OM::Output::map(o, |o| *elem = o); input = i; } Err(Err::Error(e)) => { - return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + return Err(Err::Error(OM::Error::map(e, |e| { + >::Error::append(i, ErrorKind::Count, e) + }))); } Err(e) => { return Err(e); @@ -647,7 +1002,7 @@ } } - Ok((input, ())) + Ok((input, OM::Output::bind(|| ()))) } } @@ -666,7 +1021,7 @@ /// return an error, to prevent going into an infinite loop /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::fold_many0; /// use nom::bytes::complete::tag; /// @@ -678,7 +1033,7 @@ /// acc.push(item); /// acc /// } -/// )(s) +/// ).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -686,33 +1041,61 @@ /// assert_eq!(parser("123123"), Ok(("123123", vec![]))); /// assert_eq!(parser(""), Ok(("", vec![]))); /// ``` -pub fn fold_many0( - mut f: F, - mut init: H, - mut g: G, -) -> impl FnMut(I) -> IResult -where - I: Clone + InputLength, - F: Parser, - G: FnMut(R, O) -> R, +pub fn fold_many0( + parser: F, + init: H, + g: G, +) -> impl Parser +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, H: FnMut() -> R, E: ParseError, { - move |i: I| { - let mut res = init(); + FoldMany0 { + parser, + g, + init, + r: PhantomData, + } +} + +/// Parser implementation for the [fold_many0] combinator +pub struct FoldMany0 { + parser: F, + g: G, + init: Init, + r: PhantomData, +} + +impl Parser for FoldMany0 +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, + Init: FnMut() -> R, +{ + type Output = R; + type Error = >::Error; + + fn process(&mut self, i: I) -> crate::PResult { + let mut res = OM::Output::bind(|| (self.init)()); let mut input = i; loop { let i_ = input.clone(); let len = input.input_len(); - match f.parse(i_) { + match self.parser.process::(i_) { Ok((i, o)) => { // infinite loop check: the parser must always consume if i.input_len() == len { - return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Many0) + }))); } - res = g(res, o); + res = OM::Output::combine(res, o, |res, o| (self.g)(res, o)); input = i; } Err(Err::Error(_)) => { @@ -742,7 +1125,7 @@ /// to prevent going into an infinite loop. /// /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::multi::fold_many1; /// use nom::bytes::complete::tag; /// @@ -754,7 +1137,7 @@ /// acc.push(item); /// acc /// } -/// )(s) +/// ).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -762,49 +1145,80 @@ /// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1)))); /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1)))); /// ``` -pub fn fold_many1( - mut f: F, - mut init: H, - mut g: G, -) -> impl FnMut(I) -> IResult -where - I: Clone + InputLength, - F: Parser, - G: FnMut(R, O) -> R, +pub fn fold_many1( + parser: F, + init: H, + g: G, +) -> impl Parser +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, H: FnMut() -> R, E: ParseError, { - move |i: I| { - let _i = i.clone(); - let init = init(); - match f.parse(_i) { - Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1))), + FoldMany1 { + parser, + g, + init, + r: PhantomData, + } +} + +/// Parser implementation for the [fold_many1] combinator +pub struct FoldMany1 { + parser: F, + g: G, + init: Init, + r: PhantomData, +} + +impl Parser for FoldMany1 +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, + Init: FnMut() -> R, +{ + type Output = R; + type Error = >::Error; + + fn process(&mut self, i: I) -> crate::PResult { + let mut res = OM::Output::bind(|| (self.init)()); + let input = i.clone(); + + match self.parser.process::(input) { + Err(Err::Error(_)) => Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(i, ErrorKind::Many1) + }))), Err(e) => Err(e), Ok((i1, o1)) => { - let mut acc = g(init, o1); - let mut input = i1; + res = OM::Output::combine(res, o1, |res, o| (self.g)(res, o)); + let mut input = i1; loop { - let _input = input.clone(); + let i_ = input.clone(); let len = input.input_len(); - match f.parse(_input) { - Err(Err::Error(_)) => { - break; - } - Err(e) => return Err(e), + match self.parser.process::(i_) { Ok((i, o)) => { // infinite loop check: the parser must always consume if i.input_len() == len { - return Err(Err::Failure(E::from_error_kind(i, ErrorKind::Many1))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Many1) + }))); } - acc = g(acc, o); + res = OM::Output::combine(res, o, |res, o| (self.g)(res, o)); input = i; } + Err(Err::Error(_)) => { + return Ok((input, res)); + } + Err(e) => { + return Err(e); + } } } - - Ok((input, acc)) } } } @@ -828,7 +1242,7 @@ /// to prevent going into an infinite loop. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::multi::fold_many_m_n; /// use nom::bytes::complete::tag; /// @@ -842,7 +1256,7 @@ /// acc.push(item); /// acc /// } -/// )(s) +/// ).parse(s) /// } /// /// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); @@ -851,42 +1265,80 @@ /// assert_eq!(parser(""), Ok(("", vec![]))); /// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); /// ``` -pub fn fold_many_m_n( +pub fn fold_many_m_n( min: usize, max: usize, - mut parse: F, - mut init: H, - mut fold: G, -) -> impl FnMut(I) -> IResult -where - I: Clone + InputLength, - F: Parser, - G: FnMut(R, O) -> R, + parser: F, + init: H, + g: G, +) -> impl Parser +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, H: FnMut() -> R, E: ParseError, { - move |mut input: I| { - if min > max { - return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN))); + FoldManyMN { + parser, + g, + init, + min, + max, + r: PhantomData, + } +} + +/// Parser implementation for the [fold_many_m_n] combinator +pub struct FoldManyMN { + parser: F, + g: G, + init: Init, + r: PhantomData, + min: usize, + max: usize, +} + +impl Parser for FoldManyMN +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, + Init: FnMut() -> R, +{ + type Output = R; + type Error = >::Error; + + fn process( + &mut self, + mut input: I, + ) -> crate::PResult { + if self.min > self.max { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::ManyMN) + }))); } - let mut acc = init(); - for count in 0..max { + let mut res = OM::Output::bind(|| (self.init)()); + for count in 0..self.max { let len = input.input_len(); - match parse.parse(input.clone()) { + match self.parser.process::(input.clone()) { Ok((tail, value)) => { // infinite loop check: the parser must always consume if tail.input_len() == len { - return Err(Err::Error(E::from_error_kind(tail, ErrorKind::ManyMN))); + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(tail, ErrorKind::ManyMN) + }))); } - acc = fold(acc, value); + res = OM::Output::combine(res, value, |res, o| (self.g)(res, o)); input = tail; } - //FInputXMError: handle failure properly Err(Err::Error(err)) => { - if count < min { - return Err(Err::Error(E::append(input, ErrorKind::ManyMN, err))); + if count < self.min { + return Err(Err::Error(OM::Error::map(err, |err| { + >::Error::append(input, ErrorKind::ManyMN, err) + }))); } else { break; } @@ -895,7 +1347,7 @@ } } - Ok((input, acc)) + Ok((input, res)) } } @@ -906,39 +1358,26 @@ /// # Arguments /// * `f` The parser to apply. /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; /// use nom::number::complete::be_u16; /// use nom::multi::length_data; /// use nom::bytes::complete::tag; /// /// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// length_data(be_u16)(s) +/// length_data(be_u16).parse(s) /// } /// /// assert_eq!(parser(b"\x00\x03abcefg"), Ok((&b"efg"[..], &b"abc"[..]))); /// assert_eq!(parser(b"\x00\x03a"), Err(Err::Incomplete(Needed::new(2)))); /// ``` -pub fn length_data(mut f: F) -> impl FnMut(I) -> IResult +pub fn length_data(f: F) -> impl Parser where - I: InputLength + InputTake, - N: ToUsize, - F: Parser, + I: Input, + >::Output: ToUsize, + F: Parser, E: ParseError, { - move |i: I| { - let (i, length) = f.parse(i)?; - - let length: usize = length.to_usize(); - - if let Some(needed) = length - .checked_sub(i.input_len()) - .and_then(NonZeroUsize::new) - { - Err(Err::Incomplete(Needed::Size(needed))) - } else { - Ok(i.take_split(length)) - } - } + f.flat_map(|size| take(size)) } /// Gets a number from the first parser, @@ -950,29 +1389,67 @@ /// * `f` The parser to apply. /// * `g` The parser to apply on the subslice. /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::number::complete::be_u16; /// use nom::multi::length_value; /// use nom::bytes::complete::tag; /// /// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> { -/// length_value(be_u16, tag("abc"))(s) +/// length_value(be_u16, tag("abc")).parse(s) /// } /// /// assert_eq!(parser(b"\x00\x03abcefg"), Ok((&b"efg"[..], &b"abc"[..]))); /// assert_eq!(parser(b"\x00\x03123123"), Err(Err::Error(Error::new(&b"123"[..], ErrorKind::Tag)))); /// assert_eq!(parser(b"\x00\x03a"), Err(Err::Incomplete(Needed::new(2)))); /// ``` -pub fn length_value(mut f: F, mut g: G) -> impl FnMut(I) -> IResult +pub fn length_value( + f: F, + g: G, +) -> impl Parser>::Output, Error = E> +where + I: Clone + Input, + >::Output: ToUsize, + F: Parser, + G: Parser, + E: ParseError, +{ + /*f.flat_map(|size| { + println!("got size: {size}"); + take(size) + }) + .and_then(g)*/ + LengthValue { + length: f, + parser: g, + e: PhantomData, + } +} + +/// Parser implementation for the [length_value] combinator +pub struct LengthValue { + length: F, + parser: G, + e: PhantomData, +} + +impl Parser for LengthValue where - I: Clone + InputLength + InputTake, - N: ToUsize, - F: Parser, - G: Parser, + I: Clone + Input, + F: Parser, + G: Parser, + >::Output: ToUsize, E: ParseError, { - move |i: I| { - let (i, length) = f.parse(i)?; + type Output = >::Output; + type Error = E; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let (i, length) = self + .length + .process::>(input)?; let length: usize = length.to_usize(); @@ -983,8 +1460,10 @@ Err(Err::Incomplete(Needed::Size(needed))) } else { let (rest, i) = i.take_split(length); - match g.parse(i.clone()) { - Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))), + match self.parser.process::(i.clone()) { + Err(Err::Incomplete(_)) => Err(Err::Error(OM::Error::bind(|| { + E::from_error_kind(i, ErrorKind::Complete) + }))), Err(e) => Err(e), Ok((_, o)) => Ok((rest, o)), } @@ -998,7 +1477,7 @@ /// * `f` The parser to apply to obtain the count. /// * `g` The parser to apply repeatedly. /// ```rust -/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; /// use nom::number::complete::u8; /// use nom::multi::length_count; /// use nom::bytes::complete::tag; @@ -1008,35 +1487,254 @@ /// length_count(map(u8, |i| { /// println!("got number: {}", i); /// i -/// }), tag("abc"))(s) +/// }), tag("abc")).parse(s) /// } /// /// assert_eq!(parser(&b"\x02abcabcabc"[..]), Ok(((&b"abc"[..], vec![&b"abc"[..], &b"abc"[..]])))); /// assert_eq!(parser(b"\x03123123123"), Err(Err::Error(Error::new(&b"123123123"[..], ErrorKind::Tag)))); /// ``` #[cfg(feature = "alloc")] -pub fn length_count(mut f: F, mut g: G) -> impl FnMut(I) -> IResult, E> +pub fn length_count( + f: F, + g: G, +) -> impl Parser>::Output>, Error = E> where I: Clone, - N: ToUsize, - F: Parser, - G: Parser, + >::Output: ToUsize, + F: Parser, + G: Parser, E: ParseError, { - move |i: I| { - let (i, count) = f.parse(i)?; - let mut input = i.clone(); - let mut res = Vec::new(); + LengthCount { + length: f, + parser: g, + e: PhantomData, + } +} - for _ in 0..count.to_usize() { - let input_ = input.clone(); - match g.parse(input_) { - Ok((i, o)) => { - res.push(o); - input = i; +#[cfg(feature = "alloc")] +/// Parser implementation for the [length_count] combinator +pub struct LengthCount { + length: F, + parser: G, + e: PhantomData, +} + +#[cfg(feature = "alloc")] +impl Parser for LengthCount +where + I: Clone, + F: Parser, + G: Parser, + >::Output: ToUsize, + E: ParseError, +{ + type Output = Vec<>::Output>; + type Error = E; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + match self + .length + .process::>(input) + { + Err(e) => Err(e), + Ok((i, count)) => { + let count = count.to_usize(); + let mut input = i.clone(); + let max_initial_capacity = MAX_INITIAL_CAPACITY_BYTES + / crate::lib::std::mem::size_of::<>::Output>().max(1); + let mut res = OM::Output::bind(|| { + crate::lib::std::vec::Vec::with_capacity(count.min(max_initial_capacity)) + }); + + for _ in 0..count { + let input_ = input.clone(); + match self.parser.process::(input_) { + Ok((i, o)) => { + res = OM::Output::combine(res, o, |mut res, o| { + res.push(o); + res + }); + input = i; + } + Err(Err::Error(e)) => { + return Err(Err::Error(OM::Error::map(e, |e| { + >::Error::append(i, ErrorKind::Count, e) + }))); + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input, res)) + } + } + } +} + +/// Repeats the embedded parser and collects the results in a type implementing `Extend + Default`. +/// Fails if the amount of time the embedded parser is run is not +/// within the specified range. +/// # Arguments +/// * `range` Constrains the number of iterations. +/// * A range without an upper bound `a..` is equivalent to a range of `a..=usize::MAX`. +/// * A single `usize` value is equivalent to `value..=value`. +/// * An empty range is invalid. +/// * `parse` The parser to apply. +/// +/// ```rust +/// # #[macro_use] extern crate nom; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; +/// use nom::multi::many; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// many(0..=2, tag("abc")).parse(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +/// +/// This is not limited to `Vec`, other collections like `HashMap` +/// can be used: +/// +/// ```rust +/// # #[macro_use] extern crate nom; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; +/// use nom::multi::many; +/// use nom::bytes::complete::{tag, take_while}; +/// use nom::sequence::{separated_pair, terminated}; +/// use nom::AsChar; +/// +/// use std::collections::HashMap; +/// +/// fn key_value(s: &str) -> IResult<&str, HashMap<&str, &str>> { +/// many(0.., terminated( +/// separated_pair( +/// take_while(AsChar::is_alpha), +/// tag("="), +/// take_while(AsChar::is_alpha) +/// ), +/// tag(";") +/// )).parse(s) +/// } +/// +/// assert_eq!( +/// key_value("a=b;c=d;"), +/// Ok(("", HashMap::from([("a", "b"), ("c", "d")]))) +/// ); +/// ``` +/// +/// If more control is needed on the default value, [fold] can +/// be used instead: +/// +/// ```rust +/// # #[macro_use] extern crate nom; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; +/// use nom::multi::fold; +/// use nom::bytes::complete::tag; +/// +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold( +/// 0..=4, +/// tag("abc"), +/// // preallocates a vector of the max size +/// || Vec::with_capacity(4), +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// ).parse(s) +/// } +/// +/// +/// assert_eq!(parser("abcabcabcabc"), Ok(("", vec!["abc", "abc", "abc", "abc"]))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn many( + range: G, + parser: F, +) -> impl Parser +where + I: Clone + Input, + F: Parser, + Collection: Extend<>::Output> + Default, + E: ParseError, + G: NomRange, +{ + Many { + parser, + range, + c: PhantomData, + } +} + +/// Parser implementation for the [many] combinator +pub struct Many { + parser: F, + range: R, + c: PhantomData, +} + +impl Parser for Many +where + I: Clone + Input, + F: Parser, + Collection: Extend<>::Output> + Default, + R: NomRange, +{ + type Output = Collection; + type Error = >::Error; + + fn process( + &mut self, + mut input: I, + ) -> crate::PResult { + if self.range.is_inverted() { + return Err(Err::Failure(>::Error::from_error_kind( + input, + ErrorKind::Many, + ))); + } + + let mut res = OM::Output::bind(Collection::default); + + for count in self.range.bounded_iter() { + let len = input.input_len(); + match self.parser.process::(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(input, ErrorKind::Many) + }))); + } + + res = OM::Output::combine(res, value, |mut res, value| { + res.extend(Some(value)); + res + }); + input = tail; } Err(Err::Error(e)) => { - return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + if !self.range.contains(&count) { + return Err(Err::Error(OM::Error::map(e, |e| { + >::Error::append(input, ErrorKind::Many, e) + }))); + } else { + return Ok((input, res)); + } } Err(e) => { return Err(e); @@ -1047,3 +1745,126 @@ Ok((input, res)) } } + +/// Applies a parser and accumulates the results using a given +/// function and initial value. +/// Fails if the amount of time the embedded parser is run is not +/// within the specified range. +/// +/// # Arguments +/// * `range` Constrains the number of iterations. +/// * A range without an upper bound `a..` allows the parser to run until it fails. +/// * A single `usize` value is equivalent to `value..=value`. +/// * An empty range is invalid. +/// * `parse` The parser to apply. +/// * `init` A function returning the initial value. +/// * `fold` The function that combines a result of `f` with +/// the current accumulator. +/// ```rust +/// # #[macro_use] extern crate nom; +/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser}; +/// use nom::multi::fold; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold( +/// 0..=2, +/// tag("abc"), +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// ).parse(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +pub fn fold( + range: J, + parser: F, + init: H, + fold: G, +) -> impl Parser +where + I: Clone + Input, + F: Parser, + G: FnMut(R, >::Output) -> R, + H: FnMut() -> R, + E: ParseError, + J: NomRange, +{ + Fold { + parser, + init, + fold, + range, + } +} + +/// Parser implementation for the [fold] combinator +pub struct Fold { + parser: F, + init: H, + fold: G, + range: Range, +} + +impl Parser for Fold +where + I: Clone + Input, + F: Parser, + G: FnMut(Res, >::Output) -> Res, + H: FnMut() -> Res, + Range: NomRange, +{ + type Output = Res; + type Error = >::Error; + + fn process( + &mut self, + mut input: I, + ) -> crate::PResult { + if self.range.is_inverted() { + return Err(Err::Failure(>::Error::from_error_kind( + input, + ErrorKind::Fold, + ))); + } + + let mut acc = OM::Output::bind(|| (self.init)()); + + for count in self.range.saturating_iter() { + let len = input.input_len(); + match self.parser.process::(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(Err::Error(OM::Error::bind(|| { + >::Error::from_error_kind(tail, ErrorKind::Fold) + }))); + } + + acc = OM::Output::combine(acc, value, |acc, value| (self.fold)(acc, value)); + input = tail; + } + Err(Err::Error(err)) => { + if !self.range.contains(&count) { + return Err(Err::Error(OM::Error::map(err, |err| { + >::Error::append(input, ErrorKind::Fold, err) + }))); + } else { + break; + } + } + Err(e) => return Err(e), + } + } + + Ok((input, acc)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/multi/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/multi/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/multi/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,31 +6,37 @@ internal::{Err, IResult, Needed}, lib::std::str::{self, FromStr}, number::streaming::{be_u16, be_u8}, - sequence::{pair, tuple}, + sequence::pair, + Parser, }; #[cfg(feature = "alloc")] use crate::{ lib::std::vec::Vec, multi::{ - count, fold_many0, fold_many1, fold_many_m_n, length_count, many0, many1, many_m_n, many_till, - separated_list0, separated_list1, + count, fold, fold_many0, fold_many1, fold_many_m_n, length_count, many, many0, many1, many_m_n, + many_till, separated_list0, separated_list1, }, }; #[test] #[cfg(feature = "alloc")] fn separated_list0_test() { + use core::num::NonZeroUsize; + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list0(tag(","), tag("abcd"))(i) + separated_list0(tag(","), tag("abcd")).parse(i) } fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list0(tag(","), tag(""))(i) + separated_list0(tag(","), tag("")).parse(i) } fn empty_sep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list0(tag(""), tag("abc"))(i) + separated_list0(tag(""), tag("abc")).parse(i) } fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list0(tag(".."), tag("abcd"))(i) + separated_list0(tag(".."), tag("abcd")).parse(i) + } + fn empty_both(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(""), tag("")).parse(i) } let a = &b"abcdef"[..]; @@ -50,13 +56,14 @@ assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new()))); let res3 = vec![&b""[..], &b""[..], &b""[..]]; assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3))); - let i_err_pos = &i[3..]; assert_eq!( empty_sep(i), - Err(Err::Error(error_position!( - i_err_pos, - ErrorKind::SeparatedList - ))) + Err(Err::Incomplete(Needed::Size(NonZeroUsize::new(3).unwrap()))) + ); + + assert_eq!( + empty_both(i), + Err(Err::Error(error_position!(i, ErrorKind::SeparatedList))) ); let res4 = vec![&b"abcd"[..], &b"abcd"[..]]; assert_eq!(multi(e), Ok((&b",ef"[..], res4))); @@ -70,10 +77,13 @@ #[cfg(feature = "alloc")] fn separated_list1_test() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list1(tag(","), tag("abcd"))(i) + separated_list1(tag(","), tag("abcd")).parse(i) } fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - separated_list1(tag(".."), tag("abcd"))(i) + separated_list1(tag(".."), tag("abcd")).parse(i) + } + fn empty_both(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(""), tag("")).parse(i) } let a = &b"abcdef"[..]; @@ -93,6 +103,10 @@ multi(c), Err(Err::Error(error_position!(c, ErrorKind::Tag))) ); + assert_eq!( + empty_both(f), + Err(Err::Error(error_position!(f, ErrorKind::SeparatedList))) + ); let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; assert_eq!(multi(d), Ok((&b",ef"[..], res3))); @@ -105,10 +119,10 @@ #[cfg(feature = "alloc")] fn many0_test() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(tag("abcd"))(i) + many0(tag("abcd")).parse(i) } fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(tag(""))(i) + many0(tag("")).parse(i) } assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); @@ -133,7 +147,7 @@ #[cfg(feature = "alloc")] fn many1_test() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many1(tag("abcd"))(i) + many1(tag("abcd")).parse(i) } let a = &b"abcdef"[..]; @@ -155,8 +169,9 @@ #[test] #[cfg(feature = "alloc")] fn many_till_test() { + #[allow(clippy::type_complexity)] fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { - many_till(tag("abcd"), tag("efgh"))(i) + many_till(tag("abcd"), tag("efgh")).parse(i) } let a = b"abcdabcdefghabcd"; @@ -181,19 +196,18 @@ #[cfg(feature = "std")] fn infinite_many() { fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { - println!("input: {:?}", input); Err(Err::Error(error_position!(input, ErrorKind::Tag))) } // should not go into an infinite loop fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(tst)(i) + many0(tst).parse(i) } let a = &b"abcdef"[..]; assert_eq!(multi0(a), Ok((a, Vec::new()))); fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many1(tst)(i) + many1(tst).parse(i) } let a = &b"abcdef"[..]; assert_eq!( @@ -206,7 +220,7 @@ #[cfg(feature = "alloc")] fn many_m_n_test() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many_m_n(2, 4, tag("Abcd"))(i) + many_m_n(2, 4, tag("Abcd")).parse(i) } let a = &b"Abcdef"[..]; @@ -233,7 +247,7 @@ fn count_test() { const TIMES: usize = 2; fn cnt_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - count(tag("abc"), TIMES)(i) + count(tag("abc"), TIMES).parse(i) } assert_eq!( @@ -267,7 +281,7 @@ fn count_zero() { const TIMES: usize = 0; fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - count(tag("abc"), TIMES)(i) + count(tag("abc"), TIMES).parse(i) } let done = &b"abcabcabcdef"[..]; @@ -301,7 +315,7 @@ assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2))); } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct NilError; impl From<(I, ErrorKind)> for NilError { @@ -322,14 +336,14 @@ fn number(i: &[u8]) -> IResult<&[u8], u32> { use crate::combinator::map_res; - map_res(map_res(digit, str::from_utf8), FromStr::from_str)(i) + map_res(map_res(digit, str::from_utf8), FromStr::from_str).parse(i) } #[test] #[cfg(feature = "alloc")] fn length_count_test() { fn cnt(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - length_count(number, tag("abc"))(i) + length_count(number, tag("abc")).parse(i) } assert_eq!( @@ -351,7 +365,7 @@ #[test] fn length_data_test() { fn take(i: &[u8]) -> IResult<&[u8], &[u8]> { - length_data(number)(i) + length_data(number).parse(i) } assert_eq!( @@ -369,10 +383,10 @@ #[test] fn length_value_test() { fn length_value_1(i: &[u8]) -> IResult<&[u8], u16> { - length_value(be_u8, be_u16)(i) + length_value(be_u8, be_u16).parse(i) } fn length_value_2(i: &[u8]) -> IResult<&[u8], (u8, u8)> { - length_value(be_u8, tuple((be_u8, be_u8)))(i) + length_value(be_u8, (be_u8, be_u8)).parse(i) } let i1 = [0, 5, 6]; @@ -412,10 +426,10 @@ acc } fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i) + fold_many0(tag("abcd"), Vec::new, fold_into_vec).parse(i) } fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - fold_many0(tag(""), Vec::new, fold_into_vec)(i) + fold_many0(tag(""), Vec::new, fold_into_vec).parse(i) } assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); @@ -444,7 +458,7 @@ acc } fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i) + fold_many1(tag("abcd"), Vec::new, fold_into_vec).parse(i) } let a = &b"abcdef"[..]; @@ -471,7 +485,7 @@ acc } fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i) + fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec).parse(i) } let a = &b"Abcdef"[..]; @@ -496,7 +510,7 @@ #[test] fn many0_count_test() { fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> { - many0_count(pair(digit, tag(",")))(i) + many0_count(pair(digit, tag(","))).parse(i) } assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1))); @@ -514,7 +528,7 @@ #[test] fn many1_count_test() { fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> { - many1_count(pair(digit, tag(",")))(i) + many1_count(pair(digit, tag(","))).parse(i) } assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); @@ -532,3 +546,314 @@ ))) ); } + +#[test] +#[cfg(feature = "alloc")] +fn many_test() { + // should not go into an infinite loop + fn many_error_0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + Err(Err::Error(error_position!(input, ErrorKind::Tag))) + } + many(0.., tst).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!(many_error_0(a), Ok((a, Vec::new()))); + + fn many_error_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + Err(Err::Error(error_position!(input, ErrorKind::Tag))) + } + many(1.., tst).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!( + many_error_1(a), + Err(Err::Error(error_position!(a, ErrorKind::Tag))) + ); + + fn many_error(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(0.., tag("")).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!( + many_error(a), + Err(Err::Error(error_position!(a, ErrorKind::Many))) + ); + + fn many_invalid(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(crate::lib::std::ops::Range::default(), tag("a")).parse(i) + } + + let a = &b"a"[..]; + let b = &b"b"[..]; + assert_eq!( + many_invalid(a), + Err(Err::Failure(error_position!(a, ErrorKind::Many))) + ); + assert_eq!( + many_invalid(b), + Err(Err::Failure(error_position!(b, ErrorKind::Many))) + ); + + fn many_any(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(0.., tag("abcd")).parse(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + let e = &b"abcd"[..]; + let f = &b""[..]; + assert_eq!(many_any(a), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); + assert_eq!( + many_any(b), + Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!(many_any(c), Ok((&b"azerty"[..], Vec::new()))); + assert_eq!(many_any(d), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!(many_any(e), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!(many_any(f), Err(Err::Incomplete(Needed::new(4)))); + + fn many_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(1.., tag("abcd")).parse(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + let res1 = vec![&b"abcd"[..]]; + assert_eq!(many_1(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(many_1(b), Ok((&b"efgh"[..], res2))); + assert_eq!( + many_1(c), + Err(Err::Error(error_position!(c, ErrorKind::Tag))) + ); + assert_eq!(many_1(d), Err(Err::Incomplete(Needed::new(2)))); + + fn many_m_n(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(2..=4, tag("Abcd")).parse(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + assert_eq!( + many_m_n(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(many_m_n(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(many_m_n(c), Ok((&b"efgh"[..], res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(many_m_n(d), Ok((&b"Abcdefgh"[..], res3))); + assert_eq!(many_m_n(e), Err(Err::Incomplete(Needed::new(2)))); + + fn many_fixed(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(2, tag("Abcd")).parse(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAb"[..]; + assert_eq!( + many_fixed(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(many_fixed(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(many_fixed(c), Ok((&b"AbcdAbcdefgh"[..], res2))); + assert_eq!(many_fixed(d), Err(Err::Incomplete(Needed::new(2)))); + + fn multi_exclusive(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(0..2, tag("Abcd")).parse(i) + } + + let a = &b"AbcdAbcdAbcd"[..]; + let b = &b"AAA"[..]; + let res1 = vec![&b"Abcd"[..]]; + assert_eq!(multi_exclusive(a), Ok((&b"AbcdAbcd"[..], res1))); + let res2 = vec![]; + assert_eq!(multi_exclusive(b), Ok((&b"AAA"[..], res2))); + + fn many_never(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many(0..=0, tag("A")).parse(i) + } + + let a = &b"AA"[..]; + let b = &b"B"[..]; + assert_eq!(many_never(a), Ok((&b"AA"[..], Vec::new()))); + assert_eq!(many_never(b), Ok((&b"B"[..], Vec::new()))); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_test() { + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + + // should not go into an infinite loop + fn fold_error_0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + Err(Err::Error(error_position!(input, ErrorKind::Tag))) + } + fold(0.., tst, Vec::new, fold_into_vec).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!(fold_error_0(a), Ok((a, Vec::new()))); + + fn fold_error_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + Err(Err::Error(error_position!(input, ErrorKind::Tag))) + } + fold(1.., tst, Vec::new, fold_into_vec).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!( + fold_error_1(a), + Err(Err::Error(error_position!(a, ErrorKind::Tag))) + ); + + fn fold_error(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(0.., tag(""), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"abcdef"[..]; + assert_eq!( + fold_error(a), + Err(Err::Error(error_position!(a, ErrorKind::Fold))) + ); + + fn fold_invalid(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold( + crate::lib::std::ops::Range::default(), + tag("a"), + Vec::new, + fold_into_vec, + ) + .parse(i) + } + + let a = &b"a"[..]; + let b = &b"b"[..]; + assert_eq!( + fold_invalid(a), + Err(Err::Failure(error_position!(a, ErrorKind::Fold))) + ); + assert_eq!( + fold_invalid(b), + Err(Err::Failure(error_position!(b, ErrorKind::Fold))) + ); + + fn fold_any(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(0.., tag("abcd"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + let e = &b"abcd"[..]; + let f = &b""[..]; + assert_eq!(fold_any(a), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); + assert_eq!( + fold_any(b), + Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!(fold_any(c), Ok((c, Vec::new()))); + assert_eq!(fold_any(d), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!(fold_any(e), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!(fold_any(f), Err(Err::Incomplete(Needed::new(4)))); + + fn fold_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(1.., tag("abcd"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + let res1 = vec![&b"abcd"[..]]; + assert_eq!(fold_1(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(fold_1(b), Ok((&b"efgh"[..], res2))); + assert_eq!( + fold_1(c), + Err(Err::Error(error_position!(c, ErrorKind::Tag))) + ); + assert_eq!(fold_1(d), Err(Err::Incomplete(Needed::new(2)))); + + fn fold_m_n(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(2..=4, tag("Abcd"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + assert_eq!( + fold_m_n(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(fold_m_n(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(fold_m_n(c), Ok((&b"efgh"[..], res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(fold_m_n(d), Ok((&b"Abcdefgh"[..], res3))); + assert_eq!(fold_m_n(e), Err(Err::Incomplete(Needed::new(2)))); + + fn fold_fixed(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(2, tag("Abcd"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAb"[..]; + assert_eq!( + fold_fixed(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(fold_fixed(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(fold_fixed(c), Ok((&b"AbcdAbcdefgh"[..], res2))); + assert_eq!(fold_fixed(d), Err(Err::Incomplete(Needed::new(2)))); + + fn fold_exclusive(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(0..2, tag("Abcd"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"AbcdAbcdAbcd"[..]; + let b = &b"AAA"[..]; + let res1 = vec![&b"Abcd"[..]]; + assert_eq!(fold_exclusive(a), Ok((&b"AbcdAbcd"[..], res1))); + let res2 = vec![]; + assert_eq!(fold_exclusive(b), Ok((&b"AAA"[..], res2))); + + fn fold_never(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold(0..=0, tag("A"), Vec::new, fold_into_vec).parse(i) + } + + let a = &b"AAA"[..]; + let b = &b"B"[..]; + assert_eq!(fold_never(a), Ok((&b"AAA"[..], Vec::new()))); + assert_eq!(fold_never(b), Ok((&b"B"[..], Vec::new()))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/complete.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,14 +4,12 @@ use crate::bytes::complete::tag; use crate::character::complete::{char, digit1, sign}; use crate::combinator::{cut, map, opt, recognize}; +use crate::error::ErrorKind; use crate::error::ParseError; -use crate::error::{make_error, ErrorKind}; use crate::internal::*; -use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; -use crate::sequence::{pair, tuple}; -use crate::traits::{ - AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice, -}; +use crate::lib::std::ops::{Add, Shl}; +use crate::sequence::pair; +use crate::traits::{AsBytes, AsChar, Compare, Input, Offset}; /// Recognizes an unsigned 1 byte integer. /// @@ -31,16 +29,9 @@ #[inline] pub fn be_u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + be_uint(input, 1) } /// Recognizes a big endian unsigned 2 bytes integer. @@ -61,19 +52,9 @@ #[inline] pub fn be_u16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 2; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u16; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u16; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 2) } /// Recognizes a big endian unsigned 3 byte integer. @@ -94,19 +75,9 @@ #[inline] pub fn be_u24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 3; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u32; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u32; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 3) } /// Recognizes a big endian unsigned 4 bytes integer. @@ -127,19 +98,9 @@ #[inline] pub fn be_u32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 4; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u32; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u32; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 4) } /// Recognizes a big endian unsigned 8 bytes integer. @@ -160,19 +121,9 @@ #[inline] pub fn be_u64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 8; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u64; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u64; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 8) } /// Recognizes a big endian unsigned 16 bytes integer. @@ -193,19 +144,18 @@ #[inline] pub fn be_u128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 16; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u128; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u128; - } + be_uint(input, 16) +} - Ok((input.slice(bound..), res)) - } +#[inline] +fn be_uint>(input: I, bound: usize) -> IResult +where + I: Input, + Uint: Default + Shl + Add + From, +{ + super::be_uint(bound).parse_complete(input) } /// Recognizes a signed 1 byte integer. @@ -226,7 +176,7 @@ #[inline] pub fn be_i8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u8.map(|x| x as i8).parse(input) } @@ -249,7 +199,7 @@ #[inline] pub fn be_i16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u16.map(|x| x as i16).parse(input) } @@ -272,7 +222,7 @@ #[inline] pub fn be_i24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { // Same as the unsigned version but we need to sign-extend manually here be_u24 @@ -304,7 +254,7 @@ #[inline] pub fn be_i32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u32.map(|x| x as i32).parse(input) } @@ -327,7 +277,7 @@ #[inline] pub fn be_i64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u64.map(|x| x as i64).parse(input) } @@ -350,7 +300,7 @@ #[inline] pub fn be_i128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u128.map(|x| x as i128).parse(input) } @@ -373,16 +323,9 @@ #[inline] pub fn le_u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + le_uint(input, 1) } /// Recognizes a little endian unsigned 2 bytes integer. @@ -403,19 +346,9 @@ #[inline] pub fn le_u16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 2; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u16; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u16) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 2) } /// Recognizes a little endian unsigned 3 byte integer. @@ -436,19 +369,9 @@ #[inline] pub fn le_u24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 3; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u32; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u32) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 3) } /// Recognizes a little endian unsigned 4 bytes integer. @@ -469,19 +392,9 @@ #[inline] pub fn le_u32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 4; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u32; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u32) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 4) } /// Recognizes a little endian unsigned 8 bytes integer. @@ -502,19 +415,9 @@ #[inline] pub fn le_u64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 8; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u64; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u64) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 8) } /// Recognizes a little endian unsigned 16 bytes integer. @@ -535,19 +438,18 @@ #[inline] pub fn le_u128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 16; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let mut res = 0u128; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u128) << (8 * index); - } + le_uint(input, 16) +} - Ok((input.slice(bound..), res)) - } +#[inline] +fn le_uint>(input: I, bound: usize) -> IResult +where + I: Input, + Uint: Default + Shl + Add + From, +{ + super::le_uint(bound).parse_complete(input) } /// Recognizes a signed 1 byte integer. @@ -568,7 +470,7 @@ #[inline] pub fn le_i8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u8.map(|x| x as i8).parse(input) } @@ -591,7 +493,7 @@ #[inline] pub fn le_i16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u16.map(|x| x as i16).parse(input) } @@ -614,7 +516,7 @@ #[inline] pub fn le_i24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { // Same as the unsigned version but we need to sign-extend manually here le_u24 @@ -646,7 +548,7 @@ #[inline] pub fn le_i32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u32.map(|x| x as i32).parse(input) } @@ -669,7 +571,7 @@ #[inline] pub fn le_i64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u64.map(|x| x as i64).parse(input) } @@ -692,7 +594,7 @@ #[inline] pub fn le_i128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u128.map(|x| x as i128).parse(input) } @@ -716,16 +618,9 @@ #[inline] pub fn u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Error(make_error(input, ErrorKind::Eof))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + super::u8().parse_complete(input) } /// Recognizes an unsigned 2 bytes integer @@ -754,18 +649,13 @@ /// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u16>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u16, - crate::number::Endianness::Little => le_u16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u16, - } + move |input| super::u16(endian).parse_complete(input) } /// Recognizes an unsigned 3 byte integer @@ -793,18 +683,13 @@ /// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u24>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u24, - crate::number::Endianness::Little => le_u24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u24, - } + move |input| super::u24(endian).parse_complete(input) } /// Recognizes an unsigned 4 byte integer @@ -832,18 +717,13 @@ /// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u32>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u32, - crate::number::Endianness::Little => le_u32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u32, - } + move |input| super::u32(endian).parse_complete(input) } /// Recognizes an unsigned 8 byte integer @@ -871,18 +751,13 @@ /// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u64>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u64, - crate::number::Endianness::Little => le_u64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u64, - } + move |input| super::u64(endian).parse_complete(input) } /// Recognizes an unsigned 16 byte integer @@ -910,18 +785,13 @@ /// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u128>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u128, - crate::number::Endianness::Little => le_u128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u128, - } + move |input| super::u128(endian).parse_complete(input) } /// Recognizes a signed 1 byte integer @@ -943,9 +813,9 @@ #[inline] pub fn i8>(i: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - u8.map(|x| x as i8).parse(i) + super::u8().map(|x| x as i8).parse_complete(i) } /// Recognizes a signed 2 byte integer @@ -973,18 +843,13 @@ /// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i16>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i16, - crate::number::Endianness::Little => le_i16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i16, - } + move |input| super::i16(endian).parse_complete(input) } /// Recognizes a signed 3 byte integer @@ -1012,18 +877,13 @@ /// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i24>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i24, - crate::number::Endianness::Little => le_i24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i24, - } + move |input| super::i24(endian).parse_complete(input) } /// Recognizes a signed 4 byte integer @@ -1051,18 +911,13 @@ /// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i32>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i32, - crate::number::Endianness::Little => le_i32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i32, - } + move |input| super::i32(endian).parse_complete(input) } /// Recognizes a signed 8 byte integer @@ -1090,18 +945,13 @@ /// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i64>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i64, - crate::number::Endianness::Little => le_i64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i64, - } + move |input| super::i64(endian).parse_complete(input) } /// Recognizes a signed 16 byte integer @@ -1129,18 +979,13 @@ /// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); /// ``` #[inline] -pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i128>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i128, - crate::number::Endianness::Little => le_i128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i128, - } + move |input| super::i128(endian).parse_complete(input) } /// Recognizes a big endian 4 bytes floating point number. @@ -1161,7 +1006,7 @@ #[inline] pub fn be_f32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match be_u32(input) { Err(e) => Err(e), @@ -1187,7 +1032,7 @@ #[inline] pub fn be_f64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match be_u64(input) { Err(e) => Err(e), @@ -1213,7 +1058,7 @@ #[inline] pub fn le_f32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match le_u32(input) { Err(e) => Err(e), @@ -1239,7 +1084,7 @@ #[inline] pub fn le_f64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match le_u64(input) { Err(e) => Err(e), @@ -1274,7 +1119,7 @@ #[inline] pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match endian { crate::number::Endianness::Big => be_f32, @@ -1313,7 +1158,7 @@ #[inline] pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match endian { crate::number::Endianness::Big => be_f64, @@ -1342,16 +1187,30 @@ /// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA)))); /// ``` #[inline] -pub fn hex_u32<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], u32, E> { - let (i, o) = crate::bytes::complete::is_a(&b"0123456789abcdefABCDEF"[..])(input)?; +pub fn hex_u32>(input: I) -> IResult +where + I: Input, + ::Item: AsChar, + I: AsBytes, +{ + let e: ErrorKind = ErrorKind::IsA; + let (i, o) = input.split_at_position1_complete( + |c| { + let c = c.as_char(); + !"0123456789abcdefABCDEF".contains(c) + }, + e, + )?; + // Do not parse more than 8 characters for a u32 - let (parsed, remaining) = if o.len() <= 8 { - (o, i) + let (remaining, parsed) = if o.input_len() <= 8 { + (i, o) } else { - (&input[..8], &input[8..]) + input.take_split(8) }; let res = parsed + .as_bytes() .iter() .rev() .enumerate() @@ -1385,39 +1244,31 @@ #[rustfmt::skip] pub fn recognize_float>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter, - ::Item: AsChar, - T: InputTakeAtPosition, - ::Item: AsChar, -{ - recognize( - tuple(( - opt(alt((char('+'), char('-')))), + T: Input, + ::Item: AsChar, +{ + recognize(( + opt(alt((char('+'), char('-')))), alt(( - map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), - map(tuple((char('.'), digit1)), |_| ()) + map((digit1, opt(pair(char('.'), opt(digit1)))), |_| ()), + map((char('.'), digit1), |_| ()) )), - opt(tuple(( + opt(( alt((char('e'), char('E'))), opt(alt((char('+'), char('-')))), cut(digit1) - ))) - )) - )(input) + )) + )).parse(input) } // workaround until issues with minimal-lexical are fixed #[doc(hidden)] pub fn recognize_float_or_exceptions>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter + InputTake + Compare<&'static str>, - ::Item: AsChar, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input + Compare<&'static str>, + ::Item: AsChar, { alt(( |i: T| { @@ -1432,14 +1283,15 @@ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, |i: T| { - crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) + crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, |i: T| { - crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) + crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, - ))(input) + )) + .parse(input) } /// Recognizes a floating point number in text format @@ -1451,18 +1303,15 @@ /// pub fn recognize_float_parts>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, T: Clone + Offset, - T: InputIter + InputTake, - ::Item: AsChar + Copy, - T: InputTakeAtPosition + InputLength, - ::Item: AsChar, + T: Input, + ::Item: AsChar, T: for<'a> Compare<&'a [u8]>, T: AsBytes, { let (i, sign) = sign(input.clone())?; - //let (i, zeroes) = take_while(|c: ::Item| c.as_char() == '0')(i)?; + //let (i, zeroes) = take_while(|c: ::Item| c.as_char() == '0')(i)?; let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') { Some(index) => i.take_split(index), None => i.take_split(i.input_len()), @@ -1479,13 +1328,13 @@ if integer.input_len() == 0 && zeroes.input_len() > 0 { // keep the last zero if integer is empty - integer = zeroes.slice(zeroes.input_len() - 1..); + integer = zeroes.take_from(zeroes.input_len() - 1); } - let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, opt_dot) = opt(tag(&b"."[..])).parse(i)?; let (i, fraction) = if opt_dot.is_none() { let i2 = i.clone(); - (i2, i.slice(..0)) + (i2, i.take(0)) } else { // match number, trim right zeroes let mut zero_count = 0usize; @@ -1503,6 +1352,7 @@ } } + #[allow(clippy::or_fun_call)] let position = position.unwrap_or(i.input_len()); let index = if zero_count == 0 { @@ -1513,7 +1363,7 @@ position - zero_count }; - (i.slice(position..), i.slice(..index)) + (i.take_from(position), i.take(index)) }; if integer.input_len() == 0 && fraction.input_len() == 0 { @@ -1522,13 +1372,13 @@ let i2 = i.clone(); let (i, e) = match i.as_bytes().iter().next() { - Some(b'e') => (i.slice(1..), true), - Some(b'E') => (i.slice(1..), true), + Some(b'e') => (i.take_from(1), true), + Some(b'E') => (i.take_from(1), true), _ => (i, false), }; let (i, exp) = if e { - cut(crate::character::complete::i32)(i)? + cut(crate::character::complete::i32).parse(i)? } else { (i2, 0) }; @@ -1557,13 +1407,10 @@ /// ``` pub fn float>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, T: Clone + Offset + ParseTo + Compare<&'static str>, - T: InputIter + InputLength + InputTake, - ::Item: AsChar + Copy, - ::IterElem: Clone, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, + ::Iter: Clone, T: AsBytes, T: for<'a> Compare<&'a [u8]>, { @@ -1610,13 +1457,10 @@ /// ``` pub fn double>(input: T) -> IResult where - T: Slice> + Slice> + Slice>, T: Clone + Offset + ParseTo + Compare<&'static str>, - T: InputIter + InputLength + InputTake, - ::Item: AsChar + Copy, - ::IterElem: Clone, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input, + ::Item: AsChar, + ::Iter: Clone, T: AsBytes, T: for<'a> Compare<&'a [u8]>, { @@ -1989,14 +1833,13 @@ println!("now parsing: {} -> {}", test, expected32); - let larger = format!("{}", test); - assert_parse!(recognize_float(&larger[..]), Ok(("", test))); + assert_parse!(recognize_float(test), Ok(("", test))); - assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32))); - assert_parse!(float(&larger[..]), Ok(("", expected32))); + assert_parse!(float(test.as_bytes()), Ok((&b""[..], expected32))); + assert_parse!(float(test), Ok(("", expected32))); - assert_parse!(double(larger.as_bytes()), Ok((&b""[..], expected64))); - assert_parse!(double(&larger[..]), Ok(("", expected64))); + assert_parse!(double(test.as_bytes()), Ok((&b""[..], expected64))); + assert_parse!(double(test), Ok(("", expected64))); } let remaining_exponent = "-1.234E-"; @@ -2010,8 +1853,9 @@ let (_i, inf) = float::<_, ()>("inf").unwrap(); assert!(inf.is_infinite()); - let (_i, inf) = float::<_, ()>("infinite").unwrap(); + let (i, inf) = float::<_, ()>("infinity").unwrap(); assert!(inf.is_infinite()); + assert!(i.is_empty()); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,20 @@ //! Parsers recognizing numbers +use core::{ + marker::PhantomData, + ops::{Add, Shl}, +}; + +use crate::{ + branch::alt, + character::{char, digit1}, + combinator::{cut, map, opt, recognize}, + error::{make_error, ErrorKind, ParseError}, + sequence::pair, + AsBytes, AsChar, Compare, Either, Emit, Err, Input, IsStreaming, Mode, Needed, Offset, OutputM, + Parser, +}; + pub mod complete; pub mod streaming; @@ -13,3 +28,1455 @@ /// Will match the host's endianness Native, } + +/// creates a big endian unsigned integer parser +/// +/// * `bound`: the number of bytes that will be read +/// * `Uint`: the output type +#[inline] +fn be_uint>(bound: usize) -> impl Parser +where + I: Input, + Uint: Default + Shl + Add + From, +{ + BeUint { + bound, + e: PhantomData, + u: PhantomData, + } +} + +/// Big endian unsigned integer parser +struct BeUint { + bound: usize, + e: PhantomData, + u: PhantomData, +} + +impl> Parser for BeUint +where + I: Input, + Uint: Default + Shl + Add + From, +{ + type Output = Uint; + type Error = E; + + #[inline(always)] + fn process( + &mut self, + input: I, + ) -> crate::PResult { + if input.input_len() < self.bound { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(self.bound - input.input_len()))) + } else { + Err(Err::Error(OM::Error::bind(|| { + make_error(input, ErrorKind::Eof) + }))) + } + } else { + let res = OM::Output::bind(|| { + let mut res = Uint::default(); + + // special case to avoid shift a byte with overflow + if self.bound > 1 { + for byte in input.iter_elements().take(self.bound) { + res = (res << 8) + byte.into(); + } + } else { + for byte in input.iter_elements().take(self.bound) { + res = byte.into(); + } + } + + res + }); + + Ok((input.take_from(self.bound), res)) + } + } +} + +/// Recognizes an unsigned 1 byte integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u8; +/// +/// let parser = |s| { +/// be_u8::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_u8>() -> impl Parser +where + I: Input, +{ + be_uint(1) +} + +/// Recognizes a big endian unsigned 2 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u16; +/// +/// let parser = |s| { +/// be_u16::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_u16>() -> impl Parser +where + I: Input, +{ + be_uint(2) +} + +/// Recognizes a big endian unsigned 3 byte integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u24; +/// +/// let parser = |s| { +/// be_u24::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn be_u24>() -> impl Parser +where + I: Input, +{ + be_uint(3) +} + +/// Recognizes a big endian unsigned 4 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u32; +/// +/// let parser = |s| { +/// be_u32::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_u32>() -> impl Parser +where + I: Input, +{ + be_uint(4) +} + +/// Recognizes a big endian unsigned 8 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u64; +/// +/// let parser = |s| { +/// be_u64::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_u64>() -> impl Parser +where + I: Input, +{ + be_uint(8) +} + +/// Recognizes a big endian unsigned 16 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_u128; +/// +/// let parser = |s| { +/// be_u128::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn be_u128>() -> impl Parser +where + I: Input, +{ + be_uint(16) +} + +/// Recognizes a signed 1 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i8; +/// +/// let mut parser = be_i8::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_i8>() -> impl Parser +where + I: Input, +{ + be_u8().map(|x| x as i8) +} + +/// Recognizes a big endian signed 2 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i16; +/// +/// let mut parser = be_i16::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn be_i16>() -> impl Parser +where + I: Input, +{ + be_u16().map(|x| x as i16) +} + +/// Recognizes a big endian signed 3 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i24; +/// +/// let mut parser = be_i24::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_i24>() -> impl Parser +where + I: Input, +{ + // Same as the unsigned version but we need to sign-extend manually here + be_u24().map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) +} + +/// Recognizes a big endian signed 4 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i32; +/// +/// let mut parser = be_i32::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(4)))); +/// ``` +#[inline] +pub fn be_i32>() -> impl Parser +where + I: Input, +{ + be_u32().map(|x| x as i32) +} + +/// Recognizes a big endian signed 8 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i64; +/// +/// let mut parser = be_i64::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607))); +/// assert_eq!(parser.parse(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_i64>() -> impl Parser +where + I: Input, +{ + be_u64().map(|x| x as i64) +} + +/// Recognizes a big endian signed 16 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_i128; +/// +/// let mut parser = be_i128::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); +/// assert_eq!(parser.parse(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn be_i128>() -> impl Parser +where + I: Input, +{ + be_u128().map(|x| x as i128) +} + +/// creates a little endian unsigned integer parser +/// +/// * `bound`: the number of bytes that will be read +/// * `Uint`: the output type +#[inline] +fn le_uint>(bound: usize) -> impl Parser +where + I: Input, + Uint: Default + Shl + Add + From, +{ + LeUint { + bound, + e: PhantomData, + u: PhantomData, + } +} + +/// Little endian unsigned integer parser +struct LeUint { + bound: usize, + e: PhantomData, + u: PhantomData, +} + +impl> Parser for LeUint +where + I: Input, + Uint: Default + Shl + Add + From, +{ + type Output = Uint; + type Error = E; + + #[inline(always)] + fn process( + &mut self, + input: I, + ) -> crate::PResult { + if input.input_len() < self.bound { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(self.bound - input.input_len()))) + } else { + Err(Err::Error(OM::Error::bind(|| { + make_error(input, ErrorKind::Eof) + }))) + } + } else { + let res = OM::Output::bind(|| { + let mut res = Uint::default(); + for (index, byte) in input.iter_elements().take(self.bound).enumerate() { + res = res + (Uint::from(byte) << (8 * index as u8)); + } + + res + }); + + Ok((input.take_from(self.bound), res)) + } + } +} + +/// Recognizes an unsigned 1 byte integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u8; +/// +/// let mut parser = le_u8::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_u8>() -> impl Parser +where + I: Input, +{ + le_uint(1) +} + +/// Recognizes a little endian unsigned 2 bytes integer. +/// +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u16; +/// +/// let parser = |s| { +/// le_u16::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_u16>() -> impl Parser +where + I: Input, +{ + le_uint(2) +} + +/// Recognizes a little endian unsigned 3 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u24; +/// +/// let parser = |s| { +/// le_u24::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn le_u24>() -> impl Parser +where + I: Input, +{ + le_uint(3) +} + +/// Recognizes a little endian unsigned 4 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u32; +/// +/// let parser = |s| { +/// le_u32::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_u32>() -> impl Parser +where + I: Input, +{ + le_uint(4) +} + +/// Recognizes a little endian unsigned 8 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u64; +/// +/// let parser = |s| { +/// le_u64::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_u64>() -> impl Parser +where + I: Input, +{ + le_uint(8) +} + +/// Recognizes a little endian unsigned 16 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_u128; +/// +/// let mut parser = |s| { +/// le_u128::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn le_u128>() -> impl Parser +where + I: Input, +{ + le_uint(16) +} + +/// Recognizes a signed 1 byte integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i8; +/// +/// let mut parser = le_i8::<_, (_, ErrorKind)>(); +/// +/// assert_eq!(parser.parse(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser.parse(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_i8>() -> impl Parser +where + I: Input, +{ + le_u8().map(|x| x as i8) +} + +/// Recognizes a little endian signed 2 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i16; +/// +/// let parser = |s| { +/// le_i16::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_i16>() -> impl Parser +where + I: Input, +{ + le_u16().map(|x| x as i16) +} + +/// Recognizes a little endian signed 3 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i24; +/// +/// let parser = |s| { +/// le_i24::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn le_i24>() -> impl Parser +where + I: Input, +{ + // Same as the unsigned version but we need to sign-extend manually here + le_u24().map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) +} + +/// Recognizes a little endian signed 4 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i32; +/// +/// let parser = |s| { +/// le_i32::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_i32>() -> impl Parser +where + I: Input, +{ + le_u32().map(|x| x as i32) +} + +/// Recognizes a little endian signed 8 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i64; +/// +/// let parser = |s| { +/// le_i64::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_i64>() -> impl Parser +where + I: Input, +{ + le_u64().map(|x| x as i64) +} + +/// Recognizes a little endian signed 16 bytes integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_i128; +/// +/// let parser = |s| { +/// le_i128::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn le_i128>() -> impl Parser +where + I: Input, +{ + le_u128().map(|x| x as i128) +} + +/// Recognizes an unsigned 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u8; +/// +/// let parser = |s| { +/// u8::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn u8>() -> impl Parser +where + I: Input, +{ + be_u8() +} + +/// Recognizes an unsigned 2 bytes integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u16 integer. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u16; +/// +/// let be_u16 = |s| { +/// u16::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_u16 = |s| { +/// u16::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn u16>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_u16()), + crate::number::Endianness::Little => Either::Right(le_u16()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_u16()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_u16()), + } +} + +/// Recognizes an unsigned 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u24 integer. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u24; +/// +/// let be_u24 = |s| { +/// u24::<_,(_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// +/// let le_u24 = |s| { +/// u24::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn u24>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_u24()), + crate::number::Endianness::Little => Either::Right(le_u24()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_u24()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_u24()), + } +} + +/// Recognizes an unsigned 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u32 integer. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u32; +/// +/// let be_u32 = |s| { +/// u32::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// +/// let le_u32 = |s| { +/// u32::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn u32>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_u32()), + crate::number::Endianness::Little => Either::Right(le_u32()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_u32()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_u32()), + } +} + +/// Recognizes an unsigned 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u64 integer. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u64; +/// +/// let be_u64 = |s| { +/// u64::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// +/// let le_u64 = |s| { +/// u64::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn u64>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_u64()), + crate::number::Endianness::Little => Either::Right(le_u64()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_u64()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_u64()), + } +} + +/// Recognizes an unsigned 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u128 integer. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::u128; +/// +/// let be_u128 = |s| { +/// u128::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// +/// let le_u128 = |s| { +/// u128::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn u128>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_u128()), + crate::number::Endianness::Little => Either::Right(le_u128()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_u128()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_u128()), + } +} + +/// Recognizes a signed 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i8; +/// +/// let parser = |s| { +/// i8::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn i8>() -> impl Parser +where + I: Input, +{ + u8().map(|x| x as i8) +} + +/// Recognizes a signed 2 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i16 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i16; +/// +/// let be_i16 = |s| { +/// i16::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_i16 = |s| { +/// i16::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn i16>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_i16()), + crate::number::Endianness::Little => Either::Right(le_i16()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_i16()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_i16()), + } +} + +/// Recognizes a signed 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i24 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i24; +/// +/// let be_i24 = |s| { +/// i24::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// +/// let le_i24 = |s| { +/// i24::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn i24>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_i24()), + crate::number::Endianness::Little => Either::Right(le_i24()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_i24()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_i24()), + } +} + +/// Recognizes a signed 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i32 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i32; +/// +/// let be_i32 = |s| { +/// i32::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// +/// let le_i32 = |s| { +/// i32::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn i32>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_i32()), + crate::number::Endianness::Little => Either::Right(le_i32()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_i32()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_i32()), + } +} + +/// Recognizes a signed 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i64 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i64; +/// +/// let be_i64 = |s| { +/// i64::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// +/// let le_i64 = |s| { +/// i64::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn i64>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_i64()), + crate::number::Endianness::Little => Either::Right(le_i64()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_i64()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_i64()), + } +} + +/// Recognizes a signed 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i128 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::i128; +/// +/// let be_i128 = |s| { +/// i128::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// +/// let le_i128 = |s| { +/// i128::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn i128>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_i128()), + crate::number::Endianness::Little => Either::Right(le_i128()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_i128()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_i128()), + } +} + +/// Recognizes a big endian 4 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_f32; +/// +/// let parser = |s| { +/// be_f32::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00][..]), Ok((&b""[..], 2.640625))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_f32>() -> impl Parser +where + I: Input, +{ + be_u32().map(f32::from_bits) +} + +/// Recognizes a big endian 8 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::be_f64; +/// +/// let parser = |s| { +/// be_f64::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_f64>() -> impl Parser +where + I: Input, +{ + be_u64().map(f64::from_bits) +} + +/// Recognizes a little endian 4 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_f32; +/// +/// let parser = |s| { +/// le_f32::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_f32>() -> impl Parser +where + I: Input, +{ + le_u32().map(f32::from_bits) +} + +/// Recognizes a little endian 8 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::le_f64; +/// +/// let parser = |s| { +/// le_f64::<_, (_, ErrorKind)>().parse(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 3145728.0))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_f64>() -> impl Parser +where + I: Input, +{ + le_u64().map(f64::from_bits) +} + +/// Recognizes a 4 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f32 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f32 float. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::f32; +/// +/// let be_f32 = |s| { +/// f32::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_f32 = |s| { +/// f32::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn f32>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_f32()), + crate::number::Endianness::Little => Either::Right(le_f32()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_f32()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_f32()), + } +} + +/// Recognizes an 8 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f64 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f64 float. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// # use nom::Needed::Size; +/// use nom::number::f64; +/// +/// let be_f64 = |s| { +/// f64::<_, (_, ErrorKind)>(nom::number::Endianness::Big).parse(s) +/// }; +/// +/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5)))); +/// +/// let le_f64 = |s| { +/// f64::<_, (_, ErrorKind)>(nom::number::Endianness::Little).parse(s) +/// }; +/// +/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5)))); +/// ``` +#[inline] +pub fn f64>( + endian: crate::number::Endianness, +) -> impl Parser +where + I: Input, +{ + match endian { + crate::number::Endianness::Big => Either::Left(be_f64()), + crate::number::Endianness::Little => Either::Right(le_f64()), + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => Either::Left(be_f64()), + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => Either::Right(le_f64()), + } +} + +/// Recognizes a floating point number in text format and returns the corresponding part of the input. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if it reaches the end of input. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; +/// use nom::number::recognize_float; +/// +/// let parser = |s| { +/// recognize_float().parse(s) +/// }; +/// +/// assert_eq!(parser("11e-1;"), Ok((";", "11e-1"))); +/// assert_eq!(parser("123E-02;"), Ok((";", "123E-02"))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", "123"))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char)))); +/// ``` +#[rustfmt::skip] +pub fn recognize_float>() -> impl Parser +where + T: Clone + Offset, + T: Input, + ::Item: AsChar, +{ + recognize(( + opt(alt((char('+'), char('-')))), + alt(( + map((digit1(), opt(pair(char('.'), opt(digit1())))), |_| ()), + map((char('.'), digit1()), |_| ()) + )), + opt(( + alt((char('e'), char('E'))), + opt(alt((char('+'), char('-')))), + cut(digit1()) + )) + )) +} + +/// float number text parser that also recognizes "nan", "infinity" and "inf" (case insensitive) +pub fn recognize_float_or_exceptions>() -> impl Parser +where + T: Clone + Offset, + T: Input + Compare<&'static str>, + ::Item: AsChar, +{ + alt(( + recognize_float::<_, E>(), + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + )) +} + +/// single precision floating point number parser from text +pub fn float>() -> impl Parser +where + T: Clone + Offset, + T: Input + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar + Clone, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + Float { + o: PhantomData, + e: PhantomData, + } +} + +/// double precision floating point number parser from text +pub fn double>() -> impl Parser +where + T: Clone + Offset, + T: Input + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar + Clone, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + Float { + o: PhantomData, + e: PhantomData, + } +} + +/// f64 parser from text +struct Float { + o: PhantomData, + e: PhantomData, +} + +impl> Parser for Float +where + I: Clone + Offset, + I: Input + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar + Clone, + I: AsBytes, + I: for<'a> Compare<&'a [u8]>, +{ + type Output = O; + type Error = E; + + fn process( + &mut self, + input: I, + ) -> crate::PResult { + let (i, s) = + recognize_float_or_exceptions().process::>(input)?; + + match s.parse_to() { + Some(f) => Ok((i, OM::Output::bind(|| f))), + None => Err(crate::Err::Error(OM::Error::bind(|| { + E::from_error_kind(i, crate::error::ErrorKind::Float) + }))), + } + } +} + +#[cfg(test)] +#[cfg(feature = "std")] +mod tests { + use super::*; + use crate::error::ErrorKind; + use crate::internal::Err; + + macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; + ); + + #[test] + fn float_test() { + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + assert_parse!(recognize_float().parse_complete(test), Ok(("", test))); + + /*assert_parse!(float(test.as_bytes()), Ok((&b""[..], expected32))); + assert_parse!(float(test), Ok(("", expected32))); + */ + + assert_parse!( + double().parse_complete(test.as_bytes()), + Ok((&b""[..], expected64)) + ); + assert_parse!(double().parse_complete(test), Ok(("", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + recognize_float().parse_complete(remaining_exponent), + Err(Err::Failure(("", ErrorKind::Digit))) + ); + + /*let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (i, inf) = float::<_, ()>("infinity").unwrap(); + assert!(inf.is_infinite()); + assert!(i.is_empty());*/ + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/number/streaming.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/number/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,12 +5,10 @@ use crate::character::streaming::{char, digit1, sign}; use crate::combinator::{cut, map, opt, recognize}; use crate::error::{ErrorKind, ParseError}; -use crate::internal::*; -use crate::lib::std::ops::{RangeFrom, RangeTo}; -use crate::sequence::{pair, tuple}; -use crate::traits::{ - AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice, -}; +use crate::lib::std::ops::{Add, Shl}; +use crate::sequence::pair; +use crate::traits::{AsBytes, AsChar, Compare, Offset}; +use crate::{internal::*, Input}; /// Recognizes an unsigned 1 byte integer. /// @@ -29,16 +27,9 @@ #[inline] pub fn be_u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(1))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + be_uint(input, 1) } /// Recognizes a big endian unsigned 2 bytes integer. @@ -59,19 +50,9 @@ #[inline] pub fn be_u16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 2; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u16; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u16; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 2) } /// Recognizes a big endian unsigned 3 byte integer. @@ -92,19 +73,9 @@ #[inline] pub fn be_u24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 3; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u32; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u32; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 3) } /// Recognizes a big endian unsigned 4 bytes integer. @@ -125,19 +96,9 @@ #[inline] pub fn be_u32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 4; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u32; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u32; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 4) } /// Recognizes a big endian unsigned 8 bytes integer. @@ -158,19 +119,9 @@ #[inline] pub fn be_u64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 8; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u64; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u64; - } - - Ok((input.slice(bound..), res)) - } + be_uint(input, 8) } /// Recognizes a big endian unsigned 16 bytes integer. @@ -190,19 +141,18 @@ #[inline] pub fn be_u128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 16; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u128; - for byte in input.iter_elements().take(bound) { - res = (res << 8) + byte as u128; - } + be_uint(input, 16) +} - Ok((input.slice(bound..), res)) - } +#[inline] +fn be_uint>(input: I, bound: usize) -> IResult +where + I: Input, + Uint: Default + Shl + Add + From, +{ + super::be_uint(bound).parse(input) } /// Recognizes a signed 1 byte integer. @@ -220,7 +170,7 @@ #[inline] pub fn be_i8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u8.map(|x| x as i8).parse(input) } @@ -240,7 +190,7 @@ #[inline] pub fn be_i16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u16.map(|x| x as i16).parse(input) } @@ -260,7 +210,7 @@ #[inline] pub fn be_i24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { // Same as the unsigned version but we need to sign-extend manually here be_u24 @@ -289,7 +239,7 @@ #[inline] pub fn be_i32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u32.map(|x| x as i32).parse(input) } @@ -310,7 +260,7 @@ #[inline] pub fn be_i64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u64.map(|x| x as i64).parse(input) } @@ -330,7 +280,7 @@ #[inline] pub fn be_i128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { be_u128.map(|x| x as i128).parse(input) } @@ -350,16 +300,9 @@ #[inline] pub fn le_u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(1))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + le_uint(input, 1) } /// Recognizes a little endian unsigned 2 bytes integer. @@ -380,19 +323,9 @@ #[inline] pub fn le_u16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 2; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u16; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u16) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 2) } /// Recognizes a little endian unsigned 3 bytes integer. @@ -413,19 +346,9 @@ #[inline] pub fn le_u24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 3; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u32; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u32) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 3) } /// Recognizes a little endian unsigned 4 bytes integer. @@ -446,19 +369,9 @@ #[inline] pub fn le_u32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 4; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u32; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u32) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 4) } /// Recognizes a little endian unsigned 8 bytes integer. @@ -479,19 +392,9 @@ #[inline] pub fn le_u64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 8; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u64; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u64) << (8 * index); - } - - Ok((input.slice(bound..), res)) - } + le_uint(input, 8) } /// Recognizes a little endian unsigned 16 bytes integer. @@ -512,19 +415,18 @@ #[inline] pub fn le_u128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 16; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(bound - input.input_len()))) - } else { - let mut res = 0u128; - for (index, byte) in input.iter_indices().take(bound) { - res += (byte as u128) << (8 * index); - } + le_uint(input, 16) +} - Ok((input.slice(bound..), res)) - } +#[inline] +fn le_uint>(input: I, bound: usize) -> IResult +where + I: Input, + Uint: Default + Shl + Add + From, +{ + super::le_uint(bound).parse(input) } /// Recognizes a signed 1 byte integer. @@ -542,7 +444,7 @@ #[inline] pub fn le_i8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u8.map(|x| x as i8).parse(input) } @@ -565,7 +467,7 @@ #[inline] pub fn le_i16>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u16.map(|x| x as i16).parse(input) } @@ -588,7 +490,7 @@ #[inline] pub fn le_i24>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { // Same as the unsigned version but we need to sign-extend manually here le_u24 @@ -620,7 +522,7 @@ #[inline] pub fn le_i32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u32.map(|x| x as i32).parse(input) } @@ -643,7 +545,7 @@ #[inline] pub fn le_i64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u64.map(|x| x as i64).parse(input) } @@ -666,7 +568,7 @@ #[inline] pub fn le_i128>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { le_u128.map(|x| x as i128).parse(input) } @@ -690,16 +592,9 @@ #[inline] pub fn u8>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - let bound: usize = 1; - if input.input_len() < bound { - Err(Err::Incomplete(Needed::new(1))) - } else { - let res = input.iter_elements().next().unwrap(); - - Ok((input.slice(bound..), res)) - } + super::u8().parse(input) } /// Recognizes an unsigned 2 bytes integer @@ -728,18 +623,13 @@ /// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); /// ``` #[inline] -pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u16>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u16, - crate::number::Endianness::Little => le_u16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u16, - } + move |input| super::u16(endian).parse(input) } /// Recognizes an unsigned 3 byte integer @@ -767,18 +657,13 @@ /// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); /// ``` #[inline] -pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u24>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u24, - crate::number::Endianness::Little => le_u24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u24, - } + move |input| super::u24(endian).parse(input) } /// Recognizes an unsigned 4 byte integer @@ -806,18 +691,13 @@ /// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); /// ``` #[inline] -pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u32>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u32, - crate::number::Endianness::Little => le_u32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u32, - } + move |input| super::u32(endian).parse(input) } /// Recognizes an unsigned 8 byte integer @@ -845,18 +725,13 @@ /// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); /// ``` #[inline] -pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u64>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u64, - crate::number::Endianness::Little => le_u64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u64, - } + move |input| super::u64(endian).parse(input) } /// Recognizes an unsigned 16 byte integer @@ -884,18 +759,13 @@ /// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); /// ``` #[inline] -pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn u128>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_u128, - crate::number::Endianness::Little => le_u128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u128, - } + move |input| super::u128(endian).parse(input) } /// Recognizes a signed 1 byte integer @@ -917,9 +787,9 @@ #[inline] pub fn i8>(i: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - u8.map(|x| x as i8).parse(i) + super::u8().map(|x| x as i8).parse(i) } /// Recognizes a signed 2 byte integer @@ -947,18 +817,13 @@ /// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); /// ``` #[inline] -pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i16>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i16, - crate::number::Endianness::Little => le_i16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i16, - } + move |input| super::i16(endian).parse(input) } /// Recognizes a signed 3 byte integer @@ -986,18 +851,13 @@ /// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); /// ``` #[inline] -pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i24>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i24, - crate::number::Endianness::Little => le_i24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i24, - } + move |input| super::i24(endian).parse(input) } /// Recognizes a signed 4 byte integer @@ -1025,18 +885,13 @@ /// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); /// ``` #[inline] -pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i32>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i32, - crate::number::Endianness::Little => le_i32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i32, - } + move |input| super::i32(endian).parse(input) } /// Recognizes a signed 8 byte integer @@ -1064,18 +919,13 @@ /// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); /// ``` #[inline] -pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i64>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i64, - crate::number::Endianness::Little => le_i64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i64, - } + move |input| super::i64(endian).parse(input) } /// Recognizes a signed 16 byte integer @@ -1103,18 +953,13 @@ /// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); /// ``` #[inline] -pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult +pub fn i128>( + endian: crate::number::Endianness, +) -> impl Fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { - match endian { - crate::number::Endianness::Big => be_i128, - crate::number::Endianness::Little => le_i128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i128, - } + move |input| super::i128(endian).parse(input) } /// Recognizes a big endian 4 bytes floating point number. @@ -1134,7 +979,7 @@ #[inline] pub fn be_f32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match be_u32(input) { Err(e) => Err(e), @@ -1159,7 +1004,7 @@ #[inline] pub fn be_f64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match be_u64(input) { Err(e) => Err(e), @@ -1184,7 +1029,7 @@ #[inline] pub fn le_f32>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match le_u32(input) { Err(e) => Err(e), @@ -1209,7 +1054,7 @@ #[inline] pub fn le_f64>(input: I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match le_u64(input) { Err(e) => Err(e), @@ -1244,7 +1089,7 @@ #[inline] pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match endian { crate::number::Endianness::Big => be_f32, @@ -1283,7 +1128,7 @@ #[inline] pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Slice> + InputIter + InputLength, + I: Input, { match endian { crate::number::Endianness::Big => be_f64, @@ -1306,22 +1151,34 @@ /// hex_u32(s) /// }; /// -/// assert_eq!(parser(b"01AE;"), Ok((&b";"[..], 0x01AE))); -/// assert_eq!(parser(b"abc"), Err(Err::Incomplete(Needed::new(1)))); -/// assert_eq!(parser(b"ggg"), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA)))); +/// assert_eq!(parser(&b"01AE;"[..]), Ok((&b";"[..], 0x01AE))); +/// assert_eq!(parser(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA)))); /// ``` #[inline] -pub fn hex_u32<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], u32, E> { - let (i, o) = crate::bytes::streaming::is_a(&b"0123456789abcdefABCDEF"[..])(input)?; +pub fn hex_u32>(input: I) -> IResult +where + I: Input + AsBytes, + ::Item: AsChar, +{ + let e: ErrorKind = ErrorKind::IsA; + let (i, o) = input.split_at_position1( + |c| { + let c = c.as_char(); + !"0123456789abcdefABCDEF".contains(c) + }, + e, + )?; // Do not parse more than 8 characters for a u32 - let (parsed, remaining) = if o.len() <= 8 { - (o, i) + let (remaining, parsed) = if o.input_len() <= 8 { + (i, o) } else { - (&input[..8], &input[8..]) + input.take_split(8) }; let res = parsed + .as_bytes() .iter() .rev() .enumerate() @@ -1354,39 +1211,31 @@ #[rustfmt::skip] pub fn recognize_float>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter, - ::Item: AsChar, - T: InputTakeAtPosition + InputLength, - ::Item: AsChar + T: Input, + ::Item: AsChar, { - recognize( - tuple(( + recognize(( opt(alt((char('+'), char('-')))), alt(( - map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), - map(tuple((char('.'), digit1)), |_| ()) + map((digit1, opt(pair(char('.'), opt(digit1)))), |_| ()), + map((char('.'), digit1), |_| ()) )), - opt(tuple(( + opt(( alt((char('e'), char('E'))), opt(alt((char('+'), char('-')))), cut(digit1) - ))) - )) - )(input) + )) + )).parse(input) } // workaround until issues with minimal-lexical are fixed #[doc(hidden)] pub fn recognize_float_or_exceptions>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter + InputTake + InputLength + Compare<&'static str>, - ::Item: AsChar, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input + Compare<&'static str>, + ::Item: AsChar, { alt(( |i: T| { @@ -1401,14 +1250,15 @@ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, |i: T| { - crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) + crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, |i: T| { - crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) + crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) }, - ))(input) + )) + .parse(input) } /// Recognizes a floating point number in text format @@ -1420,12 +1270,9 @@ /// pub fn recognize_float_parts>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter + crate::traits::ParseTo, - ::Item: AsChar, - T: InputTakeAtPosition + InputTake + InputLength, - ::Item: AsChar, + T: Input, + ::Item: AsChar, T: for<'a> Compare<&'a [u8]>, T: AsBytes, { @@ -1449,13 +1296,13 @@ if integer.input_len() == 0 && zeroes.input_len() > 0 { // keep the last zero if integer is empty - integer = zeroes.slice(zeroes.input_len() - 1..); + integer = zeroes.take_from(zeroes.input_len() - 1); } - let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, opt_dot) = opt(tag(&b"."[..])).parse(i)?; let (i, fraction) = if opt_dot.is_none() { let i2 = i.clone(); - (i2, i.slice(..0)) + (i2, i.take(0)) } else { // match number, trim right zeroes let mut zero_count = 0usize; @@ -1486,7 +1333,7 @@ position - zero_count }; - (i.slice(position..), i.slice(..index)) + (i.take_from(position), i.take(index)) }; if integer.input_len() == 0 && fraction.input_len() == 0 { @@ -1495,13 +1342,13 @@ let i2 = i.clone(); let (i, e) = match i.as_bytes().iter().next() { - Some(b'e') => (i.slice(1..), true), - Some(b'E') => (i.slice(1..), true), + Some(b'e') => (i.take_from(1), true), + Some(b'E') => (i.take_from(1), true), _ => (i, false), }; let (i, exp) = if e { - cut(crate::character::streaming::i32)(i)? + cut(crate::character::streaming::i32).parse(i)? } else { (i2, 0) }; @@ -1529,13 +1376,9 @@ /// ``` pub fn float>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter + InputLength + InputTake + crate::traits::ParseTo + Compare<&'static str>, - ::Item: AsChar, - ::IterElem: Clone, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar + Clone, T: AsBytes, T: for<'a> Compare<&'a [u8]>, { @@ -1583,13 +1426,9 @@ /// ``` pub fn double>(input: T) -> IResult where - T: Slice> + Slice>, T: Clone + Offset, - T: InputIter + InputLength + InputTake + crate::traits::ParseTo + Compare<&'static str>, - ::Item: AsChar, - ::IterElem: Clone, - T: InputTakeAtPosition, - ::Item: AsChar, + T: Input + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar + Clone, T: AsBytes, T: for<'a> Compare<&'a [u8]>, { @@ -1878,6 +1717,13 @@ } #[test] + fn le_u16_test() { + assert_parse!(le_u16(&[0x00, 0x03][..]), Ok((&b""[..], 0x0300))); + assert_parse!(le_u16(&[b'a', b'b'][..]), Ok((&b""[..], 0x6261))); + assert_parse!(le_u16(&[0x01][..]), Err(Err::Incomplete(Needed::new(1)))); + } + + #[test] fn le_u24_tests() { assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); @@ -1912,6 +1758,19 @@ } #[test] + fn le_u32_test() { + assert_parse!( + le_u32(&[0x00, 0x03, 0x05, 0x07][..]), + Ok((&b""[..], 0x07050300)) + ); + assert_parse!( + le_u32(&[b'a', b'b', b'c', b'd'][..]), + Ok((&b""[..], 0x64636261)) + ); + assert_parse!(le_u32(&[0x01][..]), Err(Err::Incomplete(Needed::new(3)))); + } + + #[test] fn le_i64_tests() { assert_parse!( le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), @@ -2089,8 +1948,9 @@ let (_i, inf) = float::<_, ()>("inf").unwrap(); assert!(inf.is_infinite()); - let (_i, inf) = float::<_, ()>("infinite").unwrap(); + let (i, inf) = float::<_, ()>("infinity").unwrap(); assert!(inf.is_infinite()); + assert!(i.is_empty()); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/sequence/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/sequence/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,6 +5,7 @@ use crate::error::ParseError; use crate::internal::{IResult, Parser}; +use crate::{Check, OutputM, OutputMode, PResult}; /// Gets an object from the first parser, /// then gets another object from the second parser. @@ -13,31 +14,28 @@ /// * `first` The first parser to apply. /// * `second` The second parser to apply. /// +/// # Example /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed}; -/// # use nom::Needed::Size; /// use nom::sequence::pair; /// use nom::bytes::complete::tag; +/// use nom::{error::ErrorKind, Err, Parser}; /// /// let mut parser = pair(tag("abc"), tag("efg")); /// -/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg")))); -/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg")))); -/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); -/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("abcefg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag)))); /// ``` pub fn pair, F, G>( - mut first: F, - mut second: G, -) -> impl FnMut(I) -> IResult + first: F, + second: G, +) -> impl Parser where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, o1) = first.parse(input)?; - second.parse(input).map(|(i, o2)| (i, (o1, o2))) - } + first.and(second) } /// Matches an object from the first parser and discards it, @@ -48,29 +46,52 @@ /// * `second` The second parser to get object. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; /// # use nom::Needed::Size; /// use nom::sequence::preceded; /// use nom::bytes::complete::tag; /// /// let mut parser = preceded(tag("abc"), tag("efg")); /// -/// assert_eq!(parser("abcefg"), Ok(("", "efg"))); -/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg"))); -/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); -/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("abcefg"), Ok(("", "efg"))); +/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", "efg"))); +/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag)))); /// ``` -pub fn preceded, F, G>( - mut first: F, - mut second: G, -) -> impl FnMut(I) -> IResult +pub fn preceded, F, G>( + first: F, + second: G, +) -> impl Parser where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, _) = first.parse(input)?; - second.parse(input) + Preceded { + f: first, + g: second, + } +} + +/// a +pub struct Preceded { + f: F, + g: G, +} + +impl, F: Parser, G: Parser> Parser + for Preceded +{ + type Output = >::Output; + type Error = E; + + #[inline(always)] + fn process(&mut self, i: I) -> PResult { + let (i, _) = self + .f + .process::>(i)?; + let (i, o2) = self.g.process::(i)?; + + Ok((i, o2)) } } @@ -82,29 +103,52 @@ /// * `second` The second parser to match an object. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; /// # use nom::Needed::Size; /// use nom::sequence::terminated; /// use nom::bytes::complete::tag; /// /// let mut parser = terminated(tag("abc"), tag("efg")); /// -/// assert_eq!(parser("abcefg"), Ok(("", "abc"))); -/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc"))); -/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); -/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("abcefg"), Ok(("", "abc"))); +/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", "abc"))); +/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag)))); /// ``` -pub fn terminated, F, G>( - mut first: F, - mut second: G, -) -> impl FnMut(I) -> IResult +pub fn terminated, F, G>( + first: F, + second: G, +) -> impl Parser where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, o1) = first.parse(input)?; - second.parse(input).map(|(i, _)| (i, o1)) + Terminated { + f: first, + g: second, + } +} + +/// a +pub struct Terminated { + f: F, + g: G, +} + +impl, F: Parser, G: Parser> Parser + for Terminated +{ + type Output = >::Output; + type Error = E; + + #[inline(always)] + fn process(&mut self, i: I) -> PResult { + let (i, o1) = self.f.process::(i)?; + let (i, _) = self + .g + .process::>(i)?; + + Ok((i, o1)) } } @@ -118,33 +162,29 @@ /// * `second` The second parser to apply. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; /// # use nom::Needed::Size; /// use nom::sequence::separated_pair; /// use nom::bytes::complete::tag; /// /// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg")); /// -/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg")))); -/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg")))); -/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); -/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("abc|efg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser.parse("abc|efghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag)))); /// ``` -pub fn separated_pair, F, G, H>( - mut first: F, - mut sep: G, - mut second: H, -) -> impl FnMut(I) -> IResult +pub fn separated_pair, F, G, H>( + first: F, + sep: G, + second: H, +) -> impl Parser where - F: Parser, - G: Parser, - H: Parser, + F: Parser, + G: Parser, + H: Parser, { - move |input: I| { - let (input, o1) = first.parse(input)?; - let (input, _) = sep.parse(input)?; - second.parse(input).map(|(i, o2)| (i, (o1, o2))) - } + first.and(preceded(sep, second)) } /// Matches an object from the first parser and discards it, @@ -157,47 +197,46 @@ /// * `third` The third parser to apply and discard. /// /// ```rust -/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::{Err, error::ErrorKind, Needed, Parser}; /// # use nom::Needed::Size; /// use nom::sequence::delimited; /// use nom::bytes::complete::tag; /// /// let mut parser = delimited(tag("("), tag("abc"), tag(")")); /// -/// assert_eq!(parser("(abc)"), Ok(("", "abc"))); -/// assert_eq!(parser("(abc)def"), Ok(("def", "abc"))); -/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); -/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("(abc)"), Ok(("", "abc"))); +/// assert_eq!(parser.parse("(abc)def"), Ok(("def", "abc"))); +/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag)))); /// ``` -pub fn delimited, F, G, H>( - mut first: F, - mut second: G, - mut third: H, -) -> impl FnMut(I) -> IResult +pub fn delimited, F, G, H>( + first: F, + second: G, + third: H, +) -> impl Parser where - F: Parser, - G: Parser, - H: Parser, + F: Parser, + G: Parser, + H: Parser, { - move |input: I| { - let (input, _) = first.parse(input)?; - let (input, o2) = second.parse(input)?; - third.parse(input).map(|(i, _)| (i, o2)) - } + preceded(first, terminated(second, third)) } /// Helper trait for the tuple combinator. /// /// This trait is implemented for tuples of parsers of up to 21 elements. +#[deprecated(since = "8.0.0", note = "`Parser` is directly implemented for tuples")] +#[allow(deprecated)] pub trait Tuple { /// Parses the input and returns a tuple of results of each parser. - fn parse(&mut self, input: I) -> IResult; + fn parse_tuple(&mut self, input: I) -> IResult; } -impl, F: Parser> +#[allow(deprecated)] +impl, F: Parser> Tuple for (F,) { - fn parse(&mut self, input: Input) -> IResult { + fn parse_tuple(&mut self, input: Input) -> IResult { self.0.parse(input).map(|(i, o)| (i, (o,))) } } @@ -218,12 +257,12 @@ macro_rules! tuple_trait_impl( ($($name:ident $ty: ident),+) => ( + #[allow(deprecated)] impl< Input: Clone, $($ty),+ , Error: ParseError, - $($name: Parser),+ + $($name: Parser),+ > Tuple for ( $($name),+ ) { - - fn parse(&mut self, input: Input) -> IResult { + fn parse_tuple(&mut self, input: Input) -> IResult { tuple_trait_inner!(0, self, input, (), $($name)+) } @@ -233,17 +272,17 @@ macro_rules! tuple_trait_inner( ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({ - let (i, o) = $self.$it.parse($input.clone())?; + let (i, o) = $self.$it.parse($input)?; succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+)) }); ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({ - let (i, o) = $self.$it.parse($input.clone())?; + let (i, o) = $self.$it.parse($input)?; succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+)) }); ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({ - let (i, o) = $self.$it.parse($input.clone())?; + let (i, o) = $self.$it.parse($input)?; Ok((i, ($($parsed)* , o))) }); @@ -255,8 +294,9 @@ // Special case: implement `Tuple` for `()`, the unit type. // This can come up in macros which accept a variable number of arguments. // Literally, `()` is an empty tuple, so it should simply parse nothing. +#[allow(deprecated)] impl> Tuple for () { - fn parse(&mut self, input: I) -> IResult { + fn parse_tuple(&mut self, input: I) -> IResult { Ok((input, ())) } } @@ -272,8 +312,10 @@ /// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def")))); /// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha)))); /// ``` +#[deprecated(since = "8.0.0", note = "`Parser` is directly implemented for tuples")] +#[allow(deprecated)] pub fn tuple, List: Tuple>( mut l: List, ) -> impl FnMut(I) -> IResult { - move |i: I| l.parse(i) + move |i: I| l.parse_tuple(i) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/sequence/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/sequence/tests.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/sequence/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,26 +9,17 @@ use crate::character::complete::alpha1; use crate::{error::ErrorKind, Err}; - let mut parser = tuple((alpha1,)); - assert_eq!(parser("abc123def"), Ok(("123def", ("abc",)))); + let mut parser = (alpha1,); assert_eq!( - parser("123def"), + crate::Parser::parse(&mut parser, "abc123def"), + Ok(("123def", ("abc",))) + ); + assert_eq!( + crate::Parser::parse(&mut parser, "123def"), Err(Err::Error(("123def", ErrorKind::Alpha))) ); } -#[derive(PartialEq, Eq, Debug)] -struct B { - a: u8, - b: u8, -} - -#[derive(PartialEq, Eq, Debug)] -struct C { - a: u8, - b: Option, -} - /*FIXME: convert code examples to new error management use util::{add_error_pattern, error_to_list, print_error}; @@ -87,7 +78,7 @@ #[test] fn pair_test() { fn pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(tag("abc"), tag("def"))(i) + pair(tag("abc"), tag("def")).parse(i) } assert_eq!( @@ -119,7 +110,7 @@ #[test] fn separated_pair_test() { fn sep_pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - separated_pair(tag("abc"), tag(","), tag("def"))(i) + separated_pair(tag("abc"), tag(","), tag("def")).parse(i) } assert_eq!( @@ -151,7 +142,7 @@ #[test] fn preceded_test() { fn preceded_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> { - preceded(tag("abcd"), tag("efgh"))(i) + preceded(tag("abcd"), tag("efgh")).parse(i) } assert_eq!( @@ -183,7 +174,7 @@ #[test] fn terminated_test() { fn terminated_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> { - terminated(tag("abcd"), tag("efgh"))(i) + terminated(tag("abcd"), tag("efgh")).parse(i) } assert_eq!( @@ -215,7 +206,7 @@ #[test] fn delimited_test() { fn delimited_abc_def_ghi(i: &[u8]) -> IResult<&[u8], &[u8]> { - delimited(tag("abc"), tag("def"), tag("ghi"))(i) + delimited(tag("abc"), tag("def"), tag("ghi")).parse(i) } assert_eq!( @@ -257,8 +248,9 @@ #[test] fn tuple_test() { + #[allow(clippy::type_complexity)] fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8], &[u8])> { - tuple((be_u16, take(3u8), tag("fg")))(i) + crate::Parser::parse(&mut (be_u16, take(3u8), tag("fg")), i) } assert_eq!( @@ -274,6 +266,7 @@ } #[test] +#[allow(deprecated)] fn unit_type() { assert_eq!( tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"), diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/str.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/str.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ #[cfg(test)] mod test { #[cfg(feature = "alloc")] - use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1}; + use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many}; use crate::{ bytes::complete::{is_a, is_not, tag, take, take_till, take_until}, error::{self, ErrorKind}, @@ -168,10 +168,10 @@ let c = "abcd123"; let d = "123"; - assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); - assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); - assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); - assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); + assert_eq!(f(a), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(b), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(c), Ok((d, b))); + assert_eq!(f(d), Ok((d, a))); } #[test] @@ -186,12 +186,12 @@ let c = "abcd123"; let d = "123"; - assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); - assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); - assert_eq!(f(&c[..]), Ok((&"123"[..], &b[..]))); + assert_eq!(f(a), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(b), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(c), Ok(("123", b))); assert_eq!( - f(&d[..]), - Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1))) + f(d), + Err(Err::Error(error_position!(d, ErrorKind::TakeWhile1))) ); } @@ -302,15 +302,7 @@ const CONSUMED: &str = "βèƒôřèÂßÇ"; const LEFTOVER: &str = "áƒƭèř"; fn while_s(c: char) -> bool { - c == 'β' - || c == 'è' - || c == 'ƒ' - || c == 'ô' - || c == 'ř' - || c == 'è' - || c == 'Â' - || c == 'ß' - || c == 'Ç' + matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') } fn test(input: &str) -> IResult<&str, &str> { take_while(while_s)(input) @@ -361,15 +353,7 @@ const CONSUMED: &str = "βèƒôřèÂßÇ"; const LEFTOVER: &str = "áƒƭèř"; fn while1_s(c: char) -> bool { - c == 'β' - || c == 'è' - || c == 'ƒ' - || c == 'ô' - || c == 'ř' - || c == 'è' - || c == 'Â' - || c == 'ß' - || c == 'Ç' + matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') } fn test(input: &str) -> IResult<&str, &str> { take_while1(while1_s)(input) @@ -503,15 +487,21 @@ #[test] #[cfg(feature = "alloc")] fn recognize_is_a() { + use crate::{lib::std::vec::Vec, Parser}; + let a = "aabbab"; let b = "ababcd"; fn f(i: &str) -> IResult<&str, &str> { - recognize(many1(alt((tag("a"), tag("b")))))(i) + recognize(many::<_, _, Vec<&str>, _, _>( + 1.., + alt((tag("a"), tag("b"))), + )) + .parse(i) } - assert_eq!(f(&a[..]), Ok((&a[6..], &a[..]))); - assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4]))); + assert_eq!(f(a), Ok((&a[6..], a))); + assert_eq!(f(b), Ok((&b[4..], &b[..4]))); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/src/traits.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,52 +1,575 @@ //! Traits input types have to implement to work with nom combinators +use core::iter::Enumerate; +use core::str::CharIndices; + use crate::error::{ErrorKind, ParseError}; use crate::internal::{Err, IResult, Needed}; -use crate::lib::std::iter::{Copied, Enumerate}; -use crate::lib::std::ops::{Range, RangeFrom, RangeFull, RangeTo}; +use crate::lib::std::iter::Copied; +use crate::lib::std::ops::{ + Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, +}; use crate::lib::std::slice::Iter; use crate::lib::std::str::from_utf8; -use crate::lib::std::str::CharIndices; use crate::lib::std::str::Chars; use crate::lib::std::str::FromStr; +use crate::IsStreaming; +use crate::Mode; #[cfg(feature = "alloc")] use crate::lib::std::string::String; #[cfg(feature = "alloc")] use crate::lib::std::vec::Vec; -/// Abstract method to calculate the input length -pub trait InputLength { +/// Parser input types must implement this trait +pub trait Input: Clone + Sized { + /// The current input type is a sequence of that `Item` type. + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Item; + + /// An iterator over the input type, producing the item + type Iter: Iterator; + + /// An iterator over the input type, producing the item and its byte position + /// If we're iterating over `&str`, the position + /// corresponds to the byte index of the character + type IterIndices: Iterator; + /// Calculates the input length, as indicated by its name, /// and the name of the trait itself fn input_len(&self) -> usize; + + /// Returns a slice of `index` bytes. panics if index > length + fn take(&self, index: usize) -> Self; + /// Returns a slice starting at `index` bytes. panics if index > length + fn take_from(&self, index: usize) -> Self; + /// Split the stream at the `index` byte offset. panics if index > length + fn take_split(&self, index: usize) -> (Self, Self); + + /// Returns the byte position of the first element satisfying the predicate + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool; + + /// Returns an iterator over the elements + fn iter_elements(&self) -> Self::Iter; + /// Returns an iterator over the elements and their byte offsets + fn iter_indices(&self) -> Self::IterIndices; + + /// Get the byte offset from the element's position in the stream + fn slice_index(&self, count: usize) -> Result; + + /// Looks for the first element of the input type for which the condition returns true, + /// and returns the input up to this position. + /// + /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(n) => Ok(self.take_split(n)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + /// Looks for the first element of the input type for which the condition returns true + /// and returns the input up to this position. + /// + /// Fails if the produced slice is empty. + /// + /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), + Some(n) => Ok(self.take_split(n)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + /// Looks for the first element of the input type for which the condition returns true, + /// and returns the input up to this position. + /// + /// *complete version*: If no element is found matching the condition, this will return the whole input + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.split_at_position(predicate) { + Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())), + res => res, + } + } + + /// Looks for the first element of the input type for which the condition returns true + /// and returns the input up to this position. + /// + /// Fails if the produced slice is empty. + /// + /// *complete version*: If no element is found matching the condition, this will return the whole input + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.split_at_position1(predicate, e) { + Err(Err::Incomplete(_)) => { + if self.input_len() == 0 { + Err(Err::Error(E::from_error_kind(self.clone(), e))) + } else { + Ok(self.take_split(self.input_len())) + } + } + res => res, + } + } + + /// mode version of split_at_position + fn split_at_position_mode>( + &self, + predicate: P, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(n) => Ok((self.take_from(n), OM::Output::bind(|| self.take(n)))), + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else { + let len = self.input_len(); + Ok((self.take_from(len), OM::Output::bind(|| self.take(len)))) + } + } + } + } + + /// mode version of split_at_position + fn split_at_position_mode1>( + &self, + predicate: P, + e: ErrorKind, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(0) => Err(Err::Error(OM::Error::bind(|| { + E::from_error_kind(self.clone(), e) + }))), + Some(n) => Ok((self.take_from(n), OM::Output::bind(|| self.take(n)))), + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else { + let len = self.input_len(); + if len == 0 { + Err(Err::Error(OM::Error::bind(|| { + E::from_error_kind(self.clone(), e) + }))) + } else { + Ok((self.take_from(len), OM::Output::bind(|| self.take(len)))) + } + } + } + } + } } -impl<'a, T> InputLength for &'a [T] { - #[inline] +impl<'a> Input for &'a [u8] { + type Item = u8; + type Iter = Copied>; + type IterIndices = Enumerate; + fn input_len(&self) -> usize { self.len() } -} -impl<'a> InputLength for &'a str { #[inline] + fn take(&self, index: usize) -> Self { + &self[0..index] + } + + fn take_from(&self, index: usize) -> Self { + &self[index..] + } + #[inline] + fn take_split(&self, index: usize) -> (Self, Self) { + let (prefix, suffix) = self.split_at(index); + (suffix, prefix) + } + + #[inline] + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool, + { + self.iter().position(|b| predicate(*b)) + } + + #[inline] + fn iter_elements(&self) -> Self::Iter { + self.iter().copied() + } + + #[inline] + fn iter_indices(&self) -> Self::IterIndices { + self.iter_elements().enumerate() + } + + #[inline] + fn slice_index(&self, count: usize) -> Result { + if self.len() >= count { + Ok(count) + } else { + Err(Needed::new(count - self.len())) + } + } + + #[inline(always)] + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + #[inline(always)] + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Ok(self.take_split(self.len())), + } + } + + #[inline(always)] + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + Some(i) => Ok(self.take_split(i)), + None => { + if self.is_empty() { + Err(Err::Error(E::from_error_kind(self, e))) + } else { + Ok(self.take_split(self.len())) + } + } + } + } + + /// mode version of split_at_position + #[inline(always)] + fn split_at_position_mode>( + &self, + predicate: P, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(n) => Ok((self.take_from(n), OM::Output::bind(|| self.take(n)))), + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else { + Ok(( + self.take_from(self.len()), + OM::Output::bind(|| self.take(self.len())), + )) + } + } + } + } + + /// mode version of split_at_position + #[inline(always)] + fn split_at_position_mode1>( + &self, + predicate: P, + e: ErrorKind, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(OM::Error::bind(|| E::from_error_kind(self, e)))), + Some(n) => Ok((self.take_from(n), OM::Output::bind(|| self.take(n)))), + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else if self.is_empty() { + Err(Err::Error(OM::Error::bind(|| E::from_error_kind(self, e)))) + } else { + Ok(( + self.take_from(self.len()), + OM::Output::bind(|| self.take(self.len())), + )) + } + } + } + } +} + +impl<'a> Input for &'a str { + type Item = char; + type Iter = Chars<'a>; + type IterIndices = CharIndices<'a>; + fn input_len(&self) -> usize { self.len() } -} -impl<'a> InputLength for (&'a [u8], usize) { #[inline] - fn input_len(&self) -> usize { - //println!("bit input length for ({:?}, {}):", self.0, self.1); - //println!("-> {}", self.0.len() * 8 - self.1); - self.0.len() * 8 - self.1 + fn take(&self, index: usize) -> Self { + &self[..index] + } + + #[inline] + fn take_from(&self, index: usize) -> Self { + &self[index..] + } + + // return byte index + #[inline] + fn take_split(&self, index: usize) -> (Self, Self) { + let (prefix, suffix) = self.split_at(index); + (suffix, prefix) + } + + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool, + { + self.find(predicate) + } + + #[inline] + fn iter_elements(&self) -> Self::Iter { + self.chars() + } + + #[inline] + fn iter_indices(&self) -> Self::IterIndices { + self.char_indices() + } + + #[inline] + fn slice_index(&self, count: usize) -> Result { + let mut cnt = 0; + for (index, _) in self.char_indices() { + if cnt == count { + return Ok(index); + } + cnt += 1; + } + if cnt == count { + return Ok(self.len()); + } + Err(Needed::Unknown) + } + + #[inline(always)] + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + // The position i is returned from str::find() which means it is within the bounds of the string + Some(i) => { + let (str1, str2) = self.split_at(i); + Ok((str2, str1)) + } + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + #[inline(always)] + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + // The position i is returned from str::find() which means it is within the bounds of the string + Some(i) => { + let (str1, str2) = self.split_at(i); + Ok((str2, str1)) + } + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + #[inline(always)] + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + // The position i is returned from str::find() which means it is within the bounds of the string + Some(i) => { + let (str1, str2) = self.split_at(i); + Ok((str2, str1)) + } + None => Ok(self.split_at(0)), + } + } + + #[inline(always)] + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + // The position i is returned from str::find() which means it is within the bounds of the string + Some(i) => { + let (str1, str2) = self.split_at(i); + Ok((str2, str1)) + } + None => { + if self.is_empty() { + Err(Err::Error(E::from_error_kind(self, e))) + } else { + // the end of slice is a char boundary + let (str1, str2) = self.split_at(self.len()); + Ok((str2, str1)) + } + } + } + } + + /// mode version of split_at_position + #[inline(always)] + fn split_at_position_mode>( + &self, + predicate: P, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(n) => unsafe { + // find() returns a byte index that is already in the slice at a char boundary + Ok(( + self.get_unchecked(n..), + OM::Output::bind(|| self.get_unchecked(..n)), + )) + }, + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else { + // the end of slice is a char boundary + unsafe { + Ok(( + self.get_unchecked(self.len()..), + OM::Output::bind(|| self.get_unchecked(..self.len())), + )) + } + } + } + } + } + + /// mode version of split_at_position + #[inline(always)] + fn split_at_position_mode1>( + &self, + predicate: P, + e: ErrorKind, + ) -> crate::PResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(0) => Err(Err::Error(OM::Error::bind(|| E::from_error_kind(self, e)))), + Some(n) => unsafe { + // find() returns a byte index that is already in the slice at a char boundary + Ok(( + self.get_unchecked(n..), + OM::Output::bind(|| self.get_unchecked(..n)), + )) + }, + None => { + if OM::Incomplete::is_streaming() { + Err(Err::Incomplete(Needed::new(1))) + } else if self.is_empty() { + Err(Err::Error(OM::Error::bind(|| E::from_error_kind(self, e)))) + } else { + // the end of slice is a char boundary + unsafe { + Ok(( + self.get_unchecked(self.len()..), + OM::Output::bind(|| self.get_unchecked(..self.len())), + )) + } + } + } + } } } /// Useful functions to calculate the offset between slices and show a hexdump of a slice pub trait Offset { /// Offset between the first byte of self and the first byte of the argument + /// the argument must be a part of self, otherwise this can fail with arithmetic + /// underflows as it compares byte offsets fn offset(&self, second: &Self) -> usize; } @@ -109,7 +632,7 @@ impl<'a> AsBytes for &'a [u8] { #[inline(always)] fn as_bytes(&self) -> &[u8] { - *self + self } } @@ -120,35 +643,23 @@ } } -macro_rules! as_bytes_array_impls { - ($($N:expr)+) => { - $( - impl<'a> AsBytes for &'a [u8; $N] { - #[inline(always)] - fn as_bytes(&self) -> &[u8] { - *self - } - } - - impl AsBytes for [u8; $N] { - #[inline(always)] - fn as_bytes(&self) -> &[u8] { - self - } - } - )+ - }; +impl<'a, const N: usize> AsBytes for &'a [u8; N] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self.as_slice() + } } -as_bytes_array_impls! { - 0 1 2 3 4 5 6 7 8 9 - 10 11 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27 28 29 - 30 31 32 +impl AsBytes for [u8; N] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self + } } /// Transforms common types to a char for basic token parsing -pub trait AsChar { +#[allow(clippy::len_without_is_empty)] +pub trait AsChar: Copy { /// makes a char from self fn as_char(self) -> char; @@ -167,8 +678,14 @@ fn is_hex_digit(self) -> bool; /// Tests that self is an octal digit fn is_oct_digit(self) -> bool; + /// Tests that self is a binary digit + fn is_bin_digit(self) -> bool; /// Gets the len in bytes for self fn len(self) -> usize; + /// Tests that self is ASCII space or tab + fn is_space(self) -> bool; + /// Tests if byte is ASCII newline: \n + fn is_newline(self) -> bool; } impl AsChar for u8 { @@ -178,7 +695,7 @@ } #[inline] fn is_alpha(self) -> bool { - (self >= 0x41 && self <= 0x5A) || (self >= 0x61 && self <= 0x7A) + matches!(self, 0x41..=0x5A | 0x61..=0x7A) } #[inline] fn is_alphanum(self) -> bool { @@ -186,22 +703,31 @@ } #[inline] fn is_dec_digit(self) -> bool { - self >= 0x30 && self <= 0x39 + matches!(self, 0x30..=0x39) } #[inline] fn is_hex_digit(self) -> bool { - (self >= 0x30 && self <= 0x39) - || (self >= 0x41 && self <= 0x46) - || (self >= 0x61 && self <= 0x66) + matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) } #[inline] fn is_oct_digit(self) -> bool { - self >= 0x30 && self <= 0x37 + matches!(self, 0x30..=0x37) + } + #[inline] + fn is_bin_digit(self) -> bool { + matches!(self, 0x30..=0x31) } #[inline] fn len(self) -> usize { 1 } + #[inline] + fn is_space(self) -> bool { + self == b' ' || self == b'\t' + } + fn is_newline(self) -> bool { + self == b'\n' + } } impl<'a> AsChar for &'a u8 { #[inline] @@ -210,7 +736,7 @@ } #[inline] fn is_alpha(self) -> bool { - (*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A) + matches!(*self, 0x41..=0x5A | 0x61..=0x7A) } #[inline] fn is_alphanum(self) -> bool { @@ -218,22 +744,31 @@ } #[inline] fn is_dec_digit(self) -> bool { - *self >= 0x30 && *self <= 0x39 + matches!(*self, 0x30..=0x39) } #[inline] fn is_hex_digit(self) -> bool { - (*self >= 0x30 && *self <= 0x39) - || (*self >= 0x41 && *self <= 0x46) - || (*self >= 0x61 && *self <= 0x66) + matches!(*self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) } #[inline] fn is_oct_digit(self) -> bool { - *self >= 0x30 && *self <= 0x37 + matches!(*self, 0x30..=0x37) + } + #[inline] + fn is_bin_digit(self) -> bool { + matches!(*self, 0x30..=0x31) } #[inline] fn len(self) -> usize { 1 } + #[inline] + fn is_space(self) -> bool { + *self == b' ' || *self == b'\t' + } + fn is_newline(self) -> bool { + *self == b'\n' + } } impl AsChar for char { @@ -262,9 +797,20 @@ self.is_digit(8) } #[inline] + fn is_bin_digit(self) -> bool { + self.is_digit(2) + } + #[inline] fn len(self) -> usize { self.len_utf8() } + #[inline] + fn is_space(self) -> bool { + self == ' ' || self == '\t' + } + fn is_newline(self) -> bool { + self == '\n' + } } impl<'a> AsChar for &'a char { @@ -293,417 +839,25 @@ self.is_digit(8) } #[inline] - fn len(self) -> usize { - self.len_utf8() - } -} - -/// Abstracts common iteration operations on the input type -pub trait InputIter { - /// The current input type is a sequence of that `Item` type. - /// - /// Example: `u8` for `&[u8]` or `char` for `&str` - type Item; - /// An iterator over the input type, producing the item and its position - /// for use with [Slice]. If we're iterating over `&str`, the position - /// corresponds to the byte index of the character - type Iter: Iterator; - - /// An iterator over the input type, producing the item - type IterElem: Iterator; - - /// Returns an iterator over the elements and their byte offsets - fn iter_indices(&self) -> Self::Iter; - /// Returns an iterator over the elements - fn iter_elements(&self) -> Self::IterElem; - /// Finds the byte position of the element - fn position

(&self, predicate: P) -> Option - where - P: Fn(Self::Item) -> bool; - /// Get the byte offset from the element's position in the stream - fn slice_index(&self, count: usize) -> Result; -} - -/// Abstracts slicing operations -pub trait InputTake: Sized { - /// Returns a slice of `count` bytes. panics if count > length - fn take(&self, count: usize) -> Self; - /// Split the stream at the `count` byte offset. panics if count > length - fn take_split(&self, count: usize) -> (Self, Self); -} - -impl<'a> InputIter for &'a [u8] { - type Item = u8; - type Iter = Enumerate; - type IterElem = Copied>; - - #[inline] - fn iter_indices(&self) -> Self::Iter { - self.iter_elements().enumerate() - } - #[inline] - fn iter_elements(&self) -> Self::IterElem { - self.iter().copied() - } - #[inline] - fn position

(&self, predicate: P) -> Option - where - P: Fn(Self::Item) -> bool, - { - self.iter().position(|b| predicate(*b)) - } - #[inline] - fn slice_index(&self, count: usize) -> Result { - if self.len() >= count { - Ok(count) - } else { - Err(Needed::new(count - self.len())) - } - } -} - -impl<'a> InputTake for &'a [u8] { - #[inline] - fn take(&self, count: usize) -> Self { - &self[0..count] - } - #[inline] - fn take_split(&self, count: usize) -> (Self, Self) { - let (prefix, suffix) = self.split_at(count); - (suffix, prefix) - } -} - -impl<'a> InputIter for &'a str { - type Item = char; - type Iter = CharIndices<'a>; - type IterElem = Chars<'a>; - #[inline] - fn iter_indices(&self) -> Self::Iter { - self.char_indices() + fn is_bin_digit(self) -> bool { + self.is_digit(2) } #[inline] - fn iter_elements(&self) -> Self::IterElem { - self.chars() - } - fn position

(&self, predicate: P) -> Option - where - P: Fn(Self::Item) -> bool, - { - for (o, c) in self.char_indices() { - if predicate(c) { - return Some(o); - } - } - None - } - #[inline] - fn slice_index(&self, count: usize) -> Result { - let mut cnt = 0; - for (index, _) in self.char_indices() { - if cnt == count { - return Ok(index); - } - cnt += 1; - } - if cnt == count { - return Ok(self.len()); - } - Err(Needed::Unknown) - } -} - -impl<'a> InputTake for &'a str { - #[inline] - fn take(&self, count: usize) -> Self { - &self[..count] + fn len(self) -> usize { + self.len_utf8() } - - // return byte index #[inline] - fn take_split(&self, count: usize) -> (Self, Self) { - let (prefix, suffix) = self.split_at(count); - (suffix, prefix) - } -} - -/// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`). -/// -/// When implementing a custom input type, it is possible to use directly the -/// default implementation: If the input type implements `InputLength`, `InputIter`, -/// `InputTake` and `Clone`, you can implement `UnspecializedInput` and get -/// a default version of `InputTakeAtPosition` and `Compare`. -/// -/// For performance reasons, you might want to write a custom implementation of -/// `InputTakeAtPosition` (like the one for `&[u8]`). -pub trait UnspecializedInput {} - -/// Methods to take as much input as possible until the provided function returns true for the current element. -/// -/// A large part of nom's basic parsers are built using this trait. -pub trait InputTakeAtPosition: Sized { - /// The current input type is a sequence of that `Item` type. - /// - /// Example: `u8` for `&[u8]` or `char` for `&str` - type Item; - - /// Looks for the first element of the input type for which the condition returns true, - /// and returns the input up to this position. - /// - /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` - fn split_at_position>(&self, predicate: P) -> IResult - where - P: Fn(Self::Item) -> bool; - - /// Looks for the first element of the input type for which the condition returns true - /// and returns the input up to this position. - /// - /// Fails if the produced slice is empty. - /// - /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` - fn split_at_position1>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool; - - /// Looks for the first element of the input type for which the condition returns true, - /// and returns the input up to this position. - /// - /// *complete version*: If no element is found matching the condition, this will return the whole input - fn split_at_position_complete>( - &self, - predicate: P, - ) -> IResult - where - P: Fn(Self::Item) -> bool; - - /// Looks for the first element of the input type for which the condition returns true - /// and returns the input up to this position. - /// - /// Fails if the produced slice is empty. - /// - /// *complete version*: If no element is found matching the condition, this will return the whole input - fn split_at_position1_complete>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool; -} - -impl InputTakeAtPosition - for T -{ - type Item = ::Item; - - fn split_at_position>(&self, predicate: P) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.position(predicate) { - Some(n) => Ok(self.take_split(n)), - None => Err(Err::Incomplete(Needed::new(1))), - } - } - - fn split_at_position1>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.position(predicate) { - Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), - Some(n) => Ok(self.take_split(n)), - None => Err(Err::Incomplete(Needed::new(1))), - } + fn is_space(self) -> bool { + *self == ' ' || *self == '\t' } - - fn split_at_position_complete>( - &self, - predicate: P, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.split_at_position(predicate) { - Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())), - res => res, - } - } - - fn split_at_position1_complete>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.split_at_position1(predicate, e) { - Err(Err::Incomplete(_)) => { - if self.input_len() == 0 { - Err(Err::Error(E::from_error_kind(self.clone(), e))) - } else { - Ok(self.take_split(self.input_len())) - } - } - res => res, - } - } -} - -impl<'a> InputTakeAtPosition for &'a [u8] { - type Item = u8; - - fn split_at_position>(&self, predicate: P) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.iter().position(|c| predicate(*c)) { - Some(i) => Ok(self.take_split(i)), - None => Err(Err::Incomplete(Needed::new(1))), - } - } - - fn split_at_position1>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.iter().position(|c| predicate(*c)) { - Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - Some(i) => Ok(self.take_split(i)), - None => Err(Err::Incomplete(Needed::new(1))), - } - } - - fn split_at_position_complete>( - &self, - predicate: P, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.iter().position(|c| predicate(*c)) { - Some(i) => Ok(self.take_split(i)), - None => Ok(self.take_split(self.input_len())), - } - } - - fn split_at_position1_complete>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.iter().position(|c| predicate(*c)) { - Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - Some(i) => Ok(self.take_split(i)), - None => { - if self.is_empty() { - Err(Err::Error(E::from_error_kind(self, e))) - } else { - Ok(self.take_split(self.input_len())) - } - } - } - } -} - -impl<'a> InputTakeAtPosition for &'a str { - type Item = char; - - fn split_at_position>(&self, predicate: P) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.find(predicate) { - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - None => Err(Err::Incomplete(Needed::new(1))), - } - } - - fn split_at_position1>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.find(predicate) { - Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - None => Err(Err::Incomplete(Needed::new(1))), - } - } - - fn split_at_position_complete>( - &self, - predicate: P, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.find(predicate) { - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - // the end of slice is a char boundary - None => unsafe { - Ok(( - self.get_unchecked(self.len()..), - self.get_unchecked(..self.len()), - )) - }, - } - } - - fn split_at_position1_complete>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool, - { - match self.find(predicate) { - Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - None => { - if self.is_empty() { - Err(Err::Error(E::from_error_kind(self, e))) - } else { - // the end of slice is a char boundary - unsafe { - Ok(( - self.get_unchecked(self.len()..), - self.get_unchecked(..self.len()), - )) - } - } - } - } + fn is_newline(self) -> bool { + *self == '\n' } } /// Indicates whether a comparison was successful, an error, or /// if more data was needed -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub enum CompareResult { /// Comparison was successful Ok, @@ -749,22 +903,6 @@ } } } - - /* - let len = self.len(); - let blen = t.len(); - let m = if len < blen { len } else { blen }; - let reduced = &self[..m]; - let b = &t[..m]; - - if reduced != b { - CompareResult::Error - } else if m < blen { - CompareResult::Incomplete - } else { - CompareResult::Ok - } - */ } #[inline(always)] @@ -783,46 +921,6 @@ } } -impl< - T: InputLength + InputIter + InputTake + UnspecializedInput, - O: InputLength + InputIter + InputTake, - > Compare for T -{ - #[inline(always)] - fn compare(&self, t: O) -> CompareResult { - let pos = self - .iter_elements() - .zip(t.iter_elements()) - .position(|(a, b)| a != b); - - match pos { - Some(_) => CompareResult::Error, - None => { - if self.input_len() >= t.input_len() { - CompareResult::Ok - } else { - CompareResult::Incomplete - } - } - } - } - - #[inline(always)] - fn compare_no_case(&self, t: O) -> CompareResult { - if self - .iter_elements() - .zip(t.iter_elements()) - .any(|(a, b)| lowercase_byte(a) != lowercase_byte(b)) - { - CompareResult::Error - } else if self.input_len() < t.input_len() { - CompareResult::Incomplete - } else { - CompareResult::Ok - } - } -} - impl<'a, 'b> Compare<&'b str> for &'a [u8] { #[inline(always)] fn compare(&self, t: &'b str) -> CompareResult { @@ -998,139 +1096,40 @@ } } -/// Slicing operations using ranges. -/// -/// This trait is loosely based on -/// `Index`, but can actually return -/// something else than a `&[T]` or `&str` -pub trait Slice { - /// Slices self according to the range argument - fn slice(&self, range: R) -> Self; -} - -macro_rules! impl_fn_slice { - ( $ty:ty ) => { - fn slice(&self, range: $ty) -> Self { - &self[range] - } - }; -} - -macro_rules! slice_range_impl { - ( [ $for_type:ident ], $ty:ty ) => { - impl<'a, $for_type> Slice<$ty> for &'a [$for_type] { - impl_fn_slice!($ty); - } - }; - ( $for_type:ty, $ty:ty ) => { - impl<'a> Slice<$ty> for &'a $for_type { - impl_fn_slice!($ty); - } - }; -} - -macro_rules! slice_ranges_impl { - ( [ $for_type:ident ] ) => { - slice_range_impl! {[$for_type], Range} - slice_range_impl! {[$for_type], RangeTo} - slice_range_impl! {[$for_type], RangeFrom} - slice_range_impl! {[$for_type], RangeFull} - }; - ( $for_type:ty ) => { - slice_range_impl! {$for_type, Range} - slice_range_impl! {$for_type, RangeTo} - slice_range_impl! {$for_type, RangeFrom} - slice_range_impl! {$for_type, RangeFull} - }; -} - -slice_ranges_impl! {str} -slice_ranges_impl! {[T]} - -macro_rules! array_impls { - ($($N:expr)+) => { - $( - impl InputLength for [u8; $N] { - #[inline] - fn input_len(&self) -> usize { - self.len() - } - } - - impl<'a> InputLength for &'a [u8; $N] { - #[inline] - fn input_len(&self) -> usize { - self.len() - } - } - - impl<'a> InputIter for &'a [u8; $N] { - type Item = u8; - type Iter = Enumerate; - type IterElem = Copied>; - - fn iter_indices(&self) -> Self::Iter { - (&self[..]).iter_indices() - } - - fn iter_elements(&self) -> Self::IterElem { - (&self[..]).iter_elements() - } - - fn position

(&self, predicate: P) -> Option - where P: Fn(Self::Item) -> bool { - (&self[..]).position(predicate) - } - - fn slice_index(&self, count: usize) -> Result { - (&self[..]).slice_index(count) - } - } - - impl<'a> Compare<[u8; $N]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: [u8; $N]) -> CompareResult { - self.compare(&t[..]) - } - - #[inline(always)] - fn compare_no_case(&self, t: [u8;$N]) -> CompareResult { - self.compare_no_case(&t[..]) - } - } +impl<'a, const N: usize> Compare<[u8; N]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: [u8; N]) -> CompareResult { + self.compare(&t[..]) + } - impl<'a,'b> Compare<&'b [u8; $N]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: &'b [u8; $N]) -> CompareResult { - self.compare(&t[..]) - } + #[inline(always)] + fn compare_no_case(&self, t: [u8; N]) -> CompareResult { + self.compare_no_case(&t[..]) + } +} - #[inline(always)] - fn compare_no_case(&self, t: &'b [u8;$N]) -> CompareResult { - self.compare_no_case(&t[..]) - } - } +impl<'a, 'b, const N: usize> Compare<&'b [u8; N]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: &'b [u8; N]) -> CompareResult { + self.compare(&t[..]) + } - impl FindToken for [u8; $N] { - fn find_token(&self, token: u8) -> bool { - memchr::memchr(token, &self[..]).is_some() - } - } + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8; N]) -> CompareResult { + self.compare_no_case(&t[..]) + } +} - impl<'a> FindToken<&'a u8> for [u8; $N] { - fn find_token(&self, token: &u8) -> bool { - self.find_token(*token) - } - } - )+ - }; +impl FindToken for [u8; N] { + fn find_token(&self, token: u8) -> bool { + memchr::memchr(token, &self[..]).is_some() + } } -array_impls! { - 0 1 2 3 4 5 6 7 8 9 - 10 11 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27 28 29 - 30 31 32 +impl<'a, const N: usize> FindToken<&'a u8> for [u8; N] { + fn find_token(&self, token: &u8) -> bool { + self.find_token(*token) + } } /// Abstracts something which can extend an `Extend`. @@ -1310,26 +1309,6 @@ } } -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -impl ErrorConvert> for error::VerboseError<(I, usize)> { - fn convert(self) -> error::VerboseError { - error::VerboseError { - errors: self.errors.into_iter().map(|(i, e)| (i.0, e)).collect(), - } - } -} - -#[cfg(feature = "alloc")] -#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] -impl ErrorConvert> for error::VerboseError { - fn convert(self) -> error::VerboseError<(I, usize)> { - error::VerboseError { - errors: self.errors.into_iter().map(|(i, e)| ((i, 0), e)).collect(), - } - } -} - impl ErrorConvert<()> for () { fn convert(self) {} } @@ -1385,7 +1364,7 @@ v.push(b'\t'); for &byte in chunk { - if (byte >= 32 && byte <= 126) || byte >= 128 { + if matches!(byte, 32..=126 | 128..=255) { v.push(byte); } else { v.push(b'.'); @@ -1411,6 +1390,241 @@ } } +/// A saturating iterator for usize. +pub struct SaturatingIterator { + count: usize, +} + +impl Iterator for SaturatingIterator { + type Item = usize; + + fn next(&mut self) -> Option { + let old_count = self.count; + self.count = self.count.saturating_add(1); + Some(old_count) + } +} + +/// Abstractions for range-like types. +pub trait NomRange { + /// The saturating iterator type. + type Saturating: Iterator; + /// The bounded iterator type. + type Bounded: Iterator; + + /// `true` if `item` is contained in the range. + fn contains(&self, item: &Idx) -> bool; + + /// Returns the bounds of this range. + fn bounds(&self) -> (Bound, Bound); + + /// `true` if the range is inverted. + fn is_inverted(&self) -> bool; + + /// Creates a saturating iterator. + /// A saturating iterator counts the number of iterations starting from 0 up to the upper bound of this range. + /// If the upper bound is infinite the iterator saturates at the largest representable value of its type and + /// returns it for all further elements. + fn saturating_iter(&self) -> Self::Saturating; + + /// Creates a bounded iterator. + /// A bounded iterator counts the number of iterations starting from 0 up to the upper bound of this range. + /// If the upper bounds is infinite the iterator counts up until the amount of iterations has reached the + /// largest representable value of its type and then returns `None` for all further elements. + fn bounded_iter(&self) -> Self::Bounded; +} + +impl NomRange for Range { + type Saturating = Range; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Included(self.start), Bound::Excluded(self.end)) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + self.start >= self.end + } + + fn saturating_iter(&self) -> Self::Saturating { + if self.end == 0 { + Range::default() + } else { + 0..self.end - 1 + } + } + + fn bounded_iter(&self) -> Self::Bounded { + if self.end == 0 { + Range::default() + } else { + 0..self.end - 1 + } + } +} + +impl NomRange for RangeInclusive { + type Saturating = Range; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Included(*self.start()), Bound::Included(*self.end())) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + !RangeInclusive::contains(self, self.start()) + } + + fn saturating_iter(&self) -> Self::Saturating { + 0..*self.end() + } + + fn bounded_iter(&self) -> Self::Bounded { + 0..*self.end() + } +} + +impl NomRange for RangeFrom { + type Saturating = SaturatingIterator; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Included(self.start), Bound::Unbounded) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + false + } + + fn saturating_iter(&self) -> Self::Saturating { + SaturatingIterator { count: 0 } + } + + fn bounded_iter(&self) -> Self::Bounded { + 0..usize::MAX + } +} + +impl NomRange for RangeTo { + type Saturating = Range; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Unbounded, Bound::Excluded(self.end)) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + false + } + + fn saturating_iter(&self) -> Self::Saturating { + if self.end == 0 { + Range::default() + } else { + 0..self.end - 1 + } + } + + fn bounded_iter(&self) -> Self::Bounded { + if self.end == 0 { + Range::default() + } else { + 0..self.end - 1 + } + } +} + +impl NomRange for RangeToInclusive { + type Saturating = Range; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Unbounded, Bound::Included(self.end)) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + false + } + + fn saturating_iter(&self) -> Self::Saturating { + 0..self.end + } + + fn bounded_iter(&self) -> Self::Bounded { + 0..self.end + } +} + +impl NomRange for RangeFull { + type Saturating = SaturatingIterator; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Unbounded, Bound::Unbounded) + } + + fn contains(&self, item: &usize) -> bool { + RangeBounds::contains(self, item) + } + + fn is_inverted(&self) -> bool { + false + } + + fn saturating_iter(&self) -> Self::Saturating { + SaturatingIterator { count: 0 } + } + + fn bounded_iter(&self) -> Self::Bounded { + 0..usize::MAX + } +} + +impl NomRange for usize { + type Saturating = Range; + type Bounded = Range; + + fn bounds(&self) -> (Bound, Bound) { + (Bound::Included(*self), Bound::Included(*self)) + } + + fn contains(&self, item: &usize) -> bool { + self == item + } + + fn is_inverted(&self) -> bool { + false + } + + fn saturating_iter(&self) -> Self::Saturating { + 0..*self + } + + fn bounded_iter(&self) -> Self::Bounded { + 0..*self + } +} + #[cfg(test)] mod tests { use super::*; @@ -1429,8 +1643,7 @@ #[test] fn test_offset_str() { - let s = "abcřèÂßÇd123"; - let a = &s[..]; + let a = "abcřèÂßÇd123"; let b = &a[7..]; let c = &a[..5]; let d = &a[5..9]; @@ -1438,4 +1651,31 @@ assert_eq!(a.offset(c), 0); assert_eq!(a.offset(d), 5); } + + #[test] + fn test_slice_index() { + let a = "abcřèÂßÇd123"; + assert_eq!(a.slice_index(0), Ok(0)); + assert_eq!(a.slice_index(2), Ok(2)); + } + + #[test] + fn test_slice_index_utf8() { + let a = "a¡€💢€¡a"; + + for (c, len) in a.chars().zip([1, 2, 3, 4, 3, 2, 1]) { + assert_eq!(c.len(), len); + } + + assert_eq!(a.slice_index(0), Ok(0)); + assert_eq!(a.slice_index(1), Ok(1)); + assert_eq!(a.slice_index(2), Ok(3)); + assert_eq!(a.slice_index(3), Ok(6)); + assert_eq!(a.slice_index(4), Ok(10)); + assert_eq!(a.slice_index(5), Ok(13)); + assert_eq!(a.slice_index(6), Ok(15)); + assert_eq!(a.slice_index(7), Ok(16)); + + assert!(a.slice_index(8).is_err()); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/arithmetic.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/arithmetic.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,9 +4,9 @@ character::complete::char, character::complete::{digit1 as digit, space0 as space}, combinator::map_res, - multi::fold_many0, + multi::fold, sequence::{delimited, pair}, - IResult, + IResult, Parser, }; // Parser definition @@ -15,7 +15,7 @@ // We parse any expr surrounded by parens, ignoring all whitespaces around those fn parens(i: &str) -> IResult<&str, i64> { - delimited(space, delimited(tag("("), expr, tag(")")), space)(i) + delimited(space, delimited(tag("("), expr, tag(")")), space).parse(i) } // We transform an integer string into a i64, ignoring surrounding whitespaces @@ -26,7 +26,8 @@ alt(( map_res(delimited(space, digit, space), FromStr::from_str), parens, - ))(i) + )) + .parse(i) } // We read an initial factor and for each time we find @@ -35,7 +36,8 @@ fn term(i: &str) -> IResult<&str, i64> { let (i, init) = factor(i)?; - fold_many0( + fold( + 0.., pair(alt((char('*'), char('/'))), factor), move || init, |acc, (op, val): (char, i64)| { @@ -45,13 +47,15 @@ acc / val } }, - )(i) + ) + .parse(i) } fn expr(i: &str) -> IResult<&str, i64> { let (i, init) = term(i)?; - fold_many0( + fold( + 0.., pair(alt((char('+'), char('-'))), term), move || init, |acc, (op, val): (char, i64)| { @@ -61,7 +65,8 @@ acc - val } }, - )(i) + ) + .parse(i) } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/arithmetic_ast.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic_ast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/arithmetic_ast.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/arithmetic_ast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,12 +3,13 @@ use std::str::FromStr; +use nom::Parser; use nom::{ branch::alt, bytes::complete::tag, character::complete::{digit1 as digit, multispace0 as multispace}, combinator::{map, map_res}, - multi::many0, + multi::many, sequence::{delimited, preceded}, IResult, }; @@ -63,7 +64,8 @@ multispace, delimited(tag("("), map(expr, |e| Expr::Paren(Box::new(e))), tag(")")), multispace, - )(i) + ) + .parse(i) } fn factor(i: &str) -> IResult<&str, Expr> { @@ -73,7 +75,8 @@ Expr::Value, ), parens, - ))(i) + )) + .parse(i) } fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr { @@ -90,32 +93,40 @@ fn term(i: &str) -> IResult<&str, Expr> { let (i, initial) = factor(i)?; - let (i, remainder) = many0(alt(( - |i| { - let (i, mul) = preceded(tag("*"), factor)(i)?; - Ok((i, (Oper::Mul, mul))) - }, - |i| { - let (i, div) = preceded(tag("/"), factor)(i)?; - Ok((i, (Oper::Div, div))) - }, - )))(i)?; + let (i, remainder) = many( + 0.., + alt(( + |i| { + let (i, mul) = preceded(tag("*"), factor).parse(i)?; + Ok((i, (Oper::Mul, mul))) + }, + |i| { + let (i, div) = preceded(tag("/"), factor).parse(i)?; + Ok((i, (Oper::Div, div))) + }, + )), + ) + .parse(i)?; Ok((i, fold_exprs(initial, remainder))) } fn expr(i: &str) -> IResult<&str, Expr> { let (i, initial) = term(i)?; - let (i, remainder) = many0(alt(( - |i| { - let (i, add) = preceded(tag("+"), term)(i)?; - Ok((i, (Oper::Add, add))) - }, - |i| { - let (i, sub) = preceded(tag("-"), term)(i)?; - Ok((i, (Oper::Sub, sub))) - }, - )))(i)?; + let (i, remainder) = many( + 0.., + alt(( + |i| { + let (i, add) = preceded(tag("+"), term).parse(i)?; + Ok((i, (Oper::Add, add))) + }, + |i| { + let (i, sub) = preceded(tag("-"), term).parse(i)?; + Ok((i, (Oper::Sub, sub))) + }, + )), + ) + .parse(i)?; Ok((i, fold_exprs(initial, remainder))) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/css.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/css.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/css.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/css.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,8 @@ use nom::bytes::complete::{tag, take_while_m_n}; use nom::combinator::map_res; -use nom::sequence::tuple; -use nom::IResult; +use nom::{IResult, Parser}; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Color { pub red: u8, pub green: u8, @@ -15,16 +14,16 @@ } fn is_hex_digit(c: char) -> bool { - c.is_digit(16) + c.is_ascii_hexdigit() } fn hex_primary(input: &str) -> IResult<&str, u8> { - map_res(take_while_m_n(2, 2, is_hex_digit), from_hex)(input) + map_res(take_while_m_n(2, 2, is_hex_digit), from_hex).parse(input) } fn hex_color(input: &str) -> IResult<&str, Color> { let (input, _) = tag("#")(input)?; - let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; + let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?; Ok((input, Color { red, green, blue })) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/custom_errors.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/custom_errors.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/custom_errors.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/custom_errors.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,7 +7,7 @@ #[cfg(feature = "alloc")] use nom::multi::count; use nom::sequence::terminated; -use nom::IResult; +use nom::{IResult, Parser}; #[derive(Debug)] pub struct CustomError(String); @@ -35,14 +35,14 @@ fn test2(input: &str) -> IResult<&str, &str, CustomError> { //terminated!(input, test1, fix_error!(CustomError, digit)) - terminated(test1, digit)(input) + terminated(test1, digit).parse(input) } fn test3(input: &str) -> IResult<&str, &str, CustomError> { - verify(test1, |s: &str| s.starts_with("abcd"))(input) + verify(test1, |s: &str| s.starts_with("abcd")).parse(input) } #[cfg(feature = "alloc")] fn test4(input: &str) -> IResult<&str, Vec<&str>, CustomError> { - count(test1, 4)(input) + count(test1, 4).parse(input) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/expression_ast.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/expression_ast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/expression_ast.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/expression_ast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,169 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alphanumeric1 as alphanumeric, digit1 as digit}, + combinator::{map, map_res}, + multi::separated_list0, + sequence::delimited, + IResult, Parser, +}; +use nom_language::precedence::{binary_op, precedence, unary_op, Assoc, Operation}; + +// Elements of the abstract syntax tree (ast) that represents an expression. +#[derive(Debug)] +pub enum Expr { + // A number literal. + Num(i64), + // An identifier. + Iden(String), + // Arithmetic operations. Each have a left hand side (lhs) and a right hand side (rhs). + Add(Box, Box), + Sub(Box, Box), + Mul(Box, Box), + Div(Box, Box), + // The function call operation. Left is the expression the function is called on, right is the list of parameters. + Call(Box, Vec), + // The ternary operator, the expressions from left to right are: The condition, the true case, the false case. + Tern(Box, Box, Box), +} + +// Prefix operators. +enum PrefixOp { + Identity, // + + Negate, // - +} + +// Postfix operators. +enum PostfixOp { + // The function call operator. In addition to its own representation "()" it carries additional information that we need to keep here. + // Specifically the vector of expressions that make up the parameters. + Call(Vec), // () +} + +// Binary operators. +enum BinaryOp { + Addition, // + + Subtraction, // - + Multiplication, // * + Division, // / + // The ternary operator can contain a single expression. + Ternary(Expr), // ?: +} + +// Parser for function calls. +fn function_call(i: &str) -> IResult<&str, PostfixOp> { + map( + delimited( + tag("("), + // Subexpressions are evaluated by recursing back into the expression parser. + separated_list0(tag(","), expression), + tag(")"), + ), + |v: Vec| PostfixOp::Call(v), + ) + .parse(i) +} + +// The ternary operator is actually just a binary operator that contains another expression. So it can be +// handled similarly to the function call operator except its in a binary position and can only contain +// a single expression. +// +// For example the expression "a IResult<&str, BinaryOp> { + map(delimited(tag("?"), expression, tag(":")), |e: Expr| { + BinaryOp::Ternary(e) + }) + .parse(i) +} + +// The actual expression parser . +fn expression(i: &str) -> IResult<&str, Expr> { + precedence( + alt(( + unary_op(2, map(tag("+"), |_| PrefixOp::Identity)), + unary_op(2, map(tag("-"), |_| PrefixOp::Negate)), + )), + // Function calls are implemented as postfix unary operators. + unary_op(1, function_call), + alt(( + binary_op( + 3, + Assoc::Left, + alt(( + map(tag("*"), |_| BinaryOp::Multiplication), + map(tag("/"), |_| BinaryOp::Division), + )), + ), + binary_op( + 4, + Assoc::Left, + alt(( + map(tag("+"), |_| BinaryOp::Addition), + map(tag("-"), |_| BinaryOp::Subtraction), + )), + ), + // Ternary operators are just binary operators with a subexpression. + binary_op(5, Assoc::Right, ternary_operator), + )), + alt(( + map_res(digit, |s: &str| match s.parse::() { + Ok(s) => Ok(Expr::Num(s)), + Err(e) => Err(e), + }), + map(alphanumeric, |s: &str| Expr::Iden(s.to_string())), + delimited(tag("("), expression, tag(")")), + )), + |op: Operation| -> Result { + use nom_language::precedence::Operation::*; + use BinaryOp::*; + use PostfixOp::*; + use PrefixOp::*; + match op { + // The identity operator (prefix +) is ignored. + Prefix(Identity, e) => Ok(e), + + // Unary minus gets evaluated to the same representation as a multiplication with -1. + Prefix(Negate, e) => Ok(Expr::Mul(Expr::Num(-1).into(), e.into())), + + // The list of parameters are taken from the operator and placed into the ast. + Postfix(e, Call(p)) => Ok(Expr::Call(e.into(), p)), + + // Meaning is assigned to the expressions of the ternary operator during evaluation. + // The lhs becomes the condition, the contained expression is the true case, rhs the false case. + Binary(lhs, Ternary(e), rhs) => Ok(Expr::Tern(lhs.into(), e.into(), rhs.into())), + + // Raw operators get turned into their respective ast nodes. + Binary(lhs, Multiplication, rhs) => Ok(Expr::Mul(lhs.into(), rhs.into())), + Binary(lhs, Division, rhs) => Ok(Expr::Div(lhs.into(), rhs.into())), + Binary(lhs, Addition, rhs) => Ok(Expr::Add(lhs.into(), rhs.into())), + Binary(lhs, Subtraction, rhs) => Ok(Expr::Sub(lhs.into(), rhs.into())), + } + }, + )(i) +} + +#[test] +fn expression_test() { + assert_eq!( + expression("-2*max(2,3)-2").map(|(i, x)| (i, format!("{:?}", x))), + Ok(( + "", + String::from("Sub(Mul(Mul(Num(-1), Num(2)), Call(Iden(\"max\"), [Num(2), Num(3)])), Num(2))") + )) + ); + + assert_eq!( + expression("a?2+c:-2*2").map(|(i, x)| (i, format!("{:?}", x))), + Ok(( + "", + String::from( + "Tern(Iden(\"a\"), Add(Num(2), Iden(\"c\")), Mul(Mul(Num(-1), Num(2)), Num(2)))" + ) + )) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/float.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/float.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,9 +2,13 @@ use nom::bytes::complete::tag; use nom::character::streaming::digit1 as digit; use nom::combinator::{map, map_res, opt, recognize}; +use nom::error::ErrorKind; +use nom::number::complete::f32; +use nom::number::complete::f64; +use nom::number::Endianness; use nom::sequence::{delimited, pair}; -use nom::IResult; - +use nom::Err; +use nom::{IResult, Parser}; use std::str; use std::str::FromStr; @@ -14,7 +18,7 @@ delimited(opt(digit), tag("."), digit), ))); let float_str = map_res(float_bytes, str::from_utf8); - map_res(float_str, FromStr::from_str)(i) + map_res(float_str, FromStr::from_str).parse(i) } fn float(i: &[u8]) -> IResult<&[u8], f32> { @@ -26,7 +30,8 @@ .unwrap_or(1f32) * value }, - )(i) + ) + .parse(i) } #[test] @@ -44,3 +49,59 @@ assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456))); assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456))); } + +#[test] +fn test_f32_big_endian() { + let be_f32 = |s| f32::<_, (_, ErrorKind)>(Endianness::Big)(s); + + assert_eq!( + be_f32(&[0x41, 0x48, 0x00, 0x00][..]), + Ok((&[] as &[u8], 12.5)) + ); +} + +#[test] +fn test_f32_little_endian() { + let le_f32 = |s| f32::<_, (_, ErrorKind)>(Endianness::Little)(s); + + assert_eq!( + le_f32(&[0x00, 0x00, 0x48, 0x41][..]), + Ok((&[] as &[u8], 12.5)) + ); +} + +#[test] +fn test_f64_big_endian() { + let be_f64 = |s| f64::<&[u8], (&[u8], ErrorKind)>(Endianness::Big)(s); + + let input = &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]; + let expected = 12.5f64; + match be_f64(input) { + Ok((rest, value)) => { + assert!(rest.is_empty()); + assert_eq!(value, expected); + } + Err(_) => assert!(false, "Failed to parse big-endian f64"), + } + + let incomplete_input = &b"abc"[..]; + assert!(matches!(be_f64(incomplete_input), Err(Err::Error(_)))); +} + +#[test] +fn test_f64_little_endian() { + let le_f64 = |s| f64::<&[u8], (&[u8], ErrorKind)>(Endianness::Little)(s); + + let input = &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]; + let expected = 12.5f64; + match le_f64(input) { + Ok((rest, value)) => { + assert!(rest.is_empty()); + assert_eq!(value, expected); + } + Err(_) => assert!(false, "Failed to parse little-endian f64"), + } + + let incomplete_input = &b"abc"[..]; + assert!(matches!(le_f64(incomplete_input), Err(Err::Error(_)))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/fnmut.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/fnmut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/fnmut.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/fnmut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ use nom::{ bytes::complete::tag, - multi::{many0, many0_count}, + multi::{many, many0_count}, + Parser, }; #[test] @@ -8,12 +9,12 @@ let mut counter = 0; let res = { - let mut parser = many0::<_, _, (), _>(|i| { + let mut parser = many::<_, (), Vec<&str>, _, _>(0.., |i| { counter += 1; tag("abc")(i) }); - parser("abcabcabcabc").unwrap() + parser.parse("abcabcabcabc").unwrap() }; println!("res: {:?}", res); @@ -25,12 +26,12 @@ let mut v = Vec::new(); let (_, count) = { - let mut parser = many0_count::<_, _, (), _>(|i| { + let mut parser = many0_count::<_, (), _>(|i| { let (i, o) = tag("abc")(i)?; v.push(o); Ok((i, ())) }); - parser("abcabcabcabc").unwrap() + parser.parse("abcabcabcabc").unwrap() }; println!("v: {:?}", v); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/ini.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/ini.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,9 +4,9 @@ alphanumeric1 as alphanumeric, char, multispace0 as multispace, space0 as space, }, combinator::{map, map_res, opt}, - multi::many0, - sequence::{delimited, pair, separated_pair, terminated, tuple}, - IResult, + multi::many, + sequence::{delimited, pair, separated_pair, terminated}, + IResult, Parser, }; use std::collections::HashMap; @@ -16,41 +16,44 @@ map_res( delimited(char('['), take_while(|c| c != b']'), char(']')), str::from_utf8, - )(i) + ) + .parse(i) } fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> { - let (i, key) = map_res(alphanumeric, str::from_utf8)(i)?; - let (i, _) = tuple((opt(space), char('='), opt(space)))(i)?; - let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8)(i)?; - let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n')))(i)?; + let (i, key) = map_res(alphanumeric, str::from_utf8).parse(i)?; + let (i, _) = (opt(space), char('='), opt(space)).parse(i)?; + let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8).parse(i)?; + let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n'))).parse(i)?; Ok((i, (key, val))) } fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> { - map(many0(terminated(key_value, opt(multispace))), |vec| { - vec.into_iter().collect() - })(i) + many(0.., terminated(key_value, opt(multispace))).parse(i) } fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> { - let (i, category) = terminated(category, opt(multispace))(i)?; + let (i, category) = terminated(category, opt(multispace)).parse(i)?; let (i, keys) = keys_and_values(i)?; Ok((i, (category, keys))) } fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> { map( - many0(separated_pair( - category, - opt(multispace), - map( - many0(terminated(key_value, opt(multispace))), - |vec: Vec<_>| vec.into_iter().collect(), + many( + 0.., + separated_pair( + category, + opt(multispace), + map( + many(0.., terminated(key_value, opt(multispace))), + |vec: Vec<_>| vec.into_iter().collect(), + ), ), - )), + ), |vec: Vec<_>| vec.into_iter().collect(), - )(i) + ) + .parse(i) } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/ini_str.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini_str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/ini_str.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/ini_str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,9 +2,9 @@ bytes::complete::{is_a, tag, take_till, take_while}, character::complete::{alphanumeric1 as alphanumeric, char, space0 as space}, combinator::opt, - multi::many0, - sequence::{delimited, pair, terminated, tuple}, - IResult, + multi::many, + sequence::{delimited, pair, terminated}, + IResult, Parser, }; use std::collections::HashMap; @@ -25,22 +25,23 @@ terminated( delimited(char('['), take_while(|c| c != ']'), char(']')), opt(is_a(" \r\n")), - )(i) + ) + .parse(i) } fn key_value(i: &str) -> IResult<&str, (&str, &str)> { let (i, key) = alphanumeric(i)?; - let (i, _) = tuple((opt(space), tag("="), opt(space)))(i)?; + let (i, _) = (opt(space), tag("="), opt(space)).parse(i)?; let (i, val) = take_till(is_line_ending_or_comment)(i)?; - let (i, _) = opt(space)(i)?; - let (i, _) = opt(pair(tag(";"), not_line_ending))(i)?; - let (i, _) = opt(space_or_line_ending)(i)?; + let (i, _) = opt(space).parse(i)?; + let (i, _) = opt(pair(tag(";"), not_line_ending)).parse(i)?; + let (i, _) = opt(space_or_line_ending).parse(i)?; Ok((i, (key, val))) } fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> { - many0(key_value)(i) + many(0.., key_value).parse(i) } fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> { @@ -51,11 +52,12 @@ } fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> { - pair(category, keys_and_values)(i) + pair(category, keys_and_values).parse(i) } +#[allow(clippy::type_complexity)] fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> { - many0(category_and_keys)(i) + many(0.., category_and_keys).parse(i) } fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/issues.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/issues.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/issues.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/issues.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,8 @@ //#![feature(trace_macros)] #![allow(dead_code)] -#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))] +#![allow(clippy::redundant_closure)] -use nom::{error::ErrorKind, Err, IResult, Needed}; +use nom::{error::ErrorKind, Err, IResult, Needed, Parser}; #[allow(dead_code)] struct Range { @@ -20,22 +20,22 @@ #[cfg(feature = "std")] mod parse_int { - use nom::HexDisplay; use nom::{ character::streaming::{digit1 as digit, space1 as space}, combinator::{complete, map, opt}, - multi::many0, + multi::many, IResult, }; + use nom::{HexDisplay, Parser}; use std::str; fn parse_ints(input: &[u8]) -> IResult<&[u8], Vec> { - many0(spaces_or_int)(input) + many(0.., spaces_or_int).parse(input) } fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> { println!("{}", input.to_hex(8)); - let (i, _) = opt(complete(space))(input)?; + let (i, _) = opt(complete(space)).parse(input)?; let (i, res) = map(complete(digit), |x| { println!("x: {:?}", x); let result = str::from_utf8(x).unwrap(); @@ -45,7 +45,8 @@ Ok(i) => i, Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e), } - })(i)?; + }) + .parse(i)?; Ok((i, res)) } @@ -66,7 +67,7 @@ fn usize_length_bytes_issue() { use nom::multi::length_data; use nom::number::streaming::be_u16; - let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16)(b"012346"); + let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16).parse(b"012346"); } #[test] @@ -104,13 +105,14 @@ use nom::bytes::complete::{is_not, tag}; use nom::multi::separated_list0; - separated_list0(tag([0x0]), is_not([0x0u8]))(i) + separated_list0(tag(&[0x0][..]), is_not([0x0u8])).parse(i) } mod issue_647 { use nom::bytes::streaming::tag; use nom::combinator::complete; use nom::multi::separated_list0; + use nom::Parser; use nom::{error::Error, number::streaming::be_f64, Err, IResult}; pub type Input<'a> = &'a [u8]; @@ -120,11 +122,12 @@ v: Vec, } - fn list<'a, 'b>( + #[allow(clippy::type_complexity)] + fn list<'a>( input: Input<'a>, - _cs: &'b f64, + _cs: &'_ f64, ) -> Result<(Input<'a>, Vec), Err>> { - separated_list0(complete(tag(",")), complete(be_f64))(input) + separated_list0(complete(tag(",")), complete(be_f64)).parse(input) } fn data(input: Input<'_>) -> IResult, Data> { @@ -162,7 +165,7 @@ i: &'a str, ) -> IResult<&'a str, usize, E> { use nom::{character::complete::char, error::context, multi::many0_count}; - many0_count(context("char_a", char('a')))(i) + many0_count(context("char_a", char('a'))).parse(i) } assert_eq!(parser::<()>("aaa"), Ok(("", 3))); } @@ -170,39 +173,17 @@ #[test] fn issue_many_m_n_with_zeros() { use nom::character::complete::char; - use nom::multi::many_m_n; - let mut parser = many_m_n::<_, _, (), _>(0, 0, char('a')); - assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); -} - -#[test] -fn issue_1027_convert_error_panic_nonempty() { - use nom::character::complete::char; - use nom::error::{convert_error, VerboseError}; - use nom::sequence::pair; - - let input = "a"; - - let result: IResult<_, _, VerboseError<&str>> = pair(char('a'), char('b'))(input); - let err = match result.unwrap_err() { - Err::Error(e) => e, - _ => unreachable!(), - }; - - let msg = convert_error(input, err); - assert_eq!( - msg, - "0: at line 1:\na\n ^\nexpected \'b\', got end of input\n\n" - ); + use nom::multi::many; + let mut parser = many::<_, (), Vec, _, _>(0..=0, char('a')); + assert_eq!(parser.parse("aaa"), Ok(("aaa", vec!()))); } #[test] fn issue_1231_bits_expect_fn_closure() { use nom::bits::{bits, complete::take}; use nom::error::Error; - use nom::sequence::tuple; pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits::<_, _, Error<_>, _, _>(tuple((take(1usize), take(1usize))))(input) + bits::<_, _, Error<_>, _, _>((take(1usize), take(1usize)))(input) } assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1)))); } @@ -211,23 +192,50 @@ fn issue_1282_findtoken_char() { use nom::character::complete::one_of; use nom::error::Error; - let parser = one_of::<_, _, Error<_>>(&['a', 'b', 'c'][..]); + let mut parser = one_of::<_, _, Error<_>>(&['a', 'b', 'c'][..]); assert_eq!(parser("aaa"), Ok(("aa", 'a'))); } #[test] +fn issue_x_looser_fill_bounds() { + use nom::{ + bytes::streaming::tag, character::streaming::digit1, error_position, multi::fill, + sequence::terminated, + }; + + fn fill_pair(i: &[u8]) -> IResult<&[u8], [&[u8]; 2]> { + let mut buf = [&[][..], &[][..]]; + let (i, _) = fill(terminated(digit1, tag(",")), &mut buf).parse(i)?; + Ok((i, buf)) + } + + assert_eq!( + fill_pair(b"123,456,"), + Ok((&b""[..], [&b"123"[..], &b"456"[..]])) + ); + assert_eq!( + fill_pair(b"123,456,789"), + Ok((&b"789"[..], [&b"123"[..], &b"456"[..]])) + ); + assert_eq!( + fill_pair(b"123,,"), + Err(Err::Error(error_position!(&b","[..], ErrorKind::Digit))) + ); +} + +#[test] fn issue_1459_clamp_capacity() { use nom::character::complete::char; // shouldn't panic use nom::multi::many_m_n; - let mut parser = many_m_n::<_, _, (), _>(usize::MAX, usize::MAX, char('a')); - assert_eq!(parser("a"), Err(nom::Err::Error(()))); + let mut parser = many_m_n::<_, (), _>(usize::MAX, usize::MAX, char('a')); + assert_eq!(parser.parse("a"), Err(nom::Err::Error(()))); // shouldn't panic use nom::multi::count; - let mut parser = count::<_, _, (), _>(char('a'), usize::MAX); - assert_eq!(parser("a"), Err(nom::Err::Error(()))); + let mut parser = count(char('a'), usize::MAX); + assert_eq!(parser.parse("a"), Err(nom::Err::Error(()))); } #[test] @@ -237,6 +245,27 @@ // previously, `count()` panicked if the parser had type `O = ()` let parser = map(tag::<_, _, Error<&str>>("abc"), |_| ()); // shouldn't panic - let result = count(parser, 3)("abcabcabcdef").expect("parsing should succeed"); + let result = count(parser, 3) + .parse("abcabcabcdef") + .expect("parsing should succeed"); assert_eq!(result, ("def", vec![(), (), ()])); } + +#[test] +fn issue_1586_parser_iterator_impl() { + use nom::{ + character::complete::{digit1, newline}, + combinator::{iterator, opt}, + sequence::terminated, + IResult, + }; + fn parse_line(i: &str) -> IResult<&str, &str> { + terminated(digit1, opt(newline)).parse(i) + } + + fn parse_input(i: &str) -> impl Iterator + '_ { + iterator(i, parse_line).map(|x| x.parse::().unwrap()) + } + + assert_eq!(parse_input("123\n456").collect::>(), vec![123, 456]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/json.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/json.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/json.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/json.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,7 +6,7 @@ character::complete::{anychar, char, multispace0, none_of}, combinator::{map, map_opt, map_res, value, verify}, error::ParseError, - multi::{fold_many0, separated_list0}, + multi::{fold, separated_list0}, number::complete::double, sequence::{delimited, preceded, separated_pair}, IResult, Parser, @@ -25,11 +25,11 @@ } fn boolean(input: &str) -> IResult<&str, bool> { - alt((value(false, tag("false")), value(true, tag("true"))))(input) + alt((value(false, tag("false")), value(true, tag("true")))).parse(input) } fn u16_hex(input: &str) -> IResult<&str, u16> { - map_res(take(4usize), |s| u16::from_str_radix(s, 16))(input) + map_res(take(4usize), |s| u16::from_str_radix(s, 16)).parse(input) } fn unicode_escape(input: &str) -> IResult<&str, char> { @@ -54,7 +54,8 @@ )), // Could be probably replaced with .unwrap() or _unchecked due to the verify checks std::char::from_u32, - )(input) + ) + .parse(input) } fn character(input: &str) -> IResult<&str, char> { @@ -73,7 +74,8 @@ }) }), preceded(char('u'), unicode_escape), - ))(input) + )) + .parse(input) } else { Ok((input, c)) } @@ -82,15 +84,18 @@ fn string(input: &str) -> IResult<&str, String> { delimited( char('"'), - fold_many0(character, String::new, |mut string, c| { + fold(0.., character, String::new, |mut string, c| { string.push(c); string }), char('"'), - )(input) + ) + .parse(input) } -fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> { +fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, Output = O, Error = E>>( + f: F, +) -> impl Parser<&'a str, Output = O, Error = E> { delimited(multispace0, f, multispace0) } @@ -99,7 +104,8 @@ char('['), ws(separated_list0(ws(char(',')), json_value)), char(']'), - )(input) + ) + .parse(input) } fn object(input: &str) -> IResult<&str, HashMap> { @@ -113,7 +119,8 @@ char('}'), ), |key_values| key_values.into_iter().collect(), - )(input) + ) + .parse(input) } fn json_value(input: &str) -> IResult<&str, JsonValue> { @@ -126,7 +133,8 @@ map(double, Num), map(array, Array), map(object, Object), - ))(input) + )) + .parse(input) } fn json(input: &str) -> IResult<&str, JsonValue> { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/mp4.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/mp4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/mp4.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/mp4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,9 +5,9 @@ bytes::streaming::{tag, take}, combinator::{map, map_res}, error::ErrorKind, - multi::many0, + multi::many, number::streaming::{be_f32, be_u16, be_u32, be_u64}, - Err, IResult, Needed, + Err, IResult, Needed, Parser, }; use std::str; @@ -26,7 +26,7 @@ } } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] #[derive(PartialEq,Eq,Debug)] struct FileType<'a> { major_brand: &'a str, @@ -34,7 +34,7 @@ compatible_brands: Vec<&'a str> } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] #[allow(non_snake_case)] #[derive(Debug,Clone)] pub struct Mvhd32 { @@ -64,7 +64,7 @@ track_id: u32 } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] #[allow(non_snake_case)] #[derive(Debug,Clone)] pub struct Mvhd64 { @@ -94,7 +94,7 @@ track_id: u32 } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn mvhd32(i: &[u8]) -> IResult<&[u8], MvhdBox> { let (i, version_flags) = be_u32(i)?; let (i, created_date) = be_u32(i)?; @@ -146,7 +146,7 @@ Ok((i, mvhd_box)) } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] fn mvhd64(i: &[u8]) -> IResult<&[u8], MvhdBox> { let (i, version_flags) = be_u32(i)?; let (i, created_date) = be_u64(i)?; @@ -244,13 +244,13 @@ } fn brand_name(input: &[u8]) -> IResult<&[u8], &str> { - map_res(take(4_usize), str::from_utf8)(input) + map_res(take(4_usize), str::from_utf8).parse(input) } fn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType<'_>> { let (i, name) = brand_name(input)?; let (i, version) = take(4_usize)(i)?; - let (i, brands) = many0(brand_name)(i)?; + let (i, brands) = many(0.., brand_name).parse(i)?; let ft = FileType { major_brand: name, @@ -287,7 +287,8 @@ map(tag("skip"), |_| MP4BoxType::Skip), map(tag("wide"), |_| MP4BoxType::Wide), unknown_box_type, - ))(input) + )) + .parse(input) } // warning, an alt combinator with 9 branches containing a tag combinator @@ -304,7 +305,8 @@ map(tag("clip"), |_| MP4BoxType::Clip), map(tag("trak"), |_| MP4BoxType::Trak), map(tag("udta"), |_| MP4BoxType::Udta), - ))(input) + )) + .parse(input) } fn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/multiline.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/multiline.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/multiline.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/multiline.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,8 @@ use nom::{ character::complete::{alphanumeric1 as alphanumeric, line_ending as eol}, - multi::many0, + multi::many, sequence::terminated, - IResult, + IResult, Parser, }; pub fn end_of_line(input: &str) -> IResult<&str, &str> { @@ -14,11 +14,11 @@ } pub fn read_line(input: &str) -> IResult<&str, &str> { - terminated(alphanumeric, end_of_line)(input) + terminated(alphanumeric, end_of_line).parse(input) } pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> { - many0(read_line)(input) + many(0.., read_line).parse(input) } #[cfg(feature = "alloc")] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/overflow.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/overflow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/overflow.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/overflow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,18 @@ -#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#![allow(clippy::unreadable_literal)] #![cfg(target_pointer_width = "64")] use nom::bytes::streaming::take; #[cfg(feature = "alloc")] -use nom::multi::{length_data, many0}; +use nom::multi::{length_data, many}; #[cfg(feature = "alloc")] use nom::number::streaming::be_u64; -use nom::sequence::tuple; -use nom::{Err, IResult, Needed}; +use nom::{Err, IResult, Needed, Parser}; // Parser definition // We request a length that would trigger an overflow if computing consumed + requested fn parser02(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - tuple((take(1_usize), take(18446744073709551615_usize)))(i) + (take(1_usize), take(18446744073709551615_usize)).parse(i) } #[test] @@ -28,7 +27,7 @@ #[cfg(feature = "alloc")] fn overflow_incomplete_length_bytes() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(length_data(be_u64))(i) + many(0.., length_data(be_u64)).parse(i) } // Trigger an overflow in length_data @@ -42,7 +41,7 @@ #[cfg(feature = "alloc")] fn overflow_incomplete_many0() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(length_data(be_u64))(i) + many(0.., length_data(be_u64)).parse(i) } // Trigger an overflow in many0 @@ -55,10 +54,8 @@ #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many1() { - use nom::multi::many1; - fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many1(length_data(be_u64))(i) + many(1.., length_data(be_u64)).parse(i) } // Trigger an overflow in many1 @@ -73,8 +70,9 @@ fn overflow_incomplete_many_till() { use nom::{bytes::complete::tag, multi::many_till}; + #[allow(clippy::type_complexity)] fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { - many_till(length_data(be_u64), tag("abc"))(i) + many_till(length_data(be_u64), tag("abc")).parse(i) } // Trigger an overflow in many_till @@ -87,10 +85,8 @@ #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many_m_n() { - use nom::multi::many_m_n; - fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many_m_n(2, 4, length_data(be_u64))(i) + many(2..=4, length_data(be_u64)).parse(i) } // Trigger an overflow in many_m_n @@ -106,7 +102,7 @@ use nom::multi::count; fn counter(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - count(length_data(be_u64), 2)(i) + count(length_data(be_u64), 2).parse(i) } assert_eq!( @@ -122,7 +118,7 @@ use nom::number::streaming::be_u8; fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - length_count(be_u8, length_data(be_u64))(i) + length_count(be_u8, length_data(be_u64)).parse(i) } assert_eq!( @@ -135,7 +131,7 @@ #[cfg(feature = "alloc")] fn overflow_incomplete_length_data() { fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(length_data(be_u64))(i) + many(0.., length_data(be_u64)).parse(i) } assert_eq!( diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/reborrow_fold.rs clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/reborrow_fold.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom/tests/reborrow_fold.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom/tests/reborrow_fold.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,26 +6,28 @@ use nom::bytes::complete::is_not; use nom::character::complete::char; use nom::combinator::{map, map_res}; -use nom::multi::fold_many0; +use nom::multi::fold; use nom::sequence::delimited; -use nom::IResult; +use nom::{IResult, Parser}; -fn atom<'a>(_tomb: &'a mut ()) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], String> { +fn atom(_tomb: &mut ()) -> impl for<'a> FnMut(&'a [u8]) -> IResult<&'a [u8], String> { move |input| { map( map_res(is_not(" \t\r\n"), str::from_utf8), ToString::to_string, - )(input) + ) + .parse(input) } } // FIXME: should we support the use case of borrowing data mutably in a parser? -fn list<'a>(i: &'a [u8], tomb: &'a mut ()) -> IResult<&'a [u8], String> { +fn list<'a>(i: &'a [u8], tomb: &mut ()) -> IResult<&'a [u8], String> { delimited( char('('), - fold_many0(atom(tomb), String::new, |acc: String, next: String| { + fold(0.., atom(tomb), String::new, |acc: String, next: String| { acc + next.as_str() }), char(')'), - )(i) + ) + .parse(i) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"375660cfef21494aaa1a90768e0054f2c9e6293e2085a28ea3ad0b70efd5bad6","CHANGELOG.md":"fd79f8ab367d50fd57136744fa2e0a198c279c9707c2a45f00ad1b62d0a637ab","Cargo.lock":"3b95f09a31e1fc281ef890f9623ac84f0a58bc3454a96b652d2f0682963f29b5","Cargo.toml":"9d07fd5cc339d8f7c0c164b2568164b808dee1d441b17631cb7b7d44d39ed778","Cargo.toml.orig":"c9cb8a6ee98d4c60dbdd5f9789aed2b8296a74be3f3d5eac265e032008ad34db","LICENSE":"4dbda04344456f09a7a588140455413a9ac59b6b26a1ef7cdf9c800c012d87f0","README.md":"3cbdcb07f9ef189ad617f40423a17f1e48ee5aba3f118f261886c139d64d26ae","doc/nom_recipes.md":"a903a6d8f9e5c935f2a4cbd632f67bc46e41934d1cc8517da9b9e7f3840c9955","src/bits/complete.rs":"640bdcad311a05d94e4b3a1a8b2105c540f80864edb75de0a570f03d4055e5ed","src/bits/mod.rs":"1c6aa26887d379384c1c823684e6f8e91b59df72664eefd8ddf0b6ca5517e669","src/bits/streaming.rs":"304cc5d565cfa30075827c1d6cb173b7cb92b101d8ebe9bc50476a00c92fd5dc","src/branch/mod.rs":"dbe1ed1bb0230310adf8e8d15e6afcf8826c7a111f8429e13fe3e9ebd3fbeae0","src/branch/tests.rs":"9a4a7b0c38fc28881d904f8ad6757a23e543f47a4c2d6fd6a9589eeb97209088","src/bytes/complete.rs":"666fa037c63292b1616cbc04c5b414a53c705d0d2ccd8d84399bbe78f573b7e9","src/bytes/mod.rs":"055e264f71a9fa2245be652cc747cfb2c3e34c3c2ba3b75e9611be51fcebea0b","src/bytes/streaming.rs":"e716e6555fbde14bfc2d7358a3edc2191df0522bc55b1f7735f9809ceb235829","src/bytes/tests.rs":"f0d9eb90d72873346e47e5592d30093eb38cbbb5fbf2e769cda776ccfff4f887","src/character/complete.rs":"7eeb5f00baab7aeaf7f392e5872d141d352951a146c0396721dab71e29b4c87b","src/character/mod.rs":"2fc6a3b19b766a3c37328d62eedbc0c9cb9612aa1d38ececd5cc579b61725fa2","src/character/streaming.rs":"de67ec5663475bc5ffa16f12d121ce9181353b16656b90216704197fca3010fc","src/character/tests.rs":"38958a709f96f077f93a72b32d8ded0a2ad6e488d9aadbe3cf1cfd8adaec06c8","src/combinator/mod.rs":"f7b9c35734f10a4b46d2e2ae874628d48fa1fe0bfc9f44325a89a14b3cfaea02","src/combinator/tests.rs":"1e56e2c1263d93bfbd244d24160a0bea41731e5158d57382e69c215427770b94","src/error.rs":"9d9bf87e76b47cfd9170f8ae50b6deeb02ff1c296aac3eb4f71ee1474dc0fba5","src/internal.rs":"5e670e0f5955af13da4b9a98d444fc721d38835b4637fe8170871fefef4e04cb","src/lib.rs":"9e05f2447ef1e5e9418953300c97d297f26f8f33c0528733a7681d8cb458346e","src/macros.rs":"11ac3dee346e5bf61015f328975cf6ea6f438683eb3b8b6c7c8e6383b0c5b7af","src/multi/mod.rs":"6093bd5909ddae76309442eba3a33716d279d219e5933a0dedef977312d6c5f8","src/multi/tests.rs":"806f89f5f347978c22e9b8cc7f8a49ad1d1fe23bff5974725b643a2ceffe8cb0","src/number/complete.rs":"a4f312c200710a446986142d19ebc78727265cf2c3b07b70dd84339051040bdd","src/number/mod.rs":"ba6eb439ee0befcc0872be7ce43b4836622af45c3dc2fc003b0d909ee42d7b20","src/number/streaming.rs":"1c2137235f093857e545069d687f50712ea457fac03961f3f6ac15c0f7e40c2a","src/sequence/mod.rs":"2dff114a950965e321cafdb215a441990f35d28756b12b2891179f348268fca2","src/sequence/tests.rs":"8dc4ca519b274d4e0694b373b2710c2e947e6074d43ec6a738a74113a09379f5","src/str.rs":"f26aa11f43e8a4a300ea0f310d599fab3f809102cfb29033ddf84f299ee8010c","src/traits.rs":"01934f8a61fc3cc5a03438a10751d3b074c89e5f3bcc96df8e43cf6b09be2308","tests/arithmetic.rs":"725efba4fc6cc811f542f3bcc8c7afd52702a66f64319d4f2796225e2e75d0ca","tests/arithmetic_ast.rs":"c7c28c988640405dd250c86045bbda75fc6ead2a769fb05eafbfbe74d97e0485","tests/css.rs":"36a2198e42e601efc611ebd6b3c6861f3ccb6a63525829ae6a2603bcdc4c2b11","tests/custom_errors.rs":"354d5a82a4f5a24b97901a3b411b4eab038c4d034047971956b9cdc12538e50d","tests/escaped.rs":"c25987ea6d9a7dde74d58a49c332d223da3a495569cb79e3fe921bce51729ead","tests/float.rs":"cdac92fb14afb75cba9d6b8f568e272a630b2cfb9f096b76c91909a3cd016869","tests/fnmut.rs":"dc9b6140eb3405d1497b05675fc4d3050785771a2afa81990d684b2edd0c9746","tests/ini.rs":"f0ce38b90057e9e0fd2329819395c420cbf1400457f9c4279414301faa38b19c","tests/ini_str.rs":"4c8f6ce3a2a245e8365837b873c25d2d8f24887313b791e2edd09a76a2d98947","tests/issues.rs":"1322ffc270ba1bedf39b295eb622ead2715ab7d60db0181af5305a0429c7819e","tests/json.rs":"8672fca70b889d6243a2f0f4c99389e22200e4363f253e83a3f26620b92f765e","tests/mp4.rs":"db6568ee9ccad70a7b567295831b961b369011f66dc2dd406851208007588600","tests/multiline.rs":"aef9768beaf5042b8629599b2094712646abb23eb11fa662b5a9bf3dfa432547","tests/overflow.rs":"a249ebeebfc5228faf9bfd5241a54a8181df476c4699ef87bb7d8a2161b9fc72","tests/reborrow_fold.rs":"66230bacd8d36e1559f1dc919ae8eab3515963c4aef85a079ec56218c9a6e676"},"package":"d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "869f8972a4383b13cf89574fda28cb7dbfd56517" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1551 @@ +# Change Log + +## [Unreleased][unreleased] + +### Thanks + +### Changed + +## 7.1.3 - 2023-01-15 + +### Thanks + +- @Shadow53 + +### Fixed + +- panic in `many` and `count` combinators when the output type is zero sized + +## 7.1.2 - 2023-01-01 + +### Thanks + +- @joubs +- @Fyko +- @LoganDark +- @darnuria +- @jkugelman +- @barower +- @puzzlewolf +- @epage +- @cky +- @wolthom +- @w1ll-i-code + +### Changed + +- documentation fixes +- tests fixes +- limit the initial capacity of the result vector of `many_m_n` to 64kiB +- bits parser now accept `Parser` implementors instead of only functions + +### Added + +- implement `Tuple` parsing for the unit type as a special case +- implement `ErrorConvert` on the unit type to make it usable as error type for bits parsers +- bool parser for bits input + +## 7.1.1 - 2022-03-14 + +### Thanks + +- @ThomasdenH +- @@SphinxKnight +- @irevoire +- @doehyunbaek +- @pxeger +- @punkeel +- @max-sixty +- @Xiretza +- @5c077m4n +- @erihsu +- @TheNeikos +- @LoganDark +- @nickelc +- @chotchki +- @ctrlcctrlv + + +### Changed + +- documentation fixes +- more examples + +## 7.1.0 - 2021-11-04 + +### Thanks + +- @nickelc +- @Stargateur +- @NilsIrl +- @clonejo +- @Strytyp +- @schubart +- @jihchi +- @nipunn1313 +- @Gungy2 +- @Drumato +- @Alexhuszagh +- @Aehmlo +- @homersimpsons +- @dne +- @epage +- @saiintbrisson +- @pymongo + +### Changed + +- documentation fixes +- Ci fixes +- the move to minimal-lexical for float parsing introduced bugs that cannot be resolved right now, so this version moves back to using the standard lib' parser. *This is a performance regression**. If you have specific requirements around float parsing, you are strongly encouraged to use [recognize_float](https://docs.rs/nom/latest/nom/number/complete/fn.recognize_float.html) and another library to convert to a f32 or f64 + +### Added + +- alt now works with 1 elment tuples + +## 7.0.0 - 2021-08-21 + +This release fixes dependency compilation issues and strengthen the minimum supported Rust version (MSRV) policy. This is also the first release without the macros that were used since nom's beginning. + +### Thanks + +- @djc +- @homersimpsons +- @lo48576 +- @myrrlyn +- @RalXYZ +- @nickelc +- @cenodis + +### Added + +- `take_until1` combinator +- more `to_owned` implementations +- `fail`: a parser that always fail, useful as default condition in other combinators +- text to number parsers: in the `character::streaming` and `character::complete` modules, there are parsers named `i8, u16, u32, u64, u128` and `u8 ,u16, u32, u64, u128` that recognize decimal digits and directly convert to a number in the target size (checking for max int size) + +### Removed + +- now that function combinators are the main way to write parsers, the old macro combinators are confusing newcomers. THey have been removed +- the `BitSlice` input type from bitvec has been moved into the [nom-bitvec](https://crates.io/crates/nom-bitvec) crate. nom does not depend on bitvec now +- regex parsers have been moved into the [nom-regex](https://crates.io/crates/nom-regex) crate. nom does not depend on regex now +- `ErrorKind::PArseTo` was not needed anymore + +### Changed + +- relax trait bounds +- some performance fixes +- `split_at_position*` functions should now be guaranteed panic free +- the `lexical-core` crate used for float parsing has now been replaced with `minimal-lexical`: the new crate is faster to compile, faster to parse, and has no dependencies + +### Fixed + +- infinite loop in `escaped` combinator +- `many_m_n` now fails if min > max + + +## 6.2.1 - 2021-06-23 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): + +- @homersimpsons + +### Fixed + +- fix documentation building + +## 6.2.0 - 2021-02-15 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): + +- @DavidKorczynski +- @homersimpsons +- @kornelski +- @lf- +- @lewisbelcher +- @ronan-d +- @weirane +- @heymind +- @marcianx +- @Nukesor + +### Added + +- nom is now regularly fuzzed through the OSSFuzz project + +### Changed + +- lots of documentation fixes +- relax trait bounds +- workarounds for dependency issues with bitvec and memchr + +## 6.1.2 - 2021-02-15 + +### Changed + +- Fix cargo feature usage in previous release + +## 6.1.1 - 2021-02-15 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): + +- @nickelc + +### Changed + +- Fix dependenciy incompatibilities: Restrict the bitvec->funty dependency to <=1.1 + +## 6.1.0 - 2021-01-23 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): + +- @sachaarbonel +- @vallentin +- @Lucretiel +- @meiomorphism +- @jufajardini +- @neithernut +- @drwilco + +### Changed + +- readme and documentation fixes +- rewrite of fold_many_m_n +- relax trait bounds on some parsers +- implement `std::error::Error` on `VerboseError` + + +## 6.0.1 - 2020-11-24 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): + +- @Leonqn +- @nickelc +- @toshokan +- @juchiast +- @shssoichiro +- @jlkiri +- @chifflier +- @fkloiber +- @Kaoet +- @Matthew Plant + +### Added + +- `ErrorConvert` implementation for `VerboseError` + +### Changed + +- CI fixes +- `fold_many*` now accept `FnMut` for the accumulation function +- relaxed input bounds on `length_count` + +# Fixed + +- documentation fixes +- the `#[deprecated]` attribute was removed from traits because it does not compile anymore on nightly +- bits and bytes combinators from the bits modules are now converted to use `FnMut` + +## 6.0.0 - 2020-10-31 + +### Thanks + +This release was done thanks to the hard work of (by order of appearance in the commit list): +- @chifflier +- @shepmaster +- @amerelo +- @razican +- @Palladinium +- @0ndorio +- Sebastian Zivota +- @keruspe +- @devonhollowood +- @parasyte +- @nnt0 +- @AntoineCezar +- @GuillaumeGomez +- @eijebong +- @stadelmanma +- @sphynx +- @snawaz +- @fosskers +- @JamesHarrison +- @calebsander +- @jthornber +- @ahmedcharles +- @rljacobson +- @benkay86 +- @georgeclaghorn +- @TianyiShi2001 +- @shnewto +- @alfriadox +- @resistor +- @myrrlyn +- @chipsenkbeil +- @ruza-net +- @fanf2 +- @jameysharp +- @FallenWarrior2k +- @jmg-duarte +- @ericseppanen +- @hbina +- Andreas Molzer +- @nickelc +- @bgourlie + +## Notable changes + +This release is a more polished version of nom 5, that came with a focus on +function parsers, by relaxing the requirements: combinators will return a +`impl FnMut` instead of `impl Fn`, allowing closures that change their context, +and parsers can be any type now, as long as they implement the new `Parser` trait. +That parser trait also comes with a few helper methods. + +Error management was often a pain point, so a lot of work went into making it easier. +Now it integrates with `std:error::Error`, the `IResult::finish()` method allows you +to convert to a more usable type, the `into` combinator can convert the error type +if there's a `From` implementation, and there are more specific error traits like +`ContextError` for the `context` combinator, and `FromExternalError` for `map_res`. +While the `VerboseError` type and its `convert_error` function saw some changes, +not many features ill be added to it, instead you are encouraged to build the error +type that corresponds to your needs if you are building a language parser. + +This version also integrates with the excellent [bitvec](https://crates.io/crates/bitvec) +crate for better bit level parsing. This part of nom was not great and a bit of a hack, +so this will give better options for those parsers. + +At last, documentation! There are now more code examples, functions and macros that require +specific cargo features are now clearly indicated, and there's a new `recipes` module +containing example patterns. + +### Breaking changes + +- the minimal Rust version is now 1.44 (1.37 if building without the `alloc` or `std` features) +- streaming parsers return the number of additional bytes they need, not the total. This was supposed to be the case everywhere, but some parsers were forgotten +- removed the `regexp_macros` cargo feature +- the `context` combinator is not linked to `ParseError` anymore, instead it come with its own `ContextError` trait +- `Needed::Size` now contains a `NonZeroUsize`, so we can reduce the structure's size by 8 bytes. When upgrading, `Needed::Size(number)` can be replaced with `Needed::new(number)` +- there is now a more general `Parser` trait, so parsers can be something else than a function. This trait also comes with combinator methods like `map`, `flat_map`, `or`. Since it is implemented on `Fn*` traits, it should not affect existing code too much +- combinators that returned a `impl Fn` now return a `impl FnMut` to allow parser closures that capture some mutable value from the context +- `separated_list` is now `separated_list0` +- removed the deprecated `methods` module +- removed the deprecated `whitespace` module +- the default error type is now a struct (`nom::error::Error`) instead of a tuple +- the `FromExternalError` allows wrapping the error returned by the function in the `map_res` combinator +- renamed the `dbg!` macro to avoid conflicts with `std::dbg!` +- `separated_list` now allows empty elements + + +### Added + +- function version of regex parsers +- `fill`: attempts to fill the output slice passed as argument +- `success`: returns a value without consuming the input +- `satisfy`: checks a predicate over the next character +- `eof` function combinator +- `consumed`: returns the produced value and the consumed input +- `length_count` function combinator +- `into`: converts a parser's output and error values if `From` implementations are available +- `IResult::finish()`: converts a parser's result to `Result<(I, O), E>` by removing the distinction between `Error` and `Failure` and panicking on `Incomplete` +- non macro versions of `u16`, `i32`, etc, with configurable endianness +- `is_newline` function +- `std::error::Error` implementation for nom's error types +- recipes section of the documentation, outlining common patterns in nom +- custom errors example +- bitstream parsing with the `BitSlice` type from the bitvec crate +- native endianness parsers +- github actions for CI + +### Changed + +- allows lexical-core 0.7 +- number parsers are now generic over the input type +- stabilized the `alloc` feature +- `convert_error` accepts a type that derefs to `&str` +- the JSON example now follows the spec better + +### Fixed +- use `fold_many0c` in the `fold_many0` macro + +## 5.1.1 - 2020-02-24 + +### Thanks + +- @Alexhuszagh for float fixes +- @AlexanderEkdahl, @JoshOrndorff, @akitsu-sanae for docs fixes +- @ignatenkobrain: dependency update +- @derekdreery: `map` implementation for errors +- @Lucretiel for docs fixes and compilation fixes +- adytzu2007: warning fixes +- @lo48576: error management fixes + +### Fixed + +- C symbols compilation errors due to old lexical-core version + +### Added + +- `Err` now has a `map` function + +### Changed + +- Make `error::context()` available without `alloc` feature + +## 5.1.0 - 2020-01-07 + +### Thanks + +- @Hywan, @nickmooney, @jplatte, @ngortheone, @ejmg, @SirWindfield, @demurgos, @spazm, @nyarly, @guedou, @adamnemecek, for docs fixes +- @Alxandr for error management bugfixes +- @Lucretiel for example fixes and optimizations +- @adytzu2007 for optimizations +- @audunhalland for utf8 fixes + +### Fixed + +- panic in `convert_error` +- `compile_error` macro usage + +### Added + +- `std::error::Error`, `std::fmt::Display`, `Eq`, `ToOwned` implementations for errors +- inline attribute for `ToUsize` + +### Changed + +- `convert_error` optimization +- `alt` optimization + +## 5.0.1 - 2019-08-22 + +### Thanks + +- @waywardmonkeys, @phaazon, @dalance for docs fixes +- @kali for `many0_m_n` fixes +- @ia0 for macros fixes + +### Fixed + +- `many0_m_n` now supports the n=1 case +- relaxed trait requirements in `cut` +- `peek!` macro reimplementation +- type inference in `value!` + +## 5.0.0 - 2019-06-24 + +This version comes with a complete rewrite of nom internals to use functions as a base +for parsers, instead of macros. Macros have been updated to use functions under +the hood, so that most existing parsers will work directly or require minimal changes. + +The `CompleteByteSlice` and `CompleteStr` input types were removed. To get different +behaviour related to streaming or complete input, there are different versions of some +parsers in different submodules, like `nom::character::streaming::alpha0` and +`nom::character::complete::alpha0`. + +The `verbose-errors` feature is gone, now the error type is decided through a generic +bound. To get equivalent behaviour to `verbose-errors`, check out `nom::error::VerboseError` + +### Thanks + +- @lowenheim helped in refactoring and error management +- @Keruspe helped in refactoring and fixing tests +- @pingiun, @Songbird0, @jeremystucki, @BeatButton, @NamsooCho, @Waelwindows, @rbtcollins, @MarkMcCaskey for a lot of help in rewriting the documentation and adding code examples +- @GuillaumeGomez for documentation rewriting and checking +- @iosmanthus for bug fixes +- @lo48576 for error management fixes +- @vaffeine for macros visibility fixes +- @webholik and @Havvy for `escaped` and `escaped_transform` fixes +- @proman21 for help on porting bits parsers + +### Added + +- the `VerboseError` type accumulates position info and error codes, and can generate a trace with span information +- the `lexical-core` crate is now used by default (through the `lexical` compilation feature) to parse floats from text +- documentation and code examples for all functions and macros + +### Changed + +- nom now uses functions instead of macros to generate parsers +- macros now use the functions under the hood +- the minimal Rust version is now 1.31 +- the verify combinator's condition function now takes its argument by reference +- `cond` will now return the error of the parser instead of None +- `alpha*`, `digit*`, `hex_digit*`, `alphanumeric*` now recognize only ASCII characters + +### Removed + +- deprecated string parsers (with the `_s` suffix), the normal version can be used instead +- `verbose-errors` is not needed anymore, now the error type can be decided when writing the parsers, and parsers provided by nom are generic over the error type +- `AtEof`, `CompleteByteSlice` and `CompleteStr` are gone, instead some parsers are specialized to work on streaming or complete input, and provided in different modules +- character parsers that were aliases to their `*1` version: eol, alpha, digit, hex_digit, oct_digit, alphanumeric, space, multispace +- `count_fixed` macro +- `whitespace::sp` can be replaced by `character::complete::multispace0` +- method combinators are now in the nom-methods crate +- `take_until_either`, `take_until_either1`, `take_until_either_and_consume` and `take_until_either_and_consume1`: they can be replaced with `is_not` (possibly combined with something else) +- `take_until_and_consume`, `take_until_and_consume1`: they can be replaced with `take_until` combined with `take` +- `sized_buffer` and `length_bytes!`: they can be replaced with the `length_data` function +- `non_empty`, `begin` and `rest_s` function +- `cond_reduce!`, `cond_with_error!`, `closure!`, `apply`, `map_res_err!`, `expr_opt!`, `expr_res!` +- `alt_complete`, `separated_list_complete`, `separated_nonempty_list_complete` + +## 4.2.3 - 2019-03-23 + +### Fixed + +- add missing `build.rs` file to the package +- fix code comparison links in changelog + +## 4.2.2 - 2019-03-04 + +### Fixed + +- regression in do_parse macro import for edition 2018 + +## 4.2.1 - 2019-02-27 + +### Fixed + +- macro expansion error in `do_parse` due to `compile_error` macro usage + +## 4.2.0 - 2019-01-29 + +### Thanks + +- @JoshMcguigan for unit test fixes +- @oza for documentation fixes +- @wackywendell for better error conversion +- @Zebradil for documentation fixes +- @tsraom for new combinators +- @hcpl for minimum Rust version tests +- @KellerFuchs for removing some unsafe uses in float parsing + +### Changed + +- macro import in edition 2018 code should work without importing internal macros now +- the regex parsers do not require the calling code to have imported the regex crate anymore +- error conversions are more ergonomic +- method combinators are now deprecated. They might be moved to a separate crate +- nom now specifies Rust 1.24.1 as minimum version. This was already the case before, now it is made explicit + +### Added + +- `many0_count` and `many1_count` to count applications of a parser instead of +accumulating its results in a `Vec` + +### Fixed + +- overflow in the byte wrapper for bit level parsers +- `f64` parsing does not use `transmute` anymore + +## 4.1.1 - 2018-10-14 + +### Fixed + +- compilation issue in verbose-errors mode for `add_return_error` + +## 4.1.0 - 2018-10-06 + +### Thanks + +- @xfix for fixing warnings, simplifying examples and performance fixes +- @dvberkel for documentation fixes +- @chifflier for fixing warnings +- @myrrlyn for dead code elimination +- @petrochenkov for removing redundant test macros +- @tbelaire for documentation fixes +- @khernyo for fixing warnings +- @linkmauve for documentation fixes +- @ProgVal for documentation fixes, warning fixes and error management +- @Nemo157 for compilation fixes +- @RReverser for documentation fixes +- @xpayn for fixing warnings +- Blas Rodriguez Irizar for documentation fixes +- @badboy for documentation fixes +- @kyrias for compilation fixes +- @kurnevsky for the `rest_len` parser +- @hjr3 for new documentation examples +- @fengalin for error management +- @ithinuel for the pcap example project +- @phaazon for documentation fixes +- @juchiast for documentation fixes +- @jrakow for the `u128` and `i128` parsers +- @smarnach for documentation fixes +- @derekdreery for `pub(crate)` support +- @YaLTeR for `map_res_err!` + +### Added + +- `rest_len` parser, returns the length of the remaining input +- `parse_to` has its own error code now +- `u128` and `i128` parsers in big and little endian modes +- support for `pub(crate)` syntax +- `map_res_err!` combinator that appends the error of its argument function in verbose errors mode + +### Fixed + +- lots of unused imports warnings were removed +- the `bytes` combinator was not compiling in some cases +- the big and little endian combinators now work without external imports +- CI is now faster and uses less cache +- in `add_return_error`, the provided error code is now evaluated only once + +### Changed + +- `fold_many1` will now transmit a `Failure` instead of transforming it to an `Error` +- `float` and `double` now work on all of nom's input types (`&[u8]`, `&str`, `CompleteByteSlice`, `CompleteStr` and any type that implements the required traits). `float_s` and `double_s` got the same modification, but are now deprecated +- `CompleteByteSlice` and `CompleteStr` get a small optimization by inlining some functions + + +## 4.0.0 - 2018-05-14 + +### Thanks + +- @jsgf for the new `AtEof` trait +- @tmccombs for fixes on `escaped*` combinators +- @s3bk for fixes around non Copy input types and documentation help +- @kamarkiewicz for fixes to no_std and CI +- @bheisler for documentation and examples +- @target-san for simplifying the `InputIter` trait for `&[u8]` +- @willmurphyscode for documentation and examples +- @Chaitanya1416 for typo fixes +- @fflorent for `input_len()` usage fixes +- @dbrgn for typo fixes +- @iBelieve for no_std fixes +- @kpp for warning fixes and clippy fixes +- @keruspe for fixes on FindToken +- @dtrebbien for fixes on take_until_and_consume1 +- @Henning-K for typo fixes +- @vthriller for documentation fixes +- @federicomenaquintero and @veprbl for their help fixing the float parsers +- @vmchale for new named_args versions +- @hywan for documentation fixes +- @fbenkstein for typo fixes +- @CAD97 for catching missing trait implementations +- @goldenlentils for &str optimizations +- @passy for typo fixes +- @ayrat555 for typo fixes +- @GuillaumeGomez for documentation fixes +- @jrakow for documentation fixes and fixes for `switch!` +- @phlosioneer for documentation fixes +- @creativcoder for typo fixes +- @derekdreery for typo fixes +- @lucasem for implementing `Deref` on `CompleteStr` and `CompleteByteSlice` +- @lowenheim for `parse_to!` fixes +- @myrrlyn for trait fixes around `CompleteStr` and `CompleteByteSlice` +- @NotBad4U for fixing code coverage analysis +- @murarth for code formatting +- @glandium for fixing build in no_std +- @csharad for regex compatibility with `CompleteStr` +- @FauxFaux for implementing `AsRef` on `CompleteStr` +- @jaje for implementing `std::Error` on `nom:Err` +- @fengalin for warning fixes +- @@khernyo for doc formatting + +Special thanks to @corkami for the logo :) + +### Breaking changes + +- the `IResult` type now becomes a `Result` from the standard library +- `Incomplete` now returns the additional data size needed, not the total data size needed +- verbose-errors is now a superset of basic errors +- all the errors now include the related input slice +- the arguments from `error_position` and other such macros were swapped to be more consistent with the rest of nom +- automatic error conversion: to fix error type inference issues, a custom error type must now implement `std::convert::From` +- the `not!` combinator returns unit `()` +- FindToken's calling convention was swapped +- the `take_*` combinators are now more coherent and stricter, see commit 484f6724ea3ccb for more information +- `many0` and other related parsers will now return `Incomplete` if the reach the end of input without an error of the child parser. They will also return `Incomplete` on an empty input +- the `sep!` combinator for whitespace only consumes whitespace in the prefix, while the `ws!` combinator takes care of consuming the remaining whitespace + +### Added + +- the `AtEof` trait for input type: indicate if we can get more input data later (related to streaming parsers and `Incomplete` handling) +- the `escaped*` parsers now support the `&str`input type +- the `Failure` error variant represents an unrecoverable error, for which `alt` and other combinators will not try other branches. This error means we got in the right part of the code (like, a prefix was checked correctly), but there was an error in the following parts +- the `CompleteByteSlice` and `CompleteStr` input types consider there will be no more refill of the input. They fixed the `Incomplete` related issues when we have all of the data +- the `exact!()` combinator will fail if we did not consume the whole input +- the `take_while_m_n!` combinator will match a specified number of characters +- `ErrorKind::TakeUntilAndConsume1` +- the `recognize_float` parser will match a float number's characters, but will not transform to a `f32` or `f64` +- `alpha` and other basic parsers are now much stricter about partial inputs. We also introduce the `*0` and `*1` versions of those parsers +- `named_args` can now specify the input type as well +- `HexDisplay` is now implemented for `&str` +- `alloc` feature +- the `InputTakeAtposition` trait allows specialized implementations of parsers like `take_while!` + +### Removed + +- the producers and consumers were removed +- the `error_code` and `error_node` macros are not used anymore + +### Fixed + +- `anychar!` now works correctly with multibyte characters +- `take_until_and_consume1!` no longer results in "no method named \`find_substring\`" and "no method named \`slice\`" compilation errors +- `take_until_and_consume1!` returns the correct Incomplete(Needed) amount +- `no_std` compiles properly, and nom can work with `alloc` too +- `parse_to!` now consumes its input + +### Changed + +- `alt` and other combinators will now clone the input if necessary. If the input is already `Copy` there is no performance impact +- the `rest` parser now works on various input types +- `InputIter::Item` for `&[u8]` is now a `u8` directly, not a reference +- we now use the `compile_error` macro to return a compile time error if there was a syntax issue +- the permutation combinator now supports optional child parsers +- the float numbers parsers have been refactored to use one common implementation that is nearly 2 times faster than the previous one +- the float number parsers now accept more variants + + +## 3.2.1 - 2017-10-27 + +### Thanks + +- @ordian for `alt_complete` fixes +- @friedm for documentation fixes +- @kali for improving error management + +### Fixed + +- there were cases where `alt_complete` could return `Incomplete` + +### Added + +- an `into_error_kind` method can be used to transform any error to a common value. This helps when the library is included multiple times as dependency with different feature sets + + +## 3.2.0 - 2017-07-24 + +### Thanks + +- @jedireza for documentation fixes +- @gmorenz for the `bytes` combinator +- @meh for character combinator fixes for UTF-8 +- @jethrogb for avoiding move issues in `separated_list` + +### Changed + +- new layout for the main page of documentation +- `anychar` can now work on any input type +- `length_bytes` is now an alias for `length_data` + +### Fixed + +- `one_of`, `none_of` and `char` will now index correctly UTF-8 characters +- the `compiler_error` macro is now correctly exported + + +### Added + +- the `bytes` combinator transforms a bit stream back to a byte slice for child parsers + +## 3.1.0 - 2017-06-16 + +### Thanks + +- @sdroege: implementing be_i24 and le_i24 +- @Hywan: integrating faster substring search using memchr +- @nizox: fixing type issues in bit stream parsing +- @grissiom: documentation fixes +- @doomrobo: implementing separated_list_complete and separated_nonempty_list_complete +- @CWood1: fixing memchr integration in no_std +- @lu_zero: integrating the compiler_error crate +- @dtolnay: helping debug a type inference issue in map + +### Changed + +- memchr is used for substring search if possible +- if building on nightly, some common syntax errors will display a specific error message. If building no stable, display the documentation to activate those messages +- `count` no longer preallocates its vector + +### Fixed + +- better type inference in alt_complete +- `alt` should now work with whitespace parsing +- `map` should not make type inference errors anymore + +### Added + +- be_i24 and le_i24, parsing big endian and little endian signed 24 bit integers +- `separated_list_complete` and `separated_nonempty_list_complete` will treat incomplete from sub parsers as error + +## 3.0.0 - 2017-05-12 + +### Thanks + +- Chris Pick for some `Incomplete` related refactors +- @dbrgn for documentation fixes +- @valarauca for adding `be_u24` +- @ithinuel for usability fixes +- @evuez for README readability fixes and improvements to `IResult` +- @s3bk for allowing non-`Copy` types as input +- @keruspe for documentation fixes +- @0xd34d10cc for trait fixes on `InputIter` +- @sdleffler for lifetime shenanigans on `named_args` +- @chengsun for type inference fixes in `alt` +- @iBelieve for adding str to no_std +- @Hywan for simplifying code in input traits +- @azerupi for extensive documentation of `alt` and `alt_complete` + +### Breaking Changes + +- `escaped`, `separated_list` and `separated_nonempty_list` can now return `Incomplete` when necessary +- `InputIter` does not require `AsChar` on its `Item` type anymore +- the `core` feature that was putting nom in `no_std` mode has been removed. There is now a `std` feature, activated by default. If it is not activated, nom is in `no_std` +- in `verbose-errors` mode, the error list is now stored in a `Vec` instead of a box based linked list +- `chain!` has finally been removed + +### Changed + +- `Endianness` now implements `Debug`, `PartialEq`, `Eq`, `Clone` and `Copy` +- custom input types can now be cloned if they're not `Copy` +- the infamous 'Cannot infer type for E' error should happen less often now +- `str` is now available in `no_std` mode + +### Fixed + +- `FileProducer` will be marked as `Eof` on full buffer +- `named_args!` now has lifetimes that cannot conflict with the lifetimes from other arguments + +### Added + +- `be_u24`: big endian 24 bit unsigned integer parsing +- `IResult` now has a `unwrap_or` method + + +## 2.2.1 - 2017-04-03 + +### Thanks + +- @Victor-Savu for formatting fixes in the README +- @chifflier for detecting and fixing integer overflows +- @utkarshkukreti for some performance improvements in benchmarks + +### Changed + +- when calculating how much data is needed in `IResult::Incomplete`, the addition could overflow (it is stored as a usize). This would apparently not result in any security vulnerability on release code + +## 2.2.0 - 2017-03-20 + +### Thanks + +- @seppo0010 for fixing `named_args` +- @keruspe for implementing or() on `IResult`, adding the option of default cases in `switch!`, adding support for `cargo-travis` +- @timlyo for documentation fixes +- @JayKickliter for extending `hex_u32` +- @1011X for fixing regex integration +- @Kerollmops for actually marking `chain!` as deprecated +- @joliss for documentation fixes +- @utkarshkukreti for tests refactoring and performance improvement +- @tmccombs for documentation fixes + +### Added + +- `IResult` gets an `or()` method +- `take_until1`, `take_until_and_consume1`, `take_till1!` and `take_till1_s!` require at least 1 character + +### Changed + +- `hex_u32` accepts uppercase digits as well +- the character based combinators leverage the input traits +- the whitespace parsers now work on &str and other types +- `take_while1` returns `Incomplete` on empty input +- `switch!` can now take a default case + +### Fixed + +- `named_args!` now imports `IResult` directly +- the upgrade to regex 0.2 broke the regex combinators, they work now + +## 2.1.0 - 2017-01-27 + +### Thanks + +- @nickbabcock for documentation fixes +- @derekdreery for documentation fixes +- @DirkyJerky for documentation fixes +- @saschagrunert for documentation fixes +- @lucab for documentation fixes +- @hyone for documentation fixes +- @tstorch for factoring `Slice` +- @shepmaster for adding crate categories +- @antoyo for adding `named_args!` + +### Added + +- `verify!` uses a first parser, then applies a function to check that its result satisfies some conditions +- `named_args!` creates a parser function that can accept other arguments along with the input +- `parse_to!` will use the `parse` method from `FromStr` to parse a value. It will automatically translate the input to a string if necessary +- `float`, `float_s`, `double`, `double_s` can recognize floating point numbers in text + +### Changed + +- `escaped!` will now return `Incomplete` if needed +- `permutation!` supports up to 20 child parsers + +## 2.0.1 - 2016-12-10 + +Bugfix release + +*Warning*: there is a small breaking change, `add_error!` is renamed to `add_return_error!`. This was planned for the 2.0 release but was forgotten. This is a small change in a feature that not many people use, for a release that is not yet widely in use, so there will be no 3.0 release for that change. + +### Thanks + +- @nickbabcock for catching and fixing the `add_error!` mixup +- @lucab for documentation fixes +- @jtdowney for noticing that `tag_no_case!` was not working at all for byte slices + +### Fixed + +- `add_error!` has been renamed to `add_return_error!` +- the `not!` combinator now accepts functions +- `tag_no_case!` is now working as accepted (before, it accepted everything) + + +## 2.0 - 2016-11-25 + +The 2.0 release is one of the biggest yet. It was a good opportunity to clean up some badly named combinators and fix invalid behaviours. + +Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented. + +This version also adds a lot of interesting features, like the permutation combinator or whitespace separated formats support. + +### Thanks + +- @lu-zero for license help +- @adamgreig for type inference fixes +- @keruspe for documentation and example fixes, for the `IResult => Result` conversion work, making `AsChar`'s method more consistent, and adding `many_till!` +- @jdeeny for implementing `Offset` on `&str` +- @vickenty for documentation fixes and his refactoring of `length_value!` and `length_bytes!` +- @overdrivenpotato for refactoring some combinators +- @taralx for documentation fixes +- @keeperofdakeys for fixing eol behaviour, writing documentation and adding `named_attr!` +- @jturner314 for writing documentation +- @bozaro for fixing compilation errors +- @uniphil for adding a `crates.io` badge +- @badboy for documentation fixes +- @jugglerchris for fixing `take_s!` +- @AndyShiue for implementing `Error` and `Display` on `ErrorKind` and detecting incorrect UTF-8 string indexing + +### Added + +- the "simple" error management system does not accumulates errors when backtracking. This is a big perf gain, and is activated by default in nom 2.0 +- nom can now work on any type that implement the traits defined in `src/traits.rs`: `InputLength`, `InputIter`, `InputTake`, `Compare`, `FindToken`, `FindSubstring`, `Slice` +- the documentation from Github's wiki has been moved to the `doc/` directory. They are markdown files that you can build with [cargo-external-doc](https://crates.io/crates/cargo-external-doc) +- whitespace separated format support: with the `ws!` combinator, you can automatically introduce whitespace parsers between all parsers and combinators +- the `permutation!` combinator applies its child parsers in any order, as long as they all succeed once, and return a tuple of the results +- `do_parse!` is a simpler alternative to `chain!`, which is now deprecated +- you can now transform an `IResult` in a `std::result::Result` +- `length_data!` parses a length, and returns a subslice of that length +- `tag_no_case!` provides case independent comparison. It works nicely, without any allocation, for ASCII strings, but for UTF-8 strings, it defaults to an unsatisfying (and incorrect) comparison by lowercasing both strings +- `named_attr!` creates functions like `named!` but can add attributes like documentation +- `many_till!` applies repeatedly its first child parser until the second succeeds + +### Changed + +- the "verbose" error management that was available in previous versions is now activated by the "verbose-errors" compilation feature +- code reorganization: most of the parsers were moved in separate files to make the source easier to navigate +- most of the combinators are now independent from the input type +- the `eof` function was replaced with the `eof!` macro +- `error!` and `add_error!` were replaced with `return_error!` and `add_return_error!` to fix the name conflict with the log crate +- the `offset()` method is now in the `Offset` trait +- `length_value!` has been renamed to `length_count!`. The new `length_value!` selects a slice and applies the second parser once on that slice +- `AsChar::is_0_to_9` is now `AsChar::is_dec_digit` +- the combinators with configurable endianness now take an enum instead of a boolean as parameter + +### Fixed +- the `count!`, `count_fixed!` and `length_*!` combinator calculate incomplete data needs correctly +- `eol`, `line_ending` and `not_line_ending` now have a consistent behaviour that works correctly with incomplete data +- `take_s!` didn't correctly handle the case when the slice is exactly the right length + +## 1.2.4 - 2016-07-20 + +### Thanks +- @Phlosioneer for documentation fixes +- @sourrust for fixing offsets in `take_bits!` +- @ChrisMacNaughton for the XFS crate +- @pwoolcoc for `rest_s` +- @fitzgen for more `IResult` methods +- @gtors for the negative lookahead feature +- @frk1 and @jeandudey for little endian float parsing +- @jethrogb for fixing input usage in `many1` +- @acatton for beating me at nom golf :D + +### Added +- the `rest_s` method on `IResult` returns the remaining `&str` input +- `unwrap_err` and `unwrap_inc` methods on `IResult` +- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input +- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754) +- + +### Fixed +- documentation fixes +- `take_bits!` is now more precise +- `many1` inccorectly used the `len` function instead of `input_len` +- the INI parser is simpler +- `recognize!` had an early `return` that is removed now + +## 1.2.3 - 2016-05-10 + +### Thanks +- @lu-zero for the contribution guidelines +- @GuillaumeGomez for fixes on `length_bytes` and some documentation +- @Hywan for documentation and test fixes +- @Xirdus for correct trait import issues +- @mspiegel for the new AST example +- @cholcombe973 for adding the `cond_with_error!` combinator +- @tstorch for refactoring `many0!` +- @panicbit for the folding combinators +- @evestera for `separated_list!` fixes +- @DanielKeep for correcting some enum imports + +### Added +- Regular expression combinators starting with `re_bytes_` work on byte slices +- example parsing arithmetic expressions to an AST +- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded +- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser + +### Fixed +- `length_bytes!` converts the result of its child parser to usize +- `take_till!` now imports `InputLength` instead of assuming it's in scope +- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value +- no more warnings on build + +### Changed +- simpler implementation of `many0!` + +## 1.2.2 - 2016-03-09 + +### Thanks +- @conradev for fixing `take_until_s!` +- @GuillaumeGomez for some documentation fixes +- @frewsxcv for some documentation fixes +- @tstorch for some test refactorings + +### Added +- `nom::Err` now implements `std::error::Error` + +### Fixed +- `hex_u32` does not parses more than 8 chars now +- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore + +## 1.2.1 - 2016-02-23 + +### Thanks +- @sourrust for adding methods to `IResult` +- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed` +- @joelself for fixing the method system + +### Added + +- mapping methods over `IResult` and `Needed` + +### Changed + +- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release +- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static` + +### Fixed + +- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`. +- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI + +## 1.2.0 - 2016-02-08 + +### Thanks +- @zentner-kyle for type inference fixes +- @joelself for his work on `&str` parsing and method parsers +- @GuillaumeGomez for implementing methods on `IResult` +- @dirk for the `alt_complete!` combinator +- @tstorch for a lot of refactoring work and unit tests additions +- @jansegre for the hex digit parsers +- @belgum for some documentation fixes +- @lwandrebeck for some documentation fixes and code fixes in `hex_digit` + +### Added +- `take_until_and_consume_s!` for consumption of string data until a tag +- more function patterns in `named!`. The error type can now be specified +- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly +- more unit tests for a lot of combinators +- hexadecimal digit parsers +- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!` +- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators + +### Fixed +- there were type inference issues in a few combinators. They will now be easier to compile +- `peek!` compilation with bare functions +- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes +- some method implementations were missing on `IResult` (with specified error type instead of implicit) + +## 1.1.0 - 2016-01-01 + +This release adds a lot of features related to `&str` parsing. The previous versions +were focused on `&[u8]` and bit streams parsing, but there's a need for more text +parsing with nom. The parsing functions like `alpha`, `digit` and others will now +accept either a `&[u8]` or a `&str`, so there is no breaking change on that part. + +There are also a few performance improvements and documentation fixes. + +### Thanks +- @Binero for pushing the work on `&str` parsing +- @meh for fixing `Option` and `Vec` imports +- @hoodie for a documentation fix +- @joelself for some documentation fixes +- @vberger for his traits magic making nom functions more generic + +### Added + +- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!` +- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds + +### Changed + +- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete` +- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations +- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input +- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input + +### Fixed + +- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size +- `Option,` `Some`, `None` and `Vec` are now used with full path imports + +## 1.0.1 - 2015-11-22 + +This releases makes the 1.0 version compatible with Rust 1.2 and 1.3 + +### Thanks +- @steveklabnik for fixing lifetime issues in Producers and Consumers + +## 1.0.0 - 2015-11-16 + +Stable release for nom. A lot of new features, a few breaking changes + +### Thanks +- @ahenry for macro fixes +- @bluss for fixing documentation +- @sourrust for cleaning code and debugging the new streaming utilities +- @meh for inline optimizations +- @ccmtaylor for fixing function imports +- @soro for improvements to the streaming utilities +- @breard-r for catching my typos +- @nelsonjchen for catching my typos too +- @divarvel for hex string parsers +- @mrordinaire for the `length_bytes!` combinator + +### Breaking changes +- `IResult::Error` can now use custom error types, and is generic over the input type +- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers +- `nom::ErrorCode` is now `nom::ErrorKind` +- `filter!` has been renamed to `take_while!` +- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete` +- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser +- `IResult` does not require a lifetime tag anymore, yay! + +### Added + +- `complete!` will return an error if the child parser returned `Incomplete` +- `add_error!` will wrap an error, but allow backtracking +- `hex_u32` parser + +### Fixed +- the behaviour around `Incomplete` is better for most parsers now + +## 0.5.0 - 2015-10-16 + +This release fixes a few issues and stabilizes the code. + +### Thanks +- @nox for documentation fixes +- @daboross for linting fixes +- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!` +- @bluss for tracking down and fixing issues with unsafe code +- @meh for inlining parser functions +- @ccmtaylor for fixing import of `str::from_utf8` + +### Fixed +- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters + +### Changed +- the type used in `count_fixed!` must be `Copy` +- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete +- optional parsers in `chain!` can return `Incomplete` + +## 0.4.0 - 2015-09-08 + +Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements! + +### Thanks +- @frewsxcv for documentation fixes +- @ngrewe for his work on producers and consumers +- @meh for fixes on `chain!` and for the `rest` parser +- @daboross for refactoring `many0!` and `many1!` +- @aleksander for the `switch!` combinator idea +- @TechnoMancer for his help with bit level parsing +- @sxeraverx for pointing out a bug in `is_a!` + +### Fixed +- `count_fixed!` must take an explicit type as argument to generate the fixed-size array +- optional parsing behaviour in `chain!` +- `count!` can take 0 elements +- `is_a!` and `is_not!` can now consume the whole input + +### Added +- it is now possible to seek to the end of a `MemProducer` +- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete` +- `rest` will return the remaining input +- consumers can now seek to and from the end of input +- `switch!` applies a first parser then matches on its result to choose the next parser +- bit-level parsers +- character-level parsers +- regular expression parsers +- implementation of `take_till!`, `take_while!` and `take_while1!` + +### Changed +- `alt!` can return `Incomplete` +- the error analysis functions will now take references to functions instead of moving them +- performance improvements on producers +- performance improvement for `filter!` +- performance improvement for `count!`: a `Vec` of the right size is directly allocated + +## 0.3.11 - 2015-08-04 + +### Thanks +- @bluss for remarking that the crate included random junk lying non committed in my local repository + +### Fixed +- cleanup of my local repository will ship less files in the crates, resulting in a smaller download + +## 0.3.10 - 2015-08-03 + +### Added + +- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!` +- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries +- bit level parsers are all written in `src/bits.rs` + +### Changed + +- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!` + +## 0.3.9 - 2015-07-20 + +### Thanks +- @badboy for fixing `filter!` +- @idmit for some documentation fixes + +### Added +- `opt_res!` applies a parser and transform its result in a Result. This parser never fails +- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false +- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result +- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed +- Arithmetic expression evaluation and parsing example +- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version +- type information for combinators. This will make the documentation a bit easier to navigate + +### Fixed +- `map_opt!` and `map_res!` had issues with argument order due to bad macros +- `delimited!` did not compile for certain combinations of arguments +- `filter!` did not return a byte slice but a fixed array + +## 0.3.8 - 2015-07-03 + +### Added +- code coverage is now calculated automatically on Travis CI +- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call +- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it + +### Fixed +- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported +- if a `MemProducer` reached its end, it should always return `Eof` +- `map!` had issues with argument matching + +## 0.3.7 - 2015-06-24 + +### Added +- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult +- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])` + +### Fixed +- `count_fixed!` argument parsing works again + +## 0.3.6 - 2015-06-15 + +### Added +- documentation for a few functions +- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error +- `named!` now handles the alternative `named!(pub fun_name, ...)` + +### Fixed +- `filter!` now returns the whole input if the filter function never returned false +- `take!` casts its argument as usize, so it can accepts any integer type now + +## 0.3.5 - 2015-06-10 + +### Thanks +- @cmr for some documentation fixes + +### Added +- `count_fixed!` returns a fixed array + +### Fixed +- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime + +### Changed +- functions and traits exported from `nom::util` are now directly in `nom::` + +## 0.3.4 - 2015-06-09 + +### Thanks +- @andrew-d for fixes on `cond!` +- @keruspe for features in `chain!` + +### Added +- `chain!` can now have mutable fields + +### Fixed +- `cond!` had an infinite macro recursion + +### Changed +- `chain!` generates less code now. No apprent compilation time improvement + +## 0.3.3 - 2015-06-09 + +### Thanks +- @andrew-d for the little endian signed integer parsers +- @keruspe for fixes on `count!` + +### Added +- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers + +### Changed +- the `alt!` parser compiles much faster, even with more than 8 branches +- `count!` can now return a fixed size array instead of a growable vector + +## 0.3.2 - 2015-05-31 + +### Thanks +- @keruspe for the `take_str` parser and the function application combinator + +### Added +- `take_str!`: takes the specified number of bytes and return a UTF-8 string +- `apply!`: do partial application on the parameters of a function + +### Changed +- `Needed::Size` now contains a `usize` instead of a `u32` + +## 0.3.1 - 2015-05-21 + +### Thanks +- @divarvel for the big endian signed integer parsers + +### Added +- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers +- the `core` feature can be passed to cargo to build with `no_std` +- colored hexdump can be generated from error chains + +## 0.3.0 - 2015-05-07 + +### Thanks +- @filipegoncalves for some documentation and the new eof parser +- @CrimsonVoid for putting fully qualified types in the macros +- @lu_zero for some documentation fixes + +### Added +- new error types that can contain an error code, an input slice, and a list of following errors +- `error!` will cut backtracking and return directly from the parser, with a specified error code +- `eof` parser, successful if there is no more input +- specific error codes for the parsers provided by nom + +### Changed +- fully qualified types in macros. A lot of imports are not needed anymore + +### Removed +- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`) + +## 0.2.2 - 2015-04-12 + +### Thanks +- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1 +- @thehydroimpulse for suggesting public named parsers +- @skade for removing the dependency on the collections gate + +### Added +- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));` +- `pair!(X,Y)` returns a tuple `(x, y)` +- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)` +- `preceded!(opening, X)` returns `x` +- `terminated!(X, closing)` returns `x` +- `delimited(opening, X, closing)` returns `x` +- `separated_list(sep, X)` returns a `Vec` +- `separated_nonempty_list(sep, X)` returns a `Vec` of at list one element + +### Changed +- `many0!` and `many1!` forbid parsers that do not consume input +- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte + +## 0.2.1 - 2015-04-04 + +### Thanks +- @mtsr for catching the remaining debug println! +- @jag426 who killed a lot of warnings +- @skade for removing the dependency on the core feature gate + + +### Added +- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64 +- `count!` to apply a parser a specified number of times +- `cond!` applies a parser if the condition is met +- more parser development tools in `util::*` + +### Fixed +- in one case, `opt!` would not compile + +### Removed +- most of the feature gates are now removed. The only one still needed is `collections` + +## 0.2.0 - 2015-03-24 +*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`* + +### Thanks +- Ryman for the AsBytes implementation +- jag426 and jaredly for documentation fixes +- eternaleye on #rust IRC for his help on the new macro syntax + +### Changed +- the AsBytes trait improves readability, no more b"...", but "..." instead +- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too +- `alt!` can pass the result of the parser to a closure +- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!` + +### Added +- `peek!` macro: matches the future input but does not consume it +- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser +- benchmarks are available at https://github.com/Geal/nom_benchmarks +- more documentation +- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions. +- `named!`, `closure!` and `call!` macros used to support the unnamed syntax +- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result` + +### Fixed +- `is_a!` is now working properly + +### Removed +- the `o!` macro does less than `chain!`, so it has been removed +- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now + +## 0.1.6 - 2015-02-24 +### Changed +- consumers must have an end method that will be called after parsing + +### Added +- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64 +- producers can seek +- function and macros documentation +- README documentation +### Fixed +- lifetime declarations +- tag! can return Incomplete + +## 0.1.5 - 2015-02-17 +### Changed +- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor + +### Fixed +- woeks with rustc f1bb6c2f4 + +## 0.1.4 - 2015-02-17 +### Changed +- the chaining macro can take optional arguments with '?' + +## 0.1.3 - 2015-02-16 +### Changed +- the chaining macro now takes the closure at the end of the argument list + +## 0.1.2 - 2015-02-16 +### Added +- flat_map implementation for <&[u8], &[u8]> +- chaining macro +- partial MP4 parser example + + +## 0.1.1 - 2015-02-06 +### Fixed +- closure syntax change + +## Compare code + +* [unreleased](https://github.com/Geal/nom/compare/7.1.3...HEAD) +* [7.1.2](https://github.com/Geal/nom/compare/7.1.2...7.1.3) +* [7.1.2](https://github.com/Geal/nom/compare/7.1.1...7.1.2) +* [7.1.1](https://github.com/Geal/nom/compare/7.1.0...7.1.1) +* [7.1.0](https://github.com/Geal/nom/compare/7.0.0...7.1.0) +* [7.0.0](https://github.com/Geal/nom/compare/6.2.1...7.0.0) +* [6.2.1](https://github.com/Geal/nom/compare/6.2.0...6.2.1) +* [6.2.0](https://github.com/Geal/nom/compare/6.1.2...6.2.0) +* [6.1.2](https://github.com/Geal/nom/compare/6.1.1...6.1.2) +* [6.1.1](https://github.com/Geal/nom/compare/6.1.0...6.1.1) +* [6.1.0](https://github.com/Geal/nom/compare/6.0.1...6.1.0) +* [6.0.1](https://github.com/Geal/nom/compare/6.0.0...6.0.1) +* [6.0.0](https://github.com/Geal/nom/compare/5.1.1...6.0.0) +* [5.1.1](https://github.com/Geal/nom/compare/5.1.0...5.1.1) +* [5.1.0](https://github.com/Geal/nom/compare/5.0.1...5.1.0) +* [5.0.1](https://github.com/Geal/nom/compare/5.0.0...5.0.1) +* [5.0.0](https://github.com/Geal/nom/compare/4.2.3...5.0.0) +* [4.2.3](https://github.com/Geal/nom/compare/4.2.2...4.2.3) +* [4.2.2](https://github.com/Geal/nom/compare/4.2.1...4.2.2) +* [4.2.1](https://github.com/Geal/nom/compare/4.2.0...4.2.1) +* [4.2.0](https://github.com/Geal/nom/compare/4.1.1...4.2.0) +* [4.1.1](https://github.com/Geal/nom/compare/4.1.0...4.1.1) +* [4.1.0](https://github.com/Geal/nom/compare/4.0.0...4.1.0) +* [4.0.0](https://github.com/Geal/nom/compare/3.2.1...4.0.0) +* [3.2.1](https://github.com/Geal/nom/compare/3.2.0...3.2.1) +* [3.2.0](https://github.com/Geal/nom/compare/3.1.0...3.2.0) +* [3.1.0](https://github.com/Geal/nom/compare/3.0.0...3.1.0) +* [3.0.0](https://github.com/Geal/nom/compare/2.2.1...3.0.0) +* [2.2.1](https://github.com/Geal/nom/compare/2.2.0...2.2.1) +* [2.2.0](https://github.com/Geal/nom/compare/2.1.0...2.2.0) +* [2.1.0](https://github.com/Geal/nom/compare/2.0.1...2.1.0) +* [2.0.1](https://github.com/Geal/nom/compare/2.0.0...2.0.1) +* [2.0.0](https://github.com/Geal/nom/compare/1.2.4...2.0.0) +* [1.2.4](https://github.com/Geal/nom/compare/1.2.3...1.2.4) +* [1.2.3](https://github.com/Geal/nom/compare/1.2.2...1.2.3) +* [1.2.2](https://github.com/Geal/nom/compare/1.2.1...1.2.2) +* [1.2.1](https://github.com/Geal/nom/compare/1.2.0...1.2.1) +* [1.2.0](https://github.com/Geal/nom/compare/1.1.0...1.2.0) +* [1.1.0](https://github.com/Geal/nom/compare/1.0.1...1.1.0) +* [1.0.1](https://github.com/Geal/nom/compare/1.0.0...1.0.1) +* [1.0.0](https://github.com/Geal/nom/compare/0.5.0...1.0.0) +* [0.5.0](https://github.com/geal/nom/compare/0.4.0...0.5.0) +* [0.4.0](https://github.com/geal/nom/compare/0.3.11...0.4.0) +* [0.3.11](https://github.com/geal/nom/compare/0.3.10...0.3.11) +* [0.3.10](https://github.com/geal/nom/compare/0.3.9...0.3.10) +* [0.3.9](https://github.com/geal/nom/compare/0.3.8...0.3.9) +* [0.3.8](https://github.com/Geal/nom/compare/0.3.7...0.3.8) +* [0.3.7](https://github.com/Geal/nom/compare/0.3.6...0.3.7) +* [0.3.6](https://github.com/Geal/nom/compare/0.3.5...0.3.6) +* [0.3.5](https://github.com/Geal/nom/compare/0.3.4...0.3.5) +* [0.3.4](https://github.com/Geal/nom/compare/0.3.3...0.3.4) +* [0.3.3](https://github.com/Geal/nom/compare/0.3.2...0.3.3) +* [0.3.2](https://github.com/Geal/nom/compare/0.3.1...0.3.2) +* [0.3.1](https://github.com/Geal/nom/compare/0.3.0...0.3.1) +* [0.3.0](https://github.com/Geal/nom/compare/0.2.2...0.3.0) +* [0.2.2](https://github.com/Geal/nom/compare/0.2.1...0.2.2) +* [0.2.1](https://github.com/Geal/nom/compare/0.2.0...0.2.1) +* [0.2.0](https://github.com/Geal/nom/compare/0.1.6...0.2.0) +* [0.1.6](https://github.com/Geal/nom/compare/0.1.5...0.1.6) +* [0.1.5](https://github.com/Geal/nom/compare/0.1.4...0.1.5) +* [0.1.4](https://github.com/Geal/nom/compare/0.1.3...0.1.4) +* [0.1.3](https://github.com/Geal/nom/compare/0.1.2...0.1.3) +* [0.1.2](https://github.com/Geal/nom/compare/0.1.1...0.1.2) +* [0.1.1](https://github.com/Geal/nom/compare/0.1.0...0.1.1) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,282 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +dependencies = [ + "doc-comment", + "memchr", + "minimal-lexical", + "proptest", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proptest" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +dependencies = [ + "bit-set", + "bitflags", + "byteorder", + "lazy_static", + "num-traits", + "quick-error 2.0.1", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,168 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.48" +name = "nom" +version = "7.1.3" +authors = ["contact@geoffroycouprie.com"] +include = [ + "CHANGELOG.md", + "LICENSE", + "README.md", + ".gitignore", + "Cargo.toml", + "src/*.rs", + "src/*/*.rs", + "tests/*.rs", + "doc/nom_recipes.md", +] +autoexamples = false +description = "A byte-oriented, zero-copy, parser combinators library" +documentation = "https://docs.rs/nom" +readme = "README.md" +keywords = [ + "parser", + "parser-combinators", + "parsing", + "streaming", + "bit", +] +categories = ["parsing"] +license = "MIT" +repository = "https://github.com/Geal/nom" + +[package.metadata.docs.rs] +features = [ + "alloc", + "std", + "docsrs", +] +all-features = true + +[profile.bench] +lto = true +codegen-units = 1 +debug = true + +[[example]] +name = "custom_error" +path = "examples/custom_error.rs" +required-features = ["alloc"] + +[[example]] +name = "json" +path = "examples/json.rs" +required-features = ["alloc"] + +[[example]] +name = "json_iterator" +path = "examples/json_iterator.rs" +required-features = ["alloc"] + +[[example]] +name = "iterator" +path = "examples/iterator.rs" + +[[example]] +name = "s_expression" +path = "examples/s_expression.rs" +required-features = ["alloc"] + +[[example]] +name = "string" +path = "examples/string.rs" +required-features = ["alloc"] + +[[test]] +name = "arithmetic" + +[[test]] +name = "arithmetic_ast" +required-features = ["alloc"] + +[[test]] +name = "css" + +[[test]] +name = "custom_errors" + +[[test]] +name = "float" + +[[test]] +name = "ini" +required-features = ["alloc"] + +[[test]] +name = "ini_str" +required-features = ["alloc"] + +[[test]] +name = "issues" +required-features = ["alloc"] + +[[test]] +name = "json" + +[[test]] +name = "mp4" +required-features = ["alloc"] + +[[test]] +name = "multiline" +required-features = ["alloc"] + +[[test]] +name = "overflow" + +[[test]] +name = "reborrow_fold" + +[[test]] +name = "fnmut" +required-features = ["alloc"] + +[dependencies.memchr] +version = "2.3" +default-features = false + +[dependencies.minimal-lexical] +version = "0.2.0" +default-features = false + +[dev-dependencies.doc-comment] +version = "0.3" + +[dev-dependencies.proptest] +version = "1.0.0" + +[features] +alloc = [] +default = ["std"] +docsrs = [] +std = [ + "alloc", + "memchr/std", + "minimal-lexical/std", +] + +[badges.coveralls] +branch = "main" +repository = "Geal/nom" +service = "github" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +repository = "Geal/nom" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,142 @@ +[package] + +name = "nom" +version = "7.1.3" +authors = [ "contact@geoffroycouprie.com" ] +description = "A byte-oriented, zero-copy, parser combinators library" +license = "MIT" +repository = "https://github.com/Geal/nom" +readme = "README.md" +documentation = "https://docs.rs/nom" +keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"] +categories = ["parsing"] +edition = "2018" +autoexamples = false + +# also update in README.md (badge and "Rust version requirements" section) +rust-version = "1.48" + +include = [ + "CHANGELOG.md", + "LICENSE", + "README.md", + ".gitignore", + "Cargo.toml", + "src/*.rs", + "src/*/*.rs", + "tests/*.rs", + "doc/nom_recipes.md", +] + +[features] +alloc = [] +std = ["alloc", "memchr/std", "minimal-lexical/std"] +default = ["std"] +docsrs = [] + +[dependencies.minimal-lexical] +version = "0.2.0" +default-features = false + +[dependencies.memchr] +version = "2.3" +default-features = false + +[dev-dependencies] +doc-comment = "0.3" +proptest = "1.0.0" + +[package.metadata.docs.rs] +features = ["alloc", "std", "docsrs"] +all-features = true + +[profile.bench] +debug = true +lto = true +codegen-units = 1 + +[[test]] +name = "arithmetic" + +[[test]] +name = "arithmetic_ast" +required-features = ["alloc"] + +[[test]] +name = "css" + +[[test]] +name = "custom_errors" + +[[test]] +name = "float" + +[[test]] +name = "ini" +required-features = ["alloc"] + +[[test]] +name = "ini_str" +required-features = ["alloc"] + +[[test]] +name = "issues" +required-features = ["alloc"] + +[[test]] +name = "json" + +[[test]] +name = "mp4" +required-features = ["alloc"] + +[[test]] +name = "multiline" +required-features = ["alloc"] + +[[test]] +name = "overflow" + +[[test]] +name = "reborrow_fold" + +[[test]] +name = "fnmut" +required-features = ["alloc"] + +[[example]] +name = "custom_error" +required-features = ["alloc"] +path = "examples/custom_error.rs" + +[[example]] +name = "json" +required-features = ["alloc"] +path = "examples/json.rs" + +[[example]] +name = "json_iterator" +required-features = ["alloc"] +path = "examples/json_iterator.rs" + +[[example]] +name = "iterator" +path = "examples/iterator.rs" + +[[example]] +name = "s_expression" +path = "examples/s_expression.rs" +required-features = ["alloc"] + +[[example]] +name = "string" +required-features = ["alloc"] +path = "examples/string.rs" + +[badges] +travis-ci = { repository = "Geal/nom" } +coveralls = { repository = "Geal/nom", branch = "main", service = "github" } +maintenance = { status = "actively-developed" } + +[workspace] +members = [".", "benchmarks/"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +Copyright (c) 2014-2019 Geoffroy Couprie + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/README.md clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,331 @@ +# nom, eating data byte by byte + +[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Join the chat at https://gitter.im/Geal/nom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Geal/nom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Build Status](https://github.com/Geal/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/Geal/nom/actions/workflows/ci.yml) +[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=main)](https://coveralls.io/github/Geal/nom?branch=main) +[![Crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements-msrv) + +nom is a parser combinators library written in Rust. Its goal is to provide tools +to build safe parsers without compromising the speed or memory consumption. To +that end, it uses extensively Rust's *strong typing* and *memory safety* to produce +fast and correct parsers, and provides functions, macros and traits to abstract most of the +error prone plumbing. + +![nom logo in CC0 license, by Ange Albertini](https://raw.githubusercontent.com/Geal/nom/main/assets/nom.png) + +*nom will happily take a byte out of your files :)* + + + +- [Example](#example) +- [Documentation](#documentation) +- [Why use nom?](#why-use-nom) + - [Binary format parsers](#binary-format-parsers) + - [Text format parsers](#text-format-parsers) + - [Programming language parsers](#programming-language-parsers) + - [Streaming formats](#streaming-formats) +- [Parser combinators](#parser-combinators) +- [Technical features](#technical-features) +- [Rust version requirements](#rust-version-requirements-msrv) +- [Installation](#installation) +- [Related projects](#related-projects) +- [Parsers written with nom](#parsers-written-with-nom) +- [Contributors](#contributors) + + + +## Example + +[Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser: + +```rust +extern crate nom; +use nom::{ + IResult, + bytes::complete::{tag, take_while_m_n}, + combinator::map_res, + sequence::tuple +}; + +#[derive(Debug,PartialEq)] +pub struct Color { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +fn from_hex(input: &str) -> Result { + u8::from_str_radix(input, 16) +} + +fn is_hex_digit(c: char) -> bool { + c.is_digit(16) +} + +fn hex_primary(input: &str) -> IResult<&str, u8> { + map_res( + take_while_m_n(2, 2, is_hex_digit), + from_hex + )(input) +} + +fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; + + Ok((input, Color { red, green, blue })) +} + +fn main() {} + +#[test] +fn parse_color() { + assert_eq!(hex_color("#2F14DF"), Ok(("", Color { + red: 47, + green: 20, + blue: 223, + }))); +} +``` + +## Documentation + +- [Reference documentation](https://docs.rs/nom) +- [Various design documents and tutorials](https://github.com/Geal/nom/tree/main/doc) +- [List of combinators and their behaviour](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) + +If you need any help developing your parsers, please ping `geal` on IRC (libera, geeknode, oftc), go to `#nom-parsers` on Libera IRC, or on the [Gitter chat room](https://gitter.im/Geal/nom). + +## Why use nom + +If you want to write: + +### Binary format parsers + +nom was designed to properly parse binary formats from the beginning. Compared +to the usual handwritten C parsers, nom parsers are just as fast, free from +buffer overflow vulnerabilities, and handle common patterns for you: + +- [TLV](https://en.wikipedia.org/wiki/Type-length-value) +- Bit level parsing +- Hexadecimal viewer in the debugging macros for easy data analysis +- Streaming parsers for network formats and huge files + +Example projects: + +- [FLV parser](https://github.com/rust-av/flavors) +- [Matroska parser](https://github.com/rust-av/matroska) +- [tar parser](https://github.com/Keruspe/tar-parser.rs) + +### Text format parsers + +While nom was made for binary format at first, it soon grew to work just as +well with text formats. From line based formats like CSV, to more complex, nested +formats such as JSON, nom can manage it, and provides you with useful tools: + +- Fast case insensitive comparison +- Recognizers for escaped strings +- Regular expressions can be embedded in nom parsers to represent complex character patterns succinctly +- Special care has been given to managing non ASCII characters properly + +Example projects: + +- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser) +- [TOML parser](https://github.com/joelself/tomllib) + +### Programming language parsers + +While programming language parsers are usually written manually for more +flexibility and performance, nom can be (and has been successfully) used +as a prototyping parser for a language. + +nom will get you started quickly with powerful custom error types, that you +can leverage with [nom_locate](https://github.com/fflorent/nom_locate) to +pinpoint the exact line and column of the error. No need for separate +tokenizing, lexing and parsing phases: nom can automatically handle whitespace +parsing, and construct an AST in place. + +Example projects: + +- [PHP VM](https://github.com/tagua-vm/parser) +- eve language prototype +- [xshade shading language](https://github.com/xshade-lang/xshade/) + +### Streaming formats + +While a lot of formats (and the code handling them) assume that they can fit +the complete data in memory, there are formats for which we only get a part +of the data at once, like network formats, or huge files. +nom has been designed for a correct behaviour with partial data: If there is +not enough data to decide, nom will tell you it needs more instead of silently +returning a wrong result. Whether your data comes entirely or in chunks, the +result should be the same. + +It allows you to build powerful, deterministic state machines for your protocols. + +Example projects: + +- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser) +- [Using nom with generators](https://github.com/Geal/generator_nom) + +## Parser combinators + +Parser combinators are an approach to parsers that is very different from +software like [lex](https://en.wikipedia.org/wiki/Lex_(software)) and +[yacc](https://en.wikipedia.org/wiki/Yacc). Instead of writing the grammar +in a separate file and generating the corresponding code, you use very +small functions with very specific purpose, like "take 5 bytes", or +"recognize the word 'HTTP'", and assemble them in meaningful patterns +like "recognize 'HTTP', then a space, then a version". +The resulting code is small, and looks like the grammar you would have +written with other parser approaches. + +This has a few advantages: + +- The parsers are small and easy to write +- The parsers components are easy to reuse (if they're general enough, please add them to nom!) +- The parsers components are easy to test separately (unit tests and property-based tests) +- The parser combination code looks close to the grammar you would have written +- You can build partial parsers, specific to the data you need at the moment, and ignore the rest + +## Technical features + +nom parsers are for: +- [x] **byte-oriented**: The basic type is `&[u8]` and parsers will work as much as possible on byte array slices (but are not limited to them) +- [x] **bit-oriented**: nom can address a byte slice as a bit stream +- [x] **string-oriented**: The same kind of combinators can apply on UTF-8 strings as well +- [x] **zero-copy**: If a parser returns a subset of its input data, it will return a slice of that input, without copying +- [x] **streaming**: nom can work on partial data and detect when it needs more data to produce a correct result +- [x] **descriptive errors**: The parsers can aggregate a list of error codes with pointers to the incriminated input slice. Those error lists can be pattern matched to provide useful messages. +- [x] **custom error types**: You can provide a specific type to improve errors returned by parsers +- [x] **safe parsing**: nom leverages Rust's safe memory handling and powerful types, and parsers are routinely fuzzed and tested with real world data. So far, the only flaws found by fuzzing were in code written outside of nom +- [x] **speed**: Benchmarks have shown that nom parsers often outperform many parser combinators library like Parsec and attoparsec, some regular expression engines and even handwritten C parsers + +Some benchmarks are available on [Github](https://github.com/Geal/nom_benchmarks). + +## Rust version requirements (MSRV) + +The 7.0 series of nom supports **Rustc version 1.48 or greater**. It is known to work properly on Rust 1.41.1 but there is no guarantee it will stay the case through this major release. + +The current policy is that this will only be updated in the next major nom release. + +## Installation + +nom is available on [crates.io](https://crates.io/crates/nom) and can be included in your Cargo enabled project like this: + +```toml +[dependencies] +nom = "7" +``` + +There are a few compilation features: + +* `alloc`: (activated by default) if disabled, nom can work in `no_std` builds without memory allocators. If enabled, combinators that allocate (like `many0`) will be available +* `std`: (activated by default, activates `alloc` too) if disabled, nom can work in `no_std` builds + +You can configure those features like this: + +```toml +[dependencies.nom] +version = "7" +default-features = false +features = ["alloc"] +``` + +# Related projects + +- [Get line and column info in nom's input type](https://github.com/fflorent/nom_locate) +- [Using nom as lexer and parser](https://github.com/Rydgel/monkey-rust) + +# Parsers written with nom + +Here is a (non exhaustive) list of known projects using nom: + +- Text file formats: [Ceph Crush](https://github.com/cholcombe973/crushtool), +[Cronenberg](https://github.com/ayrat555/cronenberg), +[XFS Runtime Stats](https://github.com/ChrisMacNaughton/xfs-rs), +[CSV](https://github.com/GuillaumeGomez/csv-parser), +[FASTA](https://github.com/TianyiShi2001/nom-fasta), +[FASTQ](https://github.com/elij/fastq.rs), +[INI](https://github.com/Geal/nom/blob/main/tests/ini.rs), +[ISO 8601 dates](https://github.com/badboy/iso8601), +[libconfig-like configuration file format](https://github.com/filipegoncalves/rust-config), +[Web archive](https://github.com/sbeckeriv/warc_nom_parser), +[PDB](https://github.com/TianyiShi2001/nom-pdb), +[proto files](https://github.com/tafia/protobuf-parser), +[Fountain screenplay markup](https://github.com/adamchalmers/fountain-rs), +[vimwiki](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki) & [vimwiki_macros](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki_macros) +- Programming languages: +[PHP](https://github.com/tagua-vm/parser), +[Basic Calculator](https://github.com/balajisivaraman/basic_calculator_rs), +[GLSL](https://github.com/phaazon/glsl), +[Lua](https://github.com/doomrobo/nom-lua53), +[Python](https://github.com/ProgVal/rust-python-parser), +[SQL](https://github.com/ms705/nom-sql), +[Elm](https://github.com/cout970/Elm-interpreter), +[SystemVerilog](https://github.com/dalance/sv-parser), +[Turtle](https://github.com/vandenoever/rome/tree/master/src/io/turtle), +[CSML](https://github.com/CSML-by-Clevy/csml-interpreter), +[Wasm](https://github.com/Strytyp/wasm-nom), +[Pseudocode](https://github.com/Gungy2/pseudocode) +[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch) +- Interface definition formats: [Thrift](https://github.com/thehydroimpulse/thrust) +- Audio, video and image formats: +[GIF](https://github.com/Geal/gif.rs), +[MagicaVoxel .vox](https://github.com/davidedmonds/dot_vox), +[midi](https://github.com/derekdreery/nom-midi-rs), +[SWF](https://github.com/open-flash/swf-parser), +[WAVE](http://github.com/noise-Labs/wave), +[Matroska (MKV)](https://github.com/rust-av/matroska) +- Document formats: +[TAR](https://github.com/Keruspe/tar-parser.rs), +[GZ](https://github.com/nharward/nom-gzip), +[GDSII](https://github.com/erihsu/gds2-io) +- Cryptographic formats: +[X.509](https://github.com/rusticata/x509-parser) +- Network protocol formats: +[Bencode](https://github.com/jbaum98/bencode.rs), +[D-Bus](https://github.com/toshokan/misato), +[DHCP](https://github.com/rusticata/dhcp-parser), +[HTTP](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http), +[URI](https://github.com/santifa/rrp/blob/master/src/uri.rs), +[IMAP](https://github.com/djc/tokio-imap), +[IRC](https://github.com/Detegr/RBot-parser), +[Pcap-NG](https://github.com/richo/pcapng-rs), +[Pcap](https://github.com/ithinuel/pcap-rs), +[Pcap + PcapNG](https://github.com/rusticata/pcap-parser), +[IKEv2](https://github.com/rusticata/ipsec-parser), +[NTP](https://github.com/rusticata/ntp-parser), +[SNMP](https://github.com/rusticata/snmp-parser), +[Kerberos v5](https://github.com/rusticata/kerberos-parser), +[DER](https://github.com/rusticata/der-parser), +[TLS](https://github.com/rusticata/tls-parser), +[IPFIX / Netflow v10](https://github.com/dominotree/rs-ipfix), +[GTP](https://github.com/fuerstenau/gorrosion-gtp), +[SIP](https://github.com/armatusmiles/sipcore/tree/master/crates/sipmsg), +[Prometheus](https://github.com/timberio/vector/blob/master/lib/prometheus-parser/src/line.rs) +- Language specifications: +[BNF](https://github.com/snewt/bnf) +- Misc formats: +[Gameboy ROM](https://github.com/MarkMcCaskey/gameboy-rom-parser), +[ANT FIT](https://github.com/stadelmanma/fitparse-rs), +[Version Numbers](https://github.com/fosskers/rs-versions), +[Telcordia/Bellcore SR-4731 SOR OTDR files](https://github.com/JamesHarrison/otdrs), +[MySQL binary log](https://github.com/PrivateRookie/boxercrab), +[URI](https://github.com/Skasselbard/nom-uri), +[Furigana](https://github.com/sachaarbonel/furigana.rs), +[Wordle Result](https://github.com/Fyko/wordle-stats/tree/main/parser) + +Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/Geal/nom/issues/14). + +Want to add your parser here? Create a pull request for it! + +# Contributors + +nom is the fruit of the work of many contributors over the years, many thanks for your help! + + + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/doc/nom_recipes.md clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/doc/nom_recipes.md --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/doc/nom_recipes.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/doc/nom_recipes.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,395 @@ +# Nom Recipes + +These are short recipes for accomplishing common tasks with nom. + +* [Whitespace](#whitespace) + + [Wrapper combinators that eat whitespace before and after a parser](#wrapper-combinators-that-eat-whitespace-before-and-after-a-parser) +* [Comments](#comments) + + [`// C++/EOL-style comments`](#-ceol-style-comments) + + [`/* C-style comments */`](#-c-style-comments-) +* [Identifiers](#identifiers) + + [`Rust-Style Identifiers`](#rust-style-identifiers) +* [Literal Values](#literal-values) + + [Escaped Strings](#escaped-strings) + + [Integers](#integers) + - [Hexadecimal](#hexadecimal) + - [Octal](#octal) + - [Binary](#binary) + - [Decimal](#decimal) + + [Floating Point Numbers](#floating-point-numbers) + +## Whitespace + + + +### Wrapper combinators that eat whitespace before and after a parser + +```rust +use nom::{ + IResult, + error::ParseError, + combinator::value, + sequence::delimited, + character::complete::multispace0, +}; + +/// A combinator that takes a parser `inner` and produces a parser that also consumes both leading and +/// trailing whitespace, returning the output of `inner`. +fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E> + where + F: Fn(&'a str) -> IResult<&'a str, O, E>, +{ + delimited( + multispace0, + inner, + multispace0 + ) +} +``` + +To eat only trailing whitespace, replace `delimited(...)` with `terminated(&inner, multispace0)`. +Likewise, the eat only leading whitespace, replace `delimited(...)` with `preceded(multispace0, +&inner)`. You can use your own parser instead of `multispace0` if you want to skip a different set +of lexemes. + +## Comments + +### `// C++/EOL-style comments` + +This version uses `%` to start a comment, does not consume the newline character, and returns an +output of `()`. + +```rust +use nom::{ + IResult, + error::ParseError, + combinator::value, + sequence::pair, + bytes::complete::is_not, + character::complete::char, +}; + +pub fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> +{ + value( + (), // Output is thrown away. + pair(char('%'), is_not("\n\r")) + )(i) +} +``` + +### `/* C-style comments */` + +Inline comments surrounded with sentinel tags `(*` and `*)`. This version returns an output of `()` +and does not handle nested comments. + +```rust +use nom::{ + IResult, + error::ParseError, + combinator::value, + sequence::tuple, + bytes::complete::{tag, take_until}, +}; + +pub fn pinline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> { + value( + (), // Output is thrown away. + tuple(( + tag("(*"), + take_until("*)"), + tag("*)") + )) + )(i) +} +``` + +## Identifiers + +### `Rust-Style Identifiers` + +Parsing identifiers that may start with a letter (or underscore) and may contain underscores, +letters and numbers may be parsed like this: + +```rust +use nom::{ + IResult, + branch::alt, + multi::many0_count, + combinator::recognize, + sequence::pair, + character::complete::{alpha1, alphanumeric1}, + bytes::complete::tag, +}; + +pub fn identifier(input: &str) -> IResult<&str, &str> { + recognize( + pair( + alt((alpha1, tag("_"))), + many0_count(alt((alphanumeric1, tag("_")))) + ) + )(input) +} +``` + +Let's say we apply this to the identifier `hello_world123abc`. The first `alt` parser would +recognize `h`. The `pair` combinator ensures that `ello_world123abc` will be piped to the next +`alphanumeric0` parser, which recognizes every remaining character. However, the `pair` combinator +returns a tuple of the results of its sub-parsers. The `recognize` parser produces a `&str` of the +input text that was parsed, which in this case is the entire `&str` `hello_world123abc`. + +## Literal Values + +### Escaped Strings + +This is [one of the examples](https://github.com/Geal/nom/blob/main/examples/string.rs) in the +examples directory. + +### Integers + +The following recipes all return string slices rather than integer values. How to obtain an +integer value instead is demonstrated for hexadecimal integers. The others are similar. + +The parsers allow the grouping character `_`, which allows one to group the digits by byte, for +example: `0xA4_3F_11_28`. If you prefer to exclude the `_` character, the lambda to convert from a +string slice to an integer value is slightly simpler. You can also strip the `_` from the string +slice that is returned, which is demonstrated in the second hexdecimal number parser. + +If you wish to limit the number of digits in a valid integer literal, replace `many1` with +`many_m_n` in the recipes. + +#### Hexadecimal + +The parser outputs the string slice of the digits without the leading `0x`/`0X`. + +```rust +use nom::{ + IResult, + branch::alt, + multi::{many0, many1}, + combinator::recognize, + sequence::{preceded, terminated}, + character::complete::{char, one_of}, + bytes::complete::tag, +}; + +fn hexadecimal(input: &str) -> IResult<&str, &str> { // <'a, E: ParseError<&'a str>> + preceded( + alt((tag("0x"), tag("0X"))), + recognize( + many1( + terminated(one_of("0123456789abcdefABCDEF"), many0(char('_'))) + ) + ) + )(input) +} +``` + +If you want it to return the integer value instead, use map: + +```rust +use nom::{ + IResult, + branch::alt, + multi::{many0, many1}, + combinator::{map_res, recognize}, + sequence::{preceded, terminated}, + character::complete::{char, one_of}, + bytes::complete::tag, +}; + +fn hexadecimal_value(input: &str) -> IResult<&str, i64> { + map_res( + preceded( + alt((tag("0x"), tag("0X"))), + recognize( + many1( + terminated(one_of("0123456789abcdefABCDEF"), many0(char('_'))) + ) + ) + ), + |out: &str| i64::from_str_radix(&str::replace(&out, "_", ""), 16) + )(input) +} +``` + +#### Octal + +```rust +use nom::{ + IResult, + branch::alt, + multi::{many0, many1}, + combinator::recognize, + sequence::{preceded, terminated}, + character::complete::{char, one_of}, + bytes::complete::tag, +}; + +fn octal(input: &str) -> IResult<&str, &str> { + preceded( + alt((tag("0o"), tag("0O"))), + recognize( + many1( + terminated(one_of("01234567"), many0(char('_'))) + ) + ) + )(input) +} +``` + +#### Binary + +```rust +use nom::{ + IResult, + branch::alt, + multi::{many0, many1}, + combinator::recognize, + sequence::{preceded, terminated}, + character::complete::{char, one_of}, + bytes::complete::tag, +}; + +fn binary(input: &str) -> IResult<&str, &str> { + preceded( + alt((tag("0b"), tag("0B"))), + recognize( + many1( + terminated(one_of("01"), many0(char('_'))) + ) + ) + )(input) +} +``` + +#### Decimal + +```rust +use nom::{ + IResult, + multi::{many0, many1}, + combinator::recognize, + sequence::terminated, + character::complete::{char, one_of}, +}; + +fn decimal(input: &str) -> IResult<&str, &str> { + recognize( + many1( + terminated(one_of("0123456789"), many0(char('_'))) + ) + )(input) +} +``` + +### Floating Point Numbers + +The following is adapted from [the Python parser by Valentin Lorentz (ProgVal)](https://github.com/ProgVal/rust-python-parser/blob/master/src/numbers.rs). + +```rust +use nom::{ + IResult, + branch::alt, + multi::{many0, many1}, + combinator::{opt, recognize}, + sequence::{preceded, terminated, tuple}, + character::complete::{char, one_of}, +}; + +fn float(input: &str) -> IResult<&str, &str> { + alt(( + // Case one: .42 + recognize( + tuple(( + char('.'), + decimal, + opt(tuple(( + one_of("eE"), + opt(one_of("+-")), + decimal + ))) + )) + ) + , // Case two: 42e42 and 42.42e42 + recognize( + tuple(( + decimal, + opt(preceded( + char('.'), + decimal, + )), + one_of("eE"), + opt(one_of("+-")), + decimal + )) + ) + , // Case three: 42. and 42.42 + recognize( + tuple(( + decimal, + char('.'), + opt(decimal) + )) + ) + ))(input) +} + +fn decimal(input: &str) -> IResult<&str, &str> { + recognize( + many1( + terminated(one_of("0123456789"), many0(char('_'))) + ) + )(input) +} +``` + +# implementing FromStr + +The [FromStr trait](https://doc.rust-lang.org/std/str/trait.FromStr.html) provides +a common interface to parse from a string. + +```rust +use nom::{ + IResult, Finish, error::Error, + bytes::complete::{tag, take_while}, +}; +use std::str::FromStr; + +// will recognize the name in "Hello, name!" +fn parse_name(input: &str) -> IResult<&str, &str> { + let (i, _) = tag("Hello, ")(input)?; + let (i, name) = take_while(|c:char| c.is_alphabetic())(i)?; + let (i, _) = tag("!")(i)?; + + Ok((i, name)) +} + +// with FromStr, the result cannot be a reference to the input, it must be owned +#[derive(Debug)] +pub struct Name(pub String); + +impl FromStr for Name { + // the error must be owned as well + type Err = Error; + + fn from_str(s: &str) -> Result { + match parse_name(s).finish() { + Ok((_remaining, name)) => Ok(Name(name.to_string())), + Err(Error { input, code }) => Err(Error { + input: input.to_string(), + code, + }) + } + } +} + +fn main() { + // parsed: Ok(Name("nom")) + println!("parsed: {:?}", "Hello, nom!".parse::()); + + // parsed: Err(Error { input: "123!", code: Tag }) + println!("parsed: {:?}", "Hello, 123!".parse::()); +} +``` + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/complete.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,197 @@ +//! Bit level parsers +//! + +use crate::error::{ErrorKind, ParseError}; +use crate::internal::{Err, IResult}; +use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr}; +use crate::traits::{InputIter, InputLength, Slice, ToUsize}; + +/// Generates a parser taking `count` bits +/// +/// # Example +/// ```rust +/// # use nom::bits::complete::take; +/// # use nom::IResult; +/// # use nom::error::{Error, ErrorKind}; +/// // Input is a tuple of (input: I, bit_offset: usize) +/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> { +/// take(count)(input) +/// } +/// +/// // Consumes 0 bits, returns 0 +/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0))); +/// +/// // Consumes 4 bits, returns their values and increase offset to 4 +/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001))); +/// +/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte +/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010))); +/// +/// // Tries to consume 12 bits but only 8 are available +/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof }))); +/// ``` +pub fn take>( + count: C, +) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> +where + I: Slice> + InputIter + InputLength, + C: ToUsize, + O: From + AddAssign + Shl + Shr, +{ + let count = count.to_usize(); + move |(input, bit_offset): (I, usize)| { + if count == 0 { + Ok(((input, bit_offset), 0u8.into())) + } else { + let cnt = (count + bit_offset).div(8); + if input.input_len() * 8 < count + bit_offset { + Err(Err::Error(E::from_error_kind( + (input, bit_offset), + ErrorKind::Eof, + ))) + } else { + let mut acc: O = 0_u8.into(); + let mut offset: usize = bit_offset; + let mut remaining: usize = count; + let mut end_offset: usize = 0; + + for byte in input.iter_elements().take(cnt + 1) { + if remaining == 0 { + break; + } + let val: O = if offset == 0 { + byte.into() + } else { + ((byte << offset) as u8 >> offset).into() + }; + + if remaining < 8 - offset { + acc += val >> (8 - offset - remaining); + end_offset = remaining + offset; + break; + } else { + acc += val << (remaining - (8 - offset)); + remaining -= 8 - offset; + offset = 0; + } + } + Ok(((input.slice(cnt..), end_offset), acc)) + } + } + } +} + +/// Generates a parser taking `count` bits and comparing them to `pattern` +pub fn tag>( + pattern: O, + count: C, +) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> +where + I: Slice> + InputIter + InputLength + Clone, + C: ToUsize, + O: From + AddAssign + Shl + Shr + PartialEq, +{ + let count = count.to_usize(); + move |input: (I, usize)| { + let inp = input.clone(); + + take(count)(input).and_then(|(i, o)| { + if pattern == o { + Ok((i, o)) + } else { + Err(Err::Error(error_position!(inp, ErrorKind::TagBits))) + } + }) + } +} + +/// Parses one specific bit as a bool. +/// +/// # Example +/// ```rust +/// # use nom::bits::complete::bool; +/// # use nom::IResult; +/// # use nom::error::{Error, ErrorKind}; +/// +/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> { +/// bool(input) +/// } +/// +/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true))); +/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false))); +/// ``` +pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> +where + I: Slice> + InputIter + InputLength, +{ + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_take_0() { + let input = [0b00010010].as_ref(); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; + + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + + assert_eq!(result, Ok(((input, offset), 0))); + } + + #[test] + fn test_take_eof() { + let input = [0b00010010].as_ref(); + + let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8)); + + assert_eq!( + result, + Err(crate::Err::Error(crate::error::Error { + input: (input, 8), + code: ErrorKind::Eof + })) + ) + } + + #[test] + fn test_take_span_over_multiple_bytes() { + let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref(); + + let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4)); + + assert_eq!( + result, + Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)) + ); + } + + #[test] + fn test_bool_0() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); + + assert_eq!(result, Ok(((input, 1), true))); + } + + #[test] + fn test_bool_eof() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); + + assert_eq!( + result, + Err(crate::Err::Error(crate::error::Error { + input: (input, 8), + code: ErrorKind::Eof + })) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,179 @@ +//! Bit level parsers +//! + +pub mod complete; +pub mod streaming; + +use crate::error::{ErrorKind, ParseError}; +use crate::internal::{Err, IResult, Needed, Parser}; +use crate::lib::std::ops::RangeFrom; +use crate::traits::{ErrorConvert, Slice}; + +/// Converts a byte-level input to a bit-level input, for consumption by a parser that uses bits. +/// +/// Afterwards, the input is converted back to a byte-level parser, with any remaining bits thrown +/// away. +/// +/// # Example +/// ``` +/// use nom::bits::{bits, streaming::take}; +/// use nom::error::Error; +/// use nom::sequence::tuple; +/// use nom::IResult; +/// +/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8)> { +/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input) +/// } +/// +/// let input = &[0x12, 0x34, 0xff, 0xff]; +/// +/// let output = parse(input).expect("We take 1.5 bytes and the input is longer than 2 bytes"); +/// +/// // The first byte is consumed, the second byte is partially consumed and dropped. +/// let remaining = output.0; +/// assert_eq!(remaining, [0xff, 0xff]); +/// +/// let parsed = output.1; +/// assert_eq!(parsed.0, 0x01); +/// assert_eq!(parsed.1, 0x23); +/// ``` +pub fn bits(mut parser: P) -> impl FnMut(I) -> IResult +where + E1: ParseError<(I, usize)> + ErrorConvert, + E2: ParseError, + I: Slice>, + P: Parser<(I, usize), O, E1>, +{ + move |input: I| match parser.parse((input, 0)) { + Ok(((rest, offset), result)) => { + // If the next byte has been partially read, it will be sliced away as well. + // The parser functions might already slice away all fully read bytes. + // That's why `offset / 8` isn't necessarily needed at all times. + let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 }; + Ok((rest.slice(remaining_bytes_index..), result)) + } + Err(Err::Incomplete(n)) => Err(Err::Incomplete(n.map(|u| u.get() / 8 + 1))), + Err(Err::Error(e)) => Err(Err::Error(e.convert())), + Err(Err::Failure(e)) => Err(Err::Failure(e.convert())), + } +} + +/// Counterpart to `bits`, `bytes` transforms its bit stream input into a byte slice for the underlying +/// parser, allowing byte-slice parsers to work on bit streams. +/// +/// A partial byte remaining in the input will be ignored and the given parser will start parsing +/// at the next full byte. +/// +/// ``` +/// use nom::bits::{bits, bytes, streaming::take}; +/// use nom::combinator::rest; +/// use nom::error::Error; +/// use nom::sequence::tuple; +/// use nom::IResult; +/// +/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8, &[u8])> { +/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple(( +/// take(4usize), +/// take(8usize), +/// bytes::<_, _, Error<&[u8]>, _, _>(rest) +/// )))(input) +/// } +/// +/// let input = &[0x12, 0x34, 0xff, 0xff]; +/// +/// assert_eq!(parse( input ), Ok(( &[][..], (0x01, 0x23, &[0xff, 0xff][..]) ))); +/// ``` +pub fn bytes(mut parser: P) -> impl FnMut((I, usize)) -> IResult<(I, usize), O, E2> +where + E1: ParseError + ErrorConvert, + E2: ParseError<(I, usize)>, + I: Slice> + Clone, + P: Parser, +{ + move |(input, offset): (I, usize)| { + let inner = if offset % 8 != 0 { + input.slice((1 + offset / 8)..) + } else { + input.slice((offset / 8)..) + }; + let i = (input, offset); + match parser.parse(inner) { + Ok((rest, res)) => Ok(((rest, 0), res)), + Err(Err::Incomplete(Needed::Unknown)) => Err(Err::Incomplete(Needed::Unknown)), + Err(Err::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) { + Some(v) => Err::Incomplete(Needed::new(v)), + None => Err::Failure(E2::from_error_kind(i, ErrorKind::TooLarge)), + }), + Err(Err::Error(e)) => Err(Err::Error(e.convert())), + Err(Err::Failure(e)) => Err(Err::Failure(e.convert())), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::bits::streaming::take; + use crate::error::Error; + use crate::sequence::tuple; + + #[test] + /// Take the `bits` function and assert that remaining bytes are correctly returned, if the + /// previous bytes are fully consumed + fn test_complete_byte_consumption_bits() { + let input = &[0x12, 0x34, 0x56, 0x78]; + + // Take 3 bit slices with sizes [4, 8, 4]. + let result: IResult<&[u8], (u8, u8, u8)> = + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize), take(4usize))))( + input, + ); + + let output = result.expect("We take 2 bytes and the input is longer than 2 bytes"); + + let remaining = output.0; + assert_eq!(remaining, [0x56, 0x78]); + + let parsed = output.1; + assert_eq!(parsed.0, 0x01); + assert_eq!(parsed.1, 0x23); + assert_eq!(parsed.2, 0x04); + } + + #[test] + /// Take the `bits` function and assert that remaining bytes are correctly returned, if the + /// previous bytes are NOT fully consumed. Partially consumed bytes are supposed to be dropped. + /// I.e. if we consume 1.5 bytes of 4 bytes, 2 bytes will be returned, bits 13-16 will be + /// dropped. + fn test_partial_byte_consumption_bits() { + let input = &[0x12, 0x34, 0x56, 0x78]; + + // Take bit slices with sizes [4, 8]. + let result: IResult<&[u8], (u8, u8)> = + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input); + + let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes"); + + let remaining = output.0; + assert_eq!(remaining, [0x56, 0x78]); + + let parsed = output.1; + assert_eq!(parsed.0, 0x01); + assert_eq!(parsed.1, 0x23); + } + + #[test] + #[cfg(feature = "std")] + /// Ensure that in Incomplete error is thrown, if too few bytes are passed for a given parser. + fn test_incomplete_bits() { + let input = &[0x12]; + + // Take bit slices with sizes [4, 8]. + let result: IResult<&[u8], (u8, u8)> = + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input); + + assert!(result.is_err()); + let error = result.err().unwrap(); + assert_eq!("Parsing requires 2 bytes/chars", error.to_string()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bits/streaming.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bits/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,170 @@ +//! Bit level parsers +//! + +use crate::error::{ErrorKind, ParseError}; +use crate::internal::{Err, IResult, Needed}; +use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr}; +use crate::traits::{InputIter, InputLength, Slice, ToUsize}; + +/// Generates a parser taking `count` bits +pub fn take>( + count: C, +) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> +where + I: Slice> + InputIter + InputLength, + C: ToUsize, + O: From + AddAssign + Shl + Shr, +{ + let count = count.to_usize(); + move |(input, bit_offset): (I, usize)| { + if count == 0 { + Ok(((input, bit_offset), 0u8.into())) + } else { + let cnt = (count + bit_offset).div(8); + if input.input_len() * 8 < count + bit_offset { + Err(Err::Incomplete(Needed::new(count as usize))) + } else { + let mut acc: O = 0_u8.into(); + let mut offset: usize = bit_offset; + let mut remaining: usize = count; + let mut end_offset: usize = 0; + + for byte in input.iter_elements().take(cnt + 1) { + if remaining == 0 { + break; + } + let val: O = if offset == 0 { + byte.into() + } else { + ((byte << offset) as u8 >> offset).into() + }; + + if remaining < 8 - offset { + acc += val >> (8 - offset - remaining); + end_offset = remaining + offset; + break; + } else { + acc += val << (remaining - (8 - offset)); + remaining -= 8 - offset; + offset = 0; + } + } + Ok(((input.slice(cnt..), end_offset), acc)) + } + } + } +} + +/// Generates a parser taking `count` bits and comparing them to `pattern` +pub fn tag>( + pattern: O, + count: C, +) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> +where + I: Slice> + InputIter + InputLength + Clone, + C: ToUsize, + O: From + AddAssign + Shl + Shr + PartialEq, +{ + let count = count.to_usize(); + move |input: (I, usize)| { + let inp = input.clone(); + + take(count)(input).and_then(|(i, o)| { + if pattern == o { + Ok((i, o)) + } else { + Err(Err::Error(error_position!(inp, ErrorKind::TagBits))) + } + }) + } +} + +/// Parses one specific bit as a bool. +/// +/// # Example +/// ```rust +/// # use nom::bits::complete::bool; +/// # use nom::IResult; +/// # use nom::error::{Error, ErrorKind}; +/// +/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> { +/// bool(input) +/// } +/// +/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true))); +/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false))); +/// ``` +pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> +where + I: Slice> + InputIter + InputLength, +{ + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_take_0() { + let input = [].as_ref(); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; + + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + + assert_eq!(result, Ok(((input, offset), 0))); + } + + #[test] + fn test_tag_ok() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b0001; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); + } + + #[test] + fn test_tag_err() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b1111; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!( + result, + Err(crate::Err::Error(crate::error::Error { + input: (input, offset), + code: ErrorKind::TagBits + })) + ); + } + + #[test] + fn test_bool_0() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); + + assert_eq!(result, Ok(((input, 1), true))); + } + + #[test] + fn test_bool_eof() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); + + assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1)))); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/branch/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/branch/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,267 @@ +//! Choice combinators + +#[cfg(test)] +mod tests; + +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Parser}; + +/// Helper trait for the [alt()] combinator. +/// +/// This trait is implemented for tuples of up to 21 elements +pub trait Alt { + /// Tests each parser in the tuple and returns the result of the first one that succeeds + fn choice(&mut self, input: I) -> IResult; +} + +/// Tests a list of parsers one by one until one succeeds. +/// +/// It takes as argument a tuple of parsers. There is a maximum of 21 +/// parsers. If you need more, it is possible to nest them in other `alt` calls, +/// like this: `alt(parser_a, alt(parser_b, parser_c))` +/// +/// ```rust +/// # use nom::error_position; +/// # use nom::{Err,error::ErrorKind, Needed, IResult}; +/// use nom::character::complete::{alpha1, digit1}; +/// use nom::branch::alt; +/// # fn main() { +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt((alpha1, digit1))(input) +/// }; +/// +/// // the first parser, alpha1, recognizes the input +/// assert_eq!(parser("abc"), Ok(("", "abc"))); +/// +/// // the first parser returns an error, so alt tries the second one +/// assert_eq!(parser("123456"), Ok(("", "123456"))); +/// +/// // both parsers failed, and with the default error type, alt will return the last error +/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit)))); +/// # } +/// ``` +/// +/// With a custom error type, it is possible to have alt return the error of the parser +/// that went the farthest in the input data +pub fn alt, List: Alt>( + mut l: List, +) -> impl FnMut(I) -> IResult { + move |i: I| l.choice(i) +} + +/// Helper trait for the [permutation()] combinator. +/// +/// This trait is implemented for tuples of up to 21 elements +pub trait Permutation { + /// Tries to apply all parsers in the tuple in various orders until all of them succeed + fn permutation(&mut self, input: I) -> IResult; +} + +/// Applies a list of parsers in any order. +/// +/// Permutation will succeed if all of the child parsers succeeded. +/// It takes as argument a tuple of parsers, and returns a +/// tuple of the parser results. +/// +/// ```rust +/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::character::complete::{alpha1, digit1}; +/// use nom::branch::permutation; +/// # fn main() { +/// fn parser(input: &str) -> IResult<&str, (&str, &str)> { +/// permutation((alpha1, digit1))(input) +/// } +/// +/// // permutation recognizes alphabetic characters then digit +/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123")))); +/// +/// // but also in inverse order +/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123")))); +/// +/// // it will fail if one of the parsers failed +/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit)))); +/// # } +/// ``` +/// +/// The parsers are applied greedily: if there are multiple unapplied parsers +/// that could parse the next slice of input, the first one is used. +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; +/// use nom::branch::permutation; +/// use nom::character::complete::{anychar, char}; +/// +/// fn parser(input: &str) -> IResult<&str, (char, char)> { +/// permutation((anychar, char('a')))(input) +/// } +/// +/// // anychar parses 'b', then char('a') parses 'a' +/// assert_eq!(parser("ba"), Ok(("", ('b', 'a')))); +/// +/// // anychar parses 'a', then char('a') fails on 'b', +/// // even though char('a') followed by anychar would succeed +/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char)))); +/// ``` +/// +pub fn permutation, List: Permutation>( + mut l: List, +) -> impl FnMut(I) -> IResult { + move |i: I| l.permutation(i) +} + +macro_rules! alt_trait( + ($first:ident $second:ident $($id: ident)+) => ( + alt_trait!(__impl $first $second; $($id)+); + ); + (__impl $($current:ident)*; $head:ident $($id: ident)+) => ( + alt_trait_impl!($($current)*); + + alt_trait!(__impl $($current)* $head; $($id)+); + ); + (__impl $($current:ident)*; $head:ident) => ( + alt_trait_impl!($($current)*); + alt_trait_impl!($($current)* $head); + ); +); + +macro_rules! alt_trait_impl( + ($($id:ident)+) => ( + impl< + Input: Clone, Output, Error: ParseError, + $($id: Parser),+ + > Alt for ( $($id),+ ) { + + fn choice(&mut self, input: Input) -> IResult { + match self.0.parse(input.clone()) { + Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+), + res => res, + } + } + } + ); +); + +macro_rules! alt_trait_inner( + ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => ( + match $self.$it.parse($input.clone()) { + Err(Err::Error(e)) => { + let err = $err.or(e); + succ!($it, alt_trait_inner!($self, $input, err, $($id)+)) + } + res => res, + } + ); + ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => ( + Err(Err::Error(Error::append($input, ErrorKind::Alt, $err))) + ); +); + +alt_trait!(A B C D E F G H I J K L M N O P Q R S T U); + +// Manually implement Alt for (A,), the 1-tuple type +impl, A: Parser> + Alt for (A,) +{ + fn choice(&mut self, input: Input) -> IResult { + self.0.parse(input) + } +} + +macro_rules! permutation_trait( + ( + $name1:ident $ty1:ident $item1:ident + $name2:ident $ty2:ident $item2:ident + $($name3:ident $ty3:ident $item3:ident)* + ) => ( + permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*); + ); + ( + __impl $($name:ident $ty:ident $item:ident),+; + $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)* + ) => ( + permutation_trait_impl!($($name $ty $item),+); + permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*); + ); + (__impl $($name:ident $ty:ident $item:ident),+;) => ( + permutation_trait_impl!($($name $ty $item),+); + ); +); + +macro_rules! permutation_trait_impl( + ($($name:ident $ty:ident $item:ident),+) => ( + impl< + Input: Clone, $($ty),+ , Error: ParseError, + $($name: Parser),+ + > Permutation for ( $($name),+ ) { + + fn permutation(&mut self, mut input: Input) -> IResult { + let mut res = ($(Option::<$ty>::None),+); + + loop { + let mut err: Option = None; + permutation_trait_inner!(0, self, input, res, err, $($name)+); + + // If we reach here, every iterator has either been applied before, + // or errored on the remaining input + if let Some(err) = err { + // There are remaining parsers, and all errored on the remaining input + return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err))); + } + + // All parsers were applied + match res { + ($(Some($item)),+) => return Ok((input, ($($item),+))), + _ => unreachable!(), + } + } + } + } + ); +); + +macro_rules! permutation_trait_inner( + ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => ( + if $res.$it.is_none() { + match $self.$it.parse($input.clone()) { + Ok((i, o)) => { + $input = i; + $res.$it = Some(o); + continue; + } + Err(Err::Error(e)) => { + $err = Some(match $err { + Some(err) => err.or(e), + None => e, + }); + } + Err(e) => return Err(e), + }; + } + succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*)); + ); + ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => (); +); + +permutation_trait!( + FnA A a + FnB B b + FnC C c + FnD D d + FnE E e + FnF F f + FnG G g + FnH H h + FnI I i + FnJ J j + FnK K k + FnL L l + FnM M m + FnN N n + FnO O o + FnP P p + FnQ Q q + FnR R r + FnS S s + FnT T t + FnU U u +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/branch/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/branch/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/branch/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,142 @@ +use crate::branch::{alt, permutation}; +use crate::bytes::streaming::tag; +use crate::error::ErrorKind; +use crate::internal::{Err, IResult, Needed}; +#[cfg(feature = "alloc")] +use crate::{ + error::ParseError, + lib::std::{ + fmt::Debug, + string::{String, ToString}, + }, +}; + +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq)] +pub struct ErrorStr(String); + +#[cfg(feature = "alloc")] +impl From for ErrorStr { + fn from(i: u32) -> Self { + ErrorStr(format!("custom error code: {}", i)) + } +} + +#[cfg(feature = "alloc")] +impl<'a> From<&'a str> for ErrorStr { + fn from(i: &'a str) -> Self { + ErrorStr(format!("custom error message: {}", i)) + } +} + +#[cfg(feature = "alloc")] +impl ParseError for ErrorStr { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind)) + } + + fn append(input: I, kind: ErrorKind, other: Self) -> Self { + ErrorStr(format!( + "custom error message: ({:?}, {:?}) - {:?}", + input, kind, other + )) + } +} + +#[cfg(feature = "alloc")] +#[test] +fn alt_test() { + fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok((&b""[..], input)) + } + + #[allow(unused_variables)] + fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Err(Err::Error(ErrorStr("abcd".to_string()))) + } + + fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok((input, &b""[..])) + } + + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, dont_work))(i) + } + fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, work))(i) + } + fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, dont_work, work2, dont_work))(i) + } + //named!(alt1, alt!(dont_work | dont_work)); + //named!(alt2, alt!(dont_work | work)); + //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work)); + + let a = &b"abcd"[..]; + assert_eq!( + alt1(a), + Err(Err::Error(error_node_position!( + a, + ErrorKind::Alt, + ErrorStr("abcd".to_string()) + ))) + ); + assert_eq!(alt2(a), Ok((&b""[..], a))); + assert_eq!(alt3(a), Ok((a, &b""[..]))); + + fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt((tag("abcd"), tag("efgh")))(i) + } + let b = &b"efgh"[..]; + assert_eq!(alt4(a), Ok((&b""[..], a))); + assert_eq!(alt4(b), Ok((&b""[..], b))); +} + +#[test] +fn alt_incomplete() { + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt((tag("a"), tag("bc"), tag("def")))(i) + } + + let a = &b""[..]; + assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1)))); + let a = &b"b"[..]; + assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1)))); + let a = &b"bcd"[..]; + assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..]))); + let a = &b"cde"[..]; + assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Tag)))); + let a = &b"de"[..]; + assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1)))); + let a = &b"defg"[..]; + assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..]))); +} + +#[test] +fn permutation_test() { + fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> { + permutation((tag("abcd"), tag("efg"), tag("hi")))(i) + } + + let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]); + + let a = &b"abcdefghijk"[..]; + assert_eq!(perm(a), Ok((&b"jk"[..], expected))); + let b = &b"efgabcdhijk"[..]; + assert_eq!(perm(b), Ok((&b"jk"[..], expected))); + let c = &b"hiefgabcdjk"[..]; + assert_eq!(perm(c), Ok((&b"jk"[..], expected))); + + let d = &b"efgxyzabcdefghi"[..]; + assert_eq!( + perm(d), + Err(Err::Error(error_node_position!( + &b"efgxyzabcdefghi"[..], + ErrorKind::Permutation, + error_position!(&b"xyzabcdefghi"[..], ErrorKind::Tag) + ))) + ); + + let e = &b"efgabc"[..]; + assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1)))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/complete.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,756 @@ +//! Parsers recognizing bytes streams, complete input version + +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Parser}; +use crate::lib::std::ops::RangeFrom; +use crate::lib::std::result::Result::*; +use crate::traits::{ + Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, + InputTakeAtPosition, Slice, ToUsize, +}; + +/// Recognizes a pattern +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument +/// +/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag("Hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// ``` +pub fn tag>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + Compare, + T: InputLength + Clone, +{ + move |i: Input| { + let tag_len = tag.input_len(); + let t = tag.clone(); + let res: IResult<_, _, Error> = match i.compare(t) { + CompareResult::Ok => Ok(i.take_split(tag_len)), + _ => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(Error::from_error_kind(i, e))) + } + }; + res + } +} + +/// Recognizes a case insensitive pattern. +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument with no regard to case. +/// +/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::tag_no_case; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag_no_case("hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); +/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// ``` +pub fn tag_no_case>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + Compare, + T: InputLength + Clone, +{ + move |i: Input| { + let tag_len = tag.input_len(); + let t = tag.clone(); + + let res: IResult<_, _, Error> = match (i).compare_no_case(t) { + CompareResult::Ok => Ok(i.take_split(tag_len)), + _ => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(Error::from_error_kind(i, e))) + } + }; + res + } +} + +/// Parse till certain characters are met. +/// +/// The parser will return the longest slice till one of the characters of the combinator's argument are met. +/// +/// It doesn't consume the matched character. +/// +/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::is_not; +/// +/// fn not_space(s: &str) -> IResult<&str, &str> { +/// is_not(" \t\r\n")(s) +/// } +/// +/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); +/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); +/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace"))); +/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot)))); +/// ``` +pub fn is_not>( + arr: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + T: FindToken<::Item>, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::IsNot; + i.split_at_position1_complete(|c| arr.find_token(c), e) + } +} + +/// Returns the longest slice of the matches the pattern. +/// +/// The parser will return the longest slice consisting of the characters in provided in the +/// combinator's argument. +/// +/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::is_a; +/// +/// fn hex(s: &str) -> IResult<&str, &str> { +/// is_a("1234567890ABCDEF")(s) +/// } +/// +/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); +/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); +/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); +/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E"))); +/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA)))); +/// ``` +pub fn is_a>( + arr: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + T: FindToken<::Item>, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::IsA; + i.split_at_position1_complete(|c| !arr.find_token(c), e) + } +} + +/// Returns the longest input slice (if any) that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::complete::take_while; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); +/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); +/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..]))); +/// ``` +pub fn take_while>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| i.split_at_position_complete(|c| !cond(c)) +} + +/// Returns the longest (at least 1) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take_while1; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while1(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); +/// ``` +pub fn take_while1>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::TakeWhile1; + i.split_at_position1_complete(|c| !cond(c), e) + } +} + +/// Returns the longest (m <= len <= n) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out +/// of range (m <= len <= n). +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take_while_m_n; +/// use nom::character::is_alphabetic; +/// +/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while_m_n(3, 6, is_alphabetic)(s) +/// } +/// +/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); +/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); +/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN)))); +/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); +/// ``` +pub fn take_while_m_n>( + m: usize, + n: usize, + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputIter + InputLength + Slice>, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let input = i; + + match input.position(|c| !cond(c)) { + Some(idx) => { + if idx >= m { + if idx <= n { + let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { + Ok(input.take_split(index)) + } else { + Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))) + }; + res + } else { + let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { + Ok(input.take_split(index)) + } else { + Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))) + }; + res + } + } else { + let e = ErrorKind::TakeWhileMN; + Err(Err::Error(Error::from_error_kind(input, e))) + } + } + None => { + let len = input.input_len(); + if len >= n { + match input.slice_index(n) { + Ok(index) => Ok(input.take_split(index)), + Err(_needed) => Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))), + } + } else if len >= m && len <= n { + let res: IResult<_, _, Error> = Ok((input.slice(len..), input)); + res + } else { + let e = ErrorKind::TakeWhileMN; + Err(Err::Error(Error::from_error_kind(input, e))) + } + } + } + } +} + +/// Returns the longest input slice (if any) till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::complete::take_till; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed +/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); +/// assert_eq!(till_colon(""), Ok(("", ""))); +/// ``` +pub fn take_till>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| i.split_at_position_complete(|c| cond(c)) +} + +/// Returns the longest (at least 1) input slice till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the +/// predicate matches the first input. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take_till1; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till1(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); +/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); +/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1)))); +/// ``` +pub fn take_till1>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::TakeTill1; + i.split_at_position1_complete(|c| cond(c), e) + } +} + +/// Returns an input slice containing the first N input elements (Input[..N]). +/// +/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take; +/// +/// fn take6(s: &str) -> IResult<&str, &str> { +/// take(6usize)(s) +/// } +/// +/// assert_eq!(take6("1234567"), Ok(("7", "123456"))); +/// assert_eq!(take6("things"), Ok(("", "things"))); +/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof)))); +/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); +/// ``` +/// +/// The units that are taken will depend on the input type. For example, for a +/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will +/// take that many `u8`'s: +/// +/// ```rust +/// use nom::error::Error; +/// use nom::bytes::complete::take; +/// +/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙"))); +/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref()))); +/// ``` +pub fn take>( + count: C, +) -> impl Fn(Input) -> IResult +where + Input: InputIter + InputTake, + C: ToUsize, +{ + let c = count.to_usize(); + move |i: Input| match i.slice_index(c) { + Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))), + Ok(index) => Ok(i.take_split(index)), + } +} + +/// Returns the input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` +/// if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take_until; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); +/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// ``` +pub fn take_until>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + FindSubstring, + T: InputLength + Clone, +{ + move |i: Input| { + let t = tag.clone(); + let res: IResult<_, _, Error> = match i.find_substring(t) { + None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), + Some(index) => Ok(i.take_split(index)), + }; + res + } +} + +/// Returns the non empty input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` +/// if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::complete::take_until1; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until1("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); +/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); +/// ``` +pub fn take_until1>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + FindSubstring, + T: InputLength + Clone, +{ + move |i: Input| { + let t = tag.clone(); + let res: IResult<_, _, Error> = match i.find_substring(t) { + None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), + Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), + Some(index) => Ok(i.take_split(index)), + }; + res + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not accept the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters +/// # Example +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::character::complete::digit1; +/// use nom::bytes::complete::escaped; +/// use nom::character::complete::one_of; +/// +/// fn esc(s: &str) -> IResult<&str, &str> { +/// escaped(digit1, '\\', one_of(r#""n\"#))(s) +/// } +/// +/// assert_eq!(esc("123;"), Ok((";", "123"))); +/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#))); +/// ``` +/// +pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>( + mut normal: F, + control_char: char, + mut escapable: G, +) -> impl FnMut(Input) -> IResult +where + Input: Clone + + crate::traits::Offset + + InputLength + + InputTake + + InputTakeAtPosition + + Slice> + + InputIter, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + use crate::traits::AsChar; + + move |input: Input| { + let mut i = input.clone(); + + while i.input_len() > 0 { + let current_len = i.input_len(); + + match normal.parse(i.clone()) { + Ok((i2, _)) => { + // return if we consumed everything or if the normal parser + // does not consume anything + if i2.input_len() == 0 { + return Ok((input.slice(input.input_len()..), input)); + } else if i2.input_len() == current_len { + let index = input.offset(&i2); + return Ok(input.take_split(index)); + } else { + i = i2; + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if i.iter_elements().next().unwrap().as_char() == control_char { + let next = control_char.len_utf8(); + if next >= i.input_len() { + return Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::Escaped, + ))); + } else { + match escapable.parse(i.slice(next..)) { + Ok((i2, _)) => { + if i2.input_len() == 0 { + return Ok((input.slice(input.input_len()..), input)); + } else { + i = i2; + } + } + Err(e) => return Err(e), + } + } + } else { + let index = input.offset(&i); + if index == 0 { + return Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::Escaped, + ))); + } + return Ok(input.take_split(index)); + } + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input.slice(input.input_len()..), input)) + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not match the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters and transforms them +/// +/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use std::str::from_utf8; +/// use nom::bytes::complete::{escaped_transform, tag}; +/// use nom::character::complete::alpha1; +/// use nom::branch::alt; +/// use nom::combinator::value; +/// +/// fn parser(input: &str) -> IResult<&str, String> { +/// escaped_transform( +/// alpha1, +/// '\\', +/// alt(( +/// value("\\", tag("\\")), +/// value("\"", tag("\"")), +/// value("\n", tag("n")), +/// )) +/// )(input) +/// } +/// +/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd")))); +/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd")))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn escaped_transform( + mut normal: F, + control_char: char, + mut transform: G, +) -> impl FnMut(Input) -> IResult +where + Input: Clone + + crate::traits::Offset + + InputLength + + InputTake + + InputTakeAtPosition + + Slice> + + InputIter, + Input: crate::traits::ExtendInto, + O1: crate::traits::ExtendInto, + O2: crate::traits::ExtendInto, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + use crate::traits::AsChar; + + move |input: Input| { + let mut index = 0; + let mut res = input.new_builder(); + + let i = input.clone(); + + while index < i.input_len() { + let current_len = i.input_len(); + let remainder = i.slice(index..); + match normal.parse(remainder.clone()) { + Ok((i2, o)) => { + o.extend_into(&mut res); + if i2.input_len() == 0 { + return Ok((i.slice(i.input_len()..), res)); + } else if i2.input_len() == current_len { + return Ok((remainder, res)); + } else { + index = input.offset(&i2); + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if remainder.iter_elements().next().unwrap().as_char() == control_char { + let next = index + control_char.len_utf8(); + let input_len = input.input_len(); + + if next >= input_len { + return Err(Err::Error(Error::from_error_kind( + remainder, + ErrorKind::EscapedTransform, + ))); + } else { + match transform.parse(i.slice(next..)) { + Ok((i2, o)) => { + o.extend_into(&mut res); + if i2.input_len() == 0 { + return Ok((i.slice(i.input_len()..), res)); + } else { + index = input.offset(&i2); + } + } + Err(e) => return Err(e), + } + } + } else { + if index == 0 { + return Err(Err::Error(Error::from_error_kind( + remainder, + ErrorKind::EscapedTransform, + ))); + } + return Ok((remainder, res)); + } + } + Err(e) => return Err(e), + } + } + Ok((input.slice(index..), res)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn complete_take_while_m_n_utf8_all_matching() { + let result: IResult<&str, &str> = + super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("", "øn"))); + } + + #[test] + fn complete_take_while_m_n_utf8_all_matching_substring() { + let result: IResult<&str, &str> = + super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("n", "ø"))); + } + + // issue #1336 "escaped hangs if normal parser accepts empty" + fn escaped_string(input: &str) -> IResult<&str, &str> { + use crate::character::complete::{alpha0, one_of}; + escaped(alpha0, '\\', one_of("n"))(input) + } + + // issue #1336 "escaped hangs if normal parser accepts empty" + #[test] + fn escaped_hang() { + escaped_string("7").unwrap(); + escaped_string("a7").unwrap(); + } + + // issue ##1118 escaped does not work with empty string + fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> { + use crate::bytes::complete::*; + use crate::character::complete::*; + use crate::combinator::opt; + use crate::sequence::delimited; + + delimited( + char('"'), + escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), + char('"'), + )(input) + } + + #[test] + fn escaped_hang_1118() { + assert_eq!(unquote(r#""""#), Ok(("", ""))); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +//! Parsers recognizing bytes streams + +pub mod complete; +pub mod streaming; +#[cfg(test)] +mod tests; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/streaming.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,700 @@ +//! Parsers recognizing bytes streams, streaming version + +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Needed, Parser}; +use crate::lib::std::ops::RangeFrom; +use crate::lib::std::result::Result::*; +use crate::traits::{ + Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, + InputTakeAtPosition, Slice, ToUsize, +}; + +/// Recognizes a pattern. +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::tag; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag("Hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag)))); +/// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4)))); +/// ``` +pub fn tag>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputLength + Compare, + T: InputLength + Clone, +{ + move |i: Input| { + let tag_len = tag.input_len(); + let t = tag.clone(); + + let res: IResult<_, _, Error> = match i.compare(t) { + CompareResult::Ok => Ok(i.take_split(tag_len)), + CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(Error::from_error_kind(i, e))) + } + }; + res + } +} + +/// Recognizes a case insensitive pattern. +/// +/// The input data will be compared to the tag combinator's argument and will return the part of +/// the input that matches the argument with no regard to case. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::tag_no_case; +/// +/// fn parser(s: &str) -> IResult<&str, &str> { +/// tag_no_case("hello")(s) +/// } +/// +/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); +/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); +/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); +/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5)))); +/// ``` +pub fn tag_no_case>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputLength + Compare, + T: InputLength + Clone, +{ + move |i: Input| { + let tag_len = tag.input_len(); + let t = tag.clone(); + + let res: IResult<_, _, Error> = match (i).compare_no_case(t) { + CompareResult::Ok => Ok(i.take_split(tag_len)), + CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(Error::from_error_kind(i, e))) + } + }; + res + } +} + +/// Parse till certain characters are met. +/// +/// The parser will return the longest slice till one of the characters of the combinator's argument are met. +/// +/// It doesn't consume the matched character. +/// +/// It will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::is_not; +/// +/// fn not_space(s: &str) -> IResult<&str, &str> { +/// is_not(" \t\r\n")(s) +/// } +/// +/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); +/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); +/// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn is_not>( + arr: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + T: FindToken<::Item>, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::IsNot; + i.split_at_position1(|c| arr.find_token(c), e) + } +} + +/// Returns the longest slice of the matches the pattern. +/// +/// The parser will return the longest slice consisting of the characters in provided in the +/// combinator's argument. +/// +/// # Streaming specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met +/// or if the pattern reaches the end of the input. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::is_a; +/// +/// fn hex(s: &str) -> IResult<&str, &str> { +/// is_a("1234567890ABCDEF")(s) +/// } +/// +/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); +/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); +/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); +/// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(hex(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn is_a>( + arr: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + T: FindToken<::Item>, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::IsA; + i.split_at_position1(|c| !arr.find_token(c), e) + } +} + +/// Returns the longest input slice (if any) that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take_while; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); +/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn take_while>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| i.split_at_position(|c| !cond(c)) +} + +/// Returns the longest (at least 1) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input. +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_while1; +/// use nom::character::is_alphabetic; +/// +/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while1(is_alphabetic)(s) +/// } +/// +/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); +/// ``` +pub fn take_while1>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::TakeWhile1; + i.split_at_position1(|c| !cond(c), e) + } +} + +/// Returns the longest (m <= len <= n) input slice that matches the predicate. +/// +/// The parser will return the longest slice that matches the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met. +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short. +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_while_m_n; +/// use nom::character::is_alphabetic; +/// +/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// take_while_m_n(3, 6, is_alphabetic)(s) +/// } +/// +/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); +/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); +/// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); +/// ``` +pub fn take_while_m_n>( + m: usize, + n: usize, + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputIter + InputLength, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let input = i; + + match input.position(|c| !cond(c)) { + Some(idx) => { + if idx >= m { + if idx <= n { + let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { + Ok(input.take_split(index)) + } else { + Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))) + }; + res + } else { + let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { + Ok(input.take_split(index)) + } else { + Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))) + }; + res + } + } else { + let e = ErrorKind::TakeWhileMN; + Err(Err::Error(Error::from_error_kind(input, e))) + } + } + None => { + let len = input.input_len(); + if len >= n { + match input.slice_index(n) { + Ok(index) => Ok(input.take_split(index)), + Err(_needed) => Err(Err::Error(Error::from_error_kind( + input, + ErrorKind::TakeWhileMN, + ))), + } + } else { + let needed = if m > len { m - len } else { 1 }; + Err(Err::Incomplete(Needed::new(needed))) + } + } + } + } +} + +/// Returns the longest input slice (if any) till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the +/// end of input or if there was not match. +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take_till; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed +/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn take_till>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| i.split_at_position(|c| cond(c)) +} + +/// Returns the longest (at least 1) input slice till a predicate is met. +/// +/// The parser will return the longest slice till the given predicate *(a function that +/// takes the input and returns a bool)*. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the +/// end of input or if there was not match. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_till1; +/// +/// fn till_colon(s: &str) -> IResult<&str, &str> { +/// take_till1(|c| c == ':')(s) +/// } +/// +/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); +/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); +/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn take_till1>( + cond: F, +) -> impl Fn(Input) -> IResult +where + Input: InputTakeAtPosition, + F: Fn(::Item) -> bool, +{ + move |i: Input| { + let e: ErrorKind = ErrorKind::TakeTill1; + i.split_at_position1(|c| cond(c), e) + } +} + +/// Returns an input slice containing the first N input elements (Input[..N]). +/// +/// # Streaming Specific +/// *Streaming version* if the input has less than N elements, `take` will +/// return a `Err::Incomplete(Needed::new(M))` where M is the number of +/// additional bytes the parser would need to succeed. +/// It is well defined for `&[u8]` as the number of elements is the byte size, +/// but for types like `&str`, we cannot know how many bytes correspond for +/// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)` +/// +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take; +/// +/// fn take6(s: &str) -> IResult<&str, &str> { +/// take(6usize)(s) +/// } +/// +/// assert_eq!(take6("1234567"), Ok(("7", "123456"))); +/// assert_eq!(take6("things"), Ok(("", "things"))); +/// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown))); +/// ``` +pub fn take>( + count: C, +) -> impl Fn(Input) -> IResult +where + Input: InputIter + InputTake + InputLength, + C: ToUsize, +{ + let c = count.to_usize(); + move |i: Input| match i.slice_index(c) { + Err(i) => Err(Err::Incomplete(i)), + Ok(index) => Ok(i.take_split(index)), + } +} + +/// Returns the input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't +/// contain the pattern or if the input is smaller than the pattern. +/// # Example +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::bytes::streaming::take_until; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// ``` +pub fn take_until>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputLength + FindSubstring, + T: Clone, +{ + move |i: Input| { + let t = tag.clone(); + + let res: IResult<_, _, Error> = match i.find_substring(t) { + None => Err(Err::Incomplete(Needed::Unknown)), + Some(index) => Ok(i.take_split(index)), + }; + res + } +} + +/// Returns the non empty input slice up to the first occurrence of the pattern. +/// +/// It doesn't consume the pattern. +/// +/// # Streaming Specific +/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't +/// contain the pattern or if the input is smaller than the pattern. +/// # Example +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::bytes::streaming::take_until1; +/// +/// fn until_eof(s: &str) -> IResult<&str, &str> { +/// take_until1("eof")(s) +/// } +/// +/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); +/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); +/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); +/// ``` +pub fn take_until1>( + tag: T, +) -> impl Fn(Input) -> IResult +where + Input: InputTake + InputLength + FindSubstring, + T: Clone, +{ + move |i: Input| { + let t = tag.clone(); + + let res: IResult<_, _, Error> = match i.find_substring(t) { + None => Err(Err::Incomplete(Needed::Unknown)), + Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), + Some(index) => Ok(i.take_split(index)), + }; + res + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not accept the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters +/// # Example +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use nom::character::complete::digit1; +/// use nom::bytes::streaming::escaped; +/// use nom::character::streaming::one_of; +/// +/// fn esc(s: &str) -> IResult<&str, &str> { +/// escaped(digit1, '\\', one_of("\"n\\"))(s) +/// } +/// +/// assert_eq!(esc("123;"), Ok((";", "123"))); +/// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34"))); +/// ``` +/// +pub fn escaped( + mut normal: F, + control_char: char, + mut escapable: G, +) -> impl FnMut(Input) -> IResult +where + Input: Clone + + crate::traits::Offset + + InputLength + + InputTake + + InputTakeAtPosition + + Slice> + + InputIter, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + use crate::traits::AsChar; + + move |input: Input| { + let mut i = input.clone(); + + while i.input_len() > 0 { + let current_len = i.input_len(); + + match normal.parse(i.clone()) { + Ok((i2, _)) => { + if i2.input_len() == 0 { + return Err(Err::Incomplete(Needed::Unknown)); + } else if i2.input_len() == current_len { + let index = input.offset(&i2); + return Ok(input.take_split(index)); + } else { + i = i2; + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if i.iter_elements().next().unwrap().as_char() == control_char { + let next = control_char.len_utf8(); + if next >= i.input_len() { + return Err(Err::Incomplete(Needed::new(1))); + } else { + match escapable.parse(i.slice(next..)) { + Ok((i2, _)) => { + if i2.input_len() == 0 { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + i = i2; + } + } + Err(e) => return Err(e), + } + } + } else { + let index = input.offset(&i); + return Ok(input.take_split(index)); + } + } + Err(e) => { + return Err(e); + } + } + } + + Err(Err::Incomplete(Needed::Unknown)) + } +} + +/// Matches a byte string with escaped characters. +/// +/// * The first argument matches the normal characters (it must not match the control character) +/// * The second argument is the control character (like `\` in most languages) +/// * The third argument matches the escaped characters and transforms them +/// +/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// # use std::str::from_utf8; +/// use nom::bytes::streaming::{escaped_transform, tag}; +/// use nom::character::streaming::alpha1; +/// use nom::branch::alt; +/// use nom::combinator::value; +/// +/// fn parser(input: &str) -> IResult<&str, String> { +/// escaped_transform( +/// alpha1, +/// '\\', +/// alt(( +/// value("\\", tag("\\")), +/// value("\"", tag("\"")), +/// value("\n", tag("n")), +/// )) +/// )(input) +/// } +/// +/// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd")))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn escaped_transform( + mut normal: F, + control_char: char, + mut transform: G, +) -> impl FnMut(Input) -> IResult +where + Input: Clone + + crate::traits::Offset + + InputLength + + InputTake + + InputTakeAtPosition + + Slice> + + InputIter, + Input: crate::traits::ExtendInto, + O1: crate::traits::ExtendInto, + O2: crate::traits::ExtendInto, + ::Item: crate::traits::AsChar, + F: Parser, + G: Parser, + Error: ParseError, +{ + use crate::traits::AsChar; + + move |input: Input| { + let mut index = 0; + let mut res = input.new_builder(); + + let i = input.clone(); + + while index < i.input_len() { + let current_len = i.input_len(); + let remainder = i.slice(index..); + match normal.parse(remainder.clone()) { + Ok((i2, o)) => { + o.extend_into(&mut res); + if i2.input_len() == 0 { + return Err(Err::Incomplete(Needed::Unknown)); + } else if i2.input_len() == current_len { + return Ok((remainder, res)); + } else { + index = input.offset(&i2); + } + } + Err(Err::Error(_)) => { + // unwrap() should be safe here since index < $i.input_len() + if remainder.iter_elements().next().unwrap().as_char() == control_char { + let next = index + control_char.len_utf8(); + let input_len = input.input_len(); + + if next >= input_len { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + match transform.parse(i.slice(next..)) { + Ok((i2, o)) => { + o.extend_into(&mut res); + if i2.input_len() == 0 { + return Err(Err::Incomplete(Needed::Unknown)); + } else { + index = input.offset(&i2); + } + } + Err(e) => return Err(e), + } + } + } else { + return Ok((remainder, res)); + } + } + Err(e) => return Err(e), + } + } + Err(Err::Incomplete(Needed::Unknown)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/bytes/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,636 @@ +use crate::character::is_alphabetic; +use crate::character::streaming::{ + alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, + multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, +}; +use crate::error::ErrorKind; +use crate::internal::{Err, IResult, Needed}; +#[cfg(feature = "alloc")] +use crate::{ + branch::alt, + bytes::complete::{escaped, escaped_transform, tag}, + combinator::{map, value}, + lib::std::string::String, + lib::std::vec::Vec, +}; + +#[test] +fn is_a() { + use crate::bytes::streaming::is_a; + + fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { + is_a("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..]))); + + let b = &b"bcde"[..]; + assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..]))); + + let c = &b"cdef"[..]; + assert_eq!( + a_or_b(c), + Err(Err::Error(error_position!(c, ErrorKind::IsA))) + ); + + let d = &b"bacdef"[..]; + assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..]))); +} + +#[test] +fn is_not() { + use crate::bytes::streaming::is_not; + + fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { + is_not("ab")(i) + } + + let a = &b"cdab"[..]; + assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..]))); + + let b = &b"cbde"[..]; + assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..]))); + + let c = &b"abab"[..]; + assert_eq!( + a_or_b(c), + Err(Err::Error(error_position!(c, ErrorKind::IsNot))) + ); + + let d = &b"cdefba"[..]; + assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..]))); + + let e = &b"e"[..]; + assert_eq!(a_or_b(e), Err(Err::Incomplete(Needed::new(1)))); +} + +#[cfg(feature = "alloc")] +#[allow(unused_variables)] +#[test] +fn escaping() { + use crate::character::streaming::one_of; + + fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..]))); + assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..]))); + assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..]))); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..]))); + assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..]))); + assert_eq!( + esc(&b"AB\\"[..]), + Err(Err::Error(error_position!( + &b"AB\\"[..], + ErrorKind::Escaped + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(Err::Error(error_node_position!( + &b"AB\\A"[..], + ErrorKind::Escaped, + error_position!(&b"A"[..], ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..]))); +} + +#[cfg(feature = "alloc")] +#[test] +fn escaping_str() { + use crate::character::streaming::one_of; + + fn esc(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc("abcd;"), Ok((";", "abcd"))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd"))); + assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd"))); + assert_eq!(esc("\\n;"), Ok((";", "\\n"))); + assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\""))); + assert_eq!( + esc("AB\\"), + Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped))) + ); + assert_eq!( + esc("AB\\A"), + Err(Err::Error(error_node_position!( + "AB\\A", + ErrorKind::Escaped, + error_position!("A", ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, &str> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n"))); + + fn esc3(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\u{241b}', one_of("\"n"))(i) + } + assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd"))); +} + +#[cfg(feature = "alloc")] +fn to_s(i: Vec) -> String { + String::from_utf8_lossy(&i).into_owned() +} + +#[cfg(feature = "alloc")] +#[test] +fn escape_transform() { + fn esc(i: &[u8]) -> IResult<&[u8], String> { + map( + escaped_transform( + alpha, + '\\', + alt(( + value(&b"\\"[..], tag("\\")), + value(&b"\""[..], tag("\"")), + value(&b"\n"[..], tag("n")), + )), + ), + to_s, + )(i) + } + + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); + assert_eq!( + esc(&b"ab\\\"cd;"[..]), + Ok((&b";"[..], String::from("ab\"cd"))) + ); + assert_eq!( + esc(&b"\\\"abcd;"[..]), + Ok((&b";"[..], String::from("\"abcd"))) + ); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n")))); + assert_eq!( + esc(&b"ab\\\"12"[..]), + Ok((&b"12"[..], String::from("ab\""))) + ); + assert_eq!( + esc(&b"AB\\"[..]), + Err(Err::Error(error_position!( + &b"\\"[..], + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(Err::Error(error_node_position!( + &b"AB\\A"[..], + ErrorKind::EscapedTransform, + error_position!(&b"A"[..], ErrorKind::Tag) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], String> { + map( + escaped_transform( + alpha, + '&', + alt(( + value("è".as_bytes(), tag("egrave;")), + value("à".as_bytes(), tag("agrave;")), + )), + ), + to_s, + )(i) + } + assert_eq!( + esc2(&b"abèDEF;"[..]), + Ok((&b";"[..], String::from("abèDEF"))) + ); + assert_eq!( + esc2(&b"abèDàEF;"[..]), + Ok((&b";"[..], String::from("abèDàEF"))) + ); +} + +#[cfg(feature = "std")] +#[test] +fn escape_transform_str() { + fn esc(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '\\', + alt(( + value("\\", tag("\\")), + value("\"", tag("\"")), + value("\n", tag("n")), + )), + )(i) + } + + assert_eq!(esc("abcd;"), Ok((";", String::from("abcd")))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd")))); + assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd")))); + assert_eq!(esc("\\n;"), Ok((";", String::from("\n")))); + assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\"")))); + assert_eq!( + esc("AB\\"), + Err(Err::Error(error_position!( + "\\", + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc("AB\\A"), + Err(Err::Error(error_node_position!( + "AB\\A", + ErrorKind::EscapedTransform, + error_position!("A", ErrorKind::Tag) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '&', + alt((value("è", tag("egrave;")), value("à", tag("agrave;")))), + )(i) + } + assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF")))); + assert_eq!( + esc2("abèDàEF;"), + Ok((";", String::from("abèDàEF"))) + ); + + fn esc3(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '␛', + alt((value("\0", tag("0")), value("\n", tag("n")))), + )(i) + } + assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n")))); +} + +#[test] +fn take_until_incomplete() { + use crate::bytes::streaming::take_until; + fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_until("end")(i) + } + assert_eq!(y(&b"nd"[..]), Err(Err::Incomplete(Needed::Unknown))); + assert_eq!(y(&b"123"[..]), Err(Err::Incomplete(Needed::Unknown))); + assert_eq!(y(&b"123en"[..]), Err(Err::Incomplete(Needed::Unknown))); +} + +#[test] +fn take_until_incomplete_s() { + use crate::bytes::streaming::take_until; + fn ys(i: &str) -> IResult<&str, &str> { + take_until("end")(i) + } + assert_eq!(ys("123en"), Err(Err::Incomplete(Needed::Unknown))); +} + +#[test] +fn recognize() { + use crate::bytes::streaming::{tag, take}; + use crate::combinator::recognize; + use crate::sequence::delimited; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(delimited(tag("")))(i) + } + let r = x(&b" aaa"[..]); + assert_eq!(r, Ok((&b" aaa"[..], &b""[..]))); + + let semicolon = &b";"[..]; + + fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(alpha)(i) + } + let ra = ya(&b"abc;"[..]); + assert_eq!(ra, Ok((semicolon, &b"abc"[..]))); + + fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(digit)(i) + } + let rd = yd(&b"123;"[..]); + assert_eq!(rd, Ok((semicolon, &b"123"[..]))); + + fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(hex_digit)(i) + } + let rhd = yhd(&b"123abcDEF;"[..]); + assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..]))); + + fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(oct_digit)(i) + } + let rod = yod(&b"1234567;"[..]); + assert_eq!(rod, Ok((semicolon, &b"1234567"[..]))); + + fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(alphanumeric)(i) + } + let ran = yan(&b"123abc;"[..]); + assert_eq!(ran, Ok((semicolon, &b"123abc"[..]))); + + fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(space)(i) + } + let rs = ys(&b" \t;"[..]); + assert_eq!(rs, Ok((semicolon, &b" \t"[..]))); + + fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(multispace)(i) + } + let rms = yms(&b" \t\r\n;"[..]); + assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..]))); +} + +#[test] +fn take_while() { + use crate::bytes::streaming::take_while; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while(is_alphabetic)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"abcd123"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); + assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); +} + +#[test] +fn take_while1() { + use crate::bytes::streaming::take_while1; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while1(is_alphabetic)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"abcd123"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..]))); + assert_eq!( + f(&d[..]), + Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1))) + ); +} + +#[test] +fn take_while_m_n() { + use crate::bytes::streaming::take_while_m_n; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while_m_n(2, 4, is_alphabetic)(i) + } + let a = b""; + let b = b"a"; + let c = b"abc"; + let d = b"abc123"; + let e = b"abcde"; + let f = b"123"; + + assert_eq!(x(&a[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!(x(&b[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(x(&c[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..]))); + assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..]))); + assert_eq!( + x(&f[..]), + Err(Err::Error(error_position!(&f[..], ErrorKind::TakeWhileMN))) + ); +} + +#[test] +fn take_till() { + use crate::bytes::streaming::take_till; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_till(is_alphabetic)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"123abcd"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..]))); + assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); + assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1)))); +} + +#[test] +fn take_till1() { + use crate::bytes::streaming::take_till1; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_till1(is_alphabetic)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"123abcd"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!( + f(&b[..]), + Err(Err::Error(error_position!(&b[..], ErrorKind::TakeTill1))) + ); + assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); + assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1)))); +} + +#[test] +fn take_while_utf8() { + use crate::bytes::streaming::take_while; + + fn f(i: &str) -> IResult<&str, &str> { + take_while(|c| c != '點')(i) + } + + assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd點"), Ok(("點", "abcd"))); + assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); + + fn g(i: &str) -> IResult<&str, &str> { + take_while(|c| c == '點')(i) + } + + assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); +} + +#[test] +fn take_till_utf8() { + use crate::bytes::streaming::take_till; + + fn f(i: &str) -> IResult<&str, &str> { + take_till(|c| c == '點')(i) + } + + assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd點"), Ok(("點", "abcd"))); + assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); + + fn g(i: &str) -> IResult<&str, &str> { + take_till(|c| c != '點')(i) + } + + assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); +} + +#[test] +fn take_utf8() { + use crate::bytes::streaming::{take, take_while}; + + fn f(i: &str) -> IResult<&str, &str> { + take(3_usize)(i) + } + + assert_eq!(f(""), Err(Err::Incomplete(Needed::Unknown))); + assert_eq!(f("ab"), Err(Err::Incomplete(Needed::Unknown))); + assert_eq!(f("點"), Err(Err::Incomplete(Needed::Unknown))); + assert_eq!(f("ab點cd"), Ok(("cd", "ab點"))); + assert_eq!(f("a點bcd"), Ok(("cd", "a點b"))); + assert_eq!(f("a點b"), Ok(("", "a點b"))); + + fn g(i: &str) -> IResult<&str, &str> { + take_while(|c| c == '點')(i) + } + + assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); +} + +#[test] +fn take_while_m_n_utf8() { + use crate::bytes::streaming::take_while_m_n; + + fn parser(i: &str) -> IResult<&str, &str> { + take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i) + } + assert_eq!(parser("A!"), Ok(("!", "A"))); + assert_eq!(parser("😃!"), Ok(("!", "😃"))); +} + +#[test] +fn take_while_m_n_utf8_full_match() { + use crate::bytes::streaming::take_while_m_n; + + fn parser(i: &str) -> IResult<&str, &str> { + take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i) + } + assert_eq!(parser("øn"), Ok(("n", "ø"))); +} + +#[test] +#[cfg(feature = "std")] +fn recognize_take_while() { + use crate::bytes::streaming::take_while; + use crate::character::is_alphanumeric; + use crate::combinator::recognize; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while(is_alphanumeric)(i) + } + fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(x)(i) + } + assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); + println!("X: {:?}", x(&b"ab"[..])); + assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); +} + +#[test] +fn length_bytes() { + use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8}; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + length_data(le_u8)(i) + } + assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..]))); + assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..]))); + assert_eq!(x(b"\x02."), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(x(b"\x02"), Err(Err::Incomplete(Needed::new(2)))); + + fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { + let (i, _) = tag("magic")(i)?; + length_data(le_u8)(i) + } + assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..]))); + assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..]))); + assert_eq!(y(b"magic\x02."), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(y(b"magic\x02"), Err(Err::Incomplete(Needed::new(2)))); +} + +#[cfg(feature = "alloc")] +#[test] +fn case_insensitive() { + use crate::bytes::streaming::tag_no_case; + + fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag_no_case("ABcd")(i) + } + assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..]))); + assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..]))); + assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..]))); + assert_eq!(test(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + test(&b"Hello"[..]), + Err(Err::Error(error_position!(&b"Hello"[..], ErrorKind::Tag))) + ); + assert_eq!( + test(&b"Hel"[..]), + Err(Err::Error(error_position!(&b"Hel"[..], ErrorKind::Tag))) + ); + + fn test2(i: &str) -> IResult<&str, &str> { + tag_no_case("ABcd")(i) + } + assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd"))); + assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd"))); + assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD"))); + assert_eq!(test2("ab"), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + test2("Hello"), + Err(Err::Error(error_position!(&"Hello"[..], ErrorKind::Tag))) + ); + assert_eq!( + test2("Hel"), + Err(Err::Error(error_position!(&"Hel"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn tag_fixed_size_array() { + use crate::bytes::streaming::tag; + + fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag([0x42])(i) + } + fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag(&[0x42])(i) + } + let input = [0x42, 0x00]; + assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); + assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/complete.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1227 @@ +//! Character specific parsers and combinators, complete input version. +//! +//! Functions recognizing specific characters. + +use crate::branch::alt; +use crate::combinator::opt; +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult}; +use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; +use crate::traits::{ + AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice, +}; +use crate::traits::{Compare, CompareResult}; + +/// Recognizes one character. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{ErrorKind, Error}, IResult}; +/// # use nom::character::complete::char; +/// fn parser(i: &str) -> IResult<&str, char> { +/// char('a')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser(" abc"), Err(Err::Error(Error::new(" abc", ErrorKind::Char)))); +/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); +/// ``` +pub fn char>(c: char) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar, +{ + move |i: I| match (i).iter_elements().next().map(|t| { + let b = t.as_char() == c; + (&c, b) + }) { + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + _ => Err(Err::Error(Error::from_char(i, c))), + } +} + +/// Recognizes one character and checks that it satisfies a predicate +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; +/// # use nom::character::complete::satisfy; +/// fn parser(i: &str) -> IResult<&str, char> { +/// satisfy(|c| c == 'a' || c == 'b')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy)))); +/// ``` +pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar, + F: Fn(char) -> bool, +{ + move |i: I| match (i).iter_elements().next().map(|t| { + let c = t.as_char(); + let b = cond(c); + (c, b) + }) { + Some((c, true)) => Ok((i.slice(c.len()..), c)), + _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))), + } +} + +/// Recognizes one of the provided characters. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind}; +/// # use nom::character::complete::one_of; +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("abc")("b"), Ok(("", 'b'))); +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); +/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf)))); +/// ``` +pub fn one_of>(list: T) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar + Copy, + T: FindToken<::Item>, +{ + move |i: I| match (i).iter_elements().next().map(|c| (c, list.find_token(c))) { + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::OneOf))), + } +} + +/// Recognizes a character that is not in the provided characters. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind}; +/// # use nom::character::complete::none_of; +/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("abc")("z"), Ok(("", 'z'))); +/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); +/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::NoneOf)))); +/// ``` +pub fn none_of>(list: T) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar + Copy, + T: FindToken<::Item>, +{ + move |i: I| match (i).iter_elements().next().map(|c| (c, !list.find_token(c))) { + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::NoneOf))), + } +} + +/// Recognizes the string "\r\n". +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; +/// # use nom::character::complete::crlf; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// crlf(input) +/// } +/// +/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n"))); +/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf)))); +/// ``` +pub fn crlf>(input: T) -> IResult +where + T: Slice> + Slice>, + T: InputIter, + T: Compare<&'static str>, +{ + match input.compare("\r\n") { + //FIXME: is this the right index? + CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + _ => { + let e: ErrorKind = ErrorKind::CrLf; + Err(Err::Error(E::from_error_kind(input, e))) + } + } +} + +//FIXME: there's still an incomplete +/// Recognizes a string of any char except '\r\n' or '\n'. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::not_line_ending; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// not_line_ending(input) +/// } +/// +/// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab"))); +/// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab"))); +/// assert_eq!(parser("abc"), Ok(("", "abc"))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag }))); +/// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag }))); +/// ``` +pub fn not_line_ending>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: InputIter + InputLength, + T: Compare<&'static str>, + ::Item: AsChar, + ::Item: AsChar, +{ + match input.position(|item| { + let c = item.as_char(); + c == '\r' || c == '\n' + }) { + None => Ok((input.slice(input.input_len()..), input)), + Some(index) => { + let mut it = input.slice(index..).iter_elements(); + let nth = it.next().unwrap().as_char(); + if nth == '\r' { + let sliced = input.slice(index..); + let comp = sliced.compare("\r\n"); + match comp { + //FIXME: calculate the right index + CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))), + _ => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(E::from_error_kind(input, e))) + } + } + } else { + Ok((input.slice(index..), input.slice(..index))) + } + } + } +} + +/// Recognizes an end of line (both '\n' and '\r\n'). +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::line_ending; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// line_ending(input) +/// } +/// +/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n"))); +/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf)))); +/// ``` +pub fn line_ending>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: InputIter + InputLength, + T: Compare<&'static str>, +{ + match input.compare("\n") { + CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))), + CompareResult::Incomplete => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), + CompareResult::Error => { + match input.compare("\r\n") { + //FIXME: is this the right index? + CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), + } + } + } +} + +/// Matches a newline character '\n'. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::newline; +/// fn parser(input: &str) -> IResult<&str, char> { +/// newline(input) +/// } +/// +/// assert_eq!(parser("\nc"), Ok(("c", '\n'))); +/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); +/// ``` +pub fn newline>(input: I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar, +{ + char('\n')(input) +} + +/// Matches a tab character '\t'. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::tab; +/// fn parser(input: &str) -> IResult<&str, char> { +/// tab(input) +/// } +/// +/// assert_eq!(parser("\tc"), Ok(("c", '\t'))); +/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); +/// ``` +pub fn tab>(input: I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar, +{ + char('\t')(input) +} + +/// Matches one byte as a character. Note that the input type will +/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. +/// +/// *Complete version*: Will return an error if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{character::complete::anychar, Err, error::{Error, ErrorKind}, IResult}; +/// fn parser(input: &str) -> IResult<&str, char> { +/// anychar(input) +/// } +/// +/// assert_eq!(parser("abc"), Ok(("bc",'a'))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); +/// ``` +pub fn anychar>(input: T) -> IResult +where + T: InputIter + InputLength + Slice>, + ::Item: AsChar, +{ + let mut it = input.iter_indices(); + match it.next() { + None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))), + Some((_, c)) => match it.next() { + None => Ok((input.slice(input.input_len()..), c.as_char())), + Some((idx, _)) => Ok((input.slice(idx..), c.as_char())), + }, + } +} + +/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non +/// alphabetic character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::alpha0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alpha0(input) +/// } +/// +/// assert_eq!(parser("ab1c"), Ok(("1c", "ab"))); +/// assert_eq!(parser("1c"), Ok(("1c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn alpha0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_alpha()) +} + +/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non alphabetic character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::alpha1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alpha1(input) +/// } +/// +/// assert_eq!(parser("aB1c"), Ok(("1c", "aB"))); +/// assert_eq!(parser("1c"), Err(Err::Error(Error::new("1c", ErrorKind::Alpha)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Alpha)))); +/// ``` +pub fn alpha1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_alpha(), ErrorKind::Alpha) +} + +/// Recognizes zero or more ASCII numerical characters: 0-9 +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::digit0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// digit0(input) +/// } +/// +/// assert_eq!(parser("21c"), Ok(("c", "21"))); +/// assert_eq!(parser("21"), Ok(("", "21"))); +/// assert_eq!(parser("a21c"), Ok(("a21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_dec_digit()) +} + +/// Recognizes one or more ASCII numerical characters: 0-9 +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::digit1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// digit1(input) +/// } +/// +/// assert_eq!(parser("21c"), Ok(("c", "21"))); +/// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit)))); +/// ``` +/// +/// ## Parsing an integer +/// You can use `digit1` in combination with [`map_res`] to parse an integer: +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::combinator::map_res; +/// # use nom::character::complete::digit1; +/// fn parser(input: &str) -> IResult<&str, u32> { +/// map_res(digit1, str::parse)(input) +/// } +/// +/// assert_eq!(parser("416"), Ok(("", 416))); +/// assert_eq!(parser("12b"), Ok(("b", 12))); +/// assert!(parser("b").is_err()); +/// ``` +/// +/// [`map_res`]: crate::combinator::map_res +pub fn digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_dec_digit(), ErrorKind::Digit) +} + +/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::hex_digit0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// hex_digit0(input) +/// } +/// +/// assert_eq!(parser("21cZ"), Ok(("Z", "21c"))); +/// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn hex_digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_hex_digit()) +} +/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non hexadecimal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::hex_digit1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// hex_digit1(input) +/// } +/// +/// assert_eq!(parser("21cZ"), Ok(("Z", "21c"))); +/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::HexDigit)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::HexDigit)))); +/// ``` +pub fn hex_digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_hex_digit(), ErrorKind::HexDigit) +} + +/// Recognizes zero or more octal characters: 0-7 +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non octal +/// digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::oct_digit0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// oct_digit0(input) +/// } +/// +/// assert_eq!(parser("21cZ"), Ok(("cZ", "21"))); +/// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn oct_digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_oct_digit()) +} + +/// Recognizes one or more octal characters: 0-7 +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non octal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::oct_digit1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// oct_digit1(input) +/// } +/// +/// assert_eq!(parser("21cZ"), Ok(("cZ", "21"))); +/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::OctDigit)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OctDigit)))); +/// ``` +pub fn oct_digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_oct_digit(), ErrorKind::OctDigit) +} + +/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non +/// alphanumerical character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::alphanumeric0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alphanumeric0(input) +/// } +/// +/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ"))); +/// assert_eq!(parser("&Z21c"), Ok(("&Z21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn alphanumeric0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position_complete(|item| !item.is_alphanum()) +} + +/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non alphanumerical character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::alphanumeric1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alphanumeric1(input) +/// } +/// +/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ"))); +/// assert_eq!(parser("&H2"), Err(Err::Error(Error::new("&H2", ErrorKind::AlphaNumeric)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::AlphaNumeric)))); +/// ``` +pub fn alphanumeric1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1_complete(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric) +} + +/// Recognizes zero or more spaces and tabs. +/// +/// *Complete version*: Will return the whole input if no terminating token is found (a non space +/// character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::space0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// space0(input) +/// } +/// +/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t"))); +/// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn space0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position_complete(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }) +} + +/// Recognizes one or more spaces and tabs. +/// +/// *Complete version*: Will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::space1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// space1(input) +/// } +/// +/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t"))); +/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::Space)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Space)))); +/// ``` +pub fn space1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position1_complete( + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }, + ErrorKind::Space, + ) +} + +/// Recognizes zero or more spaces, tabs, carriage returns and line feeds. +/// +/// *Complete version*: will return the whole input if no terminating token is found (a non space +/// character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::complete::multispace0; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// multispace0(input) +/// } +/// +/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); +/// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// ``` +pub fn multispace0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position_complete(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }) +} + +/// Recognizes one or more spaces, tabs, carriage returns and line feeds. +/// +/// *Complete version*: will return an error if there's not enough input data, +/// or the whole input if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::complete::multispace1; +/// fn parser(input: &str) -> IResult<&str, &str> { +/// multispace1(input) +/// } +/// +/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); +/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::MultiSpace)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::MultiSpace)))); +/// ``` +pub fn multispace1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position1_complete( + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }, + ErrorKind::MultiSpace, + ) +} + +pub(crate) fn sign>(input: T) -> IResult +where + T: Clone + InputTake, + T: for<'a> Compare<&'a [u8]>, +{ + use crate::bytes::complete::tag; + use crate::combinator::value; + + let (i, opt_sign) = opt(alt(( + value(false, tag(&b"-"[..])), + value(true, tag(&b"+"[..])), + )))(input)?; + let sign = opt_sign.unwrap_or(true); + + Ok((i, sign)) +} + +#[doc(hidden)] +macro_rules! ints { + ($($t:tt)+) => { + $( + /// will parse a number in text form to a number + /// + /// *Complete version*: can parse until the end of input. + pub fn $t>(input: T) -> IResult + where + T: InputIter + Slice> + InputLength + InputTake + Clone, + ::Item: AsChar, + T: for <'a> Compare<&'a[u8]>, + { + let (i, sign) = sign(input.clone())?; + + if i.input_len() == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); + } + + let mut value: $t = 0; + if sign { + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + } else { + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + } + + Ok((i.slice(i.input_len()..), value)) + } + )+ + } +} + +ints! { i8 i16 i32 i64 i128 } + +#[doc(hidden)] +macro_rules! uints { + ($($t:tt)+) => { + $( + /// will parse a number in text form to a number + /// + /// *Complete version*: can parse until the end of input. + pub fn $t>(input: T) -> IResult + where + T: InputIter + Slice> + InputLength, + ::Item: AsChar, + { + let i = input; + + if i.input_len() == 0 { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); + } + + let mut value: $t = 0; + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + + Ok((i.slice(i.input_len()..), value)) + } + )+ + } +} + +uints! { u8 u16 u32 u64 u128 } + +#[cfg(test)] +mod tests { + use super::*; + use crate::internal::Err; + use crate::traits::ParseTo; + use proptest::prelude::*; + + macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; + ); + + #[test] + fn character() { + let empty: &[u8] = b""; + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bytes(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::Size(1)))); + assert_parse!(alpha1(a), Ok((empty, a))); + assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..]))); + assert_eq!( + alpha1::<_, (_, ErrorKind)>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); + assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); + assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c))); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(d), + Ok(("zé12".as_bytes(), &b"a"[..])) + ); + assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); + assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e))); + assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..]))); + } + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let empty = ""; + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Ok((empty, a))); + assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..]))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..]))); + assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); + assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); + assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c))); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..]))); + assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); + assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); + assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); + assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e))); + } + + use crate::traits::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, (_, ErrorKind)>(a) { + Ok((i, _)) => { + assert_eq!(a.offset(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, (_, ErrorKind)>(b) { + Ok((i, _)) => { + assert_eq!(b.offset(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, (_, ErrorKind)>(c) { + Ok((i, _)) => { + assert_eq!(c.offset(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, (_, ErrorKind)>(d) { + Ok((i, _)) => { + assert_eq!(d.offset(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, (_, ErrorKind)>(e) { + Ok((i, _)) => { + assert_eq!(e.offset(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } + } + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(a), + Ok((&b"\nefgh"[..], &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(b), + Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(c), + Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(d), + Ok((&[][..], &d[..])) + ); + } + + #[test] + fn is_not_line_ending_str() { + /* + let a: &str = "ab12cd\nefgh"; + assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); + + let b: &str = "ab12cd\nefgh\nijkl"; + assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let c: &str = "ab12cd\r\nefgh\nijkl"; + assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let d = "βèƒôřè\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + + let e = "βèƒôřè\r\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + */ + + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag)))); + + let g2: &str = "ab12cd"; + assert_eq!(not_line_ending::<_, (_, ErrorKind)>(g2), Ok(("", g2))); + } + + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) + ); + + assert!(crate::character::is_hex_digit(b'0')); + assert!(crate::character::is_hex_digit(b'9')); + assert!(crate::character::is_hex_digit(b'a')); + assert!(crate::character::is_hex_digit(b'f')); + assert!(crate::character::is_hex_digit(b'A')); + assert!(crate::character::is_hex_digit(b'F')); + assert!(!crate::character::is_hex_digit(b'g')); + assert!(!crate::character::is_hex_digit(b'G')); + assert!(!crate::character::is_hex_digit(b'/')); + assert!(!crate::character::is_hex_digit(b':')); + assert!(!crate::character::is_hex_digit(b'@')); + assert!(!crate::character::is_hex_digit(b'\x60')); + } + + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::OctDigit))) + ); + + assert!(crate::character::is_oct_digit(b'0')); + assert!(crate::character::is_oct_digit(b'7')); + assert!(!crate::character::is_oct_digit(b'8')); + assert!(!crate::character::is_oct_digit(b'9')); + assert!(!crate::character::is_oct_digit(b'a')); + assert!(!crate::character::is_oct_digit(b'A')); + assert!(!crate::character::is_oct_digit(b'/')); + assert!(!crate::character::is_oct_digit(b':')); + assert!(!crate::character::is_oct_digit(b'@')); + assert!(!crate::character::is_oct_digit(b'\x60')); + } + + #[test] + fn full_line_windows() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\r\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); + } + + #[test] + fn full_line_unix() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); + } + + #[test] + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); + } + + #[test] + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); + } + + #[test] + fn cr_lf() { + assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + crlf(&b"\r"[..]), + Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf))) + ); + assert_parse!( + crlf(&b"\ra"[..]), + Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) + ); + + assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + crlf("\r"), + Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf))) + ); + assert_parse!( + crlf("\ra"), + Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + #[test] + fn end_of_line() { + assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); + assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + line_ending(&b"\r"[..]), + Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf))) + ); + assert_parse!( + line_ending(&b"\ra"[..]), + Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) + ); + + assert_parse!(line_ending("\na"), Ok(("a", "\n"))); + assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + line_ending("\r"), + Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf))) + ); + assert_parse!( + line_ending("\ra"), + Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + fn digit_to_i16(input: &str) -> IResult<&str, i16> { + let i = input; + let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let sign = match opt_sign { + Some('+') => true, + Some('-') => false, + _ => true, + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { + Ok((i, s)) => (i, s), + Err(_) => { + return Err(Err::Error(crate::error::Error::from_error_kind( + input, + ErrorKind::Digit, + ))) + } + }; + + match s.parse_to() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(Err::Error(crate::error::Error::from_error_kind( + i, + ErrorKind::Digit, + ))), + } + } + + fn digit_to_u32(i: &str) -> IResult<&str, u32> { + let (i, s) = digit1(i)?; + match s.parse_to() { + Some(n) => Ok((i, n)), + None => Err(Err::Error(crate::error::Error::from_error_kind( + i, + ErrorKind::Digit, + ))), + } + } + + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(&s); + let res2 = i16(s.as_str()); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(&s); + let res2 = u32(s.as_str()); + assert_eq!(res1, res2); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,116 @@ +//! Character specific parsers and combinators +//! +//! Functions recognizing specific characters + +#[cfg(test)] +mod tests; + +pub mod complete; +pub mod streaming; + +/// Tests if byte is ASCII alphabetic: A-Z, a-z +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_alphabetic; +/// assert_eq!(is_alphabetic(b'9'), false); +/// assert_eq!(is_alphabetic(b'a'), true); +/// ``` +#[inline] +pub fn is_alphabetic(chr: u8) -> bool { + (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A) +} + +/// Tests if byte is ASCII digit: 0-9 +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_digit; +/// assert_eq!(is_digit(b'a'), false); +/// assert_eq!(is_digit(b'9'), true); +/// ``` +#[inline] +pub fn is_digit(chr: u8) -> bool { + chr >= 0x30 && chr <= 0x39 +} + +/// Tests if byte is ASCII hex digit: 0-9, A-F, a-f +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_hex_digit; +/// assert_eq!(is_hex_digit(b'a'), true); +/// assert_eq!(is_hex_digit(b'9'), true); +/// assert_eq!(is_hex_digit(b'A'), true); +/// assert_eq!(is_hex_digit(b'x'), false); +/// ``` +#[inline] +pub fn is_hex_digit(chr: u8) -> bool { + (chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66) +} + +/// Tests if byte is ASCII octal digit: 0-7 +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_oct_digit; +/// assert_eq!(is_oct_digit(b'a'), false); +/// assert_eq!(is_oct_digit(b'9'), false); +/// assert_eq!(is_oct_digit(b'6'), true); +/// ``` +#[inline] +pub fn is_oct_digit(chr: u8) -> bool { + chr >= 0x30 && chr <= 0x37 +} + +/// Tests if byte is ASCII alphanumeric: A-Z, a-z, 0-9 +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_alphanumeric; +/// assert_eq!(is_alphanumeric(b'-'), false); +/// assert_eq!(is_alphanumeric(b'a'), true); +/// assert_eq!(is_alphanumeric(b'9'), true); +/// assert_eq!(is_alphanumeric(b'A'), true); +/// ``` +#[inline] +pub fn is_alphanumeric(chr: u8) -> bool { + is_alphabetic(chr) || is_digit(chr) +} + +/// Tests if byte is ASCII space or tab +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_space; +/// assert_eq!(is_space(b'\n'), false); +/// assert_eq!(is_space(b'\r'), false); +/// assert_eq!(is_space(b' '), true); +/// assert_eq!(is_space(b'\t'), true); +/// ``` +#[inline] +pub fn is_space(chr: u8) -> bool { + chr == b' ' || chr == b'\t' +} + +/// Tests if byte is ASCII newline: \n +/// +/// # Example +/// +/// ``` +/// # use nom::character::is_newline; +/// assert_eq!(is_newline(b'\n'), true); +/// assert_eq!(is_newline(b'\r'), false); +/// assert_eq!(is_newline(b' '), false); +/// assert_eq!(is_newline(b'\t'), false); +/// ``` +#[inline] +pub fn is_newline(chr: u8) -> bool { + chr == b'\n' +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/streaming.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1182 @@ +//! Character specific parsers and combinators, streaming version +//! +//! Functions recognizing specific characters + +use crate::branch::alt; +use crate::combinator::opt; +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Needed}; +use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; +use crate::traits::{ + AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice, +}; +use crate::traits::{Compare, CompareResult}; + +/// Recognizes one character. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; +/// # use nom::character::streaming::char; +/// fn parser(i: &str) -> IResult<&str, char> { +/// char('a')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); +/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn char>(c: char) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, + ::Item: AsChar, +{ + move |i: I| match (i).iter_elements().next().map(|t| { + let b = t.as_char() == c; + (&c, b) + }) { + None => Err(Err::Incomplete(Needed::new(c.len() - i.input_len()))), + Some((_, false)) => Err(Err::Error(Error::from_char(i, c))), + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + } +} + +/// Recognizes one character and checks that it satisfies a predicate +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; +/// # use nom::character::streaming::satisfy; +/// fn parser(i: &str) -> IResult<&str, char> { +/// satisfy(|c| c == 'a' || c == 'b')(i) +/// } +/// assert_eq!(parser("abc"), Ok(("bc", 'a'))); +/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); +/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Unknown))); +/// ``` +pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar, + F: Fn(char) -> bool, +{ + move |i: I| match (i).iter_elements().next().map(|t| { + let c = t.as_char(); + let b = cond(c); + (c, b) + }) { + None => Err(Err::Incomplete(Needed::Unknown)), + Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))), + Some((c, true)) => Ok((i.slice(c.len()..), c)), + } +} + +/// Recognizes one of the provided characters. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::character::streaming::one_of; +/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("abc")("b"), Ok(("", 'b'))); +/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); +/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn one_of>(list: T) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar + Copy, + T: FindToken<::Item>, +{ + move |i: I| match (i).iter_elements().next().map(|c| (c, list.find_token(c))) { + None => Err(Err::Incomplete(Needed::new(1))), + Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::OneOf))), + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + } +} + +/// Recognizes a character that is not in the provided characters. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::character::streaming::none_of; +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z'))); +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); +/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn none_of>(list: T) -> impl Fn(I) -> IResult +where + I: Slice> + InputIter, + ::Item: AsChar + Copy, + T: FindToken<::Item>, +{ + move |i: I| match (i).iter_elements().next().map(|c| (c, !list.find_token(c))) { + None => Err(Err::Incomplete(Needed::new(1))), + Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::NoneOf))), + Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), + } +} + +/// Recognizes the string "\r\n". +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::crlf; +/// assert_eq!(crlf::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n"))); +/// assert_eq!(crlf::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf)))); +/// assert_eq!(crlf::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +pub fn crlf>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: InputIter, + T: Compare<&'static str>, +{ + match input.compare("\r\n") { + //FIXME: is this the right index? + CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::CrLf; + Err(Err::Error(E::from_error_kind(input, e))) + } + } +} + +/// Recognizes a string of any char except '\r\n' or '\n'. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; +/// # use nom::character::streaming::not_line_ending; +/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Ok(("\r\nc", "ab"))); +/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("abc"), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::Unknown))); +/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rb\nc"), Err(Err::Error(("a\rb\nc", ErrorKind::Tag )))); +/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rbc"), Err(Err::Error(("a\rbc", ErrorKind::Tag )))); +/// ``` +pub fn not_line_ending>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: InputIter + InputLength, + T: Compare<&'static str>, + ::Item: AsChar, + ::Item: AsChar, +{ + match input.position(|item| { + let c = item.as_char(); + c == '\r' || c == '\n' + }) { + None => Err(Err::Incomplete(Needed::Unknown)), + Some(index) => { + let mut it = input.slice(index..).iter_elements(); + let nth = it.next().unwrap().as_char(); + if nth == '\r' { + let sliced = input.slice(index..); + let comp = sliced.compare("\r\n"); + match comp { + //FIXME: calculate the right index + CompareResult::Incomplete => Err(Err::Incomplete(Needed::Unknown)), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(Err::Error(E::from_error_kind(input, e))) + } + CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))), + } + } else { + Ok((input.slice(index..), input.slice(..index))) + } + } + } +} + +/// Recognizes an end of line (both '\n' and '\r\n'). +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::line_ending; +/// assert_eq!(line_ending::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n"))); +/// assert_eq!(line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf)))); +/// assert_eq!(line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn line_ending>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: InputIter + InputLength, + T: Compare<&'static str>, +{ + match input.compare("\n") { + CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))), + CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(1))), + CompareResult::Error => { + match input.compare("\r\n") { + //FIXME: is this the right index? + CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), + CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))), + CompareResult::Error => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), + } + } + } +} + +/// Matches a newline character '\\n'. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::newline; +/// assert_eq!(newline::<_, (_, ErrorKind)>("\nc"), Ok(("c", '\n'))); +/// assert_eq!(newline::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char)))); +/// assert_eq!(newline::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn newline>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, + ::Item: AsChar, +{ + char('\n')(input) +} + +/// Matches a tab character '\t'. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::tab; +/// assert_eq!(tab::<_, (_, ErrorKind)>("\tc"), Ok(("c", '\t'))); +/// assert_eq!(tab::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char)))); +/// assert_eq!(tab::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn tab>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, + ::Item: AsChar, +{ + char('\t')(input) +} + +/// Matches one byte as a character. Note that the input type will +/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data. +/// # Example +/// +/// ``` +/// # use nom::{character::streaming::anychar, Err, error::ErrorKind, IResult, Needed}; +/// assert_eq!(anychar::<_, (_, ErrorKind)>("abc"), Ok(("bc",'a'))); +/// assert_eq!(anychar::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn anychar>(input: T) -> IResult +where + T: InputIter + InputLength + Slice>, + ::Item: AsChar, +{ + let mut it = input.iter_indices(); + match it.next() { + None => Err(Err::Incomplete(Needed::new(1))), + Some((_, c)) => match it.next() { + None => Ok((input.slice(input.input_len()..), c.as_char())), + Some((idx, _)) => Ok((input.slice(idx..), c.as_char())), + }, + } +} + +/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non alphabetic character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::alpha0; +/// assert_eq!(alpha0::<_, (_, ErrorKind)>("ab1c"), Ok(("1c", "ab"))); +/// assert_eq!(alpha0::<_, (_, ErrorKind)>("1c"), Ok(("1c", ""))); +/// assert_eq!(alpha0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn alpha0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_alpha()) +} + +/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non alphabetic character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::alpha1; +/// assert_eq!(alpha1::<_, (_, ErrorKind)>("aB1c"), Ok(("1c", "aB"))); +/// assert_eq!(alpha1::<_, (_, ErrorKind)>("1c"), Err(Err::Error(("1c", ErrorKind::Alpha)))); +/// assert_eq!(alpha1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn alpha1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_alpha(), ErrorKind::Alpha) +} + +/// Recognizes zero or more ASCII numerical characters: 0-9 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::digit0; +/// assert_eq!(digit0::<_, (_, ErrorKind)>("21c"), Ok(("c", "21"))); +/// assert_eq!(digit0::<_, (_, ErrorKind)>("a21c"), Ok(("a21c", ""))); +/// assert_eq!(digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_dec_digit()) +} + +/// Recognizes one or more ASCII numerical characters: 0-9 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::digit1; +/// assert_eq!(digit1::<_, (_, ErrorKind)>("21c"), Ok(("c", "21"))); +/// assert_eq!(digit1::<_, (_, ErrorKind)>("c1"), Err(Err::Error(("c1", ErrorKind::Digit)))); +/// assert_eq!(digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_dec_digit(), ErrorKind::Digit) +} + +/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non hexadecimal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::hex_digit0; +/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c"))); +/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn hex_digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_hex_digit()) +} + +/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non hexadecimal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::hex_digit1; +/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c"))); +/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::HexDigit)))); +/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn hex_digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_hex_digit(), ErrorKind::HexDigit) +} + +/// Recognizes zero or more octal characters: 0-7 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non octal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::oct_digit0; +/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21"))); +/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn oct_digit0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_oct_digit()) +} + +/// Recognizes one or more octal characters: 0-7 +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non octal digit character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::oct_digit1; +/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21"))); +/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::OctDigit)))); +/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn oct_digit1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_oct_digit(), ErrorKind::OctDigit) +} + +/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non alphanumerical character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::alphanumeric0; +/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ"))); +/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("&Z21c"), Ok(("&Z21c", ""))); +/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn alphanumeric0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position(|item| !item.is_alphanum()) +} + +/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non alphanumerical character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::alphanumeric1; +/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ"))); +/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("&H2"), Err(Err::Error(("&H2", ErrorKind::AlphaNumeric)))); +/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn alphanumeric1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar, +{ + input.split_at_position1(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric) +} + +/// Recognizes zero or more spaces and tabs. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::space0; +/// assert_eq!(space0::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t"))); +/// assert_eq!(space0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(space0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn space0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }) +} +/// Recognizes one or more spaces and tabs. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::space1; +/// assert_eq!(space1::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t"))); +/// assert_eq!(space1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::Space)))); +/// assert_eq!(space1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn space1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position1( + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }, + ErrorKind::Space, + ) +} + +/// Recognizes zero or more spaces, tabs, carriage returns and line feeds. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::multispace0; +/// assert_eq!(multispace0::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); +/// assert_eq!(multispace0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", ""))); +/// assert_eq!(multispace0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn multispace0>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position(|item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }) +} + +/// Recognizes one or more spaces, tabs, carriage returns and line feeds. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data, +/// or if no terminating token is found (a non space character). +/// # Example +/// +/// ``` +/// # use nom::{Err, error::ErrorKind, IResult, Needed}; +/// # use nom::character::streaming::multispace1; +/// assert_eq!(multispace1::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); +/// assert_eq!(multispace1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::MultiSpace)))); +/// assert_eq!(multispace1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +pub fn multispace1>(input: T) -> IResult +where + T: InputTakeAtPosition, + ::Item: AsChar + Clone, +{ + input.split_at_position1( + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }, + ErrorKind::MultiSpace, + ) +} + +pub(crate) fn sign>(input: T) -> IResult +where + T: Clone + InputTake + InputLength, + T: for<'a> Compare<&'a [u8]>, +{ + use crate::bytes::streaming::tag; + use crate::combinator::value; + + let (i, opt_sign) = opt(alt(( + value(false, tag(&b"-"[..])), + value(true, tag(&b"+"[..])), + )))(input)?; + let sign = opt_sign.unwrap_or(true); + + Ok((i, sign)) +} + +#[doc(hidden)] +macro_rules! ints { + ($($t:tt)+) => { + $( + /// will parse a number in text form to a number + /// + /// *Complete version*: can parse until the end of input. + pub fn $t>(input: T) -> IResult + where + T: InputIter + Slice> + InputLength + InputTake + Clone, + ::Item: AsChar, + T: for <'a> Compare<&'a[u8]>, + { + let (i, sign) = sign(input.clone())?; + + if i.input_len() == 0 { + return Err(Err::Incomplete(Needed::new(1))); + } + + let mut value: $t = 0; + if sign { + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + } else { + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + } + + Err(Err::Incomplete(Needed::new(1))) + } + )+ + } +} + +ints! { i8 i16 i32 i64 i128 } + +#[doc(hidden)] +macro_rules! uints { + ($($t:tt)+) => { + $( + /// will parse a number in text form to a number + /// + /// *Complete version*: can parse until the end of input. + pub fn $t>(input: T) -> IResult + where + T: InputIter + Slice> + InputLength, + ::Item: AsChar, + { + let i = input; + + if i.input_len() == 0 { + return Err(Err::Incomplete(Needed::new(1))); + } + + let mut value: $t = 0; + for (pos, c) in i.iter_indices() { + match c.as_char().to_digit(10) { + None => { + if pos == 0 { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); + } else { + return Ok((i.slice(pos..), value)); + } + }, + Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) { + None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))), + Some(v) => value = v, + } + } + } + + Err(Err::Incomplete(Needed::new(1))) + } + )+ + } +} + +uints! { u8 u16 u32 u64 u128 } + +#[cfg(test)] +mod tests { + use super::*; + use crate::error::ErrorKind; + use crate::internal::{Err, Needed}; + use crate::sequence::pair; + use crate::traits::ParseTo; + use proptest::prelude::*; + + macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; + ); + + #[test] + fn anychar_str() { + use super::anychar; + assert_eq!(anychar::<_, (&str, ErrorKind)>("Ә"), Ok(("", 'Ә'))); + } + + #[test] + fn character() { + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bytes(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::new(1)))); + assert_parse!(alpha1(a), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..]))); + assert_eq!( + alpha1::<_, (_, ErrorKind)>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); + assert_eq!( + digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); + assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(c), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(d), + Ok(("zé12".as_bytes(), &b"a"[..])) + ); + assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); + assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); + assert_eq!( + oct_digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(c), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!( + space1::<_, (_, ErrorKind)>(e), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..]))); + } + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!( + alpha1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..]))); + assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..]))); + assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); + assert_eq!( + digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); + assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, (_, ErrorKind)>(c), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..]))); + assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); + assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); + assert_eq!( + oct_digit1::<_, (_, ErrorKind)>(b), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); + assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(a), + Err(Err::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, (_, ErrorKind)>(c), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); + assert_eq!( + space1::<_, (_, ErrorKind)>(e), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + use crate::traits::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, (_, ErrorKind)>(a) { + Ok((i, _)) => { + assert_eq!(a.offset(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, (_, ErrorKind)>(b) { + Ok((i, _)) => { + assert_eq!(b.offset(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, (_, ErrorKind)>(c) { + Ok((i, _)) => { + assert_eq!(c.offset(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, (_, ErrorKind)>(d) { + Ok((i, _)) => { + assert_eq!(d.offset(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, (_, ErrorKind)>(e) { + Ok((i, _)) => { + assert_eq!(e.offset(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, (_, ErrorKind)>(f) { + Ok((i, _)) => { + assert_eq!(f.offset(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } + } + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(a), + Ok((&b"\nefgh"[..], &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(b), + Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(c), + Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(d), + Err(Err::Incomplete(Needed::Unknown)) + ); + } + + #[test] + fn is_not_line_ending_str() { + /* + let a: &str = "ab12cd\nefgh"; + assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); + + let b: &str = "ab12cd\nefgh\nijkl"; + assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let c: &str = "ab12cd\r\nefgh\nijkl"; + assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let d = "βèƒôřè\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + + let e = "βèƒôřè\r\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + */ + + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag)))); + + let g2: &str = "ab12cd"; + assert_eq!( + not_line_ending::<_, (_, ErrorKind)>(g2), + Err(Err::Incomplete(Needed::Unknown)) + ); + } + + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) + ); + + assert!(crate::character::is_hex_digit(b'0')); + assert!(crate::character::is_hex_digit(b'9')); + assert!(crate::character::is_hex_digit(b'a')); + assert!(crate::character::is_hex_digit(b'f')); + assert!(crate::character::is_hex_digit(b'A')); + assert!(crate::character::is_hex_digit(b'F')); + assert!(!crate::character::is_hex_digit(b'g')); + assert!(!crate::character::is_hex_digit(b'G')); + assert!(!crate::character::is_hex_digit(b'/')); + assert!(!crate::character::is_hex_digit(b':')); + assert!(!crate::character::is_hex_digit(b'@')); + assert!(!crate::character::is_hex_digit(b'\x60')); + } + + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(i), + Err(Err::Error(error_position!(i, ErrorKind::OctDigit))) + ); + + assert!(crate::character::is_oct_digit(b'0')); + assert!(crate::character::is_oct_digit(b'7')); + assert!(!crate::character::is_oct_digit(b'8')); + assert!(!crate::character::is_oct_digit(b'9')); + assert!(!crate::character::is_oct_digit(b'a')); + assert!(!crate::character::is_oct_digit(b'A')); + assert!(!crate::character::is_oct_digit(b'/')); + assert!(!crate::character::is_oct_digit(b':')); + assert!(!crate::character::is_oct_digit(b'@')); + assert!(!crate::character::is_oct_digit(b'\x60')); + } + + #[test] + fn full_line_windows() { + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\r\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); + } + + #[test] + fn full_line_unix() { + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); + } + + #[test] + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); + } + + #[test] + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); + } + + #[test] + fn cr_lf() { + assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!(crlf(&b"\r"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!( + crlf(&b"\ra"[..]), + Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) + ); + + assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); + assert_parse!(crlf("\r"), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!( + crlf("\ra"), + Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + #[test] + fn end_of_line() { + assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); + assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + line_ending(&b"\r"[..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_parse!( + line_ending(&b"\ra"[..]), + Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) + ); + + assert_parse!(line_ending("\na"), Ok(("a", "\n"))); + assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); + assert_parse!(line_ending("\r"), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!( + line_ending("\ra"), + Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + fn digit_to_i16(input: &str) -> IResult<&str, i16> { + let i = input; + let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let sign = match opt_sign { + Some('+') => true, + Some('-') => false, + _ => true, + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { + Ok((i, s)) => (i, s), + Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)), + Err(_) => { + return Err(Err::Error(crate::error::Error::from_error_kind( + input, + ErrorKind::Digit, + ))) + } + }; + match s.parse_to() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(Err::Error(crate::error::Error::from_error_kind( + i, + ErrorKind::Digit, + ))), + } + } + + fn digit_to_u32(i: &str) -> IResult<&str, u32> { + let (i, s) = digit1(i)?; + match s.parse_to() { + Some(n) => Ok((i, n)), + None => Err(Err::Error(crate::error::Error::from_error_kind( + i, + ErrorKind::Digit, + ))), + } + } + + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(&s); + let res2 = i16(s.as_str()); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(&s); + let res2 = u32(s.as_str()); + assert_eq!(res1, res2); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/character/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/character/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +use super::streaming::*; +use crate::error::ErrorKind; +use crate::internal::{Err, IResult}; + +#[test] +fn one_of_test() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + one_of("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!(f(a), Ok((&b"bcd"[..], 'a'))); + + let b = &b"cde"[..]; + assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf)))); + + fn utf8(i: &str) -> IResult<&str, char> { + one_of("+\u{FF0B}")(i) + } + + assert!(utf8("+").is_ok()); + assert!(utf8("\u{FF0B}").is_ok()); +} + +#[test] +fn none_of_test() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + none_of("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf)))); + + let b = &b"cde"[..]; + assert_eq!(f(b), Ok((&b"de"[..], 'c'))); +} + +#[test] +fn char_byteslice() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + char('c')(i) + } + + let a = &b"abcd"[..]; + assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char)))); + + let b = &b"cde"[..]; + assert_eq!(f(b), Ok((&b"de"[..], 'c'))); +} + +#[test] +fn char_str() { + fn f(i: &str) -> IResult<&str, char> { + char('c')(i) + } + + let a = &"abcd"[..]; + assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char)))); + + let b = &"cde"[..]; + assert_eq!(f(b), Ok((&"de"[..], 'c'))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,809 @@ +//! General purpose combinators + +#![allow(unused_imports)] + +#[cfg(feature = "alloc")] +use crate::lib::std::boxed::Box; + +use crate::error::{ErrorKind, FromExternalError, ParseError}; +use crate::internal::*; +use crate::lib::std::borrow::Borrow; +use crate::lib::std::convert::Into; +#[cfg(feature = "std")] +use crate::lib::std::fmt::Debug; +use crate::lib::std::mem::transmute; +use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; +use crate::traits::{AsChar, InputIter, InputLength, InputTakeAtPosition, ParseTo}; +use crate::traits::{Compare, CompareResult, Offset, Slice}; + +#[cfg(test)] +mod tests; + +/// Return the remaining input. +/// +/// ```rust +/// # use nom::error::ErrorKind; +/// use nom::combinator::rest; +/// assert_eq!(rest::<_,(_, ErrorKind)>("abc"), Ok(("", "abc"))); +/// assert_eq!(rest::<_,(_, ErrorKind)>(""), Ok(("", ""))); +/// ``` +#[inline] +pub fn rest>(input: T) -> IResult +where + T: Slice>, + T: InputLength, +{ + Ok((input.slice(input.input_len()..), input)) +} + +/// Return the length of the remaining input. +/// +/// ```rust +/// # use nom::error::ErrorKind; +/// use nom::combinator::rest_len; +/// assert_eq!(rest_len::<_,(_, ErrorKind)>("abc"), Ok(("abc", 3))); +/// assert_eq!(rest_len::<_,(_, ErrorKind)>(""), Ok(("", 0))); +/// ``` +#[inline] +pub fn rest_len>(input: T) -> IResult +where + T: InputLength, +{ + let len = input.input_len(); + Ok((input, len)) +} + +/// Maps a function on the result of a parser. +/// +/// ```rust +/// use nom::{Err,error::ErrorKind, IResult,Parser}; +/// use nom::character::complete::digit1; +/// use nom::combinator::map; +/// # fn main() { +/// +/// let mut parser = map(digit1, |s: &str| s.len()); +/// +/// // the parser will count how many characters were returned by digit1 +/// assert_eq!(parser.parse("123456"), Ok(("", 6))); +/// +/// // this will fail if digit1 fails +/// assert_eq!(parser.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); +/// # } +/// ``` +pub fn map(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult +where + F: Parser, + G: FnMut(O1) -> O2, +{ + move |input: I| { + let (input, o1) = parser.parse(input)?; + Ok((input, f(o1))) + } +} + +/// Applies a function returning a `Result` over the result of a parser. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::character::complete::digit1; +/// use nom::combinator::map_res; +/// # fn main() { +/// +/// let mut parse = map_res(digit1, |s: &str| s.parse::()); +/// +/// // the parser will convert the result of digit1 to a number +/// assert_eq!(parse("123"), Ok(("", 123))); +/// +/// // this will fail if digit1 fails +/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); +/// +/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) +/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes)))); +/// # } +/// ``` +pub fn map_res, E2, F, G>( + mut parser: F, + mut f: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: FnMut(O1) -> Result, +{ + move |input: I| { + let i = input.clone(); + let (input, o1) = parser.parse(input)?; + match f(o1) { + Ok(o2) => Ok((input, o2)), + Err(e) => Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, e))), + } + } +} + +/// Applies a function returning an `Option` over the result of a parser. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::character::complete::digit1; +/// use nom::combinator::map_opt; +/// # fn main() { +/// +/// let mut parse = map_opt(digit1, |s: &str| s.parse::().ok()); +/// +/// // the parser will convert the result of digit1 to a number +/// assert_eq!(parse("123"), Ok(("", 123))); +/// +/// // this will fail if digit1 fails +/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit)))); +/// +/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) +/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt)))); +/// # } +/// ``` +pub fn map_opt, F, G>( + mut parser: F, + mut f: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: FnMut(O1) -> Option, +{ + move |input: I| { + let i = input.clone(); + let (input, o1) = parser.parse(input)?; + match f(o1) { + Some(o2) => Ok((input, o2)), + None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))), + } + } +} + +/// Applies a parser over the result of another one. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::character::complete::digit1; +/// use nom::bytes::complete::take; +/// use nom::combinator::map_parser; +/// # fn main() { +/// +/// let mut parse = map_parser(take(5u8), digit1); +/// +/// assert_eq!(parse("12345"), Ok(("", "12345"))); +/// assert_eq!(parse("123ab"), Ok(("", "123"))); +/// assert_eq!(parse("123"), Err(Err::Error(("123", ErrorKind::Eof)))); +/// # } +/// ``` +pub fn map_parser, F, G>( + mut parser: F, + mut applied_parser: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, +{ + move |input: I| { + let (input, o1) = parser.parse(input)?; + let (_, o2) = applied_parser.parse(o1)?; + Ok((input, o2)) + } +} + +/// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::bytes::complete::take; +/// use nom::number::complete::u8; +/// use nom::combinator::flat_map; +/// # fn main() { +/// +/// let mut parse = flat_map(u8, take); +/// +/// assert_eq!(parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..]))); +/// assert_eq!(parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof)))); +/// # } +/// ``` +pub fn flat_map, F, G, H>( + mut parser: F, + mut applied_parser: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: FnMut(O1) -> H, + H: Parser, +{ + move |input: I| { + let (input, o1) = parser.parse(input)?; + applied_parser(o1).parse(input) + } +} + +/// Optional parser, will return `None` on [`Err::Error`]. +/// +/// To chain an error up, see [`cut`]. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::opt; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// fn parser(i: &str) -> IResult<&str, Option<&str>> { +/// opt(alpha1)(i) +/// } +/// +/// assert_eq!(parser("abcd;"), Ok((";", Some("abcd")))); +/// assert_eq!(parser("123;"), Ok(("123;", None))); +/// # } +/// ``` +pub fn opt, F>(mut f: F) -> impl FnMut(I) -> IResult, E> +where + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match f.parse(input) { + Ok((i, o)) => Ok((i, Some(o))), + Err(Err::Error(_)) => Ok((i, None)), + Err(e) => Err(e), + } + } +} + +/// Calls the parser if the condition is met. +/// +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; +/// use nom::combinator::cond; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> { +/// cond(b, alpha1)(i) +/// } +/// +/// assert_eq!(parser(true, "abcd;"), Ok((";", Some("abcd")))); +/// assert_eq!(parser(false, "abcd;"), Ok(("abcd;", None))); +/// assert_eq!(parser(true, "123;"), Err(Err::Error(Error::new("123;", ErrorKind::Alpha)))); +/// assert_eq!(parser(false, "123;"), Ok(("123;", None))); +/// # } +/// ``` +pub fn cond, F>( + b: bool, + mut f: F, +) -> impl FnMut(I) -> IResult, E> +where + F: Parser, +{ + move |input: I| { + if b { + match f.parse(input) { + Ok((i, o)) => Ok((i, Some(o))), + Err(e) => Err(e), + } + } else { + Ok((input, None)) + } + } +} + +/// Tries to apply its parser without consuming the input. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::peek; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// let mut parser = peek(alpha1); +/// +/// assert_eq!(parser("abcd;"), Ok(("abcd;", "abcd"))); +/// assert_eq!(parser("123;"), Err(Err::Error(("123;", ErrorKind::Alpha)))); +/// # } +/// ``` +pub fn peek, F>(mut f: F) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match f.parse(input) { + Ok((_, o)) => Ok((i, o)), + Err(e) => Err(e), + } + } +} + +/// returns its input if it is at the end of input data +/// +/// When we're at the end of the data, this combinator +/// will succeed +/// +/// ``` +/// # use std::str; +/// # use nom::{Err, error::ErrorKind, IResult}; +/// # use nom::combinator::eof; +/// +/// # fn main() { +/// let parser = eof; +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Eof)))); +/// assert_eq!(parser(""), Ok(("", ""))); +/// # } +/// ``` +pub fn eof>(input: I) -> IResult { + if input.input_len() == 0 { + let clone = input.clone(); + Ok((input, clone)) + } else { + Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))) + } +} + +/// Transforms Incomplete into `Error`. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::bytes::streaming::take; +/// use nom::combinator::complete; +/// # fn main() { +/// +/// let mut parser = complete(take(5u8)); +/// +/// assert_eq!(parser("abcdefg"), Ok(("fg", "abcde"))); +/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Complete)))); +/// # } +/// ``` +pub fn complete, F>(mut f: F) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match f.parse(input) { + Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))), + rest => rest, + } + } +} + +/// Succeeds if all the input has been consumed by its child parser. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::all_consuming; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// let mut parser = all_consuming(alpha1); +/// +/// assert_eq!(parser("abcd"), Ok(("", "abcd"))); +/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Eof)))); +/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// # } +/// ``` +pub fn all_consuming, F>(mut f: F) -> impl FnMut(I) -> IResult +where + I: InputLength, + F: Parser, +{ + move |input: I| { + let (input, res) = f.parse(input)?; + if input.input_len() == 0 { + Ok((input, res)) + } else { + Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))) + } + } +} + +/// Returns the result of the child parser if it satisfies a verification function. +/// +/// The verification function takes as argument a reference to the output of the +/// parser. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::verify; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// let mut parser = verify(alpha1, |s: &str| s.len() == 4); +/// +/// assert_eq!(parser("abcd"), Ok(("", "abcd"))); +/// assert_eq!(parser("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify)))); +/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// # } +/// ``` +pub fn verify, F, G>( + mut first: F, + second: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Fn(&O2) -> bool, + O1: Borrow, + O2: ?Sized, +{ + move |input: I| { + let i = input.clone(); + let (input, o) = first.parse(input)?; + + if second(o.borrow()) { + Ok((input, o)) + } else { + Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify))) + } + } +} + +/// Returns the provided value if the child parser succeeds. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::value; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// let mut parser = value(1234, alpha1); +/// +/// assert_eq!(parser("abcd"), Ok(("", 1234))); +/// assert_eq!(parser("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha)))); +/// # } +/// ``` +pub fn value, F>( + val: O1, + mut parser: F, +) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| parser.parse(input).map(|(i, _)| (i, val.clone())) +} + +/// Succeeds if the child parser returns an error. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::not; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// let mut parser = not(alpha1); +/// +/// assert_eq!(parser("123"), Ok(("123", ()))); +/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Not)))); +/// # } +/// ``` +pub fn not, F>(mut parser: F) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match parser.parse(input) { + Ok(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Not))), + Err(Err::Error(_)) => Ok((i, ())), + Err(e) => Err(e), + } + } +} + +/// If the child parser was successful, return the consumed input as produced value. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::recognize; +/// use nom::character::complete::{char, alpha1}; +/// use nom::sequence::separated_pair; +/// # fn main() { +/// +/// let mut parser = recognize(separated_pair(alpha1, char(','), alpha1)); +/// +/// assert_eq!(parser("abcd,efgh"), Ok(("", "abcd,efgh"))); +/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); +/// # } +/// ``` +pub fn recognize>, O, E: ParseError, F>( + mut parser: F, +) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match parser.parse(i) { + Ok((i, _)) => { + let index = input.offset(&i); + Ok((i, input.slice(..index))) + } + Err(e) => Err(e), + } + } +} + +/// if the child parser was successful, return the consumed input with the output +/// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it +/// returns the parser output as well. +/// +/// This can be useful especially in cases where the output is not the same type +/// as the input, or the input is a user defined type. +/// +/// Returned tuple is of the format `(consumed input, produced output)`. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::combinator::{consumed, value, recognize, map}; +/// use nom::character::complete::{char, alpha1}; +/// use nom::bytes::complete::tag; +/// use nom::sequence::separated_pair; +/// +/// fn inner_parser(input: &str) -> IResult<&str, bool> { +/// value(true, tag("1234"))(input) +/// } +/// +/// # fn main() { +/// +/// let mut consumed_parser = consumed(value(true, separated_pair(alpha1, char(','), alpha1))); +/// +/// assert_eq!(consumed_parser("abcd,efgh1"), Ok(("1", ("abcd,efgh", true)))); +/// assert_eq!(consumed_parser("abcd;"),Err(Err::Error((";", ErrorKind::Char)))); +/// +/// +/// // the first output (representing the consumed input) +/// // should be the same as that of the `recognize` parser. +/// let mut recognize_parser = recognize(inner_parser); +/// let mut consumed_parser = map(consumed(inner_parser), |(consumed, output)| consumed); +/// +/// assert_eq!(recognize_parser("1234"), consumed_parser("1234")); +/// assert_eq!(recognize_parser("abcd"), consumed_parser("abcd")); +/// # } +/// ``` +pub fn consumed(mut parser: F) -> impl FnMut(I) -> IResult +where + I: Clone + Offset + Slice>, + E: ParseError, + F: Parser, +{ + move |input: I| { + let i = input.clone(); + match parser.parse(i) { + Ok((remaining, result)) => { + let index = input.offset(&remaining); + let consumed = input.slice(..index); + Ok((remaining, (consumed, result))) + } + Err(e) => Err(e), + } + } +} + +/// Transforms an [`Err::Error`] (recoverable) to [`Err::Failure`] (unrecoverable) +/// +/// This commits the parse result, preventing alternative branch paths like with +/// [`nom::branch::alt`][crate::branch::alt]. +/// +/// # Example +/// +/// Without `cut`: +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// # use nom::character::complete::{one_of, digit1}; +/// # use nom::combinator::rest; +/// # use nom::branch::alt; +/// # use nom::sequence::preceded; +/// # fn main() { +/// +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of("+-"), digit1), +/// rest +/// ))(input) +/// } +/// +/// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); +/// assert_eq!(parser("ab"), Ok(("", "ab"))); +/// assert_eq!(parser("+"), Ok(("", "+"))); +/// # } +/// ``` +/// +/// With `cut`: +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult, error::Error}; +/// # use nom::character::complete::{one_of, digit1}; +/// # use nom::combinator::rest; +/// # use nom::branch::alt; +/// # use nom::sequence::preceded; +/// use nom::combinator::cut; +/// # fn main() { +/// +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of("+-"), cut(digit1)), +/// rest +/// ))(input) +/// } +/// +/// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); +/// assert_eq!(parser("ab"), Ok(("", "ab"))); +/// assert_eq!(parser("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit }))); +/// # } +/// ``` +pub fn cut, F>(mut parser: F) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |input: I| match parser.parse(input) { + Err(Err::Error(e)) => Err(Err::Failure(e)), + rest => rest, + } +} + +/// automatically converts the child parser's result to another type +/// +/// it will be able to convert the output value and the error value +/// as long as the `Into` implementations are available +/// +/// ```rust +/// # use nom::IResult; +/// use nom::combinator::into; +/// use nom::character::complete::alpha1; +/// # fn main() { +/// +/// fn parser1(i: &str) -> IResult<&str, &str> { +/// alpha1(i) +/// } +/// +/// let mut parser2 = into(parser1); +/// +/// // the parser converts the &str output of the child parser into a Vec +/// let bytes: IResult<&str, Vec> = parser2("abcd"); +/// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100]))); +/// # } +/// ``` +pub fn into(mut parser: F) -> impl FnMut(I) -> IResult +where + O1: Into, + E1: Into, + E1: ParseError, + E2: ParseError, + F: Parser, +{ + //map(parser, Into::into) + move |input: I| match parser.parse(input) { + Ok((i, o)) => Ok((i, o.into())), + Err(Err::Error(e)) => Err(Err::Error(e.into())), + Err(Err::Failure(e)) => Err(Err::Failure(e.into())), + Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)), + } +} + +/// Creates an iterator from input data and a parser. +/// +/// Call the iterator's [ParserIterator::finish] method to get the remaining input if successful, +/// or the error value if we encountered an error. +/// +/// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`]. +/// +/// ```rust +/// use nom::{combinator::iterator, IResult, bytes::complete::tag, character::complete::alpha1, sequence::terminated}; +/// use std::collections::HashMap; +/// +/// let data = "abc|defg|hijkl|mnopqr|123"; +/// let mut it = iterator(data, terminated(alpha1, tag("|"))); +/// +/// let parsed = it.map(|v| (v, v.len())).collect::>(); +/// let res: IResult<_,_> = it.finish(); +/// +/// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect()); +/// assert_eq!(res, Ok(("123", ()))); +/// ``` +pub fn iterator(input: Input, f: F) -> ParserIterator +where + F: Parser, + Error: ParseError, +{ + ParserIterator { + iterator: f, + input, + state: Some(State::Running), + } +} + +/// Main structure associated to the [iterator] function. +pub struct ParserIterator { + iterator: F, + input: I, + state: Option>, +} + +impl ParserIterator { + /// Returns the remaining input if parsing was successful, or the error if we encountered an error. + pub fn finish(mut self) -> IResult { + match self.state.take().unwrap() { + State::Running | State::Done => Ok((self.input, ())), + State::Failure(e) => Err(Err::Failure(e)), + State::Incomplete(i) => Err(Err::Incomplete(i)), + } + } +} + +impl<'a, Input, Output, Error, F> core::iter::Iterator for &'a mut ParserIterator +where + F: FnMut(Input) -> IResult, + Input: Clone, +{ + type Item = Output; + + fn next(&mut self) -> Option { + if let State::Running = self.state.take().unwrap() { + let input = self.input.clone(); + + match (self.iterator)(input) { + Ok((i, o)) => { + self.input = i; + self.state = Some(State::Running); + Some(o) + } + Err(Err::Error(_)) => { + self.state = Some(State::Done); + None + } + Err(Err::Failure(e)) => { + self.state = Some(State::Failure(e)); + None + } + Err(Err::Incomplete(i)) => { + self.state = Some(State::Incomplete(i)); + None + } + } + } else { + None + } + } +} + +enum State { + Running, + Done, + Failure(E), + Incomplete(Needed), +} + +/// a parser which always succeeds with given value without consuming any input. +/// +/// It can be used for example as the last alternative in `alt` to +/// specify the default case. +/// +/// ```rust +/// # use nom::{Err,error::ErrorKind, IResult}; +/// use nom::branch::alt; +/// use nom::combinator::{success, value}; +/// use nom::character::complete::char; +/// # fn main() { +/// +/// let mut parser = success::<_,_,(_,ErrorKind)>(10); +/// assert_eq!(parser("xyz"), Ok(("xyz", 10))); +/// +/// let mut sign = alt((value(-1, char('-')), value(1, char('+')), success::<_,_,(_,ErrorKind)>(1))); +/// assert_eq!(sign("+10"), Ok(("10", 1))); +/// assert_eq!(sign("-10"), Ok(("10", -1))); +/// assert_eq!(sign("10"), Ok(("10", 1))); +/// # } +/// ``` +pub fn success>(val: O) -> impl Fn(I) -> IResult { + move |input: I| Ok((input, val.clone())) +} + +/// A parser which always fails. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, IResult}; +/// use nom::combinator::fail; +/// +/// let s = "string"; +/// assert_eq!(fail::<_, &str, _>(s), Err(Err::Error((s, ErrorKind::Fail)))); +/// ``` +pub fn fail>(i: I) -> IResult { + Err(Err::Error(E::from_error_kind(i, ErrorKind::Fail))) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/combinator/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,275 @@ +use super::*; +use crate::bytes::complete::take; +use crate::bytes::streaming::tag; +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Needed}; +#[cfg(feature = "alloc")] +use crate::lib::std::boxed::Box; +use crate::number::complete::u8; + +macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; +); + +/*#[test] +fn t1() { + let v1:Vec = vec![1,2,3]; + let v2:Vec = vec![4,5,6]; + let d = Ok((&v1[..], &v2[..])); + let res = d.flat_map(print); + assert_eq!(res, Ok((&v2[..], ()))); +}*/ + +#[test] +fn eof_on_slices() { + let not_over: &[u8] = &b"Hello, world!"[..]; + let is_over: &[u8] = &b""[..]; + + let res_not_over = eof(not_over); + assert_parse!( + res_not_over, + Err(Err::Error(error_position!(not_over, ErrorKind::Eof))) + ); + + let res_over = eof(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); +} + +#[test] +fn eof_on_strs() { + let not_over: &str = "Hello, world!"; + let is_over: &str = ""; + + let res_not_over = eof(not_over); + assert_parse!( + res_not_over, + Err(Err::Error(error_position!(not_over, ErrorKind::Eof))) + ); + + let res_over = eof(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); +} + +/* +#[test] +fn end_of_input() { + let not_over = &b"Hello, world!"[..]; + let is_over = &b""[..]; + named!(eof_test, eof!()); + + let res_not_over = eof_test(not_over); + assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof)))); + + let res_over = eof_test(is_over); + assert_eq!(res_over, Ok((is_over, is_over))); +} +*/ + +#[test] +fn rest_on_slices() { + let input: &[u8] = &b"Hello, world!"[..]; + let empty: &[u8] = &b""[..]; + assert_parse!(rest(input), Ok((empty, input))); +} + +#[test] +fn rest_on_strs() { + let input: &str = "Hello, world!"; + let empty: &str = ""; + assert_parse!(rest(input), Ok((empty, input))); +} + +#[test] +fn rest_len_on_slices() { + let input: &[u8] = &b"Hello, world!"[..]; + assert_parse!(rest_len(input), Ok((input, input.len()))); +} + +use crate::lib::std::convert::From; +impl From for CustomError { + fn from(_: u32) -> Self { + CustomError + } +} + +impl ParseError for CustomError { + fn from_error_kind(_: I, _: ErrorKind) -> Self { + CustomError + } + + fn append(_: I, _: ErrorKind, _: CustomError) -> Self { + CustomError + } +} + +struct CustomError; +#[allow(dead_code)] +fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> { + //fix_error!(input, CustomError, alphanumeric) + crate::character::streaming::alphanumeric1(input) +} + +#[test] +fn test_flat_map() { + let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; + assert_parse!( + flat_map(u8, take)(input), + Ok((&[103, 104][..], &[100, 101, 102][..])) + ); +} + +#[test] +fn test_map_opt() { + let input: &[u8] = &[50][..]; + assert_parse!( + map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input), + Err(Err::Error((&[50][..], ErrorKind::MapOpt))) + ); + assert_parse!( + map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input), + Ok((&[][..], 50)) + ); +} + +#[test] +fn test_map_parser() { + let input: &[u8] = &[100, 101, 102, 103, 104][..]; + assert_parse!( + map_parser(take(4usize), take(2usize))(input), + Ok((&[104][..], &[100, 101][..])) + ); +} + +#[test] +fn test_all_consuming() { + let input: &[u8] = &[100, 101, 102][..]; + assert_parse!( + all_consuming(take(2usize))(input), + Err(Err::Error((&[102][..], ErrorKind::Eof))) + ); + assert_parse!( + all_consuming(take(3usize))(input), + Ok((&[][..], &[100, 101, 102][..])) + ); +} + +#[test] +#[allow(unused)] +fn test_verify_ref() { + use crate::bytes::complete::take; + + let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]); + + assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..]))); + assert_eq!( + parser1(&b"defg"[..]), + Err(Err::Error((&b"defg"[..], ErrorKind::Verify))) + ); + + fn parser2(i: &[u8]) -> IResult<&[u8], u32> { + verify(crate::number::streaming::be_u32, |val: &u32| *val < 3)(i) + } +} + +#[test] +#[cfg(feature = "alloc")] +fn test_verify_alloc() { + use crate::bytes::complete::take; + let mut parser1 = verify(map(take(3u8), |s: &[u8]| s.to_vec()), |s: &[u8]| { + s == &b"abc"[..] + }); + + assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], (&b"abc").to_vec()))); + assert_eq!( + parser1(&b"defg"[..]), + Err(Err::Error((&b"defg"[..], ErrorKind::Verify))) + ); +} + +#[test] +#[cfg(feature = "std")] +fn test_into() { + use crate::bytes::complete::take; + use crate::{ + error::{Error, ParseError}, + Err, + }; + + let mut parser = into(take::<_, _, Error<_>>(3u8)); + let result: IResult<&[u8], Vec> = parser(&b"abcdefg"[..]); + + assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); +} + +#[test] +fn opt_test() { + fn opt_abcd(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> { + opt(tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"bcdefg"[..]; + let c = &b"ab"[..]; + assert_eq!(opt_abcd(a), Ok((&b"ef"[..], Some(&b"abcd"[..])))); + assert_eq!(opt_abcd(b), Ok((&b"bcdefg"[..], None))); + assert_eq!(opt_abcd(c), Err(Err::Incomplete(Needed::new(2)))); +} + +#[test] +fn peek_test() { + fn peek_tag(i: &[u8]) -> IResult<&[u8], &[u8]> { + peek(tag("abcd"))(i) + } + + assert_eq!(peek_tag(&b"abcdef"[..]), Ok((&b"abcdef"[..], &b"abcd"[..]))); + assert_eq!(peek_tag(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + peek_tag(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn not_test() { + fn not_aaa(i: &[u8]) -> IResult<&[u8], ()> { + not(tag("aaa"))(i) + } + + assert_eq!( + not_aaa(&b"aaa"[..]), + Err(Err::Error(error_position!(&b"aaa"[..], ErrorKind::Not))) + ); + assert_eq!(not_aaa(&b"aa"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(not_aaa(&b"abcd"[..]), Ok((&b"abcd"[..], ()))); +} + +#[test] +fn verify_test() { + use crate::bytes::streaming::take; + + fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { + verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i) + } + assert_eq!(test(&b"bcd"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + test(&b"bcdefg"[..]), + Err(Err::Error(error_position!( + &b"bcdefg"[..], + ErrorKind::Verify + ))) + ); + assert_eq!(test(&b"abcdefg"[..]), Ok((&b"fg"[..], &b"abcde"[..]))); +} + +#[test] +fn fail_test() { + let a = "string"; + let b = "another string"; + + assert_eq!(fail::<_, &str, _>(a), Err(Err::Error((a, ErrorKind::Fail)))); + assert_eq!(fail::<_, &str, _>(b), Err(Err::Error((b, ErrorKind::Fail)))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,831 @@ +//! Error management +//! +//! Parsers are generic over their error type, requiring that it implements +//! the `error::ParseError` trait. + +use crate::internal::Parser; +use crate::lib::std::fmt; + +/// This trait must be implemented by the error type of a nom parser. +/// +/// There are already implementations of it for `(Input, ErrorKind)` +/// and `VerboseError`. +/// +/// It provides methods to create an error from some combinators, +/// and combine existing errors in combinators like `alt`. +pub trait ParseError: Sized { + /// Creates an error from the input position and an [ErrorKind] + fn from_error_kind(input: I, kind: ErrorKind) -> Self; + + /// Combines an existing error with a new one created from the input + /// position and an [ErrorKind]. This is useful when backtracking + /// through a parse tree, accumulating error context on the way + fn append(input: I, kind: ErrorKind, other: Self) -> Self; + + /// Creates an error from an input position and an expected character + fn from_char(input: I, _: char) -> Self { + Self::from_error_kind(input, ErrorKind::Char) + } + + /// Combines two existing errors. This function is used to compare errors + /// generated in various branches of `alt`. + fn or(self, other: Self) -> Self { + other + } +} + +/// This trait is required by the `context` combinator to add a static string +/// to an existing error +pub trait ContextError: Sized { + /// Creates a new error from an input position, a static string and an existing error. + /// This is used mainly in the [context] combinator, to add user friendly information + /// to errors when backtracking through a parse tree + fn add_context(_input: I, _ctx: &'static str, other: Self) -> Self { + other + } +} + +/// This trait is required by the `map_res` combinator to integrate +/// error types from external functions, like [std::str::FromStr] +pub trait FromExternalError { + /// Creates a new error from an input position, an [ErrorKind] indicating the + /// wrapping parser, and an external error + fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self; +} + +/// default error type, only contains the error' location and code +#[derive(Debug, PartialEq)] +pub struct Error { + /// position of the error in the input data + pub input: I, + /// nom error code + pub code: ErrorKind, +} + +impl Error { + /// creates a new basic error + pub fn new(input: I, code: ErrorKind) -> Error { + Error { input, code } + } +} + +impl ParseError for Error { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + Error { input, code: kind } + } + + fn append(_: I, _: ErrorKind, other: Self) -> Self { + other + } +} + +impl ContextError for Error {} + +impl FromExternalError for Error { + /// Create a new error from an input position and an external error + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + Error { input, code: kind } + } +} + +/// The Display implementation allows the std::error::Error implementation +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "error {:?} at: {}", self.code, self.input) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +// for backward compatibility, keep those trait implementations +// for the previously used error type +impl ParseError for (I, ErrorKind) { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + (input, kind) + } + + fn append(_: I, _: ErrorKind, other: Self) -> Self { + other + } +} + +impl ContextError for (I, ErrorKind) {} + +impl FromExternalError for (I, ErrorKind) { + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + (input, kind) + } +} + +impl ParseError for () { + fn from_error_kind(_: I, _: ErrorKind) -> Self {} + + fn append(_: I, _: ErrorKind, _: Self) -> Self {} +} + +impl ContextError for () {} + +impl FromExternalError for () { + fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {} +} + +/// Creates an error from the input position and an [ErrorKind] +pub fn make_error>(input: I, kind: ErrorKind) -> E { + E::from_error_kind(input, kind) +} + +/// Combines an existing error with a new one created from the input +/// position and an [ErrorKind]. This is useful when backtracking +/// through a parse tree, accumulating error context on the way +pub fn append_error>(input: I, kind: ErrorKind, other: E) -> E { + E::append(input, kind, other) +} + +/// This error type accumulates errors and their position when backtracking +/// through a parse tree. With some post processing (cf `examples/json.rs`), +/// it can be used to display user friendly error messages +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +#[derive(Clone, Debug, PartialEq)] +pub struct VerboseError { + /// List of errors accumulated by `VerboseError`, containing the affected + /// part of input data, and some context + pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>, +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +#[derive(Clone, Debug, PartialEq)] +/// Error context for `VerboseError` +pub enum VerboseErrorKind { + /// Static string added by the `context` function + Context(&'static str), + /// Indicates which character was expected by the `char` function + Char(char), + /// Error kind given by various nom parsers + Nom(ErrorKind), +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl ParseError for VerboseError { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + VerboseError { + errors: vec![(input, VerboseErrorKind::Nom(kind))], + } + } + + fn append(input: I, kind: ErrorKind, mut other: Self) -> Self { + other.errors.push((input, VerboseErrorKind::Nom(kind))); + other + } + + fn from_char(input: I, c: char) -> Self { + VerboseError { + errors: vec![(input, VerboseErrorKind::Char(c))], + } + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl ContextError for VerboseError { + fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self { + other.errors.push((input, VerboseErrorKind::Context(ctx))); + other + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl FromExternalError for VerboseError { + /// Create a new error from an input position and an external error + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + Self::from_error_kind(input, kind) + } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for VerboseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "Parse error:")?; + for (input, error) in &self.errors { + match error { + VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?, + VerboseErrorKind::Char(c) => writeln!(f, "expected '{}' at: {}", c, input)?, + VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?, + } + } + + Ok(()) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for VerboseError {} + +use crate::internal::{Err, IResult}; + +/// Create a new error from an input position, a static string and an existing error. +/// This is used mainly in the [context] combinator, to add user friendly information +/// to errors when backtracking through a parse tree +pub fn context, F, O>( + context: &'static str, + mut f: F, +) -> impl FnMut(I) -> IResult +where + F: Parser, +{ + move |i: I| match f.parse(i.clone()) { + Ok(o) => Ok(o), + Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)), + Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))), + Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))), + } +} + +/// Transforms a `VerboseError` into a trace with input position information +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn convert_error>( + input: I, + e: VerboseError, +) -> crate::lib::std::string::String { + use crate::lib::std::fmt::Write; + use crate::traits::Offset; + + let mut result = crate::lib::std::string::String::new(); + + for (i, (substring, kind)) in e.errors.iter().enumerate() { + let offset = input.offset(substring); + + if input.is_empty() { + match kind { + VerboseErrorKind::Char(c) => { + write!(&mut result, "{}: expected '{}', got empty input\n\n", i, c) + } + VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s), + VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e), + } + } else { + let prefix = &input.as_bytes()[..offset]; + + // Count the number of newlines in the first `offset` bytes of input + let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1; + + // Find the line that includes the subslice: + // Find the *last* newline before the substring starts + let line_begin = prefix + .iter() + .rev() + .position(|&b| b == b'\n') + .map(|pos| offset - pos) + .unwrap_or(0); + + // Find the full line after that newline + let line = input[line_begin..] + .lines() + .next() + .unwrap_or(&input[line_begin..]) + .trim_end(); + + // The (1-indexed) column number is the offset of our substring into that line + let column_number = line.offset(substring) + 1; + + match kind { + VerboseErrorKind::Char(c) => { + if let Some(actual) = substring.chars().next() { + write!( + &mut result, + "{i}: at line {line_number}:\n\ + {line}\n\ + {caret:>column$}\n\ + expected '{expected}', found {actual}\n\n", + i = i, + line_number = line_number, + line = line, + caret = '^', + column = column_number, + expected = c, + actual = actual, + ) + } else { + write!( + &mut result, + "{i}: at line {line_number}:\n\ + {line}\n\ + {caret:>column$}\n\ + expected '{expected}', got end of input\n\n", + i = i, + line_number = line_number, + line = line, + caret = '^', + column = column_number, + expected = c, + ) + } + } + VerboseErrorKind::Context(s) => write!( + &mut result, + "{i}: at line {line_number}, in {context}:\n\ + {line}\n\ + {caret:>column$}\n\n", + i = i, + line_number = line_number, + context = s, + line = line, + caret = '^', + column = column_number, + ), + VerboseErrorKind::Nom(e) => write!( + &mut result, + "{i}: at line {line_number}, in {nom_err:?}:\n\ + {line}\n\ + {caret:>column$}\n\n", + i = i, + line_number = line_number, + nom_err = e, + line = line, + caret = '^', + column = column_number, + ), + } + } + // Because `write!` to a `String` is infallible, this `unwrap` is fine. + .unwrap(); + } + + result +} + +/// Indicates which parser returned an error +#[rustfmt::skip] +#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)] +#[allow(deprecated,missing_docs)] +pub enum ErrorKind { + Tag, + MapRes, + MapOpt, + Alt, + IsNot, + IsA, + SeparatedList, + SeparatedNonEmptyList, + Many0, + Many1, + ManyTill, + Count, + TakeUntil, + LengthValue, + TagClosure, + Alpha, + Digit, + HexDigit, + OctDigit, + AlphaNumeric, + Space, + MultiSpace, + LengthValueFn, + Eof, + Switch, + TagBits, + OneOf, + NoneOf, + Char, + CrLf, + RegexpMatch, + RegexpMatches, + RegexpFind, + RegexpCapture, + RegexpCaptures, + TakeWhile1, + Complete, + Fix, + Escaped, + EscapedTransform, + NonEmpty, + ManyMN, + Not, + Permutation, + Verify, + TakeTill1, + TakeWhileMN, + TooLarge, + Many0Count, + Many1Count, + Float, + Satisfy, + Fail, +} + +#[rustfmt::skip] +#[allow(deprecated)] +/// Converts an ErrorKind to a number +pub fn error_to_u32(e: &ErrorKind) -> u32 { + match *e { + ErrorKind::Tag => 1, + ErrorKind::MapRes => 2, + ErrorKind::MapOpt => 3, + ErrorKind::Alt => 4, + ErrorKind::IsNot => 5, + ErrorKind::IsA => 6, + ErrorKind::SeparatedList => 7, + ErrorKind::SeparatedNonEmptyList => 8, + ErrorKind::Many1 => 9, + ErrorKind::Count => 10, + ErrorKind::TakeUntil => 12, + ErrorKind::LengthValue => 15, + ErrorKind::TagClosure => 16, + ErrorKind::Alpha => 17, + ErrorKind::Digit => 18, + ErrorKind::AlphaNumeric => 19, + ErrorKind::Space => 20, + ErrorKind::MultiSpace => 21, + ErrorKind::LengthValueFn => 22, + ErrorKind::Eof => 23, + ErrorKind::Switch => 27, + ErrorKind::TagBits => 28, + ErrorKind::OneOf => 29, + ErrorKind::NoneOf => 30, + ErrorKind::Char => 40, + ErrorKind::CrLf => 41, + ErrorKind::RegexpMatch => 42, + ErrorKind::RegexpMatches => 43, + ErrorKind::RegexpFind => 44, + ErrorKind::RegexpCapture => 45, + ErrorKind::RegexpCaptures => 46, + ErrorKind::TakeWhile1 => 47, + ErrorKind::Complete => 48, + ErrorKind::Fix => 49, + ErrorKind::Escaped => 50, + ErrorKind::EscapedTransform => 51, + ErrorKind::NonEmpty => 56, + ErrorKind::ManyMN => 57, + ErrorKind::HexDigit => 59, + ErrorKind::OctDigit => 61, + ErrorKind::Many0 => 62, + ErrorKind::Not => 63, + ErrorKind::Permutation => 64, + ErrorKind::ManyTill => 65, + ErrorKind::Verify => 66, + ErrorKind::TakeTill1 => 67, + ErrorKind::TakeWhileMN => 69, + ErrorKind::TooLarge => 70, + ErrorKind::Many0Count => 71, + ErrorKind::Many1Count => 72, + ErrorKind::Float => 73, + ErrorKind::Satisfy => 74, + ErrorKind::Fail => 75, + } +} + +impl ErrorKind { + #[rustfmt::skip] + #[allow(deprecated)] + /// Converts an ErrorKind to a text description + pub fn description(&self) -> &str { + match *self { + ErrorKind::Tag => "Tag", + ErrorKind::MapRes => "Map on Result", + ErrorKind::MapOpt => "Map on Option", + ErrorKind::Alt => "Alternative", + ErrorKind::IsNot => "IsNot", + ErrorKind::IsA => "IsA", + ErrorKind::SeparatedList => "Separated list", + ErrorKind::SeparatedNonEmptyList => "Separated non empty list", + ErrorKind::Many0 => "Many0", + ErrorKind::Many1 => "Many1", + ErrorKind::Count => "Count", + ErrorKind::TakeUntil => "Take until", + ErrorKind::LengthValue => "Length followed by value", + ErrorKind::TagClosure => "Tag closure", + ErrorKind::Alpha => "Alphabetic", + ErrorKind::Digit => "Digit", + ErrorKind::AlphaNumeric => "AlphaNumeric", + ErrorKind::Space => "Space", + ErrorKind::MultiSpace => "Multiple spaces", + ErrorKind::LengthValueFn => "LengthValueFn", + ErrorKind::Eof => "End of file", + ErrorKind::Switch => "Switch", + ErrorKind::TagBits => "Tag on bitstream", + ErrorKind::OneOf => "OneOf", + ErrorKind::NoneOf => "NoneOf", + ErrorKind::Char => "Char", + ErrorKind::CrLf => "CrLf", + ErrorKind::RegexpMatch => "RegexpMatch", + ErrorKind::RegexpMatches => "RegexpMatches", + ErrorKind::RegexpFind => "RegexpFind", + ErrorKind::RegexpCapture => "RegexpCapture", + ErrorKind::RegexpCaptures => "RegexpCaptures", + ErrorKind::TakeWhile1 => "TakeWhile1", + ErrorKind::Complete => "Complete", + ErrorKind::Fix => "Fix", + ErrorKind::Escaped => "Escaped", + ErrorKind::EscapedTransform => "EscapedTransform", + ErrorKind::NonEmpty => "NonEmpty", + ErrorKind::ManyMN => "Many(m, n)", + ErrorKind::HexDigit => "Hexadecimal Digit", + ErrorKind::OctDigit => "Octal digit", + ErrorKind::Not => "Negation", + ErrorKind::Permutation => "Permutation", + ErrorKind::ManyTill => "ManyTill", + ErrorKind::Verify => "predicate verification", + ErrorKind::TakeTill1 => "TakeTill1", + ErrorKind::TakeWhileMN => "TakeWhileMN", + ErrorKind::TooLarge => "Needed data size is too large", + ErrorKind::Many0Count => "Count occurrence of >=0 patterns", + ErrorKind::Many1Count => "Count occurrence of >=1 patterns", + ErrorKind::Float => "Float", + ErrorKind::Satisfy => "Satisfy", + ErrorKind::Fail => "Fail", + } + } +} + +/// Creates a parse error from a `nom::ErrorKind` +/// and the position in the input +#[allow(unused_variables)] +#[macro_export(local_inner_macros)] +macro_rules! error_position( + ($input:expr, $code:expr) => ({ + $crate::error::make_error($input, $code) + }); +); + +/// Creates a parse error from a `nom::ErrorKind`, +/// the position in the input and the next error in +/// the parsing tree +#[allow(unused_variables)] +#[macro_export(local_inner_macros)] +macro_rules! error_node_position( + ($input:expr, $code:expr, $next:expr) => ({ + $crate::error::append_error($input, $code, $next) + }); +); + +/// Prints a message and the input if the parser fails. +/// +/// The message prints the `Error` or `Incomplete` +/// and the parser's calling code. +/// +/// It also displays the input in hexdump format +/// +/// ```rust +/// use nom::{IResult, error::dbg_dmp, bytes::complete::tag}; +/// +/// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { +/// dbg_dmp(tag("abcd"), "tag")(i) +/// } +/// +/// let a = &b"efghijkl"[..]; +/// +/// // Will print the following message: +/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) ' +/// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl +/// f(a); +/// ``` +#[cfg(feature = "std")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))] +pub fn dbg_dmp<'a, F, O, E: std::fmt::Debug>( + f: F, + context: &'static str, +) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E> +where + F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>, +{ + use crate::HexDisplay; + move |i: &'a [u8]| match f(i) { + Err(e) => { + println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8)); + Err(e) + } + a => a, + } +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use super::*; + use crate::character::complete::char; + + #[test] + fn convert_error_panic() { + let input = ""; + + let _result: IResult<_, _, VerboseError<&str>> = char('x')(input); + } +} + +/* +#[cfg(feature = "alloc")] +use lib::std::{vec::Vec, collections::HashMap}; + +#[cfg(feature = "std")] +use lib::std::hash::Hash; + +#[cfg(feature = "std")] +pub fn add_error_pattern<'a, I: Clone + Hash + Eq, O, E: Clone + Hash + Eq>( + h: &mut HashMap, &'a str>, + e: VerboseError, + message: &'a str, +) -> bool { + h.insert(e, message); + true +} + +pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) { + let start = input.as_ptr(); + let off1 = s.as_ptr() as usize - start as usize; + let off2 = off1 + s.len(); + (off1, off2) +} + +#[cfg(feature = "std")] +pub fn prepare_errors(input: &[u8], e: VerboseError<&[u8]>) -> Option> { + let mut v: Vec<(ErrorKind, usize, usize)> = Vec::new(); + + for (p, kind) in e.errors.drain(..) { + let (o1, o2) = slice_to_offsets(input, p); + v.push((kind, o1, o2)); + } + + v.reverse(); + Some(v) +} + +#[cfg(feature = "std")] +pub fn print_error(input: &[u8], res: VerboseError<&[u8]>) { + if let Some(v) = prepare_errors(input, res) { + let colors = generate_colors(&v); + println!("parser codes: {}", print_codes(&colors, &HashMap::new())); + println!("{}", print_offsets(input, 0, &v)); + } else { + println!("not an error"); + } +} + +#[cfg(feature = "std")] +pub fn generate_colors(v: &[(ErrorKind, usize, usize)]) -> HashMap { + let mut h: HashMap = HashMap::new(); + let mut color = 0; + + for &(ref c, _, _) in v.iter() { + h.insert(error_to_u32(c), color + 31); + color = color + 1 % 7; + } + + h +} + +pub fn code_from_offset(v: &[(ErrorKind, usize, usize)], offset: usize) -> Option { + let mut acc: Option<(u32, usize, usize)> = None; + for &(ref ek, s, e) in v.iter() { + let c = error_to_u32(ek); + if s <= offset && offset <= e { + if let Some((_, start, end)) = acc { + if start <= s && e <= end { + acc = Some((c, s, e)); + } + } else { + acc = Some((c, s, e)); + } + } + } + if let Some((code, _, _)) = acc { + return Some(code); + } else { + return None; + } +} + +#[cfg(feature = "alloc")] +pub fn reset_color(v: &mut Vec) { + v.push(0x1B); + v.push(b'['); + v.push(0); + v.push(b'm'); +} + +#[cfg(feature = "alloc")] +pub fn write_color(v: &mut Vec, color: u8) { + v.push(0x1B); + v.push(b'['); + v.push(1); + v.push(b';'); + let s = color.to_string(); + let bytes = s.as_bytes(); + v.extend(bytes.iter().cloned()); + v.push(b'm'); +} + +#[cfg(feature = "std")] +#[cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] +pub fn print_codes(colors: &HashMap, names: &HashMap) -> String { + let mut v = Vec::new(); + for (code, &color) in colors { + if let Some(&s) = names.get(code) { + let bytes = s.as_bytes(); + write_color(&mut v, color); + v.extend(bytes.iter().cloned()); + } else { + let s = code.to_string(); + let bytes = s.as_bytes(); + write_color(&mut v, color); + v.extend(bytes.iter().cloned()); + } + reset_color(&mut v); + v.push(b' '); + } + reset_color(&mut v); + + String::from_utf8_lossy(&v[..]).into_owned() +} + +#[cfg(feature = "std")] +pub fn print_offsets(input: &[u8], from: usize, offsets: &[(ErrorKind, usize, usize)]) -> String { + let mut v = Vec::with_capacity(input.len() * 3); + let mut i = from; + let chunk_size = 8; + let mut current_code: Option = None; + let mut current_code2: Option = None; + + let colors = generate_colors(&offsets); + + for chunk in input.chunks(chunk_size) { + let s = format!("{:08x}", i); + for &ch in s.as_bytes().iter() { + v.push(ch); + } + v.push(b'\t'); + + let mut k = i; + let mut l = i; + for &byte in chunk { + if let Some(code) = code_from_offset(&offsets, k) { + if let Some(current) = current_code { + if current != code { + reset_color(&mut v); + current_code = Some(code); + if let Some(&color) = colors.get(&code) { + write_color(&mut v, color); + } + } + } else { + current_code = Some(code); + if let Some(&color) = colors.get(&code) { + write_color(&mut v, color); + } + } + } + v.push(CHARS[(byte >> 4) as usize]); + v.push(CHARS[(byte & 0xf) as usize]); + v.push(b' '); + k = k + 1; + } + + reset_color(&mut v); + + if chunk_size > chunk.len() { + for _ in 0..(chunk_size - chunk.len()) { + v.push(b' '); + v.push(b' '); + v.push(b' '); + } + } + v.push(b'\t'); + + for &byte in chunk { + if let Some(code) = code_from_offset(&offsets, l) { + if let Some(current) = current_code2 { + if current != code { + reset_color(&mut v); + current_code2 = Some(code); + if let Some(&color) = colors.get(&code) { + write_color(&mut v, color); + } + } + } else { + current_code2 = Some(code); + if let Some(&color) = colors.get(&code) { + write_color(&mut v, color); + } + } + } + if (byte >= 32 && byte <= 126) || byte >= 128 { + v.push(byte); + } else { + v.push(b'.'); + } + l = l + 1; + } + reset_color(&mut v); + + v.push(b'\n'); + i = i + chunk_size; + } + + String::from_utf8_lossy(&v[..]).into_owned() +} +*/ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/internal.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/internal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/internal.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/internal.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,489 @@ +//! Basic types to build the parsers + +use self::Needed::*; +use crate::error::{self, ErrorKind}; +use crate::lib::std::fmt; +use core::num::NonZeroUsize; + +/// Holds the result of parsing functions +/// +/// It depends on the input type `I`, the output type `O`, and the error type `E` +/// (by default `(I, nom::ErrorKind)`) +/// +/// The `Ok` side is a pair containing the remainder of the input (the part of the data that +/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`. +/// +/// Outside of the parsing code, you can use the [Finish::finish] method to convert +/// it to a more common result type +pub type IResult> = Result<(I, O), Err>; + +/// Helper trait to convert a parser's result to a more manageable type +pub trait Finish { + /// converts the parser's result to a type that is more consumable by error + /// management libraries. It keeps the same `Ok` branch, and merges `Err::Error` + /// and `Err::Failure` into the `Err` side. + /// + /// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic. + /// - "complete" parsers: It will not be an issue, `Incomplete` is never used + /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data + /// for the parser to decide, and you should gather more data before parsing again. + /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`, + /// you can get out of the parsing loop and call `finish()` on the parser's result + fn finish(self) -> Result<(I, O), E>; +} + +impl Finish for IResult { + fn finish(self) -> Result<(I, O), E> { + match self { + Ok(res) => Ok(res), + Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e), + Err(Err::Incomplete(_)) => { + panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead") + } + } + } +} + +/// Contains information on needed data if a parser returned `Incomplete` +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub enum Needed { + /// Needs more data, but we do not know how much + Unknown, + /// Contains the required data size in bytes + Size(NonZeroUsize), +} + +impl Needed { + /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero + pub fn new(s: usize) -> Self { + match NonZeroUsize::new(s) { + Some(sz) => Needed::Size(sz), + None => Needed::Unknown, + } + } + + /// Indicates if we know how many bytes we need + pub fn is_known(&self) -> bool { + *self != Unknown + } + + /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value. + #[inline] + pub fn map usize>(self, f: F) -> Needed { + match self { + Unknown => Unknown, + Size(n) => Needed::new(f(n)), + } + } +} + +/// The `Err` enum indicates the parser was not successful +/// +/// It has three cases: +/// +/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum +/// can contain how many additional bytes are necessary. If you are sure your parser +/// is working on full data, you can wrap your parser with the `complete` combinator +/// to transform that case in `Error` +/// * `Error` means some parser did not succeed, but another one might (as an example, +/// when testing different branches of an `alt` combinator) +/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix +/// to decide on the next parser to apply, and that parser fails, you know there's no need +/// to try other parsers, you were already in the right branch, so the data is invalid +/// +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub enum Err { + /// There was not enough data + Incomplete(Needed), + /// The parser had an error (recoverable) + Error(E), + /// The parser had an unrecoverable error: we got to the right + /// branch and we know other branches won't work, so backtrack + /// as fast as possible + Failure(E), +} + +impl Err { + /// Tests if the result is Incomplete + pub fn is_incomplete(&self) -> bool { + if let Err::Incomplete(_) = self { + true + } else { + false + } + } + + /// Applies the given function to the inner error + pub fn map(self, f: F) -> Err + where + F: FnOnce(E) -> E2, + { + match self { + Err::Incomplete(n) => Err::Incomplete(n), + Err::Failure(t) => Err::Failure(f(t)), + Err::Error(t) => Err::Error(f(t)), + } + } + + /// Automatically converts between errors if the underlying type supports it + pub fn convert(e: Err) -> Self + where + E: From, + { + e.map(crate::lib::std::convert::Into::into) + } +} + +impl Err<(T, ErrorKind)> { + /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U` + pub fn map_input(self, f: F) -> Err<(U, ErrorKind)> + where + F: FnOnce(T) -> U, + { + match self { + Err::Incomplete(n) => Err::Incomplete(n), + Err::Failure((input, k)) => Err::Failure((f(input), k)), + Err::Error((input, k)) => Err::Error((f(input), k)), + } + } +} + +impl Err> { + /// Maps `Err>` to `Err>` with the given `F: T -> U` + pub fn map_input(self, f: F) -> Err> + where + F: FnOnce(T) -> U, + { + match self { + Err::Incomplete(n) => Err::Incomplete(n), + Err::Failure(error::Error { input, code }) => Err::Failure(error::Error { + input: f(input), + code, + }), + Err::Error(error::Error { input, code }) => Err::Error(error::Error { + input: f(input), + code, + }), + } + } +} + +#[cfg(feature = "alloc")] +use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec}; +#[cfg(feature = "alloc")] +impl Err<(&[u8], ErrorKind)> { + /// Obtaining ownership + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] + pub fn to_owned(self) -> Err<(Vec, ErrorKind)> { + self.map_input(ToOwned::to_owned) + } +} + +#[cfg(feature = "alloc")] +impl Err<(&str, ErrorKind)> { + /// Obtaining ownership + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] + pub fn to_owned(self) -> Err<(String, ErrorKind)> { + self.map_input(ToOwned::to_owned) + } +} + +#[cfg(feature = "alloc")] +impl Err> { + /// Obtaining ownership + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] + pub fn to_owned(self) -> Err>> { + self.map_input(ToOwned::to_owned) + } +} + +#[cfg(feature = "alloc")] +impl Err> { + /// Obtaining ownership + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] + pub fn to_owned(self) -> Err> { + self.map_input(ToOwned::to_owned) + } +} + +impl Eq for Err {} + +impl fmt::Display for Err +where + E: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u), + Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"), + Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c), + Err::Error(c) => write!(f, "Parsing Error: {:?}", c), + } + } +} + +#[cfg(feature = "std")] +use std::error::Error; + +#[cfg(feature = "std")] +impl Error for Err +where + E: fmt::Debug, +{ + fn source(&self) -> Option<&(dyn Error + 'static)> { + None // no underlying error + } +} + +/// All nom parsers implement this trait +pub trait Parser { + /// A parser takes in input type, and returns a `Result` containing + /// either the remaining input and the output value, or an error + fn parse(&mut self, input: I) -> IResult; + + /// Maps a function over the result of a parser + fn map(self, g: G) -> Map + where + G: Fn(O) -> O2, + Self: core::marker::Sized, + { + Map { + f: self, + g, + phantom: core::marker::PhantomData, + } + } + + /// Creates a second parser from the output of the first one, then apply over the rest of the input + fn flat_map(self, g: G) -> FlatMap + where + G: FnMut(O) -> H, + H: Parser, + Self: core::marker::Sized, + { + FlatMap { + f: self, + g, + phantom: core::marker::PhantomData, + } + } + + /// Applies a second parser over the output of the first one + fn and_then(self, g: G) -> AndThen + where + G: Parser, + Self: core::marker::Sized, + { + AndThen { + f: self, + g, + phantom: core::marker::PhantomData, + } + } + + /// Applies a second parser after the first one, return their results as a tuple + fn and(self, g: G) -> And + where + G: Parser, + Self: core::marker::Sized, + { + And { f: self, g } + } + + /// Applies a second parser over the input if the first one failed + fn or(self, g: G) -> Or + where + G: Parser, + Self: core::marker::Sized, + { + Or { f: self, g } + } + + /// automatically converts the parser's output and error values to another type, as long as they + /// implement the `From` trait + fn into, E2: From>(self) -> Into + where + Self: core::marker::Sized, + { + Into { + f: self, + phantom_out1: core::marker::PhantomData, + phantom_err1: core::marker::PhantomData, + phantom_out2: core::marker::PhantomData, + phantom_err2: core::marker::PhantomData, + } + } +} + +impl<'a, I, O, E, F> Parser for F +where + F: FnMut(I) -> IResult + 'a, +{ + fn parse(&mut self, i: I) -> IResult { + self(i) + } +} + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(feature = "alloc")] +impl<'a, I, O, E> Parser for Box + 'a> { + fn parse(&mut self, input: I) -> IResult { + (**self).parse(input) + } +} + +/// Implementation of `Parser::map` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Map { + f: F, + g: G, + phantom: core::marker::PhantomData, +} + +impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> O2> Parser for Map { + fn parse(&mut self, i: I) -> IResult { + match self.f.parse(i) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, (self.g)(o))), + } + } +} + +/// Implementation of `Parser::flat_map` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct FlatMap { + f: F, + g: G, + phantom: core::marker::PhantomData, +} + +impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> H, H: Parser> Parser + for FlatMap +{ + fn parse(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse(i)?; + (self.g)(o1).parse(i) + } +} + +/// Implementation of `Parser::and_then` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct AndThen { + f: F, + g: G, + phantom: core::marker::PhantomData, +} + +impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser + for AndThen +{ + fn parse(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse(i)?; + let (_, o2) = self.g.parse(o1)?; + Ok((i, o2)) + } +} + +/// Implementation of `Parser::and` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct And { + f: F, + g: G, +} + +impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser + for And +{ + fn parse(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse(i)?; + let (i, o2) = self.g.parse(i)?; + Ok((i, (o1, o2))) + } +} + +/// Implementation of `Parser::or` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Or { + f: F, + g: G, +} + +impl<'a, I: Clone, O, E: crate::error::ParseError, F: Parser, G: Parser> + Parser for Or +{ + fn parse(&mut self, i: I) -> IResult { + match self.f.parse(i.clone()) { + Err(Err::Error(e1)) => match self.g.parse(i) { + Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))), + res => res, + }, + res => res, + } + } +} + +/// Implementation of `Parser::into` +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Into, E1, E2: From> { + f: F, + phantom_out1: core::marker::PhantomData, + phantom_err1: core::marker::PhantomData, + phantom_out2: core::marker::PhantomData, + phantom_err2: core::marker::PhantomData, +} + +impl< + 'a, + I: Clone, + O1, + O2: From, + E1, + E2: crate::error::ParseError + From, + F: Parser, + > Parser for Into +{ + fn parse(&mut self, i: I) -> IResult { + match self.f.parse(i) { + Ok((i, o)) => Ok((i, o.into())), + Err(Err::Error(e)) => Err(Err::Error(e.into())), + Err(Err::Failure(e)) => Err(Err::Failure(e.into())), + Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::error::ErrorKind; + + #[doc(hidden)] + #[macro_export] + macro_rules! assert_size ( + ($t:ty, $sz:expr) => ( + assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz); + ); + ); + + #[test] + #[cfg(target_pointer_width = "64")] + fn size_test() { + assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40); + //FIXME: since rust 1.65, this is now 32 bytes, likely thanks to https://github.com/rust-lang/rust/pull/94075 + // deactivating that test for now because it'll have different values depending on the rust version + // assert_size!(IResult<&str, &str, u32>, 40); + assert_size!(Needed, 8); + assert_size!(Err, 16); + assert_size!(ErrorKind, 1); + } + + #[test] + fn err_map_test() { + let e = Err::Error(1); + assert_eq!(e.map(|v| v + 1), Err::Error(2)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,464 @@ +//! # nom, eating data byte by byte +//! +//! nom is a parser combinator library with a focus on safe parsing, +//! streaming patterns, and as much as possible zero copy. +//! +//! ## Example +//! +//! ```rust +//! use nom::{ +//! IResult, +//! bytes::complete::{tag, take_while_m_n}, +//! combinator::map_res, +//! sequence::tuple}; +//! +//! #[derive(Debug,PartialEq)] +//! pub struct Color { +//! pub red: u8, +//! pub green: u8, +//! pub blue: u8, +//! } +//! +//! fn from_hex(input: &str) -> Result { +//! u8::from_str_radix(input, 16) +//! } +//! +//! fn is_hex_digit(c: char) -> bool { +//! c.is_digit(16) +//! } +//! +//! fn hex_primary(input: &str) -> IResult<&str, u8> { +//! map_res( +//! take_while_m_n(2, 2, is_hex_digit), +//! from_hex +//! )(input) +//! } +//! +//! fn hex_color(input: &str) -> IResult<&str, Color> { +//! let (input, _) = tag("#")(input)?; +//! let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; +//! +//! Ok((input, Color { red, green, blue })) +//! } +//! +//! fn main() { +//! assert_eq!(hex_color("#2F14DF"), Ok(("", Color { +//! red: 47, +//! green: 20, +//! blue: 223, +//! }))); +//! } +//! ``` +//! +//! The code is available on [Github](https://github.com/Geal/nom) +//! +//! There are a few [guides](https://github.com/Geal/nom/tree/main/doc) with more details +//! about [how to write parsers](https://github.com/Geal/nom/blob/main/doc/making_a_new_parser_from_scratch.md), +//! or the [error management system](https://github.com/Geal/nom/blob/main/doc/error_management.md). +//! You can also check out the [recipes] module that contains examples of common patterns. +//! +//! **Looking for a specific combinator? Read the +//! ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)** +//! +//! If you are upgrading to nom 5.0, please read the +//! [migration document](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_5.md). +//! +//! ## Parser combinators +//! +//! Parser combinators are an approach to parsers that is very different from +//! software like [lex](https://en.wikipedia.org/wiki/Lex_(software)) and +//! [yacc](https://en.wikipedia.org/wiki/Yacc). Instead of writing the grammar +//! in a separate syntax and generating the corresponding code, you use very small +//! functions with very specific purposes, like "take 5 bytes", or "recognize the +//! word 'HTTP'", and assemble them in meaningful patterns like "recognize +//! 'HTTP', then a space, then a version". +//! The resulting code is small, and looks like the grammar you would have +//! written with other parser approaches. +//! +//! This gives us a few advantages: +//! +//! - The parsers are small and easy to write +//! - The parsers components are easy to reuse (if they're general enough, please add them to nom!) +//! - The parsers components are easy to test separately (unit tests and property-based tests) +//! - The parser combination code looks close to the grammar you would have written +//! - You can build partial parsers, specific to the data you need at the moment, and ignore the rest +//! +//! Here is an example of one such parser, to recognize text between parentheses: +//! +//! ```rust +//! use nom::{ +//! IResult, +//! sequence::delimited, +//! // see the "streaming/complete" paragraph lower for an explanation of these submodules +//! character::complete::char, +//! bytes::complete::is_not +//! }; +//! +//! fn parens(input: &str) -> IResult<&str, &str> { +//! delimited(char('('), is_not(")"), char(')'))(input) +//! } +//! ``` +//! +//! It defines a function named `parens` which will recognize a sequence of the +//! character `(`, the longest byte array not containing `)`, then the character +//! `)`, and will return the byte array in the middle. +//! +//! Here is another parser, written without using nom's combinators this time: +//! +//! ```rust +//! use nom::{IResult, Err, Needed}; +//! +//! # fn main() { +//! fn take4(i: &[u8]) -> IResult<&[u8], &[u8]>{ +//! if i.len() < 4 { +//! Err(Err::Incomplete(Needed::new(4))) +//! } else { +//! Ok((&i[4..], &i[0..4])) +//! } +//! } +//! # } +//! ``` +//! +//! This function takes a byte array as input, and tries to consume 4 bytes. +//! Writing all the parsers manually, like this, is dangerous, despite Rust's +//! safety features. There are still a lot of mistakes one can make. That's why +//! nom provides a list of functions to help in developing parsers. +//! +//! With functions, you would write it like this: +//! +//! ```rust +//! use nom::{IResult, bytes::streaming::take}; +//! fn take4(input: &str) -> IResult<&str, &str> { +//! take(4u8)(input) +//! } +//! ``` +//! +//! A parser in nom is a function which, for an input type `I`, an output type `O` +//! and an optional error type `E`, will have the following signature: +//! +//! ```rust,compile_fail +//! fn parser(input: I) -> IResult; +//! ``` +//! +//! Or like this, if you don't want to specify a custom error type (it will be `(I, ErrorKind)` by default): +//! +//! ```rust,compile_fail +//! fn parser(input: I) -> IResult; +//! ``` +//! +//! `IResult` is an alias for the `Result` type: +//! +//! ```rust +//! use nom::{Needed, error::Error}; +//! +//! type IResult> = Result<(I, O), Err>; +//! +//! enum Err { +//! Incomplete(Needed), +//! Error(E), +//! Failure(E), +//! } +//! ``` +//! +//! It can have the following values: +//! +//! - A correct result `Ok((I,O))` with the first element being the remaining of the input (not parsed yet), and the second the output value; +//! - An error `Err(Err::Error(c))` with `c` an error that can be built from the input position and a parser specific error +//! - An error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed +//! - An error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: We cannot backtrack and test another parser +//! +//! Please refer to the ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers. +//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/main/doc). +//! +//! ## Making new parsers with function combinators +//! +//! nom is based on functions that generate parsers, with a signature like +//! this: `(arguments) -> impl Fn(Input) -> IResult`. +//! The arguments of a combinator can be direct values (like `take` which uses +//! a number of bytes or character as argument) or even other parsers (like +//! `delimited` which takes as argument 3 parsers, and returns the result of +//! the second one if all are successful). +//! +//! Here are some examples: +//! +//! ```rust +//! use nom::IResult; +//! use nom::bytes::complete::{tag, take}; +//! fn abcd_parser(i: &str) -> IResult<&str, &str> { +//! tag("abcd")(i) // will consume bytes if the input begins with "abcd" +//! } +//! +//! fn take_10(i: &[u8]) -> IResult<&[u8], &[u8]> { +//! take(10u8)(i) // will consume and return 10 bytes of input +//! } +//! ``` +//! +//! ## Combining parsers +//! +//! There are higher level patterns, like the **`alt`** combinator, which +//! provides a choice between multiple parsers. If one branch fails, it tries +//! the next, and returns the result of the first parser that succeeds: +//! +//! ```rust +//! use nom::IResult; +//! use nom::branch::alt; +//! use nom::bytes::complete::tag; +//! +//! let mut alt_tags = alt((tag("abcd"), tag("efgh"))); +//! +//! assert_eq!(alt_tags(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..]))); +//! assert_eq!(alt_tags(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..]))); +//! assert_eq!(alt_tags(&b"ijklxxx"[..]), Err(nom::Err::Error((&b"ijklxxx"[..], nom::error::ErrorKind::Tag)))); +//! ``` +//! +//! The **`opt`** combinator makes a parser optional. If the child parser returns +//! an error, **`opt`** will still succeed and return None: +//! +//! ```rust +//! use nom::{IResult, combinator::opt, bytes::complete::tag}; +//! fn abcd_opt(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> { +//! opt(tag("abcd"))(i) +//! } +//! +//! assert_eq!(abcd_opt(&b"abcdxxx"[..]), Ok((&b"xxx"[..], Some(&b"abcd"[..])))); +//! assert_eq!(abcd_opt(&b"efghxxx"[..]), Ok((&b"efghxxx"[..], None))); +//! ``` +//! +//! **`many0`** applies a parser 0 or more times, and returns a vector of the aggregated results: +//! +//! ```rust +//! # #[cfg(feature = "alloc")] +//! # fn main() { +//! use nom::{IResult, multi::many0, bytes::complete::tag}; +//! use std::str; +//! +//! fn multi(i: &str) -> IResult<&str, Vec<&str>> { +//! many0(tag("abcd"))(i) +//! } +//! +//! let a = "abcdef"; +//! let b = "abcdabcdef"; +//! let c = "azerty"; +//! assert_eq!(multi(a), Ok(("ef", vec!["abcd"]))); +//! assert_eq!(multi(b), Ok(("ef", vec!["abcd", "abcd"]))); +//! assert_eq!(multi(c), Ok(("azerty", Vec::new()))); +//! # } +//! # #[cfg(not(feature = "alloc"))] +//! # fn main() {} +//! ``` +//! +//! Here are some basic combinators available: +//! +//! - **`opt`**: Will make the parser optional (if it returns the `O` type, the new parser returns `Option`) +//! - **`many0`**: Will apply the parser 0 or more times (if it returns the `O` type, the new parser returns `Vec`) +//! - **`many1`**: Will apply the parser 1 or more times +//! +//! There are more complex (and more useful) parsers like `tuple`, which is +//! used to apply a series of parsers then assemble their results. +//! +//! Example with `tuple`: +//! +//! ```rust +//! # fn main() { +//! use nom::{error::ErrorKind, Needed, +//! number::streaming::be_u16, +//! bytes::streaming::{tag, take}, +//! sequence::tuple}; +//! +//! let mut tpl = tuple((be_u16, take(3u8), tag("fg"))); +//! +//! assert_eq!( +//! tpl(&b"abcdefgh"[..]), +//! Ok(( +//! &b"h"[..], +//! (0x6162u16, &b"cde"[..], &b"fg"[..]) +//! )) +//! ); +//! assert_eq!(tpl(&b"abcde"[..]), Err(nom::Err::Incomplete(Needed::new(2)))); +//! let input = &b"abcdejk"[..]; +//! assert_eq!(tpl(input), Err(nom::Err::Error((&input[5..], ErrorKind::Tag)))); +//! # } +//! ``` +//! +//! But you can also use a sequence of combinators written in imperative style, +//! thanks to the `?` operator: +//! +//! ```rust +//! # fn main() { +//! use nom::{IResult, bytes::complete::tag}; +//! +//! #[derive(Debug, PartialEq)] +//! struct A { +//! a: u8, +//! b: u8 +//! } +//! +//! fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,1)) } +//! fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,2)) } +//! +//! fn f(i: &[u8]) -> IResult<&[u8], A> { +//! // if successful, the parser returns `Ok((remaining_input, output_value))` that we can destructure +//! let (i, _) = tag("abcd")(i)?; +//! let (i, a) = ret_int1(i)?; +//! let (i, _) = tag("efgh")(i)?; +//! let (i, b) = ret_int2(i)?; +//! +//! Ok((i, A { a, b })) +//! } +//! +//! let r = f(b"abcdefghX"); +//! assert_eq!(r, Ok((&b"X"[..], A{a: 1, b: 2}))); +//! # } +//! ``` +//! +//! ## Streaming / Complete +//! +//! Some of nom's modules have `streaming` or `complete` submodules. They hold +//! different variants of the same combinators. +//! +//! A streaming parser assumes that we might not have all of the input data. +//! This can happen with some network protocol or large file parsers, where the +//! input buffer can be full and need to be resized or refilled. +//! +//! A complete parser assumes that we already have all of the input data. +//! This will be the common case with small files that can be read entirely to +//! memory. +//! +//! Here is how it works in practice: +//! +//! ```rust +//! use nom::{IResult, Err, Needed, error::{Error, ErrorKind}, bytes, character}; +//! +//! fn take_streaming(i: &[u8]) -> IResult<&[u8], &[u8]> { +//! bytes::streaming::take(4u8)(i) +//! } +//! +//! fn take_complete(i: &[u8]) -> IResult<&[u8], &[u8]> { +//! bytes::complete::take(4u8)(i) +//! } +//! +//! // both parsers will take 4 bytes as expected +//! assert_eq!(take_streaming(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..]))); +//! assert_eq!(take_complete(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..]))); +//! +//! // if the input is smaller than 4 bytes, the streaming parser +//! // will return `Incomplete` to indicate that we need more data +//! assert_eq!(take_streaming(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +//! +//! // but the complete parser will return an error +//! assert_eq!(take_complete(&b"abc"[..]), Err(Err::Error(Error::new(&b"abc"[..], ErrorKind::Eof)))); +//! +//! // the alpha0 function recognizes 0 or more alphabetic characters +//! fn alpha0_streaming(i: &str) -> IResult<&str, &str> { +//! character::streaming::alpha0(i) +//! } +//! +//! fn alpha0_complete(i: &str) -> IResult<&str, &str> { +//! character::complete::alpha0(i) +//! } +//! +//! // if there's a clear limit to the recognized characters, both parsers work the same way +//! assert_eq!(alpha0_streaming("abcd;"), Ok((";", "abcd"))); +//! assert_eq!(alpha0_complete("abcd;"), Ok((";", "abcd"))); +//! +//! // but when there's no limit, the streaming version returns `Incomplete`, because it cannot +//! // know if more input data should be recognized. The whole input could be "abcd;", or +//! // "abcde;" +//! assert_eq!(alpha0_streaming("abcd"), Err(Err::Incomplete(Needed::new(1)))); +//! +//! // while the complete version knows that all of the data is there +//! assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd"))); +//! ``` +//! **Going further:** Read the [guides](https://github.com/Geal/nom/tree/main/doc), +//! check out the [recipes]! +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::doc_markdown))] +#![cfg_attr(feature = "docsrs", feature(doc_cfg))] +#![cfg_attr(feature = "docsrs", feature(extended_key_value_attributes))] +#![deny(missing_docs)] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +#[cfg(feature = "alloc")] +#[macro_use] +extern crate alloc; +#[cfg(doctest)] +extern crate doc_comment; + +#[cfg(doctest)] +doc_comment::doctest!("../README.md"); + +/// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does +/// it, albeit there it is not public. +#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] +pub mod lib { + /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally, + /// as well as `core` or `std` + #[cfg(not(feature = "std"))] + #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] + /// internal std exports for no_std compatibility + pub mod std { + #[doc(hidden)] + #[cfg(not(feature = "alloc"))] + pub use core::borrow; + + #[cfg(feature = "alloc")] + #[doc(hidden)] + pub use alloc::{borrow, boxed, string, vec}; + + #[doc(hidden)] + pub use core::{cmp, convert, fmt, iter, mem, ops, option, result, slice, str}; + + /// internal reproduction of std prelude + #[doc(hidden)] + pub mod prelude { + pub use core::prelude as v1; + } + } + + #[cfg(feature = "std")] + #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))] + /// internal std exports for no_std compatibility + pub mod std { + #[doc(hidden)] + pub use std::{ + alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, result, + slice, str, string, vec, + }; + + /// internal reproduction of std prelude + #[doc(hidden)] + pub mod prelude { + pub use std::prelude as v1; + } + } +} + +pub use self::bits::*; +pub use self::internal::*; +pub use self::traits::*; + +pub use self::str::*; + +#[macro_use] +mod macros; +#[macro_use] +pub mod error; + +pub mod branch; +pub mod combinator; +mod internal; +pub mod multi; +pub mod sequence; +mod traits; + +pub mod bits; +pub mod bytes; + +pub mod character; + +mod str; + +pub mod number; + +#[cfg(feature = "docsrs")] +#[cfg_attr(feature = "docsrs", cfg_attr(feature = "docsrs", doc = include_str!("../doc/nom_recipes.md")))] +pub mod recipes {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +macro_rules! succ ( + (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*)); + (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*)); + (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*)); + (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*)); + (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*)); + (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*)); + (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*)); + (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*)); + (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*)); + (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*)); + (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*)); + (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*)); + (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*)); + (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*)); + (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*)); + (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*)); + (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*)); + (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*)); + (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*)); + (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*)); + (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*)); +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/multi/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/multi/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1049 @@ +//! Combinators applying their child parser multiple times + +#[cfg(test)] +mod tests; + +use crate::error::ErrorKind; +use crate::error::ParseError; +use crate::internal::{Err, IResult, Needed, Parser}; +#[cfg(feature = "alloc")] +use crate::lib::std::vec::Vec; +use crate::traits::{InputLength, InputTake, ToUsize}; +use core::num::NonZeroUsize; + +/// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. +/// +/// Pre-allocating memory is a nice optimization but count fields can't +/// always be trusted. We should clamp initial capacities to some reasonable +/// amount. This reduces the risk of a bogus count value triggering a panic +/// due to an OOM error. +/// +/// This does not affect correctness. Nom will always read the full number +/// of elements regardless of the capacity cap. +#[cfg(feature = "alloc")] +const MAX_INITIAL_CAPACITY_BYTES: usize = 65536; + +/// Repeats the embedded parser, gathering the results in a `Vec`. +/// +/// This stops on [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// +/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will +/// return an error, to prevent going into an infinite loop +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::many0; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// many0(tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn many0(mut f: F) -> impl FnMut(I) -> IResult, E> +where + I: Clone + InputLength, + F: Parser, + E: ParseError, +{ + move |mut i: I| { + let mut acc = crate::lib::std::vec::Vec::with_capacity(4); + loop { + let len = i.input_len(); + match f.parse(i.clone()) { + Err(Err::Error(_)) => return Ok((i, acc)), + Err(e) => return Err(e), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many0))); + } + + i = i1; + acc.push(o); + } + } + } + } +} + +/// Runs the embedded parser, gathering the results in a `Vec`. +/// +/// This stops on [`Err::Error`] if there is at least one result, and returns the results that were accumulated. To instead chain an error up, +/// see [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// +/// *Note*: If the parser passed to `many1` accepts empty inputs +/// (like `alpha0` or `digit0`), `many1` will return an error, +/// to prevent going into an infinite loop. +/// +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::many1; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// many1(tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn many1(mut f: F) -> impl FnMut(I) -> IResult, E> +where + I: Clone + InputLength, + F: Parser, + E: ParseError, +{ + move |mut i: I| match f.parse(i.clone()) { + Err(Err::Error(err)) => Err(Err::Error(E::append(i, ErrorKind::Many1, err))), + Err(e) => Err(e), + Ok((i1, o)) => { + let mut acc = crate::lib::std::vec::Vec::with_capacity(4); + acc.push(o); + i = i1; + + loop { + let len = i.input_len(); + match f.parse(i.clone()) { + Err(Err::Error(_)) => return Ok((i, acc)), + Err(e) => return Err(e), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1))); + } + + i = i1; + acc.push(o); + } + } + } + } + } +} + +/// Applies the parser `f` until the parser `g` produces a result. +/// +/// Returns a tuple of the results of `f` in a `Vec` and the result of `g`. +/// +/// `f` keeps going so long as `g` produces [`Err::Error`]. To instead chain an error up, see [`cut`][crate::combinator::cut]. +/// +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::many_till; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, (Vec<&str>, &str)> { +/// many_till(tag("abc"), tag("end"))(s) +/// }; +/// +/// assert_eq!(parser("abcabcend"), Ok(("", (vec!["abc", "abc"], "end")))); +/// assert_eq!(parser("abc123end"), Err(Err::Error(Error::new("123end", ErrorKind::Tag)))); +/// assert_eq!(parser("123123end"), Err(Err::Error(Error::new("123123end", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcendefg"), Ok(("efg", (vec!["abc"], "end")))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn many_till( + mut f: F, + mut g: G, +) -> impl FnMut(I) -> IResult, P), E> +where + I: Clone + InputLength, + F: Parser, + G: Parser, + E: ParseError, +{ + move |mut i: I| { + let mut res = crate::lib::std::vec::Vec::new(); + loop { + let len = i.input_len(); + match g.parse(i.clone()) { + Ok((i1, o)) => return Ok((i1, (res, o))), + Err(Err::Error(_)) => { + match f.parse(i.clone()) { + Err(Err::Error(err)) => return Err(Err::Error(E::append(i, ErrorKind::ManyTill, err))), + Err(e) => return Err(e), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(E::from_error_kind(i1, ErrorKind::ManyTill))); + } + + res.push(o); + i = i1; + } + } + } + Err(e) => return Err(e), + } + } + } +} + +/// Alternates between two parsers to produce a list of elements. +/// +/// This stops when either parser returns [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `sep` Parses the separator between list elements. +/// * `f` Parses the elements of the list. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::separated_list0; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// separated_list0(tag("|"), tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); +/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"]))); +/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![]))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn separated_list0( + mut sep: G, + mut f: F, +) -> impl FnMut(I) -> IResult, E> +where + I: Clone + InputLength, + F: Parser, + G: Parser, + E: ParseError, +{ + move |mut i: I| { + let mut res = Vec::new(); + + match f.parse(i.clone()) { + Err(Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, o)) => { + res.push(o); + i = i1; + } + } + + loop { + let len = i.input_len(); + match sep.parse(i.clone()) { + Err(Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, _)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList))); + } + + match f.parse(i1.clone()) { + Err(Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i2, o)) => { + res.push(o); + i = i2; + } + } + } + } + } + } +} + +/// Alternates between two parsers to produce a list of elements until [`Err::Error`]. +/// +/// Fails if the element parser does not produce at least one element.$ +/// +/// This stops when either parser returns [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `sep` Parses the separator between list elements. +/// * `f` Parses the elements of the list. +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::separated_list1; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// separated_list1(tag("|"), tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); +/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"]))); +/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"]))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("def|abc"), Err(Err::Error(Error::new("def|abc", ErrorKind::Tag)))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn separated_list1( + mut sep: G, + mut f: F, +) -> impl FnMut(I) -> IResult, E> +where + I: Clone + InputLength, + F: Parser, + G: Parser, + E: ParseError, +{ + move |mut i: I| { + let mut res = Vec::new(); + + // Parse the first element + match f.parse(i.clone()) { + Err(e) => return Err(e), + Ok((i1, o)) => { + res.push(o); + i = i1; + } + } + + loop { + let len = i.input_len(); + match sep.parse(i.clone()) { + Err(Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, _)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList))); + } + + match f.parse(i1.clone()) { + Err(Err::Error(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i2, o)) => { + res.push(o); + i = i2; + } + } + } + } + } + } +} + +/// Repeats the embedded parser `m..=n` times +/// +/// This stops before `n` when the parser returns [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `m` The minimum number of iterations. +/// * `n` The maximum number of iterations. +/// * `f` The parser to apply. +/// +/// *Note*: If the parser passed to `many1` accepts empty inputs +/// (like `alpha0` or `digit0`), `many1` will return an error, +/// to prevent going into an infinite loop. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::many_m_n; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// many_m_n(0, 2, tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn many_m_n( + min: usize, + max: usize, + mut parse: F, +) -> impl FnMut(I) -> IResult, E> +where + I: Clone + InputLength, + F: Parser, + E: ParseError, +{ + move |mut input: I| { + if min > max { + return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN))); + } + + let max_initial_capacity = + MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); + let mut res = crate::lib::std::vec::Vec::with_capacity(min.min(max_initial_capacity)); + for count in 0..max { + let len = input.input_len(); + match parse.parse(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::ManyMN))); + } + + res.push(value); + input = tail; + } + Err(Err::Error(e)) => { + if count < min { + return Err(Err::Error(E::append(input, ErrorKind::ManyMN, e))); + } else { + return Ok((input, res)); + } + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input, res)) + } +} + +/// Repeats the embedded parser, counting the results +/// +/// This stops on [`Err::Error`]. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// +/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will +/// return an error, to prevent going into an infinite loop +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::many0_count; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, usize> { +/// many0_count(tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", 2))); +/// assert_eq!(parser("abc123"), Ok(("123", 1))); +/// assert_eq!(parser("123123"), Ok(("123123", 0))); +/// assert_eq!(parser(""), Ok(("", 0))); +/// ``` +pub fn many0_count(mut f: F) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + F: Parser, + E: ParseError, +{ + move |i: I| { + let mut input = i; + let mut count = 0; + + loop { + let input_ = input.clone(); + let len = input.input_len(); + match f.parse(input_) { + Ok((i, _)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0Count))); + } + + input = i; + count += 1; + } + + Err(Err::Error(_)) => return Ok((input, count)), + + Err(e) => return Err(e), + } + } + } +} + +/// Runs the embedded parser, counting the results. +/// +/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up, +/// see [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// +/// *Note*: If the parser passed to `many1` accepts empty inputs +/// (like `alpha0` or `digit0`), `many1` will return an error, +/// to prevent going into an infinite loop. +/// +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::many1_count; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, usize> { +/// many1_count(tag("abc"))(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", 2))); +/// assert_eq!(parser("abc123"), Ok(("123", 1))); +/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1Count)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1Count)))); +/// ``` +pub fn many1_count(mut f: F) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + F: Parser, + E: ParseError, +{ + move |i: I| { + let i_ = i.clone(); + match f.parse(i_) { + Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count))), + Err(i) => Err(i), + Ok((i1, _)) => { + let mut count = 1; + let mut input = i1; + + loop { + let len = input.input_len(); + let input_ = input.clone(); + match f.parse(input_) { + Err(Err::Error(_)) => return Ok((input, count)), + Err(e) => return Err(e), + Ok((i, _)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count))); + } + + count += 1; + input = i; + } + } + } + } + } + } +} + +/// Runs the embedded parser `count` times, gathering the results in a `Vec` +/// +/// # Arguments +/// * `f` The parser to apply. +/// * `count` How often to apply the parser. +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::count; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// count(tag("abc"), 2)(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Err(Err::Error(Error::new("123", ErrorKind::Tag)))); +/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +pub fn count(mut f: F, count: usize) -> impl FnMut(I) -> IResult, E> +where + I: Clone + PartialEq, + F: Parser, + E: ParseError, +{ + move |i: I| { + let mut input = i.clone(); + let max_initial_capacity = + MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); + let mut res = crate::lib::std::vec::Vec::with_capacity(count.min(max_initial_capacity)); + + for _ in 0..count { + let input_ = input.clone(); + match f.parse(input_) { + Ok((i, o)) => { + res.push(o); + input = i; + } + Err(Err::Error(e)) => { + return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input, res)) + } +} + +/// Runs the embedded parser repeatedly, filling the given slice with results. +/// +/// This parser fails if the input runs out before the given slice is full. +/// +/// # Arguments +/// * `f` The parser to apply. +/// * `buf` The slice to fill +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::fill; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, [&str; 2]> { +/// let mut buf = ["", ""]; +/// let (rest, ()) = fill(tag("abc"), &mut buf)(s)?; +/// Ok((rest, buf)) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", ["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Err(Err::Error(Error::new("123", ErrorKind::Tag)))); +/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", ["abc", "abc"]))); +/// ``` +pub fn fill<'a, I, O, E, F>(f: F, buf: &'a mut [O]) -> impl FnMut(I) -> IResult + 'a +where + I: Clone + PartialEq, + F: Fn(I) -> IResult + 'a, + E: ParseError, +{ + move |i: I| { + let mut input = i.clone(); + + for elem in buf.iter_mut() { + let input_ = input.clone(); + match f(input_) { + Ok((i, o)) => { + *elem = o; + input = i; + } + Err(Err::Error(e)) => { + return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input, ())) + } +} + +/// Repeats the embedded parser, calling `g` to gather the results. +/// +/// This stops on [`Err::Error`]. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// * `init` A function returning the initial value. +/// * `g` The function that combines a result of `f` with +/// the current accumulator. +/// +/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will +/// return an error, to prevent going into an infinite loop +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::fold_many0; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_many0( +/// tag("abc"), +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// )(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// ``` +pub fn fold_many0( + mut f: F, + mut init: H, + mut g: G, +) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, +{ + move |i: I| { + let mut res = init(); + let mut input = i; + + loop { + let i_ = input.clone(); + let len = input.input_len(); + match f.parse(i_) { + Ok((i, o)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0))); + } + + res = g(res, o); + input = i; + } + Err(Err::Error(_)) => { + return Ok((input, res)); + } + Err(e) => { + return Err(e); + } + } + } + } +} + +/// Repeats the embedded parser, calling `g` to gather the results. +/// +/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up, +/// see [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `f` The parser to apply. +/// * `init` A function returning the initial value. +/// * `g` The function that combines a result of `f` with +/// the current accumulator. +/// +/// *Note*: If the parser passed to `many1` accepts empty inputs +/// (like `alpha0` or `digit0`), `many1` will return an error, +/// to prevent going into an infinite loop. +/// +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::multi::fold_many1; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_many1( +/// tag("abc"), +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// )(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1)))); +/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1)))); +/// ``` +pub fn fold_many1( + mut f: F, + mut init: H, + mut g: G, +) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, +{ + move |i: I| { + let _i = i.clone(); + let init = init(); + match f.parse(_i) { + Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1))), + Err(e) => Err(e), + Ok((i1, o1)) => { + let mut acc = g(init, o1); + let mut input = i1; + + loop { + let _input = input.clone(); + let len = input.input_len(); + match f.parse(_input) { + Err(Err::Error(_)) => { + break; + } + Err(e) => return Err(e), + Ok((i, o)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(Err::Failure(E::from_error_kind(i, ErrorKind::Many1))); + } + + acc = g(acc, o); + input = i; + } + } + } + + Ok((input, acc)) + } + } + } +} + +/// Repeats the embedded parser `m..=n` times, calling `g` to gather the results +/// +/// This stops before `n` when the parser returns [`Err::Error`]. To instead chain an error up, see +/// [`cut`][crate::combinator::cut]. +/// +/// # Arguments +/// * `m` The minimum number of iterations. +/// * `n` The maximum number of iterations. +/// * `f` The parser to apply. +/// * `init` A function returning the initial value. +/// * `g` The function that combines a result of `f` with +/// the current accumulator. +/// +/// *Note*: If the parser passed to `many1` accepts empty inputs +/// (like `alpha0` or `digit0`), `many1` will return an error, +/// to prevent going into an infinite loop. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::multi::fold_many_m_n; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_many_m_n( +/// 0, +/// 2, +/// tag("abc"), +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// )(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +pub fn fold_many_m_n( + min: usize, + max: usize, + mut parse: F, + mut init: H, + mut fold: G, +) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, +{ + move |mut input: I| { + if min > max { + return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN))); + } + + let mut acc = init(); + for count in 0..max { + let len = input.input_len(); + match parse.parse(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(Err::Error(E::from_error_kind(tail, ErrorKind::ManyMN))); + } + + acc = fold(acc, value); + input = tail; + } + //FInputXMError: handle failure properly + Err(Err::Error(err)) => { + if count < min { + return Err(Err::Error(E::append(input, ErrorKind::ManyMN, err))); + } else { + break; + } + } + Err(e) => return Err(e), + } + } + + Ok((input, acc)) + } +} + +/// Gets a number from the parser and returns a +/// subslice of the input of that size. +/// If the parser returns `Incomplete`, +/// `length_data` will return an error. +/// # Arguments +/// * `f` The parser to apply. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed, IResult}; +/// use nom::number::complete::be_u16; +/// use nom::multi::length_data; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// length_data(be_u16)(s) +/// } +/// +/// assert_eq!(parser(b"\x00\x03abcefg"), Ok((&b"efg"[..], &b"abc"[..]))); +/// assert_eq!(parser(b"\x00\x03a"), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +pub fn length_data(mut f: F) -> impl FnMut(I) -> IResult +where + I: InputLength + InputTake, + N: ToUsize, + F: Parser, + E: ParseError, +{ + move |i: I| { + let (i, length) = f.parse(i)?; + + let length: usize = length.to_usize(); + + if let Some(needed) = length + .checked_sub(i.input_len()) + .and_then(NonZeroUsize::new) + { + Err(Err::Incomplete(Needed::Size(needed))) + } else { + Ok(i.take_split(length)) + } + } +} + +/// Gets a number from the first parser, +/// takes a subslice of the input of that size, +/// then applies the second parser on that subslice. +/// If the second parser returns `Incomplete`, +/// `length_value` will return an error. +/// # Arguments +/// * `f` The parser to apply. +/// * `g` The parser to apply on the subslice. +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::number::complete::be_u16; +/// use nom::multi::length_value; +/// use nom::bytes::complete::tag; +/// +/// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> { +/// length_value(be_u16, tag("abc"))(s) +/// } +/// +/// assert_eq!(parser(b"\x00\x03abcefg"), Ok((&b"efg"[..], &b"abc"[..]))); +/// assert_eq!(parser(b"\x00\x03123123"), Err(Err::Error(Error::new(&b"123"[..], ErrorKind::Tag)))); +/// assert_eq!(parser(b"\x00\x03a"), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +pub fn length_value(mut f: F, mut g: G) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength + InputTake, + N: ToUsize, + F: Parser, + G: Parser, + E: ParseError, +{ + move |i: I| { + let (i, length) = f.parse(i)?; + + let length: usize = length.to_usize(); + + if let Some(needed) = length + .checked_sub(i.input_len()) + .and_then(NonZeroUsize::new) + { + Err(Err::Incomplete(Needed::Size(needed))) + } else { + let (rest, i) = i.take_split(length); + match g.parse(i.clone()) { + Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))), + Err(e) => Err(e), + Ok((_, o)) => Ok((rest, o)), + } + } + } +} + +/// Gets a number from the first parser, +/// then applies the second parser that many times. +/// # Arguments +/// * `f` The parser to apply to obtain the count. +/// * `g` The parser to apply repeatedly. +/// ```rust +/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; +/// use nom::number::complete::u8; +/// use nom::multi::length_count; +/// use nom::bytes::complete::tag; +/// use nom::combinator::map; +/// +/// fn parser(s: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { +/// length_count(map(u8, |i| { +/// println!("got number: {}", i); +/// i +/// }), tag("abc"))(s) +/// } +/// +/// assert_eq!(parser(&b"\x02abcabcabc"[..]), Ok(((&b"abc"[..], vec![&b"abc"[..], &b"abc"[..]])))); +/// assert_eq!(parser(b"\x03123123123"), Err(Err::Error(Error::new(&b"123123123"[..], ErrorKind::Tag)))); +/// ``` +#[cfg(feature = "alloc")] +pub fn length_count(mut f: F, mut g: G) -> impl FnMut(I) -> IResult, E> +where + I: Clone, + N: ToUsize, + F: Parser, + G: Parser, + E: ParseError, +{ + move |i: I| { + let (i, count) = f.parse(i)?; + let mut input = i.clone(); + let mut res = Vec::new(); + + for _ in 0..count.to_usize() { + let input_ = input.clone(); + match g.parse(input_) { + Ok((i, o)) => { + res.push(o); + input = i; + } + Err(Err::Error(e)) => { + return Err(Err::Error(E::append(i, ErrorKind::Count, e))); + } + Err(e) => { + return Err(e); + } + } + } + + Ok((input, res)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/multi/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/multi/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/multi/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,534 @@ +use super::{length_data, length_value, many0_count, many1_count}; +use crate::{ + bytes::streaming::tag, + character::streaming::digit1 as digit, + error::{ErrorKind, ParseError}, + internal::{Err, IResult, Needed}, + lib::std::str::{self, FromStr}, + number::streaming::{be_u16, be_u8}, + sequence::{pair, tuple}, +}; +#[cfg(feature = "alloc")] +use crate::{ + lib::std::vec::Vec, + multi::{ + count, fold_many0, fold_many1, fold_many_m_n, length_count, many0, many1, many_m_n, many_till, + separated_list0, separated_list1, + }, +}; + +#[test] +#[cfg(feature = "alloc")] +fn separated_list0_test() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(","), tag("abcd"))(i) + } + fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(","), tag(""))(i) + } + fn empty_sep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(""), tag("abc"))(i) + } + fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(".."), tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b",,abc"[..]; + let e = &b"abcd,abcd,ef"[..]; + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + let i = &b"abcabc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(b), Ok((&b"ef"[..], res2))); + assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new()))); + let res3 = vec![&b""[..], &b""[..], &b""[..]]; + assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3))); + let i_err_pos = &i[3..]; + assert_eq!( + empty_sep(i), + Err(Err::Error(error_position!( + i_err_pos, + ErrorKind::SeparatedList + ))) + ); + let res4 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(e), Ok((&b",ef"[..], res4))); + + assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn separated_list1_test() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list1(tag(","), tag("abcd"))(i) + } + fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list1(tag(".."), tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b"abcd,abcd,ef"[..]; + + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(b), Ok((&b"ef"[..], res2))); + assert_eq!( + multi(c), + Err(Err::Error(error_position!(c, ErrorKind::Tag))) + ); + let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(d), Ok((&b",ef"[..], res3))); + + assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn many0_test() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(tag("abcd"))(i) + } + fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(tag(""))(i) + } + + assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); + assert_eq!( + multi(&b"abcdabcdefgh"[..]), + Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new()))); + assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!( + multi_empty(&b"abcdef"[..]), + Err(Err::Error(error_position!( + &b"abcdef"[..], + ErrorKind::Many0 + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn many1_test() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many1(tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(b), Ok((&b"efgh"[..], res2))); + assert_eq!( + multi(c), + Err(Err::Error(error_position!(c, ErrorKind::Tag))) + ); + assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn many_till_test() { + fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { + many_till(tag("abcd"), tag("efgh"))(i) + } + + let a = b"abcdabcdefghabcd"; + let b = b"efghabcd"; + let c = b"azerty"; + + let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]); + let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]); + assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a))); + assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b))); + assert_eq!( + multi(&c[..]), + Err(Err::Error(error_node_position!( + &c[..], + ErrorKind::ManyTill, + error_position!(&c[..], ErrorKind::Tag) + ))) + ); +} + +#[test] +#[cfg(feature = "std")] +fn infinite_many() { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + println!("input: {:?}", input); + Err(Err::Error(error_position!(input, ErrorKind::Tag))) + } + + // should not go into an infinite loop + fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(tst)(i) + } + let a = &b"abcdef"[..]; + assert_eq!(multi0(a), Ok((a, Vec::new()))); + + fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many1(tst)(i) + } + let a = &b"abcdef"[..]; + assert_eq!( + multi1(a), + Err(Err::Error(error_position!(a, ErrorKind::Tag))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn many_m_n_test() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many_m_n(2, 4, tag("Abcd"))(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(c), Ok((&b"efgh"[..], res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3))); + assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn count_test() { + const TIMES: usize = 2; + fn cnt_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + count(tag("abc"), TIMES)(i) + } + + assert_eq!( + cnt_2(&b"abcabcabcdef"[..]), + Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]])) + ); + assert_eq!(cnt_2(&b"ab"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(cnt_2(&b"abcab"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!( + cnt_2(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + cnt_2(&b"xxxabcabcdef"[..]), + Err(Err::Error(error_position!( + &b"xxxabcabcdef"[..], + ErrorKind::Tag + ))) + ); + assert_eq!( + cnt_2(&b"abcxxxabcdef"[..]), + Err(Err::Error(error_position!( + &b"xxxabcdef"[..], + ErrorKind::Tag + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn count_zero() { + const TIMES: usize = 0; + fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + count(tag("abc"), TIMES)(i) + } + + let done = &b"abcabcabcdef"[..]; + let parsed_done = Vec::new(); + let rest = done; + let incomplete_1 = &b"ab"[..]; + let parsed_incompl_1 = Vec::new(); + let incomplete_2 = &b"abcab"[..]; + let parsed_incompl_2 = Vec::new(); + let error = &b"xxx"[..]; + let error_remain = &b"xxx"[..]; + let parsed_err = Vec::new(); + let error_1 = &b"xxxabcabcdef"[..]; + let parsed_err_1 = Vec::new(); + let error_1_remain = &b"xxxabcabcdef"[..]; + let error_2 = &b"abcxxxabcdef"[..]; + let parsed_err_2 = Vec::new(); + let error_2_remain = &b"abcxxxabcdef"[..]; + + assert_eq!(counter_2(done), Ok((rest, parsed_done))); + assert_eq!( + counter_2(incomplete_1), + Ok((incomplete_1, parsed_incompl_1)) + ); + assert_eq!( + counter_2(incomplete_2), + Ok((incomplete_2, parsed_incompl_2)) + ); + assert_eq!(counter_2(error), Ok((error_remain, parsed_err))); + assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1))); + assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2))); +} + +#[derive(Debug, Clone, PartialEq)] +pub struct NilError; + +impl From<(I, ErrorKind)> for NilError { + fn from(_: (I, ErrorKind)) -> Self { + NilError + } +} + +impl ParseError for NilError { + fn from_error_kind(_: I, _: ErrorKind) -> NilError { + NilError + } + fn append(_: I, _: ErrorKind, _: NilError) -> NilError { + NilError + } +} + +fn number(i: &[u8]) -> IResult<&[u8], u32> { + use crate::combinator::map_res; + + map_res(map_res(digit, str::from_utf8), FromStr::from_str)(i) +} + +#[test] +#[cfg(feature = "alloc")] +fn length_count_test() { + fn cnt(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + length_count(number, tag("abc"))(i) + } + + assert_eq!( + cnt(&b"2abcabcabcdef"[..]), + Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]])) + ); + assert_eq!(cnt(&b"2ab"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(cnt(&b"3abcab"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!( + cnt(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit))) + ); + assert_eq!( + cnt(&b"2abcxxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn length_data_test() { + fn take(i: &[u8]) -> IResult<&[u8], &[u8]> { + length_data(number)(i) + } + + assert_eq!( + take(&b"6abcabcabcdef"[..]), + Ok((&b"abcdef"[..], &b"abcabc"[..])) + ); + assert_eq!(take(&b"3ab"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!( + take(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit))) + ); + assert_eq!(take(&b"2abcxxx"[..]), Ok((&b"cxxx"[..], &b"ab"[..]))); +} + +#[test] +fn length_value_test() { + fn length_value_1(i: &[u8]) -> IResult<&[u8], u16> { + length_value(be_u8, be_u16)(i) + } + fn length_value_2(i: &[u8]) -> IResult<&[u8], (u8, u8)> { + length_value(be_u8, tuple((be_u8, be_u8)))(i) + } + + let i1 = [0, 5, 6]; + assert_eq!( + length_value_1(&i1), + Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete))) + ); + assert_eq!( + length_value_2(&i1), + Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete))) + ); + + let i2 = [1, 5, 6, 3]; + assert_eq!( + length_value_1(&i2), + Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete))) + ); + assert_eq!( + length_value_2(&i2), + Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete))) + ); + + let i3 = [2, 5, 6, 3, 4, 5, 7]; + assert_eq!(length_value_1(&i3), Ok((&i3[3..], 1286))); + assert_eq!(length_value_2(&i3), Ok((&i3[3..], (5, 6)))); + + let i4 = [3, 5, 6, 3, 4, 5]; + assert_eq!(length_value_1(&i4), Ok((&i4[4..], 1286))); + assert_eq!(length_value_2(&i4), Ok((&i4[4..], (5, 6)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_many0_test() { + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i) + } + fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold_many0(tag(""), Vec::new, fold_into_vec)(i) + } + + assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]]))); + assert_eq!( + multi(&b"abcdabcdefgh"[..]), + Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new()))); + assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4)))); + assert_eq!( + multi_empty(&b"abcdef"[..]), + Err(Err::Error(error_position!( + &b"abcdef"[..], + ErrorKind::Many0 + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_many1_test() { + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(a), Ok((&b"ef"[..], res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(b), Ok((&b"efgh"[..], res2))); + assert_eq!( + multi(c), + Err(Err::Error(error_position!(c, ErrorKind::Many1))) + ); + assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_many_m_n_test() { + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(a), + Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(b), Ok((&b"efgh"[..], res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(c), Ok((&b"efgh"[..], res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3))); + assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2)))); +} + +#[test] +fn many0_count_test() { + fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> { + many0_count(pair(digit, tag(",")))(i) + } + + assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1))); + + assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + + assert_eq!( + count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); + + assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0))); +} + +#[test] +fn many1_count_test() { + fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> { + many1_count(pair(digit, tag(",")))(i) + } + + assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + + assert_eq!( + count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); + + assert_eq!( + count1_nums(&b"hello"[..]), + Err(Err::Error(error_position!( + &b"hello"[..], + ErrorKind::Many1Count + ))) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/complete.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/complete.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/complete.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/complete.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2126 @@ +//! Parsers recognizing numbers, complete input version + +use crate::branch::alt; +use crate::bytes::complete::tag; +use crate::character::complete::{char, digit1, sign}; +use crate::combinator::{cut, map, opt, recognize}; +use crate::error::ParseError; +use crate::error::{make_error, ErrorKind}; +use crate::internal::*; +use crate::lib::std::ops::{Range, RangeFrom, RangeTo}; +use crate::sequence::{pair, tuple}; +use crate::traits::{ + AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice, +}; + +/// Recognizes an unsigned 1 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u8; +/// +/// let parser = |s| { +/// be_u8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 2 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u16; +/// +/// let parser = |s| { +/// be_u16(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 2; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u16; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u16; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 3 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u24; +/// +/// let parser = |s| { +/// be_u24(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 3; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u32; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u32; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 4 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u32; +/// +/// let parser = |s| { +/// be_u32(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 4; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u32; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u32; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 8 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u64; +/// +/// let parser = |s| { +/// be_u64(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 8; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u64; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u64; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 16 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_u128; +/// +/// let parser = |s| { +/// be_u128(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_u128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 16; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u128; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u128; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a signed 1 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i8; +/// +/// let parser = |s| { +/// be_i8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u8.map(|x| x as i8).parse(input) +} + +/// Recognizes a big endian signed 2 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i16; +/// +/// let parser = |s| { +/// be_i16(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u16.map(|x| x as i16).parse(input) +} + +/// Recognizes a big endian signed 3 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i24; +/// +/// let parser = |s| { +/// be_i24(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + // Same as the unsigned version but we need to sign-extend manually here + be_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse(input) +} + +/// Recognizes a big endian signed 4 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i32; +/// +/// let parser = |s| { +/// be_i32(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u32.map(|x| x as i32).parse(input) +} + +/// Recognizes a big endian signed 8 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i64; +/// +/// let parser = |s| { +/// be_i64(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u64.map(|x| x as i64).parse(input) +} + +/// Recognizes a big endian signed 16 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_i128; +/// +/// let parser = |s| { +/// be_i128(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_i128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u128.map(|x| x as i128).parse(input) +} + +/// Recognizes an unsigned 1 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u8; +/// +/// let parser = |s| { +/// le_u8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 2 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u16; +/// +/// let parser = |s| { +/// le_u16(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 2; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u16; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u16) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 3 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u24; +/// +/// let parser = |s| { +/// le_u24(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 3; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u32; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u32) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 4 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u32; +/// +/// let parser = |s| { +/// le_u32(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 4; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u32; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u32) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 8 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u64; +/// +/// let parser = |s| { +/// le_u64(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 8; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u64; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u64) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 16 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_u128; +/// +/// let parser = |s| { +/// le_u128(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_u128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 16; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let mut res = 0u128; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u128) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a signed 1 byte integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i8; +/// +/// let parser = |s| { +/// le_i8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u8.map(|x| x as i8).parse(input) +} + +/// Recognizes a little endian signed 2 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i16; +/// +/// let parser = |s| { +/// le_i16(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u16.map(|x| x as i16).parse(input) +} + +/// Recognizes a little endian signed 3 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i24; +/// +/// let parser = |s| { +/// le_i24(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + // Same as the unsigned version but we need to sign-extend manually here + le_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse(input) +} + +/// Recognizes a little endian signed 4 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i32; +/// +/// let parser = |s| { +/// le_i32(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u32.map(|x| x as i32).parse(input) +} + +/// Recognizes a little endian signed 8 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i64; +/// +/// let parser = |s| { +/// le_i64(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u64.map(|x| x as i64).parse(input) +} + +/// Recognizes a little endian signed 16 bytes integer. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_i128; +/// +/// let parser = |s| { +/// le_i128(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_i128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u128.map(|x| x as i128).parse(input) +} + +/// Recognizes an unsigned 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u8; +/// +/// let parser = |s| { +/// u8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Error(make_error(input, ErrorKind::Eof))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes an unsigned 2 bytes integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u16 integer. +/// *complete version*: returns an error if there is not enough input data +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u16; +/// +/// let be_u16 = |s| { +/// u16(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_u16 = |s| { +/// u16(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u16, + crate::number::Endianness::Little => le_u16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u16, + } +} + +/// Recognizes an unsigned 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u24 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u24; +/// +/// let be_u24 = |s| { +/// u24(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_u24 = |s| { +/// u24(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u24, + crate::number::Endianness::Little => le_u24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u24, + } +} + +/// Recognizes an unsigned 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u32 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u32; +/// +/// let be_u32 = |s| { +/// u32(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_u32 = |s| { +/// u32(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u32, + crate::number::Endianness::Little => le_u32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u32, + } +} + +/// Recognizes an unsigned 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u64 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u64; +/// +/// let be_u64 = |s| { +/// u64(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_u64 = |s| { +/// u64(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u64, + crate::number::Endianness::Little => le_u64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u64, + } +} + +/// Recognizes an unsigned 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u128 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::u128; +/// +/// let be_u128 = |s| { +/// u128(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_u128 = |s| { +/// u128(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u128, + crate::number::Endianness::Little => le_u128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u128, + } +} + +/// Recognizes a signed 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i8; +/// +/// let parser = |s| { +/// i8(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i8>(i: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + u8.map(|x| x as i8).parse(i) +} + +/// Recognizes a signed 2 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i16 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i16; +/// +/// let be_i16 = |s| { +/// i16(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_i16 = |s| { +/// i16(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i16, + crate::number::Endianness::Little => le_i16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i16, + } +} + +/// Recognizes a signed 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i24 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i24; +/// +/// let be_i24 = |s| { +/// i24(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_i24 = |s| { +/// i24(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i24, + crate::number::Endianness::Little => le_i24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i24, + } +} + +/// Recognizes a signed 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i32 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i32; +/// +/// let be_i32 = |s| { +/// i32(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_i32 = |s| { +/// i32(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i32, + crate::number::Endianness::Little => le_i32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i32, + } +} + +/// Recognizes a signed 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i64 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i64; +/// +/// let be_i64 = |s| { +/// i64(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_i64 = |s| { +/// i64(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i64, + crate::number::Endianness::Little => le_i64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i64, + } +} + +/// Recognizes a signed 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i128 integer. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::i128; +/// +/// let be_i128 = |s| { +/// i128(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// +/// let le_i128 = |s| { +/// i128(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i128, + crate::number::Endianness::Little => le_i128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i128, + } +} + +/// Recognizes a big endian 4 bytes floating point number. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_f32; +/// +/// let parser = |s| { +/// be_f32(s) +/// }; +/// +/// assert_eq!(parser(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_f32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match be_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } +} + +/// Recognizes a big endian 8 bytes floating point number. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::be_f64; +/// +/// let parser = |s| { +/// be_f64(s) +/// }; +/// +/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn be_f64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match be_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } +} + +/// Recognizes a little endian 4 bytes floating point number. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_f32; +/// +/// let parser = |s| { +/// le_f32(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_f32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match le_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } +} + +/// Recognizes a little endian 8 bytes floating point number. +/// +/// *Complete version*: Returns an error if there is not enough input data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::le_f64; +/// +/// let parser = |s| { +/// le_f64(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn le_f64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match le_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } +} + +/// Recognizes a 4 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f32 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f32 float. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::f32; +/// +/// let be_f32 = |s| { +/// f32(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// +/// let le_f32 = |s| { +/// f32(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_f32, + crate::number::Endianness::Little => le_f32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f32, + } +} + +/// Recognizes an 8 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f64 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f64 float. +/// *complete version*: returns an error if there is not enough input data +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::f64; +/// +/// let be_f64 = |s| { +/// f64(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// +/// let le_f64 = |s| { +/// f64(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof)))); +/// ``` +#[inline] +pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_f64, + crate::number::Endianness::Little => le_f64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f64, + } +} + +/// Recognizes a hex-encoded integer. +/// +/// *Complete version*: Will parse until the end of input if it has less than 8 bytes. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::hex_u32; +/// +/// let parser = |s| { +/// hex_u32(s) +/// }; +/// +/// assert_eq!(parser(&b"01AE"[..]), Ok((&b""[..], 0x01AE))); +/// assert_eq!(parser(&b"abc"[..]), Ok((&b""[..], 0x0ABC))); +/// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA)))); +/// ``` +#[inline] +pub fn hex_u32<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], u32, E> { + let (i, o) = crate::bytes::complete::is_a(&b"0123456789abcdefABCDEF"[..])(input)?; + // Do not parse more than 8 characters for a u32 + let (parsed, remaining) = if o.len() <= 8 { + (o, i) + } else { + (&input[..8], &input[8..]) + }; + + let res = parsed + .iter() + .rev() + .enumerate() + .map(|(k, &v)| { + let digit = v as char; + digit.to_digit(16).unwrap_or(0) << (k * 4) + }) + .sum(); + + Ok((remaining, res)) +} + +/// Recognizes floating point number in a byte string and returns the corresponding slice. +/// +/// *Complete version*: Can parse until the end of input. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::recognize_float; +/// +/// let parser = |s| { +/// recognize_float(s) +/// }; +/// +/// assert_eq!(parser("11e-1"), Ok(("", "11e-1"))); +/// assert_eq!(parser("123E-02"), Ok(("", "123E-02"))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", "123"))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char)))); +/// ``` +#[rustfmt::skip] +pub fn recognize_float>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter, + ::Item: AsChar, + T: InputTakeAtPosition, + ::Item: AsChar, +{ + recognize( + tuple(( + opt(alt((char('+'), char('-')))), + alt(( + map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), + map(tuple((char('.'), digit1)), |_| ()) + )), + opt(tuple(( + alt((char('e'), char('E'))), + opt(alt((char('+'), char('-')))), + cut(digit1) + ))) + )) + )(input) +} + +// workaround until issues with minimal-lexical are fixed +#[doc(hidden)] +pub fn recognize_float_or_exceptions>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter + InputTake + Compare<&'static str>, + ::Item: AsChar, + T: InputTakeAtPosition, + ::Item: AsChar, +{ + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed), + }) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + ))(input) +} + +/// Recognizes a floating point number in text format +/// +/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input +/// data. +/// +/// *Complete version*: Can parse until the end of input. +/// +pub fn recognize_float_parts>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: Clone + Offset, + T: InputIter + InputTake, + ::Item: AsChar + Copy, + T: InputTakeAtPosition + InputLength, + ::Item: AsChar, + T: for<'a> Compare<&'a [u8]>, + T: AsBytes, +{ + let (i, sign) = sign(input.clone())?; + + //let (i, zeroes) = take_while(|c: ::Item| c.as_char() == '0')(i)?; + let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') { + Some(index) => i.take_split(index), + None => i.take_split(i.input_len()), + }; + //let (i, mut integer) = digit0(i)?; + let (i, mut integer) = match i + .as_bytes() + .iter() + .position(|c| !(*c >= b'0' && *c <= b'9')) + { + Some(index) => i.take_split(index), + None => i.take_split(i.input_len()), + }; + + if integer.input_len() == 0 && zeroes.input_len() > 0 { + // keep the last zero if integer is empty + integer = zeroes.slice(zeroes.input_len() - 1..); + } + + let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, fraction) = if opt_dot.is_none() { + let i2 = i.clone(); + (i2, i.slice(..0)) + } else { + // match number, trim right zeroes + let mut zero_count = 0usize; + let mut position = None; + for (pos, c) in i.as_bytes().iter().enumerate() { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { + zero_count += 1; + } else { + zero_count = 0; + } + } else { + position = Some(pos); + break; + } + } + + let position = position.unwrap_or(i.input_len()); + + let index = if zero_count == 0 { + position + } else if zero_count == position { + position - zero_count + 1 + } else { + position - zero_count + }; + + (i.slice(position..), i.slice(..index)) + }; + + if integer.input_len() == 0 && fraction.input_len() == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Float))); + } + + let i2 = i.clone(); + let (i, e) = match i.as_bytes().iter().next() { + Some(b'e') => (i.slice(1..), true), + Some(b'E') => (i.slice(1..), true), + _ => (i, false), + }; + + let (i, exp) = if e { + cut(crate::character::complete::i32)(i)? + } else { + (i2, 0) + }; + + Ok((i, (sign, integer, fraction, exp))) +} + +use crate::traits::ParseTo; + +/// Recognizes floating point number in text format and returns a f32. +/// +/// *Complete version*: Can parse until the end of input. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::float; +/// +/// let parser = |s| { +/// float(s) +/// }; +/// +/// assert_eq!(parser("11e-1"), Ok(("", 1.1))); +/// assert_eq!(parser("123E-02"), Ok(("", 1.23))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float)))); +/// ``` +pub fn float>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: Clone + Offset + ParseTo + Compare<&'static str>, + T: InputIter + InputLength + InputTake, + ::Item: AsChar + Copy, + ::IterElem: Clone, + T: InputTakeAtPosition, + ::Item: AsChar, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + /* + let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; + + let mut float: f32 = minimal_lexical::parse_float( + integer.as_bytes().iter(), + fraction.as_bytes().iter(), + exponent, + ); + if !sign { + float = -float; + } + + Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => Ok((i, f)), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } +} + +/// Recognizes floating point number in text format and returns a f64. +/// +/// *Complete version*: Can parse until the end of input. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::double; +/// +/// let parser = |s| { +/// double(s) +/// }; +/// +/// assert_eq!(parser("11e-1"), Ok(("", 1.1))); +/// assert_eq!(parser("123E-02"), Ok(("", 1.23))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float)))); +/// ``` +pub fn double>(input: T) -> IResult +where + T: Slice> + Slice> + Slice>, + T: Clone + Offset + ParseTo + Compare<&'static str>, + T: InputIter + InputLength + InputTake, + ::Item: AsChar + Copy, + ::IterElem: Clone, + T: InputTakeAtPosition, + ::Item: AsChar, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + /* + let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; + + let mut float: f64 = minimal_lexical::parse_float( + integer.as_bytes().iter(), + fraction.as_bytes().iter(), + exponent, + ); + if !sign { + float = -float; + } + + Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => Ok((i, f)), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::error::ErrorKind; + use crate::internal::Err; + use proptest::prelude::*; + + macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; + ); + + #[test] + fn i8_tests() { + assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn be_i8_tests() { + assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn be_i16_tests() { + assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); + } + + #[test] + fn be_u24_tests() { + assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + be_u24(&[0x12, 0x34, 0x56][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } + + #[test] + fn be_i24_tests() { + assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + be_i24(&[0xED, 0xCB, 0xAA][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + } + + #[test] + fn be_i32_tests() { + assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + be_i32(&[0x80, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } + + #[test] + fn be_i64_tests() { + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } + + #[test] + fn be_i128_tests() { + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i128( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i128( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } + + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn le_i16_tests() { + assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); + } + + #[test] + fn le_u24_tests() { + assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + le_u24(&[0x56, 0x34, 0x12][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } + + #[test] + fn le_i24_tests() { + assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + le_i24(&[0xAA, 0xCB, 0xED][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + } + + #[test] + fn le_i32_tests() { + assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + le_i32(&[0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } + + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } + + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } + + #[test] + fn be_f32_tests() { + assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), + Ok((&b""[..], 185_728_392_f32)) + ); + } + + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } + + #[test] + fn le_f32_tests() { + assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), + Ok((&b""[..], 185_728_392_f32)) + ); + } + + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } + + #[test] + fn hex_u32_tests() { + assert_parse!( + hex_u32(&b";"[..]), + Err(Err::Error(error_position!(&b";"[..], ErrorKind::IsA))) + ); + assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); + assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); + assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); + assert_parse!( + hex_u32(&b"c5a31be201;"[..]), + Ok((&b"01;"[..], 3_315_801_058)) + ); + assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); + assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); + assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af))); + } + + #[test] + #[cfg(feature = "std")] + fn float_test() { + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + let larger = format!("{}", test); + assert_parse!(recognize_float(&larger[..]), Ok(("", test))); + + assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32))); + assert_parse!(float(&larger[..]), Ok(("", expected32))); + + assert_parse!(double(larger.as_bytes()), Ok((&b""[..], expected64))); + assert_parse!(double(&larger[..]), Ok(("", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + recognize_float(remaining_exponent), + Err(Err::Failure(("", ErrorKind::Digit))) + ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); + } + + #[test] + fn configurable_endianness() { + use crate::number::Endianness; + + fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Big)(i) + } + fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Little)(i) + } + assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); + assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); + + fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 302_014_464_u32)) + ); + assert_eq!( + le_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 6_291_474_u32)) + ); + + fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_666_770_u64)) + ); + + fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Little)(i) + } + assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); + assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); + + fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 6_296_064_i32)) + ); + + fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_732_032_i64)) + ); + } + + #[cfg(feature = "std")] + fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + match recognize_float_or_exceptions(i) { + Err(e) => Err(e), + Ok((i, s)) => { + if s.is_empty() { + return Err(Err::Error(())); + } + match s.parse_to() { + Some(n) => Ok((i, n)), + None => Err(Err::Error(())), + } + } + } + } + + proptest! { + #[test] + #[cfg(feature = "std")] + fn floats(s in "\\PC*") { + println!("testing {}", s); + let res1 = parse_f64(&s); + let res2 = double::<_, ()>(s.as_str()); + assert_eq!(res1, res2); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +//! Parsers recognizing numbers + +pub mod complete; +pub mod streaming; + +/// Configurable endianness +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Endianness { + /// Big endian + Big, + /// Little endian + Little, + /// Will match the host's endianness + Native, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/streaming.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/streaming.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/number/streaming.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/number/streaming.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2206 @@ +//! Parsers recognizing numbers, streaming version + +use crate::branch::alt; +use crate::bytes::streaming::tag; +use crate::character::streaming::{char, digit1, sign}; +use crate::combinator::{cut, map, opt, recognize}; +use crate::error::{ErrorKind, ParseError}; +use crate::internal::*; +use crate::lib::std::ops::{RangeFrom, RangeTo}; +use crate::sequence::{pair, tuple}; +use crate::traits::{ + AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice, +}; + +/// Recognizes an unsigned 1 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u8; +/// +/// let parser = |s| { +/// be_u8::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(1))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 2 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u16; +/// +/// let parser = |s| { +/// be_u16::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_u16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 2; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u16; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u16; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 3 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u24; +/// +/// let parser = |s| { +/// be_u24::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn be_u24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 3; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u32; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u32; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 4 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u32; +/// +/// let parser = |s| { +/// be_u32::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_u32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 4; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u32; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u32; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 8 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u64; +/// +/// let parser = |s| { +/// be_u64::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_u64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 8; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u64; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u64; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a big endian unsigned 16 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_u128; +/// +/// let parser = |s| { +/// be_u128::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn be_u128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 16; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u128; + for byte in input.iter_elements().take(bound) { + res = (res << 8) + byte as u128; + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a signed 1 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i8; +/// +/// let parser = be_i8::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn be_i8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u8.map(|x| x as i8).parse(input) +} + +/// Recognizes a big endian signed 2 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i16; +/// +/// let parser = be_i16::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn be_i16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u16.map(|x| x as i16).parse(input) +} + +/// Recognizes a big endian signed 3 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i24; +/// +/// let parser = be_i24::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_i24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + // Same as the unsigned version but we need to sign-extend manually here + be_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse(input) +} + +/// Recognizes a big endian signed 4 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i32; +/// +/// let parser = be_i32::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(4)))); +/// ``` +#[inline] +pub fn be_i32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u32.map(|x| x as i32).parse(input) +} + +/// Recognizes a big endian signed 8 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i64; +/// +/// let parser = be_i64::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_i64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u64.map(|x| x as i64).parse(input) +} + +/// Recognizes a big endian signed 16 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_i128; +/// +/// let parser = be_i128::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn be_i128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + be_u128.map(|x| x as i128).parse(input) +} + +/// Recognizes an unsigned 1 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u8; +/// +/// let parser = le_u8::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(1))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 2 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u16; +/// +/// let parser = |s| { +/// le_u16::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_u16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 2; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u16; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u16) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 3 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u24; +/// +/// let parser = |s| { +/// le_u24::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn le_u24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 3; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u32; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u32) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 4 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u32; +/// +/// let parser = |s| { +/// le_u32::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_u32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 4; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u32; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u32) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 8 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u64; +/// +/// let parser = |s| { +/// le_u64::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_u64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 8; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u64; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u64) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a little endian unsigned 16 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_u128; +/// +/// let parser = |s| { +/// le_u128::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn le_u128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 16; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(bound - input.input_len()))) + } else { + let mut res = 0u128; + for (index, byte) in input.iter_indices().take(bound) { + res += (byte as u128) << (8 * index); + } + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes a signed 1 byte integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i8; +/// +/// let parser = le_i8::<_, (_, ErrorKind)>; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_i8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u8.map(|x| x as i8).parse(input) +} + +/// Recognizes a little endian signed 2 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i16; +/// +/// let parser = |s| { +/// le_i16::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn le_i16>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u16.map(|x| x as i16).parse(input) +} + +/// Recognizes a little endian signed 3 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i24; +/// +/// let parser = |s| { +/// le_i24::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn le_i24>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + // Same as the unsigned version but we need to sign-extend manually here + le_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse(input) +} + +/// Recognizes a little endian signed 4 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i32; +/// +/// let parser = |s| { +/// le_i32::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_i32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u32.map(|x| x as i32).parse(input) +} + +/// Recognizes a little endian signed 8 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i64; +/// +/// let parser = |s| { +/// le_i64::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_i64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u64.map(|x| x as i64).parse(input) +} + +/// Recognizes a little endian signed 16 bytes integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_i128; +/// +/// let parser = |s| { +/// le_i128::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); +/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn le_i128>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + le_u128.map(|x| x as i128).parse(input) +} + +/// Recognizes an unsigned 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u8; +/// +/// let parser = |s| { +/// u8::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn u8>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + let bound: usize = 1; + if input.input_len() < bound { + Err(Err::Incomplete(Needed::new(1))) + } else { + let res = input.iter_elements().next().unwrap(); + + Ok((input.slice(bound..), res)) + } +} + +/// Recognizes an unsigned 2 bytes integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u16 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u16; +/// +/// let be_u16 = |s| { +/// u16::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_u16 = |s| { +/// u16::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u16, + crate::number::Endianness::Little => le_u16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u16, + } +} + +/// Recognizes an unsigned 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u24 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u24; +/// +/// let be_u24 = |s| { +/// u24::<_,(_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// +/// let le_u24 = |s| { +/// u24::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u24, + crate::number::Endianness::Little => le_u24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u24, + } +} + +/// Recognizes an unsigned 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u32 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u32; +/// +/// let be_u32 = |s| { +/// u32::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// +/// let le_u32 = |s| { +/// u32::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u32, + crate::number::Endianness::Little => le_u32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u32, + } +} + +/// Recognizes an unsigned 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u64 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u64; +/// +/// let be_u64 = |s| { +/// u64::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// +/// let le_u64 = |s| { +/// u64::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u64, + crate::number::Endianness::Little => le_u64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u64, + } +} + +/// Recognizes an unsigned 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian u128 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::u128; +/// +/// let be_u128 = |s| { +/// u128::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// +/// let le_u128 = |s| { +/// u128::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_u128, + crate::number::Endianness::Little => le_u128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u128, + } +} + +/// Recognizes a signed 1 byte integer +/// +/// Note that endianness does not apply to 1 byte numbers. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i8; +/// +/// let parser = |s| { +/// i8::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00))); +/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn i8>(i: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + u8.map(|x| x as i8).parse(i) +} + +/// Recognizes a signed 2 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i16 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i16 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i16; +/// +/// let be_i16 = |s| { +/// i16::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003))); +/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_i16 = |s| { +/// i16::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300))); +/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i16, + crate::number::Endianness::Little => le_i16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i16, + } +} + +/// Recognizes a signed 3 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i24 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i24 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i24; +/// +/// let be_i24 = |s| { +/// i24::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305))); +/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// +/// let le_i24 = |s| { +/// i24::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300))); +/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2)))); +/// ``` +#[inline] +pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i24, + crate::number::Endianness::Little => le_i24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i24, + } +} + +/// Recognizes a signed 4 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i32 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i32 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i32; +/// +/// let be_i32 = |s| { +/// i32::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507))); +/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// +/// let le_i32 = |s| { +/// i32::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300))); +/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i32, + crate::number::Endianness::Little => le_i32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i32, + } +} + +/// Recognizes a signed 8 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i64 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i64 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i64; +/// +/// let be_i64 = |s| { +/// i64::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607))); +/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// +/// let le_i64 = |s| { +/// i64::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100))); +/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i64, + crate::number::Endianness::Little => le_i64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i64, + } +} + +/// Recognizes a signed 16 byte integer +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i128 integer, +/// otherwise if `nom::number::Endianness::Little` parse a little endian i128 integer. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::i128; +/// +/// let be_i128 = |s| { +/// i128::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607))); +/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// +/// let le_i128 = |s| { +/// i128::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100))); +/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15)))); +/// ``` +#[inline] +pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_i128, + crate::number::Endianness::Little => le_i128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i128, + } +} + +/// Recognizes a big endian 4 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_f32; +/// +/// let parser = |s| { +/// be_f32::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00][..]), Ok((&b""[..], 2.640625))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn be_f32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match be_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } +} + +/// Recognizes a big endian 8 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::be_f64; +/// +/// let parser = |s| { +/// be_f64::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn be_f64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match be_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } +} + +/// Recognizes a little endian 4 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_f32; +/// +/// let parser = |s| { +/// le_f32::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3)))); +/// ``` +#[inline] +pub fn le_f32>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match le_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } +} + +/// Recognizes a little endian 8 bytes floating point number. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::le_f64; +/// +/// let parser = |s| { +/// le_f64::<_, (_, ErrorKind)>(s) +/// }; +/// +/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 3145728.0))); +/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7)))); +/// ``` +#[inline] +pub fn le_f64>(input: I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match le_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } +} + +/// Recognizes a 4 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f32 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f32 float. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::f32; +/// +/// let be_f32 = |s| { +/// f32::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// +/// let le_f32 = |s| { +/// f32::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1)))); +/// ``` +#[inline] +pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_f32, + crate::number::Endianness::Little => le_f32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f32, + } +} + +/// Recognizes an 8 byte floating point number +/// +/// If the parameter is `nom::number::Endianness::Big`, parse a big endian f64 float, +/// otherwise if `nom::number::Endianness::Little` parse a little endian f64 float. +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::f64; +/// +/// let be_f64 = |s| { +/// f64::<_, (_, ErrorKind)>(nom::number::Endianness::Big)(s) +/// }; +/// +/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5)))); +/// +/// let le_f64 = |s| { +/// f64::<_, (_, ErrorKind)>(nom::number::Endianness::Little)(s) +/// }; +/// +/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5))); +/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5)))); +/// ``` +#[inline] +pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult +where + I: Slice> + InputIter + InputLength, +{ + match endian { + crate::number::Endianness::Big => be_f64, + crate::number::Endianness::Little => le_f64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f64, + } +} + +/// Recognizes a hex-encoded integer. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::hex_u32; +/// +/// let parser = |s| { +/// hex_u32(s) +/// }; +/// +/// assert_eq!(parser(b"01AE;"), Ok((&b";"[..], 0x01AE))); +/// assert_eq!(parser(b"abc"), Err(Err::Incomplete(Needed::new(1)))); +/// assert_eq!(parser(b"ggg"), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA)))); +/// ``` +#[inline] +pub fn hex_u32<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], u32, E> { + let (i, o) = crate::bytes::streaming::is_a(&b"0123456789abcdefABCDEF"[..])(input)?; + + // Do not parse more than 8 characters for a u32 + let (parsed, remaining) = if o.len() <= 8 { + (o, i) + } else { + (&input[..8], &input[8..]) + }; + + let res = parsed + .iter() + .rev() + .enumerate() + .map(|(k, &v)| { + let digit = v as char; + digit.to_digit(16).unwrap_or(0) << (k * 4) + }) + .sum(); + + Ok((remaining, res)) +} + +/// Recognizes a floating point number in text format and returns the corresponding part of the input. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if it reaches the end of input. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// use nom::number::streaming::recognize_float; +/// +/// let parser = |s| { +/// recognize_float(s) +/// }; +/// +/// assert_eq!(parser("11e-1;"), Ok((";", "11e-1"))); +/// assert_eq!(parser("123E-02;"), Ok((";", "123E-02"))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", "123"))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char)))); +/// ``` +#[rustfmt::skip] +pub fn recognize_float>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter, + ::Item: AsChar, + T: InputTakeAtPosition + InputLength, + ::Item: AsChar +{ + recognize( + tuple(( + opt(alt((char('+'), char('-')))), + alt(( + map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), + map(tuple((char('.'), digit1)), |_| ()) + )), + opt(tuple(( + alt((char('e'), char('E'))), + opt(alt((char('+'), char('-')))), + cut(digit1) + ))) + )) + )(input) +} + +// workaround until issues with minimal-lexical are fixed +#[doc(hidden)] +pub fn recognize_float_or_exceptions>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter + InputTake + InputLength + Compare<&'static str>, + ::Item: AsChar, + T: InputTakeAtPosition, + ::Item: AsChar, +{ + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed), + }) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + ))(input) +} + +/// Recognizes a floating point number in text format +/// +/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input +/// data. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +pub fn recognize_float_parts>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter + crate::traits::ParseTo, + ::Item: AsChar, + T: InputTakeAtPosition + InputTake + InputLength, + ::Item: AsChar, + T: for<'a> Compare<&'a [u8]>, + T: AsBytes, +{ + let (i, sign) = sign(input.clone())?; + + //let (i, zeroes) = take_while(|c: ::Item| c.as_char() == '0')(i)?; + let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') { + Some(index) => i.take_split(index), + None => i.take_split(i.input_len()), + }; + + //let (i, mut integer) = digit0(i)?; + let (i, mut integer) = match i + .as_bytes() + .iter() + .position(|c| !(*c >= b'0' && *c <= b'9')) + { + Some(index) => i.take_split(index), + None => i.take_split(i.input_len()), + }; + + if integer.input_len() == 0 && zeroes.input_len() > 0 { + // keep the last zero if integer is empty + integer = zeroes.slice(zeroes.input_len() - 1..); + } + + let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, fraction) = if opt_dot.is_none() { + let i2 = i.clone(); + (i2, i.slice(..0)) + } else { + // match number, trim right zeroes + let mut zero_count = 0usize; + let mut position = None; + for (pos, c) in i.as_bytes().iter().enumerate() { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { + zero_count += 1; + } else { + zero_count = 0; + } + } else { + position = Some(pos); + break; + } + } + + let position = match position { + Some(p) => p, + None => return Err(Err::Incomplete(Needed::new(1))), + }; + + let index = if zero_count == 0 { + position + } else if zero_count == position { + position - zero_count + 1 + } else { + position - zero_count + }; + + (i.slice(position..), i.slice(..index)) + }; + + if integer.input_len() == 0 && fraction.input_len() == 0 { + return Err(Err::Error(E::from_error_kind(input, ErrorKind::Float))); + } + + let i2 = i.clone(); + let (i, e) = match i.as_bytes().iter().next() { + Some(b'e') => (i.slice(1..), true), + Some(b'E') => (i.slice(1..), true), + _ => (i, false), + }; + + let (i, exp) = if e { + cut(crate::character::streaming::i32)(i)? + } else { + (i2, 0) + }; + + Ok((i, (sign, integer, fraction, exp))) +} + +/// Recognizes floating point number in text format and returns a f32. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::float; +/// +/// let parser = |s| { +/// float(s) +/// }; +/// +/// assert_eq!(parser("11e-1"), Ok(("", 1.1))); +/// assert_eq!(parser("123E-02"), Ok(("", 1.23))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float)))); +/// ``` +pub fn float>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter + InputLength + InputTake + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar, + ::IterElem: Clone, + T: InputTakeAtPosition, + ::Item: AsChar, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + /* + let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; + + let mut float: f32 = minimal_lexical::parse_float( + integer.as_bytes().iter(), + fraction.as_bytes().iter(), + exponent, + ); + if !sign { + float = -float; + } + + Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => Ok((i, f)), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } +} + +/// Recognizes floating point number in text format and returns a f64. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::complete::double; +/// +/// let parser = |s| { +/// double(s) +/// }; +/// +/// assert_eq!(parser("11e-1"), Ok(("", 1.1))); +/// assert_eq!(parser("123E-02"), Ok(("", 1.23))); +/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0))); +/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float)))); +/// ``` +pub fn double>(input: T) -> IResult +where + T: Slice> + Slice>, + T: Clone + Offset, + T: InputIter + InputLength + InputTake + crate::traits::ParseTo + Compare<&'static str>, + ::Item: AsChar, + ::IterElem: Clone, + T: InputTakeAtPosition, + ::Item: AsChar, + T: AsBytes, + T: for<'a> Compare<&'a [u8]>, +{ + /* + let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; + + let mut float: f64 = minimal_lexical::parse_float( + integer.as_bytes().iter(), + fraction.as_bytes().iter(), + exponent, + ); + if !sign { + float = -float; + } + + Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => Ok((i, f)), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::error::ErrorKind; + use crate::internal::{Err, Needed}; + use proptest::prelude::*; + + macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; + assert_eq!(res, $right); + }; + ); + + #[test] + fn i8_tests() { + assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); + assert_parse!(be_i8(&[][..]), Err(Err::Incomplete(Needed::new(1)))); + } + + #[test] + fn i16_tests() { + assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); + assert_parse!(be_i16(&[][..]), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!(be_i16(&[0x00][..]), Err(Err::Incomplete(Needed::new(1)))); + } + + #[test] + fn u24_tests() { + assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + be_u24(&[0x12, 0x34, 0x56][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + assert_parse!(be_u24(&[][..]), Err(Err::Incomplete(Needed::new(3)))); + assert_parse!(be_u24(&[0x00][..]), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!( + be_u24(&[0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i24_tests() { + assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + be_i24(&[0xED, 0xCB, 0xAA][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + assert_parse!(be_i24(&[][..]), Err(Err::Incomplete(Needed::new(3)))); + assert_parse!(be_i24(&[0x00][..]), Err(Err::Incomplete(Needed::new(2)))); + assert_parse!( + be_i24(&[0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i32_tests() { + assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + be_i32(&[0x80, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + assert_parse!(be_i32(&[][..]), Err(Err::Incomplete(Needed::new(4)))); + assert_parse!(be_i32(&[0x00][..]), Err(Err::Incomplete(Needed::new(3)))); + assert_parse!( + be_i32(&[0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i32(&[0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i64_tests() { + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + assert_parse!(be_i64(&[][..]), Err(Err::Incomplete(Needed::new(8)))); + assert_parse!(be_i64(&[0x00][..]), Err(Err::Incomplete(Needed::new(7)))); + assert_parse!( + be_i64(&[0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i128_tests() { + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i128( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i128( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + assert_parse!(be_i128(&[][..]), Err(Err::Incomplete(Needed::new(16)))); + assert_parse!(be_i128(&[0x00][..]), Err(Err::Incomplete(Needed::new(15)))); + assert_parse!( + be_i128(&[0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(14))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(13))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(12))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(11))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(10))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(9))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(8))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(7))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(Err::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i128( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + ), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i128( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + [..] + ), + Err(Err::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn le_i16_tests() { + assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); + } + + #[test] + fn le_u24_tests() { + assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + le_u24(&[0x56, 0x34, 0x12][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } + + #[test] + fn le_i24_tests() { + assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + le_i24(&[0xAA, 0xCB, 0xED][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + } + + #[test] + fn le_i32_tests() { + assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + le_i32(&[0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } + + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } + + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } + + #[test] + fn be_f32_tests() { + assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), + Ok((&b""[..], 185_728_392_f32)) + ); + } + + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } + + #[test] + fn le_f32_tests() { + assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), + Ok((&b""[..], 185_728_392_f32)) + ); + } + + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } + + #[test] + fn hex_u32_tests() { + assert_parse!( + hex_u32(&b";"[..]), + Err(Err::Error(error_position!(&b";"[..], ErrorKind::IsA))) + ); + assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); + assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); + assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); + assert_parse!( + hex_u32(&b"c5a31be201;"[..]), + Ok((&b"01;"[..], 3_315_801_058)) + ); + assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); + assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); + assert_parse!(hex_u32(&b"12af"[..]), Err(Err::Incomplete(Needed::new(1)))); + } + + #[test] + #[cfg(feature = "std")] + fn float_test() { + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + let larger = format!("{};", test); + assert_parse!(recognize_float(&larger[..]), Ok((";", test))); + + assert_parse!(float(larger.as_bytes()), Ok((&b";"[..], expected32))); + assert_parse!(float(&larger[..]), Ok((";", expected32))); + + assert_parse!(double(larger.as_bytes()), Ok((&b";"[..], expected64))); + assert_parse!(double(&larger[..]), Ok((";", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + recognize_float(remaining_exponent), + Err(Err::Incomplete(Needed::new(1))) + ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); + } + + #[test] + fn configurable_endianness() { + use crate::number::Endianness; + + fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Big)(i) + } + fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Little)(i) + } + assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); + assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); + + fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 302_014_464_u32)) + ); + assert_eq!( + le_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 6_291_474_u32)) + ); + + fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_666_770_u64)) + ); + + fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Little)(i) + } + assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); + assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); + + fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 6_296_064_i32)) + ); + + fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_732_032_i64)) + ); + } + + #[cfg(feature = "std")] + fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + use crate::traits::ParseTo; + match recognize_float_or_exceptions(i) { + Err(e) => Err(e), + Ok((i, s)) => { + if s.is_empty() { + return Err(Err::Error(())); + } + match s.parse_to() { + Some(n) => Ok((i, n)), + None => Err(Err::Error(())), + } + } + } + } + + proptest! { + #[test] + #[cfg(feature = "std")] + fn floats(s in "\\PC*") { + println!("testing {}", s); + let res1 = parse_f64(&s); + let res2 = double::<_, ()>(s.as_str()); + assert_eq!(res1, res2); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,279 @@ +//! Combinators applying parsers in sequence + +#[cfg(test)] +mod tests; + +use crate::error::ParseError; +use crate::internal::{IResult, Parser}; + +/// Gets an object from the first parser, +/// then gets another object from the second parser. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `second` The second parser to apply. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::pair; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = pair(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn pair, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + second.parse(input).map(|(i, o2)| (i, (o1, o2))) + } +} + +/// Matches an object from the first parser and discards it, +/// then gets an object from the second parser. +/// +/// # Arguments +/// * `first` The opening parser. +/// * `second` The second parser to get object. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::preceded; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = preceded(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", "efg"))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn preceded, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, +{ + move |input: I| { + let (input, _) = first.parse(input)?; + second.parse(input) + } +} + +/// Gets an object from the first parser, +/// then matches an object from the second parser and discards it. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `second` The second parser to match an object. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::terminated; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = terminated(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", "abc"))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn terminated, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + second.parse(input).map(|(i, _)| (i, o1)) + } +} + +/// Gets an object from the first parser, +/// then matches an object from the sep_parser and discards it, +/// then gets another object from the second parser. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `sep` The separator parser to apply. +/// * `second` The second parser to apply. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::separated_pair; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg")); +/// +/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn separated_pair, F, G, H>( + mut first: F, + mut sep: G, + mut second: H, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, + H: Parser, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + let (input, _) = sep.parse(input)?; + second.parse(input).map(|(i, o2)| (i, (o1, o2))) + } +} + +/// Matches an object from the first parser and discards it, +/// then gets an object from the second parser, +/// and finally matches an object from the third parser and discards it. +/// +/// # Arguments +/// * `first` The first parser to apply and discard. +/// * `second` The second parser to apply. +/// * `third` The third parser to apply and discard. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::delimited; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = delimited(tag("("), tag("abc"), tag(")")); +/// +/// assert_eq!(parser("(abc)"), Ok(("", "abc"))); +/// assert_eq!(parser("(abc)def"), Ok(("def", "abc"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn delimited, F, G, H>( + mut first: F, + mut second: G, + mut third: H, +) -> impl FnMut(I) -> IResult +where + F: Parser, + G: Parser, + H: Parser, +{ + move |input: I| { + let (input, _) = first.parse(input)?; + let (input, o2) = second.parse(input)?; + third.parse(input).map(|(i, _)| (i, o2)) + } +} + +/// Helper trait for the tuple combinator. +/// +/// This trait is implemented for tuples of parsers of up to 21 elements. +pub trait Tuple { + /// Parses the input and returns a tuple of results of each parser. + fn parse(&mut self, input: I) -> IResult; +} + +impl, F: Parser> + Tuple for (F,) +{ + fn parse(&mut self, input: Input) -> IResult { + self.0.parse(input).map(|(i, o)| (i, (o,))) + } +} + +macro_rules! tuple_trait( + ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => ( + tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*); + ); + (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => ( + tuple_trait_impl!($($name $ty),+); + tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*); + ); + (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => ( + tuple_trait_impl!($($name $ty),+); + tuple_trait_impl!($($name $ty),+, $name1 $ty1); + ); +); + +macro_rules! tuple_trait_impl( + ($($name:ident $ty: ident),+) => ( + impl< + Input: Clone, $($ty),+ , Error: ParseError, + $($name: Parser),+ + > Tuple for ( $($name),+ ) { + + fn parse(&mut self, input: Input) -> IResult { + tuple_trait_inner!(0, self, input, (), $($name)+) + + } + } + ); +); + +macro_rules! tuple_trait_inner( + ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+)) + }); + ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+)) + }); + ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + Ok((i, ($($parsed)* , o))) + }); +); + +tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L, + FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U); + +// Special case: implement `Tuple` for `()`, the unit type. +// This can come up in macros which accept a variable number of arguments. +// Literally, `()` is an empty tuple, so it should simply parse nothing. +impl> Tuple for () { + fn parse(&mut self, input: I) -> IResult { + Ok((input, ())) + } +} + +///Applies a tuple of parsers one by one and returns their results as a tuple. +///There is a maximum of 21 parsers +/// ```rust +/// # use nom::{Err, error::ErrorKind}; +/// use nom::sequence::tuple; +/// use nom::character::complete::{alpha1, digit1}; +/// let mut parser = tuple((alpha1, digit1, alpha1)); +/// +/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def")))); +/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha)))); +/// ``` +pub fn tuple, List: Tuple>( + mut l: List, +) -> impl FnMut(I) -> IResult { + move |i: I| l.parse(i) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/tests.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/sequence/tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,290 @@ +use super::*; +use crate::bytes::streaming::{tag, take}; +use crate::error::{Error, ErrorKind}; +use crate::internal::{Err, IResult, Needed}; +use crate::number::streaming::be_u16; + +#[test] +fn single_element_tuples() { + use crate::character::complete::alpha1; + use crate::{error::ErrorKind, Err}; + + let mut parser = tuple((alpha1,)); + assert_eq!(parser("abc123def"), Ok(("123def", ("abc",)))); + assert_eq!( + parser("123def"), + Err(Err::Error(("123def", ErrorKind::Alpha))) + ); +} + +#[derive(PartialEq, Eq, Debug)] +struct B { + a: u8, + b: u8, +} + +#[derive(PartialEq, Eq, Debug)] +struct C { + a: u8, + b: Option, +} + +/*FIXME: convert code examples to new error management +use util::{add_error_pattern, error_to_list, print_error}; + +#[cfg(feature = "std")] +#[rustfmt::skip] +fn error_to_string(e: &Context) -> &'static str { + let v: Vec<(P, ErrorKind)> = error_to_list(e); + // do it this way if you can use slice patterns + //match &v[..] { + // [ErrorKind::Custom(42), ErrorKind::Tag] => "missing `ijkl` tag", + // [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] => "missing `mnop` tag after `ijkl`", + // _ => "unrecognized error" + //} + + let collected: Vec> = v.iter().map(|&(_, ref e)| e.clone()).collect(); + if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Tag] { + "missing `ijkl` tag" + } else if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] { + "missing `mnop` tag after `ijkl`" + } else { + "unrecognized error" + } +} + +// do it this way if you can use box patterns +//use $crate::lib::std::str; +//fn error_to_string(e:Err) -> String +// match e { +// NodePosition(ErrorKind::Custom(42), i1, box Position(ErrorKind::Tag, i2)) => { +// format!("missing `ijkl` tag, found '{}' instead", str::from_utf8(i2).unwrap()) +// }, +// NodePosition(ErrorKind::Custom(42), i1, box NodePosition(ErrorKind::Custom(128), i2, box Position(ErrorKind::Tag, i3))) => { +// format!("missing `mnop` tag after `ijkl`, found '{}' instead", str::from_utf8(i3).unwrap()) +// }, +// _ => "unrecognized error".to_string() +// } +//} +*/ + +#[test] +fn complete() { + use crate::bytes::complete::tag; + fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> { + let (i, _) = tag("ijkl")(i)?; + tag("mnop")(i) + } + let a = &b"ijklmn"[..]; + + let res_a = err_test(a); + assert_eq!( + res_a, + Err(Err::Error(error_position!(&b"mn"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn pair_test() { + fn pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(tag("abc"), tag("def"))(i) + } + + assert_eq!( + pair_abc_def(&b"abcdefghijkl"[..]), + Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..]))) + ); + assert_eq!( + pair_abc_def(&b"ab"[..]), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + pair_abc_def(&b"abcd"[..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_eq!( + pair_abc_def(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + pair_abc_def(&b"xxxdef"[..]), + Err(Err::Error(error_position!(&b"xxxdef"[..], ErrorKind::Tag))) + ); + assert_eq!( + pair_abc_def(&b"abcxxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn separated_pair_test() { + fn sep_pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + separated_pair(tag("abc"), tag(","), tag("def"))(i) + } + + assert_eq!( + sep_pair_abc_def(&b"abc,defghijkl"[..]), + Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..]))) + ); + assert_eq!( + sep_pair_abc_def(&b"ab"[..]), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + sep_pair_abc_def(&b"abc,d"[..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_eq!( + sep_pair_abc_def(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + sep_pair_abc_def(&b"xxx,def"[..]), + Err(Err::Error(error_position!(&b"xxx,def"[..], ErrorKind::Tag))) + ); + assert_eq!( + sep_pair_abc_def(&b"abc,xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn preceded_test() { + fn preceded_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> { + preceded(tag("abcd"), tag("efgh"))(i) + } + + assert_eq!( + preceded_abcd_efgh(&b"abcdefghijkl"[..]), + Ok((&b"ijkl"[..], &b"efgh"[..])) + ); + assert_eq!( + preceded_abcd_efgh(&b"ab"[..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_eq!( + preceded_abcd_efgh(&b"abcde"[..]), + Err(Err::Incomplete(Needed::new(3))) + ); + assert_eq!( + preceded_abcd_efgh(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + preceded_abcd_efgh(&b"xxxxdef"[..]), + Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag))) + ); + assert_eq!( + preceded_abcd_efgh(&b"abcdxxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn terminated_test() { + fn terminated_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> { + terminated(tag("abcd"), tag("efgh"))(i) + } + + assert_eq!( + terminated_abcd_efgh(&b"abcdefghijkl"[..]), + Ok((&b"ijkl"[..], &b"abcd"[..])) + ); + assert_eq!( + terminated_abcd_efgh(&b"ab"[..]), + Err(Err::Incomplete(Needed::new(2))) + ); + assert_eq!( + terminated_abcd_efgh(&b"abcde"[..]), + Err(Err::Incomplete(Needed::new(3))) + ); + assert_eq!( + terminated_abcd_efgh(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + terminated_abcd_efgh(&b"xxxxdef"[..]), + Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag))) + ); + assert_eq!( + terminated_abcd_efgh(&b"abcdxxxx"[..]), + Err(Err::Error(error_position!(&b"xxxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn delimited_test() { + fn delimited_abc_def_ghi(i: &[u8]) -> IResult<&[u8], &[u8]> { + delimited(tag("abc"), tag("def"), tag("ghi"))(i) + } + + assert_eq!( + delimited_abc_def_ghi(&b"abcdefghijkl"[..]), + Ok((&b"jkl"[..], &b"def"[..])) + ); + assert_eq!( + delimited_abc_def_ghi(&b"ab"[..]), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(&b"abcde"[..]), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(&b"abcdefgh"[..]), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(&b"xxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); + assert_eq!( + delimited_abc_def_ghi(&b"xxxdefghi"[..]), + Err(Err::Error(error_position!( + &b"xxxdefghi"[..], + ErrorKind::Tag + ),)) + ); + assert_eq!( + delimited_abc_def_ghi(&b"abcxxxghi"[..]), + Err(Err::Error(error_position!(&b"xxxghi"[..], ErrorKind::Tag))) + ); + assert_eq!( + delimited_abc_def_ghi(&b"abcdefxxx"[..]), + Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn tuple_test() { + fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8], &[u8])> { + tuple((be_u16, take(3u8), tag("fg")))(i) + } + + assert_eq!( + tuple_3(&b"abcdefgh"[..]), + Ok((&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..]))) + ); + assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2)))); + assert_eq!( + tuple_3(&b"abcdejk"[..]), + Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag))) + ); +} + +#[test] +fn unit_type() { + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"), + Ok(("abxsbsh", ())) + ); + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"), + Ok(("sdfjakdsas", ())) + ); + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())(""), + Ok(("", ())) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/str.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,536 @@ +#[cfg(test)] +mod test { + #[cfg(feature = "alloc")] + use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1}; + use crate::{ + bytes::complete::{is_a, is_not, tag, take, take_till, take_until}, + error::{self, ErrorKind}, + Err, IResult, + }; + + #[test] + fn tagtr_succeed() { + const INPUT: &str = "Hello World!"; + const TAG: &str = "Hello"; + fn test(input: &str) -> IResult<&str, &str> { + tag(TAG)(input) + } + + match test(INPUT) { + Ok((extra, output)) => { + assert!(extra == " World!", "Parser `tag` consumed leftover input."); + assert!( + output == TAG, + "Parser `tag` doesn't return the tag it matched on success. \ + Expected `{}`, got `{}`.", + TAG, + output + ); + } + other => panic!( + "Parser `tag` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn tagtr_incomplete() { + use crate::bytes::streaming::tag; + + const INPUT: &str = "Hello"; + const TAG: &str = "Hello World!"; + + let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); + match res { + Err(Err::Incomplete(_)) => (), + other => { + panic!( + "Parser `tag` didn't require more input when it should have. \ + Got `{:?}`.", + other + ); + } + }; + } + + #[test] + fn tagtr_error() { + const INPUT: &str = "Hello World!"; + const TAG: &str = "Random"; // TAG must be closer than INPUT. + + let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); + match res { + Err(Err::Error(_)) => (), + other => { + panic!( + "Parser `tag` didn't fail when it should have. Got `{:?}`.`", + other + ); + } + }; + } + + #[test] + fn take_s_succeed() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + + let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT); + match res { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_s` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( + output == CONSUMED, + "Parser `take_s` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_s` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_until_succeed() { + const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř"; + const FIND: &str = "ÂßÇ∂"; + const CONSUMED: &str = "βèƒôřè"; + const LEFTOVER: &str = "ÂßÇ∂áƒƭèř"; + + let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); + match res { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_until`\ + consumed leftover input. Leftover `{}`.", + extra + ); + assert!( + output == CONSUMED, + "Parser `take_until`\ + doesn't return the string it consumed on success. Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_until` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_s_incomplete() { + use crate::bytes::streaming::take; + + const INPUT: &str = "βèƒôřèÂßÇá"; + + let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT); + match res { + Err(Err::Incomplete(_)) => (), + other => panic!( + "Parser `take` didn't require more input when it should have. \ + Got `{:?}`.", + other + ), + } + } + + use crate::internal::Needed; + + fn is_alphabetic(c: char) -> bool { + (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A) + } + + #[test] + fn take_while() { + use crate::bytes::streaming::take_while; + + fn f(i: &str) -> IResult<&str, &str> { + take_while(is_alphabetic)(i) + } + let a = ""; + let b = "abcd"; + let c = "abcd123"; + let d = "123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); + assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); + } + + #[test] + fn take_while1() { + use crate::bytes::streaming::take_while1; + + fn f(i: &str) -> IResult<&str, &str> { + take_while1(is_alphabetic)(i) + } + let a = ""; + let b = "abcd"; + let c = "abcd123"; + let d = "123"; + + assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&"123"[..], &b[..]))); + assert_eq!( + f(&d[..]), + Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1))) + ); + } + + #[test] + fn take_till_s_succeed() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn till_s(c: char) -> bool { + c == 'á' + } + fn test(input: &str) -> IResult<&str, &str> { + take_till(till_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_till` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_till` doesn't return the string it consumed on success. \ + Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_till` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_while_succeed_none() { + use crate::bytes::complete::take_while; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = ""; + const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř"; + fn while_s(c: char) -> bool { + c == '9' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while(while_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while` doesn't return the string it consumed on success. \ + Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn is_not_succeed() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const AVOID: &str = "£úçƙ¥á"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn test(input: &str) -> IResult<&str, &str> { + is_not(AVOID)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `is_not` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( + output == CONSUMED, + "Parser `is_not` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `is_not` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_while_succeed_some() { + use crate::bytes::complete::take_while; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn while_s(c: char) -> bool { + c == 'β' + || c == 'è' + || c == 'ƒ' + || c == 'ô' + || c == 'ř' + || c == 'è' + || c == 'Â' + || c == 'ß' + || c == 'Ç' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while(while_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while` doesn't return the string it consumed on success. \ + Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn is_not_fail() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const AVOID: &str = "βúçƙ¥"; + fn test(input: &str) -> IResult<&str, &str> { + is_not(AVOID)(input) + } + match test(INPUT) { + Err(Err::Error(_)) => (), + other => panic!( + "Parser `is_not` didn't fail when it should have. Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_while1_succeed() { + use crate::bytes::complete::take_while1; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn while1_s(c: char) -> bool { + c == 'β' + || c == 'è' + || c == 'ƒ' + || c == 'ô' + || c == 'ř' + || c == 'è' + || c == 'Â' + || c == 'ß' + || c == 'Ç' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while1(while1_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while1` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while1` doesn't return the string it consumed on success. \ + Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while1` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_until_incomplete() { + use crate::bytes::streaming::take_until; + + const INPUT: &str = "βèƒôřè"; + const FIND: &str = "βèƒôřèÂßÇ"; + + let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); + match res { + Err(Err::Incomplete(_)) => (), + other => panic!( + "Parser `take_until` didn't require more input when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn is_a_succeed() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const MATCH: &str = "βèƒôřèÂßÇ"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn test(input: &str) -> IResult<&str, &str> { + is_a(MATCH)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `is_a` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( + output == CONSUMED, + "Parser `is_a` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", + CONSUMED, + output + ); + } + other => panic!( + "Parser `is_a` didn't succeed when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_while1_fail() { + use crate::bytes::complete::take_while1; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + fn while1_s(c: char) -> bool { + c == '9' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while1(while1_s)(input) + } + match test(INPUT) { + Err(Err::Error(_)) => (), + other => panic!( + "Parser `take_while1` didn't fail when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + fn is_a_fail() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const MATCH: &str = "Ûñℓúçƙ¥"; + fn test(input: &str) -> IResult<&str, &str> { + is_a(MATCH)(input) + } + match test(INPUT) { + Err(Err::Error(_)) => (), + other => panic!( + "Parser `is_a` didn't fail when it should have. Got `{:?}`.", + other + ), + }; + } + + #[test] + fn take_until_error() { + use crate::bytes::streaming::take_until; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const FIND: &str = "Ráñδô₥"; + + let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); + match res { + Err(Err::Incomplete(_)) => (), + other => panic!( + "Parser `take_until` didn't fail when it should have. \ + Got `{:?}`.", + other + ), + }; + } + + #[test] + #[cfg(feature = "alloc")] + fn recognize_is_a() { + let a = "aabbab"; + let b = "ababcd"; + + fn f(i: &str) -> IResult<&str, &str> { + recognize(many1(alt((tag("a"), tag("b")))))(i) + } + + assert_eq!(f(&a[..]), Ok((&a[6..], &a[..]))); + assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4]))); + } + + #[test] + fn utf8_indexing() { + fn dot(i: &str) -> IResult<&str, &str> { + tag(".")(i) + } + + let _ = dot("點"); + } + + #[cfg(feature = "alloc")] + #[test] + fn case_insensitive() { + fn test(i: &str) -> IResult<&str, &str> { + tag_no_case("ABcd")(i) + } + assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd"))); + assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd"))); + assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD"))); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/src/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1441 @@ +//! Traits input types have to implement to work with nom combinators +use crate::error::{ErrorKind, ParseError}; +use crate::internal::{Err, IResult, Needed}; +use crate::lib::std::iter::{Copied, Enumerate}; +use crate::lib::std::ops::{Range, RangeFrom, RangeFull, RangeTo}; +use crate::lib::std::slice::Iter; +use crate::lib::std::str::from_utf8; +use crate::lib::std::str::CharIndices; +use crate::lib::std::str::Chars; +use crate::lib::std::str::FromStr; + +#[cfg(feature = "alloc")] +use crate::lib::std::string::String; +#[cfg(feature = "alloc")] +use crate::lib::std::vec::Vec; + +/// Abstract method to calculate the input length +pub trait InputLength { + /// Calculates the input length, as indicated by its name, + /// and the name of the trait itself + fn input_len(&self) -> usize; +} + +impl<'a, T> InputLength for &'a [T] { + #[inline] + fn input_len(&self) -> usize { + self.len() + } +} + +impl<'a> InputLength for &'a str { + #[inline] + fn input_len(&self) -> usize { + self.len() + } +} + +impl<'a> InputLength for (&'a [u8], usize) { + #[inline] + fn input_len(&self) -> usize { + //println!("bit input length for ({:?}, {}):", self.0, self.1); + //println!("-> {}", self.0.len() * 8 - self.1); + self.0.len() * 8 - self.1 + } +} + +/// Useful functions to calculate the offset between slices and show a hexdump of a slice +pub trait Offset { + /// Offset between the first byte of self and the first byte of the argument + fn offset(&self, second: &Self) -> usize; +} + +impl Offset for [u8] { + fn offset(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + snd as usize - fst as usize + } +} + +impl<'a> Offset for &'a [u8] { + fn offset(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + snd as usize - fst as usize + } +} + +impl Offset for str { + fn offset(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + snd as usize - fst as usize + } +} + +impl<'a> Offset for &'a str { + fn offset(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + snd as usize - fst as usize + } +} + +/// Helper trait for types that can be viewed as a byte slice +pub trait AsBytes { + /// Casts the input type to a byte slice + fn as_bytes(&self) -> &[u8]; +} + +impl<'a> AsBytes for &'a str { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + (*self).as_bytes() + } +} + +impl AsBytes for str { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self.as_ref() + } +} + +impl<'a> AsBytes for &'a [u8] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + *self + } +} + +impl AsBytes for [u8] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self + } +} + +macro_rules! as_bytes_array_impls { + ($($N:expr)+) => { + $( + impl<'a> AsBytes for &'a [u8; $N] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + *self + } + } + + impl AsBytes for [u8; $N] { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self + } + } + )+ + }; +} + +as_bytes_array_impls! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + +/// Transforms common types to a char for basic token parsing +pub trait AsChar { + /// makes a char from self + fn as_char(self) -> char; + + /// Tests that self is an alphabetic character + /// + /// Warning: for `&str` it recognizes alphabetic + /// characters outside of the 52 ASCII letters + fn is_alpha(self) -> bool; + + /// Tests that self is an alphabetic character + /// or a decimal digit + fn is_alphanum(self) -> bool; + /// Tests that self is a decimal digit + fn is_dec_digit(self) -> bool; + /// Tests that self is an hex digit + fn is_hex_digit(self) -> bool; + /// Tests that self is an octal digit + fn is_oct_digit(self) -> bool; + /// Gets the len in bytes for self + fn len(self) -> usize; +} + +impl AsChar for u8 { + #[inline] + fn as_char(self) -> char { + self as char + } + #[inline] + fn is_alpha(self) -> bool { + (self >= 0x41 && self <= 0x5A) || (self >= 0x61 && self <= 0x7A) + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + self >= 0x30 && self <= 0x39 + } + #[inline] + fn is_hex_digit(self) -> bool { + (self >= 0x30 && self <= 0x39) + || (self >= 0x41 && self <= 0x46) + || (self >= 0x61 && self <= 0x66) + } + #[inline] + fn is_oct_digit(self) -> bool { + self >= 0x30 && self <= 0x37 + } + #[inline] + fn len(self) -> usize { + 1 + } +} +impl<'a> AsChar for &'a u8 { + #[inline] + fn as_char(self) -> char { + *self as char + } + #[inline] + fn is_alpha(self) -> bool { + (*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A) + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + *self >= 0x30 && *self <= 0x39 + } + #[inline] + fn is_hex_digit(self) -> bool { + (*self >= 0x30 && *self <= 0x39) + || (*self >= 0x41 && *self <= 0x46) + || (*self >= 0x61 && *self <= 0x66) + } + #[inline] + fn is_oct_digit(self) -> bool { + *self >= 0x30 && *self <= 0x37 + } + #[inline] + fn len(self) -> usize { + 1 + } +} + +impl AsChar for char { + #[inline] + fn as_char(self) -> char { + self + } + #[inline] + fn is_alpha(self) -> bool { + self.is_ascii_alphabetic() + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + self.is_ascii_digit() + } + #[inline] + fn is_hex_digit(self) -> bool { + self.is_ascii_hexdigit() + } + #[inline] + fn is_oct_digit(self) -> bool { + self.is_digit(8) + } + #[inline] + fn len(self) -> usize { + self.len_utf8() + } +} + +impl<'a> AsChar for &'a char { + #[inline] + fn as_char(self) -> char { + *self + } + #[inline] + fn is_alpha(self) -> bool { + self.is_ascii_alphabetic() + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + self.is_ascii_digit() + } + #[inline] + fn is_hex_digit(self) -> bool { + self.is_ascii_hexdigit() + } + #[inline] + fn is_oct_digit(self) -> bool { + self.is_digit(8) + } + #[inline] + fn len(self) -> usize { + self.len_utf8() + } +} + +/// Abstracts common iteration operations on the input type +pub trait InputIter { + /// The current input type is a sequence of that `Item` type. + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Item; + /// An iterator over the input type, producing the item and its position + /// for use with [Slice]. If we're iterating over `&str`, the position + /// corresponds to the byte index of the character + type Iter: Iterator; + + /// An iterator over the input type, producing the item + type IterElem: Iterator; + + /// Returns an iterator over the elements and their byte offsets + fn iter_indices(&self) -> Self::Iter; + /// Returns an iterator over the elements + fn iter_elements(&self) -> Self::IterElem; + /// Finds the byte position of the element + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool; + /// Get the byte offset from the element's position in the stream + fn slice_index(&self, count: usize) -> Result; +} + +/// Abstracts slicing operations +pub trait InputTake: Sized { + /// Returns a slice of `count` bytes. panics if count > length + fn take(&self, count: usize) -> Self; + /// Split the stream at the `count` byte offset. panics if count > length + fn take_split(&self, count: usize) -> (Self, Self); +} + +impl<'a> InputIter for &'a [u8] { + type Item = u8; + type Iter = Enumerate; + type IterElem = Copied>; + + #[inline] + fn iter_indices(&self) -> Self::Iter { + self.iter_elements().enumerate() + } + #[inline] + fn iter_elements(&self) -> Self::IterElem { + self.iter().copied() + } + #[inline] + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool, + { + self.iter().position(|b| predicate(*b)) + } + #[inline] + fn slice_index(&self, count: usize) -> Result { + if self.len() >= count { + Ok(count) + } else { + Err(Needed::new(count - self.len())) + } + } +} + +impl<'a> InputTake for &'a [u8] { + #[inline] + fn take(&self, count: usize) -> Self { + &self[0..count] + } + #[inline] + fn take_split(&self, count: usize) -> (Self, Self) { + let (prefix, suffix) = self.split_at(count); + (suffix, prefix) + } +} + +impl<'a> InputIter for &'a str { + type Item = char; + type Iter = CharIndices<'a>; + type IterElem = Chars<'a>; + #[inline] + fn iter_indices(&self) -> Self::Iter { + self.char_indices() + } + #[inline] + fn iter_elements(&self) -> Self::IterElem { + self.chars() + } + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool, + { + for (o, c) in self.char_indices() { + if predicate(c) { + return Some(o); + } + } + None + } + #[inline] + fn slice_index(&self, count: usize) -> Result { + let mut cnt = 0; + for (index, _) in self.char_indices() { + if cnt == count { + return Ok(index); + } + cnt += 1; + } + if cnt == count { + return Ok(self.len()); + } + Err(Needed::Unknown) + } +} + +impl<'a> InputTake for &'a str { + #[inline] + fn take(&self, count: usize) -> Self { + &self[..count] + } + + // return byte index + #[inline] + fn take_split(&self, count: usize) -> (Self, Self) { + let (prefix, suffix) = self.split_at(count); + (suffix, prefix) + } +} + +/// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`). +/// +/// When implementing a custom input type, it is possible to use directly the +/// default implementation: If the input type implements `InputLength`, `InputIter`, +/// `InputTake` and `Clone`, you can implement `UnspecializedInput` and get +/// a default version of `InputTakeAtPosition` and `Compare`. +/// +/// For performance reasons, you might want to write a custom implementation of +/// `InputTakeAtPosition` (like the one for `&[u8]`). +pub trait UnspecializedInput {} + +/// Methods to take as much input as possible until the provided function returns true for the current element. +/// +/// A large part of nom's basic parsers are built using this trait. +pub trait InputTakeAtPosition: Sized { + /// The current input type is a sequence of that `Item` type. + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Item; + + /// Looks for the first element of the input type for which the condition returns true, + /// and returns the input up to this position. + /// + /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool; + + /// Looks for the first element of the input type for which the condition returns true + /// and returns the input up to this position. + /// + /// Fails if the produced slice is empty. + /// + /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool; + + /// Looks for the first element of the input type for which the condition returns true, + /// and returns the input up to this position. + /// + /// *complete version*: If no element is found matching the condition, this will return the whole input + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool; + + /// Looks for the first element of the input type for which the condition returns true + /// and returns the input up to this position. + /// + /// Fails if the produced slice is empty. + /// + /// *complete version*: If no element is found matching the condition, this will return the whole input + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool; +} + +impl InputTakeAtPosition + for T +{ + type Item = ::Item; + + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(n) => Ok(self.take_split(n)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.position(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), + Some(n) => Ok(self.take_split(n)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.split_at_position(predicate) { + Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())), + res => res, + } + } + + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.split_at_position1(predicate, e) { + Err(Err::Incomplete(_)) => { + if self.input_len() == 0 { + Err(Err::Error(E::from_error_kind(self.clone(), e))) + } else { + Ok(self.take_split(self.input_len())) + } + } + res => res, + } + } +} + +impl<'a> InputTakeAtPosition for &'a [u8] { + type Item = u8; + + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Ok(self.take_split(self.input_len())), + } + } + + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + Some(i) => Ok(self.take_split(i)), + None => { + if self.is_empty() { + Err(Err::Error(E::from_error_kind(self, e))) + } else { + Ok(self.take_split(self.input_len())) + } + } + } + } +} + +impl<'a> InputTakeAtPosition for &'a str { + type Item = char; + + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, + None => Err(Err::Incomplete(Needed::new(1))), + } + } + + fn split_at_position_complete>( + &self, + predicate: P, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, + // the end of slice is a char boundary + None => unsafe { + Ok(( + self.get_unchecked(self.len()..), + self.get_unchecked(..self.len()), + )) + }, + } + } + + fn split_at_position1_complete>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool, + { + match self.find(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, + None => { + if self.is_empty() { + Err(Err::Error(E::from_error_kind(self, e))) + } else { + // the end of slice is a char boundary + unsafe { + Ok(( + self.get_unchecked(self.len()..), + self.get_unchecked(..self.len()), + )) + } + } + } + } + } +} + +/// Indicates whether a comparison was successful, an error, or +/// if more data was needed +#[derive(Debug, PartialEq)] +pub enum CompareResult { + /// Comparison was successful + Ok, + /// We need more data to be sure + Incomplete, + /// Comparison failed + Error, +} + +/// Abstracts comparison operations +pub trait Compare { + /// Compares self to another value for equality + fn compare(&self, t: T) -> CompareResult; + /// Compares self to another value for equality + /// independently of the case. + /// + /// Warning: for `&str`, the comparison is done + /// by lowercasing both strings and comparing + /// the result. This is a temporary solution until + /// a better one appears + fn compare_no_case(&self, t: T) -> CompareResult; +} + +fn lowercase_byte(c: u8) -> u8 { + match c { + b'A'..=b'Z' => c - b'A' + b'a', + _ => c, + } +} + +impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: &'b [u8]) -> CompareResult { + let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b); + + match pos { + Some(_) => CompareResult::Error, + None => { + if self.len() >= t.len() { + CompareResult::Ok + } else { + CompareResult::Incomplete + } + } + } + + /* + let len = self.len(); + let blen = t.len(); + let m = if len < blen { len } else { blen }; + let reduced = &self[..m]; + let b = &t[..m]; + + if reduced != b { + CompareResult::Error + } else if m < blen { + CompareResult::Incomplete + } else { + CompareResult::Ok + } + */ + } + + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { + if self + .iter() + .zip(t) + .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b)) + { + CompareResult::Error + } else if self.len() < t.len() { + CompareResult::Incomplete + } else { + CompareResult::Ok + } + } +} + +impl< + T: InputLength + InputIter + InputTake + UnspecializedInput, + O: InputLength + InputIter + InputTake, + > Compare for T +{ + #[inline(always)] + fn compare(&self, t: O) -> CompareResult { + let pos = self + .iter_elements() + .zip(t.iter_elements()) + .position(|(a, b)| a != b); + + match pos { + Some(_) => CompareResult::Error, + None => { + if self.input_len() >= t.input_len() { + CompareResult::Ok + } else { + CompareResult::Incomplete + } + } + } + } + + #[inline(always)] + fn compare_no_case(&self, t: O) -> CompareResult { + if self + .iter_elements() + .zip(t.iter_elements()) + .any(|(a, b)| lowercase_byte(a) != lowercase_byte(b)) + { + CompareResult::Error + } else if self.input_len() < t.input_len() { + CompareResult::Incomplete + } else { + CompareResult::Ok + } + } +} + +impl<'a, 'b> Compare<&'b str> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: &'b str) -> CompareResult { + self.compare(AsBytes::as_bytes(t)) + } + #[inline(always)] + fn compare_no_case(&self, t: &'b str) -> CompareResult { + self.compare_no_case(AsBytes::as_bytes(t)) + } +} + +impl<'a, 'b> Compare<&'b str> for &'a str { + #[inline(always)] + fn compare(&self, t: &'b str) -> CompareResult { + self.as_bytes().compare(t.as_bytes()) + } + + //FIXME: this version is too simple and does not use the current locale + #[inline(always)] + fn compare_no_case(&self, t: &'b str) -> CompareResult { + let pos = self + .chars() + .zip(t.chars()) + .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase())); + + match pos { + Some(_) => CompareResult::Error, + None => { + if self.len() >= t.len() { + CompareResult::Ok + } else { + CompareResult::Incomplete + } + } + } + } +} + +impl<'a, 'b> Compare<&'b [u8]> for &'a str { + #[inline(always)] + fn compare(&self, t: &'b [u8]) -> CompareResult { + AsBytes::as_bytes(self).compare(t) + } + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { + AsBytes::as_bytes(self).compare_no_case(t) + } +} + +/// Look for a token in self +pub trait FindToken { + /// Returns true if self contains the token + fn find_token(&self, token: T) -> bool; +} + +impl<'a> FindToken for &'a [u8] { + fn find_token(&self, token: u8) -> bool { + memchr::memchr(token, self).is_some() + } +} + +impl<'a> FindToken for &'a str { + fn find_token(&self, token: u8) -> bool { + self.as_bytes().find_token(token) + } +} + +impl<'a, 'b> FindToken<&'a u8> for &'b [u8] { + fn find_token(&self, token: &u8) -> bool { + self.find_token(*token) + } +} + +impl<'a, 'b> FindToken<&'a u8> for &'b str { + fn find_token(&self, token: &u8) -> bool { + self.as_bytes().find_token(token) + } +} + +impl<'a> FindToken for &'a [u8] { + fn find_token(&self, token: char) -> bool { + self.iter().any(|i| *i == token as u8) + } +} + +impl<'a> FindToken for &'a str { + fn find_token(&self, token: char) -> bool { + self.chars().any(|i| i == token) + } +} + +impl<'a> FindToken for &'a [char] { + fn find_token(&self, token: char) -> bool { + self.iter().any(|i| *i == token) + } +} + +impl<'a, 'b> FindToken<&'a char> for &'b [char] { + fn find_token(&self, token: &char) -> bool { + self.find_token(*token) + } +} + +/// Look for a substring in self +pub trait FindSubstring { + /// Returns the byte position of the substring if it is found + fn find_substring(&self, substr: T) -> Option; +} + +impl<'a, 'b> FindSubstring<&'b [u8]> for &'a [u8] { + fn find_substring(&self, substr: &'b [u8]) -> Option { + if substr.len() > self.len() { + return None; + } + + let (&substr_first, substr_rest) = match substr.split_first() { + Some(split) => split, + // an empty substring is found at position 0 + // This matches the behavior of str.find(""). + None => return Some(0), + }; + + if substr_rest.is_empty() { + return memchr::memchr(substr_first, self); + } + + let mut offset = 0; + let haystack = &self[..self.len() - substr_rest.len()]; + + while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) { + offset += position; + let next_offset = offset + 1; + if &self[next_offset..][..substr_rest.len()] == substr_rest { + return Some(offset); + } + + offset = next_offset; + } + + None + } +} + +impl<'a, 'b> FindSubstring<&'b str> for &'a [u8] { + fn find_substring(&self, substr: &'b str) -> Option { + self.find_substring(AsBytes::as_bytes(substr)) + } +} + +impl<'a, 'b> FindSubstring<&'b str> for &'a str { + //returns byte index + fn find_substring(&self, substr: &'b str) -> Option { + self.find(substr) + } +} + +/// Used to integrate `str`'s `parse()` method +pub trait ParseTo { + /// Succeeds if `parse()` succeeded. The byte slice implementation + /// will first convert it to a `&str`, then apply the `parse()` function + fn parse_to(&self) -> Option; +} + +impl<'a, R: FromStr> ParseTo for &'a [u8] { + fn parse_to(&self) -> Option { + from_utf8(self).ok().and_then(|s| s.parse().ok()) + } +} + +impl<'a, R: FromStr> ParseTo for &'a str { + fn parse_to(&self) -> Option { + self.parse().ok() + } +} + +/// Slicing operations using ranges. +/// +/// This trait is loosely based on +/// `Index`, but can actually return +/// something else than a `&[T]` or `&str` +pub trait Slice { + /// Slices self according to the range argument + fn slice(&self, range: R) -> Self; +} + +macro_rules! impl_fn_slice { + ( $ty:ty ) => { + fn slice(&self, range: $ty) -> Self { + &self[range] + } + }; +} + +macro_rules! slice_range_impl { + ( [ $for_type:ident ], $ty:ty ) => { + impl<'a, $for_type> Slice<$ty> for &'a [$for_type] { + impl_fn_slice!($ty); + } + }; + ( $for_type:ty, $ty:ty ) => { + impl<'a> Slice<$ty> for &'a $for_type { + impl_fn_slice!($ty); + } + }; +} + +macro_rules! slice_ranges_impl { + ( [ $for_type:ident ] ) => { + slice_range_impl! {[$for_type], Range} + slice_range_impl! {[$for_type], RangeTo} + slice_range_impl! {[$for_type], RangeFrom} + slice_range_impl! {[$for_type], RangeFull} + }; + ( $for_type:ty ) => { + slice_range_impl! {$for_type, Range} + slice_range_impl! {$for_type, RangeTo} + slice_range_impl! {$for_type, RangeFrom} + slice_range_impl! {$for_type, RangeFull} + }; +} + +slice_ranges_impl! {str} +slice_ranges_impl! {[T]} + +macro_rules! array_impls { + ($($N:expr)+) => { + $( + impl InputLength for [u8; $N] { + #[inline] + fn input_len(&self) -> usize { + self.len() + } + } + + impl<'a> InputLength for &'a [u8; $N] { + #[inline] + fn input_len(&self) -> usize { + self.len() + } + } + + impl<'a> InputIter for &'a [u8; $N] { + type Item = u8; + type Iter = Enumerate; + type IterElem = Copied>; + + fn iter_indices(&self) -> Self::Iter { + (&self[..]).iter_indices() + } + + fn iter_elements(&self) -> Self::IterElem { + (&self[..]).iter_elements() + } + + fn position

(&self, predicate: P) -> Option + where P: Fn(Self::Item) -> bool { + (&self[..]).position(predicate) + } + + fn slice_index(&self, count: usize) -> Result { + (&self[..]).slice_index(count) + } + } + + impl<'a> Compare<[u8; $N]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: [u8; $N]) -> CompareResult { + self.compare(&t[..]) + } + + #[inline(always)] + fn compare_no_case(&self, t: [u8;$N]) -> CompareResult { + self.compare_no_case(&t[..]) + } + } + + impl<'a,'b> Compare<&'b [u8; $N]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: &'b [u8; $N]) -> CompareResult { + self.compare(&t[..]) + } + + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8;$N]) -> CompareResult { + self.compare_no_case(&t[..]) + } + } + + impl FindToken for [u8; $N] { + fn find_token(&self, token: u8) -> bool { + memchr::memchr(token, &self[..]).is_some() + } + } + + impl<'a> FindToken<&'a u8> for [u8; $N] { + fn find_token(&self, token: &u8) -> bool { + self.find_token(*token) + } + } + )+ + }; +} + +array_impls! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + +/// Abstracts something which can extend an `Extend`. +/// Used to build modified input slices in `escaped_transform` +pub trait ExtendInto { + /// The current input type is a sequence of that `Item` type. + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Item; + + /// The type that will be produced + type Extender; + + /// Create a new `Extend` of the correct type + fn new_builder(&self) -> Self::Extender; + /// Accumulate the input into an accumulator + fn extend_into(&self, acc: &mut Self::Extender); +} + +#[cfg(feature = "alloc")] +impl ExtendInto for [u8] { + type Item = u8; + type Extender = Vec; + + #[inline] + fn new_builder(&self) -> Vec { + Vec::new() + } + #[inline] + fn extend_into(&self, acc: &mut Vec) { + acc.extend(self.iter().cloned()); + } +} + +#[cfg(feature = "alloc")] +impl ExtendInto for &[u8] { + type Item = u8; + type Extender = Vec; + + #[inline] + fn new_builder(&self) -> Vec { + Vec::new() + } + #[inline] + fn extend_into(&self, acc: &mut Vec) { + acc.extend_from_slice(self); + } +} + +#[cfg(feature = "alloc")] +impl ExtendInto for str { + type Item = char; + type Extender = String; + + #[inline] + fn new_builder(&self) -> String { + String::new() + } + #[inline] + fn extend_into(&self, acc: &mut String) { + acc.push_str(self); + } +} + +#[cfg(feature = "alloc")] +impl ExtendInto for &str { + type Item = char; + type Extender = String; + + #[inline] + fn new_builder(&self) -> String { + String::new() + } + #[inline] + fn extend_into(&self, acc: &mut String) { + acc.push_str(self); + } +} + +#[cfg(feature = "alloc")] +impl ExtendInto for char { + type Item = char; + type Extender = String; + + #[inline] + fn new_builder(&self) -> String { + String::new() + } + #[inline] + fn extend_into(&self, acc: &mut String) { + acc.push(*self); + } +} + +/// Helper trait to convert numbers to usize. +/// +/// By default, usize implements `From` and `From` but not +/// `From` and `From` because that would be invalid on some +/// platforms. This trait implements the conversion for platforms +/// with 32 and 64 bits pointer platforms +pub trait ToUsize { + /// converts self to usize + fn to_usize(&self) -> usize; +} + +impl ToUsize for u8 { + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } +} + +impl ToUsize for u16 { + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } +} + +impl ToUsize for usize { + #[inline] + fn to_usize(&self) -> usize { + *self + } +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +impl ToUsize for u32 { + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } +} + +#[cfg(target_pointer_width = "64")] +impl ToUsize for u64 { + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } +} + +/// Equivalent From implementation to avoid orphan rules in bits parsers +pub trait ErrorConvert { + /// Transform to another error type + fn convert(self) -> E; +} + +impl ErrorConvert<(I, ErrorKind)> for ((I, usize), ErrorKind) { + fn convert(self) -> (I, ErrorKind) { + ((self.0).0, self.1) + } +} + +impl ErrorConvert<((I, usize), ErrorKind)> for (I, ErrorKind) { + fn convert(self) -> ((I, usize), ErrorKind) { + ((self.0, 0), self.1) + } +} + +use crate::error; +impl ErrorConvert> for error::Error<(I, usize)> { + fn convert(self) -> error::Error { + error::Error { + input: self.input.0, + code: self.code, + } + } +} + +impl ErrorConvert> for error::Error { + fn convert(self) -> error::Error<(I, usize)> { + error::Error { + input: (self.input, 0), + code: self.code, + } + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl ErrorConvert> for error::VerboseError<(I, usize)> { + fn convert(self) -> error::VerboseError { + error::VerboseError { + errors: self.errors.into_iter().map(|(i, e)| (i.0, e)).collect(), + } + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +impl ErrorConvert> for error::VerboseError { + fn convert(self) -> error::VerboseError<(I, usize)> { + error::VerboseError { + errors: self.errors.into_iter().map(|(i, e)| ((i, 0), e)).collect(), + } + } +} + +impl ErrorConvert<()> for () { + fn convert(self) {} +} + +#[cfg(feature = "std")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))] +/// Helper trait to show a byte slice as a hex dump +pub trait HexDisplay { + /// Converts the value of `self` to a hex dump, returning the owned + /// `String`. + fn to_hex(&self, chunk_size: usize) -> String; + + /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned + /// `String`. + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String; +} + +#[cfg(feature = "std")] +static CHARS: &[u8] = b"0123456789abcdef"; + +#[cfg(feature = "std")] +impl HexDisplay for [u8] { + #[allow(unused_variables)] + fn to_hex(&self, chunk_size: usize) -> String { + self.to_hex_from(chunk_size, 0) + } + + #[allow(unused_variables)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + let mut v = Vec::with_capacity(self.len() * 3); + let mut i = from; + for chunk in self.chunks(chunk_size) { + let s = format!("{:08x}", i); + for &ch in s.as_bytes().iter() { + v.push(ch); + } + v.push(b'\t'); + + i += chunk_size; + + for &byte in chunk { + v.push(CHARS[(byte >> 4) as usize]); + v.push(CHARS[(byte & 0xf) as usize]); + v.push(b' '); + } + if chunk_size > chunk.len() { + for j in 0..(chunk_size - chunk.len()) { + v.push(b' '); + v.push(b' '); + v.push(b' '); + } + } + v.push(b'\t'); + + for &byte in chunk { + if (byte >= 32 && byte <= 126) || byte >= 128 { + v.push(byte); + } else { + v.push(b'.'); + } + } + v.push(b'\n'); + } + + String::from_utf8_lossy(&v[..]).into_owned() + } +} + +#[cfg(feature = "std")] +impl HexDisplay for str { + #[allow(unused_variables)] + fn to_hex(&self, chunk_size: usize) -> String { + self.to_hex_from(chunk_size, 0) + } + + #[allow(unused_variables)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + self.as_bytes().to_hex_from(chunk_size, from) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_offset_u8() { + let s = b"abcd123"; + let a = &s[..]; + let b = &a[2..]; + let c = &a[..4]; + let d = &a[3..5]; + assert_eq!(a.offset(b), 2); + assert_eq!(a.offset(c), 0); + assert_eq!(a.offset(d), 3); + } + + #[test] + fn test_offset_str() { + let s = "abcřèÂßÇd123"; + let a = &s[..]; + let b = &a[7..]; + let c = &a[..5]; + let d = &a[5..9]; + assert_eq!(a.offset(b), 7); + assert_eq!(a.offset(c), 0); + assert_eq!(a.offset(d), 5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,94 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::char, + character::complete::{digit1 as digit, space0 as space}, + combinator::map_res, + multi::fold_many0, + sequence::{delimited, pair}, + IResult, +}; + +// Parser definition + +use std::str::FromStr; + +// We parse any expr surrounded by parens, ignoring all whitespaces around those +fn parens(i: &str) -> IResult<&str, i64> { + delimited(space, delimited(tag("("), expr, tag(")")), space)(i) +} + +// We transform an integer string into a i64, ignoring surrounding whitespaces +// We look for a digit suite, and try to convert it. +// If either str::from_utf8 or FromStr::from_str fail, +// we fallback to the parens parser defined above +fn factor(i: &str) -> IResult<&str, i64> { + alt(( + map_res(delimited(space, digit, space), FromStr::from_str), + parens, + ))(i) +} + +// We read an initial factor and for each time we find +// a * or / operator followed by another factor, we do +// the math by folding everything +fn term(i: &str) -> IResult<&str, i64> { + let (i, init) = factor(i)?; + + fold_many0( + pair(alt((char('*'), char('/'))), factor), + move || init, + |acc, (op, val): (char, i64)| { + if op == '*' { + acc * val + } else { + acc / val + } + }, + )(i) +} + +fn expr(i: &str) -> IResult<&str, i64> { + let (i, init) = term(i)?; + + fold_many0( + pair(alt((char('+'), char('-'))), term), + move || init, + |acc, (op, val): (char, i64)| { + if op == '+' { + acc + val + } else { + acc - val + } + }, + )(i) +} + +#[test] +fn factor_test() { + assert_eq!(factor("3"), Ok(("", 3))); + assert_eq!(factor(" 12"), Ok(("", 12))); + assert_eq!(factor("537 "), Ok(("", 537))); + assert_eq!(factor(" 24 "), Ok(("", 24))); +} + +#[test] +fn term_test() { + assert_eq!(term(" 12 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 2* 3 *2 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 48 / 3/2"), Ok(("", 8))); +} + +#[test] +fn expr_test() { + assert_eq!(expr(" 1 + 2 "), Ok(("", 3))); + assert_eq!(expr(" 12 + 6 - 4+ 3"), Ok(("", 17))); + assert_eq!(expr(" 1 + 2*3 + 4"), Ok(("", 11))); +} + +#[test] +fn parens_test() { + assert_eq!(expr(" ( 2 )"), Ok(("", 2))); + assert_eq!(expr(" 2* ( 3 + 4 ) "), Ok(("", 14))); + assert_eq!(expr(" 2*2 / ( 5 - 1) + 3"), Ok(("", 4))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic_ast.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic_ast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic_ast.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/arithmetic_ast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,161 @@ +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; + +use std::str::FromStr; + +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{digit1 as digit, multispace0 as multispace}, + combinator::{map, map_res}, + multi::many0, + sequence::{delimited, preceded}, + IResult, +}; + +pub enum Expr { + Value(i64), + Add(Box, Box), + Sub(Box, Box), + Mul(Box, Box), + Div(Box, Box), + Paren(Box), +} + +#[derive(Debug)] +pub enum Oper { + Add, + Sub, + Mul, + Div, +} + +impl Display for Expr { + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use self::Expr::*; + match *self { + Value(val) => write!(format, "{}", val), + Add(ref left, ref right) => write!(format, "{} + {}", left, right), + Sub(ref left, ref right) => write!(format, "{} - {}", left, right), + Mul(ref left, ref right) => write!(format, "{} * {}", left, right), + Div(ref left, ref right) => write!(format, "{} / {}", left, right), + Paren(ref expr) => write!(format, "({})", expr), + } + } +} + +impl Debug for Expr { + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use self::Expr::*; + match *self { + Value(val) => write!(format, "{}", val), + Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right), + Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right), + Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right), + Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right), + Paren(ref expr) => write!(format, "[{:?}]", expr), + } + } +} + +fn parens(i: &str) -> IResult<&str, Expr> { + delimited( + multispace, + delimited(tag("("), map(expr, |e| Expr::Paren(Box::new(e))), tag(")")), + multispace, + )(i) +} + +fn factor(i: &str) -> IResult<&str, Expr> { + alt(( + map( + map_res(delimited(multispace, digit, multispace), FromStr::from_str), + Expr::Value, + ), + parens, + ))(i) +} + +fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr { + remainder.into_iter().fold(initial, |acc, pair| { + let (oper, expr) = pair; + match oper { + Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)), + Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)), + Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)), + Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)), + } + }) +} + +fn term(i: &str) -> IResult<&str, Expr> { + let (i, initial) = factor(i)?; + let (i, remainder) = many0(alt(( + |i| { + let (i, mul) = preceded(tag("*"), factor)(i)?; + Ok((i, (Oper::Mul, mul))) + }, + |i| { + let (i, div) = preceded(tag("/"), factor)(i)?; + Ok((i, (Oper::Div, div))) + }, + )))(i)?; + + Ok((i, fold_exprs(initial, remainder))) +} + +fn expr(i: &str) -> IResult<&str, Expr> { + let (i, initial) = term(i)?; + let (i, remainder) = many0(alt(( + |i| { + let (i, add) = preceded(tag("+"), term)(i)?; + Ok((i, (Oper::Add, add))) + }, + |i| { + let (i, sub) = preceded(tag("-"), term)(i)?; + Ok((i, (Oper::Sub, sub))) + }, + )))(i)?; + + Ok((i, fold_exprs(initial, remainder))) +} + +#[test] +fn factor_test() { + assert_eq!( + factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("3"))) + ); +} + +#[test] +fn term_test() { + assert_eq!( + term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("(3 * 5)"))) + ); +} + +#[test] +fn expr_test() { + assert_eq!( + expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("(1 + (2 * 3))"))) + ); + assert_eq!( + expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)"))) + ); + assert_eq!( + expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("((72 / 2) / 3)"))) + ); +} + +#[test] +fn parens_test() { + assert_eq!( + expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("([(1 + 2)] * 3)"))) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/css.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/css.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/css.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/css.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +use nom::bytes::complete::{tag, take_while_m_n}; +use nom::combinator::map_res; +use nom::sequence::tuple; +use nom::IResult; + +#[derive(Debug, PartialEq)] +pub struct Color { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +fn from_hex(input: &str) -> Result { + u8::from_str_radix(input, 16) +} + +fn is_hex_digit(c: char) -> bool { + c.is_digit(16) +} + +fn hex_primary(input: &str) -> IResult<&str, u8> { + map_res(take_while_m_n(2, 2, is_hex_digit), from_hex)(input) +} + +fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; + + Ok((input, Color { red, green, blue })) +} + +#[test] +fn parse_color() { + assert_eq!( + hex_color("#2F14DF"), + Ok(( + "", + Color { + red: 47, + green: 20, + blue: 223, + } + )) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/custom_errors.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/custom_errors.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/custom_errors.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/custom_errors.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +#![allow(dead_code)] + +use nom::bytes::streaming::tag; +use nom::character::streaming::digit1 as digit; +use nom::combinator::verify; +use nom::error::{ErrorKind, ParseError}; +#[cfg(feature = "alloc")] +use nom::multi::count; +use nom::sequence::terminated; +use nom::IResult; + +#[derive(Debug)] +pub struct CustomError(String); + +impl<'a> From<(&'a str, ErrorKind)> for CustomError { + fn from(error: (&'a str, ErrorKind)) -> Self { + CustomError(format!("error code was: {:?}", error)) + } +} + +impl<'a> ParseError<&'a str> for CustomError { + fn from_error_kind(_: &'a str, kind: ErrorKind) -> Self { + CustomError(format!("error code was: {:?}", kind)) + } + + fn append(_: &'a str, kind: ErrorKind, other: CustomError) -> Self { + CustomError(format!("{:?}\nerror code was: {:?}", other, kind)) + } +} + +fn test1(input: &str) -> IResult<&str, &str, CustomError> { + //fix_error!(input, CustomError, tag!("abcd")) + tag("abcd")(input) +} + +fn test2(input: &str) -> IResult<&str, &str, CustomError> { + //terminated!(input, test1, fix_error!(CustomError, digit)) + terminated(test1, digit)(input) +} + +fn test3(input: &str) -> IResult<&str, &str, CustomError> { + verify(test1, |s: &str| s.starts_with("abcd"))(input) +} + +#[cfg(feature = "alloc")] +fn test4(input: &str) -> IResult<&str, Vec<&str>, CustomError> { + count(test1, 4)(input) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/escaped.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/escaped.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/escaped.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/escaped.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +use nom::bytes::complete::escaped; +use nom::character::complete::digit1; +use nom::character::complete::one_of; +use nom::{error::ErrorKind, Err, IResult}; + +fn esc(s: &str) -> IResult<&str, &str, (&str, ErrorKind)> { + escaped(digit1, '\\', one_of("\"n\\"))(s) +} + +#[cfg(feature = "alloc")] +fn esc_trans(s: &str) -> IResult<&str, String, (&str, ErrorKind)> { + use nom::bytes::complete::{escaped_transform, tag}; + escaped_transform(digit1, '\\', tag("n"))(s) +} + +#[test] +fn test_escaped() { + assert_eq!(esc("abcd"), Err(Err::Error(("abcd", ErrorKind::Escaped)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn test_escaped_transform() { + assert_eq!( + esc_trans("abcd"), + Err(Err::Error(("abcd", ErrorKind::EscapedTransform))) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/float.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/float.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::character::streaming::digit1 as digit; +use nom::combinator::{map, map_res, opt, recognize}; +use nom::sequence::{delimited, pair}; +use nom::IResult; + +use std::str; +use std::str::FromStr; + +fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> { + let float_bytes = recognize(alt(( + delimited(digit, tag("."), opt(digit)), + delimited(opt(digit), tag("."), digit), + ))); + let float_str = map_res(float_bytes, str::from_utf8); + map_res(float_str, FromStr::from_str)(i) +} + +fn float(i: &[u8]) -> IResult<&[u8], f32> { + map( + pair(opt(alt((tag("+"), tag("-")))), unsigned_float), + |(sign, value)| { + sign + .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None }) + .unwrap_or(1f32) + * value + }, + )(i) +} + +#[test] +fn unsigned_float_test() { + assert_eq!(unsigned_float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(unsigned_float(&b"0.123;"[..]), Ok((&b";"[..], 0.123))); + assert_eq!(unsigned_float(&b"123.0;"[..]), Ok((&b";"[..], 123.0))); + assert_eq!(unsigned_float(&b"123.;"[..]), Ok((&b";"[..], 123.0))); + assert_eq!(unsigned_float(&b".123;"[..]), Ok((&b";"[..], 0.123))); +} + +#[test] +fn float_test() { + assert_eq!(float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/fnmut.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/fnmut.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/fnmut.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/fnmut.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +use nom::{ + bytes::complete::tag, + multi::{many0, many0_count}, +}; + +#[test] +fn parse() { + let mut counter = 0; + + let res = { + let mut parser = many0::<_, _, (), _>(|i| { + counter += 1; + tag("abc")(i) + }); + + parser("abcabcabcabc").unwrap() + }; + + println!("res: {:?}", res); + assert_eq!(counter, 5); +} + +#[test] +fn accumulate() { + let mut v = Vec::new(); + + let (_, count) = { + let mut parser = many0_count::<_, _, (), _>(|i| { + let (i, o) = tag("abc")(i)?; + v.push(o); + Ok((i, ())) + }); + parser("abcabcabcabc").unwrap() + }; + + println!("v: {:?}", v); + assert_eq!(count, 4); + assert_eq!(v.len(), 4); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/ini.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/ini.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,207 @@ +use nom::{ + bytes::complete::take_while, + character::complete::{ + alphanumeric1 as alphanumeric, char, multispace0 as multispace, space0 as space, + }, + combinator::{map, map_res, opt}, + multi::many0, + sequence::{delimited, pair, separated_pair, terminated, tuple}, + IResult, +}; + +use std::collections::HashMap; +use std::str; + +fn category(i: &[u8]) -> IResult<&[u8], &str> { + map_res( + delimited(char('['), take_while(|c| c != b']'), char(']')), + str::from_utf8, + )(i) +} + +fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> { + let (i, key) = map_res(alphanumeric, str::from_utf8)(i)?; + let (i, _) = tuple((opt(space), char('='), opt(space)))(i)?; + let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8)(i)?; + let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n')))(i)?; + Ok((i, (key, val))) +} + +fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> { + map(many0(terminated(key_value, opt(multispace))), |vec| { + vec.into_iter().collect() + })(i) +} + +fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> { + let (i, category) = terminated(category, opt(multispace))(i)?; + let (i, keys) = keys_and_values(i)?; + Ok((i, (category, keys))) +} + +fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> { + map( + many0(separated_pair( + category, + opt(multispace), + map( + many0(terminated(key_value, opt(multispace))), + |vec: Vec<_>| vec.into_iter().collect(), + ), + )), + |vec: Vec<_>| vec.into_iter().collect(), + )(i) +} + +#[test] +fn parse_category_test() { + let ini_file = &b"[category] + +parameter=value +key = value2"[..]; + + let ini_without_category = &b"\n\nparameter=value +key = value2"[..]; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = &b"parameter=value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = &b"parameter = value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = &b"parameter=value;abc +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_keys_and_values_test() { + let ini_file = &b"parameter=value;abc + +key = value2 + +[category]"[..]; + + let ini_without_key_value = &b"[category]"[..]; + + let res = keys_and_values(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected: HashMap<&str, &str> = HashMap::new(); + expected.insert("parameter", "value"); + expected.insert("key", "value2"); + assert_eq!(res, Ok((ini_without_key_value, expected))); +} + +#[test] +fn parse_category_then_multiple_keys_and_values_test() { + //FIXME: there can be an empty line or a comment line after a category + let ini_file = &b"[abcd] +parameter=value;abc + +key = value2 + +[category]"[..]; + + let ini_after_parser = &b"[category]"[..]; + + let res = category_and_keys(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected_h: HashMap<&str, &str> = HashMap::new(); + expected_h.insert("parameter", "value"); + expected_h.insert("key", "value2"); + assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h)))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = &b"[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"[..]; + + let ini_after_parser = &b""[..]; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok((ini_after_parser, expected_h))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/ini_str.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini_str.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/ini_str.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/ini_str.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +use nom::{ + bytes::complete::{is_a, tag, take_till, take_while}, + character::complete::{alphanumeric1 as alphanumeric, char, space0 as space}, + combinator::opt, + multi::many0, + sequence::{delimited, pair, terminated, tuple}, + IResult, +}; + +use std::collections::HashMap; + +fn is_line_ending_or_comment(chr: char) -> bool { + chr == ';' || chr == '\n' +} + +fn not_line_ending(i: &str) -> IResult<&str, &str> { + take_while(|c| c != '\r' && c != '\n')(i) +} + +fn space_or_line_ending(i: &str) -> IResult<&str, &str> { + is_a(" \r\n")(i) +} + +fn category(i: &str) -> IResult<&str, &str> { + terminated( + delimited(char('['), take_while(|c| c != ']'), char(']')), + opt(is_a(" \r\n")), + )(i) +} + +fn key_value(i: &str) -> IResult<&str, (&str, &str)> { + let (i, key) = alphanumeric(i)?; + let (i, _) = tuple((opt(space), tag("="), opt(space)))(i)?; + let (i, val) = take_till(is_line_ending_or_comment)(i)?; + let (i, _) = opt(space)(i)?; + let (i, _) = opt(pair(tag(";"), not_line_ending))(i)?; + let (i, _) = opt(space_or_line_ending)(i)?; + + Ok((i, (key, val))) +} + +fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> { + many0(key_value)(i) +} + +fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> { + match keys_and_values_aggregator(input) { + Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())), + Err(e) => Err(e), + } +} + +fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> { + pair(category, keys_and_values)(i) +} + +fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> { + many0(category_and_keys)(i) +} + +fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> { + match categories_aggregator(input) { + Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())), + Err(e) => Err(e), + } +} + +#[test] +fn parse_category_test() { + let ini_file = "[category] + +parameter=value +key = value2"; + + let ini_without_category = "parameter=value +key = value2"; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = "parameter=value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = "parameter = value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = "parameter=value;abc +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_keys_and_values_test() { + let ini_file = "parameter=value;abc + +key = value2 + +[category]"; + + let ini_without_key_value = "[category]"; + + let res = keys_and_values(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected: HashMap<&str, &str> = HashMap::new(); + expected.insert("parameter", "value"); + expected.insert("key", "value2"); + assert_eq!(res, Ok((ini_without_key_value, expected))); +} + +#[test] +fn parse_category_then_multiple_keys_and_values_test() { + //FIXME: there can be an empty line or a comment line after a category + let ini_file = "[abcd] +parameter=value;abc + +key = value2 + +[category]"; + + let ini_after_parser = "[category]"; + + let res = category_and_keys(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_h: HashMap<&str, &str> = HashMap::new(); + expected_h.insert("parameter", "value"); + expected_h.insert("key", "value2"); + assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h)))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = "[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok(("", expected_h))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/issues.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/issues.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/issues.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/issues.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,242 @@ +//#![feature(trace_macros)] +#![allow(dead_code)] +#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))] + +use nom::{error::ErrorKind, Err, IResult, Needed}; + +#[allow(dead_code)] +struct Range { + start: char, + end: char, +} + +pub fn take_char(input: &[u8]) -> IResult<&[u8], char> { + if !input.is_empty() { + Ok((&input[1..], input[0] as char)) + } else { + Err(Err::Incomplete(Needed::new(1))) + } +} + +#[cfg(feature = "std")] +mod parse_int { + use nom::HexDisplay; + use nom::{ + character::streaming::{digit1 as digit, space1 as space}, + combinator::{complete, map, opt}, + multi::many0, + IResult, + }; + use std::str; + + fn parse_ints(input: &[u8]) -> IResult<&[u8], Vec> { + many0(spaces_or_int)(input) + } + + fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> { + println!("{}", input.to_hex(8)); + let (i, _) = opt(complete(space))(input)?; + let (i, res) = map(complete(digit), |x| { + println!("x: {:?}", x); + let result = str::from_utf8(x).unwrap(); + println!("Result: {}", result); + println!("int is empty?: {}", x.is_empty()); + match result.parse() { + Ok(i) => i, + Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e), + } + })(i)?; + + Ok((i, res)) + } + + #[test] + fn issue_142() { + let subject = parse_ints(&b"12 34 5689a"[..]); + let expected = Ok((&b"a"[..], vec![12, 34, 5689])); + assert_eq!(subject, expected); + + let subject = parse_ints(&b"12 34 5689 "[..]); + let expected = Ok((&b" "[..], vec![12, 34, 5689])); + assert_eq!(subject, expected) + } +} + +#[test] +fn usize_length_bytes_issue() { + use nom::multi::length_data; + use nom::number::streaming::be_u16; + let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16)(b"012346"); +} + +#[test] +fn take_till_issue() { + use nom::bytes::streaming::take_till; + + fn nothing(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_till(|_| true)(i) + } + + assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::new(1)))); + assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..]))); +} + +#[test] +fn issue_655() { + use nom::character::streaming::{line_ending, not_line_ending}; + fn twolines(i: &str) -> IResult<&str, (&str, &str)> { + let (i, l1) = not_line_ending(i)?; + let (i, _) = line_ending(i)?; + let (i, l2) = not_line_ending(i)?; + let (i, _) = line_ending(i)?; + + Ok((i, (l1, l2))) + } + + assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar")))); + assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar")))); + assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar")))); + assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar")))); +} + +#[cfg(feature = "alloc")] +fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + use nom::bytes::complete::{is_not, tag}; + use nom::multi::separated_list0; + + separated_list0(tag([0x0]), is_not([0x0u8]))(i) +} + +mod issue_647 { + use nom::bytes::streaming::tag; + use nom::combinator::complete; + use nom::multi::separated_list0; + use nom::{error::Error, number::streaming::be_f64, Err, IResult}; + pub type Input<'a> = &'a [u8]; + + #[derive(PartialEq, Debug, Clone)] + struct Data { + c: f64, + v: Vec, + } + + fn list<'a, 'b>( + input: Input<'a>, + _cs: &'b f64, + ) -> Result<(Input<'a>, Vec), Err>> { + separated_list0(complete(tag(",")), complete(be_f64))(input) + } + + fn data(input: Input<'_>) -> IResult, Data> { + let (i, c) = be_f64(input)?; + let (i, _) = tag("\n")(i)?; + let (i, v) = list(i, &c)?; + Ok((i, Data { c, v })) + } +} + +#[test] +fn issue_848_overflow_incomplete_bits_to_bytes() { + fn take(i: &[u8]) -> IResult<&[u8], &[u8]> { + use nom::bytes::streaming::take; + take(0x2000000000000000_usize)(i) + } + fn parser(i: &[u8]) -> IResult<&[u8], &[u8]> { + use nom::bits::{bits, bytes}; + + bits(bytes(take))(i) + } + assert_eq!( + parser(&b""[..]), + Err(Err::Failure(nom::error_position!( + &b""[..], + ErrorKind::TooLarge + ))) + ); +} + +#[test] +fn issue_942() { + use nom::error::{ContextError, ParseError}; + pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str>>( + i: &'a str, + ) -> IResult<&'a str, usize, E> { + use nom::{character::complete::char, error::context, multi::many0_count}; + many0_count(context("char_a", char('a')))(i) + } + assert_eq!(parser::<()>("aaa"), Ok(("", 3))); +} + +#[test] +fn issue_many_m_n_with_zeros() { + use nom::character::complete::char; + use nom::multi::many_m_n; + let mut parser = many_m_n::<_, _, (), _>(0, 0, char('a')); + assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); +} + +#[test] +fn issue_1027_convert_error_panic_nonempty() { + use nom::character::complete::char; + use nom::error::{convert_error, VerboseError}; + use nom::sequence::pair; + + let input = "a"; + + let result: IResult<_, _, VerboseError<&str>> = pair(char('a'), char('b'))(input); + let err = match result.unwrap_err() { + Err::Error(e) => e, + _ => unreachable!(), + }; + + let msg = convert_error(input, err); + assert_eq!( + msg, + "0: at line 1:\na\n ^\nexpected \'b\', got end of input\n\n" + ); +} + +#[test] +fn issue_1231_bits_expect_fn_closure() { + use nom::bits::{bits, complete::take}; + use nom::error::Error; + use nom::sequence::tuple; + pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> { + bits::<_, _, Error<_>, _, _>(tuple((take(1usize), take(1usize))))(input) + } + assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1)))); +} + +#[test] +fn issue_1282_findtoken_char() { + use nom::character::complete::one_of; + use nom::error::Error; + let parser = one_of::<_, _, Error<_>>(&['a', 'b', 'c'][..]); + assert_eq!(parser("aaa"), Ok(("aa", 'a'))); +} + +#[test] +fn issue_1459_clamp_capacity() { + use nom::character::complete::char; + + // shouldn't panic + use nom::multi::many_m_n; + let mut parser = many_m_n::<_, _, (), _>(usize::MAX, usize::MAX, char('a')); + assert_eq!(parser("a"), Err(nom::Err::Error(()))); + + // shouldn't panic + use nom::multi::count; + let mut parser = count::<_, _, (), _>(char('a'), usize::MAX); + assert_eq!(parser("a"), Err(nom::Err::Error(()))); +} + +#[test] +fn issue_1617_count_parser_returning_zero_size() { + use nom::{bytes::complete::tag, combinator::map, error::Error, multi::count}; + + // previously, `count()` panicked if the parser had type `O = ()` + let parser = map(tag::<_, _, Error<&str>>("abc"), |_| ()); + // shouldn't panic + let result = count(parser, 3)("abcabcabcdef").expect("parsing should succeed"); + assert_eq!(result, ("def", vec![(), (), ()])); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/json.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/json.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/json.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/json.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,236 @@ +#![cfg(feature = "alloc")] + +use nom::{ + branch::alt, + bytes::complete::{tag, take}, + character::complete::{anychar, char, multispace0, none_of}, + combinator::{map, map_opt, map_res, value, verify}, + error::ParseError, + multi::{fold_many0, separated_list0}, + number::complete::double, + sequence::{delimited, preceded, separated_pair}, + IResult, Parser, +}; + +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Clone)] +pub enum JsonValue { + Null, + Bool(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), +} + +fn boolean(input: &str) -> IResult<&str, bool> { + alt((value(false, tag("false")), value(true, tag("true"))))(input) +} + +fn u16_hex(input: &str) -> IResult<&str, u16> { + map_res(take(4usize), |s| u16::from_str_radix(s, 16))(input) +} + +fn unicode_escape(input: &str) -> IResult<&str, char> { + map_opt( + alt(( + // Not a surrogate + map(verify(u16_hex, |cp| !(0xD800..0xE000).contains(cp)), |cp| { + cp as u32 + }), + // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details + map( + verify( + separated_pair(u16_hex, tag("\\u"), u16_hex), + |(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low), + ), + |(high, low)| { + let high_ten = (high as u32) - 0xD800; + let low_ten = (low as u32) - 0xDC00; + (high_ten << 10) + low_ten + 0x10000 + }, + ), + )), + // Could be probably replaced with .unwrap() or _unchecked due to the verify checks + std::char::from_u32, + )(input) +} + +fn character(input: &str) -> IResult<&str, char> { + let (input, c) = none_of("\"")(input)?; + if c == '\\' { + alt(( + map_res(anychar, |c| { + Ok(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return Err(()), + }) + }), + preceded(char('u'), unicode_escape), + ))(input) + } else { + Ok((input, c)) + } +} + +fn string(input: &str) -> IResult<&str, String> { + delimited( + char('"'), + fold_many0(character, String::new, |mut string, c| { + string.push(c); + string + }), + char('"'), + )(input) +} + +fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> { + delimited(multispace0, f, multispace0) +} + +fn array(input: &str) -> IResult<&str, Vec> { + delimited( + char('['), + ws(separated_list0(ws(char(',')), json_value)), + char(']'), + )(input) +} + +fn object(input: &str) -> IResult<&str, HashMap> { + map( + delimited( + char('{'), + ws(separated_list0( + ws(char(',')), + separated_pair(string, ws(char(':')), json_value), + )), + char('}'), + ), + |key_values| key_values.into_iter().collect(), + )(input) +} + +fn json_value(input: &str) -> IResult<&str, JsonValue> { + use JsonValue::*; + + alt(( + value(Null, tag("null")), + map(boolean, Bool), + map(string, Str), + map(double, Num), + map(array, Array), + map(object, Object), + ))(input) +} + +fn json(input: &str) -> IResult<&str, JsonValue> { + ws(json_value).parse(input) +} + +#[test] +fn json_string() { + assert_eq!(string("\"\""), Ok(("", "".to_string()))); + assert_eq!(string("\"abc\""), Ok(("", "abc".to_string()))); + assert_eq!( + string("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""), + Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01——def".to_string())), + ); + assert_eq!(string("\"\\uD83D\\uDE10\""), Ok(("", "😐".to_string()))); + + assert!(string("\"").is_err()); + assert!(string("\"abc").is_err()); + assert!(string("\"\\\"").is_err()); + assert!(string("\"\\u123\"").is_err()); + assert!(string("\"\\uD800\"").is_err()); + assert!(string("\"\\uD800\\uD800\"").is_err()); + assert!(string("\"\\uDC00\"").is_err()); +} + +#[test] +fn json_object() { + use JsonValue::*; + + let input = r#"{"a":42,"b":"x"}"#; + + let expected = Object( + vec![ + ("a".to_string(), Num(42.0)), + ("b".to_string(), Str("x".to_string())), + ] + .into_iter() + .collect(), + ); + + assert_eq!(json(input), Ok(("", expected))); +} + +#[test] +fn json_array() { + use JsonValue::*; + + let input = r#"[42,"x"]"#; + + let expected = Array(vec![Num(42.0), Str("x".to_string())]); + + assert_eq!(json(input), Ok(("", expected))); +} + +#[test] +fn json_whitespace() { + use JsonValue::*; + + let input = r#" + { + "null" : null, + "true" :true , + "false": false , + "number" : 123e4 , + "string" : " abc 123 " , + "array" : [ false , 1 , "two" ] , + "object" : { "a" : 1.0 , "b" : "c" } , + "empty_array" : [ ] , + "empty_object" : { } + } + "#; + + assert_eq!( + json(input), + Ok(( + "", + Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Bool(true)), + ("false".to_string(), Bool(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Bool(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + ) + )) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/mp4.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/mp4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/mp4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/mp4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,320 @@ +#![allow(dead_code)] + +use nom::{ + branch::alt, + bytes::streaming::{tag, take}, + combinator::{map, map_res}, + error::ErrorKind, + multi::many0, + number::streaming::{be_f32, be_u16, be_u32, be_u64}, + Err, IResult, Needed, +}; + +use std::str; + +fn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> { + match be_u32(input) { + Ok((i, offset)) => { + let sz: usize = offset as usize; + if i.len() >= sz - 4 { + Ok((&i[(sz - 4)..], &i[0..(sz - 4)])) + } else { + Err(Err::Incomplete(Needed::new(offset as usize + 4))) + } + } + Err(e) => Err(e), + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[derive(PartialEq,Eq,Debug)] +struct FileType<'a> { + major_brand: &'a str, + major_brand_version: &'a [u8], + compatible_brands: Vec<&'a str> +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd32 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u32, + modified_date: u32, + scale: u32, + duration: u32, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd64 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u64, + modified_date: u64, + scale: u32, + duration: u64, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd32(i: &[u8]) -> IResult<&[u8], MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u32(i)?; + let (i, modified_date) = be_u32(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u32(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M32(Mvhd32 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd64(i: &[u8]) -> IResult<&[u8], MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u64(i)?; + let (i, modified_date) = be_u64(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u64(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M64(Mvhd64 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[derive(Debug, Clone)] +pub enum MvhdBox { + M32(Mvhd32), + M64(Mvhd64), +} + +#[derive(Debug, Clone)] +pub enum MoovBox { + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd(MvhdBox), + Clip, + Trak, + Udta, +} + +#[derive(Debug)] +enum MP4BoxType { + Ftyp, + Moov, + Mdat, + Free, + Skip, + Wide, + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd, + Clip, + Trak, + Udta, + Unknown, +} + +#[derive(Debug)] +struct MP4BoxHeader { + length: u32, + tag: MP4BoxType, +} + +fn brand_name(input: &[u8]) -> IResult<&[u8], &str> { + map_res(take(4_usize), str::from_utf8)(input) +} + +fn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType<'_>> { + let (i, name) = brand_name(input)?; + let (i, version) = take(4_usize)(i)?; + let (i, brands) = many0(brand_name)(i)?; + + let ft = FileType { + major_brand: name, + major_brand_version: version, + compatible_brands: brands, + }; + Ok((i, ft)) +} + +fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> { + let res = if input.len() < 100 { + Err(Err::Incomplete(Needed::new(100))) + } else if input.len() == 100 { + mvhd32(input) + } else if input.len() == 112 { + mvhd64(input) + } else { + Err(Err::Error(nom::error_position!(input, ErrorKind::TooLarge))) + }; + println!("res: {:?}", res); + res +} + +fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + Ok((input, MP4BoxType::Unknown)) +} + +fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + alt(( + map(tag("ftyp"), |_| MP4BoxType::Ftyp), + map(tag("moov"), |_| MP4BoxType::Moov), + map(tag("mdat"), |_| MP4BoxType::Mdat), + map(tag("free"), |_| MP4BoxType::Free), + map(tag("skip"), |_| MP4BoxType::Skip), + map(tag("wide"), |_| MP4BoxType::Wide), + unknown_box_type, + ))(input) +} + +// warning, an alt combinator with 9 branches containing a tag combinator +// can make the compilation very slow. Use functions as sub parsers, +// or split into multiple alt parsers if it gets slow +fn moov_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + alt(( + map(tag("mdra"), |_| MP4BoxType::Mdra), + map(tag("dref"), |_| MP4BoxType::Dref), + map(tag("cmov"), |_| MP4BoxType::Cmov), + map(tag("rmra"), |_| MP4BoxType::Rmra), + map(tag("iods"), |_| MP4BoxType::Iods), + map(tag("mvhd"), |_| MP4BoxType::Mvhd), + map(tag("clip"), |_| MP4BoxType::Clip), + map(tag("trak"), |_| MP4BoxType::Trak), + map(tag("udta"), |_| MP4BoxType::Udta), + ))(input) +} + +fn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = box_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} + +fn moov_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = moov_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/multiline.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/multiline.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/multiline.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/multiline.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +use nom::{ + character::complete::{alphanumeric1 as alphanumeric, line_ending as eol}, + multi::many0, + sequence::terminated, + IResult, +}; + +pub fn end_of_line(input: &str) -> IResult<&str, &str> { + if input.is_empty() { + Ok((input, input)) + } else { + eol(input) + } +} + +pub fn read_line(input: &str) -> IResult<&str, &str> { + terminated(alphanumeric, end_of_line)(input) +} + +pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> { + many0(read_line)(input) +} + +#[cfg(feature = "alloc")] +#[test] +fn read_lines_test() { + let res = Ok(("", vec!["Duck", "Dog", "Cow"])); + + assert_eq!(read_lines("Duck\nDog\nCow\n"), res); + assert_eq!(read_lines("Duck\nDog\nCow"), res); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/overflow.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/overflow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/overflow.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/overflow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,145 @@ +#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#![cfg(target_pointer_width = "64")] + +use nom::bytes::streaming::take; +#[cfg(feature = "alloc")] +use nom::multi::{length_data, many0}; +#[cfg(feature = "alloc")] +use nom::number::streaming::be_u64; +use nom::sequence::tuple; +use nom::{Err, IResult, Needed}; + +// Parser definition + +// We request a length that would trigger an overflow if computing consumed + requested +fn parser02(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + tuple((take(1_usize), take(18446744073709551615_usize)))(i) +} + +#[test] +fn overflow_incomplete_tuple() { + assert_eq!( + parser02(&b"3"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551615))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_length_bytes() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + // Trigger an overflow in length_data + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551615))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many0() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + // Trigger an overflow in many0 + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many1() { + use nom::multi::many1; + + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many1(length_data(be_u64))(i) + } + + // Trigger an overflow in many1 + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many_till() { + use nom::{bytes::complete::tag, multi::many_till}; + + fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { + many_till(length_data(be_u64), tag("abc"))(i) + } + + // Trigger an overflow in many_till + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many_m_n() { + use nom::multi::many_m_n; + + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many_m_n(2, 4, length_data(be_u64))(i) + } + + // Trigger an overflow in many_m_n + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_count() { + use nom::multi::count; + + fn counter(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + count(length_data(be_u64), 2)(i) + } + + assert_eq!( + counter(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_length_count() { + use nom::multi::length_count; + use nom::number::streaming::be_u8; + + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + length_count(be_u8, length_data(be_u64))(i) + } + + assert_eq!( + multi(&b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551598))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_length_data() { + fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + assert_eq!( + multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]), + Err(Err::Incomplete(Needed::new(18446744073709551615))) + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/reborrow_fold.rs clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/reborrow_fold.rs --- clamav-1.4.3+dfsg/.cargo/vendor/nom-7.1.3/tests/reborrow_fold.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/nom-7.1.3/tests/reborrow_fold.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +#![allow(dead_code)] +// #![allow(unused_variables)] + +use std::str; + +use nom::bytes::complete::is_not; +use nom::character::complete::char; +use nom::combinator::{map, map_res}; +use nom::multi::fold_many0; +use nom::sequence::delimited; +use nom::IResult; + +fn atom<'a>(_tomb: &'a mut ()) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], String> { + move |input| { + map( + map_res(is_not(" \t\r\n"), str::from_utf8), + ToString::to_string, + )(input) + } +} + +// FIXME: should we support the use case of borrowing data mutably in a parser? +fn list<'a>(i: &'a [u8], tomb: &'a mut ()) -> IResult<&'a [u8], String> { + delimited( + char('('), + fold_many0(atom(tomb), String::new, |acc: String, next: String| { + acc + next.as_str() + }), + char(')'), + )(i) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"90658ea608d8a1f2d7dc2a4fd96d6c8286a12cc2f215016f5320f8061416fa4f","Cargo.toml":"1d033874b1d2a89405aa922e28343de447691d731f78c4231bfc3fd91db9c87a","Cargo.toml.orig":"4be957ac834a640991fa7a538272483ebab1ae9ffcd065c93a102caf23cd3e52","LICENSE":"d69f24ad84ec2ade64c0b68bdb31b41170e997b158370342056918329cc9af1e","README.md":"d0c676701866ef0be72d02af98d65e23858666a466c84a3cb094679e1dd1b993","src/lib.rs":"1120643a52492bdd66863a9b84abe4dd77bde57f189f1c7e68c7a44657b2541f","tests/serde.rs":"b79b7a53eb91ec38c1f5122246000aeda49b43510e8800278ba52ee7edd840f4","tests/wasm_bindgen.rs":"d8e987ca90ce8552cca69ebb51df2729ce39c3cbfc4b24569a6c050f3da93fa7"},"package":"0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "8c20bc579f63561372a2243d340cedb8c7f64a9d" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "noop_proc_macro" +version = "0.3.0" +authors = ["Luca Barbato "] +description = "No-op proc_macro, literally does nothing" +readme = "README.md" +keywords = ["proc_macro", "noop"] +license = "MIT" +repository = "https://github.com/lu-zero/noop_proc_macro" + +[lib] +test = false +proc-macro = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/Cargo.toml.orig 2020-06-19 11:56:53.000000000 +0000 @@ -0,0 +1,15 @@ +[package] +name = "noop_proc_macro" +version = "0.3.0" +authors = ["Luca Barbato "] +edition = "2018" +description = "No-op proc_macro, literally does nothing" +repository = "https://github.com/lu-zero/noop_proc_macro" +readme = "README.md" +keywords = ["proc_macro", "noop"] +license = "MIT" + +[lib] +proc-macro = true +test = false + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/LICENSE 2019-11-09 06:05:48.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Luca Barbato + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/README.md clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/README.md 2020-06-19 11:56:30.000000000 +0000 @@ -0,0 +1,17 @@ +# NoOp proc macro + +NoOp mocks for `proc_macros` that you might want to make optional. + +``` rust +#[cfg(feature = "serde")] +pub(crate) use serde_derive::{Serialize, Deserialize}; + +#[cfg(not(feature = "serde")] +pub(crate) use noop_proc_macro::{Serialize, Deserialize}; +``` + +## Supported `proc_macros` + +- [Serde](https://serde.rs) +- [rust-hawktracer](https://github.com/AlexEne/rust_hawktracer) +- [wasm_bindgen](https://github.com/rustwasm/wasm-bindgen) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/src/lib.rs 2020-06-19 11:56:30.000000000 +0000 @@ -0,0 +1,29 @@ +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_derive(Serialize, attributes(serde))] +pub fn serialize(_items: proc_macro::TokenStream) -> proc_macro::TokenStream { + proc_macro::TokenStream::new() +} + +#[proc_macro_derive(Deserialize, attributes(serde))] +pub fn deserialize(_items: proc_macro::TokenStream) -> proc_macro::TokenStream { + proc_macro::TokenStream::new() +} + +#[proc_macro_attribute] +pub fn hawktracer(_args: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro] +pub fn scoped_tracepoint(_item: TokenStream) -> TokenStream { + TokenStream::new() +} + +/// https://docs.rs/wasm-bindgen-macro/0.2.63/src/wasm_bindgen_macro/lib.rs.html#9-19 +#[proc_macro_attribute] +pub fn wasm_bindgen(_attr: TokenStream, input: TokenStream) -> TokenStream { + input +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/tests/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/tests/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/serde.rs 2019-11-09 06:05:48.000000000 +0000 @@ -0,0 +1,13 @@ +use noop_proc_macro::Deserialize; +use noop_proc_macro::Serialize; + +#[derive(Serialize, Deserialize)] +struct S { + #[serde(default)] + a: usize, +} + +#[test] +fn test() { + let _ = S { a: 0 }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/tests/wasm_bindgen.rs clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/wasm_bindgen.rs --- clamav-1.4.3+dfsg/.cargo/vendor/noop_proc_macro/tests/wasm_bindgen.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/noop_proc_macro/tests/wasm_bindgen.rs 2020-06-19 11:56:30.000000000 +0000 @@ -0,0 +1,11 @@ +use noop_proc_macro::wasm_bindgen; + +#[wasm_bindgen] +struct S { + a: usize, +} + +#[test] +fn test() { + let _ = S { a: 0 }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"0cc26572b740506a14fbb4922d6f8400ce5159af36f66dd5576980195eec6c22","Cargo.toml":"a6042603541ecb91ec1f5c158679c0b47090462434e2a53e65f78395994f223f","Cargo.toml.orig":"f4aa7137c73c73c175cf68cbbf78eca76082f60a4d1612d9bdfd6bba5661b9d6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"abf3dae8d5ccf7693234cb0101a205f844959366bc906a1a5b53973a73a3054c","RELEASES.md":"80b60df30e92e913d710e558f1a2de0baa8a3e49b242c66bc1a1a18de5ff4618","benches/bigint.rs":"0943fcfdc290db028bc37d63c118284c79681a52a62311cc036da80d3b9ac390","benches/factorial.rs":"ed1d276a780e7e5fe79121b941c22a00c2854dbf92fd8a5372619853ba0c13b7","benches/gcd.rs":"3cc1a3356f680a6fa625f0ece0c8dd778f4091a53a31177f2870ef9a6c858c7d","benches/rng/mod.rs":"38144fc8283955db4be72a1533328fded98986d6f9d0bc7da0b306f7d4b5ca43","benches/roots.rs":"b31846852a7215c26df228940f2e469aff32fa8805eccc2b5ee5e7280ef0eeb4","benches/shootout-pidigits.rs":"c2a48133f5b679928f7e3f4e764c78aaa8c5b811f58b86fe57fae8c63cb07136","src/bigint.rs":"e5735688e1345396c21a7f5e8328bcdf77f5a0c7068028caa74063c68a3e4ef7","src/bigint/addition.rs":"cdc28e59a5dc6fe7dbad2d8d9514b49fe1bea061e82ebefe89c518f448dc8ba9","src/bigint/arbitrary.rs":"9fb1f7f8bbc7a792d19d4c30ed2671ed2d73847d57e5f65380ae31e5db0146c6","src/bigint/bits.rs":"3d696d43bcd336690ce1412af75a38d490fd2af745c2efc7cb2fc51bace07de8","src/bigint/convert.rs":"1463ecd5e39c938ae5b8e2b685d69a85c2e795c1fa96531b2192abb11ccdf638","src/bigint/division.rs":"dea89b4efb06b77bbbf07036c454d52f4d026658bcbacad1d15302c93d61b3dd","src/bigint/multiplication.rs":"c262f732b86cc36804895df21e5ea5221944cadc1fca7903ff75a26102ba70f1","src/bigint/power.rs":"a3823654f022014c5ce2dc2fd97afa6696589d32a54cc4ec65e6c113e8613672","src/bigint/serde.rs":"a7275341ec518f27f4d955e95b6e302b786944e9462bf0c17c7087d073212943","src/bigint/shift.rs":"3f28bca2d52621133cdf567290645d30a746e663d8dacea29c172b5ed7ff3538","src/bigint/subtraction.rs":"c2aa7e0fbfc7747099d0eec77efdedaa8d79cff88b1587d640d6b1c3c7dc0e4a","src/bigrand.rs":"115ab17de1c909b22bf20374b31cf5b1e9b28cd4914bf8cd6852375c35d6a027","src/biguint.rs":"bf69f80a59b528e0743390663f9a6a8f6d3edc8643a65c8d0f7f01a8f434f478","src/biguint/addition.rs":"1429575654102731024259da7d5586a4db44387ae86c1b170083c5565b37b410","src/biguint/arbitrary.rs":"3492432d1b5e9f851ce120549bf82e89ba2b6c51f584f8d9ac6782fe10fb58dc","src/biguint/bits.rs":"509036c6c6cb083d4568f92ac852cf5f12510f98c4547d47a80e3db4282a159e","src/biguint/convert.rs":"85cdb3e60856d281f45dff602960666fe44af0ab54ba2ce26cfa4018a9309c60","src/biguint/division.rs":"13ed075f244510eb0354b899b8b9d99216d202bd4eae445ee18a444e06dd708b","src/biguint/iter.rs":"6f843751c93520817a182a2a335001ff221478499eb765d09a0a6f19ba0f7f97","src/biguint/monty.rs":"68851ce7542acdc180431905668684dcadf7d5b422073c6d8acc418ceb86f5d0","src/biguint/multiplication.rs":"e3908aecda0fbbf8c97c96d1d9b24ff9bbe4e09df3b15e460e00c73ecf1c0e4e","src/biguint/power.rs":"4740974546f85da802f7fee4a7c595a8d1b46611914130237cd26c20c268db84","src/biguint/serde.rs":"f4d4e6f2d56c9bab95d8b178682ebeba88965a36bcff42ccade3334712c9977a","src/biguint/shift.rs":"4962ff0d8d0371e7ab39b00a9fc29907e5cd37b9819f61d5ef82ff13b0f55071","src/biguint/subtraction.rs":"b124b9a12bdb67cadb98050feba8cd04fcd22e985c2f994b7c473d38b94f4821","src/lib.rs":"70493e8293b769076d6a16df962a4913b74aa1925fe8bd448865da097ee2dbe1","src/macros.rs":"ab2a5b6e39538f62fdf39f6f3695e9f2f532715f40109795a787aadbb2b8ea9a","tests/bigint.rs":"929422608f842cfb0bdd5117f5af74c954704d3c84df7da46b0eea1fdedd5ba8","tests/bigint_bitwise.rs":"a69d59c3eb07867f9da66ad9a8ae101a15366f88fb1f72f2015a9fe4de3518db","tests/bigint_scalar.rs":"a87e801e370686985d44e1f020c69fceca72b9f048e0f7301d2b8d38469e5636","tests/biguint.rs":"61fb3cb51ab2102330225adbfbbef9934defc23be9ab04e4c09129cd67b6f380","tests/biguint_scalar.rs":"b09cda9d4fe6ec519e93282653f69b57d70db73b9cb59c0ea5cd0861ca2de266","tests/consts/mod.rs":"f077d1aea22895a29df4e1391b40cc983cde9389f97e5b30923765f61dc3d017","tests/fuzzed.rs":"f60a84c446ea2f45d87eb4ee64682ea63fdef05bc74f482739d4e968960e8f4e","tests/macros/mod.rs":"1a8f9f015e5caaac60ce9ccff01a75ae489801c3ede6e7b9b3c5079b6efefc9c","tests/modpow.rs":"f4c81111308d63876ed02229cbab50bec9bac082bfa71f481120e46b5d7e5560","tests/roots.rs":"1c1576309eef9a6eb7ac8db4358fcf1d5b55403deaf27fd40ba2aa61b9567c87"},"package":"a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a25836ec6c341d1aa40c97335842f330b6a62911" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,107 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "num-bigint" +version = "0.4.6" +authors = ["The Rust Project Developers"] +exclude = [ + "/ci/*", + "/.github/*", +] +description = "Big integer implementation for Rust" +homepage = "https://github.com/rust-num/num-bigint" +documentation = "https://docs.rs/num-bigint" +readme = "README.md" +keywords = [ + "mathematics", + "numerics", + "bignum", +] +categories = [ + "algorithms", + "data-structures", + "science", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-bigint" + +[package.metadata.docs.rs] +features = [ + "std", + "serde", + "rand", + "quickcheck", + "arbitrary", +] +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[[bench]] +name = "bigint" + +[[bench]] +name = "factorial" + +[[bench]] +name = "gcd" + +[[bench]] +name = "roots" + +[[bench]] +name = "shootout-pidigits" +harness = false + +[dependencies.arbitrary] +version = "1" +optional = true +default-features = false + +[dependencies.num-integer] +version = "0.1.46" +features = ["i128"] +default-features = false + +[dependencies.num-traits] +version = "0.2.18" +features = ["i128"] +default-features = false + +[dependencies.quickcheck] +version = "1" +optional = true +default-features = false + +[dependencies.rand] +version = "0.8" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[features] +arbitrary = ["dep:arbitrary"] +default = ["std"] +quickcheck = ["dep:quickcheck"] +rand = ["dep:rand"] +serde = ["dep:serde"] +std = [ + "num-integer/std", + "num-traits/std", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,75 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Big integer implementation for Rust" +documentation = "https://docs.rs/num-bigint" +homepage = "https://github.com/rust-num/num-bigint" +keywords = ["mathematics", "numerics", "bignum"] +categories = [ "algorithms", "data-structures", "science" ] +license = "MIT OR Apache-2.0" +name = "num-bigint" +repository = "https://github.com/rust-num/num-bigint" +version = "0.4.6" +readme = "README.md" +exclude = ["/ci/*", "/.github/*"] +edition = "2021" +rust-version = "1.60" + +[features] +default = ["std"] +std = ["num-integer/std", "num-traits/std"] +arbitrary = ["dep:arbitrary"] +quickcheck = ["dep:quickcheck"] +rand = ["dep:rand"] +serde = ["dep:serde"] + +[package.metadata.docs.rs] +features = ["std", "serde", "rand", "quickcheck", "arbitrary"] +rustdoc-args = ["--cfg", "docsrs"] + +[[bench]] +name = "bigint" + +[[bench]] +name = "factorial" + +[[bench]] +name = "gcd" + +[[bench]] +name = "roots" + +[[bench]] +harness = false +name = "shootout-pidigits" + +[dependencies] + +[dependencies.num-integer] +version = "0.1.46" +default-features = false +features = ["i128"] + +[dependencies.num-traits] +version = "0.2.18" +default-features = false +features = ["i128"] + +[dependencies.rand] +optional = true +version = "0.8" +default-features = false + +[dependencies.serde] +optional = true +version = "1.0" +default-features = false + +[dependencies.quickcheck] +optional = true +version = "1" +default-features = false + +[dependencies.arbitrary] +optional = true +version = "1" +default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/README.md clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +# num-bigint + +[![crate](https://img.shields.io/crates/v/num-bigint.svg)](https://crates.io/crates/num-bigint) +[![documentation](https://docs.rs/num-bigint/badge.svg)](https://docs.rs/num-bigint) +[![minimum rustc 1.60](https://img.shields.io/badge/rustc-1.60+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![build status](https://github.com/rust-num/num-bigint/workflows/master/badge.svg)](https://github.com/rust-num/num-bigint/actions) + +Big integer types for Rust, `BigInt` and `BigUint`. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +num-bigint = "0.4" +``` + +## Features + +The `std` crate feature is enabled by default, and is mandatory before Rust +1.36 and the stabilized `alloc` crate. If you depend on `num-bigint` with +`default-features = false`, you must manually enable the `std` feature yourself +if your compiler is not new enough. + +### Random Generation + +`num-bigint` supports the generation of random big integers when the `rand` +feature is enabled. To enable it include rand as + +```toml +rand = "0.8" +num-bigint = { version = "0.4", features = ["rand"] } +``` + +Note that you must use the version of `rand` that `num-bigint` is compatible +with: `0.8`. + +## Releases + +Release notes are available in [RELEASES.md](RELEASES.md). + +## Compatibility + +The `num-bigint` crate is tested for rustc 1.60 and greater. + +## Alternatives + +While `num-bigint` strives for good performance in pure Rust code, other +crates may offer better performance with different trade-offs. The following +table offers a brief comparison to a few alternatives. + +| Crate | License | Min rustc | Implementation | Features | +| :--------------- | :------------- | :-------- | :------------- | :------- | +| **`num-bigint`** | MIT/Apache-2.0 | 1.60 | pure rust | dynamic width, number theoretical functions | +| [`awint`] | MIT/Apache-2.0 | 1.66 | pure rust | fixed width, heap or stack, concatenation macros | +| [`bnum`] | MIT/Apache-2.0 | 1.65 | pure rust | fixed width, parity with Rust primitives including floats | +| [`crypto-bigint`] | MIT/Apache-2.0 | 1.73 | pure rust | fixed width, stack only | +| [`ibig`] | MIT/Apache-2.0 | 1.49 | pure rust | dynamic width, number theoretical functions | +| [`rug`] | LGPL-3.0+ | 1.65 | bundles [GMP] via [`gmp-mpfr-sys`] | all the features of GMP, MPFR, and MPC | + +[`awint`]: https://crates.io/crates/awint +[`bnum`]: https://crates.io/crates/bnum +[`crypto-bigint`]: https://crates.io/crates/crypto-bigint +[`ibig`]: https://crates.io/crates/ibig +[`rug`]: https://crates.io/crates/rug + +[GMP]: https://gmplib.org/ +[`gmp-mpfr-sys`]: https://crates.io/crates/gmp-mpfr-sys + +## License + +Licensed under either of + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/RELEASES.md clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/RELEASES.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/RELEASES.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/RELEASES.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,343 @@ +# Release 0.4.6 (2024-06-27) + +- [Fixed compilation on `x86_64-unknown-linux-gnux32`.][312] + +**Contributors**: @cuviper, @ralphtandetzky, @yhx-12243 + +[312]: https://github.com/rust-num/num-bigint/pull/312 + +# Release 0.4.5 (2024-05-06) + +- [Upgrade to 2021 edition, **MSRV 1.60**][292] +- [Add `const ZERO` and implement `num_traits::ConstZero`][298] +- [Add `modinv` methods for the modular inverse][288] +- [Optimize multiplication with imbalanced operands][295] +- [Optimize scalar division on x86 and x86-64][236] + +**Contributors**: @cuviper, @joelonsql, @waywardmonkeys + +[236]: https://github.com/rust-num/num-bigint/pull/236 +[288]: https://github.com/rust-num/num-bigint/pull/288 +[292]: https://github.com/rust-num/num-bigint/pull/292 +[295]: https://github.com/rust-num/num-bigint/pull/295 +[298]: https://github.com/rust-num/num-bigint/pull/298 + +# Release 0.4.4 (2023-08-22) + +- [Implemented `From` for `BigInt` and `BigUint`.][239] +- [Implemented `num_traits::Euclid` and `CheckedEuclid` for `BigInt` and `BigUint`.][245] +- [Implemented ties-to-even for `BigInt` and `BigUint::to_f32` and `to_f64`.][271] +- [Implemented `num_traits::FromBytes` and `ToBytes` for `BigInt` and `BigUint`.][276] +- Limited pre-allocation from serde size hints against potential OOM. +- Miscellaneous other code cleanups and maintenance tasks. + +**Contributors**: @AaronKutch, @archseer, @cuviper, @dramforever, @icecream17, +@icedrocket, @janmarthedal, @jaybosamiya, @OliveIsAWord, @PatrickNorton, +@smoelius, @waywardmonkeys + +[239]: https://github.com/rust-num/num-bigint/pull/239 +[245]: https://github.com/rust-num/num-bigint/pull/245 +[271]: https://github.com/rust-num/num-bigint/pull/271 +[276]: https://github.com/rust-num/num-bigint/pull/276 + +# Release 0.4.3 (2021-11-02) + +- [GHSA-v935-pqmr-g8v9]: [Fix unexpected panics in multiplication.][228] + +**Contributors**: @arvidn, @cuviper, @guidovranken + +[228]: https://github.com/rust-num/num-bigint/pull/228 +[GHSA-v935-pqmr-g8v9]: https://github.com/rust-num/num-bigint/security/advisories/GHSA-v935-pqmr-g8v9 + +# Release 0.4.2 (2021-09-03) + +- [Use explicit `Integer::div_ceil` to avoid the new unstable method.][219] + +**Contributors**: @catenacyber, @cuviper + +[219]: https://github.com/rust-num/num-bigint/pull/219 + +# Release 0.4.1 (2021-08-27) + +- [Fixed scalar divide-by-zero panics.][200] +- [Implemented `DoubleEndedIterator` for `U32Digits` and `U64Digits`.][208] +- [Optimized multiplication to avoid unnecessary allocations.][199] +- [Optimized string formatting for very large values.][216] + +**Contributors**: @cuviper, @PatrickNorton + +[199]: https://github.com/rust-num/num-bigint/pull/199 +[200]: https://github.com/rust-num/num-bigint/pull/200 +[208]: https://github.com/rust-num/num-bigint/pull/208 +[216]: https://github.com/rust-num/num-bigint/pull/216 + +# Release 0.4.0 (2021-03-05) + +### Breaking Changes + +- Updated public dependences on [arbitrary, quickcheck][194], and [rand][185]: + - `arbitrary` support has been updated to 1.0, requiring Rust 1.40. + - `quickcheck` support has been updated to 1.0, requiring Rust 1.46. + - `rand` support has been updated to 0.8, requiring Rust 1.36. +- [`Debug` now shows plain numeric values for `BigInt` and `BigUint`][195], + rather than the raw list of internal digits. + +**Contributors**: @cuviper, @Gelbpunkt + +[185]: https://github.com/rust-num/num-bigint/pull/185 +[194]: https://github.com/rust-num/num-bigint/pull/194 +[195]: https://github.com/rust-num/num-bigint/pull/195 + +# Release 0.3.3 (2021-09-03) + +- [Use explicit `Integer::div_ceil` to avoid the new unstable method.][219] + +**Contributors**: @catenacyber, @cuviper + +# Release 0.3.2 (2021-03-04) + +- [The new `BigUint` methods `count_ones` and `trailing_ones`][175] return the + number of `1` bits in the entire value or just its least-significant tail, + respectively. +- [The new `BigInt` and `BigUint` methods `bit` and `set_bit`][183] will read + and write individual bits of the value. For negative `BigInt`, bits are + determined as if they were in the two's complement representation. +- [The `from_radix_le` and `from_radix_be` methods][187] now accept empty + buffers to represent zero. +- [`BigInt` and `BigUint` can now iterate digits as `u32` or `u64`][192], + regardless of the actual internal digit size. + +**Contributors**: @BartMassey, @cuviper, @janmarthedal, @sebastianv89, @Speedy37 + +[175]: https://github.com/rust-num/num-bigint/pull/175 +[183]: https://github.com/rust-num/num-bigint/pull/183 +[187]: https://github.com/rust-num/num-bigint/pull/187 +[192]: https://github.com/rust-num/num-bigint/pull/192 + +# Release 0.3.1 (2020-11-03) + +- [Addition and subtraction now uses intrinsics][141] for performance on `x86` + and `x86_64` when built with Rust 1.33 or later. +- [Conversions `to_f32` and `to_f64` now return infinity][163] for very large + numbers, rather than `None`. This does preserve the sign too, so a large + negative `BigInt` will convert to negative infinity. +- [The optional `arbitrary` feature implements `arbitrary::Arbitrary`][166], + distinct from `quickcheck::Arbitrary`. +- [The division algorithm has been optimized][170] to reduce the number of + temporary allocations and improve the internal guesses at each step. +- [`BigInt` and `BigUint` will opportunistically shrink capacity][171] if the + internal vector is much larger than needed. + +**Contributors**: @cuviper, @e00E, @ejmahler, @notoria, @tczajka + +[141]: https://github.com/rust-num/num-bigint/pull/141 +[163]: https://github.com/rust-num/num-bigint/pull/163 +[166]: https://github.com/rust-num/num-bigint/pull/166 +[170]: https://github.com/rust-num/num-bigint/pull/170 +[171]: https://github.com/rust-num/num-bigint/pull/171 + +# Release 0.3.0 (2020-06-12) + +### Enhancements + +- [The internal `BigDigit` may now be either `u32` or `u64`][62], although that + implementation detail is not exposed in the API. For now, this is chosen to + match the target pointer size, but may change in the future. +- [No-`std` is now supported with the `alloc` crate on Rust 1.36][101]. +- [`Pow` is now implemented for bigint values][137], not just references. +- [`TryFrom` is now implemented on Rust 1.34 and later][123], converting signed + integers to unsigned, and narrowing big integers to primitives. +- [`Shl` and `Shr` are now implemented for a variety of shift types][142]. +- A new `trailing_zeros()` returns the number of consecutive zeros from the + least significant bit. +- The new `BigInt::magnitude` and `into_parts` methods give access to its + `BigUint` part as the magnitude. + +### Breaking Changes + +- `num-bigint` now requires Rust 1.31 or greater. + - The "i128" opt-in feature was removed, now always available. +- [Updated public dependences][110]: + - `rand` support has been updated to 0.7, requiring Rust 1.32. + - `quickcheck` support has been updated to 0.9, requiring Rust 1.34. +- [Removed `impl Neg for BigUint`][145], which only ever panicked. +- [Bit counts are now `u64` instead of `usize`][143]. + +**Contributors**: @cuviper, @dignifiedquire, @hansihe, +@kpcyrd, @milesand, @tech6hutch + +[62]: https://github.com/rust-num/num-bigint/pull/62 +[101]: https://github.com/rust-num/num-bigint/pull/101 +[110]: https://github.com/rust-num/num-bigint/pull/110 +[123]: https://github.com/rust-num/num-bigint/pull/123 +[137]: https://github.com/rust-num/num-bigint/pull/137 +[142]: https://github.com/rust-num/num-bigint/pull/142 +[143]: https://github.com/rust-num/num-bigint/pull/143 +[145]: https://github.com/rust-num/num-bigint/pull/145 + +# Release 0.2.6 (2020-01-27) + +- [Fix the promotion of negative `isize` in `BigInt` assign-ops][133]. + +**Contributors**: @cuviper, @HactarCE + +[133]: https://github.com/rust-num/num-bigint/pull/133 + +# Release 0.2.5 (2020-01-09) + +- [Updated the `autocfg` build dependency to 1.0][126]. + +**Contributors**: @cuviper, @tspiteri + +[126]: https://github.com/rust-num/num-bigint/pull/126 + +# Release 0.2.4 (2020-01-01) + +- [The new `BigUint::to_u32_digits` method][104] returns the number as a + little-endian vector of base-232 digits. The same method on + `BigInt` also returns the sign. +- [`BigUint::modpow` now applies a modulus even for exponent 1][113], which + also affects `BigInt::modpow`. +- [`BigInt::modpow` now returns the correct sign for negative bases with even + exponents][114]. + +[104]: https://github.com/rust-num/num-bigint/pull/104 +[113]: https://github.com/rust-num/num-bigint/pull/113 +[114]: https://github.com/rust-num/num-bigint/pull/114 + +**Contributors**: @alex-ozdemir, @cuviper, @dingelish, @Speedy37, @youknowone + +# Release 0.2.3 (2019-09-03) + +- [`Pow` is now implemented for `BigUint` exponents][77]. +- [The optional `quickcheck` feature enables implementations of `Arbitrary`][99]. +- See the [full comparison][compare-0.2.3] for performance enhancements and more! + +[77]: https://github.com/rust-num/num-bigint/pull/77 +[99]: https://github.com/rust-num/num-bigint/pull/99 +[compare-0.2.3]: https://github.com/rust-num/num-bigint/compare/num-bigint-0.2.2...num-bigint-0.2.3 + +**Contributors**: @cuviper, @lcnr, @maxbla, @mikelodder7, @mikong, +@TheLetterTheta, @tspiteri, @XAMPPRocky, @youknowone + +# Release 0.2.2 (2018-12-14) + +- [The `Roots` implementations now use better initial guesses][71]. +- [Fixed `to_signed_bytes_*` for some positive numbers][72], where the + most-significant byte is `0x80` and the rest are `0`. + +[71]: https://github.com/rust-num/num-bigint/pull/71 +[72]: https://github.com/rust-num/num-bigint/pull/72 + +**Contributors**: @cuviper, @leodasvacas + +# Release 0.2.1 (2018-11-02) + +- [`RandBigInt` now uses `Rng::fill_bytes`][53] to improve performance, instead + of repeated `gen::` calls. The also affects the implementations of the + other `rand` traits. This may potentially change the values produced by some + seeded RNGs on previous versions, but the values were tested to be stable + with `ChaChaRng`, `IsaacRng`, and `XorShiftRng`. +- [`BigInt` and `BigUint` now implement `num_integer::Roots`][56]. +- [`BigInt` and `BigUint` now implement `num_traits::Pow`][54]. +- [`BigInt` and `BigUint` now implement operators with 128-bit integers][64]. + +**Contributors**: @cuviper, @dignifiedquire, @mancabizjak, @Robbepop, +@TheIronBorn, @thomwiggers + +[53]: https://github.com/rust-num/num-bigint/pull/53 +[54]: https://github.com/rust-num/num-bigint/pull/54 +[56]: https://github.com/rust-num/num-bigint/pull/56 +[64]: https://github.com/rust-num/num-bigint/pull/64 + +# Release 0.2.0 (2018-05-25) + +### Enhancements + +- [`BigInt` and `BigUint` now implement `Product` and `Sum`][22] for iterators + of any item that we can `Mul` and `Add`, respectively. For example, a + factorial can now be simply: `let f: BigUint = (1u32..1000).product();` +- [`BigInt` now supports two's-complement logic operations][26], namely + `BitAnd`, `BitOr`, `BitXor`, and `Not`. These act conceptually as if each + number had an infinite prefix of `0` or `1` bits for positive or negative. +- [`BigInt` now supports assignment operators][41] like `AddAssign`. +- [`BigInt` and `BigUint` now support conversions with `i128` and `u128`][44], + if sufficient compiler support is detected. +- [`BigInt` and `BigUint` now implement rand's `SampleUniform` trait][48], and + [a custom `RandomBits` distribution samples by bit size][49]. +- The release also includes other miscellaneous improvements to performance. + +### Breaking Changes + +- [`num-bigint` now requires rustc 1.15 or greater][23]. +- [The crate now has a `std` feature, and won't build without it][46]. This is + in preparation for someday supporting `#![no_std]` with `alloc`. +- [The `serde` dependency has been updated to 1.0][24], still disabled by + default. The `rustc-serialize` crate is no longer supported by `num-bigint`. +- [The `rand` dependency has been updated to 0.5][48], now disabled by default. + This requires rustc 1.22 or greater for `rand`'s own requirement. +- [`Shr for BigInt` now rounds down][8] rather than toward zero, matching the + behavior of the primitive integers for negative values. +- [`ParseBigIntError` is now an opaque type][37]. +- [The `big_digit` module is no longer public][38], nor are the `BigDigit` and + `DoubleBigDigit` types and `ZERO_BIG_DIGIT` constant that were re-exported in + the crate root. Public APIs which deal in digits, like `BigUint::from_slice`, + will now always be base-`u32`. + +**Contributors**: @clarcharr, @cuviper, @dodomorandi, @tiehuis, @tspiteri + +[8]: https://github.com/rust-num/num-bigint/pull/8 +[22]: https://github.com/rust-num/num-bigint/pull/22 +[23]: https://github.com/rust-num/num-bigint/pull/23 +[24]: https://github.com/rust-num/num-bigint/pull/24 +[26]: https://github.com/rust-num/num-bigint/pull/26 +[37]: https://github.com/rust-num/num-bigint/pull/37 +[38]: https://github.com/rust-num/num-bigint/pull/38 +[41]: https://github.com/rust-num/num-bigint/pull/41 +[44]: https://github.com/rust-num/num-bigint/pull/44 +[46]: https://github.com/rust-num/num-bigint/pull/46 +[48]: https://github.com/rust-num/num-bigint/pull/48 +[49]: https://github.com/rust-num/num-bigint/pull/49 + +# Release 0.1.44 (2018-05-14) + +- [Division with single-digit divisors is now much faster.][42] +- The README now compares [`ramp`, `rug`, `rust-gmp`][20], and [`apint`][21]. + +**Contributors**: @cuviper, @Robbepop + +[20]: https://github.com/rust-num/num-bigint/pull/20 +[21]: https://github.com/rust-num/num-bigint/pull/21 +[42]: https://github.com/rust-num/num-bigint/pull/42 + +# Release 0.1.43 (2018-02-08) + +- [The new `BigInt::modpow`][18] performs signed modular exponentiation, using + the existing `BigUint::modpow` and rounding negatives similar to `mod_floor`. + +**Contributors**: @cuviper + +[18]: https://github.com/rust-num/num-bigint/pull/18 + + +# Release 0.1.42 (2018-02-07) + +- [num-bigint now has its own source repository][num-356] at [rust-num/num-bigint][home]. +- [`lcm` now avoids creating a large intermediate product][num-350]. +- [`gcd` now uses Stein's algorithm][15] with faster shifts instead of division. +- [`rand` support is now extended to 0.4][11] (while still allowing 0.3). + +**Contributors**: @cuviper, @Emerentius, @ignatenkobrain, @mhogrefe + +[home]: https://github.com/rust-num/num-bigint +[num-350]: https://github.com/rust-num/num/pull/350 +[num-356]: https://github.com/rust-num/num/pull/356 +[11]: https://github.com/rust-num/num-bigint/pull/11 +[15]: https://github.com/rust-num/num-bigint/pull/15 + + +# Prior releases + +No prior release notes were kept. Thanks all the same to the many +contributors that have made this crate what it is! + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/bigint.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/bigint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/bigint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/bigint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,450 @@ +#![feature(test)] +#![cfg(feature = "rand")] + +extern crate test; + +use num_bigint::{BigInt, BigUint, RandBigInt}; +use num_traits::{FromPrimitive, Num, One, Zero}; +use std::mem::replace; +use test::Bencher; + +mod rng; +use rng::get_rng; + +fn multiply_bench(b: &mut Bencher, xbits: u64, ybits: u64) { + let mut rng = get_rng(); + let x = rng.gen_bigint(xbits); + let y = rng.gen_bigint(ybits); + + b.iter(|| &x * &y); +} + +fn divide_bench(b: &mut Bencher, xbits: u64, ybits: u64) { + let mut rng = get_rng(); + let x = rng.gen_bigint(xbits); + let y = rng.gen_bigint(ybits); + + b.iter(|| &x / &y); +} + +fn remainder_bench(b: &mut Bencher, xbits: u64, ybits: u64) { + let mut rng = get_rng(); + let x = rng.gen_bigint(xbits); + let y = rng.gen_bigint(ybits); + + b.iter(|| &x % &y); +} + +fn factorial(n: usize) -> BigUint { + let mut f: BigUint = One::one(); + for i in 1..=n { + let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); + f *= bu; + } + f +} + +/// Compute Fibonacci numbers +fn fib(n: usize) -> BigUint { + let mut f0: BigUint = Zero::zero(); + let mut f1: BigUint = One::one(); + for _ in 0..n { + let f2 = f0 + &f1; + f0 = replace(&mut f1, f2); + } + f0 +} + +/// Compute Fibonacci numbers with two ops per iteration +/// (add and subtract, like issue #200) +fn fib2(n: usize) -> BigUint { + let mut f0: BigUint = Zero::zero(); + let mut f1: BigUint = One::one(); + for _ in 0..n { + f1 += &f0; + f0 = &f1 - f0; + } + f0 +} + +#[bench] +fn multiply_0(b: &mut Bencher) { + multiply_bench(b, 1 << 8, 1 << 8); +} + +#[bench] +fn multiply_1(b: &mut Bencher) { + multiply_bench(b, 1 << 8, 1 << 16); +} + +#[bench] +fn multiply_2(b: &mut Bencher) { + multiply_bench(b, 1 << 16, 1 << 16); +} + +#[bench] +fn multiply_3(b: &mut Bencher) { + multiply_bench(b, 1 << 16, 1 << 17); +} + +#[bench] +fn multiply_4(b: &mut Bencher) { + multiply_bench(b, 1 << 12, 1 << 13); +} + +#[bench] +fn multiply_5(b: &mut Bencher) { + multiply_bench(b, 1 << 12, 1 << 14); +} + +#[bench] +fn divide_0(b: &mut Bencher) { + divide_bench(b, 1 << 8, 1 << 6); +} + +#[bench] +fn divide_1(b: &mut Bencher) { + divide_bench(b, 1 << 12, 1 << 8); +} + +#[bench] +fn divide_2(b: &mut Bencher) { + divide_bench(b, 1 << 16, 1 << 12); +} + +#[bench] +fn divide_big_little(b: &mut Bencher) { + divide_bench(b, 1 << 16, 1 << 4); +} + +#[bench] +fn remainder_0(b: &mut Bencher) { + remainder_bench(b, 1 << 8, 1 << 6); +} + +#[bench] +fn remainder_1(b: &mut Bencher) { + remainder_bench(b, 1 << 12, 1 << 8); +} + +#[bench] +fn remainder_2(b: &mut Bencher) { + remainder_bench(b, 1 << 16, 1 << 12); +} + +#[bench] +fn remainder_big_little(b: &mut Bencher) { + remainder_bench(b, 1 << 16, 1 << 4); +} + +#[bench] +fn factorial_100(b: &mut Bencher) { + b.iter(|| factorial(100)); +} + +#[bench] +fn fib_100(b: &mut Bencher) { + b.iter(|| fib(100)); +} + +#[bench] +fn fib_1000(b: &mut Bencher) { + b.iter(|| fib(1000)); +} + +#[bench] +fn fib_10000(b: &mut Bencher) { + b.iter(|| fib(10000)); +} + +#[bench] +fn fib2_100(b: &mut Bencher) { + b.iter(|| fib2(100)); +} + +#[bench] +fn fib2_1000(b: &mut Bencher) { + b.iter(|| fib2(1000)); +} + +#[bench] +fn fib2_10000(b: &mut Bencher) { + b.iter(|| fib2(10000)); +} + +#[bench] +fn fac_to_string(b: &mut Bencher) { + let fac = factorial(100); + b.iter(|| fac.to_string()); +} + +#[bench] +fn fib_to_string(b: &mut Bencher) { + let fib = fib(100); + b.iter(|| fib.to_string()); +} + +fn to_str_radix_bench(b: &mut Bencher, radix: u32, bits: u64) { + let mut rng = get_rng(); + let x = rng.gen_bigint(bits); + b.iter(|| x.to_str_radix(radix)); +} + +#[bench] +fn to_str_radix_02(b: &mut Bencher) { + to_str_radix_bench(b, 2, 1009); +} + +#[bench] +fn to_str_radix_08(b: &mut Bencher) { + to_str_radix_bench(b, 8, 1009); +} + +#[bench] +fn to_str_radix_10(b: &mut Bencher) { + to_str_radix_bench(b, 10, 1009); +} + +#[bench] +fn to_str_radix_10_2(b: &mut Bencher) { + to_str_radix_bench(b, 10, 10009); +} + +#[bench] +fn to_str_radix_16(b: &mut Bencher) { + to_str_radix_bench(b, 16, 1009); +} + +#[bench] +fn to_str_radix_36(b: &mut Bencher) { + to_str_radix_bench(b, 36, 1009); +} + +fn from_str_radix_bench(b: &mut Bencher, radix: u32) { + let mut rng = get_rng(); + let x = rng.gen_bigint(1009); + let s = x.to_str_radix(radix); + assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap()); + b.iter(|| BigInt::from_str_radix(&s, radix)); +} + +#[bench] +fn from_str_radix_02(b: &mut Bencher) { + from_str_radix_bench(b, 2); +} + +#[bench] +fn from_str_radix_08(b: &mut Bencher) { + from_str_radix_bench(b, 8); +} + +#[bench] +fn from_str_radix_10(b: &mut Bencher) { + from_str_radix_bench(b, 10); +} + +#[bench] +fn from_str_radix_16(b: &mut Bencher) { + from_str_radix_bench(b, 16); +} + +#[bench] +fn from_str_radix_36(b: &mut Bencher) { + from_str_radix_bench(b, 36); +} + +fn rand_bench(b: &mut Bencher, bits: u64) { + let mut rng = get_rng(); + + b.iter(|| rng.gen_bigint(bits)); +} + +#[bench] +fn rand_64(b: &mut Bencher) { + rand_bench(b, 1 << 6); +} + +#[bench] +fn rand_256(b: &mut Bencher) { + rand_bench(b, 1 << 8); +} + +#[bench] +fn rand_1009(b: &mut Bencher) { + rand_bench(b, 1009); +} + +#[bench] +fn rand_2048(b: &mut Bencher) { + rand_bench(b, 1 << 11); +} + +#[bench] +fn rand_4096(b: &mut Bencher) { + rand_bench(b, 1 << 12); +} + +#[bench] +fn rand_8192(b: &mut Bencher) { + rand_bench(b, 1 << 13); +} + +#[bench] +fn rand_65536(b: &mut Bencher) { + rand_bench(b, 1 << 16); +} + +#[bench] +fn rand_131072(b: &mut Bencher) { + rand_bench(b, 1 << 17); +} + +#[bench] +fn shl(b: &mut Bencher) { + let n = BigUint::one() << 1000u32; + let mut m = n.clone(); + b.iter(|| { + m.clone_from(&n); + for i in 0..50 { + m <<= i; + } + }) +} + +#[bench] +fn shr(b: &mut Bencher) { + let n = BigUint::one() << 2000u32; + let mut m = n.clone(); + b.iter(|| { + m.clone_from(&n); + for i in 0..50 { + m >>= i; + } + }) +} + +#[bench] +fn hash(b: &mut Bencher) { + use std::collections::HashSet; + let mut rng = get_rng(); + let v: Vec = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect(); + b.iter(|| { + let h: HashSet<&BigInt> = v.iter().collect(); + assert_eq!(h.len(), v.len()); + }); +} + +#[bench] +fn pow_bench(b: &mut Bencher) { + b.iter(|| { + let upper = 100_u32; + let mut i_big = BigUint::from(1u32); + for _i in 2..=upper { + i_big += 1u32; + for j in 2..=upper { + i_big.pow(j); + } + } + }); +} + +#[bench] +fn pow_bench_bigexp(b: &mut Bencher) { + use num_traits::Pow; + + b.iter(|| { + let upper = 100_u32; + let mut i_big = BigUint::from(1u32); + for _i in 2..=upper { + i_big += 1u32; + let mut j_big = BigUint::from(1u32); + for _j in 2..=upper { + j_big += 1u32; + Pow::pow(&i_big, &j_big); + } + } + }); +} + +#[bench] +fn pow_bench_1e1000(b: &mut Bencher) { + b.iter(|| BigUint::from(10u32).pow(1_000)); +} + +#[bench] +fn pow_bench_1e10000(b: &mut Bencher) { + b.iter(|| BigUint::from(10u32).pow(10_000)); +} + +#[bench] +fn pow_bench_1e100000(b: &mut Bencher) { + b.iter(|| BigUint::from(10u32).pow(100_000)); +} + +/// This modulus is the prime from the 2048-bit MODP DH group: +/// https://tools.ietf.org/html/rfc3526#section-3 +const RFC3526_2048BIT_MODP_GROUP: &str = "\ + FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ + 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ + EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ + E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ + EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ + C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ + 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ + 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ + E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ + DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ + 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; + +#[bench] +fn modpow(b: &mut Bencher) { + let mut rng = get_rng(); + let base = rng.gen_biguint(2048); + let e = rng.gen_biguint(2048); + let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap(); + + b.iter(|| base.modpow(&e, &m)); +} + +#[bench] +fn modpow_even(b: &mut Bencher) { + let mut rng = get_rng(); + let base = rng.gen_biguint(2048); + let e = rng.gen_biguint(2048); + // Make the modulus even, so monty (base-2^32) doesn't apply. + let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap() - 1u32; + + b.iter(|| base.modpow(&e, &m)); +} + +#[bench] +fn to_u32_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.to_u32_digits()); +} + +#[bench] +fn iter_u32_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.iter_u32_digits().max()); +} + +#[bench] +fn to_u64_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.to_u64_digits()); +} + +#[bench] +fn iter_u64_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.iter_u64_digits().max()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/factorial.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/factorial.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/factorial.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/factorial.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +#![feature(test)] + +extern crate test; + +use num_bigint::BigUint; +use num_traits::One; +use std::ops::{Div, Mul}; +use test::Bencher; + +#[bench] +fn factorial_mul_biguint(b: &mut Bencher) { + b.iter(|| { + (1u32..1000) + .map(BigUint::from) + .fold(BigUint::one(), Mul::mul) + }); +} + +#[bench] +fn factorial_mul_u32(b: &mut Bencher) { + b.iter(|| (1u32..1000).fold(BigUint::one(), Mul::mul)); +} + +// The division test is inspired by this blog comparison: +// + +#[bench] +fn factorial_div_biguint(b: &mut Bencher) { + let n: BigUint = (1u32..1000).fold(BigUint::one(), Mul::mul); + b.iter(|| { + (1u32..1000) + .rev() + .map(BigUint::from) + .fold(n.clone(), Div::div) + }); +} + +#[bench] +fn factorial_div_u32(b: &mut Bencher) { + let n: BigUint = (1u32..1000).fold(BigUint::one(), Mul::mul); + b.iter(|| (1u32..1000).rev().fold(n.clone(), Div::div)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/gcd.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/gcd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/gcd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/gcd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,76 @@ +#![feature(test)] +#![cfg(feature = "rand")] + +extern crate test; + +use num_bigint::{BigUint, RandBigInt}; +use num_integer::Integer; +use num_traits::Zero; +use test::Bencher; + +mod rng; +use rng::get_rng; + +fn bench(b: &mut Bencher, bits: u64, gcd: fn(&BigUint, &BigUint) -> BigUint) { + let mut rng = get_rng(); + let x = rng.gen_biguint(bits); + let y = rng.gen_biguint(bits); + + assert_eq!(euclid(&x, &y), x.gcd(&y)); + + b.iter(|| gcd(&x, &y)); +} + +fn euclid(x: &BigUint, y: &BigUint) -> BigUint { + // Use Euclid's algorithm + let mut m = x.clone(); + let mut n = y.clone(); + while !m.is_zero() { + let temp = m; + m = n % &temp; + n = temp; + } + n +} + +#[bench] +fn gcd_euclid_0064(b: &mut Bencher) { + bench(b, 64, euclid); +} + +#[bench] +fn gcd_euclid_0256(b: &mut Bencher) { + bench(b, 256, euclid); +} + +#[bench] +fn gcd_euclid_1024(b: &mut Bencher) { + bench(b, 1024, euclid); +} + +#[bench] +fn gcd_euclid_4096(b: &mut Bencher) { + bench(b, 4096, euclid); +} + +// Integer for BigUint now uses Stein for gcd + +#[bench] +fn gcd_stein_0064(b: &mut Bencher) { + bench(b, 64, BigUint::gcd); +} + +#[bench] +fn gcd_stein_0256(b: &mut Bencher) { + bench(b, 256, BigUint::gcd); +} + +#[bench] +fn gcd_stein_1024(b: &mut Bencher) { + bench(b, 1024, BigUint::gcd); +} + +#[bench] +fn gcd_stein_4096(b: &mut Bencher) { + bench(b, 4096, BigUint::gcd); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/rng/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/rng/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/rng/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/rng/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +use rand::RngCore; + +pub(crate) fn get_rng() -> impl RngCore { + XorShiftStar { + a: 0x0123_4567_89AB_CDEF, + } +} + +/// Simple `Rng` for benchmarking without additional dependencies +struct XorShiftStar { + a: u64, +} + +impl RngCore for XorShiftStar { + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } + + fn next_u64(&mut self) -> u64 { + // https://en.wikipedia.org/wiki/Xorshift#xorshift* + self.a ^= self.a >> 12; + self.a ^= self.a << 25; + self.a ^= self.a >> 27; + self.a.wrapping_mul(0x2545_F491_4F6C_DD1D) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + for chunk in dest.chunks_mut(8) { + let bytes = self.next_u64().to_le_bytes(); + let slice = &bytes[..chunk.len()]; + chunk.copy_from_slice(slice) + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + Ok(self.fill_bytes(dest)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/roots.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/roots.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/roots.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/roots.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,166 @@ +#![feature(test)] +#![cfg(feature = "rand")] + +extern crate test; + +use num_bigint::{BigUint, RandBigInt}; +use test::Bencher; + +mod rng; +use rng::get_rng; + +// The `big64` cases demonstrate the speed of cases where the value +// can be converted to a `u64` primitive for faster calculation. +// +// The `big1k` cases demonstrate those that can convert to `f64` for +// a better initial guess of the actual value. +// +// The `big2k` and `big4k` cases are too big for `f64`, and use a simpler guess. + +fn check(x: &BigUint, n: u32) { + let root = x.nth_root(n); + if n == 2 { + assert_eq!(root, x.sqrt()) + } else if n == 3 { + assert_eq!(root, x.cbrt()) + } + + let lo = root.pow(n); + assert!(lo <= *x); + assert_eq!(lo.nth_root(n), root); + assert_eq!((&lo - 1u32).nth_root(n), &root - 1u32); + + let hi = (&root + 1u32).pow(n); + assert!(hi > *x); + assert_eq!(hi.nth_root(n), &root + 1u32); + assert_eq!((&hi - 1u32).nth_root(n), root); +} + +fn bench_sqrt(b: &mut Bencher, bits: u64) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_sqrt({})", x); + + check(&x, 2); + b.iter(|| x.sqrt()); +} + +#[bench] +fn big64_sqrt(b: &mut Bencher) { + bench_sqrt(b, 64); +} + +#[bench] +fn big1k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 1024); +} + +#[bench] +fn big2k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 2048); +} + +#[bench] +fn big4k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 4096); +} + +fn bench_cbrt(b: &mut Bencher, bits: u64) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_cbrt({})", x); + + check(&x, 3); + b.iter(|| x.cbrt()); +} + +#[bench] +fn big64_cbrt(b: &mut Bencher) { + bench_cbrt(b, 64); +} + +#[bench] +fn big1k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 1024); +} + +#[bench] +fn big2k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 2048); +} + +#[bench] +fn big4k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 4096); +} + +fn bench_nth_root(b: &mut Bencher, bits: u64, n: u32) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_{}th_root({})", n, x); + + check(&x, n); + b.iter(|| x.nth_root(n)); +} + +#[bench] +fn big64_nth_10(b: &mut Bencher) { + bench_nth_root(b, 64, 10); +} + +#[bench] +fn big1k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 1024, 10); +} + +#[bench] +fn big1k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 1024, 100); +} + +#[bench] +fn big1k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 1024, 1000); +} + +#[bench] +fn big1k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 1024, 10000); +} + +#[bench] +fn big2k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 2048, 10); +} + +#[bench] +fn big2k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 2048, 100); +} + +#[bench] +fn big2k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 2048, 1000); +} + +#[bench] +fn big2k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 2048, 10000); +} + +#[bench] +fn big4k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 4096, 10); +} + +#[bench] +fn big4k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 4096, 100); +} + +#[bench] +fn big4k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 4096, 1000); +} + +#[bench] +fn big4k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 4096, 10000); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/shootout-pidigits.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/shootout-pidigits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/benches/shootout-pidigits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/benches/shootout-pidigits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +// The Computer Language Benchmarks Game +// http://benchmarksgame.alioth.debian.org/ +// +// contributed by the Rust Project Developers + +// Copyright (c) 2013-2014 The Rust Project Developers +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// - Neither the name of "The Computer Language Benchmarks Game" nor +// the name of "The Computer Language Shootout Benchmarks" nor the +// names of its contributors may be used to endorse or promote +// products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::io; +use std::str::FromStr; + +use num_bigint::BigInt; +use num_integer::Integer; +use num_traits::{FromPrimitive, One, ToPrimitive, Zero}; + +struct Context { + numer: BigInt, + accum: BigInt, + denom: BigInt, +} + +impl Context { + fn new() -> Context { + Context { + numer: One::one(), + accum: Zero::zero(), + denom: One::one(), + } + } + + fn from_i32(i: i32) -> BigInt { + FromPrimitive::from_i32(i).unwrap() + } + + fn extract_digit(&self) -> i32 { + if self.numer > self.accum { + return -1; + } + let (q, r) = (&self.numer * Context::from_i32(3) + &self.accum).div_rem(&self.denom); + if r + &self.numer >= self.denom { + return -1; + } + q.to_i32().unwrap() + } + + fn next_term(&mut self, k: i32) { + let y2 = Context::from_i32(k * 2 + 1); + self.accum = (&self.accum + (&self.numer << 1)) * &y2; + self.numer = &self.numer * Context::from_i32(k); + self.denom = &self.denom * y2; + } + + fn eliminate_digit(&mut self, d: i32) { + let d = Context::from_i32(d); + let ten = Context::from_i32(10); + self.accum = (&self.accum - &self.denom * d) * &ten; + self.numer = &self.numer * ten; + } +} + +fn pidigits(n: isize, out: &mut dyn io::Write) -> io::Result<()> { + let mut k = 0; + let mut context = Context::new(); + + for i in 1..=n { + let mut d; + loop { + k += 1; + context.next_term(k); + d = context.extract_digit(); + if d != -1 { + break; + } + } + + write!(out, "{}", d)?; + if i % 10 == 0 { + writeln!(out, "\t:{}", i)?; + } + + context.eliminate_digit(d); + } + + let m = n % 10; + if m != 0 { + for _ in m..10 { + write!(out, " ")?; + } + writeln!(out, "\t:{}", n)?; + } + Ok(()) +} + +const DEFAULT_DIGITS: isize = 512; + +fn main() { + let args = std::env::args().collect::>(); + let n = if args.len() < 2 { + DEFAULT_DIGITS + } else if args[1] == "--bench" { + return pidigits(DEFAULT_DIGITS, &mut std::io::sink()).unwrap(); + } else { + FromStr::from_str(&args[1]).unwrap() + }; + pidigits(n, &mut std::io::stdout()).unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/addition.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/addition.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/addition.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/addition.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,239 @@ +use super::CheckedUnsignedAbs::{Negative, Positive}; +use super::Sign::{Minus, NoSign, Plus}; +use super::{BigInt, UnsignedAbs}; + +use crate::{IsizePromotion, UsizePromotion}; + +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::iter::Sum; +use core::mem; +use core::ops::{Add, AddAssign}; +use num_traits::CheckedAdd; + +// We want to forward to BigUint::add, but it's not clear how that will go until +// we compare both sign and magnitude. So we duplicate this body for every +// val/ref combination, deferring that decision to BigUint's own forwarding. +macro_rules! bigint_add { + ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { + match ($a.sign, $b.sign) { + (_, NoSign) => $a_owned, + (NoSign, _) => $b_owned, + // same sign => keep the sign with the sum of magnitudes + (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data), + // opposite signs => keep the sign of the larger with the difference of magnitudes + (Plus, Minus) | (Minus, Plus) => match $a.data.cmp(&$b.data) { + Less => BigInt::from_biguint($b.sign, $b_data - $a_data), + Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), + Equal => BigInt::ZERO, + }, + } + }; +} + +impl Add<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: &BigInt) -> BigInt { + bigint_add!( + self, + self.clone(), + &self.data, + other, + other.clone(), + &other.data + ) + } +} + +impl Add for &BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: BigInt) -> BigInt { + bigint_add!(self, self.clone(), &self.data, other, other, other.data) + } +} + +impl Add<&BigInt> for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: &BigInt) -> BigInt { + bigint_add!(self, self, self.data, other, other.clone(), &other.data) + } +} + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: BigInt) -> BigInt { + bigint_add!(self, self, self.data, other, other, other.data) + } +} + +impl AddAssign<&BigInt> for BigInt { + #[inline] + fn add_assign(&mut self, other: &BigInt) { + let n = mem::replace(self, Self::ZERO); + *self = n + other; + } +} +forward_val_assign!(impl AddAssign for BigInt, add_assign); + +promote_all_scalars!(impl Add for BigInt, add); +promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: u32) -> BigInt { + match self.sign { + NoSign => From::from(other), + Plus => BigInt::from(self.data + other), + Minus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Less => BigInt::from(other - self.data), + Greater => -BigInt::from(self.data - other), + }, + } + } +} + +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: u32) { + let n = mem::replace(self, Self::ZERO); + *self = n + other; + } +} + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: u64) -> BigInt { + match self.sign { + NoSign => From::from(other), + Plus => BigInt::from(self.data + other), + Minus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Less => BigInt::from(other - self.data), + Greater => -BigInt::from(self.data - other), + }, + } + } +} + +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: u64) { + let n = mem::replace(self, Self::ZERO); + *self = n + other; + } +} + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: u128) -> BigInt { + match self.sign { + NoSign => BigInt::from(other), + Plus => BigInt::from(self.data + other), + Minus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Less => BigInt::from(other - self.data), + Greater => -BigInt::from(self.data - other), + }, + } + } +} +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: u128) { + let n = mem::replace(self, Self::ZERO); + *self = n + other; + } +} + +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: i32) -> BigInt { + match other.checked_uabs() { + Positive(u) => self + u, + Negative(u) => self - u, + } + } +} +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: i32) { + match other.checked_uabs() { + Positive(u) => *self += u, + Negative(u) => *self -= u, + } + } +} + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: i64) -> BigInt { + match other.checked_uabs() { + Positive(u) => self + u, + Negative(u) => self - u, + } + } +} +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: i64) { + match other.checked_uabs() { + Positive(u) => *self += u, + Negative(u) => *self -= u, + } + } +} + +impl Add for BigInt { + type Output = BigInt; + + #[inline] + fn add(self, other: i128) -> BigInt { + match other.checked_uabs() { + Positive(u) => self + u, + Negative(u) => self - u, + } + } +} +impl AddAssign for BigInt { + #[inline] + fn add_assign(&mut self, other: i128) { + match other.checked_uabs() { + Positive(u) => *self += u, + Negative(u) => *self -= u, + } + } +} + +impl CheckedAdd for BigInt { + #[inline] + fn checked_add(&self, v: &BigInt) -> Option { + Some(self.add(v)) + } +} + +impl_sum_iter_type!(BigInt); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/arbitrary.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/arbitrary.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/arbitrary.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/arbitrary.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ +#![cfg(any(feature = "quickcheck", feature = "arbitrary"))] + +use super::{BigInt, Sign}; +use crate::BigUint; + +#[cfg(feature = "quickcheck")] +use alloc::boxed::Box; + +#[cfg(feature = "quickcheck")] +#[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))] +impl quickcheck::Arbitrary for BigInt { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + let positive = bool::arbitrary(g); + let sign = if positive { Sign::Plus } else { Sign::Minus }; + Self::from_biguint(sign, BigUint::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + let sign = self.sign(); + let unsigned_shrink = self.data.shrink(); + Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x))) + } +} + +#[cfg(feature = "arbitrary")] +#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))] +impl arbitrary::Arbitrary<'_> for BigInt { + fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { + let positive = bool::arbitrary(u)?; + let sign = if positive { Sign::Plus } else { Sign::Minus }; + Ok(Self::from_biguint(sign, BigUint::arbitrary(u)?)) + } + + fn arbitrary_take_rest(mut u: arbitrary::Unstructured<'_>) -> arbitrary::Result { + let positive = bool::arbitrary(&mut u)?; + let sign = if positive { Sign::Plus } else { Sign::Minus }; + Ok(Self::from_biguint(sign, BigUint::arbitrary_take_rest(u)?)) + } + + fn size_hint(depth: usize) -> (usize, Option) { + arbitrary::size_hint::and(bool::size_hint(depth), BigUint::size_hint(depth)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/bits.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/bits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/bits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/bits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,531 @@ +use super::BigInt; +use super::Sign::{Minus, NoSign, Plus}; + +use crate::big_digit::{self, BigDigit, DoubleBigDigit}; +use crate::biguint::IntDigits; + +use alloc::vec::Vec; +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; +use num_traits::{ToPrimitive, Zero}; + +// Negation in two's complement. +// acc must be initialized as 1 for least-significant digit. +// +// When negating, a carry (acc == 1) means that all the digits +// considered to this point were zero. This means that if all the +// digits of a negative BigInt have been considered, carry must be +// zero as we cannot have negative zero. +// +// 01 -> ...f ff +// ff -> ...f 01 +// 01 00 -> ...f ff 00 +// 01 01 -> ...f fe ff +// 01 ff -> ...f fe 01 +// ff 00 -> ...f 01 00 +// ff 01 -> ...f 00 ff +// ff ff -> ...f 00 01 +#[inline] +fn negate_carry(a: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { + *acc += DoubleBigDigit::from(!a); + let lo = *acc as BigDigit; + *acc >>= big_digit::BITS; + lo +} + +// + 1 & -ff = ...0 01 & ...f 01 = ...0 01 = + 1 +// +ff & - 1 = ...0 ff & ...f ff = ...0 ff = +ff +// answer is pos, has length of a +fn bitand_pos_neg(a: &mut [BigDigit], b: &[BigDigit]) { + let mut carry_b = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_b = negate_carry(bi, &mut carry_b); + *ai &= twos_b; + } + debug_assert!(b.len() > a.len() || carry_b == 0); +} + +// - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff +// -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1 +// answer is pos, has length of b +fn bitand_neg_pos(a: &mut Vec, b: &[BigDigit]) { + let mut carry_a = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = twos_a & bi; + } + debug_assert!(a.len() > b.len() || carry_a == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => a.truncate(b.len()), + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().cloned()); + } + } +} + +// - 1 & -ff = ...f ff & ...f 01 = ...f 01 = - ff +// -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff +// -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100 +// answer is neg, has length of longest with a possible carry +fn bitand_neg_neg(a: &mut Vec, b: &[BigDigit]) { + let mut carry_a = 1; + let mut carry_b = 1; + let mut carry_and = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + let twos_b = negate_carry(bi, &mut carry_b); + *ai = negate_carry(twos_a & twos_b, &mut carry_and); + } + debug_assert!(a.len() > b.len() || carry_a == 0); + debug_assert!(b.len() > a.len() || carry_b == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a, &mut carry_and); + } + debug_assert!(carry_a == 0); + } + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_and) + })); + debug_assert!(carry_b == 0); + } + } + if carry_and != 0 { + a.push(1); + } +} + +forward_val_val_binop!(impl BitAnd for BigInt, bitand); +forward_ref_val_binop!(impl BitAnd for BigInt, bitand); + +// do not use forward_ref_ref_binop_commutative! for bitand so that we can +// clone as needed, avoiding over-allocation +impl BitAnd<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn bitand(self, other: &BigInt) -> BigInt { + match (self.sign, other.sign) { + (NoSign, _) | (_, NoSign) => BigInt::ZERO, + (Plus, Plus) => BigInt::from(&self.data & &other.data), + (Plus, Minus) => self.clone() & other, + (Minus, Plus) => other.clone() & self, + (Minus, Minus) => { + // forward to val-ref, choosing the larger to clone + if self.len() >= other.len() { + self.clone() & other + } else { + other.clone() & self + } + } + } + } +} + +impl BitAnd<&BigInt> for BigInt { + type Output = BigInt; + + #[inline] + fn bitand(mut self, other: &BigInt) -> BigInt { + self &= other; + self + } +} + +forward_val_assign!(impl BitAndAssign for BigInt, bitand_assign); + +impl BitAndAssign<&BigInt> for BigInt { + fn bitand_assign(&mut self, other: &BigInt) { + match (self.sign, other.sign) { + (NoSign, _) => {} + (_, NoSign) => self.set_zero(), + (Plus, Plus) => { + self.data &= &other.data; + if self.data.is_zero() { + self.sign = NoSign; + } + } + (Plus, Minus) => { + bitand_pos_neg(self.digits_mut(), other.digits()); + self.normalize(); + } + (Minus, Plus) => { + bitand_neg_pos(self.digits_mut(), other.digits()); + self.sign = Plus; + self.normalize(); + } + (Minus, Minus) => { + bitand_neg_neg(self.digits_mut(), other.digits()); + self.normalize(); + } + } + } +} + +// + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff +// +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1 +// answer is neg, has length of b +fn bitor_pos_neg(a: &mut Vec, b: &[BigDigit]) { + let mut carry_b = 1; + let mut carry_or = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_b = negate_carry(bi, &mut carry_b); + *ai = negate_carry(*ai | twos_b, &mut carry_or); + } + debug_assert!(b.len() > a.len() || carry_b == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => { + a.truncate(b.len()); + } + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_or) + })); + debug_assert!(carry_b == 0); + } + } + // for carry_or to be non-zero, we would need twos_b == 0 + debug_assert!(carry_or == 0); +} + +// - 1 | +ff = ...f ff | ...0 ff = ...f ff = - 1 +// -ff | + 1 = ...f 01 | ...0 01 = ...f 01 = -ff +// answer is neg, has length of a +fn bitor_neg_pos(a: &mut [BigDigit], b: &[BigDigit]) { + let mut carry_a = 1; + let mut carry_or = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a | bi, &mut carry_or); + } + debug_assert!(a.len() > b.len() || carry_a == 0); + if a.len() > b.len() { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a, &mut carry_or); + } + debug_assert!(carry_a == 0); + } + // for carry_or to be non-zero, we would need twos_a == 0 + debug_assert!(carry_or == 0); +} + +// - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1 +// -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1 +// answer is neg, has length of shortest +fn bitor_neg_neg(a: &mut Vec, b: &[BigDigit]) { + let mut carry_a = 1; + let mut carry_b = 1; + let mut carry_or = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + let twos_b = negate_carry(bi, &mut carry_b); + *ai = negate_carry(twos_a | twos_b, &mut carry_or); + } + debug_assert!(a.len() > b.len() || carry_a == 0); + debug_assert!(b.len() > a.len() || carry_b == 0); + if a.len() > b.len() { + a.truncate(b.len()); + } + // for carry_or to be non-zero, we would need twos_a == 0 or twos_b == 0 + debug_assert!(carry_or == 0); +} + +forward_val_val_binop!(impl BitOr for BigInt, bitor); +forward_ref_val_binop!(impl BitOr for BigInt, bitor); + +// do not use forward_ref_ref_binop_commutative! for bitor so that we can +// clone as needed, avoiding over-allocation +impl BitOr<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn bitor(self, other: &BigInt) -> BigInt { + match (self.sign, other.sign) { + (NoSign, _) => other.clone(), + (_, NoSign) => self.clone(), + (Plus, Plus) => BigInt::from(&self.data | &other.data), + (Plus, Minus) => other.clone() | self, + (Minus, Plus) => self.clone() | other, + (Minus, Minus) => { + // forward to val-ref, choosing the smaller to clone + if self.len() <= other.len() { + self.clone() | other + } else { + other.clone() | self + } + } + } + } +} + +impl BitOr<&BigInt> for BigInt { + type Output = BigInt; + + #[inline] + fn bitor(mut self, other: &BigInt) -> BigInt { + self |= other; + self + } +} + +forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign); + +impl BitOrAssign<&BigInt> for BigInt { + fn bitor_assign(&mut self, other: &BigInt) { + match (self.sign, other.sign) { + (_, NoSign) => {} + (NoSign, _) => self.clone_from(other), + (Plus, Plus) => self.data |= &other.data, + (Plus, Minus) => { + bitor_pos_neg(self.digits_mut(), other.digits()); + self.sign = Minus; + self.normalize(); + } + (Minus, Plus) => { + bitor_neg_pos(self.digits_mut(), other.digits()); + self.normalize(); + } + (Minus, Minus) => { + bitor_neg_neg(self.digits_mut(), other.digits()); + self.normalize(); + } + } + } +} + +// + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100 +// +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100 +// answer is neg, has length of longest with a possible carry +fn bitxor_pos_neg(a: &mut Vec, b: &[BigDigit]) { + let mut carry_b = 1; + let mut carry_xor = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_b = negate_carry(bi, &mut carry_b); + *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); + } + debug_assert!(b.len() > a.len() || carry_b == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => { + for ai in a[b.len()..].iter_mut() { + let twos_b = !0; + *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); + } + } + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_xor) + })); + debug_assert!(carry_b == 0); + } + } + if carry_xor != 0 { + a.push(1); + } +} + +// - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100 +// -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100 +// answer is neg, has length of longest with a possible carry +fn bitxor_neg_pos(a: &mut Vec, b: &[BigDigit]) { + let mut carry_a = 1; + let mut carry_xor = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a ^ bi, &mut carry_xor); + } + debug_assert!(a.len() > b.len() || carry_a == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a, &mut carry_xor); + } + debug_assert!(carry_a == 0); + } + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_a = !0; + negate_carry(twos_a ^ bi, &mut carry_xor) + })); + } + } + if carry_xor != 0 { + a.push(1); + } +} + +// - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe +// -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe +// answer is pos, has length of longest +fn bitxor_neg_neg(a: &mut Vec, b: &[BigDigit]) { + let mut carry_a = 1; + let mut carry_b = 1; + for (ai, &bi) in a.iter_mut().zip(b.iter()) { + let twos_a = negate_carry(*ai, &mut carry_a); + let twos_b = negate_carry(bi, &mut carry_b); + *ai = twos_a ^ twos_b; + } + debug_assert!(a.len() > b.len() || carry_a == 0); + debug_assert!(b.len() > a.len() || carry_b == 0); + match Ord::cmp(&a.len(), &b.len()) { + Greater => { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + let twos_b = !0; + *ai = twos_a ^ twos_b; + } + debug_assert!(carry_a == 0); + } + Equal => {} + Less => { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_a = !0; + let twos_b = negate_carry(bi, &mut carry_b); + twos_a ^ twos_b + })); + debug_assert!(carry_b == 0); + } + } +} + +forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor); + +impl BitXor<&BigInt> for BigInt { + type Output = BigInt; + + #[inline] + fn bitxor(mut self, other: &BigInt) -> BigInt { + self ^= other; + self + } +} + +forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign); + +impl BitXorAssign<&BigInt> for BigInt { + fn bitxor_assign(&mut self, other: &BigInt) { + match (self.sign, other.sign) { + (_, NoSign) => {} + (NoSign, _) => self.clone_from(other), + (Plus, Plus) => { + self.data ^= &other.data; + if self.data.is_zero() { + self.sign = NoSign; + } + } + (Plus, Minus) => { + bitxor_pos_neg(self.digits_mut(), other.digits()); + self.sign = Minus; + self.normalize(); + } + (Minus, Plus) => { + bitxor_neg_pos(self.digits_mut(), other.digits()); + self.normalize(); + } + (Minus, Minus) => { + bitxor_neg_neg(self.digits_mut(), other.digits()); + self.sign = Plus; + self.normalize(); + } + } + } +} + +pub(super) fn set_negative_bit(x: &mut BigInt, bit: u64, value: bool) { + debug_assert_eq!(x.sign, Minus); + let data = &mut x.data; + + let bits_per_digit = u64::from(big_digit::BITS); + if bit >= bits_per_digit * data.len() as u64 { + if !value { + data.set_bit(bit, true); + } + } else { + // If the Uint number is + // ... 0 x 1 0 ... 0 + // then the two's complement is + // ... 1 !x 1 0 ... 0 + // |-- bit at position 'trailing_zeros' + // where !x is obtained from x by flipping each bit + let trailing_zeros = data.trailing_zeros().unwrap(); + if bit > trailing_zeros { + data.set_bit(bit, !value); + } else if bit == trailing_zeros && !value { + // Clearing the bit at position `trailing_zeros` is dealt with by doing + // similarly to what `bitand_neg_pos` does, except we start at digit + // `bit_index`. All digits below `bit_index` are guaranteed to be zero, + // so initially we have `carry_in` = `carry_out` = 1. Furthermore, we + // stop traversing the digits when there are no more carries. + let bit_index = (bit / bits_per_digit).to_usize().unwrap(); + let bit_mask = (1 as BigDigit) << (bit % bits_per_digit); + let mut digit_iter = data.digits_mut().iter_mut().skip(bit_index); + let mut carry_in = 1; + let mut carry_out = 1; + + let digit = digit_iter.next().unwrap(); + let twos_in = negate_carry(*digit, &mut carry_in); + let twos_out = twos_in & !bit_mask; + *digit = negate_carry(twos_out, &mut carry_out); + + for digit in digit_iter { + if carry_in == 0 && carry_out == 0 { + // Exit the loop since no more digits can change + break; + } + let twos = negate_carry(*digit, &mut carry_in); + *digit = negate_carry(twos, &mut carry_out); + } + + if carry_out != 0 { + // All digits have been traversed and there is a carry + debug_assert_eq!(carry_in, 0); + data.digits_mut().push(1); + } + } else if bit < trailing_zeros && value { + // Flip each bit from position 'bit' to 'trailing_zeros', both inclusive + // ... 1 !x 1 0 ... 0 ... 0 + // |-- bit at position 'bit' + // |-- bit at position 'trailing_zeros' + // bit_mask: 1 1 ... 1 0 .. 0 + // This is done by xor'ing with the bit_mask + let index_lo = (bit / bits_per_digit).to_usize().unwrap(); + let index_hi = (trailing_zeros / bits_per_digit).to_usize().unwrap(); + let bit_mask_lo = big_digit::MAX << (bit % bits_per_digit); + let bit_mask_hi = + big_digit::MAX >> (bits_per_digit - 1 - (trailing_zeros % bits_per_digit)); + let digits = data.digits_mut(); + + if index_lo == index_hi { + digits[index_lo] ^= bit_mask_lo & bit_mask_hi; + } else { + digits[index_lo] = bit_mask_lo; + for digit in &mut digits[index_lo + 1..index_hi] { + *digit = big_digit::MAX; + } + digits[index_hi] ^= bit_mask_hi; + } + } else { + // We end up here in two cases: + // bit == trailing_zeros && value: Bit is already set + // bit < trailing_zeros && !value: Bit is already cleared + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/convert.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/convert.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/convert.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,472 @@ +use super::Sign::{self, Minus, NoSign, Plus}; +use super::{BigInt, ToBigInt}; + +use crate::TryFromBigIntError; +use crate::{BigUint, ParseBigIntError, ToBigUint}; + +use alloc::vec::Vec; +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::convert::TryFrom; +use core::str::{self, FromStr}; +use num_traits::{FromPrimitive, Num, One, ToPrimitive, Zero}; + +impl FromStr for BigInt { + type Err = ParseBigIntError; + + #[inline] + fn from_str(s: &str) -> Result { + BigInt::from_str_radix(s, 10) + } +} + +impl Num for BigInt { + type FromStrRadixErr = ParseBigIntError; + + /// Creates and initializes a [`BigInt`]. + #[inline] + fn from_str_radix(mut s: &str, radix: u32) -> Result { + let sign = if let Some(tail) = s.strip_prefix('-') { + if !tail.starts_with('+') { + s = tail + } + Minus + } else { + Plus + }; + let bu = BigUint::from_str_radix(s, radix)?; + Ok(BigInt::from_biguint(sign, bu)) + } +} + +impl ToPrimitive for BigInt { + #[inline] + fn to_i64(&self) -> Option { + match self.sign { + Plus => self.data.to_i64(), + NoSign => Some(0), + Minus => { + let n = self.data.to_u64()?; + let m: u64 = 1 << 63; + match n.cmp(&m) { + Less => Some(-(n as i64)), + Equal => Some(i64::MIN), + Greater => None, + } + } + } + } + + #[inline] + fn to_i128(&self) -> Option { + match self.sign { + Plus => self.data.to_i128(), + NoSign => Some(0), + Minus => { + let n = self.data.to_u128()?; + let m: u128 = 1 << 127; + match n.cmp(&m) { + Less => Some(-(n as i128)), + Equal => Some(i128::MIN), + Greater => None, + } + } + } + } + + #[inline] + fn to_u64(&self) -> Option { + match self.sign { + Plus => self.data.to_u64(), + NoSign => Some(0), + Minus => None, + } + } + + #[inline] + fn to_u128(&self) -> Option { + match self.sign { + Plus => self.data.to_u128(), + NoSign => Some(0), + Minus => None, + } + } + + #[inline] + fn to_f32(&self) -> Option { + let n = self.data.to_f32()?; + Some(if self.sign == Minus { -n } else { n }) + } + + #[inline] + fn to_f64(&self) -> Option { + let n = self.data.to_f64()?; + Some(if self.sign == Minus { -n } else { n }) + } +} + +macro_rules! impl_try_from_bigint { + ($T:ty, $to_ty:path) => { + impl TryFrom<&BigInt> for $T { + type Error = TryFromBigIntError<()>; + + #[inline] + fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> { + $to_ty(value).ok_or(TryFromBigIntError::new(())) + } + } + + impl TryFrom for $T { + type Error = TryFromBigIntError; + + #[inline] + fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError> { + <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) + } + } + }; +} + +impl_try_from_bigint!(u8, ToPrimitive::to_u8); +impl_try_from_bigint!(u16, ToPrimitive::to_u16); +impl_try_from_bigint!(u32, ToPrimitive::to_u32); +impl_try_from_bigint!(u64, ToPrimitive::to_u64); +impl_try_from_bigint!(usize, ToPrimitive::to_usize); +impl_try_from_bigint!(u128, ToPrimitive::to_u128); + +impl_try_from_bigint!(i8, ToPrimitive::to_i8); +impl_try_from_bigint!(i16, ToPrimitive::to_i16); +impl_try_from_bigint!(i32, ToPrimitive::to_i32); +impl_try_from_bigint!(i64, ToPrimitive::to_i64); +impl_try_from_bigint!(isize, ToPrimitive::to_isize); +impl_try_from_bigint!(i128, ToPrimitive::to_i128); + +impl FromPrimitive for BigInt { + #[inline] + fn from_i64(n: i64) -> Option { + Some(BigInt::from(n)) + } + + #[inline] + fn from_i128(n: i128) -> Option { + Some(BigInt::from(n)) + } + + #[inline] + fn from_u64(n: u64) -> Option { + Some(BigInt::from(n)) + } + + #[inline] + fn from_u128(n: u128) -> Option { + Some(BigInt::from(n)) + } + + #[inline] + fn from_f64(n: f64) -> Option { + if n >= 0.0 { + BigUint::from_f64(n).map(BigInt::from) + } else { + let x = BigUint::from_f64(-n)?; + Some(-BigInt::from(x)) + } + } +} + +impl From for BigInt { + #[inline] + fn from(n: i64) -> Self { + if n >= 0 { + BigInt::from(n as u64) + } else { + let u = u64::MAX - (n as u64) + 1; + BigInt { + sign: Minus, + data: BigUint::from(u), + } + } + } +} + +impl From for BigInt { + #[inline] + fn from(n: i128) -> Self { + if n >= 0 { + BigInt::from(n as u128) + } else { + let u = u128::MAX - (n as u128) + 1; + BigInt { + sign: Minus, + data: BigUint::from(u), + } + } + } +} + +macro_rules! impl_bigint_from_int { + ($T:ty) => { + impl From<$T> for BigInt { + #[inline] + fn from(n: $T) -> Self { + BigInt::from(n as i64) + } + } + }; +} + +impl_bigint_from_int!(i8); +impl_bigint_from_int!(i16); +impl_bigint_from_int!(i32); +impl_bigint_from_int!(isize); + +impl From for BigInt { + #[inline] + fn from(n: u64) -> Self { + if n > 0 { + BigInt { + sign: Plus, + data: BigUint::from(n), + } + } else { + Self::ZERO + } + } +} + +impl From for BigInt { + #[inline] + fn from(n: u128) -> Self { + if n > 0 { + BigInt { + sign: Plus, + data: BigUint::from(n), + } + } else { + Self::ZERO + } + } +} + +macro_rules! impl_bigint_from_uint { + ($T:ty) => { + impl From<$T> for BigInt { + #[inline] + fn from(n: $T) -> Self { + BigInt::from(n as u64) + } + } + }; +} + +impl_bigint_from_uint!(u8); +impl_bigint_from_uint!(u16); +impl_bigint_from_uint!(u32); +impl_bigint_from_uint!(usize); + +impl From for BigInt { + #[inline] + fn from(n: BigUint) -> Self { + if n.is_zero() { + Self::ZERO + } else { + BigInt { + sign: Plus, + data: n, + } + } + } +} + +impl ToBigInt for BigInt { + #[inline] + fn to_bigint(&self) -> Option { + Some(self.clone()) + } +} + +impl ToBigInt for BigUint { + #[inline] + fn to_bigint(&self) -> Option { + if self.is_zero() { + Some(BigInt::ZERO) + } else { + Some(BigInt { + sign: Plus, + data: self.clone(), + }) + } + } +} + +impl ToBigUint for BigInt { + #[inline] + fn to_biguint(&self) -> Option { + match self.sign() { + Plus => Some(self.data.clone()), + NoSign => Some(BigUint::ZERO), + Minus => None, + } + } +} + +impl TryFrom<&BigInt> for BigUint { + type Error = TryFromBigIntError<()>; + + #[inline] + fn try_from(value: &BigInt) -> Result> { + value + .to_biguint() + .ok_or_else(|| TryFromBigIntError::new(())) + } +} + +impl TryFrom for BigUint { + type Error = TryFromBigIntError; + + #[inline] + fn try_from(value: BigInt) -> Result> { + if value.sign() == Sign::Minus { + Err(TryFromBigIntError::new(value)) + } else { + Ok(value.data) + } + } +} + +macro_rules! impl_to_bigint { + ($T:ty, $from_ty:path) => { + impl ToBigInt for $T { + #[inline] + fn to_bigint(&self) -> Option { + $from_ty(*self) + } + } + }; +} + +impl_to_bigint!(isize, FromPrimitive::from_isize); +impl_to_bigint!(i8, FromPrimitive::from_i8); +impl_to_bigint!(i16, FromPrimitive::from_i16); +impl_to_bigint!(i32, FromPrimitive::from_i32); +impl_to_bigint!(i64, FromPrimitive::from_i64); +impl_to_bigint!(i128, FromPrimitive::from_i128); + +impl_to_bigint!(usize, FromPrimitive::from_usize); +impl_to_bigint!(u8, FromPrimitive::from_u8); +impl_to_bigint!(u16, FromPrimitive::from_u16); +impl_to_bigint!(u32, FromPrimitive::from_u32); +impl_to_bigint!(u64, FromPrimitive::from_u64); +impl_to_bigint!(u128, FromPrimitive::from_u128); + +impl_to_bigint!(f32, FromPrimitive::from_f32); +impl_to_bigint!(f64, FromPrimitive::from_f64); + +impl From for BigInt { + fn from(x: bool) -> Self { + if x { + One::one() + } else { + Self::ZERO + } + } +} + +#[inline] +pub(super) fn from_signed_bytes_be(digits: &[u8]) -> BigInt { + let sign = match digits.first() { + Some(v) if *v > 0x7f => Sign::Minus, + Some(_) => Sign::Plus, + None => return BigInt::ZERO, + }; + + if sign == Sign::Minus { + // two's-complement the content to retrieve the magnitude + let mut digits = Vec::from(digits); + twos_complement_be(&mut digits); + BigInt::from_biguint(sign, BigUint::from_bytes_be(&digits)) + } else { + BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) + } +} + +#[inline] +pub(super) fn from_signed_bytes_le(digits: &[u8]) -> BigInt { + let sign = match digits.last() { + Some(v) if *v > 0x7f => Sign::Minus, + Some(_) => Sign::Plus, + None => return BigInt::ZERO, + }; + + if sign == Sign::Minus { + // two's-complement the content to retrieve the magnitude + let mut digits = Vec::from(digits); + twos_complement_le(&mut digits); + BigInt::from_biguint(sign, BigUint::from_bytes_le(&digits)) + } else { + BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) + } +} + +#[inline] +pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec { + let mut bytes = x.data.to_bytes_be(); + let first_byte = bytes.first().cloned().unwrap_or(0); + if first_byte > 0x7f + && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && x.sign == Sign::Minus) + { + // msb used by magnitude, extend by 1 byte + bytes.insert(0, 0); + } + if x.sign == Sign::Minus { + twos_complement_be(&mut bytes); + } + bytes +} + +#[inline] +pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec { + let mut bytes = x.data.to_bytes_le(); + let last_byte = bytes.last().cloned().unwrap_or(0); + if last_byte > 0x7f + && !(last_byte == 0x80 + && bytes.iter().rev().skip(1).all(Zero::is_zero) + && x.sign == Sign::Minus) + { + // msb used by magnitude, extend by 1 byte + bytes.push(0); + } + if x.sign == Sign::Minus { + twos_complement_le(&mut bytes); + } + bytes +} + +/// Perform in-place two's complement of the given binary representation, +/// in little-endian byte order. +#[inline] +fn twos_complement_le(digits: &mut [u8]) { + twos_complement(digits) +} + +/// Perform in-place two's complement of the given binary representation +/// in big-endian byte order. +#[inline] +fn twos_complement_be(digits: &mut [u8]) { + twos_complement(digits.iter_mut().rev()) +} + +/// Perform in-place two's complement of the given digit iterator +/// starting from the least significant byte. +#[inline] +fn twos_complement<'a, I>(digits: I) +where + I: IntoIterator, +{ + let mut carry = true; + for d in digits { + *d = !*d; + if carry { + *d = d.wrapping_add(1); + carry = d.is_zero(); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/division.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/division.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/division.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/division.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,513 @@ +use super::CheckedUnsignedAbs::{Negative, Positive}; +use super::Sign::NoSign; +use super::{BigInt, UnsignedAbs}; + +use crate::{IsizePromotion, UsizePromotion}; + +use core::ops::{Div, DivAssign, Rem, RemAssign}; +use num_integer::Integer; +use num_traits::{CheckedDiv, CheckedEuclid, Euclid, Signed, ToPrimitive, Zero}; + +forward_all_binop_to_ref_ref!(impl Div for BigInt, div); + +impl Div<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: &BigInt) -> BigInt { + let (q, _) = self.div_rem(other); + q + } +} + +impl DivAssign<&BigInt> for BigInt { + #[inline] + fn div_assign(&mut self, other: &BigInt) { + *self = &*self / other; + } +} +forward_val_assign!(impl DivAssign for BigInt, div_assign); + +promote_all_scalars!(impl Div for BigInt, div); +promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: u32) -> BigInt { + BigInt::from_biguint(self.sign, self.data / other) + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: u32) { + self.data /= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Div for u32 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + BigInt::from_biguint(other.sign, self / other.data) + } +} + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: u64) -> BigInt { + BigInt::from_biguint(self.sign, self.data / other) + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: u64) { + self.data /= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Div for u64 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + BigInt::from_biguint(other.sign, self / other.data) + } +} + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: u128) -> BigInt { + BigInt::from_biguint(self.sign, self.data / other) + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: u128) { + self.data /= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Div for u128 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + BigInt::from_biguint(other.sign, self / other.data) + } +} + +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: i32) -> BigInt { + match other.checked_uabs() { + Positive(u) => self / u, + Negative(u) => -self / u, + } + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: i32) { + match other.checked_uabs() { + Positive(u) => *self /= u, + Negative(u) => { + self.sign = -self.sign; + *self /= u; + } + } + } +} + +impl Div for i32 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u / other, + Negative(u) => u / -other, + } + } +} + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: i64) -> BigInt { + match other.checked_uabs() { + Positive(u) => self / u, + Negative(u) => -self / u, + } + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: i64) { + match other.checked_uabs() { + Positive(u) => *self /= u, + Negative(u) => { + self.sign = -self.sign; + *self /= u; + } + } + } +} + +impl Div for i64 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u / other, + Negative(u) => u / -other, + } + } +} + +impl Div for BigInt { + type Output = BigInt; + + #[inline] + fn div(self, other: i128) -> BigInt { + match other.checked_uabs() { + Positive(u) => self / u, + Negative(u) => -self / u, + } + } +} + +impl DivAssign for BigInt { + #[inline] + fn div_assign(&mut self, other: i128) { + match other.checked_uabs() { + Positive(u) => *self /= u, + Negative(u) => { + self.sign = -self.sign; + *self /= u; + } + } + } +} + +impl Div for i128 { + type Output = BigInt; + + #[inline] + fn div(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u / other, + Negative(u) => u / -other, + } + } +} + +forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); + +impl Rem<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: &BigInt) -> BigInt { + if let Some(other) = other.to_u32() { + self % other + } else if let Some(other) = other.to_i32() { + self % other + } else { + let (_, r) = self.div_rem(other); + r + } + } +} + +impl RemAssign<&BigInt> for BigInt { + #[inline] + fn rem_assign(&mut self, other: &BigInt) { + *self = &*self % other; + } +} +forward_val_assign!(impl RemAssign for BigInt, rem_assign); + +promote_all_scalars!(impl Rem for BigInt, rem); +promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: u32) -> BigInt { + BigInt::from_biguint(self.sign, self.data % other) + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: u32) { + self.data %= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Rem for u32 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + BigInt::from(self % other.data) + } +} + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: u64) -> BigInt { + BigInt::from_biguint(self.sign, self.data % other) + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: u64) { + self.data %= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Rem for u64 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + BigInt::from(self % other.data) + } +} + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: u128) -> BigInt { + BigInt::from_biguint(self.sign, self.data % other) + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: u128) { + self.data %= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Rem for u128 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + BigInt::from(self % other.data) + } +} + +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: i32) -> BigInt { + self % other.unsigned_abs() + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: i32) { + *self %= other.unsigned_abs(); + } +} + +impl Rem for i32 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u % other, + Negative(u) => -(u % other), + } + } +} + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: i64) -> BigInt { + self % other.unsigned_abs() + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: i64) { + *self %= other.unsigned_abs(); + } +} + +impl Rem for i64 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u % other, + Negative(u) => -(u % other), + } + } +} + +impl Rem for BigInt { + type Output = BigInt; + + #[inline] + fn rem(self, other: i128) -> BigInt { + self % other.unsigned_abs() + } +} + +impl RemAssign for BigInt { + #[inline] + fn rem_assign(&mut self, other: i128) { + *self %= other.unsigned_abs(); + } +} + +impl Rem for i128 { + type Output = BigInt; + + #[inline] + fn rem(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u % other, + Negative(u) => -(u % other), + } + } +} + +impl CheckedDiv for BigInt { + #[inline] + fn checked_div(&self, v: &BigInt) -> Option { + if v.is_zero() { + return None; + } + Some(self.div(v)) + } +} + +impl CheckedEuclid for BigInt { + #[inline] + fn checked_div_euclid(&self, v: &BigInt) -> Option { + if v.is_zero() { + return None; + } + Some(self.div_euclid(v)) + } + + #[inline] + fn checked_rem_euclid(&self, v: &BigInt) -> Option { + if v.is_zero() { + return None; + } + Some(self.rem_euclid(v)) + } + + fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { + Some(self.div_rem_euclid(v)) + } +} + +impl Euclid for BigInt { + #[inline] + fn div_euclid(&self, v: &BigInt) -> BigInt { + let (q, r) = self.div_rem(v); + if r.is_negative() { + if v.is_positive() { + q - 1 + } else { + q + 1 + } + } else { + q + } + } + + #[inline] + fn rem_euclid(&self, v: &BigInt) -> BigInt { + let r = self % v; + if r.is_negative() { + if v.is_positive() { + r + v + } else { + r - v + } + } else { + r + } + } + + fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { + let (q, r) = self.div_rem(v); + if r.is_negative() { + if v.is_positive() { + (q - 1, r + v) + } else { + (q + 1, r - v) + } + } else { + (q, r) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/multiplication.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/multiplication.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/multiplication.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/multiplication.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +use super::CheckedUnsignedAbs::{Negative, Positive}; +use super::Sign::{self, Minus, NoSign, Plus}; +use super::{BigInt, UnsignedAbs}; + +use crate::{IsizePromotion, UsizePromotion}; + +use core::iter::Product; +use core::ops::{Mul, MulAssign}; +use num_traits::{CheckedMul, One, Zero}; + +impl Mul for Sign { + type Output = Sign; + + #[inline] + fn mul(self, other: Sign) -> Sign { + match (self, other) { + (NoSign, _) | (_, NoSign) => NoSign, + (Plus, Plus) | (Minus, Minus) => Plus, + (Plus, Minus) | (Minus, Plus) => Minus, + } + } +} + +macro_rules! impl_mul { + ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( + impl Mul<$Other> for $Self { + type Output = BigInt; + + #[inline] + fn mul(self, other: $Other) -> BigInt { + // automatically match value/ref + let BigInt { data: x, .. } = self; + let BigInt { data: y, .. } = other; + BigInt::from_biguint(self.sign * other.sign, x * y) + } + } + )*} +} +impl_mul! { + impl Mul for BigInt; + impl Mul for &BigInt; + impl Mul<&BigInt> for BigInt; + impl Mul<&BigInt> for &BigInt; +} + +macro_rules! impl_mul_assign { + ($(impl MulAssign<$Other:ty> for BigInt;)*) => {$( + impl MulAssign<$Other> for BigInt { + #[inline] + fn mul_assign(&mut self, other: $Other) { + // automatically match value/ref + let BigInt { data: y, .. } = other; + self.data *= y; + if self.data.is_zero() { + self.sign = NoSign; + } else { + self.sign = self.sign * other.sign; + } + } + } + )*} +} +impl_mul_assign! { + impl MulAssign for BigInt; + impl MulAssign<&BigInt> for BigInt; +} + +promote_all_scalars!(impl Mul for BigInt, mul); +promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: u32) -> BigInt { + BigInt::from_biguint(self.sign, self.data * other) + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: u32) { + self.data *= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: u64) -> BigInt { + BigInt::from_biguint(self.sign, self.data * other) + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: u64) { + self.data *= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: u128) -> BigInt { + BigInt::from_biguint(self.sign, self.data * other) + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: u128) { + self.data *= other; + if self.data.is_zero() { + self.sign = NoSign; + } + } +} + +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: i32) -> BigInt { + match other.checked_uabs() { + Positive(u) => self * u, + Negative(u) => -self * u, + } + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: i32) { + match other.checked_uabs() { + Positive(u) => *self *= u, + Negative(u) => { + self.sign = -self.sign; + self.data *= u; + } + } + } +} + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: i64) -> BigInt { + match other.checked_uabs() { + Positive(u) => self * u, + Negative(u) => -self * u, + } + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: i64) { + match other.checked_uabs() { + Positive(u) => *self *= u, + Negative(u) => { + self.sign = -self.sign; + self.data *= u; + } + } + } +} + +impl Mul for BigInt { + type Output = BigInt; + + #[inline] + fn mul(self, other: i128) -> BigInt { + match other.checked_uabs() { + Positive(u) => self * u, + Negative(u) => -self * u, + } + } +} + +impl MulAssign for BigInt { + #[inline] + fn mul_assign(&mut self, other: i128) { + match other.checked_uabs() { + Positive(u) => *self *= u, + Negative(u) => { + self.sign = -self.sign; + self.data *= u; + } + } + } +} + +impl CheckedMul for BigInt { + #[inline] + fn checked_mul(&self, v: &BigInt) -> Option { + Some(self.mul(v)) + } +} + +impl_product_iter_type!(BigInt); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/power.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/power.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/power.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/power.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,94 @@ +use super::BigInt; +use super::Sign::{self, Minus, Plus}; + +use crate::BigUint; + +use num_integer::Integer; +use num_traits::{Pow, Signed, Zero}; + +/// Help function for pow +/// +/// Computes the effect of the exponent on the sign. +#[inline] +fn powsign(sign: Sign, other: &T) -> Sign { + if other.is_zero() { + Plus + } else if sign != Minus || other.is_odd() { + sign + } else { + -sign + } +} + +macro_rules! pow_impl { + ($T:ty) => { + impl Pow<$T> for BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: $T) -> BigInt { + BigInt::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs)) + } + } + + impl Pow<&$T> for BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: &$T) -> BigInt { + BigInt::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs)) + } + } + + impl Pow<$T> for &BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: $T) -> BigInt { + BigInt::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs)) + } + } + + impl Pow<&$T> for &BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: &$T) -> BigInt { + BigInt::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs)) + } + } + }; +} + +pow_impl!(u8); +pow_impl!(u16); +pow_impl!(u32); +pow_impl!(u64); +pow_impl!(usize); +pow_impl!(u128); +pow_impl!(BigUint); + +pub(super) fn modpow(x: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt { + assert!( + !exponent.is_negative(), + "negative exponentiation is not supported!" + ); + assert!( + !modulus.is_zero(), + "attempt to calculate with zero modulus!" + ); + + let result = x.data.modpow(&exponent.data, &modulus.data); + if result.is_zero() { + return BigInt::ZERO; + } + + // The sign of the result follows the modulus, like `mod_floor`. + let (sign, mag) = match (x.is_negative() && exponent.is_odd(), modulus.is_negative()) { + (false, false) => (Plus, result), + (true, false) => (Plus, &modulus.data - result), + (false, true) => (Minus, &modulus.data - result), + (true, true) => (Minus, result), + }; + BigInt::from_biguint(sign, mag) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +#![cfg(feature = "serde")] +#![cfg_attr(docsrs, doc(cfg(feature = "serde")))] + +use super::{BigInt, Sign}; + +use serde::de::{Error, Unexpected}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +impl Serialize for Sign { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Note: do not change the serialization format, or it may break + // forward and backward compatibility of serialized data! + match *self { + Sign::Minus => (-1i8).serialize(serializer), + Sign::NoSign => 0i8.serialize(serializer), + Sign::Plus => 1i8.serialize(serializer), + } + } +} + +impl<'de> Deserialize<'de> for Sign { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let sign = i8::deserialize(deserializer)?; + match sign { + -1 => Ok(Sign::Minus), + 0 => Ok(Sign::NoSign), + 1 => Ok(Sign::Plus), + _ => Err(D::Error::invalid_value( + Unexpected::Signed(sign.into()), + &"a sign of -1, 0, or 1", + )), + } + } +} + +impl Serialize for BigInt { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Note: do not change the serialization format, or it may break + // forward and backward compatibility of serialized data! + (self.sign, &self.data).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for BigInt { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let (sign, data) = Deserialize::deserialize(deserializer)?; + Ok(BigInt::from_biguint(sign, data)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/shift.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/shift.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/shift.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/shift.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,107 @@ +use super::BigInt; +use super::Sign::NoSign; + +use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; +use num_traits::{PrimInt, Signed, Zero}; + +macro_rules! impl_shift { + (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { + impl $Shx<&$rhs> for BigInt { + type Output = BigInt; + + #[inline] + fn $shx(self, rhs: &$rhs) -> BigInt { + $Shx::$shx(self, *rhs) + } + } + impl $Shx<&$rhs> for &BigInt { + type Output = BigInt; + + #[inline] + fn $shx(self, rhs: &$rhs) -> BigInt { + $Shx::$shx(self, *rhs) + } + } + impl $ShxAssign<&$rhs> for BigInt { + #[inline] + fn $shx_assign(&mut self, rhs: &$rhs) { + $ShxAssign::$shx_assign(self, *rhs); + } + } + }; + ($($rhs:ty),+) => {$( + impl Shl<$rhs> for BigInt { + type Output = BigInt; + + #[inline] + fn shl(self, rhs: $rhs) -> BigInt { + BigInt::from_biguint(self.sign, self.data << rhs) + } + } + impl Shl<$rhs> for &BigInt { + type Output = BigInt; + + #[inline] + fn shl(self, rhs: $rhs) -> BigInt { + BigInt::from_biguint(self.sign, &self.data << rhs) + } + } + impl ShlAssign<$rhs> for BigInt { + #[inline] + fn shl_assign(&mut self, rhs: $rhs) { + self.data <<= rhs + } + } + impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } + + impl Shr<$rhs> for BigInt { + type Output = BigInt; + + #[inline] + fn shr(self, rhs: $rhs) -> BigInt { + let round_down = shr_round_down(&self, rhs); + let data = self.data >> rhs; + let data = if round_down { data + 1u8 } else { data }; + BigInt::from_biguint(self.sign, data) + } + } + impl Shr<$rhs> for &BigInt { + type Output = BigInt; + + #[inline] + fn shr(self, rhs: $rhs) -> BigInt { + let round_down = shr_round_down(self, rhs); + let data = &self.data >> rhs; + let data = if round_down { data + 1u8 } else { data }; + BigInt::from_biguint(self.sign, data) + } + } + impl ShrAssign<$rhs> for BigInt { + #[inline] + fn shr_assign(&mut self, rhs: $rhs) { + let round_down = shr_round_down(self, rhs); + self.data >>= rhs; + if round_down { + self.data += 1u8; + } else if self.data.is_zero() { + self.sign = NoSign; + } + } + } + impl_shift! { @ref Shr::shr, ShrAssign::shr_assign, $rhs } + )*}; +} + +impl_shift! { u8, u16, u32, u64, u128, usize } +impl_shift! { i8, i16, i32, i64, i128, isize } + +// Negative values need a rounding adjustment if there are any ones in the +// bits that are getting shifted out. +fn shr_round_down(i: &BigInt, shift: T) -> bool { + if i.is_negative() { + let zeros = i.trailing_zeros().expect("negative values are non-zero"); + shift > T::zero() && shift.to_u64().map(|shift| zeros < shift).unwrap_or(true) + } else { + false + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/subtraction.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/subtraction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint/subtraction.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint/subtraction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,300 @@ +use super::CheckedUnsignedAbs::{Negative, Positive}; +use super::Sign::{Minus, NoSign, Plus}; +use super::{BigInt, UnsignedAbs}; + +use crate::{IsizePromotion, UsizePromotion}; + +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::mem; +use core::ops::{Sub, SubAssign}; +use num_traits::CheckedSub; + +// We want to forward to BigUint::sub, but it's not clear how that will go until +// we compare both sign and magnitude. So we duplicate this body for every +// val/ref combination, deferring that decision to BigUint's own forwarding. +macro_rules! bigint_sub { + ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { + match ($a.sign, $b.sign) { + (_, NoSign) => $a_owned, + (NoSign, _) => -$b_owned, + // opposite signs => keep the sign of the left with the sum of magnitudes + (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data), + // same sign => keep or toggle the sign of the left with the difference of magnitudes + (Plus, Plus) | (Minus, Minus) => match $a.data.cmp(&$b.data) { + Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), + Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), + Equal => BigInt::ZERO, + }, + } + }; +} + +impl Sub<&BigInt> for &BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: &BigInt) -> BigInt { + bigint_sub!( + self, + self.clone(), + &self.data, + other, + other.clone(), + &other.data + ) + } +} + +impl Sub for &BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + bigint_sub!(self, self.clone(), &self.data, other, other, other.data) + } +} + +impl Sub<&BigInt> for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: &BigInt) -> BigInt { + bigint_sub!(self, self, self.data, other, other.clone(), &other.data) + } +} + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + bigint_sub!(self, self, self.data, other, other, other.data) + } +} + +impl SubAssign<&BigInt> for BigInt { + #[inline] + fn sub_assign(&mut self, other: &BigInt) { + let n = mem::replace(self, Self::ZERO); + *self = n - other; + } +} +forward_val_assign!(impl SubAssign for BigInt, sub_assign); + +promote_all_scalars!(impl Sub for BigInt, sub); +promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: u32) -> BigInt { + match self.sign { + NoSign => -BigInt::from(other), + Minus => -BigInt::from(self.data + other), + Plus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Greater => BigInt::from(self.data - other), + Less => -BigInt::from(other - self.data), + }, + } + } +} +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: u32) { + let n = mem::replace(self, Self::ZERO); + *self = n - other; + } +} + +impl Sub for u32 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + -(other - self) + } +} + +impl Sub for u64 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + -(other - self) + } +} + +impl Sub for u128 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + -(other - self) + } +} + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: u64) -> BigInt { + match self.sign { + NoSign => -BigInt::from(other), + Minus => -BigInt::from(self.data + other), + Plus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Greater => BigInt::from(self.data - other), + Less => -BigInt::from(other - self.data), + }, + } + } +} + +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: u64) { + let n = mem::replace(self, Self::ZERO); + *self = n - other; + } +} + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: u128) -> BigInt { + match self.sign { + NoSign => -BigInt::from(other), + Minus => -BigInt::from(self.data + other), + Plus => match self.data.cmp(&From::from(other)) { + Equal => Self::ZERO, + Greater => BigInt::from(self.data - other), + Less => -BigInt::from(other - self.data), + }, + } + } +} + +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: u128) { + let n = mem::replace(self, Self::ZERO); + *self = n - other; + } +} + +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: i32) -> BigInt { + match other.checked_uabs() { + Positive(u) => self - u, + Negative(u) => self + u, + } + } +} +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: i32) { + match other.checked_uabs() { + Positive(u) => *self -= u, + Negative(u) => *self += u, + } + } +} + +impl Sub for i32 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u - other, + Negative(u) => -other - u, + } + } +} + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: i64) -> BigInt { + match other.checked_uabs() { + Positive(u) => self - u, + Negative(u) => self + u, + } + } +} +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: i64) { + match other.checked_uabs() { + Positive(u) => *self -= u, + Negative(u) => *self += u, + } + } +} + +impl Sub for i64 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u - other, + Negative(u) => -other - u, + } + } +} + +impl Sub for BigInt { + type Output = BigInt; + + #[inline] + fn sub(self, other: i128) -> BigInt { + match other.checked_uabs() { + Positive(u) => self - u, + Negative(u) => self + u, + } + } +} + +impl SubAssign for BigInt { + #[inline] + fn sub_assign(&mut self, other: i128) { + match other.checked_uabs() { + Positive(u) => *self -= u, + Negative(u) => *self += u, + } + } +} + +impl Sub for i128 { + type Output = BigInt; + + #[inline] + fn sub(self, other: BigInt) -> BigInt { + match self.checked_uabs() { + Positive(u) => u - other, + Negative(u) => -other - u, + } + } +} + +impl CheckedSub for BigInt { + #[inline] + fn checked_sub(&self, v: &BigInt) -> Option { + Some(self.sub(v)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1229 @@ +// `Add`/`Sub` ops may flip from `BigInt` to its `BigUint` magnitude +#![allow(clippy::suspicious_arithmetic_impl)] + +use alloc::string::String; +use alloc::vec::Vec; +use core::cmp::Ordering::{self, Equal}; +use core::default::Default; +use core::fmt; +use core::hash; +use core::ops::{Neg, Not}; +use core::str; + +use num_integer::{Integer, Roots}; +use num_traits::{ConstZero, Num, One, Pow, Signed, Zero}; + +use self::Sign::{Minus, NoSign, Plus}; + +use crate::big_digit::BigDigit; +use crate::biguint::to_str_radix_reversed; +use crate::biguint::{BigUint, IntDigits, U32Digits, U64Digits}; + +mod addition; +mod division; +mod multiplication; +mod subtraction; + +mod arbitrary; +mod bits; +mod convert; +mod power; +mod serde; +mod shift; + +/// A `Sign` is a [`BigInt`]'s composing element. +#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] +pub enum Sign { + Minus, + NoSign, + Plus, +} + +impl Neg for Sign { + type Output = Sign; + + /// Negate `Sign` value. + #[inline] + fn neg(self) -> Sign { + match self { + Minus => Plus, + NoSign => NoSign, + Plus => Minus, + } + } +} + +/// A big signed integer type. +pub struct BigInt { + sign: Sign, + data: BigUint, +} + +// Note: derived `Clone` doesn't specialize `clone_from`, +// but we want to keep the allocation in `data`. +impl Clone for BigInt { + #[inline] + fn clone(&self) -> Self { + BigInt { + sign: self.sign, + data: self.data.clone(), + } + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.sign = other.sign; + self.data.clone_from(&other.data); + } +} + +impl hash::Hash for BigInt { + #[inline] + fn hash(&self, state: &mut H) { + debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); + self.sign.hash(state); + if self.sign != NoSign { + self.data.hash(state); + } + } +} + +impl PartialEq for BigInt { + #[inline] + fn eq(&self, other: &BigInt) -> bool { + debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); + debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); + self.sign == other.sign && (self.sign == NoSign || self.data == other.data) + } +} + +impl Eq for BigInt {} + +impl PartialOrd for BigInt { + #[inline] + fn partial_cmp(&self, other: &BigInt) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for BigInt { + #[inline] + fn cmp(&self, other: &BigInt) -> Ordering { + debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); + debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); + let scmp = self.sign.cmp(&other.sign); + if scmp != Equal { + return scmp; + } + + match self.sign { + NoSign => Equal, + Plus => self.data.cmp(&other.data), + Minus => other.data.cmp(&self.data), + } + } +} + +impl Default for BigInt { + #[inline] + fn default() -> BigInt { + Self::ZERO + } +} + +impl fmt::Debug for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) + } +} + +impl fmt::Binary for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(!self.is_negative(), "0b", &self.data.to_str_radix(2)) + } +} + +impl fmt::Octal for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(!self.is_negative(), "0o", &self.data.to_str_radix(8)) + } +} + +impl fmt::LowerHex for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16)) + } +} + +impl fmt::UpperHex for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s = self.data.to_str_radix(16); + s.make_ascii_uppercase(); + f.pad_integral(!self.is_negative(), "0x", &s) + } +} + +// !-2 = !...f fe = ...0 01 = +1 +// !-1 = !...f ff = ...0 00 = 0 +// ! 0 = !...0 00 = ...f ff = -1 +// !+1 = !...0 01 = ...f fe = -2 +impl Not for BigInt { + type Output = BigInt; + + fn not(mut self) -> BigInt { + match self.sign { + NoSign | Plus => { + self.data += 1u32; + self.sign = Minus; + } + Minus => { + self.data -= 1u32; + self.sign = if self.data.is_zero() { NoSign } else { Plus }; + } + } + self + } +} + +impl Not for &BigInt { + type Output = BigInt; + + fn not(self) -> BigInt { + match self.sign { + NoSign => -BigInt::one(), + Plus => -BigInt::from(&self.data + 1u32), + Minus => BigInt::from(&self.data - 1u32), + } + } +} + +impl Zero for BigInt { + #[inline] + fn zero() -> BigInt { + Self::ZERO + } + + #[inline] + fn set_zero(&mut self) { + self.data.set_zero(); + self.sign = NoSign; + } + + #[inline] + fn is_zero(&self) -> bool { + self.sign == NoSign + } +} + +impl ConstZero for BigInt { + // forward to the inherent const + const ZERO: Self = Self::ZERO; +} + +impl One for BigInt { + #[inline] + fn one() -> BigInt { + BigInt { + sign: Plus, + data: BigUint::one(), + } + } + + #[inline] + fn set_one(&mut self) { + self.data.set_one(); + self.sign = Plus; + } + + #[inline] + fn is_one(&self) -> bool { + self.sign == Plus && self.data.is_one() + } +} + +impl Signed for BigInt { + #[inline] + fn abs(&self) -> BigInt { + match self.sign { + Plus | NoSign => self.clone(), + Minus => BigInt::from(self.data.clone()), + } + } + + #[inline] + fn abs_sub(&self, other: &BigInt) -> BigInt { + if *self <= *other { + Self::ZERO + } else { + self - other + } + } + + #[inline] + fn signum(&self) -> BigInt { + match self.sign { + Plus => BigInt::one(), + Minus => -BigInt::one(), + NoSign => Self::ZERO, + } + } + + #[inline] + fn is_positive(&self) -> bool { + self.sign == Plus + } + + #[inline] + fn is_negative(&self) -> bool { + self.sign == Minus + } +} + +trait UnsignedAbs { + type Unsigned; + + fn checked_uabs(self) -> CheckedUnsignedAbs; +} + +enum CheckedUnsignedAbs { + Positive(T), + Negative(T), +} +use self::CheckedUnsignedAbs::{Negative, Positive}; + +macro_rules! impl_unsigned_abs { + ($Signed:ty, $Unsigned:ty) => { + impl UnsignedAbs for $Signed { + type Unsigned = $Unsigned; + + #[inline] + fn checked_uabs(self) -> CheckedUnsignedAbs { + if self >= 0 { + Positive(self as $Unsigned) + } else { + Negative(self.wrapping_neg() as $Unsigned) + } + } + } + }; +} +impl_unsigned_abs!(i8, u8); +impl_unsigned_abs!(i16, u16); +impl_unsigned_abs!(i32, u32); +impl_unsigned_abs!(i64, u64); +impl_unsigned_abs!(i128, u128); +impl_unsigned_abs!(isize, usize); + +impl Neg for BigInt { + type Output = BigInt; + + #[inline] + fn neg(mut self) -> BigInt { + self.sign = -self.sign; + self + } +} + +impl Neg for &BigInt { + type Output = BigInt; + + #[inline] + fn neg(self) -> BigInt { + -self.clone() + } +} + +impl Integer for BigInt { + #[inline] + fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { + // r.sign == self.sign + let (d_ui, r_ui) = self.data.div_rem(&other.data); + let d = BigInt::from_biguint(self.sign, d_ui); + let r = BigInt::from_biguint(self.sign, r_ui); + if other.is_negative() { + (-d, r) + } else { + (d, r) + } + } + + #[inline] + fn div_floor(&self, other: &BigInt) -> BigInt { + let (d_ui, m) = self.data.div_mod_floor(&other.data); + let d = BigInt::from(d_ui); + match (self.sign, other.sign) { + (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => d, + (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { + if m.is_zero() { + -d + } else { + -d - 1u32 + } + } + (_, NoSign) => unreachable!(), + } + } + + #[inline] + fn mod_floor(&self, other: &BigInt) -> BigInt { + // m.sign == other.sign + let m_ui = self.data.mod_floor(&other.data); + let m = BigInt::from_biguint(other.sign, m_ui); + match (self.sign, other.sign) { + (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => m, + (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { + if m.is_zero() { + m + } else { + other - m + } + } + (_, NoSign) => unreachable!(), + } + } + + fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { + // m.sign == other.sign + let (d_ui, m_ui) = self.data.div_mod_floor(&other.data); + let d = BigInt::from(d_ui); + let m = BigInt::from_biguint(other.sign, m_ui); + match (self.sign, other.sign) { + (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => (d, m), + (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { + if m.is_zero() { + (-d, m) + } else { + (-d - 1u32, other - m) + } + } + (_, NoSign) => unreachable!(), + } + } + + #[inline] + fn div_ceil(&self, other: &Self) -> Self { + let (d_ui, m) = self.data.div_mod_floor(&other.data); + let d = BigInt::from(d_ui); + match (self.sign, other.sign) { + (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => -d, + (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => { + if m.is_zero() { + d + } else { + d + 1u32 + } + } + (_, NoSign) => unreachable!(), + } + } + + /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. + /// + /// The result is always positive. + #[inline] + fn gcd(&self, other: &BigInt) -> BigInt { + BigInt::from(self.data.gcd(&other.data)) + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. + #[inline] + fn lcm(&self, other: &BigInt) -> BigInt { + BigInt::from(self.data.lcm(&other.data)) + } + + /// Calculates the Greatest Common Divisor (GCD) and + /// Lowest Common Multiple (LCM) together. + #[inline] + fn gcd_lcm(&self, other: &BigInt) -> (BigInt, BigInt) { + let (gcd, lcm) = self.data.gcd_lcm(&other.data); + (BigInt::from(gcd), BigInt::from(lcm)) + } + + /// Greatest common divisor, least common multiple, and Bézout coefficients. + #[inline] + fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd, BigInt) { + let egcd = self.extended_gcd(other); + let lcm = if egcd.gcd.is_zero() { + Self::ZERO + } else { + BigInt::from(&self.data / &egcd.gcd.data * &other.data) + }; + (egcd, lcm) + } + + /// Deprecated, use `is_multiple_of` instead. + #[inline] + fn divides(&self, other: &BigInt) -> bool { + self.is_multiple_of(other) + } + + /// Returns `true` if the number is a multiple of `other`. + #[inline] + fn is_multiple_of(&self, other: &BigInt) -> bool { + self.data.is_multiple_of(&other.data) + } + + /// Returns `true` if the number is divisible by `2`. + #[inline] + fn is_even(&self) -> bool { + self.data.is_even() + } + + /// Returns `true` if the number is not divisible by `2`. + #[inline] + fn is_odd(&self) -> bool { + self.data.is_odd() + } + + /// Rounds up to nearest multiple of argument. + #[inline] + fn next_multiple_of(&self, other: &Self) -> Self { + let m = self.mod_floor(other); + if m.is_zero() { + self.clone() + } else { + self + (other - m) + } + } + /// Rounds down to nearest multiple of argument. + #[inline] + fn prev_multiple_of(&self, other: &Self) -> Self { + self - self.mod_floor(other) + } + + fn dec(&mut self) { + *self -= 1u32; + } + + fn inc(&mut self) { + *self += 1u32; + } +} + +impl Roots for BigInt { + fn nth_root(&self, n: u32) -> Self { + assert!( + !(self.is_negative() && n.is_even()), + "root of degree {} is imaginary", + n + ); + + BigInt::from_biguint(self.sign, self.data.nth_root(n)) + } + + fn sqrt(&self) -> Self { + assert!(!self.is_negative(), "square root is imaginary"); + + BigInt::from_biguint(self.sign, self.data.sqrt()) + } + + fn cbrt(&self) -> Self { + BigInt::from_biguint(self.sign, self.data.cbrt()) + } +} + +impl IntDigits for BigInt { + #[inline] + fn digits(&self) -> &[BigDigit] { + self.data.digits() + } + #[inline] + fn digits_mut(&mut self) -> &mut Vec { + self.data.digits_mut() + } + #[inline] + fn normalize(&mut self) { + self.data.normalize(); + if self.data.is_zero() { + self.sign = NoSign; + } + } + #[inline] + fn capacity(&self) -> usize { + self.data.capacity() + } + #[inline] + fn len(&self) -> usize { + self.data.len() + } +} + +/// A generic trait for converting a value to a [`BigInt`]. This may return +/// `None` when converting from `f32` or `f64`, and will always succeed +/// when converting from any integer or unsigned primitive, or [`BigUint`]. +pub trait ToBigInt { + /// Converts the value of `self` to a [`BigInt`]. + fn to_bigint(&self) -> Option; +} + +impl BigInt { + /// A constant `BigInt` with value 0, useful for static initialization. + pub const ZERO: Self = BigInt { + sign: NoSign, + data: BigUint::ZERO, + }; + + /// Creates and initializes a [`BigInt`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn new(sign: Sign, digits: Vec) -> BigInt { + BigInt::from_biguint(sign, BigUint::new(digits)) + } + + /// Creates and initializes a [`BigInt`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { + if sign == NoSign { + data.assign_from_slice(&[]); + } else if data.is_zero() { + sign = NoSign; + } + + BigInt { sign, data } + } + + /// Creates and initializes a [`BigInt`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { + BigInt::from_biguint(sign, BigUint::from_slice(slice)) + } + + /// Reinitializes a [`BigInt`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { + if sign == NoSign { + self.set_zero(); + } else { + self.data.assign_from_slice(slice); + self.sign = if self.data.is_zero() { NoSign } else { sign }; + } + } + + /// Creates and initializes a [`BigInt`]. + /// + /// The bytes are in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"A"), + /// BigInt::parse_bytes(b"65", 10).unwrap()); + /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AA"), + /// BigInt::parse_bytes(b"16705", 10).unwrap()); + /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AB"), + /// BigInt::parse_bytes(b"16706", 10).unwrap()); + /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"Hello world!"), + /// BigInt::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); + /// ``` + #[inline] + pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { + BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes)) + } + + /// Creates and initializes a [`BigInt`]. + /// + /// The bytes are in little-endian byte order. + #[inline] + pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt { + BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes)) + } + + /// Creates and initializes a [`BigInt`] from an array of bytes in + /// two's complement binary representation. + /// + /// The digits are in big-endian base 28. + #[inline] + pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt { + convert::from_signed_bytes_be(digits) + } + + /// Creates and initializes a [`BigInt`] from an array of bytes in two's complement. + /// + /// The digits are in little-endian base 28. + #[inline] + pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt { + convert::from_signed_bytes_le(digits) + } + + /// Creates and initializes a [`BigInt`]. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, ToBigInt}; + /// + /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); + /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); + /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); + /// ``` + #[inline] + pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { + let s = str::from_utf8(buf).ok()?; + BigInt::from_str_radix(s, radix).ok() + } + + /// Creates and initializes a [`BigInt`]. Each `u8` of the input slice is + /// interpreted as one digit of the number + /// and must therefore be less than `radix`. + /// + /// The bytes are in big-endian byte order. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// let inbase190 = vec![15, 33, 125, 12, 14]; + /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); + /// assert_eq!(a.to_radix_be(190), (Sign:: Minus, inbase190)); + /// ``` + pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option { + let u = BigUint::from_radix_be(buf, radix)?; + Some(BigInt::from_biguint(sign, u)) + } + + /// Creates and initializes a [`BigInt`]. Each `u8` of the input slice is + /// interpreted as one digit of the number + /// and must therefore be less than `radix`. + /// + /// The bytes are in little-endian byte order. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// let inbase190 = vec![14, 12, 125, 33, 15]; + /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); + /// assert_eq!(a.to_radix_be(190), (Sign::Minus, inbase190)); + /// ``` + pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option { + let u = BigUint::from_radix_le(buf, radix)?; + Some(BigInt::from_biguint(sign, u)) + } + + /// Returns the sign and the byte representation of the [`BigInt`] in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{ToBigInt, Sign}; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_bytes_be(), (Sign::Minus, vec![4, 101])); + /// ``` + #[inline] + pub fn to_bytes_be(&self) -> (Sign, Vec) { + (self.sign, self.data.to_bytes_be()) + } + + /// Returns the sign and the byte representation of the [`BigInt`] in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{ToBigInt, Sign}; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); + /// ``` + #[inline] + pub fn to_bytes_le(&self) -> (Sign, Vec) { + (self.sign, self.data.to_bytes_le()) + } + + /// Returns the sign and the `u32` digits representation of the [`BigInt`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-1125).to_u32_digits(), (Sign::Minus, vec![1125])); + /// assert_eq!(BigInt::from(4294967295u32).to_u32_digits(), (Sign::Plus, vec![4294967295])); + /// assert_eq!(BigInt::from(4294967296u64).to_u32_digits(), (Sign::Plus, vec![0, 1])); + /// assert_eq!(BigInt::from(-112500000000i64).to_u32_digits(), (Sign::Minus, vec![830850304, 26])); + /// assert_eq!(BigInt::from(112500000000i64).to_u32_digits(), (Sign::Plus, vec![830850304, 26])); + /// ``` + #[inline] + pub fn to_u32_digits(&self) -> (Sign, Vec) { + (self.sign, self.data.to_u32_digits()) + } + + /// Returns the sign and the `u64` digits representation of the [`BigInt`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-1125).to_u64_digits(), (Sign::Minus, vec![1125])); + /// assert_eq!(BigInt::from(4294967295u32).to_u64_digits(), (Sign::Plus, vec![4294967295])); + /// assert_eq!(BigInt::from(4294967296u64).to_u64_digits(), (Sign::Plus, vec![4294967296])); + /// assert_eq!(BigInt::from(-112500000000i64).to_u64_digits(), (Sign::Minus, vec![112500000000])); + /// assert_eq!(BigInt::from(112500000000i64).to_u64_digits(), (Sign::Plus, vec![112500000000])); + /// assert_eq!(BigInt::from(1u128 << 64).to_u64_digits(), (Sign::Plus, vec![0, 1])); + /// ``` + #[inline] + pub fn to_u64_digits(&self) -> (Sign, Vec) { + (self.sign, self.data.to_u64_digits()) + } + + /// Returns an iterator of `u32` digits representation of the [`BigInt`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigInt; + /// + /// assert_eq!(BigInt::from(-1125).iter_u32_digits().collect::>(), vec![1125]); + /// assert_eq!(BigInt::from(4294967295u32).iter_u32_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigInt::from(4294967296u64).iter_u32_digits().collect::>(), vec![0, 1]); + /// assert_eq!(BigInt::from(-112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// assert_eq!(BigInt::from(112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn iter_u32_digits(&self) -> U32Digits<'_> { + self.data.iter_u32_digits() + } + + /// Returns an iterator of `u64` digits representation of the [`BigInt`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigInt; + /// + /// assert_eq!(BigInt::from(-1125).iter_u64_digits().collect::>(), vec![1125u64]); + /// assert_eq!(BigInt::from(4294967295u32).iter_u64_digits().collect::>(), vec![4294967295u64]); + /// assert_eq!(BigInt::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296u64]); + /// assert_eq!(BigInt::from(-112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); + /// assert_eq!(BigInt::from(112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); + /// assert_eq!(BigInt::from(1u128 << 64).iter_u64_digits().collect::>(), vec![0, 1]); + /// ``` + #[inline] + pub fn iter_u64_digits(&self) -> U64Digits<'_> { + self.data.iter_u64_digits() + } + + /// Returns the two's-complement byte representation of the [`BigInt`] in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::ToBigInt; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_signed_bytes_be(), vec![251, 155]); + /// ``` + #[inline] + pub fn to_signed_bytes_be(&self) -> Vec { + convert::to_signed_bytes_be(self) + } + + /// Returns the two's-complement byte representation of the [`BigInt`] in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::ToBigInt; + /// + /// let i = -1125.to_bigint().unwrap(); + /// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]); + /// ``` + #[inline] + pub fn to_signed_bytes_le(&self) -> Vec { + convert::to_signed_bytes_le(self) + } + + /// Returns the integer formatted as a string in the given radix. + /// `radix` must be in the range `2...36`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigInt; + /// + /// let i = BigInt::parse_bytes(b"ff", 16).unwrap(); + /// assert_eq!(i.to_str_radix(16), "ff"); + /// ``` + #[inline] + pub fn to_str_radix(&self, radix: u32) -> String { + let mut v = to_str_radix_reversed(&self.data, radix); + + if self.is_negative() { + v.push(b'-'); + } + + v.reverse(); + unsafe { String::from_utf8_unchecked(v) } + } + + /// Returns the integer in the requested base in big-endian digit order. + /// The output is not given in a human readable alphabet but as a zero + /// based `u8` number. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_be(159), + /// (Sign::Minus, vec![2, 94, 27])); + /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 + /// ``` + #[inline] + pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec) { + (self.sign, self.data.to_radix_be(radix)) + } + + /// Returns the integer in the requested base in little-endian digit order. + /// The output is not given in a human readable alphabet but as a zero + /// based `u8` number. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_le(159), + /// (Sign::Minus, vec![27, 94, 2])); + /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) + /// ``` + #[inline] + pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec) { + (self.sign, self.data.to_radix_le(radix)) + } + + /// Returns the sign of the [`BigInt`] as a [`Sign`]. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(1234).sign(), Sign::Plus); + /// assert_eq!(BigInt::from(-4321).sign(), Sign::Minus); + /// assert_eq!(BigInt::ZERO.sign(), Sign::NoSign); + /// ``` + #[inline] + pub fn sign(&self) -> Sign { + self.sign + } + + /// Returns the magnitude of the [`BigInt`] as a [`BigUint`]. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, BigUint}; + /// use num_traits::Zero; + /// + /// assert_eq!(BigInt::from(1234).magnitude(), &BigUint::from(1234u32)); + /// assert_eq!(BigInt::from(-4321).magnitude(), &BigUint::from(4321u32)); + /// assert!(BigInt::ZERO.magnitude().is_zero()); + /// ``` + #[inline] + pub fn magnitude(&self) -> &BigUint { + &self.data + } + + /// Convert this [`BigInt`] into its [`Sign`] and [`BigUint`] magnitude, + /// the reverse of [`BigInt::from_biguint()`]. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, BigUint, Sign}; + /// + /// assert_eq!(BigInt::from(1234).into_parts(), (Sign::Plus, BigUint::from(1234u32))); + /// assert_eq!(BigInt::from(-4321).into_parts(), (Sign::Minus, BigUint::from(4321u32))); + /// assert_eq!(BigInt::ZERO.into_parts(), (Sign::NoSign, BigUint::ZERO)); + /// ``` + #[inline] + pub fn into_parts(self) -> (Sign, BigUint) { + (self.sign, self.data) + } + + /// Determines the fewest bits necessary to express the [`BigInt`], + /// not including the sign. + #[inline] + pub fn bits(&self) -> u64 { + self.data.bits() + } + + /// Converts this [`BigInt`] into a [`BigUint`], if it's not negative. + #[inline] + pub fn to_biguint(&self) -> Option { + match self.sign { + Plus => Some(self.data.clone()), + NoSign => Some(BigUint::ZERO), + Minus => None, + } + } + + #[inline] + pub fn checked_add(&self, v: &BigInt) -> Option { + Some(self + v) + } + + #[inline] + pub fn checked_sub(&self, v: &BigInt) -> Option { + Some(self - v) + } + + #[inline] + pub fn checked_mul(&self, v: &BigInt) -> Option { + Some(self * v) + } + + #[inline] + pub fn checked_div(&self, v: &BigInt) -> Option { + if v.is_zero() { + return None; + } + Some(self / v) + } + + /// Returns `self ^ exponent`. + pub fn pow(&self, exponent: u32) -> Self { + Pow::pow(self, exponent) + } + + /// Returns `(self ^ exponent) mod modulus` + /// + /// Note that this rounds like `mod_floor`, not like the `%` operator, + /// which makes a difference when given a negative `self` or `modulus`. + /// The result will be in the interval `[0, modulus)` for `modulus > 0`, + /// or in the interval `(modulus, 0]` for `modulus < 0` + /// + /// Panics if the exponent is negative or the modulus is zero. + pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { + power::modpow(self, exponent, modulus) + } + + /// Returns the modular multiplicative inverse if it exists, otherwise `None`. + /// + /// This solves for `x` such that `self * x ≡ 1 (mod modulus)`. + /// Note that this rounds like `mod_floor`, not like the `%` operator, + /// which makes a difference when given a negative `self` or `modulus`. + /// The solution will be in the interval `[0, modulus)` for `modulus > 0`, + /// or in the interval `(modulus, 0]` for `modulus < 0`, + /// and it exists if and only if `gcd(self, modulus) == 1`. + /// + /// ``` + /// use num_bigint::BigInt; + /// use num_integer::Integer; + /// use num_traits::{One, Zero}; + /// + /// let m = BigInt::from(383); + /// + /// // Trivial cases + /// assert_eq!(BigInt::zero().modinv(&m), None); + /// assert_eq!(BigInt::one().modinv(&m), Some(BigInt::one())); + /// let neg1 = &m - 1u32; + /// assert_eq!(neg1.modinv(&m), Some(neg1)); + /// + /// // Positive self and modulus + /// let a = BigInt::from(271); + /// let x = a.modinv(&m).unwrap(); + /// assert_eq!(x, BigInt::from(106)); + /// assert_eq!(x.modinv(&m).unwrap(), a); + /// assert_eq!((&a * x).mod_floor(&m), BigInt::one()); + /// + /// // Negative self and positive modulus + /// let b = -&a; + /// let x = b.modinv(&m).unwrap(); + /// assert_eq!(x, BigInt::from(277)); + /// assert_eq!((&b * x).mod_floor(&m), BigInt::one()); + /// + /// // Positive self and negative modulus + /// let n = -&m; + /// let x = a.modinv(&n).unwrap(); + /// assert_eq!(x, BigInt::from(-277)); + /// assert_eq!((&a * x).mod_floor(&n), &n + 1); + /// + /// // Negative self and modulus + /// let x = b.modinv(&n).unwrap(); + /// assert_eq!(x, BigInt::from(-106)); + /// assert_eq!((&b * x).mod_floor(&n), &n + 1); + /// ``` + pub fn modinv(&self, modulus: &Self) -> Option { + let result = self.data.modinv(&modulus.data)?; + // The sign of the result follows the modulus, like `mod_floor`. + let (sign, mag) = match (self.is_negative(), modulus.is_negative()) { + (false, false) => (Plus, result), + (true, false) => (Plus, &modulus.data - result), + (false, true) => (Minus, &modulus.data - result), + (true, true) => (Minus, result), + }; + Some(BigInt::from_biguint(sign, mag)) + } + + /// Returns the truncated principal square root of `self` -- + /// see [`num_integer::Roots::sqrt()`]. + pub fn sqrt(&self) -> Self { + Roots::sqrt(self) + } + + /// Returns the truncated principal cube root of `self` -- + /// see [`num_integer::Roots::cbrt()`]. + pub fn cbrt(&self) -> Self { + Roots::cbrt(self) + } + + /// Returns the truncated principal `n`th root of `self` -- + /// See [`num_integer::Roots::nth_root()`]. + pub fn nth_root(&self, n: u32) -> Self { + Roots::nth_root(self, n) + } + + /// Returns the number of least-significant bits that are zero, + /// or `None` if the entire number is zero. + pub fn trailing_zeros(&self) -> Option { + self.data.trailing_zeros() + } + + /// Returns whether the bit in position `bit` is set, + /// using the two's complement for negative numbers + pub fn bit(&self, bit: u64) -> bool { + if self.is_negative() { + // Let the binary representation of a number be + // ... 0 x 1 0 ... 0 + // Then the two's complement is + // ... 1 !x 1 0 ... 0 + // where !x is obtained from x by flipping each bit + if bit >= u64::from(crate::big_digit::BITS) * self.len() as u64 { + true + } else { + let trailing_zeros = self.data.trailing_zeros().unwrap(); + match Ord::cmp(&bit, &trailing_zeros) { + Ordering::Less => false, + Ordering::Equal => true, + Ordering::Greater => !self.data.bit(bit), + } + } + } else { + self.data.bit(bit) + } + } + + /// Sets or clears the bit in the given position, + /// using the two's complement for negative numbers + /// + /// Note that setting/clearing a bit (for positive/negative numbers, + /// respectively) greater than the current bit length, a reallocation + /// may be needed to store the new digits + pub fn set_bit(&mut self, bit: u64, value: bool) { + match self.sign { + Sign::Plus => self.data.set_bit(bit, value), + Sign::Minus => bits::set_negative_bit(self, bit, value), + Sign::NoSign => { + if value { + self.data.set_bit(bit, true); + self.sign = Sign::Plus; + } else { + // Clearing a bit for zero is a no-op + } + } + } + // The top bit may have been cleared, so normalize + self.normalize(); + } +} + +impl num_traits::FromBytes for BigInt { + type Bytes = [u8]; + + fn from_be_bytes(bytes: &Self::Bytes) -> Self { + Self::from_signed_bytes_be(bytes) + } + + fn from_le_bytes(bytes: &Self::Bytes) -> Self { + Self::from_signed_bytes_le(bytes) + } +} + +impl num_traits::ToBytes for BigInt { + type Bytes = Vec; + + fn to_be_bytes(&self) -> Self::Bytes { + self.to_signed_bytes_be() + } + + fn to_le_bytes(&self) -> Self::Bytes { + self.to_signed_bytes_le() + } +} + +#[test] +fn test_from_biguint() { + fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) { + let inp = BigInt::from_biguint(inp_s, BigUint::from(inp_n)); + let ans = BigInt { + sign: ans_s, + data: BigUint::from(ans_n), + }; + assert_eq!(inp, ans); + } + check(Plus, 1, Plus, 1); + check(Plus, 0, NoSign, 0); + check(Minus, 1, Minus, 1); + check(NoSign, 1, NoSign, 0); +} + +#[test] +fn test_from_slice() { + fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { + let inp = BigInt::from_slice(inp_s, &[inp_n]); + let ans = BigInt { + sign: ans_s, + data: BigUint::from(ans_n), + }; + assert_eq!(inp, ans); + } + check(Plus, 1, Plus, 1); + check(Plus, 0, NoSign, 0); + check(Minus, 1, Minus, 1); + check(NoSign, 1, NoSign, 0); +} + +#[test] +fn test_assign_from_slice() { + fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { + let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]); + inp.assign_from_slice(inp_s, &[inp_n]); + let ans = BigInt { + sign: ans_s, + data: BigUint::from(ans_n), + }; + assert_eq!(inp, ans); + } + check(Plus, 1, Plus, 1); + check(Plus, 0, NoSign, 0); + check(Minus, 1, Minus, 1); + check(NoSign, 1, NoSign, 0); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigrand.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigrand.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/bigrand.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/bigrand.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,285 @@ +//! Randomization of big integers +#![cfg(feature = "rand")] +#![cfg_attr(docsrs, doc(cfg(feature = "rand")))] + +use rand::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; +use rand::prelude::*; + +use crate::BigInt; +use crate::BigUint; +use crate::Sign::*; + +use crate::biguint::biguint_from_vec; + +use num_integer::Integer; +use num_traits::{ToPrimitive, Zero}; + +/// A trait for sampling random big integers. +/// +/// The `rand` feature must be enabled to use this. See crate-level documentation for details. +pub trait RandBigInt { + /// Generate a random [`BigUint`] of the given bit size. + fn gen_biguint(&mut self, bit_size: u64) -> BigUint; + + /// Generate a random [ BigInt`] of the given bit size. + fn gen_bigint(&mut self, bit_size: u64) -> BigInt; + + /// Generate a random [`BigUint`] less than the given bound. Fails + /// when the bound is zero. + fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint; + + /// Generate a random [`BigUint`] within the given range. The lower + /// bound is inclusive; the upper bound is exclusive. Fails when + /// the upper bound is not greater than the lower bound. + fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint; + + /// Generate a random [`BigInt`] within the given range. The lower + /// bound is inclusive; the upper bound is exclusive. Fails when + /// the upper bound is not greater than the lower bound. + fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; +} + +fn gen_bits(rng: &mut R, data: &mut [u32], rem: u64) { + // `fill` is faster than many `gen::` calls + rng.fill(data); + if rem > 0 { + let last = data.len() - 1; + data[last] >>= 32 - rem; + } +} + +impl RandBigInt for R { + cfg_digit!( + fn gen_biguint(&mut self, bit_size: u64) -> BigUint { + let (digits, rem) = bit_size.div_rem(&32); + let len = (digits + (rem > 0) as u64) + .to_usize() + .expect("capacity overflow"); + let mut data = vec![0u32; len]; + gen_bits(self, &mut data, rem); + biguint_from_vec(data) + } + + fn gen_biguint(&mut self, bit_size: u64) -> BigUint { + use core::slice; + + let (digits, rem) = bit_size.div_rem(&32); + let len = (digits + (rem > 0) as u64) + .to_usize() + .expect("capacity overflow"); + let native_digits = Integer::div_ceil(&bit_size, &64); + let native_len = native_digits.to_usize().expect("capacity overflow"); + let mut data = vec![0u64; native_len]; + unsafe { + // Generate bits in a `&mut [u32]` slice for value stability + let ptr = data.as_mut_ptr() as *mut u32; + debug_assert!(native_len * 2 >= len); + let data = slice::from_raw_parts_mut(ptr, len); + gen_bits(self, data, rem); + } + #[cfg(target_endian = "big")] + for digit in &mut data { + // swap u32 digits into u64 endianness + *digit = (*digit << 32) | (*digit >> 32); + } + biguint_from_vec(data) + } + ); + + fn gen_bigint(&mut self, bit_size: u64) -> BigInt { + loop { + // Generate a random BigUint... + let biguint = self.gen_biguint(bit_size); + // ...and then randomly assign it a Sign... + let sign = if biguint.is_zero() { + // ...except that if the BigUint is zero, we need to try + // again with probability 0.5. This is because otherwise, + // the probability of generating a zero BigInt would be + // double that of any other number. + if self.gen() { + continue; + } else { + NoSign + } + } else if self.gen() { + Plus + } else { + Minus + }; + return BigInt::from_biguint(sign, biguint); + } + } + + fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { + assert!(!bound.is_zero()); + let bits = bound.bits(); + loop { + let n = self.gen_biguint(bits); + if n < *bound { + return n; + } + } + } + + fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint { + assert!(*lbound < *ubound); + if lbound.is_zero() { + self.gen_biguint_below(ubound) + } else { + lbound + self.gen_biguint_below(&(ubound - lbound)) + } + } + + fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt { + assert!(*lbound < *ubound); + if lbound.is_zero() { + BigInt::from(self.gen_biguint_below(ubound.magnitude())) + } else if ubound.is_zero() { + lbound + BigInt::from(self.gen_biguint_below(lbound.magnitude())) + } else { + let delta = ubound - lbound; + lbound + BigInt::from(self.gen_biguint_below(delta.magnitude())) + } + } +} + +/// The back-end implementing rand's [`UniformSampler`] for [`BigUint`]. +#[derive(Clone, Debug)] +pub struct UniformBigUint { + base: BigUint, + len: BigUint, +} + +impl UniformSampler for UniformBigUint { + type X = BigUint; + + #[inline] + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = low_b.borrow(); + let high = high_b.borrow(); + assert!(low < high); + UniformBigUint { + len: high - low, + base: low.clone(), + } + } + + #[inline] + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = low_b.borrow(); + let high = high_b.borrow(); + assert!(low <= high); + Self::new(low, high + 1u32) + } + + #[inline] + fn sample(&self, rng: &mut R) -> Self::X { + &self.base + rng.gen_biguint_below(&self.len) + } + + #[inline] + fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + rng.gen_biguint_range(low.borrow(), high.borrow()) + } +} + +impl SampleUniform for BigUint { + type Sampler = UniformBigUint; +} + +/// The back-end implementing rand's [`UniformSampler`] for [`BigInt`]. +#[derive(Clone, Debug)] +pub struct UniformBigInt { + base: BigInt, + len: BigUint, +} + +impl UniformSampler for UniformBigInt { + type X = BigInt; + + #[inline] + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = low_b.borrow(); + let high = high_b.borrow(); + assert!(low < high); + UniformBigInt { + len: (high - low).into_parts().1, + base: low.clone(), + } + } + + #[inline] + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = low_b.borrow(); + let high = high_b.borrow(); + assert!(low <= high); + Self::new(low, high + 1u32) + } + + #[inline] + fn sample(&self, rng: &mut R) -> Self::X { + &self.base + BigInt::from(rng.gen_biguint_below(&self.len)) + } + + #[inline] + fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + rng.gen_bigint_range(low.borrow(), high.borrow()) + } +} + +impl SampleUniform for BigInt { + type Sampler = UniformBigInt; +} + +/// A random distribution for [`BigUint`] and [`BigInt`] values of a particular bit size. +/// +/// The `rand` feature must be enabled to use this. See crate-level documentation for details. +#[derive(Clone, Copy, Debug)] +pub struct RandomBits { + bits: u64, +} + +impl RandomBits { + #[inline] + pub fn new(bits: u64) -> RandomBits { + RandomBits { bits } + } +} + +impl Distribution for RandomBits { + #[inline] + fn sample(&self, rng: &mut R) -> BigUint { + rng.gen_biguint(self.bits) + } +} + +impl Distribution for RandomBits { + #[inline] + fn sample(&self, rng: &mut R) -> BigInt { + rng.gen_bigint(self.bits) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/addition.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/addition.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/addition.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/addition.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,256 @@ +use super::{BigUint, IntDigits}; + +use crate::big_digit::{self, BigDigit}; +use crate::UsizePromotion; + +use core::iter::Sum; +use core::ops::{Add, AddAssign}; +use num_traits::CheckedAdd; + +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64 as arch; + +#[cfg(target_arch = "x86")] +use core::arch::x86 as arch; + +// Add with carry: +#[cfg(target_arch = "x86_64")] +cfg_64!( + #[inline] + fn adc(carry: u8, a: u64, b: u64, out: &mut u64) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_addcarry_u64`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_addcarry_u64(carry, a, b, out) } + } +); + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +cfg_32!( + #[inline] + fn adc(carry: u8, a: u32, b: u32, out: &mut u32) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_addcarry_u32`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_addcarry_u32(carry, a, b, out) } + } +); + +// fallback for environments where we don't have an addcarry intrinsic +// (copied from the standard library's `carrying_add`) +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +#[inline] +fn adc(carry: u8, lhs: BigDigit, rhs: BigDigit, out: &mut BigDigit) -> u8 { + let (a, b) = lhs.overflowing_add(rhs); + let (c, d) = a.overflowing_add(carry as BigDigit); + *out = c; + u8::from(b || d) +} + +/// Two argument addition of raw slices, `a += b`, returning the carry. +/// +/// This is used when the data `Vec` might need to resize to push a non-zero carry, so we perform +/// the addition first hoping that it will fit. +/// +/// The caller _must_ ensure that `a` is at least as long as `b`. +#[inline] +pub(super) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { + debug_assert!(a.len() >= b.len()); + + let mut carry = 0; + let (a_lo, a_hi) = a.split_at_mut(b.len()); + + for (a, b) in a_lo.iter_mut().zip(b) { + carry = adc(carry, *a, *b, a); + } + + if carry != 0 { + for a in a_hi { + carry = adc(carry, *a, 0, a); + if carry == 0 { + break; + } + } + } + + carry as BigDigit +} + +/// Two argument addition of raw slices: +/// a += b +/// +/// The caller _must_ ensure that a is big enough to store the result - typically this means +/// resizing a to max(a.len(), b.len()) + 1, to fit a possible carry. +pub(super) fn add2(a: &mut [BigDigit], b: &[BigDigit]) { + let carry = __add2(a, b); + + debug_assert!(carry == 0); +} + +forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); +forward_val_assign!(impl AddAssign for BigUint, add_assign); + +impl Add<&BigUint> for BigUint { + type Output = BigUint; + + fn add(mut self, other: &BigUint) -> BigUint { + self += other; + self + } +} +impl AddAssign<&BigUint> for BigUint { + #[inline] + fn add_assign(&mut self, other: &BigUint) { + let self_len = self.data.len(); + let carry = if self_len < other.data.len() { + let lo_carry = __add2(&mut self.data[..], &other.data[..self_len]); + self.data.extend_from_slice(&other.data[self_len..]); + __add2(&mut self.data[self_len..], &[lo_carry]) + } else { + __add2(&mut self.data[..], &other.data[..]) + }; + if carry != 0 { + self.data.push(carry); + } + } +} + +promote_unsigned_scalars!(impl Add for BigUint, add); +promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); + +impl Add for BigUint { + type Output = BigUint; + + #[inline] + fn add(mut self, other: u32) -> BigUint { + self += other; + self + } +} + +impl AddAssign for BigUint { + #[inline] + fn add_assign(&mut self, other: u32) { + if other != 0 { + if self.data.is_empty() { + self.data.push(0); + } + + let carry = __add2(&mut self.data, &[other as BigDigit]); + if carry != 0 { + self.data.push(carry); + } + } + } +} + +impl Add for BigUint { + type Output = BigUint; + + #[inline] + fn add(mut self, other: u64) -> BigUint { + self += other; + self + } +} + +impl AddAssign for BigUint { + cfg_digit!( + #[inline] + fn add_assign(&mut self, other: u64) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + if hi == 0 { + *self += lo; + } else { + while self.data.len() < 2 { + self.data.push(0); + } + + let carry = __add2(&mut self.data, &[lo, hi]); + if carry != 0 { + self.data.push(carry); + } + } + } + + #[inline] + fn add_assign(&mut self, other: u64) { + if other != 0 { + if self.data.is_empty() { + self.data.push(0); + } + + let carry = __add2(&mut self.data, &[other as BigDigit]); + if carry != 0 { + self.data.push(carry); + } + } + } + ); +} + +impl Add for BigUint { + type Output = BigUint; + + #[inline] + fn add(mut self, other: u128) -> BigUint { + self += other; + self + } +} + +impl AddAssign for BigUint { + cfg_digit!( + #[inline] + fn add_assign(&mut self, other: u128) { + if other <= u128::from(u64::MAX) { + *self += other as u64 + } else { + let (a, b, c, d) = super::u32_from_u128(other); + let carry = if a > 0 { + while self.data.len() < 4 { + self.data.push(0); + } + __add2(&mut self.data, &[d, c, b, a]) + } else { + debug_assert!(b > 0); + while self.data.len() < 3 { + self.data.push(0); + } + __add2(&mut self.data, &[d, c, b]) + }; + + if carry != 0 { + self.data.push(carry); + } + } + } + + #[inline] + fn add_assign(&mut self, other: u128) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + if hi == 0 { + *self += lo; + } else { + while self.data.len() < 2 { + self.data.push(0); + } + + let carry = __add2(&mut self.data, &[lo, hi]); + if carry != 0 { + self.data.push(carry); + } + } + } + ); +} + +impl CheckedAdd for BigUint { + #[inline] + fn checked_add(&self, v: &BigUint) -> Option { + Some(self.add(v)) + } +} + +impl_sum_iter_type!(BigUint); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/arbitrary.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/arbitrary.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/arbitrary.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/arbitrary.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +#![cfg(any(feature = "quickcheck", feature = "arbitrary"))] + +use super::{biguint_from_vec, BigUint}; + +use crate::big_digit::BigDigit; +#[cfg(feature = "quickcheck")] +use alloc::boxed::Box; +use alloc::vec::Vec; + +#[cfg(feature = "quickcheck")] +#[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))] +impl quickcheck::Arbitrary for BigUint { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + // Use arbitrary from Vec + biguint_from_vec(Vec::::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + // Use shrinker from Vec + Box::new(self.data.shrink().map(biguint_from_vec)) + } +} + +#[cfg(feature = "arbitrary")] +#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))] +impl arbitrary::Arbitrary<'_> for BigUint { + fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { + Ok(biguint_from_vec(Vec::::arbitrary(u)?)) + } + + fn arbitrary_take_rest(u: arbitrary::Unstructured<'_>) -> arbitrary::Result { + Ok(biguint_from_vec(Vec::::arbitrary_take_rest(u)?)) + } + + fn size_hint(depth: usize) -> (usize, Option) { + Vec::::size_hint(depth) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/bits.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/bits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/bits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/bits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,93 @@ +use super::{BigUint, IntDigits}; + +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; + +forward_val_val_binop!(impl BitAnd for BigUint, bitand); +forward_ref_val_binop!(impl BitAnd for BigUint, bitand); + +// do not use forward_ref_ref_binop_commutative! for bitand so that we can +// clone the smaller value rather than the larger, avoiding over-allocation +impl BitAnd<&BigUint> for &BigUint { + type Output = BigUint; + + #[inline] + fn bitand(self, other: &BigUint) -> BigUint { + // forward to val-ref, choosing the smaller to clone + if self.data.len() <= other.data.len() { + self.clone() & other + } else { + other.clone() & self + } + } +} + +forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign); + +impl BitAnd<&BigUint> for BigUint { + type Output = BigUint; + + #[inline] + fn bitand(mut self, other: &BigUint) -> BigUint { + self &= other; + self + } +} +impl BitAndAssign<&BigUint> for BigUint { + #[inline] + fn bitand_assign(&mut self, other: &BigUint) { + for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { + *ai &= bi; + } + self.data.truncate(other.data.len()); + self.normalize(); + } +} + +forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); +forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign); + +impl BitOr<&BigUint> for BigUint { + type Output = BigUint; + + fn bitor(mut self, other: &BigUint) -> BigUint { + self |= other; + self + } +} +impl BitOrAssign<&BigUint> for BigUint { + #[inline] + fn bitor_assign(&mut self, other: &BigUint) { + for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { + *ai |= bi; + } + if other.data.len() > self.data.len() { + let extra = &other.data[self.data.len()..]; + self.data.extend(extra.iter().cloned()); + } + } +} + +forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); +forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign); + +impl BitXor<&BigUint> for BigUint { + type Output = BigUint; + + fn bitxor(mut self, other: &BigUint) -> BigUint { + self ^= other; + self + } +} +impl BitXorAssign<&BigUint> for BigUint { + #[inline] + fn bitxor_assign(&mut self, other: &BigUint) { + for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { + *ai ^= bi; + } + if other.data.len() > self.data.len() { + let extra = &other.data[self.data.len()..]; + self.data.extend(extra.iter().cloned()); + } + self.normalize(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/convert.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/convert.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/convert.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,866 @@ +// This uses stdlib features higher than the MSRV +#![allow(clippy::manual_range_contains)] // 1.35 + +use super::{biguint_from_vec, BigUint, ToBigUint}; + +use super::addition::add2; +use super::division::{div_rem_digit, FAST_DIV_WIDE}; +use super::multiplication::mac_with_carry; + +use crate::big_digit::{self, BigDigit}; +use crate::ParseBigIntError; +use crate::TryFromBigIntError; + +use alloc::vec::Vec; +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::convert::TryFrom; +use core::mem; +use core::str::FromStr; +use num_integer::{Integer, Roots}; +use num_traits::float::FloatCore; +use num_traits::{FromPrimitive, Num, One, PrimInt, ToPrimitive, Zero}; + +/// Find last set bit +/// fls(0) == 0, fls(u32::MAX) == 32 +fn fls(v: T) -> u8 { + mem::size_of::() as u8 * 8 - v.leading_zeros() as u8 +} + +fn ilog2(v: T) -> u8 { + fls(v) - 1 +} + +impl FromStr for BigUint { + type Err = ParseBigIntError; + + #[inline] + fn from_str(s: &str) -> Result { + BigUint::from_str_radix(s, 10) + } +} + +// Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides +// BigDigit::BITS +pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { + debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); + debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); + + let digits_per_big_digit = big_digit::BITS / bits; + + let data = v + .chunks(digits_per_big_digit.into()) + .map(|chunk| { + chunk + .iter() + .rev() + .fold(0, |acc, &c| (acc << bits) | BigDigit::from(c)) + }) + .collect(); + + biguint_from_vec(data) +} + +// Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide +// BigDigit::BITS +fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { + debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); + debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); + + let total_bits = (v.len() as u64).saturating_mul(bits.into()); + let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into()) + .to_usize() + .unwrap_or(usize::MAX); + let mut data = Vec::with_capacity(big_digits); + + let mut d = 0; + let mut dbits = 0; // number of bits we currently have in d + + // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a + // big_digit: + for &c in v { + d |= BigDigit::from(c) << dbits; + dbits += bits; + + if dbits >= big_digit::BITS { + data.push(d); + dbits -= big_digit::BITS; + // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit + // in d) - grab the bits we lost here: + d = BigDigit::from(c) >> (bits - dbits); + } + } + + if dbits > 0 { + debug_assert!(dbits < big_digit::BITS); + data.push(d as BigDigit); + } + + biguint_from_vec(data) +} + +// Read little-endian radix digits +fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { + debug_assert!(!v.is_empty() && !radix.is_power_of_two()); + debug_assert!(v.iter().all(|&c| u32::from(c) < radix)); + + // Estimate how big the result will be, so we can pre-allocate it. + #[cfg(feature = "std")] + let big_digits = { + let radix_log2 = f64::from(radix).log2(); + let bits = radix_log2 * v.len() as f64; + (bits / big_digit::BITS as f64).ceil() + }; + #[cfg(not(feature = "std"))] + let big_digits = { + let radix_log2 = ilog2(radix.next_power_of_two()) as usize; + let bits = radix_log2 * v.len(); + (bits / big_digit::BITS as usize) + 1 + }; + + let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); + + let (base, power) = get_radix_base(radix); + let radix = radix as BigDigit; + + let r = v.len() % power; + let i = if r == 0 { power } else { r }; + let (head, tail) = v.split_at(i); + + let first = head + .iter() + .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); + data.push(first); + + debug_assert!(tail.len() % power == 0); + for chunk in tail.chunks(power) { + if data.last() != Some(&0) { + data.push(0); + } + + let mut carry = 0; + for d in data.iter_mut() { + *d = mac_with_carry(0, *d, base, &mut carry); + } + debug_assert!(carry == 0); + + let n = chunk + .iter() + .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); + add2(&mut data, &[n]); + } + + biguint_from_vec(data) +} + +pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { + assert!( + 2 <= radix && radix <= 256, + "The radix must be within 2...256" + ); + + if buf.is_empty() { + return Some(BigUint::ZERO); + } + + if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { + return None; + } + + let res = if radix.is_power_of_two() { + // Powers of two can use bitwise masks and shifting instead of multiplication + let bits = ilog2(radix); + let mut v = Vec::from(buf); + v.reverse(); + if big_digit::BITS % bits == 0 { + from_bitwise_digits_le(&v, bits) + } else { + from_inexact_bitwise_digits_le(&v, bits) + } + } else { + from_radix_digits_be(buf, radix) + }; + + Some(res) +} + +pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option { + assert!( + 2 <= radix && radix <= 256, + "The radix must be within 2...256" + ); + + if buf.is_empty() { + return Some(BigUint::ZERO); + } + + if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { + return None; + } + + let res = if radix.is_power_of_two() { + // Powers of two can use bitwise masks and shifting instead of multiplication + let bits = ilog2(radix); + if big_digit::BITS % bits == 0 { + from_bitwise_digits_le(buf, bits) + } else { + from_inexact_bitwise_digits_le(buf, bits) + } + } else { + let mut v = Vec::from(buf); + v.reverse(); + from_radix_digits_be(&v, radix) + }; + + Some(res) +} + +impl Num for BigUint { + type FromStrRadixErr = ParseBigIntError; + + /// Creates and initializes a `BigUint`. + fn from_str_radix(s: &str, radix: u32) -> Result { + assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); + let mut s = s; + if let Some(tail) = s.strip_prefix('+') { + if !tail.starts_with('+') { + s = tail + } + } + + if s.is_empty() { + return Err(ParseBigIntError::empty()); + } + + if s.starts_with('_') { + // Must lead with a real digit! + return Err(ParseBigIntError::invalid()); + } + + // First normalize all characters to plain digit values + let mut v = Vec::with_capacity(s.len()); + for b in s.bytes() { + let d = match b { + b'0'..=b'9' => b - b'0', + b'a'..=b'z' => b - b'a' + 10, + b'A'..=b'Z' => b - b'A' + 10, + b'_' => continue, + _ => u8::MAX, + }; + if d < radix as u8 { + v.push(d); + } else { + return Err(ParseBigIntError::invalid()); + } + } + + let res = if radix.is_power_of_two() { + // Powers of two can use bitwise masks and shifting instead of multiplication + let bits = ilog2(radix); + v.reverse(); + if big_digit::BITS % bits == 0 { + from_bitwise_digits_le(&v, bits) + } else { + from_inexact_bitwise_digits_le(&v, bits) + } + } else { + from_radix_digits_be(&v, radix) + }; + Ok(res) + } +} + +fn high_bits_to_u64(v: &BigUint) -> u64 { + match v.data.len() { + 0 => 0, + 1 => { + // XXX Conversion is useless if already 64-bit. + #[allow(clippy::useless_conversion)] + let v0 = u64::from(v.data[0]); + v0 + } + _ => { + let mut bits = v.bits(); + let mut ret = 0u64; + let mut ret_bits = 0; + + for d in v.data.iter().rev() { + let digit_bits = (bits - 1) % u64::from(big_digit::BITS) + 1; + let bits_want = Ord::min(64 - ret_bits, digit_bits); + + if bits_want != 0 { + if bits_want != 64 { + ret <<= bits_want; + } + // XXX Conversion is useless if already 64-bit. + #[allow(clippy::useless_conversion)] + let d0 = u64::from(*d) >> (digit_bits - bits_want); + ret |= d0; + } + + // Implement round-to-odd: If any lower bits are 1, set LSB to 1 + // so that rounding again to floating point value using + // nearest-ties-to-even is correct. + // + // See: https://en.wikipedia.org/wiki/Rounding#Rounding_to_prepare_for_shorter_precision + + if digit_bits - bits_want != 0 { + // XXX Conversion is useless if already 64-bit. + #[allow(clippy::useless_conversion)] + let masked = u64::from(*d) << (64 - (digit_bits - bits_want) as u32); + ret |= (masked != 0) as u64; + } + + ret_bits += bits_want; + bits -= bits_want; + } + + ret + } + } +} + +impl ToPrimitive for BigUint { + #[inline] + fn to_i64(&self) -> Option { + self.to_u64().as_ref().and_then(u64::to_i64) + } + + #[inline] + fn to_i128(&self) -> Option { + self.to_u128().as_ref().and_then(u128::to_i128) + } + + #[allow(clippy::useless_conversion)] + #[inline] + fn to_u64(&self) -> Option { + let mut ret: u64 = 0; + let mut bits = 0; + + for i in self.data.iter() { + if bits >= 64 { + return None; + } + + // XXX Conversion is useless if already 64-bit. + ret += u64::from(*i) << bits; + bits += big_digit::BITS; + } + + Some(ret) + } + + #[inline] + fn to_u128(&self) -> Option { + let mut ret: u128 = 0; + let mut bits = 0; + + for i in self.data.iter() { + if bits >= 128 { + return None; + } + + ret |= u128::from(*i) << bits; + bits += big_digit::BITS; + } + + Some(ret) + } + + #[inline] + fn to_f32(&self) -> Option { + let mantissa = high_bits_to_u64(self); + let exponent = self.bits() - u64::from(fls(mantissa)); + + if exponent > f32::MAX_EXP as u64 { + Some(f32::INFINITY) + } else { + Some((mantissa as f32) * 2.0f32.powi(exponent as i32)) + } + } + + #[inline] + fn to_f64(&self) -> Option { + let mantissa = high_bits_to_u64(self); + let exponent = self.bits() - u64::from(fls(mantissa)); + + if exponent > f64::MAX_EXP as u64 { + Some(f64::INFINITY) + } else { + Some((mantissa as f64) * 2.0f64.powi(exponent as i32)) + } + } +} + +macro_rules! impl_try_from_biguint { + ($T:ty, $to_ty:path) => { + impl TryFrom<&BigUint> for $T { + type Error = TryFromBigIntError<()>; + + #[inline] + fn try_from(value: &BigUint) -> Result<$T, TryFromBigIntError<()>> { + $to_ty(value).ok_or(TryFromBigIntError::new(())) + } + } + + impl TryFrom for $T { + type Error = TryFromBigIntError; + + #[inline] + fn try_from(value: BigUint) -> Result<$T, TryFromBigIntError> { + <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) + } + } + }; +} + +impl_try_from_biguint!(u8, ToPrimitive::to_u8); +impl_try_from_biguint!(u16, ToPrimitive::to_u16); +impl_try_from_biguint!(u32, ToPrimitive::to_u32); +impl_try_from_biguint!(u64, ToPrimitive::to_u64); +impl_try_from_biguint!(usize, ToPrimitive::to_usize); +impl_try_from_biguint!(u128, ToPrimitive::to_u128); + +impl_try_from_biguint!(i8, ToPrimitive::to_i8); +impl_try_from_biguint!(i16, ToPrimitive::to_i16); +impl_try_from_biguint!(i32, ToPrimitive::to_i32); +impl_try_from_biguint!(i64, ToPrimitive::to_i64); +impl_try_from_biguint!(isize, ToPrimitive::to_isize); +impl_try_from_biguint!(i128, ToPrimitive::to_i128); + +impl FromPrimitive for BigUint { + #[inline] + fn from_i64(n: i64) -> Option { + if n >= 0 { + Some(BigUint::from(n as u64)) + } else { + None + } + } + + #[inline] + fn from_i128(n: i128) -> Option { + if n >= 0 { + Some(BigUint::from(n as u128)) + } else { + None + } + } + + #[inline] + fn from_u64(n: u64) -> Option { + Some(BigUint::from(n)) + } + + #[inline] + fn from_u128(n: u128) -> Option { + Some(BigUint::from(n)) + } + + #[inline] + fn from_f64(mut n: f64) -> Option { + // handle NAN, INFINITY, NEG_INFINITY + if !n.is_finite() { + return None; + } + + // match the rounding of casting from float to int + n = n.trunc(); + + // handle 0.x, -0.x + if n.is_zero() { + return Some(Self::ZERO); + } + + let (mantissa, exponent, sign) = FloatCore::integer_decode(n); + + if sign == -1 { + return None; + } + + let mut ret = BigUint::from(mantissa); + match exponent.cmp(&0) { + Greater => ret <<= exponent as usize, + Equal => {} + Less => ret >>= (-exponent) as usize, + } + Some(ret) + } +} + +impl From for BigUint { + #[inline] + fn from(mut n: u64) -> Self { + let mut ret: BigUint = Self::ZERO; + + while n != 0 { + ret.data.push(n as BigDigit); + // don't overflow if BITS is 64: + n = (n >> 1) >> (big_digit::BITS - 1); + } + + ret + } +} + +impl From for BigUint { + #[inline] + fn from(mut n: u128) -> Self { + let mut ret: BigUint = Self::ZERO; + + while n != 0 { + ret.data.push(n as BigDigit); + n >>= big_digit::BITS; + } + + ret + } +} + +macro_rules! impl_biguint_from_uint { + ($T:ty) => { + impl From<$T> for BigUint { + #[inline] + fn from(n: $T) -> Self { + BigUint::from(n as u64) + } + } + }; +} + +impl_biguint_from_uint!(u8); +impl_biguint_from_uint!(u16); +impl_biguint_from_uint!(u32); +impl_biguint_from_uint!(usize); + +macro_rules! impl_biguint_try_from_int { + ($T:ty, $from_ty:path) => { + impl TryFrom<$T> for BigUint { + type Error = TryFromBigIntError<()>; + + #[inline] + fn try_from(value: $T) -> Result> { + $from_ty(value).ok_or(TryFromBigIntError::new(())) + } + } + }; +} + +impl_biguint_try_from_int!(i8, FromPrimitive::from_i8); +impl_biguint_try_from_int!(i16, FromPrimitive::from_i16); +impl_biguint_try_from_int!(i32, FromPrimitive::from_i32); +impl_biguint_try_from_int!(i64, FromPrimitive::from_i64); +impl_biguint_try_from_int!(isize, FromPrimitive::from_isize); +impl_biguint_try_from_int!(i128, FromPrimitive::from_i128); + +impl ToBigUint for BigUint { + #[inline] + fn to_biguint(&self) -> Option { + Some(self.clone()) + } +} + +macro_rules! impl_to_biguint { + ($T:ty, $from_ty:path) => { + impl ToBigUint for $T { + #[inline] + fn to_biguint(&self) -> Option { + $from_ty(*self) + } + } + }; +} + +impl_to_biguint!(isize, FromPrimitive::from_isize); +impl_to_biguint!(i8, FromPrimitive::from_i8); +impl_to_biguint!(i16, FromPrimitive::from_i16); +impl_to_biguint!(i32, FromPrimitive::from_i32); +impl_to_biguint!(i64, FromPrimitive::from_i64); +impl_to_biguint!(i128, FromPrimitive::from_i128); + +impl_to_biguint!(usize, FromPrimitive::from_usize); +impl_to_biguint!(u8, FromPrimitive::from_u8); +impl_to_biguint!(u16, FromPrimitive::from_u16); +impl_to_biguint!(u32, FromPrimitive::from_u32); +impl_to_biguint!(u64, FromPrimitive::from_u64); +impl_to_biguint!(u128, FromPrimitive::from_u128); + +impl_to_biguint!(f32, FromPrimitive::from_f32); +impl_to_biguint!(f64, FromPrimitive::from_f64); + +impl From for BigUint { + fn from(x: bool) -> Self { + if x { + One::one() + } else { + Self::ZERO + } + } +} + +// Extract bitwise digits that evenly divide BigDigit +pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { + debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); + + let last_i = u.data.len() - 1; + let mask: BigDigit = (1 << bits) - 1; + let digits_per_big_digit = big_digit::BITS / bits; + let digits = Integer::div_ceil(&u.bits(), &u64::from(bits)) + .to_usize() + .unwrap_or(usize::MAX); + let mut res = Vec::with_capacity(digits); + + for mut r in u.data[..last_i].iter().cloned() { + for _ in 0..digits_per_big_digit { + res.push((r & mask) as u8); + r >>= bits; + } + } + + let mut r = u.data[last_i]; + while r != 0 { + res.push((r & mask) as u8); + r >>= bits; + } + + res +} + +// Extract bitwise digits that don't evenly divide BigDigit +fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { + debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); + + let mask: BigDigit = (1 << bits) - 1; + let digits = Integer::div_ceil(&u.bits(), &u64::from(bits)) + .to_usize() + .unwrap_or(usize::MAX); + let mut res = Vec::with_capacity(digits); + + let mut r = 0; + let mut rbits = 0; + + for c in &u.data { + r |= *c << rbits; + rbits += big_digit::BITS; + + while rbits >= bits { + res.push((r & mask) as u8); + r >>= bits; + + // r had more bits than it could fit - grab the bits we lost + if rbits > big_digit::BITS { + r = *c >> (big_digit::BITS - (rbits - bits)); + } + + rbits -= bits; + } + } + + if rbits != 0 { + res.push(r as u8); + } + + while let Some(&0) = res.last() { + res.pop(); + } + + res +} + +// Extract little-endian radix digits +#[inline(always)] // forced inline to get const-prop for radix=10 +pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { + debug_assert!(!u.is_zero() && !radix.is_power_of_two()); + + #[cfg(feature = "std")] + let radix_digits = { + let radix_log2 = f64::from(radix).log2(); + ((u.bits() as f64) / radix_log2).ceil() + }; + #[cfg(not(feature = "std"))] + let radix_digits = { + let radix_log2 = ilog2(radix) as usize; + ((u.bits() as usize) / radix_log2) + 1 + }; + + // Estimate how big the result will be, so we can pre-allocate it. + let mut res = Vec::with_capacity(radix_digits.to_usize().unwrap_or(0)); + + let mut digits = u.clone(); + + // X86 DIV can quickly divide by a full digit, otherwise we choose a divisor + // that's suitable for `div_half` to avoid slow `DoubleBigDigit` division. + let (base, power) = if FAST_DIV_WIDE { + get_radix_base(radix) + } else { + get_half_radix_base(radix) + }; + let radix = radix as BigDigit; + + // For very large numbers, the O(n²) loop of repeated `div_rem_digit` dominates the + // performance. We can mitigate this by dividing into chunks of a larger base first. + // The threshold for this was chosen by anecdotal performance measurements to + // approximate where this starts to make a noticeable difference. + if digits.data.len() >= 64 { + let mut big_base = BigUint::from(base); + let mut big_power = 1usize; + + // Choose a target base length near √n. + let target_len = digits.data.len().sqrt(); + while big_base.data.len() < target_len { + big_base = &big_base * &big_base; + big_power *= 2; + } + + // This outer loop will run approximately √n times. + while digits > big_base { + // This is still the dominating factor, with n digits divided by √n digits. + let (q, mut big_r) = digits.div_rem(&big_base); + digits = q; + + // This inner loop now has O(√n²)=O(n) behavior altogether. + for _ in 0..big_power { + let (q, mut r) = div_rem_digit(big_r, base); + big_r = q; + for _ in 0..power { + res.push((r % radix) as u8); + r /= radix; + } + } + } + } + + while digits.data.len() > 1 { + let (q, mut r) = div_rem_digit(digits, base); + for _ in 0..power { + res.push((r % radix) as u8); + r /= radix; + } + digits = q; + } + + let mut r = digits.data[0]; + while r != 0 { + res.push((r % radix) as u8); + r /= radix; + } + + res +} + +pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { + if u.is_zero() { + vec![0] + } else if radix.is_power_of_two() { + // Powers of two can use bitwise masks and shifting instead of division + let bits = ilog2(radix); + if big_digit::BITS % bits == 0 { + to_bitwise_digits_le(u, bits) + } else { + to_inexact_bitwise_digits_le(u, bits) + } + } else if radix == 10 { + // 10 is so common that it's worth separating out for const-propagation. + // Optimizers can often turn constant division into a faster multiplication. + to_radix_digits_le(u, 10) + } else { + to_radix_digits_le(u, radix) + } +} + +pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { + assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); + + if u.is_zero() { + return vec![b'0']; + } + + let mut res = to_radix_le(u, radix); + + // Now convert everything to ASCII digits. + for r in &mut res { + debug_assert!(u32::from(*r) < radix); + if *r < 10 { + *r += b'0'; + } else { + *r += b'a' - 10; + } + } + res +} + +/// Returns the greatest power of the radix for the `BigDigit` bit size +#[inline] +fn get_radix_base(radix: u32) -> (BigDigit, usize) { + static BASES: [(BigDigit, usize); 257] = generate_radix_bases(big_digit::MAX); + debug_assert!(!radix.is_power_of_two()); + debug_assert!((3..256).contains(&radix)); + BASES[radix as usize] +} + +/// Returns the greatest power of the radix for half the `BigDigit` bit size +#[inline] +fn get_half_radix_base(radix: u32) -> (BigDigit, usize) { + static BASES: [(BigDigit, usize); 257] = generate_radix_bases(big_digit::HALF); + debug_assert!(!radix.is_power_of_two()); + debug_assert!((3..256).contains(&radix)); + BASES[radix as usize] +} + +/// Generate tables of the greatest power of each radix that is less that the given maximum. These +/// are returned from `get_radix_base` to batch the multiplication/division of radix conversions on +/// full `BigUint` values, operating on primitive integers as much as possible. +/// +/// e.g. BASES_16[3] = (59049, 10) // 3¹⁰ fits in u16, but 3¹¹ is too big +/// BASES_32[3] = (3486784401, 20) +/// BASES_64[3] = (12157665459056928801, 40) +/// +/// Powers of two are not included, just zeroed, as they're implemented with shifts. +const fn generate_radix_bases(max: BigDigit) -> [(BigDigit, usize); 257] { + let mut bases = [(0, 0); 257]; + + let mut radix: BigDigit = 3; + while radix < 256 { + if !radix.is_power_of_two() { + let mut power = 1; + let mut base = radix; + + while let Some(b) = base.checked_mul(radix) { + if b > max { + break; + } + base = b; + power += 1; + } + bases[radix as usize] = (base, power) + } + radix += 1; + } + + bases +} + +#[test] +fn test_radix_bases() { + for radix in 3u32..256 { + if !radix.is_power_of_two() { + let (base, power) = get_radix_base(radix); + let radix = BigDigit::from(radix); + let power = u32::try_from(power).unwrap(); + assert_eq!(base, radix.pow(power)); + assert!(radix.checked_pow(power + 1).is_none()); + } + } +} + +#[test] +fn test_half_radix_bases() { + for radix in 3u32..256 { + if !radix.is_power_of_two() { + let (base, power) = get_half_radix_base(radix); + let radix = BigDigit::from(radix); + let power = u32::try_from(power).unwrap(); + assert_eq!(base, radix.pow(power)); + assert!(radix.pow(power + 1) > big_digit::HALF); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/division.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/division.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/division.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/division.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,704 @@ +use super::addition::__add2; +use super::{cmp_slice, BigUint}; + +use crate::big_digit::{self, BigDigit, DoubleBigDigit}; +use crate::UsizePromotion; + +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::mem; +use core::ops::{Div, DivAssign, Rem, RemAssign}; +use num_integer::Integer; +use num_traits::{CheckedDiv, CheckedEuclid, Euclid, One, ToPrimitive, Zero}; + +pub(super) const FAST_DIV_WIDE: bool = cfg!(any(target_arch = "x86", target_arch = "x86_64")); + +/// Divide a two digit numerator by a one digit divisor, returns quotient and remainder: +/// +/// Note: the caller must ensure that both the quotient and remainder will fit into a single digit. +/// This is _not_ true for an arbitrary numerator/denominator. +/// +/// (This function also matches what the x86 divide instruction does). +#[cfg(any(miri, not(any(target_arch = "x86", target_arch = "x86_64"))))] +#[inline] +fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { + debug_assert!(hi < divisor); + + let lhs = big_digit::to_doublebigdigit(hi, lo); + let rhs = DoubleBigDigit::from(divisor); + ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit) +} + +/// x86 and x86_64 can use a real `div` instruction. +#[cfg(all(not(miri), any(target_arch = "x86", target_arch = "x86_64")))] +#[inline] +fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { + // This debug assertion covers the potential #DE for divisor==0 or a quotient too large for one + // register, otherwise in release mode it will become a target-specific fault like SIGFPE. + // This should never occur with the inputs from our few `div_wide` callers. + debug_assert!(hi < divisor); + + // SAFETY: The `div` instruction only affects registers, reading the explicit operand as the + // divisor, and implicitly reading RDX:RAX or EDX:EAX as the dividend. The result is implicitly + // written back to RAX or EAX for the quotient and RDX or EDX for the remainder. No memory is + // used, and flags are not preserved. + unsafe { + let (div, rem); + + cfg_digit!( + macro_rules! div { + () => { + "div {0:e}" + }; + } + macro_rules! div { + () => { + "div {0:r}" + }; + } + ); + + core::arch::asm!( + div!(), + in(reg) divisor, + inout("dx") hi => rem, + inout("ax") lo => div, + options(pure, nomem, nostack), + ); + + (div, rem) + } +} + +/// For small divisors, we can divide without promoting to `DoubleBigDigit` by +/// using half-size pieces of digit, like long-division. +#[inline] +fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { + use crate::big_digit::{HALF, HALF_BITS}; + + debug_assert!(rem < divisor && divisor <= HALF); + let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor); + let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor); + ((hi << HALF_BITS) | lo, rem) +} + +#[inline] +pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { + if b == 0 { + panic!("attempt to divide by zero") + } + + let mut rem = 0; + + if !FAST_DIV_WIDE && b <= big_digit::HALF { + for d in a.data.iter_mut().rev() { + let (q, r) = div_half(rem, *d, b); + *d = q; + rem = r; + } + } else { + for d in a.data.iter_mut().rev() { + let (q, r) = div_wide(rem, *d, b); + *d = q; + rem = r; + } + } + + (a.normalized(), rem) +} + +#[inline] +fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { + if b == 0 { + panic!("attempt to divide by zero") + } + + let mut rem = 0; + + if !FAST_DIV_WIDE && b <= big_digit::HALF { + for &digit in a.data.iter().rev() { + let (_, r) = div_half(rem, digit, b); + rem = r; + } + } else { + for &digit in a.data.iter().rev() { + let (_, r) = div_wide(rem, digit, b); + rem = r; + } + } + + rem +} + +/// Subtract a multiple. +/// a -= b * c +/// Returns a borrow (if a < b then borrow > 0). +fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> BigDigit { + debug_assert!(a.len() == b.len()); + + // carry is between -big_digit::MAX and 0, so to avoid overflow we store + // offset_carry = carry + big_digit::MAX + let mut offset_carry = big_digit::MAX; + + for (x, y) in a.iter_mut().zip(b) { + // We want to calculate sum = x - y * c + carry. + // sum >= -(big_digit::MAX * big_digit::MAX) - big_digit::MAX + // sum <= big_digit::MAX + // Offsetting sum by (big_digit::MAX << big_digit::BITS) puts it in DoubleBigDigit range. + let offset_sum = big_digit::to_doublebigdigit(big_digit::MAX, *x) + - big_digit::MAX as DoubleBigDigit + + offset_carry as DoubleBigDigit + - *y as DoubleBigDigit * c as DoubleBigDigit; + + let (new_offset_carry, new_x) = big_digit::from_doublebigdigit(offset_sum); + offset_carry = new_offset_carry; + *x = new_x; + } + + // Return the borrow. + big_digit::MAX - offset_carry +} + +fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { + if d.is_zero() { + panic!("attempt to divide by zero") + } + if u.is_zero() { + return (BigUint::ZERO, BigUint::ZERO); + } + + if d.data.len() == 1 { + if d.data == [1] { + return (u, BigUint::ZERO); + } + let (div, rem) = div_rem_digit(u, d.data[0]); + // reuse d + d.data.clear(); + d += rem; + return (div, d); + } + + // Required or the q_len calculation below can underflow: + match u.cmp(&d) { + Less => return (BigUint::ZERO, u), + Equal => { + u.set_one(); + return (u, BigUint::ZERO); + } + Greater => {} // Do nothing + } + + // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D: + // + // First, normalize the arguments so the highest bit in the highest digit of the divisor is + // set: the main loop uses the highest digit of the divisor for generating guesses, so we + // want it to be the largest number we can efficiently divide by. + // + let shift = d.data.last().unwrap().leading_zeros() as usize; + + if shift == 0 { + // no need to clone d + div_rem_core(u, &d.data) + } else { + let (q, r) = div_rem_core(u << shift, &(d << shift).data); + // renormalize the remainder + (q, r >> shift) + } +} + +pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { + if d.is_zero() { + panic!("attempt to divide by zero") + } + if u.is_zero() { + return (BigUint::ZERO, BigUint::ZERO); + } + + if d.data.len() == 1 { + if d.data == [1] { + return (u.clone(), BigUint::ZERO); + } + + let (div, rem) = div_rem_digit(u.clone(), d.data[0]); + return (div, rem.into()); + } + + // Required or the q_len calculation below can underflow: + match u.cmp(d) { + Less => return (BigUint::ZERO, u.clone()), + Equal => return (One::one(), BigUint::ZERO), + Greater => {} // Do nothing + } + + // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D: + // + // First, normalize the arguments so the highest bit in the highest digit of the divisor is + // set: the main loop uses the highest digit of the divisor for generating guesses, so we + // want it to be the largest number we can efficiently divide by. + // + let shift = d.data.last().unwrap().leading_zeros() as usize; + + if shift == 0 { + // no need to clone d + div_rem_core(u.clone(), &d.data) + } else { + let (q, r) = div_rem_core(u << shift, &(d << shift).data); + // renormalize the remainder + (q, r >> shift) + } +} + +/// An implementation of the base division algorithm. +/// Knuth, TAOCP vol 2 section 4.3.1, algorithm D, with an improvement from exercises 19-21. +fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) { + debug_assert!(a.data.len() >= b.len() && b.len() > 1); + debug_assert!(b.last().unwrap().leading_zeros() == 0); + + // The algorithm works by incrementally calculating "guesses", q0, for the next digit of the + // quotient. Once we have any number q0 such that (q0 << j) * b <= a, we can set + // + // q += q0 << j + // a -= (q0 << j) * b + // + // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder. + // + // q0, our guess, is calculated by dividing the last three digits of a by the last two digits of + // b - this will give us a guess that is close to the actual quotient, but is possibly greater. + // It can only be greater by 1 and only in rare cases, with probability at most + // 2^-(big_digit::BITS-1) for random a, see TAOCP 4.3.1 exercise 21. + // + // If the quotient turns out to be too large, we adjust it by 1: + // q -= 1 << j + // a += b << j + + // a0 stores an additional extra most significant digit of the dividend, not stored in a. + let mut a0 = 0; + + // [b1, b0] are the two most significant digits of the divisor. They never change. + let b0 = b[b.len() - 1]; + let b1 = b[b.len() - 2]; + + let q_len = a.data.len() - b.len() + 1; + let mut q = BigUint { + data: vec![0; q_len], + }; + + for j in (0..q_len).rev() { + debug_assert!(a.data.len() == b.len() + j); + + let a1 = *a.data.last().unwrap(); + let a2 = a.data[a.data.len() - 2]; + + // The first q0 estimate is [a1,a0] / b0. It will never be too small, it may be too large + // by at most 2. + let (mut q0, mut r) = if a0 < b0 { + let (q0, r) = div_wide(a0, a1, b0); + (q0, r as DoubleBigDigit) + } else { + debug_assert!(a0 == b0); + // Avoid overflowing q0, we know the quotient fits in BigDigit. + // [a1,a0] = b0 * (1< a0 { + // q0 is too large. We need to add back one multiple of b. + q0 -= 1; + borrow -= __add2(&mut a.data[j..], b); + } + // The top digit of a, stored in a0, has now been zeroed. + debug_assert!(borrow == a0); + + q.data[j] = q0; + + // Pop off the next top digit of a. + a0 = a.data.pop().unwrap(); + } + + a.data.push(a0); + a.normalize(); + + debug_assert_eq!(cmp_slice(&a.data, b), Less); + + (q.normalized(), a) +} + +forward_val_ref_binop!(impl Div for BigUint, div); +forward_ref_val_binop!(impl Div for BigUint, div); +forward_val_assign!(impl DivAssign for BigUint, div_assign); + +impl Div for BigUint { + type Output = BigUint; + + #[inline] + fn div(self, other: BigUint) -> BigUint { + let (q, _) = div_rem(self, other); + q + } +} + +impl Div<&BigUint> for &BigUint { + type Output = BigUint; + + #[inline] + fn div(self, other: &BigUint) -> BigUint { + let (q, _) = self.div_rem(other); + q + } +} +impl DivAssign<&BigUint> for BigUint { + #[inline] + fn div_assign(&mut self, other: &BigUint) { + *self = &*self / other; + } +} + +promote_unsigned_scalars!(impl Div for BigUint, div); +promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign); +forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); +forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); + +impl Div for BigUint { + type Output = BigUint; + + #[inline] + fn div(self, other: u32) -> BigUint { + let (q, _) = div_rem_digit(self, other as BigDigit); + q + } +} +impl DivAssign for BigUint { + #[inline] + fn div_assign(&mut self, other: u32) { + *self = &*self / other; + } +} + +impl Div for u32 { + type Output = BigUint; + + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self as BigDigit / other.data[0]), + _ => BigUint::ZERO, + } + } +} + +impl Div for BigUint { + type Output = BigUint; + + #[inline] + fn div(self, other: u64) -> BigUint { + let (q, _) = div_rem(self, From::from(other)); + q + } +} +impl DivAssign for BigUint { + #[inline] + fn div_assign(&mut self, other: u64) { + // a vec of size 0 does not allocate, so this is fairly cheap + let temp = mem::replace(self, Self::ZERO); + *self = temp / other; + } +} + +impl Div for u64 { + type Output = BigUint; + + cfg_digit!( + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / u64::from(other.data[0])), + 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), + _ => BigUint::ZERO, + } + } + + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / other.data[0]), + _ => BigUint::ZERO, + } + } + ); +} + +impl Div for BigUint { + type Output = BigUint; + + #[inline] + fn div(self, other: u128) -> BigUint { + let (q, _) = div_rem(self, From::from(other)); + q + } +} + +impl DivAssign for BigUint { + #[inline] + fn div_assign(&mut self, other: u128) { + *self = &*self / other; + } +} + +impl Div for u128 { + type Output = BigUint; + + cfg_digit!( + #[inline] + fn div(self, other: BigUint) -> BigUint { + use super::u32_to_u128; + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / u128::from(other.data[0])), + 2 => From::from( + self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])), + ), + 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])), + 4 => From::from( + self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), + ), + _ => BigUint::ZERO, + } + } + + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / other.data[0] as u128), + 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), + _ => BigUint::ZERO, + } + } + ); +} + +forward_val_ref_binop!(impl Rem for BigUint, rem); +forward_ref_val_binop!(impl Rem for BigUint, rem); +forward_val_assign!(impl RemAssign for BigUint, rem_assign); + +impl Rem for BigUint { + type Output = BigUint; + + #[inline] + fn rem(self, other: BigUint) -> BigUint { + if let Some(other) = other.to_u32() { + &self % other + } else { + let (_, r) = div_rem(self, other); + r + } + } +} + +impl Rem<&BigUint> for &BigUint { + type Output = BigUint; + + #[inline] + fn rem(self, other: &BigUint) -> BigUint { + if let Some(other) = other.to_u32() { + self % other + } else { + let (_, r) = self.div_rem(other); + r + } + } +} +impl RemAssign<&BigUint> for BigUint { + #[inline] + fn rem_assign(&mut self, other: &BigUint) { + *self = &*self % other; + } +} + +promote_unsigned_scalars!(impl Rem for BigUint, rem); +promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign); +forward_all_scalar_binop_to_ref_val!(impl Rem for BigUint, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); +forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); + +impl Rem for &BigUint { + type Output = BigUint; + + #[inline] + fn rem(self, other: u32) -> BigUint { + rem_digit(self, other as BigDigit).into() + } +} +impl RemAssign for BigUint { + #[inline] + fn rem_assign(&mut self, other: u32) { + *self = &*self % other; + } +} + +impl Rem<&BigUint> for u32 { + type Output = BigUint; + + #[inline] + fn rem(mut self, other: &BigUint) -> BigUint { + self %= other; + From::from(self) + } +} + +macro_rules! impl_rem_assign_scalar { + ($scalar:ty, $to_scalar:ident) => { + forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); + impl RemAssign<&BigUint> for $scalar { + #[inline] + fn rem_assign(&mut self, other: &BigUint) { + *self = match other.$to_scalar() { + None => *self, + Some(0) => panic!("attempt to divide by zero"), + Some(v) => *self % v + }; + } + } + } +} + +// we can scalar %= BigUint for any scalar, including signed types +impl_rem_assign_scalar!(u128, to_u128); +impl_rem_assign_scalar!(usize, to_usize); +impl_rem_assign_scalar!(u64, to_u64); +impl_rem_assign_scalar!(u32, to_u32); +impl_rem_assign_scalar!(u16, to_u16); +impl_rem_assign_scalar!(u8, to_u8); +impl_rem_assign_scalar!(i128, to_i128); +impl_rem_assign_scalar!(isize, to_isize); +impl_rem_assign_scalar!(i64, to_i64); +impl_rem_assign_scalar!(i32, to_i32); +impl_rem_assign_scalar!(i16, to_i16); +impl_rem_assign_scalar!(i8, to_i8); + +impl Rem for BigUint { + type Output = BigUint; + + #[inline] + fn rem(self, other: u64) -> BigUint { + let (_, r) = div_rem(self, From::from(other)); + r + } +} +impl RemAssign for BigUint { + #[inline] + fn rem_assign(&mut self, other: u64) { + *self = &*self % other; + } +} + +impl Rem for u64 { + type Output = BigUint; + + #[inline] + fn rem(mut self, other: BigUint) -> BigUint { + self %= other; + From::from(self) + } +} + +impl Rem for BigUint { + type Output = BigUint; + + #[inline] + fn rem(self, other: u128) -> BigUint { + let (_, r) = div_rem(self, From::from(other)); + r + } +} + +impl RemAssign for BigUint { + #[inline] + fn rem_assign(&mut self, other: u128) { + *self = &*self % other; + } +} + +impl Rem for u128 { + type Output = BigUint; + + #[inline] + fn rem(mut self, other: BigUint) -> BigUint { + self %= other; + From::from(self) + } +} + +impl CheckedDiv for BigUint { + #[inline] + fn checked_div(&self, v: &BigUint) -> Option { + if v.is_zero() { + return None; + } + Some(self.div(v)) + } +} + +impl CheckedEuclid for BigUint { + #[inline] + fn checked_div_euclid(&self, v: &BigUint) -> Option { + if v.is_zero() { + return None; + } + Some(self.div_euclid(v)) + } + + #[inline] + fn checked_rem_euclid(&self, v: &BigUint) -> Option { + if v.is_zero() { + return None; + } + Some(self.rem_euclid(v)) + } + + fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { + Some(self.div_rem_euclid(v)) + } +} + +impl Euclid for BigUint { + #[inline] + fn div_euclid(&self, v: &BigUint) -> BigUint { + // trivially same as regular division + self / v + } + + #[inline] + fn rem_euclid(&self, v: &BigUint) -> BigUint { + // trivially same as regular remainder + self % v + } + + fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { + // trivially same as regular division and remainder + self.div_rem(v) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/iter.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/iter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/iter.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/iter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,361 @@ +use core::iter::FusedIterator; + +cfg_digit!( + /// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U32Digits<'a> { + it: core::slice::Iter<'a, u32>, + } + + /// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U32Digits<'a> { + data: &'a [u64], + next_is_lo: bool, + last_hi_is_zero: bool, + } +); + +cfg_digit!( + const _: () = { + impl<'a> U32Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u32]) -> Self { + Self { it: data.iter() } + } + } + + impl Iterator for U32Digits<'_> { + type Item = u32; + #[inline] + fn next(&mut self) -> Option { + self.it.next().cloned() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).cloned() + } + + #[inline] + fn last(self) -> Option { + self.it.last().cloned() + } + + #[inline] + fn count(self) -> usize { + self.it.count() + } + } + + impl DoubleEndedIterator for U32Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } + } + + impl ExactSizeIterator for U32Digits<'_> { + #[inline] + fn len(&self) -> usize { + self.it.len() + } + } + }; + + const _: () = { + impl<'a> U32Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u64]) -> Self { + let last_hi_is_zero = data + .last() + .map(|&last| { + let last_hi = (last >> 32) as u32; + last_hi == 0 + }) + .unwrap_or(false); + U32Digits { + data, + next_is_lo: true, + last_hi_is_zero, + } + } + } + + impl Iterator for U32Digits<'_> { + type Item = u32; + #[inline] + fn next(&mut self) -> Option { + match self.data.split_first() { + Some((&first, data)) => { + let next_is_lo = self.next_is_lo; + self.next_is_lo = !next_is_lo; + if next_is_lo { + Some(first as u32) + } else { + self.data = data; + if data.is_empty() && self.last_hi_is_zero { + self.last_hi_is_zero = false; + None + } else { + Some((first >> 32) as u32) + } + } + } + None => None, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn last(self) -> Option { + self.data.last().map(|&last| { + if self.last_hi_is_zero { + last as u32 + } else { + (last >> 32) as u32 + } + }) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + } + + impl DoubleEndedIterator for U32Digits<'_> { + fn next_back(&mut self) -> Option { + match self.data.split_last() { + Some((&last, data)) => { + let last_is_lo = self.last_hi_is_zero; + self.last_hi_is_zero = !last_is_lo; + if last_is_lo { + self.data = data; + if data.is_empty() && !self.next_is_lo { + self.next_is_lo = true; + None + } else { + Some(last as u32) + } + } else { + Some((last >> 32) as u32) + } + } + None => None, + } + } + } + + impl ExactSizeIterator for U32Digits<'_> { + #[inline] + fn len(&self) -> usize { + self.data.len() * 2 + - usize::from(self.last_hi_is_zero) + - usize::from(!self.next_is_lo) + } + } + }; +); + +impl FusedIterator for U32Digits<'_> {} + +cfg_digit!( + /// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U64Digits<'a> { + it: core::slice::Chunks<'a, u32>, + } + + /// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U64Digits<'a> { + it: core::slice::Iter<'a, u64>, + } +); + +cfg_digit!( + const _: () = { + impl<'a> U64Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u32]) -> Self { + U64Digits { it: data.chunks(2) } + } + } + + impl Iterator for U64Digits<'_> { + type Item = u64; + #[inline] + fn next(&mut self) -> Option { + self.it.next().map(super::u32_chunk_to_u64) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn last(self) -> Option { + self.it.last().map(super::u32_chunk_to_u64) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + } + + impl DoubleEndedIterator for U64Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().map(super::u32_chunk_to_u64) + } + } + }; + + const _: () = { + impl<'a> U64Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u64]) -> Self { + Self { it: data.iter() } + } + } + + impl Iterator for U64Digits<'_> { + type Item = u64; + #[inline] + fn next(&mut self) -> Option { + self.it.next().cloned() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).cloned() + } + + #[inline] + fn last(self) -> Option { + self.it.last().cloned() + } + + #[inline] + fn count(self) -> usize { + self.it.count() + } + } + + impl DoubleEndedIterator for U64Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } + } + }; +); + +impl ExactSizeIterator for U64Digits<'_> { + #[inline] + fn len(&self) -> usize { + self.it.len() + } +} + +impl FusedIterator for U64Digits<'_> {} + +#[test] +fn test_iter_u32_digits() { + let n = super::BigUint::from(5u8); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = super::BigUint::from(112500000000u64); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(830850304)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(26)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iter_u64_digits() { + let n = super::BigUint::from(5u8); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = super::BigUint::from(18_446_744_073_709_551_616u128); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iter_u32_digits_be() { + let n = super::BigUint::from(5u8); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = super::BigUint::from(112500000000u64); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(830850304)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(26)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iter_u64_digits_be() { + let n = super::BigUint::from(5u8); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next_back(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = super::BigUint::from(18_446_744_073_709_551_616u128); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next_back(), Some(1)); + assert_eq!(it.len(), 1); + assert_eq!(it.next_back(), Some(0)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/monty.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/monty.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/monty.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/monty.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,226 @@ +use alloc::vec::Vec; +use core::mem; +use core::ops::Shl; +use num_traits::One; + +use crate::big_digit::{self, BigDigit, DoubleBigDigit}; +use crate::biguint::BigUint; + +struct MontyReducer { + n0inv: BigDigit, +} + +// k0 = -m**-1 mod 2**BITS. Algorithm from: Dumas, J.G. "On Newton–Raphson +// Iteration for Multiplicative Inverses Modulo Prime Powers". +fn inv_mod_alt(b: BigDigit) -> BigDigit { + assert_ne!(b & 1, 0); + + let mut k0 = BigDigit::wrapping_sub(2, b); + let mut t = b - 1; + let mut i = 1; + while i < big_digit::BITS { + t = t.wrapping_mul(t); + k0 = k0.wrapping_mul(t + 1); + + i <<= 1; + } + debug_assert_eq!(k0.wrapping_mul(b), 1); + k0.wrapping_neg() +} + +impl MontyReducer { + fn new(n: &BigUint) -> Self { + let n0inv = inv_mod_alt(n.data[0]); + MontyReducer { n0inv } + } +} + +/// Computes z mod m = x * y * 2 ** (-n*_W) mod m +/// assuming k = -1/m mod 2**_W +/// See Gueron, "Efficient Software Implementations of Modular Exponentiation". +/// +/// In the terminology of that paper, this is an "Almost Montgomery Multiplication": +/// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result +/// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m. +#[allow(clippy::many_single_char_names)] +fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> BigUint { + // This code assumes x, y, m are all the same length, n. + // (required by addMulVVW and the for loop). + // It also assumes that x, y are already reduced mod m, + // or else the result will not be properly reduced. + assert!( + x.data.len() == n && y.data.len() == n && m.data.len() == n, + "{:?} {:?} {:?} {}", + x, + y, + m, + n + ); + + let mut z = BigUint::ZERO; + z.data.resize(n * 2, 0); + + let mut c: BigDigit = 0; + for i in 0..n { + let c2 = add_mul_vvw(&mut z.data[i..n + i], &x.data, y.data[i]); + let t = z.data[i].wrapping_mul(k); + let c3 = add_mul_vvw(&mut z.data[i..n + i], &m.data, t); + let cx = c.wrapping_add(c2); + let cy = cx.wrapping_add(c3); + z.data[n + i] = cy; + if cx < c2 || cy < c3 { + c = 1; + } else { + c = 0; + } + } + + if c == 0 { + z.data = z.data[n..].to_vec(); + } else { + { + let (first, second) = z.data.split_at_mut(n); + sub_vv(first, second, &m.data); + } + z.data = z.data[..n].to_vec(); + } + + z +} + +#[inline(always)] +fn add_mul_vvw(z: &mut [BigDigit], x: &[BigDigit], y: BigDigit) -> BigDigit { + let mut c = 0; + for (zi, xi) in z.iter_mut().zip(x.iter()) { + let (z1, z0) = mul_add_www(*xi, y, *zi); + let (c_, zi_) = add_ww(z0, c, 0); + *zi = zi_; + c = c_ + z1; + } + + c +} + +/// The resulting carry c is either 0 or 1. +#[inline(always)] +fn sub_vv(z: &mut [BigDigit], x: &[BigDigit], y: &[BigDigit]) -> BigDigit { + let mut c = 0; + for (i, (xi, yi)) in x.iter().zip(y.iter()).enumerate().take(z.len()) { + let zi = xi.wrapping_sub(*yi).wrapping_sub(c); + z[i] = zi; + // see "Hacker's Delight", section 2-12 (overflow detection) + c = ((yi & !xi) | ((yi | !xi) & zi)) >> (big_digit::BITS - 1) + } + + c +} + +/// z1<<_W + z0 = x+y+c, with c == 0 or 1 +#[inline(always)] +fn add_ww(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) { + let yc = y.wrapping_add(c); + let z0 = x.wrapping_add(yc); + let z1 = if z0 < x || yc < y { 1 } else { 0 }; + + (z1, z0) +} + +/// z1 << _W + z0 = x * y + c +#[inline(always)] +fn mul_add_www(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) { + let z = x as DoubleBigDigit * y as DoubleBigDigit + c as DoubleBigDigit; + ((z >> big_digit::BITS) as BigDigit, z as BigDigit) +} + +/// Calculates x ** y mod m using a fixed, 4-bit window. +#[allow(clippy::many_single_char_names)] +pub(super) fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint { + assert!(m.data[0] & 1 == 1); + let mr = MontyReducer::new(m); + let num_words = m.data.len(); + + let mut x = x.clone(); + + // We want the lengths of x and m to be equal. + // It is OK if x >= m as long as len(x) == len(m). + if x.data.len() > num_words { + x %= m; + // Note: now len(x) <= numWords, not guaranteed ==. + } + if x.data.len() < num_words { + x.data.resize(num_words, 0); + } + + // rr = 2**(2*_W*len(m)) mod m + let mut rr = BigUint::one(); + rr = (rr.shl(2 * num_words as u64 * u64::from(big_digit::BITS))) % m; + if rr.data.len() < num_words { + rr.data.resize(num_words, 0); + } + // one = 1, with equal length to that of m + let mut one = BigUint::one(); + one.data.resize(num_words, 0); + + let n = 4; + // powers[i] contains x^i + let mut powers = Vec::with_capacity(1 << n); + powers.push(montgomery(&one, &rr, m, mr.n0inv, num_words)); + powers.push(montgomery(&x, &rr, m, mr.n0inv, num_words)); + for i in 2..1 << n { + let r = montgomery(&powers[i - 1], &powers[1], m, mr.n0inv, num_words); + powers.push(r); + } + + // initialize z = 1 (Montgomery 1) + let mut z = powers[0].clone(); + z.data.resize(num_words, 0); + let mut zz = BigUint::ZERO; + zz.data.resize(num_words, 0); + + // same windowed exponent, but with Montgomery multiplications + for i in (0..y.data.len()).rev() { + let mut yi = y.data[i]; + let mut j = 0; + while j < big_digit::BITS { + if i != y.data.len() - 1 || j != 0 { + zz = montgomery(&z, &z, m, mr.n0inv, num_words); + z = montgomery(&zz, &zz, m, mr.n0inv, num_words); + zz = montgomery(&z, &z, m, mr.n0inv, num_words); + z = montgomery(&zz, &zz, m, mr.n0inv, num_words); + } + zz = montgomery( + &z, + &powers[(yi >> (big_digit::BITS - n)) as usize], + m, + mr.n0inv, + num_words, + ); + mem::swap(&mut z, &mut zz); + yi <<= n; + j += n; + } + } + + // convert to regular number + zz = montgomery(&z, &one, m, mr.n0inv, num_words); + + zz.normalize(); + // One last reduction, just in case. + // See golang.org/issue/13907. + if zz >= *m { + // Common case is m has high bit set; in that case, + // since zz is the same length as m, there can be just + // one multiple of m to remove. Just subtract. + // We think that the subtract should be sufficient in general, + // so do that unconditionally, but double-check, + // in case our beliefs are wrong. + // The div is not expected to be reached. + zz -= m; + if zz >= *m { + zz %= m; + } + } + + zz.normalize(); + zz +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/multiplication.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/multiplication.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/multiplication.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/multiplication.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,626 @@ +use super::addition::{__add2, add2}; +use super::subtraction::sub2; +use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits}; + +use crate::big_digit::{self, BigDigit, DoubleBigDigit}; +use crate::Sign::{self, Minus, NoSign, Plus}; +use crate::{BigInt, UsizePromotion}; + +use core::cmp::Ordering; +use core::iter::Product; +use core::ops::{Mul, MulAssign}; +use num_traits::{CheckedMul, FromPrimitive, One, Zero}; + +#[inline] +pub(super) fn mac_with_carry( + a: BigDigit, + b: BigDigit, + c: BigDigit, + acc: &mut DoubleBigDigit, +) -> BigDigit { + *acc += DoubleBigDigit::from(a); + *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c); + let lo = *acc as BigDigit; + *acc >>= big_digit::BITS; + lo +} + +#[inline] +fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { + *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b); + let lo = *acc as BigDigit; + *acc >>= big_digit::BITS; + lo +} + +/// Three argument multiply accumulate: +/// acc += b * c +fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { + if c == 0 { + return; + } + + let mut carry = 0; + let (a_lo, a_hi) = acc.split_at_mut(b.len()); + + for (a, &b) in a_lo.iter_mut().zip(b) { + *a = mac_with_carry(*a, b, c, &mut carry); + } + + let (carry_hi, carry_lo) = big_digit::from_doublebigdigit(carry); + + let final_carry = if carry_hi == 0 { + __add2(a_hi, &[carry_lo]) + } else { + __add2(a_hi, &[carry_hi, carry_lo]) + }; + assert_eq!(final_carry, 0, "carry overflow during multiplication!"); +} + +fn bigint_from_slice(slice: &[BigDigit]) -> BigInt { + BigInt::from(biguint_from_vec(slice.to_vec())) +} + +/// Three argument multiply accumulate: +/// acc += b * c +#[allow(clippy::many_single_char_names)] +fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { + // Least-significant zeros have no effect on the output. + if let Some(&0) = b.first() { + if let Some(nz) = b.iter().position(|&d| d != 0) { + b = &b[nz..]; + acc = &mut acc[nz..]; + } else { + return; + } + } + if let Some(&0) = c.first() { + if let Some(nz) = c.iter().position(|&d| d != 0) { + c = &c[nz..]; + acc = &mut acc[nz..]; + } else { + return; + } + } + + let acc = acc; + let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) }; + + // We use four algorithms for different input sizes. + // + // - For small inputs, long multiplication is fastest. + // - If y is at least least twice as long as x, split using Half-Karatsuba. + // - Next we use Karatsuba multiplication (Toom-2), which we have optimized + // to avoid unnecessary allocations for intermediate values. + // - For the largest inputs we use Toom-3, which better optimizes the + // number of operations, but uses more temporary allocations. + // + // The thresholds are somewhat arbitrary, chosen by evaluating the results + // of `cargo bench --bench bigint multiply`. + + if x.len() <= 32 { + // Long multiplication: + for (i, xi) in x.iter().enumerate() { + mac_digit(&mut acc[i..], y, *xi); + } + } else if x.len() * 2 <= y.len() { + // Karatsuba Multiplication for factors with significant length disparity. + // + // The Half-Karatsuba Multiplication Algorithm is a specialized case of + // the normal Karatsuba multiplication algorithm, designed for the scenario + // where y has at least twice as many base digits as x. + // + // In this case y (the longer input) is split into high2 and low2, + // at m2 (half the length of y) and x (the shorter input), + // is used directly without splitting. + // + // The algorithm then proceeds as follows: + // + // 1. Compute the product z0 = x * low2. + // 2. Compute the product temp = x * high2. + // 3. Adjust the weight of temp by adding m2 (* NBASE ^ m2) + // 4. Add temp and z0 to obtain the final result. + // + // Proof: + // + // The algorithm can be derived from the original Karatsuba algorithm by + // simplifying the formula when the shorter factor x is not split into + // high and low parts, as shown below. + // + // Original Karatsuba formula: + // + // result = (z2 * NBASE ^ (m2 × 2)) + ((z1 - z2 - z0) * NBASE ^ m2) + z0 + // + // Substitutions: + // + // low1 = x + // high1 = 0 + // + // Applying substitutions: + // + // z0 = (low1 * low2) + // = (x * low2) + // + // z1 = ((low1 + high1) * (low2 + high2)) + // = ((x + 0) * (low2 + high2)) + // = (x * low2) + (x * high2) + // + // z2 = (high1 * high2) + // = (0 * high2) + // = 0 + // + // Simplified using the above substitutions: + // + // result = (z2 * NBASE ^ (m2 × 2)) + ((z1 - z2 - z0) * NBASE ^ m2) + z0 + // = (0 * NBASE ^ (m2 × 2)) + ((z1 - 0 - z0) * NBASE ^ m2) + z0 + // = ((z1 - z0) * NBASE ^ m2) + z0 + // = ((z1 - z0) * NBASE ^ m2) + z0 + // = (x * high2) * NBASE ^ m2 + z0 + let m2 = y.len() / 2; + let (low2, high2) = y.split_at(m2); + + // (x * high2) * NBASE ^ m2 + z0 + mac3(acc, x, low2); + mac3(&mut acc[m2..], x, high2); + } else if x.len() <= 256 { + // Karatsuba multiplication: + // + // The idea is that we break x and y up into two smaller numbers that each have about half + // as many digits, like so (note that multiplying by b is just a shift): + // + // x = x0 + x1 * b + // y = y0 + y1 * b + // + // With some algebra, we can compute x * y with three smaller products, where the inputs to + // each of the smaller products have only about half as many digits as x and y: + // + // x * y = (x0 + x1 * b) * (y0 + y1 * b) + // + // x * y = x0 * y0 + // + x0 * y1 * b + // + x1 * y0 * b + // + x1 * y1 * b^2 + // + // Let p0 = x0 * y0 and p2 = x1 * y1: + // + // x * y = p0 + // + (x0 * y1 + x1 * y0) * b + // + p2 * b^2 + // + // The real trick is that middle term: + // + // x0 * y1 + x1 * y0 + // + // = x0 * y1 + x1 * y0 - p0 + p0 - p2 + p2 + // + // = x0 * y1 + x1 * y0 - x0 * y0 - x1 * y1 + p0 + p2 + // + // Now we complete the square: + // + // = -(x0 * y0 - x0 * y1 - x1 * y0 + x1 * y1) + p0 + p2 + // + // = -((x1 - x0) * (y1 - y0)) + p0 + p2 + // + // Let p1 = (x1 - x0) * (y1 - y0), and substitute back into our original formula: + // + // x * y = p0 + // + (p0 + p2 - p1) * b + // + p2 * b^2 + // + // Where the three intermediate products are: + // + // p0 = x0 * y0 + // p1 = (x1 - x0) * (y1 - y0) + // p2 = x1 * y1 + // + // In doing the computation, we take great care to avoid unnecessary temporary variables + // (since creating a BigUint requires a heap allocation): thus, we rearrange the formula a + // bit so we can use the same temporary variable for all the intermediate products: + // + // x * y = p2 * b^2 + p2 * b + // + p0 * b + p0 + // - p1 * b + // + // The other trick we use is instead of doing explicit shifts, we slice acc at the + // appropriate offset when doing the add. + + // When x is smaller than y, it's significantly faster to pick b such that x is split in + // half, not y: + let b = x.len() / 2; + let (x0, x1) = x.split_at(b); + let (y0, y1) = y.split_at(b); + + // We reuse the same BigUint for all the intermediate multiplies and have to size p + // appropriately here: x1.len() >= x0.len and y1.len() >= y0.len(): + let len = x1.len() + y1.len() + 1; + let mut p = BigUint { data: vec![0; len] }; + + // p2 = x1 * y1 + mac3(&mut p.data, x1, y1); + + // Not required, but the adds go faster if we drop any unneeded 0s from the end: + p.normalize(); + + add2(&mut acc[b..], &p.data); + add2(&mut acc[b * 2..], &p.data); + + // Zero out p before the next multiply: + p.data.truncate(0); + p.data.resize(len, 0); + + // p0 = x0 * y0 + mac3(&mut p.data, x0, y0); + p.normalize(); + + add2(acc, &p.data); + add2(&mut acc[b..], &p.data); + + // p1 = (x1 - x0) * (y1 - y0) + // We do this one last, since it may be negative and acc can't ever be negative: + let (j0_sign, j0) = sub_sign(x1, x0); + let (j1_sign, j1) = sub_sign(y1, y0); + + match j0_sign * j1_sign { + Plus => { + p.data.truncate(0); + p.data.resize(len, 0); + + mac3(&mut p.data, &j0.data, &j1.data); + p.normalize(); + + sub2(&mut acc[b..], &p.data); + } + Minus => { + mac3(&mut acc[b..], &j0.data, &j1.data); + } + NoSign => (), + } + } else { + // Toom-3 multiplication: + // + // Toom-3 is like Karatsuba above, but dividing the inputs into three parts. + // Both are instances of Toom-Cook, using `k=3` and `k=2` respectively. + // + // The general idea is to treat the large integers digits as + // polynomials of a certain degree and determine the coefficients/digits + // of the product of the two via interpolation of the polynomial product. + let i = y.len() / 3 + 1; + + let x0_len = Ord::min(x.len(), i); + let x1_len = Ord::min(x.len() - x0_len, i); + + let y0_len = i; + let y1_len = Ord::min(y.len() - y0_len, i); + + // Break x and y into three parts, representating an order two polynomial. + // t is chosen to be the size of a digit so we can use faster shifts + // in place of multiplications. + // + // x(t) = x2*t^2 + x1*t + x0 + let x0 = bigint_from_slice(&x[..x0_len]); + let x1 = bigint_from_slice(&x[x0_len..x0_len + x1_len]); + let x2 = bigint_from_slice(&x[x0_len + x1_len..]); + + // y(t) = y2*t^2 + y1*t + y0 + let y0 = bigint_from_slice(&y[..y0_len]); + let y1 = bigint_from_slice(&y[y0_len..y0_len + y1_len]); + let y2 = bigint_from_slice(&y[y0_len + y1_len..]); + + // Let w(t) = x(t) * y(t) + // + // This gives us the following order-4 polynomial. + // + // w(t) = w4*t^4 + w3*t^3 + w2*t^2 + w1*t + w0 + // + // We need to find the coefficients w4, w3, w2, w1 and w0. Instead + // of simply multiplying the x and y in total, we can evaluate w + // at 5 points. An n-degree polynomial is uniquely identified by (n + 1) + // points. + // + // It is arbitrary as to what points we evaluate w at but we use the + // following. + // + // w(t) at t = 0, 1, -1, -2 and inf + // + // The values for w(t) in terms of x(t)*y(t) at these points are: + // + // let a = w(0) = x0 * y0 + // let b = w(1) = (x2 + x1 + x0) * (y2 + y1 + y0) + // let c = w(-1) = (x2 - x1 + x0) * (y2 - y1 + y0) + // let d = w(-2) = (4*x2 - 2*x1 + x0) * (4*y2 - 2*y1 + y0) + // let e = w(inf) = x2 * y2 as t -> inf + + // x0 + x2, avoiding temporaries + let p = &x0 + &x2; + + // y0 + y2, avoiding temporaries + let q = &y0 + &y2; + + // x2 - x1 + x0, avoiding temporaries + let p2 = &p - &x1; + + // y2 - y1 + y0, avoiding temporaries + let q2 = &q - &y1; + + // w(0) + let r0 = &x0 * &y0; + + // w(inf) + let r4 = &x2 * &y2; + + // w(1) + let r1 = (p + x1) * (q + y1); + + // w(-1) + let r2 = &p2 * &q2; + + // w(-2) + let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0); + + // Evaluating these points gives us the following system of linear equations. + // + // 0 0 0 0 1 | a + // 1 1 1 1 1 | b + // 1 -1 1 -1 1 | c + // 16 -8 4 -2 1 | d + // 1 0 0 0 0 | e + // + // The solved equation (after gaussian elimination or similar) + // in terms of its coefficients: + // + // w0 = w(0) + // w1 = w(0)/2 + w(1)/3 - w(-1) + w(-2)/6 - 2*w(inf) + // w2 = -w(0) + w(1)/2 + w(-1)/2 - w(inf) + // w3 = -w(0)/2 + w(1)/6 + w(-1)/2 - w(-2)/6 + 2*w(inf) + // w4 = w(inf) + // + // This particular sequence is given by Bodrato and is an interpolation + // of the above equations. + let mut comp3: BigInt = (r3 - &r1) / 3u32; + let mut comp1: BigInt = (r1 - &r2) >> 1; + let mut comp2: BigInt = r2 - &r0; + comp3 = ((&comp2 - comp3) >> 1) + (&r4 << 1); + comp2 += &comp1 - &r4; + comp1 -= &comp3; + + // Recomposition. The coefficients of the polynomial are now known. + // + // Evaluate at w(t) where t is our given base to get the result. + // + // let bits = u64::from(big_digit::BITS) * i as u64; + // let result = r0 + // + (comp1 << bits) + // + (comp2 << (2 * bits)) + // + (comp3 << (3 * bits)) + // + (r4 << (4 * bits)); + // let result_pos = result.to_biguint().unwrap(); + // add2(&mut acc[..], &result_pos.data); + // + // But with less intermediate copying: + for (j, result) in [&r0, &comp1, &comp2, &comp3, &r4].iter().enumerate().rev() { + match result.sign() { + Plus => add2(&mut acc[i * j..], result.digits()), + Minus => sub2(&mut acc[i * j..], result.digits()), + NoSign => {} + } + } + } +} + +fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { + let len = x.len() + y.len() + 1; + let mut prod = BigUint { data: vec![0; len] }; + + mac3(&mut prod.data, x, y); + prod.normalized() +} + +fn scalar_mul(a: &mut BigUint, b: BigDigit) { + match b { + 0 => a.set_zero(), + 1 => {} + _ => { + if b.is_power_of_two() { + *a <<= b.trailing_zeros(); + } else { + let mut carry = 0; + for a in a.data.iter_mut() { + *a = mul_with_carry(*a, b, &mut carry); + } + if carry != 0 { + a.data.push(carry as BigDigit); + } + } + } + } +} + +fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { + // Normalize: + if let Some(&0) = a.last() { + a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; + } + if let Some(&0) = b.last() { + b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; + } + + match cmp_slice(a, b) { + Ordering::Greater => { + let mut a = a.to_vec(); + sub2(&mut a, b); + (Plus, biguint_from_vec(a)) + } + Ordering::Less => { + let mut b = b.to_vec(); + sub2(&mut b, a); + (Minus, biguint_from_vec(b)) + } + Ordering::Equal => (NoSign, BigUint::ZERO), + } +} + +macro_rules! impl_mul { + ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( + impl Mul<$Other> for $Self { + type Output = BigUint; + + #[inline] + fn mul(self, other: $Other) -> BigUint { + match (&*self.data, &*other.data) { + // multiply by zero + (&[], _) | (_, &[]) => BigUint::ZERO, + // multiply by a scalar + (_, &[digit]) => self * digit, + (&[digit], _) => other * digit, + // full multiplication + (x, y) => mul3(x, y), + } + } + } + )*} +} +impl_mul! { + impl Mul for BigUint; + impl Mul for &BigUint; + impl Mul<&BigUint> for BigUint; + impl Mul<&BigUint> for &BigUint; +} + +macro_rules! impl_mul_assign { + ($(impl MulAssign<$Other:ty> for BigUint;)*) => {$( + impl MulAssign<$Other> for BigUint { + #[inline] + fn mul_assign(&mut self, other: $Other) { + match (&*self.data, &*other.data) { + // multiply by zero + (&[], _) => {}, + (_, &[]) => self.set_zero(), + // multiply by a scalar + (_, &[digit]) => *self *= digit, + (&[digit], _) => *self = other * digit, + // full multiplication + (x, y) => *self = mul3(x, y), + } + } + } + )*} +} +impl_mul_assign! { + impl MulAssign for BigUint; + impl MulAssign<&BigUint> for BigUint; +} + +promote_unsigned_scalars!(impl Mul for BigUint, mul); +promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); + +impl Mul for BigUint { + type Output = BigUint; + + #[inline] + fn mul(mut self, other: u32) -> BigUint { + self *= other; + self + } +} +impl MulAssign for BigUint { + #[inline] + fn mul_assign(&mut self, other: u32) { + scalar_mul(self, other as BigDigit); + } +} + +impl Mul for BigUint { + type Output = BigUint; + + #[inline] + fn mul(mut self, other: u64) -> BigUint { + self *= other; + self + } +} +impl MulAssign for BigUint { + cfg_digit!( + #[inline] + fn mul_assign(&mut self, other: u64) { + if let Some(other) = BigDigit::from_u64(other) { + scalar_mul(self, other); + } else { + let (hi, lo) = big_digit::from_doublebigdigit(other); + *self = mul3(&self.data, &[lo, hi]); + } + } + + #[inline] + fn mul_assign(&mut self, other: u64) { + scalar_mul(self, other); + } + ); +} + +impl Mul for BigUint { + type Output = BigUint; + + #[inline] + fn mul(mut self, other: u128) -> BigUint { + self *= other; + self + } +} + +impl MulAssign for BigUint { + cfg_digit!( + #[inline] + fn mul_assign(&mut self, other: u128) { + if let Some(other) = BigDigit::from_u128(other) { + scalar_mul(self, other); + } else { + *self = match super::u32_from_u128(other) { + (0, 0, c, d) => mul3(&self.data, &[d, c]), + (0, b, c, d) => mul3(&self.data, &[d, c, b]), + (a, b, c, d) => mul3(&self.data, &[d, c, b, a]), + }; + } + } + + #[inline] + fn mul_assign(&mut self, other: u128) { + if let Some(other) = BigDigit::from_u128(other) { + scalar_mul(self, other); + } else { + let (hi, lo) = big_digit::from_doublebigdigit(other); + *self = mul3(&self.data, &[lo, hi]); + } + } + ); +} + +impl CheckedMul for BigUint { + #[inline] + fn checked_mul(&self, v: &BigUint) -> Option { + Some(self.mul(v)) + } +} + +impl_product_iter_type!(BigUint); + +#[test] +fn test_sub_sign() { + use crate::BigInt; + use num_traits::Num; + + fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt { + let (sign, val) = sub_sign(a, b); + BigInt::from_biguint(sign, val) + } + + let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); + let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); + let a_i = BigInt::from(a.clone()); + let b_i = BigInt::from(b.clone()); + + assert_eq!(sub_sign_i(&a.data, &b.data), &a_i - &b_i); + assert_eq!(sub_sign_i(&b.data, &a.data), &b_i - &a_i); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/power.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/power.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/power.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/power.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,258 @@ +use super::monty::monty_modpow; +use super::BigUint; + +use crate::big_digit::{self, BigDigit}; + +use num_integer::Integer; +use num_traits::{One, Pow, ToPrimitive, Zero}; + +impl Pow<&BigUint> for BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: &BigUint) -> BigUint { + if self.is_one() || exp.is_zero() { + BigUint::one() + } else if self.is_zero() { + Self::ZERO + } else if let Some(exp) = exp.to_u64() { + self.pow(exp) + } else if let Some(exp) = exp.to_u128() { + self.pow(exp) + } else { + // At this point, `self >= 2` and `exp >= 2¹²⁸`. The smallest possible result given + // `2.pow(2¹²⁸)` would require far more memory than 64-bit targets can address! + panic!("memory overflow") + } + } +} + +impl Pow for BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: BigUint) -> BigUint { + Pow::pow(self, &exp) + } +} + +impl Pow<&BigUint> for &BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: &BigUint) -> BigUint { + if self.is_one() || exp.is_zero() { + BigUint::one() + } else if self.is_zero() { + BigUint::ZERO + } else { + self.clone().pow(exp) + } + } +} + +impl Pow for &BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: BigUint) -> BigUint { + Pow::pow(self, &exp) + } +} + +macro_rules! pow_impl { + ($T:ty) => { + impl Pow<$T> for BigUint { + type Output = BigUint; + + fn pow(self, mut exp: $T) -> BigUint { + if exp == 0 { + return BigUint::one(); + } + let mut base = self; + + while exp & 1 == 0 { + base = &base * &base; + exp >>= 1; + } + + if exp == 1 { + return base; + } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base = &base * &base; + if exp & 1 == 1 { + acc *= &base; + } + } + acc + } + } + + impl Pow<&$T> for BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: &$T) -> BigUint { + Pow::pow(self, *exp) + } + } + + impl Pow<$T> for &BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: $T) -> BigUint { + if exp == 0 { + return BigUint::one(); + } + Pow::pow(self.clone(), exp) + } + } + + impl Pow<&$T> for &BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: &$T) -> BigUint { + Pow::pow(self, *exp) + } + } + }; +} + +pow_impl!(u8); +pow_impl!(u16); +pow_impl!(u32); +pow_impl!(u64); +pow_impl!(usize); +pow_impl!(u128); + +pub(super) fn modpow(x: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint { + assert!( + !modulus.is_zero(), + "attempt to calculate with zero modulus!" + ); + + if modulus.is_odd() { + // For an odd modulus, we can use Montgomery multiplication in base 2^32. + monty_modpow(x, exponent, modulus) + } else { + // Otherwise do basically the same as `num::pow`, but with a modulus. + plain_modpow(x, &exponent.data, modulus) + } +} + +fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> BigUint { + assert!( + !modulus.is_zero(), + "attempt to calculate with zero modulus!" + ); + + let i = match exp_data.iter().position(|&r| r != 0) { + None => return BigUint::one(), + Some(i) => i, + }; + + let mut base = base % modulus; + for _ in 0..i { + for _ in 0..big_digit::BITS { + base = &base * &base % modulus; + } + } + + let mut r = exp_data[i]; + let mut b = 0u8; + while r.is_even() { + base = &base * &base % modulus; + r >>= 1; + b += 1; + } + + let mut exp_iter = exp_data[i + 1..].iter(); + if exp_iter.len() == 0 && r.is_one() { + return base; + } + + let mut acc = base.clone(); + r >>= 1; + b += 1; + + { + let mut unit = |exp_is_odd| { + base = &base * &base % modulus; + if exp_is_odd { + acc *= &base; + acc %= modulus; + } + }; + + if let Some(&last) = exp_iter.next_back() { + // consume exp_data[i] + for _ in b..big_digit::BITS { + unit(r.is_odd()); + r >>= 1; + } + + // consume all other digits before the last + for &r in exp_iter { + let mut r = r; + for _ in 0..big_digit::BITS { + unit(r.is_odd()); + r >>= 1; + } + } + r = last; + } + + debug_assert_ne!(r, 0); + while !r.is_zero() { + unit(r.is_odd()); + r >>= 1; + } + } + acc +} + +#[test] +fn test_plain_modpow() { + let two = &BigUint::from(2u32); + let modulus = BigUint::from(0x1100u32); + + let exp = vec![0, 0b1]; + assert_eq!( + two.pow(0b1_00000000_u32) % &modulus, + plain_modpow(two, &exp, &modulus) + ); + let exp = vec![0, 0b10]; + assert_eq!( + two.pow(0b10_00000000_u32) % &modulus, + plain_modpow(two, &exp, &modulus) + ); + let exp = vec![0, 0b110010]; + assert_eq!( + two.pow(0b110010_00000000_u32) % &modulus, + plain_modpow(two, &exp, &modulus) + ); + let exp = vec![0b1, 0b1]; + assert_eq!( + two.pow(0b1_00000001_u32) % &modulus, + plain_modpow(two, &exp, &modulus) + ); + let exp = vec![0b1100, 0, 0b1]; + assert_eq!( + two.pow(0b1_00000000_00001100_u32) % &modulus, + plain_modpow(two, &exp, &modulus) + ); +} + +#[test] +fn test_pow_biguint() { + let base = BigUint::from(5u8); + let exponent = BigUint::from(3u8); + + assert_eq!(BigUint::from(125u8), base.pow(exponent)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +#![cfg(feature = "serde")] +#![cfg_attr(docsrs, doc(cfg(feature = "serde")))] + +use super::{biguint_from_vec, BigUint}; + +use alloc::vec::Vec; +use core::{cmp, fmt, mem}; +use serde::de::{SeqAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +// `cautious` is based on the function of the same name in `serde`, but specialized to `u32`: +// https://github.com/dtolnay/serde/blob/399ef081ecc36d2f165ff1f6debdcbf6a1dc7efb/serde/src/private/size_hint.rs#L11-L22 +fn cautious(hint: Option) -> usize { + const MAX_PREALLOC_BYTES: usize = 1024 * 1024; + + cmp::min( + hint.unwrap_or(0), + MAX_PREALLOC_BYTES / mem::size_of::(), + ) +} + +impl Serialize for BigUint { + cfg_digit!( + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Note: do not change the serialization format, or it may break forward + // and backward compatibility of serialized data! If we ever change the + // internal representation, we should still serialize in base-`u32`. + let data: &[u32] = &self.data; + data.serialize(serializer) + } + + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::SerializeSeq; + + if let Some((&last, data)) = self.data.split_last() { + let last_lo = last as u32; + let last_hi = (last >> 32) as u32; + let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; + let mut seq = serializer.serialize_seq(Some(u32_len))?; + for &x in data { + seq.serialize_element(&(x as u32))?; + seq.serialize_element(&((x >> 32) as u32))?; + } + seq.serialize_element(&last_lo)?; + if last_hi != 0 { + seq.serialize_element(&last_hi)?; + } + seq.end() + } else { + let data: &[u32] = &[]; + data.serialize(serializer) + } + } + ); +} + +impl<'de> Deserialize<'de> for BigUint { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_seq(U32Visitor) + } +} + +struct U32Visitor; + +impl<'de> Visitor<'de> for U32Visitor { + type Value = BigUint; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence of unsigned 32-bit numbers") + } + + cfg_digit!( + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + let len = cautious(seq.size_hint()); + let mut data = Vec::with_capacity(len); + + while let Some(value) = seq.next_element::()? { + data.push(value); + } + + Ok(biguint_from_vec(data)) + } + + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + use crate::big_digit::BigDigit; + use num_integer::Integer; + + let u32_len = cautious(seq.size_hint()); + let len = Integer::div_ceil(&u32_len, &2); + let mut data = Vec::with_capacity(len); + + while let Some(lo) = seq.next_element::()? { + let mut value = BigDigit::from(lo); + if let Some(hi) = seq.next_element::()? { + value |= BigDigit::from(hi) << 32; + data.push(value); + } else { + data.push(value); + break; + } + } + + Ok(biguint_from_vec(data)) + } + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/shift.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/shift.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/shift.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/shift.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,173 @@ +use super::{biguint_from_vec, BigUint}; + +use crate::big_digit; + +use alloc::borrow::Cow; +use alloc::vec::Vec; +use core::mem; +use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; +use num_traits::{PrimInt, Zero}; + +#[inline] +fn biguint_shl(n: Cow<'_, BigUint>, shift: T) -> BigUint { + if shift < T::zero() { + panic!("attempt to shift left with negative"); + } + if n.is_zero() { + return n.into_owned(); + } + let bits = T::from(big_digit::BITS).unwrap(); + let digits = (shift / bits).to_usize().expect("capacity overflow"); + let shift = (shift % bits).to_u8().unwrap(); + biguint_shl2(n, digits, shift) +} + +fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { + let mut data = match digits { + 0 => n.into_owned().data, + _ => { + let len = digits.saturating_add(n.data.len() + 1); + let mut data = Vec::with_capacity(len); + data.resize(digits, 0); + data.extend(n.data.iter()); + data + } + }; + + if shift > 0 { + let mut carry = 0; + let carry_shift = big_digit::BITS - shift; + for elem in data[digits..].iter_mut() { + let new_carry = *elem >> carry_shift; + *elem = (*elem << shift) | carry; + carry = new_carry; + } + if carry != 0 { + data.push(carry); + } + } + + biguint_from_vec(data) +} + +#[inline] +fn biguint_shr(n: Cow<'_, BigUint>, shift: T) -> BigUint { + if shift < T::zero() { + panic!("attempt to shift right with negative"); + } + if n.is_zero() { + return n.into_owned(); + } + let bits = T::from(big_digit::BITS).unwrap(); + let digits = (shift / bits).to_usize().unwrap_or(usize::MAX); + let shift = (shift % bits).to_u8().unwrap(); + biguint_shr2(n, digits, shift) +} + +fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { + if digits >= n.data.len() { + let mut n = n.into_owned(); + n.set_zero(); + return n; + } + let mut data = match n { + Cow::Borrowed(n) => n.data[digits..].to_vec(), + Cow::Owned(mut n) => { + n.data.drain(..digits); + n.data + } + }; + + if shift > 0 { + let mut borrow = 0; + let borrow_shift = big_digit::BITS - shift; + for elem in data.iter_mut().rev() { + let new_borrow = *elem << borrow_shift; + *elem = (*elem >> shift) | borrow; + borrow = new_borrow; + } + } + + biguint_from_vec(data) +} + +macro_rules! impl_shift { + (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { + impl $Shx<&$rhs> for BigUint { + type Output = BigUint; + + #[inline] + fn $shx(self, rhs: &$rhs) -> BigUint { + $Shx::$shx(self, *rhs) + } + } + impl $Shx<&$rhs> for &BigUint { + type Output = BigUint; + + #[inline] + fn $shx(self, rhs: &$rhs) -> BigUint { + $Shx::$shx(self, *rhs) + } + } + impl $ShxAssign<&$rhs> for BigUint { + #[inline] + fn $shx_assign(&mut self, rhs: &$rhs) { + $ShxAssign::$shx_assign(self, *rhs); + } + } + }; + ($($rhs:ty),+) => {$( + impl Shl<$rhs> for BigUint { + type Output = BigUint; + + #[inline] + fn shl(self, rhs: $rhs) -> BigUint { + biguint_shl(Cow::Owned(self), rhs) + } + } + impl Shl<$rhs> for &BigUint { + type Output = BigUint; + + #[inline] + fn shl(self, rhs: $rhs) -> BigUint { + biguint_shl(Cow::Borrowed(self), rhs) + } + } + impl ShlAssign<$rhs> for BigUint { + #[inline] + fn shl_assign(&mut self, rhs: $rhs) { + let n = mem::replace(self, Self::ZERO); + *self = n << rhs; + } + } + impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } + + impl Shr<$rhs> for BigUint { + type Output = BigUint; + + #[inline] + fn shr(self, rhs: $rhs) -> BigUint { + biguint_shr(Cow::Owned(self), rhs) + } + } + impl Shr<$rhs> for &BigUint { + type Output = BigUint; + + #[inline] + fn shr(self, rhs: $rhs) -> BigUint { + biguint_shr(Cow::Borrowed(self), rhs) + } + } + impl ShrAssign<$rhs> for BigUint { + #[inline] + fn shr_assign(&mut self, rhs: $rhs) { + let n = mem::replace(self, Self::ZERO); + *self = n >> rhs; + } + } + impl_shift! { @ref Shr::shr, ShrAssign::shr_assign, $rhs } + )*}; +} + +impl_shift! { u8, u16, u32, u64, u128, usize } +impl_shift! { i8, i16, i32, i64, i128, isize } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/subtraction.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/subtraction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint/subtraction.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint/subtraction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,312 @@ +use super::BigUint; + +use crate::big_digit::{self, BigDigit}; +use crate::UsizePromotion; + +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::ops::{Sub, SubAssign}; +use num_traits::CheckedSub; + +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64 as arch; + +#[cfg(target_arch = "x86")] +use core::arch::x86 as arch; + +// Subtract with borrow: +#[cfg(target_arch = "x86_64")] +cfg_64!( + #[inline] + fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_subborrow_u64(borrow, a, b, out) } + } +); + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +cfg_32!( + #[inline] + fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_subborrow_u32(borrow, a, b, out) } + } +); + +// fallback for environments where we don't have a subborrow intrinsic +// (copied from the standard library's `borrowing_sub`) +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +#[inline] +fn sbb(borrow: u8, lhs: BigDigit, rhs: BigDigit, out: &mut BigDigit) -> u8 { + let (a, b) = lhs.overflowing_sub(rhs); + let (c, d) = a.overflowing_sub(borrow as BigDigit); + *out = c; + u8::from(b || d) +} + +pub(super) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { + let mut borrow = 0; + + let len = Ord::min(a.len(), b.len()); + let (a_lo, a_hi) = a.split_at_mut(len); + let (b_lo, b_hi) = b.split_at(len); + + for (a, b) in a_lo.iter_mut().zip(b_lo) { + borrow = sbb(borrow, *a, *b, a); + } + + if borrow != 0 { + for a in a_hi { + borrow = sbb(borrow, *a, 0, a); + if borrow == 0 { + break; + } + } + } + + // note: we're _required_ to fail on underflow + assert!( + borrow == 0 && b_hi.iter().all(|x| *x == 0), + "Cannot subtract b from a because b is larger than a." + ); +} + +// Only for the Sub impl. `a` and `b` must have same length. +#[inline] +fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 { + debug_assert!(b.len() == a.len()); + + let mut borrow = 0; + + for (ai, bi) in a.iter().zip(b) { + borrow = sbb(borrow, *ai, *bi, bi); + } + + borrow +} + +fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { + debug_assert!(b.len() >= a.len()); + + let len = Ord::min(a.len(), b.len()); + let (a_lo, a_hi) = a.split_at(len); + let (b_lo, b_hi) = b.split_at_mut(len); + + let borrow = __sub2rev(a_lo, b_lo); + + assert!(a_hi.is_empty()); + + // note: we're _required_ to fail on underflow + assert!( + borrow == 0 && b_hi.iter().all(|x| *x == 0), + "Cannot subtract b from a because b is larger than a." + ); +} + +forward_val_val_binop!(impl Sub for BigUint, sub); +forward_ref_ref_binop!(impl Sub for BigUint, sub); +forward_val_assign!(impl SubAssign for BigUint, sub_assign); + +impl Sub<&BigUint> for BigUint { + type Output = BigUint; + + fn sub(mut self, other: &BigUint) -> BigUint { + self -= other; + self + } +} +impl SubAssign<&BigUint> for BigUint { + fn sub_assign(&mut self, other: &BigUint) { + sub2(&mut self.data[..], &other.data[..]); + self.normalize(); + } +} + +impl Sub for &BigUint { + type Output = BigUint; + + fn sub(self, mut other: BigUint) -> BigUint { + let other_len = other.data.len(); + if other_len < self.data.len() { + let lo_borrow = __sub2rev(&self.data[..other_len], &mut other.data); + other.data.extend_from_slice(&self.data[other_len..]); + if lo_borrow != 0 { + sub2(&mut other.data[other_len..], &[1]) + } + } else { + sub2rev(&self.data[..], &mut other.data[..]); + } + other.normalized() + } +} + +promote_unsigned_scalars!(impl Sub for BigUint, sub); +promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign); +forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); +forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); + +impl Sub for BigUint { + type Output = BigUint; + + #[inline] + fn sub(mut self, other: u32) -> BigUint { + self -= other; + self + } +} + +impl SubAssign for BigUint { + fn sub_assign(&mut self, other: u32) { + sub2(&mut self.data[..], &[other as BigDigit]); + self.normalize(); + } +} + +impl Sub for u32 { + type Output = BigUint; + + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.len() == 0 { + other.data.push(self); + } else { + sub2rev(&[self], &mut other.data[..]); + } + other.normalized() + } + + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.is_empty() { + other.data.push(self as BigDigit); + } else { + sub2rev(&[self as BigDigit], &mut other.data[..]); + } + other.normalized() + } + ); +} + +impl Sub for BigUint { + type Output = BigUint; + + #[inline] + fn sub(mut self, other: u64) -> BigUint { + self -= other; + self + } +} + +impl SubAssign for BigUint { + cfg_digit!( + #[inline] + fn sub_assign(&mut self, other: u64) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + sub2(&mut self.data[..], &[lo, hi]); + self.normalize(); + } + + #[inline] + fn sub_assign(&mut self, other: u64) { + sub2(&mut self.data[..], &[other as BigDigit]); + self.normalize(); + } + ); +} + +impl Sub for u64 { + type Output = BigUint; + + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 2 { + other.data.push(0); + } + + let (hi, lo) = big_digit::from_doublebigdigit(self); + sub2rev(&[lo, hi], &mut other.data[..]); + other.normalized() + } + + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.is_empty() { + other.data.push(self); + } else { + sub2rev(&[self], &mut other.data[..]); + } + other.normalized() + } + ); +} + +impl Sub for BigUint { + type Output = BigUint; + + #[inline] + fn sub(mut self, other: u128) -> BigUint { + self -= other; + self + } +} + +impl SubAssign for BigUint { + cfg_digit!( + #[inline] + fn sub_assign(&mut self, other: u128) { + let (a, b, c, d) = super::u32_from_u128(other); + sub2(&mut self.data[..], &[d, c, b, a]); + self.normalize(); + } + + #[inline] + fn sub_assign(&mut self, other: u128) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + sub2(&mut self.data[..], &[lo, hi]); + self.normalize(); + } + ); +} + +impl Sub for u128 { + type Output = BigUint; + + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 4 { + other.data.push(0); + } + + let (a, b, c, d) = super::u32_from_u128(self); + sub2rev(&[d, c, b, a], &mut other.data[..]); + other.normalized() + } + + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 2 { + other.data.push(0); + } + + let (hi, lo) = big_digit::from_doublebigdigit(self); + sub2rev(&[lo, hi], &mut other.data[..]); + other.normalized() + } + ); +} + +impl CheckedSub for BigUint { + #[inline] + fn checked_sub(&self, v: &BigUint) -> Option { + match self.cmp(v) { + Less => None, + Equal => Some(Self::ZERO), + Greater => Some(self.sub(v)), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/biguint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/biguint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1206 @@ +use crate::big_digit::{self, BigDigit}; + +use alloc::string::String; +use alloc::vec::Vec; +use core::cmp; +use core::cmp::Ordering; +use core::default::Default; +use core::fmt; +use core::hash; +use core::mem; +use core::str; + +use num_integer::{Integer, Roots}; +use num_traits::{ConstZero, Num, One, Pow, ToPrimitive, Unsigned, Zero}; + +mod addition; +mod division; +mod multiplication; +mod subtraction; + +mod arbitrary; +mod bits; +mod convert; +mod iter; +mod monty; +mod power; +mod serde; +mod shift; + +pub(crate) use self::convert::to_str_radix_reversed; +pub use self::iter::{U32Digits, U64Digits}; + +/// A big unsigned integer type. +pub struct BigUint { + data: Vec, +} + +// Note: derived `Clone` doesn't specialize `clone_from`, +// but we want to keep the allocation in `data`. +impl Clone for BigUint { + #[inline] + fn clone(&self) -> Self { + BigUint { + data: self.data.clone(), + } + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.data.clone_from(&other.data); + } +} + +impl hash::Hash for BigUint { + #[inline] + fn hash(&self, state: &mut H) { + debug_assert!(self.data.last() != Some(&0)); + self.data.hash(state); + } +} + +impl PartialEq for BigUint { + #[inline] + fn eq(&self, other: &BigUint) -> bool { + debug_assert!(self.data.last() != Some(&0)); + debug_assert!(other.data.last() != Some(&0)); + self.data == other.data + } +} +impl Eq for BigUint {} + +impl PartialOrd for BigUint { + #[inline] + fn partial_cmp(&self, other: &BigUint) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for BigUint { + #[inline] + fn cmp(&self, other: &BigUint) -> Ordering { + cmp_slice(&self.data[..], &other.data[..]) + } +} + +#[inline] +fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { + debug_assert!(a.last() != Some(&0)); + debug_assert!(b.last() != Some(&0)); + + match Ord::cmp(&a.len(), &b.len()) { + Ordering::Equal => Iterator::cmp(a.iter().rev(), b.iter().rev()), + other => other, + } +} + +impl Default for BigUint { + #[inline] + fn default() -> BigUint { + Self::ZERO + } +} + +impl fmt::Debug for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "", &self.to_str_radix(10)) + } +} + +impl fmt::LowerHex for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "0x", &self.to_str_radix(16)) + } +} + +impl fmt::UpperHex for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s = self.to_str_radix(16); + s.make_ascii_uppercase(); + f.pad_integral(true, "0x", &s) + } +} + +impl fmt::Binary for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "0b", &self.to_str_radix(2)) + } +} + +impl fmt::Octal for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "0o", &self.to_str_radix(8)) + } +} + +impl Zero for BigUint { + #[inline] + fn zero() -> BigUint { + Self::ZERO + } + + #[inline] + fn set_zero(&mut self) { + self.data.clear(); + } + + #[inline] + fn is_zero(&self) -> bool { + self.data.is_empty() + } +} + +impl ConstZero for BigUint { + // forward to the inherent const + const ZERO: Self = Self::ZERO; // BigUint { data: Vec::new() }; +} + +impl One for BigUint { + #[inline] + fn one() -> BigUint { + BigUint { data: vec![1] } + } + + #[inline] + fn set_one(&mut self) { + self.data.clear(); + self.data.push(1); + } + + #[inline] + fn is_one(&self) -> bool { + self.data[..] == [1] + } +} + +impl Unsigned for BigUint {} + +impl Integer for BigUint { + #[inline] + fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { + division::div_rem_ref(self, other) + } + + #[inline] + fn div_floor(&self, other: &BigUint) -> BigUint { + let (d, _) = division::div_rem_ref(self, other); + d + } + + #[inline] + fn mod_floor(&self, other: &BigUint) -> BigUint { + let (_, m) = division::div_rem_ref(self, other); + m + } + + #[inline] + fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { + division::div_rem_ref(self, other) + } + + #[inline] + fn div_ceil(&self, other: &BigUint) -> BigUint { + let (d, m) = division::div_rem_ref(self, other); + if m.is_zero() { + d + } else { + d + 1u32 + } + } + + /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. + /// + /// The result is always positive. + #[inline] + fn gcd(&self, other: &Self) -> Self { + #[inline] + fn twos(x: &BigUint) -> u64 { + x.trailing_zeros().unwrap_or(0) + } + + // Stein's algorithm + if self.is_zero() { + return other.clone(); + } + if other.is_zero() { + return self.clone(); + } + let mut m = self.clone(); + let mut n = other.clone(); + + // find common factors of 2 + let shift = cmp::min(twos(&n), twos(&m)); + + // divide m and n by 2 until odd + // m inside loop + n >>= twos(&n); + + while !m.is_zero() { + m >>= twos(&m); + if n > m { + mem::swap(&mut n, &mut m) + } + m -= &n; + } + + n << shift + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. + #[inline] + fn lcm(&self, other: &BigUint) -> BigUint { + if self.is_zero() && other.is_zero() { + Self::ZERO + } else { + self / self.gcd(other) * other + } + } + + /// Calculates the Greatest Common Divisor (GCD) and + /// Lowest Common Multiple (LCM) together. + #[inline] + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let gcd = self.gcd(other); + let lcm = if gcd.is_zero() { + Self::ZERO + } else { + self / &gcd * other + }; + (gcd, lcm) + } + + /// Deprecated, use `is_multiple_of` instead. + #[inline] + fn divides(&self, other: &BigUint) -> bool { + self.is_multiple_of(other) + } + + /// Returns `true` if the number is a multiple of `other`. + #[inline] + fn is_multiple_of(&self, other: &BigUint) -> bool { + if other.is_zero() { + return self.is_zero(); + } + (self % other).is_zero() + } + + /// Returns `true` if the number is divisible by `2`. + #[inline] + fn is_even(&self) -> bool { + // Considering only the last digit. + match self.data.first() { + Some(x) => x.is_even(), + None => true, + } + } + + /// Returns `true` if the number is not divisible by `2`. + #[inline] + fn is_odd(&self) -> bool { + !self.is_even() + } + + /// Rounds up to nearest multiple of argument. + #[inline] + fn next_multiple_of(&self, other: &Self) -> Self { + let m = self.mod_floor(other); + if m.is_zero() { + self.clone() + } else { + self + (other - m) + } + } + /// Rounds down to nearest multiple of argument. + #[inline] + fn prev_multiple_of(&self, other: &Self) -> Self { + self - self.mod_floor(other) + } + + fn dec(&mut self) { + *self -= 1u32; + } + + fn inc(&mut self) { + *self += 1u32; + } +} + +#[inline] +fn fixpoint(mut x: BigUint, max_bits: u64, f: F) -> BigUint +where + F: Fn(&BigUint) -> BigUint, +{ + let mut xn = f(&x); + + // If the value increased, then the initial guess must have been low. + // Repeat until we reverse course. + while x < xn { + // Sometimes an increase will go way too far, especially with large + // powers, and then take a long time to walk back. We know an upper + // bound based on bit size, so saturate on that. + x = if xn.bits() > max_bits { + BigUint::one() << max_bits + } else { + xn + }; + xn = f(&x); + } + + // Now keep repeating while the estimate is decreasing. + while x > xn { + x = xn; + xn = f(&x); + } + x +} + +impl Roots for BigUint { + // nth_root, sqrt and cbrt use Newton's method to compute + // principal root of a given degree for a given integer. + + // Reference: + // Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.14 + fn nth_root(&self, n: u32) -> Self { + assert!(n > 0, "root degree n must be at least 1"); + + if self.is_zero() || self.is_one() { + return self.clone(); + } + + match n { + // Optimize for small n + 1 => return self.clone(), + 2 => return self.sqrt(), + 3 => return self.cbrt(), + _ => (), + } + + // The root of non-zero values less than 2ⁿ can only be 1. + let bits = self.bits(); + let n64 = u64::from(n); + if bits <= n64 { + return BigUint::one(); + } + + // If we fit in `u64`, compute the root that way. + if let Some(x) = self.to_u64() { + return x.nth_root(n).into(); + } + + let max_bits = bits / n64 + 1; + + #[cfg(feature = "std")] + let guess = match self.to_f64() { + Some(f) if f.is_finite() => { + use num_traits::FromPrimitive; + + // We fit in `f64` (lossy), so get a better initial guess from that. + BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap() + } + _ => { + // Try to guess by scaling down such that it does fit in `f64`. + // With some (x * 2ⁿᵏ), its nth root ≈ (ⁿ√x * 2ᵏ) + let extra_bits = bits - (f64::MAX_EXP as u64 - 1); + let root_scale = Integer::div_ceil(&extra_bits, &n64); + let scale = root_scale * n64; + if scale < bits && bits - scale > n64 { + (self >> scale).nth_root(n) << root_scale + } else { + BigUint::one() << max_bits + } + } + }; + + #[cfg(not(feature = "std"))] + let guess = BigUint::one() << max_bits; + + let n_min_1 = n - 1; + fixpoint(guess, max_bits, move |s| { + let q = self / s.pow(n_min_1); + let t = n_min_1 * s + q; + t / n + }) + } + + // Reference: + // Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.13 + fn sqrt(&self) -> Self { + if self.is_zero() || self.is_one() { + return self.clone(); + } + + // If we fit in `u64`, compute the root that way. + if let Some(x) = self.to_u64() { + return x.sqrt().into(); + } + + let bits = self.bits(); + let max_bits = bits / 2 + 1; + + #[cfg(feature = "std")] + let guess = match self.to_f64() { + Some(f) if f.is_finite() => { + use num_traits::FromPrimitive; + + // We fit in `f64` (lossy), so get a better initial guess from that. + BigUint::from_f64(f.sqrt()).unwrap() + } + _ => { + // Try to guess by scaling down such that it does fit in `f64`. + // With some (x * 2²ᵏ), its sqrt ≈ (√x * 2ᵏ) + let extra_bits = bits - (f64::MAX_EXP as u64 - 1); + let root_scale = (extra_bits + 1) / 2; + let scale = root_scale * 2; + (self >> scale).sqrt() << root_scale + } + }; + + #[cfg(not(feature = "std"))] + let guess = BigUint::one() << max_bits; + + fixpoint(guess, max_bits, move |s| { + let q = self / s; + let t = s + q; + t >> 1 + }) + } + + fn cbrt(&self) -> Self { + if self.is_zero() || self.is_one() { + return self.clone(); + } + + // If we fit in `u64`, compute the root that way. + if let Some(x) = self.to_u64() { + return x.cbrt().into(); + } + + let bits = self.bits(); + let max_bits = bits / 3 + 1; + + #[cfg(feature = "std")] + let guess = match self.to_f64() { + Some(f) if f.is_finite() => { + use num_traits::FromPrimitive; + + // We fit in `f64` (lossy), so get a better initial guess from that. + BigUint::from_f64(f.cbrt()).unwrap() + } + _ => { + // Try to guess by scaling down such that it does fit in `f64`. + // With some (x * 2³ᵏ), its cbrt ≈ (∛x * 2ᵏ) + let extra_bits = bits - (f64::MAX_EXP as u64 - 1); + let root_scale = (extra_bits + 2) / 3; + let scale = root_scale * 3; + (self >> scale).cbrt() << root_scale + } + }; + + #[cfg(not(feature = "std"))] + let guess = BigUint::one() << max_bits; + + fixpoint(guess, max_bits, move |s| { + let q = self / (s * s); + let t = (s << 1) + q; + t / 3u32 + }) + } +} + +/// A generic trait for converting a value to a [`BigUint`]. +pub trait ToBigUint { + /// Converts the value of `self` to a [`BigUint`]. + fn to_biguint(&self) -> Option; +} + +/// Creates and initializes a [`BigUint`]. +/// +/// The digits are in little-endian base matching `BigDigit`. +#[inline] +pub(crate) fn biguint_from_vec(digits: Vec) -> BigUint { + BigUint { data: digits }.normalized() +} + +impl BigUint { + /// A constant `BigUint` with value 0, useful for static initialization. + pub const ZERO: Self = BigUint { data: Vec::new() }; + + /// Creates and initializes a [`BigUint`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn new(digits: Vec) -> BigUint { + let mut big = Self::ZERO; + + cfg_digit_expr!( + { + big.data = digits; + big.normalize(); + }, + big.assign_from_slice(&digits) + ); + + big + } + + /// Creates and initializes a [`BigUint`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn from_slice(slice: &[u32]) -> BigUint { + let mut big = Self::ZERO; + big.assign_from_slice(slice); + big + } + + /// Assign a value to a [`BigUint`]. + /// + /// The base 232 digits are ordered least significant digit first. + #[inline] + pub fn assign_from_slice(&mut self, slice: &[u32]) { + self.data.clear(); + + cfg_digit_expr!( + self.data.extend_from_slice(slice), + self.data.extend(slice.chunks(2).map(u32_chunk_to_u64)) + ); + + self.normalize(); + } + + /// Creates and initializes a [`BigUint`]. + /// + /// The bytes are in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from_bytes_be(b"A"), + /// BigUint::parse_bytes(b"65", 10).unwrap()); + /// assert_eq!(BigUint::from_bytes_be(b"AA"), + /// BigUint::parse_bytes(b"16705", 10).unwrap()); + /// assert_eq!(BigUint::from_bytes_be(b"AB"), + /// BigUint::parse_bytes(b"16706", 10).unwrap()); + /// assert_eq!(BigUint::from_bytes_be(b"Hello world!"), + /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); + /// ``` + #[inline] + pub fn from_bytes_be(bytes: &[u8]) -> BigUint { + if bytes.is_empty() { + Self::ZERO + } else { + let mut v = bytes.to_vec(); + v.reverse(); + BigUint::from_bytes_le(&v) + } + } + + /// Creates and initializes a [`BigUint`]. + /// + /// The bytes are in little-endian byte order. + #[inline] + pub fn from_bytes_le(bytes: &[u8]) -> BigUint { + if bytes.is_empty() { + Self::ZERO + } else { + convert::from_bitwise_digits_le(bytes, 8) + } + } + + /// Creates and initializes a [`BigUint`]. The input slice must contain + /// ascii/utf8 characters in [0-9a-zA-Z]. + /// `radix` must be in the range `2...36`. + /// + /// The function `from_str_radix` from the `Num` trait provides the same logic + /// for `&str` buffers. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigUint, ToBigUint}; + /// + /// assert_eq!(BigUint::parse_bytes(b"1234", 10), ToBigUint::to_biguint(&1234)); + /// assert_eq!(BigUint::parse_bytes(b"ABCD", 16), ToBigUint::to_biguint(&0xABCD)); + /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); + /// ``` + #[inline] + pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { + let s = str::from_utf8(buf).ok()?; + BigUint::from_str_radix(s, radix).ok() + } + + /// Creates and initializes a [`BigUint`]. Each `u8` of the input slice is + /// interpreted as one digit of the number + /// and must therefore be less than `radix`. + /// + /// The bytes are in big-endian byte order. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigUint}; + /// + /// let inbase190 = &[15, 33, 125, 12, 14]; + /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); + /// assert_eq!(a.to_radix_be(190), inbase190); + /// ``` + pub fn from_radix_be(buf: &[u8], radix: u32) -> Option { + convert::from_radix_be(buf, radix) + } + + /// Creates and initializes a [`BigUint`]. Each `u8` of the input slice is + /// interpreted as one digit of the number + /// and must therefore be less than `radix`. + /// + /// The bytes are in little-endian byte order. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigUint}; + /// + /// let inbase190 = &[14, 12, 125, 33, 15]; + /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); + /// assert_eq!(a.to_radix_be(190), inbase190); + /// ``` + pub fn from_radix_le(buf: &[u8], radix: u32) -> Option { + convert::from_radix_le(buf, radix) + } + + /// Returns the byte representation of the [`BigUint`] in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); + /// assert_eq!(i.to_bytes_be(), vec![4, 101]); + /// ``` + #[inline] + pub fn to_bytes_be(&self) -> Vec { + let mut v = self.to_bytes_le(); + v.reverse(); + v + } + + /// Returns the byte representation of the [`BigUint`] in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); + /// assert_eq!(i.to_bytes_le(), vec![101, 4]); + /// ``` + #[inline] + pub fn to_bytes_le(&self) -> Vec { + if self.is_zero() { + vec![0] + } else { + convert::to_bitwise_digits_le(self, 8) + } + } + + /// Returns the `u32` digits representation of the [`BigUint`] ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); + /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn to_u32_digits(&self) -> Vec { + self.iter_u32_digits().collect() + } + + /// Returns the `u64` digits representation of the [`BigUint`] ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).to_u64_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u64_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u64_digits(), vec![4294967296]); + /// assert_eq!(BigUint::from(112500000000u64).to_u64_digits(), vec![112500000000]); + /// assert_eq!(BigUint::from(1u128 << 64).to_u64_digits(), vec![0, 1]); + /// ``` + #[inline] + pub fn to_u64_digits(&self) -> Vec { + self.iter_u64_digits().collect() + } + + /// Returns an iterator of `u32` digits representation of the [`BigUint`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).iter_u32_digits().collect::>(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).iter_u32_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).iter_u32_digits().collect::>(), vec![0, 1]); + /// assert_eq!(BigUint::from(112500000000u64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn iter_u32_digits(&self) -> U32Digits<'_> { + U32Digits::new(self.data.as_slice()) + } + + /// Returns an iterator of `u64` digits representation of the [`BigUint`] ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).iter_u64_digits().collect::>(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).iter_u64_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296]); + /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::>(), vec![112500000000]); + /// assert_eq!(BigUint::from(1u128 << 64).iter_u64_digits().collect::>(), vec![0, 1]); + /// ``` + #[inline] + pub fn iter_u64_digits(&self) -> U64Digits<'_> { + U64Digits::new(self.data.as_slice()) + } + + /// Returns the integer formatted as a string in the given radix. + /// `radix` must be in the range `2...36`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// let i = BigUint::parse_bytes(b"ff", 16).unwrap(); + /// assert_eq!(i.to_str_radix(16), "ff"); + /// ``` + #[inline] + pub fn to_str_radix(&self, radix: u32) -> String { + let mut v = to_str_radix_reversed(self, radix); + v.reverse(); + unsafe { String::from_utf8_unchecked(v) } + } + + /// Returns the integer in the requested base in big-endian digit order. + /// The output is not given in a human readable alphabet but as a zero + /// based `u8` number. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_be(159), + /// vec![2, 94, 27]); + /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 + /// ``` + #[inline] + pub fn to_radix_be(&self, radix: u32) -> Vec { + let mut v = convert::to_radix_le(self, radix); + v.reverse(); + v + } + + /// Returns the integer in the requested base in little-endian digit order. + /// The output is not given in a human readable alphabet but as a zero + /// based u8 number. + /// `radix` must be in the range `2...256`. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), + /// vec![27, 94, 2]); + /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) + /// ``` + #[inline] + pub fn to_radix_le(&self, radix: u32) -> Vec { + convert::to_radix_le(self, radix) + } + + /// Determines the fewest bits necessary to express the [`BigUint`]. + #[inline] + pub fn bits(&self) -> u64 { + if self.is_zero() { + return 0; + } + let zeros: u64 = self.data.last().unwrap().leading_zeros().into(); + self.data.len() as u64 * u64::from(big_digit::BITS) - zeros + } + + /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to + /// be nonzero. + #[inline] + fn normalize(&mut self) { + if let Some(&0) = self.data.last() { + let len = self.data.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1); + self.data.truncate(len); + } + if self.data.len() < self.data.capacity() / 4 { + self.data.shrink_to_fit(); + } + } + + /// Returns a normalized [`BigUint`]. + #[inline] + fn normalized(mut self) -> BigUint { + self.normalize(); + self + } + + /// Returns `self ^ exponent`. + pub fn pow(&self, exponent: u32) -> Self { + Pow::pow(self, exponent) + } + + /// Returns `(self ^ exponent) % modulus`. + /// + /// Panics if the modulus is zero. + pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { + power::modpow(self, exponent, modulus) + } + + /// Returns the modular multiplicative inverse if it exists, otherwise `None`. + /// + /// This solves for `x` in the interval `[0, modulus)` such that `self * x ≡ 1 (mod modulus)`. + /// The solution exists if and only if `gcd(self, modulus) == 1`. + /// + /// ``` + /// use num_bigint::BigUint; + /// use num_traits::{One, Zero}; + /// + /// let m = BigUint::from(383_u32); + /// + /// // Trivial cases + /// assert_eq!(BigUint::zero().modinv(&m), None); + /// assert_eq!(BigUint::one().modinv(&m), Some(BigUint::one())); + /// let neg1 = &m - 1u32; + /// assert_eq!(neg1.modinv(&m), Some(neg1)); + /// + /// let a = BigUint::from(271_u32); + /// let x = a.modinv(&m).unwrap(); + /// assert_eq!(x, BigUint::from(106_u32)); + /// assert_eq!(x.modinv(&m).unwrap(), a); + /// assert!((a * x % m).is_one()); + /// ``` + pub fn modinv(&self, modulus: &Self) -> Option { + // Based on the inverse pseudocode listed here: + // https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers + // TODO: consider Binary or Lehmer's GCD algorithms for optimization. + + assert!( + !modulus.is_zero(), + "attempt to calculate with zero modulus!" + ); + if modulus.is_one() { + return Some(Self::zero()); + } + + let mut r0; // = modulus.clone(); + let mut r1 = self % modulus; + let mut t0; // = Self::zero(); + let mut t1; // = Self::one(); + + // Lift and simplify the first iteration to avoid some initial allocations. + if r1.is_zero() { + return None; + } else if r1.is_one() { + return Some(r1); + } else { + let (q, r2) = modulus.div_rem(&r1); + if r2.is_zero() { + return None; + } + r0 = r1; + r1 = r2; + t0 = Self::one(); + t1 = modulus - q; + } + + while !r1.is_zero() { + let (q, r2) = r0.div_rem(&r1); + r0 = r1; + r1 = r2; + + // let t2 = (t0 - q * t1) % modulus; + let qt1 = q * &t1 % modulus; + let t2 = if t0 < qt1 { + t0 + (modulus - qt1) + } else { + t0 - qt1 + }; + t0 = t1; + t1 = t2; + } + + if r0.is_one() { + Some(t0) + } else { + None + } + } + + /// Returns the truncated principal square root of `self` -- + /// see [Roots::sqrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.sqrt) + pub fn sqrt(&self) -> Self { + Roots::sqrt(self) + } + + /// Returns the truncated principal cube root of `self` -- + /// see [Roots::cbrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.cbrt). + pub fn cbrt(&self) -> Self { + Roots::cbrt(self) + } + + /// Returns the truncated principal `n`th root of `self` -- + /// see [Roots::nth_root](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#tymethod.nth_root). + pub fn nth_root(&self, n: u32) -> Self { + Roots::nth_root(self, n) + } + + /// Returns the number of least-significant bits that are zero, + /// or `None` if the entire number is zero. + pub fn trailing_zeros(&self) -> Option { + let i = self.data.iter().position(|&digit| digit != 0)?; + let zeros: u64 = self.data[i].trailing_zeros().into(); + Some(i as u64 * u64::from(big_digit::BITS) + zeros) + } + + /// Returns the number of least-significant bits that are ones. + pub fn trailing_ones(&self) -> u64 { + if let Some(i) = self.data.iter().position(|&digit| !digit != 0) { + let ones: u64 = self.data[i].trailing_ones().into(); + i as u64 * u64::from(big_digit::BITS) + ones + } else { + self.data.len() as u64 * u64::from(big_digit::BITS) + } + } + + /// Returns the number of one bits. + pub fn count_ones(&self) -> u64 { + self.data.iter().map(|&d| u64::from(d.count_ones())).sum() + } + + /// Returns whether the bit in the given position is set + pub fn bit(&self, bit: u64) -> bool { + let bits_per_digit = u64::from(big_digit::BITS); + if let Some(digit_index) = (bit / bits_per_digit).to_usize() { + if let Some(digit) = self.data.get(digit_index) { + let bit_mask = (1 as BigDigit) << (bit % bits_per_digit); + return (digit & bit_mask) != 0; + } + } + false + } + + /// Sets or clears the bit in the given position + /// + /// Note that setting a bit greater than the current bit length, a reallocation may be needed + /// to store the new digits + pub fn set_bit(&mut self, bit: u64, value: bool) { + // Note: we're saturating `digit_index` and `new_len` -- any such case is guaranteed to + // fail allocation, and that's more consistent than adding our own overflow panics. + let bits_per_digit = u64::from(big_digit::BITS); + let digit_index = (bit / bits_per_digit).to_usize().unwrap_or(usize::MAX); + let bit_mask = (1 as BigDigit) << (bit % bits_per_digit); + if value { + if digit_index >= self.data.len() { + let new_len = digit_index.saturating_add(1); + self.data.resize(new_len, 0); + } + self.data[digit_index] |= bit_mask; + } else if digit_index < self.data.len() { + self.data[digit_index] &= !bit_mask; + // the top bit may have been cleared, so normalize + self.normalize(); + } + } +} + +impl num_traits::FromBytes for BigUint { + type Bytes = [u8]; + + fn from_be_bytes(bytes: &Self::Bytes) -> Self { + Self::from_bytes_be(bytes) + } + + fn from_le_bytes(bytes: &Self::Bytes) -> Self { + Self::from_bytes_le(bytes) + } +} + +impl num_traits::ToBytes for BigUint { + type Bytes = Vec; + + fn to_be_bytes(&self) -> Self::Bytes { + self.to_bytes_be() + } + + fn to_le_bytes(&self) -> Self::Bytes { + self.to_bytes_le() + } +} + +pub(crate) trait IntDigits { + fn digits(&self) -> &[BigDigit]; + fn digits_mut(&mut self) -> &mut Vec; + fn normalize(&mut self); + fn capacity(&self) -> usize; + fn len(&self) -> usize; +} + +impl IntDigits for BigUint { + #[inline] + fn digits(&self) -> &[BigDigit] { + &self.data + } + #[inline] + fn digits_mut(&mut self) -> &mut Vec { + &mut self.data + } + #[inline] + fn normalize(&mut self) { + self.normalize(); + } + #[inline] + fn capacity(&self) -> usize { + self.data.capacity() + } + #[inline] + fn len(&self) -> usize { + self.data.len() + } +} + +/// Convert a `u32` chunk (len is either 1 or 2) to a single `u64` digit +#[inline] +fn u32_chunk_to_u64(chunk: &[u32]) -> u64 { + // raw could have odd length + let mut digit = chunk[0] as u64; + if let Some(&hi) = chunk.get(1) { + digit |= (hi as u64) << 32; + } + digit +} + +cfg_32_or_test!( + /// Combine four `u32`s into a single `u128`. + #[inline] + fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 { + u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96) + } +); + +cfg_32_or_test!( + /// Split a single `u128` into four `u32`. + #[inline] + fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { + ( + (n >> 96) as u32, + (n >> 64) as u32, + (n >> 32) as u32, + n as u32, + ) + } +); + +cfg_digit!( + #[test] + fn test_from_slice() { + fn check(slice: &[u32], data: &[BigDigit]) { + assert_eq!(BigUint::from_slice(slice).data, data); + } + check(&[1], &[1]); + check(&[0, 0, 0], &[]); + check(&[1, 2, 0, 0], &[1, 2]); + check(&[0, 0, 1, 2], &[0, 0, 1, 2]); + check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); + check(&[-1i32 as u32], &[-1i32 as BigDigit]); + } + + #[test] + fn test_from_slice() { + fn check(slice: &[u32], data: &[BigDigit]) { + assert_eq!( + BigUint::from_slice(slice).data, + data, + "from {:?}, to {:?}", + slice, + data + ); + } + check(&[1], &[1]); + check(&[0, 0, 0], &[]); + check(&[1, 2], &[8_589_934_593]); + check(&[1, 2, 0, 0], &[8_589_934_593]); + check(&[0, 0, 1, 2], &[0, 8_589_934_593]); + check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]); + check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]); + } +); + +#[test] +fn test_u32_u128() { + assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0)); + assert_eq!( + u32_from_u128(u128::MAX), + (u32::MAX, u32::MAX, u32::MAX, u32::MAX) + ); + + assert_eq!(u32_from_u128(u32::MAX as u128), (0, 0, 0, u32::MAX)); + + assert_eq!(u32_from_u128(u64::MAX as u128), (0, 0, u32::MAX, u32::MAX)); + + assert_eq!( + u32_from_u128((u64::MAX as u128) + u32::MAX as u128), + (0, 1, 0, u32::MAX - 1) + ); + + assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0)); +} + +#[test] +fn test_u128_u32_roundtrip() { + // roundtrips + let values = vec![ + 0u128, + 1u128, + u64::MAX as u128 * 3, + u32::MAX as u128, + u64::MAX as u128, + (u64::MAX as u128) + u32::MAX as u128, + u128::MAX, + ]; + + for val in &values { + let (a, b, c, d) = u32_from_u128(*val); + assert_eq!(u32_to_u128(a, b, c, d), *val); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,268 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Big Integer Types for Rust +//! +//! * A [`BigUint`] is unsigned and represented as a vector of digits. +//! * A [`BigInt`] is signed and is a combination of [`BigUint`] and [`Sign`]. +//! +//! Common numerical operations are overloaded, so we can treat them +//! the same way we treat other numbers. +//! +//! ## Example +//! +//! ```rust +//! # fn main() { +//! use num_bigint::BigUint; +//! use num_traits::One; +//! +//! // Calculate large fibonacci numbers. +//! fn fib(n: usize) -> BigUint { +//! let mut f0 = BigUint::ZERO; +//! let mut f1 = BigUint::one(); +//! for _ in 0..n { +//! let f2 = f0 + &f1; +//! f0 = f1; +//! f1 = f2; +//! } +//! f0 +//! } +//! +//! // This is a very large number. +//! println!("fib(1000) = {}", fib(1000)); +//! # } +//! ``` +//! +//! It's easy to generate large random numbers: +//! +//! ```rust,ignore +//! use num_bigint::{ToBigInt, RandBigInt}; +//! +//! let mut rng = rand::thread_rng(); +//! let a = rng.gen_bigint(1000); +//! +//! let low = -10000.to_bigint().unwrap(); +//! let high = 10000.to_bigint().unwrap(); +//! let b = rng.gen_bigint_range(&low, &high); +//! +//! // Probably an even larger number. +//! println!("{}", a * b); +//! ``` +//! +//! See the "Features" section for instructions for enabling random number generation. +//! +//! ## Features +//! +//! The `std` crate feature is enabled by default, which enables [`std::error::Error`] +//! implementations and some internal use of floating point approximations. This can be disabled by +//! depending on `num-bigint` with `default-features = false`. Either way, the `alloc` crate is +//! always required for heap allocation of the `BigInt`/`BigUint` digits. +//! +//! ### Random Generation +//! +//! `num-bigint` supports the generation of random big integers when the `rand` +//! feature is enabled. To enable it include rand as +//! +//! ```toml +//! rand = "0.8" +//! num-bigint = { version = "0.4", features = ["rand"] } +//! ``` +//! +//! Note that you must use the version of `rand` that `num-bigint` is compatible +//! with: `0.8`. +//! +//! ### Arbitrary Big Integers +//! +//! `num-bigint` supports `arbitrary` and `quickcheck` features to implement +//! [`arbitrary::Arbitrary`] and [`quickcheck::Arbitrary`], respectively, for both `BigInt` and +//! `BigUint`. These are useful for fuzzing and other forms of randomized testing. +//! +//! ### Serialization +//! +//! The `serde` feature adds implementations of [`Serialize`][serde::Serialize] and +//! [`Deserialize`][serde::Deserialize] for both `BigInt` and `BigUint`. Their serialized data is +//! generated portably, regardless of platform differences like the internal digit size. +//! +//! +//! ## Compatibility +//! +//! The `num-bigint` crate is tested for rustc 1.60 and greater. + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc(html_root_url = "https://docs.rs/num-bigint/0.4")] +#![warn(rust_2018_idioms)] +#![no_std] + +#[macro_use] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +use core::fmt; + +#[macro_use] +mod macros; + +mod bigint; +mod bigrand; +mod biguint; + +#[cfg(target_pointer_width = "32")] +type UsizePromotion = u32; +#[cfg(target_pointer_width = "64")] +type UsizePromotion = u64; + +#[cfg(target_pointer_width = "32")] +type IsizePromotion = i32; +#[cfg(target_pointer_width = "64")] +type IsizePromotion = i64; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseBigIntError { + kind: BigIntErrorKind, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum BigIntErrorKind { + Empty, + InvalidDigit, +} + +impl ParseBigIntError { + fn __description(&self) -> &str { + use crate::BigIntErrorKind::*; + match self.kind { + Empty => "cannot parse integer from empty string", + InvalidDigit => "invalid digit found in string", + } + } + + fn empty() -> Self { + ParseBigIntError { + kind: BigIntErrorKind::Empty, + } + } + + fn invalid() -> Self { + ParseBigIntError { + kind: BigIntErrorKind::InvalidDigit, + } + } +} + +impl fmt::Display for ParseBigIntError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.__description().fmt(f) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for ParseBigIntError { + fn description(&self) -> &str { + self.__description() + } +} + +/// The error type returned when a checked conversion regarding big integer fails. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TryFromBigIntError { + original: T, +} + +impl TryFromBigIntError { + fn new(original: T) -> Self { + TryFromBigIntError { original } + } + + fn __description(&self) -> &str { + "out of range conversion regarding big integer attempted" + } + + /// Extract the original value, if available. The value will be available + /// if the type before conversion was either [`BigInt`] or [`BigUint`]. + pub fn into_original(self) -> T { + self.original + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for TryFromBigIntError +where + T: fmt::Debug, +{ + fn description(&self) -> &str { + self.__description() + } +} + +impl fmt::Display for TryFromBigIntError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.__description().fmt(f) + } +} + +pub use crate::biguint::BigUint; +pub use crate::biguint::ToBigUint; +pub use crate::biguint::U32Digits; +pub use crate::biguint::U64Digits; + +pub use crate::bigint::BigInt; +pub use crate::bigint::Sign; +pub use crate::bigint::ToBigInt; + +#[cfg(feature = "rand")] +#[cfg_attr(docsrs, doc(cfg(feature = "rand")))] +pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; + +mod big_digit { + // A [`BigDigit`] is a [`BigUint`]'s composing element. + cfg_digit!( + pub(crate) type BigDigit = u32; + pub(crate) type BigDigit = u64; + ); + + // A [`DoubleBigDigit`] is the internal type used to do the computations. Its + // size is the double of the size of [`BigDigit`]. + cfg_digit!( + pub(crate) type DoubleBigDigit = u64; + pub(crate) type DoubleBigDigit = u128; + ); + + pub(crate) const BITS: u8 = BigDigit::BITS as u8; + pub(crate) const HALF_BITS: u8 = BITS / 2; + pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1; + + pub(crate) const MAX: BigDigit = BigDigit::MAX; + const LO_MASK: DoubleBigDigit = MAX as DoubleBigDigit; + + #[inline] + fn get_hi(n: DoubleBigDigit) -> BigDigit { + (n >> BITS) as BigDigit + } + #[inline] + fn get_lo(n: DoubleBigDigit) -> BigDigit { + (n & LO_MASK) as BigDigit + } + + /// Split one [`DoubleBigDigit`] into two [`BigDigit`]s. + #[inline] + pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { + (get_hi(n), get_lo(n)) + } + + /// Join two [`BigDigit`]s into one [`DoubleBigDigit`]. + #[inline] + pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { + DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/src/macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/src/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,473 @@ +#![allow(unused_macros)] + +macro_rules! cfg_32 { + ($($any:tt)+) => { + #[cfg(not(target_pointer_width = "64"))] $($any)+ + } +} + +macro_rules! cfg_32_or_test { + ($($any:tt)+) => { + #[cfg(any(not(target_pointer_width = "64"), test))] $($any)+ + } +} + +macro_rules! cfg_64 { + ($($any:tt)+) => { + #[cfg(target_pointer_width = "64")] $($any)+ + } +} + +macro_rules! cfg_digit { + ($item32:item $item64:item) => { + cfg_32!($item32); + cfg_64!($item64); + }; +} + +macro_rules! cfg_digit_expr { + ($expr32:expr, $expr64:expr) => { + cfg_32!($expr32); + cfg_64!($expr64); + }; +} + +macro_rules! forward_val_val_binop { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<$res> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + // forward to val-ref + $imp::$method(self, &other) + } + } + }; +} + +macro_rules! forward_val_val_binop_commutative { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<$res> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + // forward to val-ref, with the larger capacity as val + if self.capacity() >= other.capacity() { + $imp::$method(self, &other) + } else { + $imp::$method(other, &self) + } + } + } + }; +} + +macro_rules! forward_ref_val_binop { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<$res> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + // forward to ref-ref + $imp::$method(self, &other) + } + } + }; +} + +macro_rules! forward_ref_val_binop_commutative { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<$res> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + // reverse, forward to val-ref + $imp::$method(other, self) + } + } + }; +} + +macro_rules! forward_val_ref_binop { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<&$res> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + // forward to ref-ref + $imp::$method(&self, other) + } + } + }; +} + +macro_rules! forward_ref_ref_binop { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<&$res> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + // forward to val-ref + $imp::$method(self.clone(), other) + } + } + }; +} + +macro_rules! forward_ref_ref_binop_commutative { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<&$res> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + // forward to val-ref, choosing the larger to clone + if self.len() >= other.len() { + $imp::$method(self.clone(), other) + } else { + $imp::$method(other.clone(), self) + } + } + } + }; +} + +macro_rules! forward_val_assign { + (impl $imp:ident for $res:ty, $method:ident) => { + impl $imp<$res> for $res { + #[inline] + fn $method(&mut self, other: $res) { + self.$method(&other); + } + } + }; +} + +macro_rules! forward_val_assign_scalar { + (impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => { + impl $imp<$res> for $scalar { + #[inline] + fn $method(&mut self, other: $res) { + self.$method(&other); + } + } + }; +} + +/// use this if val_val_binop is already implemented and the reversed order is required +macro_rules! forward_scalar_val_val_binop_commutative { + (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { + impl $imp<$res> for $scalar { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + $imp::$method(other, self) + } + } + }; +} + +// Forward scalar to ref-val, when reusing storage is not helpful +macro_rules! forward_scalar_val_val_binop_to_ref_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + impl $imp<$scalar> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: $scalar) -> $res { + $imp::$method(&self, other) + } + } + + impl $imp<$res> for $scalar { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + $imp::$method(self, &other) + } + } + }; +} + +macro_rules! forward_scalar_ref_ref_binop_to_ref_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + impl $imp<&$scalar> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: &$scalar) -> $res { + $imp::$method(self, *other) + } + } + + impl $imp<&$res> for &$scalar { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + $imp::$method(*self, other) + } + } + }; +} + +macro_rules! forward_scalar_val_ref_binop_to_ref_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + impl $imp<&$scalar> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: &$scalar) -> $res { + $imp::$method(&self, *other) + } + } + + impl $imp<$res> for &$scalar { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + $imp::$method(*self, &other) + } + } + }; +} + +macro_rules! forward_scalar_val_ref_binop_to_val_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + impl $imp<&$scalar> for $res { + type Output = $res; + + #[inline] + fn $method(self, other: &$scalar) -> $res { + $imp::$method(self, *other) + } + } + + impl $imp<$res> for &$scalar { + type Output = $res; + + #[inline] + fn $method(self, other: $res) -> $res { + $imp::$method(*self, other) + } + } + }; +} + +macro_rules! forward_scalar_ref_val_binop_to_val_val { + (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { + impl $imp<$scalar> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: $scalar) -> $res { + $imp::$method(self.clone(), other) + } + } + + impl $imp<&$res> for $scalar { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + $imp::$method(self, other.clone()) + } + } + }; +} + +macro_rules! forward_scalar_ref_ref_binop_to_val_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + impl $imp<&$scalar> for &$res { + type Output = $res; + + #[inline] + fn $method(self, other: &$scalar) -> $res { + $imp::$method(self.clone(), *other) + } + } + + impl $imp<&$res> for &$scalar { + type Output = $res; + + #[inline] + fn $method(self, other: &$res) -> $res { + $imp::$method(*self, other.clone()) + } + } + }; +} + +macro_rules! promote_scalars { + (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { + $( + forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); + + impl $imp<$scalar> for $res { + type Output = $res; + + #[allow(clippy::cast_lossless)] + #[inline] + fn $method(self, other: $scalar) -> $res { + $imp::$method(self, other as $promo) + } + } + + impl $imp<$res> for $scalar { + type Output = $res; + + #[allow(clippy::cast_lossless)] + #[inline] + fn $method(self, other: $res) -> $res { + $imp::$method(self as $promo, other) + } + } + )* + } +} +macro_rules! promote_scalars_assign { + (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { + $( + impl $imp<$scalar> for $res { + #[allow(clippy::cast_lossless)] + #[inline] + fn $method(&mut self, other: $scalar) { + self.$method(other as $promo); + } + } + )* + } +} + +macro_rules! promote_unsigned_scalars { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_scalars!(impl $imp for $res, $method, u8, u16); + promote_scalars!(impl $imp for $res, $method, usize); + } +} + +macro_rules! promote_unsigned_scalars_assign { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_scalars_assign!(impl $imp for $res, $method, u8, u16); + promote_scalars_assign!(impl $imp for $res, $method, usize); + } +} + +macro_rules! promote_signed_scalars { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_scalars!(impl $imp for $res, $method, i8, i16); + promote_scalars!(impl $imp for $res, $method, isize); + } +} + +macro_rules! promote_signed_scalars_assign { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_scalars_assign!(impl $imp for $res, $method, i8, i16); + promote_scalars_assign!(impl $imp for $res, $method, isize); + } +} + +// Forward everything to ref-ref, when reusing storage is not helpful +macro_rules! forward_all_binop_to_ref_ref { + (impl $imp:ident for $res:ty, $method:ident) => { + forward_val_val_binop!(impl $imp for $res, $method); + forward_val_ref_binop!(impl $imp for $res, $method); + forward_ref_val_binop!(impl $imp for $res, $method); + }; +} + +// Forward everything to val-ref, so LHS storage can be reused +macro_rules! forward_all_binop_to_val_ref { + (impl $imp:ident for $res:ty, $method:ident) => { + forward_val_val_binop!(impl $imp for $res, $method); + forward_ref_val_binop!(impl $imp for $res, $method); + forward_ref_ref_binop!(impl $imp for $res, $method); + }; +} + +// Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused +macro_rules! forward_all_binop_to_val_ref_commutative { + (impl $imp:ident for $res:ty, $method:ident) => { + forward_val_val_binop_commutative!(impl $imp for $res, $method); + forward_ref_val_binop_commutative!(impl $imp for $res, $method); + forward_ref_ref_binop_commutative!(impl $imp for $res, $method); + }; +} + +macro_rules! forward_all_scalar_binop_to_ref_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + forward_scalar_val_val_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); + forward_scalar_val_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); + forward_scalar_ref_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); + } +} + +macro_rules! forward_all_scalar_binop_to_val_val { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + forward_scalar_val_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method); + forward_scalar_ref_val_binop_to_val_val!(impl $imp<$scalar> for $res, $method); + forward_scalar_ref_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method); + } +} + +macro_rules! forward_all_scalar_binop_to_val_val_commutative { + (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { + forward_scalar_val_val_binop_commutative!(impl $imp<$scalar> for $res, $method); + forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); + } +} + +macro_rules! promote_all_scalars { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_unsigned_scalars!(impl $imp for $res, $method); + promote_signed_scalars!(impl $imp for $res, $method); + } +} + +macro_rules! promote_all_scalars_assign { + (impl $imp:ident for $res:ty, $method:ident) => { + promote_unsigned_scalars_assign!(impl $imp for $res, $method); + promote_signed_scalars_assign!(impl $imp for $res, $method); + } +} + +macro_rules! impl_sum_iter_type { + ($res:ty) => { + impl Sum for $res + where + $res: Add, + { + fn sum(iter: I) -> Self + where + I: Iterator, + { + iter.fold(Self::ZERO, <$res>::add) + } + } + }; +} + +macro_rules! impl_product_iter_type { + ($res:ty) => { + impl Product for $res + where + $res: Mul, + { + fn product(iter: I) -> Self + where + I: Iterator, + { + iter.fold(One::one(), <$res>::mul) + } + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1475 @@ +use num_bigint::BigUint; +use num_bigint::Sign::{Minus, NoSign, Plus}; +use num_bigint::{BigInt, ToBigInt}; + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::collections::hash_map::RandomState; +use std::hash::{BuildHasher, Hash, Hasher}; +use std::iter::repeat; +use std::ops::Neg; +use std::{f32, f64}; + +use num_integer::Integer; +use num_traits::{ + pow, Euclid, FromBytes, FromPrimitive, Num, One, Pow, Signed, ToBytes, ToPrimitive, Zero, +}; + +mod consts; +use crate::consts::*; + +#[macro_use] +mod macros; + +#[test] +fn test_from_bytes_be() { + fn check(s: &str, result: &str) { + assert_eq!( + BigInt::from_bytes_be(Plus, s.as_bytes()), + BigInt::parse_bytes(result.as_bytes(), 10).unwrap() + ); + } + check("A", "65"); + check("AA", "16705"); + check("AB", "16706"); + check("Hello world!", "22405534230753963835153736737"); + assert_eq!(BigInt::from_bytes_be(Plus, &[]), BigInt::zero()); + assert_eq!(BigInt::from_bytes_be(Minus, &[]), BigInt::zero()); +} + +#[test] +fn test_to_bytes_be() { + fn check(s: &str, result: &str) { + let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); + let (sign, v) = b.to_bytes_be(); + assert_eq!((Plus, s.as_bytes()), (sign, &*v)); + } + check("A", "65"); + check("AA", "16705"); + check("AB", "16706"); + check("Hello world!", "22405534230753963835153736737"); + let b: BigInt = Zero::zero(); + assert_eq!(b.to_bytes_be(), (NoSign, vec![0])); + + // Test with leading/trailing zero bytes and a full BigDigit of value 0 + let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); + assert_eq!(b.to_bytes_be(), (Plus, vec![1, 0, 0, 0, 0, 0, 0, 2, 0])); +} + +#[test] +fn test_from_bytes_le() { + fn check(s: &str, result: &str) { + assert_eq!( + BigInt::from_bytes_le(Plus, s.as_bytes()), + BigInt::parse_bytes(result.as_bytes(), 10).unwrap() + ); + } + check("A", "65"); + check("AA", "16705"); + check("BA", "16706"); + check("!dlrow olleH", "22405534230753963835153736737"); + assert_eq!(BigInt::from_bytes_le(Plus, &[]), BigInt::zero()); + assert_eq!(BigInt::from_bytes_le(Minus, &[]), BigInt::zero()); +} + +#[test] +fn test_to_bytes_le() { + fn check(s: &str, result: &str) { + let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); + let (sign, v) = b.to_bytes_le(); + assert_eq!((Plus, s.as_bytes()), (sign, &*v)); + } + check("A", "65"); + check("AA", "16705"); + check("BA", "16706"); + check("!dlrow olleH", "22405534230753963835153736737"); + let b: BigInt = Zero::zero(); + assert_eq!(b.to_bytes_le(), (NoSign, vec![0])); + + // Test with leading/trailing zero bytes and a full BigDigit of value 0 + let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); + assert_eq!(b.to_bytes_le(), (Plus, vec![0, 2, 0, 0, 0, 0, 0, 0, 1])); +} + +#[test] +fn test_to_signed_bytes_le() { + fn check(s: &str, result: Vec) { + let b = BigInt::parse_bytes(s.as_bytes(), 10).unwrap(); + assert_eq!(b.to_signed_bytes_le(), result); + assert_eq!(::to_le_bytes(&b), result); + } + + check("0", vec![0]); + check("32767", vec![0xff, 0x7f]); + check("-1", vec![0xff]); + check("16777216", vec![0, 0, 0, 1]); + check("-100", vec![156]); + check("-8388608", vec![0, 0, 0x80]); + check("-192", vec![0x40, 0xff]); + check("128", vec![0x80, 0]) +} + +#[test] +fn test_from_signed_bytes_le() { + fn check(s: &[u8], result: &str) { + let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(BigInt::from_signed_bytes_le(s), b); + assert_eq!(::from_le_bytes(s), b); + } + + check(&[], "0"); + check(&[0], "0"); + check(&[0; 10], "0"); + check(&[0xff, 0x7f], "32767"); + check(&[0xff], "-1"); + check(&[0, 0, 0, 1], "16777216"); + check(&[156], "-100"); + check(&[0, 0, 0x80], "-8388608"); + check(&[0xff; 10], "-1"); + check(&[0x40, 0xff], "-192"); +} + +#[test] +fn test_to_signed_bytes_be() { + fn check(s: &str, result: Vec) { + let b = BigInt::parse_bytes(s.as_bytes(), 10).unwrap(); + assert_eq!(b.to_signed_bytes_be(), result); + assert_eq!(::to_be_bytes(&b), result); + } + + check("0", vec![0]); + check("32767", vec![0x7f, 0xff]); + check("-1", vec![255]); + check("16777216", vec![1, 0, 0, 0]); + check("-100", vec![156]); + check("-8388608", vec![128, 0, 0]); + check("-192", vec![0xff, 0x40]); + check("128", vec![0, 0x80]); +} + +#[test] +fn test_from_signed_bytes_be() { + fn check(s: &[u8], result: &str) { + let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(BigInt::from_signed_bytes_be(s), b); + assert_eq!(::from_be_bytes(s), b); + } + + check(&[], "0"); + check(&[0], "0"); + check(&[0; 10], "0"); + check(&[127, 255], "32767"); + check(&[255], "-1"); + check(&[1, 0, 0, 0], "16777216"); + check(&[156], "-100"); + check(&[128, 0, 0], "-8388608"); + check(&[255; 10], "-1"); + check(&[0xff, 0x40], "-192"); +} + +#[test] +fn test_signed_bytes_be_round_trip() { + for i in -0x1FFFF..0x20000 { + let n = BigInt::from(i); + assert_eq!(n, BigInt::from_signed_bytes_be(&n.to_signed_bytes_be())); + } +} + +#[test] +fn test_signed_bytes_le_round_trip() { + for i in -0x1FFFF..0x20000 { + let n = BigInt::from(i); + assert_eq!(n, BigInt::from_signed_bytes_le(&n.to_signed_bytes_le())); + } +} + +#[test] +fn test_cmp() { + let vs: [&[u32]; 4] = [&[2_u32], &[1, 1], &[2, 1], &[1, 1, 1]]; + let mut nums = Vec::new(); + for s in vs.iter().rev() { + nums.push(BigInt::from_slice(Minus, *s)); + } + nums.push(Zero::zero()); + nums.extend(vs.iter().map(|s| BigInt::from_slice(Plus, *s))); + + for (i, ni) in nums.iter().enumerate() { + for (j0, nj) in nums[i..].iter().enumerate() { + let j = i + j0; + if i == j { + assert_eq!(ni.cmp(nj), Equal); + assert_eq!(nj.cmp(ni), Equal); + assert_eq!(ni, nj); + assert!(!(ni != nj)); + assert!(ni <= nj); + assert!(ni >= nj); + assert!(!(ni < nj)); + assert!(!(ni > nj)); + } else { + assert_eq!(ni.cmp(nj), Less); + assert_eq!(nj.cmp(ni), Greater); + + assert!(!(ni == nj)); + assert!(ni != nj); + + assert!(ni <= nj); + assert!(!(ni >= nj)); + assert!(ni < nj); + assert!(!(ni > nj)); + + assert!(!(nj <= ni)); + assert!(nj >= ni); + assert!(!(nj < ni)); + assert!(nj > ni); + } + } + } +} + +fn hash(x: &T) -> u64 { + let mut hasher = ::Hasher::new(); + x.hash(&mut hasher); + hasher.finish() +} + +#[test] +fn test_hash() { + let a = BigInt::new(NoSign, vec![]); + let b = BigInt::new(NoSign, vec![0]); + let c = BigInt::new(Plus, vec![1]); + let d = BigInt::new(Plus, vec![1, 0, 0, 0, 0, 0]); + let e = BigInt::new(Plus, vec![0, 0, 0, 0, 0, 1]); + let f = BigInt::new(Minus, vec![1]); + assert!(hash(&a) == hash(&b)); + assert!(hash(&b) != hash(&c)); + assert!(hash(&c) == hash(&d)); + assert!(hash(&d) != hash(&e)); + assert!(hash(&c) != hash(&f)); +} + +#[test] +fn test_convert_i64() { + fn check(b1: BigInt, i: i64) { + let b2: BigInt = FromPrimitive::from_i64(i).unwrap(); + assert!(b1 == b2); + assert!(b1.to_i64().unwrap() == i); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(i64::MIN.to_bigint().unwrap(), i64::MIN); + check(i64::MAX.to_bigint().unwrap(), i64::MAX); + + assert_eq!((i64::MAX as u64 + 1).to_bigint().unwrap().to_i64(), None); + + assert_eq!( + BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i64(), + None + ); + + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 0, 0, 1 << 31])).to_i64(), + None + ); + + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i64(), + None + ); +} + +#[test] +fn test_convert_i128() { + fn check(b1: BigInt, i: i128) { + let b2: BigInt = FromPrimitive::from_i128(i).unwrap(); + assert!(b1 == b2); + assert!(b1.to_i128().unwrap() == i); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(i128::MIN.to_bigint().unwrap(), i128::MIN); + check(i128::MAX.to_bigint().unwrap(), i128::MAX); + + assert_eq!((i128::MAX as u128 + 1).to_bigint().unwrap().to_i128(), None); + + assert_eq!( + BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i128(), + None + ); + + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 0, 0, 1 << 31])).to_i128(), + None + ); + + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i128(), + None + ); +} + +#[test] +fn test_convert_u64() { + fn check(b1: BigInt, u: u64) { + let b2: BigInt = FromPrimitive::from_u64(u).unwrap(); + assert!(b1 == b2); + assert!(b1.to_u64().unwrap() == u); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(u64::MIN.to_bigint().unwrap(), u64::MIN); + check(u64::MAX.to_bigint().unwrap(), u64::MAX); + + assert_eq!( + BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u64(), + None + ); + + let max_value: BigUint = FromPrimitive::from_u64(u64::MAX).unwrap(); + assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None); + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u64(), + None + ); +} + +#[test] +fn test_convert_u128() { + fn check(b1: BigInt, u: u128) { + let b2: BigInt = FromPrimitive::from_u128(u).unwrap(); + assert!(b1 == b2); + assert!(b1.to_u128().unwrap() == u); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(u128::MIN.to_bigint().unwrap(), u128::MIN); + check(u128::MAX.to_bigint().unwrap(), u128::MAX); + + assert_eq!( + BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u128(), + None + ); + + let max_value: BigUint = FromPrimitive::from_u128(u128::MAX).unwrap(); + assert_eq!(BigInt::from_biguint(Minus, max_value).to_u128(), None); + assert_eq!( + BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u128(), + None + ); +} + +#[test] +#[allow(clippy::float_cmp)] +fn test_convert_f32() { + fn check(b1: &BigInt, f: f32) { + let b2 = BigInt::from_f32(f).unwrap(); + assert_eq!(b1, &b2); + assert_eq!(b1.to_f32().unwrap(), f); + let neg_b1 = -b1; + let neg_b2 = BigInt::from_f32(-f).unwrap(); + assert_eq!(neg_b1, neg_b2); + assert_eq!(neg_b1.to_f32().unwrap(), -f); + } + + check(&BigInt::zero(), 0.0); + check(&BigInt::one(), 1.0); + check(&BigInt::from(u16::MAX), pow(2.0_f32, 16) - 1.0); + check(&BigInt::from(1u64 << 32), pow(2.0_f32, 32)); + check(&BigInt::from_slice(Plus, &[0, 0, 1]), pow(2.0_f32, 64)); + check( + &((BigInt::one() << 100) + (BigInt::one() << 123)), + pow(2.0_f32, 100) + pow(2.0_f32, 123), + ); + check(&(BigInt::one() << 127), pow(2.0_f32, 127)); + check(&(BigInt::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); + + // keeping all 24 digits with the bits at different offsets to the BigDigits + let x: u32 = 0b00000000101111011111011011011101; + let mut f = x as f32; + let mut b = BigInt::from(x); + for _ in 0..64 { + check(&b, f); + f *= 2.0; + b <<= 1; + } + + // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 + let mut n: i64 = 0b0000000000111111111111111111111111011111111111111111111111111111; + assert!((n as f64) as f32 != n as f32); + assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); + n = -n; + assert!((n as f64) as f32 != n as f32); + assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); + + // test rounding up with the bits at different offsets to the BigDigits + let mut f = ((1u64 << 25) - 1) as f32; + let mut b = BigInt::from(1u64 << 25); + for _ in 0..64 { + assert_eq!(b.to_f32(), Some(f)); + f *= 2.0; + b <<= 1; + } + + // test correct ties-to-even rounding + let weird: i128 = (1i128 << 100) + (1i128 << (100 - f32::MANTISSA_DIGITS)); + assert_ne!(weird as f32, (weird + 1) as f32); + + assert_eq!(BigInt::from(weird).to_f32(), Some(weird as f32)); + assert_eq!(BigInt::from(weird + 1).to_f32(), Some((weird + 1) as f32)); + + // rounding + assert_eq!( + BigInt::from_f32(-f32::consts::PI), + Some(BigInt::from(-3i32)) + ); + assert_eq!(BigInt::from_f32(-f32::consts::E), Some(BigInt::from(-2i32))); + assert_eq!(BigInt::from_f32(-0.99999), Some(BigInt::zero())); + assert_eq!(BigInt::from_f32(-0.5), Some(BigInt::zero())); + assert_eq!(BigInt::from_f32(-0.0), Some(BigInt::zero())); + assert_eq!( + BigInt::from_f32(f32::MIN_POSITIVE / 2.0), + Some(BigInt::zero()) + ); + assert_eq!(BigInt::from_f32(f32::MIN_POSITIVE), Some(BigInt::zero())); + assert_eq!(BigInt::from_f32(0.5), Some(BigInt::zero())); + assert_eq!(BigInt::from_f32(0.99999), Some(BigInt::zero())); + assert_eq!(BigInt::from_f32(f32::consts::E), Some(BigInt::from(2u32))); + assert_eq!(BigInt::from_f32(f32::consts::PI), Some(BigInt::from(3u32))); + + // special float values + assert_eq!(BigInt::from_f32(f32::NAN), None); + assert_eq!(BigInt::from_f32(f32::INFINITY), None); + assert_eq!(BigInt::from_f32(f32::NEG_INFINITY), None); + + // largest BigInt that will round to a finite f32 value + let big_num = (BigInt::one() << 128u8) - 1u8 - (BigInt::one() << (128u8 - 25)); + assert_eq!(big_num.to_f32(), Some(f32::MAX)); + assert_eq!((&big_num + 1u8).to_f32(), Some(f32::INFINITY)); + assert_eq!((-&big_num).to_f32(), Some(f32::MIN)); + assert_eq!(((-&big_num) - 1u8).to_f32(), Some(f32::NEG_INFINITY)); + + assert_eq!( + ((BigInt::one() << 128u8) - 1u8).to_f32(), + Some(f32::INFINITY) + ); + assert_eq!((BigInt::one() << 128u8).to_f32(), Some(f32::INFINITY)); + assert_eq!( + (-((BigInt::one() << 128u8) - 1u8)).to_f32(), + Some(f32::NEG_INFINITY) + ); + assert_eq!( + (-(BigInt::one() << 128u8)).to_f32(), + Some(f32::NEG_INFINITY) + ); +} + +#[test] +#[allow(clippy::float_cmp)] +fn test_convert_f64() { + fn check(b1: &BigInt, f: f64) { + let b2 = BigInt::from_f64(f).unwrap(); + assert_eq!(b1, &b2); + assert_eq!(b1.to_f64().unwrap(), f); + let neg_b1 = -b1; + let neg_b2 = BigInt::from_f64(-f).unwrap(); + assert_eq!(neg_b1, neg_b2); + assert_eq!(neg_b1.to_f64().unwrap(), -f); + } + + check(&BigInt::zero(), 0.0); + check(&BigInt::one(), 1.0); + check(&BigInt::from(u32::MAX), pow(2.0_f64, 32) - 1.0); + check(&BigInt::from(1u64 << 32), pow(2.0_f64, 32)); + check(&BigInt::from_slice(Plus, &[0, 0, 1]), pow(2.0_f64, 64)); + check( + &((BigInt::one() << 100) + (BigInt::one() << 152)), + pow(2.0_f64, 100) + pow(2.0_f64, 152), + ); + check(&(BigInt::one() << 1023), pow(2.0_f64, 1023)); + check(&(BigInt::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); + + // keeping all 53 digits with the bits at different offsets to the BigDigits + let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; + let mut f = x as f64; + let mut b = BigInt::from(x); + for _ in 0..128 { + check(&b, f); + f *= 2.0; + b <<= 1; + } + + // test rounding up with the bits at different offsets to the BigDigits + let mut f = ((1u64 << 54) - 1) as f64; + let mut b = BigInt::from(1u64 << 54); + for _ in 0..128 { + assert_eq!(b.to_f64(), Some(f)); + f *= 2.0; + b <<= 1; + } + + // test correct ties-to-even rounding + let weird: i128 = (1i128 << 100) + (1i128 << (100 - f64::MANTISSA_DIGITS)); + assert_ne!(weird as f64, (weird + 1) as f64); + + assert_eq!(BigInt::from(weird).to_f64(), Some(weird as f64)); + assert_eq!(BigInt::from(weird + 1).to_f64(), Some((weird + 1) as f64)); + + // rounding + assert_eq!( + BigInt::from_f64(-f64::consts::PI), + Some(BigInt::from(-3i32)) + ); + assert_eq!(BigInt::from_f64(-f64::consts::E), Some(BigInt::from(-2i32))); + assert_eq!(BigInt::from_f64(-0.99999), Some(BigInt::zero())); + assert_eq!(BigInt::from_f64(-0.5), Some(BigInt::zero())); + assert_eq!(BigInt::from_f64(-0.0), Some(BigInt::zero())); + assert_eq!( + BigInt::from_f64(f64::MIN_POSITIVE / 2.0), + Some(BigInt::zero()) + ); + assert_eq!(BigInt::from_f64(f64::MIN_POSITIVE), Some(BigInt::zero())); + assert_eq!(BigInt::from_f64(0.5), Some(BigInt::zero())); + assert_eq!(BigInt::from_f64(0.99999), Some(BigInt::zero())); + assert_eq!(BigInt::from_f64(f64::consts::E), Some(BigInt::from(2u32))); + assert_eq!(BigInt::from_f64(f64::consts::PI), Some(BigInt::from(3u32))); + + // special float values + assert_eq!(BigInt::from_f64(f64::NAN), None); + assert_eq!(BigInt::from_f64(f64::INFINITY), None); + assert_eq!(BigInt::from_f64(f64::NEG_INFINITY), None); + + // largest BigInt that will round to a finite f64 value + let big_num = (BigInt::one() << 1024u16) - 1u8 - (BigInt::one() << (1024u16 - 54)); + assert_eq!(big_num.to_f64(), Some(f64::MAX)); + assert_eq!((&big_num + 1u8).to_f64(), Some(f64::INFINITY)); + assert_eq!((-&big_num).to_f64(), Some(f64::MIN)); + assert_eq!(((-&big_num) - 1u8).to_f64(), Some(f64::NEG_INFINITY)); + + assert_eq!( + ((BigInt::one() << 1024u16) - 1u8).to_f64(), + Some(f64::INFINITY) + ); + assert_eq!((BigInt::one() << 1024u16).to_f64(), Some(f64::INFINITY)); + assert_eq!( + (-((BigInt::one() << 1024u16) - 1u8)).to_f64(), + Some(f64::NEG_INFINITY) + ); + assert_eq!( + (-(BigInt::one() << 1024u16)).to_f64(), + Some(f64::NEG_INFINITY) + ); +} + +#[test] +fn test_convert_to_biguint() { + fn check(n: BigInt, ans_1: BigUint) { + assert_eq!(n.to_biguint().unwrap(), ans_1); + assert_eq!(n.to_biguint().unwrap().to_bigint().unwrap(), n); + } + let zero: BigInt = Zero::zero(); + let unsigned_zero: BigUint = Zero::zero(); + let positive = BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3])); + let negative = -&positive; + + check(zero, unsigned_zero); + check(positive, BigUint::new(vec![1, 2, 3])); + + assert_eq!(negative.to_biguint(), None); +} + +#[test] +fn test_convert_from_uint() { + macro_rules! check { + ($ty:ident, $max:expr) => { + assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); + assert_eq!(BigInt::from($ty::one()), BigInt::one()); + assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); + assert_eq!(BigInt::from($ty::MAX), $max); + }; + } + + check!(u8, BigInt::from_slice(Plus, &[u8::MAX as u32])); + check!(u16, BigInt::from_slice(Plus, &[u16::MAX as u32])); + check!(u32, BigInt::from_slice(Plus, &[u32::MAX])); + check!(u64, BigInt::from_slice(Plus, &[u32::MAX, u32::MAX])); + check!( + u128, + BigInt::from_slice(Plus, &[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) + ); + check!(usize, BigInt::from(usize::MAX as u64)); +} + +#[test] +fn test_convert_from_int() { + macro_rules! check { + ($ty:ident, $min:expr, $max:expr) => { + assert_eq!(BigInt::from($ty::MIN), $min); + assert_eq!(BigInt::from($ty::MIN + $ty::one()), $min + BigInt::one()); + assert_eq!(BigInt::from(-$ty::one()), -BigInt::one()); + assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); + assert_eq!(BigInt::from($ty::one()), BigInt::one()); + assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); + assert_eq!(BigInt::from($ty::MAX), $max); + }; + } + + check!( + i8, + BigInt::from_slice(Minus, &[1 << 7]), + BigInt::from_slice(Plus, &[i8::MAX as u32]) + ); + check!( + i16, + BigInt::from_slice(Minus, &[1 << 15]), + BigInt::from_slice(Plus, &[i16::MAX as u32]) + ); + check!( + i32, + BigInt::from_slice(Minus, &[1 << 31]), + BigInt::from_slice(Plus, &[i32::MAX as u32]) + ); + check!( + i64, + BigInt::from_slice(Minus, &[0, 1 << 31]), + BigInt::from_slice(Plus, &[u32::MAX, i32::MAX as u32]) + ); + check!( + i128, + BigInt::from_slice(Minus, &[0, 0, 0, 1 << 31]), + BigInt::from_slice(Plus, &[u32::MAX, u32::MAX, u32::MAX, i32::MAX as u32]) + ); + check!( + isize, + BigInt::from(isize::MIN as i64), + BigInt::from(isize::MAX as i64) + ); +} + +#[test] +fn test_convert_from_biguint() { + assert_eq!(BigInt::from(BigUint::zero()), BigInt::zero()); + assert_eq!(BigInt::from(BigUint::one()), BigInt::one()); + assert_eq!( + BigInt::from(BigUint::from_slice(&[1, 2, 3])), + BigInt::from_slice(Plus, &[1, 2, 3]) + ); +} + +#[test] +fn test_add() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + assert_op!(a + b == c); + assert_op!(b + a == c); + assert_op!(c + na == b); + assert_op!(c + nb == a); + assert_op!(a + nc == nb); + assert_op!(b + nc == na); + assert_op!(na + nb == nc); + assert_op!(a + na == BigInt::zero()); + + assert_assign_op!(a += b == c); + assert_assign_op!(b += a == c); + assert_assign_op!(c += na == b); + assert_assign_op!(c += nb == a); + assert_assign_op!(a += nc == nb); + assert_assign_op!(b += nc == na); + assert_assign_op!(na += nb == nc); + assert_assign_op!(a += na == BigInt::zero()); + } +} + +#[test] +fn test_sub() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + assert_op!(c - a == b); + assert_op!(c - b == a); + assert_op!(nb - a == nc); + assert_op!(na - b == nc); + assert_op!(b - na == c); + assert_op!(a - nb == c); + assert_op!(nc - na == nb); + assert_op!(a - a == BigInt::zero()); + + assert_assign_op!(c -= a == b); + assert_assign_op!(c -= b == a); + assert_assign_op!(nb -= a == nc); + assert_assign_op!(na -= b == nc); + assert_assign_op!(b -= na == c); + assert_assign_op!(a -= nb == c); + assert_assign_op!(nc -= na == nb); + assert_assign_op!(a -= a == BigInt::zero()); + } +} + +#[test] +fn test_mul() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + assert_op!(a * b == c); + assert_op!(b * a == c); + assert_op!(na * nb == c); + + assert_op!(na * b == nc); + assert_op!(nb * a == nc); + + assert_assign_op!(a *= b == c); + assert_assign_op!(b *= a == c); + assert_assign_op!(na *= nb == c); + + assert_assign_op!(na *= b == nc); + assert_assign_op!(nb *= a == nc); + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + assert!(a == &b * &c + &d); + assert!(a == &c * &b + &d); + } +} + +#[test] +fn test_div_mod_floor() { + fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { + let (d, m) = a.div_mod_floor(b); + assert_eq!(d, a.div_floor(b)); + assert_eq!(m, a.mod_floor(b)); + if !m.is_zero() { + assert_eq!(m.sign(), b.sign()); + } + assert!(m.abs() <= b.abs()); + assert!(*a == b * &d + &m); + assert!(d == *ans_d); + assert!(m == *ans_m); + } + + fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { + if m.is_zero() { + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &d.neg(), m); + check_sub(&a.neg(), b, &d.neg(), m); + check_sub(&a.neg(), &b.neg(), d, m); + } else { + let one: BigInt = One::one(); + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &(d.neg() - &one), &(m - b)); + check_sub(&a.neg(), b, &(d.neg() - &one), &(b - m)); + check_sub(&a.neg(), &b.neg(), d, &m.neg()); + } + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_div_rem() { + fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { + let (q, r) = a.div_rem(b); + if !r.is_zero() { + assert_eq!(r.sign(), a.sign()); + } + assert!(r.abs() <= b.abs()); + assert!(*a == b * &q + &r); + assert!(q == *ans_q); + assert!(r == *ans_r); + + let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); + assert_op!(a / b == ans_q); + assert_op!(a % b == ans_r); + assert_assign_op!(a /= b == ans_q); + assert_assign_op!(a %= b == ans_r); + } + + fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) { + check_sub(a, b, q, r); + check_sub(a, &b.neg(), &q.neg(), r); + check_sub(&a.neg(), b, &q.neg(), &r.neg()); + check_sub(&a.neg(), &b.neg(), q, &r.neg()); + } + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_div_ceil() { + fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt) { + assert_eq!(a.div_ceil(b), *ans_d); + } + + fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { + if m.is_zero() { + check_sub(a, b, d); + check_sub(a, &b.neg(), &d.neg()); + check_sub(&a.neg(), b, &d.neg()); + check_sub(&a.neg(), &b.neg(), d); + } else { + check_sub(a, b, &(d + 1)); + check_sub(a, &b.neg(), &d.neg()); + check_sub(&a.neg(), b, &d.neg()); + check_sub(&a.neg(), &b.neg(), &(d + 1)); + } + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_div_rem_euclid() { + fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { + eprintln!("{} {} {} {}", a, b, ans_d, ans_m); + assert_eq!(a.div_euclid(b), *ans_d); + assert_eq!(a.rem_euclid(b), *ans_m); + assert!(*ans_m >= BigInt::zero()); + assert!(*ans_m < b.abs()); + } + + fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { + if m.is_zero() { + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &d.neg(), m); + check_sub(&a.neg(), b, &d.neg(), m); + check_sub(&a.neg(), &b.neg(), d, m); + } else { + let one: BigInt = One::one(); + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &d.neg(), m); + check_sub(&a.neg(), b, &(d + &one).neg(), &(b - m)); + check_sub(&a.neg(), &b.neg(), &(d + &one), &(b.abs() - m)); + } + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_checked_add() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + assert!(a.checked_add(&b).unwrap() == c); + assert!(b.checked_add(&a).unwrap() == c); + assert!(c.checked_add(&(-&a)).unwrap() == b); + assert!(c.checked_add(&(-&b)).unwrap() == a); + assert!(a.checked_add(&(-&c)).unwrap() == (-&b)); + assert!(b.checked_add(&(-&c)).unwrap() == (-&a)); + assert!((-&a).checked_add(&(-&b)).unwrap() == (-&c)); + assert!(a.checked_add(&(-&a)).unwrap() == BigInt::zero()); + } +} + +#[test] +fn test_checked_sub() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + assert!(c.checked_sub(&a).unwrap() == b); + assert!(c.checked_sub(&b).unwrap() == a); + assert!((-&b).checked_sub(&a).unwrap() == (-&c)); + assert!((-&a).checked_sub(&b).unwrap() == (-&c)); + assert!(b.checked_sub(&(-&a)).unwrap() == c); + assert!(a.checked_sub(&(-&b)).unwrap() == c); + assert!((-&c).checked_sub(&(-&a)).unwrap() == (-&b)); + assert!(a.checked_sub(&a).unwrap() == BigInt::zero()); + } +} + +#[test] +fn test_checked_mul() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + assert!(a.checked_mul(&b).unwrap() == c); + assert!(b.checked_mul(&a).unwrap() == c); + + assert!((-&a).checked_mul(&b).unwrap() == -&c); + assert!((-&b).checked_mul(&a).unwrap() == -&c); + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + assert!(a == b.checked_mul(&c).unwrap() + &d); + assert!(a == c.checked_mul(&b).unwrap() + &d); + } +} +#[test] +fn test_checked_div() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if !a.is_zero() { + assert!(c.checked_div(&a).unwrap() == b); + assert!((-&c).checked_div(&(-&a)).unwrap() == b); + assert!((-&c).checked_div(&a).unwrap() == -&b); + } + if !b.is_zero() { + assert!(c.checked_div(&b).unwrap() == a); + assert!((-&c).checked_div(&(-&b)).unwrap() == a); + assert!((-&c).checked_div(&b).unwrap() == -&a); + } + + assert!(c.checked_div(&Zero::zero()).is_none()); + assert!((-&c).checked_div(&Zero::zero()).is_none()); + } +} + +#[test] +fn test_gcd() { + fn check(a: isize, b: isize, c: isize) { + let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); + let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); + let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); + + assert_eq!(big_a.gcd(&big_b), big_c); + assert_eq!(big_a.extended_gcd(&big_b).gcd, big_c); + assert_eq!(big_a.gcd_lcm(&big_b).0, big_c); + assert_eq!(big_a.extended_gcd_lcm(&big_b).0.gcd, big_c); + } + + check(10, 2, 2); + check(10, 3, 1); + check(0, 3, 3); + check(3, 3, 3); + check(56, 42, 14); + check(3, -3, 3); + check(-6, 3, 3); + check(-4, -2, 2); +} + +#[test] +fn test_lcm() { + fn check(a: isize, b: isize, c: isize) { + let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); + let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); + let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); + + assert_eq!(big_a.lcm(&big_b), big_c); + assert_eq!(big_a.gcd_lcm(&big_b).1, big_c); + assert_eq!(big_a.extended_gcd_lcm(&big_b).1, big_c); + } + + check(0, 0, 0); + check(1, 0, 0); + check(0, 1, 0); + check(1, 1, 1); + check(-1, 1, 1); + check(1, -1, 1); + check(-1, -1, 1); + check(8, 9, 72); + check(11, 5, 55); +} + +#[test] +fn test_is_multiple_of() { + assert!(BigInt::from(0).is_multiple_of(&BigInt::from(0))); + assert!(BigInt::from(6).is_multiple_of(&BigInt::from(6))); + assert!(BigInt::from(6).is_multiple_of(&BigInt::from(3))); + assert!(BigInt::from(6).is_multiple_of(&BigInt::from(1))); + + assert!(!BigInt::from(42).is_multiple_of(&BigInt::from(5))); + assert!(!BigInt::from(5).is_multiple_of(&BigInt::from(3))); + assert!(!BigInt::from(42).is_multiple_of(&BigInt::from(0))); +} + +#[test] +fn test_next_multiple_of() { + assert_eq!( + BigInt::from(16).next_multiple_of(&BigInt::from(8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(23).next_multiple_of(&BigInt::from(8)), + BigInt::from(24) + ); + assert_eq!( + BigInt::from(16).next_multiple_of(&BigInt::from(-8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(23).next_multiple_of(&BigInt::from(-8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(-16).next_multiple_of(&BigInt::from(8)), + BigInt::from(-16) + ); + assert_eq!( + BigInt::from(-23).next_multiple_of(&BigInt::from(8)), + BigInt::from(-16) + ); + assert_eq!( + BigInt::from(-16).next_multiple_of(&BigInt::from(-8)), + BigInt::from(-16) + ); + assert_eq!( + BigInt::from(-23).next_multiple_of(&BigInt::from(-8)), + BigInt::from(-24) + ); +} + +#[test] +fn test_prev_multiple_of() { + assert_eq!( + BigInt::from(16).prev_multiple_of(&BigInt::from(8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(23).prev_multiple_of(&BigInt::from(8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(16).prev_multiple_of(&BigInt::from(-8)), + BigInt::from(16) + ); + assert_eq!( + BigInt::from(23).prev_multiple_of(&BigInt::from(-8)), + BigInt::from(24) + ); + assert_eq!( + BigInt::from(-16).prev_multiple_of(&BigInt::from(8)), + BigInt::from(-16) + ); + assert_eq!( + BigInt::from(-23).prev_multiple_of(&BigInt::from(8)), + BigInt::from(-24) + ); + assert_eq!( + BigInt::from(-16).prev_multiple_of(&BigInt::from(-8)), + BigInt::from(-16) + ); + assert_eq!( + BigInt::from(-23).prev_multiple_of(&BigInt::from(-8)), + BigInt::from(-16) + ); +} + +#[test] +fn test_abs_sub() { + let zero: BigInt = Zero::zero(); + let one: BigInt = One::one(); + assert_eq!((-&one).abs_sub(&one), zero); + let one: BigInt = One::one(); + let zero: BigInt = Zero::zero(); + assert_eq!(one.abs_sub(&one), zero); + let one: BigInt = One::one(); + let zero: BigInt = Zero::zero(); + assert_eq!(one.abs_sub(&zero), one); + let one: BigInt = One::one(); + let two: BigInt = FromPrimitive::from_isize(2).unwrap(); + assert_eq!(one.abs_sub(&-&one), two); +} + +#[test] +fn test_from_str_radix() { + fn check(s: &str, ans: Option) { + let ans = ans.map(|n| { + let x: BigInt = FromPrimitive::from_isize(n).unwrap(); + x + }); + assert_eq!(BigInt::from_str_radix(s, 10).ok(), ans); + } + check("10", Some(10)); + check("1", Some(1)); + check("0", Some(0)); + check("-1", Some(-1)); + check("-10", Some(-10)); + check("+10", Some(10)); + check("--7", None); + check("++5", None); + check("+-9", None); + check("-+3", None); + check("Z", None); + check("_", None); + + // issue 10522, this hit an edge case that caused it to + // attempt to allocate a vector of size (-1u) == huge. + let x: BigInt = format!("1{}", repeat("0").take(36).collect::()) + .parse() + .unwrap(); + let _y = x.to_string(); +} + +#[test] +fn test_lower_hex() { + let a = BigInt::parse_bytes(b"A", 16).unwrap(); + let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:x}", a), "a"); + assert_eq!(format!("{:x}", hello), "-48656c6c6f20776f726c6421"); + assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); +} + +#[test] +fn test_upper_hex() { + let a = BigInt::parse_bytes(b"A", 16).unwrap(); + let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:X}", a), "A"); + assert_eq!(format!("{:X}", hello), "-48656C6C6F20776F726C6421"); + assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); +} + +#[test] +fn test_binary() { + let a = BigInt::parse_bytes(b"A", 16).unwrap(); + let hello = BigInt::parse_bytes(b"-224055342307539", 10).unwrap(); + + assert_eq!(format!("{:b}", a), "1010"); + assert_eq!( + format!("{:b}", hello), + "-110010111100011011110011000101101001100011010011" + ); + assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); +} + +#[test] +fn test_octal() { + let a = BigInt::parse_bytes(b"A", 16).unwrap(); + let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:o}", a), "12"); + assert_eq!(format!("{:o}", hello), "-22062554330674403566756233062041"); + assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); +} + +#[test] +fn test_display() { + let a = BigInt::parse_bytes(b"A", 16).unwrap(); + let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{}", a), "10"); + assert_eq!(format!("{}", hello), "-22405534230753963835153736737"); + assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); +} + +#[test] +fn test_neg() { + assert!(-BigInt::new(Plus, vec![1, 1, 1]) == BigInt::new(Minus, vec![1, 1, 1])); + assert!(-BigInt::new(Minus, vec![1, 1, 1]) == BigInt::new(Plus, vec![1, 1, 1])); + let zero: BigInt = Zero::zero(); + assert_eq!(-&zero, zero); +} + +#[test] +fn test_negative_shr() { + assert_eq!(BigInt::from(-1) >> 1, BigInt::from(-1)); + assert_eq!(BigInt::from(-2) >> 1, BigInt::from(-1)); + assert_eq!(BigInt::from(-3) >> 1, BigInt::from(-2)); + assert_eq!(BigInt::from(-3) >> 2, BigInt::from(-1)); +} + +#[test] +fn test_iter_sum() { + let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); + let data: Vec = vec![ + FromPrimitive::from_i32(-1000000).unwrap(), + FromPrimitive::from_i32(-200000).unwrap(), + FromPrimitive::from_i32(-30000).unwrap(), + FromPrimitive::from_i32(-4000).unwrap(), + FromPrimitive::from_i32(-500).unwrap(), + FromPrimitive::from_i32(-60).unwrap(), + FromPrimitive::from_i32(-7).unwrap(), + ]; + + assert_eq!(result, data.iter().sum::()); + assert_eq!(result, data.into_iter().sum::()); +} + +#[test] +fn test_iter_product() { + let data: Vec = vec![ + FromPrimitive::from_i32(1001).unwrap(), + FromPrimitive::from_i32(-1002).unwrap(), + FromPrimitive::from_i32(1003).unwrap(), + FromPrimitive::from_i32(-1004).unwrap(), + FromPrimitive::from_i32(1005).unwrap(), + ]; + let result = data.get(0).unwrap() + * data.get(1).unwrap() + * data.get(2).unwrap() + * data.get(3).unwrap() + * data.get(4).unwrap(); + + assert_eq!(result, data.iter().product::()); + assert_eq!(result, data.into_iter().product::()); +} + +#[test] +fn test_iter_sum_generic() { + let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); + let data = vec![-1000000, -200000, -30000, -4000, -500, -60, -7]; + + assert_eq!(result, data.iter().sum::()); + assert_eq!(result, data.into_iter().sum::()); +} + +#[test] +fn test_iter_product_generic() { + let data = vec![1001, -1002, 1003, -1004, 1005]; + let result = data[0].to_bigint().unwrap() + * data[1].to_bigint().unwrap() + * data[2].to_bigint().unwrap() + * data[3].to_bigint().unwrap() + * data[4].to_bigint().unwrap(); + + assert_eq!(result, data.iter().product::()); + assert_eq!(result, data.into_iter().product::()); +} + +#[test] +fn test_pow() { + let one = BigInt::from(1i32); + let two = BigInt::from(2i32); + let four = BigInt::from(4i32); + let eight = BigInt::from(8i32); + let minus_two = BigInt::from(-2i32); + macro_rules! check { + ($t:ty) => { + assert_eq!(Pow::pow(&two, 0 as $t), one); + assert_eq!(Pow::pow(&two, 1 as $t), two); + assert_eq!(Pow::pow(&two, 2 as $t), four); + assert_eq!(Pow::pow(&two, 3 as $t), eight); + assert_eq!(Pow::pow(&two, &(3 as $t)), eight); + assert_eq!(Pow::pow(&minus_two, 0 as $t), one, "-2^0"); + assert_eq!(Pow::pow(&minus_two, 1 as $t), minus_two, "-2^1"); + assert_eq!(Pow::pow(&minus_two, 2 as $t), four, "-2^2"); + assert_eq!(Pow::pow(&minus_two, 3 as $t), -&eight, "-2^3"); + }; + } + check!(u8); + check!(u16); + check!(u32); + check!(u64); + check!(usize); + + let pow_1e10000 = BigInt::from(10u32).pow(10_000_u32); + let manual_1e10000 = repeat(10u32).take(10_000).product::(); + assert!(manual_1e10000 == pow_1e10000); +} + +#[test] +fn test_bit() { + // 12 = (1100)_2 + assert!(!BigInt::from(0b1100u8).bit(0)); + assert!(!BigInt::from(0b1100u8).bit(1)); + assert!(BigInt::from(0b1100u8).bit(2)); + assert!(BigInt::from(0b1100u8).bit(3)); + assert!(!BigInt::from(0b1100u8).bit(4)); + assert!(!BigInt::from(0b1100u8).bit(200)); + assert!(!BigInt::from(0b1100u8).bit(u64::MAX)); + // -12 = (...110100)_2 + assert!(!BigInt::from(-12i8).bit(0)); + assert!(!BigInt::from(-12i8).bit(1)); + assert!(BigInt::from(-12i8).bit(2)); + assert!(!BigInt::from(-12i8).bit(3)); + assert!(BigInt::from(-12i8).bit(4)); + assert!(BigInt::from(-12i8).bit(200)); + assert!(BigInt::from(-12i8).bit(u64::MAX)); +} + +#[test] +fn test_set_bit() { + let mut x: BigInt; + + // zero + x = BigInt::zero(); + x.set_bit(200, true); + assert_eq!(x, BigInt::one() << 200); + x = BigInt::zero(); + x.set_bit(200, false); + assert_eq!(x, BigInt::zero()); + + // positive numbers + x = BigInt::from_biguint(Plus, BigUint::one() << 200); + x.set_bit(10, true); + x.set_bit(200, false); + assert_eq!(x, BigInt::one() << 10); + x.set_bit(10, false); + x.set_bit(5, false); + assert_eq!(x, BigInt::zero()); + + // negative numbers + x = BigInt::from(-12i8); + x.set_bit(200, true); + assert_eq!(x, BigInt::from(-12i8)); + x.set_bit(200, false); + assert_eq!( + x, + BigInt::from_biguint(Minus, BigUint::from(12u8) | (BigUint::one() << 200)) + ); + x.set_bit(6, false); + assert_eq!( + x, + BigInt::from_biguint(Minus, BigUint::from(76u8) | (BigUint::one() << 200)) + ); + x.set_bit(6, true); + assert_eq!( + x, + BigInt::from_biguint(Minus, BigUint::from(12u8) | (BigUint::one() << 200)) + ); + x.set_bit(200, true); + assert_eq!(x, BigInt::from(-12i8)); + + x = BigInt::from_biguint(Minus, BigUint::one() << 30); + x.set_bit(10, true); + assert_eq!( + x, + BigInt::from_biguint(Minus, (BigUint::one() << 30) - (BigUint::one() << 10)) + ); + + x = BigInt::from_biguint(Minus, BigUint::one() << 200); + x.set_bit(40, true); + assert_eq!( + x, + BigInt::from_biguint(Minus, (BigUint::one() << 200) - (BigUint::one() << 40)) + ); + + x = BigInt::from_biguint(Minus, (BigUint::one() << 200) | (BigUint::one() << 100)); + x.set_bit(100, false); + assert_eq!( + x, + BigInt::from_biguint(Minus, (BigUint::one() << 200) | (BigUint::one() << 101)) + ); + + x = BigInt::from_biguint(Minus, (BigUint::one() << 63) | (BigUint::one() << 62)); + x.set_bit(62, false); + assert_eq!(x, BigInt::from_biguint(Minus, BigUint::one() << 64)); + + x = BigInt::from_biguint(Minus, (BigUint::one() << 200) - BigUint::one()); + x.set_bit(0, false); + assert_eq!(x, BigInt::from_biguint(Minus, BigUint::one() << 200)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint_bitwise.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_bitwise.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint_bitwise.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_bitwise.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,177 @@ +use num_bigint::{BigInt, Sign, ToBigInt}; +use num_traits::ToPrimitive; + +enum ValueVec { + N, + P(&'static [u32]), + M(&'static [u32]), +} + +use crate::ValueVec::*; + +impl ToBigInt for ValueVec { + fn to_bigint(&self) -> Option { + match self { + &N => Some(BigInt::from_slice(Sign::NoSign, &[])), + &P(s) => Some(BigInt::from_slice(Sign::Plus, s)), + &M(s) => Some(BigInt::from_slice(Sign::Minus, s)), + } + } +} + +// a, !a +const NOT_VALUES: &[(ValueVec, ValueVec)] = &[ + (N, M(&[1])), + (P(&[1]), M(&[2])), + (P(&[2]), M(&[3])), + (P(&[!0 - 2]), M(&[!0 - 1])), + (P(&[!0 - 1]), M(&[!0])), + (P(&[!0]), M(&[0, 1])), + (P(&[0, 1]), M(&[1, 1])), + (P(&[1, 1]), M(&[2, 1])), +]; + +// a, b, a & b, a | b, a ^ b +const BITWISE_VALUES: &[(ValueVec, ValueVec, ValueVec, ValueVec, ValueVec)] = &[ + (N, N, N, N, N), + (N, P(&[1]), N, P(&[1]), P(&[1])), + (N, P(&[!0]), N, P(&[!0]), P(&[!0])), + (N, P(&[0, 1]), N, P(&[0, 1]), P(&[0, 1])), + (N, M(&[1]), N, M(&[1]), M(&[1])), + (N, M(&[!0]), N, M(&[!0]), M(&[!0])), + (N, M(&[0, 1]), N, M(&[0, 1]), M(&[0, 1])), + (P(&[1]), P(&[!0]), P(&[1]), P(&[!0]), P(&[!0 - 1])), + (P(&[!0]), P(&[!0]), P(&[!0]), P(&[!0]), N), + (P(&[!0]), P(&[1, 1]), P(&[1]), P(&[!0, 1]), P(&[!0 - 1, 1])), + (P(&[1]), M(&[!0]), P(&[1]), M(&[!0]), M(&[0, 1])), + (P(&[!0]), M(&[1]), P(&[!0]), M(&[1]), M(&[0, 1])), + (P(&[!0]), M(&[!0]), P(&[1]), M(&[1]), M(&[2])), + (P(&[!0]), M(&[1, 1]), P(&[!0]), M(&[1, 1]), M(&[0, 2])), + (P(&[1, 1]), M(&[!0]), P(&[1, 1]), M(&[!0]), M(&[0, 2])), + (M(&[1]), M(&[!0]), M(&[!0]), M(&[1]), P(&[!0 - 1])), + (M(&[!0]), M(&[!0]), M(&[!0]), M(&[!0]), N), + (M(&[!0]), M(&[1, 1]), M(&[!0, 1]), M(&[1]), P(&[!0 - 1, 1])), +]; + +const I32_MIN: i64 = i32::MIN as i64; +const I32_MAX: i64 = i32::MAX as i64; +const U32_MAX: i64 = u32::MAX as i64; + +// some corner cases +const I64_VALUES: &[i64] = &[ + i64::MIN, + i64::MIN + 1, + i64::MIN + 2, + i64::MIN + 3, + -U32_MAX - 3, + -U32_MAX - 2, + -U32_MAX - 1, + -U32_MAX, + -U32_MAX + 1, + -U32_MAX + 2, + -U32_MAX + 3, + I32_MIN - 3, + I32_MIN - 2, + I32_MIN - 1, + I32_MIN, + I32_MIN + 1, + I32_MIN + 2, + I32_MIN + 3, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + I32_MAX - 3, + I32_MAX - 2, + I32_MAX - 1, + I32_MAX, + I32_MAX + 1, + I32_MAX + 2, + I32_MAX + 3, + U32_MAX - 3, + U32_MAX - 2, + U32_MAX - 1, + U32_MAX, + U32_MAX + 1, + U32_MAX + 2, + U32_MAX + 3, + i64::MAX - 3, + i64::MAX - 2, + i64::MAX - 1, + i64::MAX, +]; + +#[test] +fn test_not() { + for &(ref a, ref not) in NOT_VALUES.iter() { + let a = a.to_bigint().unwrap(); + let not = not.to_bigint().unwrap(); + + // sanity check for tests that fit in i64 + if let (Some(prim_a), Some(prim_not)) = (a.to_i64(), not.to_i64()) { + assert_eq!(!prim_a, prim_not); + } + + assert_eq!(!a.clone(), not, "!{:x}", a); + assert_eq!(!not.clone(), a, "!{:x}", not); + } +} + +#[test] +fn test_not_i64() { + for &prim_a in I64_VALUES.iter() { + let a = prim_a.to_bigint().unwrap(); + let not = (!prim_a).to_bigint().unwrap(); + assert_eq!(!a.clone(), not, "!{:x}", a); + } +} + +#[test] +fn test_bitwise() { + for &(ref a, ref b, ref and, ref or, ref xor) in BITWISE_VALUES.iter() { + let a = a.to_bigint().unwrap(); + let b = b.to_bigint().unwrap(); + let and = and.to_bigint().unwrap(); + let or = or.to_bigint().unwrap(); + let xor = xor.to_bigint().unwrap(); + + // sanity check for tests that fit in i64 + if let (Some(prim_a), Some(prim_b)) = (a.to_i64(), b.to_i64()) { + if let Some(prim_and) = and.to_i64() { + assert_eq!(prim_a & prim_b, prim_and); + } + if let Some(prim_or) = or.to_i64() { + assert_eq!(prim_a | prim_b, prim_or); + } + if let Some(prim_xor) = xor.to_i64() { + assert_eq!(prim_a ^ prim_b, prim_xor); + } + } + + assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b); + assert_eq!(b.clone() & &a, and, "{:x} & {:x}", b, a); + assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b); + assert_eq!(b.clone() | &a, or, "{:x} | {:x}", b, a); + assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b); + assert_eq!(b.clone() ^ &a, xor, "{:x} ^ {:x}", b, a); + } +} + +#[test] +fn test_bitwise_i64() { + for &prim_a in I64_VALUES.iter() { + let a = prim_a.to_bigint().unwrap(); + for &prim_b in I64_VALUES.iter() { + let b = prim_b.to_bigint().unwrap(); + let and = (prim_a & prim_b).to_bigint().unwrap(); + let or = (prim_a | prim_b).to_bigint().unwrap(); + let xor = (prim_a ^ prim_b).to_bigint().unwrap(); + assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b); + assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b); + assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint_scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/bigint_scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/bigint_scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,157 @@ +use num_bigint::BigInt; +use num_bigint::Sign::Plus; +use num_traits::{One, Signed, ToPrimitive, Zero}; + +use std::ops::Neg; +use std::panic::catch_unwind; + +mod consts; +use crate::consts::*; + +#[macro_use] +mod macros; + +#[test] +fn test_scalar_add() { + fn check(x: &BigInt, y: &BigInt, z: &BigInt) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_signed_scalar_op!(x + y == z); + assert_signed_scalar_assign_op!(x += y == z); + } + + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + check(&a, &b, &c); + check(&b, &a, &c); + check(&c, &na, &b); + check(&c, &nb, &a); + check(&a, &nc, &nb); + check(&b, &nc, &na); + check(&na, &nb, &nc); + check(&a, &na, &Zero::zero()); + } +} + +#[test] +fn test_scalar_sub() { + fn check(x: &BigInt, y: &BigInt, z: &BigInt) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_signed_scalar_op!(x - y == z); + assert_signed_scalar_assign_op!(x -= y == z); + } + + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + check(&c, &a, &b); + check(&c, &b, &a); + check(&nb, &a, &nc); + check(&na, &b, &nc); + check(&b, &na, &c); + check(&a, &nb, &c); + check(&nc, &na, &nb); + check(&a, &a, &Zero::zero()); + } +} + +#[test] +fn test_scalar_mul() { + fn check(x: &BigInt, y: &BigInt, z: &BigInt) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_signed_scalar_op!(x * y == z); + assert_signed_scalar_assign_op!(x *= y == z); + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + let (na, nb, nc) = (-&a, -&b, -&c); + + check(&a, &b, &c); + check(&b, &a, &c); + check(&na, &nb, &c); + + check(&na, &b, &nc); + check(&nb, &a, &nc); + } +} + +#[test] +fn test_scalar_div_rem() { + fn check_sub(a: &BigInt, b: u32, ans_q: &BigInt, ans_r: &BigInt) { + let (q, r) = (a / b, a % b); + if !r.is_zero() { + assert_eq!(r.sign(), a.sign()); + } + assert!(r.abs() <= BigInt::from(b)); + assert!(*a == b * &q + &r); + assert!(q == *ans_q); + assert!(r == *ans_r); + + let b = BigInt::from(b); + let (a, ans_q, ans_r) = (a.clone(), ans_q.clone(), ans_r.clone()); + assert_signed_scalar_op!(a / b == ans_q); + assert_signed_scalar_op!(a % b == ans_r); + assert_signed_scalar_assign_op!(a /= b == ans_q); + assert_signed_scalar_assign_op!(a %= b == ans_r); + + let nb = -b; + assert_signed_scalar_op!(a / nb == -ans_q.clone()); + assert_signed_scalar_op!(a % nb == ans_r); + assert_signed_scalar_assign_op!(a /= nb == -ans_q.clone()); + assert_signed_scalar_assign_op!(a %= nb == ans_r); + } + + fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) { + check_sub(a, b, q, r); + check_sub(&a.neg(), b, &q.neg(), &r.neg()); + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let b = BigInt::from_slice(Plus, b_vec); + let c = BigInt::from_slice(Plus, c_vec); + + if a_vec.len() == 1 && a_vec[0] != 0 { + let a = a_vec[0]; + check(&c, a, &b, &Zero::zero()); + } + + if b_vec.len() == 1 && b_vec[0] != 0 { + let b = b_vec[0]; + check(&c, b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigInt::from_slice(Plus, a_vec); + let c = BigInt::from_slice(Plus, c_vec); + let d = BigInt::from_slice(Plus, d_vec); + + if b_vec.len() == 1 && b_vec[0] != 0 { + let b = b_vec[0]; + check(&a, b, &c, &d); + } + } +} + +#[test] +fn test_scalar_div_rem_zero() { + catch_unwind(|| BigInt::zero() / 0u32).unwrap_err(); + catch_unwind(|| BigInt::zero() % 0u32).unwrap_err(); + catch_unwind(|| BigInt::one() / 0u32).unwrap_err(); + catch_unwind(|| BigInt::one() % 0u32).unwrap_err(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/biguint.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/biguint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1921 @@ +use num_bigint::Sign::Plus; +use num_bigint::{BigInt, ToBigInt}; +use num_bigint::{BigUint, ToBigUint}; +use num_integer::Integer; + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::collections::hash_map::RandomState; +use std::hash::{BuildHasher, Hash, Hasher}; +use std::iter::repeat; +use std::str::FromStr; +use std::{f32, f64}; + +use num_traits::{ + pow, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Euclid, FromBytes, FromPrimitive, Num, + One, Pow, ToBytes, ToPrimitive, Zero, +}; + +mod consts; +use crate::consts::*; + +#[macro_use] +mod macros; + +#[test] +fn test_from_bytes_be() { + fn check(s: &str, result: &str) { + let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(BigUint::from_bytes_be(s.as_bytes()), b); + assert_eq!(::from_be_bytes(s.as_bytes()), b); + } + check("A", "65"); + check("AA", "16705"); + check("AB", "16706"); + check("Hello world!", "22405534230753963835153736737"); + assert_eq!(BigUint::from_bytes_be(&[]), BigUint::zero()); +} + +#[test] +fn test_to_bytes_be() { + fn check(s: &str, result: &str) { + let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(b.to_bytes_be(), s.as_bytes()); + assert_eq!(::to_be_bytes(&b), s.as_bytes()); + } + check("A", "65"); + check("AA", "16705"); + check("AB", "16706"); + check("Hello world!", "22405534230753963835153736737"); + let b: BigUint = Zero::zero(); + assert_eq!(b.to_bytes_be(), [0]); + + // Test with leading/trailing zero bytes and a full BigDigit of value 0 + let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); + assert_eq!(b.to_bytes_be(), [1, 0, 0, 0, 0, 0, 0, 2, 0]); +} + +#[test] +fn test_from_bytes_le() { + fn check(s: &str, result: &str) { + let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(BigUint::from_bytes_le(s.as_bytes()), b); + assert_eq!(::from_le_bytes(s.as_bytes()), b); + } + check("A", "65"); + check("AA", "16705"); + check("BA", "16706"); + check("!dlrow olleH", "22405534230753963835153736737"); + assert_eq!(BigUint::from_bytes_le(&[]), BigUint::zero()); +} + +#[test] +fn test_to_bytes_le() { + fn check(s: &str, result: &str) { + let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); + assert_eq!(b.to_bytes_le(), s.as_bytes()); + assert_eq!(::to_le_bytes(&b), s.as_bytes()); + } + check("A", "65"); + check("AA", "16705"); + check("BA", "16706"); + check("!dlrow olleH", "22405534230753963835153736737"); + let b: BigUint = Zero::zero(); + assert_eq!(b.to_bytes_le(), [0]); + + // Test with leading/trailing zero bytes and a full BigDigit of value 0 + let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); + assert_eq!(b.to_bytes_le(), [0, 2, 0, 0, 0, 0, 0, 0, 1]); +} + +#[test] +fn test_cmp() { + let data: [&[_]; 7] = [&[], &[1], &[2], &[!0], &[0, 1], &[2, 1], &[1, 1, 1]]; + let data: Vec = data.iter().map(|v| BigUint::from_slice(*v)).collect(); + for (i, ni) in data.iter().enumerate() { + for (j0, nj) in data[i..].iter().enumerate() { + let j = j0 + i; + if i == j { + assert_eq!(ni.cmp(nj), Equal); + assert_eq!(nj.cmp(ni), Equal); + assert_eq!(ni, nj); + assert!(!(ni != nj)); + assert!(ni <= nj); + assert!(ni >= nj); + assert!(!(ni < nj)); + assert!(!(ni > nj)); + } else { + assert_eq!(ni.cmp(nj), Less); + assert_eq!(nj.cmp(ni), Greater); + + assert!(!(ni == nj)); + assert!(ni != nj); + + assert!(ni <= nj); + assert!(!(ni >= nj)); + assert!(ni < nj); + assert!(!(ni > nj)); + + assert!(!(nj <= ni)); + assert!(nj >= ni); + assert!(!(nj < ni)); + assert!(nj > ni); + } + } + } +} + +fn hash(x: &T) -> u64 { + let mut hasher = ::Hasher::new(); + x.hash(&mut hasher); + hasher.finish() +} + +#[test] +fn test_hash() { + use crate::hash; + + let a = BigUint::new(vec![]); + let b = BigUint::new(vec![0]); + let c = BigUint::new(vec![1]); + let d = BigUint::new(vec![1, 0, 0, 0, 0, 0]); + let e = BigUint::new(vec![0, 0, 0, 0, 0, 1]); + assert!(hash(&a) == hash(&b)); + assert!(hash(&b) != hash(&c)); + assert!(hash(&c) == hash(&d)); + assert!(hash(&d) != hash(&e)); +} + +// LEFT, RIGHT, AND, OR, XOR +const BIT_TESTS: &[(&[u32], &[u32], &[u32], &[u32], &[u32])] = &[ + (&[], &[], &[], &[], &[]), + (&[1, 0, 1], &[1, 1], &[1], &[1, 1, 1], &[0, 1, 1]), + (&[1, 0, 1], &[0, 1, 1], &[0, 0, 1], &[1, 1, 1], &[1, 1]), + ( + &[268, 482, 17], + &[964, 54], + &[260, 34], + &[972, 502, 17], + &[712, 468, 17], + ), +]; + +#[test] +fn test_bitand() { + for elm in BIT_TESTS { + let (a_vec, b_vec, c_vec, _, _) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(a & b == c); + assert_op!(b & a == c); + assert_assign_op!(a &= b == c); + assert_assign_op!(b &= a == c); + } +} + +#[test] +fn test_bitor() { + for elm in BIT_TESTS { + let (a_vec, b_vec, _, c_vec, _) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(a | b == c); + assert_op!(b | a == c); + assert_assign_op!(a |= b == c); + assert_assign_op!(b |= a == c); + } +} + +#[test] +fn test_bitxor() { + for elm in BIT_TESTS { + let (a_vec, b_vec, _, _, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(a ^ b == c); + assert_op!(b ^ a == c); + assert_op!(a ^ c == b); + assert_op!(c ^ a == b); + assert_op!(b ^ c == a); + assert_op!(c ^ b == a); + assert_assign_op!(a ^= b == c); + assert_assign_op!(b ^= a == c); + assert_assign_op!(a ^= c == b); + assert_assign_op!(c ^= a == b); + assert_assign_op!(b ^= c == a); + assert_assign_op!(c ^= b == a); + } +} + +#[test] +fn test_shl() { + fn check(s: &str, shift: usize, ans: &str) { + let opt_biguint = BigUint::from_str_radix(s, 16).ok(); + let mut bu_assign = opt_biguint.unwrap(); + let bu = (bu_assign.clone() << shift).to_str_radix(16); + assert_eq!(bu, ans); + bu_assign <<= shift; + assert_eq!(bu_assign.to_str_radix(16), ans); + } + + check("0", 3, "0"); + check("1", 3, "8"); + + check( + "1\ + 0000\ + 0000\ + 0000\ + 0001\ + 0000\ + 0000\ + 0000\ + 0001", + 3, + "8\ + 0000\ + 0000\ + 0000\ + 0008\ + 0000\ + 0000\ + 0000\ + 0008", + ); + check( + "1\ + 0000\ + 0001\ + 0000\ + 0001", + 2, + "4\ + 0000\ + 0004\ + 0000\ + 0004", + ); + check( + "1\ + 0001\ + 0001", + 1, + "2\ + 0002\ + 0002", + ); + + check( + "\ + 4000\ + 0000\ + 0000\ + 0000", + 3, + "2\ + 0000\ + 0000\ + 0000\ + 0000", + ); + check( + "4000\ + 0000", + 2, + "1\ + 0000\ + 0000", + ); + check( + "4000", + 2, + "1\ + 0000", + ); + + check( + "4000\ + 0000\ + 0000\ + 0000", + 67, + "2\ + 0000\ + 0000\ + 0000\ + 0000\ + 0000\ + 0000\ + 0000\ + 0000", + ); + check( + "4000\ + 0000", + 35, + "2\ + 0000\ + 0000\ + 0000\ + 0000", + ); + check( + "4000", + 19, + "2\ + 0000\ + 0000", + ); + + check( + "fedc\ + ba98\ + 7654\ + 3210\ + fedc\ + ba98\ + 7654\ + 3210", + 4, + "f\ + edcb\ + a987\ + 6543\ + 210f\ + edcb\ + a987\ + 6543\ + 2100", + ); + check( + "88887777666655554444333322221111", + 16, + "888877776666555544443333222211110000", + ); +} + +#[test] +fn test_shr() { + fn check(s: &str, shift: usize, ans: &str) { + let opt_biguint = BigUint::from_str_radix(s, 16).ok(); + let mut bu_assign = opt_biguint.unwrap(); + let bu = (bu_assign.clone() >> shift).to_str_radix(16); + assert_eq!(bu, ans); + bu_assign >>= shift; + assert_eq!(bu_assign.to_str_radix(16), ans); + } + + check("0", 3, "0"); + check("f", 3, "1"); + + check( + "1\ + 0000\ + 0000\ + 0000\ + 0001\ + 0000\ + 0000\ + 0000\ + 0001", + 3, + "2000\ + 0000\ + 0000\ + 0000\ + 2000\ + 0000\ + 0000\ + 0000", + ); + check( + "1\ + 0000\ + 0001\ + 0000\ + 0001", + 2, + "4000\ + 0000\ + 4000\ + 0000", + ); + check( + "1\ + 0001\ + 0001", + 1, + "8000\ + 8000", + ); + + check( + "2\ + 0000\ + 0000\ + 0000\ + 0001\ + 0000\ + 0000\ + 0000\ + 0001", + 67, + "4000\ + 0000\ + 0000\ + 0000", + ); + check( + "2\ + 0000\ + 0001\ + 0000\ + 0001", + 35, + "4000\ + 0000", + ); + check( + "2\ + 0001\ + 0001", + 19, + "4000", + ); + + check( + "1\ + 0000\ + 0000\ + 0000\ + 0000", + 1, + "8000\ + 0000\ + 0000\ + 0000", + ); + check( + "1\ + 0000\ + 0000", + 1, + "8000\ + 0000", + ); + check( + "1\ + 0000", + 1, + "8000", + ); + check( + "f\ + edcb\ + a987\ + 6543\ + 210f\ + edcb\ + a987\ + 6543\ + 2100", + 4, + "fedc\ + ba98\ + 7654\ + 3210\ + fedc\ + ba98\ + 7654\ + 3210", + ); + + check( + "888877776666555544443333222211110000", + 16, + "88887777666655554444333322221111", + ); +} + +// `DoubleBigDigit` size dependent +#[test] +fn test_convert_i64() { + fn check(b1: BigUint, i: i64) { + let b2: BigUint = FromPrimitive::from_i64(i).unwrap(); + assert_eq!(b1, b2); + assert_eq!(b1.to_i64().unwrap(), i); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(i64::MAX.to_biguint().unwrap(), i64::MAX); + + check(BigUint::new(vec![]), 0); + check(BigUint::new(vec![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); + check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX); + + assert_eq!(i64::MIN.to_biguint(), None); + assert_eq!(BigUint::new(vec![N1, N1]).to_i64(), None); + assert_eq!(BigUint::new(vec![0, 0, 1]).to_i64(), None); + assert_eq!(BigUint::new(vec![N1, N1, N1]).to_i64(), None); +} + +#[test] +fn test_convert_i128() { + fn check(b1: BigUint, i: i128) { + let b2: BigUint = FromPrimitive::from_i128(i).unwrap(); + assert_eq!(b1, b2); + assert_eq!(b1.to_i128().unwrap(), i); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(i128::MAX.to_biguint().unwrap(), i128::MAX); + + check(BigUint::new(vec![]), 0); + check(BigUint::new(vec![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); + check(BigUint::new(vec![N1, N1, N1, N1 >> 1]), i128::MAX); + + assert_eq!(i128::MIN.to_biguint(), None); + assert_eq!(BigUint::new(vec![N1, N1, N1, N1]).to_i128(), None); + assert_eq!(BigUint::new(vec![0, 0, 0, 0, 1]).to_i128(), None); + assert_eq!(BigUint::new(vec![N1, N1, N1, N1, N1]).to_i128(), None); +} + +// `DoubleBigDigit` size dependent +#[test] +fn test_convert_u64() { + fn check(b1: BigUint, u: u64) { + let b2: BigUint = FromPrimitive::from_u64(u).unwrap(); + assert_eq!(b1, b2); + assert_eq!(b1.to_u64().unwrap(), u); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(u64::MIN.to_biguint().unwrap(), u64::MIN); + check(u64::MAX.to_biguint().unwrap(), u64::MAX); + + check(BigUint::new(vec![]), 0); + check(BigUint::new(vec![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); + check(BigUint::new(vec![N1, N1]), u64::MAX); + + assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None); + assert_eq!(BigUint::new(vec![N1, N1, N1]).to_u64(), None); +} + +#[test] +fn test_convert_u128() { + fn check(b1: BigUint, u: u128) { + let b2: BigUint = FromPrimitive::from_u128(u).unwrap(); + assert_eq!(b1, b2); + assert_eq!(b1.to_u128().unwrap(), u); + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(u128::MIN.to_biguint().unwrap(), u128::MIN); + check(u128::MAX.to_biguint().unwrap(), u128::MAX); + + check(BigUint::new(vec![]), 0); + check(BigUint::new(vec![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); + check(BigUint::new(vec![N1, N1, N1, N1]), u128::MAX); + + assert_eq!(BigUint::new(vec![0, 0, 0, 0, 1]).to_u128(), None); + assert_eq!(BigUint::new(vec![N1, N1, N1, N1, N1]).to_u128(), None); +} + +#[test] +#[allow(clippy::float_cmp)] +fn test_convert_f32() { + fn check(b1: &BigUint, f: f32) { + let b2 = BigUint::from_f32(f).unwrap(); + assert_eq!(b1, &b2); + assert_eq!(b1.to_f32().unwrap(), f); + } + + check(&BigUint::zero(), 0.0); + check(&BigUint::one(), 1.0); + check(&BigUint::from(u16::MAX), pow(2.0_f32, 16) - 1.0); + check(&BigUint::from(1u64 << 32), pow(2.0_f32, 32)); + check(&BigUint::from_slice(&[0, 0, 1]), pow(2.0_f32, 64)); + check( + &((BigUint::one() << 100) + (BigUint::one() << 123)), + pow(2.0_f32, 100) + pow(2.0_f32, 123), + ); + check(&(BigUint::one() << 127), pow(2.0_f32, 127)); + check(&(BigUint::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); + + // keeping all 24 digits with the bits at different offsets to the BigDigits + let x: u32 = 0b00000000101111011111011011011101; + let mut f = x as f32; + let mut b = BigUint::from(x); + for _ in 0..64 { + check(&b, f); + f *= 2.0; + b <<= 1; + } + + // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 + let n: u64 = 0b0000000000111111111111111111111111011111111111111111111111111111; + assert!((n as f64) as f32 != n as f32); + assert_eq!(BigUint::from(n).to_f32(), Some(n as f32)); + + // test rounding up with the bits at different offsets to the BigDigits + let mut f = ((1u64 << 25) - 1) as f32; + let mut b = BigUint::from(1u64 << 25); + for _ in 0..64 { + assert_eq!(b.to_f32(), Some(f)); + f *= 2.0; + b <<= 1; + } + + // test correct ties-to-even rounding + let weird: i128 = (1i128 << 100) + (1i128 << (100 - f32::MANTISSA_DIGITS)); + assert_ne!(weird as f32, (weird + 1) as f32); + + assert_eq!(BigInt::from(weird).to_f32(), Some(weird as f32)); + assert_eq!(BigInt::from(weird + 1).to_f32(), Some((weird + 1) as f32)); + + // rounding + assert_eq!(BigUint::from_f32(-1.0), None); + assert_eq!(BigUint::from_f32(-0.99999), Some(BigUint::zero())); + assert_eq!(BigUint::from_f32(-0.5), Some(BigUint::zero())); + assert_eq!(BigUint::from_f32(-0.0), Some(BigUint::zero())); + assert_eq!( + BigUint::from_f32(f32::MIN_POSITIVE / 2.0), + Some(BigUint::zero()) + ); + assert_eq!(BigUint::from_f32(f32::MIN_POSITIVE), Some(BigUint::zero())); + assert_eq!(BigUint::from_f32(0.5), Some(BigUint::zero())); + assert_eq!(BigUint::from_f32(0.99999), Some(BigUint::zero())); + assert_eq!(BigUint::from_f32(f32::consts::E), Some(BigUint::from(2u32))); + assert_eq!( + BigUint::from_f32(f32::consts::PI), + Some(BigUint::from(3u32)) + ); + + // special float values + assert_eq!(BigUint::from_f32(f32::NAN), None); + assert_eq!(BigUint::from_f32(f32::INFINITY), None); + assert_eq!(BigUint::from_f32(f32::NEG_INFINITY), None); + assert_eq!(BigUint::from_f32(f32::MIN), None); + + // largest BigUint that will round to a finite f32 value + let big_num = (BigUint::one() << 128u8) - 1u8 - (BigUint::one() << (128u8 - 25)); + assert_eq!(big_num.to_f32(), Some(f32::MAX)); + assert_eq!((big_num + 1u8).to_f32(), Some(f32::INFINITY)); + + assert_eq!( + ((BigUint::one() << 128u8) - 1u8).to_f32(), + Some(f32::INFINITY) + ); + assert_eq!((BigUint::one() << 128u8).to_f32(), Some(f32::INFINITY)); +} + +#[test] +#[allow(clippy::float_cmp)] +fn test_convert_f64() { + fn check(b1: &BigUint, f: f64) { + let b2 = BigUint::from_f64(f).unwrap(); + assert_eq!(b1, &b2); + assert_eq!(b1.to_f64().unwrap(), f); + } + + check(&BigUint::zero(), 0.0); + check(&BigUint::one(), 1.0); + check(&BigUint::from(u32::MAX), pow(2.0_f64, 32) - 1.0); + check(&BigUint::from(1u64 << 32), pow(2.0_f64, 32)); + check(&BigUint::from_slice(&[0, 0, 1]), pow(2.0_f64, 64)); + check( + &((BigUint::one() << 100) + (BigUint::one() << 152)), + pow(2.0_f64, 100) + pow(2.0_f64, 152), + ); + check(&(BigUint::one() << 1023), pow(2.0_f64, 1023)); + check(&(BigUint::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); + + // keeping all 53 digits with the bits at different offsets to the BigDigits + let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; + let mut f = x as f64; + let mut b = BigUint::from(x); + for _ in 0..128 { + check(&b, f); + f *= 2.0; + b <<= 1; + } + + // test rounding up with the bits at different offsets to the BigDigits + let mut f = ((1u64 << 54) - 1) as f64; + let mut b = BigUint::from(1u64 << 54); + for _ in 0..128 { + assert_eq!(b.to_f64(), Some(f)); + f *= 2.0; + b <<= 1; + } + + // test correct ties-to-even rounding + let weird: i128 = (1i128 << 100) + (1i128 << (100 - f64::MANTISSA_DIGITS)); + assert_ne!(weird as f64, (weird + 1) as f64); + + assert_eq!(BigInt::from(weird).to_f64(), Some(weird as f64)); + assert_eq!(BigInt::from(weird + 1).to_f64(), Some((weird + 1) as f64)); + + // rounding + assert_eq!(BigUint::from_f64(-1.0), None); + assert_eq!(BigUint::from_f64(-0.99999), Some(BigUint::zero())); + assert_eq!(BigUint::from_f64(-0.5), Some(BigUint::zero())); + assert_eq!(BigUint::from_f64(-0.0), Some(BigUint::zero())); + assert_eq!( + BigUint::from_f64(f64::MIN_POSITIVE / 2.0), + Some(BigUint::zero()) + ); + assert_eq!(BigUint::from_f64(f64::MIN_POSITIVE), Some(BigUint::zero())); + assert_eq!(BigUint::from_f64(0.5), Some(BigUint::zero())); + assert_eq!(BigUint::from_f64(0.99999), Some(BigUint::zero())); + assert_eq!(BigUint::from_f64(f64::consts::E), Some(BigUint::from(2u32))); + assert_eq!( + BigUint::from_f64(f64::consts::PI), + Some(BigUint::from(3u32)) + ); + + // special float values + assert_eq!(BigUint::from_f64(f64::NAN), None); + assert_eq!(BigUint::from_f64(f64::INFINITY), None); + assert_eq!(BigUint::from_f64(f64::NEG_INFINITY), None); + assert_eq!(BigUint::from_f64(f64::MIN), None); + + // largest BigUint that will round to a finite f64 value + let big_num = (BigUint::one() << 1024u16) - 1u8 - (BigUint::one() << (1024u16 - 54)); + assert_eq!(big_num.to_f64(), Some(f64::MAX)); + assert_eq!((big_num + 1u8).to_f64(), Some(f64::INFINITY)); + + assert_eq!( + ((BigUint::one() << 1024u16) - 1u8).to_f64(), + Some(f64::INFINITY) + ); + assert_eq!((BigUint::one() << 1024u16).to_f64(), Some(f64::INFINITY)); +} + +#[test] +fn test_convert_to_bigint() { + fn check(n: BigUint, ans: BigInt) { + assert_eq!(n.to_bigint().unwrap(), ans); + assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n); + } + check(Zero::zero(), Zero::zero()); + check( + BigUint::new(vec![1, 2, 3]), + BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3])), + ); +} + +#[test] +fn test_convert_from_uint() { + macro_rules! check { + ($ty:ident, $max:expr) => { + assert_eq!(BigUint::from($ty::zero()), BigUint::zero()); + assert_eq!(BigUint::from($ty::one()), BigUint::one()); + assert_eq!(BigUint::from($ty::MAX - $ty::one()), $max - BigUint::one()); + assert_eq!(BigUint::from($ty::MAX), $max); + }; + } + + check!(u8, BigUint::from_slice(&[u8::MAX as u32])); + check!(u16, BigUint::from_slice(&[u16::MAX as u32])); + check!(u32, BigUint::from_slice(&[u32::MAX])); + check!(u64, BigUint::from_slice(&[u32::MAX, u32::MAX])); + check!( + u128, + BigUint::from_slice(&[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) + ); + check!(usize, BigUint::from(usize::MAX as u64)); +} + +#[test] +fn test_add() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(a + b == c); + assert_op!(b + a == c); + assert_assign_op!(a += b == c); + assert_assign_op!(b += a == c); + } +} + +#[test] +fn test_sub() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(c - a == b); + assert_op!(c - b == a); + assert_assign_op!(c -= a == b); + assert_assign_op!(c -= b == a); + } +} + +#[test] +#[should_panic] +fn test_sub_fail_on_underflow() { + let (a, b): (BigUint, BigUint) = (Zero::zero(), One::one()); + let _ = a - b; +} + +#[test] +fn test_mul() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert_op!(a * b == c); + assert_op!(b * a == c); + assert_assign_op!(a *= b == c); + assert_assign_op!(b *= a == c); + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + assert!(a == &b * &c + &d); + assert!(a == &c * &b + &d); + } +} + +#[test] +fn test_div_rem() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + if !a.is_zero() { + assert_op!(c / a == b); + assert_op!(c % a == BigUint::zero()); + assert_assign_op!(c /= a == b); + assert_assign_op!(c %= a == BigUint::zero()); + assert_eq!(c.div_rem(&a), (b.clone(), BigUint::zero())); + } + if !b.is_zero() { + assert_op!(c / b == a); + assert_op!(c % b == BigUint::zero()); + assert_assign_op!(c /= b == a); + assert_assign_op!(c %= b == BigUint::zero()); + assert_eq!(c.div_rem(&b), (a.clone(), BigUint::zero())); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + if !b.is_zero() { + assert_op!(a / b == c); + assert_op!(a % b == d); + assert_assign_op!(a /= b == c); + assert_assign_op!(a %= b == d); + assert!(a.div_rem(&b) == (c, d)); + } + } +} + +#[test] +fn test_div_rem_big_multiple() { + let a = BigUint::from(3u32).pow(100u32); + let a2 = &a * &a; + + let (div, rem) = a2.div_rem(&a); + assert_eq!(div, a); + assert!(rem.is_zero()); + + let (div, rem) = (&a2 - 1u32).div_rem(&a); + assert_eq!(div, &a - 1u32); + assert_eq!(rem, &a - 1u32); +} + +#[test] +fn test_div_ceil() { + fn check(a: &BigUint, b: &BigUint, d: &BigUint, m: &BigUint) { + if m.is_zero() { + assert_eq!(a.div_ceil(b), *d); + } else { + assert_eq!(a.div_ceil(b), d + 1u32); + } + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_div_rem_euclid() { + fn check(a: &BigUint, b: &BigUint, d: &BigUint, m: &BigUint) { + assert_eq!(a.div_euclid(b), *d); + assert_eq!(a.rem_euclid(b), *m); + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + } + } +} + +#[test] +fn test_checked_add() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert!(a.checked_add(&b).unwrap() == c); + assert!(b.checked_add(&a).unwrap() == c); + } +} + +#[test] +fn test_checked_sub() { + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert!(c.checked_sub(&a).unwrap() == b); + assert!(c.checked_sub(&b).unwrap() == a); + + if a > c { + assert!(a.checked_sub(&c).is_none()); + } + if b > c { + assert!(b.checked_sub(&c).is_none()); + } + } +} + +#[test] +fn test_checked_mul() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + assert!(a.checked_mul(&b).unwrap() == c); + assert!(b.checked_mul(&a).unwrap() == c); + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + assert!(a == b.checked_mul(&c).unwrap() + &d); + assert!(a == c.checked_mul(&b).unwrap() + &d); + } +} + +#[test] +fn test_mul_overflow() { + // Test for issue #187 - overflow due to mac3 incorrectly sizing temporary + let s = "5311379928167670986895882065524686273295931177270319231994441382\ + 0040355986085224273916250223263671004753755210595137000079652876\ + 0829212940754539968588340162273730474622005920097370111"; + let a: BigUint = s.parse().unwrap(); + let b = a.clone(); + let _ = a.checked_mul(&b); +} + +#[test] +fn test_mul_overflow_2() { + // Try a bunch of sizes that are right on the edge of multiplication length + // overflow, where (x * x).data.len() == 2 * x.data.len() + 1. + for i in 1u8..20 { + let bits = 1u32 << i; + let x = (BigUint::one() << bits) - 1u32; + let x2 = (BigUint::one() << (2 * bits)) - &x - &x - 1u32; + assert_eq!(&x * &x, x2); + } +} + +#[test] +fn test_checked_div() { + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + if !a.is_zero() { + assert!(c.checked_div(&a).unwrap() == b); + } + if !b.is_zero() { + assert!(c.checked_div(&b).unwrap() == a); + } + + assert!(c.checked_div(&Zero::zero()).is_none()); + } +} + +#[test] +fn test_gcd() { + fn check(a: usize, b: usize, c: usize) { + let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); + let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); + let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); + + assert_eq!(big_a.gcd(&big_b), big_c); + assert_eq!(big_a.gcd_lcm(&big_b).0, big_c); + } + + check(10, 2, 2); + check(10, 3, 1); + check(0, 3, 3); + check(3, 3, 3); + check(56, 42, 14); +} + +#[test] +fn test_lcm() { + fn check(a: usize, b: usize, c: usize) { + let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); + let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); + let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); + + assert_eq!(big_a.lcm(&big_b), big_c); + assert_eq!(big_a.gcd_lcm(&big_b).1, big_c); + } + + check(0, 0, 0); + check(1, 0, 0); + check(0, 1, 0); + check(1, 1, 1); + check(8, 9, 72); + check(11, 5, 55); + check(99, 17, 1683); +} + +#[test] +fn test_is_multiple_of() { + assert!(BigUint::from(0u32).is_multiple_of(&BigUint::from(0u32))); + assert!(BigUint::from(6u32).is_multiple_of(&BigUint::from(6u32))); + assert!(BigUint::from(6u32).is_multiple_of(&BigUint::from(3u32))); + assert!(BigUint::from(6u32).is_multiple_of(&BigUint::from(1u32))); + + assert!(!BigUint::from(42u32).is_multiple_of(&BigUint::from(5u32))); + assert!(!BigUint::from(5u32).is_multiple_of(&BigUint::from(3u32))); + assert!(!BigUint::from(42u32).is_multiple_of(&BigUint::from(0u32))); +} + +#[test] +fn test_next_multiple_of() { + assert_eq!( + BigUint::from(16u32).next_multiple_of(&BigUint::from(8u32)), + BigUint::from(16u32) + ); + assert_eq!( + BigUint::from(23u32).next_multiple_of(&BigUint::from(8u32)), + BigUint::from(24u32) + ); +} + +#[test] +fn test_prev_multiple_of() { + assert_eq!( + BigUint::from(16u32).prev_multiple_of(&BigUint::from(8u32)), + BigUint::from(16u32) + ); + assert_eq!( + BigUint::from(23u32).prev_multiple_of(&BigUint::from(8u32)), + BigUint::from(16u32) + ); +} + +#[test] +fn test_is_even() { + let one: BigUint = FromStr::from_str("1").unwrap(); + let two: BigUint = FromStr::from_str("2").unwrap(); + let thousand: BigUint = FromStr::from_str("1000").unwrap(); + let big: BigUint = FromStr::from_str("1000000000000000000000").unwrap(); + let bigger: BigUint = FromStr::from_str("1000000000000000000001").unwrap(); + assert!(one.is_odd()); + assert!(two.is_even()); + assert!(thousand.is_even()); + assert!(big.is_even()); + assert!(bigger.is_odd()); + assert!((&one << 64u8).is_even()); + assert!(((&one << 64u8) + one).is_odd()); +} + +fn to_str_pairs() -> Vec<(BigUint, Vec<(u32, String)>)> { + let bits = 32; + vec![ + ( + Zero::zero(), + vec![(2, "0".to_string()), (3, "0".to_string())], + ), + ( + BigUint::from_slice(&[0xff]), + vec![ + (2, "11111111".to_string()), + (3, "100110".to_string()), + (4, "3333".to_string()), + (5, "2010".to_string()), + (6, "1103".to_string()), + (7, "513".to_string()), + (8, "377".to_string()), + (9, "313".to_string()), + (10, "255".to_string()), + (11, "212".to_string()), + (12, "193".to_string()), + (13, "168".to_string()), + (14, "143".to_string()), + (15, "120".to_string()), + (16, "ff".to_string()), + ], + ), + ( + BigUint::from_slice(&[0xfff]), + vec![ + (2, "111111111111".to_string()), + (4, "333333".to_string()), + (16, "fff".to_string()), + ], + ), + ( + BigUint::from_slice(&[1, 2]), + vec![ + ( + 2, + format!("10{}1", repeat("0").take(bits - 1).collect::()), + ), + ( + 4, + format!("2{}1", repeat("0").take(bits / 2 - 1).collect::()), + ), + ( + 10, + match bits { + 64 => "36893488147419103233".to_string(), + 32 => "8589934593".to_string(), + 16 => "131073".to_string(), + _ => panic!(), + }, + ), + ( + 16, + format!("2{}1", repeat("0").take(bits / 4 - 1).collect::()), + ), + ], + ), + ( + BigUint::from_slice(&[1, 2, 3]), + vec![ + ( + 2, + format!( + "11{}10{}1", + repeat("0").take(bits - 2).collect::(), + repeat("0").take(bits - 1).collect::() + ), + ), + ( + 4, + format!( + "3{}2{}1", + repeat("0").take(bits / 2 - 1).collect::(), + repeat("0").take(bits / 2 - 1).collect::() + ), + ), + ( + 8, + match bits { + 64 => "14000000000000000000004000000000000000000001".to_string(), + 32 => "6000000000100000000001".to_string(), + 16 => "140000400001".to_string(), + _ => panic!(), + }, + ), + ( + 10, + match bits { + 64 => "1020847100762815390427017310442723737601".to_string(), + 32 => "55340232229718589441".to_string(), + 16 => "12885032961".to_string(), + _ => panic!(), + }, + ), + ( + 16, + format!( + "3{}2{}1", + repeat("0").take(bits / 4 - 1).collect::(), + repeat("0").take(bits / 4 - 1).collect::() + ), + ), + ], + ), + ] +} + +#[test] +fn test_to_str_radix() { + let r = to_str_pairs(); + for num_pair in r.iter() { + let &(ref n, ref rs) = num_pair; + for str_pair in rs.iter() { + let &(ref radix, ref str) = str_pair; + assert_eq!(n.to_str_radix(*radix), *str); + } + } +} + +#[test] +fn test_from_and_to_radix() { + const GROUND_TRUTH: &[(&[u8], u32, &[u8])] = &[ + (b"0", 42, &[0]), + ( + b"ffffeeffbb", + 2, + &[ + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + ], + ), + ( + b"ffffeeffbb", + 3, + &[ + 2, 2, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 2, 2, 0, 1, + ], + ), + ( + b"ffffeeffbb", + 4, + &[3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], + ), + ( + b"ffffeeffbb", + 5, + &[0, 4, 3, 3, 1, 4, 2, 4, 1, 4, 4, 2, 3, 0, 0, 1, 2, 1], + ), + ( + b"ffffeeffbb", + 6, + &[5, 5, 4, 5, 5, 0, 0, 1, 2, 5, 3, 0, 1, 0, 2, 2], + ), + ( + b"ffffeeffbb", + 7, + &[4, 2, 3, 6, 0, 1, 6, 1, 6, 2, 0, 3, 2, 4, 1], + ), + ( + b"ffffeeffbb", + 8, + &[3, 7, 6, 7, 7, 5, 3, 7, 7, 7, 7, 7, 7, 1], + ), + (b"ffffeeffbb", 9, &[8, 4, 5, 7, 0, 0, 3, 2, 0, 3, 0, 8, 3]), + (b"ffffeeffbb", 10, &[5, 9, 5, 3, 1, 5, 0, 1, 5, 9, 9, 0, 1]), + (b"ffffeeffbb", 11, &[10, 7, 6, 5, 2, 0, 3, 3, 3, 4, 9, 3]), + (b"ffffeeffbb", 12, &[11, 8, 5, 10, 1, 10, 3, 1, 1, 9, 5, 1]), + (b"ffffeeffbb", 13, &[0, 5, 7, 4, 6, 5, 6, 11, 8, 12, 7]), + (b"ffffeeffbb", 14, &[11, 4, 4, 11, 8, 4, 6, 0, 3, 11, 3]), + (b"ffffeeffbb", 15, &[5, 11, 13, 2, 1, 10, 2, 0, 9, 13, 1]), + (b"ffffeeffbb", 16, &[11, 11, 15, 15, 14, 14, 15, 15, 15, 15]), + (b"ffffeeffbb", 17, &[0, 2, 14, 12, 2, 14, 8, 10, 4, 9]), + (b"ffffeeffbb", 18, &[17, 15, 5, 13, 10, 16, 16, 13, 9, 5]), + (b"ffffeeffbb", 19, &[14, 13, 2, 8, 9, 0, 1, 14, 7, 3]), + (b"ffffeeffbb", 20, &[15, 19, 3, 14, 0, 17, 19, 18, 2, 2]), + (b"ffffeeffbb", 21, &[11, 5, 4, 13, 5, 18, 9, 1, 8, 1]), + (b"ffffeeffbb", 22, &[21, 3, 7, 21, 15, 12, 17, 0, 20]), + (b"ffffeeffbb", 23, &[21, 21, 6, 9, 10, 7, 21, 0, 14]), + (b"ffffeeffbb", 24, &[11, 10, 19, 14, 22, 11, 17, 23, 9]), + (b"ffffeeffbb", 25, &[20, 18, 21, 22, 21, 14, 3, 5, 7]), + (b"ffffeeffbb", 26, &[13, 15, 24, 11, 17, 6, 23, 6, 5]), + (b"ffffeeffbb", 27, &[17, 16, 7, 0, 21, 0, 3, 24, 3]), + (b"ffffeeffbb", 28, &[11, 16, 11, 15, 14, 18, 13, 25, 2]), + (b"ffffeeffbb", 29, &[6, 8, 7, 19, 14, 13, 21, 5, 2]), + (b"ffffeeffbb", 30, &[5, 13, 18, 11, 10, 7, 8, 20, 1]), + (b"ffffeeffbb", 31, &[22, 26, 15, 19, 8, 27, 29, 8, 1]), + (b"ffffeeffbb", 32, &[27, 29, 31, 29, 30, 31, 31, 31]), + (b"ffffeeffbb", 33, &[32, 20, 27, 12, 1, 12, 26, 25]), + (b"ffffeeffbb", 34, &[17, 9, 16, 33, 13, 25, 31, 20]), + (b"ffffeeffbb", 35, &[25, 32, 2, 25, 11, 4, 3, 17]), + (b"ffffeeffbb", 36, &[35, 34, 5, 6, 32, 3, 1, 14]), + (b"ffffeeffbb", 37, &[16, 21, 18, 4, 33, 19, 21, 11]), + (b"ffffeeffbb", 38, &[33, 25, 19, 29, 20, 6, 23, 9]), + (b"ffffeeffbb", 39, &[26, 27, 29, 23, 16, 18, 0, 8]), + (b"ffffeeffbb", 40, &[35, 39, 30, 11, 16, 17, 28, 6]), + (b"ffffeeffbb", 41, &[36, 30, 9, 18, 12, 19, 26, 5]), + (b"ffffeeffbb", 42, &[11, 34, 37, 27, 1, 13, 32, 4]), + (b"ffffeeffbb", 43, &[3, 24, 11, 2, 10, 40, 1, 4]), + (b"ffffeeffbb", 44, &[43, 12, 40, 32, 3, 23, 19, 3]), + (b"ffffeeffbb", 45, &[35, 38, 44, 18, 22, 18, 42, 2]), + (b"ffffeeffbb", 46, &[21, 45, 18, 41, 17, 2, 24, 2]), + (b"ffffeeffbb", 47, &[37, 37, 11, 12, 6, 0, 8, 2]), + (b"ffffeeffbb", 48, &[11, 41, 40, 43, 5, 43, 41, 1]), + (b"ffffeeffbb", 49, &[18, 45, 7, 13, 20, 21, 30, 1]), + (b"ffffeeffbb", 50, &[45, 21, 5, 34, 21, 18, 20, 1]), + (b"ffffeeffbb", 51, &[17, 6, 26, 22, 38, 24, 11, 1]), + (b"ffffeeffbb", 52, &[39, 33, 38, 30, 46, 31, 3, 1]), + (b"ffffeeffbb", 53, &[31, 7, 44, 23, 9, 32, 49]), + (b"ffffeeffbb", 54, &[17, 35, 8, 37, 31, 18, 44]), + (b"ffffeeffbb", 55, &[10, 52, 9, 48, 36, 39, 39]), + (b"ffffeeffbb", 56, &[11, 50, 51, 22, 25, 36, 35]), + (b"ffffeeffbb", 57, &[14, 55, 12, 43, 20, 3, 32]), + (b"ffffeeffbb", 58, &[35, 18, 45, 56, 9, 51, 28]), + (b"ffffeeffbb", 59, &[51, 28, 20, 26, 55, 3, 26]), + (b"ffffeeffbb", 60, &[35, 6, 27, 46, 58, 33, 23]), + (b"ffffeeffbb", 61, &[58, 7, 6, 54, 49, 20, 21]), + (b"ffffeeffbb", 62, &[53, 59, 3, 14, 10, 22, 19]), + (b"ffffeeffbb", 63, &[53, 50, 23, 4, 56, 36, 17]), + (b"ffffeeffbb", 64, &[59, 62, 47, 59, 63, 63, 15]), + (b"ffffeeffbb", 65, &[0, 53, 39, 4, 40, 37, 14]), + (b"ffffeeffbb", 66, &[65, 59, 39, 1, 64, 19, 13]), + (b"ffffeeffbb", 67, &[35, 14, 19, 16, 25, 10, 12]), + (b"ffffeeffbb", 68, &[51, 38, 63, 50, 15, 8, 11]), + (b"ffffeeffbb", 69, &[44, 45, 18, 58, 68, 12, 10]), + (b"ffffeeffbb", 70, &[25, 51, 0, 60, 13, 24, 9]), + (b"ffffeeffbb", 71, &[54, 30, 9, 65, 28, 41, 8]), + (b"ffffeeffbb", 72, &[35, 35, 55, 54, 17, 64, 7]), + (b"ffffeeffbb", 73, &[34, 4, 48, 40, 27, 19, 7]), + (b"ffffeeffbb", 74, &[53, 47, 4, 56, 36, 51, 6]), + (b"ffffeeffbb", 75, &[20, 56, 10, 72, 24, 13, 6]), + (b"ffffeeffbb", 76, &[71, 31, 52, 60, 48, 53, 5]), + (b"ffffeeffbb", 77, &[32, 73, 14, 63, 15, 21, 5]), + (b"ffffeeffbb", 78, &[65, 13, 17, 32, 64, 68, 4]), + (b"ffffeeffbb", 79, &[37, 56, 2, 56, 25, 41, 4]), + (b"ffffeeffbb", 80, &[75, 59, 37, 41, 43, 15, 4]), + (b"ffffeeffbb", 81, &[44, 68, 0, 21, 27, 72, 3]), + (b"ffffeeffbb", 82, &[77, 35, 2, 74, 46, 50, 3]), + (b"ffffeeffbb", 83, &[52, 51, 19, 76, 10, 30, 3]), + (b"ffffeeffbb", 84, &[11, 80, 19, 19, 76, 10, 3]), + (b"ffffeeffbb", 85, &[0, 82, 20, 14, 68, 77, 2]), + (b"ffffeeffbb", 86, &[3, 12, 78, 37, 62, 61, 2]), + (b"ffffeeffbb", 87, &[35, 12, 20, 8, 52, 46, 2]), + (b"ffffeeffbb", 88, &[43, 6, 54, 42, 30, 32, 2]), + (b"ffffeeffbb", 89, &[49, 52, 85, 21, 80, 18, 2]), + (b"ffffeeffbb", 90, &[35, 64, 78, 24, 18, 6, 2]), + (b"ffffeeffbb", 91, &[39, 17, 83, 63, 17, 85, 1]), + (b"ffffeeffbb", 92, &[67, 22, 85, 79, 75, 74, 1]), + (b"ffffeeffbb", 93, &[53, 60, 39, 29, 4, 65, 1]), + (b"ffffeeffbb", 94, &[37, 89, 2, 72, 76, 55, 1]), + (b"ffffeeffbb", 95, &[90, 74, 89, 9, 9, 47, 1]), + (b"ffffeeffbb", 96, &[59, 20, 46, 35, 81, 38, 1]), + (b"ffffeeffbb", 97, &[94, 87, 60, 71, 3, 31, 1]), + (b"ffffeeffbb", 98, &[67, 22, 63, 50, 62, 23, 1]), + (b"ffffeeffbb", 99, &[98, 6, 69, 12, 61, 16, 1]), + (b"ffffeeffbb", 100, &[95, 35, 51, 10, 95, 9, 1]), + (b"ffffeeffbb", 101, &[87, 27, 7, 8, 62, 3, 1]), + (b"ffffeeffbb", 102, &[17, 3, 32, 79, 59, 99]), + (b"ffffeeffbb", 103, &[30, 22, 90, 0, 87, 94]), + (b"ffffeeffbb", 104, &[91, 68, 87, 68, 38, 90]), + (b"ffffeeffbb", 105, &[95, 80, 54, 73, 15, 86]), + (b"ffffeeffbb", 106, &[31, 30, 24, 16, 17, 82]), + (b"ffffeeffbb", 107, &[51, 50, 10, 12, 42, 78]), + (b"ffffeeffbb", 108, &[71, 71, 96, 78, 89, 74]), + (b"ffffeeffbb", 109, &[33, 18, 93, 22, 50, 71]), + (b"ffffeeffbb", 110, &[65, 53, 57, 88, 29, 68]), + (b"ffffeeffbb", 111, &[53, 93, 67, 90, 27, 65]), + (b"ffffeeffbb", 112, &[11, 109, 96, 65, 43, 62]), + (b"ffffeeffbb", 113, &[27, 23, 106, 56, 76, 59]), + (b"ffffeeffbb", 114, &[71, 84, 31, 112, 11, 57]), + (b"ffffeeffbb", 115, &[90, 22, 1, 56, 76, 54]), + (b"ffffeeffbb", 116, &[35, 38, 98, 57, 40, 52]), + (b"ffffeeffbb", 117, &[26, 113, 115, 62, 17, 50]), + (b"ffffeeffbb", 118, &[51, 14, 5, 18, 7, 48]), + (b"ffffeeffbb", 119, &[102, 31, 110, 108, 8, 46]), + (b"ffffeeffbb", 120, &[35, 93, 96, 50, 22, 44]), + (b"ffffeeffbb", 121, &[87, 61, 2, 36, 47, 42]), + (b"ffffeeffbb", 122, &[119, 64, 1, 22, 83, 40]), + (b"ffffeeffbb", 123, &[77, 119, 32, 90, 6, 39]), + (b"ffffeeffbb", 124, &[115, 122, 31, 79, 62, 37]), + (b"ffffeeffbb", 125, &[95, 108, 47, 74, 3, 36]), + (b"ffffeeffbb", 126, &[53, 25, 116, 39, 78, 34]), + (b"ffffeeffbb", 127, &[22, 23, 125, 67, 35, 33]), + (b"ffffeeffbb", 128, &[59, 127, 59, 127, 127, 31]), + (b"ffffeeffbb", 129, &[89, 36, 1, 59, 100, 30]), + (b"ffffeeffbb", 130, &[65, 91, 123, 89, 79, 29]), + (b"ffffeeffbb", 131, &[58, 72, 39, 63, 65, 28]), + (b"ffffeeffbb", 132, &[131, 62, 92, 82, 57, 27]), + (b"ffffeeffbb", 133, &[109, 31, 51, 123, 55, 26]), + (b"ffffeeffbb", 134, &[35, 74, 21, 27, 60, 25]), + (b"ffffeeffbb", 135, &[125, 132, 49, 37, 70, 24]), + (b"ffffeeffbb", 136, &[51, 121, 117, 133, 85, 23]), + (b"ffffeeffbb", 137, &[113, 60, 135, 22, 107, 22]), + (b"ffffeeffbb", 138, &[113, 91, 73, 93, 133, 21]), + (b"ffffeeffbb", 139, &[114, 75, 102, 51, 26, 21]), + (b"ffffeeffbb", 140, &[95, 25, 35, 16, 62, 20]), + (b"ffffeeffbb", 141, &[131, 137, 16, 110, 102, 19]), + (b"ffffeeffbb", 142, &[125, 121, 108, 34, 6, 19]), + (b"ffffeeffbb", 143, &[65, 78, 138, 55, 55, 18]), + (b"ffffeeffbb", 144, &[107, 125, 121, 15, 109, 17]), + (b"ffffeeffbb", 145, &[35, 13, 122, 42, 22, 17]), + (b"ffffeeffbb", 146, &[107, 38, 103, 123, 83, 16]), + (b"ffffeeffbb", 147, &[116, 96, 71, 98, 2, 16]), + (b"ffffeeffbb", 148, &[127, 23, 75, 99, 71, 15]), + (b"ffffeeffbb", 149, &[136, 110, 53, 114, 144, 14]), + (b"ffffeeffbb", 150, &[95, 140, 133, 130, 71, 14]), + (b"ffffeeffbb", 151, &[15, 50, 29, 137, 0, 14]), + (b"ffffeeffbb", 152, &[147, 15, 89, 121, 83, 13]), + (b"ffffeeffbb", 153, &[17, 87, 93, 72, 17, 13]), + (b"ffffeeffbb", 154, &[109, 113, 3, 133, 106, 12]), + (b"ffffeeffbb", 155, &[115, 141, 120, 139, 44, 12]), + (b"ffffeeffbb", 156, &[143, 45, 4, 82, 140, 11]), + (b"ffffeeffbb", 157, &[149, 92, 15, 106, 82, 11]), + (b"ffffeeffbb", 158, &[37, 107, 79, 46, 26, 11]), + (b"ffffeeffbb", 159, &[137, 37, 146, 51, 130, 10]), + (b"ffffeeffbb", 160, &[155, 69, 29, 115, 77, 10]), + (b"ffffeeffbb", 161, &[67, 98, 46, 68, 26, 10]), + (b"ffffeeffbb", 162, &[125, 155, 60, 63, 138, 9]), + (b"ffffeeffbb", 163, &[96, 43, 118, 93, 90, 9]), + (b"ffffeeffbb", 164, &[159, 99, 123, 152, 43, 9]), + (b"ffffeeffbb", 165, &[65, 17, 1, 69, 163, 8]), + (b"ffffeeffbb", 166, &[135, 108, 25, 165, 119, 8]), + (b"ffffeeffbb", 167, &[165, 116, 164, 103, 77, 8]), + (b"ffffeeffbb", 168, &[11, 166, 67, 44, 36, 8]), + (b"ffffeeffbb", 169, &[65, 59, 71, 149, 164, 7]), + (b"ffffeeffbb", 170, &[85, 83, 26, 76, 126, 7]), + (b"ffffeeffbb", 171, &[71, 132, 140, 157, 88, 7]), + (b"ffffeeffbb", 172, &[3, 6, 127, 47, 52, 7]), + (b"ffffeeffbb", 173, &[122, 66, 53, 83, 16, 7]), + (b"ffffeeffbb", 174, &[35, 6, 5, 88, 155, 6]), + (b"ffffeeffbb", 175, &[95, 20, 84, 56, 122, 6]), + (b"ffffeeffbb", 176, &[43, 91, 57, 159, 89, 6]), + (b"ffffeeffbb", 177, &[110, 127, 54, 40, 58, 6]), + (b"ffffeeffbb", 178, &[49, 115, 43, 47, 27, 6]), + (b"ffffeeffbb", 179, &[130, 91, 4, 178, 175, 5]), + (b"ffffeeffbb", 180, &[35, 122, 109, 70, 147, 5]), + (b"ffffeeffbb", 181, &[94, 94, 4, 79, 119, 5]), + (b"ffffeeffbb", 182, &[39, 54, 66, 19, 92, 5]), + (b"ffffeeffbb", 183, &[119, 2, 143, 69, 65, 5]), + (b"ffffeeffbb", 184, &[67, 57, 90, 44, 39, 5]), + (b"ffffeeffbb", 185, &[90, 63, 141, 123, 13, 5]), + (b"ffffeeffbb", 186, &[53, 123, 172, 119, 174, 4]), + (b"ffffeeffbb", 187, &[153, 21, 68, 28, 151, 4]), + (b"ffffeeffbb", 188, &[131, 138, 94, 32, 128, 4]), + (b"ffffeeffbb", 189, &[179, 121, 156, 130, 105, 4]), + (b"ffffeeffbb", 190, &[185, 179, 164, 131, 83, 4]), + (b"ffffeeffbb", 191, &[118, 123, 37, 31, 62, 4]), + (b"ffffeeffbb", 192, &[59, 106, 83, 16, 41, 4]), + (b"ffffeeffbb", 193, &[57, 37, 47, 86, 20, 4]), + (b"ffffeeffbb", 194, &[191, 140, 63, 45, 0, 4]), + (b"ffffeeffbb", 195, &[65, 169, 83, 84, 175, 3]), + (b"ffffeeffbb", 196, &[67, 158, 64, 6, 157, 3]), + (b"ffffeeffbb", 197, &[121, 26, 167, 3, 139, 3]), + (b"ffffeeffbb", 198, &[197, 151, 165, 75, 121, 3]), + (b"ffffeeffbb", 199, &[55, 175, 36, 22, 104, 3]), + (b"ffffeeffbb", 200, &[195, 167, 162, 38, 87, 3]), + (b"ffffeeffbb", 201, &[35, 27, 136, 124, 70, 3]), + (b"ffffeeffbb", 202, &[87, 64, 153, 76, 54, 3]), + (b"ffffeeffbb", 203, &[151, 191, 14, 94, 38, 3]), + (b"ffffeeffbb", 204, &[119, 103, 135, 175, 22, 3]), + (b"ffffeeffbb", 205, &[200, 79, 123, 115, 7, 3]), + (b"ffffeeffbb", 206, &[133, 165, 202, 115, 198, 2]), + (b"ffffeeffbb", 207, &[44, 153, 193, 175, 184, 2]), + (b"ffffeeffbb", 208, &[91, 190, 125, 86, 171, 2]), + (b"ffffeeffbb", 209, &[109, 151, 34, 53, 158, 2]), + (b"ffffeeffbb", 210, &[95, 40, 171, 74, 145, 2]), + (b"ffffeeffbb", 211, &[84, 195, 162, 150, 132, 2]), + (b"ffffeeffbb", 212, &[31, 15, 59, 68, 120, 2]), + (b"ffffeeffbb", 213, &[125, 57, 127, 36, 108, 2]), + (b"ffffeeffbb", 214, &[51, 132, 2, 55, 96, 2]), + (b"ffffeeffbb", 215, &[175, 133, 177, 122, 84, 2]), + (b"ffffeeffbb", 216, &[179, 35, 78, 23, 73, 2]), + (b"ffffeeffbb", 217, &[53, 101, 208, 186, 61, 2]), + (b"ffffeeffbb", 218, &[33, 9, 214, 179, 50, 2]), + (b"ffffeeffbb", 219, &[107, 147, 175, 217, 39, 2]), + (b"ffffeeffbb", 220, &[175, 81, 179, 79, 29, 2]), + (b"ffffeeffbb", 221, &[0, 76, 95, 204, 18, 2]), + (b"ffffeeffbb", 222, &[53, 213, 16, 150, 8, 2]), + (b"ffffeeffbb", 223, &[158, 161, 42, 136, 221, 1]), + (b"ffffeeffbb", 224, &[123, 54, 52, 162, 212, 1]), + (b"ffffeeffbb", 225, &[170, 43, 151, 2, 204, 1]), + (b"ffffeeffbb", 226, &[27, 68, 224, 105, 195, 1]), + (b"ffffeeffbb", 227, &[45, 69, 157, 20, 187, 1]), + (b"ffffeeffbb", 228, &[71, 213, 64, 199, 178, 1]), + (b"ffffeeffbb", 229, &[129, 203, 66, 186, 170, 1]), + (b"ffffeeffbb", 230, &[205, 183, 57, 208, 162, 1]), + (b"ffffeeffbb", 231, &[32, 50, 164, 33, 155, 1]), + (b"ffffeeffbb", 232, &[35, 135, 53, 123, 147, 1]), + (b"ffffeeffbb", 233, &[209, 47, 89, 13, 140, 1]), + (b"ffffeeffbb", 234, &[143, 56, 175, 168, 132, 1]), + (b"ffffeeffbb", 235, &[225, 157, 216, 121, 125, 1]), + (b"ffffeeffbb", 236, &[51, 66, 119, 105, 118, 1]), + (b"ffffeeffbb", 237, &[116, 150, 26, 119, 111, 1]), + (b"ffffeeffbb", 238, &[221, 15, 87, 162, 104, 1]), + (b"ffffeeffbb", 239, &[234, 155, 214, 234, 97, 1]), + (b"ffffeeffbb", 240, &[155, 46, 84, 96, 91, 1]), + (b"ffffeeffbb", 241, &[187, 48, 90, 225, 84, 1]), + (b"ffffeeffbb", 242, &[87, 212, 151, 140, 78, 1]), + (b"ffffeeffbb", 243, &[206, 22, 189, 81, 72, 1]), + (b"ffffeeffbb", 244, &[119, 93, 122, 48, 66, 1]), + (b"ffffeeffbb", 245, &[165, 224, 117, 40, 60, 1]), + (b"ffffeeffbb", 246, &[77, 121, 100, 57, 54, 1]), + (b"ffffeeffbb", 247, &[52, 128, 242, 98, 48, 1]), + (b"ffffeeffbb", 248, &[115, 247, 224, 164, 42, 1]), + (b"ffffeeffbb", 249, &[218, 127, 223, 5, 37, 1]), + (b"ffffeeffbb", 250, &[95, 54, 168, 118, 31, 1]), + (b"ffffeeffbb", 251, &[121, 204, 240, 3, 26, 1]), + (b"ffffeeffbb", 252, &[179, 138, 123, 162, 20, 1]), + (b"ffffeeffbb", 253, &[21, 50, 1, 91, 15, 1]), + (b"ffffeeffbb", 254, &[149, 11, 63, 40, 10, 1]), + (b"ffffeeffbb", 255, &[170, 225, 247, 9, 5, 1]), + (b"ffffeeffbb", 256, &[187, 255, 238, 255, 255]), + ]; + + for &(bigint, radix, inbaseradix_le) in GROUND_TRUTH.iter() { + let bigint = BigUint::parse_bytes(bigint, 16).unwrap(); + // to_radix_le + assert_eq!(bigint.to_radix_le(radix), inbaseradix_le); + // to_radix_be + let mut inbase_be = bigint.to_radix_be(radix); + inbase_be.reverse(); // now le + assert_eq!(inbase_be, inbaseradix_le); + // from_radix_le + assert_eq!( + BigUint::from_radix_le(inbaseradix_le, radix).unwrap(), + bigint + ); + // from_radix_be + let mut inbaseradix_be = Vec::from(inbaseradix_le); + inbaseradix_be.reverse(); + assert_eq!( + BigUint::from_radix_be(&inbaseradix_be, radix).unwrap(), + bigint + ); + } + + assert!(BigUint::from_radix_le(&[10, 100, 10], 50).is_none()); + assert_eq!(BigUint::from_radix_le(&[], 2), Some(BigUint::zero())); + assert_eq!(BigUint::from_radix_be(&[], 2), Some(BigUint::zero())); +} + +#[test] +fn test_from_str_radix() { + let r = to_str_pairs(); + for num_pair in r.iter() { + let &(ref n, ref rs) = num_pair; + for str_pair in rs.iter() { + let &(ref radix, ref str) = str_pair; + assert_eq!(n, &BigUint::from_str_radix(str, *radix).unwrap()); + } + } + + let zed = BigUint::from_str_radix("Z", 10).ok(); + assert_eq!(zed, None); + let blank = BigUint::from_str_radix("_", 2).ok(); + assert_eq!(blank, None); + let blank_one = BigUint::from_str_radix("_1", 2).ok(); + assert_eq!(blank_one, None); + let plus_one = BigUint::from_str_radix("+1", 10).ok(); + assert_eq!(plus_one, Some(BigUint::from_slice(&[1]))); + let plus_plus_one = BigUint::from_str_radix("++1", 10).ok(); + assert_eq!(plus_plus_one, None); + let minus_one = BigUint::from_str_radix("-1", 10).ok(); + assert_eq!(minus_one, None); + let zero_plus_two = BigUint::from_str_radix("0+2", 10).ok(); + assert_eq!(zero_plus_two, None); + let three = BigUint::from_str_radix("1_1", 2).ok(); + assert_eq!(three, Some(BigUint::from_slice(&[3]))); + let ff = BigUint::from_str_radix("1111_1111", 2).ok(); + assert_eq!(ff, Some(BigUint::from_slice(&[0xff]))); +} + +#[test] +fn test_all_str_radix() { + let n = BigUint::new((0..10).collect()); + for radix in 2..37 { + let s = n.to_str_radix(radix); + let x = BigUint::from_str_radix(&s, radix); + assert_eq!(x.unwrap(), n); + + let s = s.to_ascii_uppercase(); + let x = BigUint::from_str_radix(&s, radix); + assert_eq!(x.unwrap(), n); + } +} + +#[test] +fn test_big_str() { + for n in 2..=20_u32 { + let x: BigUint = BigUint::from(n).pow(10_000_u32); + let s = x.to_string(); + let y: BigUint = s.parse().unwrap(); + assert_eq!(x, y); + } +} + +#[test] +fn test_lower_hex() { + let a = BigUint::parse_bytes(b"A", 16).unwrap(); + let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:x}", a), "a"); + assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); + assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); +} + +#[test] +fn test_upper_hex() { + let a = BigUint::parse_bytes(b"A", 16).unwrap(); + let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:X}", a), "A"); + assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); + assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); +} + +#[test] +fn test_binary() { + let a = BigUint::parse_bytes(b"A", 16).unwrap(); + let hello = BigUint::parse_bytes(b"224055342307539", 10).unwrap(); + + assert_eq!(format!("{:b}", a), "1010"); + assert_eq!( + format!("{:b}", hello), + "110010111100011011110011000101101001100011010011" + ); + assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); +} + +#[test] +fn test_octal() { + let a = BigUint::parse_bytes(b"A", 16).unwrap(); + let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{:o}", a), "12"); + assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); + assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); +} + +#[test] +fn test_display() { + let a = BigUint::parse_bytes(b"A", 16).unwrap(); + let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + + assert_eq!(format!("{}", a), "10"); + assert_eq!(format!("{}", hello), "22405534230753963835153736737"); + assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); +} + +#[test] +fn test_factor() { + fn factor(n: usize) -> BigUint { + let mut f: BigUint = One::one(); + for i in 2..=n { + // FIXME(#5992): assignment operator overloads + // f *= FromPrimitive::from_usize(i); + let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); + f *= bu; + } + f + } + + fn check(n: usize, s: &str) { + let n = factor(n); + let ans = BigUint::from_str_radix(s, 10).unwrap(); + assert_eq!(n, ans); + } + + check(3, "6"); + check(10, "3628800"); + check(20, "2432902008176640000"); + check(30, "265252859812191058636308480000000"); +} + +#[test] +fn test_bits() { + assert_eq!(BigUint::new(vec![0, 0, 0, 0]).bits(), 0); + let n: BigUint = FromPrimitive::from_usize(0).unwrap(); + assert_eq!(n.bits(), 0); + let n: BigUint = FromPrimitive::from_usize(1).unwrap(); + assert_eq!(n.bits(), 1); + let n: BigUint = FromPrimitive::from_usize(3).unwrap(); + assert_eq!(n.bits(), 2); + let n: BigUint = BigUint::from_str_radix("4000000000", 16).unwrap(); + assert_eq!(n.bits(), 39); + let one: BigUint = One::one(); + assert_eq!((one << 426u16).bits(), 427); +} + +#[test] +fn test_iter_sum() { + let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); + let data: Vec = vec![ + FromPrimitive::from_u32(1000000).unwrap(), + FromPrimitive::from_u32(200000).unwrap(), + FromPrimitive::from_u32(30000).unwrap(), + FromPrimitive::from_u32(4000).unwrap(), + FromPrimitive::from_u32(500).unwrap(), + FromPrimitive::from_u32(60).unwrap(), + FromPrimitive::from_u32(7).unwrap(), + ]; + + assert_eq!(result, data.iter().sum::()); + assert_eq!(result, data.into_iter().sum::()); +} + +#[test] +fn test_iter_product() { + let data: Vec = vec![ + FromPrimitive::from_u32(1001).unwrap(), + FromPrimitive::from_u32(1002).unwrap(), + FromPrimitive::from_u32(1003).unwrap(), + FromPrimitive::from_u32(1004).unwrap(), + FromPrimitive::from_u32(1005).unwrap(), + ]; + let result = data.get(0).unwrap() + * data.get(1).unwrap() + * data.get(2).unwrap() + * data.get(3).unwrap() + * data.get(4).unwrap(); + + assert_eq!(result, data.iter().product::()); + assert_eq!(result, data.into_iter().product::()); +} + +#[test] +fn test_iter_sum_generic() { + let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); + let data = vec![1000000_u32, 200000, 30000, 4000, 500, 60, 7]; + + assert_eq!(result, data.iter().sum::()); + assert_eq!(result, data.into_iter().sum::()); +} + +#[test] +fn test_iter_product_generic() { + let data = vec![1001_u32, 1002, 1003, 1004, 1005]; + let result = data[0].to_biguint().unwrap() + * data[1].to_biguint().unwrap() + * data[2].to_biguint().unwrap() + * data[3].to_biguint().unwrap() + * data[4].to_biguint().unwrap(); + + assert_eq!(result, data.iter().product::()); + assert_eq!(result, data.into_iter().product::()); +} + +#[test] +fn test_pow() { + let one = BigUint::from(1u32); + let two = BigUint::from(2u32); + let four = BigUint::from(4u32); + let eight = BigUint::from(8u32); + let tentwentyfour = BigUint::from(1024u32); + let twentyfourtyeight = BigUint::from(2048u32); + macro_rules! check { + ($t:ty) => { + assert_eq!(Pow::pow(&two, 0 as $t), one); + assert_eq!(Pow::pow(&two, 1 as $t), two); + assert_eq!(Pow::pow(&two, 2 as $t), four); + assert_eq!(Pow::pow(&two, 3 as $t), eight); + assert_eq!(Pow::pow(&two, 10 as $t), tentwentyfour); + assert_eq!(Pow::pow(&two, 11 as $t), twentyfourtyeight); + assert_eq!(Pow::pow(&two, &(11 as $t)), twentyfourtyeight); + }; + } + check!(u8); + check!(u16); + check!(u32); + check!(u64); + check!(u128); + check!(usize); + + let pow_1e10000 = BigUint::from(10u32).pow(10_000_u32); + let manual_1e10000 = repeat(10u32).take(10_000).product::(); + assert!(manual_1e10000 == pow_1e10000); +} + +#[test] +fn test_trailing_zeros() { + assert!(BigUint::from(0u8).trailing_zeros().is_none()); + assert_eq!(BigUint::from(1u8).trailing_zeros().unwrap(), 0); + assert_eq!(BigUint::from(2u8).trailing_zeros().unwrap(), 1); + let x: BigUint = BigUint::one() << 128; + assert_eq!(x.trailing_zeros().unwrap(), 128); +} + +#[test] +fn test_trailing_ones() { + assert_eq!(BigUint::from(0u8).trailing_ones(), 0); + assert_eq!(BigUint::from(1u8).trailing_ones(), 1); + assert_eq!(BigUint::from(2u8).trailing_ones(), 0); + assert_eq!(BigUint::from(3u8).trailing_ones(), 2); + let x: BigUint = (BigUint::from(3u8) << 128) | BigUint::from(3u8); + assert_eq!(x.trailing_ones(), 2); + let x: BigUint = (BigUint::one() << 128) - BigUint::one(); + assert_eq!(x.trailing_ones(), 128); +} + +#[test] +fn test_count_ones() { + assert_eq!(BigUint::from(0u8).count_ones(), 0); + assert_eq!(BigUint::from(1u8).count_ones(), 1); + assert_eq!(BigUint::from(2u8).count_ones(), 1); + assert_eq!(BigUint::from(3u8).count_ones(), 2); + let x: BigUint = (BigUint::from(3u8) << 128) | BigUint::from(3u8); + assert_eq!(x.count_ones(), 4); +} + +#[test] +fn test_bit() { + assert!(!BigUint::from(0u8).bit(0)); + assert!(!BigUint::from(0u8).bit(100)); + assert!(!BigUint::from(42u8).bit(4)); + assert!(BigUint::from(42u8).bit(5)); + let x: BigUint = (BigUint::from(3u8) << 128) | BigUint::from(3u8); + assert!(x.bit(129)); + assert!(!x.bit(130)); +} + +#[test] +fn test_set_bit() { + let mut x = BigUint::from(3u8); + x.set_bit(128, true); + x.set_bit(129, true); + assert_eq!(x, (BigUint::from(3u8) << 128) | BigUint::from(3u8)); + x.set_bit(0, false); + x.set_bit(128, false); + x.set_bit(130, false); + assert_eq!(x, (BigUint::from(2u8) << 128) | BigUint::from(2u8)); + x.set_bit(129, false); + x.set_bit(1, false); + assert_eq!(x, BigUint::zero()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/biguint_scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint_scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/biguint_scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/biguint_scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +use num_bigint::BigUint; +use num_traits::{One, ToPrimitive, Zero}; + +use std::panic::catch_unwind; + +mod consts; +use crate::consts::*; + +#[macro_use] +mod macros; + +#[test] +fn test_scalar_add() { + fn check(x: &BigUint, y: &BigUint, z: &BigUint) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_unsigned_scalar_op!(x + y == z); + assert_unsigned_scalar_assign_op!(x += y == z); + } + + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + check(&a, &b, &c); + check(&b, &a, &c); + } +} + +#[test] +fn test_scalar_sub() { + fn check(x: &BigUint, y: &BigUint, z: &BigUint) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_unsigned_scalar_op!(x - y == z); + assert_unsigned_scalar_assign_op!(x -= y == z); + } + + for elm in SUM_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + check(&c, &a, &b); + check(&c, &b, &a); + } +} + +#[test] +fn test_scalar_mul() { + fn check(x: &BigUint, y: &BigUint, z: &BigUint) { + let (x, y, z) = (x.clone(), y.clone(), z.clone()); + assert_unsigned_scalar_op!(x * y == z); + assert_unsigned_scalar_assign_op!(x *= y == z); + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + check(&a, &b, &c); + check(&b, &a, &c); + } +} + +#[test] +fn test_scalar_rem_noncommutative() { + assert_eq!(5u8 % BigUint::from(7u8), BigUint::from(5u8)); + assert_eq!(BigUint::from(5u8) % 7u8, BigUint::from(5u8)); +} + +#[test] +fn test_scalar_div_rem() { + fn check(x: &BigUint, y: &BigUint, z: &BigUint, r: &BigUint) { + let (x, y, z, r) = (x.clone(), y.clone(), z.clone(), r.clone()); + assert_unsigned_scalar_op!(x / y == z); + assert_unsigned_scalar_op!(x % y == r); + assert_unsigned_scalar_assign_op!(x /= y == z); + assert_unsigned_scalar_assign_op!(x %= y == r); + } + + for elm in MUL_TRIPLES.iter() { + let (a_vec, b_vec, c_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + + if !a.is_zero() { + check(&c, &a, &b, &Zero::zero()); + } + + if !b.is_zero() { + check(&c, &b, &a, &Zero::zero()); + } + } + + for elm in DIV_REM_QUADRUPLES.iter() { + let (a_vec, b_vec, c_vec, d_vec) = *elm; + let a = BigUint::from_slice(a_vec); + let b = BigUint::from_slice(b_vec); + let c = BigUint::from_slice(c_vec); + let d = BigUint::from_slice(d_vec); + + if !b.is_zero() { + check(&a, &b, &c, &d); + assert_unsigned_scalar_op!(a / b == c); + assert_unsigned_scalar_op!(a % b == d); + assert_unsigned_scalar_assign_op!(a /= b == c); + assert_unsigned_scalar_assign_op!(a %= b == d); + } + } +} + +#[test] +fn test_scalar_div_rem_zero() { + catch_unwind(|| BigUint::zero() / 0u32).unwrap_err(); + catch_unwind(|| BigUint::zero() % 0u32).unwrap_err(); + catch_unwind(|| BigUint::one() / 0u32).unwrap_err(); + catch_unwind(|| BigUint::one() % 0u32).unwrap_err(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/consts/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/consts/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/consts/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/consts/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +#![allow(unused)] + +pub const N1: u32 = -1i32 as u32; +pub const N2: u32 = -2i32 as u32; + +pub const SUM_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ + (&[], &[], &[]), + (&[], &[1], &[1]), + (&[1], &[1], &[2]), + (&[1], &[1, 1], &[2, 1]), + (&[1], &[N1], &[0, 1]), + (&[1], &[N1, N1], &[0, 0, 1]), + (&[N1, N1], &[N1, N1], &[N2, N1, 1]), + (&[1, 1, 1], &[N1, N1], &[0, 1, 2]), + (&[2, 2, 1], &[N1, N2], &[1, 1, 2]), + (&[1, 2, 2, 1], &[N1, N2], &[0, 1, 3, 1]), +]; + +pub const M: u32 = u32::MAX; +pub const MUL_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ + (&[], &[], &[]), + (&[], &[1], &[]), + (&[2], &[], &[]), + (&[1], &[1], &[1]), + (&[2], &[3], &[6]), + (&[1], &[1, 1, 1], &[1, 1, 1]), + (&[1, 2, 3], &[3], &[3, 6, 9]), + (&[1, 1, 1], &[N1], &[N1, N1, N1]), + (&[1, 2, 3], &[N1], &[N1, N2, N2, 2]), + (&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]), + (&[N1], &[N1], &[1, N2]), + (&[N1, N1], &[N1], &[1, N1, N2]), + (&[N1, N1, N1], &[N1], &[1, N1, N1, N2]), + (&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]), + (&[M / 2 + 1], &[2], &[0, 1]), + (&[0, M / 2 + 1], &[2], &[0, 0, 1]), + (&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]), + (&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]), + (&[N1, N1, N1], &[N1, N1, N1, N1], &[1, 0, 0, N1, N2, N1, N1]), + (&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]), + (&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]), +]; + +pub const DIV_REM_QUADRUPLES: &[(&[u32], &[u32], &[u32], &[u32])] = &[ + (&[1], &[2], &[], &[1]), + (&[3], &[2], &[1], &[1]), + (&[1, 1], &[2], &[M / 2 + 1], &[1]), + (&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]), + (&[0, 1], &[N1], &[1], &[1]), + (&[N1, N1], &[N2], &[2, 1], &[3]), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/fuzzed.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/fuzzed.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/fuzzed.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/fuzzed.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,185 @@ +//! Check buggy inputs that were found by fuzzing + +use num_bigint::BigUint; +use num_traits::Num; + +#[test] +fn fuzzed_mul_1() { + let hex1 = "\ + cd6839ee857cf791a40494c2e522846eefbca9eca9912fdc1feed4561dbde75c75f1ddca2325ebb1\ + b9cd6eae07308578e58e57f4ddd7dc239b4fd347b883e37d87232a8e5d5a8690c8dba69c97fe8ac4\ + 58add18be7e460e03c9d1ae8223db53d20681a4027ffc17d1e43b764791c4db5ff7add849da7e378\ + ac8d9be0e8b517c490da3c0f944b6a52a0c5dc5217c71da8eec35d2c3110d8b041d2b52f3e2a8904\ + abcaaca517a8f2ef6cd26ceadd39a1cf9f770bc08f55f5a230cd81961348bb18534245430699de77\ + d93b805153cffd05dfd0f2cfc2332888cec9c5abf3ece9b4d7886ad94c784bf74fce12853b2a9a75\ + b62a845151a703446cc20300eafe7332330e992ae88817cd6ccef8877b66a7252300a4664d7074da\ + 181cd9fd502ea1cd71c0b02db3c009fe970a7d226382cdba5b5576c5c0341694681c7adc4ca2d059\ + d9a6b300957a2235a4eb6689b71d34dcc4037b520eabd2c8b66604bb662fe2bcf533ba8d242dbc91\ + f04c1795b9f0fee800d197d8c6e998248b15855a9602b76cb3f94b148d8f71f7d6225b79d63a8e20\ + 8ec8f0fa56a1c381b6c09bad9886056aec17fc92b9bb0f8625fd3444e40cccc2ede768ddb23c66ad\ + 59a680a26a26d519d02e4d46ce93cce9e9dd86702bdd376abae0959a0e8e418aa507a63fafb8f422\ + 83b03dc26f371c5e261a8f90f3ac9e2a6bcc7f0a39c3f73043b5aa5a950d4e945e9f68b2c2e593e3\ + b995be174714c1967b71f579043f89bfce37437af9388828a3ba0465c88954110cae6d38b638e094\ + 13c15c9faddd6fb63623fd50e06d00c4d5954e787158b3e4eea7e9fae8b189fa8a204b23ac2f7bbc\ + b601189c0df2075977c2424336024ba3594172bea87f0f92beb20276ce8510c8ef2a4cd5ede87e7e\ + 38b3fa49d66fbcd322be686a349c24919f4000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000"; + let hex2 = "\ + 40000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000007"; + + // Result produced independently in Python + let hex_result = "\ + 335a0e7ba15f3de469012530b948a11bbbef2a7b2a644bf707fbb515876f79d71d7c777288c97aec\ + 6e735bab81cc215e396395fd3775f708e6d3f4d1ee20f8df61c8caa39756a1a43236e9a725ffa2b1\ + 162b7462f9f918380f2746ba088f6d4f481a069009fff05f4790edd91e47136d7fdeb7612769f8de\ + 2b2366f83a2d45f124368f03e512da94a831771485f1c76a3bb0d74b0c44362c1074ad4bcf8aa241\ + 2af2ab2945ea3cbbdb349b3ab74e6873e7ddc2f023d57d688c33606584d22ec614d09150c1a6779d\ + f64ee01454f3ff4177f43cb3f08cca2233b2716afcfb3a6d35e21ab6531e12fdd3f384a14ecaa69d\ + 6d8aa1145469c0d11b3080c03abf9ccc8cc3a64aba2205f35b33be21ded9a9c948c02919935c1d36\ + 8607367f540ba8735c702c0b6cf0027fa5c29f4898e0b36e96d55db1700d05a51a071eb71328b416\ + 7669acc0255e888d693ad9a26dc74d373100ded483aaf4b22d99812ed98bf8af3d4ceea3490b6f24\ + 7c1305e56e7c3fba003465f631ba660922c56156a580addb2cfe52c52363dc7df58896de758ea388\ + 23b23c3e95a870e06db026eb6621815abb05ff24ae6ec3e1897f4d1139033330bb79da376c8f19ab\ + 5669a0289a89b546740b9351b3a4f33a7a77619c0af74ddaaeb8256683a39062a941e98febee3d08\ + a0ec0f709bcdc7178986a3e43ceb278a9af31fc28e70fdcc10ed6a96a54353a517a7da2cb0b964f8\ + ee656f85d1c530659edc7d5e410fe26ff38dd0debe4e220a28ee811972225504432b9b4e2d8e3825\ + 04f05727eb775bed8d88ff54381b40313565539e1c562cf93ba9fa7eba2c627ea28812c8eb0bdeef\ + 2d804627037c81d65df09090cd8092e8d6505cafaa1fc3e4afac809db3a144323bca93358117f935\ + 13d3695771180f461cf38bb995b531c9e072f84f04df87ce5ad0315387399d1086f60971dc149e06\ + c23253a64e46e467b210e704f93f2ec6f60b9b386eb1f629e48d79adf57e018e4827f5cb5e6cc0ba\ + d3573ea621a84bbc58efaff4abe2d8b7c117fe4a6bd3da03bf4fc61ff9fc5c0ea04f97384cb7df43\ + 265cf3a65ff5f7a46d0e0fe8426569063ea671cf9e87578c355775ecd1ccc2f44ab329bf20b28ab8\ + 83a59ea48bf9c0fa6c0c936cad5c415243eb59b76f559e8b1a86fd1daa46cfe4d52e351546f0a082\ + 394aafeb291eb6a3ae4f661bbda78467b3ab7a63f1e4baebf1174a13c32ea281a49e2a3937fb299e\ + 393b9116def94e15066cf5265f6566302c5bb8a69df9a8cbb45fce9203f5047ecc1e1331f6a8c9f5\ + ed31466c9e1c44d13fea4045f621496bf0b893a0187f563f68416c9e0ed8c75c061873b274f38ee5\ + 041656ef77826fcdc401cc72095c185f3e66b2c37cfcca211fcb4f332ab46a19dbfd4027fd9214a5\ + 181596f85805bb26ed706328ffcd96a57a1a1303f8ebd10d8fdeec1dc6daf08054db99e2e3e77e96\ + d85e6c588bff4441bf2baa25ec74a7e803141d6cab09ec6de23c5999548153de0fdfa6cebd738d84\ + 70e70fd3b4b1441cefa60a9a65650ead11330c83eb1c24173665e3caca83358bbdce0eacf199d1b0\ + 510a81c6930ab9ecf6a9b85328f2977947945bc251d9f7a87a135d260e965bdce354470b3a131832\ + a2f1914b1d601db64f1dbcc43ea382d85cd08bb91c7a161ec87bc14c7758c4fc8cfb8e240c8a4988\ + 5dc10e0dfb7afbed3622fb0561d715254b196ceb42869765dc5cdac5d9c6e20df9b54c6228fa07ac\ + 44619e3372464fcfd67a10117770ca23369b796d0336de113fa5a3757e8a2819d9815b75738cebd8\ + 04dd0e29c5f334dae77044fffb5ac000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000"; + + let bn1 = &BigUint::from_str_radix(hex1, 16).unwrap(); + let bn2 = &BigUint::from_str_radix(hex2, 16).unwrap(); + let result = BigUint::from_str_radix(hex_result, 16).unwrap(); + + assert_eq!(bn1 * bn2, result); + assert_eq!(bn2 * bn1, result); +} + +#[test] +fn fuzzed_mul_2() { + let hex_a = "\ + 812cff04ff812cff04ff8180ff80ffff11ff80ff2cff04ff812cff04ff812cff04ff81232cff047d\ + ff04ff812cff04ff812cff04ff812cff047f812cff04ff8180ff2cff04ff04ff8180ff2cff04ff04\ + ff812cbf04ff8180ff2cff04ff812cff0401010000000000000000ffff1a80ffc006c70084ffff80\ + ffc0064006000084ffff72ffc020ffffffffffff06d709000000dbffffffc799999999b999999999\ + 99999999000084ffff72ffc02006e1ffffffc70900ffffff00f312ff80ebffffff6f505f6c2e6712\ + 108970ffff5f6c6f6727020000000000007400000000000000000000a50000000000000000000000\ + 000000000000000000000000ff812cff04ff812cff2c04ff812cff8180ff2cff04ff04ff818b8b8b\ + 8b8b8b8b8b8b8b8b8b8b8b8b8b06c70084ffff80ffc006c700847fff80ffc006c700ffff12c70084\ + ffff80ffc0060000000000000056ff00c789bfff80ffc006c70084ffff80ffc006c700ffff840100\ + 00000000001289ffc08b8b8b8b8b8b8b2c"; + let hex_b = "\ + 7ed300fb007ed300fb007e7f00db00fb007ed3007ed300fb007edcd300fb8200fb007ed300fb007e\ + d300fb007ed300fb007ed300fbfeffffffffffffa8fb007e7f00d300fb00fb007ed340fb007e7f00\ + 00fb007ed300fb007ed300fb007e7f00d300fb00fb007e7f00d300fb007efb007e7f00d300fb007e\ + d300fb007e7f0097d300fb00bf007ed300fb007ed300fb00fb00fb00fbffffffffffffffffffff00\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000df9b3900ff908fa08d9e968c9a0000e7fffb7fff0000003fd9004c90d8f600de7f00\ + 3fdf9b3900ff908fa08d9e968cf9b9ff0000ed38ff7b00007f003ff9ffffffffffffffa900ff3876\ + 000078003ff938ff7b00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d300\ + fb00fb007e7f00d300fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb017e\ + d300fb007ed300fb007edcd300fb8200fb007e0000e580"; + let hex_c = "\ + 7b00387ffff938ff7b80007f003ff9b9ff00fdec38ff7b00007f003ff9ffffffffffffffa900ff38\ + 76000078003ff938ff7b00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d3\ + 00fb00fb007e7f00d300fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb01\ + 7ed300fb007ed300fb007edcd300fb8200fb007e000000ee7f003f0000007b00387ffff938ff7b80\ + 007f003ff9b9ff00fdec38ff7b00007f003ff9ffffffffffffffa900ff3876000078003ff938ff7b\ + 00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d300fb00fb007e7f00d300\ + fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb017ed300fb007ed300fb00\ + 7edcd300fb8200fb007e000000ee7f003f000000000000000000000000000000002a000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000df9b3900ff908fa08d9e968c9a0000e7fffb7fff0000003fd9004c90d8\ + f600de7f003fdf9b3900ff908fa08d9e968c9a0000e7fffa7fff0000004005004c90d8f600de908f\ + dcd300fb8200fb007e0000e57f003ff938ff7b00007f003d7ed300fb007ed300fb007ed300fb007e\ + fa00fb007ed300fbf9ffffffffffffffa900ff387600007f003ff938ff7b00007f003ff938fd0000\ + 7bfeffffffffffffed76003f74747474747474d300fc"; + + // Result produced independently in Python + let hex_result = "\ + 1ebf6415da7ac71a689cd450727b7a361402a1626e0b6cd057e0e2a77d4cb722c1b7d0cbd73a7c07\ + d756813fe97d73d5905c4a26404c7162769ba2dbc1e2742855a1db803e2d2c2fddc77c0598cc70fe\ + 066fd4b81cae3e23c55b4795de63acacd1343cf5ad5e715e6919d140c01bab1af1a737ebbf8a7775\ + 7602acd611f555ee2d5be56cc14b97c248009cd77490a3dfd6762bae25459a544e369eb4b0cc952a\ + 8e6a551ff35a4a7a6e5f5b0b72495c4baadf3a26b9d5d97402ad60fa2324e93adc96ca159b62d147\ + 5695f26ff27da100a76e2d273420572e61b4dfbd97e826d9d946f85b87434523f6aa7ce43c443285\ + 33f5b5adf32574167b1e9ea3bf6254d6afacf865894907de196285169cfcc1c0fcf438873d13f7e8\ + 654acc27c1abb00bec2729e34c994ff2152f60406f75db3ab616541795d9db8ca0b381148de7875f\ + e7a8191407abc390718003698ca28498948caf1dbc3f02593dd85fa929ebae86cfe783d7be473e98\ + 0060d9ec60843661cb4cb9b8ddb24bb710f93700b22530501b5ea26c5c94c7370fe0ccbafe0ce7e4\ + cd4f071d0cf0ac151c85a5b132ecaa75793abfb4a6ee33fddd2aa2f5cf2a8eb19c75322792c0d8dc\ + 1efb2dcd8ae2b49dd57b84898f531c7f745464f637716151831db56b3e293f587dc95a5e12edfe6b\ + 8458033dddf3556da55bef55ba3c3769def0c0f0c86786aca8313dc0ce09118760721eb545d69b46\ + cdb89d377f2c80e67b572da0f75760c2849288a8457c18c6f0b58244b7f95a7567ce23756f1fe359\ + 64f7e84fbe28b188157519dd99b8798b076e21984d15c37f41da1309e0fbc539e8b9b09fed36a908\ + 28c94f72e7b755c187e58db6bfef0c02309086626ad0fe2efd2ff1467b3de11e057687865f4f85e7\ + 0a39bcbc4674dcaded9b04562afe08eb92fbd96ea4a99aa4f9347a075d4421f070ce3a33225f5af1\ + 9c27ec5d1720e659ca7fff9686f46b01d76d7de64c738671aaec57ee5582ef7956206fb37c6a36f8\ + 8f226ce2124a7f9894a0e9a7aa02001746e6def35699d7adc84a7dcf513ff3da20fd849950f41a5d\ + bb02c91666697156d69ebbe2ef26732b6595d1b6d014a60006d2d3c7055ff9b531779195b8dcd7d9\ + 426e776cbc9041735384568ba4adbf7eeea7e0e6cbb47b70335a7ed12a68904eecd334921e4ae6d9\ + c983af20d73215c39573963f03bc87082450cc1c70250e1e8eaa318acaf044a072891fc60324d134\ + 6c0a1d02cceb4d4806e536d6017bf6bc125c41694ded38766fea51bfbf7a008ca0b3eb1168766486\ + 8aa8469b3e6787a5d5bad6cd67c24005a5cbaa10b63d1b4d05ac42a8b31263052a1260b5900be628\ + 4dcab4eb0cf5cda815412ced7bd78f87c00ac3581f41a04352a4a186805a5c9e37b14561a5fc97d2\ + 52ca4654fe3d82f42080c21483789cc4b4cbb568f79844f7a317aa2a6555774da26c6f027d3cb0ee\ + 9276c6dc4f285fc3b4b9a3cd51c8815cebf110e73c80a9b842cc3b7c80af13f702662b10e868eb61\ + 947000b390cd2f3a0899f6f1bab86acf767062f5526507790645ae13b9701ba96b3f873047c9d3b8\ + 5e8a5d904a01fbfe10e63495b6021e7cc082aa66679e4d92b3e4e2d62490b44f7e250584cedff0e7\ + 072a870ddaa9687a1eae11afc874d83065fb98dbc3cfd90f39517ff3015c71a8c0ab36a6483c7b87\ + f41b2c832fa9428fe95ffba4e49cc553d9e2d33a540958da51588e5120fef6497bfaa96a4dcfc024\ + 8170c57f78e9ab9546efbbaf8e9ad6a993493577edd3d29ce8fd9a2e9eb4363b5b472a4ecb2065eb\ + 38f876a841af1f227a703248955c8978329dffcd8e065d8da4d42504796ff7abc62832ed86c4f8d0\ + 0f55cd567fb9d42524be57ebdacef730c3f94c0372f86fa1b0114f8620f553e4329b2a586fcfeedc\ + af47934909090e14a1f1204e6f1681fb2df05356381e6340f4feaf0787e06218b0b0d8df51acb0bc\ + f98546f33273adf260da959d6fc4a04872122af6508d124abb963c14c30e7c07fee368324921fe33\ + 9ae89490c5d6cdae0c356bb6921de95ea13b54e23800"; + + let a = &BigUint::from_str_radix(hex_a, 16).unwrap(); + let b = &BigUint::from_str_radix(hex_b, 16).unwrap(); + let c = &BigUint::from_str_radix(hex_c, 16).unwrap(); + let result = BigUint::from_str_radix(hex_result, 16).unwrap(); + + assert_eq!(a * b * c, result); + assert_eq!(a * c * b, result); + assert_eq!(b * a * c, result); + assert_eq!(b * c * a, result); + assert_eq!(c * a * b, result); + assert_eq!(c * b * a, result); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/macros/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/macros/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/macros/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/macros/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +#![allow(unused)] + +/// Assert that an op works for all val/ref combinations +macro_rules! assert_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_eq!((&$left) $op (&$right), $expected); + assert_eq!((&$left) $op $right.clone(), $expected); + assert_eq!($left.clone() $op (&$right), $expected); + assert_eq!($left.clone() $op $right.clone(), $expected); + }; +} + +/// Assert that an assign-op works for all val/ref combinations +macro_rules! assert_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => {{ + let mut left = $left.clone(); + assert_eq!({ left $op &$right; left}, $expected); + + let mut left = $left.clone(); + assert_eq!({ left $op $right.clone(); left}, $expected); + }}; +} + +/// Assert that an op works for scalar left or right +macro_rules! assert_scalar_op { + (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { + $( + if let Some(left) = $left.$to() { + assert_op!(left $op $right == $expected); + } + if let Some(right) = $right.$to() { + assert_op!($left $op right == $expected); + } + )* + }; +} + +macro_rules! assert_unsigned_scalar_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) + $left $op $right == $expected); + }; +} + +macro_rules! assert_signed_scalar_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, + to_i8, to_i16, to_i32, to_i64, to_isize, to_i128) + $left $op $right == $expected); + }; +} + +/// Assert that an op works for scalar right +macro_rules! assert_scalar_assign_op { + (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { + $( + if let Some(right) = $right.$to() { + let mut left = $left.clone(); + assert_eq!({ left $op right; left}, $expected); + } + )* + }; +} + +macro_rules! assert_unsigned_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) + $left $op $right == $expected); + }; +} + +macro_rules! assert_signed_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, + to_i8, to_i16, to_i32, to_i64, to_isize, to_i128) + $left $op $right == $expected); + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/modpow.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/modpow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/modpow.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/modpow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,181 @@ +static BIG_B: &str = "\ + efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\ + ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\ + aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\ + 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\ + 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\ + 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\ + 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\ + 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\ + 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\ + b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\ + b4edf9cc_6ce540be_76229093_5c53893b"; + +static BIG_E: &str = "\ + be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\ + a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\ + 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\ + eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\ + 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\ + c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\ + 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\ + f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\ + a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\ + e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\ + 17946850_2ddb1822_117b68a0_32f7db88"; + +// This modulus is the prime from the 2048-bit MODP DH group: +// https://tools.ietf.org/html/rfc3526#section-3 +static BIG_M: &str = "\ + FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ + 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ + EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ + E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ + EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ + C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ + 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ + 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ + E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ + DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ + 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; + +static BIG_R: &str = "\ + a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\ + eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\ + 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\ + 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\ + fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\ + 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\ + 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\ + d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\ + 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\ + f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\ + 109c4735_6e7db425_7b5d74c7_0b709508"; + +mod biguint { + use num_bigint::BigUint; + use num_integer::Integer; + use num_traits::Num; + + fn check_modpow>(b: T, e: T, m: T, r: T) { + let b: BigUint = b.into(); + let e: BigUint = e.into(); + let m: BigUint = m.into(); + let r: BigUint = r.into(); + + assert_eq!(b.modpow(&e, &m), r); + + let even_m = &m << 1; + let even_modpow = b.modpow(&e, &even_m); + assert!(even_modpow < even_m); + assert_eq!(even_modpow.mod_floor(&m), r); + } + + #[test] + fn test_modpow_single() { + check_modpow::(1, 0, 11, 1); + check_modpow::(0, 15, 11, 0); + check_modpow::(3, 7, 11, 9); + check_modpow::(5, 117, 19, 1); + check_modpow::(20, 1, 2, 0); + check_modpow::(20, 1, 3, 2); + } + + #[test] + fn test_modpow_small() { + for b in 0u64..11 { + for e in 0u64..11 { + for m in 1..11 { + check_modpow::(b, e, m, b.pow(e as u32) % m); + } + } + } + } + + #[test] + fn test_modpow_big() { + let b = BigUint::from_str_radix(super::BIG_B, 16).unwrap(); + let e = BigUint::from_str_radix(super::BIG_E, 16).unwrap(); + let m = BigUint::from_str_radix(super::BIG_M, 16).unwrap(); + let r = BigUint::from_str_radix(super::BIG_R, 16).unwrap(); + + assert_eq!(b.modpow(&e, &m), r); + + let even_m = &m << 1; + let even_modpow = b.modpow(&e, &even_m); + assert!(even_modpow < even_m); + assert_eq!(even_modpow % m, r); + } +} + +mod bigint { + use num_bigint::BigInt; + use num_integer::Integer; + use num_traits::{Num, One, Signed}; + + fn check_modpow>(b: T, e: T, m: T, r: T) { + fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) { + assert_eq!(&b.modpow(e, m), r, "{} ** {} (mod {}) != {}", b, e, m, r); + + let even_m = m << 1u8; + let even_modpow = b.modpow(e, m); + assert!(even_modpow.abs() < even_m.abs()); + assert_eq!(&even_modpow.mod_floor(m), r); + + // the sign of the result follows the modulus like `mod_floor`, not `rem` + assert_eq!(b.modpow(&BigInt::one(), m), b.mod_floor(m)); + } + + let b: BigInt = b.into(); + let e: BigInt = e.into(); + let m: BigInt = m.into(); + let r: BigInt = r.into(); + + let neg_b_r = if e.is_odd() { + (-&r).mod_floor(&m) + } else { + r.clone() + }; + let neg_m_r = r.mod_floor(&-&m); + let neg_bm_r = neg_b_r.mod_floor(&-&m); + + check(&b, &e, &m, &r); + check(&-&b, &e, &m, &neg_b_r); + check(&b, &e, &-&m, &neg_m_r); + check(&-b, &e, &-&m, &neg_bm_r); + } + + #[test] + fn test_modpow() { + check_modpow(1, 0, 11, 1); + check_modpow(0, 15, 11, 0); + check_modpow(3, 7, 11, 9); + check_modpow(5, 117, 19, 1); + check_modpow(-20, 1, 2, 0); + check_modpow(-20, 1, 3, 1); + } + + #[test] + fn test_modpow_small() { + for b in -10i64..11 { + for e in 0i64..11 { + for m in -10..11 { + if m == 0 { + continue; + } + check_modpow(b, e, m, b.pow(e as u32).mod_floor(&m)); + } + } + } + } + + #[test] + fn test_modpow_big() { + let b = BigInt::from_str_radix(super::BIG_B, 16).unwrap(); + let e = BigInt::from_str_radix(super::BIG_E, 16).unwrap(); + let m = BigInt::from_str_radix(super::BIG_M, 16).unwrap(); + let r = BigInt::from_str_radix(super::BIG_R, 16).unwrap(); + + check_modpow(b, e, m, r); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/roots.rs clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/roots.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-bigint/tests/roots.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-bigint/tests/roots.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,159 @@ +mod biguint { + use num_bigint::BigUint; + use num_traits::{One, Zero}; + + fn check>(x: T, n: u32) { + let x: BigUint = x.into(); + let root = x.nth_root(n); + println!("check {}.nth_root({}) = {}", x, n, root); + + if n == 2 { + assert_eq!(root, x.sqrt()) + } else if n == 3 { + assert_eq!(root, x.cbrt()) + } + + let lo = root.pow(n); + assert!(lo <= x); + assert_eq!(lo.nth_root(n), root); + if !lo.is_zero() { + assert_eq!((&lo - 1u32).nth_root(n), &root - 1u32); + } + + let hi = (&root + 1u32).pow(n); + assert!(hi > x); + assert_eq!(hi.nth_root(n), &root + 1u32); + assert_eq!((&hi - 1u32).nth_root(n), root); + } + + #[test] + fn test_sqrt() { + check(99u32, 2); + check(100u32, 2); + check(120u32, 2); + } + + #[test] + fn test_cbrt() { + check(8u32, 3); + check(26u32, 3); + } + + #[test] + fn test_nth_root() { + check(0u32, 1); + check(10u32, 1); + check(100u32, 4); + } + + #[test] + #[should_panic] + fn test_nth_root_n_is_zero() { + check(4u32, 0); + } + + #[test] + fn test_nth_root_big() { + let x = BigUint::from(123_456_789_u32); + let expected = BigUint::from(6u32); + + assert_eq!(x.nth_root(10), expected); + check(x, 10); + } + + #[test] + fn test_nth_root_googol() { + let googol = BigUint::from(10u32).pow(100u32); + + // perfect divisors of 100 + for &n in &[2, 4, 5, 10, 20, 25, 50, 100] { + let expected = BigUint::from(10u32).pow(100u32 / n); + assert_eq!(googol.nth_root(n), expected); + check(googol.clone(), n); + } + } + + #[test] + fn test_nth_root_twos() { + const EXP: u32 = 12; + const LOG2: usize = 1 << EXP; + let x = BigUint::one() << LOG2; + + // the perfect divisors are just powers of two + for exp in 1..=EXP { + let n = 2u32.pow(exp); + let expected = BigUint::one() << (LOG2 / n as usize); + assert_eq!(x.nth_root(n), expected); + check(x.clone(), n); + } + + // degenerate cases should return quickly + assert!(x.nth_root(x.bits() as u32).is_one()); + assert!(x.nth_root(i32::MAX as u32).is_one()); + assert!(x.nth_root(u32::MAX).is_one()); + } + + #[test] + fn test_roots_rand1() { + // A random input that found regressions + let s = "575981506858479247661989091587544744717244516135539456183849\ + 986593934723426343633698413178771587697273822147578889823552\ + 182702908597782734558103025298880194023243541613924361007059\ + 353344183590348785832467726433749431093350684849462759540710\ + 026019022227591412417064179299354183441181373862905039254106\ + 4781867"; + let x: BigUint = s.parse().unwrap(); + + check(x.clone(), 2); + check(x.clone(), 3); + check(x.clone(), 10); + check(x, 100); + } +} + +mod bigint { + use num_bigint::BigInt; + use num_traits::Signed; + + fn check(x: i64, n: u32) { + let big_x = BigInt::from(x); + let res = big_x.nth_root(n); + + if n == 2 { + assert_eq!(&res, &big_x.sqrt()) + } else if n == 3 { + assert_eq!(&res, &big_x.cbrt()) + } + + if big_x.is_negative() { + assert!(res.pow(n) >= big_x); + assert!((res - 1u32).pow(n) < big_x); + } else { + assert!(res.pow(n) <= big_x); + assert!((res + 1u32).pow(n) > big_x); + } + } + + #[test] + fn test_nth_root() { + check(-100, 3); + } + + #[test] + #[should_panic] + fn test_nth_root_x_neg_n_even() { + check(-100, 4); + } + + #[test] + #[should_panic] + fn test_sqrt_x_neg() { + check(-4, 2); + } + + #[test] + fn test_cbrt() { + check(8, 3); + check(-8, 3); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-complex/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-complex/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"be22c6c42e3ff58cad231bd79e4f71ba1c232ce3637c68576149993d2022a198","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fa93b9b268ee49bcecd3aba356fce28262417153b7327a3a947ebabf6552708b","RELEASES.md":"7b9cb33f7b029d8c7c28d851e3b4acd74875fdd85922c36c749c02c43f10354b","src/cast.rs":"8206bcfb99b712340383332fb760dba9cee4be8c994bd9a38d0b8c6e6bc5f7b1","src/complex_float.rs":"006a4331feac2d747fef2928b4af7dc3b892e55749313f73c0396a2107339edb","src/crand.rs":"d92d8227b5b02186abc81ca8153be404a9ef0a5273deefec921d2d7f74bf6a66","src/lib.rs":"6ffac58fe149de736c70f91d05d29e797376d177d30199b37ef2189ec704cbcc","src/pow.rs":"974fd585da8c2b7ac3f68e93a3881c56a3f0f3e506009fb3d862c6000064abb7"},"package":"23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"aa92590a9f016913f0ebe3c6e1e84d775ad20902872a2eb446a71c39d145d72f","Cargo.toml":"be22c6c42e3ff58cad231bd79e4f71ba1c232ce3637c68576149993d2022a198","Cargo.toml.orig":"912aea88f7eb2ac6bd20c06fd560307a592d9d18462c5f31ae4ab279bc03b9db","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fa93b9b268ee49bcecd3aba356fce28262417153b7327a3a947ebabf6552708b","RELEASES.md":"7b9cb33f7b029d8c7c28d851e3b4acd74875fdd85922c36c749c02c43f10354b","src/cast.rs":"8206bcfb99b712340383332fb760dba9cee4be8c994bd9a38d0b8c6e6bc5f7b1","src/complex_float.rs":"006a4331feac2d747fef2928b4af7dc3b892e55749313f73c0396a2107339edb","src/crand.rs":"d92d8227b5b02186abc81ca8153be404a9ef0a5273deefec921d2d7f74bf6a66","src/lib.rs":"6ffac58fe149de736c70f91d05d29e797376d177d30199b37ef2189ec704cbcc","src/pow.rs":"974fd585da8c2b7ac3f68e93a3881c56a3f0f3e506009fb3d862c6000064abb7"},"package":"23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-complex/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-complex/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-complex/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0eb3e9019b104abd1916a8aaed3f1fbeb93eed0e" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-complex/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-complex/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-complex/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-complex/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Complex numbers implementation for Rust" +documentation = "https://docs.rs/num-complex" +homepage = "https://github.com/rust-num/num-complex" +keywords = ["mathematics", "numerics"] +categories = ["algorithms", "data-structures", "science", "no-std"] +license = "MIT OR Apache-2.0" +name = "num-complex" +repository = "https://github.com/rust-num/num-complex" +version = "0.4.5" +readme = "README.md" +exclude = ["/ci/*", "/.github/*"] +edition = "2018" + +[package.metadata.docs.rs] +features = ["bytemuck", "std", "serde", "rkyv/size_64", "bytecheck", "rand"] + +[dependencies] + +[dependencies.bytemuck] +optional = true +version = "1" + +[dependencies.num-traits] +version = "0.2.11" +default-features = false +features = ["i128"] + +[dependencies.serde] +optional = true +version = "1.0" +default-features = false + +[dependencies.rkyv] +optional = true +version = "0.7" +default-features = false + +[dependencies.bytecheck] +optional = true +version = "0.6" +default-features = false + +[dependencies.rand] +optional = true +version = "0.8" +default-features = false + +[features] +default = ["std"] +std = ["num-traits/std"] +libm = ["num-traits/libm"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"50505a63a3ff49c7e98d824a8920aea73127036a05ae126e7dd99fbbcb1ef397","Cargo.toml":"659a3cf18a53cb7bcf017efaf2e498494e854f91ebb56c9acb067e94f076f43a","Cargo.toml.orig":"181f1b6da8e4b87decfd2746416d848d354161ab7db3188f18de5e90b0e3fa72","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"4087ceabb42281161bc074db61ad4d888343f159e60e49776559a179eda34193","RELEASES.md":"044558c5a745c96d6aecec2cd073a522d9919ba9873aa21b54c90c73e850accd","src/lib.rs":"dc254b4419136764ea0d5217e21cdbb8081142b6bc87a659c0d285573aebb181","tests/empty_enum.rs":"1b2312ec2fc9866fce7172e71e0aa2efcc3cb9d7659d0b633eb352bb1e080d53","tests/issue-16.rs":"4a056b4a688805fc95f01642f016da6dadb46d1c67ceb82e5b5eaf9fe2db92cd","tests/issue-6.rs":"b7fbbe86ff82933c15ec09fabadca02d2c70e184af30b9887cae83ed2f60367e","tests/issue-9.rs":"4c87f70a63e56c24480028fafa39a845d127620141df21bc0abfa23f84ff9bb7","tests/newtype-2015.rs":"163f76f0c139c3621ba7416cec5f9fb966c86c5ebed270df77196cf75d62402f","tests/newtype-2018.rs":"ce5b005d805690b8200f6752d24a5ebe7d248703d0aa619489c6d821b3df4b9c","tests/newtype.rs":"e7beacc831d911bae50424624a6d8823ef9eb6f7a0e2774b99be30c7977b927e","tests/no_implicit_prelude.rs":"7274f4fef6c35eb374eb2be2d352808f51deef06c02f819ae0e3d1521eebc610","tests/num_derive_without_num.rs":"3ce528221a2cb752859e20c5423c4b474fec714b41d8c1b62f5614b165d7262b","tests/trivial-2015.rs":"1745e23dfafb8c717365e57d79323c61c7d4ceaa092d7399ed793fd4f2de8ff6","tests/trivial-2018.rs":"645f0ff3c3c0d014b6891bd310de2bc5f3ccb3019cb70d0b653061eb6571f7cf","tests/trivial.rs":"a6b0faab04527f6835f43cd72317a00065a7a6cf4c506d04e77f898134f7a59b","tests/with_custom_values.rs":"4f2ea85d1f987c6620efe5bda095477c3b669af3cb67f98935c5a7d59d28b339"},"package":"ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7cc33515dd2ae0eb43c5795c50ce49c554e8ba02" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56.0" +name = "num-derive" +version = "0.4.2" +authors = ["The Rust Project Developers"] +exclude = [ + "/ci/*", + "/.github/*", +] +description = "Numeric syntax extensions" +homepage = "https://github.com/rust-num/num-derive" +documentation = "https://docs.rs/num-derive" +readme = "README.md" +keywords = [ + "mathematics", + "numerics", +] +categories = ["science"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-derive" + +[lib] +name = "num_derive" +test = false +proc-macro = true + +[[test]] +name = "newtype-2015" +edition = "2015" + +[[test]] +name = "newtype-2018" +edition = "2018" + +[[test]] +name = "trivial-2015" +edition = "2015" + +[[test]] +name = "trivial-2018" +edition = "2018" + +[dependencies.proc-macro2] +version = "1" + +[dependencies.quote] +version = "1" + +[dependencies.syn] +version = "2.0.5" + +[dev-dependencies.num] +version = "0.4" + +[dev-dependencies.num-traits] +version = "0.2" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Numeric syntax extensions" +documentation = "https://docs.rs/num-derive" +homepage = "https://github.com/rust-num/num-derive" +keywords = ["mathematics", "numerics"] +categories = [ "science" ] +license = "MIT OR Apache-2.0" +name = "num-derive" +repository = "https://github.com/rust-num/num-derive" +version = "0.4.2" +readme = "README.md" +exclude = ["/ci/*", "/.github/*"] +edition = "2021" +rust-version = "1.56.0" + +[dependencies] +proc-macro2 = "1" +quote = "1" +syn = "2.0.5" + +[dev-dependencies] +num = "0.4" +num-traits = "0.2" + +[lib] +name = "num_derive" +proc-macro = true +test = false + +# Most of the tests are left implicily detected, compiled for Rust 2021, +# but let's try a few of them with the older editions too. + +[[test]] +name = "newtype-2015" +edition = "2015" + +[[test]] +name = "newtype-2018" +edition = "2018" + +[[test]] +name = "trivial-2015" +edition = "2015" + +[[test]] +name = "trivial-2018" +edition = "2018" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/README.md clamav-1.4.6+dfsg/.cargo/vendor/num-derive/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +# num-derive + +[![crate](https://img.shields.io/crates/v/num-derive.svg)](https://crates.io/crates/num-derive) +[![documentation](https://docs.rs/num-derive/badge.svg)](https://docs.rs/num-derive) +[![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![build status](https://github.com/rust-num/num-derive/workflows/master/badge.svg)](https://github.com/rust-num/num-derive/actions) + +Procedural macros to derive numeric traits in Rust. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +num-traits = "0.2" +num-derive = "0.4" +``` + +and this to your crate root: + +```rust +#[macro_use] +extern crate num_derive; +``` + +Then you can derive traits on your own types: + +```rust +#[derive(FromPrimitive, ToPrimitive)] +enum Color { + Red, + Blue, + Green, +} +``` + +## Optional features + +- **`full-syntax`** — Enables `num-derive` to handle enum discriminants + represented by complex expressions. Usually can be avoided by + [utilizing constants], so only use this feature if namespace pollution is + undesired and [compile time doubling] is acceptable. + +[utilizing constants]: https://github.com/rust-num/num-derive/pull/3#issuecomment-359044704 +[compile time doubling]: https://github.com/rust-num/num-derive/pull/3#issuecomment-359172588 + +## Releases + +Release notes are available in [RELEASES.md](RELEASES.md). + +## Compatibility + +The `num-derive` crate is tested for rustc 1.56 and greater. + +## License + +Licensed under either of + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/RELEASES.md clamav-1.4.6+dfsg/.cargo/vendor/num-derive/RELEASES.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/RELEASES.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/RELEASES.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,129 @@ +# Release 0.4.2 (2024-02-06) + +- [Use anon-const to avoid RFC 3373 warnings.][62] + +[62]: https://github.com/rust-num/num-derive/pull/62 + +# Release 0.4.1 (2023-10-07) + +- [Make `Float` work with `no_std`][56] -- thanks @vkahl! +- [Emit full paths for `Option` and `Result`.][57] +- [Add derive macro for `num_traits::Signed` and `Unsigned`][55] -- thanks @tdelabro! + +[55]: https://github.com/rust-num/num-derive/pull/55 +[56]: https://github.com/rust-num/num-derive/pull/56 +[57]: https://github.com/rust-num/num-derive/pull/57 + +# Release 0.4.0 (2023-06-29) + +- [Update to syn-2][54] -- thanks @maurer! + - This raises the minimum supported rustc to 1.56. + - The "full-syntax" feature has also been removed. + +[54]: https://github.com/rust-num/num-derive/pull/54 + +# Release 0.3.3 (2020-10-29) + +- [Make `NumOps` work with `no_std`][41] -- thanks @jedrzejboczar! + +[41]: https://github.com/rust-num/num-derive/pull/41 + +# Release 0.3.2 (2020-08-24) + +- [Add `#[inline]` to all derived functions][40] -- thanks @Amanieu! + +[40]: https://github.com/rust-num/num-derive/pull/40 + +# Release 0.3.1 (2020-07-28) + +- [Add `num_traits` proc_macro helper for explicit import][35] - thanks @jean-airoldie! +- [Provide nicer parse errors and suggest "full-syntax"][39] + +[35]: https://github.com/rust-num/num-derive/pull/35 +[39]: https://github.com/rust-num/num-derive/pull/39 + +# Release 0.3.0 (2019-09-27) + +- [Updated the `proc-macro2`, `quote`, and `syn` dependencies to 1.0][28], + which raises the minimum supported rustc to 1.31. + +[28]: https://github.com/rust-num/num-derive/pull/28 + +# Release 0.2.5 (2019-04-23) + +- [Improved the masking of lints in derived code][23]. + +[23]: https://github.com/rust-num/num-derive/pull/23 + +# Release 0.2.4 (2019-01-25) + +- [Adjusted dependencies to allow no-std targets][22]. + +[22]: https://github.com/rust-num/num-derive/pull/22 + +# Release 0.2.3 (2018-10-03) + +- [Added newtype deriving][17] for `FromPrimitive`, `ToPrimitive`, + `NumOps`, `NumCast`, `Zero`, `One`, `Num`, and `Float`. + Thanks @asayers! + +[17]: https://github.com/rust-num/num-derive/pull/17 + +# Release 0.2.2 (2018-05-22) + +- [Updated dependencies][14]. + +[14]: https://github.com/rust-num/num-derive/pull/14 + +# Release 0.2.1 (2018-05-09) + +- [Updated dependencies][12] -- thanks @spearman! + +[12]: https://github.com/rust-num/num-derive/pull/12 + +# Release 0.2.0 (2018-02-21) + +- [Discriminant matching is now simplified][10], casting values directly by + name, rather than trying to compute offsets from known values manually. +- **breaking change**: [Derivations now import the traits from `num-traits`][11] + instead of the full `num` crate. These are still compatible, but users need + to have an explicit `num-traits = "0.2"` dependency in their `Cargo.toml`. + +[10]: https://github.com/rust-num/num-derive/pull/10 +[11]: https://github.com/rust-num/num-derive/pull/11 + + +# Release 0.1.44 (2018-01-26) + +- [The derived code now explicitly allows `unused_qualifications`][9], so users + that globally deny that lint don't encounter an error. + +[9]: https://github.com/rust-num/num-derive/pull/9 + + +# Release 0.1.43 (2018-01-23) + +- [The derived code now explicitly allows `trivial_numeric_casts`][7], so users + that globally deny that lint don't encounter an error. + +[7]: https://github.com/rust-num/num-derive/pull/7 + + +# Release 0.1.42 (2018-01-22) + +- [num-derive now has its own source repository][num-356] at [rust-num/num-derive][home]. +- [The derivation macros have been updated][3] to using `syn` 0.12. Support for complex + expressions in enum values can be enabled with the `full-syntax` feature. + +Thanks to @cuviper and @hcpl for their contributions! + +[home]: https://github.com/rust-num/num-derive +[num-356]: https://github.com/rust-num/num/pull/356 +[3]: https://github.com/rust-num/num-derive/pull/3 + + +# Prior releases + +No prior release notes were kept. Thanks all the same to the many +contributors that have made this crate what it is! + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1004 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "proc-macro"] +#![doc(html_root_url = "https://docs.rs/num-derive/0.3")] +#![recursion_limit = "512"] + +//! Procedural macros to derive numeric traits in Rust. +//! +//! ## Usage +//! +//! Add this to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! num-traits = "0.2" +//! num-derive = "0.3" +//! ``` +//! +//! Then you can derive traits on your own types: +//! +//! ```rust +//! #[macro_use] +//! extern crate num_derive; +//! +//! #[derive(FromPrimitive, ToPrimitive)] +//! enum Color { +//! Red, +//! Blue, +//! Green, +//! } +//! # fn main() {} +//! ``` +//! +//! ## Explicit import +//! +//! By default the `num_derive` procedural macros assume that the +//! `num_traits` crate is a direct dependency. If `num_traits` is instead +//! a transitive dependency, the `num_traits` helper attribute can be +//! used to tell `num_derive` to use a specific identifier for its imports. +//! +//! ```rust +//! #[macro_use] +//! extern crate num_derive; +//! // Lets pretend this is a transitive dependency from another crate +//! // reexported as `some_other_ident`. +//! extern crate num_traits as some_other_ident; +//! +//! #[derive(FromPrimitive, ToPrimitive)] +//! #[num_traits = "some_other_ident"] +//! enum Color { +//! Red, +//! Blue, +//! Green, +//! } +//! # fn main() {} +//! ``` + +extern crate proc_macro; + +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Data, Fields, Ident}; + +/// Try to parse the tokens, or else return a compilation error +macro_rules! parse { + ($tokens:ident as $type:ty) => { + match syn::parse::<$type>($tokens) { + Ok(parsed) => parsed, + Err(error) => { + return TokenStream::from(error.to_compile_error()); + } + } + }; +} + +// Within `exp`, you can bring things into scope with `extern crate`. +// +// We don't want to assume that `num_traits::` is in scope - the user may have imported it under a +// different name, or may have imported it in a non-toplevel module (common when putting impls +// behind a feature gate). +// +// Solution: let's just generate `extern crate num_traits as _num_traits` and then refer to +// `_num_traits` in the derived code. However, macros are not allowed to produce `extern crate` +// statements at the toplevel. +// +// Solution: let's generate `mod _impl_foo` and import num_traits within that. However, now we +// lose access to private members of the surrounding module. This is a problem if, for example, +// we're deriving for a newtype, where the inner type is defined in the same module, but not +// exported. +// +// Solution: use the anonymous const trick. For some reason, `extern crate` statements are allowed +// here, but everything from the surrounding module is in scope. This trick is taken from serde. +fn anon_const_trick(exp: TokenStream2) -> TokenStream2 { + quote! { + #[allow(non_upper_case_globals, unused_qualifications)] + const _: () = { + #[allow(clippy::useless_attribute)] + #[allow(rust_2018_idioms)] + extern crate num_traits as _num_traits; + #exp + }; + } +} + +// If `data` is a newtype, return the type it's wrapping. +fn newtype_inner(data: &syn::Data) -> Option { + match *data { + Data::Struct(ref s) => { + match s.fields { + Fields::Unnamed(ref fs) => { + if fs.unnamed.len() == 1 { + Some(fs.unnamed[0].ty.clone()) + } else { + None + } + } + Fields::Named(ref fs) => { + if fs.named.len() == 1 { + panic!("num-derive doesn't know how to handle newtypes with named fields yet. \ + Please use a tuple-style newtype, or submit a PR!"); + } + None + } + _ => None, + } + } + _ => None, + } +} + +struct NumTraits { + import: Ident, + explicit: bool, +} + +impl quote::ToTokens for NumTraits { + fn to_tokens(&self, tokens: &mut TokenStream2) { + self.import.to_tokens(tokens); + } +} + +impl NumTraits { + fn new(ast: &syn::DeriveInput) -> Self { + // If there is a `num_traits` MetaNameValue attribute on the input, + // retrieve its value, and use it to create an `Ident` to be used + // to import the `num_traits` crate. + for attr in &ast.attrs { + if attr.path().is_ident("num_traits") { + if let Ok(syn::MetaNameValue { + value: + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(ref lit_str), + .. + }), + .. + }) = attr.meta.require_name_value() + { + return NumTraits { + import: syn::Ident::new(&lit_str.value(), lit_str.span()), + explicit: true, + }; + } else { + panic!("#[num_traits] attribute value must be a str"); + } + } + } + + // Otherwise, we'll implicitly import our own. + NumTraits { + import: Ident::new("_num_traits", Span::call_site()), + explicit: false, + } + } + + fn wrap(&self, output: TokenStream2) -> TokenStream2 { + if self.explicit { + output + } else { + anon_const_trick(output) + } + } +} + +/// Derives [`num_traits::FromPrimitive`][from] for simple enums and newtypes. +/// +/// [from]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.FromPrimitive.html +/// +/// # Examples +/// +/// Simple enums can be derived: +/// +/// ```rust +/// # #[macro_use] +/// # extern crate num_derive; +/// +/// #[derive(FromPrimitive)] +/// enum Color { +/// Red, +/// Blue, +/// Green = 42, +/// } +/// # fn main() {} +/// ``` +/// +/// Enums that contain data are not allowed: +/// +/// ```compile_fail +/// # #[macro_use] +/// # extern crate num_derive; +/// +/// #[derive(FromPrimitive)] +/// enum Color { +/// Rgb(u8, u8, u8), +/// Hsv(u8, u8, u8), +/// } +/// # fn main() {} +/// ``` +/// +/// Structs are not allowed: +/// +/// ```compile_fail +/// # #[macro_use] +/// # extern crate num_derive; +/// #[derive(FromPrimitive)] +/// struct Color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// # fn main() {} +/// ``` +#[proc_macro_derive(FromPrimitive, attributes(num_traits))] +pub fn from_primitive(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + + let import = NumTraits::new(&ast); + + let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) { + quote! { + impl #import::FromPrimitive for #name { + #[inline] + fn from_i64(n: i64) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_i64(n).map(#name) + } + #[inline] + fn from_u64(n: u64) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_u64(n).map(#name) + } + #[inline] + fn from_isize(n: isize) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_isize(n).map(#name) + } + #[inline] + fn from_i8(n: i8) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_i8(n).map(#name) + } + #[inline] + fn from_i16(n: i16) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_i16(n).map(#name) + } + #[inline] + fn from_i32(n: i32) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_i32(n).map(#name) + } + #[inline] + fn from_i128(n: i128) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_i128(n).map(#name) + } + #[inline] + fn from_usize(n: usize) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_usize(n).map(#name) + } + #[inline] + fn from_u8(n: u8) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_u8(n).map(#name) + } + #[inline] + fn from_u16(n: u16) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_u16(n).map(#name) + } + #[inline] + fn from_u32(n: u32) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_u32(n).map(#name) + } + #[inline] + fn from_u128(n: u128) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_u128(n).map(#name) + } + #[inline] + fn from_f32(n: f32) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_f32(n).map(#name) + } + #[inline] + fn from_f64(n: f64) -> ::core::option::Option { + <#inner_ty as #import::FromPrimitive>::from_f64(n).map(#name) + } + } + } + } else { + let variants = match ast.data { + Data::Enum(ref data_enum) => &data_enum.variants, + _ => panic!( + "`FromPrimitive` can be applied only to enums and newtypes, {} is neither", + name + ), + }; + + let from_i64_var = quote! { n }; + let clauses: Vec<_> = variants + .iter() + .map(|variant| { + let ident = &variant.ident; + match variant.fields { + Fields::Unit => (), + _ => panic!( + "`FromPrimitive` can be applied only to unitary enums and newtypes, \ + {}::{} is either struct or tuple", + name, ident + ), + } + + quote! { + if #from_i64_var == #name::#ident as i64 { + ::core::option::Option::Some(#name::#ident) + } + } + }) + .collect(); + + let from_i64_var = if clauses.is_empty() { + quote!(_) + } else { + from_i64_var + }; + + quote! { + impl #import::FromPrimitive for #name { + #[allow(trivial_numeric_casts)] + #[inline] + fn from_i64(#from_i64_var: i64) -> ::core::option::Option { + #(#clauses else)* { + ::core::option::Option::None + } + } + + #[inline] + fn from_u64(n: u64) -> ::core::option::Option { + Self::from_i64(n as i64) + } + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::ToPrimitive`][to] for simple enums and newtypes. +/// +/// [to]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.ToPrimitive.html +/// +/// # Examples +/// +/// Simple enums can be derived: +/// +/// ```rust +/// # #[macro_use] +/// # extern crate num_derive; +/// +/// #[derive(ToPrimitive)] +/// enum Color { +/// Red, +/// Blue, +/// Green = 42, +/// } +/// # fn main() {} +/// ``` +/// +/// Enums that contain data are not allowed: +/// +/// ```compile_fail +/// # #[macro_use] +/// # extern crate num_derive; +/// +/// #[derive(ToPrimitive)] +/// enum Color { +/// Rgb(u8, u8, u8), +/// Hsv(u8, u8, u8), +/// } +/// # fn main() {} +/// ``` +/// +/// Structs are not allowed: +/// +/// ```compile_fail +/// # #[macro_use] +/// # extern crate num_derive; +/// #[derive(ToPrimitive)] +/// struct Color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// # fn main() {} +/// ``` +#[proc_macro_derive(ToPrimitive, attributes(num_traits))] +pub fn to_primitive(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + + let import = NumTraits::new(&ast); + + let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) { + quote! { + impl #import::ToPrimitive for #name { + #[inline] + fn to_i64(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_i64(&self.0) + } + #[inline] + fn to_u64(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_u64(&self.0) + } + #[inline] + fn to_isize(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_isize(&self.0) + } + #[inline] + fn to_i8(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_i8(&self.0) + } + #[inline] + fn to_i16(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_i16(&self.0) + } + #[inline] + fn to_i32(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_i32(&self.0) + } + #[inline] + fn to_i128(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_i128(&self.0) + } + #[inline] + fn to_usize(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_usize(&self.0) + } + #[inline] + fn to_u8(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_u8(&self.0) + } + #[inline] + fn to_u16(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_u16(&self.0) + } + #[inline] + fn to_u32(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_u32(&self.0) + } + #[inline] + fn to_u128(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_u128(&self.0) + } + #[inline] + fn to_f32(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_f32(&self.0) + } + #[inline] + fn to_f64(&self) -> ::core::option::Option { + <#inner_ty as #import::ToPrimitive>::to_f64(&self.0) + } + } + } + } else { + let variants = match ast.data { + Data::Enum(ref data_enum) => &data_enum.variants, + _ => panic!( + "`ToPrimitive` can be applied only to enums and newtypes, {} is neither", + name + ), + }; + + let variants: Vec<_> = variants + .iter() + .map(|variant| { + let ident = &variant.ident; + match variant.fields { + Fields::Unit => (), + _ => { + panic!("`ToPrimitive` can be applied only to unitary enums and newtypes, {}::{} is either struct or tuple", name, ident) + }, + } + + // NB: We have to check each variant individually, because we'll only have `&self` + // for the input. We can't move from that, and it might not be `Clone` or `Copy`. + // (Otherwise we could just do `*self as i64` without a `match` at all.) + quote!(#name::#ident => #name::#ident as i64) + }) + .collect(); + + let match_expr = if variants.is_empty() { + // No variants found, so do not use Some to not to trigger `unreachable_code` lint + quote! { + match *self {} + } + } else { + quote! { + ::core::option::Option::Some(match *self { + #(#variants,)* + }) + } + }; + + quote! { + impl #import::ToPrimitive for #name { + #[inline] + #[allow(trivial_numeric_casts)] + fn to_i64(&self) -> ::core::option::Option { + #match_expr + } + + #[inline] + fn to_u64(&self) -> ::core::option::Option { + self.to_i64().map(|x| x as u64) + } + } + } + }; + + import.wrap(impl_).into() +} + +const NEWTYPE_ONLY: &str = "This trait can only be derived for newtypes"; + +/// Derives [`num_traits::NumOps`][num_ops] for newtypes. The inner type must already implement +/// `NumOps`. +/// +/// [num_ops]: https://docs.rs/num-traits/0.2/num_traits/trait.NumOps.html +/// +/// Note that, since `NumOps` is really a trait alias for `Add + Sub + Mul + Div + Rem`, this macro +/// generates impls for _those_ traits. Furthermore, in all generated impls, `RHS=Self` and +/// `Output=Self`. +#[proc_macro_derive(NumOps)] +pub fn num_ops(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + let impl_ = quote! { + impl ::core::ops::Add for #name { + type Output = Self; + #[inline] + fn add(self, other: Self) -> Self { + #name(<#inner_ty as ::core::ops::Add>::add(self.0, other.0)) + } + } + impl ::core::ops::Sub for #name { + type Output = Self; + #[inline] + fn sub(self, other: Self) -> Self { + #name(<#inner_ty as ::core::ops::Sub>::sub(self.0, other.0)) + } + } + impl ::core::ops::Mul for #name { + type Output = Self; + #[inline] + fn mul(self, other: Self) -> Self { + #name(<#inner_ty as ::core::ops::Mul>::mul(self.0, other.0)) + } + } + impl ::core::ops::Div for #name { + type Output = Self; + #[inline] + fn div(self, other: Self) -> Self { + #name(<#inner_ty as ::core::ops::Div>::div(self.0, other.0)) + } + } + impl ::core::ops::Rem for #name { + type Output = Self; + #[inline] + fn rem(self, other: Self) -> Self { + #name(<#inner_ty as ::core::ops::Rem>::rem(self.0, other.0)) + } + } + }; + impl_.into() +} + +/// Derives [`num_traits::NumCast`][num_cast] for newtypes. The inner type must already implement +/// `NumCast`. +/// +/// [num_cast]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.NumCast.html +#[proc_macro_derive(NumCast, attributes(num_traits))] +pub fn num_cast(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::NumCast for #name { + #[inline] + fn from(n: T) -> ::core::option::Option { + <#inner_ty as #import::NumCast>::from(n).map(#name) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::Zero`][zero] for newtypes. The inner type must already implement `Zero`. +/// +/// [zero]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.Zero.html +#[proc_macro_derive(Zero, attributes(num_traits))] +pub fn zero(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Zero for #name { + #[inline] + fn zero() -> Self { + #name(<#inner_ty as #import::Zero>::zero()) + } + #[inline] + fn is_zero(&self) -> bool { + <#inner_ty as #import::Zero>::is_zero(&self.0) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::One`][one] for newtypes. The inner type must already implement `One`. +/// +/// [one]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.One.html +#[proc_macro_derive(One, attributes(num_traits))] +pub fn one(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::One for #name { + #[inline] + fn one() -> Self { + #name(<#inner_ty as #import::One>::one()) + } + #[inline] + fn is_one(&self) -> bool { + <#inner_ty as #import::One>::is_one(&self.0) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::Num`][num] for newtypes. The inner type must already implement `Num`. +/// +/// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html +#[proc_macro_derive(Num, attributes(num_traits))] +pub fn num(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Num for #name { + type FromStrRadixErr = <#inner_ty as #import::Num>::FromStrRadixErr; + #[inline] + fn from_str_radix(s: &str, radix: u32) -> ::core::result::Result { + <#inner_ty as #import::Num>::from_str_radix(s, radix).map(#name) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::Float`][float] for newtypes. The inner type must already implement +/// `Float`. +/// +/// [float]: https://docs.rs/num-traits/0.2/num_traits/float/trait.Float.html +#[proc_macro_derive(Float, attributes(num_traits))] +pub fn float(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Float for #name { + #[inline] + fn nan() -> Self { + #name(<#inner_ty as #import::Float>::nan()) + } + #[inline] + fn infinity() -> Self { + #name(<#inner_ty as #import::Float>::infinity()) + } + #[inline] + fn neg_infinity() -> Self { + #name(<#inner_ty as #import::Float>::neg_infinity()) + } + #[inline] + fn neg_zero() -> Self { + #name(<#inner_ty as #import::Float>::neg_zero()) + } + #[inline] + fn min_value() -> Self { + #name(<#inner_ty as #import::Float>::min_value()) + } + #[inline] + fn min_positive_value() -> Self { + #name(<#inner_ty as #import::Float>::min_positive_value()) + } + #[inline] + fn max_value() -> Self { + #name(<#inner_ty as #import::Float>::max_value()) + } + #[inline] + fn is_nan(self) -> bool { + <#inner_ty as #import::Float>::is_nan(self.0) + } + #[inline] + fn is_infinite(self) -> bool { + <#inner_ty as #import::Float>::is_infinite(self.0) + } + #[inline] + fn is_finite(self) -> bool { + <#inner_ty as #import::Float>::is_finite(self.0) + } + #[inline] + fn is_normal(self) -> bool { + <#inner_ty as #import::Float>::is_normal(self.0) + } + #[inline] + fn classify(self) -> ::core::num::FpCategory { + <#inner_ty as #import::Float>::classify(self.0) + } + #[inline] + fn floor(self) -> Self { + #name(<#inner_ty as #import::Float>::floor(self.0)) + } + #[inline] + fn ceil(self) -> Self { + #name(<#inner_ty as #import::Float>::ceil(self.0)) + } + #[inline] + fn round(self) -> Self { + #name(<#inner_ty as #import::Float>::round(self.0)) + } + #[inline] + fn trunc(self) -> Self { + #name(<#inner_ty as #import::Float>::trunc(self.0)) + } + #[inline] + fn fract(self) -> Self { + #name(<#inner_ty as #import::Float>::fract(self.0)) + } + #[inline] + fn abs(self) -> Self { + #name(<#inner_ty as #import::Float>::abs(self.0)) + } + #[inline] + fn signum(self) -> Self { + #name(<#inner_ty as #import::Float>::signum(self.0)) + } + #[inline] + fn is_sign_positive(self) -> bool { + <#inner_ty as #import::Float>::is_sign_positive(self.0) + } + #[inline] + fn is_sign_negative(self) -> bool { + <#inner_ty as #import::Float>::is_sign_negative(self.0) + } + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + #name(<#inner_ty as #import::Float>::mul_add(self.0, a.0, b.0)) + } + #[inline] + fn recip(self) -> Self { + #name(<#inner_ty as #import::Float>::recip(self.0)) + } + #[inline] + fn powi(self, n: i32) -> Self { + #name(<#inner_ty as #import::Float>::powi(self.0, n)) + } + #[inline] + fn powf(self, n: Self) -> Self { + #name(<#inner_ty as #import::Float>::powf(self.0, n.0)) + } + #[inline] + fn sqrt(self) -> Self { + #name(<#inner_ty as #import::Float>::sqrt(self.0)) + } + #[inline] + fn exp(self) -> Self { + #name(<#inner_ty as #import::Float>::exp(self.0)) + } + #[inline] + fn exp2(self) -> Self { + #name(<#inner_ty as #import::Float>::exp2(self.0)) + } + #[inline] + fn ln(self) -> Self { + #name(<#inner_ty as #import::Float>::ln(self.0)) + } + #[inline] + fn log(self, base: Self) -> Self { + #name(<#inner_ty as #import::Float>::log(self.0, base.0)) + } + #[inline] + fn log2(self) -> Self { + #name(<#inner_ty as #import::Float>::log2(self.0)) + } + #[inline] + fn log10(self) -> Self { + #name(<#inner_ty as #import::Float>::log10(self.0)) + } + #[inline] + fn max(self, other: Self) -> Self { + #name(<#inner_ty as #import::Float>::max(self.0, other.0)) + } + #[inline] + fn min(self, other: Self) -> Self { + #name(<#inner_ty as #import::Float>::min(self.0, other.0)) + } + #[inline] + fn abs_sub(self, other: Self) -> Self { + #name(<#inner_ty as #import::Float>::abs_sub(self.0, other.0)) + } + #[inline] + fn cbrt(self) -> Self { + #name(<#inner_ty as #import::Float>::cbrt(self.0)) + } + #[inline] + fn hypot(self, other: Self) -> Self { + #name(<#inner_ty as #import::Float>::hypot(self.0, other.0)) + } + #[inline] + fn sin(self) -> Self { + #name(<#inner_ty as #import::Float>::sin(self.0)) + } + #[inline] + fn cos(self) -> Self { + #name(<#inner_ty as #import::Float>::cos(self.0)) + } + #[inline] + fn tan(self) -> Self { + #name(<#inner_ty as #import::Float>::tan(self.0)) + } + #[inline] + fn asin(self) -> Self { + #name(<#inner_ty as #import::Float>::asin(self.0)) + } + #[inline] + fn acos(self) -> Self { + #name(<#inner_ty as #import::Float>::acos(self.0)) + } + #[inline] + fn atan(self) -> Self { + #name(<#inner_ty as #import::Float>::atan(self.0)) + } + #[inline] + fn atan2(self, other: Self) -> Self { + #name(<#inner_ty as #import::Float>::atan2(self.0, other.0)) + } + #[inline] + fn sin_cos(self) -> (Self, Self) { + let (x, y) = <#inner_ty as #import::Float>::sin_cos(self.0); + (#name(x), #name(y)) + } + #[inline] + fn exp_m1(self) -> Self { + #name(<#inner_ty as #import::Float>::exp_m1(self.0)) + } + #[inline] + fn ln_1p(self) -> Self { + #name(<#inner_ty as #import::Float>::ln_1p(self.0)) + } + #[inline] + fn sinh(self) -> Self { + #name(<#inner_ty as #import::Float>::sinh(self.0)) + } + #[inline] + fn cosh(self) -> Self { + #name(<#inner_ty as #import::Float>::cosh(self.0)) + } + #[inline] + fn tanh(self) -> Self { + #name(<#inner_ty as #import::Float>::tanh(self.0)) + } + #[inline] + fn asinh(self) -> Self { + #name(<#inner_ty as #import::Float>::asinh(self.0)) + } + #[inline] + fn acosh(self) -> Self { + #name(<#inner_ty as #import::Float>::acosh(self.0)) + } + #[inline] + fn atanh(self) -> Self { + #name(<#inner_ty as #import::Float>::atanh(self.0)) + } + #[inline] + fn integer_decode(self) -> (u64, i16, i8) { + <#inner_ty as #import::Float>::integer_decode(self.0) + } + #[inline] + fn epsilon() -> Self { + #name(<#inner_ty as #import::Float>::epsilon()) + } + #[inline] + fn to_degrees(self) -> Self { + #name(<#inner_ty as #import::Float>::to_degrees(self.0)) + } + #[inline] + fn to_radians(self) -> Self { + #name(<#inner_ty as #import::Float>::to_radians(self.0)) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::Signed`][signed] for newtypes. The inner type must already implement +/// `Signed`. +/// +/// [signed]: https://docs.rs/num-traits/0.2/num_traits/sign/trait.Signed.html +#[proc_macro_derive(Signed, attributes(num_traits))] +pub fn signed(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Signed for #name { + #[inline] + fn abs(&self) -> Self { + #name(<#inner_ty as #import::Signed>::abs(&self.0)) + } + #[inline] + fn abs_sub(&self, other: &Self) -> Self { + #name(<#inner_ty as #import::Signed>::abs_sub(&self.0, &other.0)) + } + #[inline] + fn signum(&self) -> Self { + #name(<#inner_ty as #import::Signed>::signum(&self.0)) + } + #[inline] + fn is_positive(&self) -> bool { + <#inner_ty as #import::Signed>::is_positive(&self.0) + } + #[inline] + fn is_negative(&self) -> bool { + <#inner_ty as #import::Signed>::is_negative(&self.0) + } + } + }; + + import.wrap(impl_).into() +} + +/// Derives [`num_traits::Unsigned`][unsigned]. The inner type must already implement +/// `Unsigned`. +/// +/// [unsigned]: https://docs.rs/num/latest/num/traits/trait.Unsigned.html +#[proc_macro_derive(Unsigned, attributes(num_traits))] +pub fn unsigned(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Unsigned for #name {} + }; + + import.wrap(impl_).into() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/empty_enum.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/empty_enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/empty_enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/empty_enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate num as num_renamed; +#[macro_use] +extern crate num_derive; + +#[derive(Debug, PartialEq, FromPrimitive, ToPrimitive)] +enum Color {} + +#[test] +fn test_empty_enum() { + let v: [Option; 1] = [num_renamed::FromPrimitive::from_u64(0)]; + + assert_eq!(v, [None]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-16.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-16.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-16.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-16.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +macro_rules! get_an_isize { + () => { + 0_isize + }; +} + +#[derive(num_derive::FromPrimitive)] +pub enum CLikeEnum { + VarA = get_an_isize!(), + VarB = 2, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-6.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-6.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-6.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-6.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +#![deny(trivial_numeric_casts)] + +#[macro_use] +extern crate num_derive; + +#[derive(FromPrimitive, ToPrimitive)] +pub enum SomeEnum { + A = 1, +} + +#[test] +fn test_trivial_numeric_casts() { + use num::{FromPrimitive, ToPrimitive}; + assert!(SomeEnum::from_u64(1).is_some()); + assert!(SomeEnum::from_i64(-1).is_none()); + assert_eq!(SomeEnum::A.to_u64(), Some(1)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-9.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-9.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/issue-9.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/issue-9.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +#![deny(unused_qualifications)] + +#[macro_use] +extern crate num_derive; +use num::FromPrimitive; +use num::ToPrimitive; + +#[derive(FromPrimitive, ToPrimitive)] +pub enum SomeEnum { + A = 1, +} + +#[test] +fn test_unused_qualifications() { + assert!(SomeEnum::from_u64(1).is_some()); + assert!(SomeEnum::from_i64(-1).is_none()); + assert!(SomeEnum::A.to_i64().is_some()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype-2015.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2015.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype-2015.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2015.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +// Same source, just compiled for 2015 edition +include!("newtype.rs"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype-2018.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2018.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype-2018.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype-2018.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +// Same source, just compiled for 2018 edition +include!("newtype.rs"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/newtype.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/newtype.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,108 @@ +extern crate num as num_renamed; +#[macro_use] +extern crate num_derive; + +use crate::num_renamed::{ + Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Unsigned, Zero, +}; +use std::ops::Neg; + +#[derive(PartialEq, Zero, One, NumOps, Num, Unsigned)] +struct MyNum(u32); + +#[test] +fn test_derive_unsigned_works() { + fn do_nothing_on_unsigned(_input: impl Unsigned) {} + + let x = MyNum(42); + do_nothing_on_unsigned(x); +} + +#[derive( + Debug, + Clone, + Copy, + PartialEq, + PartialOrd, + ToPrimitive, + FromPrimitive, + NumOps, + NumCast, + One, + Zero, + Num, + Float, + Signed, +)] +struct MyFloat(f64); + +impl Neg for MyFloat { + type Output = MyFloat; + fn neg(self) -> Self { + MyFloat(self.0.neg()) + } +} + +#[test] +fn test_from_primitive() { + assert_eq!(MyFloat::from_u32(25), Some(MyFloat(25.0))); +} + +#[test] +fn test_from_primitive_128() { + assert_eq!( + MyFloat::from_i128(std::i128::MIN), + Some(MyFloat((-2.0).powi(127))) + ); +} + +#[test] +fn test_to_primitive() { + assert_eq!(MyFloat(25.0).to_u32(), Some(25)); +} + +#[test] +fn test_to_primitive_128() { + let f = MyFloat::from_f32(std::f32::MAX).unwrap(); + assert_eq!(f.to_i128(), None); + assert_eq!(f.to_u128(), Some(0xffff_ff00_0000_0000_0000_0000_0000_0000)); +} + +#[test] +fn test_num_ops() { + assert_eq!(MyFloat(25.0) + MyFloat(10.0), MyFloat(35.0)); + assert_eq!(MyFloat(25.0) - MyFloat(10.0), MyFloat(15.0)); + assert_eq!(MyFloat(25.0) * MyFloat(2.0), MyFloat(50.0)); + assert_eq!(MyFloat(25.0) / MyFloat(10.0), MyFloat(2.5)); + assert_eq!(MyFloat(25.0) % MyFloat(10.0), MyFloat(5.0)); +} + +#[test] +fn test_num_cast() { + assert_eq!(::from(25u8), Some(MyFloat(25.0))); +} + +#[test] +fn test_zero() { + assert_eq!(MyFloat::zero(), MyFloat(0.0)); +} + +#[test] +fn test_one() { + assert_eq!(MyFloat::one(), MyFloat(1.0)); +} + +#[test] +fn test_num() { + assert_eq!(MyFloat::from_str_radix("25", 10).ok(), Some(MyFloat(25.0))); +} + +#[test] +fn test_float() { + assert_eq!(MyFloat(4.0).log(MyFloat(2.0)), MyFloat(2.0)); +} + +#[test] +fn test_signed() { + assert!(MyFloat(-2.0).is_negative()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/no_implicit_prelude.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/no_implicit_prelude.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/no_implicit_prelude.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/no_implicit_prelude.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +#![no_implicit_prelude] + +use ::num_derive::*; + +#[derive(FromPrimitive, ToPrimitive)] +enum Color { + Red, + Blue, + Green, +} + +#[derive(FromPrimitive, ToPrimitive, NumCast, PartialEq, Zero, One, NumOps, Num)] +struct NewI32(i32); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/num_derive_without_num.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/num_derive_without_num.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/num_derive_without_num.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/num_derive_without_num.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate num_derive; + +#[derive(Debug, FromPrimitive, ToPrimitive)] +enum Direction { + Up, + Down, + Left, + Right, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial-2015.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2015.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial-2015.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2015.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +// Same source, just compiled for 2015 edition +include!("trivial.rs"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial-2018.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2018.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial-2018.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial-2018.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +// Same source, just compiled for 2018 edition +include!("trivial.rs"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/trivial.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/trivial.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate num as num_renamed; +#[macro_use] +extern crate num_derive; + +#[derive(Debug, PartialEq, FromPrimitive, ToPrimitive)] +enum Color { + Red, + Blue, + Green, +} + +#[test] +fn test_from_primitive_for_trivial_case() { + let v: [Option; 4] = [ + num_renamed::FromPrimitive::from_u64(0), + num_renamed::FromPrimitive::from_u64(1), + num_renamed::FromPrimitive::from_u64(2), + num_renamed::FromPrimitive::from_u64(3), + ]; + + assert_eq!( + v, + [ + Some(Color::Red), + Some(Color::Blue), + Some(Color::Green), + None + ] + ); +} + +#[test] +fn test_to_primitive_for_trivial_case() { + let v: [Option; 3] = [ + num_renamed::ToPrimitive::to_u64(&Color::Red), + num_renamed::ToPrimitive::to_u64(&Color::Blue), + num_renamed::ToPrimitive::to_u64(&Color::Green), + ]; + + assert_eq!(v, [Some(0), Some(1), Some(2)]); +} + +#[test] +fn test_reflexive_for_trivial_case() { + let before: [u64; 3] = [0, 1, 2]; + let after: Vec> = before + .iter() + .map(|&x| -> Option { num_renamed::FromPrimitive::from_u64(x) }) + .map(|x| x.and_then(|x| num_renamed::ToPrimitive::to_u64(&x))) + .collect(); + let before = before.iter().cloned().map(Some).collect::>(); + + assert_eq!(before, after); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/with_custom_values.rs clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/with_custom_values.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-derive/tests/with_custom_values.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-derive/tests/with_custom_values.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate num as num_renamed; +#[macro_use] +extern crate num_derive; + +#[derive(Debug, PartialEq, FromPrimitive, ToPrimitive)] +enum Color { + Red, + Blue = 5, + Green, + Alpha = (-3 - (-5isize)) - 10, +} + +#[test] +fn test_from_primitive_for_enum_with_custom_value() { + let v: [Option; 5] = [ + num_renamed::FromPrimitive::from_u64(0), + num_renamed::FromPrimitive::from_u64(5), + num_renamed::FromPrimitive::from_u64(6), + num_renamed::FromPrimitive::from_u64(-8isize as u64), + num_renamed::FromPrimitive::from_u64(3), + ]; + + assert_eq!( + v, + [ + Some(Color::Red), + Some(Color::Blue), + Some(Color::Green), + Some(Color::Alpha), + None + ] + ); +} + +#[test] +fn test_to_primitive_for_enum_with_custom_value() { + let v: [Option; 4] = [ + num_renamed::ToPrimitive::to_u64(&Color::Red), + num_renamed::ToPrimitive::to_u64(&Color::Blue), + num_renamed::ToPrimitive::to_u64(&Color::Green), + num_renamed::ToPrimitive::to_u64(&Color::Alpha), + ]; + + assert_eq!(v, [Some(0), Some(5), Some(6), Some(-8isize as u64)]); +} + +#[test] +fn test_reflexive_for_enum_with_custom_value() { + let before: [u64; 3] = [0, 5, 6]; + let after: Vec> = before + .iter() + .map(|&x| -> Option { num_renamed::FromPrimitive::from_u64(x) }) + .map(|x| x.and_then(|x| num_renamed::ToPrimitive::to_u64(&x))) + .collect(); + let before = before.iter().cloned().map(Some).collect::>(); + + assert_eq!(before, after); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-integer/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-integer/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"f5e54fe018d780d7320b47a3fdae3b1ec3f6d04ac5adab3a8ddf207531aecef8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"f0513e0dd3fccc992b4047aa56d02721466d9ec53c77ad2d3812d94161d8c9b2","RELEASES.md":"680e32706fc80d279399cf0feee73eeb252b3507e38505aa9e8058390994e299","benches/average.rs":"e9bab6ecef0f964b57cba8e83bd0cc24006389d34869c42c0be588bf8ab1995b","benches/gcd.rs":"409efaff0e1d0383b0b02641100198360a78eb36605b639e3625e5e6ed137447","benches/roots.rs":"74e12185650e44463cde6383f4331bef9e8a99441738892fda52e451bb5d43a0","src/average.rs":"72f041da3ede7913c7ed8620f21075396671fba6cd9aeb98ec907db1be8fe699","src/lib.rs":"e521b425767463a9d96fbeb69872013f0c8a19f8887f6bdcf04cf221419210a5","src/roots.rs":"4509c75ad2dcecc4a7a096077575592affb4c89c4d021b66678844b033d4c8c4","tests/average.rs":"70d95d1030dcdefa3d0d398ce833d3b72f9815f0c145502d4b06a5fee3f9e2f8","tests/roots.rs":"839902657e051d93a918dcb8e5501d762d0755fa213179b52939b62842d4d8b7"},"package":"7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"9a0bd412198124f729903572f5a08c35e253274ac20a0d4decf6d8da0309948a","Cargo.toml":"f5e54fe018d780d7320b47a3fdae3b1ec3f6d04ac5adab3a8ddf207531aecef8","Cargo.toml.orig":"efe6398cc01575661501931c7c30d58f50dc3d11d891d14ac44d5fecc4e3bac2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"f0513e0dd3fccc992b4047aa56d02721466d9ec53c77ad2d3812d94161d8c9b2","RELEASES.md":"680e32706fc80d279399cf0feee73eeb252b3507e38505aa9e8058390994e299","benches/average.rs":"e9bab6ecef0f964b57cba8e83bd0cc24006389d34869c42c0be588bf8ab1995b","benches/gcd.rs":"409efaff0e1d0383b0b02641100198360a78eb36605b639e3625e5e6ed137447","benches/roots.rs":"74e12185650e44463cde6383f4331bef9e8a99441738892fda52e451bb5d43a0","src/average.rs":"72f041da3ede7913c7ed8620f21075396671fba6cd9aeb98ec907db1be8fe699","src/lib.rs":"e521b425767463a9d96fbeb69872013f0c8a19f8887f6bdcf04cf221419210a5","src/roots.rs":"4509c75ad2dcecc4a7a096077575592affb4c89c4d021b66678844b033d4c8c4","tests/average.rs":"70d95d1030dcdefa3d0d398ce833d3b72f9815f0c145502d4b06a5fee3f9e2f8","tests/roots.rs":"839902657e051d93a918dcb8e5501d762d0755fa213179b52939b62842d4d8b7"},"package":"7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-integer/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-integer/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-integer/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ede2d2cb993e55e7b1c992bfd22ecbf16601a652" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-integer/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-integer/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-integer/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-integer/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Integer traits and functions" +documentation = "https://docs.rs/num-integer" +homepage = "https://github.com/rust-num/num-integer" +keywords = ["mathematics", "numerics"] +categories = ["algorithms", "science", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-integer" +name = "num-integer" +version = "0.1.46" +readme = "README.md" +exclude = ["/ci/*", "/.github/*"] +edition = "2018" +rust-version = "1.31" + +[package.metadata.docs.rs] +features = ["std"] + +[dependencies.num-traits] +version = "0.2.11" +default-features = false +features = ["i128"] + +[features] +default = ["std"] +std = ["num-traits/std"] + +# vestigial features, now always in effect +i128 = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"3e4edb740dc994c9b8b52ef84c2a81955fd06ed67183e86a0dfbe9cfd45d234e","Cargo.toml":"5d0e183e1c4b1ad6fe8a288f51ee840ae06c72be900608ea4c3ccc0380e62d01","Cargo.toml.orig":"7973a947de62839e3b16448af97df861e3479f0835221f30bb3591c79cf18774","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"5607898a0a862be3e6ab042d126f0b7888aeb98eac0251c328f4ae0c3bc3c83e","RELEASES.md":"4aa5ba49bb998ea864f796af0d5229d4c07b27f96d8c2d2eeddb69bc06a00cd3","src/lib.rs":"6ce781e573521fb81f5ca47c1e6dab64e4eafc7f7d8e85094161fca5bb39c015","src/pow.rs":"c38cabc61e75e99425ee4fea7ac5b0712a648baa0635a2c40a6215edd43ae4a3"},"package":"f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4d55ad22ac86ebbc4cb45d79a956e4a1f7af57d1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "num-rational" +version = "0.4.2" +authors = ["The Rust Project Developers"] +exclude = [ + "/ci/*", + "/.github/*", +] +description = "Rational numbers implementation for Rust" +homepage = "https://github.com/rust-num/num-rational" +documentation = "https://docs.rs/num-rational" +readme = "README.md" +keywords = [ + "mathematics", + "numerics", + "fractions", +] +categories = [ + "algorithms", + "data-structures", + "science", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-rational" + +[package.metadata.docs.rs] +features = [ + "std", + "num-bigint-std", + "serde", +] + +[dependencies.num-bigint] +version = "0.4.0" +optional = true +default-features = false + +[dependencies.num-integer] +version = "0.1.42" +features = ["i128"] +default-features = false + +[dependencies.num-traits] +version = "0.2.18" +features = ["i128"] +default-features = false + +[dependencies.serde] +version = "1.0.0" +optional = true +default-features = false + +[features] +default = [ + "num-bigint", + "std", +] +num-bigint = ["dep:num-bigint"] +num-bigint-std = ["num-bigint/std"] +serde = ["dep:serde"] +std = [ + "num-bigint?/std", + "num-integer/std", + "num-traits/std", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Rational numbers implementation for Rust" +documentation = "https://docs.rs/num-rational" +homepage = "https://github.com/rust-num/num-rational" +keywords = ["mathematics", "numerics", "fractions"] +categories = ["algorithms", "data-structures", "science", "no-std"] +license = "MIT OR Apache-2.0" +name = "num-rational" +repository = "https://github.com/rust-num/num-rational" +version = "0.4.2" +readme = "README.md" +exclude = ["/ci/*", "/.github/*"] +edition = "2021" +rust-version = "1.60" + +[package.metadata.docs.rs] +features = ["std", "num-bigint-std", "serde"] + +[dependencies] + +[dependencies.num-bigint] +optional = true +version = "0.4.0" +default-features = false + +[dependencies.num-integer] +version = "0.1.42" +default-features = false +features = ["i128"] + +[dependencies.num-traits] +version = "0.2.18" +default-features = false +features = ["i128"] + +[dependencies.serde] +optional = true +version = "1.0.0" +default-features = false + +[features] +default = ["num-bigint", "std"] +std = ["num-bigint?/std", "num-integer/std", "num-traits/std"] +num-bigint-std = ["num-bigint/std"] +num-bigint = ["dep:num-bigint"] +serde = ["dep:serde"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/README.md clamav-1.4.6+dfsg/.cargo/vendor/num-rational/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +# num-rational + +[![crate](https://img.shields.io/crates/v/num-rational.svg)](https://crates.io/crates/num-rational) +[![documentation](https://docs.rs/num-rational/badge.svg)](https://docs.rs/num-rational) +[![minimum rustc 1.60](https://img.shields.io/badge/rustc-1.60+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![build status](https://github.com/rust-num/num-rational/workflows/master/badge.svg)](https://github.com/rust-num/num-rational/actions) + +Generic `Rational` numbers (aka fractions) for Rust. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +num-rational = "0.4" +``` + +## Features + +This crate can be used without the standard library (`#![no_std]`) by disabling +the default `std` feature. Use this in `Cargo.toml`: + +```toml +[dependencies.num-rational] +version = "0.4" +default-features = false +``` + +## Releases + +Release notes are available in [RELEASES.md](RELEASES.md). + +## Compatibility + +The `num-rational` crate is tested for rustc 1.60 and greater. + +## License + +Licensed under either of + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/RELEASES.md clamav-1.4.6+dfsg/.cargo/vendor/num-rational/RELEASES.md --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/RELEASES.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/RELEASES.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,174 @@ +# Release 0.4.2 (2024-05-07) + +- [Upgrade to 2021 edition, **MSRV 1.60**][126] +- [Add `Ratio::approximate_float_unsigned` to convert `FloatCore` types to unsigned][109] +- [Add `const ZERO` and `ONE`, and implement `num_traits::ConstZero` and `ConstOne`][128] +- [Add `Ratio::into_raw` to deconstruct the numerator and denominator][129] + +**Contributors**: @cuviper, @Enyium, @flavioroth, @waywardmonkeys + +[109]: https://github.com/rust-num/num-rational/pull/109 +[126]: https://github.com/rust-num/num-rational/pull/126 +[128]: https://github.com/rust-num/num-rational/pull/128 +[129]: https://github.com/rust-num/num-rational/pull/129 + +# Release 0.4.1 (2022-06-23) + +- [Fewer `clone` calls are used when reducing a new `Ratio`][98]. +- [Conversions to floating point are better at avoiding underflow][104]. +- [`Ratio` now implements `Default`][105], returning a zero value. + +**Contributors**: @cuviper, @lemmih, @MattX + +[98]: https://github.com/rust-num/num-rational/pull/98 +[104]: https://github.com/rust-num/num-rational/pull/104 +[105]: https://github.com/rust-num/num-rational/pull/105 + +# Release 0.4.0 (2021-03-05) + +- The optional `num-bigint` dependency is now 0.4. +- [The `Rational` alias for `Ratio` is now deprecated][92]. It is + recommended to use specific type sizes for numeric computation, like + `Rational32` and `Rational64`. + +**Contributors**: @cuviper, @vks + +[92]: https://github.com/rust-num/num-rational/pull/92 + +# Release 0.3.2 (2020-11-06) + +- [Fix always rebuilding with --remap-path-prefix][88] + +**Contributors**: @Nemo157 + +[88]: https://github.com/rust-num/num-rational/pull/88 + +# Release 0.3.1 (2020-10-29) + +- [Handle to_f64() with raw division by zero][83]. +- [Better document panic behaviour][84]. +- Clarify the license specification as "MIT OR Apache-2.0". + +**Contributors**: @cuviper, @zetok + +[83]: https://github.com/rust-num/num-rational/pull/83 +[84]: https://github.com/rust-num/num-rational/pull/84 + +# Release 0.3.0 (2020-06-13) + +### Enhancements + +- [`Ratio` now implements `ToPrimitive`][52]. +- [`Ratio` now implements additional formatting traits][56]: + - `Binary`, `Octal`, `LowerHex`, `UpperHex`, `LowerExp`, `UpperExp` +- [The `Pow` implementations have been expanded][70]. + - `Pow` and `Pow` are now implemented. + - `Pow<_> for &Ratio` now uses `&T: Pow`. + - The inherent `pow` method now uses `&T: Pow`. + +### Breaking Changes + +- [`num-rational` now requires Rust 1.31 or greater][66]. + - The "i128" opt-in feature was removed, now always available. +- [The "num-bigint-std" feature replaces "bigint" with `std` enabled][80]. + - The "num-bigint" feature without `std` uses `alloc` on Rust 1.36+. + +**Contributors**: @cuviper, @MattX, @maxbla + +[52]: https://github.com/rust-num/num-rational/pull/52 +[56]: https://github.com/rust-num/num-rational/pull/56 +[66]: https://github.com/rust-num/num-rational/pull/66 +[70]: https://github.com/rust-num/num-rational/pull/70 +[80]: https://github.com/rust-num/num-rational/pull/80 + +# Release 0.2.4 (2020-03-17) + +- [Fixed `CheckedDiv` when both dividend and divisor are 0][74]. +- [Fixed `CheckedDiv` with `min_value()` numerators][76]. + +[74]: https://github.com/rust-num/num-rational/pull/74 +[76]: https://github.com/rust-num/num-rational/pull/76 + +# Release 0.2.3 (2020-01-09) + +- [`Ratio` now performs earlier reductions to avoid overflow with `+-*/%` operators][42]. +- [`Ratio::{new_raw, numer, denom}` are now `const fn` for Rust 1.31 and later][48]. +- [Updated the `autocfg` build dependency to 1.0][63]. + +**Contributors**: @cuviper, @dingelish, @jimbo1qaz, @maxbla + +[42]: https://github.com/rust-num/num-rational/pull/42 +[48]: https://github.com/rust-num/num-rational/pull/48 +[63]: https://github.com/rust-num/num-rational/pull/63 + +# Release 0.2.2 (2019-06-10) + +- [`Ratio` now implements `Zero::set_zero` and `One::set_one`][47]. + +**Contributors**: @cuviper, @ignatenkobrain, @vks + +[47]: https://github.com/rust-num/num-rational/pull/47 + +# Release 0.2.1 (2018-06-22) + +- Maintenance release to fix `html_root_url`. + +# Release 0.2.0 (2018-06-19) + +### Enhancements + +- [`Ratio` now implements `One::is_one` and the `Inv` trait][19]. +- [`Ratio` now implements `Sum` and `Product`][25]. +- [`Ratio` now supports `i128` and `u128` components][29] with Rust 1.26+. +- [`Ratio` now implements the `Pow` trait][21]. + +### Breaking Changes + +- [`num-rational` now requires rustc 1.15 or greater][18]. +- [There is now a `std` feature][23], enabled by default, along with the + implication that building *without* this feature makes this a `#![no_std]` + crate. A few methods now require `FloatCore` instead of `Float`. +- [The `serde` dependency has been updated to 1.0][24], and `rustc-serialize` + is no longer supported by `num-rational`. +- The optional `num-bigint` dependency has been updated to 0.2, and should be + enabled using the `bigint-std` feature. In the future, it may be possible + to use the `bigint` feature with `no_std`. + +**Contributors**: @clarcharr, @cuviper, @Emerentius, @robomancer-or, @vks + +[18]: https://github.com/rust-num/num-rational/pull/18 +[19]: https://github.com/rust-num/num-rational/pull/19 +[21]: https://github.com/rust-num/num-rational/pull/21 +[23]: https://github.com/rust-num/num-rational/pull/23 +[24]: https://github.com/rust-num/num-rational/pull/24 +[25]: https://github.com/rust-num/num-rational/pull/25 +[29]: https://github.com/rust-num/num-rational/pull/29 + + +# Release 0.1.42 (2018-02-08) + +- Maintenance release to update dependencies. + + +# Release 0.1.41 (2018-01-26) + +- [num-rational now has its own source repository][num-356] at [rust-num/num-rational][home]. +- [`Ratio` now implements `CheckedAdd`, `CheckedSub`, `CheckedMul`, and `CheckedDiv`][11]. +- [`Ratio` now implements `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, and `RemAssign`][12] + with either `Ratio` or an integer on the right side. The non-assignment operators now also + accept integers as an operand. +- [`Ratio` operators now make fewer `clone()` calls][14]. + +Thanks to @c410-f3r, @cuviper, and @psimonyi for their contributions! + +[home]: https://github.com/rust-num/num-rational +[num-356]: https://github.com/rust-num/num/pull/356 +[11]: https://github.com/rust-num/num-rational/pull/11 +[12]: https://github.com/rust-num/num-rational/pull/12 +[14]: https://github.com/rust-num/num-rational/pull/14 + + +# Prior releases + +No prior release notes were kept. Thanks all the same to the many +contributors that have made this crate what it is! diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3131 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Rational numbers +//! +//! ## Compatibility +//! +//! The `num-rational` crate is tested for rustc 1.60 and greater. + +#![doc(html_root_url = "https://docs.rs/num-rational/0.4")] +#![no_std] +// Ratio ops often use other "suspicious" ops +#![allow(clippy::suspicious_arithmetic_impl)] +#![allow(clippy::suspicious_op_assign_impl)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; + +use core::cmp; +use core::fmt; +use core::fmt::{Binary, Display, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex}; +use core::hash::{Hash, Hasher}; +use core::ops::{Add, Div, Mul, Neg, Rem, ShlAssign, Sub}; +use core::str::FromStr; +#[cfg(feature = "std")] +use std::error::Error; + +#[cfg(feature = "num-bigint")] +use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; + +use num_integer::Integer; +use num_traits::float::FloatCore; +use num_traits::{ + Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, ConstOne, ConstZero, FromPrimitive, + Inv, Num, NumCast, One, Pow, Signed, ToPrimitive, Unsigned, Zero, +}; + +mod pow; + +/// Represents the ratio between two numbers. +#[derive(Copy, Clone, Debug)] +#[allow(missing_docs)] +pub struct Ratio { + /// Numerator. + numer: T, + /// Denominator. + denom: T, +} + +/// Alias for a `Ratio` of machine-sized integers. +#[deprecated( + since = "0.4.0", + note = "it's better to use a specific size, like `Rational32` or `Rational64`" +)] +pub type Rational = Ratio; +/// Alias for a `Ratio` of 32-bit-sized integers. +pub type Rational32 = Ratio; +/// Alias for a `Ratio` of 64-bit-sized integers. +pub type Rational64 = Ratio; + +#[cfg(feature = "num-bigint")] +/// Alias for arbitrary precision rationals. +pub type BigRational = Ratio; + +/// These method are `const`. +impl Ratio { + /// Creates a `Ratio` without checking for `denom == 0` or reducing. + /// + /// **There are several methods that will panic if used on a `Ratio` with + /// `denom == 0`.** + #[inline] + pub const fn new_raw(numer: T, denom: T) -> Ratio { + Ratio { numer, denom } + } + + /// Deconstructs a `Ratio` into its numerator and denominator. + #[inline] + pub fn into_raw(self) -> (T, T) { + (self.numer, self.denom) + } + + /// Gets an immutable reference to the numerator. + #[inline] + pub const fn numer(&self) -> &T { + &self.numer + } + + /// Gets an immutable reference to the denominator. + #[inline] + pub const fn denom(&self) -> &T { + &self.denom + } +} + +impl Ratio { + /// Creates a new `Ratio`. + /// + /// **Panics if `denom` is zero.** + #[inline] + pub fn new(numer: T, denom: T) -> Ratio { + let mut ret = Ratio::new_raw(numer, denom); + ret.reduce(); + ret + } + + /// Creates a `Ratio` representing the integer `t`. + #[inline] + pub fn from_integer(t: T) -> Ratio { + Ratio::new_raw(t, One::one()) + } + + /// Converts to an integer, rounding towards zero. + #[inline] + pub fn to_integer(&self) -> T { + self.trunc().numer + } + + /// Returns true if the rational number is an integer (denominator is 1). + #[inline] + pub fn is_integer(&self) -> bool { + self.denom.is_one() + } + + /// Puts self into lowest terms, with `denom` > 0. + /// + /// **Panics if `denom` is zero.** + fn reduce(&mut self) { + if self.denom.is_zero() { + panic!("denominator == 0"); + } + if self.numer.is_zero() { + self.denom.set_one(); + return; + } + if self.numer == self.denom { + self.set_one(); + return; + } + let g: T = self.numer.gcd(&self.denom); + + // FIXME(#5992): assignment operator overloads + // T: Clone + Integer != T: Clone + NumAssign + + #[inline] + fn replace_with(x: &mut T, f: impl FnOnce(T) -> T) { + let y = core::mem::replace(x, T::zero()); + *x = f(y); + } + + // self.numer /= g; + replace_with(&mut self.numer, |x| x / g.clone()); + + // self.denom /= g; + replace_with(&mut self.denom, |x| x / g); + + // keep denom positive! + if self.denom < T::zero() { + replace_with(&mut self.numer, |x| T::zero() - x); + replace_with(&mut self.denom, |x| T::zero() - x); + } + } + + /// Returns a reduced copy of self. + /// + /// In general, it is not necessary to use this method, as the only + /// method of procuring a non-reduced fraction is through `new_raw`. + /// + /// **Panics if `denom` is zero.** + pub fn reduced(&self) -> Ratio { + let mut ret = self.clone(); + ret.reduce(); + ret + } + + /// Returns the reciprocal. + /// + /// **Panics if the `Ratio` is zero.** + #[inline] + pub fn recip(&self) -> Ratio { + self.clone().into_recip() + } + + #[inline] + fn into_recip(self) -> Ratio { + match self.numer.cmp(&T::zero()) { + cmp::Ordering::Equal => panic!("division by zero"), + cmp::Ordering::Greater => Ratio::new_raw(self.denom, self.numer), + cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom, T::zero() - self.numer), + } + } + + /// Rounds towards minus infinity. + #[inline] + pub fn floor(&self) -> Ratio { + if *self < Zero::zero() { + let one: T = One::one(); + Ratio::from_integer( + (self.numer.clone() - self.denom.clone() + one) / self.denom.clone(), + ) + } else { + Ratio::from_integer(self.numer.clone() / self.denom.clone()) + } + } + + /// Rounds towards plus infinity. + #[inline] + pub fn ceil(&self) -> Ratio { + if *self < Zero::zero() { + Ratio::from_integer(self.numer.clone() / self.denom.clone()) + } else { + let one: T = One::one(); + Ratio::from_integer( + (self.numer.clone() + self.denom.clone() - one) / self.denom.clone(), + ) + } + } + + /// Rounds to the nearest integer. Rounds half-way cases away from zero. + #[inline] + pub fn round(&self) -> Ratio { + let zero: Ratio = Zero::zero(); + let one: T = One::one(); + let two: T = one.clone() + one.clone(); + + // Find unsigned fractional part of rational number + let mut fractional = self.fract(); + if fractional < zero { + fractional = zero - fractional + }; + + // The algorithm compares the unsigned fractional part with 1/2, that + // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use + // a >= (b/2)+1. This avoids overflow issues. + let half_or_larger = if fractional.denom.is_even() { + fractional.numer >= fractional.denom / two + } else { + fractional.numer >= (fractional.denom / two) + one + }; + + if half_or_larger { + let one: Ratio = One::one(); + if *self >= Zero::zero() { + self.trunc() + one + } else { + self.trunc() - one + } + } else { + self.trunc() + } + } + + /// Rounds towards zero. + #[inline] + pub fn trunc(&self) -> Ratio { + Ratio::from_integer(self.numer.clone() / self.denom.clone()) + } + + /// Returns the fractional part of a number, with division rounded towards zero. + /// + /// Satisfies `self == self.trunc() + self.fract()`. + #[inline] + pub fn fract(&self) -> Ratio { + Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone()) + } + + /// Raises the `Ratio` to the power of an exponent. + #[inline] + pub fn pow(&self, expon: i32) -> Ratio + where + for<'a> &'a T: Pow, + { + Pow::pow(self, expon) + } +} + +#[cfg(feature = "num-bigint")] +impl Ratio { + /// Converts a float into a rational number. + pub fn from_float(f: T) -> Option { + if !f.is_finite() { + return None; + } + let (mantissa, exponent, sign) = f.integer_decode(); + let bigint_sign = if sign == 1 { Sign::Plus } else { Sign::Minus }; + if exponent < 0 { + let one: BigInt = One::one(); + let denom: BigInt = one << ((-exponent) as usize); + let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap(); + Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom)) + } else { + let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap(); + numer <<= exponent as usize; + Some(Ratio::from_integer(BigInt::from_biguint( + bigint_sign, + numer, + ))) + } + } +} + +impl Default for Ratio { + /// Returns zero + fn default() -> Self { + Ratio::zero() + } +} + +// From integer +impl From for Ratio +where + T: Clone + Integer, +{ + fn from(x: T) -> Ratio { + Ratio::from_integer(x) + } +} + +// From pair (through the `new` constructor) +impl From<(T, T)> for Ratio +where + T: Clone + Integer, +{ + fn from(pair: (T, T)) -> Ratio { + Ratio::new(pair.0, pair.1) + } +} + +// Comparisons + +// Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy +// for those multiplications to overflow fixed-size integers, so we need to take care. + +impl Ord for Ratio { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + // With equal denominators, the numerators can be directly compared + if self.denom == other.denom { + let ord = self.numer.cmp(&other.numer); + return if self.denom < T::zero() { + ord.reverse() + } else { + ord + }; + } + + // With equal numerators, the denominators can be inversely compared + if self.numer == other.numer { + if self.numer.is_zero() { + return cmp::Ordering::Equal; + } + let ord = self.denom.cmp(&other.denom); + return if self.numer < T::zero() { + ord + } else { + ord.reverse() + }; + } + + // Unfortunately, we don't have CheckedMul to try. That could sometimes avoid all the + // division below, or even always avoid it for BigInt and BigUint. + // FIXME- future breaking change to add Checked* to Integer? + + // Compare as floored integers and remainders + let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom); + let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom); + match self_int.cmp(&other_int) { + cmp::Ordering::Greater => cmp::Ordering::Greater, + cmp::Ordering::Less => cmp::Ordering::Less, + cmp::Ordering::Equal => { + match (self_rem.is_zero(), other_rem.is_zero()) { + (true, true) => cmp::Ordering::Equal, + (true, false) => cmp::Ordering::Less, + (false, true) => cmp::Ordering::Greater, + (false, false) => { + // Compare the reciprocals of the remaining fractions in reverse + let self_recip = Ratio::new_raw(self.denom.clone(), self_rem); + let other_recip = Ratio::new_raw(other.denom.clone(), other_rem); + self_recip.cmp(&other_recip).reverse() + } + } + } + } + } +} + +impl PartialOrd for Ratio { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Ratio { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == cmp::Ordering::Equal + } +} + +impl Eq for Ratio {} + +// NB: We can't just `#[derive(Hash)]`, because it needs to agree +// with `Eq` even for non-reduced ratios. +impl Hash for Ratio { + fn hash(&self, state: &mut H) { + recurse(&self.numer, &self.denom, state); + + fn recurse(numer: &T, denom: &T, state: &mut H) { + if !denom.is_zero() { + let (int, rem) = numer.div_mod_floor(denom); + int.hash(state); + recurse(denom, &rem, state); + } else { + denom.hash(state); + } + } + } +} + +mod iter_sum_product { + use crate::Ratio; + use core::iter::{Product, Sum}; + use num_integer::Integer; + use num_traits::{One, Zero}; + + impl Sum for Ratio { + fn sum(iter: I) -> Self + where + I: Iterator>, + { + iter.fold(Self::zero(), |sum, num| sum + num) + } + } + + impl<'a, T: Integer + Clone> Sum<&'a Ratio> for Ratio { + fn sum(iter: I) -> Self + where + I: Iterator>, + { + iter.fold(Self::zero(), |sum, num| sum + num) + } + } + + impl Product for Ratio { + fn product(iter: I) -> Self + where + I: Iterator>, + { + iter.fold(Self::one(), |prod, num| prod * num) + } + } + + impl<'a, T: Integer + Clone> Product<&'a Ratio> for Ratio { + fn product(iter: I) -> Self + where + I: Iterator>, + { + iter.fold(Self::one(), |prod, num| prod * num) + } + } +} + +mod opassign { + use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; + + use crate::Ratio; + use num_integer::Integer; + use num_traits::NumAssign; + + impl AddAssign for Ratio { + fn add_assign(&mut self, other: Ratio) { + if self.denom == other.denom { + self.numer += other.numer + } else { + let lcm = self.denom.lcm(&other.denom); + let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); + let rhs_numer = other.numer * (lcm.clone() / other.denom); + self.numer = lhs_numer + rhs_numer; + self.denom = lcm; + } + self.reduce(); + } + } + + // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd)) + impl DivAssign for Ratio { + fn div_assign(&mut self, other: Ratio) { + let gcd_ac = self.numer.gcd(&other.numer); + let gcd_bd = self.denom.gcd(&other.denom); + self.numer /= gcd_ac.clone(); + self.numer *= other.denom / gcd_bd.clone(); + self.denom /= gcd_bd; + self.denom *= other.numer / gcd_ac; + self.reduce(); // TODO: remove this line. see #8. + } + } + + // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc)) + impl MulAssign for Ratio { + fn mul_assign(&mut self, other: Ratio) { + let gcd_ad = self.numer.gcd(&other.denom); + let gcd_bc = self.denom.gcd(&other.numer); + self.numer /= gcd_ad.clone(); + self.numer *= other.numer / gcd_bc.clone(); + self.denom /= gcd_bc; + self.denom *= other.denom / gcd_ad; + self.reduce(); // TODO: remove this line. see #8. + } + } + + impl RemAssign for Ratio { + fn rem_assign(&mut self, other: Ratio) { + if self.denom == other.denom { + self.numer %= other.numer + } else { + let lcm = self.denom.lcm(&other.denom); + let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); + let rhs_numer = other.numer * (lcm.clone() / other.denom); + self.numer = lhs_numer % rhs_numer; + self.denom = lcm; + } + self.reduce(); + } + } + + impl SubAssign for Ratio { + fn sub_assign(&mut self, other: Ratio) { + if self.denom == other.denom { + self.numer -= other.numer + } else { + let lcm = self.denom.lcm(&other.denom); + let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); + let rhs_numer = other.numer * (lcm.clone() / other.denom); + self.numer = lhs_numer - rhs_numer; + self.denom = lcm; + } + self.reduce(); + } + } + + // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b + impl AddAssign for Ratio { + fn add_assign(&mut self, other: T) { + self.numer += self.denom.clone() * other; + self.reduce(); + } + } + + impl DivAssign for Ratio { + fn div_assign(&mut self, other: T) { + let gcd = self.numer.gcd(&other); + self.numer /= gcd.clone(); + self.denom *= other / gcd; + self.reduce(); // TODO: remove this line. see #8. + } + } + + impl MulAssign for Ratio { + fn mul_assign(&mut self, other: T) { + let gcd = self.denom.gcd(&other); + self.denom /= gcd.clone(); + self.numer *= other / gcd; + self.reduce(); // TODO: remove this line. see #8. + } + } + + // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b + impl RemAssign for Ratio { + fn rem_assign(&mut self, other: T) { + self.numer %= self.denom.clone() * other; + self.reduce(); + } + } + + // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b + impl SubAssign for Ratio { + fn sub_assign(&mut self, other: T) { + self.numer -= self.denom.clone() * other; + self.reduce(); + } + } + + macro_rules! forward_op_assign { + (impl $imp:ident, $method:ident) => { + impl<'a, T: Clone + Integer + NumAssign> $imp<&'a Ratio> for Ratio { + #[inline] + fn $method(&mut self, other: &Ratio) { + self.$method(other.clone()) + } + } + impl<'a, T: Clone + Integer + NumAssign> $imp<&'a T> for Ratio { + #[inline] + fn $method(&mut self, other: &T) { + self.$method(other.clone()) + } + } + }; + } + + forward_op_assign!(impl AddAssign, add_assign); + forward_op_assign!(impl DivAssign, div_assign); + forward_op_assign!(impl MulAssign, mul_assign); + forward_op_assign!(impl RemAssign, rem_assign); + forward_op_assign!(impl SubAssign, sub_assign); +} + +macro_rules! forward_ref_ref_binop { + (impl $imp:ident, $method:ident) => { + impl<'a, 'b, T: Clone + Integer> $imp<&'b Ratio> for &'a Ratio { + type Output = Ratio; + + #[inline] + fn $method(self, other: &'b Ratio) -> Ratio { + self.clone().$method(other.clone()) + } + } + impl<'a, 'b, T: Clone + Integer> $imp<&'b T> for &'a Ratio { + type Output = Ratio; + + #[inline] + fn $method(self, other: &'b T) -> Ratio { + self.clone().$method(other.clone()) + } + } + }; +} + +macro_rules! forward_ref_val_binop { + (impl $imp:ident, $method:ident) => { + impl<'a, T> $imp> for &'a Ratio + where + T: Clone + Integer, + { + type Output = Ratio; + + #[inline] + fn $method(self, other: Ratio) -> Ratio { + self.clone().$method(other) + } + } + impl<'a, T> $imp for &'a Ratio + where + T: Clone + Integer, + { + type Output = Ratio; + + #[inline] + fn $method(self, other: T) -> Ratio { + self.clone().$method(other) + } + } + }; +} + +macro_rules! forward_val_ref_binop { + (impl $imp:ident, $method:ident) => { + impl<'a, T> $imp<&'a Ratio> for Ratio + where + T: Clone + Integer, + { + type Output = Ratio; + + #[inline] + fn $method(self, other: &Ratio) -> Ratio { + self.$method(other.clone()) + } + } + impl<'a, T> $imp<&'a T> for Ratio + where + T: Clone + Integer, + { + type Output = Ratio; + + #[inline] + fn $method(self, other: &T) -> Ratio { + self.$method(other.clone()) + } + } + }; +} + +macro_rules! forward_all_binop { + (impl $imp:ident, $method:ident) => { + forward_ref_ref_binop!(impl $imp, $method); + forward_ref_val_binop!(impl $imp, $method); + forward_val_ref_binop!(impl $imp, $method); + }; +} + +// Arithmetic +forward_all_binop!(impl Mul, mul); +// a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc)) +impl Mul> for Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + #[inline] + fn mul(self, rhs: Ratio) -> Ratio { + let gcd_ad = self.numer.gcd(&rhs.denom); + let gcd_bc = self.denom.gcd(&rhs.numer); + Ratio::new( + self.numer / gcd_ad.clone() * (rhs.numer / gcd_bc.clone()), + self.denom / gcd_bc * (rhs.denom / gcd_ad), + ) + } +} +// a/b * c/1 = (a*c) / (b*1) = (a*c) / b +impl Mul for Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + #[inline] + fn mul(self, rhs: T) -> Ratio { + let gcd = self.denom.gcd(&rhs); + Ratio::new(self.numer * (rhs / gcd.clone()), self.denom / gcd) + } +} + +forward_all_binop!(impl Div, div); +// (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd)) +impl Div> for Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + + #[inline] + fn div(self, rhs: Ratio) -> Ratio { + let gcd_ac = self.numer.gcd(&rhs.numer); + let gcd_bd = self.denom.gcd(&rhs.denom); + Ratio::new( + self.numer / gcd_ac.clone() * (rhs.denom / gcd_bd.clone()), + self.denom / gcd_bd * (rhs.numer / gcd_ac), + ) + } +} +// (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c) +impl Div for Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + + #[inline] + fn div(self, rhs: T) -> Ratio { + let gcd = self.numer.gcd(&rhs); + Ratio::new(self.numer / gcd.clone(), self.denom * (rhs / gcd)) + } +} + +macro_rules! arith_impl { + (impl $imp:ident, $method:ident) => { + forward_all_binop!(impl $imp, $method); + // Abstracts a/b `op` c/d = (a*lcm/b `op` c*lcm/d)/lcm where lcm = lcm(b,d) + impl $imp> for Ratio { + type Output = Ratio; + #[inline] + fn $method(self, rhs: Ratio) -> Ratio { + if self.denom == rhs.denom { + return Ratio::new(self.numer.$method(rhs.numer), rhs.denom); + } + let lcm = self.denom.lcm(&rhs.denom); + let lhs_numer = self.numer * (lcm.clone() / self.denom); + let rhs_numer = rhs.numer * (lcm.clone() / rhs.denom); + Ratio::new(lhs_numer.$method(rhs_numer), lcm) + } + } + // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern + impl $imp for Ratio { + type Output = Ratio; + #[inline] + fn $method(self, rhs: T) -> Ratio { + Ratio::new(self.numer.$method(self.denom.clone() * rhs), self.denom) + } + } + }; +} + +arith_impl!(impl Add, add); +arith_impl!(impl Sub, sub); +arith_impl!(impl Rem, rem); + +// a/b * c/d = (a*c)/(b*d) +impl CheckedMul for Ratio +where + T: Clone + Integer + CheckedMul, +{ + #[inline] + fn checked_mul(&self, rhs: &Ratio) -> Option> { + let gcd_ad = self.numer.gcd(&rhs.denom); + let gcd_bc = self.denom.gcd(&rhs.numer); + Some(Ratio::new( + (self.numer.clone() / gcd_ad.clone()) + .checked_mul(&(rhs.numer.clone() / gcd_bc.clone()))?, + (self.denom.clone() / gcd_bc).checked_mul(&(rhs.denom.clone() / gcd_ad))?, + )) + } +} + +// (a/b) / (c/d) = (a*d)/(b*c) +impl CheckedDiv for Ratio +where + T: Clone + Integer + CheckedMul, +{ + #[inline] + fn checked_div(&self, rhs: &Ratio) -> Option> { + if rhs.is_zero() { + return None; + } + let (numer, denom) = if self.denom == rhs.denom { + (self.numer.clone(), rhs.numer.clone()) + } else if self.numer == rhs.numer { + (rhs.denom.clone(), self.denom.clone()) + } else { + let gcd_ac = self.numer.gcd(&rhs.numer); + let gcd_bd = self.denom.gcd(&rhs.denom); + ( + (self.numer.clone() / gcd_ac.clone()) + .checked_mul(&(rhs.denom.clone() / gcd_bd.clone()))?, + (self.denom.clone() / gcd_bd).checked_mul(&(rhs.numer.clone() / gcd_ac))?, + ) + }; + // Manual `reduce()`, avoiding sharp edges + if denom.is_zero() { + None + } else if numer.is_zero() { + Some(Self::zero()) + } else if numer == denom { + Some(Self::one()) + } else { + let g = numer.gcd(&denom); + let numer = numer / g.clone(); + let denom = denom / g; + let raw = if denom < T::zero() { + // We need to keep denom positive, but 2's-complement MIN may + // overflow negation -- instead we can check multiplying -1. + let n1 = T::zero() - T::one(); + Ratio::new_raw(numer.checked_mul(&n1)?, denom.checked_mul(&n1)?) + } else { + Ratio::new_raw(numer, denom) + }; + Some(raw) + } + } +} + +// As arith_impl! but for Checked{Add,Sub} traits +macro_rules! checked_arith_impl { + (impl $imp:ident, $method:ident) => { + impl $imp for Ratio { + #[inline] + fn $method(&self, rhs: &Ratio) -> Option> { + let gcd = self.denom.clone().gcd(&rhs.denom); + let lcm = (self.denom.clone() / gcd.clone()).checked_mul(&rhs.denom)?; + let lhs_numer = (lcm.clone() / self.denom.clone()).checked_mul(&self.numer)?; + let rhs_numer = (lcm.clone() / rhs.denom.clone()).checked_mul(&rhs.numer)?; + Some(Ratio::new(lhs_numer.$method(&rhs_numer)?, lcm)) + } + } + }; +} + +// a/b + c/d = (lcm/b*a + lcm/d*c)/lcm, where lcm = lcm(b,d) +checked_arith_impl!(impl CheckedAdd, checked_add); + +// a/b - c/d = (lcm/b*a - lcm/d*c)/lcm, where lcm = lcm(b,d) +checked_arith_impl!(impl CheckedSub, checked_sub); + +impl Neg for Ratio +where + T: Clone + Integer + Neg, +{ + type Output = Ratio; + + #[inline] + fn neg(self) -> Ratio { + Ratio::new_raw(-self.numer, self.denom) + } +} + +impl<'a, T> Neg for &'a Ratio +where + T: Clone + Integer + Neg, +{ + type Output = Ratio; + + #[inline] + fn neg(self) -> Ratio { + -self.clone() + } +} + +impl Inv for Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + + #[inline] + fn inv(self) -> Ratio { + self.recip() + } +} + +impl<'a, T> Inv for &'a Ratio +where + T: Clone + Integer, +{ + type Output = Ratio; + + #[inline] + fn inv(self) -> Ratio { + self.recip() + } +} + +// Constants +impl Ratio { + /// A constant `Ratio` 0/1. + pub const ZERO: Self = Self::new_raw(T::ZERO, T::ONE); +} + +impl ConstZero for Ratio { + const ZERO: Self = Self::ZERO; +} + +impl Zero for Ratio { + #[inline] + fn zero() -> Ratio { + Ratio::new_raw(Zero::zero(), One::one()) + } + + #[inline] + fn is_zero(&self) -> bool { + self.numer.is_zero() + } + + #[inline] + fn set_zero(&mut self) { + self.numer.set_zero(); + self.denom.set_one(); + } +} + +impl Ratio { + /// A constant `Ratio` 1/1. + pub const ONE: Self = Self::new_raw(T::ONE, T::ONE); +} + +impl ConstOne for Ratio { + const ONE: Self = Self::ONE; +} + +impl One for Ratio { + #[inline] + fn one() -> Ratio { + Ratio::new_raw(One::one(), One::one()) + } + + #[inline] + fn is_one(&self) -> bool { + self.numer == self.denom + } + + #[inline] + fn set_one(&mut self) { + self.numer.set_one(); + self.denom.set_one(); + } +} + +impl Num for Ratio { + type FromStrRadixErr = ParseRatioError; + + /// Parses `numer/denom` where the numbers are in base `radix`. + fn from_str_radix(s: &str, radix: u32) -> Result, ParseRatioError> { + if s.splitn(2, '/').count() == 2 { + let mut parts = s.splitn(2, '/').map(|ss| { + T::from_str_radix(ss, radix).map_err(|_| ParseRatioError { + kind: RatioErrorKind::ParseError, + }) + }); + let numer: T = parts.next().unwrap()?; + let denom: T = parts.next().unwrap()?; + if denom.is_zero() { + Err(ParseRatioError { + kind: RatioErrorKind::ZeroDenominator, + }) + } else { + Ok(Ratio::new(numer, denom)) + } + } else { + Err(ParseRatioError { + kind: RatioErrorKind::ParseError, + }) + } + } +} + +impl Signed for Ratio { + #[inline] + fn abs(&self) -> Ratio { + if self.is_negative() { + -self.clone() + } else { + self.clone() + } + } + + #[inline] + fn abs_sub(&self, other: &Ratio) -> Ratio { + if *self <= *other { + Zero::zero() + } else { + self - other + } + } + + #[inline] + fn signum(&self) -> Ratio { + if self.is_positive() { + Self::one() + } else if self.is_zero() { + Self::zero() + } else { + -Self::one() + } + } + + #[inline] + fn is_positive(&self) -> bool { + (self.numer.is_positive() && self.denom.is_positive()) + || (self.numer.is_negative() && self.denom.is_negative()) + } + + #[inline] + fn is_negative(&self) -> bool { + (self.numer.is_negative() && self.denom.is_positive()) + || (self.numer.is_positive() && self.denom.is_negative()) + } +} + +// String conversions +macro_rules! impl_formatting { + ($fmt_trait:ident, $prefix:expr, $fmt_str:expr, $fmt_alt:expr) => { + impl $fmt_trait for Ratio { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let pre_pad = if self.denom.is_one() { + format!($fmt_str, self.numer) + } else { + if f.alternate() { + format!(concat!($fmt_str, "/", $fmt_alt), self.numer, self.denom) + } else { + format!(concat!($fmt_str, "/", $fmt_str), self.numer, self.denom) + } + }; + if let Some(pre_pad) = pre_pad.strip_prefix("-") { + f.pad_integral(false, $prefix, pre_pad) + } else { + f.pad_integral(true, $prefix, &pre_pad) + } + } + #[cfg(not(feature = "std"))] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let plus = if f.sign_plus() && self.numer >= T::zero() { + "+" + } else { + "" + }; + if self.denom.is_one() { + if f.alternate() { + write!(f, concat!("{}", $fmt_alt), plus, self.numer) + } else { + write!(f, concat!("{}", $fmt_str), plus, self.numer) + } + } else { + if f.alternate() { + write!( + f, + concat!("{}", $fmt_alt, "/", $fmt_alt), + plus, self.numer, self.denom + ) + } else { + write!( + f, + concat!("{}", $fmt_str, "/", $fmt_str), + plus, self.numer, self.denom + ) + } + } + } + } + }; +} + +impl_formatting!(Display, "", "{}", "{:#}"); +impl_formatting!(Octal, "0o", "{:o}", "{:#o}"); +impl_formatting!(Binary, "0b", "{:b}", "{:#b}"); +impl_formatting!(LowerHex, "0x", "{:x}", "{:#x}"); +impl_formatting!(UpperHex, "0x", "{:X}", "{:#X}"); +impl_formatting!(LowerExp, "", "{:e}", "{:#e}"); +impl_formatting!(UpperExp, "", "{:E}", "{:#E}"); + +impl FromStr for Ratio { + type Err = ParseRatioError; + + /// Parses `numer/denom` or just `numer`. + fn from_str(s: &str) -> Result, ParseRatioError> { + let mut split = s.splitn(2, '/'); + + let n = split.next().ok_or(ParseRatioError { + kind: RatioErrorKind::ParseError, + })?; + let num = FromStr::from_str(n).map_err(|_| ParseRatioError { + kind: RatioErrorKind::ParseError, + })?; + + let d = split.next().unwrap_or("1"); + let den = FromStr::from_str(d).map_err(|_| ParseRatioError { + kind: RatioErrorKind::ParseError, + })?; + + if Zero::is_zero(&den) { + Err(ParseRatioError { + kind: RatioErrorKind::ZeroDenominator, + }) + } else { + Ok(Ratio::new(num, den)) + } + } +} + +impl From> for (T, T) { + fn from(val: Ratio) -> Self { + (val.numer, val.denom) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Ratio +where + T: serde::Serialize + Clone + Integer + PartialOrd, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + (self.numer(), self.denom()).serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, T> serde::Deserialize<'de> for Ratio +where + T: serde::Deserialize<'de> + Clone + Integer + PartialOrd, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + use serde::de::Unexpected; + let (numer, denom): (T, T) = serde::Deserialize::deserialize(deserializer)?; + if denom.is_zero() { + Err(Error::invalid_value( + Unexpected::Signed(0), + &"a ratio with non-zero denominator", + )) + } else { + Ok(Ratio::new_raw(numer, denom)) + } + } +} + +// FIXME: Bubble up specific errors +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct ParseRatioError { + kind: RatioErrorKind, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +enum RatioErrorKind { + ParseError, + ZeroDenominator, +} + +impl fmt::Display for ParseRatioError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.kind.description().fmt(f) + } +} + +#[cfg(feature = "std")] +impl Error for ParseRatioError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.kind.description() + } +} + +impl RatioErrorKind { + fn description(&self) -> &'static str { + match *self { + RatioErrorKind::ParseError => "failed to parse integer", + RatioErrorKind::ZeroDenominator => "zero value denominator", + } + } +} + +#[cfg(feature = "num-bigint")] +impl FromPrimitive for Ratio { + fn from_i64(n: i64) -> Option { + Some(Ratio::from_integer(n.into())) + } + + fn from_i128(n: i128) -> Option { + Some(Ratio::from_integer(n.into())) + } + + fn from_u64(n: u64) -> Option { + Some(Ratio::from_integer(n.into())) + } + + fn from_u128(n: u128) -> Option { + Some(Ratio::from_integer(n.into())) + } + + fn from_f32(n: f32) -> Option { + Ratio::from_float(n) + } + + fn from_f64(n: f64) -> Option { + Ratio::from_float(n) + } +} + +macro_rules! from_primitive_integer { + ($typ:ty, $approx:ident) => { + impl FromPrimitive for Ratio<$typ> { + fn from_i64(n: i64) -> Option { + <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer) + } + + fn from_i128(n: i128) -> Option { + <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer) + } + + fn from_u64(n: u64) -> Option { + <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer) + } + + fn from_u128(n: u128) -> Option { + <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer) + } + + fn from_f32(n: f32) -> Option { + $approx(n, 10e-20, 30) + } + + fn from_f64(n: f64) -> Option { + $approx(n, 10e-20, 30) + } + } + }; +} + +from_primitive_integer!(i8, approximate_float); +from_primitive_integer!(i16, approximate_float); +from_primitive_integer!(i32, approximate_float); +from_primitive_integer!(i64, approximate_float); +from_primitive_integer!(i128, approximate_float); +from_primitive_integer!(isize, approximate_float); + +from_primitive_integer!(u8, approximate_float_unsigned); +from_primitive_integer!(u16, approximate_float_unsigned); +from_primitive_integer!(u32, approximate_float_unsigned); +from_primitive_integer!(u64, approximate_float_unsigned); +from_primitive_integer!(u128, approximate_float_unsigned); +from_primitive_integer!(usize, approximate_float_unsigned); + +impl Ratio { + pub fn approximate_float(f: F) -> Option> { + // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems + // to work well. Might want to choose something based on the types in the future, e.g. + // T::max().recip() and T::bits() or something similar. + let epsilon = ::from(10e-20).expect("Can't convert 10e-20"); + approximate_float(f, epsilon, 30) + } +} + +impl Ratio { + pub fn approximate_float_unsigned(f: F) -> Option> { + // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems + // to work well. Might want to choose something based on the types in the future, e.g. + // T::max().recip() and T::bits() or something similar. + let epsilon = ::from(10e-20).expect("Can't convert 10e-20"); + approximate_float_unsigned(f, epsilon, 30) + } +} + +fn approximate_float(val: F, max_error: F, max_iterations: usize) -> Option> +where + T: Integer + Signed + Bounded + NumCast + Clone, + F: FloatCore + NumCast, +{ + let negative = val.is_sign_negative(); + let abs_val = val.abs(); + + let r = approximate_float_unsigned(abs_val, max_error, max_iterations)?; + + // Make negative again if needed + Some(if negative { r.neg() } else { r }) +} + +// No Unsigned constraint because this also works on positive integers and is called +// like that, see above +fn approximate_float_unsigned(val: F, max_error: F, max_iterations: usize) -> Option> +where + T: Integer + Bounded + NumCast + Clone, + F: FloatCore + NumCast, +{ + // Continued fractions algorithm + // https://web.archive.org/web/20200629111319/http://mathforum.org:80/dr.math/faq/faq.fractions.html#decfrac + + if val < F::zero() || val.is_nan() { + return None; + } + + let mut q = val; + let mut n0 = T::zero(); + let mut d0 = T::one(); + let mut n1 = T::one(); + let mut d1 = T::zero(); + + let t_max = T::max_value(); + let t_max_f = ::from(t_max.clone())?; + + // 1/epsilon > T::MAX + let epsilon = t_max_f.recip(); + + // Overflow + if q > t_max_f { + return None; + } + + for _ in 0..max_iterations { + let a = match ::from(q) { + None => break, + Some(a) => a, + }; + + let a_f = match ::from(a.clone()) { + None => break, + Some(a_f) => a_f, + }; + let f = q - a_f; + + // Prevent overflow + if !a.is_zero() + && (n1 > t_max.clone() / a.clone() + || d1 > t_max.clone() / a.clone() + || a.clone() * n1.clone() > t_max.clone() - n0.clone() + || a.clone() * d1.clone() > t_max.clone() - d0.clone()) + { + break; + } + + let n = a.clone() * n1.clone() + n0.clone(); + let d = a.clone() * d1.clone() + d0.clone(); + + n0 = n1; + d0 = d1; + n1 = n.clone(); + d1 = d.clone(); + + // Simplify fraction. Doing so here instead of at the end + // allows us to get closer to the target value without overflows + let g = Integer::gcd(&n1, &d1); + if !g.is_zero() { + n1 = n1 / g.clone(); + d1 = d1 / g.clone(); + } + + // Close enough? + let (n_f, d_f) = match (::from(n), ::from(d)) { + (Some(n_f), Some(d_f)) => (n_f, d_f), + _ => break, + }; + if (n_f / d_f - val).abs() < max_error { + break; + } + + // Prevent division by ~0 + if f < epsilon { + break; + } + q = f.recip(); + } + + // Overflow + if d1.is_zero() { + return None; + } + + Some(Ratio::new(n1, d1)) +} + +#[cfg(not(feature = "num-bigint"))] +macro_rules! to_primitive_small { + ($($type_name:ty)*) => ($( + impl ToPrimitive for Ratio<$type_name> { + fn to_i64(&self) -> Option { + self.to_integer().to_i64() + } + + fn to_i128(&self) -> Option { + self.to_integer().to_i128() + } + + fn to_u64(&self) -> Option { + self.to_integer().to_u64() + } + + fn to_u128(&self) -> Option { + self.to_integer().to_u128() + } + + fn to_f64(&self) -> Option { + let float = self.numer.to_f64().unwrap() / self.denom.to_f64().unwrap(); + if float.is_nan() { + None + } else { + Some(float) + } + } + } + )*) +} + +#[cfg(not(feature = "num-bigint"))] +to_primitive_small!(u8 i8 u16 i16 u32 i32); + +#[cfg(all(target_pointer_width = "32", not(feature = "num-bigint")))] +to_primitive_small!(usize isize); + +#[cfg(not(feature = "num-bigint"))] +macro_rules! to_primitive_64 { + ($($type_name:ty)*) => ($( + impl ToPrimitive for Ratio<$type_name> { + fn to_i64(&self) -> Option { + self.to_integer().to_i64() + } + + fn to_i128(&self) -> Option { + self.to_integer().to_i128() + } + + fn to_u64(&self) -> Option { + self.to_integer().to_u64() + } + + fn to_u128(&self) -> Option { + self.to_integer().to_u128() + } + + fn to_f64(&self) -> Option { + let float = ratio_to_f64( + self.numer as i128, + self.denom as i128 + ); + if float.is_nan() { + None + } else { + Some(float) + } + } + } + )*) +} + +#[cfg(not(feature = "num-bigint"))] +to_primitive_64!(u64 i64); + +#[cfg(all(target_pointer_width = "64", not(feature = "num-bigint")))] +to_primitive_64!(usize isize); + +#[cfg(feature = "num-bigint")] +impl ToPrimitive for Ratio { + fn to_i64(&self) -> Option { + self.to_integer().to_i64() + } + + fn to_i128(&self) -> Option { + self.to_integer().to_i128() + } + + fn to_u64(&self) -> Option { + self.to_integer().to_u64() + } + + fn to_u128(&self) -> Option { + self.to_integer().to_u128() + } + + fn to_f64(&self) -> Option { + let float = match (self.numer.to_i64(), self.denom.to_i64()) { + (Some(numer), Some(denom)) => ratio_to_f64( + >::from(numer), + >::from(denom), + ), + _ => { + let numer: BigInt = self.numer.to_bigint()?; + let denom: BigInt = self.denom.to_bigint()?; + ratio_to_f64(numer, denom) + } + }; + if float.is_nan() { + None + } else { + Some(float) + } + } +} + +trait Bits { + fn bits(&self) -> u64; +} + +#[cfg(feature = "num-bigint")] +impl Bits for BigInt { + fn bits(&self) -> u64 { + self.bits() + } +} + +impl Bits for i128 { + fn bits(&self) -> u64 { + (128 - self.wrapping_abs().leading_zeros()).into() + } +} + +/// Converts a ratio of `T` to an f64. +/// +/// In addition to stated trait bounds, `T` must be able to hold numbers 56 bits larger than +/// the largest of `numer` and `denom`. This is automatically true if `T` is `BigInt`. +fn ratio_to_f64 + ToPrimitive>( + numer: T, + denom: T, +) -> f64 { + use core::f64::{INFINITY, MANTISSA_DIGITS, MAX_EXP, MIN_EXP, RADIX}; + + assert_eq!( + RADIX, 2, + "only floating point implementations with radix 2 are supported" + ); + + // Inclusive upper and lower bounds to the range of exactly-representable ints in an f64. + const MAX_EXACT_INT: i64 = 1i64 << MANTISSA_DIGITS; + const MIN_EXACT_INT: i64 = -MAX_EXACT_INT; + + let flo_sign = numer.signum().to_f64().unwrap() / denom.signum().to_f64().unwrap(); + if !flo_sign.is_normal() { + return flo_sign; + } + + // Fast track: both sides can losslessly be converted to f64s. In this case, letting the + // FPU do the job is faster and easier. In any other case, converting to f64s may lead + // to an inexact result: https://stackoverflow.com/questions/56641441/. + if let (Some(n), Some(d)) = (numer.to_i64(), denom.to_i64()) { + let exact = MIN_EXACT_INT..=MAX_EXACT_INT; + if exact.contains(&n) && exact.contains(&d) { + return n.to_f64().unwrap() / d.to_f64().unwrap(); + } + } + + // Otherwise, the goal is to obtain a quotient with at least 55 bits. 53 of these bits will + // be used as the mantissa of the resulting float, and the remaining two are for rounding. + // There's an error of up to 1 on the number of resulting bits, so we may get either 55 or + // 56 bits. + let mut numer = numer.abs(); + let mut denom = denom.abs(); + let (is_diff_positive, absolute_diff) = match numer.bits().checked_sub(denom.bits()) { + Some(diff) => (true, diff), + None => (false, denom.bits() - numer.bits()), + }; + + // Filter out overflows and underflows. After this step, the signed difference fits in an + // isize. + if is_diff_positive && absolute_diff > MAX_EXP as u64 { + return INFINITY * flo_sign; + } + if !is_diff_positive && absolute_diff > -MIN_EXP as u64 + MANTISSA_DIGITS as u64 + 1 { + return 0.0 * flo_sign; + } + let diff = if is_diff_positive { + absolute_diff.to_isize().unwrap() + } else { + -absolute_diff.to_isize().unwrap() + }; + + // Shift is chosen so that the quotient will have 55 or 56 bits. The exception is if the + // quotient is going to be subnormal, in which case it may have fewer bits. + let shift: isize = diff.max(MIN_EXP as isize) - MANTISSA_DIGITS as isize - 2; + if shift >= 0 { + denom <<= shift as usize + } else { + numer <<= -shift as usize + }; + + let (quotient, remainder) = numer.div_rem(&denom); + + // This is guaranteed to fit since we've set up quotient to be at most 56 bits. + let mut quotient = quotient.to_u64().unwrap(); + let n_rounding_bits = { + let quotient_bits = 64 - quotient.leading_zeros() as isize; + let subnormal_bits = MIN_EXP as isize - shift; + quotient_bits.max(subnormal_bits) - MANTISSA_DIGITS as isize + } as usize; + debug_assert!(n_rounding_bits == 2 || n_rounding_bits == 3); + let rounding_bit_mask = (1u64 << n_rounding_bits) - 1; + + // Round to 53 bits with round-to-even. For rounding, we need to take into account both + // our rounding bits and the division's remainder. + let ls_bit = quotient & (1u64 << n_rounding_bits) != 0; + let ms_rounding_bit = quotient & (1u64 << (n_rounding_bits - 1)) != 0; + let ls_rounding_bits = quotient & (rounding_bit_mask >> 1) != 0; + if ms_rounding_bit && (ls_bit || ls_rounding_bits || !remainder.is_zero()) { + quotient += 1u64 << n_rounding_bits; + } + quotient &= !rounding_bit_mask; + + // The quotient is guaranteed to be exactly representable as it's now 53 bits + 2 or 3 + // trailing zeros, so there is no risk of a rounding error here. + let q_float = quotient as f64 * flo_sign; + ldexp(q_float, shift as i32) +} + +/// Multiply `x` by 2 to the power of `exp`. Returns an accurate result even if `2^exp` is not +/// representable. +fn ldexp(x: f64, exp: i32) -> f64 { + use core::f64::{INFINITY, MANTISSA_DIGITS, MAX_EXP, RADIX}; + + assert_eq!( + RADIX, 2, + "only floating point implementations with radix 2 are supported" + ); + + const EXPONENT_MASK: u64 = 0x7ff << 52; + const MAX_UNSIGNED_EXPONENT: i32 = 0x7fe; + const MIN_SUBNORMAL_POWER: i32 = MANTISSA_DIGITS as i32; + + if x.is_zero() || x.is_infinite() || x.is_nan() { + return x; + } + + // Filter out obvious over / underflows to make sure the resulting exponent fits in an isize. + if exp > 3 * MAX_EXP { + return INFINITY * x.signum(); + } else if exp < -3 * MAX_EXP { + return 0.0 * x.signum(); + } + + // curr_exp is the x's *biased* exponent, and is in the [-54, MAX_UNSIGNED_EXPONENT] range. + let (bits, curr_exp) = if !x.is_normal() { + // If x is subnormal, we make it normal by multiplying by 2^53. This causes no loss of + // precision or rounding. + let normal_x = x * 2f64.powi(MIN_SUBNORMAL_POWER); + let bits = normal_x.to_bits(); + // This cast is safe because the exponent is at most 0x7fe, which fits in an i32. + ( + bits, + ((bits & EXPONENT_MASK) >> 52) as i32 - MIN_SUBNORMAL_POWER, + ) + } else { + let bits = x.to_bits(); + let curr_exp = (bits & EXPONENT_MASK) >> 52; + // This cast is safe because the exponent is at most 0x7fe, which fits in an i32. + (bits, curr_exp as i32) + }; + + // The addition can't overflow because exponent is between 0 and 0x7fe, and exp is between + // -2*MAX_EXP and 2*MAX_EXP. + let new_exp = curr_exp + exp; + + if new_exp > MAX_UNSIGNED_EXPONENT { + INFINITY * x.signum() + } else if new_exp > 0 { + // Normal case: exponent is not too large nor subnormal. + let new_bits = (bits & !EXPONENT_MASK) | ((new_exp as u64) << 52); + f64::from_bits(new_bits) + } else if new_exp >= -(MANTISSA_DIGITS as i32) { + // Result is subnormal but may not be zero. + // In this case, we increase the exponent by 54 to make it normal, then multiply the end + // result by 2^-53. This results in a single multiplication with no prior rounding error, + // so there is no risk of double rounding. + let new_exp = new_exp + MIN_SUBNORMAL_POWER; + debug_assert!(new_exp >= 0); + let new_bits = (bits & !EXPONENT_MASK) | ((new_exp as u64) << 52); + f64::from_bits(new_bits) * 2f64.powi(-MIN_SUBNORMAL_POWER) + } else { + // Result is zero. + return 0.0 * x.signum(); + } +} + +#[cfg(test)] +#[cfg(feature = "std")] +fn hash(x: &T) -> u64 { + use std::collections::hash_map::RandomState; + use std::hash::BuildHasher; + let mut hasher = ::Hasher::new(); + x.hash(&mut hasher); + hasher.finish() +} + +#[cfg(test)] +mod test { + use super::ldexp; + #[cfg(feature = "num-bigint")] + use super::{BigInt, BigRational}; + use super::{Ratio, Rational64}; + + use core::f64; + use core::i32; + use core::i64; + use core::str::FromStr; + use num_integer::Integer; + use num_traits::ToPrimitive; + use num_traits::{FromPrimitive, One, Pow, Signed, Zero}; + + pub const _0: Rational64 = Ratio { numer: 0, denom: 1 }; + pub const _1: Rational64 = Ratio { numer: 1, denom: 1 }; + pub const _2: Rational64 = Ratio { numer: 2, denom: 1 }; + pub const _NEG2: Rational64 = Ratio { + numer: -2, + denom: 1, + }; + pub const _8: Rational64 = Ratio { numer: 8, denom: 1 }; + pub const _15: Rational64 = Ratio { + numer: 15, + denom: 1, + }; + pub const _16: Rational64 = Ratio { + numer: 16, + denom: 1, + }; + + pub const _1_2: Rational64 = Ratio { numer: 1, denom: 2 }; + pub const _1_8: Rational64 = Ratio { numer: 1, denom: 8 }; + pub const _1_15: Rational64 = Ratio { + numer: 1, + denom: 15, + }; + pub const _1_16: Rational64 = Ratio { + numer: 1, + denom: 16, + }; + pub const _3_2: Rational64 = Ratio { numer: 3, denom: 2 }; + pub const _5_2: Rational64 = Ratio { numer: 5, denom: 2 }; + pub const _NEG1_2: Rational64 = Ratio { + numer: -1, + denom: 2, + }; + pub const _1_NEG2: Rational64 = Ratio { + numer: 1, + denom: -2, + }; + pub const _NEG1_NEG2: Rational64 = Ratio { + numer: -1, + denom: -2, + }; + pub const _1_3: Rational64 = Ratio { numer: 1, denom: 3 }; + pub const _NEG1_3: Rational64 = Ratio { + numer: -1, + denom: 3, + }; + pub const _2_3: Rational64 = Ratio { numer: 2, denom: 3 }; + pub const _NEG2_3: Rational64 = Ratio { + numer: -2, + denom: 3, + }; + pub const _MIN: Rational64 = Ratio { + numer: i64::MIN, + denom: 1, + }; + pub const _MIN_P1: Rational64 = Ratio { + numer: i64::MIN + 1, + denom: 1, + }; + pub const _MAX: Rational64 = Ratio { + numer: i64::MAX, + denom: 1, + }; + pub const _MAX_M1: Rational64 = Ratio { + numer: i64::MAX - 1, + denom: 1, + }; + pub const _BILLION: Rational64 = Ratio { + numer: 1_000_000_000, + denom: 1, + }; + + #[cfg(feature = "num-bigint")] + pub fn to_big(n: Rational64) -> BigRational { + Ratio::new( + FromPrimitive::from_i64(n.numer).unwrap(), + FromPrimitive::from_i64(n.denom).unwrap(), + ) + } + #[cfg(not(feature = "num-bigint"))] + pub fn to_big(n: Rational64) -> Rational64 { + Ratio::new( + FromPrimitive::from_i64(n.numer).unwrap(), + FromPrimitive::from_i64(n.denom).unwrap(), + ) + } + + #[test] + fn test_test_constants() { + // check our constants are what Ratio::new etc. would make. + assert_eq!(_0, Zero::zero()); + assert_eq!(_1, One::one()); + assert_eq!(_2, Ratio::from_integer(2)); + assert_eq!(_1_2, Ratio::new(1, 2)); + assert_eq!(_3_2, Ratio::new(3, 2)); + assert_eq!(_NEG1_2, Ratio::new(-1, 2)); + assert_eq!(_2, From::from(2)); + } + + #[test] + fn test_new_reduce() { + assert_eq!(Ratio::new(2, 2), One::one()); + assert_eq!(Ratio::new(0, i32::MIN), Zero::zero()); + assert_eq!(Ratio::new(i32::MIN, i32::MIN), One::one()); + } + #[test] + #[should_panic] + fn test_new_zero() { + let _a = Ratio::new(1, 0); + } + + #[test] + fn test_approximate_float() { + assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2))); + assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2))); + assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1))); + assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1))); + assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100))); + assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100))); + + assert_eq!(Ratio::::from_f32(63.5f32), Some(Ratio::new(127i8, 2))); + assert_eq!(Ratio::::from_f32(126.5f32), Some(Ratio::new(126i8, 1))); + assert_eq!(Ratio::::from_f32(127.0f32), Some(Ratio::new(127i8, 1))); + assert_eq!(Ratio::::from_f32(127.5f32), None); + assert_eq!(Ratio::::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2))); + assert_eq!( + Ratio::::from_f32(-126.5f32), + Some(Ratio::new(-126i8, 1)) + ); + assert_eq!( + Ratio::::from_f32(-127.0f32), + Some(Ratio::new(-127i8, 1)) + ); + assert_eq!(Ratio::::from_f32(-127.5f32), None); + + assert_eq!(Ratio::::from_f32(-127f32), None); + assert_eq!(Ratio::::from_f32(127f32), Some(Ratio::new(127u8, 1))); + assert_eq!(Ratio::::from_f32(127.5f32), Some(Ratio::new(255u8, 2))); + assert_eq!(Ratio::::from_f32(256f32), None); + + assert_eq!(Ratio::::from_f64(-10e200), None); + assert_eq!(Ratio::::from_f64(10e200), None); + assert_eq!(Ratio::::from_f64(f64::INFINITY), None); + assert_eq!(Ratio::::from_f64(f64::NEG_INFINITY), None); + assert_eq!(Ratio::::from_f64(f64::NAN), None); + assert_eq!( + Ratio::::from_f64(f64::EPSILON), + Some(Ratio::new(1, 4503599627370496)) + ); + assert_eq!(Ratio::::from_f64(0.0), Some(Ratio::new(0, 1))); + assert_eq!(Ratio::::from_f64(-0.0), Some(Ratio::new(0, 1))); + } + + #[test] + #[allow(clippy::eq_op)] + fn test_cmp() { + assert!(_0 == _0 && _1 == _1); + assert!(_0 != _1 && _1 != _0); + assert!(_0 < _1 && !(_1 < _0)); + assert!(_1 > _0 && !(_0 > _1)); + + assert!(_0 <= _0 && _1 <= _1); + assert!(_0 <= _1 && !(_1 <= _0)); + + assert!(_0 >= _0 && _1 >= _1); + assert!(_1 >= _0 && !(_0 >= _1)); + + let _0_2: Rational64 = Ratio::new_raw(0, 2); + assert_eq!(_0, _0_2); + } + + #[test] + fn test_cmp_overflow() { + use core::cmp::Ordering; + + // issue #7 example: + let big = Ratio::new(128u8, 1); + let small = big.recip(); + assert!(big > small); + + // try a few that are closer together + // (some matching numer, some matching denom, some neither) + let ratios = [ + Ratio::new(125_i8, 127_i8), + Ratio::new(63_i8, 64_i8), + Ratio::new(124_i8, 125_i8), + Ratio::new(125_i8, 126_i8), + Ratio::new(126_i8, 127_i8), + Ratio::new(127_i8, 126_i8), + ]; + + fn check_cmp(a: Ratio, b: Ratio, ord: Ordering) { + #[cfg(feature = "std")] + println!("comparing {} and {}", a, b); + assert_eq!(a.cmp(&b), ord); + assert_eq!(b.cmp(&a), ord.reverse()); + } + + for (i, &a) in ratios.iter().enumerate() { + check_cmp(a, a, Ordering::Equal); + check_cmp(-a, a, Ordering::Less); + for &b in &ratios[i + 1..] { + check_cmp(a, b, Ordering::Less); + check_cmp(-a, -b, Ordering::Greater); + check_cmp(a.recip(), b.recip(), Ordering::Greater); + check_cmp(-a.recip(), -b.recip(), Ordering::Less); + } + } + } + + #[test] + fn test_to_integer() { + assert_eq!(_0.to_integer(), 0); + assert_eq!(_1.to_integer(), 1); + assert_eq!(_2.to_integer(), 2); + assert_eq!(_1_2.to_integer(), 0); + assert_eq!(_3_2.to_integer(), 1); + assert_eq!(_NEG1_2.to_integer(), 0); + } + + #[test] + fn test_numer() { + assert_eq!(_0.numer(), &0); + assert_eq!(_1.numer(), &1); + assert_eq!(_2.numer(), &2); + assert_eq!(_1_2.numer(), &1); + assert_eq!(_3_2.numer(), &3); + assert_eq!(_NEG1_2.numer(), &(-1)); + } + #[test] + fn test_denom() { + assert_eq!(_0.denom(), &1); + assert_eq!(_1.denom(), &1); + assert_eq!(_2.denom(), &1); + assert_eq!(_1_2.denom(), &2); + assert_eq!(_3_2.denom(), &2); + assert_eq!(_NEG1_2.denom(), &2); + } + + #[test] + fn test_is_integer() { + assert!(_0.is_integer()); + assert!(_1.is_integer()); + assert!(_2.is_integer()); + assert!(!_1_2.is_integer()); + assert!(!_3_2.is_integer()); + assert!(!_NEG1_2.is_integer()); + } + + #[cfg(not(feature = "std"))] + use core::fmt::{self, Write}; + #[cfg(not(feature = "std"))] + #[derive(Debug)] + struct NoStdTester { + cursor: usize, + buf: [u8; NoStdTester::BUF_SIZE], + } + + #[cfg(not(feature = "std"))] + impl NoStdTester { + fn new() -> NoStdTester { + NoStdTester { + buf: [0; Self::BUF_SIZE], + cursor: 0, + } + } + + fn clear(&mut self) { + self.buf = [0; Self::BUF_SIZE]; + self.cursor = 0; + } + + const WRITE_ERR: &'static str = "Formatted output too long"; + const BUF_SIZE: usize = 32; + } + + #[cfg(not(feature = "std"))] + impl Write for NoStdTester { + fn write_str(&mut self, s: &str) -> fmt::Result { + for byte in s.bytes() { + self.buf[self.cursor] = byte; + self.cursor += 1; + if self.cursor >= self.buf.len() { + return Err(fmt::Error {}); + } + } + Ok(()) + } + } + + #[cfg(not(feature = "std"))] + impl PartialEq for NoStdTester { + fn eq(&self, other: &str) -> bool { + let other = other.as_bytes(); + for index in 0..self.cursor { + if self.buf.get(index) != other.get(index) { + return false; + } + } + true + } + } + + macro_rules! assert_fmt_eq { + ($fmt_args:expr, $string:expr) => { + #[cfg(not(feature = "std"))] + { + let mut tester = NoStdTester::new(); + write!(tester, "{}", $fmt_args).expect(NoStdTester::WRITE_ERR); + assert_eq!(tester, *$string); + tester.clear(); + } + #[cfg(feature = "std")] + { + assert_eq!(std::fmt::format($fmt_args), $string); + } + }; + } + + #[test] + fn test_show() { + // Test: + // :b :o :x, :X, :? + // alternate or not (#) + // positive and negative + // padding + // does not test precision (i.e. truncation) + assert_fmt_eq!(format_args!("{}", _2), "2"); + assert_fmt_eq!(format_args!("{:+}", _2), "+2"); + assert_fmt_eq!(format_args!("{:-}", _2), "2"); + assert_fmt_eq!(format_args!("{}", _1_2), "1/2"); + assert_fmt_eq!(format_args!("{}", -_1_2), "-1/2"); // test negatives + assert_fmt_eq!(format_args!("{}", _0), "0"); + assert_fmt_eq!(format_args!("{}", -_2), "-2"); + assert_fmt_eq!(format_args!("{:+}", -_2), "-2"); + assert_fmt_eq!(format_args!("{:b}", _2), "10"); + assert_fmt_eq!(format_args!("{:#b}", _2), "0b10"); + assert_fmt_eq!(format_args!("{:b}", _1_2), "1/10"); + assert_fmt_eq!(format_args!("{:+b}", _1_2), "+1/10"); + assert_fmt_eq!(format_args!("{:-b}", _1_2), "1/10"); + assert_fmt_eq!(format_args!("{:b}", _0), "0"); + assert_fmt_eq!(format_args!("{:#b}", _1_2), "0b1/0b10"); + // no std does not support padding + #[cfg(feature = "std")] + assert_eq!(&format!("{:010b}", _1_2), "0000001/10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:#010b}", _1_2), "0b001/0b10"); + let half_i8: Ratio = Ratio::new(1_i8, 2_i8); + assert_fmt_eq!(format_args!("{:b}", -half_i8), "11111111/10"); + assert_fmt_eq!(format_args!("{:#b}", -half_i8), "0b11111111/0b10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:05}", Ratio::new(-1_i8, 1_i8)), "-0001"); + + assert_fmt_eq!(format_args!("{:o}", _8), "10"); + assert_fmt_eq!(format_args!("{:o}", _1_8), "1/10"); + assert_fmt_eq!(format_args!("{:o}", _0), "0"); + assert_fmt_eq!(format_args!("{:#o}", _1_8), "0o1/0o10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:010o}", _1_8), "0000001/10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:#010o}", _1_8), "0o001/0o10"); + assert_fmt_eq!(format_args!("{:o}", -half_i8), "377/2"); + assert_fmt_eq!(format_args!("{:#o}", -half_i8), "0o377/0o2"); + + assert_fmt_eq!(format_args!("{:x}", _16), "10"); + assert_fmt_eq!(format_args!("{:x}", _15), "f"); + assert_fmt_eq!(format_args!("{:x}", _1_16), "1/10"); + assert_fmt_eq!(format_args!("{:x}", _1_15), "1/f"); + assert_fmt_eq!(format_args!("{:x}", _0), "0"); + assert_fmt_eq!(format_args!("{:#x}", _1_16), "0x1/0x10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:010x}", _1_16), "0000001/10"); + #[cfg(feature = "std")] + assert_eq!(&format!("{:#010x}", _1_16), "0x001/0x10"); + assert_fmt_eq!(format_args!("{:x}", -half_i8), "ff/2"); + assert_fmt_eq!(format_args!("{:#x}", -half_i8), "0xff/0x2"); + + assert_fmt_eq!(format_args!("{:X}", _16), "10"); + assert_fmt_eq!(format_args!("{:X}", _15), "F"); + assert_fmt_eq!(format_args!("{:X}", _1_16), "1/10"); + assert_fmt_eq!(format_args!("{:X}", _1_15), "1/F"); + assert_fmt_eq!(format_args!("{:X}", _0), "0"); + assert_fmt_eq!(format_args!("{:#X}", _1_16), "0x1/0x10"); + #[cfg(feature = "std")] + assert_eq!(format!("{:010X}", _1_16), "0000001/10"); + #[cfg(feature = "std")] + assert_eq!(format!("{:#010X}", _1_16), "0x001/0x10"); + assert_fmt_eq!(format_args!("{:X}", -half_i8), "FF/2"); + assert_fmt_eq!(format_args!("{:#X}", -half_i8), "0xFF/0x2"); + + assert_fmt_eq!(format_args!("{:e}", -_2), "-2e0"); + assert_fmt_eq!(format_args!("{:#e}", -_2), "-2e0"); + assert_fmt_eq!(format_args!("{:+e}", -_2), "-2e0"); + assert_fmt_eq!(format_args!("{:e}", _BILLION), "1e9"); + assert_fmt_eq!(format_args!("{:+e}", _BILLION), "+1e9"); + assert_fmt_eq!(format_args!("{:e}", _BILLION.recip()), "1e0/1e9"); + assert_fmt_eq!(format_args!("{:+e}", _BILLION.recip()), "+1e0/1e9"); + + assert_fmt_eq!(format_args!("{:E}", -_2), "-2E0"); + assert_fmt_eq!(format_args!("{:#E}", -_2), "-2E0"); + assert_fmt_eq!(format_args!("{:+E}", -_2), "-2E0"); + assert_fmt_eq!(format_args!("{:E}", _BILLION), "1E9"); + assert_fmt_eq!(format_args!("{:+E}", _BILLION), "+1E9"); + assert_fmt_eq!(format_args!("{:E}", _BILLION.recip()), "1E0/1E9"); + assert_fmt_eq!(format_args!("{:+E}", _BILLION.recip()), "+1E0/1E9"); + } + + mod arith { + use super::super::{Ratio, Rational64}; + use super::{to_big, _0, _1, _1_2, _2, _3_2, _5_2, _MAX, _MAX_M1, _MIN, _MIN_P1, _NEG1_2}; + use core::fmt::Debug; + use num_integer::Integer; + use num_traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, NumAssign}; + + #[test] + fn test_add() { + fn test(a: Rational64, b: Rational64, c: Rational64) { + assert_eq!(a + b, c); + assert_eq!( + { + let mut x = a; + x += b; + x + }, + c + ); + assert_eq!(to_big(a) + to_big(b), to_big(c)); + assert_eq!(a.checked_add(&b), Some(c)); + assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c))); + } + fn test_assign(a: Rational64, b: i64, c: Rational64) { + assert_eq!(a + b, c); + assert_eq!( + { + let mut x = a; + x += b; + x + }, + c + ); + } + + test(_1, _1_2, _3_2); + test(_1, _1, _2); + test(_1_2, _3_2, _2); + test(_1_2, _NEG1_2, _0); + test_assign(_1_2, 1, _3_2); + } + + #[test] + fn test_add_overflow() { + // compares Ratio(1, T::max_value()) + Ratio(1, T::max_value()) + // to Ratio(1+1, T::max_value()) for each integer type. + // Previously, this calculation would overflow. + fn test_add_typed_overflow() + where + T: Integer + Bounded + Clone + Debug + NumAssign, + { + let _1_max = Ratio::new(T::one(), T::max_value()); + let _2_max = Ratio::new(T::one() + T::one(), T::max_value()); + assert_eq!(_1_max.clone() + _1_max.clone(), _2_max); + assert_eq!( + { + let mut tmp = _1_max.clone(); + tmp += _1_max; + tmp + }, + _2_max + ); + } + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + test_add_typed_overflow::(); + } + + #[test] + fn test_sub() { + fn test(a: Rational64, b: Rational64, c: Rational64) { + assert_eq!(a - b, c); + assert_eq!( + { + let mut x = a; + x -= b; + x + }, + c + ); + assert_eq!(to_big(a) - to_big(b), to_big(c)); + assert_eq!(a.checked_sub(&b), Some(c)); + assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c))); + } + fn test_assign(a: Rational64, b: i64, c: Rational64) { + assert_eq!(a - b, c); + assert_eq!( + { + let mut x = a; + x -= b; + x + }, + c + ); + } + + test(_1, _1_2, _1_2); + test(_3_2, _1_2, _1); + test(_1, _NEG1_2, _3_2); + test_assign(_1_2, 1, _NEG1_2); + } + + #[test] + fn test_sub_overflow() { + // compares Ratio(1, T::max_value()) - Ratio(1, T::max_value()) to T::zero() + // for each integer type. Previously, this calculation would overflow. + fn test_sub_typed_overflow() + where + T: Integer + Bounded + Clone + Debug + NumAssign, + { + let _1_max: Ratio = Ratio::new(T::one(), T::max_value()); + assert!(T::is_zero(&(_1_max.clone() - _1_max.clone()).numer)); + { + let mut tmp: Ratio = _1_max.clone(); + tmp -= _1_max; + assert!(T::is_zero(&tmp.numer)); + } + } + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + test_sub_typed_overflow::(); + } + + #[test] + fn test_mul() { + fn test(a: Rational64, b: Rational64, c: Rational64) { + assert_eq!(a * b, c); + assert_eq!( + { + let mut x = a; + x *= b; + x + }, + c + ); + assert_eq!(to_big(a) * to_big(b), to_big(c)); + assert_eq!(a.checked_mul(&b), Some(c)); + assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c))); + } + fn test_assign(a: Rational64, b: i64, c: Rational64) { + assert_eq!(a * b, c); + assert_eq!( + { + let mut x = a; + x *= b; + x + }, + c + ); + } + + test(_1, _1_2, _1_2); + test(_1_2, _3_2, Ratio::new(3, 4)); + test(_1_2, _NEG1_2, Ratio::new(-1, 4)); + test_assign(_1_2, 2, _1); + } + + #[test] + fn test_mul_overflow() { + fn test_mul_typed_overflow() + where + T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul, + { + let two = T::one() + T::one(); + let _3 = T::one() + T::one() + T::one(); + + // 1/big * 2/3 = 1/(max/4*3), where big is max/2 + // make big = max/2, but also divisible by 2 + let big = T::max_value() / two.clone() / two.clone() * two.clone(); + let _1_big: Ratio = Ratio::new(T::one(), big.clone()); + let _2_3: Ratio = Ratio::new(two.clone(), _3.clone()); + assert_eq!(None, big.clone().checked_mul(&_3.clone())); + let expected = Ratio::new(T::one(), big / two.clone() * _3.clone()); + assert_eq!(expected.clone(), _1_big.clone() * _2_3.clone()); + assert_eq!( + Some(expected.clone()), + _1_big.clone().checked_mul(&_2_3.clone()) + ); + assert_eq!(expected, { + let mut tmp = _1_big; + tmp *= _2_3; + tmp + }); + + // big/3 * 3 = big/1 + // make big = max/2, but make it indivisible by 3 + let big = T::max_value() / two / _3.clone() * _3.clone() + T::one(); + assert_eq!(None, big.clone().checked_mul(&_3.clone())); + let big_3 = Ratio::new(big.clone(), _3.clone()); + let expected = Ratio::new(big, T::one()); + assert_eq!(expected, big_3.clone() * _3.clone()); + assert_eq!(expected, { + let mut tmp = big_3; + tmp *= _3; + tmp + }); + } + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + test_mul_typed_overflow::(); + } + + #[test] + fn test_div() { + fn test(a: Rational64, b: Rational64, c: Rational64) { + assert_eq!(a / b, c); + assert_eq!( + { + let mut x = a; + x /= b; + x + }, + c + ); + assert_eq!(to_big(a) / to_big(b), to_big(c)); + assert_eq!(a.checked_div(&b), Some(c)); + assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c))); + } + fn test_assign(a: Rational64, b: i64, c: Rational64) { + assert_eq!(a / b, c); + assert_eq!( + { + let mut x = a; + x /= b; + x + }, + c + ); + } + + test(_1, _1_2, _2); + test(_3_2, _1_2, _1 + _2); + test(_1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2); + test_assign(_1, 2, _1_2); + } + + #[test] + fn test_div_overflow() { + fn test_div_typed_overflow() + where + T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul, + { + let two = T::one() + T::one(); + let _3 = T::one() + T::one() + T::one(); + + // 1/big / 3/2 = 1/(max/4*3), where big is max/2 + // big ~ max/2, and big is divisible by 2 + let big = T::max_value() / two.clone() / two.clone() * two.clone(); + assert_eq!(None, big.clone().checked_mul(&_3.clone())); + let _1_big: Ratio = Ratio::new(T::one(), big.clone()); + let _3_two: Ratio = Ratio::new(_3.clone(), two.clone()); + let expected = Ratio::new(T::one(), big / two.clone() * _3.clone()); + assert_eq!(expected.clone(), _1_big.clone() / _3_two.clone()); + assert_eq!( + Some(expected.clone()), + _1_big.clone().checked_div(&_3_two.clone()) + ); + assert_eq!(expected, { + let mut tmp = _1_big; + tmp /= _3_two; + tmp + }); + + // 3/big / 3 = 1/big where big is max/2 + // big ~ max/2, and big is not divisible by 3 + let big = T::max_value() / two / _3.clone() * _3.clone() + T::one(); + assert_eq!(None, big.clone().checked_mul(&_3.clone())); + let _3_big = Ratio::new(_3.clone(), big.clone()); + let expected = Ratio::new(T::one(), big); + assert_eq!(expected, _3_big.clone() / _3.clone()); + assert_eq!(expected, { + let mut tmp = _3_big; + tmp /= _3; + tmp + }); + } + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + test_div_typed_overflow::(); + } + + #[test] + fn test_rem() { + fn test(a: Rational64, b: Rational64, c: Rational64) { + assert_eq!(a % b, c); + assert_eq!( + { + let mut x = a; + x %= b; + x + }, + c + ); + assert_eq!(to_big(a) % to_big(b), to_big(c)) + } + fn test_assign(a: Rational64, b: i64, c: Rational64) { + assert_eq!(a % b, c); + assert_eq!( + { + let mut x = a; + x %= b; + x + }, + c + ); + } + + test(_3_2, _1, _1_2); + test(_3_2, _1_2, _0); + test(_5_2, _3_2, _1); + test(_2, _NEG1_2, _0); + test(_1_2, _2, _1_2); + test_assign(_3_2, 1, _1_2); + } + + #[test] + fn test_rem_overflow() { + // tests that Ratio(1,2) % Ratio(1, T::max_value()) equals 0 + // for each integer type. Previously, this calculation would overflow. + fn test_rem_typed_overflow() + where + T: Integer + Bounded + Clone + Debug + NumAssign, + { + let two = T::one() + T::one(); + // value near to maximum, but divisible by two + let max_div2 = T::max_value() / two.clone() * two.clone(); + let _1_max: Ratio = Ratio::new(T::one(), max_div2); + let _1_two: Ratio = Ratio::new(T::one(), two); + assert!(T::is_zero(&(_1_two.clone() % _1_max.clone()).numer)); + { + let mut tmp: Ratio = _1_two; + tmp %= _1_max; + assert!(T::is_zero(&tmp.numer)); + } + } + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + test_rem_typed_overflow::(); + } + + #[test] + fn test_neg() { + fn test(a: Rational64, b: Rational64) { + assert_eq!(-a, b); + assert_eq!(-to_big(a), to_big(b)) + } + + test(_0, _0); + test(_1_2, _NEG1_2); + test(-_1, _1); + } + #[test] + #[allow(clippy::eq_op)] + fn test_zero() { + assert_eq!(_0 + _0, _0); + assert_eq!(_0 * _0, _0); + assert_eq!(_0 * _1, _0); + assert_eq!(_0 / _NEG1_2, _0); + assert_eq!(_0 - _0, _0); + } + #[test] + #[should_panic] + fn test_div_0() { + let _a = _1 / _0; + } + + #[test] + fn test_checked_failures() { + let big = Ratio::new(128u8, 1); + let small = Ratio::new(1, 128u8); + assert_eq!(big.checked_add(&big), None); + assert_eq!(small.checked_sub(&big), None); + assert_eq!(big.checked_mul(&big), None); + assert_eq!(small.checked_div(&big), None); + assert_eq!(_1.checked_div(&_0), None); + } + + #[test] + fn test_checked_zeros() { + assert_eq!(_0.checked_add(&_0), Some(_0)); + assert_eq!(_0.checked_sub(&_0), Some(_0)); + assert_eq!(_0.checked_mul(&_0), Some(_0)); + assert_eq!(_0.checked_div(&_0), None); + } + + #[test] + fn test_checked_min() { + assert_eq!(_MIN.checked_add(&_MIN), None); + assert_eq!(_MIN.checked_sub(&_MIN), Some(_0)); + assert_eq!(_MIN.checked_mul(&_MIN), None); + assert_eq!(_MIN.checked_div(&_MIN), Some(_1)); + assert_eq!(_0.checked_add(&_MIN), Some(_MIN)); + assert_eq!(_0.checked_sub(&_MIN), None); + assert_eq!(_0.checked_mul(&_MIN), Some(_0)); + assert_eq!(_0.checked_div(&_MIN), Some(_0)); + assert_eq!(_1.checked_add(&_MIN), Some(_MIN_P1)); + assert_eq!(_1.checked_sub(&_MIN), None); + assert_eq!(_1.checked_mul(&_MIN), Some(_MIN)); + assert_eq!(_1.checked_div(&_MIN), None); + assert_eq!(_MIN.checked_add(&_0), Some(_MIN)); + assert_eq!(_MIN.checked_sub(&_0), Some(_MIN)); + assert_eq!(_MIN.checked_mul(&_0), Some(_0)); + assert_eq!(_MIN.checked_div(&_0), None); + assert_eq!(_MIN.checked_add(&_1), Some(_MIN_P1)); + assert_eq!(_MIN.checked_sub(&_1), None); + assert_eq!(_MIN.checked_mul(&_1), Some(_MIN)); + assert_eq!(_MIN.checked_div(&_1), Some(_MIN)); + } + + #[test] + fn test_checked_max() { + assert_eq!(_MAX.checked_add(&_MAX), None); + assert_eq!(_MAX.checked_sub(&_MAX), Some(_0)); + assert_eq!(_MAX.checked_mul(&_MAX), None); + assert_eq!(_MAX.checked_div(&_MAX), Some(_1)); + assert_eq!(_0.checked_add(&_MAX), Some(_MAX)); + assert_eq!(_0.checked_sub(&_MAX), Some(_MIN_P1)); + assert_eq!(_0.checked_mul(&_MAX), Some(_0)); + assert_eq!(_0.checked_div(&_MAX), Some(_0)); + assert_eq!(_1.checked_add(&_MAX), None); + assert_eq!(_1.checked_sub(&_MAX), Some(-_MAX_M1)); + assert_eq!(_1.checked_mul(&_MAX), Some(_MAX)); + assert_eq!(_1.checked_div(&_MAX), Some(_MAX.recip())); + assert_eq!(_MAX.checked_add(&_0), Some(_MAX)); + assert_eq!(_MAX.checked_sub(&_0), Some(_MAX)); + assert_eq!(_MAX.checked_mul(&_0), Some(_0)); + assert_eq!(_MAX.checked_div(&_0), None); + assert_eq!(_MAX.checked_add(&_1), None); + assert_eq!(_MAX.checked_sub(&_1), Some(_MAX_M1)); + assert_eq!(_MAX.checked_mul(&_1), Some(_MAX)); + assert_eq!(_MAX.checked_div(&_1), Some(_MAX)); + } + + #[test] + fn test_checked_min_max() { + assert_eq!(_MIN.checked_add(&_MAX), Some(-_1)); + assert_eq!(_MIN.checked_sub(&_MAX), None); + assert_eq!(_MIN.checked_mul(&_MAX), None); + assert_eq!( + _MIN.checked_div(&_MAX), + Some(Ratio::new(_MIN.numer, _MAX.numer)) + ); + assert_eq!(_MAX.checked_add(&_MIN), Some(-_1)); + assert_eq!(_MAX.checked_sub(&_MIN), None); + assert_eq!(_MAX.checked_mul(&_MIN), None); + assert_eq!(_MAX.checked_div(&_MIN), None); + } + } + + #[test] + fn test_round() { + assert_eq!(_1_3.ceil(), _1); + assert_eq!(_1_3.floor(), _0); + assert_eq!(_1_3.round(), _0); + assert_eq!(_1_3.trunc(), _0); + + assert_eq!(_NEG1_3.ceil(), _0); + assert_eq!(_NEG1_3.floor(), -_1); + assert_eq!(_NEG1_3.round(), _0); + assert_eq!(_NEG1_3.trunc(), _0); + + assert_eq!(_2_3.ceil(), _1); + assert_eq!(_2_3.floor(), _0); + assert_eq!(_2_3.round(), _1); + assert_eq!(_2_3.trunc(), _0); + + assert_eq!(_NEG2_3.ceil(), _0); + assert_eq!(_NEG2_3.floor(), -_1); + assert_eq!(_NEG2_3.round(), -_1); + assert_eq!(_NEG2_3.trunc(), _0); + + assert_eq!(_1_2.ceil(), _1); + assert_eq!(_1_2.floor(), _0); + assert_eq!(_1_2.round(), _1); + assert_eq!(_1_2.trunc(), _0); + + assert_eq!(_NEG1_2.ceil(), _0); + assert_eq!(_NEG1_2.floor(), -_1); + assert_eq!(_NEG1_2.round(), -_1); + assert_eq!(_NEG1_2.trunc(), _0); + + assert_eq!(_1.ceil(), _1); + assert_eq!(_1.floor(), _1); + assert_eq!(_1.round(), _1); + assert_eq!(_1.trunc(), _1); + + // Overflow checks + + let _neg1 = Ratio::from_integer(-1); + let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1); + let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX); + let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1); + let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2); + let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX); + let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2); + let _large_rat7 = Ratio::new(1, i32::MIN + 1); + let _large_rat8 = Ratio::new(1, i32::MAX); + + assert_eq!(_large_rat1.round(), One::one()); + assert_eq!(_large_rat2.round(), One::one()); + assert_eq!(_large_rat3.round(), One::one()); + assert_eq!(_large_rat4.round(), One::one()); + assert_eq!(_large_rat5.round(), _neg1); + assert_eq!(_large_rat6.round(), _neg1); + assert_eq!(_large_rat7.round(), Zero::zero()); + assert_eq!(_large_rat8.round(), Zero::zero()); + } + + #[test] + fn test_fract() { + assert_eq!(_1.fract(), _0); + assert_eq!(_NEG1_2.fract(), _NEG1_2); + assert_eq!(_1_2.fract(), _1_2); + assert_eq!(_3_2.fract(), _1_2); + } + + #[test] + fn test_recip() { + assert_eq!(_1 * _1.recip(), _1); + assert_eq!(_2 * _2.recip(), _1); + assert_eq!(_1_2 * _1_2.recip(), _1); + assert_eq!(_3_2 * _3_2.recip(), _1); + assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1); + + assert_eq!(_3_2.recip(), _2_3); + assert_eq!(_NEG1_2.recip(), _NEG2); + assert_eq!(_NEG1_2.recip().denom(), &1); + } + + #[test] + #[should_panic(expected = "division by zero")] + fn test_recip_fail() { + let _a = Ratio::new(0, 1).recip(); + } + + #[test] + fn test_pow() { + fn test(r: Rational64, e: i32, expected: Rational64) { + assert_eq!(r.pow(e), expected); + assert_eq!(Pow::pow(r, e), expected); + assert_eq!(Pow::pow(r, &e), expected); + assert_eq!(Pow::pow(&r, e), expected); + assert_eq!(Pow::pow(&r, &e), expected); + #[cfg(feature = "num-bigint")] + test_big(r, e, expected); + } + + #[cfg(feature = "num-bigint")] + fn test_big(r: Rational64, e: i32, expected: Rational64) { + let r = BigRational::new_raw(r.numer.into(), r.denom.into()); + let expected = BigRational::new_raw(expected.numer.into(), expected.denom.into()); + assert_eq!((&r).pow(e), expected); + assert_eq!(Pow::pow(r.clone(), e), expected); + assert_eq!(Pow::pow(r.clone(), &e), expected); + assert_eq!(Pow::pow(&r, e), expected); + assert_eq!(Pow::pow(&r, &e), expected); + } + + test(_1_2, 2, Ratio::new(1, 4)); + test(_1_2, -2, Ratio::new(4, 1)); + test(_1, 1, _1); + test(_1, i32::MAX, _1); + test(_1, i32::MIN, _1); + test(_NEG1_2, 2, _1_2.pow(2i32)); + test(_NEG1_2, 3, -_1_2.pow(3i32)); + test(_3_2, 0, _1); + test(_3_2, -1, _3_2.recip()); + test(_3_2, 3, Ratio::new(27, 8)); + } + + #[test] + #[cfg(feature = "std")] + fn test_to_from_str() { + use std::string::{String, ToString}; + fn test(r: Rational64, s: String) { + assert_eq!(FromStr::from_str(&s), Ok(r)); + assert_eq!(r.to_string(), s); + } + test(_1, "1".to_string()); + test(_0, "0".to_string()); + test(_1_2, "1/2".to_string()); + test(_3_2, "3/2".to_string()); + test(_2, "2".to_string()); + test(_NEG1_2, "-1/2".to_string()); + } + #[test] + fn test_from_str_fail() { + fn test(s: &str) { + let rational: Result = FromStr::from_str(s); + assert!(rational.is_err()); + } + + let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"]; + for &s in xs.iter() { + test(s); + } + } + + #[cfg(feature = "num-bigint")] + #[test] + fn test_from_float() { + use num_traits::float::FloatCore; + fn test(given: T, (numer, denom): (&str, &str)) { + let ratio: BigRational = Ratio::from_float(given).unwrap(); + assert_eq!( + ratio, + Ratio::new( + FromStr::from_str(numer).unwrap(), + FromStr::from_str(denom).unwrap() + ) + ); + } + + // f32 + test(core::f32::consts::PI, ("13176795", "4194304")); + test(2f32.powf(100.), ("1267650600228229401496703205376", "1")); + test( + -(2f32.powf(100.)), + ("-1267650600228229401496703205376", "1"), + ); + test( + 1.0 / 2f32.powf(100.), + ("1", "1267650600228229401496703205376"), + ); + test(684729.48391f32, ("1369459", "2")); + test(-8573.5918555f32, ("-4389679", "512")); + + // f64 + test( + core::f64::consts::PI, + ("884279719003555", "281474976710656"), + ); + test(2f64.powf(100.), ("1267650600228229401496703205376", "1")); + test( + -(2f64.powf(100.)), + ("-1267650600228229401496703205376", "1"), + ); + test(684729.48391f64, ("367611342500051", "536870912")); + test(-8573.5918555f64, ("-4713381968463931", "549755813888")); + test( + 1.0 / 2f64.powf(100.), + ("1", "1267650600228229401496703205376"), + ); + } + + #[cfg(feature = "num-bigint")] + #[test] + fn test_from_float_fail() { + use core::{f32, f64}; + + assert_eq!(Ratio::from_float(f32::NAN), None); + assert_eq!(Ratio::from_float(f32::INFINITY), None); + assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None); + assert_eq!(Ratio::from_float(f64::NAN), None); + assert_eq!(Ratio::from_float(f64::INFINITY), None); + assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None); + } + + #[test] + fn test_signed() { + assert_eq!(_NEG1_2.abs(), _1_2); + assert_eq!(_3_2.abs_sub(&_1_2), _1); + assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero()); + assert_eq!(_1_2.signum(), One::one()); + assert_eq!(_NEG1_2.signum(), ->::one()); + assert_eq!(_0.signum(), Zero::zero()); + assert!(_NEG1_2.is_negative()); + assert!(_1_NEG2.is_negative()); + assert!(!_NEG1_2.is_positive()); + assert!(!_1_NEG2.is_positive()); + assert!(_1_2.is_positive()); + assert!(_NEG1_NEG2.is_positive()); + assert!(!_1_2.is_negative()); + assert!(!_NEG1_NEG2.is_negative()); + assert!(!_0.is_positive()); + assert!(!_0.is_negative()); + } + + #[test] + #[cfg(feature = "std")] + fn test_hash() { + assert!(crate::hash(&_0) != crate::hash(&_1)); + assert!(crate::hash(&_0) != crate::hash(&_3_2)); + + // a == b -> hash(a) == hash(b) + let a = Rational64::new_raw(4, 2); + let b = Rational64::new_raw(6, 3); + assert_eq!(a, b); + assert_eq!(crate::hash(&a), crate::hash(&b)); + + let a = Rational64::new_raw(123456789, 1000); + let b = Rational64::new_raw(123456789 * 5, 5000); + assert_eq!(a, b); + assert_eq!(crate::hash(&a), crate::hash(&b)); + } + + #[test] + fn test_into_pair() { + assert_eq!((0, 1), _0.into()); + assert_eq!((-2, 1), _NEG2.into()); + assert_eq!((1, -2), _1_NEG2.into()); + } + + #[test] + fn test_from_pair() { + assert_eq!(_0, Ratio::from((0, 1))); + assert_eq!(_1, Ratio::from((1, 1))); + assert_eq!(_NEG2, Ratio::from((-2, 1))); + assert_eq!(_1_NEG2, Ratio::from((1, -2))); + } + + #[test] + fn ratio_iter_sum() { + // generic function to assure the iter method can be called + // for any Iterator with Item = Ratio or Ratio<&impl Integer> + fn iter_sums(slice: &[Ratio]) -> [Ratio; 3] { + let mut manual_sum = Ratio::new(T::zero(), T::one()); + for ratio in slice { + manual_sum = manual_sum + ratio; + } + [manual_sum, slice.iter().sum(), slice.iter().cloned().sum()] + } + // collect into array so test works on no_std + let mut nums = [Ratio::new(0, 1); 1000]; + for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { + nums[i] = r; + } + let sums = iter_sums(&nums[..]); + assert_eq!(sums[0], sums[1]); + assert_eq!(sums[0], sums[2]); + } + + #[test] + fn ratio_iter_product() { + // generic function to assure the iter method can be called + // for any Iterator with Item = Ratio or Ratio<&impl Integer> + fn iter_products(slice: &[Ratio]) -> [Ratio; 3] { + let mut manual_prod = Ratio::new(T::one(), T::one()); + for ratio in slice { + manual_prod = manual_prod * ratio; + } + [ + manual_prod, + slice.iter().product(), + slice.iter().cloned().product(), + ] + } + + // collect into array so test works on no_std + let mut nums = [Ratio::new(0, 1); 1000]; + for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { + nums[i] = r; + } + let products = iter_products(&nums[..]); + assert_eq!(products[0], products[1]); + assert_eq!(products[0], products[2]); + } + + #[test] + fn test_num_zero() { + let zero = Rational64::zero(); + assert!(zero.is_zero()); + + let mut r = Rational64::new(123, 456); + assert!(!r.is_zero()); + assert_eq!(r + zero, r); + + r.set_zero(); + assert!(r.is_zero()); + } + + #[test] + fn test_num_one() { + let one = Rational64::one(); + assert!(one.is_one()); + + let mut r = Rational64::new(123, 456); + assert!(!r.is_one()); + assert_eq!(r * one, r); + + r.set_one(); + assert!(r.is_one()); + } + + #[test] + fn test_const() { + const N: Ratio = Ratio::new_raw(123, 456); + const N_NUMER: &i32 = N.numer(); + const N_DENOM: &i32 = N.denom(); + + assert_eq!(N_NUMER, &123); + assert_eq!(N_DENOM, &456); + + let r = N.reduced(); + assert_eq!(r.numer(), &(123 / 3)); + assert_eq!(r.denom(), &(456 / 3)); + } + + #[test] + fn test_ratio_to_i64() { + assert_eq!(5, Rational64::new(70, 14).to_u64().unwrap()); + assert_eq!(-3, Rational64::new(-31, 8).to_i64().unwrap()); + assert_eq!(None, Rational64::new(-31, 8).to_u64()); + } + + #[test] + #[cfg(feature = "num-bigint")] + fn test_ratio_to_i128() { + assert_eq!( + 1i128 << 70, + Ratio::::new(1i128 << 77, 1i128 << 7) + .to_i128() + .unwrap() + ); + } + + #[test] + #[cfg(feature = "num-bigint")] + fn test_big_ratio_to_f64() { + assert_eq!( + BigRational::new( + "1234567890987654321234567890987654321234567890" + .parse() + .unwrap(), + "3".parse().unwrap() + ) + .to_f64(), + Some(411522630329218100000000000000000000000000000f64) + ); + assert_eq!(Ratio::from_float(5e-324).unwrap().to_f64(), Some(5e-324)); + assert_eq!( + // subnormal + BigRational::new(BigInt::one(), BigInt::one() << 1050).to_f64(), + Some(2.0f64.powi(-50).powi(21)) + ); + assert_eq!( + // definite underflow + BigRational::new(BigInt::one(), BigInt::one() << 1100).to_f64(), + Some(0.0) + ); + assert_eq!( + BigRational::from(BigInt::one() << 1050).to_f64(), + Some(core::f64::INFINITY) + ); + assert_eq!( + BigRational::from((-BigInt::one()) << 1050).to_f64(), + Some(core::f64::NEG_INFINITY) + ); + assert_eq!( + BigRational::new( + "1234567890987654321234567890".parse().unwrap(), + "987654321234567890987654321".parse().unwrap() + ) + .to_f64(), + Some(1.2499999893125f64) + ); + assert_eq!( + BigRational::new_raw(BigInt::one(), BigInt::zero()).to_f64(), + Some(core::f64::INFINITY) + ); + assert_eq!( + BigRational::new_raw(-BigInt::one(), BigInt::zero()).to_f64(), + Some(core::f64::NEG_INFINITY) + ); + assert_eq!( + BigRational::new_raw(BigInt::zero(), BigInt::zero()).to_f64(), + None + ); + } + + #[test] + fn test_ratio_to_f64() { + assert_eq!(Ratio::::new(1, 2).to_f64(), Some(0.5f64)); + assert_eq!(Rational64::new(1, 2).to_f64(), Some(0.5f64)); + assert_eq!(Rational64::new(1, -2).to_f64(), Some(-0.5f64)); + assert_eq!(Rational64::new(0, 2).to_f64(), Some(0.0f64)); + assert_eq!(Rational64::new(0, -2).to_f64(), Some(-0.0f64)); + assert_eq!(Rational64::new((1 << 57) + 1, 1 << 54).to_f64(), Some(8f64)); + assert_eq!( + Rational64::new((1 << 52) + 1, 1 << 52).to_f64(), + Some(1.0000000000000002f64), + ); + assert_eq!( + Rational64::new((1 << 60) + (1 << 8), 1 << 60).to_f64(), + Some(1.0000000000000002f64), + ); + assert_eq!( + Ratio::::new_raw(1, 0).to_f64(), + Some(core::f64::INFINITY) + ); + assert_eq!( + Ratio::::new_raw(-1, 0).to_f64(), + Some(core::f64::NEG_INFINITY) + ); + assert_eq!(Ratio::::new_raw(0, 0).to_f64(), None); + } + + #[test] + fn test_ldexp() { + use core::f64::{INFINITY, MAX_EXP, MIN_EXP, NAN, NEG_INFINITY}; + assert_eq!(ldexp(1.0, 0), 1.0); + assert_eq!(ldexp(1.0, 1), 2.0); + assert_eq!(ldexp(0.0, 1), 0.0); + assert_eq!(ldexp(-0.0, 1), -0.0); + + // Cases where ldexp is equivalent to multiplying by 2^exp because there's no over- or + // underflow. + assert_eq!(ldexp(3.5, 5), 3.5 * 2f64.powi(5)); + assert_eq!(ldexp(1.0, MAX_EXP - 1), 2f64.powi(MAX_EXP - 1)); + assert_eq!(ldexp(2.77, MIN_EXP + 3), 2.77 * 2f64.powi(MIN_EXP + 3)); + + // Case where initial value is subnormal + assert_eq!(ldexp(5e-324, 4), 5e-324 * 2f64.powi(4)); + assert_eq!(ldexp(5e-324, 200), 5e-324 * 2f64.powi(200)); + + // Near underflow (2^exp is too small to represent, but not x*2^exp) + assert_eq!(ldexp(4.0, MIN_EXP - 3), 2f64.powi(MIN_EXP - 1)); + + // Near overflow + assert_eq!(ldexp(0.125, MAX_EXP + 3), 2f64.powi(MAX_EXP)); + + // Overflow and underflow cases + assert_eq!(ldexp(1.0, MIN_EXP - 54), 0.0); + assert_eq!(ldexp(-1.0, MIN_EXP - 54), -0.0); + assert_eq!(ldexp(1.0, MAX_EXP), INFINITY); + assert_eq!(ldexp(-1.0, MAX_EXP), NEG_INFINITY); + + // Special values + assert_eq!(ldexp(INFINITY, 1), INFINITY); + assert_eq!(ldexp(NEG_INFINITY, 1), NEG_INFINITY); + assert!(ldexp(NAN, 1).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-rational/src/pow.rs clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/pow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/num-rational/src/pow.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-rational/src/pow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,173 @@ +use crate::Ratio; + +use core::cmp; +use num_integer::Integer; +use num_traits::{One, Pow}; + +macro_rules! pow_unsigned_impl { + (@ $exp:ty) => { + type Output = Ratio; + #[inline] + fn pow(self, expon: $exp) -> Ratio { + Ratio::new_raw(self.numer.pow(expon), self.denom.pow(expon)) + } + }; + ($exp:ty) => { + impl> Pow<$exp> for Ratio { + pow_unsigned_impl!(@ $exp); + } + impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio + where + &'a T: Pow<$exp, Output = T>, + { + pow_unsigned_impl!(@ $exp); + } + impl<'b, T: Clone + Integer + Pow<$exp, Output = T>> Pow<&'b $exp> for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'b $exp) -> Ratio { + Pow::pow(self, *expon) + } + } + impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio + where + &'a T: Pow<$exp, Output = T>, + { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'b $exp) -> Ratio { + Pow::pow(self, *expon) + } + } + }; +} +pow_unsigned_impl!(u8); +pow_unsigned_impl!(u16); +pow_unsigned_impl!(u32); +pow_unsigned_impl!(u64); +pow_unsigned_impl!(u128); +pow_unsigned_impl!(usize); + +macro_rules! pow_signed_impl { + (@ &'b BigInt, BigUint) => { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'b BigInt) -> Ratio { + match expon.sign() { + Sign::NoSign => One::one(), + Sign::Minus => { + Pow::pow(self, expon.magnitude()).into_recip() + } + Sign::Plus => Pow::pow(self, expon.magnitude()), + } + } + }; + (@ $exp:ty, $unsigned:ty) => { + type Output = Ratio; + #[inline] + fn pow(self, expon: $exp) -> Ratio { + match expon.cmp(&0) { + cmp::Ordering::Equal => One::one(), + cmp::Ordering::Less => { + let expon = expon.wrapping_abs() as $unsigned; + Pow::pow(self, expon).into_recip() + } + cmp::Ordering::Greater => Pow::pow(self, expon as $unsigned), + } + } + }; + ($exp:ty, $unsigned:ty) => { + impl> Pow<$exp> for Ratio { + pow_signed_impl!(@ $exp, $unsigned); + } + impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio + where + &'a T: Pow<$unsigned, Output = T>, + { + pow_signed_impl!(@ $exp, $unsigned); + } + impl<'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'b $exp> for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'b $exp) -> Ratio { + Pow::pow(self, *expon) + } + } + impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio + where + &'a T: Pow<$unsigned, Output = T>, + { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'b $exp) -> Ratio { + Pow::pow(self, *expon) + } + } + }; +} +pow_signed_impl!(i8, u8); +pow_signed_impl!(i16, u16); +pow_signed_impl!(i32, u32); +pow_signed_impl!(i64, u64); +pow_signed_impl!(i128, u128); +pow_signed_impl!(isize, usize); + +#[cfg(feature = "num-bigint")] +mod bigint { + use super::*; + use num_bigint::{BigInt, BigUint, Sign}; + + impl Pow<&'b BigUint, Output = T>> Pow for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: BigUint) -> Ratio { + Pow::pow(self, &expon) + } + } + impl<'a, T: Clone + Integer> Pow for &'a Ratio + where + &'a T: for<'b> Pow<&'b BigUint, Output = T>, + { + type Output = Ratio; + #[inline] + fn pow(self, expon: BigUint) -> Ratio { + Pow::pow(self, &expon) + } + } + impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigUint> for Ratio { + pow_unsigned_impl!(@ &'b BigUint); + } + impl<'a, 'b, T: Clone + Integer> Pow<&'b BigUint> for &'a Ratio + where + &'a T: Pow<&'b BigUint, Output = T>, + { + pow_unsigned_impl!(@ &'b BigUint); + } + + impl Pow<&'b BigUint, Output = T>> Pow for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: BigInt) -> Ratio { + Pow::pow(self, &expon) + } + } + impl<'a, T: Clone + Integer> Pow for &'a Ratio + where + &'a T: for<'b> Pow<&'b BigUint, Output = T>, + { + type Output = Ratio; + #[inline] + fn pow(self, expon: BigInt) -> Ratio { + Pow::pow(self, &expon) + } + } + impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigInt> for Ratio { + pow_signed_impl!(@ &'b BigInt, BigUint); + } + impl<'a, 'b, T: Clone + Integer> Pow<&'b BigInt> for &'a Ratio + where + &'a T: Pow<&'b BigUint, Output = T>, + { + pow_signed_impl!(@ &'b BigInt, BigUint); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-traits/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-traits/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"dd701a0da6cce7e6e047cc944b2330f3c5e48cd64329e10942ea7d9299d435be","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"3fa9b7a124e7bc011758919f6d13fbdce58027852abc6c0851ddf6addfedabd5","RELEASES.md":"eb3298353c12e0cd48c79437199bd7f159c4250da06f8362afcf71004e98fde5","build.rs":"d3969209fc1c9d201c66ed11820d0b328600d75b3971f8ceebeab04900bc0587","src/bounds.rs":"a79325f6a92269ad7df3d11b9ff700d2d13fb1160e28f0c091a644efc4badc2b","src/cast.rs":"d2c9337163c3d594a701bfce21aec56571625fa0117f970f14fd82dcc4504bf6","src/float.rs":"2caf20ca3227422dcd8981accc79898e889bbda97fce1fc7f881c98e7091d8c3","src/identities.rs":"c26d7f2fd6636721930d11d345e0c7103b0a4ac242dc4035dbc956a45eba422f","src/int.rs":"ca214bab6624cb7f19bcb439958aa34596e0b13d8fc9b0090a7b37e89946d124","src/lib.rs":"00973c9c52fd607d6e4b1da4ce4d5caa7d1bc39c8cd6f5d64878075766c8ad33","src/macros.rs":"ee96613a2c73a3bef10ec7ae4d359dbf5f0b41f83e8a87c3d62ccc18dd27e498","src/ops/bytes.rs":"24ade942062566d686c6de5674b5668ea3cd688c7c88bd8e5df7ea7f96d70c6e","src/ops/checked.rs":"01e6379bf1d8eeca9dcf8bb5397e419e898e4043b57b0e2470e225bc27e81e6a","src/ops/euclid.rs":"89c09c2df7fcc4bdba32533d4e7254dceb424085239544ea2a9ae8a606bf7383","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"2b3c396af44cd240205ba8b560625fa00c07cf387139d2c49eeb7869545d976d","src/ops/mul_add.rs":"15bd64d9420c86300c5ea7f57aa736af2ef968e4e5eaaae03f62fd277f124569","src/ops/overflowing.rs":"01f4cd27f8b0e257687170cc537188029e08e5d13e0c552b01153be5d66d5716","src/ops/saturating.rs":"165993c829c10c4f60e32c8cf34434b669ef54284d7f73dc7ec58a22ba65e6fc","src/ops/wrapping.rs":"39d7bc7e074ba7590cd29b40206baed9cb30ae70dca2b7ceb460c6ca7eaad2a8","src/pow.rs":"92c12990d2396b2dabd4ba80e80ad706c0c8fd0f1b967ab3bdd9cb738b150702","src/real.rs":"b45bc1ca54549595c8d4f91a0e192769c1d924b40eda3446af4780f7a07ac8ed","src/sign.rs":"7ca11eebee94b553a33a9e53b7663ba5173db297dee523d1a2600fbbc80ef850","tests/cast.rs":"6fcc0d6653253182e979e42542fe971829cd24ab2c3a21a668e935c23d39f7c0"},"package":"071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e34bdc2d65c741cc679d2e5c72c8ed8d952d2e20c5712a3c950af4235363ad7b","Cargo.toml":"dd701a0da6cce7e6e047cc944b2330f3c5e48cd64329e10942ea7d9299d435be","Cargo.toml.orig":"172863fc77ccbdd76c7d65660c1030e553cc3629931808f18f4cd4cc73a08c53","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"3fa9b7a124e7bc011758919f6d13fbdce58027852abc6c0851ddf6addfedabd5","RELEASES.md":"eb3298353c12e0cd48c79437199bd7f159c4250da06f8362afcf71004e98fde5","build.rs":"d3969209fc1c9d201c66ed11820d0b328600d75b3971f8ceebeab04900bc0587","src/bounds.rs":"a79325f6a92269ad7df3d11b9ff700d2d13fb1160e28f0c091a644efc4badc2b","src/cast.rs":"d2c9337163c3d594a701bfce21aec56571625fa0117f970f14fd82dcc4504bf6","src/float.rs":"2caf20ca3227422dcd8981accc79898e889bbda97fce1fc7f881c98e7091d8c3","src/identities.rs":"c26d7f2fd6636721930d11d345e0c7103b0a4ac242dc4035dbc956a45eba422f","src/int.rs":"ca214bab6624cb7f19bcb439958aa34596e0b13d8fc9b0090a7b37e89946d124","src/lib.rs":"00973c9c52fd607d6e4b1da4ce4d5caa7d1bc39c8cd6f5d64878075766c8ad33","src/macros.rs":"ee96613a2c73a3bef10ec7ae4d359dbf5f0b41f83e8a87c3d62ccc18dd27e498","src/ops/bytes.rs":"24ade942062566d686c6de5674b5668ea3cd688c7c88bd8e5df7ea7f96d70c6e","src/ops/checked.rs":"01e6379bf1d8eeca9dcf8bb5397e419e898e4043b57b0e2470e225bc27e81e6a","src/ops/euclid.rs":"89c09c2df7fcc4bdba32533d4e7254dceb424085239544ea2a9ae8a606bf7383","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"2b3c396af44cd240205ba8b560625fa00c07cf387139d2c49eeb7869545d976d","src/ops/mul_add.rs":"15bd64d9420c86300c5ea7f57aa736af2ef968e4e5eaaae03f62fd277f124569","src/ops/overflowing.rs":"01f4cd27f8b0e257687170cc537188029e08e5d13e0c552b01153be5d66d5716","src/ops/saturating.rs":"165993c829c10c4f60e32c8cf34434b669ef54284d7f73dc7ec58a22ba65e6fc","src/ops/wrapping.rs":"39d7bc7e074ba7590cd29b40206baed9cb30ae70dca2b7ceb460c6ca7eaad2a8","src/pow.rs":"92c12990d2396b2dabd4ba80e80ad706c0c8fd0f1b967ab3bdd9cb738b150702","src/real.rs":"b45bc1ca54549595c8d4f91a0e192769c1d924b40eda3446af4780f7a07ac8ed","src/sign.rs":"7ca11eebee94b553a33a9e53b7663ba5173db297dee523d1a2600fbbc80ef850","tests/cast.rs":"6fcc0d6653253182e979e42542fe971829cd24ab2c3a21a668e935c23d39f7c0"},"package":"071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-traits/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/num-traits/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-traits/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7ec3d41d39b28190ec1d42db38021107b3951f3a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/num-traits/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/num-traits/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/num-traits/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/num-traits/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +authors = ["The Rust Project Developers"] +description = "Numeric traits for generic mathematics" +documentation = "https://docs.rs/num-traits" +homepage = "https://github.com/rust-num/num-traits" +keywords = ["mathematics", "numerics"] +categories = ["algorithms", "science", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-traits" +name = "num-traits" +version = "0.2.19" +readme = "README.md" +build = "build.rs" +exclude = ["/ci/*", "/.github/*"] +edition = "2021" +rust-version = "1.60" + +[package.metadata.docs.rs] +features = ["std"] +rustdoc-args = ["--generate-link-to-definition"] + +[dependencies] +libm = { version = "0.2.0", optional = true } + +[features] +default = ["std"] +libm = ["dep:libm"] +std = [] + +# vestigial features, now always in effect +i128 = [] + +[build-dependencies] +autocfg = "1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"cc4e490ceb3a92be753f3ffee297921a341faf67b304e1e0e63833aba4c3d529","Cargo.lock":"57fb641115940cc1870a3460ebb53ca921461c38894a68e62bf0fc4438825fa8","Cargo.toml":"b0c4dcab027bb78093c9cd0e643b778303bb113fed7f3ab251252141d2b6735d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"2331182c8b5a6971fd0d04a0ca711d5839e93b3de6b2003108940a8c93850aaf","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"32ee2c252d176726e62cf1f81a270d3738cb06784c47d4064e62350d9f7672cd","src/imp_pl.rs":"6a97f60a91ab44192dcaf028e987f6be0328b5d4d69216dcdaec93bc39401f68","src/imp_std.rs":"1c130f83be5c1360dfd379911f97797c1e4c730b845f465c8c2630467ca317d2","src/lib.rs":"60fe685113e11203ec32876b5dad9c8e1eb705da5854eff8f044d3f4651a7d0f","src/race.rs":"e8400987cc44b3e4b1a321d1e0506df07be7034a7d1c16be641dc75b44fee05c","tests/it/main.rs":"e6e9987e053af84b9d76052602995b1e777efb5bc06cd5f49009e6f03b18626c","tests/it/race.rs":"8dfe38563b6d0be890ab076be1fc1122d41a7c7792354cd7f60bc4454666b968","tests/it/race_once_box.rs":"1c2fe9e2988ec38d60c93c797fceb4c7a65d1b2e48a6a1e78db78ab91388e844","tests/it/sync_lazy.rs":"a36c5d66340b3d6d20aad331a499858a2125dfdfd624c5bf3b4b06a0b157c75c","tests/it/sync_once_cell.rs":"0d04beeb394eb53dd3fc0309fcfc382d56350e72b89d22356e0047d6c7bfef58","tests/it/unsync_lazy.rs":"51a1ffd411770d1e32399ec23feb5f61be362bbed34e100eb7509f8496224e1a","tests/it/unsync_once_cell.rs":"82b72936d7bd4090db25cfc543c01ef3206d6917ac56f09d17d4110a65deb30a"},"package":"3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ce48f117b520071d8d0cb826a4f36838b19d7a4798ae6eda159865fa2de5b3cc",".github/workflows/ci.yaml":"b1c9b12babf51fcaa7de2adc737c91e882da240cf847becf380141cec320cf2d","CHANGELOG.md":"cc4e490ceb3a92be753f3ffee297921a341faf67b304e1e0e63833aba4c3d529","Cargo.lock":"57fb641115940cc1870a3460ebb53ca921461c38894a68e62bf0fc4438825fa8","Cargo.toml":"b0c4dcab027bb78093c9cd0e643b778303bb113fed7f3ab251252141d2b6735d","Cargo.toml.orig":"86f2c5b24f6b696785a4c987283a45181548ecd2b1e2e4d3b31f3ef86f886e20","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"2331182c8b5a6971fd0d04a0ca711d5839e93b3de6b2003108940a8c93850aaf","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"32ee2c252d176726e62cf1f81a270d3738cb06784c47d4064e62350d9f7672cd","src/imp_pl.rs":"6a97f60a91ab44192dcaf028e987f6be0328b5d4d69216dcdaec93bc39401f68","src/imp_std.rs":"1c130f83be5c1360dfd379911f97797c1e4c730b845f465c8c2630467ca317d2","src/lib.rs":"60fe685113e11203ec32876b5dad9c8e1eb705da5854eff8f044d3f4651a7d0f","src/race.rs":"e8400987cc44b3e4b1a321d1e0506df07be7034a7d1c16be641dc75b44fee05c","tests/it/main.rs":"e6e9987e053af84b9d76052602995b1e777efb5bc06cd5f49009e6f03b18626c","tests/it/race.rs":"8dfe38563b6d0be890ab076be1fc1122d41a7c7792354cd7f60bc4454666b968","tests/it/race_once_box.rs":"1c2fe9e2988ec38d60c93c797fceb4c7a65d1b2e48a6a1e78db78ab91388e844","tests/it/sync_lazy.rs":"a36c5d66340b3d6d20aad331a499858a2125dfdfd624c5bf3b4b06a0b157c75c","tests/it/sync_once_cell.rs":"0d04beeb394eb53dd3fc0309fcfc382d56350e72b89d22356e0047d6c7bfef58","tests/it/unsync_lazy.rs":"51a1ffd411770d1e32399ec23feb5f61be362bbed34e100eb7509f8496224e1a","tests/it/unsync_once_cell.rs":"82b72936d7bd4090db25cfc543c01ef3206d6917ac56f09d17d4110a65deb30a"},"package":"3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c48d3c2c01de926228aea2ac1d03672b4ce160c1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.github/workflows/ci.yaml clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.github/workflows/ci.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/once_cell/.github/workflows/ci.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/once_cell/.github/workflows/ci.yaml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +name: CI +on: + pull_request: + push: + branches: ["master", "staging", "trying"] + +env: + CARGO_INCREMENTAL: 0 + CARGO_NET_RETRY: 10 + CI: 1 + RUST_BACKTRACE: short + RUSTFLAGS: -D warnings + RUSTUP_MAX_RETRIES: 10 + +jobs: + test: + name: Rust + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # fetch tags for publish + - uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 + - run: cargo run -p xtask -- ci + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} + MIRIFLAGS: -Zmiri-strict-provenance diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/once_cell/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/once_cell/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/once_cell/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/once_cell/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +[package] +name = "once_cell" +version = "1.19.0" +authors = ["Aleksey Kladov "] +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.60" + +description = "Single assignment cells and lazy values." +readme = "README.md" +documentation = "https://docs.rs/once_cell" + +repository = "https://github.com/matklad/once_cell" +keywords = ["lazy", "static"] +categories = ["rust-patterns", "memory-management"] + +exclude = ["*.png", "*.svg", "/Cargo.lock.msrv", "rustfmt.toml"] + +[workspace] +members = ["xtask"] + +[dependencies] +parking_lot_core = { version = "0.9.3", optional = true, default_features = false } +portable-atomic = { version = "1", optional = true } +critical-section = { version = "1", optional = true } + +[dev-dependencies] +regex = "1.2.0" +critical-section = { version = "1.1.1", features = ["std"] } + +[features] +default = ["std"] + +# Enables `once_cell::sync` module. +std = ["alloc"] + +# Enables `once_cell::race::OnceBox` type. +alloc = ["race"] + +# Enables `once_cell::race` module. +race = [] + +# Uses parking_lot to implement once_cell::sync::OnceCell. +# This makes no speed difference, but makes each OnceCell +# up to 16 bytes smaller, depending on the size of the T. +parking_lot = ["dep:parking_lot_core"] + +# Uses `critical-section` to implement `sync` and `race` modules. in +# `#![no_std]` mode. Please read `critical-section` docs carefully +# before enabling this feature. +critical-section = ["dep:critical-section", "portable-atomic" ] + +# Enables semver-exempt APIs of this crate. +# At the moment, this feature is unused. +unstable = [] + +# Only for backwards compatibility. +atomic-polyfill = ["critical-section"] + +[[example]] +name = "bench" +required-features = ["std"] + +[[example]] +name = "bench_acquire" +required-features = ["std"] + +[[example]] +name = "lazy_static" +required-features = ["std"] + +[[example]] +name = "reentrant_init_deadlocks" +required-features = ["std"] + +[[example]] +name = "regex" +required-features = ["std"] + +[[example]] +name = "test_synchronization" +required-features = ["std"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/paste/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/paste/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"e9c7d8e96c8924319e562b184b3e46bb391071edad2664ba612a1194fe8fdec3","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cd8f304fa9cca9566dff0bb3492beae55f47f3972ddfb8f1fa38c3da1068b4a8","build.rs":"e1f79dc7a4f6507a5834fd0124a08eb7f90b700b2f4c0225eb1086eb9b8591d1","src/attr.rs":"e8301f019e107ef9f5d8a3bbed355ffa9c0fd73396646d7fedbba333d341b7bc","src/error.rs":"be08d9d48b4cb9984b5141b12f21c31bd7293942c18b3ce25754723930cf54f5","src/lib.rs":"3900e549bdb54881813a627574b9711c48a08dd03e885808ba9e97979853bec3","src/segment.rs":"462be04eea3ad48028d0841e8000c13205eb049522b8003bcc2926f21e93cb78","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_attr.rs":"39a55dcce5a127b2f85e9127a810b4aa3318e408cac93ff678301a2120aac5b5","tests/test_doc.rs":"7afb22427cb1c54fcf75a581fec5503404d8e93274027040b4d901f8caa597bb","tests/test_expr.rs":"d25ff118a78bd8e7d38ff532f0b9abb046bd0fbe61db8080b973bff67743af4e","tests/test_item.rs":"9641e55f7f47ea4b27facd53ba53e8cb4e95bebc5e7cc48acc326cd5286701b3","tests/ui/case-warning.rs":"6b7cb803527911fe698e7fbe080160bc5d07c0da36fac0ec29d599753ce8bd10","tests/ui/case-warning.stderr":"7b7d470edc2a11b0864534099b360e0c42d423e068f49cea7858e0b340c2ef3d","tests/ui/env-empty.rs":"093fb0844475f4710580b5e4cad162918896d4fb48d1516bae04eb39dddd265a","tests/ui/env-empty.stderr":"3462f06f6f21130a81efff3be3bc838b395f6107bfbf753e479ec5a60e09b15d","tests/ui/env-non-string.rs":"516460860e7790b412b0fcd203289720a155dfba2498616967e4d7e6e6ab4990","tests/ui/env-non-string.stderr":"fea08d588a238e0f4c06de5c5ae97ac195bb2bcfc070040fb8087bdf4d1f4eee","tests/ui/env-suffix.rs":"0f1756608efc7a6c5810b8b21528092546ac95371e048c6060064e747c1b0a27","tests/ui/env-suffix.stderr":"287fecb2a91abc61501e0bd71d7f111670a526960ab18a554f4d16ed83d940b5","tests/ui/env-unexpected.rs":"18f06317e72ea16dae6ebe7c20bf5ef26b46e01a5c54fd31dc2a351ba68e8ca5","tests/ui/env-unexpected.stderr":"14d9a40160daf0191efc2b53be5fdde5b066674053e76af170e58af08f4022aa","tests/ui/invalid-ident.rs":"c3f375cac04d56684e427834076128b6e77eeeb9e99067a06307e27693b0ff51","tests/ui/invalid-ident.stderr":"b56d1c26253dec71ba1f97ffa01602b3a4429fc85a6b5c87f5290aab0568ea30","tests/ui/missing-paren-on-env.rs":"05cafef972e8c99f82834e164e7713f6056ac1a24b1f31d0320ac4fe361a53bd","tests/ui/missing-paren-on-env.stderr":"baf7b420d201f033e2113eaebd85376047397d991c35c441f07e5c6f1ec2b685","tests/ui/no-env-var.rs":"330bb71f2f3d98d23176acc5aeb1c0b66443af14c0857bb5bc92bfd130eb4a62","tests/ui/no-env-var.stderr":"68af072d3ccb2537bca9a5cd6d5796bb5ab5408f59564c8e8c66b1590ac7c5a5","tests/ui/no-ident-after-colon.rs":"a5af9548ab8d7f5b6130e1410c90f2cc589c595eb99f6939e6deb3f54e7262a2","tests/ui/no-ident-after-colon.stderr":"efac036a78f077c9c10a1ed048d69531293dcb97784ed784af0b24788ecbab54","tests/ui/unexpected-group.rs":"6b2e398a9ad3e077ea49c68b7c134ec3268e398723f4d9d5ef7b4d7b8513ac44","tests/ui/unexpected-group.stderr":"1260b5a4c295639958e3dd0da475c385184f0a916f5fdc4f1f2bfe232688f43c","tests/ui/unexpected-modifier.rs":"8b7e4c93f06fe7e7be469375e8bbaf19fec5fdffe688a0c29d2de2944a420337","tests/ui/unexpected-modifier.stderr":"581212b89358ac6bd38632bfd4322c25c171046875711fd639cfb498e01629c8","tests/ui/unexpected-punct.rs":"430e98bc03abdcc46f72cea01264c278a9c25f3d1d63064a6d78f4ae71b6a2d9","tests/ui/unexpected-punct.stderr":"24ab2e32d2da8dad93ef04dc05a2ecf6fdeb11bdebeae9454ad4759cc2b16551","tests/ui/unsupported-literal.rs":"1b2d3634fba5dc35d5ac9012d488aa93e329d1fa4489df1eadee65613a010e59","tests/ui/unsupported-literal.stderr":"6b137ccd6bc2a341aeb1e0d5321a896aa6c8db9a4e2571f4e41bd744511760bf","tests/ui/unsupported-modifier.rs":"03bb0239880070e8b470a6072c06094e1483ea91256e7cb4b9f2e8761696fa5a","tests/ui/unsupported-modifier.stderr":"890d7f484fdbd46da72923db4d7aba0ac3eaece253bb7195b7a36ae9a918027e"},"package":"de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3e4273384b612d7bbbc9a32ae2131b8a2c0dc066fc88c87f473c5410edc095a7",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"c1615e93528c2010fb520f493ab7af69e031c8149118f5764c0ccf18112ddcac","Cargo.toml":"e9c7d8e96c8924319e562b184b3e46bb391071edad2664ba612a1194fe8fdec3","Cargo.toml.orig":"1e81f36f9f948083408c14dc7d2c9cddac0cb405bbd07245ceac69106762ed2d","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cd8f304fa9cca9566dff0bb3492beae55f47f3972ddfb8f1fa38c3da1068b4a8","build.rs":"e1f79dc7a4f6507a5834fd0124a08eb7f90b700b2f4c0225eb1086eb9b8591d1","src/attr.rs":"e8301f019e107ef9f5d8a3bbed355ffa9c0fd73396646d7fedbba333d341b7bc","src/error.rs":"be08d9d48b4cb9984b5141b12f21c31bd7293942c18b3ce25754723930cf54f5","src/lib.rs":"3900e549bdb54881813a627574b9711c48a08dd03e885808ba9e97979853bec3","src/segment.rs":"462be04eea3ad48028d0841e8000c13205eb049522b8003bcc2926f21e93cb78","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_attr.rs":"39a55dcce5a127b2f85e9127a810b4aa3318e408cac93ff678301a2120aac5b5","tests/test_doc.rs":"7afb22427cb1c54fcf75a581fec5503404d8e93274027040b4d901f8caa597bb","tests/test_expr.rs":"d25ff118a78bd8e7d38ff532f0b9abb046bd0fbe61db8080b973bff67743af4e","tests/test_item.rs":"9641e55f7f47ea4b27facd53ba53e8cb4e95bebc5e7cc48acc326cd5286701b3","tests/ui/case-warning.rs":"6b7cb803527911fe698e7fbe080160bc5d07c0da36fac0ec29d599753ce8bd10","tests/ui/case-warning.stderr":"7b7d470edc2a11b0864534099b360e0c42d423e068f49cea7858e0b340c2ef3d","tests/ui/env-empty.rs":"093fb0844475f4710580b5e4cad162918896d4fb48d1516bae04eb39dddd265a","tests/ui/env-empty.stderr":"3462f06f6f21130a81efff3be3bc838b395f6107bfbf753e479ec5a60e09b15d","tests/ui/env-non-string.rs":"516460860e7790b412b0fcd203289720a155dfba2498616967e4d7e6e6ab4990","tests/ui/env-non-string.stderr":"fea08d588a238e0f4c06de5c5ae97ac195bb2bcfc070040fb8087bdf4d1f4eee","tests/ui/env-suffix.rs":"0f1756608efc7a6c5810b8b21528092546ac95371e048c6060064e747c1b0a27","tests/ui/env-suffix.stderr":"287fecb2a91abc61501e0bd71d7f111670a526960ab18a554f4d16ed83d940b5","tests/ui/env-unexpected.rs":"18f06317e72ea16dae6ebe7c20bf5ef26b46e01a5c54fd31dc2a351ba68e8ca5","tests/ui/env-unexpected.stderr":"14d9a40160daf0191efc2b53be5fdde5b066674053e76af170e58af08f4022aa","tests/ui/invalid-ident.rs":"c3f375cac04d56684e427834076128b6e77eeeb9e99067a06307e27693b0ff51","tests/ui/invalid-ident.stderr":"b56d1c26253dec71ba1f97ffa01602b3a4429fc85a6b5c87f5290aab0568ea30","tests/ui/missing-paren-on-env.rs":"05cafef972e8c99f82834e164e7713f6056ac1a24b1f31d0320ac4fe361a53bd","tests/ui/missing-paren-on-env.stderr":"baf7b420d201f033e2113eaebd85376047397d991c35c441f07e5c6f1ec2b685","tests/ui/no-env-var.rs":"330bb71f2f3d98d23176acc5aeb1c0b66443af14c0857bb5bc92bfd130eb4a62","tests/ui/no-env-var.stderr":"68af072d3ccb2537bca9a5cd6d5796bb5ab5408f59564c8e8c66b1590ac7c5a5","tests/ui/no-ident-after-colon.rs":"a5af9548ab8d7f5b6130e1410c90f2cc589c595eb99f6939e6deb3f54e7262a2","tests/ui/no-ident-after-colon.stderr":"efac036a78f077c9c10a1ed048d69531293dcb97784ed784af0b24788ecbab54","tests/ui/unexpected-group.rs":"6b2e398a9ad3e077ea49c68b7c134ec3268e398723f4d9d5ef7b4d7b8513ac44","tests/ui/unexpected-group.stderr":"1260b5a4c295639958e3dd0da475c385184f0a916f5fdc4f1f2bfe232688f43c","tests/ui/unexpected-modifier.rs":"8b7e4c93f06fe7e7be469375e8bbaf19fec5fdffe688a0c29d2de2944a420337","tests/ui/unexpected-modifier.stderr":"581212b89358ac6bd38632bfd4322c25c171046875711fd639cfb498e01629c8","tests/ui/unexpected-punct.rs":"430e98bc03abdcc46f72cea01264c278a9c25f3d1d63064a6d78f4ae71b6a2d9","tests/ui/unexpected-punct.stderr":"24ab2e32d2da8dad93ef04dc05a2ecf6fdeb11bdebeae9454ad4759cc2b16551","tests/ui/unsupported-literal.rs":"1b2d3634fba5dc35d5ac9012d488aa93e329d1fa4489df1eadee65613a010e59","tests/ui/unsupported-literal.stderr":"6b137ccd6bc2a341aeb1e0d5321a896aa6c8db9a4e2571f4e41bd744511760bf","tests/ui/unsupported-modifier.rs":"03bb0239880070e8b470a6072c06094e1483ea91256e7cb4b9f2e8761696fa5a","tests/ui/unsupported-modifier.stderr":"890d7f484fdbd46da72923db4d7aba0ac3eaece253bb7195b7a36ae9a918027e"},"package":"de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/paste/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/paste/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/paste/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "1e0cc1025af5388397c67fa4389ad7ad24814df8" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/paste/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/paste/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/paste/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/paste/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/paste/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,82 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.56.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + + msrv: + name: Rust 1.31.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@1.31.0 + - run: cargo check + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/paste/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/paste/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/paste/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/paste/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "paste" +version = "1.0.14" +authors = ["David Tolnay "] +categories = ["development-tools", "no-std", "no-std::no-alloc"] +description = "Macros for all your token pasting needs" +edition = "2018" +keywords = ["macros"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/paste" +rust-version = "1.31" + +[lib] +proc-macro = true + +[dev-dependencies] +paste-test-suite = { version = "0", path = "tests/macros" } +rustversion = "1.0" +trybuild = { version = "1.0.49", features = ["diff"] } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"3a84f1b8c41cc4d26d09965ae5dd49b52cf3763f0242447263a2d87dc3c89060",".github/FUNDING.yml":"811cd7ab66a672a4a042b7fa366603e80884aebe1426ace94ccbf1438b0bbd5f",".github/dependabot.yml":"8a14bc47e61bbe241fe68f743ba3bba053f02a2097a41e034c9431e812be2de0",".github/release-butler.toml":"7f4803ff5d9dfb4a68e7b4197ec26b340bb38919bf61e99cd2281a8b62034f43",".github/workflows/ci.yml":"73f20451e121834ff83a050ff25ee2563c462fc9b783d2ab704bc9612229f731",".github/workflows/release.yml":"a68267b5a44e3aa307137a0757abeb3446cb1dec6622df44ef208fdf0c417079",".vscode/settings.json":"f6fdace4a64381daa80d174466ddbe899217efe051d474e03ac09389e8ed501f","CHANGELOG.md":"b62896af2cf8bccb43382a7c0be38b1480049cd3dd6eb0c45a00c83244fe95be","CONTRIBUTING.md":"ddd3372ad6e6b7b6d89e646d44efca5edac49ee48d014563d0a38edf559a89fb","Cargo.lock":"81ee06e5563acafe76a427dfdfef1ac93552d793d83e2bd50887e40bc9caf525","Cargo.toml":"6c7f177d66fdc12fd76ffdbe78350cbc5a9eab3103ab77436b7afce2bf38357e","Cargo.toml.orig":"06c099ea0278f8b2205392b367a682e9a7deefdf2b032d547afd8920c704d60d","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"eea7706ff3a7db6a47fafe6d47ddca47291d6edd0c8b023b09022d60f2b77d15","src/attr.rs":"b1ae291a92c3a974e58c17a8d2ca23135f0dff31065736d494e78fec4aef1544","src/error.rs":"be08d9d48b4cb9984b5141b12f21c31bd7293942c18b3ce25754723930cf54f5","src/lib.rs":"993be9dc7827240af1b6ba82aa482ad3f5ed7c0bc636dc61757238aefa589b39","src/segment.rs":"c5b03c660fd04a7f2c56f6dee0fcee4e19ed75cf1ab8faddfb52e5c1c1ef9bb3","test.sh":"ff58b4e5aea598493315c8b41d804daf840aa8674cde8819105d6637bcba3728"},"package":"35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d9aabae3fb80c0f74940677dadd930f6bffe7496" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: AS1100K diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "cargo" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/release-butler.toml clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/release-butler.toml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/release-butler.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/release-butler.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +version = 1 + +default_branch = "master" + +[issues_meta_data] +allowed_authors = ["AS1100K"] + +[packages.pastey] +path = "" +changelog_file = "CHANGELOG.md" +pre_release_changelog_file = "PRERELEASE-CHANGELOG.md" +create_gh_release = true +package_manager = "cargo" \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.56.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: ./test.sh ${{matrix.rust}} + - uses: actions/upload-artifact@v4 + if: matrix.rust == 'nightly' && always() + with: + name: Cargo.lock + path: Cargo.lock + + msrv: + name: Rust 1.54 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.54 + - run: cargo check + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + MIRIFLAGS: -Zmiri-strict-provenance + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cd ./pastey-test-suite && cargo miri setup && cargo miri test && cd ../ + - run: cd ./paste-compat && cargo miri setup && cargo miri test && cd ../ + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/workflows/release.yml clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/release.yml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.github/workflows/release.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.github/workflows/release.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +on: + push: + # Pattern matched against refs/tags + tags: + - "v*" + +permissions: + contents: write + +jobs: + publish: + name: Publish + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Rust Toolchain + uses: rs-workspace/rust-toolchain@v0.2.0 + + - name: Publish Crate + run: cargo publish --token ${CRATES_TOKEN} + env: + CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/.vscode/settings.json clamav-1.4.6+dfsg/.cargo/vendor/pastey/.vscode/settings.json --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/.vscode/settings.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/.vscode/settings.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "rust-analyzer.linkedProjects": ["./paste-compat/Cargo.toml", "./pastey-test-suite/Cargo.toml"] +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/pastey/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.1] - 2025-08-12 + +### Removed + +- `build.rs` and inline literal parsing logic [#16](https://github.com/AS1100K/pastey/pull/16) + +## [0.1.0] - 2025-03-12 + +### Added + +- Raw Mode in `paste!` macro [#8](https://github.com/AS1100K/pastey/pull/8) + +## [v0.0.1] + +### Added + +- `lower_camel` case conversion modifier [#4](https://github.com/AS1100K/pastey/issues/4) +- `upper_camel` case conversion modifier, similar to `camel` +- `camel_edge` case coversion modifer [#3](https://github.com/AS1100K/pastey/issues/3) +- Internal crate `paste-compat` for testing behaviour against paste crate diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/CONTRIBUTING.md clamav-1.4.6+dfsg/.cargo/vendor/pastey/CONTRIBUTING.md --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/CONTRIBUTING.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +# Contributing to Pastey + +Thank you for your interest in contributing to Pastey! Here are some guidelines to help you get started. + +## Project Goals + +One of our main goals is to ensure that Pastey is a drop-in replacement for the paste crate. It should +not change the behavior or names of existing modifiers. For new behavior, please create a new modifier. + +For this we have a special test crate named [paste-compat](./paste-compat/), it is always appreciated +to add more test cases here that works on paste crate. + +## Testing + +Run `./test.sh` for testing your code + +## How to Contribute + +1. **Fork the repository**: Click the "Fork" button at the top right of the repository page. +2. **Clone your fork**: + + ```sh + git clone https://github.com/your-username/pastey.git + cd pastey + ``` + +3. **Create a new branch**: + + ```sh + git checkout -b my-feature-branch + ``` + +4. **Make your changes**: Implement your feature or bug fix. +5. **Commit your changes**: + + ```sh + git commit -am 'Add new feature' + ``` + +6. **Push to your branch**: + + ```sh + git push origin my-feature-branch + ``` + +7. **Create a Pull Request**: Go to the repository on GitHub and click "New Pull Request". + +## Code Style + +Please follow the existing code style and conventions. Ensure your code is well-documented and tested. + +## Reporting Issues + +If you find a bug or have a feature request, please create an issue on GitHub. Provide as much detail as +possible to help us understand and address the issue. + +## License + +By contributing to Pastey, you agree that your contributions will be licensed under the same license as the project: either the Apache License, Version 2.0 or the MIT license. + +Thank you for your contributions! diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "pastey" +version = "0.1.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.54" +name = "pastey" +version = "0.1.1" +authors = [ + "Aditya Kumar ", + "David Tolnay ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Macros for all your token pasting needs. Successor of paste." +readme = "README.md" +keywords = ["macros"] +categories = [ + "development-tools", + "no-std", + "no-std::no-alloc", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/as1100k/pastey" + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "pastey" +path = "src/lib.rs" +proc-macro = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +[package] +name = "pastey" +version = "0.1.1" +authors = [ + "Aditya Kumar ", + "David Tolnay ", +] +categories = ["development-tools", "no-std", "no-std::no-alloc"] +description = "Macros for all your token pasting needs. Successor of paste." +edition = "2018" +keywords = ["macros"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/as1100k/pastey" +rust-version = "1.54" + +[lib] +proc-macro = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/README.md clamav-1.4.6+dfsg/.cargo/vendor/pastey/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,243 @@ +Macros for all your token pasting needs +======================================= + +[github](https://github.com/as1100k/pastey) +[crates.io](https://crates.io/crates/pastey) +[docs.rs](https://docs.rs/pastey) +[build status](https://github.com/as1100k/pastey/actions?query=branch%master) + +**_`pastey` is the fork of `paste` and is aimed to be a drop-in replacement with additional features for +`paste` crate_** + +
+ +

+Migrating from paste crate + +Migrating from `paste` crate to `pastey` is super simple, just change the following in your `Cargo.toml` + +```diff +[dependencies] +- paste = "1" ++ pastey = "*" # Or any specific version of pastey +``` + +Or even better way: + +```diff +[dependencies] +- paste = "1" ++ paste = { package = "pastey", version = "*" } +``` + +
+ +
+ +## Quick Start + +Add `pastey` as your dependency in `Cargo.toml` + +```toml +[dependencies] +# TODO: Replace with latest version available on crates.io +pastey = "*" +``` + +This approach works with any Rust compiler 1.54+. + +## Pasting identifiers + +Within the `paste!` macro, identifiers inside `[<`...`>]` are pasted together to +form a single identifier. + +```rust +use pastey::paste; + +paste! { + // Defines a const called `QRST`. + const []: &str = "success!"; +} + +fn main() { + assert_eq!( + paste! { [].len() }, + 8, + ); +} +``` + +
+ +## More elaborate example + +The next example shows a macro that generates accessor methods for some struct +fields. It demonstrates how you might find it useful to bundle a paste +invocation inside of a macro\_rules macro. + +```rust +use pastey::paste; + +macro_rules! make_a_struct_and_getters { + ($name:ident { $($field:ident),* }) => { + // Define a struct. This expands to: + // + // pub struct S { + // a: String, + // b: String, + // c: String, + // } + pub struct $name { + $( + $field: String, + )* + } + + // Build an impl block with getters. This expands to: + // + // impl S { + // pub fn get_a(&self) -> &str { &self.a } + // pub fn get_b(&self) -> &str { &self.b } + // pub fn get_c(&self) -> &str { &self.c } + // } + paste! { + impl $name { + $( + pub fn [](&self) -> &str { + &self.$field + } + )* + } + } + } +} + +make_a_struct_and_getters!(S { a, b, c }); + +fn call_some_getters(s: &S) -> bool { + s.get_a() == s.get_b() && s.get_c().is_empty() +} +``` + +
+ +## Case conversion + +The `pastey` crate supports the following case modfiers: + +| Modifier | Description | +|------------------------------------|---------------------------------------| +| `$var:lower` | Lower Case | +| `$var:upper` | Upper Case | +| `$var:snake` | [Snake Case] | +| `$var:camel` or `$var:upper_camel` | Upper Camel Case | +| `$var:lower_camel` | Lower Camel Case [#4] | +| `$var:camel_edge` | Covers Edge cases of Camel Case. [#3] | + +_**NOTE: The pastey crate is going to be a drop in replacement to paste crate, +and will not change the behaviour of existing modifier like `lower`, `upper`, +`snake` and `camel`. For modifying the behaviour new modifiers will be created, +like `camel_edge`**_ + +You can also use multiple of these modifers like `$var:snake:upper` would give you +`SCREAMING_SNAKE_CASE`. + +Example + +```rust +use pastey::paste; + +paste! { + const []: &str = "libpastey"; + + let _ = LIBPASTEY; +} +``` + +The precise Unicode conversions are as defined by [`str::to_lowercase`] and +[`str::to_uppercase`]. + +[#3]: https://github.com/AS1100K/pastey/issues/3 +[#4]: https://github.com/AS1100K/pastey/issues/4 +[`str::to_lowercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase +[`str::to_uppercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_uppercase + +
+ +## Raw Identifier Generation + +`pastey` now supports raw identifiers using a special raw mode. By prefixing a token with `#` +inside the paste syntax, it treats that token as a raw identifier. + +```rust +use pastey::paste; + +macro_rules! define_struct_and_impl { + ($name:ident $(- $name_tail:ident)*) => { + paste!{ + struct [< # $name:camel $( $name_tail)* >]; // '#' signals a raw identifier + + impl [< # $name:camel $( $name_tail)* >] { + fn [< # $name:snake $( _ $name_tail:snake)* >]() {} + } + + } + } +} + +define_struct_and_impl!(loop); +define_struct_and_impl!(loop - xyz); + +fn test_fn() { + let _ = Loop::r#loop(); + let _ = Loopxyz::loop_xyz(); +} +``` + +
+ +## Pasting documentation strings + +Within the `paste!` macro, arguments to a #\[doc ...\] attribute are implicitly +concatenated together to form a coherent documentation string. + +```rust +use pastey::paste; + +macro_rules! method_new { + ($ret:ident) => { + paste! { + #[doc = "Create a new `" $ret "` object."] + pub fn new() -> $ret { todo!() } + } + }; +} + +pub struct Pastey {} + +method_new!(Pastey); // expands to #[doc = "Create a new `Paste` object"] +``` + +
+ +#### Credits + + +This crate is the fork of paste and I appreciate the efforts of +@dtolnay and other contributors. + + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/attr.rs clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/attr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/attr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/attr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,171 @@ +use crate::error::Result; +use crate::segment::{self, Segment}; +use proc_macro::{Delimiter, Group, Spacing, Span, TokenStream, TokenTree}; +use std::iter; +use std::mem; +use std::str::FromStr; + +pub fn expand_attr( + attr: TokenStream, + span: Span, + contains_paste: &mut bool, +) -> Result { + let mut tokens = attr.clone().into_iter(); + let mut leading_colons = 0; // $(::)? + let mut leading_path = 0; // $($ident)::+ + + let mut token; + let group = loop { + token = tokens.next(); + match token { + // colon after `$(:)?` + Some(TokenTree::Punct(ref punct)) + if punct.as_char() == ':' && leading_colons < 2 && leading_path == 0 => + { + leading_colons += 1; + } + // ident after `$(::)? $($ident ::)*` + Some(TokenTree::Ident(_)) if leading_colons != 1 && leading_path % 3 == 0 => { + leading_path += 1; + } + // colon after `$(::)? $($ident ::)* $ident $(:)?` + Some(TokenTree::Punct(ref punct)) if punct.as_char() == ':' && leading_path % 3 > 0 => { + leading_path += 1; + } + // eq+value after `$(::)? $($ident)::+` + Some(TokenTree::Punct(ref punct)) + if punct.as_char() == '=' && leading_path % 3 == 1 => + { + let mut count = 0; + if tokens.inspect(|_| count += 1).all(|tt| is_stringlike(&tt)) && count > 1 { + *contains_paste = true; + let leading = leading_colons + leading_path; + return do_paste_name_value_attr(attr, span, leading); + } + return Ok(attr); + } + // parens after `$(::)? $($ident)::+` + Some(TokenTree::Group(ref group)) + if group.delimiter() == Delimiter::Parenthesis && leading_path % 3 == 1 => + { + break group; + } + // bail out + _ => return Ok(attr), + } + }; + + // There can't be anything else after the first group in a valid attribute. + if tokens.next().is_some() { + return Ok(attr); + } + + let mut group_contains_paste = false; + let mut expanded = TokenStream::new(); + let mut nested_attr = TokenStream::new(); + for tt in group.stream() { + match &tt { + TokenTree::Punct(punct) if punct.as_char() == ',' => { + expanded.extend(expand_attr( + nested_attr, + group.span(), + &mut group_contains_paste, + )?); + expanded.extend(iter::once(tt)); + nested_attr = TokenStream::new(); + } + _ => nested_attr.extend(iter::once(tt)), + } + } + + if !nested_attr.is_empty() { + expanded.extend(expand_attr( + nested_attr, + group.span(), + &mut group_contains_paste, + )?); + } + + if group_contains_paste { + *contains_paste = true; + let mut group = Group::new(Delimiter::Parenthesis, expanded); + group.set_span(span); + Ok(attr + .into_iter() + // Just keep the initial ident in `#[ident(...)]`. + .take(leading_colons + leading_path) + .chain(iter::once(TokenTree::Group(group))) + .collect()) + } else { + Ok(attr) + } +} + +fn do_paste_name_value_attr(attr: TokenStream, span: Span, leading: usize) -> Result { + let mut expanded = TokenStream::new(); + let mut tokens = attr.into_iter().peekable(); + expanded.extend(tokens.by_ref().take(leading + 1)); // `doc =` + + let mut segments = segment::parse(&mut tokens)?; + + for segment in &mut segments { + if let Segment::String(string) = segment { + if let Some(open_quote) = string.value.find('"') { + if open_quote == 0 { + string.value.truncate(string.value.len() - 1); + string.value.remove(0); + } else { + let begin = open_quote + 1; + let end = string.value.rfind('"').unwrap(); + let raw_string = mem::take(&mut string.value); + for ch in raw_string[begin..end].chars() { + string.value.extend(ch.escape_default()); + } + } + } + } + } + + let mut lit = segment::paste(&segments)?; + + if lit.starts_with("r#") { + // Raw mode doesn't have any impact when using in attribute + lit.remove(0); + lit.remove(0); + } + + lit.insert(0, '"'); + lit.push('"'); + + let mut lit = TokenStream::from_str(&lit) + .unwrap() + .into_iter() + .next() + .unwrap(); + lit.set_span(span); + expanded.extend(iter::once(lit)); + Ok(expanded) +} + +fn is_stringlike(token: &TokenTree) -> bool { + match token { + TokenTree::Ident(_) => true, + TokenTree::Literal(literal) => { + let repr = literal.to_string(); + !repr.starts_with('b') && !repr.starts_with('\'') + } + TokenTree::Group(group) => { + if group.delimiter() != Delimiter::None { + return false; + } + let mut inner = group.stream().into_iter(); + match inner.next() { + Some(first) => inner.next().is_none() && is_stringlike(&first), + None => false, + } + } + TokenTree::Punct(punct) => { + punct.as_char() == '\'' || punct.as_char() == ':' && punct.spacing() == Spacing::Alone + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +pub type Result = std::result::Result; + +pub struct Error { + begin: Span, + end: Span, + msg: String, +} + +impl Error { + pub fn new(span: Span, msg: &str) -> Self { + Self::new2(span, span, msg) + } + + pub fn new2(begin: Span, end: Span, msg: &str) -> Self { + Error { + begin, + end, + msg: msg.to_owned(), + } + } + + pub fn to_compile_error(&self) -> TokenStream { + // compile_error! { $msg } + TokenStream::from_iter(vec![ + TokenTree::Ident(Ident::new("compile_error", self.begin)), + TokenTree::Punct({ + let mut punct = Punct::new('!', Spacing::Alone); + punct.set_span(self.begin); + punct + }), + TokenTree::Group({ + let mut group = Group::new(Delimiter::Brace, { + TokenStream::from_iter(vec![TokenTree::Literal({ + let mut string = Literal::string(&self.msg); + string.set_span(self.end); + string + })]) + }); + group.set_span(self.end); + group + }), + ]) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,326 @@ +#![doc = include_str!("../README.md")] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::doc_markdown, + clippy::match_same_arms, + clippy::module_name_repetitions, + clippy::needless_doctest_main, + clippy::too_many_lines +)] + +extern crate proc_macro; + +mod attr; +mod error; +mod segment; + +use crate::attr::expand_attr; +use crate::error::{Error, Result}; +use crate::segment::Segment; +use proc_macro::{ + Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, +}; +use std::char; +use std::iter; +use std::panic; +use std::str::FromStr; + +#[proc_macro] +pub fn paste(input: TokenStream) -> TokenStream { + let mut contains_paste = false; + let flatten_single_interpolation = true; + match expand( + input.clone(), + &mut contains_paste, + flatten_single_interpolation, + ) { + Ok(expanded) => { + if contains_paste { + expanded + } else { + input + } + } + Err(err) => err.to_compile_error(), + } +} + +#[doc(hidden)] +#[proc_macro] +pub fn item(input: TokenStream) -> TokenStream { + paste(input) +} + +#[doc(hidden)] +#[proc_macro] +pub fn expr(input: TokenStream) -> TokenStream { + paste(input) +} + +fn expand( + input: TokenStream, + contains_paste: &mut bool, + flatten_single_interpolation: bool, +) -> Result { + let mut expanded = TokenStream::new(); + let mut lookbehind = Lookbehind::Other; + let mut prev_none_group = None::; + let mut tokens = input.into_iter().peekable(); + loop { + let token = tokens.next(); + if let Some(group) = prev_none_group.take() { + if match (&token, tokens.peek()) { + (Some(TokenTree::Punct(fst)), Some(TokenTree::Punct(snd))) => { + fst.as_char() == ':' && snd.as_char() == ':' && fst.spacing() == Spacing::Joint + } + _ => false, + } { + expanded.extend(group.stream()); + *contains_paste = true; + } else { + expanded.extend(iter::once(TokenTree::Group(group))); + } + } + match token { + Some(TokenTree::Group(group)) => { + let delimiter = group.delimiter(); + let content = group.stream(); + let span = group.span(); + if delimiter == Delimiter::Bracket && is_paste_operation(&content) { + let segments = parse_bracket_as_segments(content, span)?; + let pasted = segment::paste(&segments)?; + let tokens = pasted_to_tokens(pasted, span)?; + expanded.extend(tokens); + *contains_paste = true; + } else if flatten_single_interpolation + && delimiter == Delimiter::None + && is_single_interpolation_group(&content) + { + expanded.extend(content); + *contains_paste = true; + } else { + let mut group_contains_paste = false; + let is_attribute = delimiter == Delimiter::Bracket + && (lookbehind == Lookbehind::Pound || lookbehind == Lookbehind::PoundBang); + let mut nested = expand( + content, + &mut group_contains_paste, + flatten_single_interpolation && !is_attribute, + )?; + if is_attribute { + nested = expand_attr(nested, span, &mut group_contains_paste)?; + } + let group = if group_contains_paste { + let mut group = Group::new(delimiter, nested); + group.set_span(span); + *contains_paste = true; + group + } else { + group.clone() + }; + if delimiter != Delimiter::None { + expanded.extend(iter::once(TokenTree::Group(group))); + } else if lookbehind == Lookbehind::DoubleColon { + expanded.extend(group.stream()); + *contains_paste = true; + } else { + prev_none_group = Some(group); + } + } + lookbehind = Lookbehind::Other; + } + Some(TokenTree::Punct(punct)) => { + lookbehind = match punct.as_char() { + ':' if lookbehind == Lookbehind::JointColon => Lookbehind::DoubleColon, + ':' if punct.spacing() == Spacing::Joint => Lookbehind::JointColon, + '#' => Lookbehind::Pound, + '!' if lookbehind == Lookbehind::Pound => Lookbehind::PoundBang, + _ => Lookbehind::Other, + }; + expanded.extend(iter::once(TokenTree::Punct(punct))); + } + Some(other) => { + lookbehind = Lookbehind::Other; + expanded.extend(iter::once(other)); + } + None => return Ok(expanded), + } + } +} + +#[derive(PartialEq)] +enum Lookbehind { + JointColon, + DoubleColon, + Pound, + PoundBang, + Other, +} + +// https://github.com/dtolnay/paste/issues/26 +fn is_single_interpolation_group(input: &TokenStream) -> bool { + #[derive(PartialEq)] + enum State { + Init, + Ident, + Literal, + Apostrophe, + Lifetime, + Colon1, + Colon2, + } + + let mut state = State::Init; + for tt in input.clone() { + state = match (state, &tt) { + (State::Init, TokenTree::Ident(_)) => State::Ident, + (State::Init, TokenTree::Literal(_)) => State::Literal, + (State::Init, TokenTree::Punct(punct)) if punct.as_char() == '\'' => State::Apostrophe, + (State::Apostrophe, TokenTree::Ident(_)) => State::Lifetime, + (State::Ident, TokenTree::Punct(punct)) + if punct.as_char() == ':' && punct.spacing() == Spacing::Joint => + { + State::Colon1 + } + (State::Colon1, TokenTree::Punct(punct)) + if punct.as_char() == ':' && punct.spacing() == Spacing::Alone => + { + State::Colon2 + } + (State::Colon2, TokenTree::Ident(_)) => State::Ident, + _ => return false, + }; + } + + state == State::Ident || state == State::Literal || state == State::Lifetime +} + +fn is_paste_operation(input: &TokenStream) -> bool { + let mut tokens = input.clone().into_iter(); + + match &tokens.next() { + Some(TokenTree::Punct(punct)) if punct.as_char() == '<' => {} + _ => return false, + } + + let mut has_token = false; + loop { + match &tokens.next() { + Some(TokenTree::Punct(punct)) if punct.as_char() == '>' => { + return has_token && tokens.next().is_none(); + } + Some(_) => has_token = true, + None => return false, + } + } +} + +fn parse_bracket_as_segments(input: TokenStream, scope: Span) -> Result> { + let mut tokens = input.into_iter().peekable(); + + match &tokens.next() { + Some(TokenTree::Punct(punct)) if punct.as_char() == '<' => {} + Some(wrong) => return Err(Error::new(wrong.span(), "expected `<`")), + None => return Err(Error::new(scope, "expected `[< ... >]`")), + } + + let mut segments = segment::parse(&mut tokens)?; + + match &tokens.next() { + Some(TokenTree::Punct(punct)) if punct.as_char() == '>' => {} + Some(wrong) => return Err(Error::new(wrong.span(), "expected `>`")), + None => return Err(Error::new(scope, "expected `[< ... >]`")), + } + + if let Some(unexpected) = tokens.next() { + return Err(Error::new( + unexpected.span(), + "unexpected input, expected `[< ... >]`", + )); + } + + for segment in &mut segments { + if let Segment::String(string) = segment { + if string.value.starts_with("'\\u{") { + let hex = &string.value[4..string.value.len() - 2]; + if let Ok(unsigned) = u32::from_str_radix(hex, 16) { + if let Some(ch) = char::from_u32(unsigned) { + string.value.clear(); + string.value.push(ch); + continue; + } + } + } + if string.value.contains(&['\\', '.', '+'][..]) + || string.value.starts_with("b'") + || string.value.starts_with("b\"") + || string.value.starts_with("br\"") + { + return Err(Error::new(string.span, "unsupported literal")); + } + let mut range = 0..string.value.len(); + if string.value.starts_with("r\"") { + range.start += 2; + range.end -= 1; + } else if string.value.starts_with(&['"', '\''][..]) { + range.start += 1; + range.end -= 1; + } + string.value = string.value[range].replace('-', "_"); + } + } + + Ok(segments) +} + +fn pasted_to_tokens(mut pasted: String, span: Span) -> Result { + let mut raw_mode = false; + let mut tokens = TokenStream::new(); + + if pasted.starts_with(|ch: char| ch.is_ascii_digit()) { + let literal = match panic::catch_unwind(|| Literal::from_str(&pasted)) { + Ok(Ok(literal)) => TokenTree::Literal(literal), + Ok(Err(LexError { .. })) | Err(_) => { + return Err(Error::new( + span, + &format!("`{:?}` is not a valid literal", pasted), + )); + } + }; + tokens.extend(iter::once(literal)); + return Ok(tokens); + } + + if pasted.starts_with('\'') { + let mut apostrophe = TokenTree::Punct(Punct::new('\'', Spacing::Joint)); + apostrophe.set_span(span); + tokens.extend(iter::once(apostrophe)); + pasted.remove(0); + } + + if pasted.starts_with("r#") { + raw_mode = true; + } + + let ident = match panic::catch_unwind(|| { + if raw_mode { + let mut spasted = pasted.clone(); + spasted.remove(0); + spasted.remove(0); + Ident::new_raw(&spasted, span) + } else { + Ident::new(&pasted, span) + } + }) { + Ok(ident) => TokenTree::Ident(ident), + Err(_) => { + return Err(Error::new( + span, + &format!("`{:?}` is not a valid identifier", pasted), + )); + } + }; + + tokens.extend(iter::once(ident)); + Ok(tokens) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/segment.rs clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/segment.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/src/segment.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/src/segment.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,281 @@ +use crate::error::{Error, Result}; +use proc_macro::{token_stream, Delimiter, Ident, Span, TokenTree}; +use std::iter::Peekable; + +pub(crate) enum Segment { + String(LitStr), + Apostrophe(Span), + Env(LitStr), + Modifier(Colon, Ident), +} + +pub(crate) struct LitStr { + pub value: String, + pub span: Span, +} + +pub(crate) struct Colon { + pub span: Span, +} + +pub(crate) fn parse(tokens: &mut Peekable) -> Result> { + let mut segments = Vec::new(); + while match tokens.peek() { + None => false, + Some(TokenTree::Punct(punct)) => punct.as_char() != '>', + Some(_) => true, + } { + match tokens.next().unwrap() { + TokenTree::Ident(ident) => { + let mut fragment = ident.to_string(); + if fragment.starts_with("r#") { + fragment = fragment.split_off(2); + } + if fragment == "env" + && match tokens.peek() { + Some(TokenTree::Punct(punct)) => punct.as_char() == '!', + _ => false, + } + { + let bang = tokens.next().unwrap(); // `!` + let expect_group = tokens.next(); + let parenthesized = match &expect_group { + Some(TokenTree::Group(group)) + if group.delimiter() == Delimiter::Parenthesis => + { + group + } + Some(wrong) => return Err(Error::new(wrong.span(), "expected `(`")), + None => { + return Err(Error::new2( + ident.span(), + bang.span(), + "expected `(` after `env!`", + )); + } + }; + let mut inner = parenthesized.stream().into_iter(); + let lit = match inner.next() { + Some(TokenTree::Literal(lit)) => lit, + Some(wrong) => { + return Err(Error::new(wrong.span(), "expected string literal")) + } + None => { + return Err(Error::new2( + ident.span(), + parenthesized.span(), + "expected string literal as argument to env! macro", + )) + } + }; + let lit_string = lit.to_string(); + if lit_string.starts_with('"') + && lit_string.ends_with('"') + && lit_string.len() >= 2 + { + // TODO: maybe handle escape sequences in the string if + // someone has a use case. + segments.push(Segment::Env(LitStr { + value: lit_string[1..lit_string.len() - 1].to_owned(), + span: lit.span(), + })); + } else { + return Err(Error::new(lit.span(), "expected string literal")); + } + if let Some(unexpected) = inner.next() { + return Err(Error::new( + unexpected.span(), + "unexpected token in env! macro", + )); + } + } else { + segments.push(Segment::String(LitStr { + value: fragment, + span: ident.span(), + })); + } + } + TokenTree::Literal(lit) => { + segments.push(Segment::String(LitStr { + value: lit.to_string(), + span: lit.span(), + })); + } + TokenTree::Punct(punct) => match punct.as_char() { + '_' => segments.push(Segment::String(LitStr { + value: "_".to_owned(), + span: punct.span(), + })), + '\'' => segments.push(Segment::Apostrophe(punct.span())), + ':' => { + let colon_span = punct.span(); + let colon = Colon { span: colon_span }; + let ident = match tokens.next() { + Some(TokenTree::Ident(ident)) => ident, + wrong => { + let span = wrong.as_ref().map_or(colon_span, TokenTree::span); + return Err(Error::new(span, "expected identifier after `:`")); + } + }; + segments.push(Segment::Modifier(colon, ident)); + } + '#' => segments.push(Segment::String(LitStr { + value: "#".to_string(), + span: punct.span(), + })), + _ => return Err(Error::new(punct.span(), "unexpected punct")), + }, + TokenTree::Group(group) => { + if group.delimiter() == Delimiter::None { + let mut inner = group.stream().into_iter().peekable(); + let nested = parse(&mut inner)?; + if let Some(unexpected) = inner.next() { + return Err(Error::new(unexpected.span(), "unexpected token")); + } + segments.extend(nested); + } else { + return Err(Error::new(group.span(), "unexpected token")); + } + } + } + } + Ok(segments) +} + +pub(crate) fn paste(segments: &[Segment]) -> Result { + let mut evaluated = Vec::new(); + let mut is_lifetime = false; + + for (i, segment) in segments.iter().enumerate() { + match segment { + Segment::String(segment) => { + if segment.value.as_str() == "#" { + if i == 0 { + // Enable Raw mode + evaluated.push(String::from("r#")); + continue; + } + return Err(Error::new( + segment.span, + "`#` is reserved keyword and it enables the raw mode \ + (i.e. generate Raw Identifiers) and it is only allowed in \ + the beginning like `[< # ... >]`", + )); + } + evaluated.push(segment.value.clone()); + } + Segment::Apostrophe(span) => { + if is_lifetime { + return Err(Error::new(*span, "unexpected lifetime")); + } + is_lifetime = true; + } + Segment::Env(var) => { + let resolved = match std::env::var(&var.value) { + Ok(resolved) => resolved, + Err(_) => { + return Err(Error::new( + var.span, + &format!("no such env var: {:?}", var.value), + )); + } + }; + let resolved = resolved.replace('-', "_"); + evaluated.push(resolved); + } + Segment::Modifier(colon, ident) => { + let last = match evaluated.pop() { + Some(last) => last, + None => { + return Err(Error::new2(colon.span, ident.span(), "unexpected modifier")) + } + }; + match ident.to_string().as_str() { + "lower" => { + evaluated.push(last.to_lowercase()); + } + "upper" => { + evaluated.push(last.to_uppercase()); + } + "snake" => { + let mut acc = String::new(); + let mut prev = '_'; + for ch in last.chars() { + if ch.is_uppercase() && prev != '_' { + acc.push('_'); + } + acc.push(ch); + prev = ch; + } + evaluated.push(acc.to_lowercase()); + } + "camel" | "upper_camel" | "lower_camel" => { + let mut is_lower_camel = ident.to_string().as_str() == "lower_camel"; + let mut acc = String::new(); + let mut prev = '_'; + for ch in last.chars() { + if ch != '_' { + if prev == '_' { + if is_lower_camel { + for chl in ch.to_lowercase() { + acc.push(chl); + } + is_lower_camel = false; + } else { + for chu in ch.to_uppercase() { + acc.push(chu); + } + } + } else if prev.is_uppercase() { + for chl in ch.to_lowercase() { + acc.push(chl); + } + } else { + acc.push(ch); + } + } + prev = ch; + } + evaluated.push(acc); + } + "camel_edge" => { + let mut acc = String::new(); + let mut prev = '_'; + for ch in last.chars() { + if ch != '_' { + if prev == '_' { + for chu in ch.to_uppercase() { + acc.push(chu); + } + } else if prev.is_uppercase() { + for chl in ch.to_lowercase() { + acc.push(chl); + } + } else { + acc.push(ch); + } + } else if prev == '_' { + acc.push(ch); + } + prev = ch; + } + evaluated.push(acc); + } + _ => { + return Err(Error::new2( + colon.span, + ident.span(), + "unsupported modifier", + )); + } + } + } + } + } + + let mut pasted = evaluated.into_iter().collect::(); + if is_lifetime { + pasted.insert(0, '\''); + } + Ok(pasted) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pastey/test.sh clamav-1.4.6+dfsg/.cargo/vendor/pastey/test.sh --- clamav-1.4.3+dfsg/.cargo/vendor/pastey/test.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pastey/test.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e # Exit immediately if any command exits with a non-zero status + +# This is a Temporary Fix for CI fail as CI fails on nightly toolchain due to some formatting issues which I am unable +# to reproduce locally. +# +# For more info, check https://github.com/AS1100K/pastey/pull/15 +if [[ "$1" == "nightly" ]]; then + cp pastey-test-suite/tests/ui/case-warning.nightly.stderr pastey-test-suite/tests/ui/case-warning.stderr + cp pastey-test-suite/tests/ui/raw-mode-wrong-position.nightly.stderr pastey-test-suite/tests/ui/raw-mode-wrong-position.stderr +else + cp pastey-test-suite/tests/ui/case-warning.stable.stderr pastey-test-suite/tests/ui/case-warning.stderr + cp pastey-test-suite/tests/ui/raw-mode-wrong-position.stable.stderr pastey-test-suite/tests/ui/raw-mode-wrong-position.stderr +fi + +echo "========================================" +echo "Running tests with pastey crate..." +echo "========================================" +cargo test + +echo "========================================" +echo "Running tests with pastey-test-suite crate..." +echo "========================================" +cd pastey-test-suite +cargo test +rm ./tests/ui/case-warning.stderr +rm ./tests/ui/raw-mode-wrong-position.stderr +cd ../ + +cd paste-compat +./test.sh +cd ../ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/peeking_take_while/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/peeking_take_while/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"caf1a07b54869ad1b35394c5b9262fe1e8f63b7ab85bf517ad6d59c1ad1d64bc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"9f7659439d3e98a3aae69562648a651e49eeac7152f489deb77dd09c0c8010d0","src/lib.rs":"699149181f71aa88dc6585bd047fc29c6f5baba2b8bf5fbd1c5612966322b379"},"package":"19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"} \ No newline at end of file +{"files":{".travis.yml":"9871eecb27ad6d76270d75534bd54581fab2a4feae93d114ae65a287ffbad5fe","Cargo.toml":"caf1a07b54869ad1b35394c5b9262fe1e8f63b7ab85bf517ad6d59c1ad1d64bc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"9f7659439d3e98a3aae69562648a651e49eeac7152f489deb77dd09c0c8010d0","src/lib.rs":"699149181f71aa88dc6585bd047fc29c6f5baba2b8bf5fbd1c5612966322b379"},"package":"19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/peeking_take_while/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/peeking_take_while/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/peeking_take_while/.travis.yml 2017-05-16 23:26:02.000000000 +0000 @@ -0,0 +1,18 @@ +sudo: false +language: rust + +rust: + - stable + - beta + - nightly + +cache: cargo + +env: + matrix: + - PROFILE="" + - PROFILE="--release" + +script: + - cargo build $PROFILE --verbose + - cargo test $PROFILE --verbose diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/png/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGES.md":"a53250005c1da36d801ad997b8ce14f3814c741d136d5eebf9ebb2b3cf826b61","Cargo.lock":"e1b4a061845139e1d54a0209c68b92ef1825d5f886298eec94cfb153254d0a53","Cargo.toml":"c15f47bc0da06ef4246a813c9171bcb8a41aee1a77c3ca385e8c4ce90179ad9a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"a87e2bc972068409cff0665241349c4eb72291b33d12ed97a09f97e9a2560655","benches/README.md":"0c60c3d497abdf6c032863aa47da41bc6bb4f5ff696d45dec0e6eb33459b14b0","benches/decoder.rs":"a54832d82a48bba09b588456c67b3d4f9202eab213ee47c65de0b87b00b65b44","benches/expand_paletted.rs":"945123a752835f13a4cc1c82470602183f9613c71b1e81f6a8096e2bb227423b","benches/unfilter.rs":"413392304afaf6e016924b582dd6dc0d39aa9e39acdcdec52cbd45326f92bfa2","examples/change-png-info.rs":"7cb5627bc8701a5acb28990bc9c98443d5a6edf73020c70bf3e73f176d4804c2","examples/corpus-bench.rs":"c1fcbf01b188b021798ae8406ee6fbe0678fbd46f2ffe7dfa743e6001cd28b9e","examples/png-generate.rs":"e4cca06b9cc3291b52261d88a2e016940620b613fc1402bb54ccc68f73026a96","examples/pngcheck.rs":"7a5cb4cbb4d166f4337ff69a9e4b16783dce482a56ca56a709bf636d8f3bb981","examples/show.rs":"5c4d5231bafca9c6c01d930792b69f30c659eb6214d78f55f649ed2ca1880ae0","src/adam7.rs":"62851c15b0591004a9add076a349d1c0f08d8555eb21211cd4a620f8fa178a7c","src/benchable_apis.rs":"bb5176efe8b44ed9d9edab7059a53cfba8e384e884517eaba1f4a7597641121f","src/chunk.rs":"eff04345e9af621ce51a9141f35657262ee1a891e724332a80ac40eec90a2c45","src/common.rs":"98e14532e8fb83aa744fcfd321cbaf47f99f29bbc3b0b59b009634012b42af4a","src/decoder/mod.rs":"4f6b7ddafc01e4e84afb216ba0995d94db6a216deb31b88d269675eb4feefe3d","src/decoder/stream.rs":"93c403bb9f008e2efe9f50733908e1b9f1be2f9f168d5fbe6caed660d84e2f85","src/decoder/transform.rs":"250058f36f63a3b4fe46f5f777359f24e4328d2767f7341f337df08d7e9a2481","src/decoder/transform/palette.rs":"f0d2e3de33d4fe26135f1ebcaeaebf2ffc490de8766bed254a975552aa44576b","src/decoder/zlib.rs":"f76341b9ec50a9cb0e8326fdea26ef967f09a4700761d135675328bc1af32fce","src/encoder.rs":"69e3e12aef222f7a01bf60af5f1c6bbd1b016acbf338eac2b084b22869595c1d","src/filter.rs":"48174721ad77b9319bd996cbb562df97b912cde058addfe7b46b04bd6c34d834","src/lib.rs":"586f0f5fe369f4be7f0e363d41c3adba06abe45115b51e8afd214bbe994d9d33","src/srgb.rs":"da1609902064016853410633926d316b5289d4bbe1fa469b21f116c1c1b2c18e","src/test_utils.rs":"4b25339d91ef71ce1bb67d3f68d742a41c64c11042247fe9dfa231457642788f","src/text_metadata.rs":"b73fec5d6009b08374eb137dbf906d5d75792f5a6c7249d601bdfc51c31f5749","src/traits.rs":"79d357244e493f5174ca11873b0d5c443fd4a5e6e1f7c6df400a1767c5ad05b2"},"package":"06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a91fcad138a986e75f1b1969eb9a7ea09f54c3e8ba0e980506935a0694fd55cf","CHANGES.md":"10f69a3816c2e3ad5000190eacbfbdff49443a1ea4e857c0d76f47b90bfa6f4a","Cargo.lock":"ec5134bceca1b6cb6106843edad4abd9b17f4e11c095a622a2c4924f172187bf","Cargo.toml":"49f6371a3cb2902abffd8f1695d76ffa4c73c5c50c9302f799b9f31f9b45bb36","Cargo.toml.orig":"b0b9532d5a2b9103fac3d1ce049d7270de530a8182e9bbb033cc02d3f1741a5e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"2a69e61783cf6433b712acfe5b32ba1c539f947ccd00b1c07312d5eec3445b46","benches/README.md":"0c60c3d497abdf6c032863aa47da41bc6bb4f5ff696d45dec0e6eb33459b14b0","benches/adam7.rs":"ac81f74f2547790f85b09344d79f881718353b31bcb39402b115582df408701c","benches/decoder.rs":"390e75054ee3a4237a57aa255ac35429f3d81c1d2fc18bd0464fbc13e85b1f8c","benches/expand_paletted.rs":"945123a752835f13a4cc1c82470602183f9613c71b1e81f6a8096e2bb227423b","benches/unfilter.rs":"9186de79e6eef9df127f22051180c8286b75a7409c9d13b15be63dd1ad62e3f9","examples/change-png-info.rs":"bc4f3d7af7cee03714e80c3d58f5633f24b3406721af8eedd0a72ac78da6356f","examples/corpus-bench.rs":"b994744b00335536903408bc95fa203b637ee5401e568b6043d1e86fd234007e","examples/png-generate.rs":"e4cca06b9cc3291b52261d88a2e016940620b613fc1402bb54ccc68f73026a96","examples/pngcheck.rs":"575084dc9fe8754677f9875c0b1790c3f52adb58c19de63b59d28f6fea47dd71","src/adam7.rs":"60cb6d675d95a0f193b0aadf38c43404d38a726f4dec63d13e0744a8db4c384c","src/benchable_apis.rs":"be9c486ebaaa698517b7c0ac5c4d9ecf812eee4e6454bd32dfcb790048b3a0f9","src/chunk.rs":"3bfd87e49b951e0ec4372e34d6374a4813cb499f89104f2a20e109c95b63a2ac","src/common.rs":"f7289605ac9034a31033a844d8abc6c362f23fcd19cbf636b5bd5e191a0c4d53","src/decoder/interlace_info.rs":"ab953aabc548af9bdafdefcaeacf19bced6010ea15831039d47715661010c1d2","src/decoder/mod.rs":"db5e8258b9517cea28188f6d43a387cc161454f758c6e29449d8b7476f5866cd","src/decoder/read_decoder.rs":"ddde714e6ee17298850f934fd2328f7095cd3c9d096930867edef0bfab91cc5d","src/decoder/stream.rs":"80f529c8924e72cf8c72f0671aa2327939e3fe688e8b4b22c79983593e69b65b","src/decoder/transform.rs":"3ec21b666d543fc6e2203313663a0214837cb5dc5bdb32d4a3c23d4a8567cecf","src/decoder/transform/palette.rs":"8eed7854aa122c1ecf8f3f41e2cccdc08d60a0c323f3ef16c3dd5f1710bde38a","src/decoder/unfiltering_buffer.rs":"d8753a284cf2f962bc56bf8f22ea8aba763b5f04734860e9515768e056091bd6","src/decoder/zlib.rs":"c6b6df0d1ff9b7aa6fea6636eda49ddfa2952c88f71208950706b6368e7da999","src/encoder.rs":"31cfcb7f39b1ec4495a906046819d52405aab3f21fc9bef2b2c2228aa5fb40a1","src/filter.rs":"1d3e23c1914723fc6e86a3c34a0c9af97fe776e0050ed6d733976af6f9fd1ac8","src/lib.rs":"750d56a7859502bf55e8f4050621f097e5c5ef36bd2be88f44aa44b7a1adc67c","src/srgb.rs":"da1609902064016853410633926d316b5289d4bbe1fa469b21f116c1c1b2c18e","src/test_utils.rs":"9002657a02768d68fef55041629f4b0067570fa93e2ed91e40367dca60eed91c","src/text_metadata.rs":"1df449a40f1798daf5b77195cccc644d3d5ae0e5cc629d71b5399b457b1438a8","src/traits.rs":"79d357244e493f5174ca11873b0d5c443fd4a5e6e1f7c6df400a1767c5ad05b2"},"package":"97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/png/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7d4c1b0866089f2eefdae5e9b44c521d52e5d348" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/CHANGES.md clamav-1.4.6+dfsg/.cargo/vendor/png/CHANGES.md --- clamav-1.4.3+dfsg/.cargo/vendor/png/CHANGES.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/CHANGES.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,107 @@ -## Unreleased +## 0.18.0 + +### API Breaking Changes + +* Removed deprecated `Info::encode` and `Encoder::set_srgb` methods. +* Improved the compression settings API for encoding. +* `Decoder` now requires a reader that implements `Seek` and `BufRead` traits. +* Bump bitflags dependency to 2.0. +* `StreamingDecoder::update` now takes a structured `UnfilterBuf` argument + instead of a direct reference to a vector. This allows in-place + decompression. There is a public constructor for `UnfilterBuf`. +* The methods `Decoder::output_buffer_size` and `output_line_size` now return + `Option` to reflect that these calculations no longer overflow on some + targets where the required buffers can not be represented in the address + space. They return the mathematically correct size where possible. +* The `Decoded` enum returned from `StreamingDecoder::update` was simplified to + no longer contains any chunk payload data. Instead, it now contains only + chunk events where every chunk that was started will eventually be ended by + `ChunkComplete`, `BadAncillaryChunk` or `SkippedAncillaryChunk`. +* Ancillary chunks, i.e. those not critical to decoder interpretation of the + file, which fail to parse are now terminated with a `BadAncillaryChunk` event + but no longer returned a `DecodingError`. This includes text chunks as well + as many metadata chunks (except for `fcTL` that we deem crucial to the + parser's understanding of the image sequence in an APNG despite being + technically ancillary). + +### Additions + +* Added `Reader::read_row` method. +* Add support for parsing eXIf chunk. +* Treat most auxiliary chunk errors as benign. +* Added `splat_interlaced_row`, which implements an alternative method for + merging Adam7 interlaced lines into the output buffer that is more suitable + for the presentation of progressive states of the buffer. +* Added `Adam7Variant` documenting the various methods for applying interlaced + rows and to prepare an API to progressively read frames through `Decoder`. + +### Changes + +* The decoding of Adam7 interlaced data is now much faster. +* The `acTL` chunk is now ignored when it is invalid, instead of producing + errors while reading or decoding the following APNG chunks. +* The requirement of the `fcTL` chunk for the default image to match the IHDR's + indicate image size is now enforced. +* More minor format errors in auxiliary chunks are now ignored by the decoder, + instead disregarding the malformed chunk. +* Adam7 Interlacing on 32-bit targets now handles some cases correctly that + previously wrote some bytes to the wrong pixel indices due to overflows. + +## 0.17.16 + +* Make gAMA and cHRM fallback optional for sRGB ([#547]) +* Pass through nightly feature to crc32fast crate to get SIMD crc32 on Aarch64 ([#545]) +* Fix bug in iCCP chunk encoding ([#458]) +* Deprecate Info::encode ([#550]) + +[#545]: https://github.com/image-rs/image-png/pull/545 +[#458]: https://github.com/image-rs/image-png/pull/548 +[#550]: https://github.com/image-rs/image-png/pull/550 +[#547]: https://github.com/image-rs/image-png/pull/547 + +## 0.17.15 + +### Added + +* Add a public API to advance to the next frame in APNG decoder ([#518]) +* Add APIs to write ICC and EXIF chunks ([#526]) +* Add support for parsing the sBIT chunk ([#524]) +* Add support for parsing the bKGD chunk ([#538]) +* Add support for parsing the cICP chunk ([#529]) +* Add support for parsing mDCV and cLLI chunks ([#528], ([#543])) + +### Changed + +* Improve performance of Paeth filter during decoding ([#512], [#539]) + +### Fixed + +* Avoid an infinite loop when retrying after a fatal error using `StreamingDecoder` ([#520]) +* Fixed chunk order in encoded files ([#526]) + +[#495]: https://github.com/image-rs/image-png/pull/495 +[#496]: https://github.com/image-rs/image-png/pull/496 +[#512]: https://github.com/image-rs/image-png/pull/512 +[#518]: https://github.com/image-rs/image-png/pull/518 +[#520]: https://github.com/image-rs/image-png/pull/520 +[#524]: https://github.com/image-rs/image-png/pull/524 +[#526]: https://github.com/image-rs/image-png/pull/526 +[#528]: https://github.com/image-rs/image-png/pull/528 +[#529]: https://github.com/image-rs/image-png/pull/529 +[#538]: https://github.com/image-rs/image-png/pull/538 +[#539]: https://github.com/image-rs/image-png/pull/539 +[#543]: https://github.com/image-rs/image-png/pull/543 + +## 0.17.14 + +* Updated to miniz_oxide 0.8.0. +* Added public API to consume interlaced rows one by one ([#495]) +* Improved support for resuming decoding after an `UnexpectedEof`, which lets you start parsing a file before it's fully received over the network ([#496]) +* Fixed some broken links in documentation, improved some documentation comments + +[#495]: https://github.com/image-rs/image-png/pull/495 +[#496]: https://github.com/image-rs/image-png/pull/496 + ## 0.17.13 @@ -19,7 +122,7 @@ * Added `new_with_info` constructor for encoder. * Removed hard-coded memory limits. * No longer allow zero sized images. -* Added `Reader::finish` to read all the auxillary chunks that comes after the +* Added `Reader::finish` to read all the auxiliary chunks that comes after the image. ## 0.17.10 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -1,30 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.1.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "anes" @@ -33,78 +15,81 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] -name = "arrayref" -version = "0.3.7" +name = "anstream" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] [[package]] -name = "arrayvec" -version = "0.5.2" +name = "anstyle" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle-parse" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "utf8parse", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "anstyle-query" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] [[package]] -name = "backtrace" -version = "0.3.69" +name = "anstyle-wincon" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "anstyle", + "once_cell_polyfill", + "windows-sys", ] [[package]] -name = "bitflags" -version = "1.3.2" +name = "approx" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] [[package]] -name = "bitflags" -version = "2.4.1" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "block" -version = "0.1.6" +name = "bitflags" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytemuck" -version = "1.14.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byteorder" @@ -113,54 +98,22 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "calloop" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e0d00eb1ea24371a97d2da6201c6747a633dc6dc1988ef503403b4c59504a8" -dependencies = [ - "bitflags 1.3.2", - "log", - "nix 0.25.1", - "slotmap", - "thiserror", - "vec_map", -] - -[[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cgl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] - -[[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -169,15 +122,15 @@ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -185,162 +138,49 @@ [[package]] name = "clap" -version = "3.2.25" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ - "atty", - "bitflags 1.3.2", + "clap_builder", "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +dependencies = [ + "anstream", + "anstyle", "clap_lex", - "indexmap 1.9.3", - "once_cell", "strsim", - "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.25" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - -[[package]] -name = "cocoa" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics 0.22.3", - "foreign-types 0.3.2", - "libc", - "objc", -] - -[[package]] -name = "cocoa" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics 0.23.1", - "foreign-types 0.5.0", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation", - "core-graphics-types", - "libc", - "objc", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.5.0", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - -[[package]] -name = "core-text" -version = "20.1.0" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" -dependencies = [ - "core-foundation", - "core-graphics 0.23.1", - "foreign-types 0.5.0", - "libc", -] +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "crc32fast" @@ -353,25 +193,22 @@ [[package]] name = "criterion" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" dependencies = [ "anes", - "atty", "cast", "ciborium", "clap", "criterion-plot", "itertools", - "lazy_static", "num-traits", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -379,417 +216,123 @@ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", "itertools", ] [[package]] -name = "crossbeam-deque" -version = "0.8.5" +name = "crossbeam-channel" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ - "crossbeam-epoch", + "cfg-if", "crossbeam-utils", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.18" +name = "crossbeam-deque" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ + "cfg-if", + "crossbeam-epoch", "crossbeam-utils", ] [[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crossfont" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb5a3822b594afc99b503cc1859b94686d3c3efdd60507a28587dab80ee1071" -dependencies = [ - "cocoa 0.25.0", - "core-foundation", - "core-foundation-sys", - "core-graphics 0.23.1", - "core-text", - "dwrote", - "foreign-types 0.5.0", - "freetype-rs", - "libc", - "log", - "objc", - "once_cell", - "pkg-config", - "servo-fontconfig", - "winapi", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" +name = "crossbeam-epoch" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" dependencies = [ "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading 0.8.1", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "dwrote" -version = "0.11.0" +name = "crossbeam-utils" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ + "cfg-if", "lazy_static", - "libc", - "serde", - "serde_derive", - "winapi", - "wio", ] [[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "equivalent" -version = "1.0.1" +name = "crunchy" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] -name = "expat-sys" -version = "2.1.6" +name = "either" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] [[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared 0.3.1", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "freetype-rs" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb" -dependencies = [ - "bitflags 1.3.2", - "freetype-sys", - "libc", -] - -[[package]] -name = "freetype-sys" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] name = "getrandom" -version = "0.2.12" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", + "r-efi", "wasi", ] [[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - -[[package]] -name = "glium" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2766728ecb86014b91d3d687614b32d65aacbbdc887f424a7b03cba3ab593bf" -dependencies = [ - "backtrace", - "fnv", - "gl_generator", - "glutin", - "lazy_static", - "memoffset", - "smallvec", - "takeable-option", -] - -[[package]] name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "glutin" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444c9ad294fdcaf20ccf6726b78f380b5450275540c9b68ab62f49726ad1c713" -dependencies = [ - "cgl", - "cocoa 0.24.1", - "core-foundation", - "glutin_egl_sys", - "glutin_gles2_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "libloading 0.7.4", - "log", - "objc", - "once_cell", - "osmesa-sys", - "parking_lot", - "raw-window-handle 0.5.2", - "wayland-client", - "wayland-egl", - "winapi", - "winit", -] - -[[package]] -name = "glutin_egl_sys" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68900f84b471f31ea1d1355567eb865a2cf446294f06cef8d653ed7bcf5f013d" -dependencies = [ - "gl_generator", - "winapi", -] - -[[package]] -name = "glutin_gles2_sys" -version = "0.1.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103" -dependencies = [ - "gl_generator", - "objc", -] +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] -name = "glutin_glx_sys" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93d0575865098580c5b3a423188cd959419912ea60b1e48e8b3b526f6d02468" -dependencies = [ - "gl_generator", - "x11-dl", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.1.5" +name = "half" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ - "gl_generator", + "cfg-if", + "crunchy", ] [[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -801,80 +344,37 @@ ] [[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "instant" -version = "0.1.12" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jni-sys" -version = "0.3.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -882,80 +382,33 @@ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall", -] - -[[package]] -name = "lock_api" -version = "0.4.11" +name = "libz-rs-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a" dependencies = [ - "autocfg", - "scopeguard", + "zlib-rs", ] [[package]] name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "malloc_buf" -version = "0.0.6" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "libc", + "cfg-if", ] [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memoffset" @@ -968,162 +421,44 @@ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] -name = "mio" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle 0.5.2", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-glue" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" -dependencies = [ - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", - "once_cell", - "parking_lot", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - -[[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] [[package]] -name = "num_enum" -version = "0.5.11" +name = "num_cpus" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", + "hermit-abi", + "libc", ] [[package]] -name = "object" -version = "0.32.2" +name = "once_cell" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] -name = "once_cell" -version = "1.19.0" +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "oorandom" @@ -1132,60 +467,10 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "osmesa-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" -dependencies = [ - "shared_library", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pkg-config" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" - -[[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -1196,125 +481,81 @@ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "png" -version = "0.17.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +version = "0.18.0" dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "png" -version = "0.17.13" -dependencies = [ - "bitflags 1.3.2", + "approx", + "bitflags", "byteorder", "clap", "crc32fast", "criterion", "fdeflate", "flate2", - "getopts", - "glium", "glob", "miniz_oxide", "rand", - "term", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] name = "rand" -version = "0.8.5" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -1322,123 +563,64 @@ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom", ] [[package]] -name = "raw-window-handle" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" -dependencies = [ - "cty", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] name = "rayon" -version = "1.8.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ + "autocfg", + "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ + "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox", - "thiserror", + "lazy_static", + "num_cpus", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rustc-demangle" -version = "0.1.23" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "safe_arch" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" -dependencies = [ - "bytemuck", -] +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -1450,153 +632,60 @@ ] [[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sctk-adwaita" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61270629cc6b4d77ec1907db1033d5c2e1a404c412743621981a871dc9c12339" -dependencies = [ - "crossfont", - "log", - "smithay-client-toolkit", - "tiny-skia", -] +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - -[[package]] -name = "shared_library" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" -dependencies = [ - "lazy_static", - "libc", -] - -[[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "smithay-client-toolkit" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" -dependencies = [ - "bitflags 1.3.2", - "calloop", - "dlib", - "lazy_static", - "log", - "memmap2", - "nix 0.24.3", - "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1604,83 +693,6 @@ ] [[package]] -name = "takeable-option" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ae8932fcfea38b7d3883ae2ab357b0d57a02caaa18ebb4f5ece08beaec4aa0" - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tiny-skia" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642680569bb895b16e4b9d181c60be1ed136fa0c9c7f11d004daf053ba89bf82" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "png 0.17.10", - "safe_arch", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c114d32f0c2ee43d585367cb013dfaba967ab9f62b90d9af0d696e955e70fa6c" -dependencies = [ - "arrayref", - "bytemuck", -] - -[[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1691,92 +703,68 @@ ] [[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - -[[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "vec_map" -version = "0.8.2" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] -name = "version_check" -version = "0.9.4" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", + "winapi", "winapi-util", ] [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1784,111 +772,31 @@ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" - -[[package]] -name = "wayland-client" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ - "bitflags 1.3.2", - "downcast-rs", - "libc", - "nix 0.24.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" -dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" -dependencies = [ - "nix 0.24.3", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-egl" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402de949f81a012926d821a2d659f930694257e76dd92b6e0042ceb27be4107d" -dependencies = [ - "wayland-client", - "wayland-sys", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" -dependencies = [ - "bitflags 1.3.2", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", + "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -1912,9 +820,9 @@ [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] @@ -1926,184 +834,96 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.36.1" +name = "windows-link" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.48.5", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] -name = "winit" -version = "0.27.5" +name = "wit-bindgen-rt" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb796d6fbd86b2fd896c9471e6f04d39d750076ebe5680a3958f00f5ab97657c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 1.3.2", - "cocoa 0.24.1", - "core-foundation", - "core-graphics 0.22.3", - "dispatch", - "instant", - "libc", - "log", - "mio", - "ndk", - "ndk-glue", - "objc", - "once_cell", - "parking_lot", - "percent-encoding", - "raw-window-handle 0.4.3", - "raw-window-handle 0.5.2", - "sctk-adwaita", - "smithay-client-toolkit", - "wasm-bindgen", - "wayland-client", - "wayland-protocols", - "web-sys", - "windows-sys 0.36.1", - "x11-dl", + "bitflags", ] [[package]] -name = "winnow" -version = "0.5.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" -dependencies = [ - "memchr", -] - -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "xcursor" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" - -[[package]] -name = "xml-rs" -version = "0.8.19" +name = "zlib-rs" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -10,11 +10,12 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" -rust-version = "1.57" +edition = "2021" +rust-version = "1.73" name = "png" -version = "0.17.13" +version = "0.18.0" authors = ["The image-rs Developers"] +build = false include = [ "/LICENSE-MIT", "/LICENSE-APACHE", @@ -24,31 +25,67 @@ "/examples/", "/benches/", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "PNG decoding and encoding library in pure Rust" readme = "README.md" categories = ["multimedia::images"] license = "MIT OR Apache-2.0" repository = "https://github.com/image-rs/image-png" +[features] +benchmarks = [] +unstable = ["crc32fast/nightly"] +zlib-rs = ["flate2/zlib-rs"] + +[lib] +name = "png" +path = "src/lib.rs" + +[[example]] +name = "change-png-info" +path = "examples/change-png-info.rs" + +[[example]] +name = "corpus-bench" +path = "examples/corpus-bench.rs" + +[[example]] +name = "png-generate" +path = "examples/png-generate.rs" + +[[example]] +name = "pngcheck" +path = "examples/pngcheck.rs" + +[[bench]] +name = "adam7" +path = "benches/adam7.rs" +harness = false +required-features = ["benchmarks"] + [[bench]] name = "decoder" path = "benches/decoder.rs" harness = false [[bench]] -name = "unfilter" -path = "benches/unfilter.rs" +name = "expand_paletted" +path = "benches/expand_paletted.rs" harness = false required-features = ["benchmarks"] [[bench]] -name = "expand_paletted" -path = "benches/expand_paletted.rs" +name = "unfilter" +path = "benches/unfilter.rs" harness = false required-features = ["benchmarks"] [dependencies.bitflags] -version = "1.0" +version = "2.0" [dependencies.crc32fast] version = "1.2.0" @@ -57,39 +94,37 @@ version = "0.3.3" [dependencies.flate2] -version = "1.0.11" +version = "1.0.35" [dependencies.miniz_oxide] -version = "0.7.1" +version = "0.8" features = ["simd"] +[dev-dependencies.approx] +version = "0.5.1" + [dev-dependencies.byteorder] version = "1.5.0" [dev-dependencies.clap] -version = "3.0" +version = "4.0" features = ["derive"] [dev-dependencies.criterion] -version = "0.4.0" - -[dev-dependencies.getopts] -version = "0.2.14" - -[dev-dependencies.glium] -version = "0.32" -features = ["glutin"] +version = "0.7.0" +features = ["cargo_bench_support"] default-features = false [dev-dependencies.glob] version = "0.3" [dev-dependencies.rand] -version = "0.8.4" +version = "0.9.2" -[dev-dependencies.term] -version = "0.7" +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.7.0" -[features] -benchmarks = [] -unstable = [] +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(fuzzing)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/png/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,75 @@ +[package] +name = "png" +version = "0.18.0" +license = "MIT OR Apache-2.0" + +description = "PNG decoding and encoding library in pure Rust" +categories = ["multimedia::images"] +authors = ["The image-rs Developers"] +repository = "https://github.com/image-rs/image-png" + +edition = "2021" +rust-version = "1.73" +include = [ + "/LICENSE-MIT", + "/LICENSE-APACHE", + "/README.md", + "/CHANGES.md", + "/src/", + "/examples/", + "/benches/", +] + +[dependencies] +bitflags = "2.0" +crc32fast = "1.2.0" +fdeflate = "0.3.3" +flate2 = "1.0.35" +miniz_oxide = { version = "0.8", features = ["simd"] } + +[dev-dependencies] +approx = "0.5.1" +byteorder = "1.5.0" +clap = { version = "4.0", features = ["derive"] } +criterion = { version = "0.7.0", default-features = false, features = ["cargo_bench_support"] } +glob = "0.3" +rand = "0.9.2" +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = "0.7.0" + +[features] +# Use nightly-only features for a minor performance boost in PNG decoding +unstable = ["crc32fast/nightly"] +# Use zlib-rs for faster PNG encoding at the cost of some `unsafe` code. +# WARNING: this changes the flate2 backend for your entire dependency tree! +# While the `png` crate always uses fully memory-safe decoding, +# this enables zlib-rs and introduces some unsafe code to all other crates +# that rely on flate2, including the decoding codepaths. +zlib-rs = ["flate2/zlib-rs"] +benchmarks = [] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } + +[[bench]] +path = "benches/decoder.rs" +name = "decoder" +harness = false + +[[bench]] +path = "benches/unfilter.rs" +name = "unfilter" +harness = false +required-features = ["benchmarks"] + +[[bench]] +path = "benches/adam7.rs" +name = "adam7" +harness = false +required-features = ["benchmarks"] + +[[bench]] +path = "benches/expand_paletted.rs" +name = "expand_paletted" +harness = false +required-features = ["benchmarks"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/README.md clamav-1.4.6+dfsg/.cargo/vendor/png/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/png/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -2,26 +2,19 @@ [![Build Status](https://github.com/image-rs/image-png/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-png/actions) [![Documentation](https://docs.rs/png/badge.svg)](https://docs.rs/png) [![Crates.io](https://img.shields.io/crates/v/png.svg)](https://crates.io/crates/png) -![Lines of Code](https://tokei.rs/b1/github/image-rs/image-png) [![License](https://img.shields.io/crates/l/png.svg)](https://github.com/image-rs/image-png) -[![fuzzit](https://app.fuzzit.dev/badge?org_id=image-rs)](https://app.fuzzit.dev/orgs/image-rs/dashboard) -PNG decoder/encoder in pure Rust. +Robust and performant PNG decoder/encoder in pure Rust. Also supports [APNG](https://en.wikipedia.org/wiki/APNG). -It contains all features required to handle the entirety of [the PngSuite by -Willem van Schack][PngSuite]. +No `unsafe` code, battle-tested, and fuzzed on [OSS-fuzz](https://github.com/google/oss-fuzz). -[PngSuite]: http://www.schaik.com/pngsuite2011/pngsuite.html +## Performance -## pngcheck +Performance is typically on par with or better than libpng. -The `pngcheck` utility is a small demonstration binary that checks and prints -metadata on every `.png` image provided via parameter. You can run it (for -example on the test directories) with +Includes a fast encoding mode powered by [fdeflate](https://crates.io/crates/fdeflate) that is dramatically faster than the fastest mode of libpng while *simultaneously* providing better compression ratio. -```bash -cargo run --release --example pngcheck ./tests/pngsuite/* -``` +On nightly Rust compiler you can slightly speed up decoding of some images by enabling the `unstable` feature of this crate. ## License diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/benches/adam7.rs clamav-1.4.6+dfsg/.cargo/vendor/png/benches/adam7.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/benches/adam7.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/benches/adam7.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +//! Usage example: +//! +//! ``` +//! $ alias bench="rustup run nightly cargo bench" +//! $ bench --bench=expand_adam7 --features=benchmarks -- --save-baseline my_baseline +//! ... tweak something, say the expansion of 8-bit ... +//! $ bench --bench=expand_adam7 --features=benchmarks -- bpp=8 --baseline my_baseline +//! ``` +use criterion::{criterion_group, criterion_main, Criterion, Throughput}; +use png::benchable_apis::adam7; + +fn expand_all(c: &mut Criterion) { + let expand_bpp = [1, 2, 4, 8, 16, 24, 32]; + let expand_size = [1 << 4, 1 << 8, 1 << 12]; + + for &bpp in expand_bpp.iter() { + for &sz in expand_size.iter() { + bench_group_expand_full(c, sz, bpp); + } + } +} + +criterion_group!(benches, expand_all); +criterion_main!(benches); + +fn bench_group_expand_full(c: &mut Criterion, sz: u32, bpp: u8) { + let mut group = c.benchmark_group("expand-adam7"); + + group.throughput(Throughput::Bytes( + u64::from(sz) * (u64::from(sz) * u64::from(bpp)).div_ceil(8), + )); + + let row_bytes = (sz as usize * usize::from(bpp)).div_ceil(8); + let buffer = vec![0u8; (sz as usize) * row_bytes]; + let buffer = core::cell::RefCell::new(buffer); + let rowdata = core::hint::black_box(vec![0u8; row_bytes]); + + group.bench_with_input(format!("size={sz:?}/bpp={bpp}"), &buffer, |b, img| { + b.iter(|| adam7(&mut *img.borrow_mut(), &rowdata, sz, sz, bpp)); + }); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/benches/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/png/benches/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/benches/decoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/benches/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -use std::fs; +use std::{fs, io::Cursor}; use criterion::{ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, Throughput, @@ -41,6 +41,13 @@ bench_noncompressed_png(&mut g, 2048, 0x7fffffff); // 16 MB bench_noncompressed_png(&mut g, 12288, 0x7fffffff); // 576 MB g.finish(); + + // Incremental decoding via `read_row` + let mut g = c.benchmark_group("row-by-row"); + let mut data = Vec::new(); + test_utils::write_noncompressed_png(&mut data, 128, 4096); + bench_read_row(&mut g, data, "128x128-4k-idat"); + g.finish(); } criterion_group! {benches, load_all} @@ -52,23 +59,14 @@ bench_file(g, data, format!("{size}x{size}.png")); } +/// This benchmarks decoding via a call to `Reader::next_frame`. fn bench_file(g: &mut BenchmarkGroup, data: Vec, name: String) { if data.len() > 1_000_000 { g.sample_size(10); } - fn create_reader(data: &[u8]) -> Reader<&[u8]> { - let mut decoder = Decoder::new(data); - - // Cover default transformations used by the `image` crate when constructing - // `image::codecs::png::PngDecoder`. - decoder.set_transformations(Transformations::EXPAND); - - decoder.read_info().unwrap() - } - let mut reader = create_reader(data.as_slice()); - let mut image = vec![0; reader.output_buffer_size()]; + let mut image = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.next_frame(&mut image).unwrap(); g.throughput(Throughput::Bytes(info.buffer_size() as u64)); @@ -79,3 +77,30 @@ }) }); } + +/// This benchmarks decoding via a sequence of `Reader::read_row` calls. +fn bench_read_row(g: &mut BenchmarkGroup, data: Vec, name: &str) { + let reader = create_reader(data.as_slice()); + let mut image = vec![0; reader.output_buffer_size().unwrap()]; + let bytes_per_row = reader.output_line_size(reader.info().width).unwrap(); + g.throughput(Throughput::Bytes(image.len() as u64)); + g.bench_with_input(name, &data, |b, data| { + b.iter(|| { + let mut reader = create_reader(data.as_slice()); + + for output_row in image.chunks_exact_mut(bytes_per_row) { + reader.read_row(output_row).unwrap().unwrap(); + } + }) + }); +} + +fn create_reader(data: &[u8]) -> Reader> { + let mut decoder = Decoder::new(Cursor::new(data)); + + // Cover default transformations used by the `image` crate when constructing + // `image::codecs::png::PngDecoder`. + decoder.set_transformations(Transformations::EXPAND); + + decoder.read_info().unwrap() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/benches/unfilter.rs clamav-1.4.6+dfsg/.cargo/vendor/png/benches/unfilter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/benches/unfilter.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/benches/unfilter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,24 +2,19 @@ //! //! ``` //! $ alias bench="rustup run nightly cargo bench" -//! $ bench --bench=unfilter --features=benchmarks,unstable -- --save-baseline my_baseline +//! $ bench --bench=unfilter --features=benchmarks -- --save-baseline my_baseline //! ... tweak something, say the Sub filter ... -//! $ bench --bench=unfilter --features=benchmarks,unstable -- filter=Sub --baseline my_baseline +//! $ bench --bench=unfilter --features=benchmarks -- filter=Sub --baseline my_baseline //! ``` use criterion::{criterion_group, criterion_main, Criterion, Throughput}; use png::benchable_apis::unfilter; -use png::FilterType; +use png::Filter; use rand::Rng; fn unfilter_all(c: &mut Criterion) { let bpps = [1, 2, 3, 4, 6, 8]; - let filters = [ - FilterType::Sub, - FilterType::Up, - FilterType::Avg, - FilterType::Paeth, - ]; + let filters = [Filter::Sub, Filter::Up, Filter::Avg, Filter::Paeth]; for &filter in filters.iter() { for &bpp in bpps.iter() { bench_unfilter(c, filter, bpp); @@ -30,7 +25,7 @@ criterion_group!(benches, unfilter_all); criterion_main!(benches); -fn bench_unfilter(c: &mut Criterion, filter: FilterType, bpp: u8) { +fn bench_unfilter(c: &mut Criterion, filter: Filter, bpp: u8) { let mut group = c.benchmark_group("unfilter"); fn get_random_bytes(rng: &mut R, n: usize) -> Vec { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/examples/change-png-info.rs clamav-1.4.6+dfsg/.cargo/vendor/png/examples/change-png-info.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/examples/change-png-info.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/examples/change-png-info.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,10 @@ /// Tests "editing"/re-encoding of an image: /// decoding, editing, re-encoding use std::fs::File; -use std::io::BufWriter; +use std::io::{BufReader, BufWriter}; use std::path::Path; + +use png::DecodingError::LimitsExceeded; pub type BoxResult = Result>; fn main() -> BoxResult<()> { @@ -11,12 +13,12 @@ let path_in = Path::new(r"./tests/pngsuite/basi0g01.png"); // The decoder is a build for reader and can be used to set various decoding options // via `Transformations`. The default output transformation is `Transformations::IDENTITY`. - let decoder = png::Decoder::new(File::open(path_in)?); + let decoder = png::Decoder::new(BufReader::new(File::open(path_in)?)); let mut reader = decoder.read_info()?; // Allocate the output buffer. let png_info = reader.info(); - let mut buf = vec![0; reader.output_buffer_size()]; - dbg!(png_info); + let mut buf = vec![0; reader.output_buffer_size().ok_or(LimitsExceeded)?]; + println!("{png_info:?}"); // # Encode let path_out = Path::new(r"./target/test_modified.png"); @@ -43,7 +45,6 @@ let mut counter = 0u8; while let Ok(info) = reader.next_frame(&mut buf) { let bytes = &buf[..info.buffer_size()]; - println!("{} {}", info.buffer_size(), reader.output_buffer_size()); writer.write_image_data(&bytes)?; counter += 1; println!("Written frame: {}", counter); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/examples/corpus-bench.rs clamav-1.4.6+dfsg/.cargo/vendor/png/examples/corpus-bench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/examples/corpus-bench.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/examples/corpus-bench.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -use std::{fs, path::PathBuf}; +use std::{fs, io::Cursor, path::PathBuf}; use clap::Parser; use png::Decoder; @@ -43,20 +43,16 @@ encoder.set_depth(bit_depth); encoder.set_compression(match args.speed { Speed::Fast => png::Compression::Fast, - Speed::Default => png::Compression::Default, - Speed::Best => png::Compression::Best, + Speed::Default => png::Compression::Balanced, + Speed::Best => png::Compression::High, }); encoder.set_filter(match args.filter { - Filter::None => png::FilterType::NoFilter, - Filter::Sub => png::FilterType::Sub, - Filter::Up => png::FilterType::Up, - Filter::Average => png::FilterType::Avg, - Filter::Paeth => png::FilterType::Paeth, - Filter::Adaptive => png::FilterType::Paeth, - }); - encoder.set_adaptive_filter(match args.filter { - Filter::Adaptive => png::AdaptiveFilterType::Adaptive, - _ => png::AdaptiveFilterType::NonAdaptive, + Filter::None => png::Filter::NoFilter, + Filter::Sub => png::Filter::Sub, + Filter::Up => png::Filter::Up, + Filter::Average => png::Filter::Avg, + Filter::Paeth => png::Filter::Paeth, + Filter::Adaptive => png::Filter::Adaptive, }); let mut encoder = encoder.write_header().unwrap(); encoder.write_image_data(image).unwrap(); @@ -66,7 +62,7 @@ #[inline(never)] fn run_decode(image: &[u8], output: &mut [u8]) { - let mut reader = Decoder::new(image).read_info().unwrap(); + let mut reader = Decoder::new(Cursor::new(image)).read_info().unwrap(); reader.next_frame(output).unwrap(); } @@ -111,7 +107,7 @@ // Parse let data = fs::read(entry.path()).unwrap(); - let mut decoder = Decoder::new(&*data); + let mut decoder = Decoder::new(Cursor::new(&*data)); if decoder.read_header_info().ok().map(|h| h.color_type) == Some(png::ColorType::Indexed) { @@ -123,7 +119,7 @@ Ok(reader) => reader, Err(_) => continue, }; - let mut image = vec![0; reader.output_buffer_size()]; + let mut image = vec![0; reader.output_buffer_size().unwrap()]; let info = match reader.next_frame(&mut image) { Ok(info) => info, Err(_) => continue, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/examples/pngcheck.rs clamav-1.4.6+dfsg/.cargo/vendor/png/examples/pngcheck.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/examples/pngcheck.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/examples/pngcheck.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,46 +1,27 @@ #![allow(non_upper_case_globals)] -extern crate getopts; -extern crate glob; -extern crate png; - -use std::env; use std::fs::File; use std::io; use std::io::prelude::*; -use std::path::Path; +use std::path::{Path, PathBuf}; -use getopts::{Matches, Options, ParsingStyle}; -use term::{color, Attr}; +use clap::Parser; -fn parse_args() -> Matches { - let args: Vec = env::args().collect(); - let mut opts = Options::new(); - opts.optflag("c", "", "colorize output (for ANSI terminals)") - .optflag("q", "", "test quietly (output only errors)") - .optflag( - "t", - "", - "print contents of tEXt/zTXt/iTXt chunks (can be used with -q)", - ) - .optflag("v", "", "test verbosely (print most chunk data)") - .parsing_style(ParsingStyle::StopAtFirstFree); - if args.len() > 1 { - match opts.parse(&args[1..]) { - Ok(matches) => return matches, - Err(err) => println!("{}", err), - } - } - println!("{}", opts.usage("Usage: pngcheck [-cpt] [file ...]")); - std::process::exit(0); -} +use png::chunk; -#[derive(Clone, Copy)] +#[derive(Parser)] +#[command(about, version)] struct Config { + /// test quietly (output only errors) + #[arg(short, long)] quiet: bool, + /// test verbosely (print most chunk data) + #[arg(short, long)] verbose: bool, - color: bool, + /// print contents of tEXt/zTXt/iTXt chunks (can be used with -q) + #[arg(short, long)] text: bool, + paths: Vec, } fn display_interlaced(i: bool) -> &'static str { @@ -76,11 +57,10 @@ Rgba => 4, } } -fn check_image>(c: Config, fname: P) -> io::Result<()> { - // TODO improve performance by resusing allocations from decoder + +fn check_image>(c: &Config, fname: P) -> io::Result<()> { + // TODO improve performance by reusing allocations from decoder use png::Decoded::*; - let mut t = term::stdout() - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not open terminal"))?; let data = &mut vec![0; 10 * 1024][..]; let mut reader = io::BufReader::new(File::open(&fname)?); let fname = fname.as_ref().to_string_lossy(); @@ -108,57 +88,23 @@ }); ); let display_error = |err| -> Result<_, io::Error> { - let mut t = term::stdout() - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not open terminal"))?; if c.verbose { - if c.color { - print!(": "); - t.fg(color::RED)?; - writeln!(t, "{}", err)?; - t.attr(Attr::Bold)?; - write!(t, "ERRORS DETECTED")?; - t.reset()?; - } else { - println!(": {}", err); - print!("ERRORS DETECTED") - } + println!(": {}", err); + print!("ERRORS DETECTED"); println!(" in {}", fname); } else { if !c.quiet { - if c.color { - t.fg(color::RED)?; - t.attr(Attr::Bold)?; - write!(t, "ERROR")?; - t.reset()?; - write!(t, ": ")?; - t.fg(color::YELLOW)?; - writeln!(t, "{}", fname)?; - t.reset()?; - } else { - println!("ERROR: {}", fname) - } + println!("ERROR: {}", fname) } print!("{}: ", fname); - if c.color { - t.fg(color::RED)?; - writeln!(t, "{}", err)?; - t.reset()?; - } else { - println!("{}", err); - } + println!("{}", err); } Ok(()) }; if c.verbose { print!("File: "); - if c.color { - t.attr(Attr::Bold)?; - write!(t, "{}", fname)?; - t.reset()?; - } else { - print!("{}", fname); - } + print!("{}", fname); print!(" ({}) bytes", data.len()) } loop { @@ -174,8 +120,8 @@ } buf = &data[..n]; } - match decoder.update(buf, &mut Vec::new()) { - Ok((_, ImageEnd)) => { + match decoder.update(buf, None) { + Ok((_, ChunkComplete(chunk::IEND))) => { if !have_idat { // This isn't beautiful. But it works. display_error(png::DecodingError::IoError(io::Error::new( @@ -185,18 +131,7 @@ break; } if !c.verbose && !c.quiet { - if c.color { - t.fg(color::GREEN)?; - t.attr(Attr::Bold)?; - write!(t, "OK")?; - t.reset()?; - write!(t, ": ")?; - t.fg(color::YELLOW)?; - write!(t, "{}", fname)?; - t.reset()?; - } else { - print!("OK: {}", fname) - } + print!("OK: {}", fname); println!( " ({}x{}, {}{}, {}, {:.1}%)", width, @@ -208,14 +143,7 @@ ) } else if !c.quiet { println!(); - if c.color { - t.fg(color::GREEN)?; - t.attr(Attr::Bold)?; - write!(t, "No errors detected ")?; - t.reset()?; - } else { - print!("No errors detected "); - } + print!("No errors detected "); println!( "in {} ({} chunks, {:.1}% compression)", fname, @@ -229,30 +157,16 @@ buf = &buf[n..]; pos += n; match res { - Header(w, h, b, c, i) => { - width = w; - height = h; - bits = b as u8; - color = c; - interlaced = i; - } ChunkBegin(len, type_str) => { - use png::chunk; n_chunks += 1; if c.verbose { let chunk = type_str; println!(); print!(" chunk "); - if c.color { - t.fg(color::YELLOW)?; - write!(t, "{:?}", chunk)?; - t.reset()?; - } else { - print!("{:?}", chunk) - } + print!("{:?}", chunk); print!( " at offset {:#07x}, length {}", - pos - 4, // substract chunk name length + pos - 4, // subtract chunk name length len ) } @@ -267,12 +181,14 @@ _ => (), } } - ImageData => { - //println!("got {} bytes of image data", data.len()) - } - ChunkComplete(_, type_str) if c.verbose => { - use png::chunk::*; - if type_str == IHDR { + ChunkComplete(chunk::IHDR) => { + width = decoder.info().unwrap().width; + height = decoder.info().unwrap().height; + bits = decoder.info().unwrap().bit_depth as u8; + color = decoder.info().unwrap().color_type; + interlaced = decoder.info().unwrap().interlaced; + + if c.verbose { println!(); print!( " {} x {} image, {}{}, {}", @@ -284,11 +200,13 @@ ); } } - AnimationControl(actl) => { + ChunkComplete(chunk::acTL) => { + let actl = decoder.info().unwrap().animation_control.unwrap(); println!(); print!(" {} frames, {} plays", actl.num_frames, actl.num_plays,); } - FrameControl(fctl) => { + ChunkComplete(chunk::fdAT) => { + let fctl = decoder.info().unwrap().frame_control.unwrap(); println!(); println!( " sequence #{}, {} x {} pixels @ ({}, {})", @@ -314,6 +232,9 @@ fctl.blend_op, ); } + ImageData => { + //println!("got {} bytes of image data", data.len()) + } _ => (), } //println!("{} {:?}", n, res) @@ -349,32 +270,25 @@ } fn main() { - let m = parse_args(); - - let config = Config { - quiet: m.opt_present("q"), - verbose: m.opt_present("v"), - color: m.opt_present("c"), - text: m.opt_present("t"), - }; + let config = Config::parse(); - for file in m.free { - let result = if file.contains('*') { - glob::glob(&file) + for file in &config.paths { + let result = if let Some(glob) = file.to_str().filter(|n| n.contains('*')) { + glob::glob(glob) .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) .and_then(|mut glob| { glob.try_for_each(|entry| { entry .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) - .and_then(|file| check_image(config, file)) + .and_then(|file| check_image(&config, file)) }) }) } else { - check_image(config, &file) + check_image(&config, &file) }; result.unwrap_or_else(|err| { - println!("{}: {}", file, err); + println!("{}: {}", file.display(), err); std::process::exit(1) }); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/examples/show.rs clamav-1.4.6+dfsg/.cargo/vendor/png/examples/show.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/examples/show.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/examples/show.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,198 +0,0 @@ -use glium::{ - backend::glutin::Display, - glutin::{ - self, dpi, - event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, - event_loop::ControlFlow, - }, - texture::{ClientFormat, RawImage2d}, - BlitTarget, Rect, Surface, -}; -use std::{borrow::Cow, env, fs::File, io, path}; - -/// Load the image using `png` -fn load_image(path: &path::PathBuf) -> io::Result> { - use png::ColorType::*; - let mut decoder = png::Decoder::new(File::open(path)?); - decoder.set_transformations(png::Transformations::normalize_to_color8()); - let mut reader = decoder.read_info()?; - let mut img_data = vec![0; reader.output_buffer_size()]; - let info = reader.next_frame(&mut img_data)?; - - let (data, format) = match info.color_type { - Rgb => (img_data, ClientFormat::U8U8U8), - Rgba => (img_data, ClientFormat::U8U8U8U8), - Grayscale => ( - { - let mut vec = Vec::with_capacity(img_data.len() * 3); - for g in img_data { - vec.extend([g, g, g].iter().cloned()) - } - vec - }, - ClientFormat::U8U8U8, - ), - GrayscaleAlpha => ( - { - let mut vec = Vec::with_capacity(img_data.len() * 3); - for ga in img_data.chunks(2) { - let g = ga[0]; - let a = ga[1]; - vec.extend([g, g, g, a].iter().cloned()) - } - vec - }, - ClientFormat::U8U8U8U8, - ), - _ => unreachable!("uncovered color type"), - }; - - Ok(RawImage2d { - data: Cow::Owned(data), - width: info.width, - height: info.height, - format, - }) -} - -fn main_loop(files: Vec) -> io::Result<()> { - let mut files = files.into_iter(); - let image = load_image(&files.next().unwrap())?; - - let event_loop = glutin::event_loop::EventLoop::new(); - let window_builder = glutin::window::WindowBuilder::new().with_title("Show Example"); - let context_builder = glutin::ContextBuilder::new().with_vsync(true); - let display = glium::Display::new(window_builder, context_builder, &event_loop) - .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; - resize_window(&display, &image); - let mut texture = glium::Texture2d::new(&display, image).unwrap(); - draw(&display, &texture); - - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => exit(control_flow), - Event::WindowEvent { - event: - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: code, - .. - }, - .. - }, - .. - } => match code { - Some(VirtualKeyCode::Escape) => exit(control_flow), - Some(VirtualKeyCode::Right) => match &files.next() { - Some(path) => { - match load_image(path) { - Ok(image) => { - resize_window(&display, &image); - texture = glium::Texture2d::new(&display, image).unwrap(); - draw(&display, &texture); - } - Err(err) => { - println!("Error: {}", err); - exit(control_flow); - } - }; - } - None => exit(control_flow), - }, - _ => {} - }, - Event::RedrawRequested(_) => draw(&display, &texture), - _ => {} - }); -} - -fn draw(display: &glium::Display, texture: &glium::Texture2d) { - let frame = display.draw(); - fill_v_flipped( - &texture.as_surface(), - &frame, - glium::uniforms::MagnifySamplerFilter::Linear, - ); - frame.finish().unwrap(); -} - -fn exit(control_flow: &mut ControlFlow) { - *control_flow = ControlFlow::Exit; -} - -fn fill_v_flipped(src: &S1, target: &S2, filter: glium::uniforms::MagnifySamplerFilter) -where - S1: Surface, - S2: Surface, -{ - let src_dim = src.get_dimensions(); - let src_rect = Rect { - left: 0, - bottom: 0, - width: src_dim.0, - height: src_dim.1, - }; - let target_dim = target.get_dimensions(); - let target_rect = BlitTarget { - left: 0, - bottom: target_dim.1, - width: target_dim.0 as i32, - height: -(target_dim.1 as i32), - }; - src.blit_color(&src_rect, target, &target_rect, filter); -} - -fn resize_window(display: &Display, image: &RawImage2d<'static, u8>) { - let mut width = image.width; - let mut height = image.height; - if width < 50 && height < 50 { - width *= 10; - height *= 10; - } - display - .gl_window() - .window() - .set_inner_size(dpi::LogicalSize::new(f64::from(width), f64::from(height))); -} - -fn main() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - println!("Usage: show files [...]"); - } else { - let mut files = vec![]; - for file in args.iter().skip(1) { - match if file.contains('*') { - (|| -> io::Result<_> { - for entry in glob::glob(file) - .map_err(|err| io::Error::new(io::ErrorKind::Other, err.msg))? - { - files.push( - entry - .map_err(|_| io::Error::new(io::ErrorKind::Other, "glob error"))?, - ) - } - Ok(()) - })() - } else { - files.push(path::PathBuf::from(file)); - Ok(()) - } { - Ok(_) => (), - Err(err) => { - println!("{}: {}", file, err); - break; - } - } - } - // "tests/pngsuite/pngsuite.png" - match main_loop(files) { - Ok(_) => (), - Err(err) => println!("Error: {}", err), - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/adam7.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/adam7.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/adam7.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/adam7.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,136 @@ -//! Utility functions -use std::iter::StepBy; -use std::ops::Range; +//! Utility functions related to handling of +//! [the Adam7 algorithm](https://en.wikipedia.org/wiki/Adam7_algorithm). +use core::ops::RangeTo; + +/// Describes which stage of +/// [the Adam7 algorithm](https://en.wikipedia.org/wiki/Adam7_algorithm) +/// applies to a decoded row. +/// +/// See also [Reader.next_interlaced_row](crate::decoder::Reader::next_interlaced_row). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Adam7Info { + /// The Adam7 pass number, 1..7. + pub(crate) pass: u8, + /// The index of the line within this pass. + pub(crate) line: u32, + /// The original pixel count. + pub(crate) width: u32, + /// How many Adam7 samples there are. + pub(crate) samples: u32, +} + +/// The index of a bit in the image buffer. +/// +/// We do not use a pure `usize` to avoid overflows on 32-bit targets. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct BitPostion { + byte: usize, + /// [0..8) + bit: u8, +} + +impl Adam7Info { + /// Creates a new `Adam7Info`. May panic if the arguments are out of range (e.g. if `pass` is + /// 0 or greater than 8). + /// + /// * `pass` corresponds to a pass of the + /// [the Adam7 algorithm](https://en.wikipedia.org/wiki/Adam7_algorithm) + /// * `line` is the number of a line within a pass (starting with 0). For example, + /// in an image of height 8, `line` can be beteween `0..4` in the 7th `pass` + /// (those 4 interlaced rows correspond to 2nd, 4th, 6th, and 8th row of the full image). + /// * `width` describes how many pixels are in a full row of the image. The bytes in each + /// passline of the Adam7 are calculated from this number. + /// + /// Note that in typical usage, `Adam7Info`s are returned by [Reader.next_interlaced_row] + /// and there is no need to create them by calling `Adam7Info::new`. `Adam7Info::new` is + /// nevertheless exposed as a public API, because it helps to provide self-contained example + /// usage of [expand_interlaced_row](crate::expand_interlaced_row). + pub fn new(pass: u8, line: u32, width: u32) -> Self { + assert!(1 <= pass && pass <= 7); + assert!(width > 0); + + let info = PassConstants::PASSES[pass as usize - 1]; + let samples = info.count_samples(width); + + Self { + pass, + line, + width, + samples, + } + } + + fn pass_constants(&self) -> PassConstants { + PassConstants::PASSES[self.pass as usize - 1] + } + + /// How often to repeat a pixel. + fn splat_pixel_repeat(self, idx: usize) -> u8 { + let pass = self.pass_constants(); + let x_pixel = idx as u32 * u32::from(pass.x_sampling) + u32::from(pass.x_offset); + (self.width - x_pixel).min(pass.splat_x_repeat().into()) as u8 + } + + fn splat_line_repeat(self, height: u32) -> u8 { + let pass = self.pass_constants(); + let y_line = self.line * u32::from(pass.y_sampling) + u32::from(pass.y_offset); + (height - y_line).min(pass.splat_y_repeat().into()) as u8 + } +} + +#[derive(Clone, Copy)] +struct PassConstants { + x_sampling: u8, + x_offset: u8, + y_sampling: u8, + y_offset: u8, +} + +impl PassConstants { + const fn splat_x_repeat(self) -> u8 { + self.x_sampling - self.x_offset + } + + const fn splat_y_repeat(self) -> u8 { + self.y_sampling - self.y_offset + } + + fn count_samples(self, width: u32) -> u32 { + width + .saturating_sub(u32::from(self.x_offset)) + .div_ceil(u32::from(self.x_sampling)) + } + + fn count_lines(self, height: u32) -> u32 { + height + .saturating_sub(u32::from(self.y_offset)) + .div_ceil(u32::from(self.y_sampling)) + } + + /// The constants associated with each of the 7 passes. Note that it is 0-indexed while the + /// pass number (as per specification) is 1-indexed. + pub const PASSES: [Self; 7] = { + // Shortens the constructor for readability, retains clear argument order below. + const fn new(x_sampling: u8, x_offset: u8, y_sampling: u8, y_offset: u8) -> PassConstants { + PassConstants { + x_sampling, + x_offset, + y_sampling, + y_offset, + } + } + + [ + new(8, 0, 8, 0), + new(8, 4, 8, 0), + new(4, 0, 8, 4), + new(4, 2, 4, 0), + new(2, 0, 4, 2), + new(2, 1, 2, 0), + new(1, 0, 2, 1), + ] + }; +} /// This iterator iterates over the different passes of an image Adam7 encoded /// PNG image @@ -40,37 +170,26 @@ /// Calculates the bounds of the current pass fn init_pass(&mut self) { - let w = f64::from(self.width); - let h = f64::from(self.height); - let (line_width, lines) = match self.current_pass { - 1 => (w / 8.0, h / 8.0), - 2 => ((w - 4.0) / 8.0, h / 8.0), - 3 => (w / 4.0, (h - 4.0) / 8.0), - 4 => ((w - 2.0) / 4.0, h / 4.0), - 5 => (w / 2.0, (h - 2.0) / 4.0), - 6 => ((w - 1.0) / 2.0, h / 2.0), - 7 => (w, (h - 1.0) / 2.0), - _ => unreachable!(), - }; - self.line_width = line_width.ceil() as u32; - self.lines = lines.ceil() as u32; + let info = PassConstants::PASSES[self.current_pass as usize - 1]; + self.line_width = info.count_samples(self.width); + self.lines = info.count_lines(self.height); self.line = 0; } - - /// The current pass#. - pub fn current_pass(&self) -> u8 { - self.current_pass - } } -/// Iterates over the (passes, lines, widths) +/// Iterates over `Adam7Info`s. impl Iterator for Adam7Iterator { - type Item = (u8, u32, u32); + type Item = Adam7Info; fn next(&mut self) -> Option { if self.line < self.lines && self.line_width > 0 { let this_line = self.line; self.line += 1; - Some((self.current_pass, this_line, self.line_width)) + Some(Adam7Info { + pass: self.current_pass, + line: this_line, + width: self.width, + samples: self.line_width, + }) } else if self.current_pass < 7 { self.current_pass += 1; self.init_pass(); @@ -81,304 +200,824 @@ } } -fn subbyte_pixels(scanline: &[u8], bits_pp: usize) -> impl Iterator + '_ { - (0..scanline.len() * 8) - .step_by(bits_pp) - .map(move |bit_idx| { - let byte_idx = bit_idx / 8; - - // sub-byte samples start in the high-order bits - let rem = 8 - bit_idx % 8 - bits_pp; - - match bits_pp { - // evenly divides bytes - 1 => (scanline[byte_idx] >> rem) & 1, - 2 => (scanline[byte_idx] >> rem) & 3, - 4 => (scanline[byte_idx] >> rem) & 15, - _ => unreachable!(), - } - }) +/// The algorithm to use when progressively filling pixel data from Adam7 interlaced passes. +/// +/// Adam7 interlacing is a technique optionally used in PNG by which only a sub-sample of pixel +/// data is encoded in the beginning of the image data chunks, followed by progressively larger +/// subsets of the data in subsequent passes. Therefore a 'rough image' is available after ust a +/// very tiny fraction of the data has been read which can be advantageous for loading an image +/// from a slow IO medium while optimizing time-to-first-meaningful-paint and then replacing the +/// presented data as it is streamed in. +/// +/// There are trade-offs to make here. The strictly necessary requirement for an implementation is +/// that the exact image is recovered after all passes are applied. However the intermediate states +/// of the output are left to the implementation, as long as it follows the restriction of +/// resulting in the intended image when all passes have been applied. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[non_exhaustive] +pub enum Adam7Variant { + /// This is the adam7 de-interlace we do by default. Only pixels related to the pass are + /// written. The output buffer should not be directly used for presentation until all passes + /// are complete. At least the invalid pixels in the buffer should be masked. However, this + /// performs the least amount of writes and is optimal when you're only reading full frames. + /// + /// This corresponds to [`crate::expand_interlaced_row`]. + #[default] + Sparse, + /// A variant of the Adam7 de-interlace that ensures that all pixels are initialized after each + /// pass, and are progressively refined towards the final image. Performs more writes than the + /// other variant as some pixels are touched repeatedly, but ensures the buffer can be used as + /// directly as possible for presentation. + /// + /// This corresponds to [`crate::splat_interlaced_row`]. + Splat, +} + +fn subbyte_values( + scanline: &[u8], + bit_pos: [u8; N], + mask: u8, +) -> impl Iterator + '_ { + (scanline.iter().copied()).flat_map(move |value| bit_pos.map(|n| (value >> n) & mask)) } -/// Given pass, image width, and line number, produce an iterator of bit positions of pixels to copy -/// from the input scanline to the image buffer. +/// Given `row_stride`, interlace `info`, and bits-per-pixel, produce an iterator of bit positions +/// of pixels to copy from the input scanline to the image buffer. The positions are expressed as +/// bit offsets from position (0,0) in the frame that is currently being decoded. +/// +/// This should only be used with `bits_pp < 8`. fn expand_adam7_bits( - pass: u8, - width: usize, - line_no: usize, - bits_pp: usize, -) -> StepBy> { - let (line_mul, line_off, samp_mul, samp_off) = match pass { - 1 => (8, 0, 8, 0), - 2 => (8, 0, 8, 4), - 3 => (8, 4, 4, 0), - 4 => (4, 0, 4, 2), - 5 => (4, 2, 2, 0), - 6 => (2, 0, 2, 1), - 7 => (2, 1, 1, 0), - _ => panic!("Adam7 pass out of range: {}", pass), + row_stride_in_bytes: usize, + info: &Adam7Info, + bits_pp: u8, +) -> impl Iterator { + debug_assert!(bits_pp == 1 || bits_pp == 2 || bits_pp == 4); + let (line_mul, line_off, samp_mul, samp_off) = { + let constants = info.pass_constants(); + ( + // Convert each to their respectively required type from u8. + usize::from(constants.y_sampling), + usize::from(constants.y_offset), + u64::from(constants.x_sampling), + u64::from(constants.x_offset), + ) }; // the equivalent line number in progressive scan - let prog_line = line_mul * line_no + line_off; - // line width is rounded up to the next byte - let line_width = (width * bits_pp + 7) & !7; - let line_start = prog_line * line_width; - let start = line_start + (samp_off * bits_pp); - let stop = line_start + (width * bits_pp); + let prog_line = line_mul * info.line as usize + line_off; + let byte_start = prog_line * row_stride_in_bytes; - (start..stop).step_by(bits_pp * samp_mul) + // In contrast to `subbyte_values` we *must* be precise with our length here. + (0..u64::from(info.samples)) + // Bounded by u32::MAX * 8 * 4 + 16 so does not overflow `u64`. + .map(move |i| (i * samp_mul + samp_off) * u64::from(bits_pp)) + .map(move |i| BitPostion { + // Bounded by the buffer size which already exists. + byte: byte_start + (i / 8) as usize, + bit: i as u8 % 8, + }) } -/// Expands an Adam 7 pass +fn expand_adam7_bytes( + row_stride_in_bytes: usize, + info: &Adam7Info, + bytes_pp: u8, +) -> impl Iterator { + let (line_mul, line_off, samp_mul, samp_off) = { + let constants = info.pass_constants(); + ( + // Convert each to their respectively required type from u8. + usize::from(constants.y_sampling), + usize::from(constants.y_offset), + u64::from(constants.x_sampling), + u64::from(constants.x_offset), + ) + }; + + // the equivalent line number in progressive scan + let prog_line = line_mul * info.line as usize + line_off; + let byte_start = prog_line * row_stride_in_bytes; + + (0..u64::from(info.samples)) + .map(move |i| (i * samp_mul + samp_off) * u64::from(bytes_pp)) + // Bounded by the allocated buffer size so must fit in `usize` + .map(move |i| i as usize + byte_start) +} + +/// Copies pixels from `interlaced_row` into the right location in `img`. +/// +/// First bytes of `img` should belong to the top-left corner of the currently decoded frame. +/// +/// `img_row_stride` specifies an offset in bytes between subsequent rows of `img`. +/// This can be the width of the current frame being decoded, but this is not required - a bigger +/// stride may be useful if the frame being decoded is a sub-region of `img`. +/// +/// `interlaced_row` and `interlace_info` typically come from +/// [crate::decoder::Reader::next_interlaced_row], but this is not required. In particular, before +/// calling `expand_interlaced_row` one may need to expand the decoded row, so that its format and +/// `bits_per_pixel` matches that of `img`. Note that in initial Adam7 passes the `interlaced_row` +/// may contain less pixels that the width of the frame being decoded (e.g. it contains only 1/8th +/// of pixels in the initial pass). +/// +/// Example: +/// +/// ``` +/// use png::{expand_interlaced_row, Adam7Info}; +/// let info = Adam7Info::new(5, 0, 8); +/// let mut img = vec![0; 8 * 8]; +/// let row = vec![1, 2, 3, 4]; +/// expand_interlaced_row(&mut img, 8, &row, &info, 8); +/// assert_eq!(&img, &[ +/// 0, 0, 0, 0, 0, 0, 0, 0, +/// 0, 0, 0, 0, 0, 0, 0, 0, +/// 1, 0, 2, 0, 3, 0, 4, 0, // <= this is where the 1st line of 5s appears +/// 0, 0, 0, 0, 0, 0, 0, 0, // in the schematic drawing of the passes at +/// 0, 0, 0, 0, 0, 0, 0, 0, // https://en.wikipedia.org/wiki/Adam7_algorithm +/// 0, 0, 0, 0, 0, 0, 0, 0, +/// 0, 0, 0, 0, 0, 0, 0, 0, +/// 0, 0, 0, 0, 0, 0, 0, 0, +/// ]); +/// ``` pub fn expand_pass( img: &mut [u8], - width: u32, - scanline: &[u8], - pass: u8, - line_no: u32, - bits_pp: u8, + img_row_stride: usize, + interlaced_row: &[u8], + interlace_info: &Adam7Info, + bits_per_pixel: u8, ) { - let width = width as usize; - let line_no = line_no as usize; - let bits_pp = bits_pp as usize; - - // pass is out of range but don't blow up - if pass == 0 || pass > 7 { - return; - } - - let bit_indices = expand_adam7_bits(pass, width, line_no, bits_pp); - - if bits_pp < 8 { - for (pos, px) in bit_indices.zip(subbyte_pixels(scanline, bits_pp)) { - let rem = 8 - pos % 8 - bits_pp; - img[pos / 8] |= px << rem as u8; - } - } else { - let bytes_pp = bits_pp / 8; - - for (bitpos, px) in bit_indices.zip(scanline.chunks(bytes_pp)) { - for (offset, val) in px.iter().enumerate() { - img[bitpos / 8 + offset] = *val; + match bits_per_pixel { + // Note: for 1, 2, 4 multiple runs through the iteration will access the same byte in `img` + // so we can not iterate over `&mut u8` values. A better strategy would write multiple bit + // groups in one go. This would then also not be as bounds-check heavy? + 1 => { + const BIT_POS_1: [u8; 8] = [7, 6, 5, 4, 3, 2, 1, 0]; + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 1); + for (pos, px) in bit_indices.zip(subbyte_values(interlaced_row, BIT_POS_1, 0b1)) { + let shift = 8 - bits_per_pixel - pos.bit; + img[pos.byte] |= px << shift; + } + } + 2 => { + const BIT_POS_2: [u8; 4] = [6, 4, 2, 0]; + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 2); + + for (pos, px) in bit_indices.zip(subbyte_values(interlaced_row, BIT_POS_2, 0b11)) { + let shift = 8 - bits_per_pixel - pos.bit; + img[pos.byte] |= px << shift; + } + } + 4 => { + const BIT_POS_4: [u8; 2] = [4, 0]; + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 4); + + for (pos, px) in bit_indices.zip(subbyte_values(interlaced_row, BIT_POS_4, 0b1111)) { + let shift = 8 - bits_per_pixel - pos.bit; + img[pos.byte] |= px << shift; + } + } + // While caught by the below loop, we special case this for codegen. The effects are + // massive when the compiler uses the constant chunk size in particular for this case where + // no more copy_from_slice is being issued by everything happens in the register alone. + 8 => { + let byte_indices = expand_adam7_bytes(img_row_stride, interlace_info, 1); + + for (bytepos, &px) in byte_indices.zip(interlaced_row) { + img[bytepos] = px; + } + } + 16 => { + let byte_indices = expand_adam7_bytes(img_row_stride, interlace_info, 2); + + for (bytepos, px) in byte_indices.zip(interlaced_row.chunks(2)) { + img[bytepos..][..2].copy_from_slice(px); + } + } + _ => { + debug_assert!(bits_per_pixel % 8 == 0); + let bytes_pp = bits_per_pixel / 8; + let byte_indices = expand_adam7_bytes(img_row_stride, interlace_info, bytes_pp); + + for (bytepos, px) in byte_indices.zip(interlaced_row.chunks(bytes_pp.into())) { + img[bytepos..][..px.len()].copy_from_slice(px); } } } } -#[test] -fn test_adam7() { - /* - 1646 - 7777 - 5656 - 7777 - */ - let it = Adam7Iterator::new(4, 4); - let passes: Vec<_> = it.collect(); - assert_eq!( - &*passes, - &[ - (1, 0, 1), - (4, 0, 1), - (5, 0, 2), - (6, 0, 2), - (6, 1, 2), - (7, 0, 4), - (7, 1, 4) - ] - ); -} +/// Expand pass, but also ensure that after each pass the whole image has been initialized up to +/// the data available. In constrast to `expand_pass` there are no holes left in the image. +/// +/// For instance, consider the first pass which is an eighth subsampling of the original image. +/// Here's a side by-side of pixel data written from each of the two algorithms: +/// +/// ```text +/// normal: splat: +/// 1------- 11111111 +/// -------- 11111111 +/// -------- 11111111 +/// -------- 11111111 +/// -------- 11111111 +/// -------- 11111111 +/// -------- 11111111 +/// ``` +/// +/// Data written in previous passes must not be modified. We 'weave' the data of passes and repeat +/// them in the neighbouring pixels until their subsampling alignment. For details, see the +/// `x_repeat` and `y_repeat` data. Thus the 4th pass would look like this: +/// +/// ```text +/// normal: splat: +/// --4---4- --44--44 +/// -------- --44--44 +/// -------- --44--44 +/// --4---4- --44--44 +/// -------- --44--44 +/// -------- --44--44 +/// -------- --44--44 +/// ``` +/// +pub fn expand_pass_splat( + img: &mut [u8], + img_row_stride: usize, + interlaced_row: &[u8], + interlace_info: &Adam7Info, + bits_per_pixel: u8, +) { + fn expand_bits_to_img( + img: &mut [u8], + px: u8, + mut pos: BitPostion, + repeat: RangeTo, + bpp: u8, + ) { + let (mut into, mut tail) = img[pos.byte..].split_first_mut().unwrap(); + let mask = (1u8 << bpp) - 1; + + for _ in 0..repeat.end { + if pos.bit >= 8 { + pos.byte += 1; + pos.bit -= 8; -#[test] -fn test_subbyte_pixels() { - let scanline = &[0b10101010, 0b10101010]; + (into, tail) = tail.split_first_mut().unwrap(); + } - let pixels = subbyte_pixels(scanline, 1).collect::>(); - assert_eq!(pixels.len(), 16); - assert_eq!(pixels, [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]); -} + let shift = 8 - bpp - pos.bit; + // Preserve all other bits, but be prepared for existing bits + let pre = (*into >> shift) & mask; + *into ^= (pre ^ px) << shift; -#[test] -fn test_expand_adam7_bits() { - let width = 32; - let bits_pp = 1; + pos.bit += bpp; + } + } - let expected = |offset: usize, step: usize, count: usize| { - (0..count) - .map(move |i| step * i + offset) - .collect::>() - }; + let height = (img.len() / img_row_stride) as u32; + let y_repeat = interlace_info.splat_line_repeat(height); + debug_assert!(y_repeat > 0); + + match bits_per_pixel { + // Note: for 1, 2, 4 multiple runs through the iteration will access the same byte in `img` + // so we can not iterate over `&mut u8` values. A better strategy would write multiple bit + // groups in one go. This would then also not be as bounds-check heavy? + 1 => { + const BIT_POS_1: [u8; 8] = [7, 6, 5, 4, 3, 2, 1, 0]; + + for offset in 0..y_repeat { + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 1); + let line_offset = usize::from(offset) * img_row_stride; + + for (idx, (mut pos, px)) in bit_indices + .zip(subbyte_values(interlaced_row, BIT_POS_1, 0b1)) + .enumerate() + { + let x_repeat = interlace_info.splat_pixel_repeat(idx); + debug_assert!(x_repeat > 0); + pos.byte += line_offset; + expand_bits_to_img(img, px, pos, ..x_repeat, bits_per_pixel); + } + } + } + 2 => { + const BIT_POS_2: [u8; 4] = [6, 4, 2, 0]; - for line_no in 0..8 { - let start = 8 * line_no * width; + for offset in 0..y_repeat { + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 2); + let line_offset = usize::from(offset) * img_row_stride; + + for (idx, (mut pos, px)) in bit_indices + .zip(subbyte_values(interlaced_row, BIT_POS_2, 0b11)) + .enumerate() + { + let x_repeat = interlace_info.splat_pixel_repeat(idx); + pos.byte += line_offset; + expand_bits_to_img(img, px, pos, ..x_repeat, bits_per_pixel); + } + } + } + 4 => { + const BIT_POS_4: [u8; 2] = [4, 0]; + for offset in 0..y_repeat { + let bit_indices = expand_adam7_bits(img_row_stride, interlace_info, 4); + let line_offset = usize::from(offset) * img_row_stride; + + for (idx, (mut pos, px)) in bit_indices + .zip(subbyte_values(interlaced_row, BIT_POS_4, 0b1111)) + .enumerate() + { + let x_repeat = interlace_info.splat_pixel_repeat(idx); + pos.byte += line_offset; + expand_bits_to_img(img, px, pos, ..x_repeat, bits_per_pixel); + } + } + } + // While caught by the below loop, we special case this for codegen. The effects are + // massive when the compiler uses the constant chunk size in particular for this case where + // no more copy_from_slice is being issued by everything happens in the register alone. + 8 => { + for offset in 0..y_repeat { + let byte_indices = expand_adam7_bytes(img_row_stride, interlace_info, 1); + let line_offset = usize::from(offset) * img_row_stride; + + for (idx, (bytepos, px)) in byte_indices.zip(interlaced_row).enumerate() { + let x_repeat = usize::from(interlace_info.splat_pixel_repeat(idx)); + debug_assert!(x_repeat > 0); + img[line_offset + bytepos..][..x_repeat].fill(*px); + } + } + } + _ => { + debug_assert!(bits_per_pixel % 8 == 0); + let bytes = bits_per_pixel / 8; + let chunk = usize::from(bytes); + + for offset in 0..y_repeat { + let byte_indices = expand_adam7_bytes(img_row_stride, interlace_info, bytes); + let line_offset = usize::from(offset) * img_row_stride; + + for (idx, (bytepos, px)) in byte_indices + .zip(interlaced_row.chunks_exact(chunk)) + .enumerate() + { + let x_repeat = usize::from(interlace_info.splat_pixel_repeat(idx)); + let target = &mut img[line_offset + bytepos..][..chunk * x_repeat]; + + for target in target.chunks_exact_mut(chunk) { + target.copy_from_slice(px); + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_adam7() { + /* + 1646 + 7777 + 5656 + 7777 + */ + let it = Adam7Iterator::new(4, 4); + let passes: Vec<_> = it.collect(); assert_eq!( - expand_adam7_bits(1, width, line_no, bits_pp).collect::>(), - expected(start, 8, 4) + &*passes, + &[ + Adam7Info { + pass: 1, + line: 0, + samples: 1, + width: 4, + }, + Adam7Info { + pass: 4, + line: 0, + samples: 1, + width: 4, + }, + Adam7Info { + pass: 5, + line: 0, + samples: 2, + width: 4, + }, + Adam7Info { + pass: 6, + line: 0, + samples: 2, + width: 4, + }, + Adam7Info { + pass: 6, + line: 1, + samples: 2, + width: 4, + }, + Adam7Info { + pass: 7, + line: 0, + samples: 4, + width: 4, + }, + Adam7Info { + pass: 7, + line: 1, + samples: 4, + width: 4, + } + ] ); + } - let start = start + 4; + #[test] + fn test_subbyte_pixels() { + const BIT_POS_1: [u8; 8] = [7, 6, 5, 4, 3, 2, 1, 0]; - assert_eq!( - expand_adam7_bits(2, width, line_no, bits_pp).collect::>(), - expected(start, 8, 4) - ); + let scanline = &[0b10101010, 0b10101010]; + let pixels = subbyte_values(scanline, BIT_POS_1, 1).collect::>(); + + assert_eq!(pixels.len(), 16); + assert_eq!(pixels, [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]); + } + + #[test] + fn test_expand_adam7_bits() { + let width = 32; + let bits_pp = 1; + let stride = width / 8; + let info = + |pass, line, img_width| create_adam7_info_for_tests(pass, line as u32, img_width); + + let expected = |offset: usize, step: usize, count: usize| { + (0..count) + .map(move |i| step * i + offset) + .map(|i| BitPostion { + byte: i / 8, + bit: (i % 8) as u8, + }) + .collect::>() + }; + + for line_no in 0..8 { + let start = 8 * line_no * width; + + assert_eq!( + expand_adam7_bits(stride, &info(1, line_no, width), bits_pp).collect::>(), + expected(start, 8, 4) + ); + + let start = start + 4; + + assert_eq!( + expand_adam7_bits(stride, &info(2, line_no, width), bits_pp).collect::>(), + expected(start, 8, 4) + ); + + let start = (8 * line_no + 4) * width; + + assert_eq!( + expand_adam7_bits(stride, &info(3, line_no, width), bits_pp).collect::>(), + expected(start, 4, 8) + ); + } + + for line_no in 0..16 { + let start = 4 * line_no * width + 2; + + assert_eq!( + expand_adam7_bits(stride, &info(4, line_no, width), bits_pp).collect::>(), + expected(start, 4, 8) + ); + + let start = (4 * line_no + 2) * width; + + assert_eq!( + expand_adam7_bits(stride, &info(5, line_no, width), bits_pp).collect::>(), + expected(start, 2, 16) + ) + } + + for line_no in 0..32 { + let start = 2 * line_no * width + 1; + + assert_eq!( + expand_adam7_bits(stride, &info(6, line_no, width), bits_pp).collect::>(), + expected(start, 2, 16), + "line_no: {}", + line_no + ); + + let start = (2 * line_no + 1) * width; + + assert_eq!( + expand_adam7_bits(stride, &info(7, line_no, width), bits_pp).collect::>(), + expected(start, 1, 32) + ); + } + } + + #[test] + fn test_expand_adam7_bits_independent_row_stride() { + let pass = 1; + let line_no = 1; + let width = 32; + let info = create_adam7_info_for_tests; + + { + let stride = width; + assert_eq!( + expand_adam7_bytes(stride, &info(pass, line_no, width), 1).collect::>(), + [2048, 2112, 2176, 2240].map(|n| n / 8), + ); + } + + { + let stride = 10000; + assert_eq!( + expand_adam7_bytes(stride, &info(pass, line_no, width), 1).collect::>(), + [640000, 640064, 640128, 640192].map(|n| n / 8), + ); + } + } + + #[test] + fn test_expand_pass_subbyte() { + let mut img = [0u8; 8]; + let width = 8; + let stride = width / 8; + let bits_pp = 1; + let info = create_adam7_info_for_tests; - let start = (8 * line_no + 4) * width; + expand_pass(&mut img, stride, &[0b10000000], &info(1, 0, width), bits_pp); + assert_eq!(img, [0b10000000u8, 0, 0, 0, 0, 0, 0, 0]); + expand_pass(&mut img, stride, &[0b10000000], &info(2, 0, width), bits_pp); + assert_eq!(img, [0b10001000u8, 0, 0, 0, 0, 0, 0, 0]); + + expand_pass(&mut img, stride, &[0b11000000], &info(3, 0, width), bits_pp); + assert_eq!(img, [0b10001000u8, 0, 0, 0, 0b10001000, 0, 0, 0]); + + expand_pass(&mut img, stride, &[0b11000000], &info(4, 0, width), bits_pp); + assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10001000, 0, 0, 0]); + + expand_pass(&mut img, stride, &[0b11000000], &info(4, 1, width), bits_pp); + assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10101010, 0, 0, 0]); + + expand_pass(&mut img, stride, &[0b11110000], &info(5, 0, width), bits_pp); + assert_eq!(img, [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0, 0]); + + expand_pass(&mut img, stride, &[0b11110000], &info(5, 1, width), bits_pp); assert_eq!( - expand_adam7_bits(3, width, line_no, bits_pp).collect::>(), - expected(start, 4, 8) + img, + [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0] ); - } - for line_no in 0..16 { - let start = 4 * line_no * width + 2; + expand_pass(&mut img, stride, &[0b11110000], &info(6, 0, width), bits_pp); + assert_eq!( + img, + [0b11111111u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0] + ); + expand_pass(&mut img, stride, &[0b11110000], &info(6, 1, width), bits_pp); assert_eq!( - expand_adam7_bits(4, width, line_no, bits_pp).collect::>(), - expected(start, 4, 8) + img, + [0b11111111u8, 0, 0b11111111, 0, 0b10101010, 0, 0b10101010, 0] ); - let start = (4 * line_no + 2) * width; + expand_pass(&mut img, stride, &[0b11110000], &info(6, 2, width), bits_pp); + assert_eq!( + img, + [0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b10101010, 0] + ); + expand_pass(&mut img, stride, &[0b11110000], &info(6, 3, width), bits_pp); assert_eq!( - expand_adam7_bits(5, width, line_no, bits_pp).collect::>(), - expected(start, 2, 16) - ) - } + [0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b11111111, 0], + img + ); - for line_no in 0..32 { - let start = 2 * line_no * width + 1; + expand_pass(&mut img, stride, &[0b11111111], &info(7, 0, width), bits_pp); + assert_eq!( + [ + 0b11111111u8, + 0b11111111, + 0b11111111, + 0, + 0b11111111, + 0, + 0b11111111, + 0 + ], + img + ); + expand_pass(&mut img, stride, &[0b11111111], &info(7, 1, width), bits_pp); assert_eq!( - expand_adam7_bits(6, width, line_no, bits_pp).collect::>(), - expected(start, 2, 16), - "line_no: {}", - line_no + [ + 0b11111111u8, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0, + 0b11111111, + 0 + ], + img ); - let start = (2 * line_no + 1) * width; + expand_pass(&mut img, stride, &[0b11111111], &info(7, 2, width), bits_pp); + assert_eq!( + [ + 0b11111111u8, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0 + ], + img + ); + expand_pass(&mut img, stride, &[0b11111111], &info(7, 3, width), bits_pp); assert_eq!( - expand_adam7_bits(7, width, line_no, bits_pp).collect::>(), - expected(start, 1, 32) + [ + 0b11111111u8, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111 + ], + img ); } -} -#[test] -fn test_expand_pass_subbyte() { - let mut img = [0u8; 8]; - let width = 8; - let bits_pp = 1; - - expand_pass(&mut img, width, &[0b10000000], 1, 0, bits_pp); - assert_eq!(img, [0b10000000u8, 0, 0, 0, 0, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b10000000], 2, 0, bits_pp); - assert_eq!(img, [0b10001000u8, 0, 0, 0, 0, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b11000000], 3, 0, bits_pp); - assert_eq!(img, [0b10001000u8, 0, 0, 0, 0b10001000, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b11000000], 4, 0, bits_pp); - assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10001000, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b11000000], 4, 1, bits_pp); - assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10101010, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b11110000], 5, 0, bits_pp); - assert_eq!(img, [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0, 0]); - - expand_pass(&mut img, width, &[0b11110000], 5, 1, bits_pp); - assert_eq!( - img, - [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0] - ); - - expand_pass(&mut img, width, &[0b11110000], 6, 0, bits_pp); - assert_eq!( - img, - [0b11111111u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0] - ); - - expand_pass(&mut img, width, &[0b11110000], 6, 1, bits_pp); - assert_eq!( - img, - [0b11111111u8, 0, 0b11111111, 0, 0b10101010, 0, 0b10101010, 0] - ); - - expand_pass(&mut img, width, &[0b11110000], 6, 2, bits_pp); - assert_eq!( - img, - [0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b10101010, 0] - ); - - expand_pass(&mut img, width, &[0b11110000], 6, 3, bits_pp); - assert_eq!( - [0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b11111111, 0], - img - ); + // We use 4bpp as representative for bit-fiddling passes bpp 1, 2, 4. The choice was made + // because it is succinct to write in hex so one can read this and understand it. + #[test] + fn test_expand_pass_splat_4bpp() { + let width = 8; + let bits_pp = 4; + + let mut img = [0u8; 8]; + let stride = width / 2; + + let passes: &[(&'static [u8], &'static [u8])] = &[ + (&[0x10], &[0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11]), // pass 1, 0 + (&[0x20], &[0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x22, 0x22]), // pass 2, 0 + // no third pass.. + (&[0x4a], &[0x11, 0x44, 0x22, 0xaa, 0x11, 0x44, 0x22, 0xaa]), // pass 4, 0 + // no fifth pass.. + ( + &[0x6b, 0x6b], + &[0x16, 0x4b, 0x26, 0xab, 0x16, 0x4b, 0x26, 0xab], + ), // pass 6, 0 + ( + &[0x7c, 0xc7, 0x7c, 0x7c], + &[0x16, 0x4b, 0x26, 0xab, 0x7c, 0xc7, 0x7c, 0x7c], + ), // pass 7, 0 + ]; + + let adam7 = Adam7Iterator::new(8, 2); + for ((data, expected), adam7_info) in passes.iter().zip(adam7) { + expand_pass_splat(&mut img, stride, data, &adam7_info, bits_pp); + assert_eq!(img, *expected, "{img:x?} {expected:x?} {adam7_info:?}"); + } + } - expand_pass(&mut img, width, &[0b11111111], 7, 0, bits_pp); - assert_eq!( - [ - 0b11111111u8, - 0b11111111, - 0b11111111, - 0, - 0b11111111, - 0, - 0b11111111, - 0 - ], - img - ); + /// Check that our different Adam7 strategies lead to the same result once all interlace lines + /// have been applied. + #[test] + fn adam7_equivalence() { + // Choose ragged sizes to cover bugs that write outside etc. + const WIDTH: u32 = 8; + const HEIGHT: u32 = 8; + + let interace_pool: Vec<_> = (0x42u8..).take(32).collect(); + + for &bpp in &[1u8, 2, 4, 8, 16, 24, 32][2..] { + let bytes_of = |pix: u32| (u32::from(bpp) * pix).next_multiple_of(8) as usize / 8; + + let rowbytes = bytes_of(WIDTH); + + // In the sparse case we do not promise to override all bits + let mut buf_sparse = vec![0x00; rowbytes * HEIGHT as usize]; + // Whereas in the spat case we do, so we may as well set some arbitrary initial + let mut buf_splat = vec![0xaa; rowbytes * HEIGHT as usize]; + + // Now execute all the iterations, then compare buffers. + for adam7_info in Adam7Iterator::new(WIDTH, HEIGHT) { + let adam7_bytes = bytes_of(adam7_info.samples); + let interlace_line = &interace_pool[..adam7_bytes]; - expand_pass(&mut img, width, &[0b11111111], 7, 1, bits_pp); - assert_eq!( - [ - 0b11111111u8, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0, - 0b11111111, - 0 - ], - img - ); + expand_pass(&mut buf_sparse, rowbytes, interlace_line, &adam7_info, bpp); + expand_pass_splat(&mut buf_splat, rowbytes, interlace_line, &adam7_info, bpp); + } - expand_pass(&mut img, width, &[0b11111111], 7, 2, bits_pp); - assert_eq!( - [ - 0b11111111u8, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0 - ], - img - ); + assert_eq!( + buf_sparse, buf_splat, + "{buf_sparse:x?} {buf_splat:x?} bpp={bpp}" + ); + } + } - expand_pass(&mut img, width, &[0b11111111], 7, 3, bits_pp); - assert_eq!( - [ - 0b11111111u8, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111 - ], - img - ); + #[test] + fn test_expand_pass_splat_1bpp() { + let width = 8; + let bits_pp = 1; + + let mut img = [0u8; 8]; + let stride = 1; + + // Since bits do not suffice to represent the pass number in pixels we choose interlace + // rows such that we toggle all affected bits each time. In particular the input bits that + // must not be used are set to the inverse. + let passes: &[(&'static [u8], &'static [u8])] = &[ + (&[0x80], &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), // pass 1, 0 + (&[0x7f], &[0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0]), // pass 2, 0 + (&[0xc0], &[0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff]), // pass 3, 0 + (&[0x3f], &[0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff]), // pass 4, 0 + (&[0x3f], &[0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc]), // pass 4, 1 + (&[0xf0], &[0xc0, 0xc0, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xcc]), // pass 5, 0 + (&[0xf0], &[0xc0, 0xc0, 0xff, 0xff, 0xcc, 0xcc, 0xff, 0xff]), // pass 5, 1 + (&[0x0f], &[0x80, 0x80, 0xff, 0xff, 0xcc, 0xcc, 0xff, 0xff]), // pass 6, 0 + (&[0x0f], &[0x80, 0x80, 0xaa, 0xaa, 0xcc, 0xcc, 0xff, 0xff]), // pass 6, 1 + (&[0x0f], &[0x80, 0x80, 0xaa, 0xaa, 0x88, 0x88, 0xff, 0xff]), // pass 6, 2 + (&[0x0f], &[0x80, 0x80, 0xaa, 0xaa, 0x88, 0x88, 0xaa, 0xaa]), // pass 6, 3 + (&[0xff], &[0x80, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0xaa, 0xaa]), // pass 7, 0 + (&[0xff], &[0x80, 0xff, 0xaa, 0xff, 0x88, 0x88, 0xaa, 0xaa]), // pass 7, 1 + (&[0xff], &[0x80, 0xff, 0xaa, 0xff, 0x88, 0xff, 0xaa, 0xaa]), // pass 7, 2 + (&[0xff], &[0x80, 0xff, 0xaa, 0xff, 0x88, 0xff, 0xaa, 0xff]), // pass 7, 3 + ]; + + let adam7 = Adam7Iterator::new(width, 8); + for ((data, expected), adam7_info) in passes.iter().zip(adam7) { + expand_pass_splat(&mut img, stride, data, &adam7_info, bits_pp); + assert_eq!(img, *expected, "{img:x?} {expected:x?} {adam7_info:?}"); + } + } + + /// This test ensures that `expand_pass` works correctly on 32-bit machines, even when the indices + /// of individual bits in the target buffer can not be expressed within a `usize`. We ensure that + /// the output buffer size is between `usize::MAX / 8` and `isize::MAX` to trigger that condition. + #[cfg(target_pointer_width = "32")] + #[test] + fn regression_overflow_adam7_bitfill() { + fn multibyte_expand_pass_test_helper(width: usize, height: usize, bits_pp: u8) -> Vec { + let bytes_pp = bits_pp / 8; + let size = width * height * bytes_pp as usize; + let mut img = vec![0u8; size]; + let img_row_stride = width * bytes_pp as usize; + + for it in Adam7Iterator::new(width as u32, height as u32).into_iter() { + if it.pass != 7 { + continue; + } + + if it.line != (width / 2) as u32 - 1 { + continue; + } + + let interlace_size = it.width * (bytes_pp as u32); + // Ensure that expanded pixels are never empty bits. This differentiates the written bits + // from the initial bits that are all zeroed. + let interlaced_row: Vec<_> = (0..interlace_size).map(|_| 0xff).collect(); + + expand_pass(&mut img, img_row_stride, &interlaced_row, &it, bits_pp); + } + + img + } + + let expanded = multibyte_expand_pass_test_helper(1 << 14, 1 << 14, 32); + assert_eq!(*expanded.last().unwrap(), 0xff); + } + + #[cfg(test)] + fn create_adam7_info_for_tests(pass: u8, line: u32, img_width: usize) -> Adam7Info { + let width = { + let img_height = 8; + Adam7Iterator::new(img_width as u32, img_height) + .filter(|info| info.pass == pass) + .map(|info| info.samples) + .next() + .unwrap() + }; + + Adam7Info { + pass, + line, + samples: width, + width, + } + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/benchable_apis.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/benchable_apis.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/benchable_apis.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/benchable_apis.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,17 +1,36 @@ //! Development-time-only helper module for exporting private APIs so that they can be benchmarked. //! This module is gated behind the "benchmarks" feature. +use crate::adam7::{expand_pass, Adam7Iterator}; use crate::common::BytesPerPixel; -use crate::filter::FilterType; +use crate::filter::{Filter, RowFilter}; use crate::{BitDepth, ColorType, Info}; /// Re-exporting `unfilter` to make it easier to benchmark, despite some items being only /// `pub(crate)`: `fn unfilter`, `enum BytesPerPixel`. -pub fn unfilter(filter: FilterType, tbpp: u8, previous: &[u8], current: &mut [u8]) { +pub fn unfilter(filter: Filter, tbpp: u8, previous: &[u8], current: &mut [u8]) { + let filter = RowFilter::from_method(filter).unwrap(); // RowFilter type is private let tbpp = BytesPerPixel::from_usize(tbpp as usize); crate::filter::unfilter(filter, tbpp, previous, current) } +pub fn adam7(img: &mut [u8], buffer: &[u8], width: u32, height: u32, bpp: u8) { + fn bytes_of_width(width: u32, bpp: u8) -> usize { + let total = (u64::from(width) * u64::from(bpp)).div_ceil(8); + usize::try_from(total).unwrap() + } + + let img_row_stride = bytes_of_width(width, bpp); + for adam7 in Adam7Iterator::new(width as u32, height as u32).into_iter() { + // We use the same buffer for all interlace passes, to avoid counting the creation time in + // the benchmark here. But the expansion expects us to pass a slice so make sure we use the + // correct one. As of writing the implementation is not sensitive to this but it may become + // so. + let used_bytes = bytes_of_width(adam7.width, bpp); + expand_pass(img, img_row_stride, &buffer[..used_bytes], &adam7, bpp); + } +} + pub use crate::decoder::transform::{create_transform_fn, TransformFn}; pub fn create_info_from_plte_trns_bitdepth<'a>( diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/chunk.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/chunk.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/chunk.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/chunk.rs 2006-07-24 01:21:28.000000000 +0000 @@ -35,12 +35,22 @@ pub const sRGB: ChunkType = ChunkType(*b"sRGB"); /// ICC profile chunk pub const iCCP: ChunkType = ChunkType(*b"iCCP"); +/// Coding-independent code points for video signal type identification chunk +pub const cICP: ChunkType = ChunkType(*b"cICP"); +/// Mastering Display Color Volume chunk +pub const mDCV: ChunkType = ChunkType(*b"mDCV"); +/// Content Light Level Information chunk +pub const cLLI: ChunkType = ChunkType(*b"cLLI"); +/// EXIF metadata chunk +pub const eXIf: ChunkType = ChunkType(*b"eXIf"); /// Latin-1 uncompressed textual data pub const tEXt: ChunkType = ChunkType(*b"tEXt"); /// Latin-1 compressed textual data pub const zTXt: ChunkType = ChunkType(*b"zTXt"); /// UTF-8 textual data pub const iTXt: ChunkType = ChunkType(*b"iTXt"); +// Significant bits +pub const sBIT: ChunkType = ChunkType(*b"sBIT"); // -- Extension chunks -- diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/common.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/common.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/common.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/common.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,7 @@ //! Common types shared between the encoder and decoder -use crate::text_metadata::{EncodableTextChunk, ITXtChunk, TEXtChunk, ZTXtChunk}; +use crate::text_metadata::{ITXtChunk, TEXtChunk, ZTXtChunk}; +#[allow(unused_imports)] // used by doc comments only +use crate::Filter; use crate::{chunk, encoder}; use io::Write; use std::{borrow::Cow, convert::TryFrom, fmt, io}; @@ -77,6 +79,16 @@ || self == ColorType::Rgba)) || (bit_depth == BitDepth::Sixteen && self == ColorType::Indexed) } + + pub(crate) fn bits_per_pixel(&self, bit_depth: BitDepth) -> usize { + self.samples() * bit_depth as usize + } + + pub(crate) fn bytes_per_pixel(&self, bit_depth: BitDepth) -> usize { + // If adjusting this for expansion or other transformation passes, remember to keep the old + // implementation for bpp_in_prediction, which is internal to the png specification. + self.samples() * ((bit_depth as usize + 7) >> 3) + } } /// Bit depth of the PNG file. @@ -303,33 +315,107 @@ } /// The type and strength of applied compression. +/// +/// This is a simple, high-level interface that will automatically choose +/// the appropriate DEFLATE compression mode and PNG filter. +/// +/// If you need more control over the encoding parameters, +/// you can set the [DeflateCompression] and [Filter] manually. #[derive(Debug, Clone, Copy)] +#[non_exhaustive] pub enum Compression { - /// Default level - Default, - /// Fast minimal compression - Fast, - /// Higher compression level + /// No compression whatsoever. Fastest, but results in large files. + NoCompression, + /// Extremely fast but light compression. + /// + /// Note: When used in streaming mode, this compression level can actually result in files + /// *larger* than would be produced by `NoCompression` on incompressible data because + /// it doesn't do any buffering of the output stream to detect whether the data is being compressed or not. + Fastest, + /// Extremely fast compression with a decent compression ratio. /// - /// Best in this context isn't actually the highest possible level - /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2` - /// library. - Best, - #[deprecated( - since = "0.17.6", - note = "use one of the other compression levels instead, such as 'fast'" - )] - Huffman, - #[deprecated( - since = "0.17.6", - note = "use one of the other compression levels instead, such as 'fast'" - )] - Rle, + /// Significantly outperforms libpng and other popular encoders by using a [specialized DEFLATE + /// implementation tuned for PNG](https://crates.io/crates/fdeflate), while still providing + /// better compression ratio than the fastest modes of other encoders. + /// + /// Like `Compression::Fast` this can currently produce files larger than `NoCompression` in + /// streaming mode when given incompressible data. This may change in the future. + Fast, + /// Balances encoding speed and compression ratio + Balanced, + /// Spend much more time to produce a slightly smaller file than with `Balanced`. + High, } impl Default for Compression { fn default() -> Self { - Self::Default + Self::Balanced + } +} + +/// Advanced compression settings with more customization options than [Compression]. +/// +/// Note that this setting only affects DEFLATE compression. +/// Another setting that influences the compression ratio and lets you choose +/// between encoding speed and compression ratio is the [Filter]. +/// +/// ### Stability guarantees +/// +/// The implementation details of DEFLATE compression may evolve over time, +/// even without a semver-breaking change to the version of `png` crate. +/// +/// If a certain compression setting is superseded by other options, +/// it may be marked deprecated and remapped to a different option. +/// You will see a deprecation notice when compiling code relying on such options. +#[non_exhaustive] +#[derive(Debug, Clone, Copy)] +pub enum DeflateCompression { + /// Do not compress the data at all. + /// + /// Useful for incompressible images, or when speed is paramount and you don't care about size + /// at all. + /// + /// This mode also disables filters, forcing [Filter::NoFilter]. + NoCompression, + + /// Excellent for creating lightly compressed PNG images very quickly. + /// + /// Uses the [fdeflate](https://crates.io/crates/fdeflate) crate under the hood to achieve + /// speeds far exceeding what libpng is capable of while still providing a decent compression + /// ratio. + /// + /// Note: When used in streaming mode, this compression level can actually result in files + /// *larger* than would be produced by `NoCompression` because it doesn't do any buffering of + /// the output stream to detect whether the data is being compressed or not. + FdeflateUltraFast, + + /// Compression level between 1 and 9, where higher values mean better compression at the cost of + /// speed. + /// + /// This is currently implemented via [flate2](https://crates.io/crates/flate2) crate + /// by passing through the [compression level](flate2::Compression::new). + /// + /// The implementation details and the exact meaning of each level may change in the future, + /// including in semver-compatible releases. + Level(u8), + // Other variants can be added in the future +} + +impl Default for DeflateCompression { + fn default() -> Self { + Self::from_simple(Compression::Balanced) + } +} + +impl DeflateCompression { + pub(crate) fn from_simple(value: Compression) -> Self { + match value { + Compression::NoCompression => Self::NoCompression, + Compression::Fastest => Self::FdeflateUltraFast, + Compression::Fast => Self::FdeflateUltraFast, + Compression::Balanced => Self::Level(flate2::Compression::default().level() as u8), + Compression::High => Self::Level(flate2::Compression::best().level() as u8), + } } } @@ -343,7 +429,7 @@ /// Gets whether the value is within the clamped range of this type. pub fn in_range(value: f32) -> bool { - value >= 0.0 && (value * Self::SCALING).floor() <= std::u32::MAX as f32 + value >= 0.0 && (value * Self::SCALING).floor() <= u32::MAX as f32 } /// Gets whether the value can be exactly converted in round-trip. @@ -470,6 +556,95 @@ } } +/// Coding-independent code points (cICP) specify the color space (primaries), +/// transfer function, matrix coefficients and scaling factor of the image using +/// the code points specified in [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273). +/// +/// See https://www.w3.org/TR/png-3/#cICP-chunk for more details. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CodingIndependentCodePoints { + /// Id number of the color primaries defined in + /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 2 - + /// Interpretation of colour primaries (ColourPrimaries) value". + pub color_primaries: u8, + + /// Id number of the transfer characteristics defined in + /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 3 - + /// Interpretation of transfer characteristics (TransferCharacteristics) + /// value". + pub transfer_function: u8, + + /// Id number of the matrix coefficients defined in + /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 4 - + /// Interpretation of matrix coefficients (MatrixCoefficients) value". + /// + /// This field is included to faithfully replicate the base + /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but matrix coefficients + /// will always be set to 0, because RGB is currently the only supported color mode in PNG. + pub matrix_coefficients: u8, + + /// Whether the image is + /// [a full range image](https://www.w3.org/TR/png-3/#dfn-full-range-image) + /// or + /// [a narrow range image](https://www.w3.org/TR/png-3/#dfn-narrow-range-image). + /// + /// This field is included to faithfully replicate the base + /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but it has limited + /// practical application to PNG images, because narrow-range images are [quite + /// rare](https://github.com/w3c/png/issues/312#issuecomment-2327349614) in practice. + pub is_video_full_range_image: bool, +} + +/// Mastering Display Color Volume (mDCV) used at the point of content creation, +/// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899). +/// +/// See https://www.w3.org/TR/png-3/#mDCV-chunk for more details. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct MasteringDisplayColorVolume { + /// Mastering display chromaticities. + pub chromaticities: SourceChromaticities, + + /// Mastering display maximum luminance. + /// + /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field + /// is set to `10000000` then it indicates 1000 cd/m^2. + pub max_luminance: u32, + + /// Mastering display minimum luminance. + /// + /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field + /// is set to `10000000` then it indicates 1000 cd/m^2. + pub min_luminance: u32, +} + +/// Content light level information of HDR content. +/// +/// See https://www.w3.org/TR/png-3/#cLLI-chunk for more details. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ContentLightLevelInfo { + /// Maximum Content Light Level indicates the maximum light level of any + /// single pixel (in cd/m^2, also known as nits) of the entire playback + /// sequence. + /// + /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field + /// is set to `10000000` then it indicates 1000 cd/m^2. + /// + /// A value of zero means that the value is unknown or not currently calculable. + pub max_content_light_level: u32, + + /// Maximum Frame Average Light Level indicates the maximum value of the + /// frame average light level (in cd/m^2, also known as nits) of the entire + /// playback sequence. It is calculated by first averaging the decoded + /// luminance values of all the pixels in each frame, and then using the + /// value for the frame with the highest value. + /// + /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field + /// is set to `10000000` then it indicates 1000 cd/m^2. + /// + /// A value of zero means that the value is unknown or not currently calculable. + pub max_frame_average_light_level: u32, +} + /// PNG info struct #[derive(Clone, Debug)] #[non_exhaustive] @@ -480,6 +655,8 @@ /// How colors are stored in the image. pub color_type: ColorType, pub interlaced: bool, + /// The image's `sBIT` chunk, if present; contains significant bits of the sample. + pub sbit: Option>, /// The image's `tRNS` chunk, if present; contains the alpha channel of the image's palette, 1 byte per entry. pub trns: Option>, pub pixel_dims: Option, @@ -491,10 +668,11 @@ /// The contents of the image's `cHRM` chunk, if present. /// Prefer `source_chromaticities` to also get the derived replacements from sRGB chunks. pub chrm_chunk: Option, + /// The contents of the image's `bKGD` chunk, if present. + pub bkgd: Option>, pub frame_control: Option, pub animation_control: Option, - pub compression: Compression, /// Gamma of the source system. /// Set by both `gAMA` as well as to a replacement by `sRGB` chunk. pub source_gamma: Option, @@ -507,6 +685,14 @@ pub srgb: Option, /// The ICC profile for the image. pub icc_profile: Option>, + /// The coding-independent code points for video signal type identification of the image. + pub coding_independent_code_points: Option, + /// The mastering display color volume for the image. + pub mastering_display_color_volume: Option, + /// The content light information for the image. + pub content_light_level: Option, + /// The EXIF metadata for the image. + pub exif_metadata: Option>, /// tEXt field pub uncompressed_latin1_text: Vec, /// zTXt field @@ -524,19 +710,22 @@ color_type: ColorType::Grayscale, interlaced: false, palette: None, + sbit: None, trns: None, gama_chunk: None, chrm_chunk: None, + bkgd: None, pixel_dims: None, frame_control: None, animation_control: None, - // Default to `deflate::Compression::Fast` and `filter::FilterType::Sub` - // to maintain backward compatible output. - compression: Compression::Fast, source_gamma: None, source_chromaticities: None, srgb: None, icc_profile: None, + coding_independent_code_points: None, + mastering_display_color_volume: None, + content_light_level: None, + exif_metadata: None, uncompressed_latin1_text: Vec::new(), compressed_latin1_text: Vec::new(), utf8_text: Vec::new(), @@ -576,14 +765,14 @@ /// Returns the number of bits per pixel. pub fn bits_per_pixel(&self) -> usize { - self.color_type.samples() * self.bit_depth as usize + self.color_type.bits_per_pixel(self.bit_depth) } /// Returns the number of bytes per pixel. pub fn bytes_per_pixel(&self) -> usize { // If adjusting this for expansion or other transformation passes, remember to keep the old // implementation for bpp_in_prediction, which is internal to the png specification. - self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3) + self.color_type.bytes_per_pixel(self.bit_depth) } /// Return the number of bytes for this pixel used in prediction. @@ -618,71 +807,33 @@ .raw_row_length_from_width(self.bit_depth, width) } - /// Encode this header to the writer. - /// - /// Note that this does _not_ include the PNG signature, it starts with the IHDR chunk and then - /// includes other chunks that were added to the header. - pub fn encode(&self, mut w: W) -> encoder::Result<()> { - // Encode the IHDR chunk - let mut data = [0; 13]; - data[..4].copy_from_slice(&self.width.to_be_bytes()); - data[4..8].copy_from_slice(&self.height.to_be_bytes()); - data[8] = self.bit_depth as u8; - data[9] = self.color_type as u8; - data[12] = self.interlaced as u8; - encoder::write_chunk(&mut w, chunk::IHDR, &data)?; - // Encode the pHYs chunk - if let Some(pd) = self.pixel_dims { - let mut phys_data = [0; 9]; - phys_data[0..4].copy_from_slice(&pd.xppu.to_be_bytes()); - phys_data[4..8].copy_from_slice(&pd.yppu.to_be_bytes()); - match pd.unit { - Unit::Meter => phys_data[8] = 1, - Unit::Unspecified => phys_data[8] = 0, - } - encoder::write_chunk(&mut w, chunk::pHYs, &phys_data)?; - } - - if let Some(p) = &self.palette { - encoder::write_chunk(&mut w, chunk::PLTE, p)?; - }; - - if let Some(t) = &self.trns { - encoder::write_chunk(&mut w, chunk::tRNS, t)?; - } - - // If specified, the sRGB information overrides the source gamma and chromaticities. - if let Some(srgb) = &self.srgb { - let gamma = crate::srgb::substitute_gamma(); - let chromaticities = crate::srgb::substitute_chromaticities(); - srgb.encode(&mut w)?; - gamma.encode_gama(&mut w)?; - chromaticities.encode(&mut w)?; + /// Gamma dependent on sRGB chunk + pub fn gamma(&self) -> Option { + if self.srgb.is_some() { + Some(crate::srgb::substitute_gamma()) } else { - if let Some(gma) = self.source_gamma { - gma.encode_gama(&mut w)? - } - if let Some(chrms) = self.source_chromaticities { - chrms.encode(&mut w)?; - } - } - if let Some(actl) = self.animation_control { - actl.encode(&mut w)?; - } - - for text_chunk in &self.uncompressed_latin1_text { - text_chunk.encode(&mut w)?; - } - - for text_chunk in &self.compressed_latin1_text { - text_chunk.encode(&mut w)?; + self.gama_chunk } + } - for text_chunk in &self.utf8_text { - text_chunk.encode(&mut w)?; + /// Chromaticities dependent on sRGB chunk + pub fn chromaticities(&self) -> Option { + if self.srgb.is_some() { + Some(crate::srgb::substitute_chromaticities()) + } else { + self.chrm_chunk } + } - Ok(()) + /// Mark the image data as conforming to the SRGB color space with the specified rendering intent. + /// + /// Any ICC profiles will be ignored. + /// + /// Source gamma and chromaticities will be written only if they're set to fallback + /// values specified in [11.3.2.5](https://www.w3.org/TR/png-3/#sRGB-gAMA-cHRM). + pub(crate) fn set_source_srgb(&mut self, rendering_intent: SrgbRenderingIntent) { + self.srgb = Some(rendering_intent); + self.icc_profile = None; } } @@ -704,7 +855,7 @@ } } -bitflags! { +bitflags::bitflags! { /// Output transformations /// /// Many flags from libpng are not yet supported. A PR discussing/adding them would be nice. @@ -740,6 +891,7 @@ const SCALE_16 = 0x8000; // read only ``` "] + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Transformations: u32 { /// No transformation const IDENTITY = 0x00000; // read and write */ @@ -791,6 +943,10 @@ /// library will perform the checks necessary to ensure that data was accurate or error with a /// format error otherwise. PolledAfterEndOfImage, + /// Attempt to continue decoding after a fatal, non-resumable error was reported (e.g. after + /// [`DecodingError::Format`]). The only case when it is possible to resume after an error + /// is an `UnexpectedEof` scenario - see [`DecodingError::IoError`]. + PolledAfterFatalError, } impl From for ParameterError { @@ -807,6 +963,9 @@ write!(fmt, "wrong data size, expected {} got {}", expected, actual) } PolledAfterEndOfImage => write!(fmt, "End of image has been reached"), + PolledAfterFatalError => { + write!(fmt, "A fatal decoding error has been encounted earlier") + } } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/interlace_info.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/interlace_info.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/interlace_info.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/interlace_info.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,128 @@ +use std::ops::Range; + +use crate::adam7::{Adam7Info, Adam7Iterator}; + +/// Describes which interlacing algorithm applies to a decoded row. +/// +/// PNG (2003) specifies two interlace modes, but reserves future extensions. +/// +/// See also [Reader.next_interlaced_row](crate::Reader::next_interlaced_row). +#[derive(Clone, Copy, Debug)] +pub enum InterlaceInfo { + /// The `null` method means no interlacing. + Null(NullInfo), + /// [The `Adam7` algorithm](https://en.wikipedia.org/wiki/Adam7_algorithm) derives its name + /// from doing 7 passes over the image, only decoding a subset of all pixels in each pass. + /// The following table shows pictorially what parts of each 8x8 area of the image is found in + /// each pass: + /// + /// ```txt + /// 1 6 4 6 2 6 4 6 + /// 7 7 7 7 7 7 7 7 + /// 5 6 5 6 5 6 5 6 + /// 7 7 7 7 7 7 7 7 + /// 3 6 4 6 3 6 4 6 + /// 7 7 7 7 7 7 7 7 + /// 5 6 5 6 5 6 5 6 + /// 7 7 7 7 7 7 7 7 + /// ``` + Adam7(Adam7Info), +} + +#[derive(Clone, Copy, Debug)] +pub struct NullInfo { + line: u32, +} + +impl InterlaceInfo { + pub(crate) fn line_number(&self) -> u32 { + match self { + InterlaceInfo::Null(NullInfo { line }) => *line, + InterlaceInfo::Adam7(Adam7Info { line, .. }) => *line, + } + } + + pub(crate) fn get_adam7_info(&self) -> Option<&Adam7Info> { + match self { + InterlaceInfo::Null(_) => None, + InterlaceInfo::Adam7(adam7info) => Some(adam7info), + } + } +} + +pub(crate) struct InterlaceInfoIter(IterImpl); + +impl InterlaceInfoIter { + pub fn empty() -> Self { + Self(IterImpl::None(0..0)) + } + + pub fn new(width: u32, height: u32, interlaced: bool) -> Self { + if interlaced { + Self(IterImpl::Adam7(Adam7Iterator::new(width, height))) + } else { + Self(IterImpl::None(0..height)) + } + } +} + +impl Iterator for InterlaceInfoIter { + type Item = InterlaceInfo; + + fn next(&mut self) -> Option { + match self.0 { + IterImpl::Adam7(ref mut adam7) => Some(InterlaceInfo::Adam7(adam7.next()?)), + IterImpl::None(ref mut height) => Some(InterlaceInfo::Null(NullInfo { + line: height.next()?, + })), + } + } +} + +enum IterImpl { + None(Range), + Adam7(Adam7Iterator), +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn null() { + assert_eq!( + InterlaceInfoIter::new(8, 8, false) + .map(|info| info.line_number()) + .collect::>(), + vec![0, 1, 2, 3, 4, 5, 6, 7], + ); + } + + #[test] + fn adam7() { + assert_eq!( + InterlaceInfoIter::new(8, 8, true) + .map(|info| info.line_number()) + .collect::>(), + vec![ + 0, // pass 1 + 0, // pass 2 + 0, // pass 3 + 0, 1, // pass 4 + 0, 1, // pass 5 + 0, 1, 2, 3, // pass 6 + 0, 1, 2, 3, // pass 7 + ], + ); + } + + #[test] + fn empty() { + assert_eq!( + InterlaceInfoIter::empty() + .map(|info| info.line_number()) + .collect::>(), + vec![], + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,21 +1,27 @@ -mod stream; +mod interlace_info; +mod read_decoder; +pub(crate) mod stream; pub(crate) mod transform; +mod unfiltering_buffer; mod zlib; -pub use self::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder}; -use self::stream::{FormatErrorInner, CHUNCK_BUFFER_SIZE}; +use self::read_decoder::{ImageDataCompletionStatus, ReadDecoder}; +use self::stream::{DecodeOptions, DecodingError, FormatErrorInner}; use self::transform::{create_transform_fn, TransformFn}; +use self::unfiltering_buffer::UnfilteringBuffer; -use std::io::{BufRead, BufReader, Read}; +use std::io::{BufRead, Seek}; use std::mem; -use std::ops::Range; -use crate::adam7; -use crate::chunk; +use crate::adam7::Adam7Info; use crate::common::{ BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations, }; -use crate::filter::{unfilter, FilterType}; +use crate::FrameControl; +pub use zlib::{UnfilterBuf, UnfilterRegion}; + +pub use interlace_info::InterlaceInfo; +use interlace_info::InterlaceInfoIter; /* pub enum InterlaceHandling { @@ -81,7 +87,7 @@ } /// PNG Decoder -pub struct Decoder { +pub struct Decoder { read_decoder: ReadDecoder, /// Output transformations transform: Transformations, @@ -99,30 +105,11 @@ self.data } - pub fn interlace(&self) -> InterlaceInfo { - self.interlace + pub fn interlace(&self) -> &InterlaceInfo { + &self.interlace } } -/// PNG (2003) specifies two interlace modes, but reserves future extensions. -#[derive(Clone, Copy, Debug)] -pub enum InterlaceInfo { - /// the null method means no interlacing - Null, - /// Adam7 derives its name from doing 7 passes over the image, only decoding a subset of all pixels in each pass. - /// The following table shows pictorially what parts of each 8x8 area of the image is found in each pass: - /// - /// 1 6 4 6 2 6 4 6 - /// 7 7 7 7 7 7 7 7 - /// 5 6 5 6 5 6 5 6 - /// 7 7 7 7 7 7 7 7 - /// 3 6 4 6 3 6 4 6 - /// 7 7 7 7 7 7 7 7 - /// 5 6 5 6 5 6 5 6 - /// 7 7 7 7 7 7 7 7 - Adam7 { pass: u8, line: u32, width: u32 }, -} - /// A row of data without interlace information. #[derive(Clone, Copy, Debug)] pub struct Row<'data> { @@ -135,7 +122,7 @@ } } -impl Decoder { +impl Decoder { /// Create a new decoder configuration with default limits. pub fn new(r: R) -> Decoder { Decoder::new_with_limits(r, Limits::default()) @@ -143,30 +130,22 @@ /// Create a new decoder configuration with custom limits. pub fn new_with_limits(r: R, limits: Limits) -> Decoder { - let mut decoder = StreamingDecoder::new(); - decoder.limits = limits; + let mut read_decoder = ReadDecoder::new(r); + read_decoder.set_limits(limits); Decoder { - read_decoder: ReadDecoder { - reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r), - decoder, - at_eof: false, - }, + read_decoder, transform: Transformations::IDENTITY, } } - /// Create a new decoder configuration with custom `DecodeOptions`. + /// Create a new decoder configuration with custom [`DecodeOptions`]. pub fn new_with_options(r: R, decode_options: DecodeOptions) -> Decoder { - let mut decoder = StreamingDecoder::new_with_options(decode_options); - decoder.limits = Limits::default(); + let mut read_decoder = ReadDecoder::with_options(r, decode_options); + read_decoder.set_limits(Limits::default()); Decoder { - read_decoder: ReadDecoder { - reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r), - decoder, - at_eof: false, - }, + read_decoder, transform: Transformations::IDENTITY, } } @@ -181,21 +160,22 @@ /// /// ``` /// use std::fs::File; + /// use std::io::BufReader; /// use png::{Decoder, Limits}; /// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes. /// let mut limits = Limits::default(); /// limits.bytes = 3; - /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits); + /// let mut decoder = Decoder::new_with_limits(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()), limits); /// assert!(decoder.read_info().is_err()); /// /// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib /// let mut limits = Limits::default(); /// limits.bytes = 10*1024; - /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits); + /// let mut decoder = Decoder::new_with_limits(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()), limits); /// assert!(decoder.read_info().is_ok()); /// ``` pub fn set_limits(&mut self, limits: Limits) { - self.read_decoder.decoder.limits = limits; + self.read_decoder.set_limits(limits); } /// Read the PNG header and return the information contained within. @@ -203,55 +183,59 @@ /// Most image metadata will not be read until `read_info` is called, so those fields will be /// None or empty. pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> { - let mut buf = Vec::new(); - while self.read_decoder.info().is_none() { - buf.clear(); - if self.read_decoder.decode_next(&mut buf)?.is_none() { - return Err(DecodingError::Format( - FormatErrorInner::UnexpectedEof.into(), - )); - } - } - Ok(self.read_decoder.info().unwrap()) + self.read_decoder.read_header_info() } /// Reads all meta data until the first IDAT chunk pub fn read_info(mut self) -> Result, DecodingError> { - self.read_header_info()?; + let info = self.read_header_info()?; + let unfiltering_buffer = UnfilteringBuffer::new(info); let mut reader = Reader { decoder: self.read_decoder, bpp: BytesPerPixel::One, subframe: SubframeInfo::not_yet_init(), - fctl_read: 0, - next_frame: SubframeIdx::Initial, - data_stream: Vec::new(), - prev_start: 0, - current_start: 0, + remaining_frames: 0, // Temporary value - fixed below after reading `acTL` and `fcTL`. + unfiltering_buffer, transform: self.transform, transform_fn: None, scratch_buffer: Vec::new(), + finished: false, }; // Check if the decoding buffer of a single raw line has a valid size. + // + // FIXME: this check and the next can be delayed until processing image data. This would + // allow usage where only the metadata is processes, or where the image is processed + // line-by-line even on targets that can not fit the whole image into their address space. + // We should strive for a balance between implementation complexity (still ensure that the + // no-overflow preconditions are met for internal calculation) and use possibilities. if reader.info().checked_raw_row_length().is_none() { return Err(DecodingError::LimitsExceeded); } // Check if the output buffer has a valid size. - let (width, height) = reader.info().size(); - let (color, depth) = reader.output_color_type(); - let rowlen = color - .checked_raw_row_length(depth, width) - .ok_or(DecodingError::LimitsExceeded)? - - 1; - let height: usize = - std::convert::TryFrom::try_from(height).map_err(|_| DecodingError::LimitsExceeded)?; - if rowlen.checked_mul(height).is_none() { + // + // FIXME: see above and + // + if reader.output_buffer_size().is_none() { return Err(DecodingError::LimitsExceeded); } reader.read_until_image_data()?; + + reader.remaining_frames = match reader.info().animation_control.as_ref() { + None => 1, // No `acTL` => only expecting `IDAT` frame. + Some(animation) => { + let mut num_frames = animation.num_frames as usize; + if reader.info().frame_control.is_none() { + // No `fcTL` before `IDAT` => `IDAT` is not part of the animation, but + // represents an *extra*, default frame for non-APNG-aware decoders. + num_frames += 1; + } + num_frames + } + }; Ok(reader) } @@ -268,106 +252,49 @@ /// eg. /// ``` /// use std::fs::File; + /// use std::io::BufReader; /// use png::Decoder; - /// let mut decoder = Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap()); + /// let mut decoder = Decoder::new(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap())); /// decoder.set_ignore_text_chunk(true); /// assert!(decoder.read_info().is_ok()); /// ``` pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) { - self.read_decoder - .decoder - .set_ignore_text_chunk(ignore_text_chunk); + self.read_decoder.set_ignore_text_chunk(ignore_text_chunk); + } + + /// Set the decoder to ignore iccp chunks while parsing. + /// + /// eg. + /// ``` + /// use std::fs::File; + /// use std::io::BufReader; + /// use png::Decoder; + /// let mut decoder = Decoder::new(BufReader::new(File::open("tests/iccp/broken_iccp.png").unwrap())); + /// decoder.set_ignore_iccp_chunk(true); + /// assert!(decoder.read_info().is_ok()); + /// ``` + pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) { + self.read_decoder.set_ignore_iccp_chunk(ignore_iccp_chunk); } /// Set the decoder to ignore and not verify the Adler-32 checksum /// and CRC code. pub fn ignore_checksums(&mut self, ignore_checksums: bool) { - self.read_decoder - .decoder - .set_ignore_adler32(ignore_checksums); - self.read_decoder.decoder.set_ignore_crc(ignore_checksums); - } -} - -struct ReadDecoder { - reader: BufReader, - decoder: StreamingDecoder, - at_eof: bool, -} - -impl ReadDecoder { - /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written - /// into image_data. - fn decode_next(&mut self, image_data: &mut Vec) -> Result, DecodingError> { - while !self.at_eof { - let (consumed, result) = { - let buf = self.reader.fill_buf()?; - if buf.is_empty() { - return Err(DecodingError::Format( - FormatErrorInner::UnexpectedEof.into(), - )); - } - self.decoder.update(buf, image_data)? - }; - self.reader.consume(consumed); - match result { - Decoded::Nothing => (), - Decoded::ImageEnd => self.at_eof = true, - result => return Ok(Some(result)), - } - } - Ok(None) - } - - fn finish_decoding(&mut self) -> Result<(), DecodingError> { - while !self.at_eof { - let buf = self.reader.fill_buf()?; - if buf.is_empty() { - return Err(DecodingError::Format( - FormatErrorInner::UnexpectedEof.into(), - )); - } - let (consumed, event) = self.decoder.update(buf, &mut vec![])?; - self.reader.consume(consumed); - match event { - Decoded::Nothing => (), - Decoded::ImageEnd => self.at_eof = true, - // ignore more data - Decoded::ChunkComplete(_, _) | Decoded::ChunkBegin(_, _) | Decoded::ImageData => {} - Decoded::ImageDataFlushed => return Ok(()), - Decoded::PartialChunk(_) => {} - new => unreachable!("{:?}", new), - } - } - - Err(DecodingError::Format( - FormatErrorInner::UnexpectedEof.into(), - )) - } - - fn info(&self) -> Option<&Info<'static>> { - self.decoder.info.as_ref() + self.read_decoder.ignore_checksums(ignore_checksums); } } /// PNG reader (mostly high-level interface) /// /// Provides a high level that iterates over lines or whole images. -pub struct Reader { +pub struct Reader { decoder: ReadDecoder, bpp: BytesPerPixel, subframe: SubframeInfo, - /// Number of frame control chunks read. - /// By the APNG specification the total number must equal the count specified in the animation - /// control chunk. The IDAT image _may_ have such a chunk applying to it. - fctl_read: u32, - next_frame: SubframeIdx, - /// Vec containing the uncompressed image data currently being processed. - data_stream: Vec, - /// Index in `data_stream` where the previous row starts. - prev_start: usize, - /// Index in `data_stream` where the current row starts. - current_start: usize, + /// How many frames remain to be decoded. Decremented after each `IDAT` or `fdAT` sequence. + remaining_frames: usize, + /// Buffer with not-yet-`unfilter`-ed image rows + unfiltering_buffer: UnfilteringBuffer, /// Output transformations transform: Transformations, /// Function that can transform decompressed, unfiltered rows into final output. @@ -377,6 +304,8 @@ /// to a byte slice. In a future version of this library, this buffer will be removed and /// `next_row` and `next_interlaced_row` will write directly into a user provided output buffer. scratch_buffer: Vec, + /// Whether `ImageEnd` was already reached by `fn finish`. + finished: bool, } /// The subframe specific information. @@ -389,76 +318,56 @@ width: u32, height: u32, rowlen: usize, - interlace: InterlaceIter, + current_interlace_info: Option, + interlace_info_iter: InterlaceInfoIter, consumed_and_flushed: bool, } -#[derive(Clone)] -enum InterlaceIter { - None(Range), - Adam7(adam7::Adam7Iterator), -} - -/// Denote a frame as given by sequence numbers. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -enum SubframeIdx { - /// The initial frame in an IDAT chunk without fcTL chunk applying to it. - /// Note that this variant precedes `Some` as IDAT frames precede fdAT frames and all fdAT - /// frames must have a fcTL applying to it. - Initial, - /// An IDAT frame with fcTL or an fdAT frame. - Some(u32), - /// The past-the-end index. - End, -} +impl Reader { + /// Advances to the start of the next animation frame and + /// returns a reference to the `FrameControl` info that describes it. + /// Skips and discards the image data of the previous frame if necessary. + /// + /// Returns a [`ParameterError`] when there are no more animation frames. + /// To avoid this the caller can check if [`Info::animation_control`] exists + /// and consult [`AnimationControl::num_frames`]. + pub fn next_frame_info(&mut self) -> Result<&FrameControl, DecodingError> { + let remaining_frames = if self.subframe.consumed_and_flushed { + self.remaining_frames + } else { + // One remaining frame will be consumed by the `finish_decoding` call below. + self.remaining_frames - 1 + }; + if remaining_frames == 0 { + return Err(DecodingError::Parameter( + ParameterErrorKind::PolledAfterEndOfImage.into(), + )); + } + + if !self.subframe.consumed_and_flushed { + self.subframe.current_interlace_info = None; + self.finish_decoding()?; + } + self.read_until_image_data()?; + + // The PNG standard (and `StreamingDecoder `) guarantes that there is an `fcTL` chunk + // before the start of image data in a sequence of `fdAT` chunks. Therefore `unwrap` + // below is guaranteed to not panic. + Ok(self.info().frame_control.as_ref().unwrap()) + } -impl Reader { /// Reads all meta data until the next frame data starts. /// Requires IHDR before the IDAT and fcTL before fdAT. fn read_until_image_data(&mut self) -> Result<(), DecodingError> { - loop { - // This is somewhat ugly. The API requires us to pass a buffer to decode_next but we - // know that we will stop before reading any image data from the stream. Thus pass an - // empty buffer and assert that remains empty. - let mut buf = Vec::new(); - let state = self.decoder.decode_next(&mut buf)?; - assert!(buf.is_empty()); - - match state { - Some(Decoded::ChunkBegin(_, chunk::IDAT)) - | Some(Decoded::ChunkBegin(_, chunk::fdAT)) => break, - Some(Decoded::FrameControl(_)) => { - self.subframe = SubframeInfo::new(self.info()); - // The next frame is the one to which this chunk applies. - self.next_frame = SubframeIdx::Some(self.fctl_read); - // TODO: what about overflow here? That would imply there are more fctl chunks - // than can be specified in the animation control but also that we have read - // several gigabytes of data. - self.fctl_read += 1; - } - None => { - return Err(DecodingError::Format( - FormatErrorInner::MissingImageData.into(), - )) - } - // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT - // chunks and their control chunks. - _ => {} - } - } + self.decoder.read_until_image_data()?; - let info = self - .decoder - .info() - .ok_or(DecodingError::Format(FormatErrorInner::MissingIhdr.into()))?; - self.bpp = info.bpp_in_prediction(); - self.subframe = SubframeInfo::new(info); + self.subframe = SubframeInfo::new(self.info()); + self.bpp = self.info().bpp_in_prediction(); + self.unfiltering_buffer.reset_all(); // Allocate output buffer. - let buflen = self.output_line_size(self.subframe.width); - self.decoder.decoder.limits.reserve_bytes(buflen)?; - - self.prev_start = self.current_start; + let buflen = self.unguarded_output_line_size(self.subframe.width); + self.decoder.reserve_bytes(buflen)?; Ok(()) } @@ -484,25 +393,28 @@ /// Output lines will be written in row-major, packed matrix with width and height of the read /// frame (or subframe), all samples are in big endian byte order where this matters. pub fn next_frame(&mut self, buf: &mut [u8]) -> Result { - let subframe_idx = match self.decoder.info().unwrap().frame_control() { - None => SubframeIdx::Initial, - Some(_) => SubframeIdx::Some(self.fctl_read - 1), - }; - - if self.next_frame == SubframeIdx::End { + if self.remaining_frames == 0 { return Err(DecodingError::Parameter( ParameterErrorKind::PolledAfterEndOfImage.into(), )); - } else if self.next_frame != subframe_idx { - // Advance until we've read the info / fcTL for this frame. + } else if self.subframe.consumed_and_flushed { + // Advance until the next `fdAT` + // (along the way we should encounter the fcTL for this frame). self.read_until_image_data()?; } - if buf.len() < self.output_buffer_size() { + // Note that we only check if the buffer size calculation holds in a call to decoding the + // frame. Consequently, we can represent the `Info` and frameless decoding even when the + // target architecture's address space is too small for a frame. However reading the actual + let required_len = self + .output_buffer_size() + .ok_or(DecodingError::LimitsExceeded)?; + + if buf.len() < required_len { return Err(DecodingError::Parameter( ParameterErrorKind::ImageBufferSize { - expected: buf.len(), - actual: self.output_buffer_size(), + expected: required_len, + actual: buf.len(), } .into(), )); @@ -514,112 +426,158 @@ height: self.subframe.height, color_type, bit_depth, - line_size: self.output_line_size(self.subframe.width), + line_size: self.unguarded_output_line_size(self.subframe.width), }; - self.data_stream.clear(); - self.current_start = 0; - self.prev_start = 0; - let width = self.info().width; if self.info().interlaced { + let stride = self.unguarded_output_line_size(self.info().width); + let samples = color_type.samples() as u8; + let bits_pp = samples * (bit_depth as u8); + let expand = crate::adam7::expand_pass; + while let Some(InterlacedRow { data: row, interlace, .. }) = self.next_interlaced_row()? { - let (line, pass) = match interlace { - InterlaceInfo::Adam7 { line, pass, .. } => (line, pass), - InterlaceInfo::Null => unreachable!("expected interlace information"), - }; - let samples = color_type.samples() as u8; - adam7::expand_pass(buf, width, row, pass, line, samples * (bit_depth as u8)); + // `unwrap` won't panic, because we checked `self.info().interlaced` above. + let adam7info = interlace.get_adam7_info().unwrap(); + expand(buf, stride, row, adam7info, bits_pp); } } else { + let current_interlace_info = self.subframe.current_interlace_info.as_ref(); + let already_done_rows = current_interlace_info + .map(|info| info.line_number()) + .unwrap_or(self.subframe.height); + for row in buf .chunks_exact_mut(output_info.line_size) .take(self.subframe.height as usize) + .skip(already_done_rows as usize) { self.next_interlaced_row_impl(self.subframe.rowlen, row)?; } } // Advance over the rest of data for this (sub-)frame. + self.finish_decoding()?; + + Ok(output_info) + } + + fn mark_subframe_as_consumed_and_flushed(&mut self) { + assert!(self.remaining_frames > 0); + self.remaining_frames -= 1; + + self.subframe.consumed_and_flushed = true; + } + + /// Advance over the rest of data for this (sub-)frame. + /// Called after decoding the last row of a frame. + fn finish_decoding(&mut self) -> Result<(), DecodingError> { + // Double-check that all rows of this frame have been decoded (i.e. that the potential + // `finish_decoding` call below won't be discarding any data). + assert!(self.subframe.current_interlace_info.is_none()); + + // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks. if !self.subframe.consumed_and_flushed { - self.decoder.finish_decoding()?; + self.decoder.finish_decoding_image_data()?; + self.mark_subframe_as_consumed_and_flushed(); } - // Advance our state to expect the next frame. - let past_end_subframe = self - .info() - .animation_control() - .map(|ac| ac.num_frames) - .unwrap_or(0); - self.next_frame = match self.next_frame { - SubframeIdx::End => unreachable!("Next frame called when already at image end"), - // Reached the end of non-animated image. - SubframeIdx::Initial if past_end_subframe == 0 => SubframeIdx::End, - // An animated image, expecting first subframe. - SubframeIdx::Initial => SubframeIdx::Some(0), - // This was the last subframe, slightly fuzzy condition in case of programmer error. - SubframeIdx::Some(idx) if past_end_subframe <= idx + 1 => SubframeIdx::End, - // Expecting next subframe. - SubframeIdx::Some(idx) => SubframeIdx::Some(idx + 1), - }; - - Ok(output_info) + Ok(()) } - /// Returns the next processed row of the image - pub fn next_row(&mut self) -> Result, DecodingError> { + /// Returns the next processed row of the image (discarding `InterlaceInfo`). + /// + /// See also [`Reader.read_row`], which reads into a caller-provided buffer. + pub fn next_row(&mut self) -> Result>, DecodingError> { self.next_interlaced_row() .map(|v| v.map(|v| Row { data: v.data })) } - /// Returns the next processed row of the image - pub fn next_interlaced_row(&mut self) -> Result, DecodingError> { - let (rowlen, interlace) = match self.next_pass() { - Some((rowlen, interlace)) => (rowlen, interlace), - None => return Ok(None), - }; + /// Returns the next processed row of the image. + /// + /// See also [`Reader.read_row`], which reads into a caller-provided buffer. + pub fn next_interlaced_row(&mut self) -> Result>, DecodingError> { + let mut output_buffer = mem::take(&mut self.scratch_buffer); + let max_line_size = self + .output_line_size(self.info().width) + .ok_or(DecodingError::LimitsExceeded)?; + output_buffer.resize(max_line_size, 0u8); + let result = self.read_row(&mut output_buffer); + self.scratch_buffer = output_buffer; + result.map(move |option| { + option.map(move |interlace| { + let output_line_size = self.output_line_size_for_interlace_info(&interlace); + InterlacedRow { + data: &self.scratch_buffer[..output_line_size], + interlace, + } + }) + }) + } - let width = if let InterlaceInfo::Adam7 { width, .. } = interlace { - width - } else { - self.subframe.width + /// Reads the next row of the image into the provided `output_buffer`. + /// `Ok(None)` will be returned if the current image frame has no more rows. + /// + /// `output_buffer` needs to be long enough to accommodate [`Reader.output_line_size`] for + /// [`Info.width`] (initial interlaced rows may need less than that). + /// + /// See also [`Reader.next_row`] and [`Reader.next_interlaced_row`], which read into a + /// `Reader`-owned buffer. + pub fn read_row( + &mut self, + output_buffer: &mut [u8], + ) -> Result, DecodingError> { + let interlace = match self.subframe.current_interlace_info.as_ref() { + None => { + self.finish_decoding()?; + return Ok(None); + } + Some(interlace) => *interlace, + }; + if interlace.line_number() == 0 { + self.unfiltering_buffer.reset_prev_row(); + } + let rowlen = match interlace { + InterlaceInfo::Null(_) => self.subframe.rowlen, + InterlaceInfo::Adam7(Adam7Info { samples: width, .. }) => { + self.info().raw_row_length_from_width(width) + } }; - let output_line_size = self.output_line_size(width); - // TODO: change the interface of `next_interlaced_row` to take an output buffer instead of - // making us return a reference to a buffer that we own. - let mut output_buffer = mem::take(&mut self.scratch_buffer); - output_buffer.resize(output_line_size, 0u8); - let ret = self.next_interlaced_row_impl(rowlen, &mut output_buffer); - self.scratch_buffer = output_buffer; - ret?; + let output_line_size = self.output_line_size_for_interlace_info(&interlace); + let output_buffer = &mut output_buffer[..output_line_size]; - Ok(Some(InterlacedRow { - data: &self.scratch_buffer[..output_line_size], - interlace, - })) + self.next_interlaced_row_impl(rowlen, output_buffer)?; + + Ok(Some(interlace)) + } + + fn output_line_size_for_interlace_info(&self, interlace: &InterlaceInfo) -> usize { + let width = match interlace { + InterlaceInfo::Adam7(Adam7Info { samples: width, .. }) => *width, + InterlaceInfo::Null(_) => self.subframe.width, + }; + self.unguarded_output_line_size(width) } /// Read the rest of the image and chunks and finish up, including text chunks or others /// This will discard the rest of the image if the image is not read already with [`Reader::next_frame`], [`Reader::next_row`] or [`Reader::next_interlaced_row`] pub fn finish(&mut self) -> Result<(), DecodingError> { - self.next_frame = SubframeIdx::End; - self.data_stream.clear(); - self.current_start = 0; - self.prev_start = 0; - loop { - let mut buf = Vec::new(); - let state = self.decoder.decode_next(&mut buf)?; - - if state.is_none() { - break; - } + if self.finished { + return Err(DecodingError::Parameter( + ParameterErrorKind::PolledAfterEndOfImage.into(), + )); } + self.remaining_frames = 0; + self.unfiltering_buffer.reset_all(); + self.decoder.read_until_end_of_input()?; + + self.finished = true; Ok(()) } @@ -630,8 +588,8 @@ output_buffer: &mut [u8], ) -> Result<(), DecodingError> { self.next_raw_interlaced_row(rowlen)?; - assert_eq!(self.current_start - self.prev_start, rowlen - 1); - let row = &self.data_stream[self.prev_start..self.current_start]; + let row = self.unfiltering_buffer.prev_row(); + assert_eq!(row.len(), rowlen - 1); // Apply transformations and write resulting data to buffer. let transform_fn = { @@ -642,6 +600,7 @@ }; transform_fn(row, output_buffer, self.info()); + self.subframe.current_interlace_info = self.subframe.interlace_info_iter.next(); Ok(()) } @@ -681,96 +640,60 @@ } } - /// Returns the number of bytes required to hold a deinterlaced image frame - /// that is decoded using the given input transformations. - pub fn output_buffer_size(&self) -> usize { + /// Return the number of bytes required to hold a deinterlaced image frame that is decoded + /// using the given input transformations. + /// + /// Returns `None` if the output buffer does not fit into the memory space of the machine, + /// otherwise returns the byte length in `Some`. The length is smaller than [`isize::MAX`]. + pub fn output_buffer_size(&self) -> Option { let (width, height) = self.info().size(); - let size = self.output_line_size(width); - size * height as usize + let (color, depth) = self.output_color_type(); + // The subtraction should always work, but we do this for consistency. Also note that by + // calling `checked_raw_row_length` the row buffer is guaranteed to work whereas if we + // ran other function that didn't include the filter byte that could later fail on an image + // that is `1xN`... + let linelen = color.checked_raw_row_length(depth, width)?.checked_sub(1)?; + let height = usize::try_from(height).ok()?; + let imglen = linelen.checked_mul(height)?; + // Ensure that it fits into address space not only `usize` to allocate. + (imglen <= isize::MAX as usize).then_some(imglen) } /// Returns the number of bytes required to hold a deinterlaced row. - pub fn output_line_size(&self, width: u32) -> usize { + pub(crate) fn unguarded_output_line_size(&self, width: u32) -> usize { let (color, depth) = self.output_color_type(); color.raw_row_length_from_width(depth, width) - 1 } - fn next_pass(&mut self) -> Option<(usize, InterlaceInfo)> { - match self.subframe.interlace { - InterlaceIter::Adam7(ref mut adam7) => { - let last_pass = adam7.current_pass(); - let (pass, line, width) = adam7.next()?; - let rowlen = self.info().raw_row_length_from_width(width); - if last_pass != pass { - self.prev_start = self.current_start; - } - Some((rowlen, InterlaceInfo::Adam7 { pass, line, width })) - } - InterlaceIter::None(ref mut height) => { - let _ = height.next()?; - Some((self.subframe.rowlen, InterlaceInfo::Null)) - } - } + /// Returns the number of bytes required to hold a deinterlaced row. + /// + /// Returns `None` if the output buffer does not fit into the memory space of the machine, + /// otherwise returns the byte length in `Some`. The length is smaller than [`isize::MAX`]. + pub fn output_line_size(&self, width: u32) -> Option { + let (color, depth) = self.output_color_type(); + let length = color.checked_raw_row_length(depth, width)?.checked_sub(1)?; + // Ensure that it fits into address space not only `usize` to allocate. + (length <= isize::MAX as usize).then_some(length) } - /// Write the next raw interlaced row into `self.prev`. - /// - /// The scanline is filtered against the previous scanline according to the specification. + /// Unfilter the next raw interlaced row into `self.unfiltering_buffer`. fn next_raw_interlaced_row(&mut self, rowlen: usize) -> Result<(), DecodingError> { // Read image data until we have at least one full row (but possibly more than one). - while self.data_stream.len() - self.current_start < rowlen { + while self.unfiltering_buffer.curr_row_len() < rowlen { if self.subframe.consumed_and_flushed { return Err(DecodingError::Format( FormatErrorInner::NoMoreImageData.into(), )); } - // Clear the current buffer before appending more data. - if self.prev_start > 0 { - self.data_stream.copy_within(self.prev_start.., 0); - self.data_stream - .truncate(self.data_stream.len() - self.prev_start); - self.current_start -= self.prev_start; - self.prev_start = 0; - } - - match self.decoder.decode_next(&mut self.data_stream)? { - Some(Decoded::ImageData) => {} - Some(Decoded::ImageDataFlushed) => { - self.subframe.consumed_and_flushed = true; - } - None => { - return Err(DecodingError::Format( - if self.data_stream.is_empty() { - FormatErrorInner::NoMoreImageData - } else { - FormatErrorInner::UnexpectedEndOfChunk - } - .into(), - )); - } - _ => (), + let mut buffer = self.unfiltering_buffer.as_unfilled_buffer(); + match self.decoder.decode_image_data(Some(&mut buffer))? { + ImageDataCompletionStatus::ExpectingMoreData => (), + ImageDataCompletionStatus::Done => self.mark_subframe_as_consumed_and_flushed(), } } - // Get a reference to the current row and point scan_start to the next one. - let (prev, row) = self.data_stream.split_at_mut(self.current_start); - - // Unfilter the row. - let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format( - FormatErrorInner::UnknownFilterMethod(row[0]).into(), - ))?; - unfilter( - filter, - self.bpp, - &prev[self.prev_start..], - &mut row[1..rowlen], - ); - - self.prev_start = self.current_start + 1; - self.current_start += rowlen; - - Ok(()) + self.unfiltering_buffer.unfilter_curr_row(rowlen, self.bpp) } } @@ -780,7 +703,8 @@ width: 0, height: 0, rowlen: 0, - interlace: InterlaceIter::None(0..0), + current_interlace_info: None, + interlace_info_iter: InterlaceInfoIter::empty(), consumed_and_flushed: false, } } @@ -794,17 +718,14 @@ (info.width, info.height) }; - let interlace = if info.interlaced { - InterlaceIter::Adam7(adam7::Adam7Iterator::new(width, height)) - } else { - InterlaceIter::None(0..height) - }; - + let mut interlace_info_iter = InterlaceInfoIter::new(width, height, info.interlaced); + let current_interlace_info = interlace_info_iter.next(); SubframeInfo { width, height, rowlen: info.raw_row_length_from_width(width), - interlace, + current_interlace_info, + interlace_info_iter, consumed_and_flushed: false, } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/read_decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/read_decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/read_decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/read_decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,153 @@ +use super::stream::{DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder}; +use super::zlib::UnfilterBuf; +use super::Limits; + +use std::io::{BufRead, ErrorKind, Read, Seek}; + +use crate::chunk; +use crate::common::Info; + +/// Helper for encapsulating reading input from `Read` and feeding it into a `StreamingDecoder` +/// while hiding low-level `Decoded` events and only exposing a few high-level reading operations +/// like: +/// +/// * `read_header_info` - reading until `IHDR` chunk +/// * `read_until_image_data` - reading until `IDAT` / `fdAT` sequence +/// * `decode_image_data` - reading from `IDAT` / `fdAT` sequence into `Vec` +/// * `finish_decoding_image_data()` - discarding remaining data from `IDAT` / `fdAT` sequence +/// * `read_until_end_of_input()` - reading until `IEND` chunk +pub(crate) struct ReadDecoder { + reader: R, + decoder: StreamingDecoder, +} + +impl ReadDecoder { + pub fn new(r: R) -> Self { + Self { + reader: r, + decoder: StreamingDecoder::new(), + } + } + + pub fn with_options(r: R, options: DecodeOptions) -> Self { + let mut decoder = StreamingDecoder::new_with_options(options); + decoder.limits = Limits::default(); + + Self { reader: r, decoder } + } + + pub fn set_limits(&mut self, limits: Limits) { + self.decoder.limits = limits; + } + + pub fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> { + self.decoder.limits.reserve_bytes(bytes) + } + + pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) { + self.decoder.set_ignore_text_chunk(ignore_text_chunk); + } + + pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) { + self.decoder.set_ignore_iccp_chunk(ignore_iccp_chunk); + } + + pub fn ignore_checksums(&mut self, ignore_checksums: bool) { + self.decoder.set_ignore_adler32(ignore_checksums); + self.decoder.set_ignore_crc(ignore_checksums); + } + + /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written + /// into image_data. + fn decode_next( + &mut self, + image_data: Option<&mut UnfilterBuf<'_>>, + ) -> Result { + let (consumed, result) = { + let buf = self.reader.fill_buf()?; + if buf.is_empty() { + return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into())); + } + self.decoder.update(buf, image_data)? + }; + self.reader.consume(consumed); + Ok(result) + } + + /// Reads until the end of `IHDR` chunk. + /// + /// Prerequisite: None (idempotent). + pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> { + while self.info().is_none() { + if let Decoded::ChunkComplete(chunk::IEND) = self.decode_next(None)? { + unreachable!() + } + } + Ok(self.info().unwrap()) + } + + /// Reads until the start of the next `IDAT` or `fdAT` chunk. + /// + /// Prerequisite: **Not** within `IDAT` / `fdAT` chunk sequence. + pub fn read_until_image_data(&mut self) -> Result<(), DecodingError> { + loop { + match self.decode_next(None)? { + Decoded::ChunkBegin(_, chunk::IDAT) | Decoded::ChunkBegin(_, chunk::fdAT) => break, + Decoded::ChunkComplete(chunk::IEND) => { + return Err(DecodingError::Format( + FormatErrorInner::MissingImageData.into(), + )) + } + // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT + // chunks and their control chunks. + _ => {} + } + } + Ok(()) + } + + /// Reads `image_data` and reports whether there may be additional data afterwards (i.e. if it + /// is okay to call `decode_image_data` and/or `finish_decoding_image_data` again).. + /// + /// Prerequisite: Input is currently positioned within `IDAT` / `fdAT` chunk sequence. + pub fn decode_image_data( + &mut self, + image_data: Option<&mut UnfilterBuf<'_>>, + ) -> Result { + match self.decode_next(image_data)? { + Decoded::ImageData => Ok(ImageDataCompletionStatus::ExpectingMoreData), + Decoded::ImageDataFlushed => Ok(ImageDataCompletionStatus::Done), + // Ignore other events that may happen within an `IDAT` / `fdAT` chunks sequence. + _ => Ok(ImageDataCompletionStatus::ExpectingMoreData), + } + } + + /// Consumes and discards the rest of an `IDAT` / `fdAT` chunk sequence. + /// + /// Prerequisite: Input is currently positioned within `IDAT` / `fdAT` chunk sequence. + pub fn finish_decoding_image_data(&mut self) -> Result<(), DecodingError> { + loop { + if let ImageDataCompletionStatus::Done = self.decode_image_data(None)? { + return Ok(()); + } + } + } + + /// Reads until the `IEND` chunk. + /// + /// Prerequisite: `IEND` chunk hasn't been reached yet. + pub fn read_until_end_of_input(&mut self) -> Result<(), DecodingError> { + while !matches!(self.decode_next(None)?, Decoded::ChunkComplete(chunk::IEND)) {} + Ok(()) + } + + pub fn info(&self) -> Option<&Info<'static>> { + self.decoder.info.as_ref() + } +} + +#[derive(Debug, Eq, PartialEq)] +pub(crate) enum ImageDataCompletionStatus { + ExpectingMoreData, + Done, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/stream.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/stream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/stream.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/stream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,4 @@ -extern crate crc32fast; - -use std::convert::{From, TryInto}; -use std::default::Default; +use std::convert::TryInto; use std::error; use std::fmt; use std::io; @@ -9,23 +6,26 @@ use crc32fast::Hasher as Crc32; +use super::zlib::UnfilterBuf; use super::zlib::ZlibStream; +use crate::chunk::is_critical; use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR}; use crate::common::{ - AnimationControl, BitDepth, BlendOp, ColorType, DisposeOp, FrameControl, Info, ParameterError, - PixelDimensions, ScaledFloat, SourceChromaticities, Unit, + AnimationControl, BitDepth, BlendOp, ColorType, ContentLightLevelInfo, DisposeOp, FrameControl, + Info, MasteringDisplayColorVolume, ParameterError, ParameterErrorKind, PixelDimensions, + ScaledFloat, SourceChromaticities, Unit, }; use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk}; use crate::traits::ReadBytesExt; -use crate::Limits; +use crate::{CodingIndependentCodePoints, Limits}; -/// TODO check if these size are reasonable -pub const CHUNCK_BUFFER_SIZE: usize = 32 * 1024; +pub const CHUNK_BUFFER_SIZE: usize = 128; /// Determines if checksum checks should be disabled globally. /// /// This is used only in fuzzing. `afl` automatically adds `--cfg fuzzing` to RUSTFLAGS which can /// be used to detect that build. +#[allow(unexpected_cfgs)] const CHECKSUM_DISABLED: bool = cfg!(fuzzing); /// Kind of `u32` value that is being read via `State::U32`. @@ -62,11 +62,8 @@ accumulated_count: usize, }, /// In this state we are reading chunk data from external input, and appending it to - /// `ChunkState::raw_bytes`. + /// `ChunkState::raw_bytes`. Then if all data has been read, we parse the chunk. ReadChunkData(ChunkType), - /// In this state we check if all chunk data has been already read into `ChunkState::raw_bytes` - /// and if so then we parse the chunk. Otherwise, we go back to the `ReadChunkData` state. - ParseChunkData(ChunkType), /// In this state we are reading image data from external input and feeding it directly into /// `StreamingDecoder::inflater`. ImageData(ChunkType), @@ -87,20 +84,28 @@ pub enum Decoded { /// Nothing decoded yet Nothing, - Header(u32, u32, BitDepth, ColorType, bool), + + /// A chunk header (length and type fields) has been read. ChunkBegin(u32, ChunkType), - ChunkComplete(u32, ChunkType), - PixelDimensions(PixelDimensions), - AnimationControl(AnimationControl), - FrameControl(FrameControl), + + /// Chunk has been read successfully. + ChunkComplete(ChunkType), + + /// An ancillary chunk has been read but it was in the wrong place, had corrupt contents, or had + /// an invalid CRC. + BadAncillaryChunk(ChunkType), + + /// Skipped an ancillary chunk because it was unrecognized or the decoder was configured to skip + /// this type of chunk. + SkippedAncillaryChunk(ChunkType), + /// Decoded raw image data. ImageData, + /// The last of a consecutive chunk of IDAT was done. /// This is distinct from ChunkComplete which only marks that some IDAT chunk was completed but /// not that no additional IDAT chunk follows. ImageDataFlushed, - PartialChunk(ChunkType), - ImageEnd, } /// Any kind of error during PNG decoding. @@ -111,6 +116,11 @@ #[derive(Debug)] pub enum DecodingError { /// An error in IO of the underlying reader. + /// + /// Note that some IO errors may be recoverable - decoding may be retried after the + /// error is resolved. For example, decoding from a slow stream of data (e.g. decoding from a + /// network stream) may occasionally result in [std::io::ErrorKind::UnexpectedEof] kind of + /// error, but decoding can resume when more data becomes available. IoError(io::Error), /// The input image was not a valid PNG. /// @@ -163,13 +173,7 @@ }, /// Not a PNG, the magic signature is missing. InvalidSignature, - /// End of file, within a chunk event. - UnexpectedEof, - /// End of file, while expecting more image data. - UnexpectedEndOfChunk, // Errors of chunk level ordering, missing etc. - /// Ihdr must occur. - MissingIhdr, /// Fctl must occur if an animated chunk occurs. MissingFctl, /// Image data that was indicated in IHDR or acTL is missing. @@ -182,6 +186,10 @@ AfterIdat { kind: ChunkType, }, + // 4.3., Some chunks must be after PLTE. + BeforePlte { + kind: ChunkType, + }, /// 4.3., some chunks must be before PLTE. AfterPlte { kind: ChunkType, @@ -207,6 +215,16 @@ expected: usize, len: usize, }, + /// sBIT chunk size based on color type. + InvalidSbitChunkSize { + color_type: ColorType, + expected: usize, + len: usize, + }, + InvalidSbit { + sample_depth: BitDepth, + sbit: u8, + }, /// A palletized image did not have a palette. PaletteRequired, /// The color-depth combination is not valid according to Table 11.1. @@ -230,7 +248,7 @@ /// The subframe is not in bounds of the image. /// TODO: fields with relevant data. BadSubFrameBounds {}, - // Errors specific to the IDAT/fDAT chunks. + // Errors specific to the IDAT/fdAT chunks. /// The compression of the data stream was faulty. CorruptFlateStream { err: fdeflate::DecompressionError, @@ -241,6 +259,26 @@ BadTextEncoding(TextDecodingError), /// fdAT shorter than 4 bytes FdatShorterThanFourBytes, + /// "11.2.4 IDAT Image data" section of the PNG spec says: There may be multiple IDAT chunks; + /// if so, they shall appear consecutively with no other intervening chunks. + /// `UnexpectedRestartOfDataChunkSequence{kind: IDAT}` indicates that there were "intervening + /// chunks". + /// + /// The APNG spec doesn't directly describe an error similar to `CantInterleaveIdatChunks`, + /// but we require that a new sequence of consecutive `fdAT` chunks cannot appear unless we've + /// seen an `fcTL` chunk. + UnexpectedRestartOfDataChunkSequence { + kind: ChunkType, + }, + /// Failure to parse a chunk, because the chunk didn't contain enough bytes. + ChunkTooShort { + kind: ChunkType, + }, + UnrecognizedCriticalChunk { + /// The type of the unrecognized critical chunk. + type_str: ChunkType, + }, + BadGammaValue, } impl error::Error for DecodingError { @@ -278,11 +316,11 @@ "CRC error: expected 0x{:x} have 0x{:x} while decoding {:?} chunk.", crc_val, crc_sum, chunk ), - MissingIhdr => write!(fmt, "IHDR chunk missing"), MissingFctl => write!(fmt, "fcTL chunk missing before fdAT chunk."), - MissingImageData => write!(fmt, "IDAT or fDAT chunk is missing."), + MissingImageData => write!(fmt, "IDAT or fdAT chunk is missing."), ChunkBeforeIhdr { kind } => write!(fmt, "{:?} chunk appeared before IHDR chunk", kind), AfterIdat { kind } => write!(fmt, "Chunk {:?} is invalid after IDAT chunk.", kind), + BeforePlte { kind } => write!(fmt, "Chunk {:?} is invalid before PLTE chunk.", kind), AfterPlte { kind } => write!(fmt, "Chunk {:?} is invalid after PLTE chunk.", kind), OutsidePlteIdat { kind } => write!( fmt, @@ -300,6 +338,16 @@ "Not enough palette entries, expect {} got {}.", expected, len ), + InvalidSbitChunkSize {color_type, expected, len} => write!( + fmt, + "The size of the sBIT chunk should be {} byte(s), but {} byte(s) were provided for the {:?} color type.", + expected, len, color_type + ), + InvalidSbit {sample_depth, sbit} => write!( + fmt, + "Invalid sBIT value {}. It must be greater than zero and less than the sample depth {:?}.", + sbit, sample_depth + ), PaletteRequired => write!(fmt, "Missing palette of indexed image."), InvalidDimensions => write!(fmt, "Invalid image dimensions"), InvalidColorBitDepth { @@ -315,7 +363,7 @@ "Transparency chunk found for color type {:?}.", color_type ), - InvalidBitDepth(nr) => write!(fmt, "Invalid dispose operation {}.", nr), + InvalidBitDepth(nr) => write!(fmt, "Invalid bit depth {}.", nr), InvalidColorType(nr) => write!(fmt, "Invalid color type {}.", nr), InvalidDisposeOp(nr) => write!(fmt, "Invalid dispose op {}.", nr), InvalidBlendOp(nr) => write!(fmt, "Invalid blend op {}.", nr), @@ -326,9 +374,10 @@ UnknownInterlaceMethod(nr) => write!(fmt, "Unknown interlace method {}.", nr), BadSubFrameBounds {} => write!(fmt, "Sub frame is out-of-bounds."), InvalidSignature => write!(fmt, "Invalid PNG signature."), - UnexpectedEof => write!(fmt, "Unexpected end of data before image end."), - UnexpectedEndOfChunk => write!(fmt, "Unexpected end of data within a chunk."), - NoMoreImageData => write!(fmt, "IDAT or fDAT chunk is has not enough data for image."), + NoMoreImageData => write!( + fmt, + "IDAT or fDAT chunk does not have enough data for image." + ), CorruptFlateStream { err } => { write!(fmt, "Corrupt deflate stream. ")?; write!(fmt, "{:?}", err) @@ -363,6 +412,16 @@ } } FdatShorterThanFourBytes => write!(fmt, "fdAT chunk shorter than 4 bytes"), + UnexpectedRestartOfDataChunkSequence { kind } => { + write!(fmt, "Unexpected restart of {:?} chunk sequence", kind) + } + ChunkTooShort { kind } => { + write!(fmt, "Chunk is too short: {:?}", kind) + } + UnrecognizedCriticalChunk { type_str } => { + write!(fmt, "Unrecognized critical chunk: {:?}", type_str) + } + BadGammaValue => write!(fmt, "Bad gamma value."), } } } @@ -408,6 +467,7 @@ ignore_adler32: bool, ignore_crc: bool, ignore_text_chunk: bool, + ignore_iccp_chunk: bool, skip_ancillary_crc_failures: bool, } @@ -417,6 +477,7 @@ ignore_adler32: true, ignore_crc: false, ignore_text_chunk: false, + ignore_iccp_chunk: false, skip_ancillary_crc_failures: true, } } @@ -451,6 +512,13 @@ self.ignore_text_chunk = ignore_text_chunk; } + /// Ignore ICCP chunks while decoding. + /// + /// Defaults to `false`. + pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) { + self.ignore_iccp_chunk = ignore_iccp_chunk; + } + /// Ignore ancillary chunks if CRC fails /// /// Defaults to `true` @@ -476,6 +544,15 @@ /// Whether we have already seen a start of an IDAT chunk. (Used to validate chunk ordering - /// some chunk types can only appear before or after an IDAT chunk.) have_idat: bool, + /// Whether we are ready for a start of an `IDAT` chunk sequence. Initially `true` and set to + /// `false` when the first sequence of consecutive `IDAT` chunks ends. + ready_for_idat_chunks: bool, + /// Whether we are ready for a start of an `fdAT` chunk sequence. Initially `false`. Set to + /// `true` after encountering an `fcTL` chunk. Set to `false` when a sequence of consecutive + /// `fdAT` chunks ends. + ready_for_fdat_chunks: bool, + /// Whether we have already seen an iCCP chunk. Used to prevent parsing of duplicate iCCP chunks. + have_iccp: bool, decode_options: DecodeOptions, pub(crate) limits: Limits, } @@ -509,11 +586,19 @@ StreamingDecoder { state: Some(State::new_u32(U32ValueKind::Signature1stU32)), - current_chunk: ChunkState::default(), + current_chunk: ChunkState { + type_: ChunkType([0; 4]), + crc: Crc32::new(), + remaining: 0, + raw_bytes: Vec::with_capacity(CHUNK_BUFFER_SIZE), + }, inflater, info: None, current_seq_no: None, have_idat: false, + have_iccp: false, + ready_for_idat_chunks: true, + ready_for_fdat_chunks: false, decode_options, limits: Limits { bytes: usize::MAX }, } @@ -540,6 +625,10 @@ self.decode_options.set_ignore_text_chunk(ignore_text_chunk); } + pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) { + self.decode_options.set_ignore_iccp_chunk(ignore_iccp_chunk); + } + /// Return whether the decoder is set to ignore the Adler-32 checksum. pub fn ignore_adler32(&self) -> bool { self.inflater.ignore_adler32() @@ -580,17 +669,28 @@ pub fn update( &mut self, mut buf: &[u8], - image_data: &mut Vec, + mut image_data: Option<&mut UnfilterBuf<'_>>, ) -> Result<(usize, Decoded), DecodingError> { + if self.state.is_none() { + return Err(DecodingError::Parameter( + ParameterErrorKind::PolledAfterFatalError.into(), + )); + } + let len = buf.len(); - while !buf.is_empty() && self.state.is_some() { + while !buf.is_empty() { + let image_data = image_data.as_deref_mut(); + match self.next_state(buf, image_data) { Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..], Ok((bytes, result)) => { buf = &buf[bytes..]; return Ok((len - buf.len(), result)); } - Err(err) => return Err(err), + Err(err) => { + debug_assert!(self.state.is_none()); + return Err(err); + } } } Ok((len - buf.len(), Decoded::Nothing)) @@ -599,7 +699,7 @@ fn next_state( &mut self, buf: &[u8], - image_data: &mut Vec, + image_data: Option<&mut UnfilterBuf<'_>>, ) -> Result<(usize, Decoded), DecodingError> { use self::State::*; @@ -646,20 +746,6 @@ } } } - ParseChunkData(type_str) => { - debug_assert!(type_str != IDAT && type_str != chunk::fdAT); - if self.current_chunk.remaining == 0 { - // Got complete chunk. - Ok((0, self.parse_chunk(type_str)?)) - } else { - // Make sure we have room to read more of the chunk. - // We need it fully before parsing. - self.reserve_current_chunk()?; - - self.state = Some(ReadChunkData(type_str)); - Ok((0, Decoded::PartialChunk(type_str))) - } - } ReadChunkData(type_str) => { debug_assert!(type_str != IDAT && type_str != chunk::fdAT); if self.current_chunk.remaining == 0 { @@ -673,35 +759,54 @@ type_: _, } = &mut self.current_chunk; + if raw_bytes.len() == raw_bytes.capacity() { + if self.limits.bytes == 0 { + return Err(DecodingError::LimitsExceeded); + } + + // Double the size of the Vec, but not beyond the allocation limit. + debug_assert!(raw_bytes.capacity() > 0); + let reserve_size = raw_bytes.capacity().min(self.limits.bytes); + + self.limits.reserve_bytes(reserve_size)?; + raw_bytes.reserve_exact(reserve_size); + } + let buf_avail = raw_bytes.capacity() - raw_bytes.len(); let bytes_avail = min(buf.len(), buf_avail); let n = min(*remaining, bytes_avail as u32); - if buf_avail == 0 { - self.state = Some(ParseChunkData(type_str)); - Ok((0, Decoded::Nothing)) - } else { - let buf = &buf[..n as usize]; - if !self.decode_options.ignore_crc { - crc.update(buf); - } - raw_bytes.extend_from_slice(buf); - *remaining -= n; - if *remaining == 0 { - self.state = Some(ParseChunkData(type_str)); - } else { - self.state = Some(ReadChunkData(type_str)); - } - Ok((n as usize, Decoded::Nothing)) + let buf = &buf[..n as usize]; + if !self.decode_options.ignore_crc { + crc.update(buf); } + raw_bytes.extend_from_slice(buf); + + *remaining -= n; + if *remaining == 0 { + debug_assert!(type_str != IDAT && type_str != chunk::fdAT); + self.state = Some(State::new_u32(U32ValueKind::Crc(type_str))); + } else { + self.state = Some(ReadChunkData(type_str)); + } + Ok((n as usize, Decoded::Nothing)) } } ImageData(type_str) => { debug_assert!(type_str == IDAT || type_str == chunk::fdAT); let len = std::cmp::min(buf.len(), self.current_chunk.remaining as usize); let buf = &buf[..len]; - let consumed = self.inflater.decompress(buf, image_data)?; - self.current_chunk.crc.update(&buf[..consumed]); + + let consumed = if let Some(image_data) = image_data { + self.inflater.decompress(buf, image_data)? + } else { + len + }; + + if !self.decode_options.ignore_crc { + self.current_chunk.crc.update(&buf[..consumed]); + } + self.current_chunk.remaining -= consumed as u32; if self.current_chunk.remaining == 0 { self.state = Some(State::new_u32(U32ValueKind::Crc(type_str))); @@ -717,7 +822,7 @@ &mut self, kind: U32ValueKind, u32_be_bytes: &[u8], - image_data: &mut Vec, + image_data: Option<&mut UnfilterBuf<'_>>, ) -> Result { debug_assert_eq!(u32_be_bytes.len(), 4); let bytes = u32_be_bytes.try_into().unwrap(); @@ -759,8 +864,12 @@ && (self.current_chunk.type_ == IDAT || self.current_chunk.type_ == chunk::fdAT) { self.current_chunk.type_ = type_str; - self.inflater.finish_compressed_chunks(image_data)?; - self.inflater.reset(); + if let Some(image_data) = image_data { + self.inflater.finish_compressed_chunks(image_data)?; + } + + self.ready_for_idat_chunks = false; + self.ready_for_fdat_chunks = false; self.state = Some(State::U32 { kind, bytes, @@ -768,15 +877,16 @@ }); return Ok(Decoded::ImageDataFlushed); } - self.current_chunk.type_ = type_str; - if !self.decode_options.ignore_crc { - self.current_chunk.crc.reset(); - self.current_chunk.crc.update(&type_str.0); - } - self.current_chunk.remaining = length; - self.current_chunk.raw_bytes.clear(); self.state = match type_str { chunk::fdAT => { + if !self.ready_for_fdat_chunks { + return Err(DecodingError::Format( + FormatErrorInner::UnexpectedRestartOfDataChunkSequence { + kind: chunk::fdAT, + } + .into(), + )); + } if length < 4 { return Err(DecodingError::Format( FormatErrorInner::FdatShorterThanFourBytes.into(), @@ -785,11 +895,26 @@ Some(State::new_u32(U32ValueKind::ApngSequenceNumber)) } IDAT => { + if !self.ready_for_idat_chunks { + return Err(DecodingError::Format( + FormatErrorInner::UnexpectedRestartOfDataChunkSequence { + kind: IDAT, + } + .into(), + )); + } self.have_idat = true; Some(State::ImageData(type_str)) } _ => Some(State::ReadChunkData(type_str)), }; + self.current_chunk.type_ = type_str; + if !self.decode_options.ignore_crc { + self.current_chunk.crc.reset(); + self.current_chunk.crc.update(&type_str.0); + } + self.current_chunk.remaining = length; + self.current_chunk.raw_bytes.clear(); Ok(Decoded::ChunkBegin(length, type_str)) } U32ValueKind::Crc(type_str) => { @@ -803,18 +928,21 @@ }; if val == sum || CHECKSUM_DISABLED { - self.state = Some(State::new_u32(U32ValueKind::Length)); - if type_str == IEND { - Ok(Decoded::ImageEnd) - } else { - Ok(Decoded::ChunkComplete(val, type_str)) + // A fatal error in chunk parsing leaves the decoder in state 'None' to enforce + // that parsing can't continue after an error. + debug_assert!(self.state.is_none()); + let decoded = self.parse_chunk(type_str)?; + + if type_str != IEND { + self.state = Some(State::new_u32(U32ValueKind::Length)); } + Ok(decoded) } else if self.decode_options.skip_ancillary_crc_failures && !chunk::is_critical(type_str) { // Ignore ancillary chunk with invalid CRC self.state = Some(State::new_u32(U32ValueKind::Length)); - Ok(Decoded::Nothing) + Ok(Decoded::BadAncillaryChunk(type_str)) } else { Err(DecodingError::Format( FormatErrorInner::CrcMismatch { @@ -855,32 +983,24 @@ } self.state = Some(State::ImageData(chunk::fdAT)); - Ok(Decoded::PartialChunk(chunk::fdAT)) + Ok(Decoded::Nothing) } } } - fn reserve_current_chunk(&mut self) -> Result<(), DecodingError> { - let max = self.limits.bytes; - let buffer = &mut self.current_chunk.raw_bytes; - - // Double if necessary, but no more than until the limit is reached. - let reserve_size = max.saturating_sub(buffer.capacity()).min(buffer.len()); - self.limits.reserve_bytes(reserve_size)?; - buffer.reserve_exact(reserve_size); - - if buffer.capacity() == buffer.len() { - Err(DecodingError::LimitsExceeded) - } else { - Ok(()) - } - } - fn parse_chunk(&mut self, type_str: ChunkType) -> Result { - self.state = Some(State::new_u32(U32ValueKind::Crc(type_str))); - let parse_result = match type_str { + let mut parse_result = match type_str { + // Critical non-data chunks. IHDR => self.parse_ihdr(), chunk::PLTE => self.parse_plte(), + chunk::IEND => Ok(()), // TODO: Check chunk size. + + // Data chunks handled separately. + chunk::IDAT => Ok(()), + chunk::fdAT => Ok(()), + + // Recognized bounded-size ancillary chunks. + chunk::sBIT => self.parse_sbit(), chunk::tRNS => self.parse_trns(), chunk::pHYs => self.parse_phys(), chunk::gAMA => self.parse_gama(), @@ -888,20 +1008,64 @@ chunk::fcTL => self.parse_fctl(), chunk::cHRM => self.parse_chrm(), chunk::sRGB => self.parse_srgb(), - chunk::iCCP => self.parse_iccp(), + chunk::cICP => self.parse_cicp(), + chunk::mDCV => self.parse_mdcv(), + chunk::cLLI => self.parse_clli(), + chunk::bKGD => self.parse_bkgd(), + + // Ancillary chunks with unbounded size. + chunk::eXIf => self.parse_exif(), // TODO: allow skipping. + chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(), chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(), chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(), chunk::iTXt if !self.decode_options.ignore_text_chunk => self.parse_itxt(), - _ => Ok(Decoded::PartialChunk(type_str)), + + // Unrecognized chunks. + _ => { + if is_critical(type_str) { + return Err(DecodingError::Format( + FormatErrorInner::UnrecognizedCriticalChunk { type_str }.into(), + )); + } else { + return Ok(Decoded::SkippedAncillaryChunk(type_str)); + } + } }; - if parse_result.is_err() { - self.state = None; + parse_result = parse_result.map_err(|e| { + match e { + // `parse_chunk` is invoked after gathering **all** bytes of a chunk, so + // `UnexpectedEof` from something like `read_be` is permanent and indicates an + // invalid PNG that should be represented as a `FormatError`, rather than as a + // (potentially recoverable) `IoError` / `UnexpectedEof`. + DecodingError::IoError(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { + let fmt_err: FormatError = + FormatErrorInner::ChunkTooShort { kind: type_str }.into(); + fmt_err.into() + } + e => e, + } + }); + + match parse_result { + Ok(()) => Ok(Decoded::ChunkComplete(type_str)), + Err(DecodingError::Format(_)) + if type_str != chunk::fcTL && !chunk::is_critical(type_str) => + { + // Ignore benign errors in most auxiliary chunks. `LimitsExceeded`, `Parameter` and + // other error kinds are *not* treated as benign. We don't ignore errors in `fcTL` + // chunks because the fallback to the static/non-animated image has to be + // implemented *on top* of the `StreamingDecoder` API. + // + // TODO: Consider supporting a strict mode where even benign errors are reported up. + // See https://github.com/image-rs/image-png/pull/569#issuecomment-2642062285 + Ok(Decoded::BadAncillaryChunk(type_str)) + } + Err(e) => Err(e), } - parse_result } - fn parse_fctl(&mut self) -> Result { + fn parse_fctl(&mut self) -> Result<(), DecodingError> { let mut buf = &self.current_chunk.raw_bytes[..]; let next_seq_no = buf.read_be()?; @@ -930,6 +1094,7 @@ 0 }); self.inflater.reset(); + self.ready_for_fdat_chunks = true; let fc = FrameControl { sequence_number: next_seq_no, width: buf.read_be()?, @@ -962,11 +1127,14 @@ }, }; self.info.as_ref().unwrap().validate(&fc)?; + if !self.have_idat { + self.info.as_ref().unwrap().validate_default_image(&fc)?; + } self.info.as_mut().unwrap().frame_control = Some(fc); - Ok(Decoded::FrameControl(fc)) + Ok(()) } - fn parse_actl(&mut self) -> Result { + fn parse_actl(&mut self) -> Result<(), DecodingError> { if self.have_idat { Err(DecodingError::Format( FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(), @@ -977,12 +1145,17 @@ num_frames: buf.read_be()?, num_plays: buf.read_be()?, }; + // The spec says that "0 is not a valid value" for `num_frames`. + // So let's ignore such malformed `acTL` chunks. + if actl.num_frames == 0 { + return Ok(()); + } self.info.as_mut().unwrap().animation_control = Some(actl); - Ok(Decoded::AnimationControl(actl)) + Ok(()) } } - fn parse_plte(&mut self) -> Result { + fn parse_plte(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if info.palette.is_some() { // Only one palette is allowed @@ -993,11 +1166,78 @@ self.limits .reserve_bytes(self.current_chunk.raw_bytes.len())?; info.palette = Some(Cow::Owned(self.current_chunk.raw_bytes.clone())); - Ok(Decoded::Nothing) + Ok(()) } } - fn parse_trns(&mut self) -> Result { + fn parse_sbit(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + if info.palette.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(), + )); + } + + if self.have_idat { + return Err(DecodingError::Format( + FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(), + )); + } + + if info.sbit.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(), + )); + } + + let (color_type, bit_depth) = { (info.color_type, info.bit_depth) }; + // The sample depth for color type 3 is fixed at eight bits. + let sample_depth = if color_type == ColorType::Indexed { + BitDepth::Eight + } else { + bit_depth + }; + self.limits + .reserve_bytes(self.current_chunk.raw_bytes.len())?; + let vec = self.current_chunk.raw_bytes.clone(); + let len = vec.len(); + + // expected lenth of the chunk + let expected = match color_type { + ColorType::Grayscale => 1, + ColorType::Rgb | ColorType::Indexed => 3, + ColorType::GrayscaleAlpha => 2, + ColorType::Rgba => 4, + }; + + // Check if the sbit chunk size is valid. + if expected != len { + return Err(DecodingError::Format( + FormatErrorInner::InvalidSbitChunkSize { + color_type, + expected, + len, + } + .into(), + )); + } + + for sbit in &vec { + if *sbit < 1 || *sbit > sample_depth as u8 { + return Err(DecodingError::Format( + FormatErrorInner::InvalidSbit { + sample_depth, + sbit: *sbit, + } + .into(), + )); + } + } + info.sbit = Some(Cow::Owned(vec)); + Ok(()) + } + + fn parse_trns(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if info.trns.is_some() { return Err(DecodingError::Format( @@ -1021,7 +1261,7 @@ vec.truncate(1); } info.trns = Some(Cow::Owned(vec)); - Ok(Decoded::Nothing) + Ok(()) } ColorType::Rgb => { if len < 6 { @@ -1036,14 +1276,14 @@ vec.truncate(3); } info.trns = Some(Cow::Owned(vec)); - Ok(Decoded::Nothing) + Ok(()) } ColorType::Indexed => { // The transparency chunk must be after the palette chunk and // before the data chunk. if info.palette.is_none() { return Err(DecodingError::Format( - FormatErrorInner::AfterPlte { kind: chunk::tRNS }.into(), + FormatErrorInner::BeforePlte { kind: chunk::tRNS }.into(), )); } else if self.have_idat { return Err(DecodingError::Format( @@ -1052,7 +1292,7 @@ } info.trns = Some(Cow::Owned(vec)); - Ok(Decoded::Nothing) + Ok(()) } c => Err(DecodingError::Format( FormatErrorInner::ColorWithBadTrns(c).into(), @@ -1060,7 +1300,7 @@ } } - fn parse_phys(&mut self) -> Result { + fn parse_phys(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if self.have_idat { Err(DecodingError::Format( @@ -1085,11 +1325,11 @@ }; let pixel_dims = PixelDimensions { xppu, yppu, unit }; info.pixel_dims = Some(pixel_dims); - Ok(Decoded::PixelDimensions(pixel_dims)) + Ok(()) } } - fn parse_chrm(&mut self) -> Result { + fn parse_chrm(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if self.have_idat { Err(DecodingError::Format( @@ -1130,16 +1370,11 @@ }; info.chrm_chunk = Some(source_chromaticities); - // Ignore chromaticities if sRGB profile is used. - if info.srgb.is_none() { - info.source_chromaticities = Some(source_chromaticities); - } - - Ok(Decoded::Nothing) + Ok(()) } } - fn parse_gama(&mut self) -> Result { + fn parse_gama(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if self.have_idat { Err(DecodingError::Format( @@ -1152,23 +1387,23 @@ } else { let mut buf = &self.current_chunk.raw_bytes[..]; let source_gamma: u32 = buf.read_be()?; - let source_gamma = ScaledFloat::from_scaled(source_gamma); - - info.gama_chunk = Some(source_gamma); - // Ignore chromaticities if sRGB profile is used. - if info.srgb.is_none() { - info.source_gamma = Some(source_gamma); + if source_gamma == 0 { + return Err(DecodingError::Format( + FormatErrorInner::BadGammaValue.into(), + )); } - Ok(Decoded::Nothing) + let source_gamma = ScaledFloat::from_scaled(source_gamma); + info.gama_chunk = Some(source_gamma); + Ok(()) } } - fn parse_srgb(&mut self) -> Result { + fn parse_srgb(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); if self.have_idat { Err(DecodingError::Format( - FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(), + FormatErrorInner::AfterIdat { kind: chunk::sRGB }.into(), )) } else if info.srgb.is_some() { Err(DecodingError::Format( @@ -1183,73 +1418,223 @@ // Set srgb and override source gamma and chromaticities. info.srgb = Some(rendering_intent); - info.source_gamma = Some(crate::srgb::substitute_gamma()); - info.source_chromaticities = Some(crate::srgb::substitute_chromaticities()); - Ok(Decoded::Nothing) + Ok(()) } } - fn parse_iccp(&mut self) -> Result { + fn parse_cicp(&mut self) -> Result<(), DecodingError> { let info = self.info.as_mut().unwrap(); + + // The spec requires that the cICP chunk MUST come before the PLTE and IDAT chunks. + if info.coding_independent_code_points.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::cICP }.into(), + )); + } else if info.palette.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::AfterPlte { kind: chunk::cICP }.into(), + )); + } else if self.have_idat { + return Err(DecodingError::Format( + FormatErrorInner::AfterIdat { kind: chunk::cICP }.into(), + )); + } + + let mut buf = &*self.current_chunk.raw_bytes; + let color_primaries: u8 = buf.read_be()?; + let transfer_function: u8 = buf.read_be()?; + let matrix_coefficients: u8 = buf.read_be()?; + let is_video_full_range_image = { + let flag: u8 = buf.read_be()?; + match flag { + 0 => false, + 1 => true, + _ => { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + } + } + }; + + // RGB is currently the only supported color model in PNG, and as + // such Matrix Coefficients shall be set to 0. + if matrix_coefficients != 0 { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + } + + if !buf.is_empty() { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + } + + info.coding_independent_code_points = Some(CodingIndependentCodePoints { + color_primaries, + transfer_function, + matrix_coefficients, + is_video_full_range_image, + }); + + Ok(()) + } + + fn parse_mdcv(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + + // The spec requires that the mDCV chunk MUST come before the PLTE and IDAT chunks. + if info.mastering_display_color_volume.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::mDCV }.into(), + )); + } else if info.palette.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::AfterPlte { kind: chunk::mDCV }.into(), + )); + } else if self.have_idat { + return Err(DecodingError::Format( + FormatErrorInner::AfterIdat { kind: chunk::mDCV }.into(), + )); + } + + let mut buf = &*self.current_chunk.raw_bytes; + let red_x: u16 = buf.read_be()?; + let red_y: u16 = buf.read_be()?; + let green_x: u16 = buf.read_be()?; + let green_y: u16 = buf.read_be()?; + let blue_x: u16 = buf.read_be()?; + let blue_y: u16 = buf.read_be()?; + let white_x: u16 = buf.read_be()?; + let white_y: u16 = buf.read_be()?; + fn scale(chunk: u16) -> ScaledFloat { + // `ScaledFloat::SCALING` is hardcoded to 100_000, which works + // well for the `cHRM` chunk where the spec says that "a value + // of 0.3127 would be stored as the integer 31270". In the + // `mDCV` chunk the spec says that "0.708, 0.292)" is stored as + // "{ 35400, 14600 }", using a scaling factor of 50_000, so we + // multiply by 2 before converting. + ScaledFloat::from_scaled((chunk as u32) * 2) + } + let chromaticities = SourceChromaticities { + white: (scale(white_x), scale(white_y)), + red: (scale(red_x), scale(red_y)), + green: (scale(green_x), scale(green_y)), + blue: (scale(blue_x), scale(blue_y)), + }; + let max_luminance: u32 = buf.read_be()?; + let min_luminance: u32 = buf.read_be()?; + if !buf.is_empty() { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + } + info.mastering_display_color_volume = Some(MasteringDisplayColorVolume { + chromaticities, + max_luminance, + min_luminance, + }); + + Ok(()) + } + + fn parse_clli(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + if info.content_light_level.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::cLLI }.into(), + )); + } + + let mut buf = &*self.current_chunk.raw_bytes; + let max_content_light_level: u32 = buf.read_be()?; + let max_frame_average_light_level: u32 = buf.read_be()?; + if !buf.is_empty() { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + } + info.content_light_level = Some(ContentLightLevelInfo { + max_content_light_level, + max_frame_average_light_level, + }); + + Ok(()) + } + + fn parse_exif(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + if info.exif_metadata.is_some() { + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::eXIf }.into(), + )); + } + + info.exif_metadata = Some(self.current_chunk.raw_bytes.clone().into()); + Ok(()) + } + + fn parse_iccp(&mut self) -> Result<(), DecodingError> { if self.have_idat { Err(DecodingError::Format( FormatErrorInner::AfterIdat { kind: chunk::iCCP }.into(), )) - } else if info.icc_profile.is_some() { - // We have already encountered an iCCP chunk before. - // - // Section "4.2.2.4. iCCP Embedded ICC profile" of the spec says: - // > A file should contain at most one embedded profile, - // > whether explicit like iCCP or implicit like sRGB. - // but - // * This is a "should", not a "must" - // * The spec also says that "All ancillary chunks are optional, in the sense that - // [...] decoders can ignore them." - // * The reference implementation (libpng) ignores the subsequent iCCP chunks - // (treating them as a benign error). - Ok(Decoded::Nothing) + } else if self.have_iccp { + Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::iCCP }.into(), + )) } else { - let mut buf = &self.current_chunk.raw_bytes[..]; + self.have_iccp = true; + let _ = self.parse_iccp_raw(); + Ok(()) + } + } - // read profile name - let _: u8 = buf.read_be()?; - for _ in 1..80 { - let raw: u8 = buf.read_be()?; - if raw == 0 { - break; - } - } + fn parse_iccp_raw(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + let mut buf = &self.current_chunk.raw_bytes[..]; - match buf.read_be()? { - // compression method - 0u8 => (), - n => { - return Err(DecodingError::Format( - FormatErrorInner::UnknownCompressionMethod(n).into(), - )) - } + // read profile name + for len in 0..=80 { + let raw: u8 = buf.read_be()?; + if (raw == 0 && len == 0) || (raw != 0 && len == 80) { + return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize)); } + if raw == 0 { + break; + } + } - match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) { - Ok(profile) => { - self.limits.reserve_bytes(profile.len())?; - info.icc_profile = Some(Cow::Owned(profile)); - } - Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => { - return Err(DecodingError::Format( - FormatErrorInner::CorruptFlateStream { err }.into(), - )) - } - Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => { - return Err(DecodingError::LimitsExceeded); - } + match buf.read_be()? { + // compression method + 0u8 => (), + n => { + return Err(DecodingError::Format( + FormatErrorInner::UnknownCompressionMethod(n).into(), + )) } + } - Ok(Decoded::Nothing) + match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) { + Ok(profile) => { + self.limits.reserve_bytes(profile.len())?; + info.icc_profile = Some(Cow::Owned(profile)); + } + Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => { + return Err(DecodingError::Format( + FormatErrorInner::CorruptFlateStream { err }.into(), + )) + } + Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => { + return Err(DecodingError::LimitsExceeded); + } } + + Ok(()) } - fn parse_ihdr(&mut self) -> Result { + fn parse_ihdr(&mut self) -> Result<(), DecodingError> { if self.info.is_some() { return Err(DecodingError::Format( FormatErrorInner::DuplicateChunk { kind: IHDR }.into(), @@ -1321,16 +1706,6 @@ } }; - if let Some(mut raw_row_len) = color_type.checked_raw_row_length(bit_depth, width) { - if interlaced { - // This overshoots, but overestimating should be fine. - // TODO: Calculate **exact** IDAT size for interlaced images. - raw_row_len = raw_row_len.saturating_mul(2); - } - self.inflater - .set_max_total_output((height as usize).saturating_mul(raw_row_len)); - } - self.info = Some(Info { width, height, @@ -1340,9 +1715,7 @@ ..Default::default() }); - Ok(Decoded::Header( - width, height, bit_depth, color_type, interlaced, - )) + Ok(()) } fn split_keyword(buf: &[u8]) -> Result<(&[u8], &[u8]), DecodingError> { @@ -1358,7 +1731,7 @@ Ok((&buf[..null_byte_index], &buf[null_byte_index + 1..])) } - fn parse_text(&mut self) -> Result { + fn parse_text(&mut self) -> Result<(), DecodingError> { let buf = &self.current_chunk.raw_bytes[..]; self.limits.reserve_bytes(buf.len())?; @@ -1370,10 +1743,10 @@ .uncompressed_latin1_text .push(TEXtChunk::decode(keyword_slice, value_slice).map_err(DecodingError::from)?); - Ok(Decoded::Nothing) + Ok(()) } - fn parse_ztxt(&mut self) -> Result { + fn parse_ztxt(&mut self) -> Result<(), DecodingError> { let buf = &self.current_chunk.raw_bytes[..]; self.limits.reserve_bytes(buf.len())?; @@ -1390,10 +1763,10 @@ .map_err(DecodingError::from)?, ); - Ok(Decoded::Nothing) + Ok(()) } - fn parse_itxt(&mut self) -> Result { + fn parse_itxt(&mut self) -> Result<(), DecodingError> { let buf = &self.current_chunk.raw_bytes[..]; self.limits.reserve_bytes(buf.len())?; @@ -1438,11 +1811,68 @@ .map_err(DecodingError::from)?, ); - Ok(Decoded::Nothing) + Ok(()) + } + + fn parse_bkgd(&mut self) -> Result<(), DecodingError> { + let info = self.info.as_mut().unwrap(); + if info.bkgd.is_some() { + // Only one bKGD chunk is allowed + return Err(DecodingError::Format( + FormatErrorInner::DuplicateChunk { kind: chunk::bKGD }.into(), + )); + } else if self.have_idat { + return Err(DecodingError::Format( + FormatErrorInner::AfterIdat { kind: chunk::bKGD }.into(), + )); + } + + let expected = match info.color_type { + ColorType::Indexed => { + if info.palette.is_none() { + return Err(DecodingError::IoError( + std::io::ErrorKind::InvalidData.into(), + )); + }; + 1 + } + ColorType::Grayscale | ColorType::GrayscaleAlpha => 2, + ColorType::Rgb | ColorType::Rgba => 6, + }; + let vec = self.current_chunk.raw_bytes.clone(); + if vec.len() != expected { + return Err(DecodingError::Format( + FormatErrorInner::ChunkTooShort { kind: chunk::bKGD }.into(), + )); + } + + info.bkgd = Some(Cow::Owned(vec)); + Ok(()) } } impl Info<'_> { + fn validate_default_image(&self, fc: &FrameControl) -> Result<(), DecodingError> { + // https://www.w3.org/TR/png-3/#fcTL-chunk says that: + // + // > The fcTL chunk corresponding to the default image, if it exists, has these + // > restrictions: + // > + // > * The x_offset and y_offset fields must be 0. + // > * The width and height fields must equal + // > the corresponding fields from the IHDR chunk. + if fc.x_offset != 0 + || fc.y_offset != 0 + || fc.width != self.width + || fc.height != self.height + { + return Err(DecodingError::Format( + FormatErrorInner::BadSubFrameBounds {}.into(), + )); + } + Ok(()) + } + fn validate(&self, fc: &FrameControl) -> Result<(), DecodingError> { if fc.width == 0 || fc.height == 0 { return Err(DecodingError::Format( @@ -1472,33 +1902,30 @@ } } -impl Default for ChunkState { - fn default() -> Self { - ChunkState { - type_: ChunkType([0; 4]), - crc: Crc32::new(), - remaining: 0, - raw_bytes: Vec::with_capacity(CHUNCK_BUFFER_SIZE), - } - } -} - #[cfg(test)] mod tests { use super::ScaledFloat; use super::SourceChromaticities; use crate::test_utils::*; - use crate::{Decoder, DecodingError}; + use crate::{Decoder, DecodingError, Reader, SrgbRenderingIntent, Unit}; + use approx::assert_relative_eq; use byteorder::WriteBytesExt; + use std::borrow::Cow; + use std::cell::RefCell; + use std::fs::File; - use std::io::Write; + use std::io::BufRead; + use std::io::Cursor; + use std::io::Seek; + use std::io::{BufReader, ErrorKind, Read, Write}; + use std::rc::Rc; #[test] fn image_gamma() -> Result<(), ()> { fn trial(path: &str, expected: Option) { - let decoder = crate::Decoder::new(File::open(path).unwrap()); + let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap())); let reader = decoder.read_info().unwrap(); - let actual: Option = reader.info().source_gamma; + let actual: Option = reader.info().gamma(); assert!(actual == expected); } trial("tests/pngsuite/f00n0g08.png", None); @@ -1537,9 +1964,9 @@ #[test] fn image_source_chromaticities() -> Result<(), ()> { fn trial(path: &str, expected: Option) { - let decoder = crate::Decoder::new(File::open(path).unwrap()); + let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap())); let reader = decoder.read_info().unwrap(); - let actual: Option = reader.info().source_chromaticities; + let actual: Option = reader.info().chromaticities(); assert!(actual == expected); } trial( @@ -1721,6 +2148,28 @@ Ok(()) } + #[test] + fn image_source_sbit() { + fn trial(path: &str, expected: Option>) { + let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap())); + let reader = decoder.read_info().unwrap(); + let actual: Option> = reader.info().sbit.clone(); + assert!(actual == expected); + } + + trial("tests/sbit/g.png", Some(Cow::Owned(vec![5u8]))); + trial("tests/sbit/ga.png", Some(Cow::Owned(vec![5u8, 3u8]))); + trial( + "tests/sbit/indexed.png", + Some(Cow::Owned(vec![5u8, 6u8, 5u8])), + ); + trial("tests/sbit/rgb.png", Some(Cow::Owned(vec![5u8, 6u8, 5u8]))); + trial( + "tests/sbit/rgba.png", + Some(Cow::Owned(vec![5u8, 6u8, 5u8, 8u8])), + ); + } + /// Test handling of a PNG file that contains *two* iCCP chunks. /// This is a regression test for https://github.com/image-rs/image/issues/1825. #[test] @@ -1729,7 +2178,9 @@ // https://github.com/image-rs/image/issues/1825#issuecomment-1321798639, // but the 2nd iCCP chunk has been altered manually (see the 2nd comment below for more // details). - let decoder = crate::Decoder::new(File::open("tests/bugfixes/issue#1825.png").unwrap()); + let decoder = crate::Decoder::new(BufReader::new( + File::open("tests/bugfixes/issue#1825.png").unwrap(), + )); let reader = decoder.read_info().unwrap(); let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned(); @@ -1740,6 +2191,135 @@ assert_eq!(4070462061, crc32fast::hash(&icc_profile)); } + #[test] + fn test_iccp_roundtrip() { + let dummy_icc = b"I'm a profile"; + + let mut info = crate::Info::with_size(1, 1); + info.icc_profile = Some(dummy_icc.into()); + let mut encoded_image = Vec::new(); + let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap(); + let mut enc = enc.write_header().unwrap(); + enc.write_image_data(&[0]).unwrap(); + enc.finish().unwrap(); + + let dec = crate::Decoder::new(Cursor::new(&encoded_image)); + let dec = dec.read_info().unwrap(); + assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap()); + } + + #[test] + fn test_phys_roundtrip() { + let mut info = crate::Info::with_size(1, 1); + info.pixel_dims = Some(crate::PixelDimensions { + xppu: 12, + yppu: 34, + unit: Unit::Meter, + }); + let mut encoded_image = Vec::new(); + let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap(); + let mut enc = enc.write_header().unwrap(); + enc.write_image_data(&[0]).unwrap(); + enc.finish().unwrap(); + + let dec = crate::Decoder::new(Cursor::new(&encoded_image)); + let dec = dec.read_info().unwrap(); + let phys = dec.info().pixel_dims.as_ref().unwrap(); + assert_eq!(phys.xppu, 12); + assert_eq!(phys.yppu, 34); + assert_eq!(phys.unit, Unit::Meter); + } + + #[test] + fn test_srgb_roundtrip() { + let mut info = crate::Info::with_size(1, 1); + info.srgb = Some(SrgbRenderingIntent::Saturation); + let mut encoded_image = Vec::new(); + let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap(); + let mut enc = enc.write_header().unwrap(); + enc.write_image_data(&[0]).unwrap(); + enc.finish().unwrap(); + + let dec = crate::Decoder::new(Cursor::new(&encoded_image)); + let dec = dec.read_info().unwrap(); + assert_eq!(dec.info().srgb.unwrap(), SrgbRenderingIntent::Saturation); + } + + #[test] + fn test_png_with_broken_iccp() { + let decoder = crate::Decoder::new(BufReader::new( + File::open("tests/iccp/broken_iccp.png").unwrap(), + )); + assert!(decoder.read_info().is_ok()); + let mut decoder = crate::Decoder::new(BufReader::new( + File::open("tests/iccp/broken_iccp.png").unwrap(), + )); + decoder.set_ignore_iccp_chunk(true); + assert!(decoder.read_info().is_ok()); + } + + /// Test handling of `cICP`, `mDCV`, and `cLLI` chunks. + #[test] + fn test_cicp_mdcv_and_clli_chunks() { + let mut decoder = crate::Decoder::new(BufReader::new( + File::open("tests/bugfixes/cicp_pq.png").unwrap(), + )); + decoder.ignore_checksums(true); + let reader = decoder.read_info().unwrap(); + let info = reader.info(); + + let cicp = info.coding_independent_code_points.unwrap(); + assert_eq!(cicp.color_primaries, 9); + assert_eq!(cicp.transfer_function, 16); + assert_eq!(cicp.matrix_coefficients, 0); + assert!(cicp.is_video_full_range_image); + + let mdcv = info.mastering_display_color_volume.unwrap(); + assert_relative_eq!(mdcv.chromaticities.red.0.into_value(), 0.680); + assert_relative_eq!(mdcv.chromaticities.red.1.into_value(), 0.320); + assert_relative_eq!(mdcv.chromaticities.green.0.into_value(), 0.265); + assert_relative_eq!(mdcv.chromaticities.green.1.into_value(), 0.690); + assert_relative_eq!(mdcv.chromaticities.blue.0.into_value(), 0.150); + assert_relative_eq!(mdcv.chromaticities.blue.1.into_value(), 0.060); + assert_relative_eq!(mdcv.chromaticities.white.0.into_value(), 0.3127); + assert_relative_eq!(mdcv.chromaticities.white.1.into_value(), 0.3290); + assert_relative_eq!(mdcv.min_luminance as f32 / 10_000.0, 0.01); + assert_relative_eq!(mdcv.max_luminance as f32 / 10_000.0, 5000.0); + + let clli = info.content_light_level.unwrap(); + assert_relative_eq!(clli.max_content_light_level as f32 / 10_000.0, 4000.0); + assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0); + } + + /// Test handling of `eXIf` chunk. + #[test] + fn test_exif_chunk() { + let decoder = crate::Decoder::new(BufReader::new( + File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap(), + )); + let reader = decoder.read_info().unwrap(); + let info = reader.info(); + let exif = info.exif_metadata.as_ref().unwrap().as_ref(); + assert_eq!(exif.len(), 90); + } + + /// Tests what happens then [`Reader.finish`] is called twice. + #[test] + fn test_finishing_twice() { + let mut png = Vec::new(); + write_noncompressed_png(&mut png, 16, 1024); + let decoder = Decoder::new(Cursor::new(&png)); + let mut reader = decoder.read_info().unwrap(); + + // First call to `finish` - expecting success. + reader.finish().unwrap(); + + // Second call to `finish` - expecting an error. + let err = reader.finish().unwrap_err(); + assert!(matches!(&err, DecodingError::Parameter(_))); + assert_eq!("End of image has been reached", format!("{err}")); + } + /// Writes an acTL chunk. /// See https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) { @@ -1816,16 +2396,26 @@ write_fdat_prefix(&mut png, 2, 8); write_chunk(&mut png, b"fdAT", &[]); - let decoder = Decoder::new(png.as_slice()); + let decoder = Decoder::new(Cursor::new(&png)); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; reader.next_frame(&mut buf).unwrap(); // 0-length fdAT should result in an error. let err = reader.next_frame(&mut buf).unwrap_err(); assert!(matches!(&err, DecodingError::Format(_))); - let msg = format!("{err}"); - assert_eq!("fdAT chunk shorter than 4 bytes", msg); + assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}")); + + // Calling `next_frame` again should return an error. Same error as above would be nice, + // but it is probably unnecessary and infeasible (`DecodingError` can't derive `Clone` + // because `std::io::Error` doesn't implement `Clone`).. But it definitely shouldn't enter + // an infinite loop. + let err2 = reader.next_frame(&mut buf).unwrap_err(); + assert!(matches!(&err2, DecodingError::Parameter(_))); + assert_eq!( + "A fatal decoding error has been encounted earlier", + format!("{err2}") + ); } #[test] @@ -1834,16 +2424,15 @@ write_fdat_prefix(&mut png, 2, 8); write_chunk(&mut png, b"fdAT", &[1, 0, 0]); - let decoder = Decoder::new(png.as_slice()); + let decoder = Decoder::new(Cursor::new(&png)); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; reader.next_frame(&mut buf).unwrap(); // 3-bytes-long fdAT should result in an error. let err = reader.next_frame(&mut buf).unwrap_err(); assert!(matches!(&err, DecodingError::Format(_))); - let msg = format!("{err}"); - assert_eq!("fdAT chunk shorter than 4 bytes", msg); + assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}")); } #[test] @@ -1873,9 +2462,9 @@ }; // Start decoding. - let decoder = Decoder::new(png.as_slice()); + let decoder = Decoder::new(Cursor::new(&png)); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; let Some(animation_control) = reader.info().animation_control else { panic!("No acTL"); }; @@ -1909,7 +2498,7 @@ panic!("No fcTL (2nd frame)"); }; // The sequence number is taken from the `fcTL` chunk that comes before the two `fdAT` - // chunks. Note that sequence numbers inside `fdAT` chunks are not publically exposed + // chunks. Note that sequence numbers inside `fdAT` chunks are not publicly exposed // (but they are still checked when decoding to verify that they are sequential). assert_eq!(frame_control.sequence_number, 1); } @@ -1936,13 +2525,689 @@ write_iend(&mut png); png }; - let decoder = Decoder::new(png.as_slice()); + let decoder = Decoder::new(Cursor::new(&png)); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; // TODO: Should this return an error instead? For now let's just have test assertions for // the current behavior. reader.next_frame(&mut buf).unwrap(); assert_eq!(3093270825, crc32fast::hash(&buf)); } + + #[test] + fn test_only_idat_chunk_in_input_stream() { + let png = { + let mut png = Vec::new(); + write_png_sig(&mut png); + write_chunk(&mut png, b"IDAT", &[]); + png + }; + let decoder = Decoder::new(Cursor::new(&png)); + let Err(err) = decoder.read_info() else { + panic!("Expected an error") + }; + assert!(matches!(&err, DecodingError::Format(_))); + assert_eq!( + "ChunkType { type: IDAT, \ + critical: true, \ + private: false, \ + reserved: false, \ + safecopy: false \ + } chunk appeared before IHDR chunk", + format!("{err}"), + ); + } + + /// `StreamingInput` can be used by tests to simulate a streaming input + /// (e.g. a slow http response, where all bytes are not immediately available). + #[derive(Clone)] + struct StreamingInput { + full_input: Vec, + state: Rc>, + } + + struct StreamingInputState { + current_pos: usize, + available_len: usize, + } + + impl StreamingInput { + fn new(full_input: Vec) -> Self { + Self { + full_input, + state: Rc::new(RefCell::new(StreamingInputState { + current_pos: 0, + available_len: 0, + })), + } + } + + fn with_noncompressed_png(width: u32, idat_size: usize) -> Self { + let mut png = Vec::new(); + write_noncompressed_png(&mut png, width, idat_size); + Self::new(png) + } + + fn expose_next_byte(&self) { + let mut state = self.state.borrow_mut(); + assert!(state.available_len < self.full_input.len()); + state.available_len += 1; + } + + fn stream_input_until_reader_is_available(&self) -> Reader { + loop { + self.state.borrow_mut().current_pos = 0; + match Decoder::new(self.clone()).read_info() { + Ok(reader) => { + break reader; + } + Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => { + self.expose_next_byte(); + } + _ => panic!("Unexpected error"), + } + } + } + + fn decode_full_input(&self, f: F) -> R + where + F: FnOnce(Reader>) -> R, + { + let decoder = Decoder::new(Cursor::new(&*self.full_input)); + f(decoder.read_info().unwrap()) + } + } + + impl Read for StreamingInput { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let mut state = self.state.borrow_mut(); + let mut available_bytes = &self.full_input[state.current_pos..state.available_len]; + let number_of_read_bytes = available_bytes.read(buf)?; + state.current_pos += number_of_read_bytes; + assert!(state.current_pos <= state.available_len); + Ok(number_of_read_bytes) + } + } + impl BufRead for StreamingInput { + fn fill_buf(&mut self) -> std::io::Result<&[u8]> { + let state = self.state.borrow(); + Ok(&self.full_input[state.current_pos..state.available_len]) + } + + fn consume(&mut self, amt: usize) { + let mut state = self.state.borrow_mut(); + state.current_pos += amt; + assert!(state.current_pos <= state.available_len); + } + } + impl Seek for StreamingInput { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + let mut state = self.state.borrow_mut(); + state.current_pos = match pos { + std::io::SeekFrom::Start(n) => n as usize, + std::io::SeekFrom::End(n) => (self.full_input.len() as i64 + n) as usize, + std::io::SeekFrom::Current(n) => (state.current_pos as i64 + n) as usize, + } as usize; + Ok(state.current_pos as u64) + } + fn stream_position(&mut self) -> std::io::Result { + Ok(self.state.borrow().current_pos as u64) + } + } + + /// Test resuming/retrying `Reader.next_frame` after `UnexpectedEof`. + #[test] + fn test_streaming_input_and_decoding_via_next_frame() { + const WIDTH: u32 = 16; + const IDAT_SIZE: usize = 512; + let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE); + + let (whole_output_info, decoded_from_whole_input) = + streaming_input.decode_full_input(|mut r| { + let mut buf = vec![0; r.output_buffer_size().unwrap()]; + let output_info = r.next_frame(&mut buf).unwrap(); + (output_info, buf) + }); + + let mut png_reader = streaming_input.stream_input_until_reader_is_available(); + let mut decoded_from_streaming_input = vec![0; png_reader.output_buffer_size().unwrap()]; + let streaming_output_info = loop { + match png_reader.next_frame(decoded_from_streaming_input.as_mut_slice()) { + Ok(output_info) => break output_info, + Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => { + streaming_input.expose_next_byte() + } + e => panic!("Unexpected error: {:?}", e), + } + }; + assert_eq!(whole_output_info, streaming_output_info); + assert_eq!( + crc32fast::hash(&decoded_from_whole_input), + crc32fast::hash(&decoded_from_streaming_input) + ); + } + + /// Test resuming/retrying `Reader.next_row` after `UnexpectedEof`. + #[test] + fn test_streaming_input_and_decoding_via_next_row() { + const WIDTH: u32 = 16; + const IDAT_SIZE: usize = 512; + let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE); + + let decoded_from_whole_input = streaming_input.decode_full_input(|mut r| { + let mut buf = vec![0; r.output_buffer_size().unwrap()]; + r.next_frame(&mut buf).unwrap(); + buf + }); + + let mut png_reader = streaming_input.stream_input_until_reader_is_available(); + let mut decoded_from_streaming_input = Vec::new(); + loop { + match png_reader.next_row() { + Ok(None) => break, + Ok(Some(row)) => decoded_from_streaming_input.extend_from_slice(row.data()), + Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => { + streaming_input.expose_next_byte() + } + e => panic!("Unexpected error: {:?}", e), + } + } + assert_eq!( + crc32fast::hash(&decoded_from_whole_input), + crc32fast::hash(&decoded_from_streaming_input) + ); + } + + /// Test resuming/retrying `Decoder.read_header_info` after `UnexpectedEof`. + #[test] + fn test_streaming_input_and_reading_header_info() { + const WIDTH: u32 = 16; + const IDAT_SIZE: usize = 512; + let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE); + + let info_from_whole_input = streaming_input.decode_full_input(|r| r.info().clone()); + + let mut decoder = Decoder::new(streaming_input.clone()); + let info_from_streaming_input = loop { + match decoder.read_header_info() { + Ok(info) => break info.clone(), + Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => { + streaming_input.expose_next_byte() + } + e => panic!("Unexpected error: {:?}", e), + } + }; + + assert_eq!(info_from_whole_input.width, info_from_streaming_input.width); + assert_eq!( + info_from_whole_input.height, + info_from_streaming_input.height + ); + assert_eq!( + info_from_whole_input.bit_depth, + info_from_streaming_input.bit_depth + ); + assert_eq!( + info_from_whole_input.color_type, + info_from_streaming_input.color_type + ); + assert_eq!( + info_from_whole_input.interlaced, + info_from_streaming_input.interlaced + ); + } + + /// Creates a ready-to-test [`Reader`] which decodes a PNG that contains: + /// IHDR, IDAT, IEND. + fn create_reader_of_ihdr_idat() -> Reader>> { + let mut png = Vec::new(); + write_noncompressed_png(&mut png, /* width = */ 16, /* idat_size = */ 1024); + Decoder::new(Cursor::new(png)).read_info().unwrap() + } + + /// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains: + /// IHDR, acTL, fcTL, IDAT, fcTL, fdAT, IEND. (i.e. IDAT is part of the animation) + fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader>> { + let width = 16; + let mut fctl = crate::FrameControl { + width, + height: width, + ..Default::default() + }; + + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, width); + write_actl( + &mut png, + &crate::AnimationControl { + num_frames: 2, + num_plays: 0, + }, + ); + fctl.sequence_number = 0; + write_fctl(&mut png, &fctl); + // Using `fctl.height + 1` means that the `IDAT` will have "left-over" data after + // processing. This helps to verify that `Reader.read_until_image_data` discards the + // left-over data when resetting `UnfilteredRowsBuffer`. + let idat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height + 1); + write_chunk(&mut png, b"IDAT", &idat_data); + + let fdat_width = 10; + fctl.sequence_number = 1; + // Using different width in `IDAT` and `fDAT` frames helps to catch problems that + // may arise when `Reader.read_until_image_data` doesn't properly reset + // `UnfilteredRowsBuffer`. + fctl.width = fdat_width; + write_fctl(&mut png, &fctl); + let fdat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height); + write_fdat(&mut png, 2, &fdat_data); + write_iend(&mut png); + + Decoder::new(Cursor::new(png)).read_info().unwrap() + } + + /// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains: IHDR, acTL, + /// IDAT, fcTL, fdAT, fcTL, fdAT, IEND. (i.e. IDAT is *not* part of the animation) + fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader>> { + let width = 16; + let frame_data = generate_rgba8_with_width_and_height(width, width); + let mut fctl = crate::FrameControl { + width, + height: width, + ..Default::default() + }; + + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, width); + write_actl( + &mut png, + &crate::AnimationControl { + num_frames: 2, + num_plays: 0, + }, + ); + write_chunk(&mut png, b"IDAT", &frame_data); + fctl.sequence_number = 0; + write_fctl(&mut png, &fctl); + write_fdat(&mut png, 1, &frame_data); + fctl.sequence_number = 2; + write_fctl(&mut png, &fctl); + write_fdat(&mut png, 3, &frame_data); + write_iend(&mut png); + + Decoder::new(Cursor::new(png)).read_info().unwrap() + } + + fn get_fctl_sequence_number(reader: &Reader) -> u32 { + reader + .info() + .frame_control + .as_ref() + .unwrap() + .sequence_number + } + + /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called + /// after already decoding a single frame in a non-animated PNG. + #[test] + fn test_next_frame_polling_after_end_non_animated() { + let mut reader = create_reader_of_ihdr_idat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + reader + .next_frame(&mut buf) + .expect("Expecting no error for IDAT frame"); + + let err = reader + .next_frame(&mut buf) + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// Tests that [`Reader.next_frame_info`] will report a `PolledAfterEndOfImage` error when + /// called when decoding a PNG that only contains a single frame. + #[test] + fn test_next_frame_info_polling_after_end_non_animated() { + let mut reader = create_reader_of_ihdr_idat(); + + let err = reader + .next_frame_info() + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called + /// after already decoding a single frame in an animated PNG where IDAT is part of the + /// animation. + #[test] + fn test_next_frame_polling_after_end_idat_part_of_animation() { + let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + + assert_eq!(get_fctl_sequence_number(&reader), 0); + reader + .next_frame(&mut buf) + .expect("Expecting no error for IDAT frame"); + + // `next_frame` doesn't advance to the next `fcTL`. + assert_eq!(get_fctl_sequence_number(&reader), 0); + + reader + .next_frame(&mut buf) + .expect("Expecting no error for fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 1); + + let err = reader + .next_frame(&mut buf) + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called + /// after already decoding a single frame in an animated PNG where IDAT is *not* part of the + /// animation. + #[test] + fn test_next_frame_polling_after_end_idat_not_part_of_animation() { + let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + + assert!(reader.info().frame_control.is_none()); + reader + .next_frame(&mut buf) + .expect("Expecting no error for IDAT frame"); + + // `next_frame` doesn't advance to the next `fcTL`. + assert!(reader.info().frame_control.is_none()); + + reader + .next_frame(&mut buf) + .expect("Expecting no error for 1st fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 0); + + reader + .next_frame(&mut buf) + .expect("Expecting no error for 2nd fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 2); + + let err = reader + .next_frame(&mut buf) + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// Tests that after decoding a whole frame via [`Reader.next_row`] the call to + /// [`Reader.next_frame`] will decode the **next** frame. + #[test] + fn test_row_by_row_then_next_frame() { + let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + + assert_eq!(get_fctl_sequence_number(&reader), 0); + while let Some(_) = reader.next_row().unwrap() {} + assert_eq!(get_fctl_sequence_number(&reader), 0); + + buf.fill(0x0f); + reader + .next_frame(&mut buf) + .expect("Expecting no error from next_frame call"); + + // Verify if we have read the next `fcTL` chunk + repopulated `buf`: + assert_eq!(get_fctl_sequence_number(&reader), 1); + assert!(buf.iter().any(|byte| *byte != 0x0f)); + } + + /// Tests that after decoding a whole frame via [`Reader.next_row`] it is possible + /// to use [`Reader.next_row`] to decode the next frame (by using the `next_frame_info` API to + /// advance to the next frame when `next_row` returns `None`). + #[test] + fn test_row_by_row_of_two_frames() { + let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat(); + + let mut rows_of_frame1 = 0; + assert_eq!(get_fctl_sequence_number(&reader), 0); + while let Some(_) = reader.next_row().unwrap() { + rows_of_frame1 += 1; + } + assert_eq!(rows_of_frame1, 16); + assert_eq!(get_fctl_sequence_number(&reader), 0); + + let mut rows_of_frame2 = 0; + assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1); + assert_eq!(get_fctl_sequence_number(&reader), 1); + while let Some(_) = reader.next_row().unwrap() { + rows_of_frame2 += 1; + } + assert_eq!(rows_of_frame2, 16); + assert_eq!(get_fctl_sequence_number(&reader), 1); + + let err = reader + .next_frame_info() + .expect_err("No more frames - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// This test is similar to `test_next_frame_polling_after_end_idat_part_of_animation`, but it + /// uses `next_frame_info` calls to read to the next `fcTL` earlier - before the next call to + /// `next_frame` (knowing `fcTL` before calling `next_frame` may be helpful to determine the + /// size of the output buffer and/or to prepare the buffer based on the `DisposeOp` of the + /// previous frames). + #[test] + fn test_next_frame_info_after_next_frame() { + let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + + assert_eq!(get_fctl_sequence_number(&reader), 0); + reader + .next_frame(&mut buf) + .expect("Expecting no error for IDAT frame"); + + // `next_frame` doesn't advance to the next `fcTL`. + assert_eq!(get_fctl_sequence_number(&reader), 0); + + // But `next_frame_info` can be used to go to the next `fcTL`. + assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1); + assert_eq!(get_fctl_sequence_number(&reader), 1); + + reader + .next_frame(&mut buf) + .expect("Expecting no error for fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 1); + + let err = reader + .next_frame_info() + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + /// This test is similar to `test_next_frame_polling_after_end_idat_not_part_of_animation`, but + /// it uses `next_frame_info` to skip the `IDAT` frame entirely + to move between frames. + #[test] + fn test_next_frame_info_to_skip_first_frame() { + let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + + // First (IDAT) frame doesn't have frame control info, which means + // that it is not part of the animation. + assert!(reader.info().frame_control.is_none()); + + // `next_frame_info` can be used to skip the IDAT frame (without first having to separately + // discard the image data - e.g. by also calling `next_frame` first). + assert_eq!(reader.next_frame_info().unwrap().sequence_number, 0); + assert_eq!(get_fctl_sequence_number(&reader), 0); + reader + .next_frame(&mut buf) + .expect("Expecting no error for 1st fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 0); + + // Get the `fcTL` for the 2nd frame. + assert_eq!(reader.next_frame_info().unwrap().sequence_number, 2); + reader + .next_frame(&mut buf) + .expect("Expecting no error for 2nd fdAT frame"); + assert_eq!(get_fctl_sequence_number(&reader), 2); + + let err = reader + .next_frame_info() + .expect_err("Main test - expecting error"); + assert!( + matches!(&err, DecodingError::Parameter(_)), + "Unexpected kind of error: {:?}", + &err, + ); + } + + #[test] + fn test_incorrect_trns_chunk_is_ignored() { + let png = { + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, 8); + write_chunk(&mut png, b"tRNS", &[12, 34, 56]); + write_chunk( + &mut png, + b"IDAT", + &generate_rgba8_with_width_and_height(8, 8), + ); + write_iend(&mut png); + png + }; + let decoder = Decoder::new(Cursor::new(&png)); + let mut reader = decoder.read_info().unwrap(); + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; + assert!(reader.info().trns.is_none()); + reader.next_frame(&mut buf).unwrap(); + assert_eq!(3093270825, crc32fast::hash(&buf)); + assert!(reader.info().trns.is_none()); + } + + /// This is a regression test for https://crbug.com/422421347 + #[test] + fn test_actl_num_frames_zero() { + let width = 16; + let frame_data = generate_rgba8_with_width_and_height(width, width); + + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, width); + write_actl( + &mut png, + &crate::AnimationControl { + num_frames: 0, // <= spec violation needed by this test + num_plays: 0, + }, + ); + // Presence of an `fcTL` chunk will prevent incrementing + // `num_frames` when calculating `remaining_frames` in + // `Decoder::read_info`. So the test writes an `fcTL` chunk + // to end up with `remaining_frames == 0` if `parse_actl` allows + // `num_frames == 0`. + write_fctl( + &mut png, + &crate::FrameControl { + width, + height: width, + ..Default::default() + }, + ); + write_chunk(&mut png, b"IDAT", &frame_data); + write_iend(&mut png); + + let mut reader = Decoder::new(Cursor::new(png)).read_info().unwrap(); + + // Using `next_interlaced_row` in the test, because it doesn't check + // `Reader::remaining_frames` (unlike `next_frame`), because it assumes that either + // `read_info` or `next_frame` leave `Reader` in a valid state. + // + // The test passes if these `next_interlaced_row` calls don't hit any `assert!` failures. + while let Some(_row) = reader.next_interlaced_row().unwrap() {} + } + + #[test] + fn test_small_fctl() { + const FCTL_SIZE: u32 = 30; + const IHDR_SIZE: u32 = 50; + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, IHDR_SIZE); + write_actl( + &mut png, + &crate::AnimationControl { + num_frames: 1, + num_plays: 1, + }, + ); + write_fctl( + &mut png, + &crate::FrameControl { + width: FCTL_SIZE, + height: FCTL_SIZE, + x_offset: 10, + y_offset: 10, + sequence_number: 0, + ..Default::default() + }, + ); + write_chunk( + &mut png, + b"IDAT", + &generate_rgba8_with_width_and_height(IHDR_SIZE, IHDR_SIZE), + ); + write_iend(&mut png); + + let reader = Decoder::new(Cursor::new(png)).read_info(); + let err = reader.err().unwrap(); + assert!(matches!(&err, DecodingError::Format(_))); + assert_eq!("Sub frame is out-of-bounds.", format!("{err}")); + } + + #[test] + fn test_invalid_text_chunk() { + // The spec requires a NUL character (separating keyword from text) within the first 80 + // bytes of the chunk. Here there is no NUL character in the first 100 bytes, so this + // chunk is invalid and should trigger an error in `parse_text`. + let invalid_text_chunk = vec![b'A'; 100]; + + const SIZE: u32 = 20; + let mut png = Vec::new(); + write_png_sig(&mut png); + write_rgba8_ihdr_with_width(&mut png, SIZE); + write_chunk(&mut png, b"tEXt", invalid_text_chunk.as_slice()); + write_chunk( + &mut png, + b"IDAT", + &generate_rgba8_with_width_and_height(SIZE, SIZE), + ); + write_iend(&mut png); + + let reader = Decoder::new(Cursor::new(png)).read_info().unwrap(); + let info = reader.info(); + assert_eq!(info.width, SIZE); + assert_eq!(info.uncompressed_latin1_text.len(), 0); + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/transform/palette.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform/palette.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/transform/palette.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform/palette.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,11 @@ -//! Helpers for taking a slice of indeces (indices into `PLTE` and/or `trNS` +//! Helpers for taking a slice of indices (indices into `PLTE` and/or `trNS` //! entries) and transforming this into RGB or RGBA output. //! //! # Memoization //! //! To achieve higher throughput, `create_rgba_palette` combines entries from //! `PLTE` and `trNS` chunks into a single lookup table. This is based on the -//! ideas explored in https://crbug.com/706134. +//! ideas explored in . //! //! Memoization is a trade-off: //! * On one hand, memoization requires spending X ns before starting to call @@ -70,7 +70,7 @@ palette_iter = &palette_iter[3..]; rgba_iter = &mut rgba_iter[1..]; } - if palette_iter.len() > 0 { + if !palette_iter.is_empty() { rgba_iter[0][0..3].copy_from_slice(&palette_iter[0..3]); } } @@ -99,7 +99,7 @@ input = &input[1..]; output = &mut output[3..]; } - if output.len() > 0 { + if !output.is_empty() { let rgba = &rgba_palette[input[0] as usize]; output[0..3].copy_from_slice(&rgba[0..3]); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/transform.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/transform.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/transform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -30,18 +30,18 @@ match color_type { ColorType::Indexed if expand => { if info.palette.is_none() { - return Err(DecodingError::Format( + Err(DecodingError::Format( FormatErrorInner::PaletteRequired.into(), - )); + )) } else if let BitDepth::Sixteen = info.bit_depth { // This should have been caught earlier but let's check again. Can't hurt. - return Err(DecodingError::Format( + Err(DecodingError::Format( FormatErrorInner::InvalidColorBitDepth { color_type: ColorType::Indexed, bit_depth: BitDepth::Sixteen, } .into(), - )); + )) } else { Ok(if trns { palette::create_expansion_into_rgba8(info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/unfiltering_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/unfiltering_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/unfiltering_buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/unfiltering_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,230 @@ +use super::stream::{DecodingError, FormatErrorInner}; +use super::zlib::UnfilterBuf; +use crate::common::BytesPerPixel; +use crate::filter::{unfilter, RowFilter}; +use crate::Info; + +// Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows. +pub(crate) struct UnfilteringBuffer { + /// Vec containing the uncompressed image data currently being processed. + data_stream: Vec, + /// Index in `data_stream` where the previous row starts. + /// This excludes the filter type byte - it points at the first byte of actual pixel data. + /// The pixel data is already-`unfilter`-ed. + /// + /// If `prev_start == current_start` then it means that there is no previous row. + prev_start: usize, + /// Index in `data_stream` where the current row starts. + /// This points at the filter type byte of the current row (i.e. the actual pixel data starts at `current_start + 1`) + /// The pixel data is not-yet-`unfilter`-ed. + /// + /// `current_start` can wrap around the length. + current_start: usize, + /// Logical length of data that must be preserved. + filled: usize, + /// Length of data that can be modified. + available: usize, + /// The number of bytes before we shift the buffer back. + shift_back_limit: usize, +} + +impl UnfilteringBuffer { + pub const GROWTH_BYTES: usize = 8 * 1024; + + /// Asserts in debug builds that all the invariants hold. No-op in release + /// builds. Intended to be called after creating or mutating `self` to + /// ensure that the final state preserves the invariants. + fn debug_assert_invariants(&self) { + debug_assert!(self.prev_start <= self.current_start); + debug_assert!(self.current_start <= self.available); + debug_assert!(self.available <= self.filled); + debug_assert!(self.filled <= self.data_stream.len()); + } + + /// Create a buffer tuned for filtering rows of the image type. + pub fn new(info: &Info<'_>) -> Self { + // We don't need all of `info` here so if that becomes a structural problem then these + // derived constants can be extracted into a parameter struct. For instance they may be + // adjusted according to platform hardware such as cache sizes. + let data_stream_capacity = { + let max_data = info + .checked_raw_row_length() + // In the current state this is really dependent on IDAT sizes and the compression + // settings. We aim to avoid overallocation here, but that occurs in part due to + // the algorithm for draining the buffer, which at the time of writing is at each + // individual IDAT chunk boundary. So this is set for a quadratic image roughly + // fitting into a single 4k chunk at compression.. A very arbitrary choice made + // from (probably overfitting) a benchmark of that image size. With a different + // algorithm we may come to different buffer uses and have to re-evaluate. + .and_then(|v| v.checked_mul(info.height.min(128) as usize)) + // In the worst case this is additional room for use of unmasked SIMD moves. But + // the other idea here is that the allocator generally aligns the buffer. + .and_then(|v| checked_next_multiple_of(v, 256)) + .unwrap_or(usize::MAX); + // We do not want to pre-allocate too much in case of a faulty image (no DOS by + // pretending to be very very large) and also we want to avoid allocating more data + // than we need for the image itself. + max_data.min(128 * 1024) + }; + + let shift_back_limit = { + // Prefer shifting by powers of two and only after having done some number of + // lines that then become free at the end of the buffer. + let rowlen_pot = info + .checked_raw_row_length() + // Ensure some number of rows are actually present before shifting back, i.e. next + // time around we want to be able to decode them without reallocating the buffer. + .and_then(|v| v.checked_mul(4)) + // And also, we should be able to use aligned memcopy on the whole thing. Well at + // least that is the idea but the parameter is just benchmarking. Higher numbers + // did not result in performance gains but lowers also, so this is fickle. Maybe + // our shift back behavior can not be tuned very well. + .and_then(|v| checked_next_multiple_of(v, 64)) + .unwrap_or(isize::MAX as usize); + // But never shift back before we have a number of pages freed. + rowlen_pot.max(128 * 1024) + }; + + let result = Self { + data_stream: Vec::with_capacity(data_stream_capacity), + prev_start: 0, + current_start: 0, + filled: 0, + available: 0, + shift_back_limit, + }; + + result.debug_assert_invariants(); + result + } + + /// Called to indicate that there is no previous row (e.g. when the current + /// row is the first scanline of a given Adam7 pass). + pub fn reset_prev_row(&mut self) { + self.prev_start = self.current_start; + self.debug_assert_invariants(); + } + + pub fn reset_all(&mut self) { + self.data_stream.clear(); + self.prev_start = 0; + self.current_start = 0; + self.filled = 0; + self.available = 0; + } + + /// Returns the previous (already `unfilter`-ed) row. + pub fn prev_row(&self) -> &[u8] { + &self.data_stream[self.prev_start..self.current_start] + } + + /// Returns how many bytes of the current row are present in the buffer. + pub fn curr_row_len(&self) -> usize { + self.available - self.current_start + } + + /// Returns a `&mut Vec` suitable for passing to + /// `ReadDecoder.decode_image_data` or `StreamingDecoder.update`. + /// + /// Invariants of `self` depend on the assumption that the caller will only + /// append new bytes to the returned vector (which is indeed the behavior of + /// `ReadDecoder` and `StreamingDecoder`). TODO: Consider protecting the + /// invariants by returning an append-only view of the vector + /// (`FnMut(&[u8])`??? or maybe `std::io::Write`???). + pub fn as_unfilled_buffer(&mut self) -> UnfilterBuf<'_> { + if self.prev_start >= self.shift_back_limit + // Avoid the shift back if the buffer is still very empty. Consider how we got here: a + // previous decompression filled the buffer, then we unfiltered, we're now refilling + // the buffer again. The condition implies, the previous decompression filled at most + // half the buffer. Likely the same will happen again so the following decompression + // attempt will not yet be limited by the buffer length. + && self.filled >= self.data_stream.len() / 2 + { + // We have to relocate the data to the start of the buffer. Benchmarking suggests that + // the codegen for an unbounded range is better / different than the one for a bounded + // range. We prefer the former if the data overhead is not too high. `16` was + // determined experimentally and might be system (memory) dependent. There's also the + // question if we could be a little smarter and avoid crossing page boundaries when + // that is not required. Alas, microbenchmarking TBD. + if let Some(16..) = self.data_stream.len().checked_sub(self.filled) { + self.data_stream + .copy_within(self.prev_start..self.filled, 0); + } else { + self.data_stream.copy_within(self.prev_start.., 0); + } + + // The data kept its relative position to `filled` which now lands exactly at + // the distance between prev_start and filled. + self.current_start -= self.prev_start; + self.available -= self.prev_start; + self.filled -= self.prev_start; + self.prev_start = 0; + } + + if self.filled + Self::GROWTH_BYTES > self.data_stream.len() { + self.data_stream.resize(self.filled + Self::GROWTH_BYTES, 0); + } + + UnfilterBuf { + buffer: &mut self.data_stream, + filled: &mut self.filled, + available: &mut self.available, + } + } + + /// Runs `unfilter` on the current row, and then shifts rows so that the current row becomes the previous row. + /// + /// Will panic if `self.curr_row_len() < rowlen`. + pub fn unfilter_curr_row( + &mut self, + rowlen: usize, + bpp: BytesPerPixel, + ) -> Result<(), DecodingError> { + debug_assert!(rowlen >= 2); // 1 byte for `FilterType` and at least 1 byte of pixel data. + + let (prev, row) = self.data_stream.split_at_mut(self.current_start); + let prev: &[u8] = &prev[self.prev_start..]; + + debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1)); + + // Get the filter type. + let filter = RowFilter::from_u8(row[0]).ok_or(DecodingError::Format( + FormatErrorInner::UnknownFilterMethod(row[0]).into(), + ))?; + let row = &mut row[1..rowlen]; + + unfilter(filter, bpp, prev, row); + + self.prev_start = self.current_start + 1; + self.current_start += rowlen; + + self.debug_assert_invariants(); + + Ok(()) + } +} + +fn checked_next_multiple_of(val: usize, factor: usize) -> Option { + if factor == 0 { + return None; + } + + let remainder = val % factor; + + if remainder > 0 { + val.checked_add(factor - remainder) + } else { + Some(val) + } +} + +#[test] +fn next_multiple_of_backport_testsuite() { + assert_eq!(checked_next_multiple_of(1, 0), None); + assert_eq!(checked_next_multiple_of(2, 0), None); + assert_eq!(checked_next_multiple_of(1, 2), Some(2)); + assert_eq!(checked_next_multiple_of(2, 2), Some(2)); + assert_eq!(checked_next_multiple_of(2, 5), Some(5)); + assert_eq!(checked_next_multiple_of(1, usize::MAX), Some(usize::MAX)); + assert_eq!(checked_next_multiple_of(usize::MAX, 2), None); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/zlib.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/zlib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/decoder/zlib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/decoder/zlib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,27 +1,48 @@ -use super::{stream::FormatErrorInner, DecodingError, CHUNCK_BUFFER_SIZE}; +use super::{stream::FormatErrorInner, unfiltering_buffer::UnfilteringBuffer, DecodingError}; use fdeflate::Decompressor; +/// An inplace buffer for decompression and filtering of PNG rowlines. +/// +/// The underlying data structure is a vector, with additional markers denoting a region of bytes +/// that are utilized by the decompression but not yet available to arbitrary modifications. The +/// caller can still shift around data between calls to the stream decompressor as long as the data +/// in the marked region is not modified and the indices adjusted accordingly. See +/// [`UnfilterRegion`] that contains these markers. +/// +/// Violating the invariants, i.e. modifying bytes in the marked region, results in absurdly wacky +/// decompression output or panics but not undefined behavior. +pub struct UnfilterBuf<'data> { + /// The data container. Starts with arbitrary data unrelated to the decoder, a slice of decoder + /// private data followed by free space for further decoder output. The regions are delimited + /// by `filled` and `available` which must be updated accordingly. + pub(crate) buffer: &'data mut Vec, + /// Where we record changes to the out position. + pub(crate) filled: &'data mut usize, + /// Where we record changes to the available byte. + pub(crate) available: &'data mut usize, +} + +/// A region into a buffer utilized as a [`UnfilterBuf`]. +/// +/// The span of data denoted by `filled..available` is the region of bytes that must be preserved +/// for use by the decompression algorithm. It may be moved, e.g. by subtracting the same amount +/// from both of these fields. Always ensure that `filled <= available`, the library does not +/// violate this invariant when modifying this struct as an [`UnfilterBuf`]. +#[derive(Default, Clone, Copy)] +pub struct UnfilterRegion { + /// The past-the-end index of byte that are allowed to be modified. + pub available: usize, + /// The past-the-end of bytes that have been written to. + pub filled: usize, +} + /// Ergonomics wrapper around `miniz_oxide::inflate::stream` for zlib compressed data. pub(super) struct ZlibStream { /// Current decoding state. state: Box, /// If there has been a call to decompress already. started: bool, - /// Remaining buffered decoded bytes. - /// The decoder sometimes wants inspect some already finished bytes for further decoding. So we - /// keep a total of 32KB of decoded data available as long as more data may be appended. - out_buffer: Vec, - /// The first index of `out_buffer` where new data can be written. - out_pos: usize, - /// The first index of `out_buffer` that hasn't yet been passed to our client - /// (i.e. not yet appended to the `image_data` parameter of `fn decompress` or `fn - /// finish_compressed_chunks`). - read_pos: usize, - /// Limit on how many bytes can be decompressed in total. This field is mostly used for - /// performance optimizations (e.g. to avoid allocating and zeroing out large buffers when only - /// a small image is being decoded). - max_total_output: usize, /// Ignore and do not calculate the Adler-32 checksum. Defaults to `true`. /// /// This flag overrides `TINFL_FLAG_COMPUTE_ADLER32`. @@ -31,31 +52,28 @@ } impl ZlibStream { + // [PNG spec](https://www.w3.org/TR/2003/REC-PNG-20031110/#10Compression) says that + // "deflate/inflate compression with a sliding window (which is an upper bound on the + // distances appearing in the deflate stream) of at most 32768 bytes". + // + // `fdeflate` requires that we keep this many most recently decompressed bytes in the + // `out_buffer` - this allows referring back to them when handling "length and distance + // codes" in the deflate stream). + const LOOKBACK_SIZE: usize = 32768; + pub(crate) fn new() -> Self { ZlibStream { state: Box::new(Decompressor::new()), started: false, - out_buffer: Vec::new(), - out_pos: 0, - read_pos: 0, - max_total_output: usize::MAX, ignore_adler32: true, } } pub(crate) fn reset(&mut self) { self.started = false; - self.out_buffer.clear(); - self.out_pos = 0; - self.read_pos = 0; - self.max_total_output = usize::MAX; *self.state = Decompressor::new(); } - pub(crate) fn set_max_total_output(&mut self, n: usize) { - self.max_total_output = n; - } - /// Set the `ignore_adler32` flag and return `true` if the flag was /// successfully set. /// @@ -82,7 +100,7 @@ pub(crate) fn decompress( &mut self, data: &[u8], - image_data: &mut Vec, + image_data: &mut UnfilterBuf<'_>, ) -> Result { // There may be more data past the adler32 checksum at the end of the deflate stream. We // match libpng's default behavior and ignore any trailing data. In the future we may want @@ -91,23 +109,29 @@ return Ok(data.len()); } - self.prepare_vec_for_appending(); - if !self.started && self.ignore_adler32 { self.state.ignore_adler32(); } + let (buffer, filled) = image_data.borrow_mut(); + let output_limit = (filled + UnfilteringBuffer::GROWTH_BYTES).min(buffer.len()); let (in_consumed, out_consumed) = self .state - .read(data, self.out_buffer.as_mut_slice(), self.out_pos, false) + .read(data, &mut buffer[..output_limit], filled, false) .map_err(|err| { DecodingError::Format(FormatErrorInner::CorruptFlateStream { err }.into()) })?; self.started = true; - self.out_pos += out_consumed; - self.transfer_finished_data(image_data); - self.compact_out_buffer_if_needed(); + let filled = filled + out_consumed; + image_data.filled(filled); + + if self.state.is_done() { + image_data.commit(filled); + } else { + // See [`Self::LOOKBACK_SIZE`]. + image_data.commit(filled.saturating_sub(Self::LOOKBACK_SIZE)); + } Ok(in_consumed) } @@ -119,112 +143,71 @@ /// more data were passed to it. pub(crate) fn finish_compressed_chunks( &mut self, - image_data: &mut Vec, + image_data: &mut UnfilterBuf<'_>, ) -> Result<(), DecodingError> { if !self.started { return Ok(()); } + if self.state.is_done() { + // We can end up here only after the [`decompress`] call above has detected the state + // to be done, too. In this case the filled and committed amount of data are already + // equal to each other. So neither of them needs to be touched in any way. + return Ok(()); + } + + let (_, mut filled) = image_data.borrow_mut(); while !self.state.is_done() { - self.prepare_vec_for_appending(); - let (_in_consumed, out_consumed) = self - .state - .read(&[], self.out_buffer.as_mut_slice(), self.out_pos, true) - .map_err(|err| { + let (buffer, _) = image_data.borrow_mut(); + let (_in_consumed, out_consumed) = + self.state.read(&[], buffer, filled, true).map_err(|err| { DecodingError::Format(FormatErrorInner::CorruptFlateStream { err }.into()) })?; - self.out_pos += out_consumed; + filled += out_consumed; if !self.state.is_done() { - let transferred = self.transfer_finished_data(image_data); - assert!( - transferred > 0 || out_consumed > 0, - "No more forward progress made in stream decoding." - ); - self.compact_out_buffer_if_needed(); + image_data.flush_allocate(); } } - self.transfer_finished_data(image_data); - self.out_buffer.clear(); + image_data.filled(filled); + image_data.commit(filled); + Ok(()) } +} - /// Resize the vector to allow allocation of more data. - fn prepare_vec_for_appending(&mut self) { - // The `debug_assert` below explains why we can use `>=` instead of `>` in the condition - // that compares `self.out_post >= self.max_total_output` in the next `if` statement. - debug_assert!(!self.state.is_done()); - if self.out_pos >= self.max_total_output { - // This can happen when the `max_total_output` was miscalculated (e.g. - // because the `IHDR` chunk was malformed and didn't match the `IDAT` chunk). In - // this case, let's reset `self.max_total_output` before further calculations. - self.max_total_output = usize::MAX; - } - - let current_len = self.out_buffer.len(); - let desired_len = self - .out_pos - .saturating_add(CHUNCK_BUFFER_SIZE) - .min(self.max_total_output); - if current_len >= desired_len { - return; - } - - let buffered_len = self.decoding_size(self.out_buffer.len()); - debug_assert!(self.out_buffer.len() <= buffered_len); - self.out_buffer.resize(buffered_len, 0u8); - } - - fn decoding_size(&self, len: usize) -> usize { - // Allocate one more chunk size than currently or double the length while ensuring that the - // allocation is valid and that any cursor within it will be valid. - len - // This keeps the buffer size a power-of-two, required by miniz_oxide. - .saturating_add(CHUNCK_BUFFER_SIZE.max(len)) - // Ensure all buffer indices are valid cursor positions. - // Note: both cut off and zero extension give correct results. - .min(u64::max_value() as usize) - // Ensure the allocation request is valid. - // TODO: maximum allocation limits? - .min(isize::max_value() as usize) - // Don't unnecessarily allocate more than `max_total_output`. - .min(self.max_total_output) - } - - fn transfer_finished_data(&mut self, image_data: &mut Vec) -> usize { - let transferred = &self.out_buffer[self.read_pos..self.out_pos]; - image_data.extend_from_slice(transferred); - self.read_pos = self.out_pos; - transferred.len() - } - - fn compact_out_buffer_if_needed(&mut self) { - // [PNG spec](https://www.w3.org/TR/2003/REC-PNG-20031110/#10Compression) says that - // "deflate/inflate compression with a sliding window (which is an upper bound on the - // distances appearing in the deflate stream) of at most 32768 bytes". - // - // `fdeflate` requires that we keep this many most recently decompressed bytes in the - // `out_buffer` - this allows referring back to them when handling "length and distance - // codes" in the deflate stream). - const LOOKBACK_SIZE: usize = 32768; - - // Compact `self.out_buffer` when "needed". Doing this conditionally helps to put an upper - // bound on the amortized cost of copying the data within `self.out_buffer`. - // - // TODO: The factor of 4 is an ad-hoc heuristic. Consider measuring and using a different - // factor. (Early experiments seem to indicate that factor of 4 is faster than a factor of - // 2 and 4 * `LOOKBACK_SIZE` seems like an acceptable memory trade-off. Higher factors - // result in higher memory usage, but the compaction cost is lower - factor of 4 means - // that 1 byte gets copied during compaction for 3 decompressed bytes.) - if self.out_pos > LOOKBACK_SIZE * 4 { - // Only preserve the `lookback_buffer` and "throw away" the earlier prefix. - let lookback_buffer = self.out_pos.saturating_sub(LOOKBACK_SIZE)..self.out_pos; - let preserved_len = lookback_buffer.len(); - self.out_buffer.copy_within(lookback_buffer, 0); - self.read_pos = preserved_len; - self.out_pos = preserved_len; +impl UnfilterRegion { + /// Use this region to decompress new filtered rowline data. + /// + /// Pass the wrapped buffer to + /// [`StreamingDecoder::update`][`super::stream::StreamingDecoder::update`] to fill it with + /// data and update the region indices. + pub fn as_buf<'data>(&'data mut self, buffer: &'data mut Vec) -> UnfilterBuf<'data> { + UnfilterBuf { + buffer, + filled: &mut self.filled, + available: &mut self.available, } } } + +impl UnfilterBuf<'_> { + pub(crate) fn borrow_mut(&mut self) -> (&mut [u8], usize) { + (self.buffer, *self.filled) + } + + pub(crate) fn filled(&mut self, filled: usize) { + *self.filled = filled; + } + + pub(crate) fn commit(&mut self, howmany: usize) { + *self.available = howmany; + } + + pub(crate) fn flush_allocate(&mut self) { + let len = self.buffer.len() + 32 * 1024; + self.buffer.resize(len, 0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/encoder.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,13 +9,14 @@ use crate::chunk::{self, ChunkType}; use crate::common::{ AnimationControl, BitDepth, BlendOp, BytesPerPixel, ColorType, Compression, DisposeOp, - FrameControl, Info, ParameterError, ParameterErrorKind, PixelDimensions, ScaledFloat, + FrameControl, Info, ParameterError, ParameterErrorKind, PixelDimensions, ScaledFloat, Unit, }; -use crate::filter::{filter, AdaptiveFilterType, FilterType}; +use crate::filter::{filter, Filter}; use crate::text_metadata::{ - EncodableTextChunk, ITXtChunk, TEXtChunk, TextEncodingError, ZTXtChunk, + encode_iso_8859_1, EncodableTextChunk, ITXtChunk, TEXtChunk, TextEncodingError, ZTXtChunk, }; use crate::traits::WriteBytesExt; +use crate::DeflateCompression; pub type Result = result::Result; @@ -151,13 +152,13 @@ options: Options, } -/// Decoding options, internal type, forwarded to the Writer. +/// Encoding options, internal type, forwarded to the Writer. #[derive(Default)] struct Options { - filter: FilterType, - adaptive_filter: AdaptiveFilterType, + filter: Filter, sep_def_img: bool, validate_sequence: bool, + compression: DeflateCompression, } impl<'a, W: Write> Encoder<'a, W> { @@ -267,10 +268,12 @@ /// Mark the image data as conforming to the SRGB color space with the specified rendering intent. /// - /// Matching source gamma and chromaticities chunks are added automatically. - /// Any manually specified source gamma or chromaticities will be ignored. - pub fn set_srgb(&mut self, rendering_intent: super::SrgbRenderingIntent) { - self.info.srgb = Some(rendering_intent); + /// Any ICC profiles will be ignored. + /// + /// Source gamma and chromaticities will be written only if they're set to fallback + /// values specified in [11.3.2.5](https://www.w3.org/TR/png-3/#sRGB-gAMA-cHRM). + pub fn set_source_srgb(&mut self, rendering_intent: super::SrgbRenderingIntent) { + self.info.set_source_srgb(rendering_intent); } /// Start encoding by writing the header data. @@ -294,36 +297,28 @@ self.info.bit_depth = depth; } - /// Set compression parameters. - /// - /// Accepts a `Compression` or any type that can transform into a `Compression`. Notably `deflate::Compression` and - /// `deflate::CompressionOptions` which "just work". + /// Set compression parameters, see [Compression] for the available options. pub fn set_compression(&mut self, compression: Compression) { - self.info.compression = compression; + self.set_deflate_compression(DeflateCompression::from_simple(compression)); + self.set_filter(Filter::from_simple(compression)); } - /// Set the used filter type. + /// Provides in-depth customization of DEFLATE compression options. /// - /// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for - /// sample values based on the previous. For a potentially better compression ratio, at the - /// cost of more complex processing, try out [`FilterType::Paeth`]. - /// - /// [`FilterType::Sub`]: enum.FilterType.html#variant.Sub - /// [`FilterType::Paeth`]: enum.FilterType.html#variant.Paeth - pub fn set_filter(&mut self, filter: FilterType) { - self.options.filter = filter; + /// For a simpler selection of compression options see [Self::set_compression]. + pub fn set_deflate_compression(&mut self, compression: DeflateCompression) { + self.options.compression = compression; } - /// Set the adaptive filter type. + /// Set the used filter type. + /// + /// The default filter is [`Filter::Adaptive`] which automatically selects the best filter + /// for each row of the image. /// - /// Adaptive filtering attempts to select the best filter for each line - /// based on heuristics which minimize the file size for compression rather - /// than use a single filter for the entire image. The default method is - /// [`AdaptiveFilterType::NonAdaptive`]. - /// - /// [`AdaptiveFilterType::NonAdaptive`]: enum.AdaptiveFilterType.html - pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) { - self.options.adaptive_filter = adaptive_filter; + /// You should only change this if you are after very fast compression, + /// and either don't care about compression ratio or know exactly what works best for your images. + pub fn set_filter(&mut self, filter: Filter) { + self.options.filter = filter; } /// Set the fraction of time every frame is going to be displayed, in seconds. @@ -333,7 +328,7 @@ /// /// If the denominator is 0, it is to be treated as if it were 100 /// (that is, the numerator then specifies 1/100ths of a second). - /// If the the value of the numerator is 0 the decoder should render the next frame + /// If the value of the numerator is 0 the decoder should render the next frame /// as quickly as possible, though viewers may impose a reasonable lower bound. /// /// The default value is 0 for both the numerator and denominator. @@ -341,9 +336,8 @@ /// This method will return an error if the image is not animated. /// (see [`set_animated`]) /// - /// [`write_header`]: struct.Encoder.html#method.write_header - /// [`set_animated`]: struct.Encoder.html#method.set_animated - /// [`Writer::set_frame_delay`]: struct.Writer#method.set_frame_delay + /// [`write_header`]: Self::write_header + /// [`set_animated`]: Self::set_animated pub fn set_frame_delay(&mut self, numerator: u16, denominator: u16) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.delay_den = denominator; @@ -374,11 +368,8 @@ /// This method will return an error if the image is not animated. /// (see [`set_animated`]) /// - /// [`BlendOP`]: enum.BlendOp.html - /// [`BlendOP::Source`]: enum.BlendOp.html#variant.Source - /// [`write_header`]: struct.Encoder.html#method.write_header - /// [`set_animated`]: struct.Encoder.html#method.set_animated - /// [`Writer::set_blend_op`]: struct.Writer#method.set_blend_op + /// [`write_header`]: Self::write_header + /// [`set_animated`]: Self::set_animated pub fn set_blend_op(&mut self, op: BlendOp) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.blend_op = op; @@ -406,13 +397,8 @@ /// This method will return an error if the image is not animated. /// (see [`set_animated`]) /// - /// [`DisposeOp`]: ../common/enum.BlendOp.html - /// [`DisposeOp::Previous`]: ../common/enum.BlendOp.html#variant.Previous - /// [`DisposeOp::Background`]: ../common/enum.BlendOp.html#variant.Background - /// [`DisposeOp::None`]: ../common/enum.BlendOp.html#variant.None - /// [`write_header`]: struct.Encoder.html#method.write_header - /// [`set_animated`]: struct.Encoder.html#method.set_animated - /// [`Writer::set_dispose_op`]: struct.Writer#method.set_dispose_op + /// [`set_animated`]: Self::set_animated + /// [`write_header`]: Self::write_header pub fn set_dispose_op(&mut self, op: DisposeOp) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.dispose_op = op; @@ -495,7 +481,6 @@ color_type: ColorType, frame_control: Option, animation_control: Option, - compression: Compression, has_palette: bool, } @@ -508,39 +493,25 @@ color_type: info.color_type, frame_control: info.frame_control, animation_control: info.animation_control, - compression: info.compression, has_palette: info.palette.is_some(), } } fn bpp_in_prediction(&self) -> BytesPerPixel { - // Passthrough - self.to_info().bpp_in_prediction() + BytesPerPixel::from_usize(self.bytes_per_pixel()) } - fn raw_row_length(&self) -> usize { - // Passthrough - self.to_info().raw_row_length() + fn bytes_per_pixel(&self) -> usize { + self.color_type.bytes_per_pixel(self.bit_depth) } - fn raw_row_length_from_width(&self, width: u32) -> usize { - // Passthrough - self.to_info().raw_row_length_from_width(width) + fn raw_row_length(&self) -> usize { + self.raw_row_length_from_width(self.width) } - /// Converts this partial info to an owned Info struct, - /// setting missing values to their defaults - fn to_info(&self) -> Info<'static> { - Info { - width: self.width, - height: self.height, - bit_depth: self.bit_depth, - color_type: self.color_type, - frame_control: self.frame_control, - animation_control: self.animation_control, - compression: self.compression, - ..Default::default() - } + fn raw_row_length_from_width(&self, width: u32) -> usize { + self.color_type + .raw_row_length_from_width(self.bit_depth, width) } } @@ -589,16 +560,100 @@ )); } - self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?; // PNG signature - info.encode(&mut self.w)?; + self.encode_header(info)?; Ok(self) } + /// Encode PNG signature, IHDR, and then chunks that were added to the `Info` + fn encode_header(&mut self, info: &Info<'_>) -> Result<()> { + self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?; // PNG signature + + // Encode the IHDR chunk + let mut data = [0; 13]; + data[..4].copy_from_slice(&info.width.to_be_bytes()); + data[4..8].copy_from_slice(&info.height.to_be_bytes()); + data[8] = info.bit_depth as u8; + data[9] = info.color_type as u8; + data[12] = info.interlaced as u8; + self.write_chunk(chunk::IHDR, &data)?; + + // Encode the pHYs chunk + if let Some(pd) = info.pixel_dims { + let mut phys_data = [0; 9]; + phys_data[0..4].copy_from_slice(&pd.xppu.to_be_bytes()); + phys_data[4..8].copy_from_slice(&pd.yppu.to_be_bytes()); + match pd.unit { + Unit::Meter => phys_data[8] = 1, + Unit::Unspecified => phys_data[8] = 0, + } + self.write_chunk(chunk::pHYs, &phys_data)?; + } + + // If specified, the sRGB information overrides the source gamma and chromaticities. + if let Some(srgb) = &info.srgb { + srgb.encode(&mut self.w)?; + + // gAMA and cHRM are optional, for backwards compatibility + let srgb_gamma = crate::srgb::substitute_gamma(); + if Some(srgb_gamma) == info.source_gamma { + srgb_gamma.encode_gama(&mut self.w)? + } + let srgb_chromaticities = crate::srgb::substitute_chromaticities(); + if Some(srgb_chromaticities) == info.source_chromaticities { + srgb_chromaticities.encode(&mut self.w)?; + } + } else { + if let Some(gma) = info.source_gamma { + gma.encode_gama(&mut self.w)? + } + if let Some(chrms) = info.source_chromaticities { + chrms.encode(&mut self.w)?; + } + if let Some(iccp) = &info.icc_profile { + self.write_iccp_chunk("_", iccp)? + } + } + + if let Some(exif) = &info.exif_metadata { + self.write_chunk(chunk::eXIf, exif)?; + } + + if let Some(actl) = info.animation_control { + actl.encode(&mut self.w)?; + } + + // The position of the PLTE chunk is important, it must come before the tRNS chunk and after + // many of the other metadata chunks. + if let Some(p) = &info.palette { + self.write_chunk(chunk::PLTE, p)?; + }; + + if let Some(t) = &info.trns { + self.write_chunk(chunk::tRNS, t)?; + } + + for text_chunk in &info.uncompressed_latin1_text { + self.write_text_chunk(text_chunk)?; + } + + for text_chunk in &info.compressed_latin1_text { + self.write_text_chunk(text_chunk)?; + } + + for text_chunk in &info.utf8_text { + self.write_text_chunk(text_chunk)?; + } + + Ok(()) + } + /// Write a raw chunk of PNG data. /// - /// The chunk will have its CRC calculated and correctly. The data is not filtered in any way, - /// but the chunk needs to be short enough to have its length encoded correctly. + /// This function calculates the required CRC sum so this should not be included in the input + /// `data`, otherwise the data is not filtered in any way. This function returns an error if + /// the length of `data` can't be parsed as a `u32` though the length of the chunk data should + /// not exceed `i32::MAX` or 2,147,483,647. pub fn write_chunk(&mut self, name: ChunkType, data: &[u8]) -> Result<()> { use std::convert::TryFrom; @@ -614,6 +669,31 @@ text_chunk.encode(&mut self.w) } + fn write_iccp_chunk(&mut self, profile_name: &str, icc_profile: &[u8]) -> Result<()> { + let profile_name = encode_iso_8859_1(profile_name)?; + if profile_name.is_empty() || profile_name.len() > 79 { + return Err(TextEncodingError::InvalidKeywordSize.into()); + } + + let estimated_compressed_size = icc_profile.len() * 3 / 4; + let chunk_size = profile_name + .len() + .checked_add(2) // string NUL + compression type. Checked add optimizes out later Vec reallocations. + .and_then(|s| s.checked_add(estimated_compressed_size)) + .ok_or(EncodingError::LimitsExceeded)?; + + let mut data = Vec::new(); + data.try_reserve_exact(chunk_size) + .map_err(|_| EncodingError::LimitsExceeded)?; + + data.extend(profile_name.into_iter().chain([0, 0])); + + let mut encoder = ZlibEncoder::new(data, flate2::Compression::default()); + encoder.write_all(icc_profile)?; + + self.write_chunk(chunk::iCCP, &encoder.finish()?) + } + /// Check if we should allow writing another image. fn validate_new_image(&self) -> Result<()> { if !self.options.validate_sequence { @@ -652,9 +732,9 @@ } } - const MAX_IDAT_CHUNK_LEN: u32 = std::u32::MAX >> 1; + const MAX_IDAT_CHUNK_LEN: u32 = u32::MAX >> 1; #[allow(non_upper_case_globals)] - const MAX_fdAT_CHUNK_LEN: u32 = (std::u32::MAX >> 1) - 4; + const MAX_fdAT_CHUNK_LEN: u32 = (u32::MAX >> 1) - 4; /// Writes the next image data. pub fn write_image_data(&mut self, data: &[u8]) -> Result<()> { @@ -691,22 +771,23 @@ let bpp = self.info.bpp_in_prediction(); let filter_method = self.options.filter; - let adaptive_method = self.options.adaptive_filter; - let zlib_encoded = match self.info.compression { - Compression::Fast => { + let zlib_encoded = match self.options.compression { + DeflateCompression::NoCompression => { + let mut compressor = + fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?; + for line in data.chunks(in_len) { + compressor.write_data(&[0])?; + compressor.write_data(line)?; + } + compressor.finish()?.into_inner() + } + DeflateCompression::FdeflateUltraFast => { let mut compressor = fdeflate::Compressor::new(std::io::Cursor::new(Vec::new()))?; let mut current = vec![0; in_len + 1]; for line in data.chunks(in_len) { - let filter_type = filter( - filter_method, - adaptive_method, - bpp, - prev, - line, - &mut current[1..], - ); + let filter_type = filter(filter_method, bpp, prev, line, &mut current[1..]); current[0] = filter_type as u8; compressor.write_data(¤t)?; @@ -720,10 +801,7 @@ // Write uncompressed data since the result from fast compression would take // more space than that. // - // We always use FilterType::NoFilter here regardless of the filter method - // requested by the user. Doing filtering again would only add performance - // cost for both encoding and subsequent decoding, without improving the - // compression ratio. + // This is essentially a fallback to NoCompression. let mut compressor = fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?; for line in data.chunks(in_len) { @@ -735,19 +813,13 @@ compressed } } - _ => { + DeflateCompression::Level(level) => { let mut current = vec![0; in_len]; - let mut zlib = ZlibEncoder::new(Vec::new(), self.info.compression.to_options()); + let mut zlib = + ZlibEncoder::new(Vec::new(), flate2::Compression::new(u32::from(level))); for line in data.chunks(in_len) { - let filter_type = filter( - filter_method, - adaptive_method, - bpp, - prev, - line, - &mut current, - ); + let filter_type = filter(filter_method, bpp, prev, line, &mut current); zlib.write_all(&[filter_type as u8])?; zlib.write_all(¤t)?; @@ -817,28 +889,15 @@ Ok(()) } - /// Set the used filter type for the following frames. + /// Set the used filter type. /// - /// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for - /// sample values based on the previous. For a potentially better compression ratio, at the - /// cost of more complex processing, try out [`FilterType::Paeth`]. - /// - /// [`FilterType::Sub`]: enum.FilterType.html#variant.Sub - /// [`FilterType::Paeth`]: enum.FilterType.html#variant.Paeth - pub fn set_filter(&mut self, filter: FilterType) { - self.options.filter = filter; - } - - /// Set the adaptive filter type for the following frames. + /// The default filter is [`Filter::Adaptive`] which automatically selects the best filter + /// for each row of the image. /// - /// Adaptive filtering attempts to select the best filter for each line - /// based on heuristics which minimize the file size for compression rather - /// than use a single filter for the entire image. The default method is - /// [`AdaptiveFilterType::NonAdaptive`]. - /// - /// [`AdaptiveFilterType::NonAdaptive`]: enum.AdaptiveFilterType.html - pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) { - self.options.adaptive_filter = adaptive_filter; + /// You should only change this if you are after very fast compression, + /// and either don't care about compression ratio or know exactly what works best for your images. + pub fn set_filter(&mut self, filter: Filter) { + self.options.filter = filter; } /// Set the fraction of time the following frames are going to be displayed, @@ -846,7 +905,7 @@ /// /// If the denominator is 0, it is to be treated as if it were 100 /// (that is, the numerator then specifies 1/100ths of a second). - /// If the the value of the numerator is 0 the decoder should render the next frame + /// If the value of the numerator is 0 the decoder should render the next frame /// as quickly as possible, though viewers may impose a reasonable lower bound. /// /// This method will return an error if the image is not animated. @@ -924,7 +983,7 @@ /// /// This method will return an error if the image is not animated. /// - /// [`reset_frame_position`]: struct.Writer.html#method.reset_frame_position + /// [`reset_frame_position`]: Writer::reset_frame_position pub fn reset_frame_dimension(&mut self) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.width = self.info.width - fctl.x_offset; @@ -941,7 +1000,7 @@ /// /// This method will return an error if the image is not animated. /// - /// [`set_frame_position(0, 0)`]: struct.Writer.html#method.set_frame_position + /// [`set_frame_position(0, 0)`]: Writer::set_frame_position pub fn reset_frame_position(&mut self) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.x_offset = 0; @@ -965,8 +1024,6 @@ /// of each play.* /// /// This method will return an error if the image is not animated. - /// - /// [`BlendOP`]: enum.BlendOp.html pub fn set_blend_op(&mut self, op: BlendOp) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.blend_op = op; @@ -987,10 +1044,6 @@ /// it will be treated as [`DisposeOp::Background`].* /// /// This method will return an error if the image is not animated. - /// - /// [`DisposeOp`]: ../common/enum.BlendOp.html - /// [`DisposeOp::Previous`]: ../common/enum.BlendOp.html#variant.Previous - /// [`DisposeOp::Background`]: ../common/enum.BlendOp.html#variant.Background pub fn set_dispose_op(&mut self, op: DisposeOp) -> Result<()> { if let Some(ref mut fctl) = self.info.frame_control { fctl.dispose_op = op; @@ -1008,7 +1061,7 @@ /// /// This borrows the writer which allows for manually appending additional /// chunks after the image data has been written. - pub fn stream_writer(&mut self) -> Result> { + pub fn stream_writer(&mut self) -> Result> { self.stream_writer_with_size(DEFAULT_BUFFER_LENGTH) } @@ -1016,16 +1069,18 @@ /// /// See [`stream_writer`]. /// - /// [`stream_writer`]: #fn.stream_writer - pub fn stream_writer_with_size(&mut self, size: usize) -> Result> { + /// [`stream_writer`]: Self::stream_writer + pub fn stream_writer_with_size(&mut self, size: usize) -> Result> { StreamWriter::new(ChunkOutput::Borrowed(self), size) } /// Turn this into a stream writer for image data. /// /// This allows you to create images that do not fit in memory. The default - /// chunk size is 4K, use `stream_writer_with_size` to set another chunk + /// chunk size is 4K, use [`stream_writer_with_size`] to set another chunk /// size. + /// + /// [`stream_writer_with_size`]: Self::stream_writer_with_size pub fn into_stream_writer(self) -> Result> { self.into_stream_writer_with_size(DEFAULT_BUFFER_LENGTH) } @@ -1034,7 +1089,7 @@ /// /// See [`into_stream_writer`]. /// - /// [`into_stream_writer`]: #fn.into_stream_writer + /// [`into_stream_writer`]: Self::into_stream_writer pub fn into_stream_writer_with_size(self, size: usize) -> Result> { StreamWriter::new(ChunkOutput::Owned(self), size) } @@ -1119,7 +1174,7 @@ // // TODO (maybe): find a way to hold two chunks at a time if `usize` // is 64 bits. - const CAP: usize = std::u32::MAX as usize >> 1; + const CAP: usize = u32::MAX as usize >> 1; let curr_chunk = if writer.images_written == 0 { chunk::IDAT } else { @@ -1182,7 +1237,7 @@ Ok(()) } - /// Set the `FrameControl` for the following frame + /// Set the [`FrameControl`] for the following frame /// /// It will ignore the `sequence_number` of the parameter /// as it is updated internally. @@ -1280,13 +1335,29 @@ /// variant is used to signal that. enum Wrapper<'a, W: Write> { Chunk(ChunkWriter<'a, W>), - Zlib(ZlibEncoder>), + Flate2(ZlibEncoder>), + FDeflate(fdeflate::Compressor>), Unrecoverable, /// This is used in-between, should never be matched None, } impl<'a, W: Write> Wrapper<'a, W> { + fn from_level(writer: ChunkWriter<'a, W>, compression: DeflateCompression) -> io::Result { + Ok(match compression { + DeflateCompression::NoCompression => { + Wrapper::Flate2(ZlibEncoder::new(writer, flate2::Compression::none())) + } + DeflateCompression::FdeflateUltraFast => { + Wrapper::FDeflate(fdeflate::Compressor::new(writer)?) + } + DeflateCompression::Level(level) => Wrapper::Flate2(ZlibEncoder::new( + writer, + flate2::Compression::new(u32::from(level)), + )), + }) + } + /// Like `Option::take` this returns the `Wrapper` contained /// in `self` and replaces it with `Wrapper::None` fn take(&mut self) -> Wrapper<'a, W> { @@ -1299,15 +1370,17 @@ /// Streaming PNG writer /// /// This may silently fail in the destructor, so it is a good idea to call -/// [`finish`](#method.finish) or [`flush`] before dropping. +/// [`finish`] or [`flush`] before dropping. /// -/// [`flush`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html#tymethod.flush +/// [`finish`]: Self::finish +/// [`flush`]: Write::flush pub struct StreamWriter<'a, W: Write> { /// The option here is needed in order to access the inner `ChunkWriter` in-between /// each frame, which is needed for writing the fcTL chunks between each frame writer: Wrapper<'a, W>, prev_buf: Vec, curr_buf: Vec, + filtered_buf: Vec, /// Amount of data already written index: usize, /// length of the current scanline @@ -1319,10 +1392,9 @@ height: u32, bpp: BytesPerPixel, - filter: FilterType, - adaptive_filter: AdaptiveFilterType, + filter: Filter, fctl: Option, - compression: Compression, + compression: DeflateCompression, } impl<'a, W: Write> StreamWriter<'a, W> { @@ -1331,32 +1403,31 @@ width, height, frame_control: fctl, - compression, .. } = writer.info; let bpp = writer.info.bpp_in_prediction(); let in_len = writer.info.raw_row_length() - 1; let filter = writer.options.filter; - let adaptive_filter = writer.options.adaptive_filter; + let compression = writer.options.compression; let prev_buf = vec![0; in_len]; let curr_buf = vec![0; in_len]; + let filtered_buf = vec![0; in_len]; let mut chunk_writer = ChunkWriter::new(writer, buf_len); let (line_len, to_write) = chunk_writer.next_frame_info(); chunk_writer.write_header()?; - let zlib = ZlibEncoder::new(chunk_writer, compression.to_options()); Ok(StreamWriter { - writer: Wrapper::Zlib(zlib), + writer: Wrapper::from_level(chunk_writer, compression)?, index: 0, prev_buf, curr_buf, + filtered_buf, bpp, filter, width, height, - adaptive_filter, line_len, to_write, fctl, @@ -1364,28 +1435,15 @@ }) } - /// Set the used filter type for the next frame. + /// Set the used filter type. /// - /// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for - /// sample values based on the previous. For a potentially better compression ratio, at the - /// cost of more complex processing, try out [`FilterType::Paeth`]. - /// - /// [`FilterType::Sub`]: enum.FilterType.html#variant.Sub - /// [`FilterType::Paeth`]: enum.FilterType.html#variant.Paeth - pub fn set_filter(&mut self, filter: FilterType) { - self.filter = filter; - } - - /// Set the adaptive filter type for the next frame. + /// The default filter is [`Filter::Adaptive`] which automatically selects the best filter + /// for each row of the image. /// - /// Adaptive filtering attempts to select the best filter for each line - /// based on heuristics which minimize the file size for compression rather - /// than use a single filter for the entire image. The default method is - /// [`AdaptiveFilterType::NonAdaptive`]. - /// - /// [`AdaptiveFilterType::NonAdaptive`]: enum.AdaptiveFilterType.html - pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) { - self.adaptive_filter = adaptive_filter; + /// You should only change this if you are after very fast compression, + /// and either don't care about compression ratio or know exactly what works best for your images. + pub fn set_filter(&mut self, filter: Filter) { + self.filter = filter; } /// Set the fraction of time the following frames are going to be displayed, @@ -1393,7 +1451,7 @@ /// /// If the denominator is 0, it is to be treated as if it were 100 /// (that is, the numerator then specifies 1/100ths of a second). - /// If the the value of the numerator is 0 the decoder should render the next frame + /// If the value of the numerator is 0 the decoder should render the next frame /// as quickly as possible, though viewers may impose a reasonable lower bound. /// /// This method will return an error if the image is not animated. @@ -1467,7 +1525,7 @@ /// /// This method will return an error if the image is not animated. /// - /// [`reset_frame_position`]: struct.Writer.html#method.reset_frame_position + /// [`reset_frame_position`]: Writer::reset_frame_position pub fn reset_frame_dimension(&mut self) -> Result<()> { if let Some(ref mut fctl) = self.fctl { fctl.width = self.width - fctl.x_offset; @@ -1484,7 +1542,7 @@ /// /// This method will return an error if the image is not animated. /// - /// [`set_frame_position(0, 0)`]: struct.Writer.html#method.set_frame_position + /// [`set_frame_position(0, 0)`]: Writer::set_frame_position pub fn reset_frame_position(&mut self) -> Result<()> { if let Some(ref mut fctl) = self.fctl { fctl.x_offset = 0; @@ -1508,8 +1566,6 @@ /// of each play.* /// /// This method will return an error if the image is not animated. - /// - /// [`BlendOP`]: enum.BlendOp.html pub fn set_blend_op(&mut self, op: BlendOp) -> Result<()> { if let Some(ref mut fctl) = self.fctl { fctl.blend_op = op; @@ -1530,10 +1586,6 @@ /// it will be treated as [`DisposeOp::Background`].* /// /// This method will return an error if the image is not animated. - /// - /// [`DisposeOp`]: ../common/enum.BlendOp.html - /// [`DisposeOp::Previous`]: ../common/enum.BlendOp.html#variant.Previous - /// [`DisposeOp::Background`]: ../common/enum.BlendOp.html#variant.Background pub fn set_dispose_op(&mut self, op: DisposeOp) -> Result<()> { if let Some(ref mut fctl) = self.fctl { fctl.dispose_op = op; @@ -1550,16 +1602,33 @@ /// [`Writer`], then it will also do a check on their correctness. Differently from /// [`Writer::finish`], this just `flush`es, returns error if some data is abandoned. pub fn finish(mut self) -> Result<()> { + self.finish_mut() + } + + /// Internal helper that can be called both from `fn finish(mut self)` + /// and from `fn drop(&mut self)`. + fn finish_mut(&mut self) -> Result<()> { if self.to_write > 0 { let err = FormatErrorKind::MissingData(self.to_write).into(); return Err(EncodingError::Format(err)); } - // TODO: call `writer.finish` somehow? self.flush()?; - - if let Wrapper::Chunk(wrt) = self.writer.take() { - wrt.writer.validate_sequence_done()?; + match self.writer.take() { + Wrapper::Chunk(wrt) => { + wrt.writer.validate_sequence_done()?; + } + Wrapper::FDeflate(wrt) => { + wrt.finish()?; + } + Wrapper::Flate2(wrt) => { + wrt.finish()?; + } + Wrapper::None => unreachable!(), + Wrapper::Unrecoverable => { + let err = FormatErrorKind::Unrecoverable.into(); + return Err(EncodingError::Format(err)); + } } Ok(()) @@ -1576,7 +1645,9 @@ let err = FormatErrorKind::Unrecoverable.into(); return Err(EncodingError::Format(err)); } - Wrapper::Zlib(_) => unreachable!("never called on a half-finished frame"), + Wrapper::Flate2(_) | Wrapper::FDeflate(_) => { + unreachable!("never called on a half-finished frame") + } Wrapper::None => unreachable!(), }; wrt.flush()?; @@ -1594,10 +1665,13 @@ // now it can be taken because the next statements cannot cause any errors match self.writer.take() { - Wrapper::Chunk(wrt) => { - let encoder = ZlibEncoder::new(wrt, self.compression.to_options()); - self.writer = Wrapper::Zlib(encoder); - } + Wrapper::Chunk(wrt) => match Wrapper::from_level(wrt, self.compression) { + Ok(writer) => self.writer = writer, + Err(err) => { + self.writer = Wrapper::Unrecoverable; + return Err(err.into()); + } + }, _ => unreachable!(), }; @@ -1618,7 +1692,14 @@ if self.to_write == 0 { match self.writer.take() { - Wrapper::Zlib(wrt) => match wrt.finish() { + Wrapper::Flate2(wrt) => match wrt.finish() { + Ok(chunk) => self.writer = Wrapper::Chunk(chunk), + Err(err) => { + self.writer = Wrapper::Unrecoverable; + return Err(err); + } + }, + Wrapper::FDeflate(wrt) => match wrt.finish() { Ok(chunk) => self.writer = Wrapper::Chunk(chunk), Err(err) => { self.writer = Wrapper::Unrecoverable; @@ -1639,24 +1720,26 @@ self.to_write -= written; if self.index == self.line_len { - // TODO: reuse this buffer between rows. - let mut filtered = vec![0; self.curr_buf.len()]; let filter_type = filter( self.filter, - self.adaptive_filter, self.bpp, &self.prev_buf, &self.curr_buf, - &mut filtered, + &mut self.filtered_buf, ); // This can't fail as the other variant is used only to allow the zlib encoder to finish - let wrt = match &mut self.writer { - Wrapper::Zlib(wrt) => wrt, + match &mut self.writer { + Wrapper::Flate2(wrt) => { + wrt.write_all(&[filter_type as u8])?; + wrt.write_all(&self.filtered_buf)?; + } + Wrapper::FDeflate(wrt) => { + wrt.write_data(&[filter_type as u8])?; + wrt.write_data(&self.filtered_buf)?; + } _ => unreachable!(), }; - wrt.write_all(&[filter_type as u8])?; - wrt.write_all(&filtered)?; mem::swap(&mut self.prev_buf, &mut self.curr_buf); self.index = 0; } @@ -1666,8 +1749,9 @@ fn flush(&mut self) -> io::Result<()> { match &mut self.writer { - Wrapper::Zlib(wrt) => wrt.flush()?, + Wrapper::Flate2(wrt) => wrt.flush()?, Wrapper::Chunk(wrt) => wrt.flush()?, + Wrapper::FDeflate(_) => (), // TODO: Add `flush()` to `fdeflate::Compressor`? // This handles both the case where we entered an unrecoverable state after zlib // decoding failure and after a panic while we had taken the chunk/zlib reader. Wrapper::Unrecoverable | Wrapper::None => { @@ -1687,26 +1771,7 @@ impl Drop for StreamWriter<'_, W> { fn drop(&mut self) { - let _ = self.flush(); - } -} - -/// Mod to encapsulate the converters depending on the `deflate` crate. -/// -/// Since this only contains trait impls, there is no need to make this public, they are simply -/// available when the mod is compiled as well. -impl Compression { - fn to_options(self) -> flate2::Compression { - #[allow(deprecated)] - match self { - Compression::Default => flate2::Compression::default(), - Compression::Fast => flate2::Compression::fast(), - Compression::Best => flate2::Compression::best(), - #[allow(deprecated)] - Compression::Huffman => flate2::Compression::none(), - #[allow(deprecated)] - Compression::Rle => flate2::Compression::none(), - } + let _ = self.finish_mut(); } } @@ -1715,15 +1780,25 @@ use super::*; use crate::Decoder; - use rand::{thread_rng, Rng}; + use io::BufReader; + use rand::{rng, Rng}; + use std::cmp; use std::fs::File; - use std::io::{Cursor, Write}; - use std::{cmp, io}; + use std::io::Cursor; #[test] - fn roundtrip() { + fn roundtrip1() { + roundtrip_inner(); + } + + #[test] + fn roundtrip2() { + roundtrip_inner(); + } + + fn roundtrip_inner() { // More loops = more random testing, but also more test wait time - for _ in 0..10 { + for _ in 0..5 { for path in glob::glob("tests/pngsuite/*.png") .unwrap() .map(|r| r.unwrap()) @@ -1734,42 +1809,55 @@ } eprintln!("{}", path.display()); // Decode image - let decoder = Decoder::new(File::open(path).unwrap()); + let decoder = Decoder::new(BufReader::new(File::open(path).unwrap())); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.next_frame(&mut buf).unwrap(); - // Encode decoded image - let mut out = Vec::new(); - { - let mut wrapper = RandomChunkWriter { - rng: thread_rng(), - w: &mut out, - }; - - let mut encoder = Encoder::new(&mut wrapper, info.width, info.height); - encoder.set_color(info.color_type); - encoder.set_depth(info.bit_depth); - if let Some(palette) = &reader.info().palette { - encoder.set_palette(palette.clone()); + use DeflateCompression::*; + for compression in [NoCompression, FdeflateUltraFast, Level(4)] { + // Encode decoded image + let mut out = Vec::new(); + { + let mut wrapper = RandomChunkWriter { + rng: rng(), + w: &mut out, + }; + + let mut encoder = Encoder::new(&mut wrapper, info.width, info.height); + encoder.set_color(info.color_type); + encoder.set_depth(info.bit_depth); + encoder.set_deflate_compression(compression); + if let Some(palette) = &reader.info().palette { + encoder.set_palette(palette.clone()); + } + let mut encoder = encoder.write_header().unwrap(); + encoder.write_image_data(&buf).unwrap(); } - let mut encoder = encoder.write_header().unwrap(); - encoder.write_image_data(&buf).unwrap(); + // Decode encoded decoded image + let decoder = Decoder::new(Cursor::new(&*out)); + let mut reader = decoder.read_info().unwrap(); + let mut buf2 = vec![0; reader.output_buffer_size().unwrap()]; + reader.next_frame(&mut buf2).unwrap(); + // check if the encoded image is ok: + assert_eq!(buf, buf2); } - // Decode encoded decoded image - let decoder = Decoder::new(&*out); - let mut reader = decoder.read_info().unwrap(); - let mut buf2 = vec![0; reader.output_buffer_size()]; - reader.next_frame(&mut buf2).unwrap(); - // check if the encoded image is ok: - assert_eq!(buf, buf2); } } } #[test] - fn roundtrip_stream() { + fn roundtrip_stream1() { + roundtrip_stream_inner(); + } + + #[test] + fn roundtrip_stream2() { + roundtrip_stream_inner(); + } + + fn roundtrip_stream_inner() { // More loops = more random testing, but also more test wait time - for _ in 0..10 { + for _ in 0..5 { for path in glob::glob("tests/pngsuite/*.png") .unwrap() .map(|r| r.unwrap()) @@ -1779,41 +1867,45 @@ continue; } // Decode image - let decoder = Decoder::new(File::open(path).unwrap()); + let decoder = Decoder::new(BufReader::new(File::open(path).unwrap())); let mut reader = decoder.read_info().unwrap(); - let mut buf = vec![0; reader.output_buffer_size()]; + let mut buf = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.next_frame(&mut buf).unwrap(); - // Encode decoded image - let mut out = Vec::new(); - { - let mut wrapper = RandomChunkWriter { - rng: thread_rng(), - w: &mut out, - }; - - let mut encoder = Encoder::new(&mut wrapper, info.width, info.height); - encoder.set_color(info.color_type); - encoder.set_depth(info.bit_depth); - if let Some(palette) = &reader.info().palette { - encoder.set_palette(palette.clone()); - } - let mut encoder = encoder.write_header().unwrap(); - let mut stream_writer = encoder.stream_writer().unwrap(); + use DeflateCompression::*; + for compression in [NoCompression, FdeflateUltraFast, Level(4)] { + // Encode decoded image + let mut out = Vec::new(); + { + let mut wrapper = RandomChunkWriter { + rng: rng(), + w: &mut out, + }; + + let mut encoder = Encoder::new(&mut wrapper, info.width, info.height); + encoder.set_color(info.color_type); + encoder.set_depth(info.bit_depth); + encoder.set_deflate_compression(compression); + if let Some(palette) = &reader.info().palette { + encoder.set_palette(palette.clone()); + } + let mut encoder = encoder.write_header().unwrap(); + let mut stream_writer = encoder.stream_writer().unwrap(); + + let mut outer_wrapper = RandomChunkWriter { + rng: rng(), + w: &mut stream_writer, + }; - let mut outer_wrapper = RandomChunkWriter { - rng: thread_rng(), - w: &mut stream_writer, - }; - - outer_wrapper.write_all(&buf).unwrap(); + outer_wrapper.write_all(&buf).unwrap(); + } + // Decode encoded decoded image + let decoder = Decoder::new(Cursor::new(&*out)); + let mut reader = decoder.read_info().unwrap(); + let mut buf2 = vec![0; reader.output_buffer_size().unwrap()]; + reader.next_frame(&mut buf2).unwrap(); + // check if the encoded image is ok: + assert_eq!(buf, buf2); } - // Decode encoded decoded image - let decoder = Decoder::new(&*out); - let mut reader = decoder.read_info().unwrap(); - let mut buf2 = vec![0; reader.output_buffer_size()]; - reader.next_frame(&mut buf2).unwrap(); - // check if the encoded image is ok: - assert_eq!(buf, buf2); } } } @@ -1823,10 +1915,10 @@ for &bit_depth in &[1u8, 2, 4, 8] { // Do a reference decoding, choose a fitting palette image from pngsuite let path = format!("tests/pngsuite/basn3p0{}.png", bit_depth); - let decoder = Decoder::new(File::open(&path).unwrap()); + let decoder = Decoder::new(BufReader::new(File::open(&path).unwrap())); let mut reader = decoder.read_info().unwrap(); - let mut decoded_pixels = vec![0; reader.output_buffer_size()]; + let mut decoded_pixels = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.info(); assert_eq!( info.width as usize * info.height as usize * usize::from(bit_depth), @@ -1848,9 +1940,9 @@ } // Decode re-encoded image - let decoder = Decoder::new(&*out); + let decoder = Decoder::new(Cursor::new(&*out)); let mut reader = decoder.read_info().unwrap(); - let mut redecoded = vec![0; reader.output_buffer_size()]; + let mut redecoded = vec![0; reader.output_buffer_size().unwrap()]; reader.next_frame(&mut redecoded).unwrap(); // check if the encoded image is ok: assert_eq!(indexed_data, redecoded); @@ -2040,7 +2132,7 @@ fn all_filters_roundtrip() -> io::Result<()> { let pixel: Vec<_> = (0..48).collect(); - let roundtrip = |filter: FilterType| -> io::Result<()> { + let roundtrip = |filter: Filter| -> io::Result<()> { let mut buffer = vec![]; let mut encoder = Encoder::new(&mut buffer, 4, 4); encoder.set_depth(BitDepth::Eight); @@ -2060,11 +2152,11 @@ Ok(()) }; - roundtrip(FilterType::NoFilter)?; - roundtrip(FilterType::Sub)?; - roundtrip(FilterType::Up)?; - roundtrip(FilterType::Avg)?; - roundtrip(FilterType::Paeth)?; + roundtrip(Filter::NoFilter)?; + roundtrip(Filter::Sub)?; + roundtrip(Filter::Up)?; + roundtrip(Filter::Avg)?; + roundtrip(Filter::Paeth)?; Ok(()) } @@ -2078,7 +2170,7 @@ let mut encoder = Encoder::new(&mut buffer, 4, 4); encoder.set_depth(BitDepth::Eight); encoder.set_color(ColorType::Rgb); - encoder.set_filter(FilterType::Avg); + encoder.set_filter(Filter::Avg); if let Some(gamma) = gamma { encoder.set_source_gamma(gamma); } @@ -2087,7 +2179,7 @@ let decoder = crate::Decoder::new(Cursor::new(buffer)); let mut reader = decoder.read_info()?; assert_eq!( - reader.info().source_gamma, + reader.info().gamma(), gamma, "Deviation with gamma {:?}", gamma @@ -2302,13 +2394,42 @@ let mut encoder = Encoder::new(&mut cursor, 8, 8); encoder.set_color(ColorType::Rgba); - encoder.set_filter(FilterType::Paeth); + encoder.set_filter(Filter::Paeth); + let mut writer = encoder.write_header()?; + let mut stream = writer.stream_writer()?; + + for _ in 0..8 { + let written = stream.write(&[1; 32])?; + assert_eq!(written, 32); + } + stream.finish()?; + drop(writer); + + { + cursor.set_position(0); + let mut decoder = Decoder::new(cursor).read_info().expect("A valid image"); + let mut buffer = [0u8; 256]; + decoder.next_frame(&mut buffer[..]).expect("Valid read"); + assert_eq!(buffer, [1; 256]); + } + + Ok(()) + } + + fn test_stream_flushing(compression: Compression) -> Result<()> { + let output = vec![0u8; 1024]; + let mut cursor = Cursor::new(output); + + let mut encoder = Encoder::new(&mut cursor, 8, 8); + encoder.set_color(ColorType::Rgba); + encoder.set_compression(compression); let mut writer = encoder.write_header()?; let mut stream = writer.stream_writer()?; for _ in 0..8 { let written = stream.write(&[1; 32])?; assert_eq!(written, 32); + stream.flush()?; } stream.finish()?; drop(writer); @@ -2325,6 +2446,31 @@ } #[test] + fn stream_flushing_with_high_compression() -> Result<()> { + test_stream_flushing(Compression::High) + } + + #[test] + fn stream_flushing_with_balanced_compression() -> Result<()> { + test_stream_flushing(Compression::Balanced) + } + + #[test] + fn stream_flushing_with_fast_compression() -> Result<()> { + test_stream_flushing(Compression::Fast) + } + + #[test] + fn stream_flushing_with_fastest_compression() -> Result<()> { + test_stream_flushing(Compression::Fastest) + } + + #[test] + fn stream_flushing_with_no_compression() -> Result<()> { + test_stream_flushing(Compression::NoCompression) + } + + #[test] #[cfg(all(unix, not(target_pointer_width = "32")))] fn exper_error_on_huge_chunk() -> Result<()> { // Okay, so we want a proper 4 GB chunk but not actually spend the memory for reserving it. @@ -2401,7 +2547,7 @@ impl Write for RandomChunkWriter { fn write(&mut self, buf: &[u8]) -> io::Result { // choose a random length to write - let len = cmp::min(self.rng.gen_range(1..50), buf.len()); + let len = cmp::min(self.rng.random_range(1..50), buf.len()); self.w.write(&buf[0..len]) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/filter.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/filter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/filter.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/filter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,179 +1,61 @@ use core::convert::TryInto; -use crate::common::BytesPerPixel; +use crate::{common::BytesPerPixel, Compression}; -/// SIMD helpers for `fn unfilter` +/// The byte level filter applied to scanlines to prepare them for compression. /// -/// TODO(https://github.com/rust-lang/rust/issues/86656): Stop gating this module behind the -/// "unstable" feature of the `png` crate. This should be possible once the "portable_simd" -/// feature of Rust gets stabilized. -#[cfg(feature = "unstable")] -mod simd { - use std::simd::cmp::{SimdOrd, SimdPartialEq}; - use std::simd::num::{SimdInt, SimdUint}; - use std::simd::{u8x4, u8x8, LaneCount, Simd, SupportedLaneCount}; - - /// This is an equivalent of the `PaethPredictor` function from - /// [the spec](http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html#Filter-type-4-Paeth) - /// except that it simultaenously calculates the predictor for all SIMD lanes. - /// Mapping between parameter names and pixel positions can be found in - /// [a diagram here](https://www.w3.org/TR/png/#filter-byte-positions). - /// - /// Examples of how different pixel types may be represented as multiple SIMD lanes: - /// - RGBA => 4 lanes of `i16x4` contain R, G, B, A - /// - RGB => 4 lanes of `i16x4` contain R, G, B, and a ignored 4th value - /// - /// The SIMD algorithm below is based on [`libpng`](https://github.com/glennrp/libpng/blob/f8e5fa92b0e37ab597616f554bee254157998227/intel/filter_sse2_intrinsics.c#L261-L280). - fn paeth_predictor( - a: Simd, - b: Simd, - c: Simd, - ) -> Simd - where - LaneCount: SupportedLaneCount, - { - let pa = b - c; // (p-a) == (a+b-c - a) == (b-c) - let pb = a - c; // (p-b) == (a+b-c - b) == (a-c) - let pc = pa + pb; // (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) - - let pa = pa.abs(); - let pb = pb.abs(); - let pc = pc.abs(); - - let smallest = pc.simd_min(pa.simd_min(pb)); - - // Paeth algorithm breaks ties favoring a over b over c, so we execute the following - // lane-wise selection: - // - // if smalest == pa - // then select a - // else select (if smallest == pb then select b else select c) - smallest - .simd_eq(pa) - .select(a, smallest.simd_eq(pb).select(b, c)) - } - - /// Memory of previous pixels (as needed to unfilter `FilterType::Paeth`). - /// See also https://www.w3.org/TR/png/#filter-byte-positions - #[derive(Default)] - struct PaethState - where - LaneCount: SupportedLaneCount, - { - /// Previous pixel in the previous row. - c: Simd, - - /// Previous pixel in the current row. - a: Simd, - } - - /// Mutates `x` as needed to unfilter `FilterType::Paeth`. - /// - /// `b` is the current pixel in the previous row. `x` is the current pixel in the current row. - /// See also https://www.w3.org/TR/png/#filter-byte-positions - fn paeth_step(state: &mut PaethState, b: Simd, x: &mut Simd) - where - LaneCount: SupportedLaneCount, - { - // Storing the inputs. - let b = b.cast::(); - - // Calculating the new value of the current pixel. - let predictor = paeth_predictor(state.a, b, state.c); - *x += predictor.cast::(); - - // Preparing for the next step. - state.c = b; - state.a = x.cast::(); - } - - fn load3(src: &[u8]) -> u8x4 { - u8x4::from_array([src[0], src[1], src[2], 0]) - } +/// Compression in general benefits from repetitive data. The filter is a content-aware method of +/// compressing the range of occurring byte values to help the compression algorithm. Note that +/// this does not operate on pixels but on raw bytes of a scanline. +/// +/// Details on how each filter works can be found in the [PNG Book](http://www.libpng.org/pub/png/book/chapter09.html). +/// +/// The default filter is `Adaptive`, which uses heuristics to select the best filter for every row. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum Filter { + NoFilter, + Sub, + Up, + Avg, + Paeth, + Adaptive, +} - fn store3(src: u8x4, dest: &mut [u8]) { - dest[0..3].copy_from_slice(&src.to_array()[0..3]) +impl Default for Filter { + fn default() -> Self { + Filter::Adaptive } +} - /// Undoes `FilterType::Paeth` for `BytesPerPixel::Three`. - pub fn unfilter_paeth3(mut prev_row: &[u8], mut curr_row: &mut [u8]) { - debug_assert_eq!(prev_row.len(), curr_row.len()); - debug_assert_eq!(prev_row.len() % 3, 0); - - let mut state = PaethState::<4>::default(); - while prev_row.len() >= 4 { - // `u8x4` requires working with `[u8;4]`, but we can just load and ignore the first - // byte from the next triple. This optimization technique mimics the algorithm found - // in - // https://github.com/glennrp/libpng/blob/f8e5fa92b0e37ab597616f554bee254157998227/intel/filter_sse2_intrinsics.c#L130-L131 - let b = u8x4::from_slice(prev_row); - let mut x = u8x4::from_slice(curr_row); - - paeth_step(&mut state, b, &mut x); - - // We can speculate that writing 4 bytes might be more efficient (just as with using - // `u8x4::from_slice` above), but we can't use that here, because we can't clobber the - // first byte of the next pixel in the `curr_row`. - store3(x, curr_row); - - prev_row = &prev_row[3..]; - curr_row = &mut curr_row[3..]; +impl From for Filter { + fn from(value: RowFilter) -> Self { + match value { + RowFilter::NoFilter => Filter::NoFilter, + RowFilter::Sub => Filter::Sub, + RowFilter::Up => Filter::Up, + RowFilter::Avg => Filter::Avg, + RowFilter::Paeth => Filter::Paeth, } - // Can't use `u8x4::from_slice` for the last `[u8;3]`. - let b = load3(prev_row); - let mut x = load3(curr_row); - paeth_step(&mut state, b, &mut x); - store3(x, curr_row); - } - - fn load6(src: &[u8]) -> u8x8 { - u8x8::from_array([src[0], src[1], src[2], src[3], src[4], src[5], 0, 0]) - } - - fn store6(src: u8x8, dest: &mut [u8]) { - dest[0..6].copy_from_slice(&src.to_array()[0..6]) } +} - /// Undoes `FilterType::Paeth` for `BytesPerPixel::Six`. - pub fn unfilter_paeth6(mut prev_row: &[u8], mut curr_row: &mut [u8]) { - debug_assert_eq!(prev_row.len(), curr_row.len()); - debug_assert_eq!(prev_row.len() % 6, 0); - - let mut state = PaethState::<8>::default(); - while prev_row.len() >= 8 { - // `u8x8` requires working with `[u8;8]`, but we can just load and ignore the first two - // bytes from the next pixel. This optimization technique mimics the algorithm found - // in - // https://github.com/glennrp/libpng/blob/f8e5fa92b0e37ab597616f554bee254157998227/intel/filter_sse2_intrinsics.c#L130-L131 - let b = u8x8::from_slice(prev_row); - let mut x = u8x8::from_slice(curr_row); - - paeth_step(&mut state, b, &mut x); - - // We can speculate that writing 8 bytes might be more efficient (just as with using - // `u8x8::from_slice` above), but we can't use that here, because we can't clobber the - // first bytes of the next pixel in the `curr_row`. - store6(x, curr_row); - - prev_row = &prev_row[6..]; - curr_row = &mut curr_row[6..]; +impl Filter { + pub(crate) fn from_simple(compression: Compression) -> Self { + match compression { + Compression::NoCompression => Filter::NoFilter, // with no DEFLATE filtering would only waste time + Compression::Fastest => Filter::Up, // pairs well with FdeflateUltraFast, producing much smaller files while being very fast + Compression::Fast => Filter::Adaptive, + Compression::Balanced => Filter::Adaptive, + Compression::High => Filter::Adaptive, } - // Can't use `u8x8::from_slice` for the last `[u8;6]`. - let b = load6(prev_row); - let mut x = load6(curr_row); - paeth_step(&mut state, b, &mut x); - store6(x, curr_row); } } -/// The byte level filter applied to scanlines to prepare them for compression. -/// -/// Compression in general benefits from repetitive data. The filter is a content-aware method of -/// compressing the range of occurring byte values to help the compression algorithm. Note that -/// this does not operate on pixels but on raw bytes of a scanline. +/// Unlike the public [Filter], does not include the "Adaptive" option #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] -pub enum FilterType { +pub(crate) enum RowFilter { NoFilter = 0, Sub = 1, Up = 2, @@ -181,47 +63,40 @@ Paeth = 4, } -impl Default for FilterType { +impl Default for RowFilter { fn default() -> Self { - FilterType::Sub + RowFilter::Up } } -impl FilterType { - /// u8 -> Self. Temporary solution until Rust provides a canonical one. - pub fn from_u8(n: u8) -> Option { +impl RowFilter { + pub fn from_u8(n: u8) -> Option { match n { - 0 => Some(FilterType::NoFilter), - 1 => Some(FilterType::Sub), - 2 => Some(FilterType::Up), - 3 => Some(FilterType::Avg), - 4 => Some(FilterType::Paeth), + 0 => Some(Self::NoFilter), + 1 => Some(Self::Sub), + 2 => Some(Self::Up), + 3 => Some(Self::Avg), + 4 => Some(Self::Paeth), _ => None, } } -} -/// The filtering method for preprocessing scanline data before compression. -/// -/// Adaptive filtering performs additional computation in an attempt to maximize -/// the compression of the data. [`NonAdaptive`] filtering is the default. -/// -/// [`NonAdaptive`]: enum.AdaptiveFilterType.html#variant.NonAdaptive -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum AdaptiveFilterType { - Adaptive, - NonAdaptive, -} - -impl Default for AdaptiveFilterType { - fn default() -> Self { - AdaptiveFilterType::NonAdaptive + pub fn from_method(strat: Filter) -> Option { + match strat { + Filter::NoFilter => Some(Self::NoFilter), + Filter::Sub => Some(Self::Sub), + Filter::Up => Some(Self::Up), + Filter::Avg => Some(Self::Avg), + Filter::Paeth => Some(Self::Paeth), + Filter::Adaptive => None, + } } } -fn filter_paeth_decode(a: u8, b: u8, c: u8) -> u8 { - // Decoding seems to optimize better with this algorithm +fn filter_paeth(a: u8, b: u8, c: u8) -> u8 { + // On ARM this algorithm performs much better than the one above adapted from stb, + // and this is the better-studied algorithm we've always used here, + // so we default to it on all non-x86 platforms. let pa = (i16::from(b) - i16::from(c)).abs(); let pb = (i16::from(a) - i16::from(c)).abs(); let pc = ((i16::from(a) - i16::from(c)) + (i16::from(b) - i16::from(c))).abs(); @@ -240,7 +115,24 @@ out } -fn filter_paeth(a: u8, b: u8, c: u8) -> u8 { +fn filter_paeth_stbi(a: u8, b: u8, c: u8) -> u8 { + // Decoding optimizes better with this algorithm than with `filter_paeth` + // + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + // + // Adapted from public domain PNG implementation: + // https://github.com/nothings/stb/blob/5c205738c191bcb0abc65c4febfa9bd25ff35234/stb_image.h#L4657-L4668 + let thresh = i16::from(c) * 3 - (i16::from(a) + i16::from(b)); + let lo = a.min(b); + let hi = a.max(b); + let t0 = if hi as i16 <= thresh { lo } else { c }; + let t1 = if thresh <= lo as i16 { hi } else { t0 }; + t1 +} + +fn filter_paeth_fpnge(a: u8, b: u8, c: u8) -> u8 { // This is an optimized version of the paeth filter from the PNG specification, proposed by // Luca Versari for [FPNGE](https://www.lucaversari.it/FJXL_and_FPNGE.pdf). It operates // entirely on unsigned 8-bit quantities, making it more conducive to vectorization. @@ -282,12 +174,12 @@ } pub(crate) fn unfilter( - mut filter: FilterType, + mut filter: RowFilter, tbpp: BytesPerPixel, previous: &[u8], current: &mut [u8], ) { - use self::FilterType::*; + use self::RowFilter::*; // If the previous row is empty, then treat it as if it were filled with zeros. if previous.is_empty() { @@ -298,6 +190,9 @@ } } + // Auto-vectorization notes + // ======================== + // // [2023/01 @okaneco] - Notes on optimizing decoding filters // // Links: @@ -378,6 +273,27 @@ // array operations and performing them component-wise may unlock previously // unavailable optimizations from the compiler, even when using the // `chunks_exact` methods for their potential auto-vectorization benefits. + // + // `std::simd` notes + // ================= + // + // In the past we have experimented with `std::simd` for unfiltering. This + // experiment was removed in https://github.com/image-rs/image-png/pull/585 + // because: + // + // * The crate's microbenchmarks showed that `std::simd` didn't have a + // significant advantage over auto-vectorization for most filters, except + // for Paeth unfiltering - see + // https://github.com/image-rs/image-png/pull/414#issuecomment-1736655668 + // * In the crate's microbenchmarks `std::simd` seemed to help with Paeth + // unfiltering only on x86/x64, with mixed results on ARM - see + // https://github.com/image-rs/image-png/pull/539#issuecomment-2512748043 + // * In Chromium end-to-end microbenchmarks `std::simd` either didn't help + // or resulted in a small regression (as measured on x64). See + // https://crrev.com/c/6090592. + // * Field trial data from some "real world" scenarios shows that + // performance can be quite good without relying on `std::simd` - see + // https://github.com/image-rs/image-png/discussions/562#discussioncomment-13303307 match filter { NoFilter => {} Sub => match tbpp { @@ -616,7 +532,15 @@ } } }, + #[allow(unreachable_code)] Paeth => { + // Select the fastest Paeth filter implementation based on the target architecture. + let filter_paeth_decode = if cfg!(target_arch = "x86_64") { + filter_paeth_stbi + } else { + filter_paeth + }; + // Paeth filter pixels: // C B D // A X @@ -650,37 +574,58 @@ } } BytesPerPixel::Three => { - #[cfg(feature = "unstable")] - simd::unfilter_paeth3(previous, current); + let mut a_bpp = [0; 3]; + let mut c_bpp = [0; 3]; + + let mut previous = &previous[..previous.len() / 3 * 3]; + let current_len = current.len(); + let mut current = &mut current[..current_len / 3 * 3]; - #[cfg(not(feature = "unstable"))] + while let ([c0, c1, c2, c_rest @ ..], [p0, p1, p2, p_rest @ ..]) = + (current, previous) { - let mut a_bpp = [0; 3]; - let mut c_bpp = [0; 3]; - for (chunk, b_bpp) in - current.chunks_exact_mut(3).zip(previous.chunks_exact(3)) - { - let new_chunk = [ - chunk[0].wrapping_add(filter_paeth_decode( - a_bpp[0], b_bpp[0], c_bpp[0], - )), - chunk[1].wrapping_add(filter_paeth_decode( - a_bpp[1], b_bpp[1], c_bpp[1], - )), - chunk[2].wrapping_add(filter_paeth_decode( - a_bpp[2], b_bpp[2], c_bpp[2], - )), - ]; - *TryInto::<&mut [u8; 3]>::try_into(chunk).unwrap() = new_chunk; - a_bpp = new_chunk; - c_bpp = b_bpp.try_into().unwrap(); - } + current = c_rest; + previous = p_rest; + + *c0 = c0.wrapping_add(filter_paeth_decode(a_bpp[0], *p0, c_bpp[0])); + *c1 = c1.wrapping_add(filter_paeth_decode(a_bpp[1], *p1, c_bpp[1])); + *c2 = c2.wrapping_add(filter_paeth_decode(a_bpp[2], *p2, c_bpp[2])); + + a_bpp = [*c0, *c1, *c2]; + c_bpp = [*p0, *p1, *p2]; } } BytesPerPixel::Four => { + // Using the `simd` module here has no effect on Linux + // and appears to regress performance on Windows, so we don't use it here. + // See https://github.com/image-rs/image-png/issues/567 + let mut a_bpp = [0; 4]; let mut c_bpp = [0; 4]; - for (chunk, b_bpp) in current.chunks_exact_mut(4).zip(previous.chunks_exact(4)) + + let mut previous = &previous[..previous.len() & !3]; + let current_len = current.len(); + let mut current = &mut current[..current_len & !3]; + + while let ([c0, c1, c2, c3, c_rest @ ..], [p0, p1, p2, p3, p_rest @ ..]) = + (current, previous) + { + current = c_rest; + previous = p_rest; + + *c0 = c0.wrapping_add(filter_paeth_decode(a_bpp[0], *p0, c_bpp[0])); + *c1 = c1.wrapping_add(filter_paeth_decode(a_bpp[1], *p1, c_bpp[1])); + *c2 = c2.wrapping_add(filter_paeth_decode(a_bpp[2], *p2, c_bpp[2])); + *c3 = c3.wrapping_add(filter_paeth_decode(a_bpp[3], *p3, c_bpp[3])); + + a_bpp = [*c0, *c1, *c2, *c3]; + c_bpp = [*p0, *p1, *p2, *p3]; + } + } + BytesPerPixel::Six => { + let mut a_bpp = [0; 6]; + let mut c_bpp = [0; 6]; + for (chunk, b_bpp) in current.chunks_exact_mut(6).zip(previous.chunks_exact(6)) { let new_chunk = [ chunk[0] @@ -691,49 +636,16 @@ .wrapping_add(filter_paeth_decode(a_bpp[2], b_bpp[2], c_bpp[2])), chunk[3] .wrapping_add(filter_paeth_decode(a_bpp[3], b_bpp[3], c_bpp[3])), + chunk[4] + .wrapping_add(filter_paeth_decode(a_bpp[4], b_bpp[4], c_bpp[4])), + chunk[5] + .wrapping_add(filter_paeth_decode(a_bpp[5], b_bpp[5], c_bpp[5])), ]; - *TryInto::<&mut [u8; 4]>::try_into(chunk).unwrap() = new_chunk; + *TryInto::<&mut [u8; 6]>::try_into(chunk).unwrap() = new_chunk; a_bpp = new_chunk; c_bpp = b_bpp.try_into().unwrap(); } } - BytesPerPixel::Six => { - #[cfg(feature = "unstable")] - simd::unfilter_paeth6(previous, current); - - #[cfg(not(feature = "unstable"))] - { - let mut a_bpp = [0; 6]; - let mut c_bpp = [0; 6]; - for (chunk, b_bpp) in - current.chunks_exact_mut(6).zip(previous.chunks_exact(6)) - { - let new_chunk = [ - chunk[0].wrapping_add(filter_paeth_decode( - a_bpp[0], b_bpp[0], c_bpp[0], - )), - chunk[1].wrapping_add(filter_paeth_decode( - a_bpp[1], b_bpp[1], c_bpp[1], - )), - chunk[2].wrapping_add(filter_paeth_decode( - a_bpp[2], b_bpp[2], c_bpp[2], - )), - chunk[3].wrapping_add(filter_paeth_decode( - a_bpp[3], b_bpp[3], c_bpp[3], - )), - chunk[4].wrapping_add(filter_paeth_decode( - a_bpp[4], b_bpp[4], c_bpp[4], - )), - chunk[5].wrapping_add(filter_paeth_decode( - a_bpp[5], b_bpp[5], c_bpp[5], - )), - ]; - *TryInto::<&mut [u8; 6]>::try_into(chunk).unwrap() = new_chunk; - a_bpp = new_chunk; - c_bpp = b_bpp.try_into().unwrap(); - } - } - } BytesPerPixel::Eight => { let mut a_bpp = [0; 8]; let mut c_bpp = [0; 8]; @@ -768,16 +680,16 @@ } fn filter_internal( - method: FilterType, + method: RowFilter, bpp: usize, len: usize, previous: &[u8], current: &[u8], output: &mut [u8], -) -> FilterType { - use self::FilterType::*; +) -> RowFilter { + use self::RowFilter::*; - // This value was chosen experimentally based on what acheived the best performance. The + // This value was chosen experimentally based on what achieved the best performance. The // Rust compiler does auto-vectorization, and 32-bytes per loop iteration seems to enable // the fastest code when doing so. const CHUNK_SIZE: usize = 32; @@ -883,7 +795,7 @@ .zip(&mut c_chunks) { for i in 0..CHUNK_SIZE { - out[i] = cur[i].wrapping_sub(filter_paeth(a[i], b[i], c[i])); + out[i] = cur[i].wrapping_sub(filter_paeth_fpnge(a[i], b[i], c[i])); } } @@ -895,11 +807,11 @@ .zip(b_chunks.remainder()) .zip(c_chunks.remainder()) { - *out = cur.wrapping_sub(filter_paeth(a, b, c)); + *out = cur.wrapping_sub(filter_paeth_fpnge(a, b, c)); } for i in 0..bpp { - output[i] = current[i].wrapping_sub(filter_paeth(0, previous[i], 0)); + output[i] = current[i].wrapping_sub(filter_paeth_fpnge(0, previous[i], 0)); } Paeth } @@ -907,24 +819,20 @@ } pub(crate) fn filter( - method: FilterType, - adaptive: AdaptiveFilterType, + method: Filter, bpp: BytesPerPixel, previous: &[u8], current: &[u8], output: &mut [u8], -) -> FilterType { - use FilterType::*; +) -> RowFilter { + use RowFilter::*; let bpp = bpp.into_usize(); let len = current.len(); - match adaptive { - AdaptiveFilterType::NonAdaptive => { - filter_internal(method, bpp, len, previous, current, output) - } - AdaptiveFilterType::Adaptive => { + match method { + Filter::Adaptive => { let mut min_sum: u64 = u64::MAX; - let mut filter_choice = FilterType::NoFilter; + let mut filter_choice = RowFilter::NoFilter; for &filter in [Sub, Up, Avg, Paeth].iter() { filter_internal(filter, bpp, len, previous, current, output); let sum = sum_buffer(output); @@ -939,6 +847,10 @@ } filter_choice } + _ => { + let filter = RowFilter::from_method(method).unwrap(); + filter_internal(filter, bpp, len, previous, current, output) + } } } @@ -968,7 +880,7 @@ #[cfg(test)] mod test { - use super::{filter, unfilter, AdaptiveFilterType, BytesPerPixel, FilterType}; + use super::*; use core::iter; #[test] @@ -978,11 +890,10 @@ let previous: Vec<_> = iter::repeat(1).take(LEN.into()).collect(); let current: Vec<_> = (0..LEN).collect(); let expected = current.clone(); - let adaptive = AdaptiveFilterType::NonAdaptive; - let roundtrip = |kind, bpp: BytesPerPixel| { + let roundtrip = |kind: RowFilter, bpp: BytesPerPixel| { let mut output = vec![0; LEN.into()]; - filter(kind, adaptive, bpp, &previous, ¤t, &mut output); + filter(kind.into(), bpp, &previous, ¤t, &mut output); unfilter(kind, bpp, &previous, &mut output); assert_eq!( output, expected, @@ -992,11 +903,11 @@ }; let filters = [ - FilterType::NoFilter, - FilterType::Sub, - FilterType::Up, - FilterType::Avg, - FilterType::Paeth, + RowFilter::NoFilter, + RowFilter::Sub, + RowFilter::Up, + RowFilter::Avg, + RowFilter::Paeth, ]; let bpps = [ @@ -1016,17 +927,33 @@ } #[test] + #[ignore] // takes ~20s without optimizations + fn paeth_impls_are_equivalent() { + for a in 0..=255 { + for b in 0..=255 { + for c in 0..=255 { + let baseline = filter_paeth(a, b, c); + let fpnge = filter_paeth_fpnge(a, b, c); + let stbi = filter_paeth_stbi(a, b, c); + + assert_eq!(baseline, fpnge); + assert_eq!(baseline, stbi); + } + } + } + } + + #[test] fn roundtrip_ascending_previous_line() { // A multiple of 8, 6, 4, 3, 2, 1 const LEN: u8 = 240; let previous: Vec<_> = (0..LEN).collect(); let current: Vec<_> = (0..LEN).collect(); let expected = current.clone(); - let adaptive = AdaptiveFilterType::NonAdaptive; - let roundtrip = |kind, bpp: BytesPerPixel| { + let roundtrip = |kind: RowFilter, bpp: BytesPerPixel| { let mut output = vec![0; LEN.into()]; - filter(kind, adaptive, bpp, &previous, ¤t, &mut output); + filter(kind.into(), bpp, &previous, ¤t, &mut output); unfilter(kind, bpp, &previous, &mut output); assert_eq!( output, expected, @@ -1036,11 +963,11 @@ }; let filters = [ - FilterType::NoFilter, - FilterType::Sub, - FilterType::Up, - FilterType::Avg, - FilterType::Paeth, + RowFilter::NoFilter, + RowFilter::Sub, + RowFilter::Up, + RowFilter::Avg, + RowFilter::Paeth, ]; let bpps = [ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,20 +4,21 @@ //! //! ## The decoder //! -//! The most important types for decoding purposes are [`Decoder`](struct.Decoder.html) and -//! [`Reader`](struct.Reader.html). They both wrap a `std::io::Read`. -//! `Decoder` serves as a builder for `Reader`. Calling `Decoder::read_info` reads from the `Read` until the +//! The most important types for decoding purposes are [`Decoder`] and +//! [`Reader`]. They both wrap a [`std::io::Read`]. +//! `Decoder` serves as a builder for `Reader`. Calling [`Decoder::read_info`] reads from the `Read` until the //! image data is reached. //! //! ### Using the decoder //! ``` //! use std::fs::File; +//! use std::io::BufReader; //! // The decoder is a build for reader and can be used to set various decoding options //! // via `Transformations`. The default output transformation is `Transformations::IDENTITY`. -//! let decoder = png::Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap()); +//! let decoder = png::Decoder::new(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap())); //! let mut reader = decoder.read_info().unwrap(); //! // Allocate the output buffer. -//! let mut buf = vec![0; reader.output_buffer_size()]; +//! let mut buf = vec![0; reader.output_buffer_size().unwrap()]; //! // Read the next frame. An APNG might contain multiple frames. //! let info = reader.next_frame(&mut buf).unwrap(); //! // Grab the bytes of the image. @@ -58,11 +59,13 @@ //! ``` //! -#![cfg_attr(feature = "unstable", feature(portable_simd))] #![forbid(unsafe_code)] - -#[macro_use] -extern crate bitflags; +// Silence certain clippy warnings until our MSRV is higher. +// +// The #[default] attribute was stabilized in Rust 1.62.0. +#![allow(clippy::derivable_impls)] +// IIUC format args capture was stabilized in Rust 1.58.1. +#![allow(clippy::uninlined_format_args)] mod adam7; pub mod chunk; @@ -74,12 +77,17 @@ pub mod text_metadata; mod traits; -pub use crate::common::*; -pub use crate::decoder::{ - DecodeOptions, Decoded, Decoder, DecodingError, Limits, OutputInfo, Reader, StreamingDecoder, +pub use crate::adam7::{ + expand_pass as expand_interlaced_row, expand_pass_splat as splat_interlaced_row, }; + +pub use crate::adam7::{Adam7Info, Adam7Variant}; +pub use crate::common::*; +pub use crate::decoder::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder}; +pub use crate::decoder::{Decoder, InterlaceInfo, InterlacedRow, Limits, OutputInfo, Reader}; +pub use crate::decoder::{UnfilterBuf, UnfilterRegion}; pub use crate::encoder::{Encoder, EncodingError, StreamWriter, Writer}; -pub use crate::filter::{AdaptiveFilterType, FilterType}; +pub use crate::filter::Filter; #[cfg(test)] pub(crate) mod test_utils; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/test_utils.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/test_utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/test_utils.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/test_utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -26,7 +26,6 @@ /// [this /// discussion](https://github.com/image-rs/image-png/discussions/416#discussioncomment-7436871) /// for more details). -#[allow(dead_code)] // Used from `benches/decoder.rs` pub fn write_noncompressed_png(w: &mut impl Write, size: u32, idat_bytes: usize) { write_png_sig(w); write_rgba8_ihdr_with_width(w, size); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/png/src/text_metadata.rs clamav-1.4.6+dfsg/.cargo/vendor/png/src/text_metadata.rs --- clamav-1.4.3+dfsg/.cargo/vendor/png/src/text_metadata.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/png/src/text_metadata.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,9 +5,9 @@ //! chunks. There are three kinds of text chunks. //! - `tEXt`: This has a `keyword` and `text` field, and is ISO 8859-1 encoded. //! - `zTXt`: This is semantically the same as `tEXt`, i.e. it has the same fields and -//! encoding, but the `text` field is compressed before being written into the PNG file. +//! encoding, but the `text` field is compressed before being written into the PNG file. //! - `iTXt`: This chunk allows for its `text` field to be any valid UTF-8, and supports -//! compression of the text field as well. +//! compression of the text field as well. //! //! The `ISO 8859-1` encoding technically doesn't allow any control characters //! to be used, but in practice these values are encountered anyway. This can @@ -24,17 +24,13 @@ //! //! ``` //! use std::fs::File; +//! use std::io::BufReader; //! use std::iter::FromIterator; //! use std::path::PathBuf; //! //! // Opening a png file that has a zTXt chunk //! let decoder = png::Decoder::new( -//! File::open(PathBuf::from_iter([ -//! "tests", -//! "text_chunk_examples", -//! "ztxt_example.png", -//! ])) -//! .unwrap(), +//! BufReader::new(File::open("tests/text_chunk_examples/ztxt_example.png").unwrap()) //! ); //! let mut reader = decoder.read_info().unwrap(); //! // If the text chunk is before the image data frames, `reader.info()` already contains the text. @@ -145,7 +141,7 @@ /// A generalized text chunk trait pub trait EncodableTextChunk { - /// Encode text chunk as Vec to a `Write` + /// Encode text chunk as `Vec` to a `Write` fn encode(&self, w: &mut W) -> Result<(), EncodingError>; } @@ -162,7 +158,7 @@ text.iter().map(|&b| b as char).collect() } -fn encode_iso_8859_1(text: &str) -> Result, TextEncodingError> { +pub(crate) fn encode_iso_8859_1(text: &str) -> Result, TextEncodingError> { encode_iso_8859_1_iter(text).collect() } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"2fb1672300ee2dc24306b2ba3a58a3ecec6e4165154232e4ae7ab079226cbe65","CHANGELOG.md":"0bd1d2bdb4a940a0d867a782644eb007e79611be0a8d74d4ba106e83597716df","Cargo.toml":"aa9337145bd03a6e76fd42c2ee5f07c5c23ff6b2eb73cfc35c3070d76c5bacb8","Cargo.toml.orig":"eab2d53c62ed1a81b0f7d9e1cda5c2a6c15b3b3ab2a8f2a2ec8fb5c865db46c9","LICENSE-APACHE":"0218327e7a480793ffdd4eb792379a9709e5c135c7ba267f709d6f6d4d70af0a","LICENSE-MIT":"4cada0bd02ea3692eee6f16400d86c6508bbd3bafb2b65fed0419f36d4f83e8f","src/generic.rs":"4ed0101db7e24bd12472c4ebb347b200f7e0a71838abc10b223d2ae1508960c2","src/lib.rs":"45f498128e4843e920df48a285b26b87d2366983226b131e8f55535b45d03127","src/soft.rs":"12248968388d2f94dc90672bfee04fbf4fe7cba6f7237394c3607a9aa0600373","src/types.rs":"a1c9e993f85a99d1762597193d72ee8ff00c3f1116885040b4e4ecfbdedabf0a","src/x86_64/mod.rs":"89827a9d6a310adf8825961df92e1476c4da5012ee46961f26c6bc498065cf27","src/x86_64/sse2.rs":"7b5b3b8caefa7a75f00ac44a95e630b3bdd8d0d08fd7d37ab0b287939289c951"},"package":"85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "000a6cd6bbcb0b091381dc5f8fe6d6efa480b818" + }, + "path_in_vcs": "utils-simd/ppv-lite86" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.2.16] +### Added +- add [u64; 4] conversion for generic vec256, to support BLAKE on non-x86. +- impl `From` (rather than just `Into`) for conversions between `*_storage` types and arrays. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.61" +name = "ppv-lite86" +version = "0.2.21" +authors = ["The CryptoCorrosion Contributors"] +build = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Cross-platform cryptography-oriented low-level SIMD library." +readme = false +keywords = [ + "crypto", + "simd", + "x86", +] +categories = [ + "cryptography", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/cryptocorrosion/cryptocorrosion" + +[lib] +name = "ppv_lite86" +path = "src/lib.rs" + +[dependencies.zerocopy] +version = "0.8.23" +features = ["simd"] + +[features] +default = ["std"] +no_simd = [] +simd = [] +std = [] + +[badges.travis-ci] +repository = "cryptocorrosion/cryptocorrosion" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "ppv-lite86" +version = "0.2.21" +authors = ["The CryptoCorrosion Contributors"] +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Cross-platform cryptography-oriented low-level SIMD library." +repository = "https://github.com/cryptocorrosion/cryptocorrosion" +keywords = ["crypto", "simd", "x86"] +categories = ["cryptography", "no-std"] +rust-version = "1.61" + +[dependencies] +zerocopy = { version = "0.8.23", features = ["simd"] } + +[badges] +travis-ci = { repository = "cryptocorrosion/cryptocorrosion" } + +[features] +default = ["std"] +std = [] +simd = [] # deprecated +no_simd = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2019 The CryptoCorrosion Contributors + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2019 The CryptoCorrosion Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/generic.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/generic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/generic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/generic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,872 @@ +#![allow(non_camel_case_types)] + +use crate::soft::{x2, x4}; +use crate::types::*; +use core::ops::*; +use zerocopy::{FromBytes, IntoBytes}; + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(C)] + #[derive(Clone, Copy)] + pub union vec128_storage { + d: [u32; 4], + q: [u64; 2], + } +} + +impl From<[u32; 4]> for vec128_storage { + #[inline(always)] + fn from(d: [u32; 4]) -> Self { + Self { d } + } +} +impl From for [u32; 4] { + #[inline(always)] + fn from(d: vec128_storage) -> Self { + unsafe { d.d } + } +} +impl From<[u64; 2]> for vec128_storage { + #[inline(always)] + fn from(q: [u64; 2]) -> Self { + Self { q } + } +} +impl From for [u64; 2] { + #[inline(always)] + fn from(q: vec128_storage) -> Self { + unsafe { q.q } + } +} +impl Default for vec128_storage { + #[inline(always)] + fn default() -> Self { + Self { q: [0, 0] } + } +} +impl Eq for vec128_storage {} +impl PartialEq for vec128_storage { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { self.q == rhs.q } + } +} +#[derive(Clone, Copy, PartialEq, Eq, Default)] +pub struct vec256_storage { + v128: [vec128_storage; 2], +} +impl vec256_storage { + #[inline(always)] + pub fn new128(v128: [vec128_storage; 2]) -> Self { + Self { v128 } + } + #[inline(always)] + pub fn split128(self) -> [vec128_storage; 2] { + self.v128 + } +} +impl From for [u64; 4] { + #[inline(always)] + fn from(q: vec256_storage) -> Self { + let [a, b]: [u64; 2] = q.v128[0].into(); + let [c, d]: [u64; 2] = q.v128[1].into(); + [a, b, c, d] + } +} +impl From<[u64; 4]> for vec256_storage { + #[inline(always)] + fn from([a, b, c, d]: [u64; 4]) -> Self { + Self { + v128: [[a, b].into(), [c, d].into()], + } + } +} +#[derive(Clone, Copy, PartialEq, Eq, Default)] +pub struct vec512_storage { + v128: [vec128_storage; 4], +} +impl vec512_storage { + #[inline(always)] + pub fn new128(v128: [vec128_storage; 4]) -> Self { + Self { v128 } + } + #[inline(always)] + pub fn split128(self) -> [vec128_storage; 4] { + self.v128 + } +} + +#[inline(always)] +fn dmap(t: T, f: F) -> T +where + T: Store + Into, + F: Fn(u32) -> u32, +{ + let t: vec128_storage = t.into(); + let d = unsafe { t.d }; + let d = vec128_storage { + d: [f(d[0]), f(d[1]), f(d[2]), f(d[3])], + }; + unsafe { T::unpack(d) } +} + +fn dmap2(a: T, b: T, f: F) -> T +where + T: Store + Into, + F: Fn(u32, u32) -> u32, +{ + let a: vec128_storage = a.into(); + let b: vec128_storage = b.into(); + let ao = unsafe { a.d }; + let bo = unsafe { b.d }; + let d = vec128_storage { + d: [ + f(ao[0], bo[0]), + f(ao[1], bo[1]), + f(ao[2], bo[2]), + f(ao[3], bo[3]), + ], + }; + unsafe { T::unpack(d) } +} + +#[inline(always)] +fn qmap(t: T, f: F) -> T +where + T: Store + Into, + F: Fn(u64) -> u64, +{ + let t: vec128_storage = t.into(); + let q = unsafe { t.q }; + let q = vec128_storage { + q: [f(q[0]), f(q[1])], + }; + unsafe { T::unpack(q) } +} + +#[inline(always)] +fn qmap2(a: T, b: T, f: F) -> T +where + T: Store + Into, + F: Fn(u64, u64) -> u64, +{ + let a: vec128_storage = a.into(); + let b: vec128_storage = b.into(); + let ao = unsafe { a.q }; + let bo = unsafe { b.q }; + let q = vec128_storage { + q: [f(ao[0], bo[0]), f(ao[1], bo[1])], + }; + unsafe { T::unpack(q) } +} + +#[inline(always)] +fn o_of_q(q: [u64; 2]) -> u128 { + u128::from(q[0]) | (u128::from(q[1]) << 64) +} + +#[inline(always)] +fn q_of_o(o: u128) -> [u64; 2] { + [o as u64, (o >> 64) as u64] +} + +#[inline(always)] +fn omap(a: T, f: F) -> T +where + T: Store + Into, + F: Fn(u128) -> u128, +{ + let a: vec128_storage = a.into(); + let ao = o_of_q(unsafe { a.q }); + let o = vec128_storage { q: q_of_o(f(ao)) }; + unsafe { T::unpack(o) } +} + +#[inline(always)] +fn omap2(a: T, b: T, f: F) -> T +where + T: Store + Into, + F: Fn(u128, u128) -> u128, +{ + let a: vec128_storage = a.into(); + let b: vec128_storage = b.into(); + let ao = o_of_q(unsafe { a.q }); + let bo = o_of_q(unsafe { b.q }); + let o = vec128_storage { + q: q_of_o(f(ao, bo)), + }; + unsafe { T::unpack(o) } +} + +impl RotateEachWord128 for u128x1_generic {} +impl BitOps128 for u128x1_generic {} +impl BitOps64 for u128x1_generic {} +impl BitOps64 for u64x2_generic {} +impl BitOps32 for u128x1_generic {} +impl BitOps32 for u64x2_generic {} +impl BitOps32 for u32x4_generic {} +impl BitOps0 for u128x1_generic {} +impl BitOps0 for u64x2_generic {} +impl BitOps0 for u32x4_generic {} + +macro_rules! impl_bitops { + ($vec:ident) => { + impl Not for $vec { + type Output = Self; + #[inline(always)] + fn not(self) -> Self::Output { + omap(self, |x| !x) + } + } + impl BitAnd for $vec { + type Output = Self; + #[inline(always)] + fn bitand(self, rhs: Self) -> Self::Output { + omap2(self, rhs, |x, y| x & y) + } + } + impl BitOr for $vec { + type Output = Self; + #[inline(always)] + fn bitor(self, rhs: Self) -> Self::Output { + omap2(self, rhs, |x, y| x | y) + } + } + impl BitXor for $vec { + type Output = Self; + #[inline(always)] + fn bitxor(self, rhs: Self) -> Self::Output { + omap2(self, rhs, |x, y| x ^ y) + } + } + impl AndNot for $vec { + type Output = Self; + #[inline(always)] + fn andnot(self, rhs: Self) -> Self::Output { + omap2(self, rhs, |x, y| !x & y) + } + } + impl BitAndAssign for $vec { + #[inline(always)] + fn bitand_assign(&mut self, rhs: Self) { + *self = *self & rhs + } + } + impl BitOrAssign for $vec { + #[inline(always)] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs + } + } + impl BitXorAssign for $vec { + #[inline(always)] + fn bitxor_assign(&mut self, rhs: Self) { + *self = *self ^ rhs + } + } + + impl Swap64 for $vec { + #[inline(always)] + fn swap1(self) -> Self { + qmap(self, |x| { + ((x & 0x5555555555555555) << 1) | ((x & 0xaaaaaaaaaaaaaaaa) >> 1) + }) + } + #[inline(always)] + fn swap2(self) -> Self { + qmap(self, |x| { + ((x & 0x3333333333333333) << 2) | ((x & 0xcccccccccccccccc) >> 2) + }) + } + #[inline(always)] + fn swap4(self) -> Self { + qmap(self, |x| { + ((x & 0x0f0f0f0f0f0f0f0f) << 4) | ((x & 0xf0f0f0f0f0f0f0f0) >> 4) + }) + } + #[inline(always)] + fn swap8(self) -> Self { + qmap(self, |x| { + ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8) + }) + } + #[inline(always)] + fn swap16(self) -> Self { + dmap(self, |x| x.rotate_left(16)) + } + #[inline(always)] + fn swap32(self) -> Self { + qmap(self, |x| x.rotate_left(32)) + } + #[inline(always)] + fn swap64(self) -> Self { + omap(self, |x| (x << 64) | (x >> 64)) + } + } + }; +} +impl_bitops!(u32x4_generic); +impl_bitops!(u64x2_generic); +impl_bitops!(u128x1_generic); + +impl RotateEachWord32 for u32x4_generic { + #[inline(always)] + fn rotate_each_word_right7(self) -> Self { + dmap(self, |x| x.rotate_right(7)) + } + #[inline(always)] + fn rotate_each_word_right8(self) -> Self { + dmap(self, |x| x.rotate_right(8)) + } + #[inline(always)] + fn rotate_each_word_right11(self) -> Self { + dmap(self, |x| x.rotate_right(11)) + } + #[inline(always)] + fn rotate_each_word_right12(self) -> Self { + dmap(self, |x| x.rotate_right(12)) + } + #[inline(always)] + fn rotate_each_word_right16(self) -> Self { + dmap(self, |x| x.rotate_right(16)) + } + #[inline(always)] + fn rotate_each_word_right20(self) -> Self { + dmap(self, |x| x.rotate_right(20)) + } + #[inline(always)] + fn rotate_each_word_right24(self) -> Self { + dmap(self, |x| x.rotate_right(24)) + } + #[inline(always)] + fn rotate_each_word_right25(self) -> Self { + dmap(self, |x| x.rotate_right(25)) + } +} + +impl RotateEachWord32 for u64x2_generic { + #[inline(always)] + fn rotate_each_word_right7(self) -> Self { + qmap(self, |x| x.rotate_right(7)) + } + #[inline(always)] + fn rotate_each_word_right8(self) -> Self { + qmap(self, |x| x.rotate_right(8)) + } + #[inline(always)] + fn rotate_each_word_right11(self) -> Self { + qmap(self, |x| x.rotate_right(11)) + } + #[inline(always)] + fn rotate_each_word_right12(self) -> Self { + qmap(self, |x| x.rotate_right(12)) + } + #[inline(always)] + fn rotate_each_word_right16(self) -> Self { + qmap(self, |x| x.rotate_right(16)) + } + #[inline(always)] + fn rotate_each_word_right20(self) -> Self { + qmap(self, |x| x.rotate_right(20)) + } + #[inline(always)] + fn rotate_each_word_right24(self) -> Self { + qmap(self, |x| x.rotate_right(24)) + } + #[inline(always)] + fn rotate_each_word_right25(self) -> Self { + qmap(self, |x| x.rotate_right(25)) + } +} +impl RotateEachWord64 for u64x2_generic { + #[inline(always)] + fn rotate_each_word_right32(self) -> Self { + qmap(self, |x| x.rotate_right(32)) + } +} + +// workaround for koute/cargo-web#52 (u128::rotate_* broken with cargo web) +#[inline(always)] +fn rotate_u128_right(x: u128, i: u32) -> u128 { + (x >> i) | (x << (128 - i)) +} +#[test] +fn test_rotate_u128() { + const X: u128 = 0x0001_0203_0405_0607_0809_0a0b_0c0d_0e0f; + assert_eq!(rotate_u128_right(X, 17), X.rotate_right(17)); +} + +impl RotateEachWord32 for u128x1_generic { + #[inline(always)] + fn rotate_each_word_right7(self) -> Self { + Self([rotate_u128_right(self.0[0], 7)]) + } + #[inline(always)] + fn rotate_each_word_right8(self) -> Self { + Self([rotate_u128_right(self.0[0], 8)]) + } + #[inline(always)] + fn rotate_each_word_right11(self) -> Self { + Self([rotate_u128_right(self.0[0], 11)]) + } + #[inline(always)] + fn rotate_each_word_right12(self) -> Self { + Self([rotate_u128_right(self.0[0], 12)]) + } + #[inline(always)] + fn rotate_each_word_right16(self) -> Self { + Self([rotate_u128_right(self.0[0], 16)]) + } + #[inline(always)] + fn rotate_each_word_right20(self) -> Self { + Self([rotate_u128_right(self.0[0], 20)]) + } + #[inline(always)] + fn rotate_each_word_right24(self) -> Self { + Self([rotate_u128_right(self.0[0], 24)]) + } + #[inline(always)] + fn rotate_each_word_right25(self) -> Self { + Self([rotate_u128_right(self.0[0], 25)]) + } +} +impl RotateEachWord64 for u128x1_generic { + #[inline(always)] + fn rotate_each_word_right32(self) -> Self { + Self([rotate_u128_right(self.0[0], 32)]) + } +} + +#[derive(Copy, Clone)] +pub struct GenericMachine; +impl Machine for GenericMachine { + type u32x4 = u32x4_generic; + type u64x2 = u64x2_generic; + type u128x1 = u128x1_generic; + type u32x4x2 = u32x4x2_generic; + type u64x2x2 = u64x2x2_generic; + type u64x4 = u64x4_generic; + type u128x2 = u128x2_generic; + type u32x4x4 = u32x4x4_generic; + type u64x2x4 = u64x2x4_generic; + type u128x4 = u128x4_generic; + #[inline(always)] + unsafe fn instance() -> Self { + Self + } +} + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u32x4_generic([u32; 4]); +} + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u64x2_generic([u64; 2]); +} + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u128x1_generic([u128; 1]); +} + +impl From for vec128_storage { + #[inline(always)] + fn from(d: u32x4_generic) -> Self { + Self { d: d.0 } + } +} +impl From for vec128_storage { + #[inline(always)] + fn from(q: u64x2_generic) -> Self { + Self { q: q.0 } + } +} +impl From for vec128_storage { + #[inline(always)] + fn from(o: u128x1_generic) -> Self { + Self { q: q_of_o(o.0[0]) } + } +} + +impl Store for u32x4_generic { + #[inline(always)] + unsafe fn unpack(s: vec128_storage) -> Self { + Self(s.d) + } +} +impl Store for u64x2_generic { + #[inline(always)] + unsafe fn unpack(s: vec128_storage) -> Self { + Self(s.q) + } +} +impl Store for u128x1_generic { + #[inline(always)] + unsafe fn unpack(s: vec128_storage) -> Self { + Self([o_of_q(s.q); 1]) + } +} + +impl ArithOps for u32x4_generic {} +impl ArithOps for u64x2_generic {} +impl ArithOps for u128x1_generic {} + +impl Add for u32x4_generic { + type Output = Self; + #[inline(always)] + fn add(self, rhs: Self) -> Self::Output { + dmap2(self, rhs, |x, y| x.wrapping_add(y)) + } +} +impl Add for u64x2_generic { + type Output = Self; + #[inline(always)] + fn add(self, rhs: Self) -> Self::Output { + qmap2(self, rhs, |x, y| x.wrapping_add(y)) + } +} +impl Add for u128x1_generic { + type Output = Self; + #[inline(always)] + fn add(self, rhs: Self) -> Self::Output { + omap2(self, rhs, |x, y| x.wrapping_add(y)) + } +} +impl AddAssign for u32x4_generic { + #[inline(always)] + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} +impl AddAssign for u64x2_generic { + #[inline(always)] + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} +impl AddAssign for u128x1_generic { + #[inline(always)] + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} +impl BSwap for u32x4_generic { + #[inline(always)] + fn bswap(self) -> Self { + dmap(self, |x| x.swap_bytes()) + } +} +impl BSwap for u64x2_generic { + #[inline(always)] + fn bswap(self) -> Self { + qmap(self, |x| x.swap_bytes()) + } +} +impl BSwap for u128x1_generic { + #[inline(always)] + fn bswap(self) -> Self { + omap(self, |x| x.swap_bytes()) + } +} +impl StoreBytes for u32x4_generic { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + let x = u32x4_generic::read_from_bytes(input).unwrap(); + dmap(x, |x| x.to_le()) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + let x = u32x4_generic::read_from_bytes(input).unwrap(); + dmap(x, |x| x.to_be()) + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + let x = dmap(self, |x| x.to_le()); + x.write_to(out).unwrap(); + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + let x = dmap(self, |x| x.to_be()); + x.write_to(out).unwrap(); + } +} +impl StoreBytes for u64x2_generic { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + let x = u64x2_generic::read_from_bytes(input).unwrap(); + qmap(x, |x| x.to_le()) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + let x = u64x2_generic::read_from_bytes(input).unwrap(); + qmap(x, |x| x.to_be()) + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + let x = qmap(self, |x| x.to_le()); + x.write_to(out).unwrap(); + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + let x = qmap(self, |x| x.to_be()); + x.write_to(out).unwrap(); + } +} + +#[derive(Copy, Clone)] +pub struct G0; +#[derive(Copy, Clone)] +pub struct G1; +pub type u32x4x2_generic = x2; +pub type u64x2x2_generic = x2; +pub type u64x4_generic = x2; +pub type u128x2_generic = x2; +pub type u32x4x4_generic = x4; +pub type u64x2x4_generic = x4; +pub type u128x4_generic = x4; + +impl Vector<[u32; 16]> for u32x4x4_generic { + fn to_scalars(self) -> [u32; 16] { + let [a, b, c, d] = self.0; + let a = a.0; + let b = b.0; + let c = c.0; + let d = d.0; + [ + a[0], a[1], a[2], a[3], // + b[0], b[1], b[2], b[3], // + c[0], c[1], c[2], c[3], // + d[0], d[1], d[2], d[3], // + ] + } +} + +impl MultiLane<[u32; 4]> for u32x4_generic { + #[inline(always)] + fn to_lanes(self) -> [u32; 4] { + self.0 + } + #[inline(always)] + fn from_lanes(xs: [u32; 4]) -> Self { + Self(xs) + } +} +impl MultiLane<[u64; 2]> for u64x2_generic { + #[inline(always)] + fn to_lanes(self) -> [u64; 2] { + self.0 + } + #[inline(always)] + fn from_lanes(xs: [u64; 2]) -> Self { + Self(xs) + } +} +impl MultiLane<[u64; 4]> for u64x4_generic { + #[inline(always)] + fn to_lanes(self) -> [u64; 4] { + let (a, b) = (self.0[0].to_lanes(), self.0[1].to_lanes()); + [a[0], a[1], b[0], b[1]] + } + #[inline(always)] + fn from_lanes(xs: [u64; 4]) -> Self { + let (a, b) = ( + u64x2_generic::from_lanes([xs[0], xs[1]]), + u64x2_generic::from_lanes([xs[2], xs[3]]), + ); + x2::new([a, b]) + } +} +impl MultiLane<[u128; 1]> for u128x1_generic { + #[inline(always)] + fn to_lanes(self) -> [u128; 1] { + self.0 + } + #[inline(always)] + fn from_lanes(xs: [u128; 1]) -> Self { + Self(xs) + } +} +impl Vec4 for u32x4_generic { + #[inline(always)] + fn extract(self, i: u32) -> u32 { + self.0[i as usize] + } + #[inline(always)] + fn insert(mut self, v: u32, i: u32) -> Self { + self.0[i as usize] = v; + self + } +} +impl Vec4 for u64x4_generic { + #[inline(always)] + fn extract(self, i: u32) -> u64 { + let d: [u64; 4] = self.to_lanes(); + d[i as usize] + } + #[inline(always)] + fn insert(self, v: u64, i: u32) -> Self { + self.0[(i / 2) as usize].insert(v, i % 2); + self + } +} +impl Vec2 for u64x2_generic { + #[inline(always)] + fn extract(self, i: u32) -> u64 { + self.0[i as usize] + } + #[inline(always)] + fn insert(mut self, v: u64, i: u32) -> Self { + self.0[i as usize] = v; + self + } +} + +impl Words4 for u32x4_generic { + #[inline(always)] + fn shuffle2301(self) -> Self { + self.swap64() + } + #[inline(always)] + fn shuffle1230(self) -> Self { + let x = self.0; + Self([x[3], x[0], x[1], x[2]]) + } + #[inline(always)] + fn shuffle3012(self) -> Self { + let x = self.0; + Self([x[1], x[2], x[3], x[0]]) + } +} +impl LaneWords4 for u32x4_generic { + #[inline(always)] + fn shuffle_lane_words2301(self) -> Self { + self.shuffle2301() + } + #[inline(always)] + fn shuffle_lane_words1230(self) -> Self { + self.shuffle1230() + } + #[inline(always)] + fn shuffle_lane_words3012(self) -> Self { + self.shuffle3012() + } +} + +impl Words4 for u64x4_generic { + #[inline(always)] + fn shuffle2301(self) -> Self { + x2::new([self.0[1], self.0[0]]) + } + #[inline(always)] + fn shuffle1230(self) -> Self { + unimplemented!() + } + #[inline(always)] + fn shuffle3012(self) -> Self { + unimplemented!() + } +} + +impl u32x4 for u32x4_generic {} +impl u64x2 for u64x2_generic {} +impl u128x1 for u128x1_generic {} +impl u32x4x2 for u32x4x2_generic {} +impl u64x2x2 for u64x2x2_generic {} +impl u64x4 for u64x4_generic {} +impl u128x2 for u128x2_generic {} +impl u32x4x4 for u32x4x4_generic {} +impl u64x2x4 for u64x2x4_generic {} +impl u128x4 for u128x4_generic {} + +#[macro_export] +macro_rules! dispatch { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + let $mach = unsafe { $crate::generic::GenericMachine::instance() }; + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + fn_impl($mach, $($arg),*) + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt $(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} +#[macro_export] +macro_rules! dispatch_light128 { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + let $mach = unsafe { $crate::generic::GenericMachine::instance() }; + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + fn_impl($mach, $($arg),*) + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt $(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} +#[macro_export] +macro_rules! dispatch_light256 { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + let $mach = unsafe { $crate::generic::GenericMachine::instance() }; + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + fn_impl($mach, $($arg),*) + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt $(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} +#[macro_export] +macro_rules! dispatch_light512 { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + let $mach = unsafe { $crate::generic::GenericMachine::instance() }; + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + fn_impl($mach, $($arg),*) + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt $(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_bswap32() { + let xs = [0x0f0e_0d0c, 0x0b0a_0908, 0x0706_0504, 0x0302_0100]; + let ys = [0x0c0d_0e0f, 0x0809_0a0b, 0x0405_0607, 0x0001_0203]; + + let m = unsafe { GenericMachine::instance() }; + + let x: ::u32x4 = m.vec(xs); + let x = x.bswap(); + + let y = m.vec(ys); + assert_eq!(x, y); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +#![no_std] + +// Design: +// - safety: safe creation of any machine type is done only by instance methods of a +// Machine (which is a ZST + Copy type), which can only by created unsafely or safely +// through feature detection (e.g. fn AVX2::try_get() -> Option). + +mod soft; +mod types; +pub use self::types::*; + +#[cfg(all( + target_arch = "x86_64", + target_feature = "sse2", + not(feature = "no_simd"), + not(miri) +))] +pub mod x86_64; +#[cfg(all( + target_arch = "x86_64", + target_feature = "sse2", + not(feature = "no_simd"), + not(miri) +))] +use self::x86_64 as arch; + +#[cfg(any( + feature = "no_simd", + miri, + not(target_arch = "x86_64"), + all(target_arch = "x86_64", not(target_feature = "sse2")) +))] +pub mod generic; +#[cfg(any( + feature = "no_simd", + miri, + not(target_arch = "x86_64"), + all(target_arch = "x86_64", not(target_feature = "sse2")) +))] +use self::generic as arch; + +pub use self::arch::{vec128_storage, vec256_storage, vec512_storage}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/soft.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/soft.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/soft.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/soft.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,480 @@ +//! Implement 256- and 512- bit in terms of 128-bit, for machines without native wide SIMD. + +use crate::types::*; +use crate::{vec128_storage, vec256_storage, vec512_storage}; +use core::marker::PhantomData; +use core::ops::*; + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Default)] + #[allow(non_camel_case_types)] + pub struct x2(pub [W; 2], PhantomData); +} + +impl x2 { + #[inline(always)] + pub fn new(xs: [W; 2]) -> Self { + x2(xs, PhantomData) + } +} +macro_rules! fwd_binop_x2 { + ($trait:ident, $fn:ident) => { + impl $trait for x2 { + type Output = x2; + #[inline(always)] + fn $fn(self, rhs: Self) -> Self::Output { + x2::new([self.0[0].$fn(rhs.0[0]), self.0[1].$fn(rhs.0[1])]) + } + } + }; +} +macro_rules! fwd_binop_assign_x2 { + ($trait:ident, $fn_assign:ident) => { + impl $trait for x2 { + #[inline(always)] + fn $fn_assign(&mut self, rhs: Self) { + (self.0[0]).$fn_assign(rhs.0[0]); + (self.0[1]).$fn_assign(rhs.0[1]); + } + } + }; +} +macro_rules! fwd_unop_x2 { + ($fn:ident) => { + #[inline(always)] + fn $fn(self) -> Self { + x2::new([self.0[0].$fn(), self.0[1].$fn()]) + } + }; +} +impl RotateEachWord32 for x2 +where + W: Copy + RotateEachWord32, +{ + fwd_unop_x2!(rotate_each_word_right7); + fwd_unop_x2!(rotate_each_word_right8); + fwd_unop_x2!(rotate_each_word_right11); + fwd_unop_x2!(rotate_each_word_right12); + fwd_unop_x2!(rotate_each_word_right16); + fwd_unop_x2!(rotate_each_word_right20); + fwd_unop_x2!(rotate_each_word_right24); + fwd_unop_x2!(rotate_each_word_right25); +} +impl RotateEachWord64 for x2 +where + W: Copy + RotateEachWord64, +{ + fwd_unop_x2!(rotate_each_word_right32); +} +impl RotateEachWord128 for x2 where W: RotateEachWord128 {} +impl BitOps0 for x2 +where + W: BitOps0, + G: Copy, +{ +} +impl BitOps32 for x2 +where + W: BitOps32 + BitOps0, + G: Copy, +{ +} +impl BitOps64 for x2 +where + W: BitOps64 + BitOps0, + G: Copy, +{ +} +impl BitOps128 for x2 +where + W: BitOps128 + BitOps0, + G: Copy, +{ +} +fwd_binop_x2!(BitAnd, bitand); +fwd_binop_x2!(BitOr, bitor); +fwd_binop_x2!(BitXor, bitxor); +fwd_binop_x2!(AndNot, andnot); +fwd_binop_assign_x2!(BitAndAssign, bitand_assign); +fwd_binop_assign_x2!(BitOrAssign, bitor_assign); +fwd_binop_assign_x2!(BitXorAssign, bitxor_assign); +impl ArithOps for x2 +where + W: ArithOps, + G: Copy, +{ +} +fwd_binop_x2!(Add, add); +fwd_binop_assign_x2!(AddAssign, add_assign); +impl Not for x2 { + type Output = x2; + #[inline(always)] + fn not(self) -> Self::Output { + x2::new([self.0[0].not(), self.0[1].not()]) + } +} +impl UnsafeFrom<[W; 2]> for x2 { + #[inline(always)] + unsafe fn unsafe_from(xs: [W; 2]) -> Self { + x2::new(xs) + } +} +impl Vec2 for x2 { + #[inline(always)] + fn extract(self, i: u32) -> W { + self.0[i as usize] + } + #[inline(always)] + fn insert(mut self, w: W, i: u32) -> Self { + self.0[i as usize] = w; + self + } +} +impl, G> Store for x2 { + #[inline(always)] + unsafe fn unpack(p: vec256_storage) -> Self { + let p = p.split128(); + x2::new([W::unpack(p[0]), W::unpack(p[1])]) + } +} +impl From> for vec256_storage +where + W: Copy, + vec128_storage: From, +{ + #[inline(always)] + fn from(x: x2) -> Self { + vec256_storage::new128([x.0[0].into(), x.0[1].into()]) + } +} +impl Swap64 for x2 +where + W: Swap64 + Copy, +{ + fwd_unop_x2!(swap1); + fwd_unop_x2!(swap2); + fwd_unop_x2!(swap4); + fwd_unop_x2!(swap8); + fwd_unop_x2!(swap16); + fwd_unop_x2!(swap32); + fwd_unop_x2!(swap64); +} +impl MultiLane<[W; 2]> for x2 { + #[inline(always)] + fn to_lanes(self) -> [W; 2] { + self.0 + } + #[inline(always)] + fn from_lanes(lanes: [W; 2]) -> Self { + x2::new(lanes) + } +} +impl BSwap for x2 { + #[inline(always)] + fn bswap(self) -> Self { + x2::new([self.0[0].bswap(), self.0[1].bswap()]) + } +} +impl StoreBytes for x2 { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + let input = input.split_at(input.len() / 2); + x2::new([W::unsafe_read_le(input.0), W::unsafe_read_le(input.1)]) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + let input = input.split_at(input.len() / 2); + x2::new([W::unsafe_read_be(input.0), W::unsafe_read_be(input.1)]) + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + let out = out.split_at_mut(out.len() / 2); + self.0[0].write_le(out.0); + self.0[1].write_le(out.1); + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + let out = out.split_at_mut(out.len() / 2); + self.0[0].write_be(out.0); + self.0[1].write_be(out.1); + } +} +impl LaneWords4 for x2 { + #[inline(always)] + fn shuffle_lane_words2301(self) -> Self { + Self::new([ + self.0[0].shuffle_lane_words2301(), + self.0[1].shuffle_lane_words2301(), + ]) + } + #[inline(always)] + fn shuffle_lane_words1230(self) -> Self { + Self::new([ + self.0[0].shuffle_lane_words1230(), + self.0[1].shuffle_lane_words1230(), + ]) + } + #[inline(always)] + fn shuffle_lane_words3012(self) -> Self { + Self::new([ + self.0[0].shuffle_lane_words3012(), + self.0[1].shuffle_lane_words3012(), + ]) + } +} + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Default)] + #[allow(non_camel_case_types)] + pub struct x4(pub [W; 4]); +} + +impl x4 { + #[inline(always)] + pub fn new(xs: [W; 4]) -> Self { + x4(xs) + } +} +macro_rules! fwd_binop_x4 { + ($trait:ident, $fn:ident) => { + impl $trait for x4 { + type Output = x4; + #[inline(always)] + fn $fn(self, rhs: Self) -> Self::Output { + x4([ + self.0[0].$fn(rhs.0[0]), + self.0[1].$fn(rhs.0[1]), + self.0[2].$fn(rhs.0[2]), + self.0[3].$fn(rhs.0[3]), + ]) + } + } + }; +} +macro_rules! fwd_binop_assign_x4 { + ($trait:ident, $fn_assign:ident) => { + impl $trait for x4 { + #[inline(always)] + fn $fn_assign(&mut self, rhs: Self) { + self.0[0].$fn_assign(rhs.0[0]); + self.0[1].$fn_assign(rhs.0[1]); + self.0[2].$fn_assign(rhs.0[2]); + self.0[3].$fn_assign(rhs.0[3]); + } + } + }; +} +macro_rules! fwd_unop_x4 { + ($fn:ident) => { + #[inline(always)] + fn $fn(self) -> Self { + x4([ + self.0[0].$fn(), + self.0[1].$fn(), + self.0[2].$fn(), + self.0[3].$fn(), + ]) + } + }; +} +impl RotateEachWord32 for x4 +where + W: Copy + RotateEachWord32, +{ + fwd_unop_x4!(rotate_each_word_right7); + fwd_unop_x4!(rotate_each_word_right8); + fwd_unop_x4!(rotate_each_word_right11); + fwd_unop_x4!(rotate_each_word_right12); + fwd_unop_x4!(rotate_each_word_right16); + fwd_unop_x4!(rotate_each_word_right20); + fwd_unop_x4!(rotate_each_word_right24); + fwd_unop_x4!(rotate_each_word_right25); +} +impl RotateEachWord64 for x4 +where + W: Copy + RotateEachWord64, +{ + fwd_unop_x4!(rotate_each_word_right32); +} +impl RotateEachWord128 for x4 where W: RotateEachWord128 {} +impl BitOps0 for x4 where W: BitOps0 {} +impl BitOps32 for x4 where W: BitOps32 + BitOps0 {} +impl BitOps64 for x4 where W: BitOps64 + BitOps0 {} +impl BitOps128 for x4 where W: BitOps128 + BitOps0 {} +fwd_binop_x4!(BitAnd, bitand); +fwd_binop_x4!(BitOr, bitor); +fwd_binop_x4!(BitXor, bitxor); +fwd_binop_x4!(AndNot, andnot); +fwd_binop_assign_x4!(BitAndAssign, bitand_assign); +fwd_binop_assign_x4!(BitOrAssign, bitor_assign); +fwd_binop_assign_x4!(BitXorAssign, bitxor_assign); +impl ArithOps for x4 where W: ArithOps {} +fwd_binop_x4!(Add, add); +fwd_binop_assign_x4!(AddAssign, add_assign); +impl Not for x4 { + type Output = x4; + #[inline(always)] + fn not(self) -> Self::Output { + x4([ + self.0[0].not(), + self.0[1].not(), + self.0[2].not(), + self.0[3].not(), + ]) + } +} +impl UnsafeFrom<[W; 4]> for x4 { + #[inline(always)] + unsafe fn unsafe_from(xs: [W; 4]) -> Self { + x4(xs) + } +} +impl Vec4 for x4 { + #[inline(always)] + fn extract(self, i: u32) -> W { + self.0[i as usize] + } + #[inline(always)] + fn insert(mut self, w: W, i: u32) -> Self { + self.0[i as usize] = w; + self + } +} +impl Vec4Ext for x4 { + #[inline(always)] + fn transpose4(a: Self, b: Self, c: Self, d: Self) -> (Self, Self, Self, Self) + where + Self: Sized, + { + ( + x4([a.0[0], b.0[0], c.0[0], d.0[0]]), + x4([a.0[1], b.0[1], c.0[1], d.0[1]]), + x4([a.0[2], b.0[2], c.0[2], d.0[2]]), + x4([a.0[3], b.0[3], c.0[3], d.0[3]]), + ) + } +} +impl> Store for x4 { + #[inline(always)] + unsafe fn unpack(p: vec512_storage) -> Self { + let p = p.split128(); + x4([ + W::unpack(p[0]), + W::unpack(p[1]), + W::unpack(p[2]), + W::unpack(p[3]), + ]) + } +} +impl From> for vec512_storage +where + W: Copy, + vec128_storage: From, +{ + #[inline(always)] + fn from(x: x4) -> Self { + vec512_storage::new128([x.0[0].into(), x.0[1].into(), x.0[2].into(), x.0[3].into()]) + } +} +impl Swap64 for x4 +where + W: Swap64 + Copy, +{ + fwd_unop_x4!(swap1); + fwd_unop_x4!(swap2); + fwd_unop_x4!(swap4); + fwd_unop_x4!(swap8); + fwd_unop_x4!(swap16); + fwd_unop_x4!(swap32); + fwd_unop_x4!(swap64); +} +impl MultiLane<[W; 4]> for x4 { + #[inline(always)] + fn to_lanes(self) -> [W; 4] { + self.0 + } + #[inline(always)] + fn from_lanes(lanes: [W; 4]) -> Self { + x4(lanes) + } +} +impl BSwap for x4 { + #[inline(always)] + fn bswap(self) -> Self { + x4([ + self.0[0].bswap(), + self.0[1].bswap(), + self.0[2].bswap(), + self.0[3].bswap(), + ]) + } +} +impl StoreBytes for x4 { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + let n = input.len() / 4; + x4([ + W::unsafe_read_le(&input[..n]), + W::unsafe_read_le(&input[n..n * 2]), + W::unsafe_read_le(&input[n * 2..n * 3]), + W::unsafe_read_le(&input[n * 3..]), + ]) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + let n = input.len() / 4; + x4([ + W::unsafe_read_be(&input[..n]), + W::unsafe_read_be(&input[n..n * 2]), + W::unsafe_read_be(&input[n * 2..n * 3]), + W::unsafe_read_be(&input[n * 3..]), + ]) + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + let n = out.len() / 4; + self.0[0].write_le(&mut out[..n]); + self.0[1].write_le(&mut out[n..n * 2]); + self.0[2].write_le(&mut out[n * 2..n * 3]); + self.0[3].write_le(&mut out[n * 3..]); + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + let n = out.len() / 4; + self.0[0].write_be(&mut out[..n]); + self.0[1].write_be(&mut out[n..n * 2]); + self.0[2].write_be(&mut out[n * 2..n * 3]); + self.0[3].write_be(&mut out[n * 3..]); + } +} +impl LaneWords4 for x4 { + #[inline(always)] + fn shuffle_lane_words2301(self) -> Self { + x4([ + self.0[0].shuffle_lane_words2301(), + self.0[1].shuffle_lane_words2301(), + self.0[2].shuffle_lane_words2301(), + self.0[3].shuffle_lane_words2301(), + ]) + } + #[inline(always)] + fn shuffle_lane_words1230(self) -> Self { + x4([ + self.0[0].shuffle_lane_words1230(), + self.0[1].shuffle_lane_words1230(), + self.0[2].shuffle_lane_words1230(), + self.0[3].shuffle_lane_words1230(), + ]) + } + #[inline(always)] + fn shuffle_lane_words3012(self) -> Self { + x4([ + self.0[0].shuffle_lane_words3012(), + self.0[1].shuffle_lane_words3012(), + self.0[2].shuffle_lane_words3012(), + self.0[3].shuffle_lane_words3012(), + ]) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/types.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/types.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/types.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/types.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,298 @@ +#![allow(non_camel_case_types)] +use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign, Not}; + +pub trait AndNot { + type Output; + fn andnot(self, rhs: Self) -> Self::Output; +} +pub trait BSwap { + fn bswap(self) -> Self; +} +/// Ops that depend on word size +pub trait ArithOps: Add + AddAssign + Sized + Copy + Clone + BSwap {} +/// Ops that are independent of word size and endian +pub trait BitOps0: + BitAnd + + BitOr + + BitXor + + BitXorAssign + + Not + + AndNot + + Sized + + Copy + + Clone +{ +} + +pub trait BitOps32: BitOps0 + RotateEachWord32 {} +pub trait BitOps64: BitOps32 + RotateEachWord64 {} +pub trait BitOps128: BitOps64 + RotateEachWord128 {} + +pub trait RotateEachWord32 { + fn rotate_each_word_right7(self) -> Self; + fn rotate_each_word_right8(self) -> Self; + fn rotate_each_word_right11(self) -> Self; + fn rotate_each_word_right12(self) -> Self; + fn rotate_each_word_right16(self) -> Self; + fn rotate_each_word_right20(self) -> Self; + fn rotate_each_word_right24(self) -> Self; + fn rotate_each_word_right25(self) -> Self; +} + +pub trait RotateEachWord64 { + fn rotate_each_word_right32(self) -> Self; +} + +pub trait RotateEachWord128 {} + +// Vector type naming scheme: +// uN[xP]xL +// Unsigned; N-bit words * P bits per lane * L lanes +// +// A lane is always 128-bits, chosen because common SIMD architectures treat 128-bit units of +// wide vectors specially (supporting e.g. intra-lane shuffles), and tend to have limited and +// slow inter-lane operations. + +use crate::arch::{vec128_storage, vec256_storage, vec512_storage}; + +#[allow(clippy::missing_safety_doc)] +pub trait UnsafeFrom { + unsafe fn unsafe_from(t: T) -> Self; +} + +/// A vector composed of two elements, which may be words or themselves vectors. +pub trait Vec2 { + fn extract(self, i: u32) -> W; + fn insert(self, w: W, i: u32) -> Self; +} + +/// A vector composed of four elements, which may be words or themselves vectors. +pub trait Vec4 { + fn extract(self, i: u32) -> W; + fn insert(self, w: W, i: u32) -> Self; +} +/// Vec4 functions which may not be implemented yet for all Vec4 types. +/// NOTE: functions in this trait may be moved to Vec4 in any patch release. To avoid breakage, +/// import Vec4Ext only together with Vec4, and don't qualify its methods. +pub trait Vec4Ext { + fn transpose4(a: Self, b: Self, c: Self, d: Self) -> (Self, Self, Self, Self) + where + Self: Sized; +} +pub trait Vector { + fn to_scalars(self) -> T; +} + +// TODO: multiples of 4 should inherit this +/// A vector composed of four words; depending on their size, operations may cross lanes. +pub trait Words4 { + fn shuffle1230(self) -> Self; + fn shuffle2301(self) -> Self; + fn shuffle3012(self) -> Self; +} + +/// A vector composed one or more lanes each composed of four words. +pub trait LaneWords4 { + fn shuffle_lane_words1230(self) -> Self; + fn shuffle_lane_words2301(self) -> Self; + fn shuffle_lane_words3012(self) -> Self; +} + +// TODO: make this a part of BitOps +/// Exchange neigboring ranges of bits of the specified size +pub trait Swap64 { + fn swap1(self) -> Self; + fn swap2(self) -> Self; + fn swap4(self) -> Self; + fn swap8(self) -> Self; + fn swap16(self) -> Self; + fn swap32(self) -> Self; + fn swap64(self) -> Self; +} + +pub trait u32x4: + BitOps32 + + Store + + ArithOps + + Vec4 + + Words4 + + LaneWords4 + + StoreBytes + + MultiLane<[u32; 4]> + + Into +{ +} +pub trait u64x2: + BitOps64 + Store + ArithOps + Vec2 + MultiLane<[u64; 2]> + Into +{ +} +pub trait u128x1: + BitOps128 + Store + Swap64 + MultiLane<[u128; 1]> + Into +{ +} + +pub trait u32x4x2: + BitOps32 + + Store + + Vec2 + + MultiLane<[M::u32x4; 2]> + + ArithOps + + Into + + StoreBytes +{ +} +pub trait u64x2x2: + BitOps64 + + Store + + Vec2 + + MultiLane<[M::u64x2; 2]> + + ArithOps + + StoreBytes + + Into +{ +} +pub trait u64x4: + BitOps64 + + Store + + Vec4 + + MultiLane<[u64; 4]> + + ArithOps + + Words4 + + StoreBytes + + Into +{ +} +pub trait u128x2: + BitOps128 + + Store + + Vec2 + + MultiLane<[M::u128x1; 2]> + + Swap64 + + Into +{ +} + +pub trait u32x4x4: + BitOps32 + + Store + + Vec4 + + Vec4Ext + + Vector<[u32; 16]> + + MultiLane<[M::u32x4; 4]> + + ArithOps + + LaneWords4 + + Into + + StoreBytes +{ +} +pub trait u64x2x4: + BitOps64 + + Store + + Vec4 + + MultiLane<[M::u64x2; 4]> + + ArithOps + + Into +{ +} +// TODO: Words4 +pub trait u128x4: + BitOps128 + + Store + + Vec4 + + MultiLane<[M::u128x1; 4]> + + Swap64 + + Into +{ +} + +/// A vector composed of multiple 128-bit lanes. +pub trait MultiLane { + /// Split a multi-lane vector into single-lane vectors. + fn to_lanes(self) -> Lanes; + /// Build a multi-lane vector from individual lanes. + fn from_lanes(lanes: Lanes) -> Self; +} + +/// Combine single vectors into a multi-lane vector. +pub trait VZip { + fn vzip(self) -> V; +} + +impl VZip for T +where + V: MultiLane, +{ + #[inline(always)] + fn vzip(self) -> V { + V::from_lanes(self) + } +} + +pub trait Machine: Sized + Copy { + type u32x4: u32x4; + type u64x2: u64x2; + type u128x1: u128x1; + + type u32x4x2: u32x4x2; + type u64x2x2: u64x2x2; + type u64x4: u64x4; + type u128x2: u128x2; + + type u32x4x4: u32x4x4; + type u64x2x4: u64x2x4; + type u128x4: u128x4; + + #[inline(always)] + fn unpack>(self, s: S) -> V { + unsafe { V::unpack(s) } + } + + #[inline(always)] + fn vec(self, a: A) -> V + where + V: MultiLane, + { + V::from_lanes(a) + } + + #[inline(always)] + fn read_le(self, input: &[u8]) -> V + where + V: StoreBytes, + { + unsafe { V::unsafe_read_le(input) } + } + + #[inline(always)] + fn read_be(self, input: &[u8]) -> V + where + V: StoreBytes, + { + unsafe { V::unsafe_read_be(input) } + } + + /// # Safety + /// Caller must ensure the type of Self is appropriate for the hardware of the execution + /// environment. + unsafe fn instance() -> Self; +} + +pub trait Store { + /// # Safety + /// Caller must ensure the type of Self is appropriate for the hardware of the execution + /// environment. + unsafe fn unpack(p: S) -> Self; +} + +pub trait StoreBytes { + /// # Safety + /// Caller must ensure the type of Self is appropriate for the hardware of the execution + /// environment. + unsafe fn unsafe_read_le(input: &[u8]) -> Self; + /// # Safety + /// Caller must ensure the type of Self is appropriate for the hardware of the execution + /// environment. + unsafe fn unsafe_read_be(input: &[u8]) -> Self; + fn write_le(self, out: &mut [u8]); + fn write_be(self, out: &mut [u8]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,441 @@ +// crate minimums: sse2, x86_64 + +use crate::types::*; +use core::arch::x86_64::{__m128i, __m256i}; + +mod sse2; + +#[derive(Copy, Clone)] +pub struct YesS3; +#[derive(Copy, Clone)] +pub struct NoS3; + +#[derive(Copy, Clone)] +pub struct YesS4; +#[derive(Copy, Clone)] +pub struct NoS4; + +#[derive(Copy, Clone)] +pub struct YesA1; +#[derive(Copy, Clone)] +pub struct NoA1; + +#[derive(Copy, Clone)] +pub struct YesA2; +#[derive(Copy, Clone)] +pub struct NoA2; + +#[derive(Copy, Clone)] +pub struct YesNI; +#[derive(Copy, Clone)] +pub struct NoNI; + +use core::marker::PhantomData; + +#[derive(Copy, Clone)] +pub struct SseMachine(PhantomData<(S3, S4, NI)>); +impl Machine for SseMachine +where + sse2::u128x1_sse2: Swap64, + sse2::u64x2_sse2: BSwap + RotateEachWord32 + MultiLane<[u64; 2]> + Vec2, + sse2::u32x4_sse2: BSwap + RotateEachWord32 + MultiLane<[u32; 4]> + Vec4, + sse2::u64x4_sse2: BSwap + Words4, + sse2::u128x1_sse2: BSwap, + sse2::u128x2_sse2: Into>, + sse2::u128x2_sse2: Into>, + sse2::u128x2_sse2: Into>, + sse2::u128x4_sse2: Into>, + sse2::u128x4_sse2: Into>, +{ + type u32x4 = sse2::u32x4_sse2; + type u64x2 = sse2::u64x2_sse2; + type u128x1 = sse2::u128x1_sse2; + + type u32x4x2 = sse2::u32x4x2_sse2; + type u64x2x2 = sse2::u64x2x2_sse2; + type u64x4 = sse2::u64x4_sse2; + type u128x2 = sse2::u128x2_sse2; + + type u32x4x4 = sse2::u32x4x4_sse2; + type u64x2x4 = sse2::u64x2x4_sse2; + type u128x4 = sse2::u128x4_sse2; + + #[inline(always)] + unsafe fn instance() -> Self { + SseMachine(PhantomData) + } +} + +#[derive(Copy, Clone)] +pub struct Avx2Machine(PhantomData); +impl Machine for Avx2Machine +where + sse2::u128x1_sse2: BSwap + Swap64, + sse2::u64x2_sse2: BSwap + RotateEachWord32 + MultiLane<[u64; 2]> + Vec2, + sse2::u32x4_sse2: BSwap + RotateEachWord32 + MultiLane<[u32; 4]> + Vec4, + sse2::u64x4_sse2: BSwap + Words4, +{ + type u32x4 = sse2::u32x4_sse2; + type u64x2 = sse2::u64x2_sse2; + type u128x1 = sse2::u128x1_sse2; + + type u32x4x2 = sse2::avx2::u32x4x2_avx2; + type u64x2x2 = sse2::u64x2x2_sse2; + type u64x4 = sse2::u64x4_sse2; + type u128x2 = sse2::u128x2_sse2; + + type u32x4x4 = sse2::avx2::u32x4x4_avx2; + type u64x2x4 = sse2::u64x2x4_sse2; + type u128x4 = sse2::u128x4_sse2; + + #[inline(always)] + unsafe fn instance() -> Self { + Avx2Machine(PhantomData) + } +} + +pub type SSE2 = SseMachine; +pub type SSSE3 = SseMachine; +pub type SSE41 = SseMachine; +/// AVX but not AVX2: only 128-bit integer operations, but use VEX versions of everything +/// to avoid expensive SSE/VEX conflicts. +pub type AVX = SseMachine; +pub type AVX2 = Avx2Machine; + +zerocopy::cryptocorrosion_derive_traits! { + #[repr(C)] + /// Generic wrapper for unparameterized storage of any of the possible impls. + /// Converting into and out of this type should be essentially free, although it may be more + /// aligned than a particular impl requires. + #[allow(non_camel_case_types)] + #[derive(Copy, Clone)] + pub union vec128_storage { + u32x4: [u32; 4], + u64x2: [u64; 2], + u128x1: [u128; 1], + sse2: __m128i, + } +} + +impl Store for vec128_storage { + #[inline(always)] + unsafe fn unpack(p: vec128_storage) -> Self { + p + } +} +impl<'a> From<&'a vec128_storage> for &'a [u32; 4] { + #[inline(always)] + fn from(x: &'a vec128_storage) -> Self { + unsafe { &x.u32x4 } + } +} +impl From<[u32; 4]> for vec128_storage { + #[inline(always)] + fn from(u32x4: [u32; 4]) -> Self { + vec128_storage { u32x4 } + } +} +impl Default for vec128_storage { + #[inline(always)] + fn default() -> Self { + vec128_storage { u128x1: [0] } + } +} +impl Eq for vec128_storage {} +impl PartialEq for vec128_storage { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { self.u128x1 == rhs.u128x1 } + } +} + +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub union vec256_storage { + u32x8: [u32; 8], + u64x4: [u64; 4], + u128x2: [u128; 2], + sse2: [vec128_storage; 2], + avx: __m256i, +} +impl From<[u64; 4]> for vec256_storage { + #[inline(always)] + fn from(u64x4: [u64; 4]) -> Self { + vec256_storage { u64x4 } + } +} +impl Default for vec256_storage { + #[inline(always)] + fn default() -> Self { + vec256_storage { u128x2: [0, 0] } + } +} +impl vec256_storage { + #[inline(always)] + pub fn new128(xs: [vec128_storage; 2]) -> Self { + Self { sse2: xs } + } + #[inline(always)] + pub fn split128(self) -> [vec128_storage; 2] { + unsafe { self.sse2 } + } +} +impl Eq for vec256_storage {} +impl PartialEq for vec256_storage { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { self.sse2 == rhs.sse2 } + } +} + +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub union vec512_storage { + u32x16: [u32; 16], + u64x8: [u64; 8], + u128x4: [u128; 4], + sse2: [vec128_storage; 4], + avx: [vec256_storage; 2], +} +impl Default for vec512_storage { + #[inline(always)] + fn default() -> Self { + vec512_storage { + u128x4: [0, 0, 0, 0], + } + } +} +impl vec512_storage { + #[inline(always)] + pub fn new128(xs: [vec128_storage; 4]) -> Self { + Self { sse2: xs } + } + #[inline(always)] + pub fn split128(self) -> [vec128_storage; 4] { + unsafe { self.sse2 } + } +} +impl Eq for vec512_storage {} +impl PartialEq for vec512_storage { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { self.avx == rhs.avx } + } +} + +macro_rules! impl_into { + ($storage:ident, $array:ty, $name:ident) => { + impl From<$storage> for $array { + #[inline(always)] + fn from(vec: $storage) -> Self { + unsafe { vec.$name } + } + } + }; +} +impl_into!(vec128_storage, [u32; 4], u32x4); +impl_into!(vec128_storage, [u64; 2], u64x2); +impl_into!(vec128_storage, [u128; 1], u128x1); +impl_into!(vec256_storage, [u32; 8], u32x8); +impl_into!(vec256_storage, [u64; 4], u64x4); +impl_into!(vec256_storage, [u128; 2], u128x2); +impl_into!(vec512_storage, [u32; 16], u32x16); +impl_into!(vec512_storage, [u64; 8], u64x8); +impl_into!(vec512_storage, [u128; 4], u128x4); + +/// Generate the full set of optimized implementations to take advantage of the most important +/// hardware feature sets. +/// +/// This dispatcher is suitable for maximizing throughput. +#[macro_export] +macro_rules! dispatch { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[cfg(feature = "std")] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + use std::arch::x86_64::*; + #[target_feature(enable = "avx2")] + unsafe fn impl_avx2($($arg: $argty),*) -> $ret { + let ret = fn_impl($crate::x86_64::AVX2::instance(), $($arg),*); + _mm256_zeroupper(); + ret + } + #[target_feature(enable = "avx")] + #[target_feature(enable = "sse4.1")] + #[target_feature(enable = "ssse3")] + unsafe fn impl_avx($($arg: $argty),*) -> $ret { + let ret = fn_impl($crate::x86_64::AVX::instance(), $($arg),*); + _mm256_zeroupper(); + ret + } + #[target_feature(enable = "sse4.1")] + #[target_feature(enable = "ssse3")] + unsafe fn impl_sse41($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::SSE41::instance(), $($arg),*) + } + #[target_feature(enable = "ssse3")] + unsafe fn impl_ssse3($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::SSSE3::instance(), $($arg),*) + } + #[target_feature(enable = "sse2")] + unsafe fn impl_sse2($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + unsafe { + if is_x86_feature_detected!("avx2") { + impl_avx2($($arg),*) + } else if is_x86_feature_detected!("avx") { + impl_avx($($arg),*) + } else if is_x86_feature_detected!("sse4.1") { + impl_sse41($($arg),*) + } else if is_x86_feature_detected!("ssse3") { + impl_ssse3($($arg),*) + } else if is_x86_feature_detected!("sse2") { + impl_sse2($($arg),*) + } else { + unimplemented!() + } + } + } + #[cfg(not(feature = "std"))] + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + unsafe fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + unsafe { + if cfg!(target_feature = "avx2") { + fn_impl($crate::x86_64::AVX2::instance(), $($arg),*) + } else if cfg!(target_feature = "avx") { + fn_impl($crate::x86_64::AVX::instance(), $($arg),*) + } else if cfg!(target_feature = "sse4.1") { + fn_impl($crate::x86_64::SSE41::instance(), $($arg),*) + } else if cfg!(target_feature = "ssse3") { + fn_impl($crate::x86_64::SSSE3::instance(), $($arg),*) + } else { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + } + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt $(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} + +/// Generate only the basic implementations necessary to be able to operate efficiently on 128-bit +/// vectors on this platfrom. For x86-64, that would mean SSE2 and AVX. +/// +/// This dispatcher is suitable for vector operations that do not benefit from advanced hardware +/// features (e.g. because they are done infrequently), so minimizing their contribution to code +/// size is more important. +#[macro_export] +macro_rules! dispatch_light128 { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[cfg(feature = "std")] + $($pub $(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + use std::arch::x86_64::*; + #[target_feature(enable = "avx")] + unsafe fn impl_avx($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::AVX::instance(), $($arg),*) + } + #[target_feature(enable = "sse2")] + unsafe fn impl_sse2($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + unsafe { + if is_x86_feature_detected!("avx") { + impl_avx($($arg),*) + } else if is_x86_feature_detected!("sse2") { + impl_sse2($($arg),*) + } else { + unimplemented!() + } + } + } + #[cfg(not(feature = "std"))] + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + unsafe fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + unsafe { + if cfg!(target_feature = "avx2") { + fn_impl($crate::x86_64::AVX2::instance(), $($arg),*) + } else if cfg!(target_feature = "avx") { + fn_impl($crate::x86_64::AVX::instance(), $($arg),*) + } else if cfg!(target_feature = "sse4.1") { + fn_impl($crate::x86_64::SSE41::instance(), $($arg),*) + } else if cfg!(target_feature = "ssse3") { + fn_impl($crate::x86_64::SSSE3::instance(), $($arg),*) + } else { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + } + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch_light128!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} + +/// Generate only the basic implementations necessary to be able to operate efficiently on 256-bit +/// vectors on this platfrom. For x86-64, that would mean SSE2, AVX, and AVX2. +/// +/// This dispatcher is suitable for vector operations that do not benefit from advanced hardware +/// features (e.g. because they are done infrequently), so minimizing their contribution to code +/// size is more important. +#[macro_export] +macro_rules! dispatch_light256 { + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block }) => { + #[cfg(feature = "std")] + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> $ret { + #[inline(always)] + fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + use std::arch::x86_64::*; + #[target_feature(enable = "avx")] + unsafe fn impl_avx($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::AVX::instance(), $($arg),*) + } + #[target_feature(enable = "sse2")] + unsafe fn impl_sse2($($arg: $argty),*) -> $ret { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + unsafe { + if is_x86_feature_detected!("avx") { + impl_avx($($arg),*) + } else if is_x86_feature_detected!("sse2") { + impl_sse2($($arg),*) + } else { + unimplemented!() + } + } + } + #[cfg(not(feature = "std"))] + #[inline(always)] + $($pub$(($krate))*)* fn $name($($arg: $argty),*) -> $ret { + unsafe fn fn_impl<$MTy: $crate::Machine>($mach: $MTy, $($arg: $argty),*) -> $ret $body + unsafe { + if cfg!(target_feature = "avx2") { + fn_impl($crate::x86_64::AVX2::instance(), $($arg),*) + } else if cfg!(target_feature = "avx") { + fn_impl($crate::x86_64::AVX::instance(), $($arg),*) + } else if cfg!(target_feature = "sse4.1") { + fn_impl($crate::x86_64::SSE41::instance(), $($arg),*) + } else if cfg!(target_feature = "ssse3") { + fn_impl($crate::x86_64::SSSE3::instance(), $($arg),*) + } else { + fn_impl($crate::x86_64::SSE2::instance(), $($arg),*) + } + } + } + }; + ($mach:ident, $MTy:ident, { $([$pub:tt$(($krate:tt))*])* fn $name:ident($($arg:ident: $argty:ty),* $(,)*) $body:block }) => { + dispatch_light256!($mach, $MTy, { + $([$pub $(($krate))*])* fn $name($($arg: $argty),*) -> () $body + }); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/sse2.rs clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/sse2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/sse2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ppv-lite86/src/x86_64/sse2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1711 @@ +use crate::soft::{x2, x4}; +use crate::types::*; +use crate::vec128_storage; +use crate::x86_64::Avx2Machine; +use crate::x86_64::SseMachine as Machine86; +use crate::x86_64::{NoS3, NoS4, YesS3, YesS4}; +use core::arch::x86_64::*; +use core::marker::PhantomData; +use core::ops::{ + Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, +}; +use zerocopy::transmute; + +macro_rules! impl_binop { + ($vec:ident, $trait:ident, $fn:ident, $impl_fn:ident) => { + impl $trait for $vec { + type Output = Self; + #[inline(always)] + fn $fn(self, rhs: Self) -> Self::Output { + Self::new(unsafe { $impl_fn(self.x, rhs.x) }) + } + } + }; +} + +macro_rules! impl_binop_assign { + ($vec:ident, $trait:ident, $fn_assign:ident, $fn:ident) => { + impl $trait for $vec + where + $vec: Copy, + { + #[inline(always)] + fn $fn_assign(&mut self, rhs: Self) { + *self = self.$fn(rhs); + } + } + }; +} + +macro_rules! def_vec { + ($vec:ident, $word:ident) => { + zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[allow(non_camel_case_types)] + #[derive(Copy, Clone)] + pub struct $vec { + x: __m128i, + s3: PhantomData, + s4: PhantomData, + ni: PhantomData, + } + } + + impl Store for $vec { + #[inline(always)] + unsafe fn unpack(x: vec128_storage) -> Self { + Self::new(x.sse2) + } + } + impl From<$vec> for vec128_storage { + #[inline(always)] + fn from(x: $vec) -> Self { + vec128_storage { sse2: x.x } + } + } + impl $vec { + #[inline(always)] + fn new(x: __m128i) -> Self { + $vec { + x, + s3: PhantomData, + s4: PhantomData, + ni: PhantomData, + } + } + } + + impl StoreBytes for $vec + where + Self: BSwap, + { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + assert_eq!(input.len(), 16); + Self::new(_mm_loadu_si128(input.as_ptr() as *const _)) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + assert_eq!(input.len(), 16); + Self::new(_mm_loadu_si128(input.as_ptr() as *const _)).bswap() + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + assert_eq!(out.len(), 16); + unsafe { _mm_storeu_si128(out.as_mut_ptr() as *mut _, self.x) } + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + assert_eq!(out.len(), 16); + let x = self.bswap().x; + unsafe { + _mm_storeu_si128(out.as_mut_ptr() as *mut _, x); + } + } + } + + impl Default for $vec { + #[inline(always)] + fn default() -> Self { + Self::new(unsafe { _mm_setzero_si128() }) + } + } + + impl Not for $vec { + type Output = Self; + #[inline(always)] + fn not(self) -> Self::Output { + unsafe { + let ff = _mm_set1_epi64x(-1i64); + self ^ Self::new(ff) + } + } + } + + impl BitOps0 for $vec {} + impl_binop!($vec, BitAnd, bitand, _mm_and_si128); + impl_binop!($vec, BitOr, bitor, _mm_or_si128); + impl_binop!($vec, BitXor, bitxor, _mm_xor_si128); + impl_binop_assign!($vec, BitAndAssign, bitand_assign, bitand); + impl_binop_assign!($vec, BitOrAssign, bitor_assign, bitor); + impl_binop_assign!($vec, BitXorAssign, bitxor_assign, bitxor); + impl AndNot for $vec { + type Output = Self; + #[inline(always)] + fn andnot(self, rhs: Self) -> Self { + Self::new(unsafe { _mm_andnot_si128(self.x, rhs.x) }) + } + } + }; +} + +macro_rules! impl_bitops32 { + ($vec:ident) => { + impl BitOps32 for $vec where + $vec: RotateEachWord32 + { + } + }; +} + +macro_rules! impl_bitops64 { + ($vec:ident) => { + impl_bitops32!($vec); + impl BitOps64 for $vec where + $vec: RotateEachWord64 + RotateEachWord32 + { + } + }; +} + +macro_rules! impl_bitops128 { + ($vec:ident) => { + impl_bitops64!($vec); + impl BitOps128 for $vec where + $vec: RotateEachWord128 + { + } + }; +} + +macro_rules! rotr_32_s3 { + ($name:ident, $k0:expr, $k1:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi8(self.x, _mm_set_epi64x($k0, $k1)) }) + } + }; +} +macro_rules! rotr_32 { + ($name:ident, $i:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { + _mm_or_si128( + _mm_srli_epi32(self.x, $i as i32), + _mm_slli_epi32(self.x, 32 - $i as i32), + ) + }) + } + }; +} +impl RotateEachWord32 for u32x4_sse2 { + rotr_32!(rotate_each_word_right7, 7); + rotr_32_s3!( + rotate_each_word_right8, + 0x0c0f_0e0d_080b_0a09, + 0x0407_0605_0003_0201 + ); + rotr_32!(rotate_each_word_right11, 11); + rotr_32!(rotate_each_word_right12, 12); + rotr_32_s3!( + rotate_each_word_right16, + 0x0d0c_0f0e_0908_0b0a, + 0x0504_0706_0100_0302 + ); + rotr_32!(rotate_each_word_right20, 20); + rotr_32_s3!( + rotate_each_word_right24, + 0x0e0d_0c0f_0a09_080b, + 0x0605_0407_0201_0003 + ); + rotr_32!(rotate_each_word_right25, 25); +} +impl RotateEachWord32 for u32x4_sse2 { + rotr_32!(rotate_each_word_right7, 7); + rotr_32!(rotate_each_word_right8, 8); + rotr_32!(rotate_each_word_right11, 11); + rotr_32!(rotate_each_word_right12, 12); + #[inline(always)] + fn rotate_each_word_right16(self) -> Self { + Self::new(swap16_s2(self.x)) + } + rotr_32!(rotate_each_word_right20, 20); + rotr_32!(rotate_each_word_right24, 24); + rotr_32!(rotate_each_word_right25, 25); +} + +macro_rules! rotr_64_s3 { + ($name:ident, $k0:expr, $k1:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi8(self.x, _mm_set_epi64x($k0, $k1)) }) + } + }; +} +macro_rules! rotr_64 { + ($name:ident, $i:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { + _mm_or_si128( + _mm_srli_epi64(self.x, $i as i32), + _mm_slli_epi64(self.x, 64 - $i as i32), + ) + }) + } + }; +} +impl RotateEachWord32 for u64x2_sse2 { + rotr_64!(rotate_each_word_right7, 7); + rotr_64_s3!( + rotate_each_word_right8, + 0x080f_0e0d_0c0b_0a09, + 0x0007_0605_0403_0201 + ); + rotr_64!(rotate_each_word_right11, 11); + rotr_64!(rotate_each_word_right12, 12); + rotr_64_s3!( + rotate_each_word_right16, + 0x0908_0f0e_0d0c_0b0a, + 0x0100_0706_0504_0302 + ); + rotr_64!(rotate_each_word_right20, 20); + rotr_64_s3!( + rotate_each_word_right24, + 0x0a09_080f_0e0d_0c0b, + 0x0201_0007_0605_0403 + ); + rotr_64!(rotate_each_word_right25, 25); +} +impl RotateEachWord32 for u64x2_sse2 { + rotr_64!(rotate_each_word_right7, 7); + rotr_64!(rotate_each_word_right8, 8); + rotr_64!(rotate_each_word_right11, 11); + rotr_64!(rotate_each_word_right12, 12); + #[inline(always)] + fn rotate_each_word_right16(self) -> Self { + Self::new(swap16_s2(self.x)) + } + rotr_64!(rotate_each_word_right20, 20); + rotr_64!(rotate_each_word_right24, 24); + rotr_64!(rotate_each_word_right25, 25); +} +impl RotateEachWord64 for u64x2_sse2 { + #[inline(always)] + fn rotate_each_word_right32(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi32(self.x, 0b10110001) }) + } +} + +macro_rules! rotr_128 { + ($name:ident, $i:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { + _mm_or_si128( + _mm_srli_si128(self.x, $i as i32), + _mm_slli_si128(self.x, 128 - $i as i32), + ) + }) + } + }; +} +// TODO: completely unoptimized +impl RotateEachWord32 for u128x1_sse2 { + rotr_128!(rotate_each_word_right7, 7); + rotr_128!(rotate_each_word_right8, 8); + rotr_128!(rotate_each_word_right11, 11); + rotr_128!(rotate_each_word_right12, 12); + rotr_128!(rotate_each_word_right16, 16); + rotr_128!(rotate_each_word_right20, 20); + rotr_128!(rotate_each_word_right24, 24); + rotr_128!(rotate_each_word_right25, 25); +} +// TODO: completely unoptimized +impl RotateEachWord64 for u128x1_sse2 { + rotr_128!(rotate_each_word_right32, 32); +} +impl RotateEachWord128 for u128x1_sse2 {} + +def_vec!(u32x4_sse2, u32); +def_vec!(u64x2_sse2, u64); +def_vec!(u128x1_sse2, u128); + +impl MultiLane<[u32; 4]> for u32x4_sse2 { + #[inline(always)] + fn to_lanes(self) -> [u32; 4] { + unsafe { + let x = _mm_cvtsi128_si64(self.x) as u64; + let y = _mm_extract_epi64(self.x, 1) as u64; + [x as u32, (x >> 32) as u32, y as u32, (y >> 32) as u32] + } + } + #[inline(always)] + fn from_lanes(xs: [u32; 4]) -> Self { + unsafe { + let mut x = _mm_cvtsi64_si128((xs[0] as u64 | ((xs[1] as u64) << 32)) as i64); + x = _mm_insert_epi64(x, (xs[2] as u64 | ((xs[3] as u64) << 32)) as i64, 1); + Self::new(x) + } + } +} +impl MultiLane<[u32; 4]> for u32x4_sse2 { + #[inline(always)] + fn to_lanes(self) -> [u32; 4] { + unsafe { + let x = _mm_cvtsi128_si64(self.x) as u64; + let y = _mm_cvtsi128_si64(_mm_shuffle_epi32(self.x, 0b11101110)) as u64; + [x as u32, (x >> 32) as u32, y as u32, (y >> 32) as u32] + } + } + #[inline(always)] + fn from_lanes(xs: [u32; 4]) -> Self { + unsafe { + let x = (xs[0] as u64 | ((xs[1] as u64) << 32)) as i64; + let y = (xs[2] as u64 | ((xs[3] as u64) << 32)) as i64; + let x = _mm_cvtsi64_si128(x); + let y = _mm_slli_si128(_mm_cvtsi64_si128(y), 8); + Self::new(_mm_or_si128(x, y)) + } + } +} +impl MultiLane<[u64; 2]> for u64x2_sse2 { + #[inline(always)] + fn to_lanes(self) -> [u64; 2] { + unsafe { + [ + _mm_cvtsi128_si64(self.x) as u64, + _mm_extract_epi64(self.x, 1) as u64, + ] + } + } + #[inline(always)] + fn from_lanes(xs: [u64; 2]) -> Self { + unsafe { + let mut x = _mm_cvtsi64_si128(xs[0] as i64); + x = _mm_insert_epi64(x, xs[1] as i64, 1); + Self::new(x) + } + } +} +impl MultiLane<[u64; 2]> for u64x2_sse2 { + #[inline(always)] + fn to_lanes(self) -> [u64; 2] { + unsafe { + [ + _mm_cvtsi128_si64(self.x) as u64, + _mm_cvtsi128_si64(_mm_srli_si128(self.x, 8)) as u64, + ] + } + } + #[inline(always)] + fn from_lanes(xs: [u64; 2]) -> Self { + unsafe { + let x = _mm_cvtsi64_si128(xs[0] as i64); + let y = _mm_slli_si128(_mm_cvtsi64_si128(xs[1] as i64), 8); + Self::new(_mm_or_si128(x, y)) + } + } +} +impl MultiLane<[u128; 1]> for u128x1_sse2 { + #[inline(always)] + fn to_lanes(self) -> [u128; 1] { + unimplemented!() + } + #[inline(always)] + fn from_lanes(xs: [u128; 1]) -> Self { + unimplemented!("{:?}", xs) + } +} + +impl MultiLane<[u64; 4]> for u64x4_sse2 +where + u64x2_sse2: MultiLane<[u64; 2]> + Copy, +{ + #[inline(always)] + fn to_lanes(self) -> [u64; 4] { + let (a, b) = (self.0[0].to_lanes(), self.0[1].to_lanes()); + [a[0], a[1], b[0], b[1]] + } + #[inline(always)] + fn from_lanes(xs: [u64; 4]) -> Self { + let (a, b) = ( + u64x2_sse2::from_lanes([xs[0], xs[1]]), + u64x2_sse2::from_lanes([xs[2], xs[3]]), + ); + x2::new([a, b]) + } +} + +macro_rules! impl_into { + ($from:ident, $to:ident) => { + impl From<$from> for $to { + #[inline(always)] + fn from(x: $from) -> Self { + $to::new(x.x) + } + } + }; +} + +impl_into!(u128x1_sse2, u32x4_sse2); +impl_into!(u128x1_sse2, u64x2_sse2); + +impl_bitops32!(u32x4_sse2); +impl_bitops64!(u64x2_sse2); +impl_bitops128!(u128x1_sse2); + +impl ArithOps for u32x4_sse2 where + u32x4_sse2: BSwap +{ +} +impl ArithOps for u64x2_sse2 where + u64x2_sse2: BSwap +{ +} +impl_binop!(u32x4_sse2, Add, add, _mm_add_epi32); +impl_binop!(u64x2_sse2, Add, add, _mm_add_epi64); +impl_binop_assign!(u32x4_sse2, AddAssign, add_assign, add); +impl_binop_assign!(u64x2_sse2, AddAssign, add_assign, add); + +impl u32x4> for u32x4_sse2 +where + u32x4_sse2: RotateEachWord32 + BSwap + MultiLane<[u32; 4]> + Vec4, + Machine86: Machine, +{ +} +impl u64x2> for u64x2_sse2 +where + u64x2_sse2: + RotateEachWord64 + RotateEachWord32 + BSwap + MultiLane<[u64; 2]> + Vec2, + Machine86: Machine, +{ +} +impl u128x1> for u128x1_sse2 +where + u128x1_sse2: Swap64 + RotateEachWord64 + RotateEachWord32 + BSwap, + Machine86: Machine, + u128x1_sse2: Into< as Machine>::u32x4>, + u128x1_sse2: Into< as Machine>::u64x2>, +{ +} + +impl u32x4> for u32x4_sse2 +where + u32x4_sse2: RotateEachWord32 + BSwap + MultiLane<[u32; 4]> + Vec4, + Machine86: Machine, +{ +} +impl u64x2> for u64x2_sse2 +where + u64x2_sse2: + RotateEachWord64 + RotateEachWord32 + BSwap + MultiLane<[u64; 2]> + Vec2, + Machine86: Machine, +{ +} +impl u128x1> for u128x1_sse2 +where + u128x1_sse2: Swap64 + RotateEachWord64 + RotateEachWord32 + BSwap, + Machine86: Machine, + u128x1_sse2: Into< as Machine>::u32x4>, + u128x1_sse2: Into< as Machine>::u64x2>, +{ +} + +impl UnsafeFrom<[u32; 4]> for u32x4_sse2 { + #[inline(always)] + unsafe fn unsafe_from(xs: [u32; 4]) -> Self { + Self::new(_mm_set_epi32( + xs[3] as i32, + xs[2] as i32, + xs[1] as i32, + xs[0] as i32, + )) + } +} + +impl Vec4 for u32x4_sse2 +where + Self: MultiLane<[u32; 4]>, +{ + #[inline(always)] + fn extract(self, i: u32) -> u32 { + self.to_lanes()[i as usize] + } + #[inline(always)] + fn insert(self, v: u32, i: u32) -> Self { + Self::new(unsafe { + match i { + 0 => _mm_insert_epi32(self.x, v as i32, 0), + 1 => _mm_insert_epi32(self.x, v as i32, 1), + 2 => _mm_insert_epi32(self.x, v as i32, 2), + 3 => _mm_insert_epi32(self.x, v as i32, 3), + _ => unreachable!(), + } + }) + } +} +impl Vec4 for u32x4_sse2 +where + Self: MultiLane<[u32; 4]>, +{ + #[inline(always)] + fn extract(self, i: u32) -> u32 { + self.to_lanes()[i as usize] + } + #[inline(always)] + fn insert(self, v: u32, i: u32) -> Self { + Self::new(unsafe { + match i { + 0 => { + let x = _mm_andnot_si128(_mm_cvtsi32_si128(-1), self.x); + _mm_or_si128(x, _mm_cvtsi32_si128(v as i32)) + } + 1 => { + let mut x = _mm_shuffle_epi32(self.x, 0b0111_1000); + x = _mm_slli_si128(x, 4); + x = _mm_or_si128(x, _mm_cvtsi32_si128(v as i32)); + _mm_shuffle_epi32(x, 0b1110_0001) + } + 2 => { + let mut x = _mm_shuffle_epi32(self.x, 0b1011_0100); + x = _mm_slli_si128(x, 4); + x = _mm_or_si128(x, _mm_cvtsi32_si128(v as i32)); + _mm_shuffle_epi32(x, 0b1100_1001) + } + 3 => { + let mut x = _mm_slli_si128(self.x, 4); + x = _mm_or_si128(x, _mm_cvtsi32_si128(v as i32)); + _mm_shuffle_epi32(x, 0b0011_1001) + } + _ => unreachable!(), + } + }) + } +} + +impl LaneWords4 for u32x4_sse2 { + #[inline(always)] + fn shuffle_lane_words2301(self) -> Self { + self.shuffle2301() + } + #[inline(always)] + fn shuffle_lane_words1230(self) -> Self { + self.shuffle1230() + } + #[inline(always)] + fn shuffle_lane_words3012(self) -> Self { + self.shuffle3012() + } +} + +impl Words4 for u32x4_sse2 { + #[inline(always)] + fn shuffle2301(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi32(self.x, 0b0100_1110) }) + } + #[inline(always)] + fn shuffle1230(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi32(self.x, 0b1001_0011) }) + } + #[inline(always)] + fn shuffle3012(self) -> Self { + Self::new(unsafe { _mm_shuffle_epi32(self.x, 0b0011_1001) }) + } +} + +impl Words4 for u64x4_sse2 { + #[inline(always)] + fn shuffle2301(self) -> Self { + x2::new([u64x2_sse2::new(self.0[1].x), u64x2_sse2::new(self.0[0].x)]) + } + #[inline(always)] + fn shuffle3012(self) -> Self { + unsafe { + x2::new([ + u64x2_sse2::new(_mm_alignr_epi8(self.0[1].x, self.0[0].x, 8)), + u64x2_sse2::new(_mm_alignr_epi8(self.0[0].x, self.0[1].x, 8)), + ]) + } + } + #[inline(always)] + fn shuffle1230(self) -> Self { + unsafe { + x2::new([ + u64x2_sse2::new(_mm_alignr_epi8(self.0[0].x, self.0[1].x, 8)), + u64x2_sse2::new(_mm_alignr_epi8(self.0[1].x, self.0[0].x, 8)), + ]) + } + } +} +impl Words4 for u64x4_sse2 { + #[inline(always)] + fn shuffle2301(self) -> Self { + x2::new([u64x2_sse2::new(self.0[1].x), u64x2_sse2::new(self.0[0].x)]) + } + #[inline(always)] + fn shuffle3012(self) -> Self { + unsafe { + let a = _mm_srli_si128(self.0[0].x, 8); + let b = _mm_slli_si128(self.0[0].x, 8); + let c = _mm_srli_si128(self.0[1].x, 8); + let d = _mm_slli_si128(self.0[1].x, 8); + let da = _mm_or_si128(d, a); + let bc = _mm_or_si128(b, c); + x2::new([u64x2_sse2::new(da), u64x2_sse2::new(bc)]) + } + } + #[inline(always)] + fn shuffle1230(self) -> Self { + unsafe { + let a = _mm_srli_si128(self.0[0].x, 8); + let b = _mm_slli_si128(self.0[0].x, 8); + let c = _mm_srli_si128(self.0[1].x, 8); + let d = _mm_slli_si128(self.0[1].x, 8); + let da = _mm_or_si128(d, a); + let bc = _mm_or_si128(b, c); + x2::new([u64x2_sse2::new(bc), u64x2_sse2::new(da)]) + } + } +} + +impl UnsafeFrom<[u64; 2]> for u64x2_sse2 { + #[inline(always)] + unsafe fn unsafe_from(xs: [u64; 2]) -> Self { + Self::new(_mm_set_epi64x(xs[1] as i64, xs[0] as i64)) + } +} + +impl Vec2 for u64x2_sse2 { + #[inline(always)] + fn extract(self, i: u32) -> u64 { + unsafe { + match i { + 0 => _mm_cvtsi128_si64(self.x) as u64, + 1 => _mm_extract_epi64(self.x, 1) as u64, + _ => unreachable!(), + } + } + } + #[inline(always)] + fn insert(self, x: u64, i: u32) -> Self { + Self::new(unsafe { + match i { + 0 => _mm_insert_epi64(self.x, x as i64, 0), + 1 => _mm_insert_epi64(self.x, x as i64, 1), + _ => unreachable!(), + } + }) + } +} +impl Vec2 for u64x2_sse2 { + #[inline(always)] + fn extract(self, i: u32) -> u64 { + unsafe { + match i { + 0 => _mm_cvtsi128_si64(self.x) as u64, + 1 => _mm_cvtsi128_si64(_mm_shuffle_epi32(self.x, 0b11101110)) as u64, + _ => unreachable!(), + } + } + } + #[inline(always)] + fn insert(self, x: u64, i: u32) -> Self { + Self::new(unsafe { + match i { + 0 => _mm_or_si128( + _mm_andnot_si128(_mm_cvtsi64_si128(-1), self.x), + _mm_cvtsi64_si128(x as i64), + ), + 1 => _mm_or_si128( + _mm_move_epi64(self.x), + _mm_slli_si128(_mm_cvtsi64_si128(x as i64), 8), + ), + _ => unreachable!(), + } + }) + } +} + +impl BSwap for u32x4_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + Self::new(unsafe { + let k = _mm_set_epi64x(0x0c0d_0e0f_0809_0a0b, 0x0405_0607_0001_0203); + _mm_shuffle_epi8(self.x, k) + }) + } +} +#[inline(always)] +fn bswap32_s2(x: __m128i) -> __m128i { + unsafe { + let mut y = _mm_unpacklo_epi8(x, _mm_setzero_si128()); + y = _mm_shufflehi_epi16(y, 0b0001_1011); + y = _mm_shufflelo_epi16(y, 0b0001_1011); + let mut z = _mm_unpackhi_epi8(x, _mm_setzero_si128()); + z = _mm_shufflehi_epi16(z, 0b0001_1011); + z = _mm_shufflelo_epi16(z, 0b0001_1011); + _mm_packus_epi16(y, z) + } +} +impl BSwap for u32x4_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + Self::new(bswap32_s2(self.x)) + } +} + +impl BSwap for u64x2_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + Self::new(unsafe { + let k = _mm_set_epi64x(0x0809_0a0b_0c0d_0e0f, 0x0001_0203_0405_0607); + _mm_shuffle_epi8(self.x, k) + }) + } +} +impl BSwap for u64x2_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + Self::new(unsafe { bswap32_s2(_mm_shuffle_epi32(self.x, 0b1011_0001)) }) + } +} + +impl BSwap for u128x1_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + Self::new(unsafe { + let k = _mm_set_epi64x(0x0f0e_0d0c_0b0a_0908, 0x0706_0504_0302_0100); + _mm_shuffle_epi8(self.x, k) + }) + } +} +impl BSwap for u128x1_sse2 { + #[inline(always)] + fn bswap(self) -> Self { + unimplemented!() + } +} + +macro_rules! swapi { + ($x:expr, $i:expr, $k:expr) => { + unsafe { + const K: u8 = $k; + let k = _mm_set1_epi8(K as i8); + u128x1_sse2::new(_mm_or_si128( + _mm_srli_epi16(_mm_and_si128($x.x, k), $i), + _mm_and_si128(_mm_slli_epi16($x.x, $i), k), + )) + } + }; +} +#[inline(always)] +fn swap16_s2(x: __m128i) -> __m128i { + unsafe { _mm_shufflehi_epi16(_mm_shufflelo_epi16(x, 0b1011_0001), 0b1011_0001) } +} +impl Swap64 for u128x1_sse2 { + #[inline(always)] + fn swap1(self) -> Self { + swapi!(self, 1, 0xaa) + } + #[inline(always)] + fn swap2(self) -> Self { + swapi!(self, 2, 0xcc) + } + #[inline(always)] + fn swap4(self) -> Self { + swapi!(self, 4, 0xf0) + } + #[inline(always)] + fn swap8(self) -> Self { + u128x1_sse2::new(unsafe { + let k = _mm_set_epi64x(0x0e0f_0c0d_0a0b_0809, 0x0607_0405_0203_0001); + _mm_shuffle_epi8(self.x, k) + }) + } + #[inline(always)] + fn swap16(self) -> Self { + u128x1_sse2::new(unsafe { + let k = _mm_set_epi64x(0x0d0c_0f0e_0908_0b0a, 0x0504_0706_0100_0302); + _mm_shuffle_epi8(self.x, k) + }) + } + #[inline(always)] + fn swap32(self) -> Self { + u128x1_sse2::new(unsafe { _mm_shuffle_epi32(self.x, 0b1011_0001) }) + } + #[inline(always)] + fn swap64(self) -> Self { + u128x1_sse2::new(unsafe { _mm_shuffle_epi32(self.x, 0b0100_1110) }) + } +} +impl Swap64 for u128x1_sse2 { + #[inline(always)] + fn swap1(self) -> Self { + swapi!(self, 1, 0xaa) + } + #[inline(always)] + fn swap2(self) -> Self { + swapi!(self, 2, 0xcc) + } + #[inline(always)] + fn swap4(self) -> Self { + swapi!(self, 4, 0xf0) + } + #[inline(always)] + fn swap8(self) -> Self { + u128x1_sse2::new(unsafe { + _mm_or_si128(_mm_slli_epi16(self.x, 8), _mm_srli_epi16(self.x, 8)) + }) + } + #[inline(always)] + fn swap16(self) -> Self { + u128x1_sse2::new(swap16_s2(self.x)) + } + #[inline(always)] + fn swap32(self) -> Self { + u128x1_sse2::new(unsafe { _mm_shuffle_epi32(self.x, 0b1011_0001) }) + } + #[inline(always)] + fn swap64(self) -> Self { + u128x1_sse2::new(unsafe { _mm_shuffle_epi32(self.x, 0b0100_1110) }) + } +} + +#[derive(Copy, Clone)] +pub struct G0; +#[derive(Copy, Clone)] +pub struct G1; + +#[allow(non_camel_case_types)] +pub type u32x4x2_sse2 = x2, G0>; +#[allow(non_camel_case_types)] +pub type u64x2x2_sse2 = x2, G0>; +#[allow(non_camel_case_types)] +pub type u64x4_sse2 = x2, G1>; +#[allow(non_camel_case_types)] +pub type u128x2_sse2 = x2, G0>; + +#[allow(non_camel_case_types)] +pub type u32x4x4_sse2 = x4>; +#[allow(non_camel_case_types)] +pub type u64x2x4_sse2 = x4>; +#[allow(non_camel_case_types)] +pub type u128x4_sse2 = x4>; + +impl Vector<[u32; 16]> for u32x4x4_sse2 { + #[inline(always)] + fn to_scalars(self) -> [u32; 16] { + transmute!(self) + } +} + +impl u32x4x2> for u32x4x2_sse2 +where + u32x4_sse2: RotateEachWord32 + BSwap, + Machine86: Machine, + u32x4x2_sse2: MultiLane<[ as Machine>::u32x4; 2]>, + u32x4x2_sse2: Vec2< as Machine>::u32x4>, +{ +} +impl u64x2x2> for u64x2x2_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Machine86: Machine, + u64x2x2_sse2: MultiLane<[ as Machine>::u64x2; 2]>, + u64x2x2_sse2: Vec2< as Machine>::u64x2>, +{ +} +impl u64x4> for u64x4_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Machine86: Machine, + u64x4_sse2: MultiLane<[u64; 4]> + Vec4 + Words4, +{ +} +impl u128x2> for u128x2_sse2 +where + u128x1_sse2: Swap64 + BSwap, + Machine86: Machine, + u128x2_sse2: MultiLane<[ as Machine>::u128x1; 2]>, + u128x2_sse2: Vec2< as Machine>::u128x1>, + u128x2_sse2: Into< as Machine>::u32x4x2>, + u128x2_sse2: Into< as Machine>::u64x2x2>, + u128x2_sse2: Into< as Machine>::u64x4>, +{ +} + +impl u32x4x2> for u32x4x2_sse2 +where + u32x4_sse2: RotateEachWord32 + BSwap, + Avx2Machine: Machine, + u32x4x2_sse2: MultiLane<[ as Machine>::u32x4; 2]>, + u32x4x2_sse2: Vec2< as Machine>::u32x4>, +{ +} +impl u64x2x2> for u64x2x2_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Avx2Machine: Machine, + u64x2x2_sse2: MultiLane<[ as Machine>::u64x2; 2]>, + u64x2x2_sse2: Vec2< as Machine>::u64x2>, +{ +} +impl u64x4> for u64x4_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Avx2Machine: Machine, + u64x4_sse2: MultiLane<[u64; 4]> + Vec4 + Words4, +{ +} +impl u128x2> for u128x2_sse2 +where + u128x1_sse2: Swap64 + BSwap, + Avx2Machine: Machine, + u128x2_sse2: MultiLane<[ as Machine>::u128x1; 2]>, + u128x2_sse2: Vec2< as Machine>::u128x1>, + u128x2_sse2: Into< as Machine>::u32x4x2>, + u128x2_sse2: Into< as Machine>::u64x2x2>, + u128x2_sse2: Into< as Machine>::u64x4>, +{ +} + +impl Vec4 for u64x4_sse2 +where + u64x2_sse2: Copy + Vec2, +{ + #[inline(always)] + fn extract(self, i: u32) -> u64 { + match i { + 0 => self.0[0].extract(0), + 1 => self.0[0].extract(1), + 2 => self.0[1].extract(0), + 3 => self.0[1].extract(1), + _ => panic!(), + } + } + #[inline(always)] + fn insert(mut self, w: u64, i: u32) -> Self { + match i { + 0 => self.0[0] = self.0[0].insert(w, 0), + 1 => self.0[0] = self.0[0].insert(w, 1), + 2 => self.0[1] = self.0[1].insert(w, 0), + 3 => self.0[1] = self.0[1].insert(w, 1), + _ => panic!(), + }; + self + } +} + +impl u32x4x4> for u32x4x4_sse2 +where + u32x4_sse2: RotateEachWord32 + BSwap, + Machine86: Machine, + u32x4x4_sse2: MultiLane<[ as Machine>::u32x4; 4]>, + u32x4x4_sse2: Vec4< as Machine>::u32x4>, + u32x4x4_sse2: Vec4Ext< as Machine>::u32x4>, + u32x4x4_sse2: Vector<[u32; 16]>, +{ +} +impl u64x2x4> for u64x2x4_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Machine86: Machine, + u64x2x4_sse2: MultiLane<[ as Machine>::u64x2; 4]>, + u64x2x4_sse2: Vec4< as Machine>::u64x2>, +{ +} +impl u128x4> for u128x4_sse2 +where + u128x1_sse2: Swap64 + BSwap, + Machine86: Machine, + u128x4_sse2: MultiLane<[ as Machine>::u128x1; 4]>, + u128x4_sse2: Vec4< as Machine>::u128x1>, + u128x4_sse2: Into< as Machine>::u32x4x4>, + u128x4_sse2: Into< as Machine>::u64x2x4>, +{ +} + +impl u64x2x4> for u64x2x4_sse2 +where + u64x2_sse2: RotateEachWord64 + RotateEachWord32 + BSwap, + Avx2Machine: Machine, + u64x2x4_sse2: MultiLane<[ as Machine>::u64x2; 4]>, + u64x2x4_sse2: Vec4< as Machine>::u64x2>, +{ +} +impl u128x4> for u128x4_sse2 +where + u128x1_sse2: Swap64 + BSwap, + Avx2Machine: Machine, + u128x4_sse2: MultiLane<[ as Machine>::u128x1; 4]>, + u128x4_sse2: Vec4< as Machine>::u128x1>, + u128x4_sse2: Into< as Machine>::u32x4x4>, + u128x4_sse2: Into< as Machine>::u64x2x4>, +{ +} + +macro_rules! impl_into_x { + ($from:ident, $to:ident) => { + impl From, Gf>> + for x2<$to, Gt> + { + #[inline(always)] + fn from(x: x2<$from, Gf>) -> Self { + x2::new([$to::from(x.0[0]), $to::from(x.0[1])]) + } + } + impl From>> for x4<$to> { + #[inline(always)] + fn from(x: x4<$from>) -> Self { + x4::new([ + $to::from(x.0[0]), + $to::from(x.0[1]), + $to::from(x.0[2]), + $to::from(x.0[3]), + ]) + } + } + }; +} +impl_into_x!(u128x1_sse2, u64x2_sse2); +impl_into_x!(u128x1_sse2, u32x4_sse2); + +///// Debugging + +use core::fmt::{Debug, Formatter, Result}; + +impl PartialEq for x2 { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + self.0[0] == rhs.0[0] && self.0[1] == rhs.0[1] + } +} + +#[allow(unused)] +#[inline(always)] +unsafe fn eq128_s4(x: __m128i, y: __m128i) -> bool { + let q = _mm_shuffle_epi32(_mm_cmpeq_epi64(x, y), 0b1100_0110); + _mm_cvtsi128_si64(q) == -1 +} + +#[inline(always)] +unsafe fn eq128_s2(x: __m128i, y: __m128i) -> bool { + let q = _mm_cmpeq_epi32(x, y); + let p = _mm_cvtsi128_si64(_mm_srli_si128(q, 8)); + let q = _mm_cvtsi128_si64(q); + (p & q) == -1 +} + +impl PartialEq for u32x4_sse2 { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { eq128_s2(self.x, rhs.x) } + } +} +impl Debug for u32x4_sse2 +where + Self: Copy + MultiLane<[u32; 4]>, +{ + #[cold] + fn fmt(&self, fmt: &mut Formatter) -> Result { + fmt.write_fmt(format_args!("{:08x?}", &self.to_lanes())) + } +} + +impl PartialEq for u64x2_sse2 { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + unsafe { eq128_s2(self.x, rhs.x) } + } +} +impl Debug for u64x2_sse2 +where + Self: Copy + MultiLane<[u64; 2]>, +{ + #[cold] + fn fmt(&self, fmt: &mut Formatter) -> Result { + fmt.write_fmt(format_args!("{:016x?}", &self.to_lanes())) + } +} + +impl Debug for u64x4_sse2 +where + u64x2_sse2: Copy + MultiLane<[u64; 2]>, +{ + #[cold] + fn fmt(&self, fmt: &mut Formatter) -> Result { + let (a, b) = (self.0[0].to_lanes(), self.0[1].to_lanes()); + fmt.write_fmt(format_args!("{:016x?}", &[a[0], a[1], b[0], b[1]])) + } +} + +#[cfg(test)] +#[cfg(target_arch = "x86_64")] +mod test { + use super::*; + use crate::x86_64::{SSE2, SSE41, SSSE3}; + use crate::Machine; + + #[test] + #[cfg_attr(not(target_feature = "ssse3"), ignore)] + fn test_bswap32_s2_vs_s3() { + let xs = [0x0f0e_0d0c, 0x0b0a_0908, 0x0706_0504, 0x0302_0100]; + let ys = [0x0c0d_0e0f, 0x0809_0a0b, 0x0405_0607, 0x0001_0203]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + + let x_s2 = { + let x_s2: ::u32x4 = s2.vec(xs); + x_s2.bswap() + }; + + let x_s3 = { + let x_s3: ::u32x4 = s3.vec(xs); + x_s3.bswap() + }; + + assert_eq!(x_s2, transmute!(x_s3)); + assert_eq!(x_s2, s2.vec(ys)); + } + + #[test] + #[cfg_attr(not(target_feature = "ssse3"), ignore)] + fn test_bswap64_s2_vs_s3() { + let xs = [0x0f0e_0d0c_0b0a_0908, 0x0706_0504_0302_0100]; + let ys = [0x0809_0a0b_0c0d_0e0f, 0x0001_0203_0405_0607]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + + let x_s2 = { + let x_s2: ::u64x2 = s2.vec(xs); + x_s2.bswap() + }; + + let x_s3 = { + let x_s3: ::u64x2 = s3.vec(xs); + x_s3.bswap() + }; + + assert_eq!(x_s2, s2.vec(ys)); + assert_eq!(x_s3, transmute!(x_s3)); + } + + #[test] + #[cfg_attr(not(target_feature = "ssse3"), ignore)] + fn test_shuffle32_s2_vs_s3() { + let xs = [0x0, 0x1, 0x2, 0x3]; + let ys = [0x2, 0x3, 0x0, 0x1]; + let zs = [0x1, 0x2, 0x3, 0x0]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + + let x_s2 = { + let x_s2: ::u32x4 = s2.vec(xs); + x_s2.shuffle2301() + }; + let x_s3 = { + let x_s3: ::u32x4 = s3.vec(xs); + x_s3.shuffle2301() + }; + assert_eq!(x_s2, s2.vec(ys)); + assert_eq!(x_s3, transmute!(x_s3)); + + let x_s2 = { + let x_s2: ::u32x4 = s2.vec(xs); + x_s2.shuffle3012() + }; + let x_s3 = { + let x_s3: ::u32x4 = s3.vec(xs); + x_s3.shuffle3012() + }; + assert_eq!(x_s2, s2.vec(zs)); + assert_eq!(x_s3, transmute!(x_s3)); + + let x_s2 = x_s2.shuffle1230(); + let x_s3 = x_s3.shuffle1230(); + assert_eq!(x_s2, s2.vec(xs)); + assert_eq!(x_s3, transmute!(x_s3)); + } + + #[test] + #[cfg_attr(not(target_feature = "ssse3"), ignore)] + fn test_shuffle64_s2_vs_s3() { + let xs = [0x0, 0x1, 0x2, 0x3]; + let ys = [0x2, 0x3, 0x0, 0x1]; + let zs = [0x1, 0x2, 0x3, 0x0]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + + let x_s2 = { + let x_s2: ::u64x4 = s2.vec(xs); + x_s2.shuffle2301() + }; + let x_s3 = { + let x_s3: ::u64x4 = s3.vec(xs); + x_s3.shuffle2301() + }; + assert_eq!(x_s2, s2.vec(ys)); + assert_eq!(x_s3, transmute!(x_s3)); + + let x_s2 = { + let x_s2: ::u64x4 = s2.vec(xs); + x_s2.shuffle3012() + }; + let x_s3 = { + let x_s3: ::u64x4 = s3.vec(xs); + x_s3.shuffle3012() + }; + assert_eq!(x_s2, s2.vec(zs)); + assert_eq!(x_s3, transmute!(x_s3)); + + let x_s2 = x_s2.shuffle1230(); + let x_s3 = x_s3.shuffle1230(); + assert_eq!(x_s2, s2.vec(xs)); + assert_eq!(x_s3, transmute!(x_s3)); + } + + #[cfg_attr(not(all(target_feature = "ssse3", target_feature = "sse4.1")), ignore)] + #[test] + fn test_lanes_u32x4() { + let xs = [0x1, 0x2, 0x3, 0x4]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + let s4 = unsafe { SSE41::instance() }; + + { + let x_s2: ::u32x4 = s2.vec(xs); + let y_s2 = ::u32x4::from_lanes(xs); + assert_eq!(x_s2, y_s2); + assert_eq!(xs, y_s2.to_lanes()); + } + + { + let x_s3: ::u32x4 = s3.vec(xs); + let y_s3 = ::u32x4::from_lanes(xs); + assert_eq!(x_s3, y_s3); + assert_eq!(xs, y_s3.to_lanes()); + } + + { + let x_s4: ::u32x4 = s4.vec(xs); + let y_s4 = ::u32x4::from_lanes(xs); + assert_eq!(x_s4, y_s4); + assert_eq!(xs, y_s4.to_lanes()); + } + } + + #[test] + #[cfg_attr(not(all(target_feature = "ssse3", target_feature = "sse4.1")), ignore)] + fn test_lanes_u64x2() { + let xs = [0x1, 0x2]; + + let s2 = unsafe { SSE2::instance() }; + let s3 = unsafe { SSSE3::instance() }; + let s4 = unsafe { SSE41::instance() }; + + { + let x_s2: ::u64x2 = s2.vec(xs); + let y_s2 = ::u64x2::from_lanes(xs); + assert_eq!(x_s2, y_s2); + assert_eq!(xs, y_s2.to_lanes()); + } + + { + let x_s3: ::u64x2 = s3.vec(xs); + let y_s3 = ::u64x2::from_lanes(xs); + assert_eq!(x_s3, y_s3); + assert_eq!(xs, y_s3.to_lanes()); + } + + { + let x_s4: ::u64x2 = s4.vec(xs); + let y_s4 = ::u64x2::from_lanes(xs); + assert_eq!(x_s4, y_s4); + assert_eq!(xs, y_s4.to_lanes()); + } + } + + #[test] + fn test_vec4_u32x4_s2() { + let xs = [1, 2, 3, 4]; + let s2 = unsafe { SSE2::instance() }; + let x_s2: ::u32x4 = s2.vec(xs); + assert_eq!(x_s2.extract(0), 1); + assert_eq!(x_s2.extract(1), 2); + assert_eq!(x_s2.extract(2), 3); + assert_eq!(x_s2.extract(3), 4); + assert_eq!(x_s2.insert(0xf, 0), s2.vec([0xf, 2, 3, 4])); + assert_eq!(x_s2.insert(0xf, 1), s2.vec([1, 0xf, 3, 4])); + assert_eq!(x_s2.insert(0xf, 2), s2.vec([1, 2, 0xf, 4])); + assert_eq!(x_s2.insert(0xf, 3), s2.vec([1, 2, 3, 0xf])); + } + + #[test] + #[cfg_attr(not(all(target_feature = "ssse3", target_feature = "sse4.1")), ignore)] + fn test_vec4_u32x4_s4() { + let xs = [1, 2, 3, 4]; + let s4 = unsafe { SSE41::instance() }; + let x_s4: ::u32x4 = s4.vec(xs); + assert_eq!(x_s4.extract(0), 1); + assert_eq!(x_s4.extract(1), 2); + assert_eq!(x_s4.extract(2), 3); + assert_eq!(x_s4.extract(3), 4); + assert_eq!(x_s4.insert(0xf, 0), s4.vec([0xf, 2, 3, 4])); + assert_eq!(x_s4.insert(0xf, 1), s4.vec([1, 0xf, 3, 4])); + assert_eq!(x_s4.insert(0xf, 2), s4.vec([1, 2, 0xf, 4])); + assert_eq!(x_s4.insert(0xf, 3), s4.vec([1, 2, 3, 0xf])); + } + + #[test] + fn test_vec2_u64x2_s2() { + let xs = [0x1, 0x2]; + let s2 = unsafe { SSE2::instance() }; + let x_s2: ::u64x2 = s2.vec(xs); + assert_eq!(x_s2.extract(0), 1); + assert_eq!(x_s2.extract(1), 2); + assert_eq!(x_s2.insert(0xf, 0), s2.vec([0xf, 2])); + assert_eq!(x_s2.insert(0xf, 1), s2.vec([1, 0xf])); + } + + #[test] + #[cfg_attr(not(all(target_feature = "ssse3", target_feature = "sse4.1")), ignore)] + fn test_vec4_u64x2_s4() { + let xs = [0x1, 0x2]; + let s4 = unsafe { SSE41::instance() }; + let x_s4: ::u64x2 = s4.vec(xs); + assert_eq!(x_s4.extract(0), 1); + assert_eq!(x_s4.extract(1), 2); + assert_eq!(x_s4.insert(0xf, 0), s4.vec([0xf, 2])); + assert_eq!(x_s4.insert(0xf, 1), s4.vec([1, 0xf])); + } +} + +pub mod avx2 { + #![allow(non_camel_case_types)] + use crate::soft::{x2, x4}; + use crate::types::*; + use crate::x86_64::sse2::{u128x1_sse2, u32x4_sse2, G0}; + use crate::x86_64::{vec256_storage, vec512_storage, Avx2Machine, YesS3, YesS4}; + use core::arch::x86_64::*; + use core::marker::PhantomData; + use core::ops::*; + use zerocopy::transmute; + + zerocopy::cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone)] + pub struct u32x4x2_avx2 { + x: __m256i, + ni: PhantomData, + } + } + + impl u32x4x2_avx2 { + #[inline(always)] + fn new(x: __m256i) -> Self { + Self { x, ni: PhantomData } + } + } + + impl u32x4x2> for u32x4x2_avx2 where NI: Copy {} + impl Store for u32x4x2_avx2 { + #[inline(always)] + unsafe fn unpack(p: vec256_storage) -> Self { + Self::new(p.avx) + } + } + impl StoreBytes for u32x4x2_avx2 { + #[inline(always)] + unsafe fn unsafe_read_le(input: &[u8]) -> Self { + assert_eq!(input.len(), 32); + Self::new(_mm256_loadu_si256(input.as_ptr() as *const _)) + } + #[inline(always)] + unsafe fn unsafe_read_be(input: &[u8]) -> Self { + Self::unsafe_read_le(input).bswap() + } + #[inline(always)] + fn write_le(self, out: &mut [u8]) { + unsafe { + assert_eq!(out.len(), 32); + _mm256_storeu_si256(out.as_mut_ptr() as *mut _, self.x) + } + } + #[inline(always)] + fn write_be(self, out: &mut [u8]) { + self.bswap().write_le(out) + } + } + impl MultiLane<[u32x4_sse2; 2]> for u32x4x2_avx2 { + #[inline(always)] + fn to_lanes(self) -> [u32x4_sse2; 2] { + unsafe { + [ + u32x4_sse2::new(_mm256_extracti128_si256(self.x, 0)), + u32x4_sse2::new(_mm256_extracti128_si256(self.x, 1)), + ] + } + } + #[inline(always)] + fn from_lanes(x: [u32x4_sse2; 2]) -> Self { + Self::new(unsafe { _mm256_setr_m128i(x[0].x, x[1].x) }) + } + } + impl Vec2> for u32x4x2_avx2 { + #[inline(always)] + fn extract(self, i: u32) -> u32x4_sse2 { + unsafe { + match i { + 0 => u32x4_sse2::new(_mm256_extracti128_si256(self.x, 0)), + 1 => u32x4_sse2::new(_mm256_extracti128_si256(self.x, 1)), + _ => panic!(), + } + } + } + #[inline(always)] + fn insert(self, w: u32x4_sse2, i: u32) -> Self { + Self::new(unsafe { + match i { + 0 => _mm256_inserti128_si256(self.x, w.x, 0), + 1 => _mm256_inserti128_si256(self.x, w.x, 1), + _ => panic!(), + } + }) + } + } + impl BitOps32 for u32x4x2_avx2 where NI: Copy {} + impl ArithOps for u32x4x2_avx2 where NI: Copy {} + macro_rules! shuf_lane_bytes { + ($name:ident, $k0:expr, $k1:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { + _mm256_shuffle_epi8(self.x, _mm256_set_epi64x($k0, $k1, $k0, $k1)) + }) + } + }; + } + macro_rules! rotr_32 { + ($name:ident, $i:expr) => { + #[inline(always)] + fn $name(self) -> Self { + Self::new(unsafe { + _mm256_or_si256( + _mm256_srli_epi32(self.x, $i as i32), + _mm256_slli_epi32(self.x, 32 - $i as i32), + ) + }) + } + }; + } + impl RotateEachWord32 for u32x4x2_avx2 { + rotr_32!(rotate_each_word_right7, 7); + shuf_lane_bytes!( + rotate_each_word_right8, + 0x0c0f_0e0d_080b_0a09, + 0x0407_0605_0003_0201 + ); + rotr_32!(rotate_each_word_right11, 11); + rotr_32!(rotate_each_word_right12, 12); + shuf_lane_bytes!( + rotate_each_word_right16, + 0x0d0c_0f0e_0908_0b0a, + 0x0504_0706_0100_0302 + ); + rotr_32!(rotate_each_word_right20, 20); + shuf_lane_bytes!( + rotate_each_word_right24, + 0x0e0d_0c0f_0a09_080b, + 0x0605_0407_0201_0003 + ); + rotr_32!(rotate_each_word_right25, 25); + } + impl BitOps0 for u32x4x2_avx2 where NI: Copy {} + impl From> for vec256_storage { + #[inline(always)] + fn from(x: u32x4x2_avx2) -> Self { + Self { avx: x.x } + } + } + + macro_rules! impl_assign { + ($vec:ident, $Assign:ident, $assign_fn:ident, $bin_fn:ident) => { + impl $Assign for $vec + where + NI: Copy, + { + #[inline(always)] + fn $assign_fn(&mut self, rhs: Self) { + *self = self.$bin_fn(rhs); + } + } + }; + } + impl_assign!(u32x4x2_avx2, BitXorAssign, bitxor_assign, bitxor); + impl_assign!(u32x4x2_avx2, BitOrAssign, bitor_assign, bitor); + impl_assign!(u32x4x2_avx2, BitAndAssign, bitand_assign, bitand); + impl_assign!(u32x4x2_avx2, AddAssign, add_assign, add); + + macro_rules! impl_bitop { + ($vec:ident, $Op:ident, $op_fn:ident, $impl_fn:ident) => { + impl $Op for $vec { + type Output = Self; + #[inline(always)] + fn $op_fn(self, rhs: Self) -> Self::Output { + Self::new(unsafe { $impl_fn(self.x, rhs.x) }) + } + } + }; + } + impl_bitop!(u32x4x2_avx2, BitXor, bitxor, _mm256_xor_si256); + impl_bitop!(u32x4x2_avx2, BitOr, bitor, _mm256_or_si256); + impl_bitop!(u32x4x2_avx2, BitAnd, bitand, _mm256_and_si256); + impl_bitop!(u32x4x2_avx2, AndNot, andnot, _mm256_andnot_si256); + impl_bitop!(u32x4x2_avx2, Add, add, _mm256_add_epi32); + + impl Not for u32x4x2_avx2 { + type Output = Self; + #[inline(always)] + fn not(self) -> Self::Output { + unsafe { + let f = _mm256_set1_epi8(-0x7f); + Self::new(f) ^ self + } + } + } + + impl BSwap for u32x4x2_avx2 { + shuf_lane_bytes!(bswap, 0x0c0d_0e0f_0809_0a0b, 0x0405_0607_0001_0203); + } + + impl From, G0>> for u32x4x2_avx2 + where + NI: Copy, + { + #[inline(always)] + fn from(x: x2, G0>) -> Self { + Self::new(unsafe { _mm256_setr_m128i(x.0[0].x, x.0[1].x) }) + } + } + + impl LaneWords4 for u32x4x2_avx2 { + #[inline(always)] + fn shuffle_lane_words1230(self) -> Self { + Self::new(unsafe { _mm256_shuffle_epi32(self.x, 0b1001_0011) }) + } + #[inline(always)] + fn shuffle_lane_words2301(self) -> Self { + Self::new(unsafe { _mm256_shuffle_epi32(self.x, 0b0100_1110) }) + } + #[inline(always)] + fn shuffle_lane_words3012(self) -> Self { + Self::new(unsafe { _mm256_shuffle_epi32(self.x, 0b0011_1001) }) + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// + + pub type u32x4x4_avx2 = x2, G0>; + impl u32x4x4> for u32x4x4_avx2 {} + + impl Store for u32x4x4_avx2 { + #[inline(always)] + unsafe fn unpack(p: vec512_storage) -> Self { + Self::new([ + u32x4x2_avx2::unpack(p.avx[0]), + u32x4x2_avx2::unpack(p.avx[1]), + ]) + } + } + impl MultiLane<[u32x4_sse2; 4]> for u32x4x4_avx2 { + #[inline(always)] + fn to_lanes(self) -> [u32x4_sse2; 4] { + let [a, b] = self.0[0].to_lanes(); + let [c, d] = self.0[1].to_lanes(); + [a, b, c, d] + } + #[inline(always)] + fn from_lanes(x: [u32x4_sse2; 4]) -> Self { + let ab = u32x4x2_avx2::from_lanes([x[0], x[1]]); + let cd = u32x4x2_avx2::from_lanes([x[2], x[3]]); + Self::new([ab, cd]) + } + } + impl Vec4> for u32x4x4_avx2 { + #[inline(always)] + fn extract(self, i: u32) -> u32x4_sse2 { + match i { + 0 => self.0[0].extract(0), + 1 => self.0[0].extract(1), + 2 => self.0[1].extract(0), + 3 => self.0[1].extract(1), + _ => panic!(), + } + } + #[inline(always)] + fn insert(self, w: u32x4_sse2, i: u32) -> Self { + Self::new(match i { + 0 | 1 => [self.0[0].insert(w, i), self.0[1]], + 2 | 3 => [self.0[0], self.0[1].insert(w, i - 2)], + _ => panic!(), + }) + } + } + impl Vec4Ext> for u32x4x4_avx2 { + #[inline(always)] + fn transpose4(a: Self, b: Self, c: Self, d: Self) -> (Self, Self, Self, Self) { + /* + * a00:a01 a10:a11 + * b00:b01 b10:b11 + * c00:c01 c10:c11 + * d00:d01 d10:d11 + * => + * a00:b00 c00:d00 + * a01:b01 c01:d01 + * a10:b10 c10:d10 + * a11:b11 c11:d11 + */ + unsafe { + let ab00 = u32x4x2_avx2::new(_mm256_permute2x128_si256(a.0[0].x, b.0[0].x, 0x20)); + let ab01 = u32x4x2_avx2::new(_mm256_permute2x128_si256(a.0[0].x, b.0[0].x, 0x31)); + let ab10 = u32x4x2_avx2::new(_mm256_permute2x128_si256(a.0[1].x, b.0[1].x, 0x20)); + let ab11 = u32x4x2_avx2::new(_mm256_permute2x128_si256(a.0[1].x, b.0[1].x, 0x31)); + let cd00 = u32x4x2_avx2::new(_mm256_permute2x128_si256(c.0[0].x, d.0[0].x, 0x20)); + let cd01 = u32x4x2_avx2::new(_mm256_permute2x128_si256(c.0[0].x, d.0[0].x, 0x31)); + let cd10 = u32x4x2_avx2::new(_mm256_permute2x128_si256(c.0[1].x, d.0[1].x, 0x20)); + let cd11 = u32x4x2_avx2::new(_mm256_permute2x128_si256(c.0[1].x, d.0[1].x, 0x31)); + ( + Self::new([ab00, cd00]), + Self::new([ab01, cd01]), + Self::new([ab10, cd10]), + Self::new([ab11, cd11]), + ) + } + } + } + impl Vector<[u32; 16]> for u32x4x4_avx2 { + #[inline(always)] + fn to_scalars(self) -> [u32; 16] { + transmute!(self) + } + } + impl From> for vec512_storage { + #[inline(always)] + fn from(x: u32x4x4_avx2) -> Self { + Self { + avx: [ + vec256_storage { avx: x.0[0].x }, + vec256_storage { avx: x.0[1].x }, + ], + } + } + } + impl From>> for u32x4x4_avx2 { + #[inline(always)] + fn from(x: x4>) -> Self { + Self::new(unsafe { + [ + u32x4x2_avx2::new(_mm256_setr_m128i(x.0[0].x, x.0[1].x)), + u32x4x2_avx2::new(_mm256_setr_m128i(x.0[2].x, x.0[3].x)), + ] + }) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"962425caf531d66ad4b3d6b2fce020314754dbbcafc8bcd4e36b67b92229668b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a7e6d152cdc6ea603077e50b8d55af374d9d21fd9f62d08a008588b17d785e6e","build.rs":"fdf8aa9b5441b298c72ae23645e227adc52ac69d2decc1bda04e1a91f70ff87d","examples/input.rs":"53350088f12a346a99034af41ef432dedcc9e5d581c5592d9aae3807c42656c1","examples/output.prettyplease.rs":"fa63c118daadb64c456ec5b8d5e46e5d7fabbbeb6a6e61a08eabc23360a18fbd","examples/output.rustc.rs":"0c66f8929fa40a2822d4ea1aec3d8b83db598aba043b17f3c1a6133f0d657135","examples/output.rustfmt.rs":"914a9aea1c51e097bfd80c9af4011811e6126c9df5fb0eac3d40b1203fba7c58","src/algorithm.rs":"7a4a7b62f5300aabf7fcff3cd8c8aaa3ae1e3d1dc717eea1e4797988ce0e18c7","src/attr.rs":"54e829ae468f22c8e2853d669515575f1444bfee026cfd9b19538f77caf10ab7","src/convenience.rs":"dd392b009b691d3587c7d8e3caeaacf450303c4223792b5f89c336358e371c39","src/data.rs":"9db6623d3ccc79b541a28bdc88875ad0036576689e085007eb362819f8e9a2d3","src/expr.rs":"b750a8b63b24b0800988749ac2d82b33381232ed2ff4c2dc4fcc0c0f337cb6e3","src/file.rs":"5689efa3c5959a6a0d8cfc2c13bf8a37ab0669e2b81dbded3f3c28884a88fca0","src/generics.rs":"60df8d54fe81279bcdf790e027eb5e6f80798ffd0873fa0f5bdff921582df397","src/item.rs":"711f2c9a00e9577c058d38cf3e521390f77cb7d0a36955353a4fac2b64af2a4b","src/iter.rs":"38b2cd3b38719c6024fb6b3aa739f6f8736c83193fd21e2365d4f6c27bc41666","src/lib.rs":"2bc04803e06aba238c3dd0386b25c4325d57d8b98fb6974be45d4c02ac90002f","src/lifetime.rs":"6d420430168185b2da3409bc38a45f63cced9443915f04e6aec71367fc070dcf","src/lit.rs":"9ea6d25533e64df4ff01c084fa1c31ddf64fb3b159409eec7d80dbf281e5171e","src/mac.rs":"62911747c308187afc750b4bd4f8bd24ee825081043d78da68a001ea55ab5853","src/pat.rs":"d130b141a3fd8098913cb179efe6600a5f010a2719447ecb3d4fb29e9b546220","src/path.rs":"b9c78a53c433678140b5a0e4044872989f25db2fe4fd44123e2500efbde671eb","src/ring.rs":"e23d133209b977e457b07b0cd93b3711d01f4172d7cfa4cf6a7247637390e606","src/stmt.rs":"c9328d8e5111087ed0f8226b9765ddc636e17cb9e4f86301794bb9d3a27cb39a","src/token.rs":"c288b1d81f2a35673d4ca1dd10d3386670b067460121df3038303e1ed73b41a7","src/ty.rs":"b5fa5f318c5e4593ed3eed4707e63dceaa62eea4ecdfba0f59bd946917ca3dbd","tests/test.rs":"04994ad0a37c43457390f11ade6ab74fc26c5e879b0a374f0b64acb530a0a496"},"package":"5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"9c52181d1c40a55ccf6f6d89b096ac59f84f96a98a8b4e9e8380bcefe289ee51",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"2f391c47ef4230c2b58d9a85d472e478cf4fcb33b5c50e2b55541cfb148dbc89","Cargo.toml":"962425caf531d66ad4b3d6b2fce020314754dbbcafc8bcd4e36b67b92229668b","Cargo.toml.orig":"c5e435b0003d71fe090f0bf58c9a1b6a23a823f2a16e133e17d42cec656690ee","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a7e6d152cdc6ea603077e50b8d55af374d9d21fd9f62d08a008588b17d785e6e","build.rs":"fdf8aa9b5441b298c72ae23645e227adc52ac69d2decc1bda04e1a91f70ff87d","examples/.tokeignore":"23ab7a9f335a33747ebbc74f39c81b145cb7928e7fefe8055ca4db0a4fac7557","examples/input.rs":"53350088f12a346a99034af41ef432dedcc9e5d581c5592d9aae3807c42656c1","examples/output.prettyplease.rs":"fa63c118daadb64c456ec5b8d5e46e5d7fabbbeb6a6e61a08eabc23360a18fbd","examples/output.rustc.rs":"0c66f8929fa40a2822d4ea1aec3d8b83db598aba043b17f3c1a6133f0d657135","examples/output.rustfmt.rs":"914a9aea1c51e097bfd80c9af4011811e6126c9df5fb0eac3d40b1203fba7c58","src/algorithm.rs":"7a4a7b62f5300aabf7fcff3cd8c8aaa3ae1e3d1dc717eea1e4797988ce0e18c7","src/attr.rs":"54e829ae468f22c8e2853d669515575f1444bfee026cfd9b19538f77caf10ab7","src/convenience.rs":"dd392b009b691d3587c7d8e3caeaacf450303c4223792b5f89c336358e371c39","src/data.rs":"9db6623d3ccc79b541a28bdc88875ad0036576689e085007eb362819f8e9a2d3","src/expr.rs":"b750a8b63b24b0800988749ac2d82b33381232ed2ff4c2dc4fcc0c0f337cb6e3","src/file.rs":"5689efa3c5959a6a0d8cfc2c13bf8a37ab0669e2b81dbded3f3c28884a88fca0","src/generics.rs":"60df8d54fe81279bcdf790e027eb5e6f80798ffd0873fa0f5bdff921582df397","src/item.rs":"711f2c9a00e9577c058d38cf3e521390f77cb7d0a36955353a4fac2b64af2a4b","src/iter.rs":"38b2cd3b38719c6024fb6b3aa739f6f8736c83193fd21e2365d4f6c27bc41666","src/lib.rs":"2bc04803e06aba238c3dd0386b25c4325d57d8b98fb6974be45d4c02ac90002f","src/lifetime.rs":"6d420430168185b2da3409bc38a45f63cced9443915f04e6aec71367fc070dcf","src/lit.rs":"9ea6d25533e64df4ff01c084fa1c31ddf64fb3b159409eec7d80dbf281e5171e","src/mac.rs":"62911747c308187afc750b4bd4f8bd24ee825081043d78da68a001ea55ab5853","src/pat.rs":"d130b141a3fd8098913cb179efe6600a5f010a2719447ecb3d4fb29e9b546220","src/path.rs":"b9c78a53c433678140b5a0e4044872989f25db2fe4fd44123e2500efbde671eb","src/ring.rs":"e23d133209b977e457b07b0cd93b3711d01f4172d7cfa4cf6a7247637390e606","src/stmt.rs":"c9328d8e5111087ed0f8226b9765ddc636e17cb9e4f86301794bb9d3a27cb39a","src/token.rs":"c288b1d81f2a35673d4ca1dd10d3386670b067460121df3038303e1ed73b41a7","src/ty.rs":"b5fa5f318c5e4593ed3eed4707e63dceaa62eea4ecdfba0f59bd946917ca3dbd","tests/test.rs":"04994ad0a37c43457390f11ade6ab74fc26c5e879b0a374f0b64acb530a0a496"},"package":"5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e0d74e690006a2cdc89db8c45091ae123bf41c53" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,113 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.60.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - run: cargo check + - run: cargo check --features verbatim + - run: cargo test + env: + RUSTFLAGS: ${{env.RUSTFLAGS}} ${{matrix.rust == 'nightly' && '--cfg exhaustive' || ''}} + + examples: + name: Examples + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: llvm-tools, rustc-dev, rustfmt + - run: cargo run --manifest-path examples/update/Cargo.toml + - run: git diff --exit-code + - run: cargo run --manifest-path cargo-expand/update/Cargo.toml + - run: git diff --exit-code + + fuzz: + name: Fuzz + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz check + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --features verbatim -- -Dclippy::all -Dclippy::pedantic + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +[package] +name = "prettyplease" +version = "0.2.19" +authors = ["David Tolnay "] +autoexamples = false +categories = ["development-tools"] +description = "A minimal `syn` syntax tree pretty-printer" +documentation = "https://docs.rs/prettyplease" +edition = "2021" +exclude = ["cargo-expand"] +keywords = ["rustfmt"] +license = "MIT OR Apache-2.0" +links = "prettyplease02" +repository = "https://github.com/dtolnay/prettyplease" +rust-version = "1.60" + +[features] +verbatim = ["syn/parsing"] + +[dependencies] +proc-macro2 = { version = "1.0.80", default-features = false } +syn = { version = "2.0.59", default-features = false, features = ["full"] } + +[dev-dependencies] +indoc = "2" +proc-macro2 = { version = "1.0.80", default-features = false } +quote = { version = "1.0.35", default-features = false } +syn = { version = "2.0.59", default-features = false, features = ["parsing"] } + +[lib] +doc-scrape-examples = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.playground] +features = ["verbatim"] + +[workspace] +members = ["cargo-expand/update", "examples/update"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/examples/.tokeignore clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/examples/.tokeignore --- clamav-1.4.3+dfsg/.cargo/vendor/prettyplease/examples/.tokeignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/prettyplease/examples/.tokeignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +*.rs diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/primal-check/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/primal-check/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"c0a0ae121190d17789db77a479a48ec033ba7c185b9f1b54fe47101a6470760e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6d3a9431e65e69c73a8923e6517b889d17549b23db406b9ec027710d16af701f","src/is_prime.rs":"fb7e6bcb2908b9b0d431015e61c13ec1208aedd8bf022964f5911a2008b85be9","src/lib.rs":"9f8d77f275abce70218c68fcf641116d5a863905cdbdedf63bff6b2636371679","src/perfect_power.rs":"a72c630a9ed37f84645f1d3c426197ca71ed891acf21111446a8ef5e359dd5bd"},"package":"9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"6b7f1271c2a367456bfed34545fba7a90f4d21260513dd01da75e55155896590","Cargo.toml":"c0a0ae121190d17789db77a479a48ec033ba7c185b9f1b54fe47101a6470760e","Cargo.toml.orig":"d47a441cd534b34747dd9778570bc8dde88f30c75a41115e001909db63122bbe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6d3a9431e65e69c73a8923e6517b889d17549b23db406b9ec027710d16af701f","src/is_prime.rs":"fb7e6bcb2908b9b0d431015e61c13ec1208aedd8bf022964f5911a2008b85be9","src/lib.rs":"9f8d77f275abce70218c68fcf641116d5a863905cdbdedf63bff6b2636371679","src/perfect_power.rs":"a72c630a9ed37f84645f1d3c426197ca71ed891acf21111446a8ef5e359dd5bd"},"package":"9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/primal-check/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/primal-check/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/primal-check/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ab58f001aa4f836cf226af999ab9e01e61308858" + }, + "path_in_vcs": "primal-check" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/primal-check/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/primal-check/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/primal-check/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/primal-check/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +[package] +name = "primal-check" +version = "0.3.3" +authors = ["Huon Wilson "] +edition = "2018" + +homepage = "https://github.com/huonw/primal" +repository = "https://github.com/huonw/primal" +documentation = "http://docs.rs/primal-check/" +license = "MIT OR Apache-2.0" +keywords = ["math", "mathematics", "primes", "number-theory"] + +description = """ +Fast standalone primality testing. +""" + +[dependencies] +num-integer = "0.1" + +[dev-dependencies] +primal = { path = "..", version = "0.3" } + +[features] +unstable = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"e8da19e7edc1b99758582bb1b22b37bea070ddd9c86eb4c4aea32029a6a46b13","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c609b6865476d6c35879784e9155367a97a0da496aa5c3c61488440a20f59883","build.rs":"7cd349266bac2d2acbd0adb43ab94b6ad6d4effbaac8e516172ae7f04c63ff4e","build/probe.rs":"971fd2178dc506ccdc5c2065c37b77696a4aee8e00330ca52625db4a857f68d3","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/extra.rs":"7c3864497cb5298fd5d0e9f5ae5797860338a9a4263220a8e8eabecda1583797","src/fallback.rs":"60a66c3a97f2d3962bf13d876b03bf12d899be3849d9af48ee765d814498422e","src/lib.rs":"876498c37412c62f5cc9875ce7d3e3de6e5a5ca0fdbca1adbc4184d249538b9e","src/location.rs":"f55d2e61f1bb1af65e14ed04c9e91eb1ddbf8430e8c05f2048d1cd538d27368e","src/marker.rs":"c11c5a1be8bdf18be3fcd224393f350a9aae7ce282e19ce583c84910c6903a8f","src/parse.rs":"4b77cddbc2752bc4d38a65acd8b96b6786c5220d19b1e1b37810257b5d24132d","src/rcvec.rs":"1c3c48c4f819927cc445ae15ca3bb06775feff2fd1cb21901ae4c40c7e6b4e82","src/wrapper.rs":"e41df9abc846b40f0cf01150d22b91944d07cde93bc72aa34798101652675844","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"473e962ee1aa0633dd5cf9a973b3bbd0ef43b740d4b7f6d008ff455a6b89d386","tests/test.rs":"9261ca13805a8311e9cb51d39cc9b0bfe0329496169c32d86558f25abf217a49","tests/test_fmt.rs":"b7743b612af65f2c88cbe109d50a093db7aa7e87f9e37bf45b7bbaeb240aa020","tests/test_size.rs":"acf05963c1e62052d769d237b50844a2c59b4182b491231b099a4f74e5456ab0"},"package":"3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"10fa24be9ebbce60045d729ffefa19cff2ce850959ca2ea8a4244773fa9962e5",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"9a9f80a475b96b7cc6d8925107b7d9cdb2c15607522ee4e92987d0db988a8937","Cargo.lock":"c4f3873028eb4641a071caf6305d1954f19c09c379ba7d17b96a486d04e56343","Cargo.toml":"7980427de55465c7dd0c7f72125e687bee70072c582ce0500043a1cdc55efbfb","Cargo.toml.orig":"8e681871e2f08a0a967a98bf5ed0d65a22638862ce87716bca6a45cfbd008346","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"9fb9e04cc2b889e838404d352920bc09c5a76a36536a2d1b44006472afdd0f8a","build.rs":"baeb20b52f6b536be8657a566591a507bb2e34a45cf8baa42b135510a0c3c729","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/extra.rs":"29f094473279a29b71c3cc9f5fa27c2e2c30c670390cf7e4b7cf451486cc857e","src/fallback.rs":"962e1897fefb138101ae3f6fda9c46cecff787550cdfb9133066326379464d90","src/lib.rs":"c48927ec6e1c8df1ead83bcb45e9f68f77c6361db8400be91b12bd7f2e013ada","src/location.rs":"9225c5a55f03b56cce42bc55ceb509e8216a5e0b24c94aa1cd071b04e3d6c15f","src/marker.rs":"c11c5a1be8bdf18be3fcd224393f350a9aae7ce282e19ce583c84910c6903a8f","src/num.rs":"82d625cbcd255965e46231ac3af1b74ab8bff9787c799e8ed1f978de146cb0b5","src/parse.rs":"bec389e2e6b1e8e005959ac05c8e1a291cb6a2679f0dac5b5180d3a4f47068dd","src/probe.rs":"2b57e8ebf46a7c60ee2762f23f16d24ee9ddb8f1acd0a7faf7a99cf2e4187151","src/probe/proc_macro_span.rs":"f3f9c728438060c9450d4568621beca9125f559eb65faab9574d2e43e9b49643","src/probe/proc_macro_span_file.rs":"a20a1920d121b153ce33c8e2ea203b9370606744847b62e8ffd0c657d2545778","src/probe/proc_macro_span_location.rs":"71a4768f65f8a87e5a3c2bc2e05fb84d2562a0f4733780e9f919563f25ee07dc","src/rcvec.rs":"a159d246cac59aae2d51b899471ce34766f51f3c11c376ac36ee501ee3f12a7a","src/rustc_literal_escaper.rs":"188cbe8fffe7af3899977530cbb1b6c0b1dff51623db0ec115db1e082159e7b6","src/wrapper.rs":"8caa6f0878493b14efb257d88aec2abbc44e22935e163465c7ac0a40d28127e2","tests/comments.rs":"11520f6baee23b9258db904f4c256fd3877493f754e2b99041f73a330e74a911","tests/features.rs":"7e52c0c801019b271bf11a994c2e1799a1429b0c1a3a34e551a23971797fe412","tests/marker.rs":"f16299460587d6c65603ed809f1a3b81853e4b99d6cb44d0b68bb07259d7e9f8","tests/test.rs":"7d58c3a754241ffdec84e4e9ac799852071db71d77359de164ca7ba6217020e9","tests/test_fmt.rs":"b7743b612af65f2c88cbe109d50a093db7aa7e87f9e37bf45b7bbaeb240aa020","tests/test_size.rs":"7ed5f07c3ccc74c4d09f3c1c43542fbbe23417146761558a0fd4659e19ae1afc"},"package":"9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "43213695a9a04a0e33a72595f3d635b45a7ed07a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [1.80.0, stable, beta] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - run: cargo test + - run: cargo test --no-default-features + - run: cargo test --features span-locations + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test + run: cargo test + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features + run: cargo test --no-default-features + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + + nightly: + name: Rust nightly + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout\ --cfg=randomize_layout >> $GITHUB_ENV + - run: cargo check + env: + RUSTFLAGS: --cfg procmacro2_nightly_testing ${{env.RUSTFLAGS}} + - run: cargo test + - run: cargo test --no-default-features + - run: cargo test --no-default-features --test features -- --ignored make_sure_no_proc_macro # run the ignored test to make sure the `proc-macro` feature is disabled + - run: cargo test --features span-locations + - run: cargo test --manifest-path tests/ui/Cargo.toml + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test + run: cargo test + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features + run: cargo test --no-default-features + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + - name: RUSTFLAGS='-Z allow-features=' cargo test + run: cargo test + env: + RUSTFLAGS: -Z allow-features= --cfg procmacro2_backtrace ${{env.RUSTFLAGS}} + - uses: actions/upload-artifact@v6 + if: always() + with: + name: Cargo.lock + path: Cargo.lock + continue-on-error: true + + layout: + name: Layout + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - run: cargo test --test test_size + - run: cargo test --test test_size --features span-locations + - run: cargo test --test test_size --no-default-features + - run: cargo test --test test_size --no-default-features --features span-locations + + msrv: + name: Rust 1.68.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@1.68.0 + with: + components: rust-src + - run: cargo check + - run: cargo check --no-default-features + - run: cargo check --features span-locations + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo check + run: cargo check + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo check --no-default-features + run: cargo check --no-default-features + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + webassembly: + name: WebAssembly + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + target: wasm32-unknown-unknown + components: rust-src + - name: Ignore WebAssembly linker warning + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Alinker_messages >> $GITHUB_ENV + - run: cargo test --target wasm32-unknown-unknown --no-run + + fuzz: + name: Fuzz + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz check + - run: cargo check --no-default-features --features afl + working-directory: fuzz + - uses: dtolnay/install@honggfuzz + - name: Run apt install binutils-dev libunwind-dev + run: | + sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf + sudo rm -f /var/lib/man-db/auto-update + sudo apt-get update + sudo apt-get install binutils-dev libunwind-dev + - run: cargo hfuzz build --no-default-features --features honggfuzz + working-directory: fuzz + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + - run: cargo clippy --tests --all-features -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,326 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", +] + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2" +version = "1.0.104" +dependencies = [ + "flate2", + "quote", + "rayon", + "rustversion", + "tar", + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2 1.0.103", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,13 +11,18 @@ [package] edition = "2021" -rust-version = "1.56" +rust-version = "1.68" name = "proc-macro2" -version = "1.0.81" +version = "1.0.104" authors = [ "David Tolnay ", "Alex Crichton ", ] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false autobenches = false description = "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case." documentation = "https://docs.rs/proc-macro2" @@ -31,24 +36,54 @@ repository = "https://github.com/dtolnay/proc-macro2" [package.metadata.docs.rs] -rustc-args = [ - "--cfg", - "procmacro2_semver_exempt", -] +rustc-args = ["--cfg=procmacro2_semver_exempt"] +targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ - "--cfg", - "procmacro2_semver_exempt", - "--cfg", - "doc_cfg", + "--cfg=procmacro2_semver_exempt", "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] -targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] features = ["span-locations"] +[features] +default = ["proc-macro"] +nightly = [] +proc-macro = [] +span-locations = [] + [lib] -doc-scrape-examples = false +name = "proc_macro2" +path = "src/lib.rs" + +[[test]] +name = "comments" +path = "tests/comments.rs" + +[[test]] +name = "features" +path = "tests/features.rs" + +[[test]] +name = "marker" +path = "tests/marker.rs" + +[[test]] +name = "test" +path = "tests/test.rs" + +[[test]] +name = "test_fmt" +path = "tests/test_fmt.rs" + +[[test]] +name = "test_size" +path = "tests/test_size.rs" [dependencies.unicode-ident] version = "1.0" @@ -58,7 +93,7 @@ [dev-dependencies.quote] version = "1.0" -default_features = false +default-features = false [dev-dependencies.rayon] version = "1.0" @@ -68,9 +103,3 @@ [dev-dependencies.tar] version = "0.4" - -[features] -default = ["proc-macro"] -nightly = [] -proc-macro = [] -span-locations = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,67 @@ +[package] +name = "proc-macro2" +version = "1.0.104" +authors = ["David Tolnay ", "Alex Crichton "] +autobenches = false +categories = ["development-tools::procedural-macro-helpers"] +description = "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case." +documentation = "https://docs.rs/proc-macro2" +edition = "2021" +keywords = ["macros", "syn"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/proc-macro2" +rust-version = "1.68" + +[package.metadata.docs.rs] +rustc-args = ["--cfg=procmacro2_semver_exempt"] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--cfg=procmacro2_semver_exempt", + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", +] + +[package.metadata.playground] +features = ["span-locations"] + +[dependencies] +unicode-ident = "1.0" + +[dev-dependencies] +flate2 = "1.0" +quote = { version = "1.0", default-features = false } +rayon = "1.0" +rustversion = "1" +tar = "0.4" + +[features] +proc-macro = [] +default = ["proc-macro"] + +# Expose methods Span::start and Span::end which give the line/column location +# of a token. +span-locations = [] + +# This feature no longer means anything. +nightly = [] + +[workspace] +members = ["benches/bench-libproc-macro", "tests/ui"] + +[patch.crates-io] +# Our doc tests depend on quote which depends on proc-macro2. Without this line, +# the proc-macro2 dependency of quote would be the released version of +# proc-macro2. Quote would implement its traits for types from that proc-macro2, +# meaning impls would be missing when tested against types from the local +# proc-macro2. +# +# GitHub Actions builds that are in progress at the time that you publish may +# spuriously fail. This is because they'll be building a local proc-macro2 which +# carries the second-most-recent version number, pulling in quote which resolves +# to a dependency on the just-published most recent version number. Thus the +# patch will fail to apply because the version numbers are different. +proc-macro2 = { path = "." } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/README.md clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -62,7 +62,7 @@ To opt into the additional APIs available in the most recent nightly compiler, the `procmacro2_semver_exempt` config flag must be passed to rustc. We will -polyfill those nightly-only APIs back to Rust 1.56.0. As these are unstable APIs +polyfill those nightly-only APIs back to Rust 1.68.0. As these are unstable APIs that track the nightly compiler, minor versions of proc-macro2 may make breaking changes to them at any time. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/build/probe.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build/probe.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/build/probe.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build/probe.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -// This code exercises the surface area that we expect of Span's unstable API. -// If the current toolchain is able to compile it, then proc-macro2 is able to -// offer these APIs too. - -#![feature(proc_macro_span)] - -extern crate proc_macro; - -use core::ops::{Range, RangeBounds}; -use proc_macro::{Literal, Span}; - -pub fn byte_range(this: &Span) -> Range { - this.byte_range() -} - -pub fn join(this: &Span, other: Span) -> Option { - this.join(other) -} - -pub fn subspan>(this: &Literal, range: R) -> Option { - this.subspan(range) -} - -// Include in sccache cache key. -const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/build.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/build.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,41 +1,11 @@ -// rustc-cfg emitted by the build script: -// -// "wrap_proc_macro" -// Wrap types from libproc_macro rather than polyfilling the whole API. -// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set, -// because we can't emulate the unstable API without emulating everything -// else. Also enabled unconditionally on nightly, in which case the -// procmacro2_semver_exempt surface area is implemented by using the -// nightly-only proc_macro API. -// -// "hygiene" -// Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at -// and Span::located_at. Enabled on Rust 1.45+. -// -// "proc_macro_span" -// Enable non-dummy behavior of Span::start and Span::end methods which -// requires an unstable compiler feature. Enabled when building with -// nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable -// features. -// -// "super_unstable" -// Implement the semver exempt API in terms of the nightly-only proc_macro -// API. Enabled when using procmacro2_semver_exempt on a nightly compiler. -// -// "span_locations" -// Provide methods Span::start and Span::end which give the line/column -// location of a token. Enabled by procmacro2_semver_exempt or the -// "span-locations" Cargo cfg. This is behind a cfg because tracking -// location inside spans is a performance hit. -// -// "is_available" -// Use proc_macro::is_available() to detect if the proc macro API is -// available or needs to be polyfilled instead of trying to use the proc -// macro API and catching a panic if it isn't available. Enabled on Rust -// 1.57+. +#![allow(unknown_lints)] +#![allow(unexpected_cfgs)] +#![allow(clippy::uninlined_format_args)] use std::env; use std::ffi::OsString; +use std::fs; +use std::io::ErrorKind; use std::iter; use std::path::Path; use std::process::{self, Command, Stdio}; @@ -44,26 +14,54 @@ fn main() { let rustc = rustc_minor_version().unwrap_or(u32::MAX); - let docs_rs = env::var_os("DOCS_RS").is_some(); - let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs; + if rustc >= 80 { + println!("cargo:rustc-check-cfg=cfg(fuzzing)"); + println!("cargo:rustc-check-cfg=cfg(no_is_available)"); + println!("cargo:rustc-check-cfg=cfg(no_literal_byte_character)"); + println!("cargo:rustc-check-cfg=cfg(no_literal_c_string)"); + println!("cargo:rustc-check-cfg=cfg(no_source_text)"); + println!("cargo:rustc-check-cfg=cfg(proc_macro_span)"); + println!("cargo:rustc-check-cfg=cfg(proc_macro_span_file)"); + println!("cargo:rustc-check-cfg=cfg(proc_macro_span_location)"); + println!("cargo:rustc-check-cfg=cfg(procmacro2_backtrace)"); + println!("cargo:rustc-check-cfg=cfg(procmacro2_build_probe)"); + println!("cargo:rustc-check-cfg=cfg(procmacro2_nightly_testing)"); + println!("cargo:rustc-check-cfg=cfg(procmacro2_semver_exempt)"); + println!("cargo:rustc-check-cfg=cfg(randomize_layout)"); + println!("cargo:rustc-check-cfg=cfg(span_locations)"); + println!("cargo:rustc-check-cfg=cfg(super_unstable)"); + println!("cargo:rustc-check-cfg=cfg(wrap_proc_macro)"); + } + + let semver_exempt = cfg!(procmacro2_semver_exempt); if semver_exempt { // https://github.com/dtolnay/proc-macro2/issues/147 println!("cargo:rustc-cfg=procmacro2_semver_exempt"); } if semver_exempt || cfg!(feature = "span-locations") { + // Provide methods Span::start and Span::end which give the line/column + // location of a token. This is behind a cfg because tracking location + // inside spans is a performance hit. println!("cargo:rustc-cfg=span_locations"); } if rustc < 57 { + // Do not use proc_macro::is_available() to detect whether the proc + // macro API is available vs needs to be polyfilled. Instead, use the + // proc macro API unconditionally and catch the panic that occurs if it + // isn't available. println!("cargo:rustc-cfg=no_is_available"); } if rustc < 66 { + // Do not call libproc_macro's Span::source_text. Always return None. println!("cargo:rustc-cfg=no_source_text"); } if rustc < 79 { + // Do not call Literal::byte_character nor Literal::c_string. They can + // be emulated by way of Literal::from_str. println!("cargo:rustc-cfg=no_literal_byte_character"); println!("cargo:rustc-cfg=no_literal_c_string"); } @@ -73,18 +71,16 @@ return; } - println!("cargo:rerun-if-changed=build/probe.rs"); - let proc_macro_span; let consider_rustc_bootstrap; - if compile_probe(false) { + if compile_probe_unstable("proc_macro_span", false) { // This is a nightly or dev compiler, so it supports unstable features // regardless of RUSTC_BOOTSTRAP. No need to rerun build script if // RUSTC_BOOTSTRAP is changed. proc_macro_span = true; consider_rustc_bootstrap = false; } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { - if compile_probe(true) { + if compile_probe_unstable("proc_macro_span", true) { // This is a stable or beta compiler for which the user has set // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script // if they change it. @@ -111,14 +107,38 @@ } if proc_macro_span || !semver_exempt { + // Wrap types from libproc_macro rather than polyfilling the whole API. + // Enabled as long as procmacro2_semver_exempt is not set, because we + // can't emulate the unstable API without emulating everything else. + // Also enabled unconditionally on nightly, in which case the + // procmacro2_semver_exempt surface area is implemented by using the + // nightly-only proc_macro API. println!("cargo:rustc-cfg=wrap_proc_macro"); } if proc_macro_span { + // Enable non-dummy behavior of Span::byte_range and Span::join methods + // which requires an unstable compiler feature. Enabled when building + // with nightly, unless `-Z allow-feature` in RUSTFLAGS disallows + // unstable features. println!("cargo:rustc-cfg=proc_macro_span"); } + if proc_macro_span || (rustc >= 88 && compile_probe_stable("proc_macro_span_location")) { + // Enable non-dummy behavior of Span::start and Span::end methods on + // Rust 1.88+. + println!("cargo:rustc-cfg=proc_macro_span_location"); + } + + if proc_macro_span || (rustc >= 88 && compile_probe_stable("proc_macro_span_file")) { + // Enable non-dummy behavior of Span::file and Span::local_file methods + // on Rust 1.88+. + println!("cargo:rustc-cfg=proc_macro_span_file"); + } + if semver_exempt && proc_macro_span { + // Implement the semver exempt API in terms of the nightly-only + // proc_macro API. println!("cargo:rustc-cfg=super_unstable"); } @@ -127,21 +147,38 @@ } } -fn compile_probe(rustc_bootstrap: bool) -> bool { - if env::var_os("RUSTC_STAGE").is_some() { - // We are running inside rustc bootstrap. This is a highly non-standard - // environment with issues such as: - // - // https://github.com/rust-lang/cargo/issues/11138 - // https://github.com/rust-lang/rust/issues/114839 - // - // Let's just not use nightly features here. - return false; - } +fn compile_probe_unstable(feature: &str, rustc_bootstrap: bool) -> bool { + // RUSTC_STAGE indicates that this crate is being compiled as a dependency + // of a multistage rustc bootstrap. This environment uses Cargo in a highly + // non-standard way with issues such as: + // + // https://github.com/rust-lang/cargo/issues/11138 + // https://github.com/rust-lang/rust/issues/114839 + // + env::var_os("RUSTC_STAGE").is_none() && do_compile_probe(feature, rustc_bootstrap) +} + +fn compile_probe_stable(feature: &str) -> bool { + env::var_os("RUSTC_STAGE").is_some() || do_compile_probe(feature, true) +} + +fn do_compile_probe(feature: &str, rustc_bootstrap: bool) -> bool { + println!("cargo:rerun-if-changed=src/probe/{}.rs", feature); let rustc = cargo_env_var("RUSTC"); let out_dir = cargo_env_var("OUT_DIR"); - let probefile = Path::new("build").join("probe.rs"); + let out_subdir = Path::new(&out_dir).join("probe"); + let probefile = Path::new("src") + .join("probe") + .join(feature) + .with_extension("rs"); + + if let Err(err) = fs::create_dir(&out_subdir) { + if err.kind() != ErrorKind::AlreadyExists { + eprintln!("Failed to create {}: {}", out_subdir.display(), err); + process::exit(1); + } + } let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let rustc_workspace_wrapper = @@ -158,13 +195,14 @@ } cmd.stderr(Stdio::null()) + .arg("--cfg=procmacro2_build_probe") .arg("--edition=2021") .arg("--crate-name=proc_macro2") .arg("--crate-type=lib") .arg("--cap-lints=allow") .arg("--emit=dep-info,metadata") .arg("--out-dir") - .arg(out_dir) + .arg(&out_subdir) .arg(probefile); if let Some(target) = env::var_os("TARGET") { @@ -180,10 +218,31 @@ } } - match cmd.status() { + let success = match cmd.status() { Ok(status) => status.success(), Err(_) => false, + }; + + // Clean up to avoid leaving nondeterministic absolute paths in the dep-info + // file in OUT_DIR, which causes nonreproducible builds in build systems + // that treat the entire OUT_DIR as an artifact. + if let Err(err) = fs::remove_dir_all(&out_subdir) { + // libc::ENOTEMPTY + // Some filesystems (NFSv3) have timing issues under load where '.nfs*' + // dummy files can continue to get created for a short period after the + // probe command completes, breaking remove_dir_all. + // To be replaced with ErrorKind::DirectoryNotEmpty (Rust 1.83+). + const ENOTEMPTY: i32 = 39; + + if !(err.kind() == ErrorKind::NotFound + || (cfg!(target_os = "linux") && err.raw_os_error() == Some(ENOTEMPTY))) + { + eprintln!("Failed to clean up {}: {}", out_subdir.display(), err); + process::exit(1); + } } + + success } fn rustc_minor_version() -> Option { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/extra.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/extra.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/extra.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/extra.rs 2006-07-24 01:21:28.000000000 +0000 @@ -69,7 +69,7 @@ /// This function is not applicable to and will panic if called from a /// procedural macro. #[cfg(span_locations)] -#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] +#[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn invalidate_current_thread_spans() { crate::imp::invalidate_current_thread_spans(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/fallback.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/fallback.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/fallback.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/fallback.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,5 @@ +#[cfg(wrap_proc_macro)] +use crate::imp; #[cfg(span_locations)] use crate::location::LineColumn; use crate::parse::{self, Cursor}; @@ -9,15 +11,21 @@ use core::cell::RefCell; #[cfg(span_locations)] use core::cmp; +#[cfg(all(span_locations, not(fuzzing)))] +use core::cmp::Ordering; use core::fmt::{self, Debug, Display, Write}; use core::mem::ManuallyDrop; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::ptr; -use core::str::{self, FromStr}; +use core::str; +#[cfg(feature = "proc-macro")] +use core::str::FromStr; use std::ffi::CStr; -#[cfg(procmacro2_semver_exempt)] +#[cfg(wrap_proc_macro)] +use std::panic; +#[cfg(span_locations)] use std::path::PathBuf; /// Force use of proc-macro2's fallback implementation of the API for now, even @@ -57,13 +65,31 @@ } impl TokenStream { - pub fn new() -> Self { + pub(crate) fn new() -> Self { TokenStream { inner: RcVecBuilder::new().build(), } } - pub fn is_empty(&self) -> bool { + pub(crate) fn from_str_checked(src: &str) -> Result { + // Create a dummy file & add it to the source map + let mut cursor = get_cursor(src); + + // Strip a byte order mark if present + const BYTE_ORDER_MARK: &str = "\u{feff}"; + if cursor.starts_with(BYTE_ORDER_MARK) { + cursor = cursor.advance(BYTE_ORDER_MARK.len()); + } + + parse::token_stream(cursor) + } + + #[cfg(feature = "proc-macro")] + pub(crate) fn from_str_unchecked(src: &str) -> Self { + Self::from_str_checked(src).unwrap() + } + + pub(crate) fn is_empty(&self) -> bool { self.inner.len() == 0 } @@ -101,21 +127,32 @@ // Nonrecursive to prevent stack overflow. impl Drop for TokenStream { fn drop(&mut self) { - let mut inner = match self.inner.get_mut() { - Some(inner) => inner, + let mut stack = Vec::new(); + let mut current = match self.inner.get_mut() { + Some(inner) => inner.take().into_iter(), None => return, }; - while let Some(token) = inner.pop() { - let group = match token { - TokenTree::Group(group) => group.inner, - _ => continue, - }; - #[cfg(wrap_proc_macro)] - let group = match group { - crate::imp::Group::Fallback(group) => group, - crate::imp::Group::Compiler(_) => continue, - }; - inner.extend(group.stream.take_inner()); + loop { + while let Some(token) = current.next() { + let group = match token { + TokenTree::Group(group) => group.inner, + _ => continue, + }; + #[cfg(wrap_proc_macro)] + let group = match group { + crate::imp::Group::Fallback(group) => group, + crate::imp::Group::Compiler(_) => continue, + }; + let mut group = group; + if let Some(inner) = group.stream.inner.get_mut() { + stack.push(current); + current = inner.take().into_iter(); + } + } + match stack.pop() { + Some(next) => current = next, + None => return, + } } } } @@ -125,23 +162,23 @@ } impl TokenStreamBuilder { - pub fn new() -> Self { + pub(crate) fn new() -> Self { TokenStreamBuilder { inner: RcVecBuilder::new(), } } - pub fn with_capacity(cap: usize) -> Self { + pub(crate) fn with_capacity(cap: usize) -> Self { TokenStreamBuilder { inner: RcVecBuilder::with_capacity(cap), } } - pub fn push_token_from_parser(&mut self, tt: TokenTree) { + pub(crate) fn push_token_from_parser(&mut self, tt: TokenTree) { self.inner.push(tt); } - pub fn build(self) -> TokenStream { + pub(crate) fn build(self) -> TokenStream { TokenStream { inner: self.inner.build(), } @@ -170,23 +207,6 @@ Cursor { rest: src } } -impl FromStr for TokenStream { - type Err = LexError; - - fn from_str(src: &str) -> Result { - // Create a dummy file & add it to the source map - let mut cursor = get_cursor(src); - - // Strip a byte order mark if present - const BYTE_ORDER_MARK: &str = "\u{feff}"; - if cursor.starts_with(BYTE_ORDER_MARK) { - cursor = cursor.advance(BYTE_ORDER_MARK.len()); - } - - parse::token_stream(cursor) - } -} - impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("cannot parse string into token stream") @@ -202,13 +222,13 @@ } joint = false; match tt { - TokenTree::Group(tt) => Display::fmt(tt, f), - TokenTree::Ident(tt) => Display::fmt(tt, f), + TokenTree::Group(tt) => write!(f, "{}", tt), + TokenTree::Ident(tt) => write!(f, "{}", tt), TokenTree::Punct(tt) => { joint = tt.spacing() == Spacing::Joint; - Display::fmt(tt, f) + write!(f, "{}", tt) } - TokenTree::Literal(tt) => Display::fmt(tt, f), + TokenTree::Literal(tt) => write!(f, "{}", tt), }?; } @@ -226,20 +246,14 @@ #[cfg(feature = "proc-macro")] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { - inner - .to_string() - .parse() - .expect("compiler token stream parse failed") + TokenStream::from_str_unchecked(&inner.to_string()) } } #[cfg(feature = "proc-macro")] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { - inner - .to_string() - .parse() - .expect("failed to parse to compiler tokens") + proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) } } @@ -299,34 +313,6 @@ } } -#[cfg(procmacro2_semver_exempt)] -#[derive(Clone, PartialEq, Eq)] -pub(crate) struct SourceFile { - path: PathBuf, -} - -#[cfg(procmacro2_semver_exempt)] -impl SourceFile { - /// Get the path to this source file as a string. - pub fn path(&self) -> PathBuf { - self.path.clone() - } - - pub fn is_real(&self) -> bool { - false - } -} - -#[cfg(procmacro2_semver_exempt)] -impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SourceFile") - .field("path", &self.path()) - .field("is_real", &self.is_real()) - .finish() - } -} - #[cfg(all(span_locations, not(fuzzing)))] thread_local! { static SOURCE_MAP: RefCell = RefCell::new(SourceMap { @@ -471,36 +457,39 @@ span } - #[cfg(procmacro2_semver_exempt)] - fn filepath(&self, span: Span) -> PathBuf { - for (i, file) in self.files.iter().enumerate() { - if file.span_within(span) { - return PathBuf::from(if i == 0 { - "".to_owned() - } else { - format!("", i) - }); + fn find(&self, span: Span) -> usize { + match self.files.binary_search_by(|file| { + if file.span.hi < span.lo { + Ordering::Less + } else if file.span.lo > span.hi { + Ordering::Greater + } else { + assert!(file.span_within(span)); + Ordering::Equal } + }) { + Ok(i) => i, + Err(_) => unreachable!("Invalid span with no related FileInfo!"), } - unreachable!("Invalid span with no related FileInfo!"); } - fn fileinfo(&self, span: Span) -> &FileInfo { - for file in &self.files { - if file.span_within(span) { - return file; - } + fn filepath(&self, span: Span) -> String { + let i = self.find(span); + if i == 0 { + "".to_owned() + } else { + format!("", i) } - unreachable!("Invalid span with no related FileInfo!"); + } + + fn fileinfo(&self, span: Span) -> &FileInfo { + let i = self.find(span); + &self.files[i] } fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo { - for file in &mut self.files { - if file.span_within(span) { - return file; - } - } - unreachable!("Invalid span with no related FileInfo!"); + let i = self.find(span); + &mut self.files[i] } } @@ -514,52 +503,37 @@ impl Span { #[cfg(not(span_locations))] - pub fn call_site() -> Self { + pub(crate) fn call_site() -> Self { Span {} } #[cfg(span_locations)] - pub fn call_site() -> Self { + pub(crate) fn call_site() -> Self { Span { lo: 0, hi: 0 } } - pub fn mixed_site() -> Self { + pub(crate) fn mixed_site() -> Self { Span::call_site() } #[cfg(procmacro2_semver_exempt)] - pub fn def_site() -> Self { + pub(crate) fn def_site() -> Self { Span::call_site() } - pub fn resolved_at(&self, _other: Span) -> Span { + pub(crate) fn resolved_at(&self, _other: Span) -> Span { // Stable spans consist only of line/column information, so // `resolved_at` and `located_at` only select which span the // caller wants line/column information from. *self } - pub fn located_at(&self, other: Span) -> Span { + pub(crate) fn located_at(&self, other: Span) -> Span { other } - #[cfg(procmacro2_semver_exempt)] - pub fn source_file(&self) -> SourceFile { - #[cfg(fuzzing)] - return SourceFile { - path: PathBuf::from(""), - }; - - #[cfg(not(fuzzing))] - SOURCE_MAP.with(|sm| { - let sm = sm.borrow(); - let path = sm.filepath(*self); - SourceFile { path } - }) - } - #[cfg(span_locations)] - pub fn byte_range(&self) -> Range { + pub(crate) fn byte_range(&self) -> Range { #[cfg(fuzzing)] return 0..0; @@ -574,7 +548,7 @@ } #[cfg(span_locations)] - pub fn start(&self) -> LineColumn { + pub(crate) fn start(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; @@ -587,7 +561,7 @@ } #[cfg(span_locations)] - pub fn end(&self) -> LineColumn { + pub(crate) fn end(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; @@ -599,13 +573,30 @@ }) } + #[cfg(span_locations)] + pub(crate) fn file(&self) -> String { + #[cfg(fuzzing)] + return "".to_owned(); + + #[cfg(not(fuzzing))] + SOURCE_MAP.with(|sm| { + let sm = sm.borrow(); + sm.filepath(*self) + }) + } + + #[cfg(span_locations)] + pub(crate) fn local_file(&self) -> Option { + None + } + #[cfg(not(span_locations))] - pub fn join(&self, _other: Span) -> Option { + pub(crate) fn join(&self, _other: Span) -> Option { Some(Span {}) } #[cfg(span_locations)] - pub fn join(&self, other: Span) -> Option { + pub(crate) fn join(&self, other: Span) -> Option { #[cfg(fuzzing)] return { let _ = other; @@ -627,12 +618,12 @@ } #[cfg(not(span_locations))] - pub fn source_text(&self) -> Option { + pub(crate) fn source_text(&self) -> Option { None } #[cfg(span_locations)] - pub fn source_text(&self) -> Option { + pub(crate) fn source_text(&self) -> Option { #[cfg(fuzzing)] return None; @@ -709,7 +700,7 @@ } impl Group { - pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { + pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self { Group { delimiter, stream, @@ -717,27 +708,27 @@ } } - pub fn delimiter(&self) -> Delimiter { + pub(crate) fn delimiter(&self) -> Delimiter { self.delimiter } - pub fn stream(&self) -> TokenStream { + pub(crate) fn stream(&self) -> TokenStream { self.stream.clone() } - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { self.span } - pub fn span_open(&self) -> Span { + pub(crate) fn span_open(&self) -> Span { self.span.first_byte() } - pub fn span_close(&self) -> Span { + pub(crate) fn span_close(&self) -> Span { self.span.last_byte() } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } } @@ -781,45 +772,45 @@ #[derive(Clone)] pub(crate) struct Ident { - sym: String, + sym: Box, span: Span, raw: bool, } impl Ident { #[track_caller] - pub fn new_checked(string: &str, span: Span) -> Self { + pub(crate) fn new_checked(string: &str, span: Span) -> Self { validate_ident(string); Ident::new_unchecked(string, span) } - pub fn new_unchecked(string: &str, span: Span) -> Self { + pub(crate) fn new_unchecked(string: &str, span: Span) -> Self { Ident { - sym: string.to_owned(), + sym: Box::from(string), span, raw: false, } } #[track_caller] - pub fn new_raw_checked(string: &str, span: Span) -> Self { + pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self { validate_ident_raw(string); Ident::new_raw_unchecked(string, span) } - pub fn new_raw_unchecked(string: &str, span: Span) -> Self { + pub(crate) fn new_raw_unchecked(string: &str, span: Span) -> Self { Ident { - sym: string.to_owned(), + sym: Box::from(string), span, raw: true, } } - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { self.span } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } } @@ -886,9 +877,9 @@ fn eq(&self, other: &T) -> bool { let other = other.as_ref(); if self.raw { - other.starts_with("r#") && self.sym == other[2..] + other.starts_with("r#") && *self.sym == other[2..] } else { - self.sym == other + *self.sym == *other } } } @@ -898,7 +889,7 @@ if self.raw { f.write_str("r#")?; } - Display::fmt(&self.sym, f) + f.write_str(&self.sym) } } @@ -933,7 +924,7 @@ macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { + pub(crate) fn $name(n: $kind) -> Literal { Literal::_new(format!(concat!("{}", stringify!($kind)), n)) } )*) @@ -941,7 +932,7 @@ macro_rules! unsuffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { + pub(crate) fn $name(n: $kind) -> Literal { Literal::_new(n.to_string()) } )*) @@ -955,6 +946,36 @@ } } + pub(crate) fn from_str_checked(repr: &str) -> Result { + let mut cursor = get_cursor(repr); + #[cfg(span_locations)] + let lo = cursor.off; + + let negative = cursor.starts_with_char('-'); + if negative { + cursor = cursor.advance(1); + if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) { + return Err(LexError::call_site()); + } + } + + if let Ok((rest, mut literal)) = parse::literal(cursor) { + if rest.is_empty() { + if negative { + literal.repr.insert(0, '-'); + } + literal.span = Span { + #[cfg(span_locations)] + lo, + #[cfg(span_locations)] + hi: rest.off, + }; + return Ok(literal); + } + } + Err(LexError::call_site()) + } + pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { Literal::_new(repr.to_owned()) } @@ -992,7 +1013,7 @@ isize_unsuffixed => isize, } - pub fn f32_unsuffixed(f: f32) -> Literal { + pub(crate) fn f32_unsuffixed(f: f32) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); @@ -1000,7 +1021,7 @@ Literal::_new(s) } - pub fn f64_unsuffixed(f: f64) -> Literal { + pub(crate) fn f64_unsuffixed(f: f64) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); @@ -1008,7 +1029,7 @@ Literal::_new(s) } - pub fn string(string: &str) -> Literal { + pub(crate) fn string(string: &str) -> Literal { let mut repr = String::with_capacity(string.len() + 2); repr.push('"'); escape_utf8(string, &mut repr); @@ -1016,7 +1037,7 @@ Literal::_new(repr) } - pub fn character(ch: char) -> Literal { + pub(crate) fn character(ch: char) -> Literal { let mut repr = String::new(); repr.push('\''); if ch == '"' { @@ -1029,7 +1050,7 @@ Literal::_new(repr) } - pub fn byte_character(byte: u8) -> Literal { + pub(crate) fn byte_character(byte: u8) -> Literal { let mut repr = "b'".to_string(); #[allow(clippy::match_overlapping_arm)] match byte { @@ -1048,7 +1069,7 @@ Literal::_new(repr) } - pub fn byte_string(bytes: &[u8]) -> Literal { + pub(crate) fn byte_string(bytes: &[u8]) -> Literal { let mut repr = "b\"".to_string(); let mut bytes = bytes.iter(); while let Some(&b) = bytes.next() { @@ -1074,7 +1095,7 @@ Literal::_new(repr) } - pub fn c_string(string: &CStr) -> Literal { + pub(crate) fn c_string(string: &CStr) -> Literal { let mut repr = "c\"".to_string(); let mut bytes = string.to_bytes(); while !bytes.is_empty() { @@ -1102,15 +1123,15 @@ Literal::_new(repr) } - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { self.span } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } - pub fn subspan>(&self, range: R) -> Option { + pub(crate) fn subspan>(&self, range: R) -> Option { #[cfg(not(span_locations))] { let _ = range; @@ -1152,40 +1173,6 @@ } } -impl FromStr for Literal { - type Err = LexError; - - fn from_str(repr: &str) -> Result { - let mut cursor = get_cursor(repr); - #[cfg(span_locations)] - let lo = cursor.off; - - let negative = cursor.starts_with_char('-'); - if negative { - cursor = cursor.advance(1); - if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) { - return Err(LexError::call_site()); - } - } - - if let Ok((rest, mut literal)) = parse::literal(cursor) { - if rest.is_empty() { - if negative { - literal.repr.insert(0, '-'); - } - literal.span = Span { - #[cfg(span_locations)] - lo, - #[cfg(span_locations)] - hi: rest.off, - }; - return Ok(literal); - } - } - Err(LexError::call_site()) - } -} - impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.repr, f) @@ -1224,3 +1211,46 @@ } } } + +#[cfg(feature = "proc-macro")] +pub(crate) trait FromStr2: FromStr { + #[cfg(wrap_proc_macro)] + fn valid(src: &str) -> bool; + + #[cfg(wrap_proc_macro)] + fn from_str_checked(src: &str) -> Result { + // Validate using fallback parser, because rustc is incapable of + // returning a recoverable Err for certain invalid token streams, and + // will instead permanently poison the compilation. + if !Self::valid(src) { + return Err(imp::LexError::CompilerPanic); + } + + // Catch panic to work around https://github.com/rust-lang/rust/issues/58736. + match panic::catch_unwind(|| Self::from_str(src)) { + Ok(Ok(ok)) => Ok(ok), + Ok(Err(lex)) => Err(imp::LexError::Compiler(lex)), + Err(_panic) => Err(imp::LexError::CompilerPanic), + } + } + + fn from_str_unchecked(src: &str) -> Self { + Self::from_str(src).unwrap() + } +} + +#[cfg(feature = "proc-macro")] +impl FromStr2 for proc_macro::TokenStream { + #[cfg(wrap_proc_macro)] + fn valid(src: &str) -> bool { + TokenStream::from_str_checked(src).is_ok() + } +} + +#[cfg(feature = "proc-macro")] +impl FromStr2 for proc_macro::Literal { + #[cfg(wrap_proc_macro)] + fn valid(src: &str) -> bool { + Literal::from_str_checked(src).is_ok() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,8 +9,6 @@ //! A wrapper around the procedural macro API of the compiler's [`proc_macro`] //! crate. This library serves two purposes: //! -//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ -//! //! - **Bring proc-macro-like functionality to other contexts like build.rs and //! main.rs.** Types from `proc_macro` are entirely specific to procedural //! macros and cannot ever exist in code outside of a procedural macro. @@ -65,7 +63,7 @@ //! //! To opt into the additional APIs available in the most recent nightly //! compiler, the `procmacro2_semver_exempt` config flag must be passed to -//! rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As +//! rustc. We will polyfill those nightly-only APIs back to Rust 1.68.0. As //! these are unstable APIs that track the nightly compiler, minor versions of //! proc-macro2 may make breaking changes to them at any time. //! @@ -86,34 +84,39 @@ //! a different thread. // Proc-macro2 types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.81")] +#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.104")] #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] #![cfg_attr(super_unstable, feature(proc_macro_def_site))] -#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![deny(unsafe_op_in_unsafe_fn)] #![allow( clippy::cast_lossless, clippy::cast_possible_truncation, clippy::checked_conversions, clippy::doc_markdown, + clippy::elidable_lifetime_names, clippy::incompatible_msrv, clippy::items_after_statements, clippy::iter_without_into_iter, clippy::let_underscore_untyped, clippy::manual_assert, clippy::manual_range_contains, + clippy::missing_panics_doc, clippy::missing_safety_doc, clippy::must_use_candidate, clippy::needless_doctest_main, + clippy::needless_lifetimes, clippy::new_without_default, clippy::return_self_not_must_use, clippy::shadow_unrelated, clippy::trivially_copy_pass_by_ref, + clippy::uninlined_format_args, clippy::unnecessary_wraps, clippy::unused_self, clippy::used_underscore_binding, clippy::vec_init_then_push )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] #[cfg(all(procmacro2_semver_exempt, wrap_proc_macro, not(super_unstable)))] compile_error! {"\ @@ -139,6 +142,7 @@ mod marker; mod parse; +mod probe; mod rcvec; #[cfg(wrap_proc_macro)] @@ -160,8 +164,16 @@ #[cfg(span_locations)] mod location; +#[cfg(procmacro2_semver_exempt)] +mod num; +#[cfg(procmacro2_semver_exempt)] +#[allow(dead_code)] +mod rustc_literal_escaper; + use crate::extra::DelimSpan; use crate::marker::{ProcMacroAutoTraits, MARKER}; +#[cfg(procmacro2_semver_exempt)] +use crate::rustc_literal_escaper::MixedUnit; use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; use core::hash::{Hash, Hasher}; @@ -171,13 +183,17 @@ use core::str::FromStr; use std::error::Error; use std::ffi::CStr; -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] use std::path::PathBuf; #[cfg(span_locations)] -#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] +#[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub use crate::location::LineColumn; +#[cfg(procmacro2_semver_exempt)] +#[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] +pub use crate::rustc_literal_escaper::EscapeError; + /// An abstract stream of tokens, or more concretely a sequence of token trees. /// /// This type provides interfaces for iterating over token trees and for @@ -207,7 +223,7 @@ fn _new_fallback(inner: fallback::TokenStream) -> Self { TokenStream { - inner: inner.into(), + inner: imp::TokenStream::from(inner), _marker: MARKER, } } @@ -243,27 +259,29 @@ type Err = LexError; fn from_str(src: &str) -> Result { - let e = src.parse().map_err(|e| LexError { - inner: e, - _marker: MARKER, - })?; - Ok(TokenStream::_new(e)) + match imp::TokenStream::from_str_checked(src) { + Ok(tokens) => Ok(TokenStream::_new(tokens)), + Err(lex) => Err(LexError { + inner: lex, + _marker: MARKER, + }), + } } } #[cfg(feature = "proc-macro")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] +#[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { - TokenStream::_new(inner.into()) + TokenStream::_new(imp::TokenStream::from(inner)) } } #[cfg(feature = "proc-macro")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] +#[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { - inner.inner.into() + proc_macro::TokenStream::from(inner.inner) } } @@ -274,8 +292,8 @@ } impl Extend for TokenStream { - fn extend>(&mut self, streams: I) { - self.inner.extend(streams); + fn extend>(&mut self, tokens: I) { + self.inner.extend(tokens); } } @@ -286,12 +304,38 @@ } } +impl Extend for TokenStream { + fn extend>(&mut self, tokens: I) { + self.inner.extend(tokens.into_iter().map(TokenTree::Group)); + } +} + +impl Extend for TokenStream { + fn extend>(&mut self, tokens: I) { + self.inner.extend(tokens.into_iter().map(TokenTree::Ident)); + } +} + +impl Extend for TokenStream { + fn extend>(&mut self, tokens: I) { + self.inner.extend(tokens.into_iter().map(TokenTree::Punct)); + } +} + +impl Extend for TokenStream { + fn extend>(&mut self, tokens: I) { + self.inner + .extend(tokens.into_iter().map(TokenTree::Literal)); + } +} + /// Collects a number of token trees into a single stream. impl FromIterator for TokenStream { - fn from_iter>(streams: I) -> Self { - TokenStream::_new(streams.into_iter().collect()) + fn from_iter>(tokens: I) -> Self { + TokenStream::_new(tokens.into_iter().collect()) } } + impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) @@ -335,57 +379,6 @@ impl Error for LexError {} -/// The source file of a given `Span`. -/// -/// This type is semver exempt and not exposed by default. -#[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] -#[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] -#[derive(Clone, PartialEq, Eq)] -pub struct SourceFile { - inner: imp::SourceFile, - _marker: ProcMacroAutoTraits, -} - -#[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] -impl SourceFile { - fn _new(inner: imp::SourceFile) -> Self { - SourceFile { - inner, - _marker: MARKER, - } - } - - /// Get the path to this source file. - /// - /// ### Note - /// - /// If the code span associated with this `SourceFile` was generated by an - /// external macro, this may not be an actual path on the filesystem. Use - /// [`is_real`] to check. - /// - /// Also note that even if `is_real` returns `true`, if - /// `--remap-path-prefix` was passed on the command line, the path as given - /// may not actually be valid. - /// - /// [`is_real`]: #method.is_real - pub fn path(&self) -> PathBuf { - self.inner.path() - } - - /// Returns `true` if this source file is a real source file, and not - /// generated by an external macro's expansion. - pub fn is_real(&self) -> bool { - self.inner.is_real() - } -} - -#[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] -impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Debug::fmt(&self.inner, f) - } -} - /// A region of source code, along with macro expansion information. #[derive(Copy, Clone)] pub struct Span { @@ -403,7 +396,7 @@ fn _new_fallback(inner: fallback::Span) -> Self { Span { - inner: inner.into(), + inner: imp::Span::from(inner), _marker: MARKER, } } @@ -428,7 +421,7 @@ /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] - #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] + #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn def_site() -> Self { Span::_new(imp::Span::def_site()) } @@ -467,15 +460,6 @@ self.unwrap() } - /// The original source file into which this span points. - /// - /// This method is semver exempt and not exposed by default. - #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] - #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] - pub fn source_file(&self) -> SourceFile { - SourceFile::_new(self.inner.source_file()) - } - /// Returns the span's byte position range in the source file. /// /// This method requires the `"span-locations"` feature to be enabled. @@ -486,7 +470,7 @@ /// procedural macro, such as main.rs or build.rs, the byte range is always /// accurate regardless of toolchain. #[cfg(span_locations)] - #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] + #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn byte_range(&self) -> Range { self.inner.byte_range() } @@ -501,7 +485,7 @@ /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] - #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] + #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn start(&self) -> LineColumn { self.inner.start() } @@ -516,11 +500,34 @@ /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] - #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] + #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn end(&self) -> LineColumn { self.inner.end() } + /// The path to the source file in which this span occurs, for display + /// purposes. + /// + /// This might not correspond to a valid file system path. It might be + /// remapped, or might be an artificial path such as `""`. + #[cfg(span_locations)] + #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] + pub fn file(&self) -> String { + self.inner.file() + } + + /// The path to the source file in which this span occurs on disk. + /// + /// This is the actual path on disk. It is unaffected by path remapping. + /// + /// This path should not be embedded in the output of the macro; prefer + /// `file()` instead. + #[cfg(span_locations)] + #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] + pub fn local_file(&self) -> Option { + self.inner.local_file() + } + /// Create a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. @@ -528,8 +535,6 @@ /// Warning: the underlying [`proc_macro::Span::join`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. - /// - /// [`proc_macro::Span::join`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.join pub fn join(&self, other: Span) -> Option { self.inner.join(other.inner).map(Span::_new) } @@ -538,7 +543,7 @@ /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] - #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] + #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn eq(&self, other: &Span) -> bool { self.inner.eq(&other.inner) } @@ -685,6 +690,18 @@ /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`. /// Invisible delimiters may not survive roundtrip of a token stream through /// a string. + /// + ///
+ /// + /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output + /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input + /// of a proc_macro macro are preserved, and only in very specific circumstances. + /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve + /// operator priorities as indicated above. The other `Delimiter` variants should be used + /// instead in this context. This is a rustc bug. For details, see + /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062). + /// + ///
None, } @@ -695,7 +712,7 @@ fn _new_fallback(inner: fallback::Group) -> Self { Group { - inner: inner.into(), + inner: imp::Group::from(inner), } } @@ -821,10 +838,16 @@ /// The returned `Punct` will have the default span of `Span::call_site()` /// which can be further configured with the `set_span` method below. pub fn new(ch: char, spacing: Spacing) -> Self { - Punct { - ch, - spacing, - span: Span::call_site(), + if let '!' | '#' | '$' | '%' | '&' | '\'' | '*' | '+' | ',' | '-' | '.' | '/' | ':' | ';' + | '<' | '=' | '>' | '?' | '@' | '^' | '|' | '~' = ch + { + Punct { + ch, + spacing, + span: Span::call_site(), + } + } else { + panic!("unsupported proc macro punctuation character {:?}", ch); } } @@ -949,6 +972,13 @@ } } + fn _new_fallback(inner: fallback::Ident) -> Self { + Ident { + inner: imp::Ident::from(inner), + _marker: MARKER, + } + } + /// Creates a new `Ident` with the given `string` as well as the specified /// `span`. /// @@ -1118,7 +1148,7 @@ fn _new_fallback(inner: fallback::Literal) -> Self { Literal { - inner: inner.into(), + inner: imp::Literal::from(inner), _marker: MARKER, } } @@ -1267,12 +1297,116 @@ /// Warning: the underlying [`proc_macro::Literal::subspan`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. - /// - /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan pub fn subspan>(&self, range: R) -> Option { self.inner.subspan(range).map(Span::_new) } + /// Returns the unescaped string value if this is a string literal. + #[cfg(procmacro2_semver_exempt)] + pub fn str_value(&self) -> Result { + let repr = self.to_string(); + + if repr.starts_with('"') && repr[1..].ends_with('"') { + let quoted = &repr[1..repr.len() - 1]; + let mut value = String::with_capacity(quoted.len()); + let mut error = None; + rustc_literal_escaper::unescape_str(quoted, |_range, res| match res { + Ok(ch) => value.push(ch), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + return match error { + Some(error) => Err(error), + None => Ok(value), + }; + } + + if repr.starts_with('r') { + if let Some(raw) = get_raw(&repr[1..]) { + return Ok(raw.to_owned()); + } + } + + Err(ConversionErrorKind::InvalidLiteralKind) + } + + /// Returns the unescaped string value (including nul terminator) if this is + /// a c-string literal. + #[cfg(procmacro2_semver_exempt)] + pub fn cstr_value(&self) -> Result, ConversionErrorKind> { + let repr = self.to_string(); + + if repr.starts_with("c\"") && repr[2..].ends_with('"') { + let quoted = &repr[2..repr.len() - 1]; + let mut value = Vec::with_capacity(quoted.len()); + let mut error = None; + rustc_literal_escaper::unescape_c_str(quoted, |_range, res| match res { + Ok(MixedUnit::Char(ch)) => { + value.extend_from_slice(ch.get().encode_utf8(&mut [0; 4]).as_bytes()); + } + Ok(MixedUnit::HighByte(byte)) => value.push(byte.get()), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + return match error { + Some(error) => Err(error), + None => { + value.push(b'\0'); + Ok(value) + } + }; + } + + if repr.starts_with("cr") { + if let Some(raw) = get_raw(&repr[2..]) { + let mut value = Vec::with_capacity(raw.len() + 1); + value.extend_from_slice(raw.as_bytes()); + value.push(b'\0'); + return Ok(value); + } + } + + Err(ConversionErrorKind::InvalidLiteralKind) + } + + /// Returns the unescaped string value if this is a byte string literal. + #[cfg(procmacro2_semver_exempt)] + pub fn byte_str_value(&self) -> Result, ConversionErrorKind> { + let repr = self.to_string(); + + if repr.starts_with("b\"") && repr[2..].ends_with('"') { + let quoted = &repr[2..repr.len() - 1]; + let mut value = Vec::with_capacity(quoted.len()); + let mut error = None; + rustc_literal_escaper::unescape_byte_str(quoted, |_range, res| match res { + Ok(byte) => value.push(byte), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + return match error { + Some(error) => Err(error), + None => Ok(value), + }; + } + + if repr.starts_with("br") { + if let Some(raw) = get_raw(&repr[2..]) { + return Ok(raw.as_bytes().to_owned()); + } + } + + Err(ConversionErrorKind::InvalidLiteralKind) + } + // Intended for the `quote!` macro to use when constructing a proc-macro2 // token out of a macro_rules $:literal token, which is already known to be // a valid literal. This avoids reparsing/validating the literal's string @@ -1287,10 +1421,13 @@ type Err = LexError; fn from_str(repr: &str) -> Result { - repr.parse().map(Literal::_new).map_err(|inner| LexError { - inner, - _marker: MARKER, - }) + match imp::Literal::from_str_checked(repr) { + Ok(lit) => Ok(Literal::_new(lit)), + Err(lex) => Err(LexError { + inner: lex, + _marker: MARKER, + }), + } } } @@ -1306,6 +1443,33 @@ } } +/// Error when retrieving a string literal's unescaped value. +#[cfg(procmacro2_semver_exempt)] +#[derive(Debug, PartialEq, Eq)] +pub enum ConversionErrorKind { + /// The literal is of the right string kind, but its contents are malformed + /// in a way that cannot be unescaped to a value. + FailedToUnescape(EscapeError), + /// The literal is not of the string kind whose value was requested, for + /// example byte string vs UTF-8 string. + InvalidLiteralKind, +} + +// ###"..."### -> ... +#[cfg(procmacro2_semver_exempt)] +fn get_raw(repr: &str) -> Option<&str> { + let pounds = repr.len() - repr.trim_start_matches('#').len(); + if repr.len() >= pounds + 1 + 1 + pounds + && repr[pounds..].starts_with('"') + && repr.trim_end_matches('#').len() + pounds == repr.len() + && repr[..repr.len() - pounds].ends_with('"') + { + Some(&repr[pounds + 1..repr.len() - pounds - 1]) + } else { + None + } +} + /// Public implementation details for the `TokenStream` type, such as iterators. pub mod token_stream { use crate::marker::{ProcMacroAutoTraits, MARKER}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/location.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/location.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/location.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/location.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,7 +3,7 @@ /// A line-column pair representing the start or end of a `Span`. /// /// This type is semver exempt and not exposed by default. -#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] +#[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/num.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/num.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/num.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/num.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// TODO: use NonZero in Rust 1.89+ +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct NonZeroChar(char); + +impl NonZeroChar { + pub fn new(ch: char) -> Option { + if ch == '\0' { + None + } else { + Some(NonZeroChar(ch)) + } + } + + pub fn get(self) -> char { + self.0 + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/parse.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/parse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/parse.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/parse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ use crate::fallback::{ - self, is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, + self, is_ident_continue, is_ident_start, Group, Ident, LexError, Literal, Span, TokenStream, TokenStreamBuilder, }; use crate::{Delimiter, Punct, Spacing, TokenTree}; @@ -8,13 +8,13 @@ #[derive(Copy, Clone, Eq, PartialEq)] pub(crate) struct Cursor<'a> { - pub rest: &'a str, + pub(crate) rest: &'a str, #[cfg(span_locations)] - pub off: u32, + pub(crate) off: u32, } impl<'a> Cursor<'a> { - pub fn advance(&self, bytes: usize) -> Cursor<'a> { + pub(crate) fn advance(&self, bytes: usize) -> Cursor<'a> { let (_front, rest) = self.rest.split_at(bytes); Cursor { rest, @@ -23,22 +23,22 @@ } } - pub fn starts_with(&self, s: &str) -> bool { + pub(crate) fn starts_with(&self, s: &str) -> bool { self.rest.starts_with(s) } - pub fn starts_with_char(&self, ch: char) -> bool { + pub(crate) fn starts_with_char(&self, ch: char) -> bool { self.rest.starts_with(ch) } - pub fn starts_with_fn(&self, f: Pattern) -> bool + pub(crate) fn starts_with_fn(&self, f: Pattern) -> bool where Pattern: FnMut(char) -> bool, { self.rest.starts_with(f) } - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.rest.is_empty() } @@ -166,13 +166,13 @@ const ERROR: &str = "(/*ERROR*/)"; pub(crate) fn token_stream(mut input: Cursor) -> Result { - let mut trees = TokenStreamBuilder::new(); + let mut tokens = TokenStreamBuilder::new(); let mut stack = Vec::new(); loop { input = skip_whitespace(input); - if let Ok((rest, ())) = doc_comment(input, &mut trees) { + if let Ok((rest, ())) = doc_comment(input, &mut tokens) { input = rest; continue; } @@ -180,19 +180,16 @@ #[cfg(span_locations)] let lo = input.off; - let first = match input.bytes().next() { - Some(first) => first, - None => match stack.last() { - None => return Ok(trees.build()), + let Some(first) = input.bytes().next() else { + return match stack.last() { + None => Ok(tokens.build()), #[cfg(span_locations)] - Some((lo, _frame)) => { - return Err(LexError { - span: Span { lo: *lo, hi: *lo }, - }) - } + Some((lo, _frame)) => Err(LexError { + span: Span { lo: *lo, hi: *lo }, + }), #[cfg(not(span_locations))] - Some(_frame) => return Err(LexError { span: Span {} }), - }, + Some(_frame) => Err(LexError { span: Span {} }), + }; }; if let Some(open_delimiter) = match first { @@ -202,20 +199,19 @@ _ => None, } { input = input.advance(1); - let frame = (open_delimiter, trees); + let frame = (open_delimiter, tokens); #[cfg(span_locations)] let frame = (lo, frame); stack.push(frame); - trees = TokenStreamBuilder::new(); + tokens = TokenStreamBuilder::new(); } else if let Some(close_delimiter) = match first { b')' => Some(Delimiter::Parenthesis), b']' => Some(Delimiter::Bracket), b'}' => Some(Delimiter::Brace), _ => None, } { - let frame = match stack.pop() { - Some(frame) => frame, - None => return Err(lex_error(input)), + let Some(frame) = stack.pop() else { + return Err(lex_error(input)); }; #[cfg(span_locations)] let (lo, frame) = frame; @@ -224,15 +220,15 @@ return Err(lex_error(input)); } input = input.advance(1); - let mut g = Group::new(open_delimiter, trees.build()); + let mut g = Group::new(open_delimiter, tokens.build()); g.set_span(Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: input.off, }); - trees = outer; - trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g))); + tokens = outer; + tokens.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g))); } else { let (rest, mut tt) = match leaf_token(input) { Ok((rest, tt)) => (rest, tt), @@ -244,7 +240,7 @@ #[cfg(span_locations)] hi: rest.off, })); - trees.push_token_from_parser(tt); + tokens.push_token_from_parser(tt); input = rest; } } @@ -300,10 +296,8 @@ let (rest, sym) = ident_not_raw(rest)?; if !raw { - let ident = crate::Ident::_new(crate::imp::Ident::new_unchecked( - sym, - fallback::Span::call_site(), - )); + let ident = + crate::Ident::_new_fallback(Ident::new_unchecked(sym, fallback::Span::call_site())); return Ok((rest, ident)); } @@ -312,10 +306,8 @@ _ => {} } - let ident = crate::Ident::_new(crate::imp::Ident::new_raw_unchecked( - sym, - fallback::Span::call_site(), - )); + let ident = + crate::Ident::_new_fallback(Ident::new_raw_unchecked(sym, fallback::Span::call_site())); Ok((rest, ident)) } @@ -861,7 +853,7 @@ continue; } _ => break, - }; + } len += 1; empty = false; } @@ -875,7 +867,10 @@ fn punct(input: Cursor) -> PResult { let (rest, ch) = punct_char(input)?; if ch == '\'' { - if ident_any(rest)?.0.starts_with_char('\'') { + let (after_lifetime, _ident) = ident_any(rest)?; + if after_lifetime.starts_with_char('\'') + || (after_lifetime.starts_with_char('#') && !rest.starts_with("r#")) + { Err(Reject) } else { Ok((rest, Punct::new('\'', Spacing::Joint))) @@ -896,11 +891,8 @@ } let mut chars = input.chars(); - let first = match chars.next() { - Some(ch) => ch, - None => { - return Err(Reject); - } + let Some(first) = chars.next() else { + return Err(Reject); }; let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; if recognized.contains(first) { @@ -910,7 +902,7 @@ } } -fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> { +fn doc_comment<'a>(input: Cursor<'a>, tokens: &mut TokenStreamBuilder) -> PResult<'a, ()> { #[cfg(span_locations)] let lo = input.off; let (rest, (comment, inner)) = doc_comment_contents(input)?; @@ -933,18 +925,18 @@ let mut pound = Punct::new('#', Spacing::Alone); pound.set_span(span); - trees.push_token_from_parser(TokenTree::Punct(pound)); + tokens.push_token_from_parser(TokenTree::Punct(pound)); if inner { let mut bang = Punct::new('!', Spacing::Alone); bang.set_span(span); - trees.push_token_from_parser(TokenTree::Punct(bang)); + tokens.push_token_from_parser(TokenTree::Punct(bang)); } - let doc_ident = crate::Ident::_new(crate::imp::Ident::new_unchecked("doc", fallback_span)); + let doc_ident = crate::Ident::_new_fallback(Ident::new_unchecked("doc", fallback_span)); let mut equal = Punct::new('=', Spacing::Alone); equal.set_span(span); - let mut literal = crate::Literal::string(comment); + let mut literal = crate::Literal::_new_fallback(Literal::string(comment)); literal.set_span(span); let mut bracketed = TokenStreamBuilder::with_capacity(3); bracketed.push_token_from_parser(TokenTree::Ident(doc_ident)); @@ -953,7 +945,7 @@ let group = Group::new(Delimiter::Bracket, bracketed.build()); let mut group = crate::Group::_new_fallback(group); group.set_span(span); - trees.push_token_from_parser(TokenTree::Group(group)); + tokens.push_token_from_parser(TokenTree::Group(group)); Ok((rest, ())) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +// This code exercises the surface area that we expect of Span's unstable API. +// If the current toolchain is able to compile it, then proc-macro2 is able to +// offer these APIs too. + +#![cfg_attr(procmacro2_build_probe, feature(proc_macro_span))] + +extern crate proc_macro; + +use core::ops::{Range, RangeBounds}; +use proc_macro::{Literal, Span}; +use std::path::PathBuf; + +pub fn byte_range(this: &Span) -> Range { + this.byte_range() +} + +pub fn start(this: &Span) -> Span { + this.start() +} + +pub fn end(this: &Span) -> Span { + this.end() +} + +pub fn line(this: &Span) -> usize { + this.line() +} + +pub fn column(this: &Span) -> usize { + this.column() +} + +pub fn file(this: &Span) -> String { + this.file() +} + +pub fn local_file(this: &Span) -> Option { + this.local_file() +} + +pub fn join(this: &Span, other: Span) -> Option { + this.join(other) +} + +pub fn subspan>(this: &Literal, range: R) -> Option { + this.subspan(range) +} + +// Include in sccache cache key. +#[cfg(procmacro2_build_probe)] +const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_file.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_file.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +// The subset of Span's API stabilized in Rust 1.88. + +extern crate proc_macro; + +use proc_macro::Span; +use std::path::PathBuf; + +pub fn file(this: &Span) -> String { + this.file() +} + +pub fn local_file(this: &Span) -> Option { + this.local_file() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_location.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_location.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_location.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe/proc_macro_span_location.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// The subset of Span's API stabilized in Rust 1.88. + +extern crate proc_macro; + +use proc_macro::Span; + +pub fn start(this: &Span) -> Span { + this.start() +} + +pub fn end(this: &Span) -> Span { + this.end() +} + +pub fn line(this: &Span) -> usize { + this.line() +} + +pub fn column(this: &Span) -> usize { + this.column() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/probe.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/probe.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +#![allow(dead_code)] + +#[cfg(proc_macro_span)] +pub(crate) mod proc_macro_span; + +#[cfg(proc_macro_span_file)] +pub(crate) mod proc_macro_span_file; + +#[cfg(proc_macro_span_location)] +pub(crate) mod proc_macro_span_location; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/rcvec.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rcvec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/rcvec.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rcvec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -22,19 +22,19 @@ } impl RcVec { - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.inner.is_empty() } - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.inner.len() } - pub fn iter(&self) -> slice::Iter { + pub(crate) fn iter(&self) -> slice::Iter { self.inner.iter() } - pub fn make_mut(&mut self) -> RcVecMut + pub(crate) fn make_mut(&mut self) -> RcVecMut where T: Clone, { @@ -43,12 +43,12 @@ } } - pub fn get_mut(&mut self) -> Option> { + pub(crate) fn get_mut(&mut self) -> Option> { let inner = Rc::get_mut(&mut self.inner)?; Some(RcVecMut { inner }) } - pub fn make_owned(mut self) -> RcVecBuilder + pub(crate) fn make_owned(mut self) -> RcVecBuilder where T: Clone, { @@ -62,31 +62,31 @@ } impl RcVecBuilder { - pub fn new() -> Self { + pub(crate) fn new() -> Self { RcVecBuilder { inner: Vec::new() } } - pub fn with_capacity(cap: usize) -> Self { + pub(crate) fn with_capacity(cap: usize) -> Self { RcVecBuilder { inner: Vec::with_capacity(cap), } } - pub fn push(&mut self, element: T) { + pub(crate) fn push(&mut self, element: T) { self.inner.push(element); } - pub fn extend(&mut self, iter: impl IntoIterator) { + pub(crate) fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } - pub fn as_mut(&mut self) -> RcVecMut { + pub(crate) fn as_mut(&mut self) -> RcVecMut { RcVecMut { inner: &mut self.inner, } } - pub fn build(self) -> RcVec { + pub(crate) fn build(self) -> RcVec { RcVec { inner: Rc::new(self.inner), } @@ -94,20 +94,21 @@ } impl<'a, T> RcVecMut<'a, T> { - pub fn push(&mut self, element: T) { + pub(crate) fn push(&mut self, element: T) { self.inner.push(element); } - pub fn extend(&mut self, iter: impl IntoIterator) { + pub(crate) fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } - pub fn pop(&mut self) -> Option { - self.inner.pop() + pub(crate) fn as_mut(&mut self) -> RcVecMut { + RcVecMut { inner: self.inner } } - pub fn as_mut(&mut self) -> RcVecMut { - RcVecMut { inner: self.inner } + pub(crate) fn take(self) -> RcVecBuilder { + let vec = mem::take(self.inner); + RcVecBuilder { inner: vec } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/rustc_literal_escaper.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rustc_literal_escaper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/rustc_literal_escaper.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/rustc_literal_escaper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,701 @@ +// Vendored from rustc-literal-escaper v0.0.5 +// https://github.com/rust-lang/literal-escaper/tree/v0.0.5 + +//! Utilities for validating (raw) string, char, and byte literals and +//! turning escape sequences into the values they represent. + +use crate::num::NonZeroChar; +use std::ffi::CStr; +use std::num::NonZeroU8; +use std::ops::Range; +use std::str::Chars; + +/// Errors and warnings that can occur during string, char, and byte unescaping. +/// +/// Mostly relating to malformed escape sequences, but also a few other problems. +#[derive(Debug, PartialEq, Eq)] +pub enum EscapeError { + /// Expected 1 char, but 0 were found. + ZeroChars, + /// Expected 1 char, but more than 1 were found. + MoreThanOneChar, + + /// Escaped '\' character without continuation. + LoneSlash, + /// Invalid escape character (e.g. '\z'). + InvalidEscape, + /// Raw '\r' encountered. + BareCarriageReturn, + /// Raw '\r' encountered in raw string. + BareCarriageReturnInRawString, + /// Unescaped character that was expected to be escaped (e.g. raw '\t'). + EscapeOnlyChar, + + /// Numeric character escape is too short (e.g. '\x1'). + TooShortHexEscape, + /// Invalid character in numeric escape (e.g. '\xz') + InvalidCharInHexEscape, + /// Character code in numeric escape is non-ascii (e.g. '\xFF'). + OutOfRangeHexEscape, + + /// '\u' not followed by '{'. + NoBraceInUnicodeEscape, + /// Non-hexadecimal value in '\u{..}'. + InvalidCharInUnicodeEscape, + /// '\u{}' + EmptyUnicodeEscape, + /// No closing brace in '\u{..}', e.g. '\u{12'. + UnclosedUnicodeEscape, + /// '\u{_12}' + LeadingUnderscoreUnicodeEscape, + /// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}' + OverlongUnicodeEscape, + /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'. + LoneSurrogateUnicodeEscape, + /// Out of bounds unicode character code, e.g. '\u{FFFFFF}'. + OutOfRangeUnicodeEscape, + + /// Unicode escape code in byte literal. + UnicodeEscapeInByte, + /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. + NonAsciiCharInByte, + + /// `\0` in a C string literal. + NulInCStr, + + /// After a line ending with '\', the next line contains whitespace + /// characters that are not skipped. + UnskippedWhitespaceWarning, + + /// After a line ending with '\', multiple lines are skipped. + MultipleSkippedLinesWarning, +} + +impl EscapeError { + /// Returns true for actual errors, as opposed to warnings. + pub fn is_fatal(&self) -> bool { + !matches!( + self, + EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning + ) + } +} + +/// Check a raw string literal for validity +/// +/// Takes the contents of a raw string literal (without quotes) +/// and produces a sequence of characters or errors, +/// which are returned by invoking `callback`. +/// NOTE: Does no escaping, but produces errors for bare carriage return ('\r'). +pub fn check_raw_str(src: &str, callback: impl FnMut(Range, Result)) { + str::check_raw(src, callback); +} + +/// Check a raw byte string literal for validity +/// +/// Takes the contents of a raw byte string literal (without quotes) +/// and produces a sequence of bytes or errors, +/// which are returned by invoking `callback`. +/// NOTE: Does no escaping, but produces errors for bare carriage return ('\r'). +pub fn check_raw_byte_str(src: &str, callback: impl FnMut(Range, Result)) { + <[u8]>::check_raw(src, callback); +} + +/// Check a raw C string literal for validity +/// +/// Takes the contents of a raw C string literal (without quotes) +/// and produces a sequence of characters or errors, +/// which are returned by invoking `callback`. +/// NOTE: Does no escaping, but produces errors for bare carriage return ('\r'). +pub fn check_raw_c_str( + src: &str, + callback: impl FnMut(Range, Result), +) { + CStr::check_raw(src, callback); +} + +/// Trait for checking raw string literals for validity +trait CheckRaw { + /// Unit type of the implementing string type (`char` for string, `u8` for byte string) + type RawUnit; + + /// Converts chars to the unit type of the literal type + fn char2raw_unit(c: char) -> Result; + + /// Takes the contents of a raw literal (without quotes) + /// and produces a sequence of `Result` + /// which are returned via `callback`. + /// + /// NOTE: Does no escaping, but produces errors for bare carriage return ('\r'). + fn check_raw( + src: &str, + mut callback: impl FnMut(Range, Result), + ) { + let mut chars = src.chars(); + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); + let res = match c { + '\r' => Err(EscapeError::BareCarriageReturnInRawString), + _ => Self::char2raw_unit(c), + }; + let end = src.len() - chars.as_str().len(); + callback(start..end, res); + } + + // Unfortunately, it is a bit unclear whether the following equivalent code is slower or faster: bug 141855 + // src.char_indices().for_each(|(pos, c)| { + // callback( + // pos..pos + c.len_utf8(), + // if c == '\r' { + // Err(EscapeError::BareCarriageReturnInRawString) + // } else { + // Self::char2raw_unit(c) + // }, + // ); + // }); + } +} + +impl CheckRaw for str { + type RawUnit = char; + + #[inline] + fn char2raw_unit(c: char) -> Result { + Ok(c) + } +} + +impl CheckRaw for [u8] { + type RawUnit = u8; + + #[inline] + fn char2raw_unit(c: char) -> Result { + char2byte(c) + } +} + +/// Turn an ascii char into a byte +#[inline] +fn char2byte(c: char) -> Result { + // do NOT do: c.try_into().ok_or(EscapeError::NonAsciiCharInByte) + if c.is_ascii() { + Ok(c as u8) + } else { + Err(EscapeError::NonAsciiCharInByte) + } +} + +impl CheckRaw for CStr { + type RawUnit = NonZeroChar; + + #[inline] + fn char2raw_unit(c: char) -> Result { + NonZeroChar::new(c).ok_or(EscapeError::NulInCStr) + } +} + +/// Unescape a char literal +/// +/// Takes the contents of a char literal (without quotes), +/// and returns an unescaped char or an error. +#[inline] +pub fn unescape_char(src: &str) -> Result { + str::unescape_single(&mut src.chars()) +} + +/// Unescape a byte literal +/// +/// Takes the contents of a byte literal (without quotes), +/// and returns an unescaped byte or an error. +#[inline] +pub fn unescape_byte(src: &str) -> Result { + <[u8]>::unescape_single(&mut src.chars()) +} + +/// Unescape a string literal +/// +/// Takes the contents of a string literal (without quotes) +/// and produces a sequence of escaped characters or errors, +/// which are returned by invoking `callback`. +pub fn unescape_str(src: &str, callback: impl FnMut(Range, Result)) { + str::unescape(src, callback) +} + +/// Unescape a byte string literal +/// +/// Takes the contents of a byte string literal (without quotes) +/// and produces a sequence of escaped bytes or errors, +/// which are returned by invoking `callback`. +pub fn unescape_byte_str(src: &str, callback: impl FnMut(Range, Result)) { + <[u8]>::unescape(src, callback) +} + +/// Unescape a C string literal +/// +/// Takes the contents of a C string literal (without quotes) +/// and produces a sequence of escaped MixedUnits or errors, +/// which are returned by invoking `callback`. +pub fn unescape_c_str( + src: &str, + callback: impl FnMut(Range, Result), +) { + CStr::unescape(src, callback) +} + +/// Enum representing either a char or a byte +/// +/// Used for mixed utf8 string literals, i.e. those that allow both unicode +/// chars and high bytes. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum MixedUnit { + /// Used for ASCII chars (written directly or via `\x00`..`\x7f` escapes) + /// and Unicode chars (written directly or via `\u` escapes). + /// + /// For example, if '¥' appears in a string it is represented here as + /// `MixedUnit::Char('¥')`, and it will be appended to the relevant byte + /// string as the two-byte UTF-8 sequence `[0xc2, 0xa5]` + Char(NonZeroChar), + + /// Used for high bytes (`\x80`..`\xff`). + /// + /// For example, if `\xa5` appears in a string it is represented here as + /// `MixedUnit::HighByte(0xa5)`, and it will be appended to the relevant + /// byte string as the single byte `0xa5`. + HighByte(NonZeroU8), +} + +impl From for MixedUnit { + #[inline] + fn from(c: NonZeroChar) -> Self { + MixedUnit::Char(c) + } +} + +impl From for MixedUnit { + #[inline] + fn from(byte: NonZeroU8) -> Self { + if byte.get().is_ascii() { + MixedUnit::Char(NonZeroChar::new(byte.get() as char).unwrap()) + } else { + MixedUnit::HighByte(byte) + } + } +} + +impl TryFrom for MixedUnit { + type Error = EscapeError; + + #[inline] + fn try_from(c: char) -> Result { + NonZeroChar::new(c) + .map(MixedUnit::Char) + .ok_or(EscapeError::NulInCStr) + } +} + +impl TryFrom for MixedUnit { + type Error = EscapeError; + + #[inline] + fn try_from(byte: u8) -> Result { + NonZeroU8::new(byte) + .map(From::from) + .ok_or(EscapeError::NulInCStr) + } +} + +/// Trait for unescaping escape sequences in strings +trait Unescape { + /// Unit type of the implementing string type (`char` for string, `u8` for byte string) + type Unit; + + /// Result of unescaping the zero char ('\0') + const ZERO_RESULT: Result; + + /// Converts non-zero bytes to the unit type + fn nonzero_byte2unit(b: NonZeroU8) -> Self::Unit; + + /// Converts chars to the unit type + fn char2unit(c: char) -> Result; + + /// Converts the byte of a hex escape to the unit type + fn hex2unit(b: u8) -> Result; + + /// Converts the result of a unicode escape to the unit type + fn unicode2unit(r: Result) -> Result; + + /// Unescape a single unit (single quote syntax) + fn unescape_single(chars: &mut Chars<'_>) -> Result { + let res = match chars.next().ok_or(EscapeError::ZeroChars)? { + '\\' => Self::unescape_1(chars), + '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), + '\r' => Err(EscapeError::BareCarriageReturn), + c => Self::char2unit(c), + }?; + if chars.next().is_some() { + return Err(EscapeError::MoreThanOneChar); + } + Ok(res) + } + + /// Unescape the first unit of a string (double quoted syntax) + fn unescape_1(chars: &mut Chars<'_>) -> Result { + // Previous character was '\\', unescape what follows. + let c = chars.next().ok_or(EscapeError::LoneSlash)?; + if c == '0' { + Self::ZERO_RESULT + } else { + simple_escape(c) + .map(|b| Self::nonzero_byte2unit(b)) + .or_else(|c| match c { + 'x' => Self::hex2unit(hex_escape(chars)?), + 'u' => Self::unicode2unit({ + let value = unicode_escape(chars)?; + if value > char::MAX as u32 { + Err(EscapeError::OutOfRangeUnicodeEscape) + } else { + char::from_u32(value).ok_or(EscapeError::LoneSurrogateUnicodeEscape) + } + }), + _ => Err(EscapeError::InvalidEscape), + }) + } + } + + /// Unescape a string literal + /// + /// Takes the contents of a raw string literal (without quotes) + /// and produces a sequence of `Result` + /// which are returned via `callback`. + fn unescape( + src: &str, + mut callback: impl FnMut(Range, Result), + ) { + let mut chars = src.chars(); + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); + let res = match c { + '\\' => { + if let Some(b'\n') = chars.as_str().as_bytes().first() { + let _ = chars.next(); + // skip whitespace for backslash newline, see [Rust language reference] + // (https://doc.rust-lang.org/reference/tokens.html#string-literals). + let callback_err = |range, err| callback(range, Err(err)); + skip_ascii_whitespace(&mut chars, start, callback_err); + continue; + } else { + Self::unescape_1(&mut chars) + } + } + '"' => Err(EscapeError::EscapeOnlyChar), + '\r' => Err(EscapeError::BareCarriageReturn), + c => Self::char2unit(c), + }; + let end = src.len() - chars.as_str().len(); + callback(start..end, res); + } + } +} + +/// Interpret a non-nul ASCII escape +/// +/// Parses the character of an ASCII escape (except nul) without the leading backslash. +#[inline] // single use in Unescape::unescape_1 +fn simple_escape(c: char) -> Result { + // Previous character was '\\', unescape what follows. + Ok(NonZeroU8::new(match c { + '"' => b'"', + 'n' => b'\n', + 'r' => b'\r', + 't' => b'\t', + '\\' => b'\\', + '\'' => b'\'', + _ => Err(c)?, + }) + .unwrap()) +} + +/// Interpret a hexadecimal escape +/// +/// Parses the two hexadecimal characters of a hexadecimal escape without the leading r"\x". +#[inline] // single use in Unescape::unescape_1 +fn hex_escape(chars: &mut impl Iterator) -> Result { + let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?; + let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; + + let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?; + let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; + + Ok((hi * 16 + lo) as u8) +} + +/// Interpret a unicode escape +/// +/// Parse the braces with hexadecimal characters (and underscores) part of a unicode escape. +/// This r"{...}" normally comes after r"\u" and cannot start with an underscore. +#[inline] // single use in Unescape::unescape_1 +fn unicode_escape(chars: &mut impl Iterator) -> Result { + if chars.next() != Some('{') { + return Err(EscapeError::NoBraceInUnicodeEscape); + } + + // First character must be a hexadecimal digit. + let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? { + '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape), + '}' => return Err(EscapeError::EmptyUnicodeEscape), + c => c + .to_digit(16) + .ok_or(EscapeError::InvalidCharInUnicodeEscape)?, + }; + + // First character is valid, now parse the rest of the number + // and closing brace. + let mut n_digits = 1; + loop { + match chars.next() { + None => return Err(EscapeError::UnclosedUnicodeEscape), + Some('_') => continue, + Some('}') => { + // Incorrect syntax has higher priority for error reporting + // than unallowed value for a literal. + return if n_digits > 6 { + Err(EscapeError::OverlongUnicodeEscape) + } else { + Ok(value) + }; + } + Some(c) => { + let digit: u32 = c + .to_digit(16) + .ok_or(EscapeError::InvalidCharInUnicodeEscape)?; + n_digits += 1; + if n_digits > 6 { + // Stop updating value since we're sure that it's incorrect already. + continue; + } + value = value * 16 + digit; + } + }; + } +} + +/// Interpret a string continuation escape (https://doc.rust-lang.org/reference/expressions/literal-expr.html#string-continuation-escapes) +/// +/// Skip ASCII whitespace, except for the formfeed character +/// (see [this issue](https://github.com/rust-lang/rust/issues/136600)). +/// Warns on unescaped newline and following non-ASCII whitespace. +#[inline] // single use in Unescape::unescape +fn skip_ascii_whitespace( + chars: &mut Chars<'_>, + start: usize, + mut callback: impl FnMut(Range, EscapeError), +) { + let rest = chars.as_str(); + let first_non_space = rest + .bytes() + .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r') + .unwrap_or(rest.len()); + let (space, rest) = rest.split_at(first_non_space); + // backslash newline adds 2 bytes + let end = start + 2 + first_non_space; + if space.contains('\n') { + callback(start..end, EscapeError::MultipleSkippedLinesWarning); + } + *chars = rest.chars(); + if let Some(c) = chars.clone().next() { + if c.is_whitespace() { + // for error reporting, include the character that was not skipped in the span + callback( + start..end + c.len_utf8(), + EscapeError::UnskippedWhitespaceWarning, + ); + } + } +} + +impl Unescape for str { + type Unit = char; + + const ZERO_RESULT: Result = Ok('\0'); + + #[inline] + fn nonzero_byte2unit(b: NonZeroU8) -> Self::Unit { + b.get().into() + } + + #[inline] + fn char2unit(c: char) -> Result { + Ok(c) + } + + #[inline] + fn hex2unit(b: u8) -> Result { + if b.is_ascii() { + Ok(b as char) + } else { + Err(EscapeError::OutOfRangeHexEscape) + } + } + + #[inline] + fn unicode2unit(r: Result) -> Result { + r + } +} + +impl Unescape for [u8] { + type Unit = u8; + + const ZERO_RESULT: Result = Ok(b'\0'); + + #[inline] + fn nonzero_byte2unit(b: NonZeroU8) -> Self::Unit { + b.get() + } + + #[inline] + fn char2unit(c: char) -> Result { + char2byte(c) + } + + #[inline] + fn hex2unit(b: u8) -> Result { + Ok(b) + } + + #[inline] + fn unicode2unit(_r: Result) -> Result { + Err(EscapeError::UnicodeEscapeInByte) + } +} + +impl Unescape for CStr { + type Unit = MixedUnit; + + const ZERO_RESULT: Result = Err(EscapeError::NulInCStr); + + #[inline] + fn nonzero_byte2unit(b: NonZeroU8) -> Self::Unit { + b.into() + } + + #[inline] + fn char2unit(c: char) -> Result { + c.try_into() + } + + #[inline] + fn hex2unit(byte: u8) -> Result { + byte.try_into() + } + + #[inline] + fn unicode2unit(r: Result) -> Result { + Self::char2unit(r?) + } +} + +/// Enum of the different kinds of literal +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Mode { + /// `'a'` + Char, + + /// `b'a'` + Byte, + + /// `"hello"` + Str, + /// `r"hello"` + RawStr, + + /// `b"hello"` + ByteStr, + /// `br"hello"` + RawByteStr, + + /// `c"hello"` + CStr, + /// `cr"hello"` + RawCStr, +} + +impl Mode { + pub fn in_double_quotes(self) -> bool { + match self { + Mode::Str + | Mode::RawStr + | Mode::ByteStr + | Mode::RawByteStr + | Mode::CStr + | Mode::RawCStr => true, + Mode::Char | Mode::Byte => false, + } + } + + pub fn prefix_noraw(self) -> &'static str { + match self { + Mode::Char | Mode::Str | Mode::RawStr => "", + Mode::Byte | Mode::ByteStr | Mode::RawByteStr => "b", + Mode::CStr | Mode::RawCStr => "c", + } + } +} + +/// Check a literal only for errors +/// +/// Takes the contents of a literal (without quotes) +/// and produces a sequence of only errors, +/// which are returned by invoking `error_callback`. +/// +/// NB Does not produce any output other than errors +pub fn check_for_errors( + src: &str, + mode: Mode, + mut error_callback: impl FnMut(Range, EscapeError), +) { + match mode { + Mode::Char => { + let mut chars = src.chars(); + if let Err(e) = str::unescape_single(&mut chars) { + error_callback(0..(src.len() - chars.as_str().len()), e); + } + } + Mode::Byte => { + let mut chars = src.chars(); + if let Err(e) = <[u8]>::unescape_single(&mut chars) { + error_callback(0..(src.len() - chars.as_str().len()), e); + } + } + Mode::Str => unescape_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + Mode::ByteStr => unescape_byte_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + Mode::CStr => unescape_c_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + Mode::RawStr => check_raw_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + Mode::RawByteStr => check_raw_byte_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + Mode::RawCStr => check_raw_c_str(src, |range, res| { + if let Err(e) = res { + error_callback(range, e); + } + }), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/wrapper.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/wrapper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/src/wrapper.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/src/wrapper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,15 +1,20 @@ use crate::detection::inside_proc_macro; +use crate::fallback::{self, FromStr2 as _}; #[cfg(span_locations)] use crate::location::LineColumn; -use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; +#[cfg(proc_macro_span)] +use crate::probe::proc_macro_span; +#[cfg(all(span_locations, proc_macro_span_file))] +use crate::probe::proc_macro_span_file; +#[cfg(all(span_locations, proc_macro_span_location))] +use crate::probe::proc_macro_span_location; +use crate::{Delimiter, Punct, Spacing, TokenTree}; use core::fmt::{self, Debug, Display}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; -use core::str::FromStr; use std::ffi::CStr; -use std::panic; -#[cfg(super_unstable)] +#[cfg(span_locations)] use std::path::PathBuf; #[derive(Clone)] @@ -42,11 +47,11 @@ #[cfg(procmacro2_backtrace)] { let backtrace = std::backtrace::Backtrace::force_capture(); - panic!("compiler/fallback mismatch #{}\n\n{}", line, backtrace) + panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace) } #[cfg(not(procmacro2_backtrace))] { - panic!("compiler/fallback mismatch #{}", line) + panic!("compiler/fallback mismatch L{}", line) } } @@ -78,7 +83,7 @@ } impl TokenStream { - pub fn new() -> Self { + pub(crate) fn new() -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) } else { @@ -86,7 +91,19 @@ } } - pub fn is_empty(&self) -> bool { + pub(crate) fn from_str_checked(src: &str) -> Result { + if inside_proc_macro() { + Ok(TokenStream::Compiler(DeferredTokenStream::new( + proc_macro::TokenStream::from_str_checked(src)?, + ))) + } else { + Ok(TokenStream::Fallback( + fallback::TokenStream::from_str_checked(src)?, + )) + } + } + + pub(crate) fn is_empty(&self) -> bool { match self { TokenStream::Compiler(tts) => tts.is_empty(), TokenStream::Fallback(tts) => tts.is_empty(), @@ -108,26 +125,6 @@ } } -impl FromStr for TokenStream { - type Err = LexError; - - fn from_str(src: &str) -> Result { - if inside_proc_macro() { - Ok(TokenStream::Compiler(DeferredTokenStream::new( - proc_macro_parse(src)?, - ))) - } else { - Ok(TokenStream::Fallback(src.parse()?)) - } - } -} - -// Work around https://github.com/rust-lang/rust/issues/58736. -fn proc_macro_parse(src: &str) -> Result { - let result = panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)); - result.unwrap_or_else(|_| Err(LexError::CompilerPanic)) -} - impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -147,7 +144,9 @@ fn from(inner: TokenStream) -> Self { match inner { TokenStream::Compiler(inner) => inner.into_token_stream(), - TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(), + TokenStream::Fallback(inner) => { + proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) + } } } } @@ -161,7 +160,7 @@ // Assumes inside_proc_macro(). fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { match token { - TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), + TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()), TokenTree::Punct(tt) => { let spacing = match tt.spacing() { Spacing::Joint => proc_macro::Spacing::Joint, @@ -169,31 +168,33 @@ }; let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); punct.set_span(tt.span().inner.unwrap_nightly()); - punct.into() + proc_macro::TokenTree::Punct(punct) } - TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), - TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), + TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()), + TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()), } } impl From for TokenStream { fn from(token: TokenTree) -> Self { if inside_proc_macro() { - TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into())) + TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from( + into_compiler_token(token), + ))) } else { - TokenStream::Fallback(token.into()) + TokenStream::Fallback(fallback::TokenStream::from(token)) } } } impl FromIterator for TokenStream { - fn from_iter>(trees: I) -> Self { + fn from_iter>(tokens: I) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new( - trees.into_iter().map(into_compiler_token).collect(), + tokens.into_iter().map(into_compiler_token).collect(), )) } else { - TokenStream::Fallback(trees.into_iter().collect()) + TokenStream::Fallback(tokens.into_iter().collect()) } } } @@ -223,15 +224,15 @@ } impl Extend for TokenStream { - fn extend>(&mut self, stream: I) { + fn extend>(&mut self, tokens: I) { match self { TokenStream::Compiler(tts) => { // Here is the reason for DeferredTokenStream. - for token in stream { + for token in tokens { tts.extra.push(into_compiler_token(token)); } } - TokenStream::Fallback(tts) => tts.extend(stream), + TokenStream::Fallback(tts) => tts.extend(tokens), } } } @@ -336,7 +337,9 @@ TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { - proc_macro::TokenTree::Group(tt) => crate::Group::_new(Group::Compiler(tt)).into(), + proc_macro::TokenTree::Group(tt) => { + TokenTree::Group(crate::Group::_new(Group::Compiler(tt))) + } proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, @@ -344,10 +347,14 @@ }; let mut o = Punct::new(tt.as_char(), spacing); o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); - o.into() + TokenTree::Punct(o) + } + proc_macro::TokenTree::Ident(s) => { + TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s))) + } + proc_macro::TokenTree::Literal(l) => { + TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l))) } - proc_macro::TokenTree::Ident(s) => crate::Ident::_new(Ident::Compiler(s)).into(), - proc_macro::TokenTree::Literal(l) => crate::Literal::_new(Literal::Compiler(l)).into(), }) } @@ -359,45 +366,6 @@ } } -#[derive(Clone, PartialEq, Eq)] -#[cfg(super_unstable)] -pub(crate) enum SourceFile { - Compiler(proc_macro::SourceFile), - Fallback(fallback::SourceFile), -} - -#[cfg(super_unstable)] -impl SourceFile { - fn nightly(sf: proc_macro::SourceFile) -> Self { - SourceFile::Compiler(sf) - } - - /// Get the path to this source file as a string. - pub fn path(&self) -> PathBuf { - match self { - SourceFile::Compiler(a) => a.path(), - SourceFile::Fallback(a) => a.path(), - } - } - - pub fn is_real(&self) -> bool { - match self { - SourceFile::Compiler(a) => a.is_real(), - SourceFile::Fallback(a) => a.is_real(), - } - } -} - -#[cfg(super_unstable)] -impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - SourceFile::Compiler(a) => Debug::fmt(a, f), - SourceFile::Fallback(a) => Debug::fmt(a, f), - } - } -} - #[derive(Copy, Clone)] pub(crate) enum Span { Compiler(proc_macro::Span), @@ -405,7 +373,7 @@ } impl Span { - pub fn call_site() -> Self { + pub(crate) fn call_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::call_site()) } else { @@ -413,7 +381,7 @@ } } - pub fn mixed_site() -> Self { + pub(crate) fn mixed_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::mixed_site()) } else { @@ -422,7 +390,7 @@ } #[cfg(super_unstable)] - pub fn def_site() -> Self { + pub(crate) fn def_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::def_site()) } else { @@ -430,7 +398,7 @@ } } - pub fn resolved_at(&self, other: Span) -> Span { + pub(crate) fn resolved_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), @@ -439,7 +407,7 @@ } } - pub fn located_at(&self, other: Span) -> Span { + pub(crate) fn located_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), @@ -448,26 +416,18 @@ } } - pub fn unwrap(self) -> proc_macro::Span { + pub(crate) fn unwrap(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } - #[cfg(super_unstable)] - pub fn source_file(&self) -> SourceFile { - match self { - Span::Compiler(s) => SourceFile::nightly(s.source_file()), - Span::Fallback(s) => SourceFile::Fallback(s.source_file()), - } - } - #[cfg(span_locations)] - pub fn byte_range(&self) -> Range { + pub(crate) fn byte_range(&self) -> Range { match self { #[cfg(proc_macro_span)] - Span::Compiler(s) => s.byte_range(), + Span::Compiler(s) => proc_macro_span::byte_range(s), #[cfg(not(proc_macro_span))] Span::Compiler(_) => 0..0, Span::Fallback(s) => s.byte_range(), @@ -475,25 +435,62 @@ } #[cfg(span_locations)] - pub fn start(&self) -> LineColumn { + pub(crate) fn start(&self) -> LineColumn { match self { + #[cfg(proc_macro_span_location)] + Span::Compiler(s) => LineColumn { + line: proc_macro_span_location::line(s), + column: proc_macro_span_location::column(s).saturating_sub(1), + }, + #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.start(), } } #[cfg(span_locations)] - pub fn end(&self) -> LineColumn { + pub(crate) fn end(&self) -> LineColumn { match self { + #[cfg(proc_macro_span_location)] + Span::Compiler(s) => { + let end = proc_macro_span_location::end(s); + LineColumn { + line: proc_macro_span_location::line(&end), + column: proc_macro_span_location::column(&end).saturating_sub(1), + } + } + #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.end(), } } - pub fn join(&self, other: Span) -> Option { + #[cfg(span_locations)] + pub(crate) fn file(&self) -> String { + match self { + #[cfg(proc_macro_span_file)] + Span::Compiler(s) => proc_macro_span_file::file(s), + #[cfg(not(proc_macro_span_file))] + Span::Compiler(_) => "".to_owned(), + Span::Fallback(s) => s.file(), + } + } + + #[cfg(span_locations)] + pub(crate) fn local_file(&self) -> Option { + match self { + #[cfg(proc_macro_span_file)] + Span::Compiler(s) => proc_macro_span_file::local_file(s), + #[cfg(not(proc_macro_span_file))] + Span::Compiler(_) => None, + Span::Fallback(s) => s.local_file(), + } + } + + pub(crate) fn join(&self, other: Span) -> Option { let ret = match (self, other) { #[cfg(proc_macro_span)] - (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(proc_macro_span::join(a, b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; @@ -501,7 +498,7 @@ } #[cfg(super_unstable)] - pub fn eq(&self, other: &Span) -> bool { + pub(crate) fn eq(&self, other: &Span) -> bool { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), @@ -509,7 +506,7 @@ } } - pub fn source_text(&self) -> Option { + pub(crate) fn source_text(&self) -> Option { match self { #[cfg(not(no_source_text))] Span::Compiler(s) => s.source_text(), @@ -564,7 +561,7 @@ } impl Group { - pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { + pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self { match stream { TokenStream::Compiler(tts) => { let delimiter = match delimiter { @@ -581,7 +578,7 @@ } } - pub fn delimiter(&self) -> Delimiter { + pub(crate) fn delimiter(&self) -> Delimiter { match self { Group::Compiler(g) => match g.delimiter() { proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, @@ -593,35 +590,35 @@ } } - pub fn stream(&self) -> TokenStream { + pub(crate) fn stream(&self) -> TokenStream { match self { Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())), Group::Fallback(g) => TokenStream::Fallback(g.stream()), } } - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span()), Group::Fallback(g) => Span::Fallback(g.span()), } } - pub fn span_open(&self) -> Span { + pub(crate) fn span_open(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_open()), Group::Fallback(g) => Span::Fallback(g.span_open()), } } - pub fn span_close(&self) -> Span { + pub(crate) fn span_close(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_close()), Group::Fallback(g) => Span::Fallback(g.span_close()), } } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), @@ -670,37 +667,29 @@ impl Ident { #[track_caller] - pub fn new_checked(string: &str, span: Span) -> Self { + pub(crate) fn new_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)), } } - pub fn new_unchecked(string: &str, span: fallback::Span) -> Self { - Ident::Fallback(fallback::Ident::new_unchecked(string, span)) - } - #[track_caller] - pub fn new_raw_checked(string: &str, span: Span) -> Self { + pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)), } } - pub fn new_raw_unchecked(string: &str, span: fallback::Span) -> Self { - Ident::Fallback(fallback::Ident::new_raw_unchecked(string, span)) - } - - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { match self { Ident::Compiler(t) => Span::Compiler(t.span()), Ident::Fallback(t) => Span::Fallback(t.span()), } } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), @@ -717,6 +706,12 @@ } } +impl From for Ident { + fn from(inner: fallback::Ident) -> Self { + Ident::Fallback(inner) + } +} + impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { match (self, other) { @@ -767,7 +762,7 @@ macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { + pub(crate) fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { @@ -779,7 +774,7 @@ macro_rules! unsuffixed_integers { ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { + pub(crate) fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { @@ -790,9 +785,19 @@ } impl Literal { - pub unsafe fn from_str_unchecked(repr: &str) -> Self { + pub(crate) fn from_str_checked(repr: &str) -> Result { + if inside_proc_macro() { + let literal = proc_macro::Literal::from_str_checked(repr)?; + Ok(Literal::Compiler(literal)) + } else { + let literal = fallback::Literal::from_str_checked(repr)?; + Ok(Literal::Fallback(literal)) + } + } + + pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::from_str(repr).expect("invalid literal")) + Literal::Compiler(proc_macro::Literal::from_str_unchecked(repr)) } else { Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) }) } @@ -831,7 +836,7 @@ isize_unsuffixed => isize, } - pub fn f32_unsuffixed(f: f32) -> Literal { + pub(crate) fn f32_unsuffixed(f: f32) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) } else { @@ -839,7 +844,7 @@ } } - pub fn f64_unsuffixed(f: f64) -> Literal { + pub(crate) fn f64_unsuffixed(f: f64) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) } else { @@ -847,7 +852,7 @@ } } - pub fn string(string: &str) -> Literal { + pub(crate) fn string(string: &str) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::string(string)) } else { @@ -855,7 +860,7 @@ } } - pub fn character(ch: char) -> Literal { + pub(crate) fn character(ch: char) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::character(ch)) } else { @@ -863,7 +868,7 @@ } } - pub fn byte_character(byte: u8) -> Literal { + pub(crate) fn byte_character(byte: u8) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_byte_character))] @@ -874,7 +879,7 @@ #[cfg(no_literal_byte_character)] { let fallback = fallback::Literal::byte_character(byte); - fallback.repr.parse::().unwrap() + proc_macro::Literal::from_str_unchecked(&fallback.repr) } }) } else { @@ -882,7 +887,7 @@ } } - pub fn byte_string(bytes: &[u8]) -> Literal { + pub(crate) fn byte_string(bytes: &[u8]) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::byte_string(bytes)) } else { @@ -890,7 +895,7 @@ } } - pub fn c_string(string: &CStr) -> Literal { + pub(crate) fn c_string(string: &CStr) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_c_string))] @@ -901,7 +906,7 @@ #[cfg(no_literal_c_string)] { let fallback = fallback::Literal::c_string(string); - fallback.repr.parse::().unwrap() + proc_macro::Literal::from_str_unchecked(&fallback.repr) } }) } else { @@ -909,14 +914,14 @@ } } - pub fn span(&self) -> Span { + pub(crate) fn span(&self) -> Span { match self { Literal::Compiler(lit) => Span::Compiler(lit.span()), Literal::Fallback(lit) => Span::Fallback(lit.span()), } } - pub fn set_span(&mut self, span: Span) { + pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), @@ -925,10 +930,10 @@ } } - pub fn subspan>(&self, range: R) -> Option { + pub(crate) fn subspan>(&self, range: R) -> Option { match self { #[cfg(proc_macro_span)] - Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler), + Literal::Compiler(lit) => proc_macro_span::subspan(lit, range).map(Span::Compiler), #[cfg(not(proc_macro_span))] Literal::Compiler(_lit) => None, Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), @@ -949,20 +954,6 @@ } } -impl FromStr for Literal { - type Err = LexError; - - fn from_str(repr: &str) -> Result { - if inside_proc_macro() { - let literal = proc_macro::Literal::from_str(repr)?; - Ok(Literal::Compiler(literal)) - } else { - let literal = fallback::Literal::from_str(repr)?; - Ok(Literal::Fallback(literal)) - } - } -} - impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/comments.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/comments.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/comments.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/comments.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -#![allow(clippy::assertions_on_result_states)] +#![allow(clippy::assertions_on_result_states, clippy::uninlined_format_args)] use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/features.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/features.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/features.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/features.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,5 @@ +#![allow(clippy::assertions_on_constants, clippy::ignore_without_reason)] + #[test] #[ignore] fn make_sure_no_proc_macro() { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/marker.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/marker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/marker.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/marker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -56,19 +56,17 @@ #[cfg(procmacro2_semver_exempt)] mod semver_exempt { - use proc_macro2::{LineColumn, SourceFile}; + use proc_macro2::LineColumn; assert_impl!(LineColumn is Send and Sync); - - assert_impl!(SourceFile is not Send or Sync); } mod unwind_safe { + #[cfg(procmacro2_semver_exempt)] + use proc_macro2::LineColumn; use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; - #[cfg(procmacro2_semver_exempt)] - use proc_macro2::{LineColumn, SourceFile}; use std::panic::{RefUnwindSafe, UnwindSafe}; macro_rules! assert_unwind_safe { @@ -95,6 +93,5 @@ #[cfg(procmacro2_semver_exempt)] assert_unwind_safe! { LineColumn - SourceFile } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/test.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/test.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,7 +4,8 @@ clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::non_ascii_literal, - clippy::octal_escapes + clippy::octal_escapes, + clippy::uninlined_format_args )] use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; @@ -145,6 +146,30 @@ .unwrap_err(); } +#[cfg(procmacro2_semver_exempt)] +#[test] +fn literal_string_value() { + for string in ["", "...", "...\t...", "...\\...", "...\0...", "...\u{1}..."] { + assert_eq!(string, Literal::string(string).str_value().unwrap()); + assert_eq!( + string, + format!("r\"{string}\"") + .parse::() + .unwrap() + .str_value() + .unwrap(), + ); + assert_eq!( + string, + format!("r##\"{string}\"##") + .parse::() + .unwrap() + .str_value() + .unwrap(), + ); + } +} + #[test] fn literal_byte_character() { #[track_caller] @@ -190,6 +215,42 @@ "br\"\u{a0}\"".parse::().unwrap_err(); } +#[cfg(procmacro2_semver_exempt)] +#[test] +fn literal_byte_string_value() { + for bytestr in [ + &b""[..], + b"...", + b"...\t...", + b"...\\...", + b"...\0...", + b"...\xF0...", + ] { + assert_eq!( + bytestr, + Literal::byte_string(bytestr).byte_str_value().unwrap(), + ); + if let Ok(string) = str::from_utf8(bytestr) { + assert_eq!( + bytestr, + format!("br\"{string}\"") + .parse::() + .unwrap() + .byte_str_value() + .unwrap(), + ); + assert_eq!( + bytestr, + format!("br##\"{string}\"##") + .parse::() + .unwrap() + .byte_str_value() + .unwrap(), + ); + } + } +} + #[test] fn literal_c_string() { #[track_caller] @@ -261,6 +322,42 @@ } } +#[cfg(procmacro2_semver_exempt)] +#[test] +fn literal_c_string_value() { + for cstr in [ + c"", + c"...", + c"...\t...", + c"...\\...", + c"...\u{1}...", + c"...\xF0...", + ] { + assert_eq!( + cstr.to_bytes_with_nul(), + Literal::c_string(cstr).cstr_value().unwrap(), + ); + if let Ok(string) = cstr.to_str() { + assert_eq!( + cstr.to_bytes_with_nul(), + format!("cr\"{string}\"") + .parse::() + .unwrap() + .cstr_value() + .unwrap(), + ); + assert_eq!( + cstr.to_bytes_with_nul(), + format!("cr##\"{string}\"##") + .parse::() + .unwrap() + .cstr_value() + .unwrap(), + ); + } + } +} + #[test] fn literal_character() { #[track_caller] @@ -454,6 +551,81 @@ } #[test] +fn lifetimes() { + let mut tokens = "'a 'static 'struct 'r#gen 'r#prefix#lifetime" + .parse::() + .unwrap() + .into_iter(); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '\'' && punct.spacing() == Spacing::Joint + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "a", + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '\'' && punct.spacing() == Spacing::Joint + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "static", + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '\'' && punct.spacing() == Spacing::Joint + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "struct", + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '\'' && punct.spacing() == Spacing::Joint + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "r#gen", + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '\'' && punct.spacing() == Spacing::Joint + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "r#prefix", + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Punct(punct)) => { + punct.as_char() == '#' && punct.spacing() == Spacing::Alone + } + _ => false, + }); + assert!(match tokens.next() { + Some(TokenTree::Ident(ident)) => ident == "lifetime", + _ => false, + }); + + "' a".parse::().unwrap_err(); + "' r#gen".parse::().unwrap_err(); + "' prefix#lifetime".parse::().unwrap_err(); + "'prefix#lifetime".parse::().unwrap_err(); + "'aa'bb".parse::().unwrap_err(); + "'r#gen'a".parse::().unwrap_err(); +} + +#[test] fn roundtrip() { fn roundtrip(p: &str) { println!("parse: {}", p); @@ -541,7 +713,6 @@ } #[cfg(procmacro2_semver_exempt)] -#[cfg(not(nightly))] #[test] fn default_span() { let start = Span::call_site().start(); @@ -550,9 +721,8 @@ let end = Span::call_site().end(); assert_eq!(end.line, 1); assert_eq!(end.column, 0); - let source_file = Span::call_site().source_file(); - assert_eq!(source_file.path().to_string_lossy(), ""); - assert!(!source_file.is_real()); + assert_eq!(Span::call_site().file(), ""); + assert!(Span::call_site().local_file().is_none()); } #[cfg(procmacro2_semver_exempt)] @@ -569,11 +739,8 @@ .into_iter() .collect::>(); - assert!(source1[0].span().source_file() != source2[0].span().source_file()); - assert_eq!( - source1[0].span().source_file(), - source1[1].span().source_file() - ); + assert!(source1[0].span().file() != source2[0].span().file()); + assert_eq!(source1[0].span().file(), source1[1].span().file()); let joined1 = source1[0].span().join(source1[1].span()); let joined2 = source1[0].span().join(source2[0].span()); @@ -587,10 +754,7 @@ assert_eq!(end.line, 2); assert_eq!(end.column, 3); - assert_eq!( - joined1.unwrap().source_file(), - source1[0].span().source_file() - ); + assert_eq!(joined1.unwrap().file(), source1[0].span().file()); } #[test] @@ -620,9 +784,8 @@ let joint_punct = Punct::new(':', Spacing::Joint); let stream = TokenStream::from(TokenTree::Punct(joint_punct)); - let punct = match stream.into_iter().next().unwrap() { - TokenTree::Punct(punct) => punct, - _ => unreachable!(), + let TokenTree::Punct(punct) = stream.into_iter().next().unwrap() else { + unreachable!(); }; assert_eq!(punct.spacing(), Spacing::Joint); } @@ -638,19 +801,43 @@ } #[test] -fn test_debug_ident() { +fn test_display_ident() { let ident = Ident::new("proc_macro", Span::call_site()); + assert_eq!(format!("{ident}"), "proc_macro"); + assert_eq!(format!("{ident:-^14}"), "proc_macro"); - #[cfg(not(span_locations))] - let expected = "Ident(proc_macro)"; + let ident = Ident::new_raw("proc_macro", Span::call_site()); + assert_eq!(format!("{ident}"), "r#proc_macro"); + assert_eq!(format!("{ident:-^14}"), "r#proc_macro"); +} - #[cfg(span_locations)] - let expected = "Ident { sym: proc_macro }"; +#[test] +fn test_debug_ident() { + let ident = Ident::new("proc_macro", Span::call_site()); + let expected = if cfg!(span_locations) { + "Ident { sym: proc_macro }" + } else { + "Ident(proc_macro)" + }; + assert_eq!(expected, format!("{:?}", ident)); + let ident = Ident::new_raw("proc_macro", Span::call_site()); + let expected = if cfg!(span_locations) { + "Ident { sym: r#proc_macro }" + } else { + "Ident(r#proc_macro)" + }; assert_eq!(expected, format!("{:?}", ident)); } #[test] +fn test_display_tokenstream() { + let tts = TokenStream::from_str("[a + 1]").unwrap(); + assert_eq!(format!("{tts}"), "[a + 1]"); + assert_eq!(format!("{tts:-^5}"), "[a + 1]"); +} + +#[test] fn test_debug_tokenstream() { let tts = TokenStream::from_str("[a + 1]").unwrap(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/test_size.rs clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test_size.rs --- clamav-1.4.3+dfsg/.cargo/vendor/proc-macro2/tests/test_size.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/proc-macro2/tests/test_size.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,42 +1,79 @@ +#![allow(unused_attributes)] + extern crate proc_macro; use std::mem; -#[rustversion::attr(before(1.32), ignore)] +#[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] +#[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[test] -fn test_proc_macro_span_size() { +fn test_proc_macro_size() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 4); + assert_eq!(mem::size_of::(), 20); + assert_eq!(mem::size_of::(), 12); + assert_eq!(mem::size_of::(), 8); + assert_eq!(mem::size_of::(), 16); + assert_eq!(mem::size_of::(), 4); } -#[cfg_attr(not(all(not(wrap_proc_macro), not(span_locations))), ignore)] +#[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] +#[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] +#[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] +#[cfg_attr(span_locations, ignore = "span locations are on")] #[test] -fn test_proc_macro2_fallback_span_size_without_locations() { +fn test_proc_macro2_fallback_size_without_locations() { assert_eq!(mem::size_of::(), 0); assert_eq!(mem::size_of::>(), 1); + assert_eq!(mem::size_of::(), 16); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 8); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 8); } -#[cfg_attr(not(all(not(wrap_proc_macro), span_locations)), ignore)] +#[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] +#[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] +#[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] +#[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] -fn test_proc_macro2_fallback_span_size_with_locations() { +fn test_proc_macro2_fallback_size_with_locations() { assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::>(), 12); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 32); + assert_eq!(mem::size_of::(), 16); + assert_eq!(mem::size_of::(), 32); + assert_eq!(mem::size_of::(), 8); } -#[rustversion::attr(before(1.32), ignore)] -#[rustversion::attr( - since(1.32), - cfg_attr(not(all(wrap_proc_macro, not(span_locations))), ignore) -)] +#[rustversion::attr(before(1.71), ignore = "requires Rust 1.71+")] +#[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] +#[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] +#[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] +#[cfg_attr(span_locations, ignore = "span locations are on")] #[test] -fn test_proc_macro2_wrapper_span_size_without_locations() { +fn test_proc_macro2_wrapper_size_without_locations() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 8); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 12); + assert_eq!(mem::size_of::(), 24); + assert_eq!(mem::size_of::(), 32); } -#[cfg_attr(not(all(wrap_proc_macro, span_locations)), ignore)] +#[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] +#[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] +#[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] +#[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] -fn test_proc_macro2_wrapper_span_size_with_locations() { +fn test_proc_macro2_wrapper_size_with_locations() { assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::>(), 12); + assert_eq!(mem::size_of::(), 32); + assert_eq!(mem::size_of::(), 32); + assert_eq!(mem::size_of::(), 20); + assert_eq!(mem::size_of::(), 32); + assert_eq!(mem::size_of::(), 32); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"e5a98684e0a7fefd5968abeda46bc88f653d9fad4c0d8a63373020b043dd45ba","Cargo.lock":"34646e287d15fc4c25eee86a0fe4b016add9f1304c5966241bf08ad5299a51cc","Cargo.toml":"f0aa8099638ae52d2d33a774c546af0342b0ba7585a5af2f5deef9a2c5564a3a","Cargo.toml.orig":"dc822869139176bfdf3af32081e3bba5eee2c017f4c38732c01625158d62b38c","README.md":"970c9abdb06b09f7cdb52ab5b5d578e2c928d0b909320c24fcdac9e526d45b1a","src/empty_impl.rs":"4d6ee3bb4add86d8b01a7ae5f319dce7b463d89e724dfcb031c3239fb1229eec","src/lib.rs":"2eb645fff043b95ac6e37b5304f0d1b0fe6d7935c68a644f21c4d6dd83aa1907","src/optick_impl.rs":"92430474c21bc49c3e54d8073b215772850d2498abf600d7c54cfd8acd92e5c6","src/puffin_impl.rs":"8d859ef3ca3f1deda8981ba9b9e7b9d3f2ea3c4417526d9ec4d188bc3806c167","src/superluminal_impl.rs":"061fe63327a9f4dbb5632f26482e44212aa08f8e26e60170076785fd279f2e5c","src/tracing_impl.rs":"94b74d71928478402863d85dcbb66e96da2268745ca5434106d1374b89b54261","src/tracy_impl.rs":"1b632448ed75bd698d3ed9067afdf05f60caec7a55ebf0258e2519afb951f890","src/type_check_impl.rs":"230d91cabf46a63f46e4a0e2764537634e6b10bdb879d44e21dd4ed02a12ad54"},"package":"3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "740d74c82212f1f0584cfa5c6d884c5ab5367101" + }, + "path_in_vcs": "profiling" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,786 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "optick" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7e7ab6068cdba9928db83674b18fe7aa2efbaa9920698d260ecbaf7906c6548" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +dependencies = [ + "bincode", + "env_logger", + "lazy_static", + "log", + "optick", + "profiling-procmacros", + "puffin", + "superluminal-perf", + "tracing", + "tracing-subscriber", + "tracing-tracy", + "tracy-client", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "puffin" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9dae7b05c02ec1a6bc9bcf20d8bc64a7dcbf57934107902a872014899b741f" +dependencies = [ + "anyhow", + "byteorder", + "cfg-if", + "itertools", + "once_cell", + "parking_lot", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "superluminal-perf" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f25a01f65079fdaf562930db1293d7a4abd4d98346a450cb7f37073af5c2b10" +dependencies = [ + "superluminal-perf-sys", +] + +[[package]] +name = "superluminal-perf-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83d163f90b68349a742c75793727483b4d90a7bc77b7db434c79650f0b127e7" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-tracy" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracy-client", +] + +[[package]] +name = "tracy-client" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3927832d93178f979a970d26deed7b03510586e328f31b0f9ad7a73985b8332a" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c032d68a49d25d9012a864fef1c64ac17aee43c87e0477bf7301d8ae8bfea7b7" +dependencies = [ + "cc", + "windows-targets", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,107 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.60" +name = "profiling" +version = "1.0.17" +authors = ["Philip Degarmo "] +build = false +exclude = [ + "/examples", + "/screenshots", +] +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "This crate provides a very thin abstraction over other profiler crates." +homepage = "https://github.com/aclysma/profiling" +readme = "README.md" +keywords = [ + "performance", + "profiling", +] +categories = ["development-tools::profiling"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/aclysma/profiling" + +[lib] +name = "profiling" +path = "src/lib.rs" + +[dependencies.optick] +version = "1.3" +optional = true + +[dependencies.profiling-procmacros] +version = "1.0.17" +optional = true + +[dependencies.puffin] +version = "0.19" +optional = true + +[dependencies.superluminal-perf] +version = "0.4" +optional = true + +[dependencies.tracing] +version = "0.1" +optional = true + +[dependencies.tracy-client] +version = "0.18" +optional = true + +[dev-dependencies.bincode] +version = "1.3.1" + +[dev-dependencies.env_logger] +version = "0.6" + +[dev-dependencies.lazy_static] +version = "1" + +[dev-dependencies.log] +version = "0.4" + +[dev-dependencies.tracing-subscriber] +version = "0.3" + +[dev-dependencies.tracing-tracy] +version = "0.11.3" + +[features] +default = ["procmacros"] +procmacros = ["profiling-procmacros"] +profile-with-optick = [ + "optick", + "profiling-procmacros?/profile-with-optick", +] +profile-with-puffin = [ + "puffin", + "profiling-procmacros?/profile-with-puffin", +] +profile-with-superluminal = [ + "superluminal-perf", + "profiling-procmacros?/profile-with-superluminal", +] +profile-with-tracing = [ + "tracing", + "profiling-procmacros?/profile-with-tracing", +] +profile-with-tracy = [ + "tracy-client", + "profiling-procmacros?/profile-with-tracy", +] +type-check = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +[package] +name = "profiling" +version = "1.0.17" +authors = ["Philip Degarmo "] +edition = "2018" +description = "This crate provides a very thin abstraction over other profiler crates." +license = "MIT OR Apache-2.0" +readme = "../README.md" +repository = "https://github.com/aclysma/profiling" +homepage = "https://github.com/aclysma/profiling" +keywords = ["performance", "profiling"] +categories = ["development-tools::profiling"] +exclude = ["/examples", "/screenshots"] +rust-version = "1.60" + +[dependencies] +puffin = { version = "0.19", optional = true } +optick = { version = "1.3", optional = true } +tracing = { version = "0.1", optional = true } +tracy-client = { version = "0.18", optional = true } +superluminal-perf = { version = "0.4", optional = true } +profiling-procmacros = { version = "1.0.17", path = "../profiling-procmacros", optional = true } + +[dev-dependencies] +bincode = "1.3.1" +lazy_static = "1" +log = "0.4" +env_logger = "0.6" + +tracing-tracy = { version = "0.11.3" } +tracing-subscriber = { version = "0.3" } + +[features] +default = ["procmacros"] +profile-with-puffin = ["puffin", "profiling-procmacros?/profile-with-puffin"] +profile-with-optick = ["optick", "profiling-procmacros?/profile-with-optick"] +profile-with-superluminal = [ + "superluminal-perf", + "profiling-procmacros?/profile-with-superluminal", +] +profile-with-tracing = ["tracing", "profiling-procmacros?/profile-with-tracing"] +profile-with-tracy = [ + "tracy-client", + "profiling-procmacros?/profile-with-tracy", +] +type-check = [] +procmacros = ["profiling-procmacros"] + +[[example]] +name = "simple" +path = "examples/simple.rs" +required-features = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/README.md clamav-1.4.6+dfsg/.cargo/vendor/profiling/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,246 @@ +# profiling + +Provides a very thin abstraction over instrumented profiling crates like `puffin`, `optick`, `tracy`, and `superluminal-perf`. + +Mark up your code like this: + +```rust +#[profiling::function] +fn some_function() { + burn_time(5); + + for i in 0..5 { + profiling::scope!("Looped Operation"); + } +} +``` + +See below for resulting visualization and more details on the exposed API. + +**Friendly Warning:** Some profiler backends implicitly listen on network ports immediately when the host app is +launched. If this is a concern, please review the enabled profiler(s) documentation for details! + +## Puffin + +* https://github.com/EmbarkStudios/puffin +* Cross-platform +* You need to call `profiling::finish_frame!()` at least once per frame +* To show the flamegraph, you either need to use [`puffin_http`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_http`) and [`puffin_viewer`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_viewer`), or if you're writing an [`egui`](https://github.com/emilk/egui) app, use [`puffin_egui`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_egui`). + +[![Puffin](screenshots/puffin-small.png)](screenshots/puffin.png) + +## Optick + +* https://github.com/bombomby/optick +* The upstream crate only provides binaries for windows. However it could probably be made to work by building +optick capture code and linking against it manually. The UI is windows only. + +[![Optick](screenshots/optick-small.png)](screenshots/optick.jpeg) + +## Superluminal + +* https://superluminal.eu +* Windows only + +[![Superluminal](screenshots/superluminal-small.png)](screenshots/superluminal.jpeg) + +## Tracing + +* https://crates.io/crates/tracing +* Cross-platform +* The tracing backend injects tracing `span!()` macros that match the lifetime of the profiling macros. +Tracing uses callbacks rather than inlining specific pre-determined code, +so it is more flexible than profiling +(at the cost of more lines of code and potentially higher overhead). +This allows existing and new tracing-compatible handlers to work with profiling. + +![Tracing](screenshots/tracing.png) + +## Tracy + +* https://github.com/wolfpld/tracy +* Cross-platform (windows, macOS, linux) + +[![Tracy](screenshots/tracy-small.png)](screenshots/tracy.jpeg) + +## Usage + +Currently, there's just six macros: + * `profiling::scope!(name: &str, [tag: &str])` + * name: scopes will appear in the profiler under this name + * tag: optional extra data + * For maximum compatibility, you are **strongly** recommended to use literal strings for the name. Some backends require + static lifetime string references and some require literal strings. + * `#[profiling::function]` + * procmacro placed on a function to quickly wrap it in a scope using the function name + * `#[profiling::all_functions]` + * procmacro placed on a struct impl block to apply `#[profiling::function]` on each function under that struct impl block + * `#[profiling::skip]` + * use with `#[profiling::all_functions]`, placed this procmacro on a function to avoid the action that `#[profiling::all_functions]` apply + * `profiling::register_thread!([name: &str])` + * name: optional, defaults to `std::thread::current().name`, or `.id` if it's unnamed + * `profiling::finish_frame!()` + * Many profilers have the concept of a "frame" as a unit of work. Use this to indicate where one frame ends and the + next one begins. + * `profiling::function_scope!([tag: &str])` + * Macro that can be placed within a function to create a scope with the function name + * tag: optional extra data + +Support for individual profilers can be turned on/off with feature flags. By default, they're all off, resulting in +no dependencies or runtime code. + +## Who is this for? + * Authors of binaries that want to have multiple options for profiling their code, but don't want to duplicate their + instrumentation once per each profiler's individual API. + * Authors of libraries that would like to instrument their crate for their end-users. + +This crate is intended to be **TINY**. It won't support every possible usage, just the basics. I'm open to adding +more things but I plan to be very selective to maintain a slim size. + +When enabled, using a macro produces identical code as if you used the wrapped profiling API directly. So it is +completely fine to directly use a profiler's API when this abstraction doesn't support something you want to do. + +## Alternatives + +**tracing**: `tracing` is more flexible than `profiling` but is significantly larger and has +some potential runtime cost. `profiling` is only useful for instrumented profiling. Instrumentation is inserted directly +into your code inline via macros as if you were using the profiler's crate directly. This results in smaller code with +no additional overhead. + +Using profiling crates (i.e. puffin/optick/etc.) directly: + * For authors of binaries, you may still need to use APIs on those crates to get started. But when instrumenting your + code, `profiling::scope!("Scope Name")` inside a function or `#[profiling::function]` on a function will instrument + it for all the supported profiler-specific crates. You can still use those crates directly if you want to take + advantage of custom APIs they provide to surface additional data. + * For authors of upstream libraries, this crate lets you implement simple instrumentation once. Hopefully this will + allow the community to benefit from instrumented profiling, even if a significant amount of a codebase is made + of upstream crates. + +## Using from a Binary + +It's up to you to initialize the profiling crate of your choice (although some do not need explicit initialization +and will immediately work). The examples demonstrate this for all the supported crates, but it's worth looking +at the docs for the profiler you're interested in using! `profiling` re-exports the profiler crates if they are +enabled, simplifying the modifications you would need to make to your Cargo.toml. + +Once initialized, you can mix/match the macros provided by your profiler of choice and the generic ones in this +crate. For example: + +```rust +// This may map to something like: +// - puffin::profile_scope!("Scope Name") +// - optick::event!("Scope Name") +// - tracing::span!(tracing::Level::INFO, "Scope Name") +// - superluminal_perf::begin_event("Scope Name") +profiling::scope!("Scope Name"); + +// This may map to something like: +// - puffin::profile_scope_data!("Scope Name", "extra data") +// - optick::event!("Scope Name"); optick::tag!("tag", "extra data"); +// - tracing::span!(tracing::Level::INFO, "Scope Name", tag = "extra data") +// - superluminal_perf::begin_event_with_data("Scope Name", "extra data", 0) +profiling::scope!("Scope Name", "extra data"); +``` + +There is also a proc macro to decorate functions: + +```rust +#[profiling::function] +fn my_function() { + +} +``` + +Take a look at the code for the helpful macros `register_thread!()` and `finish_frame!()`. + +I recommend adding features for each backend you want to use to your binary crate. This allows you to optionally compile +in code to setup and configure a backend. + +```toml +[dependencies] +profiling = "1.0" + +[features] +profile-with-puffin = ["profiling/profile-with-puffin"] +profile-with-optick = ["profiling/profile-with-optick"] +profile-with-superluminal = ["profiling/profile-with-superluminal"] +profile-with-tracing = ["profiling/profile-with-tracing"] +profile-with-tracy = ["profiling/profile-with-tracy"] +``` + + * You can use the default feature to quickly/temporarily turn something on: `default = ["profile-with-optick"]` + * `cargo run --features=profile-with-optick` works too! + +## Using from a Library + +Add the profiling crate to Cargo.toml: + +```toml +[dependencies] +profiling = "1.0" +``` + +Now you can instrument your library using the API exposed via the `profiling` crate. + +If the end-user of your library doesn't use profiling, the macros in this crate will emit no code at all. + +## Feature Flags + + * profile-with-puffin: Enable the `puffin` crate + * profile-with-optick: Enable the `optick` crate + * profile-with-superluminal: Enable the `superluminal-perf` crate + * profile-with-tracing: Enable the `tracing` crate. (This is just an abstraction layer - you'd want to hook it to do something!) + * profile-with-tracy: Enable the `tracy-client` crate. + +**Only one backend can be enabled at a time!** + +## Examples + + * simple: Shows a bare minimum requirements to do some simple instrumented profiling. Once it's running, you + can connect to the process using optick/tracy/superluminal. Some of these are windows only! + +``` +run --example simple --features="profile-with-optick" +run --example simple --features="profile-with-tracy" +run --example simple --features="profile-with-puffin" +run --example simple --features="profile-with-superluminal" +``` + + * puffin: Launches a basic app with imgui integration showing the puffin UI. This one should run everywhere + that supports imgui. + +``` +cargo run --example puffin --features="profile-with-puffin" +``` + +## MSRV + +This project will strive to keep a conservative MSRV, but some backends will support a lower MSRV than others. +The MSRV set in this project only represents the MSRV for compiling the profiling crate with no backends +enabled. + +As a point of reference, currently the most popular crate relying on profiling is wgpu, and their +MSRV is constrained to Firefox nightly build MSRV. So the MSRV of this crate (ignoring backends) +should not move faster than wgpu and firefox nightly. (See `MINIMUM_RUST_VERSION` in +[`python/mozboot/mozboot/util.py`](https://searchfox.org/mozilla-central/source/python/mozboot/mozboot/util.py)) + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +The examples directory contains [`NotoSans-Medium.ttf`](https://www.google.com/get/noto/), available under SIL Open Font +License (OFL). + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/empty_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/empty_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/empty_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/empty_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +/// Opens a scope. Two variants: +/// - profiling::scope!(name: &str) - Opens a scope with the given name +/// - profiling::scope!(name: &str, data: &str) - Opens a scope with the given name and an extra +/// datafield. Details of this depend on the API, but it should be a &str. If the extra data is +/// named, it will be named "tag". Some APIs support adding more data (for example, `optic::tag!`) +/// +/// ``` +/// profiling::scope!("outer"); +/// for _ in 0..10 { +/// profiling::scope!("inner", format!("iteration {}").as_str()); +/// } +/// ``` +#[macro_export] +macro_rules! scope { + ($name:expr) => {}; + ($name:expr, $data:expr) => {}; +} + +/// Opens a scope automatically named after the current function. +/// - profiling::function_scope!() - Opens a scope with the current function name +/// - profiling::function_scope!(data: &str) - Opens a scope with the current function name and an extra data field. +/// +/// ``` +/// fn function_a(){ +/// profiling::function_scope!(); +/// } +/// fn function_b(iteration: u32){ +/// profiling::function_scope!(format!("iteration {}", iteration).as_str()); +/// } +/// ``` +#[macro_export] +macro_rules! function_scope { + () => {}; + ($data:expr) => {}; +} + +/// Registers a thread with the profiler API(s). This is usually setting a name for the thread. +/// Two variants: +/// - register_thread!() - Tries to get the name of the thread, or an ID if no name is set +/// - register_thread!(name: &str) - Registers the thread using the given name +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => {}; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => {}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,167 @@ +// +// To use this library, enable one of the feature flags. Each backend implementation provides the +// exact same interface. Only one may be active at a time. +// + +// This library itself does not require std, but if any features are enabled, the upstream crate +// likely will bring in std. +#![no_std] + +/// Proc macro for creating a scope around each function under struct impl block +/// ``` +/// pub struct Foo { +/// // some data... +/// } +/// +/// #[profiling::all_functions] +/// impl Foo { +/// pub fn do_something(&self) { +/// // some code... +/// } +/// +/// pub fn do_otherthing(&self) { +/// // some code... +/// } +/// } +/// ``` +/// +/// The following will generate the same code +/// +/// ``` +/// pub struct Foo { +/// // some data... +/// } +/// +/// impl Foo { +/// #[profiling::function] +/// pub fn do_something(&self) { +/// // some code... +/// } +/// +/// #[profiling::function] +/// pub fn do_otherthing(&self) { +/// // some code... +/// } +/// } +/// ``` +#[cfg(feature = "procmacros")] +pub use profiling_procmacros::all_functions; +/// Proc macro for creating a scope around the function, using the name of the function for the +/// scope's name +/// +/// This must be done as a proc macro because tracing requires a const string +/// +/// ``` +/// #[profiling::function] +/// fn my_function() { +/// +/// } +/// ``` +#[cfg(feature = "procmacros")] +pub use profiling_procmacros::function; +/// Proc macro to skip the auto_impl for the function +/// ``` +/// pub struct Foo { +/// // some data... +/// } +/// +/// #[profiling::all_functions] +/// impl Foo { +/// pub fn do_something(&self) { +/// // some code... +/// } +/// +/// #[profiling::skip] +/// pub fn do_otherthing(&self) { +/// // some code... +/// } +/// } +/// ``` +/// +/// The following will generate the same code +/// +/// ``` +/// pub struct Foo { +/// // some data... +/// } +/// +/// impl Foo { +/// #[profiling::function] +/// pub fn do_something(&self) { +/// // some code... +/// } +/// +/// pub fn do_otherthing(&self) { +/// // some code... +/// } +/// } +/// ``` +#[cfg(feature = "procmacros")] +pub use profiling_procmacros::skip; + +#[cfg(feature = "profile-with-puffin")] +pub use puffin; +#[cfg(feature = "profile-with-puffin")] +mod puffin_impl; +#[cfg(feature = "profile-with-puffin")] +#[allow(unused_imports)] +pub use puffin_impl::*; + +#[cfg(feature = "profile-with-optick")] +pub use optick; +#[cfg(feature = "profile-with-optick")] +mod optick_impl; +#[cfg(feature = "profile-with-optick")] +#[allow(unused_imports)] +pub use optick_impl::*; + +#[cfg(feature = "profile-with-superluminal")] +pub use superluminal_perf; +#[cfg(feature = "profile-with-superluminal")] +mod superluminal_impl; +#[cfg(feature = "profile-with-superluminal")] +#[allow(unused_imports)] +pub use superluminal_impl::*; + +#[cfg(feature = "profile-with-tracing")] +pub use tracing; +#[cfg(feature = "profile-with-tracing")] +mod tracing_impl; +#[cfg(feature = "profile-with-tracing")] +#[allow(unused_imports)] +pub use tracing_impl::*; + +#[cfg(feature = "profile-with-tracy")] +pub use tracy_client; +#[cfg(feature = "profile-with-tracy")] +mod tracy_impl; +#[cfg(feature = "profile-with-tracy")] +#[allow(unused_imports)] +pub use tracy_impl::*; + +#[cfg(feature = "type-check")] +mod type_check_impl; +#[cfg(feature = "type-check")] +#[allow(unused_imports)] +pub use type_check_impl::*; + +#[cfg(not(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracing", + feature = "profile-with-tracy", + feature = "type-check" +)))] +mod empty_impl; + +#[cfg(not(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracing", + feature = "profile-with-tracy", + feature = "type-check" +)))] +#[allow(unused_imports)] +pub use empty_impl::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/optick_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/optick_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/optick_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/optick_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + $crate::optick::event!($name); + }; + // NOTE: I've not been able to get attached data to work with optick + ($name:expr, $data:expr) => { + $crate::optick::event!($name); + $crate::optick::tag!("tag", $data); + }; +} + +#[macro_export] +macro_rules! function_scope { + () => { + $crate::optick::event!(); + }; + ($data:expr) => { + $crate::optick::event!(); + $crate::optick::tag!("tag", $data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::optick::register_thread($name); + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::optick::next_frame(); + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/puffin_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/puffin_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/puffin_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/puffin_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + $crate::puffin::profile_scope!($name); + }; + ($name:expr, $data:expr) => { + $crate::puffin::profile_scope!($name, $data); + }; +} + +#[macro_export] +macro_rules! function_scope { + () => { + $crate::puffin::profile_function!(); + }; + ($data:expr) => { + $crate::puffin::profile_function!($data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => { + // puffin uses the thread name + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::puffin::GlobalProfiler::lock().new_frame(); + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/superluminal_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/superluminal_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/superluminal_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/superluminal_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _superluminal_guard = $crate::superluminal::SuperluminalGuard::new($name); + }; + ($name:expr, $data:expr) => { + let _superluminal_guard = + $crate::superluminal::SuperluminalGuard::new_with_data($name, $data); + }; +} + +#[macro_export] +macro_rules! function_scope { + () => { + let _function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + $crate::scope!(_function_name); + }; + ($data:expr) => { + let _function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + $crate::scope!(_function_name, $data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::superluminal_perf::set_current_thread_name($name); + }; +} + +#[macro_export] +macro_rules! finish_frame { + () => { + // superluminal does not have a frame end function + }; +} + +// +// RAII wrappers to support superluminal. These are public as they need to be callable from macros +// but are not intended for direct use. +// +#[doc(hidden)] +pub mod superluminal { + pub struct SuperluminalGuard; + + // 0xFFFFFFFF means "use default color" + const DEFAULT_SUPERLUMINAL_COLOR: u32 = 0xFFFFFFFF; + + impl SuperluminalGuard { + pub fn new(name: &'static str) -> Self { + superluminal_perf::begin_event(name); + SuperluminalGuard + } + + pub fn new_with_data( + name: &'static str, + data: &str, + ) -> Self { + superluminal_perf::begin_event_with_data(name, data, DEFAULT_SUPERLUMINAL_COLOR); + SuperluminalGuard + } + } + + impl Drop for SuperluminalGuard { + fn drop(&mut self) { + superluminal_perf::end_event(); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/tracing_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracing_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/tracing_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracing_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _span = $crate::tracing::span!($crate::tracing::Level::INFO, $name); + let _span_entered = _span.enter(); + }; + ($name:expr, $data:expr) => { + let _span = $crate::tracing::span!($crate::tracing::Level::INFO, $name, tag = $data); + let _span_entered = _span.enter(); + }; +} + +#[macro_export] +macro_rules! function_scope { + () => { + let function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + let _span = $crate::tracing::span!( + $crate::tracing::Level::INFO, + "function_scope", + "{}", + function_name + ); + let _span_entered = _span.enter(); + }; + ($data:expr) => { + let function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + let _span = $crate::tracing::span!( + $crate::tracing::Level::INFO, + "function_scope", + tag = $data, + "{}", + function_name + ); + let _span_entered = _span.enter(); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => {}; +} + +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::tracing::event!($crate::tracing::Level::INFO, tracy.frame_mark = true); + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/tracy_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracy_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/tracy_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/tracy_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,82 @@ +#[macro_export] +macro_rules! scope { + // Note: literal patterns provided as an optimization since they can skip an allocation. + ($name:literal) => { + // Note: callstack_depth is 0 since this has significant overhead + let _tracy_span = $crate::tracy_client::span!($name, 0); + }; + ($name:literal, $data:expr) => { + // Note: callstack_depth is 0 since this has significant overhead + let _tracy_span = $crate::tracy_client::span!($name, 0); + _tracy_span.emit_text($data); + }; + ($name:expr) => { + let _function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + let _tracy_span = $crate::tracy_client::Client::running() + .expect("scope! without a running tracy_client::Client") + // Note: callstack_depth is 0 since this has significant overhead + .span_alloc(Some($name), _function_name, file!(), line!(), 0); + }; + ($name:expr, $data:expr) => { + let _function_name = { + struct S; + let type_name = core::any::type_name::(); + &type_name[..type_name.len() - 3] + }; + let _tracy_span = $crate::tracy_client::Client::running() + .expect("scope! without a running tracy_client::Client") + // Note: callstack_depth is 0 since this has significant overhead + .span_alloc(Some($name), _function_name, file!(), line!(), 0); + _tracy_span.emit_text($data); + }; +} + +#[macro_export] +macro_rules! function_scope { + () => { + let _tracy_span = $crate::tracy_client::span!(); + }; + ($data:expr) => { + let _location = $crate::tracy_client::span_location!(); + let _tracy_span = $crate::tracy_client::Client::running() + .expect("function_scope! without a running tracy_client::Client") + .span(_location, 0); + _tracy_span.emit_text($data); + }; +} + +/// Registers a thread with the profiler API(s). This is usually setting a name for the thread. +/// Two variants: +/// - register_thread!() - Tries to get the name of the thread, or an ID if no name is set +/// - register_thread!(name: &str) - Registers the thread using the given name +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::tracy_client::Client::running() + .expect("register_thread! without a running tracy_client::Client") + .set_thread_name($name); + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::tracy_client::Client::running() + .expect("finish_frame! without a running tracy_client::Client") + .frame_mark(); + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/type_check_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/type_check_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling/src/type_check_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling/src/type_check_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +// This backend is intended to force type checking + +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _: &str = $name; + }; + ($name:expr, $data:expr) => { + let _: &str = $name; + let _: &str = $data; + }; +} + +#[macro_export] +macro_rules! function_scope { + () => {}; + ($data:expr) => { + let _: &str = $data; + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => { + let _: &str = $name; + }; +} + +#[macro_export] +macro_rules! finish_frame { + () => {}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"3bfee4a7ddbfa52ef162e2f9e0ff3359e3519ea715ed84a77fea24099d50f8ba","Cargo.toml":"952e7375dad002f92688b4c6378c631e73881e6cde9e5d3ba37b22ea301c49b2","Cargo.toml.orig":"43cedc78066cccd623e9bc6aa472f1bb142a628736fd2336b4c07d43b7d48dda","README.md":"970c9abdb06b09f7cdb52ab5b5d578e2c928d0b909320c24fcdac9e526d45b1a","src/lib.rs":"c3744fe4dd9595c1f9047a4c7fff0c49be565be4460a0dd539a218da3f70e717"},"package":"52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "740d74c82212f1f0584cfa5c6d884c5ab5367101" + }, + "path_in_vcs": "profiling-procmacros" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.65" +name = "profiling-procmacros" +version = "1.0.17" +authors = ["Philip Degarmo "] +build = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "This crate provides a very thin abstraction over other profiler crates." +homepage = "https://github.com/aclysma/profiling" +readme = "README.md" +keywords = [ + "performance", + "profiling", +] +categories = ["development-tools::profiling"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/aclysma/profiling" + +[lib] +name = "profiling_procmacros" +path = "src/lib.rs" +proc-macro = true + +[dependencies.quote] +version = "1.0" +default-features = false + +[dependencies.syn] +version = "2.0" +features = ["full"] + +[features] +profile-with-optick = [] +profile-with-puffin = [] +profile-with-superluminal = [] +profile-with-tracing = [] +profile-with-tracy = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +[package] +name = "profiling-procmacros" +version = "1.0.17" +authors = ["Philip Degarmo "] +edition = "2018" +description = "This crate provides a very thin abstraction over other profiler crates." +license = "MIT OR Apache-2.0" +readme = "../README.md" +repository = "https://github.com/aclysma/profiling" +homepage = "https://github.com/aclysma/profiling" +keywords = ["performance", "profiling"] +categories = ["development-tools::profiling"] +rust-version = "1.65" + +[dependencies] +quote = { version = "1.0", default-features = false } +syn = { version = "2.0", features = ["full"] } + +[lib] +proc-macro=true + +[features] +profile-with-puffin = [] +profile-with-optick = [] +profile-with-superluminal = [] +profile-with-tracing = [] +profile-with-tracy = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/README.md clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,246 @@ +# profiling + +Provides a very thin abstraction over instrumented profiling crates like `puffin`, `optick`, `tracy`, and `superluminal-perf`. + +Mark up your code like this: + +```rust +#[profiling::function] +fn some_function() { + burn_time(5); + + for i in 0..5 { + profiling::scope!("Looped Operation"); + } +} +``` + +See below for resulting visualization and more details on the exposed API. + +**Friendly Warning:** Some profiler backends implicitly listen on network ports immediately when the host app is +launched. If this is a concern, please review the enabled profiler(s) documentation for details! + +## Puffin + +* https://github.com/EmbarkStudios/puffin +* Cross-platform +* You need to call `profiling::finish_frame!()` at least once per frame +* To show the flamegraph, you either need to use [`puffin_http`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_http`) and [`puffin_viewer`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_viewer`), or if you're writing an [`egui`](https://github.com/emilk/egui) app, use [`puffin_egui`](`https://github.com/EmbarkStudios/puffin/tree/main/puffin_egui`). + +[![Puffin](screenshots/puffin-small.png)](screenshots/puffin.png) + +## Optick + +* https://github.com/bombomby/optick +* The upstream crate only provides binaries for windows. However it could probably be made to work by building +optick capture code and linking against it manually. The UI is windows only. + +[![Optick](screenshots/optick-small.png)](screenshots/optick.jpeg) + +## Superluminal + +* https://superluminal.eu +* Windows only + +[![Superluminal](screenshots/superluminal-small.png)](screenshots/superluminal.jpeg) + +## Tracing + +* https://crates.io/crates/tracing +* Cross-platform +* The tracing backend injects tracing `span!()` macros that match the lifetime of the profiling macros. +Tracing uses callbacks rather than inlining specific pre-determined code, +so it is more flexible than profiling +(at the cost of more lines of code and potentially higher overhead). +This allows existing and new tracing-compatible handlers to work with profiling. + +![Tracing](screenshots/tracing.png) + +## Tracy + +* https://github.com/wolfpld/tracy +* Cross-platform (windows, macOS, linux) + +[![Tracy](screenshots/tracy-small.png)](screenshots/tracy.jpeg) + +## Usage + +Currently, there's just six macros: + * `profiling::scope!(name: &str, [tag: &str])` + * name: scopes will appear in the profiler under this name + * tag: optional extra data + * For maximum compatibility, you are **strongly** recommended to use literal strings for the name. Some backends require + static lifetime string references and some require literal strings. + * `#[profiling::function]` + * procmacro placed on a function to quickly wrap it in a scope using the function name + * `#[profiling::all_functions]` + * procmacro placed on a struct impl block to apply `#[profiling::function]` on each function under that struct impl block + * `#[profiling::skip]` + * use with `#[profiling::all_functions]`, placed this procmacro on a function to avoid the action that `#[profiling::all_functions]` apply + * `profiling::register_thread!([name: &str])` + * name: optional, defaults to `std::thread::current().name`, or `.id` if it's unnamed + * `profiling::finish_frame!()` + * Many profilers have the concept of a "frame" as a unit of work. Use this to indicate where one frame ends and the + next one begins. + * `profiling::function_scope!([tag: &str])` + * Macro that can be placed within a function to create a scope with the function name + * tag: optional extra data + +Support for individual profilers can be turned on/off with feature flags. By default, they're all off, resulting in +no dependencies or runtime code. + +## Who is this for? + * Authors of binaries that want to have multiple options for profiling their code, but don't want to duplicate their + instrumentation once per each profiler's individual API. + * Authors of libraries that would like to instrument their crate for their end-users. + +This crate is intended to be **TINY**. It won't support every possible usage, just the basics. I'm open to adding +more things but I plan to be very selective to maintain a slim size. + +When enabled, using a macro produces identical code as if you used the wrapped profiling API directly. So it is +completely fine to directly use a profiler's API when this abstraction doesn't support something you want to do. + +## Alternatives + +**tracing**: `tracing` is more flexible than `profiling` but is significantly larger and has +some potential runtime cost. `profiling` is only useful for instrumented profiling. Instrumentation is inserted directly +into your code inline via macros as if you were using the profiler's crate directly. This results in smaller code with +no additional overhead. + +Using profiling crates (i.e. puffin/optick/etc.) directly: + * For authors of binaries, you may still need to use APIs on those crates to get started. But when instrumenting your + code, `profiling::scope!("Scope Name")` inside a function or `#[profiling::function]` on a function will instrument + it for all the supported profiler-specific crates. You can still use those crates directly if you want to take + advantage of custom APIs they provide to surface additional data. + * For authors of upstream libraries, this crate lets you implement simple instrumentation once. Hopefully this will + allow the community to benefit from instrumented profiling, even if a significant amount of a codebase is made + of upstream crates. + +## Using from a Binary + +It's up to you to initialize the profiling crate of your choice (although some do not need explicit initialization +and will immediately work). The examples demonstrate this for all the supported crates, but it's worth looking +at the docs for the profiler you're interested in using! `profiling` re-exports the profiler crates if they are +enabled, simplifying the modifications you would need to make to your Cargo.toml. + +Once initialized, you can mix/match the macros provided by your profiler of choice and the generic ones in this +crate. For example: + +```rust +// This may map to something like: +// - puffin::profile_scope!("Scope Name") +// - optick::event!("Scope Name") +// - tracing::span!(tracing::Level::INFO, "Scope Name") +// - superluminal_perf::begin_event("Scope Name") +profiling::scope!("Scope Name"); + +// This may map to something like: +// - puffin::profile_scope_data!("Scope Name", "extra data") +// - optick::event!("Scope Name"); optick::tag!("tag", "extra data"); +// - tracing::span!(tracing::Level::INFO, "Scope Name", tag = "extra data") +// - superluminal_perf::begin_event_with_data("Scope Name", "extra data", 0) +profiling::scope!("Scope Name", "extra data"); +``` + +There is also a proc macro to decorate functions: + +```rust +#[profiling::function] +fn my_function() { + +} +``` + +Take a look at the code for the helpful macros `register_thread!()` and `finish_frame!()`. + +I recommend adding features for each backend you want to use to your binary crate. This allows you to optionally compile +in code to setup and configure a backend. + +```toml +[dependencies] +profiling = "1.0" + +[features] +profile-with-puffin = ["profiling/profile-with-puffin"] +profile-with-optick = ["profiling/profile-with-optick"] +profile-with-superluminal = ["profiling/profile-with-superluminal"] +profile-with-tracing = ["profiling/profile-with-tracing"] +profile-with-tracy = ["profiling/profile-with-tracy"] +``` + + * You can use the default feature to quickly/temporarily turn something on: `default = ["profile-with-optick"]` + * `cargo run --features=profile-with-optick` works too! + +## Using from a Library + +Add the profiling crate to Cargo.toml: + +```toml +[dependencies] +profiling = "1.0" +``` + +Now you can instrument your library using the API exposed via the `profiling` crate. + +If the end-user of your library doesn't use profiling, the macros in this crate will emit no code at all. + +## Feature Flags + + * profile-with-puffin: Enable the `puffin` crate + * profile-with-optick: Enable the `optick` crate + * profile-with-superluminal: Enable the `superluminal-perf` crate + * profile-with-tracing: Enable the `tracing` crate. (This is just an abstraction layer - you'd want to hook it to do something!) + * profile-with-tracy: Enable the `tracy-client` crate. + +**Only one backend can be enabled at a time!** + +## Examples + + * simple: Shows a bare minimum requirements to do some simple instrumented profiling. Once it's running, you + can connect to the process using optick/tracy/superluminal. Some of these are windows only! + +``` +run --example simple --features="profile-with-optick" +run --example simple --features="profile-with-tracy" +run --example simple --features="profile-with-puffin" +run --example simple --features="profile-with-superluminal" +``` + + * puffin: Launches a basic app with imgui integration showing the puffin UI. This one should run everywhere + that supports imgui. + +``` +cargo run --example puffin --features="profile-with-puffin" +``` + +## MSRV + +This project will strive to keep a conservative MSRV, but some backends will support a lower MSRV than others. +The MSRV set in this project only represents the MSRV for compiling the profiling crate with no backends +enabled. + +As a point of reference, currently the most popular crate relying on profiling is wgpu, and their +MSRV is constrained to Firefox nightly build MSRV. So the MSRV of this crate (ignoring backends) +should not move faster than wgpu and firefox nightly. (See `MINIMUM_RUST_VERSION` in +[`python/mozboot/mozboot/util.py`](https://searchfox.org/mozilla-central/source/python/mozboot/mozboot/util.py)) + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +The examples directory contains [`NotoSans-Medium.ttf`](https://www.google.com/get/noto/), available under SIL Open Font +License (OFL). + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/profiling-procmacros/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/profiling-procmacros/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,140 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::{parse_macro_input, parse_quote, ImplItem, ItemFn, ItemImpl}; + +#[proc_macro_attribute] +pub fn function( + _attr: TokenStream, + item: TokenStream, +) -> TokenStream { + let mut function = parse_macro_input!(item as ItemFn); + let instrumented_function_name = function.sig.ident.to_string(); + + let body = &function.block; + let new_body: syn::Block = impl_block(body, &instrumented_function_name); + + function.block = Box::new(new_body); + + (quote! { + #function + }) + .into() +} + +#[proc_macro_attribute] +pub fn skip( + _attr: TokenStream, + item: TokenStream, +) -> TokenStream { + item +} + +#[proc_macro_attribute] +pub fn all_functions( + _attr: TokenStream, + item: TokenStream, +) -> TokenStream { + let mut content = parse_macro_input!(item as ItemImpl); + let struct_name = content.self_ty.to_token_stream().to_string(); + + 'func_loop: for block in &mut content.items { + // Currently, we only care about the function impl part. + // In the future, expand the code to following if we are interested in other parts + // + // match block { + // ImplItem::Fn(ref mut func) => { + // for func_attr in &func.attrs { + // if let syn::Meta::Path(ref func_attr_info) = func_attr.meta { + // let attr_seg = func_attr_info.segments.last().unwrap(); + // if attr_seg.ident.to_string() == "skip".to_string() { + // continue 'func_loop; + // } + // } + // } + // let prev_block = &func.block; + // let func_name = func.sig.ident.to_string(); + // func.block = impl_block(prev_block, &func_name); + // } + // ImplItem::Macro(_) => { // some code... }, + // ImplItem::Type(_) => { // some code... }, + // _ => {} + // } + let ImplItem::Fn(ref mut func) = block else { + continue; + }; + + for func_attr in &func.attrs { + let func_attr_info = func_attr.path(); + if func_attr_info.segments.is_empty() { + continue; + } + if func_attr_info.segments.first().unwrap().ident != "profiling" { + continue; + } + if func_attr_info.segments.last().unwrap().ident == "skip" { + continue 'func_loop; + } + } + let prev_block = &func.block; + let calling_info = format!("{}: {}", struct_name, func.sig.ident); + func.block = impl_block(prev_block, &calling_info); + } + + (quote!( + #content + )) + .into() +} + +#[cfg(not(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracing", + feature = "profile-with-tracy" +)))] +fn impl_block( + body: &syn::Block, + _instrumented_function_name: &str, +) -> syn::Block { + parse_quote! { + { + #body + } + } +} + +#[cfg(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracy" +))] +fn impl_block( + body: &syn::Block, + _instrumented_function_name: &str, +) -> syn::Block { + parse_quote! { + { + profiling::function_scope!(); + + #body + } + } +} + +#[cfg(feature = "profile-with-tracing")] +fn impl_block( + body: &syn::Block, + instrumented_function_name: &str, +) -> syn::Block { + parse_quote! { + { + let _fn_span = profiling::tracing::span!(profiling::tracing::Level::INFO, #instrumented_function_name); + let _fn_span_entered = _fn_span.enter(); + + #body + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"22ea53ad09f4f7d3bd03659bbda9986fd758245886f918912312f42507f94e76","Cargo.lock":"9f4e647c34bdc262c33f3b57ffd25c00de5ed4e6c7df16a7f979d39dfe78cd81","Cargo.toml":"24a64d70e909f08c0b20c0f07a5e31e5b202af8983638b3a5ae082ed29b44f8f","Cargo.toml.orig":"071837b84b652ef03ff4abf26707b403f3bba569cb84bc1bb7d24a88b23a82df","LICENSE-APACHE.md":"90bf2d659c43045111b65c733ab2a6d4cbcb422a098368c8c58a9ba3db4ed0c5","LICENSE.md":"2aa92cada6431e75615e3fe6cb1a9082c98f777d48ae1c087c0da0e37f7b8bff","README.md":"6801a6d052094d6161f7a832ed7c2982c6096584efaba100a4aaf4021d8e66b9","src/acos.rs":"a8d492160b69310c36731a5b52dffb8073a5e135af4a474a380f952c3cd47bd0","src/acosf.rs":"04b07a384a4e689c35807c184528895c34448ccb3fbe047fc129cc78350a3a9e","src/acospi.rs":"db7d06d0e6584d1c097953894acdd904608b6b04005d2c7bb22ff0ea902f6bf2","src/acospif.rs":"a1d3709047181429c5a534b3f970d45007a0c2687c0a6b31d77dd3dfc02602e7","src/asin.rs":"be04fc290354468067aec3af13c3ecde093cb237f4a7e0b0d4ae774b405606fd","src/asin_eval_dyadic.rs":"eb77ab0318b965f055f2ad75133a34e3f62f5e7e30bc8741b0960e990c3c61cd","src/asinf.rs":"786fdf6254ee13abbb1a37985f87627da036c06110171acb7005ee8db082e1c7","src/asinpi.rs":"417288fe78ec9d2bb920ef0113e6721102d6ec9c1e383d9f7fe0b3698bf8e5a4","src/asinpif.rs":"07136e6bca6d981f0241102ac4c6da8c4a366ff77f69a030ad9c6fed5f99275c","src/bessel/alpha0.rs":"7ebf163f01e259f37127a3c14e565260727d1fea1763c6e929dc2625a3037a4b","src/bessel/alpha1.rs":"e64dd1c5b8cb425fbfa8c8857490db1194517259f76a1c2e6cafe52b6310861d","src/bessel/bessel_exp.rs":"170bf2a70b682b5a267ac2e00652b818dd4fcf924af5f3b792be5c72facf3918","src/bessel/beta0.rs":"192c69967f0d9a4ef87476e21e9c50eb018945bbaee1e59f2c5a65e0880e6375","src/bessel/beta1.rs":"1a922c0e9ddd43ecf26a74e407138e53aea0703f74330a3b460b226231d9866b","src/bessel/i0.rs":"80f826010d6d46296c9528371f322742a3f74d5eaac1b52134a05ea042a8d8fa","src/bessel/i0e.rs":"f644f77a9527644b813b9bdf2644d00a0c268e9495b95c116053d26b688c2009","src/bessel/i0ef.rs":"1f4ec76b36bd2e31c9712231523d7469da26782a7eaaf81df66a89568987675c","src/bessel/i0f.rs":"b3a7d60cce60b9bec1d1d311a26c644c3e113a5fc320107560dadf5523a5b694","src/bessel/i1.rs":"8f2b48fafca29a9cea2b51f8915e1c56b944c759dc084bc7fd8988674694ea93","src/bessel/i1e.rs":"9d838fd45c6c543c6e7b4077719d00bf9a4228d452e8b85338b4713f305e3b86","src/bessel/i1ef.rs":"4c7686774e1177053c0146b30c0eeaf123f85d3184f2d9cc373ffccc70793696","src/bessel/i1f.rs":"6286c04a34ee5d429de2fe6d33806d1700e0b0378a55386ca3d7fba61aa22ad5","src/bessel/i2.rs":"97326976fd51eb5f0a98cd8f2753789d71261edb941c9ea0c2302ebe5ac68f3c","src/bessel/i2f.rs":"bd9d1ff3142c3ae34b0c6a014f4c2a9c43e1030f00b51bc679457f3c8b3ccb5f","src/bessel/j0.rs":"3b383587b8abb1fe3d1fd52815c91e7d7d200860ff735b233e5992118b6830ed","src/bessel/j0_coeffs_remez.rs":"6204dad4ddf69ff1023021a99feef8bf43d1aa8c73545082d8b49ce0281497b2","src/bessel/j0_coeffs_taylor.rs":"47fe8e937c8efce54781d97b097feb77767ae9041906cd2acf14cf9e599eb028","src/bessel/j0f.rs":"a9752ce8d51b7d6d9ea610cb7e3fd914e0f64ee4e16eeb9bf9704dde5c2c0ea6","src/bessel/j0f_coeffs.rs":"d40202a746b9e623cd1348b3140f7494408d30b66cb388dc7e7d7727a98d34d1","src/bessel/j1.rs":"4212692a87949c0fae13368f2f1c14d45c7e005d54b1e76a06667ef05bae9a8b","src/bessel/j1_coeffs.rs":"34f531655ef7b14475d9271fdf64655812e9aa945df6488d082eebbc8929b7d0","src/bessel/j1_coeffs_taylor.rs":"ba4909aa15fc13a3b88c1cbfd5f6c4354b197e4f62f0805dc07966845defc785","src/bessel/j1f.rs":"dd023c227d5f020c7b667c8428cd97e1f99ab4be83f3748ca65881080452ed6e","src/bessel/j1f_coeffs.rs":"f3ef1140498e55abb2ec09fb61ca554d0891aee0d91021fb0f51de5533687ff1","src/bessel/jincpi.rs":"d855d440c41bb4f1b5bc80f01069d4bf97d3f17af9bf3c0ea16d0b03087cbe9c","src/bessel/jincpif.rs":"195438fc0fe3ffb41d35b06b7d92a16d7d193320afebec0fb9018fce6b2cb502","src/bessel/k0.rs":"9b0dfed53c492b358b73000dc9b73ce846e28af0918b660e2feb4aead568a1d4","src/bessel/k0e.rs":"8f136c756b3758b9c05fb5d5942540ec56d1a05d80905bbe9c19e3e366df2f9f","src/bessel/k0ef.rs":"26f8adb91a5c9fcb1414fc05e021bac2c3d90236cf8a34dc7f6306af79ac59d4","src/bessel/k0f.rs":"15ed6238a4bb6601343dc8f871e1c6593b75cf968d4c00b3c87224841add7b8c","src/bessel/k1.rs":"8064dd00e71b5d84aec0098b53a43d0aace9db966440a3ca824d20f47681a524","src/bessel/k1e.rs":"a27e318a4cee29d04039db60f53b7fabd3bf264b7da30585bafae7f8ae72e18f","src/bessel/k1ef.rs":"c6df1fbfaeaf2d4a5c31855dbbccaea0dcaa56c8f313cd18f631b2316227d2e2","src/bessel/k1f.rs":"e76fa4ddb0af5322891218fc1b3bd73273c834e9bbd2d500df4ad13c914d5d1e","src/bessel/k2f.rs":"7e90f1bc220bfe98b51b69ac22a2d163254628e63cf8fcf74de1e59572c8278b","src/bessel/mod.rs":"f2ab47171df2618ea45a657bd17b90e597981fc31ac084fbd05b8e44291f0126","src/bessel/trigo_bessel.rs":"1ca01aca46c1227e2f9a30196a01e8077a099e8766e014a08d0dc3531da6ded5","src/bessel/y0.rs":"28627f80302df220153b713389bacabc10ca3797deeebb14f96a4e949322cdf5","src/bessel/y0_coeffs.rs":"f08da0d88e76c1ab23facb4eabc499f913c2a53a34b9f984271edb4fdf5ed419","src/bessel/y0_coeffs_taylor.rs":"40f172ccf604c4a8130604af2b5d0f1ca64afccbea348fb92062108b3b55a4cc","src/bessel/y0f.rs":"95e7e248e696095f34ac1ada2b38a0dca8f4bb6b577abbe359ef23b5c808781e","src/bessel/y0f_coeffs.rs":"30b363de4190f99e7350e21d87315350986120160264de4950d83a258fb49464","src/bessel/y1.rs":"ee9b48b6aeb9a0a1e9bc9e9e93f955e1486b17f8d06b8e154f0c7a0c61d149b5","src/bessel/y1_coeffs.rs":"458cb875f62a2b4334f845f7e53f0fa05883d7a2b0409e53dc142d2765bc3407","src/bessel/y1_coeffs_taylor.rs":"08965702b6fe117f41c26f4c46a2a71f0f85783b331872ecb9eb516e24ce8651","src/bessel/y1f.rs":"aa600a57b3b12098e56d052f5b1157060c853d3d7ee2500baa13870fad005306","src/bessel/y1f_coeffs.rs":"1ad75d7452cdecb4814d513cd96dd3084332932de939dbd5ba98af8751fce3b6","src/bits.rs":"c1dd9c8715e74c864297b44fc659551f28df301ea647465326a149e7421f0d77","src/common.rs":"793cba0d7e45d88fb1f96752cce607ffcdcf9f3a5cb9b999c87a95de83d6d97a","src/compound/compound_d.rs":"2373986e33ecedcb29e1910b4febc5e063d6c6ab0a57ad78f611c632bf08442f","src/compound/compound_m1.rs":"9ce50b5ffc7da1fa58f04d5955aa241244e8c2fea5afe2aa80db9d7ab3f98520","src/compound/compound_m1f.rs":"b1f8b02cf3ef72267d0350adc543604ebae41100ba9f964286e0b9bf9054dc99","src/compound/compoundf.rs":"fe814426b2417c8e0a743aaef67aeb080737fa30df793532f0160ce73ad792bc","src/compound/mod.rs":"53dd718f5f32c790f4d546fab39183607f1ec10ad39430ed83da914ce6ec1e6b","src/compound/powm1.rs":"f7f1ecae13a11dc1aa9d018dcbe783a2de0d8d8ecd4d8fd982cc691a8e8a86db","src/compound/powm1f.rs":"956ea1cd3d8b52112e6155409c34fd28040402cced629afa25fdd6993f277f78","src/cosm1.rs":"af463f39bfa2d9b3cce3ecdb62834eba249678dff1073ba4f42773a155df914e","src/csc.rs":"07b999eeecfa882c7029069ab49948be5744d1e34cb1303893928a4723af8f98","src/cube_roots/cbrt.rs":"73eb949b09b8c7442147d39cdc810878a021dcc5f821bf03907a7848f63d7a07","src/cube_roots/cbrtf.rs":"3ea8fb88ea5d380d790700945f3abf0716e026c8e328abcce27402e778825f8e","src/cube_roots/mod.rs":"2c983ef30479e84560b5917c1f7fd617110b61dfdc1ac62ee1d3e086d197f289","src/cube_roots/rcbrt.rs":"77cbec703a128cda3748f9ef6993e67d77550b76154d52510ffccac7da6cb622","src/cube_roots/rcbrtf.rs":"fea443c8ae9b1ac9c62e386d29258709f5aa3677a1c6978b3c0e18e00a11b812","src/double_double.rs":"a80c8af8bb0dc118437239d5cd43d138ee44e59ff7867ab534197cb9d1315f26","src/dyadic_float.rs":"f34b71d55119a61d1cc4081d9187b0ffca3a09f717517706189d1021898c087b","src/err/erf.rs":"20fe5cc475c4fb58d5f9fc70e0f65f0e89f1ab93e7f4b80d8f8347e34b2f1805","src/err/erf_poly.rs":"646a61db928506140a16d2735e0d658358f0417b5e9dcdffe106113975d58c1d","src/err/erfc.rs":"d235148c0eb7084b52bd0cd710b0393fd134b8a6dc6ea07b820f7988f99b2a2b","src/err/erfcx.rs":"78c46b5f55f1ede56eb8f6297cd25cceb2bdabfb4ba07f00a4c5c0ef33184d40","src/err/erfcxf.rs":"3994da904951b5d161a94df2b33867120f321e7f637fda310bb97f293def877a","src/err/erff.rs":"dba4e753e5c80713ab22b665254fb8015b6c9122e183a581cc62b9e5ede949cd","src/err/erffc.rs":"515bc3b610c1793a2c74abede586d8d47f36bf5a2a6dd4fec01f79d40186a77e","src/err/inverf.rs":"8c1a1118035a4da5fa4c05a33402fd77ba7c656f9d7f45e52e664e0c963985f8","src/err/inverfc.rs":"80dae9a4a7828a7b4d516b421b316c3b41ce501408f498d6b592f7299bb0de71","src/err/inverfcf.rs":"42a8c4060c6fb42967f41759c4eb5cd15b1f29ebb3a881d98b1a609180e77349","src/err/inverff.rs":"0aa75341b3a63ef6f3262f13fd671d680aae2734748a8eaa74b2412c8957bf76","src/err/mod.rs":"a0afef529216116a821f3dce17cbc4b7baa1d5a016e0a1cf8105a4d6cb7f7204","src/err/rerf.rs":"33bd9259ee605a4e408830445ec11313fe96b3440f55e0a05894b60346e8c01b","src/err/rerf_poly.rs":"3454eb7f0ab412ac3dfce3cbbeadd68e715dd2a84cfa849f6d505b3216346340","src/err/rerff.rs":"53fd2cc62f0077fb1a14c8f9ba03e8c34902c88bf596255d0c6ddf775f882d3d","src/exponents/auxiliary.rs":"c28d3fd0e8f330c7135bd1968680fab177d911c465195ce292c6ff519214202e","src/exponents/exp.rs":"12809f08c9057b6cd8714b33c596c4a05de877ce898a9a613bfda9526eadee8c","src/exponents/exp10.rs":"306024b06aa7515442e17b6bbad986fd5cc4c19e9d6fc9fd5bc10aa46d3fec75","src/exponents/exp10f.rs":"604ac825412c4c64a6d1406868ef3787369ee059bf93177109ab7c6306b20c75","src/exponents/exp10m1.rs":"df8e5596b898547506a7de8c19c48dca6a8151332bd43a0c0c96e65be54e3db0","src/exponents/exp10m1f.rs":"4d8c5a1c34a890a20e646068fb12b931ad383c896fb1eff157aab682bef3258f","src/exponents/exp2.rs":"e0a2896b5a4cb51bfb0e86d7e005a44ac9bf25e81b809781fb7684afa4538959","src/exponents/exp2f.rs":"26cb2148a423ec3510755977c96b7a8640744dcfc64b27a644201ff379e706eb","src/exponents/exp2m1.rs":"3edcf9e7357ae06f50680bd953a2aec2418147b57376ea2a441145ed2913e024","src/exponents/exp2m1f.rs":"31edd367096b1686710dd60f11d2085f3117134a52a927a9ac301dfa9c4dcd01","src/exponents/exp_f128.rs":"76b923bb6c930037d2260b2665fed5ea297eed4e001e852b15e22021660e2791","src/exponents/expf.rs":"8a85d8ef4040c6b7796b4cc77e616ad1949c039107bb6bde46378b116951f570","src/exponents/expm1.rs":"17e45db5d31704e0fa3501365927fc8c17fcbe48bfa08911f256f91cd2390007","src/exponents/expm1f.rs":"6c1aeeb924815fb6185dda314128ca165027b03389b48f8c00c437e882226fe9","src/exponents/logistic.rs":"d9aca2e16d469739bf33ec284613acbe5e2cde932272d6d4e883b6c9fad693f0","src/exponents/logisticf.rs":"a53af764cc1bb52367fdfd409993b52fe84464e80cc622f6cf39c82dff474852","src/exponents/mod.rs":"6ece4dd48846aa96ef941579db3da4147e7f4f2cd29ce6b82df39aa185c497dd","src/gamma/beta.rs":"ff1fd454dce28a6022b29e42a096fc5c2379e9812c760e9c6db92451b98af706","src/gamma/betaf.rs":"7d050b02f082ac4399bd594db34b76d0948e62dfacd5f9430b363628faab8438","src/gamma/betainc.rs":"dc3ee56ed9297df83d01d7f9d60a99f2148c66068045dbf846bf051b76e793a1","src/gamma/betaincf.rs":"2955cc2c4ff8e333ab4677c8df9c949cfdd1cb39f60e76cb5da224e783ac7d92","src/gamma/digamma.rs":"1f18a2f6de389ea9f010ba0fa29c2334d2b118582c144b93f80349af34f1b47a","src/gamma/digamma_coeffs.rs":"475e143cbe92f20f857dfda56298d9a84358562cf70444144d232c659de10e69","src/gamma/digammaf.rs":"b38efcaeef235750891439723b8e862f99b5cab5a2b2c407ac8f4f2c41722bd5","src/gamma/gamma_p.rs":"3dbb86e82a8967810db9d4fa8b6ab2ce7dbbd7d02484807fa04cc781bb8ef6e7","src/gamma/gamma_pf.rs":"2abc66a925275b71a49276a8c296de44dd9d5ee72196e4cb440664420abebcf7","src/gamma/gamma_q.rs":"9fb8069dc72abff46ad04341427dc65c89f4bd4f01246dc67c145cc09c54f7d0","src/gamma/gamma_qf.rs":"26aceeb33abe5904711f41d898e2da8608f977dbf5ea47d72b947d606cc07a38","src/gamma/lgamma.rs":"e0aed21549ab6cd2cad6949ad049041cfa7be2deb71ac3fd9e0abcaf8a80f17d","src/gamma/lgamma_r.rs":"d51f7183ac2ab69c7423256998c2992f0cc8575a50495da701ac0884f1405ded","src/gamma/lgamma_rf.rs":"2f9ef773d522b2e1b58f2271094ce86f74604b312bf10c46512d703f8ff62255","src/gamma/lgammaf.rs":"da92c1db67800febecd6ba63f855622bb1e0eb3799d83bd6d36ed492055b01be","src/gamma/lnbeta.rs":"b3166c1caf4198e3c6370e0da9dd79e925ed8fc4a495b899b07feed56100669b","src/gamma/lnbetaf.rs":"1f76606129b8d2f397524ddde04ad97a30301d6b4b19c5decf805c9b02b19e85","src/gamma/mod.rs":"7ade6b23121e88c39c85d67ce5d7ccd2693d809b3b7a9f14f0cd96f47de75228","src/gamma/tgamma.rs":"996de0685c98b99bddb07bce70722e6c27975cc234744f814195665dfefaec46","src/gamma/tgammaf.rs":"aa05744a801f0fe27b5cbff91c24ea23028c575632a655b308f500f8ca7fa1e5","src/gamma/trigamma.rs":"a28929c0dd4853300dcc525842a9e12dfcf441fbd5b232c31d246651240196cd","src/gamma/trigammaf.rs":"a4a384d85ce0c236d6c24e27fd7a0fbc0cf6e4f24e5b6373220a800b3ce465e5","src/hyperbolic/acosh.rs":"940bfa16d8ee56241ee5630813d4ead17118b289d86d99fe3c7c391d96b436a9","src/hyperbolic/acoshf.rs":"bc6bc5a4e352f7307c4db02d6578e5d067f0e8610d8fb7bbba854f48a82bfe4f","src/hyperbolic/asinh.rs":"79216cd89fb84474d7522d9326ea859ffbbc0d76de1db0a6cd48b7290332cd5c","src/hyperbolic/asinhf.rs":"924a0373e987632b3a0b5400c289b24847c76923922a3a1a868e9042e3026fbb","src/hyperbolic/atanh.rs":"ac61d5225b3b243c9d7dacb32a66593246b18a4f79c70ed034b61128a6545abd","src/hyperbolic/atanhf.rs":"ba2787b6de2948158e147260fbb5023005d10923d9880b5ca09b6ae5ce98ee89","src/hyperbolic/cosh.rs":"55f0f2ed8172cc5262aea975394dfb1e8083448287c6dcdef05646c330c26c4b","src/hyperbolic/coshf.rs":"92ab5751a9ad442341a21752b7d756b6fcb9cac1d49786554a6f334f3c1b0fd9","src/hyperbolic/mod.rs":"a606ade87f628efac4645e358e2f852011bd8cc50bd728506caa7a30d77e8d4d","src/hyperbolic/sinh.rs":"eaf4214d13c69f86eedb65cf55229276bd9fee6138787787d97214063598f737","src/hyperbolic/sinhf.rs":"2653daef3e63ac32c3531867a871cc734c5c949050b9582e62db2a9e0b21ef7b","src/hyperbolic/tanh.rs":"5b462170977ca4dcdf120bc67840d5c2344cde4bb633a20e94f0e7466b7adcd8","src/hyperbolic/tanhf.rs":"8fa9f3c0767815f0a8daa6d730d254d0f43449fcf56520def66febc53891be8d","src/lib.rs":"21cbd35f49dc3214d91146c84ff3e06d3e817ce0e7839f3d42ea41a0610f1cb3","src/logs/fast_log.rs":"e9cdb1a48d26d0cac471feaab100a863d1740dd16cfd3282abc9d7f065cab5a4","src/logs/fast_log_dd.rs":"42d1f258060b6fcf65f64d12584cb34c20552ba5f0fb83d72069a020eb93fb0d","src/logs/log.rs":"594af7dfdb97d0aa0edac3759dcc8fd8f4dafdf4a3a72d783765d42c533ee89f","src/logs/log10.rs":"4c6bd082d02546e0441e71bd5d7c5260c505960b1ec9478c3227be8b465da6b1","src/logs/log10dd.rs":"3a8658cba9a744d2428c254ad18e6e9a9ae74c417a0644a116020c78601a38df","src/logs/log10dd_coeffs.rs":"c468a0ee18694a1e8b7b4386e2732e35d4a108b518dc714273339b2f1b7f1c9d","src/logs/log10f.rs":"1b2d70fa5b3b57bf258d820200f875591957cf3d6f7d04f57a0ae0ee0241361b","src/logs/log10p1.rs":"4e6f4e6983e3b90c030c23a4b56473ced24bd0af48147f01808bc6ef0b1da593","src/logs/log10p1_tables.rs":"9d409e1116368553c3213060dd2c300ff76cc9e1344e4dac55e2ec0ac6168005","src/logs/log10p1f.rs":"c5253df7b3264890b9afa6cd437001d06eacbb72c3d44842c0ba45f14383542d","src/logs/log10td.rs":"069484c9d1f5d125e6905980e98b431cd8fd8d39d2f708f53c3512eab86a0ed1","src/logs/log10td_coeffs.rs":"5f08f92ccfc63c52207d7a5f7bd5e0f34bd3ee65ff8379f1911660eca0e4625f","src/logs/log1p.rs":"d5adb622580b000866e3f0c90fceaa31b93017e4259a290509b33c2685e59305","src/logs/log1p_dd.rs":"ce9068098b15915a8d0c962b37271dfe53b2f8b3d65efb0bd668daaf4e6e3cf8","src/logs/log1p_dyadic.rs":"edbf5f770db427b0e45616ca45a8291366309412e841e5ecb6522675bad8d423","src/logs/log1p_dyadic_tables.rs":"9c586fa3c2b6c114ab56b94103696f4baa5a09d7f402564d483219b549fc79be","src/logs/log1pf.rs":"99668fd46a10334c81ef4d3eedc35414e94ac640ee6cd29a23911e6b3da8d6b5","src/logs/log1pmx.rs":"035949d61a48a0f86c1035f081a0d6950934c55b105e46a579d2d5b85c0ed543","src/logs/log1pmxf.rs":"498f909457349abb67e62029a8256d285a0a0ea9067400777c54f0b7227c1140","src/logs/log2.rs":"d170d8fb8e7d1a0f453049005dfb0dbf1bcc810dfba5bae213a967d9b151d504","src/logs/log2dd.rs":"78db86ce569beaaab6fff06b1aaaa3a80ede22b29dca9704bd2f01091379b5fd","src/logs/log2dd_coeffs.rs":"282980d41a3d4a0208e99fdaea810c8748fd47e1d5b5882ae94349cef97bab6e","src/logs/log2f.rs":"9fff6552f2debd3866326a54cade1443f35b33a55f1ca4ee2ccfd199c0429266","src/logs/log2p1.rs":"e3b1974aebbd21e3426a04bb49dd82189f97dac48ad47ee25c857844cf82c1d9","src/logs/log2p1_dyadic_tables.rs":"a903ef0a75b54bbbfe510ef1bf290f8db5b912232c2300c7cb4aba89459d2f82","src/logs/log2p1_tables.rs":"d2ec82e8ab7fff3ddffeac26c578a162dcf45d7f637876316ac43c3a47bc40dd","src/logs/log2p1f.rs":"8375cdcfad0d68f6fbd1cfb98e2918df4c73ba7494e4dc88598e1d551cd7e983","src/logs/log2td.rs":"c80fee77e0a1312bc7d8cc8a073174677f0a58e5082f45eea777237224691eff","src/logs/log2td_coeffs.rs":"9542b9bbe323029b6045d0c75523fc694a19771a8955ed60d85aa73c2208b840","src/logs/log_dd.rs":"5adebb367e6bc85647cb3122bcd7dae7a6a8657c30de7bbecce628bd22b54d70","src/logs/log_dd_coeffs.rs":"19fc1ad0eef40d7baf9cf4a9c8d60822dbb7a1068e989690cf9a27237224f677","src/logs/log_dyadic.rs":"bf81c388f8d44795c7e5dffa7846d7ed51ff281e103bf003d3b546d309c6c31a","src/logs/log_range_reduction.rs":"a787acc4e956c25b7a46efa07f7c01f8b791b03be1e2ce4df0c9f703d42ccc5b","src/logs/log_td.rs":"dc3d9e254f5a75b3ff398fad6292307c264273ab367a379ef20c51f6cd97b84d","src/logs/log_td_table.rs":"19b9a4545aa5df47f235e52024a32b5118d965acfbaafac0184615b98c21b207","src/logs/logf.rs":"0aa03d486fdebea7bfe8bf6f6164ebf5ab25c709b4b74b531f0cebc888cef281","src/logs/logit.rs":"cdf0475b18d7dafd88cc0241a5da2a1c8d6326206051af19d2d2ac4d6246032c","src/logs/logitf.rs":"505c892f331d3c15922e3916e2116a3b0ece0516263f0c52132bacf17b1b6352","src/logs/mod.rs":"1bef403d9e36bfb0229a1b2dd0f4c8029310366e9b5ac1d05c4f5b4a43cd2618","src/polyeval.rs":"4c846ba4e771b86bacae94a6c4bed967cdec60a3ee6160bf3651e4e1a86f9315","src/pow.rs":"f7f71a97d6abde5eaf01c81f61d2bc9c4b87d3710d69995ac7adbf172e7c4e72","src/pow_exec.rs":"fcaa267aa079acc162a5e847b93ef0a84b1c287724d6bbc2a2dec05c3f05716d","src/pow_tables.rs":"7620a4b2b9c7e7520787927ab1ab50d2a28ebf4ae6674378b01c29ce10a44e14","src/powf.rs":"f2d94c92a5c1b5d00c7e525304613cc66bc4648573feeaf6a732043a662b80ca","src/powf_tables.rs":"e4cb02ae7e2d2e8b3b57bae4c743f08022fe0ae4e33f833956f2548a04fc8f2e","src/rounding/ceil.rs":"6cdc572345191be0768b88924bacbed097969da3cf41d55b6efdef80e35a648b","src/rounding/floor.rs":"129e8648c55227ea4aa91a1ac9592841cbae467e42fdd8252ede239ddb165e28","src/rounding/mod.rs":"a1e6673b936ce706863dd3db905cd4c7f061aaefc38582b634c1f161411e1c24","src/rounding/rint.rs":"e023791434538b9f1c8f31faedca5fbfc91e5e9971af56527b2dc1b50f50c8ec","src/rounding/rintf.rs":"b9de6f6ba9e968876f809c6025823759621f68cc62435167cf071a3b13044ac1","src/rounding/round.rs":"08dc7712a1d60c3e38abd892c2e2d10fb8517894471e428fbc2d7bbd659af34b","src/rounding/round_ties_even.rs":"2e568ca29fe20e7e6773df56bb87b6e88772719b92eb1581f4911f2975465771","src/rounding/trunc.rs":"b08b177fbaa8e4f7593ab4dfcc39d8c99caf8cad853550608cd70705cbba3a4e","src/rounding/truncf.rs":"88ae108b6c6e0b69a866dd434ee9343fa901e9f204f887a249fd55dcb60366c6","src/sec.rs":"6baba92ca6c68ed45d9ac059d579e00d753a384448cc422d1f07080bb8671874","src/shared_eval.rs":"1ecaf9e1c6404a3749b4bffe550f812a2603f7b8dc451f2f5bfd4fe87c023018","src/sin.rs":"116926de9c983f79d19c49533e216345aad0514b2fa5fd36b249657516b85648","src/sin_cosf/argument_reduction.rs":"56975a987e2dded4ba70400df4c2472a0f2bf6fdb1d1bb74ded2d9b595e6cb9e","src/sin_cosf/argument_reduction_pi.rs":"00b8eaf01f9b33579528289a9571070e735fc0f97895f83226672b1e26da0880","src/sin_cosf/cosf.rs":"41c6adb898902e5c49822513c252ba1a3b6fe2212fb2b8f03923d44b2cb252de","src/sin_cosf/cosm1f.rs":"e886964945744d55ea1bc4d022667c2a2a8b01e93b6b6ce417e0539870981e09","src/sin_cosf/cospif.rs":"b03df9f1ff69bdd765aec57b9f700718f24b7fd60e71f89f621df7e479b65c40","src/sin_cosf/cscf.rs":"02da41b9611ee892fdecbe3e25705b4d8dacc8903235565a13b154e1e72881dc","src/sin_cosf/mod.rs":"9815d30834601d70bb523da405e887fa5e9caaea9bc74bc41c4b1f9e0ac1d03a","src/sin_cosf/secf.rs":"e899a48549c02b7dc1b6563a7848289a7e83aa439966b420461f4dc178731460","src/sin_cosf/sincf.rs":"121b98119fafb5bc59ab8614cf20eacca9c2d95eedea6386c665c8cf194ee075","src/sin_cosf/sincosf.rs":"d8fbfbf5f24f3eb887b1a8aa64535a0a8d99c083dab83e6ed8b7eca3776ae2a6","src/sin_cosf/sincosf_eval.rs":"a0cd895b43d7958cc219f38630c5d8aed6c3b77d4e0df7d6ef7130a1798e7f3a","src/sin_cosf/sincospif.rs":"858dfa3700b2e7c6de637e5a1d8427484747c9c56230393b2d00db03ce92c4fe","src/sin_cosf/sincpif.rs":"1e3f6704cd4007e1f439b59bb1402b0f4ff4981acf1bfb790678c9b54bd03c45","src/sin_cosf/sinf.rs":"6bb2cf505c8bde2f168b0858f0872754e6f54a07d7beeb69376f9724393f59cf","src/sin_cosf/sinmxf.rs":"4f5edf62a1483c4e7ae7e1dc3e8a801127f3b6e9fab60264cb411a81310d2e61","src/sin_cosf/sinpif.rs":"ee46ee295816b99499879606412b9cb524d8f47fe6868a22c866f11d73d0277e","src/sin_helper.rs":"3633466ed8776a2a4912f64a9f3bf6ad69415d38a678902d8276a8dba4ae6235","src/sin_table.rs":"d2389d9b1202fd77e79e3c52162508f3f5d031414bd0af85fa269bb2a9fa2168","src/sinc.rs":"7cc75042a408bb731819f90c7cfda333290a8dc8f9fa8330001dbfd6a4774a5b","src/sincos.rs":"4af31cfc51964bfac7370308fee81c1f3e9f4d85c927ec1900cd701b1bc834e6","src/sincos_dyadic.rs":"d780c5e4c9624ad09d67db2653e12f7a11fc7281d1e1abcd6578afb5fe5e44fb","src/sincos_reduce.rs":"acbe6bf686759a8501748835ea20dfdf972331fe4d3cad894251c09fdc5bb78a","src/sincos_reduce_tables.rs":"5d3eb8abfadf7152750574ff58d771c099d1087334449426149bd1458eb43466","src/sincospi.rs":"8a3e16eeda2064df73876dc66262ebead6154ae2e7f509b0392972810c50a401","src/sincospi_tables.rs":"31450cabd3e90091869ee84a9f6b3c84ea483c62196eb077af65284074e85017","src/sincpi.rs":"9b2d63c876fa5f77bc73e1e5b2a4269595fb1f18309c4cbd5b16d7be7763f972","src/sinmx.rs":"605a8e9f66078fcc283bab5189dfc1fe903b58fc7289ed89e708b75ecc35bc62","src/square_root/mod.rs":"a41139822b23581a5cc221d75a73db2c6e64d65c1e3133b0450d6f43c593fa5f","src/square_root/rsqrt.rs":"2b6db60ffa11180208d99ad54d8b500c0f4ece264fe01256c6337a1e3670fb4b","src/square_root/rsqrtf.rs":"573a2d629fb08b62f411da76a5b8ec19d42bfde1d6e20fb4f734136700f1704a","src/square_root/sqrt1pm1.rs":"f306564c5657b16d9f51f846546bb826c19a2fe530b28234dc431dea33761e86","src/square_root/sqrt1pm1f.rs":"8d889f75e03d0c14ed4e7a40ebbc09d6b0153794d93dd3f8ce5544b9c6d50f13","src/square_root/sqrtf.rs":"662001fa74cbab0d09a5681c733d257def85cd9bb0163bb8fa8bd796b3bd3a76","src/tangent/atan.rs":"296f244a3a775fed3fa00d41b2bfe1ed24f850718453963b4af88a46ddd39198","src/tangent/atan2.rs":"2eb8bb58062609f4cabe7a6205741055e8b04240145e4ac21e52a38b2d0fb27e","src/tangent/atan2f.rs":"8922b8f33808d60883be968b7a908fa6f15608774f6739b7755620d8056bd47f","src/tangent/atan2pi.rs":"f3a8545fb37d1ffacf3d913c4480d5e4ba9ae39f6fc1cdce0d5d1fbdcd496196","src/tangent/atan2pif.rs":"cd959232196efc1820f28af89375ea97270ed3e5f6271b602af3da76b5c379a6","src/tangent/atanf.rs":"2cb7e4fa0d7d6c0fbb85a23d6ae267cb3853e186333f2bc17f7147a8ef683b5d","src/tangent/atanpi.rs":"604e7e25a79c5c5ffd2e4f73345f25a92784297f083b8994e7f4ad40ddb47389","src/tangent/atanpif.rs":"a4f41976371ca449e539d1add0e157cb5109ed89ad5745a767e8611c3a098ba2","src/tangent/cot.rs":"d0b9770b5a08d38185a69d99eb3688ff74045ef3a88eda5d054398eeee39e6e3","src/tangent/cotf.rs":"d678a3ed1394f381c90dd275d38d5f518820d21dc09a835b1111a2f5657c078c","src/tangent/cotpi.rs":"64d239338ace4ec533ae7c11e481754032529c3afeb345af6da04b7c00d323a1","src/tangent/cotpif.rs":"98c314069ac99a0bcbbcdc572ca4d274aec2762e8bba442a64ee9dcfcebe65a7","src/tangent/evalf.rs":"e6b57defaa626746d9d1bddb1ea2e3cdd435d57a36f00071edcb3000ec64bddb","src/tangent/mod.rs":"a77d7e5993042e303848dbffcbf275fc1481480e13d19b6341d721d1472e68be","src/tangent/tan.rs":"956d1bf84e5d1429ae79d4403f92a4bebdb5940ccfb4e4aa7fbd0dd139bdc97c","src/tangent/tanf.rs":"34fd09b087cddce07d142214d6f6ffb786144e298d265844342e88c76610623b","src/tangent/tanpi.rs":"2bcc396636e48444668cc47687a1284249ffb08c2266144f661bada528a1e1d3","src/tangent/tanpi_table.rs":"c45782e4fe269b6e9ecc75f9e3a7dbe06265e29e68598e379e0b47046f8d0b44","src/tangent/tanpif.rs":"4862ff8fa1657119a36e6e933918f218ed054e724377e84a9c3db75da1aa6a14","src/triangle/cathetus.rs":"a6116ba821f89e813b8149ec9a9b5a4c09f78c9590ab19054c1ab954fe028f7c","src/triangle/cathetusf.rs":"8a3731839e9be913f0eef72228b6e4be138ddb360b6881a4164fc887812f48f9","src/triangle/hypot.rs":"74a40e144288f2a344e64cd00827de5331bb7829806a193e7da7d4c5bf33b9fa","src/triangle/hypot3f.rs":"1ad88da7fe731bc0d002b37159dce6462e7aa8c8d99fe65a18981d84b37f1623","src/triangle/hypotf.rs":"c41fca4910ab42bf1be47f0642c36e166173e2b90b5ad4437bb882631187ff8c","src/triangle/mod.rs":"57fadfc087347e05967f7dcb770c35153dcad56abafbec5e59707ba4024bd267","src/triple_double.rs":"1058996679c3a466838f3b4041f205a476d3ab2fe0d887d7b8225d7dd56e2b20"},"package":"7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "195fb65251147f329826bf60c8b0a87b6fb7d690" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "pxfm" +version = "0.1.27" +dependencies = [ + "num-traits", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +rust-version = "1.85" +name = "pxfm" +version = "0.1.27" +authors = ["Radzivon Bartoshyk"] +build = false +include = [ + "/src/", + "/README.md", + "/LICENSE.md", + "/LICENSE-APACHE.md", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Fast and accurate math" +documentation = "https://github.com/awxkee/pxfm" +readme = "README.md" +keywords = [ + "libm", + "math", +] +categories = ["mathematics"] +license = "BSD-3-Clause OR Apache-2.0" +repository = "https://github.com/awxkee/pxfm" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[lib] +name = "pxfm" +path = "src/lib.rs" + +[dependencies.num-traits] +version = "0.2.3" + +[profile.dev.package.bessel] +opt-level = 3 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +workspace = { members = ["app"], exclude = [ "bessel", "fuzz"] } + +[package] +name = "pxfm" +version = "0.1.27" +edition = "2024" +documentation = "https://github.com/awxkee/pxfm" +keywords = ["libm", "math"] +license = "BSD-3-Clause OR Apache-2.0" +authors = ["Radzivon Bartoshyk"] +readme = "README.md" +repository = "https://github.com/awxkee/pxfm" +rust-version = "1.85" +categories = ["mathematics"] +description = "Fast and accurate math" +include = ["/src/", "/README.md", "/LICENSE.md", "/LICENSE-APACHE.md"] + +[dependencies] +num-traits = "0.2.3" + +[profile.dev.package] +bessel.opt-level = 3 + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --no-deps --open +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/LICENSE-APACHE.md clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE-APACHE.md --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/LICENSE-APACHE.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE-APACHE.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Radzivon Bartoshyk + + 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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/LICENSE.md clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE.md --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/LICENSE.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/LICENSE.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright (c) Radzivon Bartoshyk. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/README.md clamav-1.4.6+dfsg/.cargo/vendor/pxfm/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +# Math routines + +Mostly fast and accurate math. + +Most of the methods have ULP less than 0.5. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acos.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acos.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acos.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acos.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::acospi::PI_OVER_TWO_F128; +use crate::asin::asin_eval; +use crate::asin_eval_dyadic::asin_eval_dyadic; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; + +/// Computes acos(x) +/// +/// Max found ULP 0.5 +pub fn f_acos(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + const PI_OVER_TWO: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), + ); + + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // |x| < 0.5. + if x_e < E_BIAS - 1 { + // |x| < 2^-55. + if x_e < E_BIAS - 55 { + // When |x| < 2^-55, acos(x) = pi/2 + return (x_abs + f64::from_bits(0x35f0000000000000)) + PI_OVER_TWO.hi; + } + + let x_sq = DoubleDouble::from_exact_mult(x, x); + let err = x_abs * f64::from_bits(0x3cc0000000000000); + // Polynomial approximation: + // p ~ asin(x)/x + let (p, err) = asin_eval(x_sq, err); + // asin(x) ~ x * p + let r0 = DoubleDouble::from_exact_mult(x, p.hi); + // acos(x) = pi/2 - asin(x) + // ~ pi/2 - x * p + // = pi/2 - x * (p.hi + p.lo) + let r_hi = f_fmla(-x, p.hi, PI_OVER_TWO.hi); + // Use Dekker's 2SUM algorithm to compute the lower part. + let mut r_lo = ((PI_OVER_TWO.hi - r_hi) - r0.hi) - r0.lo; + r_lo = f_fmla(-x, p.lo, r_lo + PI_OVER_TWO.lo); + + let r_upper = r_hi + (r_lo + err); + let r_lower = r_hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + return acos_less_0p5_hard(x, x_sq); + } + + // |x| >= 0.5 + + let x_sign = if x.is_sign_negative() { -1.0 } else { 1.0 }; + + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + // |x| >= 1 + if x_e >= E_BIAS { + // x = +-1, asin(x) = +- pi/2 + if x_abs == 1.0 { + // x = 1, acos(x) = 0, + // x = -1, acos(x) = pi + return if x == 1.0 { + 0.0 + } else { + f_fmla(-x_sign, PI.hi, PI.lo) + }; + } + // |x| > 1, return NaN. + return f64::NAN; + } + + // When |x| >= 0.5, we perform range reduction as follow: + // + // When 0.5 <= x < 1, let: + // y = acos(x) + // We will use the double angle formula: + // cos(2y) = 1 - 2 sin^2(y) + // and the complement angle identity: + // x = cos(y) = 1 - 2 sin^2 (y/2) + // So: + // sin(y/2) = sqrt( (1 - x)/2 ) + // And hence: + // y/2 = asin( sqrt( (1 - x)/2 ) ) + // Equivalently: + // acos(x) = y = 2 * asin( sqrt( (1 - x)/2 ) ) + // Let u = (1 - x)/2, then: + // acos(x) = 2 * asin( sqrt(u) ) + // Moreover, since 0.5 <= x < 1: + // 0 < u <= 1/4, and 0 < sqrt(u) <= 0.5, + // And hence we can reuse the same polynomial approximation of asin(x) when + // |x| <= 0.5: + // acos(x) ~ 2 * sqrt(u) * P(u). + // + // When -1 < x <= -0.5, we reduce to the previous case using the formula: + // acos(x) = pi - acos(-x) + // = pi - 2 * asin ( sqrt( (1 + x)/2 ) ) + // ~ pi - 2 * sqrt(u) * P(u), + // where u = (1 - |x|)/2. + + // u = (1 - |x|)/2 + let u = f_fmla(x_abs, -0.5, 0.5); + // v_hi + v_lo ~ sqrt(u). + // Let: + // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) + // Then: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // ~ v_hi + h / (2 * v_hi) + // So we can use: + // v_lo = h / (2 * v_hi). + let v_hi = u.sqrt(); + + let h; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + h = f_fmla(v_hi, -v_hi, u); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let v_hi_sq = DoubleDouble::from_exact_mult(v_hi, v_hi); + h = (u - v_hi_sq.hi) - v_hi_sq.lo; + } + + // Scale v_lo and v_hi by 2 from the formula: + // vh = v_hi * 2 + // vl = 2*v_lo = h / v_hi. + let vh = v_hi * 2.0; + let vl = h / v_hi; + + // Polynomial approximation: + // p ~ asin(sqrt(u))/sqrt(u) + let err = vh * f64::from_bits(0x3cc0000000000000); + + let (p, err) = asin_eval(DoubleDouble::new(0.0, u), err); + + // Perform computations in double-double arithmetic: + // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) + let r0 = DoubleDouble::quick_mult(DoubleDouble::new(vl, vh), p); + + let r_hi; + let r_lo; + if x.is_sign_positive() { + r_hi = r0.hi; + r_lo = r0.lo; + } else { + let r = DoubleDouble::from_exact_add(PI.hi, -r0.hi); + r_hi = r.hi; + r_lo = (PI.lo - r0.lo) + r.lo; + } + + let r_upper = r_hi + (r_lo + err); + let r_lower = r_hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + acos_hard(x, u, v_hi, h, vh, vl) +} + +#[cold] +#[inline(never)] +fn acos_hard(x: f64, u: f64, v_hi: f64, h: f64, vh: f64, vl: f64) -> f64 { + // Ziv's accuracy test failed, we redo the computations in Float128. + // Recalculate mod 1/64. + let idx = (u * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // After the first step of Newton-Raphson approximating v = sqrt(u), we have + // that: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // v_lo = h / (2 * v_hi) + // With error: + // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) + // = -h^2 / (2*v * (sqrt(u) + v)^2). + // Since: + // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, + // we can add another correction term to (v_hi + v_lo) that is: + // v_ll = -h^2 / (2*v_hi * 4u) + // = -v_lo * (h / 4u) + // = -vl * (h / 8u), + // making the errors: + // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) + // well beyond 128-bit precision needed. + + // Get the rounding error of vl = 2 * v_lo ~ h / vh + // Get full product of vh * vl + let vl_lo; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + vl_lo = f_fmla(-v_hi, vl, h) / v_hi; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let vh_vl = DoubleDouble::from_exact_mult(v_hi, vl); + vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; + } + let t = h * (-0.25) / u; + let vll = f_fmla(vl, t, vl_lo); + let m_v_p = DyadicFloat128::new_from_f64(vl) + DyadicFloat128::new_from_f64(vll); + let mut m_v = DyadicFloat128::new_from_f64(vh) + m_v_p; + m_v.sign = if x.is_sign_negative() { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + + // Perform computations in Float128: + // acos(x) = (v_hi + v_lo + vll) * P(u) , when 0.5 <= x < 1, + // = pi - (v_hi + v_lo + vll) * P(u) , when -1 < x <= -0.5. + let y_f128 = + DyadicFloat128::new_from_f64(f_fmla(idx as f64, f64::from_bits(0xbf90000000000000), u)); + + let p_f128 = asin_eval_dyadic(y_f128, idx); + let mut r_f128 = m_v * p_f128; + + if x.is_sign_negative() { + const PI_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + r_f128 = PI_F128 + r_f128; + } + + r_f128.fast_as_f64() +} + +#[cold] +#[inline(never)] +fn acos_less_0p5_hard(x: f64, x_sq: DoubleDouble) -> f64 { + // Ziv's accuracy test failed, perform 128-bit calculation. + + // Recalculate mod 1/64. + let idx = (x_sq.hi * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // Get x^2 - idx/64 exactly. When FMA is available, double-double + // multiplication will be correct for all rounding modes. Otherwise, we use + // Float128 directly. + let mut x_f128 = DyadicFloat128::new_from_f64(x); + + let u: DyadicFloat128; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + // u = x^2 - idx/64 + let u_hi = DyadicFloat128::new_from_f64(f_fmla( + idx as f64, + f64::from_bits(0xbf90000000000000), + x_sq.hi, + )); + u = u_hi.quick_add(&DyadicFloat128::new_from_f64(x_sq.lo)); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x_sq_f128 = x_f128.quick_mul(&x_f128); + u = x_sq_f128.quick_add(&DyadicFloat128::new_from_f64( + idx as f64 * f64::from_bits(0xbf90000000000000), + )); + } + + let p_f128 = asin_eval_dyadic(u, idx); + // Flip the sign of x_f128 to perform subtraction. + x_f128.sign = x_f128.sign.negate(); + let r = PI_OVER_TWO_F128.quick_add(&x_f128.quick_mul(&p_f128)); + r.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn f_acos_test() { + assert_eq!(f_acos(0.7), 0.7953988301841436); + assert_eq!(f_acos(-0.1), 1.6709637479564565); + assert_eq!(f_acos(-0.4), 1.9823131728623846); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acosf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acosf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acosf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acosf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use std::hint::black_box; + +#[inline(always)] +pub(crate) fn poly12 f64>(z: f64, c: [u64; 12], fma: &Q) -> f64 { + let z2 = z * z; + let z4 = z2 * z2; + let mut c0 = fma(z, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c2 = fma(z, f64::from_bits(c[3]), f64::from_bits(c[2])); + let mut c4 = fma(z, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c6 = fma(z, f64::from_bits(c[7]), f64::from_bits(c[6])); + let mut c8 = fma(z, f64::from_bits(c[9]), f64::from_bits(c[8])); + let c10 = fma(z, f64::from_bits(c[11]), f64::from_bits(c[10])); + c0 = fma(c2, z2, c0); + c4 = fma(c6, z2, c4); + c8 = fma(z2, c10, c8); + fma(z4, fma(z4, c8, c4), c0) +} + +#[cold] +fn as_special(x: f32) -> f32 { + const PIH: f32 = f64::from_bits(0x400921fb60000000) as f32; + const PIL: f32 = -f64::from_bits(0x3e70000000000000) as f32; + let t = x.to_bits(); + if t == (0x7fu32 << 23) { + return 0.0; + } // x=1 + if t == (0x17fu32 << 23) { + return PIH + PIL; + } // x=-1 + let ax = t.wrapping_shl(1); + if ax > (0xffu32 << 24) { + return x + x; + } // nan + f32::NAN +} + +#[inline(always)] +fn acosf_gen_impl f64>(x: f32, fma: Q) -> f32 { + const PI2: f64 = f64::from_bits(0x3ff921fb54442d18); + const O: [f64; 2] = [0., f64::from_bits(0x400921fb54442d18)]; + let xs = x as f64; + let mut r: f64; + let t = x.to_bits(); + let ax = t.wrapping_shl(1); + if ax >= 0x7f << 24 { + return as_special(x); + } + if ax < 0x7ec2a1dcu32 { + // |x| < 0.880141 + const B: [u64; 16] = [ + 0x3fefffffffd9ccb8, + 0x3fc5555c94838007, + 0x3fb32ded4b7c20fa, + 0x3fa8566df703309e, + 0xbf9980c959bec9a3, + 0x3fe56fbb04998344, + 0xc01403d8e4c49f52, + 0x403b06c3e9f311ea, + 0xc059ea97c4e2c21f, + 0x407200b8261cc61b, + 0xc082274c2799a5c7, + 0x408a558a59cc19d3, + 0xc08aca4b6a529ff0, + 0x408228744703f813, + 0xc06d7dbb0b322228, + 0x4045c2018c0c0105, + ]; + /* avoid spurious underflow */ + if ax < 0x40000000u32 { + // |x| < 2^-63 + return PI2 as f32; + } + let z = xs; + let z2 = z * z; + + let w0 = fma(z2, f64::from_bits(B[1]), f64::from_bits(B[0])); + let w1 = fma(z2, f64::from_bits(B[3]), f64::from_bits(B[2])); + let w2 = fma(z2, f64::from_bits(B[5]), f64::from_bits(B[4])); + let w3 = fma(z2, f64::from_bits(B[7]), f64::from_bits(B[6])); + let w4 = fma(z2, f64::from_bits(B[9]), f64::from_bits(B[8])); + let w5 = fma(z2, f64::from_bits(B[11]), f64::from_bits(B[10])); + let w6 = fma(z2, f64::from_bits(B[13]), f64::from_bits(B[12])); + let w7 = fma(z2, f64::from_bits(B[15]), f64::from_bits(B[14])); + + let z4 = z2 * z2; + let z8 = z4 * z4; + let z16 = z8 * z8; + + r = z + * ((fma(z4, w1, w0) + z8 * fma(z4, w3, w2)) + + z16 * (fma(z4, w5, w4) + z8 * fma(z4, w7, w6))); + + let ub = f64::from_bits(0x3ff921fb54574191) - r; + let lb = f64::from_bits(0x3ff921fb543118a0) - r; + // Ziv's accuracy test + if ub == lb { + return ub as f32; + } + } + // accurate path + if ax < (0x7eu32 << 24) { + const C: [u64; 12] = [ + 0x3fc555555555529c, + 0x3fb333333337e0dd, + 0x3fa6db6db3b4465e, + 0x3f9f1c72e13ac306, + 0x3f96e89cebe06bc4, + 0x3f91c6dcf5289094, + 0x3f8c6dbbcc7c6315, + 0x3f88f8dc2615e996, + 0x3f7a5833b7bf15e8, + 0x3f943f44ace1665c, + 0xbf90fb17df881c73, + 0x3fa07520c026b2d6, + ]; + if t == 0x328885a3u32 { + return black_box(f64::from_bits(0x3ff921fb60000000) as f32) + + black_box(f64::from_bits(0x3e60000000000000) as f32); + } + if t == 0x39826222u32 { + return black_box(f64::from_bits(0x3ff920f6a0000000) as f32) + + black_box(f64::from_bits(0x3e60000000000000) as f32); + } + let x2 = xs * xs; + r = fma(-(xs * x2), poly12(x2, C, &fma), PI2 - xs); + } else { + const C: [u64; 12] = [ + 0x3ff6a09e667f3bcb, + 0x3fbe2b7dddff2db9, + 0x3f9b27247ab42dbc, + 0x3f802995cc4e0744, + 0x3f65ffb0276ec8ea, + 0x3f5033885a928dec, + 0x3f3911f2be23f8c7, + 0x3f24c3c55d2437fd, + 0x3f0af477e1d7b461, + 0x3f0abd6bdff67dcb, + 0xbef1717e86d0fa28, + 0x3ef6ff526de46023, + ]; + let bx = xs.abs(); + let z = 1.0 - bx; + let s = f64::copysign(z.sqrt(), xs); + r = fma(s, poly12(z, C, &fma), O[t.wrapping_shr(31) as usize]); + } + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn acosf_fma_impl(x: f32) -> f32 { + acosf_gen_impl(x, f64::mul_add) +} + +/// Compute acos +/// +/// Max found ULP 0.49999982 +#[inline] +pub fn f_acosf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + acosf_gen_impl(x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + acosf_fma_impl + } else { + fn def_acosf(x: f32) -> f32 { + acosf_gen_impl(x, f_fmla) + } + def_acosf + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_acosf() { + assert_eq!(f_acosf(-0.5), 2.0943952); + assert_eq!(f_acosf(0.5), std::f32::consts::FRAC_PI_3); + assert!(f_acosf(7.).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acospi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acospi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,369 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::asin::asin_eval; +use crate::asin_eval_dyadic::asin_eval_dyadic; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; + +pub(crate) const INV_PI_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc76b01ec5417056), + f64::from_bits(0x3fd45f306dc9c883), +); + +// 1/PI with 128-bit precision generated by SageMath with: +// def format_hex(value): +// l = hex(value)[2:] +// n = 8 +// x = [l[i:i + n] for i in range(0, len(l), n)] +// return "0x" + "'".join(x) + "_u128" +// r = 1/pi +// (s, m, e) = RealField(128)(r).sign_mantissa_exponent(); +// print(format_hex(m)); +pub(crate) const INV_PI_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa2f9836e_4e441529_fc2757d1_f534ddc1_u128, +}; + +pub(crate) const PI_OVER_TWO_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, +}; + +/// Computes acos(x)/PI +/// +/// Max ULP 0.5 +pub fn f_acospi(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + const PI_OVER_TWO: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), + ); + + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // |x| < 0.5. + if x_e < E_BIAS - 1 { + // |x| < 2^-55. + if x_e < E_BIAS - 55 { + // When |x| < 2^-55, acos(x) = pi/2 + return f_fmla(f64::from_bits(0xbc80000000000000), x, 0.5); + } + + let x_sq = DoubleDouble::from_exact_mult(x, x); + let err = x_abs * f64::from_bits(0x3cc0000000000000); + // Polynomial approximation: + // p ~ asin(x)/x + let (p, err) = asin_eval(x_sq, err); + // asin(x) ~ x * p + let r0 = DoubleDouble::from_exact_mult(x, p.hi); + // acos(x) = pi/2 - asin(x) + // ~ pi/2 - x * p + // = pi/2 - x * (p.hi + p.lo) + let mut r_hi = f_fmla(-x, p.hi, PI_OVER_TWO.hi); + // Use Dekker's 2SUM algorithm to compute the lower part. + let mut r_lo = ((PI_OVER_TWO.hi - r_hi) - r0.hi) - r0.lo; + r_lo = f_fmla(-x, p.lo, r_lo + PI_OVER_TWO.lo); + + let p = DoubleDouble::mult(DoubleDouble::new(r_lo, r_hi), INV_PI_DD); + r_hi = p.hi; + r_lo = p.lo; + + let r_upper = r_hi + (r_lo + err); + let r_lower = r_hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, perform 128-bit calculation. + + // Recalculate mod 1/64. + let idx = (x_sq.hi * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // Get x^2 - idx/64 exactly. When FMA is available, double-double + // multiplication will be correct for all rounding modes. Otherwise, we use + // Float128 directly. + let mut x_f128 = DyadicFloat128::new_from_f64(x); + + let u: DyadicFloat128; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + // u = x^2 - idx/64 + let u_hi = DyadicFloat128::new_from_f64(f_fmla( + idx as f64, + f64::from_bits(0xbf90000000000000), + x_sq.hi, + )); + u = u_hi.quick_add(&DyadicFloat128::new_from_f64(x_sq.lo)); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x_sq_f128 = x_f128.quick_mul(&x_f128); + u = x_sq_f128.quick_add(&DyadicFloat128::new_from_f64( + idx as f64 * f64::from_bits(0xbf90000000000000), + )); + } + + let p_f128 = asin_eval_dyadic(u, idx); + // Flip the sign of x_f128 to perform subtraction. + x_f128.sign = x_f128.sign.negate(); + let mut r = PI_OVER_TWO_F128.quick_add(&x_f128.quick_mul(&p_f128)); + r = r.quick_mul(&INV_PI_F128); + return r.fast_as_f64(); + } + + // |x| >= 0.5 + + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + // |x| >= 1 + if x_e >= E_BIAS { + // x = +-1, asin(x) = +- pi/2 + if x_abs == 1.0 { + // x = 1, acos(x) = 0, + // x = -1, acos(x) = pi + return if x == 1.0 { 0.0 } else { 1.0 }; + } + // |x| > 1, return NaN. + return f64::NAN; + } + + // When |x| >= 0.5, we perform range reduction as follow: + // + // When 0.5 <= x < 1, let: + // y = acos(x) + // We will use the double angle formula: + // cos(2y) = 1 - 2 sin^2(y) + // and the complement angle identity: + // x = cos(y) = 1 - 2 sin^2 (y/2) + // So: + // sin(y/2) = sqrt( (1 - x)/2 ) + // And hence: + // y/2 = asin( sqrt( (1 - x)/2 ) ) + // Equivalently: + // acos(x) = y = 2 * asin( sqrt( (1 - x)/2 ) ) + // Let u = (1 - x)/2, then: + // acos(x) = 2 * asin( sqrt(u) ) + // Moreover, since 0.5 <= x < 1: + // 0 < u <= 1/4, and 0 < sqrt(u) <= 0.5, + // And hence we can reuse the same polynomial approximation of asin(x) when + // |x| <= 0.5: + // acos(x) ~ 2 * sqrt(u) * P(u). + // + // When -1 < x <= -0.5, we reduce to the previous case using the formula: + // acos(x) = pi - acos(-x) + // = pi - 2 * asin ( sqrt( (1 + x)/2 ) ) + // ~ pi - 2 * sqrt(u) * P(u), + // where u = (1 - |x|)/2. + + // u = (1 - |x|)/2 + let u = f_fmla(x_abs, -0.5, 0.5); + // v_hi + v_lo ~ sqrt(u). + // Let: + // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) + // Then: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // ~ v_hi + h / (2 * v_hi) + // So we can use: + // v_lo = h / (2 * v_hi). + let v_hi = u.sqrt(); + + let h; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + h = f_fmla(v_hi, -v_hi, u); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let v_hi_sq = DoubleDouble::from_exact_mult(v_hi, v_hi); + h = (u - v_hi_sq.hi) - v_hi_sq.lo; + } + + // Scale v_lo and v_hi by 2 from the formula: + // vh = v_hi * 2 + // vl = 2*v_lo = h / v_hi. + let vh = v_hi * 2.0; + let vl = h / v_hi; + + // Polynomial approximation: + // p ~ asin(sqrt(u))/sqrt(u) + let err = vh * f64::from_bits(0x3cc0000000000000); + + let (p, err) = asin_eval(DoubleDouble::new(0.0, u), err); + + // Perform computations in double-double arithmetic: + // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) + let r0 = DoubleDouble::quick_mult(DoubleDouble::new(vl, vh), p); + + let mut r_hi; + let mut r_lo; + if x.is_sign_positive() { + r_hi = r0.hi; + r_lo = r0.lo; + } else { + let r = DoubleDouble::from_exact_add(PI.hi, -r0.hi); + r_hi = r.hi; + r_lo = (PI.lo - r0.lo) + r.lo; + } + + let p = DoubleDouble::mult(DoubleDouble::new(r_lo, r_hi), INV_PI_DD); + r_hi = p.hi; + r_lo = p.lo; + + let r_upper = r_hi + (r_lo + err); + let r_lower = r_hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, we redo the computations in Float128. + // Recalculate mod 1/64. + let idx = (u * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // After the first step of Newton-Raphson approximating v = sqrt(u), we have + // that: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // v_lo = h / (2 * v_hi) + // With error: + // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) + // = -h^2 / (2*v * (sqrt(u) + v)^2). + // Since: + // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, + // we can add another correction term to (v_hi + v_lo) that is: + // v_ll = -h^2 / (2*v_hi * 4u) + // = -v_lo * (h / 4u) + // = -vl * (h / 8u), + // making the errors: + // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) + // well beyond 128-bit precision needed. + + // Get the rounding error of vl = 2 * v_lo ~ h / vh + // Get full product of vh * vl + let vl_lo; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + vl_lo = f_fmla(-v_hi, vl, h) / v_hi; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let vh_vl = DoubleDouble::from_exact_mult(v_hi, vl); + vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; + } + let t = h * (-0.25) / u; + let vll = f_fmla(vl, t, vl_lo); + // m_v = -(v_hi + v_lo + v_ll). + let m_v_p = DyadicFloat128::new_from_f64(vl) + DyadicFloat128::new_from_f64(vll); + let mut m_v = DyadicFloat128::new_from_f64(vh) + m_v_p; + m_v.sign = if x.is_sign_negative() { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + + // Perform computations in Float128: + // acos(x) = (v_hi + v_lo + vll) * P(u) , when 0.5 <= x < 1, + // = pi - (v_hi + v_lo + vll) * P(u) , when -1 < x <= -0.5. + let y_f128 = + DyadicFloat128::new_from_f64(f_fmla(idx as f64, f64::from_bits(0xbf90000000000000), u)); + + let p_f128 = asin_eval_dyadic(y_f128, idx); + let mut r_f128 = m_v * p_f128; + + if x.is_sign_negative() { + const PI_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + r_f128 = PI_F128 + r_f128; + } + + r_f128 = r_f128.quick_mul(&INV_PI_F128); + + r_f128.fast_as_f64() +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn acospi_test() { + assert_eq!(f_acospi(0.5), 0.3333333333333333); + assert!(f_acospi(1.5).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acospif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/acospif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/acospif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,136 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::asinpif::ASINCOSF_PI_TABLE; +use crate::common::{dd_fmla, f_fmla}; + +#[inline(always)] +/// fma - fma +/// dd_fma - mandatory fma fallback +fn acospif_gen_impl f64, F: Fn(f64, f64, f64) -> f64>( + x: f32, + fma: Q, + dd_fma: F, +) -> f32 { + let ax = x.abs(); + let az = ax as f64; + let z = x as f64; + let t: u32 = x.to_bits(); + let e: i32 = ((t >> 23) & 0xff) as i32; + if e >= 127 { + if x == 1.0 { + return 0.0; + } + if x == -1.0 { + return 1.0; + } + if e == 0xff && (t.wrapping_shl(9)) != 0 { + return x + x; + } // nan + return f32::NAN; + } + let s: i32 = 146i32.wrapping_sub(e); + let mut i = 0i32; + if s < 32 { + i = (((t & 0x007fffff) | 1 << 23) >> s) as i32; + } + let c = ASINCOSF_PI_TABLE[i as usize & 15]; + let z2 = z * z; + let z4 = z2 * z2; + if i == 0 { + let mut c0 = fma(z2, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c2 = fma(z2, f64::from_bits(c[3]), f64::from_bits(c[2])); + let mut c4 = fma(z2, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c6 = fma(z2, f64::from_bits(c[7]), f64::from_bits(c[6])); + c0 += c2 * z4; + c4 += c6 * z4; + /* For |x| <= 0x1.0fd288p-127, c0 += c4*(z4*z4) would raise a spurious + underflow exception, we use an FMA instead, where c4 * z4 does not + underflow. */ + c0 = dd_fma(c4 * z4, z4, c0); + fma(-z, c0, 0.5) as f32 + } else { + let f = (1. - az).sqrt(); + let mut c0 = fma(az, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c2 = fma(az, f64::from_bits(c[3]), f64::from_bits(c[2])); + let mut c4 = fma(az, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c6 = fma(az, f64::from_bits(c[7]), f64::from_bits(c[6])); + c0 += c2 * z2; + c4 += c6 * z2; + c0 += c4 * z4; + static SIGN: [f64; 2] = [0., 1.]; + let r = SIGN[(t >> 31) as usize] + c0 * f64::copysign(f, x as f64); + r as f32 + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn acospif_fma_impl(x: f32) -> f32 { + acospif_gen_impl(x, f64::mul_add, f64::mul_add) +} + +/// Computes acos(x)/PI +/// +/// Max ULP 0.5 +#[inline] +pub fn f_acospif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + acospif_gen_impl(x, f_fmla, dd_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + acospif_fma_impl + } else { + fn def_acospif(x: f32) -> f32 { + acospif_gen_impl(x, f_fmla, dd_fmla) + } + def_acospif + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_acospif() { + assert_eq!(f_acospif(0.0), 0.5); + assert_eq!(f_acospif(0.5), 0.33333334); + assert_eq!(f_acospif(1.0), 0.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asin.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asin.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,490 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::asin_eval_dyadic::asin_eval_dyadic; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; + +static ASIN_COEFFS: [[u64; 12]; 9] = [ + [ + 0x3ff0000000000000, + 0x0000000000000000, + 0x3fc5555555555555, + 0x3c65555555555555, + 0x3fb3333333333333, + 0x3fa6db6db6db6db7, + 0x3f9f1c71c71c71c7, + 0x3f96e8ba2e8ba2e9, + 0x3f91c4ec4ec4ec4f, + 0x3f8c99999999999a, + 0x3f87a87878787878, + 0x3f83fde50d79435e, + ], + [ + 0x3ff015a397cf0f1c, + 0xbc8eebd6ccfe3ee3, + 0x3fc5f3581be7b08b, + 0xbc65df80d0e7237d, + 0x3fb4519ddf1ae530, + 0x3fa8eb4b6eeb1696, + 0x3fa17bc85420fec8, + 0x3f9a8e39b5dcad81, + 0x3f953f8df127539b, + 0x3f91a485a0b0130a, + 0x3f8e20e6e4930020, + 0x3f8a466a7030f4c9, + ], + [ + 0x3ff02be9ce0b87cd, + 0x3c7e5d09da2e0f04, + 0x3fc69ab5325bc359, + 0xbc692f480cfede2d, + 0x3fb58a4c3097aab1, + 0x3fab3db36068dd80, + 0x3fa3b94821846250, + 0x3f9eedc823765d21, + 0x3f998e35d756be6b, + 0x3f95ea4f1b32731a, + 0x3f9355115764148e, + 0x3f916a5853847c91, + ], + [ + 0x3ff042dc6a65ffbf, + 0xbc8c7ea28dce95d1, + 0x3fc74c4bd7412f9d, + 0x3c5447024c0a3c87, + 0x3fb6e09c6d2b72b9, + 0x3faddd9dcdae5315, + 0x3fa656f1f64058b8, + 0x3fa21a42e4437101, + 0x3f9eed0350b7edb2, + 0x3f9b6bc877e58c52, + 0x3f9903a0872eb2a4, + 0x3f974da839ddd6d8, + ], + [ + 0x3ff05a8621feb16b, + 0xbc7e5b33b1407c5f, + 0x3fc809186c2e57dd, + 0xbc33dcb4d6069407, + 0x3fb8587d99442dc5, + 0x3fb06c23d1e75be3, + 0x3fa969024051c67d, + 0x3fa54e4f934aacfd, + 0x3fa2d60a732dbc9c, + 0x3fa149f0c046eac7, + 0x3fa053a56dba1fba, + 0x3f9f7face3343992, + ], + [ + 0x3ff072f2b6f1e601, + 0xbc92dcbb05419970, + 0x3fc8d2397127aeba, + 0x3c6ead0c497955fb, + 0x3fb9f68df88da518, + 0x3fb21ee26a5900d7, + 0x3fad08e7081b53a9, + 0x3fa938dd661713f7, + 0x3fa71b9f299b72e6, + 0x3fa5fbc7d2450527, + 0x3fa58573247ec325, + 0x3fa585a174a6a4ce, + ], + [ + 0x3ff08c2f1d638e4c, + 0x3c7b47c159534a3d, + 0x3fc9a8f592078624, + 0xbc6ea339145b65cd, + 0x3fbbc04165b57aab, + 0x3fb410df5f58441d, + 0x3fb0ab6bdf5f8f70, + 0x3fae0b92eea1fce1, + 0x3fac9094e443a971, + 0x3fac34651d64bc74, + 0x3facaa008d1af080, + 0x3fadc165bc0c4fc5, + ], + [ + 0x3ff0a649a73e61f2, + 0x3c874ac0d817e9c7, + 0x3fca8ec30dc93890, + 0xbc48ab1c0eef300c, + 0x3fbdbc11ea95061b, + 0x3fb64e371d661328, + 0x3fb33e0023b3d895, + 0x3fb2042269c243ce, + 0x3fb1cce74bda2230, + 0x3fb244d425572ce9, + 0x3fb34d475c7f1e3e, + 0x3fb4d4e653082ad3, + ], + [ + 0x3ff0c152382d7366, + 0xbc9ee6913347c2a6, + 0x3fcb8550d62bfb6d, + 0xbc6d10aec3f116d5, + 0x3fbff1bde0fa3ca0, + 0x3fb8e5f3ab69f6a4, + 0x3fb656be8b6527ce, + 0x3fb5c39755dc041a, + 0x3fb661e6ebd40599, + 0x3fb7ea3dddee2a4f, + 0x3fba4f439abb4869, + 0x3fbd9181c0fda658, + ], +]; + +#[inline] +pub(crate) fn asin_eval(u: DoubleDouble, err: f64) -> (DoubleDouble, f64) { + // k = round(u * 32). + let k = (u.hi * f64::from_bits(0x4040000000000000)).cpu_round(); + let idx = k as u64; + // y = u - k/32. + let y_hi = f_fmla(k, f64::from_bits(0xbfa0000000000000), u.hi); // Exact + let y = DoubleDouble::from_exact_add(y_hi, u.lo); + let y2 = y.hi * y.hi; + // Add double-double errors in addition to the relative errors from y2. + let err = f_fmla(err, y2, f64::from_bits(0x3990000000000000)); + let coeffs = ASIN_COEFFS[idx as usize]; + let c0 = DoubleDouble::quick_mult( + y, + DoubleDouble::new(f64::from_bits(coeffs[3]), f64::from_bits(coeffs[2])), + ); + let c1 = f_fmla(y.hi, f64::from_bits(coeffs[5]), f64::from_bits(coeffs[4])); + let c2 = f_fmla(y.hi, f64::from_bits(coeffs[7]), f64::from_bits(coeffs[6])); + let c3 = f_fmla(y.hi, f64::from_bits(coeffs[9]), f64::from_bits(coeffs[8])); + let c4 = f_fmla(y.hi, f64::from_bits(coeffs[11]), f64::from_bits(coeffs[10])); + + let y4 = y2 * y2; + let d0 = f_fmla(y2, c2, c1); + let d1 = f_fmla(y2, c4, c3); + + let mut r = DoubleDouble::from_exact_add(f64::from_bits(coeffs[0]), c0.hi); + + let e1 = f_fmla(y4, d1, d0); + + r.lo = f_fmla(y2, e1, f64::from_bits(coeffs[1]) + c0.lo + r.lo); + + (r, err) +} + +/// Computes asin(x) +/// +/// Max found ULP 0.5 +pub fn f_asin(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // |x| < 0.5. + if x_e < E_BIAS - 1 { + // |x| < 2^-26. + if x_e < E_BIAS - 26 { + // When |x| < 2^-26, the relative error of the approximation asin(x) ~ x + // is: + // |asin(x) - x| / |asin(x)| < |x^3| / (6|x|) + // = x^2 / 6 + // < 2^-54 + // < epsilon(1)/2. + // = x otherwise. , + if x.abs() == 0. { + return x; + } + // Get sign(x) * min_normal. + let eps = f64::copysign(f64::MIN_POSITIVE, x); + let normalize_const = if x_e == 0 { eps } else { 0.0 }; + let scaled_normal = + f_fmla(x + normalize_const, f64::from_bits(0x4350000000000000), eps); + return f_fmla( + scaled_normal, + f64::from_bits(0x3c90000000000000), + -normalize_const, + ); + } + + let x_sq = DoubleDouble::from_exact_mult(x, x); + let err = x_abs * f64::from_bits(0x3cc0000000000000); + // Polynomial approximation: + // p ~ asin(x)/x + + let (p, err) = asin_eval(x_sq, err); + // asin(x) ~ x * (ASIN_COEFFS[idx][0] + p) + let r0 = DoubleDouble::from_exact_mult(x, p.hi); + let r_lo = f_fmla(x, p.lo, r0.lo); + + let r_upper = r0.hi + (r_lo + err); + let r_lower = r0.hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, perform 128-bit calculation. + + // Recalculate mod 1/64. + let idx = (x_sq.hi * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // Get x^2 - idx/64 exactly. When FMA is available, double-double + // multiplication will be correct for all rounding modes. Otherwise, we use + // Float128 directly. + let x_f128 = DyadicFloat128::new_from_f64(x); + + let u: DyadicFloat128; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + // u = x^2 - idx/64 + let u_hi = DyadicFloat128::new_from_f64(f_fmla( + idx as f64, + f64::from_bits(0xbf90000000000000), + x_sq.hi, + )); + u = u_hi.quick_add(&DyadicFloat128::new_from_f64(x_sq.lo)); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x_sq_f128 = x_f128.quick_mul(&x_f128); + u = x_sq_f128.quick_add(&DyadicFloat128::new_from_f64( + idx as f64 * (f64::from_bits(0xbf90000000000000)), + )); + } + + let p_f128 = asin_eval_dyadic(u, idx); + let r = x_f128.quick_mul(&p_f128); + return r.fast_as_f64(); + } + + const PI_OVER_TWO: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), + ); + + let x_sign = if x.is_sign_negative() { -1.0 } else { 1.0 }; + + // |x| >= 1 + if x_e >= E_BIAS { + // x = +-1, asin(x) = +- pi/2 + if x_abs == 1.0 { + // return +- pi/2 + return f_fmla(x_sign, PI_OVER_TWO.hi, x_sign * PI_OVER_TWO.lo); + } + // |x| > 1, return NaN. + if x.is_nan() { + return x; + } + return f64::NAN; + } + + // u = (1 - |x|)/2 + let u = f_fmla(x_abs, -0.5, 0.5); + // v_hi + v_lo ~ sqrt(u). + // Let: + // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) + // Then: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // ~ v_hi + h / (2 * v_hi) + // So we can use: + // v_lo = h / (2 * v_hi). + // Then, + // asin(x) ~ pi/2 - 2*(v_hi + v_lo) * P(u) + let v_hi = u.sqrt(); + let h; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + h = f_fmla(v_hi, -v_hi, u); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let v_hi_sq = DoubleDouble::from_exact_mult(v_hi, v_hi); + h = (u - v_hi_sq.hi) - v_hi_sq.lo; + } + // Scale v_lo and v_hi by 2 from the formula: + // vh = v_hi * 2 + // vl = 2*v_lo = h / v_hi. + let vh = v_hi * 2.0; + let vl = h / v_hi; + + // Polynomial approximation: + // p ~ asin(sqrt(u))/sqrt(u) + let err = vh * f64::from_bits(0x3cc0000000000000); + + let (p, err) = asin_eval(DoubleDouble::new(0.0, u), err); + + // Perform computations in double-double arithmetic: + // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) + let r0 = DoubleDouble::quick_mult(DoubleDouble::new(vl, vh), p); + let r = DoubleDouble::from_exact_add(PI_OVER_TWO.hi, -r0.hi); + + let r_lo = PI_OVER_TWO.lo - r0.lo + r.lo; + + let (r_upper, r_lower); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + r_upper = f_fmla(r.hi, x_sign, f_fmla(r_lo, x_sign, err)); + r_lower = f_fmla(r.hi, x_sign, f_fmla(r_lo, x_sign, -err)); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let r_lo = r_lo * x_sign; + let r_hi = r.hi * x_sign; + r_upper = r_hi + (r_lo + err); + r_lower = r.hi + (r_lo - err); + } + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, we redo the computations in Float128. + // Recalculate mod 1/64. + let idx = (u * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // After the first step of Newton-Raphson approximating v = sqrt(u), we have + // that: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // v_lo = h / (2 * v_hi) + // With error: + // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) + // = -h^2 / (2*v * (sqrt(u) + v)^2). + // Since: + // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, + // we can add another correction term to (v_hi + v_lo) that is: + // v_ll = -h^2 / (2*v_hi * 4u) + // = -v_lo * (h / 4u) + // = -vl * (h / 8u), + // making the errors: + // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) + // well beyond 128-bit precision needed. + + // Get the rounding error of vl = 2 * v_lo ~ h / vh + // Get full product of vh * vl + let vl_lo; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + vl_lo = f_fmla(-v_hi, vl, h) / v_hi; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let vh_vl = DoubleDouble::from_exact_mult(v_hi, vl); + vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; + } + + // vll = 2*v_ll = -vl * (h / (4u)). + let t = h * (-0.25) / u; + let vll = f_fmla(vl, t, vl_lo); + // m_v = -(v_hi + v_lo + v_ll). + let mv0 = DyadicFloat128::new_from_f64(vl) + DyadicFloat128::new_from_f64(vll); + let mut m_v = DyadicFloat128::new_from_f64(vh) + mv0; + m_v.sign = DyadicSign::Neg; + + // Perform computations in Float128: + // asin(x) = pi/2 - (v_hi + v_lo + vll) * P(u). + let y_f128 = + DyadicFloat128::new_from_f64(f_fmla(idx as f64, f64::from_bits(0xbf90000000000000), u)); + + const PI_OVER_TWO_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let p_f128 = asin_eval_dyadic(y_f128, idx); + let r0_f128 = m_v.quick_mul(&p_f128); + let mut r_f128 = PI_OVER_TWO_F128.quick_add(&r0_f128); + + if x.is_sign_negative() { + r_f128.sign = DyadicSign::Neg; + } + + r_f128.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_asin_test() { + assert_eq!(f_asin(-0.4), -0.41151684606748806); + assert_eq!(f_asin(-0.8), -0.9272952180016123); + assert_eq!(f_asin(0.3), 0.3046926540153975); + assert_eq!(f_asin(0.6), 0.6435011087932844); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asin_eval_dyadic.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin_eval_dyadic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asin_eval_dyadic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asin_eval_dyadic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1478 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval16; + +// > procedure PRINTF128(a) { +// write("{"); +// if (a < 0) +// then write("Sign::NEG, ") else write("Sign::Pos, "); +// a_exp = floor(log2(a)) + 1; +// write((a + 2 ^ a_exp) * 2 ^ -128); +// print("},"); +// }; +// > verbosity = 0; +// > procedure ASIN_APPROX(N, Deg) { +// abs_error = 0; +// rel_error = 0; +// for i from 1 to N / 4 do { +// Q = fpminimax(asin(sqrt(i / N + x)) / sqrt(i / N + x), Deg, +// [| 128... | ], [ -1 / (2 * N), 1 / (2 * N) ]); +// abs_err = dirtyinfnorm(asin(sqrt(i / N + x)) - sqrt(i / N + x) * Q, +// [ -1 / (2 * N), 1 / (2 * N) ]); +// rel_err = dirtyinfnorm(asin(sqrt(i / N + x)) / sqrt(i / N + x) - Q, +// [ -1 / (2 * N), 1 / (2 * N) ]); +// if (abs_err > abs_error) then abs_error = abs_err; +// if (rel_err > rel_error) then rel_error = rel_err; +// write("{"); +// for j from 0 to Deg do PRINTF128(coeff(Q, j)); +// print("},"); +// }; +// print("Absolute Errors:", abs_error); +// print("Relative Errors:", rel_error); +// }; +// > ASIN_APPROX(64, 15); +// ... +// Absolute Errors: 0x1.0b3...p-129 +// Relative Errors: 0x1.1db...p-128 +// +// For k = 0, we use Taylor polynomial of asin(x)/x around x = 0. +// asin(x)/x ~ 1 + x^2/6 + (3 x^4)/40 + (5 x^6)/112 + (35 x^8)/1152 + +// + (63 x^10)/2816 + (231 x^12)/13312 + (143 x^14)/10240 + +// + (6435 x^16)/557056 + (12155 x^18)/1245184 + +// + (46189 x^20)/5505024 + (88179 x^22)/12058624 + +// + (676039 x^24)/104857600 + (1300075 x^26)/226492416 + +// + (5014575 x^28)/973078528 + (9694845 x^30)/2080374784. +static ASIN_COEFFS_F128: [[DyadicFloat128; 16]; 17] = [ + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x99999999_99999999_99999999_9999999a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xb6db6db6_db6db6db_6db6db6d_b6db6db7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf8e38e38_e38e38e3_8e38e38e_38e38e39_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xb745d174_5d1745d1_745d1745_d1745d17_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8e276276_27627627_62762762_76276276_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xe4cccccc_cccccccc_cccccccc_cccccccd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xbd43c3c3_c3c3c3c3_c3c3c3c3_c3c3c3c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x9fef286b_ca1af286_bca1af28_6bca1af3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x89779e79_e79e79e7_9e79e79e_79e79e7a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xef9de9bd_37a6f4de_9bd37a6f_4de9bd38_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd3431eb8_51eb851e_b851eb85_1eb851ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xbc16ed09_7b425ed0_97b425ed_097b425f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa8dd1846_9ee58469_ee58469e_e58469ee_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x98b41def_7bdef7bd_ef7bdef7_bdef7bdf_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8055f060_94f0f05f_3ac3b927_50a701d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xad19c2ea_e3dd2429_8d04f71d_b965ee1b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9dfa882b_7b31af17_f9f19d33_0c45d24b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xbedd3b58_c9e605ef_1404e1f0_4ba57940_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x83df2581_cb4fea82_b406f201_2fde6d5c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc534fe61_9b82dd16_ed5d8a43_f7710526_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x9b56fa62_88295ddf_ce8425fe_a04d733e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xfdeddb19_4a030da7_27158080_d24caf46_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xd55827db_ff416ea8_042c4d8c_07cddeeb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xb71d73a9_f2ba0688_5eaeeae9_413a0f5f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x9fde87e2_ace91274_38f82666_d619c1ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x8d876557_5e4626a1_1b621336_93587847_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xfd801840_c8710595_6880fe13_a9657f8f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe54245a9_4c8c2ebb_30488494_64b0e34d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd11eb46f_4095a661_8890d123_15c96482_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc01a4201_467fbc0b_960618d5_ec2adaa8_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80ad1cbe_7878de11_4293301c_11ce9d49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaf9ac0df_3d845544_0fe5e31b_9051d03e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa28ceef8_d7297e05_f94773ad_f4a695c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc75a5b77_58b4b11d_396c68ad_6733022b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x8bde42a1_084a6674_50c5bceb_005d4b62_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xd471cdae_e2f35a96_bd4bc513_e0ccdf2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa9fc6fd5_d204a4e3_e609940c_6b991b67_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8d242d97_ba12b492_e25c7e7c_0c3fcf60_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xf0f1ba74_b149afc3_2f0bbab5_a20c6199_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xd21b42fb_d8e9098d_19612692_9a043332_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xba5e5492_7896a3e7_193a74d5_78631587_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xa7a17ae7_fc707f45_910e7a5d_c95251f4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x98889a6a_b0370464_50c950d3_61d79ed7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x8c29330e_4318fd29_25c5b528_84e39e7c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x81e7bf48_b25bc7c0_b9204a4f_d4f5fa8b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf2801b09_11bf0768_773996dd_5224d852_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x81058e3e_f82ba622_ab81cd63_e1a91d57_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb22e7055_c80dd354_8a2f2e8e_860d3f33_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa753ce1a_7e3d1f57_247b37e6_03f93624_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xd05c5604_8eca8d18_dcdd76b7_f4b1f185_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x947cdd5e_f1d64df0_84f78df1_e2ecb854_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xe5218370_2ebbf6e8_3727a755_57843b93_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xba482553_383b92eb_186f78f1_8c35d6af_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x9d2b034a_7266c6a1_54b78a98_1a547429_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8852f723_feea6046_e125f5a9_64e168e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xf19c9891_6c896c99_732052fe_5c54e992_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xd9cc81a5_c5ddf0f0_d651011e_a8ecd936_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xc7173169_dcb6095f_a6160847_b595aaff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xb81cd3f6_4a422ebe_07aeb734_e4dcf3a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xabf01b1c_d15932aa_698d4382_512318a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xa1f1cf1b_d889a1ac_7120ca2f_bbbc1745_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x99a1b838_e38fbf11_429a4350_76b7d191_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x815f4e70_5c3e68f2_e84ed170_78211dfd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb4d5a992_de1ac4da_16fe6024_3a6cc371_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xac526184_bd558c65_66642dce_edc4b04a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xd9ed9b03_46ec0bab_429ea221_4774bbc1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x9dca410c_1efaeb74_87956685_dd5fe848_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf76e411b_a926fc02_7f942265_9c39a882_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xcc71b004_eeb60c0f_1d387f76_44b46bf8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xaf527a40_6f1084fb_5019904e_d12d384d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x9a9304b0_d8a9de19_e1803691_269be22c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8b3d37c0_dbde09ef_342ddf4f_e80dd3fb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xff2e9111_3a961c78_92297bab_cc257804_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xed1fb643_f2ca31c1_b0a1553a_e077285a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xdeeb0f5e_81ad5e30_78d79ae3_83be1c18_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xd3a13ba6_8ce9abfc_a66eb1fd_c0c760fd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xcaa8c381_d44bb44f_0ab25126_9a5fae10_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xc36fb2c4_244401cf_10dd8a39_78ccbf7f_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x81ba6750_6064f4dd_08015b7c_713688f0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb791524b_d975fdd1_584037b7_103b42ca_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb18c26c5_3ced9856_db5bc672_cc95a64f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe4199ce5_d25be89b_4a0ad208_da77022d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xa7d77999_0f80e3e9_7e97e9d1_0e337550_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x85c3e039_8959c95b_e6e1e87f_7e6636b1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xe0b90ecd_95f7e6eb_a675bae0_628bd214_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc3edb6b4_ed0a684c_c7a3ee4d_f1dcd3f9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xafa274d2_e66e1f61_9e8ab3c7_7221214e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa0dd903d_e110b71a_8a1fc9df_cc080308_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x95e2f38c_60441961_72b90625_e3a37573_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8d9fe38f_2c705139_029f857c_9f628b2b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8762410a_4967a974_6b609e83_7c025a39_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x82b220be_d9ec0e5a_9ce9af7c_c65c94b9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xfe866073_2312c056_4265d82a_3afea10c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xf99b667c_5f8ef6a6_11fafa4d_5c76ebb3_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8216e353_2ffdf638_15d72316_a2f327f2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xba625eba_097ce944_7024c0a3_c873729b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb704e369_5b95ce44_cde30106_90e92cc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xeeecee6d_7298b8a3_075da5d7_456bdcde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xb2b78fb1_fcfdc273_1d1ac11c_e29c16f1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x90d21722_148fdaf5_0d566a01_0bb8784b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf7681c54_9771ebb6_17686858_eb5e1caf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xdb5e45c0_52ec0c1c_ff28765e_d4c44bfb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc7ff0dd7_a34ee29b_7cb689af_fe887bf5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xba4e6f37_a98a3e3f_f1175427_20f45c82_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xb08f6e11_688e4174_b3d48abe_c0a6d5cd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa9af6a33_14aabe45_26da1218_05bbb52e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa4fd22fa_1b4f0d7f_1456af96_cbd0cde6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa20229b4_7e9c2e39_22c49987_66a05c5a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa0775ca8_4409c735_351d01f1_34467927_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xa010d2d9_08428a53_53603f20_66c8b8ba_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8274cd6a_f25e642d_0b1a02fb_03f53f3e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xbd49d2c8_b9005b2a_ee795b17_92181a48_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xbcc0ac23_98e00fd7_c40811f5_486aca6a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xfa756493_b381b917_6cdea268_e44dd2fd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xbe7fce1e_462b43c6_0537d6f7_138c87ac_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x9d00958b_edc83095_b4cc907c_a92c30f1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x886a2440_ed93d825_333c19c2_6de36d73_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf616ebc0_4f576462_d9312544_e8fbe0fd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xe43f4c9d_ebb5d685_00903a00_7bd6ad39_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xd8516eab_32337672_569b4e19_a44e795c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xd091fa04_954666ee_cc4da283_82e977c0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xcbf13442_c4c0f859_0449c2c4_2fc046fe_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc9c1d1b4_dea4c76c_d101e562_dc3af77f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc9924d2a_b8ec37d9_80af1780_0fb63e4e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xcb24b252_1ff37e4a_41f35260_2b9ace95_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xce2d87ac_194a6304_1658ed0e_4cdb8161_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x82d4310f_f58b570d_266275fc_1d085c87_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc048c361_72bee7b0_8d2ca7e5_afe4f335_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc2c3ecca_216e290e_b99c5c53_5d48595a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x83611e8f_3adf2217_be3c342a_dfb1c562_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xcb481202_8b0ba9aa_e586f73d_faea68e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xaa727c9a_4caba65d_c8dc13ef_8bed52e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x96b05462_efac126e_db6871d0_0be1eff9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x8a4f8752_9b3c9232_63eb1596_a2c83eb4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x828be6f4_1b14e6e6_8efc1012_2afe425a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xfbd2f055_9d699ea9_b572008e_1fb08088_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf71b3c70_dc4610e6_bc1e581c_817b88bd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf5e8ebf6_3b0aef3f_97ba4c8f_e49b6f0a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xf7986238_1eb8bd7a_73577ed0_c05e4abf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xfbc3832a_a903cd65_a46ee523_f342c621_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x811ea5f3_7409245e_1777fdd1_59b29f80_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x85619588_b83c90ef_67740d6a_d2f372a8_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x83351a49_8764656f_e1774024_a5e751a6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc36057da_23d39c2b_336474e0_3a893914_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc913714c_a46cc0bf_3bdd68ba_53a309d4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x89f2254d_f1469d60_e1324bac_95db6742_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xd92b27f6_38df6911_5842365c_c120cc63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xb94ff079_7848d391_486efffa_a6fbc37f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xa6c03919_862e8437_70f86a73_43da3a6e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x9bcb70c9_a378e97f_a59f25f3_ba202e33_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x95b103b0_62aa9f64_ee2d6146_76020bc5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x92fa4a1c_7d7fd161_8f25aa4e_f65ca52f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x92d387a2_c5dd771d_4015ca29_e3eda1d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x94c13c5c_997615c3_8a2f63c8_c314226f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x987b8c8f_5e9e7a5f_e8497909_d60d1194_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x9ddb0978_da99e6ad_83d5eca2_9d079ef7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xa4d9aeee_4b512ed4_5ec95cd1_37ce3f22_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xad602af3_1e14d681_8a267da2_57c030de_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x839795b7_8f3005a4_689f57cc_d201f7dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc691cb89_3d75d3d5_a1892f2a_bf54ec45_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xcfb46fc4_6d28c32c_9ae5ad3d_a7749dc8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x90f71352_c806c830_20edb8b2_7594386b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe8473840_d511dc77_d63def5d_7f4de9c0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc9c6eb30_aaf2b63d_ec20f671_8689534a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xb8dcfa84_eb6cab93_3023ddcc_b8f68a2f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xafde4094_c1a14390_9609a3ea_847225a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xac1254e7_5852a836_b2aca5e5_0cfc484f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xac0d3ffa_d6171016_b1a12557_858663c1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xaf0877f9_0ca5c52f_fc54b5af_b5cbc350_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xb498574f_af349a2b_f391ff83_b3570919_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xbc87c7bb_34182440_280647cd_976affb0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc6c5688f_58a42593_4569de36_0855c393_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xd368b088_5bb9496a_dd7c92df_8798aaf7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe272168a_c8dbe668_381542bf_fc24c266_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x83fbb09c_fbb0ebf4_208c9037_70373f79_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc9de6f84_8e652b0b_3b2a2bb9_f7ce3de8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xd6ac93c7_6e215233_f184fdcc_e5872970_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x987a35b9_87c02522_1927dee9_70fc6b18_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xf8be450d_266409a9_2e534ffd_905f4424_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xdc0c36d7_34415e3b_c5121c4d_4e28c17d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xcd551b98_81d982a8_1399d9ba_ddf55821_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc6f91e3f_428d6be3_646f3147_20445145_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc64f100c_85e1e8f1_6f501d1e_2155f872_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc9fe25ae_295f1f24_5924cf9a_036a31f2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xd157410e_fcc10fbb_fceb318a_b4990bd7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xdc0aeb56_ca679f92_3b3c44d8_99b1add7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xea05b383_bc339550_e5c5c34b_bfa416a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xfb5e3897_5a5c8f62_280a90dc_9ebe9107_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x88301d81_b38f225d_2226ab7e_df342d90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x949e3465_e4a8aef7_46311182_5fc3fde8_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x846178eb_1c7260da_3e0aca9a_51e68d84_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcd47ac90_3c311c2b_98dd7493_4656d210_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xde020b2d_abd5628c_b88634e5_73f312fc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa086fafa_c220fb73_9939cae3_2d69683f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x855b5efa_f6963d73_e4664cb1_d43f03a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xf05c9774_fe0de25c_ccf1c1df_d2ed9941_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe484a941_19639229_f06ae955_f8edc7d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe1a32bb2_52ca122c_bf2f0904_cfc476cb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe528e091_7bb8a01a_9218ce3e_1e85af60_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xeddd556a_faa2d46f_e91c61fa_adf12aec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xfb390fa3_15e9d55f_5683c0c4_c7719f81_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x868e5fa4_15597c8f_7c42a262_8f2d6332_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x91d79767_a3d037f9_cd84ead5_c0714310_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9fa6a035_915bc052_377a8abb_faf4e3c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb04edefd_6ac2a93e_ec33e6f6_3d53e7c2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc416980d_dc5c186b_7bdcded6_97ea5844_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x84c8fd4d_ffdf9fc6_bdd7ebca_88183d7b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd0cf0544_11dbf845_cb6eeae5_bc980e2f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe5bb9480_7ce0eaca_74300a46_8398e944_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa92a18f8_d611860b_5f2ef8c6_8e8ca002_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x8f2e1684_17eb4e6c_1ec44b9b_e4b1c3e5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x837f1764_0ee8f416_8694b4a1_c647af0c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xfed7e2a9_05a5190e_b7d70a61_a24ad801_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x803f29ff_dc6fd2bc_3c3c4b50_a9dc860c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x84c61e09_b8aa35e4_96239f9c_b1d00b3c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x8c7ed311_f77980d6_842ddf90_6a68a0bc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9746077b_d397c2d1_038a4744_a76f5fb5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa5341277_c4185ace_54f26328_322158e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb68d78f5_0972f6de_9189aa23_d3ecefc2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xcbbcefc2_15bade4e_f1d36947_c8b6e460_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe564a459_c851390d_d45a4748_f29f182b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x820ea28b_c89662c3_2a64ccdc_efb2b259_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x85324d39_f30f9174_ac0d817e_9c744b0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd476186e_49c47f3a_a71f8886_7f9f21c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xede08f54_a830e87b_07881700_65e57b6c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb271b8eb_309963ee_89187c73_0b92f7d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x99f0011d_95d3a6dd_282bd00a_db808151_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9021134e_02b479e7_3aabf9bb_b7ab6cf3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x8e673bf2_f11db54a_909c4c72_6389499f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9226a371_88dd55f7_bfe21777_4a42a7ae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9a4d78fc_9df79d9a_44609c02_a625808a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa68335fb_41d2d91c_e7bbd2a3_31a1d17b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb6d89c39_28d0cb26_809d4df6_e55cba1a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xcba71468_9177fc2d_7f23df2f_37226488_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe5846de8_44833ae9_34416c87_0315eb9e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x82a07032_64e6226b_200d94a1_66fc7951_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9602695c_b6fa8886_68ca0cba_b59ea683_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xad7d185a_ab3d14dd_d908a7b1_c57352bb_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x859d78fa_4405d8fa_287dbc69_95d0975e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd83ea3bc_131d6baa_67c51d88_4c4dae01_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xf6790edb_df07342b_aad85870_167af128_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xbc6daa33_12be0f85_bc7fa753_52b10a83_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa5bd41bc_9c986b13_1af2542e_92aacb59_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9e4358bc_24e04364_b4539b76_e444b790_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9f7fc21b_dca1f2b5_f3f6d44b_c5a37626_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa6fd793c_0b9c44c1_30a518cc_66b5e511_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb3dccfac_cd1592b3_bcd6b7c0_9749993d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc6056c3a_4a5f329a_48f1429d_27f930fc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xddd9e529_858a4502_6e7f3d1c_1e7dcb89_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xfc1bccee_dc8d2567_1721c468_6f7f53ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x90f2bb21_5cdbe7e2_f9ef8e12_059cc66a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa857d5df_5b4da940_15ce4e95_7201fc79_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc54119c0_10c02bf4_d87ece17_1ef85c5f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe8c50ebc_880356de_2c1f4c42_9ee9748f_u128, + }, + ], + [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x860a91c1_6b9b2c23_2dd99707_ab3d688b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xdc2a86b1_5fdb645d_ea2781dd_25555f49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xff8def07_d1e514d7_b2e8ebb6_5c3afe5e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc72f9d5b_4fb559e3_20db92e3_a5ae3f73_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb2b5f45b_1d26f4dd_0b210309_fb68914f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xae1cbaae_c7b55465_4da858f5_47e62a37_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb30f3998_10202a0d_a52ec085_a7d63289_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xbf51f27f_b7aff89d_dc24e2aa_208d2054_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xd250735e_87d0b527_6f99bcc9_bd6fc717_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xec543ec2_bddb2efb_36d9ce81_a7c84336_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x871f73e3_298ef45c_eed83998_2bc731b9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9cbb5447_af8574f1_21fa4cda_93d82b7e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb7f5a6c0_430a347f_11b22cde_91de0885_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xda153cc4_14abdb96_840df7c2_3299fec0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x826c129b_3e4a2612_b2cd11f1_4d2ba60c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9d19c289_fc0e8aa4_f351418b_b760ce90_u128, + }, + ], +]; + +#[cold] +pub(crate) fn asin_eval_dyadic(u: DyadicFloat128, idx: usize) -> DyadicFloat128 { + let coeffs = ASIN_COEFFS_F128[idx]; + f_polyeval16( + u, coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], coeffs[6], coeffs[7], + coeffs[8], coeffs[9], coeffs[10], coeffs[11], coeffs[12], coeffs[13], coeffs[14], + coeffs[15], + ) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,203 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::acosf::poly12; +use crate::common::{dd_fmlaf, f_fmla}; + +#[cold] +fn as_special(x: f32) -> f32 { + let t = x.to_bits(); + let ax = t.wrapping_shl(1); + if ax > (0xffu32 << 24) { + return x + x; + } // nan + f32::NAN +} + +#[inline(always)] +/// fma - fma +/// dd_fma - mandatory fma fallback +fn asinf_gen_impl f64, F: Fn(f32, f32, f32) -> f32>( + x: f32, + fma: Q, + dd_fma: F, +) -> f32 { + const PI2: f64 = f64::from_bits(0x3ff921fb54442d18); + let xs = x as f64; + let mut r; + let t = x.to_bits(); + let ax = t.wrapping_shl(1); + if ax > 0x7f << 24 { + return as_special(x); + } + if ax < 0x7ec29000u32 { + // |x| < 1.49029 + if ax < 115 << 24 { + // |x| < 0.000244141 + return dd_fma(x, f64::from_bits(0x3e60000000000000) as f32, x); + } + const B: [u64; 16] = [ + 0x3ff0000000000005, + 0x3fc55557aeca105d, + 0x3fb3314ec3db7d12, + 0x3fa775738a5a6f92, + 0x3f75d5f7ce1c8538, + 0x3fd605c6d58740f0, + 0xc005728b732d73c6, + 0x402f152170f151eb, + 0xc04f962ea3ca992e, + 0x40671971e17375a0, + 0xc07860512b4ba230, + 0x40826a3b8d4bdb14, + 0xc0836f2ea5698b51, + 0x407b3d722aebfa2e, + 0xc066cf89703b1289, + 0x4041518af6a65e2d, + ]; + let z = xs; + let z2 = z * z; + let w0 = fma(z2, f64::from_bits(B[1]), f64::from_bits(B[0])); + let w1 = fma(z2, f64::from_bits(B[3]), f64::from_bits(B[2])); + let w2 = fma(z2, f64::from_bits(B[5]), f64::from_bits(B[4])); + let w3 = fma(z2, f64::from_bits(B[7]), f64::from_bits(B[6])); + let w4 = fma(z2, f64::from_bits(B[9]), f64::from_bits(B[8])); + let w5 = fma(z2, f64::from_bits(B[11]), f64::from_bits(B[10])); + let w6 = fma(z2, f64::from_bits(B[13]), f64::from_bits(B[12])); + let w7 = fma(z2, f64::from_bits(B[15]), f64::from_bits(B[14])); + + let z4 = z2 * z2; + let z8 = z4 * z4; + let z16 = z8 * z8; + + r = z + * ((fma(z4, w1, w0) + z8 * fma(z4, w3, w2)) + + z16 * (fma(z4, w5, w4) + z8 * fma(z4, w7, w6))); + let ub = r; + let lb = r - z * f64::from_bits(0x3e0efa8eb0000000); + // Ziv's accuracy test + if ub == lb { + return ub as f32; + } + } + if ax < (0x7eu32 << 24) { + const C: [u64; 12] = [ + 0x3fc555555555529c, + 0x3fb333333337e0dd, + 0x3fa6db6db3b4465e, + 0x3f9f1c72e13ac306, + 0x3f96e89cebe06bc4, + 0x3f91c6dcf5289094, + 0x3f8c6dbbcc7c6315, + 0x3f88f8dc2615e996, + 0x3f7a5833b7bf15e8, + 0x3f943f44ace1665c, + 0xbf90fb17df881c73, + 0x3fa07520c026b2d6, + ]; + let z = xs; + let z2 = z * z; + let c0 = poly12(z2, C, &fma); + r = z + (z * z2) * c0; + } else { + if ax == 0x7e55688au32 { + return f32::copysign(f64::from_bits(0x3fe75b8a20000000) as f32, x) + + f32::copysign(f64::from_bits(0x3e50000000000000) as f32, x); + } + if ax == 0x7e107434u32 { + return f32::copysign(f64::from_bits(0x3fe1f4b640000000) as f32, x) + + f32::copysign(f64::from_bits(0x3e50000000000000) as f32, x); + } + let bx = xs.abs(); + let z = 1.0 - bx; + let s = z.sqrt(); + const C: [u64; 12] = [ + 0x3ff6a09e667f3bcb, + 0x3fbe2b7dddff2db9, + 0x3f9b27247ab42dbc, + 0x3f802995cc4e0744, + 0x3f65ffb0276ec8ea, + 0x3f5033885a928dec, + 0x3f3911f2be23f8c7, + 0x3f24c3c55d2437fd, + 0x3f0af477e1d7b461, + 0x3f0abd6bdff67dcb, + 0xbef1717e86d0fa28, + 0x3ef6ff526de46023, + ]; + r = PI2 - s * poly12(z, C, &fma); + r = f64::copysign(r, xs); + } + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn asinf_fma_impl(x: f32) -> f32 { + asinf_gen_impl(x, f64::mul_add, f32::mul_add) +} + +/// Computes asin +/// +/// Max found ULP 0.49999928 +#[inline] +pub fn f_asinf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + asinf_gen_impl(x, f_fmla, dd_fmlaf) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + asinf_fma_impl + } else { + fn def_asinf(x: f32) -> f32 { + asinf_gen_impl(x, f_fmla, dd_fmlaf) + } + def_asinf + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_asinf() { + assert_eq!(f_asinf(-0.5), -std::f32::consts::FRAC_PI_6); + assert_eq!(f_asinf(0.5), std::f32::consts::FRAC_PI_6); + assert!(f_asinf(7.).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,370 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::acospi::INV_PI_DD; +use crate::asin::asin_eval; +use crate::asin_eval_dyadic::asin_eval_dyadic; +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; + +/// Computes asin(x)/PI +/// +/// Max found ULP 0.5 +pub fn f_asinpi(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // |x| < 0.5. + if x_e < E_BIAS - 1 { + // |x| < 2^-26. + if x_e < E_BIAS - 26 { + // When |x| < 2^-26, the relative error of the approximation asin(x) ~ x + // is: + // |asin(x) - x| / |asin(x)| < |x^3| / (6|x|) + // = x^2 / 6 + // < 2^-54 + // < epsilon(1)/2. + // = x otherwise. , + if x.abs() == 0. { + return x; + } + + if x_e < E_BIAS - 56 { + if (x_abs.to_bits().wrapping_shl(12)) == 0x59af9a1194efe000u64 { + let e = (x.to_bits() >> 52) & 0x7ff; + let h = f64::from_bits(0x3c7b824198b94a89); + let l = f64::from_bits(0x391fffffffffffff); + let mut t = (if x > 0. { 1.0f64 } else { -1.0f64 }).to_bits(); + t = t.wrapping_sub(0x3c9u64.wrapping_sub(e).wrapping_shl(52)); + return f_fmla(l, f64::from_bits(t), h * f64::from_bits(t)); + } + + let h = x * INV_PI_DD.hi; + let sx = x * f64::from_bits(0x4690000000000000); /* scale x */ + let mut l = dd_fmla(sx, INV_PI_DD.hi, -h * f64::from_bits(0x4690000000000000)); + l = dd_fmla(sx, INV_PI_DD.lo, l); + /* scale back */ + let res = dyad_fmla(l, f64::from_bits(0x3950000000000000), h); + return res; + } + + /* We use the Sollya polynomial 0x1.45f306dc9c882a53f84eafa3ea4p-2 * x + + 0x1.b2995e7b7b606p-5 * x^3, with relative error bounded by 2^-106.965 + on [2^-53, 2^-26] */ + const C1H: f64 = f64::from_bits(0x3fd45f306dc9c883); + const C1L: f64 = f64::from_bits(0xbc76b01ec5417057); + const C3: f64 = f64::from_bits(0x3fab2995e7b7b606); + let h = C1H; + let l = dd_fmla(C3, x * x, C1L); + /* multiply h+l by x */ + let hh = h * x; + let mut ll = dd_fmla(h, x, -hh); + /* hh+ll = h*x */ + ll = dd_fmla(l, x, ll); + return hh + ll; + } + + let x_sq = DoubleDouble::from_exact_mult(x, x); + let err = x_abs * f64::from_bits(0x3cc0000000000000); + // Polynomial approximation: + // p ~ asin(x)/x + + let (p, err) = asin_eval(x_sq, err); + // asin(x) ~ x * (ASIN_COEFFS[idx][0] + p) + let mut r0 = DoubleDouble::from_exact_mult(x, p.hi); + let mut r_lo = f_fmla(x, p.lo, r0.lo); + + r0 = DoubleDouble::mult(DoubleDouble::new(r_lo, r0.hi), INV_PI_DD); + r_lo = r0.lo; + + let r_upper = r0.hi + (r_lo + err); + let r_lower = r0.hi + (r_lo - err); + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, perform 128-bit calculation. + + // Recalculate mod 1/64. + let idx = (x_sq.hi * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // Get x^2 - idx/64 exactly. When FMA is available, double-double + // multiplication will be correct for all rounding modes. Otherwise, we use + // Float128 directly. + let x_f128 = DyadicFloat128::new_from_f64(x); + + let u: DyadicFloat128; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + // u = x^2 - idx/64 + let u_hi = DyadicFloat128::new_from_f64(f_fmla( + idx as f64, + f64::from_bits(0xbf90000000000000), + x_sq.hi, + )); + u = u_hi.quick_add(&DyadicFloat128::new_from_f64(x_sq.lo)); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x_sq_f128 = x_f128.quick_mul(&x_f128); + u = x_sq_f128.quick_add(&DyadicFloat128::new_from_f64( + idx as f64 * (f64::from_bits(0xbf90000000000000)), + )); + } + + let p_f128 = asin_eval_dyadic(u, idx); + let mut r = x_f128.quick_mul(&p_f128); + r = r.quick_mul(&crate::acospi::INV_PI_F128); + return r.fast_as_f64(); + } + + const PI_OVER_TWO: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), + ); + + let x_sign = if x.is_sign_negative() { -1.0 } else { 1.0 }; + + // |x| >= 1 + if x_e >= E_BIAS { + // x = +-1, asin(x) = +- pi/2 + if x_abs == 1.0 { + // return +- pi/2 + return x * 0.5; // asinpi_specific + } + // |x| > 1, return NaN. + if x.is_nan() { + return x; + } + return f64::NAN; + } + + // u = (1 - |x|)/2 + let u = f_fmla(x_abs, -0.5, 0.5); + // v_hi + v_lo ~ sqrt(u). + // Let: + // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) + // Then: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // ~ v_hi + h / (2 * v_hi) + // So we can use: + // v_lo = h / (2 * v_hi). + // Then, + // asin(x) ~ pi/2 - 2*(v_hi + v_lo) * P(u) + let v_hi = u.sqrt(); + let h; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + h = f_fmla(v_hi, -v_hi, u); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let v_hi_sq = DoubleDouble::from_exact_mult(v_hi, v_hi); + h = (u - v_hi_sq.hi) - v_hi_sq.lo; + } + // Scale v_lo and v_hi by 2 from the formula: + // vh = v_hi * 2 + // vl = 2*v_lo = h / v_hi. + let vh = v_hi * 2.0; + let vl = h / v_hi; + + // Polynomial approximation: + // p ~ asin(sqrt(u))/sqrt(u) + let err = vh * f64::from_bits(0x3cc0000000000000); + + let (p, err) = asin_eval(DoubleDouble::new(0.0, u), err); + + // Perform computations in double-double arithmetic: + // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) + let r0 = DoubleDouble::quick_mult(DoubleDouble::new(vl, vh), p); + let mut r = DoubleDouble::from_exact_add(PI_OVER_TWO.hi, -r0.hi); + + let mut r_lo = PI_OVER_TWO.lo - r0.lo + r.lo; + + let p = DoubleDouble::mult(DoubleDouble::new(r_lo, r.hi), INV_PI_DD); + r_lo = p.lo; + r.hi = p.hi; + + let (r_upper, r_lower); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + r_upper = f_fmla(r.hi, x_sign, f_fmla(r_lo, x_sign, err)); + r_lower = f_fmla(r.hi, x_sign, f_fmla(r_lo, x_sign, -err)); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let r_lo = r_lo * x_sign; + let r_hi = r.hi * x_sign; + r_upper = r_hi + (r_lo + err); + r_lower = r.hi + (r_lo - err); + } + + if r_upper == r_lower { + return r_upper; + } + + // Ziv's accuracy test failed, we redo the computations in Float128. + // Recalculate mod 1/64. + let idx = (u * f64::from_bits(0x4050000000000000)).cpu_round() as usize; + + // After the first step of Newton-Raphson approximating v = sqrt(u), we have + // that: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // v_lo = h / (2 * v_hi) + // With error: + // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) + // = -h^2 / (2*v * (sqrt(u) + v)^2). + // Since: + // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, + // we can add another correction term to (v_hi + v_lo) that is: + // v_ll = -h^2 / (2*v_hi * 4u) + // = -v_lo * (h / 4u) + // = -vl * (h / 8u), + // making the errors: + // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) + // well beyond 128-bit precision needed. + + // Get the rounding error of vl = 2 * v_lo ~ h / vh + // Get full product of vh * vl + let vl_lo; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + vl_lo = f_fmla(-v_hi, vl, h) / v_hi; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let vh_vl = DoubleDouble::from_exact_mult(v_hi, vl); + vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; + } + + // vll = 2*v_ll = -vl * (h / (4u)). + let t = h * (-0.25) / u; + let vll = f_fmla(vl, t, vl_lo); + // m_v = -(v_hi + v_lo + v_ll). + let mv0 = DyadicFloat128::new_from_f64(vl) + DyadicFloat128::new_from_f64(vll); + let mut m_v = DyadicFloat128::new_from_f64(vh) + mv0; + m_v.sign = DyadicSign::Neg; + + // Perform computations in Float128: + // asin(x) = pi/2 - (v_hi + v_lo + vll) * P(u). + let y_f128 = + DyadicFloat128::new_from_f64(f_fmla(idx as f64, f64::from_bits(0xbf90000000000000), u)); + + const PI_OVER_TWO_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let p_f128 = asin_eval_dyadic(y_f128, idx); + let r0_f128 = m_v * p_f128; + let mut r_f128 = PI_OVER_TWO_F128 + r0_f128; + + if x.is_sign_negative() { + r_f128.sign = DyadicSign::Neg; + } + + r_f128 = r_f128.quick_mul(&crate::acospi::INV_PI_F128); + + r_f128.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_asinpi_test() { + assert_eq!( + f_asinpi(-0.00000000032681723993732703), + -0.00000000010402915844735117 + ); + assert_eq!(f_asinpi(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017801371778309684), 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005666352624669099); + assert_eq!(f_asinpi(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026752519513526076), 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008515591441480124); + assert_eq!(f_asinpi(-0.4), -0.13098988043445461); + assert_eq!(f_asinpi(-0.8), -0.2951672353008666); + assert_eq!(f_asinpi(0.4332432142124432), 0.14263088583055605); + assert_eq!(f_asinpi(0.8543543534343434), 0.326047108714517); + assert_eq!(f_asinpi(0.00323146509843243), 0.0010286090778797426); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/asinpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/asinpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,294 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +pub(crate) static ASINCOSF_PI_TABLE: [[u64; 8]; 16] = [ + [ + 0x3fd45f306dc9c882, + 0x3fab2995e7b7dc2f, + 0x3f98723a1cf50c7e, + 0x3f8d1a4591d16a29, + 0x3f83ce3aa68ddaee, + 0x3f7d3182ab0cc1bf, + 0x3f762b379a8b88e3, + 0x3f76811411fcfec2, + ], + [ + 0x3fdffffffffd3cda, + 0xbfb17cc1b3355fdd, + 0x3f9d067a1e8d5a99, + 0xbf908e16fb09314a, + 0x3f85eed43d42dcb2, + 0xbf7f58baca7acc71, + 0x3f75dab64e2dcf15, + 0xbf659270e30797ac, + ], + [ + 0x3fdfffffff7c4617, + 0xbfb17cc149ded3a2, + 0x3f9d0654d4cb2c1a, + 0xbf908c3ba713d33a, + 0x3f85d2053481079c, + 0xbf7e485ebc545e7e, + 0x3f7303baca167ddd, + 0xbf5dee8d16d06b38, + ], + [ + 0x3fdffffffa749848, + 0xbfb17cbe71559350, + 0x3f9d05a312269adf, + 0xbf90862b3ee617d7, + 0x3f85920708db2a73, + 0xbf7cb0463b3862c3, + 0x3f702b82478f95d7, + 0xbf552a7b8579e729, + ], + [ + 0x3fdfffffe1f92bb5, + 0xbfb17cb3e74c64e3, + 0x3f9d03af67311cbf, + 0xbf9079441cbfc7a0, + 0x3f852b4287805a61, + 0xbf7ac3286d604a98, + 0x3f6b2f1210d9701b, + 0xbf4e740ddc25afd6, + ], + [ + 0x3fdfffff92beb6e2, + 0xbfb17c986fe9518b, + 0x3f9cff98167c9a5e, + 0xbf90638b591eae52, + 0x3f84a0803828959e, + 0xbf78adeca229f11d, + 0x3f66b9a7ba05dfce, + 0xbf4640521a43b2d0, + ], + [ + 0x3fdffffeccee5bfc, + 0xbfb17c5f1753f5ea, + 0x3f9cf874e4fe258f, + 0xbf9043e6cf77b256, + 0x3f83f7db42227d92, + 0xbf7691a6fa2a2882, + 0x3f62f6543162bc61, + 0xbf407d5da05822b6, + ], + [ + 0x3fdffffd2f64431d, + 0xbfb17bf8208c10c1, + 0x3f9ced7487cdb124, + 0xbf901a0d30932905, + 0x3f83388f99b254da, + 0xbf74844e245c65bd, + 0x3f5fa777150197c6, + 0xbf38c1ecf16a05c8, + ], + [ + 0x3fdffffa36d1712e, + 0xbfb17b523971bd4e, + 0x3f9cddee26de2dee, + 0xbf8fccb00abaaabc, + 0x3f8269afc3622342, + 0xbf72933152686752, + 0x3f5a76d4956cc9a3, + 0xbf32ce7d6dc651ce, + ], + [ + 0x3fdffff5402ab3a1, + 0xbfb17a5ba85da77a, + 0x3f9cc96894e05c02, + 0xbf8f532143cb832e, + 0x3f819180b660ff09, + 0xbf70c57417a78b3c, + 0x3f562e26cbd7bb1e, + 0xbf2ce28d33fe1df3, + ], + [ + 0x3fdfffed8d639751, + 0xbfb1790349f3ae76, + 0x3f9caf9a4fd1b398, + 0xbf8ec986b111342e, + 0x3f80b53c3ad4baa4, + 0xbf6e3c2282eeace4, + 0x3f52a55369f55bbe, + 0xbf2667fe48c396e8, + ], + [ + 0x3fdfffe24b714161, + 0xbfb177394fbcb719, + 0x3f9c90652d920ebd, + 0xbf8e3239197bddf1, + 0x3f7fb2188525b025, + 0xbf6b3aadd451afc7, + 0x3f4f74020f31fdab, + 0xbf218b0cb246768d, + ], + [ + 0x3fdfffd298bec9e2, + 0xbfb174efbfd34648, + 0x3f9c6bcfe48ea92b, + 0xbf8d8f9f2a16157c, + 0x3f7e0044f56c8864, + 0xbf6883e2347fe76c, + 0x3f4a9f0e3c1b7af5, + 0xbf1bb5acc0e60825, + ], + [ + 0x3fdfffbd8b784c4d, + 0xbfb1721abdd3722e, + 0x3f9c41fee756d4b0, + 0xbf8ce40bccf8065f, + 0x3f7c59b684b70ef9, + 0xbf66133d027996b3, + 0x3f469cad01106397, + 0xbf160f8e45494156, + ], + [ + 0x3fdfffa23749cf88, + 0xbfb16eb0a8285c06, + 0x3f9c132d762e1b0d, + 0xbf8c31a959398f4e, + 0x3f7ac1c5b46bc8a0, + 0xbf63e34f1abe51dc, + 0x3f4346738737c0b9, + 0xbf11b227a3f5c750, + ], + [ + 0x3fdfff7fb25bb407, + 0xbfb16aaa14d75640, + 0x3f9bdfa75fca5ff2, + 0xbf8b7a6e260d079c, + 0x3f793ab06911033c, + 0xbf61ee5560967fd5, + 0x3f407d31060838bf, + 0xbf0c96f33a283115, + ], +]; + +#[inline(always)] +fn asinpif_gen_impl f64>(x: f32, fma: Q) -> f32 { + let ax = x.abs(); + let az = ax as f64; + let z = x as f64; + let t = x.to_bits(); + let e: i32 = ((t >> 23) & 0xff) as i32; + if e >= 127 { + // |x| >= 1 or nan + if ax == 1.0 { + return f32::copysign(0.5, x); + } // |x| = 1 + if e == 0xff && (t.wrapping_shl(9)) != 0 { + return x + x; + } // x = nan + return f32::NAN; // |x| > 1 + } + let s: i32 = 146i32.wrapping_sub(e); + let mut i = 0i32; + // s<32 corresponds to |x| >= 2^-12 + if s < 32 { + i = (((t & 0x007fffff) | 1 << 23) >> s) as i32; + } + let z2 = z * z; + let z4 = z2 * z2; + let c = ASINCOSF_PI_TABLE[i as usize & 15]; + if i == 0 { + // |x| < 2^-4 + let mut c0 = fma(z2, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c2 = fma(z2, f64::from_bits(c[3]), f64::from_bits(c[2])); + let mut c4 = fma(z2, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c6 = fma(z2, f64::from_bits(c[7]), f64::from_bits(c[6])); + c0 = fma(c2, z4, c0); + c4 = fma(c6, z4, c4); + c0 += c4 * (z4 * z4); + (z * c0) as f32 + } else { + // |x| >= 2^-4 + let f = (1. - az).sqrt(); + let mut c0 = fma(az, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c2 = fma(az, f64::from_bits(c[3]), f64::from_bits(c[2])); + let mut c4 = fma(az, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c6 = fma(az, f64::from_bits(c[7]), f64::from_bits(c[6])); + c0 = fma(c2, z2, c0); + c4 = fma(c6, z2, c4); + c0 += c4 * z4; + let r = fma( + -c0, + f64::copysign(f, x as f64), + f64::copysign(0.5, x as f64), + ); + r as f32 + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn asinpif_fma_impl(x: f32) -> f32 { + asinpif_gen_impl(x, f64::mul_add) +} + +/// Computes asin(x)/PI +/// +/// Max ULP 0.5 +#[inline] +pub fn f_asinpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + asinpif_gen_impl(x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + asinpif_fma_impl + } else { + fn def_asinpif(x: f32) -> f32 { + asinpif_gen_impl(x, f_fmla) + } + def_asinpif + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_asinpif() { + assert_eq!(f_asinpif(0.0), 0.); + assert_eq!(f_asinpif(0.5), 0.16666667); + assert!(f_asinpif(1.5).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/alpha0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/alpha0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,292 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval9; + +// +/// See [bessel_0_asympt_alpha] for the info +pub(crate) fn bessel_0_asympt_alpha_hard(reciprocal: DyadicFloat128) -> DyadicFloat128 { + static C: [DyadicFloat128; 18] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x85555555_55555555_55555555_55555555_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd6999999_99999999_99999999_9999999a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0xd1ac2492_49249249_24924924_92492492_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -123, + mantissa: 0xbbcd0fc7_1c71c71c_71c71c71_c71c71c7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -118, + mantissa: 0x85e8fe45_8ba2e8ba_2e8ba2e8_ba2e8ba3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0x8b5a8f33_63c4ec4e_c4ec4ec4_ec4ec4ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -108, + mantissa: 0xc7661d79_9d59b555_55555555_55555555_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -102, + mantissa: 0xbbced715_c2897a28_78787878_78787878_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -96, + mantissa: 0xe14b19b4_aae3f7fe_be1af286_bca1af28_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xa7af7341_db2192db_975e0c30_c30c30c3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -82, + mantissa: 0x97a8f676_b349f6fc_5cefd338_590b2164_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -75, + mantissa: 0xa3d299fb_6f304d73_86e15f12_0fd70a3d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -68, + mantissa: 0xd050b737_cbc044ef_e8807e3c_87f43da1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -60, + mantissa: 0x9a02379b_daa7e492_854f42de_6d3dffe6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -52, + mantissa: 0x83011a39_380e467d_de6b70ec_b92ce0cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -45, + mantissa: 0xfe16521f_c79e5d9a_a5bed653_e3844e9a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -36, + mantissa: 0x8b54b13d_3fb3e1c4_15dbb880_0bb32218_u128, + }, + ]; + + let x2 = reciprocal * reciprocal; + + let mut p = C[17]; + for i in (0..17).rev() { + p = x2 * p + C[i]; + } + + p * reciprocal +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` +**/ +#[inline] +pub(crate) fn bessel_0_asympt_alpha(recip: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3fc0000000000000), + (0x3c55555555555555, 0xbfb0aaaaaaaaaaab), + (0x3c5999999999999a, 0x3fcad33333333333), + (0xbc92492492492492, 0xbffa358492492492), + (0xbcbc71c71c71c71c, 0x403779a1f8e38e39), + (0xbd0745d1745d1746, 0xc080bd1fc8b1745d), + (0xbd7d89d89d89d89e, 0x40d16b51e66c789e), + (0x3dc5555555555555, 0xc128ecc3af33ab37), + (0x3e2143c3c3c3c3c4, 0x418779dae2b8512f), + (0x3df41e50d79435e5, 0xc1ec296336955c7f), + (0x3ef6dcbaf0618618, 0x4254f5ee683b6432), + (0x3f503a3102cc7a6f, 0xc2c2f51eced6693f), + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[11]), + DoubleDouble::from_bit_pair(C[10]), + ); + + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[9])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[8])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[7])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[6])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[0].1)); + + let z = DoubleDouble::quick_mult(p, recip); + + DoubleDouble::from_exact_add(z.hi, z.lo) +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` +**/ +#[inline] +pub(crate) fn bessel_0_asympt_alpha_fast(recip: DoubleDouble) -> DoubleDouble { + const C: [u64; 12] = [ + 0x3fc0000000000000, + 0xbfb0aaaaaaaaaaab, + 0x3fcad33333333333, + 0xbffa358492492492, + 0x403779a1f8e38e39, + 0xc080bd1fc8b1745d, + 0x40d16b51e66c789e, + 0xc128ecc3af33ab37, + 0x418779dae2b8512f, + 0xc1ec296336955c7f, + 0x4254f5ee683b6432, + 0xc2c2f51eced6693f, + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let p = f_polyeval9( + x2.hi, + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + f64::from_bits(C[10]), + f64::from_bits(C[11]), + ); + + let mut z = DoubleDouble::mul_f64_add_f64(x2, p, f64::from_bits(C[2])); + z = DoubleDouble::mul_add_f64(x2, z, f64::from_bits(C[1])); + z = DoubleDouble::mul_add_f64(x2, z, f64::from_bits(C[0])); + DoubleDouble::quick_mult(z, recip) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/alpha1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/alpha1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/alpha1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,296 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval9; + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn bessel_1_asympt_alpha_fast(recip: DoubleDouble) -> DoubleDouble { + const C: [u64; 12] = [ + 0xbfd8000000000000, + 0x3fc5000000000000, + 0xbfd7bccccccccccd, + 0x4002f486db6db6db, + 0xc03e9fbf40000000, + 0x4084997b55945d17, + 0xc0d4a914195269d9, + 0x412cd1b53816aec1, + 0xc18aa4095d419351, + 0x41ef809305f11b9d, + 0xc2572e6809ed618b, + 0x42c4c5b6057839f9, + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let p = f_polyeval9( + x2.hi, + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + f64::from_bits(C[10]), + f64::from_bits(C[11]), + ); + + let mut z = DoubleDouble::mul_f64_add_f64(x2, p, f64::from_bits(C[2])); + z = DoubleDouble::mul_add_f64(x2, z, f64::from_bits(C[1])); + z = DoubleDouble::mul_add_f64(x2, z, f64::from_bits(C[0])); + DoubleDouble::quick_mult(z, recip) +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn bessel_1_asympt_alpha(recip: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 12] = [ + (0x0000000000000000, 0xbfd8000000000000), + (0x0000000000000000, 0x3fc5000000000000), + (0x3c6999999999999a, 0xbfd7bccccccccccd), + (0x3cab6db6db6db6db, 0x4002f486db6db6db), + (0x0000000000000000, 0xc03e9fbf40000000), + (0x3d21745d1745d174, 0x4084997b55945d17), + (0x3d789d89d89d89d9, 0xc0d4a914195269d9), + (0xbdb999999999999a, 0x412cd1b53816aec1), + (0xbdfe5a5a5a5a5a5a, 0xc18aa4095d419351), + (0x3e7e0ca50d79435e, 0x41ef809305f11b9d), + (0xbedff8b720000000, 0xc2572e6809ed618b), + (0xbf64e5d8ae68b7a7, 0x42c4c5b6057839f9), + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[11]), + DoubleDouble::from_bit_pair(C[10]), + ); + + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[9])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[8])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[7])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[6])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[3].1)); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[1].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[0].1)); + + let z = DoubleDouble::quick_mult(p, recip); + + DoubleDouble::from_exact_add(z.hi, z.lo) +} + +// +/// See [bessel_1_asympt_alpha] for the info +pub(crate) fn bessel_1_asympt_alpha_hard(reciprocal: DyadicFloat128) -> DyadicFloat128 { + static C: [DyadicFloat128; 18] = [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xc0000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa8000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xbde66666_66666666_66666666_66666666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x97a436db_6db6db6d_b6db6db6_db6db6db_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -123, + mantissa: 0xf4fdfa00_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xa4cbdaac_a2e8ba2e_8ba2e8ba_2e8ba2e9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -113, + mantissa: 0xa548a0ca_934ec4ec_4ec4ec4e_c4ec4ec5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0xe68da9c0_b5760666_66666666_66666666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -102, + mantissa: 0xd5204aea_0c9a8879_69696969_69696969_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -96, + mantissa: 0xfc04982f_88dce9e0_ca50d794_35e50d79_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xb973404f_6b0c58ff_c5b90000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -82, + mantissa: 0xa62db02b_c1cfc563_44ea32e9_0b21642d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -75, + mantissa: 0xb220e7ff_443c1584_7e85f4e0_55eb851f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -68, + mantissa: 0xe10a255c_ca5e68cc_00c2d6c0_acdc8000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -60, + mantissa: 0xa573790c_5186f23b_5db502ea_d9fa5432_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -52, + mantissa: 0x8c0ffedc_407a7015_453df84e_9c3f1d39_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -44, + mantissa: 0x874226ed_c298a17a_d8c49a4e_dc9281a5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -36, + mantissa: 0x93cab36c_9ab9495c_310fa9cd_4b065359_u128, + }, + ]; + + let x2 = reciprocal * reciprocal; + + let mut p = C[17]; + for i in (0..17).rev() { + p = x2 * p + C[i]; + } + + p * reciprocal +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/bessel_exp.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/bessel_exp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/bessel_exp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/bessel_exp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,157 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1}; +use crate::rounding::CpuRound; + +#[inline(always)] +fn exp_poly(z: f64) -> DoubleDouble { + /* The following is a degree-4 polynomial generated by Sollya for exp(x) + over [-2^-12.905,2^-12.905] + with absolute error < 2^-74.34 (see sollya/Q_1.sollya). */ + const Q_1: [u64; 5] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555997996, + 0x3fa5555555849d8d, + ]; + let mut q = dd_fmla(f64::from_bits(Q_1[4]), z, f64::from_bits(Q_1[3])); + q = dd_fmla(q, z, f64::from_bits(Q_1[2])); + let h0 = dd_fmla(q, z, f64::from_bits(Q_1[1])); + + let v1 = DoubleDouble::from_exact_mult(z, h0); + DoubleDouble::f64_add(f64::from_bits(Q_1[0]), v1) +} + +#[inline] +pub(crate) fn i0_exp(r: f64) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r * INVLOG2).cpu_round(); + + const LOG_2E: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d0718432a1b0e26), + f64::from_bits(0x3f262e42ff000000), + ); + + let zh = f_fmla(LOG_2E.lo, k, f_fmla(-LOG_2E.hi, k, r)); + + let bk = unsafe { + k.to_int_unchecked::() // k is already integer, this is just a conversion + }; + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let mut de = DoubleDouble::quick_mult(t1, t0); + let q = exp_poly(zh); + de = DoubleDouble::quick_mult(de, q); + + let mut du = (mk as u64).wrapping_shl(52); + du = f64::from_bits(du).to_bits(); + DoubleDouble::quick_mult_f64(de, f64::from_bits(du)) +} + +#[inline(always)] +fn exp_poly_dd(z: DoubleDouble) -> DoubleDouble { + // Generated by Sollya: + // d = [-2^-12.905,2^-12.905]; + // f = exp(x); + // w = 1; + // p = remez(f, 6, d, w); + // pf = fpminimax(f, [|0,1,2,3,4,5,6|], [|1, 107...|], d, absolute, floating, 0, p); + // err_p = -log2(dirtyinfnorm(pf*w-f, d)); + // display = decimal; + const Q_1: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3a20e40000000000, 0x3ff0000000000000), + (0x3a04820000000000, 0x3fe0000000000000), + (0xbc756423c5338a66, 0x3fc5555555555556), + (0xbc5560f74db5556c, 0x3fa5555555555556), + (0x3c3648eca89bc6ac, 0x3f8111111144fbee), + (0xbbd53d924ae90c8c, 0x3f56c16c16ffeecc), + ]; + let mut p = DoubleDouble::quick_mul_add( + z, + DoubleDouble::from_bit_pair(Q_1[6]), + DoubleDouble::from_bit_pair(Q_1[5]), + ); + p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[4])); + p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[3])); + p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[2])); + p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[1])); + DoubleDouble::quick_mul_add_f64(z, p, f64::from_bits(0x3ff0000000000000)) +} + +#[cold] +pub(crate) fn i0_exp_accurate(r: f64) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r * INVLOG2).cpu_round(); + + const L2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d0718432a1b0e26), + f64::from_bits(0x3f262e42ff000000), + ); + const L2LL: f64 = f64::from_bits(0x3999ff0342542fc3); + let dx = f_fmla(-L2.hi, k, r); + let dx_dd = DoubleDouble::quick_mult_f64(DoubleDouble::new(L2LL, L2.lo), k); + let dz = DoubleDouble::full_add_f64(dx_dd, dx); + + let bk = unsafe { + k.to_int_unchecked::() // k is already integer, this is just a conversion + }; + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let mut de = DoubleDouble::quick_mult(t1, t0); + let q = exp_poly_dd(dz); + de = DoubleDouble::quick_mult(de, q); + + let mut du = (mk as u64).wrapping_shl(52); + du = f64::from_bits(du).to_bits(); + DoubleDouble::quick_mult_f64(de, f64::from_bits(du)) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_i0() { + assert_eq!(i0_exp(0.5).to_f64(), 1.6487212707001282); + assert_eq!(i0_exp_accurate(0.5).to_f64(), 1.6487212707001282); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/beta0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/beta0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,260 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval9; + +/** +Beta series + +Generated by SageMath: +```python +#generate b series +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +#see the series +print(b_series) +``` +**/ +#[inline] +pub(crate) fn bessel_0_asympt_beta(recip: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0xbfb0000000000000), + (0x0000000000000000, 0x3fba800000000000), + (0x0000000000000000, 0xbfe15f0000000000), + (0x0000000000000000, 0x4017651180000000), + (0x0000000000000000, 0xc05ab8c13b800000), + (0x0000000000000000, 0x40a730492f262000), + (0x0000000000000000, 0xc0fc73a7acd696f0), + (0xbdf3a00000000000, 0x41577458dd9fce68), + (0xbe4ba6b000000000, 0xc1b903ab9b27e18f), + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[9]), + DoubleDouble::from_bit_pair(C[8]), + ); + + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[7].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[6].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[5].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[4].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[3].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[2].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[1].1)); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[0].1)); + p +} + +/** +Beta series + +Generated by SageMath: +```python +#generate b series +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +#see the series +print(b_series) +``` +**/ +#[inline] +pub(crate) fn bessel_0_asympt_beta_fast(recip: DoubleDouble) -> DoubleDouble { + const C: [u64; 10] = [ + 0x3ff0000000000000, + 0xbfb0000000000000, + 0x3fba800000000000, + 0xbfe15f0000000000, + 0x4017651180000000, + 0xc05ab8c13b800000, + 0x40a730492f262000, + 0xc0fc73a7acd696f0, + 0x41577458dd9fce68, + 0xc1b903ab9b27e18f, + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let p = f_polyeval9( + x2.hi, + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + ); + + DoubleDouble::mul_f64_add_f64(x2, p, f64::from_bits(C[0])) +} + +/// see [bessel_0_asympt_beta] for more info +pub(crate) fn bessel_0_asympt_beta_hard(recip: DyadicFloat128) -> DyadicFloat128 { + static C: [DyadicFloat128; 12] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xd4000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8af80000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -125, + mantissa: 0xbb288c00_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -121, + mantissa: 0xd5c609dc_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0xb9824979_31000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -111, + mantissa: 0xe39d3d66_b4b78000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -105, + mantissa: 0xbba2c6ec_fe733d8c_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -99, + mantissa: 0xc81d5cd9_3f0c79ba_6b000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -92, + mantissa: 0x86118ddf_c1ffc100_0ee1b000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xdc7ccfa9_930b874d_52df3464_00000000_u128, + }, + ]; + + let x2 = recip * recip; + + let mut p = C[11]; + for i in (0..11).rev() { + p = x2 * p + C[i]; + } + p +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/beta1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/beta1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/beta1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,264 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval9; + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +# see the beta series +print(b_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn bessel_1_asympt_beta_fast(recip: DoubleDouble) -> DoubleDouble { + const C: [u64; 10] = [ + 0x3ff0000000000000, + 0x3fc8000000000000, + 0xbfc8c00000000000, + 0x3fe9c50000000000, + 0xc01ef5b680000000, + 0x40609860dd400000, + 0xc0abae9b7a06e000, + 0x41008711d41c1428, + 0xc15ab70164c8be6e, + 0x41bc1055e24f297f, + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let p = f_polyeval9( + x2.hi, + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + ); + + DoubleDouble::mul_f64_add_f64(x2, p, f64::from_bits(C[0])) +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +# see the beta series +print(b_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn bessel_1_asympt_beta(recip: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), // 1 + (0x0000000000000000, 0x3fc8000000000000), // 2 + (0x0000000000000000, 0xbfc8c00000000000), // 3 + (0x0000000000000000, 0x3fe9c50000000000), // 4 + (0x0000000000000000, 0xc01ef5b680000000), // 5 + (0x0000000000000000, 0x40609860dd400000), // 6 + (0x0000000000000000, 0xc0abae9b7a06e000), // 7 + (0x0000000000000000, 0x41008711d41c1428), // 8 + (0xbdf7a00000000000, 0xc15ab70164c8be6e), + (0xbe40e1f000000000, 0x41bc1055e24f297f), + ]; + + // Doing (1/x)*(1/x) instead (1/(x*x)) to avoid spurious overflow/underflow + let x2 = DoubleDouble::quick_mult(recip, recip); + + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[9]), + DoubleDouble::from_bit_pair(C[8]), + ); + + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[7].1)); // 8 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[6].1)); // 7 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[5].1)); // 6 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[4].1)); // 5 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[3].1)); // 4 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[2].1)); // 3 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[1].1)); // 2 + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(C[0].1)); // 1 + p +} + +/// see [bessel_1_asympt_beta] for more info +pub(crate) fn bessel_1_asympt_beta_hard(recip: DyadicFloat128) -> DyadicFloat128 { + static C: [DyadicFloat128; 12] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc0000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xc6000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xce280000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -125, + mantissa: 0xf7adb400_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0x84c306ea_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -116, + mantissa: 0xdd74dbd0_37000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x84388ea0_e0a14000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -105, + mantissa: 0xd5b80b26_45f372f4_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0xe082af12_794bf6f1_e1000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -92, + mantissa: 0x94a06149_f30146bc_fe8ed000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -86, + mantissa: 0xf212edfc_42a62526_4fac2b0c_00000000_u128, + }, + ]; + + let x2 = recip * recip; + + let mut p = C[11]; + for i in (0..11).rev() { + p = x2 * p + C[i]; + } + p +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1118 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::bessel_exp::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::rational128_exp; +use crate::polyeval::{f_estrin_polyeval5, f_polyeval4}; + +/// Modified Bessel of the first kind of order 0 +/// +/// Max ULP 0.5 +pub fn f_i0(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x760af31dc4611874u64 { + // |x| <= 2.2204460492503131e-24 + return 1.; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // Power series of I0(x) ~ 1 + x^2/4 + O(x^4) + let half_x = x * 0.5; + return f_fmla(half_x, half_x, 1.); + } + if x.is_infinite() { + return f64::INFINITY; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if xb > 0x40864fe5304e83e4u64 { + // |x| > 713.9869085439682 + return f64::INFINITY; + } + + if xb <= 0x4023000000000000u64 { + // |x| <= 9.5 + if xb <= 0x400ccccccccccccdu64 { + // |x| <= 3.6 + return i0_0_to_3p6_exec(f64::from_bits(xb)); + } else if xb <= 0x401e000000000000u64 { + // |x| <= 7.5 + return i3p6_to_7p5(f64::from_bits(xb)); + } + return i0_7p5_to_9p5(f64::from_bits(xb)); + } + + i0_asympt(f64::from_bits(xb)) +} + +/** +Computes I0 on interval [-7.5; -3.6], [3.6; 7.5] +**/ +#[inline] +fn i3p6_to_7p5(x: f64) -> f64 { + let r = i0_3p6_to_7p5_dd(x); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c56a09e667f3bcd), // 2^-57.5 + f64::from_bits(0x3c00000000000000), // 2^-63 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub != lb { + return eval_small_hard_3p6_to_7p5(x).to_f64(); + } + r.to_f64() +} + +/** +Computes I0 on interval [-7.5; -3.6], [3.6; 7.5] +as rational approximation I0 = 1 + (x/2)^2 * Pn((x/2)^2)/Qm((x/2)^2)) + +Relative error on interval 2^-(105.71). + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn i0_0_to_3p6_dd(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + const P: [(u64, u64); 8] = [ + (0xba93dec1e5396e30, 0x3ff0000000000000), + (0xbc5d3d919a2b891a, 0x3fcb128f49a1f59f), + (0xbc3c4d80de165459, 0x3f9353508fce278f), + (0x3be7e0e75c00d411, 0x3f4b760657892e15), + (0xbb9bc959d02076a4, 0x3ef588ff0ba5872e), + (0x3b257756675180e4, 0x3e932e320d411521), + (0xbaca098436a47ec6, 0x3e2285f524a51de0), + (0x3a0e48fa0331db75, 0x3d9ee6518d82a209), + ]; + let ps_num = f_estrin_polyeval5( + eval_x.hi, + f64::from_bits(0x3f4b760657892e15), + f64::from_bits(0x3ef588ff0ba5872e), + f64::from_bits(0x3e932e320d411521), + f64::from_bits(0x3e2285f524a51de0), + f64::from_bits(0x3d9ee6518d82a209), + ); + let mut p_num = DoubleDouble::mul_f64_add(eval_x, ps_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + const Q: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c26136ec7050a58, 0xbfa3b5c2d9782985), + (0x3bdf9cd5be66297b, 0x3f478d5c030ea692), + (0xbb5036196d4b865c, 0xbee1a83b6e8c6fd6), + (0xbb1a9dafadc75858, 0x3e71ba443893032b), + (0xba7a719ba9ed7e7f, 0xbdf6e673af3e0c66), + (0xb9e17740b37a23ec, 0x3d6e2c993fef696f), + ]; + let ps_den = f_polyeval4( + eval_x.hi, + f64::from_bits(0xbee1a83b6e8c6fd6), + f64::from_bits(0x3e71ba443893032b), + f64::from_bits(0xbdf6e673af3e0c66), + f64::from_bits(0x3d6e2c993fef696f), + ); + let mut p_den = DoubleDouble::mul_f64_add(eval_x, ps_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(eval_x, p_den, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::mul_add_f64(DoubleDouble::div(p_num, p_den), eval_x, 1.) +} + +// Generated by Wolfram Mathematica: +// I0(x) = 1+(x/2)^2 * R((x/2)^2) +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +pub(crate) fn i0_3p6_to_7p5_dd(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + const P: [(u64, u64); 10] = [ + (0xbae8195e94c833a1, 0x3ff0000000000000), + (0xbc6f4db3a04cf778, 0x3fcbca374cf8efde), + (0x3c31e334a32ed081, 0x3f9493391f88f49c), + (0x3bb77456438b622e, 0x3f4f2aff2cd821b7), + (0x3b312b847b83fa80, 0x3efb249e459c00fa), + (0x3b1d3faf77d3ee5b, 0x3e9cd199c39f6d6c), + (0xbaaf6a6a3d483df8, 0x3e331192e34cb81f), + (0x3a406e234cb7aede, 0x3dbef6023ba17d1a), + (0x39dee1ec666e30b5, 0x3d3c8bab78d825e9), + (0x3910b9821c993936, 0x3ca73bf438398234), + ]; + let ps_num = f_estrin_polyeval5( + eval_x.hi, + f64::from_bits(0x3e9cd199c39f6d6c), + f64::from_bits(0x3e331192e34cb81f), + f64::from_bits(0x3dbef6023ba17d1a), + f64::from_bits(0x3d3c8bab78d825e9), + f64::from_bits(0x3ca73bf438398234), + ); + let mut p_num = DoubleDouble::mul_f64_add(eval_x, ps_num, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c16498103ae0f29, 0xbfa0d722cc1c408a), + (0x3ba9b44df49b7368, 0x3f41a06d24a9b89a), + (0x3b43ef4989b8a3ed, 0xbed8363c48ecd98c), + (0xbaf6197838a8a2ef, 0x3e6830647038f0ac), + (0x3a96c443c7d52296, 0xbdf257666a799e31), + (0x3a118e8a97f0df20, 0x3d753ffeb530f0c8), + (0xb99e90b659ab1bb7, 0xbcf243374f2b7d6c), + (0x38f647cfef513fc5, 0x3c654740fd120da3), + (0x386d691099d0e8fc, 0xbbc9c9c826756a76), + ]; + let ps_den = f_estrin_polyeval5( + eval_x.hi, + f64::from_bits(0xbdf257666a799e31), + f64::from_bits(0x3d753ffeb530f0c8), + f64::from_bits(0xbcf243374f2b7d6c), + f64::from_bits(0x3c654740fd120da3), + f64::from_bits(0xbbc9c9c826756a76), + ); + let mut p_den = DoubleDouble::mul_f64_add(eval_x, ps_den, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(eval_x, p_den, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::mul_add_f64(DoubleDouble::div(p_num, p_den), eval_x, 1.) +} + +// Generated by Wolfram Mathematica: +// I0(x) = 1+(x/2)^2 * R((x/2)^2) +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[cold] +#[inline(never)] +pub(crate) fn eval_small_hard_3p6_to_7p5(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + const P: [(u64, u64); 10] = [ + (0xbae8195e94c833a1, 0x3ff0000000000000), + (0xbc6f4db3a04cf778, 0x3fcbca374cf8efde), + (0x3c31e334a32ed081, 0x3f9493391f88f49c), + (0x3bb77456438b622e, 0x3f4f2aff2cd821b7), + (0x3b312b847b83fa80, 0x3efb249e459c00fa), + (0x3b1d3faf77d3ee5b, 0x3e9cd199c39f6d6c), + (0xbaaf6a6a3d483df8, 0x3e331192e34cb81f), + (0x3a406e234cb7aede, 0x3dbef6023ba17d1a), + (0x39dee1ec666e30b5, 0x3d3c8bab78d825e9), + (0x3910b9821c993936, 0x3ca73bf438398234), + ]; + let mut p_num = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[7])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c16498103ae0f29, 0xbfa0d722cc1c408a), + (0x3ba9b44df49b7368, 0x3f41a06d24a9b89a), + (0x3b43ef4989b8a3ed, 0xbed8363c48ecd98c), + (0xbaf6197838a8a2ef, 0x3e6830647038f0ac), + (0x3a96c443c7d52296, 0xbdf257666a799e31), + (0x3a118e8a97f0df20, 0x3d753ffeb530f0c8), + (0xb99e90b659ab1bb7, 0xbcf243374f2b7d6c), + (0x38f647cfef513fc5, 0x3c654740fd120da3), + (0x386d691099d0e8fc, 0xbbc9c9c826756a76), + ]; + let mut p_den = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[7])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(eval_x, p_den, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::mul_add_f64(DoubleDouble::div(p_num, p_den), eval_x, 1.) +} + +#[inline] +pub(crate) fn i0_0_to_3p6_exec(x: f64) -> f64 { + let r = i0_0_to_3p6_dd(x); + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3be0000000000000), // 2^-66 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r.to_f64(); + } + i0_0_to_3p6_hard(x).to_f64() +} + +// Generated by Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[cold] +#[inline(never)] +pub(crate) fn i0_0_to_3p6_hard(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + const P: [(u64, u64); 8] = [ + (0xba93dec1e5396e30, 0x3ff0000000000000), + (0xbc5d3d919a2b891a, 0x3fcb128f49a1f59f), + (0xbc3c4d80de165459, 0x3f9353508fce278f), + (0x3be7e0e75c00d411, 0x3f4b760657892e15), + (0xbb9bc959d02076a4, 0x3ef588ff0ba5872e), + (0x3b257756675180e4, 0x3e932e320d411521), + (0xbaca098436a47ec6, 0x3e2285f524a51de0), + (0x3a0e48fa0331db75, 0x3d9ee6518d82a209), + ]; + let mut p_num = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + const Q: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c26136ec7050a58, 0xbfa3b5c2d9782985), + (0x3bdf9cd5be66297b, 0x3f478d5c030ea692), + (0xbb5036196d4b865c, 0xbee1a83b6e8c6fd6), + (0xbb1a9dafadc75858, 0x3e71ba443893032b), + (0xba7a719ba9ed7e7f, 0xbdf6e673af3e0c66), + (0xb9e17740b37a23ec, 0x3d6e2c993fef696f), + ]; + let mut p_den = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(Q[6]), + DoubleDouble::from_bit_pair(Q[5]), + ); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[0])); + DoubleDouble::mul_add_f64(DoubleDouble::div(p_num, p_den), eval_x, 1.) +} + +/** +Mid-interval [7.5;9.5] generated by Wolfram: +I0(x)=R(1/x)/sqrt(x)*Exp(x) +```text +<120] +num=Numerator[approx][[1]]; +den=Denominator[approx][[1]]; +poly=den; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0_7p5_to_9p5(x: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + + const P: [(u64, u64); 12] = [ + (0x3c778e3de1f76f48, 0x3fd988450531281b), + (0xbcb572f6149f389e, 0xc01a786676fb4d3a), + (0x3cf2f373365347ed, 0x405c0e8405fdb642), + (0x3d276a94c8f1e627, 0xc0885e4718dfb761), + (0x3d569f8a993434e2, 0x40b756d52d5fa90c), + (0xbd6f953f7dd1a223, 0xc0c8818365c47790), + (0xbd74247967fbf7b2, 0x40e8cf89daf87353), + (0x3db449add7abb056, 0x41145d3c2d96d159), + (0xbdc5cc822b71f891, 0xc123694c58fd039b), + (0x3da2047ac1a6fba8, 0x415462e630bf3e7e), + (0xbdc2f2c06eda6a95, 0xc14c6984ebdd6792), + (0xbdf51fa85dafeca5, 0x4166a437c202d27b), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cde08e4cbf324d1, 0xc030b67bd69af0ca), + (0x3cec5e4ee7e77024, 0x4071b54c0f58409c), + (0xbd340e1131739e2f, 0xc09f140a738b14b3), + (0x3d607673189d6644, 0x40cdb44bd822add2), + (0xbd7793a4f1dd74d1, 0xc0e03fe2689b802d), + (0xbd8415501228a87e, 0x410009beafea72cc), + (0x3dcecdac2702661f, 0x4128c2073da9a447), + (0xbdd8386404f3dec5, 0xc1389ec7d7186bf4), + (0xbe06eb53a3e86436, 0x4168b7a2dc85ed0b), + (0x3e098e2cefaf8299, 0xc1604f8cf34af02c), + (0x3e1a5e496b547001, 0x41776b1e0153d1e9), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let e = i0_exp(dx); + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + let r = DoubleDouble::quick_mult(z * r_sqrt, e); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3bc0000000000000), + f64::from_bits(0x392bdb8cdadbe111), + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up != lb { + return i0_7p5_to_9p5_hard(x); + } + r.to_f64() +} + +/** +Mid-interval [7.5;9.5] generated by Wolfram Mathematica: +I0(x)=R(1/x)/sqrt(x)*Exp(x) +Polynomial generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i0_7p5_to_9p5_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 14] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc422a04_45cde144_75a3800b_45c38460_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -124, + mantissa: 0xada66144_fcccc1a3_036f76b2_cabd6281_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0xeabdda02_fa201d98_10e58d1f_7eb62bd7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -116, + mantissa: 0xbbfd3297_6f88a7df_5924587b_d5bdcdb8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xfca29453_efe393bf_1651627b_7d543875_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -110, + mantissa: 0xee7c7220_bbbd248e_bb6adac6_f9a5ce95_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -107, + mantissa: 0xc07455dd_830ba705_414408c6_06732a5a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -105, + mantissa: 0xe2247793_b50cd0f0_80e8981d_933f75da_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -103, + mantissa: 0xe14a9831_82582a0b_dd27e8b6_4ed9aac2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -101, + mantissa: 0xa3b2ae2f_5b64f37e_c1538435_34f02faf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -100, + mantissa: 0xbab73503_5b7e38d9_bbe4a84b_9007c6e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -99, + mantissa: 0xa68911fc_5d87bbe7_0d4fe854_5c681ac5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0x9e997222_55ef4045_fa9f311d_57d082a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -99, + mantissa: 0xbe93656a_b0a4f32d_3ebbfdeb_b1cbb839_u128, + }, + ]; + static Q: [DyadicFloat128; 14] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -123, + mantissa: 0xdaa34a7e_861dddff_a0642080_cd83dd65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0x93f05740_f4758772_bb9992f9_91e72795_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -115, + mantissa: 0xeddcb810_054c9aab_fa7e4214_d59d18b0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xa0180fcd_831ff6c0_ac2b8f02_37f3cfd1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -108, + mantissa: 0x97d25106_3b66907e_90b4f786_26daa0bb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -106, + mantissa: 0xf595ce38_aac16c11_001b874a_99603b45_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -103, + mantissa: 0x912b3715_4aca68f6_5821c2ed_43d77111_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -101, + mantissa: 0x90f97141_b896e2b6_38b87354_8945a43c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -100, + mantissa: 0xd3e5f967_89097d6b_3a3060fe_852ff580_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0xf0d6de35_939da009_9ced21fd_48af7281_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0xd2a0b183_6ac613b2_6745ce1d_8ed1c323_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -98, + mantissa: 0xbb9c089a_b7e939a2_732b3fb5_2e66cd77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0xcb2107c3_736bef81_609718c0_ba82cd8e_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[13]; + for i in (0..13).rev() { + p_num = recip * p_num + P[i]; + } + let mut p_den = Q[13]; + for i in (0..13).rev() { + p_den = recip * p_den + Q[i]; + } + let z = p_num * p_den.reciprocal(); + + let r_sqrt = bessel_rsqrt_hard(x, recip); + let f_exp = rational128_exp(x); + (z * r_sqrt * f_exp).fast_as_f64() +} + +/** +I0(x)=R(1/x)*Exp(x)/sqrt(x) +Generated in Wolfram: +```text +<120] +poly=Numerator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]] +``` +**/ +#[inline] +fn i0_asympt(x: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + const P: [(u64, u64); 12] = [ + (0xbc7ca19c5d824c54, 0x3fd9884533d43651), + (0x3cca32eb734e010e, 0xc03b7ca35caf42eb), + (0x3d03af8238d6f25e, 0x408b92cfcaa7070f), + (0xbd7a8ff7fdebed70, 0xc0d0a3be432cce93), + (0xbdababdb579bb076, 0x410a77dc51f1804d), + (0x3dc5e4e3c972832a, 0xc13cb0be2f74839c), + (0x3e01076f9b102e38, 0x41653b064cc61661), + (0xbe2157e700d445f4, 0xc184e1b076927460), + (0xbdfa4577156dde56, 0x41999e9653f9dc5f), + (0xbe47aa238a739ffe, 0xc1a130f6ded40c00), + (0xbe331b560b6fbf4a, 0x419317f11e674cae), + (0xbe0765596077d1e3, 0xc16024404db59d3f), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcf687703e843d07, 0xc051418f1c4dd0b9), + (0x3d468ab92cb87a0b, 0x40a15891d823e48d), + (0x3d8bfc17e5183376, 0xc0e4fce40dd82796), + (0xbdccbbcc2ecf8d4c, 0x4120beef869c61ec), + (0xbdf42170b4d5d150, 0xc1523ad18834a7ed), + (0xbe0eaa32f405afd4, 0x417b24ec57a8f480), + (0x3e3ec900705e7252, 0xc19af2a91d23d62e), + (0x3e3e220e274fa46b, 0x41b0cb905cc99ff5), + (0xbe46c6c61dee11f6, 0xc1b7452e50518520), + (0x3e3ed0fc063187bf, 0x41ac1772d1749896), + (0xbe11c578f04f4be1, 0xc180feb5b2ca47cb), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let mut e = i0_exp(dx * 0.5); + e = DoubleDouble::from_exact_add(e.hi, e.lo); + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + let r = DoubleDouble::quick_mult(z * r_sqrt * e, e); + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up != lb { + return i0_asympt_hard(x); + } + lb +} + +#[inline] +pub(crate) fn bessel_rsqrt_hard(x: f64, recip: DyadicFloat128) -> DyadicFloat128 { + let r = DyadicFloat128::new_from_f64(x.sqrt()) * recip; + let fx = DyadicFloat128::new_from_f64(x); + let rx = r * fx; + let drx = r * fx - rx; + const M_ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let h = r * rx + M_ONE + r * drx; + let mut ddr = r; + ddr.exponent -= 1; // ddr * 0.5 + let dr = ddr * h; + r - dr +} + +/** +I0(x)=R(1/x)*Exp(x)/sqrt(x) +Generated in Wolfram: +```text +<120] +poly=Numerator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i0_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc42299e_a1b28468_7e5aad4a_70b749c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -122, + mantissa: 0xabb4209d_ca11bdaa_186bef7f_390e6b77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0x8a2725e2_4749db25_625ad1f2_12a2a16c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -111, + mantissa: 0x8b4c2cd4_9e5d0c8b_c9be4d3e_781bb676_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -107, + mantissa: 0xc33fad7c_40599f7d_713e3081_6b5ad791_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -103, + mantissa: 0xc81da271_b623ba88_0be032b5_827d92fa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0x99ec4975_b6aa7cae_7692a287_ed8ae47c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -96, + mantissa: 0xb3aa4745_fc2dd441_2dbd3e3c_d4539687_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -93, + mantissa: 0x9f14edc2_6882afca_29d2a067_dc459729_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -91, + mantissa: 0xd35c4d01_78d8cec6_fc8ae0ee_834da837_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xcdc529c7_6e082342_faad3073_07a9b61f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -87, + mantissa: 0x8ccac88f_2598c8a6_423b1f42_63591cb9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0xfc044cfb_a20f0885_93d58660_17819ed5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0x813a700c_74d23f52_f81b179d_7ff0da9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -88, + mantissa: 0xe6c43da4_297216bf_bdd987cb_636906cf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -91, + mantissa: 0xa4998323_649c3cf2_64477869_3d2c6afd_u128, + }, + ]; + static Q: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -121, + mantissa: 0xd772d5fd_a7077638_6e007274_d83b013c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xad914ef0_451ced2e_515657ef_fc7eeb53_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -110, + mantissa: 0xaf41180c_dffe96e5_f192fa40_0b1bff1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -106, + mantissa: 0xf60dc728_241f71fd_5b93e653_ccbedace_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -102, + mantissa: 0xfcaefef9_39cf96e7_3cb75a98_da5e9761_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -98, + mantissa: 0xc2d2c837_5789587a_13ef38c6_a24c3413_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -95, + mantissa: 0xe41725c3_51d14486_a650044e_e8588f7b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -92, + mantissa: 0xcabeed9b_5e2e888d_81d32b11_d289a624_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0x8764876d_11ad6607_8a8d5382_3ffe82d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0x84c9f9e5_6a5f5034_ad2c8512_16cb1ba1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xb7c1d143_a15d8aab_03a7fa3e_b7d07a36_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -85, + mantissa: 0xa78f8257_4658040f_7a1ad39c_91ea9483_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0xb231e0ca_b729a404_44c38f52_be208507_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -86, + mantissa: 0xae317981_42349081_8bc68b28_f69b8e49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xb451abd3_5cd79c6d_7e578164_32f16da1_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[15]; + for i in (0..15).rev() { + p_num = recip * p_num + P[i]; + } + + let mut p_den = Q[15]; + for i in (0..15).rev() { + p_den = recip * p_den + Q[i]; + } + + let z = p_num * p_den.reciprocal(); + + let r_sqrt = bessel_rsqrt_hard(x, recip); + let f_exp = rational128_exp(x); + (z * r_sqrt * f_exp).fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i0() { + assert_eq!(f_i0(2.2204460492503131e-24f64), 1.0); + assert_eq!(f_i0(f64::EPSILON), 1.0); + assert_eq!(f_i0(9.500000000005492,), 1753.4809905364318); + assert!(f_i0(f64::NAN).is_nan()); + assert_eq!(f_i0(f64::INFINITY), f64::INFINITY); + assert_eq!(f_i0(f64::NEG_INFINITY), f64::INFINITY); + assert_eq!(f_i0(7.500000000788034), 268.1613117118702); + assert_eq!(f_i0(715.), f64::INFINITY); + assert_eq!(f_i0(12.), 18948.925349296307); + assert_eq!(f_i0(16.), 893446.227920105); + assert_eq!(f_i0(18.432), 9463892.87209841); + assert_eq!(f_i0(26.432), 23507752424.350075); + assert_eq!(f_i0(0.2), 1.010025027795146); + assert_eq!(f_i0(7.5), 268.16131151518937); + assert_eq!(f_i0(-1.5), 1.646723189772891); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0e.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0e.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0e.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0e.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,834 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::bessel_exp::i0_exp_accurate; +use crate::bessel::i0::{ + bessel_rsqrt_hard, eval_small_hard_3p6_to_7p5, i0_0_to_3p6_dd, i0_0_to_3p6_hard, + i0_3p6_to_7p5_dd, +}; +use crate::bessel::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +/// Modified exponentially scaled Bessel of the first kind of order 0 +/// +/// Computes exp(-|x|)*I0(x) +pub fn f_i0e(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x760af31dc4611874u64 { + // |x| <= 2.2204460492503131e-24f64 + return 1.; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // Power series of I0(x)Exp[-x] ~ 1 - x + O(x^2) + return 1. - x; + } + if x.is_infinite() { + return 0.; + } + return x + f64::NAN; // x = NaN + } + + let xb = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if xb <= 0x4023000000000000u64 { + // |x| <= 9.5 + if xb <= 0x400ccccccccccccdu64 { + // |x| <= 3.6 + return i0e_0_to_3p6_exec(f64::from_bits(xb)); + } else if xb <= 0x401e000000000000u64 { + // |x| <= 7.5 + return i0e3p6_to_7p5(f64::from_bits(xb)); + } + return i0e_7p5_to_9p5(f64::from_bits(xb)); + } + + i0e_asympt(f64::from_bits(xb)) +} + +/** +Computes I0 on interval [-7.5; -3.6], [3.6; 7.5] +**/ +#[inline] +fn i0e3p6_to_7p5(x: f64) -> f64 { + let mut r = i0_3p6_to_7p5_dd(x); + + let v_exp = i0_exp(-x); + r = DoubleDouble::quick_mult(r, v_exp); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c56a09e667f3bcd), // 2^-57.5 + f64::from_bits(0x3c00000000000000), // 2^-63 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return ub; + } + let v = eval_small_hard_3p6_to_7p5(x); + let v_exp_accurate = i0_exp_accurate(-x); + DoubleDouble::quick_mult(v, v_exp_accurate).to_f64() +} + +#[inline] +fn i0e_0_to_3p6_exec(x: f64) -> f64 { + let mut r = i0_0_to_3p6_dd(x); + + let v_exp = i0_exp(-x); + r = DoubleDouble::quick_mult(r, v_exp); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3be0000000000000), // 2^-66 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return ub; + } + let v = i0_0_to_3p6_hard(x); + let v_exp_accurate = i0_exp_accurate(-x); + DoubleDouble::quick_mult(v, v_exp_accurate).to_f64() +} + +/** +Mid-interval [7.5;9.5] generated by Wolfram: +I0(x)=R(1/x)/sqrt(x)*Exp(x) +```text +<120] +num=Numerator[approx][[1]]; +den=Denominator[approx][[1]]; +poly=den; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0e_7p5_to_9p5(x: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + + const P: [(u64, u64); 12] = [ + (0x3c778e3de1f76f48, 0x3fd988450531281b), + (0xbcb572f6149f389e, 0xc01a786676fb4d3a), + (0x3cf2f373365347ed, 0x405c0e8405fdb642), + (0x3d276a94c8f1e627, 0xc0885e4718dfb761), + (0x3d569f8a993434e2, 0x40b756d52d5fa90c), + (0xbd6f953f7dd1a223, 0xc0c8818365c47790), + (0xbd74247967fbf7b2, 0x40e8cf89daf87353), + (0x3db449add7abb056, 0x41145d3c2d96d159), + (0xbdc5cc822b71f891, 0xc123694c58fd039b), + (0x3da2047ac1a6fba8, 0x415462e630bf3e7e), + (0xbdc2f2c06eda6a95, 0xc14c6984ebdd6792), + (0xbdf51fa85dafeca5, 0x4166a437c202d27b), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cde08e4cbf324d1, 0xc030b67bd69af0ca), + (0x3cec5e4ee7e77024, 0x4071b54c0f58409c), + (0xbd340e1131739e2f, 0xc09f140a738b14b3), + (0x3d607673189d6644, 0x40cdb44bd822add2), + (0xbd7793a4f1dd74d1, 0xc0e03fe2689b802d), + (0xbd8415501228a87e, 0x410009beafea72cc), + (0x3dcecdac2702661f, 0x4128c2073da9a447), + (0xbdd8386404f3dec5, 0xc1389ec7d7186bf4), + (0xbe06eb53a3e86436, 0x4168b7a2dc85ed0b), + (0x3e098e2cefaf8299, 0xc1604f8cf34af02c), + (0x3e1a5e496b547001, 0x41776b1e0153d1e9), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + let r = z * r_sqrt; + + let err = f_fmla( + r.hi, + f64::from_bits(0x3bc0000000000000), + f64::from_bits(0x392bdb8cdadbe111), + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up != lb { + return i0e_7p5_to_9p5_hard(x); + } + r.to_f64() +} + +/** +Mid-interval [7.5;9.5] generated by Wolfram Mathematica: +I0(x)=R(1/x)/sqrt(x)*Exp(x) +Polynomial generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i0e_7p5_to_9p5_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 14] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc422a04_45cde144_75a3800b_45c38460_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -124, + mantissa: 0xada66144_fcccc1a3_036f76b2_cabd6281_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0xeabdda02_fa201d98_10e58d1f_7eb62bd7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -116, + mantissa: 0xbbfd3297_6f88a7df_5924587b_d5bdcdb8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xfca29453_efe393bf_1651627b_7d543875_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -110, + mantissa: 0xee7c7220_bbbd248e_bb6adac6_f9a5ce95_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -107, + mantissa: 0xc07455dd_830ba705_414408c6_06732a5a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -105, + mantissa: 0xe2247793_b50cd0f0_80e8981d_933f75da_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -103, + mantissa: 0xe14a9831_82582a0b_dd27e8b6_4ed9aac2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -101, + mantissa: 0xa3b2ae2f_5b64f37e_c1538435_34f02faf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -100, + mantissa: 0xbab73503_5b7e38d9_bbe4a84b_9007c6e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -99, + mantissa: 0xa68911fc_5d87bbe7_0d4fe854_5c681ac5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0x9e997222_55ef4045_fa9f311d_57d082a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -99, + mantissa: 0xbe93656a_b0a4f32d_3ebbfdeb_b1cbb839_u128, + }, + ]; + static Q: [DyadicFloat128; 14] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -123, + mantissa: 0xdaa34a7e_861dddff_a0642080_cd83dd65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0x93f05740_f4758772_bb9992f9_91e72795_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -115, + mantissa: 0xeddcb810_054c9aab_fa7e4214_d59d18b0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xa0180fcd_831ff6c0_ac2b8f02_37f3cfd1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -108, + mantissa: 0x97d25106_3b66907e_90b4f786_26daa0bb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -106, + mantissa: 0xf595ce38_aac16c11_001b874a_99603b45_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -103, + mantissa: 0x912b3715_4aca68f6_5821c2ed_43d77111_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -101, + mantissa: 0x90f97141_b896e2b6_38b87354_8945a43c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -100, + mantissa: 0xd3e5f967_89097d6b_3a3060fe_852ff580_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0xf0d6de35_939da009_9ced21fd_48af7281_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0xd2a0b183_6ac613b2_6745ce1d_8ed1c323_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -98, + mantissa: 0xbb9c089a_b7e939a2_732b3fb5_2e66cd77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0xcb2107c3_736bef81_609718c0_ba82cd8e_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[13]; + for i in (0..13).rev() { + p_num = recip * p_num + P[i]; + } + let mut p_den = Q[13]; + for i in (0..13).rev() { + p_den = recip * p_den + Q[i]; + } + let z = p_num * p_den.reciprocal(); + + let r_sqrt = bessel_rsqrt_hard(x, recip); + (z * r_sqrt).fast_as_f64() +} + +/** +I0(x)=R(1/x)*Exp(x)/sqrt(x) +Generated in Wolfram: +```text +<120] +poly=Numerator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]] +``` +**/ +#[inline] +fn i0e_asympt(x: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + const P: [(u64, u64); 12] = [ + (0xbc7ca19c5d824c54, 0x3fd9884533d43651), + (0x3cca32eb734e010e, 0xc03b7ca35caf42eb), + (0x3d03af8238d6f25e, 0x408b92cfcaa7070f), + (0xbd7a8ff7fdebed70, 0xc0d0a3be432cce93), + (0xbdababdb579bb076, 0x410a77dc51f1804d), + (0x3dc5e4e3c972832a, 0xc13cb0be2f74839c), + (0x3e01076f9b102e38, 0x41653b064cc61661), + (0xbe2157e700d445f4, 0xc184e1b076927460), + (0xbdfa4577156dde56, 0x41999e9653f9dc5f), + (0xbe47aa238a739ffe, 0xc1a130f6ded40c00), + (0xbe331b560b6fbf4a, 0x419317f11e674cae), + (0xbe0765596077d1e3, 0xc16024404db59d3f), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcf687703e843d07, 0xc051418f1c4dd0b9), + (0x3d468ab92cb87a0b, 0x40a15891d823e48d), + (0x3d8bfc17e5183376, 0xc0e4fce40dd82796), + (0xbdccbbcc2ecf8d4c, 0x4120beef869c61ec), + (0xbdf42170b4d5d150, 0xc1523ad18834a7ed), + (0xbe0eaa32f405afd4, 0x417b24ec57a8f480), + (0x3e3ec900705e7252, 0xc19af2a91d23d62e), + (0x3e3e220e274fa46b, 0x41b0cb905cc99ff5), + (0xbe46c6c61dee11f6, 0xc1b7452e50518520), + (0x3e3ed0fc063187bf, 0x41ac1772d1749896), + (0xbe11c578f04f4be1, 0xc180feb5b2ca47cb), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + let r = z * r_sqrt; + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up != lb { + return i0e_asympt_hard(x); + } + lb +} + +/** +I0(x)=R(1/x)*Exp(x)/sqrt(x) +Generated in Wolfram: +```text +<120] +poly=Numerator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i0e_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc42299e_a1b28468_7e5aad4a_70b749c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -122, + mantissa: 0xabb4209d_ca11bdaa_186bef7f_390e6b77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0x8a2725e2_4749db25_625ad1f2_12a2a16c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -111, + mantissa: 0x8b4c2cd4_9e5d0c8b_c9be4d3e_781bb676_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -107, + mantissa: 0xc33fad7c_40599f7d_713e3081_6b5ad791_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -103, + mantissa: 0xc81da271_b623ba88_0be032b5_827d92fa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -99, + mantissa: 0x99ec4975_b6aa7cae_7692a287_ed8ae47c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -96, + mantissa: 0xb3aa4745_fc2dd441_2dbd3e3c_d4539687_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -93, + mantissa: 0x9f14edc2_6882afca_29d2a067_dc459729_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -91, + mantissa: 0xd35c4d01_78d8cec6_fc8ae0ee_834da837_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xcdc529c7_6e082342_faad3073_07a9b61f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -87, + mantissa: 0x8ccac88f_2598c8a6_423b1f42_63591cb9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0xfc044cfb_a20f0885_93d58660_17819ed5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0x813a700c_74d23f52_f81b179d_7ff0da9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -88, + mantissa: 0xe6c43da4_297216bf_bdd987cb_636906cf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -91, + mantissa: 0xa4998323_649c3cf2_64477869_3d2c6afd_u128, + }, + ]; + static Q: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -121, + mantissa: 0xd772d5fd_a7077638_6e007274_d83b013c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xad914ef0_451ced2e_515657ef_fc7eeb53_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -110, + mantissa: 0xaf41180c_dffe96e5_f192fa40_0b1bff1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -106, + mantissa: 0xf60dc728_241f71fd_5b93e653_ccbedace_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -102, + mantissa: 0xfcaefef9_39cf96e7_3cb75a98_da5e9761_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -98, + mantissa: 0xc2d2c837_5789587a_13ef38c6_a24c3413_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -95, + mantissa: 0xe41725c3_51d14486_a650044e_e8588f7b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -92, + mantissa: 0xcabeed9b_5e2e888d_81d32b11_d289a624_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0x8764876d_11ad6607_8a8d5382_3ffe82d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0x84c9f9e5_6a5f5034_ad2c8512_16cb1ba1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xb7c1d143_a15d8aab_03a7fa3e_b7d07a36_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -85, + mantissa: 0xa78f8257_4658040f_7a1ad39c_91ea9483_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0xb231e0ca_b729a404_44c38f52_be208507_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -86, + mantissa: 0xae317981_42349081_8bc68b28_f69b8e49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xb451abd3_5cd79c6d_7e578164_32f16da1_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[15]; + for i in (0..15).rev() { + p_num = recip * p_num + P[i]; + } + + let mut p_den = Q[15]; + for i in (0..15).rev() { + p_den = recip * p_den + Q[i]; + } + + let z = p_num * p_den.reciprocal(); + + let r_sqrt = bessel_rsqrt_hard(x, recip); + (z * r_sqrt).fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_i0e() { + assert_eq!(f_i0e(0.00000000000000000000000000052342), 1.0); + assert_eq!(f_i0e(f64::EPSILON), 0.9999999999999998); + assert_eq!(f_i0e(9.500000000005492,), 0.13125126081422883); + assert!(f_i0e(f64::NAN).is_nan()); + assert_eq!(f_i0e(f64::INFINITY), 0.); + assert_eq!(f_i0e(f64::NEG_INFINITY), 0.); + assert_eq!(f_i0e(7.500000000788034), 0.14831583006929877); + assert_eq!(f_i0e(715.), 0.014922205745802662); + assert_eq!(f_i0e(12.), 0.11642622121344044); + assert_eq!(f_i0e(16.), 0.10054412736125203); + assert_eq!(f_i0e(18.432), 0.09357372647647); + assert_eq!(f_i0e(26.432), 0.07797212360059241); + assert_eq!(f_i0e(0.2), 0.8269385516343293); + assert_eq!(f_i0e(7.5), 0.14831583007739552); + assert_eq!(f_i0e(-1.5), 0.36743360905415834); + assert_eq!(i0e_asympt_hard(18.432), 0.09357372647647); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0ef.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0ef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0ef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0ef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,335 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::polyeval::{ + f_estrin_polyeval5, f_estrin_polyeval7, f_estrin_polyeval8, f_polyeval6, f_polyeval10, +}; + +/// Modified exponentially scaled Bessel of the first kind of order 0 +/// +/// Computes exp(-|x|)*I0(x) +/// +/// Max ULP 0.5 +pub fn f_i0ef(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN + if ux == 0 { + // |x| == 0 + return 1.; + } + if x.is_infinite() { + return 0.; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff; + + if xb <= 0x40f00000u32 { + // |x| <= 7.5 + let core_expf = core_expf(-f32::from_bits(xb)); + if xb < 0x3f800000u32 { + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + // taylor series for I0(x) * exp(-x) ~ 1 - x + O(x^2) + return 1. - x; + } + // |x| < 1 + return i0f_small(f32::from_bits(xb), core_expf); + } else if xb <= 0x40600000u32 { + // |x| <= 3.5 + return i0ef_1_to_3p5(f32::from_bits(xb), core_expf); + } else if xb <= 0x40c00000u32 { + // |x| <= 6 + return i0f_3p5_to_6(f32::from_bits(xb), core_expf); + } + return i0f_6_to_7p5(f32::from_bits(xb), core_expf); + } + + i0ef_asympt(f32::from_bits(xb)) +} + +/** +How polynomial is obtained described at [i0f_1_to_7p5]. + +Computes I0(x) as follows: +I0(x) = 1 + (x/2)^2 * P(x) + +This method valid only [0;1] + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn i0f_small(x: f32, v_exp: f64) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p = f_estrin_polyeval7( + eval_x, + f64::from_bits(0x3ff000000000013a), + f64::from_bits(0x3fcffffffffc20b6), + f64::from_bits(0x3f9c71c71e6cd6a2), + f64::from_bits(0x3f5c71c65b0af15f), + f64::from_bits(0x3f1234796fceb081), + f64::from_bits(0x3ec0280faf31678c), + f64::from_bits(0x3e664fd494223545), + ); + (f_fmla(p, eval_x, 1.) * v_exp) as f32 +} + +/** +Computes I0. + +/// Valid only on interval [1;3.5] + +as rational approximation I0 = 1 + (x/2)^2 * Pn((x/2)^2)/Qm((x/2)^2)) + +Generated by Wolram Mathematica: +```python +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0ef_1_to_3p5(x: f32, v_exp: f64) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_polyeval6( + eval_x, + f64::from_bits(0x3feffffffffffb69), + f64::from_bits(0x3fc9ed7bd9dc97a7), + f64::from_bits(0x3f915c14693c842e), + f64::from_bits(0x3f45c6dc6a719e42), + f64::from_bits(0x3eeacb79eba725f7), + f64::from_bits(0x3e7b51e2acfc4355), + ); + let p_den = f_estrin_polyeval5( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa84a10988f28eb), + f64::from_bits(0x3f50f5599197a4be), + f64::from_bits(0xbeea420cf9b13b1b), + f64::from_bits(0x3e735d0c1eb6ed7d), + ); + + (f_fmla(p_num / p_den, eval_x, 1.) * v_exp) as f32 +} + +// Valid only on interval [6;7] +// Generated by Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +fn i0f_6_to_7p5(x: f32, v_exp: f64) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_estrin_polyeval8( + eval_x, + f64::from_bits(0x3fefffffffffff7d), + f64::from_bits(0x3fcb373b00569ccf), + f64::from_bits(0x3f939069c3363b81), + f64::from_bits(0x3f4c2095c90c66b3), + f64::from_bits(0x3ef6713f648413db), + f64::from_bits(0x3e947efa2f9936b4), + f64::from_bits(0x3e2486a182f49420), + f64::from_bits(0x3da213034a33de33), + ); + let p_den = f_estrin_polyeval7( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa32313fea59d9e), + f64::from_bits(0x3f460594c2ec6706), + f64::from_bits(0xbedf725fb714690f), + f64::from_bits(0x3e6d9cb39b19555c), + f64::from_bits(0xbdf1900e3abcb7a6), + f64::from_bits(0x3d64a21a2ea78ef6), + ); + + (f_fmla(p_num / p_den, eval_x, 1.) * v_exp) as f32 +} + +// Valid only on interval [3.5;6] +// Generated in Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +fn i0f_3p5_to_6(x: f32, v_exp: f64) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_polyeval6( + eval_x, + f64::from_bits(0x3feffffffffd9550), + f64::from_bits(0x3fc97e18ee033fb4), + f64::from_bits(0x3f90b3199079bce1), + f64::from_bits(0x3f442c300a425372), + f64::from_bits(0x3ee7831030ae18ca), + f64::from_bits(0x3e76387d67354932), + ); + let p_den = f_polyeval6( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfaa079c484e406a), + f64::from_bits(0x3f5452098f1556fb), + f64::from_bits(0xbef33efb4a8128ac), + f64::from_bits(0x3e865996e19448ca), + f64::from_bits(0xbe09acbb64533c3e), + ); + + (f_fmla(p_num / p_den, eval_x, 1.) * v_exp) as f32 +} + +/** +Asymptotic expansion for I0. + +Computes: +sqrt(x) * exp(-x) * I0(x) = Pn(1/x)/Qn(1/x) +hence: +I0(x)exp(-x) = Pn(1/x)/Qm(1/x)/sqrt(x) + +Generated by Mathematica: +```text +<70] +num=Numerator[approx][[1]]; +den=Denominator[approx][[1]]; +poly=num; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=den; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0ef_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let p_num = f_polyeval10( + recip, + f64::from_bits(0x3fd9884533d4364f), + f64::from_bits(0xc02ed6c9269921a7), + f64::from_bits(0x4070ee77ffed64a5), + f64::from_bits(0xc0a4ffd558b06889), + f64::from_bits(0x40cf2633e2840f6f), + f64::from_bits(0xc0ea813a9ba42b84), + f64::from_bits(0x40f569bf5d63eb8c), + f64::from_bits(0xc0b3138874cdd180), + f64::from_bits(0xc0fa3152ed485937), + f64::from_bits(0x40ddaccbed454f47), + ); + let p_den = f_polyeval10( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc0436352c350b88c), + f64::from_bits(0x40855eaa17b05edd), + f64::from_bits(0xc0baa46f155bd266), + f64::from_bits(0x40e3e9fd90a2e695), + f64::from_bits(0xc1012dc621dfc1e8), + f64::from_bits(0x410cafeea713e8ce), + f64::from_bits(0xc0e0a3ee0077d7f7), + f64::from_bits(0xc110bcced6a39e9e), + f64::from_bits(0x40f9a1e4a91be4d6), + ); + let z = p_num / p_den; + let r_sqrt = j1f_rsqrt(dx); + (z * r_sqrt) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i0f() { + assert!(f_i0ef(f32::NAN).is_nan()); + assert_eq!(f_i0ef(f32::NEG_INFINITY), 0.); + assert_eq!(f_i0ef(f32::INFINITY), 0.); + assert_eq!(f_i0ef(1.), 0.4657596); + assert_eq!(f_i0ef(5.), 0.1835408); + assert_eq!(f_i0ef(16.), 0.100544125); + assert_eq!(f_i0ef(32.), 0.070804186); + assert_eq!(f_i0ef(92.0), 0.04164947); + assert_eq!(f_i0ef(0.), 1.0); + assert_eq!(f_i0ef(28.), 0.075736605); + assert_eq!(f_i0ef(-28.), 0.075736605); + assert_eq!(f_i0ef(-32.), 0.070804186); + assert_eq!(f_i0ef(-92.0), 0.04164947); + assert_eq!(f_i0ef(-0.), 1.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i0f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i0f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,354 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::polyeval::{ + f_estrin_polyeval5, f_estrin_polyeval7, f_estrin_polyeval8, f_estrin_polyeval9, f_polyeval6, +}; + +/// Modified Bessel of the first kind of order 0 +/// +/// Max ULP 0.5 +pub fn f_i0f(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN + if ux == 0 { + // |x| == 0 + return 1.; + } + if x.is_infinite() { + return f32::INFINITY; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff; + + if xb >= 0x42b7cd32u32 { + // |x| >= 91.90077 + return f32::INFINITY; + } + + if xb < 0x40f00000u32 { + // |x| < 7.5 + if xb < 0x3f800000u32 { + // |x| < 1 + if xb <= 0x34000000u32 { + // |x| < f32::EPSILON + // taylor series for I0(x) ~ 1 + x^2/4 + O(x^4) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, x * 0.25, 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + return f_fmla(dx, dx * 0.25, 1.) as f32; + } + } + return i0f_small(f32::from_bits(xb)) as f32; + } else if xb <= 0x40600000u32 { + // |x| < 3.5 + return i0f_1_to_3p5(f32::from_bits(xb)); + } else if xb <= 0x40c00000u32 { + // |x| < 6 + return i0f_3p5_to_6(f32::from_bits(xb)); + } + return i0f_6_to_7p5(f32::from_bits(xb)); + } + + i0f_asympt(f32::from_bits(xb)) +} + +/** +How polynomial is obtained described at [i0f_1_to_7p5]. + +Computes I0(x) as follows: +I0(x) = 1 + (x/2)^2 * P(x) + +This method valid only [0;1] + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn i0f_small(x: f32) -> f64 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p = f_estrin_polyeval7( + eval_x, + f64::from_bits(0x3ff000000000013a), + f64::from_bits(0x3fcffffffffc20b6), + f64::from_bits(0x3f9c71c71e6cd6a2), + f64::from_bits(0x3f5c71c65b0af15f), + f64::from_bits(0x3f1234796fceb081), + f64::from_bits(0x3ec0280faf31678c), + f64::from_bits(0x3e664fd494223545), + ); + f_fmla(p, eval_x, 1.) +} + +/** +Computes I0. + +/// Valid only on interval [1;3.5] + +as rational approximation I0 = 1 + (x/2)^2 * Pn((x/2)^2)/Qm((x/2)^2)) + +Generated by Wolram Mathematica: +```python +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0f_1_to_3p5(x: f32) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_polyeval6( + eval_x, + f64::from_bits(0x3feffffffffffb69), + f64::from_bits(0x3fc9ed7bd9dc97a7), + f64::from_bits(0x3f915c14693c842e), + f64::from_bits(0x3f45c6dc6a719e42), + f64::from_bits(0x3eeacb79eba725f7), + f64::from_bits(0x3e7b51e2acfc4355), + ); + let p_den = f_estrin_polyeval5( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa84a10988f28eb), + f64::from_bits(0x3f50f5599197a4be), + f64::from_bits(0xbeea420cf9b13b1b), + f64::from_bits(0x3e735d0c1eb6ed7d), + ); + + f_fmla(p_num / p_den, eval_x, 1.) as f32 +} + +// Valid only on interval [6;7] +// Generated by Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +fn i0f_6_to_7p5(x: f32) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_estrin_polyeval8( + eval_x, + f64::from_bits(0x3fefffffffffff7d), + f64::from_bits(0x3fcb373b00569ccf), + f64::from_bits(0x3f939069c3363b81), + f64::from_bits(0x3f4c2095c90c66b3), + f64::from_bits(0x3ef6713f648413db), + f64::from_bits(0x3e947efa2f9936b4), + f64::from_bits(0x3e2486a182f49420), + f64::from_bits(0x3da213034a33de33), + ); + let p_den = f_estrin_polyeval7( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa32313fea59d9e), + f64::from_bits(0x3f460594c2ec6706), + f64::from_bits(0xbedf725fb714690f), + f64::from_bits(0x3e6d9cb39b19555c), + f64::from_bits(0xbdf1900e3abcb7a6), + f64::from_bits(0x3d64a21a2ea78ef6), + ); + + f_fmla(p_num / p_den, eval_x, 1.) as f32 +} + +// Valid only on interval [3.5;6] +// Generated in Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +fn i0f_3p5_to_6(x: f32) -> f32 { + let dx = x as f64; + const C: f64 = 1. / 4.; + let eval_x = dx * dx * C; + + let p_num = f_polyeval6( + eval_x, + f64::from_bits(0x3feffffffffd9550), + f64::from_bits(0x3fc97e18ee033fb4), + f64::from_bits(0x3f90b3199079bce1), + f64::from_bits(0x3f442c300a425372), + f64::from_bits(0x3ee7831030ae18ca), + f64::from_bits(0x3e76387d67354932), + ); + let p_den = f_polyeval6( + eval_x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfaa079c484e406a), + f64::from_bits(0x3f5452098f1556fb), + f64::from_bits(0xbef33efb4a8128ac), + f64::from_bits(0x3e865996e19448ca), + f64::from_bits(0xbe09acbb64533c3e), + ); + + f_fmla(p_num / p_den, eval_x, 1.) as f32 +} + +/** +Asymptotic expansion for I0. + +Computes: +sqrt(x) * exp(-x) * I0(x) = Pn(1/x)/Qn(1/x) +hence: +I0(x) = Pn(1/x)/Qm(1/x)*exp(x)/sqrt(x) + +Generated by Mathematica: +```text +<70] +num=Numerator[approx][[1]]; +den=Denominator[approx][[1]]; +poly=num; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0f_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let p_num = f_estrin_polyeval9( + recip, + f64::from_bits(0x3fd9884533d44829), + f64::from_bits(0xc02c940f40595581), + f64::from_bits(0x406d41c495c2f762), + f64::from_bits(0xc0a10ab76dda4520), + f64::from_bits(0x40c825b1c2a48d07), + f64::from_bits(0xc0e481d606d0b748), + f64::from_bits(0x40f34759deefbd40), + f64::from_bits(0xc0ef4b7fb49fa116), + f64::from_bits(0x40c409a6f882ba00), + ); + let p_den = f_estrin_polyeval9( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc041f8a9131ad229), + f64::from_bits(0x408278e56af035bb), + f64::from_bits(0xc0b5a34a108f3e35), + f64::from_bits(0x40dee6f278ee24f5), + f64::from_bits(0xc0fa95093b0c4f9f), + f64::from_bits(0x4109982b87f75651), + f64::from_bits(0xc10618cc3c91e2db), + f64::from_bits(0x40e30895aec6fc4f), + ); + let z = p_num / p_den; + + let e = core_expf(x); + let r_sqrt = j1f_rsqrt(dx); + (z * r_sqrt * e) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i0f() { + assert!(f_i0f(f32::NAN).is_nan()); + assert_eq!(f_i0f(f32::NEG_INFINITY), f32::INFINITY); + assert_eq!(f_i0f(f32::INFINITY), f32::INFINITY); + assert_eq!(f_i0f(1.), 1.2660658); + assert_eq!(f_i0f(5.), 27.239872); + assert_eq!(f_i0f(16.), 893446.25); + assert_eq!(f_i0f(32.), 5590908000000.0); + assert_eq!(f_i0f(92.0), f32::INFINITY); + assert_eq!(f_i0f(0.), 1.0); + assert_eq!(f_i0f(28.), 109534600000.0); + assert_eq!(f_i0f(-28.), 109534600000.0); + assert_eq!(f_i0f(-16.), 893446.25); + assert_eq!(f_i0f(-32.), 5590908000000.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,656 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::rational128_exp; +use crate::polyeval::{f_estrin_polyeval5, f_polyeval6}; + +/// Modified Bessel of the first kind of order 1 +/// +/// Max found ULP 0.5 +pub fn f_i1(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x760af31dc4611874u64 { + // Power series of I1(x) ~ x/2 + O(x^3) + // |x| <= 2.2204460492503131e-24 + return x * 0.5; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // Power series of I1(x) ~ x/2 + x^3/16 + O(x^4) + const A0: f64 = 1. / 2.; + const A1: f64 = 1. / 16.; + let r0 = f_fmla(x, x * A1, A0); + return r0 * x; + } + if x.is_infinite() { + return if x.is_sign_positive() { + f64::INFINITY + } else { + f64::NEG_INFINITY + }; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if xb >= 0x40864fe69ff9fec8u64 { + // |x| >= 713.9876098185423 + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + static SIGN: [f64; 2] = [1., -1.]; + + let sign_scale = SIGN[x.is_sign_negative() as usize]; + + if xb < 0x401f000000000000u64 { + // |x| <= 7.75 + return f64::copysign(i1_0_to_7p75(f64::from_bits(xb)).to_f64(), sign_scale); + } + + i1_asympt(f64::from_bits(xb), sign_scale) +} + +/** +Computes +I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) + +Polynomial generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn i1_0_to_7p75(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + + const P: [(u64, u64); 5] = [ + (0x3c55555555555555, 0x3fb5555555555555), + (0x3c1253e1df138479, 0x3f7304597c4fbd4c), + (0x3bcec398b7059ee9, 0x3f287b5b01f6b9c0), + (0xbb7354e7c92c4f77, 0x3ed21de117470d10), + (0xbb1d35ac0d7923cc, 0x3e717f3714dddc04), + ]; + + let ps_num = f_estrin_polyeval5( + eval_x.hi, + f64::from_bits(0x3e063684ca1944a4), + f64::from_bits(0x3d92ac4a0e48a9bb), + f64::from_bits(0x3d1425988b0b0aea), + f64::from_bits(0x3c899839e74ddefc), + f64::from_bits(0x3bed8747bcdd1e61), + ); + + let mut p_num = DoubleDouble::mul_f64_add(eval_x, ps_num, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 4] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc3e59afb81ac7ea, 0xbf9c4848e0661d70), + (0x3bd62fa3dbc1a19c, 0x3f38a9eafcd7e674), + (0x3b6f4688b9eab7d0, 0xbecbfdec51454533), + ]; + + let ps_den = f_polyeval6( + eval_x.hi, + f64::from_bits(0x3e56e7cde9266a32), + f64::from_bits(0xbddc316dff4a672f), + f64::from_bits(0x3d5a43aaee30ebb5), + f64::from_bits(0xbcd1fb023f4f1fa0), + f64::from_bits(0x3c4089ede324209f), + f64::from_bits(0xbb9f64f47ba69604), + ); + + let mut p_den = DoubleDouble::mul_f64_add(eval_x, ps_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(eval_x, p_den, f64::from_bits(0x3ff0000000000000)); + + let p = DoubleDouble::div(p_num, p_den); + + let eval_sqr = DoubleDouble::quick_mult(eval_x, eval_x); + + let mut z = DoubleDouble::mul_f64_add_f64(eval_x, 0.5, 1.); + z = DoubleDouble::mul_add(p, eval_sqr, z); + + let x_over_05 = DoubleDouble::from_exact_mult(x, 0.5); + + let r = DoubleDouble::quick_mult(z, x_over_05); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r; + } + i1_0_to_7p5_hard(x) +} + +// Polynomial generated by Wolfram Mathematica: +// I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[cold] +#[inline(never)] +pub(crate) fn i1_0_to_7p5_hard(x: f64) -> DoubleDouble { + const ONE_OVER_4: f64 = 1. / 4.; + let eval_x = DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_mult(x, x), ONE_OVER_4); + + const P: [(u64, u64); 10] = [ + (0x3c55555555555555, 0x3fb5555555555555), + (0x3c1253e1df138479, 0x3f7304597c4fbd4c), + (0x3bcec398b7059ee9, 0x3f287b5b01f6b9c0), + (0xbb7354e7c92c4f77, 0x3ed21de117470d10), + (0xbb1d35ac0d7923cc, 0x3e717f3714dddc04), + (0xba928dee24678e32, 0x3e063684ca1944a4), + (0xba36aa59912fcbed, 0x3d92ac4a0e48a9bb), + (0x39bad76f18b5ad37, 0x3d1425988b0b0aea), + (0xb923a6bab6928df4, 0x3c899839e74ddefc), + (0x3864356cdfa7b321, 0x3bed8747bcdd1e61), + ]; + + let mut p_num = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[7])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc3e59afb81ac7ea, 0xbf9c4848e0661d70), + (0x3bd62fa3dbc1a19c, 0x3f38a9eafcd7e674), + (0x3b6f4688b9eab7d0, 0xbecbfdec51454533), + (0x3af0fb4a17103ef8, 0x3e56e7cde9266a32), + (0xba71755779c6d4bd, 0xbddc316dff4a672f), + (0x39cf8ed8d449e2c6, 0x3d5a43aaee30ebb5), + (0x39704e900a373874, 0xbcd1fb023f4f1fa0), + (0xb8e33e87e4bffbb1, 0x3c4089ede324209f), + (0x380fb09b3fd49d5c, 0xbb9f64f47ba69604), + ]; + + let mut p_den = DoubleDouble::mul_add( + eval_x, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[7])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[0])); + + let p = DoubleDouble::div(p_num, p_den); + + let eval_sqr = DoubleDouble::quick_mult(eval_x, eval_x); + + let mut z = DoubleDouble::mul_f64_add_f64(eval_x, 0.5, 1.); + z = DoubleDouble::mul_add(p, eval_sqr, z); + + let x_over_05 = DoubleDouble::from_exact_mult(x, 0.5); + + DoubleDouble::quick_mult(z, x_over_05) +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x) = Pn(1/x)/Qm(1/x)*exp(x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1_asympt(x: f64, sign_scale: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + const P: [(u64, u64); 12] = [ + (0xbc73a823f28a2f5e, 0x3fd9884533d43651), + (0x3cc0d5bb78e674b3, 0xc0354325c8029263), + (0x3d20e1155aaaa283, 0x4080c09b027c46a4), + (0xbd5b90dcf81b99c1, 0xc0bfc1311090c839), + (0xbd98f2fda9e8fa1b, 0x40f3bb81bb190ae2), + (0xbdcec960752b60da, 0xc1207c0bbbc31cd9), + (0x3dd3c9a299c9c41f, 0x414253e25c4584af), + (0xbde82e7b9a3e1acc, 0xc159a656aece377c), + (0x3e0d3d30d701a8ab, 0x416398df24c74ef2), + (0xbdf57b85ab7006e2, 0xc151fd119be1702b), + (0x3dd760928f4515fd, 0xc1508327e42639bc), + (0x3dc09e71bc648589, 0x4143e4933afa621c), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcb334d5a476d9ad, 0xc04a75f94c1a0c1a), + (0xbd324d58ed98bfae, 0x4094b00e60301c42), + (0x3d7c8725666c4360, 0xc0d36b9d28d45928), + (0x3d7f8457c2945822, 0x4107d6c398a174ed), + (0x3dbc655ea216594b, 0xc1339393e6776e38), + (0xbdebb5dffef78272, 0x415537198d23f6a1), + (0xbdb577f8abad883e, 0xc16c6c399dcd6949), + (0x3e14261c5362f109, 0x4173c02446576949), + (0x3dc382ededad42c5, 0xc1547dff5770f4ec), + (0xbe05c0f74d4c7956, 0xc165c88046952562), + (0xbdbf9145927aa2c7, 0x414395e46bc45d5b), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let e = i0_exp(dx * 0.5); + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + + let r = DoubleDouble::quick_mult(z * r_sqrt * e, e); + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3ba0000000000000), // 2^-69 + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up == lb { + return f64::copysign(r.to_f64(), sign_scale); + } + i1_asympt_hard(x, sign_scale) +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x) = Pn(1/x)/Qm(1/x)*exp(x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i1_asympt_hard(x: f64, sign_scale: f64) -> f64 { + static P: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc42299e_a1b28468_bea7da47_28f13acc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -124, + mantissa: 0xda979406_3df6e66f_cf31c3f5_f194b48c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -120, + mantissa: 0xd60b7b96_c958929b_cabe1d8c_3d874767_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xd27aad9a_8fb38d56_46ab4510_8479306e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -108, + mantissa: 0xe0167305_c451bd1f_d2f17b68_5c62e2ff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -103, + mantissa: 0x8f6d238f_c80d8e4a_08c130f6_24e1c925_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -100, + mantissa: 0xfe32280f_2ea99024_d9924472_92d7ac8f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -96, + mantissa: 0xa48815ac_d265609f_da4ace94_811390b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -93, + mantissa: 0x9ededfe5_833b4cc1_731efd5c_f8729c6c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -91, + mantissa: 0xe5b43203_2784ae6a_f7458556_0a8308ea_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xf5df279a_3fb4ef60_8d10adee_7dd2f47b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0xbdb59963_7a757ed1_87280e0e_7f93ca2b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xc87fdea5_53177ca8_c91de5fb_3f8f78d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -85, + mantissa: 0x846d16a7_4663ef5d_ad42d599_5bc726b8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xb3ed2055_74262d95_389f33e4_2ac3774a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -88, + mantissa: 0xa511aa32_c18c34e4_3d029a90_a71b7a55_u128, + }, + ]; + static Q: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -122, + mantissa: 0x877b771a_ad8f5fd3_5aacf5f9_f04ee9de_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -118, + mantissa: 0x89475ecd_9c84361e_800c8a3a_c8af23bf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0x837d1196_cf2723f1_23b54da8_225efe05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -106, + mantissa: 0x8ae3aecb_15355751_a9ee12e5_a4dd9dde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -102, + mantissa: 0xb0886afa_bc13f996_ab45d252_75c8f587_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0x9b37d7cd_b114b86b_7d14a389_26599aa1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -95, + mantissa: 0xc716bf54_09d5dd9f_bc16679b_93aaeca4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -92, + mantissa: 0xbe0cd82e_c8af8371_ab028ed9_c7902dd2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0x875f8d91_8ef5d434_a39d00f9_2aed3d2a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -87, + mantissa: 0x8e030781_5aa4ce7f_70156b82_8b216b7c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -86, + mantissa: 0xd4dd2687_92646fbd_5ea2d422_da64fc0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0xd6d72ab3_64b4a827_0499af0f_13a51a80_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -84, + mantissa: 0x828f4e8b_728747a9_2cebe54a_810e2681_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0x91570096_36a3fcfb_6b936d44_68dda1be_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xf082ad00_86024ed4_dd31613b_ec41e3f8_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[15]; + for i in (0..15).rev() { + p_num = recip * p_num + P[i]; + } + let mut p_den = Q[15]; + for i in (0..15).rev() { + p_den = recip * p_den + Q[i]; + } + let z = p_num * p_den.reciprocal(); + let r_sqrt = bessel_rsqrt_hard(x, recip); + let f_exp = rational128_exp(x); + (z * r_sqrt * f_exp).fast_as_f64() * sign_scale +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_fi1() { + assert_eq!( + f_i1(0.0000000000000000000000000000000006423424234121), + 3.2117121170605e-34 + ); + assert_eq!(f_i1(7.750000000757874), 315.8524811496668); + assert_eq!(f_i1(7.482812501363189), 245.58002285881892); + assert_eq!(f_i1(-7.750000000757874), -315.8524811496668); + assert_eq!(f_i1(-7.482812501363189), -245.58002285881892); + assert!(f_i1(f64::NAN).is_nan()); + assert_eq!(f_i1(f64::INFINITY), f64::INFINITY); + assert_eq!(f_i1(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert_eq!(f_i1(0.01), 0.005000062500260418); + assert_eq!(f_i1(-0.01), -0.005000062500260418); + assert_eq!(f_i1(-9.01), -1040.752038018038); + assert_eq!(f_i1(9.01), 1040.752038018038); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1e.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1e.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1e.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1e.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,460 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::bessel::i1::i1_0_to_7p75; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +/// Modified exponentially scaled Bessel of the first kind of order 1 +/// +/// Computes exp(-|x|)*I1(x) +pub fn f_i1e(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x760af31dc4611874u64 { + // |x| <= 2.2204460492503131e-24 + return x * 0.5; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // Power series of I1(x)*exp(-|x|) ~ x/2 - x^2/2 + O(x^3) + return f_fmla(x, -x * 0.5, x * 0.5); + } + if x.is_infinite() { + return 0.; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + static SIGN: [f64; 2] = [1., -1.]; + + let sign_scale = SIGN[x.is_sign_negative() as usize]; + + if xb < 0x401f000000000000u64 { + // |x| <= 7.75 + let v_exp = i0_exp(-f64::from_bits(xb)); + let vi1 = i1_0_to_7p75(f64::from_bits(xb)); + let r = DoubleDouble::quick_mult(vi1, v_exp); + return f64::copysign(r.to_f64(), sign_scale); + } + + i1e_asympt(f64::from_bits(xb), sign_scale) +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x)exp(-|x|) = Pn(1/x)/Qm(1/x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1e_asympt(x: f64, sign_scale: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + const P: [(u64, u64); 12] = [ + (0xbc73a823f28a2f5e, 0x3fd9884533d43651), + (0x3cc0d5bb78e674b3, 0xc0354325c8029263), + (0x3d20e1155aaaa283, 0x4080c09b027c46a4), + (0xbd5b90dcf81b99c1, 0xc0bfc1311090c839), + (0xbd98f2fda9e8fa1b, 0x40f3bb81bb190ae2), + (0xbdcec960752b60da, 0xc1207c0bbbc31cd9), + (0x3dd3c9a299c9c41f, 0x414253e25c4584af), + (0xbde82e7b9a3e1acc, 0xc159a656aece377c), + (0x3e0d3d30d701a8ab, 0x416398df24c74ef2), + (0xbdf57b85ab7006e2, 0xc151fd119be1702b), + (0x3dd760928f4515fd, 0xc1508327e42639bc), + (0x3dc09e71bc648589, 0x4143e4933afa621c), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcb334d5a476d9ad, 0xc04a75f94c1a0c1a), + (0xbd324d58ed98bfae, 0x4094b00e60301c42), + (0x3d7c8725666c4360, 0xc0d36b9d28d45928), + (0x3d7f8457c2945822, 0x4107d6c398a174ed), + (0x3dbc655ea216594b, 0xc1339393e6776e38), + (0xbdebb5dffef78272, 0x415537198d23f6a1), + (0xbdb577f8abad883e, 0xc16c6c399dcd6949), + (0x3e14261c5362f109, 0x4173c02446576949), + (0x3dc382ededad42c5, 0xc1547dff5770f4ec), + (0xbe05c0f74d4c7956, 0xc165c88046952562), + (0xbdbf9145927aa2c7, 0x414395e46bc45d5b), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + + let r = z * r_sqrt; + + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3ba0000000000000), // 2^-69 + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up == lb { + return f64::copysign(r.to_f64(), sign_scale); + } + i1e_asympt_hard(x, sign_scale) +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x)exp(-|x|) = Pn(1/x)/Qm(1/x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i1e_asympt_hard(x: f64, sign_scale: f64) -> f64 { + static P: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc42299e_a1b28468_bea7da47_28f13acc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -124, + mantissa: 0xda979406_3df6e66f_cf31c3f5_f194b48c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -120, + mantissa: 0xd60b7b96_c958929b_cabe1d8c_3d874767_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xd27aad9a_8fb38d56_46ab4510_8479306e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -108, + mantissa: 0xe0167305_c451bd1f_d2f17b68_5c62e2ff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -103, + mantissa: 0x8f6d238f_c80d8e4a_08c130f6_24e1c925_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -100, + mantissa: 0xfe32280f_2ea99024_d9924472_92d7ac8f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -96, + mantissa: 0xa48815ac_d265609f_da4ace94_811390b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -93, + mantissa: 0x9ededfe5_833b4cc1_731efd5c_f8729c6c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -91, + mantissa: 0xe5b43203_2784ae6a_f7458556_0a8308ea_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xf5df279a_3fb4ef60_8d10adee_7dd2f47b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -87, + mantissa: 0xbdb59963_7a757ed1_87280e0e_7f93ca2b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xc87fdea5_53177ca8_c91de5fb_3f8f78d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -85, + mantissa: 0x846d16a7_4663ef5d_ad42d599_5bc726b8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -86, + mantissa: 0xb3ed2055_74262d95_389f33e4_2ac3774a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -88, + mantissa: 0xa511aa32_c18c34e4_3d029a90_a71b7a55_u128, + }, + ]; + static Q: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -122, + mantissa: 0x877b771a_ad8f5fd3_5aacf5f9_f04ee9de_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -118, + mantissa: 0x89475ecd_9c84361e_800c8a3a_c8af23bf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0x837d1196_cf2723f1_23b54da8_225efe05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -106, + mantissa: 0x8ae3aecb_15355751_a9ee12e5_a4dd9dde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -102, + mantissa: 0xb0886afa_bc13f996_ab45d252_75c8f587_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0x9b37d7cd_b114b86b_7d14a389_26599aa1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -95, + mantissa: 0xc716bf54_09d5dd9f_bc16679b_93aaeca4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -92, + mantissa: 0xbe0cd82e_c8af8371_ab028ed9_c7902dd2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0x875f8d91_8ef5d434_a39d00f9_2aed3d2a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -87, + mantissa: 0x8e030781_5aa4ce7f_70156b82_8b216b7c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -86, + mantissa: 0xd4dd2687_92646fbd_5ea2d422_da64fc0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0xd6d72ab3_64b4a827_0499af0f_13a51a80_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -84, + mantissa: 0x828f4e8b_728747a9_2cebe54a_810e2681_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -85, + mantissa: 0x91570096_36a3fcfb_6b936d44_68dda1be_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xf082ad00_86024ed4_dd31613b_ec41e3f8_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[15]; + for i in (0..15).rev() { + p_num = recip * p_num + P[i]; + } + let mut p_den = Q[15]; + for i in (0..15).rev() { + p_den = recip * p_den + Q[i]; + } + let z = p_num * p_den.reciprocal(); + let r_sqrt = bessel_rsqrt_hard(x, recip); + (z * r_sqrt).fast_as_f64() * sign_scale +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_fi1e() { + assert_eq!(f_i1e(f64::EPSILON), 1.1102230246251563e-16); + assert_eq!(f_i1e(7.750000000757874), 0.13605110007443239); + assert_eq!(f_i1e(7.482812501363189), 0.13818116726273896); + assert_eq!(f_i1e(-7.750000000757874), -0.13605110007443239); + assert_eq!(f_i1e(-7.482812501363189), -0.13818116726273896); + assert!(f_i1e(f64::NAN).is_nan()); + assert_eq!(f_i1e(f64::INFINITY), 0.); + assert_eq!(f_i1e(f64::NEG_INFINITY), 0.); + assert_eq!(f_i1e(0.01), 0.004950311047118276); + assert_eq!(f_i1e(-0.01), -0.004950311047118276); + assert_eq!(f_i1e(-9.01), -0.12716101566063667); + assert_eq!(f_i1e(9.01), 0.12716101566063667); + assert_eq!(f_i1e(763.), 0.014435579051182581); + assert_eq!(i1e_asympt_hard(9.01, 1.), 0.12716101566063667); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1ef.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1ef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1ef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1ef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::polyeval::{f_estrin_polyeval7, f_estrin_polyeval9, f_polyeval10}; + +/// Modified exponentially scaled Bessel of the first kind of order 1 +/// +/// Computes exp(-|x|)*I1(x) +/// +/// Max ULP 0.5 +pub fn f_i1ef(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + // |x| == 0 + return 0.; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { -0. }; + } + return x + f32::NAN; // |x| == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff; + + static SIGN: [f64; 2] = [1., -1.]; + + let sign_scale = SIGN[x.is_sign_negative() as usize]; + + if xb <= 0x40f80000u32 { + // |x| <= 7.75 + let core_expf = core_expf(-f32::from_bits(xb)); + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + // taylor series for I1(x)/Exp(x) ~ x/2 - x^2/2 + O(x^3) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + let half_x = 0.5 * x; + return f_fmlaf(x, -half_x, half_x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + let half_x = 0.5 * dx; + return f_fmla(dx, -half_x, half_x) as f32; + } + } + return i1ef_small(f32::from_bits(xb), sign_scale, core_expf) as f32; + } + + i1ef_asympt(f32::from_bits(xb), sign_scale) +} + +/** +Computes +I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) + +Generated by Woflram Mathematica: + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1ef_small(x: f32, sign_scale: f64, core_expf: f64) -> f64 { + let dx = x as f64; + let x_over_two = dx * 0.5; + let x_over_two_sqr = x_over_two * x_over_two; + let x_over_two_p4 = x_over_two_sqr * x_over_two_sqr; + + let p_num = f_estrin_polyeval7( + x_over_two_sqr, + f64::from_bits(0x3fb5555555555555), + f64::from_bits(0x3f706cdccca396c4), + f64::from_bits(0x3f23f9e12bdbba92), + f64::from_bits(0x3ec8e39208e926b2), + f64::from_bits(0x3e62e53b433c42ff), + f64::from_bits(0x3def7cb16d10fb46), + f64::from_bits(0x3d6747cd73d9d783), + ); + let p_den = f_estrin_polyeval7( + x_over_two_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa2075f77b54885), + f64::from_bits(0x3f438c6d797c29f5), + f64::from_bits(0xbeda57e2a258c6da), + f64::from_bits(0x3e677e777c569432), + f64::from_bits(0xbdea9212a96babc1), + f64::from_bits(0x3d5e183186d5d782), + ); + let p = p_num / p_den; + + let p1 = f_fmla(0.5, x_over_two_sqr, 1.); + let p2 = f_fmla(x_over_two_p4, p, p1); + p2 * x_over_two * sign_scale * core_expf +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x)*exp(-x) = Pn(1/x)/Qm(1/x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1ef_asympt(x: f32, sign_scale: f64) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let p_num = f_polyeval10( + recip, + f64::from_bits(0x3fd9884533d43652), + f64::from_bits(0xc030686a3694d13c), + f64::from_bits(0x407344697f45c2ee), + f64::from_bits(0xc0aa037ee36a8967), + f64::from_bits(0x40d5b2eab8cf5b17), + f64::from_bits(0xc0f65addf81dbee8), + f64::from_bits(0x410afc22ec1f9b8b), + f64::from_bits(0xc110821dd0fc12b4), + f64::from_bits(0x40feb3452c93aada), + f64::from_bits(0xc0c6d04e8c5d02f3), + ); + let p_den = f_estrin_polyeval9( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc04460707a9ceed4), + f64::from_bits(0x4087ac89fcf51e9b), + f64::from_bits(0xc0bf830689f31b42), + f64::from_bits(0x40e9c281c367fab2), + f64::from_bits(0xc109b59ade76eb8c), + f64::from_bits(0x411d553a9f5673c5), + f64::from_bits(0xc11f9dbe0665523b), + f64::from_bits(0x4103b62a329b60d7), + ); + let z = p_num / p_den; + let r_sqrt = j1f_rsqrt(dx); + (z * r_sqrt * sign_scale) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i1ef() { + assert!(f_i1ef(f32::NAN).is_nan()); + assert_eq!(f_i1ef(f32::INFINITY), 0.0); + assert_eq!(f_i1ef(f32::NEG_INFINITY), 0.0); + assert_eq!(f_i1ef(0.), 0.); + assert_eq!(f_i1ef(1.), 0.20791042); + assert_eq!(f_i1ef(-1.), -0.20791042); + assert_eq!(f_i1ef(9.), 0.12722498); + assert_eq!(f_i1ef(-9.), -0.12722498); + assert_eq!(f_i1ef(0.000000000543453), 2.717265e-10); + assert_eq!(f_i1ef(-0.000000000543453), -2.717265e-10); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,210 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::polyeval::{f_estrin_polyeval7, f_estrin_polyeval9, f_polyeval10}; + +/// Modified Bessel of the first kind of order 1 +/// +/// Max ULP 0.5 +pub fn f_i1f(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN + if ux == 0 { + // |x| == 0 + return 0.; + } + if x.is_infinite() { + return if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NEG_INFINITY + }; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff; + + if xb > 0x42b7d001 { + // x > 91.906261 + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + + static SIGN: [f64; 2] = [1., -1.]; + + let sign_scale = SIGN[x.is_sign_negative() as usize]; + + if xb <= 0x40f80000u32 { + // |x| <= 7.75 + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + // taylor series for I1(x) ~ x/2 + O(x^3) + return x * 0.5; + } + return i1f_small(f32::from_bits(xb), sign_scale) as f32; + } + + i1f_asympt(f32::from_bits(xb), sign_scale) +} + +/** +Computes +I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) + +Generated by Woflram Mathematica: + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1f_small(x: f32, sign_scale: f64) -> f64 { + let dx = x as f64; + let x_over_two = dx * 0.5; + let x_over_two_sqr = x_over_two * x_over_two; + let x_over_two_p4 = x_over_two_sqr * x_over_two_sqr; + + let p_num = f_estrin_polyeval7( + x_over_two_sqr, + f64::from_bits(0x3fb5555555555555), + f64::from_bits(0x3f706cdccca396c4), + f64::from_bits(0x3f23f9e12bdbba92), + f64::from_bits(0x3ec8e39208e926b2), + f64::from_bits(0x3e62e53b433c42ff), + f64::from_bits(0x3def7cb16d10fb46), + f64::from_bits(0x3d6747cd73d9d783), + ); + let p_den = f_estrin_polyeval7( + x_over_two_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa2075f77b54885), + f64::from_bits(0x3f438c6d797c29f5), + f64::from_bits(0xbeda57e2a258c6da), + f64::from_bits(0x3e677e777c569432), + f64::from_bits(0xbdea9212a96babc1), + f64::from_bits(0x3d5e183186d5d782), + ); + let p = p_num / p_den; + + let p1 = f_fmla(0.5, x_over_two_sqr, 1.); + let p2 = f_fmla(x_over_two_p4, p, p1); + p2 * x_over_two * sign_scale +} + +/** +Asymptotic expansion for I1. + +Computes: +sqrt(x) * exp(-x) * I1(x) = Pn(1/x)/Qn(1/x) +hence: +I1(x) = Pn(1/x)/Qm(1/x)*exp(x)/sqrt(x) + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1f_asympt(x: f32, sign_scale: f64) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let p_num = f_polyeval10( + recip, + f64::from_bits(0x3fd9884533d43711), + f64::from_bits(0xc0309c047537243a), + f64::from_bits(0x4073bdb14a29bf68), + f64::from_bits(0xc0aaf9eca14d15af), + f64::from_bits(0x40d6c629318a9e42), + f64::from_bits(0xc0f7bee33088a4b0), + f64::from_bits(0x410d018cef093ee2), + f64::from_bits(0xc111f32b325d3fe4), + f64::from_bits(0x4100dddad80e0b42), + f64::from_bits(0xc0c96006c91a00e2), + ); + let p_den = f_estrin_polyeval9( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc044a11d10bae889), + f64::from_bits(0x408843069497d993), + f64::from_bits(0xc0c058710de4b9b9), + f64::from_bits(0x40eb0d97f71420ae), + f64::from_bits(0xc10b55d181ef9ea1), + f64::from_bits(0x411f9413e1932a48), + f64::from_bits(0xc1213bff5bc7d2d6), + f64::from_bits(0x4105c53e92d9b9c0), + ); + let z = p_num / p_den; + let e = core_expf(x); + let r_sqrt = j1f_rsqrt(dx); + (z * r_sqrt * e * sign_scale) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i1f() { + assert!(f_i1f(f32::NAN).is_nan()); + assert!(f_i1f(f32::INFINITY).is_infinite()); + assert!(f_i1f(f32::NEG_INFINITY).is_infinite()); + assert_eq!(f_i1f(0.), 0.); + assert_eq!(f_i1f(1.), 0.5651591); + assert_eq!(f_i1f(-1.), -0.5651591); + assert_eq!(f_i1f(9.), 1030.9147); + assert_eq!(f_i1f(-9.), -1030.9147); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i2.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,587 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::rational128_exp; + +/// Modified bessel of the first kind of order 2 +pub fn f_i2(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + // |x| == 0 + return 0.; + } + if x.is_infinite() { + return f64::INFINITY; + } + return x + f64::NAN; // x = NaN + } + + let xb = x.to_bits() & 0x7fff_ffff_ffff_ffffu64; + + if xb < 0x401f000000000000u64 { + // |x| < 7.75 + if xb <= 0x3cb0000000000000u64 { + // |x| <= f64::EPSILON + // Power series of I2(x) ~ x^2/8 + O(x^4) + const R: f64 = 1. / 8.; + let x2 = x * x * R; + return x2; + } + return i2_small(f64::from_bits(xb)); + } + + if xb >= 0x40864feaeefb23b8 { + // x >= 713.9897136326099 + return f64::INFINITY; + } + + i2_asympt(f64::from_bits(xb)) +} + +/** +Computes +I2(x) = x^2 * R(x^2) + +Generated by Wolfram Mathematica: + +```text +<75] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i2_small(x: f64) -> f64 { + const P: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3fc0000000000000), + (0x3c247833fda9de9a, 0x3f8387c6e72a1b5f), + (0xbbccaf0be91261a6, 0x3f30ba88efff56fa), + (0x3b57c911bfebe1d7, 0x3ecc62e53d061300), + (0x3af3b963f26a3d05, 0x3e5bb090327a14e1), + (0x3a898bff9d40e030, 0x3de0d29c3d37e5b5), + (0xb9f2f63c80d377db, 0x3d5a9e365f1bf6e0), + (0xb965e6d78e1c2b65, 0x3ccbf7ef0929b813), + (0xb8da83d7d40e7310, 0x3c33737520046f4d), + (0xb83f811d5aa3f36e, 0x3b91506558dab318), + (0xb78e601bf5c998c3, 0x3ae2013b3e858bd1), + (0xb6c8185c51734ed8, 0x3a20cc277a5051ba), + ]; + let x_sqr = DoubleDouble::from_exact_mult(x, x); + let x2 = x_sqr * x_sqr; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let e0 = DoubleDouble::mul_add_f64( + x_sqr, + DoubleDouble::from_bit_pair(P[1]), + f64::from_bits(0x3fc0000000000000), + ); + let e1 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc0ba42af56ed76b, 0xbf7cd8e6e2b39f60), + (0x3b90697aa005e598, 0x3efa0260394e1a3d), + (0xbb0c7ccde1f63c82, 0xbe6f1766ec64e492), + (0x3a63f18409bc336f, 0x3ddb80b6b5abad98), + (0xb9e0cd49f22132fe, 0xbd42ff9b55d553da), + (0xb934bfe64905d309, 0x3ca50814fa258ebc), + (0x38a1e35c2d6860f4, 0xbc02c4f2faca2195), + (0xb7ff39e268277e4e, 0x3b5aa545a2c1f16d), + (0xb71053f58545760c, 0xbaacde4c133d42d1), + (0xb68d0c2ccab0ae5b, 0x39f5a965b92b06bc), + (0xb5dc35bda16bee7b, 0xb931375b1c9cfbc7), + ]; + + let e0 = DoubleDouble::mul_add_f64( + x_sqr, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + x_sqr, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let p = DoubleDouble::div(p_num, p_den); + DoubleDouble::quick_mult(p, x_sqr).to_f64() +} + +/** +Asymptotic expansion for I2. +I2(x)=R(1/x)*Exp(x)/sqrt(x) + +Generated in Wolfram: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i2_asympt(x: f64) -> f64 { + let dx = x; + let recip = DoubleDouble::from_quick_recip(x); + const P: [(u64, u64); 12] = [ + (0x3c718bb28ebc5f4e, 0x3fd9884533d43650), + (0x3c96e15a87b6e1d1, 0xc0350acc9e5cb0f9), + (0xbd20b212a79e08f5, 0x40809251af67598a), + (0xbd563b7397df3a54, 0xc0bfc09ede682c8b), + (0xbd5eb872cb057d91, 0x40f44253a9e1e1ab), + (0x3d7614735e566fc5, 0xc121cbcd96dc8765), + (0xbddc4f8df2010026, 0x4145a592e8ec74ad), + (0x3dea227617b678a7, 0xc161df96fb6a9df9), + (0x3e17c9690d906194, 0x41732c71397757f8), + (0x3e0638226ce0b938, 0xc178893fde0e6ed7), + (0xbe09d8dc4e7930ce, 0x417066abe24b31df), + (0xbde152007ee29e54, 0xc150531da3f31b16), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcd0d33e9e73b503, 0xc0496f5a09751d50), + (0x3d2f9c44a069dc4b, 0x40934427187ac370), + (0xbd69e2e5a3618381, 0xc0d19983f74fdf52), + (0x3d88c69a62ae8b44, 0x410524fcaa71e85a), + (0xbdc0345b806dd0bf, 0xc13120daf531b66b), + (0xbdd35875712fff6f, 0x4152943a4f9f1c7f), + (0xbdf8dd50e92553fd, 0xc169b83aeede08ea), + (0x3e0800ecaa77f79e, 0x41746c61554a08ce), + (0x3dd74fbc32c5f696, 0xc16ba2febd1932a3), + (0x3dc23eb2c943b539, 0x413574ae68b6b378), + (0xbd95d86c5c94cd65, 0xc104adac99eaa90c), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let mut e = i0_exp(dx * 0.5); + e = DoubleDouble::from_exact_add(e.hi, e.lo); + let r_sqrt = DoubleDouble::from_rsqrt_fast(dx); + let r = DoubleDouble::quick_mult(z * r_sqrt * e, e); + let err = f_fmla( + r.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3ba0000000000000), // 2^-69 + ); + let up = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if up == lb { + return r.to_f64(); + } + i2_asympt_hard(x) +} + +/** +Asymptotic expansion for I2. +I2(x)=R(1/x)*Exp(x)/sqrt(x) + +Generated in Wolfram: +```text +<120] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn i2_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc42299e_a1b28468_3bb16645_ba1dc793_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -123, + mantissa: 0xe202abf7_de10e93f_2a2e6a0f_af69c788_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xf70296c3_ad33bde6_866cfd01_0e846cfc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -113, + mantissa: 0xa83df971_736c4e6c_1a35479b_ad6d9172_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0x9baa2015_9c5ca461_0aff0b62_54a70fdb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -106, + mantissa: 0xc70af95d_f95d14ad_1094ea1b_e46b2d2f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -103, + mantissa: 0xa838fb48_e79fb706_642da604_6a73b4f8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -101, + mantissa: 0x8fe29f37_02b1e876_39e88664_1c8b3b5d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -100, + mantissa: 0xc8e9a474_0a03f93a_16d2e7a9_627eba4e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -95, + mantissa: 0x8807d1f6_6d646a08_8c7e8900_12d6a5ed_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -93, + mantissa: 0xe5c25026_97518024_36878256_fd81c08f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -91, + mantissa: 0xeaa075f0_f5151bed_95ec612f_ab9834a7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0x9b267222_82d5c666_348d7d1d_0fedfba4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -88, + mantissa: 0x81b45c4c_3e828396_1d5bdede_869c3b84_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xf4495d43_4bc8dba6_42bdb5d6_c8ba2c9c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -90, + mantissa: 0xc9b29546_0c226270_bb428035_587b6d6a_u128, + }, + ]; + static Q: [DyadicFloat128; 16] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -121, + mantissa: 0x89e18bae_ca9629a1_26927ba2_fbdd66ab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0x92a90fc2_e905f634_4946e8a0_dd8e3874_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -112, + mantissa: 0xc1742696_d29e3846_3e183737_29db8b68_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0xabf61cc0_236a0e90_2572113d_fa339591_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -105, + mantissa: 0xcff0fe90_dac1b08e_9a5740ae_b2984fc1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -102, + mantissa: 0x9ff36729_e407c538_cfcea3a7_63f39043_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -101, + mantissa: 0xc86ff6a3_9b803a31_d385e9ea_83f9d751_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -98, + mantissa: 0xb4a125b1_6cab70f3_0f314558_708843df_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -94, + mantissa: 0x9670fd33_f83bcaa7_85cf2d82_c0bf8cd5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -92, + mantissa: 0xd70b4ea5_32fedb9d_78a3c047_05e650f4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -90, + mantissa: 0xb9c7904c_3f97b633_c2c0ad9b_ad573ede_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -89, + mantissa: 0xc2023c21_5155e9fe_6fb17bb2_c865becd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -89, + mantissa: 0xd9400a5e_27c58803_22948cf3_6154ac49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -90, + mantissa: 0x87aa272d_6a9700b4_449a9db8_1a93b0ee_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -93, + mantissa: 0xd1a86655_5b259611_dfc7affc_6ffb0e20_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + + let mut p_num = P[15]; + for i in (0..15).rev() { + p_num = recip * p_num + P[i]; + } + let mut p_den = Q[15]; + for i in (0..15).rev() { + p_den = recip * p_den + Q[i]; + } + let z = p_num * p_den.reciprocal(); + let r_sqrt = bessel_rsqrt_hard(x, recip); + let f_exp = rational128_exp(x); + (z * r_sqrt * f_exp).fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_i2() { + assert_eq!(f_i2(7.750000000757874), 257.0034362785801); + assert_eq!(f_i2(7.482812501363189), 198.26765887136534); + assert_eq!(f_i2(-7.750000000757874), 257.0034362785801); + assert_eq!(f_i2(-7.482812501363189), 198.26765887136534); + assert!(f_i2(f64::NAN).is_nan()); + assert_eq!(f_i2(f64::INFINITY), f64::INFINITY); + assert_eq!(f_i2(f64::NEG_INFINITY), f64::INFINITY); + assert_eq!(f_i2(0.01), 1.2500104166992188e-5); + assert_eq!(f_i2(-0.01), 1.2500104166992188e-5); + assert_eq!(f_i2(-9.01), 872.9250699638584); + assert_eq!(f_i2(9.01), 872.9250699638584); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i2f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/i2f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/i2f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,194 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::exponents::core_expf; +use crate::polyeval::{f_estrin_polyeval8, f_estrin_polyeval9}; + +/// Modified Bessel of the first kind of order 2 +/// +/// ULP 0.5 +pub fn f_i2f(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN + if ux == 0 { + // |x| == 0 + return 0.; + } + if x.is_infinite() { + return f32::INFINITY; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits() & 0x7fff_ffff; + + if xb >= 0x42b7d875u32 { + // |x| >= 91.92277 it's infinity + return f32::INFINITY; + } + + if xb <= 0x40f80000u32 { + // |x| <= 7.75 + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + let dx = x as f64; + const R: f64 = 1. / 8.; + return (dx * dx * R) as f32; + } + return i2f_small(f32::from_bits(xb)); + } + + i2f_asympt(f32::from_bits(xb)) +} + +/** +Computes +I2(x) = x^2 * R(x^2) + +Generated by Wolfram Mathematica: + +```text +<75] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i2f_small(x: f32) -> f32 { + let dx = x as f64; + let x_sqr = dx * dx; + + let p_num = f_estrin_polyeval9( + x_sqr, + f64::from_bits(0x3fc0000000000000), + f64::from_bits(0x3f831469a38d72c7), + f64::from_bits(0x3f2f453dd3dd98f4), + f64::from_bits(0x3ec8af52ee8fce9b), + f64::from_bits(0x3e5589f2cb4e0ec9), + f64::from_bits(0x3dd60fa268a4206d), + f64::from_bits(0x3d4ab3091ee18d6b), + f64::from_bits(0x3cb1efec43b15186), + f64::from_bits(0x3c050992c6e9e63f), + ); + let p_den = f_estrin_polyeval8( + x_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbf82075d8e3f1476), + f64::from_bits(0x3f03ef86564a284b), + f64::from_bits(0xbe7c498fab4a57d8), + f64::from_bits(0x3dec162ca0f68486), + f64::from_bits(0xbd53bb6398461540), + f64::from_bits(0x3cb265215261e64a), + f64::from_bits(0xbc01cf52cc350e81), + ); + let p = p_num / p_den; + (p * x_sqr) as f32 +} + +/** +Asymptotic expansion for I2. + +Computes: +sqrt(x) * exp(-x) * I2(x) = Pn(1/x)/Qn(1/x) +hence: +I2(x) = Pn(1/x)/Qm(1/x)*exp(x)/sqrt(x) + +Generated by Mathematica: +```text +<70] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i2f_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let p_num = f_estrin_polyeval9( + recip, + f64::from_bits(0x3fd9884533d45f46), + f64::from_bits(0xc02b979526807e1e), + f64::from_bits(0x406b1dd3e795bbed), + f64::from_bits(0xc09e43629031ec91), + f64::from_bits(0x40c48c03a39aec1d), + f64::from_bits(0xc0e0f022ccb8807a), + f64::from_bits(0x40f0302eeb22a776), + f64::from_bits(0xc0f02b01549d38b8), + f64::from_bits(0x40dad4e70f2bc264), + ); + let p_den = f_estrin_polyeval9( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc0405a71a88b191c), + f64::from_bits(0x407e19f7d247d098), + f64::from_bits(0xc0aeaac6e0ca17fe), + f64::from_bits(0x40d2301702f40a98), + f64::from_bits(0xc0e7e6c6c01841b3), + f64::from_bits(0x40ed67317e9e46cc), + f64::from_bits(0xc0d13786aa1ef416), + f64::from_bits(0xc0a6c9cfe579ae22), + ); + let z = p_num / p_den; + + let e = core_expf(x); + let r_sqrt = j1f_rsqrt(dx); + (z * r_sqrt * e) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_i2f() { + assert_eq!(f_i2f(0.), 0.); + assert_eq!(f_i2f(f32::INFINITY), f32::INFINITY); + assert_eq!(f_i2f(f32::NEG_INFINITY), f32::INFINITY); + assert_eq!(f_i2f(1.), 0.13574767); + assert_eq!(f_i2f(-1.), 0.13574767); + assert_eq!(f_i2f(9.432), 1314.6553); + assert_eq!(f_i2f(-9.432), 1314.6553); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,631 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::alpha0::{ + bessel_0_asympt_alpha, bessel_0_asympt_alpha_fast, bessel_0_asympt_alpha_hard, +}; +use crate::bessel::beta0::{ + bessel_0_asympt_beta, bessel_0_asympt_beta_fast, bessel_0_asympt_beta_hard, +}; +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::j0_coeffs_remez::J0_COEFFS_REMEZ; +use crate::bessel::j0_coeffs_taylor::J0_COEFFS_TAYLOR; +use crate::bessel::j0f_coeffs::{J0_ZEROS, J0_ZEROS_VALUE}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::{f_polyeval9, f_polyeval10, f_polyeval12, f_polyeval19}; +use crate::rounding::CpuCeil; +use crate::sin_helper::{cos_dd_small, cos_dd_small_fast, cos_f128_small}; +use crate::sincos_reduce::{AngleReduced, rem2pi_any, rem2pi_f128}; + +/// Bessel of the first kind of order 0 +pub fn f_j0(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, |x| == NaN + if ux <= 0x77723ef88126da90u64 { + // |x| <= 0.00000000000000000000532 + return 1.; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // J0(x) ~ 1-x^2/4+O[x]^4 + let half_x = 0.5 * x; // exact. + return f_fmla(half_x, -half_x, 1.); + } + if x.is_infinite() { + return 0.; + } + return x + f64::NAN; // x == NaN + } + + let x_abs = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + let ax = f64::from_bits(x_abs); + + if x_abs <= 0x4052b33333333333u64 { + // |x| <= 74.8 + if x_abs <= 0x3ff199999999999au64 { + // |x| <= 1.1 + return j0_maclaurin_series_fast(ax); + } + return j0_small_argument_fast(ax); + } + + j0_asympt_fast(ax) +} + +/** +Generated by SageMath: +```python +mp.prec = 180 +def print_expansion_at_0(): + print(f"const J0_MACLAURIN_SERIES: [(u64, u64); 12] = [") + from mpmath import mp, j0, taylor + poly = taylor(lambda val: j0(val), 0, 24) + real_i = 0 + for i in range(0, 24, 2): + print_double_double("", DD(poly[i])) + real_i = real_i + 1 + print("];") + print(poly) + +print_expansion_at_0() +``` +**/ +#[inline] +pub(crate) fn j0_maclaurin_series_fast(x: f64) -> f64 { + const C: [u64; 12] = [ + 0x3ff0000000000000, + 0xbfd0000000000000, + 0x3f90000000000000, + 0xbf3c71c71c71c71c, + 0x3edc71c71c71c71c, + 0xbe723456789abcdf, + 0x3e002e85c0898b71, + 0xbd8522a43f65486a, + 0x3d0522a43f65486a, + 0xbc80b313289be0b9, + 0x3bf5601885e63e5d, + 0xbb669ca9cf3b7f54, + ]; + + let dx2 = DoubleDouble::from_exact_mult(x, x); + + let p = f_polyeval10( + dx2.hi, + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + f64::from_bits(C[10]), + f64::from_bits(C[11]), + ); + let mut z = DoubleDouble::mul_f64_add_f64(dx2, p, f64::from_bits(C[1])); + z = DoubleDouble::mul_add_f64(dx2, z, f64::from_bits(C[0])); + + // squaring error (2^-56) + poly error 2^-75 + let err = f_fmla( + dx2.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3b40000000000000), // 2^-75 + ); + let ub = z.hi + (z.lo + err); + let lb = z.hi + (z.lo - err); + + if ub == lb { + return z.to_f64(); + } + j0_maclaurin_series(x) +} + +/** +Generated by SageMath: +```python +mp.prec = 180 +def print_expansion_at_0(): + print(f"const J0_MACLAURIN_SERIES: [(u64, u64); 12] = [") + from mpmath import mp, j0, taylor + poly = taylor(lambda val: j0(val), 0, 24) + real_i = 0 + for i in range(0, 24, 2): + print_double_double("", DD(poly[i])) + real_i = real_i + 1 + print("];") + print(poly) + +print_expansion_at_0() +``` +**/ +#[cold] +pub(crate) fn j0_maclaurin_series(x: f64) -> f64 { + const C: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0xbfd0000000000000), + (0x0000000000000000, 0x3f90000000000000), + (0xbbdc71c71c71c71c, 0xbf3c71c71c71c71c), + (0x3b7c71c71c71c71c, 0x3edc71c71c71c71c), + (0xbab23456789abcdf, 0xbe723456789abcdf), + (0xba8b6edec0692e65, 0x3e002e85c0898b71), + (0x3a2604db055bd075, 0xbd8522a43f65486a), + (0xb9a604db055bd075, 0x3d0522a43f65486a), + (0x3928824198c6f6e1, 0xbc80b313289be0b9), + (0xb869b0b430eb27b8, 0x3bf5601885e63e5d), + (0x380ee6b4638f3a25, 0xbb669ca9cf3b7f54), + ]; + + let dx2 = DoubleDouble::from_exact_mult(x, x); + + let p = f_polyeval12( + dx2, + DoubleDouble::from_bit_pair(C[0]), + DoubleDouble::from_bit_pair(C[1]), + DoubleDouble::from_bit_pair(C[2]), + DoubleDouble::from_bit_pair(C[3]), + DoubleDouble::from_bit_pair(C[4]), + DoubleDouble::from_bit_pair(C[5]), + DoubleDouble::from_bit_pair(C[6]), + DoubleDouble::from_bit_pair(C[7]), + DoubleDouble::from_bit_pair(C[8]), + DoubleDouble::from_bit_pair(C[9]), + DoubleDouble::from_bit_pair(C[10]), + DoubleDouble::from_bit_pair(C[11]), + ); + let r = DoubleDouble::from_exact_add(p.hi, p.lo); + const ERR: f64 = f64::from_bits(0x39d0000000000000); // 2^-98 + let ub = r.hi + (r.lo + ERR); + let lb = r.hi + (r.lo - ERR); + if ub == lb { + return r.to_f64(); + } + j0_maclaurin_series_hard(x) +} + +/** +Generated by SageMath: + +```python +mp.prec = 180 +def print_expansion_at_0(): + print(f"const P: [DyadicFloat128; 12] = [") + from mpmath import mp, j0, taylor + poly = taylor(lambda val: j0(val), 0, 24) + # print(poly) + real_i = 0 + for i in range(0, 24, 2): + print_dyadic(DD(poly[i])) + real_i = real_i + 1 + print("];") + print(poly) + +print_expansion_at_0() +``` +**/ +#[cold] +#[inline(never)] +pub(crate) fn j0_maclaurin_series_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 12] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -139, + mantissa: 0xe38e38e3_8e38e38e_38e38e38_e38e38e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xe38e38e3_8e38e38e_38e38e38_e38e38e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0x91a2b3c4_d5e6f809_1a2b3c4d_5e6f8092_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -158, + mantissa: 0x81742e04_4c5b8724_8909fcb6_8cd4e410_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -166, + mantissa: 0xa91521fb_2a434d3f_649f5485_f169a743_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -174, + mantissa: 0xa91521fb_2a434d3f_649f5485_f169a743_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -182, + mantissa: 0x85989944_df05c4ef_b7cce721_23e1b391_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -191, + mantissa: 0xab00c42f_31f2e799_3d2f3c53_6120e5d8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -200, + mantissa: 0xb4e54e79_dbfa9c23_29738e18_bb602809_u128, + }, + ]; + let dx = DyadicFloat128::new_from_f64(x); + let x2 = dx * dx; + + let mut p = P[11]; + for i in (0..11).rev() { + p = x2 * p + P[i]; + } + + p.fast_as_f64() +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +pub(crate) fn j0_small_argument_fast(x: f64) -> f64 { + // let avg_step = 74.6145 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6299043751549631; + + let fx = x * INV_STEP; + const J0_ZEROS_COUNT: f64 = (J0_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J0_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(J0_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J0_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J0_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x).abs(); + let dist1 = (found_zero1.hi - x).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return j0_maclaurin_series_fast(x); + } + + let is_too_close_too_zero = dist.abs() < 1e-3; + + let c = if is_too_close_too_zero { + &J0_COEFFS_TAYLOR[idx - 1] + } else { + &J0_COEFFS_REMEZ[idx - 1] + }; + + let r = DoubleDouble::full_add_f64(-found_zero, x.abs()); + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(J0_ZEROS_VALUE[idx]); + } + let p = f_polyeval19( + r.hi, + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + f64::from_bits(c[13].1), + f64::from_bits(c[14].1), + f64::from_bits(c[15].1), + f64::from_bits(c[16].1), + f64::from_bits(c[17].1), + f64::from_bits(c[18].1), + f64::from_bits(c[19].1), + f64::from_bits(c[20].1), + f64::from_bits(c[21].1), + f64::from_bits(c[22].1), + f64::from_bits(c[23].1), + ); + + let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[4])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0])); + let err = f_fmla( + z.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3bf0000000000000), // 2^-64 + ); + let ub = z.hi + (z.lo + err); + let lb = z.hi + (z.lo - err); + + if ub == lb { + return z.to_f64(); + } + + j0_small_argument_dd(r, c) +} + +#[cold] +fn j0_small_argument_dd(r: DoubleDouble, c0: &[(u64, u64); 24]) -> f64 { + let c = &c0[15..]; + + let p0 = f_polyeval9( + r.to_f64(), + f64::from_bits(c[0].1), + f64::from_bits(c[1].1), + f64::from_bits(c[2].1), + f64::from_bits(c[3].1), + f64::from_bits(c[4].1), + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + ); + + let c = c0; + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c10000000000000), // 2^-62 + f64::from_bits(0x3a90000000000000), // 2^-86 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return j0_small_argument_hard(r, c); + } + p.to_f64() +} + +#[cold] +#[inline(never)] +fn j0_small_argument_hard(r: DoubleDouble, c: &[(u64, u64); 24]) -> f64 { + let mut p = DoubleDouble::from_bit_pair(c[23]); + for i in (0..23).rev() { + p = DoubleDouble::mul_add(r, p, DoubleDouble::from_bit_pair(c[i])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + } + p.to_f64() +} + +/* + Evaluates: + J0 = sqrt(2/(PI*x)) * beta(x) * cos(x - PI/4 - alpha(x)) +*/ +#[inline] +pub(crate) fn j0_asympt_fast(x: f64) -> f64 { + let x = x.abs(); + + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let recip = if x.to_bits() > 0x7fd000000000000u64 { + DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_div_fma(4.0, x), 0.25) + } else { + DoubleDouble::from_recip(x) + }; + + let alpha = bessel_0_asympt_alpha_fast(recip); + let beta = bessel_0_asympt_beta_fast(recip); + + let AngleReduced { angle } = rem2pi_any(x); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = cos_dd_small_fast(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let r_sqrt = DoubleDouble::from_rsqrt_fast(x); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let p = DoubleDouble::quick_mult(scale, z0); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3be0000000000000), // 2^-65 + f64::from_bits(0x3a60000000000000), // 2^-89 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64(); + } + j0_asympt(x, recip, r_sqrt, angle) +} + +/* + Evaluates: + J0 = sqrt(2/(PI*x)) * beta(x) * cos(x - PI/4 - alpha(x)) +*/ +pub(crate) fn j0_asympt( + x: f64, + recip: DoubleDouble, + r_sqrt: DoubleDouble, + angle: DoubleDouble, +) -> f64 { + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let alpha = bessel_0_asympt_alpha(recip); + let beta = bessel_0_asympt_beta(recip); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = cos_dd_small(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3bd0000000000000), // 2^-66 + f64::from_bits(0x39e0000000000000), // 2^-97 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64(); + } + j0_asympt_hard(x) +} + +/* + Evaluates: + J0 = sqrt(2/(PI*x)) * beta(x) * cos(x - PI/4 - alpha(x)) +*/ +#[cold] +#[inline(never)] +pub(crate) fn j0_asympt_hard(x: f64) -> f64 { + const SQRT_2_OVER_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcc42299e_a1b28468_7e59e280_5d5c7180_u128, + }; + + const MPI_OVER_4: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let x_dyadic = DyadicFloat128::new_from_f64(x); + let recip = DyadicFloat128::accurate_reciprocal(x); + + let alpha = bessel_0_asympt_alpha_hard(recip); + let beta = bessel_0_asympt_beta_hard(recip); + + let angle = rem2pi_f128(x_dyadic); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_sin = cos_f128_small(r0); + + let z0 = beta * m_sin; + let r_sqrt = bessel_rsqrt_hard(x, recip); + let scale = SQRT_2_OVER_PI * r_sqrt; + let p = scale * z0; + p.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_j0() { + assert_eq!(f_j0(f64::EPSILON), 1.0); + assert_eq!(f_j0(-0.000000000000000000000532), 1.0); + assert_eq!(f_j0(0.0000000000000000000532), 1.0); + assert_eq!(f_j0(-2.000976555054876), 0.22332760641907712); + assert_eq!(f_j0(-2.3369499004222215E+304), -3.3630754230844632e-155); + assert_eq!( + f_j0(f64::from_bits(0xd71a31ffe2ff7e9f)), + f64::from_bits(0xb2e58532f95056ff) + ); + assert_eq!(f_j0(6.1795701510782757E+307), 6.075192922402001e-155); + assert_eq!(f_j0(6.1795701510782757E+301), 4.118334155030934e-152); + assert_eq!(f_j0(6.1795701510782757E+157), 9.5371668900364e-80); + assert_eq!(f_j0(79.), -0.08501719554953485); + // Without FMA 2.703816901253004e-16 + #[cfg(any( + all(target_arch = "x86_64", target_feature = "fma"), + target_arch = "aarch64" + ))] + assert_eq!(f_j0(93.463718781944774171190), 2.7038169012530046e-16); + assert_eq!(f_j0(99.746819858680596470279979), -8.419106281522749e-17); + assert_eq!(f_j0(f64::INFINITY), 0.); + assert_eq!(f_j0(f64::NEG_INFINITY), 0.); + assert!(f_j0(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_remez.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_remez.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_remez.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_remez.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1347 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Taylor series expansion for J0 +Generated by SageMath: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = (zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(j0_zeros) +# print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 500; +bessel_j0 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_j0(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RealField(500)(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +def print_remez_coeffs(poly): + print("J0TaylorExtendedSeries {") + print_double_double("a0: ", poly[0]) + print_double_double("a1: ", poly[1]) + print_double_double("a2: ", poly[2]) + print_double_double("a3: ", poly[3]) + print_double_double("a4: ", poly[4]) + print_double_double("a5: ", poly[5]) + print_double_double("a6: ", poly[6]) + print_double_double("a7: ", poly[7]) + print_double_double("a8: ", poly[8]) + print_double_double("a9: ", poly[9]) + print_double_double("a10: ", poly[10]) + print_double_double("a11: ", poly[11]) + print_double_double("a12: ", poly[12]) + print_double_double("a13: ", poly[13]) + print("c: [") + for i in range(14, len(poly)): + coeff = poly[i] + print(f"{double_to_hex(coeff)},") + print("],") + print("},") + + +degree = 21 + +print(f"pub(crate) static J0_COEFFS: [J0TaylorExtendedSeries; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print_remez_coeffs(coeffs) +print("];") +``` +see notes/bessel_j0_taylor.ipynb +**/ +pub(crate) static J0_COEFFS_REMEZ: [[(u64, u64); 24]; 47] = [ + [ + (0x35cabb65251ee9e1, 0xb940904225a2e689), + (0xbc8ac8cc3d6baf81, 0xbfe09cdb36551280), + (0xbc5b50b1160eaa90, 0x3fbba1deea029494), + (0x3c4bc98bcfdb9552, 0x3facfae864368d70), + (0xbc1a87a5513baa19, 0xbf81bb1cbe1a4071), + (0x3bcf770f17b53b67, 0xbf61f992590d12bd), + (0x3ba05111ecddc158, 0x3f315382ba06cc47), + (0x3ba2b3fa2a3da72a, 0x3f06ed3b9f07eb28), + (0xbb46f7b4858b68c3, 0xbed232c77d228ab6), + (0x3b47b12392b6b437, 0xbea1cce302821846), + (0xbab50abcf1097a30, 0x3e67ff99166c20b8), + (0xbad63d3a07c5005a, 0x3e32951bd4726a93), + (0xba9950044640bb2e, 0xbdf5c2c38b2a2783), + (0xba541f8018d200d7, 0xbdbbdc468c1a7eee), + (0xba165a9b127054c4, 0x3d7cd41cf2489ea1), + (0x39d72c6649bda0f9, 0x3d3f70b02016ca26), + (0xb993b90d2d9ac399, 0xbcfd22d8ef92bec0), + (0xb957753210682ee6, 0xbcbbaa35275a6222), + (0xb8d21bc46d19becc, 0x3c77361304109810), + (0xb8d349b7e68b934a, 0x3c33829044877cd2), + (0xb885327d8bda1ea2, 0xbbede8805081c87c), + (0x382f2276708fc7d3, 0xbba68d801b3bad5d), + (0xb8067b24c3fb14b1, 0x3b601bea84e3ff3f), + (0x37a9569e06a99bfe, 0x3b19ff405c2e53c4), + ], + [ + (0x3c62de1143765a96, 0xbfd9c6cf582cbf7f), + (0xb5f60db51e8c7541, 0x395df78c3799704c), + (0xbc52de1143765a6f, 0x3fc9c6cf582cbf7f), + (0xbc3b84c5dde44b4f, 0xbf91f06d14e11e02), + (0x3c27767d96985ea8, 0xbf8b589d1da13905), + (0x3beae1afe730c7c9, 0x3f50f9103cf5b152), + (0x3bd3e8ae8ef24234, 0x3f386445621cc085), + (0x3b8a8903a2c6108a, 0xbefa2a033ccf2705), + (0xbb6859eebd6af12b, 0xbed83a06e30c4109), + (0xbb3d51d443e4c446, 0x3e96a4fd997104b3), + (0x3af99b61d1c76464, 0x3e6ec03c7b7d1357), + (0xbac247e4733f0637, 0xbe295db03343bc40), + (0xba9b3084e57a7079, 0xbdfb1e242e3fafb5), + (0x3a505dc534b67fe8, 0x3db3fa9bccb27d21), + (0x3a20ef6f1892b081, 0x3d8195cae4f67f76), + (0xb9ddf4b73fd307e9, 0xbd3762afe2a6aee9), + (0x398a6dd1d504dc6d, 0xbd017a40c9409365), + (0xb90b1f08ce463e38, 0x3cb52a10c56acb7f), + (0xb8f458d9f512adee, 0x3c7b78e3226aab83), + (0xb88362e957f09f13, 0xbc2e864870efa32e), + (0x3883c3c8d8c9548c, 0xbbf180323daae355), + (0xb84ee7453edcaae1, 0x3ba1f821fbac48d2), + (0x38094473de9ddfb1, 0x3b62580a3d2321cb), + (0x37afb06968799ff5, 0xbb13009d6caab011), + ], + [ + (0x35dbe52d2b337a1c, 0xb9486fd64fd4d5ac), + (0xbc6af17f78e5834c, 0x3fd5c6e60a097823), + (0xbc22c1940b6591bc, 0xbf9f8f72e7a848e0), + (0x3c39226a69688cd8, 0xbfab2150cb41e8c1), + (0xbc0ead94b778456a, 0x3f72f7ffe90256bb), + (0xbbdc44bdbd19f356, 0x3f627e31fe9a9779), + (0xbbc64599a5779ae3, 0xbf26f641f41956f7), + (0xbb948617d08510cb, 0xbf0863f481a43036), + (0x3b680f7f67daa761, 0x3ecad77d748a06db), + (0x3b3cc529a50aa60d, 0x3ea32e6d99c6af7d), + (0xbac1cce367cee3c7, 0xbe62da37e38435b9), + (0xbada187c686c04e7, 0xbe341d72d9392e0e), + (0xba9d2e19dd36e939, 0x3df1d0433d9a0e48), + (0x3a31b2df296572e6, 0x3dbe2f3389aa5fae), + (0x39eecfa6ba4ba8c8, 0xbd78498ffdebd97b), + (0x39d03604efc229e3, 0xbd410477aeae8e02), + (0xb9773b9fe3142404, 0x3cf911a8d777928f), + (0xb957c6801c088821, 0x3cbde68af5af2e98), + (0xb90138809c41f3e6, 0xbc744b38708ab5a6), + (0x38db3cf268b04601, 0xbc350be960e7059b), + (0xb88759fc2b6b9b1a, 0x3bea7a1734099f03), + (0x3834f08a90df154d, 0x3ba84749424dc4da), + (0xb7d2d06b0965e481, 0xbb5c42f208f4edf8), + (0xb7bf8d11d7307b88, 0xbb1812bbeb085f69), + ], + [ + (0x3c7af22d033ee0a4, 0x3fd33518b3874e8a), + (0xb565f8b72bba82bc, 0xb8cc87a125947e43), + (0xbc6af22d033ee078, 0xbfc33518b3874e8a), + (0xbc006437c8a4159e, 0x3f7d34125d59d8ff), + (0x3c276d8715dea5f6, 0x3f880c83bdeee5b0), + (0x3be6843190a13b37, 0xbf4483c20f1cb1cf), + (0xbbb05a9f2f74161a, 0xbf36ffa5fc8cad74), + (0x3b913c314acf400c, 0x3ef2ccf7b21fff81), + (0x3b3475a5e179bf64, 0x3ed796a751f89051), + (0x3b28cd72cc09b73f, 0xbe91e850e4c28d2e), + (0xbb0d842a5a3f172c, 0xbe6e6a49ae425df4), + (0x3ac77dfa876dbcd5, 0x3e254c4387ef6820), + (0xba4ce9bca6cbfb11, 0x3dfb084d1fe8eb86), + (0xba46d58ee64093b4, 0xbdb177e06f295811), + (0x3a2849b6d182b267, 0xbd8198853f279199), + (0xb9d57dcf1658bea4, 0x3d350c2b4db30b56), + (0x39abd4acfcd6f54a, 0x3d0183edbb87358c), + (0xb95012e0c95b80e9, 0xbcb376d168f148ae), + (0x390c67518d849338, 0xbc7b8a6525f06ee6), + (0xb8cd24af389f1494, 0x3c2c8b0bedec138a), + (0x3894158db0bcbb7a, 0x3bf189a730b0f950), + (0xb84a2fbef2679eb4, 0xbba1058c9711525e), + (0xb80049fcdfa04e9b, 0xbb62579aecb57942), + (0x37bdf8b8eca85db7, 0x3b11906f2331b44b), + ], + [ + (0xb5f59a445e01eb06, 0x3950ae6da0547fff), + (0x3c70b85158068ef5, 0xbfd15f7977a772d4), + (0x3c1371b46642a67b, 0x3f900f7fcf183e0d), + (0xbc44d97f9cced450, 0x3fa68b984ec6493c), + (0x3c042ebf64ae5867, 0xbf648e63600d8418), + (0xbbeee6fe2679d992, 0xbf60e0d60385a6f0), + (0x3baeef0b8f617ca9, 0x3f1d796052775aab), + (0xbba7aac03828df95, 0x3f07800bc550673c), + (0xbb5a87dc43504bb3, 0xbec3324842f7d51c), + (0xbb4a6095f3f5ebca, 0xbea30e8cc35f2086), + (0x3ae3bca6d31bd279, 0x3e5ceda479a13c54), + (0xbad0ae4da6548e0c, 0x3e34582cb217a0ff), + (0xba7adb1d4f626b31, 0xbdecade19f5ddb0d), + (0xba5f5d3513abe02f, 0xbdbedafbed1c0060), + (0x3a0b34ecc7b06112, 0x3d743c230e74eaef), + (0x39da767fb508fb46, 0x3d41820d4a511a84), + (0xb98edf1089e10b5b, 0xbcf56d4abf96e195), + (0xb93ff26a999ae6a3, 0xbcbee1c9645e9dcf), + (0xb8e367fc57f02855, 0x3c71b0595f0e1dc1), + (0xb8d180382e6bf1c1, 0x3c35c9767e2c08b3), + (0x387cd5296e5b56a9, 0xbbe76fd0e549a473), + (0xb84bc9a6b0df08ca, 0xbba9294c38de66a6), + (0xb7e02c9e93087d88, 0x3b595008e255e71b), + (0x37b5a3d651bbe212, 0x3b188b36ce9fc633), + ], + [ + (0xbc5052a3a2541c56, 0xbfcff654544ebcd1), + (0xb60528028a348c29, 0x396d15232f36db8f), + (0x3c4052a3a2541b46, 0x3fbff654544ebcd1), + (0xbc1261ff874dd101, 0xbf70c17ff72afae7), + (0x3c123a275592e8f3, 0xbf84b0c5d5da6789), + (0xbbda98843b2d7643, 0x3f394154be70ed46), + (0x3bd7d4055820b3e5, 0x3f34e12c3067bef4), + (0x3b83b9b8d3c54cc7, 0xbee9f32fc25ad134), + (0x3b7dd34ebfa238e0, 0xbed63c5475439cb2), + (0xbb2e2ce103e7ab56, 0x3e8adbafdf1415b1), + (0xbb04326873ff6a93, 0x3e6d601d278516f5), + (0xbaaec485a6d4e24e, 0xbe20eedcab593552), + (0xba8c720226ba7a69, 0xbdfa84fedb589fe6), + (0xba416138f5e356cd, 0x3dacf8e343fe22e2), + (0xba24b409ac564a10, 0x3d81702cfaaee181), + (0x39c7d31ba4d6f537, 0xbd320271d8cdc0c2), + (0x39a6d8840aab3531, 0xbd01797e5ea36c33), + (0xb92966390929c005, 0x3cb10ed3b69b52d3), + (0x391516ca621c4097, 0x3c7b98f43bd2851c), + (0x38b9ad988a829a99, 0xbc297cc12a1feee1), + (0x389015ff3d9a5854, 0xbbf19fe694606f79), + (0xb83de6f88813ef23, 0x3b9edac0e4d9d135), + (0x37c618b3f375f1a3, 0x3b627614b4015fcf), + (0xb797a11ae6442380, 0xbb0fd9f6fd427743), + ], + [ + (0x36182629090c00b9, 0xb981570c6a6c1920), + (0xbc56d72d40e790a3, 0x3fcdc13e66ac2e77), + (0xbc17a0058564d1fe, 0xbf842ff0cdc58463), + (0xbc4ea7eea5885fab, 0xbfa38d1dd8992e04), + (0xbbe0000f328e352e, 0x3f5a55e9b346edc1), + (0xbbf1ad5da345eb7e, 0x3f5e2e16f97d0a81), + (0x3bba0bf2e3bea8c6, 0xbf13dfc3782af205), + (0x3baf57787ba2c01a, 0xbf05ce7f496656d0), + (0x3b554db180ff9e7b, 0x3ebbb178da9c4ac0), + (0x3b4faac66e76c3d4, 0x3ea2346d74940be8), + (0x3afdf2da5b6281cc, 0xbe5612f2e799b732), + (0x3aa72b6634c3ae5c, 0xbe33d79882e5df9f), + (0x3a865e4a580e28bc, 0x3de6dbc112bdb275), + (0x3a5f226492347489, 0x3dbe88c4d898d67e), + (0xba18523fedb5deb4, 0xbd70ad880fc1dc07), + (0x39ce811e88c6c354, 0xbd4180d64e2c6148), + (0xb9932884c5f7b3a4, 0x3cf220941372b04a), + (0x395486256f555b5a, 0x3cbf18a851090945), + (0x3906d76d19d83863, 0xbc6e8dc104a832cd), + (0x38de3ac4d7a1c28e, 0xbc360ce0fa8619a8), + (0xb8723deefb433289, 0x3be494552b1ee19e), + (0x38260b2fc3fa5df7, 0x3ba98e84df559883), + (0x37de2732117b2742, 0xbb56861d006ce503), + (0xb727a6bd23f6ede0, 0xbb18d0646a86c4e8), + ], + [ + (0x3c6c8c66d2e42062, 0x3fcbf3337873a7d8), + (0xb60f0cbcd3444aa6, 0xb964840aa1183331), + (0xbc5c8c66d2e41fc8, 0xbfbbf3337873a7d8), + (0x3bfaea5f363a1a4a, 0x3f66604d91f926ee), + (0xbc24192692d91168, 0x3f8251858011816b), + (0xbbdcdb1275879ace, 0xbf314bc11a32c246), + (0x3bd505487959e0b7, 0xbf32e7decd1f73a5), + (0xbb847a9b71aaa4b6, 0x3ee293b4c9a24966), + (0x3b6e3a2461d917f1, 0x3ed4a6704d05ad0b), + (0x3b124de00e846cdf, 0xbe843ca9b71b6996), + (0x3afc563d5074b0c6, 0xbe6bddfbf35630ba), + (0xbabc60e5bca9317e, 0x3e1aae76737061db), + (0xba871cc918e40357, 0x3df992424643ff62), + (0xba3975292cf7e7a6, 0xbda7aad4b0989b20), + (0xba0b3d3cb2ccb405, 0xbd81051e84a7a409), + (0x39cd31eea0333123, 0x3d2e49ae1a0f5538), + (0xb9a4374f38b86f7b, 0x3d013585a9ad29c6), + (0xb943f3b2e472171f, 0xbcad5c6822190eea), + (0xb91a3dcc41f8b30f, 0xbc7b5bcfa3070c5e), + (0xb8b8722028e41e05, 0x3c2659e1ea7b0928), + (0xb89ccb60dab570a5, 0x3bf18ed1ab836080), + (0xb82cd51c1659b017, 0xbb9b79f386c69ed4), + (0xb80e73ef8d65d07f, 0xbb6274a94c2329fb), + (0x37966592010226ae, 0x3b0c90cd312dc7b4), + ], + [ + (0x35b57b124ca891a6, 0xb9753e82348b36e7), + (0x3c32010996eec73f, 0xbfca701d0f967500), + (0xbc1331fb2bff5f5f, 0x3f7c54b930fef892), + (0x3c442403558772be, 0x3fa17798aa09f11f), + (0xbbf91cbfe50364c6, 0xbf52a2151407dd09), + (0xbbeaf2596c181ca5, 0xbf5b541f829bfb41), + (0x3b96785653f397a8, 0x3f0cc0bda19ffe34), + (0x3b7cc73c0281eea2, 0x3f041f3b0662f49e), + (0x3b50b097e3ffae6e, 0xbeb4b230b114b149), + (0xbb39f756c517f389, 0xbea1223e2bd0689f), + (0xbadb05bfc44ceed1, 0x3e511963968a437f), + (0xbadcfd5e302d5caa, 0x3e32ffb8dedaa0e5), + (0xba7ba82c85c63aed, 0xbde24c47f1c46f85), + (0x3a56063e275fb1ee, 0xbdbda527540ac8ab), + (0x3a042a1749b80056, 0x3d6b75eeb2587187), + (0x39cf0477925a6771, 0x3d412dcf9e14ca72), + (0x3965d39c1b93d637, 0xbcee8dc94e4a47ce), + (0xb94ec20106752176, 0xbcbec6e9eef76922), + (0xb90db7e15209bac8, 0x3c6a411a8f127544), + (0x38d4829603e3c8d8, 0x3c35f7179d3c30ad), + (0x38752bac2edc6ca6, 0xbbe1f8b6ea290920), + (0xb82284d049652280, 0xbba99593860b4ea4), + (0xb7dada6a0b2440d5, 0x3b53ef32d1c66177), + (0xb7baf92eb88ac861, 0x3b18d6a7f6c008d1), + ], + [ + (0x3c6e9557ccd1703f, 0xbfc925c6fca08f55), + (0x35fab5fb9c5380cd, 0x397dd9d8f9235378), + (0xbc5e9557ccd170e3, 0x3fb925c6fca08f55), + (0xbbf0bd4a46186c99, 0xbf6049377403bcb4), + (0xbc1dac1b118906a5, 0xbf809463bbd0367f), + (0xbbbd1ccb59bc25f7, 0x3f297b354706c53c), + (0xbbdfefc73f41d900, 0x3f314dd4404e5fcc), + (0xbb768a017e0a8626, 0xbedbf665d5afcb1e), + (0xbb5562ef116833bd, 0xbed32cb00ee8c1f3), + (0x3b1692f6b84439ce, 0x3e7f50fa815b542a), + (0xbaec0ca08efbeecb, 0x3e6a4339e5f906ee), + (0x3aa7971bb866b080, 0xbe1541c07333f998), + (0xba57a16f0ea87b71, 0xbdf86c0bb112e482), + (0xba36e61435a1cd00, 0x3da35fba37d1f734), + (0x3a1f20691ce23042, 0x3d80700770cc1156), + (0xb9b992380621d60f, 0xbd2963b2030905ef), + (0x3994c48a74316e13, 0xbd00c5877018b95c), + (0x3934c66edb676868, 0x3ca91e0b94a51ae6), + (0x38d882f89d4daaf7, 0x3c7adb6f4a466e65), + (0xb8ce178a661e3146, 0xbc2373e4dad053be), + (0x388de38db781365d, 0xbbf155ead1bcc6e1), + (0xb838caf4a70bed71, 0x3b9843ad83497bad), + (0x380a61496dc04a9e, 0x3b624dcba30b4ca7), + (0xb7a04207f42b18e2, 0xbb0975abfc72009f), + ], + [ + (0x35e086b1188ee76d, 0xb9659deaf309da6c), + (0x3c4a4f96a2520bb6, 0x3fc8077f56c9b782), + (0xbbf97f76587fbf04, 0xbf75467eb535deaa), + (0x3c28681fd3a1f1d9, 0xbf9fd7c3ad6f59e0), + (0x3be0e0f0ccefc77f, 0x3f4c1b47c809c5eb), + (0x3bf6295d17ac5a65, 0x3f59166c7d3eaa7c), + (0xbba4cf4874f894a7, 0xbf05f0152478f5f6), + (0x3ba861e7bdca105b, 0xbf02aa939fd9fc9b), + (0xbb5e0f4929f81ac1, 0x3eb0129708ec2410), + (0x3b439423523353b8, 0x3ea01716dc9f2e1b), + (0x3ad0e7c543b4566f, 0xbe4b227eef409a9c), + (0xbadfc64557b91f43, 0xbe32101c49d611c3), + (0x3a7be06eedb88596, 0x3dddb1e8b7adba58), + (0x3a037d51b581b88f, 0x3dbc80aab1d93238), + (0x3a04fb2f6b0c475b, 0xbd66c2b17ab70f1a), + (0xb9e88a8587ab97a1, 0xbd40ad5f60b5515a), + (0x398a5248c0478c2e, 0x3ce9d02ffd43b4b6), + (0xb92666b9cd4e8f2b, 0x3cbe1eda1d7f5a91), + (0xb8f1b085dd83117e, 0xbc668e7624b57aed), + (0xb8d7b1a60f9f9ddd, 0xbc35a3dd86c4185f), + (0xb803b25228593cc6, 0x3bdf559780a6bb0e), + (0x382586b97e4f1ff9, 0x3ba957aa7a9d5cb7), + (0xb7ed5614f18b6bf3, 0xbb5198d0c1cebd10), + (0xb7a8382c4740132b, 0xbb18a72411fe5ccf), + ], + [ + (0x3c62da0057f84d3b, 0x3fc70c511227d5aa), + (0x360a5b28d6094082, 0x397cbdb54d06802e), + (0xbc52da0057f84c9a, 0xbfb70c511227d5aa), + (0x3bfe726f7024dd2d, 0x3f5910ebe1f1cbcd), + (0xbc0e61277df378de, 0x3f7e7dc08e70e99a), + (0x3bb740aae8c42ea9, 0xbf23bd7d159e09a5), + (0x3bc9abf1335e8790, 0xbf300357a187375c), + (0x3b7cab6494ed67eb, 0x3ed5ec73302455b1), + (0xbb76a67dea84dca0, 0x3ed1e5d2836c8d99), + (0xbad181196d149707, 0xbe78f41b94dfba1f), + (0xbafeb3021d837aa6, 0xbe68c11aada79ae8), + (0xba8510c3ac160a0a, 0x3e1141423452a28d), + (0xba892fee369915f4, 0x3df73ef6f4772770), + (0x3a3b488b50613a1c, 0xbda007403efd2ccd), + (0x39f5bf6b3205778c, 0xbd7f93ab666786fa), + (0x39cec570d9db2fc3, 0x3d25638d0e0e19b5), + (0x3992830e7334f62d, 0x3d003d05920debc7), + (0x3928fcb1f53c1973, 0xbca5832b6cec0d11), + (0x3905c27fab0794dc, 0xbc7a2e88dfea664c), + (0xb888ccbe8e25c424, 0x3c20e8847ee36bf7), + (0xb88b102ba2ef2315, 0x3bf0ff53969fee86), + (0x380e372a38bcf693, 0xbb955dc67acbb8c1), + (0xb7f237d40b294b7a, 0xbb62083f7d27b5d9), + (0x377966f003d521c9, 0x3b06a16c733cdfe2), + ], + [ + (0x36043fe2f5037bf7, 0x39714ccaaa6fb0d5), + (0xbc6444d3d89ac012, 0xbfc62d93aa9d05bb), + (0xbc1afb8f729bef14, 0x3f70ba9ce88929f2), + (0xbc2f64ee23828443, 0x3f9d7073daebb02c), + (0x3bd6ad884b6c9520, 0xbf462813c7f58733), + (0xbbc1c5da6149803a, 0xbf574a948d05638e), + (0x3ba7816473a6692a, 0x3f01695765f13bbf), + (0x3b9157b6b65ca494, 0x3f0170ab5eeb0e4e), + (0x3b2716b17d28be20, 0xbea9c8e418a20315), + (0x3b394c2374daaa73, 0xbe9e4d893dce335e), + (0xbaef0ae11c684392, 0x3e460f73a6ccb16f), + (0x3ad9ae1edaadae80, 0x3e312782f0f2448a), + (0x3a51af0d933062c5, 0xbdd881d5842ec66b), + (0xba56bb5ed05dc669, 0xbdbb4c521a31613b), + (0xb9fae678b88ed7b7, 0x3d63132da6b9e700), + (0x39d7ed04f36de95b, 0x3d4019364d866ae6), + (0xb97cfaa457ac4250, 0xbce5f4ab6157e7be), + (0x394e31d3157f8b40, 0xbcbd47ca9a1247cb), + (0xb90d596ff8cf14c9, 0x3c6373719443eb4a), + (0x38d15089179a9756, 0x3c352a81aa5252ec), + (0x387db4c0fd37289a, 0xbbdb5bf6bb6be367), + (0x384ae6b921aecd05, 0xbba8eb04a93528a2), + (0xb7e3e44a16c09699, 0x3b4f12507c54bef3), + (0xb7b95db3cb024c97, 0x3b184f56b858ed01), + ], + [ + (0x3c6a47ab4241a9f5, 0xbfc5664e13b70622), + (0xb5f760d6e0df5525, 0xb96a27b55db95023), + (0xbc5a47ab4241aa99, 0x3fb5664e13b70622), + (0x3bddc134f1d56911, 0xbf540ee3940b092f), + (0xbbffe75afd61d48d, 0xbf7c5e1ad9fb2f40), + (0xbbab8661007349b1, 0x3f1fb8a98ef4a243), + (0xbbc018bee0f9b515, 0x3f2de9be58a373e2), + (0xbb75089c8e88074b, 0xbed1bec95415e630), + (0x3b44800f434e8417, 0xbed0cf264341409e), + (0x3ac78de205cc4cd6, 0x3e74677d9e214cd4), + (0x3b022bc30f064717, 0x3e6766cc63507104), + (0xbaa2f651c24f2d57, 0xbe0c905882b94f65), + (0x3a9112b75a40b2a8, 0xbdf62157963573da), + (0xba20399ceae10199, 0x3d9ae2e0cbb67b5c), + (0x39ff975d6442b115, 0x3d7e456a1c8db625), + (0xb9a84aef2f5c2b19, 0xbd222e473663eea9), + (0x399ffbe46660f083, 0xbcff56a09d8cd619), + (0x393107311db89703, 0x3ca28607cd9d833f), + (0x391393d18c89b7c0, 0x3c796a2f1da7d934), + (0x38935c8a666a0b0e, 0xbc1d78e9ab2b3109), + (0x386087d39d98f4be, 0xbbf096321470c83b), + (0xb831ea93ce0d9c89, 0x3b92d4333620b1e7), + (0x37b11cc0e6a17b7a, 0x3b61ad4cac5f830d), + (0xb7932d42d34590f1, 0xbb041e3c367ed3b2), + ], + [ + (0x35fb617f2a7d3e44, 0x39534fd9c53767f3), + (0xbc6e5d93454f99e3, 0x3fc4b2a2ebf61ece), + (0x3bf37b02bd5f62b0, 0xbf6b3297fdae7902), + (0x3c2eb354a631372f, 0xbf9b8105d59b114c), + (0x3bb9bab613407fc9, 0x3f420a3f8c12a1ff), + (0xbbf48ec1e2f4d8eb, 0x3f55d18d69de6cfb), + (0x3b0ad3357483176b, 0xbefc79db4b341e8e), + (0x3b70c0983bb2f771, 0xbf00679c92c303b2), + (0xbb4af53c2daf664b, 0x3ea53ac4ecd4be2d), + (0x3b3bd8bfa73be7aa, 0x3e9ca7507840c04b), + (0xbadae384e855ecf8, 0xbe4253415f09767a), + (0x3a835115b77c34b2, 0xbe305141505c9f00), + (0x3a6c4c5d652bb599, 0x3dd4919940f05334), + (0xba58b3871fdc4174, 0x3dba20de95780e2b), + (0xba0a69548bda3e7f, 0xbd602fff3daab710), + (0x39d417d75702d45d, 0xbd3f01d18581c5a9), + (0xb9753674cf72aa69, 0x3ce2d78e0d8458c3), + (0xb9203e6bf52424e4, 0x3cbc5cc76fd7614d), + (0xb8f39cb8f8a8d557, 0xbc60e0077908e478), + (0xb8cd5838286ea7a4, 0xbc349c9cfabd7bb7), + (0x381968d8765f42f8, 0x3bd7fb4989ff942e), + (0x3844cfbad0863c18, 0x3ba861a8f70eebaa), + (0x37deeff465dec1db, 0xbb4b7ea330f8d706), + (0x37bb0df82dbf52ea, 0xbb17dc3e59fbd2b3), + ], + [ + (0x3c6316f8ffd294bc, 0x3fc40f90793605bb), + (0xb5bc63171f8ad7f8, 0xb95cae2e73fe7fb0), + (0xbc5316f8ffd29417, 0xbfb40f90793605bb), + (0x3bf7017919c19ee3, 0x3f5085775a5529c9), + (0xbbe51eb6f0b3a2c8, 0x3f7aa0ce0421d1a8), + (0x3bb34ca5a9d8eee5, 0xbf1a32a28e4bc82e), + (0x3b829f8e74c703e7, 0xbf2c26ebca0e46de), + (0xbb655ef820b8ed31, 0x3ecd7400876206d0), + (0x3b4cb530be3f4c97, 0x3ecfc1bbf57e3ae2), + (0xbb1b043cc6acf5d6, 0xbe710c7090487d3e), + (0x3af031f8178d9744, 0xbe6634db39e4a305), + (0xbaad7fb323c3df7f, 0x3e0810d7e4efab4a), + (0xba9ee3d784feb6b0, 0x3df51b513b3c4cef), + (0x3a2790b6bc250dd4, 0xbd96dd877beb37bf), + (0xba19b6fbdfe4281c, 0xbd7d06057acf8fa0), + (0x39a09d743019f4e9, 0x3d1f3b007c5421d0), + (0xb994cbeda4661eeb, 0x3cfe3418121e09f1), + (0x394f465df58cfe59, 0xbca0119136910e8f), + (0xb91cf9a0016f1fe5, 0xbc789daf5f18a5af), + (0xb8a09684e33e70bf, 0x3c19d09d89e3d4e7), + (0x389e2b54b001cc6c, 0x3bf023a06c8fea08), + (0x382b986bb50f84de, 0xbb90a4fdf6b47d26), + (0xb7fdb60c46ef0002, 0xbb614563ff0bb2b8), + (0x37a20bcc61b90c31, 0x3b01ebc30518711a), + ], + [ + (0x35f3364fd9d34cb1, 0x397482cca2804d57), + (0x3c5948539688f9cb, 0xbfc37aac8c1aeabb), + (0x3c0e1b9871576171, 0x3f66ac0d2e2f2f87), + (0xbc3e2c9f8f0de37f, 0x3f99e74e754ea71f), + (0x3bc834f162077a01, 0xbf3e1c0589e32bb1), + (0x3bfe8b15bd171deb, 0xbf5496158dc5f7ff), + (0x3b66422ba8f591b3, 0x3ef7d55405348ca9), + (0x3b913888244cb67e, 0x3eff0b30f4506228), + (0xbb49c57ec3fb6664, 0xbea1d9e3629b98ec), + (0x3b31cbbb1f5801f4, 0xbe9b35ef28e9de24), + (0x3ac3a4c0891c58de, 0x3e3f0200e2650870), + (0xbacbfc59e2173110, 0x3e2f1fb225e849cb), + (0xba74d0e4dbfc0552, 0xbdd187928a64d03e), + (0x3a28ff960c8419c5, 0xbdb908ba84482af5), + (0xb9fd78b0c3058f80, 0x3d5bd0a97427d7c2), + (0x39b4f3422c873b72, 0x3d3dd98a1888d3c4), + (0x398676253f0dc67e, 0xbce05368fda435c7), + (0x3954262b278fb382, 0xbcbb6e7eba338096), + (0x38f1da524082e61d, 0x3c5d7e5c6064299d), + (0x38dbb3c7ca9d7c4a, 0x3c34063c1ddae8bd), + (0x387e4fa2050cb586, 0xbbd521e70bcccf02), + (0xb83b4d316015135a, 0xbba7c8f868314c63), + (0xb7a6a57c7316cadd, 0x3b486ba7bc735663), + (0xb76268b35420b1c6, 0x3b1758996990291d), + ], + [ + (0x3c689d1f48185c7e, 0xbfc2f2072e638cf4), + (0xb5ed38c4f6890952, 0x394461aeca52479d), + (0xbc589d1f48185d20, 0x3fb2f2072e638cf4), + (0x3be64a78bbba5f88, 0xbf4bd42b64fc5bed), + (0x3c082c4cf0185189, 0xbf792bb5e1e159fc), + (0x3ba0f7052d2216a4, 0x3f161ace3386dfd7), + (0xbbc911bb7e9afeac, 0x3f2aa8d1cf8db852), + (0x3b53e6d52ff3d031, 0xbec8ef624c36fc32), + (0x3b54f2165ec886a8, 0xbece26d3747fe829), + (0x3b0ba49dcf5f6fd0, 0x3e6d010d2bdb6fa2), + (0xbb091b80aed15c31, 0x3e65272828ae4057), + (0xba8eb72fbfdc3a74, 0xbe0497b03c4482e4), + (0xba9363f2627d714a, 0xbdf42e35495a0b9c), + (0xba32072f1fd852bb, 0x3d93b2e62efa9f34), + (0xba1e4f176dd7ecab, 0x3d7bdc7867dad736), + (0xb990e20c6ed58c22, 0xbd1b1acb454d4a67), + (0xb99fc3000cfbbd47, 0xbcfd1ce799670eb9), + (0xb92e5f75bbb7af1c, 0x3c9c1b1fc9d584de), + (0xb91578e77423719c, 0x3c77d2b95397d836), + (0xb850bafe09573a49, 0xbc16c0325b1f55bb), + (0xb870fccd3a2e4892, 0xbbef5c231492c633), + (0xb81afdc499b9ae20, 0x3b8d8f129e22a179), + (0xb80d2a72cf226d5a, 0x3b60d71423839ff2), + (0x37a376b0e7e390a2, 0xbb0004820cb21317), + ], + [ + (0xb5fe7034a738c57f, 0xb965d89919797608), + (0xbc389c717cff1eb2, 0x3fc27407dfadee6d), + (0x3c01b3998e256aba, 0xbf6346950bfd91f1), + (0x3c3dd532243e7bdf, 0xbf988d48d1d4eb7b), + (0x3bcf03d11acc3cef, 0x3f399e6923ada922), + (0x3bf2c9a985d24428, 0x3f538984b76cdf4a), + (0x3b96fc0cd00a1e02, 0xbef452194b75f3c7), + (0xbb929abb89c807a0, 0xbefd855d7b8f0243), + (0x3b33da403d28aa47, 0x3e9e8a88601ff296), + (0x3aebbce16fe837d2, 0x3e99f1bd69b16e6b), + (0x3ac9d47900ce737a, 0xbe3aa483fce054e3), + (0x3ac5507ea35951eb, 0xbe2dc4c02391c504), + (0x3a50d4172d38a515, 0x3dce48dc1b4db78b), + (0xba5adebc7a9a6eae, 0x3db807112e663700), + (0x39be45131e2d0e10, 0xbd582c0e5f51a78c), + (0x39d352a7d1eff8f8, 0xbd3cc1592707ba1f), + (0xb97498b39d0e69d4, 0x3cdc8f29e77a7dbc), + (0xb95f8164e5aa870e, 0x3cba864ef2011d61), + (0x38d4d82995e917f3, 0xbc59f854a17b0eb3), + (0x38c2b397d698e08f, 0xbc336efc952890f2), + (0xb85e61d1aea7560f, 0x3bd2bbab562fd018), + (0x3844a8bee87edfd3, 0x3ba72a2cd621b87c), + (0x37b0634af3b51b0d, 0xbb45ca2b0c668e28), + (0xb786436234762b46, 0xbb16cc8b2df45666), + ], + [ + (0x3c51f9b16832f362, 0x3fc1ff5eec6a01cd), + (0x3608538a42387313, 0x39703f488735c3d2), + (0xbc41f9b16832f226, 0xbfb1ff5eec6a01cd), + (0xbbe5f2ed43d916df, 0x3f47daf64983af9d), + (0xbc19a4b7b3f004ae, 0x3f77ed5fffc1c774), + (0xbbafa9d6f36c74e4, 0xbf12f947962314a1), + (0x3bba27856fb2a3d9, 0xbf296027ea1d6e5c), + (0xbb585d62c36dd030, 0x3ec57486c67fbc78), + (0x3b6dbac7c03738c9, 0x3eccc11a59e13739), + (0x3b07e8342468c4ca, 0xbe690ade515567ae), + (0x3aff414d51e7ab0e, 0xbe6438a7e22c9734), + (0xbaac64a5bfb76d87, 0x3e01db6d29a7d049), + (0xba7a7ab522e094b3, 0x3df3588cd2990098), + (0xba353be57bfdf484, 0xbd912b3d3f46a156), + (0xba024df787236d46, 0xbd7aca95934e0225), + (0x39b4eea5a63388b9, 0x3d17c19e5c2accea), + (0x399da5ae5c22cafa, 0x3cfc15e96b11e6a8), + (0xb91064ad2d23f659, 0xbc98c7e06936a2ce), + (0x391a3907b000a135, 0xbc770ecfa1a29de4), + (0xb8a29f60e2d525d6, 0x3c142e96cdb6412a), + (0xb84a16ff92e47bb9, 0x3bee735a654a68e5), + (0xb8292e46bf7abeaa, 0xbb8a61d3cc01d06e), + (0x37f75c146bd04a11, 0xbb6066ff09d84644), + (0x3799d2dbdc6509c3, 0x3afcc034864d659f), + ], + [ + (0xb5eb961d9912b9a7, 0xb9682c6f4767341f), + (0x3c6f5f4b08a76fd4, 0xbfc192f23ce3e051), + (0x3bdee957b8601e17, 0x3f60a668185c01b1), + (0x3c39de5fb6906b20, 0x3f9764141d652089), + (0x3bd0a73bf174fe85, 0xbf3624437a2fe76a), + (0xbbe29f0dad78a87f, 0xbf52a184be0d9891), + (0x3b9224756b415cd4, 0x3ef196de0eeef190), + (0x3b54bbcaa68c5293, 0x3efc317f854112ad), + (0xbb3c48e804e50119, 0xbe9a8019ef772196), + (0x3b1fa8a6e09c6db9, 0xbe98d38497beea33), + (0x3ad0d50082f534e7, 0x3e37318410813eeb), + (0xbaa0ab33bf6dee66, 0x3e2c8d9d45d76323), + (0xba5370b8aa12ac53, 0xbdca782c1acc5d79), + (0x3a50c665c12ff6de, 0xbdb71bbb74f830ec), + (0x39efa2e983abd5aa, 0x3d5539502b6b020f), + (0x39c79df656360a67, 0x3d3bbc22cd6efb9f), + (0xb97de689090afaa9, 0xbcd933a6400afa8f), + (0xb9538df7643bec5c, 0xbcb9a8f9bcb96916), + (0xb8f3ea053f8219b5, 0x3c5709ca7b2dbe67), + (0x38aaa5e94cc9a9ff, 0x3c32db59b4212a49), + (0x3875dd42a8ae8eb2, 0xbbd0b55ba2bce2af), + (0x384f96f41944caf5, 0xbba68b427859d5fc), + (0x37ed698b1a87de93, 0x3b438a193d38c988), + (0x37becfa942bd3543, 0x3b163dbcc0f4e249), + ], + [ + (0x3c6e71c482be67be, 0xbfc12dd57bf18ada), + (0xb56ade05c8d02fe1, 0xb8f86dd1ee1cd4b8), + (0xbc5e71c482be685a, 0x3fb12dd57bf18ada), + (0x3bd11b1ac52c9e63, 0xbf44bebeff7b7f02), + (0xbc1286f932bc06e0, 0xbf76d9afe88301fa), + (0x3b859ae05ee9b9e1, 0x3f10842d50687949), + (0xbbc5025e9c48ddf7, 0x3f2841d86b9b92f4), + (0x3b45bc8a5bed0a88, 0xbec2b5caad1f2b9a), + (0xbb3770fdeb5f4fdb, 0xbecb86bad42fc220), + (0x3ac419e306d0b4f6, 0x3e65e5117a965bcf), + (0x3b0715f2ca682ea9, 0x3e6364a25cc7309d), + (0xba8789a8788b4eb8, 0xbdff53dcc9459e76), + (0xba7a9cb0ee97c39b, 0xbdf297f421bb27b9), + (0x3a21251ff8e8e5fd, 0x3d8e3c9c7289c6c0), + (0xba04a1e2968b5e32, 0x3d79cfbae2bdb794), + (0x39a8e2edbbc6a796, 0xbd1502858f3b96b9), + (0xb99b52142daa6d4d, 0xbcfb20c42e50d24c), + (0xb93206530eead3e5, 0x3c9604b999fb92e6), + (0xb91d665f1b08d083, 0x3c7654b9ed136fab), + (0x38820031c752db33, 0xbc120524ce30eaa4), + (0x387abcba8637daf2, 0xbbed91d6a951e05e), + (0xb811548ed562e5dd, 0x3b87ac7727dd5787), + (0xb7df152483a30c1d, 0x3b5ff0620f1479de), + (0x37930d38ec1cefd3, 0xbaf9eb53c9bb31d6), + ], + [ + (0xb5b3453ff73e0bdd, 0x393fd7d1a10c14b9), + (0x3c53f099a5f56db3, 0x3fc0cf3ed059c573), + (0xbbff3cb9b807f03b, 0xbf5d242aa529931c), + (0x3beb544962a1902a, 0xbf96613d93b0180b), + (0x3bde039e228ed279, 0x3f33627f261f5116), + (0x3bf7fb39963e2efc, 0x3f51d69ca0d88394), + (0xbb384fc08b8a0bbe, 0xbeeed574afab70fd), + (0xbb95a4431994f7ed, 0xbefb06384e48ee5b), + (0xbb387c5180387ee8, 0x3e97452c65235728), + (0xbaf8807a182da1e9, 0x3e97d51f133b6843), + (0xbad80ae2bd8213ae, 0xbe346ac67a7e0c7c), + (0x3ac7244b550b1780, 0xbe2b75d66a8d7fbb), + (0x3a669cb8e5bcff01, 0x3dc75f5a5db478e9), + (0xba5afd0a5423da82, 0x3db64531ca4ef465), + (0xb9fa4a2410291e1f, 0xbd52ceac14a86241), + (0xb9d685e38c55ad6c, 0xbd3aca497ff207d0), + (0x39542d374b775a5a, 0x3cd66b96eb099cc5), + (0xb9597fd736e29864, 0x3cb8d889b2e1f475), + (0x38e51f4f682fb00a, 0xbc5494fef4e26442), + (0xb8cc652bba3e525d, 0xbc324dc25f106529), + (0x380c5c0722c461e5, 0x3bcdfc3c890260b7), + (0x38473d4459e77144, 0x3ba5efe49281d368), + (0x37d76e1dde8d0fdc, 0xbb419c5b516958d8), + (0xb7a6d50e7f01d17c, 0xbb15aff74e510abf), + ], + [ + (0x3c61a13e2fee5687, 0x3fc076826cc2c191), + (0x35fbed7a3ebfda21, 0xb970a6aa5adc8d66), + (0xbc51a13e2fee55ee, 0xbfb076826cc2c191), + (0x3be79f62aa4912e7, 0x3f4241b03eaaf5d9), + (0xbc15dbe9d7239a1e, 0x3f75e7f53001e4b1), + (0x3ba5f4ab60853145, 0xbf0d17978e2d0336), + (0xbbb79a682db866ff, 0xbf2745b0df80666a), + (0x3b63b65170c03680, 0x3ec0803f7f7fe323), + (0xbb5016bca9a839cb, 0x3eca7006e6ad9cfe), + (0xbb09b83b761c8dad, 0xbe63590d57d48525), + (0xbad1e26a947a9c23, 0xbe62a7084b42b890), + (0x3a87e1ccce8475a5, 0x3dfbc0dd5a22c9a6), + (0x3a7031ad9111bbe1, 0x3df1e9e4e20477ca), + (0x3a2e94263a9c2435, 0xbd8ade1de2460f0e), + (0x3a12379dba208e28, 0xbd78ea3bc5e5158b), + (0xb9b0319572048e91, 0x3d12bb86a88d447a), + (0x399493366981bd01, 0x3cfa3d6bcabdd7ff), + (0xb936ae36a8b153bc, 0xbc93b47615e29aea), + (0x391e0fe4bfd67f75, 0xbc75a597f7583751), + (0x38b24cb1a71df570, 0x3c1030bba99bb5cc), + (0x387b1b9ba6d62368, 0x3becba423ca5f9ce), + (0x37e762b30a8a5a4c, 0xbb855b595b5871b2), + (0x37f25ff71c04c351, 0xbb5f1916ebc1bb1a), + (0xb79220ba6f90a9af, 0x3af7791a566a7a85), + ], + [ + (0xb60c6a70e175e648, 0x39735f9916d9837d), + (0x3c665439df5bb54b, 0xbfc0230b9797a7b3), + (0x3bd7d914863d8b85, 0x3f59c8083b2b753a), + (0xbc3c455b2fe15157, 0x3f957d3203befd90), + (0xbbd3de5214d61226, 0xbf3127cba22892de), + (0x3bf0c5ff9d68abde, 0xbf51234471455a6c), + (0xbb8a9c283025b635, 0x3eeb4fe26ec3e489), + (0xbb9cd17c61f89721, 0x3ef9fc5254f1086c), + (0xbb3a464f70c3c823, 0xbe94a44c6506c43f), + (0x3b3f504de9997bea, 0xbe96f17dd184ad59), + (0x3a90aecf258a5953, 0x3e3225640a6a9328), + (0xbab85c7b0680994b, 0x3e2a7943505d15ed), + (0xba6cf77c6abfe37c, 0xbdc4d296ecea7b5b), + (0xba3e0d08073ac67f, 0xbdb58177059b1ee7), + (0x39fe64bae160ea42, 0x3d50cd71be541f6c), + (0xb9de66ddc4c43f8f, 0x3d39eafac486df97), + (0x397f8cdc2afe705d, 0xbcd417df1a7faedc), + (0xb9481c4ab05db957, 0xbcb81583d8826b2f), + (0x38d9d79064997308, 0x3c52822e1fc6fcbb), + (0x38d8493a5a515ee9, 0x3c31c75f9746b7f8), + (0xb85d87e0134de425, 0xbbcb0fab39bb8bfe), + (0xb830a586be8798a7, 0xbba55a2deec91831), + (0xb7d2c2b65fcec4b3, 0x3b3fe74d126342bb), + (0xb796cef3b221776c, 0x3b15259d7309762d), + ], + [ + (0x3c5d7cc4171715a0, 0xbfbfa8b41711c83a), + (0xb60ba9b9f91fb8b5, 0xb966589e13c65233), + (0xbc4d7cc4171716ca, 0x3fafa8b41711c83a), + (0x3bca510f3e4d422a, 0xbf403a8d0f110fe1), + (0x3c195ccf34ff059f, 0xbf7511c6dadaaa12), + (0xbb6fad55d0eb473e, 0x3f09e040fc62c87e), + (0x3bb45c7340135a79, 0x3f266582f66d8d4c), + (0xbb2c8a3f0d0d8730, 0xbebd62a18e287536), + (0x3b667f97c31286c8, 0xbec976fb023f0f79), + (0x3b0f3da3b757dc00, 0x3e6141188eda6cd5), + (0x3afa50d6da64db1a, 0x3e61fc77546c2a70), + (0xba85cd99748ec679, 0xbdf8ccadf7842b28), + (0x3a8f0a159918c910, 0xbdf14c0515097ba8), + (0x3a267994041e70e6, 0x3d8810b7fe5b7b00), + (0x3a19f29d974623dc, 0x3d781814784424c6), + (0xb98d0230bc946bce, 0xbd10d30b1ed751e4), + (0xb97b8f89dea8e8b4, 0xbcf96afe8202dbff), + (0x39286258642b03cd, 0x3c91c038ce19ab04), + (0x38e5014a0308a5f1, 0x3c750195ff9477a1), + (0x3877348a77be6ba1, 0xbc0d437455c82ee5), + (0xb8854f0f0926b218, 0xbbebedd520bd61e5), + (0x3802b652644462a2, 0x3b835da91ec0fb79), + (0xb7f3b739a177a033, 0x3b5e4a41b6b72b80), + (0x376f5eb22e1b1ed0, 0xbaf55a9e0c921524), + ], + [ + (0x361a1ce3816c12e9, 0xb970a7cb3e4926ce), + (0x3c581bdf89b0a8b3, 0x3fbf13faf32c8e0a), + (0xbbee91046256adc2, 0xbf570558dddb7d46), + (0xbc326d6d43908d73, 0xbf94b24d7a933972), + (0xbbb5423c2dd21ed6, 0x3f2ea52a21487a11), + (0xbbf33353f1356cea, 0x3f50834d8f3fdd5b), + (0x3b8f2ed187ec8c27, 0xbee86941a4b43bea), + (0xbb93d844185ba20f, 0xbef90e32cef3e900), + (0xbb24c412e1beda17, 0x3e92785f6385b273), + (0xbaf58ee8d31f36a8, 0x3e962482bf9d2bb8), + (0xbaaf8eeab1cf99c8, 0xbe3043125386ac84), + (0x3acbaa01c1b653ac, 0xbe29943c303e31c2), + (0xba66220f22c18b8e, 0x3dc2b2457a1921af), + (0x3a5711c244de4ccd, 0x3db4ce82afcbf543), + (0xb9d04d4e5a872347, 0xbd4e3dcde42d3546), + (0xb9df1485d764cf0a, 0xbd391cdf33ca545f), + (0x397020766d9e2bc7, 0x3cd220c06f47b251), + (0x3941d73392b94dde, 0x3cb75f9d03c7dab4), + (0xb8e752a11f1ff8cf, 0xbc50be9727e162d0), + (0x38c8623cee5ad9d9, 0xbc31489750bef0f5), + (0x384f066486611d86, 0x3bc88de9469da922), + (0x3839422334460fd8, 0x3ba4cb353920bd3f), + (0xb7d635c8739b1cc3, 0xbb3d0958e2b20819), + (0x37b805c0dbe5c052, 0xbb14a01af94d0b34), + ], + [ + (0x3c0020b4016594a1, 0x3fbe8727daa3daed), + (0x35e429e6f0925013, 0x3954c091fcd570df), + (0xbbf020b401657018, 0xbfae8727daa3daed), + (0xbbae628434cc3c70, 0x3f3d19c52e070d9f), + (0xbc1361836c55971f, 0x3f74524d4813cc25), + (0xbb7cb5b9b349156d, 0xbf0735f790b535f3), + (0xbbcfed1fa3bfcdb7, 0xbf259c8f9f0a3484), + (0xbb45b8645b0be816, 0x3eba619ffc5a3ad0), + (0x3b695223039dbc70, 0x3ec896d7dc819faf), + (0xbaad000c2e45e4dd, 0xbe5f04efbdfeacf4), + (0x3aff55bb37d4ad1a, 0xbe6162253f3024f4), + (0x3a774121f038cc79, 0x3df653d736c3ef75), + (0x3a97cad085bd78e6, 0x3df0bc406f716b3d), + (0xba1b1362e426bbf6, 0xbd85b5420be0cc8e), + (0xba06a1118f4cd431, 0xbd77573e801c920a), + (0x399a08aaec9f5f5a, 0x3d0e6b725d3bea39), + (0x399f56e3dc7cb7dc, 0x3cf8a83e6e3a037e), + (0xb932a9c0fdf0215f, 0xbc901633974b8728), + (0xb90da8cd34f16ed9, 0xbc74685bc5b412ab), + (0xb89a26475fca50a1, 0x3c0a9719b6c2c317), + (0x3884ebc520e017d9, 0x3beb2ce5154261a5), + (0x381bbed6afb225d9, 0xbb81a55f76501009), + (0x37e01b88fc0ca8c4, 0xbb5d84f510d0e5db), + (0xb77f816f7a76ffd2, 0x3af38293e0fae553), + ], + [ + (0x35f7b4ea1935a568, 0xb956dc89f8b0297a), + (0xbc5a45a53b37a59e, 0xbfbe018d99f5da1b), + (0x3be001e9c4dcec6c, 0x3f54b85897b36265), + (0xbc32db4ef382192e, 0x3f93fc442153435d), + (0xbbcf201dea1f5a71, 0xbf2b9694d71486e3), + (0xbbef8e2381bad736, 0xbf4fe6fdc644ddde), + (0x3b87d6d0d3615a87, 0x3ee5fd096e4523fb), + (0xbb6b106322d36ddc, 0x3ef83770c9a84498), + (0x3b3a40e2b2746cab, 0xbe90a6f6f7e05f1b), + (0xbb3f771adc91215c, 0xbe956ad4a35eb0ad), + (0x3ab3b86f94e0c858, 0x3e2d5bea474ca54f), + (0xbac5585b134469a5, 0x3e28c39f68d21b3c), + (0xba690d5e5a6b3a35, 0xbdc0e73408ce7d83), + (0x3a327165e3e97d3a, 0xbdb42a6dedaa1a20), + (0xb9dd142a729ed644, 0x3d4b640f953ca9d2), + (0x39d7f71ecb3fc409, 0x3d385e74fde5cbdb), + (0xb97b8a515f767ea6, 0xbcd07409455800ac), + (0xb95ec4cbe35c9396, 0xbcb6b62242767fd2), + (0xb8e317bb80a9622e, 0x3c4e76f4a5aa2684), + (0x38b554cbd013807d, 0x3c30d15ee339d044), + (0xb8101586ff6d60a8, 0xbbc664451d8e4e4f), + (0xb849c3a261353029, 0xbba4436d1959e4e5), + (0x37b47984bdada57e, 0x3b3a8bfe9a4ae941), + (0x37b807503fdd6126, 0x3b1420356bcc7e9f), + ], + [ + (0xbc5cb1f28997ca38, 0xbfbd8293aa55d18f), + (0xb61515229b393b76, 0xb9729d22385eacde), + (0x3c4cb1f28997c91b, 0x3fad8293aa55d18f), + (0x3bb680f417a90d4b, 0xbf3a48fe4afedcc8), + (0xbc16c091c5e058be, 0xbf73a5ccbc12a67b), + (0xbba33c90d0f9c0c9, 0x3f04f91e41eee9bc), + (0xbb9b30874f0a2926, 0x3f24e72224db2c0e), + (0xbb169858252daef6, 0xbeb7dac8202ad4fb), + (0x3b63726cbb3fc903, 0xbec7cbd49c315be0), + (0x3aee4734322f57a4, 0x3e5c1396b62b0f84), + (0x3af3c6385c4eb2c7, 0x3e60d5c64a9c427f), + (0x3a70141b0643212e, 0xbdf43c4a5d5a74a1), + (0xba8fd98f49242c47, 0xbdf038cb3f5e3248), + (0xba158fe9d08d69ff, 0x3d83b473da8d9cc0), + (0xba029334408e97a4, 0x3d76a5d59f9a7a17), + (0x39ad9590d69212ea, 0xbd0ba9a1977eefff), + (0xb971f0fe79a4cdf4, 0xbcf7f3d211c66187), + (0x391950769136ef0f, 0x3c8d51075a5e7bbb), + (0xb916720d8484ea73, 0x3c73d94e734e8879), + (0xb892e80fae65fb53, 0xbc0848485fe35579), + (0x38777f0c4d7b3dfa, 0xbbea774325d98b75), + (0x382276ef09c2242b, 0x3b8026f3af966377), + (0xb7f67847065ac7b4, 0x3b5cc9941483fe56), + (0x377a99585b78b747, 0xbaf1e6750f0747ba), + ], + [ + (0xb6025c847eb79bd4, 0xb964158ebf13126e), + (0x3c5f215e77086bf5, 0x3fbd09b210b30217), + (0x3bfc1f6fd559ba97, 0xbf52c74f6d120291), + (0x3c0587bb3b3049ff, 0xbf9357bfc2be5860), + (0xbbca26f6fb3da340, 0x3f2901e4c495acea), + (0x3bdfa22468c1def8, 0x3f4ee2a36979f905), + (0xbb819f063106cdcb, 0xbee3f0cb93a497a4), + (0x3b845c631b76c8a1, 0xbef7748921871bcc), + (0x3af9b751dac720d1, 0x3e8e39a085fc522a), + (0x3b168e67fb0cb203, 0x3e94c1b7a6b2509f), + (0xbaca52721df6c6b6, 0xbe2aabe92ddd7d73), + (0x3ac84b97b1182cc0, 0xbe2804c5ad3234f3), + (0xba54edd49d1edf2d, 0x3dbec02b4af63baf), + (0xba503f24cfdd22c9, 0x3db3938387c8ea5e), + (0xb9ee5637ec8cd309, 0xbd48f3df4c86043e), + (0xb97c878aca76d363, 0xbd37ae3cd67c3185), + (0x3953bf1f530af427, 0x3cce075e0947f84e), + (0x394a5c410c455b26, 0x3cb61833a4ed09fb), + (0xb8d6421dd6abfed8, 0xbc4bda71bc7ca99f), + (0x38d6cb9f7285a2f3, 0xbc30616da73cfd68), + (0xb860f21809293998, 0x3bc483adcba31a64), + (0xb819a874856663c4, 0x3ba3c2e3aaaa861b), + (0x37d51466fd699b53, 0xbb385faa94578a21), + (0x379f3946f24c4995, 0xbb13a642c5cb638d), + ], + [ + (0xbc49df1f0f8d2108, 0x3fbc96700bf039e2), + (0xb5aa78cc35dda805, 0x393def6cb4dcf261), + (0x3c39df1f0f8d2339, 0xbfac96700bf039e2), + (0xbbb8cb9fe6e3ff6e, 0x3f37e5647d30fea8), + (0x3c063977044d6f5c, 0x3f73095734a24496), + (0xbb56346fb6ed118c, 0xbf0312a4db537d5b), + (0x3bc2ab35d69fc6e2, 0xbf24424a96e62373), + (0xbb5dc2fb5a697d64, 0x3eb5b4a6639fb7be), + (0xbb533dbdb81ff3d8, 0x3ec712e4d44c4a74), + (0xba8ccfbfe857180a, 0xbe59917dedf003d7), + (0x3b0b894b3c8075c7, 0xbe6055757b098917), + (0x3a95a6cc3450560a, 0x3df2728cdc02e18c), + (0xba805244323472ea, 0x3def80393fe2fc7c), + (0x3a2d37e6a4cca504, 0xbd81fcaa37a8b3b3), + (0xba1bcda846633c8d, 0xbd760225681cce6f), + (0x39a7e3fa90942e91, 0x3d0949ef9ee67213), + (0xb995a2c090d0fa89, 0x3cf74c654a150fde), + (0xb912f420e2959c3d, 0xbc8ad88e52941a98), + (0x39086b9adf654b32, 0xbc7353b6bf507102), + (0x38a54a053e9cfe0f, 0x3c0646e8a6aa6dbe), + (0x38174c918b573c6f, 0x3be9cc769d138c5f), + (0xb80b75e9f287b65e, 0xbb7db1eb4b8463d9), + (0x37f46072c5cf6b31, 0xbb5c181474bdc517), + (0x379310eb69ece94f, 0x3af07ca4c538ae49), + ], + [ + (0xb6025d7555eb3333, 0xb96e6cb57bbffe78), + (0xbc37a2663626dca6, 0xbfbc28612a3bc18b), + (0xbbf422f2d193783c, 0x3f511f52577ff6ba), + (0x3c3976e0041aa223, 0x3f92c21da135f56c), + (0xbbc90eddb53bb0bc, 0xbf26ce18f8229e00), + (0xbbed07e9f5028d13, 0xbf4df586d8b786e1), + (0xbb8f298c930f3daa, 0x3ee230fede9c5ad4), + (0xbb94e2ce32d56eeb, 0x3ef6c2a7558fc928), + (0xbb04521d6df510c8, 0xbe8b97329e667f58), + (0x3b301d874878e4d4, 0xbe9426ecfd66cd08), + (0xbab8e3f15d7488a6, 0x3e285e012a388a8c), + (0x3aca2aaf6142964c, 0x3e27557143798fcd), + (0xba467e3999dd049e, 0xbdbc1f9f6fa068b6), + (0x3a5bd65c11af362e, 0xbdb30842b25be60a), + (0x39cac535c84bd033, 0x3d46d975726392d2), + (0xb9d9799d506b6536, 0x3d370aced616e29d), + (0xb960a1d7a205223b, 0xbccb8986f84a30fa), + (0xb8fca075da3aafd8, 0xbcb584e49cb6db11), + (0x38e10f7fdc1a5917, 0x3c4995407ad5e053), + (0xb8cee1114e53e0aa, 0x3c2ff0b6f99d000a), + (0x38430648734f6eb9, 0xbbc2dffde43760ea), + (0x3835046e458663d2, 0xbba3496b757a3add), + (0xb7dc717d402f56b2, 0x3b36778e7fdb6444), + (0xb7b8d1b6dcf93aee, 0x3b13324afffd82fa), + ], + [ + (0x3c58fff4515190b5, 0xbfbbbf246914235f), + (0x35d982a917cde59c, 0x3950d75272d68d70), + (0xbc48fff4515191c8, 0x3fabbf246914235f), + (0x3b9cd1da148e225e, 0xbf35d923e8470178), + (0xbbfbef9e89616fef, 0xbf727a96f174b6d1), + (0xbb885ae82b0f986d, 0x3f01715e4bbb00e7), + (0xbbcb5280334e8030, 0x3f23abacdb5106b5), + (0xbb5ee327f9eba23d, 0xbeb3dc30d27849d7), + (0x3b6dfe7950a9c090, 0xbec6698d6ee99eb9), + (0x3aeb757878040b38, 0x3e576911a4642dff), + (0xbaee8dc651ba599a, 0x3e5fbf415682210b), + (0x3a81620ce1ff0741, 0xbdf0e7d3674631fb), + (0xba8353972b806230, 0xbdeea1cbf2d9d28a), + (0xba25d1ac6266a88d, 0x3d80805ad6510660), + (0xba069055b8b763ed, 0x3d756aaba5459ef1), + (0xb9a9f31ddbf5fa91, 0xbd073ab529b3b8ec), + (0x398c43d0fb4ec9a1, 0xbcf6b0b8fe628d9e), + (0xb8c99b2526d558a3, 0x3c88b1cfe95984a1), + (0x38c9b40ec3d6b48d, 0x3c72d6d66d90227d), + (0xb8a48afcea90991a, 0xbc04861250a2137e), + (0xb88e608ec89832fa, 0xbbe92be16535de20), + (0xb805a233b6080776, 0x3b7b6761d996b09c), + (0xb7f3fb75ac66c54a, 0x3b5b702a10c5d8d6), + (0x3787fbc0b82d70c7, 0xbaee7b19f87b38e8), + ], + [ + (0x35ff73655c8feec1, 0x39576c36a9ae2d5c), + (0x3c5d0edcbac85111, 0x3fbb5a6219b35e14), + (0x3be54c0ba940867f, 0xbf4f645fdb1a8c89), + (0x3c37a2e3fd651672, 0xbf923940d01de8e9), + (0x3bb0148b185376f2, 0x3f24e86a1e6384ff), + (0xbbe17bbc96492f6b, 0x3f4d1c6a18c7ed95), + (0xbb8c8ebdf6811341, 0xbee0aeec61621923), + (0xbb99391cbc0f757c, 0xbef61f7d30244338), + (0xbaa9ea01a9b8fa8c, 0x3e8950f781c1c41c), + (0x3b3c5364d9ae9a38, 0x3e93989942e07175), + (0x3acc3081ebda4ff1, 0xbe265fd114ee2251), + (0xbab6323d2dc56e9e, 0xbe26b3bd4dfd4b81), + (0x3a5ff68cf4ae06aa, 0x3db9d8a1bbe00791), + (0xba462dc328f651f0, 0x3db2875c16e4487f), + (0x39a13905c77f8bc2, 0xbd4505775bc7e4de), + (0x39ca895460eb8613, 0xbd3672e2d4f29271), + (0x39541d93187b0343, 0x3cc95d609db7ab8a), + (0xb94983f2e6b2775d, 0x3cb4fb4d36ab3e60), + (0xb8c9c87d6b8b88ce, 0xbc4798ba8aedf4d9), + (0xb8c9a4efd28a4426, 0xbc2f2b65d0eb351a), + (0x3864f45927d43933, 0x3bc16f636e45b56a), + (0xb84852ca897a91ce, 0x3ba2d6b5ad521072), + (0xb7a77d76082f0cb2, 0xbb34c92434bd9c18), + (0xb7baea41b7cf079e, 0xbb12c43424dc0933), + ], + [ + (0xbc5024304247ada3, 0x3fbaf9cb49c4f935), + (0xb606a30b444ceba4, 0xb9708319890a5e6d), + (0x3c4024304247aeb1, 0xbfaaf9cb49c4f935), + (0xbbdc12274808197b, 0x3f3413b75ce0cc1b), + (0x3c06b1ae60010808, 0x3f71f7a8fec6eba8), + (0xbbac4403af34826f, 0xbf0008442739ebfc), + (0xbbc9d6333d2b3d56, 0xbf23215dab7537c6), + (0xbb3addf7c6694661, 0x3eb242e9e6bab199), + (0xbb4ca73ddba08b13, 0x3ec5cdc48f5d75eb), + (0x3afbb2f24513857c, 0xbe5589cf32f43f3a), + (0xbafb14e3e9852288, 0xbe5ee5f0d63c1125), + (0x3a8b9bbc9f549992, 0x3def216eedb0f95e), + (0x3a7b918a152ee6ef, 0x3dedd414a7d8c97b), + (0xba0a1e2e293b285d, 0xbd7e69fdff8447cd), + (0xba130096e56c8b4c, 0xbd74de15be68829d), + (0x39845da07a4cf814, 0x3d056e1418ae157c), + (0xb9994fbaa41d7396, 0x3cf61fa98590ddb6), + (0x392ed1bc75d499ea, 0xbc86cf2506f44167), + (0x391952212e39899e, 0xbc7261f3fbe2abde), + (0x38af858de9bd8291, 0x3c02fb5ec2e4f362), + (0xb884c724ba966327, 0x3be894d61148c89d), + (0x3814ecb4513b97db, 0xbb7961b08a806964), + (0x37f74e1e809c4297, 0xbb5ad164c25d22e1), + (0x378b5dec7edc635c, 0x3aec45b6d88eaf60), + ], + [ + (0x35fc420ae9aceac9, 0xb9652ed980617fa4), + (0x3c508b7cc7933a76, 0xbfba9d1835947d70), + (0xbbcfb3814e43f8ba, 0x3f4cea253049a85b), + (0x3c3e993cf753c70d, 0x3f91bb71f665dcdf), + (0x3bc6de474ee9719c, 0xbf23427f4797ae90), + (0x3bab43046c68dd4b, 0xbf4c54a7bd6f30c1), + (0xbb74fee51586a24b, 0x3edebe9e65809919), + (0xbb914661f197da7a, 0x3ef58924fa089950), + (0xbb1b1c449258996b, 0xbe87564501e7bcdc), + (0xbb32d1ffd0fc3508, 0xbe9315306e5bb42b), + (0x3ab9cf483ad9233b, 0x3e24a32382dea2a5), + (0xbacfa4096d44c807, 0x3e261e0ee5367a22), + (0x3a4c5e7f996c4e59, 0xbdb7db853758262e), + (0x3a56a3ad86030da8, 0xbdb20facb4a9bb8a), + (0xb9e5ff48c852945f, 0x3d436bd6f000149c), + (0x39d6c37ca2f2d752, 0x3d35e552618cbb0c), + (0x396867fd75ecd168, 0xbcc7754c8d2d22bc), + (0xb9220db8a9e7d56d, 0xbcb47a92b936acfa), + (0xb8edde52032032d2, 0x3c45d9205d867e02), + (0x38c44f9ceec60e46, 0x3c2e71f7334b0fac), + (0x3864418502fa183f, 0xbbc029e4f35c0aa8), + (0xb84306e130ba75b2, 0xbba26a627f026785), + (0xb79943e923428172, 0x3b334bc2432e2477), + (0x37b67d0793319e79, 0x3b125bc6a2301ad4), + ], + [ + (0xbc55d35a88f1e0a3, 0xbfba4407e04298d1), + (0x35c8ff9720aff2d4, 0xb952ea1cdd28e494), + (0x3c45d35a88f1df9c, 0x3faa4407e04298d1), + (0xbbdfcf49ead42a08, 0xbf3288694b34ab21), + (0x3c1c3cb8ccc5cfb9, 0xbf717f0266db2149), + (0x3b7370def0b046b9, 0x3efd9a9a1d05433b), + (0xbbc76ae4901c1264, 0x3f22a1c916a2d5a1), + (0xbb55855d21f5ed77, 0xbeb0dd9e92661e07), + (0xbb0d68a20388319a, 0xbec53dd972d8f232), + (0x3af0f257afd1ac40, 0x3e53e6e553aac740), + (0xbadedfaa1b67f332, 0x3e5e1cc65033998a), + (0xba7a37ed01b9dc68, 0xbdecc8a3f36b4e82), + (0xba7e73855d5a6fce, 0xbded152ceac33738), + (0x3a0403bc50b56bec, 0x3d7c249e1f30a046), + (0x3a07ab8d362d1a04, 0x3d745b3c1804b70e), + (0x396e1c149d462be8, 0xbd03d90bb02406e2), + (0xb973199796754cc5, 0xbcf598302aa37892), + (0xb916ac374a93ff56, 0x3c85259cd94ec2fe), + (0x3902b130fb62197d, 0x3c71f460935c9412), + (0x38a7f1bf80e44c1a, 0xbc019e603f7b6fda), + (0x386260160040e9ca, 0xbbe806a4e2d693da), + (0xb81630b9badcde1d, 0x3b77968008016bca), + (0x37d07b22ab7a0d45, 0x3b5a3b41f167ae95), + (0xb76d821cbcda7119, 0xbaea4e94d614d85d), + ], + [ + (0xb594a4d849ef503c, 0x3938d6c331cb03ad), + (0x3c2748c82bad8c50, 0x3fb9ee5ee937fc89), + (0x3bebaa9c093c243c, 0xbf4abf28ad5bf6da), + (0x3bf098a110e15588, 0xbf9147481084ae0f), + (0xbbcb58642b3fc6f6, 0x3f21d137345cfee5), + (0x3bdbab7a25ea6636, 0x3f4b9c10ddf62464), + (0x3b707cd24e8374d7, 0xbedc72c9d49c6d7a), + (0x3b9799bc070c59b2, 0xbef4fe0b363ccc66), + (0x3b2f6fb041c061d5, 0x3e859a1c336b7506), + (0xbb38437a08d58d5c, 0x3e929b6632cc324d), + (0xba9f406b3224c41e, 0xbe231cd6e7991df9), + (0xbab2457dd0d0e718, 0xbe25930872001f69), + (0x3a548f54ac84016e, 0x3db61befbaaf9fff), + (0xba589a9303d7d25f, 0x3db1a038446ec46b), + (0xb9db6b1cfe9b31f4, 0xbd42030319ffb5eb), + (0x39bf4002924f6ae5, 0xbd356117967009ca), + (0x394da21091709c76, 0x3cc5c664f861ad05), + (0xb93ec733758fe60c, 0x3cb401eb6a584504), + (0xb8c585bd91ee5a94, 0xbc444cf483677683), + (0x38b16263dda87c68, 0xbc2dc380ac38062e), + (0xb85553427dd612fd, 0x3bbe11fffb02da4f), + (0xb8433d91b3bab077, 0x3ba2040b40b2538d), + (0xb7df7b4517c493ac, 0xbb31f841ca6c686b), + (0xb7b3136588d9a93e, 0xbb11f8bc69e97ebb), + ], + [ + (0x3c5728ab934a269f, 0x3fb99be744018c90), + (0xb60a99831efba67e, 0xb968c3fcaae6f521), + (0xbc4728ab934a259d, 0xbfa99be744018c90), + (0xbbc84fc914744b2d, 0x3f312d4e1c1ca4c3), + (0x3c0f281d89c5c387, 0x3f710f5ca51f98b0), + (0x3b9fa3d9c31f9653, 0xbefb71417476a570), + (0xbb82784b5921b117, 0xbf222b9fa8dfd762), + (0xbb2378a1f5ba83c5, 0x3eaf471061b7dd7e), + (0x3b688d2d785bb65e, 0x3ec4b862279de756), + (0x3ae3ff1d8fa9486f, 0xbe52763f34a53566), + (0xbafc90858b5fda2a, 0xbe5d61e605e8e69a), + (0xba8db88bf0b8b3a0, 0x3deab7331a682503), + (0x3a83becc2585c0e6, 0x3dec637428f3fda0), + (0xb9f91cdb1c054c59, 0xbd7a236ad0b3eba5), + (0x3a130d91a2571fc8, 0xbd73e11cef6ea796), + (0x39ab3e18bb4b1cc4, 0x3d0272cbaef4a6ce), + (0xb992fbf6044183a9, 0x3cf519623b3e6ff3), + (0x392d2f84f2aa9293, 0xbc83ac610a98a111), + (0x390f58be5a588034, 0xbc718d7aab4e57b8), + (0xb89f4ff0d5411205, 0x3c006837647ec51a), + (0xb880cf6db8b6e7c8, 0x3be780a339ad4fe5), + (0xb80c4294a291cdbe, 0xbb75fd4c1cf239b2), + (0x37a40abc824fc196, 0xbb59ad37b5365c90), + (0xb78678af8405295a, 0x3ae88d6e7fc415df), + ], + [ + (0x35f8589681278026, 0x39644f6712268762), + (0xbc4e31356cad466e, 0xbfb94c6f54aef04b), + (0xbbe68528f64c7b1b, 0x3f48d6371f018ef0), + (0xbbf705a06948b19e, 0x3f90db975fd7dc47), + (0x3bc06e812fcafb21, 0xbf208bd1634353c9), + (0x3beeb410edf2c87a, 0xbf4af0d3d4cd140d), + (0x3b6d81ec11b0f0a1, 0x3eda6c8e7c9d023e), + (0xbb94f5f0c72b68d7, 0x3ef47cddcdac15d7), + (0xbaee0517040c548e, 0xbe8412394fc50e0a), + (0xbb3fb62ad27acc53, 0xbe922a21cb1edfe9), + (0xbac19c23bc37cb83, 0x3e21c417dedcf50f), + (0xbaae59d2170adaa5, 0x3e25117f3061daaa), + (0xba5e45da99f1d381, 0xbdb49009a6c8ef21), + (0x3a587572c3e6ea79, 0xbdb13823dda87c56), + (0xb9e347d6a1129f4a, 0x3d40c350b604f8b8), + (0xb9cc2ad178b32695, 0x3d34e54a89ae35f1), + (0xb96a80e6a3444766, 0xbcc447dde867e136), + (0xb958d6073cf4ba2f, 0xbcb3909fa79d8804), + (0xb8d64b27142de74c, 0x3c42ec7e360503ed), + (0x38c6d01b41c0980d, 0x3c2d1f243bdfcc89), + (0xb85a84d31e1eccc9, 0xbbbc0eb8ec6b686f), + (0x383387e43fd2ce16, 0xbba1a3489d347b47), + (0x37dde5e850e9f781, 0x3b30c8b4a21c4541), + (0x379dea6fe0f54701, 0x3b119ac8a8b69886), + ], + [ + (0x3c5e213a1a4b3671, 0xbfb8ffc9bd24fe08), + (0xb6087102bb621f14, 0xb968aedf9eaeb722), + (0xbc4e213a1a4b376e, 0x3fa8ffc9bd24fe08), + (0xbbcd363274122e3f, 0xbf2ff51b38eef42c), + (0xbc0f532ddb1fa0a0, 0xbf70a7a725d3fbc4), + (0xbb834bf08647ec89, 0x3ef988128728122a), + (0xbbb5bd6096bda7b8, 0x3f21bdc846a09e43), + (0x3b30137f6ede612f, 0xbead1b60a4812ac4), + (0xbb5a77139f0b51d5, 0xbec43c2d8e698c10), + (0x3ad810635b7d0ab5, 0x3e512fd6ccdafecc), + (0xbaf69212c4f321ef, 0x3e5cb3bb8802e835), + (0x3a8f78dd26a56680, 0xbde8e1dd09a92325), + (0x3a8e97521eebd870, 0xbdebbd84404b6233), + (0x3a0668a211ed0544, 0x3d785bcfd7db3e06), + (0xba1ac0b0871b3637, 0x3d736ed7607396ae), + (0xb955951b23d30299, 0xbd01343464758a13), + (0xb9870af9e1cfe573, 0xbcf4a26ef2120ad4), + (0x392f6ff8929d9ec8, 0x3c825c400013c92d), + (0xb91624b068d7998e, 0x3c712caecd60a253), + (0xb89eef1d95657c36, 0xbbfea68103e8017a), + (0xb85dbca3eb7791dd, 0xbbe7022f94b51f88), + (0x381743e0f343b5ae, 0x3b748f053210dc4e), + (0xb7fa879e893fa8e0, 0x3b5926bc9b441cf3), + (0x378b8478cb5f337e, 0xbae6f9f3f5bcbb92), + ], + [ + (0x3601868fee3dfc1f, 0xb967b581e11caa4e), + (0x3c35e8738ef1b9cc, 0x3fb8b5ccad12d632), + (0xbbd18507f867652e, 0xbf4724d0185980d2), + (0x3c1f6ab95e49bea7, 0xbf907764ae2b1eeb), + (0x3bbea971beb0d4c5, 0x3f1ed6acc18fdf29), + (0x3bca7600bd6cd00f, 0x3f4a51693df2efbb), + (0x3b5424c646ef6906, 0xbed8a0ec61e4df7b), + (0xbb2fcebd0b42c3a3, 0xbef4047f31fae045), + (0xbb244d840b8d48b4, 0x3e82b668af276950), + (0x3b3cad3ad53887a6, 0x3e91c07467ed6403), + (0xbac9698769c60aee, 0xbe2091d32eea7f0f), + (0xbacf39eabd09fce6, 0xbe24987294de7d1e), + (0xba4e5986bfe40615, 0x3db32fe6ab220650), + (0x3a4ecd045a4261a7, 0x3db0d6b127f8ac20), + (0x39d762ccc3d86511, 0xbd3f4d16b8caee52), + (0xb9d08617d1af539c, 0xbd34711e3d50f4ef), + (0xb96508919fc82bc0, 0x3cc2f28e5dd490f1), + (0x395bb058a146ba42, 0x3cb326098ea185f3), + (0xb8e94f0af2b5ad80, 0xbc41b16976a3d442), + (0x38c176e23d72ae5d, 0xbc2c84134caa87ba), + (0x385559d5c6add4b3, 0x3bba412149720827), + (0xb840ccac5bb143cd, 0x3ba147b6307ccbc3), + (0xb7b2120a01259b99, 0xbb2f70570b14782d), + (0x37b4facf0ef3cce3, 0xbb11419a7914e3d3), + ], + [ + (0x3c5b1c9821974148, 0x3fb86e51be0a9153), + (0xb5f75cf6d696fc83, 0xb95827c8ffd9b363), + (0xbc4b1c982197404f, 0xbfa86e51be0a9153), + (0xbbcc79e50a2cd67c, 0x3f2dd3c244b53279), + (0xbbe9cfc13650412e, 0x3f7046fc5a218a86), + (0x3b473390e469f8a4, 0xbef7d51accbfba76), + (0x3bbac27d2877fb16, 0xbf2157556c0e1b1a), + (0xbb2e687ae53690de, 0x3eab2d01c12c8227), + (0xbb685c4f9e1e413b, 0x3ec3c838897d0a1e), + (0xbaf6af7b27e224bc, 0xbe500d37aa536a8b), + (0x3afe75b9f5dba876, 0xbe5c10ecf088eac6), + (0x3a7e762d28ae6967, 0x3de73f8d1af57f4c), + (0xba76c817fc84ee3f, 0x3deb2227fe940228), + (0x3a0d6d1da90d883a, 0xbd76c5390bcf01cc), + (0x39fafe0f0f7cf1bb, 0xbd7303a6ded9e74a), + (0x39a769658d5dfcab, 0x3d0017772c8c67d0), + (0x39816dc9a19e88df, 0x3cf4329cf31c85bc), + (0xb9187bba5059be09, 0xbc812f535bf22ca0), + (0x39028bb4a0afb991, 0xbc70d1775336e3dd), + (0x388f6ab178fe4eee, 0x3bfcb5a6e861125e), + (0xb8764727329b2f6d, 0x3be68ab377a5b3ae), + (0x380ffcd7837774b1, 0xbb7345ce122d1040), + (0x37f98513cc233bda, 0xbb58a74b58fe9d86), + (0x37810ff858a703fb, 0x3ae58ea451ed4ee5), + ], + [ + (0x3609fbc30a1ed1d3, 0xb9625183186cb588), + (0x3c40ee4d5b1b8051, 0xbfb829356999a097), + (0x3be3831592c6b0a5, 0x3f45a280e033eb59), + (0x3c215c7646576687, 0x3f9019dba8336e48), + (0x3b986e85a68d172a, 0xbf1cd4559d95e619), + (0xbbc0173a940c218c, 0xbf49bc857750335e), + (0xbb63dae6bf1f89ae, 0x3ed70706580693f9), + (0x3b8384969ed36c54, 0x3ef393fc6cf8481f), + (0xbaf56ba053870856, 0xbe81800af4665cb3), + (0xbb2c21dbefaffb7f, 0xbe915d91a2289a30), + (0x3a9c9f08edce59cf, 0x3e1f009c83572407), + (0x3ab89826637a4616, 0x3e2427054565b344), + (0xba34b49867a6db4f, 0xbdb1f5167f464cc1), + (0x3a578760251f40d0, 0xbdb07b3a2cb21728), + (0xb9d9c43afa0fe4e6, 0x3d3d4f453474c223), + (0x39d2dacef909b870, 0x3d3403dd864cdceb), + (0x394afae738fa0ade, 0xbcc1c09693482adf), + (0xb955a0b7487878c3, 0xbcb2c193ec7672bc), + (0xb8e991d90439ccb6, 0x3c40967d711ba719), + (0xb8bd41e60b473ee2, 0x3c2bf18fb3b9d25e), + (0x38559b44bb41d0b5, 0xbbb8a1e44dd80d7b), + (0xb8300b6984de9d94, 0xbba0f0f498e20346), + (0xb7be574e735a8cb7, 0x3b2d850a1c84b4b5), + (0xb791e712d7e8c434, 0x3b10ece621e460f6), + ], + [ + (0x3c21907f595a082c, 0xbfb7e656efb009ae), + (0xb5d70ebcecd9fbaa, 0xb9348631c28e1012), + (0xbc11907f595a0fca, 0x3fa7e656efb009ae), + (0x3bcce5fd1ce60611, 0xbf2bec6b33efcb49), + (0x3bcf8f1c97773b2d, 0xbf6fd932c26aad94), + (0x3b80b8964e3bc289, 0x3ef6504d7e054d50), + (0xbbb3c0e78ce81095, 0x3f20f77ce6105150), + (0x3b3d95f66e8bcdc7, 0xbea972e573db9593), + (0x3b4458e98ac8a7d0, 0xbec35ba58bf2f993), + (0x3ad1d824fbf1c841, 0x3e4e1246a53112c6), + (0xbacbe1b18e34adb3, 0x3e5b7850b3bc8175), + (0x3a8ea247bf864770, 0xbde5c8dcec477a4f), + (0xba8c8c74de40c8c9, 0xbdea905348b49249), + (0xba0bd92b052944e0, 0x3d7558a1f12cdd8b), + (0xba1c00a1d58c8cfb, 0x3d729edf3b285f5a), + (0xb992a01268eb295d, 0xbcfe2f9cdddcaae8), + (0xb996b7f5d81cfb6a, 0xbcf3c947b927c569), + (0xb925ba6791e41b2f, 0x3c8020bb87a79ea9), + (0xb90e7d0294d49287, 0x3c707b5b9c74c0fe), + (0x38890499436f4660, 0xbbfaf62358105eee), + (0xb88dc52f6583904b, 0xbbe619a4100326eb), + (0x37f0135f77fb4dbd, 0x3b721cbe450a51a8), + (0xb7e6ee90d9e1aa8a, 0x3b582e655a55f7e3), + (0xb7348781a2c50334, 0xbae44663af3f368d), + ], + [ + (0xb6020e4a1b2a8f8d, 0x396ab0500de5301b), + (0xbc529270d2a71e93, 0x3fb7a597e9550934), + (0xbbd42472048d4d2c, 0xbf44486c0b012534), + (0xbc2ac52ac43275af, 0xbf8f848eec0e0e6b), + (0x3b684f3433759ef3, 0x3f1b077fae06adc6), + (0xbbce518d0ac3eb8f, 0x3f49310d6e6842c6), + (0x3b230b8e78861165, 0xbed597a5befbd70e), + (0x3b9e1e122fd16318, 0xbef32a855e4e113b), + (0xbb1d74885153e029, 0x3e8069ba0b1a612d), + (0xbb3a50c31550125c, 0x3e9100c97ba8e22d), + (0xbaaea70ea0155098, 0xbe1d15b5350404fa), + (0x3ac3cb5036af1144, 0xbe23bc775cca4413), + (0xba5b1e821a17c11c, 0x3db0da51f94c98eb), + (0xba50d67d4e601934, 0x3db0252dc33a4d71), + (0xb9c1e859398b6f43, 0xbd3b84d751a3586e), + (0xb9df2f53d258d2cf, 0xbd339ce8224cadca), + (0xb9601e564eee8b92, 0x3cc0ad1ba9bada71), + (0x393bd1c6476589ac, 0x3cb262b8db685d38), + (0x38d88290cd473175, 0xbc3f2ec74017a50b), + (0x38cc155000aaf19d, 0xbc2b66eb4fd1abd4), + (0xb84d6b52f7a6d523, 0x3bb72adeccad55cf), + (0xb81b307d97df219d, 0x3ba09e84d1e5cbd9), + (0x37cfdfe2f1e86ba7, 0xbb2bc6df8963705f), + (0x37bd47c432afc7ac, 0xbb10899f2f554f23), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_taylor.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_taylor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_taylor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0_coeffs_taylor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1292 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Taylor expansion at zeros and extremums for J0. + +Generated by SageMath: +```python +mp.prec = 180 +def print_taylor_coeffs(poly): + print("[") + for i in range(0, 24): + coeff = poly[i] + print_double_double("", coeff) + print("],") + +def print_taylor_coeffs_dyad(poly): + print("[") + for i in range(0, 24): + coeff = poly[i] + print_dyadic(coeff) + print("],") + +print(f"pub(crate) static J0_COEFFS_TAYLOR: [[(u64, u64); 24]; {len(j0_zeros)}] = [") + +prev_zero = 0 + +for i in range(0, len(j0_zeros)): + k_range = j0_zeros[i] + range_diff = k_range - prev_zero + + mp.prec = 180 + x0 = mp.mpf(k_range) + from mpmath import mp, j0, taylor + poly = taylor(lambda val: j0(val), x0, 24) + print_taylor_coeffs(poly) + # print(poly) + prev_zero = j0_zeros[i] + +print("];") +``` +**/ +pub(crate) static J0_COEFFS_TAYLOR: [[(u64, u64); 24]; 47] = [ + [ + (0xb5be985fa7f83cc3, 0xb91cba5b78f9bcd0), + (0xbc8ac8cc3d6bafa4, 0xbfe09cdb36551280), + (0xbc5b50b1160e9078, 0x3fbba1deea029494), + (0x3c4bc98bcfdc7a7f, 0x3facfae864368d70), + (0xbc1a87a5518aec0c, 0xbf81bb1cbe1a4071), + (0x3bcf770ef9886bfc, 0xbf61f992590d12bd), + (0x3ba05114c54b25ab, 0x3f315382ba06cc47), + (0x3ba2b401cd6c68ec, 0x3f06ed3b9f07eb28), + (0xbb46fe17c9b10921, 0xbed232c77d228ab6), + (0x3b479fbd07230860, 0xbea1cce302821846), + (0x3ac3ee3080fdf4d2, 0x3e67ff99166c20b8), + (0x3ad99d2c20223b95, 0x3e32951bd4726a93), + (0xba982691b667ba5c, 0xbdf5c2c38b2a278c), + (0x3a44e89952bc724c, 0xbdbbdc468c1a817a), + (0x3a0ebde93f245a29, 0x3d7cd41cf248a22e), + (0x39aeeb56633d8ce6, 0x3d3f70b0201c12a4), + (0xb98e8ed54af59db8, 0xbcfd22d8ef70f1aa), + (0x394a95ebfce4a435, 0xbcbbaa352d8622af), + (0xb91ff1b0b50e7818, 0x3c773612afd5db30), + (0xb8dd29c3a1d1250e, 0x3c3382933550f440), + (0xb8840afcc88fadb8, 0xbbede7dcd5e6dab6), + (0x384023453882217b, 0xbba68bbe41057f40), + (0x37e0c3131ee8f030, 0x3b5fce24eb23551c), + (0x379a6895f9086a05, 0x3b15bc1becd9a431), + ], + [ + (0x3c62de1143765a96, 0xbfd9c6cf582cbf7f), + (0xb56eab9a5fff323e, 0x38d9a91f973ec303), + (0xbc52de1143765a96, 0x3fc9c6cf582cbf7f), + (0xbc3b84c5dde43674, 0xbf91f06d14e11e02), + (0x3c27767d9698b536, 0xbf8b589d1da13905), + (0x3beae1afe6c3eeda, 0x3f50f9103cf5b152), + (0x3bd3e8ae8dea10a7, 0x3f386445621cc085), + (0x3b8a8905b308cb21, 0xbefa2a033ccf2705), + (0xbb6859e8c0ae37ce, 0xbed83a06e30c4109), + (0xbb3d54a069e9c64a, 0x3e96a4fd997104b3), + (0x3af989d32babfca4, 0x3e6ec03c7b7d1357), + (0xbab1ecf377bfa04f, 0xbe295db03343bc40), + (0xba90b0b6e5fe7551, 0xbdfb1e242e3fafb5), + (0x3a3fd469738e9f05, 0x3db3fa9bccb27cd1), + (0xba1b0f91d98a1070, 0x3d8195cae4f67f9d), + (0xb9ba66f04112da4a, 0xbd3762afe2a5cc10), + (0xb99f157bfc6eaf25, 0xbd017a40c9422e17), + (0x39512dfe72026e3a, 0x3cb52a10c3c6a274), + (0x390b50bb7a057314, 0x3c7b78e32c0ddf7a), + (0x38b2f2ab795ef554, 0xbc2e86449ded35db), + (0x3886128863c137b0, 0xbbf180413173c4a1), + (0x3830411cc8598621, 0x3ba1f599693c21d5), + (0x38061e9b17fc3c4e, 0x3b62704bba47e657), + (0x37ba5ced95be86b1, 0xbb119329ee1d3fb9), + ], + [ + (0xb5bc6f55d4dac0c2, 0xb916caed64280f3e), + (0xbc6af17f78e58353, 0x3fd5c6e60a097823), + (0xbc22c1940b65933b, 0xbf9f8f72e7a848e0), + (0x3c39226a6968a5d4, 0xbfab2150cb41e8c1), + (0xbc0ead94b776cda6, 0x3f72f7ffe90256bb), + (0xbbdc44bdbe1112fc, 0x3f627e31fe9a9779), + (0xbbc64599a8123499, 0xbf26f641f41956f7), + (0xbb948616b6922642, 0xbf0863f481a43036), + (0x3b680f8935f5af0c, 0x3ecad77d748a06db), + (0x3b3cc25f06059d1b, 0x3ea32e6d99c6af7d), + (0xbac3305a73e5ec68, 0xbe62da37e38435b9), + (0xbad5c613351595f6, 0xbe341d72d9392e0e), + (0xba9c8106c7bc6fb7, 0x3df1d0433d9a0e49), + (0x3a54e8ace2031b36, 0x3dbe2f3389aa5f69), + (0x3a1a0f5d1cba1387, 0xbd78498ffdebdd63), + (0x39c72f8fafe52f38, 0xbd410477aeae347a), + (0x398287fc3bba485f, 0x3cf911a8d781ae91), + (0x395788d424859469, 0x3cbde68af47fa3dd), + (0xb914472b326b8d7e, 0xbc744b3881dbc1de), + (0x38d8ef43414cc878, 0xbc350be81f6c25f7), + (0x388738457ea68eb1, 0x3bea7a3cd386daef), + (0x381867e5c9a67b59, 0x3ba845cae670510a), + (0xb7fd1902fcb38c68, 0xbb5c71de4246f315), + (0xb7bbe92f443184c2, 0xbb175a569f596544), + ], + [ + (0x3c7af22d033ee0a4, 0x3fd33518b3874e8a), + (0xb5a1c201a4cbcd4f, 0x390f8a0b194e92aa), + (0xbc6af22d033ee0a5, 0xbfc33518b3874e8a), + (0xbc006437c8a4bc6d, 0x3f7d34125d59d8ff), + (0x3c276d8715df682d, 0x3f880c83bdeee5b0), + (0x3be68431910b0ef3, 0xbf4483c20f1cb1cf), + (0xbbb05a9f39ef055c, 0xbf36ffa5fc8cad74), + (0x3b913c3053e04d46, 0x3ef2ccf7b21fff81), + (0x3b34763d026d3263, 0x3ed796a751f89051), + (0x3b28d27038a5d6ff, 0xbe91e850e4c28d2e), + (0xbb0dacba8ae06269, 0xbe6e6a49ae425df4), + (0x3abf3eddd6df5c90, 0x3e254c4387ef6820), + (0xba918835ce9eaca7, 0x3dfb084d1fe8eb88), + (0x3a5d71d0cc12f311, 0xbdb177e06f2957d2), + (0x3a128331bef5dabb, 0xbd8198853f2794c4), + (0xb9d9afdf19b00f9a, 0x3d350c2b4db26303), + (0x399d5420c79c50f5, 0x3d0183edbb8ef55e), + (0x3950904a54f66bdd, 0xbcb376d167cfd12b), + (0x3900fa2cc4b5e6f2, 0xbc7b8a653f1cd809), + (0x38c18dc8b4e37444, 0x3c2c8b097fe47227), + (0x38721faa0c98eabc, 0x3bf189c13e615d1f), + (0x384e91176ed97cac, 0xbba1041440ddec2d), + (0x380179051848c349, 0xbb6276b7a23c8925), + (0x37b217667c662a42, 0x3b10d45d32f264a5), + ], + [ + (0xb5a271a164439dcf, 0x39091ad14f5534e3), + (0x3c70b85158068ef8, 0xbfd15f7977a772d4), + (0x3c1371b46642ace0, 0x3f900f7fcf183e0d), + (0xbc44d97f9ccedb81, 0x3fa68b984ec6493c), + (0x3c042ebf64ab2f7d, 0xbf648e63600d8418), + (0xbbeee6fe26323549, 0xbf60e0d60385a6f0), + (0x3baeef0ba4a3d132, 0x3f1d796052775aab), + (0xbba7aac08a2ef0bb, 0x3f07800bc550673c), + (0xbb5a88016ef7845c, 0xbec3324842f7d51c), + (0xbb4a5fc6166e08e4, 0xbea30e8cc35f2086), + (0x3ae456e8b4cd8ab1, 0x3e5ceda479a13c54), + (0xbad32f77090cf486, 0x3e34582cb217a0ff), + (0xba896f49e7d71906, 0xbdecade19f5ddb10), + (0x3a21bb7dfbc8d1d7, 0xbdbedafbed1c0039), + (0x3a0e246bb345d838, 0x3d743c230e74f083), + (0xb9ef2b99a0d63f0b, 0x3d41820d4a50e7ac), + (0x39930eba3f48ee4f, 0xbcf56d4abfa3f75e), + (0xb9404cba8724060b, 0xbcbee1c963b55043), + (0x38e5999953118f29, 0x3c71b059736ac012), + (0xb8670d7b409cc9b1, 0x3c35c975cfa56031), + (0x38874e8a77d0b989, 0xbbe76ff93efd4a1a), + (0xb846172c476991f2, 0xbba9288634dcae38), + (0xb7c3ad53cba7bf5d, 0x3b597e272f8ae371), + (0xb793a523f540949e, 0x3b183832a1cf9585), + ], + [ + (0xbc5052a3a2541c57, 0xbfcff654544ebcd1), + (0xb59d2cb904ed26e5, 0xb8f8cdeedd7089d9), + (0x3c4052a3a2541c57, 0x3fbff654544ebcd1), + (0xbc1261ff874d8f29, 0xbf70c17ff72afae7), + (0x3c123a275590a85f, 0xbf84b0c5d5da6789), + (0xbbda98843bd20bfa, 0x3f394154be70ed46), + (0x3bd7d4055bf0fe2a, 0x3f34e12c3067bef4), + (0x3b83b9ba50d44e92, 0xbee9f32fc25ad134), + (0x3b7dd3415a058d7b, 0xbed63c5475439cb2), + (0xbb2e30b182db0623, 0x3e8adbafdf1415b1), + (0xbb03faa98b08aa74, 0x3e6d601d278516f5), + (0xba8bdda43ca62c5a, 0xbe20eedcab593552), + (0x3a9e2fad33581bf9, 0xbdfa84fedb589fe9), + (0xba43dc502b3bc37b, 0x3dacf8e343fe2283), + (0x3a20042e6b66d5ce, 0x3d81702cfaaee589), + (0x399e7a30f53ca26c, 0xbd320271d8cd44dc), + (0x39a5f9316e1c5efa, 0xbd01797e5eacddfb), + (0xb9547c274818e871, 0x3cb10ed3b5c9be93), + (0x390484c268c0ce85, 0x3c7b98f45921983a), + (0x38c24e5982383c83, 0xbc297cbf7079afbf), + (0x389b277576e91bd0, 0xbbf1a00382f67f4b), + (0xb81f48467ddb418e, 0x3b9ed8b7eb419122), + (0x37fcd9d0b0e535bf, 0x3b629700d2c00fd9), + (0x379a08401f2ad096, 0xbb0ee1e52f6de1ed), + ], + [ + (0x35857c582b5ea1c9, 0x390bee0ed8c1329b), + (0xbc56d72d40e790b3, 0x3fcdc13e66ac2e77), + (0xbc17a0058564dc78, 0xbf842ff0cdc58463), + (0xbc4ea7eea5885b06, 0xbfa38d1dd8992e04), + (0xbbe0000f328100a7, 0x3f5a55e9b346edc1), + (0xbbf1ad5da35cf264, 0x3f5e2e16f97d0a81), + (0x3bba0bf2d8b00c54, 0xbf13dfc3782af205), + (0x3baf5778b0601b70, 0xbf05ce7f496656d0), + (0x3b554dd7e814f538, 0x3ebbb178da9c4ac0), + (0x3b4faa40f4ef4735, 0x3ea2346d74940be8), + (0x3afda3f1a9c16a33, 0xbe5612f2e799b732), + (0x3ab1ff4f9f08910e, 0xbe33d79882e5df9f), + (0xba8b82d54967fe42, 0x3de6dbc112bdb279), + (0x3a54c5a3f521e570, 0x3dbe88c4d898d665), + (0x3a0aab5610ed8408, 0xbd70ad880fc1e195), + (0x39ecb4a2ad16ceb5, 0xbd4180d64e2c4131), + (0xb99c77042f820598, 0x3cf22094137f7e15), + (0xb94dafad35b07003, 0x3cbf18a8509fa48c), + (0x390d0551dfd7b655, 0xbc6e8dc12bc24aba), + (0x38c7f144bd8a3779, 0xbc360ce090718b01), + (0x3887e3ff32f169c4, 0x3be4947b20d26a23), + (0x384fdb50bbf01aa8, 0x3ba98e129bc0f8a1), + (0xb7f91bc574623289, 0xbb56b091d8385139), + (0x37b564d63f3376cc, 0xbb18aa3f6c83b7e7), + ], + [ + (0x3c6c8c66d2e42062, 0x3fcbf3337873a7d8), + (0xb540e662913e9721, 0xb8b8ae14acc03cc2), + (0xbc5c8c66d2e42062, 0xbfbbf3337873a7d8), + (0x3bfaea5f3639483f, 0x3f66604d91f926ee), + (0xbc24192692d7c9db, 0x3f8251858011816b), + (0xbbdcdb12750487fd, 0xbf314bc11a32c246), + (0x3bd50548750ad314, 0xbf32e7decd1f73a5), + (0xbb847a9ca039b976, 0x3ee293b4c9a24966), + (0x3b6e3a426e412d42, 0x3ed4a6704d05ad0b), + (0x3b1253e91cb63be7, 0xbe843ca9b71b6996), + (0x3afbda58c238f16a, 0xbe6bddfbf35630ba), + (0x3aba3f365a5e64b5, 0x3e1aae76737061da), + (0x3a96b049b0e48195, 0x3df992424643ff64), + (0x3a42ad17879fc5b9, 0xbda7aad4b0989ad6), + (0xba22956ea0fa52e3, 0xbd81051e84a7a86a), + (0x39c7f26c2e23f425, 0x3d2e49ae1a0e9424), + (0xb998466ad52efa61, 0x3d013585a9b7473f), + (0xb93c2bb2beb0ccde, 0xbcad5c6820d4c19c), + (0xb90356383e63d305, 0xbc7b5bcfc1f36461), + (0xb8714991402d4264, 0x3c2659e097d2d299), + (0x3893b54f82b6acd5, 0x3bf18eefb530cdde), + (0x380fec88aec6bc4b, 0xbb9b78694703192c), + (0x37fadce1d8598d3f, 0xbb6296435cd2331f), + (0xb7a9cd5a8e59cb5f, 0x3b0bdae97028e6a9), + ], + [ + (0x35ac59c6428de284, 0x390f184285843311), + (0x3c32010996eec734, 0xbfca701d0f967500), + (0xbc1331fb2bff5c30, 0x3f7c54b930fef892), + (0x3c44240355876f9f, 0x3fa17798aa09f11f), + (0xbbf91cbfe509a337, 0xbf52a2151407dd09), + (0xbbeaf2596bf8cd55, 0xbf5b541f829bfb41), + (0x3b9678567dcb0401, 0x3f0cc0bda19ffe34), + (0x3b7cc73ae3f8a72f, 0x3f041f3b0662f49e), + (0x3b50b073a3604389, 0xbeb4b230b114b149), + (0xbb39f6a1ea249aed, 0xbea1223e2bd0689f), + (0xbad9dcc2b787e5e9, 0x3e511963968a437f), + (0xbade1245aa3f79f6, 0x3e32ffb8dedaa0e5), + (0xba7ddb5234f87c44, 0xbde24c47f1c46f88), + (0x3a4b24f96f04dc6f, 0xbdbda527540ac89a), + (0x3a002159e830fd60, 0x3d6b75eeb2587be0), + (0x39a7a5cb88cfcf0b, 0x3d412dcf9e14b526), + (0x39536a23b6e364bc, 0xbcee8dc94e61fd9e), + (0x39406182c6b2e611, 0xbcbec6e9eeb29dec), + (0xb8fb12be3176058a, 0x3c6a411ab303dfdb), + (0xb8da27a89b185f00, 0x3c35f7175a19426f), + (0x388abe97716ef10a, 0xbbe1f8d987025207), + (0x383e3b32dc10b94d, 0xbba99550856225f2), + (0xb7e9ddb15c3ea3e0, 0x3b5415925aa1431b), + (0x3795803255a3ea0c, 0x3b18c98cea89bbf7), + ], + [ + (0x3c6e9557ccd1703f, 0xbfc925c6fca08f55), + (0x35a0840c3eb5c8e9, 0x3909bb79105907c8), + (0xbc5e9557ccd1703f, 0x3fb925c6fca08f55), + (0xbbf0bd4a4617bca0, 0xbf6049377403bcb4), + (0xbc1dac1b118bb946, 0xbf809463bbd0367f), + (0xbbbd1ccb5b6a209d, 0x3f297b354706c53c), + (0xbbdfefc73ab9ea4c, 0x3f314dd4404e5fcc), + (0xbb7689ff8e8b648e, 0xbedbf665d5afcb1e), + (0xbb55632e0e751036, 0xbed32cb00ee8c1f3), + (0x3b168e07e41d973b, 0x3e7f50fa815b542a), + (0xbaeb09f8b87a4826, 0x3e6a4339e5f906ee), + (0x3ab370c114b8364e, 0xbe1541c07333f998), + (0x3a95f92ca4cd1f66, 0xbdf86c0bb112e485), + (0x3a3d7a90841bd326, 0x3da35fba37d1f6f7), + (0xba2b575752323f67, 0x3d80700770cc15dd), + (0xb9557a6df0847bf2, 0xbd2963b203086961), + (0x3994060b8e456ec8, 0xbd00c58770231c0a), + (0x3934b091af50e5cb, 0x3ca91e0b939f2d33), + (0xb91ee976639f1136, 0x3c7adb6f69ceb591), + (0xb8b63616ac9c64e9, 0xbc2373e3cab8e402), + (0x387455d8787bd080, 0xbbf156093877495b), + (0x3823f244d844aa0f, 0x3b9842736a626a94), + (0x37f3628fad20886f, 0x3b626f881139ee38), + (0x379bb0027a1cd34e, 0xbb08e814b7cab6b6), + ], + [ + (0xb59e68fd63ab1a3d, 0xb8fc6246c85a6640), + (0x3c4a4f96a2520bad, 0x3fc8077f56c9b782), + (0xbbf97f76587fd9cb, 0xbf75467eb535deaa), + (0x3c28681fd3a1faac, 0xbf9fd7c3ad6f59e0), + (0x3be0e0f0ccfb4015, 0x3f4c1b47c809c5eb), + (0x3bf6295d17a16103, 0x3f59166c7d3eaa7c), + (0xbba4cf48882a0699, 0xbf05f0152478f5f6), + (0x3ba861e7d6d89ac5, 0xbf02aa939fd9fc9b), + (0xbb5e0f27f02ffdbc, 0x3eb0129708ec2410), + (0x3b4393e44832fa90, 0x3ea01716dc9f2e1b), + (0x3acfaffff96cb541, 0xbe4b227eef409a9c), + (0xbadf064b85fdb242, 0xbe32101c49d611c3), + (0xba4ba7b2c5f1707c, 0x3dddb1e8b7adba5e), + (0x3a5a73ba24830cae, 0x3dbc80aab1d9322c), + (0xba00db3fc0b0c1ba, 0xbd66c2b17ab71886), + (0x39e8d291d0b4d27a, 0xbd40ad5f60b542e8), + (0x3973527417cabd58, 0x3ce9d02ffd593bab), + (0xb950911cb567e2a5, 0x3cbe1eda1d51b8b7), + (0xb8f1f756b53acec7, 0xbc668e76453989dd), + (0x38c7df6bb93ac8ec, 0xbc35a3dd5c2dd312), + (0x387c31c12e84cbf7, 0x3bdf55d5df5603a5), + (0x381a4e01bffe5027, 0x3ba95785174d99bc), + (0xb7f4002fdaa22aa2, 0xbb51bb3ba4b3316a), + (0xb7b1fe1d3a814203, 0xbb18a987773fb87c), + ], + [ + (0x3c62da0057f84d3c, 0x3fc70c511227d5aa), + (0xb590c69cd835e65a, 0xb8fbdadd24cf38cb), + (0xbc52da0057f84d3c, 0xbfb70c511227d5aa), + (0x3bfe726f70245274, 0x3f5910ebe1f1cbcd), + (0xbc0e61277dedf705, 0x3f7e7dc08e70e99a), + (0x3bb740aaea2c85b5, 0xbf23bd7d159e09a5), + (0x3bc9abf12a21a247, 0xbf300357a187375c), + (0x3b7cab62f60660b1, 0x3ed5ec73302455b1), + (0xbb76a66de44f6f2b, 0x3ed1e5d2836c8d99), + (0xbad13f153900acfb, 0xbe78f41b94dfba1f), + (0xbaff3652c8e5edf0, 0xbe68c11aada79ae8), + (0xbaa209f480ef1062, 0x3e1141423452a28d), + (0x3a9e19c8e523a095, 0x3df73ef6f4772772), + (0xba405794c4ab8e4d, 0xbda007403efd2c9a), + (0xb9c2a7b0a727a022, 0xbd7f93ab6667901d), + (0xb9c5c7ae4a96c60d, 0x3d25638d0e0d9767), + (0xb942fb1c3cc08579, 0x3d003d0592185f1c), + (0x39373a63f1b5e963, 0xbca5832b6c129523), + (0xb916b9966d8ed631, 0xbc7a2e88ff86af9c), + (0x38c0ec56239fb4ce, 0x3c20e8839dc5443a), + (0x3884c544300024fc, 0x3bf0ff71f08432b7), + (0x3829d5c62bdc57b6, 0xbb955cc426feea1c), + (0xb7ff81402cdf65ad, 0xbb6229c7418b10f0), + (0x3773be52416792c2, 0x3b062f08720eaee7), + ], + [ + (0x35a8346aa8f5b4bb, 0xb909c0fc24f65a67), + (0xbc6444d3d89ac00f, 0xbfc62d93aa9d05bb), + (0xbc1afb8f729be80a, 0x3f70ba9ce88929f2), + (0xbc2f64ee23828a95, 0x3f9d7073daebb02c), + (0x3bd6ad884b57cbba, 0xbf462813c7f58733), + (0xbbc1c5da610ae750, 0xbf574a948d05638e), + (0x3ba7816485085533, 0x3f01695765f13bbf), + (0x3b9157b692bbea45, 0x3f0170ab5eeb0e4e), + (0x3b2715c0e1d13855, 0xbea9c8e418a20315), + (0x3b394c7caa0cf226, 0xbe9e4d893dce335e), + (0xbaee8ffa7c53b5fb, 0x3e460f73a6ccb16f), + (0x3ad92747d94d94d7, 0x3e312782f0f2448a), + (0x3a5745f5f5b1bc73, 0xbdd881d5842ec670), + (0xba53516c45370c96, 0xbdbb4c521a316133), + (0x39f845348a27f4b9, 0x3d63132da6b9ef80), + (0xb9e1395c98d19f4a, 0x3d4019364d86610c), + (0xb973bba720cb85bf, 0xbce5f4ab616b4a7d), + (0xb92365a073b465df, 0xbcbd47ca99f425b7), + (0xb90304c2a5a66771, 0x3c637371b17caa3a), + (0xb8dc112a193fb5f1, 0x3c352a819018d0f2), + (0x387a7ad3dc13170e, 0xbbdb5c2ea7518f33), + (0xb848fe010506d44a, 0xbba8eaf2df7cede6), + (0xb7e6b127ce015440, 0x3b4f4fdfa642b717), + (0xb7a66fe7bcf681da, 0x3b185bcb7268f7c2), + ], + [ + (0x3c6a47ab4241a9f5, 0xbfc5664e13b70622), + (0xb5ac924d5c123479, 0x3900f098dc38e480), + (0xbc5a47ab4241a9f5, 0x3fb5664e13b70622), + (0x3bddc134f1d74a51, 0xbf540ee3940b092f), + (0xbbffe75afd6ce0fa, 0xbf7c5e1ad9fb2f40), + (0xbbab866102da4707, 0x3f1fb8a98ef4a243), + (0xbbc018bed7b77750, 0x3f2de9be58a373e2), + (0xbb75089b2cae9b03, 0xbed1bec95415e630), + (0x3b447f8eea3cc056, 0xbed0cf264341409e), + (0x3ac71d5b65310e89, 0x3e74677d9e214cd4), + (0x3b026d69949fca90, 0x3e6766cc63507104), + (0xba902c01ede1dfd5, 0xbe0c905882b94f65), + (0xba995672d0443f95, 0xbdf62157963573dc), + (0xba18987abee2ab90, 0x3d9ae2e0cbb67b06), + (0x3a01b88c86e07d4b, 0x3d7e456a1c8dbf40), + (0xb9a82e3122996ca9, 0xbd222e4736637ff5), + (0x397f896eb454c48a, 0xbcff56a09da19f70), + (0xb939b4426eb8647c, 0x3ca28607cce512f7), + (0x38da5f520ae3c80c, 0x3c796a2f3d059107), + (0xb8bff36f14735622, 0xbc1d78e82e3dfe4c), + (0xb8985995658ccf15, 0xbbf096501f12c820), + (0x381ac1859ffca23b, 0x3b92d35996fa684b), + (0xb808697949d6df60, 0x3b61ce65ead2f56a), + (0x37a076885f254fcf, 0xbb03bf2c7d52312b), + ], + [ + (0x357834c50798eee0, 0xb9046916861c7cbe), + (0xbc6e5d93454f99e3, 0x3fc4b2a2ebf61ece), + (0x3bf37b02bd5f53a6, 0xbf6b3297fdae7902), + (0x3c2eb354a6313bb4, 0xbf9b8105d59b114c), + (0x3bb9bab6138b6903, 0x3f420a3f8c12a1ff), + (0xbbf48ec1e2fa78e5, 0x3f55d18d69de6cfb), + (0x3b0ad2f6c6600043, 0xbefc79db4b341e8e), + (0x3b70c098a1ba083c, 0xbf00679c92c303b2), + (0xbb4af505f8420dfd, 0x3ea53ac4ecd4be2d), + (0x3b3bd880347c15c4, 0x3e9ca7507840c04b), + (0xbadbc0ebcece96aa, 0xbe4253415f09767a), + (0x3a8f2f3402a0f194, 0xbe305141505c9f00), + (0xba73147caddad17a, 0x3dd4919940f05339), + (0x3a20801c08cd53d5, 0x3dba20de95780e25), + (0x3a0aad83cdc61600, 0xbd602fff3daabeb6), + (0xb9cd95539d508286, 0xbd3f01d18581b85a), + (0x3986a1dccaaee4ac, 0x3ce2d78e0d95c2b1), + (0xb9420e56b2382383, 0x3cbc5cc76fc4031e), + (0x390db41e1b715d4d, 0xbc60e00793400a38), + (0xb8d97d5c56eaa5d3, 0xbc349c9cebd4542b), + (0xb87767b6f54f3ae0, 0x3bd7fb7ba24468a5), + (0x384f6e8dcd984b87, 0x3ba861a49c8b4594), + (0xb7a3310c04ca52f6, 0xbb4bb5b1358f5d66), + (0xb7bf2be7dc5aa7d5, 0xbb17ef6c51c02185), + ], + [ + (0x3c6316f8ffd294bc, 0x3fc40f90793605bb), + (0xb57f9e2ffd50aa0c, 0xb8e84b55d671e3ab), + (0xbc5316f8ffd294bc, 0xbfb40f90793605bb), + (0x3bf7017919c133d4, 0x3f5085775a5529c9), + (0xbbe51eb6f09db1a0, 0x3f7aa0ce0421d1a8), + (0x3bb34ca5aae2a0a8, 0xbf1a32a28e4bc82e), + (0x3b829f8de1c1e358, 0xbf2c26ebca0e46de), + (0xbb655efa83f66d77, 0x3ecd7400876206d0), + (0x3b4cb5b0088841fe, 0x3ecfc1bbf57e3ae2), + (0xbb1b0133a27f94ef, 0xbe710c7090487d3e), + (0x3aef5fb8bc32c77a, 0xbe6634db39e4a305), + (0x3aa91e07a77165aa, 0x3e0810d7e4efab49), + (0x3a839aaf703b3d25, 0x3df51b513b3c4cf1), + (0x3a336ceec537a192, 0xbd96dd877beb3775), + (0xba0a1b2154c0dad9, 0xbd7d06057acf98a1), + (0xb9b49d50f1878b22, 0x3d1f3b007c53631a), + (0x3998369e87f01d70, 0x3cfe341812329072), + (0x394269c561f0abb0, 0xbca0119135f2618c), + (0x390e03cff1d48846, 0xbc789daf7e05bf20), + (0xb89d5c1dd0bd003d, 0x3c19d09c42c2fd20), + (0xb89ec3091d0a20a5, 0x3bf023bdfeef2b62), + (0x383eea157ba50462, 0xbb90a443b12390a2), + (0x380faad5050249de, 0xbb6165e9e44cf4fc), + (0x37ac0bb1b2874365, 0x3b019b4693645186), + ], + [ + (0xb563251dec0c8419, 0xb90190e21085c59e), + (0x3c5948539688f9cf, 0xbfc37aac8c1aeabb), + (0x3c0e1b9871576e7b, 0x3f66ac0d2e2f2f87), + (0xbc3e2c9f8f0de524, 0x3f99e74e754ea71f), + (0x3bc834f161e5b53a, 0xbf3e1c0589e32bb1), + (0x3bfe8b15bd1b2805, 0xbf5496158dc5f7ff), + (0x3b66422c8ac686b8, 0x3ef7d55405348ca9), + (0x3b9138881216a9f6, 0x3eff0b30f4506228), + (0xbb49c5af94afc68e, 0xbea1d9e3629b98ec), + (0x3b31cbe80255f739, 0xbe9b35ef28e9de24), + (0x3ac5335f73a99784, 0x3e3f0200e2650870), + (0xbacc80c87bd0e106, 0x3e2f1fb225e849cb), + (0xba76daf9021379d3, 0xbdd187928a64d042), + (0xba42b8804ba3e9e1, 0xbdb908ba84482af1), + (0xb9f798e4ea85d67c, 0x3d5bd0a97427e582), + (0x39ae28268a102015, 0x3d3dd98a1888cb0d), + (0x39800b32153c5fbf, 0xbce05368fdb3dbd3), + (0x395973c2e28b46eb, 0xbcbb6e7eba27d4df), + (0xb8fd64860bbe4d9f, 0x3c5d7e5c8f77a962), + (0x388996f5c1af67cd, 0x3c34063c16fd02be), + (0x386cbbfcf555cb4a, 0xbbd52213fb27642b), + (0x384eb9fd51a68df4, 0xbba7c8fd7f555061), + (0xb7c915bb96c79ac0, 0x3b489cfc43bd06a7), + (0x37bcc11a3c54068e, 0x3b177056c238889b), + ], + [ + (0x3c689d1f48185c7e, 0xbfc2f2072e638cf4), + (0xb5952cb9317551e1, 0x3901222bb44bcf14), + (0xbc589d1f48185c7e, 0x3fb2f2072e638cf4), + (0x3be64a78bbbb198f, 0xbf4bd42b64fc5bed), + (0x3c082c4cf012e7aa, 0xbf792bb5e1e159fc), + (0x3ba0f7052b5160b8, 0x3f161ace3386dfd7), + (0xbbc911bb758a62b7, 0x3f2aa8d1cf8db852), + (0x3b53e6d95cbd37f7, 0xbec8ef624c36fc32), + (0x3b54f1d79d1c68cf, 0xbece26d3747fe829), + (0x3b0b9f4f6af339a7, 0x3e6d010d2bdb6fa2), + (0xbb08db6527b88cec, 0x3e65272828ae4057), + (0x3a509976106e8349, 0xbe0497b03c4482e4), + (0x3a79f5e122b84d8f, 0xbdf42e35495a0b9f), + (0x39cbebe4937d13e3, 0x3d93b2e62efa9ef3), + (0x3a14579198fd4bcf, 0x3d7bdc7867dae011), + (0xb9bf0d7f81848e9e, 0xbd1b1acb454ca400), + (0xb97ccb74999a40d8, 0xbcfd1ce7997b3c0d), + (0xb9380511e3a7c101, 0x3c9c1b1fc8c0e04f), + (0x38cac264c6c80d21, 0x3c77d2b971f6828b), + (0xb8b8eacaf1c3a530, 0xbc16c0313e58129c), + (0xb85cf03733411e25, 0xbbef5c5d17f54410), + (0x3815be1ad7496a82, 0x3b8d8dcf1e84a9c2), + (0xb7e5c044edc6060a, 0x3b60f6f0c4603224), + (0x379126e0d0da66b9, 0xbaff7e6aff22be1e), + ], + [ + (0xb5627bd5768d6ae9, 0x38cc4a2cf6a18867), + (0xbc389c717cff1eba, 0x3fc27407dfadee6d), + (0x3c01b3998e2560e2, 0xbf6346950bfd91f1), + (0x3c3dd532243e7d0c, 0xbf988d48d1d4eb7b), + (0x3bcf03d11aeaafca, 0x3f399e6923ada922), + (0x3bf2c9a985cf61c7, 0x3f538984b76cdf4a), + (0x3b96fc0cb69470ac, 0xbef452194b75f3c7), + (0xbb929abb7ce27bd1, 0xbefd855d7b8f0243), + (0x3b33da9849a0f970, 0x3e9e8a88601ff296), + (0x3aebb8f5815fd80b, 0x3e99f1bd69b16e6b), + (0x3ac86d0d07634a8b, 0xbe3aa483fce054e3), + (0x3ac5ab23f0a90bfb, 0xbe2dc4c02391c504), + (0x3a69996a456ab65e, 0x3dce48dc1b4db792), + (0x3a30cc58e232dc0c, 0x3db807112e6636fd), + (0x39f6e9562163f106, 0xbd582c0e5f51b3f0), + (0xb9c5c661501e7ee5, 0xbd3cc1592707b4bb), + (0x3966aa764333f3df, 0x3cdc8f29e796ad34), + (0xb95785ee30c62c1f, 0x3cba864ef1faff74), + (0xb8ff8a02ad81ef19, 0xbc59f854cbd9efdc), + (0x384627f385cebec8, 0xbc336efc940e4c98), + (0xb87617b5b0e9289b, 0x3bd2bbd3c0ba4c14), + (0xb84c5ed87745f0e5, 0x3ba72a3898c03cd9), + (0x37e4b8d60a63fdb3, 0xbb45f681005965fc), + (0xb7a7ad15bf5e48a5, 0xbb16e75915fef489), + ], + [ + (0x3c51f9b16832f362, 0x3fc1ff5eec6a01cd), + (0xb59a05b7856c4a22, 0xb8ff07a73b062717), + (0xbc41f9b16832f362, 0xbfb1ff5eec6a01cd), + (0xbbe5f2ed43d9b503, 0x3f47daf64983af9d), + (0xbc19a4b7b3ed5b9d, 0x3f77ed5fffc1c774), + (0xbbafa9d6f1d224d2, 0xbf12f947962314a1), + (0x3bba27855de20282, 0xbf296027ea1d6e5c), + (0xbb585d6672f6864b, 0x3ec57486c67fbc78), + (0x3b6dbae692eab5c3, 0x3eccc11a59e13739), + (0x3b07ece30b8718ed, 0xbe690ade515567ae), + (0x3afec36878fc6271, 0xbe6438a7e22c9734), + (0x3aac5fba9cf90508, 0x3e01db6d29a7d048), + (0x3a9c694efcaf05a9, 0x3df3588cd299009a), + (0xba304f511d090519, 0xbd912b3d3f46a11d), + (0xba1f96e81c9933ce, 0xbd7aca95934e0ad5), + (0x39a4c6d8ef3baa67, 0x3d17c19e5c2a3a3a), + (0xb98de02178f2e8a7, 0x3cfc15e96b25adba), + (0x3904b1879dbd8e47, 0xbc98c7e06842ee3d), + (0xb8f76e2dea2e96ba, 0xbc770ecfbf61ca0d), + (0x38b68e1efbe2a988, 0x3c142e95d318b6f5), + (0xb874c2ceb9ea4228, 0x3bee73932c419ab8), + (0x37f46e3304b4ae0c, 0xbb8a60b7a857ccc0), + (0x380c4d64ccf85fc7, 0xbb608626d8e04736), + (0xb7990c5c39207c1f, 0x3afc47487352322d), + ], + [ + (0x35ab7cbed9b6b1f4, 0x390239f235357955), + (0x3c6f5f4b08a76fd4, 0xbfc192f23ce3e051), + (0x3bdee957b8603928, 0x3f60a668185c01b1), + (0x3c39de5fb6906a4e, 0x3f9764141d652089), + (0x3bd0a73bf1673e03, 0xbf3624437a2fe76a), + (0xbbe29f0dad749d08, 0xbf52a184be0d9891), + (0x3b92247582470aeb, 0x3ef196de0eeef190), + (0x3b54bbca179d7e5e, 0x3efc317f854112ad), + (0xbb3c4937a266ae2b, 0xbe9a8019ef772196), + (0x3b1fa8fc16fd89b6, 0xbe98d38497beea33), + (0x3ad1777abda5cdbe, 0x3e37318410813eeb), + (0xbaa199670acf66d4, 0x3e2c8d9d45d76323), + (0x3a61c9a46bc0a86d, 0xbdca782c1acc5d80), + (0xba47414175e77281, 0xbdb71bbb74f830ea), + (0x39fb21ba4fd0050e, 0x3d5539502b6b0d41), + (0x39bde0e950bf1a4a, 0x3d3bbc22cd6ef8b2), + (0xb951eab6630258a6, 0xbcd933a6402470d3), + (0xb90f7f72f87b85f2, 0xbcb9a8f9bcb762d2), + (0xb8f0fd489e307f2b, 0x3c5709caa1708994), + (0xb8bf22055786ef23, 0x3c32db59b73d17f0), + (0xb84510913d0bb141, 0xbbd0b5801d4ebd68), + (0xb83e3fe31926f1ed, 0xbba68b53041d22be), + (0xb7ecd50940caefad, 0x3b43b217fd3ffb23), + (0x37a50bcc9d97c7ac, 0x3b165a991dfc9832), + ], + [ + (0x3c6e71c482be67bd, 0xbfc12dd57bf18ada), + (0x35745b4d4ccbb68f, 0x38d7a991cf97ce2e), + (0xbc5e71c482be67bd, 0x3fb12dd57bf18ada), + (0x3bd11b1ac52dc1e2, 0xbf44bebeff7b7f02), + (0xbc1286f932bea2b2, 0xbf76d9afe88301fa), + (0x3b859ae0593310ce, 0x3f10842d50687949), + (0xbbc5025e938d5cb6, 0x3f2841d86b9b92f4), + (0x3b45bc90ed56ac34, 0xbec2b5caad1f2b9a), + (0xbb3771ef99211bfa, 0xbecb86bad42fc220), + (0x3ac3d72243d64739, 0x3e65e5117a965bcf), + (0x3b07539fc5e6a80e, 0x3e6364a25cc7309d), + (0x3a51d7761a4ff87d, 0xbdff53dcc9459e76), + (0x3a99aab279c470e8, 0xbdf297f421bb27bc), + (0xba27ed296e5c55e5, 0x3d8e3c9c7289c65b), + (0xba1d2b7fc29cc174, 0x3d79cfbae2bdc016), + (0xb99b7a6311b584d8, 0xbd1502858f3b1429), + (0x399664d160d01e32, 0xbcfb20c42e642ccd), + (0x391ef844bb66595d, 0x3c9604b99922c587), + (0xb91aa631f65ad96a, 0x3c7654ba0a2b4ab4), + (0xb8bee3929b6ac229, 0xbc120523ef69f26a), + (0xb88fba8fecf60808, 0xbbed920e28727809), + (0x3816d4cbcfecdce6, 0x3b87ab7af32311cf), + (0xb7f2f0febd96b7f0, 0x3b60169fdd2f6938), + (0x3782a08850768123, 0xbaf9808bbbe92c37), + ], + [ + (0x359dd81c30ee48fe, 0xb8f151a3aeac900c), + (0x3c53f099a5f56db3, 0x3fc0cf3ed059c573), + (0xbbff3cb9b807fae1, 0xbf5d242aa529931c), + (0x3beb544962a1a242, 0xbf96613d93b0180b), + (0x3bde039e229b4e70, 0x3f33627f261f5116), + (0x3bf7fb39963ccff5, 0x3f51d69ca0d88394), + (0xbb384fc5c48bb913, 0xbeeed574afab70fd), + (0xbb95a44313a48eb8, 0xbefb06384e48ee5b), + (0xbb387c094254f81d, 0x3e97452c65235728), + (0xbaf881554ea8f625, 0x3e97d51f133b6843), + (0xbad89e4d3b4b48e5, 0xbe346ac67a7e0c7c), + (0x3ac74865f688f55b, 0xbe2b75d66a8d7fbb), + (0x3a6411700cfe955c, 0x3dc75f5a5db478ef), + (0xba50702b7e55e69b, 0x3db64531ca4ef464), + (0x39b8d5aa5d138d2b, 0xbd52ceac14a86c69), + (0xb9b1503306d5d1c3, 0xbd3aca497ff206bc), + (0xb972644a7dcc9d17, 0x3cd66b96eb20b32f), + (0xb954b544843ae3aa, 0x3cb8d889b2e2fb84), + (0xb8e75b07f541d7cb, 0xbc5494ff17910999), + (0x38c576f2b4ee6110, 0xbc324dc265486d0f), + (0xb85a9820119b4156, 0x3bcdfc7ea51b3fad), + (0x38430f69314493a8, 0x3ba5eff892c2d831), + (0xb7dc83562058d69b, 0xbb41c095467f781e), + (0x37bbc403c5629dc3, 0xbb15ce2e25be6e38), + ], + [ + (0x3c61a13e2fee5687, 0x3fc076826cc2c191), + (0xb5391b2ea81aa5bf, 0x38c00dbc5df9a26a), + (0xbc51a13e2fee5687, 0xbfb076826cc2c191), + (0x3be79f62aa488a9d, 0x3f4241b03eaaf5d9), + (0xbc15dbe9d7210c2e, 0x3f75e7f53001e4b1), + (0x3ba5f4ab61cd1e51, 0xbf0d17978e2d0336), + (0xbbb79a683ed1c80a, 0xbf2745b0df80666a), + (0x3b63b64ff7d7f045, 0x3ec0803f7f7fe323), + (0xbb50168184fb2a2f, 0x3eca7006e6ad9cfe), + (0xbb09b47df06e299a, 0xbe63590d57d48525), + (0xbad3c549213b58f2, 0xbe62a7084b42b890), + (0x3a391d2842dc92cf, 0x3dfbc0dd5a22c9a6), + (0xba9fb98847ec903b, 0x3df1e9e4e20477cd), + (0xba2be602f82a15a9, 0xbd8ade1de2460eb2), + (0x3a17881703d93302, 0xbd78ea3bc5e51ddd), + (0x397ca6386538b34a, 0x3d12bb86a88ccf82), + (0x399525cc1707dd4e, 0x3cfa3d6bcad0c3fc), + (0x393d78e1fc33fbc8, 0xbc93b476152074ba), + (0x39110f06e5116481, 0xbc75a59813c6ee3d), + (0x38bc4c43696de6db, 0x3c1030bae23c4e59), + (0xb844d08b5dab4a58, 0x3becba7872c6d35c), + (0x37cead7255599d43, 0xbb855a77ed00896a), + (0x37e2184f9f8c0595, 0xbb5f548425ac1d81), + (0x3797f6a7c6e97b07, 0x3af71a13b7056576), + ], + [ + (0x357bf96ef321056c, 0x38e8be4b9ac053ef), + (0x3c665439df5bb54c, 0xbfc0230b9797a7b3), + (0x3bd7d914863ddca7, 0x3f59c8083b2b753a), + (0xbc3c455b2fe151b8, 0x3f957d3203befd90), + (0xbbd3de5214e17418, 0xbf3127cba22892de), + (0x3bf0c5ff9d698a77, 0xbf51234471455a6c), + (0xbb8a9c280a18d4c7, 0x3eeb4fe26ec3e489), + (0xbb9cd17c659ae229, 0x3ef9fc5254f1086c), + (0xbb3a46913af4f447, 0xbe94a44c6506c43f), + (0x3b3f5055c4929bc5, 0xbe96f17dd184ad59), + (0x3a9912b1a43a7c95, 0x3e3225640a6a9328), + (0xbab880b364397a7e, 0x3e2a7943505d15ed), + (0x3a4ecbcb0eff2849, 0xbdc4d296ecea7b61), + (0x3a453c61fa23edd4, 0xbdb58177059b1ee7), + (0x39e59e5790859f3e, 0x3d50cd71be5428ab), + (0xb9dab853aa81b7a6, 0x3d39eafac486dfeb), + (0x39594ed10e15fb80, 0xbcd417df1a94b2d2), + (0xb940b5960ba1aada, 0xbcb81583d885c1c9), + (0xb8fa5f714b1f1036, 0x3c52822e3f56f84b), + (0xb8da3a40678675b0, 0x3c31c75f9fd23d85), + (0x38595afb542f1092, 0xbbcb0fe75f5fce5e), + (0xb8206d9263935574, 0xbba55a4472710434), + (0x37b1baa0847432ef, 0x3b4014997c5c3405), + (0xb7baecc415e584a1, 0x3b1544b15eb627ac), + ], + [ + (0x3c5d7cc4171715a0, 0xbfbfa8b41711c83a), + (0x357640b3baebf195, 0xb8d6a301383ff88d), + (0xbc4d7cc4171715a0, 0x3fafa8b41711c83a), + (0x3bca510f3e4f0ba8, 0xbf403a8d0f110fe1), + (0x3c195ccf34fc85bb, 0xbf7511c6dadaaa12), + (0xbb6fad55e36d2414, 0x3f09e040fc62c87e), + (0x3bb45c7350ce4d8a, 0x3f266582f66d8d4c), + (0xbb2c8a29c78431da, 0xbebd62a18e287536), + (0x3b667f7ad529fbab, 0xbec976fb023f0f79), + (0x3b0f3a432d46b94e, 0x3e6141188eda6cd5), + (0x3afac6e99d820d1b, 0x3e61fc77546c2a70), + (0xba3e756c586379ea, 0xbdf8ccadf7842b28), + (0xba8280b1979ddc28, 0xbdf14c0515097baa), + (0x3a1187e8ad78c9df, 0x3d8810b7fe5b7aae), + (0xba14e29f33da57b3, 0x3d78181478442ce9), + (0xb9b79ebe6761a2d6, 0xbd10d30b1ed6e857), + (0xb995f6bc31063165, 0xbcf96afe82155a3c), + (0x3927bc733591bf77, 0x3c91c038cd6a8753), + (0xb8f984f4b5077d41, 0x3c7501961b5bf1bf), + (0xb8a4dc2a78afb902, 0xbc0d4372ee42b73d), + (0xb88b4f0dd2f40637, 0xbbebee0a131ab576), + (0xb81ffd82b16be530, 0x3b835cde101c242e), + (0x37ec5511ff967fb0, 0x3b5e84462bfb49f0), + (0x378914b866c350ff, 0xbaf50552417f971d), + ], + [ + (0xb556b1f952a5712e, 0xb8d6808df2a13f7c), + (0x3c581bdf89b0a8b1, 0x3fbf13faf32c8e0a), + (0xbbee91046256d1d1, 0xbf570558dddb7d46), + (0xbc326d6d43908d3c, 0xbf94b24d7a933972), + (0xbbb5423c2da87eef, 0x3f2ea52a21487a11), + (0xbbf33353f135e755, 0x3f50834d8f3fdd5b), + (0x3b8f2ed165228a36, 0xbee86941a4b43bea), + (0xbb93d8441684ef00, 0xbef90e32cef3e900), + (0xbb24c39a94ebc802, 0x3e92785f6385b273), + (0xbaf58f1dccae728c, 0x3e962482bf9d2bb8), + (0xbab1b25f4a923de6, 0xbe3043125386ac84), + (0x3acbae29202faa10, 0xbe29943c303e31c2), + (0xba689e50e7b79f94, 0x3dc2b2457a1921b4), + (0xba5fc1c10645d26a, 0x3db4ce82afcbf544), + (0x39e8d1c21f25be80, 0xbd4e3dcde42d462d), + (0x39cd7cc147b1feaa, 0xbd391cdf33ca55c9), + (0x396660b123953dac, 0x3cd220c06f5ae707), + (0xb95a54474bf84f20, 0x3cb75f9d03ccf4de), + (0x38e97ead5ea85772, 0xbc50be9744b83b69), + (0x38d4e9dad41717fb, 0xbc3148975b0a87db), + (0x38499800271bb705, 0x3bc88e2038a62c01), + (0xb84c766c188201e5, 0x3ba4cb4d904c6a21), + (0x37d9528d3a53acbd, 0xbb3d4587fbb07d3a), + (0x37aa22e47790bf77, 0xbb14bfb26c12f06a), + ], + [ + (0x3c0020b4016594ac, 0x3fbe8727daa3daed), + (0x357bd9f848327b9d, 0xb8d74664ec9bed14), + (0xbbf020b4016594ac, 0xbfae8727daa3daed), + (0xbbae628434d2d25b, 0x3f3d19c52e070d9f), + (0xbc1361836c532514, 0x3f74524d4813cc25), + (0xbb7cb5b9aae4885e, 0xbf0735f790b535f3), + (0xbbcfed1fabeeb9ac, 0xbf259c8f9f0a3484), + (0xbb45b8692da7d38c, 0x3eba619ffc5a3ad0), + (0x3b69523f4f9b3609, 0x3ec896d7dc819faf), + (0xbaac3c0f5c29d085, 0xbe5f04efbdfeacf4), + (0x3afee241ecc24fbe, 0xbe6162253f3024f4), + (0xba6d1ca080c948cb, 0x3df653d736c3ef75), + (0xba92d3e20a44098b, 0x3df0bc406f716b40), + (0x3a244bdd54062834, 0xbd85b5420be0cc44), + (0x3a0a9968781f3a0f, 0xbd77573e801c99fe), + (0x39a0139e52f2e139, 0x3d0e6b725d3b2ae6), + (0xb99e56935f64b195, 0x3cf8a83e6e4c168c), + (0x392ead92886f9ee6, 0xbc90163396acd7b1), + (0x391d3d6b8efb3080, 0xbc74685be0d8a97e), + (0xb8a6ef909392303e, 0x3c0a9718712afa89), + (0x385c475ef4355891, 0x3beb2d18cd37a98f), + (0x382d92b3e5d0a3a0, 0xbb81a4a7bc85c3b0), + (0x37e8bb074772c480, 0xbb5dbd9c4b52231d), + (0x3792acc4acbf596f, 0x3af335a8be4bc776), + ], + [ + (0x35982ed3998876be, 0xb8f5dc9ed9d5e051), + (0xbc5a45a53b37a59e, 0xbfbe018d99f5da1b), + (0x3be001e9c4dcf8a1, 0x3f54b85897b36265), + (0xbc32db4ef3821944, 0x3f93fc442153435d), + (0xbbcf201dea326b1a, 0xbf2b9694d71486e3), + (0xbbef8e2381ba7f64, 0xbf4fe6fdc644ddde), + (0x3b87d6d0f34bdbc3, 0x3ee5fd096e4523fb), + (0xbb6b1063264f1631, 0x3ef83770c9a84498), + (0x3b3a40ab832d99d2, 0xbe90a6f6f7e05f1b), + (0xbb3f771b18195677, 0xbe956ad4a35eb0ad), + (0x3ab57ad37dd35a78, 0x3e2d5bea474ca54f), + (0xbac551a8f3695cff, 0x3e28c39f68d21b3c), + (0x3a3d3669caabf1d6, 0xbdc0e73408ce7d88), + (0xba59b3ea5bc5c592, 0xbdb42a6dedaa1a20), + (0xb9ddcafa3dca5d8b, 0x3d4b640f953cb953), + (0x397af903fd708234, 0x3d385e74fde5ce1a), + (0x397d0253626bd0a6, 0xbcd0740945699eba), + (0x39554011a8afef74, 0xbcb6b622427cf222), + (0x38d2f100ca9a88c8, 0x3c4e76f4da90ff0f), + (0x38d40ee48b131878, 0x3c30d15eeed4b2da), + (0xb86bd3c37ebf7704, 0xbbc6647780d4dd5f), + (0x384830339986f999, 0xbba44386be6e1434), + (0x37b288dd01211d3e, 0x3b3ac32d5099a684), + (0xb7bdc2d6cb33959c, 0x3b14400df422e81f), + ], + [ + (0xbc5cb1f28997ca39, 0xbfbd8293aa55d18f), + (0x35ac5e4a18056845, 0x39005c1969d4e17b), + (0x3c4cb1f28997ca39, 0x3fad8293aa55d18f), + (0x3bb680f417abeace, 0xbf3a48fe4afedcc8), + (0xbc16c091c5e2bd3b, 0xbf73a5ccbc12a67b), + (0xbba33c90d1ef4886, 0x3f04f91e41eee9bc), + (0xbb9b30870eff030b, 0x3f24e72224db2c0e), + (0xbb169834dfa01495, 0xbeb7dac8202ad4fb), + (0x3b6372510d6e3ed7, 0xbec7cbd49c315be0), + (0x3aee3c01a205f644, 0x3e5c1396b62b0f84), + (0x3af43728856e7e95, 0x3e60d5c64a9c427f), + (0x3a8951d1fb56f9e5, 0xbdf43c4a5d5a74a1), + (0x3a9dff3a9a1305b7, 0xbdf038cb3f5e324b), + (0xba2227a6954a8107, 0x3d83b473da8d9c7c), + (0x3a00f6b33cdc63fd, 0x3d76a5d59f9a81dd), + (0xb988bc6d23c00f13, 0xbd0ba9a1977e4129), + (0x398765f6255cb3d1, 0xbcf7f3d211d80ca6), + (0x392695fb30ce2147, 0x3c8d5107593c868e), + (0xb917c43ab17af1b0, 0x3c73d94e8dd594b7), + (0x3898ca359e8db05d, 0xbc08484736827c1c), + (0xb8762b3eb4479bca, 0xbbea7775ae8da32a), + (0x37fbcf628aa86234, 0x3b80264bfaa20223), + (0x37e271fa49b2756e, 0x3b5d00eb74cea235), + (0x379f3f3a922be29c, 0xbaf1a063ed726ac9), + ], + [ + (0x35854b02b59f20a5, 0xb8e34bc17457894f), + (0x3c5f215e77086bf5, 0x3fbd09b210b30217), + (0x3bfc1f6fd559ad63, 0xbf52c74f6d120291), + (0x3c0587bb3b3049f5, 0xbf9357bfc2be5860), + (0xbbca26f6fb2c1060, 0x3f2901e4c495acea), + (0x3bdfa22468c2245a, 0x3f4ee2a36979f905), + (0xbb819f064e6a387e, 0xbee3f0cb93a497a4), + (0x3b845c631a25decc, 0xbef7748921871bcc), + (0x3af9ba7ee835a985, 0x3e8e39a085fc522a), + (0x3b168e73edf85eb9, 0x3e94c1b7a6b2509f), + (0xbacb21d04553bf28, 0xbe2aabe92ddd7d73), + (0x3ac83c7d3d064b50, 0xbe2804c5ad3234f3), + (0x3a2c4059ace3745e, 0x3dbec02b4af63bb7), + (0x3a5e5f6d54d90428, 0x3db3938387c8ea5e), + (0xb9a027aa900640db, 0xbd48f3df4c861285), + (0xb9a31a1b83cb9055, 0xbd37ae3cd67c3467), + (0x3962c6e3f82d4e4a, 0x3cce075e0968692d), + (0x395097056b18178c, 0x3cb61833a4f480be), + (0x38dbe00af812e106, 0xbc4bda71ed3079b1), + (0xb8dbcc3ff8d7603a, 0xbc30616db3cfc278), + (0x38543a30e58a4f05, 0x3bc483dc2d93ca5e), + (0x383474a59c970c7b, 0x3ba3c2fe3717b507), + (0xb7ce38a86dc4a340, 0xbb3892749970c097), + (0xb7b9f0d1aaa91069, 0xbb13c62adb209305), + ], + [ + (0xbc49df1f0f8d2108, 0x3fbc96700bf039e2), + (0xb59b9f4f3b516a10, 0xb900369fa71bf644), + (0x3c39df1f0f8d2108, 0xbfac96700bf039e2), + (0xbbb8cb9fe6e6c906, 0x3f37e5647d30fea8), + (0x3c06397704521ddc, 0x3f73095734a24496), + (0xbb56346f9ac2b6d1, 0xbf0312a4db537d5b), + (0x3bc2ab35cecaca9f, 0xbf24424a96e62373), + (0xbb5dc2fd60429a9d, 0x3eb5b4a6639fb7be), + (0xbb533d879080abe9, 0x3ec712e4d44c4a74), + (0xba8a3e2fc66990c5, 0xbe59917dedf003d7), + (0x3b0b520e9010331b, 0xbe6055757b098917), + (0x3a8b72c27ccfb937, 0x3df2728cdc02e18c), + (0x3a7adc897bdb4467, 0x3def80393fe2fc80), + (0xb9fad4f603343968, 0xbd81fcaa37a8b374), + (0x3a03afc083aed050, 0xbd760225681cd60a), + (0x39753518ad0e9b45, 0x3d0949ef9ee5d1b2), + (0xb979524731c89f4a, 0x3cf74c654a2656ac), + (0x391010895dc3b28c, 0xbc8ad88e518a28d9), + (0xb9155499f6d680c6, 0xbc7353b6d93fd106), + (0x38a0ae7b9e53be9c, 0x3c0646e795fc374a), + (0x3872458a3118ee05, 0x3be9cca80299b7b1), + (0xb81bebc11d5a928d, 0xbb7db0b7e5620486), + (0xb7fe8030136a44be, 0xbb5c4e2a3f8819a4), + (0x379be3a580646aab, 0x3af03c8d0fb251d3), + ], + [ + (0x359ca6ecae51f0ce, 0x38f785cd60d2c1ed), + (0xbc37a2663626dcab, 0xbfbc28612a3bc18b), + (0xbbf422f2d193784d, 0x3f511f52577ff6ba), + (0x3c3976e0041aa23b, 0x3f92c21da135f56c), + (0xbbc90eddb54be50c, 0xbf26ce18f8229e00), + (0xbbed07e9f503136f, 0xbf4df586d8b786e1), + (0xbb8f298c77e80033, 0x3ee230fede9c5ad4), + (0xbb94e2ce3149cc01, 0x3ef6c2a7558fc928), + (0xbb0453950e023ff5, 0xbe8b97329e667f58), + (0x3b301d8210db0b8e, 0xbe9426ecfd66cd08), + (0xbab764b9a347914a, 0x3e285e012a388a8c), + (0x3aca4092574b7b84, 0x3e27557143798fcd), + (0x3a3440e2c63fef00, 0xbdbc1f9f6fa068be), + (0xba5fe0095953ab69, 0xbdb30842b25be60a), + (0xb9d755f288da184b, 0x3d46d9757263a003), + (0xb9bbfc5a456628aa, 0x3d370aced616e601), + (0xb94bab13fb9e7f92, 0xbccb8986f8682a20), + (0x3943b3e29fa75536, 0xbcb584e49cbf1ef2), + (0x38ea081cc361bec5, 0x3c499540a7d48541), + (0xb8c430149fc9b075, 0x3c2ff0b7143f7ffe), + (0xb853ec9906091bb5, 0xbbc2e028bd3c8a70), + (0xb83e36c66c5cd25b, 0xbba34986a6eaad8f), + (0x37c533e5238e3cf1, 0x3b36a6785a72ecd5), + (0x37a56b5d17159660, 0x3b1352244bd5f525), + ], + [ + (0x3c58fff4515190b5, 0xbfbbbf246914235f), + (0xb538ee4bd006c414, 0xb8bef99392c87f53), + (0xbc48fff4515190b5, 0x3fabbf246914235f), + (0x3b9cd1da1498a8c8, 0xbf35d923e8470178), + (0xbbfbef9e896a9a49, 0xbf727a96f174b6d1), + (0xbb885ae82e4dfd87, 0x3f01715e4bbb00e7), + (0xbbcb52802ba3fd33, 0x3f23abacdb5106b5), + (0xbb5ee3261cd7bab4, 0xbeb3dc30d27849d7), + (0x3b6dfe5ed028776c, 0xbec6698d6ee99eb9), + (0x3aeb6c016c328002, 0x3e576911a4642dff), + (0xbaedb58a3fa04f2e, 0x3e5fbf415682210b), + (0x3a8ffce5bcffc5e8, 0xbdf0e7d3674631fb), + (0x3a850b7e524d421f, 0xbdeea1cbf2d9d28f), + (0x3a0972a562b54d3c, 0x3d80805ad6510626), + (0x3a139fee7249181d, 0x3d756aaba545a661), + (0xb994ba8b6414df04, 0xbd073ab529b32537), + (0x39993a6f276892ca, 0xbcf6b0b8fe737496), + (0x39299d1bde722fbd, 0x3c88b1cfe8649fd4), + (0x391ed1ce51d7dd6c, 0x3c72d6d686eeb22f), + (0xb8a7b2dc61e1a2b3, 0xbc0486115598b4ec), + (0x38788c9ff45e0eaa, 0xbbe92c11b4ee051b), + (0x380d5cd889980784, 0x3b7b6646fc1094e2), + (0xb7d3fbaf9d9205e6, 0x3b5ba50d4ef914aa), + (0x377a30dc81384d5d, 0xbaee055a0471899a), + ], + [ + (0xb51bc83c3a0e0aea, 0xb8afa7c9add8202e), + (0x3c5d0edcbac85112, 0x3fbb5a6219b35e14), + (0x3be54c0ba9407e4c, 0xbf4f645fdb1a8c89), + (0x3c37a2e3fd65164b, 0xbf923940d01de8e9), + (0x3bb0148b1871872e, 0x3f24e86a1e6384ff), + (0xbbe17bbc96485963, 0x3f4d1c6a18c7ed95), + (0xbb8c8ebe0fad0153, 0xbee0aeec61621923), + (0xbb99391cbe507ac5, 0xbef61f7d30244338), + (0xbaa992f34ae4f53d, 0x3e8950f781c1c41c), + (0x3b3c536bd805608d, 0x3e93989942e07175), + (0x3acb7edf5e20bddc, 0xbe265fd114ee2251), + (0xbab668c775bebb6a, 0xbe26b3bd4dfd4b81), + (0xba547f4392b0f26c, 0x3db9d8a1bbe00799), + (0xba342c15e8cbe561, 0x3db2875c16e44880), + (0xb9e8058b52e08699, 0xbd4505775bc7f118), + (0x399839569d133457, 0xbd3672e2d4f2963b), + (0x39448b9b5bdc1385, 0x3cc95d609dd374b0), + (0x3922fcd538cfb114, 0x3cb4fb4d36b42032), + (0xb8dba4f56475a1e4, 0xbc4798bab4a35bfe), + (0xb8cbc77ae9cc73f8, 0xbc2f2b65eca95481), + (0x38680bd8b9d2b683, 0x3bc16f8b2574d5ff), + (0xb81bbb799c6ddbe9, 0x3ba2d6d14c18aef1), + (0xb778386cee84a709, 0xbb34f49f286455da), + (0x37858cd2c19af21f, 0xbb12e3e607d95973), + ], + [ + (0xbc5024304247ada3, 0x3fbaf9cb49c4f935), + (0xb59f12f721a3d64f, 0x38fd67b1800cc2aa), + (0x3c4024304247ada3, 0xbfaaf9cb49c4f935), + (0xbbdc12274808bdaf, 0x3f3413b75ce0cc1b), + (0x3c06b1ae600584f2, 0x3f71f7a8fec6eba8), + (0xbbac4403ae7487a8, 0xbf0008442739ebfc), + (0xbbc9d63344ad0f44, 0xbf23215dab7537c6), + (0xbb3addfeaaf586b0, 0x3eb242e9e6bab199), + (0xbb4ca6d60de07627, 0x3ec5cdc48f5d75eb), + (0x3afbb75278987302, 0xbe5589cf32f43f3a), + (0xbafb7ec07d34bce4, 0xbe5ee5f0d63c1125), + (0x3a7c35d35717242c, 0x3def216eedb0f95e), + (0x3a8f8e312b763d9b, 0x3dedd414a7d8c97f), + (0x3a0cada00b33585e, 0xbd7e69fdff844763), + (0x3a13060575a01497, 0xbd74de15be6889e6), + (0x3953d8e70538cd11, 0x3d056e1418ad8cf1), + (0x399662b0ae22d5ef, 0x3cf61fa985a16926), + (0xb91ad31c7ecc6374, 0xbc86cf250611e72c), + (0xb90005c6530d9799, 0xbc7261f414b70fcc), + (0xb88ee36933bdb2e6, 0x3c02fb5ddae9e3c7), + (0xb876a7ccb4b4f8e6, 0x3be895055837a30a), + (0x37c443af13e1d435, 0xbb7960ab422d80c4), + (0xb7d0c27f905f8955, 0xbb5b052425ccb1af), + (0x37393e1ef7ae32d2, 0x3aebd91e8263d1bb), + ], + [ + (0xb5841211c9e4fbf8, 0x38e6aabd721697ea), + (0x3c508b7cc7933a75, 0xbfba9d1835947d70), + (0xbbcfb3814e43eef7, 0x3f4cea253049a85b), + (0x3c3e993cf753c741, 0x3f91bb71f665dcdf), + (0x3bc6de474edb7971, 0xbf23427f4797ae90), + (0x3bab43046c577e07, 0xbf4c54a7bd6f30c1), + (0xbb74fee4e6b715a1, 0x3edebe9e65809919), + (0xbb914661eec5967d, 0x3ef58924fa089950), + (0xbb1b1ce67962bafd, 0xbe87564501e7bcdc), + (0xbb32d2083a6e1367, 0xbe9315306e5bb42b), + (0x3abb19a5dd98b1c8, 0x3e24a32382dea2a5), + (0xbacf847c762942f2, 0x3e261e0ee5367a22), + (0xba5d25a1687ec831, 0xbdb7db8537582634), + (0x3a40dc676669750a, 0xbdb20facb4a9bb8b), + (0xb9e774de35526b14, 0x3d436bd6f0001ffb), + (0x39c4a236b9d81483, 0x3d35e552618cbf26), + (0x39679d0392cc254a, 0xbcc7754c8d46f92d), + (0x394ad96fb5f59779, 0xbcb47a92b94007d3), + (0xb8ef6b6af098cfd0, 0x3c45d920844ef181), + (0xb8c4d1cfab1f2a0c, 0x3c2e71f74fd91a7e), + (0xb86232b9682bb59c, 0xbbc02a09e0e77777), + (0xb83a4f51c8d25c89, 0xbba26a7e606b3d3b), + (0x37ac0d8d0af00df2, 0x3b33742f43880b52), + (0x37b2cfe1ad3e0ef1, 0x3b127b3f3a3c24de), + ], + [ + (0xbc55d35a88f1e0a3, 0xbfba4407e04298d1), + (0xb57a12f3e3faa5bd, 0xb8ebd844c546d1fe), + (0x3c45d35a88f1e0a3, 0x3faa4407e04298d1), + (0xbbdfcf49ead39f19, 0xbf3288694b34ab21), + (0x3c1c3cb8ccc39cf1, 0xbf717f0266db2149), + (0x3b7370deeb1fc99d, 0x3efd9a9a1d05433b), + (0xbbc76ae488c15a1a, 0x3f22a1c916a2d5a1), + (0xbb55855b88c468bb, 0xbeb0dd9e92661e07), + (0xbb0d6efd0446126a, 0xbec53dd972d8f232), + (0x3af0ee48a1c77965, 0x3e53e6e553aac740), + (0xbadd40df09e40809, 0x3e5e1cc65033998a), + (0xba32b59db0216721, 0xbdecc8a3f36b4e82), + (0xba8b62a99a7fbe14, 0xbded152ceac3373c), + (0x3a1c9ccca0c04104, 0x3d7c249e1f309fe3), + (0x3a0ef225196657ba, 0x3d745b3c1804be30), + (0xb9afb28e8d2ffa7d, 0xbd03d90bb0238840), + (0xb97d594b3ede144b, 0xbcf598302ab3ac8a), + (0xb92a26a4f451568c, 0x3c85259cd87cdd6c), + (0xb912f6ad38a9745a, 0x3c71f460abad18ae), + (0x388ed6abd853f84f, 0xbc019e5f6867ef21), + (0xb8739b58b6a444ab, 0xbbe806d32d68c464), + (0x380a7ea4b739cc38, 0x3b77958de1803c3e), + (0x37ef37708fa55952, 0x3b5a6deb944c06b2), + (0xb78f61f40b1c77dc, 0xbae9ea1590f503a9), + ], + [ + (0x357379a2bd7c52ce, 0xb8fbc8219db67734), + (0x3c2748c82bad8c51, 0x3fb9ee5ee937fc89), + (0x3bebaa9c093c19b6, 0xbf4abf28ad5bf6da), + (0x3bf098a110e151ad, 0xbf9147481084ae0f), + (0xbbcb58642b32be0e, 0x3f21d137345cfee5), + (0x3bdbab7a25ecf8c2, 0x3f4b9c10ddf62464), + (0x3b707cd222ddff83, 0xbedc72c9d49c6d7a), + (0x3b9799bc03c5acb7, 0xbef4fe0b363ccc66), + (0x3b2f6ffbbd8a09bd, 0x3e859a1c336b7506), + (0xbb3843707d4c5068, 0x3e929b6632cc324d), + (0xbaa20857a0292715, 0xbe231cd6e7991df9), + (0xbab28b65ed5397d3, 0xbe25930872001f69), + (0xba5cf09bb859c9ae, 0x3db61befbaafa006), + (0xba2fa8cd2c2d9dc1, 0x3db1a038446ec46c), + (0x39d429e8620217b4, 0xbd42030319ffc086), + (0x39d5f3fcc28971f9, 0xbd35611796700e22), + (0xb921b9f1f88c6b8d, 0x3cc5c664f879c556), + (0x395775c1e2792ff0, 0x3cb401eb6a61fbc2), + (0x38ead4ec597eb512, 0xbc444cf4a7922ede), + (0x389608d2d57a3ecf, 0xbc2dc380c95ab35d), + (0xb85138d52c6d34af, 0x3bbe1244da523859), + (0x3811c5c33ebcb580, 0x3ba2042743d87f84), + (0x37c0000bf1ca678b, 0xbb321df42759daa3), + (0xb7b3e51de8fa1afc, 0xbb1217eed90481cc), + ], + [ + (0x3c5728ab934a26a0, 0x3fb99be744018c90), + (0x359a217cfc0fd73f, 0x38f8cb0a4bb92b1c), + (0xbc4728ab934a26a0, 0xbfa99be744018c90), + (0xbbc84fc91475651a, 0x3f312d4e1c1ca4c3), + (0x3c0f281d89ca12e4, 0x3f710f5ca51f98b0), + (0x3b9fa3d9c46c2f87, 0xbefb71417476a570), + (0xbb82784bcc79df7f, 0xbf222b9fa8dfd762), + (0xbb2378ade6a74c3f, 0x3eaf471061b7dd7e), + (0x3b688d4663776f74, 0x3ec4b862279de756), + (0x3ae406b21b8c7a34, 0xbe52763f34a53566), + (0xbafcf6291cf32841, 0xbe5d61e605e8e69a), + (0x3a86957e31ae2fc6, 0x3deab7331a682502), + (0x3a8a902f91e8c962, 0x3dec637428f3fda4), + (0x39f24e732a100c1c, 0xbd7a236ad0b3eb49), + (0xba105ad2fccf3d78, 0xbd73e11cef6eae93), + (0xb995c95ce2902dca, 0x3d0272cbaef43092), + (0xb995e32a69772db7, 0x3cf519623b4e50ac), + (0xb9292fc5f6cbd421, 0xbc83ac6109d4a7c0), + (0xb916701f83b25b26, 0xbc718d7ac32164f8), + (0xb8a62d82d427d871, 0x3c0068369bb2c654), + (0x388344bf0ff0ace9, 0x3be780d0943d0646), + (0xb7f8d6f94baf1bf3, 0xbb75fc6a10345edb), + (0xb7d82ddcd0a763ae, 0xbb59ded950660f9a), + (0x378e6b4fc0afac52, 0x3ae82fa57e04df35), + ], + [ + (0xb59824ff875a6f4d, 0xb8fef5ad62580f34), + (0xbc4e31356cad466d, 0xbfb94c6f54aef04b), + (0xbbe68528f64c6571, 0x3f48d6371f018ef0), + (0xbbf705a06948ad50, 0x3f90db975fd7dc47), + (0x3bc06e812fbec708, 0xbf208bd1634353c9), + (0x3beeb410edf15681, 0xbf4af0d3d4cd140d), + (0x3b6d81ec6351ba6b, 0x3eda6c8e7c9d023e), + (0xbb94f5f0c3884299, 0x3ef47cddcdac15d7), + (0xbaee0980702c7029, 0xbe8412394fc50e0a), + (0xbb3fb63544124d21, 0xbe922a21cb1edfe9), + (0xbac10c16da7fd9d1, 0x3e21c417dedcf50f), + (0xbaadc343b535f5ab, 0x3e25117f3061daaa), + (0xba52f41f6480b3af, 0xbdb49009a6c8ef27), + (0xba1394b790b42720, 0xbdb13823dda87c57), + (0x39ecf2b99857d12c, 0x3d40c350b60502a2), + (0x39d16c5f3587dedc, 0x3d34e54a89ae3a78), + (0xb96e84c18fd85bb6, 0xbcc447dde87e69d6), + (0xb92fa9fc1fe799a6, 0xbcb3909fa7a78345), + (0x38e1d450f52eeca1, 0x3c42ec7e57d796d5), + (0x38bc5414c0376e8d, 0x3c2d1f245967f392), + (0x384f6a4fc5c93b04, 0xbbbc0ef954471f60), + (0xb8436aa08a547d96, 0xbba1a364a86e2ed4), + (0xb7c059ecba8db4c0, 0x3b30ebf4b4f1127f), + (0xb792d76142a8ff7b, 0x3b11b9abb3510b7f), + ], + [ + (0x3c5e213a1a4b3671, 0xbfb8ffc9bd24fe08), + (0x3568e6cd71e05784, 0xb8c846638d0f2565), + (0xbc4e213a1a4b3671, 0x3fa8ffc9bd24fe08), + (0xbbcd36327411471d, 0xbf2ff51b38eef42c), + (0xbc0f532ddb23dab4, 0xbf70a7a725d3fbc4), + (0xbb834bf088b48836, 0x3ef988128728122a), + (0xbbb5bd608899de58, 0x3f21bdc846a09e43), + (0x3b3013850114c517, 0xbead1b60a4812ac4), + (0xbb5a77447ea6fe43, 0xbec43c2d8e698c10), + (0x3ad8023dfb41774f, 0x3e512fd6ccdafecc), + (0xbaf62e671fb10d65, 0x3e5cb3bb8802e835), + (0xba859d9d3a171da7, 0xbde8e1dd09a92324), + (0x3a8ce00fffe0e74e, 0xbdebbd84404b6237), + (0x3a0700486612292d, 0x3d785bcfd7db3db0), + (0x3a131220e196908b, 0x3d736ed760739d88), + (0x399d6eab7135136a, 0xbd01343464751bc4), + (0x399a9e6748bc0bea, 0xbcf4a26ef2219c2c), + (0x3916fec76005e868, 0x3c825c3fff5cf7ca), + (0xb8f4e1647a2b0045, 0x3c712caee4bc257a), + (0xb895bdf1f04f1575, 0xbbfea67f8d5490ce), + (0x388017eb7fef7e93, 0xbbe7025c0acb6ed2), + (0xb80d402134b327c6, 0x3b748e326c33fa45), + (0xb7f36f706b3d34ec, 0x3b595763182ec3fa), + (0xb77ee821070f844b, 0xbae6a29de364d58e), + ], + [ + (0xb52b322a93406970, 0xb8e11567e5257506), + (0x3c35e8738ef1b9ca, 0x3fb8b5ccad12d632), + (0xbbd18507f867922a, 0xbf4724d0185980d2), + (0x3c1f6ab95e49bd79, 0xbf907764ae2b1eeb), + (0x3bbea971bec7b60e, 0x3f1ed6acc18fdf29), + (0x3bca7600bd731e34, 0x3f4a51693df2efbb), + (0x3b5424c5adeb27a5, 0xbed8a0ec61e4df7b), + (0xbb2fcebf02eeb8d6, 0xbef4047f31fae045), + (0xbb244d41e0ecfe16, 0x3e82b668af276950), + (0x3b3cad4603e7028e, 0x3e91c07467ed6403), + (0xbac9f09027e17c0c, 0xbe2091d32eea7f0f), + (0xbacf61c0a2077065, 0xbe24987294de7d1e), + (0x3a4c64cfb1cdc317, 0x3db32fe6ab220655), + (0xba52d5ac79807dc5, 0x3db0d6b127f8ac22), + (0x39d08853ae95a955, 0xbd3f4d16b8cb00ea), + (0x39c9258c596bcdf2, 0xbd34711e3d50f99d), + (0xb9607956efca23e8, 0x3cc2f28e5de9b115), + (0x394e73cc5f03a293, 0x3cb326098eabb602), + (0x38c9a844bf92f26d, 0xbc41b1699659661e), + (0x38c79ee3937d0522, 0xbc2c84136a790cfd), + (0xb84d287adf77e7fa, 0x3bba415dab11fbcc), + (0x3843b689e4f1e579, 0x3ba147d23398faea), + (0x37b913ca23ec4cc0, 0xbb2fb26f3c616548), + (0x37a819aab969975c, 0xbb1160299cd9ebeb), + ], + [ + (0x3c5b1c9821974148, 0x3fb86e51be0a9153), + (0xb5720ba7256e1fdc, 0x38ee1da34bfeb8e0), + (0xbc4b1c9821974148, 0xbfa86e51be0a9153), + (0xbbcc79e50a2dc677, 0x3f2dd3c244b53279), + (0xbbe9cfc1363faa0e, 0x3f7046fc5a218a86), + (0x3b47339108bed763, 0xbef7d51accbfba76), + (0x3bbac27d1a98311f, 0xbf2157556c0e1b1a), + (0xbb2e6885549f0df6, 0x3eab2d01c12c8227), + (0xbb685c37a3fcd2ca, 0x3ec3c838897d0a1e), + (0xbaf6ac2b47952135, 0xbe500d37aa536a8b), + (0x3afe13ef178fd248, 0xbe5c10ecf088eac6), + (0x3a640bc972bc618d, 0x3de73f8d1af57f4c), + (0xba7d1502b5443bc9, 0x3deb2227fe94022c), + (0xba0e6bfbee228ee6, 0xbd76c5390bcf017b), + (0xba1975f49279a432, 0xbd7303a6ded9ee03), + (0x399abf56810fc89c, 0x3d0017772c8c0084), + (0x399af156baca0aee, 0x3cf4329cf32bcb6e), + (0xb9219214145d8323, 0xbc812f535b46fd28), + (0x3904bff1857123e5, 0xbc70d1776a208c18), + (0x3888ba3ef05e5fd1, 0x3bfcb5a589ad0a5c), + (0x3871815404beb4a9, 0x3be68adf143f5d78), + (0xb8166a2869445d1c, 0xbb734508c6e2f203), + (0x37edd1f20932a7cc, 0xbb58d702f0f1cb76), + (0xb774cc6cd565f7bf, 0x3ae53cf6ad4248fb), + ], + [ + (0x3586adcfc24a15bd, 0x38fb4b40fa7659d2), + (0x3c40ee4d5b1b8050, 0xbfb829356999a097), + (0x3be3831592c6b168, 0x3f45a280e033eb59), + (0x3c215c764657672c, 0x3f9019dba8336e48), + (0x3b986e85a6375663, 0xbf1cd4559d95e619), + (0xbbc0173a9412da83, 0xbf49bc857750335e), + (0xbb63dae6774006f7, 0x3ed70706580693f9), + (0x3b838496a72af1a4, 0x3ef393fc6cf8481f), + (0xbaf56d91a42ef902, 0xbe81800af4665cb3), + (0xbb2c21f37756b0a2, 0xbe915d91a2289a30), + (0x3aa04b0681616769, 0x3e1f009c83572407), + (0x3ab8eb4169a44614, 0x3e2427054565b344), + (0xba4aede413980977, 0xbdb1f5167f464cc6), + (0xba42c3010298ffea, 0xbdb07b3a2cb21729), + (0xb9d5250b5c48f994, 0x3d3d4f453474d39c), + (0x39d7de25bab32cb7, 0x3d3403dd864ce1b5), + (0xb959c7b70a761729, 0xbcc1c096935c0515), + (0x3949cfca62e35a95, 0xbcb2c193ec80c816), + (0x38d72ce5fb9c0118, 0x3c40967d8ee82f54), + (0x38b2d922c1971637, 0x3c2bf18fd1afe1de), + (0x385409db53827004, 0xbbb8a21d0c689575), + (0x384dc5f7e6e04311, 0xbba0f11083b9c847), + (0x37ce8f2e696187cf, 0x3b2dc3272d23ffd6), + (0xb7b0e86cfd0bfa4f, 0x3b110b1caef3d73d), + ], + [ + (0x3c21907f595a082a, 0xbfb7e656efb009ae), + (0xb590e3abdd6e7404, 0x38f3c9c05fc68dd7), + (0xbc11907f595a082a, 0x3fa7e656efb009ae), + (0x3bcce5fd1ce6de53, 0xbf2bec6b33efcb49), + (0x3bcf8f1c9736150f, 0xbf6fd932c26aad94), + (0x3b80b8964c190cdc, 0x3ef6504d7e054d50), + (0xbbb3c0e77f493518, 0x3f20f77ce6105150), + (0x3b3d95fb56d1d86f, 0xbea972e573db9593), + (0x3b44588b63a38eb3, 0xbec35ba58bf2f993), + (0x3ad1cbaf2f9e7b25, 0x3e4e1246a53112c6), + (0xbac8e1b1b14782dd, 0x3e5b7850b3bc8175), + (0xba87c131e73bb3fd, 0xbde5c8dcec477a4e), + (0xba84c1608c9f12fa, 0xbdea905348b4924d), + (0x39e529efb683a910, 0x3d7558a1f12cdd3f), + (0x3a18c3b5cbcd2fee, 0x3d729edf3b2865f3), + (0x399e9dec38211b14, 0xbcfe2f9cdddbe89c), + (0x3991f206b8c5d3a1, 0xbcf3c947b936c2fd), + (0xb926d15a781493eb, 0x3c8020bb8706a05b), + (0x391b89b4941b2fbc, 0x3c707b5bb2f1e971), + (0x3875331d8b43e31b, 0xbbfaf6220e4137a4), + (0x388fbf932efdfa5c, 0xbbe619cedd775137), + (0xb7f15f7042e6e287, 0x3b721c04bebc0bb5), + (0x37f3601b48c231f4, 0x3b585d398a9b6f0b), + (0x378dd18a95cb152b, 0xbae3f99b23077622), + ], + [ + (0x352bf89ec4e05302, 0x38c2beead70ae7d0), + (0xbc529270d2a71e91, 0x3fb7a597e9550934), + (0xbbd42472048d4fe5, 0xbf44486c0b012534), + (0xbc2ac52ac4327de6, 0xbf8f848eec0e0e6b), + (0x3b684f34372ed852, 0x3f1b077fae06adc6), + (0xbbce518d0a756962, 0x3f49310d6e6842c6), + (0x3b230b8888fa2afa, 0xbed597a5befbd70e), + (0x3b9e1e12047ef68f, 0xbef32a855e4e113b), + (0xbb1d73ebaa41845b, 0x3e8069ba0b1a612d), + (0xbb3a5058b2aec6be, 0x3e9100c97ba8e22d), + (0xbab085381e3747da, 0xbe1d15b5350404fa), + (0x3ac28b1288705592, 0xbe23bc775cca4413), + (0x3a5ffd971088266f, 0x3db0da51f94c98f0), + (0x3a5dfce6ace7ab08, 0x3db0252dc33a4d7a), + (0xb9dc3fdc25aa9e9a, 0xbd3b84d751a36bd2), + (0x39b47e26246286bb, 0xbd339ce8224cc6de), + (0x395a80d541531404, 0x3cc0ad1ba9d01451), + (0xb95b7f3b36aa04cc, 0x3cb262b8db934833), + (0x38dc5e49fddd8fdf, 0xbc3f2ec77da02f0e), + (0x38a348be97d223b5, 0xbc2b66ebaf597acc), + (0x385369dda16c7b7d, 0x3bb72b1780503c41), + (0x3840d18df6c3b214, 0x3ba09ec633447fba), + (0xb7afbf9889f21003, 0xbb2c0312119c246e), + (0xb7bc1892f4c2e089, 0xbb10ba3b452a59bb), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,425 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f_coeffs::{J0_ZEROS, J0_ZEROS_VALUE, J0F_COEFFS}; +use crate::bessel::trigo_bessel::cos_small; +use crate::double_double::DoubleDouble; +use crate::polyeval::{f_polyeval9, f_polyeval10, f_polyeval12, f_polyeval14}; +use crate::rounding::CpuCeil; +use crate::sincos_reduce::rem2pif_any; + +/// Bessel of the first kind of order 0 +/// +/// Max ulp 0.5 +pub fn f_j0f(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux <= 0x6800_0000u32 { + // |x| == 0, |x| == inf, |x| == NaN, |x| <= f32::EPSILON + if ux == 0 { + // |x| == 0 + return f64::from_bits(0x3ff0000000000000) as f32; + } + if x.is_infinite() { + return 0.; + } + + if ux <= 0x6800_0000u32 { + // |x| < f32::EPSILON + // taylor series for J0(x) ~ 1 - x^2/4 + O(x^4) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, -x * 0.25, 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::f_fmla; + let dx = x as f64; + return f_fmla(dx, -dx * 0.25, 1.) as f32; + } + } + + return x + f32::NAN; // x == NaN + } + + let x_abs = x.to_bits() & 0x7fff_ffff; + + if x_abs <= 0x4295999au32 { + // |x| <= 74.8 + if x_abs <= 0x3e800000u32 { + // |x| <= 0.25 + return j0f_maclaurin_series(x); + } + + if x_abs == 0x401a42e8u32 { + return f32::from_bits(0xbb3b2f69u32); + } + + return small_argument_path(x); + } + + // Exceptions + if x_abs == 0x65ce46e4 { + return f32::from_bits(0x1eed85c4); + } else if x_abs == 0x7e3dcda0 { + return f32::from_bits(0x92b81111); + } else if x_abs == 0x76d84625 { + return f32::from_bits(0x95d7a68b); + } else if x_abs == 0x6bf68a7b { + return f32::from_bits(0x1dc70a09); + } else if x_abs == 0x7842c820 { + return f32::from_bits(0x17ebf13e); + } else if x_abs == 0x4ba332e9 { + return f32::from_bits(0x27250206); + } + + j0f_asympt(f32::from_bits(x_abs)) +} + +/** +Generated by SageMath: +```python +# Maclaurin series for j0 +def print_expansion_at_0_f(): + print(f"pub(crate) const J0_MACLAURIN_SERIES: [u64; 9] = [") + from mpmath import mp, j0, taylor + mp.prec = 60 + poly = taylor(lambda val: j0(val), 0, 18) + z = 0 + for i in range(0, 18, 2): + print(f"{double_to_hex(poly[i])},") + print("];") + + print(f"poly {poly}") + +print_expansion_at_0_f() +``` +**/ +#[inline] +fn j0f_maclaurin_series(x: f32) -> f32 { + pub(crate) const C: [u64; 9] = [ + 0x3ff0000000000000, + 0xbfd0000000000000, + 0x3f90000000000000, + 0xbf3c71c71c71c71c, + 0x3edc71c71c71c71c, + 0xbe723456789abcdf, + 0x3e002e85c0898b71, + 0xbd8522a43f65486a, + 0x3d0522a43f65486a, + ]; + let dx = x as f64; + f_polyeval9( + dx * dx, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + ) as f32 +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +fn small_argument_path(x: f32) -> f32 { + let x_abs = f32::from_bits(x.to_bits() & 0x7fff_ffff) as f64; + + // let avg_step = 74.6145 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6299043751549631; + + let fx = x_abs * INV_STEP; + const J0_ZEROS_COUNT: f64 = (J0_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J0_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(J0_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J0_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J0_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return j0f_maclaurin_series(x); + } + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(J0_ZEROS_VALUE[idx]) as f32; + } + + let c = &J0F_COEFFS[idx - 1]; + + let r = (x_abs - found_zero.hi) - found_zero.lo; + + let p = f_polyeval14( + r, + f64::from_bits(c[0]), + f64::from_bits(c[1]), + f64::from_bits(c[2]), + f64::from_bits(c[3]), + f64::from_bits(c[4]), + f64::from_bits(c[5]), + f64::from_bits(c[6]), + f64::from_bits(c[7]), + f64::from_bits(c[8]), + f64::from_bits(c[9]), + f64::from_bits(c[10]), + f64::from_bits(c[11]), + f64::from_bits(c[12]), + f64::from_bits(c[13]), + ); + + p as f32 +} + +#[inline] +pub(crate) fn j1f_rsqrt(x: f64) -> f64 { + (1. / x) * x.sqrt() +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - PI/4 - alpha(x)) +*/ +#[inline] +fn j0f_asympt(x: f32) -> f32 { + let dx = x as f64; + + let alpha = j0f_asympt_alpha(dx); + let beta = j0f_asympt_beta(dx); + + let angle = rem2pif_any(x); + + const SQRT_2_OVER_PI: f64 = f64::from_bits(0x3fe9884533d43651); + const MPI_OVER_4: f64 = f64::from_bits(0xbfe921fb54442d18); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_cos = cos_small(r0); + + let z0 = beta * m_cos; + let scale = SQRT_2_OVER_PI * j1f_rsqrt(dx); + + (scale * z0) as f32 +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` +**/ +#[inline] +pub(crate) fn j0f_asympt_alpha(x: f64) -> f64 { + const C: [u64; 12] = [ + 0x3fc0000000000000, + 0xbfb0aaaaaaaaaaab, + 0x3fcad33333333333, + 0xbffa358492492492, + 0x403779a1f8e38e39, + 0xc080bd1fc8b1745d, + 0x40d16b51e66c789e, + 0xc128ecc3af33ab37, + 0x418779dae2b8512f, + 0xc1ec296336955c7f, + 0x4254f5ee683b6432, + 0xc2c2f51eced6693f, + ]; + let recip = 1. / x; + let x2 = recip * recip; + let p = f_polyeval12( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + f64::from_bits(C[10]), + f64::from_bits(C[11]), + ); + p * recip +} + +/** +Beta series + +Generated by SageMath: +```python +#generate b series +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x', default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(0, x, 50) +Q = Qn_asymptotic(0, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +#see the series +print(b_series) +``` +**/ +#[inline] +pub(crate) fn j0f_asympt_beta(x: f64) -> f64 { + const C: [u64; 10] = [ + 0x3ff0000000000000, + 0xbfb0000000000000, + 0x3fba800000000000, + 0xbfe15f0000000000, + 0x4017651180000000, + 0xc05ab8c13b800000, + 0x40a730492f262000, + 0xc0fc73a7acd696f0, + 0x41577458dd9fce68, + 0xc1b903ab9b27e18f, + ]; + let recip = 1. / x; + let x2 = recip * recip; + f_polyeval10( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + ) +} + +#[cfg(test)] +mod tests { + use crate::f_j0f; + + #[test] + fn test_j0f() { + println!("0x{:8x}", f32::EPSILON.to_bits().wrapping_shl(1)); + assert_eq!(f_j0f(-3123.), 0.012329336); + assert_eq!(f_j0f(-0.1), 0.99750155); + assert_eq!(f_j0f(-15.1), -0.03456193); + assert_eq!(f_j0f(3123.), 0.012329336); + assert_eq!(f_j0f(0.1), 0.99750155); + assert_eq!(f_j0f(15.1), -0.03456193); + assert_eq!(f_j0f(f32::INFINITY), 0.); + assert_eq!(f_j0f(f32::NEG_INFINITY), 0.); + assert!(f_j0f(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0f_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j0f_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j0f_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1050 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +J0 zeros and extremums. + +Generated by SageMath: +```python +# searching for zeros and extremums +R120 = RealField(120) + +zeros = [] + +mp.prec = 150 + +step = mpf("0.001") +epsilon = mpf("1e-35") +x = mpf("0.0") + +def j0_prime(x): + return diff(lambda t: besselj(0, t), x) + +previous_zero = R120(0) +j0_zeros = [] + +while x < mpf("76.0"): + f1 = besselj(0, x) + f2 = besselj(0, x + step) + if f1 * f2 < 0: + zero = findroot(lambda t: j0(t), (x, x + step), solver='bisect', tol=mp.mpf("1e-41")) + previous_zero = zero + j0_zeros.append(zero) + if previous_zero is not None and abs(x - mpf(f'{round(x)}')) < epsilon: + zeros.append(previous_zero) + x += step + +j0_extrema = [] + +x = mpf("0.0") +while x < mpf("76.0"): + d1 = mp.diff(lambda t: j0(t), x) + d2 = mp.diff(lambda t: j0(t), x + step) + if d1 * d2 < 0: + extremum = findroot(lambda t: mp.diff(lambda u: j0(u), t), (x, x + step), solver='bisect', tol=mp.mpf("1e-41")) + j0_extrema.append(extremum) + x += step + +# Print results +for i, z in enumerate(j0_zeros): + print(f"Zero {i+1}: x ≈ {z}") + +print("Extrema (peaks/valleys) of J0(x):") +for e in j0_extrema: + print(f"nExtrema: {e}") + +j0_zeros.extend(j0_extrema) + +j0_zeros = sorted(j0_zeros) + +# Print results +for i, z in enumerate(j0_zeros): + print(f"Peak or zero {i+1}: x ≈ {z}") + +print("") + +print("pub(crate) static J0_ZEROS: [(u64, u64); 48] = [") +print(f"(0x0, 0x0),") +for z in j0_zeros: + k = split_double_double(z) + hi = double_to_hex(k[1]) + lo = double_to_hex(k[0]) + print(f"({lo}, {hi}),") + +print("];") +``` +**/ +pub(crate) static J0_ZEROS: [(u64, u64); 48] = [ + (0x0, 0x0), + (0xbca0f539d7da258e, 0x40033d152e971b40), + (0xbca60155a9d1b256, 0x400ea75575af6f09), + (0x3c975054cd60a517, 0x4016148f5b2c2e45), + (0xbc9b226d9d243827, 0x401c0ff5f3b47250), + (0xbcb51970714c7c25, 0x40214eb56cccdeca), + (0x3cc02610a51562b6, 0x402458d0d0bdfc29), + (0x3cb444fd5821d5b1, 0x40279544008272b6), + (0x3cb2bce7fd18e693, 0x402aa5baf310e5a2), + (0xbcc9796609364e85, 0x402ddca13ef271d2), + (0xbcdd2a68e88ab317, 0x4030787b360508c5), + (0xbcd165fd108f46ff, 0x403212313f8a19f6), + (0xbcd21830197e9e86, 0x40339da8e7416ca4), + (0x3cc1d2dfa1c3b5a8, 0x4035362dd173f792), + (0xbcc1bf33afef88f1, 0x4036c294e3d4d8ac), + (0x3cd0847c620015e0, 0x40385a3b930156dd), + (0x3cc1a2686480d882, 0x4039e7570dcea106), + (0x3cdd2b3714972b28, 0x403b7e54a5fd5f11), + (0xbcb42ce39ec976fb, 0x403d0bfcf471fccc), + (0xbcc36bbabc1c9f31, 0x403ea27591cbbed2), + (0xbcdbe3a1cd066b66, 0x404018476e6b2bf0), + (0x3cda326cf4307839, 0x4040e34e13a66fe6), + (0xbced5fbbff045068, 0x4041aa890dc5e97c), + (0xbcd0b6068f861c6f, 0x404275637a9619ec), + (0x3cc9eafeca0ca4fd, 0x40433cc523d5cb69), + (0xbcb34c86f4e27936, 0x4044077a7ed6293a), + (0x3cc489bd556e510a, 0x4044cefcf1734b62), + (0x3cced48fe99f45ef, 0x40459992c65d0d8d), + (0x3ce4f716f3179d90, 0x404661315d6b133f), + (0xbcd05a7a0525058f, 0x40472bac0f810810), + (0xbcef3950a842db79, 0x4047f36312028ad6), + (0x3ce575dc7f8a031a, 0x4048bdc6293f0657), + (0x3ce85d7bdb30baf1, 0x404985928f96d51e), + (0xbcdfa16a338bbaee, 0x404a4fe0ee444c7b), + (0x3ce3d41e041caa68, 0x404b17c038c2018c), + (0xbce43e4a90356acf, 0x404be1fc41a4c607), + (0x3cda139ce2cd08ac, 0x404ca9ec5a82324b), + (0x3ce0f4b1c9544480, 0x404d74180c9e41f6), + (0xbcb12e6ef2e594e1, 0x404e3c1731d64f1e), + (0x3ceff10a69607aab, 0x404f06343d0971d4), + (0x3cdfd1ee8286358a, 0x404fce40efb1156e), + (0xbcf8991ca07c84c0, 0x40504c28621f11e6), + (0x3ced3cacfc720419, 0x4050b034dde75b42), + (0xbcee90a52cffc26f, 0x40511536cb22d72b), + (0xbcee669304bfe748, 0x40517948db63675c), + (0xbcf5328276c045f2, 0x4051de4554a1c2dd), + (0x3cf8eb4a94b63936, 0x4052425c7dcacdf6), + (0x3cff05f585843675, 0x4052a753fa820480), +]; + +/** +Roots and values for extremums and J0 zeros. + +Generated by MPFR: +```text +let mut arr = vec![]; +for zeros in J0_ZEROS.iter() { + let mpfr = Float::with_val(107, f64::from_bits(zeros.1)).j0(); + arr.push(mpfr.to_f64().to_bits()); +} +println!( + "arr: [{}]", + arr.iter() + .map(|x| format!("0x{:016x}", x)) + .collect::>() + .join(", ") +); +``` +**/ +pub(crate) static J0_ZEROS_VALUE: [u64; 48] = [ + 0x3ff0000000000000, + 0xbc919b7921f03c8e, + 0xbfd9c6cf582cbf7f, + 0xbc7fbb40985f6e34, + 0x3fd33518b3874e8a, + 0xbc96e8eeb22e5818, + 0xbfcff654544ebcd1, + 0xbc92d8ed368e0843, + 0x3fcbf3337873a7d8, + 0xbca50be2ef09843e, + 0xbfc925c6fca08f55, + 0x3caa2122af76659e, + 0x3fc70c511227d5aa, + 0x3c98b4b912da2218, + 0xbfc5664e13b70622, + 0xbca55e059345b430, + 0x3fc40f90793605bb, + 0x3cb1c17abe35eaae, + 0xbfc2f2072e638cf4, + 0x3c966608ac164dbd, + 0x3fc1ff5eec6a01cd, + 0x3cacc62c8409daa7, + 0xbfc12dd57bf18ada, + 0x3ca18e7b1f5c77ae, + 0x3fc076826cc2c191, + 0xbc8376cc57901722, + 0xbfbfa8b41711c83a, + 0xbc9df12b66b26573, + 0x3fbe8727daa3daed, + 0xbc9eab3b2bf5813d, + 0xbfbd8293aa55d18f, + 0xbcb3795064667200, + 0x3fbc96700bf039e2, + 0xbcabd526bce38ac7, + 0xbfbbbf246914235f, + 0x3cb14dbc2a692434, + 0x3fbaf9cb49c4f935, + 0x3cac341b9f831174, + 0xbfba4407e04298d1, + 0xbcb9e23f9c9ca91e, + 0x3fb99be744018c90, + 0xbcc3725f95922088, + 0xbfb8ffc9bd24fe08, + 0x3cb79a2187735244, + 0x3fb86e51be0a9153, + 0xbcc0012df1d3ef73, + 0xbfb7e656efb009ae, + 0xbcc6ecd27843db59, +]; + +/** +Taylor coefficients for J0 [0; 74.62] + +Generated by SageMath with Sollya: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = (zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(j0_zeros) +# print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 500; +bessel_j0 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_j0(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RR(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +degree = 13 + +print(f"pub(crate) static J0F_COEFFS: [[u64;{degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print("[") + for c in coeffs: + print(double_to_hex(c) + ",") + print("],") +print("];") +``` +**/ +pub(crate) static J0F_COEFFS: [[u64; 14]; 47] = [ + [ + 0xbca69de51bcc0120, + 0xbfe09cdb3655127d, + 0x3fbba1deea029925, + 0x3facfae8643687e7, + 0xbf81bb1cbe1caeb6, + 0xbf61f992590d3f89, + 0x3f315382bbf1a06b, + 0x3f06ed3ba591e6da, + 0xbed232c8d8aba5cc, + 0xbea1cceb52db45ee, + 0x3e68006b6b5682ca, + 0x3e329cc1da0793f0, + 0xbdf5dbb0053da32b, + 0xbdc04e14e5d96539, + ], + [ + 0xbfd9c6cf582cbf7f, + 0x3cb1d608597b5d8f, + 0x3fc9c6cf582cbf55, + 0xbf91f06d14e12b29, + 0xbf8b589d1da0f7e4, + 0x3f50f9103d00ae93, + 0x3f38644561ce9290, + 0xbefa2a034c749192, + 0xbed83a0686fd1dd2, + 0x3e96a5085d7844b5, + 0x3e6ebfcaacd49b87, + 0xbe2964b9932b57f3, + 0xbdfad73cf4701511, + 0x3db5acbea609d3e5, + ], + [ + 0xbc6a1105f9dbcdd5, + 0x3fd5c6e60a097826, + 0xbf9f8f72e7a8471e, + 0xbfab2150cb41ece4, + 0x3f72f7ffe901b59c, + 0x3f627e31fe9ddafb, + 0xbf26f641f369bbbd, + 0xbf0863f485fc7e89, + 0x3ecad77cbbb32bcd, + 0x3ea32e705af41964, + 0xbe62d9d2bb447e35, + 0xbe341f0e4f4dc44a, + 0x3df198b51eee9749, + 0x3dbec8f104a030ca, + ], + [ + 0x3fd33518b3874e8a, + 0xbca7f56ee546a569, + 0xbfc33518b3874e3b, + 0x3f7d34125d59fb96, + 0x3f880c83bdee71b4, + 0xbf4483c20f2abbd1, + 0xbf36ffa5fc0ccc0f, + 0x3ef2ccf7bbc1d620, + 0x3ed796a6caa245fc, + 0xbe91e85738cfdd42, + 0xbe6e69b581df4be3, + 0x3e2550287122730e, + 0x3dfab73cc2e87ac7, + 0xbdb250809ed630ba, + ], + [ + 0x3c684670459725e1, + 0xbfd15f7977a772d5, + 0x3f900f7fcf183c65, + 0x3fa68b984ec64b1d, + 0xbf648e63600c54a1, + 0xbf60e0d6038721a4, + 0x3f1d7960512fb682, + 0x3f07800bc7410c66, + 0xbec3324799a7e0fb, + 0xbea30e8df2325ca1, + 0x3e5cecefe3d75abb, + 0x3e3458cbaa06ef8d, + 0xbdec4dd6cf551d07, + 0xbdbefa0975b65713, + ], + [ + 0xbfcff654544ebcd1, + 0x3ca0ffc636e7373a, + 0x3fbff654544ebc20, + 0xbf70c17ff72b1352, + 0xbf84b0c5d5d9e7c9, + 0x3f394154be849b76, + 0x3f34e12c2fdccc3a, + 0xbee9f32fcfbab067, + 0xbed63c53e4cc158b, + 0x3e8adbb88b7826d7, + 0x3e6d5f825ac22ee0, + 0xbe20f17a50351084, + 0xbdfa326458f60fce, + 0x3dae0e0c6fa040ee, + ], + [ + 0xbc648b5c145d146f, + 0x3fcdc13e66ac2e78, + 0xbf842ff0cdc58194, + 0xbfa38d1dd8992ef5, + 0x3f5a55e9b344ea02, + 0x3f5e2e16f97e7f5f, + 0xbf13dfc37714f92e, + 0xbf05ce7f4a51d917, + 0x3ebbb177bc7895b4, + 0x3ea2346df84ab988, + 0xbe56125b44798bd5, + 0xbe33d7cc75fbdd4e, + 0x3de68bc84d67bb0a, + 0x3dbe749161c75b7f, + ], + [ + 0x3fcbf3337873a7d8, + 0xbc999eb31028b75f, + 0xbfbbf3337873a725, + 0x3f66604d91f94ba7, + 0x3f8251858010ffd8, + 0xbf314bc11a41832e, + 0xbf32e7decc933381, + 0x3ee293b4d39e1d9e, + 0x3ed4a66fbc1f8e7c, + 0xbe843cb02661be36, + 0xbe6bdd61e41af9d3, + 0x3e1ab24db7abbdd7, + 0x3df940cc3ecafe33, + 0xbda870435d8d1863, + ], + [ + 0x3c6110461d393f0c, + 0xbfca701d0f967501, + 0x3f7c54b930fef3e4, + 0x3fa17798aa09f194, + 0xbf52a21514062f70, + 0xbf5b541f829ca99f, + 0x3f0cc0bd9fd11443, + 0x3f041f3b06c79efa, + 0xbeb4b22fc3292c98, + 0xbea1223e5773d27c, + 0x3e5118e5cf14a591, + 0x3e32ffb6478c2281, + 0xbde20a2b34bd7e9f, + 0xbdbd77afc051bc6c, + ], + [ + 0xbfc925c6fca08f54, + 0x3c941bba0a9908a3, + 0x3fb925c6fca08ea3, + 0xbf6049377403d97d, + 0xbf809463bbcfb70d, + 0x3f297b35471ddd4a, + 0x3f314dd43fc4bda8, + 0xbedbf665e54737fe, + 0xbed32caf8123dd12, + 0x3e7f510484fa37ba, + 0x3e6a42a3b8b1effd, + 0xbe1544b8d56d77a8, + 0xbdf81cfb72892ddb, + 0x3da3f5749b01c5c3, + ], + [ + 0xbc5c64a3611bf4cb, + 0x3fc8077f56c9b782, + 0xbf75467eb535dac4, + 0xbf9fd7c3ad6f5a3e, + 0x3f4c1b47c806f9c6, + 0x3f59166c7d3ee8f7, + 0xbf05f01522f72552, + 0xbf02aa939ff2e34a, + 0x3eb0129642c0eedc, + 0x3ea01716d7274ce0, + 0xbe4b21ada69ec1ec, + 0xbe320ffbd6f367e8, + 0x3ddd441699eaa4df, + 0x3dbc46351a30e033, + ], + [ + 0x3fc70c511227d5aa, + 0xbc903dd711e6b7a7, + 0xbfb70c511227d4fe, + 0x3f5910ebe1f1fa45, + 0x3f7e7dc08e6ff244, + 0xbf23bd7d15b0a88f, + 0xbf300357a101d595, + 0x3ed5ec733cb20d5b, + 0x3ed1e5d1fa4386ae, + 0xbe78f423a07fedeb, + 0xbe68c089aeb3a360, + 0x3e1143a2a87b28be, + 0x3df6f2d06548607b, + 0xbda07d7d6f49ddb9, + ], + [ + 0x3c57d1baaf487c60, + 0xbfc62d93aa9d05bb, + 0x3f70ba9ce88926ac, + 0x3f9d7073daebb038, + 0xbf462813c7f32d76, + 0xbf574a948d055ffc, + 0x3f01695764ad01fd, + 0x3f0170ab5ed77aa3, + 0xbea9c8e2cba34328, + 0xbe9e4d88f9ebcadb, + 0x3e460ec3e9bbfca2, + 0x3e312751ad8cf2c9, + 0xbdd825b2017389c1, + 0xbdbb0b4f2fdaca95, + ], + [ + 0xbfc5664e13b70621, + 0x3c8adfee580612ab, + 0x3fb5664e13b7057b, + 0xbf540ee3940b2f9d, + 0xbf7c5e1ad9fa40ad, + 0x3f1fb8a98f136a0c, + 0x3f2de9be57a255f8, + 0xbed1bec95e73b04b, + 0xbed0cf25bf302fd8, + 0x3e746784408bf531, + 0x3e676640f349bd8a, + 0xbe0c944164ad511b, + 0xbdf5d837e7a07aba, + 0x3d9ba3ab0edd6dab, + ], + [ + 0xbc543722dc20f623, + 0x3fc4b2a2ebf61ecd, + 0xbf6b3297fdae7373, + 0xbf9b8105d59b1125, + 0x3f420a3f8c10a2c5, + 0x3f55d18d69de4109, + 0xbefc79db490d157b, + 0xbf00679c92947f5d, + 0x3ea53ac3d1de0eb7, + 0x3e9ca750128116cf, + 0xbe4252ac12ff61fa, + 0xbe3051067c8a6420, + 0x3dd4435be57e146d, + 0x3db9dcd0ca8a2a1d, + ], + [ + 0x3fc40f90793605bb, + 0xbc86a24c27e99837, + 0xbfb40f907936051b, + 0x3f5085775a554a25, + 0x3f7aa0ce0420ebfd, + 0xbf1a32a28e65afde, + 0xbf2c26ebc916e22b, + 0x3ecd740098d21c07, + 0x3ecfc1baf78438dd, + 0xbe710c76235f5aa1, + 0xbe663455427d9c57, + 0x3e08141f4d843200, + 0x3df4d5216dec0df1, + 0xbd977e29b16d5fdb, + ], + [ + 0x3c5158813dc387f0, + 0xbfc37aac8c1aeabb, + 0x3f66ac0d2e2f2ac1, + 0x3f99e74e754ea6d8, + 0xbf3e1c0589dfbd21, + 0xbf5496158dc5b2be, + 0x3ef7d554035ae72e, + 0x3eff0b30f3d1fb7e, + 0xbea1d9e26f5a608f, + 0xbe9b35eeaebb5fed, + 0x3e3f010034c79a0b, + 0x3e2f1f31b65b3b40, + 0xbdd1445486f07cd4, + 0xbdb8c39615e71112, + ], + [ + 0xbfc2f2072e638cf3, + 0x3c8361a1f631cd41, + 0x3fb2f2072e638c5a, + 0xbf4bd42b64fc9353, + 0xbf792bb5e1e07ce1, + 0x3f161ace339d0b73, + 0x3f2aa8d1ce9fa384, + 0xbec8ef625b21b762, + 0xbece26d28032c92c, + 0x3e6d0116b3ae24e4, + 0x3e6526a75ee1fb24, + 0xbe049a7cd1a8b231, + 0xbdf3eac7c4ed94be, + 0x3d943b63ca10efa6, + ], + [ + 0xbc4e15276b2257f6, + 0x3fc27407dfadee6d, + 0xbf6346950bfd8dcc, + 0xbf988d48d1d4eb20, + 0x3f399e6923aaadf2, + 0x3f538984b76c8a40, + 0xbef4521949da5854, + 0xbefd855d7afc24f7, + 0x3e9e8a86b94090aa, + 0x3e99f1bce3767a28, + 0xbe3aa3a4df470ca3, + 0xbe2dc43a0da754d3, + 0x3dcdd3f81803822b, + 0x3db7c1fb1e948790, + ], + [ + 0x3fc1ff5eec6a01cd, + 0xbc80d20b3aa154f7, + 0xbfb1ff5eec6a0139, + 0x3f47daf64983dfb0, + 0x3f77ed5fffc0f26a, + 0xbf12f9479636506c, + 0xbf296027e938174a, + 0x3ec57486d36f86d5, + 0x3eccc1196ea00471, + 0xbe690ae6942f1564, + 0xbe64382bea1931c6, + 0x3e01ddd9b1b7300f, + 0x3df317ad2d0ae68b, + 0xbd91a1072249bec4, + ], + [ + 0x3c4a5ad4fde0c9d8, + 0xbfc192f23ce3e050, + 0x3f60a668185bfe0f, + 0x3f9764141d652022, + 0xbf3624437a2d49f0, + 0xbf52a184be0d3982, + 0x3ef196de0d85b64c, + 0x3efc317f84a19048, + 0xbe9a80187c3c9493, + 0xbe98d3840a83aa5f, + 0x3e3730c02a4a94ac, + 0x3e2c8d1491c62663, + 0xbdca1189016a9692, + 0xbdb6d754fe28a395, + ], + [ + 0xbfc12dd57bf18ad9, + 0x3c7d8e82da6b051b, + 0x3fb12dd57bf18a4a, + 0xbf44bebeff7ba93d, + 0xbf76d9afe882346d, + 0x3f10842d50795e09, + 0x3f2841d86abe55fe, + 0xbec2b5cab87b5693, + 0xbecb86b9f14c3df8, + 0x3e65e518bb040851, + 0x3e63642ad66ee13c, + 0xbdff581d7497507c, + 0xbdf2596d87b9a5f8, + 0x3d8f0ac4f8bd7787, + ], + [ + 0xbc47483488f843f0, + 0x3fc0cf3ed059c573, + 0xbf5d242aa5298caf, + 0xbf96613d93b0179b, + 0x3f33627f261d008d, + 0x3f51d69ca0d81e39, + 0xbeeed574ad2bb0d3, + 0xbefb06384da1c6bc, + 0x3e97452b1c4c76e9, + 0x3e97d51e823013c9, + 0xbe346a18e9324483, + 0xbe2b754cf5bbe0eb, + 0x3dc70467e00ca1a0, + 0x3db601d42e3f412d, + ], + [ + 0x3fc076826cc2c191, + 0xbc7a319136b9885b, + 0xbfb076826cc2c107, + 0x3f4241b03eab1b46, + 0x3f75e7f530011e0e, + 0xbf0d17978e4af2b0, + 0xbf2745b0deaaa29c, + 0x3ec0803f899002ed, + 0x3eca70060b7e6d91, + 0xbe635913c3c95352, + 0xbe62a694daaaf841, + 0x3dfbc4a0d8050004, + 0x3df1ad85820a38f2, + 0xbd8b942dd09eb308, + ], + [ + 0x3c44bc1f080e9694, + 0xbfc0230b9797a7b2, + 0x3f59c8083b2b6f7f, + 0x3f957d3203befd1b, + 0xbf3127cba226824c, + 0xbf5123447144f140, + 0x3eeb4fe26c88e56e, + 0x3ef9fc5254458847, + 0xbe94a44b3f692077, + 0xbe96f17d3ebae645, + 0x3e3224c9056773e9, + 0x3e2a78ba4580cd4b, + 0xbdc481589f7c80a5, + 0xbdb53f51ba6e502a, + ], + [ + 0xbfbfa8b41711c839, + 0x3c776c1e8f7fbdf3, + 0x3fafa8b41711c72d, + 0xbf403a8d0f113157, + 0xbf7511c6dad9e9ce, + 0x3f09e040fc7d8bd2, + 0x3f266582f59eaade, + 0xbebd62a1a025f4b0, + 0xbec976fa2e25f4ab, + 0x3e61411e4c00a8c3, + 0x3e61fc07a47b587f, + 0xbdf8d00a9e1b01e2, + 0xbdf1119f53145e82, + 0x3d88b3165222eaa1, + ], + [ + 0xbc429a344bf53c30, + 0x3fbf13faf32c8e0a, + 0xbf570558dddb7821, + 0xbf94b24d7a9338fa, + 0x3f2ea52a2144c44d, + 0x3f50834d8f3f71fa, + 0xbee86941a2b2f276, + 0xbef90e32ce46341a, + 0x3e92785e5b786d2a, + 0x3e9624822c6837c1, + 0xbe304286df6c8e25, + 0xbe2993b44677fad8, + 0x3dc2692b9cb4de6f, + 0x3db48dab755272e9, + ], + [ + 0x3fbe8727daa3daec, + 0xbc75105fe04e17a2, + 0xbfae8727daa3d9e9, + 0x3f3d19c52e0749cd, + 0x3f74524d481311c0, + 0xbf0735f790cd464b, + 0xbf259c8f9e41a823, + 0x3eba61a00c8699ad, + 0x3ec896d70eee04c2, + 0xbe5f04fa0ee2b2df, + 0xbe6161b9029aa2c1, + 0x3df656dc5e9fcd6d, + 0x3df083ab26947d7d, + 0xbd8646da85095b0a, + ], + [ + 0x3c40c6e5f0cb085b, + 0xbfbe018d99f5da1b, + 0x3f54b85897b35dc0, + 0x3f93fc44215342e3, + 0xbf2b9694d7112c4c, + 0xbf4fe6fdc6440535, + 0x3ee5fd096c74d7eb, + 0x3ef83770c8f9fca0, + 0xbe90a6f608ea2259, + 0xbe956ad410ba57f4, + 0x3e2d5aedc8414c7c, + 0x3e28c319213f9f62, + 0xbdc0a501a42574f9, + 0xbdb3eaef334996a5, + ], + [ + 0xbfbd8293aa55d18f, + 0x3c731f5b2ff0d80c, + 0x3fad8293aa55d093, + 0xbf3a48fe4aff1369, + 0xbf73a5ccbc11f183, + 0x3f04f91e4204c18c, + 0x3f24e72224187971, + 0xbeb7dac82ed8c06b, + 0xbec7cbd3d4a2512f, + 0x3e5c13a012cfa9d9, + 0x3e60d55d3c7a1e36, + 0xbdf43f07dbc0afd9, + 0xbdf001e1c5b3f199, + 0x3d8438754303f506, + ], + [ + 0xbc3e721cd5615376, + 0x3fbd09b210b30217, + 0xbf52c74f6d11fe58, + 0xbf9357bfc2be57e6, + 0x3f2901e4c492a05d, + 0x3f4ee2a36979201d, + 0xbee3f0cb91fe387d, + 0xbef7748920d95467, + 0x3e8e399ed3001c0e, + 0x3e94c1b715414ff1, + 0xbe2aab03479a9f97, + 0xbe2804415514f135, + 0x3dbe479692aefaf1, + 0x3db3555d82fea6b2, + ], + [ + 0x3fbc96700bf039e1, + 0xbc71712327ccc0e1, + 0xbfac96700bf038ec, + 0x3f37e5647d31307c, + 0x3f73095734a194a7, + 0xbf0312a4db676954, + 0xbf24424a9628de60, + 0x3eb5b4a67102dd95, + 0x3ec712e41250bc42, + 0xbe59918677637160, + 0xbe60550f5e9164bb, + 0x3df2750c65ef60c0, + 0x3def157ced5a6a13, + 0xbd8274ea409a4ed7, + ], + [ + 0x3c3bc4a30293d67b, + 0xbfbc28612a3bc18a, + 0x3f511f52577ff2df, + 0x3f92c21da135f4f3, + 0xbf26ce18f81fd4cd, + 0xbf4df586d8b6aeb3, + 0x3ee230fedd1a2b84, + 0x3ef6c2a754e321b0, + 0xbe8b973110796ae8, + 0xbe9426ec6d82a4f4, + 0x3e285d2ec3ed03c3, + 0x3e2754eefd1cc277, + 0xbdbbb13bcfd1095a, + 0xbdb2cb6d2f5a71d0, + ], + [ + 0xbfbbbf246914235e, + 0x3c6ff848b8004f4e, + 0x3fabbf2469142270, + 0xbf35d923e8472f22, + 0xbf727a96f1740b8b, + 0x3f01715e4bcd425f, + 0x3f23abacda98c7ab, + 0xbeb3dc30debc954f, + 0xbec6698cb2175b00, + 0x3e57691976ae1f76, + 0x3e5fbe7a90c59bea, + 0xbdf0ea1d3534d622, + 0xbdee39eb617c4576, + 0x3d80ee68d9ec5553, + ], + [ + 0xbc396e9c97e8f53c, + 0x3fbb5a6219b35e14, + 0xbf4f645fdb1a8578, + 0xbf923940d01de870, + 0x3f24e86a1e60f65a, + 0x3f4d1c6a18c716ef, + 0xbee0aeec5fff60bb, + 0xbef61f7d2f793aca, + 0x3e8950f6140dd479, + 0x3e939898b4cca68e, + 0xbe265f0fa2e22f9c, + 0xbe26b33d2f34a7ca, + 0x3db9731a4bc752ba, + 0x3db24bcd6b2996ce, + ], + [ + 0x3fbaf9cb49c4f934, + 0xbc6d6d35ce7e44b9, + 0xbfaaf9cb49c4f84c, + 0x3f3413b75ce0f622, + 0x3f71f7a8fec644b8, + 0xbf000844274ab940, + 0xbf23215daac1a429, + 0x3eb242e9f204ac2f, + 0x3ec5cdc3d7570c8d, + 0xbe5589d6656d4bd3, + 0xbe5ee52f2093b13f, + 0x3def25a4c863585f, + 0x3ded6edb90588bb5, + 0xbd7f34526b242536, + ], + [ + 0x3c37650e44849b1d, + 0xbfba9d1835947d6f, + 0x3f4cea253049a1d9, + 0x3f91bb71f665dc68, + 0xbf23427f47955327, + 0xbf4c54a7bd6e5c2f, + 0x3edebe9e62f23b54, + 0x3ef58924f95f83e9, + 0xbe875643b068495f, + 0xbe93152fe242208c, + 0x3e24a270e811a32a, + 0x3e261d90f63d69a9, + 0xbdb77dbf375b3033, + 0xbdb1d55983193fd8, + ], + [ + 0xbfba4407e04298d1, + 0x3c6b2fc36b7bca2c, + 0x3faa4407e04297ee, + 0xbf3288694b34d1f5, + 0xbf717f0266da7e64, + 0x3efd9a9a1d244e54, + 0x3f22a1c915f39e35, + 0xbeb0dd9e9cd3be0d, + 0xbec53dd8bf4c31dc, + 0x3e53e6ebf97ad18c, + 0x3e5e1c0952edd05e, + 0xbdeccc874da25bb3, + 0xbdecb26ccd2d18eb, + 0x3d7cdf4dbb3c6f9d, + ], + [ + 0xbc359685a4f3dcbc, + 0x3fb9ee5ee937fc88, + 0xbf4abf28ad5bf0d6, + 0xbf9147481084ad98, + 0x3f21d137345ad0c1, + 0x3f4b9c10ddf55248, + 0xbedc72c9d23eafc6, + 0xbef4fe0b3595e36e, + 0x3e859a1afaceaec9, + 0x3e929b65a8c65855, + 0xbe231c3162eaeee6, + 0xbe25928cb280552e, + 0x3db5c4ff841acff7, + 0x3db167146fe195c5, + ], + [ + 0x3fb99be744018c90, + 0xbc694d1606868f19, + 0xbfa99be744018bb2, + 0x3f312d4e1c1cc8e5, + 0x3f710f5ca51ef993, + 0xbefb714174938907, + 0xbf222b9fa834b14b, + 0x3eaf47107520863c, + 0x3ec4b861783e33d4, + 0xbe5276456457a7e2, + 0xbe5d612d705e69ee, + 0x3deabad16a1c7f4d, + 0x3dec0302ce313ca1, + 0xbd7ad13436da91d1, + ], + [ + 0x3c33fe4be92d3d54, + 0xbfb94c6f54aef04b, + 0x3f48d6371f01895c, + 0x3f90db975fd7dbd2, + 0xbf208bd163414db7, + 0xbf4af0d3d4cc449e, + 0x3eda6c8e7a6a50d9, + 0x3ef47cddcd0777cf, + 0xbe8412382d315a8f, + 0xbe922a214336182c, + 0x3e21c37df131e495, + 0x3e25110597bc5108, + 0xbdb43f276f813535, + 0xbdb10022868bfde2, + ], + [ + 0xbfb8ffc9bd24fe07, + 0x3c67889977473d30, + 0x3fa8ffc9bd24fd2f, + 0xbf2ff51b38ef3764, + 0xbf70a7a725d36032, + 0x3ef988128742f09f, + 0x3f21bdc845f948f5, + 0xbead1b60b68e1dce, + 0xbec43c2ce2f40a20, + 0x3e512fdc8d93240a, + 0x3e5cb30713086e1b, + 0xbde8e53a40557273, + 0xbdeb5f3c07e7903e, + 0x3d78fd3f37268235, + ], + [ + 0xbc3292fab12602d5, + 0x3fb8b5ccad12d631, + 0xbf4724d018597ba3, + 0xbf907764ae2b1e77, + 0x3f1ed6acc18c1a89, + 0x3f4a51693df22314, + 0xbed8a0ec5fd8948c, + 0xbef4047f31589663, + 0x3e82b667a039f6a4, + 0x3e91c073e21e1306, + 0xbe209143960c8785, + 0xbe2497fb13bc2530, + 0x3db2e4699f6adc63, + 0x3db09fc4db2b9fa9, + ], + [ + 0x3fb86e51be0a9153, + 0xbc65fa6f95d443a0, + 0xbfa86e51be0a907f, + 0x3f2dd3c244b5713f, + 0x3f7046fc5a20f248, + 0xbef7d51accd8d1f8, + 0xbf2157556b6a5aec, + 0x3eab2d01d207a4bc, + 0x3ec3c837e1b45aa2, + 0xbe500d3d097d314b, + 0xbe5c103c5b331300, + 0x3de742b129024e6b, + 0x3deac5e6c8a70206, + 0xbd775bdd14ccde28, + ], + [ + 0x3c314cbdbd279267, + 0xbfb829356999a096, + 0x3f45a280e033e683, + 0x3f9019dba8336dd6, + 0xbf1cd4559d92616b, + 0xbf49bc85774f69b2, + 0x3ed70706561ca508, + 0x3ef393fc6c586d81, + 0xbe818009f70f6704, + 0xbe915d911e7ad3a2, + 0x3e1eff8fd0ef6949, + 0x3e24268fd4573ff9, + 0xbdb1ae6de683a236, + 0xbdb0455820923c5a, + ], + [ + 0xbfb7e656efb009ad, + 0x3c649ee393402ee6, + 0x3fa7e656efb008de, + 0xbf2bec6b33f0062e, + 0xbf6fd932c269835b, + 0x3ef6504d7e1cd7db, + 0x3f20f77ce56ff037, + 0xbea972e583ac028d, + 0xbec35ba4e79f8507, + 0x3e4e1250b982c251, + 0x3e5b77a3c340d6b3, + 0xbde5cbcf474ee83d, + 0xbdea35fa30652af1, + 0x3d75e5f83583c368, + ], + [ + 0xbc375f30b05ffab2, + 0x3fb7a597e9550932, + 0xbf44486c0b011f0f, + 0xbf8f848eec0e0c40, + 0x3f1b077fae02763b, + 0x3f49310d6e6682f5, + 0xbed597a5bccfeb73, + 0xbef32a855d113180, + 0x3e8069b8fa206f26, + 0x3e9100c89784eeac, + 0xbe1d14a175c009c5, + 0xbe23bbc9bff27ef1, + 0x3db0950fae2cbe6f, + 0x3dafc6492b94025c, + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,702 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#![allow(clippy::excessive_precision)] + +use crate::bessel::alpha1::{ + bessel_1_asympt_alpha, bessel_1_asympt_alpha_fast, bessel_1_asympt_alpha_hard, +}; +use crate::bessel::beta1::{ + bessel_1_asympt_beta, bessel_1_asympt_beta_fast, bessel_1_asympt_beta_hard, +}; +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::j1_coeffs::{J1_COEFFS, J1_ZEROS, J1_ZEROS_VALUE}; +use crate::bessel::j1_coeffs_taylor::J1_COEFFS_TAYLOR; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::{f_polyeval8, f_polyeval9, f_polyeval12, f_polyeval19}; +use crate::rounding::CpuCeil; +use crate::sin_helper::{sin_dd_small, sin_dd_small_fast, sin_f128_small}; +use crate::sincos_reduce::{AngleReduced, rem2pi_any, rem2pi_f128}; + +/// Bessel of the first kind of order 1 +/// +/// Note about accuracy: +/// - Close to zero Bessel have tiny values such that testing against MPFR must be done exactly +/// in the same precision, since any nearest representable number have ULP > 0.5, +/// for example `J1(0.000000000000000000000000000000000000023509886)` in single precision +/// have 0.7 ULP for any number with extended precision that would be represented in f32 +/// Same applies to J1(4.4501477170144018E-309) in double precision and some others subnormal numbers +pub fn f_j1(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x72338c9356bb0314u64 { + // |x| <= 0.000000000000000000000000000000001241 + // J1(x) ~ x/2+O[x]^3 + return x * 0.5; + } + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + // J1(x) ~ x/2-x^3/16+O[x]^5 + let quad_part_x = x * 0.125; // exact. x / 8 + return f_fmla(quad_part_x, -quad_part_x, 0.5) * x; + } + if x.is_infinite() { + return 0.; + } + return x + f64::NAN; // x == NaN + } + + let ax: u64 = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if ax < 0x4052a6784230fcf8u64 { + // |x| < 74.60109 + if ax < 0x3feccccccccccccd { + // |x| < 0.9 + return j1_maclaurin_series_fast(x); + } + return j1_small_argument_fast(x); + } + + j1_asympt_fast(x) +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) +*/ +#[inline] +fn j1_asympt_fast(x: f64) -> f64 { + let origin_x = x; + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + let x = x.abs(); + + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let recip = if x.to_bits() > 0x7fd000000000000u64 { + DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_div_fma(4.0, x), 0.25) + } else { + DoubleDouble::from_recip(x) + }; + + let alpha = bessel_1_asympt_alpha_fast(recip); + let beta = bessel_1_asympt_beta_fast(recip); + + let AngleReduced { angle } = rem2pi_any(x); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_sin = sin_dd_small_fast(r0); + let z0 = DoubleDouble::quick_mult(beta, m_sin); + let r_sqrt = DoubleDouble::from_rsqrt_fast(x); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let p = DoubleDouble::quick_mult(scale, z0); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3be0000000000000), // 2^-65 + f64::from_bits(0x3a60000000000000), // 2^-89 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64() * sign_scale; + } + + j1_asympt(origin_x, recip, r_sqrt, angle) +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) +*/ +fn j1_asympt(x: f64, recip: DoubleDouble, r_sqrt: DoubleDouble, angle: DoubleDouble) -> f64 { + let origin_x = x; + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let alpha = bessel_1_asympt_alpha(recip); + let beta = bessel_1_asympt_beta(recip); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_sin = sin_dd_small(r0); + let z0 = DoubleDouble::quick_mult(beta, m_sin); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3bc0000000000000), // 2^-67 + f64::from_bits(0x39c0000000000000), // 2^-99 + ); + + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64() * sign_scale; + } + + j1_asympt_hard(origin_x) +} + +/** +Generated in Sollya: +```text +pretty = proc(u) { + return ~(floor(u*1000)/1000); +}; + +bessel_j1 = library("./cmake-build-release/libbessel_sollya.dylib"); + +f = bessel_j1(x)/x; +d = [0, 0.921]; +w = 1; +pf = fpminimax(f, [|0,2,4,6,8,10,12,14,16,18,20,22,24|], [|107, 107, 107, 107, 107, D...|], d, absolute, floating); + +w = 1; +or_f = bessel_j1(x); +pf1 = pf * x; +err_p = -log2(dirtyinfnorm(pf1*w-or_f, d)); +print ("relative error:", pretty(err_p)); + +for i from 0 to degree(pf) by 2 do { + print("'", coeff(pf, i), "',"); +}; +``` +See ./notes/bessel_sollya/bessel_j1_at_zero_fast.sollya +**/ +#[inline] +pub(crate) fn j1_maclaurin_series_fast(x: f64) -> f64 { + const C0: DoubleDouble = DoubleDouble::from_bit_pair((0x3b30e9e087200000, 0x3fe0000000000000)); + let x2 = DoubleDouble::from_exact_mult(x, x); + let p = f_polyeval12( + x2.hi, + f64::from_bits(0xbfb0000000000000), + f64::from_bits(0x3f65555555555555), + f64::from_bits(0xbf0c71c71c71c45e), + f64::from_bits(0x3ea6c16c16b82b02), + f64::from_bits(0xbe3845c87ec0cbef), + f64::from_bits(0x3dc27e0313e8534c), + f64::from_bits(0xbd4443dd2d0305d0), + f64::from_bits(0xbd0985a435fe9aa1), + f64::from_bits(0x3d10c82d92c46d30), + f64::from_bits(0xbd0aa3684321f219), + f64::from_bits(0x3cf8351f29ac345a), + f64::from_bits(0xbcd333fe6cd52c9f), + ); + let mut z = DoubleDouble::mul_f64_add(x2, p, C0); + z = DoubleDouble::quick_mult_f64(z, x); + + // squaring error (2^-56) + poly error 2^-75 + let err = f_fmla( + x2.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3b40000000000000), // 2^-75 + ); + let ub = z.hi + (z.lo + err); + let lb = z.hi + (z.lo - err); + + if ub == lb { + return z.to_f64(); + } + j1_maclaurin_series(x) +} + +/** +Generated in Sollya: +```text +pretty = proc(u) { + return ~(floor(u*1000)/1000); +}; + +bessel_j1 = library("./cmake-build-release/libbessel_sollya.dylib"); + +f = bessel_j1(x)/x; +d = [0, 0.921]; +w = 1; +pf = fpminimax(f, [|0,2,4,6,8,10,12,14,16,18,20,22,24|], [|107, 107, 107, 107, 107, D...|], d, absolute, floating); + +w = 1; +or_f = bessel_j1(x); +pf1 = pf * x; +err_p = -log2(dirtyinfnorm(pf1*w-or_f, d)); +print ("relative error:", pretty(err_p)); + +for i from 0 to degree(pf) by 2 do { + print("'", coeff(pf, i), "',"); +}; +``` +See ./notes/bessel_sollya/bessel_j1_at_zero.sollya +**/ +pub(crate) fn j1_maclaurin_series(x: f64) -> f64 { + let origin_x = x; + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + let x = x.abs(); + + const CL: [(u64, u64); 5] = [ + (0xb930000000000000, 0x3fe0000000000000), + (0x39c8e80000000000, 0xbfb0000000000000), + (0x3c05555554f3add7, 0x3f65555555555555), + (0xbbac71c4eb0f8c94, 0xbf0c71c71c71c71c), + (0xbb3f56b7a43206d4, 0x3ea6c16c16c16c17), + ]; + + let dx2 = DoubleDouble::from_exact_mult(x, x); + + let p = f_polyeval8( + dx2.hi, + f64::from_bits(0xbe3845c8a0ce5129), + f64::from_bits(0x3dc27e4fb7789ea2), + f64::from_bits(0xbd4522a43f633af1), + f64::from_bits(0x3cc2c97589d53f97), + f64::from_bits(0xbc3ab8151dca7912), + f64::from_bits(0x3baf08732286d1d4), + f64::from_bits(0xbb10ac65637413f4), + f64::from_bits(0xbae4d8336e4f779c), + ); + + let mut p_e = DoubleDouble::mul_f64_add(dx2, p, DoubleDouble::from_bit_pair(CL[4])); + p_e = DoubleDouble::mul_add(dx2, p_e, DoubleDouble::from_bit_pair(CL[3])); + p_e = DoubleDouble::mul_add(dx2, p_e, DoubleDouble::from_bit_pair(CL[2])); + p_e = DoubleDouble::mul_add(dx2, p_e, DoubleDouble::from_bit_pair(CL[1])); + p_e = DoubleDouble::mul_add(dx2, p_e, DoubleDouble::from_bit_pair(CL[0])); + + let p = DoubleDouble::quick_mult_f64(p_e, x); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3bd0000000000000), // 2^-66 + f64::from_bits(0x3a00000000000000), // 2^-95 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return j1_maclaurin_series_hard(origin_x); + } + + p.to_f64() * sign_scale +} + +/** +Taylor expansion at 0 + +Generated by SageMath: +```python +def print_expansion_at_0(): + print(f"static C: [DyadicFloat128; 13] = ") + from mpmath import mp, j1, taylor, expm1 + poly = taylor(lambda val: j1(val), 0, 26) + real_i = 0 + print("[") + for i in range(1, len(poly), 2): + print_dyadic(poly[i]) + real_i = real_i + 1 + print("],") + + print("];") + +mp.prec = 180 + +print_expansion_at_0() +``` +**/ +#[cold] +#[inline(never)] +fn j1_maclaurin_series_hard(x: f64) -> f64 { + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + let x = x.abs(); + static C: [DyadicFloat128; 13] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0xe38e38e3_8e38e38e_38e38e38_e38e38e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -148, + mantissa: 0xb60b60b6_0b60b60b_60b60b60_b60b60b6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -155, + mantissa: 0xc22e4506_72894ab6_cd8efb11_d33f5618_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -162, + mantissa: 0x93f27dbb_c4fae397_780b69f5_333c725b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -170, + mantissa: 0xa91521fb_2a434d3f_649f5485_f169a743_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -178, + mantissa: 0x964bac6d_7ae67d8d_aec68405_485dea03_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -187, + mantissa: 0xd5c0f53a_fe6fa17f_8c7b0b68_39691f4e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -196, + mantissa: 0xf8bb4be7_8e7896b0_58fee362_01a4370c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -205, + mantissa: 0xf131bdf7_cff8d02e_e1ef6820_f9d58ab6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -214, + mantissa: 0xc5e72c48_0d1aec75_3caa2e0d_edd008ca_u128, + }, + ]; + + let rx = DyadicFloat128::new_from_f64(x); + let dx = rx * rx; + + let mut p = C[12]; + for i in (0..12).rev() { + p = dx * p + C[i]; + } + + (p * rx).fast_as_f64() * sign_scale +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +pub(crate) fn j1_small_argument_fast(x: f64) -> f64 { + static SIGN: [f64; 2] = [1., -1.]; + let sign_scale = SIGN[x.is_sign_negative() as usize]; + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // let avg_step = 74.60109 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6300176043004198; + + let fx = x_abs * INV_STEP; + const J1_ZEROS_COUNT: f64 = (J1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(J1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return j1_maclaurin_series_fast(x); + } + + let r = DoubleDouble::full_add_f64(-found_zero, x_abs); + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(J1_ZEROS_VALUE[idx]) * sign_scale; + } + + let is_zero_too_close = dist.abs() < 1e-3; + + let c = if is_zero_too_close { + &J1_COEFFS_TAYLOR[idx - 1] + } else { + &J1_COEFFS[idx - 1] + }; + + let p = f_polyeval19( + r.hi, + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + f64::from_bits(c[13].1), + f64::from_bits(c[14].1), + f64::from_bits(c[15].1), + f64::from_bits(c[16].1), + f64::from_bits(c[17].1), + f64::from_bits(c[18].1), + f64::from_bits(c[19].1), + f64::from_bits(c[20].1), + f64::from_bits(c[21].1), + f64::from_bits(c[22].1), + f64::from_bits(c[23].1), + ); + + let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[4])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0])); + let err = f_fmla( + z.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3bf0000000000000), // 2^-64 + ); + let ub = z.hi + (z.lo + err); + let lb = z.hi + (z.lo - err); + + if ub == lb { + return z.to_f64() * sign_scale; + } + + j1_small_argument_dd(sign_scale, r, c) +} + +fn j1_small_argument_dd(sign_scale: f64, r: DoubleDouble, c0: &[(u64, u64); 24]) -> f64 { + let c = &c0[15..]; + + let p0 = f_polyeval9( + r.to_f64(), + f64::from_bits(c[0].1), + f64::from_bits(c[1].1), + f64::from_bits(c[2].1), + f64::from_bits(c[3].1), + f64::from_bits(c[4].1), + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + ); + + let c = c0; + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c10000000000000), // 2^-62 + f64::from_bits(0x3a00000000000000), // 2^-95 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return j1_small_argument_path_hard(sign_scale, r, c); + } + p.to_f64() * sign_scale +} + +#[cold] +#[inline(never)] +fn j1_small_argument_path_hard(sign_scale: f64, r: DoubleDouble, c: &[(u64, u64); 24]) -> f64 { + let mut p = DoubleDouble::from_bit_pair(c[23]); + for i in (0..23).rev() { + p = DoubleDouble::mul_add(r, p, DoubleDouble::from_bit_pair(c[i])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + } + p.to_f64() * sign_scale +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) + + This method is required for situations where x*x or 1/(x*x) will overflow +*/ +#[cold] +#[inline(never)] +fn j1_asympt_hard(x: f64) -> f64 { + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + let x = x.abs(); + + const SQRT_2_OVER_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcc42299e_a1b28468_7e59e280_5d5c7180_u128, + }; + + const MPI_OVER_4: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let x_dyadic = DyadicFloat128::new_from_f64(x); + let recip = DyadicFloat128::accurate_reciprocal(x); + + let alpha = bessel_1_asympt_alpha_hard(recip); + let beta = bessel_1_asympt_beta_hard(recip); + + let angle = rem2pi_f128(x_dyadic); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_sin = sin_f128_small(r0); + + let z0 = beta * m_sin; + let r_sqrt = bessel_rsqrt_hard(x, recip); + let scale = SQRT_2_OVER_PI * r_sqrt; + let p = scale * z0; + p.fast_as_f64() * sign_scale +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_j1() { + assert_eq!(f_j1(0.000000000000000000000000000000001241), 6.205e-34); + assert_eq!(f_j1(0.0000000000000000000000000000004321), 2.1605e-31); + assert_eq!(f_j1(0.00000000000000000004321), 2.1605e-20); + assert_eq!(f_j1(73.81695991658546), -0.06531447184607607); + assert_eq!(f_j1(0.01), 0.004999937500260416); + assert_eq!(f_j1(0.9), 0.4059495460788057); + assert_eq!( + f_j1(162605674999778540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008686943178258183 + ); + assert_eq!(f_j1(3.831705970207517), -1.8501090915423025e-15); + assert_eq!(f_j1(-3.831705970207517), 1.8501090915423025e-15); + assert_eq!(f_j1(-6.1795701510782757E+307), 8.130935041593236e-155); + assert_eq!( + f_j1(0.000000000000000000000000000000000000008827127), + 0.0000000000000000000000000000000000000044135635 + ); + assert_eq!( + f_j1(-0.000000000000000000000000000000000000008827127), + -0.0000000000000000000000000000000000000044135635 + ); + assert_eq!(f_j1(5.4), -0.3453447907795863); + assert_eq!( + f_j1(77.743162408196766932633181568235159), + 0.09049267898021947 + ); + assert_eq!( + f_j1(84.027189586293545175976760219782591), + 0.0870430264022591 + ); + assert_eq!(f_j1(f64::NEG_INFINITY), 0.0); + assert_eq!(f_j1(f64::INFINITY), 0.0); + assert!(f_j1(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1543 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +J1 zeros and extremums on [-76;76] + +Generated in SageMath: +```python +from mpmath import mp, mpf, findroot, j1 +from sage.all import * +import struct + +DR = RealField(52) +DD = RealField(190) + +def double_to_hex(f): + packed = struct.pack('>d', float(f)) + return '0x' + packed.hex() + +def split_double_double(x): + x_hi = DR(x) # convert to f64 + x_lo = x - DD(x_hi) + return (x_lo,x_hi) + +def print_double_double(mark, x): + splat = split_double_double(x) + print(f"{mark}({double_to_hex(splat[0])}, {double_to_hex(splat[1])}),") + +zeros = [] + +# Step size to detect sign changes +mp.prec = 150 + +step = mpf("0.001") +epsilon = mpf("1e-35") +x = mpf("0.0") + +previous_zero = R120(0) +j1_zeros = [] + +while x < mpf("76.0"): + f1 = besselj(1, x) + f2 = besselj(1, x + step) + if f1 * f2 < 0: + zero = findroot(lambda t: j1(t), (x, x + step), solver='bisect', tol=mp.mpf("1e-41")) + previous_zero = zero + j1_zeros.append(zero) + if previous_zero is not None and abs(x - mpf(f'{round(x)}')) < epsilon: + zeros.append(previous_zero) + x += step + +j1_extrema = [] + +x = mpf("0.0") +while x < mpf("76.0"): + d1 = mp.diff(lambda t: j1(t), x) + d2 = mp.diff(lambda t: j1(t), x + step) + if d1 * d2 < 0: + extremum = findroot(lambda t: mp.diff(lambda u: j1(u), t), (x, x + step), solver='bisect', tol=mp.mpf("1e-41")) + j1_extrema.append(extremum) + x += step + +j1_zeros.extend(j1_extrema) +j1_zeros = sorted(j1_zeros) + +print("static J1_ZEROS: [(u64, u64); 46] = [") +for z in j1_zeros: + k = split_double_double(DD(z)) + hi = double_to_hex(k[1]) + lo = double_to_hex(k[0]) + print(f"({lo}, {hi}),") + +print("];") +``` +See notes/bessel_j1_taylor.ipynb +**/ +pub(crate) static J1_ZEROS: [(u64, u64); 48] = [ + (0x0, 0x0), + (0x3c5616d820cfdaeb, 0x3ffd757d1fec8a3a), + (0xbca60155a9d1b257, 0x400ea75575af6f09), + (0x3ca5c646a75d7539, 0x40155365bc032467), + (0xbc9b226d9d243828, 0x401c0ff5f3b47250), + (0xbca63e17ec20a31d, 0x402112980f0b88a1), + (0x3cc02610a51562b6, 0x402458d0d0bdfc29), + (0x3cc9a84d3a5fedc1, 0x40276979797ee5ac), + (0x3cb2bce7fd18e693, 0x402aa5baf310e5a2), + (0xbcc6932b987094f1, 0x402dba284a17ac59), + (0xbcdd2a68e88ab318, 0x4030787b360508c5), + (0xbca022f6b2b54db9, 0x403203f9a24e6527), + (0xbcd21830197e9e86, 0x40339da8e7416ca4), + (0x3cdeaafeaf8ec1af, 0x40352a1424a1a9fa), + (0xbcc1bf33afef88f2, 0x4036c294e3d4d8ac), + (0xbcb2d773b50cf8b9, 0x40384fb31dee1635), + (0x3cc1a2686480d882, 0x4039e7570dcea106), + (0x3cd0bdee27293d79, 0x403b75014427514d), + (0xbcb42ce39ec976fb, 0x403d0bfcf471fccc), + (0x3cbda49c2c143483, 0x403e9a179fba532a), + (0xbcdbe3a1cd066b67, 0x404018476e6b2bf0), + (0xbce6b00c1279ef0a, 0x4040df82ebd54e32), + (0xbced5fbbff045068, 0x4041aa890dc5e97c), + (0x3cd7d864bbf17a30, 0x404271eb1b80430e), + (0x3cc9eafeca0ca4fc, 0x40433cc523d5cb69), + (0xbce5cecac300a9a1, 0x40440447e50db184), + (0x3cc489bd556e5109, 0x4044cefcf1734b62), + (0x3cdd0fd96f29c211, 0x4045969bc7271083), + (0x3ce4f716f3179d90, 0x404661315d6b133f), + (0xbce158b763edd0e8, 0x404728e892a88fc9), + (0xbcef3950a842db79, 0x4047f36312028ad6), + (0x3ce97656bbc2396e, 0x4048bb2fa2037de3), + (0x3ce85d7bdb30baf1, 0x404985928f96d51e), + (0xbce71f8560ac9f18, 0x404a4d71fcb56f8c), + (0x3ce3d41e041caa68, 0x404b17c038c2018c), + (0xbcde6d04716d8d21, 0x404bdfb06eb790aa), + (0x3cda139ce2cd08ac, 0x404ca9ec5a82324b), + (0x3cc8b5cc7b4501c1, 0x404d71eb98682f07), + (0xbcb12e6ef2e594e2, 0x404e3c1731d64f1e), + (0x3cb399bfca430021, 0x404f0423f99b4b53), + (0x3cdfd1ee8286358a, 0x404fce40efb1156e), + (0x3c800660b51502f0, 0x40504b2cfcbb084d), + (0x3ced3cacfc720418, 0x4050b034dde75b42), + (0x3cc4b877d4f6d900, 0x40511446f60f1458), + (0xbcee669304bfe748, 0x40517948db63675c), + (0x3cfad20ca758a714, 0x4051dd600b743a9b), + (0x3cf8eb4a94b63936, 0x4052425c7dcacdf6), + (0xbcfa196892f68386, 0x4052a67859bc641e), +]; + +/** +Precomputed values in exact Bessel J1 zero. + +Generated by MPFR: +```text +let mut arr = vec![]; +for zeros in J1_ZEROS.iter() { + let mpfr = Float::with_val(107, f64::from_bits(zeros.1)).j1(); + arr.push(mpfr.to_f64().to_bits()); +} +println!( + "arr: [{}]", + arr.iter() + .map(|x| format!("0x{:016X}", x)) + .collect::>() + .join(", ") +); +``` +**/ +pub(crate) static J1_ZEROS_VALUE: [u64; 48] = [ + 0x0000000000000000, + 0x3FE29EA3D19F035F, + 0xBC91B9C1C3FB286F, + 0xBFD626EE83500BF2, + 0x3C8049770CE74C2E, + 0x3FD17DBF09D40D25, + 0x3CA0212F4E592523, + 0xBFCDDCEB4CE1BF4A, + 0xBC905DCC62D0D222, + 0x3FCA7F63FEA81F26, + 0xBCB6EB905BA2ABFA, + 0xBFC810F50225B04B, + 0x3CAA10B2F7B4E69D, + 0x3FC633E7F7F05301, + 0xBC97BC6D5A660382, + 0xBFC4B71D4CA2CC69, + 0xBC961C29FAC28FDF, + 0x3FC37DFA8F5A550A, + 0xBC87E3B01386785F, + 0xBFC2768D29C69936, + 0x3CAF5EFD41F756B6, + 0x3FC194EBA75B32F9, + 0xBCBF89DCEDB3EA9B, + 0xBFC0D0D36473E98C, + 0xBC9AAAF726A29E97, + 0x3FC02455675AB6D2, + 0x3C9451B6225ACBFB, + 0xBFBF161D0C28B48C, + 0xBCB40032091A4E00, + 0x3FBE0357C158B119, + 0xBCBCCB5A05A6E4AA, + 0xBFBD0B36E5737458, + 0xBCB5C457E4A6A2F1, + 0x3FBC29AE8400A320, + 0x3CB13169F65EFC7C, + 0xBFBB5B8273B75055, + 0xBCA5FB7DBD93E256, + 0x3FBA9E13A0DB6429, + 0xBC7C3482175F80D7, + 0xBFB9EF3BB2213B0B, + 0xBCA977092852774B, + 0x3FB94D3276914E51, + 0x3CB6D73591BFEB5D, + 0xBFB8B67A2481077D, + 0x3CB735BC851F7831, + 0x3FB829D06FEE9266, + 0x3CC29C7C75EEB12F, + 0xBFB7A62320798175, +]; + +/** +Following search for J1 (see [J1_ZEROS]) zeros and extremums: +at each zero and extremum we're doing Taylor series expansion +one that should be enough to cover whole interval between zero or peak +which is PI/4 + +Generated in SageMath and Sollya: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = (zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(j1_zeros) +# print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 500; +bessel_j1 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_j1(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RealField(500)(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +def print_remez_coeffs(poly): + print("J1TaylorExtendedSeries {") + print_double_double("a0: ", poly[0]) + print_double_double("a1: ", poly[1]) + print_double_double("a2: ", poly[2]) + print_double_double("a3: ", poly[3]) + print_double_double("a4: ", poly[4]) + print_double_double("a5: ", poly[5]) + print_double_double("a6: ", poly[6]) + print_double_double("a7: ", poly[7]) + print_double_double("a8: ", poly[8]) + print_double_double("a9: ", poly[9]) + print_double_double("a10: ", poly[10]) + print_double_double("a11: ", poly[11]) + print_double_double("a12: ", poly[12]) + print_double_double("a13: ", poly[13]) + print("c: [") + for i in range(14, len(poly)): + coeff = poly[i] + print(f"{double_to_hex(coeff)},") + print("],") + print("},") + +degree = 23 + +print(f"pub(crate) static J1_COEFFS: [J1TaylorExtendedSeries; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print_remez_coeffs(coeffs) +print("];") +``` +**/ +pub(crate) static J1_COEFFS: [[(u64, u64); 24]; 47] = [ + [ + (0x3c61f1c324453b22, 0x3fe29ea3d19f035f), + (0x35fa0d84854cf50d, 0xb9a948d98c79544d), + (0xbc6e3631ae170265, 0xbfca41115c5df243), + (0xbc18acc50ffb929f, 0x3f78d1448e6fed48), + (0x3c0e85a7cffdb986, 0x3f8c441a2f9de22b), + (0x3bd94ca1957aa906, 0xbf386671c18b088a), + (0x3bd950ccbdd65736, 0xbf39e2504ddc7608), + (0xbb61b3ae884e8323, 0x3ee34ccbca0c75d1), + (0x3b7ab8f6e0e5328c, 0x3eda4973784d1087), + (0x3b1f40e6cc67a3d5, 0xbe81045322aaab45), + (0x3b06ea738f9ecf6a, 0xbe70fae0da6cdcef), + (0xbabbaad3785f91ec, 0x3e13546cef5ed00e), + (0x3a89c3da0f7d1467, 0x3dfe5ee82e6676f1), + (0xba262fd170d5dbad, 0xbd9ec80cc8b644d5), + (0xba23036bcf1b50d2, 0xbd83eb2e99627fad), + (0xb9cc7616af2b9f56, 0x3d222bfcdb211968), + (0xb9909fcb58b04d57, 0x3d03fb337676fc98), + (0x3946bee5d8936909, 0xbca0901290ec992d), + (0x391f5d570e3a4795, 0xbc7fa6a8aa2582e5), + (0xb8b23101eae00b2a, 0x3c18078252545e8a), + (0x386d13c8640abb7d, 0x3bf44b354a191eee), + (0xb827a697c66ddb50, 0xbb8c75d1f25f35fc), + (0x380d5a5801772dad, 0xbb6549fce4790a31), + (0x378246c0eb5ba71c, 0x3affdbc62c23326e), + ], + [ + (0x35f9dfa8e2931f8b, 0xb95730bb59760ac5), + (0x3c62de1143765a99, 0xbfd9c6cf582cbf7f), + (0xbc46b8d73329a70b, 0x3faae8a39f51ad04), + (0xbc47767d9698b3c4, 0x3fab589d1da13905), + (0x3c0e65e41f715973, 0xbf7537544c331da7), + (0x3bc117d1587f9833, 0xbf624b3409959064), + (0x3bb8c81b4b053820, 0x3f26e4c2d5354224), + (0x3b9859e946b98719, 0x3f083a06e30c4109), + (0x3b51fd9c02e20b11, 0xbec9799d4c9f2549), + (0xbb4ffc0b40a079e5, 0xbea33825cd2e2c16), + (0x3aeb5032c6339f4e, 0x3e617069233e916c), + (0x3a80c496c8db027f, 0x3e34569b22afc3c8), + (0xba9a374b068a8d41, 0xbdf03b9e9651056f), + (0x3a4c5798959dc28e, 0xbdbec62310af5fa2), + (0xba11dc4cca029308, 0x3d75ec84e47b7d9e), + (0x39d2cf2c8d7c612a, 0x3d417a40c942a964), + (0x3971ff6b4d2284f1, 0xbcf67cb1d01a03c7), + (0xb943da1ee0003f81, 0xbcbee7ff9372e125), + (0xb8f9e098c8ea9826, 0x3c721fb8d23ce65d), + (0x38d89765c4f16618, 0x3c35e053c1413792), + (0xb8575b3ab1c49578, 0xbbe79265a43bea11), + (0xb82c7bf56bef062f, 0xbba95d6cc94f810f), + (0xb7f5bad532a4cc34, 0x3b59332b7e688450), + (0x37ac610ae03b7f77, 0x3b1a2c1db24ae655), + ], + [ + (0xbc782d627160714a, 0xbfd626ee83500bf2), + (0x35e215832cad36da, 0x39465d6b7a56edac), + (0x3c6ae8952e6f1d78, 0x3fc55f6bec9ef962), + (0x3c0d30f1a30544cb, 0xbf83d23336fd10e4), + (0x3c2695c3589d6e1d, 0xbf88c77a983a0814), + (0x3bea1200f42f4b09, 0x3f45cdc98db1cbe2), + (0x3bd343248aee865b, 0x3f373576ff46ee3b), + (0x3b8a8cd3c63aa60b, 0xbef2461447d7b423), + (0x3b6a8a9edacbe6fe, 0xbed7b853456b6eaa), + (0xbaff3625eaafdafc, 0x3e90abfc68274a98), + (0xbaea64c013116245, 0x3e6ea7a1ee26124d), + (0x3acef44f1141cf97, 0xbe235c0413e01419), + (0xba7020655e19f397, 0xbdfb5c5d512fbafe), + (0x3a2522345bdc9b62, 0x3daf4c5e26fd6f49), + (0xba1a9c1d9fde6bb0, 0x3d81e4c43397bb8d), + (0x39aead7c3865323c, 0xbd32addefc4e427f), + (0x399ef826261673f0, 0xbd01e4fadc073884), + (0xb9584f8fae96d4c1, 0x3cb12a0b89e91563), + (0x3911cf3d91af7eef, 0x3c7c4246886f561c), + (0xb8932b17cb520173, 0xbc290ee1bd0b60e5), + (0x388f8ba7ff012875, 0xbbf21116fef61a90), + (0x38093d7080102807, 0x3b9dcbd61b5fcfcc), + (0xb7ddad88c94d63e2, 0x3b62f7833d3a6e0a), + (0xb7a7e960c2811c48, 0xbb0f75a3322d6adb), + ], + [ + (0x35d923fac9298498, 0xb943ab00450c21a5), + (0x3c7af22d033ee0a8, 0x3fd33518b3874e8a), + (0xbc23b4d62984701e, 0xbf95e70dc60362bf), + (0xbc476d8715df734e, 0xbfa80c83bdeee5b0), + (0x3c03dac20aaf9d3e, 0x3f69a4b292e3de42), + (0x3bd887eed7bf2f4a, 0x3f613fbc7d698217), + (0xbbac52a914699396, 0xbf207358bbdbff91), + (0xbb64764498326fe8, 0xbf0796a751f89051), + (0xbb6df66e2a5b80ce, 0x3ec4255b015aded4), + (0xbb3ae5bbd6b6b7b2, 0x3ea3026e0ce97ab9), + (0xbaf53c3132b45416, 0xbe5d48dcdae92f2c), + (0x3ac329ab58cdf5c8, 0xbe344639d7eeb0a6), + (0xba7227361e36b492, 0x3dec62ccb4a32eb2), + (0x3a436c156b981e3c, 0x3dbecae92e85448e), + (0xba15900bb4077790, 0xbd73bb6898d7381b), + (0x39ceeaf13516632f, 0xbd4183edbb8f3baa), + (0xb946b19e901a3f2a, 0x3cf4ae3e7e418192), + (0x395392c9d1b10508, 0x3cbefbb1e7e7f06a), + (0xb91d78a8cbca8fc8, 0xbc70f28d91f2bb8c), + (0xb8c1412abdb69981, 0xbc35ec327b001a36), + (0x3866c77527da5dfe, 0x3be65536194079a9), + (0x37d83c37616b601d, 0x3ba9644a2a48ce1f), + (0xb7fc2f10d93b3bda, 0xbb58069a9c48e50d), + (0x37b28c16423dadcd, 0xbb18f8666a0fbd52), + ], + [ + (0xbc7d48dbfa0ea1a4, 0x3fd17dbf09d40d25), + (0xb5f12f0e1a0ea25f, 0xb95b2c846748c809), + (0xbc61eb914d33c2b5, 0xbfc1404bf647c28f), + (0x3c098a23a393f866, 0x3f74f4df2769f830), + (0x3c24ae93dcb9bf99, 0x3f85c6285429b66d), + (0x3bdddb259c934d19, 0xbf3d68ab722881bd), + (0xbbd8cd731b94002b, 0xbf356acb6452d860), + (0x3b60d2c0a7987aa7, 0x3eec10b47cf7ef69), + (0xbb3cc8bfc9cf9d54, 0x3ed67eaae97bbc86), + (0x3b021d7ef8f06ed1, 0xbe8bb6530c63f2df), + (0xbaf7d003a6f8a38a, 0xbe6d87201e450edd), + (0xba5df682e9056c25, 0x3e20f47c83ec550b), + (0x3a784cc2fbcd5b3c, 0x3dfa98331f6ea797), + (0x3a3af02acc5d445a, 0xbdac70414a236ade), + (0xba1ac139214727ff, 0xbd817c057a5fc937), + (0x39abeb4e52ce6eb7, 0x3d316fea14d29892), + (0x39a6a5fe18553faf, 0x3d0189bd3eb9f3c6), + (0x3946aa341fe1b254, 0xbcb05af44bb23c5f), + (0x39010e85f5ece2bd, 0xbc7bbdb45d92e4fc), + (0xb89b4dc8ed25771b, 0x3c284360a40ed89d), + (0x38779d6e01f88769, 0x3bf1bfb967530933), + (0xb82198845d1335e3, 0xbb9d37a860a66a8e), + (0xb806974ac174343c, 0xbb62a0bbacab19c8), + (0x37906170939ea2eb, 0x3b0e5619160fd338), + ], + [ + (0xb60ab4d43f876701, 0xb969264876fdf3dc), + (0xbc5052a3a2541c57, 0xbfcff654544ebcd1), + (0xbc01b402d42eae53, 0x3f89223ff2c0785b), + (0xbc323a2755909c5f, 0x3fa4b0c5d5da6789), + (0x3bb3ea54acd19ff8, 0xbf5f91a9ee0d2897), + (0x3bfc41f7f5f8cde0, 0xbf5f51c2489b9e6f), + (0x3bad7af9dcc67129, 0x3f16b4c9ca0f770d), + (0xbbadd341169fa322, 0x3f063c5475439cb2), + (0x3b59f6ed48ce32ee, 0xbebe3725daf69867), + (0x3b21f00381a6cb34, 0xbea25c1238b32e59), + (0xbaebcfa91cc88fb7, 0x3e57486f6b9aa951), + (0x3adb600d25e5d0fc, 0x3e33e3bf248277ee), + (0xba5d774620c03673, 0xbde78a38a73e7c07), + (0x3a59e464c4822ecc, 0xbdbe844eb6b211d0), + (0x3a19b0c1a7646942, 0x3d70e24abb406b2c), + (0x39d0a87b33c9afed, 0x3d41797e5ead05d1), + (0x397bece1bd73373b, 0xbcf21fc0f119f3a6), + (0x39422a1731e7d087, 0xbcbf0c12e4c83411), + (0x390bbdff1dae57a0, 0x3c6e44232fae84a9), + (0x38d9844b6a7d039c, 0x3c360804e71ba342), + (0x38824f2c3cf7a869, 0xbbe43e13e137bab9), + (0xb8314bfff0c04984, 0xbba9903092d3c1c6), + (0xb7e5d3b1cb26c861, 0x3b56091b8d2a60e0), + (0x37988d9bfceddedd, 0x3b18e8b26041597f), + ], + [ + (0x3c50f8942d3f902b, 0xbfcddceb4ce1bf4a), + (0xb62c35de62add74d, 0x3982dff6c1e15731), + (0x3c433d5334b42b3d, 0x3fbda52116c0a640), + (0xbbe72468a28b4443, 0xbf6a9da4603b67ea), + (0xbc0c5e0831771de5, 0xbf8331e74ea59ab8), + (0xbbdac4579b1b1f5c, 0x3f33e5cb6eba6eaa), + (0x3bd0ad97399a9309, 0x3f33885fe9afa541), + (0xbb74d732b8ca0df8, 0xbee494c0f4b0680b), + (0x3b783e803ffeb597, 0xbed512b9d37762d7), + (0x3b1382127dd60cd6, 0x3e85a861082bfb7f), + (0xbb05de78d8bef340, 0x3e6c323ea0a042c3), + (0xbaba616d9a2d0acd, 0xbe1bcc962f7b91eb), + (0xba9907e5c13d4bf5, 0xbdf9bc94e2f29a4f), + (0xba4dd160d698c980, 0x3da82bc6fcfa8ee1), + (0xba0febc61d1c4bb8, 0x3d81141ce7b77ff8), + (0xb9b71ce5b90d51b7, 0xbd2e79ccb186eec5), + (0xb9729b55c285b0b8, 0xbd013e1fbe002f34), + (0x394b7b4b328dbd37, 0x3cad36d12c86586f), + (0x3913c4bb8b85fa48, 0x3c7b66070cb3ac2c), + (0x38cf4dafb0ab1446, 0xbc260cbaacd645d2), + (0xb892f6df683de3de, 0xbbf19605537cf4ab), + (0xb806112791bea534, 0x3b9aed6b864dcd18), + (0xb7dc24510173386c, 0x3b627eca9f946e65), + (0xb79c60e9a1146a47, 0xbb0bfef86c0d63d6), + ], + [ + (0x3601c162477c9abb, 0x396159aca5db6572), + (0x3c6c8c66d2e42063, 0x3fcbf3337873a7d8), + (0x3c25e81c4baa875d, 0xbf80c83a2d7add33), + (0x3c44192692d7c60a, 0xbfa251858011816b), + (0x3bd0475c48fd4015, 0x3f559eb160bf72d8), + (0x3b9e04d420af1ac6, 0x3f5c5bce33af2d77), + (0x3b7eb4916c85fb39, 0xbf10413e306e0039), + (0xbb9e3a42c4a3fc86, 0xbf04a6704d05ad0b), + (0xbb5a4f57a7a75039, 0x3eb6c43eedfed6c9), + (0x3b2d30c35715c7fa, 0x3ea16abd7815de74), + (0xbae381d774667710, 0xbe5257f16f5d4346), + (0xbad24f76ba3d2cac, 0xbe332db1b4b2ff8b), + (0xba886b6bef46e0df, 0x3de33acccf7bfdcb), + (0x3a40f79d1cb77e70, 0x3dbdc8f5682566ce), + (0xb9f02059cbf2dc1b, 0xbd6c6513386da08e), + (0xb9aee6c6f049704d, 0xbd413585a9b760a0), + (0x396399b887813c07, 0x3cef322ea2ca7028), + (0x3957137aaf1256dd, 0x3cbec749ba83ed87), + (0xb90e8d0898b37a61, 0xbc6a8aba908ced81), + (0xb8d53fcac77872af, 0xbc35f2abf33d3a06), + (0xb881d148fd35588c, 0x3be206e2b69fc921), + (0xb8490f14e83f785c, 0x3ba98eef781c5c36), + (0xb7ea20a48a9f15a7, 0xbb53df43cc1537c9), + (0x37b0c3f1e8cb94e8, 0xbb18d93abc409fbc), + ], + [ + (0xbc26397095487bbc, 0x3fca7f63fea81f26), + (0x35c7769fcbedbba7, 0xb94670973020cb53), + (0x3c4341d92ebaf230, 0xbfba60afb06640cf), + (0x3c0aa0cf7ee02729, 0x3f62c1e930935d3c), + (0x3c2253175b5c623d, 0x3f814506466d7f1f), + (0x3bcf594f6bbbe6b1, 0xbf2cca8c0c0eaa3f), + (0xbbc23306b101db0c, 0xbf31df821cc1377e), + (0xbb6f426f813ba1cf, 0x3edee8814ed0ac45), + (0x3b3530e090190f04, 0x3ed3a365a4199dd1), + (0xbb253c7c31f63d20, 0xbe80ed2f9c3e458e), + (0xbae6d6e3d35d7af7, 0xbe6ab3b37c5271b3), + (0xbab5876ea3da2c96, 0x3e1684d6e62b5c66), + (0xba61146a8712cc76, 0x3df8b105a5120ecf), + (0x3a497e08482e4f36, 0xbda42dc5991b9d46), + (0xba1c93b9ca69994f, 0xbd808d6405ffdf4d), + (0xb9bb9c06669b183b, 0x3d2a152033665a46), + (0x39a7ab21a3b60319, 0x3d00d7c118b17a82), + (0x39456872094da304, 0xbca984ffd3ac0d7d), + (0x3909c82687cc959e, 0xbc7aecb2b37b54c2), + (0xb8cf42b62c996f29, 0x3c2397005ee8dd8b), + (0xb886e35dc2991042, 0x3bf15c9c692b5bb4), + (0xb832ecad9f92b6aa, 0xbb98431fbb78646d), + (0x38062f0967c8bd95, 0xbb62529cf346132a), + (0x37a9a4acee74819c, 0x3b0964837b2ece97), + ], + [ + (0x360120a78f21538d, 0xb97c8b54640b722a), + (0x3c6e9557ccd17041, 0xbfc925c6fca08f55), + (0x3c091bef692396e7, 0x3f786dd32e059b0e), + (0x3c3dac1b118bbe70, 0x3fa09463bbd0367f), + (0x3be231ff192e138d, 0xbf4fda0298c8768b), + (0xbbf0185527f60d8b, 0xbf59f4be60758fb1), + (0xbbac474076e2749b, 0x3f0877991af9d1bb), + (0x3b85632e8431fcaa, 0x3f032cb00ee8c1f3), + (0x3b46a07ad1a2663e, 0xbeb19d8ce8c35f58), + (0x3b443944f6114d11, 0xbea06a042fbba455), + (0xbaeb45186aece340, 0x3e4d3a689e677731), + (0xbadf9a18bdd365cc, 0x3e325108c4ce2b64), + (0xba6505bb4a19817a, 0xbddf7b8e9ab5314c), + (0x3a5ad487a5bbd7ab, 0xbdbcc40d05652650), + (0xb9dcf99ac25c15c5, 0x3d67cd76e2d7d943), + (0xb9d024e4f22a308b, 0x3d40c58770232cfe), + (0x3952f8f057a0b1c2, 0xbceaafec4cc364ff), + (0x3933c2290c85768f, 0xbcbe36dd573e6a63), + (0xb8dfd609484ae481, 0x3c67199e5ff69f74), + (0x388f3830f4ff63d7, 0x3c35ab8bb9a71dac), + (0x387ca89ca7c948bf, 0xbbdfd6f8b70e778b), + (0xb844329e8362812f, 0xbba9598a6da0f2c3), + (0x37fd2c2ab7de98e2, 0x3b51c436362641e5), + (0x37b80a5354c74c14, 0x3b18a9fec4d5983d), + ], + [ + (0x3c2a5f1938003f60, 0xbfc810f50225b04b), + (0x35f6ee82870d84bf, 0xb97d05564a508c39), + (0x3c5462bc86c50e66, 0x3fb7fdf97ac36b1f), + (0x3beaefb0d3cf3530, 0xbf5c3c256a8caa05), + (0xbc191dbdbe49d9f5, 0xbf7f98feb7286b47), + (0xbbcd0c6b4ea34036, 0x3f25f6559e5686e2), + (0xbbd9de4a690cb448, 0x3f3080f57ac215af), + (0xbb69ed0a7174b68e, 0xbed80c51397e5eba), + (0x3ae06f2933360b4a, 0xbed256db543cd140), + (0x3b1af76fcd5528a0, 0x3e7af7598a219824), + (0x3b06515217062c3a, 0x3e69398226ca2305), + (0xba795db0bb871535, 0xbe1260985d92587d), + (0xba74a82a307b019b, 0xbdf792bb3eea6f67), + (0x3a3817c8f7ec2b4c, 0x3da0d862695e1ab2), + (0xba1b8749aa4dca22, 0x3d7fe52adc2ba19c), + (0x39cda3a73a18530c, 0xbd263801377428c8), + (0xb997a6607141db31, 0xbd005a1befd1620e), + (0x394738fbaf9e72c3, 0x3ca620504263602e), + (0x3919acd0b705176b, 0x3c7a4e14e3f85acf), + (0x38bbce9a9cbe0c23, 0xbc213ef23a1a245a), + (0x389387792bae4d33, 0xbbf10cae24ff432c), + (0x383135b979266427, 0x3b95a41b5b0291e9), + (0x380630df36241504, 0x3b62113e229c18af), + (0x3779c024d092ed81, 0xbb06d663d6acddea), + ], + [ + (0xb5e79c1121733c06, 0xb97dd765a46686aa), + (0x3c62da0057f84d3f, 0x3fc70c511227d5aa), + (0xbbfb574e506cd46d, 0xbf72ccb0e97558da), + (0x3c2e61277dedefa5, 0xbf9e7dc08e70e99a), + (0x3ba77952d9976f3f, 0x3f48acdc5b058c0e), + (0xbbf340f4df902276, 0x3f580503724ad30a), + (0xbba115f68568f545, 0xbf032ee4ca1fcafb), + (0x3ba6a66dcfa3c51f, 0xbf01e5d2836c8d99), + (0xbb2b2738baeaafd8, 0x3eac129f077bb163), + (0x3b33825b34f3c4e4, 0x3e9ef161591181a2), + (0x3ae4e499d619d66a, 0xbe47b9bb07f19f82), + (0x3ac1a055b5da7ef9, 0xbe316f3937595d96), + (0xba7ad6f9f1cbf4a9, 0x3dda0bc8665b6876), + (0xba4fc8c4f001bcc9, 0x3dbba135f99a9e23), + (0xba00713e44285b86, 0xbd640d543d2cb545), + (0xb9d8806fb4e057c8, 0xbd403d0592186aa2), + (0x3976ebbceb30453a, 0x3ce6db5e22c00286), + (0xb95cfcc8d365b2a3, 0x3cbd745a1f9b2cc0), + (0xb8e84bda052a24a4, 0xbc64141c2da5de65), + (0x38cd92252322f7fa, 0xbc353f4e8c94bba5), + (0xb8715b904e388e03, 0x3bdc0988ad3d45d6), + (0xb7f1437e75284c5c, 0x3ba8f98a7bde325e), + (0xb7e5101387db5e8b, 0xbb4fa52f2ce39750), + (0x37b59c36f27d26bd, 0xbb1859ec268d8e36), + ], + [ + (0xbc6b166d180d579d, 0x3fc633e7f7f05301), + (0x35ffee1a88c4c7db, 0x39597a12d5b67dc0), + (0xbc100659a075cf2f, 0xbfb6273784c1c06e), + (0x3bfcb74bd087b3a0, 0x3f563ae94ade18d4), + (0x3c02a45d712493c7, 0x3f7d4666536c88b9), + (0x3b825e9ac0d7a01e, 0xbf216d528345ca11), + (0x3bbb9405cb89e345, 0xbf2ec0dcdbb7c5fe), + (0xbb7cb6decc20866e, 0x3ed34e966b0b09f8), + (0xbb7a79f0d76f0cbb, 0x3ed135c64dc2d8d0), + (0x3b01209dcbada35f, 0xbe75f7bc78b5fc2b), + (0xbaf600f169603982, 0xbe67dc35b0764096), + (0xba9e587e011af4be, 0x3e0e6d697361ea54), + (0x3a9d43cb8e00cb1a, 0x3df679e3704987b1), + (0xba3d2f784a54c5d4, 0xbd9c595f278a4dc9), + (0x3a0e613d8bf8177d, 0xbd7ea36aef56e594), + (0x39bad5b0fa90b31d, 0x3d22fd66b4e699f0), + (0xb983e4c916a5d37c, 0x3cffa04c9f95e420), + (0xb929ce3db1f0e449, 0xbca32f47f100cd0a), + (0x38d1dc8a519c68bb, 0xbc7996582817ca81), + (0x38bd0c28a3f651c5, 0x3c1e4c27a12867d7), + (0x3893ddf51221f64b, 0x3bf0aafd1db63771), + (0x383228e1d6fab232, 0xbb933b296a9fe2c2), + (0xb8026ac12c9d03cc, 0xbb61bce573aebd8d), + (0x37a6fcc6415460a7, 0x3b0476ec3eb1a5b8), + ], + [ + (0xb605d92a84ac636d, 0x396c0a10d4b8d049), + (0x3c6a47ab4241a9f3, 0xbfc5664e13b70622), + (0x3c04d78c254f378c, 0x3f6e16555e108dc6), + (0x3c1fe75afd6ceb7e, 0x3f9c5e1ad9fb2f40), + (0x3be099fe50ede362, 0xbf43d369f958e56a), + (0xbbf3ed70de3ce58d, 0xbf566f4ec27a96e9), + (0xbb9b30f0921d946f, 0x3eff0de0532652d5), + (0xbb747f8e74699e57, 0x3f00cf264341409e), + (0x3b4f302f945bfb6b, 0xbea6f46d51e5766f), + (0xbb37090d5299f2bd, 0xbe9d407f7c248d45), + (0xbaeee2a1b6297a03, 0x3e43a33cd9df6696), + (0x3ad36edf4ce5ba78, 0x3e309901b0a816e5), + (0xba69797c9a665948, 0xbdd5d856a58443f0), + (0x3a581a0de548434c, 0xbdba7cbcd8fc075f), + (0x39f4161aad5502dc, 0x3d610b62c2fd4020), + (0x39b2429685721bb6, 0x3d3f56a09da1af17), + (0xb986edb5e42e4df0, 0xbce3ae6849a19196), + (0xb956860a8cce360d, 0xbcbc977524bd849e), + (0x3904f25392c2b4b0, 0x3c617fc9c0a81a86), + (0xb8b42258c6440740, 0x3c34bbe439c863fb), + (0x385dba6e1d13451b, 0xbbd8b5326e15f6b7), + (0xb84cacd442a85cbe, 0xbba87bd53addeb1f), + (0xb7ed606f4edc8467, 0x3b4c2aa54d8d8127), + (0xb788c3a332c0e10d, 0x3b17efec97ba8f61), + ], + [ + (0xbc4f6f339127993c, 0xbfc4b71d4ca2cc69), + (0x35ca4f8d42ff3858, 0x3971bd20421445e5), + (0x3c5422c1a1ae8e1c, 0x3fb4ae245697fba6), + (0xbbf4ff572c18ea0c, 0xbf5215e4e1a5f1d6), + (0xbbf259ec9aa6f76a, 0xbf7b633ed6d9cf61), + (0x3bab33aa4933effd, 0x3f1c7f17b4b7dbbd), + (0xbb79333bf7f0a288, 0x3f2ce01b8b6aa34c), + (0x3b5f4e5959a7242e, 0xbecfced71b11e35b), + (0x3b57f36535a55c97, 0xbed03c9d5823261d), + (0xbb15ca3a5fd6e4c3, 0x3e724508091063b2), + (0x3b0278797fb483cd, 0x3e66a2d20111e303), + (0x3aa462d914cbe692, 0xbe0995a18f8e6888), + (0xba92d2f68fe7bbf3, 0xbdf572d1a074f644), + (0xba3d2febd6b25c97, 0x3d981df03c191241), + (0xba1df51a16a51cab, 0x3d7d6895e48f3e4a), + (0x3979fc3e189a5876, 0xbd205887f0b4463d), + (0xb99ef66a10579222, 0xbcfe86703dca7086), + (0xb93a92c2e3662797, 0x3ca0b3c70d522804), + (0xb91294d0f373d163, 0x3c78d28b840bbf9e), + (0xb8a3ac6e917d987d, 0xbc1aa928bdc7c69b), + (0xb889057510b0376b, 0xbbf03e6bbda694dd), + (0xb83da10a22fdbcd6, 0x3b9117421c5b8302), + (0xb804a226000323af, 0x3b615b28f6d151e7), + (0x378448f5a65efa22, 0xbb02540c2640944f), + ], + [ + (0x35f8435be9512d0c, 0x39596a809853afc4), + (0x3c6316f8ffd294bc, 0x3fc40f90793605bb), + (0xbbd411ad350e3915, 0xbf68c833077fbeae), + (0x3c051eb6f09da299, 0xbf9aa0ce0421d1a8), + (0xbbec0fe78ad65dee, 0x3f405fa598ef5d1d), + (0x3bff2085596f93c4, 0x3f551d30d78ab526), + (0x3b92b31b50a0ff60, 0xbef9c5807675c5f6), + (0xbb7cb5b05cc545a3, 0xbeffc1bbf57e3ae2), + (0x3b3cc24f7215eccc, 0x3ea32dfea2518ce6), + (0x3b18c92945575b15, 0x3e9bc212085dcbc6), + (0xbaecddf3334d6159, 0xbe408b946d64c5c2), + (0x3ac0b1a7f29c826b, 0xbe2fa8f9d8da736a), + (0xba756320d1b782d7, 0x3dd293fe14af1d0b), + (0xba5e3bcddd76a2bf, 0x3db96544cb75a592), + (0x39f0a916b1e33716, 0xbd5d4750748e1ec5), + (0x3992aa2022ba01f9, 0xbd3e341812329adf), + (0x396e5a994597409d, 0x3ce112aa494174e0), + (0x395a9a5bb21cd5ce, 0x3cbbb1656dd4f875), + (0x38fd92cb597fcae9, 0xbc5ea7b95ef8e08b), + (0x38c2aa6384ba6bbe, 0xbc342cad8878d4a5), + (0xb868a671070d345c, 0x3bd5d76ac6e68151), + (0xb82311f5dacdef0c, 0x3ba7ec1ff36b8002), + (0xb7db96a9ba77f2bd, 0xbb491cad22e089cd), + (0xb7b0a5b54e7f6cac, 0xbb177445429e42ae), + ], + [ + (0x3c4f5ffd019535e1, 0x3fc37dfa8f5a550a), + (0xb5aaaff7214acba6, 0xb93cb5c70d300ac5), + (0xbc5c4cd2161ee66e, 0xbfb3775c1a04f09c), + (0x3bd3d562913491bc, 0x3f4e2b4810a46c60), + (0xbc1b976f331a69fb, 0x3f79d151a72b83a8), + (0x3bbcef8b51459dfe, 0xbf17d8e5a090e4e6), + (0xbbcb7ef1646f65dc, 0xbf2b49a6427386a0), + (0x3b592486856820bb, 0x3ecac10957ddd2eb), + (0x3b424317f186fd5b, 0x3ececa620745d3d3), + (0xbaf34eef3c6c9553, 0xbe6eefc7e795dcdd), + (0x3ae4b6734611daf2, 0xbe658c5d2a0da41d), + (0x3aa97ce5a3d8c757, 0x3e05d4721f44a8f9), + (0xba9b1942d77688ab, 0x3df481ce2314af57), + (0x3a2ac654ac1c449a, 0xbd94c0d3279e9252), + (0xba1f470c6e36c705, 0xbd7c3ea70752fc73), + (0xb97829121cc317d9, 0x3d1c61d5b166a9e5), + (0xb989ebd713c25b94, 0x3cfd72bf188712ae), + (0xb9078152b026b94d, 0xbc9d427a9891c892), + (0xb904e8f099d7cfab, 0xbc780c9634dc0029), + (0x38b5c69bf0be9c48, 0x3c178e382c9b5ff2), + (0x38536f9bd3face06, 0x3bef99f1b78427a0), + (0xb828de3e89d5fd1e, 0xbb8e7352b4b18839), + (0xb805ad010982fbed, 0xbb60f1a2b1d2a86e), + (0x37abf1ea36b06bd9, 0x3b00708aca8b132c), + ], + [ + (0xb5c06f78c8d4a275, 0xb93d524b57168b9f), + (0x3c689d1f48185c7e, 0xbfc2f2072e638cf4), + (0x3c0f48257333a5e0, 0x3f64df208bbd44f1), + (0xbc282c4cf012e4f5, 0x3f992bb5e1e159fc), + (0x3bb5967313f39524, 0xbf3ba181c06897cd), + (0xbbea6566cfb71c2e, 0xbf53fe9d5baa4a3d), + (0xbb98b4ff32e89d05, 0x3ef5d17602b01cac), + (0xbb84f1d77f1fffd7, 0x3efe26d3747fe829), + (0xbb47896f2e82c323, 0xbea0509768ab6ecb), + (0xbb30ede6356a7015, 0xbe9a70f232d9d06c), + (0x3ade8fe4e5a1ed7e, 0x3e3c509252de33f9), + (0x3ac6ae9c749edc67, 0x3e2e454fee07116e), + (0x3a73b1f5bbe63372, 0xbdd0015b062ba122), + (0xba44c8407e1ecc95, 0xbdb860e95adf8412), + (0x39fddd4f18607329, 0x3d59691e90f7ccfc), + (0x39d00120e60006cf, 0x3d3d1ce7997b42b4), + (0x39682a77f2b9ac62, 0xbcdddcd1c52fea1b), + (0xb95c20e8a1ea2f57, 0xbcbacd10a03d8921), + (0xb8f1731302036655, 0x3c5b043a4e72efe2), + (0xb8d6d22b4e2f1fae, 0x3c3399ba323db8d6), + (0x385b209322c8d73d, 0xbbd364e661355e9a), + (0x3838be7c1f6126ff, 0xbba75381cf058174), + (0x37d1ce55ad6a8310, 0x3b46755328d7d302), + (0xb7b75f604bab0893, 0x3b16ee50ed715cef), + ], + [ + (0xbc6b9fbd89653a0a, 0xbfc2768d29c69936), + (0x35ca97e1f25db68b, 0xb93ffabfa86ef843), + (0xbc592c5350d4d817, 0x3fb271811730b0ef), + (0xbbcd42067c35395a, 0xbf49a8df96a1225e), + (0xbbde8196594d5f87, 0xbf787c81cf1c6fc4), + (0x3ba098686a079be4, 0x3f14549cdbb77978), + (0xbbcc0c93813e02ce, 0x3f29ed2568116e19), + (0xbb638a1fa72a2206, 0xbec6e4136f033ace), + (0xbb692b62efc42c9a, 0xbecd53330316cde7), + (0x3af835560f2b31cd, 0x3e6a983b5782dfca), + (0x3b0d287b84d78d98, 0x3e64952ba7c5a1dc), + (0xba72905636bd36a9, 0xbe02df3ad6f82e0d), + (0x3a99c062ae844d27, 0xbdf3a70f9a89d2c0), + (0x3a3c9ffd5cdbf957, 0x3d920e086c17f618), + (0x3a1e25413f7cf79b, 0x3d7b29a554c10cda), + (0x39b937b07d944fb1, 0xbd18dbe08f4b3b70), + (0x399966ea8cf6d238, 0xbcfc6bd9fc31d25f), + (0xb9310d7ab87b2019, 0x3c99ce5a745e4984), + (0xb918ade94c5553fb, 0x3c774addf0c26059), + (0x38be87d79b895c6e, 0xbc14eb89eaaa0820), + (0x388e01622132e11d, 0xbbeeb605f9932592), + (0x37f1d8f9c78e8f53, 0x3b8b3a602349f9f9), + (0x37fda89d6c3f2718, 0x3b6084d788afe5ac), + (0x379093629c8ee8ea, 0xbafd92b61b88c69e), + ], + [ + (0xb61e3a4d721e8324, 0xb970e12b7d27cf07), + (0x3c51f9b16832f365, 0x3fc1ff5eec6a01cd), + (0xbc0f89ce0d1cad55, 0xbf61e438b722c3b5), + (0x3c39a4b7b3ed5aa3, 0xbf97ed5fffc1c774), + (0xbbdc35d9a8eaece6, 0x3f37b7997babd9ca), + (0xbbe39da40664c597, 0x3f53081def9612c5), + (0x3b8551b9d43f8119, 0xbef2c5f5edafc4e9), + (0xbb9dbae69d6d1983, 0xbefcc11a59e13739), + (0x3b35152e3ec9bcce, 0x3e9c2c3a1b8014a3), + (0xbb333a08049d2a47, 0x3e9946d1dab7bd01), + (0x3ad9a43f93c7a3c8, 0xbe388db61946be64), + (0x3ac51a4e1f57e228, 0xbe2d04d33be580e8), + (0xba5f39a3631ac3ea, 0x3dcbe64386d2c5c9), + (0xba50e72fbf713685, 0x3db77142e0e4497d), + (0x39f05d87c3131a89, 0xbd56458476678b0a), + (0x39dcadde2840dbd3, 0xbd3c15e96b25b19b), + (0xb970bb70de53f974, 0x3cda545e6eacddb5), + (0x39573a21f1dd7482, 0x3cb9f0a9b7519cb4), + (0xb8f26c0a88ddf73c, 0xbc57f751c3434bc5), + (0x38dba5906a1609ba, 0xbc33083bfa2b9853), + (0xb876257782c7fb32, 0x3bd14f52f8c40156), + (0xb8455e6398eb5536, 0x3ba6b866ba0cd5f9), + (0xb7dd533054211520, 0xbb442a164ec53a73), + (0xb7b5895e0b2acd11, 0xbb1663bd8ed78f9c), + ], + [ + (0x3c54fa3fb220c497, 0x3fc194eba75b32f9), + (0x36084c365974fe27, 0xb97351f4ef13fe26), + (0x3c59f5fdd12caab1, 0xbfb190f7dc27362b), + (0xbbd96244746b5f38, 0x3f462bb47a5c5f7f), + (0x3c106edbe0b8c444, 0x3f7756ef20f5d2e2), + (0x3bb1231bc38d74fa, 0xbf1198b0ba97ecfb), + (0xbbafcaf470009ca5, 0xbf28be8cf9358d55), + (0x3b341ae8492fe909, 0x3ec3dd6f7c8cc3c0), + (0xbb227b6134d4cb1b, 0x3ecc09c80ee7f9af), + (0xbb0404bf1dcee0f4, 0xbe6728e46a451e32), + (0xbb0524de73bc4a47, 0xbe63b91113508622), + (0xba958725ca8bba0a, 0x3e0080fddad62bf8), + (0xba979be80a70704c, 0x3df2e111e88dae1d), + (0x3a16d9f11e8a571a, 0xbd8fbae88bdab281), + (0x3a026df37d7f2f86, 0xbd7a2a4fbea86012), + (0x39b683e401b5c962, 0x3d15f540e97728a3), + (0xb95202b2fa6547b4, 0x3cfb74c0b254e833), + (0xb938463548f90bb3, 0xbc96eb75a8c251ef), + (0x391ab9d89901dd33, 0xbc76910c0073cf6f), + (0x38b57304713e6ec7, 0x3c12af37349ec30d), + (0x388e4a0ca7b6a403, 0x3bedd6cb83761ce6), + (0xb82fbe9670a0583a, 0xbb88745a179736e3), + (0x37f9ae92b9c8d8b8, 0xbb60180931dceaf3), + (0xb78cba499e17a878, 0x3afab192c9241f99), + ], + [ + (0x35cbb600d4239a22, 0x39251b64cfa537e4), + (0x3c6e71c482be67bd, 0xbfc12dd57bf18ada), + (0xbbe9a8a827c4bbb7, 0x3f5f1e1e7f393e83), + (0x3c3286f932bea35e, 0x3f96d9afe88301fa), + (0xbbd360330de30bf2, 0xbf34a538a482979b), + (0x3bef838ddd50c780, 0xbf52316250b4ae37), + (0xbb94c13fc989fce7, 0x3ef05f11577b4627), + (0x3b6771efd22cab1c, 0x3efb86bad42fc220), + (0x3b1a6ca937a8bc13, 0xbe98a1b3a9e92749), + (0x3b32d767937947d7, 0xbe983dcaf3f8fcc5), + (0x3aba8d8d67ac9dda, 0x3e3589a7ca5fdcf1), + (0x3ac9ad46d29f3be0, 0x3e2be3ee3298bb99), + (0xba6e973d129d8f1f, 0xbdc8913f1d0ff123), + (0x3a203a3c6881bd79, 0xbdb695c386660814), + (0x39fb47463477c5c8, 0x3d53b25d3647586b), + (0xb98bb89b4c085acf, 0x3d3b20c42e642e99), + (0x397afedf65fe5bfe, 0xbcd76505329d2147), + (0x3958669626edb388, 0xbcb91f514b70dc66), + (0xb8ecf324e9269490, 0x3c55661a888ce787), + (0xb8b1401ccd948cf2, 0x3c327b48d4454d52), + (0xb8698f6cf1c5e01c, 0xbbcf10cd4224310e), + (0x384b17d2f0b22cb7, 0xbba61f092d4fb132), + (0xb7db3b4d370a111b, 0x3b422f16a2b51a21), + (0x37ace9fba95b7f40, 0x3b15d89abfbbc58c), + ], + [ + (0xbc27736b1f56d6fe, 0xbfc0d0d36473e98c), + (0xb5eeec74a121164b, 0xb94d417ee84a02e1), + (0xbc517d3bbb8e77ff, 0x3fb0cda9974abe2b), + (0xbbe2a43b589bb30c, 0xbf4367f38f201c25), + (0xbc17d132300354c7, 0xbf7656b75e3c242e), + (0x3b94b9f5aa61b16a, 0x3f0ed82abf7489f1), + (0xbbcb0bedfa6ed1b8, 0x3f27b4e5b83eeb36), + (0x3b0620c0f4833a16, 0xbec171fd0fb670e7), + (0xbb638b5f7ce177c8, 0xbecae62b4ad017fb), + (0x3b0b87c8b1ba0970, 0x3e64648495a7b49e), + (0x3b05b3200be63707, 0x3e62f42a577135ad), + (0xba91dadfc29e6554, 0xbdfd286e7fa32656), + (0x3a9d8beeb2cb7298, 0xbdf22dbcbf76a1c5), + (0x3a2a43a2ea6cef43, 0x3d8c222accc0d332), + (0xba0327331125a6e3, 0x3d793fc7f6c8caef), + (0xb9acf6791f2a444c, 0xbd138c7e1f6709fa), + (0x399fac78a0046126, 0xbcfa8e4efc5ad38f), + (0x3933d41876c7d322, 0x3c947e808f83bea6), + (0xb91b783f58eeeb68, 0x3c75e0f0594a5008), + (0xb86c4cbf1e35e546, 0xbc10c8678c595f1c), + (0xb87ae60cd98137bf, 0xbbecffab1af4612b), + (0x382a6f17570f961d, 0x3b86111d5963e0eb), + (0x37f00fe3e9f49b7c, 0x3b5f5ac4d0ed3683), + (0x377ece1c4a712e4e, 0xbaf8306e05270fd5), + ], + [ + (0xb60d733c7a7e52a7, 0x3970250757e24008), + (0x3c61a13e2fee5687, 0x3fc076826cc2c191), + (0xbbcb789ffb6667b2, 0xbf5b62885e0070c6), + (0x3c35dbe9d7210bbe, 0xbf95e7f53001e4b1), + (0xbbddb8eb1d2bf603, 0x3f322ebeb8dc2202), + (0xbbf72618e8704270, 0x3f517444a7a04cd0), + (0x3b7b01e86b4a3da0, 0xbeece06f1f1fcd7e), + (0x3b8016817bdb5904, 0xbefa7006e6ad9cfe), + (0x3b13ab2699f50e0a, 0x3e95c42f02cf15ca), + (0x3b08b6ecfe623226, 0x3e9750ca5e1366b4), + (0xbabee952793294d7, 0xbe3314982df7eaa2), + (0x3abefa05a9bee7a7, 0xbe2aded75306b3b3), + (0x3a67ece2ba1179c1, 0x3dc5d47847d8ebeb), + (0xba5c6d6993547389, 0x3db5ccf44d287a22), + (0x39e36e4501d8e34a, 0xbd518fce3e03f8ff), + (0xb9a320cde8d9c336, 0xbd3a3d6bcad0c437), + (0xb976652eddf4a16e, 0x3cd4efbd765ccd7d), + (0x392c39469b09709e, 0x3cb85a4b163d5fb1), + (0xb8fcb83bb2002a51, 0xbc5339ddcc1bcec2), + (0xb8d45b1a219ef1df, 0xbc31f48b401dcae3), + (0xb86e5c376fb9eb81, 0x3bcc067f698492f8), + (0x384a2903db3f0c8f, 0x3ba58a055bf542b9), + (0xb7e2ee806b9979fc, 0xbb4078cceb371d66), + (0xb7bbbf36698a9adf, 0xbb154fa9d8bb2e05), + ], + [ + (0x3c61a6e02553980e, 0x3fc02455675ab6d2), + (0xb5c5f31d846909a7, 0x3920fd28a7ab34ea), + (0xbc5a58b3083e7da5, 0xbfb021c155a720df), + (0xbbea19c1039cb49f, 0x3f412be56fc1449a), + (0x3c01bad3e8f49c57, 0x3f75749d556ad61c), + (0xbb75621379d06ca1, 0xbf0b51f1f9bea93e), + (0x3bc81ccb322d1126, 0xbf26c96a07e236bd), + (0xbb21804e8cca606d, 0x3ebef3a7abd5ac6b), + (0xbb6f6eedeef435f9, 0x3ec9e207c257433a), + (0xbaf0b5ea62a8de24, 0xbe6220b96eef8058), + (0xbad2fa9552352869, 0xbe624317cb296737), + (0xba7c0f987894ba0a, 0x3df9fc2f2cd3917f), + (0xba7936059699e1c2, 0x3df18ae8347e8254), + (0x3a1573486603ca10, 0xbd892540423f2e30), + (0xba1e19de8fd09a84, 0xbd78687dcdc2db72), + (0xb97684a35e3ea9dc, 0x3d1187909104433c), + (0x39630ebfb454443d, 0x3cf9b8362860195d), + (0x38c1923b5504cc9f, 0xbc92711ece62b404), + (0xb903c12865011bca, 0xbc753b340e1ec1f7), + (0xb8a22b4edd218aaf, 0x3c0e50ed1c32be11), + (0x387ce89517a6eb64, 0x3bec3274fc0c19bf), + (0x382cd7af1eec7b55, 0xbb8401a453695584), + (0xb7f9f56cebafb7ea, 0xbb5e8c7520273be2), + (0xb794336346140121, 0x3af602279247901e), + ], + [ + (0x35eae2ce139b755d, 0x396742f004f756a7), + (0x3c5d7cc41717159f, 0xbfbfa8b41711c83a), + (0x3bf6219a48a24bc6, 0x3f5857d3969997d1), + (0xbc395ccf34fc8573, 0x3f9511c6dadaaa12), + (0x3bd13cc55aed0677, 0xbf302c289dbdbd4f), + (0xbbde8aacf938011b, 0xbf50cc2238d229f9), + (0x3b831f1c6dd9cc15, 0x3ee9b64d5c63668f), + (0xbb967f7ad298da49, 0x3ef976fb023f0f79), + (0xbb26429ad31066a5, 0xbe93693ba0b5ba70), + (0xbb30bc57284d2f2f, 0xbe967b952987350c), + (0x3adfd4fe0a523682, 0x3e310cb79a2addab), + (0x3abbd4987c3e4ca2, 0x3e29f2079f8e397f), + (0xba6750593e1e01e8, 0xbdc38d957eaa53a8), + (0x3a5878f2c117ca3c, 0xbdb51511e93ba74c), + (0x39d6e8ba61764a78, 0x3d4f8bb4d9d2e233), + (0x39d8bdf5fdad66d3, 0x3d396afe82155942), + (0x39700aa17bd0529e, 0xbcd2dc3c5a2d6062), + (0x39264d3a8a0c9e0a, 0xbcb7a1c8dec30b78), + (0xb8fa02e0c4da574e, 0x3c51600c1fbbd4ea), + (0xb8dd822a2730dcdd, 0x3c3174c6425ae3bb), + (0x38597c34fcb10a17, 0xbbc969aad5156298), + (0xb84606c1cf335ef0, 0xbba4fad8aa607bb2), + (0xb78af3fa0ad5b88d, 0x3b3df9a69e01b8c9), + (0x37a075924edc374d, 0x3b14caa46ecb07e4), + ], + [ + (0x3c50e4250a158a23, 0xbfbf161d0c28b48c), + (0x3611a74b58e68914, 0x3973ee78b8c079ca), + (0x3c421e360c4c6fb3, 0x3faf11d837aa6f64), + (0x3bd18f48c3538dba, 0xbf3eab76da4d07a0), + (0x3c1ebe3b989625cd, 0xbf74ab329f067aea), + (0xbb5e80c38d8ec580, 0x3f086ada57bc1c51), + (0x3bc03960e72796ae, 0x3f25f6e78f11ab9a), + (0x3b5e771583ebe81e, 0xbebbb271f54c8965), + (0x3b5cfd56b457272d, 0xbec8f85328c26cb7), + (0x3b05a90e2d074d12, 0x3e603f82aebdeac1), + (0x3b0054f935b9aa08, 0x3e61a3010279a195), + (0x3a5b79af494102ab, 0xbdf75660809cdedf), + (0x3a8b7a2894daf42e, 0xbdf0f6931774a05d), + (0x3a13e36d17ff7a01, 0x3d86a2e612670759), + (0x3a1478f3b027f12a, 0x3d77a2a8e0311432), + (0x39a89f64fe6a7cac, 0xbd0fa4c8e3cec9ee), + (0x399791d5ae2f24c9, 0xbcf8f1926f3bf5c9), + (0xb90779dd9b4f4523, 0x3c90b165b307c656), + (0x38c874530c0e61a2, 0x3c749fd30e4702fb), + (0xb8a3d520095f9475, 0xbc0b864b8eb17f2d), + (0xb887f6b35d01d945, 0xbbeb6fef448f9ec9), + (0xb82c404eab8fd764, 0x3b8238c2939c0306), + (0xb7cf45b246f68cc2, 0x3b5dc6a5afbef1d7), + (0x37879b3e205ae80b, 0xbaf41b15e5934cd1), + ], + [ + (0x35e2402b29b452e6, 0xb95669e940f0e62d), + (0x3c0020b4016594be, 0x3fbe8727daa3daed), + (0xbbea4d873618607e, 0xbf55d353e2854a37), + (0x3c3361836c5324f0, 0xbf94524d4813cc25), + (0xbbb70735fac009ce, 0x3f2d037574e28370), + (0x3bf7f1d7c0f3582e, 0x3f50356bb747a763), + (0x3b73015c49ea72dd, 0xbee7156bfccef376), + (0xbb99523f50a17202, 0xbef896d7dc819faf), + (0x3b307ed5444cfe33, 0x3e9172c6dadf4149), + (0xbb334d67f3854d6b, 0x3e95baae8efc2e31), + (0x3abbd2db893ce2b0, 0xbe2eb347eb4d6941), + (0x3acc3ffb82d08806, 0xbe291a60a72a20e0), + (0x3a62e32cc76420f9, 0x3dc1a345a9a6a5f2), + (0xba511d514fc93073, 0x3db46c56b01906be), + (0x39eb5948642788cd, 0xbd4c84bb3767683a), + (0xb9c6dbefdede6e96, 0xbd38a83e6e4c14a6), + (0xb960551193c229eb, 0x3cd11796d0057ab1), + (0xb952ad5a14be2d5e, 0x3cb6f5675ceddd1b), + (0xb8d70078fb2fe673, 0xbc4f936ccfdc26d8), + (0xb8bf16cd40d79f50, 0xbc30fc2f7536e2fb), + (0xb82fad0a6a231690, 0x3bc727e83d15ee4b), + (0x3807b3ed34c03c50, 0x3ba472426379c0dd), + (0xb7d0fc2af29aaf50, 0xbb3b644d13049235), + (0xb7a0b4b41cc19800, 0xbb144a95537eaf6c), + ], + [ + (0xbc5b4c98f0d3c4c3, 0x3fbe0357c158b119), + (0xb60d0c75a77e2033, 0xb967816058366b9c), + (0xbc410072ccb8850d, 0xbfadffc2fc1a91f5), + (0x3bd769e0c0dcd2d3, 0x3f3b9b82ae07da44), + (0xbc02d8dbfa1e178d, 0x3f73f64e05320ac6), + (0x3bafe44f6d4ea208, 0xbf05fe4b66cf19d9), + (0xbbc540e87c50de38, 0xbf2539518e1b00f5), + (0xbb397c57bc8091bf, 0x3eb8f8d01c487905), + (0xbb5e179d1aaec556, 0x3ec825045b97e2dc), + (0xbad3613aacf5b7ad, 0xbe5d565f3bb61dea), + (0x3af7612fa1765a21, 0xbe611186586f4f74), + (0xba999c78eb7ba93a, 0x3df51a669158191c), + (0x3a8fdeaddc76e697, 0x3df06ef52f6715a9), + (0xb9f43ddc362f0509, 0xbd848215e95caabe), + (0xb9e3ce8533da1d00, 0xbd76ec8422019334), + (0xb977fdbacbb88faa, 0x3d0cbaf5fc1449cc), + (0xb994adec13653643, 0x3cf8393ffa3d864a), + (0xb920340fd1f6eaf4, 0xbc8e6232fcacc946), + (0xb91a15a57d08156b, 0xbc740e69a1eec644), + (0xb882efe890d1719f, 0x3c091cd31485cd1d), + (0xb87204ec8daa0e68, 0x3beab83a7b21fd23), + (0x37ee5c4a3769c7c2, 0xbb80ab43d4957dfa), + (0x37d0433b7ef63b8f, 0xbb5d0a0f23f73309), + (0xb76e179e9a438fab, 0x3af2707876868cba), + ], + [ + (0x3610ef51183cb002, 0x3972fe6576610a9d), + (0xbc5cb1f28997ca3a, 0xbfbd8293aa55d18f), + (0xbbd0e0b711c1383a, 0x3f53b6beb83f2596), + (0x3c36c091c5e2bd45, 0x3f93a5ccbc12a67b), + (0x3bc80bb5067d449d, 0xbf2a3765d26aa42b), + (0x3bc464654b3effa9, 0xbf4f5ab33748c215), + (0xbb86c3ad3a1d34af, 0x3ee4df6f1c257a5c), + (0xbb9372510da194bb, 0x3ef7cbd49c315be0), + (0x3b1dfd4ff2a51cd9, 0xbe8f96098cf07175), + (0x3b0aec441511ad05, 0xbe950b37dd43531f), + (0x3aa7073eee76aad1, 0x3e2bd2e6405c605d), + (0xbaba14df19ca3ca5, 0x3e285530df0d4b70), + (0xba5940f4b5dbe91a, 0xbdc0029e21930f20), + (0x3a40c5ac889e279f, 0xbdb3d11aeba731a1), + (0x39b3628671f6f9fe, 0x3d49ef077e064e5f), + (0x39cb6ce5407798b1, 0x3d37f3d211d80a08), + (0xb947488a9811c854, 0xbccf2617ceaee07b), + (0x39261e70e580a2ad, 0xbcb654785f893e5c), + (0xb8d177e15b92fb85, 0x3c4cd5d45e8ed84c), + (0x38da56fe6bb5e9e1, 0x3c308aa980f020fb), + (0x38655215f7c6e0cd, 0xbbc53213f4bfc10c), + (0x3846a2e45c9c7024, 0xbba3f087bcfff455), + (0xb7bf1d6ed9e53a8a, 0x3b3922460f936d70), + (0x37bd5d3f90200af4, 0x3b13cfffa188113e), + ], + [ + (0xbc57ac02118ce034, 0xbfbd0b36e5737458), + (0x35e5dbf97ada5b8e, 0x39455ca750ec6752), + (0xbc494ec699987d83, 0x3fad082ce3c6b59b), + (0x3bdbdb6b7d6ce172, 0xbf3905d00c5e6800), + (0xbc14d8fddd6666b4, 0xbf7352b073fdac7b), + (0x3ba8a390ec67540a, 0x3f03f1ccfec2fc88), + (0xbb8f74934a18e861, 0x3f248d74583834bc), + (0x3b536c48c738b669, 0xbeb6a9ef0d896bae), + (0xbb686cf2b10eb75c, 0xbec764d9798d6a80), + (0xbaf45b48c636943c, 0x3e5aa785d6736f5c), + (0x3b032808a4ecc777, 0x3e608cae36118cdb), + (0x3a954183d5d06233, 0xbdf332ddfb39cd01), + (0xba85b57db0ba4e83, 0xbdefe502ff1a8f08), + (0x3a0e117f9b9a2106, 0x3d82afc83348eef3), + (0x3a1f9e55699c4976, 0x3d764468c0a30d64), + (0xb9800b377972327f, 0xbd0a399e849ce64d), + (0xb987e7e0201e1a08, 0xbcf78e09771972ad), + (0xb92e0978fe137b3a, 0x3c8bc9dea78f9166), + (0x3917220a53df58e4, 0x3c738663c7562da0), + (0x3893066b32284ca1, 0xbc07042b3fa91e95), + (0x3880dae944b873e0, 0xbbea0b14ac68d97e), + (0x3816034e3ccdafa3, 0x3b7e9f946caccd4b), + (0x37ee935573e4975e, 0x3b5c56e575651cdb), + (0x378326c82431dace, 0xbaf0f996416a3127), + ], + [ + (0xb5cba20478c84ae1, 0xb941c202ce623e76), + (0xbc49df1f0f8d2107, 0x3fbc96700bf039e2), + (0x3bd298b7ed2d3ac6, 0xbf51ec0b5de4befe), + (0xbc26397704521dc0, 0xbf93095734a24496), + (0xbbbe43e7480a487e, 0x3f27d74e12285cb2), + (0x3bbff97a4e7b98d7, 0x3f4e636fe259352c), + (0x3b74153ba07b8f20, 0xbee2fe11972bc0c6), + (0x3b833d8792db4991, 0xbef712e4d44c4a74), + (0xbb0f1553b4c20b5d, 0x3e8cc3adabae0452), + (0x3b2bb2d302a59ebb, 0x3e946ad2d9cbeb5c), + (0x3abbcd480e0362ce, 0xbe295d81ae83f621), + (0xbab3ff4398d1910c, 0xbe27a02aefea3d60), + (0xba59673869d1d69f, 0x3dbd3a949a722395), + (0xba4dc28fd0eb18e2, 0x3db341e0bb193b48), + (0xb9c0a6ee415a5306, 0xbd47b550a4f76700), + (0x3994e75cd4e25783, 0xbd374c654a26537e), + (0x396bf6b9da90343a, 0x3ccc86173683ecb7), + (0xb9343315e10774e3, 0x3cb5be2db45fdd99), + (0xb8dd50a28dc1737f, 0xbc4a7432d3c802d5), + (0xb89104cb13cbb909, 0xbc301fe8f4a0a59a), + (0x3862fc2b2f292a7c, 0x3bc37bcc945caecc), + (0x383f40a66926ee1f, 0x3ba375a2264aec44), + (0x37876edaf3b8c254, 0xbb3726c4f48ef3c9), + (0x37bfb858dba2f507, 0xbb135b197250609d), + ], + [ + (0x3c2c279ff462c3be, 0x3fbc29ae8400a320), + (0x35cbc9db3681c2a9, 0x396a5c619f751287), + (0xbc47ac9bcf3441f8, 0xbfac27138da31c2b), + (0xbbbe5ab192ad8423, 0x3f36d141fcbea853), + (0x3c12b724fd73605f, 0x3f72bdc71062acd6), + (0x3baf5f2a5e20af51, 0xbf0231cf643ffc17), + (0x3b6e53f73e07f7ec, 0xbf23f0bf3b3fe8be), + (0xbb4cfe2786564eab, 0x3eb4b05e955de175), + (0x3b6d19da721e7488, 0x3ec6b52b868fa5e2), + (0x3afd657f133da2a0, 0xbe585a7aa3e84cc3), + (0x3afd8305110d0415, 0xbe6012d3384c9164), + (0x3a82a12fcbf74576, 0x3df18f8c4872544f), + (0x3a83ddc6dcd20390, 0x3deeffc4029f2f01), + (0x3a2a5f86153ccacb, 0xbd811d5a3daf7136), + (0x3a1939ffd2f149a3, 0xbd75a8d84ce122b1), + (0x39948d45aa4f471b, 0x3d080dfa27f2ad6a), + (0x397ee5f9b8f0f308, 0x3cf6eec07f0d91c7), + (0xb92b05e0bbac3b01, 0xbc8987d6f4b58a17), + (0xb90c392890cae7e7, 0xbc7307194fcc3abc), + (0xb894aeaf37740080, 0x3c052f0ff8dc5a44), + (0x3880e377a138ed87, 0x3be96804c6d0c4c3), + (0xb7fb165b04bc999e, 0xbb7c3d1f829825de), + (0x37fc727aeddf2fd2, 0xbb5bad09acad456f), + (0xb74fed0f6e3c7260, 0x3aef5d6f1dc95101), + ], + [ + (0xb5e9f9b32cc9c472, 0xb94f1c4dc0fd7ad0), + (0x3c58fff4515190b5, 0xbfbbbf246914235f), + (0xbbb59d638f72d376, 0x3f5062daee35411a), + (0x3c1bef9e896a99ca, 0x3f927a96f174b6d1), + (0x3bc79c688e87e02d, 0xbf25cdb5dea9c121), + (0x3bd1f78082ed604a, 0xbf4d818348f98a0f), + (0xbb8cf93ec0b60def, 0x3ee160aab829409d), + (0xbb9dfe5ed21cbf06, 0x3ef6698d6ee99eb9), + (0xbb0db19c59160d9d, 0xbe8a5633d8f0b3bf), + (0x3b3148c171a390c6, 0xbe93d788d61154a7), + (0xbabd69ba99ca8de9, 0x3e273ec2ae0084b9), + (0x3a4e64bbbfd099bd, 0x3e26f958f6235deb), + (0x3a5eece34fec9144, 0xbdbad0939c43a9f7), + (0xba3e162f724391e6, 0xbdb2bd56309cf194), + (0xb9d6bdc444caeccb, 0x3d45c709d717e64d), + (0x39923c04d3fffb00, 0x3d36b0b8fe7370f7), + (0x39668435dfe7dada, 0xbcca3cece6ce50aa), + (0x3928e245f64dcddd, 0xbcb531b157c3eb03), + (0x38d9c8cd5a159ad6, 0x3c485f346abae02a), + (0xb8c42e265a4503fd, 0x3c2f771606e9b677), + (0x3869cf65db30f118, 0xbbc1faf5bae17a4f), + (0x3843ce2b3bffa99c, 0xbba3015dbdae4304), + (0x37d01253f07a747a, 0x3b356721e926aabc), + (0x37ab991b20a5ed5f, 0x3b12ebe23c0e019c), + ], + [ + (0xbc4b1bd5a08c4697, 0xbfbb5b8273b75055), + (0xb5fc5d98089f691c, 0xb9617b443b19e784), + (0xbc19066393ec8b4b, 0x3fab59418c36a684), + (0x3bd4c6e4a4b5908a, 0xbf34eafeaa92aa79), + (0xbc1e8c2463f5dff7, 0xbf7235801af9be44), + (0x3b9bcf2d229387a5, 0x3f00af9747d0be92), + (0xbbaf4068b21f5f13, 0x3f23611db0e1566f), + (0xbb5fa296ae418fd9, 0xbeb2fbe414da1250), + (0xbb6579a7a7d2b7a9, 0xbec613ccbb9cbe59), + (0xbafb9e935c5d4727, 0x3e565cf274e84d31), + (0xbae9f705bc9fc3a8, 0x3e5f452996e3dc2b), + (0x3a88db40653fa6ad, 0xbdf023f5382da3ad), + (0xba87d1ea787e96d5, 0xbdee2be24fbad63a), + (0x39e1374c2f3e53a0, 0x3d7f7ed3740f8d64), + (0x39f934955bbeefc4, 0x3d75187e998a123d), + (0x39aeb3c518f70011, 0xbd06293c9e78a94a), + (0xb980e7fd6e1aba60, 0xbcf65a49785b93de), + (0xb925d4c892512e3e, 0x3c878dbf031e576d), + (0xb912bf351c2e7bd2, 0x3c728fde13655c16), + (0xb8aaed4885e1dc5d, 0xbc0392b9e7067906), + (0x3814e81144aa2192, 0xbbe8ce75f24e6d2f), + (0xb81d860830f44f3e, 0x3b7a224d38043629), + (0xb7ef6d218b7f22e1, 0x3b5b0c2b72afb1a5), + (0xb7213d15be1c6e9a, 0xbaed12d5bc6b57ab), + ], + [ + (0xb61ce6cbc1f04255, 0x397036fa5f6395cb), + (0xbc5024304247ada4, 0x3fbaf9cb49c4f935), + (0x3bd43675d81a335c, 0xbf4e1d930b513228), + (0xbc26b1ae60058494, 0xbf91f7a8fec6eba8), + (0xbbccaafb65fcb92e, 0x3f240a55310866fc), + (0xbbe93eb318fd63c7, 0x3f4cb20c812fd3aa), + (0x3b7bc11f9b0249b7, 0xbedff51953c6b6cc), + (0x3b7ca6d618312011, 0xbef5cdc48f5d75eb), + (0xbb1e5d2044572b21, 0x3e883b091952c721), + (0x3b392f30805656b3, 0x3e934fb685e58ab7), + (0x3abdef10942d29ba, 0xbe2566fc4369ab71), + (0x3ac87311849ba940, 0xbe265f0f7de29720), + (0x3a589755adec28c8, 0x3db8b61e5f9b79f9), + (0xba46ab4cdf8eab9f, 0x3db24253069b78a8), + (0xb9d3414dfa14e877, 0xbd441732d722a86f), + (0xb9c20d9bc0b7d20e, 0xbd361fa985a1652f), + (0xb962a44c7096efd1, 0x3cc83c1756587290), + (0xb94098c5fbe9b36b, 0x3cb4ae329744cc53), + (0xb8e5a6b655add69f, 0xbc468a7f4c14db50), + (0xb8c263b696f21145, 0xbc2eba469216c470), + (0x386c7b9219cb3b7a, 0x3bc0a74a6d599cb0), + (0x383259264f03f94d, 0x3ba2936d1cb0c961), + (0xb7de00e6c53ea913, 0xbb33da81fd8c724e), + (0x37a15c8a04c7e7ef, 0xbb128235bc0c47ff), + ], + [ + (0x3c5ffacf3e2418f7, 0x3fba9e13a0db6429), + (0x360c15fcefbc6cf7, 0xb96b692a38880539), + (0xbc305f5aef32722d, 0xbfaa9c1ca2161b9b), + (0xbbd5ab98ac975e2e, 0x3f3344a09efdc635), + (0x3be8bf0e555b3029, 0x3f71b82c430a2381), + (0xbb93a994567a3c7b, 0xbefebfb97bca01f2), + (0xbb991369e36b1830, 0xbf22dcdb1bc1d038), + (0x3b5ea31075526d31, 0x3eb180047f0b79ae), + (0x3b46ada0a01da18a, 0x3ec57eeeee84d0d0), + (0xbadb2a1ce7632789, 0xbe54a0c699c8318b), + (0x3addd02fc0b7c908, 0xbe5e7594e8a2c760), + (0xba80e5f270287d53, 0x3dedccbbb4c0ba7f), + (0x3a7ca797a3565ecd, 0x3ded6766337b5c91), + (0x3a1ab23ec0eb4599, 0xbd7d1a05cea18a69), + (0x39e1f4b5b52d14cc, 0xbd74922fb50a22bf), + (0x395024c9150c0f64, 0x3d047fa35bf6ab34), + (0x3985f2bf77091074, 0x3cf5cfa08701ca2f), + (0xb9266c2a76db875b, 0xbc85d0099455bd99), + (0xb91f43baef384b49, 0xbc72200ae9780072), + (0xb8a3a3083fb87713, 0x3c02265fdf769ade), + (0x38836fad8505e902, 0x3be83dc86da8bc25), + (0x37ea0aade21b140f, 0xbb78447b5e2dbf2f), + (0xb7f62e5f79c1ca9c, 0xbb5a73de1878cbf9), + (0x378acaea6a6d9658, 0x3aeb08df74d22d98), + ], + [ + (0xb5d780da95d79b82, 0x395404a4367c1acf), + (0xbc55d35a88f1e0a3, 0xbfba4407e04298d1), + (0x3bdf6dddc07aba4f, 0x3f4bcc9df0cf00b2), + (0xbc3c3cb8ccc39d2a, 0x3f917f0266db2149), + (0x3ba3d974ad41d7db, 0xbf2280a052234a05), + (0x3bb902b66919d00f, 0xbf4bf2ada1f44071), + (0xbb64ad3ffb27706b, 0x3edd83d58032b48d), + (0x3b3d6efc3f5aa589, 0x3ef53dd972d8f232), + (0xbb230bc40c1510e8, 0xbe8663c1fe202028), + (0xbb26dba834dbae96, 0xbe92d1fbf2203ff6), + (0x3ac7c87693a0820a, 0x3e23c9f0b759c5f9), + (0x3ac4688bb194b145, 0x3e25cfe1b012696d), + (0xba597597731528c4, 0xbdb6ddc0795781e2), + (0x3a30fd07b7c74b96, 0xbdb1cfd495042669), + (0xb9e56d22c0bed868, 0x3d429b7af52144d6), + (0x39c7617697a68dba, 0x3d3598302ab3a84e), + (0xb969ff73c4a2ed6f, 0xbcc677f6a5ebe777), + (0x3900de58e64b147d, 0xbcb432ecc1192f3c), + (0x38ee92d01dc42743, 0x3c44ec1126d1a78e), + (0x38c2b1157c94ede8, 0x3c2e0887dbe88798), + (0xb7d2d49d120bbb3a, 0xbbbef4037751e14b), + (0x3837430b053ee391, 0xbba22b7609bcdbcb), + (0x37d8cec91a9bdbe3, 0x3b327988001f32dc), + (0x376c8d2e6d2182d4, 0x3b121ddd67c06d53), + ], + [ + (0x3c423404089aea02, 0xbfb9ef3bb2213b0b), + (0xb5c87de2f8cebd53, 0xb962e8408ad4e1a5), + (0x3c342c5cb51f294f, 0x3fa9ed82007a9a45), + (0xbbad41b75b8ea526, 0xbf31d2fdeeb29f8a), + (0x3c18994595321a31, 0xbf71446866ff1b83), + (0x3b94bf0ff8b9b23d, 0x3efc73b684f93259), + (0xbbc79edfbf5325fb, 0x3f22628de594b6c9), + (0xbb2befa01f9526e8, 0xbeb03303c1427449), + (0x3b691967f42c542c, 0xbec4f51007c51087), + (0x3af5410acbffa9a8, 0x3e531adfa36f2213), + (0xbafc56975a6a16e6, 0x3e5db4f306b19095), + (0x3a79c0979a0204dd, 0xbdeb9e33598f899e), + (0xba765a4f110b219b, 0xbdecb09ed6ecb892), + (0xb9f410899a06c92c, 0x3d7afe1183148af8), + (0x39f78f1dd4b75a7f, 0x3d7414e442aa864a), + (0xb99a9b988c884db4, 0xbd0307c12941fdc5), + (0xb990c58e388b6028, 0xbcf54ddabc97b3bb), + (0x390b34a178291a11, 0x3c84455c63029495), + (0x391979fc805b19bd, 0x3c71b7024cd44274), + (0x389e56ba399caf6e, 0xbc00e2d078dd0efb), + (0xb82f4378acefe136, 0xbbe7b55bb497c4cb), + (0x381a7fc1f4e5a681, 0x3b769ad969d0625b), + (0xb7931840ec89fbc9, 0x3b59e3a726e2743d), + (0x378455d827026a82, 0xbae936884740c735), + ], + [ + (0x35fae2734bb315aa, 0x3968400e2d1b8167), + (0x3c5728ab934a269f, 0x3fb99be744018c90), + (0xbbdb8852614fe955, 0xbf49c3f52a2af724), + (0xbc2f281d89ca125d, 0xbf910f5ca51f98b0), + (0xbbc3c6681ad02312, 0x3f2126c8e8ca2766), + (0x3babb471b2a0c061, 0x3f4b416f7d4fc313), + (0xbb677b339729278d, 0xbedb5e2e5580e1ce), + (0xbb988d465ffb2680, 0xbef4b862279de756), + (0xbb2b440cbefcb86d, 0x3e84c5071b39dc13), + (0xbb3de6305e87339f, 0x3e925d2fc3b19021), + (0x3ac90d431ee8f3e6, 0xbe225df322279972), + (0xbac3c7a2f5c16d4a, 0xbe254a971eb6fe3b), + (0x3a515ee7ac48908a, 0x3db53cc6c9922f25), + (0x3a5ec538d819665b, 0x3db164f95180d8bf), + (0x39d2657db4413c0c, 0xbd414b9ef404e359), + (0x39d5a070336f534a, 0xbd3519623b4e4c39), + (0x396e222733381912, 0x3cc4e7271a5acddf), + (0xb94d7cdd22f0028c, 0x3cb3bf2a1b7bb45e), + (0xb8e550d76b23a690, 0xbc437bc0b629d672), + (0x38b920c14a99cb5c, 0xbc2d61049bf3447b), + (0x3855956d27abf79f, 0x3bbcdb091753dc1f), + (0x384b894b04dc498b, 0x3ba1c91964954692), + (0x37d5bcb82226b372, 0xbb313e10f59f02a2), + (0x37bd81d4f7329d91, 0xbb11be93ca114b15), + ], + [ + (0xbc54096ec8637e04, 0x3fb94d3276914e51), + (0x35b1f799a74fb76a, 0x395d690fadf22a83), + (0x3c4baee1d6c0d48a, 0xbfa94bac1950e319), + (0x3bdbfe3ad50b9727, 0x3f308d4ff8f2059e), + (0xbc1cca1c2772d45e, 0x3f70d90d29bfeecd), + (0xbb987fee6366d20f, 0xbefa6d56162f7fb4), + (0xbbc7e7232a191e61, 0xbf21f107da23807d), + (0x3b42cbe0cc45eb3d, 0x3eae1a626277437b), + (0x3b665f948e1d7ee0, 0x3ec474eafd0cc642), + (0x3acb746c7398995a, 0xbe51c27144f42d78), + (0x3af77d2dd1ae1ba3, 0xbe5d01999b1a4fe9), + (0x3a77ecdd37e45371, 0x3de9b014801da87a), + (0x3a855ec04282c8cc, 0x3dec061740bc8a41), + (0x3a1fc05e7d7c7991, 0xbd791f8c297254d7), + (0x3a0ace8e68225aa3, 0xbd739fb558b7a363), + (0x398b465ba48d7de4, 0x3d01b9f74d482556), + (0x399084cac0e412c2, 0x3cf4d425556e6c52), + (0xb91cfaa8a45d49ae, 0xbc82e617aee470c1), + (0xb91bd25d6d983a31, 0xbc71543271ff906d), + (0xb89586b26f4fbcba, 0x3bff8440e63c211d), + (0x386772bb21a29d94, 0x3be734945f8177cb), + (0xb80904837292f3d9, 0xbb751e13261a9dc1), + (0x37f62a65371653ca, 0xbb595b06b5ab1c41), + (0x378aee2000820cbf, 0x3ae79434d2d5aa8d), + ], + [ + (0x35fd3e35d9fc508f, 0x39692a03d61a6765), + (0x3c5e213a1a4b3671, 0xbfb8ffc9bd24fe08), + (0x3be5e8a5d70cddcc, 0x3f47f7d46ab33721), + (0x3c2f532ddb23da23, 0x3f90a7a725d3fbc4), + (0xbbb3f089aa77a72c, 0xbf1fea1728f216b4), + (0xbbdf63ef331627c3, 0xbf4a9cac69f0ed64), + (0x3b78f775a8392238, 0x3ed977f48ff1056b), + (0x3b8a77447708dbe0, 0x3ef43c2d8e698c10), + (0x3b293fa288b304e6, 0xbe8355d1a6765ea6), + (0x3b17742d486c25ae, 0xbe91f0553501d121), + (0xba8ae50dffeaa9a9, 0x3e211b47f6a44829), + (0xbaa73bc70607579c, 0x3e24ce23303889a9), + (0x3a5d5eb483ce8058, 0xbdb3ca98df62221a), + (0x3a46a518fdfd8131, 0xbdb100fc746529d6), + (0x39e722b8c5f7aad4, 0x3d4020f11e2dc07c), + (0xb9d9956b0c21d835, 0x3d34a26ef221978f), + (0x396850ab1f7d4d53, 0xbcc38203ff3d18df), + (0x3945a4bf6ed3a626, 0xbcb35244c14991ae), + (0xb8eeb070694cf5e7, 0x3c4232db9b60cb00), + (0xb8a56af95593329b, 0x3c2cc2f2efd1e051), + (0xb817a34eb41964e7, 0xbbbafa643c1fee7f), + (0x38319c576c8452aa, 0xbba16bf81ee3b787), + (0x37d076f627ec3422, 0x3b3022fbfe27424b), + (0xb7a801683d487848, 0x3b116413b0cae3c2), + ], + [ + (0x3c4123b2f0e7c9dd, 0xbfb8b67a2481077d), + (0xb5edd5946b3cb2a5, 0x3946a50da827f406), + (0xbc4b4ca91be60c39, 0x3fa8b51f21068ea2), + (0x3bb25eeb0c76260b, 0xbf2ed935c7aefa31), + (0xbbf1e976299c9c65, 0xbf707522a5037f2d), + (0x3b9aa02b2a63445a, 0x3ef8a196061f8bbc), + (0x3bc503ddc4900b75, 0x3f21874a47e3c1e3), + (0x3b255f883f2d82a2, 0xbeac10cf34c04f17), + (0xbb5b1d29b71073a0, 0xbec3fd6c2d4fa2a4), + (0xbaeb8c54608e9282, 0x3e50906d55522785), + (0xbac0c29c0a96e3da, 0x3e5c5a1c124dfa08), + (0xba7aa4d02da2e1f4, 0xbde7f883b31a5f59), + (0xba7747971035692d, 0xbdeb668cf53028e0), + (0x3a1b938795c32e6d, 0x3d7775372d05b2b0), + (0xba0cfec68b9fa162, 0x3d7331d871d67118), + (0xb9ae3aa9398e5a58, 0xbd0090102489f480), + (0xb99e9cec5597a630, 0xbcf461c4066d0e4a), + (0x3914deb7f36c5b05, 0x3c81abf9941a3423), + (0xb8df6670bd950fcb, 0x3c70f715e31f4f53), + (0xb88076dcbbb6bbc6, 0xbbfd7ed45d36754d), + (0x3884befa4b49ff70, 0xbbe6badf59009f89), + (0xb817484bd8d9cd12, 0x3b73c80adb5c7d1b), + (0x37e6bcd3e344ffce, 0x3b58d97e797244fc), + (0x377002e0099ec551, 0xbae61ba441542113), + ], + [ + (0xb5e15739920a6042, 0x3957411605b9cd8d), + (0x3c5b1c9821974147, 0x3fb86e51be0a9153), + (0xbbeaa494385da6b8, 0xbf465ed1b387e5da), + (0x3c09cfc1363fac8e, 0xbf9046fc5a218a86), + (0x3bbf17fc5592840d, 0x3f1dca617fefa913), + (0xbbe411ddd3f3c7e1, 0x3f4a0300221528a7), + (0xbb35922b096464c9, 0xbed7c7618906f1e2), + (0x3b985c37a80f1f32, 0xbef3c838897d0a1e), + (0xbb1cfd1e42294da1, 0x3e820ede9f9dd7dd), + (0x3b3d337f0c931d76, 0x3e918a94165592bb), + (0x3aba2064c2ef620a, 0xbe1ff76205118f09), + (0x3ab62166ef13ed4e, 0xbe24599dfeef01a1), + (0xba4104861aca6ff9, 0x3db2803e5998312f), + (0x3a5eb79000c7671a, 0x3db0a33202feb041), + (0x39ad6a6495675c7f, 0xbd3e2bff73866f0b), + (0x39d02f8782470b05, 0xbd34329cf32bc6b1), + (0xb94c1fab2f5d49d8, 0x3cc2424890e7103d), + (0x395165f2cbeeb591, 0x3cb2eba6575a58fb), + (0xb8ee488b45b19302, 0xbc410bda2b2fedfa), + (0x38c169197f6744f6, 0xbc2c2d96bb6d554b), + (0xb839df5ffc139231, 0x3bb94a6157935d73), + (0x38438133f79f8aef, 0x3ba113b61477f5c4), + (0xb7c400b9f75f31c1, 0xbb2e47f731863fb7), + (0xb7bf6daddcc30386, 0xbb110e1251b8eda4), + ], + [ + (0x3c48caabfef07d2b, 0x3fb829d06fee9266), + (0xb61c7c2ce51dc943, 0xb97019a7cd7017ec), + (0xbc46f7f24522358e, 0xbfa8289a526d7785), + (0xbbbd55f5936024f5, 0x3f2cd680355c9eb6), + (0x3c19dafafbc6423c, 0x3f7017d70f512861), + (0x3b94ef9247fbd18a, 0xbef707978e2a0db8), + (0xbbb84f6dc795e259, 0xbf21247ce15e7385), + (0x3b3c154e3f91cb1f, 0x3eaa3f6125485ec1), + (0xbb6485e10f66ec36, 0x3ec38da848401be9), + (0xbae822e833951880, 0xbe4efe39d8db4cd8), + (0xbaf0a59f02f9da6b, 0xbe5bbd40f1db0e94), + (0x3a88e5731b6d2f4f, 0x3de66f7d49436f83), + (0xba3e79da115ba52a, 0x3dead0e8148229af), + (0xb999a0303d870988, 0xbd75f78595133d59), + (0x39d279bb13e85151, 0xbd72ca9bb1031b0b), + (0x398dc73294489cd5, 0x3cff09e49c89467c), + (0xb98c493ba49ccabf, 0x3cf3f60eeb57dab2), + (0xb928107dd8db2eda, 0xbc8091d68a71f568), + (0x391a43591422376a, 0xbc709f3347db6cf2), + (0xb88bd7e4b3dfccd4, 0x3bfbad357dd86bf0), + (0x386a0a018ebdb436, 0x3be647b364d0856e), + (0x381f08d09391197b, 0xbb72939f68459b07), + (0xb7ea807173f17da8, 0xbb585e93fb40bea8), + (0xb78b806a2be014c6, 0x3ae4c7339928aa1f), + ], + [ + (0xb5dba30ce3053693, 0x3937ea2409abe46b), + (0x3c21907f595a082a, 0xbfb7e656efb009ae), + (0x3bea53822a52cdff, 0x3f44f15066f3d876), + (0xbbef8f1c97361f96, 0x3f8fd932c26aad94), + (0xbba4e6bbdef5d491, 0xbf1be460dd86a0a4), + (0x3bdda15b3ef145a9, 0xbf49733b591879f8), + (0x3b7b0e61e74c413c, 0x3ed64488c56022e0), + (0xbb74588b74c5876f, 0x3ef35ba58bf2f993), + (0xbb2d010d38a866aa, 0xbe80ea47bceb9a8f), + (0xbb1839485029ea9f, 0xbe912b327055d0e9), + (0xbab04b71fdf73b8a, 0x3e1df42fc4e2482c), + (0xba732a2fe61d6156, 0x3e23ec3e76876dba), + (0xba511e7db88fce7c, 0xbdb1580393f473be), + (0xba5b5424c61c9156, 0xbdb04b0353c35933), + (0xb9c9856b07421c8e, 0x3d3c4ca30ffe1933), + (0x39c738eb74a7f61d, 0x3d33c947b936be26), + (0xb9400509632244dc, 0xbcc122c73f63e006), + (0x3916d7eae173a1b3, 0xbcb28ac72945c28e), + (0xb8e73a0527a29464, 0x3c4002241bb36c01), + (0x38cad2069d44143f, 0x3c2ba04276d6d12c), + (0x385b64b543fd96d2, 0xbbb7c48f7753a6e6), + (0xb848072abf17cd35, 0xbba0bffbbb75a502), + (0xb7a49b7af751a348, 0x3b2c7ae054639d4d), + (0x37b54394c52e23e8, 0x3b10bc481d251ae6), + ], + [ + (0xbc2f952341a4610c, 0xbfb7a62320798175), + (0x3608d7aa0df33a13, 0x396cf7a4a97dd69b), + (0x3c4f5aadff868840, 0x3fa7a50ca4504bb8), + (0xbbc425ed1e39553c, 0xbf2b095ccb50a68c), + (0x3c0088e41716f14b, 0xbf6f80ef11daa37a), + (0xbb8b1b49b7c35e54, 0x3ef59822dc75b064), + (0x3bc22455d3c1fa15, 0x3f20c7e6a7c66630), + (0x3b4cb7a0033a7704, 0xbea89e00b5c358d0), + (0x3b4c5ee49818e61f, 0xbec324d5238b26d0), + (0x3ae1d17d1c1f9459, 0x3e4d13a888d5dd30), + (0xbac771ff3649d30b, 0x3e5b29f941a95b07), + (0xba65c3a8faacb7ca, 0xbde50e6ebb3d1df7), + (0xba5e1fa2b117348a, 0xbdea4434c6b929d9), + (0x3a1aa33d3910c73c, 0x3d74a03fe2c47ae3), + (0x39fc6f3d0c6f0177, 0x3d7269628f2df267), + (0x3998d07708e4c6bf, 0xbcfd28cc08f5cbae), + (0xb95557f1f159116a, 0xbcf390706324d249), + (0x3901d36b70d2e2f4, 0x3c7f26c3f4d4f4a6), + (0x38f56e280758755e, 0x3c704c1cbbe93d3e), + (0xb86ceb268d238b88, 0xbbfa089cde4d22c5), + (0xb889788b18499f22, 0xbbe5da907334a8cc), + (0x38130abe343bca1e, 0x3b7181ee2ddebf21), + (0x37f04d8f909b3d76, 0x3b57e93ad9acbcc3), + (0x378249417d24489f, 0xbae648d6e71bec37), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs_taylor.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs_taylor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs_taylor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1_coeffs_taylor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1282 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +J1 taylor expansion at zeros and extremums. + +Generated by SageMath: +```python +def print_taylor_coeffs(poly, x0): + print("[") + for i in range(0, 24): + coeff = poly[i] + print_double_double("", coeff) + # print(f"{double_to_hex(coeff)},") + print("],") + +print(f"pub(crate) static J1_COEFFS_TAYLOR: [(u64, u64); {len(j1_zeros)}] = [") + +for i in range(0, len(j1_zeros)): + k_range = j1_zeros[i] + range_diff = k_range - prev_zero + g_c = 1 + + x0 = mp.mpf(k_range) + from mpmath import mp, j1, taylor + poly = taylor(lambda val: j1(val), x0, 25) + print_taylor_coeffs(poly, CDR(k_range)) + prev_zero = j1_zeros[i] + +print("];") +``` +**/ +pub(crate) static J1_COEFFS_TAYLOR: [[(u64, u64); 24]; 47] = [ + [ + (0x3c61f1c324453b30, 0x3fe29ea3d19f035f), + (0xb5b2f6354c9ff45d, 0x392031b7410e0111), + (0xbc6e3631ae171270, 0xbfca41115c5df243), + (0xbc18acc5100eb0b3, 0x3f78d1448e6fed48), + (0x3c0e85a7d0bc098f, 0x3f8c441a2f9de22b), + (0x3bd94ca1b6912493, 0xbf386671c18b088a), + (0x3bd950cc4e8482d1, 0xbf39e2504ddc7608), + (0xbb61b481438e4089, 0x3ee34ccbca0c75d1), + (0x3b7aba05e287d170, 0x3eda4973784d1087), + (0x3b1ffacaebcbb72b, 0xbe81045322aaab45), + (0x3b03dabae8fea73e, 0xbe70fae0da6cdcef), + (0x3abc719b8692aa74, 0x3e13546cef5ed00a), + (0xba8ac75d7c570055, 0x3dfe5ee82e667708), + (0xba263b1d65111e4c, 0xbd9ec80cc8b63c39), + (0xba145e6e27b1490b, 0xbd83eb2e99629b44), + (0x39b7626e428b4f57, 0x3d222bfcdb19561c), + (0xb98421e04d0e0d8c, 0x3d03fb3376a42e35), + (0xb922e25ac68f0c81, 0xbca0901287d105ae), + (0x391c50bf6cf518de, 0xbc7fa6a90c6a0c33), + (0xb8b3ffd27bab3779, 0x3c180774f17c486b), + (0x38976f3626c20293, 0x3bf44b79578fc6fb), + (0xb82c4199c877aeaa, 0xbb8c6ab05fe77307), + (0x380edbb8b3f4ef74, 0xbb65805fbd38e218), + (0x3787f411d416c35b, 0x3afbed5bcea231a2), + ], + [ + (0x356eab958ab851b5, 0xb8d9a91f973ec303), + (0x3c62de1143765a96, 0xbfd9c6cf582cbf7f), + (0xbc46b8d73329ae53, 0x3faae8a39f51ad04), + (0xbc47767d9698b536, 0x3fab589d1da13905), + (0x3c0e65e41f8b156f, 0xbf7537544c331da7), + (0x3bc117d15907382b, 0xbf624b3409959064), + (0x3bb8c81b03584e43, 0x3f26e4c2d5354224), + (0x3b9859e8c0ae37ce, 0x3f083a06e30c4109), + (0x3b51fe68ee4dfe26, 0xbec9799d4c9f2549), + (0xbb4ffb11fda5bef3, 0xbea33825cd2e2c16), + (0x3ae8a5cec4a77c6c, 0x3e617069233e916c), + (0xbaabdbb69c094017, 0x3e34569b22afc3c8), + (0x3a76236a521c1ecc, 0xbdf03b9e9651056a), + (0xba58526061a7319e, 0xbdbec62310af5f52), + (0x39f8c0813d01aca5, 0x3d75ec84e47b6f4f), + (0x39df157bfc6eaf25, 0x3d417a40c9422e17), + (0x399dbf21a6dd6ae2, 0xbcf67cb1d0030c9c), + (0xb95f5d6974a310bb, 0xbcbee7ff918f9b69), + (0xb8ed0057404186a7, 0x3c721fb8bdc4d7fa), + (0x38a1a3560d39e992, 0x3c35e0517dd0b5c9), + (0x388155451c853ffa, 0xbbe792595a1eec68), + (0xb829a85503eb4baf, 0xbba95a682022dcb8), + (0x37f61a6a78be1e62, 0x3b59438c464a0b99), + (0x37ba49a9e0951317, 0x3b187f5c94382543), + ], + [ + (0xbc782d627160714a, 0xbfd626ee83500bf2), + (0x35a0f040f68d1816, 0x3909887c15bb2d86), + (0x3c6ae8952e6f1d99, 0x3fc55f6bec9ef962), + (0x3c0d30f1a30652af, 0xbf83d23336fd10e4), + (0x3c2695c3589cdcfe, 0xbf88c77a983a0814), + (0x3bea1200f3887332, 0x3f45cdc98db1cbe2), + (0x3bd343248cea52bc, 0x3f373576ff46ee3b), + (0x3b8a8cd6bedb881b, 0xbef2461447d7b423), + (0x3b6a8a902c87e6bb, 0xbed7b853456b6eaa), + (0xbaff7253673d7fa0, 0x3e90abfc68274a98), + (0xbae9e22e3ad66ed4, 0x3e6ea7a1ee26124d), + (0xbac56987dde26b61, 0xbe235c0413e01418), + (0x3a9eb6867453dd1c, 0xbdfb5c5d512fbb00), + (0x3a3a4481d08d2199, 0x3daf4c5e26fd6e90), + (0xba21e34f6852a2b6, 0x3d81e4c43397be51), + (0x39d14c360485170d, 0xbd32addefc4d51c5), + (0xb9605d05ffcc6dea, 0xbd01e4fadc0e435c), + (0xb923b05198207824, 0x3cb12a0b88508f37), + (0x391a5ac22b8f14bd, 0x3c7c4246a0342e39), + (0xb8ce78a27a5aabf3, 0xbc290ede5816f2ce), + (0xb8986d234d468db8, 0xbbf211307906e314), + (0x381bc4668970e7dc, 0x3b9dc7bf70396b28), + (0x380949fa46f6dd76, 0x3b6316e7f158a264), + (0xb79167d26945830c, 0xbb0d623edc3b24ac), + ], + [ + (0x35a1c201de6b176a, 0xb90f8a0b194e92aa), + (0x3c7af22d033ee0a5, 0x3fd33518b3874e8a), + (0xbc23b4d6298472ae, 0xbf95e70dc60362bf), + (0xbc476d8715df682d, 0xbfa80c83bdeee5b0), + (0x3c03dac20ab22d50, 0x3f69a4b292e3de42), + (0x3bd887eed6e6880a, 0x3f613fbc7d698217), + (0xbbac52a925910e75, 0xbf207358bbdbff91), + (0xbb64763d026d3263, 0xbf0796a751f89051), + (0xbb6df65f1fdd48ef, 0x3ec4255b015aded4), + (0xbb3ae816d26784fd, 0x3ea3026e0ce97ab9), + (0xbaf57b3883b98fa3, 0xbe5d48dcdae92f2c), + (0x3aca4c50b5ee02fb, 0xbe344639d7eeb0a6), + (0xba8fd8f34b9ecafc, 0x3dec62ccb4a32eb5), + (0xba5032cb87171f64, 0x3dbecae92e854457), + (0xba1beb1ed7eaf160, 0xbd73bb6898d73cd2), + (0xb9dd5420c79c50f5, 0xbd4183edbb8ef55e), + (0x399a66b105ba2d65, 0x3cf4ae3e7e4cce3d), + (0xb918cb92ea651e7f, 0x3cbefbb1e700730a), + (0xb9146c2f2b670d08, 0xbc70f28da3efa3c7), + (0x38c4ac35b8206d4a, 0xbc35ec318df9b467), + (0x388be1913e828c5e, 0x3be6555a952345fa), + (0x384ff998fe9bf37c, 0x3ba9633c7f133c92), + (0x37f9fe5cad2d2342, 0xbb583145f93c70ae), + (0x37bb7a15502058b2, 0xbb1881cb99e6a1d9), + ], + [ + (0xbc7d48dbfa0ea1a4, 0x3fd17dbf09d40d25), + (0x35a4427f3ab43500, 0x3910992c4b87a2c6), + (0xbc61eb914d33c2fa, 0xbfc1404bf647c28f), + (0x3c098a23a3934c81, 0x3f74f4df2769f830), + (0x3c24ae93dcbae42e, 0x3f85c6285429b66d), + (0x3bdddb259d6919ae, 0xbf3d68ab722881bd), + (0xbbd8cd731f6bf3ff, 0xbf356acb6452d860), + (0x3b60d2b8ff5b8f47, 0x3eec10b47cf7ef69), + (0xbb3cc7e8d830a4e7, 0x3ed67eaae97bbc86), + (0x3b0230ef0e6803fa, 0xbe8bb6530c63f2df), + (0xbaf83f73085e8893, 0xbe6d87201e450edd), + (0xbaaefe243bce74cc, 0x3e20f47c83ec550b), + (0x3a995905da4f9c80, 0x3dfa98331f6ea799), + (0x3a40b4039f32743f, 0xbdac70414a236a67), + (0xba249d55aee4b10f, 0xbd817c057a5fcd3d), + (0x39d02164b46fc11f, 0x3d316fea14d1fe7c), + (0x39990498a42b8b9e, 0x3d0189bd3ec36234), + (0x39512fd1dca06419, 0xbcb05af44aaf2ab4), + (0x38fe8d7eea675e23, 0xbc7bbdb47ae6b94d), + (0xb8b4cc5b1f63c320, 0x3c28435e8461ed37), + (0x3882cf7a81930228, 0x3bf1bfd66fba7b36), + (0xb828cec539879f22, 0xbb9d3526fa2c65e2), + (0xb7f6bbe8d3df2731, 0xbb62c1e2b3f208cd), + (0x376ec8c34abcf067, 0x3b0d1f12fb9ae97d), + ], + [ + (0x359d2cb8a50a29e8, 0x38f8cdeedd7089d9), + (0xbc5052a3a2541c57, 0xbfcff654544ebcd1), + (0xbc01b402d42ea509, 0x3f89223ff2c0785b), + (0xbc323a275590a85f, 0x3fa4b0c5d5da6789), + (0x3bb3ea54ac68ef82, 0xbf5f91a9ee0d2897), + (0x3bfc41f7f61682c1, 0xbf5f51c2489b9e6f), + (0x3bad7af9f28c7680, 0x3f16b4c9ca0f770d), + (0xbbadd3415a058d7b, 0x3f063c5475439cb2), + (0x3b59f6c7b33666e7, 0xbebe3725daf69867), + (0x3b21f2a7db95aa23, 0xbea25c1238b32e59), + (0xbaeb35e7c5937061, 0x3e57486f6b9aa951), + (0x3ad95c3e197deb05, 0x3e33e3bf248277ee), + (0xba77b9fdb9bee258, 0xbde78a38a73e7c0a), + (0xba480ea277e7ec50, 0xbdbe844eb6b211b0), + (0x3a0c6dae4342e4f7, 0x3d70e24abb40708e), + (0xb9e5f9316e1c5efa, 0x3d41797e5eacddfb), + (0x398387d37934edf1, 0xbcf21fc0f1265a7c), + (0xb95b8aad5aec742b, 0xbcbf0c12e445cb41), + (0x390e42f5b55d3825, 0x3c6e4423559080b2), + (0x38cc1d5a56b93a77, 0x3c36080463b41f1d), + (0xb87dbc48deb40e7d, 0xbbe43e38b263073e), + (0x38442a4086626b0d, 0xbba98fa121c815cb), + (0x37e94a11e9993a14, 0x3b56325cba16fa62), + (0x378f6607677ad6cb, 0x3b18b3fd438c6ab3), + ], + [ + (0x3c50f8942d3f902b, 0xbfcddceb4ce1bf4a), + (0xb5776203d5c7d545, 0x39009f7250661abf), + (0x3c433d5334b42c83, 0x3fbda52116c0a640), + (0xbbe72468a28942f7, 0xbf6a9da4603b67ea), + (0xbc0c5e08317c5bc1, 0xbf8331e74ea59ab8), + (0xbbdac4579bb7d320, 0x3f33e5cb6eba6eaa), + (0x3bd0ad973dfed7a9, 0x3f33885fe9afa541), + (0xbb74d72fe9613abb, 0xbee494c0f4b0680b), + (0x3b783e70ffbfc8f8, 0xbed512b9d37762d7), + (0x3b137aef41758720, 0x3e85a861082bfb7f), + (0xbb059fce2a743f33, 0x3e6c323ea0a042c3), + (0xbaaeb25b7edb5f5d, 0xbe1bcc962f7b91eb), + (0x3a6a5caf0a45be46, 0xbdf9bc94e2f29a52), + (0x3a4115f7a8e1da37, 0x3da82bc6fcfa8e89), + (0x3a2ca2e9a78a230c, 0x3d81141ce7b78460), + (0x399649188487057f, 0xbd2e79ccb1860d7a), + (0x397e5f7602a25533, 0xbd013e1fbe0a5971), + (0xb91843ce4e8dd1b6, 0x3cad36d12b0d249d), + (0xb9191629f123918b, 0x3c7b66072bbdf478), + (0x38cfbb54dd8d36aa, 0xbc260cb923a35433), + (0x385274d20bfe6ac3, 0xbbf196237500b24e), + (0x383559483b284848, 0x3b9aeba1005e1830), + (0x380a4bb85b8cb2ba, 0x3b62a07d164c6a6f), + (0xb76cc607fa3605e1, 0xbb0b27ac12f04a31), + ], + [ + (0x3540e66d0c71e44c, 0x38b8ae14acc03cc2), + (0x3c6c8c66d2e42062, 0x3fcbf3337873a7d8), + (0x3c25e81c4baa84e9, 0xbf80c83a2d7add33), + (0x3c44192692d7c9db, 0xbfa251858011816b), + (0x3bd0475c4916a7f2, 0x3f559eb160bf72d8), + (0x3b9e04d41bf0d87b, 0x3f5c5bce33af2d77), + (0x3b7eb490c3282478, 0xbf10413e306e0039), + (0xbb9e3a426e412d42, 0xbf04a6704d05ad0b), + (0xbb5a4f33202681b2, 0x3eb6c43eedfed6c9), + (0x3b2d2f110d38d23b, 0x3ea16abd7815de74), + (0xbae416eabc41ca79, 0xbe5257f16f5d4346), + (0xbad1043744ab6130, 0xbe332db1b4b2ff8b), + (0xba872ca31e31d0a7, 0x3de33acccf7bfdce), + (0x3a00b03336c2218e, 0x3dbdc8f5682566ba), + (0xb9e9cd15ad06d38b, 0xbd6c6513386daae2), + (0x39d8466ad52efa61, 0xbd413585a9b7473f), + (0xb9408c90ab21329f, 0x3cef322ea2e20db6), + (0x3952e07fa31826b3, 0x3cbec749ba31d0ed), + (0x3904a43ae3e1adf7, 0xbc6a8abab44a5a16), + (0x38bd7572726e9fd6, 0xbc35f2aba27d0156), + (0xb8753cce6cac9ae4, 0x3be20705169a0885), + (0x38458824bb426ee4, 0x3ba98e9c9fa1064a), + (0xb7e6e8cdd35eeba7, 0xbb540557c89d65c9), + (0x3759f423b384f394, 0xbb18c41cdedb0d3e), + ], + [ + (0xbc26397095487bb8, 0x3fca7f63fea81f26), + (0xb579a23f3e01c02a, 0x3900cbe4fe15df81), + (0x3c4341d92ebaf0e5, 0xbfba60afb06640cf), + (0x3c0aa0cf7edfc4af, 0x3f62c1e930935d3c), + (0x3c2253175b5dc28b, 0x3f814506466d7f1f), + (0x3bcf594f6cb1e048, 0xbf2cca8c0c0eaa3f), + (0xbbc23306ba391f44, 0xbf31df821cc1377e), + (0xbb6f4273eb18d486, 0x3edee8814ed0ac45), + (0x3b3531e00c0b1e91, 0x3ed3a365a4199dd1), + (0xbb2539aeb3d4946a, 0xbe80ed2f9c3e458e), + (0xbae7dc7c41800a98, 0xbe6ab3b37c5271b3), + (0xbabe3080b40ebc8e, 0x3e1684d6e62b5c66), + (0xba980fe8dabe0c36, 0x3df8b105a5120ed2), + (0xba34afb054573ddf, 0xbda42dc5991b9d01), + (0x3a24e165917f0851, 0xbd808d6405ffe3dc), + (0xb9bea36c059d9a67, 0x3d2a15203365a9e0), + (0x397717476aec9541, 0x3d00d7c118bbeb37), + (0x39474ba7f9cdad9c, 0xbca984ffd2857b4d), + (0xb8f090df156cf8ee, 0xbc7aecb2d322693f), + (0xb8b29f8b4dabfed8, 0x3c2396ff2d246042), + (0xb86310d4b1263ad5, 0x3bf15cbae441ca24), + (0xb8388b6c6238abda, 0xbb9841be044fa28d), + (0xb7f60da5e67d9193, 0xbb627467b799ccfc), + (0xb7ab569bc7745d94, 0x3b08c28575d745a7), + ], + [ + (0xb5a0840c646e7364, 0xb909bb79105907c8), + (0x3c6e9557ccd1703f, 0xbfc925c6fca08f55), + (0x3c091bef69239af0, 0x3f786dd32e059b0e), + (0x3c3dac1b118bb946, 0x3fa09463bbd0367f), + (0x3be231ff19225462, 0xbf4fda0298c8768b), + (0xbbf0185527e9208e, 0xbf59f4be60758fb1), + (0xbbac474063460803, 0x3f0877991af9d1bb), + (0x3b85632e0e751036, 0x3f032cb00ee8c1f3), + (0x3b46a0371f5eb5de, 0xbeb19d8ce8c35f58), + (0x3b44398edcd31b46, 0xbea06a042fbba455), + (0xbaeabb097c7d4aab, 0x3e4d3a689e677731), + (0x3adf851e84662874, 0x3e325108c4ce2b63), + (0x3a700c6a94a96471, 0xbddf7b8e9ab53152), + (0xb9e39398140885a8, 0xbdbcc40d05652642), + (0xb9debdd38ee83cbd, 0x3d67cd76e2d7e2cb), + (0xb9d4060b8e456ec8, 0x3d40c58770231c0a), + (0xb986fdcd6522fa14, 0xbceaafec4cd92006), + (0x395ac6a53012f35d, 0xbcbe36dd57088c43), + (0xb90acfe289832416, 0x3c67199e80bb8ec3), + (0xb8d65ad3a5a6b128, 0x3c35ab8b86951bb2), + (0xb87d16fd2ded0f9a, 0xbbdfd7377ba12be2), + (0xb83aa7858e0cbb98, 0xbba9595b17afa78d), + (0xb7f5f340e3e25bf0, 0x3b51e6cee419b353), + (0xb7a44c40cb1a1e24, 0x3b18a74f87d027a4), + ], + [ + (0x3c2a5f1938003f5d, 0xbfc810f50225b04b), + (0x358a4e47631896a5, 0xb8fd56c48838f152), + (0x3c5462bc86c50f0a, 0x3fb7fdf97ac36b1f), + (0x3beaefb0d3d06c9d, 0xbf5c3c256a8caa05), + (0xbc191dbdbe4ca6d9, 0xbf7f98feb7286b47), + (0xbbcd0c6b4f6c3ad8, 0x3f25f6559e5686e2), + (0xbbd9de4a645cf978, 0x3f3080f57ac215af), + (0xbb69ed06d60efe89, 0xbed80c51397e5eba), + (0x3ae04eb6bd1f24a9, 0xbed256db543cd140), + (0x3b1af2db1b084be5, 0x3e7af7598a219824), + (0x3b0693a9fa38dfa0, 0x3e69398226ca2305), + (0x3a95f5676bd10cd5, 0xbe1260985d92587d), + (0x3a8d5612be0b4b05, 0xbdf792bb3eea6f6a), + (0x3a4432d95d96cbda, 0x3da0d862695e1a7a), + (0x39d7cd101d99d4e5, 0x3d7fe52adc2baacf), + (0x39baa545a1a5eb63, 0xbd263801377398f0), + (0xb90a458f0e1e2682, 0xbd005a1befdbe42c), + (0x39473f5560f8b44e, 0x3ca6205041739aa5), + (0x38f53ca728fe9101, 0x3c7a4e1503b6d0e4), + (0x38a22b93c20b3937, 0xbc213ef141f6d641), + (0x3854274bba40b623, 0xbbf10ccc96cd4c02), + (0x382225ebf160c143, 0x3b95a2fe023aea26), + (0x380398ff54fa8423, 0x3b6232d7c90d33bc), + (0x37acf10d8068ed39, 0xbb0656435697f160), + ], + [ + (0x3590c69d1d5ad990, 0x38fbdadd24cf38cb), + (0x3c62da0057f84d3c, 0x3fc70c511227d5aa), + (0xbbfb574e506cf75b, 0xbf72ccb0e97558da), + (0x3c2e61277dedf705, 0xbf9e7dc08e70e99a), + (0x3ba77952da42c6eb, 0x3f48acdc5b058c0e), + (0xbbf340f4df9939b5, 0x3f580503724ad30a), + (0xbba115f69745949b, 0xbf032ee4ca1fcafb), + (0x3ba6a66de44f6f2b, 0xbf01e5d2836c8d99), + (0xbb2b264207f7cf59, 0x3eac129f077bb163), + (0x3b3381f3bd8fb4b6, 0x3e9ef161591181a2), + (0x3ae466d818a45b43, 0xbe47b9bb07f19f82), + (0x3ac2d952a84a8f21, 0xbe316f3937595d96), + (0xba7571ae406938c3, 0x3dda0bc8665b687b), + (0x3a588295d4921561, 0x3dbba135f99a9e19), + (0xb9ff299934254ca8, 0xbd640d543d2cbdf0), + (0x3982fb1c3cc08579, 0xbd403d0592185f1c), + (0xb925c1461a28ff32, 0x3ce6db5e22d3be75), + (0xb939bcdb12fd3c24, 0x3cbd745a1f778590), + (0xb8f8314c949b4d69, 0xbc64141c4b5a4105), + (0x38a825ab0fff4716, 0xbc353f4e6ca53f65), + (0x387f0bb5f3376671, 0x3bdc09c1732e9344), + (0x3845a8dc1ed995e7, 0x3ba8f971fa1f374a), + (0xb7ce30cb1f02717b, 0xbb4fe39c23f51b6c), + (0x37b9858646741b7e, 0xbb1862f419e2ba54), + ], + [ + (0xbc6b166d180d579d, 0x3fc633e7f7f05301), + (0x356d48b037092f86, 0x38f9187186657edf), + (0xbc100659a075d9a7, 0xbfb6273784c1c06e), + (0x3bfcb74bd0872e23, 0x3f563ae94ade18d4), + (0x3c02a45d712a2f91, 0x3f7d4666536c88b9), + (0x3b825e9acb600ae8, 0xbf216d528345ca11), + (0x3bbb9405b8c58d57, 0xbf2ec0dcdbb7c5fe), + (0xbb7cb6e04f4b97e8, 0x3ed34e966b0b09f8), + (0xbb7a79e09bd0a7d3, 0x3ed135c64dc2d8d0), + (0x3b01284c6af65eda, 0xbe75f7bc78b5fc2b), + (0xbaf68597192a53a4, 0xbe67dc35b0764096), + (0xbaab08d1b3bdd3d7, 0x3e0e6d697361ea54), + (0x3a825acf92327a4e, 0x3df679e3704987b4), + (0x3a25a180ac4a289b, 0xbd9c595f278a4d6c), + (0xba0b8a094432fbc2, 0xbd7ea36aef56eec0), + (0x39c8d7c90342cb95, 0x3d22fd66b4e62185), + (0xb99cefe59fbb0bf2, 0x3cffa04c9faacec1), + (0x3947eb4362c2f94b, 0xbca32f47f03857d7), + (0x3912dc0b9f745208, 0xbc799658479ebb31), + (0xb8ab4e5c1533c13c, 0x3c1e4c26032e5de5), + (0x389fabe9c1dc18b3, 0x3bf0ab1b47f9c785), + (0xb83bf6eec6ed25da, 0xbb933a3c78295756), + (0xb7f90ac82d0d0179, 0xbb61de19b957005d), + (0x37ab71627757371c, 0x3b040e310c05ed67), + ], + [ + (0x35ac924d3bf8bf5b, 0xb900f098dc38e480), + (0x3c6a47ab4241a9f5, 0xbfc5664e13b70622), + (0x3c04d78c254f4422, 0x3f6e16555e108dc6), + (0x3c1fe75afd6ce0fa, 0x3f9c5e1ad9fb2f40), + (0x3be099fe50e43632, 0xbf43d369f958e56a), + (0xbbf3ed70de366684, 0xbf566f4ec27a96e9), + (0xbb9b30f071ce70bb, 0x3eff0de0532652d5), + (0xbb747f8eea3cc056, 0x3f00cf264341409e), + (0x3b4f2ff7c971467d, 0xbea6f46d51e5766f), + (0xbb3708c3f9c7bd34, 0xbe9d407f7c248d45), + (0xbaee70df563a5b0f, 0x3e43a33cd9df6696), + (0x3ad300d61c332fb0, 0x3e309901b0a816e5), + (0x3a69fdf1dd8c15b3, 0xbdd5d856a58443f5), + (0xba3f02f5ec08db44, 0xbdba7cbcd8fc0758), + (0xb9fcaa58f7c81511, 0x3d610b62c2fd47f6), + (0xb9bf896eb454c48a, 0x3d3f56a09da19f70), + (0xb97cb0796a5c153d, 0xbce3ae6849b36426), + (0x39389530ecefefbd, 0xbcbc977524a64328), + (0x390af889f4247b24, 0x3c617fc9db74cefd), + (0x38de6ffabef002da, 0x3c34bbe426d77a28), + (0x387b388027811ac5, 0xbbd8b5659628a8e3), + (0xb83cddf274f119b8, 0xbba87bcc22e21171), + (0x37ec559bf73a5d47, 0x3b4c62cff42626ad), + (0x37656c3911a78ec3, 0x3b1800b5df5b52ae), + ], + [ + (0xbc4f6f339127993d, 0xbfc4b71d4ca2cc69), + (0x359c1da4eb8655d5, 0xb8f3a018f8f76877), + (0x3c5422c1a1ae8ec4, 0x3fb4ae245697fba6), + (0xbbf4ff572c18742a, 0xbf5215e4e1a5f1d6), + (0xbbf259ec9ab217a9, 0xbf7b633ed6d9cf61), + (0x3bab33aa46f3e729, 0x3f1c7f17b4b7dbbd), + (0xbb79333ace27b68d, 0x3f2ce01b8b6aa34c), + (0x3b5f4e5e8507bc88, 0xbecfced71b11e35b), + (0x3b57f324d6293b07, 0xbed03c9d5823261d), + (0xbb15cd82948c15bb, 0x3e724508091063b2), + (0x3b02ba31739f7dac, 0x3e66a2d20111e303), + (0x3aae84f884334dbd, 0xbe0995a18f8e6888), + (0x3a67a35968d37628, 0xbdf572d1a074f647), + (0xba3a336c953bedde, 0x3d981df03c1911f1), + (0xba104dc5bcacab30, 0x3d7d6895e48f475d), + (0x39c36eea9cd69feb, 0xbd205887f0b3df78), + (0xb98ded8dfba53f0d, 0xbcfe86703ddf1bbb), + (0x394a6d81e9b745de, 0x3ca0b3c70ca73df2), + (0xb91aba894f18e42b, 0x3c78d28ba328c189), + (0x38aea5b88a7dff57, 0xbc1aa9275d6882a0), + (0xb88b4724ad7898dc, 0xbbf03e89774aa977), + (0x3836acf6717c7348, 0x3b911679204a4a38), + (0xb7fc2c9e5a53a6f2, 0x3b617bd36a04e549), + (0x37a2112e77b7283b, 0xbb01fc50745d8566), + ], + [ + (0x357f9e30ee0b6fbb, 0x38e84b55d671e3ab), + (0x3c6316f8ffd294bc, 0x3fc40f90793605bb), + (0xbbd411ad350e6def, 0xbf68c833077fbeae), + (0x3c051eb6f09db1a0, 0xbf9aa0ce0421d1a8), + (0xbbec0fe78acda469, 0x3f405fa598ef5d1d), + (0x3bff2085596ae958, 0x3f551d30d78ab526), + (0x3b92b31b33779fc8, 0xbef9c5807675c5f6), + (0xbb7cb5b0088841fe, 0xbeffc1bbf57e3ae2), + (0x3b3cc2b42d9f0f1a, 0x3ea32dfea2518ce6), + (0x3b18c85914c086a8, 0x3e9bc212085dcbc6), + (0xbaed44a5431df5e5, 0xbe408b946d64c5c2), + (0x3ac14bfc6bd39224, 0xbe2fa8f9d8da736a), + (0xba679104007a668d, 0x3dd293fe14af1d0f), + (0x3a2b5ef4a8a2fdf9, 0x3db96544cb75a58d), + (0xb9d2b2107643b642, 0xbd5d4750748e2ce8), + (0xb9d8369e87f01d70, 0xbd3e341812329072), + (0x398c6f9e47f04995, 0x3ce112aa495187a4), + (0xb950e224f8078ca7, 0x3cbbb1656dc67704), + (0x38e16eb1b3f03824, 0xbc5ea7b98f478c96), + (0x38b9cf2d9132a338, 0xbc342cad7eaaf63a), + (0xb82267864912b80e, 0x3bd5d798d87eadd4), + (0xb83715c9cdc64b23, 0x3ba7ec2199e9d0da), + (0xb7e050cf70a270e2, 0xbb494f3573e03531), + (0x379b105713845f41, 0xbb178a4eaef852c1), + ], + [ + (0x3c4f5ffd019535e2, 0x3fc37dfa8f5a550a), + (0xb5701036f2fd5ce7, 0x38d71a135ef735e1), + (0xbc5c4cd2161ee713, 0xbfb3775c1a04f09c), + (0x3bd3d562913301ed, 0x3f4e2b4810a46c60), + (0xbc1b976f3317abb9, 0x3f79d151a72b83a8), + (0x3bbcef8b523f5a0b, 0xbf17d8e5a090e4e6), + (0xbbcb7ef16d9cb057, 0xbf2b49a6427386a0), + (0x3b59248209e494f4, 0x3ecac10957ddd2eb), + (0x3b424396e09f7471, 0x3ececa620745d3d3), + (0xbaf3438d41f60802, 0xbe6eefc7e795dcdd), + (0x3ae3b35ebff03a32, 0xbe658c5d2a0da41d), + (0x3aa0b413dedd34fc, 0x3e05d4721f44a8f9), + (0x3a892a275db60362, 0x3df481ce2314af59), + (0x3a3feec436d1ef8f, 0xbd94c0d3279e920d), + (0x3a19e07a129c683f, 0xbd7c3ea707530563), + (0x39a52b925c059e39, 0x3d1c61d5b165f7da), + (0xb94e05a7550119da, 0x3cfd72bf189b67b4), + (0xb9108732c7d2e8ad, 0xbc9d427a9769e9ed), + (0xb91f784bb6f88124, 0xbc780c9653705698), + (0x38b8d964fc9666c3, 0x3c178e36fc02b9df), + (0x38865f872c0449a7, 0x3bef9a2c168b6442), + (0x38235589e9a3fa21, 0xbb8e71f82f6f0229), + (0x37fbb8f42441d570, 0xbb6111ac11e28162), + (0x377b5f7617aeeb8e, 0x3b0025a92b5f22a5), + ], + [ + (0x35952cb8f89f3c55, 0xb901222bb44bcf14), + (0x3c689d1f48185c7e, 0xbfc2f2072e638cf4), + (0x3c0f48257333acd5, 0x3f64df208bbd44f1), + (0xbc282c4cf012e7aa, 0x3f992bb5e1e159fc), + (0x3bb5967313b48e35, 0xbf3ba181c06897cd), + (0xbbea6566cfb06bed, 0xbf53fe9d5baa4a3d), + (0xbb98b4ff1892c87c, 0x3ef5d17602b01cac), + (0xbb84f1d79d1c68cf, 0x3efe26d3747fe829), + (0xbb47899cac28d06e, 0xbea0509768ab6ecb), + (0xbb30edc18e594fda, 0xbe9a70f232d9d06c), + (0x3adf4967ed4b405c, 0x3e3c509252de33f9), + (0x3ac643cb92fae2ea, 0x3e2e454fee07116e), + (0xba7c2d5f536fab40, 0xbdd0015b062ba125), + (0xba43993ecbbb44ab, 0xbdb860e95adf840f), + (0x39fd1ca7896c45b4, 0x3d59691e90f7d9c0), + (0x39bccb74999a40d8, 0x3d3d1ce7997b3c0d), + (0x397d856301e23d11, 0xbcdddcd1c54cee54), + (0xb958f0d58afd0876, 0xbcbacd10a03552dc), + (0xb8f2692f00e7abd7, 0x3c5b043a7a08961a), + (0x38a216228008b2d7, 0x3c3399ba2ef94a8a), + (0xb87b2260cea416f3, 0xbbd3650fec070f67), + (0xb84885e84e43eded, 0xbba7538b0e0444f1), + (0x37e7ac0e69e3062b, 0x3b46a2dce760f8a5), + (0x37b02054fc976f06, 0x3b1707ea3ba222e3), + ], + [ + (0xbc6b9fbd89653a0b, 0xbfc2768d29c69936), + (0xb5883d7e7aae0fdd, 0xb8ec8fe2d361f507), + (0xbc592c5350d4d775, 0x3fb271811730b0ef), + (0xbbcd42067c3280c8, 0xbf49a8df96a1225e), + (0xbbde819659787fc8, 0xbf787c81cf1c6fc4), + (0x3ba0986868518e75, 0x3f14549cdbb77978), + (0xbbcc0c937839cf2f, 0x3f29ed2568116e19), + (0xbb638a1daff4bf5c, 0xbec6e4136f033ace), + (0xbb692b821c2e6f36, 0xbecd53330316cde7), + (0x3af82b5a8a9ea4e0, 0x3e6a983b5782dfca), + (0x3b0d6817ea51c39b, 0x3e64952ba7c5a1dc), + (0x3a858779f386d0c6, 0xbe02df3ad6f82e0d), + (0xba85be3593e2be88, 0xbdf3a70f9a89d2c2), + (0xba32f63410f44e43, 0x3d920e086c17f5dc), + (0xb9feeb5c5526cc87, 0x3d7b29a554c1159f), + (0xb9b6a518f14f6a05, 0xbd18dbe08f4a9f69), + (0x396f8eba4a78c6ed, 0xbcfc6bd9fc45c380), + (0x390a2175db343220, 0x3c99ce5a735b2911), + (0x390e5b428d8e3c26, 0x3c774ade0ebbb04a), + (0x38a68dee1fa00957, 0xbc14eb88e02b008f), + (0x3835846ba71a1987, 0xbbeeb63f264071fb), + (0x38105020072f2234, 0x3b8b39319da680c5), + (0xb80e1b59bc2fb16c, 0x3b60a4325ae8cea7), + (0xb79ae8092aa3eb9d, 0xbafd11021ccd9832), + ], + [ + (0x359a05b7bb6a66e7, 0x38ff07a73b062717), + (0x3c51f9b16832f362, 0x3fc1ff5eec6a01cd), + (0xbc0f89ce0d1cb83e, 0xbf61e438b722c3b5), + (0x3c39a4b7b3ed5b9d, 0xbf97ed5fffc1c774), + (0xbbdc35d9a8dca8fd, 0x3f37b7997babd9ca), + (0xbbe39da4066981e2, 0x3f53081def9612c5), + (0x3b8551b9a497b582, 0xbef2c5f5edafc4e9), + (0xbb9dbae692eab5c3, 0xbefcc11a59e13739), + (0x3b351580930803f5, 0x3e9c2c3a1b8014a3), + (0xbb333a214b9dbd86, 0x3e9946d1dab7bd01), + (0x3ad8fc5f68299915, 0xbe388db61946be64), + (0x3ac5620984f97782, 0xbe2d04d33be580e8), + (0xba6d7f1c30d157b7, 0x3dcbe64386d2c5d0), + (0xba48b7e9cdf3e557, 0x3db77142e0e4497b), + (0x39fe42ca4fdc0820, 0xbd56458476679697), + (0x39cde02178f2e8a7, 0xbd3c15e96b25adba), + (0xb96d7f2805e659cb, 0x3cda545e6ec71d21), + (0xb95169031622e59c, 0x3cb9f0a9b74e034f), + (0xb8f6c8c4cb1d2951, 0xbc57f751eaad5943), + (0x38b9f3826864d2b2, 0xbc33083bfba900b3), + (0xb83ad0a2f62d2470, 0x3bd14f7886799e5e), + (0xb846ea6a99d583b1, 0x3ba6b8756a3461ea), + (0xb7bff8edb785364b, 0xbb44533c12e31410), + (0x37b9373ae2b3a681, 0xbb167fc01d26c703), + ], + [ + (0x3c54fa3fb220c497, 0x3fc194eba75b32f9), + (0x35968efa101689a5, 0x38fdc9a2706a3090), + (0x3c59f5fdd12caa11, 0xbfb190f7dc27362b), + (0xbbd96244746ca1b2, 0x3f462bb47a5c5f7f), + (0x3c106edbe0bb689e, 0x3f7756ef20f5d2e2), + (0x3bb1231bc44f6f51, 0xbf1198b0ba97ecfb), + (0xbbafcaf4935a1752, 0xbf28be8cf9358d55), + (0x3b341ada5c144f0c, 0x3ec3dd6f7c8cc3c0), + (0xbb22797862876f18, 0x3ecc09c80ee7f9af), + (0xbb04005395d49e04, 0xbe6728e46a451e32), + (0xbb056333198576a9, 0xbe63b91113508622), + (0xbaa195a6693f0d85, 0x3e0080fddad62bf8), + (0x3a8352e1bf38cbc8, 0x3df2e111e88dae1f), + (0xba2109236d67d65e, 0xbd8fbae88bdab215), + (0x39fdc60e2c5c7d37, 0xbd7a2a4fbea868a8), + (0x39b8e39633481264, 0x3d15f540e9769e8b), + (0x39976a66d79bb910, 0x3cfb74c0b2686df3), + (0xb92c1d434c75162e, 0xbc96eb75a7dd13a2), + (0x390c7fe154372598, 0xbc76910c1dc865c3), + (0xb8a43f5790d81d03, 0x3c12af36490b5c71), + (0x3886f89d2e40041f, 0x3bedd7036ea48d55), + (0xb82a048b55f91332, 0xbb88734f1fdd1068), + (0xb7dfa5ba1f878585, 0xbb6036af368c39fc), + (0xb7993db41d2f7ce5, 0x3afa3fd8a11def52), + ], + [ + (0xb5745b4e1af1b85e, 0xb8d7a991cf97ce2e), + (0x3c6e71c482be67bd, 0xbfc12dd57bf18ada), + (0xbbe9a8a827c4a2d4, 0x3f5f1e1e7f393e83), + (0x3c3286f932bea2b2, 0x3f96d9afe88301fa), + (0xbbd360330deffaa0, 0xbf34a538a482979b), + (0x3bef838ddd540b11, 0xbf52316250b4ae37), + (0xbb94c13fb3eaf5ab, 0x3ef05f11577b4627), + (0x3b6771ef99211bfa, 0x3efb86bad42fc220), + (0x3b1a6b7e5cebbbf8, 0xbe98a1b3a9e92749), + (0x3b32d778489fadef, 0xbe983dcaf3f8fcc5), + (0x3abceef7b37a414b, 0x3e3589a7ca5fdcf1), + (0x3ac97ff4495956a4, 0x3e2be3ee3298bb99), + (0x3a6770b1a9ab05ca, 0xbdc8913f1d0ff12a), + (0x3a430c1f9492528b, 0xbdb695c386660813), + (0xb9fd8f50c7d974dd, 0x3d53b25d364762e7), + (0xb9d664d160d01e32, 0x3d3b20c42e642ccd), + (0x397bc60dbe38d043, 0xbcd7650532b4f1e0), + (0xb920283e56ce5b47, 0xbcb91f514b70b40a), + (0x38fcae3e188ec691, 0x3c55661aac4dcfde), + (0xb8b0ad982f98ebec, 0x3c327b48d9478b06), + (0x38441168fe323c23, 0xbbcf11115f1e0760), + (0x383a0b5e44af3cea, 0xbba61f1bd02130ad), + (0x37eb4e4f03156997, 0x3b4254646f0f97c7), + (0x37b0ea6aa46492cb, 0x3b15f63be5634cd2), + ], + [ + (0xbc27736b1f56d701, 0xbfc0d0d36473e98c), + (0x356c9dc61ea15303, 0xb90248314540cb10), + (0xbc517d3bbb8e7764, 0x3fb0cda9974abe2b), + (0xbbe2a43b589b29f9, 0xbf4367f38f201c25), + (0xbc17d1323005eae7, 0xbf7656b75e3c242e), + (0x3b94b9f5a7acb7cc, 0x3f0ed82abf7489f1), + (0xbbcb0bedf1c81292, 0x3f27b4e5b83eeb36), + (0x3b0621247626b416, 0xbec171fd0fb670e7), + (0xbb638b7d64b281f7, 0xbecae62b4ad017fb), + (0x3b0b83d61a6ff722, 0x3e64648495a7b49e), + (0x3b05f0212db7e5c2, 0x3e62f42a577135ad), + (0xba76b0fd54cd9d5a, 0xbdfd286e7fa32656), + (0xba30ca02b11abb11, 0xbdf22dbcbf76a1c7), + (0x3a27e83235238ba2, 0x3d8c222accc0d2d2), + (0x3a056929761e3d77, 0x3d793fc7f6c8d355), + (0x39bc237122bbb790, 0xbd138c7e1f668eb4), + (0xb99070434bc7e0cc, 0xbcfa8e4efc6deb61), + (0x3935816fed04585f, 0x3c947e808eb72ce3), + (0xb91069ce4b7c1dbd, 0x3c75e0f075f73393), + (0xb8ab681bd123ab34, 0xbc10c866ba43aebb), + (0xb87344f73adf2486, 0xbbecffe1c0e02083), + (0x3821df2bad78c005, 0x3b86102f988e0a87), + (0xb7f3ec5f37bb8303, 0x3b5f96a57efd09fb), + (0x379def01809beed4, 0xbaf7cbac5fb57a91), + ], + [ + (0x35391b3b00fc7751, 0xb8c00dbc5df9a26a), + (0x3c61a13e2fee5687, 0x3fc076826cc2c191), + (0xbbcb789ffb667f58, 0xbf5b62885e0070c6), + (0x3c35dbe9d7210c2e, 0xbf95e7f53001e4b1), + (0xbbddb8eb1d2032f3, 0x3f322ebeb8dc2202), + (0xbbf72618e87154fc, 0x3f517444a7a04cd0), + (0x3b7b01e81c8c370d, 0xbeece06f1f1fcd7e), + (0x3b80168184fb2a2f, 0xbefa7006e6ad9cfe), + (0x3b13ac36b9efbb35, 0x3e95c42f02cf15ca), + (0x3b08b69b698a2f2f, 0x3e9750ca5e1366b4), + (0xbac08a205d6fbd27, 0xbe3314982df7eaa2), + (0x3abf2c98d7c5b0b0, 0xbe2aded75306b3b3), + (0xba2551d965dce668, 0x3dc5d47847d8ebf1), + (0x3a2b475ee50f9af2, 0x3db5ccf44d287a21), + (0x39d9490ac846b5fb, 0xbd518fce3e04028a), + (0xb9d525cc1707dd4e, 0xbd3a3d6bcad0c3fc), + (0x39615f1fc81188f8, 0x3cd4efbd76727c05), + (0x3954cf183e4c6eef, 0x3cb85a4b163fcc04), + (0xb8eb35201a650448, 0xbc5339ddeca79d0a), + (0xb8df2fda8e574f19, 0xbc31f48b47bc4419), + (0x384d7bc59effa619, 0x3bcc06bd6710b45b), + (0xb84a385b5ed821eb, 0x3ba58a1ad9e65449), + (0xb7c4e5225bdf41b3, 0xbb409abe2b8be0ed), + (0xb7ba1343bcfa4e16, 0xbb156e575d965e88), + ], + [ + (0x3c61a6e02553980f, 0x3fc02455675ab6d2), + (0x35884b224ed40dc9, 0x38eb5eb0626a64d4), + (0xbc5a58b3083e7e3d, 0xbfb021c155a720df), + (0xbbea19c1039d30bd, 0x3f412be56fc1449a), + (0x3c01bad3e8f9abb9, 0x3f75749d556ad61c), + (0xbb75621370147dfe, 0xbf0b51f1f9bea93e), + (0x3bc81ccb29b6a851, 0xbf26c96a07e236bd), + (0xbb218064e9ecad2c, 0x3ebef3a7abd5ac6b), + (0xbb6f6ed0aeaecba4, 0x3ec9e207c257433a), + (0xbaf0aed16a93326e, 0xbe6220b96eef8058), + (0xbad4d7e3d546f2c4, 0xbe624317cb296737), + (0xba91f73fb3d22bed, 0x3df9fc2f2cd3917f), + (0x3a9403e6cf9143a4, 0x3df18ae8347e8256), + (0x3a2f17c7d5411c26, 0xbd892540423f2dda), + (0x3a04a4080028f5b2, 0xbd78687dcdc2e3a9), + (0x39a201bd34791753, 0x3d1187909103d474), + (0x39844a97e12dfc96, 0x3cf9b8362872c324), + (0x393da5147587382e, 0xbc92711ecdaaeca0), + (0x38fae8f5aa2732b8, 0xbc753b342a24814e), + (0x388ad67623e40669, 0x3c0e50eba2ee4760), + (0xb86ad1f354cf2e6b, 0x3bec32aa5f596a62), + (0xb8257b3c1a8fb2c7, 0xbb8400cf17d2fcd3), + (0x37f2a48d3485143a, 0xbb5ec6ef456ce7f9), + (0xb79fa0988ef64e6e, 0x3af5a82ff0aad8bd), + ], + [ + (0xb57640b478e02a1f, 0x38d6a301383ff88d), + (0x3c5d7cc4171715a0, 0xbfbfa8b41711c83a), + (0x3bf6219a48a25ba1, 0x3f5857d3969997d1), + (0xbc395ccf34fc85bb, 0x3f9511c6dadaaa12), + (0x3bd13cc55ae24369, 0xbf302c289dbdbd4f), + (0xbbde8aacf935744f, 0xbf50cc2238d229f9), + (0x3b831f1c91d27574, 0x3ee9b64d5c63668f), + (0xbb967f7ad529fbab, 0x3ef976fb023f0f79), + (0xbb26431725df20f0, 0xbe93693ba0b5ba70), + (0xbb30bc5202714831, 0xbe967b952987350c), + (0xbadfac3d160cee71, 0x3e310cb79a2addac), + (0x3abbc10a636cca3c, 0x3e29f2079f8e397f), + (0xba6f1f3686791203, 0xbdc38d957eaa53ad), + (0x3a5a464b4d5f0cbd, 0xbdb51511e93ba74c), + (0xb9d76cb5fc51dd5d, 0x3d4f8bb4d9d2f3a4), + (0x39d5f6bc31063165, 0x3d396afe82155a3c), + (0xb9789c1d34756db7, 0xbcd2dc3c5a412fc8), + (0x394e5ac9a5d43674, 0xbcb7a1c8dec76ff7), + (0x38fa62b937a855d9, 0x3c51600c3d779ccc), + (0x3891168a3d883e25, 0x3c3174c64bf0b16a), + (0xb8380d11dc898cc6, 0xbbc969e37524ef7c), + (0xb8337a7c5fb777c9, 0xbba4faf03e3cc2d5), + (0x37d9f91b76239dc9, 0x3b3e37a63e276939), + (0x37b81fff9e082645, 0x3b14e9f8e51a9731), + ], + [ + (0x3c50e4250a158a22, 0xbfbf161d0c28b48c), + (0x3588b2630fb1ecb4, 0xb8fcdc55525190c5), + (0x3c421e360c4c70dd, 0x3faf11d837aa6f64), + (0x3bd18f48c3547c45, 0xbf3eab76da4d07a0), + (0x3c1ebe3b9893ac4d, 0xbf74ab329f067aea), + (0xbb5e80c3b0d6f6c7, 0x3f086ada57bc1c51), + (0x3bc03960ef6e6bc0, 0x3f25f6e78f11ab9a), + (0x3b5e77180c5644f6, 0xbebbb271f54c8965), + (0x3b5cfd1d7da5a2ee, 0xbec8f85328c26cb7), + (0x3b05a5d710343230, 0x3e603f82aebdeac1), + (0x3b008f5133b080df, 0x3e61a3010279a195), + (0x3a8746b6f6e07b70, 0xbdf75660809cdedf), + (0xba824b566432a315, 0xbdf0f6931774a05f), + (0xb9f3c0bb6b052f2c, 0x3d86a2e61267070b), + (0xba1950de7a0ba4a4, 0x3d77a2a8e0311c3a), + (0xb9a048f7d1f2b252, 0xbd0fa4c8e3ce0140), + (0x3973ca66f22df187, 0xbcf8f1926f4e33ae), + (0x391f7bbe0252e068, 0x3c90b165b2615bc8), + (0xb90630bee239e401, 0x3c749fd329a93d0e), + (0xb8723f37b0afb367, 0xbc0b864a393597bd), + (0xb88ea6b58b8f277b, 0xbbeb70236cfe6bd6), + (0xb81ff9b7e892d837, 0x3b823801bcba96ae), + (0xb7f460e58de7fcd8, 0x3b5dffc2deb31092), + (0x379c28f920f7c081, 0xbaf3c9fe3b84a659), + ], + [ + (0xb57bd9f791078c7d, 0x38d74664ec9bed14), + (0x3c0020b4016594ac, 0x3fbe8727daa3daed), + (0xbbea4d873618788f, 0xbf55d353e2854a37), + (0x3c3361836c532514, 0xbf94524d4813cc25), + (0xbbb70735fa989563, 0x3f2d037574e28370), + (0x3bf7f1d7c0f30b41, 0x3f50356bb747a763), + (0x3b73015c07f2d91b, 0xbee7156bfccef376), + (0xbb99523f4f9b3609, 0xbef896d7dc819faf), + (0x3b307f0e451ebc2a, 0x3e9172c6dadf4149), + (0xbb334d6933f971d7, 0x3e95baae8efc2e31), + (0x3aba01d72c453106, 0xbe2eb347eb4d6941), + (0x3acc3dd30f660e51, 0xbe291a60a72a20e0), + (0xba0f68f511402a90, 0x3dc1a345a9a6a5f7), + (0x3a3173892dc95a66, 0x3db46c56b01906be), + (0x39d1db37247899b5, 0xbd4c84bb37677838), + (0x39de56935f64b195, 0xbd38a83e6e4c168c), + (0xb968986bb0f698d5, 0x3cd11796d017a52c), + (0x394e35cdfe4ad2e0, 0x3cb6f5675cf3bead), + (0xb8e0c38450c266b7, 0xbc4f936d06630982), + (0xb8da35936b142aeb, 0xbc30fc2f8042c9f9), + (0x38692f73e25e293e, 0x3bc7281c276f90d6), + (0xb8390095011ee718, 0x3ba4725b73c87824), + (0xb7a6c2d5c298847c, 0xbb3b9d22918ceeba), + (0x37901e1a341f19f8, 0xbb146a436f16dfe0), + ], + [ + (0xbc5b4c98f0d3c4c3, 0x3fbe0357c158b119), + (0x3583cebeaacf2fa8, 0xb8efc7d3f760c89c), + (0xbc410072ccb88630, 0xbfadffc2fc1a91f5), + (0x3bd769e0c0dbfe1c, 0x3f3b9b82ae07da44), + (0xbc02d8dbfa194096, 0x3f73f64e05320ac6), + (0x3bafe44f6e4f7a6d, 0xbf05fe4b66cf19d9), + (0xbbc540e88468d2a5, 0xbf2539518e1b00f5), + (0xbb397c60f4bd9fcd, 0x3eb8f8d01c487905), + (0xbb5e1765287d55c8, 0x3ec825045b97e2dc), + (0xbad349d279137fbd, 0xbe5d565f3bb61dea), + (0x3af6ef17211ae45b, 0xbe611186586f4f74), + (0x3a9d5c753068eefb, 0x3df51a669158191b), + (0xba9c8af441d79379, 0x3df06ef52f6715ac), + (0x3a0be37a7ebfa57f, 0xbd848215e95caa77), + (0xba12aea2c5547dd9, 0xbd76ec8422019b0d), + (0xb995ce432bf4ea43, 0x3d0cbaf5fc139339), + (0xb9937ae255b6301e, 0x3cf8393ffa4f5afd), + (0xb92ae7fb140219c1, 0xbc8e6232fb7e093b), + (0xb8f4f418e0ddb215, 0xbc740e69bcb200c8), + (0x38ab0659f3e0af92, 0x3c091cd1de02ebf5), + (0x388ccf22ef87b9fa, 0x3beab86d72560db8), + (0xb82e0b1ad1c5038b, 0xbb80aa949dd60551), + (0xb7d9ff00c88f4aa2, 0xbb5d41db239438ec), + (0xb79bfe1d2d6ef829, 0x3af2270328ec903e), + ], + [ + (0xb5ac5e4a2e275705, 0xb9005c1969d4e17b), + (0xbc5cb1f28997ca39, 0xbfbd8293aa55d18f), + (0xbbd0e0b711c0f01a, 0x3f53b6beb83f2596), + (0x3c36c091c5e2bd3b, 0x3f93a5ccbc12a67b), + (0x3bc80bb5066b1aa8, 0xbf2a3765d26aa42b), + (0x3bc464654b3f4248, 0xbf4f5ab33748c215), + (0xbb86c3ad1bc53ee0, 0x3ee4df6f1c257a5c), + (0xbb9372510d6e3ed7, 0x3ef7cbd49c315be0), + (0x3b1dfc7e29b94af4, 0xbe8f96098cf07175), + (0x3b0aec3564d78716, 0xbe950b37dd43531f), + (0x3aaa5efe8cd0d0ca, 0x3e2bd2e6405c605d), + (0xbab9fdafce391124, 0x3e285530df0d4b70), + (0x3a6ec037594c88d5, 0xbdc0029e21930f25), + (0xba5f6bee6aa06bbf, 0xbdb3d11aeba731a1), + (0xb9ee33d66b9efc78, 0x3d49ef077e065d17), + (0xb9c765f6255cb3d1, 0x3d37f3d211d80ca6), + (0xb95ffeb5c7b606b6, 0xbccf2617ced04ef7), + (0xb95d433df855b01a, 0xbcb654785f90474d), + (0x38a47f029dbdf48b, 0x3c4cd5d490baf361), + (0x38d6ed83985660af, 0x3c308aa98d1885fa), + (0xb81200c557f40391, 0xbbc53243b8f4a2ce), + (0x384da8d1f6aaa7a2, 0xbba3f0a1e04e0f85), + (0x37ce2a379bc1d480, 0x3b39568fa5547980), + (0xb7a7c00b2c409082, 0x3b13efd3e10a8faf), + ], + [ + (0xbc57ac02118ce034, 0xbfbd0b36e5737458), + (0x355dad3277703540, 0x38d5fb77d2e0e26b), + (0xbc494ec699987c67, 0x3fad082ce3c6b59b), + (0x3bdbdb6b7d6d9ed8, 0xbf3905d00c5e6800), + (0xbc14d8fddd68c49d, 0xbf7352b073fdac7b), + (0x3ba8a390eb7c2b92, 0x3f03f1ccfec2fc88), + (0xbb8f7492cb6fd0c1, 0x3f248d74583834bc), + (0x3b536c4ae37b379a, 0xbeb6a9ef0d896bae), + (0xbb686d0e0d1bf502, 0xbec764d9798d6a80), + (0xbaf460a4621e034f, 0x3e5aa785d6736f5c), + (0x3b035fd3f6a4b201, 0x3e608cae36118cdb), + (0x3a9d857819eb2176, 0xbdf332ddfb39cd01), + (0x3a737fa058aa2bf7, 0xbdefe502ff1a8f0d), + (0xb9e58926244b72c2, 0x3d82afc83348eeb2), + (0x3a12be94371e2b16, 0x3d764468c0a31511), + (0x39a6e4a5223f4dab, 0xbd0a399e849c3f2a), + (0x3993f30753f88192, 0xbcf78e09772ae1e8), + (0xb90378dd4b889265, 0x3c8bc9dea67a7452), + (0xb90f40c403d002cc, 0x3c738663e180417e), + (0xb8a2c55a9de7b5bb, 0xbc07042a23846064), + (0x3863528c0f407011, 0xbbea0b467e151132), + (0x38083d5af6007837, 0x3b7e9e53f034f206), + (0xb7fe52cf6cca2436, 0x3b5c8d6dc762abf9), + (0x3781845e75790839, 0xbaf0b68e9fe150d5), + ], + [ + (0x359b9f4f66331222, 0x3900369fa71bf644), + (0xbc49df1f0f8d2108, 0x3fbc96700bf039e2), + (0x3bd298b7ed2d16c5, 0xbf51ec0b5de4befe), + (0xbc26397704521ddc, 0xbf93095734a24496), + (0xbbbe43e747e8c9b8, 0x3f27d74e12285cb2), + (0x3bbff97a4e7e808e, 0x3f4e636fe259352c), + (0x3b74153b68748e94, 0xbee2fe11972bc0c6), + (0x3b833d879080abe9, 0xbef712e4d44c4a74), + (0xbb0f13d0520649e9, 0x3e8cc3adabae0452), + (0x3b2bb2db97d7803d, 0x3e946ad2d9cbeb5c), + (0x3aba423494626154, 0xbe295d81ae83f621), + (0xbab425671ce4734d, 0xbe27a02aefea3d60), + (0xba5a8cbe07596457, 0x3dbd3a949a72239d), + (0xba589ce4399c7b23, 0x3db341e0bb193b49), + (0x39c60f1c6ee12738, 0xbd47b550a4f77497), + (0x39b9524731c89f4a, 0xbd374c654a2656ac), + (0x396b773706300926, 0x3ccc861736a2cb66), + (0x393ffcb4d6c5437c, 0x3cb5be2db467cb27), + (0xb8d79e659806e4b3, 0xbc4a7433021b81a8), + (0x38d24a44d0a8359e, 0xbc301fe901a012cf), + (0x385ca56d7686e059, 0x3bc37bf8ae8852f8), + (0x3823e08435643d0a, 0x3ba375bd0bad91a1), + (0x37af4610bb7d3555, 0xbb37570ac69055a0), + (0x37aa35e716b3a1f5, 0xbb137aed9b4389e6), + ], + [ + (0x3c2c279ff462c3c0, 0x3fbc29ae8400a320), + (0x356e0e33fd319cb9, 0xb8d9231986c55c3a), + (0xbc47ac9bcf34430d, 0xbfac27138da31c2b), + (0xbbbe5ab192b0135a, 0x3f36d141fcbea853), + (0x3c12b724fd75b152, 0x3f72bdc71062acd6), + (0x3baf5f2a5ef8fa68, 0xbf0231cf643ffc17), + (0x3b6e53f54e3bf9fc, 0xbf23f0bf3b3fe8be), + (0xbb4cfe2b683d9564, 0x3eb4b05e955de175), + (0x3b6d19f537fcf89e, 0x3ec6b52b868fa5e2), + (0x3afd6a6cb52830e5, 0xbe585a7aa3e84cc3), + (0x3afd15d476513524, 0xbe6012d3384c9164), + (0x3a5b65df2e4e4330, 0x3df18f8c4872544f), + (0xba81d06080a51e9d, 0x3deeffc4029f2f06), + (0x3a249fcb796b8760, 0xbd811d5a3daf70fa), + (0x3a00e5fc84cbd7e0, 0xbd75a8d84ce12a33), + (0x39aac0f727b50a5e, 0x3d080dfa27f213b4), + (0xb98deba8bfe45bc0, 0x3cf6eec07f1e9fed), + (0x3926f40f27003ad3, 0xbc8987d6f3b6b977), + (0xb900c69dbdeb6cd7, 0xbc7307196963d259), + (0xb8970cc24a5ffc69, 0x3c052f0ef3a48697), + (0xb82c63f97263dd39, 0x3be968357fda6848), + (0x38062270d5c769fc, 0xbb7c3bf907642446), + (0xb7f7074e3e5184fa, 0xbb5be25cb690eabb), + (0xb76e99e1fa5b8f27, 0x3aeee27d7ef3ffc0), + ], + [ + (0x3538ee4168591cac, 0x38bef99392c87f53), + (0x3c58fff4515190b5, 0xbfbbbf246914235f), + (0xbbb59d638f727e96, 0x3f5062daee35411a), + (0x3c1bef9e896a9a49, 0x3f927a96f174b6d1), + (0x3bc79c688e785f3a, 0xbf25cdb5dea9c121), + (0x3bd1f78082ebf798, 0xbf4d818348f98a0f), + (0xbb8cf93ea6c33ca2, 0x3ee160aab829409d), + (0xbb9dfe5ed028776c, 0x3ef6698d6ee99eb9), + (0xbb0db3033371a004, 0xbe8a5633d8f0b3bf), + (0x3b3148bb33e218be, 0xbe93d788d61154a7), + (0xbabbfbbbe3dfb01e, 0x3e273ec2ae0084b9), + (0x3a5bb0a12307343a, 0x3e26f958f6235deb), + (0x3a36a5b33f99627e, 0xbdbad0939c43a9fe), + (0xba4257e147ffea34, 0xbdb2bd56309cf195), + (0xb9e2488ea9163776, 0x3d45c709d717f2e4), + (0xb9d93a6f276892ca, 0x3d36b0b8fe737496), + (0x3964c91263a6ad47, 0xbcca3cece6eae9d2), + (0xb95aac081c12d91a, 0xbcb531b157cc8875), + (0xb8e3db9a4bc40ecb, 0x3c485f3495a556d9), + (0xb8cf57e3f8bac92a, 0x3c2f771622298662), + (0xb86da2770d25e277, 0xbbc1fb1e956ae1b4), + (0x3836de845e2a3207, 0xbba30179264b3e35), + (0xb7dd698f3e703bcd, 0x3b3593d8b3319ae7), + (0xb79dcfbbb66501cd, 0x3b130b99b87c3b97), + ], + [ + (0xbc4b1bd5a08c4698, 0xbfbb5b8273b75055), + (0xb579007ca42ecf31, 0xb8f30640d843b3e4), + (0xbc19066393ec82d1, 0x3fab59418c36a684), + (0x3bd4c6e4a4b62a0c, 0xbf34eafeaa92aa79), + (0xbc1e8c2463f82477, 0xbf7235801af9be44), + (0x3b9bcf2d21045067, 0x3f00af9747d0be92), + (0xbbaf406893c94ac9, 0x3f23611db0e1566f), + (0xbb5fa294e3a6cf5c, 0xbeb2fbe414da1250), + (0xbb6579c1dd810ff1, 0xbec613ccbb9cbe59), + (0xbafba31f9ef26cbe, 0x3e565cf274e84d31), + (0xbae9213eec3645d6, 0x3e5f452996e3dc2b), + (0x3a93719707a6b39b, 0xbdf023f5382da3ad), + (0x3a83d3a0c57bd4cc, 0xbdee2be24fbad63f), + (0x3a1e0d9a1a424f4e, 0x3d7f7ed3740f8cf5), + (0xba195448240988be, 0x3d75187e998a1997), + (0xb9a83d289fab0c82, 0xbd06293c9e781b76), + (0x399920ae46c70e84, 0xbcf65a49786c4515), + (0xb9223154eb869eba, 0x3c878dbf0233422a), + (0xb8db7350f762522d, 0x3c728fde2c70ddb7), + (0x389a86a79f193b5b, 0xbc0392b8f6167154), + (0xb883a3fc81fa37b9, 0xbbe8cea59f44a3e2), + (0x37d28560a2d0c913, 0x3b7a213dbaca9263), + (0xb7672b5585eddf9a, 0x3b5b40576765c08e), + (0xb78ee5530750cce7, 0xbaeca1b39264a34b), + ], + [ + (0x359f12f74a1a873e, 0xb8fd67b1800cc2aa), + (0xbc5024304247ada3, 0x3fbaf9cb49c4f935), + (0x3bd43675d81a390c, 0xbf4e1d930b513228), + (0xbc26b1ae600584f2, 0xbf91f7a8fec6eba8), + (0xbbccaafb65ee566e, 0x3f240a55310866fc), + (0xbbe93eb318fc691a, 0x3f4cb20c812fd3aa), + (0x3b7bc11f6acb6aed, 0xbedff51953c6b6cc), + (0x3b7ca6d60de07627, 0xbef5cdc48f5d75eb), + (0xbb1e5c798f5702c3, 0x3e883b091952c721), + (0x3b392f384e40f60f, 0x3e934fb685e58ab7), + (0x3abc9afeb4201722, 0xbe2566fc4369ab71), + (0x3ac8555b1f6751cc, 0xbe265f0f7de29720), + (0x3a505976fb73241a, 0x3db8b61e5f9b7a00), + (0xba04a898dd824080, 0x3db24253069b78a9), + (0x39bb5929dac6aff0, 0xbd441732d722b422), + (0xb9d662b0ae22d5ef, 0xbd361fa985a16926), + (0xb92bfd8dca36b2a6, 0x3cc83c175673059f), + (0xb956fcc071485aba, 0x3cb4ae32974df1c6), + (0xb8d5a8f989475dc8, 0xbc468a7f73f5be7c), + (0xb8c1d7200f0ee470, 0xbc2eba46ae458bcc), + (0xb8686a635728619a, 0x3bc0a770636ddc81), + (0x3846e16decd06b9b, 0x3ba29388d9fcba28), + (0xb7da9125321029a4, 0xbb34040dedb7bebe), + (0x37af7783c5802665, 0xbb12a1bc8335b315), + ], + [ + (0x3c5ffacf3e2418f7, 0x3fba9e13a0db6429), + (0xb583910dd6018bba, 0x38e353089e99116d), + (0xbc305f5aef327444, 0xbfaa9c1ca2161b9b), + (0xbbd5ab98ac97faea, 0x3f3344a09efdc635), + (0x3be8bf0e556cf4b8, 0x3f71b82c430a2381), + (0xbb93a99455084734, 0xbefebfb97bca01f2), + (0xbb99136a1ed7b5f9, 0xbf22dcdb1bc1d038), + (0x3b5ea30ecc612715, 0x3eb180047f0b79ae), + (0x3b46ae074e2d9e22, 0x3ec57eeeee84d0d0), + (0xbadb1941bb0e0bc1, 0xbe54a0c699c8318b), + (0x3adc2d735741fddf, 0xbe5e7594e8a2c760), + (0xba8de62221d00ec8, 0x3dedccbbb4c0ba7f), + (0x3a8cf847ee673438, 0x3ded6766337b5c95), + (0xba0200bd41d3e51f, 0xbd7d1a05cea18a02), + (0xba1f3622c8b76f5f, 0xbd74922fb50a29f1), + (0xb99416959af186e5, 0x3d047fa35bf627ce), + (0x3983729747e80125, 0x3cf5cfa087122294), + (0xb90144302fbdaa10, 0xbc85d009937bf5ab), + (0x3907a8b2df9e5ac3, 0xbc72200b01fdbf9d), + (0xb8a0a7e595a1fb47, 0x3c02265f004c1d49), + (0x387e52805deaab21, 0x3be83df71ae8ab7a), + (0x37bb19a9df1aa0a8, 0xbb7843800001ddf6), + (0xb7eb3ebd0a11156f, 0xbb5aa6f0e2f25140), + (0x37780a266a5c06bb, 0x3aeaa04878c515a9), + ], + [ + (0x357a12f34662767b, 0x38ebd844c546d1fe), + (0xbc55d35a88f1e0a3, 0xbfba4407e04298d1), + (0x3bdf6dddc07add4c, 0x3f4bcc9df0cf00b2), + (0xbc3c3cb8ccc39cf1, 0x3f917f0266db2149), + (0x3ba3d974ad0c21fe, 0xbf2280a052234a05), + (0x3bb902b669103937, 0xbf4bf2ada1f44071), + (0xbb64ad3fa1509171, 0x3edd83d58032b48d), + (0x3b3d6efd0446126a, 0x3ef53dd972d8f232), + (0xbb230c11b6006891, 0xbe8663c1fe202028), + (0xbb26dbba4ce8bd7d, 0xbe92d1fbf2203ff6), + (0x3ac866e6e348b7b7, 0x3e23c9f0b759c5f9), + (0x3ac489ff33dfce8f, 0x3e25cfe1b012696d), + (0x3a4981337ac7965a, 0xbdb6ddc0795781e9), + (0xba4b13e076398cc3, 0xbdb1cfd49504266a), + (0x39edb765a45cfad5, 0x3d429b7af5214fbc), + (0x39bd594b3ede144b, 0x3d3598302ab3ac8a), + (0xb96436f0bc69940b, 0xbcc677f6a604ab42), + (0xb95aaa7d20415d1b, 0xbcb432ecc122bbc3), + (0x38b6c227de389245, 0x3c44ec114bfb6bf7), + (0x38b8822ee44d55d6, 0x3c2e0887f8c2f57d), + (0x38569ce3e7c211fb, 0xbbbef44a37f84f12), + (0x384d44f14e9f294c, 0xbba22b91f5f4449b), + (0xb7c6e331300713b4, 0x3b32a03f80301aa2), + (0xb7bc71f13c4d9d35, 0x3b123d23f8f7ad2f), + ], + [ + (0x3c423404089aea01, 0xbfb9ef3bb2213b0b), + (0x3564b334f22dc8c4, 0x38ec7aef8237b6d2), + (0x3c342c5cb51f2b57, 0x3fa9ed82007a9a45), + (0xbbad41b75b8a8df3, 0xbf31d2fdeeb29f8a), + (0x3c189945952fed1e, 0xbf71446866ff1b83), + (0x3b94bf0ff761bace, 0x3efc73b684f93259), + (0xbbc79edfb80bfc5d, 0x3f22628de594b6c9), + (0xbb2bef93c666f4ba, 0xbeb03303c1427449), + (0x3b69194ecd6aac53, 0xbec4f51007c51087), + (0x3af53d1fa2147ee3, 0x3e531adfa36f2213), + (0xbafbf005f05fcc98, 0x3e5db4f306b19095), + (0x3a88f72949d1398a, 0xbdeb9e33598f899e), + (0xba8457c3274ebd59, 0xbdecb09ed6ecb896), + (0xba159f6f24f8986e, 0x3d7afe1183148a99), + (0x3a11bfaf9fbcb95f, 0x3d7414e442aa8d57), + (0x39ae38a755a019d9, 0xbd0307c129418397), + (0xb99de6576700d7e4, 0xbcf54ddabca7b729), + (0xb91f28f4f591d3f4, 0x3c84455c62381679), + (0xb913f1c98ec45b97, 0x3c71b70264da382d), + (0xb8a8129bcf1d63a0, 0xbc00e2cfa963d4c5), + (0xb8879c81e5b960aa, 0xbbe7b5896de3457b), + (0xb8030217c1f78b40, 0x3b7699efca5cd8c8), + (0x37e0b0e37cbd943a, 0x3b5a15ae188cedc6), + (0xb78b8997136a2cc2, 0xbae8d5720aed06a6), + ], + [ + (0xb59a217cd5a5fc59, 0xb8f8cb0a4bb92b1c), + (0x3c5728ab934a26a0, 0x3fb99be744018c90), + (0xbbdb8852614fe858, 0xbf49c3f52a2af724), + (0xbc2f281d89ca12e4, 0xbf910f5ca51f98b0), + (0xbbc3c6681ac39db5, 0x3f2126c8e8ca2766), + (0x3babb471b2b6cf3f, 0x3f4b416f7d4fc313), + (0xbb677b33eb16cea4, 0xbedb5e2e5580e1ce), + (0xbb988d4663776f74, 0xbef4b862279de756), + (0xbb2b43c42f7f04bd, 0x3e84c5071b39dc13), + (0xbb3de6264de806d7, 0x3e925d2fc3b19021), + (0x3ac879393dd83f28, 0xbe225df322279972), + (0xbac3ec23ad6e970a, 0xbe254a971eb6fe3b), + (0x3a5048109b74bd8a, 0x3db53cc6c9922f2b), + (0xba43610ec595546e, 0x3db164f95180d8c1), + (0x39e236638a339577, 0xbd414b9ef404ed89), + (0x39d5e32a69772db7, 0xbd3519623b4e50ac), + (0x396ac2c256389163, 0x3cc4e7271a71f23c), + (0x39593e237428a68a, 0x3cb3bf2a1b859197), + (0xb8e5a9f4a410aefa, 0xbc437bc0d8e44b83), + (0x38afa844b04c9f72, 0xbc2d6104b94c47d8), + (0xb85bd976332a8ad4, 0x3bbcdb4b3544bc80), + (0xb81ec0f06119d6f0, 0x3ba1c93567462aba), + (0xb7dbdd21527e43db, 0xbb31623ef293806e), + (0x37b58068411a8ada, 0xbb11dd917bc85327), + ], + [ + (0xbc54096ec8637e04, 0x3fb94d3276914e51), + (0xb599a52e7e447fba, 0xb8f7c4d3a1091c64), + (0x3c4baee1d6c0d38b, 0xbfa94bac1950e319), + (0x3bdbfe3ad50b1c19, 0x3f308d4ff8f2059e), + (0xbc1cca1c2770b225, 0x3f70d90d29bfeecd), + (0xbb987fee6225f412, 0xbefa6d56162f7fb4), + (0xbbc7e723313bf860, 0xbf21f107da23807d), + (0x3b42cbddeb0faca2, 0x3eae1a626277437b), + (0x3b665fad37433b79, 0x3ec474eafd0cc642), + (0x3acb91aaa2286db9, 0xbe51c27144f42d78), + (0x3af7189d5fa17ee0, 0xbe5d01999b1a4fe9), + (0x3a35f0e0348c776a, 0x3de9b014801da87a), + (0x3a8958b840cda80a, 0x3dec061740bc8a45), + (0x3a16875708b7d88b, 0xbd791f8c2972547e), + (0x3a1c0289b9700b84, 0xbd739fb558b7aa4d), + (0x39a9d6b95b5ce534, 0x3d01b9f74d47b35f), + (0x3992cf3210e813d7, 0x3cf4d425557e1f1c), + (0x392e1b1b93526a26, 0xbc82e617ae27952e), + (0x3913ab3cd31920c7, 0xbc715432898c29d0), + (0x3894feceefbf4d3a, 0x3bff843f6347963f), + (0x388afc3194a2db07, 0x3be734c130fc648e), + (0xb81e9da93ee8d83a, 0xbb751d395949afbc), + (0x37d1fb7f6ae8afc8, 0xbb598c0f03028f01), + (0x3751f15d40f7c19d, 0x3ae739cc4684a5bc), + ], + [ + (0xb568e6ce9dddcc62, 0x38c846638d0f2565), + (0x3c5e213a1a4b3671, 0xbfb8ffc9bd24fe08), + (0x3be5e8a5d70cf555, 0x3f47f7d46ab33721), + (0x3c2f532ddb23dab4, 0x3f90a7a725d3fbc4), + (0xbbb3f089aa8f2adf, 0xbf1fea1728f216b4), + (0xbbdf63ef3319327c, 0xbf4a9cac69f0ed64), + (0x3b78f775cf86e9c6, 0x3ed977f48ff1056b), + (0x3b8a77447ea6fe43, 0x3ef43c2d8e698c10), + (0x3b293f5e91559672, 0xbe8355d1a6765ea6), + (0x3b177401cf3aa17c, 0xbe91f0553501d121), + (0xba823a3e8101b9d1, 0x3e211b47f6a44829), + (0xbaa6a02fffa2b5eb, 0x3e24ce23303889a9), + (0xba42b03ad2eec174, 0xbdb3ca98df62221f), + (0xba50afdcc563be7a, 0xbdb100fc746529d7), + (0xb9edcbe05d10e11a, 0x3d4020f11e2dca08), + (0xb9da9e6748bc0bea, 0x3d34a26ef2219c2c), + (0x3957914c29f9b911, 0xbcc38203ff52c747), + (0xb94441377b47cfd9, 0xbcb35244c153aa29), + (0xb8ef173859510b43, 0x3c4232dbbbea35fb), + (0x38b7c43340294390, 0x3c2cc2f30d7e4a86), + (0xb850cdea356a6de6, 0xbbbafaa22e04387a), + (0x38455c9d49ba1463, 0xbba16c1420a026bc), + (0x37ce36d7bd132716, 0x3b3044e17b70797e), + (0x37bc48ba65be1620, 0x3b1182c036f66e44), + ], + [ + (0x3c4123b2f0e7c9dd, 0xbfb8b67a2481077d), + (0xb54bc05ff5d82c4f, 0xb8f3f299f5be57c2), + (0xbc4b4ca91be60b3e, 0x3fa8b51f21068ea2), + (0x3bb25eeb0c780d24, 0xbf2ed935c7aefa31), + (0xbbf1e97629a4fbd3, 0xbf707522a5037f2d), + (0x3b9aa02b2936e0d6, 0x3ef8a196061f8bbc), + (0x3bc503ddcb9034df, 0x3f21874a47e3c1e3), + (0x3b255f9307a25ea3, 0xbeac10cf34c04f17), + (0xbb5b1d5a1969a1af, 0xbec3fd6c2d4fa2a4), + (0xbaeb932c5947d65c, 0x3e50906d55522785), + (0xbabb5acdea3816e2, 0x3e5c5a1c124dfa08), + (0xba561fcb9b3ed156, 0xbde7f883b31a5f59), + (0xba75531c808efbb8, 0xbdeb668cf53028e4), + (0x3a104761ec9ef33f, 0x3d7775372d05b25d), + (0xba0f2cfa85a363c5, 0x3d7331d871d677e0), + (0xb9a6539a2342e3af, 0xbd009010248989d3), + (0x398a668272dab0b6, 0xbcf461c4067c742d), + (0xb92d7ef952991dfa, 0x3c81abf993696e78), + (0x3913091355b7de99, 0x3c70f715fa383b8a), + (0x3875a2bcb94003ab, 0xbbfd7ed2f30db038), + (0x388cafff31b61f18, 0xbbe6bb0b4da7d6b8), + (0xb7ea731441eedbfd, 0x3b73c73f0e157e5c), + (0xb7f38c8cb3f130f8, 0x3b5909945c395947), + (0x37892d92eac220fa, 0xbae5c71cc3e16dfe), + ], + [ + (0x35720ba7b8040a50, 0xb8ee1da34bfeb8e0), + (0x3c5b1c9821974148, 0x3fb86e51be0a9153), + (0xbbeaa494385dab26, 0xbf465ed1b387e5da), + (0x3c09cfc1363faa0e, 0xbf9046fc5a218a86), + (0x3bbf17fc55a88b96, 0x3f1dca617fefa913), + (0xbbe411ddd3f224d7, 0x3f4a0300221528a7), + (0xbb35922d57d34f24, 0xbed7c7618906f1e2), + (0x3b985c37a3fcd2ca, 0xbef3c838897d0a1e), + (0xbb1cfc9e9ef07548, 0x3e820ede9f9dd7dd), + (0x3b3d338a91461c93, 0x3e918a94165592bb), + (0x3ab91bf2c08f3e78, 0xbe1ff76205118f09), + (0x3ab5cfc207f32cd7, 0xbe24599dfeef01a1), + (0x3a40b7bcb17c141b, 0x3db2803e59983134), + (0xba1b8c9ffd59054b, 0x3db0a33202feb043), + (0x39bbb27b9c04cfb6, 0xbd3e2bff738680f8), + (0xb9daf156baca0aee, 0xbd34329cf32bcb6e), + (0xb95aa99554b94956, 0x3cc2424890fb6cfb), + (0xb94757efb61f4861, 0x3cb2eba657649d9b), + (0x38e0a8b550a3fb8e, 0xbc410bda49bebe27), + (0xb8b5e1a905ee61d3, 0xbc2c2d96d94f34d6), + (0x38596b550a29ba35, 0x3bb94a9b8509dda4), + (0xb8120159994b4d70, 0x3ba113d205a63be1), + (0x37caf2ee39614a11, 0xbb2e87a2990f48e9), + (0xb7a8109d37f955d6, 0xbb112c694684c14b), + ], + [ + (0x3c48caabfef07d2c, 0x3fb829d06fee9266), + (0xb57d95eabe44a5ef, 0xb8d5c95908041d40), + (0xbc46f7f245223685, 0xbfa8289a526d7785), + (0xbbbd55f593621103, 0x3f2cd680355c9eb6), + (0x3c19dafafbc85033, 0x3f7017d70f512861), + (0x3b94ef924915594e, 0xbef707978e2a0db8), + (0xbbb84f6dd554027b, 0xbf21247ce15e7385), + (0x3b3c1549321f5896, 0x3eaa3f6125485ec1), + (0xbb6485c950af11e4, 0x3ec38da848401be9), + (0xbae81c7e658ccb44, 0xbe4efe39d8db4cd8), + (0xbaf106727152dad2, 0xbe5bbd40f1db0e94), + (0x3a7e01f9c4e4c0e2, 0x3de66f7d49436f83), + (0xba6a9de5073f8785, 0x3dead0e8148229b3), + (0xb9edea6b298d9cb4, 0xbd75f78595133d0b), + (0x3a0ffda12b15058b, 0xbd72ca9bb10321b3), + (0xb995d841a594fd98, 0x3cff09e49c887e91), + (0xb993b69afd44cfe7, 0x3cf3f60eeb66f747), + (0xb910a7c26357cc61, 0xbc8091d689cc53d3), + (0x3912aa74818ab310, 0xbc709f335e86201a), + (0x389d74a5732f64e7, 0x3bfbad342a8e077c), + (0xb889c873abcae58c, 0x3be647de871fcaea), + (0x380999f107e74e72, 0xbb7292e087988121), + (0xb7dd56a4a524a0b3, 0xbb588dc30bd642e2), + (0x373e8c81645a59c4, 0x3ae4781fefecc3ab), + ], + [ + (0x3590e3abb994f19d, 0xb8f3c9c05fc68dd7), + (0x3c21907f595a082a, 0xbfb7e656efb009ae), + (0x3bea53822a52d942, 0x3f44f15066f3d876), + (0xbbef8f1c9736150f, 0x3f8fd932c26aad94), + (0xbba4e6bbdf1f5013, 0xbf1be460dd86a0a4), + (0x3bdda15b3eedcfa3, 0xbf49733b591879f8), + (0x3b7b0e620a04314f, 0x3ed64488c56022e0), + (0xbb74588b63a38eb3, 0x3ef35ba58bf2f993), + (0xbb2d0149456492a2, 0xbe80ea47bceb9a8f), + (0xbb1839787899a71b, 0xbe912b327055d0e9), + (0xbaaeacb6c41bd108, 0x3e1df42fc4e2482c), + (0xba6bbde5a22c7137, 0x3e23ec3e76876dba), + (0xba4c4c84b112be57, 0xbdb1580393f473c3), + (0x3a22a6076d63b081, 0xbdb04b0353c35935), + (0xb9c9681ae93e12c5, 0x3d3c4ca30ffe2a12), + (0xb9d1f206b8c5d3a1, 0x3d33c947b936c2fd), + (0xb963c18fe06a22d6, 0xbcc122c73f770a60), + (0x39590514d9616a4d, 0xbcb28ac7295026a0), + (0x38e4da699d53ec4a, 0x3c4002243876b909), + (0x38b0a1100a850e1a, 0x3c2ba04294d52584), + (0xb85e4caf2a0c3dac, 0xbbb7c4c63a56cf5d), + (0x383d5bda7bf4fb51, 0xbba0c0178f4adc58), + (0x37ba459191582324, 0x3b2cb6cf025ab9d0), + (0x37b2a1b95a167cc0, 0x3b10da465bbcd445), + ], + [ + (0xbc2f952341a4610f, 0xbfb7a62320798175), + (0x3588b8c77a52cc96, 0xb8e354421b948434), + (0x3c4f5aadff868986, 0x3fa7a50ca4504bb8), + (0xbbc425ed1e2ffb88, 0xbf2b095ccb50a68c), + (0x3c0088e41711bdb7, 0xbf6f80ef11daa37a), + (0xbb8b1b49cdffecd8, 0x3ef59822dc75b064), + (0x3bc22455dc1dd149, 0x3f20c7e6a7c66630), + (0x3b4cb7b87c0d2237, 0xbea89e00b5c358d0), + (0x3b4c5e752b8da3c2, 0xbec324d5238b26d0), + (0x3ae195d9c7c418a5, 0x3e4d13a888d5dd30), + (0xbac402a4638ae535, 0x3e5b29f941a95b07), + (0x3a831332fd181280, 0xbde50e6ebb3d1df6), + (0xba87a4d1a4734618, 0xbdea4434c6b929dd), + (0x3a1460d05df6e757, 0x3d74a03fe2c47842), + (0x3a08550d3cb8e7ab, 0x3d7269628f2df98c), + (0x398caf5ddb7a6639, 0xbcfd28cc08ef4278), + (0xb9786d9d39f281e6, 0xbcf390706334abc3), + (0xb90ccf6b842a2b18, 0x3c7f26c3ea443ebe), + (0xb909111db3c1a608, 0x3c704c1cd3344483), + (0xb89c3b1307b1967f, 0xbbfa08922dcea305), + (0x38837f0ef471dbfb, 0xbbe5dabbff6c2bfb), + (0xb80bcc939f982679, 0x3b717bccb6cd02d3), + (0x37fb40b6199ccfa5, 0x3b5818261a2214e1), + (0xb78fcd71326e756b, 0xbae3485ef660d33a), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,427 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j1_coeffs::{J1_ZEROS, J1_ZEROS_VALUE}; +use crate::bessel::j1f_coeffs::J1F_COEFFS; +use crate::bessel::trigo_bessel::sin_small; +use crate::double_double::DoubleDouble; +use crate::polyeval::{f_polyeval7, f_polyeval10, f_polyeval12, f_polyeval14}; +use crate::rounding::CpuCeil; +use crate::sincos_reduce::rem2pif_any; + +/// Bessel of the first kind of order 1 +/// +/// Max ULP 0.5 +/// +/// Note about accuracy: +/// - Close to zero Bessel have tiny values such that testing against MPFR must be done exactly +/// in the same precision, since any nearest representable number have ULP > 0.5. +/// For example `J1(0.000000000000000000000000000000000000023509886)` in single precision +/// have an error at least 0.72 ULP for any number with extended precision, +/// that would be represented in f32. +pub fn f_j1f(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN + if ux == 0 { + // |x| == 0 + return x; + } + if x.is_infinite() { + return 0.; + } + return x + f32::NAN; // x == NaN + } + + let ax = x.to_bits() & 0x7fff_ffff; + + if ax < 0x429533c2u32 { + // |x| <= 74.60109 + if ax < 0x3e800000u32 { + // |x| <= 0.25 + if ax <= 0x34000000u32 { + // |x| <= f32::EPSILON + // taylor series for J1(x) ~ x/2 + O(x^3) + return x * 0.5; + } + return poly_near_zero(x); + } + return small_argument_path(x); + } + + // Exceptional cases: + if ax == 0x6ef9be45 { + return if x.is_sign_negative() { + f32::from_bits(0x187d8a8f) + } else { + -f32::from_bits(0x187d8a8f) + }; + } else if ax == 0x7f0e5a38 { + return if x.is_sign_negative() { + -f32::from_bits(0x131f680b) + } else { + f32::from_bits(0x131f680b) + }; + } + + j1f_asympt(x) as f32 +} + +#[inline] +fn j1f_rsqrt(x: f64) -> f64 { + (1. / x) * x.sqrt() +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) +*/ +#[inline] +fn j1f_asympt(x: f32) -> f64 { + static SGN: [f64; 2] = [1., -1.]; + let sign_scale = SGN[x.is_sign_negative() as usize]; + let x = f32::from_bits(x.to_bits() & 0x7fff_ffff); + + let dx = x as f64; + + let alpha = j1f_asympt_alpha(dx); + let beta = j1f_asympt_beta(dx); + + let angle = rem2pif_any(x); + + const SQRT_2_OVER_PI: f64 = f64::from_bits(0x3fe9884533d43651); + const MPI_OVER_4: f64 = f64::from_bits(0xbfe921fb54442d18); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_sin = sin_small(r0); + + let z0 = beta * m_sin; + let scale = SQRT_2_OVER_PI * j1f_rsqrt(dx); + + scale * z0 * sign_scale +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied. + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +R_series = (-Q/P) + +# alpha is atan(R_series) so we're doing Taylor series atan expansion on R_series + +arctan_series_Z = sum([QQ(-1)**k * x**(QQ(2)*k+1) / RealField(700)(RealField(700)(2)*k+1) for k in range(25)]) +alpha_series = arctan_series_Z(R_series) + +# see the series +print(alpha_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn j1f_asympt_alpha(x: f64) -> f64 { + const C: [u64; 12] = [ + 0xbfd8000000000000, + 0x3fc5000000000000, + 0xbfd7bccccccccccd, + 0x4002f486db6db6db, + 0xc03e9fbf40000000, + 0x4084997b55945d17, + 0xc0d4a914195269d9, + 0x412cd1b53816aec1, + 0xc18aa4095d419351, + 0x41ef809305f11b9d, + 0xc2572e6809ed618b, + 0x42c4c5b6057839f9, + ]; + let recip = 1. / x; + let x2 = recip * recip; + let p = f_polyeval12( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + f64::from_bits(C[10]), + f64::from_bits(C[11]), + ); + p * recip +} + +/** +Note expansion generation below: this is negative series expressed in Sage as positive, +so before any real evaluation `x=1/x` should be applied + +Generated by SageMath: +```python +def binomial_like(n, m): + prod = QQ(1) + z = QQ(4)*(n**2) + for k in range(1,m + 1): + prod *= (z - (2*k - 1)**2) + return prod / (QQ(2)**(2*m) * (ZZ(m).factorial())) + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() + +def Pn_asymptotic(n, y, terms=10): + # now y = 1/x + return sum( (-1)**m * binomial_like(n, 2*m) / (QQ(2)**(2*m)) * y**(QQ(2)*m) for m in range(terms) ) + +def Qn_asymptotic(n, y, terms=10): + return sum( (-1)**m * binomial_like(n, 2*m + 1) / (QQ(2)**(2*m + 1)) * y**(QQ(2)*m + 1) for m in range(terms) ) + +P = Pn_asymptotic(1, x, 50) +Q = Qn_asymptotic(1, x, 50) + +def sqrt_series(s): + val = S.valuation() + lc = S[val] # Leading coefficient + b = lc.sqrt() * x**(val // 2) + + for _ in range(5): + b = (b + S / b) / 2 + b = b + return b + +S = (P**2 + Q**2).truncate(50) + +b_series = sqrt_series(S).truncate(30) +# see the beta series +print(b_series) +``` + +See notes/bessel_asympt.ipynb for generation +**/ +#[inline] +pub(crate) fn j1f_asympt_beta(x: f64) -> f64 { + const C: [u64; 10] = [ + 0x3ff0000000000000, + 0x3fc8000000000000, + 0xbfc8c00000000000, + 0x3fe9c50000000000, + 0xc01ef5b680000000, + 0x40609860dd400000, + 0xc0abae9b7a06e000, + 0x41008711d41c1428, + 0xc15ab70164c8be6e, + 0x41bc1055e24f297f, + ]; + let recip = 1. / x; + let x2 = recip * recip; + f_polyeval10( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + f64::from_bits(C[7]), + f64::from_bits(C[8]), + f64::from_bits(C[9]), + ) +} + +/** +Generated in Sollya: +```python +pretty = proc(u) { + return ~(floor(u*1000)/1000); +}; + +bessel_j1 = library("./cmake-build-release/libbessel_sollya.dylib"); + +f = bessel_j1(x)/x; +d = [0, 0.921]; +w = 1; +pf = fpminimax(f, [|0,2,4,6,8,10,12|], [|D...|], d, absolute, floating); + +w = 1; +or_f = bessel_j1(x); +pf1 = pf * x; +err_p = -log2(dirtyinfnorm(pf1*w-or_f, d)); +print ("relative error:", pretty(err_p)); + +for i from 0 to degree(pf) by 2 do { + print("'", coeff(pf, i), "',"); +}; +``` +See ./notes/bessel_sollya/bessel_j1f_at_zero.sollya +**/ +#[inline] +fn poly_near_zero(x: f32) -> f32 { + let dx = x as f64; + let x2 = dx * dx; + let p = f_polyeval7( + x2, + f64::from_bits(0x3fe0000000000000), + f64::from_bits(0xbfaffffffffffffc), + f64::from_bits(0x3f65555555554089), + f64::from_bits(0xbf0c71c71c2a74ae), + f64::from_bits(0x3ea6c16bbd1dc5c1), + f64::from_bits(0xbe384562afb69e7d), + f64::from_bits(0x3dc248d0d0221cd0), + ); + (p * dx) as f32 +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +fn small_argument_path(x: f32) -> f32 { + static SIGN: [f64; 2] = [1., -1.]; + let sign_scale = SIGN[x.is_sign_negative() as usize]; + let x_abs = f32::from_bits(x.to_bits() & 0x7fff_ffff) as f64; + + // let avg_step = 74.60109 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6300176043004198; + + let fx = x_abs * INV_STEP; + const J1_ZEROS_COUNT: f64 = (J1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(J1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return poly_near_zero(x); + } + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return (f64::from_bits(J1_ZEROS_VALUE[idx]) * sign_scale) as f32; + } + + let c = &J1F_COEFFS[idx - 1]; + + let r = (x_abs - found_zero.hi) - found_zero.lo; + + let p = f_polyeval14( + r, + f64::from_bits(c[0]), + f64::from_bits(c[1]), + f64::from_bits(c[2]), + f64::from_bits(c[3]), + f64::from_bits(c[4]), + f64::from_bits(c[5]), + f64::from_bits(c[6]), + f64::from_bits(c[7]), + f64::from_bits(c[8]), + f64::from_bits(c[9]), + f64::from_bits(c[10]), + f64::from_bits(c[11]), + f64::from_bits(c[12]), + f64::from_bits(c[13]), + ); + + (p * sign_scale) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_j1f() { + assert_eq!( + f_j1f(77.743162408196766932633181568235159), + 0.09049267898021947 + ); + assert_eq!( + f_j1f(-0.000000000000000000000000000000000000008827127), + -0.0000000000000000000000000000000000000044135635 + ); + assert_eq!( + f_j1f(0.000000000000000000000000000000000000008827127), + 0.0000000000000000000000000000000000000044135635 + ); + assert_eq!(f_j1f(5.4), -0.3453447907795863); + assert_eq!( + f_j1f(84.027189586293545175976760219782591), + 0.0870430264022591 + ); + assert_eq!(f_j1f(f32::INFINITY), 0.); + assert_eq!(f_j1f(f32::NEG_INFINITY), 0.); + assert!(f_j1f(f32::NAN).is_nan()); + assert_eq!(f_j1f(-1.7014118e38), 0.000000000000000000006856925); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1f_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/j1f_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/j1f_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,857 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generating Taylor expansions for zero and extremums see [crate::bessel::j1_coeffs::J1_ZEROS] +to start of explanation. + +Generated by SageMath and Sollya: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = (zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(j1_zeros) +# print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 500; +bessel_j1 = library("./pxfm/notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_j1(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d, 1, 1e-25); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RR(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +degree = 13 + +print(f"pub(crate) static J1F_COEFFS: [[u64;{degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print("[") + for c in coeffs: + print(double_to_hex(c) + ",") + print("],") +print("];") +``` +**/ +pub(crate) static J1F_COEFFS: [[u64; 14]; 47] = [ + [ + 0x3fe29ea3d19f035d, + 0xbce22d3695a081b6, + 0xbfca41115c5deeab, + 0x3f78d1448e710c46, + 0x3f8c441a2f9a4f69, + 0xbf386671c22a634e, + 0xbf39e2504b2e7b5b, + 0x3ee34ccc14eef789, + 0x3eda49718b72405e, + 0xbe810474efe3c9c6, + 0xbe70fa29fb791201, + 0x3e1362d76c062ab0, + 0x3dfdd76f07295520, + 0xbda1a753bf39cb58, + ], + [ + 0xbc600f4743bf63e1, + 0xbfd9c6cf582cbf8a, + 0x3faae8a39f51ad73, + 0x3fab589d1da1462b, + 0xbf7537544c334c23, + 0xbf624b34099ee01c, + 0x3f26e4c2d53c4f46, + 0x3f083a06ee794927, + 0xbec9799d241e5d2b, + 0xbea3382caabc394d, + 0x3e617039a48bb9f6, + 0x3e345a8c920dcd07, + 0xbdf014c3bf3000a5, + 0xbdc034aa4e0a0169, + ], + [ + 0xbfd626ee83500bf2, + 0x3cb26dfd317b25ec, + 0x3fc55f6bec9ef90d, + 0xbf83d23336fd2aca, + 0xbf88c77a98398e83, + 0x3f45cdc98dc64f81, + 0x3f373576fec2e394, + 0xbef24614559dc202, + 0xbed7b852bb05a2ff, + 0x3e90ac054c63ba46, + 0x3e6ea70b302a9ba3, + 0xbe23616f333984e9, + 0xbdfb0a064790ebe6, + 0x3db0d9e08e0394a8, + ], + [ + 0xbc69b70cbe5811c2, + 0x3fd33518b3874e8d, + 0xbf95e70dc6036109, + 0xbfa80c83bdeee89d, + 0x3f69a4b292e2ab0d, + 0x3f613fbc7d6bc462, + 0xbf207358bb38afba, + 0xbf0796a754e5c2d1, + 0x3ec4255a5a67b552, + 0x3ea3026fd5c83da8, + 0xbe5d482c06555943, + 0xbe34473271553ffa, + 0x3dec0515656e1a0c, + 0x3dbf11e1948b68d2, + ], + [ + 0x3fd17dbf09d40d24, + 0xbca5b86542306439, + 0xbfc1404bf647c233, + 0x3f74f4df276a170d, + 0x3f85c628542932bb, + 0xbf3d68ab724123eb, + 0xbf356acb63c4c7d5, + 0x3eec10b48d91d910, + 0x3ed67eaa56c73092, + 0xbe8bb65dbfeed0f6, + 0xbe6d8683c673b075, + 0x3e20f7b6316797c6, + 0x3dfa451f70b9922a, + 0xbdadce2c76e4d044, + ], + [ + 0x3c65df812ede650d, + 0xbfcff654544ebcd3, + 0x3f89223ff2c07565, + 0x3fa4b0c5d5da68d8, + 0xbf5f91a9ee0b0e8a, + 0xbf5f51c2489da5c1, + 0x3f16b4c9c8efdfe6, + 0x3f063c54768ebb67, + 0xbebe3724b50493f9, + 0xbea25c12f8827c9d, + 0x3e5747d49182153b, + 0x3e33e41718262cb9, + 0xbde738f2d8f2cac8, + 0xbdbe80a4948dbf09, + ], + [ + 0xbfcddceb4ce1bf49, + 0x3c9e79566c79eb3d, + 0x3fbda52116c0a587, + 0xbf6a9da4603b9358, + 0xbf8331e74ea51630, + 0x3f33e5cb6ecbca42, + 0x3f33885fe920e6b8, + 0xbee494c100626ece, + 0xbed512b940a2ae49, + 0x3e85a8688c9ba4ce, + 0x3e6c31a31b773184, + 0xbe1bd11439ffd259, + 0xbdf96a9daeb33936, + 0x3da9176221cc5aa0, + ], + [ + 0xbc62383f10698557, + 0x3fcbf3337873a7d9, + 0xbf80c83a2d7adab7, + 0xbfa251858011820e, + 0x3f559eb160bdad7b, + 0x3f5c5bce33b024a1, + 0xbf10413e2f7af958, + 0xbf04a6704d9a9d07, + 0x3eb6c43df550ea17, + 0x3ea16abdc27eeb92, + 0xbe52576e7fc9d1e6, + 0xbe332dc1c1ed3ee2, + 0x3de2f6391206ebbc, + 0x3dbda410af6fe5f4, + ], + [ + 0x3fca7f63fea81f25, + 0xbc9710bf367611f2, + 0xbfba60afb0664019, + 0x3f62c1e930937e24, + 0x3f814506466cfd08, + 0xbf2cca8c0c28fab3, + 0xbf31df821c353039, + 0x3edee8816088c0d5, + 0x3ed3a365144be247, + 0xbe80ed354ac60d34, + 0xbe6ab31b90ea8e41, + 0x3e168836e968cdd7, + 0x3df8613c2e496c6b, + 0xbda4daa0300cec8d, + ], + [ + 0x3c5e59bc05abf185, + 0xbfc925c6fca08f55, + 0x3f786dd32e0596e8, + 0x3fa09463bbd036c8, + 0xbf4fda0298c57ed5, + 0xbf59f4be6075f749, + 0x3f0877991961e89e, + 0x3f032cb00f1d1bde, + 0xbeb19d8c17e4c965, + 0xbea06a043bd432bf, + 0x3e4d398ca8f49a5e, + 0x3e3250f2ec743ceb, + 0xbddf086f08c63838, + 0xbdbc8e4fa8a9f9e9, + ], + [ + 0xbfc810f50225b04a, + 0x3c923e2f625151bc, + 0x3fb7fdf97ac36a6f, + 0xbf5c3c256a8cde19, + 0xbf7f98feb7276ef1, + 0x3f25f6559e6b5a2c, + 0x3f3080f57a3a527d, + 0xbed80c5147824d09, + 0xbed256dac8ee5bae, + 0x3e7af7628377d0c7, + 0x3e6938ef2e239da2, + 0xbe12633fe4f5465f, + 0xbdf745af34a2de92, + 0x3da15e1c189cc1e4, + ], + [ + 0xbc59737d6e4fe431, + 0x3fc70c511227d5aa, + 0xbf72ccb0e975555d, + 0xbf9e7dc08e70e9c5, + 0x3f48acdc5b030cb1, + 0x3f580503724ae80a, + 0xbf032ee4c8c82218, + 0xbf01e5d2836968fa, + 0x3eac129da754f086, + 0x3e9ef1612a209ee4, + 0xbe47b90193cc5cb3, + 0xbe316f0e2a3b6246, + 0x3dd9aabe334f3655, + 0x3dbb62c2bd937db8, + ], + [ + 0x3fc633e7f7f05300, + 0xbc8dba9947515d38, + 0xbfb6273784c1bfc4, + 0x3f563ae94ade4347, + 0x3f7d4666536b9564, + 0xbf216d528356c33f, + 0xbf2ec0dcdab1fcc9, + 0x3ed34e967676159e, + 0x3ed135c5c78436c9, + 0xbe75f7c3c6380689, + 0xbe67dba82b616a97, + 0x3e0e71b8431ababd, + 0x3df62fc761d5cf41, + 0xbd9d2fe54f4a496b, + ], + [ + 0x3c558a68c87f4030, + 0xbfc5664e13b70622, + 0x3f6e16555e1087dd, + 0x3f9c5e1ad9fb2f2d, + 0xbf43d369f956c6bd, + 0xbf566f4ec27a7a37, + 0x3eff0de050de72b9, + 0x3f00cf26431ce3a2, + 0xbea6f46c2694b0df, + 0xbe9d407f232dd5f2, + 0x3e43a29f2e4c9c8a, + 0x3e3098ca879e4471, + 0xbdd585d6255bc3df, + 0xbdba39fcc1ea78bf, + ], + [ + 0xbfc4b71d4ca2cc69, + 0x3c88c930c0b4c560, + 0x3fb4ae245697fb03, + 0xbf5215e4e1a6153c, + 0xbf7b633ed6d8e543, + 0x3f1c7f17b4d42a82, + 0x3f2ce01b8a6eca10, + 0xbecfced72e1b750f, + 0xbed03c9cd706bc3a, + 0x3e72450e1e5d9dd3, + 0x3e66a249f63c5bc1, + 0xbe0999366388212b, + 0xbdf52ba007be60f3, + 0x3d98ced5beb32a74, + ], + [ + 0xbc526f6d035edf6d, + 0x3fc40f90793605bb, + 0xbf68c833077fb99d, + 0xbf9aa0ce0421d16e, + 0x3f405fa598ed8bab, + 0x3f551d30d78a7993, + 0xbef9c5807480a6e1, + 0xbeffc1bbf50ca15b, + 0x3ea32dfda14ee884, + 0x3e9bc2119616c18d, + 0xbe408b0d01f43d88, + 0xbe2fa87db40715d8, + 0x3dd24d20c9bf3988, + 0x3db920af9a64d8b9, + ], + [ + 0x3fc37dfa8f5a550a, + 0xbc850d0284917193, + 0xbfb3775c1a04efff, + 0x3f4e2b4810a4a882, + 0x3f79d151a72aa26d, + 0xbf17d8e5a0a8f01d, + 0xbf2b49a641814268, + 0x3ecac10968085b43, + 0x3ececa610eed952d, + 0xbe6eefd23aebb19b, + 0xbe658bda5ec8aafe, + 0x3e05d77b1c39da47, + 0x3df43d63ca6b9538, + 0xbd9555dba21d3a76, + ], + [ + 0x3c4fe3057c054c4c, + 0xbfc2f2072e638cf3, + 0x3f64df208bbd408f, + 0x3f992bb5e1e159a9, + 0xbf3ba181c0657121, + 0xbf53fe9d5ba9fb4a, + 0x3ef5d17600fd9483, + 0x3efe26d373f4ffea, + 0xbea0509689b62f58, + 0xbe9a70f1b160bc28, + 0x3e3c4fa74da61f57, + 0x3e2e44cc2feeed24, + 0xbdcf87b5a4255e18, + 0xbdb81bebaaec3c7c, + ], + [ + 0xbfc2768d29c69936, + 0x3c822565e3c86e7f, + 0x3fb271811730b057, + 0xbf49a8df96a15635, + 0xbf787c81cf1b96e9, + 0x3f14549cdbcc339c, + 0x3f29ed2567282f3d, + 0xbec6e4137cf2411c, + 0xbecd53321406f402, + 0x3e6a98443cd6fc90, + 0x3e6494adc7c6521b, + 0xbe02e1d787962f20, + 0xbdf3653d7772f823, + 0x3d928dbabedf1d31, + ], + [ + 0xbc4bd8c1a48b98b5, + 0x3fc1ff5eec6a01cd, + 0xbf61e438b722bfe0, + 0xbf97ed5fffc1c711, + 0x3f37b7997ba917ee, + 0x3f53081def95b78f, + 0xbef2c5f5ec3350b1, + 0xbefcc11a59469f36, + 0x3e9c2c3894e80d05, + 0x3e9946d150444e47, + 0xbe388ce82c32666d, + 0xbe2d044ba8d28f8d, + 0x3dcb7a77f047774e, + 0x3db72cad88060e0b, + ], + [ + 0x3fc194eba75b32f9, + 0xbc7faef3b1a5e821, + 0xbfb190f7dc273599, + 0x3f462bb47a5c8cc1, + 0x3f7756ef20f501d3, + 0xbf1198b0baaa058c, + 0xbf28be8cf854b2d7, + 0x3ec3dd6f88b69c69, + 0x3ecc09c72877c12b, + 0xbe6728ec2da828ad, + 0xbe63b897c2c7b139, + 0x3e008344f3db34b5, + 0x3df2a1a5ef6e57ff, + 0xbd904c70dc90d3bc, + ], + [ + 0x3c4888e51c985983, + 0xbfc12dd57bf18ad9, + 0x3f5f1e1e7f3937bf, + 0x3f96d9afe883018e, + 0xbf34a538a4802887, + 0xbf52316250b44b33, + 0x3ef05f11562b37ff, + 0x3efb86bad38b7b43, + 0xbe98a1b250bb7d2f, + 0xbe983dca646511fe, + 0x3e3588f1be962e6d, + 0x3e2be36513882145, + 0xbdc831edc515fa05, + 0xbdb6520b1c14e6f6, + ], + [ + 0xbfc0d0d36473e98c, + 0x3c7bf69dcc64d467, + 0x3fb0cda9974abd9e, + 0xbf4367f38f204418, + 0xbf7656b75e3b5a4f, + 0x3f0ed82abf947b58, + 0x3f27b4e5b765cd39, + 0xbec171fd1a726d85, + 0xbecae62a6c526e99, + 0x3e64648b6f18fd5e, + 0x3e62f3b53a117819, + 0xbdfd2c72ca1c90f8, + 0xbdf1f085bd0fab41, + 0x3d8ce566a6478844, + ], + [ + 0xbc45ca84b624bf30, + 0x3fc076826cc2c191, + 0xbf5b62885e006ac2, + 0xbf95e7f53001e43e, + 0x3f322ebeb8d9f78a, + 0x3f517444a79fe500, + 0xbeece06f1cc95449, + 0xbefa7006e603acdb, + 0x3e95c42dcf4cb755, + 0x3e9750c9cbea6158, + 0xbe3313f5f0d7c83f, + 0xbe2ade4e1f9c8db0, + 0x3dc57f801723eb46, + 0x3db58a5b7895974e, + ], + [ + 0x3fc02455675ab6d2, + 0xbc78e3f9125495c0, + 0xbfb021c155a72057, + 0x3f412be56fc16829, + 0x3f75749d556a12df, + 0xbf0b51f1f9db1832, + 0xbf26c96a07103bad, + 0x3ebef3a7bef163ee, + 0x3ec9e206eb2ce693, + 0xbe6220bf8745e1a3, + 0xbe6242a68bb3eb7f, + 0x3df9ffc1c0ac86f0, + 0x3df14fb8a5e39fac, + 0xbd89d286115bf7a6, + ], + [ + 0x3c4380441b0b0c6a, + 0xbfbfa8b41711c839, + 0x3f5857d39699926e, + 0x3f9511c6dadaa99b, + 0xbf302c289dbbcc5a, + 0xbf50cc2238d1bf52, + 0x3ee9b64d5a4aa86c, + 0x3ef976fb01920f8b, + 0xbe93693a8cc790fd, + 0xbe967b9496685d1b, + 0x3e310c25f77e4f25, + 0x3e29f17f3e13ecd9, + 0xbdc3414987038eec, + 0xbdb4d3b9dc98b4b1, + ], + [ + 0xbfbf161d0c28b48b, + 0x3c765dc0b792167d, + 0x3faf11d837aa6e5c, + 0xbf3eab76da4d4788, + 0xbf74ab329f05bdc5, + 0x3f086ada57d5a903, + 0x3f25f6e78e464093, + 0xbebbb2720677d252, + 0xbec8f8525854df7e, + 0x3e603f882886871e, + 0x3e61a293516bd71e, + 0xbdf75995de0fcb8d, + 0xbdf0bd411cec4c70, + 0x3d873e4d136b8f8b, + ], + [ + 0xbc418c91b7939a2c, + 0x3fbe8727daa3daec, + 0xbf55d353e285455c, + 0xbf94524d4813cbac, + 0x3f2d037574df02eb, + 0x3f50356bb7473b5d, + 0xbee7156bfaea76f5, + 0xbef896d7dbd3810e, + 0x3e9172c5e1abd5c6, + 0x3e95baadfc18282d, + 0xbe2eb240c0cc9c75, + 0xbe2919d9b9e0a0b9, + 0x3dc15e50952db326, + 0x3db42c51c147e65d, + ], + [ + 0x3fbe0357c158b118, + 0xbc74361048923786, + 0xbfadffc2fc1a90f5, + 0x3f3b9b82ae081404, + 0x3f73f64e05315346, + 0xbf05fe4b66e63077, + 0xbf2539518d55a85c, + 0x3eb8f8d02bcc2897, + 0x3ec825039164993f, + 0xbe5d566920c2c9ab, + 0xbe61111befe6e2b8, + 0x3df51d4c70439a2f, + 0x3df0375b8b7f66b3, + 0xbd850e412a9bff06, + ], + [ + 0x3c3fc518d24f616f, + 0xbfbd8293aa55d18f, + 0x3f53b6beb83f212f, + 0x3f93a5ccbc12a602, + 0xbf2a3765d26776da, + 0xbf4f5ab33747e91e, + 0x3ee4df6f1a6da3df, + 0x3ef7cbd49b834b1a, + 0xbe8f9607c8362a02, + 0xbe950b374b4c0d92, + 0x3e2bd1f7180ef6ba, + 0x3e2854abbc0c7de8, + 0xbdbf87db79765a71, + 0xbdb3926b2e69585a, + ], + [ + 0xbfbd0b36e5737457, + 0x3c726585805a22d8, + 0x3fad082ce3c6b4a2, + 0xbf3905d00c5e9c91, + 0xbf7352b073fcfa33, + 0x3f03f1ccfed800a0, + 0x3f248d74577878fa, + 0xbeb6a9ef1ba885bb, + 0xbec764d8b51b8b1c, + 0x3e5aa78ed7e846ea, + 0x3e608c46d6182272, + 0xbdf33581106d6379, + 0xbdef78fcff7e62ac, + 0x3d832f39fadd44c1, + ], + [ + 0xbc3cea65a1050db5, + 0x3fbc96700bf039e1, + 0xbf51ec0b5de4bafb, + 0xbf93095734a2441c, + 0x3f27d74e122576e6, + 0x3f4e636fe2585c98, + 0xbee2fe11959a4f56, + 0xbef712e4d39f1e3a, + 0x3e8cc3ac0e3e5a57, + 0x3e946ad2493deefc, + 0xbe295ca72f5034a9, + 0xbe279fa7ce9e0732, + 0x3dbcc7fe67868a0c, + 0x3db30482af82a3e3, + ], + [ + 0x3fbc29ae8400a31f, + 0xbc70d624180ba1cb, + 0xbfac27138da31b39, + 0x3f36d141fcbed86f, + 0x3f72bdc71061ff60, + 0xbf0231cf645337e2, + 0xbf23f0bf3a855d26, + 0x3eb4b05ea24a407d, + 0x3ec6b52ac7705590, + 0xbe585a82e1962dc0, + 0xbe60126ea6b0d3d5, + 0x3df191f5eda7279d, + 0x3dee96ae83ca14cd, + 0xbd8191df21c5049c, + ], + [ + 0x3c3a725871d54f1e, + 0xbfbbbf246914235e, + 0x3f5062daee353d6e, + 0x3f927a96f174b658, + 0xbf25cdb5dea7195a, + 0xbf4d818348f8b2ae, + 0x3ee160aab6b91ebc, + 0x3ef6698d6e3dde27, + 0xbe8a56325d99553d, + 0xbe93d7884737e010, + 0x3e273dfa1c71021f, + 0x3e26f8d7f1f40cd1, + 0xbdba675a7a73a904, + 0xbdb28141631b6b6a, + ], + [ + 0xbfbb5b8273b75054, + 0x3c6ef081b4f49e8c, + 0x3fab59418c36a598, + 0xbf34eafeaa92d6ad, + 0xbf7235801af9154a, + 0x3f00af9747e26a9d, + 0x3f23611db02b9d63, + 0xbeb2fbe420b9b6ee, + 0xbec613cc016f8c79, + 0x3e565cfa070daeea, + 0x3e5f4465aa2f3924, + 0xbdf0262c878a66b9, + 0xbdedc58772bf3be9, + 0x3d802a5900529d85, + ], + [ + 0xbc384aa4fbafc099, + 0x3fbaf9cb49c4f934, + 0xbf4e1d930b512b68, + 0xbf91f7a8fec6eb30, + 0x3f240a553105f569, + 0x3f4cb20c812efe23, + 0xbedff5195120ac4b, + 0xbef5cdc48eb38532, + 0x3e883b07bbc753fc, + 0x3e934fb5f8f40030, + 0xbe2566435ca657bc, + 0xbe265e90a4422b0e, + 0x3db85513c8865e5e, + 0x3db2077cf853887e, + ], + [ + 0x3fba9e13a0db6429, + 0xbc6c8fc49071e774, + 0xbfaa9c1ca2161ab5, + 0x3f3344a09efdef03, + 0x3f71b82c43097eb4, + 0xbefebfb97beaa2a2, + 0xbf22dcdb1b1095b7, + 0x3eb180048a016cca, + 0x3ec57eee38f33b34, + 0xbe54a0cd96cea7fb, + 0xbe5e74d5d6cab4bf, + 0x3dedd0d2df39d680, + 0x3ded0395b2b002c8, + 0xbd7ddf4961633a0a, + ], + [ + 0x3c366129d7cdda38, + 0xbfba4407e04298d1, + 0x3f4bcc9df0cefa78, + 0x3f917f0266db20d1, + 0xbf2280a052210834, + 0xbf4bf2ada1f36d37, + 0x3edd83d57dbfecdc, + 0x3ef53dd97231158c, + 0xbe8663c0bacd7255, + 0xbe92d1fb6736ed8c, + 0x3e23c94599131ea8, + 0x3e25cf6504993c56, + 0xbdb683e80faa06e8, + 0xbdb19631ce482d25, + ], + [ + 0xbfb9ef3bb2213b0a, + 0x3c6a7968b4e09650, + 0x3fa9ed82007a9965, + 0xbf31d2fdeeb2c55d, + 0xbf71446866fe7a9f, + 0x3efc73b6851770db, + 0x3f22628de4e7b12f, + 0xbeb03303cb6b68e6, + 0xbec4f50f5682c560, + 0x3e531ae61db4a107, + 0x3e5db4387e5cde8e, + 0xbdeba1fde369500d, + 0xbdec4f2d9a6ca338, + 0x3d7bb4d1335b858d, + ], + [ + 0xbc34b2fde0d60fa7, + 0x3fb99be744018c90, + 0xbf49c3f52a2af15f, + 0xbf910f5ca51f983b, + 0x3f2126c8e8c80fca, + 0x3f4b416f7d4ef26a, + 0xbedb5e2e533b6e90, + 0xbef4b86226f8434d, + 0x3e84c505ef1872eb, + 0x3e925d2f3adca31c, + 0xbe225d5434e81821, + 0xbe254a1c99a03af6, + 0x3db4e94bd07d8a6f, + 0x3db12c7cbd69804c, + ], + [ + 0x3fb94d3276914e50, + 0xbc68a054fb407a48, + 0xbfa94bac1950e23d, + 0x3f308d4ff8f228ce, + 0x3f70d90d29bf518f, + 0xbefa6d56164ba1ad, + 0xbf21f107d97a6716, + 0x3eae1a62755de03b, + 0x3ec474ea4fd020bb, + 0xbe51c2774b54b19c, + 0xbe5d00e34f95d0da, + 0x3de9b39b1acf50d9, + 0x3deba6dd96aebb23, + 0xbd79c96d87e11eb2, + ], + [ + 0x3c3336a57f397478, + 0xbfb8ffc9bd24fe07, + 0x3f47f7d46ab331c5, + 0x3f90a7a725d3fb50, + 0xbf1fea1728ee3283, + 0xbf4a9cac69f01f7f, + 0x3ed977f48dd3df20, + 0x3ef43c2d8dc63c79, + 0xbe8355d08ef44310, + 0xbe91f054ae49cd66, + 0x3e211ab3e0c31baf, + 0x3e24cdaac969d4dd, + 0xbdb37cc6ee5acaa3, + 0xbdb0c99a10f9a149, + ], + [ + 0xbfb8b67a2481077c, + 0x3c66ff282f533f22, + 0x3fa8b51f21068dcb, + 0xbf2ed935c7af3be8, + 0xbf707522a502e55b, + 0x3ef8a1960639d120, + 0x3f21874a473e56eb, + 0xbeac10cf4666ac95, + 0xbec3fd6b83d91ed3, + 0x3e509072f594172b, + 0x3e5c5969c0715bb8, + 0xbde7fbce7fa1d168, + 0xbdeb09679444c7c3, + 0x3d7813cf0f88ee50, + ], + [ + 0xbc31df60e9bfe4d4, + 0x3fb86e51be0a9153, + 0xbf465ed1b387e0dc, + 0xbf9046fc5a218a13, + 0x3f1dca617fec07ec, + 0x3f4a030022145da6, + 0xbed7c761870dcbbb, + 0xbef3c83888dc1ceb, + 0x3e820edd9a880dbb, + 0x3e918a9391ba3964, + 0xbe1ff64d38db85c5, + 0xbe245927a9c55d79, + 0x3db2377b4d9f1923, + 0x3db06cdd9727d79f, + ], + [ + 0x3fb829d06fee9265, + 0xbc6580de45a47453, + 0xbfa8289a526d76b3, + 0x3f2cd680355cdc28, + 0x3f7017d70f5091c7, + 0xbef707978e429e47, + 0xbf21247ce0bc7ead, + 0x3eaa3f6135c91ad4, + 0x3ec38da7a255e74a, + 0xbe4efe445dfcd93f, + 0xbe5bbc925c9c4b66, + 0x3de6729121dc2aec, + 0x3dea75b6fa634294, + 0xbd768bad7f03cc70, + ], + [ + 0x3c30ac9cf88bc679, + 0xbfb7e656efb009ad, + 0x3f44f15066f3d3cc, + 0x3f8fd932c26aacb2, + 0xbf1be460dd833bb1, + 0xbf49733b5917b1ec, + 0x3ed64488c387546b, + 0x3ef35ba58b547387, + 0xbe80ea46c863072a, + 0xbe912b31edd1db5a, + 0x3e1df32c5fd2f995, + 0x3e23ebca247be24d, + 0xbdb113cb7b7c70db, + 0xbdb015b1107de244, + ], + [ + 0xbfb7a62320798174, + 0x3c9957b1463c023c, + 0x3fa7a50ca4504ab9, + 0xbf2b095ccb52d0c4, + 0xbf6f80ef11d944d8, + 0x3ef59822dd4acc8e, + 0x3f20c7e6a7116068, + 0xbea89e01408239eb, + 0xbec324d470ec229a, + 0x3e4d13ff680fb32a, + 0x3e5b2943a9554368, + 0xbde5283c9b463c57, + 0xbde9e8488fabd47c, + 0x3d7a620fb02a1ce9, + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/jincpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/jincpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,408 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#![allow(clippy::excessive_precision)] + +use crate::bessel::alpha1::bessel_1_asympt_alpha_fast; +use crate::bessel::beta1::bessel_1_asympt_beta_fast; +use crate::bessel::j1_coeffs::{J1_COEFFS, J1_ZEROS, J1_ZEROS_VALUE}; +use crate::bessel::j1_coeffs_taylor::J1_COEFFS_TAYLOR; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::polyeval::{f_polyeval9, f_polyeval19}; +use crate::rounding::CpuCeil; +use crate::rounding::CpuRound; +use crate::sin_helper::sin_dd_small_fast; + +/// Normalized jinc 2*J1(PI\*x)/(pi\*x) +pub fn f_jincpi(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON, |x| == inf, x == NaN + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + return 1.0; + } + if x.is_infinite() { + return 0.; + } + return x + f64::NAN; // x = NaN + } + + let ax: u64 = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if ax < 0x4052a6784230fcf8u64 { + // |x| < 74.60109 + if ax < 0x3fd3333333333333 { + // |x| < 0.3 + return jincpi_near_zero(f64::from_bits(ax)); + } + let scaled_pix = f64::from_bits(ax) * std::f64::consts::PI; // just test boundaries + if scaled_pix < 74.60109 { + return jinc_small_argument_fast(f64::from_bits(ax)); + } + } + + jinc_asympt_fast(f64::from_bits(ax)) +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) +*/ +#[inline] +fn jinc_asympt_fast(ox: f64) -> f64 { + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + let px = DoubleDouble::quick_mult_f64(PI, ox); + + // 2^(3/2)/(Pi^2) + // reduce argument 2*sqrt(2/(PI*(x*PI))) = 2*sqrt(2)/PI + // adding additional pi from division then 2*sqrt(2)/PI^2 + const Z2_3_2_OVER_PI_SQR: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc76213a285b8094, 0x3fd25751e5614413)); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + // argument reduction assuming x here value is already multiple of PI. + // k = round((x*Pi) / (pi*2)) + let kd = (ox * 0.5).cpu_round(); + // y = (x * Pi) - k * 2 + let rem = f_fmla(kd, -2., ox); + let angle = DoubleDouble::quick_mult_f64(PI, rem); + + let recip = px.recip(); + + let alpha = bessel_1_asympt_alpha_fast(recip); + let beta = bessel_1_asympt_beta_fast(recip); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_sin = sin_dd_small_fast(r0); + let z0 = DoubleDouble::quick_mult(beta, m_sin); + let ox_recip = DoubleDouble::from_quick_recip(ox); + let dx_sqrt = ox_recip.fast_sqrt(); + let scale = DoubleDouble::quick_mult(Z2_3_2_OVER_PI_SQR, dx_sqrt); + let p = DoubleDouble::quick_mult(scale, z0); + + DoubleDouble::quick_mult(p, ox_recip).to_f64() +} + +#[inline] +pub(crate) fn jincpi_near_zero(x: f64) -> f64 { + // Polynomial Generated by Wolfram Mathematica: + // <60] + // poly=Numerator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 8] = [ + (0xbb3bddffe9450ca6, 0x3ff0000000000000), + (0x3c4b0b0a7393eccb, 0xbfde4cd3c3c87615), + (0xbc8f9f784e0594a6, 0xbff043283b1e383f), + (0xbc7af77bca466875, 0x3fdee46673cf919f), + (0xbc1b62837b038ea8, 0x3fd0b7cc55c9a4af), + (0x3c6c08841871f124, 0xbfc002b65231dcdd), + (0xbc36cf2d89ea63bc, 0xbf949022a7a0712b), + (0xbbf535d492c0ac1c, 0x3f840b48910d5105), + ]; + + const Q: [(u64, u64); 8] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c4aba6577f3253e, 0xbfde4cd3c3c87615), + (0x3c52f58f82e3438c, 0x3fcbd0a475006cf9), + (0x3c36e496237d6b49, 0xbfb9f4cea13b06e9), + (0xbbbbf3e4ef3a28fe, 0x3f967ed0cee85392), + (0x3c267ac442bb3bcf, 0xbf846e192e22f862), + (0x3bd84e9888993cb0, 0x3f51e0fff3cfddee), + (0x3bd7c0285797bd8e, 0xbf3ea7a621fa1c8c), + ]; + + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = x2 * x2; + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + x, + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + x, + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + x, + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + x, + DoubleDouble::from_bit_pair(P[6]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let p_num = DoubleDouble::mul_add(x4, q1, q0); + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[1]), + x, + DoubleDouble::from_bit_pair(Q[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[3]), + x, + DoubleDouble::from_bit_pair(Q[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[5]), + x, + DoubleDouble::from_bit_pair(Q[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + x, + DoubleDouble::from_bit_pair(Q[6]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let p_den = DoubleDouble::mul_add(x4, q1, q0); + + DoubleDouble::div(p_num, p_den).to_f64() +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +pub(crate) fn jinc_small_argument_fast(x: f64) -> f64 { + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + // let avg_step = 74.60109 / 47.0; + // let inv_step = 1.0 / avg_step; + + let dx = DoubleDouble::quick_mult_f64(PI, x); + + const INV_STEP: f64 = 0.6300176043004198; + + let fx = dx.hi * INV_STEP; + const J1_ZEROS_COUNT: f64 = (J1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(J1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - dx.hi).abs(); + let dist1 = (found_zero1.hi - dx.hi).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return jincpi_near_zero(x); + } + + let r = DoubleDouble::quick_dd_sub(dx, found_zero); + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return DoubleDouble::quick_mult_f64( + DoubleDouble::from_f64_div_dd(f64::from_bits(J1_ZEROS_VALUE[idx]), dx), + 2., + ) + .to_f64(); + } + + let is_zero_too_close = dist.abs() < 1e-3; + + let c = if is_zero_too_close { + &J1_COEFFS_TAYLOR[idx - 1] + } else { + &J1_COEFFS[idx - 1] + }; + + let p = f_polyeval19( + r.hi, + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + f64::from_bits(c[13].1), + f64::from_bits(c[14].1), + f64::from_bits(c[15].1), + f64::from_bits(c[16].1), + f64::from_bits(c[17].1), + f64::from_bits(c[18].1), + f64::from_bits(c[19].1), + f64::from_bits(c[20].1), + f64::from_bits(c[21].1), + f64::from_bits(c[22].1), + f64::from_bits(c[23].1), + ); + + let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[4])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0])); + + z = DoubleDouble::div(z, dx); + z.hi *= 2.; + z.lo *= 2.; + + let err = f_fmla( + z.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3bf0000000000000), // 2^-64 + ); + let ub = z.hi + (z.lo + err); + let lb = z.hi + (z.lo - err); + + if ub == lb { + return z.to_f64(); + } + + j1_small_argument_dd(r, c, dx) +} + +fn j1_small_argument_dd(r: DoubleDouble, c0: &[(u64, u64); 24], inv_scale: DoubleDouble) -> f64 { + let c = &c0[15..]; + + let p0 = f_polyeval9( + r.to_f64(), + f64::from_bits(c[0].1), + f64::from_bits(c[1].1), + f64::from_bits(c[2].1), + f64::from_bits(c[3].1), + f64::from_bits(c[4].1), + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + ); + + let c = c0; + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let mut z = DoubleDouble::div(p, inv_scale); + z.hi *= 2.; + z.lo *= 2.; + z.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_jincpi() { + assert_eq!(f_jincpi(f64::EPSILON), 1.0); + assert_eq!(f_jincpi(0.000043242121), 0.9999999976931268); + assert_eq!(f_jincpi(0.5000000000020244), 0.7217028449014163); + assert_eq!(f_jincpi(73.81695991658546), -0.0004417546638317049); + assert_eq!(f_jincpi(0.01), 0.9998766350182722); + assert_eq!(f_jincpi(0.9), 0.28331697846510623); + assert_eq!(f_jincpi(3.831705970207517), -0.036684415010255086); + assert_eq!(f_jincpi(-3.831705970207517), -0.036684415010255086); + assert_eq!( + f_jincpi(0.000000000000000000000000000000000000008827127), + 1.0 + ); + assert_eq!( + f_jincpi(-0.000000000000000000000000000000000000008827127), + 1.0 + ); + assert_eq!(f_jincpi(5.4), -0.010821736808448256); + assert_eq!( + f_jincpi(77.743162408196766932633181568235159), + -0.00041799098646950523 + ); + assert_eq!( + f_jincpi(84.027189586293545175976760219782591), + -0.00023927934929850555 + ); + assert_eq!(f_jincpi(f64::NEG_INFINITY), 0.0); + assert_eq!(f_jincpi(f64::INFINITY), 0.0); + assert!(f_jincpi(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/jincpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/jincpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/jincpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,417 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(clippy::too_many_arguments)] +use crate::bessel::j0f::j1f_rsqrt; +use crate::bessel::j1_coeffs::{J1_ZEROS, J1_ZEROS_VALUE}; +use crate::bessel::j1f::{j1f_asympt_alpha, j1f_asympt_beta}; +use crate::bessel::j1f_coeffs::J1F_COEFFS; +use crate::bessel::trigo_bessel::sin_small; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::rounding::CpuCeil; +use crate::rounding::CpuRound; + +pub(crate) trait JincpifBackend { + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn round(&self, x: f64) -> f64; + fn ceil(&self, x: f64) -> f64; + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64; + fn polyeval14( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + a7: f64, + a8: f64, + a9: f64, + a10: f64, + a11: f64, + a12: f64, + a13: f64, + ) -> f64; +} + +struct GenJincpifBackend {} + +impl JincpifBackend for GenJincpifBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.cpu_round() + } + + #[inline(always)] + fn ceil(&self, x: f64) -> f64 { + x.cpu_ceil() + } + + #[inline(always)] + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 { + use crate::polyeval::f_polyeval6; + f_polyeval6(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn polyeval14( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + a7: f64, + a8: f64, + a9: f64, + a10: f64, + a11: f64, + a12: f64, + a13: f64, + ) -> f64 { + use crate::polyeval::f_polyeval14; + f_polyeval14( + x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, + ) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +struct FmaJincpifBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl JincpifBackend for FmaJincpifBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.round() + } + + #[inline(always)] + fn ceil(&self, x: f64) -> f64 { + x.ceil() + } + + #[inline(always)] + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 { + use crate::polyeval::d_polyeval6; + d_polyeval6(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn polyeval14( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + a7: f64, + a8: f64, + a9: f64, + a10: f64, + a11: f64, + a12: f64, + a13: f64, + ) -> f64 { + use crate::polyeval::d_polyeval14; + d_polyeval14( + x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, + ) + } +} + +#[inline(always)] +fn jincpif_gen(x: f32, backend: B) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux <= 0x6800_0000u32 { + // |x| <= f32::EPSILON, |x| == inf, |x| == NaN + if ux <= 0x6800_0000u32 { + // |x| == 0 + return 1.; + } + if x.is_infinite() { + return 0.; + } + return x + f32::NAN; // x == NaN + } + + let ax = x.to_bits() & 0x7fff_ffff; + + if ax < 0x429533c2u32 { + // |x| < 74.60109 + if ax <= 0x3e800000u32 { + // |x| < 0.25 + return jincf_near_zero(f32::from_bits(ax), &backend); + } + let scaled_pix = f32::from_bits(ax) * std::f32::consts::PI; // just test boundaries + if scaled_pix < 74.60109 { + return jincpif_small_argument(f32::from_bits(ax), &backend); + } + } + + jincpif_asympt(f32::from_bits(ax), &backend) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn jincpif_fma_impl(x: f32) -> f32 { + jincpif_gen(x, FmaJincpifBackend {}) +} + +/// Normalized jinc 2*J1(PI\*x)/(pi\*x) +/// +pub fn f_jincpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + jincpif_gen(x, GenJincpifBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + jincpif_fma_impl + } else { + fn def_jincpif(x: f32) -> f32 { + jincpif_gen(x, GenJincpifBackend {}) + } + def_jincpif + } + }); + unsafe { q(x) } + } +} + +#[inline(always)] +fn jincf_near_zero(x: f32, backend: &B) -> f32 { + let dx = x as f64; + // Generated in Wolfram Mathematica: + // <60] + // poly=Numerator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = backend.polyeval6( + dx, + f64::from_bits(0x3ff0000000000002), + f64::from_bits(0xbfe46cd1822a5aa0), + f64::from_bits(0xbfee583c923dc6f4), + f64::from_bits(0x3fe3834f47496519), + f64::from_bits(0x3fc8118468756e6f), + f64::from_bits(0xbfbfaff09f13df88), + ); + let p_den = backend.polyeval6( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfe46cd1822a4cb0), + f64::from_bits(0x3fd2447a026f477a), + f64::from_bits(0xbfc6bdf2192404e5), + f64::from_bits(0x3fa0cf182218e448), + f64::from_bits(0xbf939ab46c3f7a7d), + ); + (p_num / p_den) as f32 +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline(always)] +fn jincpif_small_argument(ox: f32, backend: &B) -> f32 { + const PI: f64 = f64::from_bits(0x400921fb54442d18); + let x = ox as f64 * PI; + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + // let avg_step = 74.60109 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6300176043004198; + + let inv_scale = x; + + let fx = x_abs * INV_STEP; + const J1_ZEROS_COUNT: f64 = (J1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(J1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + backend + .ceil(fx) + .min(J1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(J1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(J1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return jincf_near_zero(ox, backend); + } + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return (f64::from_bits(J1_ZEROS_VALUE[idx]) / inv_scale * 2.) as f32; + } + + let c = &J1F_COEFFS[idx - 1]; + + let r = (x_abs - found_zero.hi) - found_zero.lo; + + let p = backend.polyeval14( + r, + f64::from_bits(c[0]), + f64::from_bits(c[1]), + f64::from_bits(c[2]), + f64::from_bits(c[3]), + f64::from_bits(c[4]), + f64::from_bits(c[5]), + f64::from_bits(c[6]), + f64::from_bits(c[7]), + f64::from_bits(c[8]), + f64::from_bits(c[9]), + f64::from_bits(c[10]), + f64::from_bits(c[11]), + f64::from_bits(c[12]), + f64::from_bits(c[13]), + ); + + (p / inv_scale * 2.) as f32 +} + +/* + Evaluates: + J1 = sqrt(2/(PI*x)) * beta(x) * cos(x - 3*PI/4 - alpha(x)) + discarding 1*PI/2 using identities gives: + J1 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) + + to avoid squashing small (-PI/4 - alpha(x)) into a large x actual expansion is: + + J1 = sqrt(2/(PI*x)) * beta(x) * sin((x mod 2*PI) - PI/4 - alpha(x)) +*/ +#[inline(always)] +pub(crate) fn jincpif_asympt(x: f32, backend: &B) -> f64 { + const PI: f64 = f64::from_bits(0x400921fb54442d18); + + let dox = x as f64; + let dx = dox * PI; + + let alpha = j1f_asympt_alpha(dx); + let beta = j1f_asympt_beta(dx); + + // argument reduction assuming x here value is already multiple of PI. + // k = round((x*Pi) / (pi*2)) + let kd = backend.round(dox * 0.5); + // y = (x * Pi) - k * 2 + let angle = backend.fma(kd, -2., dox) * PI; + + // 2^(3/2)/(Pi^2) + // reduce argument 2*sqrt(2/(PI*(x*PI))) = 2*sqrt(2)/PI + // adding additional pi from division then 2*sqrt(2)/PI^2 + const Z2_3_2_OVER_PI_SQR: f64 = f64::from_bits(0x3fd25751e5614413); + const MPI_OVER_4: f64 = f64::from_bits(0xbfe921fb54442d18); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_sin = sin_small(r0); + + let z0 = beta * m_sin; + let scale = Z2_3_2_OVER_PI_SQR * j1f_rsqrt(dox); + + let j1pix = scale * z0; + j1pix / dox +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_jincpif() { + assert_eq!(f_jincpif(-102.59484), 0.00024380769); + assert_eq!(f_jincpif(102.59484), 0.00024380769); + assert_eq!(f_jincpif(100.08199), -0.00014386141); + assert_eq!(f_jincpif(0.27715185), 0.9081822); + assert_eq!(f_jincpif(0.007638072), 0.99992806); + assert_eq!(f_jincpif(-f32::EPSILON), 1.0); + assert_eq!(f_jincpif(f32::EPSILON), 1.0); + assert_eq!( + f_jincpif(0.000000000000000000000000000000000000008827127), + 1.0 + ); + assert_eq!(f_jincpif(5.4), -0.010821743); + assert_eq!( + f_jincpif(77.743162408196766932633181568235159), + -0.00041799102 + ); + assert_eq!( + f_jincpif(-77.743162408196766932633181568235159), + -0.00041799102 + ); + assert_eq!( + f_jincpif(84.027189586293545175976760219782591), + -0.00023927793 + ); + assert_eq!(f_jincpif(f32::INFINITY), 0.); + assert_eq!(f_jincpif(f32::NEG_INFINITY), 0.); + assert!(f_jincpif(f32::NAN).is_nan()); + assert_eq!(f_jincpif(-1.7014118e38), -0.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,643 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::rational128_exp; +use crate::logs::{fast_log_d_to_dd, log_dd}; +use crate::polyeval::f_polyeval3; + +/// Modified Bessel of the second kind of order 0 +/// +/// Max ULP 0.5 +pub fn f_k0(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f64::NAN }; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb >= 0x40862e42fefa39f0u64 { + // x >= 709.7827128933841 + return 0.; + } + + if xb <= 0x3ff0000000000000 { + // x <= 1 + return k0_small_dd(x).to_f64(); + } + + k0_asympt(x) +} + +/** +Computes I0 on interval [0; 1] +as rational approximation I0 = 1 + (x/2)^2 * Pn((x/2)^2)/Qm((x/2)^2)) + +Generated by Wolfram Mathematica: +```python +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i0_0_to_1_fast(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + + const P: [(u64, u64); 3] = [ + (0xbae20452afd5045b, 0x3ff0000000000000), + (0xbc5b6ff3f140da20, 0x3fc93c83592c03de), + (0x3c25b350e9128d49, 0x3f904f33ef2de455), + ]; + + let ps_num = f_polyeval3( + eval_x.hi, + f64::from_bits(0x3f433805a2fabaaa), + f64::from_bits(0x3ee5897e7f554966), + f64::from_bits(0x3e731401f0bb5de4), + ); + let mut p_num = DoubleDouble::mul_f64_add(eval_x, ps_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 3] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c323fa63bef2b4e, 0xbfab0df29b4ff089), + (0x3bfedbdf64ed3110, 0x3f564662064157d2), + ]; + + let ps_den = f_polyeval3( + eval_x.hi, + f64::from_bits(0xbef6bdbb484fd0a4), + f64::from_bits(0x3e8d6ced53309351), + f64::from_bits(0xbe13cff13854e945), + ); + let mut p_den = DoubleDouble::mul_f64_add(eval_x, ps_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[0])); + let p = DoubleDouble::div(p_num, p_den); + + let z = DoubleDouble::quick_mult(p, eval_x); + + DoubleDouble::full_add_f64(z, 1.) +} + +/** +K0(x) + log(x) * I0(x) = P(x^2) +hence +K0(x) = P(x^2) - log(x)*I0(x) + +Generated in Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn k0_small_dd(x: f64) -> DoubleDouble { + let dx = DoubleDouble::from_exact_mult(x, x); + const P: [(u64, u64); 6] = [ + (0x3c1be095d044e896, 0x3fbdadb014541eb2), + (0x3c7321baa1d0a2d9, 0x3fd1b9f19bc9019a), + (0xbc33ce33a244e5bd, 0x3f94ec39f8744183), + (0x3bd7008dfc623255, 0x3f3d85175b25727d), + (0xbb4aa2a1c4905d30, 0x3ed007a860ef3235), + (0xbae8daa77abd6f7f, 0x3e4839e32c19f31a), + ]; + + let ps_num = f_polyeval3( + dx.hi, + f64::from_bits(0x3f3d85175b25727d), + f64::from_bits(0x3ed007a860ef3235), + f64::from_bits(0x3e4839e32c19f31a), + ); + + let mut p_num = DoubleDouble::mul_f64_add(dx, ps_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 3] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc2a82a292acdc83, 0xbf91be3a25c968d6), + (0xbb9d2c37183a6496, 0x3f23bac6961619d8), + ]; + + let ps_den = f_polyeval3( + dx.hi, + f64::from_bits(0xbeac315b81faa1bf), + f64::from_bits(0x3e2ab2d2fbae0863), + f64::from_bits(0xbd9be23550f83df7), + ); + let mut p_den = DoubleDouble::mul_f64_add(dx, ps_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(dx, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(dx, p_den, f64::from_bits(0x3ff0000000000000)); + + let prod = DoubleDouble::div(p_num, p_den); + + let vi_log = fast_log_d_to_dd(x); + let vi = i0_0_to_1_fast(x); + let r = DoubleDouble::mul_add(vi_log, -vi, prod); + let err = r.hi * f64::from_bits(0x3c00000000000000); // 2^-63 + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r; + } + + k0_small_hard(x, vi) +} + +/** +K0(x) + log(x) * I0(x) = P(x^2) +hence +K0(x) = P(x^2) - log(x)*I0(x) + +Generated in Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn k0_small_hard(x: f64, vi: DoubleDouble) -> DoubleDouble { + let dx = DoubleDouble::from_exact_mult(x, x); + const P: [(u64, u64); 6] = [ + (0x3c1be095d044e896, 0x3fbdadb014541eb2), + (0x3c7321baa1d0a2d9, 0x3fd1b9f19bc9019a), + (0xbc33ce33a244e5bd, 0x3f94ec39f8744183), + (0x3bd7008dfc623255, 0x3f3d85175b25727d), + (0xbb4aa2a1c4905d30, 0x3ed007a860ef3235), + (0xbae8daa77abd6f7f, 0x3e4839e32c19f31a), + ]; + + let mut p_num = DoubleDouble::mul_add( + dx, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(dx, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 6] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc2a82a292acdc83, 0xbf91be3a25c968d6), + (0xbb9d2c37183a6496, 0x3f23bac6961619d8), + (0xbb32032e14c6c2b2, 0xbeac315b81faa1bf), + (0x3aa1a1dc04bfba96, 0x3e2ab2d2fbae0863), + (0x3a3e0f678099fcff, 0xbd9be23550f83df7), + ]; + + let mut p_den = DoubleDouble::mul_add( + dx, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + p_den = DoubleDouble::mul_add(dx, p_den, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(dx, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(dx, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(dx, p_den, f64::from_bits(0x3ff0000000000000)); + + let prod = DoubleDouble::div(p_num, p_den); + + let v_log = log_dd(x); + + DoubleDouble::mul_add(v_log, -vi, prod) +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x) = Pn(1/x)/Qm(1/x) / (sqrt(x) * exp(x)) + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0_asympt(x: f64) -> f64 { + let recip = DoubleDouble::from_quick_recip(x); + let e = i0_exp(x * 0.5); + let r_sqrt = DoubleDouble::from_sqrt(x); + + const P: [(u64, u64); 12] = [ + (0xbc9a6a11d237114e, 0x3ff40d931ff62706), + (0x3cdd614ddf4929e5, 0x4040645168c3e483), + (0xbd1ecf9ea0af6ab2, 0x40757419a703a2ab), + (0xbd3da3551fb27770, 0x409d4e65365522a2), + (0xbd564d58855d1a46, 0x40b6dd32f5a199d9), + (0xbd6cf055ca963a8e, 0x40c4fd2368f19618), + (0x3d4b6cdfbdc058df, 0x40c68faa11ebcd59), + (0x3d5b4ce4665bfa46, 0x40bb6fbe08e0a8ea), + (0xbd4316909063be15, 0x40a1953103a5be31), + (0x3d12f3f8edf41af0, 0x4074d2cb001e175c), + (0xbcd7bba36540264f, 0x40316cffcad5f8f9), + (0xbc6bf28dfdd5d37d, 0x3fc2f487fe78b8d7), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcb9e8a5b17e696a, 0x403a485acd64d64a), + (0x3cd2e2e9c87f71f7, 0x4071518092320ecb), + (0xbd0d05bdb9431a2f, 0x4097e57e4c22c08e), + (0x3d5207068ab19ba9, 0x40b2ebadb2db62f9), + (0xbd64e37674083471, 0x40c1c0e4e9d6493d), + (0x3d3efb7a9a62b020, 0x40c3b94e8d62cdc7), + (0x3d47d6ce80a2114b, 0x40b93c2fd39e868e), + (0xbd1dfda61f525861, 0x40a1877a53a7f8d8), + (0x3d1236ff523dfcfa, 0x4077c3a10c2827de), + (0xbcc889997c9b0fe7, 0x4039a1d80b11c4a1), + (0x3c7ded0e8d73dddc, 0x3fdafe4913722123), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r = DoubleDouble::div(z, e * r_sqrt * e); + + let err = r.hi * f64::from_bits(0x3c10000000000000); // 2^-62 + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub != lb { + return k0_asympt_hard(x); + } + r.to_f64() +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x) = Pn(1/x)/Qm(1/x) / (sqrt(x) * exp(x)) + +```text +<90] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline(never)] +#[cold] +fn k0_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa06c98ff_b1382cb2_be520f51_a7b8f970_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xc84d8d0c_7faeef84_e56abccc_3d70f8a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xd1a71096_3da22280_35768c9e_0d3ddf42_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xf202e474_3698aabb_05688da0_ea1a088d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0xaaa01830_8138af4d_1137b2dd_11a216f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x99e0649f_320bca1a_c7adadb3_f5d8498e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb4d81657_de1baf00_918cbc76_c6974e96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8a9a28c8_a61c2c7a_12416d56_51c0b3d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x88a079f1_d9bd4582_6353316c_3aeb9dc9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xa82e10eb_9dc6225a_ef6223e7_54aa254d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xf5fc07fe_6b652e8a_0b9e74ba_d0c56118_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xc5288444_c7354b24_4a4e1663_86488928_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0x96d3d226_a220ae6e_d6cca1ae_40f01e27_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -121, + mantissa: 0xa7ab931b_499c4964_499c1091_4ab9673d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf8373d1a_9ff3f9c6_e5cfbe0a_85ccc131_u128, + }, + ]; + + static Q: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xa05190f4_dcf0d35c_277e0f21_0635c538_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xa8837381_94c38992_86c0995d_5e5fa474_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xc3a4f279_9297e905_f59cc065_75959de8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0x8b05ade4_03432e06_881ce37d_a907216d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xfd77f85e_35626f21_355ae728_01b78cbe_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0x972ed117_254970eb_661121dc_a4462d2f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xec9d204a_9294ab57_2ef500d5_59d701b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xf033522d_cae45860_53a01453_c56da895_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0x9a33640c_9896ead5_1ce040d7_b36544f3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xefe714fa_49da0166_fdf8bc68_57b77fa0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xd323b84c_214196b0_e25b8931_930fea0d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0xbbb5240b_346642d8_010383cb_1e8a607e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0x88dcfa2a_f9f7d2ab_dd017994_8fae7e87_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc891477c_526e0f5e_74c4ae9f_9d8732b5_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + let e = rational128_exp(x); + let r_sqrt = bessel_rsqrt_hard(x, recip); + + let mut p0 = P[14]; + for i in (0..14).rev() { + p0 = recip * p0 + P[i]; + } + + let mut q = Q[14]; + for i in (0..14).rev() { + q = recip * q + Q[i]; + } + + let v = p0 * q.reciprocal(); + let r = v * e.reciprocal() * r_sqrt; + r.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k0() { + assert_eq!(f_k0(0.11), 2.3332678776741127); + assert_eq!(f_k0(0.643), 0.7241025575342853); + assert_eq!(f_k0(0.964), 0.4433737413379138); + assert_eq!(f_k0(2.964), 0.03621679838808167); + assert_eq!(f_k0(423.43), 7.784461905543397e-186); + assert_eq!(f_k0(0.), f64::INFINITY); + assert_eq!(f_k0(-0.), f64::INFINITY); + assert!(f_k0(-0.5).is_nan()); + assert!(f_k0(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_k0(f64::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0e.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0e.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0e.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0e.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,434 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::bessel::k0::k0_small_dd; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +/// Modified exponentially scaled Bessel of the first kind of order 0 +/// +/// Computes K0(x)exp(x) +pub fn f_k0e(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f64::NAN }; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x3ff0000000000000 { + // x <= 1 + let v_k0 = k0_small_dd(x); + let v_exp = i0_exp(x); + return DoubleDouble::quick_mult(v_exp, v_k0).to_f64(); + } + + k0e_asympt(x) +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x)exp(x) = Pn(1/x)/Qm(1/x) / sqrt(x) + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0e_asympt(x: f64) -> f64 { + let recip = DoubleDouble::from_quick_recip(x); + let r_sqrt = DoubleDouble::from_sqrt(x); + + const P: [(u64, u64); 12] = [ + (0xbc9a6a11d237114e, 0x3ff40d931ff62706), + (0x3cdd614ddf4929e5, 0x4040645168c3e483), + (0xbd1ecf9ea0af6ab2, 0x40757419a703a2ab), + (0xbd3da3551fb27770, 0x409d4e65365522a2), + (0xbd564d58855d1a46, 0x40b6dd32f5a199d9), + (0xbd6cf055ca963a8e, 0x40c4fd2368f19618), + (0x3d4b6cdfbdc058df, 0x40c68faa11ebcd59), + (0x3d5b4ce4665bfa46, 0x40bb6fbe08e0a8ea), + (0xbd4316909063be15, 0x40a1953103a5be31), + (0x3d12f3f8edf41af0, 0x4074d2cb001e175c), + (0xbcd7bba36540264f, 0x40316cffcad5f8f9), + (0xbc6bf28dfdd5d37d, 0x3fc2f487fe78b8d7), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcb9e8a5b17e696a, 0x403a485acd64d64a), + (0x3cd2e2e9c87f71f7, 0x4071518092320ecb), + (0xbd0d05bdb9431a2f, 0x4097e57e4c22c08e), + (0x3d5207068ab19ba9, 0x40b2ebadb2db62f9), + (0xbd64e37674083471, 0x40c1c0e4e9d6493d), + (0x3d3efb7a9a62b020, 0x40c3b94e8d62cdc7), + (0x3d47d6ce80a2114b, 0x40b93c2fd39e868e), + (0xbd1dfda61f525861, 0x40a1877a53a7f8d8), + (0x3d1236ff523dfcfa, 0x4077c3a10c2827de), + (0xbcc889997c9b0fe7, 0x4039a1d80b11c4a1), + (0x3c7ded0e8d73dddc, 0x3fdafe4913722123), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r = DoubleDouble::div(z, r_sqrt); + + let err = r.hi * f64::from_bits(0x3c10000000000000); // 2^-62 + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub != lb { + return k0e_asympt_hard(x); + } + r.to_f64() +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x)exp(x) = Pn(1/x)/Qm(1/x) / sqrt(x) + +```text +<90] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline(never)] +#[cold] +fn k0e_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa06c98ff_b1382cb2_be520f51_a7b8f970_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xc84d8d0c_7faeef84_e56abccc_3d70f8a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xd1a71096_3da22280_35768c9e_0d3ddf42_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xf202e474_3698aabb_05688da0_ea1a088d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0xaaa01830_8138af4d_1137b2dd_11a216f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x99e0649f_320bca1a_c7adadb3_f5d8498e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb4d81657_de1baf00_918cbc76_c6974e96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8a9a28c8_a61c2c7a_12416d56_51c0b3d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x88a079f1_d9bd4582_6353316c_3aeb9dc9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xa82e10eb_9dc6225a_ef6223e7_54aa254d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xf5fc07fe_6b652e8a_0b9e74ba_d0c56118_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xc5288444_c7354b24_4a4e1663_86488928_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0x96d3d226_a220ae6e_d6cca1ae_40f01e27_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -121, + mantissa: 0xa7ab931b_499c4964_499c1091_4ab9673d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf8373d1a_9ff3f9c6_e5cfbe0a_85ccc131_u128, + }, + ]; + + static Q: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xa05190f4_dcf0d35c_277e0f21_0635c538_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xa8837381_94c38992_86c0995d_5e5fa474_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xc3a4f279_9297e905_f59cc065_75959de8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0x8b05ade4_03432e06_881ce37d_a907216d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xfd77f85e_35626f21_355ae728_01b78cbe_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0x972ed117_254970eb_661121dc_a4462d2f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xec9d204a_9294ab57_2ef500d5_59d701b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xf033522d_cae45860_53a01453_c56da895_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0x9a33640c_9896ead5_1ce040d7_b36544f3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xefe714fa_49da0166_fdf8bc68_57b77fa0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xd323b84c_214196b0_e25b8931_930fea0d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -116, + mantissa: 0xbbb5240b_346642d8_010383cb_1e8a607e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0x88dcfa2a_f9f7d2ab_dd017994_8fae7e87_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc891477c_526e0f5e_74c4ae9f_9d8732b5_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + let r_sqrt = bessel_rsqrt_hard(x, recip); + + let mut p0 = P[14]; + for i in (0..14).rev() { + p0 = recip * p0 + P[i]; + } + + let mut q = Q[14]; + for i in (0..14).rev() { + q = recip * q + Q[i]; + } + + let v = p0 * q.reciprocal(); + let r = v * r_sqrt; + r.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k0() { + assert_eq!(f_k0e(0.00060324324), 7.533665613459802); + assert_eq!(f_k0e(0.11), 2.6045757643537244); + assert_eq!(f_k0e(0.643), 1.3773725807788395); + assert_eq!(f_k0e(0.964), 1.1625987432322884); + assert_eq!(f_k0e(2.964), 0.7017119941259377); + assert_eq!(f_k0e(423.43), 0.06088931243251448); + assert_eq!(f_k0e(4324235240321.43), 6.027056776336986e-7); + assert_eq!(k0e_asympt_hard(423.43), 0.06088931243251448); + assert_eq!(f_k0e(0.), f64::INFINITY); + assert_eq!(f_k0e(-0.), f64::INFINITY); + assert!(f_k0e(-0.5).is_nan()); + assert!(f_k0e(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_k0e(f64::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0ef.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0ef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0ef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0ef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,184 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0f::i0f_small; +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::logs::fast_logf; +use crate::polyeval::{f_estrin_polyeval7, f_estrin_polyeval8}; + +/// Modified exponentially scaled Bessel of the first kind of order 0 +/// +/// Computes K0(x)exp(x) +/// +/// Max ULP 0.5 +pub fn f_k0ef(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + // |x| == 0 + return f32::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f32::NAN }; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x3f800000u32 { + // x <= 1.0 + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + // taylor series for K0(x)exp(x) ~ (-euler_gamma + log(2) - log(x)) + (-euler_gamma + log(2) - log(x)) * x + let dx = x as f64; + let log_x = fast_logf(x); + const M_EULER_GAMMA_P_LOG2: f64 = f64::from_bits(0x3fbdadb014541eb2); + let c1 = -log_x + M_EULER_GAMMA_P_LOG2; + return f_fmla(c1, dx, c1) as f32; + } + return k0ef_small(x); + } + + k0ef_asympt(x) +} + +/** +K0(x) + log(x) * I0(x) = P(x^2) +hence +K0(x) = P(x^2) - log(x)*I0(x) + +Polynomial generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0ef_small(x: f32) -> f32 { + let v_log = fast_logf(x); + let i0 = i0f_small(x); + + let v_exp = core_expf(x); + + let dx = x as f64; + + let p = f_estrin_polyeval7( + dx * dx, + f64::from_bits(0x3fbdadb014541ece), + f64::from_bits(0x3fd1dadb01453e9c), + f64::from_bits(0x3f99dadb01491ac7), + f64::from_bits(0x3f4bb90e82a4f609), + f64::from_bits(0x3eef4749ebd25b10), + f64::from_bits(0x3e85d5b5668593af), + f64::from_bits(0x3e15233b0788618b), + ); + let c = f_fmla(-i0, v_log, p); + (c * v_exp) as f32 +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x)exp(x) = Pn(1/x)/Qm(1/x) / sqrt(x) + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0ef_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let r_sqrt = j1f_rsqrt(dx); + + let p_num = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff40d931ff62701), + f64::from_bits(0x402d8410a60e2ced), + f64::from_bits(0x404e9f18049bf704), + f64::from_bits(0x405c07682282783c), + f64::from_bits(0x4057379c68ce6d5e), + f64::from_bits(0x403ffd64a0105c4e), + f64::from_bits(0x400cc53ed67913b4), + f64::from_bits(0x3faf8cc8747a5d72), + ); + let p_den = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4027ccde1d0eeb14), + f64::from_bits(0x40492418133aa7a7), + f64::from_bits(0x4057be8a004d0938), + f64::from_bits(0x4054cc77d1dfef26), + f64::from_bits(0x403fd2187097af1d), + f64::from_bits(0x4011c77649649e55), + f64::from_bits(0x3fc2080a5965ef9b), + ); + let v = p_num / p_den; + let pp = v * r_sqrt; + pp as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k0f() { + assert_eq!(f_k0ef(2.034804e-5), 10.918679); + assert_eq!(f_k0ef(0.010260499), 4.743962); + assert_eq!(f_k0ef(0.3260499), 1.7963701); + assert_eq!(f_k0ef(0.72341), 1.3121376); + assert_eq!(f_k0ef(0.), f32::INFINITY); + assert_eq!(f_k0ef(-0.), f32::INFINITY); + assert!(f_k0ef(-0.5).is_nan()); + assert!(f_k0ef(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_k0ef(f32::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k0f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k0f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,184 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0f::i0f_small; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::logs::fast_logf; +use crate::polyeval::{f_estrin_polyeval7, f_estrin_polyeval8}; + +/// Modified Bessel of the second kind of order 0 +/// +/// Max ULP 0.5 +/// +/// This method have exactly one exception which is not correctly rounded with FMA. +pub fn f_k0f(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f32::NAN }; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb >= 0x42cbc4fbu32 { + // x > 101.88473 + return 0.; + } + + if xb <= 0x3f800000u32 { + if xb <= 0x34000000u32 { + // |x| < f32::EPSILON + // taylor series for K0(x) ~ -euler_gamma + log(2) - log(x) + let log_x = fast_logf(x); + const EULER_GAMMA_PLUS_LOG2: f64 = f64::from_bits(0x3fbdadb014541eb2); + return (-log_x + EULER_GAMMA_PLUS_LOG2) as f32; + } + // x <= 1.0 + return k0f_small(x); + } + + k0f_asympt(x) +} + +/** +K0(x) + log(x) * I0(x) = P(x^2) +hence +K0(x) = P(x^2) - log(x)*I0(x) + +Polynomial generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0f_small(x: f32) -> f32 { + let v_log = fast_logf(x); + let i0 = i0f_small(x); + + let dx = x as f64; + + let p = f_estrin_polyeval7( + dx * dx, + f64::from_bits(0x3fbdadb014541ece), + f64::from_bits(0x3fd1dadb01453e9c), + f64::from_bits(0x3f99dadb01491ac7), + f64::from_bits(0x3f4bb90e82a4f609), + f64::from_bits(0x3eef4749ebd25b10), + f64::from_bits(0x3e85d5b5668593af), + f64::from_bits(0x3e15233b0788618b), + ); + let c = f_fmla(-i0, v_log, p); + c as f32 +} + +/** +Generated in Wolfram + +Computes sqrt(x)*exp(x)*K0(x)=Pn(1/x)/Qm(1/x) +hence +K0(x) = Pn(1/x)/Qm(1/x) / (sqrt(x) * exp(x)) + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k0f_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let e = core_expf(x); + let r_sqrt = dx.sqrt(); + + let p_num = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff40d931ff62701), + f64::from_bits(0x402d8410a62d9c17), + f64::from_bits(0x404e9f1804dd7e54), + f64::from_bits(0x405c076822dcd255), + f64::from_bits(0x4057379c6932949f), + f64::from_bits(0x403ffd64a0bd54b7), + f64::from_bits(0x400cc53ed733fd97), + f64::from_bits(0x3faf8cc8756944eb), + ); + let p_den = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4027ccde1d27ffc9), + f64::from_bits(0x40492418136fb90f), + f64::from_bits(0x4057be8a00983906), + f64::from_bits(0x4054cc77d2379b76), + f64::from_bits(0x403fd218713ec08d), + f64::from_bits(0x4011c77649d3f65f), + f64::from_bits(0x3fc2080a59e87324), + ); + let v = p_num / p_den; + let pp = v / (e * r_sqrt); + pp as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k0f() { + assert_eq!(f_k0f(2.034804e-5), 10.918458); + assert_eq!(f_k0f(0.010260499), 4.695535); + assert_eq!(f_k0f(0.3260499), 1.2965646); + assert_eq!(f_k0f(0.72341), 0.636511734); + assert_eq!(f_k0f(0.), f32::INFINITY); + assert_eq!(f_k0f(-0.), f32::INFINITY); + assert!(f_k0f(-0.5).is_nan()); + assert!(f_k0f(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_k0f(f32::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,644 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::rational128_exp; +use crate::logs::{fast_log_d_to_dd, log_dd}; +use crate::polyeval::f_polyeval3; + +/// Modified Bessel of the second kind of order 1 +/// +/// Max ULP 0.5 +pub fn f_k1(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f64::NAN }; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb >= 0x4086140538aa7d38u64 { + // 706.5025494880165 + return 0.; + } + + if xb <= 0x3ff0000000000000 { + // x <= 1 + return k1_small(x).to_f64(); + } + + k1_asympt(x) +} + +// Generated by Wolfram Mathematica: +// <60] +// poly=Numerator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +// poly=Denominator[approx][[1]]; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +#[inline] +fn i1_fast(x: f64) -> DoubleDouble { + let half_x = x * 0.5; // this is exact + let eval_x = DoubleDouble::from_exact_mult(half_x, half_x); + + const P: [(u64, u64); 3] = [ + (0x3c5555555553c008, 0x3fb5555555555555), + (0x3c06f1014b703de8, 0x3f6dfda17d0a2cef), + (0xbbc2594d655d84db, 0x3f21b2c299108f7b), + ]; + + let ps_num = f_polyeval3( + eval_x.hi, + f64::from_bits(0x3ec37625c178f5e2), + f64::from_bits(0x3e5843215f0d5088), + f64::from_bits(0x3dd97f1f45f47244), + ); + let mut p_num = DoubleDouble::mul_f64_add(eval_x, ps_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(eval_x, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 3] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc32ebd3ac0e6253, 0xbfa42c718ce308f7), + (0xbbe1626e81e3c1bc, 0x3f482772320eab0e), + ]; + + let ps_den = f_polyeval3( + eval_x.hi, + f64::from_bits(0xbee169811ef4f4a1), + f64::from_bits(0x3e6ebdab5dbe02a5), + f64::from_bits(0xbdeb1dbb29fec52a), + ); + let mut p_den = DoubleDouble::mul_f64_add(eval_x, ps_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add(eval_x, p_den, DoubleDouble::from_bit_pair(Q[0])); + let p = DoubleDouble::div(p_num, p_den); + + let eval_sqr = DoubleDouble::quick_mult(eval_x, eval_x); + + let mut z = DoubleDouble::mul_f64_add_f64(eval_x, 0.5, 1.); + z = DoubleDouble::mul_add(p, eval_sqr, z); + + let x_over_05 = DoubleDouble::from_exact_mult(x, 0.5); + + DoubleDouble::quick_mult(z, x_over_05) +} + +/** +Rational approximant for +f(x) := BesselK(1, x) - Log(x)*BesselI(1, x) - 1/x + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +pub(crate) fn k1_small(x: f64) -> DoubleDouble { + let rcp = DoubleDouble::from_quick_recip(x); + let x2 = DoubleDouble::from_exact_mult(x, x); + + const P: [(u64, u64); 6] = [ + (0xbc7037c12b888927, 0xbfd3b5b6028a83d6), + (0x3c39dba459d023e5, 0xbfb4bac288cfe0cd), + (0x3be0575395050120, 0xbf6c4a1abe9061df), + (0x3b755df8e375b3d4, 0xbf0c850679678599), + (0xbb097e0ec926785f, 0xbe98c4a9b608ae1f), + (0xbaa029f31c786e81, 0xbe104efe2246ee51), + ]; + + let ps_num = f_polyeval3( + x2.hi, + f64::from_bits(0xbf0c850679678599), + f64::from_bits(0xbe98c4a9b608ae1f), + f64::from_bits(0xbe104efe2246ee51), + ); + + let mut p_num = DoubleDouble::mul_f64_add(x2, ps_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c19f62e592f3e71, 0xbf8d3bd595449ca9), + (0xbba8472b975a12d7, 0x3f194de71babe24a), + (0xbb2eec4b611c19b5, 0xbe994a5dbec84e4d), + (0x3a9bae2028402903, 0x3e0981ded64a954b), + ]; + + let ps_den = f_fmla( + x2.hi, + f64::from_bits(0x3e0981ded64a954b), + f64::from_bits(0xbe994a5dbec84e4d), + ); + + let mut p_den = DoubleDouble::mul_f64_add(x2, ps_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(x2, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(x2, p_den, f64::from_bits(0x3ff0000000000000)); + + let p = DoubleDouble::div(p_num, p_den); + + let lg = fast_log_d_to_dd(x); + let v_i = i1_fast(x); + let z = DoubleDouble::mul_add(v_i, lg, rcp); + let r = DoubleDouble::mul_f64_add(p, x, z); + let err = f_fmla( + r.hi, + f64::from_bits(0x3c20000000000000), // 2^-61 + f64::from_bits(0x3a80000000000000), // 2^-87 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r; + } + k1_small_hard(x) +} + +/** +Rational approximant for +f(x) := BesselK(1, x) - Log(x)*BesselI(1, x) - 1/x + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn k1_small_hard(x: f64) -> DoubleDouble { + let rcp = DoubleDouble::from_quick_recip(x); + let x2 = DoubleDouble::from_exact_mult(x, x); + + const P: [(u64, u64); 6] = [ + (0xbc7037c12b888927, 0xbfd3b5b6028a83d6), + (0x3c39dba459d023e5, 0xbfb4bac288cfe0cd), + (0x3be0575395050120, 0xbf6c4a1abe9061df), + (0x3b755df8e375b3d4, 0xbf0c850679678599), + (0xbb097e0ec926785f, 0xbe98c4a9b608ae1f), + (0xbaa029f31c786e81, 0xbe104efe2246ee51), + ]; + + let mut p_num = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(x2, p_num, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c19f62e592f3e71, 0xbf8d3bd595449ca9), + (0xbba8472b975a12d7, 0x3f194de71babe24a), + (0xbb2eec4b611c19b5, 0xbe994a5dbec84e4d), + (0x3a9bae2028402903, 0x3e0981ded64a954b), + ]; + + let mut p_den = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(Q[4]), + DoubleDouble::from_bit_pair(Q[3]), + ); + p_den = DoubleDouble::mul_add(x2, p_den, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(x2, p_den, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add(x2, p_den, DoubleDouble::from_bit_pair(Q[0])); + + let p = DoubleDouble::div(p_num, p_den); + + let lg = log_dd(x); + let v_i = i1_fast(x); + let z = DoubleDouble::mul_add(v_i, lg, rcp); + DoubleDouble::mul_f64_add(p, x, z) +} + +/** +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1_asympt(x: f64) -> f64 { + let recip = DoubleDouble::from_quick_recip(x); + let e = i0_exp(x * 0.5); + let r_sqrt = DoubleDouble::from_sqrt(x); + + const P: [(u64, u64); 12] = [ + (0xbc9a6a0690becb3b, 0x3ff40d931ff62706), + (0xbce573e1bbf2f0b7, 0x40402cebfab5721d), + (0x3d11a739b7c11e7b, 0x4074f58abc0cfbf1), + (0xbd2682a09ded0116, 0x409c8315f8facef2), + (0xbd3a19e91a120168, 0x40b65f7a4caed8b9), + (0x3d449c3d2b834543, 0x40c4fe41fdb4e7b8), + (0xbd6bdd415ac7f7e1, 0x40c7aa402d035d03), + (0x3d528412ff0d6b24, 0x40bf68faddd7d850), + (0xbd48f4bb3f61dac6, 0x40a75f5650249952), + (0xbd1dc534b275e309, 0x4081bddd259c0582), + (0xbcce5103350bd226, 0x4046c7a049014484), + (0x3c8935f8acd6c1d0, 0x3fef7524082b1859), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cc0d2508437b3f4, 0x40396ff483adec14), + (0xbd130a9c9f8a5338, 0x4070225588d8c15d), + (0xbceceba8fa0e65a2, 0x4095481f6684e3bb), + (0x3d4099f3c178fd2a, 0x40afedc8a778bf42), + (0xbd3a7e6a6276a3e7, 0x40bc0c060112692e), + (0x3d11538c155b16d8, 0x40bcb12bd1101782), + (0xbd5f7b04cdea2c61, 0x40b07fa363202e10), + (0xbce444ed035b66c6, 0x4093d6fe8f44f838), + (0xbcf6f88fb942b610, 0x4065c99fa44030c3), + (0xbcbd1d2aedee5bc9, 0x40207ffabeb00eea), + (0xbc39a0c8091102c9, 0x3facff3d892cd57a), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let mut r_e = DoubleDouble::quick_mult(e, r_sqrt); + r_e = DoubleDouble::from_exact_add(r_e.hi, r_e.lo); + r_e = DoubleDouble::quick_mult(r_e, e); + r_e = DoubleDouble::from_exact_add(r_e.hi, r_e.lo); + + let r = DoubleDouble::div(z, r_e); + + let err = r.hi * f64::from_bits(0x3c10000000000000); // 2^-61 + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub != lb { + return k1_asympt_hard(x); + } + r.to_f64() +} + +/** +Generated by Wolfram Mathematica: +```text +<70] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn k1_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa06c98ff_b1382cb2_be5210ac_f26f25d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xc5f546cb_659a39d0_fafbd188_36ca05b9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xcd0b7cfa_de158d26_7084bbe9_f1bdb66d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xeac7be2f_957d1260_8849508a_2a5a8972_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0xa4d14fec_fecc6444_4c7b0287_dad71a86_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x94e3180c_01df9932_ad2acd8b_bab59c05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb0de10f8_74918442_94a96368_8eaa4d0d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8adfea76_d6dbe5d9_46bfaf83_9341f4b5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8f0a4337_b69b602c_cf187222_f3a3379f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xbd4c3ebf_c2db0fad_1b425641_cc470043_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x9b14d29f_9b97e3c8_c1a7b9d0_787f0ddb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0x93e670d2_07a553ef_a90d4895_cf1b5011_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0x93e0ee0a_cb4d8910_6b4d3e37_f4f9df49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0xff0ce10d_5585abd1_e8a53a12_65131ad4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0xf020536d_822cbe51_c8de095a_03367c83_u128, + }, + ]; + + static Q: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0x9c729dd5_4828a918_42807f58_d485a511_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0x9ff6f631_0794001d_433ab0c5_d4c682a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xb3f81e8b_1e0e85a6_3928342e_c83088a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xf6b1c203_a60d4294_239ad045_2c67c224_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xd7a98b14_7a499762_abde5c38_3a5b40e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0xf4eb8b77_a2cdc686_afd1273f_d464c8b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb4c1e12a_93ee86fc_930c6f94_cfa6ac3a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xaaeaab88_32b776b7_fdd76b0f_24349f41_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0xc8ec9d61_5bf2ee9b_878b4962_4a5cee85_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0x8b97bab0_3351673f_22f10d40_fd1c9ff3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -114, + mantissa: 0xd31cb80a_bf8cbedc_b0dcf7e7_c599f79e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -117, + mantissa: 0x96b354c8_69197193_ea4f608f_81943988_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0x989af1bb_e48b5c44_7cd09746_f15e935a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb7b51326_23c29ed5_8d3dcf5a_79bd9a4f_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + let e = rational128_exp(x); + let r_sqrt = bessel_rsqrt_hard(x, recip); + + let mut p0 = P[14]; + for i in (0..14).rev() { + p0 = recip * p0 + P[i]; + } + + let mut q0 = Q[14]; + for i in (0..14).rev() { + q0 = recip * q0 + Q[i]; + } + + let v = p0 * q0.reciprocal(); + let r = v * (e.reciprocal() * r_sqrt); + r.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_k1() { + assert_eq!(f_k1(0.643), 1.184534109892725); + assert_eq!(f_k1(0.964), 0.6402280656771248); + assert_eq!(f_k1(2.964), 0.04192888446074039); + assert_eq!(f_k1(8.43), 9.824733212831289e-5); + assert_eq!(f_k1(16.43), 2.3142404075259965e-8); + assert_eq!(f_k1(423.43), 7.793648638470207e-186); + assert_eq!(f_k1(0.), f64::INFINITY); + assert_eq!(f_k1(-0.), f64::INFINITY); + assert!(f_k1(-0.5).is_nan()); + assert!(f_k1(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_k1(f64::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1e.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1e.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1e.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1e.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,425 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::i0_exp; +use crate::bessel::k1::k1_small; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +/// Modified exponentially scaled Bessel of the second kind of order 1 +/// +/// Computes K1(x)exp(x) +pub fn f_k1e(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f64::NAN }; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x3ff0000000000000 { + // x <= 1 + let v_exp = i0_exp(x); + let v_k = k1_small(x); + return DoubleDouble::quick_mult(v_exp, v_k).to_f64(); + } + + k1e_asympt(x) +} + +/** +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1e_asympt(x: f64) -> f64 { + let recip = DoubleDouble::from_quick_recip(x); + let r_sqrt = DoubleDouble::from_sqrt(x); + + const P: [(u64, u64); 12] = [ + (0xbc9a6a0690becb3b, 0x3ff40d931ff62706), + (0xbce573e1bbf2f0b7, 0x40402cebfab5721d), + (0x3d11a739b7c11e7b, 0x4074f58abc0cfbf1), + (0xbd2682a09ded0116, 0x409c8315f8facef2), + (0xbd3a19e91a120168, 0x40b65f7a4caed8b9), + (0x3d449c3d2b834543, 0x40c4fe41fdb4e7b8), + (0xbd6bdd415ac7f7e1, 0x40c7aa402d035d03), + (0x3d528412ff0d6b24, 0x40bf68faddd7d850), + (0xbd48f4bb3f61dac6, 0x40a75f5650249952), + (0xbd1dc534b275e309, 0x4081bddd259c0582), + (0xbcce5103350bd226, 0x4046c7a049014484), + (0x3c8935f8acd6c1d0, 0x3fef7524082b1859), + ]; + + let x2 = DoubleDouble::quick_mult(recip, recip); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cc0d2508437b3f4, 0x40396ff483adec14), + (0xbd130a9c9f8a5338, 0x4070225588d8c15d), + (0xbceceba8fa0e65a2, 0x4095481f6684e3bb), + (0x3d4099f3c178fd2a, 0x40afedc8a778bf42), + (0xbd3a7e6a6276a3e7, 0x40bc0c060112692e), + (0x3d11538c155b16d8, 0x40bcb12bd1101782), + (0xbd5f7b04cdea2c61, 0x40b07fa363202e10), + (0xbce444ed035b66c6, 0x4093d6fe8f44f838), + (0xbcf6f88fb942b610, 0x4065c99fa44030c3), + (0xbcbd1d2aedee5bc9, 0x40207ffabeb00eea), + (0xbc39a0c8091102c9, 0x3facff3d892cd57a), + ]; + + let e0 = DoubleDouble::mul_add_f64( + recip, + DoubleDouble::from_bit_pair(Q[1]), + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_add( + recip, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let z = DoubleDouble::div(p_num, p_den); + + let r = DoubleDouble::div(z, r_sqrt); + + let err = r.hi * f64::from_bits(0x3c10000000000000); // 2^-61 + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub != lb { + return k1e_asympt_hard(x); + } + r.to_f64() +} + +/** +Generated by Wolfram Mathematica: +```text +<70] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[cold] +#[inline(never)] +fn k1e_asympt_hard(x: f64) -> f64 { + static P: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa06c98ff_b1382cb2_be5210ac_f26f25d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0xc5f546cb_659a39d0_fafbd188_36ca05b9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0xcd0b7cfa_de158d26_7084bbe9_f1bdb66d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xeac7be2f_957d1260_8849508a_2a5a8972_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0xa4d14fec_fecc6444_4c7b0287_dad71a86_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x94e3180c_01df9932_ad2acd8b_bab59c05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb0de10f8_74918442_94a96368_8eaa4d0d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8adfea76_d6dbe5d9_46bfaf83_9341f4b5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -108, + mantissa: 0x8f0a4337_b69b602c_cf187222_f3a3379f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xbd4c3ebf_c2db0fad_1b425641_cc470043_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0x9b14d29f_9b97e3c8_c1a7b9d0_787f0ddb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -112, + mantissa: 0x93e670d2_07a553ef_a90d4895_cf1b5011_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0x93e0ee0a_cb4d8910_6b4d3e37_f4f9df49_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -120, + mantissa: 0xff0ce10d_5585abd1_e8a53a12_65131ad4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0xf020536d_822cbe51_c8de095a_03367c83_u128, + }, + ]; + + static Q: [DyadicFloat128; 15] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0x9c729dd5_4828a918_42807f58_d485a511_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -118, + mantissa: 0x9ff6f631_0794001d_433ab0c5_d4c682a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xb3f81e8b_1e0e85a6_3928342e_c83088a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -113, + mantissa: 0xf6b1c203_a60d4294_239ad045_2c67c224_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0xd7a98b14_7a499762_abde5c38_3a5b40e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0xf4eb8b77_a2cdc686_afd1273f_d464c8b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xb4c1e12a_93ee86fc_930c6f94_cfa6ac3a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -109, + mantissa: 0xaaeaab88_32b776b7_fdd76b0f_24349f41_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -110, + mantissa: 0xc8ec9d61_5bf2ee9b_878b4962_4a5cee85_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -111, + mantissa: 0x8b97bab0_3351673f_22f10d40_fd1c9ff3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -114, + mantissa: 0xd31cb80a_bf8cbedc_b0dcf7e7_c599f79e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -117, + mantissa: 0x96b354c8_69197193_ea4f608f_81943988_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -122, + mantissa: 0x989af1bb_e48b5c44_7cd09746_f15e935a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb7b51326_23c29ed5_8d3dcf5a_79bd9a4f_u128, + }, + ]; + + let recip = DyadicFloat128::accurate_reciprocal(x); + let r_sqrt = bessel_rsqrt_hard(x, recip); + + let mut p0 = P[14]; + for i in (0..14).rev() { + p0 = recip * p0 + P[i]; + } + + let mut q0 = Q[14]; + for i in (0..14).rev() { + q0 = recip * q0 + Q[i]; + } + + let v = p0 * q0.reciprocal(); + let r = v * r_sqrt; + r.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_k1() { + assert_eq!(f_k1e(0.643), 2.253195748291852); + assert_eq!(f_k1e(0.964), 1.6787831013451477); + assert_eq!(f_k1e(2.964), 0.8123854795542738); + assert_eq!(f_k1e(8.43), 0.4502184086111872); + assert_eq!(f_k1e(16.43), 0.3161307996938612); + assert_eq!(f_k1e(423.43), 0.06096117017402597); + assert_eq!(f_k1e(9044.431), 0.01317914752085687); + assert_eq!(k1e_asympt_hard(16.43), 0.3161307996938612); + assert_eq!(k1e_asympt_hard(423.43), 0.06096117017402597); + assert_eq!(k1e_asympt_hard(9044.431), 0.01317914752085687); + assert_eq!(f_k1e(0.), f64::INFINITY); + assert_eq!(f_k1e(-0.), f64::INFINITY); + assert!(f_k1e(-0.5).is_nan()); + assert!(f_k1e(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_k1e(f64::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1ef.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1ef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1ef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1ef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,240 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::logs::fast_logf; +use crate::polyeval::{f_estrin_polyeval8, f_polyeval3, f_polyeval4}; + +/// Modified exponentially scaled Bessel of the second kind of order 1 +/// +/// Computes K1(x)exp(x) +/// +/// Max ULP 0.5 +pub fn f_k1ef(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f32::NAN }; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x3f800000u32 { + // x <= 1.0 + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + let dx = x as f64; + let leading_term = 1. / dx + 1.; + if xb <= 0x3109705fu32 { + // |x| <= 2e-9 + // taylor series for tiny K1(x)exp(x) ~ 1/x + 1 + O(x) + return leading_term as f32; + } + // taylor series for small K1(x)exp(x) ~ 1/x+1+1/4 (1+2 EulerGamma-2 Log[2]+2 Log[x]) x + O(x^3) + const C: f64 = f64::from_bits(0xbffd8773039049e8); // 1 + 2 EulerGamma-2 Log[2] + let log_x = fast_logf(x); + let r = f_fmla(log_x, 2., C); + let w0 = f_fmla(dx * 0.25, r, leading_term); + return w0 as f32; + } + return k1ef_small(x); + } + + k1ef_asympt(x) +} + +/** +Computes +I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) + +Generated by Woflram Mathematica: + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1f_small(x: f32) -> f64 { + let dx = x as f64; + let x_over_two = dx * 0.5; + let x_over_two_sqr = x_over_two * x_over_two; + let x_over_two_p4 = x_over_two_sqr * x_over_two_sqr; + + let p_num = f_polyeval4( + x_over_two_sqr, + f64::from_bits(0x3fb5555555555355), + f64::from_bits(0x3f6ebf07f0dbc49b), + f64::from_bits(0x3f1fdc02bf28a8d9), + f64::from_bits(0x3ebb5e7574c700a6), + ); + let p_den = f_polyeval3( + x_over_two_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa39b64b6135b5a), + f64::from_bits(0x3f3fa729bbe951f9), + ); + let p = p_num / p_den; + + let p1 = f_fmla(0.5, x_over_two_sqr, 1.); + let p2 = f_fmla(x_over_two_p4, p, p1); + p2 * x_over_two +} + +/** +Series for +f(x) := BesselK(1, x) - Log(x)*BesselI(1, x) - 1/x + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1ef_small(x: f32) -> f32 { + let dx = x as f64; + let rcp = 1. / dx; + let x2 = dx * dx; + let p_num = f_polyeval4( + x2, + f64::from_bits(0xbfd3b5b6028a83d6), + f64::from_bits(0xbfb3fde2c83f7cca), + f64::from_bits(0xbf662b2e5defbe8c), + f64::from_bits(0xbefa2a63cc5c4feb), + ); + let p_den = f_polyeval4( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbf9833197207a7c6), + f64::from_bits(0x3f315663bc7330ef), + f64::from_bits(0xbeb9211958f6b8c3), + ); + let p = p_num / p_den; + + let v_exp = core_expf(x); + let lg = fast_logf(x); + let v_i = i1f_small(x); + let z = f_fmla(lg, v_i, rcp); + let z0 = f_fmla(p, dx, z); + (z0 * v_exp) as f32 +} + +/** +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1ef_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let r_sqrt = j1f_rsqrt(dx); + let p_num = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff40d931ff6270d), + f64::from_bits(0x402d250670ed7a6c), + f64::from_bits(0x404e517b9b494d38), + f64::from_bits(0x405cb02b7433a838), + f64::from_bits(0x405a03e606a1b871), + f64::from_bits(0x4045c98d4308dbcd), + f64::from_bits(0x401d115c4ce0540c), + f64::from_bits(0x3fd4213e72b24b3a), + ); + let p_den = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x402681096aa3a87d), + f64::from_bits(0x404623ab8d72ceea), + f64::from_bits(0x40530af06ea802b2), + f64::from_bits(0x404d526906fb9cec), + f64::from_bits(0x403281caca389f1b), + f64::from_bits(0x3ffdb93996948bb4), + f64::from_bits(0x3f9a009da07eb989), + ); + let v = p_num / p_den; + let pp = v * r_sqrt; + pp as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k1f() { + assert_eq!(f_k1ef(0.00000000005423), 18439980000.0); + assert_eq!(f_k1ef(0.0000000043123), 231894820.0); + assert_eq!(f_k1ef(0.3), 4.125158); + assert_eq!(f_k1ef(1.89), 1.0710458); + assert_eq!(f_k1ef(5.89), 0.5477655); + assert_eq!(f_k1ef(101.89), 0.12461915); + assert_eq!(f_k1ef(0.), f32::INFINITY); + assert_eq!(f_k1ef(-0.), f32::INFINITY); + assert!(f_k1ef(-0.5).is_nan()); + assert!(f_k1ef(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_k1ef(f32::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,240 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::logs::fast_logf; +use crate::polyeval::{f_estrin_polyeval8, f_polyeval3, f_polyeval4}; + +/// Modified Bessel of the second kind of order 1 +/// +/// Max ULP 0.5 +pub fn f_k1f(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f32::NAN }; + } + return x + f32::NAN; + } + + let xb = x.to_bits(); + + if xb >= 0x42cbc779u32 { + // x > 101.889595 + return 0.; + } + + if xb <= 0x3f800000u32 { + // x <= 1.0 + if xb <= 0x34000000u32 { + // |x| <= f32::EPSILON + let dx = x as f64; + let leading_term = 1. / dx; + if xb <= 0x3109705fu32 { + // |x| <= 2e-9 + // taylor series for tiny K1(x) ~ 1/x + O(x) + return leading_term as f32; + } + // taylor series for small K1(x) ~ 1/x+1/4 (-1+2 EulerGamma-2 Log[2]+2 Log[x]) x + O(x^3) + const C: f64 = f64::from_bits(0xbff3b5b6028a83d7); // -1+2 EulerGamma-2 Log[2] + let log_x = fast_logf(x); + let r = f_fmla(log_x, 2., C); + let w0 = f_fmla(dx * 0.25, r, leading_term); + return w0 as f32; + } + return k1f_small(x); + } + + k1f_asympt(x) +} + +/** +Computes +I1(x) = x/2 * (1 + 1 * (x/2)^2 + (x/2)^4 * P((x/2)^2)) + +Generated by Woflram Mathematica: + +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i1f_small(x: f32) -> f64 { + let dx = x as f64; + let x_over_two = dx * 0.5; + let x_over_two_sqr = x_over_two * x_over_two; + let x_over_two_p4 = x_over_two_sqr * x_over_two_sqr; + + let p_num = f_polyeval4( + x_over_two_sqr, + f64::from_bits(0x3fb5555555555355), + f64::from_bits(0x3f6ebf07f0dbc49b), + f64::from_bits(0x3f1fdc02bf28a8d9), + f64::from_bits(0x3ebb5e7574c700a6), + ); + let p_den = f_polyeval3( + x_over_two_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfa39b64b6135b5a), + f64::from_bits(0x3f3fa729bbe951f9), + ); + let p = p_num / p_den; + + let p1 = f_fmla(0.5, x_over_two_sqr, 1.); + let p2 = f_fmla(x_over_two_p4, p, p1); + p2 * x_over_two +} + +/** +Series for +f(x) := BesselK(1, x) - Log(x)*BesselI(1, x) - 1/x + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1f_small(x: f32) -> f32 { + let dx = x as f64; + let rcp = 1. / dx; + let x2 = dx * dx; + let p_num = f_polyeval4( + x2, + f64::from_bits(0xbfd3b5b6028a83d6), + f64::from_bits(0xbfb3fde2c83f7cca), + f64::from_bits(0xbf662b2e5defbe8c), + f64::from_bits(0xbefa2a63cc5c4feb), + ); + let p_den = f_polyeval4( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbf9833197207a7c6), + f64::from_bits(0x3f315663bc7330ef), + f64::from_bits(0xbeb9211958f6b8c3), + ); + let p = p_num / p_den; + + let lg = fast_logf(x); + let v_i = i1f_small(x); + let z = f_fmla(lg, v_i, rcp); + let z0 = f_fmla(p, dx, z); + z0 as f32 +} + +/** +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k1f_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let e = core_expf(x); + let r_sqrt = dx.sqrt(); + let p_num = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff40d931ff6270d), + f64::from_bits(0x402d250670ed7a6c), + f64::from_bits(0x404e517b9b494d38), + f64::from_bits(0x405cb02b7433a838), + f64::from_bits(0x405a03e606a1b871), + f64::from_bits(0x4045c98d4308dbcd), + f64::from_bits(0x401d115c4ce0540c), + f64::from_bits(0x3fd4213e72b24b3a), + ); + let p_den = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x402681096aa3a87d), + f64::from_bits(0x404623ab8d72ceea), + f64::from_bits(0x40530af06ea802b2), + f64::from_bits(0x404d526906fb9cec), + f64::from_bits(0x403281caca389f1b), + f64::from_bits(0x3ffdb93996948bb4), + f64::from_bits(0x3f9a009da07eb989), + ); + let v = p_num / p_den; + let pp = v / (e * r_sqrt); + pp as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k1f() { + assert_eq!(f_k1f(0.3), 3.055992); + assert_eq!(f_k1f(1.89), 0.16180483); + assert_eq!(f_k1f(5.89), 0.0015156545); + assert_eq!(f_k1f(101.89), 0.); + assert_eq!(f_k1f(0.), f32::INFINITY); + assert_eq!(f_k1f(-0.), f32::INFINITY); + assert!(f_k1f(-0.5).is_nan()); + assert!(f_k1f(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_k1f(f32::INFINITY), 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k2f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k2f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/k2f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/k2f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,262 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::exponents::core_expf; +use crate::logs::fast_logf; +use crate::polyeval::{f_estrin_polyeval5, f_estrin_polyeval8, f_polyeval4, f_polyeval11}; + +/// Modified Bessel of the second kind of order 2 +/// +/// ulp 0.5 +pub fn f_k2f(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + // |x| == 0 + return f32::INFINITY; + } + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f32::NAN }; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb >= 0x42cbceefu32 { + // |x| >= 101.90417 + return 0.; + } + + if xb <= 0x3f800000u32 { + // x <= 1.0 + if xb <= 0x3e9eb852u32 { + // x <= 0.31 + if xb <= 0x34000000u32 { + // x <= f32::EPSILON + let dx = x as f64; + let r = 2. / (dx * dx); + return r as f32; + } + return k2f_tiny(x); + } + return k2f_small(x); + } + + k2f_asympt(x) +} + +#[inline] +fn k2f_tiny(x: f32) -> f32 { + // Power series at zero for K2 + // 2.0000000000000000/x^2-0.50000000000000000-0.12500000000000000 (-0.86593151565841245+1.0000000000000000 Log[x]) x^2-0.010416666666666667 (-1.5325981823250791+1.0000000000000000 Log[x]) x^4-0.00032552083333333333 (-1.9075981823250791+1.0000000000000000 Log[x]) x^6-0.0000054253472222222222 (-2.1742648489917458+1.0000000000000000 Log[x]) x^8+O[x]^9 + //-0.50000000000000000+2.0000000000000000/x^2 + a3 * x^8 + x^6 * a2 + x^4 * a1 + x^2 * a0 + let dx = x as f64; + let log_x = fast_logf(x); + let a0 = f_fmla(-4.0000000000000000, log_x, 3.4637260626336498) * 0.031250000000000000; + let a1 = f_fmla(-12.000000000000000, log_x, 18.391178187900949) * 0.00086805555555555556; + let a2 = f_fmla(-24.000000000000000, log_x, 45.782356375801899) * 0.000013563368055555556; + let a3 = (log_x - 2.1742648489917458) * (-0.0000054253472222222222); + let dx_sqr = dx * dx; + let two_over_dx = 2. / dx_sqr; + let p = f_polyeval4(dx_sqr, a0, a1, a2, a3); + let r = f_fmla(p, dx_sqr, two_over_dx) - 0.5; + r as f32 +} + +/** +Computes +I2(x) = x^2 * R(x^2) + +Generated by Wolfram Mathematica: + +```text +<75] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn i2f_small(x: f32) -> f64 { + let dx = x as f64; + let x_sqr = dx * dx; + + let p_num = f_estrin_polyeval5( + x_sqr, + f64::from_bits(0x3fc0000000000000), + f64::from_bits(0x3f81520c0669099e), + f64::from_bits(0x3f27310bf5c5e9b0), + f64::from_bits(0x3eb8e2947e0a6098), + f64::from_bits(0x3e336dfad46e2f35), + ); + let p_den = f_estrin_polyeval5( + x_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbf900d253bb12edc), + f64::from_bits(0x3f1ed3d9ab228297), + f64::from_bits(0xbea14e6660c00303), + f64::from_bits(0x3e13eb951a6cf38f), + ); + let p = p_num / p_den; + p * x_sqr +} + +/** +Series for +R(x^2) := (BesselK(2, x) - Log(x)*BesselI(2, x) - 2/x^2)/(1+x^2) + +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k2f_small(x: f32) -> f32 { + let dx = x as f64; + let dx_sqr = dx * dx; + let p_num = f_polyeval11( + dx_sqr, + f64::from_bits(0xbfdff794c9ee3b5c), + f64::from_bits(0xc047d3276f18e5d2), + f64::from_bits(0xc09200ed3702875a), + f64::from_bits(0xc0c39f395c47be27), + f64::from_bits(0xc0e0ec95bd1a3192), + f64::from_bits(0xc0e5973cb871c8d0), + f64::from_bits(0xc0cdaf528de00d53), + f64::from_bits(0xc0afe6d3009de17c), + f64::from_bits(0xc098417b22844112), + f64::from_bits(0x4025c45260bb1b6a), + f64::from_bits(0x402f2bf6b95ffe0c), + ); + let p_den = f_polyeval11( + dx_sqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x405879a43b253224), + f64::from_bits(0x40a3a501408a0198), + f64::from_bits(0x40d8172abc4a8ccc), + f64::from_bits(0x40f9fcb05e98bdbd), + f64::from_bits(0x4109c45b54be586b), + f64::from_bits(0x4106ad7023dd0b90), + f64::from_bits(0x40ed7e988d2ba5a9), + f64::from_bits(0x40966305e1c1123a), + f64::from_bits(0xc090832b6a87317c), + f64::from_bits(0x403b48eb703f4644), + ); + let p = p_num / p_den; + + let two_over_dx_sqr = 2. / dx_sqr; + + let lg = fast_logf(x); + let v_i = i2f_small(x); + let z = f_fmla(lg, v_i, two_over_dx_sqr); + let z0 = f_fmla(p, f_fmla(dx, dx, 1.), z); + z0 as f32 +} + +/** +Generated by Wolfram Mathematica: +```text +<60] +poly=Numerator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=Denominator[approx][[1]]; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +``` +**/ +#[inline] +fn k2f_asympt(x: f32) -> f32 { + let dx = x as f64; + let recip = 1. / dx; + let e = core_expf(x); + let r_sqrt = dx.sqrt(); + let p_num = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff40d931ff626f2), + f64::from_bits(0x402d954dceb445df), + f64::from_bits(0x405084ea6680d028), + f64::from_bits(0x406242344a8ea488), + f64::from_bits(0x406594aa56f50fea), + f64::from_bits(0x405aa04eb4f0af1c), + f64::from_bits(0x403dd3e8e63849ef), + f64::from_bits(0x4004e85453648d43), + ); + let p_den = f_estrin_polyeval8( + recip, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4023da9f4e05358e), + f64::from_bits(0x4040a4e4ceb523c9), + f64::from_bits(0x404725c423c9f990), + f64::from_bits(0x403a60c00deededc), + f64::from_bits(0x40149975b84c3946), + f64::from_bits(0x3fc69439846db871), + f64::from_bits(0xbf6400819bac6f45), + ); + let v = p_num / p_den; + let pp = v / (e * r_sqrt); + pp as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_k2f() { + assert!(f_k2f(-1.).is_nan()); + assert!(f_k2f(f32::NAN).is_nan()); + assert_eq!(f_k2f(0.), f32::INFINITY); + assert_eq!(f_k2f(0.65), 4.3059196); + assert_eq!(f_k2f(1.65), 0.44830766); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![deny(unreachable_pub)] +mod alpha0; +mod alpha1; +mod bessel_exp; +mod beta0; +mod beta1; +mod i0; +mod i0e; +mod i0ef; +mod i0f; +mod i1; +mod i1e; +mod i1ef; +mod i1f; +mod i2; +mod i2f; +mod j0; +mod j0_coeffs_remez; +mod j0_coeffs_taylor; +mod j0f; +mod j0f_coeffs; +mod j1; +mod j1_coeffs; +mod j1_coeffs_taylor; +mod j1f; +mod j1f_coeffs; +mod jincpi; +mod jincpif; +mod k0; +mod k0e; +mod k0ef; +mod k0f; +mod k1; +mod k1e; +mod k1ef; +mod k1f; +mod k2f; +mod trigo_bessel; +mod y0; +mod y0_coeffs; +mod y0_coeffs_taylor; +mod y0f; +mod y0f_coeffs; +mod y1; +mod y1_coeffs; +mod y1_coeffs_taylor; +mod y1f; +mod y1f_coeffs; + +pub(crate) use bessel_exp::i0_exp; +pub use i0::f_i0; +pub use i0e::f_i0e; +pub use i0ef::f_i0ef; +pub use i0f::f_i0f; +pub use i1::f_i1; +pub use i1e::f_i1e; +pub use i1ef::f_i1ef; +pub use i1f::f_i1f; +pub use i2::f_i2; +pub use i2f::f_i2f; +pub use j0::f_j0; +pub use j0f::f_j0f; +pub use j1::f_j1; +pub use j1f::f_j1f; +pub use jincpi::f_jincpi; +pub use jincpif::f_jincpif; +pub use k0::f_k0; +pub use k0e::f_k0e; +pub use k0ef::f_k0ef; +pub use k0f::f_k0f; +pub use k1::f_k1; +pub use k1e::f_k1e; +pub use k1ef::f_k1ef; +pub use k1f::f_k1f; +pub use k2f::f_k2f; +pub use y0::f_y0; +pub use y0f::f_y0f; +pub use y1::f_y1; +pub use y1f::f_y1f; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/trigo_bessel.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/trigo_bessel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/trigo_bessel.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/trigo_bessel.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,285 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, min_normal_f64}; +use crate::rounding::CpuRound; + +// Generated by SageMath: +// print("[") +// for k in range(128): +// k = RealField(150)(k) * RealField(150).pi() / RealField(150)(64) +// print(double_to_hex(k.sin()) + ",") +// print("];") +pub(crate) static SIN_K_PI_OVER_64: [u64; 128] = [ + 0x0000000000000000, + 0x3fa91f65f10dd814, + 0x3fb917a6bc29b42c, + 0x3fc2c8106e8e613a, + 0x3fc8f8b83c69a60b, + 0x3fcf19f97b215f1b, + 0x3fd294062ed59f06, + 0x3fd58f9a75ab1fdd, + 0x3fd87de2a6aea963, + 0x3fdb5d1009e15cc0, + 0x3fde2b5d3806f63b, + 0x3fe073879922ffee, + 0x3fe1c73b39ae68c8, + 0x3fe30ff7fce17035, + 0x3fe44cf325091dd6, + 0x3fe57d69348ceca0, + 0x3fe6a09e667f3bcd, + 0x3fe7b5df226aafaf, + 0x3fe8bc806b151741, + 0x3fe9b3e047f38741, + 0x3fea9b66290ea1a3, + 0x3feb728345196e3e, + 0x3fec38b2f180bdb1, + 0x3feced7af43cc773, + 0x3fed906bcf328d46, + 0x3fee212104f686e5, + 0x3fee9f4156c62dda, + 0x3fef0a7efb9230d7, + 0x3fef6297cff75cb0, + 0x3fefa7557f08a517, + 0x3fefd88da3d12526, + 0x3feff621e3796d7e, + 0x3ff0000000000000, + 0x3feff621e3796d7e, + 0x3fefd88da3d12526, + 0x3fefa7557f08a517, + 0x3fef6297cff75cb0, + 0x3fef0a7efb9230d7, + 0x3fee9f4156c62dda, + 0x3fee212104f686e5, + 0x3fed906bcf328d46, + 0x3feced7af43cc773, + 0x3fec38b2f180bdb1, + 0x3feb728345196e3e, + 0x3fea9b66290ea1a3, + 0x3fe9b3e047f38741, + 0x3fe8bc806b151741, + 0x3fe7b5df226aafaf, + 0x3fe6a09e667f3bcd, + 0x3fe57d69348ceca0, + 0x3fe44cf325091dd6, + 0x3fe30ff7fce17035, + 0x3fe1c73b39ae68c8, + 0x3fe073879922ffee, + 0x3fde2b5d3806f63b, + 0x3fdb5d1009e15cc0, + 0x3fd87de2a6aea963, + 0x3fd58f9a75ab1fdd, + 0x3fd294062ed59f06, + 0x3fcf19f97b215f1b, + 0x3fc8f8b83c69a60b, + 0x3fc2c8106e8e613a, + 0x3fb917a6bc29b42c, + 0x3fa91f65f10dd814, + 0xb69f77598338bfdf, + 0xbfa91f65f10dd814, + 0xbfb917a6bc29b42c, + 0xbfc2c8106e8e613a, + 0xbfc8f8b83c69a60b, + 0xbfcf19f97b215f1b, + 0xbfd294062ed59f06, + 0xbfd58f9a75ab1fdd, + 0xbfd87de2a6aea963, + 0xbfdb5d1009e15cc0, + 0xbfde2b5d3806f63b, + 0xbfe073879922ffee, + 0xbfe1c73b39ae68c8, + 0xbfe30ff7fce17035, + 0xbfe44cf325091dd6, + 0xbfe57d69348ceca0, + 0xbfe6a09e667f3bcd, + 0xbfe7b5df226aafaf, + 0xbfe8bc806b151741, + 0xbfe9b3e047f38741, + 0xbfea9b66290ea1a3, + 0xbfeb728345196e3e, + 0xbfec38b2f180bdb1, + 0xbfeced7af43cc773, + 0xbfed906bcf328d46, + 0xbfee212104f686e5, + 0xbfee9f4156c62dda, + 0xbfef0a7efb9230d7, + 0xbfef6297cff75cb0, + 0xbfefa7557f08a517, + 0xbfefd88da3d12526, + 0xbfeff621e3796d7e, + 0xbff0000000000000, + 0xbfeff621e3796d7e, + 0xbfefd88da3d12526, + 0xbfefa7557f08a517, + 0xbfef6297cff75cb0, + 0xbfef0a7efb9230d7, + 0xbfee9f4156c62dda, + 0xbfee212104f686e5, + 0xbfed906bcf328d46, + 0xbfeced7af43cc773, + 0xbfec38b2f180bdb1, + 0xbfeb728345196e3e, + 0xbfea9b66290ea1a3, + 0xbfe9b3e047f38741, + 0xbfe8bc806b151741, + 0xbfe7b5df226aafaf, + 0xbfe6a09e667f3bcd, + 0xbfe57d69348ceca0, + 0xbfe44cf325091dd6, + 0xbfe30ff7fce17035, + 0xbfe1c73b39ae68c8, + 0xbfe073879922ffee, + 0xbfde2b5d3806f63b, + 0xbfdb5d1009e15cc0, + 0xbfd87de2a6aea963, + 0xbfd58f9a75ab1fdd, + 0xbfd294062ed59f06, + 0xbfcf19f97b215f1b, + 0xbfc8f8b83c69a60b, + 0xbfc2c8106e8e613a, + 0xbfb917a6bc29b42c, + 0xbfa91f65f10dd814, +]; + +#[inline] +pub(crate) fn reduce_small_pi64(x: f64) -> (f64, i64) { + // Generated in SageMath: + // z = RealField(300)(64) / RealField(300).pi() + // n = 32 + // x_hi = RealField(n)(z) # convert to f64 + // x_mid = RealField(n)(z - RealField(300)(x_hi)) + // x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + // print(double_to_hex(x_hi), ",") + // print(double_to_hex(x_mid), ",") + // print(double_to_hex(x_lo), ",") + const MPI_OVER_SIXTY_FOUR: [u64; 3] = + [0xbfa921fb54400000, 0xbd80b4611a600000, 0xbb53198a2e037073]; + const SIXTY_EIGHT_OVER_PI: f64 = f64::from_bits(0x40345f306dc9c883); + let prod_hi = x * SIXTY_EIGHT_OVER_PI; + let kd = prod_hi.cpu_round(); + + // Let y = x - k * (pi/64) + // Then |y| < pi / 64 + // With extra rounding errors, we can bound |y| < 1.6 * 2^-7. + let y_hi = f_fmla(kd, f64::from_bits(MPI_OVER_SIXTY_FOUR[0]), x); // Exact + // |u.hi| < 1.6*2^-7 + let u_hi = f_fmla(kd, f64::from_bits(MPI_OVER_SIXTY_FOUR[1]), y_hi); + (u_hi, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) +} + +struct SinCosPi64 { + v_sin: f64, + v_cos: f64, +} + +#[inline] +fn sincos_eval_pi64(x: f64) -> SinCosPi64 { + let x2 = x * x; + let x4 = x2 * x2; + + // Sin poly generated by Sollya: + // d = [0, pi/64]; + // f_sin = sin(x)/x; + // Q = fpminimax(f_sin, [|0, 2, 4, 6|], [|D...|], d); + const S: [u64; 4] = [ + 0x3ff0000000000000, + 0xbfc5555555555451, + 0x3f8111111072c563, + 0xbf2a01321c030841, + ]; + + let s0 = f_fmla(x2, f64::from_bits(S[1]), f64::from_bits(S[0])); + let s1 = f_fmla(x2, f64::from_bits(S[3]), f64::from_bits(S[2])); + let v_sin = f_fmla(x4, s1, s0) * x; + + // Cos poly generated by Sollya: + // d = [0, pi/64]; + // f_cos = cos(x); + // Q = fpminimax(f_cos, [|0, 2, 4, 6|], [|1, D...|], d); + const C: [u64; 4] = [ + 0x3ff0000000000000, + 0xbfdffffffffffb6c, + 0x3fa5555553f117c1, + 0xbf56c0f056672a03, + ]; + let c0 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let c1 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let v_cos = f_fmla(x4, c1, c0); + + SinCosPi64 { v_sin, v_cos } +} + +#[inline] +pub(crate) fn sin_small(z: f64) -> f64 { + let x_e = (z.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 26 { + return f_fmla(z, f64::from_bits(0xbc90000000000000), z); + } + + let (angle_dd, k) = reduce_small_pi64(z); + let sin_cos = sincos_eval_pi64(angle_dd); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 64) * pi/64). + let sk = SIN_K_PI_OVER_64[((k as u64) & 127) as usize]; + let ck = SIN_K_PI_OVER_64[(((k as u64).wrapping_add(32)) & 127) as usize]; + + let sin_k = f64::from_bits(sk); + let cos_k = f64::from_bits(ck); + f_fmla(sin_cos.v_cos, sin_k, sin_cos.v_sin * cos_k) +} + +#[inline] +pub(crate) fn cos_small(z: f64) -> f64 { + let x_e = (z.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 27 { + // Signed zeros. + if z == 0.0 { + return 1.0; + } + // For |x| < 2^-26, |sin(x) - x| < ulp(x)/2. + return 1.0 - min_normal_f64(); + } + + let (angle_dd, k) = reduce_small_pi64(z); + + let sin_cos = sincos_eval_pi64(angle_dd); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 64) * pi/64). + let sk = SIN_K_PI_OVER_64[((k as u64).wrapping_add(64) & 127) as usize]; + let ck = SIN_K_PI_OVER_64[(((k as u64).wrapping_add(32)) & 127) as usize]; + + let sin_k = f64::from_bits(sk); + let cos_k = f64::from_bits(ck); + f_fmla(sin_cos.v_cos, cos_k, sin_cos.v_sin * sin_k) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1022 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::alpha0::{ + bessel_0_asympt_alpha, bessel_0_asympt_alpha_fast, bessel_0_asympt_alpha_hard, +}; +use crate::bessel::beta0::{ + bessel_0_asympt_beta, bessel_0_asympt_beta_fast, bessel_0_asympt_beta_hard, +}; +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::j0::j0_maclaurin_series; +use crate::bessel::y0_coeffs::Y0_COEFFS; +use crate::bessel::y0_coeffs_taylor::Y0_COEFFS_TAYLOR; +use crate::bessel::y0f_coeffs::{Y0_ZEROS, Y0_ZEROS_VALUES}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log_dd_fast; +use crate::polyeval::{f_polyeval12, f_polyeval13, f_polyeval15, f_polyeval22, f_polyeval24}; +use crate::rounding::CpuCeil; +use crate::sin_helper::{sin_dd_small, sin_dd_small_fast, sin_f128_small}; +use crate::sincos_reduce::{AngleReduced, rem2pi_any, rem2pi_f128}; + +/// Bessel of the second kind of order 0 (Y0) +pub fn f_y0(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::NEG_INFINITY; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f64::NAN; + } + return 0.; + } + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x4052d9999999999au64 { + // x <= 75.4 + if xb <= 0x4000000000000000u64 { + // x <= 2 + if xb <= 0x3ff599999999999au64 { + // x < 1.35 + return y0_near_zero_fast(x); + } + // transient zone from 1.46 to 2 have bad behavior for log poly already, + // and not yet good to be easily covered, thus it use its own poly + return y0_transient_area_fast(x); + } + return y0_small_argument_fast(x); + } + + y0_asympt_fast(x) +} + +/** +Generated by SageMath: +Evaluates: +Y0(x) = 2/pi*(euler_gamma + log(x/2))*J0(x) - sum((-1)^m*(x/2)^(2*m)/(m!)^2*sum(1+1/2 + ... 1/m)) +expressed as: +Y0(x)=log(x)*W0(x) - Z0(x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() +N = 10 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() + +# Define J0(x) Taylor expansion at x = 0 +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J0_series = j_series(0, x) + +def z_series(x): + return sum([(-1)**m * (x/2)**(ZZ(2)*ZZ(m)) / ZZ(m).factorial()**ZZ(2) * sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) for m in range(1, N)]) + +W0 = (d2/pi) * J0_series +Z0 = -gamma * (d2/pi) * J0_series + RealField(300)(2).log() * (d2/pi) * J0_series + (d2/pi) * z_series(x) + +# see the series +print(W0) +print(Z0) +``` +**/ +#[inline] +fn y0_near_zero_fast(x: f64) -> f64 { + const W: [(u64, u64); 15] = [ + (0xbc86b01ec5417056, 0x3fe45f306dc9c883), + (0x3c66b01ec5417056, 0xbfc45f306dc9c883), + (0xbc26b01ec5417056, 0x3f845f306dc9c883), + (0xbbd67fe4a5feb897, 0xbf321bb945252402), + (0x3b767fe4a5feb897, 0x3ed21bb945252402), + (0xbaf5c2495706f745, 0xbe672db9f21b0f5f), + (0x3a90c8209874dfad, 0x3df49a6c656d62ff), + (0x3a12921e91b07dd0, 0xbd7ae90af76a4d0f), + (0xb992921e91b07dd0, 0x3cfae90af76a4d0f), + (0x39089b0d8a9228ca, 0xbc754331c053fdad), + (0x3878d321ddfd3c6e, 0x3beb3749ebf0a0dd), + (0x37e77548130d809b, 0xbb5cca5ae46eae67), + (0xb73a848e7ca1c943, 0x3ac9976d3cd4293f), + (0xb6c884706195a054, 0xba336206ff1ce731), + (0xb6387a7d2389630d, 0x39995103e9f1818f), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + + let w0 = f_polyeval12( + x2.hi, + f64::from_bits(W[3].1), + f64::from_bits(W[4].1), + f64::from_bits(W[5].1), + f64::from_bits(W[6].1), + f64::from_bits(W[7].1), + f64::from_bits(W[8].1), + f64::from_bits(W[9].1), + f64::from_bits(W[10].1), + f64::from_bits(W[11].1), + f64::from_bits(W[12].1), + f64::from_bits(W[13].1), + f64::from_bits(W[14].1), + ); + + let mut w = DoubleDouble::mul_f64_add(x2, w0, DoubleDouble::from_bit_pair(W[2])); + w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[1])); + w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[0])); + + const Z: [(u64, u64); 15] = [ + (0xbc5ddfd831a70821, 0x3fb2e4d699cbd01f), + (0xbc6d93e63489aea6, 0xbfc6bbcb41034286), + (0xbc1b88525c2e130b, 0x3f9075b1bbf41364), + (0x3be097334e26e578, 0xbf41a6206b7b973d), + (0x3b51c64a34c78cda, 0x3ee3e99794203bbd), + (0xbb1c407b0f5b2805, 0xbe7bce4a600d3ea4), + (0xbaa57d1e1e88c9ca, 0x3e0a6ee796b871b6), + (0x3a3b6e7030a77899, 0xbd92393d82c6b2e4), + (0x397fcfedacb03781, 0x3d131085da82054c), + (0xb8e45f51f6118e46, 0xbc8f4ed4b492ebcc), + (0xb89bd46046c3c8de, 0x3c04b7ac8a1b15d0), + (0x37d1a206fb205e32, 0xbb769201941d0d49), + (0x3782f38acbf23993, 0x3ae4987e587ab039), + (0x36b691bdabf5672b, 0xba4ff1953e0a7c5b), + (0x3636e1c8cd260e18, 0x39b55031dc5e1967), + ]; + let z0 = f_polyeval12( + x2.hi, + f64::from_bits(Z[3].1), + f64::from_bits(Z[4].1), + f64::from_bits(Z[5].1), + f64::from_bits(Z[6].1), + f64::from_bits(Z[7].1), + f64::from_bits(Z[8].1), + f64::from_bits(Z[9].1), + f64::from_bits(Z[10].1), + f64::from_bits(Z[11].1), + f64::from_bits(Z[12].1), + f64::from_bits(Z[13].1), + f64::from_bits(Z[14].1), + ); + + let mut z = DoubleDouble::mul_f64_add(x2, z0, DoubleDouble::from_bit_pair(Z[2])); + z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[1])); + z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[0])); + let w_log = log_dd_fast(x); + let p = DoubleDouble::mul_add(w, w_log, -z); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c50000000000000), // 2^-58 + f64::from_bits(0x3c30000000000000), // 2^-60 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y0_near_zero(x, w_log) +} + +/** +Generated by SageMath: +Evaluates: +Y0(x) = 2/pi*(euler_gamma + log(x/2))*J0(x) - sum((-1)^m*(x/2)^(2*m)/(m!)^2*sum(1+1/2 + ... 1/m)) +expressed as: +Y0(x)=log(x)*W0(x) - Z0(x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() +N = 10 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() + +# Define J0(x) Taylor expansion at x = 0 +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J0_series = j_series(0, x) + +def z_series(x): + return sum([(-1)**m * (x/2)**(ZZ(2)*ZZ(m)) / ZZ(m).factorial()**ZZ(2) * sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) for m in range(1, N)]) + +W0 = (d2/pi) * J0_series +Z0 = -gamma * (d2/pi) * J0_series + RealField(300)(2).log() * (d2/pi) * J0_series + (d2/pi) * z_series(x) + +# see the series +print(W0) +print(Z0) +``` +**/ +#[cold] +#[inline(never)] +fn y0_near_zero(x: f64, w_log: DoubleDouble) -> f64 { + const W: [(u64, u64); 15] = [ + (0xbc86b01ec5417056, 0x3fe45f306dc9c883), + (0x3c66b01ec5417056, 0xbfc45f306dc9c883), + (0xbc26b01ec5417056, 0x3f845f306dc9c883), + (0xbbd67fe4a5feb897, 0xbf321bb945252402), + (0x3b767fe4a5feb897, 0x3ed21bb945252402), + (0xbaf5c2495706f745, 0xbe672db9f21b0f5f), + (0x3a90c8209874dfad, 0x3df49a6c656d62ff), + (0x3a12921e91b07dd0, 0xbd7ae90af76a4d0f), + (0xb992921e91b07dd0, 0x3cfae90af76a4d0f), + (0x39089b0d8a9228ca, 0xbc754331c053fdad), + (0x3878d321ddfd3c6e, 0x3beb3749ebf0a0dd), + (0x37e77548130d809b, 0xbb5cca5ae46eae67), + (0xb73a848e7ca1c943, 0x3ac9976d3cd4293f), + (0xb6c884706195a054, 0xba336206ff1ce731), + (0xb6387a7d2389630d, 0x39995103e9f1818f), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let w = f_polyeval15( + x2, + DoubleDouble::from_bit_pair(W[0]), + DoubleDouble::from_bit_pair(W[1]), + DoubleDouble::from_bit_pair(W[2]), + DoubleDouble::from_bit_pair(W[3]), + DoubleDouble::from_bit_pair(W[4]), + DoubleDouble::from_bit_pair(W[5]), + DoubleDouble::from_bit_pair(W[6]), + DoubleDouble::from_bit_pair(W[7]), + DoubleDouble::from_bit_pair(W[8]), + DoubleDouble::from_bit_pair(W[9]), + DoubleDouble::from_bit_pair(W[10]), + DoubleDouble::from_bit_pair(W[11]), + DoubleDouble::from_bit_pair(W[12]), + DoubleDouble::from_bit_pair(W[13]), + DoubleDouble::from_bit_pair(W[14]), + ); + + const Z: [(u64, u64); 15] = [ + (0xbc5ddfd831a70821, 0x3fb2e4d699cbd01f), + (0xbc6d93e63489aea6, 0xbfc6bbcb41034286), + (0xbc1b88525c2e130b, 0x3f9075b1bbf41364), + (0x3be097334e26e578, 0xbf41a6206b7b973d), + (0x3b51c64a34c78cda, 0x3ee3e99794203bbd), + (0xbb1c407b0f5b2805, 0xbe7bce4a600d3ea4), + (0xbaa57d1e1e88c9ca, 0x3e0a6ee796b871b6), + (0x3a3b6e7030a77899, 0xbd92393d82c6b2e4), + (0x397fcfedacb03781, 0x3d131085da82054c), + (0xb8e45f51f6118e46, 0xbc8f4ed4b492ebcc), + (0xb89bd46046c3c8de, 0x3c04b7ac8a1b15d0), + (0x37d1a206fb205e32, 0xbb769201941d0d49), + (0x3782f38acbf23993, 0x3ae4987e587ab039), + (0x36b691bdabf5672b, 0xba4ff1953e0a7c5b), + (0x3636e1c8cd260e18, 0x39b55031dc5e1967), + ]; + let z = f_polyeval15( + x2, + DoubleDouble::from_bit_pair(Z[0]), + DoubleDouble::from_bit_pair(Z[1]), + DoubleDouble::from_bit_pair(Z[2]), + DoubleDouble::from_bit_pair(Z[3]), + DoubleDouble::from_bit_pair(Z[4]), + DoubleDouble::from_bit_pair(Z[5]), + DoubleDouble::from_bit_pair(Z[6]), + DoubleDouble::from_bit_pair(Z[7]), + DoubleDouble::from_bit_pair(Z[8]), + DoubleDouble::from_bit_pair(Z[9]), + DoubleDouble::from_bit_pair(Z[10]), + DoubleDouble::from_bit_pair(Z[11]), + DoubleDouble::from_bit_pair(Z[12]), + DoubleDouble::from_bit_pair(Z[13]), + DoubleDouble::from_bit_pair(Z[14]), + ); + DoubleDouble::mul_add(w, w_log, -z).to_f64() +} + +/** +Path for transient area between 1.35 to 2. +**/ +#[inline] +pub(crate) fn y0_transient_area_fast(x: f64) -> f64 { + /** + Polynomial generated by Wolfram: + ```text + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + ``` + **/ + const C: [(u64, u64); 28] = [ + (0xbc689e111675434b, 0x3fe0aa48442f014b), + (0x396ffb11562e8c70, 0x3cc1806f07aceb3c), + (0xbc6156edff56513d, 0xbfd0aa48442f0030), + (0xbc278dbff5ee7db4, 0x3fa439fac165db2d), + (0x3c1f9463c2023663, 0x3f80d2af4ebc8fc4), + (0xbbee09e5733a1236, 0x3f4f716488aebd9c), + (0xbbf261a1f255ddf4, 0xbf5444bd2a7e6254), + (0x3bd4f543544f1fe7, 0x3f384c300e8674d8), + (0xbb96ef8d95fe049b, 0xbf217a0fc83af41e), + (0x3ba2be82573ae98d, 0x3f0dbc664048e495), + (0xbb942b15646c85f2, 0xbef8522f83e4a3e3), + (0x3b7a127725ba4606, 0x3ee775c010ce4146), + (0x3ae4a02f0b2a18e2, 0x3e7d1d7cf40f9697), + (0x3b8fcf1a3d27236b, 0x3eea9c226c21712d), + (0xbb70b3aa0a1e9ffb, 0x3ef8f237831ec74b), + (0x3baa6c24261245f3, 0x3f08ebfea3ea469e), + (0x3bb5fa1b8c4587c4, 0x3f1474022b90cbda), + (0x3b69545db8d098d1, 0x3f1d153dc04c51c0), + (0x3bc68eab6520d21b, 0x3f2198a4578cb6ca), + (0xbbc255734bc49c8b, 0x3f2212febf7cecdd), + (0x3bb8dd02722339f5, 0x3f1f314deec17049), + (0x3bbb6ef8f04b26a2, 0x3f1657d051699088), + (0x3b878233fbf501dc, 0x3f0a1a422dafcef6), + (0xbb73730138d1dbc2, 0x3ef8423cd021f1dd), + (0x3b7e2a0d7009d709, 0x3ee145cae37afe1b), + (0x3b6af21aeaba4e57, 0x3ec1bc74380f6d7b), + (0xbb3607fb9242657f, 0x3e977341fc10cdc8), + (0xbac747923880f651, 0x3e5e30218bc1fee3), + ]; + + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + + let r = DoubleDouble::full_add_f64(-ZERO, x); + + let p0 = f_polyeval24( + r.to_f64(), + f64::from_bits(C[4].1), + f64::from_bits(C[5].1), + f64::from_bits(C[6].1), + f64::from_bits(C[7].1), + f64::from_bits(C[8].1), + f64::from_bits(C[9].1), + f64::from_bits(C[10].1), + f64::from_bits(C[11].1), + f64::from_bits(C[12].1), + f64::from_bits(C[13].1), + f64::from_bits(C[14].1), + f64::from_bits(C[15].1), + f64::from_bits(C[16].1), + f64::from_bits(C[17].1), + f64::from_bits(C[18].1), + f64::from_bits(C[19].1), + f64::from_bits(C[20].1), + f64::from_bits(C[21].1), + f64::from_bits(C[22].1), + f64::from_bits(C[23].1), + f64::from_bits(C[24].1), + f64::from_bits(C[25].1), + f64::from_bits(C[26].1), + f64::from_bits(C[27].1), + ); + + let mut p = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[0])); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3c50000000000000), // 2^-58 + f64::from_bits(0x3b10000000000000), // 2^-78 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return y0_transient_area_moderate(x); + } + p.to_f64() +} + +/** +Path for transient area between 1.35 to 2. +**/ +fn y0_transient_area_moderate(x: f64) -> f64 { + /** + Polynomial generated by Wolfram: + ```text + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + ``` + **/ + const C: [(u64, u64); 28] = [ + (0xbc689e111675434b, 0x3fe0aa48442f014b), + (0x396ffb11562e8c70, 0x3cc1806f07aceb3c), + (0xbc6156edff56513d, 0xbfd0aa48442f0030), + (0xbc278dbff5ee7db4, 0x3fa439fac165db2d), + (0x3c1f9463c2023663, 0x3f80d2af4ebc8fc4), + (0xbbee09e5733a1236, 0x3f4f716488aebd9c), + (0xbbf261a1f255ddf4, 0xbf5444bd2a7e6254), + (0x3bd4f543544f1fe7, 0x3f384c300e8674d8), + (0xbb96ef8d95fe049b, 0xbf217a0fc83af41e), + (0x3ba2be82573ae98d, 0x3f0dbc664048e495), + (0xbb942b15646c85f2, 0xbef8522f83e4a3e3), + (0x3b7a127725ba4606, 0x3ee775c010ce4146), + (0x3ae4a02f0b2a18e2, 0x3e7d1d7cf40f9697), + (0x3b8fcf1a3d27236b, 0x3eea9c226c21712d), + (0xbb70b3aa0a1e9ffb, 0x3ef8f237831ec74b), + (0x3baa6c24261245f3, 0x3f08ebfea3ea469e), + (0x3bb5fa1b8c4587c4, 0x3f1474022b90cbda), + (0x3b69545db8d098d1, 0x3f1d153dc04c51c0), + (0x3bc68eab6520d21b, 0x3f2198a4578cb6ca), + (0xbbc255734bc49c8b, 0x3f2212febf7cecdd), + (0x3bb8dd02722339f5, 0x3f1f314deec17049), + (0x3bbb6ef8f04b26a2, 0x3f1657d051699088), + (0x3b878233fbf501dc, 0x3f0a1a422dafcef6), + (0xbb73730138d1dbc2, 0x3ef8423cd021f1dd), + (0x3b7e2a0d7009d709, 0x3ee145cae37afe1b), + (0x3b6af21aeaba4e57, 0x3ec1bc74380f6d7b), + (0xbb3607fb9242657f, 0x3e977341fc10cdc8), + (0xbac747923880f651, 0x3e5e30218bc1fee3), + ]; + + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + + let mut r = DoubleDouble::full_add_f64(-ZERO, x); + r = DoubleDouble::from_exact_add(r.hi, r.lo); + + let p0 = f_polyeval13( + r.to_f64(), + f64::from_bits(C[15].1), + f64::from_bits(C[16].1), + f64::from_bits(C[17].1), + f64::from_bits(C[18].1), + f64::from_bits(C[19].1), + f64::from_bits(C[20].1), + f64::from_bits(C[21].1), + f64::from_bits(C[22].1), + f64::from_bits(C[23].1), + f64::from_bits(C[24].1), + f64::from_bits(C[25].1), + f64::from_bits(C[26].1), + f64::from_bits(C[27].1), + ); + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c10000000000000), // 2^-62 + f64::from_bits(0x3a30000000000000), // 2^-91 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return y0_transient_area_hard(x); + } + p.to_f64() +} + +#[cold] +#[inline(never)] +fn y0_transient_area_hard(x: f64) -> f64 { + const ZERO: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x8c9df6a6_ff921721_70d796f3_2017e155_u128, + }; + let r = DyadicFloat128::new_from_f64(x) - ZERO; + /* + Polynomial generated by Wolfram: + ```text + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + ``` + */ + static C: [DyadicFloat128; 28] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x85524221_780a573b_0f774c55_e5a946dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -178, + mantissa: 0x8c03783d_6759e3ff_622ac5d1_8df27811_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x85524221_78018115_6edff565_13cf55ab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xa1cfd60b_2ed96743_9200508c_125cf3d8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x86957a75_e47e21f9_463c2023_663178df_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xfb8b2445_75ecdc3e_c35198bd_b9330775_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xa225e953_f312a24c_343e4abb_be73338f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xc2618074_33a6c29e_a86a89e3_fcde0075_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -140, + mantissa: 0x8bd07e41_d7a0f05b_be3657f8_126b9715_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xede33202_4724aa57_d04ae75d_31ad69cd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xc2917c1f_251f1a85_62ac8d90_be4550ff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xbbae0086_720a31a1_27725ba4_605e0479_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xe8ebe7a0_7cb4b852_80bc2ca8_63864ee0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xd4e11361_0b896bf9_e347a4e4_6d642f8e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xc791bc18_f63a577a_62afaf0b_002753e2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xc75ff51f_5234f34d_8484c248_be6beef2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0xa3a0115c_865ed2bf_437188b0_f87883dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0xe8a9ee02_628e0019_545db8d0_98d12eff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0x8cc522bc_65b652d1_d56ca41a_43537f6a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0x9097f5fb_e766e5b5_5196876c_6ea798ce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0xf98a6f76_0b824b1b_a04e4467_3ea487e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0xb2be828b_4c84436d_df1e0964_d44f420f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xd0d2116d_7e77b0bc_119fdfa8_0ee2dfee_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xc211e681_0f8ee764_67f63971_21f1a199_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0x8a2e571b_d7f0d9e2_a0d7009d_70969fa2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0x8de3a1c0_7b6bdb5e_435d5749_cadf3edd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -149, + mantissa: 0xbb9a0fe0_866e3d3f_008db7b3_5029fe59_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -153, + mantissa: 0xf1810c5e_0ff717a2_e1b71dfc_26babb9f_u128, + }, + ]; + let mut z = C[27]; + for i in (0..27).rev() { + z = r * z + C[i]; + } + z.fast_as_f64() +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +pub(crate) fn y0_small_argument_fast(x: f64) -> f64 { + let x_abs = x; + + // let avg_step = 74.607799 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6299609508652038; + + let fx = x_abs * INV_STEP; + const Y0_ZEROS_COUNT: f64 = (Y0_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(Y0_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(Y0_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(Y0_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(Y0_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return j0_maclaurin_series(x); + } + + let is_too_close_to_zero = dist.abs() < 1e-3; + + let c = if is_too_close_to_zero { + &Y0_COEFFS_TAYLOR[idx - 1] + } else { + &Y0_COEFFS[idx - 1] + }; + + let r = DoubleDouble::full_add_f64(-found_zero, x); + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(Y0_ZEROS_VALUES[idx]); + } + + let p = f_polyeval22( + r.hi, + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + f64::from_bits(c[13].1), + f64::from_bits(c[14].1), + f64::from_bits(c[15].1), + f64::from_bits(c[16].1), + f64::from_bits(c[17].1), + f64::from_bits(c[18].1), + f64::from_bits(c[19].1), + f64::from_bits(c[20].1), + f64::from_bits(c[21].1), + f64::from_bits(c[22].1), + f64::from_bits(c[23].1), + f64::from_bits(c[24].1), + f64::from_bits(c[25].1), + f64::from_bits(c[26].1), + f64::from_bits(c[27].1), + ); + + let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[5])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[4])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0])); + let p = z; + let err = f_fmla( + p.hi, + f64::from_bits(0x3c60000000000000), // 2^-57 + f64::from_bits(0x3c20000000000000), // 2^-61 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return y0_small_argument_moderate(r, c); + } + z.to_f64() +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +fn y0_small_argument_moderate(r: DoubleDouble, c: &[(u64, u64); 28]) -> f64 { + let c0 = &c[15..]; + + let p0 = f_polyeval13( + r.to_f64(), + f64::from_bits(c0[0].1), + f64::from_bits(c0[1].1), + f64::from_bits(c0[2].1), + f64::from_bits(c0[3].1), + f64::from_bits(c0[4].1), + f64::from_bits(c0[5].1), + f64::from_bits(c0[6].1), + f64::from_bits(c0[7].1), + f64::from_bits(c0[8].1), + f64::from_bits(c0[9].1), + f64::from_bits(c0[10].1), + f64::from_bits(c0[11].1), + f64::from_bits(c0[12].1), + ); + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3a30000000000000), // 2^-91 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub != lb { + return y0_small_argument_hard(r, c); + } + p.to_f64() +} + +#[cold] +#[inline(never)] +fn y0_small_argument_hard(r: DoubleDouble, c: &[(u64, u64); 28]) -> f64 { + let mut p = DoubleDouble::from_bit_pair(c[27]); + for i in (0..27).rev() { + p = DoubleDouble::mul_add(r, p, DoubleDouble::from_bit_pair(c[i])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + } + p.to_f64() +} + +/* + Evaluates: + Y0 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) +*/ +#[inline] +pub(crate) fn y0_asympt_fast(x: f64) -> f64 { + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let recip = if x.to_bits() > 0x7fd000000000000u64 { + DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_div_fma(4.0, x), 0.25) + } else { + DoubleDouble::from_recip(x) + }; + + let alpha = bessel_0_asympt_alpha_fast(recip); + let beta = bessel_0_asympt_beta_fast(recip); + + let AngleReduced { angle } = rem2pi_any(x); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = sin_dd_small_fast(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let r_sqrt = DoubleDouble::from_rsqrt_fast(x); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3c10000000000000), // 2^-62 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64(); + } + y0_asympt(x, recip, r_sqrt, angle) +} + +/* + Evaluates: + Y0 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) +*/ +fn y0_asympt(x: f64, recip: DoubleDouble, r_sqrt: DoubleDouble, angle: DoubleDouble) -> f64 { + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let alpha = bessel_0_asympt_alpha(recip); + let beta = bessel_0_asympt_beta(recip); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = sin_dd_small(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3a20000000000000), // 2^-93 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + + if ub == lb { + return p.to_f64(); + } + y0_asympt_hard(x) +} + +/* + Evaluates: + Y0 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) +*/ +#[cold] +#[inline(never)] +fn y0_asympt_hard(x: f64) -> f64 { + const SQRT_2_OVER_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcc42299e_a1b28468_7e59e280_5d5c7180_u128, + }; + + const MPI_OVER_4: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let x_dyadic = DyadicFloat128::new_from_f64(x); + let recip = DyadicFloat128::accurate_reciprocal(x); + + let alpha = bessel_0_asympt_alpha_hard(recip); + let beta = bessel_0_asympt_beta_hard(recip); + + let angle = rem2pi_f128(x_dyadic); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_sin = sin_f128_small(r0); + + let z0 = beta * m_sin; + let r_sqrt = bessel_rsqrt_hard(x, recip); + let scale = SQRT_2_OVER_PI * r_sqrt; + let p = scale * z0; + p.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_y0() { + //ULP should be less than 0.5, but it was 1017.1969361449036, on 3 result 0.37685001001284685, using f_y0 and MPFR 0.3768500100127904 + assert_eq!(f_y0(3.), 0.3768500100127904); + assert_eq!(f_y0(0.906009703874588), 0.01085796448629276); + assert_eq!(f_y0(80.), -0.05562033908977); + assert_eq!(f_y0(5.), -0.30851762524903376); + assert_eq!( + f_y0(f64::from_bits(0x3fec982eb8d417ea)), + -0.000000000000000023389279284062102 + ); + assert!(f_y0(f64::NAN).is_nan()); + assert_eq!(f_y0(f64::INFINITY), 0.); + assert!(f_y0(f64::NEG_INFINITY).is_nan()); + } + + #[test] + fn test_y0_edge_values() { + assert_eq!(f_y0(0.8900000000138676), -0.0031519646708080126); + assert_eq!(f_y0(0.8900000000409116), -0.0031519646469294936); + assert_eq!(f_y0(98.1760435789366), 0.0000000000000056889416242533015); + assert_eq!( + f_y0(91.8929453121571802176), + -0.00000000000000007281665706677893 + ); + assert_eq!( + f_y0(f64::from_bits(0x6e7c1d741dc52512u64)), + f64::from_bits(0x2696f860815bc669) + ); + assert_eq!(f_y0(f64::from_bits(0x3e04cdee58a47edd)), -13.58605001628649); + assert_eq!( + f_y0(0.89357696627916749), + -0.000000000000000023389279284062102 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1517 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Y0 Remez poly coeffs at zeros and extremums +Generated by SageMath: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = 1.35 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.03 - zeros[i] + b = (zeros[i]) + 0.83 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.03 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(y0_zeros) +# print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 200; +bessel_y0 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_y0(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RealField(500)(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +def print_remez_coeffs(poly): + print("[") + for i in range(len(poly)): + coeff = poly[i] + print_double_double("", coeff) + print("],") + +degree = 27 + +print(f"pub(crate) static Y0_COEFFS: [[(u64, u64); {degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print_remez_coeffs(coeffs) +print("];") +``` +**/ +pub(crate) static Y0_COEFFS: [[(u64, u64); 28]; 47] = [ + [ + (0xbc7492c1ad707fcd, 0x3fe0aa48442f014b), + (0x3889cbe7f6454fdf, 0x3becdccc60399188), + (0x3c6201923a596bb0, 0xbfd0aa48442f014b), + (0x3c24b04e2557df22, 0x3fa439fac16525f5), + (0xbc059b63c3765131, 0x3f80d2af4e9323bc), + (0xbbdcec718054f585, 0x3f4f71646bea8f8b), + (0x3bf856364cecf8b8, 0xbf5444bda8b69d4e), + (0x3bda1cb8be57cc8f, 0x3f384c2206701bfd), + (0xbb8ae41d36dcce8d, 0xbf217ab4af8d0bf0), + (0xbba9cb2ac1552425, 0x3f0dafb9b99a70f2), + (0xbb951efcd9701bd5, 0xbef8bb9639d60207), + (0x3b8a10d871292a77, 0x3ee48b6751827819), + (0xbb709569bb189616, 0xbed1364cc5887f8d), + (0x3b248bd9aba7d332, 0x3ebd06afc4e97689), + (0x3b44874f3eb42a7d, 0xbea899b75531d45b), + (0xbb036dc9313b0b72, 0x3e94f157466889b4), + (0xbb15fb0fa7789259, 0xbe81e537d57e5872), + (0xbae227bb9fde16a8, 0x3e6ebca03e74f872), + (0x3ae23bb7c6812f3e, 0xbe5a95bfc7177df2), + (0x3ae9256929650559, 0x3e46b9b8baa2a7e6), + (0x3ac02e410dd7de2b, 0xbe32d4cd9df0cdc3), + (0x3ac47f4d926b3967, 0x3e2169d04e3c7866), + (0x3ab6f6c4b513d045, 0xbe12dac47ffdcb13), + (0x3a6fa8ccc9968ba6, 0x3dfa16bd9d2454ff), + (0xba171664de1838ee, 0xbda18f57d00cd0c8), + (0x3a636003e2d9973c, 0x3dcac3134b14f54c), + (0x3a5cb30d6a3e73d7, 0xbdd88bfc936d3a46), + (0x3a600c3863532a47, 0x3dc074a2bfd935a7), + ], + [ + (0xb6985ea12b68dbc6, 0xba0ce46bb97e3b37), + (0xbc5a4026e448075b, 0xbfd9c34256a12a0c), + (0xbc49ded6e42ffb00, 0x3faa09c9290367ef), + (0xbc253b026c745733, 0x3fadf6d59bf50ebd), + (0xbc18dbfc7b944e60, 0xbf7c116fdc598096), + (0x3bf40cf995f4f110, 0xbf61e32bc4ef8a41), + (0xbbcb82d9e30fbb8a, 0x3f29982765166254), + (0xbb7a0c04b5d6f2fd, 0x3f0ab2c1fecdcfc4), + (0x3b7cda0c15fabc6d, 0xbed486371e6a6640), + (0xbb079525b0987a4e, 0xbe93b21684089b98), + (0xbaf3ba730f1c40e9, 0xbe5777058741ab00), + (0xbaf583debf7de8c9, 0x3e5452ea009488fe), + (0x3ab98e298e66ceb6, 0xbe2f6938829aeacd), + (0x3aa9d6dc6976f3c9, 0x3e0a5a1f3a03d35d), + (0x3a7994a2d0f56a03, 0xbde994e7358cedf6), + (0x3a5a354bba4fc371, 0x3dc88ae5d31af5c1), + (0xba357cd4a8a94073, 0xbda75329787f3d8c), + (0xba2d0839c51ea186, 0x3d8643c578f084cf), + (0xba0526a2696c015c, 0xbd6554780d3aba1a), + (0xb9ec9b6ca0c2368e, 0x3d447c69a36927e9), + (0xb9b175a5c0e46062, 0xbd23b88e0a626f34), + (0x3994f94bb00b0bd0, 0x3d02fdee82cca7a8), + (0xb98eac61aa84bafd, 0xbce25983eb139aeb), + (0xb9685d6dfdbe7bfb, 0x3cc2440cd8848b87), + (0x3922fa28d497dc91, 0xbca164c6877c570d), + (0xb917682fb55945f7, 0x3c78a082a7dc3992), + (0xb90f407a50193eb2, 0xbc621ea0651d2198), + (0xb8c56e242114685f, 0x3c523596b99eb3ff), + ], + [ + (0x3c7b8d2a1c496808, 0xbfd5c7c556f0c19a), + (0x36068b8c3a0eb972, 0x396e4544b8708e19), + (0xbc6b8d2a1c496844, 0x3fc5c7c556f0c19a), + (0xbc2b4d44aaaf080d, 0xbf8564d4b1ed0d7e), + (0x3c2e4289c3ae4c4e, 0xbf8a15d92dfe3e27), + (0xbbedbea922f2213b, 0x3f4b438430469ff7), + (0x3bdc176048714c11, 0x3f37a8924cc2f914), + (0xbb7021dbf4219b23, 0xbef5f69b4a8a3c05), + (0xbb7729647a7cf1b3, 0xbed85b940eb607f9), + (0x3b3d99d888f48f01, 0x3e955ac0f5c3162c), + (0x3b0f25a287448fcc, 0x3e6d563e18b47eb8), + (0x3ac452983ff83fe5, 0xbe23eac3a45e06f4), + (0xbaa55a4be8b255ef, 0xbe0007671d55a8af), + (0x3a6681c171d8b7ac, 0x3dc04e13e8d2d63b), + (0xb9cb304019dc95a9, 0xbd46e2b306d18fe2), + (0xb9e569987d3c61bc, 0x3d54d18f7c808f5a), + (0xb9d65bf264af4caa, 0xbd349808958007f4), + (0x39af1658e9591f8b, 0x3d0a5b43a3168022), + (0xb98b94f19368caef, 0xbce1c9c4d5c7e2e7), + (0xb91d94e29089b67f, 0x3cb933cacbb762ef), + (0xb931aa0bcf9e385e, 0xbc91c66b5e59c10e), + (0xb907d452cfe5d11e, 0x3c690530621ffb6d), + (0x38e2fc94e9e2e560, 0xbc41a7142b188ece), + (0x389fe83adc9ec098, 0x3c18ea69b49fa0ec), + (0x386baf69f710f067, 0xbbf186b62773cb8b), + (0xb830ab83fea718cc, 0x3bc97ee300661ddb), + (0xb841e9ca9ef3f273, 0xbba4203d2c71dee3), + (0x381487ed7b4c5c12, 0x3b7779cb668f4f30), + ], + [ + (0x35f13ef25b4edb08, 0x3952841995e45c48), + (0xbc78d4484b7cd2a7, 0x3fd334cca0697a5b), + (0xbc341c66c86d3ee2, 0xbf95aef611fc4d57), + (0xbc44929b43aab7e3, 0xbfa8969c64cbf452), + (0x3bfab353487eb8be, 0x3f6b2f14a95527cb), + (0x3c0aa67a62fa8841, 0x3f61d35e85fde2a3), + (0xbbb270ba54528c94, 0xbf226dd71e391c8b), + (0xbb61863ae7da7a16, 0xbf08177e4fe52324), + (0x3b4949552d9354dc, 0x3ec6a9227352f96a), + (0xbb44a5b99cf95459, 0x3ea34aa7573ef14e), + (0xbb0698b7b84362ae, 0xbe60a2814d7ac448), + (0xbad900bb94c56b91, 0xbe3442a3d3359ad9), + (0x3a8ac6ca8212a487, 0x3defa6c509566c72), + (0x3a56a6cae4d17a25, 0x3dbf14e5584823d7), + (0xb9f7410034885564, 0xbd7714c292be3962), + (0x39d1bcc695f4f231, 0xbd40679cd58549e2), + (0x3997214169109d52, 0x3cf3365d5a792113), + (0xb95497cd3660e90c, 0x3cc38cf06b3134d3), + (0xb92ac63766c35618, 0xbc82bd5a84bf3644), + (0x38dd10b30698d66a, 0x3c326e932d44d957), + (0xb8bf280f5863dcdc, 0xbc1271150465312d), + (0xb878f6f4bf335d0d, 0x3be8df3e61da29e5), + (0x384a254e3a1a9970, 0xbbb9b1263c861574), + (0x381db06e04e97e27, 0x3b8b3ef4b052ee69), + (0xb7f2c3a3c46974ad, 0xbb5da7aeb72ad1b2), + (0xb7c4810afcc72e8d, 0x3b2fdbbcc787affa), + (0x37a36df7ebbbb4ed, 0xbb031287031f9ece), + (0xb75db740f07d1867, 0x3ad85ce53417a3c0), + ], + [ + (0x3c61dc672a53c590, 0x3fd15f993fceab5c), + (0x35ea878b9ff55f5c, 0xb946a81d8aec1515), + (0xbc51dc672a53c58f, 0xbfc15f993fceab5c), + (0xbc0d1c390189caf7, 0x3f758ef6efbed797), + (0xbc243ede64b782d9, 0x3f86395dfe49fcd4), + (0xbbbb4484582c217c, 0xbf3fb15104a41c00), + (0xbbd4410e752beb78, 0xbf35f88a11d5564f), + (0xbb8b2d9b83a5b450, 0x3eef37d226a824b7), + (0xbb61fb1782379734, 0x3ed6f7bab104f355), + (0x3b2da2cb873ba95e, 0xbe8f0c45a3824d70), + (0xbac11338801bec18, 0xbe6dfe11df12c715), + (0xbac52938286abb6d, 0x3e2311adc2e753ee), + (0xba9200612bccbf82, 0x3dfad34e18504e16), + (0xba4c6eb5b9fade2d, 0xbdafdc8061ae8b15), + (0xba251747464962f8, 0xbd819498ca6cef9b), + (0x39d9f9efcc54f4de, 0x3d33a291d5991f6b), + (0x39af3f93679996f3, 0x3d016f7ae80cadff), + (0xb9422e176854fc2b, 0xbcb1f8d80decb659), + (0xb8ef665f3b08f8e4, 0xbc7c27b5350d7ce7), + (0x38af81adc69c8ae0, 0x3c2d08034e0e0d4c), + (0xb88ed31bb5296f3b, 0x3befac201220d678), + (0x37f6dcad77609354, 0xbb93e9257bbbec92), + (0x37f2bad6f8609fad, 0xbb6dce086bd954ec), + (0x37c3c466a462a963, 0x3b2c45f44eeac691), + (0x377aca1c9e5ead22, 0xbaebf82d453f586e), + (0x371d5ba887167511, 0x3abef01a452e6243), + (0xb6e1a818be163885, 0xba8faba1ac8fc141), + (0xb6f75474af743fde, 0x3a59bbaf9916fed8), + ], + [ + (0x360f6f90e85783b8, 0x396e539ee4be998b), + (0x3c61e8f568f8c6b6, 0xbfcff635cc72b9f1), + (0x3c0fa6ebe8b754aa, 0x3f89036451ff57c5), + (0x3c46345bcf3c5b81, 0x3fa4e667a71556af), + (0x3c065e386829f088, 0xbf60325ee41e910c), + (0x3bfde6b6846da9c7, 0xbf5fe23914fb9128), + (0xbbb9c28522c54b49, 0x3f17f84d7c50e4c4), + (0xbbaeab0290c997f1, 0x3f06afdd57be1e14), + (0xbb2bbdfb6c40ca93, 0xbec04053abf4386a), + (0x3b3787c4b69beaba, 0xbea2aea9ec48d8fd), + (0xbaf17a36377f9c62, 0x3e593eb9f1ddb4e9), + (0x3ad9f8321f3ce337, 0x3e3428a3a3e30a13), + (0xba49c9c135d6bfa4, 0xbde99d8c42f7a020), + (0xba59203ca37ccc7f, 0xbdbec9805045aa58), + (0xba08ceab2aadd382, 0x3d72613659ce994f), + (0xb9e8053d9b1a7b6c, 0x3d418f302bdba980), + (0xb96ea7068003a9dc, 0xbcf3bc9ccb704250), + (0xb93e32e516fbc8fc, 0xbcbf0dc4067be8fe), + (0xb91a819a6b2cfdb1, 0x3c706e491f458177), + (0xb8b2f6e0e017d3a4, 0x3c36013bac772fd5), + (0xb88860e3b038bbbc, 0xbbe616b4d60c99dd), + (0x38440765a3381ed6, 0xbba93fb6fc116a65), + (0x37f070ddd36dbc13, 0x3b57963a3ba9df68), + (0x37b30f1b7dcdc2ea, 0x3b1937f28596352a), + (0x3760f019da1d4947, 0xbac837f92e435c71), + (0xb6cfd07d0b99a723, 0xba80a4be8fbdea42), + (0xb6b4329fac42bf24, 0x3a19c0ce24bac50d), + (0xb69a16105af87cd5, 0x39ff46fe69318a2c), + ], + [ + (0x3c54d14c77bc1691, 0xbfcdc14ea14e89f9), + (0xb61ccfd68577b5e8, 0xb97a750db049a3bc), + (0xbc44d14c77bc1688, 0x3fbdc14ea14e89f9), + (0x3c00ff03f975831b, 0xbf6b037fe9cf2a52), + (0xbc2f19a8f5b137a3, 0xbf8367d7d608e4ba), + (0x3bdd892317f290f5, 0x3f34abef5636e4f7), + (0x3bd5ba5b5b609686, 0x3f33d8a661229259), + (0xbb700a3f0097a359, 0xbee5cfe92a1a2c45), + (0xbb6087e84c57990c, 0xbed571814a1aa301), + (0x3b22b6740db0f074, 0x3e87414e33c9bacd), + (0x3afa4836a20e8280, 0x3e6ca7069e73d1d9), + (0x3abe65fd39b0188a, 0xbe1e0b3a705ff247), + (0x3a95774f6fa018cb, 0xbdfa15dd62cf9f10), + (0xba399e86b7dd9f12, 0x3daa33948eada12c), + (0x3a22398b28ff34ba, 0x3d81419b1fd428ef), + (0x39c9ae1ea6c0045a, 0xbd30882f60b8a775), + (0x39a31e54bbe9a33e, 0xbd015e5c0af749d4), + (0x39454d020e06c1f7, 0x3cafb1e115e089b2), + (0x3910a4f9eea95a23, 0x3c7b83826370860f), + (0xb8c57c15f2ff0eb8, 0xbc27e5d539874c6c), + (0xb87dc14618f0e43b, 0xbbf19dae391ff57d), + (0xb82fe2e247291923, 0x3b9d2b7278390d46), + (0x37f3825b1f8b77eb, 0x3b6298bb72cef60f), + (0x37a7910d5f5dc998, 0xbb0d50bc222d50f5), + (0x3776acb65e1367e0, 0xbad08ac20d33e370), + (0x37062a8b170aa42b, 0x3a79154a0ab2b1c5), + (0xb6d06d11501acdf8, 0x3a3884b2a5dd01b8), + (0x36832f558f511cbf, 0xb9e1c3f19ed31df1), + ], + [ + (0xb5d1f4401b5b78db, 0x396e44a7ff47853b), + (0x3c41398cacaa32cb, 0x3fcbf32a27594007), + (0x3bfe5ce4af72439b, 0xbf80bc2d84e65214), + (0x3c4acd5148eb7ea0, 0xbfa26cab38a8b368), + (0x3bfab9a1103e209b, 0x3f55f03e47165d72), + (0xbbc4598141a3f87e, 0x3f5caaa76e34992d), + (0xbbbb7ab55e886663, 0xbf10c5f18c46d030), + (0xbb99f58bad5e7b5f, 0xbf04f0af7d46cd48), + (0xbb3040f00afdd8ce, 0x3eb7d1e28094e21a), + (0xbb3f12deda9fd086, 0x3ea1ad0731228479), + (0xbae9fe69a18b2b74, 0xbe536021c8cb3c34), + (0x3ad92bf3eabb82c3, 0xbe3371ae6c759181), + (0x3a630cb928debacf, 0x3de46ce077a8bed7), + (0xba5feb436591c0b8, 0x3dbe235d3564b639), + (0xb9d711ddaf978bf4, 0xbd6e408e259c72fb), + (0xb9c9d325620234dd, 0xbd415f07ac87e832), + (0x399b66d31155b6c3, 0x3cf0a44f77f6a8ee), + (0xb927de212062774e, 0x3cbefd8ab52f8ec1), + (0x38daebbaa8d140b4, 0xbc6c54ebb5ad3567), + (0xb8d1c883890c6817, 0xbc360b43cbb605a1), + (0x38851f7136cf7e49, 0x3be33d74aac5c469), + (0xb84c8ae944909141, 0x3ba99bfbb428a4d1), + (0xb7f50f7d69247480, 0xbb555c095b9d3de2), + (0xb78d195ad02b9a0b, 0xbb18c29d6b596412), + (0x37588e53fd261c0a, 0x3ac3c05d45a0cec2), + (0xb722c1c138d71c9e, 0x3a843feaf2fed511), + (0xb6c263b564f34be6, 0xba2ec5c49e1d5e88), + (0x36731f7cd8008380, 0xb9ec82a1b1f74089), + ], + [ + (0x3c57ba12cd0fc91f, 0x3fca7022be084d99), + (0xb5db8122d606073c, 0xb9614f36f1550bec), + (0xbc47ba12cd0fc91d, 0xbfba7022be084d99), + (0xbc0b3327197c9ced, 0x3f62ee079d020b12), + (0x3c2d0f8f3671311f, 0x3f8163191c30aa62), + (0xbbcc7f2dbb383293, 0xbf2d7806ea72fc76), + (0x3bcf9ec581434d48, 0xbf320f95702b1d4e), + (0x3b899e1a0f3c0abe, 0x3ee00610882294aa), + (0x3b61505ce3b25d40, 0x3ed3e398cbc472ea), + (0xbae050c778e973e5, 0xbe81bbe181c65162), + (0xbb0c3fb832d7b54d, 0xbe6b0f89b7c61f3a), + (0x3ab91b7cb5170340, 0x3e17c3f85882049b), + (0xba976a7f60f10aab, 0x3df90236614c84dc), + (0xba43abb3499d78c0, 0xbda564920d1387dc), + (0x3a2b1f00d1e27499, 0xbd80be1811255cfe), + (0x39b7396b68be0fd5, 0x3d2bb9712586bfac), + (0x39a50316c82a22d1, 0x3d0101c31e1df222), + (0xb93cd112332c006f, 0xbcab298cda76e792), + (0x39181c12a03d0651, 0xbc7b22acc441d614), + (0xb8cf36eb93d76394, 0x3c24dca37a331862), + (0x387338c4943fcecc, 0x3bf176e94edd9a37), + (0xb7ed97a80ea3375c, 0xbb99d4f0d7cf230e), + (0x37c85bd213356682, 0xbb6287584fe1cda1), + (0xb7957f660392a1e8, 0x3b0a5c024222d0c1), + (0xb7798291e622cf2f, 0x3ad07cad512e27f5), + (0xb712f27bce7fdd19, 0xba76918588d0c395), + (0xb6d55b12c898a874, 0xba38d39ee7749b0b), + (0xb680c165d28960ac, 0x39e0d21cd12bf761), + ], + [ + (0x360f530de8a2298c, 0xb96ccd9d9aa9b157), + (0xbc65b9c39e42719c, 0xbfc925c35988ee29), + (0xbbdda9c0588bab35, 0x3f7862549367591e), + (0x3c4a142ed6a5521c, 0x3fa0a4512039d6a2), + (0x3be94ce533c65b81, 0xbf5013b38cfb9292), + (0xbbea2a14cf0f61a4, 0xbf5a24a1215f6684), + (0xbbae7b4c448b426e, 0x3f08f91421377fad), + (0x3baf72fd0f5209e6, 0x3f035d17cec0172f), + (0x3b3cd242e4f6fc44, 0xbeb2283a93114096), + (0x3b259dda3f9805c1, 0xbea099e71392f54e), + (0xbad6dce1c34353e2, 0x3e4e5de01e2e6566), + (0xbab52eec6344539e, 0x3e32885854ea8b06), + (0x3a6795d88d7a428b, 0xbde0730c2985fd22), + (0x3a4e069c266df28e, 0xbdbd1743cbb2e11a), + (0x3a0121929f450b8e, 0x3d68f8728745e1e6), + (0x39de1722c384607b, 0x3d40f166cb29a7d1), + (0xb98c9b7f51aa7e71, 0xbcec10e67c004e39), + (0x39306913ae262394, 0xbcbe7aec1ba33e89), + (0x38d8c6bf0ecbf421, 0x3c68543e12c9bcc0), + (0x38d880f40d10394c, 0x3c35d3939f6d29f1), + (0xb885e7f0bd8af4c8, 0xbbe0c7ba1192da1c), + (0xb84abbb402955d93, 0xbba97d91773fae0d), + (0xb7c3bf48e2c5ddfc, 0x3b52dfb951fe4ab6), + (0xb7ac27c13775b2fb, 0x3b18c04f68a8baaf), + (0xb751cb733bb217c3, 0xbac1a783b2905f0d), + (0xb72e01e5e434cb26, 0xba844df5fac82b00), + (0x36c6a6f050600220, 0x3a2bbf5dc58ec268), + (0xb672c2ec04596698, 0x39ec99f34bc330e3), + ], + [ + (0xbc63db68c567283b, 0xbfc80781c32422e7), + (0xb60d9441230a8778, 0x397deb1fbbaf8566), + (0x3c53db68c5672838, 0x3fb80781c32422e7), + (0xbbfab5094c039945, 0xbf5c6923374d561f), + (0xbc032419a9d405ca, 0xbf7fbe6df840847f), + (0x3bc0f03bc2e75f5d, 0x3f264f4711a85f1a), + (0x3bbd9972e6c197c9, 0x3f309ff42b0d7a68), + (0xbb61aba5a7ce6e95, 0xbed8a60685a597d9), + (0xbafdb153b11ed74e, 0xbed282d26a74c38e), + (0xbb1d21d4a93dbe75, 0x3e7bdb57a889a4c1), + (0xbb099a040b2ccf5b, 0x3e697d9c12a60cef), + (0x3a35e0f484533648, 0xbe131aa8691738fb), + (0x3a93c99c395b5c9a, 0xbdf7d486eee39a85), + (0x3a223dad46ae9400, 0x3da197f258214b3d), + (0xba1654ac01c16c13, 0x3d801dd7f92195ff), + (0xb9cbde35eb70ebd4, 0xbd27480b9efaa860), + (0x39a7bbce185d5c09, 0xbd00833ea1f83461), + (0x393326656e27aad9, 0x3ca73bf7964edc39), + (0x391e8e85dd3ba305, 0x3c7a891d704fed29), + (0x38c6737263e77e58, 0xbc22222dcf097253), + (0x3815c44bf33c3053, 0xbbf12db9d219b624), + (0xb83a6ffdfedc9a0a, 0x3b96c4638eb6d0ab), + (0xb7f870f3fdb66e9d, 0x3b624ff29cc34a5f), + (0x3784f30eee231ab0, 0xbb0782fe0a2ed548), + (0x376d3a1f2a7e18f9, 0xbad05b98a2d38bad), + (0xb6fbbf0362b64b66, 0x3a745719daf0033a), + (0xb6b5c16ada4dc5fa, 0x3a38b51735f94ad1), + (0xb668156ec309831f, 0xb9de827eef669a9e), + ], + [ + (0xb5d71d9a0e2250f8, 0x3932accf9d404efd), + (0x3c64fef53f4893e5, 0x3fc70c4f66cab47f), + (0xbc1e032768318e73, 0xbf72c6731071e936), + (0x3c2f806b21bc9578, 0xbf9e924b85a17361), + (0xbbe1434be87c634b, 0x3f48d6c364d92082), + (0x3bf5cbe0638f4cee, 0x3f58247b02d6b0f6), + (0xbbaade8b3660fd3f, 0xbf0376125938561d), + (0x3bae81e47dd3839a, 0xbf0206da232a2b6a), + (0x3b424b3c317353f9, 0x3eacaf84db871510), + (0xbb022e3bac6444e5, 0x3e9f3671177306ca), + (0x3a9f8b17e5f17584, 0xbe48654b001006cd), + (0x3ad272b91e39e04f, 0xbe3199ec88b18766), + (0x3a6b9a2ed7b2626d, 0x3ddaeb1a849305fb), + (0x3a57caf104216cf2, 0x3dbbe67c197c48c0), + (0xb9c6b55595b8d04e, 0xbd64cdfa0bd69898), + (0xb9dbab7dec1030e5, 0xbd4064936f97922f), + (0xb978bade7534a976, 0x3ce7c83b5186222e), + (0xb95c7c9291c10511, 0x3cbdb73ad7fa8bcd), + (0x38c3fe342ee888e5, 0xbc64eecbf0b91aab), + (0xb8ddc5bba4aa2657, 0xbc356ab697c0b36f), + (0xb85034aab887d3c4, 0x3bdd4506fe39afb4), + (0x383d49e7992e0ac5, 0x3ba925d81aa2ac79), + (0x37e1c2dbc1cbe029, 0xbb50a89d8a666333), + (0xb7b31ae47aa79118, 0xbb18875d46ae8913), + (0xb75fe255d6973d67, 0x3abf7e2c067e0a91), + (0x37086207483b1723, 0x3a8432812904a786), + (0x36a9a69e34c77135, 0xba28f9cef0d7c221), + (0x366e1739129c6d8d, 0xb9ec7ae64440285f), + ], + [ + (0xbc6d2f0105f3ce7c, 0x3fc62d94d97e859c), + (0xb6196ae975958785, 0x3977cba836bb33ee), + (0x3c5d2f0105f3ce79, 0xbfb62d94d97e859c), + (0xbbf6c13bde837d51, 0x3f565481b55eaefb), + (0x3c17013075a066fe, 0x3f7d5f857a2a6107), + (0x3bc5f065aa633b82, 0xbf21a015a2ccb78f), + (0xbbc12f349174f00d, 0xbf2eeb4eafd8614b), + (0xbb53525d6141b63b, 0x3ed3a7b79e4d80fc), + (0xbb662d899f08e930, 0x3ed154ed4598d2f0), + (0xbb0444753ed61eee, 0xbe767f762ea293a1), + (0xbafe11bb6d8cf182, 0xbe680ec1e042ee62), + (0x3aa725a69e88f41a, 0x3e0f529652b9de0f), + (0xba97b07721f181ff, 0x3df6ad7bd2247f55), + (0x39e37ab8d29d6ed4, 0xbd9d4e582fb43553), + (0x3a1f7027dbae57b9, 0xbd7eeb6efcbb6228), + (0x39c89f73cf547041, 0x3d23b1eabb5c1c2c), + (0x39960a6cdd6c228d, 0x3cffe92f0882b43f), + (0xb94a0a88609a2efa, 0xbca3f20671568bda), + (0xb917e7036f59109d, 0xbc79ce30ac166c3b), + (0xb8b710f5a0405cb7, 0x3c1f8db6e94f5c58), + (0x388042b39eb414de, 0x3bf0cc90c05bf217), + (0xb83bf397bb30cb6c, 0xbb940c6bba534367), + (0xb7f70d1d6ed27860, 0xbb61fe3820203226), + (0xb77b9fa8fe59f5f1, 0x3b04ed91184b349c), + (0x377e0b12ab59c923, 0x3ad023371cf7aa58), + (0x370fad8a026e8d00, 0xba72475258dcb995), + (0x36d50611a23601a2, 0xba3874f481897d45), + (0xb67546ab95be8675, 0x39db9a35cb0268a5), + ], + [ + (0xb6160b0c9b9ffd9f, 0xb97a3923dc9c072f), + (0x3c5fe2103f7148c0, 0xbfc5664d37c37d7b), + (0xbc0a0fbbe8bcf31e, 0x3f6e0ee8ec84659a), + (0xbc383a77d074bd10, 0x3f9c6c415c971b4b), + (0xbbb06fe5233f1827, 0xbf43ec49cb941f55), + (0x3bfe14142e172805, 0xbf56853b2d047885), + (0xbb98cea461592a31, 0x3eff632a9396fd4e), + (0xbba049885559b284, 0x3f00e6afa01af561), + (0x3b452a854998ce1f, 0xbea7541247acdf59), + (0x3b3a7242d1d8f2ff, 0xbe9d735e8beb8fcc), + (0xbae93d2eb5241282, 0x3e440e6a7cafc096), + (0x3acae709b26c74f3, 0x3e30b9cfae2ab337), + (0x3a72d6e49ffa1efb, 0xbdd668087e67279b), + (0x3a5eab7f746fd96e, 0xbdbab498e6f69c73), + (0x3a0c7eba82778adf, 0x3d618b5674894afb), + (0xb9dabc635cef6b79, 0x3d3f99da023c7232), + (0x396198c6e558139c, 0xbce450b8165c264b), + (0xb9379aa14a14f4cc, 0xbcbcd387688c5092), + (0xb8d00bf3298263f3, 0x3c621a103bd09ea7), + (0x38c2b31b04643f75, 0x3c34e540faeea510), + (0x387fbfca69c0c002, 0xbbd999b3cf8b9794), + (0xb84578c966f9c437, 0xbba8a8f1c19ab5c8), + (0xb7d1af3943438fb6, 0x3b4d71c31555dffa), + (0xb797b6eaed91b502, 0x3b18289e061910a0), + (0x371f92726b30b6ae, 0xbabc18185dc0f589), + (0x372dd6314cb1a609, 0xba83f7bf0ecd3312), + (0xb6b22addb7be68de, 0x3a2677b40b678a01), + (0xb6852d3eb4bf8c8d, 0x39ec35403f3feccb), + ], + [ + (0xbc5e9088e9ff2519, 0xbfc4b2a38f1ab9b4), + (0xb5e56cdffbbb5799, 0xb95b36c3b9e47f10), + (0x3c4e9088e9ff251a, 0x3fb4b2a38f1ab9b4), + (0xbbfcc8083276a072, 0xbf5225a5c73f2233), + (0x3c1525fe797e2125, 0xbf7b750d89a9b35f), + (0xbbb08db59499cc78, 0x3f1cbdb4f1d5dbbd), + (0x3bc35c23938c8103, 0x3f2cfe933fc6d0b8), + (0x3b52d453a3ea1d43, 0xbed01ef10d839bbc), + (0x3b71cffb5ca02d28, 0xbed05375a588a72b), + (0xbb03f71b7795fb19, 0x3e729afe7ea7ba43), + (0x3af336f1328c096c, 0x3e66c8fe015e6610), + (0x3aa95a6cae05afad, 0xbe0a2a01e7af0241), + (0xba78518ab4937cc9, 0xbdf59b33050d2092), + (0xba24b06fe0fbe4ff, 0x3d98c0a50e7852d3), + (0x3a16de13327f4ad6, 0x3d7da3426f355690), + (0xb9cf30f26c9fd872, 0xbd20d3b48429ce84), + (0x399b0cd9583574ed, 0xbcfec46e14cd5d9d), + (0xb948a60ceb0a4c6f, 0x3ca13c3da7405df7), + (0x39055845c840358d, 0x3c79043b4a0f0164), + (0xb8a1906c502f6088, 0xbc1b902f4b27239f), + (0x3883b1fc8ff5cfb3, 0xbbf05dbe7502cf7d), + (0x3824e300158ee2c9, 0x3b91b0f5dc9eb0ab), + (0x3803c301aa3c55ff, 0x3b619b550a0380e8), + (0x37a48585c1f9fef8, 0xbb02a3e12dd3a21e), + (0xb755a96cd7834eba, 0xbacfb47bc6c98397), + (0x3705d5f51aa77044, 0x3a706b51c73e4699), + (0x36cba3931d96b5c4, 0x3a381b0b33df04c5), + (0x367c6c6e733152da, 0xb9d8f4cc5f2cd78e), + ], + [ + (0xb6025bf8fd89fcf9, 0xb972fca96d67ab3c), + (0x3c5f3474ffad3fda, 0x3fc40f8ffdf09a5f), + (0x3c047810b9792fcf, 0xbf68c37a29c4586f), + (0xbc348471cc77dfe6, 0xbf9aab099314b209), + (0x3be6aa80fcd0444f, 0x3f406f735cc0f6a6), + (0x3bebe02c39288577, 0x3f552d29a06802e0), + (0x3b89fdf10253db0c, 0xbef9fc04c675c0ed), + (0xbb62f9306dab6a7d, 0xbeffe48825ed3c8e), + (0x3b4325167726e7d5, 0x3ea36bd2d58ff45b), + (0xbb2af08b6d9e350f, 0x3e9be87e2cad2ce7), + (0xbaec807c6aa50609, 0xbe40d1fdedc6cb17), + (0xba7064ddbed15f1c, 0xbe2fdbeb107ddccf), + (0x3a758934a4493d29, 0x3dd2f44d01321684), + (0xba4232e1c56c35a5, 0x3db9921373ea0f26), + (0xb9d9c42dee5eb68c, 0xbd5df6b83ac56981), + (0x39db0125ce11e878, 0xbd3e6c005b62bffa), + (0x3945c956b1073d49, 0x3ce1848c91de7161), + (0xb95e0318e089dc41, 0x3cbbe5530d0fcf21), + (0xb8fe3f75946d3513, 0xbc5f8540b8b05bd4), + (0x38b0d6e492206c61, 0xbc3451eb9bf04528), + (0xb875fecfd5f528a6, 0x3bd67f1edd3c6bd2), + (0xb84a4a9a4b0746cb, 0x3ba8169212ae867e), + (0xb7b418bb0baae011, 0xbb4a1a0ded4a699f), + (0x378a8c57d3055718, 0xbb17b199d846adfb), + (0xb72c6c0833446ef6, 0x3ab91bb0a0b6110c), + (0xb701ddf674f848ee, 0x3a83a75f8b7df40d), + (0xb6bc25ec9cd09377, 0xba243ac68cfbb83d), + (0xb6618a00b084ab2f, 0xb9ebd3094ccdd46d), + ], + [ + (0x3c4997782859a00d, 0x3fc37aaceac987b9), + (0x360c6c83fa2a3645, 0xb97062679197f9db), + (0xbc3997782859a008, 0xbfb37aaceac987b9), + (0xbbd05a6eb7d72466, 0x3f4e3fdbfd65014a), + (0x3c1d91e80a0529b4, 0x3f79de7a33bc3a97), + (0xbbb56ef10c1ebcd7, 0xbf1801d911fbd06c), + (0x3bcce92f388f20fc, 0xbf2b605a5ade3a80), + (0xbb539bcd81dc9893, 0x3ecb0a2608144a3d), + (0xbb6b367577014662, 0x3eceeceb341ad833), + (0xbaf6cb1030890b1a, 0xbe6f623fc7be9f9f), + (0xbb0412babf35582b, 0xbe65a9ca94a0d7dd), + (0x3a9025c74264c26e, 0x3e0638ba2f5f5e6b), + (0xba745be766d5eb9d, 0x3df4a1b4217ef864), + (0xba32b2b63b552f66, 0xbd9530c712e738d4), + (0xba0b3a7b1b9435f0, 0xbd7c6e5208e89146), + (0x39aef5cdd93013e3, 0x3d1d0eb5303a804a), + (0x3990081346d33170, 0x3cfda6ae03deea13), + (0x39354c124a1478d1, 0xbc9e05ef8aaeac88), + (0x3913481334a524ae, 0xbc783796c23b10d8), + (0xb898c79983099259, 0x3c183703be1e37be), + (0x386b3b99444e2d90, 0x3befd20ef0b0aee1), + (0x381f9397cf40686a, 0xbb8f58105cfa40b0), + (0xb8049a8a70075841, 0xbb612ee751921afc), + (0xb7875e58d602839d, 0x3b00a4ae3e504c17), + (0x376491233ef907eb, 0x3acf0d6bf9e21094), + (0xb6870c562302f707, 0xba6d8997e250f98a), + (0x36a578a2cb0b00eb, 0xba37af38523f4d8b), + (0x3679f669a4d364ef, 0x39d69507180a7fc3), + ], + [ + (0xb6079fabfeb11cd6, 0x39708ac287c0d455), + (0xbc569479644686c3, 0xbfc2f206e49909c7), + (0x3c0fab1b83d45c37, 0x3f64dbf6a9fb80d7), + (0xbc32d9141794e6d9, 0x3f99336443318ed1), + (0xbbd0d543bfdf046d, 0xbf3bb6aa3d4e9e78), + (0x3bebe3f687043927, 0xbf540aaa5d94bd8d), + (0x3b419d1c00b33367, 0x3ef5f61b666129a6), + (0x3b7d88846cdeebc8, 0x3efe4158391f2c2b), + (0x3b46369cf5ae0043, 0xbea07a7a0745f74a), + (0xbaff9b3405275d12, 0xbe9a8ea97b670057), + (0xbac6b3f282a770b3, 0x3e3cb10b3affeaff), + (0x3a82ba290c76ba69, 0x3e2e6d78879f98a1), + (0xba64a2f934330d70, 0xbdd044447904054e), + (0xba47c3a2994a01a1, 0xbdb8850c99b76d50), + (0x39f0a14b971e592d, 0x3d59e4fa8ff52f90), + (0x39daa4eb91c06585, 0x3d3d4b2c1afd964f), + (0x3939ae655dba1592, 0xbcde807e2b00279f), + (0xb95a357647485d8d, 0xbcbaf942a59e1d56), + (0x38d3683474a866fa, 0x3c5ba64c4108b1cf), + (0x38d4c3ea257eaf58, 0x3c33ba614d4a472c), + (0xb87c3f27ee7c8094, 0xbbd3e1ce58589614), + (0xb8227a954e0b146b, 0xbba779ee6dc8cecf), + (0x37e88af1866245a5, 0x3b473c7bb3ac4992), + (0x37bd028f8f76417f, 0x3b172ca46f7c7bc4), + (0x370731151b8a5503, 0xbab681c8b15fa806), + (0xb7217a27a51bae97, 0xba83492f6b615d6b), + (0xb6cf3fd3e1e70ee8, 0x3a22406d4c30a6aa), + (0xb66fde7de35eca76, 0x39eb5d275267b9b5), + ], + [ + (0x3c6b7326e3fbaa70, 0xbfc2740819f1caaa), + (0xb60fcb36d157f3a9, 0xb974f95783b2a4e6), + (0xbc5b7326e3fbaa6e, 0x3fb2740819f1caaa), + (0xbbe4b7a0f7878877, 0xbf49b6f37d0a00f9), + (0xbc011249d3675d9f, 0xbf78868d7401bf2e), + (0x3bb6d7fdfc21db19, 0x3f1470a7cbcb436a), + (0xbbc5a6b64d367c53, 0x3f29fe94ce3d3e83), + (0xbb5352a68b135b7b, 0xbec71660e61f0f0c), + (0xbb68d34686b6e2aa, 0xbecd6dfcdb026028), + (0x3af006603a221bb1, 0x3e6ae79c35d01bca), + (0xbb0ef1a3e0a6b3b6, 0x3e64ac50be6ca02e), + (0x3a8def2f028aea7c, 0xbe03258409210f45), + (0x3a9043d06a02be21, 0xbdf3c09685c05e25), + (0x3a14118389ed7283, 0x3d925d85992670e2), + (0x3a183ee519f14ba8, 0x3d7b509288f452b8), + (0x39b2d75ecdbfec21, 0xbd19586d0c8690d8), + (0x395ab270216fde7c, 0xbcfc973a175ffbb5), + (0x3937848946c30fb7, 0x3c9a5d61717a7048), + (0xb90bfd5527d43039, 0x3c776fa9ee1a4030), + (0x38b4a933130a967e, 0xbc156907cfeb9559), + (0xb880e1c36e1b1a90, 0xbbeee74de5f3fe9d), + (0xb824cf2a1363166f, 0x3b8be6f4a0dc6589), + (0x37e62c8c1385fd2e, 0x3b60be8c55ae96fd), + (0x37612da67cbdd550, 0xbafdd3c1d9b37f13), + (0xb755b91662c8fbb1, 0xbace5ad7a8b76af2), + (0x37022a0cf4345b80, 0x3a6aa28d0971fd8b), + (0xb6d5974c96417b09, 0x3a37382bb4104861), + (0xb67d94e7b14fbe9b, 0xb9d478c454226508), + ], + [ + (0x35ad2d12470026b7, 0xb961b6856d13f265), + (0xbc6be2029a752b30, 0x3fc1ff5ebddd3c3a), + (0xbc04bba52e05ed21, 0xbf61e2035324643c), + (0xbc3a42d5bcad2050, 0xbf97f3506d4a1231), + (0xbbd8ddfdbbecb4f0, 0x3f37c65c9302c53b), + (0xbbff79e837d220e0, 0x3f53117816335151), + (0x3b97f81238bbf14f, 0xbef2df9afa521294), + (0xbb9270fec55a19f5, 0xbefcd5d4a9d78a14), + (0xbb3a3cd8b565f901, 0x3e9c672d4d6f7766), + (0xbb2736243a1ddf58, 0x3e995e4b102194f0), + (0xbad74d875eae428a, 0xbe38d22636140e12), + (0x3acf7d99ccb23385, 0xbe2d24fc9458bf7f), + (0xba609b81368ae5f9, 0x3dcc462d9da63971), + (0x3a5ec11516a5a336, 0x3db78eafb15964df), + (0xb9d97eb9ab4c3802, 0xbd569f5d498b660b), + (0x39c6683560d9facd, 0xbd3c3c4e5b0fab49), + (0x39720c56827dbad1, 0x3cdaccaf11834f8b), + (0x393a34dc5c675840, 0x3cba161c63abb183), + (0x38da1df31f53fe59, 0xbc5870224af67b03), + (0xb8dad0b4c075b658, 0xbc3324870c0ba14c), + (0xb8797656c00d0ccf, 0x3bd1adca419ec564), + (0x383d51df22546bde, 0x3ba6da83c474e675), + (0x37e46d6d0e6bdfc9, 0xbb44c90643c60c0a), + (0x37b79fc85a4600ba, 0xbb16a1256bbedf24), + (0xb71139afc5c7d131, 0x3ab44023f1dfc483), + (0x372a8761b55eada4, 0x3a82e31b2fbf1f0c), + (0xb69918ba0175b2cd, 0xba208375ee71a5da), + (0xb68573d1d2e5403d, 0xb9eadaddc4679dad), + ], + [ + (0xbc4081c2a50ad27b, 0x3fc192f2627a74e3), + (0xb602cbb028d0be5e, 0xb96f19a82d415934), + (0x3c3081c2a50ad27f, 0xbfb192f2627a74e3), + (0xbbed88bdcc1e72ee, 0x3f4635b38affe698), + (0x3bfbe434e30d7a5a, 0x3f775eceaabf7f86), + (0x3b9ca8671aa555b7, 0xbf11ac9e0164f7c1), + (0x3bc6ba93b83783b1, 0xbf28cc464a35b0af), + (0xbb6979a9d3cf3231, 0x3ec4014d9bf389c3), + (0xbb64740ce7aaeb6b, 0x3ecc1f05a2d85165), + (0x3b05322df741e1c6, 0xbe6761d18ebb04af), + (0xbb0eb4591bc8e09e, 0xbe63cb9af103e0f5), + (0x3aa091626e94e457, 0x3e00b3cb55bbe5d2), + (0xba9e3e57a5ff1ba9, 0x3df2f5c763b33667), + (0x3a315b0c770078e5, 0xbd9017771db5a5e9), + (0xba14aef80f7b4c8d, 0xbd7a4a5e79f39fb9), + (0x399f2119d96b7934, 0x3d165128cc4d99cc), + (0xb99044f60a617a04, 0x3cfb991575a9dafe), + (0xb926aff2cdbba534, 0xbc9756473a57c945), + (0xb8eddecc5081ac54, 0xbc76b070fece7fc3), + (0x38aa9bf0f1b7e51f, 0x3c130e1f9f15895b), + (0x387bf52f2b971db4, 0x3bee01b29beac9db), + (0xb82b5d175030a5d2, 0xbb88f8681f6cb14f), + (0xb802f353c2babb03, 0xbb604e16aece260c), + (0x3796062f77cde739, 0x3afad6e7811caa58), + (0xb769dd7aa9c09187, 0x3acda3c957b84f57), + (0xb69ebf7c2909d637, 0xba681861ce3144a5), + (0x36d6353c4ed8910a, 0xba36bb1e8cb840f7), + (0xb6713ccdbc67576a, 0x39d29b2e1989c79c), + ], + [ + (0xb60827407277ec38, 0x3962a629f22fc940), + (0xbc4e7aa4db2a788c, 0xbfc12dd55d4be2b3), + (0xbbf6da5fa7c96d5a, 0x3f5f1aee31818d19), + (0xbc319e43d5f0f1d3, 0x3f96de64242a8310), + (0xbbd5e566736996f3, 0xbf34afdf89fca61a), + (0x3bd951e5980d1ee4, 0xbf5238cfc13ac771), + (0x3b9632bd2bd2da27, 0x3ef0719d13e00e52), + (0x3b672b1f29067499, 0x3efb974781a526b4), + (0xbb1d4aa2a14eec77, 0xbe98cc82a70d752f), + (0xbb3bd18c494bed4b, 0xbe9850ae878c25bb), + (0x3ad9b4f299f8cbdf, 0x3e35bba73e282ede), + (0x3ac284476e69e80f, 0x3e2bfe1396e83644), + (0x3a452a15bea62efd, 0xbdc8d7dbe4a241ab), + (0xba562396ff096680, 0xbdb6adfbd773748d), + (0x39fff36c9935638b, 0x3d53f51dcb398ad2), + (0xb9d0c0a18775989a, 0x3d3b40d30be85f3d), + (0xb968a32d9f779535, 0xbcd7bf544872d9cc), + (0xb9300a2db3cd9c4c, 0xbcb93f163a09379e), + (0xb8f5e58d33a695d3, 0x3c55c1ca7d35fae3), + (0xb8cde16328522c93, 0x3c3293b43a786cbd), + (0x3868b9d269703d27, 0xbbcfa1df021b9c1e), + (0xb81fb6589e93977e, 0xbba63d0b33ef1315), + (0xb7ebbf0e52f441d1, 0x3b42afdbaac319ef), + (0x3763682a897a7957, 0x3b1614280111c2d3), + (0x374088e1875cc18a, 0xbab24b9d3911b7e1), + (0xb7203b62eacc40a5, 0xba82796c2afed41a), + (0xb6bf609b433463fb, 0x3a1dfaf4709fa729), + (0xb678488c980025d3, 0x39ea51c4a8e6f489), + ], + [ + (0x3c60c06e2860e868, 0xbfc0cf3ee98f769b), + (0xb5f9feaabed5f911, 0xb969e1daf76ea4e3), + (0xbc50c06e2860e867, 0x3fb0cf3ee98f769b), + (0xbbb4697a99d5d86c, 0xbf436f451f6e14fb), + (0x3c194225ed089993, 0xbf765d05948a946a), + (0x3b91ed6777d1a61a, 0x3f0ef55c5a0d16cd), + (0x3bcf058a2a3a8b03, 0x3f27bfec9d15d038), + (0x3b563856fcc3c4f3, 0xbec18c549f28e528), + (0x3b59158b454353b0, 0xbecaf7544eeac766), + (0x3af5145c85d21cb0, 0x3e648e81edf38b1d), + (0x3afbd8241e556e27, 0x3e630341e78d1014), + (0xba51c1fc73bfe02c, 0xbdfd73d2c942e970), + (0xba8a049a511a826c, 0xbdf23ec2729d3a6d), + (0x3a22971a921d0af9, 0x3d8c78e44cdec8b3), + (0x39d9c56e9b4dce66, 0x3d795a6f6107b4e6), + (0xb9bb8e56874267da, 0xbd13d1c77de8a03d), + (0x3998a5b51d6fc50e, 0xbcfaace944141c60), + (0xb93cff4a30c305b7, 0x3c94cfcb5e849650), + (0xb8e907aca70c354e, 0x3c75fbc3b0ec933d), + (0xb8a0d1de4a1de392, 0xbc11115c48c08b34), + (0x38719338bd822266, 0xbbed24eb2fafa2dc), + (0xb7d3634e9413e271, 0x3b8677909f205b32), + (0x37fb57fb5bb117fe, 0x3b5fbfecf15f1ecd), + (0xb7822bf0c08e088c, 0xbaf8423bd6a1b4d1), + (0xb76a00917d57eda7, 0xbacced1ef16333df), + (0x36eddbee5e40116d, 0x3a65e06ebbfe2e14), + (0xb6cf548c275b3e70, 0x3a363be97f954678), + (0x3646fc15979b90b0, 0xb9d0f619585e1af0), + ], + [ + (0xb5eea501cb87ef99, 0x3972465ed4007bdd), + (0xbc64353fd6c42f1e, 0x3fc0768257dad56a), + (0x3bf3a4186dcff329, 0xbf5b602a7beaaa48), + (0x3c16aaef36d826e2, 0xbf95ebc22efd092c), + (0xbb76c80c9b064de4, 0x3f3236a604142e61), + (0x3beddcf66c5978c8, 0x3f517a482faa8d85), + (0x3b66ad649af92b73, 0xbeecfc00890787ae), + (0x3b928f6dcddab559, 0xbefa7d7b128ac538), + (0x3b25a6c98550b698, 0x3e95e419f1b57043), + (0xbaf32b6c630a02f3, 0x3e97603cea235244), + (0xbad9cee3035468eb, 0xbe333a0b436c8824), + (0x3abe7890b1e58aeb, 0xbe2af46417845f40), + (0x3a4f73757ba505ba, 0x3dc609ac8cd8177a), + (0xba59cd5b34bda911, 0x3db5e11b87ad3903), + (0x39f753770c6a00bd, 0xbd51c2756590391a), + (0x39988f32e9922679, 0xbd3a586483dd891d), + (0x3977131f1f9126e6, 0x3cd534d22c600962), + (0x39500677438cdb27, 0x3cb8755ad322c506), + (0xb8f45577511a2e70, 0xbc53809e528c5e70), + (0x38d78081f89f0b4f, 0xbc3209a0a78d692e), + (0xb8532441923d88b3, 0x3bcc77842d1425ee), + (0x38002948000e0b89, 0x3ba5a4538094a38e), + (0x37d2ec02968bd2b8, 0xbb40e2a860417e77), + (0x37b26676c0acf6d9, 0xbb1588f3ef728c24), + (0xb75b53bc7d88d00a, 0x3ab099700fe34bf3), + (0x36e30a044384490d, 0x3a820f1c712673f5), + (0xb6ab8f46c26e1b98, 0xba1b4fa75c261c78), + (0x366effaba36280e2, 0xb9e9c5f163a1d50e), + ], + [ + (0x3c61166b7995967a, 0x3fc0230ba90f2871), + (0xb5c8e0d3f893a50f, 0xb944e3fd95304f5b), + (0xbc51166b7995967a, 0xbfb0230ba90f2871), + (0x3be85d0df08ff932, 0x3f413164a0864cde), + (0x3c175b99fcae0fa4, 0x3f7579c1bdbcfc99), + (0xbbaa847d3261afc4, 0xbf0b67e1913c668b), + (0xbbbdc3b0bfb76e55, 0xbf26d26de4fd8c5d), + (0x3b509cffcaa70410, 0x3ebf1b520b063853), + (0x3b56e93d7c50e034, 0x3ec9f01e7c1909a0), + (0x3aeb43dee887c41e, 0xbe624071b1796027), + (0x3a99b4c11c97bb23, 0xbe624f8e939ce43c), + (0xba9ac0bb48385d05, 0x3dfa35663595463f), + (0xba62567920c13146, 0x3df199120d49d507), + (0x3a1bdcb5b3b180ed, 0xbd896771e1b15e44), + (0x3a1adae6ea9dcc28, 0xbd787ede134ed7a0), + (0x39ac92871627b22c, 0x3d11bccdfbafa1fd), + (0xb98c58fbb742d0bf, 0x3cf9d22a6dc5a57b), + (0xb91dd27f9db4339f, 0xbc92b00e367301ce), + (0x391afb7d91b7ccfc, 0xbc755236722b2dc7), + (0x38ab20732a5e1932, 0x3c0ec2ce49a984e5), + (0xb878a4f67789acc8, 0x3bec52d2fb40494f), + (0xb82efb139c9eabfa, 0xbb84522e39f45c23), + (0xb7e18df511f3aea9, 0xbb5eeb3ed3be49c9), + (0x3790a89c14bccf9f, 0x3af606528674e24f), + (0x3762e9176a7f8941, 0x3acc3a09b96f5019), + (0xb6d1b63a61a018b7, 0xba63f00d5dec7881), + (0xb6d89c276f90a3f7, 0xba35bd3ff3734b8b), + (0xb63f6e7b2ed1bd35, 0x39cf0615ab9d7cb3), + ], + [ + (0xb5d35e9581fc00c3, 0xb940bf81e7b6bf7f), + (0x3c10417847765c1c, 0xbfbfa8b3f9ae4375), + (0xbbcf334b36194e10, 0x3f5856073b7fa2cd), + (0x3c3664c698368b18, 0x3f9514e652eb2e96), + (0xbbb93b53ec8276c9, 0xbf3032298718ea1a), + (0x3bfdfbf103edc8e4, 0xbf50d1153fde431b), + (0x3b7c365adad42aa7, 0x3ee9cb455c29d6a7), + (0xbb9fa9b04c310c1c, 0x3ef982167b1c52c3), + (0x3b3466b70782cb7f, 0xbe938191ef68eab3), + (0x3b31f4e70613c5d6, 0xbe968865345b3130), + (0x3adaf50c9e003b40, 0x3e312960010da387), + (0xbace36911be0e026, 0x3e2a0403679f6882), + (0x3a41779eb4010bf6, 0xbdc3b67cc0b96c06), + (0xba565f31bf6e70fc, 0xbdb526038b956efd), + (0xb9d5ed9568f49fa3, 0x3d4fda06e840fa34), + (0x39d1e175fdd2dad7, 0x3d3981de640d0e00), + (0xb97d648a5890112c, 0xbcd311fc56c4b888), + (0xb93dacd97e23c3ac, 0xbcb7b8f62899fc83), + (0x38f158e1e7d5426e, 0x3c51977cb2740dc9), + (0x38da9c4d3d78fa2e, 0x3c318706eb31dddd), + (0x38690756a8b2b9b3, 0xbbc9c2ecf3513bc2), + (0xb843d0ba97dc7b3a, 0xbba511e7341f19f5), + (0xb7c70af900714fae, 0x3b3eaa18f0a1bc9d), + (0xb7821dafb6b0a02f, 0x3b150190ffd95109), + (0x372d7c9b2e2dbe3b, 0xbaae3fb72389f327), + (0x372d26a5ec602bfe, 0xba81a629641ad013), + (0xb6b095243f6598d9, 0x3a18f85627d46b37), + (0xb679a0a342b383f9, 0x39e93a4bfaf23e38), + ], + [ + (0x3c50db2c50623ec0, 0xbfbf13fb0c0e6fcd), + (0x35fba9ea35ce88dd, 0x396fbca69a15def7), + (0xbc40db2c50623ec1, 0x3faf13fb0c0e6fcd), + (0xbbddaa71693254ea, 0xbf3eb3e6fcc47c00), + (0xbc1a7c91ef9a7d9f, 0xbf74af74cbd77bef), + (0xbb8ca4e36c0e1909, 0x3f087bb1ebeaec75), + (0x3bc0dc1e11076c53, 0x3f25fe629203150e), + (0xbb5990b5b3489011, 0xbebbd0f2a6555e6b), + (0x3b6af9c37c820e57, 0xbec9040de830649e), + (0x3ae759c4b2a6504b, 0x3e6057f7a76993d7), + (0xbaf1d65072f86b24, 0x3e61ad6dd5105c3e), + (0x3a9d40eb328040f7, 0xbdf782a6f5738cdb), + (0x3a8bf5e5277cbb15, 0xbdf1027dc06d4453), + (0xba28e3867173de2a, 0x3d86d65b13b16f65), + (0xb9fcb2787109df88, 0x3d77b59e9ed7367d), + (0x39ae1b468c4215d5, 0xbd0ff800f2a49a01), + (0xb999ff66e26a3daf, 0xbcf907be43054aeb), + (0xb926a66c1da18e82, 0x3c90e2e1d8f5ad75), + (0xb91450507fc3a22f, 0x3c74b3a8b0fb5013), + (0x38960772f0ae799d, 0xbc0be06d96b7165d), + (0xb880df93b3817817, 0xbbeb8c22733ba4a9), + (0xb800279bf5e0f4bd, 0x3b8278dcce924024), + (0x37f6405c8f354677, 0x3b5e1fb516b57c41), + (0x379e9caf5e3a0d68, 0xbaf4159150b0936f), + (0xb7554adeee798af2, 0xbacb8c841ae83900), + (0x36e38beff289f2bd, 0x3a623d5f11f3220d), + (0x36c4bb8b7542c332, 0x3a3540f31271ca17), + (0xb6641ee382a94dd9, 0xb9cc774f548476e1), + ], + [ + (0xb5a8c0565f36d2df, 0x39138a74ee514d1c), + (0x3c56a7c2ed8fa844, 0x3fbe8727c572a2c2), + (0x3bfdee3ce04b3d12, 0xbf55d1ef092ab395), + (0x3c206dda20eba87a, 0xbf9454e7a7395636), + (0x3bb99eb39ffae527, 0x3f2d0cc3a7fa6d3d), + (0xbbc9d1e5b54f9af7, 0x3f50398d2cbd02df), + (0x3b8aa1f4bf33f006, 0xbee725b0909f9c66), + (0xbb9b20d87a760073, 0xbef8a022f5fee447), + (0xbb1fcb0c42b327cc, 0x3e9185b1ea97a54b), + (0x3b3ea0aa1deb8165, 0x3e95c571167401ae), + (0x3acd2759d32f612d, 0xbe2edff6514e1da9), + (0x3ab2592f69cf47b5, 0xbe29298da3c4fa71), + (0xba621593a3e29e00, 0x3dc1c34705eadfb1), + (0xba424eda63e46424, 0x3db47ab8ec529c51), + (0xb9e71b8905efe1df, 0xbd4cc24a2f007c3e), + (0xb9c2a661b676a229, 0xbd38bbcc44e6c225), + (0x396f64643e54c71a, 0x3cd1420df9bb4358), + (0xb952c79ec699f349, 0x3cb7095f8b3266be), + (0x38e9b99fa1cd4cdb, 0xbc4feb87e4e6508e), + (0xb8d4b81d9d1d9436, 0xbc310c0caf4ba7ed), + (0xb8635b1ba8939988, 0x3bc76f4ca2183df3), + (0xb8470f94857758df, 0x3ba4868177e6a94b), + (0xb7d51e8dd2ddba52, 0xbb3bf93dac9dd574), + (0x37b66de2ce896857, 0xbb147f2c3ea4f41f), + (0x37422b1ac15ef2d9, 0x3aabacb94681ac1b), + (0x372b5172ed4e760e, 0x3a813fd96ffd162f), + (0xb6bfc10cab672280, 0xba16e97ff088b7e8), + (0x368ef32e3b7f65be, 0xb9e8b0d2637124f7), + ], + [ + (0xbc3b9f1d130797af, 0x3fbe018dac1c17e3), + (0xb5e141aefdec9b98, 0xb96cc7fef8ec3e0d), + (0x3c2b9f1d130797b4, 0xbfae018dac1c17e3), + (0xbbc5edf62333ab91, 0x3f3ba21bd15d02a4), + (0x3c138b4f0d3a410f, 0x3f73f9e0db07e7ef), + (0xbba6f23ddcae3185, 0xbf060b77c5e27622), + (0x3ba86d4e04faa24d, 0xbf253f9b1a5d228c), + (0xbb5fddc005e37ab4, 0x3eb910b38812c253), + (0xbb40935ad5366a7f, 0x3ec82ee6dfdfedeb), + (0x3afa8bf30766210f, 0xbe5d7cc2a9a602ee), + (0x3b0b507850a97457, 0xbe611a57d8645358), + (0x3a8673cba0bc56e8, 0x3df53d401519442d), + (0xba8c0365adf75127, 0x3df07915ef87408d), + (0x3a20221e3beb4ce4, 0xbd84aabcb6141c76), + (0xba1d282fee2792c3, 0xbd76fcb8e2eada15), + (0xb9a71c1e6871ca1b, 0x3d0cfcfdb2faeb02), + (0xb99d6b8f41ec2a2a, 0x3cf84c5369d2e33d), + (0x39204114eb9c2f69, 0xbc8eb11d7e6581d1), + (0xb9191341e21aab61, 0xbc741f9ab4632bff), + (0x38a996918c6850e8, 0x3c0965159407e959), + (0xb88a5f0c11aeb57c, 0x3bead0e3ccfe39e7), + (0x382f54e660147ef3, 0xbb80dee0e993354d), + (0xb7f1c5f5adc77455, 0xbb5d5e03476b81b0), + (0x37898d6415c2c8f8, 0x3af264535f4853fa), + (0x376323c802fd85b0, 0x3acae5afea45a1d0), + (0xb7064e5aaa6a944b, 0xba60bfa00dd729a9), + (0x36cb04c64064bf04, 0xba34c82d1f8992b1), + (0xb64e911d15e3dd3d, 0x39ca34d3a49f024e), + ], + [ + (0x359edfac18b305f3, 0x39163cc00f5dbc0b), + (0x3c555d27e18add4d, 0xbfbd82939ab62339), + (0xbbe5f2055a671371, 0x3f53b5a54845670f), + (0xbc331ee0af44ab91, 0x3f93a7ff1622def8), + (0xbbb2001fd86915ca, 0xbf2a3ebc476a606d), + (0xbbb7a5c728534a7e, 0xbf4f61adde3a8c61), + (0xbb6721b027970cdc, 0x3ee4ec45da0478b0), + (0x3b60295953d04e61, 0x3ef7d3b28159f23c), + (0x3b21dd48381068cc, 0xbe8fb3f21bcd7fc4), + (0x3b3047a478ead9ea, 0xbe95145a876d2273), + (0xbac575cc2dd16f8c, 0x3e2bf64cdf7c0558), + (0x3a9c7ea36a18f920, 0x3e2862204ac427d2), + (0x3a25529af35b5dcf, 0xbdc01c0d48888811), + (0x3a3766e366a3fc7a, 0xbdb3dd6cb1cbcd8f), + (0x39e0fa707938a9eb, 0x3d4a2020c8b3c20d), + (0x39bbbc58f9d26ec6, 0x3d3804a9d711292e), + (0xb96e85f6cc946fb5, 0xbccf6a1ef9182e2a), + (0x39591e00ef906d2f, 0xbcb665c82dfd3112), + (0xb8eea5743e788fee, 0x3c4d1cbc474ae19a), + (0x38c6e72f6eaa6ee4, 0x3c309883728ed044), + (0xb85fe1b5b6914470, 0xbbc56bda19bbd907), + (0xb83f2fa5959c5300, 0xbba4025c7e86cfc8), + (0xb7d115ca11e0e05e, 0x3b39a17a25046119), + (0xb7a514b6675a5e5f, 0x3b14026121051408), + (0xb73ae1c02372f342, 0xbaa96b5d080744b6), + (0xb6f3427ab8e0fc99, 0xba80dcf24b28c249), + (0x36b101dd967ab100, 0x3a1519032b200dc8), + (0x3675b89a8e98627b, 0x39e82ad2bc03a6a9), + ], + [ + (0xbc56edd809f4ec43, 0xbfbd09b21e36c0bd), + (0x35e5d21c4590e23a, 0xb963ad3554cdbdc3), + (0x3c46edd809f4ec44, 0x3fad09b21e36c0bd), + (0x3bd1da06fbc18d60, 0xbf390b0e6a475e45), + (0xbc140975d5184af7, 0xbf7355b904fbf7ee), + (0x3b9e3b983f1177c4, 0x3f03fc459d1e25a4), + (0xbbb494c77a177888, 0x3f2492cc61d19dfe), + (0x3b46367d4d2995c5, 0xbeb6bcf110a02ad1), + (0x3b6b6ea46d6df357, 0xbec76d44f6a83523), + (0x3a803005742b014c, 0x3e5ac61efcb3c36c), + (0x3afeb84629addc98, 0x3e609436fcaa3965), + (0xba99e294d7264bfe, 0xbdf34eb6095f969b), + (0xba88db7c11c38cf9, 0xbdeff662945eb368), + (0xba237b9cbf75a8c0, 0x3d82d05bf8ff5181), + (0xb9d4ca3e6003606c, 0x3d76525fbb563fe0), + (0xb9a93e3cfc188270, 0xbd0a6eb937c7f6c0), + (0xb98026c04e791e1c, 0xbcf79e90468589aa), + (0x39252d8dea0a8e75, 0x3c8c0998b46c2a84), + (0xb9065519f44afceb, 0x3c73955fe5fb10db), + (0x38ac6a20d09a8309, 0xbc073ec89759ba44), + (0x3868ea900cd0acee, 0xbbea20bd7b455493), + (0xb7fd0a1ee99e85f5, 0x3b7ef3962cbda037), + (0x37ea27d0e101e8a6, 0x3b5ca6506245824f), + (0xb773dd8f476a0af7, 0xbaf0e8cae31c27f5), + (0xb75f5c680a514474, 0xbaca461c76aba331), + (0x36c4607ce2cc9a56, 0x3a5ede6da0b05cf5), + (0x36b52adf7a554ae1, 0x3a3453a0c69c3020), + (0xb66d21d6c5df4ac2, 0xb9c8341f8ff89500), + ], + [ + (0xb604e106c1a5d68b, 0x3960e1cf91ecbcd0), + (0x3c4e1f19f10295a0, 0x3fbc96700031f601), + (0x3bd8339df4a4988a, 0xbf51eb2a07d0f09e), + (0xbc39bfe53ec12c89, 0xbf930b36eddaa234), + (0xbbb206af4ba8cd76, 0x3f27dd2dde84b73c), + (0xbbd1f3a6f0dd2e5a, 0x3f4e696553e0b8a5), + (0x3b70bebcc672dde7, 0xbee3085aa35a1647), + (0x3b964955e62a56d1, 0xbef7199f24bccae1), + (0x3b29acbd06286b9c, 0x3e8cdbab6a766176), + (0x3b336b635edd5e8a, 0x3e9472a7cffbf91e), + (0xbaa919ffae68f01f, 0xbe2979f5211c4dae), + (0xbacb3a83d6a4505a, 0xbe27ab4b01a902db), + (0xba3d20efa9eb9b62, 0x3dbd63904e4c487c), + (0x3a3a2266d5d6a8ef, 0x3db34c83fb1c2279), + (0x39d10d542056a77f, 0xbd47dcfdf13e5ccc), + (0x39b3859d37da710a, 0xbd375b01ddacf988), + (0xb9565b371d7ee634, 0x3cccbd41ea6afd27), + (0xb9581212fb798324, 0x3cb5cd46eaba1e98), + (0x38e7f3fcdfe0798f, 0xbc4aaded22d1c26d), + (0x38c46a63e955520e, 0xbc302c0feb2cc9ce), + (0x385cf68aedadaeff, 0x3bc3ab0efb07293e), + (0x384f8dd325a6cd09, 0x3ba38564ae72454e), + (0xb7d09df47a273d60, 0xbb379494d9aa279b), + (0x3794fe8c13f0d784, 0xbb138b6c661b3cba), + (0xb7395294aeae0a19, 0x3aa76f5fd4aa472c), + (0x3729b16a6763e36e, 0x3a807de116ccc64f), + (0xb6b1c69123ace593, 0xba137e1e22a65820), + (0x368881179d4440a6, 0xb9e7a919992ba54e), + ], + [ + (0xbc5ca34ef67ceca5, 0x3fbc2861347b1b39), + (0xb5d9566d846e8e8c, 0x396cceb50dfed9ea), + (0x3c4ca34ef67ceca4, 0xbfac2861347b1b39), + (0x3bbf201ae22fff02, 0x3f36d57bffb37fd5), + (0xbc16b4ecac2fa1c1, 0x3f72c060ef553f18), + (0xbb9df91b90d34532, 0xbf023a407b722d2e), + (0xbbca3432d200d5d1, 0xbf23f55581ec683d), + (0xbb5e04bafba5db02, 0x3eb4bfb4daa2ff62), + (0xbb42a29e46400df9, 0x3ec6bc69099af2f7), + (0xbafb52717e31e7c3, 0xbe5873340987d276), + (0xbadb973833d824fb, 0xbe601951f02d2b37), + (0x3a8c2da9623b39af, 0x3df1a6174fe55fbe), + (0xba72657ffe3c0d22, 0x3def0eca5bc0284a), + (0xba1b8e7e494f244b, 0xbd8137cb1fcc55a3), + (0x39c37c1a924f4abf, 0xbd75b4f7f2bb19ed), + (0x3999da79a9d54cda, 0x3d083934ed797abc), + (0xb989eab29e540769, 0x3cf6fd29fcbcf38a), + (0x3920c6c752968451, 0xbc89bbe4a386b212), + (0xb91a160d6358c9f0, 0xbc73143b8f6fa78f), + (0xb8a480a782f588c3, 0x3c055f1ef8c6530d), + (0xb887a3802525f474, 0x3be97b209a79f9f3), + (0x37f474a28bfc52ff, 0xbb7c822a3d9869c8), + (0x37f5fabb96a9e9b8, 0xbb5bf86d95cc8f12), + (0xb78a0516ef829f54, 0x3aef35917d0b3f76), + (0x37622045f0e24361, 0x3ac9adf870fd0a7b), + (0xb6e0bdb6d552746a, 0xba5c8b4b32991b65), + (0xb6ca53a583f641f6, 0xba33e3ad6afab22c), + (0x3644ed17a9579532, 0x39c66c8a74f2a901), + ], + [ + (0x35d31fe5aa13389e, 0x39517eb126abaf87), + (0xbc2986f8b543f27a, 0xbfbbbf246019c0d4), + (0xbbf8243dc68fb135, 0x3f506224199140d8), + (0xbc31c8ab4f070de8, 0x3f927c3416c09898), + (0x3bc1400990dffef0, 0xbf25d279dc87cf69), + (0xbba49f5dbb72a065, 0xbf4d86a5f5adbdac), + (0x3b8c1a134d478c22, 0x3ee169041634c248), + (0x3b908bd4df68b45a, 0x3ef66f5bd1bedae1), + (0x3b2340bc492fa102, 0xbe8a69b2c717d54a), + (0x3b2b327658083b81, 0xbe93de4eab456cbd), + (0xba8a5251b6ada8e0, 0x3e2755eabbde6915), + (0xbaceee9ff7faabed, 0x3e2702fe7ba9f8c3), + (0xba380d3becf77482, 0xbdbaf2007eeae256), + (0x3a5fcfcac159b57e, 0xbdb2c69746948e55), + (0x39e98e02f368d7f4, 0x3d45e77ad9a9daf0), + (0xb9d9fd1217de9157, 0x3d36bd7bc6045cd0), + (0xb96832ead3387986, 0xbcca6a2a200a32c0), + (0xb955d0d8052f28a5, 0xbcb53ef0001a8fc4), + (0xb8bb1f311ea4c9b4, 0x3c488eb37fc1cfd3), + (0x38cf9a896df080b1, 0x3c2f8c832f51b4aa), + (0x37d4b18c2095b824, 0xbbc22200a0360453), + (0xb829797fcaa4e047, 0xbba30f596dbfddae), + (0x37a2d23a75e1c560, 0x3b35c6dd016030cd), + (0xb734e085d594092d, 0x3b131a4ea769c7d3), + (0x373bce3510c7cb6b, 0xbaa5ae7bd23b9081), + (0x371fb7fbd6256541, 0xba8022d72980d3c8), + (0xb6916a353736b148, 0x3a1211535635a157), + (0xb68195f4662a5736, 0x39e72c1b69eda79f), + ], + [ + (0x3c497d2b9281abc8, 0xbfbb5a622198a72c), + (0xb5e793f1c68299a8, 0xb94513e9f11c844a), + (0xbc397d2b9281abc8, 0x3fab5a622198a72c), + (0x3bd29fd72f6919a6, 0xbf34ee71cf67c243), + (0x3bef69e3e89e3763, 0xbf7237c02b462f6f), + (0xbbaa32f85df10cac, 0x3f00b67b6fdfec62), + (0xbbcb53a20d4b2f6c, 0x3f2365167d8bc330), + (0xbb5df27a7ce0ec5b, 0xbeb3086b7a296e69), + (0xbb64ce30c488b9c8, 0xbec61a141425c2a6), + (0xbaf5a586400cf358, 0x3e56712b23991e80), + (0x3afc0839ad44e9db, 0x3e5f50736839e481), + (0x3a894d2884c96f7c, 0xbdf0366d02b91b84), + (0xba3b7d3083bff34e, 0xbdee38f9bda5f6df), + (0x3a0f47f210ca9110, 0x3d7faa3d1cb01e65), + (0xba1e53d61aed5735, 0x3d752317a2a5b9a2), + (0x39a61437236ae98e, 0xbd064cd06847bd1d), + (0xb98a88cfd6fbb36d, 0xbcf666eebfeb573c), + (0xb921559c51711009, 0x3c87b8b54f1785d0), + (0xb906f3154f9ab684, 0x3c729b70ca32ed3d), + (0xb8ae6effa325d36e, 0xbc03ba848f793a6f), + (0xb8862efc7da56047, 0xbbe8df655223f804), + (0xb7f4102cd3bf6abf, 0x3b7a5b9007f4f46f), + (0x37fe605a6b4873f8, 0x3b5b53fa1a9d0aeb), + (0xb7858edfd4fa5bb7, 0xbaece6fce7a8c528), + (0xb763c9762154c0c5, 0xbac91d34853abb67), + (0xb6f1321ee8b9d4f4, 0x3a5a7ad6f4ddf512), + (0x36c7e2ebffed7e36, 0x3a3378793c3201e1), + (0x363afde2a34531f7, 0xb9c4d6575c0bc39d), + ], + [ + (0xb60d030c92133af6, 0x396cca2f2b0d4235), + (0x3c56e5b3d654a3dd, 0x3fbaf9cb42cd08a7), + (0x3bd4df22cc11675d, 0xbf4e1c66d7616e37), + (0x3c32068ccdde2ecd, 0xbf91f90fd1013589), + (0xbbb9426a5fb5b160, 0x3f240e3eb09b7d6d), + (0x3bcf4131edb03e41, 0x3f4cb682ff471274), + (0x3b8c9cd4cf70b12b, 0xbee0016819a61dd8), + (0x3b8325d69b159807, 0xbef5d2d1c420646d), + (0xbb157a8a155cbaaa, 0x3e884b0fe8a85355), + (0x3b1d5bbe26d980b7, 0x3e93559d96bef598), + (0x3ac3da55cd6ad83e, 0xbe257a0be74997ad), + (0xbaac817776a96dfe, 0xbe26677c8f53b6a6), + (0xba48a3c160c8aa22, 0x3db8d1ae21b756a1), + (0xba55e41c05b333bc, 0x3db24a6e1ac65e87), + (0x39d8b28dfb36d53c, 0xbd4432017034b94c), + (0xb9b0c0b8d7240fb1, 0xbd362ae0447c7c88), + (0xb96e042713d54739, 0x3cc86190e6a87083), + (0xb940efa65c450767, 0x3cb4b9e1622f9586), + (0x38cb94e9a0146b9b, 0xbc46b1f3e51e7332), + (0x38c980a0b48ea2c9, 0xbc2ecd41315429fa), + (0x386a6123111c55fe, 0x3bc0c7d6edd07b17), + (0x3843ce4f1feb2ebc, 0x3ba29fe1dfade081), + (0xb7b6d84618b5e516, 0xbb342eb57150f9e4), + (0xb7a6474c8a6dcfb7, 0xbb12aee3771f508d), + (0xb7333647a6c944af, 0x3aa4201b40c833df), + (0xb71eb58df16b4736, 0x3a7f97bc8a144320), + (0xb6aee477a8ff3709, 0xba10cc450b34befb), + (0x368b6b8edb270aaf, 0xb9e6b4102ba6d220), + ], + [ + (0x3c49a6abbfd839f8, 0x3fba9d183bc04545), + (0xb5f15a143d9b75a9, 0x395a77273a2f7cb1), + (0xbc39a6abbfd839f9, 0xbfaa9d183bc04545), + (0x3b97025ee34cb468, 0x3f334779874010dc), + (0xbc01fefbfc4e4e9b, 0x3f71ba2299ab88a8), + (0xbb55c0e2a1925dd2, 0xbefecb19f5bdc649), + (0xbbcce75d4325824c, 0xbf22e052707cc859), + (0xbb5a63ba682d624b, 0x3eb18a5da77edd83), + (0xbb6dd00d5413ce37, 0x3ec5846b622f592b), + (0xbae5e872e9afa841, 0xbe54b17e97b5884a), + (0x3ac6a221aaf909f2, 0xbe5e7f76674dfaab), + (0xba84b34281199881, 0x3dedeb504ed353c6), + (0x3a86775826683d8c, 0x3ded72e25f190409), + (0xba00d222c75ec8a5, 0xbd7d3e076b0201d6), + (0x39c62484e2aaf790, 0xbd749b825302af88), + (0x39ad85f9e975e5bb, 0x3d049d35475fc5c4), + (0xb99ca04c877af6e6, 0x3cf5dac9623f7b3a), + (0x39280969190bc2ec, 0xbc85f3d5130dc427), + (0x390c3038a68f53f8, 0xbc722a4aeb6975db), + (0x38930f7db32e8831, 0x3c02479e3ad0904f), + (0x386d535dbc6c1f3b, 0x3be84cdbd491db42), + (0x381f7a28d6ae78be, 0xbb78745ed68ebb0a), + (0xb7eb97e422517d33, 0xbb5ab87a4b0f3210), + (0x378e41504a923c16, 0x3aeada8753b4f2fa), + (0x375ded58316b4b3b, 0x3ac8939aed0eb956), + (0x36d24ca9391ef811, 0xba58a3c50700bb64), + (0xb6c8cff6f49b7cc7, 0xba331204a4a28f43), + (0x366456ce1c2efeb7, 0x39c36abd94cda9ea), + ], + [ + (0xb5d6aeec01447ebf, 0xb94fef3146f8bc8c), + (0x3c5729f43724612e, 0xbfba4407dac72297), + (0x3be5723d945cf783, 0x3f4bcba4dec1da44), + (0xbc3fe775590d7dad, 0x3f91803c65cafdfb), + (0x3bc90cfa57dbb4d4, 0xbf2283df2b3e4a6e), + (0x3bc3e3e0391f1e1c, 0xbf4bf695e89259cd), + (0x3b630f86ed6a9315, 0x3edd8f3759122d51), + (0x3b9030fb5fd0d14f, 0x3ef54246c8e04218), + (0xbb1b2983b9c2c402, 0xbe867111bc8e67a4), + (0xbb3a3cef2b75d6f2, 0xbe92d72a1f62ec18), + (0x3acbd165702624f6, 0x3e23d9ca3eb1e22f), + (0xbacc01aeccf1babb, 0x3e25d74a6e225515), + (0xba59e0b645683780, 0xbdb6f4b420b2f957), + (0xba5cdfc243103d08, 0xbdb1d6f985dc3ec9), + (0x39e7bf317b14f352, 0x3d42b1d81101dea8), + (0xb9d83163c0057ca7, 0x3d35a2197089fbfb), + (0x395c76bb39cce133, 0xbcc6974aff17c78e), + (0x39598eb0a01efbec, 0xbcb43d4892ea1bcf), + (0xb8ed15e01c0238c4, 0x3c450d21b45ff80d), + (0xb84241f1dc4f6f34, 0x3c2e196b40872b31), + (0x385c04a02280abca, 0xbbbf2abd4db5d9be), + (0xb84959c23561aa48, 0xbba23699d666bfec), + (0xb7d227fbae70ed91, 0x3b32c4313f19d90c), + (0x37b6f63990f0594b, 0x3b1248f0a9284b37), + (0x372ffeb55db91815, 0xbaa2bd11bf68d5b1), + (0x371b75883a5be1b6, 0xba7ef1cd2cb739b8), + (0xb6aa77e2877a5055, 0x3a0f531ca9868a0f), + (0x368cea389ee72d20, 0x39e64106dd656961), + ], + [ + (0x3c4f5da9526c15aa, 0xbfb9ee5eee1a97c6), + (0xb5f1d3382c1276a4, 0xb96402f67a0b5834), + (0xbc3f5da9526c15a9, 0x3fa9ee5eee1a97c6), + (0xbbc331009164145e, 0xbf31d55d93e59bd7), + (0xbbb6887e944cd005, 0xbf7146219394a99c), + (0x3b8ca8e50931e16c, 0x3efc7d32bb646e2a), + (0x3b459561844c17b3, 0x3f226599aed4f1ca), + (0x3b2f06633c8a4cba, 0xbeb03ba58ec85c12), + (0xbb602686ed9edd3e, 0xbec4f9e3961bb9dd), + (0x3aeea9ee2c6a2043, 0x3e5328d4dc334079), + (0xbaef3a53acd5c6d4, 0x3e5dbda7ac70ff93), + (0x3a77a849dd25fe0f, 0xbdebb7c2f187144e), + (0xba64d006a8eb9c0b, 0xbdecbac24c760567), + (0x3a16ef76e61a4831, 0x3d7b1c35b65eca4e), + (0xba1dac5564e87883, 0x3d741d23f93de7a0), + (0x39a9abd11b46d7e7, 0xbd03208d806698c2), + (0x399718ab551976b2, 0xbcf557c166250d9c), + (0xb92d6295443bb3ec, 0x3c84637130a9d7f8), + (0x3916194c75a97d3e, 0x3c71c021934a59f1), + (0xb89fd63bcb1b75d7, 0xbc00fed119c972a1), + (0xb88c541b145b8b02, 0xbbe7c2d6451d6c10), + (0x381dbc09437e925e, 0x3b76c3357c9d7057), + (0x37fb570ed16daac3, 0x3b5a25664a0ac691), + (0xb74761fb4819cca1, 0xbae906c5b9661a95), + (0xb76d18cd574324fb, 0xbac810df45f48012), + (0x36ef5b739f6495ca, 0x3a56fe3f66728fcb), + (0xb6d5974f41aa1f59, 0x3a32b0377532218e), + (0xb660f1fa91a8fb3e, 0xb9c22493f39e943f), + ], + [ + (0xb5e9353c25c13119, 0xb94016db9db1eb7c), + (0x3c422d28ddb0663f, 0x3fb99be73fa3efcc), + (0x3bc06623176e8b2d, 0xbf49c3248da75775), + (0x3c24e67d5d6f01f7, 0xbf91107147eda800), + (0xbbb9f85d6cd5a259, 0x3f212980be9d8520), + (0xbbc6d7f4255305b5, 0x3f4b44e1221e6051), + (0xbb75ffceb4091f98, 0xbedb67b78c1dd9c5), + (0xbb952647474dbc63, 0xbef4bc49e9b5bcfd), + (0xbb07d96f251b94dc, 0x3e84d02ffb8bcfd0), + (0x3b3e32d27646b4d2, 0x3e9261c31456e43c), + (0xbac761199eda3ccb, 0xbe226b400744def1), + (0x3acd5778eedbc215, 0xbe2551251a2b4223), + (0x3a46fe837cedeee3, 0x3db5500f9531112d), + (0x3a083f723e083d02, 0x3db16b4e936f8a96), + (0x39d95bf8d7caafb4, 0xbd415e70b28182e4), + (0xb9d30dafff387703, 0xbd352230c03cb29f), + (0x3945e77279062e4c, 0x3cc5019095879293), + (0x395492014f9c999d, 0x3cb3c864dd8bd877), + (0xb8c1fd1436671589, 0xbc4397af75e3218c), + (0x38b351e168817cda, 0xbc2d701c9937c95b), + (0xb855e93cc818d8e2, 0x3bbd0965d926054d), + (0xb84897cb99dccaef, 0x3ba1d319c4fa1430), + (0xb7dc0895bb1677aa, 0xbb3180c1e083f84d), + (0x37be77bf0edd596f, 0xbb11e83053760c66), + (0x374b4d74f0bce05a, 0x3aa17f5e91af9659), + (0x371838fbe922ebee, 0x3a7e53a0935a1f43), + (0x3684c2589850e2ae, 0xba0d4939983de020), + (0x3684fdd4fb568c5f, 0xb9e5d2ed99505e47), + ], + [ + (0xbc55bbc298d062cd, 0x3fb94c6f5898708b), + (0xb5f666b728efc40e, 0x396f720ac4a0590b), + (0x3c45bbc298d062cc, 0xbfa94c6f5898708b), + (0xbbc91fb79f2262de, 0x3f308f4f1b8fb0dc), + (0x3c11274d5c28ac62, 0x3f70da931c776c71), + (0x3b468ef3cfeee3c5, 0xbefa7550d2940f2a), + (0x3bbf74462dfd6413, 0xbf21f3b978a47cf4), + (0xbb46a542136ebda6, 0x3eae28ea02472df4), + (0xbb6c80d173cac31c, 0x3ec47930aec78cb8), + (0x3adf057ade22322a, 0xbe51ce32c4f34e51), + (0x3afb45adc8973d4f, 0xbe5d0950e99c8b39), + (0xba7a6617d572dc1b, 0x3de9c5a1603e79e8), + (0xba8e2eff860f1411, 0x3dec0f1778cf9887), + (0xba168f093dfd4cd6, 0xbd7938fe13097690), + (0xba1ecefa9c9a3a82, 0xbd73a70bdaedabef), + (0x39aed81642403d1e, 0x3d01ceeed28a9bbc), + (0x3997da4ad363efc9, 0x3cf4dcf95c5ca949), + (0xb91477913a3a55c0, 0xbc82ff92717657c8), + (0x3910bab9b4893246, 0xbc715c5a3e02442f), + (0x389d817a2ccfa8fd, 0x3bffb3c968d17246), + (0xb87cd010a2041864, 0x3be740ae3a8d3fe3), + (0xb7e3b9850dbb1fd0, 0xbb754054fa60c54d), + (0x37fb925f8ad7d3fb, 0xbb599a3322fec174), + (0x3784fd568b6ae4b0, 0x3ae763dc0015bdca), + (0xb76b4c77e261251c, 0x3ac794a91384b8c1), + (0x36e8d58063ff5bb1, 0xba5583a75fd37094), + (0xb69a2c623fdcd0ef, 0xba3252e98814e1a2), + (0x3663e86d6d6cf480, 0x39c0feb0ea2eacb6), + ], + [ + (0xb5e1d5aab91b0735, 0xb94d62f7652911ef), + (0xbbb1d709b3e6a9e9, 0xbfb8ffc9b9a131f6), + (0x3bdb4dd57b364903, 0x3f47f724314bb99d), + (0xbc3086cbc396cba9, 0x3f90a89c5d1074ba), + (0x3bb8da379d94d4d2, 0xbf1feeaeb33465e8), + (0xbbef433944c1a759, 0xbf4a9fba36a7a08e), + (0xbb7f256bdb98dce6, 0x3ed980034770f3b2), + (0x3b91b4c8faeaae0e, 0x3ef43fa4bb8cba57), + (0xbad948481030ddf3, 0xbe835f40f3a3902b), + (0x3b3e2e9d940a676f, 0xbe91f465ba292c0d), + (0xba98e1102f6772d7, 0x3e212688f74f8106), + (0x3ac17030071395d4, 0x3e24d3f7e3fdde95), + (0xba567e74d2a2034d, 0xbdb3daee9c38c74a), + (0x3a51aeaf0688f02c, 0xbdb106a132ee69a7), + (0x39ebe0f4bca30d89, 0x3d4030e7765d6c75), + (0x39c14fc8399d63ea, 0x3d34aa4c24070ac4), + (0x3933883151a4972a, 0xbcc3987402712b5f), + (0xb942dee4f35f615b, 0xbcb35a87994f9f22), + (0x38d71bf8bdfcbf64, 0x3c424aa138f72437), + (0xb8ba56b686d5a4be, 0x3c2cd07eb7a4b5c9), + (0xb8558c1bfdd348e3, 0xbbbb21f2d5bbbf78), + (0xb83550a5585a2688, 0xbba174fb8120d7fa), + (0x37b47b0dfc8fc083, 0x3b305ef4c6de1408), + (0xb7bb881b76be83a0, 0x3b118c57455ac2ea), + (0xb743465c91dd6734, 0xbaa061f86f5a1fc0), + (0x3708e74190a8b10c, 0xba7dbce43544e4d4), + (0xb68a21eaceaae3f4, 0x3a0b7321833d28bb), + (0x36809484f141d2c7, 0x39e569a3e2d05d37), + ], + [ + (0x3c5827414357db53, 0xbfb8b5ccb03d459b), + (0x35f22b8b60cf7290, 0xb96f103383ea761f), + (0xbc4827414357db52, 0x3fa8b5ccb03d459b), + (0x3bc829bf4eaf9cff, 0xbf2edc98b92fedf3), + (0x3c0a89c9aabf283f, 0xbf70767d524cea88), + (0xbb9b6aea43cf84ab, 0x3ef8a85a847c89c3), + (0x3b9126e1254c1bf9, 0x3f2189afaa2bffcc), + (0xbb239c5c72e2b4cb, 0xbeac1d231a69bb02), + (0x3b6e89e6ffd35f3d, 0xbec40139bdbc9d36), + (0xbac6599803b1efd4, 0x3e509a6859c8e374), + (0x3aded4460b047b6f, 0x3e5c60fc5f9b505f), + (0xba80f4ba4649d3f0, 0xbde80ad391f7224c), + (0xba8175d1cbd50fa3, 0xbdeb6e954dd6c922), + (0xba13a4fa3d4d4a86, 0x3d778adc76ca1d1b), + (0x39e0b384d483dfc2, 0x3d733867c824f37c), + (0xb993f2721a70fbeb, 0xbd00a1ec5f4dca90), + (0xb99e890379206b1f, 0xbcf469ac872b68fc), + (0xb9207c6b7625a1c3, 0x3c81c1b6937f11f5), + (0xb901775a0f7e0f63, 0x3c70fe687033cdc5), + (0xb89ff8b30b7fba36, 0xbbfda774598edc97), + (0x3875c8039f93b5dd, 0xbbe6c5c790b36d34), + (0x380ece04cbe1e4a9, 0x3b73e54f8cfb2b46), + (0xb7d83bd27bce64ed, 0x3b59165852609f70), + (0x377e5472e34f528f, 0xbae5eb353d0d715e), + (0x376ef3c901224023, 0xbac71e9aa439eb8d), + (0x36e5bd48680a81b7, 0x3a542e64e00789ab), + (0xb6d03ab3c0296c8d, 0x3a31f9ea0deead8a), + (0x364a1b07722309cf, 0xb9bfea22321266c2), + ], + [ + (0x35ef906f4164dc60, 0xb96927bfa8db52b2), + (0x3c116404635b617f, 0x3fb86e51bb2ee24d), + (0x3be40f7dbe05ef72, 0xbf465e3bad214eb8), + (0xbc3502bddec37519, 0xbf9047d6ed159c31), + (0xbbb68a41509da16e, 0x3f1dce4a381ce24e), + (0x3be0a2f7a61834bd, 0x3f4a05b93842da9a), + (0x3b384a0ade4543c9, 0xbed7ce3df60b0ea1), + (0x3b8858267c36b09d, 0xbef3cb50138cce4b), + (0x3b2cb60fbd506539, 0x3e8216e84a5dec74), + (0x3b2d7337b289b637, 0x3e918e354c01533b), + (0xbac53c3102b1edb8, 0xbe2005493039e5f0), + (0x3ac1ef2cc0ca439b, 0xbe245ed4a3733e9d), + (0xba3577e316826199, 0x3db28e2ed388f175), + (0xba51361966067e0a, 0x3db0a83fb8aae5cc), + (0x39d23d4aec4b7be8, 0xbd3e4745b1e410b2), + (0xb9cc2b2efa2e5867, 0xbd3439aae872dae3), + (0xb9550093ed38173e, 0x3cc2557a9d9a519f), + (0xb95c225721c7ed22, 0x3cb2f313647cb524), + (0xb8d9dd312bb7ea5b, 0xbc4120389f39a6c8), + (0xb8cbc43aa5cd2092, 0xbc2c39cb315eea3a), + (0xb84185a7cc406293, 0x3bb96c5a7748a20c), + (0x38496ead43ea8719, 0x3ba11bdcff0ab3e8), + (0xb7984affa3f0408a, 0xbb2eb47bf3d0d392), + (0x37b23b859b45c934, 0xbb11351924a215f1), + (0xb721ee8c0d2d3f36, 0x3a9ec1444b23676a), + (0x371b235f8e2c7f49, 0x3a7d2d3b6879bb57), + (0x36aa24c57ef1bc5e, 0xba09ca3fc26a353f), + (0xb68eda4b8fd67c50, 0xb9e504fbf8d34ffc), + ], + [ + (0xbc5aa58d824fcbf0, 0x3fb829356c2fb67c), + (0xb5fd77431283aa4a, 0x3960ecbe354c0a2c), + (0x3c4aa58d824fcbf0, 0xbfa829356c2fb67c), + (0x3bc03ee1c336a8c1, 0x3f2cd964e5e4caa0), + (0x3c0adae94b604803, 0x3f70190ce66b97c3), + (0xbb6093ba87cf1908, 0xbef70d5fd8bad7b5), + (0xbbae25e1759c4268, 0xbf2126a150469b05), + (0x3b4f93e54fe01c25, 0x3eaa49ea85815004), + (0xbb4a798f7842e742, 0x3ec3910f5c159f54), + (0x3ab455b6ae464798, 0xbe4f0f4bdbe20c90), + (0xbaf74c179ba876ae, 0xbe5bc3697829b270), + (0x3a88354a18f986f7, 0x3de67f2959cd47c2), + (0x3a6dc6f645f5de18, 0x3dead81c085abf1e), + (0xb9f0a5000d22a9e2, 0xbd760a10ab0898ac), + (0x3a0d6591c74acc66, 0xbd72d07fd9984920), + (0xb99f00218c9ca6f1, 0x3cff2887ab34ba4c), + (0xb988be1c4afb3efb, 0x3cf3fd2c46f43bf9), + (0xb8eadfedf70fa7fe, 0xbc80a48214b2d829), + (0x3909f66df0bcce8b, 0xbc70a5cd24e7ae0a), + (0xb899f61798b66d98, 0x3bfbd0274fe475d9), + (0xb86046afc74d497f, 0x3be6519199343e6f), + (0xb812000c63615941, 0xbb72acc84cb991fe), + (0xb7e378e992bff237, 0xbb589952fc8a6a0a), + (0x378b39a8bc2ecbfa, 0x3ae49748fe385729), + (0xb76b443078ea68f5, 0x3ac6ae557e486745), + (0x36f8b6a88bc9e19b, 0xba52f9ba63bb636e), + (0xb6a8a49f117ff2cd, 0xba31a503187756c4), + (0x36578837435086f9, 0x39be08f63a02804b), + ], + [ + (0xb5f43effe24b00dd, 0x3964e5a96d3cc648), + (0xbc4ea89f3a432081, 0xbfb7e656ed57a0d1), + (0x3bed3586339a9eb0, 0x3f44f0cfc62eb61c), + (0x3c1736dd17549bf3, 0x3f8fdaba63e9c655), + (0x3bb8a2f82c46dec6, 0xbf1be7bad1c50547), + (0x3be9f603d64ca817, 0xbf4975ac0770c98d), + (0xbb716dcdea217fca, 0x3ed64a6af83ba860), + (0x3b95937b8720b7ef, 0x3ef35e6b41b6d77b), + (0x3b1fd0d91a2464a1, 0xbe80f12d050df219), + (0x3b0b801799b9f100, 0xbe912e744222ec5c), + (0x3a882bc4d34bf5de, 0x3e1e04a8c0a89be6), + (0x3ab7f6d69f6f7175, 0x3e23f0ed5e6a0d3b), + (0x3a40221dd027ff69, 0xbdb163fd7157593b), + (0x3a410e6fc017b151, 0xbdb04f8efe519654), + (0xb9d61b861892425f, 0x3d3c6417f7a11d41), + (0xb9df60b877c4e61e, 0x3d33cfa2affaf9e4), + (0xb93fca12e22cd45c, 0xbcc1334e857adc92), + (0xb940fcaa7e7a1f84, 0xbcb2917ae18b1995), + (0x38d075a83e7685a6, 0x3c4013b4389ffbb8), + (0x38b3ec31956d766e, 0x3c2bab4c1141e9b7), + (0xb82612cb7e109475, 0xbbb7e1ea817e1f13), + (0x3842297934775f91, 0xbba0c761c6922ab8), + (0xb7a89c07cafc73fb, 0x3b2cdd9a9bd10cbd), + (0xb7b8b565eb366f1b, 0x3b10e22afb97e007), + (0xb73a476233fdd42f, 0xba9cef8ddac69711), + (0xb716e797381cb799, 0xba7ca4454618f908), + (0xb6a5522943296628, 0x3a0848f98ce0dc8b), + (0x365472b048929931, 0x39e4a4c39def3d0d), + ], + [ + (0xbc52d2ff041ff2f6, 0xbfb7a597eb76a5e3), + (0xb5d66723cbc9de74, 0x3962eb71e7008809), + (0x3c42d2ff041ff2f6, 0x3fa7a597eb76a5e3), + (0x3bb9dc564fefd757, 0xbf2b0bd9eb615315), + (0xbc03cbe9e9bac1aa, 0xbf6f831b9629acd2), + (0xbb95cc1ecba38581, 0x3ef59d1c40c95ba7), + (0x3bad7b9ad1a3693d, 0x3f20c9d35d4be191), + (0xbb39533f4678ca4e, 0xbea8a711bec6920b), + (0xbb4180f2a560b483, 0xbec327e42f39066e), + (0x3adb23dbc7dc1492, 0x3e4d225aa8ded6cd), + (0xbaea1e7c5ffe5f6a, 0x3e5b2f83a946aed5), + (0x3a7207083f443397, 0xbde51bef06eb5d9f), + (0xba7f450be91eb6e9, 0xbdea4ab19859cce7), + (0xba0907e63b078849, 0x3d74b03ce339d83a), + (0x3a00617d77666243, 0x3d726eb2bbaa63c7), + (0x3998200aa70ed135, 0xbcfd433d6a1a8fc4), + (0xb95c36471111f47b, 0xbcf396dd9428b7d7), + (0x391cfade411a585e, 0x3c7f470853f5d974), + (0xb9104560036c71a2, 0x3c705215ddbe6f8c), + (0xb89e9dfcc8c7b005, 0xbbfa26d0528541cb), + (0x3877907f8f994b48, 0xbbe5e38754f217db), + (0xb7a00f2e50ac7581, 0x3b7192400028c4b5), + (0x37d0b5957a7cceb4, 0x3b5822a7a7e2efa6), + (0x378c09ba2822432c, 0xbae3636f4f21f020), + (0x3762ceed74e3669d, 0xbac6437cc6062eef), + (0xb6e668ce43677d5d, 0x3a51e56360c22f9c), + (0x36a1ef54ef26b01a, 0x3a3153d505a39c09), + (0x36443c33037016fa, 0xb9bfaca1a975c527), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs_taylor.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs_taylor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs_taylor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0_coeffs_taylor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1478 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated Y0 Taylor expansion at zero and extremums. + +Generated by SageMath: +```python +mp.prec = 115 +terms = 28 +print(f"pub(crate) static Y0_COEFFS_TAYLOR: [[(u64, u64); {terms}]; {len(y0_zeros)}] = [") + +def get_constant_term(poly, y): + for term in poly.operands(): + if term.is_constant(): + return term + +def print_taylor_coeffs(poly, n): + print("[") + for i in range(0, n): + coeff = poly[i] + print_double_double("", RealField(300)(coeff)) + # print(f"{double_to_hex(coeff)},") + print("],") + +prev_zero = 0 + +for i in range(0, len(y0_zeros)): + k_range = y0_zeros[i] + range_diff = k_range - prev_zero + + x0 = mp.mpf(k_range) + from mpmath import mp, bessely, taylor, chebyfit + poly = taylor(lambda val: bessely(0, val), x0, terms) + print_taylor_coeffs(poly, terms) + prev_zero = y0_zeros[i] + +print("];") +``` +**/ +pub(crate) static Y0_COEFFS_TAYLOR: [[(u64, u64); 28]; 47] = [ + [ + (0xbc749367c4c05aaa, 0x3fe0aa48442f014b), + (0x0000000000000000, 0x0000000000000000), + (0x3c649367c4c05aaa, 0xbfd0aa48442f014b), + (0x3c4098c5b27f9542, 0x3fa439fac16525f6), + (0xbc25adcf3e0230ee, 0x3f80d2af4e932386), + (0xbbe4e773096516dd, 0x3f4f71646bea8111), + (0x3bf3295907be08a9, 0xbf5444bda8b664a9), + (0x3bcc92ed3e7dac0f, 0x3f384c220672ab82), + (0xbbc2b56b5db9ac40, 0xbf217ab4afac0735), + (0x3ba57929ce662323, 0x3f0dafb9b8983d86), + (0xbb9a34080fad5051, 0xbef8bb962fa6c504), + (0xbb70f97215a75a9f, 0x3ee48b6770c210bf), + (0xbb6ac5099b6b7783, 0xbed1364ddbddf33b), + (0x3b5c6a28d5d49339, 0x3ebd06aadd881cef), + (0x3b360737a2bfac90, 0xbea8998eefe8caa1), + (0x3b10ceb1fd02d154, 0x3e94f198aa7c73a8), + (0x3b201bb903ea5d53, 0xbe81e742c1cf6acb), + (0x3b0e3c97eb74692a, 0x3e6eb820636013a9), + (0xbae9e5875024afeb, 0xbe5a709593e5d778), + (0x3a9c3113327b82cf, 0x3e46d299b1a6ab0d), + (0x3ad32a9aab166472, 0xbe33c08d3e0a3e4c), + (0xbab2ec0cd7aefe76, 0x3e2122b2a831eedc), + (0xba7fd1a1eaeba4e2, 0xbe0dcbb767b405d4), + (0xba9f28de864d6d7d, 0x3df9f4d817711be0), + (0xba84e5784f3ba466, 0xbde6a732ce7db295), + (0x3a2ba83b1dceb593, 0x3dd3cdb1820544fc), + (0x3a64cd3a569b8afb, 0xbdc156d9d7a9603b), + (0xba4c3618e715b8ab, 0x3dae68388d1e7164), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc5a4026e436c4d3, 0xbfd9c34256a12a0c), + (0xbc49ded6e8236fd3, 0x3faa09c9290367ef), + (0xbc253b02d2a53d30, 0x3fadf6d59bf50ebd), + (0xbc18dbf118b1a2cc, 0xbf7c116fdc598096), + (0x3bf40db0aa3d7078, 0xbf61e32bc4ef8a41), + (0xbbcbb6264c727077, 0x3f29982765166254), + (0xbb86be82f4783a97, 0x3f0ab2c1fecdcfc4), + (0x3b74540a4df5362c, 0xbed486371e6a663e), + (0xbb38925afac5b2b8, 0xbe93b21684089b4c), + (0x3af8953a9c0487f4, 0xbe5777058741bf97), + (0xbad841f372dee964, 0x3e5452ea00945a70), + (0x3aa79f6248f7f1b0, 0xbe2f6938829664f1), + (0xba9880934623f972, 0x3e0a5a1f3a2a293e), + (0xba74d07ce1ea2db9, 0xbde994e736de8ef8), + (0x3a666975b24e41c6, 0x3dc88ae5c83467bc), + (0x39e7564160acaf67, 0xbda75329361f19bb), + (0x39f36d6ccdec6121, 0x3d8643c7a49b7f43), + (0x39e06cdcecde2c8d, 0xbd655480c70f5929), + (0xb9ee4b7548f46bdb, 0x3d447c1c44c1487e), + (0x398be3f2b0a46b7a, 0xbd23b7d1fbf0fdd0), + (0xb9aeefcda909f8cb, 0x3d0305531056d810), + (0x398546902be387f3, 0xbce2626f5e5dfcac), + (0x395bf1c6ad49bc60, 0x3cc1cd4c7460b8d8), + (0xb91985693844d5c0, 0xbca1445851bfea5f), + (0xb92b3bdde2175982, 0x3c80c63a86aa43b3), + (0xb8ff7f8fe9d70fe2, 0xbc6051ca830eb872), + (0xb8b0d0de6a7a8a72, 0x3c3fcc0fa90bfb3f), + ], + [ + (0x3c7b8d2a1c496808, 0xbfd5c7c556f0c19a), + (0x0000000000000000, 0x0000000000000000), + (0xbc6b8d2a1c496808, 0x3fc5c7c556f0c19a), + (0xbc2b4d44aaadbbec, 0xbf8564d4b1ed0d7e), + (0x3c2e4289c3acba27, 0xbf8a15d92dfe3e27), + (0xbbedbea927b719eb, 0x3f4b438430469ff7), + (0x3bdc1760512f76cc, 0x3f37a8924cc2f914), + (0xbb70219aa771d161, 0xbef5f69b4a8a3c05), + (0xbb77299907aec5c4, 0xbed85b940eb607f9), + (0x3b3d5ae26ad627b8, 0x3e955ac0f5c3162c), + (0xbb0f58c09c1fabd1, 0x3e6d563e18b47eb9), + (0x3a99750b0b40769a, 0xbe23eac3a45e06ef), + (0x3a9e3d09f9f42f26, 0xbe0007671d55a8be), + (0xba495377f5d84985, 0x3dc04e13e8d2ceb5), + (0x3981b2ad63946aa5, 0xbd46e2b306cbb1f3), + (0xb9fbadc4f0bb048c, 0x3d54d18f7c90e926), + (0xb9c8225b40e694f7, 0xbd34980895b5067a), + (0xb998c3893e3c0087, 0x3d0a5b439cef90cb), + (0x3977814f4b07cebf, 0xbce1c9c4c0d530e1), + (0x3952fcdfd498e788, 0x3cb933cc6493bf1c), + (0x393ffe3660f335f2, 0xbc91c67122e8e134), + (0x3904bb25b4c5ee57, 0x3c6904e906c46283), + (0x38cd1dbe18c0ee49, 0xbc41a5ff5486c2fe), + (0xb8a09b2fbba2c634, 0x3c18f24433ae1991), + (0x3898e91198e4959c, 0xbbf1a84c8250ebd5), + (0xb856349e52eccab3, 0x3bc90826d8cc3eff), + (0xb848f5b7e7d4ec81, 0xbba1c456da51d36d), + (0x37f66d77762bebcf, 0x3b7940bb04835b31), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc78d4484b7cd2a6, 0x3fd334cca0697a5b), + (0xbc341c66c86d3ebd, 0xbf95aef611fc4d57), + (0xbc44929b43aab7fb, 0xbfa8969c64cbf452), + (0x3bfab353487eb36f, 0x3f6b2f14a95527cb), + (0x3c0aa67a62fad710, 0x3f61d35e85fde2a3), + (0xbbb270ba54459cab, 0xbf226dd71e391c8b), + (0xbb61863b08bc5950, 0xbf08177e4fe52324), + (0x3b494954a2d7de21, 0x3ec6a9227352f96a), + (0xbb44a5b1e0c3c3e1, 0x3ea34aa7573ef14e), + (0xbb06984676a524bc, 0xbe60a2814d7ac448), + (0xbad9251769eb31a9, 0xbe3442a3d3359ad9), + (0x3a86fc915b18c175, 0x3defa6c509566c72), + (0xba3b534d6e1095ea, 0x3dbf14e5584823db), + (0x3a16e8b19c361860, 0xbd7714c292be3936), + (0x39e500ccc143989e, 0xbd40679cd5855172), + (0xb998a55fa2ea549b, 0x3cf3365d5a786a7b), + (0x395c00dd62ac7e1c, 0x3cc38cf06b47bc6e), + (0x38f0c8bd8691968e, 0xbc82bd5a83b64d59), + (0x38bddc7ea088ddcd, 0x3c326e92cf91d829), + (0x38b27643db6c3b27, 0xbc127116123c3d66), + (0x388c47f57a6d55b0, 0x3be8df4f1bd4a3f7), + (0x3853b5c4a12853b5, 0xbbb9b0c7fab8762b), + (0x381d1068b57233fd, 0x3b8b3b04447f58f8), + (0x37f6b2b5793b64aa, 0xbb5dbd231117d61d), + (0xb7d3a5abcdba22eb, 0x3b3035d90c22fa4e), + (0xb786f2af60849004, 0xbb01a58ba966a549), + (0x376712c78c816e41, 0x3ad33cc7a0e946ec), + ], + [ + (0x3c61dc672a53c590, 0x3fd15f993fceab5c), + (0x0000000000000000, 0x0000000000000000), + (0xbc51dc672a53c590, 0xbfc15f993fceab5c), + (0xbc0d1c390189cb30, 0x3f758ef6efbed797), + (0xbc243ede64b782d9, 0x3f86395dfe49fcd4), + (0xbbbb4484582c2699, 0xbf3fb15104a41c00), + (0xbbd4410e752be535, 0xbf35f88a11d5564f), + (0xbb8b2d9b83a11c89, 0x3eef37d226a824b7), + (0xbb61fb17827843f5, 0x3ed6f7bab104f355), + (0x3b2da2cb75d8087f, 0xbe8f0c45a3824d70), + (0xbac1132bedbb6ebc, 0xbe6dfe11df12c715), + (0xbac5290f391bbfe1, 0x3e2311adc2e753ee), + (0xba92039061518817, 0x3dfad34e18504e16), + (0xba4d6cd9e6f85fe9, 0xbdafdc8061ae8b15), + (0xba189257c63f6446, 0xbd819498ca6cef9b), + (0xb9c8f0f4bb78628c, 0x3d33a291d5991f74), + (0x399127448ae5dbb8, 0x3d016f7ae80cad77), + (0xb958d1b0f5eaa04b, 0xbcb1f8d80deccee6), + (0x3910d158fa5b41a8, 0xbc7c27b5350a923c), + (0x38c3559986f928ac, 0x3c2d08034e70dd4a), + (0xb86c6bb218da7ccb, 0x3befac2006e277e3), + (0x383c518f1fca847d, 0xbb93e926868daea2), + (0x380ef79adc3898ef, 0xbb6dcdf980ddfdf4), + (0x37cea115c120894b, 0x3b2c4665b1564c6a), + (0xb783f5bf36c1dc64, 0xbaec0521ead39203), + (0xb74144c7cd1de85b, 0x3abed64c1afbe47b), + (0x3722cfb0d396394e, 0xba8e04ab2a193e84), + (0xb6f088c0c22460a8, 0x3a5a77e09ed6a09d), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c61e8f568f8c6b9, 0xbfcff635cc72b9f1), + (0x3c0fa6ebe8b75862, 0x3f89036451ff57c5), + (0x3c46345bcf3c5b7d, 0x3fa4e667a71556af), + (0x3c065e386829f03c, 0xbf60325ee41e910c), + (0x3bfde6b6846da9d0, 0xbf5fe23914fb9128), + (0xbbb9c28522c54ab2, 0x3f17f84d7c50e4c4), + (0xbbaeab0290c99b85, 0x3f06afdd57be1e14), + (0xbb2bbdfb6c4ce197, 0xbec04053abf4386a), + (0x3b3787c4b6b6a0b6, 0xbea2aea9ec48d8fd), + (0xbaf17a3632e2edc5, 0x3e593eb9f1ddb4e9), + (0x3ad9f831e08fbb99, 0x3e3428a3a3e30a13), + (0xba49cae682f11d51, 0xbde99d8c42f7a020), + (0xba591eb785e59448, 0xbdbec9805045aa58), + (0xba086b5bad70f23b, 0x3d72613659ce994f), + (0xb9eb4013d9ba0032, 0x3d418f302bdba980), + (0x38e42c05bf9582a5, 0xbcf3bc9ccb704253), + (0x3952d598704c3b46, 0xbcbf0dc4067be8b2), + (0x391246064faa45fa, 0x3c706e491f458956), + (0xb88908e1a67ee56c, 0x3c36013bac769277), + (0x388f595373e53a2e, 0xbbe616b4d62a47f6), + (0x384c63a51904dc22, 0xbba93fb6fa556eab), + (0xb7fb730412560441, 0x3b57963a88acf606), + (0xb7aad1cf0b52dca3, 0x3b1937ef4e3db6a9), + (0x37592af1b29a1e7c, 0xbac8387c0e875a84), + (0xb6f7ae247b07d290, 0xba80a12689ec647c), + (0x36beb9fdadfcf39a, 0x3a1bcc6e30896704), + (0xb697aa9158bd1808, 0x39fd4db12fab6895), + ], + [ + (0x3c54d14c77bc1691, 0xbfcdc14ea14e89f9), + (0x0000000000000000, 0x0000000000000000), + (0xbc44d14c77bc1691, 0x3fbdc14ea14e89f9), + (0x3c00ff03f97580f3, 0xbf6b037fe9cf2a52), + (0xbc2f19a8f5b1379e, 0xbf8367d7d608e4ba), + (0x3bdd892317f291c8, 0x3f34abef5636e4f7), + (0x3bd5ba5b5b609683, 0x3f33d8a661229259), + (0xbb700a3f00979ee5, 0xbee5cfe92a1a2c45), + (0xbb6087e84c57d2ad, 0xbed571814a1aa301), + (0x3b22b6740da6456f, 0x3e87414e33c9bacd), + (0x3afa4836a36f8841, 0x3e6ca7069e73d1d9), + (0x3abe65fd6bda59de, 0xbe1e0b3a705ff247), + (0x3a95774cb23eb7b8, 0xbdfa15dd62cf9f10), + (0xba399fbe055cb8be, 0x3daa33948eada12c), + (0x3a2240f402a7b379, 0x3d81419b1fd428ef), + (0x39cc415e74e0cbc8, 0xbd30882f60b8a775), + (0xb991c41d97727556, 0xbd015e5c0af749d4), + (0x392937d5bb210372, 0x3cafb1e115e08994), + (0x38f58b3c9e456997, 0x3c7b838263708865), + (0x38c5cd0199e8f790, 0xbc27e5d539870f02), + (0xb89a3dc2e116c3ad, 0xbbf19dae392457a1), + (0x383bc230f8650284, 0x3b9d2b72778fe832), + (0x37f13768b14c0c18, 0x3b6298bb7e2277f2), + (0xb7aa1239c7070276, 0xbb0d50baf60db64c), + (0xb773592299e9674f, 0xbad08ad53b850ab4), + (0x3717cc8a5ae6e9ab, 0x3a79141842fa569d), + (0xb6b9bec849ea1c6d, 0x3a38ab0a361907e6), + (0xb67a764f692d7a9b, 0xb9e14491ed3e919d), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c41398cacaa32d4, 0x3fcbf32a27594007), + (0x3bfe5ce4af724b17, 0xbf80bc2d84e65214), + (0x3c4acd5148eb7e9d, 0xbfa26cab38a8b368), + (0x3bfab9a1103e2000, 0x3f55f03e47165d72), + (0xbbc4598141a3f849, 0x3f5caaa76e34992d), + (0xbbbb7ab55e886623, 0xbf10c5f18c46d030), + (0xbb99f58bad5e7aa5, 0xbf04f0af7d46cd48), + (0xbb3040f00afca09c, 0x3eb7d1e28094e21a), + (0xbb3f12dedaa2ba65, 0x3ea1ad0731228479), + (0xbae9fe69a3662740, 0xbe536021c8cb3c34), + (0x3ad92bf3f184780b, 0xbe3371ae6c759181), + (0x3a630cc7c21c0cfc, 0x3de46ce077a8bed7), + (0xba5feb6d0e335e60, 0x3dbe235d3564b639), + (0xb9d7ae1d94bd92ac, 0xbd6e408e259c72fb), + (0xb9c8768c2460ab80, 0xbd415f07ac87e832), + (0xb91b6919f885a208, 0x3cf0a44f77f6a8ef), + (0x393312b132a8d347, 0x3cbefd8ab52f8eb9), + (0x38f1bfe622c31b37, 0xbc6c54ebb5ad3869), + (0xb8a61a375002a1c0, 0xbc360b43cbb5f5e9), + (0xb88cc62cec929222, 0x3be33d74aacb57e2), + (0x3842ffe5c04b22b9, 0x3ba99bfbb3fe627d), + (0x37e1d4df5722a5b0, 0xbb555c0969d70a77), + (0x37b44cfc1475dce9, 0xbb18c29d2318e9b5), + (0xb7682246c98d07a1, 0x3ac3c0750d221b4f), + (0xb717ffcd427c1eee, 0x3a843fa688c2eb51), + (0x369fc06d11ba5fce, 0xba2ef4ae2931c6ca), + (0xb674d5d2266c5526, 0xb9ec57869d64feb9), + ], + [ + (0x3c57ba12cd0fc91f, 0x3fca7022be084d99), + (0x0000000000000000, 0x0000000000000000), + (0xbc47ba12cd0fc91f, 0xbfba7022be084d99), + (0xbc0b3327197c9da3, 0x3f62ee079d020b12), + (0x3c2d0f8f36713120, 0x3f8163191c30aa62), + (0xbbcc7f2dbb383204, 0xbf2d7806ea72fc76), + (0x3bcf9ec581434d38, 0xbf320f95702b1d4e), + (0x3b899e1a0f3c0857, 0x3ee00610882294aa), + (0x3b61505ce3b29a78, 0x3ed3e398cbc472ea), + (0xbae050c77864dd20, 0xbe81bbe181c65162), + (0xbb0c3fb8339198a1, 0xbe6b0f89b7c61f3a), + (0x3ab91b7c8e3c7c3c, 0x3e17c3f85882049b), + (0xba976a7c841dba14, 0x3df90236614c84dc), + (0xba43ab3b18e59a65, 0xbda564920d1387dc), + (0x3a2b1754ca712321, 0xbd80be1811255cfe), + (0x39b342bebee2071b, 0x3d2bb9712586bfac), + (0xb99c92d876d25063, 0x3d0101c31e1df223), + (0xb916e23fb5f67bb8, 0xbcab298cda76e77b), + (0x3918a11b915d1274, 0xbc7b22acc441d872), + (0x38cdcc71612b99d0, 0x3c24dca37a32e97c), + (0x38855c0754c54ab3, 0x3bf176e94ee1fe21), + (0x3836cf20a369d629, 0xbb99d4f0d74e9093), + (0x3802940330562608, 0xbb6287585b150c7c), + (0x37a0f4cbacc81873, 0x3b0a5c015f1f057c), + (0x3779aaaf8d850193, 0x3ad07cc0082a44cf), + (0xb70fd62f89ce46a9, 0xba76909f83007714), + (0xb6d4e9d85e17b208, 0xba38f88423d4ad97), + (0xb66d34e3378a5539, 0x39e072fc561ac2bd), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc65b9c39e42719e, 0xbfc925c35988ee29), + (0xbbdda9c0588bc7cc, 0x3f7862549367591e), + (0x3c4a142ed6a5521f, 0x3fa0a4512039d6a2), + (0x3be94ce533c65cad, 0xbf5013b38cfb9292), + (0xbbea2a14cf0f61af, 0xbf5a24a1215f6684), + (0xbbae7b4c448b42eb, 0x3f08f91421377fad), + (0x3baf72fd0f5209a4, 0x3f035d17cec0172f), + (0x3b3cd242e4f5ce10, 0xbeb2283a93114096), + (0x3b259dda3f9c3cd8, 0xbea099e71392f54e), + (0xbad6dce1bfae1a53, 0x3e4e5de01e2e6566), + (0xbab52eec76dd7e24, 0x3e32885854ea8b06), + (0x3a6795ca81b0c1a2, 0xbde0730c2985fd22), + (0x3a4e06d8277ffd55, 0xbdbd1743cbb2e11a), + (0x3a013448997f1418, 0x3d68f8728745e1e6), + (0x39dd9a182e4412f8, 0x3d40f166cb29a7d1), + (0x398dd4bcf72e3139, 0xbcec10e67c004e3b), + (0xb9542acf7b7def7d, 0xbcbe7aec1ba33e83), + (0xb908d6ed91615a58, 0x3c68543e12c9bf9a), + (0x38a13a9d572a9420, 0x3c35d3939f6d1ed2), + (0x387a4284a63f1993, 0xbbe0c7ba11981a01), + (0x38405b9a6bff4fca, 0xbba97d9177222a00), + (0xb7f4c779b6c742c8, 0x3b52dfb95f4a8634), + (0xb7aba81ffd3b5c41, 0x3b18c04f3759b6eb), + (0x375fa028706c2252, 0xbac1a799c1562309), + (0xb729c62dd7828d2a, 0xba844dc9c3e85489), + (0xb6cf5aac2a393499, 0x3a2bea86b90f9faf), + (0x36614b1df5aeed9d, 0x39ec85971210b79b), + ], + [ + (0xbc63db68c567283b, 0xbfc80781c32422e7), + (0x0000000000000000, 0x0000000000000000), + (0x3c53db68c567283b, 0x3fb80781c32422e7), + (0xbbfab5094c039454, 0xbf5c6923374d561f), + (0xbc032419a9d405db, 0xbf7fbe6df840847f), + (0x3bc0f03bc2e75d6b, 0x3f264f4711a85f1a), + (0x3bbd9972e6c197fd, 0x3f309ff42b0d7a68), + (0xbb61aba5a7ce6455, 0xbed8a60685a597d9), + (0xbafdb153b13f2cf0, 0xbed282d26a74c38e), + (0xbb1d21d4a94b9e91, 0x3e7bdb57a889a4c1), + (0xbb099a040a6939c6, 0x3e697d9c12a60cef), + (0x3a35e114fc2a1213, 0xbe131aa8691738fb), + (0x3a93c999393c858b, 0xbdf7d486eee39a85), + (0x3a223c1c4424f0db, 0x3da197f258214b3d), + (0xba1644a8cbcb4af5, 0x3d801dd7f92195ff), + (0xb9ca37ef1c0ef3fa, 0xbd27480b9efaa860), + (0xb98847e4ec1195cf, 0xbd00833ea1f83461), + (0xb928c4b1729bab7e, 0x3ca73bf7964edc26), + (0x3913ebe30cf0771f, 0x3c7a891d704fef9b), + (0x3881294f9e950341, 0xbc22222dcf094b80), + (0xb898aeadae639677, 0xbbf12db9d21e37ed), + (0x37ea537285a44833, 0x3b96c4638e4cc003), + (0xb7f3ee61741a27e7, 0x3b624ff2a82fc9c9), + (0xb7987ce466329a95, 0xbb0782fd4fc7cb7b), + (0xb75dca0980ad8630, 0xbad05bab97dc88c3), + (0x36f1b4cbf5a58e0a, 0x3a74565e5f91bb35), + (0xb6d553555a830f19, 0x3a38da3118f887bc), + (0x36758225c016dcfa, 0xb9ddea7aa8da61e4), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c64fef53f4893e5, 0x3fc70c4f66cab47f), + (0xbc1e032768318e4d, 0xbf72c6731071e936), + (0x3c2f806b21bc9577, 0xbf9e924b85a17361), + (0xbbe1434be87c6363, 0x3f48d6c364d92082), + (0x3bf5cbe0638f4cef, 0x3f58247b02d6b0f6), + (0xbbaade8b3660fd4e, 0xbf0376125938561d), + (0x3bae81e47dd383cf, 0xbf0206da232a2b6a), + (0x3b424b3c3173e20f, 0x3eacaf84db871510), + (0xbb022e3bac70bc67, 0x3e9f3671177306ca), + (0x3a9f8b17b052db72, 0xbe48654b001006cd), + (0x3ad272b921d7360d, 0xbe3199ec88b18766), + (0x3a6b9a3bf5083c1d, 0x3ddaeb1a849305fb), + (0x3a57cadaf3f1d693, 0x3dbbe67c197c48c0), + (0xb9c7cc3d8d1e5e49, 0xbd64cdfa0bd69898), + (0xb9db4ff4c3ee8f12, 0xbd4064936f97922f), + (0xb9777557537dd027, 0x3ce7c83b5186222f), + (0x395de8595a9345f0, 0x3cbdb73ad7fa8bc8), + (0x38f6136241cc3637, 0xbc64eecbf0b91d4f), + (0xb8d2eab985ecf43c, 0xbc356ab697c0ab6d), + (0x387327e90134d3b9, 0x3bdd4506fe436113), + (0xb837e66ef2a0608f, 0x3ba925d81a8dc397), + (0xb7f15df323201ec3, 0xbb50a89d96a14715), + (0xb7bfc8950449ed4b, 0xbb18875d24cf9582), + (0xb754b1be99b10be3, 0x3abf7e546e402e74), + (0x372718433d137dec, 0x3a84326527427bb9), + (0xb68468a05b2cb0da, 0xba2921298884b92b), + (0x367c4fc25beb34a3, 0xb9ec75a8ffac9550), + ], + [ + (0xbc6d2f0105f3ce7c, 0x3fc62d94d97e859c), + (0x0000000000000000, 0x0000000000000000), + (0x3c5d2f0105f3ce7c, 0xbfb62d94d97e859c), + (0xbbf6c13bde837960, 0x3f565481b55eaefb), + (0x3c17013075a066f9, 0x3f7d5f857a2a6107), + (0x3bc5f065aa6339f5, 0xbf21a015a2ccb78f), + (0xbbc12f349174f010, 0xbf2eeb4eafd8614b), + (0xbb53525d6141be28, 0x3ed3a7b79e4d80fc), + (0xbb662d899f08a704, 0x3ed154ed4598d2f0), + (0xbb0444753ebe791d, 0xbe767f762ea293a1), + (0xbafe11bb6f1d4207, 0xbe680ec1e042ee62), + (0x3aa725a667375b0d, 0x3e0f529652b9de0f), + (0xba97b074118bab16, 0x3df6ad7bd2247f55), + (0x39e3900c76e6a68e, 0xbd9d4e582fb43553), + (0x3a1f5fd82381bd59, 0xbd7eeb6efcbb6228), + (0x39c7389b8d7fe521, 0x3d23b1eabb5c1c2c), + (0x3992974c386cdc2a, 0x3cffe92f0882b440), + (0xb923c49452353597, 0xbca3f20671568bca), + (0xb9002a4da3d3a816, 0xbc79ce30ac166eb5), + (0x38b02f60dd891164, 0x3c1f8db6e94f1a96), + (0x383459153c91e395, 0x3bf0cc90c0607e7d), + (0x383003b333010a99, 0xbb940c6bb9f9a6c4), + (0x37d6a317d4f5ae21, 0xbb61fe382b9ca927), + (0xb76dfd62097696b0, 0x3b04ed907b4ff4b6), + (0xb75abcbe1108a215, 0x3ad0234a19150d32), + (0xb71105a3cea0d529, 0xba7246b54dbf759d), + (0xb6cf812a75ac4069, 0xba3899f3eb5b7cf1), + (0x36688dddcd012369, 0x39db1cda80386890), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c5fe2103f7148bb, 0xbfc5664d37c37d7b), + (0xbc0a0fbbe8bcf9a6, 0x3f6e0ee8ec84659a), + (0xbc383a77d074bd0a, 0x3f9c6c415c971b4b), + (0xbbb06fe5233f06e8, 0xbf43ec49cb941f55), + (0x3bfe14142e1727fe, 0xbf56853b2d047885), + (0xbb98cea461592c41, 0x3eff632a9396fd4e), + (0xbba049885559b2a5, 0x3f00e6afa01af561), + (0x3b452a8549984c17, 0xbea7541247acdf59), + (0x3b3a7242d1da1ee5, 0xbe9d735e8beb8fcc), + (0xbae93d2eb398218a, 0x3e440e6a7cafc096), + (0x3acae709ad00bd19, 0x3e30b9cfae2ab337), + (0x3a72d6de94168a75, 0xbdd668087e67279b), + (0x3a5eab8fef3b6421, 0xbdbab498e6f69c73), + (0x3a0c8ec8094d97ed, 0x3d618b5674894afb), + (0xb9db00611b51a32b, 0x3d3f99da023c7232), + (0x3971efb1b8385b20, 0xbce450b8165c264c), + (0xb934a2a8921ee27a, 0xbcbcd387688c508f), + (0x390195709783e7c1, 0x3c621a103bd0a113), + (0x38dbfdcea4f39167, 0x3c34e540faee9f3c), + (0xb87ade2a66df50ab, 0xbbd999b3cf947860), + (0x3847c3fb15ff4625, 0xbba8a8f1c18bd090), + (0xb7c279575afc11de, 0x3b4d71c32bb0428b), + (0x3797f3b19c608f42, 0x3b18289deefa7196), + (0x3754153d9d2c7699, 0xbabc183d32d93a1f), + (0x371c05c0e3242945, 0xba83f7ae467ae529), + (0xb69ad19453e29618, 0x3a269b7adc6804ef), + (0x367130005d91c163, 0x39ec3a580d0009a9), + ], + [ + (0xbc5e9088e9ff2518, 0xbfc4b2a38f1ab9b4), + (0x0000000000000000, 0x0000000000000000), + (0x3c4e9088e9ff2519, 0x3fb4b2a38f1ab9b4), + (0xbbfcc8083276a193, 0xbf5225a5c73f2233), + (0x3c1525fe797e2126, 0xbf7b750d89a9b35f), + (0xbbb08db59499cb94, 0x3f1cbdb4f1d5dbbd), + (0x3bc35c23938c810e, 0x3f2cfe933fc6d0b8), + (0x3b52d453a3ea26cd, 0xbed01ef10d839bbc), + (0x3b71cffb5ca00bc2, 0xbed05375a588a72b), + (0xbb03f71b77aa7082, 0x3e729afe7ea7ba43), + (0x3af336f1341f6d84, 0x3e66c8fe015e6610), + (0x3aa95a6cddd6ccb3, 0xbe0a2a01e7af0241), + (0xba7851970a0eac4f, 0xbdf59b33050d2092), + (0xba24b1969b00bcf7, 0x3d98c0a50e7852d3), + (0x3a16ee76e659ed58, 0x3d7da3426f355690), + (0xb9cdfb48abef1f45, 0xbd20d3b48429ce84), + (0x399e510926654c46, 0xbcfec46e14cd5d9e), + (0xb94d8b3c4e2a8910, 0x3ca13c3da7405de9), + (0xb9199ffbceedc2fd, 0x3c79043b4a0f03df), + (0xb8b7be40ca4f6a7f, 0xbc1b902f4b26eb03), + (0x38971ae8f878f8af, 0xbbf05dbe75075aa3), + (0xb834ec73bf06d543, 0x3b91b0f5dc51ac20), + (0x37f5aae0017b0662, 0x3b619b551575f49b), + (0xb799e67f64663319, 0xbb02a3e0a7397c83), + (0x376711f24f4773dc, 0xbacfb4a185898d2d), + (0x371e5adab87fe639, 0x3a706acbac6f6bd1), + (0xb694af13fd9e3bbb, 0x3a383fb94408a8c0), + (0x367e1f0c9bfb4eba, 0xb9d88b17eec4fb7c), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c5f3474ffad3fd7, 0x3fc40f8ffdf09a5f), + (0x3c047810b9792b13, 0xbf68c37a29c4586f), + (0xbc348471cc77dfe2, 0xbf9aab099314b209), + (0x3be6aa80fcd045e0, 0x3f406f735cc0f6a6), + (0x3bebe02c3928856d, 0x3f552d29a06802e0), + (0x3b89fdf10253d75f, 0xbef9fc04c675c0ed), + (0xbb62f9306dab684a, 0xbeffe48825ed3c8e), + (0x3b43251677276142, 0x3ea36bd2d58ff45b), + (0xbb2af08b6d9ffd1a, 0x3e9be87e2cad2ce7), + (0xbaec807c6c103803, 0xbe40d1fdedc6cb17), + (0xba7064dd3b6b5724, 0xbe2fdbeb107ddccf), + (0x3a75893a2f37955a, 0x3dd2f44d01321684), + (0xba4232fa9e2160b9, 0x3db9921373ea0f26), + (0xb9da39ce7fd7d9d8, 0xbd5df6b83ac56981), + (0x39db340c9865a7cd, 0xbd3e6c005b62bffa), + (0xb9708387feb998a6, 0x3ce1848c91de7162), + (0x39532ac00e2fa8ff, 0x3cbbe5530d0fcf1e), + (0xb8f7971717114a0f, 0xbc5f8540b8b06042), + (0xb8d7787ecd6e687d, 0xbc3451eb9bf040e8), + (0xb8696fbf3607765c, 0x3bd67f1edd448664), + (0xb84ad321b52d14f9, 0x3ba8169212a3f8c0), + (0x37d9b42cb89199fa, 0xbb4a1a0e01aa07e3), + (0x37a4d1d59a34de84, 0xbb17b199c8e398ae), + (0x37565ae964dca96e, 0x3ab91bd224db8139), + (0xb71f2cb70464cd53, 0x3a83a756c81f58e6), + (0x36a634d3a7864fac, 0xba245b460d9907d1), + (0xb68d4c3a3fc04b15, 0xb9ebdf60ca34bcd7), + ], + [ + (0x3c4997782859a00d, 0x3fc37aaceac987b9), + (0x0000000000000000, 0x0000000000000000), + (0xbc3997782859a00d, 0xbfb37aaceac987b9), + (0xbbd05a6eb7d72f47, 0x3f4e3fdbfd65014a), + (0x3c1d91e80a0529b8, 0x3f79de7a33bc3a97), + (0xbbb56ef10c1ebaad, 0xbf1801d911fbd06c), + (0x3bcce92f388f20ea, 0xbf2b605a5ade3a80), + (0xbb539bcd81dca55a, 0x3ecb0a2608144a3d), + (0xbb6b3675770103a2, 0x3eceeceb341ad833), + (0xbaf6cb1030653935, 0xbe6f623fc7be9f9f), + (0xbb0412babffea489, 0xbe65a9ca94a0d7dd), + (0x3a9025c6eebf2e96, 0x3e0638ba2f5f5e6b), + (0xba745bdb1a5b34d9, 0x3df4a1b4217ef864), + (0xba32b235688fed51, 0xbd9530c712e738d4), + (0xba0b5b22087c168f, 0xbd7c6e5208e89146), + (0x39aabbad8d2c58ef, 0x3d1d0eb5303a804a), + (0x3988eb799dd68c33, 0x3cfda6ae03deea14), + (0xb91737db06df4072, 0xbc9e05ef8aaeac6f), + (0xb8ffe2eecdfe0f4b, 0xbc783796c23b134e), + (0x38836225e752dac9, 0x3c183703be1e065f), + (0xb87377273654d7a7, 0x3befd20ef0b9b32e), + (0x381f98f1f5615157, 0xbb8f58105c7413a4), + (0xb7f08f641ff4b998, 0xbb612ee75ce95b31), + (0x37ac304030a2dba7, 0x3b00a4adc945e963), + (0xb760c6584778a1df, 0x3acf0d914ecfdc7d), + (0x36e07d1a751a4b9c, 0xba6d88af68997ed9), + (0x36db1ad813072ac7, 0xba37d36ec5b8b8d2), + (0x3672facc8520936e, 0x39d63a55dc5490c7), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc569479644686c1, 0xbfc2f206e49909c7), + (0x3c0fab1b83d46057, 0x3f64dbf6a9fb80d7), + (0xbc32d9141794e6dc, 0x3f99336443318ed1), + (0xbbd0d543bfdf0729, 0xbf3bb6aa3d4e9e78), + (0x3bebe3f68704392e, 0xbf540aaa5d94bd8d), + (0x3b419d1c00b3671e, 0x3ef5f61b666129a6), + (0x3b7d88846cdeeaef, 0x3efe4158391f2c2b), + (0x3b46369cf5ad9126, 0xbea07a7a0745f74a), + (0xbaff9b34051c76b6, 0xbe9a8ea97b670057), + (0xbac6b3f27d760998, 0x3e3cb10b3affeaff), + (0x3a82ba28da6d4ef2, 0x3e2e6d78879f98a1), + (0xba64a30357ebbef6, 0xbdd044447904054e), + (0xba47c38fca3d087e, 0xbdb8850c99b76d50), + (0x39f0bc2d92a30cdc, 0x3d59e4fa8ff52f90), + (0x39da7eb9dc7c3857, 0x3d3d4b2c1afd964f), + (0x397e3e8ba2460cb7, 0xbcde807e2b0027a1), + (0x394f139f76a41235, 0xbcbaf942a59e1d55), + (0x38e1843405416d9e, 0x3c5ba64c4108b5da), + (0x38d7063d60c6e606, 0x3c33ba614d4a4418), + (0xb86c7ec67073bb42, 0xbbd3e1ce585ffa1f), + (0x37e22b5fc552851b, 0xbba779ee6dc176e6), + (0x37e956c614ab6059, 0x3b473c7bc63c3880), + (0xb7b796c186b6db87, 0x3b172ca465caf995), + (0x37588aab872e21fa, 0xbab681e73200f9aa), + (0x37260574a8f5d812, 0xba83492c838e2b86), + (0x36bb446923624df9, 0x3a225df78223620b), + (0xb680e905ae135da7, 0x39eb6eaa1f93591f), + ], + [ + (0x3c6b7326e3fbaa70, 0xbfc2740819f1caaa), + (0x0000000000000000, 0x0000000000000000), + (0xbc5b7326e3fbaa70, 0x3fb2740819f1caaa), + (0xbbe4b7a0f7878f6f, 0xbf49b6f37d0a00f9), + (0xbc011249d3675d98, 0xbf78868d7401bf2e), + (0x3bb6d7fdfc21dddd, 0x3f1470a7cbcb436a), + (0xbbc5a6b64d367c4b, 0x3f29fe94ce3d3e83), + (0xbb5352a68b13573e, 0xbec71660e61f0f0c), + (0xbb68d34686b724d9, 0xbecd6dfcdb026028), + (0x3af006603a027d68, 0x3e6ae79c35d01bca), + (0xbb0ef1a3dfdf0941, 0x3e64ac50be6ca02e), + (0x3a8def2f9646d0a2, 0xbe03258409210f45), + (0x3a9043cd5dc1ca57, 0xbdf3c09685c05e25), + (0x3a140fbcac25067c, 0x3d925d85992670e2), + (0x3a184f1121e2c362, 0x3d7b509288f452b8), + (0x39b4b4c230260136, 0xbd19586d0c8690d8), + (0x39776fb98c811c8b, 0xbcfc973a175ffbb6), + (0xb9337afd9ae7c0eb, 0x3c9a5d61717a7033), + (0x3907444e5980ecc1, 0x3c776fa9ee1a429f), + (0x38bdaeb8edb9cbf2, 0xbc156907cfeb69d8), + (0xb8705ec9beaf1eac, 0xbbeee74de5fce6e5), + (0x382fdb3ba7577f93, 0x3b8be6f4a0664634), + (0xb80c67b2a3f6b8fa, 0x3b60be8c60df72fe), + (0xb7980c2fe23edbd8, 0xbafdd3c10be941a0), + (0x376107929e229c71, 0xbace5afc740d98d1), + (0xb6ffc39670c4b338, 0x3a6aa1c12cf8bc0c), + (0x36bf0bd26da1ffcc, 0x3a375bd104e008ce), + (0x3671519a4046ccc5, 0xb9d429e651c05e27), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc6be2029a752b31, 0x3fc1ff5ebddd3c3a), + (0xbc04bba52e05ef56, 0xbf61e2035324643c), + (0xbc3a42d5bcad204f, 0xbf97f3506d4a1231), + (0xbbd8ddfdbbecb379, 0x3f37c65c9302c53b), + (0xbbff79e837d220e1, 0x3f53117816335151), + (0x3b97f81238bbf061, 0xbef2df9afa521294), + (0xbb9270fec55a19ce, 0xbefcd5d4a9d78a14), + (0xbb3a3cd8b5652e44, 0x3e9c672d4d6f7766), + (0xbb2736243a1eeac9, 0x3e995e4b102194f0), + (0xbad74d87610e5d51, 0xbe38d22636140e12), + (0x3acf7d99cf14d15d, 0xbe2d24fc9458bf7f), + (0xba609b77f08fc036, 0x3dcc462d9da63971), + (0x3a5ec10df895da79, 0x3db78eafb15964df), + (0xb9d9e108200b834c, 0xbd569f5d498b660b), + (0x39c6a15cc2204e9d, 0xbd3c3c4e5b0fab49), + (0xb9732871d1bbe384, 0x3cdaccaf11834f8d), + (0xb93cb3c7ca476321, 0x3cba161c63abb182), + (0xb8e7d3af6ae5f8f7, 0xbc5870224af67eb4), + (0xb8dc947a17c950f7, 0xbc3324870c0b9f1a), + (0x3835837498a32b18, 0x3bd1adca41a58439), + (0x384e7a933bc23443, 0x3ba6da83c46ff8a1), + (0xb7e2d9939a6b62de, 0xbb44c90654b3ecef), + (0x37b4d48249a8211b, 0xbb16a125665039e4), + (0x3751c4fab8892f89, 0x3ab4403fbdd7d32b), + (0xb723bebaa05fe118, 0x3a82e31c9f4289aa), + (0x36be4670338eb907, 0xba209e5b516e3eb9), + (0x36636814b89df314, 0xb9eaf0173952c775), + ], + [ + (0xbc4081c2a50ad27b, 0x3fc192f2627a74e3), + (0x0000000000000000, 0x0000000000000000), + (0x3c3081c2a50ad27b, 0xbfb192f2627a74e3), + (0xbbed88bdcc1e7819, 0x3f4635b38affe698), + (0x3bfbe434e30d7a64, 0x3f775eceaabf7f86), + (0x3b9ca8671aa55df6, 0xbf11ac9e0164f7c1), + (0x3bc6ba93b83783a0, 0xbf28cc464a35b0af), + (0xbb6979a9d3cf377f, 0x3ec4014d9bf389c3), + (0xbb64740ce7aaa9f5, 0x3ecc1f05a2d85165), + (0x3b05322df74ff9fc, 0xbe6761d18ebb04af), + (0xbb0eb4591c8e1e8d, 0xbe63cb9af103e0f5), + (0x3aa091624db08269, 0x3e00b3cb55bbe5d2), + (0xba9e3e54a390f0cd, 0x3df2f5c763b33667), + (0x3a315b71b511ed17, 0xbd9017771db5a5e9), + (0xba14beedd13cfb94, 0xbd7a4a5e79f39fb9), + (0x39987da2b8e5b9fc, 0x3d165128cc4d99cc), + (0xb995477d64dc86b2, 0x3cfb991575a9daff), + (0x391a0c68aab7bf20, 0xbc9756473a57c932), + (0x391f7919e47d81ac, 0xbc76b070fece822a), + (0x38aea8dff65f4d33, 0x3c130e1f9f1562ad), + (0xb885307e292801c8, 0x3bee01b29bf38fbe), + (0x380c55e014e1fd44, 0xbb88f8681f03bf7f), + (0xb7a97a5de24d257a, 0xbb604e16b9d18563), + (0xb79be9ebe189653a, 0x3afad6e6ca7adff4), + (0xb75781440aba92bc, 0x3acda3ed85696d1e), + (0x36e87609f3833ad8, 0xba6817ad40ddad7a), + (0xb6d43ee7c83c85cd, 0xba36de22ba99ddd2), + (0x3644163dc4acb5e3, 0x39d255cee2696246), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc4e7aa4db2a788a, 0xbfc12dd55d4be2b3), + (0xbbf6da5fa7c968b2, 0x3f5f1aee31818d19), + (0xbc319e43d5f0f1d5, 0x3f96de64242a8310), + (0xbbd5e5667369987f, 0xbf34afdf89fca61a), + (0x3bd951e5980d1eeb, 0xbf5238cfc13ac771), + (0x3b9632bd2bd2db1d, 0x3ef0719d13e00e52), + (0x3b672b1f290673a0, 0x3efb974781a526b4), + (0xbb1d4aa2a151d3bc, 0xbe98cc82a70d752f), + (0xbb3bd18c494b86c6, 0xbe9850ae878c25bb), + (0x3ad9b4f29c25b035, 0x3e35bba73e282ede), + (0x3ac284476c98f69a, 0x3e2bfe1396e83644), + (0x3a4529f3c858a5ed, 0xbdc8d7dbe4a241ab), + (0xba562391a18ff729, 0xbdb6adfbd773748d), + (0xb9fff61487742711, 0x3d53f51dcb398ad3), + (0xb9d0d5d8e6a35200, 0x3d3b40d30be85f3d), + (0xb97f65625ced3453, 0xbcd7bf544872d9cd), + (0xb9476385a2a2b1f8, 0xbcb93f163a09379d), + (0x38f06b1beee10cee, 0x3c55c1ca7d35fe43), + (0x38b8eeb49079a75a, 0x3c3293b43a786b37), + (0xb854b85c8c7227d3, 0xbbcfa1df0227f182), + (0xb80a3744049cba08, 0xbba63d0b33ebfae1), + (0xb7cca2e89550a07c, 0x3b42afdbba3b1d6f), + (0xb799806c5d3ae5db, 0x3b161427fedb2614), + (0x374631901a8ab5ef, 0xbab24bb69b617f29), + (0x3706634bb0b1f240, 0xba827970d7fd5a93), + (0x369d62ccd478840e, 0x3a1e2c0be398bf2f), + (0xb676a35ad46d678c, 0x39ea69a77fc2c19d), + ], + [ + (0x3c60c06e2860e868, 0xbfc0cf3ee98f769b), + (0x0000000000000000, 0x0000000000000000), + (0xbc50c06e2860e868, 0x3fb0cf3ee98f769b), + (0xbbb4697a99d5fadb, 0xbf436f451f6e14fb), + (0x3c194225ed089995, 0xbf765d05948a946a), + (0x3b91ed6777d1acf2, 0x3f0ef55c5a0d16cd), + (0x3bcf058a2a3a8b0d, 0x3f27bfec9d15d038), + (0x3b563856fcc3c915, 0xbec18c549f28e528), + (0x3b59158b4542d2c4, 0xbecaf7544eeac766), + (0x3af5145c85b8d71b, 0x3e648e81edf38b1d), + (0x3afbd8241fda0445, 0x3e630341e78d1014), + (0xba51c1f8c39d84cc, 0xbdfd73d2c942e970), + (0xba8a04a03e6e4b0a, 0xbdf23ec2729d3a6d), + (0x3a229664fb891b84, 0x3d8c78e44cdec8b3), + (0x39dac0cbab30eb59, 0x3d795a6f6107b4e6), + (0xb9ba116bfc433ee0, 0xbd13d1c77de8a03d), + (0x399e9b0cd3f3a20f, 0xbcfaace944141c61), + (0x393126e2b3ac5379, 0x3c94cfcb5e84963e), + (0x390ce3384ec723cf, 0x3c75fbc3b0ec9599), + (0xb8a8a1431d96f0b6, 0xbc11115c48c0688d), + (0x385d6ff29b2308fa, 0xbbed24eb2fb8425b), + (0xb825e6a6df55bdde, 0x3b8677909ec26485), + (0xb7c21d072a134e9c, 0x3b5fbfed070231f3), + (0xb797829f30055e39, 0xbaf8423b3340403e), + (0xb75751d2373f6e38, 0xbacced4275822f9a), + (0x370ed561d6ebcce7, 0x3a65dfcd7ab2578d), + (0x36cf53856f82b22b, 0x3a365e43730aa685), + (0xb61c3bb3f92eb84f, 0xb9d0b87da5a9b4de), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc64353fd6c42f1d, 0x3fc0768257dad56a), + (0x3bf3a4186dcffc49, 0xbf5b602a7beaaa48), + (0x3c16aaef36d826d8, 0xbf95ebc22efd092c), + (0xbb76c80c9b070fe3, 0x3f3236a604142e61), + (0x3beddcf66c5978ce, 0x3f517a482faa8d85), + (0x3b66ad649af93743, 0xbeecfc00890787ae), + (0x3b928f6dcddab568, 0xbefa7d7b128ac538), + (0x3b25a6c98552063d, 0x3e95e419f1b57043), + (0xbaf32b6c630ee4fa, 0x3e97603cea235244), + (0xbad9cee30553553d, 0xbe333a0b436c8824), + (0x3abe7890b4a4106e, 0xbe2af46417845f40), + (0x3a4f7394a3298f16, 0x3dc609ac8cd8177a), + (0xba59cd5f345dc226, 0x3db5e11b87ad3903), + (0x39f73ed5597f6f80, 0xbd51c2756590391a), + (0x399986e8c9348fca, 0xbd3a586483dd891d), + (0xb97cc034606fd4e1, 0x3cd534d22c600964), + (0xb957a2d70318a209, 0x3cb8755ad322c506), + (0x38e4680effc80bb4, 0xbc53809e528c6189), + (0x38d5dd4c01f7d4c2, 0xbc3209a0a78d682e), + (0xb8644847850e1cab, 0x3bcc77842d1f731c), + (0x384c2f3bd9e41480, 0x3ba5a4538092f65b), + (0x37efb4bb53ec98f4, 0xbb40e2a86e6cb3f9), + (0x377521ae7e540c78, 0xbb1588f3efb4ad64), + (0x375fdbdc3816089b, 0x3ab099874d761b53), + (0x37298a0b16897a8b, 0x3a820f23922028f2), + (0x36b4686e1a4ffa47, 0xba1b7c94063b4326), + (0xb682cf52edcbf7b1, 0xb9e9dfbe640c7d02), + ], + [ + (0x3c61166b7995967a, 0x3fc0230ba90f2871), + (0x0000000000000000, 0x0000000000000000), + (0xbc51166b7995967a, 0xbfb0230ba90f2871), + (0x3be85d0df08ff853, 0x3f413164a0864cde), + (0x3c175b99fcae0fa4, 0x3f7579c1bdbcfc99), + (0xbbaa847d3261af11, 0xbf0b67e1913c668b), + (0xbbbdc3b0bfb76e70, 0xbf26d26de4fd8c5d), + (0x3b509cffcaa6fd75, 0x3ebf1b520b063853), + (0x3b56e93d7c515f0c, 0x3ec9f01e7c1909a0), + (0x3aeb43dee8b56e57, 0xbe624071b1796027), + (0x3a99b4c0bd0ff4a5, 0xbe624f8e939ce43c), + (0xba9ac0bb7d806efd, 0x3dfa35663595463f), + (0xba625661d1f74770, 0x3df199120d49d507), + (0x3a1bddfd9246953c, 0xbd896771e1b15e44), + (0x3a1acb7638900b33, 0xbd787ede134ed7a0), + (0x39a9e2e9004bba4f, 0x3d11bccdfbafa1fd), + (0xb995262f16494ab9, 0x3cf9d22a6dc5a57c), + (0x393e65a43ea6fde8, 0xbc92b00e367301bf), + (0xb8e38ef38ce7f9e3, 0xbc755236722b3018), + (0xb8a085f6fce94877, 0x3c0ec2ce49a94662), + (0x38851022a9daf9df, 0x3bec52d2fb48c061), + (0xb8260ec09f1c11bc, 0xbb84522e399fa43a), + (0x37d6e8cbd63da93e, 0xbb5eeb3ee8f96a17), + (0xb780414b4648c1d1, 0x3af60651f3414a8f), + (0xb75a1e55435fe75b, 0x3acc3a2c8e72fa37), + (0x37034c532c4c52e0, 0xba63ef7c46a9be7d), + (0xb6d60fee2f339275, 0xba35deebe060dd5c), + (0x366c4892cbf5f446, 0x39ce97bce469d7a5), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c10417847765c1a, 0xbfbfa8b3f9ae4375), + (0xbbcf334b3619566d, 0x3f5856073b7fa2cd), + (0x3c3664c698368b18, 0x3f9514e652eb2e96), + (0xbbb93b53ec827565, 0xbf3032298718ea1a), + (0x3bfdfbf103edc8e3, 0xbf50d1153fde431b), + (0x3b7c365adad42a66, 0x3ee9cb455c29d6a7), + (0xbb9fa9b04c310c2c, 0x3ef982167b1c52c3), + (0x3b3466b707822fa7, 0xbe938191ef68eab3), + (0x3b31f4e7061400c0, 0xbe968865345b3130), + (0x3adaf50c9fd62c74, 0x3e312960010da387), + (0xbace36911ce663a9, 0x3e2a0403679f6882), + (0x3a4177820d3b2b22, 0xbdc3b67cc0b96c06), + (0xba565f2ed3c28fcc, 0xbdb526038b956efd), + (0xb9d5a1b33bcbb16b, 0x3d4fda06e840fa34), + (0x39d1d67f1bd55539, 0x3d3981de640d0e00), + (0x397c94419a95b1f3, 0xbcd311fc56c4b88a), + (0x39532577b4bca3e2, 0xbcb7b8f62899fc83), + (0xb8f552faebfd4704, 0x3c51977cb27410a2), + (0x38d26b959afd2d20, 0x3c318706eb31dd46), + (0x386ce90ca03d9538, 0xbbc9c2ecf35b9e14), + (0x384b179344e2eb73, 0xbba511e7341e8837), + (0xb7dba680290d429b, 0x3b3eaa190aa91ed0), + (0xb7b49a491a85f98b, 0x3b1501910205c4a9), + (0xb74ebc3f994c58ab, 0xbaae3fe1d152dac7), + (0xb72316bcea29e953, 0xba81a632639f368e), + (0xb698c03bf571184d, 0x3a192191e962f593), + (0xb68c49d86016d888, 0x39e95576c2d368f1), + ], + [ + (0x3c50db2c50623ec0, 0xbfbf13fb0c0e6fcd), + (0x0000000000000000, 0x0000000000000000), + (0xbc40db2c50623ec0, 0x3faf13fb0c0e6fcd), + (0xbbddaa7169324a5a, 0xbf3eb3e6fcc47c00), + (0xbc1a7c91ef9a7da1, 0xbf74af74cbd77bef), + (0xbb8ca4e36c0e29e8, 0x3f087bb1ebeaec75), + (0x3bc0dc1e11076c62, 0x3f25fe629203150e), + (0xbb5990b5b348875c, 0xbebbd0f2a6555e6b), + (0x3b6af9c37c81d002, 0xbec9040de830649e), + (0x3ae759c4b27cdf74, 0x3e6057f7a76993d7), + (0xbaf1d65071810a7a, 0x3e61ad6dd5105c3e), + (0x3a9d40eb62d35800, 0xbdf782a6f5738cdb), + (0x3a8bf5df6e6d389e, 0xbdf1027dc06d4453), + (0xba28e41b1a5587d6, 0x3d86d65b13b16f65), + (0xb9fc75d3c8772d41, 0x3d77b59e9ed7367d), + (0xb9af754c04eface9, 0xbd0ff800f2a49a00), + (0xb991f98cd4e6ac14, 0xbcf907be43054aec), + (0xb933d033de8a73d1, 0x3c90e2e1d8f5ad67), + (0x38eed8fb6a3c50a9, 0x3c74b3a8b0fb5259), + (0x388913f9676a0ac9, 0xbc0be06d96b6ddb7), + (0xb88ea864297f3fc7, 0xbbeb8c227343f289), + (0xb82ff7b2b57b5685, 0x3b8278dcce458371), + (0xb7f78beca367a3df, 0x3b5e1fb52b874a03), + (0x379b7478eaac89e3, 0xbaf41590cb708f7e), + (0xb752fe7b149fbb7c, 0xbacb8ca63f91e577), + (0xb70548503aed227a, 0x3a623cdbe3c71609), + (0x36c12f6cf019ff77, 0x3a3561f0d31660bb), + (0x365d1dc388e61bc9, 0xb9cc13f7faffaf26), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c56a7c2ed8fa844, 0x3fbe8727c572a2c2), + (0x3bfdee3ce04b3d39, 0xbf55d1ef092ab395), + (0x3c206dda20eba87a, 0xbf9454e7a7395636), + (0x3bb99eb39ffae4f4, 0x3f2d0cc3a7fa6d3d), + (0xbbc9d1e5b54f9af7, 0x3f50398d2cbd02df), + (0x3b8aa1f4bf33efdb, 0xbee725b0909f9c66), + (0xbb9b20d87a760067, 0xbef8a022f5fee447), + (0xbb1fcb0c42b0e854, 0x3e9185b1ea97a54b), + (0x3b3ea0aa1deb55ca, 0x3e95c571167401ae), + (0x3acd2759cfccc15b, 0xbe2edff6514e1da9), + (0x3ab2592f6b4b9153, 0xbe29298da3c4fa71), + (0xba62158d0945cb91, 0x3dc1c34705eadfb1), + (0xba424ede84d84b4b, 0x3db47ab8ec529c51), + (0xb9e73e83248604d7, 0xbd4cc24a2f007c3e), + (0xb9c2979e3d03632b, 0xbd38bbcc44e6c225), + (0x39703e1bd29b296c, 0x3cd1420df9bb4359), + (0x395d047d716a7a8d, 0x3cb7095f8b3266bd), + (0xb8cd11469be08694, 0xbc4feb87e4e655cc), + (0x38be1dd0526935fa, 0xbc310c0caf4ba7a9), + (0x385a60dd5e84c9c5, 0x3bc76f4ca221cf39), + (0xb83ecbabc0dd7d07, 0x3ba4868177e6f5ef), + (0x37b8847e584a462d, 0xbb3bf93dc497bf28), + (0xb7bb4e77466271a4, 0xbb147f2c424e92f5), + (0x374a584169fadea4, 0x3aabace093fa5e7e), + (0x370af91e2a607b95, 0x3a813fe3dbef7300), + (0x36a10a818d4db7be, 0xba170f75c4345a45), + (0xb6269b19813edb68, 0xb9e8ccf104c5a0ca), + ], + [ + (0xbc3b9f1d130797af, 0x3fbe018dac1c17e3), + (0x0000000000000000, 0x0000000000000000), + (0x3c2b9f1d130797af, 0xbfae018dac1c17e3), + (0xbbc5edf62333beba, 0x3f3ba21bd15d02a4), + (0x3c138b4f0d3a4110, 0x3f73f9e0db07e7ef), + (0xbba6f23ddcae2db1, 0xbf060b77c5e27622), + (0x3ba86d4e04faa212, 0xbf253f9b1a5d228c), + (0xbb5fddc005e382a4, 0x3eb910b38812c253), + (0xbb40935ad53575b8, 0x3ec82ee6dfdfedeb), + (0x3afa8bf307790c80, 0xbe5d7cc2a9a602ee), + (0x3b0b50784ff133f1, 0xbe611a57d8645358), + (0x3a8673cb487ec434, 0x3df53d401519442d), + (0xba8c03600ffb7a70, 0x3df07915ef87408d), + (0x3a2022a5f15014b6, 0xbd84aabcb6141c76), + (0xba1d37109cce2377, 0xbd76fcb8e2eada15), + (0xb9a95525555a3484, 0x3d0cfcfdb2faeb02), + (0x39997fd3cf0000fa, 0x3cf84c5369d2e33d), + (0x38f88b42ac1a9330, 0xbc8eb11d7e6581b7), + (0x39181a3f66a29421, 0xbc741f9ab4632e3b), + (0xb8abf00ddaa40351, 0x3c0965159407b5ab), + (0x3885289d8a9dc178, 0x3bead0e3cd065e84), + (0xb8220f36807a6153, 0xbb80dee0e94d3838), + (0xb7e15def3c2d10d9, 0xbb5d5e035bd44cab), + (0x379e09d7e4e2053c, 0x3af26452e5cf7372), + (0x375c2b8feb4af0ba, 0x3acae5d15fef7e8f), + (0x370c46b7285b4063, 0xba60bf2894ab39b9), + (0x36bc8ff0c23e41b6, 0xba34e87ee39a6f39), + (0x366a289544183384, 0x39c9daa655367c6d), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c555d27e18add4d, 0xbfbd82939ab62339), + (0xbbe5f2055a671318, 0x3f53b5a54845670f), + (0xbc331ee0af44ab91, 0x3f93a7ff1622def8), + (0xbbb2001fd8691606, 0xbf2a3ebc476a606d), + (0xbbb7a5c728534a7d, 0xbf4f61adde3a8c61), + (0xbb6721b027970bc9, 0x3ee4ec45da0478b0), + (0x3b60295953d04e19, 0x3ef7d3b28159f23c), + (0x3b21dd48380f5e9a, 0xbe8fb3f21bcd7fc4), + (0x3b3047a478eaf94e, 0xbe95145a876d2273), + (0xbac575cc2ab01d93, 0x3e2bf64cdf7c0558), + (0x3a9c7ea365ef1c0c, 0x3e2862204ac427d2), + (0x3a25523941e42ede, 0xbdc01c0d48888811), + (0x3a3766e8ee24e58a, 0xbdb3dd6cb1cbcd8f), + (0x39e11ac6552bc64c, 0x3d4a2020c8b3c20d), + (0x39bbaa3793fd39c4, 0x3d3804a9d711292e), + (0xb965d9ecddfcbd4d, 0xbccf6a1ef9182e2c), + (0xb95ee6d1970be0a7, 0xbcb665c82dfd3111), + (0x38e2ccf8afc7f5eb, 0x3c4d1cbc474ae672), + (0x38baa3fe632e7af8, 0x3c309883728ed041), + (0x386cc2812a2e5111, 0xbbc56bda19c4b049), + (0x3825988783a1ff06, 0xbba4025c7e87cb33), + (0x3798e8afd688bd54, 0x3b39a17a3b2afb39), + (0x37b0dd0e73f34a5f, 0x3b14026125d71009), + (0xb73504f75a230f17, 0xbaa96b8155611361), + (0x36fcaf6a0d9e7292, 0xba80dcfdcb67c11b), + (0x363354ed9306d4a3, 0x3a153c10e4500766), + (0xb6880389022204ec, 0x39e84794b22bad24), + ], + [ + (0xbc56edd809f4ec43, 0xbfbd09b21e36c0bd), + (0x0000000000000000, 0x0000000000000000), + (0x3c46edd809f4ec43, 0x3fad09b21e36c0bd), + (0x3bd1da06fbc186d3, 0xbf390b0e6a475e45), + (0xbc140975d5184af6, 0xbf7355b904fbf7ee), + (0x3b9e3b983f117cfc, 0x3f03fc459d1e25a4), + (0xbbb494c77a177873, 0x3f2492cc61d19dfe), + (0x3b46367d4d299b08, 0xbeb6bcf110a02ad1), + (0x3b6b6ea46d6db74f, 0xbec76d44f6a83523), + (0x3a8030056b81d3a7, 0x3e5ac61efcb3c36c), + (0x3afeb8462b17799c, 0x3e609436fcaa3965), + (0xba99e294aeb8cd7b, 0xbdf34eb6095f969b), + (0xba88db8194acb808, 0xbdeff662945eb368), + (0xba237c1915fc9c0d, 0x3d82d05bf8ff5181), + (0xb9d3e0b801e8758e, 0x3d76525fbb563fe0), + (0xb9a734f42937bddb, 0xbd0a6eb937c7f6c0), + (0x396073f8f8b180ec, 0xbcf79e90468589ab), + (0xb922e469e5eb93e5, 0x3c8c0998b46c2a6d), + (0x38badc48095c4e55, 0x3c73955fe5fb130b), + (0xb8949ebb69e71ffd, 0xbc073ec897598aef), + (0xb88f7564544e1430, 0xbbea20bd7b4d506a), + (0xb7fb326fec2fdde6, 0x3b7ef3962c3d7988), + (0x37e82dd0be2c1482, 0x3b5ca6507646e165), + (0xb7879646e68dbcf8, 0xbaf0e8ca73f2d68d), + (0xb74018d4e9ae2637, 0xbaca463d4098cc93), + (0x36f61d9992deaded, 0x3a5edd93261617c3), + (0xb6dbe7fd3fa3deaf, 0x3a34734a62443d4b), + (0x3623d3bbf119c872, 0xb9c7e1ec2479954a), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c4e1f19f10295a1, 0x3fbc96700031f601), + (0x3bd8339df4a4a968, 0xbf51eb2a07d0f09e), + (0xbc39bfe53ec12c8a, 0xbf930b36eddaa234), + (0xbbb206af4ba8d313, 0x3f27dd2dde84b73c), + (0xbbd1f3a6f0dd2e56, 0x3f4e696553e0b8a5), + (0x3b70bebcc672e081, 0xbee3085aa35a1647), + (0x3b964955e62a56d5, 0xbef7199f24bccae1), + (0x3b29acbd0629609d, 0x3e8cdbab6a766176), + (0x3b336b635edd4912, 0x3e9472a7cffbf91e), + (0xbaa919ffba04358e, 0xbe2979f5211c4dae), + (0xbacb3a83d64d312f, 0xbe27ab4b01a902db), + (0xba3d20c26289bb46, 0x3dbd63904e4c487c), + (0x3a3a2263834e8f85, 0x3db34c83fb1c2279), + (0x39d0d1629893175f, 0xbd47dcfdf13e5ccc), + (0x39b38e8b7b2086d0, 0xbd375b01ddacf988), + (0xb96c94f8a51700d8, 0x3cccbd41ea6afd29), + (0xb9596f4635f2eb43, 0x3cb5cd46eaba1e98), + (0xb8ef331fa6111e01, 0xbc4aaded22d1c6ea), + (0xb8c316503d17378d, 0xbc302c0feb2cc9ff), + (0xb86b0bb9dacdd402, 0x3bc3ab0efb0f5a6a), + (0xb83c8dfa9ab81f86, 0x3ba38564ae73cbd4), + (0xb7ce2bd40d6dd04f, 0xbb379494ee2fe052), + (0xb7a9f50c26ffe35d, 0xbb138b6c6bd628fc), + (0xb704cc1a22fd0a79, 0x3aa76f817567d54d), + (0xb72b4eeb7ce6fd0f, 0x3a807ded69c2252a), + (0x36b142adaa59897c, 0xba139e9549f763d8), + (0xb6561aae4c08fc78, 0xb9e7c644065d040a), + ], + [ + (0xbc5ca34ef67ceca5, 0x3fbc2861347b1b39), + (0x0000000000000000, 0x0000000000000000), + (0x3c4ca34ef67ceca5, 0xbfac2861347b1b39), + (0x3bbf201ae2302561, 0x3f36d57bffb37fd5), + (0xbc16b4ecac2fa1c2, 0x3f72c060ef553f18), + (0xbb9df91b90d34cd8, 0xbf023a407b722d2e), + (0xbbca3432d200d5db, 0xbf23f55581ec683d), + (0xbb5e04bafba5dc5a, 0x3eb4bfb4daa2ff62), + (0xbb42a29e463f2261, 0x3ec6bc69099af2f7), + (0xbafb52717e21f4f1, 0xbe5873340987d276), + (0xbadb9738396340d1, 0xbe601951f02d2b37), + (0x3a8c2da917c5d2d4, 0x3df1a6174fe55fbe), + (0xba7265752e07ea23, 0x3def0eca5bc0284a), + (0xba1b8d994d0c183a, 0xbd8137cb1fcc55a3), + (0x39c1b1fb4f7e04be, 0xbd75b4f7f2bb19ed), + (0x39961a8be6115ecd, 0x3d083934ed797abc), + (0xb998209f68cee7a8, 0x3cf6fd29fcbcf38b), + (0x38da8f6db73066be, 0xbc89bbe4a386b1fc), + (0x39119e7a973ba60e, 0xbc73143b8f6fa9b5), + (0xb8a42d280d3b7044, 0x3c055f1ef8c6277c), + (0xb8741bc4d5b892a4, 0x3be97b209a81cdd1), + (0x381f56010f66d563, 0xbb7c822a3d227a0b), + (0xb7d326c5dc6baa73, 0xbb5bf86da968d5d8), + (0x37685ec534d88737, 0x3aef3590b082abca), + (0x376f5328f688841e, 0x3ac9ae18938ed4dc), + (0x369b410a6e56968b, 0xba5c8a82558390d1), + (0xb6c5a55f28288a0c, 0xba3402b3aeae6a78), + (0x365785f4c242b76d, 0x39c621268afb8484), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc2986f8b543f277, 0xbfbbbf246019c0d4), + (0xbbf8243dc68faf05, 0x3f506224199140d8), + (0xbc31c8ab4f070de9, 0x3f927c3416c09898), + (0x3bc1400990dffd7c, 0xbf25d279dc87cf69), + (0xbba49f5dbb72a054, 0xbf4d86a5f5adbdac), + (0x3b8c1a134d478d15, 0x3ee169041634c248), + (0x3b908bd4df68b455, 0x3ef66f5bd1bedae1), + (0x3b2340bc492ebacd, 0xbe8a69b2c717d54a), + (0x3b2b327658085637, 0xbe93de4eab456cbd), + (0xba8a52518b85c3bb, 0x3e2755eabbde6915), + (0xbaceee9ff82c0693, 0x3e2702fe7ba9f8c3), + (0xba380d66035d4ef3, 0xbdbaf2007eeae256), + (0x3a5fcfcb227b90a8, 0xbdb2c69746948e55), + (0x39e9a9de8d952335, 0x3d45e77ad9a9daf0), + (0xb9d9fd6d3c1b2712, 0x3d36bd7bc6045cd0), + (0x392032afd924a7d3, 0xbcca6a2a200a32c2), + (0xb959d59bb0713bcd, 0xbcb53ef0001a8fc4), + (0xb8ed4be5f4212c88, 0x3c488eb37fc1d400), + (0xb89d39eabce00ec1, 0x3c2f8c832f51b562), + (0x3840e097e8a92261, 0xbbc22200a03da113), + (0x384c3af44c4ec552, 0xbba30f596dc1d400), + (0xb7dc9bccb090c4a1, 0x3b35c6dd14718296), + (0xb7bce5b1aace9f68, 0x3b131a4eaddd4e23), + (0x3744f32babed55e0, 0xbaa5ae9b0fa87ab5), + (0x372de16b15f9f82a, 0xba8022e41d997f41), + (0x36b5867aa0456426, 0x3a122f7b20539f5a), + (0x368433fa75fa367b, 0x39e74982e085fb06), + ], + [ + (0x3c497d2b9281abc8, 0xbfbb5a622198a72c), + (0x0000000000000000, 0x0000000000000000), + (0xbc397d2b9281abc8, 0x3fab5a622198a72c), + (0x3bd29fd72f6917e5, 0xbf34ee71cf67c243), + (0x3bef69e3e89e3765, 0xbf7237c02b462f6f), + (0xbbaa32f85df10bfa, 0x3f00b67b6fdfec62), + (0xbbcb53a20d4b2f61, 0x3f2365167d8bc330), + (0xbb5df27a7ce0e8f5, 0xbeb3086b7a296e69), + (0xbb64ce30c488f398, 0xbec61a141425c2a6), + (0xbaf5a586401bb54e, 0x3e56712b23991e80), + (0x3afc0839aea10c7b, 0x3e5f50736839e481), + (0x3a894d28c9a59269, 0xbdf0366d02b91b84), + (0xba3b7dda45b64dc6, 0xbdee38f9bda5f6df), + (0x3a0f464a8fd7c7bf, 0x3d7faa3d1cb01e65), + (0xba1e45ca78c915d9, 0x3d752317a2a5b9a2), + (0x39a7d004a800c3b5, 0xbd064cd06847bd1d), + (0xb95179a5ef0f66b7, 0xbcf666eebfeb573d), + (0xb9285e2b929e1519, 0x3c87b8b54f1785bc), + (0xb919589128d0188e, 0x3c729b70ca32ef58), + (0xb8a46a9746bfb343, 0xbc03ba848f791229), + (0x386730f56682d5be, 0xbbe8df65522ba529), + (0x37f2ab030e344d2f, 0x3b7a5b900787f393), + (0xb7bb11ca75f0fcdb, 0x3b5b53fa2dd77bb4), + (0x378eb255c1629783, 0xbaece6fc2aac5380), + (0xb729982419793a6f, 0xbac91d5406064eb8), + (0xb6ebe671ea8254cb, 0x3a5a7a1d77627f77), + (0xb6cf1004e96b1aa1, 0x3a3396e1ce8aa477), + (0xb62a0c13a37cd740, 0xb9c490dcdeea0de1), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c56e5b3d654a3de, 0x3fbaf9cb42cd08a7), + (0x3bd4df22cc118423, 0xbf4e1c66d7616e37), + (0x3c32068ccdde2ecb, 0xbf91f90fd1013589), + (0xbbb9426a5fb5baf4, 0x3f240e3eb09b7d6d), + (0x3bcf4131edb03e4e, 0x3f4cb682ff471274), + (0x3b8c9cd4cf70b38d, 0xbee0016819a61dd8), + (0x3b8325d69b159805, 0xbef5d2d1c420646d), + (0xbb157a8a155b14f1, 0x3e884b0fe8a85355), + (0x3b1d5bbe26d9661b, 0x3e93559d96bef598), + (0x3ac3da55cae73bf1, 0xbe257a0be74997ad), + (0xbaac817776602a6c, 0xbe26677c8f53b6a6), + (0xba48a3adc3758fa2, 0x3db8d1ae21b756a1), + (0xba55e41c080dae7e, 0x3db24a6e1ac65e87), + (0x39d87ea029a22f95, 0xbd4432017034b94c), + (0xb9b0c571c0172220, 0xbd362ae0447c7c88), + (0x392c7ada7dc7ba07, 0x3cc86190e6a87084), + (0xb8cce5846ffd630a, 0x3cb4b9e1622f9586), + (0x38e2a29910f701c9, 0xbc46b1f3e51e7716), + (0x389f461c8b8d14fd, 0xbc2ecd4131542af6), + (0xb865a2f5fd7d4f74, 0x3bc0c7d6edd792f0), + (0xb84d80cbe9f82337, 0x3ba29fe1dfb030da), + (0xb7be1d7b0beadd6d, 0xbb342eb58314dd57), + (0xb7bd13d73eb584cb, 0xbb12aee37e25148e), + (0x3706be9737507cbd, 0x3aa420385af46d51), + (0x37178c7e05bb4a09, 0x3a7f97d766899d96), + (0x36b40aa8f19fb9a4, 0xba10e85b8b8bab6c), + (0xb68622de5eece514, 0xb9e6d19365680b1c), + ], + [ + (0x3c49a6abbfd839f8, 0x3fba9d183bc04545), + (0x0000000000000000, 0x0000000000000000), + (0xbc39a6abbfd839f8, 0xbfaa9d183bc04545), + (0x3b97025ee34cfaec, 0x3f334779874010dc), + (0xbc01fefbfc4e4e9c, 0x3f71ba2299ab88a8), + (0xbb55c0e2a19295ff, 0xbefecb19f5bdc649), + (0xbbcce75d43258257, 0xbf22e052707cc859), + (0xbb5a63ba682d6499, 0x3eb18a5da77edd83), + (0xbb6dd00d54139579, 0x3ec5846b622f592b), + (0xbae5e872e9945332, 0xbe54b17e97b5884a), + (0x3ac6a221a04b77f7, 0xbe5e7f76674dfaab), + (0xba84b342c0e05e8d, 0x3dedeb504ed353c6), + (0x3a86775d5b3d25ee, 0x3ded72e25f190409), + (0xba00d09a917a59f6, 0xbd7d3e076b0201d6), + (0x39c46b750b88e7f8, 0xbd749b825302af88), + (0x39abeb00dd42cc76, 0x3d049d35475fc5c4), + (0x399639c0b0dc546c, 0x3cf5dac9623f7b3a), + (0xb8c1489d884eb85a, 0xbc85f3d5130dc414), + (0xb91861dc55985f01, 0xbc722a4aeb6977eb), + (0x3890153f6d844191, 0x3c02479e3ad06b06), + (0x3880093480726623, 0x3be84cdbd4996301), + (0xb80c8f94083b0211, 0xbb78745ed629d641), + (0x37e3f2458bb649a6, 0xbb5ab87a5deb4183), + (0xb788f6fa139ccbd7, 0x3aeada86a4d62add), + (0x3756d41ddc1f8d52, 0x3ac893b9d1f77835), + (0xb6ee50fc22fbfa2f, 0xba58a3198036b128), + (0x36c2de5121e2e61a, 0xba332fd57127bac6), + (0xb63875952298668b, 0x39c32aa4779bf0be), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c5729f43724612e, 0xbfba4407dac72297), + (0x3be5723d945cf385, 0x3f4bcba4dec1da44), + (0xbc3fe775590d7dac, 0x3f91803c65cafdfb), + (0x3bc90cfa57dbb628, 0xbf2283df2b3e4a6e), + (0x3bc3e3e0391f1e19, 0xbf4bf695e89259cd), + (0x3b630f86ed6a90e0, 0x3edd8f3759122d51), + (0x3b9030fb5fd0d14f, 0x3ef54246c8e04218), + (0xbb1b2983b9c451c8, 0xbe867111bc8e67a4), + (0xbb3a3cef2b75d5c2, 0xbe92d72a1f62ec18), + (0x3acbd165727f6821, 0x3e23d9ca3eb1e22f), + (0xbacc01aecceaa6e4, 0x3e25d74a6e225515), + (0xba59e0bf6ede94ee, 0xbdb6f4b420b2f957), + (0xba5cdfc28e1823b4, 0xbdb1d6f985dc3ec9), + (0x39e7d772f8fce3e1, 0x3d42b1d81101dea8), + (0xb9d82ef548b3e361, 0x3d35a2197089fbfb), + (0xb956841fa8612f5c, 0xbcc6974aff17c78f), + (0x394b2b4bcdaabf0e, 0xbcb43d4892ea1bcf), + (0xb8dd3073293bb4a5, 0x3c450d21b45ffbaf), + (0xb8b6f6e75ed53665, 0x3c2e196b40872c65), + (0x384e654070aa0a0c, 0xbbbf2abd4dc31a0d), + (0x3847ef0270966133, 0xbba23699d6695800), + (0xb7d774e0a1072a6c, 0x3b32c4314fb1b042), + (0x3798dfd4a7af4ecb, 0x3b1248f0b0a01e5c), + (0x374feaa8039e5d21, 0xbaa2bd2ced8351bd), + (0x37162b8b059830f3, 0xba7ef1e8bc571d77), + (0x36a5be76c75f587a, 0x3a0f87929eae0a41), + (0x367e0d8209c727ce, 0x39e65e8aae87b358), + ], + [ + (0x3c4f5da9526c15aa, 0xbfb9ee5eee1a97c6), + (0x0000000000000000, 0x0000000000000000), + (0xbc3f5da9526c15aa, 0x3fa9ee5eee1a97c6), + (0xbbc33100916421b3, 0xbf31d55d93e59bd7), + (0xbbb6887e944ccfcf, 0xbf7146219394a99c), + (0x3b8ca8e50931ec0e, 0x3efc7d32bb646e2a), + (0x3b459561844c2171, 0x3f226599aed4f1ca), + (0x3b2f06633c8a57af, 0xbeb03ba58ec85c12), + (0xbb602686ed9f14f1, 0xbec4f9e3961bb9dd), + (0x3aeea9ee2c50aae8, 0x3e5328d4dc334079), + (0xbaef3a53aa36f2d4, 0x3e5dbda7ac70ff93), + (0x3a77a84a53fa4382, 0xbdebb7c2f187144e), + (0xba64d01b19ecf2c5, 0xbdecbac24c760567), + (0x3a16eec036aa6895, 0x3d7b1c35b65eca4e), + (0xba1d9ece3561eb27, 0x3d741d23f93de7a0), + (0x39ab2aa54e1d2f75, 0xbd03208d806698c2), + (0xb99acf6d8899800a, 0xbcf557c166250d9c), + (0x391934ffa520f9d8, 0x3c84637130a9d7e6), + (0x38f36ddde127bd83, 0x3c71c021934a5bf8), + (0xb89d68e84d698c21, 0xbc00fed119c94fe7), + (0x388e25551faa0fb9, 0xbbe7c2d64524cfa1), + (0x381e8f2946a1a0bb, 0x3b76c3357c3f7adf), + (0x37f7b13ebe2df289, 0x3b5a25665c8bb28a), + (0xb78e1214cb5a34de, 0xbae906c5169421c4), + (0x376f2d89008c8e68, 0xbac810fd94a57b7b), + (0x36d90aeea93b07c4, 0x3a56fd9fc0a89c82), + (0xb6dc9ebd96e6e684, 0x3a32cd7652121959), + (0xb61332c9199d4380, 0xb9c1e8fff9203895), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c422d28ddb0663f, 0x3fb99be73fa3efcc), + (0x3bc06623176e8323, 0xbf49c3248da75775), + (0x3c24e67d5d6f01f8, 0xbf91107147eda800), + (0xbbb9f85d6cd5a102, 0x3f212980be9d8520), + (0xbbc6d7f4255305b6, 0x3f4b44e1221e6051), + (0xbb75ffceb4092099, 0xbedb67b78c1dd9c5), + (0xbb952647474dbc63, 0xbef4bc49e9b5bcfd), + (0xbb07d96f2518a716, 0x3e84d02ffb8bcfd0), + (0x3b3e32d27646b835, 0x3e9261c31456e43c), + (0xbac76119a10d67c2, 0xbe226b400744def1), + (0x3acd5778eebf7e73, 0xbe2551251a2b4223), + (0x3a46fe94a695c8b2, 0x3db5500f9531112d), + (0x3a083f83ad3b6fcc, 0x3db16b4e936f8a96), + (0x39d92e892227b268, 0xbd415e70b28182e4), + (0xb9d311286e6202d4, 0xbd352230c03cb29f), + (0x39694a35e842f6b5, 0x3cc5019095879294), + (0xb95c82d35e7d0a85, 0x3cb3c864dd8bd878), + (0xb8e021ec04623c9c, 0xbc4397af75e324f3), + (0xb8c1d4036b77bcc2, 0xbc2d701c9937cabc), + (0x385d6fca0674878d, 0x3bbd0965d9326e17), + (0xb84fa05c3c3c3a3f, 0x3ba1d319c4fce696), + (0xb77cd5e86688f3b8, 0xbb3180c1f00da609), + (0xb7ba86637aa4bf02, 0xbb11e8305b488b70), + (0x3736c6f17e2a0301, 0x3aa17f7804b40b24), + (0xb7084fe04399b71a, 0x3a7e53bca7936259), + (0x369739312d3bebf0, 0xba0d7a5725978bd4), + (0x3689e9b194e5ecb2, 0xb9e5f05f8d349ae8), + ], + [ + (0xbc55bbc298d062cd, 0x3fb94c6f5898708b), + (0x0000000000000000, 0x0000000000000000), + (0x3c45bbc298d062cd, 0xbfa94c6f5898708b), + (0xbbc91fb79f224deb, 0x3f308f4f1b8fb0dc), + (0x3c11274d5c28ac61, 0x3f70da931c776c71), + (0x3b468ef3cfedd83e, 0xbefa7550d2940f2a), + (0x3bbf74462dfd6402, 0xbf21f3b978a47cf4), + (0xbb46a542136ebd9e, 0x3eae28ea02472df4), + (0xbb6c80d173ca8c69, 0x3ec47930aec78cb8), + (0x3adf057ade51b16d, 0xbe51ce32c4f34e51), + (0x3afb45adc74dd76d, 0xbe5d0950e99c8b39), + (0xba7a6618445563ec, 0x3de9c5a1603e79e8), + (0xba8e2efa815aa6df, 0x3dec0f1778cf9887), + (0xba168e5ec792cc80, 0xbd7938fe13097690), + (0xba1edc43381b3d99, 0xbd73a70bdaedabef), + (0x39ad72e528e9a77a, 0x3d01ceeed28a9bbc), + (0x3981b5050358ac3a, 0x3cf4dcf95c5ca94a), + (0x38e5c074caf95ef8, 0xbc82ff92717657b8), + (0xb8c1517cb6203642, 0xbc715c5a3e02462c), + (0x38848ac21ce9d63b, 0x3bffb3c968d1317c), + (0xb868eaf9f67497e9, 0x3be740ae3a9480c4), + (0xb7e7ce53355d1e7c, 0xbb754054fa0921f1), + (0xb7db46466a3c45dd, 0xbb599a3335285172), + (0x376a7830f0710c1c, 0x3ae763db68405483), + (0x37496d5dfac38e6e, 0x3ac794c6d23aefa1), + (0xb6d0259444fde6bc, 0xba5583129058029b), + (0xb6b49a7445a09fb2, 0xba326f9c89204c85), + (0x3648f301c94c285c, 0x39c0c73ede23db3f), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbbb1d709b3e6aac3, 0xbfb8ffc9b9a131f6), + (0x3bdb4dd57b3641ab, 0x3f47f724314bb99d), + (0xbc3086cbc396cba9, 0x3f90a89c5d1074ba), + (0x3bb8da379d94d744, 0xbf1feeaeb33465e8), + (0xbbef433944c1a75a, 0xbf4a9fba36a7a08e), + (0xbb7f256bdb98dded, 0x3ed980034770f3b2), + (0x3b91b4c8faeaae10, 0x3ef43fa4bb8cba57), + (0xbad948481046b8ce, 0xbe835f40f3a3902b), + (0x3b3e2e9d940a603b, 0xbe91f465ba292c0d), + (0xba98e1101ee20622, 0x3e212688f74f8106), + (0x3ac17030074177fa, 0x3e24d3f7e3fdde95), + (0xba567e7ce0ee9db6, 0xbdb3daee9c38c74a), + (0x3a51aeae4597f6fa, 0xbdb106a132ee69a7), + (0x39ebf6485dd79da8, 0x3d4030e7765d6c75), + (0x39c15870eda63050, 0x3d34aa4c24070ac4), + (0xb958792c38458a32, 0xbcc3987402712b60), + (0xb95ac711e3d7df47, 0xbcb35a87994f9f22), + (0xb8b987c84af86497, 0x3c424aa138f72769), + (0x38cd1d7e8860d6ea, 0x3c2cd07eb7a4b74f), + (0xb85adedac22a5607, 0xbbbb21f2d5c76559), + (0xb8403dbefd803008, 0xbba174fb8123d957), + (0xb7decb7c15886751, 0x3b305ef4d5737c95), + (0xb78dcfe2c3d73d6b, 0x3b118c574d742d02), + (0x3746542ad0f810ba, 0xbaa0621051dc9615), + (0x371434d10d672431, 0xba7dbd00a70ea7c3), + (0x36a3d2f4625f489c, 0x3a0ba13931894290), + (0x367d34b5778ce244, 0x39e586f4fb44eb1c), + ], + [ + (0x3c5827414357db53, 0xbfb8b5ccb03d459b), + (0x0000000000000000, 0x0000000000000000), + (0xbc4827414357db53, 0x3fa8b5ccb03d459b), + (0x3bc829bf4eaf884d, 0xbf2edc98b92fedf3), + (0x3c0a89c9aabf2841, 0xbf70767d524cea88), + (0xbb9b6aea43cf7c69, 0x3ef8a85a847c89c3), + (0x3b9126e1254c1c3f, 0x3f2189afaa2bffcc), + (0xbb239c5c72e2b643, 0xbeac1d231a69bb02), + (0x3b6e89e6ffd32981, 0xbec40139bdbc9d36), + (0xbac65998040abd88, 0x3e509a6859c8e374), + (0x3aded4461012c62e, 0x3e5c60fc5f9b505f), + (0xba80f4ba127543b5, 0xbde80ad391f7224c), + (0xba8175d6b9c314bd, 0xbdeb6e954dd6c922), + (0xba13a59996f17ca1, 0x3d778adc76ca1d1b), + (0x39e11be5ff01d8f8, 0x3d733867c824f37c), + (0xb99156aaeb019d3d, 0xbd00a1ec5f4dca90), + (0xb98d52e6f6ab31a5, 0xbcf469ac872b68fd), + (0xb92873e76419e2d3, 0x3c81c1b6937f11e6), + (0x38ccce25f4bbd867, 0x3c70fe687033cfb9), + (0x3891a388623b4d18, 0xbbfda774598ea00a), + (0xb869e8b9411b1044, 0xbbe6c5c790ba8cb1), + (0x38166a66767c0cb3, 0x3b73e54f8ca945a2), + (0xb7f10320398ad824, 0x3b5916586436314c), + (0x37824e29afdee9e2, 0xbae5eb34af321144), + (0x376cca34b6192949, 0xbac71eb7d8b137e6), + (0xb6e44bfb5b2e06d0, 0x3a542dd9e755ef71), + (0x36d5af611735126d, 0x3a321616f456ec2b), + (0xb6303bf3b5725f15, 0xb9bf82bf12709cef), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c116404635b6173, 0x3fb86e51bb2ee24d), + (0x3be40f7dbe05e2df, 0xbf465e3bad214eb8), + (0xbc3502bddec37518, 0xbf9047d6ed159c31), + (0xbbb68a41509d990f, 0x3f1dce4a381ce24e), + (0x3be0a2f7a61834bb, 0x3f4a05b93842da9a), + (0x3b384a0ade44f859, 0xbed7ce3df60b0ea1), + (0x3b8858267c36b09d, 0xbef3cb50138cce4b), + (0x3b2cb60fbd510cee, 0x3e8216e84a5dec74), + (0x3b2d7337b289cb04, 0x3e918e354c01533b), + (0xbac53c3104a34351, 0xbe2005493039e5f0), + (0x3ac1ef2cc08d8fcc, 0xbe245ed4a3733e9d), + (0xba3577c4c664c7a0, 0x3db28e2ed388f175), + (0xba513618783b7d45, 0x3db0a83fb8aae5cc), + (0x39d2152affe981ca, 0xbd3e4745b1e410b2), + (0xb9cc35474710f93a, 0xbd3439aae872dae3), + (0xb90f376af336ee4d, 0x3cc2557a9d9a51a0), + (0xb9418e01d92d0d8b, 0x3cb2f313647cb524), + (0xb8ee555d5c581be4, 0xbc4120389f39a9c9), + (0x38bceac00481a0f5, 0xbc2c39cb315eebe0), + (0x38543f94ec753f1e, 0x3bb96c5a77539703), + (0xb7f664a9d463aaf9, 0x3ba11bdcff0ddb62), + (0xb7909879d65e235f, 0xbb2eb47c0f406536), + (0x37b323a3eb4616f4, 0xbb1135192cf31d4c), + (0x36df969385034399, 0x3a9ec17139b4fa1e), + (0xb712728ddaed35bd, 0x3a7d2d581a06903c), + (0xb68322eeb5683b7f, 0xba09f599e9b3fcee), + (0xb6584681390e9457, 0xb9e522216f24e570), + ], + [ + (0xbc5aa58d824fcbf0, 0x3fb829356c2fb67c), + (0x0000000000000000, 0x0000000000000000), + (0x3c4aa58d824fcbf0, 0xbfa829356c2fb67c), + (0x3bc03ee1c336b408, 0x3f2cd964e5e4caa0), + (0x3c0adae94b604802, 0x3f70190ce66b97c3), + (0xbb6093ba87cf3d05, 0xbef70d5fd8bad7b5), + (0xbbae25e1759c428e, 0xbf2126a150469b05), + (0x3b4f93e54fe01a02, 0x3eaa49ea85815004), + (0xbb4a798f784213ff, 0x3ec3910f5c159f54), + (0x3ab455b6aeed4cdd, 0xbe4f0f4bdbe20c90), + (0xbaf74c179ce6757b, 0xbe5bc3697829b270), + (0x3a883549e84165fc, 0x3de67f2959cd47c2), + (0x3a6dc709a66c6637, 0x3dead81c085abf1e), + (0xb9f0a2a8eed90e0b, 0xbd760a10ab0898ac), + (0x3a0d4bed5455a7cd, 0xbd72d07fd9984920), + (0x399e8c3991730925, 0x3cff2887ab34ba4b), + (0xb99d15049de98d82, 0x3cf3fd2c46f43bfa), + (0x3918217b1630091e, 0xbc80a48214b2d81b), + (0xb90aebeb32b2ec56, 0xbc70a5cd24e7aff5), + (0x387f8e2a60b26930, 0x3bfbd0274fe43cf0), + (0xb87decdf6830646f, 0x3be65191993b3def), + (0xb8169726f5849485, 0xbb72acc84c6c9c30), + (0xb7ecea63d3d7881a, 0xbb5899530e0f85dd), + (0x3783523fe1e47394, 0x3ae4974878ee147d), + (0xb75b7329483fca7c, 0x3ac6ae722e577e49), + (0x36f5f5ad175e3a10, 0xba52f937d6c2c894), + (0x36da45ec2b162935, 0xba31c0af96ec39d1), + (0xb63b5886d2aae802, 0x39bda7e9893ee0e5), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc4ea89f3a43207f, 0xbfb7e656ed57a0d1), + (0x3bed3586339aa922, 0x3f44f0cfc62eb61c), + (0x3c1736dd17549bef, 0x3f8fdaba63e9c655), + (0x3bb8a2f82c46d7d1, 0xbf1be7bad1c50547), + (0x3be9f603d64ca819, 0xbf4975ac0770c98d), + (0xbb716dcdea217bd7, 0x3ed64a6af83ba860), + (0x3b95937b8720b7f0, 0x3ef35e6b41b6d77b), + (0x3b1fd0d91a2328f8, 0xbe80f12d050df219), + (0x3b0b801799b9887e, 0xbe912e744222ec5c), + (0x3a882bc4f09a4762, 0x3e1e04a8c0a89be6), + (0x3ab7f6d6a00158e7, 0x3e23f0ed5e6a0d3b), + (0x3a40220f85fad9d6, 0xbdb163fd7157593b), + (0x3a410e6d9a99af97, 0xbdb04f8efe519654), + (0xb9d5f5b1b377833f, 0x3d3c6417f7a11d41), + (0xb9df5b1599ff1601, 0x3d33cfa2affaf9e4), + (0xb953811266af2ff0, 0xbcc1334e857adc93), + (0xb95d7d93dd11d118, 0xbcb2917ae18b1995), + (0x38e71d9f8e4fabac, 0x3c4013b4389ffe8d), + (0x38b8b37790d4d1d0, 0x3c2bab4c1141eb75), + (0x3858ea4627e8efee, 0xbbb7e1ea8188735c), + (0x381cd9d4b13e954d, 0xbba0c761c695703d), + (0xb7c2ccb36474c65d, 0x3b2cdd9ab5adf543), + (0xb7ad59a9bff1b6e1, 0x3b10e22b0412a059), + (0x37298e06ba0a7eff, 0xba9cefb8354e799e), + (0x371ce2c8c6a65fa1, 0xba7ca4621c89c3ea), + (0x369bfbcde055522b, 0x3a0871d638e71562), + (0x36702a74cab2e18d, 0x39e4c1b3f6f3c4fc), + ], + [ + (0xbc52d2ff041ff2f6, 0xbfb7a597eb76a5e3), + (0x0000000000000000, 0x0000000000000000), + (0x3c42d2ff041ff2f6, 0x3fa7a597eb76a5e3), + (0x3bb9dc564feff08d, 0xbf2b0bd9eb615315), + (0xbc03cbe9e9bac1ac, 0xbf6f831b9629acd2), + (0xbb95cc1ecba38a9d, 0x3ef59d1c40c95ba7), + (0x3bad7b9ad1a36974, 0x3f20c9d35d4be191), + (0xbb39533f46784cb0, 0xbea8a711bec6920b), + (0xbb4180f2a561ac4b, 0xbec327e42f39066e), + (0x3adb23dbc633fe86, 0x3e4d225aa8ded6cd), + (0xbaea1e7c5d2c24a0, 0x3e5b2f83a946aed5), + (0x3a72070bf439257d, 0xbde51bef06eb5d9f), + (0xba7f45169aef013e, 0xbdea4ab19859cce7), + (0xba0912db1823cb9f, 0x3d74b03ce339d83a), + (0x3a007d1a27a09f97, 0x3d726eb2bbaa63c7), + (0xb991c095fa32b480, 0xbcfd433d6a1a8fc3), + (0x3988ca74e8a71011, 0xbcf396dd9428b7d8), + (0xb91f2420c8969cf6, 0x3c7f470853f5d87d), + (0x39129d5b5b244d63, 0x3c705215ddbe7188), + (0xb89ad8ca1c6e4ad7, 0xbbfa26d052836024), + (0xb86057f50da94b85, 0xbbe5e38754f9398d), + (0x381cce919f096c57, 0x3b71923ffdac92d4), + (0x37f2bbe0806d82ac, 0x3b5822a7b984366d), + (0x377a0e974a7e67bc, 0xbae3636b0de0af87), + (0x376c2d3712cd37ea, 0xbac6439959854a9a), + (0xb6f5653a15338763, 0x3a51e12428cdc675), + (0x36bd7966e734f9d4, 0x3a316f2e8a6d63cb), + (0xb64936e1f9cb0f09, 0xb9bbf81db6228424), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,341 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::{j0f_asympt_alpha, j0f_asympt_beta, j1f_rsqrt}; +use crate::bessel::trigo_bessel::sin_small; +use crate::bessel::y0f_coeffs::{Y0_ZEROS, Y0_ZEROS_VALUES, Y0F_COEFFS}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::fast_logf; +use crate::polyeval::{f_polyeval10, f_polyeval18}; +use crate::rounding::CpuCeil; +use crate::sincos_reduce::rem2pif_any; + +/// Bessel of the second kind of order 0 (Y0) +/// +/// Max ULP 0.5 +pub fn f_y0f(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + return f32::NEG_INFINITY; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f32::NAN; + } + return 0.; + } + + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x4296999au32 { + // x <= 75.3 + if xb <= 0x40000000u32 { + // x <= 2 + if xb <= 0x3faccccdu32 { + // x <= 1.35 + return y0f_near_zero(f32::from_bits(xb)); + } + // transient zone from 1.35 to 2 have bad behavior for log poly already, + // and not yet good to be easily covered, thus it use its own poly + return y0_transient_area(x); + } + + return y0f_small_argument_path(f32::from_bits(xb)); + } + + // Exceptions: + let xb = x.to_bits(); + if xb == 0x5023e87f { + return f32::from_bits(0x28085b2d); + } else if xb == 0x48171521 { + return f32::from_bits(0x2bd244ba); + } else if xb == 0x4398c299 { + return f32::from_bits(0x32c730db); + } else if xb == 0x7f0e5a38 { + return f32::from_bits(0x131f680b); + } else if xb == 0x6ef9be45 { + return f32::from_bits(0x987d8a8f); + } + + y0f_asympt(x) +} + +/** +Generated by SageMath: +Evaluates: +Y0(x) = 2/pi*(euler_gamma + log(x/2))*J0(x) - sum((-1)^m*(x/2)^(2*m)/(m!)^2*sum(1+1/2 + ... 1/m)) +expressed as: +Y0(x)=log(x)*W0(x) - Z0(x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() +N = 10 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() + +# Define J0(x) Taylor expansion at x = 0 +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J0_series = j_series(0, x) + +def z_series(x): + return sum([(-1)**m * (x/2)**(ZZ(2)*ZZ(m)) / ZZ(m).factorial()**ZZ(2) * sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) for m in range(1, N)]) + +W0 = (d2/pi) * J0_series +Z0 = -gamma * (d2/pi) * J0_series + RealField(300)(2).log() * (d2/pi) * J0_series + (d2/pi) * z_series(x) + +# see the series +print(W0) +print(Z0) +``` +**/ +#[inline] +fn y0f_near_zero(x: f32) -> f32 { + const W: [u64; 10] = [ + 0x3fe45f306dc9c883, + 0xbfc45f306dc9c883, + 0x3f845f306dc9c883, + 0xbf321bb945252402, + 0x3ed21bb945252402, + 0xbe672db9f21b0f5f, + 0x3df49a6c656d62ff, + 0xbd7ae90af76a4d0f, + 0x3cfae90af76a4d0f, + 0xbc754331c053fdad, + ]; + let dx = x as f64; + let x2 = dx * dx; + let w0 = f_polyeval10( + x2, + f64::from_bits(W[0]), + f64::from_bits(W[1]), + f64::from_bits(W[2]), + f64::from_bits(W[3]), + f64::from_bits(W[4]), + f64::from_bits(W[5]), + f64::from_bits(W[6]), + f64::from_bits(W[7]), + f64::from_bits(W[8]), + f64::from_bits(W[9]), + ); + const Z: [u64; 10] = [ + 0x3fb2e4d699cbd01f, + 0xbfc6bbcb41034286, + 0x3f9075b1bbf41364, + 0xbf41a6206b7b973d, + 0x3ee3e99794203bbd, + 0xbe7bce4a600d3ea4, + 0x3e0a6ee796b871b6, + 0xbd92393d82c6b2e4, + 0x3d131085da82054c, + 0xbc8f4ed4b492ebcc, + ]; + let z0 = f_polyeval10( + x2, + f64::from_bits(Z[0]), + f64::from_bits(Z[1]), + f64::from_bits(Z[2]), + f64::from_bits(Z[3]), + f64::from_bits(Z[4]), + f64::from_bits(Z[5]), + f64::from_bits(Z[6]), + f64::from_bits(Z[7]), + f64::from_bits(Z[8]), + f64::from_bits(Z[9]), + ); + let w_log = fast_logf(x); + f_fmla(w0, w_log, -z0) as f32 +} + +#[inline] +fn y0_transient_area(x: f32) -> f32 { + let dx = x as f64; + // first Y0 bessel zero + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + let r = (dx - ZERO.hi) - ZERO.lo; + /* + Poly generated by Wolfram Matematica: + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + */ + let p = f_polyeval18( + r, + f64::from_bits(0x3fe0aa48442f8375), + f64::from_bits(0x3de601d3b959b8d8), + f64::from_bits(0xbfd0aa4840bb8529), + f64::from_bits(0x3fa439fc16d4835e), + f64::from_bits(0x3f80d2dcd97d2b4f), + f64::from_bits(0x3f4f833368f9f047), + f64::from_bits(0xbf541a702ee92277), + f64::from_bits(0x3f3abc113cf0f4da), + f64::from_bits(0xbefac1ded6f17ba8), + f64::from_bits(0x3f33ef372e24df82), + f64::from_bits(0x3f3bf8b42322df40), + f64::from_bits(0x3f4582f9daec9ca7), + f64::from_bits(0x3f479fc07175494e), + f64::from_bits(0x3f4477a5e32b723a), + f64::from_bits(0x3f39fbfd6a6d6f0c), + f64::from_bits(0x3f2760a66816527b), + f64::from_bits(0x3f0a68fdeeba224f), + f64::from_bits(0x3edd78c6c87089e1), + ); + p as f32 +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +fn y0f_small_argument_path(x: f32) -> f32 { + let x_abs = x as f64; + + // let avg_step = 74.607799 / 47.0; + // let inv_step = 1.0 / avg_step; + + const INV_STEP: f64 = 0.6299609508652038; + + let fx = x_abs * INV_STEP; + const Y0_ZEROS_COUNT: f64 = (Y0_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(Y0_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(Y0_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(Y0_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(Y0_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + // Really should not happen here, but if it is then to log expansion + return y0f_near_zero(x); + } + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(Y0_ZEROS_VALUES[idx]) as f32; + } + + let c = &Y0F_COEFFS[idx - 1]; + + let r = (x_abs - found_zero.hi) - found_zero.lo; + + let p = f_polyeval18( + r, + f64::from_bits(c[0]), + f64::from_bits(c[1]), + f64::from_bits(c[2]), + f64::from_bits(c[3]), + f64::from_bits(c[4]), + f64::from_bits(c[5]), + f64::from_bits(c[6]), + f64::from_bits(c[7]), + f64::from_bits(c[8]), + f64::from_bits(c[9]), + f64::from_bits(c[10]), + f64::from_bits(c[11]), + f64::from_bits(c[12]), + f64::from_bits(c[13]), + f64::from_bits(c[14]), + f64::from_bits(c[15]), + f64::from_bits(c[16]), + f64::from_bits(c[17]), + ); + + p as f32 +} + +/* + Evaluates: + Y0 = sqrt(2/(PI*x)) * beta(x) * sin(x - PI/4 - alpha(x)) +*/ +#[inline] +fn y0f_asympt(x: f32) -> f32 { + let dx = x as f64; + + let alpha = j0f_asympt_alpha(dx); + let beta = j0f_asympt_beta(dx); + + let angle = rem2pif_any(x); + + const SQRT_2_OVER_PI: f64 = f64::from_bits(0x3fe9884533d43651); + const MPI_OVER_4: f64 = f64::from_bits(0xbfe921fb54442d18); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_cos = sin_small(r0); + + let z0 = beta * m_cos; + let scale = SQRT_2_OVER_PI * j1f_rsqrt(dx); + + (scale * z0) as f32 +} + +#[cfg(test)] +mod tests { + use crate::f_y0f; + + #[test] + fn test_y0f() { + assert_eq!(f_y0f(90.5), 0.08254846); + assert_eq!(f_y0f(77.5), 0.087678276); + assert_eq!(f_y0f(1.5), 0.3824489); + assert_eq!(f_y0f(0.5), -0.44451874); + assert!(f_y0f(-1.).is_nan()); + assert_eq!(f_y0f(0.), f32::NEG_INFINITY); + assert_eq!(f_y0f(-0.), f32::NEG_INFINITY); + assert_eq!(f_y0f(f32::INFINITY), 0.); + assert!(f_y0f(f32::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0f_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y0f_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y0f_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1236 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Y0 zeros and extremums. +Generated by SageMath: +```python +R120 = RealField(120) + +zeros = [] + +mp.prec = 150 + +step = mpf("0.1") +epsilon = mpf("1e-35") +x = mpf("1.25") + +previous_zero = R120(0) +y0_zeros = [] + +while x < mpf("76.0"): + f1 = bessely(0, x) + f2 = bessely(0, x + step) + if f1 * f2 < 0: + zero = findroot(lambda t: bessely(0, t), (x, x + step), solver='secant', tol=mp.mpf("1e-41")) + previous_zero = zero + y0_zeros.append(zero) + if previous_zero is not None and abs(x - mpf(f'{round(x)}')) < epsilon: + zeros.append(previous_zero) + x += step + +y0_extrema = [] + +x = mpf("1.25") +while x < mpf("76.0"): + d1 = mp.diff(lambda t: bessely(0, t), x) + d2 = mp.diff(lambda t: bessely(0, t), x + step) + if d1 * d2 < 0: + extremum = findroot(lambda t: mp.diff(lambda u: bessely(0, u), t), (x, x + step), solver='secant', tol=mp.mpf("1e-41")) + y0_extrema.append(extremum) + x += step + +# Print results +for i, z in enumerate(j0_zeros): + print(f"Zero {i+1}: x ≈ {z}") + +print("Extrema (peaks/valleys) of Y0(x):") +for e in y0_extrema: + print(f"nExtrema: {e}") + +y0_zeros.extend(y0_extrema) + +y0_zeros = sorted(y0_zeros) + +# Print results +for i, z in enumerate(y0_zeros): + print(f"Peak or zero {i+1}: x ≈ {z}") + +print("") + +print("pub(crate) static Y0_ZEROS: [(u64, u64); 48] = [") +print(f"(0x0, 0x0),") +for z in y0_zeros: + k = split_double_double(z) + hi = double_to_hex(k[1]) + lo = double_to_hex(k[0]) + print(f"({lo}, {hi}),") + +print("];") +``` +**/ +pub(crate) static Y0_ZEROS: [(u64, u64); 48] = [ + (0x0, 0x0), // not really used, just a stab to avoid messing with indices + (0xbc8bd1e50d219bfd, 0x400193bed4dff243), + (0xbc9f06ae7804384e, 0x400fa9534d98569c), + (0x3cbdfe7bac228e8c, 0x4015b7fe4e87b02e), + (0xbc99774a495f56cf, 0x401c581dc4e72103), + (0x3cb479cc068d9046, 0x40213127ae6169b4), + (0xbcccb49ff791c495, 0x402471d735a47d58), + (0x3c80fc786ce06080, 0x40277f9138d43206), + (0xbcc7df81de86f24d, 0x402ab8e1c4a1e74a), + (0xbcc5e091a50f8e05, 0x402dcb7d88de848b), + (0x3cd25a237d12159b, 0x4030803c74003214), + (0xbcda1ee4c5487ede, 0x40320b1c695f1e3b), + (0xbcd8bf92d51fbaeb, 0x4033a42cdf5febd7), + (0x3cd391b14410528f, 0x40353025492188cd), + (0x3cdca75080cf53a8, 0x4036c832fd77ac07), + (0x3cb52f75f025b205, 0x403854fa303820ca), + (0xbcb03e052bd9c0af, 0x4039ec46f3e80146), + (0xbcbcf130fbea3b24, 0x403b79acee8cfb7d), + (0x3cd0aab17eca74b9, 0x403d106449616c4f), + (0xbc9e7a77047d6166, 0x403e9e480605283c), + (0x3ced2f18aa8a8f2f, 0x40401a4420e4abee), + (0xbce96beabef7ecf4, 0x4040e16907f8fb56), + (0xbca9dd1578036d11, 0x4041ac588c944279), + (0x3cd2481e87adfe57, 0x404273a7b35a7aff), + (0xbce9c3dd43e59158, 0x40433e6ecf5cb221), + (0x3cda8ffacaac8461, 0x404405e18393afb5), + (0xbce753b7fcd5250c, 0x4044d0867ec213f3), + (0x3cbfe463face2c1c, 0x4045981787d668db), + (0x3cec2eb6ee3e4c70, 0x4046629f4e1e0321), + (0xbce26390f25f01cb, 0x40472a4a85cc317e), + (0xbcaafdee84ced526, 0x4047f4b904dc9a53), + (0xbcdcc667e557a177, 0x4048bc7b10ed3960), + (0x3cebbca9a96dc1aa, 0x404986d378522b70), + (0x3cb377717d2f36f7, 0x404a4ea9997b5eaa), + (0xbcedf185c89a4066, 0x404b18ee87b4e700), + (0xbcc68a841a2af000, 0x404be0d6766d13de), + (0x3ced8a878e90eda4, 0x404cab0a1968b221), + (0x3cddcc8dd083c434, 0x404d7301ec2bf16e), + (0xbceb5c58b22794af, 0x404e3d2619226875), + (0xbce5919b54336657, 0x404f052c3146d1da), + (0xbc87b54cc765fd11, 0x404fcf4276983013), + (0xbcf389f975d9dfa2, 0x40504baab8e42f8f), + (0xbce195534d06b08a, 0x4050b0af92483bf5), + (0xbcd4e0ffa0b9d2e9, 0x405114bee8d0f4bd), + (0xbcf1c076cb371565, 0x405179be0c18f0e1), + (0x3cf5d0de43102daa, 0x4051ddd2b7398636), + (0xbce8a4f19e47d0be, 0x405242cca44048f8), + (0x3ceb379dbe48b8f5, 0x4052a6e6306f1d08), +]; + +/** +Zeros and extremums solved values for Y0 + +Generated by MPFR: +```text +let mut arr = vec![]; +for zeros in Y0_ZEROS.iter() { + if zeros.1 == 0 { + arr.push(0); + } else { + let mpfr = Float::with_val(107, f64::from_bits(zeros.1)).y0(); + arr.push(mpfr.to_f64().to_bits()); + } +} +println!( + "arr: [{}]", + arr.iter() + .map(|x| format!("0x{:016x}", x)) + .collect::>() + .join(", ") +); +``` +**/ +pub(crate) static Y0_ZEROS_VALUES: [u64; 48] = [ + 0x0000000000000000, + 0x3fe0aa48442f014b, + 0xbc88fa8956b4b481, + 0xbfd5c7c556f0c19a, + 0x3c7e91b198d39ce2, + 0x3fd15f993fceab5c, + 0xbcacabd7c823bf21, + 0xbfcdc14ea14e89f9, + 0x3ca4d9fe48a91cef, + 0x3fca7022be084d99, + 0x3cacd827f6c074a2, + 0xbfc80781c32422e7, + 0x3cb1d336c8b0a153, + 0x3fc62d94d97e859c, + 0x3cb3296749aaf800, + 0xbfc4b2a38f1ab9b4, + 0x3c845d52c7c075b2, + 0x3fc37aaceac987b9, + 0x3ca3bc249963d4c1, + 0xbfc2740819f1caaa, + 0xbcc069eacea8ff0b, + 0x3fc192f2627a74e3, + 0xbc7bc4fd81e2b2c5, + 0xbfc0cf3ee98f769b, + 0x3cba82b3a8997d82, + 0x3fc0230ba90f2871, + 0xbcb71414f52d813b, + 0xbfbf13fb0c0e6fcd, + 0xbcbae2d399eafcc6, + 0x3fbe018dac1c17e3, + 0xbc78e44442565953, + 0xbfbd09b21e36c0bd, + 0xbcb8c779e4075b10, + 0x3fbc2861347b1b39, + 0xbcb9f6a4816aab2e, + 0xbfbb5a622198a72c, + 0xbcb8e727b71a083d, + 0x3fba9d183bc04545, + 0xbcb67533047d83fb, + 0xbfb9ee5eee1a97c6, + 0x3c52f9257b962770, + 0x3fb94c6f5898708b, + 0xbcab7916830bd3b8, + 0xbfb8b5ccb03d459b, + 0x3cbb1b180f8e9062, + 0x3fb829356c2fb67c, + 0xbcb267f22477b55d, + 0xbfb7a597eb76a5e3, +]; + +/** +Taylor series at different zeros and extremums for Y0 +Generated by SageMath: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = 2 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(y0_zeros) +print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 500; +bessel_y0 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_y0(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RR(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +degree = 17 + +print(f"pub(crate) static Y0F_COEFFS: [[u64;{degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print("[") + for c in coeffs: + print(double_to_hex(c) + ",") + print("],") +print("];") +``` +**/ +pub(crate) static Y0F_COEFFS: [[u64; 18]; 47] = [ + [ + 0x3fe0aa48442f014b, + 0xbc009e915c2e5f95, + 0xbfd0aa48442f0143, + 0x3fa439fac165257c, + 0x3f80d2af4e929791, + 0x3f4f71646c0dc646, + 0xbf5444bda7f2ee4c, + 0x3f384c21f1d0de42, + 0xbf217ab4d69ab0db, + 0x3f0dafc989c8ea40, + 0xbef8bbefbac0d893, + 0x3ee48ac7a622784f, + 0xbed1245593770ad0, + 0x3ebc28878607b687, + 0xbea585c089718cc9, + 0x3e8b7ad75bd333d8, + 0xbe68a20d8d3d57a5, + 0x3e362c70b36d12a4, + ], + [ + 0x3bf75cf88f1b7237, + 0xbfd9c34256a12a0c, + 0x3faa09c9290367ec, + 0x3fadf6d59bf50e4b, + 0xbf7c116fdc597e2f, + 0xbf61e32bc4eef0b0, + 0x3f29982765136b27, + 0x3f0ab2c1fd5871c0, + 0xbed486371d6e71eb, + 0xbe93b212b9208b3e, + 0xbe577700c20e01fd, + 0x3e545234fb052f6a, + 0xbe2f6a5f736d8c82, + 0x3e0a8134a3ddd47f, + 0xbde9666a74f1504a, + 0x3dc63b75b90c0da3, + 0xbdaa991122c61028, + 0x3d930f1a31e30006, + ], + [ + 0xbfd5c7c556f0c19a, + 0xbbc44b457ab6a440, + 0x3fc5c7c556f0c19a, + 0xbf8564d4b1ed0d7e, + 0xbf8a15d92dfe3e28, + 0x3f4b438430469f6e, + 0x3f37a8924cc2fcab, + 0xbef5f69b4a89930d, + 0xbed85b940ebd0c07, + 0x3e955ac0f4e7f8ab, + 0x3e6d563e284b0072, + 0xbe23eac267e6cf3c, + 0xbe00077161c32b55, + 0x3dc04d965b688847, + 0xbd45e4f4886f7d51, + 0x3d5501605dba787a, + 0xbd363e6119f047ec, + 0x3d096861e7e8004b, + ], + [ + 0xbb236a0ad5bec7c3, + 0x3fd334cca0697a5b, + 0xbf95aef611fc4d57, + 0xbfa8969c64cbf452, + 0x3f6b2f14a95527cb, + 0x3f61d35e85fde2a4, + 0xbf226dd71e391c65, + 0xbf08177e4fe524db, + 0x3ec6a9227352b13b, + 0x3ea34aa757412911, + 0xbe60a2814d2e238a, + 0xbe3442a3d67717ae, + 0x3defa6c448c9759c, + 0x3dbf14eacd6e3a21, + 0xbd771434b676ae83, + 0xbd406a106470261f, + 0x3cf2c5324aed291b, + 0x3cc47f208256e17f, + ], + [ + 0x3fd15f993fceab5c, + 0xbb597aaa5d4472ea, + 0xbfc15f993fceab5c, + 0x3f758ef6efbed797, + 0x3f86395dfe49fcd4, + 0xbf3fb15104a41c03, + 0xbf35f88a11d55641, + 0x3eef37d226a827fd, + 0x3ed6f7bab104d878, + 0xbe8f0c45a3868f32, + 0xbe6dfe11ded99f62, + 0x3e2311adc6046d1a, + 0x3dfad34dd085ee0f, + 0xbdafdc85833041dc, + 0xbd819463fb6a5c22, + 0x3d33a4c369438250, + 0x3d014560b8776112, + 0xbcb2ae15d3a41e47, + ], + [ + 0x3b12ba7db6ce5807, + 0xbfcff635cc72b9f1, + 0x3f89036451ff57c5, + 0x3fa4e667a71556af, + 0xbf60325ee41e910c, + 0xbf5fe23914fb9128, + 0x3f17f84d7c50e49e, + 0x3f06afdd57be1e75, + 0xbec04053abf415e2, + 0xbea2aea9ec4954d7, + 0x3e593eb9f19579b5, + 0x3e3428a3a4917f21, + 0xbde99d8be9e4cd5a, + 0xbdbec9815ee61f19, + 0x3d7260f619cb637c, + 0x3d418f963ce687db, + 0xbcf38a6e7195daa0, + 0xbcbf332d386dfb1b, + ], + [ + 0xbfcdc14ea14e89f9, + 0x3b52ef4e10970973, + 0x3fbdc14ea14e89f9, + 0xbf6b037fe9cf2a52, + 0xbf8367d7d608e4ba, + 0x3f34abef5636e4f9, + 0x3f33d8a66122924a, + 0xbee5cfe92a1a2ead, + 0xbed571814a1a8669, + 0x3e87414e33ccd6d7, + 0x3e6ca7069e37c5b4, + 0xbe1e0b3a74e3f35e, + 0xbdfa15dd188a976e, + 0x3daa33983e3b34b5, + 0x3d8141656fbf9e02, + 0xbd3089bd5153b08a, + 0xbd01345e91fc8d5c, + 0x3cb05566655c2807, + ], + [ + 0xbb10bed1f7905ee9, + 0x3fcbf32a27594007, + 0xbf80bc2d84e65214, + 0xbfa26cab38a8b368, + 0x3f55f03e47165d72, + 0x3f5caaa76e34992d, + 0xbf10c5f18c46d00f, + 0xbf04f0af7d46cd82, + 0x3eb7d1e28094a46b, + 0x3ea1ad073122cd33, + 0xbe536021c88affe4, + 0xbe3371ae6cd96849, + 0x3de46ce028e7c109, + 0x3dbe235dc856ef66, + 0xbd6e401d592ca47a, + 0xbd415f37788a98a4, + 0x3cf078a1b34fa822, + 0x3cbefbc3ca8cda9f, + ], + [ + 0x3fca7022be084d99, + 0xbb4ddca3665cb95a, + 0xbfba7022be084d99, + 0x3f62ee079d020b12, + 0x3f8163191c30aa62, + 0xbf2d7806ea72fc7a, + 0xbf320f95702b1d3e, + 0x3ee006108822968d, + 0x3ed3e398cbc455aa, + 0xbe81bbe181c8bfbe, + 0xbe6b0f89b78908bf, + 0x3e17c3f85c062f0a, + 0x3df902361639d835, + 0xbda56494e7b59641, + 0xbd80bde23236fbba, + 0x3d2bbbd3bb25cf30, + 0x3d00d7f96ac5af92, + 0xbcabe3861f527a48, + ], + [ + 0x3b0d39acdbc38af2, + 0xbfc925c35988ee29, + 0x3f7862549367591e, + 0x3fa0a4512039d6a2, + 0xbf5013b38cfb9292, + 0xbf5a24a1215f6684, + 0x3f08f91421377f72, + 0x3f035d17cec01753, + 0xbeb2283a93110ac0, + 0xbea099e713932038, + 0x3e4e5de01dbe7d10, + 0x3e3288585522eec4, + 0xbde0730be51a22c7, + 0xbdbd174416e1daeb, + 0x3d68f810d9b70d7c, + 0x3d40f177553ea68b, + 0xbcebc58c79d9f1a6, + 0xbcbe6305e9d630f0, + ], + [ + 0xbfc80781c32422e7, + 0x3b483f69e003254a, + 0x3fb80781c32422e7, + 0xbf5c6923374d561f, + 0xbf7fbe6df840847f, + 0x3f264f4711a85f1d, + 0x3f309ff42b0d7a58, + 0xbed8a60685a59ae7, + 0xbed282d26a74a669, + 0x3e7bdb57a88d9298, + 0x3e697d9c12695952, + 0xbe131aa86bece7b9, + 0xbdf7d486a4891297, + 0x3da197f4a31bb9d7, + 0x3d801da2d1e74508, + 0xbd2749f32e6b29e4, + 0xbd005a3044bf379a, + 0x3ca7cdb1346a2761, + ], + [ + 0xbb095b0f9cce8be6, + 0x3fc70c4f66cab47f, + 0xbf72c6731071e936, + 0xbf9e924b85a17361, + 0x3f48d6c364d92082, + 0x3f58247b02d6b0f6, + 0xbf037612593855eb, + 0xbf0206da232a2b7e, + 0x3eacaf84db86b79e, + 0x3e9f367117733794, + 0xbe48654affaeff8a, + 0xbe3199ec88cf0125, + 0x3ddaeb1a0e170f3e, + 0x3dbbe67c38767c0a, + 0xbd64cda59f058a2d, + 0xbd406490f1401c35, + 0x3ce7873ddbd2ecb8, + 0x3cbd9254c745332c, + ], + [ + 0x3fc62d94d97e859c, + 0xbb4423d84fd9daf1, + 0xbfb62d94d97e859c, + 0x3f565481b55eaefb, + 0x3f7d5f857a2a6107, + 0xbf21a015a2ccb791, + 0xbf2eeb4eafd8612c, + 0x3ed3a7b79e4d8384, + 0x3ed154ed4598b648, + 0xbe767f762ea5d48d, + 0xbe680ec1e0075865, + 0x3e0f52965769de53, + 0x3df6ad7b894b88a3, + 0xbd9d4e5bf81e66fd, + 0xbd7eeb07104d446e, + 0x3d23b37b411dc13d, + 0x3cff991c92fdc4d8, + 0xbca4681dcbe602f7, + ], + [ + 0x3b0608e1eb7299ca, + 0xbfc5664d37c37d7b, + 0x3f6e0ee8ec84659a, + 0x3f9c6c415c971b4b, + 0xbf43ec49cb941f55, + 0xbf56853b2d047885, + 0x3eff632a9396fcf6, + 0x3f00e6afa01af56c, + 0xbea7541247ac8e20, + 0xbe9d735e8beba89d, + 0x3e440e6a7c5b76f7, + 0x3e30b9cfae36d52a, + 0xbdd66808178f0472, + 0xbdbab498e9ad024c, + 0x3d618b0d40031fb2, + 0x3d3f99bd1527877f, + 0xbce4186fe1076e16, + 0xbcbca6e4a9f85609, + ], + [ + 0xbfc4b2a38f1ab9b4, + 0x3b4106370f2ef866, + 0x3fb4b2a38f1ab9b4, + 0xbf5225a5c73f2233, + 0xbf7b750d89a9b35f, + 0x3f1cbdb4f1d5dbc0, + 0x3f2cfe933fc6d09a, + 0xbed01ef10d839ddf, + 0xbed05375a5888b31, + 0x3e729afe7eaa78e7, + 0x3e66c8fe01244a3c, + 0xbe0a2a01eba23e6a, + 0xbdf59b32be188f85, + 0x3d98c0a83d3ee202, + 0x3d7da2dd5a1ff0d5, + 0xbd20d5047e87a8a0, + 0xbcfe76ab94a96cf5, + 0x3ca19e4f3f768bb8, + ], + [ + 0xbb033ddc20ef994b, + 0x3fc40f8ffdf09a5f, + 0xbf68c37a29c4586f, + 0xbf9aab099314b209, + 0x3f406f735cc0f6a6, + 0x3f552d29a06802e0, + 0xbef9fc04c675c0a0, + 0xbeffe48825ed3c99, + 0x3ea36bd2d58fad6c, + 0x3e9be87e2cad35c1, + 0xbe40d1fded7d33ea, + 0xbe2fdbeb107f2787, + 0x3dd2f44ca7722117, + 0x3db992136419242c, + 0xbd5df6388aabd242, + 0xbd3e6bd4176ef817, + 0x3ce15380b88a0004, + 0x3cbbb4210e2ade39, + ], + [ + 0x3fc37aaceac987b9, + 0xbb3d355a175fbb67, + 0xbfb37aaceac987b9, + 0x3f4e3fdbfd65014a, + 0x3f79de7a33bc3a97, + 0xbf1801d911fbd06f, + 0xbf2b605a5ade3a62, + 0x3ecb0a2608144de7, + 0x3eceeceb341aa1c8, + 0xbe6f623fc7c35376, + 0xbe65a9ca94685dee, + 0x3e0638ba32c100f7, + 0x3df4a1b3dc97031d, + 0xbd9530c9cb91ec68, + 0xbd7c6deff6c29a1e, + 0x3d1d10f27ed0d91c, + 0x3cfd5b5110a971f2, + 0xbc9eac069b193638, + ], + [ + 0x3b00e83df01ac491, + 0xbfc2f206e49909c7, + 0x3f64dbf6a9fb80d7, + 0x3f99336443318ed1, + 0xbf3bb6aa3d4e9e78, + 0xbf540aaa5d94bd8d, + 0x3ef5f61b66612962, + 0x3efe4158391f2c2d, + 0xbea07a7a0745b8f1, + 0xbe9a8ea97b66fe4d, + 0x3e3cb10b3a7e93b8, + 0x3e2e6d788791546c, + 0xbdd044442a2af39d, + 0xbdb8850c7d8525ad, + 0x3d59e48a6e2fcf83, + 0x3d3d4af5e70dabe3, + 0xbcde2a65241d7e39, + 0xbcbac578a90cdb0d, + ], + [ + 0xbfc2740819f1caaa, + 0x3b395de3b03fa760, + 0x3fb2740819f1caaa, + 0xbf49b6f37d0a00f9, + 0xbf78868d7401bf2e, + 0x3f1470a7cbcb436d, + 0x3f29fe94ce3d3e66, + 0xbec71660e61f123b, + 0xbecd6dfcdb022b53, + 0x3e6ae79c35d4303c, + 0x3e64ac50be35d108, + 0xbe0325840c0fab26, + 0xbdf3c09642eaf47d, + 0x3d925d87f4bac822, + 0x3d7b50337a12ad98, + 0xbd195a5cf071931d, + 0xbcfc4e3bdd8deb9e, + 0x3c9aec36c7cd8057, + ], + [ + 0xbafde3378387cd4f, + 0x3fc1ff5ebddd3c3a, + 0xbf61e2035324643c, + 0xbf97f3506d4a1231, + 0x3f37c65c9302c53a, + 0x3f53117816335151, + 0xbef2df9afa521258, + 0xbefcd5d4a9d78a10, + 0x3e9c672d4d6f090d, + 0x3e995e4b10218b56, + 0xbe38d22635a19a7c, + 0xbe2d24fc943fc6e5, + 0x3dcc462d12216cc2, + 0x3db78eaf8cc86453, + 0xbd569efa1b265a8d, + 0xbd3c3c11b66258b3, + 0x3cda808e4f387067, + 0x3cb9e0f8deb75911, + ], + [ + 0x3fc192f2627a74e3, + 0xbb3645a3987074b0, + 0xbfb192f2627a74e3, + 0x3f4635b38affe698, + 0x3f775eceaabf7f86, + 0xbf11ac9e0164f7c3, + 0xbf28cc464a35b093, + 0x3ec4014d9bf38c8d, + 0x3ecc1f05a2d81e1e, + 0xbe6761d18ebe9900, + 0xbe63cb9af0ceb4cf, + 0x3e00b3cb584e2702, + 0x3df2f5c722e3bf8d, + 0xbd9017792eaec1aa, + 0xbd7a4a02574df6fb, + 0x3d1652dad940d7a4, + 0x3cfb525fce2f20bd, + 0xbc97d2bda2bb98bd, + ], + [ + 0x3afa988afe4c49f9, + 0xbfc12dd55d4be2b3, + 0x3f5f1aee31818d19, + 0x3f96de64242a8310, + 0xbf34afdf89fca61a, + 0xbf5238cfc13ac771, + 0x3ef0719d13e00e1d, + 0x3efb974781a526ac, + 0xbe98cc82a70d12de, + 0xbe9850ae878c16d4, + 0x3e35bba73dc2363a, + 0x3e2bfe1396c7d24f, + 0xbdc8d7db68570364, + 0xbdb6adfbad375234, + 0x3d53f4c573239e3d, + 0x3d3b40924b9cec60, + 0xbcd77b88ddf3cd06, + 0xbcb909671eb81963, + ], + [ + 0xbfc0cf3ee98f769b, + 0x3b33bcff5c943527, + 0x3fb0cf3ee98f769b, + 0xbf436f451f6e14fb, + 0xbf765d05948a946a, + 0x3f0ef55c5a0d16d1, + 0x3f27bfec9d15d01e, + 0xbec18c549f28e7a1, + 0xbecaf7544eea95a1, + 0x3e648e81edf6b6c0, + 0x3e630341e759775f, + 0xbdfd73d2cdd0aab5, + 0xbdf23ec233be72a4, + 0x3d8c78e7f536eeff, + 0x3d795a1608a24a32, + 0xbd13d34748616c7a, + 0xbcfa685ede39fb91, + 0x3c953d75ba0ff04b, + ], + [ + 0xbaf7d336e374344e, + 0x3fc0768257dad56a, + 0xbf5b602a7beaaa48, + 0xbf95ebc22efd092c, + 0x3f3236a604142e61, + 0x3f517a482faa8d85, + 0xbeecfc008907874e, + 0xbefa7d7b128ac52d, + 0x3e95e419f1b51819, + 0x3e97603cea233f99, + 0xbe333a0b43111627, + 0xbe2af464175ecac5, + 0x3dc609ac1d6253eb, + 0x3db5e11b59984046, + 0xbd51c2262e85ed55, + 0xbd3a58213539aed8, + 0x3cd4f80a679b93ee, + 0x3cb83fa375444bd0, + ], + [ + 0x3fc0230ba90f2871, + 0xbb31a4207958473d, + 0xbfb0230ba90f2871, + 0x3f413164a0864cde, + 0x3f7579c1bdbcfc99, + 0xbf0b67e1913c668f, + 0xbf26d26de4fd8c43, + 0x3ebf1b520b063cbf, + 0x3ec9f01e7c18d94a, + 0xbe624071b17c353c, + 0xbe624f8e936aca3d, + 0x3dfa356639a676b4, + 0x3df19911d0412ad5, + 0xbd89677525aa079f, + 0xbd787e875d392b57, + 0x3d11be245f9c21d5, + 0x3cf98faabb17d8d4, + 0xbc93119ed524d1f5, + ], + [ + 0x3af57b2a92bacca4, + 0xbfbfa8b3f9ae4375, + 0x3f5856073b7fa2cd, + 0x3f9514e652eb2e96, + 0xbf3032298718ea1a, + 0xbf50d1153fde431b, + 0x3ee9cb455c29d651, + 0x3ef982167b1c52b5, + 0xbe938191ef689b27, + 0xbe968865345b1bd6, + 0x3e31296000bb210d, + 0x3e2a0403677632fc, + 0xbdc3b67c5c27ec16, + 0xbdb526035aeb726c, + 0x3d4fd977f75a677c, + 0x3d398199969ac0ac, + 0xbcd2db2724a8c540, + 0xbcb7838b8a136198, + ], + [ + 0xbfbf13fb0c0e6fcd, + 0x3b2fb8a657120d32, + 0x3faf13fb0c0e6fcd, + 0xbf3eb3e6fcc47c00, + 0xbf74af74cbd77bef, + 0x3f087bb1ebeaec78, + 0x3f25fe62920314f5, + 0xbebbd0f2a6556264, + 0xbec9040de83035a2, + 0x3e6057f7a76c1f7c, + 0x3e61ad6dd4dfaab9, + 0xbdf782a6f91b13a7, + 0xbdf1027d851ec0eb, + 0x3d86d65e028f8e8e, + 0x3d77b54a61df8d64, + 0xbd0ffa6793d8746b, + 0xbcf8c72862ef4d7d, + 0x3c913a3849824cc1, + ], + [ + 0xbaf37825e4b1711a, + 0x3fbe8727c572a2c2, + 0xbf55d1ef092ab395, + 0xbf9454e7a7395636, + 0x3f2d0cc3a7fa6d3d, + 0x3f50398d2cbd02df, + 0xbee725b0909f9c17, + 0xbef8a022f5fee439, + 0x3e9185b1ea975d21, + 0x3e95c5711673ea6a, + 0xbe2edff650b86504, + 0xbe29298da3993db9, + 0x3dc1c346aaab062e, + 0x3db47ab8b9f6e94a, + 0xbd4cc1c87cd4af9d, + 0xbd38bb86b43ec34d, + 0x3cd1104df3fa9e99, + 0x3cb6d47888429c17, + ], + [ + 0x3fbe018dac1c17e3, + 0xbb2cbf68b5ed7271, + 0xbfae018dac1c17e3, + 0x3f3ba21bd15d02a4, + 0x3f73f9e0db07e7ef, + 0xbf060b77c5e27625, + 0xbf253f9b1a5d2273, + 0x3eb910b38812c5ec, + 0x3ec82ee6dfdfc034, + 0xbe5d7cc2a9aa9fae, + 0xbe611a57d834f490, + 0x3df53d401868b2b6, + 0x3df07915b5d7b1b9, + 0xbd84aabf5e11aa97, + 0xbd76fc66f73ce419, + 0x3d0cff2a096a9861, + 0x3cf80d87c580ea09, + 0xbc8f4ef03ad4ec66, + ], + [ + 0x3af1bbdf10c72747, + 0xbfbd82939ab62339, + 0x3f53b5a54845670f, + 0x3f93a7ff1622def8, + 0xbf2a3ebc476a606d, + 0xbf4f61adde3a8c61, + 0x3ee4ec45da047869, + 0x3ef7d3b28159f22c, + 0xbe8fb3f21bccfc28, + 0xbe95145a876d09d8, + 0x3e2bf64cdef37a7c, + 0x3e2862204a96b8ac, + 0xbdc01c0cf54f6b8d, + 0xbdb3dd6c7e6818d8, + 0x3d4a1faa7e189d99, + 0x3d3804640c4d999d, + 0xbccf0f5eda690a07, + 0xbcb63189b3dc27d0, + ], + [ + 0xbfbd09b21e36c0bd, + 0x3b2a335791a61ca6, + 0x3fad09b21e36c0bd, + 0xbf390b0e6a475e45, + 0xbf7355b904fbf7ee, + 0x3f03fc459d1e25a7, + 0x3f2492cc61d19de6, + 0xbeb6bcf110a02e19, + 0xbec76d44f6a8089e, + 0x3e5ac61efcb7f75f, + 0x3e609436fc7c1966, + 0xbdf34eb60c63b887, + 0xbdeff662240b32ed, + 0x3d82d05e647447d5, + 0x3d76520ffbea05d6, + 0xbd0a70b3d6b77e3f, + 0xbcf7617161d2567e, + 0x3c8c991bfcf38c32, + ], + [ + 0xbaf03b145709e9fb, + 0x3fbc96700031f601, + 0xbf51eb2a07d0f09e, + 0xbf930b36eddaa234, + 0x3f27dd2dde84b73c, + 0x3f4e696553e0b8a5, + 0xbee3085aa35a1606, + 0xbef7199f24bccad0, + 0x3e8cdbab6a75e8e1, + 0x3e9472a7cffbdf8d, + 0xbe2979f5209f2f88, + 0xbe27ab4b017a68c3, + 0x3dbd638fb5c45254, + 0x3db34c83c71aa648, + 0xbd47dc91892a3240, + 0xbd375abc2b119f77, + 0x3ccc6a16f48d942f, + 0x3cb599c2db65d50c, + ], + [ + 0x3fbc2861347b1b39, + 0xbb27f93aa95d7811, + 0xbfac2861347b1b39, + 0x3f36d57bffb37fd5, + 0x3f72c060ef553f18, + 0xbf023a407b722d31, + 0xbf23f55581ec6826, + 0x3eb4bfb4daa30262, + 0x3ec6bc69099ac792, + 0xbe587334098baabf, + 0xbe601951f000356a, + 0x3df1a61752a7a337, + 0x3def0ec9ee45cf6f, + 0xbd8137cd564b9118, + 0xbd75b4aa3b6c601b, + 0x3d083b040a6d9f05, + 0x3cf6c19bd64bc967, + 0xbc8a3eded96f75bf, + ], + [ + 0x3aedd70a3afed493, + 0xbfbbbf246019c0d4, + 0x3f506224199140d8, + 0x3f927c3416c09898, + 0xbf25d279dc87cf68, + 0xbf4d86a5f5adbdac, + 0x3ee169041634c20c, + 0x3ef66f5bd1bedad0, + 0xbe8a69b2c7176656, + 0xbe93de4eab455284, + 0x3e2755eabb6b4563, + 0x3e2702fe7b7aa32d, + 0xbdbaf1fff2894365, + 0xbdb2c697124bdb4b, + 0x3d45e717125b6112, + 0x3d36bd366d374341, + 0xbcca1d9ce8759323, + 0xbcb50c32fba6f689, + ], + [ + 0xbfbb5a622198a72c, + 0x3b261140492792be, + 0x3fab5a622198a72c, + 0xbf34ee71cf67c243, + 0xbf7237c02b462f6f, + 0x3f00b67b6fdfec64, + 0x3f2365167d8bc319, + 0xbeb3086b7a29712d, + 0xbec61a141425984e, + 0x3e56712b239ca861, + 0x3e5f507367e2287b, + 0xbdf0366d05430f3b, + 0xbdee38f952d755dd, + 0x3d7faa412f355ab7, + 0x3d7522cbd2af359c, + 0xbd064e7a6cf56505, + 0xbcf62cd7c73270a1, + 0x3c883112ff8933cd, + ], + [ + 0xbaeb8a30d224cee7, + 0x3fbaf9cb42cd08a7, + 0xbf4e1c66d7616e37, + 0xbf91f90fd1013589, + 0x3f240e3eb09b7d6d, + 0x3f4cb682ff471274, + 0xbee0016819a61da0, + 0xbef5d2d1c420645b, + 0x3e884b0fe8a7ecd7, + 0x3e93559d96bedaf4, + 0xbe257a0be6df375d, + 0xbe26677c8f23f9e7, + 0x3db8d1ada000f3d8, + 0x3db24a6de676e9f8, + 0xbd4431a53c25281e, + 0xbd362a9b74747797, + 0x3cc81ad277664852, + 0x3cb487f213f494c1, + ], + [ + 0x3fba9d183bc04545, + 0xbb24612b590e8e50, + 0xbfaa9d183bc04545, + 0x3f334779874010dc, + 0x3f71ba2299ab88a8, + 0xbefecb19f5bdc64d, + 0xbf22e052707cc843, + 0x3eb18a5da77ee010, + 0x3ec5846b622f2fd0, + 0xbe54b17e97b8ccc9, + 0xbe5e7f7666f84ced, + 0x3dedeb50538393d5, + 0x3ded72e1f6ccd5a2, + 0xbd7d3e0b2d7b598f, + 0xbd749b384c86d390, + 0x3d049ebe7a682354, + 0x3cf5a2123b57dec6, + 0xbc8662ce26072b62, + ], + [ + 0x3ae97c92b0497970, + 0xbfba4407dac72297, + 0x3f4bcba4dec1da44, + 0x3f91803c65cafdfb, + 0xbf2283df2b3e4a6d, + 0xbf4bf695e89259cd, + 0x3edd8f3759122cea, + 0x3ef54246c8e04206, + 0xbe867111bc8e08a2, + 0xbe92d72a1f62d131, + 0x3e23d9ca3e4f40f9, + 0x3e25d74a6df26826, + 0xbdb6f4b3a86a00b8, + 0xbdb1d6f951aed310, + 0x3d42b1828de6ffa0, + 0x3d35a1d54468858d, + 0xbcc655ad620318bd, + 0xbcb40c27591e7a1a, + ], + [ + 0xbfb9ee5eee1a97c6, + 0x3b22e5c966133b1c, + 0x3fa9ee5eee1a97c6, + 0xbf31d55d93e59bd7, + 0xbf7146219394a99c, + 0x3efc7d32bb646e2e, + 0x3f226599aed4f1b4, + 0xbeb03ba58ec85e6f, + 0xbec4f9e3961b9170, + 0x3e5328d4dc364807, + 0x3e5dbda7ac1d3f8b, + 0xbdebb7c2f5dfce50, + 0xbdecbac1e6849bc9, + 0x3d7b1c39328db702, + 0x3d741cdba002ff38, + 0xbd0321f9e5a1aec7, + 0xbcf520545c68186a, + 0x3c84ca30f2d8fe34, + ], + [ + 0xbae7aaec85700fa6, + 0x3fb99be73fa3efcc, + 0xbf49c3248da75775, + 0xbf91107147eda800, + 0x3f212980be9d8520, + 0x3f4b44e1221e6051, + 0xbedb67b78c1dd966, + 0xbef4bc49e9b5bceb, + 0x3e84d02ffb8b7772, + 0x3e9261c31456c932, + 0xbe226b4006e91d9d, + 0xbe25512519fb5144, + 0x3db5500f2545f2d3, + 0x3db16b4e5f84ad48, + 0xbd415e211f9e7a0f, + 0xbd3521ed4cbd2b27, + 0x3cc4c4800c50a30c, + 0x3cb39810921b4be9, + ], + [ + 0x3fb94c6f5898708b, + 0xbb219499b2c197ca, + 0xbfa94c6f5898708b, + 0x3f308f4f1b8fb0dc, + 0x3f70da931c776c71, + 0xbefa7550d2940f2e, + 0xbf21f3b978a47cde, + 0x3eae28ea0247325a, + 0x3ec47930aec7652a, + 0xbe51ce32c4f61fb7, + 0xbe5d0950e94a9be9, + 0x3de9c5a164496f38, + 0x3dec0f17151563cb, + 0xbd79390150c5d3eb, + 0xbd73a6c5157c0de8, + 0x3d01d041a270134c, + 0x3cf4a6c2b9e9b4e9, + 0xbc835f05ebdf3e12, + ], + [ + 0x3ae60bdc6a36e0e5, + 0xbfb8ffc9b9a131f6, + 0x3f47f724314bb99d, + 0x3f90a89c5d1074ba, + 0xbf1feeaeb33465e7, + 0xbf4a9fba36a7a08e, + 0x3ed980034770f358, + 0x3ef43fa4bb8cba45, + 0xbe835f40f3a33db9, + 0xbe91f465ba2910f8, + 0x3e212688f6f9e1b4, + 0x3e24d3f7e3ce0c1a, + 0xbdb3daee33c4651d, + 0xbdb106a0ff5e7529, + 0x3d40309d2f92ac42, + 0x3d34aa09772c258a, + 0xbcc35f72aaef208c, + 0xbcb32afd4e360d62, + ], + [ + 0xbfb8b5ccb03d459b, + 0x3b206ac337f71f68, + 0x3fa8b5ccb03d459b, + 0xbf2edc98b92fedf3, + 0xbf70767d524cea88, + 0x3ef8a85a847c89c6, + 0x3f2189afaa2bffb7, + 0xbeac1d231a69bf1e, + 0xbec40139bdbc767b, + 0x3e509a6859cb8509, + 0x3e5c60fc5f4b173c, + 0xbde80ad395bd719c, + 0xbdeb6e94ec333a76, + 0x3d778adf7d6d4ffb, + 0x3d7338227f2ea5d9, + 0xbd00a328a2899a4a, + 0xbcf4349a4535eb0d, + 0x3c821ac1fe027675, + ], + [ + 0xbae4990a795d52df, + 0x3fb86e51bb2ee24d, + 0xbf465e3bad214eb8, + 0xbf9047d6ed159c31, + 0x3f1dce4a381ce24d, + 0x3f4a05b93842da9a, + 0xbed7ce3df60b0e4e, + 0xbef3cb50138cce39, + 0x3e8216e84a5d9f52, + 0x3e918e354c013832, + 0xbe2005492fe9c63e, + 0xbe245ed4a343a749, + 0x3db28e2e71c56d3c, + 0x3db0a83f8589bb9d, + 0xbd3e46baa33f452c, + 0xbd3439690ccae646, + 0x3cc2201c8a30e9e6, + 0x3cb2c44f88828341, + ], + [ + 0x3fb829356c2fb67c, + 0xbb1ebe6fec859455, + 0xbfa829356c2fb67c, + 0x3f2cd964e5e4caa0, + 0x3f70190ce66b97c3, + 0xbef70d5fd8bad7b8, + 0xbf2126a150469af1, + 0x3eaa49ea858153dd, + 0x3ec3910f5c157962, + 0xbe4f0f4bdbe6f9e5, + 0xbe5bc36977db17fb, + 0x3de67f295d55fdea, + 0x3dead81ba8b0c52f, + 0xbd760a13803ef42a, + 0xbd72d03bf820c54e, + 0x3cff2ad7c1434050, + 0x3cf3c92e07a03306, + 0xbc80f7d055471199, + ], + [ + 0x3ae34bfa6ed120b4, + 0xbfb7e656ed57a0d1, + 0x3f44f0cfc62eb61c, + 0x3f8fdaba63e9c655, + 0xbf1be7bad1c50546, + 0xbf4975ac0770c98d, + 0x3ed64a6af83ba812, + 0x3ef35e6b41b6d769, + 0xbe80f12d050da9bf, + 0xbe912e744222d16c, + 0x3e1e04a8c0124324, + 0x3e23f0ed5e3ac1ab, + 0xbdb163fd1599c398, + 0xbdb04f8ecba977f7, + 0x3d3c639575076eb9, + 0x3d33cf61a84aa254, + 0xbcc101368b088743, + 0xbcb26377b4c35c24, + ], + [ + 0xbfb7a597eb76a5e3, + 0x3b53aefe167f1294, + 0x3fa7a597eb76a5e3, + 0xbf2b0bd9eb615315, + 0xbf6f831b9629acd2, + 0x3ef59d1c40c95bc4, + 0x3f20c9d35d4be179, + 0xbea8a711bec6b4b0, + 0xbec327e42f38db9e, + 0x3e4d225aa909ad2f, + 0x3e5b2f83a8f0f85c, + 0xbde51bef24cad6b5, + 0xbdea4ab13337518e, + 0x3d74b0547a699854, + 0x3d726e6cf385d626, + 0xbcfd56db39ddf26a, + 0xbcf362be01af446b, + 0x3c82edb1a6e2242c, + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1117 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::alpha1::{ + bessel_1_asympt_alpha, bessel_1_asympt_alpha_fast, bessel_1_asympt_alpha_hard, +}; +use crate::bessel::beta1::{ + bessel_1_asympt_beta, bessel_1_asympt_beta_fast, bessel_1_asympt_beta_hard, +}; +use crate::bessel::i0::bessel_rsqrt_hard; +use crate::bessel::y1_coeffs::Y1_COEFFS_REMEZ; +use crate::bessel::y1_coeffs_taylor::Y1_COEFFS; +use crate::bessel::y1f_coeffs::{Y1_ZEROS, Y1_ZEROS_VALUES}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log_dd_fast; +use crate::polyeval::{f_polyeval12, f_polyeval13, f_polyeval15, f_polyeval22, f_polyeval24}; +use crate::rounding::CpuCeil; +use crate::sin_helper::{cos_dd_small, cos_dd_small_fast, cos_f128_small}; +use crate::sincos_reduce::{AngleReduced, rem2pi_any, rem2pi_f128}; + +/// Bessel of the second kind of order 1 ( Y1 ) +pub fn f_y1(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x7ffu64 << 52 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::NEG_INFINITY; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f64::NAN; + } + return 0.; + } + + return x + f64::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x4049c00000000000u64 { + // x <= 51.5 + if xb <= 0x4000000000000000u64 { + // x <= 2 + if xb <= 0x3ff75c28f5c28f5cu64 { + // x <= 1.46 + return y1_near_zero_fast(x); + } + // transient zone from 1.46 to 2 have bad behavior for log poly already, + // and not yet good to be easily covered, thus it use its own poly + return y1_transient_zone_fast(x); + } + + return y1_small_argument_fast(x); + } + + y1_asympt_fast(x) +} + +/** +Generated by SageMath: +Evaluates: +y2 = -J1(x)*log(x) + 1/x * (1 - sum((-1)^m*(H(m)+H(m-1))/(2^m*m!*(m-1)!)*x^(2*m)) +Y1(x) = 2/pi*(-y2(x)+(euler_gamma - log(2))*J1(x)) +expressed as: +Y1(x)=log(x)*W1(x) - Z1(x) - 2/(pi*x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x', default_prec=300) +x = R.gen() +N = 16 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() +log2 = RealField(300)(2).log() + +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J1_series = j_series(1, x) + +def harmony(m): + return sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) + +def z_series(x): + return sum([(-1)**m * (x)**(ZZ(2)*ZZ(m)) / (ZZ(2)**(2*m) * ZZ(m).factorial() * (ZZ(m) - ZZ(1)).factorial()) * (harmony(m) + harmony(m - 1)) for m in range(1, N)]) + +W1 = d2/pi * J1_series +Z1 = -(d2/(x*pi) * z_series(x) + d2/pi * gamma * J1_series(x) - d2/pi * log2 * J1_series(x)) + +def y1_full(x): + return d2/pi * (J1_series(x) * x.log() - 1/x * ( 1 - z_series(x)) + (gamma - log2) * J1_series(x)) + +# see the series +print(W0) +print(Z0) +``` +See ./notes/bessel_y1_taylor.ipynb for generation +**/ +#[inline] +fn y1_near_zero_fast(x: f64) -> f64 { + const W: [(u64, u64); 15] = [ + (0xbc76b01ec5417056, 0x3fd45f306dc9c883), + (0x3c46b01ec5417056, 0xbfa45f306dc9c883), + (0xbbfe40290701eb1e, 0x3f5b2995e7b7b604), + (0xbba67fe4a5feb897, 0xbf021bb945252402), + (0xbb0334914cdd2ba9, 0x3e9cf9286ea1d337), + (0x3aab4f3c6d42c1f4, 0xbe2ee7a29824147f), + (0xba407fb57ef4dc2c, 0x3db78be9987d036d), + (0x39d2921e91b07dd0, 0xbd3ae90af76a4d0f), + (0x395a28c8620dc90e, 0x3cb7eb97f85e7d62), + (0xb8cf83f52abe45c5, 0xbc31028e3376648a), + (0xb8441050c68ca435, 0x3ba3cb1e7d0c17e7), + (0xb7ab072548a1aa43, 0xbb133191ed9f1eef), + (0xb6f05192c2d9b6ee, 0x3a7f7f4b5e8ef7b0), + (0x367ad65afe306d57, 0xb9e626e36cb3515d), + (0xb5ea1c4136f8f230, 0x394b01153dce6810), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let w0 = f_polyeval12( + x2.hi, + f64::from_bits(W[3].1), + f64::from_bits(W[4].1), + f64::from_bits(W[5].1), + f64::from_bits(W[6].1), + f64::from_bits(W[7].1), + f64::from_bits(W[8].1), + f64::from_bits(W[9].1), + f64::from_bits(W[10].1), + f64::from_bits(W[11].1), + f64::from_bits(W[12].1), + f64::from_bits(W[13].1), + f64::from_bits(W[14].1), + ); + + let mut w = DoubleDouble::mul_f64_add(x2, w0, DoubleDouble::from_bit_pair(W[2])); + w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[1])); + w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[0])); + w = DoubleDouble::quick_mult_f64(w, x); + + const Z: [(u64, u64); 15] = [ + (0x3c61d7eb2e54cda1, 0x3fc91866143cbc8a), + (0xbc2f9f7a0ce54a40, 0xbfabd3975c75b4a7), + (0xbbf7659313f45e8c, 0x3f6835b97894be5b), + (0x3b9cbcd40f1be7b9, 0xbf12c7dbffcde97d), + (0xbb495d78778645b4, 0x3eb0a780ac776eac), + (0xbae15be86455c1ab, 0xbe432e5a4ddeea30), + (0xba5ad966c12f1e3c, 0x3dcf0ce34d2066a6), + (0x39e9717155dc7521, 0xbd52a4e1aea45c18), + (0x394f447fe5de1290, 0x3cd1474ade9154ac), + (0xb8e1699d9009a7fc, 0xbc4978ba84f218c0), + (0xb8505502096ead17, 0x3bbe9598c016378b), + (0x37942b6c36b2c5f1, 0xbb2e7e5fcfc4b7b1), + (0x37210853b78bd08a, 0x3a99a6c1266c116d), + (0xb686c9639c9d976e, 0xba02738998fe7337), + (0xb603b739ee04b9fe, 0x3966f58cd41b6d08), + ]; + let z0 = f_polyeval12( + x2.hi, + f64::from_bits(Z[3].1), + f64::from_bits(Z[4].1), + f64::from_bits(Z[5].1), + f64::from_bits(Z[6].1), + f64::from_bits(Z[7].1), + f64::from_bits(Z[8].1), + f64::from_bits(Z[9].1), + f64::from_bits(Z[10].1), + f64::from_bits(Z[11].1), + f64::from_bits(Z[12].1), + f64::from_bits(Z[13].1), + f64::from_bits(Z[14].1), + ); + + let mut z = DoubleDouble::mul_f64_add(x2, z0, DoubleDouble::from_bit_pair(Z[2])); + z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[1])); + z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[0])); + z = DoubleDouble::quick_mult_f64(z, x); + + let w_log = log_dd_fast(x); + + const MINUS_TWO_OVER_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3c86b01ec5417056, 0xbfe45f306dc9c883)); + + let m_two_over_pi_div_x: DoubleDouble; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + m_two_over_pi_div_x = DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::two_product_compatible; + m_two_over_pi_div_x = if two_product_compatible(x) { + DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x) + } else { + DoubleDouble::div_safe_dd_f64(MINUS_TWO_OVER_PI, x) + }; + } + if m_two_over_pi_div_x.hi.is_infinite() { + return f64::NEG_INFINITY; + } + + let zvp = DoubleDouble::mul_add(w, w_log, -z); + let p = DoubleDouble::add(m_two_over_pi_div_x, zvp); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_near_zero(x, w_log) +} + +/** +Generated by SageMath: +Evaluates: +y2 = -J1(x)*log(x) + 1/x * (1 - sum((-1)^m*(H(m)+H(m-1))/(2^m*m!*(m-1)!)*x^(2*m)) +Y1(x) = 2/pi*(-y2(x)+(euler_gamma - log(2))*J1(x)) +expressed as: +Y1(x)=log(x)*W1(x) - Z1(x) - 2/(pi*x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x', default_prec=300) +x = R.gen() +N = 16 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() +log2 = RealField(300)(2).log() + +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J1_series = j_series(1, x) + +def harmony(m): + return sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) + +def z_series(x): + return sum([(-1)**m * (x)**(ZZ(2)*ZZ(m)) / (ZZ(2)**(2*m) * ZZ(m).factorial() * (ZZ(m) - ZZ(1)).factorial()) * (harmony(m) + harmony(m - 1)) for m in range(1, N)]) + +W1 = d2/pi * J1_series +Z1 = -(d2/(x*pi) * z_series(x) + d2/pi * gamma * J1_series(x) - d2/pi * log2 * J1_series(x)) + +def y1_full(x): + return d2/pi * (J1_series(x) * x.log() - 1/x * ( 1 - z_series(x)) + (gamma - log2) * J1_series(x)) + +# see the series +print(W0) +print(Z0) +``` +See ./notes/bessel_y1_taylor.ipynb for generation +**/ +#[cold] +#[inline(never)] +fn y1_near_zero(x: f64, w_log: DoubleDouble) -> f64 { + const W: [(u64, u64); 15] = [ + (0xbc76b01ec5417056, 0x3fd45f306dc9c883), + (0x3c46b01ec5417056, 0xbfa45f306dc9c883), + (0xbbfe40290701eb1e, 0x3f5b2995e7b7b604), + (0xbba67fe4a5feb897, 0xbf021bb945252402), + (0xbb0334914cdd2ba9, 0x3e9cf9286ea1d337), + (0x3aab4f3c6d42c1f4, 0xbe2ee7a29824147f), + (0xba407fb57ef4dc2c, 0x3db78be9987d036d), + (0x39d2921e91b07dd0, 0xbd3ae90af76a4d0f), + (0x395a28c8620dc90e, 0x3cb7eb97f85e7d62), + (0xb8cf83f52abe45c5, 0xbc31028e3376648a), + (0xb8441050c68ca435, 0x3ba3cb1e7d0c17e7), + (0xb7ab072548a1aa43, 0xbb133191ed9f1eef), + (0xb6f05192c2d9b6ee, 0x3a7f7f4b5e8ef7b0), + (0x367ad65afe306d57, 0xb9e626e36cb3515d), + (0xb5ea1c4136f8f230, 0x394b01153dce6810), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut w = f_polyeval15( + x2, + DoubleDouble::from_bit_pair(W[0]), + DoubleDouble::from_bit_pair(W[1]), + DoubleDouble::from_bit_pair(W[2]), + DoubleDouble::from_bit_pair(W[3]), + DoubleDouble::from_bit_pair(W[4]), + DoubleDouble::from_bit_pair(W[5]), + DoubleDouble::from_bit_pair(W[6]), + DoubleDouble::from_bit_pair(W[7]), + DoubleDouble::from_bit_pair(W[8]), + DoubleDouble::from_bit_pair(W[9]), + DoubleDouble::from_bit_pair(W[10]), + DoubleDouble::from_bit_pair(W[11]), + DoubleDouble::from_bit_pair(W[12]), + DoubleDouble::from_bit_pair(W[13]), + DoubleDouble::from_bit_pair(W[14]), + ); + w = DoubleDouble::quick_mult_f64(w, x); + + const Z: [(u64, u64); 15] = [ + (0x3c61d7eb2e54cda1, 0x3fc91866143cbc8a), + (0xbc2f9f7a0ce54a40, 0xbfabd3975c75b4a7), + (0xbbf7659313f45e8c, 0x3f6835b97894be5b), + (0x3b9cbcd40f1be7b9, 0xbf12c7dbffcde97d), + (0xbb495d78778645b4, 0x3eb0a780ac776eac), + (0xbae15be86455c1ab, 0xbe432e5a4ddeea30), + (0xba5ad966c12f1e3c, 0x3dcf0ce34d2066a6), + (0x39e9717155dc7521, 0xbd52a4e1aea45c18), + (0x394f447fe5de1290, 0x3cd1474ade9154ac), + (0xb8e1699d9009a7fc, 0xbc4978ba84f218c0), + (0xb8505502096ead17, 0x3bbe9598c016378b), + (0x37942b6c36b2c5f1, 0xbb2e7e5fcfc4b7b1), + (0x37210853b78bd08a, 0x3a99a6c1266c116d), + (0xb686c9639c9d976e, 0xba02738998fe7337), + (0xb603b739ee04b9fe, 0x3966f58cd41b6d08), + ]; + let mut z = f_polyeval15( + x2, + DoubleDouble::from_bit_pair(Z[0]), + DoubleDouble::from_bit_pair(Z[1]), + DoubleDouble::from_bit_pair(Z[2]), + DoubleDouble::from_bit_pair(Z[3]), + DoubleDouble::from_bit_pair(Z[4]), + DoubleDouble::from_bit_pair(Z[5]), + DoubleDouble::from_bit_pair(Z[6]), + DoubleDouble::from_bit_pair(Z[7]), + DoubleDouble::from_bit_pair(Z[8]), + DoubleDouble::from_bit_pair(Z[9]), + DoubleDouble::from_bit_pair(Z[10]), + DoubleDouble::from_bit_pair(Z[11]), + DoubleDouble::from_bit_pair(Z[12]), + DoubleDouble::from_bit_pair(Z[13]), + DoubleDouble::from_bit_pair(Z[14]), + ); + z = DoubleDouble::quick_mult_f64(z, x); + + const MINUS_TWO_OVER_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3c86b01ec5417056, 0xbfe45f306dc9c883)); + + let m_two_over_pi_div_x: DoubleDouble; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + m_two_over_pi_div_x = DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::two_product_compatible; + m_two_over_pi_div_x = if two_product_compatible(x) { + DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x) + } else { + DoubleDouble::div_safe_dd_f64(MINUS_TWO_OVER_PI, x) + }; + } + if m_two_over_pi_div_x.hi.is_infinite() { + return f64::NEG_INFINITY; + } + + let zvp = DoubleDouble::mul_add(w, w_log, -z); + DoubleDouble::full_dd_add(m_two_over_pi_div_x, zvp).to_f64() +} + +#[inline] +fn y1_transient_zone_fast(x: f64) -> f64 { + /* + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + */ + const C: [(u64, u64); 28] = [ + (0x38d23216c8eac2ee, 0x3c631de77e55e9b0), + (0x3c77f3a6718f8e03, 0x3fe0aa48442f0150), + (0xbc52b77d09be8679, 0xbfbe56f82217b33a), + (0x3c237af39fc9d759, 0xbfa0d2af4e922afe), + (0xbc08241e95389bc3, 0xbf73a6dec2f9f739), + (0x3c18eac6a35acd63, 0x3f7e671c82a1c956), + (0x3be0a0f3c8908083, 0xbf65429d5dbc3bb0), + (0x3be217fa58861600, 0x3f517abad71c26c0), + (0x3bebc327d6c65514, 0xbf40b28b4ef33a56), + (0xbbcb597d6bdd5992, 0x3f2ef0d150ec9934), + (0x3bb1a480de696e07, 0xbf1c0758a86844be), + (0xbb9c6ea6352ab84e, 0x3f0b7c88b58d9ef3), + (0x3b7dbb78dfd868a9, 0xbee97ef9519bdcfd), + (0xbb8d4519030f499d, 0x3f04815f08e7ad5e), + (0x3bbbd70e1480e260, 0x3f10f348483b57bc), + (0x3b7117cf4d2b6f3c, 0x3f231914389bb1bb), + (0x3b8ca48beaf6a58d, 0x3f30b29e838345b4), + (0x3bccfac65ce17cf9, 0x3f39a69e98f61897), + (0xbbeae7e3065b09c9, 0x3f40b9511666fcf0), + (0xbbe5cbddf691e7e6, 0x3f428cd8388e634b), + (0xbbd91372412d1e1b, 0x3f414ba048d9e1d5), + (0xbbb0781a70c6f715, 0x3f3acdcf66f1de95), + (0xbba3ae83fd425494, 0x3f30f44ae6620bba), + (0x3bc001d75da77b74, 0x3f21154a0a1f2161), + (0xbb91c9afb1a1b874, 0x3f0a687b664cbac6), + (0x3b8e0a06b9444963, 0x3eed7c3cbb4ba5d8), + (0x3b4f0e9dfc915934, 0x3ec53ca23fdd0999), + (0xbb0409258f8ffca8, 0x3e8de620acb51b2d), + ]; + + // this poly relative to first zero + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + + let mut r = DoubleDouble::full_add_f64(-ZERO, x); + r = DoubleDouble::from_exact_add(r.hi, r.lo); + + let p0 = f_polyeval24( + r.to_f64(), + f64::from_bits(C[4].1), + f64::from_bits(C[5].1), + f64::from_bits(C[6].1), + f64::from_bits(C[7].1), + f64::from_bits(C[8].1), + f64::from_bits(C[9].1), + f64::from_bits(C[10].1), + f64::from_bits(C[11].1), + f64::from_bits(C[12].1), + f64::from_bits(C[13].1), + f64::from_bits(C[14].1), + f64::from_bits(C[15].1), + f64::from_bits(C[16].1), + f64::from_bits(C[17].1), + f64::from_bits(C[18].1), + f64::from_bits(C[19].1), + f64::from_bits(C[20].1), + f64::from_bits(C[21].1), + f64::from_bits(C[22].1), + f64::from_bits(C[23].1), + f64::from_bits(C[24].1), + f64::from_bits(C[25].1), + f64::from_bits(C[26].1), + f64::from_bits(C[27].1), + ); + + let mut p = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[0])); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3c50000000000000), // 2^-58 + f64::from_bits(0x3b90000000000000), // 2^-70 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_transient_zone(x) +} + +fn y1_transient_zone(x: f64) -> f64 { + /* + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + */ + const C: [(u64, u64); 28] = [ + (0x38d23216c8eac2ee, 0x3c631de77e55e9b0), + (0x3c77f3a6718f8e03, 0x3fe0aa48442f0150), + (0xbc52b77d09be8679, 0xbfbe56f82217b33a), + (0x3c237af39fc9d759, 0xbfa0d2af4e922afe), + (0xbc08241e95389bc3, 0xbf73a6dec2f9f739), + (0x3c18eac6a35acd63, 0x3f7e671c82a1c956), + (0x3be0a0f3c8908083, 0xbf65429d5dbc3bb0), + (0x3be217fa58861600, 0x3f517abad71c26c0), + (0x3bebc327d6c65514, 0xbf40b28b4ef33a56), + (0xbbcb597d6bdd5992, 0x3f2ef0d150ec9934), + (0x3bb1a480de696e07, 0xbf1c0758a86844be), + (0xbb9c6ea6352ab84e, 0x3f0b7c88b58d9ef3), + (0x3b7dbb78dfd868a9, 0xbee97ef9519bdcfd), + (0xbb8d4519030f499d, 0x3f04815f08e7ad5e), + (0x3bbbd70e1480e260, 0x3f10f348483b57bc), + (0x3b7117cf4d2b6f3c, 0x3f231914389bb1bb), + (0x3b8ca48beaf6a58d, 0x3f30b29e838345b4), + (0x3bccfac65ce17cf9, 0x3f39a69e98f61897), + (0xbbeae7e3065b09c9, 0x3f40b9511666fcf0), + (0xbbe5cbddf691e7e6, 0x3f428cd8388e634b), + (0xbbd91372412d1e1b, 0x3f414ba048d9e1d5), + (0xbbb0781a70c6f715, 0x3f3acdcf66f1de95), + (0xbba3ae83fd425494, 0x3f30f44ae6620bba), + (0x3bc001d75da77b74, 0x3f21154a0a1f2161), + (0xbb91c9afb1a1b874, 0x3f0a687b664cbac6), + (0x3b8e0a06b9444963, 0x3eed7c3cbb4ba5d8), + (0x3b4f0e9dfc915934, 0x3ec53ca23fdd0999), + (0xbb0409258f8ffca8, 0x3e8de620acb51b2d), + ]; + + // this poly relative to first zero + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + + let r = DoubleDouble::full_add_f64(-ZERO, x); + + let p0 = f_polyeval13( + r.to_f64(), + f64::from_bits(C[15].1), + f64::from_bits(C[16].1), + f64::from_bits(C[17].1), + f64::from_bits(C[18].1), + f64::from_bits(C[19].1), + f64::from_bits(C[20].1), + f64::from_bits(C[21].1), + f64::from_bits(C[22].1), + f64::from_bits(C[23].1), + f64::from_bits(C[24].1), + f64::from_bits(C[25].1), + f64::from_bits(C[26].1), + f64::from_bits(C[27].1), + ); + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c20000000000000), // 2^-61 + f64::from_bits(0x3a90000000000000), // 2^-86 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_transient_hard(x) +} + +#[cold] +#[inline(never)] +fn y1_transient_hard(x: f64) -> f64 { + /* + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + */ + pub(crate) static C: [DyadicFloat128; 28] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -184, + mantissa: 0x98ef3bf2_af4d8048_c85b23ab_0bb72488_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x85524221_780a817f_3a6718f8_e03513ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xf2b7c110_bd99d256_efa137d0_cf1f7988_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0x86957a74_9157ef64_286301b1_453792e2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -135, + mantissa: 0x9d36f617_cfb9c982_41e95389_bc32e8c2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf338e415_0e4ab31d_58d46b59_ac6792eb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xaa14eaed_e1dd7f7a_f861bb7b_fbe6acb5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0x8bd5d6b8_e1360121_7fa58861_5ff9b614_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0x85945a77_99d2ac87_9b052735_5d7f5f59_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0xf7868a87_64c99c94_d0528454_cdccd44c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -141, + mantissa: 0xe03ac543_4225edcb_6fe432d2_3f11a8b0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xdbe445ac_6cf79639_159cad54_7b1eda7c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xcbf7ca8c_dee7e624_48720279_75757a17_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xa40af847_3d6aef15_d737e785_b3163322_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0x879a4241_dabde37a_e1c2901c_4c06b1dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0x98c8a1c4_dd8dd811_17cf4d2b_6f3c3910_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0x8594f41c_1a2da01c_a48beaf6_a58cef9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xcd34f4c7_b0c4b9cf_ac65ce17_cf940c9c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0x85ca88b3_37e77ca3_039f349e_c6ddb06d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0x9466c1c4_731a5546_84412dc3_033a8ee7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0x8a5d0246_cf0ea66e_c8dbed2e_1e50b14f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xd66e7b37_8ef4a77c_3f2c79c8_4757a40d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0x87a25733_105dcfb1_45f00af6_adb11b5f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0x88aa5050_f90b0a00_3aebb4ef_6e7e9ce1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xd343db32_65d62ee3_6504e5e4_78c55965_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xebe1e5da_5d2ec3c1_40d72889_2c57e483_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0xa9e511fe_e84cc8f8_74efe48a_c9a09ebc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xef310565_a8d9675f_b6d38380_1abf92a6_u128, + }, + ]; + const ZERO: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x8c9df6a6_ff921721_70d796f3_2017e155_u128, + }; + let r = DyadicFloat128::new_from_f64(x) - ZERO; + + let mut p = C[27]; + for i in (0..27).rev() { + p = r * p + C[i]; + } + p.fast_as_f64() +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +pub(crate) fn y1_small_argument_fast(x: f64) -> f64 { + // let avg_step = 51.03 / 33.0; + // let inv_step = 1.0 / avg_step; + // + // println!("inv_step {}", inv_step); + + const INV_STEP: f64 = 0.6466784244562023; + + let fx = x * INV_STEP; + const Y1_ZEROS_COUNT: f64 = (Y1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(Y1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(Y1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x).abs(); + let dist1 = (found_zero1.hi - x).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + return y1_near_zero_fast(x); + } + + let close_to_zero = dist.abs() < 1e-3; + + let c = if close_to_zero { + &Y1_COEFFS[idx - 1] + } else { + &Y1_COEFFS_REMEZ[idx - 1] + }; + + let r = DoubleDouble::full_add_f64(-found_zero, x); + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(Y1_ZEROS_VALUES[idx]); + } + + let p = f_polyeval22( + r.hi, + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + f64::from_bits(c[13].1), + f64::from_bits(c[14].1), + f64::from_bits(c[15].1), + f64::from_bits(c[16].1), + f64::from_bits(c[17].1), + f64::from_bits(c[18].1), + f64::from_bits(c[19].1), + f64::from_bits(c[20].1), + f64::from_bits(c[21].1), + f64::from_bits(c[22].1), + f64::from_bits(c[23].1), + f64::from_bits(c[24].1), + f64::from_bits(c[25].1), + f64::from_bits(c[26].1), + f64::from_bits(c[27].1), + ); + + let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[5])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[4])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1])); + z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0])); + let p = z; + let err = f_fmla( + p.hi, + f64::from_bits(0x3c60000000000000), // 2^-57 + f64::from_bits(0x3c20000000000000), // 2^-61 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y0_small_argument_moderate(r, c) +} + +fn y0_small_argument_moderate(r: DoubleDouble, c0: &[(u64, u64); 28]) -> f64 { + let c = &c0[15..]; + + let p0 = f_polyeval13( + r.to_f64(), + f64::from_bits(c[0].1), + f64::from_bits(c[1].1), + f64::from_bits(c[2].1), + f64::from_bits(c[3].1), + f64::from_bits(c[4].1), + f64::from_bits(c[5].1), + f64::from_bits(c[6].1), + f64::from_bits(c[7].1), + f64::from_bits(c[8].1), + f64::from_bits(c[9].1), + f64::from_bits(c[10].1), + f64::from_bits(c[11].1), + f64::from_bits(c[12].1), + ); + + let c = c0; + + let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1])); + p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0])); + + let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3bf0000000000000), // 2^-64 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_small_argument_hard(r, c) +} + +#[cold] +#[inline(never)] +fn y1_small_argument_hard(r: DoubleDouble, c: &[(u64, u64); 28]) -> f64 { + // if we're too close to zero taylor will converge faster and more accurate, + // since remez, minimax and other almost cannot polynomial optimize near zero + let mut p = DoubleDouble::from_bit_pair(c[27]); + for i in (0..27).rev() { + p = DoubleDouble::mul_add(r, p, DoubleDouble::from_bit_pair(c[i])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + } + p.to_f64() +} + +/* + Evaluates: + Y1 = sqrt(2/(PI*x)) * beta(x) * sin(x - 3*PI/4 - alpha(x)) + + Discarding 1/2*PI gives: + Y1 = sqrt(2/(PI*x)) * beta(x) * (-cos(x - PI/4 - alpha(x))) +*/ +#[inline] +pub(crate) fn y1_asympt_fast(x: f64) -> f64 { + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let recip = if x.to_bits() > 0x7fd000000000000u64 { + DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_div_fma(4.0, x), 0.25) + } else { + DoubleDouble::from_recip(x) + }; + + let alpha = bessel_1_asympt_alpha_fast(recip); + let beta = bessel_1_asympt_beta_fast(recip); + + let AngleReduced { angle } = rem2pi_any(x); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = -cos_dd_small_fast(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let r_sqrt = DoubleDouble::from_rsqrt_fast(x); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c40000000000000), // 2^-60 + f64::from_bits(0x3bf0000000000000), // 2^-87 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_asympt(x, recip, r_sqrt, angle) +} + +/* + Evaluates: + Y1 = sqrt(2/(PI*x)) * beta(x) * sin(x - 3*PI/4 - alpha(x)) + + Discarding 1/2*PI gives: + Y1 = sqrt(2/(PI*x)) * beta(x) * (-cos(x - PI/4 - alpha(x))) +*/ +fn y1_asympt(x: f64, recip: DoubleDouble, r_sqrt: DoubleDouble, angle: DoubleDouble) -> f64 { + const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8cbc0d30ebfd15), + f64::from_bits(0x3fe9884533d43651), + ); + const MPI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc81a62633145c07), + f64::from_bits(0xbfe921fb54442d18), + ); + + let alpha = bessel_1_asympt_alpha(recip); + let beta = bessel_1_asympt_beta(recip); + + // Without full subtraction cancellation happens sometimes + let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha); + let r0 = DoubleDouble::full_dd_add(angle, x0pi34); + + let m_cos = -cos_dd_small(r0); + let z0 = DoubleDouble::quick_mult(beta, m_cos); + let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt); + let r = DoubleDouble::quick_mult(scale, z0); + let p = DoubleDouble::from_exact_add(r.hi, r.lo); + let err = f_fmla( + p.hi, + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3a80000000000000), // 2^-87 + ); + let ub = p.hi + (p.lo + err); + let lb = p.hi + (p.lo - err); + if ub == lb { + return p.to_f64(); + } + y1_asympt_hard(x) +} + +/* + Evaluates: + Y1 = sqrt(2/(PI*x)) * beta(x) * sin(x - 3*PI/4 - alpha(x)) + + Discarding 1/2*PI gives: + Y1 = sqrt(2/(PI*x)) * beta(x) * (-cos(x - PI/4 - alpha(x))) +*/ +#[cold] +#[inline(never)] +fn y1_asympt_hard(x: f64) -> f64 { + const SQRT_2_OVER_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcc42299e_a1b28468_7e59e280_5d5c7180_u128, + }; + + const MPI_OVER_4: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + + let x_dyadic = DyadicFloat128::new_from_f64(x); + let recip = DyadicFloat128::accurate_reciprocal(x); + + let alpha = bessel_1_asympt_alpha_hard(recip); + let beta = bessel_1_asympt_beta_hard(recip); + + let angle = rem2pi_f128(x_dyadic); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_cos = cos_f128_small(r0).negated(); + + let z0 = beta * m_cos; + let r_sqrt = bessel_rsqrt_hard(x, recip); + let scale = SQRT_2_OVER_PI * r_sqrt; + let p = scale * z0; + p.fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_y1() { + // ULP should be less than 0.500001, but it was 0.5089558379720955, on 2.1957931471395398 result -0.0007023285780874727, using f_y1 and MPFR -0.0007023285780874729 + assert_eq!(f_y1(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007291282546733975), + -873124540555277200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_y1(2.1957931471395398), -0.0007023285780874727); + assert_eq!( + f_y1(f64::from_bits(0x571a31ffe2ff7e9fu64)), + f64::from_bits(0x32e58532f95056ffu64) + ); + assert_eq!( + f_y1(f64::from_bits(0x400193bed4dff243)), + 0.00000000000000002513306678922122 + ); + assert_eq!( + f_y1(f64::from_bits(0x3ffc513c569fe78e)), + -0.24189760895998239 + ); + assert_eq!( + f_y1(f64::from_bits(0x4192391e4c8faa60)), + -0.000000000000000002572292246748134 + ); + assert_eq!( + f_y1(f64::from_bits(0x403e9e480605283c)), + -0.00000000000000001524456280251315 + ); + assert_eq!( + f_y1(f64::from_bits(0x40277f9138d43206)), + 0.000000000000000006849807120770496 + ); + assert_eq!(f_y1(f64::INFINITY), 0.); + assert!(f_y1(f64::NEG_INFINITY).is_nan()); + assert!(f_y1(f64::NAN).is_nan()); + } + + #[test] + fn test_y1_edge_cases() { + assert_eq!(f_y1(2.1904620854463985), -0.0034837351616785234); + assert_eq!(f_y1(2.197142201034536), 4.5568985277260593e-7); + assert_eq!(f_y1(1.4000000000000004), -0.4791469742327998); + assert_eq!(f_y1(2.0002288794493848), -0.1069033735586767); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1068 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Remez poly at point for Y1 + +Generated by SageMath and Sollya: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = 1.4 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.03 - zeros[i] + b = (zeros[i]) + 0.83 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.03 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.03 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(y1_zeros) +print(intervals) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 200; +bessel_y1 = library("/Users/radzivon/RustroverProjects/pxfm/notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_y1(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RealField(500)(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +def print_remez_coeffs(poly): + print("[") + for i in range(len(poly)): + coeff = poly[i] + print_double_double("", coeff) + print("],") + +degree = 27 + +print(f"pub(crate) static Y1_COEFFS: [[(u64, u64); {degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print_remez_coeffs(coeffs) +print("];") +``` +**/ +pub(crate) static Y1_COEFFS_REMEZ: [[(u64, u64); 28]; 32] = [ + [ + (0xb839eddec375bf6c, 0x3b9d10948a169574), + (0xbc74a40e665752d5, 0x3fe0aa48442f014b), + (0xbc5d63ac05d1c2a6, 0xbfbe56f82217b8f1), + (0x3c1a86d2f484de78, 0xbfa0d2af4e932384), + (0xbc18399f4b2b50aa, 0xbf73a6dec3729034), + (0x3c0746a596f9ad9c, 0x3f7e671c7d1193a4), + (0x3bf3d92bfdba1d2f, 0xbf65429dc5a47c3d), + (0xbbf4b8971a16b469, 0x3f517ab4afad8d4c), + (0x3b652513f456a41f, 0xbf40b2d877c8c1c4), + (0xbbcc3336d312aa0f, 0x3f2eea7bbac80106), + (0xbbaf716735bf35cc, 0xbf1c3fae403eeb85), + (0xbbad1a66b3876cc3, 0x3f09d174ea03d698), + (0x3b8d9b871bbf32f3, 0xbef7956a25d2646a), + (0xbb773ed35ee47138, 0x3ee58659a1776ea8), + (0xbb62769d658c2265, 0xbed3a28e8e3dbde3), + (0xbb552085e0470bd4, 0x3ec1e78375f4f94a), + (0xbb08d21567003010, 0xbeb050ddfe36a8d4), + (0x3ad34a82d3857504, 0x3e9db7fda6f15f12), + (0x3b2eab75515a5387, 0xbe8b2f16073b5272), + (0x3b154bf5b63c1a3c, 0x3e78ee8a3e626df9), + (0xbae94fc562d9a8af, 0xbe65dbfe34a22d4b), + (0xbafe6d5418c52ec0, 0x3e52ed2e77b64c13), + (0xbae2e47cbd9517fb, 0xbe45f153b0798574), + (0x3ad48498c8542ad5, 0x3e37beb356ba6efd), + (0xba9b754aa573c033, 0xbe026b71e3609cb5), + (0xba952f344bc0c1b0, 0xbdf0ee25335de707), + (0xba9d8998731da058, 0xbe10333960f701ed), + (0x3aa4fd188b620a2f, 0x3e02f1394b2fc331), + ], + [ + (0x3c3c696f3e8f595c, 0x3fdaabb4011ed330), + (0x37349e0b66c92237, 0x3aa5d4664eb6a104), + (0xbc682b7fdbcd42e2, 0xbfc8b45babe797ba), + (0x3bf25562940422c5, 0x3f8e147099a6f0ea), + (0xbbfea4fe1c2176f7, 0x3f88c5af1eeb2d6b), + (0xbbc92561b6f1afd0, 0xbf4133fa47da52e2), + (0xbbd2318dbab67c78, 0xbf3bf8af93ff0b8c), + (0x3b8367aefe821e18, 0x3f021d64be62ccf7), + (0xbb5ba2bd39c31481, 0x3eb44d2ce67b2ce0), + (0x3b33f47634278a41, 0x3eb14c3ab2ad7c72), + (0xbb35600f33967647, 0xbe9b8eee52e1c5c0), + (0x3b1e72487b134917, 0x3e7a85f1a876eaac), + (0x3af57616cb55d15e, 0xbe5bf86b3c8c3956), + (0xbacc84ceaea79fcd, 0x3e3f01920ab67df5), + (0xbacf7e9704007b68, 0xbe20fac5449162d1), + (0xba8a696b60bf9429, 0x3e0281882dcdc5b5), + (0xba74ae0431042976, 0xbde42b5ce9ff90d4), + (0x3a4ccb47728927b2, 0x3dc5f94ad54c0b9a), + (0x3a2998fdce097e66, 0xbda7ed4bc62e5bfe), + (0x3a25b8d3d29e6d16, 0x3d8a0a9970b12e30), + (0xb9fd16bf93867f52, 0xbd6c55bc3e323959), + (0xb9be0d077b14dc04, 0x3d4eddb2bc728a6f), + (0x39bef3623a05f15f, 0xbd30ceb720a28712), + (0xb9af97a81acfc768, 0x3d11f5e51ac3427a), + (0x3990a840895512d8, 0xbcf30a29d26fe9e8), + (0xb97f8b7789198fa8, 0x3cd774949aecc05b), + (0x3930f32d60ee9695, 0xbcbee41d171d95d6), + (0xb92bb8694cebdcf4, 0x3c96d81ef4f30d1d), + ], + [ + (0xb5bd273adffce0f7, 0xb95d4023dff47874), + (0x3c7b8d2a1c4966d1, 0xbfd5c7c556f0c19a), + (0xbc370c18fffaa71b, 0x3fa00b9f8571ca1f), + (0xbc4e4289c3a5bb03, 0x3faa15d92dfe3e27), + (0xbbf5a35920e4110a, 0xbf710a329e2c23fa), + (0xbc05118854f257ec, 0xbf61be6db9923acf), + (0x3bcb875e5c6cb75b, 0x3f2337c7e138f484), + (0x3ba72a340f9a98f1, 0x3f085b940eb607f9), + (0xbb21a52945306bc3, 0xbec80619147b78f2), + (0xbb469f0f1be4d82d, 0xbea255e6cf70cf33), + (0x3ae6cf00d3f14236, 0x3e5b62cd0201498a), + (0x3ad09fb089acb5d5, 0x3e380b1aac007d45), + (0x3a846c00973acf35, 0xbdfa7ee05a569284), + (0xba2f88c51e1b4b4a, 0x3d84065ca5ea7a77), + (0x3a12f4d97219bd18, 0xbd93847684c52488), + (0xba07e0dcba44e25e, 0x3d74980895f648d3), + (0x39efb8f4f34b685f, 0xbd4c00f7d7a2505b), + (0xb9b0c1aa67b8ed6e, 0x3d2402fd40ed4b9e), + (0x3993d56fd395d2c5, 0xbcfded828c8c4b93), + (0xb95fd48828b69170, 0x3cd6381399866139), + (0xb953bf2573b4d2c9, 0xbcb06b3a2379b696), + (0xb92dc38af391a21b, 0x3c884327396947d2), + (0xb90f7aa26b6f4550, 0xbc61ee8868358f55), + (0xb8db41373ba1af43, 0x3c3a9d108cee5321), + (0x38b6c01210cd7020, 0xbc1373d3a1131d7c), + (0x387b749adc7b48d6, 0x3bea94db4c089199), + (0xb86a113c4f1a075b, 0xbbc7ddb04ee5e8fa), + (0x38478b50ffaa017a, 0x3ba9bccbc209b225), + ], + [ + (0xbc583acf6511df31, 0xbfd36732d4b96094), + (0x35bb32394e3544b3, 0xb9504d29c8d39de2), + (0xbc5b435291c33435, 0x3fc3001c8002caf8), + (0x3c085153ba2c8a0d, 0xbf7bf5a03bab4999), + (0x3c28d66c54022151, 0xbf8751ea028c1953), + (0x3be6d2f42909876b, 0x3f423874cd8d0401), + (0xbbb4d7b925e5e573, 0x3f364f6610d64939), + (0xbb9920eb8c3a22f7, 0xbef02978de3838b9), + (0x3b66c8e6bd84e120, 0xbed72f0766d0d591), + (0x3b20b7ba8289b800, 0x3e8f2081874c7e33), + (0xbafe9312e3e2eb2a, 0x3e6defd5dce00666), + (0x3ab45c8d50dfdf07, 0xbe2205c6fe8f26fd), + (0x3a63094c526b5e53, 0xbdfb6432e005a435), + (0x3a5f030235b03180, 0x3db0289fce476893), + (0x3a06336d9bbe36cd, 0x3d80778a2d37fd6e), + (0x39ca74bc4d2363cc, 0xbd29723fe568d2cc), + (0xb9a9854b8c15ca93, 0xbd082f3f7062fec4), + (0xb960225f10f6c2a9, 0x3cc7a09f41509f4d), + (0x38e482bb3a554a6f, 0xbc85319ecc467384), + (0x390dda9bdc9a0a0c, 0x3c62d63451822c2b), + (0xb8c73bb6bf497904, 0xbc38c3eac5e357dd), + (0xb8814c483642d1a7, 0x3c0ba16f9ef7d844), + (0x3871b7e296e61522, 0xbbdf92d4713ff54f), + (0xb84e39cdf13f5f7c, 0x3bb25448a2561236), + (0x37fdcd7885723648, 0xbb85269652dc40ed), + (0x37e69c4b0a60ddd9, 0x3b58bb2c31aabdf7), + (0x37cd1cbdeb5d68ef, 0xbb2f0558fc9fc6be), + (0xb77691ca0957001c, 0x3aff85ebcabb7e09), + ], + [ + (0xb5d0a191002f7d89, 0x3946a82e829b73d0), + (0x3c61dc672a53c58f, 0x3fd15f993fceab5c), + (0xbc1455aa7db14f8f, 0xbf902b3933cf21b1), + (0x3c443ede64b782da, 0xbfa6395dfe49fcd4), + (0x3be10ad2b71b989e, 0x3f63ced2a2e69180), + (0x3c0f30cad7e0eac9, 0x3f607a678d6000bb), + (0x3baf8fd02659436b, 0xbf1b50d7e1d32020), + (0x3b91fb17828700ad, 0xbf06f7bab104f355), + (0xbb60ab92716b77c6, 0x3ec176e72bf94b8f), + (0x3b31557f37d0bc88, 0x3ea2becb2b6bbc6d), + (0x3aea30df2d48cbea, 0xbe5a384eebfe1367), + (0xbad27cd4c55aaf05, 0xbe341e7a923c3a90), + (0x3a8bfdf2814022d5, 0x3de9e3284f5dd101), + (0xba5d8b8089251a1e, 0x3dbec40b623ea350), + (0xba1f7c34ccfe84c2, 0xbd726868b83f8d7d), + (0x39eff9c315ea063c, 0xbd416f7ae80cad5e), + (0x3901c0bf665fc134, 0x3cf318658ecb9f66), + (0xb95a3e748f544b78, 0x3cbfacabdbab4e26), + (0xb9045493a1f3354c, 0xbc713cc1f69cc0fc), + (0xb8b0df6f123cf21e, 0xbc33cb940319e5c9), + (0x3863c569980a714d, 0x3bda2202db83e3df), + (0xb85ff8178cbd6f47, 0x3bb47d99d87a6c81), + (0x381b27b5c35fabff, 0xbb7452b1dfb57b43), + (0x37dfa437b73973d9, 0x3b350569c6b6e6ea), + (0xb7ade85c8a408aba, 0xbb080cb19b69b6d0), + (0xb7663e78d5cbec8e, 0x3ad82b8c2a256a02), + (0xb732862a69eab24c, 0xbaa7b1cc7eec05b9), + (0x371988acfb374395, 0x3a78a467c1568a16), + ], + [ + (0xbc64f19a2762f5ae, 0x3fd00ef3745e0e3c), + (0xb5f8d8215e0ae323, 0x39749943012b8dfc), + (0xbc2a5ca3437ac1e3, 0xbfbfcdacdda138f2), + (0x3c19a8e604f9385e, 0x3f706cc34cd829fa), + (0x3c01d3813b5701b6, 0x3f84641bb10c16cb), + (0x3bbd08ac252b4bd1, 0xbf37fac943e2a16d), + (0xbbd98c55ed55e628, 0xbf34769ed32e14a2), + (0xbb8b665d8b88d4a7, 0x3ee80608ecda1520), + (0xbb7d207258853e42, 0x3ed5cc8242d77e79), + (0x3b2f5c5f13a6d47c, 0xbe888c8f253923cc), + (0xbb0d50fa940eb605, 0xbe6ce5908c1f1376), + (0x3abc197e72c6469e, 0x3e1ed1625825eeeb), + (0x3a969b2f19a7ed88, 0x3dfa30d624f10edf), + (0x3a41771a6391a818, 0xbdaa50765ef82dbe), + (0x39eb336c0c56cc4b, 0xbd814cd364ef8287), + (0xb9d42fa2e0b554e2, 0x3d306199db2399a2), + (0x39a86abea2a826ff, 0x3d0164150f087364), + (0xb910d2f6ebf5241d, 0xbcaefb1085d3b487), + (0x390479f708f87e53, 0xbc7ba1419f5a8512), + (0xb8cf5a4e3ac59e65, 0x3c27638ccf278b3d), + (0xb89307e1a0fbb15c, 0x3bf18a62dcf6ad4f), + (0x3829bd1dae700b20, 0xbb9b54a49cff984a), + (0x37fef0a051abf082, 0xbb6359324a5430fd), + (0x379ca525de290a07, 0x3b10367cab8a544a), + (0x376e61614232382c, 0x3aca894799ef9e96), + (0xb6d099267c5285fc, 0xba44a99194b99bec), + (0xb6cac95a848fd4ed, 0xba4e189da839ed62), + (0xb6a1589b016c9eb3, 0x3a0eb3a19cff56d9), + ], + [ + (0xb6157dc0fbaeeffe, 0x397a750db1884eed), + (0x3c54d14c77bc1688, 0xbfcdc14ea14e89f9), + (0x3c2340bd04e7ddab, 0x3f84429fef5b5fbd), + (0x3c4f19a8f5b137a3, 0x3fa367d7d608e4ba), + (0xbbf4eb6bddef3531, 0xbf59d6eb2bc49e35), + (0xbba2f121221c3a28, 0xbf5dc4f991b3db86), + (0x3bbf047b904254ec, 0x3f1315ec04d6e6bc), + (0x3b9087e84c57d400, 0x3f0571814a1aa301), + (0x3b2795eb852a844d, 0xbeba2977fa42f227), + (0x3b3f92ddd9d5b409, 0xbea1e86423086328), + (0x3aff19e1c4bddb87, 0x3e54a7b82d41f690), + (0xbad019797b0c36e0, 0x3e3390660a1bb74c), + (0x3a8a68e98c9b9a08, 0xbde549e8b3ed12f4), + (0x3a500e13e664d35d, 0xbdbe32cf77b347a3), + (0xb9d4a45373f28834, 0x3d6eff58d55a39fb), + (0x39d2d3ed13f5fe2d, 0x3d415e5c0af749d4), + (0x39116a2ef1b4cefb, 0xbcf0d67f939f4916), + (0xb907e51a357adff3, 0xbcbef3f2afde997e), + (0xb8ba32737d1e38e3, 0x3c6c60ed34505e3e), + (0x38db347adfaf8e1c, 0x3c360519c76d8628), + (0x387aa159aedf8fee, 0xbbe324831e6fcd1d), + (0x38366083503c9cb5, 0xbba99201cdb23c66), + (0x37de183660131013, 0x3b5512064fe60126), + (0x37b1a5631a9356cb, 0x3b18d0404e2355af), + (0x37401bfae4d1c1bd, 0xbac3979694373619), + (0x36fc444a6f9d50fd, 0xba840b6d6d5adfae), + (0xb6bab8d9fe8decf4, 0x3a2cebab05fc8474), + (0xb6643dfbc2e7b96e, 0x39ee6703cd7c47ef), + ], + [ + (0xbc5a8046704071bd, 0xbfcc075da85beb4f), + (0x360798e196eec32e, 0xb971c7c4d6d8ab9e), + (0xbc53b0c30f3f6ea8, 0x3fbbdeb6ff9f55e1), + (0x3bef54869c181889, 0xbf661eefb74da882), + (0xbc20492140a086de, 0xbf8229ea914b846e), + (0xbbc9a664ae9a2d3a, 0x3f30cbcc6778fd37), + (0xbbd8078d46437191, 0x3f32aa59f5091f7b), + (0xbb7b81f3aff076e3, 0xbee1c15d5251ae6a), + (0x3b707e9f1d7b9d80, 0xbed4583f15abd692), + (0xbb2cc9b93fea46bb, 0x3e831d151a1284aa), + (0x3b0aa58bde012b8a, 0x3e6b74e57c226d3c), + (0x3abe0f5313d3a3df, 0xbe19044f1378d3e4), + (0xba92c7e5b316fd24, 0xbdf93b1ec7cafe33), + (0x3a314f797aa7c27a, 0x3da61a4e89bf8438), + (0x3a2985182535db57, 0x3d80d430f7e78fff), + (0xb9c88dfe73b74d4c, 0xbd2c3b0a8f7a7b0e), + (0x39abe65ee3cc9c8d, 0xbd010e773677ab43), + (0x391b33dc1a20b3ea, 0x3cab59410f7e6f2b), + (0xb913e4b69baed354, 0x3c7b2e693f06a59f), + (0x38b855eec84bd050, 0xbc24d1b6b5dc1362), + (0x3895dc4ab685c9a0, 0xbbf17c6418e3a01d), + (0xb833fe3056697f69, 0x3b999a3de53bc586), + (0x37f8f01faf48a793, 0x3b628ca7df1c74e1), + (0xb77f3f6f64fd7c97, 0xbb09f8ce2cdbd2b7), + (0xb762fd5da648ce9c, 0xbad083f17385f58f), + (0x3716906b313f0c25, 0x3a7628fa950b5817), + (0xb6c02a526d5ba00c, 0x3a38dadf7e4128f1), + (0xb68876e851c5781b, 0xb9e0755c2cf04c01), + ], + [ + (0xb60b222179696176, 0x39614f36ef623dbe), + (0x3c57ba12cd0fc91d, 0x3fca7022be084d99), + (0xbc17334559c5149d, 0xbf7c650b6b83109a), + (0xbc4d0f8f3671311f, 0xbfa163191c30aa62), + (0x3bbcf7c95031f9af, 0x3f526b045287ddca), + (0xbbf7b71420f279ed, 0x3f5b17602840abf5), + (0xbb99a95b35521dab, 0xbf0c0a9cee3c842a), + (0xbb91505ce3b29b1b, 0xbf03e398cbc472ea), + (0x3b5125ae0676cb8e, 0x3eb3f35db1ff1b8e), + (0xbb4e582cdfc3c4cd, 0x3ea0e9b612dbd385), + (0x3ae57a34be37e069, 0xbe5056babcd9632b), + (0x3ad18fdd5d5f696f, 0xbe32c1a8c8f963a5), + (0xb9e38df4d597ab98, 0x3de161b6aa9fde63), + (0xba4ed163038669b8, 0x3dbd4caa1e0162bc), + (0xba08f4a604b97cee, 0xbd69fdda132e53b1), + (0x39dc01e3b41a02ab, 0xbd4101c31e1df223), + (0xb986207f93b27521, 0x3cecdc25a81e55f2), + (0x3954737eca211d08, 0x3cbe87025cca1386), + (0xb90b81b0f636ed32, 0xbc68c602211c726f), + (0xb8c8869ba08d8915, 0xbc35d4a3a29a8a84), + (0x3873a38e72663f1d, 0x3be0f3be0d4659ff), + (0x384c0a8ef8364a36, 0x3ba97a197d5f15ec), + (0x37d74edace719127, 0xbb52f220ef308891), + (0xb7a8963ecee526ab, 0xbb18bb20459441c5), + (0xb76b806269e7e9d0, 0x3ac1a0e6c4af5773), + (0xb6e3b3a0df8cf60e, 0x3a844a1fb6f8097f), + (0x36cfc680cfe3679a, 0xba2b974aca95015c), + (0xb616726934bf9753, 0xb9ec9d1d06dc3c83), + ], + [ + (0x3c518b0303bbe2f5, 0x3fc931a5a0ae5aa0), + (0x36121d64a54c4faf, 0x397d0e55f98c2988), + (0x3c348c3f5f957879, 0xbfb919c8a3f203fa), + (0xbc0ef6b166c80d4c, 0x3f602a38da6262a9), + (0xbc207165718dd6e1, 0x3f807ced48910819), + (0x3bc68f5ae1c266f9, 0xbf2900f33a00690a), + (0xbbc8c05ccff0a4b5, 0xbf31278d46fd153c), + (0xbb6f62aece58d8e5, 0x3edb2595529cf1c7), + (0xbb731bd584077786, 0x3ed2f7c2d608e0eb), + (0xbb1f324b3544fc75, 0xbe7e212d2378b576), + (0xbb005c49aacfd364, 0xbe69f3fcf3638b5a), + (0xbab2a5d20b39cff5, 0x3e144fbf0377cdfa), + (0xba636fe0444316b4, 0x3df82268e83f4ed0), + (0x3a40f4d52865b8bd, 0xbda26cc2b02dc737), + (0x3a2cea5ea61316c8, 0xbd80418bae8bbc48), + (0x39b62f3557be1ae9, 0x3d2812815e643e0a), + (0xb995174e2d5d5173, 0x3d009b2ac849ff66), + (0xb94bf84e1c96b290, 0xbca7c55d0a6d073d), + (0xb91bee74f41f6ceb, 0xbc7aa167b939dcf6), + (0xb894276de305638b, 0x3c2264568716791b), + (0x389d8028e4fa69b9, 0x3bf137648ca28b1b), + (0x383829bd6501c349, 0xbb96ed64da9d1ba3), + (0x37d8257b2a34401a, 0xbb62564f7e37977f), + (0x37a8ba671e5c18cd, 0x3b0789c67b0265e0), + (0x377cd4a2067dca1a, 0x3ad05f6c5196ec96), + (0xb719395c6f8dc2fc, 0xba7443a74dff8e34), + (0xb6d72ed3f4c7738e, 0xba38b9f499af8cbf), + (0x366f755619b61063, 0x39de5a75c31562e5), + ], + [ + (0x3613f88ad2184341, 0xb97deb1fbadd35dc), + (0xbc63db68c5672838, 0xbfc80781c32422e7), + (0xbc1bf83906fd4d0d, 0x3f754eda697a0098), + (0x3c232419a9d405ca, 0x3f9fbe6df840847f), + (0x3bd5a76a98bd919a, 0xbf4be318d61276e1), + (0xbbe633162d1131ea, 0xbf58efee4094379c), + (0xbb4139e1a56cbd35, 0x3f059145b4f0e4de), + (0x3b2db153b13f607a, 0x3f0282d26a74c38e), + (0x3b48c60f3e75a12e, 0xbeaf56c29d9ad959), + (0xbb2ffef5e5fc81af, 0xbe9fdd03174f902a), + (0x3acf87aa05cc99f1, 0x3e4a44a7907fee59), + (0xbaded732e6cb4b4d, 0x3e31df65332ab3e4), + (0xba6ed0c9b89ddac3, 0xbddc96e9cf361a43), + (0x3a2bdfd4155ccb1c, 0xbdbc3439f3fac67e), + (0x3a0882dd9c8f8976, 0x3d65d38ae50afdda), + (0x39c918a46e201723, 0x3d40833ea1f83461), + (0xb9805ea372f2e760, 0xbce8afb70fb3c9e7), + (0xb9589e6fcbbece80, 0xbcbdda411e59ed93), + (0xb8fe64047a8b5cb6, 0x3c65889665db0701), + (0x38cc032f117d0608, 0x3c35792846a5cf0c), + (0x3877212a63ae9eee, 0xbbdde1c2aabb0157), + (0x38433a64e3a464ef, 0xbba92deda759a7ee), + (0x37f57ed77143c7c0, 0x3b50e62605143db4), + (0x37bcf9184fd6279b, 0x3b1889818af5b2f7), + (0x37585a8626052c83, 0xbabfc6cafa7cab59), + (0x371544bf1179e875, 0xba8431694dabf284), + (0xb6c8663570999d11, 0x3a291671421e9a9a), + (0x366d87c073318aaf, 0x39ec7c2e9f5155fa), + ], + [ + (0x3c559364e26d93ec, 0xbfc713fc51664c74), + (0x35fb44d96564e55b, 0x395783f5327e6c23), + (0xbc488077fd102b68, 0x3fb7049760cde490), + (0xbbff945ad33190e5, 0xbf58ef5f1cbe4874), + (0x3c0b034f6fcde56c, 0xbf7e5f53caf3bead), + (0x3bcb16596420529e, 0x3f237b0b62ddadd1), + (0xbb74114140670232, 0x3f2fd3bac08286da), + (0xbb66bf25df781814, 0xbed5789803de3afe), + (0xbb30f115b8c5264b, 0xbed1c0faa89993b9), + (0xbb1173613a405c7a, 0x3e7845b49b0674ba), + (0x3ada42fc27fec004, 0x3e6886872801396c), + (0x3a9cf2618301d0ff, 0xbe10b036779ac071), + (0xba8ed0ec9b47defb, 0xbdf7049d18354c88), + (0x3a3b54899e1cad3f, 0x3d9edd9d0fb2ebd2), + (0x3a01a5a29ccc845b, 0x3d7f44600957fa58), + (0xb9ca58ef04ecc85d, 0xbd2486b1d6a91df8), + (0xb9990a9ead891a51, 0xbd0016025abd20b3), + (0x38e7c870470babf1, 0x3ca498b3d1754fe9), + (0x38f03447a5f61ea1, 0x3c79f47baf518c44), + (0x38ceb6119f0d50ac, 0xbc2029b685b74cd7), + (0x38512b942de2f7a8, 0xbbf0ddbdab3fefe6), + (0x3827e51f6a1999e3, 0x3b94667d2d99941b), + (0x380b6b9ec305a50e, 0x3b620a8a16336d5f), + (0xb7951f2acc7ec6bd, 0xbb052c2d5a568fd7), + (0x377c8c53cd7e3c8e, 0xbad02a6eef6c4f74), + (0xb70808e163129b9f, 0x3a7266d35702aef4), + (0x36b4acbcd065af62, 0x3a387c082ca923a1), + (0x362c2b7e6c7f80f3, 0xb9dbb92bd7a2a5fb), + ], + [ + (0xb5fce01036202a2f, 0xb977cba8376f75ad), + (0xbc6d2f0105f3ce79, 0x3fc62d94d97e859c), + (0x3bd10ece6e29dfc9, 0xbf70bf614807033c), + (0xbc37013075a066ff, 0xbf9d5f857a2a6107), + (0x3be49380eb03f59c, 0x3f46081b0b7fe572), + (0x3bfce3676d17b413, 0x3f57307b03e248f8), + (0xbbabc5fb92b99d48, 0xbf0132c0aa83d0dc), + (0x3b962d899f08a69c, 0xbf0154ed4598d2f0), + (0x3b436681f34a9d12, 0x3ea94f64f476e615), + (0xbb2a69d5b518c645, 0x3e9e12725853a9fb), + (0x3aec161d9a9d14fb, 0xbe4588c758dfc8ab), + (0xbade3ba8f5e7da28, 0xbe31021cdd9b5f7f), + (0x3a7b80d1898736a0, 0x3dd7cfa7a6c26b53), + (0xba5b73ca7f2fd400, 0x3dbb0e011d23f5e3), + (0x3a0a4b395e402c3a, 0xbd6276cc0fa65a6a), + (0xb9d2e425ec7c0961, 0xbd3fe92f0882b440), + (0xb97dfb208f190c67, 0x3ce53126d86bf486), + (0x39466ab6083aa181, 0x3cbd07f6c1993c8f), + (0xb8fc1c6cc0e8c2a3, 0xbc62bc249a86f555), + (0xb8dace7e8fe0ba98, 0xbc34ffb4f078a4b9), + (0x38784b88dbeaf757, 0x3bda504d640eb072), + (0xb84627e1aa462991, 0x3ba8bd8d3c086d8d), + (0xb7acd97ac1b07880, 0xbb4e157f9aadb1fb), + (0xb770a16ecb1b132a, 0xbb1834ef40762499), + (0xb6fcba2044990927, 0x3abc8e561ba674cf), + (0xb7113212416c8ac8, 0x3a83fd2ac64e50dc), + (0x36c9bcf42c5735bb, 0xba26bc42552c47ab), + (0xb68c57d3f3c335cf, 0xb9ec3b9a1d42e3e6), + ], + [ + (0xbc5b858aeca267e1, 0x3fc56b97f8091ac5), + (0xb5db386c16851988, 0xb958742bfa32f6c1), + (0xbc21d2a41bfc4c19, 0xbfb560fcc8c08469), + (0xbbe6529450b1fd05, 0x3f53fafa39618883), + (0xbc1ad54776e42e71, 0x3f7c49141623372f), + (0x3bb39ecd4785a5a4, 0xbf1f69980694fd17), + (0x3bcc2a33b89df083, 0xbf2dc5f848aa9d34), + (0xbb7ed412867be351, 0x3ed178fc979b77bd), + (0x3b73a93300f08ebf, 0x3ed0b494a4bafcc7), + (0xbb1a1471efdf1226, 0xbe73fc3884c2743a), + (0x3b0b5eabaae144fe, 0xbe673afb9fb4d844), + (0xbaa47c72bb33286a, 0x3e0bd90346a3e0ed), + (0xba99f0845cc41fa4, 0x3df5f3bafb215b44), + (0x3a2ab1757b26fafb, 0xbd9a1c27c37569c8), + (0xba09d78a09cb2510, 0xbd7e0455dbf9cc4f), + (0xb9cc60b0fda73c5a, 0x3d2199b19fcacda0), + (0x398ae18bb5a4d6cb, 0x3cff1334609dc3bc), + (0xb93dfbfdb03c0541, 0xbca1e37265d5ce13), + (0xb9124b9c1211f5ba, 0xbc79353f1aee07d2), + (0x38b6ddd071a04833, 0x3c1c68e4abc15d44), + (0xb89af51247543220, 0x3bf075c5531fabc6), + (0xb83bd38f05e57450, 0xbb921f6f50975ff8), + (0xb8036a56ab0cdb14, 0xbb61ae48288fd913), + (0x375b9f05da83eefa, 0x3b02fdf3cf9be443), + (0x37523bbd552356c6, 0x3acfccedcdaa6c1c), + (0x370a91e99171a293, 0xba70a685da70f4ee), + (0x36b74aa0dfffb869, 0xba38280b96abaf7a), + (0x36763d2c62a700f6, 0x39d93cfbd5a050e0), + ], + [ + (0x35ff76e3d2dd1a44, 0x395b36c3bc5679d2), + (0xbc5e9088e9ff251a, 0xbfc4b2a38f1ab9b4), + (0x3bf658189763e156, 0x3f6b3878aadeb34d), + (0xbc3525fe797e2125, 0x3f9b750d89a9b35f), + (0x3bb2c48be700fe5e, 0xbf41f6911725a956), + (0xbbed0a355d52c199, 0xbf55beee6fd51c8a), + (0xbb8079c92f6ce382, 0x3efc3625d7a65089), + (0xbba1cffb5ca00b9e, 0x3f005375a588a72b), + (0xbb398a01195f4a0d, 0xbea4ee5e4e7cb18b), + (0xbb2804ad81294950, 0xbe9c7b3d81b5ff94), + (0x3aea91d5260903d9, 0x3e41fce14f48518c), + (0xbadb70b3abcec291, 0x3e30346643c9d86e), + (0xba7397d52845348b, 0xbdd41c861bc1c34b), + (0xba5410b5ffe22406, 0xbdb9eeda214eabbe), + (0x39f8192b2b15935c, 0x3d5f8cf277ce6338), + (0xb9de17c1ee8e15dd, 0x3d3ec46e14cd5d9e), + (0xb97a6de668e3d04f, 0xbce2500181b463c6), + (0x392d839824b54192, 0xbcbc24c2b350e45d), + (0x38e6e5769440b209, 0x3c605d9c149f1949), + (0xb8d2d7cef4612fe4, 0x3c34752e1249361d), + (0xb85cc90966d8e53e, 0xbbd73842b122f4e9), + (0xb84a80ace8d16161, 0xbba83594fd8e48aa), + (0x37e69bb04bf99132, 0x3b4acb92dbb1222f), + (0xb76f84be471103d9, 0x3b17c779363e533d), + (0x375bd738b69b7baf, 0xbab9a6bc39977c62), + (0xb72709f09b9c49c1, 0xba83b3d20f9f7463), + (0xb68fc77a615eb219, 0x3a2494670cd27cf5), + (0xb6826334c4bccfb0, 0x39ebe0ddc5ab4300), + ], + [ + (0xbc4d00ae4313eed0, 0xbfc413644356a52b), + (0x361469f16306ea73, 0xb97886d88ac06c23), + (0x3c2e7840863e7c12, 0x3fb40bb88c6f2b85), + (0x3bd5631193c7bbe6, 0xbf5078d13cfc400e), + (0x3c1a406bffcdbe30, 0xbf7a9191262ab9d5), + (0x3bbe2809cb4317d4, 0x3f1a005297618f35), + (0x3bc92fd90e2b1391, 0x3f2c0cbad847a60e), + (0x3b6faeaea4946c57, 0xbecd1a72e7c35fd8), + (0x3b6a2e571e687616, 0xbecf9a2654099c40), + (0x3b14a1a09cdfd73c, 0x3e70c6b06e20fcbe), + (0xbb08c15da7f48d8f, 0x3e66136d6425ea74), + (0xbaa9c15de165ee39, 0xbe07977677c6badc), + (0x3a91f269e34226c9, 0xbdf4f77b3143a31f), + (0xba2add845990ae24, 0x3d965720b0a36de3), + (0x3a0614d5e1fc171d, 0x3d7cd126dc5db8d4), + (0x39acdeda9cc1b993, 0xbd1e6d575a54f608), + (0x3998efad7cccf4f0, 0xbcfdfb4d0beacd2e), + (0xb93dd45bf2db34c1, 0x3c9f3cccbe3a6b23), + (0xb90d9046de649745, 0x3c786f5c7a82a7c3), + (0x38bcc387ac92fa4e, 0xbc190b8ec99c1761), + (0xb897fa896ae9170b, 0xbbf0061c155efe6d), + (0xb80e81b9d7fb3a38, 0x3b901f2cce805aa0), + (0xb7e9b68e9f1a61ca, 0x3b61476b1f425669), + (0xb7a17936a7b35d36, 0xbb0109964cb5ee15), + (0xb71070e07280a9b5, 0xbacf2f6936a50cd9), + (0xb704566a8e45b2c1, 0x3a6e1ae6370795ee), + (0xb6c4223bfe21f7a6, 0x3a37c2c229a343d5), + (0xb6672d858cefe400, 0xb9d6f33f958fa10d), + ], + [ + (0x3611a27c9ec03a6f, 0x39706267910ea7d6), + (0x3c4997782859a008, 0x3fc37aaceac987b9), + (0xbc09de167b0f525a, 0xbf66afe4fe0bc0f7), + (0xbc3d91e80a0529b5, 0xbf99de7a33bc3a97), + (0x3bdacaad4f266c0b, 0x3f3e024f567ac487), + (0xbbf5aee36a6b58b3, 0x3f548843c426abe0), + (0xbb8ed7ac2e5ef1cf, 0xbef7a8e14711c0f5), + (0x3b9b367577010374, 0xbefeeceb341ad833), + (0xbb4d96e37263f84b, 0x3ea1a743e05b39ca), + (0xbb36e8969000eefe, 0x3e9b143d39c90dd5), + (0xbad319f8c17a1d1b, 0xbe3e8e00012321d3), + (0x3aae89c89982dfa2, 0xbe2ef28e323e7496), + (0x3a7f30c6340427ad, 0x3dd137a1bf5bde2c), + (0x3a5bf7e9721f9c44, 0x3db8e087c7cb7f1d), + (0x39fb9386784ae3b7, 0xbd5b3dc9dd36d846), + (0xb9c9416eb664afb4, 0xbd3da6ae03deea14), + (0x397c9f46130e8018, 0x3cdfe64e83599734), + (0xb94f05115daba819, 0x3cbb3e899a8275ba), + (0x38c31d3c51684ee2, 0xbc5cc15471c3a370), + (0x38dff660cb4ed828, 0xbc33e3495674137f), + (0x386b19ea37ea8387, 0x3bd491cabca4a282), + (0xb7fee9491d40343c, 0x3ba7a07e1fc95f06), + (0x37e4a41a5994c845, 0xbb47ecb9be67f4a7), + (0x3786f1c46d712a3a, 0xbb174a2d06d7d6cc), + (0x37594e2ff6a6309a, 0x3ab712a9f6839c0d), + (0xb7147e96a2d3fad0, 0x3a835bcefeaed781), + (0xb6c430af3e496108, 0xba22a3254eb3d159), + (0xb683689f2fc779f3, 0xb9eb727d700d89b6), + ], + [ + (0x3c4f123683cf20a8, 0x3fc2f4e70d6c7e01), + (0x361f442aef336146, 0xb97591bf30ddf0c2), + (0xbc5702b97938a87d, 0xbfb2ef24d6f7526a), + (0x3be17c9efd992fc9, 0x3f4bc33c9dc6ec82), + (0xbc153a673a682d1e, 0x3f7920414ee2acbe), + (0xbba8c8602e55078d, 0xbf15f9173916a219), + (0xbbbd01332ea23729, 0xbf2a94fdbdcec471), + (0xbb6340ead67ee22f, 0x3ec8b309990f950c), + (0x3b62bfaf2a2b92bf, 0x3ece087ff4517c02), + (0x3b05bdd16ba2b30c, 0xbe6ca22ab12cb4b7), + (0x3ad498149d36365c, 0xbe650d1f28635cda), + (0x3aac3cc8c5cf9b92, 0x3e04441552e259a7), + (0xba95d08f72147a49, 0x3df411b8a8258957), + (0xb9f001851befe105, 0xbd9354e914c31b45), + (0x3a1141eaf70efbe6, 0xbd7bb16f111ebae7), + (0x39b1abb08be1dbdb, 0x3d1a888536e27439), + (0xb992bb2516838f25, 0x3cfced726c1026c8), + (0x392858a15531d1cd, 0xbc9b745d75ff638e), + (0xb8f68dca35d3026e, 0xbc77aaea63220979), + (0x38ba5598d094c6db, 0x3c162ef6548b3d48), + (0x3868e319c4957108, 0x3bef27eac43efa6e), + (0xb823d9360fee46a7, 0xbb8cc635a6cfb635), + (0xb801a40c068e9744, 0xbb60db1d947bfc05), + (0x37881141d0dd48d0, 0x3afea05195871c93), + (0x3766e70475fe3f97, 0x3ace8489e5ad7b34), + (0x36ff2a338fa956ef, 0xba6b3d80597f37cb), + (0xb681333c765d8ec9, 0xba375182dac04c91), + (0x367a4126c3cf44ba, 0x39d4e0f3b5cdb046), + ], + [ + (0x361be200b4a5908e, 0x3974f957842c3586), + (0x3c6b7326e3fbaa6e, 0xbfc2740819f1caaa), + (0xbbad91d1969669a0, 0x3f6349369dc780bb), + (0x3c211249d3675d9f, 0x3f98868d7401bf2e), + (0x3bab901426ad7111, 0xbf398cd1bebe1445), + (0x3b8e845cf46e9a08, 0xbf537eef9aadeee2), + (0xbb978bd723278bd2, 0x3ef43394c95b2d2b), + (0x3b98d34686b7250a, 0x3efd6dfcdb026028), + (0xbb39039620a09507, 0xbe9e448fbc8a1f43), + (0x3b1ab8335f58d6d9, 0xbe99d764ee07c839), + (0xbad24a385e18b9fd, 0x3e3a53958c8d74ff), + (0x3aae692fd829adc7, 0x3e2da0e1c8a08d37), + (0xba68265b22821350, 0xbdcdd7f918de776f), + (0xba554536fed50ee3, 0xbdb7e68037d5c861), + (0x39e8fab1857f8e79, 0x3d57c2e63bbe27ca), + (0xb9b6eea6ea65f06f, 0x3d3c973a175ffbb6), + (0xb97a4e6705d4e73d, 0xbcdc033788921734), + (0xb95d7517b81f587e, 0xbcba5d9f2bdd8af4), + (0x38fc5fbb6c45e1de, 0x3c596cb946e789e8), + (0x38c497a6d69d23c5, 0x3c335090afbe12d6), + (0x38799c64a296461a, 0xbbd24f90893c37df), + (0xb7fbecdd04e88b2a, 0xbba706010539124a), + (0xb7eafe8f4b0c9808, 0x3b457032af41d7a4), + (0xb7bc178a723aab4c, 0x3b16c43d5e0cacac), + (0x37373a6759c668d6, 0xbab4ce42861296d9), + (0x3714ea53a56cccdf, 0xba82fa99ffa503c9), + (0x36a6206269dd287a, 0x3a20e7e4d182d7e6), + (0xb64ef30807ed040a, 0x39eaf6aa0936f5c1), + ], + [ + (0x3c34f78a7cfd8a8a, 0xbfc20198200b699d), + (0x360565ac287f5dbb, 0x3964862986ce6868), + (0x3c1ede75d6e0c0a5, 0x3fb1fd242a74e630), + (0x3be31a446a06705c, 0xbf47cf261dfbf19a), + (0xbc0b11e38b0823ed, 0xbf77e4820ec1dde4), + (0xbbbbba7e6db236bb, 0x3f12e1bd281dfcbb), + (0x3bc48aed48d0a238, 0x3f2950bb06c6fdf9), + (0x3b5f50566d2c1e7b, 0xbec54a38ab6af546), + (0xbb69fdc0d6c239ec, 0xbecca94f38024fdc), + (0xbaf76dde5126de40, 0x3e68c7e75971c85c), + (0xbb0678751bf4f650, 0x3e6423fc7e251ca9), + (0x3aab4294dcf0c897, 0xbe019fe1d8e51b96), + (0xba976b8065979a15, 0xbdf34198c795142c), + (0x3a1b7155c351ab8b, 0x3d90e78cdab26dd9), + (0xba1a3a4b53edd6ed, 0x3d7aa74cb5ba4b0e), + (0xb9a9e4993f6f7c4a, 0xbd1756ee8369797d), + (0xb992ea1492b57e10, 0xbcfbee3ccbac62a3), + (0xb9058529ec2e805b, 0x3c984c93627c1378), + (0xb90c3b9cf073d667, 0x3c76ecd2977e72a5), + (0x38be2449e2bf487c, 0xbc13c1ad21981036), + (0x3883f6d9af30b491, 0xbbee45c90965f9de), + (0xb7f83349481ced2f, 0x3b89c8e8d181a236), + (0x380803a9275b7f65, 0x3b606d491b5da420), + (0x3798109188279175, 0xbafb9c064d80a138), + (0x376013fe3b9f77b2, 0xbacdd315dbfb672b), + (0x36fc9d61cb3c3abf, 0x3a68b2de73775fa8), + (0xb6ce777cbee59127, 0x3a36d90ef88dab95), + (0xb67862ced9ec7588, 0xb9d305b1d99a3c61), + ], + [ + (0xb5fb86fee5ebbcf6, 0x396f19a82c6866ac), + (0xbc4081c2a50ad27f, 0x3fc192f2627a74e3), + (0x3c06268e5916d632, 0xbf60a846a83fecf2), + (0xbc1be434e30d7a5a, 0xbf975eceaabf7f86), + (0x3bbc2d7f1eb154d6, 0x3f3617c581be35b1), + (0xbbb0beeca29a2baa, 0x3f529934b7a84483), + (0xbb91b58b66aab0a7, 0xbef18123e875188a), + (0x3b94740ce7aaa9dc, 0xbefc1f05a2d85165), + (0xbb3fd873b63ab5e9, 0x3e9a4e0bc0926545), + (0xbb233d21389bce0f, 0x3e98be81ad44d933), + (0xbabb1f9ca258cce3, 0xbe36f73795e25c01), + (0x3ababafde69f161c, 0xbe2c70ab158cd19a), + (0x3a5796bd01bf9720, 0x3dca262190472d9a), + (0x3a444e2c448f52df, 0x3db70112aab52bc2), + (0xb9f5a65a43d3cb6e, 0xbd54ec163f88c02f), + (0x39d52f72c43ac9e8, 0xbd3b991575a9daff), + (0xb9742584b2344dbc, 0x3cd8cbabadfd45c4), + (0xb952f19a04e89b00, 0x3cb9867f1ea85270), + (0xb8f407ccf94d1457, 0xbc56a0c58ce961b7), + (0xb8d0795ea11bd36d, 0xbc32c10fa1783b9d), + (0xb85c7f401bf9086f, 0x3bd0630454542422), + (0x3831adbad02f8547, 0x3ba66b5f3f83dfb5), + (0xb7c18a605d4d2201, 0xbb434a75d1b13844), + (0x37a6e2dd153188df, 0xbb163af22779791d), + (0xb75d10a8ae54e7d5, 0x3ab2d2655ffc3033), + (0xb72fe47a60aa5d90, 0x3a829478c1a243e5), + (0xb69af79b5351dbd0, 0xba1ebe95a9db6af0), + (0xb68a3c131c1f2df8, 0xb9ea729d3347c622), + ], + [ + (0x3c68f71f103b6bf8, 0x3fc12f9870d68e18), + (0x35eedd0c814b660b, 0x39584c0de5cb23f9), + (0xbc5fd0d25668ad6b, 0xbfb12c11811945f9), + (0x3bebc70ffc015992, 0x3f44b638f21f0f76), + (0x3c1bc10a4e0506fd, 0x3f76d2a897d58353), + (0x3ba5de76c7b42d7a, 0xbf10732e5458ba20), + (0x3bcfca03362738fd, 0xbf2835929300df3f), + (0x3b4992f62f114659, 0x3ec297283816a83b), + (0xbb50d6dea52a7094, 0x3ecb73adedf11a43), + (0xbb0dce80931dc602, 0xbe65b455b903f09c), + (0x3b0295728813e0af, 0xbe6353f0797a6699), + (0xba8bf23e761207b9, 0x3dfefc9ac17b1eeb), + (0xba878c04e9d38305, 0x3df28535463ce067), + (0xba096e621beb197b, 0xbd8dd894cbbee3f9), + (0xba0f45ad9ade804f, 0xbd79b288cc392b5b), + (0x39916204abd42d65, 0x3d14b2ec9ace070c), + (0xb9936d340e28fba5, 0x3cfaff72f6057831), + (0x393a603e53eacc06, 0xbc95a7bfada0275b), + (0xb901b469e17f5bb3, 0xbc7637b7b45acfc3), + (0xb8820547fceb973f, 0x3c11b216f1fbcae9), + (0x38886047cf777ac4, 0x3bed6a4aa2540e36), + (0xb7deebf62d61db26, 0xbb87366125ff8ead), + (0xb7f352b13b569959, 0xbb6000a238ddbac3), + (0x378f208cf7576478, 0x3af8faebb4eb88ac), + (0xb7338292ec57b7e3, 0x3acd201e6cbbf759), + (0xb70a1ecbbc05a2ed, 0xba6674d821ccdd7a), + (0x36c727a7e3d4fb6c, 0xba365d344fa9d6d7), + (0x365f47ff2787d3f1, 0x39d15e5b7cf8fc11), + ], + [ + (0x360bdb5b805e25b0, 0x3969e1daf83188a7), + (0x3c60c06e2860e867, 0xbfc0cf3ee98f769b), + (0xbbfc2c390327e76c, 0x3f5d26e7af251f79), + (0xbc394225ed089993, 0x3f965d05948a946a), + (0xbbcb3460aae307ce, 0xbf335959b8482e40), + (0xbbf744279fabe84c, 0xbf51cff175d05c2a), + (0xbb83714c1d2b527e, 0x3eeeb59416879106), + (0xbb89158b4542d28b, 0x3efaf7544eeac766), + (0x3b284917e9916dd8, 0xbe9720522bb1fc81), + (0xbb31671693e89a81, 0xbe97c41261705419), + (0x3a886ab5cb454f45, 0x3e343fa0ea5e007d), + (0xbab8f90f9f428048, 0x3e2b5e23abebd7a4), + (0x3a64e5d5f577d2d2, 0xbdc722397e750312), + (0xba51768fabb7fdb1, 0xbdb62f2174e6be49), + (0xb9fba4dd6a628798, 0x3d5294ab060a163a), + (0xb9de8957f248872f, 0x3d3aace944141c61), + (0x394ff7327b4ba565, 0xbcd61cc8146cdfa1), + (0xb9394e82e72782f6, 0xbcb8bb3c270a284d), + (0x38f4722936097c3e, 0x3c54449d966478fa), + (0x385797f171c71fea, 0x3c323712fdd32aac), + (0xb85151bbb56468ad, 0xbbcd7cedd0538c51), + (0x3800563232817820, 0xbba5d3f2f4d3b9e1), + (0xb7d9661fbc11e8a2, 0x3b416f9a7e4f8d43), + (0xb7b5912190425469, 0x3b15b1f1d8d05a13), + (0x375dae4cd5158605, 0xbab116c0b74e863e), + (0xb72f2d5922ef51d5, 0xba822c909d7ff79e), + (0x3686e084ffb6066d, 0x3a1c0950bfbf78de), + (0x36899d263bfc66cf, 0x39e9ea82b7b42ba3), + ], + [ + (0xbc6742aa46ea9b31, 0xbfc077eede4a0d89), + (0xb5d51339f008438b, 0xb93d0e3fbdb78328), + (0x3c3cabc5883fc763, 0x3fb0751548b2924d), + (0x3bd8c3b817f5be4f, 0xbf423b5d46a73864), + (0x3c1e7b0b0210cbce, 0xbf75e2467c8fb832), + (0xbb9abdc39961759f, 0x3f0cfe5c189d6e4d), + (0xbbcf4c0c63a83958, 0x3f273bbd8c7aef2d), + (0x3b6d9272577eb3fa, 0xbec06974d3d04287), + (0xbb56fb637948d35e, 0xbeca6081d36e6a2b), + (0xbaee9b9b2585b7c5, 0x3e6334a83cf6092b), + (0xbb0e3539c25f29f0, 0x3e6299571cb4e1fb), + (0xba80b2cd9f616718, 0xbdfb7f5bc0aada50), + (0xba818316569b1592, 0xbdf1da63b4d6f878), + (0xba03f4308aff6abe, 0x3d8a9288ceccd9f2), + (0x3a16f5c0a511bfb0, 0x3d78d1d74c88ee4c), + (0x39a16735a5eb7383, 0xbd127eed3a482d7f), + (0xb9883ce9962db86a, 0xbcfa2143706ccb78), + (0xb933e39af0b0a816, 0x3c936d1464c4bf22), + (0x390afef7e49ce49a, 0x3c758cc3ad07d84d), + (0xb8ae01cde6f904a8, 0xbc0fe0c8ce96de05), + (0x387fd4921dadf9fd, 0xbbec97f7854a0777), + (0x37f77fd4b81374ba, 0x3b84fee62588d5e1), + (0xb7f6a3ad2cef6d22, 0x3b5f2dcbb8b70749), + (0x379518518eb791db, 0xbaf6b09656bd01ca), + (0x3755aca529972d2e, 0xbacc6f2f1ddb116e), + (0xb70b72b0eec38d9d, 0x3a647b8c438cfbcc), + (0x36cc4b3943e41f19, 0x3a35e0cb3264bc18), + (0x36290f8597bf8fe9, 0xb9cfcd0aefeb1cbe), + ], + [ + (0x35d2722913fb4c63, 0x3944e3fd926f8fb1), + (0x3c61166b7995967a, 0x3fc0230ba90f2871), + (0x3bfb746b17280a35, 0xbf59ca16f0c9734e), + (0xbc375b99fcae0fa4, 0xbf9579c1bdbcfc99), + (0x3bc1259c7efa1bb2, 0x3f3120ecfac5c017), + (0xbbd35a76e06cda5a, 0x3f511dd26bbe2946), + (0x3b72ed405d5bc408, 0xbeeb37e7c9a57149), + (0xbb86e93d7c515f2f, 0xbef9f01e7c1909a0), + (0xbb2f562d62e74ecf, 0x3e94887fe7a88c2c), + (0xbad010f8761951e4, 0x3e96e37238841d4b), + (0xba99b7f17d43bc36, 0xbe3204b644d6a04b), + (0xbacc8fcda9cad56e, 0xbe2a659b13eebf8a), + (0x3a42b7267c5e128a, 0x3dc4a40c87601c97), + (0xba57720418c52447, 0x3db56f0250e4fcac), + (0xb9f80ede07f2b143, 0xbd50a1011bf4a7dd), + (0x39d51971dde44362, 0xbd39d22a6dc5a57c), + (0x3973c4be23c7c005, 0x3cd3db0f19da31d9), + (0xb95d91267d6c60a3, 0x3cb7fc7d4070961c), + (0xb8e43885990b2b03, 0xbc5243aa7bbc7ede), + (0x38d02229cd94d6a5, 0xbc31b3c3dd0d78fd), + (0xb83af6a3d8823899, 0x3bcaabdcab96df5c), + (0x384894bf3b4da9f0, 0x3ba541bb402c78ac), + (0xb7dda9ab25eaff8c, 0xbb3fa915b2fa47b8), + (0x379cbdf7cf876dad, 0xbb152ba169685593), + (0x3733162e8c1ee94b, 0x3aaf26066ae9706e), + (0x36f9819114677bb3, 0x3a81c51763321aee), + (0x36a446eca6c003a9, 0xba19a5c3984013f5), + (0xb68b1567ca85f2fe, 0xb9e96168a239b1d9), + ], + [ + (0xbc446154ab44acb3, 0x3fbfab0b166d23d8), + (0x35dbf46a8ed0ff76, 0x393d7c0296d587f1), + (0x3c4290cc8b89531c, 0xbfafa65c1ce7ebd6), + (0x3be9bdd7d19e6706, 0x3f4035bf503ffc1f), + (0x3be801473cc85f34, 0x3f750d1b04713c41), + (0x3babe22a416a834b, 0xbf09cd14a92842a2), + (0x3bca868e6f4e4834, 0xbf265d504af5d8fe), + (0x3b5814b5b96336a9, 0x3ebd3feeb33d9cee), + (0xbb4c05f6b4f495e3, 0x3ec96a257062f76e), + (0x3b0b04fde267ccf6, 0xbe61254f302b36b2), + (0x3ad771b2683ddadc, 0xbe61f11585e04fca), + (0x3a8b3d53dc0784a1, 0x3df89a7674dd98cd), + (0x3a7b6da4a2d7c8b5, 0x3df13f0ba48c1692), + (0x3a248eb19153b909, 0xbd87d67b47fd268e), + (0x3a0aa35dfad0cb5d, 0xbd780381812ad9b0), + (0xb97e8eabaacf7749, 0x3d10a41213b1209a), + (0xb9694e4f19ae8248, 0x3cf9530714f8af89), + (0xb935bd4a759fcd07, 0xbc918884a9ff47a4), + (0x390c5a7313603d8b, 0xbc74ec3ce9f28ddc), + (0x3891396752d2f4be, 0x3c0cde4ce08c9c88), + (0xb88f3ed08df90975, 0x3bebd00bdad9a3b4), + (0xb82845f2323731b8, 0xbb831454d10def31), + (0x37f8ae176f7e036c, 0xbb5e62383fd8bdbf), + (0xb7891c6860574ef2, 0x3af4b117f31a9f40), + (0xb76e1cfee2b9a0d7, 0x3acbc29e8f1ce304), + (0xb6d4fcd41e5c1c66, 0xba62bec668d1d14b), + (0xb69b898b21726f67, 0xba3565d792f0e519), + (0xb667b0601d949d31, 0x39cd328695f5c7be), + ], + [ + (0xb5856985dc45fea1, 0xb96fbca69975e716), + (0x3c50db2c50623ec1, 0xbfbf13fb0c0e6fcd), + (0x3bf63fd50ee5bfaf, 0x3f5706ed3d935d00), + (0x3c3a7c91ef9a7d9f, 0x3f94af74cbd77bef), + (0xbbac31e3b8ee60ac, 0xbf2e9a9e66e5a792), + (0x3bf35ae9733a6eb9, 0xbf507ec9ed824fcb), + (0xbb4a161032086ff0, 0x3ee856d4518ab29e), + (0xbb9af9c37c81cff9, 0x3ef9040de830649e), + (0x3af6ec0adcd73b17, 0xbe9262f69c56c652), + (0xbb34da0db90f8b57, 0xbe9618c94a54734d), + (0x3acfc6bc54a1c19e, 0x3e3029d2c8bf70d6), + (0x3ab60f30dc12e39e, 0x3e2983bca0a3e67c), + (0x3a60395cd0053820, 0xbdc28e2a00002a82), + (0xba51c63c15e96dac, 0xbdb4beeacafc4fad), + (0x39ed5a030c6605c2, 0x3d4df880e37a5060), + (0x39d2026270de9105, 0x3d3907be43054aec), + (0xb952832db501353a, 0xbcd1f10ff685083c), + (0x395f463c7798955d, 0xbcb74a1dc71abca5), + (0x38e7d8e5ae99ce88, 0x3c508d41117c90f3), + (0xb8d552c759edc37c, 0x3c313795880a77fc), + (0x386b16755d17fac8, 0xbbc83ea1ceb16a07), + (0xb848188a8a68517f, 0xbba4b5cc8ded0fc2), + (0xb7d762214edd8666, 0x3b3cdf000bd6f203), + (0xb789ca564a28d131, 0x3b14a97cac9def65), + (0xb74e5064a15a2c78, 0xbaac7eef42820297), + (0x371d86a43d3d4298, 0xba815f89d5c7d990), + (0xb6ba98e94c93cb57, 0x3a1789ebfe3c8e8c), + (0xb68a2c469d8fa268, 0x39e8d984b79cb9e9), + ], + [ + (0xbc5bf01bf61d8ed3, 0xbfbe891b327da16d), + (0xb5cc3c81dba6f81d, 0x3953aec892af6d03), + (0xbc3636379e4f582f, 0x3fae8533ce07bdb8), + (0x3bc53b9dd0e1816e, 0xbf3d1253218e31b0), + (0xbc1eae521e3467c6, 0xbf744e6826476498), + (0xbb6864ec60e7922a, 0x3f07271a9b5e3cb4), + (0x3bace83941ef46b5, 0x3f2595b697c8ec04), + (0xbb5f57ab9661648d, 0xbeba46b03ecb38cc), + (0xbb4dc38fda907530, 0xbec88c173e07621e), + (0x3add237c79f6db0f, 0x3e5ed9b1754fbd3c), + (0xbb0d6748bb472b61, 0x3e615891ef314e18), + (0x3a8caec9a3fbb1e1, 0xbdf62ca352cf904e), + (0x3a7916cf164a75f3, 0xbdf0b14767c2b010), + (0x3a2595ab6e7a4beb, 0x3d85879bb4a2a8ac), + (0xb9f9a36051cbdc81, 0x3d7745bbca5b0e82), + (0xb9a0856355ee0f2f, 0xbd0e21736ab8469f), + (0x3985ce3b693f20e7, 0xbcf893b256068d4d), + (0x3920359c32c5de22, 0x3c8fd42c80d03657), + (0xb9029a5c2c268edd, 0x3c7455e80611a14d), + (0xb8a84439970d2016, 0xbc0a4682da82870e), + (0x3879596804aa9b9c, 0xbbeb12f0bb307616), + (0xb815b3814c55d4ca, 0x3b816a7f58b7a414), + (0xb7f11e258570c30d, 0x3b5d9fa088a0baf3), + (0xb78f1b32689b744c, 0xbaf2f1ad94886e01), + (0x376c31c2ebc43a82, 0xbacb1bde877c7dfa), + (0x36f7154043b459d4, 0x3a6136b97f99fb4d), + (0x3693894e8fe8da2f, 0x3a34edb643b11559), + (0x36486be2c3a76600, 0xb9cae2d7b5d6550c), + ], + [ + (0xb5e117018bd0a4d7, 0x396cc7fef85a11ce), + (0xbc3b9f1d130797b4, 0x3fbe018dac1c17e3), + (0x3be072789a66c0ad, 0xbf54b994dd05c1fb), + (0xbc338b4f0d3a410f, 0xbf93f9e0db07e7ef), + (0xbb9a8995613210dd, 0x3f2b8e55b75b13ab), + (0xbbd251fa83bbf995, 0x3f4fdf68a78bb3d2), + (0xbb783beff5b1e008, 0xbee5ee9d17106a08), + (0x3b70935ad535759f, 0xbef82ee6dfdfedeb), + (0xbb36eeb8b4349e83, 0x3e90962d7f6d61a6), + (0x3b3ddb699c12a377, 0x3e9560edce7d682d), + (0xbaadbe6efa7bc4c2, 0xbe2d34381d02bdbe), + (0xbab5faefe93fce4d, 0xbe28b5a0e74ae0d3), + (0xba651c2d1b2cfd90, 0x3dc0cab953f05720), + (0xba4cdf9f9b970a3b, 0x3db41d21c68d7ed3), + (0x39efe10ea47be16f, 0xbd4b2d2dd7cb3c52), + (0xb9d985842dbfa533, 0xbd384c5369d2e33d), + (0x396e2573c81613c3, 0x3cd04e17ab25ece8), + (0x3940629f2b3df4a6, 0x3cb6a38e0aef9402), + (0xb8e1d69808a03084, 0xbc4e28099fc922c0), + (0xb8c82332ebaf3236, 0xbc30c28e6023fb30), + (0x386b9c9fc0c05d07, 0x3bc62487322c4643), + (0xb84bcacb7b5c3520, 0x3ba430a24f213ff8), + (0xb7c5039f9a7e3931, 0xbb3a7037139e97ed), + (0x379c58e611949e56, 0xbb142c5d039a4a70), + (0x3727db4e84bd36dc, 0x3aaa2a8a29e14a1d), + (0x36cc215ba322ceb2, 0x3a80fcdc0bece4f5), + (0xb6b57109b2328425, 0xba15ac88c96a9a92), + (0x3661fe5c16d66355, 0xb9e854529bb11eca), + ], + [ + (0xbc4d7a7b8d722118, 0x3fbd84391bb2748d), + (0xb5f89e9b40c23cab, 0x39715c553323e555), + (0x3c4b439a88ed803b, 0xbfad80edb3c4ea05), + (0xbbd902d343596722, 0x3f3a431f5421f7ef), + (0xbc13a66c5c4dc379, 0x3f73a282fe7b63a8), + (0x3bacf6f60b035a27, 0xbf04ed653e607bdd), + (0xbbb378680e9561b7, 0xbf24e15832bda3c4), + (0xbb5464c53ca4420f, 0x3eb7c5832dd1374f), + (0x3b40f0848ee6fe3d, 0x3ec7c2b80da8df98), + (0xbadb963cfcbd4c8f, 0xbe5bf160ccd35445), + (0xbac9dbc6af458996, 0xbe60cda2141b2a1e), + (0x3a876693420f17fa, 0x3df41d31d2a419e4), + (0xba820602dcfc6a1c, 0x3df02f6ca850168a), + (0xba125360d2345a18, 0xbd83901f61054085), + (0xba17df49fb76cb0e, 0xbd7696ce2b748d02), + (0x39af2c4622bc54e9, 0x3d0b6e82997a390e), + (0x399ac81facf7b5ab, 0x3cf7e214796bec18), + (0x3927c686b63cfcd2, 0xbc8d0a3822eede5d), + (0xb9116570c5a93cb1, 0xbc73c944a2b7a866), + (0xb8a7e7acb8f1f32c, 0x3c080748c2fd703d), + (0xb87cb3127b6df48b, 0x3bea608ebfae056a), + (0xb81b4f7b9cda848d, 0xbb7fee483d8cb2bd), + (0xb7fcfe24d11f96d0, 0xbb5ce67574b83792), + (0x3757b86fe74315fe, 0x3af168f6128b62f7), + (0xb76886b34e3ecd6f, 0x3aca7bbe8016f1c0), + (0x36d81a3f26ccf62a, 0xba5fb8acc96dbd9b), + (0xb6dd8ec78e1a519f, 0xba347945efb0e5b5), + (0xb650c6a09f8b3be4, 0x39c8d517ce0975bd), + ], + [ + (0xb5f1cdfb0cbbbf9b, 0x3963ad355553c663), + (0xbc56edd809f4ec44, 0xbfbd09b21e36c0bd), + (0xbbfd63853cd12a08, 0x3f52c84acfb586b4), + (0x3c340975d5184af7, 0x3f9355b904fbf7ee), + (0xbbc2e53f276aead9, 0xbf28fb570465af0d), + (0x3bdedf2b372334a8, 0xbf4edc3292ba6cfd), + (0xbb81b7d6d1c235c3, 0x3ee3e552ee8c2577), + (0xbb9b6ea46d6db745, 0x3ef76d44f6a83523), + (0x3b2fdb93f3cf1ba4, 0xbe8e1ee2dc4a3bda), + (0x3b3cccd425113a57, 0xbe94b944bbd4c7bf), + (0xbac4687392bdbcfe, 0x3e2a8c3a4ce36f16), + (0x3ac2a4a12febf7d8, 0x3e27f8c9ef47068e), + (0xba40ac973313c53b, 0xbdbe9295749ee471), + (0x3a116490085933e1, 0xbdb38813c3eb77e4), + (0x39e5a2d8c5b27290, 0x3d48c7cda44b7754), + (0xb9a05a73d2dc3c66, 0x3d379e90468589ab), + (0x3961ad36dfeb19e3, 0xbccdca323fb2ed12), + (0xb95c95ee628cae05, 0xbcb6080be2ba756c), + (0x38e14a5e61e5df84, 0x3c4b9a8e33ba505f), + (0x38869b43fbbf40af, 0x3c3054766d105227), + (0x3869a58ba74326c8, 0xbbc44fda8cffeefb), + (0xb80e3c951291e0af, 0xbba3b257514f6e67), + (0x37d7232bb9cc06e3, 0x3b384ea2f19dc085), + (0xb7b20d806734b932, 0x3b13b4adeb19bbff), + (0x37470ea8b4edb81d, 0xbaa81cf876394534), + (0x372493d295b38feb, 0xba809da078876581), + (0xb6b9d7d8c4984442, 0x3a14055384d957ac), + (0xb68f3f22c46d785d, 0x39e7d2d65aaf6d5b), + ], + [ + (0xbc579e384ae35818, 0xbfbc97d79918527d), + (0x35eb9172f9b7276c, 0x395ce1b629f3b194), + (0x3c415f3ee939a0c0, 0x3fac95081ab2b511), + (0x3bd3c58af0675aab, 0xbf37e0b14f7d7c3f), + (0x3c167e93b7727b22, 0xbf730688f6836a76), + (0xbb9eaad91947069e, 0x3f030941f6e78e36), + (0x3bb70db1e3b30ff6, 0x3f243d5898657a6f), + (0xbb39f80469778551, 0xbeb5a39a94f2ad54), + (0xbb5db472078111de, 0xbec70b18406146f7), + (0x3af60534ae337487, 0x3e597607f9532274), + (0xbad7032885ed6fc7, 0x3e604e788f4f63b9), + (0xba876faf3495b1f5, 0xbdf2598919473e7e), + (0xba64011e20bbe632, 0xbdef70154273be01), + (0xba12fbde85806234, 0x3d81df5c1ca3869c), + (0x3a11557ac79b4968, 0x3d75f5256665e918), + (0xb96dc72056cbaf44, 0xbd091a176f7295bc), + (0xb99ab0535f46bdf0, 0xbcf73cf989310b2c), + (0x392f229ecb648d6b, 0x3c8a9f0a04e76a3b), + (0x38dd6e9f2d0c2bf9, 0x3c7345b205781b7b), + (0x38a22edb9f6d2f0c, 0xbc0611e4c0bc23e9), + (0xb888702d77aa4448, 0xbbe9b88423f59f05), + (0xb7df03c936a4e4a6, 0x3b7d637385b6b500), + (0xb7f31f276ec1d4a1, 0x3b5c36bdc90c0d20), + (0x37908786cc7f97a2, 0xbaf00eeea5fbf4a4), + (0xb7521f3b34bd9065, 0xbac9e29e4e7fe131), + (0xb6d9c8943eaa0627, 0x3a5d56f0d36bcfd3), + (0x36cd064c8625bd4e, 0x3a3408faa535443a), + (0xb66864ee592be672, 0xb9c8d8880a8fa4ae), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs_taylor.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs_taylor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs_taylor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1_coeffs_taylor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1030 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Taylor series for Y1 in extremums and zeros. + +Generated by SageMath: + +```python +mp.prec = 115 +terms = 28 +print(f"pub(crate) static Y1_COEFFS: [[(u64, u64); {terms}]; {len(y1_zeros)}] = [") + +def get_constant_term(poly, y): + for term in poly.operands(): + if term.is_constant(): + return term + +def print_taylor_coeffs(poly, n): + print("[") + for i in range(0, n): + coeff = poly[i] + print_double_double("", RealField(115)(coeff)) + # print(f"{double_to_hex(coeff)},") + print("],") + +prev_zero = 0 + +for i in range(0, len(y1_zeros)): + k_range = y1_zeros[i] + range_diff = k_range - prev_zero + + x0 = mp.mpf(k_range) + from mpmath import mp, bessely, taylor + poly = taylor(lambda val: bessely(1, val), x0, terms) + # print(poly) + print_taylor_coeffs(poly, terms) + prev_zero = y1_zeros[i] + +print("];") +``` + */ +pub(crate) static Y1_COEFFS: [[(u64, u64); 28]; 32] = [ + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc749367c4c05aaa, 0x3fe0aa48442f014b), + (0xbc58e5288bbf5fe3, 0xbfbe56f82217b8f1), + (0x3c45adcf3e0230ee, 0xbfa0d2af4e932386), + (0xbc1aef581a20d1b6, 0xbf73a6dec37290aa), + (0x3bea0fd3a3179817, 0x3f7e671c7d1196fd), + (0x3bdbfdc1a54825cd, 0xbf65429dc5a45612), + (0x3bf2b56b5db9ac40, 0x3f517ab4afac0735), + (0x3bebebd87be68c3c, 0xbf40b2d877d5a29c), + (0xbbcf3ef5ec675b9a, 0x3f2eea7bbb907646), + (0xbbbc5481911cf1b3, 0xbf1c3fae3b0ad706), + (0xbb97d87196deccbb, 0x3f09d174c9ccecd9), + (0x3b9ce9bed2434862, 0xbef7956ad3fe9783), + (0xbb81a3285733db7f, 0x3ee5865d11ebb14d), + (0x3b7c0f8e48b356f0, 0xbed3a27f1fd4ac6e), + (0xbb601bb903ea5d53, 0x3ec1e742c1cf6acb), + (0xbb208185a8aebef4, 0xbeb051d134cb0a72), + (0x3b2d22383a2945e9, 0x3e9dbea846629267), + (0xbb2d0bd2365f955b, 0xbe8b1a1682f5eb1f), + (0xbb17f54155dbfd8e, 0x3e78b0b08d8ccddf), + (0x3b0c6ae86d8ad6fe, 0xbe667d8a7cc18981), + (0xbaea87f82b9f7fa9, 0x3e547c0e174bc402), + (0x3ae6655ff087a6b2, 0xbe42a7fb50d94c09), + (0xba74f97124d12cda, 0x3e30fd661ade45f0), + (0x3aad4c923a16d045, 0xbe1ef1655b283bca), + (0x3aa6328133433e29, 0x3e0c2d21fe733c5f), + (0xba292d7e82d617f2, 0xbdf9a7efb711afac), + (0xba60d9e2266f470a, 0x3de75c3fc5194fe2), + ], + [ + (0x3c3c696f3eb0ae77, 0x3fdaabb4011ed330), + (0x0000000000000000, 0x0000000000000000), + (0xbc682b7fe4dd90ef, 0xbfc8b45babe797ba), + (0x3bf255e280edf040, 0x3f8e147099a6f0ea), + (0xbbfea368c6887e7f, 0x3f88c5af1eeb2d6b), + (0xbbca04ffe9904e56, 0xbf4133fa47da52e2), + (0xbbd3086cde21e2cb, 0xbf3bf8af93ff0b8c), + (0xbbafa9018f253e3c, 0x3f021d64be62ccf9), + (0x3b3a4d52bc5a61e1, 0x3eb44d2ce67b2d18), + (0xbb48016de8c47acb, 0x3eb14c3ab2ad79cc), + (0x3b28724eeca6e146, 0xbe9b8eee52e1ce01), + (0xbb184699c450d4ac, 0x3e7a85f1a878746a), + (0xbaf5fb00f2f338b7, 0xbe5bf86b3c89849b), + (0x3adf14ae65986334, 0x3e3f01920a1ecb6b), + (0xbac5a8492238e17f, 0xbe20fac544c5a674), + (0x3a972f86dd69da9b, 0x3e02818841d3a289), + (0xba686f565d0da109, 0xbde42b5ceddd3872), + (0x3a540c6129af60a6, 0x3dc5f9472a38633d), + (0xba4276328d0b688c, 0xbda7ed484e6442ee), + (0xba23ab0f9748db4a, 0x3d8a0b10351f65a6), + (0x39d5b91f2ce320af, 0xbd6c567ba5000a2c), + (0x39e0b587d390388d, 0x3d4ed39e06bafa8a), + (0xb9ca4dd40bbdfa57, 0xbd30c36f7f68d190), + (0xb9ae9f2d1d6c950e, 0x3d123a81488a8c60), + (0x39796d1b53f4c705, 0xbcf3d198a043957c), + (0xb97e66e460933260, 0x3cd58b80d1da3cb2), + (0xb95de7856c390662, 0xbcb76b414bca83a9), + (0x3923face03bca6a1, 0x3c99742311b12a8a), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c7b8d2a1c496808, 0xbfd5c7c556f0c19a), + (0xbc370c18fffb661e, 0x3fa00b9f8571ca1f), + (0xbc4e4289c3acba27, 0x3faa15d92dfe3e27), + (0xbbf5a3591cb63f33, 0xbf710a329e2c23fa), + (0xbc0511883ce39919, 0xbf61be6db9923acf), + (0x3bcb8759d4a0e5cd, 0x3f2337c7e138f484), + (0x3ba7299907aec5c4, 0x3f085b940eb607f9), + (0xbb2063eb830ecaea, 0xbec80619147b78f2), + (0xbb4468879e6c349e, 0xbea255e6cf70cf33), + (0xbafc601de5ef1462, 0x3e5b62cd02014989), + (0xbad6adc77b77235d, 0x3e380b1aac007d1d), + (0x3a624f45defeeef1, 0xbdfa7ee05a568fe6), + (0xba283df15edc8775, 0x3d84065ca5f23bb5), + (0xba2c1a2ebca15779, 0xbd93847684c7da93), + (0x3a08225b40e694f7, 0x3d74980895b5067a), + (0xb9eed81f16f01fb8, 0xbd4c00f7d6be89d7), + (0xb9a4e2f268d1912d, 0x3d2402fd58efd6fd), + (0x399973b6338a6d0f, 0xbcfded82b76f72f2), + (0x3978023c06cffc92, 0x3cd6380d6ba31980), + (0xb94735a17d43c8d2, 0xbcb06b38ec70e0a6), + (0x3907f71a9df6b85b, 0x3c88443f14394c1d), + (0xb8f01075b123018b, 0xbc61ee2105252260), + (0xb8b57669955b81a8, 0x3c3a7c72c37961bf), + (0xb8954dc89e6e0348, 0xbc138e5e595f9137), + (0xb87ee16a4e8bff5b, 0x3becdf0d22c4f792), + (0xb86abb1732ed43be, 0xbbc54e9dcbced4f1), + (0xb82e4e62e1a676d6, 0x3b9f718438e6ba2f), + ], + [ + (0xbc583acf6511df31, 0xbfd36732d4b96094), + (0x0000000000000000, 0x0000000000000000), + (0xbc5b435291c33433, 0x3fc3001c8002caf8), + (0x3c085153ba2c907f, 0xbf7bf5a03bab4999), + (0x3c28d66c540219c4, 0xbf8751ea028c1953), + (0x3be6d2f429037cfc, 0x3f423874cd8d0401), + (0xbbb4d7b925522373, 0x3f364f6610d64939), + (0xbb9920eb782e7608, 0xbef02978de3838b9), + (0x3b66c8e5402ae5c0, 0xbed72f0766d0d591), + (0x3b20b724f28fabb4, 0x3e8f2081874c7e33), + (0xbafe89c3eab7b761, 0x3e6defd5dce00666), + (0x3ab712e9adc751d5, 0xbe2205c6fe8f26fd), + (0xba90a1fcff20092c, 0xbdfb6432e005a435), + (0xba40d93a2f6bee54, 0x3db0289fce476883), + (0xba2c7d1344d3ff23, 0x3d80778a2d37fe43), + (0x39a7b4208bcbde0d, 0xbd29723fe5684800), + (0xb9a84df62153f4f5, 0xbd082f3f70663f33), + (0xb91998f4a32b0e4b, 0x3cc7a09f40ec7306), + (0x39256931314bf68c, 0xbc85319ec342127c), + (0x38fd4eda573e2499, 0x3c62d63483483be2), + (0xb8a4a42a37750699, 0xbc38c3ecf9381019), + (0x3893811d88a13751, 0x3c0ba15f09ca6382), + (0xb8653a606cd73ccb, 0xbbdf92174ea83693), + (0x385bcb6c1b8ec617, 0x3bb25604c3a40365), + (0xb82168dd0f69d5f1, 0xbb853b55eb1a54fe), + (0xb7e96fc33c8ede98, 0x3b5889d72e8200c6), + (0xb7b3762a6112ab36, 0xbb2c5b6e1cc194ec), + (0xb78614198a535866, 0x3b0061d24b95ed7a), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c61dc672a53c590, 0x3fd15f993fceab5c), + (0xbc1455aa7db14f38, 0xbf902b3933cf21b1), + (0x3c443ede64b782d9, 0xbfa6395dfe49fcd4), + (0x3be10ad2b71b9820, 0x3f63ced2a2e69180), + (0x3c0f30cad7e0ebe8, 0x3f607a678d6000bb), + (0x3baf8fd02659f1ef, 0xbf1b50d7e1d32020), + (0x3b91fb17827843f5, 0xbf06f7bab104f355), + (0xbb60ab92724984c7, 0x3ec176e72bf94b8f), + (0x3b31557f6e92a4a7, 0x3ea2becb2b6bbc6d), + (0x3aea30e9dd0c4fab, 0xbe5a384eebfe1367), + (0xbad27d53b702d9ee, 0xbe341e7a923c3a90), + (0x3a8be8710ba9cded, 0x3de9e3284f5dd101), + (0xba5a7ff332888842, 0x3dbec40b623ea350), + (0x3a1bb0f2b7e06e32, 0xbd726868b83f8d7d), + (0xb9d127448ae5dbb8, 0xbd416f7ae80cad77), + (0xb98b4267f56d6b60, 0x3cf318658ecb9bd5), + (0x394a28f7ccb2ac45, 0x3cbfacabdbabe483), + (0xb8fdeb4ca08fc098, 0xbc713cc1f6930364), + (0x38c8e1a7a7c446ff, 0xbc33cb94044d8aee), + (0x3846a7a1323190de, 0x3bda22029099f534), + (0x385ab5c5889916dc, 0x3bb47d9b88989e97), + (0x381dfc385d309d52, 0xbb745299177606ed), + (0x37def84f6911654b, 0x3b3503d9701ead82), + (0x3757dbc183f5d86f, 0xbb08176b7514ca80), + (0x3726e80a82be2e11, 0x3ad863cb123482cb), + (0xb7400c9d5c314e72, 0xbaa6552586051784), + (0xb6ed950d76fdf6bc, 0x3a74afbafce97c21), + ], + [ + (0xbc64f19a2762f5ae, 0x3fd00ef3745e0e3c), + (0x0000000000000000, 0x0000000000000000), + (0xbc2a5ca3437ac1c3, 0xbfbfcdacdda138f2), + (0x3c19a8e604f93931, 0x3f706cc34cd829fa), + (0x3c01d3813b5701a3, 0x3f84641bb10c16cb), + (0x3bbd08ac252b4932, 0xbf37fac943e2a16d), + (0xbbd98c55ed55e5ec, 0xbf34769ed32e14a2), + (0xbb8b665d8b88b73b, 0x3ee80608ecda1520), + (0xbb7d207258864fea, 0x3ed5cc8242d77e79), + (0x3b2f5c5f133a954a, 0xbe888c8f253923cc), + (0xbb0d50fa8d8c7a72, 0xbe6ce5908c1f1376), + (0x3abc19806933366e, 0x3e1ed1625825eeeb), + (0x3a969b1553c1a884, 0x3dfa30d624f10edf), + (0x3a41711a2b894301, 0xbdaa50765ef82dbe), + (0x39ef8b9861fc6da9, 0xbd814cd364ef8287), + (0xb9bec99ce5124af1, 0x3d306199db2399a2), + (0x39a24cb0ca5a627f, 0x3d0164150f087360), + (0xb90883d74ed9e2a1, 0xbcaefb1085d3b5a6), + (0x390110bd90901ca7, 0xbc7ba1419f5a6f40), + (0x389f7ac7f08169b1, 0x3c27638ccf29c1b0), + (0xb89f51222b4b42bb, 0x3bf18a62dccdca9d), + (0xb83b3be96059d0b4, 0xbb9b54a4a2d7343a), + (0x38017f10a44ce3ed, 0xbb635931e0eacdee), + (0x37be3118e01854ca, 0x3b1036817e50e3af), + (0xb7657afa36f3f4a9, 0x3aca87e3e3debd9e), + (0x36c384606510e7f7, 0xba44ec6558f8bb31), + (0x36c308ed950cf583, 0xba4d684c0820785d), + (0xb6acfa02e081161c, 0x3a0f0d58bca1c41b), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c54d14c77bc1691, 0xbfcdc14ea14e89f9), + (0x3c2340bd04e7df4a, 0x3f84429fef5b5fbd), + (0x3c4f19a8f5b1379e, 0x3fa367d7d608e4ba), + (0xbbf4eb6bddef363a, 0xbf59d6eb2bc49e35), + (0xbba2f121221c388c, 0xbf5dc4f991b3db86), + (0x3bbf047b90425584, 0x3f1315ec04d6e6bc), + (0x3b9087e84c57d2ad, 0x3f0571814a1aa301), + (0x3b2795eb85278f1d, 0xbeba2977fa42f227), + (0x3b3f92ddd9da4ad7, 0xbea1e86423086328), + (0x3aff19e1c5d9e237, 0x3e54a7b82d41f690), + (0xbad0197985af09ca, 0x3e3390660a1bb74c), + (0x3a8a68e5322dab0d, 0xbde549e8b3ed12f4), + (0x3a500e54fb5a85ec, 0xbdbe32cf77b347a3), + (0xb9d3ea446c95f85a, 0x3d6eff58d55a39fb), + (0x39d1c41d97727556, 0x3d415e5c0af749d4), + (0x3994a6959d259d8b, 0xbcf0d67f939f4917), + (0x3951f0d6f37c7a4e, 0xbcbef3f2afde9972), + (0xb8ce371e6c4a5fb7, 0x3c6c60ed345061d2), + (0xb8ce6598cd4716cf, 0x3c360519c76d6d8a), + (0xb868ddc08c092699, 0xbbe324831e767061), + (0x3820a7a0186edebf, 0xbba99201cd6f64ed), + (0xb7d50b99e3cbd8ed, 0x3b55120660d9db07), + (0x37bd05b3e6de1af6, 0x3b18d03fd947900e), + (0x373b419f47dccb93, 0xbac397b2f45393ab), + (0x371a75815e071b8c, 0xba840af84bf4566b), + (0x36c253d300be5f73, 0x3a2d23b6405995b9), + (0x365d14598eec4332, 0x39ee07cb3c4c18f5), + ], + [ + (0xbc5a8046704071bd, 0xbfcc075da85beb4f), + (0x0000000000000000, 0x0000000000000000), + (0xbc53b0c30f3f6eaa, 0x3fbbdeb6ff9f55e1), + (0x3bef54869c1812be, 0xbf661eefb74da882), + (0xbc20492140a086db, 0xbf8229ea914b846e), + (0xbbc9a664ae9a2c1e, 0x3f30cbcc6778fd37), + (0xbbd8078d46437190, 0x3f32aa59f5091f7b), + (0xbb7b81f3aff07289, 0xbee1c15d5251ae6a), + (0x3b707e9f1d7b7e6a, 0xbed4583f15abd692), + (0xbb2cc9b93ff3f6ce, 0x3e831d151a1284aa), + (0x3b0aa58bdebda7d1, 0x3e6b74e57c226d3c), + (0x3abe0f534111cac9, 0xbe19044f1378d3e4), + (0xba92c7e898648f68, 0xbdf93b1ec7cafe33), + (0x3a314e62ad0639ef, 0x3da61a4e89bf8438), + (0x3a298cd71751f9aa, 0x3d80d430f7e78fff), + (0xb9c643be1c5347dd, 0xbd2c3b0a8f7a7b0e), + (0xb9608e40ab9aafb9, 0xbd010e773677ab43), + (0x3946ed856edf6b25, 0x3cab59410f7e6f10), + (0xb8e86e49965ef8df, 0x3c7b2e693f06a801), + (0xb8bd6df9232d394a, 0xbc24d1b6b5dbdd8a), + (0x389d45bfc9e28c95, 0xbbf17c6418e80b27), + (0x38330cb81415d134, 0x3b999a3de4a881f9), + (0x38014861b029a2c1, 0x3b628ca7ea60d3ed), + (0x3763e7968eedb33e, 0xbb09f8cd292fbd53), + (0xb772e1ee82abca63, 0xbad0840446d9db33), + (0x36eac14fda382bcb, 0x3a7627f31e8af8f1), + (0x36d03dd271f85894, 0x3a38fffe9d4c8a9c), + (0x368992b4a1b37e32, 0xb9e006ef0777e888), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c57ba12cd0fc91f, 0x3fca7022be084d99), + (0xbc17334559c5138c, 0xbf7c650b6b83109a), + (0xbc4d0f8f36713120, 0xbfa163191c30aa62), + (0x3bbcf7c95031f425, 0x3f526b045287ddca), + (0xbbf7b71420f279ea, 0x3f5b17602840abf5), + (0xbb99a95b35521d32, 0xbf0c0a9cee3c842a), + (0xbb91505ce3b29a78, 0xbf03e398cbc472ea), + (0x3b5125ae0677178c, 0x3eb3f35db1ff1b8e), + (0xbb4e582cdfc5009b, 0x3ea0e9b612dbd385), + (0x3ae57a34bc6cd52d, 0xbe5056babcd9632b), + (0x3ad18fdd63164b8f, 0xbe32c1a8c8f963a5), + (0xb9e37fef15ca364c, 0x3de161b6aa9fde63), + (0xba4ed1a8c48bfaf3, 0x3dbd4caa1e0162bc), + (0xba0907496979f354, 0xbd69fdda132e53b1), + (0x39dc92d876d25063, 0xbd4101c31e1df223), + (0xb980f5f389d54392, 0x3cecdc25a81e55f3), + (0xb9476a7e07116985, 0x3cbe87025cca1380), + (0x38f93a72b93872b3, 0xbc68c602211c7544), + (0xb8dd598494fb4eb0, 0xbc35d4a3a29a7da9), + (0x387e1025298516ea, 0x3be0f3be0d4b8ee0), + (0x3829d1ee76262ed4, 0x3ba97a197d3cf12a), + (0xb7f42ff2642fd193, 0xbb52f220fc5e4bf1), + (0xb79a001d511e0971, 0xbb18bb200c3f6737), + (0xb75720aadc56d8cc, 0x3ac1a0fc9e585d08), + (0xb6f810019c65facf, 0x3a8449eb5d1ccd0b), + (0x36c0524fdb6e5bf4, 0xba2bc209d14d289f), + (0xb663781b8b017ac7, 0xb9ec816d53cd34ad), + ], + [ + (0x3c518b0303bbe2f5, 0x3fc931a5a0ae5aa0), + (0x0000000000000000, 0x0000000000000000), + (0x3c348c3f5f957887, 0xbfb919c8a3f203fa), + (0xbc0ef6b166c80aea, 0x3f602a38da6262a9), + (0xbc207165718dd6e6, 0x3f807ced48910819), + (0x3bc68f5ae1c2651e, 0xbf2900f33a00690a), + (0xbbc8c05ccff0a4b4, 0xbf31278d46fd153c), + (0xbb6f62aece58de7b, 0x3edb2595529cf1c7), + (0xbb731bd5840756d7, 0x3ed2f7c2d608e0eb), + (0xbb1f324b35355b3a, 0xbe7e212d2378b576), + (0xbb005c49ab958b73, 0xbe69f3fcf3638b5a), + (0xbab2a5d22fb87422, 0x3e144fbf0377cdfa), + (0xba636fc80c961f59, 0x3df82268e83f4ed0), + (0x3a40f5458ba7db6a, 0xbda26cc2b02dc737), + (0x3a2ce24e6964787f, 0xbd80418bae8bbc48), + (0x39b27ec279e7b798, 0x3d2812815e643e0a), + (0x39a36cf3023b50ff, 0x3d009b2ac849ff66), + (0x39133d4af08ad917, 0xbca7c55d0a6d0728), + (0x38de47b036357356, 0xbc7aa167b939df6b), + (0x3886507c635a91ef, 0x3c22645687164ddf), + (0xb88b93b25f237a68, 0x3bf137648ca710a0), + (0xb8159c0acc3fb928, 0xbb96ed64da2728ee), + (0x37e7e2b02a3ea356, 0xbb62564f89aafafd), + (0xb7a8f4b2647af4ab, 0x3b0789c5abd21586), + (0xb7722d480745c160, 0x3ad05f7f4ebd3555), + (0x37185f3d16f70670, 0xba7442d6813292c4), + (0xb6d2d55a451fd98e, 0xba38df199441f62a), + (0xb65428bef2d53556, 0x39ddaedad9d103ec), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc63db68c567283b, 0xbfc80781c32422e7), + (0xbc1bf83906fd50c1, 0x3f754eda697a0098), + (0x3c232419a9d405db, 0x3f9fbe6df840847f), + (0x3bd5a76a98bd9674, 0xbf4be318d61276e1), + (0xbbe633162d1131fe, 0xbf58efee4094379c), + (0xbb4139e1a56d06b2, 0x3f059145b4f0e4de), + (0x3b2db153b13f2cee, 0x3f0282d26a74c38e), + (0x3b48c60f3e751263, 0xbeaf56c29d9ad959), + (0xbb2ffef5e5f8ef91, 0xbe9fdd03174f902a), + (0x3acf87aa0c95189d, 0x3e4a44a7907fee59), + (0xbaded732eaed6428, 0x3e31df65332ab3e4), + (0xba6ed0d6f75e03b2, 0xbddc96e9cf361a43), + (0x3a2be09d928f0cb2, 0xbdbc3439f3fac67e), + (0x3a0894702a4e04ba, 0x3d65d38ae50afdda), + (0x39c847e4ec1195d0, 0x3d40833ea1f83461), + (0xb9816bc0dd8ea673, 0xbce8afb70fb3c9e8), + (0x395196a0917179fd, 0xbcbdda411e59ed8f), + (0xb8c4610e8c50f3dd, 0x3c65889665db09a8), + (0xb8d125a6e60383eb, 0x3c35792846a5c5e9), + (0x38475c9e6c26184f, 0xbbdde1c2aac4bc04), + (0xb834983a005c0922, 0xbba92deda741b574), + (0xb7fd331deb45d073, 0x3b50e62611579a41), + (0xb7b4d43c6fbeedae, 0x3b18898163cacd25), + (0x37345581502d5210, 0xbabfc6f37553b483), + (0xb72eac4aa67583bb, 0xba843147e449ee48), + (0x36a768c097b2d633, 0x3a293dd77e784298), + (0xb667f8f81d88a65c, 0x39ec7209a4872362), + ], + [ + (0x3c559364e26d93ec, 0xbfc713fc51664c74), + (0x0000000000000000, 0x0000000000000000), + (0xbc488077fd102b67, 0x3fb7049760cde490), + (0xbbff945ad3318fed, 0xbf58ef5f1cbe4874), + (0x3c0b034f6fcde568, 0xbf7e5f53caf3bead), + (0x3bcb16596420523c, 0x3f237b0b62ddadd1), + (0xbb7411414067003c, 0x3f2fd3bac08286da), + (0xbb66bf25df78108f, 0xbed5789803de3afe), + (0xbb30f115b8c73e8d, 0xbed1c0faa89993b9), + (0xbb1173613a4d69f6, 0x3e7845b49b0674ba), + (0x3ada42fc2e50738e, 0x3e6886872801396c), + (0x3a9cf261fcd9b5e3, 0xbe10b036779ac071), + (0xba8ed0f2c9abc118, 0xbdf7049d18354c88), + (0x3a3b53ce13beae6c, 0x3d9edd9d0fb2ebd2), + (0x3a01c67e454c422c, 0x3d7f44600957fa58), + (0xb9c8cf2dd5194971, 0xbd2486b1d6a91df8), + (0x39a50688f914608c, 0xbd0016025abd20b4), + (0x392da82dcfc4875f, 0x3ca498b3d1754fd7), + (0xb9082f62c6ce39c5, 0x3c79f47baf518ec1), + (0x38a6105821b4975c, 0xbc2029b685b728de), + (0x389216a765538354, 0xbbf0ddbdab448097), + (0x3830ae5354e24a65, 0x3b94667d2d37a045), + (0x38016f3b498e4738, 0x3b620a8a21b80dcb), + (0xb78daf501176b370, 0xbb052c2caec48eea), + (0x377fe5ca7bc39984, 0xbad02a81f53376b9), + (0xb714e540400d2a70, 0x3a7266275dfcd434), + (0xb6a1501fbef1dde4, 0x3a38a1141391318a), + (0x3672180bf6683e02, 0xb9db2e3c29487cd8), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc6d2f0105f3ce7c, 0x3fc62d94d97e859c), + (0x3bd10ece6e29b084, 0xbf70bf614807033c), + (0xbc37013075a066f9, 0xbf9d5f857a2a6107), + (0x3be49380eb03f78d, 0x3f46081b0b7fe572), + (0x3bfce3676d17b40c, 0x3f57307b03e248f8), + (0xbbabc5fb92b99e67, 0xbf0132c0aa83d0dc), + (0x3b962d899f08a704, 0xbf0154ed4598d2f0), + (0x3b436681f34b2420, 0x3ea94f64f476e615), + (0xbb2a69d5b51b6d77, 0x3e9e12725853a9fb), + (0x3aec161d9909f167, 0xbe4588c758dfc8ab), + (0xbade3ba8f2d73fb0, 0xbe31021cdd9b5f7f), + (0x3a7b80d7aefb24c5, 0x3dd7cfa7a6c26b53), + (0xba5b73dd1f1185ae, 0x3dbb0e011d23f5e3), + (0x3a0a3aee2b581931, 0xbd6276cc0fa65a6a), + (0xb9d2974c386cdc2a, 0xbd3fe92f0882b440), + (0xb982bfc89a29ddc4, 0x3ce53126d86bf487), + (0xb94dd068a7b1e2e7, 0x3cbd07f6c1993c8c), + (0xb8fb38430712c4a6, 0xbc62bc249a86f7c9), + (0xb8d065bd6a2ed972, 0xbc34ffb4f0789e1c), + (0xb854136ccbc577a4, 0x3bda504d6417aae1), + (0xb84be408189a39ee, 0x3ba8bd8d3bf76896), + (0x37eab1c3ced9a78a, 0xbb4e157fb142efc6), + (0x37a40d8e8cc67990, 0xbb1834ef259f93cb), + (0xb75167300d24b2f1, 0x3abc8e7b497b27c6), + (0x36d98f27f9bf4556, 0x3a83fd162f3a5584), + (0x36c5a4266d838510, 0xba26e0585c2f983a), + (0x366678ba75bc0bf4, 0xb9ec3d3ba73f49c5), + ], + [ + (0xbc5b858aeca267e1, 0x3fc56b97f8091ac5), + (0x0000000000000000, 0x0000000000000000), + (0xbc21d2a41bfc4c1d, 0xbfb560fcc8c08469), + (0xbbe6529450b1ff0b, 0x3f53fafa39618883), + (0xbc1ad54776e42e6f, 0x3f7c49141623372f), + (0x3bb39ecd4785a672, 0xbf1f69980694fd17), + (0x3bcc2a33b89df073, 0xbf2dc5f848aa9d34), + (0xbb7ed412867be695, 0x3ed178fc979b77bd), + (0x3b73a93300f0b087, 0x3ed0b494a4bafcc7), + (0xbb1a1471efd3f084, 0xbe73fc3884c2743a), + (0x3b0b5eabaa159e81, 0xbe673afb9fb4d844), + (0xbaa47c72ef2556f3, 0x3e0bd90346a3e0ed), + (0xba99f08140c074ed, 0x3df5f3bafb215b44), + (0x3a2ab2b535dc2fdf, 0xbd9a1c27c37569c8), + (0xba09f88e2bb9d462, 0xbd7e0455dbf9cc4f), + (0xb9cdb0302c98b2dd, 0x3d2199b19fcacda0), + (0x39851865cfbaca3e, 0x3cff1334609dc3bd), + (0xb8c2cd00a5fcb440, 0xbca1e37265d5ce04), + (0x38c8d0340828b4e4, 0xbc79353f1aee0a50), + (0xb897b28613de5d51, 0x3c1c68e4abc12011), + (0x388b3ab1625e378c, 0x3bf075c553243bdb), + (0xb82923cf876dbeab, 0xbb921f6f50442923), + (0xb80ef47dee3f5afd, 0xbb61ae48340c53aa), + (0x37a8614c654ed794, 0x3b02fdf33e2b9584), + (0x376126c601c703f9, 0x3acfcd13a6548328), + (0x371d5986e5068b9e, 0xba70a5f4affbe604), + (0x36c041d0dc32e320, 0xba384ccca4432680), + (0xb652e0a78e43b84d, 0x39d8c95636d09811), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc5e9088e9ff2518, 0xbfc4b2a38f1ab9b4), + (0x3bf658189763e4b9, 0x3f6b3878aadeb34d), + (0xbc3525fe797e2126, 0x3f9b750d89a9b35f), + (0x3bb2c48be700f9e6, 0xbf41f6911725a956), + (0xbbed0a355d52c196, 0xbf55beee6fd51c8a), + (0xbb8079c92f6ce1f4, 0x3efc3625d7a65089), + (0xbba1cffb5ca00bc2, 0x3f005375a588a72b), + (0xbb398a011960416e, 0xbea4ee5e4e7cb18b), + (0xbb2804ad812748e6, 0xbe9c7b3d81b5ff94), + (0x3aea91d5277c5345, 0x3e41fce14f48518c), + (0xbadb70b3ae1d3fb1, 0x3e30346643c9d86e), + (0xba7397dad107b33b, 0xbdd41c861bc1c34b), + (0xba5410a8098eafad, 0xbdb9eeda214eabbe), + (0x39f8372842605aa2, 0x3d5f8cf277ce6338), + (0xb9de510926654c46, 0x3d3ec46e14cd5d9e), + (0xb962703fb3cb397d, 0xbce2500181b463c7), + (0xb95b2c04b73484a3, 0xbcbc24c2b350e45a), + (0x3888f6781f273b56, 0x3c605d9c149f1b8a), + (0x38d31e5cc968c925, 0x3c34752e1249314b), + (0x387b7657eab8f7e8, 0xbbd73842b12b31ea), + (0xb846e57a01049463, 0xbba83594fd823055), + (0xb7e962546fd68b46, 0x3b4acb92f062a2fd), + (0x37beb28a448a691b, 0x3b17c779242729e1), + (0xb7536df5c047d7ba, 0xbab9a6de3d6e1877), + (0x36e0ce403e109088, 0xba83b3c68747091c), + (0x36bd2b9ab8c7eb26, 0x3a24b55c31763430), + (0x36831011a1450327, 0x39ebeab3c6cb6a58), + ], + [ + (0xbc4d00ae4313eed0, 0xbfc413644356a52b), + (0x0000000000000000, 0x0000000000000000), + (0x3c2e7840863e7c03, 0x3fb40bb88c6f2b85), + (0x3bd5631193c7aba5, 0xbf5078d13cfc400e), + (0x3c1a406bffcdbe35, 0xbf7a9191262ab9d5), + (0x3bbe2809cb431b0a, 0x3f1a005297618f35), + (0x3bc92fd90e2b1396, 0x3f2c0cbad847a60e), + (0x3b6faeaea4946f0f, 0xbecd1a72e7c35fd8), + (0x3b6a2e571e6832b0, 0xbecf9a2654099c40), + (0x3b14a1a09cd63457, 0x3e70c6b06e20fcbe), + (0xbb08c15da7295060, 0x3e66136d6425ea74), + (0xbaa9c15db46970d1, 0xbe07977677c6badc), + (0x3a91f266c960af6f, 0xbdf4f77b3143a31f), + (0xba2ade992d25ffbb, 0x3d965720b0a36de3), + (0x3a0635bc57fc436d, 0x3d7cd126dc5db8d4), + (0x39b0b42ceb8837b9, 0xbd1e6d575a54f608), + (0x399c1abf000da8a7, 0xbcfdfb4d0beacd2f), + (0x3926e0efc20cf902, 0x3c9f3cccbe3a6b08), + (0xb90208f2daceba75, 0x3c786f5c7a82aa3d), + (0xb890e01b243ac14b, 0xbc190b8ec99be279), + (0x386588585f7010ee, 0xbbf0061c1563865c), + (0x3839090c97be6541, 0x3b901f2cce387f59), + (0xb808c405323747f4, 0x3b61476b2aa5f9cd), + (0x37aa73fdd9180681, 0xbb010995cf568203), + (0x376999ab5e964dc7, 0xbacf2f8eadcda35c), + (0xb6eef0a26c086d84, 0x3a6e19ecc98ab1c0), + (0x36cbb3d7e3e4912f, 0x3a37e713fd44413e), + (0x367917d21157a7a9, 0xb9d6910a2ab8996f), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c4997782859a00d, 0x3fc37aaceac987b9), + (0xbc09de167b0f4e45, 0xbf66afe4fe0bc0f7), + (0xbc3d91e80a0529b8, 0xbf99de7a33bc3a97), + (0x3bdacaad4f266959, 0x3f3e024f567ac487), + (0xbbf5aee36a6b58af, 0x3f548843c426abe0), + (0xbb8ed7ac2e5eef51, 0xbef7a8e14711c0f5), + (0x3b9b3675770103a2, 0xbefeeceb341ad833), + (0xbb4d96e3726387e9, 0x3ea1a743e05b39ca), + (0xbb36e8969001b255, 0x3e9b143d39c90dd5), + (0xbad319f8c4237007, 0xbe3e8e00012321d3), + (0x3aae89c8a788cf46, 0xbe2ef28e323e7496), + (0x3a7f30cb64f4f0d2, 0x3dd137a1bf5bde2c), + (0x3a5bf7dee3b649de, 0x3db8e087c7cb7f1d), + (0x39fb7806a5d33650, 0xbd5b3dc9dd36d846), + (0xb9c8eb799dd68c33, 0xbd3da6ae03deea14), + (0x394156b16e9a68f1, 0x3cdfe64e83599736), + (0xb93c20b358422ecc, 0x3cbb3e899a8275b8), + (0x38e23edcbf53670c, 0xbc5cc15471c3a791), + (0x38d6153c40fa8364, 0xbc33e34956740ffd), + (0x387da1d09b7c1150, 0x3bd491cabcac2ce3), + (0xb84c9d6b2a07c067, 0x3ba7a07e1fc0dd64), + (0x37bbd51dd0af2201, 0xbb47ecb9d1547f7f), + (0x37bc94c2359a7968, 0xbb174a2cfb1be55e), + (0x375ec790d520dd3c, 0x3ab712c909b7eb19), + (0x3721fa30708a2d3f, 0x3a835bca00a6162a), + (0xb6b4073920a6f8c9, 0xba22c13871e75a28), + (0x368fbab0e8ced2dd, 0xb9eb82223e5c0791), + ], + [ + (0x3c4f123683cf20a8, 0x3fc2f4e70d6c7e01), + (0x0000000000000000, 0x0000000000000000), + (0xbc5702b97938a87e, 0xbfb2ef24d6f7526a), + (0x3be17c9efd9928a1, 0x3f4bc33c9dc6ec82), + (0xbc153a673a682d1a, 0x3f7920414ee2acbe), + (0xbba8c8602e5501dd, 0xbf15f9173916a219), + (0xbbbd01332ea23750, 0xbf2a94fdbdcec471), + (0xbb6340ead67ee8d4, 0x3ec8b309990f950c), + (0x3b62bfaf2a2bd5b2, 0x3ece087ff4517c02), + (0x3b05bdd16bb39ef5, 0xbe6ca22ab12cb4b7), + (0x3ad4981496e99ee8, 0xbe650d1f28635cda), + (0x3aac3cc89e59b451, 0x3e04441552e259a7), + (0xba95d08c5f0c93c3, 0x3df411b8a8258957), + (0xb9eff3ddb842e46e, 0xbd9354e914c31b45), + (0x3a11319e6211da5e, 0xbd7bb16f111ebae7), + (0x39af5cff5d440351, 0x3d1a888536e27439), + (0xb9967f728b3f0a85, 0x3cfced726c1026c9), + (0x39328206ff6f6ec6, 0xbc9b745d75ff6377), + (0xb91cb1d8bb8b1e84, 0xbc77aaea63220bec), + (0xb8b1d26bdb3cb23f, 0x3c162ef6548b0ef1), + (0xb85086d51f21de1e, 0x3bef27eac447efa0), + (0xb81b0359e4922880, 0xbb8cc635a651ed03), + (0xb7c265c1a580ae14, 0xbb60db1d9fbb3868), + (0x379bfffc557e0311, 0x3afea050ba5a6c00), + (0xb7616b89acbe6940, 0x3ace84aeda9b4b7b), + (0xb690317b7234e3f2, 0xba6b3ca6e927e7ca), + (0xb6d96744c0e38388, 0xba37754b584db1b4), + (0xb67873c14331a4ce, 0x39d48c23ea283d56), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c6b7326e3fbaa70, 0xbfc2740819f1caaa), + (0xbbad91d196951b1e, 0x3f6349369dc780bb), + (0x3c211249d3675d98, 0x3f98868d7401bf2e), + (0x3bab901426ad555e, 0xbf398cd1bebe1445), + (0x3b8e845cf46e9c36, 0xbf537eef9aadeee2), + (0xbb978bd7232789d5, 0x3ef43394c95b2d2b), + (0x3b98d34686b724d9, 0x3efd6dfcdb026028), + (0xbb39039620a1668b, 0xbe9e448fbc8a1f43), + (0x3b1ab8335f5b2e44, 0xbe99d764ee07c839), + (0xbad24a385ba857b8, 0x3e3a53958c8d74ff), + (0x3aae692fcd7541f7, 0x3e2da0e1c8a08d37), + (0xba682664a5ef0aa2, 0xbdcdd7f918de776f), + (0xba55452efda66af5, 0xbdb7e68037d5c861), + (0x39e92d13e5b8bdbb, 0x3d57c2e63bbe27ca), + (0xb9b76fb98c811c8b, 0x3d3c973a175ffbb6), + (0x3961655ae92c79f4, 0xbcdc033788921736), + (0xb93459b0496214b2, 0xbcba5d9f2bdd8af3), + (0xb8c9fbdcd265117f, 0x3c596cb946e78db0), + (0x38ca3b3e172d732c, 0x3c335090afbe104f), + (0xb87ce7df25d16bb8, 0xbbd24f9089431e12), + (0x38470e95a1733e58, 0xbba7060105333e1d), + (0x37e148c26a9d2e03, 0x3b457032c08fa72b), + (0xb7bcc5adf699f555, 0x3b16c43d570a329d), + (0xb7472f3277e653fc, 0xbab4ce5eeb2252e9), + (0xb72e4e66be44e7f5, 0xba82fa99d3f60727), + (0xb6c49cda263bbcc6, 0x3a21035a54fa4f71), + (0xb682adf1bab34466, 0x39eb0a7a1202f74d), + ], + [ + (0x3c34f78a7cfd8a8a, 0xbfc20198200b699d), + (0x0000000000000000, 0x0000000000000000), + (0x3c1ede75d6e0c0b0, 0x3fb1fd242a74e630), + (0x3be31a446a0673c4, 0xbf47cf261dfbf19a), + (0xbc0b11e38b0823f1, 0xbf77e4820ec1dde4), + (0xbbbbba7e6db23817, 0x3f12e1bd281dfcbb), + (0x3bc48aed48d0a248, 0x3f2950bb06c6fdf9), + (0x3b5f50566d2c2881, 0xbec54a38ab6af546), + (0xbb69fdc0d6c27c0b, 0xbecca94f38024fdc), + (0xbaf76dde5144d48d, 0x3e68c7e75971c85c), + (0xbb0678751b2ddc2c, 0x3e6423fc7e251ca9), + (0x3aab4294ffe166f7, 0xbe019fe1d8e51b96), + (0xba976b836ebd0291, 0xbdf34198c795142c), + (0x3a1b6fa7e1df9192, 0x3d90e78cdab26dd9), + (0xba1a2a34bc1f8645, 0x3d7aa74cb5ba4b0e), + (0xb9a65f2dd9b4219b, 0xbd1756ee8369797d), + (0xb98cae4f94465269, 0xbcfbee3ccbac62a4), + (0xb93edac05af99c66, 0x3c984c93627c1364), + (0x39192f873368f6f8, 0x3c76ecd2977e750f), + (0x3893a3df310cde1b, 0xbc13c1ad2197e738), + (0xb83e79b62fc45f90, 0xbbee45c9096ecdab), + (0x3808f4906192c428, 0x3b89c8e8d1127213), + (0xb7d635517d589b2c, 0x3b606d492670f0ba), + (0xb772bd51822a155e, 0xbafb9c058bf87bc8), + (0xb755af5326fb8ade, 0xbacdd33a39371327), + (0xb6fa0c8a817bd238, 0x3a68b21edf0d733b), + (0x36ce1e27351bb092, 0x3a36fc3cd1a4c613), + (0xb678b7b2ca8c7003, 0xb9d2bb8db2dfce26), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc4081c2a50ad27b, 0x3fc192f2627a74e3), + (0x3c06268e5916da13, 0xbf60a846a83fecf2), + (0xbc1be434e30d7a64, 0xbf975eceaabf7f86), + (0x3bbc2d7f1eb14a8d, 0x3f3617c581be35b1), + (0xbbb0beeca29a2b7c, 0x3f529934b7a84483), + (0xbb91b58b66aaaf71, 0xbef18123e875188a), + (0x3b94740ce7aaa9f5, 0xbefc1f05a2d85165), + (0xbb3fd873b639f93b, 0x3e9a4e0bc0926545), + (0xbb233d21389cb3a0, 0x3e98be81ad44d933), + (0xbabb1f9cab4acd40, 0xbe36f73795e25c01), + (0x3ababafdeab2d269, 0xbe2c70ab158cd19a), + (0x3a5796ce7385bd76, 0x3dca262190472d9a), + (0x3a444e202e2ab843, 0x3db70112aab52bc2), + (0xb9f5bd722355d797, 0xbd54ec163f88c02f), + (0x39d5477d64dc86b2, 0xbd3b991575a9daff), + (0x39314b432a7313b8, 0x3cd8cbabadfd45c5), + (0xb953683d210d31e2, 0x3cb9867f1ea8526f), + (0x38f1cbbb05b76a2a, 0xbc56a0c58ce9652e), + (0x38dd3e4ed9b9011d, 0xbc32c10fa17839d7), + (0x387159e93c92ec73, 0x3bd06304545a75ab), + (0x3831184208b9509c, 0x3ba66b5f3f801768), + (0xb7bf7ef3af29f9f4, 0xbb434a75e18850f7), + (0xb7b72f867bfa08f9, 0xbb163af2240f11d6), + (0x374e71e41ce0bd04, 0x3ab2d27f5aad2f87), + (0xb70e338eb53b4d25, 0x3a82947c379d043b), + (0xb6a879620ef8dcbc, 0xba1ef0cd1e11d5d6), + (0xb68cfba8dcf4726a, 0xb9ea897622f547ac), + ], + [ + (0x3c68f71f103b6bf8, 0x3fc12f9870d68e18), + (0x0000000000000000, 0x0000000000000000), + (0xbc5fd0d25668ad6b, 0xbfb12c11811945f9), + (0x3bebc70ffc015b97, 0x3f44b638f21f0f76), + (0x3c1bc10a4e0506fd, 0x3f76d2a897d58353), + (0x3ba5de76c7b42be1, 0xbf10732e5458ba20), + (0x3bcfca03362738f1, 0xbf2835929300df3f), + (0x3b4992f62f113a88, 0x3ec297283816a83b), + (0xbb50d6dea529ee4f, 0x3ecb73adedf11a43), + (0xbb0dce80931068a0, 0xbe65b455b903f09c), + (0x3b029572874fb52c, 0xbe6353f0797a6699), + (0xba8bf23ef2ca5a38, 0x3dfefc9ac17b1eeb), + (0xba878bfeeecafab3, 0x3df28535463ce067), + (0xba096b62f6b59354, 0xbd8dd894cbbee3f9), + (0xba0f655d10343892, 0xbd79b288cc392b5b), + (0x3986335c7e33b227, 0x3d14b2ec9ace070c), + (0xb998edce804ba0e3, 0x3cfaff72f6057832), + (0xb936e4ec62dfa238, 0xbc95a7bfada02748), + (0x39060aebd6f74bda, 0xbc7637b7b45ad224), + (0x38b5e34b545164b0, 0x3c11b216f1fba65d), + (0x387400818419c16a, 0x3bed6a4aa25cbcad), + (0x38222d3819e4ad1c, 0xbb873661259c7b49), + (0xb7c47385cbfe72a2, 0xbb6000a243c0a825), + (0x3790aa941ed924d2, 0x3af8faeb08a0872d), + (0x374285ea5fb533a8, 0x3acd2042259aeb3b), + (0xb70ef65d241a95c5, 0xba66742de4a4a980), + (0xb6dbeb8e3fb1ee6a, 0xba367fbd4af52810), + (0xb666550a2bc73761, 0x39d11cea7748dd35), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c60c06e2860e868, 0xbfc0cf3ee98f769b), + (0xbbfc2c390327e0f7, 0x3f5d26e7af251f79), + (0xbc394225ed089995, 0x3f965d05948a946a), + (0xbbcb3460aae30c17, 0xbf335959b8482e40), + (0xbbf744279fabe84a, 0xbf51cff175d05c2a), + (0xbb83714c1d2b4ff3, 0x3eeeb59416879106), + (0xbb89158b4542d2c4, 0x3efaf7544eeac766), + (0x3b284917e9900e02, 0xbe9720522bb1fc81), + (0xbb31671693e842ab, 0xbe97c41261705419), + (0x3a886ab60cf89699, 0x3e343fa0ea5e007d), + (0xbab8f90fa25a8f71, 0x3e2b5e23abebd7a4), + (0x3a64e5cdf3a099a5, 0xbdc722397e750312), + (0xba51768b235cacdf, 0xbdb62f2174e6be49), + (0xb9fb8faac380f50e, 0x3d5294ab060a163a), + (0xb9de9b0cd3f3a20f, 0x3d3aace944141c61), + (0xb96472a1bdce3160, 0xbcd61cc8146cdfa2), + (0xb9583fcfac500424, 0xbcb8bb3c270a284c), + (0xb8f56040266e6114, 0x3c54449d96647c28), + (0xb8c4997de83d7967, 0x3c323712fdd32979), + (0xb84d0513eb7ddb33, 0xbbcd7cedd05f23ee), + (0xb8138c0b1312b9f5, 0xbba5d3f2f4d18257), + (0xb7d6343b2af8488e, 0x3b416f9a8cd62e2d), + (0xb7b741512b4836ab, 0x3b15b1f1d821a3b4), + (0x375de94b9017c7ec, 0xbab116d887db5467), + (0xb720b9ee354d1861, 0xba822c96cd78a74c), + (0xb6b7416d012e04a4, 0x3a1c3754078e6137), + (0x3688b4af62f8f0ae, 0x39ea0388f41538a5), + ], + [ + (0xbc6742aa46ea9b31, 0xbfc077eede4a0d89), + (0x0000000000000000, 0x0000000000000000), + (0x3c3cabc5883fc763, 0x3fb0751548b2924d), + (0x3bd8c3b817f5bd1a, 0xbf423b5d46a73864), + (0x3c1e7b0b0210cbce, 0xbf75e2467c8fb832), + (0xbb9abdc3996174ac, 0x3f0cfe5c189d6e4d), + (0xbbcf4c0c63a8394c, 0x3f273bbd8c7aef2d), + (0x3b6d9272577eb6ff, 0xbec06974d3d04287), + (0xbb56fb637949537f, 0xbeca6081d36e6a2b), + (0xbaee9b9b25b5c745, 0x3e6334a83cf6092b), + (0xbb0e3539c19e4313, 0x3e6299571cb4e1fb), + (0xba80b2cd2f45d38c, 0xbdfb7f5bc0aada50), + (0xba81831c37e0afc0, 0xbdf1da63b4d6f878), + (0xba03f6e20cbba970, 0x3d8a9288ceccd9f2), + (0x3a17055344e86eaa, 0x3d78d1d74c88ee4c), + (0x39a439e54f23f947, 0xbd127eed3a482d7f), + (0xb9766b420f9bcda0, 0xbcfa2143706ccb79), + (0x3933ce1edc9f0854, 0x3c936d1464c4bf11), + (0x3907d2e3e5d4bfa8, 0x3c758cc3ad07daa3), + (0xb89bcc0a4f099447, 0xbc0fe0c8ce969c5e), + (0x38838ca595ab732b, 0xbbec97f785528e08), + (0x3821507942984ee9, 0x3b84fee6252fe140), + (0xb7df46f0f7734483, 0x3b5f2dcbce169f1a), + (0x379086aaae683dab, 0xbaf6b095bc2831d4), + (0xb76de10fe678bda7, 0xbacc6f522af04f90), + (0xb703ee192a62f4f4, 0x3a647af3c1c3a557), + (0x36d76dc7bb35ad50, 0x3a3602a9d860d2a3), + (0xb66b7ac21c3ed2e5, 0xb9cf58721d5d6786), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c61166b7995967a, 0x3fc0230ba90f2871), + (0x3bfb746b17280b83, 0xbf59ca16f0c9734e), + (0xbc375b99fcae0fa4, 0xbf9579c1bdbcfc99), + (0x3bc1259c7efa1ad5, 0x3f3120ecfac5c017), + (0xbbd35a76e06cda58, 0x3f511dd26bbe2946), + (0x3b72ed405d5bc473, 0xbeeb37e7c9a57149), + (0xbb86e93d7c515f0c, 0xbef9f01e7c1909a0), + (0xbb2f562d62e60e11, 0x3e94887fe7a88c2c), + (0xbad010f87629f8e9, 0x3e96e37238841d4b), + (0xba99b7f19b7b3b20, 0xbe3204b644d6a04b), + (0xbacc8fcda8a1a29b, 0xbe2a659b13eebf8a), + (0x3a42b743f24d4d7e, 0x3dc4a40c87601c97), + (0xba577207717e09cd, 0x3db56f0250e4fcac), + (0xb9f8225d38237f55, 0xbd50a1011bf4a7dd), + (0x39d5262f16494ab9, 0xbd39d22a6dc5a57c), + (0x397bb4017d6e9239, 0x3cd3db0f19da31da), + (0x392600d1fe84f91f, 0x3cb7fc7d4070961b), + (0xb8c183aaceabe7cd, 0xbc5243aa7bbc81ca), + (0x38c5abd4abae47a9, 0xbc31b3c3dd0d783d), + (0xb86b0ca32f2b28ba, 0x3bcaabdcaba1878d), + (0xb83fe00611a5322d, 0x3ba541bb402b78f0), + (0xb7d85111e57bb4b2, 0xbb3fa915cdaddb2d), + (0xb798d2801af024f8, 0xbb152ba16ad63ba9), + (0xb7344e83ea6e82fc, 0x3aaf26322e6939a3), + (0x36eecf18659e6ff5, 0x3a81c51fa64eb3db), + (0x36ba22c423e879e5, 0xba19d00760b94df4), + (0xb6523572ecb98917, 0xb9e97bff11d536c1), + ], + [ + (0xbc446154ab44acb3, 0x3fbfab0b166d23d8), + (0x0000000000000000, 0x0000000000000000), + (0x3c4290cc8b89531c, 0xbfafa65c1ce7ebd6), + (0x3be9bdd7d19e67a3, 0x3f4035bf503ffc1f), + (0x3be801473cc85f32, 0x3f750d1b04713c41), + (0x3babe22a416a82d0, 0xbf09cd14a92842a2), + (0x3bca868e6f4e4828, 0xbf265d504af5d8fe), + (0x3b5814b5b963313b, 0x3ebd3feeb33d9cee), + (0xbb4c05f6b4f39a25, 0x3ec96a257062f76e), + (0x3b0b04fde272af41, 0xbe61254f302b36b2), + (0x3ad771b26251f405, 0xbe61f11585e04fca), + (0x3a8b3d53767b22ba, 0x3df89a7674dd98cd), + (0x3a7b6db02fadeed1, 0x3df13f0ba48c1692), + (0x3a248f4db1fc6761, 0xbd87d67b47fd268e), + (0x3a0a84c861831984, 0xbd780381812ad9b0), + (0xb98981455f0897cf, 0x3d10a41213b1209a), + (0xb98573618414b59a, 0x3cf9530714f8af8a), + (0x393f79d60d660532, 0xbc918884a9ff4796), + (0x3912da336a20734e, 0xbc74ec3ce9f29027), + (0x3896c9321058ffc6, 0x3c0cde4ce08c6119), + (0x38894686518435ab, 0x3bebd00bdae20153), + (0x37ff64113a65f339, 0xbb831454d0bd6f49), + (0x37e88cc5762134d4, 0xbb5e623854cff634), + (0x3793b39a55f6f728, 0x3af4b117674c743f), + (0xb76c32187c451ad3, 0x3acbc2c0ede2286c), + (0xb7077e3bc9fbf218, 0xba62be3ca56b47a4), + (0x36dcde9bceca3e29, 0xba35870a752de79f), + (0x361b91f4f1f1a50f, 0x39ccc9aaaa2d7785), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0x3c50db2c50623ec0, 0xbfbf13fb0c0e6fcd), + (0x3bf63fd50ee5b7c3, 0x3f5706ed3d935d00), + (0x3c3a7c91ef9a7da1, 0x3f94af74cbd77bef), + (0xbbac31e3b8ee4b9e, 0xbf2e9a9e66e5a792), + (0x3bf35ae9733a6eb6, 0xbf507ec9ed824fcb), + (0xbb4a1610320898f4, 0x3ee856d4518ab29e), + (0xbb9af9c37c81d002, 0x3ef9040de830649e), + (0x3af6ec0adcce1274, 0xbe9262f69c56c652), + (0xbb34da0db90f5974, 0xbe9618c94a54734d), + (0x3acfc6bc581d66ff, 0x3e3029d2c8bf70d6), + (0x3ab60f30da5c2b13, 0x3e2983bca0a3e67c), + (0x3a60395605657e5e, 0xbdc28e2a00002a82), + (0xba51c639ac25ee1a, 0xbdb4beeacafc4fad), + (0x39ed7df744a0b21a, 0x3d4df880e37a5060), + (0x39d1f98cd4e6ac14, 0x3d3907be43054aec), + (0xb95bcb238e3393c6, 0xbcd1f10ff685083d), + (0xb948ad06b5e0f6af, 0xbcb74a1dc71abca4), + (0xb8f9b8f70559bd9a, 0x3c508d41117c93a5), + (0xb8b35b059841e08e, 0x3c313795880a7796), + (0x3865f51a8e31e18f, 0xbbc83ea1cebb3c84), + (0x3838606560ae8152, 0xbba4b5cc8ded02e2), + (0xb7df776dd1580636, 0x3b3cdf002471ce45), + (0x37b71f6e27bbe64e, 0x3b14a97cafad6c19), + (0x374d40fd5c1285de, 0xbaac7f1793e7126e), + (0xb6f7da220c547e42, 0xba815f93ab822e98), + (0xb6a0911cfb822772, 0x3a17b0d93bc7bbc8), + (0xb6846b70143e3a42, 0x39e8f533a6e89c51), + ], + [ + (0xbc5bf01bf61d8ed3, 0xbfbe891b327da16d), + (0x0000000000000000, 0x0000000000000000), + (0xbc3636379e4f582e, 0x3fae8533ce07bdb8), + (0x3bc53b9dd0e187fa, 0xbf3d1253218e31b0), + (0xbc1eae521e3467c6, 0xbf744e6826476498), + (0xbb6864ec60e7a724, 0x3f07271a9b5e3cb4), + (0x3bace83941ef46ea, 0x3f2595b697c8ec04), + (0xbb5f57ab96615e4a, 0xbeba46b03ecb38cc), + (0xbb4dc38fda916c56, 0xbec88c173e07621e), + (0x3add237c79a7a74d, 0x3e5ed9b1754fbd3c), + (0xbb0d6748ba8d2dd7, 0x3e615891ef314e18), + (0x3a8caeca005426a6, 0xbdf62ca352cf904e), + (0x3a7916c3c0550fc0, 0xbdf0b14767c2b010), + (0x3a25951d764f773e, 0x3d85879bb4a2a8ac), + (0xb9f96759cfddd4b5, 0x3d7745bbca5b0e82), + (0xb99c649f85048056, 0xbd0e21736ab8469f), + (0x399387632a0c4eab, 0xbcf893b256068d4e), + (0x39225636fb1c995b, 0x3c8fd42c80d0363c), + (0xb919336e177a135c, 0x3c7455e80611a38d), + (0xb894f0ece16e6c03, 0xbc0a4682da825109), + (0x388f20cb0640e817, 0xbbeb12f0bb38aa78), + (0xb7ff5df786b91715, 0x3b816a7f586e7ed5), + (0xb7ff8ddcae160d2a, 0x3b5d9fa09d2f4601), + (0xb7808a35f4fc1e15, 0xbaf2f1ad1590d095), + (0x373f1307c6b6dcfd, 0xbacb1c0038406c42), + (0x36f40bb96d08f57f, 0x3a61363c85b6c4db), + (0x36cb8e8704706c26, 0x3a350e3e866a311e), + (0xb666cdfdf4125dc0, 0xb9ca841b08aca0a3), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc3b9f1d130797af, 0x3fbe018dac1c17e3), + (0x3be072789a66cf0c, 0xbf54b994dd05c1fb), + (0xbc338b4f0d3a4111, 0xbf93f9e0db07e7ef), + (0xbb9a899561323713, 0x3f2b8e55b75b13ab), + (0xbbd251fa83bbf98d, 0x3f4fdf68a78bb3d2), + (0xbb783beff5b1db62, 0xbee5ee9d17106a08), + (0x3b70935ad53575b8, 0xbef82ee6dfdfedeb), + (0xbb36eeb8b4341708, 0x3e90962d7f6d61a6), + (0x3b3ddb699c127f13, 0x3e9560edce7d682d), + (0xbaadbe6f075c9b8e, 0xbe2d34381d02bdbe), + (0xbab5faefe806c858, 0xbe28b5a0e74ae0d3), + (0xba651c26d41110d4, 0x3dc0cab953f05720), + (0xba4cdfa2ed9741f0, 0x3db41d21c68d7ed3), + (0x39efbfd30004913c, 0xbd4b2d2dd7cb3c52), + (0xb9d97fd3cf0000fa, 0xbd384c5369d2e33d), + (0x3968bd8125247874, 0x3cd04e17ab25ece9), + (0xb928ec3a9bb7352b, 0x3cb6a38e0aef9402), + (0x38ed2d1073a2c3f0, 0xbc4e28099fc927bb), + (0x38d2c69d895d6715, 0xbc30c28e6023fb13), + (0xb8509810eebec087, 0x3bc62487323559ca), + (0xb84607b5c3508235, 0x3ba430a24f21f4b6), + (0x37dcd1d9a6fb187a, 0xbb3a70372a5a35f5), + (0xb7ba9055f83c1a46, 0xbb142c5d07f39eeb), + (0x3747d181d0f16b66, 0x3aaa2aaf684b8a30), + (0x371c65863116b54e, 0x3a80fce718ed7a5e), + (0xb6b4123df1746b77, 0xba15d07c57e5f8fc), + (0xb6898be9e1a577c3, 0xb9e870c605b22513), + ], + [ + (0xbc4d7a7b8d722118, 0x3fbd84391bb2748d), + (0x0000000000000000, 0x0000000000000000), + (0x3c4b439a88ed803c, 0xbfad80edb3c4ea05), + (0xbbd902d343595b94, 0x3f3a431f5421f7ef), + (0xbc13a66c5c4dc37b, 0x3f73a282fe7b63a8), + (0x3bacf6f60b03558d, 0xbf04ed653e607bdd), + (0xbbb378680e9561c9, 0xbf24e15832bda3c4), + (0xbb5464c53ca44363, 0x3eb7c5832dd1374f), + (0x3b40f0848ee7f0af, 0x3ec7c2b80da8df98), + (0xbadb963cfc74e722, 0xbe5bf160ccd35445), + (0xbac9dbc6baadaa9d, 0xbe60cda2141b2a1e), + (0x3a876692ed94eb99, 0x3df41d31d2a419e4), + (0xba8205fd4d4f295d, 0x3df02f6ca850168a), + (0xba12525d1774cdfa, 0xbd83901f61054085), + (0xba17ee02df9f104d, 0xbd7696ce2b748d02), + (0x39ad0bfbcbf0de66, 0x3d0b6e82997a390e), + (0x39911978fd395acf, 0x3cf7e214796bec19), + (0x38f14ad6e06bfc76, 0xbc8d0a3822eede44), + (0x38ea8d322da40464, 0xbc73c944a2b7aa9b), + (0x38a984e57b8c632b, 0x3c080748c2fd3ed7), + (0xb88ca608783691d5, 0x3bea608ebfb61101), + (0xb7fd3b588ddf9629, 0xbb7fee483d06f76f), + (0x37f5b0b20d62c293, 0xbb5ce67588df7595), + (0x37950cdd33b84f9d, 0x3af168f59e870bd0), + (0x376249d762f468f2, 0x3aca7bdf85923387), + (0xb6fefd0fec5de258, 0xba5fb7c898747d3e), + (0x36de35ad136a6653, 0xba349926b4cfc177), + (0xb6321892fca8dd05, 0x39c87ee43e8319a5), + ], + [ + (0x0000000000000000, 0x0000000000000000), + (0xbc56edd809f4ec43, 0xbfbd09b21e36c0bd), + (0xbbfd63853cd1251f, 0x3f52c84acfb586b4), + (0x3c340975d5184af6, 0x3f9355b904fbf7ee), + (0xbbc2e53f276aee1d, 0xbf28fb570465af0d), + (0x3bdedf2b372334ad, 0xbf4edc3292ba6cfd), + (0xbb81b7d6d1c233d4, 0x3ee3e552ee8c2577), + (0xbb9b6ea46d6db74f, 0x3ef76d44f6a83523), + (0x3b2fdb93f3ce1be4, 0xbe8e1ee2dc4a3bda), + (0x3b3cccd4251153ff, 0xbe94b944bbd4c7bf), + (0xbac468738fc1e577, 0x3e2a8c3a4ce36f16), + (0x3ac2a4a12f818a06, 0x3e27f8c9ef47068e), + (0xba40acae788b04d5, 0xbdbe9295749ee471), + (0x3a1164a101ab66dc, 0xbdb38813c3eb77e4), + (0x39e5c1a4e6a441fe, 0x3d48c7cda44b7754), + (0xb9a073f8f8b180ec, 0x3d379e90468589ab), + (0xb96fed4f7bb5b2dd, 0xbccdca323fb2ed13), + (0xb95878df442a1f61, 0xbcb6080be2ba756c), + (0x387f1fa3709d7eff, 0x3c4b9a8e33ba54fc), + (0xb8dc56a14b4f3362, 0x3c3054766d105243), + (0xb857137346804b31, 0xbbc44fda8d0857c1), + (0x384bb0403ea0d8f3, 0xbba3b2575150baf6), + (0xb7a85fe85251016c, 0x3b384ea306ad146b), + (0x37b304a7ebd0a72a, 0x3b13b4adf072996e), + (0x3748b8e00542081f, 0xbaa81d1af5c14291), + (0x372aac7dc3b524ef, 0xba809dac6fd771cd), + (0x36baf45596c923ee, 0x3a14269f3ec695f6), + (0x36759ddc6feb07d0, 0x39e7efc8823b70ff), + ], + [ + (0xbc579e384ae35818, 0xbfbc97d79918527d), + (0x0000000000000000, 0x0000000000000000), + (0x3c415f3ee939a0c0, 0x3fac95081ab2b511), + (0x3bd3c58af0675f79, 0xbf37e0b14f7d7c3f), + (0x3c167e93b7727b21, 0xbf730688f6836a76), + (0xbb9eaad919470a89, 0x3f030941f6e78e36), + (0x3bb70db1e3b31015, 0x3f243d5898657a6f), + (0xbb39f8046976f799, 0xbeb5a39a94f2ad54), + (0xbb5db47207819abe, 0xbec70b18406146f7), + (0x3af60534adb9126c, 0x3e597607f9532274), + (0xbad703287fac9a7c, 0x3e604e788f4f63b9), + (0xba876fad0fcbbb39, 0xbdf2598919473e7e), + (0xba640135e9b4a88f, 0xbdef70154273be01), + (0xba130237cf72ed16, 0x3d81df5c1ca3869c), + (0x3a1164e3491c1c38, 0x3d75f5256665e918), + (0x3995f76e145eb882, 0xbd091a176f7295bc), + (0xb9928726702a883a, 0xbcf73cf989310b2d), + (0x39202ef4e750363b, 0x3c8a9f0a04e769ab), + (0x38f077c349f5886f, 0x3c7345b205781db7), + (0xb8add8bb23d58463, 0xbc0611e4c0bb0b33), + (0xb87f88c08a95c014, 0xbbe9b88423fdad3a), + (0xb8109abefbf8e094, 0x3b7d637382cff4b7), + (0x37f703e341c86f9e, 0x3b5c36bddd0beae2), + (0xb7802c952716a8be, 0xbaf00eec29705267), + (0xb755facd187ba820, 0xbac9e2beddaac35c), + (0xb6e129db12cb1ab9, 0x3a5d51fa8552737e), + (0xb6cd627e8469503b, 0x3a342847a5dc8d0a), + (0xb66dc34aae9113ef, 0xb9c6b1f64bc800a0), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,353 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::j0f::j1f_rsqrt; +use crate::bessel::j1f::{j1f_asympt_alpha, j1f_asympt_beta}; +use crate::bessel::trigo_bessel::cos_small; +use crate::bessel::y1f_coeffs::{Y1_ZEROS, Y1_ZEROS_VALUES, Y1F_COEFFS}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::fast_logf; +use crate::polyeval::{f_polyeval10, f_polyeval18, f_polyeval19}; +use crate::rounding::CpuCeil; +use crate::sincos_reduce::rem2pif_any; + +/// Bessel of the second kind of order 1 (Y1) +/// +/// Max ULP 0.5 +pub fn f_y1f(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0xffu32 << 23 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0 + if ux.wrapping_shl(1) == 0 { + // |x| == 0 + return f32::NEG_INFINITY; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f32::NAN; + } + return 0.; + } + return x + f32::NAN; // x == NaN + } + + let xb = x.to_bits(); + + if xb <= 0x424e0000u32 { + // x <= 51.5 + if xb <= 0x40000000u32 { + // x <= 2 + if xb <= 0x3fb5c28fu32 { + // x <= 1.42 + return y1f_near_zero(x); + } + // transient zone from 1.42 to 2 have bad behavior for log poly already, + // and not yet good to be easily covered, thus it use its own poly + return y1_transient_area(x); + } + return y1f_small_argument_path(x); + } + + // Exceptions + let bx = x.to_bits(); + if bx == 0x47037a3d { + return f32::from_bits(0x2deededb); + } else if bx == 0x65ce46e4 { + return f32::from_bits(0x9eed85c4); + } else if bx == 0x6bf68a7b { + return f32::from_bits(0x9dc70a09); + } else if bx == 0x76d84625 { + return f32::from_bits(0x15d7a68b); + } else if bx == 0x7e3dcda0 { + return f32::from_bits(0x12b81111); + } + + y1f_asympt(x) +} + +/** +Generated by SageMath: +Evaluates: +y2 = -J1(x)*log(x) + 1/x * (1 - sum((-1)^m*(H(m)+H(m-1))/(2^m*m!*(m-1)!)*x^(2*m)) +Y1(x) = 2/pi*(-y2(x)+(euler_gamma - log(2))*J1(x)) +expressed as: +Y1(x)=log(x)*W1(x) - Z1(x) - 2/(pi*x) +```python +from sage.all import * + +R = LaurentSeriesRing(RealField(300), 'x',default_prec=300) +x = R.gen() +N = 16 # Number of terms (adjust as needed) +gamma = RealField(300)(euler_gamma) +d2 = RealField(300)(2) +pi = RealField(300).pi() +log2 = RealField(300)(2).log() + +def j_series(n, x): + return sum([(-1)**m * (x/2)**(ZZ(n) + ZZ(2)*ZZ(m)) / (ZZ(m).factorial() * (ZZ(m) + ZZ(n)).factorial()) for m in range(N)]) + +J1_series = j_series(1, x) + +def harmony(m): + return sum(RealField(300)(1)/RealField(300)(k) for k in range(1, m+1)) + +def z_series(x): + return sum([(-1)**m * (x)**(ZZ(2)*ZZ(m)) / (ZZ(2)**(2*m) * ZZ(m).factorial() * (ZZ(m) - ZZ(1)).factorial()) * (harmony(m) + harmony(m - 1)) for m in range(1, N)]) + +W1 = d2/pi * J1_series +Z1 = -(d2/(x*pi) * z_series(x) + d2/pi * gamma * J1_series(x) - d2/pi * log2 * J1_series(x)) + +# see the series +print(W0) +print(Z0) +``` +See ./notes/bessel_y1_taylor.ipynb for generation +**/ +#[inline] +fn y1f_near_zero(x: f32) -> f32 { + const W: [u64; 10] = [ + 0x3fd45f306dc9c883, + 0xbfa45f306dc9c883, + 0x3f5b2995e7b7b604, + 0xbf021bb945252402, + 0x3e9cf9286ea1d337, + 0xbe2ee7a29824147f, + 0x3db78be9987d036d, + 0xbd3ae90af76a4d0f, + 0x3cb7eb97f85e7d62, + 0xbc31028e3376648a, + ]; + let dx = x as f64; + let x2 = dx * dx; + let w0 = f_polyeval10( + x2, + f64::from_bits(W[0]), + f64::from_bits(W[1]), + f64::from_bits(W[2]), + f64::from_bits(W[3]), + f64::from_bits(W[4]), + f64::from_bits(W[5]), + f64::from_bits(W[6]), + f64::from_bits(W[7]), + f64::from_bits(W[8]), + f64::from_bits(W[9]), + ) * dx; + const Z: [u64; 10] = [ + 0x3fc91866143cbc8a, + 0xbfabd3975c75b4a7, + 0x3f6835b97894be5b, + 0xbf12c7dbffcde97d, + 0x3eb0a780ac776eac, + 0xbe432e5a4ddeea30, + 0x3dcf0ce34d2066a6, + 0xbd52a4e1aea45c18, + 0x3cd1474ade9154ac, + 0xbc4978ba84f218c0, + ]; + let z0 = f_polyeval10( + x2, + f64::from_bits(Z[0]), + f64::from_bits(Z[1]), + f64::from_bits(Z[2]), + f64::from_bits(Z[3]), + f64::from_bits(Z[4]), + f64::from_bits(Z[5]), + f64::from_bits(Z[6]), + f64::from_bits(Z[7]), + f64::from_bits(Z[8]), + f64::from_bits(Z[9]), + ) * dx; + let w_log = fast_logf(x); + const TWO_OVER_PI: f64 = f64::from_bits(0x3fe45f306dc9c883); + let recip = 1. / dx; + let z = f_fmla(w0, w_log, -z0); + f_fmla(recip, -TWO_OVER_PI, z) as f32 +} + +#[inline] +fn y1_transient_area(x: f32) -> f32 { + let dx = x as f64; + // first Y0 bessel zero + const ZERO: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243)); + let r = (dx - ZERO.hi) - ZERO.lo; + /* + Poly generated by Wolfram Matematica: + <120] + poly=error[[1]]; + coeffs=CoefficientList[poly,x]; + TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + */ + let p = f_polyeval18( + r, + f64::from_bits(0x3d9b15a8283b069b), + f64::from_bits(0x3fe0aa484455fd09), + f64::from_bits(0xbfbe56f80802fa38), + f64::from_bits(0xbfa0d2ac9d0409ad), + f64::from_bits(0xbf73a619b3551650), + f64::from_bits(0x3f7e6c480057ecbb), + f64::from_bits(0xbf650dc773a5df4d), + f64::from_bits(0x3f531e9ccab7d4da), + f64::from_bits(0xbf29b76999169b0e), + f64::from_bits(0x3f509c829abceaf7), + f64::from_bits(0x3f575aee5697c4d8), + f64::from_bits(0x3f63f7f9598be176), + f64::from_bits(0x3f67a6ae61541282), + f64::from_bits(0x3f665e6d3de19021), + f64::from_bits(0x3f5ee8837b9197f6), + f64::from_bits(0x3f4e6924f270fd7e), + f64::from_bits(0x3f32ca61e5b74925), + f64::from_bits(0x3f0725735bc3890b), + ); + p as f32 +} + +/// This method on small range searches for nearest zero or extremum. +/// Then picks stored series expansion at the point end evaluates the poly at the point. +#[inline] +fn y1f_small_argument_path(x: f32) -> f32 { + let x_abs = x as f64; + + // let avg_step = 51.03 / 33.0; + // let inv_step = 1.0 / avg_step; + // + // println!("inv_step {}", inv_step); + + const INV_STEP: f64 = 0.6466784244562023; + + let fx = x_abs * INV_STEP; + const Y1_ZEROS_COUNT: f64 = (Y1_ZEROS.len() - 1) as f64; + let idx0 = unsafe { fx.min(Y1_ZEROS_COUNT).to_int_unchecked::() }; + let idx1 = unsafe { + fx.cpu_ceil() + .min(Y1_ZEROS_COUNT) + .to_int_unchecked::() + }; + + let found_zero0 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx0]); + let found_zero1 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx1]); + + let dist0 = (found_zero0.hi - x_abs).abs(); + let dist1 = (found_zero1.hi - x_abs).abs(); + + let (found_zero, idx, dist) = if dist0 < dist1 { + (found_zero0, idx0, dist0) + } else { + (found_zero1, idx1, dist1) + }; + + if idx == 0 { + // Really should not happen here, but if it is then to log expansion + return y1f_near_zero(x); + } + + // We hit exact zero, value, better to return it directly + if dist == 0. { + return f64::from_bits(Y1_ZEROS_VALUES[idx]) as f32; + } + + let c = &Y1F_COEFFS[idx - 1]; + + let r = (x_abs - found_zero.hi) - found_zero.lo; + + let p = f_polyeval19( + r, + f64::from_bits(c[0]), + f64::from_bits(c[1]), + f64::from_bits(c[2]), + f64::from_bits(c[3]), + f64::from_bits(c[4]), + f64::from_bits(c[5]), + f64::from_bits(c[6]), + f64::from_bits(c[7]), + f64::from_bits(c[8]), + f64::from_bits(c[9]), + f64::from_bits(c[10]), + f64::from_bits(c[11]), + f64::from_bits(c[12]), + f64::from_bits(c[13]), + f64::from_bits(c[14]), + f64::from_bits(c[15]), + f64::from_bits(c[16]), + f64::from_bits(c[17]), + f64::from_bits(c[18]), + ); + + p as f32 +} + +/* + Evaluates: + Y1 = sqrt(2/(PI*x)) * beta(x) * sin(x - 3*PI/4 - alpha(x)) + + Discarding 1/2*PI gives: + Y1 = sqrt(2/(PI*x)) * beta(x) * (-cos(x - PI/4 - alpha(x))) +*/ +#[inline] +fn y1f_asympt(x: f32) -> f32 { + let dx = x as f64; + + let alpha = j1f_asympt_alpha(dx); + let beta = j1f_asympt_beta(dx); + + let angle = rem2pif_any(x); + + const SQRT_2_OVER_PI: f64 = f64::from_bits(0x3fe9884533d43651); + const MPI_OVER_4: f64 = f64::from_bits(0xbfe921fb54442d18); + + let x0pi34 = MPI_OVER_4 - alpha; + let r0 = angle + x0pi34; + + let m_cos = -cos_small(r0); + + let z0 = beta * m_cos; + let scale = SQRT_2_OVER_PI * j1f_rsqrt(dx); + + (scale * z0) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bessel_zero() { + assert_eq!(f_y1f(700.76), 0.024876066); + assert_eq!(f_y1f(35.76), 0.121432826); + assert_eq!(f_y1f(1.76), -0.24787569); + assert_eq!(f_y1f(0.87), -0.9030042); + assert_eq!(f_y1f(f32::INFINITY), 0.0); + assert!(f_y1f(f32::NEG_INFINITY).is_nan()); + assert!(f_y1f(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1f_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bessel/y1f_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bessel/y1f_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,923 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Y1 zeros and extremum on [0, 52] interval +Generated by SageMath: +```python +R120 = RealField(120) + +zeros = [] + +mp.prec = 150 + +step = mpf("0.1") +epsilon = mpf("1e-35") +x = mpf("1.25") + +previous_zero = R120(0) +y1_zeros = [] + +while x < mpf("52.0"): + f1 = bessely(1, x) + f2 = bessely(1, x + step) + if f1 * f2 < 0: + zero = findroot(lambda t: bessely(1, t), (x, x + step), solver='secant', tol=mp.mpf("1e-41")) + previous_zero = zero + y1_zeros.append(zero) + if previous_zero is not None and abs(x - mpf(f'{round(x)}')) < epsilon: + zeros.append(previous_zero) + x += step + +y1_extrema = [] + +x = mpf("1.25") +while x < mpf("52.0"): + d1 = mp.diff(lambda t: bessely(1, t), x) + d2 = mp.diff(lambda t: bessely(1, t), x + step) + if d1 * d2 < 0: + extremum = findroot(lambda t: mp.diff(lambda u: bessely(1, u), t), (x, x + step), solver='secant', tol=mp.mpf("1e-41")) + y1_extrema.append(extremum) + x += step + +y1_zeros.extend(y1_extrema) + +y1_zeros = sorted(y1_zeros) + +print(f"pub(crate) static Y1_ZEROS: [(u64, u64); {len(y1_zeros)}] = [") +print(f"(0x0, 0x0),") +for z in y1_zeros: + k = split_double_double(z) + hi = double_to_hex(k[1]) + lo = double_to_hex(k[0]) + print(f"({lo}, {hi}),") + +print("];") +``` +**/ +pub(crate) static Y1_ZEROS: [(u64, u64); 33] = [ + (0x0, 0x0), // not really used, just a stab to avoid indices messing + (0xbc8bd1e50d219bfd, 0x400193bed4dff243), + (0x3c53bac0714e4129, 0x400d76d4affba175), + (0x3cbdfe7bac228e8c, 0x4015b7fe4e87b02e), + (0x3ca7960b6b1c46ac, 0x401bc41890588553), + (0x3cb479cc068d9046, 0x40213127ae6169b4), + (0x3cc8f4ba5d68e440, 0x40243f2ee51e8c7e), + (0x3c80fc786ce06080, 0x40277f9138d43206), + (0xbcaf6ef7a3571593, 0x402a924ee4a3e52c), + (0xbcc5e091a50f8e05, 0x402dcb7d88de848b), + (0x3cc07320221cd5e5, 0x403070a7a43daae6), + (0xbcda1ee4c5487ede, 0x40320b1c695f1e3b), + (0xbcd2903124fef7e3, 0x4033971a15717510), + (0x3cd391b14410528f, 0x40353025492188cd), + (0xbcc15ec09721b746, 0x4036bcefd7de87a3), + (0x3cb52f75f025b205, 0x403854fa303820ca), + (0x3cb6f57f7696f493, 0x4039e262715f12a9), + (0xbcbcf130fbea3b24, 0x403b79acee8cfb7d), + (0xbc912142b10a5c65, 0x403d079247e8f51b), + (0xbc9e7a77047d6166, 0x403e9e480605283c), + (0x3cb1452eb07cd937, 0x40401649819af8fa), + (0xbce96beabef7ecf4, 0x4040e16907f8fb56), + (0x3cec6086fb5dd335, 0x4041a8b8a142d536), + (0x3cd2481e87adfe57, 0x404273a7b35a7aff), + (0x3cd7df5b6f701c7a, 0x40433b1ac0375e31), + (0x3cda8ffacaac8461, 0x404405e18393afb5), + (0xbce5b5acaff0a867, 0x4044cd72d2adfb0c), + (0x3cbfe463face2c1c, 0x4045981787d668db), + (0xbcefcba6ea61df1b, 0x40465fc2f7ca5b81), + (0xbce26390f25f01cb, 0x40472a4a85cc317e), + (0xbcbba46ca6ef9b6f, 0x4047f20cbfc32967), + (0xbcdcc667e557a177, 0x4048bc7b10ed3960), + (0x3cea473d4f209faf, 0x4049845158040451), +]; + +/** +Value at zero or extremum of Y1 belongs to [Y1_ZEROS] +Generated by MPFR: +```text +let mut arr = vec![]; +for zeros in Y1_ZEROS.iter() { + if zeros.1 == 0 { + arr.push(0); + } else { + let mpfr = Float::with_val(107, f64::from_bits(zeros.1)).y1(); + arr.push(mpfr.to_f64().to_bits()); + } +} +println!( + "arr: [{}]", + arr.iter() + .map(|x| format!("0x{:016x}", x)) + .collect::>() + .join(", ") +); +``` +**/ +pub(crate) static Y1_ZEROS_VALUES: [u64; 33] = [ + 0x0000000000000000, + 0x3c7cf9f8d5e1a475, + 0x3fdaabb4011ed330, + 0x3ca46a40b234169c, + 0xbfd36732d4b96094, + 0xbc963bc010b45f46, + 0x3fd00ef3745e0e3c, + 0x3c5f96d32c02f147, + 0xbfcc075da85beb4f, + 0x3ca213201464272b, + 0x3fc931a5a0ae5aa0, + 0xbcb39d4c41d5839f, + 0xbfc713fc51664c74, + 0xbcab20138dd047ec, + 0x3fc56b97f8091ac5, + 0x3c8b67dbfd3bd179, + 0xbfc413644356a52b, + 0x3c919e290514c619, + 0x3fc2f4e70d6c7e01, + 0xbc719366994a86bc, + 0xbfc20198200b699d, + 0x3cbbec2345ac18e2, + 0x3fc12f9870d68e18, + 0x3ca334eb74fdcfd1, + 0xbfc077eede4a0d89, + 0xbcaaca291aee3c35, + 0x3fbfab0b166d23d8, + 0x3c8ef92aa9c8e53c, + 0xbfbe891b327da16d, + 0x3cb13e3c695ea088, + 0x3fbd84391bb2748d, + 0xbcaa1c861fdd1438, + 0xbfbc97d79918527d, +]; + +/** +Series expansion at point for Y1 + +Generated by SageMath and Sollya: +```python +def compute_intervals(zeros): + intervals = [] + for i in range(0, len(zeros)): + if i == 0: + a = 2 - zeros[i] + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + elif i + 1 > len(zeros) - 1: + a = (zeros[i - 1] + zeros[i]) / 2 - 0.05 - zeros[i] + b = (zeros[i]) + 0.83 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + else: + a = (zeros[i - 1] + zeros[i]) / 2 - zeros[i] - 0.05 + b = (zeros[i] + zeros[i + 1]) / 2 + 0.05 - zeros[i] + intervals.append((RealField(18)(a), RealField(18)(b), RealField(110)(zeros[i]))) + return intervals + +intervals = compute_intervals(y1_zeros) + +def build_sollya_script(a, b, zero, deg): + return f""" +prec = 250; +bessel_y1 = library("./notes/bessel_sollya/cmake-build-release/libbessel_sollya.dylib"); +f = bessel_y1(x + {zero}); +d = [{a}, {b}]; +pf = remez(f, {deg}, d); +for i from 0 to degree(pf) do {{ + write(coeff(pf, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RR(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(a, b, zero, degree=12): + sollya_script = build_sollya_script(a, b, zero, degree) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +degree = 18 + +print(f"pub(crate) static Y1F_COEFFS: [[u64;{degree + 1}]; {len(intervals)}] = [") +for i in range(0, len(intervals)): + interval = intervals[i] + call_sollya_on_interval(interval[0], interval[1], interval[2], degree) + coeffs = load_coefficients(f"coefficients.txt") + print("[") + for c in coeffs: + print(double_to_hex(c) + ",") + print("],") +print("];") +``` +**/ +pub(crate) static Y1F_COEFFS: [[u64; 19]; 32] = [ + [ + 0x3bdca2ee18606a4b, + 0x3fe0aa48442f014b, + 0xbfbe56f82217b8f4, + 0xbfa0d2af4e932400, + 0xbf73a6dec3726cd5, + 0x3f7e671c7d12ea48, + 0xbf65429dc5c0e9d4, + 0x3f517ab4af4655e4, + 0xbf40b2d8647a250d, + 0x3f2eea7b1b675766, + 0xbf1c3fb728e7d2ff, + 0x3f09d1da72e12f44, + 0xbef7964bf8511e22, + 0x3ee57c2a83e1f972, + 0xbed33f4211a00375, + 0x3ec02bcdac2103fd, + 0xbea6fefcf033ab9d, + 0x3e874128ed97d3bb, + 0xbe57d5b1eac16658, + ], + [ + 0x3fdaabb4011ed330, + 0x3c54da7c52fcf446, + 0xbfc8b45babe797b6, + 0x3f8e147099a6f00d, + 0x3f88c5af1eeb2143, + 0xbf4133fa47d8ea48, + 0xbf3bf8af93e7a2f0, + 0x3f021d64bd4e2cd8, + 0x3eb44d2c32fdaf23, + 0x3eb14c3b9e7960c1, + 0xbe9b8ee25c629be6, + 0x3e7a85b5b497dc6c, + 0xbe5bfa422fb8d949, + 0x3e3f0ad81d293f5a, + 0xbe20e6844c6faba7, + 0x3e0214b2d826d072, + 0xbde4ff658967d425, + 0x3dcb549cdc774a83, + 0xbda6b5df4d9c1682, + ], + [ + 0x3b7ff35240713789, + 0xbfd5c7c556f0c19a, + 0x3fa00b9f8571ca1f, + 0x3faa15d92dfe3e27, + 0xbf710a329e2c23f5, + 0xbf61be6db9923ac9, + 0x3f2337c7e138eb84, + 0x3f085b940eb5f37f, + 0xbec80619146a1e65, + 0xbea255e6cf4b3254, + 0x3e5b62ccdc392c5a, + 0x3e380b1a5a61e6b5, + 0xbdfa7ec7fd0d2925, + 0x3d840d04ff01d1b2, + 0xbd938dc1b2e33eca, + 0x3d74839c586126ca, + 0xbd4b045bc7ad769b, + 0x3d261d10a8575c45, + 0xbd052a6cc14bcc54, + ], + [ + 0xbfd36732d4b96094, + 0x3b3886a5ed6fd628, + 0x3fc3001c8002caf8, + 0xbf7bf5a03bab4999, + 0xbf8751ea028c1953, + 0x3f423874cd8d0402, + 0x3f364f6610d6493b, + 0xbef02978de38394f, + 0xbed72f0766d0d9c7, + 0x3e8f2081874e556c, + 0x3e6defd5dce91973, + 0xbe2205c70046a2c7, + 0xbdfb6432eb3ab7ea, + 0x3db028a1c0572973, + 0x3d807791dcab03a0, + 0xbd29778204deee13, + 0xbd08342db2e7148e, + 0x3cc898efb37f9dad, + 0xbc84e2adc305e2ab, + ], + [ + 0xbac1435819592d4c, + 0x3fd15f993fceab5c, + 0xbf902b3933cf21b1, + 0xbfa6395dfe49fcd4, + 0x3f63ced2a2e69180, + 0x3f607a678d6000bb, + 0xbf1b50d7e1d3201e, + 0xbf06f7bab104f34b, + 0x3ec176e72bf94a3a, + 0x3ea2becb2b6bacd1, + 0xbe5a384eebfb23c2, + 0xbe341e7a921f7f66, + 0x3de9e3284b918a26, + 0x3dbec40b21f2c78f, + 0xbd726865da6190a9, + 0xbd416f4fe7eed351, + 0x3cf3160bd2bd6c64, + 0x3cbf6d61c945b95c, + 0xbc706809636e0aec, + ], + [ + 0x3fd00ef3745e0e3c, + 0x3aff192f298c81c3, + 0xbfbfcdacdda138f2, + 0x3f706cc34cd829fa, + 0x3f84641bb10c16cb, + 0xbf37fac943e2a16d, + 0xbf34769ed32e14a2, + 0x3ee80608ecda1508, + 0x3ed5cc8242d77e23, + 0xbe888c8f2538feb8, + 0xbe6ce5908c1e5174, + 0x3e1ed16257e17417, + 0x3dfa30d623eda066, + 0xbdaa5076123e3ecf, + 0xbd814cd297d2be7e, + 0x3d306166947e23e9, + 0x3d01635f73179569, + 0xbcaeafcf4c2f127b, + 0xbc7b0828175d92fa, + ], + [ + 0x3aba1488e1b7782d, + 0xbfcdc14ea14e89f9, + 0x3f84429fef5b5fbd, + 0x3fa367d7d608e4ba, + 0xbf59d6eb2bc49e35, + 0xbf5dc4f991b3db86, + 0x3f1315ec04d6e6bb, + 0x3f0571814a1aa2f5, + 0xbeba2977fa42f00f, + 0xbea1e864230850b8, + 0x3e54a7b82d3fa1e5, + 0x3e33906609f9fe4c, + 0xbde549e8b0e16969, + 0xbdbe32cf2ce99d6f, + 0x3d6eff542dd345c3, + 0x3d415e2a9c2f4933, + 0xbcf0d48dde3c3ffe, + 0xbcbeac3c36b4bce2, + 0x3c6af1612c5ddab0, + ], + [ + 0xbfcc075da85beb4f, + 0xbafcfa84f4024782, + 0x3fbbdeb6ff9f55e1, + 0xbf661eefb74da882, + 0xbf8229ea914b846e, + 0x3f30cbcc6778fd37, + 0x3f32aa59f5091f7b, + 0xbee1c15d5251ae54, + 0xbed4583f15abd654, + 0x3e831d151a12624a, + 0x3e6b74e57c21e022, + 0xbe19044f1339b061, + 0xbdf93b1ec70c7bbc, + 0x3da61a4e437e8105, + 0x3d80d4305f038451, + 0xbd2c3aad6f3b35c7, + 0xbd010dec3a02c58c, + 0x3cab15901b6d0925, + 0x3c7ab2531f00c501, + ], + [ + 0xbab392a85abdc950, + 0x3fca7022be084d99, + 0xbf7c650b6b83109a, + 0xbfa163191c30aa62, + 0x3f526b045287ddca, + 0x3f5b17602840abf5, + 0xbf0c0a9cee3c8429, + 0xbf03e398cbc472de, + 0x3eb3f35db1ff19f5, + 0x3ea0e9b612dbc0ea, + 0xbe5056babcd79a11, + 0xbe32c1a8c8d768b1, + 0x3de161b6a84838d0, + 0x3dbd4ca9d2d67d78, + 0xbd69fdd67a999eab, + 0xbd4101919ce84a07, + 0x3cecd91fa7851496, + 0x3cbe3f8588ebbfdf, + 0xbc67a4499c96e38d, + ], + [ + 0x3fc931a5a0ae5aa0, + 0x3afa23fd08be9891, + 0xbfb919c8a3f203fa, + 0x3f602a38da6262a9, + 0x3f807ced48910819, + 0xbf2900f33a00690a, + 0xbf31278d46fd153c, + 0x3edb2595529cf19f, + 0x3ed2f7c2d608e0bb, + 0xbe7e212d23787793, + 0xbe69f3fcf3631e9c, + 0x3e144fbf033f1974, + 0x3df82268e7ab0cdb, + 0xbda26cc2714815d4, + 0xbd80418b35c32375, + 0x3d28122e50410f0a, + 0x3d009aba27e11464, + 0xbca78943175d4e84, + 0xbc7a379f959c0224, + ], + [ + 0x3aaf25ce7e30cbc6, + 0xbfc80781c32422e7, + 0x3f754eda697a0098, + 0x3f9fbe6df840847f, + 0xbf4be318d61276e1, + 0xbf58efee4094379c, + 0x3f059145b4f0e4dd, + 0x3f0282d26a74c382, + 0xbeaf56c29d9ad6c8, + 0xbe9fdd03174f6b47, + 0x3e4a44a7907d0ec6, + 0x3e31df6533090779, + 0xbddc96e9cb6ee22b, + 0xbdbc3439a99213c4, + 0x3d65d387fc8083e0, + 0x3d40830db4ec8a6e, + 0xbce8ad426f9ce3f5, + 0xbcbd93c0cf35d116, + 0x3c649b19a5449ffa, + ], + [ + 0xbfc713fc51664c74, + 0xbaf73aab14face16, + 0x3fb7049760cde490, + 0xbf58ef5f1cbe4874, + 0xbf7e5f53caf3bead, + 0x3f237b0b62ddadd1, + 0x3f2fd3bac08286da, + 0xbed5789803de3adb, + 0xbed1c0faa8999393, + 0x3e7845b49b063dc7, + 0x3e6886872800e226, + 0xbe10b03677687883, + 0xbdf7049d17bd230b, + 0x3d9edd9ca057f252, + 0x3d7f445f42a168e6, + 0xbd24866878075342, + 0xbd0015a37275b46d, + 0x3ca463bd3d4059be, + 0x3c79974848138496, + ], + [ + 0xbaa9a62f9227c851, + 0x3fc62d94d97e859c, + 0xbf70bf614807033c, + 0xbf9d5f857a2a6107, + 0x3f46081b0b7fe572, + 0x3f57307b03e248f8, + 0xbf0132c0aa83d0db, + 0xbf0154ed4598d2e4, + 0x3ea94f64f476e3f5, + 0x3e9e1272585385c0, + 0xbe4588c758dd66db, + 0xbe31021cdd7a4f3a, + 0x3dd7cfa7a39f5d48, + 0x3dbb0e00d41ec645, + 0xbd6276c9a451cdb1, + 0xbd3fe8cf17671ae1, + 0x3ce52f1a6f7ae06f, + 0x3cbcc2eb893d62ce, + 0xbc61f4c0af8bd0fb, + ], + [ + 0x3fc56b97f8091ac5, + 0x3af48a947d2475cd, + 0xbfb560fcc8c08469, + 0x3f53fafa39618883, + 0x3f7c49141623372f, + 0xbf1f69980694fd17, + 0xbf2dc5f848aa9d33, + 0x3ed178fc979b779d, + 0x3ed0b494a4bafca8, + 0xbe73fc3884c243a5, + 0xbe673afb9fb48ff7, + 0x3e0bd903464b077a, + 0x3df5f3bafabcdabe, + 0xbd9a1c27612b5f03, + 0xbd7e04553366c10e, + 0x3d219970f1564c7c, + 0x3cff128fbd867c78, + 0xbca1b4d2be53f3ad, + 0xbc78e13fb654b036, + ], + [ + 0x3aa5951bb8e2b477, + 0xbfc4b2a38f1ab9b4, + 0x3f6b3878aadeb34d, + 0x3f9b750d89a9b35f, + 0xbf41f6911725a956, + 0xbf55beee6fd51c8a, + 0x3efc3625d7a65087, + 0x3f005375a588a71f, + 0xbea4ee5e4e7cafc0, + 0xbe9c7b3d81b5dc31, + 0x3e41fce14f464e1e, + 0x3e30346643a98dcb, + 0xbdd41c86191a49ce, + 0xbdb9eed9da04017a, + 0x3d5f8cee5e5b42b4, + 0x3d3ec41075d33352, + 0xbce24e44459e28b0, + 0xbcbbe16f7d769c15, + 0x3c5f670ad9138f1f, + ], + [ + 0xbfc413644356a52b, + 0xbaf22d9ab9060f8f, + 0x3fb40bb88c6f2b85, + 0xbf5078d13cfc400e, + 0xbf7a9191262ab9d5, + 0x3f1a005297618f35, + 0x3f2c0cbad847a60e, + 0xbecd1a72e7c35fa0, + 0xbecf9a2654099c0b, + 0x3e70c6b06e20d1c0, + 0x3e66136d6425acf0, + 0xbe0797767778226d, + 0xbdf4f77b30ed58c3, + 0x3d96572059bf2445, + 0x3d7cd12649b82d6f, + 0xbd1e6ce514a88f2d, + 0xbcfdfabaf5c37514, + 0x3c9eea8202989176, + 0x3c782260f7596e02, + ], + [ + 0xbaa27e57c2b07d4b, + 0x3fc37aaceac987b9, + 0xbf66afe4fe0bc0f7, + 0xbf99de7a33bc3a97, + 0x3f3e024f567ac487, + 0x3f548843c426abe0, + 0xbef7a8e14711c0f4, + 0xbefeeceb341ad81c, + 0x3ea1a743e05b383f, + 0x3e9b143d39c8eb5f, + 0xbe3e8e00011fabc3, + 0xbe2ef28e31ff924c, + 0x3dd137a1bd136742, + 0x3db8e0878264a773, + 0xbd5b3dc655a5a5f4, + 0xbd3da652e8239897, + 0x3cdfe34eace42448, + 0x3cbafd0cc7251807, + 0xbc5b9b0102453020, + ], + [ + 0x3fc2f4e70d6c7e01, + 0x3af022defda0ec45, + 0xbfb2ef24d6f7526a, + 0x3f4bc33c9dc6ec82, + 0x3f7920414ee2acbe, + 0xbf15f9173916a219, + 0xbf2a94fdbdcec471, + 0x3ec8b309990f94db, + 0x3ece087ff4517bd5, + 0xbe6ca22ab12c685c, + 0xbe650d1f28632753, + 0x3e044415529c950b, + 0x3df411b8a7d9d1bc, + 0xbd9354e8c7a8bfd7, + 0xbd7bb16e8ee8c711, + 0x3d1a881fddcb8d86, + 0x3cfcecee70233b69, + 0xbc9b2b6cccd3802a, + 0xbc77637662fa6ba8, + ], + [ + 0x3aa00f5dbb23e90b, + 0xbfc2740819f1caaa, + 0x3f6349369dc780bb, + 0x3f98868d7401bf2e, + 0xbf398cd1bebe1445, + 0xbf537eef9aadeee2, + 0x3ef43394c95b2d29, + 0x3efd6dfcdb026013, + 0xbe9e448fbc8a1c95, + 0xbe99d764ee07a6b7, + 0x3e3a53958c8a71d8, + 0x3e2da0e1c86368ce, + 0xbdcdd7f914e496e5, + 0xbdb7e67ff45daf48, + 0x3d57c2e32861f41c, + 0x3d3c96e18ab6db69, + 0xbcdc0099b11f0478, + 0xbcba1dfeafeb6e19, + 0x3c586b4c940f74bc, + ], + [ + 0xbfc20198200b699d, + 0xbaecc875d54af9d0, + 0x3fb1fd242a74e630, + 0xbf47cf261dfbf19a, + 0xbf77e4820ec1dde4, + 0x3f12e1bd281dfcba, + 0x3f2950bb06c6fdf9, + 0xbec54a38ab6af51a, + 0xbecca94f38024fb4, + 0x3e68c7e75971843f, + 0x3e6423fc7e24ed40, + 0xbe019fe1d8a6e0d8, + 0xbdf34198c7517f5a, + 0x3d90e78c95f157aa, + 0x3d7aa74c4042e051, + 0xbd1756942b9afcaf, + 0xbcfbedc3e7dae4e4, + 0x3c980b9567289463, + 0x3c76a9e024cc6a52, + ], + [ + 0xba9c33661811b8ff, + 0x3fc192f2627a74e3, + 0xbf60a846a83fecf2, + 0xbf975eceaabf7f86, + 0x3f3617c581be35b1, + 0x3f529934b7a84483, + 0xbef18123e8751889, + 0xbefc1f05a2d85150, + 0x3e9a4e0bc09262e9, + 0x3e98be81ad44b8a4, + 0xbe36f73795dfb5c7, + 0xbe2c70ab155167d1, + 0x3dca26218cc79400, + 0x3db7011269271056, + 0xbd54ec138a5f86cd, + 0xbd3b98bf6fa2fe47, + 0x3cd8c95d73f0c84c, + 0x3cb948b2dd021429, + 0xbc55bd7c63fa9765, + ], + [ + 0x3fc12f9870d68e18, + 0x3ae9cd1ac1fa64f9, + 0xbfb12c11811945f9, + 0x3f44b638f21f0f76, + 0x3f76d2a897d58353, + 0xbf10732e5458ba20, + 0xbf2835929300df3e, + 0x3ec297283816a814, + 0x3ecb73adedf11a1f, + 0xbe65b455b903b389, + 0xbe6353f0797a3bf1, + 0x3dfefc9ac10b87d9, + 0x3df2853545ffa79d, + 0xbd8dd8945079a88f, + 0xbd79b28860cd63f8, + 0x3d14b29ba2797832, + 0x3cfaff02f362ca7e, + 0xbc956d8436ee55ed, + 0xbc75f881bb0137f5, + ], + [ + 0x3a9900b85a085cfa, + 0xbfc0cf3ee98f769b, + 0x3f5d26e7af251f79, + 0x3f965d05948a946a, + 0xbf335959b8482e40, + 0xbf51cff175d05c2a, + 0x3eeeb59416879104, + 0x3efaf7544eeac751, + 0xbe9720522bb1fa69, + 0xbe97c41261703475, + 0x3e343fa0ea5ba663, + 0x3e2b5e23abb21a5f, + 0xbdc722397b59adb6, + 0xbdb62f213532a0b8, + 0x3d5294a89e377c98, + 0x3d3aac95aead6ada, + 0xbcd61abb584f3fc2, + 0xbcb87f3345758fd5, + 0x3c537a3b70fc94b7, + ], + [ + 0xbfc077eede4a0d89, + 0xbae73fb2e67b1968, + 0x3fb0751548b2924d, + 0xbf423b5d46a73864, + 0xbf75e2467c8fb832, + 0x3f0cfe5c189d6e4d, + 0x3f273bbd8c7aef2c, + 0xbec06974d3d04263, + 0xbeca6081d36e6a0b, + 0x3e6334a83cf5d21d, + 0x3e6299571cb4bb1e, + 0xbdfb7f5bc046450f, + 0xbdf1da63b49ed896, + 0x3d8a92885fb339ae, + 0x3d78d1d6e93bb23d, + 0xbd127ea4434f9fb5, + 0xbcfa20dab6b920e9, + 0x3c93389d892643a0, + 0x3c7550b88147fd02, + ], + [ + 0xba96582ab366c758, + 0x3fc0230ba90f2871, + 0xbf59ca16f0c9734e, + 0xbf9579c1bdbcfc99, + 0x3f3120ecfac5c017, + 0x3f511dd26bbe2946, + 0xbeeb37e7c9a57147, + 0xbef9f01e7c19098c, + 0x3e94887fe7a88a4d, + 0x3e96e3723883fe87, + 0xbe3204b644d485a1, + 0xbe2a659b13b69c6b, + 0x3dc4a40c8498625a, + 0x3db56f0212f628e4, + 0xbd50a0fef4ac5a44, + 0xbd39d1d92cf50973, + 0x3cd3d93917ae0666, + 0x3cb7c222c421cbf8, + 0xbc518e27cddeecfd, + ], + [ + 0x3fbfab0b166d23d8, + 0x3ae50cd9856106aa, + 0xbfafa65c1ce7ebd6, + 0x3f4035bf503ffc1f, + 0x3f750d1b04713c41, + 0xbf09cd14a92842a1, + 0xbf265d504af5d8fe, + 0x3ebd3feeb33d9cae, + 0x3ec96a257062f750, + 0xbe61254f302b04d0, + 0xbe61f11585e02bfc, + 0x3df89a7674827723, + 0x3df13f0ba458182e, + 0xbd87d67ae3559fb7, + 0xbd78038124810666, + 0x3d10a3cffab7b16e, + 0x3cf952a4679b4020, + 0xbc9158ffabf6b26f, + 0xbc74b2e8c7ca451f, + ], + [ + 0x3a9422b204fbf27f, + 0xbfbf13fb0c0e6fcd, + 0x3f5706ed3d935d00, + 0x3f94af74cbd77bef, + 0xbf2e9a9e66e5a792, + 0xbf507ec9ed824fcb, + 0x3ee856d4518ab29c, + 0x3ef9040de830648a, + 0xbe9262f69c56c4a2, + 0xbe9618c94a54555e, + 0x3e3029d2c8bd8b0e, + 0x3e2983bca06d479e, + 0xbdc28e29fd7e309a, + 0xbdb4beea8ebaabe8, + 0x3d4df87d00b82fa1, + 0x3d39076f370434b4, + 0xbcd1ef67bd03c16c, + 0xbcb7115a994eb5d5, + 0x3c4fd28ad1effa7c, + ], + [ + 0xbfbe891b327da16d, + 0xbae325aba995f36e, + 0x3fae8533ce07bdb8, + 0xbf3d1253218e31b0, + 0xbf744e6826476498, + 0x3f07271a9b5e3cb4, + 0x3f2595b697c8ec04, + 0xbeba46b03ecb3892, + 0xbec88c173e076203, + 0x3e5ed9b1754f626a, + 0x3e615891ef312cd4, + 0xbdf62ca3527c988f, + 0xbdf0b14767922479, + 0x3d85879b58ff9d05, + 0x3d7745bb7346aea9, + 0xbd0e20fb122a7c2a, + 0xbcf89354d05f7b8c, + 0x3c8f7da941b1f5c8, + 0x3c741ef462ba56a3, + ], + [ + 0xba923c4506ec812e, + 0x3fbe018dac1c17e3, + 0xbf54b994dd05c1fb, + 0xbf93f9e0db07e7ef, + 0x3f2b8e55b75b13ab, + 0x3f4fdf68a78bb3d2, + 0xbee5ee9d17106a07, + 0xbef82ee6dfdfedd8, + 0x3e90962d7f6d601e, + 0x3e9560edce7d4b08, + 0xbe2d34381cff4d39, + 0xbe28b5a0e715b17d, + 0x3dc0cab951aa6b0b, + 0x3db41d218be1cc79, + 0xbd4b2d2a51de7089, + 0xbd384c06737cf8d9, + 0x3cd04c96e113bd0a, + 0x3cb66c4b3dc74284, + 0xbc4cfe4908cedcb8, + ], + [ + 0x3fbd84391bb2748d, + 0x3ae17f232c3596e7, + 0xbfad80edb3c4ea05, + 0x3f3a431f5421f7ef, + 0x3f73a282fe7b63a8, + 0xbf04ed653e607bdc, + 0xbf24e15832bda3c4, + 0x3eb7c5832dd13719, + 0x3ec7c2b80da8df7e, + 0xbe5bf160ccd30135, + 0xbe60cda2141b0afb, + 0x3df41d31d25837e8, + 0x3df02f6ca822716e, + 0xbd83901f0d351db4, + 0xbd7696cdd91c27b7, + 0x3d0b6e1487e46414, + 0x3cf7e1bb61dba0fc, + 0xbc8cbb194749390a, + 0xbc7394699d841c82, + ], + [ + 0x3a909e71c2163ed3, + 0xbfbd09b21e36c0bd, + 0x3f52c84acfb586b4, + 0x3f9355b904fbf7ee, + 0xbf28fb570465af0d, + 0xbf4edc3292ba6cfd, + 0x3ee3e552ee8c2575, + 0x3ef76d44f6a83510, + 0xbe8e1ee2dc4a3910, + 0xbe94b944bbd4ab57, + 0x3e2a8c3a4ce04c1b, + 0x3e27f8c9ef133245, + 0xbdbe92957079603b, + 0xbdb388138abed52f, + 0x3d48c7ca6d80cb32, + 0x3d379e45475751e8, + 0xbccdc773f7abde68, + 0xbcb5d2331c76adb9, + 0x3c4a8aa5ca753696, + ], + [ + 0xbfbc97d79918527d, + 0xbae4d780a21f2057, + 0x3fac95081ab2b511, + 0xbf37e0b14f7d7c3f, + 0xbf730688f6836a76, + 0x3f030941f6e78e36, + 0x3f243d5898657a6f, + 0xbeb5a39a94f2ad1c, + 0xbec70b18406146b4, + 0x3e597607f952cd69, + 0x3e604e788f4f18d9, + 0xbdf2598918fbb9ee, + 0xbdef701541acccd2, + 0x3d81df5bcb47b899, + 0x3d75f524c73bc009, + 0xbd0919aede2dcbf2, + 0xbcf73c65c9ce91ed, + 0x3c8a553df0f1b569, + 0x3c72fe9f3f0dcae2, + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bits.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/bits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/bits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub(crate) const fn get_exponent_f32(x: f32) -> i32 { + let bits = x.to_bits(); + (((bits >> 23) & 0xFF) as i32).wrapping_sub(127) +} + +// #[inline] +// pub(crate) const fn mantissa_f32(x: f32) -> u32 { +// x.to_bits() & ((1u32 << 23) - 1) +// } + +#[inline] +pub(crate) const fn mantissa_f64(x: f64) -> u64 { + x.to_bits() & ((1u64 << 52) - 1) +} + +#[inline] +pub(crate) const fn get_exponent_f64(x: f64) -> i64 { + ((x.to_bits() as i64 & EXP_MASK as i64) >> 52).wrapping_sub(1023) +} + +#[inline] +pub(crate) const fn biased_exponent_f64(x: f64) -> i64 { + (x.to_bits() as i64 & EXP_MASK as i64) >> 52 +} + +#[inline] +pub(crate) const fn mask_trailing_ones(len: u64) -> u64 { + if len >= 64 { + u64::MAX + } else { + (1u64 << len).wrapping_sub(1) + } +} + +pub(crate) const EXP_MASK: u64 = mask_trailing_ones(11) << 52; + +#[inline] +pub(crate) fn set_exponent_f64(x: u64, new_exp: u64) -> u64 { + let encoded_mask = new_exp.wrapping_shl(52) & EXP_MASK; + x ^ ((x ^ encoded_mask) & EXP_MASK) +} + +#[inline] +pub(crate) const fn min_normal_f32(sign: bool) -> f32 { + let sign_bit = if sign { 1u32 << 31 } else { 0 }; + let exponent = 1u32 << 23; + f32::from_bits(sign_bit | exponent) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/common.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/common.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/common.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/common.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,437 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use num_traits::MulAdd; +use std::ops::{Add, Mul}; + +#[inline(always)] +pub(crate) fn is_integerf(x: f32) -> bool { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + x.round_ties_even() == x + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + let x_u = x.to_bits(); + let x_e = (x_u & EXP_MASK_F32) >> 23; + let lsb = (x_u | EXP_MASK_F32).trailing_zeros(); + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + const UNIT_EXPONENT: u32 = E_BIAS + 23; + x_e + lsb >= UNIT_EXPONENT + } +} + +#[inline(always)] +pub(crate) fn is_odd_integerf(x: f32) -> bool { + #[cfg(target_arch = "aarch64")] + { + (x as i32 & 1) != 0 + } + #[cfg(not(target_arch = "aarch64"))] + { + let x_u = x.to_bits(); + let x_e = (x_u & EXP_MASK_F32) >> 23; + let lsb = (x_u | EXP_MASK_F32).trailing_zeros(); + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + + const UNIT_EXPONENT: u32 = E_BIAS + 23; + x_e + lsb == UNIT_EXPONENT + } +} + +#[inline(always)] +pub(crate) fn is_integer(n: f64) -> bool { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + n == n.round_ties_even() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + use crate::bits::EXP_MASK; + let x_u = n.to_bits(); + let x_e = (x_u & EXP_MASK) >> 52; + let lsb = (x_u | EXP_MASK).trailing_zeros(); + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + const UNIT_EXPONENT: u64 = E_BIAS + 52; + x_e + lsb as u64 >= UNIT_EXPONENT + } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn is_odd_integer_fast(x: f64) -> bool { + unsafe { (x.to_int_unchecked::() & 1) != 0 } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn is_odd_integerf_fast(x: f32) -> bool { + unsafe { (x.to_int_unchecked::() & 1) != 0 } +} + +#[inline(always)] +pub(crate) fn is_odd_integer(x: f64) -> bool { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + (x as i64 & 1) != 0 + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + use crate::bits::EXP_MASK; + let x_u = x.to_bits(); + let x_e = (x_u & EXP_MASK) >> 52; + let lsb = (x_u | EXP_MASK).trailing_zeros(); + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + const UNIT_EXPONENT: u64 = E_BIAS + 52; + x_e + lsb as u64 == UNIT_EXPONENT + } +} + +#[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +))] +#[inline(always)] +pub(crate) fn mlaf + Add + MulAdd>( + acc: T, + a: T, + b: T, +) -> T { + MulAdd::mul_add(a, b, acc) +} + +#[inline(always)] +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +)))] +pub(crate) fn mlaf + Add + MulAdd>( + acc: T, + a: T, + b: T, +) -> T { + acc + a * b +} + +#[inline] +pub(crate) const fn rintfk(x: f32) -> f32 { + (if x < 0. { x - 0.5 } else { x + 0.5 }) as i32 as f32 +} + +#[inline(always)] +pub(crate) const fn fmlaf(a: f32, b: f32, c: f32) -> f32 { + c + a * b +} + +#[inline(always)] +pub(crate) fn f_fmlaf(a: f32, b: f32, c: f32) -> f32 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + f32::mul_add(a, b, c) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + a * b + c + } +} + +/// Optional FMA, if it is available hardware FMA will use, if not then just scalar `c + a * b` +#[inline(always)] +pub(crate) fn f_fmla(a: f64, b: f64, c: f64) -> f64 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + f64::mul_add(a, b, c) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + a * b + c + } +} + +#[inline(always)] +pub(crate) const fn fmla(a: f64, b: f64, c: f64) -> f64 { + c + a * b +} + +/// Executes mandatory FMA +/// if not available will be simulated through Dekker and Veltkamp +#[inline(always)] +pub(crate) fn dd_fmla(a: f64, b: f64, c: f64) -> f64 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + f_fmla(a, b, c) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::DoubleDouble; + DoubleDouble::dd_f64_mul_add(a, b, c) + } +} + +// Executes mandatory FMA +// if not available will be simulated through dyadic float 128 +#[inline(always)] +pub(crate) fn dyad_fmla(a: f64, b: f64, c: f64) -> f64 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + f_fmla(a, b, c) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::dyadic_float::DyadicFloat128; + let z = DyadicFloat128::new_from_f64(a); + let k = DyadicFloat128::new_from_f64(b); + let p = z * k + DyadicFloat128::new_from_f64(c); + p.fast_as_f64() + } +} + +// Executes mandatory FMA +// if not available will be simulated through Dekker and Veltkamp +#[inline(always)] +#[allow(unused)] +pub(crate) fn dd_fmlaf(a: f32, b: f32, c: f32) -> f32 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + f_fmlaf(a, b, c) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + (a as f64 * b as f64 + c as f64) as f32 + } +} + +#[allow(dead_code)] +#[inline(always)] +pub(crate) fn c_mlaf + Add + MulAdd>( + a: T, + b: T, + c: T, +) -> T { + mlaf(c, a, b) +} + +/// Copies sign from `y` to `x` +#[inline] +pub const fn copysignfk(x: f32, y: f32) -> f32 { + f32::from_bits((x.to_bits() & !(1 << 31)) ^ (y.to_bits() & (1 << 31))) +} + +// #[inline] +// // Founds n in ln(𝑥)=ln(𝑎)+𝑛ln(2) +// pub(crate) const fn ilogb2kf(d: f32) -> i32 { +// (((d.to_bits() as i32) >> 23) & 0xff) - 0x7f +// } +// +// #[inline] +// // Founds a in x=a+𝑛ln(2) +// pub(crate) const fn ldexp3kf(d: f32, n: i32) -> f32 { +// f32::from_bits(((d.to_bits() as i32) + (n << 23)) as u32) +// } + +#[inline] +pub(crate) const fn pow2if(q: i32) -> f32 { + f32::from_bits((q.wrapping_add(0x7f) as u32) << 23) +} + +/// Round towards whole integral number +#[inline] +pub(crate) const fn rintk(x: f64) -> f64 { + (if x < 0. { x - 0.5 } else { x + 0.5 }) as i64 as f64 +} + +/// Computes 2^n +#[inline(always)] +pub(crate) const fn pow2i(q: i32) -> f64 { + f64::from_bits((q.wrapping_add(0x3ff) as u64) << 52) +} + +// #[inline] +// pub(crate) const fn ilogb2k(d: f64) -> i32 { +// (((d.to_bits() >> 52) & 0x7ff) as i32) - 0x3ff +// } +// +// #[inline] +// pub(crate) const fn ldexp3k(d: f64, e: i32) -> f64 { +// f64::from_bits(((d.to_bits() as i64) + ((e as i64) << 52)) as u64) +// } + +/// Copies sign from `y` to `x` +#[inline] +pub const fn copysignk(x: f64, y: f64) -> f64 { + f64::from_bits((x.to_bits() & !(1 << 63)) ^ (y.to_bits() & (1 << 63))) +} + +#[inline] +pub(crate) const fn min_normal_f64() -> f64 { + let exponent_bits = 1u64 << 52; + let bits = exponent_bits; + + f64::from_bits(bits) +} + +#[inline] +const fn mask_trailing_ones_u32(len: u32) -> u32 { + if len >= 32 { + u32::MAX // All ones if length is 64 or more + } else { + (1u32 << len).wrapping_sub(1) + } +} + +pub(crate) const EXP_MASK_F32: u32 = mask_trailing_ones_u32(8) << 23; + +#[inline] +pub(crate) fn set_exponent_f32(x: u32, new_exp: u32) -> u32 { + let encoded_mask = new_exp.wrapping_shl(23) & EXP_MASK_F32; + x ^ ((x ^ encoded_mask) & EXP_MASK_F32) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_is_integer() { + assert_eq!(is_integer(5.), true); + assert_eq!(is_integer(6.), true); + assert_eq!(is_integer(6.01), false); + assert_eq!(is_odd_integer(5.), true); + assert_eq!(is_odd_integer(6.), false); + assert_eq!(is_odd_integer(6.01), false); + assert_eq!(is_integerf(5.), true); + assert_eq!(is_integerf(6.), true); + assert_eq!(is_integerf(6.01), false); + assert_eq!(is_odd_integerf(5.), true); + assert_eq!(is_odd_integerf(6.), false); + assert_eq!(is_odd_integerf(6.01), false); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_d.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_d.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_d.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_d.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,485 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integer, is_odd_integer}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::{log1p_f64_dyadic, log1p_fast_dd}; +use crate::pow_exec::{exp_dyadic, pow_exp_dd}; +use crate::triple_double::TripleDouble; + +/// Computes (1+x)^y +/// +pub fn f_compound(x: f64, y: f64) -> f64 { + /* + Rules from IEEE 754-2019 for compound (x, n) with n integer: + (a) compound (x, 0) is 1 for x >= -1 or quiet NaN + (b) compound (-1, n) is +Inf and signals the divideByZero exception for n < 0 + (c) compound (-1, n) is +0 for n > 0 + (d) compound (+/-0, n) is 1 + (e) compound (+Inf, n) is +Inf for n > 0 + (f) compound (+Inf, n) is +0 for n < 0 + (g) compound (x, n) is qNaN and signals the invalid exception for x < -1 + (h) compound (qNaN, n) is qNaN for n <> 0. + */ + + let x_sign = x.is_sign_negative(); + let y_sign = y.is_sign_negative(); + + let x_abs = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_abs = y.to_bits() & 0x7fff_ffff_ffff_ffff; + + const MANTISSA_MASK: u64 = (1u64 << 52) - 1; + + let y_mant = y.to_bits() & MANTISSA_MASK; + let x_u = x.to_bits(); + let x_a = x_abs; + let y_a = y_abs; + + // If x or y is signaling NaN + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + + let mut s = 1.0; + + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let ay = y.to_bits() & 0x7fff_ffff_ffff_ffff; + + // The double precision number that is closest to 1 is (1 - 2^-53), which has + // log2(1 - 2^-53) ~ -1.715...p-53. + // So if |y| > |1075 / log2(1 - 2^-53)|, and x is finite: + // |y * log2(x)| = 0 or > 1075. + // Hence, x^y will either overflow or underflow if x is not zero. + if y_mant == 0 + || y_a > 0x43d7_4910_d52d_3052 + || x_u == 1f64.to_bits() + || x_u >= f64::INFINITY.to_bits() + || x_u < f64::MIN.to_bits() + { + // Exceptional exponents. + if y == 0.0 { + return 1.0; + } + + // (h) compound(qNaN, n) is qNaN for n ≠ 0 + if x.is_nan() { + if y != 0. { + return x; + } // propagate qNaN + return 1.0; + } + + // (d) compound(±0, n) is 1 + if x == 0.0 { + return 1.0; + } + + // (e, f) compound(+Inf, n) + if x.is_infinite() && x > 0.0 { + return if y > 0. { x } else { 0.0 }; + } + + // (g) compound(x, n) is qNaN and signals invalid for x < -1 + if x < -1.0 { + // Optional: raise invalid explicitly + return f64::NAN; + } + + // (b, c) compound(-1, n) + if x == -1.0 { + return if y < 0. { f64::INFINITY } else { 0.0 }; + } + + match y_a { + 0x3fe0_0000_0000_0000 => { + // TODO: speed up x^(-1/2) with rsqrt(x) when available. + if x == 0.0 { + return 1.0; + } + let z = DoubleDouble::from_full_exact_add(x, 1.0).sqrt(); + return if y_sign { + z.recip().to_f64() + } else { + z.to_f64() + }; + } + 0x3ff0_0000_0000_0000 => { + return if y_sign { + const ONES: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let z = DyadicFloat128::new_from_f64(x) + ONES; + z.reciprocal().fast_as_f64() + } else { + DoubleDouble::from_full_exact_add(x, 1.0).to_f64() + }; + } + 0x4000_0000_0000_0000 => { + let z0 = DoubleDouble::from_full_exact_add(x, 1.0); + let z = DoubleDouble::quick_mult(z0, z0); + return if y_sign { + z.recip().to_f64() + } else { + f64::copysign(z.to_f64(), x) + }; + } + _ => {} + } + + // |y| > |1075 / log2(1 - 2^-53)|. + if y_a >= 0x7ff0_0000_0000_0000 { + // y is inf or nan + if y_mant != 0 { + // y is NaN + // pow(1, NaN) = 1 + // pow(x, NaN) = NaN + return if x_u == 1f64.to_bits() { 1.0 } else { y }; + } + + // Now y is +-Inf + if f64::from_bits(x_abs).is_nan() { + // pow(NaN, +-Inf) = NaN + return x; + } + + if x == 0.0 && y_sign { + // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO + return f64::INFINITY; + } + // pow (|x| < 1, -inf) = +inf + // pow (|x| < 1, +inf) = 0.0 + // pow (|x| > 1, -inf) = 0.0 + // pow (|x| > 1, +inf) = +inf + return if (x_a < 1f64.to_bits()) == y_sign { + f64::INFINITY + } else { + 0.0 + }; + } + + // y is finite and non-zero. + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return if out_is_neg { -0.0 } else { 0.0 }; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + + // x is finite and negative, and y is a finite integer. + if x_sign { + if is_integer(y) { + if is_odd_integer(y) { + // sign = -1.0; + static CS: [f64; 2] = [1.0, -1.0]; + + // set sign to 1 for y even, to -1 for y odd + let y_parity = if (y.abs()) >= f64::from_bits(0x4340000000000000) { + 0usize + } else { + (y as i64 & 0x1) as usize + }; + s = CS[y_parity]; + } + } else { + // pow( negative, non-integer ) = NaN + return f64::NAN; + } + } + + // y is finite and non-zero. + + if x_u == 1f64.to_bits() { + // compound(1, y) = 1 + return 2.0; + } + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return if out_is_neg { -0.0 } else { 0.0 }; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + + let min_abs = f64::min(f64::from_bits(ax), f64::from_bits(ay)).to_bits(); + let max_abs = f64::max(f64::from_bits(ax), f64::from_bits(ay)).to_bits(); + let min_exp = min_abs.wrapping_shr(52); + let max_exp = max_abs.wrapping_shr(52); + + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // then will go with hard path + if scale_up || scale_down { + return compound_accurate(x, y, s); + } + } + } + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + let straight_path_precondition: bool = true; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + let straight_path_precondition: bool = y.is_sign_positive(); + // this is correct only for positive exponent number without FMA, + // otherwise reciprocal may overflow. + // y is integer and in [-102;102] and |x|<2^10 + if is_integer(y) + && y_a <= 0x4059800000000000u64 + && x_a <= 0x4090000000000000u64 + && x_a > 0x3cc0_0000_0000_0000 + && straight_path_precondition + { + let mut s = DoubleDouble::from_full_exact_add(1.0, x); + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { + s + } else { + DoubleDouble::new(0., 1.) + }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = DoubleDouble::mult(s, s); + if iter_count % 2 != 0 { + acc = DoubleDouble::mult(acc, s); + } + } + + let dz = if y.is_sign_negative() { + acc.recip() + } else { + acc + }; + let ub = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), -dz.hi, dz.lo); // 2^-59 + let lb = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), dz.hi, dz.lo); // 2^-59 + if ub == lb { + return dz.to_f64(); + } + return mul_fixed_power_hard(x, y); + } + + let l = log1p_fast_dd(x); + let ey = ((y.to_bits() >> 52) & 0x7ff) as i32; + if ey < 0x36 || ey >= 0x7f5 { + return compound_accurate(x, y, s); + } + + let r = DoubleDouble::quick_mult_f64(l, y); + let res = pow_exp_dd(r, s); + let res_min = res.hi + f_fmla(f64::from_bits(0x3bf0000000000000), -res.hi, res.lo); + let res_max = res.hi + f_fmla(f64::from_bits(0x3bf0000000000000), res.hi, res.lo); + if res_min == res_max { + return res_max; + } + + compound_accurate(x, y, s) +} + +#[cold] +fn compound_accurate(x: f64, y: f64, s: f64) -> f64 { + /* the idea of returning res_max instead of res_min is due to Laurent + Théry: it is better in case of underflow since res_max = +0 always. */ + + let f_y = DyadicFloat128::new_from_f64(y); + + let r = log1p_f64_dyadic(x) * f_y; + let mut result = exp_dyadic(r); + + // 2^R.ex <= R < 2^(R.ex+1) + + /* case R < 2^-1075: underflow case */ + if result.exponent < -1075 { + return 0.5 * (s * f64::from_bits(0x0000000000000001)); + } + if result.exponent >= 1025 { + return 1.0; + } + + result.sign = if s == -1.0 { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + + result.fast_as_f64() +} + +#[cold] +#[inline(never)] +fn mul_fixed_power_hard(x: f64, y: f64) -> f64 { + let mut s = TripleDouble::from_full_exact_add(1.0, x); + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { + s + } else { + TripleDouble::new(0., 0., 1.) + }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = TripleDouble::quick_mult(s, s); + if iter_count % 2 != 0 { + acc = TripleDouble::quick_mult(acc, s); + } + } + + if y.is_sign_negative() { + acc.recip().to_f64() + } else { + acc.to_f64() + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_compound() { + assert_eq!(f_compound(4831835136., -13.),0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012780345669344118 ); + assert_eq!( + f_compound(11468322278342656., 2.9995136260713475), + 1481455956234813000000000000000000000000000000000. + ); + assert_eq!(f_compound(0.9999999999999999, 3.), 7.999999999999999); + assert_eq!( + f_compound(1.0039215087890625, 10.000000000349134), + 1044.2562119607103 + ); + assert_eq!(f_compound(10., 18.0), 5559917313492231000.0); + assert_eq!( + f_compound(131071.65137729312, 2.000001423060894), + 17180328027.532265 + ); + assert_eq!(f_compound(2., 5.), 243.); + assert_eq!(f_compound(126.4324324, 126.4324324), 1.4985383310514043e266); + assert_eq!(f_compound(0.4324324, 126.4324324), 5.40545942023447e19); + assert!(f_compound(-0.4324324, 126.4324324).is_nan()); + assert_eq!(f_compound(0.0, 0.0), 1.0); + assert_eq!(f_compound(0.0, -1. / 2.), 1.0); + assert_eq!(f_compound(-1., -1. / 2.), f64::INFINITY); + assert_eq!(f_compound(f64::INFINITY, -1. / 2.), 0.0); + assert_eq!(f_compound(f64::INFINITY, 1. / 2.), f64::INFINITY); + assert_eq!(f_compound(46.3828125, 46.3828125), 5.248159634773675e77); + } + + #[test] + fn test_compound_exotic_cases() { + assert_eq!(f_compound(0.9999999850987819, -1.), 0.5000000037253046); + assert_eq!( + f_compound(22427285907987670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000., + -1.), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004458854290718438 + ); + assert_eq!(f_compound(0.786438105629145, 607.999512419221), + 1616461095392737200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_compound( 1.0000002381857613, 960.8218657970428), + 17228671476562465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_compound(1., 1.0000000000000284), 2.); + assert_eq!(f_compound(1., f64::INFINITY), f64::INFINITY); + assert_eq!( + f_compound(10.000000000000007, -8.), + 0.00000000466507380209731 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,573 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log1p_fast_dd; +use crate::pow_exec::pow_expm1_1; + +/// Computes (1+x)^y - 1 +/// +/// max found ULP 0.56 +pub fn f_compound_m1(x: f64, y: f64) -> f64 { + /* + Rules from IEEE 754-2019 for compound (x, n) with n integer: + (a) compound (x, 0) is 1 for x >= -1 or quiet NaN + (b) compound (-1, n) is +Inf and signals the divideByZero exception for n < 0 + (c) compound (-1, n) is +0 for n > 0 + (d) compound (+/-0, n) is 1 + (e) compound (+Inf, n) is +Inf for n > 0 + (f) compound (+Inf, n) is +0 for n < 0 + (g) compound (x, n) is qNaN and signals the invalid exception for x < -1 + (h) compound (qNaN, n) is qNaN for n <> 0. + */ + + let x_sign = x.is_sign_negative(); + let y_sign = y.is_sign_negative(); + + let x_abs = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_abs = y.to_bits() & 0x7fff_ffff_ffff_ffff; + + const MANTISSA_MASK: u64 = (1u64 << 52) - 1; + + let y_mant = y.to_bits() & MANTISSA_MASK; + let x_u = x.to_bits(); + let x_a = x_abs; + let y_a = y_abs; + + // If x or y is signaling NaN + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + + let mut s = 1.0; + + // The double precision number that is closest to 1 is (1 - 2^-53), which has + // log2(1 - 2^-53) ~ -1.715...p-53. + // So if |y| > |1075 / log2(1 - 2^-53)|, and x is finite: + // |y * log2(x)| = 0 or > 1075. + // Hence, x^y will either overflow or underflow if x is not zero. + if y_mant == 0 + || y_a > 0x43d7_4910_d52d_3052 + || x_u == 1f64.to_bits() + || x_u >= f64::INFINITY.to_bits() + || x_u < f64::MIN.to_bits() + { + // Exceptional exponents. + if y == 0.0 { + return 0.0; + } + + // (h) compound(qNaN, n) is qNaN for n ≠ 0 + if x.is_nan() { + if y != 0. { + return x; + } // propagate qNaN + return 0.0; + } + + // (d) compound(±0, n) is 1 + if x == 0.0 { + return 0.0; + } + + // (e, f) compound(+Inf, n) + if x.is_infinite() && x > 0.0 { + return if y > 0. { x } else { -1.0 }; + } + + // (g) compound(x, n) is qNaN and signals invalid for x < -1 + if x < -1.0 { + // Optional: raise invalid explicitly + return f64::NAN; + } + + // (b, c) compound(-1, n) + if x == -1.0 { + return if y < 0. { f64::INFINITY } else { -1.0 }; + } + + match y_a { + // 0x3fe0_0000_0000_0000 => { + // if x == 0.0 { + // return 0.0; + // } + // let z = Dekker::from_full_exact_add(x, 1.0).sqrt(); + // if y_sign { + // const M_ONES: DyadicFloat128 = DyadicFloat128 { + // sign: DyadicSign::Neg, + // exponent: -127, + // mantissa: 0x80000000_00000000_00000000_00000000_u128, + // }; + // let z = DyadicFloat128::new_from_f64(z.to_f64()); + // (z.reciprocal() + M_ONES).fast_as_f64() + // } else { + // const M_ONES: DyadicFloat128 = DyadicFloat128 { + // sign: DyadicSign::Neg, + // exponent: -127, + // mantissa: 0x80000000_00000000_00000000_00000000_u128, + // }; + // let z = DyadicFloat128::new_from_f64(z.to_f64()); + // (z + M_ONES).fast_as_f64() + // }; + // } + 0x3ff0_0000_0000_0000 => { + return if y_sign { + let z = DyadicFloat128::new_from_f64(x); + const ONES: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + const M_ONES: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let p = (z + ONES).reciprocal() + M_ONES; + p.fast_as_f64() + } else { + x + }; + } + 0x4000_0000_0000_0000 => { + const ONES: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let z0 = DyadicFloat128::new_from_f64(x) + ONES; + let z = z0 * z0; + const M_ONES: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + return if y_sign { + (z.reciprocal() + M_ONES).fast_as_f64() + } else { + f64::copysign((z + M_ONES).fast_as_f64(), x) + }; + } + _ => {} + } + + // |y| > |1075 / log2(1 - 2^-53)|. + if y_a >= 0x7ff0_0000_0000_0000 { + // y is inf or nan + if y_mant != 0 { + // y is NaN + // pow(1, NaN) = 1 + // pow(x, NaN) = NaN + return if x_u == 1f64.to_bits() { 1.0 } else { y }; + } + + // Now y is +-Inf + if f64::from_bits(x_abs).is_nan() { + // pow(NaN, +-Inf) = NaN + return x; + } + + if x_a == 0x3ff0_0000_0000_0000 { + // pow(+-1, +-Inf) = 1.0 + return 0.0; + } + + if x == 0.0 && y_sign { + // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO + return f64::INFINITY; + } + // pow (|x| < 1, -inf) = +inf + // pow (|x| < 1, +inf) = 0.0 + // pow (|x| > 1, -inf) = 0.0 + // pow (|x| > 1, +inf) = +inf + return if (x_a < 1f64.to_bits()) == y_sign { + f64::INFINITY + } else { + -1.0 + }; + } + + // y is finite and non-zero. + + if x_u == 1f64.to_bits() { + // pow(1, y) = 1 + return 0.0; + } + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return -1.0; + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return if out_is_neg { -1.0 } else { 1.0 }; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + + // x is finite and negative, and y is a finite integer. + if x_sign { + if is_integer(y) { + if is_odd_integer(y) { + // sign = -1.0; + static CS: [f64; 2] = [1.0, -1.0]; + + // set sign to 1 for y even, to -1 for y odd + let y_parity = if (y.abs()) >= f64::from_bits(0x4340000000000000) { + 0usize + } else { + (y as i64 & 0x1) as usize + }; + s = CS[y_parity]; + } + } else { + // pow( negative, non-integer ) = NaN + return f64::NAN; + } + } + + // y is finite and non-zero. + + if x_u == 1f64.to_bits() { + // pow(1, y) = 1 + return 0.0; + } + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return -1.; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + } + + // evaluate (1+x)^y explicitly for integer y in [-1024,1024] range and |x|<2^64 + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + let straight_path_precondition: bool = true; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + let straight_path_precondition: bool = y.is_sign_positive(); + // this is correct only for positive exponent number without FMA, + // otherwise reciprocal may overflow. + if is_integer(y) + && y_a <= 0x4059800000000000u64 + && x_a <= 0x4090000000000000u64 + && x_a > 0x3cc0_0000_0000_0000 + && straight_path_precondition + { + let mut s = DoubleDouble::from_full_exact_add(1.0, x); + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { + s + } else { + DoubleDouble::new(0., 1.) + }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = DoubleDouble::mult(s, s); + if iter_count % 2 != 0 { + acc = DoubleDouble::mult(acc, s); + } + } + + let mut dz = if y.is_sign_negative() { + acc.recip() + } else { + acc + }; + + dz = DoubleDouble::full_add_f64(dz, -1.); + let ub = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), -dz.hi, dz.lo); // 2^-59 + let lb = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), dz.hi, dz.lo); // 2^-59 + if ub == lb { + return dz.to_f64(); + } + return mul_fixed_power_hard(x, y); + } + + // approximate log1p(x) + let l = log1p_fast_dd(x); + + let ey = ((y.to_bits() >> 52) & 0x7ff) as i32; + if ey < 0x36 || ey >= 0x7f5 { + return 0.; + } + + let r = DoubleDouble::quick_mult_f64(l, y); + let res = pow_expm1_1(r, s); + + res.to_f64() +} + +#[cold] +#[inline(never)] +fn mul_fixed_power_hard(x: f64, y: f64) -> f64 { + const ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + const M_ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let mut s = DyadicFloat128::new_from_f64(x) + ONE; + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { s } else { ONE }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = s * s; + if iter_count % 2 != 0 { + acc = acc * s; + } + } + + if y.is_sign_negative() { + (acc.reciprocal() + M_ONE).fast_as_f64() + } else { + (acc + M_ONE).fast_as_f64() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_compound_exotic() { + assert_eq!( + f_compound_m1(0.000152587890625, -8.484374999999998), + -0.0012936766014690006 + ); + assert_eq!( + f_compound_m1( + 0.00000000000000799360578102344, + -0.000000000000000000000001654361225106131 + ), + -0.000000000000000000000000000000000000013224311452909338 + ); + assert_eq!( + f_compound_m1( 4.517647064592699, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055329046628180653), + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009449932890153435 + ); + assert_eq!(f_compound_m1( + 11944758478933760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000., + -1242262631503757300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000., + ), -1.); + } + + #[test] + fn test_compound_m1() { + assert_eq!( + f_compound_m1(0.0000000000000009991998751296936, -4.), + -0.000000000000003996799500518764 + ); + assert_eq!(f_compound_m1(-0.003173828125, 25.), -0.0763960132649781); + assert_eq!(f_compound_m1(3., 2.8927001953125), 54.154259038961406); + assert_eq!( + f_compound_m1(-0.43750000000000044, 19.), + -0.9999821216263793 + ); + assert_eq!( + f_compound_m1(127712., -2.0000000000143525), + -0.9999999999386903 + ); + assert_eq!( + f_compound_m1(-0.11718749767214207, 2893226081485815000000000000000.), + -1. + ); + assert_eq!( + f_compound_m1(2418441935074801400000000., 512.), + f64::INFINITY + ); + assert_eq!( + f_compound_m1(32.50198364245834, 128000.00000000093), + f64::INFINITY + ); + assert_eq!( + f_compound_m1(1.584716796877785, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004168916810703412), + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003958869879428553 + ); + assert_eq!( + f_compound_m1( + -0.000000000000000000000000000000001997076793037533, + 366577337071337140000000000000000f64 + ), + -0.5190938261758579 + ); + assert_eq!(f_compound_m1(2.1075630259863374, 0.5), 00.7628281328553664); + assert_eq!(f_compound_m1(2.1078916412661783, 0.5), 0.7629213372315222); + assert_eq!(f_compound_m1(3.0000000000001115, -0.5), -0.500000000000007); + assert_eq!( + f_compound_m1(0.0004873839215895903, 3.), + 0.0014628645098045245 + ); + + assert_eq!(f_compound_m1(-0.483765364602732, 3.), -0.862424399516842); + assert_eq!(f_compound_m1(3.0000001192092896, -2.), -0.9375000037252902); + assert_eq!(f_compound_m1(29.38323424607434, -1.), -0.9670871115332561); + + assert_eq!(f_compound_m1(-0.4375, 4.), -0.8998870849609375); + assert_eq!( + f_compound_m1(-0.0039033182037826464, 3.), + -0.011664306402886494 + ); + assert_eq!( + f_compound_m1(0.000000000000000000000000000000000000007715336350455947, + -262034087537726030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + -1., + ); + assert_eq!(f_compound_m1(10.000000059604645, 10.), 25937426005.44638); + assert_eq!(f_compound_m1(10., -308.25471555814863), -1.0); + assert_eq!( + f_compound_m1(5.4172231599824623E-312, 9.4591068440831498E+164), + 5.124209266851586e-147 + ); + assert_eq!( + f_compound_m1(5.8776567263633397E-39, 3.4223548116804511E-310), + 0.0 + ); + assert_eq!( + f_compound_m1(5.8639503496997932E-148, -7.1936801558778956E+305), + 0.0 + ); + assert_eq!( + f_compound_m1(0.9908447265624999, + -19032028850336152000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + -1. + ); + assert_eq!( + f_compound_m1(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006952247559980936, + 5069789834563405000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + 3.524643400695958e-163 + ); + assert_eq!( + f_compound_m1(1.000000000000341, + -69261261804788370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + -1. + ); + assert_eq!( + f_compound_m1( + 0.0000000000000001053438024827798, + 0.0000000000000001053438024827798 + ), + 0.000000000000000000000000000000011097316721530923 + ); + assert_eq!( + f_compound_m1( + 0.00000000000000010755285551056508, + 0.00000000000000010755285551056508 + ), + 0.00000000000000000000000000000001156761672847649 + ); + + assert_eq!(f_compound_m1(2.4324324, 1.4324324), 4.850778380908823); + assert_eq!(f_compound_m1(2., 5.), 242.); + assert_eq!(f_compound_m1(0.4324324, 126.4324324), 5.40545942023447e19); + assert!(f_compound_m1(-0.4324324, 126.4324324).is_nan()); + assert_eq!(f_compound_m1(0.0, 0.0), 0.0); + assert_eq!(f_compound_m1(0.0, -1. / 2.), 0.0); + assert_eq!(f_compound_m1(-1., -1. / 2.), f64::INFINITY); + assert_eq!(f_compound_m1(f64::INFINITY, -1. / 2.), -1.0); + assert_eq!(f_compound_m1(f64::INFINITY, 1. / 2.), f64::INFINITY); + assert_eq!(f_compound_m1(46.3828125, 46.3828125), 5.248159634773675e77); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compound_m1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,439 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::compound::compoundf::{ + COMPOUNDF_EXP2_T, COMPOUNDF_EXP2_U, compoundf_exp2_poly2, compoundf_log2p1_accurate, + compoundf_log2p1_fast, +}; +use crate::double_double::DoubleDouble; +use crate::exponents::exp2m1_accurate_tiny; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +// INVLOG2 = 1/log(2) * (1 + eps1) with |eps1| < 2^-55.976 +const INVLOG2: f64 = f64::from_bits(0x3ff71547652b82fe); + +#[cold] +#[inline(never)] +fn as_compoundm1f_special(x: f32, y: f32) -> f32 { + let nx = x.to_bits(); + let ny = y.to_bits(); + let ax: u32 = nx.wrapping_shl(1); + let ay: u32 = ny.wrapping_shl(1); + + if ax == 0 || ay == 0 { + // x or y is 0 + if ax == 0 { + // compound(0,y) = 1 except for y = sNaN + return if y.is_nan() { x + y } else { 0.0 }; + } + + if ay == 0 { + // compound (x, 0) + if x.is_nan() { + return x + y; + } // x = sNaN + return if x < -1.0 { + f32::NAN // rule (g) + } else { + 0.0 + }; // rule (a) + } + } + + let mone = (-1.0f32).to_bits(); + if ay >= 0xffu32 << 24 { + // y=Inf/NaN + // the case x=0 was already checked above + if ax > 0xffu32 << 24 { + return x + y; + } // x=NaN + if ay == 0xffu32 << 24 { + // y = +/-Inf + if nx > mone { + return f32::NAN; + } // rule (g) + let sy = ny >> 31; // sign bit of y + if nx == mone { + return if sy == 0 { + -1. // Rule (c) + } else { + f32::INFINITY // Rule (b) + }; + } + if x < 0.0 { + return if sy == 0 { -1. } else { f32::INFINITY }; + } + if x > 0.0 { + return if sy != 0 { -1. } else { f32::INFINITY }; + } + return 0.0; + } + return x + y; // case y=NaN + } + + if nx >= mone || nx >= 0xffu32 << 23 { + // x is Inf, NaN or <= -1 + if ax == 0xffu32 << 24 { + // x is +Inf or -Inf + if (nx >> 31) != 0 { + return f32::NAN; + } // x = -Inf, rule (g) + // (1 + Inf)^y = +Inf for y > 0, +0 for y < 0 + return (if (ny >> 31) != 0 { 1.0 / x } else { x }) - 1.; + } + if ax > 0xffu32 << 24 { + return x + y; + } // x is NaN + if nx > mone { + return f32::NAN; // x < -1.0: rule (g) + } + // now x = -1 + return if (ny >> 31) != 0 { + // y < 0 + f32::INFINITY + } else { + // y > 0 + -1.0 + }; + } + -1. +} + +/* for |z| <= 2^-6, returns an approximation of 2^z +with absolute error < 2^-43.540 */ +#[inline] +pub(crate) fn compoundf_expf_poly(z: f64) -> f64 { + /* Q is a degree-4 polynomial generated by Sollya (cf compoundf_expf.sollya) + with absolute error < 2^-43.549 */ + const Q: [u64; 5] = [ + 0x3fe62e42fefa39ef, + 0x3fcebfbdff8098eb, + 0x3fac6b08d7045dc3, + 0x3f83b2b276ce985d, + 0x3f55d8849c67ace4, + ]; + let z2 = z * z; + let c3 = dd_fmla(f64::from_bits(Q[4]), z, f64::from_bits(Q[3])); + let c0 = dd_fmla(f64::from_bits(Q[1]), z, f64::from_bits(Q[0])); + let c2 = dd_fmla(c3, z, f64::from_bits(Q[2])); + dd_fmla(c2, z2, c0) * z +} + +/* return the correct rounding of (1+x)^y, otherwise -1.0 +where t is an approximation of y*log2(1+x) with absolute error < 2^-40.680, +assuming 0x1.7154759a0df53p-24 <= |t| <= 150 +exact is non-zero iff (1+x)^y is exact or midpoint */ +fn exp2m1_fast(t: f64) -> f64 { + let k = t.cpu_round_ties_even(); // 0 <= |k| <= 150 + let mut r = t - k; // |r| <= 1/2, exact + let mut v: u64 = (3.015625 + r).to_bits(); // 2.5 <= v <= 3.5015625 + // we add 2^-6 so that i is rounded to nearest + let i: i32 = (v >> 46) as i32 - 0x10010; // 0 <= i <= 32 + r -= f64::from_bits(COMPOUNDF_EXP2_T[i as usize]); // exact + // now |r| <= 2^-6 + // 2^t = 2^k * exp2_U[i][0] * 2^r + let mut s = f64::from_bits(COMPOUNDF_EXP2_U[i as usize].1); + let su = unsafe { ((k.to_int_unchecked::() as u64).wrapping_add(0x3ffu64)) << 52 }; // k is already integer + s *= f64::from_bits(su); + let q_poly = compoundf_expf_poly(r); + v = q_poly.to_bits(); + /* the absolute error on exp2_U[i][0] is bounded by 2^-53.092, with + exp2_U[i][0] < 2^0.5, and that on q1(r) is bounded by 2^-43.540, + with |q1(r)| < 1.011, thus |v| < 1.43, and the absolute error on v is + bounded by ulp(v) + 2^0.5s * 2^-43.540 + 2^-53.092 * 1.011 < 2^-43.035. + Now t approximates u := y*log2(1+x) with |t-u| < 2^-40.680 thus + 2^u = 2^t * (1 + eps) with eps < 2^(2^-40.680)-1 < 2^-41.208. + The total absolute error is thus bounded by 2^-43.035 + 2^-41.208 + < 2^-40.849. */ + let mut err: u64 = 0x3d61d00000000000; // 2^-40.849 < 0x1.1dp-41 + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v = f_fmla(f64::from_bits(v), s, s - 1f64).to_bits(); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let p0 = DoubleDouble::from_full_exact_add(s, -1.); + let z = DoubleDouble::from_exact_mult(f64::from_bits(v), s); + v = DoubleDouble::add(z, p0).to_f64().to_bits(); + } + + // in case of potential underflow, we defer to the accurate path + if f64::from_bits(v) < f64::from_bits(0x3d61d00000000000) { + return -1.0; + } + err = unsafe { err.wrapping_add((k.to_int_unchecked::() << 52) as u64) }; // scale the error by 2^k too + let lb = (f64::from_bits(v) - f64::from_bits(err)) as f32; + let rb = (f64::from_bits(v) + f64::from_bits(err)) as f32; + if lb != rb { + return -1.0; + } // rounding test failed + + f64::from_bits(v) +} + +fn compoundf_exp2m1_accurate(x_dd: DoubleDouble, x: f32, y: f32) -> f32 { + if y == 1.0 { + let res = x; + return res; + } + + // check easy cases h+l is tiny thus 2^(h+l) rounds to 1, 1- or 1+ + // if x_dd.hi.abs() <= f64::from_bits(0x3fc0000000000000u64) { + // /* the relative error between h and y*log2(1+x) is bounded by + // (1 + 2^-48.445) * (1 + 2^-91.120) - 1 < 2^-48.444. + // 2^h rounds to 1 to nearest for |h| <= H0 := 0x1.715476af0d4d9p-25. + // The above threshold is such that h*(1+2^-48.444) < H0. */ + // return exp2m1_accurate_tiny(x_dd.to_f64()) as f32; + // } + + let k = x_dd.hi.cpu_round_ties_even(); // |k| <= 150 + + // check easy cases h+l is tiny thus 2^(h+l) rounds to 1, 1- or 1+ + if k == 0. && x_dd.hi.abs() <= f64::from_bits(0x3e6715476af0d4c8) { + /* the relative error between h and y*log2(1+x) is bounded by + (1 + 2^-48.445) * (1 + 2^-91.120) - 1 < 2^-48.444. + 2^h rounds to 1 to nearest for |h| <= H0 := 0x1.715476af0d4d9p-25. + The above threshold is such that h*(1+2^-48.444) < H0. */ + // let z0 = 1.0 + x_dd.hi * 0.5; + // let k = Dekker::from_exact_sub(z0, 1.); + // return k.to_f64() as f32; + + use crate::exponents::GenericExpfBackend; + return exp2m1_accurate_tiny(x_dd.to_f64(), &GenericExpfBackend {}) as f32; + } + + let r = x_dd.hi - k; // |r| <= 1/2, exact + // since r is an integer multiple of ulp(h), fast_two_sum() below is exact + let mut v_dd = DoubleDouble::from_exact_add(r, x_dd.lo); + let mut v = (3.015625 + v_dd.hi).to_bits(); // 2.5 <= v <= 3.5015625 + // we add 2^-6 so that i is rounded to nearest + let i: i32 = ((v >> 46) as i32).wrapping_sub(0x10010); // 0 <= i <= 32 + // h is near (i-16)/2^5 + v_dd.hi -= f64::from_bits(COMPOUNDF_EXP2_T[i as usize]); // exact + + // now |h| <= 2^-6 + // 2^(h+l) = 2^k * exp2_U[i] * 2^(h+l) + v_dd = DoubleDouble::from_exact_add(v_dd.hi, v_dd.lo); + let q = compoundf_exp2_poly2(v_dd); + + /* we have 0.989 < qh < 1.011, |ql| < 2^-51.959, and + |qh + ql - 2^(h+l)| < 2^-85.210 */ + let exp2u = DoubleDouble::from_bit_pair(COMPOUNDF_EXP2_U[i as usize]); + let mut q = DoubleDouble::quick_mult(exp2u, q); + + q = DoubleDouble::from_exact_add(q.hi, q.lo); + + let mut du = unsafe { + k.to_int_unchecked::() + .wrapping_add(0x3ff) + .wrapping_shl(52) as u64 + }; + du = f64::from_bits(du).to_bits(); + let scale = f64::from_bits(du); + + q.hi *= scale; + q.lo *= scale; + + let zf: DoubleDouble = DoubleDouble::from_full_exact_add(q.hi, -1.0); + q.lo += zf.lo; + q.hi = zf.hi; + + v = q.to_f64().to_bits(); + + f64::from_bits(v) as f32 +} + +// at input, exact is non-zero iff (1+x)^y is exact +// x,y=0x1.0f6f1ap+1,0x1.c643bp+5: 49 identical bits after round bit +// x,y=0x1.ef272cp+15,-0x1.746ab2p+1: 55 identical bits after round bit +// x,y=0x1.07ffcp+0,-0x1.921a8ap+4: 47 identical bits after round bit +#[cold] +#[inline(never)] +fn compoundm1f_accurate(x: f32, y: f32) -> f32 { + let mut v = compoundf_log2p1_accurate(x as f64); + v = DoubleDouble::quick_mult_f64(v, y as f64); + compoundf_exp2m1_accurate(v, x, y) +} + +/// Computes compound (1.0 + x)^y - 1 +/// +/// Max ULP 0.5 +#[inline] +pub fn f_compound_m1f(x: f32, y: f32) -> f32 { + /* Rules from IEEE 754-2019 for compound (x, n) with n integer: + (a) compound (x, 0) is 1 for x >= -1 or quiet NaN + (b) compound (-1, n) is +Inf and signals the divideByZero exception for n < 0 + (c) compound (-1, n) is +0 for n > 0 + (d) compound (+/-0, n) is 1 + (e) compound (+Inf, n) is +Inf for n > 0 + (f) compound (+Inf, n) is +0 for n < 0 + (g) compound (x, n) is qNaN and signals the invalid exception for x < -1 + (h) compound (qNaN, n) is qNaN for n <> 0. + */ + let mone = (-1.0f32).to_bits(); + let nx = x.to_bits(); + let ny = y.to_bits(); + if nx >= mone { + return as_compoundm1f_special(x, y); + } // x <= -1 + // now x > -1 + + let ax: u32 = nx.wrapping_shl(1); + let ay: u32 = ny.wrapping_shl(1); + + if ax == 0 || ax >= 0xffu32 << 24 || ay == 0 || ay >= 0xffu32 << 24 { + return as_compoundm1f_special(x, y); + } // x=+-0 || x=+-inf/nan || y=+-0 || y=+-inf/nan + + // evaluate (1+x)^y explicitly for integer y in [-16,16] range and |x|<2^64 + if is_integerf(y) && ay <= 0x83000000u32 && ax <= 0xbefffffeu32 { + if ax <= 0x62000000u32 { + return 1.0 + y * x; + } // does it work for |x|<2^-29 and |y|<=16? + let mut s = x as f64 + 1.; + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { s } else { 1. }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = s * s; + if iter_count % 2 != 0 { + acc *= s; + } + } + + let dz = if y.is_sign_negative() { 1. / acc } else { acc }; + return DoubleDouble::from_full_exact_add(dz, -1.).to_f64() as f32; + } + + let xd = x as f64; + let yd = y as f64; + let tx = xd.to_bits(); + let ty = yd.to_bits(); + + let l: f64 = if ax < 0x62000000u32 { + // |x| < 2^-29 + /* |log2(1+x) - 1/log(2) * (x - x^2/2)| < 2^-59.584 * |log2(1+x)| + (cf compoundf.sollya) */ + let t = xd - (xd * xd) * 0.5; + /* since x is epresentable in binary32, x*x is exact, and so is (x * x) * 0.5. + Thus the only error in the computation of t is the final rounding, which + is bounded by ulp(t): t = (x - x^2/2) * (1 + eps2) with |eps2| < 2^-52 + */ + INVLOG2 * t + /* since INVLOG2 = 1/log(2) * (1 + eps1) and + and t = (x - x^2/2) * (1 + eps2) + let u = o(INVLOG2 * t) then u = INVLOG2 * t * (1 + eps3) with |eps3|<2^-53 + thus u = 1/log(2) * (x - x^2/2) * (1 + eps1)*(1 + eps2)*(1 + eps3) + = 1/log(2) * (x - x^2/2) * (1 + eps4) with |eps4| < 2^-50.954 + Now Sollya says the relative error by approximating log2(1+x) by + 1/log(2) * (x - x^2/2) for |x| < 2^-29 is bounded by 2^-59.584 + (file compoundf.sollya), thus: + u = log2(1+x) * (1+eps4)*(1+eps5) with |eps5| < 2^-59.584 + = log2(1+x) * (1+eps6) with |eps6| < 2^-50.950 */ + } else { + compoundf_log2p1_fast(f64::from_bits(tx)) + }; + + /* l approximates log2(1+x) with relative error < 2^-47.997, + and 2^-149 <= |l| < 128 */ + + let t: u64 = (l * f64::from_bits(ty)).to_bits(); + /* since 2^-149 <= |l| < 128 and 2^-149 <= |y| < 2^128, we have + 2^-298 <= |t| < 2^135, thus no underflow/overflow in double is possible. + The relative error is bounded by (1+2^-47.997)*(1+2^-52)-1 < 2^-47.909 */ + + // detect overflow/underflow + if (t.wrapping_shl(1)) >= (0x406u64 << 53) { + // |t| >= 128 + if t >= 0x3018bu64 << 46 { + // t <= -150 + return black_box(f32::from_bits(0x00800000)) * black_box(f32::from_bits(0x00800000)); + } else if (t >> 63) == 0 { + // t >= 128: overflow + return black_box(f32::from_bits(0x7e800000)) * black_box(f32::from_bits(0x7e800000)); + } + } + + let res = exp2m1_fast(f64::from_bits(t)); + if res != -1.0 { + return res as f32; + } + compoundm1f_accurate(x, y) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::compound::compound_m1f::{compoundf_exp2m1_accurate, exp2m1_fast}; + use crate::double_double::DoubleDouble; + + #[test] + fn test_compoundf() { + assert_eq!( + f_compound_m1f(-0.000000000000001191123, -0.000000000000001191123), + 0.0000000000000000000000000000014187741 + ); + assert_eq!(f_compound_m1f(-0.000000000000001191123, 16.), 1.0); + assert_eq!(f_compound_m1f(0.91123, 16.), 31695.21); + assert_eq!(f_compound_m1f(0.91123, -16.), -0.99996847); + } + + #[test] + fn test_compoundf_expm1_fast() { + assert_eq!(exp2m1_fast(3.764), 12.585539943149435); + } + + #[test] + fn test_compoundf_expm1_accurate() { + assert_eq!( + compoundf_exp2m1_accurate(DoubleDouble::new(0., 2.74), 12., 53.), + 5.680703, + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compoundf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compoundf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/compoundf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/compoundf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1000 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, is_integerf}; +use crate::double_double::DoubleDouble; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +#[cold] +#[inline(never)] +fn as_compoundf_special(x: f32, y: f32) -> f32 { + let nx = x.to_bits(); + let ny = y.to_bits(); + let ax: u32 = nx.wrapping_shl(1); + let ay: u32 = ny.wrapping_shl(1); + + if ax == 0 || ay == 0 { + // x or y is 0 + if ax == 0 { + // compound(0,y) = 1 except for y = sNaN + return if y.is_nan() { x + y } else { 1.0 }; + } + + if ay == 0 { + // compound (x, 0) + if x.is_nan() { + return x + y; + } // x = sNaN + return if x < -1.0 { + f32::NAN // rule (g) + } else { + 1.0 + }; // rule (a) + } + } + + let mone = (-1.0f32).to_bits(); + if ay >= 0xffu32 << 24 { + // y=Inf/NaN + // the case x=0 was already checked above + if ax > 0xffu32 << 24 { + return x + y; + } // x=NaN + if ay == 0xffu32 << 24 { + // y = +/-Inf + if nx > mone { + return f32::NAN; + } // rule (g) + let sy = ny >> 31; // sign bit of y + if nx == mone { + return if sy == 0 { + 0.0 // Rule (c) + } else { + f32::INFINITY // Rule (b) + }; + } + if x < 0.0 { + return if sy == 0 { 0.0 } else { f32::INFINITY }; + } + if x > 0.0 { + return if sy != 0 { 0.0 } else { f32::INFINITY }; + } + return 1.0; + } + return x + y; // case y=NaN + } + + if nx >= mone || nx >= 0xffu32 << 23 { + // x is Inf, NaN or <= -1 + if ax == 0xffu32 << 24 { + // x is +Inf or -Inf + if (nx >> 31) != 0 { + return f32::NAN; + } // x = -Inf, rule (g) + // (1 + Inf)^y = +Inf for y > 0, +0 for y < 0 + return if (ny >> 31) != 0 { 1.0 / x } else { x }; + } + if ax > 0xffu32 << 24 { + return x + y; + } // x is NaN + if nx > mone { + return f32::NAN; // x < -1.0: rule (g) + } + // now x = -1 + return if (ny >> 31) != 0 { + // y < 0 + f32::INFINITY + } else { + // y > 0 + 0.0 + }; + } + 0.0 +} + +#[inline] +pub(crate) fn log2p1_polyeval_1(z: f64) -> f64 { + // we include P[0] = 0 so that P[i] corresponds to degree i + // this degree-8 polynomial generated by Sollya (cf p1.sollya) + // has relative error < 2^-50.98 + const P: [u64; 8] = [ + 0x0000000000000000, + 0x3ff71547652b82fe, + 0xbfe71547652b8d11, + 0x3fdec709dc3a5014, + 0xbfd715475b144983, + 0x3fd2776c3fda300e, + 0xbfcec990162358ce, + 0x3fca645337c29e27, + ]; + + let z2 = z * z; + let mut c5 = dd_fmla(f64::from_bits(P[6]), z, f64::from_bits(P[5])); + let c3 = dd_fmla(f64::from_bits(P[4]), z, f64::from_bits(P[3])); + let mut c1 = dd_fmla(f64::from_bits(P[2]), z, f64::from_bits(P[1])); + let z4 = z2 * z2; + c5 = dd_fmla(f64::from_bits(P[7]), z2, c5); + c1 = dd_fmla(c3, z2, c1); + c1 = dd_fmla(c5, z4, c1); + z * c1 +} + +// for 0<=i<46, inv[i] approximates 1/t for 1/2+(i+13)/64 <= t < 1/2+(i+14)/64 +pub(crate) static LOG2P1_COMPOUNDF_INV: [u64; 46] = [ + 0x3ff6800000000000, + 0x3ff6000000000000, + 0x3ff5800000000000, + 0x3ff5000000000000, + 0x3ff4c00000000000, + 0x3ff4400000000000, + 0x3ff4000000000000, + 0x3ff3800000000000, + 0x3ff3400000000000, + 0x3ff2c00000000000, + 0x3ff2800000000000, + 0x3ff2000000000000, + 0x3ff1c00000000000, + 0x3ff1800000000000, + 0x3ff1400000000000, + 0x3ff1000000000000, + 0x3ff0c00000000000, + 0x3ff0800000000000, + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fef400000000000, + 0x3feec00000000000, + 0x3fee400000000000, + 0x3fee000000000000, + 0x3fed800000000000, + 0x3fed000000000000, + 0x3feca00000000000, + 0x3fec400000000000, + 0x3febe00000000000, + 0x3feb800000000000, + 0x3feb200000000000, + 0x3feac00000000000, + 0x3fea800000000000, + 0x3fea200000000000, + 0x3fe9c00000000000, + 0x3fe9800000000000, + 0x3fe9200000000000, + 0x3fe8c00000000000, + 0x3fe8800000000000, + 0x3fe8400000000000, + 0x3fe8000000000000, + 0x3fe7c00000000000, + 0x3fe7600000000000, + 0x3fe7200000000000, + 0x3fe6e00000000000, + 0x3fe6a00000000000, +]; + +/* log2inv[i][0]+log2inv[i][1] is a double-double approximation of +-log2(inv[i]), with log2inv[i][0] having absolute error < 2^-54.462, +and log2inv[i][0]+log2inv[i][1] absolute error < 2^-109.101 */ +pub(crate) static LOG2P1_COMPOUNDF_LOG2_INV: [(u64, u64); 46] = [ + (0x3c68f3673ffdd785, 0xbfdf7a8568cb06cf), + (0x3c1c141e66faaaad, 0xbfdd6753e032ea0f), + (0x3c76fae441c09d76, 0xbfdb47ebf73882a1), + (0x3c72d352bea51e59, 0xbfd91bba891f1709), + (0xbc69575b04fa6fbd, 0xbfd800a563161c54), + (0x3c7817fd3b7d7e5d, 0xbfd5c01a39fbd688), + (0x3c1b6d40900b2502, 0xbfd49a784bcd1b8b), + (0x3c7f6e91ad16ecff, 0xbfd24407ab0e073a), + (0x3c6a7b47d2c352d9, 0xbfd11307dad30b76), + (0x3c5b85a54d7ee2fd, 0xbfcd49ee4c325970), + (0x3c401ee1343fe7ca, 0xbfcacf5e2db4ec94), + (0x3c6817fd3b7d7e5d, 0xbfc5c01a39fbd688), + (0xbc4f51f2c075a74c, 0xbfc32ae9e278ae1a), + (0x3c6a7610e40bd6ab, 0xbfc08c588cda79e4), + (0xbc58ecb169b9465f, 0xbfbbc84240adabba), + (0xbc5f3314e0985116, 0xbfb663f6fac91316), + (0x3c530c22d15199b8, 0xbfb0eb389fa29f9b), + (0xbc389b03784b5be1, 0xbfa6bad3758efd87), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3c3491f06c085bc2, 0x3fa184b8e4c56af8), + (0x3c0155660710eb2a, 0x3fad6ebd1f1febfe), + (0x3c2c141e66faaaad, 0x3fb4c560fe68af88), + (0x3c59ced1447e30ad, 0x3fb7d60496cfbb4c), + (0x3c592ce9636c90a0, 0x3fbe0b1ae8f2fd56), + (0xbc5696e2866c718e, 0x3fc22dadc2ab3497), + (0xbc61562d61af73f8, 0x3fc494f863b8df35), + (0xbc60798d1aa21694, 0x3fc7046031c79f85), + (0xbc6e95734abd2fcc, 0x3fc97c1cb13c7ec1), + (0x3c2bc0af7b82e7d7, 0x3fcbfc67a7fff4cc), + (0xbc6086fce864a1f6, 0x3fce857d3d361368), + (0xbc53d56efe4338fe, 0x3fd08bce0d95fa38), + (0x3c7c8d43e017579b, 0x3fd169c05363f158), + (0xbc50132ae5e417cd, 0x3fd2baa0c34be1ec), + (0xbc7c658d602e66b0, 0x3fd4106017c3eca3), + (0x3c7e393a16b94b52, 0x3fd4f6fbb2cec598), + (0x3c7ac9080333c605, 0x3fd6552b49986277), + (0x3c68f89e2eb553b2, 0x3fd7b89f02cf2aad), + (0x3c799aa6df8b7d83, 0x3fd8a8980abfbd32), + (0x3c7bca36fd02def0, 0x3fd99b072a96c6b2), + (0x3c5817fd3b7d7e5d, 0x3fda8ff971810a5e), + (0xbc501d98c3531027, 0x3fdb877c57b1b070), + (0x3c78a38b4175d665, 0x3fdcffae611ad12b), + (0x3c438c8946414c6a, 0x3fddfdd89d586e2b), + (0x3c76d261f1753e0b, 0x3fdefec61b011f85), + (0xbc87398fe685f171, 0x3fe0014332be0033), +]; + +/* for |z| <= 2^-6, returns an approximation of 2^z +with absolute error < 2^-43.540 */ +#[inline] +fn compoundf_expf_poly(z: f64) -> f64 { + /* Q is a degree-4 polynomial generated by Sollya (cf q1.sollya) + with absolute error < 2^-43.549 */ + const Q: [u64; 5] = [ + 0x3ff0000000000000, + 0x3fe62e42fef6d01a, + 0x3fcebfbdff7feeba, + 0x3fac6b167e579bee, + 0x3f83b2b3428d06de, + ]; + let z2 = z * z; + let c3 = dd_fmla(f64::from_bits(Q[4]), z, f64::from_bits(Q[3])); + let c0 = dd_fmla(f64::from_bits(Q[1]), z, f64::from_bits(Q[0])); + let c2 = dd_fmla(c3, z, f64::from_bits(Q[2])); + dd_fmla(c2, z2, c0) +} + +pub(crate) fn compoundf_log2p1_fast(x: f64) -> f64 { + /* for x > 0, 1+x is exact when 2^-29 <= x < 2^53 + for x < 0, 1+x is exact when -1 < x <= 2^-30 */ + + // double u = (x >= 0x1p53) ? x : 1.0 + x; + let u = 1.0 + x; + /* For x < 0x1p53, x + 1 is exact thus u = x+1. + For x >= 2^53, we estimate log2(x) instead of log2(1+x), + since log2(1+x) = log2(x) + log2(1+1/x), + log2(x) >= 53 and |log2(1+1/x)| < 2^-52.471, the additional relative + error is bounded by 2^-52.471/53 < 2^-58.198 */ + + let mut v = u.to_bits(); + let m: u64 = v & 0xfffffffffffffu64; + let e: i64 = (v >> 52) as i64 - 0x3ff + (m >= 0x6a09e667f3bcdu64) as i64; + // 2^e/sqrt(2) < u < 2^e*sqrt(2), with -29 <= e <= 128 + v = v.wrapping_sub((e << 52) as u64); + let t = f64::from_bits(v); + // u = 2^e*t with 1/sqrt(2) < t < sqrt(2) + // thus log2(u) = e + log2(t) + v = (f64::from_bits(v) + 2.0).to_bits(); // add 2 so that v.f is always in the binade [2, 4) + let i = (v >> 45) as i32 - 0x2002d; // 0 <= i <= 45 + let r = f64::from_bits(LOG2P1_COMPOUNDF_INV[i as usize]); + let z = dd_fmla(r, t, -1.0); // exact, -1/64 <= z <= 1/64 + // we approximates log2(t) by -log2(r) + log2(r*t) + let p = log2p1_polyeval_1(z); + // p approximates log2(r*t) with rel. error < 2^-49.642, and |p| < 2^-5.459 + e as f64 + (f64::from_bits(LOG2P1_COMPOUNDF_LOG2_INV[i as usize].1) + p) +} + +pub(crate) static COMPOUNDF_EXP2_T: [u64; 33] = [ + 0xbfe0000000000000, + 0xbfde000000000000, + 0xbfdc000000000000, + 0xbfda000000000000, + 0xbfd8000000000000, + 0xbfd6000000000000, + 0xbfd4000000000000, + 0xbfd2000000000000, + 0xbfd0000000000000, + 0xbfcc000000000000, + 0xbfc8000000000000, + 0xbfc4000000000000, + 0xbfc0000000000000, + 0xbfb8000000000000, + 0xbfb0000000000000, + 0xbfa0000000000000, + 0x0000000000000000, + 0x3fa0000000000000, + 0x3fb0000000000000, + 0x3fb8000000000000, + 0x3fc0000000000000, + 0x3fc4000000000000, + 0x3fc8000000000000, + 0x3fcc000000000000, + 0x3fd0000000000000, + 0x3fd2000000000000, + 0x3fd4000000000000, + 0x3fd6000000000000, + 0x3fd8000000000000, + 0x3fda000000000000, + 0x3fdc000000000000, + 0x3fde000000000000, + 0x3fe0000000000000, +]; + +/* exp2_U[i] is a double-double approximation h+l of 2^exp2_T[i] +so that h approximates 2^exp2_T[i] with absolute error < 2^-53.092, +and h+l approximates 2^exp2_T[i] with absolute error < 2^-107.385 */ +pub(crate) static COMPOUNDF_EXP2_U: [(u64, u64); 33] = [ + (0xbc8bdd3413b26456, 0x3fe6a09e667f3bcd), + (0xbc716e4786887a99, 0x3fe71f75e8ec5f74), + (0xbc741577ee04992f, 0x3fe7a11473eb0187), + (0xbc8d4c1dd41532d8, 0x3fe82589994cce13), + (0x3c86e9f156864b27, 0x3fe8ace5422aa0db), + (0xbc575fc781b57ebc, 0x3fe93737b0cdc5e5), + (0x3c6c7c46b071f2be, 0x3fe9c49182a3f090), + (0xbc8d2f6edb8d41e1, 0x3fea5503b23e255d), + (0x3c87a1cd345dcc81, 0x3feae89f995ad3ad), + (0xbc65584f7e54ac3b, 0x3feb7f76f2fb5e47), + (0x3c711065895048dd, 0x3fec199bdd85529c), + (0x3c6503cbd1e949db, 0x3fecb720dcef9069), + (0x3c72ed02d75b3707, 0x3fed5818dcfba487), + (0xbc81a5cd4f184b5c, 0x3fedfc97337b9b5f), + (0xbc8e9c23179c2893, 0x3feea4afa2a490da), + (0x3c89d3e12dd8a18b, 0x3fef50765b6e4540), + (0x0000000000000000, 0x3ff0000000000000), + (0x3c8d73e2a475b465, 0x3ff059b0d3158574), + (0x3c98a62e4adc610b, 0x3ff0b5586cf9890f), + (0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0x3c99b07eb6c70573, 0x3ff2387a6e756238), + (0x3c8612e8afad1255, 0x3ff29e9df51fdee1), + (0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xbc807abe1db13cad, 0x3ff5342b569d4f82), + (0x3c96324c054647ad, 0x3ff5ab07dd485429), + (0xbc9383c17e40b497, 0x3ff6247eb03a5585), + (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), +]; + +/* return the correct rounding of (1+x)^y, otherwise -1.0 +where t is an approximation of y*log2(1+x) with absolute error < 2^-40.680, +assuming 0x1.7154759a0df53p-24 <= |t| <= 150 +exact is non-zero iff (1+x)^y is exact or midpoint */ +fn exp2_fast(t: f64) -> f64 { + let k = t.cpu_round_ties_even(); // 0 <= |k| <= 150 + let mut r = t - k; // |r| <= 1/2, exact + let mut v: u64 = (3.015625 + r).to_bits(); // 2.5 <= v <= 3.5015625 + // we add 2^-6 so that i is rounded to nearest + let i: i32 = (v >> 46) as i32 - 0x10010; // 0 <= i <= 32 + r -= f64::from_bits(COMPOUNDF_EXP2_T[i as usize]); // exact + // now |r| <= 2^-6 + // 2^t = 2^k * exp2_U[i][0] * 2^r + v = (f64::from_bits(COMPOUNDF_EXP2_U[i as usize].1) * compoundf_expf_poly(r)).to_bits(); + /* the absolute error on exp2_U[i][0] is bounded by 2^-53.092, with + exp2_U[i][0] < 2^0.5, and that on q1(r) is bounded by 2^-43.540, + with |q1(r)| < 1.011, thus |v| < 1.43, and the absolute error on v is + bounded by ulp(v) + 2^0.5 * 2^-43.540 + 2^-53.092 * 1.011 < 2^-43.035. + Now t approximates u := y*log2(1+x) with |t-u| < 2^-40.680 thus + 2^u = 2^t * (1 + eps) with eps < 2^(2^-40.680)-1 < 2^-41.208. + The total absolute error is thus bounded by 2^-43.035 + 2^-41.208 + < 2^-40.849. */ + let mut err: u64 = 0x3d61d00000000000; // 2^-40.849 < 0x1.1dp-41 + v = unsafe { v.wrapping_add(k.to_int_unchecked::().wrapping_shl(52) as u64) }; // scale v by 2^k, k is already integer + + // in case of potential underflow, we defer to the accurate path + if f64::from_bits(v) < f64::from_bits(0x38100000000008e2) { + return -1.0; + } + err = unsafe { err.wrapping_add((k.to_int_unchecked::() << 52) as u64) }; // scale the error by 2^k too + let lb = (f64::from_bits(v) - f64::from_bits(err)) as f32; + let rb = (f64::from_bits(v) + f64::from_bits(err)) as f32; + if lb != rb { + return -1.0; + } // rounding test failed + + f64::from_bits(v) +} + +// 2^e/sqrt(2) < h < 2^e*sqrt(2), with -29 <= e <= 128 +// divide h, l by 2^e +pub(crate) static LOG2P1_SCALE: [u64; 158] = [ + 0x41c0000000000000, + 0x41b0000000000000, + 0x41a0000000000000, + 0x4190000000000000, + 0x4180000000000000, + 0x4170000000000000, + 0x4160000000000000, + 0x4150000000000000, + 0x4140000000000000, + 0x4130000000000000, + 0x4120000000000000, + 0x4110000000000000, + 0x4100000000000000, + 0x40f0000000000000, + 0x40e0000000000000, + 0x40d0000000000000, + 0x40c0000000000000, + 0x40b0000000000000, + 0x40a0000000000000, + 0x4090000000000000, + 0x4080000000000000, + 0x4070000000000000, + 0x4060000000000000, + 0x4050000000000000, + 0x4040000000000000, + 0x4030000000000000, + 0x4020000000000000, + 0x4010000000000000, + 0x4000000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fd0000000000000, + 0x3fc0000000000000, + 0x3fb0000000000000, + 0x3fa0000000000000, + 0x3f90000000000000, + 0x3f80000000000000, + 0x3f70000000000000, + 0x3f60000000000000, + 0x3f50000000000000, + 0x3f40000000000000, + 0x3f30000000000000, + 0x3f20000000000000, + 0x3f10000000000000, + 0x3f00000000000000, + 0x3ef0000000000000, + 0x3ee0000000000000, + 0x3ed0000000000000, + 0x3ec0000000000000, + 0x3eb0000000000000, + 0x3ea0000000000000, + 0x3e90000000000000, + 0x3e80000000000000, + 0x3e70000000000000, + 0x3e60000000000000, + 0x3e50000000000000, + 0x3e40000000000000, + 0x3e30000000000000, + 0x3e20000000000000, + 0x3e10000000000000, + 0x3e00000000000000, + 0x3df0000000000000, + 0x3de0000000000000, + 0x3dd0000000000000, + 0x3dc0000000000000, + 0x3db0000000000000, + 0x3da0000000000000, + 0x3d90000000000000, + 0x3d80000000000000, + 0x3d70000000000000, + 0x3d60000000000000, + 0x3d50000000000000, + 0x3d40000000000000, + 0x3d30000000000000, + 0x3d20000000000000, + 0x3d10000000000000, + 0x3d00000000000000, + 0x3cf0000000000000, + 0x3ce0000000000000, + 0x3cd0000000000000, + 0x3cc0000000000000, + 0x3cb0000000000000, + 0x3ca0000000000000, + 0x3c90000000000000, + 0x3c80000000000000, + 0x3c70000000000000, + 0x3c60000000000000, + 0x3c50000000000000, + 0x3c40000000000000, + 0x3c30000000000000, + 0x3c20000000000000, + 0x3c10000000000000, + 0x3c00000000000000, + 0x3bf0000000000000, + 0x3be0000000000000, + 0x3bd0000000000000, + 0x3bc0000000000000, + 0x3bb0000000000000, + 0x3ba0000000000000, + 0x3b90000000000000, + 0x3b80000000000000, + 0x3b70000000000000, + 0x3b60000000000000, + 0x3b50000000000000, + 0x3b40000000000000, + 0x3b30000000000000, + 0x3b20000000000000, + 0x3b10000000000000, + 0x3b00000000000000, + 0x3af0000000000000, + 0x3ae0000000000000, + 0x3ad0000000000000, + 0x3ac0000000000000, + 0x3ab0000000000000, + 0x3aa0000000000000, + 0x3a90000000000000, + 0x3a80000000000000, + 0x3a70000000000000, + 0x3a60000000000000, + 0x3a50000000000000, + 0x3a40000000000000, + 0x3a30000000000000, + 0x3a20000000000000, + 0x3a10000000000000, + 0x3a00000000000000, + 0x39f0000000000000, + 0x39e0000000000000, + 0x39d0000000000000, + 0x39c0000000000000, + 0x39b0000000000000, + 0x39a0000000000000, + 0x3990000000000000, + 0x3980000000000000, + 0x3970000000000000, + 0x3960000000000000, + 0x3950000000000000, + 0x3940000000000000, + 0x3930000000000000, + 0x3920000000000000, + 0x3910000000000000, + 0x3900000000000000, + 0x38f0000000000000, + 0x38e0000000000000, + 0x38d0000000000000, + 0x38c0000000000000, + 0x38b0000000000000, + 0x38a0000000000000, + 0x3890000000000000, + 0x3880000000000000, + 0x3870000000000000, + 0x3860000000000000, + 0x3850000000000000, + 0x3840000000000000, + 0x3830000000000000, + 0x3820000000000000, + 0x3810000000000000, + 0x3800000000000000, + 0x37f0000000000000, +]; + +/* put in h+l an approximation of log2(1+zh+zl) + for |zh| <= 1/64 + 2^-51.508, |zl| < 2^-58 and |zl| < ulp(zh). + We have |h|, |h+l| < 2^-5.459, |l| < 2^-56.162, + the relative error is bounded by 2^-91.196, + and |l| < 2^-50.523 |h| (see analyze_p2() in compoundf.sage). +*/ + +/* degree-13 polynomial generated by Sollya which approximates + log2(1+z) for |z| <= 1/64 with relative error < 2^-93.777 + (cf file p2.sollya) +*/ +static LOG2P1_LOG2_POLY: [u64; 18] = [ + 0x3ff71547652b82fe, + 0x3c7777d0ffda0d80, + 0xbfe71547652b82fe, + 0xbc6777d0fd20b49c, + 0x3fdec709dc3a03fd, + 0x3c7d27f05171b74a, + 0xbfd71547652b82fe, + 0xbc57814e70b828b0, + 0x3fd2776c50ef9bfe, + 0x3c7e4f63e12bff83, + 0xbfcec709dc3a03f4, + 0x3fca61762a7adecc, + 0xbfc71547652d8849, + 0x3fc484b13d7e7029, + 0xbfc2776c1b2a40fd, + 0x3fc0c9a80f9b7c1c, + 0xbfbecc6801121200, + 0x3fbc6e4b91fd10e5, +]; + +fn log2_poly2(z: DoubleDouble) -> DoubleDouble { + /* since we can't expect a relative accuracy better than 2^-93.777, + the lower part of the double-double approximation only needs to + have about 94-53 = 41 accurate bits. Since |p7*z^7/p1| < 2^-44, + we evaluate terms of degree 7 or more in double precision only. */ + let mut h = f64::from_bits(LOG2P1_LOG2_POLY[4 + 13]); // degree 13 + + for i in 7..=12 { + h = dd_fmla(z.hi, z.hi, f64::from_bits(LOG2P1_LOG2_POLY[4 + i])); + } + + let mut v = DoubleDouble::quick_mult_f64(z, h); + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[10])); + v.hi = t.hi; + v.lo += t.lo; + + v = DoubleDouble::quick_mult(v, z); + + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[8])); + v.hi = t.hi; + v.lo += t.lo + f64::from_bits(LOG2P1_LOG2_POLY[9]); + + v = DoubleDouble::quick_mult(v, z); + + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[6])); + v.hi = t.hi; + v.lo += t.lo + f64::from_bits(LOG2P1_LOG2_POLY[7]); + + v = DoubleDouble::quick_mult(v, z); + + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[4])); + v.hi = t.hi; + v.lo += t.lo + f64::from_bits(LOG2P1_LOG2_POLY[5]); + + v = DoubleDouble::quick_mult(v, z); + + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[2])); + v.hi = t.hi; + v.lo += t.lo + f64::from_bits(LOG2P1_LOG2_POLY[3]); + + v = DoubleDouble::quick_mult(v, z); + + let t = DoubleDouble::from_exact_add(v.hi, f64::from_bits(LOG2P1_LOG2_POLY[0])); + v.hi = t.hi; + v.lo += t.lo + f64::from_bits(LOG2P1_LOG2_POLY[1]); + + v = DoubleDouble::quick_mult(v, z); + + v +} + +/* assuming -1 < x < 2^128, and x is representable in binary32, +put in h+l a double-double approximation of log2(1+x), +with relative error bounded by 2^-91.123, and |l| < 2^-48.574 |h| +(see analyze_log2p1_accurate() in compoundf.sage) */ +pub(crate) fn compoundf_log2p1_accurate(x: f64) -> DoubleDouble { + let mut v_dd = if 1.0 >= x { + // then 1.0 >= |x| since x > -1 + if (x as f32).abs() >= f32::from_bits(0x25000000) { + DoubleDouble::from_exact_add(1.0, x) + } else { + DoubleDouble::new(x, 1.0) + } + } else { + // fast_two_sum() is exact when |x| < 2^54 by Lemma 1 condition (ii) of [1] + DoubleDouble::from_exact_add(x, 1.0) + }; + + // now h + l = 1 + x + eps with |eps| <= 2^-105 |h| and |l| <= ulp(h) + let mut v = v_dd.hi.to_bits(); + let m = v & 0xfffffffffffffu64; + let e: i64 = (v >> 52) as i64 - 0x3ff + (m >= 0x6a09e667f3bcdu64) as i64; + + let scale = f64::from_bits(LOG2P1_SCALE[e.wrapping_add(29) as usize]); + v_dd.hi *= scale; + v_dd.lo *= scale; + + // now |h| < sqrt(2) and |l| <= ulp(h) <= 2^-52 + + // now 1 + x ~ 2^e * (h + l) thus log2(1+x) ~ e + log2(h+l) + + v = (2.0 + v_dd.hi).to_bits(); // add 2 so that v.f is always in the binade [2, 4) + let i: i32 = (v >> 45) as i32 - 0x2002d; // h is near 1/2+(i+13)/64 + let r = f64::from_bits(LOG2P1_COMPOUNDF_INV[i as usize]); + let mut z_dd = DoubleDouble::new(r * v_dd.lo, dd_fmla(r, v_dd.hi, -1.0)); // exact, -1/64 <= zh <= 1/64 + // since |r| <= 0x1.68p+0 and |l| <= 2^-52, |zl| <= 2^-51.508 + // zh + zl = r*(h+l)-1 + // log2(h+l) = -log2(r) + log2(r*(h+l)) = -log2(r) + log2(1+zh+zl) + z_dd = DoubleDouble::from_exact_add(z_dd.hi, z_dd.lo); + // now |zh| <= 1/64 + 2^-51.508 and |zl| < 2^-58 + /* the relative error of fast_two_sum() is bounded by 2^-105, + this amplified the relative error on p2() as follows: + (1+2^-91.196)*(1+2^-105)-1 < 2^-91.195. */ + + // now |zh| <= 1/64 + 2^-51.508 and |zl| < 2^-58 + /* the relative error of fast_two_sum() is bounded by 2^-105, + this amplified the relative error on p2() as follows: + (1+2^-91.196)*(1+2^-105)-1 < 2^-91.195. */ + let log_p = log2_poly2(z_dd); + // ph + pl approximates log2(1+zh+zl) with relative error < 2^-93.471 + + /* since |log2inv[i][0]| < 1 and e is integer, the precondition of + fast_two_sum is fulfilled: either |e| >= 1, or e=0 and fast_two_sum + is exact */ + let log2_inv = LOG2P1_COMPOUNDF_LOG2_INV[i as usize]; + v_dd = DoubleDouble::from_exact_add(e as f64, f64::from_bits(log2_inv.1)); + v_dd.lo += f64::from_bits(log2_inv.0); + let mut p = DoubleDouble::from_exact_add(v_dd.hi, log_p.hi); + p.lo += v_dd.lo + log_p.lo; + p +} + +pub(crate) fn compoundf_exp2_poly2(z: DoubleDouble) -> DoubleDouble { + /* Q2 is a degree-8 polynomial generated by Sollya (cf q2.sollya) + with absolute error < 2^-85.218 */ + + static Q2: [u64; 12] = [ + 0x3ff0000000000000, + 0x3fe62e42fefa39ef, + 0x3c7abc9d45534d06, + 0x3fcebfbdff82c58f, + 0xbc65e4383cf9ddf7, + 0x3fac6b08d704a0c0, + 0xbc46cbc55586c8f1, + 0x3f83b2ab6fba4e77, + 0x3f55d87fe789aec5, + 0x3f2430912f879daa, + 0x3eeffcc774b2367a, + 0x3eb62c017b9bdfe6, + ]; + let h2 = z.hi * z.hi; + let c7 = dd_fmla(f64::from_bits(Q2[11]), z.hi, f64::from_bits(Q2[10])); + let mut c5 = dd_fmla(f64::from_bits(Q2[9]), z.hi, f64::from_bits(Q2[8])); + c5 = dd_fmla(c7, h2, c5); + // since ulp(c5*h^5) <= 2^-86, we still compute c5*z as double + let z_vqh = c5 * z.hi; + let mut q = DoubleDouble::from_exact_add(f64::from_bits(Q2[7]), z_vqh); + // multiply by z + q = DoubleDouble::quick_mult(q, z); + // add coefficient of degree 3 + let t = DoubleDouble::from_exact_add(f64::from_bits(Q2[5]), q.hi); + q.hi = t.hi; + q.lo += t.lo + f64::from_bits(Q2[6]); + // multiply by z and add coefficient of degree 2 + q = DoubleDouble::quick_mult(q, z); + let t = DoubleDouble::from_exact_add(f64::from_bits(Q2[3]), q.hi); + q.hi = t.hi; + q.lo += t.lo + f64::from_bits(Q2[4]); + // multiply by h+l and add coefficient of degree 1 + q = DoubleDouble::quick_mult(q, z); + let t = DoubleDouble::from_exact_add(f64::from_bits(Q2[1]), q.hi); + q.hi = t.hi; + q.lo += t.lo + f64::from_bits(Q2[2]); + // multiply by h+l and add coefficient of degree 0 + q = DoubleDouble::quick_mult(q, z); + let t = DoubleDouble::from_exact_add(f64::from_bits(Q2[0]), q.hi); + q.hi = t.hi; + q.lo += t.lo; + q +} + +/* return the correct rounding of (1+x)^y or -1 if the rounding test failed, +where t is an approximation of y*log2(1+x). +We assume |h+l| < 150, |l/h| < 2^-48.445 |h|, +and the relative error between h+l and y*log2(1+x) is < 2^-91.120. +x and y are the original inputs of compound. */ +fn compoundf_exp2_accurate(x_dd: DoubleDouble, x: f32, y: f32) -> f32 { + if y == 1.0 { + let res = 1.0 + x; + return res; + } + let k = x_dd.hi.cpu_round_ties_even(); // |k| <= 150 + + // check easy cases h+l is tiny thus 2^(h+l) rounds to 1, 1- or 1+ + if k == 0. && x_dd.hi.abs() <= f64::from_bits(0x3e6715476af0d4c8) { + /* the relative error between h and y*log2(1+x) is bounded by + (1 + 2^-48.445) * (1 + 2^-91.120) - 1 < 2^-48.444. + 2^h rounds to 1 to nearest for |h| <= H0 := 0x1.715476af0d4d9p-25. + The above threshold is such that h*(1+2^-48.444) < H0. */ + return (1.0 + x_dd.hi * 0.5) as f32; + } + + let r = x_dd.hi - k; // |r| <= 1/2, exact + // since r is an integer multiple of ulp(h), fast_two_sum() below is exact + let mut v_dd = DoubleDouble::from_exact_add(r, x_dd.lo); + let mut v = (3.015625 + v_dd.hi).to_bits(); // 2.5 <= v <= 3.5015625 + // we add 2^-6 so that i is rounded to nearest + let i: i32 = ((v >> 46) as i32).wrapping_sub(0x10010); // 0 <= i <= 32 + // h is near (i-16)/2^5 + v_dd.hi -= f64::from_bits(COMPOUNDF_EXP2_T[i as usize]); // exact + + // now |h| <= 2^-6 + // 2^(h+l) = 2^k * exp2_U[i] * 2^(h+l) + v_dd = DoubleDouble::from_exact_add(v_dd.hi, v_dd.lo); + let q = compoundf_exp2_poly2(v_dd); + + /* we have 0.989 < qh < 1.011, |ql| < 2^-51.959, and + |qh + ql - 2^(h+l)| < 2^-85.210 */ + let exp2u = DoubleDouble::from_bit_pair(COMPOUNDF_EXP2_U[i as usize]); + let mut q = DoubleDouble::quick_mult(exp2u, q); + q = DoubleDouble::from_exact_add(q.hi, q.lo); + /* Total error: + * at input we have a relative error between h+l and y*log2(1+x) bounded + by 2^-91.120: h + l = y*log2(1+x) * (1 + eps1) with |eps1| < 2^-91.120. + Since |h+l| <= 150, this yields an absolute error bounded + by 150*2^-91.120 < 2^-83.891: + h + l = y*log2(1+x) + eps2 with |eps2| <= 150*2^-91.120 < 2^-83.891. + * the absolute error in q2() is bounded by 2^-85.210 + and is multiplied by exp2_U[i] < 1.415 + * the absolute d_mul() error is bounded by 2^-102.199 + * the fast_two_sum() error is bounded by 2^-105 + All this yields an absolute error on qh+ql bounded by: + 2^-83.891 + 2^-85.210*1.415 + 2^-102.199 + 2^-105 < 2^-83.242. + + We distinguish the "small" case when at input |h+l| <= 2^-9. + In this case k=0, i=16, thus exp2_T[i]=0, exp2_U[i]=1, + and absolute error in q2() is bounded by 2^-102.646, + and remains unchanged since the d_mul() call does not change qh, ql. + */ + + /* Rounding test: since |ql| < ulp(qh), and the error is less than ulp(qh), + the rounding test can fail only when the last 53-25 = 28 bits of qh + represent a signed number in [-1,1] (when it is -2 or 2, adding ql and + the error cannot cross a rounding boundary). */ + let mut w = q.hi.to_bits(); + if ((w.wrapping_add(1)) & 0xfffffffu64) <= 2 { + static ERR: [u64; 2] = [0x3abb100000000000, 0x3a2d800000000000]; + let small: bool = k == 0. && i == 16 && x_dd.hi <= f64::from_bits(0x3f60000000000000); + let err = f64::from_bits(ERR[small as usize]); + + w = (q.hi + (q.lo + err)).to_bits(); + w = unsafe { w.wrapping_add(k.to_int_unchecked::().wrapping_shl(52) as u64) }; + } + + /* multiply qh+ql by 2^k: since 0.989 < qh_in < 1.011 and + 0.707 < exp2_U[i] < 1.415, we have 0.69 < qh+ql < 1.44 */ + v = (q.hi + q.lo).to_bits(); + /* For RNDN, if qh fits exactly in 25 bits, and ql is tiny, so that + qh + ql rounds to qh, then we might have a double-rounding issue. */ + if (w.wrapping_shl(36)) == 0 && f64::from_bits(v) == q.hi && q.lo != 0. { + v = v.wrapping_add((if q.lo > 0. { 1i64 } else { -1i64 }) as u64); // simulate round to odd + } + v = unsafe { v.wrapping_add(k.to_int_unchecked::().wrapping_shl(52) as u64) }; + // there is no underflow/overflow in the scaling by 2^k since |k| <= 150 + f64::from_bits(v) as f32 +} + +// at input, exact is non-zero iff (1+x)^y is exact +// x,y=0x1.0f6f1ap+1,0x1.c643bp+5: 49 identical bits after round bit +// x,y=0x1.ef272cp+15,-0x1.746ab2p+1: 55 identical bits after round bit +// x,y=0x1.07ffcp+0,-0x1.921a8ap+4: 47 identical bits after round bit +#[cold] +#[inline(never)] +fn compoundf_accurate(x: f32, y: f32) -> f32 { + let mut v = compoundf_log2p1_accurate(x as f64); + /* h + l is a double-double approximation of log(1+x), + with relative error bounded by 2^-91.123, + and |l| < 2^-48.574 |h| */ + v = DoubleDouble::quick_mult_f64(v, y as f64); + /* h + l is a double-double approximation of y*log(1+x). + Since 2^-149 <= |h_in+l_in| < 128 and 2^-149 <= |y| < 2^128, we have + 2^-298 <= |h+l| < 2^135, thus no underflow/overflow in double is possible. + The s_mul() error is bounded by ulp(l). Since |l_in| < 2^-48.574 |h_in|, + and the intermediate variable lo in s_mul() satisfies |lo| < ulp(h), + we have |l| < ulp(h) + |y l_in| <= ulp(h) + 2^-48.574 |y h_in| + < (2^-52 + 2^-48.574) |h| < 2^-48.445 |h|. The s_mul() error is thus + bounded by 2^-48.445*2^-52 = 2^-100.445 |h|. This yields a total relative + error bounded by (1+2^-91.123)*(1+2^-100.445)-1 < 2^-91.120. */ + compoundf_exp2_accurate(v, x, y) +} + +/// Computes compound function (1.0 + x)^y +/// +/// Max ULP 0.5 +#[inline] +pub fn f_compoundf(x: f32, y: f32) -> f32 { + /* Rules from IEEE 754-2019 for compound (x, n) with n integer: + (a) compound (x, 0) is 1 for x >= -1 or quiet NaN + (b) compound (-1, n) is +Inf and signals the divideByZero exception for n < 0 + (c) compound (-1, n) is +0 for n > 0 + (d) compound (+/-0, n) is 1 + (e) compound (+Inf, n) is +Inf for n > 0 + (f) compound (+Inf, n) is +0 for n < 0 + (g) compound (x, n) is qNaN and signals the invalid exception for x < -1 + (h) compound (qNaN, n) is qNaN for n <> 0. + */ + let mone = (-1.0f32).to_bits(); + let nx = x.to_bits(); + let ny = y.to_bits(); + if nx >= mone { + return as_compoundf_special(x, y); + } // x <= -1 + // now x > -1 + + let ax: u32 = nx.wrapping_shl(1); + let ay: u32 = ny.wrapping_shl(1); + if ax == 0 || ax >= 0xffu32 << 24 || ay == 0 || ay >= 0xffu32 << 24 { + return as_compoundf_special(x, y); + } // x=+-0 || x=+-inf/nan || y=+-0 || y=+-inf/nan + + // evaluate (1+x)^y explicitly for integer y in [-16,16] range and |x|<2^64 + if is_integerf(y) && ay <= 0x83000000u32 && ax <= 0xbefffffeu32 { + if ax <= 0x62000000u32 { + return 1.0 + y * x; + } // does it work for |x|<2^-29 and |y|<=16? + let mut s = x as f64 + 1.; + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { s } else { 1. }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = s * s; + if iter_count % 2 != 0 { + acc *= s; + } + } + + let dz = if y.is_sign_negative() { 1. / acc } else { acc }; + return dz as f32; + } + + let xd = x as f64; + let yd = y as f64; + let tx = xd.to_bits(); + let ty = yd.to_bits(); + + let l: f64 = compoundf_log2p1_fast(f64::from_bits(tx)); + + /* l approximates log2(1+x) with relative error < 2^-47.997, + and 2^-149 <= |l| < 128 */ + + let t: u64 = (l * f64::from_bits(ty)).to_bits(); + /* since 2^-149 <= |l| < 128 and 2^-149 <= |y| < 2^128, we have + 2^-298 <= |t| < 2^135, thus no underflow/overflow in double is possible. + The relative error is bounded by (1+2^-47.997)*(1+2^-52)-1 < 2^-47.909 */ + + // detect overflow/underflow + if (t.wrapping_shl(1)) >= (0x406u64 << 53) { + // |t| >= 128 + if t >= 0x3018bu64 << 46 { + // t <= -150 + return black_box(f32::from_bits(0x00800000)) * black_box(f32::from_bits(0x00800000)); + } else if (t >> 63) == 0 { + // t >= 128: overflow + return black_box(f32::from_bits(0x7e800000)) * black_box(f32::from_bits(0x7e800000)); + } + } + + /* since |t| < 150, the absolute error on t is bounded by + 150*2^-47.909 < 2^-40.680 */ + + // 2^t rounds to 1 to nearest when |t| <= 0x1.715476ba97f14p-25 + if (t.wrapping_shl(1)) <= 0x3e6715476ba97f14u64 { + return if (t >> 63) != 0 { + black_box(1.0) - black_box(f32::from_bits(0x33000000)) + } else { + black_box(1.0) + black_box(f32::from_bits(0x33000000)) + }; + } + + let res = exp2_fast(f64::from_bits(t)); + if res != -1.0 { + return res as f32; + } + compoundf_accurate(x, y) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_compoundf() { + assert_eq!( + f_compoundf( + 0.000000000000000000000000000000000000011754944, + -170502050000000000000000000000000000000. + ), + 1. + ); + assert_eq!(f_compoundf(1.235, 1.432), 3.1634824); + assert_eq!(f_compoundf(2., 3.0), 27.); + assert!(f_compoundf(-2., 5.0).is_nan()); + assert_eq!(f_compoundf(1., f32::INFINITY), f32::INFINITY); + assert_eq!(f_compoundf(1., f32::NEG_INFINITY), 0.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod compound_d; +mod compound_m1; +mod compound_m1f; +mod compoundf; +mod powm1; +mod powm1f; + +pub use compound_d::f_compound; +pub use compound_m1::f_compound_m1; +pub use compound_m1f::f_compound_m1f; +pub use compoundf::f_compoundf; +pub use powm1::f_powm1; +pub use powm1f::f_powm1f; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/powm1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/powm1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{is_integer, is_odd_integer}; +use crate::double_double::DoubleDouble; +use crate::exponents::{EXPM1_T0, EXPM1_T1, ldexp}; +use crate::pow_exec::pow_log_1; +use crate::rounding::CpuRoundTiesEven; + +/// Computes x^y - 1 +pub fn f_powm1(x: f64, y: f64) -> f64 { + let ax: u64 = x.to_bits().wrapping_shl(1); + let ay: u64 = y.to_bits().wrapping_shl(1); + + // filter out exceptional cases + if ax == 0 || ax >= 0x7ffu64 << 53 || ay == 0 || ay >= 0x7ff64 << 53 { + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + + // Handle infinities + if x.is_infinite() { + return if x.is_sign_positive() { + if y.is_infinite() { + return f64::INFINITY; + } else if y > 0.0 { + f64::INFINITY // inf^positive -> inf + } else if y < 0.0 { + -1.0 // inf^negative -> 0, so powm1 = -1 + } else { + f64::NAN // inf^0 -> NaN (0^0 conventionally 1, inf^0 = NaN) + } + } else { + // x = -inf + if y.is_infinite() { + return -1.0; + } + if is_integer(y) { + // Negative base: (-inf)^even = +inf, (-inf)^odd = -inf + let pow = if y as i32 % 2 == 0 { + f64::INFINITY + } else { + f64::NEG_INFINITY + }; + pow - 1.0 + } else { + f64::NAN // Negative base with non-integer exponent + } + }; + } + + // Handle y infinite + if y.is_infinite() { + return if x.abs() > 1.0 { + if y.is_sign_positive() { + f64::INFINITY + } else { + -1.0 + } + } else if x.abs() < 1.0 { + if y.is_sign_positive() { + -1.0 + } else { + f64::INFINITY + } + } else { + // |x| == 1 + f64::NAN // 1^inf or -1^inf is undefined + }; + } + + // Handle zero base + if x == 0.0 { + return if y > 0.0 { + -1.0 // 0^positive -> 0, powm1 = -1 + } else if y < 0.0 { + f64::INFINITY // 0^negative -> inf + } else { + 0.0 // 0^0 -> conventionally 1, powm1 = 0 + }; + } + } + + let y_integer = is_integer(y); + + let mut negative_parity: bool = false; + + let mut x = x; + + // Handle negative base with non-integer exponent + if x < 0.0 { + if !y_integer { + return f64::NAN; // x < 0 and non-integer y + } + x = x.abs(); + if is_odd_integer(y) { + negative_parity = true; + } + } + + let (mut l, _) = pow_log_1(x); + l = DoubleDouble::from_exact_add(l.hi, l.lo); + + let r = DoubleDouble::quick_mult_f64(l, y); + if r.hi < -37.42994775023705 { + // underflow + return -1.; + } + let res = powm1_expm1_1(r); + // For x < 0 and integer y = n: + // if n is even: x^n = |x|^n → powm1 = |x|^n - 1 (same sign as res). + // if n is odd: x^n = -|x|^n → powm1 = -|x|^n - 1 = - (|x|^n + 1). + if negative_parity { + DoubleDouble::full_add_f64(-res, -2.).to_f64() + } else { + res.to_f64() + } +} + +#[inline] +pub(crate) fn powm1_expm1_1(r: DoubleDouble) -> DoubleDouble { + let ax = r.hi.to_bits() & 0x7fffffffffffffffu64; + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + + if ax <= 0x3f80000000000000 { + // |x| < 2^-7 + if ax < 0x3970000000000000 { + // |x| < 2^-104 + return r; + } + let d = crate::pow_exec::expm1_poly_dd_tiny(r); + return d; + } + + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r.hi * INVLOG2).cpu_round_ties_even(); + + let z = DoubleDouble::mul_f64_add(DoubleDouble::new(LOG2L, LOG2H), -k, r); + + let bk = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXPM1_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXPM1_T1[i1 as usize]); + let tbh = DoubleDouble::quick_mult(t1, t0); + let mut de = tbh; + // exp(k)=2^k*exp(r) + (2^k - 1) + let q = crate::pow_exec::expm1_poly_fast(z); + de = DoubleDouble::quick_mult(de, q); + de = DoubleDouble::add(tbh, de); + + let ie = mk - 0x3ff; + + let off: f64 = f64::from_bits((2048i64 + 1023i64).wrapping_sub(ie).wrapping_shl(52) as u64); + + let e: f64; + if ie < 53 { + let fhz = DoubleDouble::from_exact_add(off, de.hi); + de.hi = fhz.hi; + e = fhz.lo; + } else if ie < 104 { + let fhz = DoubleDouble::from_exact_add(de.hi, off); + de.hi = fhz.hi; + e = fhz.lo; + } else { + e = 0.; + } + de.lo += e; + de.hi = ldexp(de.to_f64(), ie as i32); + de.lo = 0.; + de +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_powm1() { + assert_eq!(f_powm1(f64::INFINITY, f64::INFINITY), f64::INFINITY); + assert_eq!(f_powm1(50850368932909610000000000., 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023201985303960773), 1.3733470789307166e-303); + assert_eq!(f_powm1(-3.375, -9671689000000000000000000.), -1.); + assert_eq!(f_powm1(1.83329e-40, 2.4645883e-32), -2.255031542428047e-30); + assert_eq!(f_powm1(3., 2.), 8.); + assert_eq!(f_powm1(3., 3.), 26.); + assert_eq!(f_powm1(5., 2.), 24.); + assert_eq!(f_powm1(5., -2.), 1. / 25. - 1.); + assert_eq!(f_powm1(-5., 2.), 24.); + assert_eq!(f_powm1(-5., 3.), -126.); + assert_eq!( + f_powm1(196560., 0.000000000000000000000000000000000000001193773), + 1.4550568430468268e-38 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/powm1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/compound/powm1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/compound/powm1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,260 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::compound::compound_m1f::compoundf_expf_poly; +use crate::compound::compoundf::{ + COMPOUNDF_EXP2_T, COMPOUNDF_EXP2_U, LOG2P1_COMPOUNDF_INV, LOG2P1_COMPOUNDF_LOG2_INV, +}; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +#[inline] +fn powm1f_log2_fast(x: f64) -> f64 { + /* for x > 0, 1+x is exact when 2^-29 <= x < 2^53 + for x < 0, 1+x is exact when -1 < x <= 2^-30 */ + + // double u = (x >= 0x1p53) ? x : 1.0 + x; + /* For x < 0x1p53, x + 1 is exact thus u = x+1. + For x >= 2^53, we estimate log2(x) instead of log2(1+x), + since log2(1+x) = log2(x) + log2(1+1/x), + log2(x) >= 53 and |log2(1+1/x)| < 2^-52.471, the additional relative + error is bounded by 2^-52.471/53 < 2^-58.198 */ + + let mut v = x.to_bits(); + let m: u64 = v & 0xfffffffffffffu64; + let e: i64 = (v >> 52) as i64 - 0x3ff + (m >= 0x6a09e667f3bcdu64) as i64; + // 2^e/sqrt(2) < u < 2^e*sqrt(2), with -29 <= e <= 128 + v = v.wrapping_sub((e << 52) as u64); + let t = f64::from_bits(v); + // u = 2^e*t with 1/sqrt(2) < t < sqrt(2) + // thus log2(u) = e + log2(t) + v = (f64::from_bits(v) + 2.0).to_bits(); // add 2 so that v.f is always in the binade [2, 4) + let i = (v >> 45) as i32 - 0x2002d; // 0 <= i <= 45 + let r = f64::from_bits(LOG2P1_COMPOUNDF_INV[i as usize]); + let z = dd_fmla(r, t, -1.0); // exact, -1/64 <= z <= 1/64 + // we approximates log2(t) by -log2(r) + log2(r*t) + let p = crate::compound::compoundf::log2p1_polyeval_1(z); + // p approximates log2(r*t) with rel. error < 2^-49.642, and |p| < 2^-5.459 + e as f64 + (f64::from_bits(LOG2P1_COMPOUNDF_LOG2_INV[i as usize].1) + p) +} + +/// Computes x^y - 1 +pub fn f_powm1f(x: f32, y: f32) -> f32 { + let ax: u32 = x.to_bits().wrapping_shl(1); + let ay: u32 = y.to_bits().wrapping_shl(1); + + // filter out exceptional cases + if ax == 0 || ax >= 0xffu32 << 24 || ay == 0 || ay >= 0xffu32 << 24 { + if x.is_nan() || y.is_nan() { + return f32::NAN; + } + + // Handle infinities + if x.is_infinite() { + return if x.is_sign_positive() { + if y.is_infinite() { + return f32::INFINITY; + } else if y > 0.0 { + f32::INFINITY // inf^positive -> inf + } else if y < 0.0 { + -1.0 // inf^negative -> 0, so powm1 = -1 + } else { + f32::NAN // inf^0 -> NaN (0^0 conventionally 1, inf^0 = NaN) + } + } else { + // x = -inf + if y.is_infinite() { + return -1.0; + } + if is_integerf(y) { + // Negative base: (-inf)^even = +inf, (-inf)^odd = -inf + let pow = if y as i32 % 2 == 0 { + f32::INFINITY + } else { + f32::NEG_INFINITY + }; + pow - 1.0 + } else { + f32::NAN // Negative base with non-integer exponent + } + }; + } + + // Handle y infinite + if y.is_infinite() { + return if x.abs() > 1.0 { + if y.is_sign_positive() { + f32::INFINITY + } else { + -1.0 + } + } else if x.abs() < 1.0 { + if y.is_sign_positive() { + -1.0 + } else { + f32::INFINITY + } + } else { + // |x| == 1 + f32::NAN // 1^inf or -1^inf is undefined + }; + } + + // Handle zero base + if x == 0.0 { + return if y > 0.0 { + -1.0 // 0^positive -> 0, powm1 = -1 + } else if y < 0.0 { + f32::INFINITY // 0^negative -> inf + } else { + 0.0 // 0^0 -> conventionally 1, powm1 = 0 + }; + } + } + + let y_integer = is_integerf(y); + + let mut negative_parity: bool = false; + + let mut x = x; + + // Handle negative base with non-integer exponent + if x < 0.0 { + if !y_integer { + return f32::NAN; // x < 0 and non-integer y + } + x = x.abs(); + if is_odd_integerf(y) { + negative_parity = true; + } + } + + let xd = x as f64; + let yd = y as f64; + let tx = xd.to_bits(); + let ty = yd.to_bits(); + + let l: f64 = powm1f_log2_fast(f64::from_bits(tx)); + + /* l approximates log2(1+x) with relative error < 2^-47.997, + and 2^-149 <= |l| < 128 */ + + let dt = l * f64::from_bits(ty); + let t: u64 = dt.to_bits(); + + // detect overflow/underflow + if (t.wrapping_shl(1)) >= (0x406u64 << 53) { + // |t| >= 128 + if t >= 0x3018bu64 << 46 { + // t <= -150 + return -1.; + } else if (t >> 63) == 0 { + // t >= 128: overflow + return black_box(f32::from_bits(0x7e800000)) * black_box(f32::from_bits(0x7e800000)); + } + } + + let res = powm1_exp2m1_fast(f64::from_bits(t)); + // For x < 0 and integer y = n: + // if n is even: x^n = |x|^n → powm1 = |x|^n - 1 (same sign as res). + // if n is odd: x^n = -|x|^n → powm1 = -|x|^n - 1 = - (|x|^n + 1). + if negative_parity { + (-res - 2.) as f32 + } else { + res as f32 + } +} + +#[inline] +pub(crate) fn powm1_exp2m1_fast(t: f64) -> f64 { + let k = t.cpu_round_ties_even(); // 0 <= |k| <= 150 + let mut r = t - k; // |r| <= 1/2, exact + let mut v: f64 = 3.015625 + r; // 2.5 <= v <= 3.5015625 + // we add 2^-6 so that i is rounded to nearest + let i: i32 = (v.to_bits() >> 46) as i32 - 0x10010; // 0 <= i <= 32 + r -= f64::from_bits(COMPOUNDF_EXP2_T[i as usize]); // exact + // now |r| <= 2^-6 + // 2^t = 2^k * exp2_U[i][0] * 2^r + let mut s = f64::from_bits(COMPOUNDF_EXP2_U[i as usize].1); + let su = unsafe { + k.to_int_unchecked::().wrapping_shl(52) // k is already integer + }; + s = f64::from_bits(s.to_bits().wrapping_add(su as u64)); + let q_poly = compoundf_expf_poly(r); + v = q_poly; + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v = f_fmla(v, s, s - 1f64); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::DoubleDouble; + let p0 = DoubleDouble::from_full_exact_add(s, -1.); + let z = DoubleDouble::from_exact_mult(v, s); + v = DoubleDouble::add(z, p0).to_f64(); + } + + v +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_powm1f() { + assert_eq!(f_powm1f(1.83329e-40, 2.4645883e-32), -2.2550315e-30); + assert_eq!(f_powm1f(f32::INFINITY, f32::INFINITY), f32::INFINITY); + assert_eq!(f_powm1f(-3.375, -9671689000000000000000000.), -1.); + assert_eq!(f_powm1f(3., 2.), 8.); + assert_eq!(f_powm1f(3., 3.), 26.); + assert_eq!(f_powm1f(5., 2.), 24.); + assert_eq!(f_powm1f(5., -2.), 1. / 25. - 1.); + assert_eq!(f_powm1f(-5., 2.), 24.); + assert_eq!(f_powm1f(-5., 3.), -126.); + assert_eq!( + f_powm1f(196560., 0.000000000000000000000000000000000000001193773), + 1.455057e-38 + ); + assert!(f_powm1f(f32::NAN, f32::INFINITY).is_nan()); + assert!(f_powm1f(f32::INFINITY, f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cosm1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cosm1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cosm1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cosm1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::polyeval::f_polyeval4; +use crate::sin::{range_reduction_small, sincos_eval}; +use crate::sin_helper::sincos_eval_dd; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_reduce::LargeArgumentReduction; + +#[cold] +#[inline(never)] +fn cosm1_accurate(y: DoubleDouble, sin_k: DoubleDouble, cos_k: DoubleDouble) -> f64 { + let r_sincos = sincos_eval_dd(y); + + // k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + let mut rr = DoubleDouble::full_dd_add(sin_k_cos_y, cos_k_sin_y); + + // Computing cos(x) - 1 as follows: + // cos(x) - 1 = -2*sin^2(x/2) + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = DoubleDouble::quick_mult(rr, rr); + rr = DoubleDouble::quick_mult_f64(rr, -2.); + + rr.to_f64() +} + +#[cold] +fn cosm1_tiny_hard(x: f64) -> f64 { + // Generated by Sollya: + // d = [2^-27, 2^-7]; + // f_cosm1 = cos(x) - 1; + // Q = fpminimax(f_cosm1, [|2,4,6,8|], [|0, 107...|], d); + // See ./notes/cosm1_hard.sollya + const C: [(u64, u64); 3] = [ + (0x3c453997dc8ae20d, 0x3fa5555555555555), + (0x3bf6100c76a1827a, 0xbf56c16c16c15749), + (0x3b918f45acdd1fb2, 0x3efa019ddf5a583a), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[2]), + DoubleDouble::from_bit_pair(C[1]), + ); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p = DoubleDouble::mul_add_f64(x2, p, f64::from_bits(0xbfe0000000000000)); + p = DoubleDouble::quick_mult(p, x2); + p.to_f64() +} + +/// Computes cos(x) - 1 +pub fn f_cosm1(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS + 16 { + // |x| < 2^-7 + if x_e < E_BIAS - 7 { + // |x| < 2^-26 + if x_e < E_BIAS - 27 { + // Signed zeros. + if x == 0.0 { + return 0.0; + } + // Taylor expansion for small cos(x) - 1 ~ -x^2/2 + x^4/24 + O(x^6) + let x_sqr = x * x; + const A0: f64 = -1. / 2.; + const A1: f64 = 1. / 24.; + let r0 = f_fmla(x_sqr, A1, A0); + return r0 * x_sqr; + } + + // Generated by Sollya: + // d = [2^-27, 2^-7]; + // f_cosm1 = (cos(x) - 1); + // Q = fpminimax(f_cosm1, [|2,4,6,8|], [|0, D...|], d); + // See ./notes/cosm1.sollya + + let x2 = DoubleDouble::from_exact_mult(x, x); + let p = f_polyeval4( + x2.hi, + f64::from_bits(0xbfe0000000000000), + f64::from_bits(0x3fa5555555555555), + f64::from_bits(0xbf56c16c16b9c2b7), + f64::from_bits(0x3efa014d03f38855), + ); + + let r = DoubleDouble::quick_mult_f64(x2, p); + + let eps = x * f_fmla( + x2.hi, + f64::from_bits(0x3d00000000000000), // 2^-47 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + + let ub = r.hi + (r.lo + eps); + let lb = r.hi + (r.lo - eps); + if ub == lb { + return r.to_f64(); + } + return cosm1_tiny_hard(x); + } else { + // // Small range reduction. + (y, k) = range_reduction_small(x * 0.5); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // cos(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + // k = argument_reduction.high_part(x); + (k, y) = argument_reduction.reduce(x * 0.5); + } + + // Computing cos(x) - 1 as follows: + // cos(x) - 1 = -2*sin^2(x/2) + + let r_sincos = sincos_eval(y); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = DoubleDouble::quick_mult(rr, rr); + rr = DoubleDouble::quick_mult_f64(rr, -2.); + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + + cosm1_accurate(y, sin_k, cos_k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_cosm1f_test() { + assert_eq!(f_cosm1(0.0017700195313803402), -0.000001566484161754997); + assert_eq!( + f_cosm1(0.0000000011641532182693484), + -0.0000000000000000006776263578034406 + ); + assert_eq!(f_cosm1(0.006164513528517324), -0.000019000553351160402); + assert_eq!(f_cosm1(6.2831853071795862), -2.999519565323715e-32); + assert_eq!(f_cosm1(0.00015928394), -1.2685686744140693e-8); + assert_eq!(f_cosm1(0.0), 0.0); + assert_eq!(f_cosm1(0.0), 0.0); + assert_eq!(f_cosm1(std::f64::consts::PI), -2.); + assert_eq!(f_cosm1(0.5), -0.12241743810962728); + assert_eq!(f_cosm1(0.7), -0.23515781271551153); + assert_eq!(f_cosm1(1.7), -1.1288444942955247); + assert!(f_cosm1(f64::INFINITY).is_nan()); + assert!(f_cosm1(f64::NEG_INFINITY).is_nan()); + assert!(f_cosm1(f64::NAN).is_nan()); + assert_eq!(f_cosm1(0.0002480338), -3.0760382813519806e-8); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/csc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/csc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/csc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/csc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::sin::{get_sin_k_rational, range_reduction_small, sincos_eval}; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_dyadic::{range_reduction_small_f128, sincos_eval_dyadic}; +use crate::sincos_reduce::LargeArgumentReduction; + +#[cold] +fn csc_accurate(x: f64, argument_reduction: &mut LargeArgumentReduction, x_e: u64, k: u64) -> f64 { + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + let u_f128 = if x_e < EXP_BIAS + 16 { + range_reduction_small_f128(x) + } else { + argument_reduction.accurate() + }; + + let sin_cos = sincos_eval_dyadic(&u_f128); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sin_k_f128 = get_sin_k_rational(k); + let cos_k_f128 = get_sin_k_rational(k.wrapping_add(64)); + + // sin(x) = sin(k * pi/128 + u) + // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) + let r = (sin_k_f128 * sin_cos.v_cos) + (cos_k_f128 * sin_cos.v_sin); + r.reciprocal().fast_as_f64() +} + +/// Cosecant for double precision +/// +/// ULP 0.5 +pub fn f_csc(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS + 16 { + // |x| < 2^-26 + if x_e < E_BIAS - 26 { + // Signed zeros. + if x == 0.0 { + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_e < E_BIAS - 52 { + return 1. / x; + } + + // For |x| < 2^-26, |sin(x) - x| < ulp(x)/2. + let rcp = DoubleDouble::from_quick_recip(x); + return DoubleDouble::f64_mul_f64_add(x, f64::from_bits(0x3fc5555555555555), rcp) + .to_f64(); + } + + // // Small range reduction. + (y, k) = range_reduction_small(x); + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sin(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let r_sincos = sincos_eval(y); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = rr.recip(); + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + + csc_accurate(x, &mut argument_reduction, x_e, k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_csc() { + assert_eq!(f_csc(0.000000014901161055069778), 67108864.62500001); + assert_eq!(f_csc( 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000541722315998), f64::INFINITY); + assert_eq!(f_csc(0.0), f64::INFINITY); + assert_eq!(f_csc(-0.0), f64::NEG_INFINITY); + assert!(f_csc(f64::NAN).is_nan()); + assert_eq!(f_csc(1.0), 1.1883951057781212); + assert_eq!(f_csc(-0.5), -2.085829642933488); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrt.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,231 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::cube_roots::cbrtf::halley_refine_d; +use crate::double_double::DoubleDouble; +use crate::exponents::fast_ldexp; + +pub(crate) trait CbrtBackend { + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn polyeval4(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64) -> f64; + fn halley(&self, x: f64, a: f64) -> f64; + fn exact_mul(&self, x: f64, y: f64) -> DoubleDouble; + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble; +} + +pub(crate) struct GenericCbrtBackend {} + +impl CbrtBackend for GenericCbrtBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } + #[inline(always)] + fn polyeval4(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64) -> f64 { + use crate::polyeval::f_polyeval4; + f_polyeval4(x, a0, a1, a2, a3) + } + #[inline(always)] + fn halley(&self, x: f64, a: f64) -> f64 { + halley_refine_d(x, a) + } + #[inline(always)] + fn exact_mul(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult(x, y) + } + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64(x, y) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub(crate) struct FmaCbrtBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl CbrtBackend for FmaCbrtBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + #[inline(always)] + fn polyeval4(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64) -> f64 { + use crate::polyeval::d_polyeval4; + d_polyeval4(x, a0, a1, a2, a3) + } + #[inline(always)] + fn halley(&self, x: f64, a: f64) -> f64 { + use crate::cube_roots::cbrtf::halley_refine_d_fma; + halley_refine_d_fma(x, a) + } + #[inline(always)] + fn exact_mul(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult_fma(x, y) + } + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64_fma(x, y) + } +} + +#[inline(always)] +fn cbrt_gen_impl(x: f64, backend: B) -> f64 { + // 1; 2^{1/3}; 2^{2/3} + static ESCALE: [f64; 3] = [ + 1.0, + f64::from_bits(0x3ff428a2f98d728b), + f64::from_bits(0x3ff965fea53d6e3d), + ]; + + let bits = x.to_bits(); + let mut exp = ((bits >> 52) & 0x7ff) as i32; + let mut mant = bits & ((1u64 << 52) - 1); + + if exp == 0x7ff || x == 0.0 { + return x + x; + } + + // Normalize subnormal + if exp == 0 && x != 0.0 { + let norm = x * f64::from_bits(0x4350000000000000); // * 2^54 + let norm_bits = norm.to_bits(); + mant = norm_bits & ((1u64 << 52) - 1); + exp = ((norm_bits >> 52) & 0x7ff) as i32 - 54; + } + + exp -= 1023; + + mant |= 0x3ff << 52; + let m = f64::from_bits(mant); + + // Polynomial for x^(1/3) on [1.0; 2.0] + // Generated by Sollya: + // d = [1.0, 2.0]; + // f_cbrt = x^(1/3); + // Q = fpminimax(f_cbrt, 4, [|D...|], d, relative, floating); + // See ./notes/cbrt.sollya + + let p = backend.polyeval4( + m, + f64::from_bits(0x3fe1b0babceeaafa), + f64::from_bits(0x3fe2c9a3e8e06a3c), + f64::from_bits(0xbfc4dc30afb71885), + f64::from_bits(0x3f97a8d3e05458e4), + ); + + // split exponent e = 3*q + r with r in {0,1,2} + // use div_euclid/rem_euclid to get r >= 0 + let q = exp.div_euclid(3); + let rem_scale = exp.rem_euclid(3); + + let z = p * ESCALE[rem_scale as usize]; + + let mm = fast_ldexp(m, rem_scale); // bring mantissa into [1;8] + + let r = 1.0 / mm; + + // One Halley's method step + // then refine in partial double-double precision with Newton-Raphson iteration + let y0 = backend.halley(z, mm); + let d2y = backend.exact_mul(y0, y0); + let d3y = backend.quick_mult_f64(d2y, y0); + // Newton-Raphson step + // h = (x^3 - a) * r + // y1 = y0 - 1/3 * h * y0 + let h = ((d3y.hi - mm) + d3y.lo) * r; + // y1 = y0 - 1/3*y0*(h.lo + h.hi) = y0 - 1/3 *y0*h.lo - 1/3 * y0 * h.hi + let y = backend.fma(-f64::from_bits(0x3fd5555555555555), y0 * h, y0); + + f64::copysign(fast_ldexp(y, q), x) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cbrt_fma_impl(x: f64) -> f64 { + cbrt_gen_impl(x, FmaCbrtBackend {}) +} + +/// Computes cube root +/// +/// Max found ULP 0.5 +pub fn f_cbrt(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cbrt_gen_impl(x, GenericCbrtBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cbrt_fma_impl + } else { + fn def_cbrt(x: f64) -> f64 { + cbrt_gen_impl(x, GenericCbrtBackend {}) + } + def_cbrt + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_cbrt() { + assert_eq!(f_cbrt(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005432309223745), + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017579026781511548); + assert_eq!(f_cbrt(1.225158611559834), 1.0700336588124544); + assert_eq!(f_cbrt(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139491540182158), 1.1173329935611586e-103); + assert_eq!(f_cbrt(27.0), 3.0); + assert_eq!(f_cbrt(64.0), 4.0); + assert_eq!(f_cbrt(125.0), 5.0); + assert_eq!(f_cbrt(216.0), 6.0); + assert_eq!(f_cbrt(343.0), 7.0); + assert_eq!(f_cbrt(512.0), 8.0); + assert_eq!(f_cbrt(729.0), 9.0); + assert_eq!(f_cbrt(-729.0), -9.0); + assert_eq!(f_cbrt(-512.0), -8.0); + assert_eq!(f_cbrt(-343.0), -7.0); + assert_eq!(f_cbrt(-216.0), -6.0); + assert_eq!(f_cbrt(-125.0), -5.0); + assert_eq!(f_cbrt(-64.0), -4.0); + assert_eq!(f_cbrt(-27.0), -3.0); + assert_eq!(f_cbrt(0.0), 0.0); + assert_eq!(f_cbrt(f64::INFINITY), f64::INFINITY); + assert_eq!(f_cbrt(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert!(f_cbrt(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrtf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrtf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrtf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/cbrtf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,170 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::cube_roots::cbrt::{CbrtBackend, GenericCbrtBackend}; + +#[inline(always)] +pub(crate) fn halley_refine_d(x: f64, a: f64) -> f64 { + let tx = x * x * x; + x * f_fmla(2., a, tx) / f_fmla(2., tx, a) +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn halley_refine_d_fma(x: f64, a: f64) -> f64 { + let tx = x * x * x; + x * f64::mul_add(2., a, tx) / f64::mul_add(2., tx, a) +} + +#[inline(always)] +const fn halley_refine(x: f32, a: f32) -> f32 { + let tx = x * x * x; + x * (tx + 2f32 * a) / (2f32 * tx + a) +} + +/// Cbrt for given value for const context. +/// This is simplified version just to make a good approximation on const context. +#[inline] +pub const fn cbrtf(x: f32) -> f32 { + let u = x.to_bits(); + let au = u.wrapping_shl(1); + if au < (1u32 << 24) || au >= (0xffu32 << 24) { + if au >= (0xffu32 << 24) { + return x + x; /* inf, nan */ + } + if au == 0 { + return x; /* +-0 */ + } + } + + const B1: u32 = 709958130; + let mut t: f32; + let mut ui: u32 = x.to_bits(); + let mut hx: u32 = ui & 0x7fffffff; + + hx = (hx / 3).wrapping_add(B1); + ui &= 0x80000000; + ui |= hx; + + t = f32::from_bits(ui); + t = halley_refine(t, x); + halley_refine(t, x) +} + +#[inline(always)] +fn cbrtf_gen_impl(x: f32, backend: B) -> f32 { + let u = x.to_bits(); + let au = u.wrapping_shl(1); + if au < (1u32 << 24) || au >= (0xffu32 << 24) { + if au >= (0xffu32 << 24) { + return x + x; /* inf, nan */ + } + if au == 0 { + return x; /* +-0 */ + } + } + + let mut ui: u32 = x.to_bits(); + let mut hx: u32 = ui & 0x7fffffff; + + if hx < 0x00800000 { + /* zero or subnormal? */ + if hx == 0 { + return x; /* cbrt(+-0) is itself */ + } + const TWO_EXP_24: f32 = f32::from_bits(0x4b800000); + ui = (x * TWO_EXP_24).to_bits(); + hx = ui & 0x7fffffff; + const B2: u32 = 642849266; + hx = (hx / 3).wrapping_add(B2); + } else { + const B1: u32 = 709958130; + hx = (hx / 3).wrapping_add(B1); + } + ui &= 0x80000000; + ui |= hx; + + let mut t = f32::from_bits(ui) as f64; + let dx = x as f64; + t = backend.halley(t, dx); + backend.halley(t, dx) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cbrtf_fma_impl(x: f32) -> f32 { + use crate::cube_roots::cbrt::FmaCbrtBackend; + cbrtf_gen_impl(x, FmaCbrtBackend {}) +} + +/// Computes cube root +/// +/// Peak ULP on 64 bit = 0.49999577 +#[inline] +pub fn f_cbrtf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cbrtf_gen_impl(x, GenericCbrtBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cbrtf_fma_impl + } else { + fn def_cbrt(x: f32) -> f32 { + cbrtf_gen_impl(x, GenericCbrtBackend {}) + } + def_cbrt + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fcbrtf() { + assert_eq!(f_cbrtf(0.0), 0.0); + assert_eq!(f_cbrtf(-27.0), -3.0); + assert_eq!(f_cbrtf(27.0), 3.0); + assert_eq!(f_cbrtf(64.0), 4.0); + assert_eq!(f_cbrtf(-64.0), -4.0); + assert_eq!(f_cbrtf(f32::NEG_INFINITY), f32::NEG_INFINITY); + assert_eq!(f_cbrtf(f32::INFINITY), f32::INFINITY); + assert!(f_cbrtf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod cbrt; +mod cbrtf; +mod rcbrt; +mod rcbrtf; + +pub use cbrt::f_cbrt; +pub use cbrtf::{cbrtf, f_cbrtf}; +pub use rcbrt::f_rcbrt; +pub use rcbrtf::f_rcbrtf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrt.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,311 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::exponents::fast_ldexp; +use crate::polyeval::f_polyeval6; + +// +// // y1 = y0 + 1/3 * y0 * (1 - a * y0 * y0 * y0) +// #[inline] +// fn raphson_step(x: f64, a: f64) -> f64 { +// let h = f_fmla(-a * x, x * x, 1.0); +// f_fmla(1. / 3. * h, x, x) +// } + +// y1 = y0(k1 − c(k2 − k3c), c = x*y0*y0*y0 +// k1 = 14/9 , k2 = 7/9 , k3 = 2/9 +#[inline(always)] +fn halleys_div_free(x: f64, a: f64) -> f64 { + const K3: f64 = 2. / 9.; + const K2: f64 = 7. / 9.; + const K1: f64 = 14. / 9.; + let c = a * x * x * x; + let mut y = f_fmla(-K3, c, K2); + y = f_fmla(-c, y, K1); + y * x +} + +#[inline(always)] +#[allow(unused)] +fn halleys_div_free_fma(x: f64, a: f64) -> f64 { + const K3: f64 = 2. / 9.; + const K2: f64 = 7. / 9.; + const K1: f64 = 14. / 9.; + let c = a * x * x * x; + let mut y = f64::mul_add(-K3, c, K2); + y = f64::mul_add(-c, y, K1); + y * x +} + +#[inline(always)] +fn rcbrt_gen_impl(a: f64) -> f64 { + // Decompose a = m * 2^e, with m in [0.5, 1) + let xu = a.to_bits(); + let exp = ((xu >> 52) & 0x7ff) as i32; + let mut e = ((xu >> 52) & 0x7ff) as i32; + let mut mant = xu & ((1u64 << 52) - 1); + + if exp == 0x7ff { + if a.is_infinite() { + return if a.is_sign_negative() { -0.0 } else { 0.0 }; + } + return a + a; + } + if exp == 0 && a == 0. { + return if a.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + // Normalize subnormal + if exp == 0 { + let norm = a * f64::from_bits(0x4350000000000000); // * 2^54 + let norm_bits = norm.to_bits(); + mant = norm_bits & ((1u64 << 52) - 1); + e = ((norm_bits >> 52) & 0x7ff) as i32 - 54; + } + + e -= 1023; + + mant |= 0x3ff << 52; + let m = f64::from_bits(mant); + + // Polynomial for x^(-1/3) on [1.0; 2.0] + // Generated by Sollya: + // d = [1.0, 2.0]; + // f_inv_cbrt = x^(-1/3); + // Q = fpminimax(f_inv_cbrt, 5, [|D...|], d, relative, floating); + // See ./notes/inv_cbrt.sollya + + let p = f_polyeval6( + m, + f64::from_bits(0x3ffc7f365bceaf71), + f64::from_bits(0xbff90e741fb9c896), + f64::from_bits(0x3ff3e68b9b2cd237), + f64::from_bits(0xbfe321c5eb24a185), + f64::from_bits(0x3fc3fa269b897f69), + f64::from_bits(0xbf916d6f13849fd1), + ); + + // split exponent e = 3*q + r with r in {0,1,2} + // use div_euclid/rem_euclid to get r >= 0 + let q = e.div_euclid(3); + let rem_scale = e.rem_euclid(3); + + // 1; 2^{-1/3}; 2^{-2/3} + static ESCALE: [u64; 3] = [1.0f64.to_bits(), 0x3fe965fea53d6e3d, 0x3fe428a2f98d728b]; + + let z = p * f64::from_bits(ESCALE[rem_scale as usize]); + + let mm = fast_ldexp(m, rem_scale); // bring domain into [1;8] + + // One Halley's method step + // then refine in partial double-double precision with Newton-Raphson iteration + let y0 = halleys_div_free(z, mm); + + let d2y = DoubleDouble::from_exact_mult(y0, y0); + let d3y = DoubleDouble::quick_mult_f64(d2y, y0); + let hb = DoubleDouble::quick_mult_f64(d3y, mm); + + let y: f64; + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + // decompose double-double in linear FMA sums + // r = (1.0 - hb.hi - hb.lo) * y0 = y0 - hb.hi * y0 - hb.lo * y0 = fma(-hb.lo, y0, fma(-hb.hi, y0, y0)) + let r = f_fmla(-hb.lo, y0, f_fmla(hb.hi, -y0, y0)); + // // y1 = y0 + 1/3 * y0 * (1 - a * y0 * y0 * y0) = y0 + 1/3 * r + y = f_fmla(1. / 3., r, y0); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let m_hb = DoubleDouble::full_add_f64(-hb, 1.0); + let r = DoubleDouble::quick_mult_f64(m_hb, y0); + y = f_fmla(1. / 3., r.to_f64(), y0); + } + f64::copysign(fast_ldexp(y, -q), a) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn rcbrt_fma_impl(a: f64) -> f64 { + // Decompose a = m * 2^e, with m in [0.5, 1) + let xu = a.to_bits(); + let exp = ((xu >> 52) & 0x7ff) as i32; + let mut e = ((xu >> 52) & 0x7ff) as i32; + let mut mant = xu & ((1u64 << 52) - 1); + + if exp == 0x7ff { + if a.is_infinite() { + return if a.is_sign_negative() { -0.0 } else { 0.0 }; + } + return a + a; + } + if exp == 0 && a == 0. { + return if a.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + // Normalize subnormal + if exp == 0 { + let norm = a * f64::from_bits(0x4350000000000000); // * 2^54 + let norm_bits = norm.to_bits(); + mant = norm_bits & ((1u64 << 52) - 1); + e = ((norm_bits >> 52) & 0x7ff) as i32 - 54; + } + + e -= 1023; + + mant |= 0x3ff << 52; + let m = f64::from_bits(mant); + + // Polynomial for x^(-1/3) on [1.0; 2.0] + // Generated by Sollya: + // d = [1.0, 2.0]; + // f_inv_cbrt = x^(-1/3); + // Q = fpminimax(f_inv_cbrt, 5, [|D...|], d, relative, floating); + // See ./notes/inv_cbrt.sollya + + use crate::polyeval::d_polyeval6; + let p = d_polyeval6( + m, + f64::from_bits(0x3ffc7f365bceaf71), + f64::from_bits(0xbff90e741fb9c896), + f64::from_bits(0x3ff3e68b9b2cd237), + f64::from_bits(0xbfe321c5eb24a185), + f64::from_bits(0x3fc3fa269b897f69), + f64::from_bits(0xbf916d6f13849fd1), + ); + + // split exponent e = 3*q + r with r in {0,1,2} + // use div_euclid/rem_euclid to get r >= 0 + let q = e.div_euclid(3); + let rem_scale = e.rem_euclid(3); + + // 1; 2^{-1/3}; 2^{-2/3} + static ESCALE: [u64; 3] = [1.0f64.to_bits(), 0x3fe965fea53d6e3d, 0x3fe428a2f98d728b]; + + let z = p * f64::from_bits(ESCALE[rem_scale as usize]); + + let mm = fast_ldexp(m, rem_scale); // bring domain into [1;8] + + // One Halley's method step + // then refine in partial double-double precision with Newton-Raphson iteration + let y0 = halleys_div_free_fma(z, mm); + + let d2y = DoubleDouble::from_exact_mult_fma(y0, y0); + let d3y = DoubleDouble::quick_mult_f64_fma(d2y, y0); + let hb = DoubleDouble::quick_mult_f64_fma(d3y, mm); + + // decompose double-double in linear FMA sums + // r = (1.0 - hb.hi - hb.lo) * y0 = y0 - hb.hi * y0 - hb.lo * y0 = fma(-hb.lo, y0, fma(-hb.hi, y0, y0)) + let r = f64::mul_add(-hb.lo, y0, f64::mul_add(hb.hi, -y0, y0)); + // // y1 = y0 + 1/3 * y0 * (1 - a * y0 * y0 * y0) = y0 + 1/3 * r + let y = f64::mul_add(1. / 3., r, y0); + f64::copysign(fast_ldexp(y, -q), a) +} + +/// Computes 1/cbrt(x) +/// +/// ULP 0.5 +pub fn f_rcbrt(a: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + rcbrt_gen_impl(a) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + rcbrt_fma_impl + } else { + fn def_rcbrt(x: f64) -> f64 { + rcbrt_gen_impl(x) + } + def_rcbrt + } + }); + unsafe { q(a) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_rcbrt() { + assert_eq!(f_rcbrt(0.9999999999999717), 1.0000000000000095); + assert_eq!(f_rcbrt(-68355745214719140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + -0.000000000000000000000000000000000000000002445728958868668); + assert_eq!(f_rcbrt(-96105972807656840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + -0.0000000000000000000000000000000000000000000000000000000002183148143573148); + assert_eq!(f_rcbrt(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139491540182158), + 8949883389846071000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_rcbrt(0.00008386280387617153), 22.846001824951983); + assert_eq!(f_rcbrt(-125.0), -0.2); + assert_eq!(f_rcbrt(125.0), 0.2); + assert_eq!(f_rcbrt(1.0), 1.0); + assert_eq!(f_rcbrt(-1.0), -1.0); + assert_eq!(f_rcbrt(0.0), f64::INFINITY); + assert_eq!(f_rcbrt(-27.0), -1. / 3.); + assert_eq!( + f_rcbrt(2417851639214765300000000.), + 0.000000007450580596938716 + ); + assert_eq!(f_rcbrt(27.0), 1. / 3.); + assert_eq!(f_rcbrt(64.0), 0.25); + assert_eq!(f_rcbrt(-64.0), -0.25); + assert_eq!(f_rcbrt(f64::NEG_INFINITY), -0.0); + assert_eq!(f_rcbrt(f64::INFINITY), 0.0); + assert!(f_rcbrt(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrtf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrtf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrtf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/cube_roots/rcbrtf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +// // y1 = y0 * (2+x*y0^3)/(1+2*x*y0^3) +// #[inline(always)] +// fn halley_refine_d(x: f64, a: f64) -> f64 { +// let tx = x * x * x; +// x * f_fmla(tx, a, 2.0) / f_fmla(2. * a, tx, 1.0) +// } + +#[inline(always)] +fn rapshon_refine_inv_cbrt(x: f64, a: f64) -> f64 { + x * f_fmla(-1. / 3. * a, x * x * x, 4. / 3.) +} + +#[inline(always)] +#[allow(unused)] +fn rapshon_refine_inv_cbrt_fma(x: f64, a: f64) -> f64 { + x * f64::mul_add(-1. / 3. * a, x * x * x, 4. / 3.) +} + +// y1 = y0(k1 − c(k2 − k3c), c = x*y0*y0*y0 +// k1 = 14/9 , k2 = 7/9 , k3 = 2/9 +#[inline(always)] +fn halleys_div_free(x: f64, a: f64) -> f64 { + const K3: f64 = 2. / 9.; + const K2: f64 = 7. / 9.; + const K1: f64 = 14. / 9.; + let c = a * x * x * x; + let mut y = f_fmla(-K3, c, K2); + y = f_fmla(-c, y, K1); + y * x +} + +#[inline(always)] +#[allow(unused)] +fn halleys_div_free_fma(x: f64, a: f64) -> f64 { + const K3: f64 = 2. / 9.; + const K2: f64 = 7. / 9.; + const K1: f64 = 14. / 9.; + let c = a * x * x * x; + let mut y = f64::mul_add(-K3, c, K2); + y = f64::mul_add(-c, y, K1); + y * x +} + +#[inline(always)] +fn rcbrtf_gen_impl f64, NewtonRaphson: Fn(f64, f64) -> f64>( + x: f32, + halley: Halley, + rapshon: NewtonRaphson, +) -> f32 { + let u = x.to_bits(); + let au = u.wrapping_shl(1); + if au < (1u32 << 24) || au >= (0xffu32 << 24) { + if x.is_infinite() { + return if x.is_sign_negative() { -0.0 } else { 0.0 }; + } + if au >= (0xffu32 << 24) { + return x + x; /* inf, nan */ + } + if x == 0. { + return if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NEG_INFINITY + }; /* +-inf */ + } + } + + let mut ui: u32 = x.to_bits(); + let mut hx: u32 = ui & 0x7fffffff; + + if hx < 0x00800000 { + /* zero or subnormal? */ + if hx == 0 { + return x; /* cbrt(+-0) is itself */ + } + const TWO_EXP_24: f32 = f32::from_bits(0x4b800000); + ui = (x * TWO_EXP_24).to_bits(); + hx = ui & 0x7fffffff; + const B: u32 = 0x54a21d2au32 + (8u32 << 23); + hx = B.wrapping_sub(hx / 3); + } else { + hx = 0x54a21d2au32.wrapping_sub(hx / 3); + } + ui &= 0x80000000; + ui |= hx; + + let t = f32::from_bits(ui) as f64; + let dx = x as f64; + let mut t = halley(t, dx); + t = halley(t, dx); + t = rapshon(t, dx); + t as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn rcbrtf_fma_impl(x: f32) -> f32 { + rcbrtf_gen_impl(x, halleys_div_free_fma, rapshon_refine_inv_cbrt_fma) +} + +/// Computes 1/cbrt(x) +/// +/// ULP 0.5 +#[inline] +pub fn f_rcbrtf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + rcbrtf_gen_impl(x, halleys_div_free, rapshon_refine_inv_cbrt) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + rcbrtf_fma_impl + } else { + fn def_rcbrtf(x: f32) -> f32 { + rcbrtf_gen_impl(x, halleys_div_free, rapshon_refine_inv_cbrt) + } + def_rcbrtf + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fcbrtf() { + assert_eq!(f_rcbrtf(0.0), f32::INFINITY); + assert_eq!(f_rcbrtf(-0.0), f32::NEG_INFINITY); + assert_eq!(f_rcbrtf(-27.0), -1. / 3.); + assert_eq!(f_rcbrtf(27.0), 1. / 3.); + assert_eq!(f_rcbrtf(64.0), 0.25); + assert_eq!(f_rcbrtf(-64.0), -0.25); + assert_eq!(f_rcbrtf(f32::NEG_INFINITY), -0.0); + assert_eq!(f_rcbrtf(f32::INFINITY), 0.0); + assert!(f_rcbrtf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/double_double.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/double_double.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/double_double.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/double_double.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1095 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::get_exponent_f64; +#[allow(unused_imports)] +use crate::common::*; +use std::ops::{Mul, Neg}; +// https://hal.science/hal-01351529v3/document + +#[derive(Copy, Clone, Default, Debug)] +pub(crate) struct DoubleDouble { + pub(crate) lo: f64, + pub(crate) hi: f64, +} + +impl Neg for DoubleDouble { + type Output = Self; + + #[inline] + fn neg(self) -> Self::Output { + Self { + hi: -self.hi, + lo: -self.lo, + } + } +} + +impl DoubleDouble { + #[inline] + pub(crate) const fn from_bit_pair(pair: (u64, u64)) -> Self { + Self { + lo: f64::from_bits(pair.0), + hi: f64::from_bits(pair.1), + } + } + + #[inline] + pub(crate) const fn new(lo: f64, hi: f64) -> Self { + DoubleDouble { lo, hi } + } + + // Non FMA helper + #[allow(dead_code)] + #[inline] + pub(crate) const fn split(a: f64) -> DoubleDouble { + // CN = 2^N. + const CN: f64 = (1 << 27) as f64; + const C: f64 = CN + 1.0; + let t1 = C * a; + let t2 = a - t1; + let r_hi = t1 + t2; + let r_lo = a - r_hi; + DoubleDouble::new(r_lo, r_hi) + } + + // Non FMA helper + #[allow(dead_code)] + #[inline] + fn from_exact_mult_impl_non_fma(asz: DoubleDouble, a: f64, b: f64) -> Self { + let bs = DoubleDouble::split(b); + + let r_hi = a * b; + let t1 = asz.hi * bs.hi - r_hi; + let t2 = asz.hi * bs.lo + t1; + let t3 = asz.lo * bs.hi + t2; + let r_lo = asz.lo * bs.lo + t3; + DoubleDouble::new(r_lo, r_hi) + } + + // valid only for |a| > b + #[inline] + pub(crate) const fn from_exact_add(a: f64, b: f64) -> DoubleDouble { + let r_hi = a + b; + let t = r_hi - a; + let r_lo = b - t; + DoubleDouble::new(r_lo, r_hi) + } + + // valid only for |a| > b + #[inline] + pub(crate) const fn from_exact_sub(a: f64, b: f64) -> DoubleDouble { + let r_hi = a - b; + let t = a - r_hi; + let r_lo = t - b; + DoubleDouble::new(r_lo, r_hi) + } + + #[inline] + pub(crate) const fn from_full_exact_add(a: f64, b: f64) -> DoubleDouble { + let r_hi = a + b; + let t1 = r_hi - a; + let t2 = r_hi - t1; + let t3 = b - t1; + let t4 = a - t2; + let r_lo = t3 + t4; + DoubleDouble::new(r_lo, r_hi) + } + + #[allow(unused)] + #[inline] + pub(crate) fn dd_f64_mul_add(a: f64, b: f64, c: f64) -> f64 { + let ddx2 = DoubleDouble::from_exact_mult(a, b); + let zv = DoubleDouble::full_add_f64(ddx2, c); + zv.to_f64() + } + + #[inline] + pub(crate) const fn from_full_exact_sub(a: f64, b: f64) -> Self { + let r_hi = a - b; + let t1 = r_hi - a; + let t2 = r_hi - t1; + let t3 = -b - t1; + let t4 = a - t2; + let r_lo = t3 + t4; + DoubleDouble::new(r_lo, r_hi) + } + + #[inline] + pub(crate) fn add(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let s = a.hi + b.hi; + let d = s - a.hi; + let l = ((b.hi - d) + (a.hi + (d - s))) + (a.lo + b.lo); + DoubleDouble::new(l, s) + } + + #[inline] + pub(crate) fn quick_dd_add(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let DoubleDouble { hi: sh, lo: sl } = DoubleDouble::from_full_exact_add(a.hi, b.hi); + let v = a.lo + b.lo; + let w = sl + v; + DoubleDouble::from_exact_add(sh, w) + } + + #[inline] + pub(crate) fn quick_dd_sub(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let DoubleDouble { hi: sh, lo: sl } = DoubleDouble::from_full_exact_sub(a.hi, b.hi); + let v = a.lo - b.lo; + let w = sl + v; + DoubleDouble::from_exact_add(sh, w) + } + + #[inline] + pub(crate) fn full_dd_add(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let DoubleDouble { hi: sh, lo: sl } = DoubleDouble::from_full_exact_add(a.hi, b.hi); + let DoubleDouble { hi: th, lo: tl } = DoubleDouble::from_full_exact_add(a.lo, b.lo); + let c = sl + th; + let v = DoubleDouble::from_exact_add(sh, c); + let w = tl + v.lo; + DoubleDouble::from_exact_add(v.hi, w) + } + + #[inline] + pub(crate) fn full_dd_sub(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + DoubleDouble::full_dd_add(a, -b) + } + + #[inline] + pub(crate) fn sub(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let s = a.hi - b.hi; + let d = s - a.hi; + let l = ((-b.hi - d) + (a.hi + (d - s))) + (a.lo - b.lo); + DoubleDouble::new(l, s) + } + + /// DoubleDouble-style square root for a double-double number + #[inline] + pub(crate) fn sqrt(self) -> DoubleDouble { + let a = self.hi + self.lo; + + if a == 0.0 { + return DoubleDouble { hi: 0.0, lo: 0.0 }; + } + if a < 0.0 || a.is_nan() { + return DoubleDouble { + hi: f64::NAN, + lo: 0.0, + }; + } + if a.is_infinite() { + return DoubleDouble { + hi: f64::INFINITY, + lo: 0.0, + }; + } + + let x = a.sqrt(); + + let x2 = DoubleDouble::from_exact_mult(x, x); + + // Residual = self - x² + let mut r = self.hi - x2.hi; + r += self.lo; + r -= x2.lo; + + let dx = r / (2.0 * x); + let hi = x + dx; + let lo = (x - hi) + dx; + + DoubleDouble { hi, lo } + } + + /// DoubleDouble-style square root for a double-double number + #[inline] + pub(crate) fn fast_sqrt(self) -> DoubleDouble { + let a = self.hi + self.lo; + let x = a.sqrt(); + + let x2 = DoubleDouble::from_exact_mult(x, x); + + // Residual = self - x² + let mut r = self.hi - x2.hi; + r += self.lo; + r -= x2.lo; + + let dx = r / (2.0 * x); + let hi = x + dx; + let lo = (x - hi) + dx; + + DoubleDouble { hi, lo } + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn mul_add_f64(a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_full_exact_add(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline(always)] + #[allow(unused)] + pub(crate) fn mul_add_f64_fma(a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_fma(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_full_exact_add(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn quick_mul_add_f64(a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_exact_add(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn mul_f64_add_f64(a: DoubleDouble, b: f64, c: f64) -> DoubleDouble { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_f64(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_full_exact_add(c, h); + DoubleDouble::new(r + q, p) + } + + // /// Accurate reciprocal: 1 / self + // #[inline] + // pub(crate) fn recip_raphson(self) -> DoubleDouble { + // let y0 = DoubleDouble::recip(self); + // let z = DoubleDouble::mul_add_f64(-self, y0, 1.0); + // DoubleDouble::mul_add(y0, z, y0) + // } + + /// Accurate reciprocal: 1 / self + #[inline] + pub(crate) fn recip(self) -> DoubleDouble { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let y = 1. / self.hi; + let e1 = f_fmla(-self.hi, y, 1.0); + let e2 = f_fmla(-self.lo, y, e1); + let e = y * e2; + DoubleDouble::new(e, y) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let y = 1.0 / self.hi; + + let DoubleDouble { hi: p1, lo: err1 } = DoubleDouble::from_exact_mult(self.hi, y); + let e1 = (1.0 - p1) - err1; + let DoubleDouble { hi: p2, lo: err2 } = DoubleDouble::from_exact_mult(self.lo, y); + let e2 = (e1 - p2) - err2; + let e = y * e2; + + DoubleDouble::new(e, y) + } + } + + #[inline] + pub(crate) fn from_recip(b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let x_hi = 1.0 / b; + let err = f_fmla(-x_hi, b, 1.0); + let x_lo = err / b; + Self::new(x_lo, x_hi) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x_hi = 1.0 / b; + let prod = Self::from_exact_mult(x_hi, b); + let err = (1.0 - prod.hi) - prod.lo; + let x_lo = err / b; + Self::new(x_lo, x_hi) + } + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn from_quick_recip_fma(b: f64) -> Self { + let h = 1.0 / b; + let hl = f64::mul_add(h, -b, 1.) * h; + DoubleDouble::new(hl, h) + } + + #[inline] + pub(crate) fn from_quick_recip(b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let h = 1.0 / b; + let hl = f_fmla(h, -b, 1.) * h; + DoubleDouble::new(hl, h) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let h = 1.0 / b; + let pr = DoubleDouble::from_exact_mult(h, b); + let err = (1.0 - pr.hi) - pr.lo; + let hl = err * h; + DoubleDouble::new(hl, h) + } + } + + #[inline] + pub(crate) fn from_exact_div(a: f64, b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let q_hi = a / b; + let r = f_fmla(-q_hi, b, a); + let q_lo = r / b; + Self::new(q_lo, q_hi) + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let q_hi = a / b; + + let p = DoubleDouble::from_exact_mult(q_hi, b); + let r = DoubleDouble::from_exact_sub(a, p.hi); + let r = r.hi + (r.lo - p.lo); + let q_lo = r / b; + + Self::new(q_lo, q_hi) + } + } + + // Resistant to overflow without FMA + #[inline] + pub(crate) fn from_exact_div_fma(a: f64, b: f64) -> Self { + let q_hi = a / b; + let r = f64::mul_add(-q_hi, b, a); + let q_lo = r / b; + Self::new(q_lo, q_hi) + } + + #[inline] + pub(crate) fn from_sqrt(x: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let h = x.sqrt(); + /* h = sqrt(x) * (1 + e1) with |e1| < 2^-52 + thus h^2 = x * (1 + e2) with |e2| < 2^-50.999 */ + let e = -f_fmla(h, h, -x); // exact + + /* e = x - h^2 */ + let l = e / (h + h); + DoubleDouble::new(l, h) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let h = x.sqrt(); + let prod_hh = DoubleDouble::from_exact_mult(h, h); + let e = (x - prod_hh.hi) - prod_hh.lo; // exact + + /* e = x - h^2 */ + let l = e / (h + h); + DoubleDouble::new(l, h) + } + } + + /// Safe to overflow underflow division using mandatory FMA. + #[inline] + #[allow(dead_code)] + pub(crate) fn div_safe_dd_f64(a: DoubleDouble, b: f64) -> Self { + let q1 = a.hi / b; + let r = f64::mul_add(-q1, b, a.hi); + let r = r + a.lo; + let q2 = r / b; + + DoubleDouble::new(q2, q1) + } + + #[inline] + pub(crate) fn div_dd_f64(a: DoubleDouble, b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let q1 = a.hi / b; + let r = f_fmla(-q1, b, a.hi); + let r = r + a.lo; + let q2 = r / b; + + DoubleDouble::new(q2, q1) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let th = a.hi / b; + let prod = DoubleDouble::from_exact_mult(th, b); + let beta_h = a.hi - prod.hi; + let beta_l = beta_h - prod.lo; + let beta = beta_l + a.lo; + let tl = beta / b; + DoubleDouble::new(tl, th) + } + } + + // /// Dekker division with one refinement step + // #[inline] + // pub(crate) fn div_dd_f64_newton_raphson(a: DoubleDouble, b: f64) -> Self { + // // Initial estimate q = a / b + // let q = DoubleDouble::div_dd_f64(a, b); + // + // // One Newton-Raphson refinement step: + // // e = a - q * b + // let qb = DoubleDouble::quick_mult_f64(q, b); + // let e = DoubleDouble::sub(a, qb); + // let e_div_b = DoubleDouble::div_dd_f64(e, b); + // + // DoubleDouble::add(q, e_div_b) + // } + + // /// Dekker division with two Newton-Raphson refinement steps + // #[inline] + // pub(crate) fn div_dd_f64_newton_raphson_2(a: Dekker, b: f64) -> Self { + // // First estimate: q = a / b (one round of Dekker division) + // let q1 = Dekker::div_dd_f64(a, b); + // + // // First refinement: q2 = q1 + (a - q1 * b) / b + // let qb1 = Dekker::quick_mult_f64(q1, b); + // let e1 = Dekker::sub(a, qb1); + // let dq1 = Dekker::div_dd_f64(e1, b); + // let q2 = Dekker::add(q1, dq1); + // + // // Second refinement: q3 = q2 + (a - q2 * b) / b + // let qb2 = Dekker::quick_mult_f64(q2, b); + // let e2 = Dekker::sub(a, qb2); + // let dq2 = Dekker::div_dd_f64(e2, b); + // + // Dekker::add(q2, dq2) + // } + + // #[inline] + // pub(crate) fn neg(self) -> Self { + // Self { + // lo: -self.lo, hi: -self.hi, + // } + // } + + #[inline] + pub(crate) fn from_f64_div_dd(a: f64, b: DoubleDouble) -> Self { + let q1 = a / b.hi; + + let prod = DoubleDouble::from_exact_mult(q1, b.hi); + let prod_lo = f_fmla(q1, b.lo, prod.lo); + let rem = f_fmla(-1.0, prod.hi, a) - prod_lo; + + let q2 = rem / b.hi; + + DoubleDouble::new(q2, q1) + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn from_f64_div_dd_fma(a: f64, b: DoubleDouble) -> Self { + let q1 = a / b.hi; + + let prod = DoubleDouble::from_exact_mult_fma(q1, b.hi); + let prod_lo = f64::mul_add(q1, b.lo, prod.lo); + let rem = f64::mul_add(-1.0, prod.hi, a) - prod_lo; + + let q2 = rem / b.hi; + + DoubleDouble::new(q2, q1) + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn div_fma(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let q = 1.0 / b.hi; + let r_hi = a.hi * q; + let e_hi = f64::mul_add(b.hi, -r_hi, a.hi); + let e_lo = f64::mul_add(b.lo, -r_hi, a.lo); + let r_lo = q * (e_hi + e_lo); + DoubleDouble::new(r_lo, r_hi) + } + + #[inline] + pub(crate) fn div(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let q = 1.0 / b.hi; + let r_hi = a.hi * q; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let e_hi = f_fmla(b.hi, -r_hi, a.hi); + let e_lo = f_fmla(b.lo, -r_hi, a.lo); + let r_lo = q * (e_hi + e_lo); + DoubleDouble::new(r_lo, r_hi) + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let b_hi_r_hi = DoubleDouble::from_exact_mult(b.hi, -r_hi); + let b_lo_r_hi = DoubleDouble::from_exact_mult(b.lo, -r_hi); + let e_hi = (a.hi + b_hi_r_hi.hi) + b_hi_r_hi.lo; + let e_lo = (a.lo + b_lo_r_hi.hi) + b_lo_r_hi.lo; + let r_lo = q * (e_hi + e_lo); + DoubleDouble::new(r_lo, r_hi) + } + } + + #[inline] + pub(crate) fn from_exact_mult(a: f64, b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let r_hi = a * b; + let r_lo = f_fmla(a, b, -r_hi); + DoubleDouble::new(r_lo, r_hi) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let splat = DoubleDouble::split(a); + DoubleDouble::from_exact_mult_impl_non_fma(splat, a, b) + } + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn from_exact_mult_fma(a: f64, b: f64) -> Self { + let r_hi = a * b; + let r_lo = f64::mul_add(a, b, -r_hi); + DoubleDouble::new(r_lo, r_hi) + } + + // #[inline] + // pub(crate) fn add_f64(&self, other: f64) -> DoubleDouble { + // let r = DoubleDouble::from_exact_add(self.hi, other); + // Dekker::from_exact_add(r.hi, r.lo + self.lo) + // } + + // #[inline] + // pub(crate) fn to_triple(self) -> TripleDouble { + // TripleDouble::new(0., self.lo, self.hi) + // } + + /// Computes `a * b + c` + /// `b` is an `f64`, `a` and `c` are `DoubleDouble`. + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn mul_f64_add(a: DoubleDouble, b: f64, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_f64(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::full_add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + /// Computes `a * b + c` + /// `b` is an `f64`, `a` and `c` are `DoubleDouble`. + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + /// + /// *Correctness* + /// |c.hi| > |a.hi * b.hi| + #[inline] + pub(crate) fn quick_mul_f64_add(a: DoubleDouble, b: f64, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_f64(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + /// Computes `a * b + c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + /// + /// *Correctness* + /// |c.hi| > |a.hi * b.hi| + #[inline] + pub(crate) fn quick_mul_f64_add_f64(a: DoubleDouble, b: f64, c: f64) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_f64(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_exact_add(c, h); + DoubleDouble::new(r + q, p) + } + + // #[inline] + // pub(crate) fn mul_f64_add_full(a: DoubleDouble, b: f64, c: DoubleDouble) -> Self { + // /* + // double _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8; \ + // \ + // Mul12(&_t1,&_t2,(a),(bh)); \ + // Add12(_t3,_t4,(ch),_t1); \ + // _t5 = (bl) * (a); \ + // _t6 = (cl) + _t2; \ + // _t7 = _t5 + _t6; \ + // _t8 = _t7 + _t4; \ + // Add12((*(resh)),(*(resl)),_t3,_t8); \ + // */ + // let DoubleDouble { hi: t1, lo: t2 } = DoubleDouble::from_exact_mult(a.hi, b); + // let DoubleDouble { hi: t3, lo: t4 } = DoubleDouble::from_full_exact_add(c.hi, t1); + // let t5 = a.lo * b; + // let t6 = c.lo + t2; + // let t7 = t5 + t6; + // let t8 = t7 + t4; + // DoubleDouble::from_full_exact_add(t3, t8) + // } + + /// Computes `a * b + c` + /// `b` is an `f64`, `a` and `c` are `DoubleDouble`. + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn f64_mul_f64_add(a: f64, b: f64, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::from_exact_mult(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::full_add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + // /// Computes `a * b + c` + // /// `b` is an `f64`, `a` and `c` are `DoubleDouble`. + // /// + // /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + // #[inline] + // pub(crate) fn single_mul_add(a: f64, b: f64, c: f64) -> Self { + // let DoubleDouble { hi: h, lo: r } = DoubleDouble::from_exact_mult(a, b); + // let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_full_exact_add(c, h); + // DoubleDouble::new(r + q, p) + // } + + // /// Computes `a * b + c` safe to overflow without FMA + // /// `b` is an `f64`, `a` and `c` are `DoubleDouble`. + // /// + // /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + // #[inline] + // pub(crate) fn mul_f64_safe_add(a: DoubleDouble, b: f64, c: DoubleDouble) -> Self { + // let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_safe_f64(a, b); + // let DoubleDouble { hi: p, lo: q } = DoubleDouble::full_add_f64(c, h); + // DoubleDouble::new(r + q, p) + // } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline] + pub(crate) fn mul_add(a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::full_add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + #[inline(always)] + #[allow(unused)] + pub(crate) fn mul_add_fma(a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_fma(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::full_add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + /// + /// *Correctness* + /// |c.hi| > |a.hi * b.hi| + #[inline] + pub(crate) fn quick_mul_add(a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + /// `a*b+c` + /// + /// *Accurate dot product (Ogita, Rump and Oishi 2004)* + /// + /// *Correctness* + /// |c.hi| > |a.hi * b.hi| + #[inline(always)] + #[allow(unused)] + pub(crate) fn quick_mul_add_fma(a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> Self { + let DoubleDouble { hi: h, lo: r } = DoubleDouble::quick_mult_fma(a, b); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::add_f64(c, h); + DoubleDouble::new(r + q, p) + } + + #[inline] + pub(crate) fn quick_mult(a: DoubleDouble, b: DoubleDouble) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let mut r = DoubleDouble::from_exact_mult(a.hi, b.hi); + let t1 = f_fmla(a.hi, b.lo, r.lo); + let t2 = f_fmla(a.lo, b.hi, t1); + r.lo = t2; + r + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b.hi); + let tl1 = a.hi * b.lo; + let tl2 = a.lo * b.hi; + let cl2 = tl1 + tl2; + let cl3 = cl1 + cl2; + DoubleDouble::new(cl3, ch) + } + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn quick_mult_fma(a: DoubleDouble, b: DoubleDouble) -> Self { + let mut r = DoubleDouble::from_exact_mult_fma(a.hi, b.hi); + let t1 = f64::mul_add(a.hi, b.lo, r.lo); + let t2 = f64::mul_add(a.lo, b.hi, t1); + r.lo = t2; + r + } + + #[inline] + pub(crate) fn mult(a: DoubleDouble, b: DoubleDouble) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b.hi); + let tl0 = a.lo * b.lo; + let tl1 = f_fmla(a.hi, b.lo, tl0); + let cl2 = f_fmla(a.lo, b.hi, tl1); + let cl3 = cl1 + cl2; + DoubleDouble::from_exact_add(ch, cl3) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b.hi); + let tl1 = a.hi * b.lo; + let tl2 = a.lo * b.hi; + let cl2 = tl1 + tl2; + let cl3 = cl1 + cl2; + DoubleDouble::from_exact_add(ch, cl3) + } + } + + #[inline] + pub(crate) fn mult_f64(a: DoubleDouble, b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b); + let cl3 = f_fmla(a.lo, b, cl1); + DoubleDouble::from_exact_add(ch, cl3) + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b); + let cl2 = a.lo * b; + let t = DoubleDouble::from_exact_add(ch, cl2); + let tl2 = t.lo + cl1; + DoubleDouble::from_exact_add(t.hi, tl2) + } + } + + #[inline(always)] + pub(crate) fn quick_f64_mult(a: f64, b: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_f64(b, a) + } + + #[inline] + pub(crate) fn quick_mult_f64(a: DoubleDouble, b: f64) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let h = b * a.hi; + let l = f_fmla(b, a.lo, f_fmla(b, a.hi, -h)); + Self { lo: l, hi: h } + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let DoubleDouble { hi: ch, lo: cl1 } = DoubleDouble::from_exact_mult(a.hi, b); + let cl2 = a.lo * b; + let cl3 = cl1 + cl2; + DoubleDouble::new(cl3, ch) + } + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn quick_mult_f64_fma(a: DoubleDouble, b: f64) -> Self { + let h = b * a.hi; + let l = f64::mul_add(b, a.lo, f64::mul_add(b, a.hi, -h)); + Self { lo: l, hi: h } + } + + // /// Double-double multiplication safe to overflow without FMA + // #[inline] + // pub(crate) fn quick_mult_safe_f64(a: DoubleDouble, b: f64) -> Self { + // let h = b * a.hi; + // let l = f64::mul_add(b, a.lo, f64::mul_add(b, a.hi, -h)); + // Self { lo: l, hi: h } + // } + + /// Valid only |a.hi| > |b| + #[inline] + pub(crate) fn add_f64(a: DoubleDouble, b: f64) -> Self { + let t = DoubleDouble::from_exact_add(a.hi, b); + let l = a.lo + t.lo; + Self { lo: l, hi: t.hi } + } + + #[inline] + pub(crate) fn full_add_f64(a: DoubleDouble, b: f64) -> Self { + let t = DoubleDouble::from_full_exact_add(a.hi, b); + let l = a.lo + t.lo; + Self { lo: l, hi: t.hi } + } + + /// Valid only |b| > |a.hi| + #[inline] + pub(crate) fn f64_add(b: f64, a: DoubleDouble) -> Self { + let t = DoubleDouble::from_exact_add(b, a.hi); + let l = a.lo + t.lo; + Self { lo: l, hi: t.hi } + } + + #[inline] + pub(crate) const fn to_f64(self) -> f64 { + self.lo + self.hi + } + + // #[inline] + // pub(crate) fn from_rsqrt(x: f64) -> DoubleDouble { + // let r = DoubleDouble::div_dd_f64(DoubleDouble::from_sqrt(x), x); + // let rx = DoubleDouble::quick_mult_safe_f64(r, x); + // let drx = DoubleDouble::mul_f64_safe_add(r, x, -rx); + // let h = DoubleDouble::mul_add(r, drx, DoubleDouble::mul_add_f64(r, rx, -1.0)); + // let dr = DoubleDouble::quick_mult(DoubleDouble::quick_mult_f64(r, 0.5), h); + // DoubleDouble::add(r, dr) + // } + + #[inline] + pub(crate) fn from_rsqrt_fast(x: f64) -> DoubleDouble { + let sqrt_x = DoubleDouble::from_sqrt(x); + sqrt_x.recip() + } +} + +impl Mul for DoubleDouble { + type Output = Self; + + #[inline] + fn mul(self, rhs: DoubleDouble) -> Self::Output { + DoubleDouble::quick_mult(self, rhs) + } +} + +/// check if number is valid for Exact mult +#[allow(dead_code)] +#[inline] +pub(crate) fn two_product_compatible(x: f64) -> bool { + let exp = get_exponent_f64(x); + !(exp >= 970 || exp <= -970) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_f64_mult() { + let d1 = 1.1231; + let d2 = DoubleDouble::new(1e-22, 3.2341); + let p = DoubleDouble::quick_f64_mult(d1, d2); + assert_eq!(p.hi, 3.6322177100000004); + assert_eq!(p.lo, -1.971941841373783e-16); + } + + #[test] + fn test_mult_64() { + let d1 = 1.1231; + let d2 = DoubleDouble::new(1e-22, 3.2341); + let p = DoubleDouble::mult_f64(d2, d1); + assert_eq!(p.hi, 3.6322177100000004); + assert_eq!(p.lo, -1.971941841373783e-16); + } + + #[test] + fn recip_test() { + let d1 = 1.54352432142; + let recip = DoubleDouble::new(0., d1).recip(); + assert_eq!(recip.hi, d1.recip()); + assert_ne!(recip.lo, 0.); + } + + #[test] + fn from_recip_test() { + let d1 = 1.54352432142; + let recip = DoubleDouble::from_recip(d1); + assert_eq!(recip.hi, d1.recip()); + assert_ne!(recip.lo, 0.); + } + + #[test] + fn from_quick_recip_test() { + let d1 = 1.54352432142; + let recip = DoubleDouble::from_quick_recip(d1); + assert_eq!(recip.hi, d1.recip()); + assert_ne!(recip.lo, 0.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/dyadic_float.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/dyadic_float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/dyadic_float.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/dyadic_float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,881 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::EXP_MASK; +use crate::common::f_fmla; +use std::ops::{Add, Mul, Sub}; + +#[repr(u8)] +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] +pub(crate) enum DyadicSign { + Pos = 0, + Neg = 1, +} + +impl DyadicSign { + #[inline] + pub(crate) fn negate(self) -> Self { + match self { + DyadicSign::Pos => DyadicSign::Neg, + DyadicSign::Neg => DyadicSign::Pos, + } + } + + #[inline] + pub(crate) const fn to_bit(self) -> u8 { + match self { + DyadicSign::Pos => 0, + DyadicSign::Neg => 1, + } + } + + #[inline] + pub(crate) const fn mult(self, rhs: Self) -> Self { + if (self as u8) ^ (rhs as u8) != 0 { + DyadicSign::Neg + } else { + DyadicSign::Pos + } + } +} + +const BITS: u32 = 128; + +#[derive(Copy, Clone, Debug)] +pub(crate) struct DyadicFloat128 { + pub(crate) sign: DyadicSign, + pub(crate) exponent: i16, + pub(crate) mantissa: u128, +} + +#[inline] +pub(crate) const fn f64_from_parts(sign: DyadicSign, exp: u64, mantissa: u64) -> f64 { + let r_sign = (if sign.to_bit() == 0 { 0u64 } else { 1u64 }).wrapping_shl(63); + let r_exp = exp.wrapping_shl(52); + f64::from_bits(r_sign | r_exp | mantissa) +} + +#[inline] +pub(crate) fn mulhi_u128(a: u128, b: u128) -> u128 { + let a_lo = a as u64 as u128; + let a_hi = (a >> 64) as u64 as u128; + let b_lo = b as u64 as u128; + let b_hi = (b >> 64) as u64 as u128; + + let lo_lo = a_lo * b_lo; + let lo_hi = a_lo * b_hi; + let hi_lo = a_hi * b_lo; + let hi_hi = a_hi * b_hi; + + let carry = (lo_lo >> 64) + .wrapping_add(lo_hi & 0xffff_ffff_ffff_ffff) + .wrapping_add(hi_lo & 0xffff_ffff_ffff_ffff); + let mid = (lo_hi >> 64) + .wrapping_add(hi_lo >> 64) + .wrapping_add(carry >> 64); + + hi_hi.wrapping_add(mid) +} + +#[inline] +const fn explicit_exponent(x: f64) -> i16 { + let exp = ((x.to_bits() >> 52) & ((1u64 << 11) - 1u64)) as i16 - 1023; + if x == 0. { + return 0; + } else if x.is_subnormal() { + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + return 1i16 - EXP_BIAS as i16; + } + exp +} + +#[inline] +const fn explicit_mantissa(x: f64) -> u64 { + const MASK: u64 = (1u64 << 52) - 1; + let sig_bits = x.to_bits() & MASK; + if x.is_subnormal() || x == 0. { + return sig_bits; + } + (1u64 << 52) | sig_bits +} + +impl DyadicFloat128 { + #[inline] + pub(crate) const fn zero() -> Self { + Self { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0, + } + } + + #[inline] + pub(crate) const fn new_from_f64(x: f64) -> Self { + let sign = if x.is_sign_negative() { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + let exponent = explicit_exponent(x) - 52; + let mantissa = explicit_mantissa(x) as u128; + let mut new_val = Self { + sign, + exponent, + mantissa, + }; + new_val.normalize(); + new_val + } + + #[inline] + pub(crate) fn new(sign: DyadicSign, exponent: i16, mantissa: u128) -> Self { + let mut new_item = DyadicFloat128 { + sign, + exponent, + mantissa, + }; + new_item.normalize(); + new_item + } + + #[inline] + pub(crate) fn accurate_reciprocal(a: f64) -> Self { + let mut r = DyadicFloat128::new_from_f64(4.0 / a); /* accurate to about 53 bits */ + r.exponent -= 2; + /* we use Newton's iteration: r -> r + r*(1-a*r) */ + let ba = DyadicFloat128::new_from_f64(-a); + let mut q = ba * r; + const F128_ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }; + q = F128_ONE + q; + q = r * q; + r + q + } + + #[inline] + pub(crate) fn from_div_f64(a: f64, b: f64) -> Self { + let reciprocal = DyadicFloat128::accurate_reciprocal(b); + let da = DyadicFloat128::new_from_f64(a); + reciprocal * da + } + + /// Multiply self by integer scalar `b`. + /// Returns a new normalized DyadicFloat128. + #[inline] + pub(crate) fn mul_int64(&self, b: i64) -> DyadicFloat128 { + if b == 0 { + return DyadicFloat128::zero(); + } + + let abs_b = b.unsigned_abs(); + let sign = if (b < 0) ^ (self.sign == DyadicSign::Neg) { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + + let mut hi_prod = (self.mantissa >> 64).wrapping_mul(abs_b as u128); + let m = hi_prod.leading_zeros(); + hi_prod <<= m; + + let mut lo_prod = (self.mantissa & 0xffff_ffff_ffff_ffff).wrapping_mul(abs_b as u128); + lo_prod = (lo_prod << (m - 1)) >> 63; + + let (mut product, overflow) = hi_prod.overflowing_add(lo_prod); + + let mut result = DyadicFloat128 { + sign, + exponent: self.exponent + 64 - m as i16, + mantissa: product, + }; + + if overflow { + // Overflow means an implicit bit in the 129th place, which we shift down. + product += product & 0x1; + result.mantissa = (product >> 1) | (1u128 << 127); + result.shift_right(1); + } + + result.normalize(); + result + } + + #[inline] + fn shift_right(&mut self, amount: u32) { + if amount < BITS { + self.exponent += amount as i16; + self.mantissa = self.mantissa.wrapping_shr(amount); + } else { + self.exponent = 0; + self.mantissa = 0; + } + } + + #[inline] + fn shift_left(&mut self, amount: u32) { + if amount < BITS { + self.exponent -= amount as i16; + self.mantissa = self.mantissa.wrapping_shl(amount); + } else { + self.exponent = 0; + self.mantissa = 0; + } + } + + // Don't forget to call if manually created + #[inline] + pub(crate) const fn normalize(&mut self) { + if self.mantissa != 0 { + let shift_length = self.mantissa.leading_zeros(); + self.exponent -= shift_length as i16; + self.mantissa = self.mantissa.wrapping_shl(shift_length); + } + } + + #[inline] + pub(crate) fn negated(&self) -> Self { + Self { + sign: self.sign.negate(), + exponent: self.exponent, + mantissa: self.mantissa, + } + } + + #[inline] + pub(crate) fn quick_sub(&self, rhs: &Self) -> Self { + self.quick_add(&rhs.negated()) + } + + #[inline] + pub(crate) fn quick_add(&self, rhs: &Self) -> Self { + if self.mantissa == 0 { + return *rhs; + } + if rhs.mantissa == 0 { + return *self; + } + let mut a = *self; + let mut b = *rhs; + + let exp_diff = a.exponent.wrapping_sub(b.exponent); + + // If exponent difference is too large, b is negligible + if exp_diff.abs() >= BITS as i16 { + return if a.sign == b.sign { + // Adding very small number to large: return a + return if a.exponent > b.exponent { a } else { b }; + } else if a.exponent > b.exponent { + a + } else { + b + }; + } + + // Align exponents + if a.exponent > b.exponent { + b.shift_right((a.exponent - b.exponent) as u32); + } else if b.exponent > a.exponent { + a.shift_right((b.exponent - a.exponent) as u32); + } + + let mut result = DyadicFloat128::zero(); + + if a.sign == b.sign { + // Addition + result.sign = a.sign; + result.exponent = a.exponent; + result.mantissa = a.mantissa; + let (sum, is_overflow) = result.mantissa.overflowing_add(b.mantissa); + result.mantissa = sum; + if is_overflow { + // Mantissa addition overflow. + result.shift_right(1); + result.mantissa |= 1u128 << 127; + } + // Result is already normalized. + return result; + } + + // Subtraction + if a.mantissa >= b.mantissa { + result.sign = a.sign; + result.exponent = a.exponent; + result.mantissa = a.mantissa.wrapping_sub(b.mantissa); + } else { + result.sign = b.sign; + result.exponent = b.exponent; + result.mantissa = b.mantissa.wrapping_sub(a.mantissa); + } + + result.normalize(); + result + } + + #[inline] + pub(crate) fn quick_mul(&self, rhs: &Self) -> Self { + let mut result = DyadicFloat128 { + sign: if self.sign != rhs.sign { + DyadicSign::Neg + } else { + DyadicSign::Pos + }, + exponent: self.exponent + rhs.exponent + BITS as i16, + mantissa: 0, + }; + + if !(self.mantissa == 0 || rhs.mantissa == 0) { + result.mantissa = mulhi_u128(self.mantissa, rhs.mantissa); + // Check the leading bit directly, should be faster than using clz in + // normalize(). + if result.mantissa >> 127 == 0 { + result.shift_left(1); + } + } else { + result.mantissa = 0; + } + result + } + + #[inline] + pub(crate) fn fast_as_f64(&self) -> f64 { + if self.mantissa == 0 { + return if self.sign == DyadicSign::Pos { + 0. + } else { + -0.0 + }; + } + + // Assume that it is normalized, and output is also normal. + const PRECISION: u32 = 52 + 1; + + // SIG_MASK - FRACTION_MASK + const SIG_MASK: u64 = (1u64 << 52) - 1; + const FRACTION_MASK: u64 = (1u64 << 52) - 1; + const IMPLICIT_MASK: u64 = SIG_MASK - FRACTION_MASK; + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut exp_hi = self.exponent as i32 + ((BITS - 1) as i32 + EXP_BIAS as i32); + + if exp_hi > 2 * EXP_BIAS as i32 { + // Results overflow. + let d_hi = f64_from_parts(self.sign, 2 * EXP_BIAS, IMPLICIT_MASK); + // volatile prevents constant propagation that would result in infinity + // always being returned no matter the current rounding mode. + let two = 2.0f64; + let r = two * d_hi; + return r; + } + + let mut denorm = false; + let mut shift = BITS - PRECISION; + if exp_hi <= 0 { + // Output is denormal. + denorm = true; + shift = (BITS - PRECISION) + (1 - exp_hi) as u32; + + exp_hi = EXP_BIAS as i32; + } + + let exp_lo = exp_hi.wrapping_sub(PRECISION as i32).wrapping_sub(1); + + let m_hi = if shift >= BITS { + 0 + } else { + self.mantissa >> shift + }; + + let d_hi = f64_from_parts( + self.sign, + exp_hi as u64, + (m_hi as u64 & SIG_MASK) | IMPLICIT_MASK, + ); + + let round_mask = if shift > BITS { + 0 + } else { + 1u128.wrapping_shl(shift.wrapping_sub(1)) + }; + let sticky_mask = round_mask.wrapping_sub(1u128); + + let round_bit = (self.mantissa & round_mask) != 0; + let sticky_bit = (self.mantissa & sticky_mask) != 0; + let round_and_sticky = round_bit as i32 * 2 + sticky_bit as i32; + + let d_lo: f64; + + if exp_lo <= 0 { + // d_lo is denormal, but the output is normal. + let scale_up_exponent = 1 - exp_lo; + let scale_up_factor = f64_from_parts( + DyadicSign::Pos, + EXP_BIAS + scale_up_exponent as u64, + IMPLICIT_MASK, + ); + let scale_down_factor = f64_from_parts( + DyadicSign::Pos, + EXP_BIAS - scale_up_exponent as u64, + IMPLICIT_MASK, + ); + + d_lo = f64_from_parts( + self.sign, + (exp_lo + scale_up_exponent) as u64, + IMPLICIT_MASK, + ); + + return f_fmla(d_lo, round_and_sticky as f64, d_hi * scale_up_factor) + * scale_down_factor; + } + + d_lo = f64_from_parts(self.sign, exp_lo as u64, IMPLICIT_MASK); + + // Still correct without FMA instructions if `d_lo` is not underflow. + let r = f_fmla(d_lo, round_and_sticky as f64, d_hi); + + if denorm { + const SIG_LEN: u64 = 52; + // Exponent before rounding is in denormal range, simply clear the + // exponent field. + let clear_exp: u64 = (exp_hi as u64) << SIG_LEN; + let mut r_bits: u64 = r.to_bits() - clear_exp; + + if r_bits & EXP_MASK == 0 { + // Output is denormal after rounding, clear the implicit bit for 80-bit + // long double. + r_bits -= IMPLICIT_MASK; + } + + return f64::from_bits(r_bits); + } + + r + } + + // Approximate reciprocal - given a nonzero `a`, make a good approximation to 1/a. + // The method is Newton-Raphson iteration, based on quick_mul. + #[inline] + pub(crate) fn reciprocal(self) -> DyadicFloat128 { + // Computes the reciprocal using Newton-Raphson iteration: + // Given an approximation x ≈ 1/a, we refine via: + // x' = x * (2 - a * x) + // This squares the error term: if ax ≈ 1 - e, then ax' ≈ 1 - e². + + let guess = 1. / self.fast_as_f64(); + let mut x = DyadicFloat128::new_from_f64(guess); + + // The constant 2, which we'll need in every iteration + let twos = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + + x = x * (twos - (self * x)); + x = x * (twos - (self * x)); + x + } + + // // Approximate reciprocal - given a nonzero `a`, make a good approximation to 1/a. + // // The method is Newton-Raphson iteration, based on quick_mul. + // // *This is very crude guess* + // #[inline] + // fn approximate_reciprocal(&self) -> DyadicFloat128 { + // // Given an approximation x to 1/a, a better one is x' = x(2-ax). + // // + // // You can derive this by using the Newton-Raphson formula with the function + // // f(x) = 1/x - a. But another way to see that it works is to say: suppose + // // that ax = 1-e for some small error e. Then ax' = ax(2-ax) = (1-e)(1+e) = + // // 1-e^2. So the error in x' is the square of the error in x, i.e. the number + // // of correct bits in x' is double the number in x. + // + // // An initial approximation to the reciprocal + // let mut x = DyadicFloat128 { + // sign: DyadicSign::Pos, + // exponent: -32 - self.exponent - BITS as i16, + // mantissa: self.mantissa >> (BITS - 32), + // }; + // x.normalize(); + // + // // The constant 2, which we'll need in every iteration + // let two = DyadicFloat128::new(DyadicSign::Pos, 1, 1); + // + // // We expect at least 31 correct bits from our 32-bit starting approximation + // let mut ok_bits = 31usize; + // + // // The number of good bits doubles in each iteration, except that rounding + // // errors introduce a little extra each time. Subtract a bit from our + // // accuracy assessment to account for that. + // while ok_bits < BITS as usize { + // x = x * (two - (*self * x)); + // ok_bits = 2 * ok_bits - 1; + // } + // + // x + // } +} + +impl Add for DyadicFloat128 { + type Output = DyadicFloat128; + #[inline] + fn add(self, rhs: DyadicFloat128) -> Self::Output { + self.quick_add(&rhs) + } +} + +impl DyadicFloat128 { + #[inline] + pub(crate) fn biased_exponent(&self) -> i16 { + self.exponent + (BITS as i16 - 1) + } + + #[inline] + pub(crate) fn trunc_to_i64(&self) -> i64 { + if self.exponent <= -(BITS as i16) { + // Absolute value of x is greater than equal to 0.5 but less than 1. + return 0; + } + let hi = self.mantissa >> 64; + let norm_exp = self.biased_exponent(); + if norm_exp > 63 { + return if self.sign == DyadicSign::Neg { + i64::MIN + } else { + i64::MAX + }; + } + let r: i64 = (hi >> (63 - norm_exp)) as i64; + + if self.sign == DyadicSign::Neg { -r } else { r } + } + + #[inline] + pub(crate) fn round_to_nearest(&self) -> DyadicFloat128 { + if self.exponent == -(BITS as i16) { + // Absolute value of x is greater than equal to 0.5 but less than 1. + return DyadicFloat128 { + sign: self.sign, + exponent: -(BITS as i16 - 1), + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + } + if self.exponent <= -((BITS + 1) as i16) { + // Absolute value of x is greater than equal to 0.5 but less than 1. + return DyadicFloat128 { + sign: self.sign, + exponent: 0, + mantissa: 0u128, + }; + } + const FRACTION_LENGTH: u32 = BITS - 1; + let trim_size = + (FRACTION_LENGTH as i64).wrapping_sub(self.exponent as i64 + (BITS - 1) as i64) as u128; + let half_bit_set = + self.mantissa & (1u128.wrapping_shl(trim_size.wrapping_sub(1) as u32)) != 0; + let trunc_u: u128 = self + .mantissa + .wrapping_shr(trim_size as u32) + .wrapping_shl(trim_size as u32); + if trunc_u == self.mantissa { + return *self; + } + + let truncated = DyadicFloat128::new(self.sign, self.exponent, trunc_u); + + if !half_bit_set { + // Franctional part is less than 0.5 so round value is the + // same as the trunc value. + truncated + } else if self.sign == DyadicSign::Neg { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -(BITS as i16 - 1), + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }; + truncated - ones + } else { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -(BITS as i16 - 1), + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }; + truncated + ones + } + } + + #[inline] + pub(crate) fn round_to_nearest_f64(&self) -> f64 { + self.round_to_nearest().fast_as_f64() + } +} + +impl Sub for DyadicFloat128 { + type Output = DyadicFloat128; + #[inline] + fn sub(self, rhs: DyadicFloat128) -> Self::Output { + self.quick_sub(&rhs) + } +} + +impl Mul for DyadicFloat128 { + type Output = DyadicFloat128; + #[inline] + fn mul(self, rhs: DyadicFloat128) -> Self::Output { + self.quick_mul(&rhs) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dyadic_float() { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let cvt = ones.fast_as_f64(); + assert_eq!(cvt, 1.0); + + let minus_0_5 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let cvt0 = minus_0_5.fast_as_f64(); + assert_eq!(cvt0, -1.0 / 2.0); + + let minus_1_f4 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }; + let cvt0 = minus_1_f4.fast_as_f64(); + assert_eq!(cvt0, -1.0 / 24.0); + + let minus_1_f8 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xd00d00d0_0d00d00d_00d00d00_d00d00d0_u128, + }; + let cvt0 = minus_1_f8.fast_as_f64(); + assert_eq!(cvt0, 1.0 / 40320.0); + } + + #[test] + fn dyadic_float_add() { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + + let cvt = ones.fast_as_f64(); + assert_eq!(cvt, 1.0); + + let minus_0_5 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let cvt0 = ones.quick_add(&minus_0_5).fast_as_f64(); + assert_eq!(cvt0, 0.5); + } + + #[test] + fn dyadic_float_mul() { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + + let cvt = ones.fast_as_f64(); + assert_eq!(cvt, 1.0); + + let minus_0_5 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let product = ones.quick_mul(&minus_0_5); + let cvt0 = product.fast_as_f64(); + assert_eq!(cvt0, -0.5); + + let twos = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + + let cvt = twos.fast_as_f64(); + assert_eq!(cvt, 2.0); + } + + #[test] + fn dyadic_round_trip() { + let z00 = 0.0; + let zvt00 = DyadicFloat128::new_from_f64(z00); + let b00 = zvt00.fast_as_f64(); + assert_eq!(b00, z00); + + let zvt000 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0, + }; + let b000 = zvt000.fast_as_f64(); + assert_eq!(b000, z00); + + let z0 = 1.0; + let zvt0 = DyadicFloat128::new_from_f64(z0); + let b0 = zvt0.fast_as_f64(); + assert_eq!(b0, z0); + + let z1 = 0.5; + let zvt1 = DyadicFloat128::new_from_f64(z1); + let b1 = zvt1.fast_as_f64(); + assert_eq!(b1, z1); + + let z2 = -0.5; + let zvt2 = DyadicFloat128::new_from_f64(z2); + let b2 = zvt2.fast_as_f64(); + assert_eq!(b2, z2); + + let z3 = -532322.54324324232; + let zvt3 = DyadicFloat128::new_from_f64(z3); + let b3 = zvt3.fast_as_f64(); + assert_eq!(b3, z3); + } + + #[test] + fn dyadic_float_reciprocal() { + let ones = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + } + .reciprocal(); + + let cvt = ones.fast_as_f64(); + assert_eq!(cvt, 1.0); + + let minus_0_5 = DyadicFloat128::new_from_f64(4.).reciprocal(); + let cvt0 = minus_0_5.fast_as_f64(); + assert_eq!(cvt0, 0.25); + } + + #[test] + fn dyadic_float_from_div() { + let from_div = DyadicFloat128::from_div_f64(1.0, 4.0); + let cvt = from_div.fast_as_f64(); + assert_eq!(cvt, 0.25); + } + + #[test] + fn dyadic_float_accurate_reciprocal() { + let from_div = DyadicFloat128::accurate_reciprocal(4.0); + let cvt = from_div.fast_as_f64(); + assert_eq!(cvt, 0.25); + } + + #[test] + fn dyadic_float_mul_int() { + let from_div = DyadicFloat128::new_from_f64(4.0); + let m1 = from_div.mul_int64(-2); + assert_eq!(m1.fast_as_f64(), -8.0); + + let from_div = DyadicFloat128::new_from_f64(-4.0); + let m1 = from_div.mul_int64(-2); + assert_eq!(m1.fast_as_f64(), 8.0); + + let from_div = DyadicFloat128::new_from_f64(2.5); + let m1 = from_div.mul_int64(2); + assert_eq!(m1.fast_as_f64(), 5.0); + } + + #[test] + fn dyadic_float_round() { + let from_div = DyadicFloat128::new_from_f64(2.5); + let m1 = from_div.round_to_nearest_f64(); + assert_eq!(m1, 3.0); + + let from_div = DyadicFloat128::new_from_f64(0.5); + let m1 = from_div.round_to_nearest_f64(); + assert_eq!(m1, 1.0); + + let from_div = DyadicFloat128::new_from_f64(-0.5); + let m1 = from_div.round_to_nearest_f64(); + assert_eq!(m1, -1.0); + + let from_div = DyadicFloat128::new_from_f64(-0.351); + let m1 = from_div.round_to_nearest_f64(); + assert_eq!(m1, (-0.351f64).round()); + + let from_div = DyadicFloat128::new_from_f64(0.351); + let m1 = from_div.round_to_nearest_f64(); + assert_eq!(m1, 0.351f64.round()); + + let z00 = 25.6; + let zvt00 = DyadicFloat128::new_from_f64(z00); + let b00 = zvt00.round_to_nearest_f64(); + assert_eq!(b00, 26.); + } + + #[test] + fn dyadic_int_trunc() { + let from_div = DyadicFloat128::new_from_f64(-2.5); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, -2); + + let from_div = DyadicFloat128::new_from_f64(2.5); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, 2); + + let from_div = DyadicFloat128::new_from_f64(0.5); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, 0); + + let from_div = DyadicFloat128::new_from_f64(-0.5); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, 0); + + let from_div = DyadicFloat128::new_from_f64(-0.351); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, 0); + + let from_div = DyadicFloat128::new_from_f64(0.351); + let m1 = from_div.trunc_to_i64(); + assert_eq!(m1, 0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,319 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::err::erf_poly::{ERF_POLY, ERF_POLY_C2}; +use crate::rounding::CpuFloor; +/* double-double approximation of 2/sqrt(pi) to nearest */ +const TWO_OVER_SQRT_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c71ae3a914fed80), + f64::from_bits(0x3ff20dd750429b6d), +); + +pub(crate) struct Erf { + pub(crate) result: DoubleDouble, + pub(crate) err: f64, +} + +/* for |z| < 1/8, assuming z >= 2^-61, thus no underflow can occur */ +#[cold] +fn cr_erf_accurate_tiny(x: f64) -> DoubleDouble { + static P: [u64; 15] = [ + 0x3ff20dd750429b6d, + 0x3c71ae3a914fed80, + 0xbfd812746b0379e7, + 0x3c6ee12e49ca96ba, + 0x3fbce2f21a042be2, + 0xbc52871bc0a0a0d0, + 0xbf9b82ce31288b51, + 0x3c21003accf1355c, + 0x3f7565bcd0e6a53f, + 0xbf4c02db40040cc3, + 0x3f1f9a326fa3cf50, + 0xbeef4d25e3c73ce9, + 0x3ebb9eb332b31646, + 0xbe864a4bd5eca4d7, + 0x3e6c0acc2502e94e, + ]; + let z2 = x * x; + let mut h = f64::from_bits(P[21 / 2 + 4]); /* degree 21 */ + for a in (12..=19).rev().step_by(2) { + h = dd_fmla(h, z2, f64::from_bits(P[(a / 2 + 4) as usize])) + } + let mut l = 0.; + for a in (8..=11).rev().step_by(2) { + let mut t = DoubleDouble::from_exact_mult(h, x); + t.lo = dd_fmla(l, x, t.lo); + let mut k = DoubleDouble::from_exact_mult(t.hi, x); + k.lo = dd_fmla(t.lo, x, k.lo); + let p = DoubleDouble::from_exact_add(f64::from_bits(P[(a / 2 + 4) as usize]), k.hi); + l = k.lo + p.lo; + h = p.hi; + } + for a in (1..=7).rev().step_by(2) { + let mut t = DoubleDouble::from_exact_mult(h, x); + t.lo = dd_fmla(l, x, t.lo); + let mut k = DoubleDouble::from_exact_mult(t.hi, x); + k.lo = dd_fmla(t.lo, x, k.lo); + let p = DoubleDouble::from_exact_add(f64::from_bits(P[a - 1]), k.hi); + l = k.lo + p.lo + f64::from_bits(P[a]); + h = p.hi; + } + /* multiply by z */ + let p = DoubleDouble::from_exact_mult(h, x); + l = dd_fmla(l, x, p.lo); + DoubleDouble::new(l, p.hi) +} + +/* Assuming 0 <= z <= 0x1.7afb48dc96626p+2, put in h+l an accurate +approximation of erf(z). +Assumes z >= 2^-61, thus no underflow can occur. */ +#[cold] +#[inline(never)] +pub(crate) fn erf_accurate(x: f64) -> DoubleDouble { + if x < 0.125 + /* z < 1/8 */ + { + return cr_erf_accurate_tiny(x); + } + + let v = (8.0 * x).cpu_floor(); + let i: u32 = (8.0 * x) as u32; + let z = (x - 0.0625) - 0.125 * v; + /* now |z| <= 1/16 */ + let p = ERF_POLY_C2[(i - 1) as usize]; + let mut h = f64::from_bits(p[26]); /* degree-18 */ + for a in (11..=17).rev() { + h = dd_fmla(h, z, f64::from_bits(p[(8 + a) as usize])); /* degree j */ + } + let mut l: f64 = 0.; + for a in (8..=10).rev() { + let mut t = DoubleDouble::from_exact_mult(h, z); + t.lo = dd_fmla(l, z, t.lo); + let p = DoubleDouble::from_exact_add(f64::from_bits(p[(8 + a) as usize]), t.hi); + h = p.hi; + l = p.lo + t.lo; + } + for a in (0..=7).rev() { + let mut t = DoubleDouble::from_exact_mult(h, z); + t.lo = dd_fmla(l, z, t.lo); + /* add p[2*j] + p[2*j+1] to th + tl: we use two_sum() instead of + fast_two_sum because for example for i=3, the coefficient of + degree 7 is tiny (0x1.060b78c935b8ep-13) with respect to that + of degree 8 (0x1.678b51a9c4b0ap-7) */ + let v = DoubleDouble::from_exact_add(f64::from_bits(p[(2 * a) as usize]), t.hi); + h = v.hi; + l = v.lo + t.lo + f64::from_bits(p[(2 * a + 1) as usize]); + } + DoubleDouble::new(l, h) +} + +/* Assuming 0 <= z <= 5.9215871957945065, put in h+l an approximation +of erf(z). Return err the maximal relative error: +|(h + l)/erf(z) - 1| < err*|h+l| */ +#[inline] +pub(crate) fn erf_fast(x: f64) -> Erf { + /* we split [0,5.9215871957945065] into intervals i/16 <= z < (i+1)/16, + and for each interval, we use a minimax polynomial: + * for i=0 (0 <= z < 1/16) we use a polynomial evaluated at zero, + since if we evaluate in the middle 1/32, we will get bad accuracy + for tiny z, and moreover z-1/32 might not be exact + * for 1 <= i <= 94, we use a polynomial evaluated in the middle of + the interval, namely i/16+1/32 + */ + if x < 0.0625 + /* z < 1/16 */ + { + /* the following is a degree-11 minimax polynomial for erf(x) on [0,1/16] + generated by Sollya, with double-double coefficients for degree 1 and 3, + and double coefficients for degrees 5 to 11 (file erf0.sollya). + The maximal relative error is 2^-68.935. */ + let z2 = DoubleDouble::from_exact_mult(x, x); + const C: [u64; 8] = [ + 0x3ff20dd750429b6d, + 0x3c71ae3a7862d9c4, + 0xbfd812746b0379e7, + 0x3c6f1a64d72722a2, + 0x3fbce2f21a042b7f, + 0xbf9b82ce31189904, + 0x3f7565bbf8a0fe0b, + 0xbf4bf9f8d2c202e4, + ]; + let z4 = z2.hi * z2.hi; + let c9 = dd_fmla(f64::from_bits(C[7]), z2.hi, f64::from_bits(C[6])); + let mut c5 = dd_fmla(f64::from_bits(C[5]), z2.hi, f64::from_bits(C[4])); + c5 = dd_fmla(c9, z4, c5); + /* compute c0[2] + c0[3] + z2h*c5 */ + let mut t = DoubleDouble::from_exact_mult(z2.hi, c5); + let mut v = DoubleDouble::from_exact_add(f64::from_bits(C[2]), t.hi); + v.lo += t.lo + f64::from_bits(C[3]); + /* compute c0[0] + c0[1] + (z2h + z2l)*(h + l) */ + t = DoubleDouble::from_exact_mult(z2.hi, v.hi); + let h_c = v.hi; + t.lo += dd_fmla(z2.hi, v.lo, f64::from_bits(C[1])); + v = DoubleDouble::from_exact_add(f64::from_bits(C[0]), t.hi); + v.lo += dd_fmla(z2.lo, h_c, t.lo); + v = DoubleDouble::quick_mult_f64(v, x); + return Erf { + result: v, + err: f64::from_bits(0x3ba7800000000000), + }; /* err < 2.48658249618372e-21, cf Analyze0() */ + } + + let v = (16.0 * x).cpu_floor(); + let i: u32 = (16.0 * x) as u32; + /* i/16 <= z < (i+1)/16 */ + /* For 0.0625 0 <= z <= 0x1.7afb48dc96626p+2, z - 0.03125 is exact: + (1) either z - 0.03125 is in the same binade as z, then 0.03125 is + an integer multiple of ulp(z), so is z - 0.03125 + (2) if z - 0.03125 is in a smaller binade, both z and 0.03125 are + integer multiple of the ulp() of that smaller binade. + Also, subtracting 0.0625 * v is exact. */ + let z = (x - 0.03125) - 0.0625 * v; + /* now |z| <= 1/32 */ + let c = ERF_POLY[(i - 1) as usize]; + let z2 = z * z; + let z4 = z2 * z2; + /* the degree-10 coefficient is c[12] */ + let c9 = dd_fmla(f64::from_bits(c[12]), z, f64::from_bits(c[11])); + let mut c7 = dd_fmla(f64::from_bits(c[10]), z, f64::from_bits(c[9])); + let c5 = dd_fmla(f64::from_bits(c[8]), z, f64::from_bits(c[7])); + /* c3h, c3l <- c[5] + z*c[6] */ + let mut c3 = DoubleDouble::from_exact_add(f64::from_bits(c[5]), z * f64::from_bits(c[6])); + c7 = dd_fmla(c9, z2, c7); + /* c3h, c3l <- c3h, c3l + c5*z2 */ + let p = DoubleDouble::from_exact_add(c3.hi, c5 * z2); + c3.hi = p.hi; + c3.lo += p.lo; + /* c3h, c3l <- c3h, c3l + c7*z4 */ + let p = DoubleDouble::from_exact_add(c3.hi, c7 * z4); + c3.hi = p.hi; + c3.lo += p.lo; + /* c2h, c2l <- c[4] + z*(c3h + c3l) */ + let mut t = DoubleDouble::from_exact_mult(z, c3.hi); + let mut c2 = DoubleDouble::from_exact_add(f64::from_bits(c[4]), t.hi); + c2.lo += dd_fmla(z, c3.lo, t.lo); + /* compute c[2] + c[3] + z*(c2h + c2l) */ + t = DoubleDouble::from_exact_mult(z, c2.hi); + let mut v = DoubleDouble::from_exact_add(f64::from_bits(c[2]), t.hi); + v.lo += t.lo + dd_fmla(z, c2.lo, f64::from_bits(c[3])); + /* compute c[0] + c[1] + z*(h + l) */ + t = DoubleDouble::from_exact_mult(z, v.hi); + t.lo = dd_fmla(z, v.lo, t.lo); + v = DoubleDouble::from_exact_add(f64::from_bits(c[0]), t.hi); + v.lo += t.lo + f64::from_bits(c[1]); + Erf { + result: v, + err: f64::from_bits(0x3ba1100000000000), + } /* err < 1.80414390200020e-21, cf analyze_p(1) + (larger values of i yield smaller error bounds) */ +} + +/// Error function +/// +/// Max ULP 0.5 +pub fn f_erf(x: f64) -> f64 { + let z = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + let mut t = z.to_bits(); + let ux = t; + /* erf(x) rounds to +/-1 for RNDN for |x| > 0x4017afb48dc96626 */ + if ux > 0x4017afb48dc96626 + // |x| > 0x4017afb48dc96626 + { + let os = f64::copysign(1.0, x); + const MASK: u64 = 0x7ff0000000000000u64; + if ux > MASK { + return x + x; /* NaN */ + } + if ux == MASK { + return os; /* +/-Inf */ + } + return f_fmla(-f64::from_bits(0x3c90000000000000), os, os); + } + + /* now |x| <= 0x4017afb48dc96626 */ + if z < f64::from_bits(0x3c20000000000000) { + /* for x=-0 the code below returns +0 which is wrong */ + if x == 0. { + return x; + } + /* tiny x: erf(x) ~ 2/sqrt(pi) * x + O(x^3), where the ratio of the O(x^3) + term to the main term is in x^2/3, thus less than 2^-123 */ + let y = TWO_OVER_SQRT_PI.hi * x; /* tentative result */ + /* scale x by 2^106 to get out the subnormal range */ + let sx = x * f64::from_bits(0x4690000000000000); + let mut p = DoubleDouble::quick_mult_f64(TWO_OVER_SQRT_PI, sx); + /* now compute the residual h + l - y */ + p.lo += f_fmla(-y, f64::from_bits(0x4690000000000000), p.hi); /* h-y*2^106 is exact since h and y are very close */ + let res = dyad_fmla(p.lo, f64::from_bits(0x3950000000000000), y); + return res; + } + + let result = erf_fast(z); + let mut u = result.result.hi.to_bits(); + let mut v = result.result.lo.to_bits(); + t = x.to_bits(); + + const SIGN_MASK: u64 = 0x8000000000000000u64; + u ^= t & SIGN_MASK; + v ^= t & SIGN_MASK; + + let left = f64::from_bits(u) + f_fmla(result.err, -f64::from_bits(u), f64::from_bits(v)); + let right = f64::from_bits(u) + f_fmla(result.err, f64::from_bits(u), f64::from_bits(v)); + + if left == right { + return left; + } + + let a_results = erf_accurate(z); + + if x >= 0. { + a_results.to_f64() + } else { + (-a_results.hi) + (-a_results.lo) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_erf() { + assert_eq!(f_erf(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009456563898732), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010670589695636709); + assert_eq!(f_erf(0.), 0.); + assert_eq!(f_erf(1.), 0.8427007929497149); + assert_eq!(f_erf(0.49866735123), 0.5193279892991808); + assert_eq!(f_erf(-0.49866735123), -0.5193279892991808); + assert!(f_erf(f64::NAN).is_nan()); + assert_eq!(f_erf(f64::INFINITY), 1.0); + assert_eq!(f_erf(f64::NEG_INFINITY), -1.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erf_poly.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf_poly.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erf_poly.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erf_poly.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,177 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[rustfmt::skip] +pub(crate) static ERF_POLY: [[u64; 13]; 94] = [ + [ 0x3fbb0081148a873a, 0xbc2f0295f16ba5d8, 0x3ff1e565bca400d4, 0xbc962d0ac26c78d3, 0xbfbad8189af6013d, 0xbfd7712743c42914, 0x3faaafd4760d7634, 0x3fbba14988b4127e, 0xbf91afcdb244078a, 0xbf99d72ee25cf211, 0x3f719502f7beca8f, 0x3f73b955bfd46624, 0xbf4a4e2d4d32228b ], + [ 0x3fc662a0bdf7a89f, 0xbc4ef7bc5856c2d4, 0x3ff19e5e92b964ab, 0x3c6cca4dec08a640, 0xbfc605f63767bdd6, 0xbfd6582e9b69c9a9, 0x3fb5aa32b580ec64, 0x3fb97594c2593d3e, 0xbf9c69c62749fb7f, 0xbf96fa7f611aacdc, 0x3f7bf1e628a4606e, 0x3f70e50e4329e8a9, 0xbf568ca9c1954b4c ], + [ 0x3fcf190aa85540e2, 0xbc6e522ac9f718e6, 0x3ff135e3075d076b, 0xbc6e2d8ed30e4a48, 0xbfce1e4d4ce2ccfb, 0xbfd4c04e66e0d59b, 0x3fbd2855d59988e8, 0x3fb659a35f29781a, 0xbfa2cf6266a634c8, 0xbf92ef4180b1f3fa, 0x3f823199a6da60e3, 0x3f69e80d13a3368c, 0xbf5ba4e4eff641dd ], + [ 0x3fd3c9aa8b84beda, 0x3c538ec27d3e5820, 0x3ff0ae54fa490723, 0xbc9d016b7bc67433, 0xbfd2c41f99922807, 0xbfd2b900b640a201, 0x3fc1c6c7eef8fa14, 0x3fb277ad7822021e, 0xbfa66c9b2023b9df, 0xbf8bf7e7b4e8559e, 0x3f853005de4b5751, 0x3f60737c6ba405f0, 0xbf606ccc916b15dc ], + [ 0x3fd7e15944d9d3e4, 0xbc695f819cf77862, 0x3ff00abcf3e187a9, 0x3c85860d868dc542, 0xbfd60ec3cf561a89, 0xbfd05599bafe4ecc, 0x3fc451ef6280e70f, 0x3fac06c6e434be6f, 0xbfa8e2d73679096f, 0xbf80ea4a60550d9c, 0x3f86c911882cc99c, 0x3f48c65a9990353b, 0xbf61e8a88301a7b5 ], + [ 0x3fdbccfec24855b8, 0xbc7472ab1c2b898c, 0x3fee9d5a8e4c934e, 0xbc79a002a2814a72, 0xbfd8dfd9939e37af, 0xbfcb588d8dc5bb96, 0x3fc62338788aee97, 0x3fa26cf85bc6dff9, 0xbfaa1bcaa91da902, 0xbf65b4a7d42d0f64, 0x3f86edef7de2b68d, 0xbf4037b458e2da8c, 0xbf5e8d6001a54334 ], + [ 0x3fdf86faa9428f9d, 0x3c79996c0c376e32, 0x3fecfc41e36c7df9, 0xbc79be994724ea34, 0xbfdb2c7dc535b619, 0xbfc5a9de93f9c0d5, 0x3fc7317958d24aae, 0x3f9133e02ab7d777, 0xbfaa155bbde32db8, 0x3f672049c0cc8525, 0x3f85adde5c722d85, 0xbf5b0a7ec5dc80fc, 0xbf5aa9393b806535 ], + [ 0x3fe1855a5fd3dd50, 0x3c88f6964e67d61a, 0x3feb3aafcc27502e, 0xbc7a9dd26edea8a2, 0xbfdcee5ac8e9c531, 0xbfbfa02983c853d1, 0x3fc77cd75ec73100, 0xbf5fa6f82f9333b7, 0xbfa8e0db5528e559, 0x3f800bf7062212bc, 0x3f83319e670adc9f, 0xbf658833e091aa36, 0xbf58f99b6e81e8f5 ], + [ 0x3fe32a54cb8db67b, 0xbc696221f7e18978, 0x3fe96164fafd8de3, 0x3c70887f82841acc, 0xbfde23a7ea0d187e, 0xbfb3f5ee1564be49, 0x3fc70e469de06907, 0xbf93da6878ae6fd8, 0xbfa6a0d076468415, 0x3f88cf081f1fc304, 0x3f7f6d62866525e6, 0xbf6b93149d5701a4, 0xbf51a6c1a9f7ea73 ], + [ 0x3fe4b13713ad3513, 0x3c6e944ee1b212e4, 0x3fe7791b886e7403, 0xbc6da43cb53d911c, 0xbfdecef42310f844, 0xbfa15c3c5ce705df, 0x3fc5f6890affa468, 0xbfa1da642fabd4da, 0xbfa385991202c7eb, 0x3f8fa4f37fc7c6d4, 0x3f77156b4e430998, 0xbf6f546a4377d648, 0xbf432e4e5abb1e1a ], + [ 0x3fe61955607dd15d, 0x3c898ff39319ab83, 0x3fe58a445da7c74c, 0x3c808ec8e156809b, 0xbfdef6c246a12e7e, 0x3f7e83e0da030480, 0x3fc44cc65df8bfc7, 0xbfa87d3c8dd62c82, 0xbf9f9271a8a1d4e2, 0x3f9225234c1c0a0e, 0x3f6c0b0e055a0c48, 0xbf70585251f84919, 0xbf285bfb02436e0f ], + [ 0x3fe762870f720c6f, 0x3c8118b1ba6da9a7, 0x3fe39ccc1b136d5a, 0x3c5faa9371c0dd80, 0xbfdea4feea4e5add, 0x3fa715e595343353, 0x3fc22cdbdb4cdd0c, 0xbfada50ae547e69e, 0xbf975578f87f217d, 0x3f9353319c65f251, 0x3f539db53a2d03d5, 0xbf6fc0364ce17870, 0x3f3272bc18b0f2ce ], + [ 0x3fe88d1cd474a2e0, 0x3c86f571ada77d52, 0x3fe1b7e98fe26217, 0x3c7952bd607eb12e, 0xbfdde65a22ce0587, 0x3fb40686a3f3dc2b, 0x3fbf6b0cb6926c42, 0xbfb09c7caecd317d, 0xbf8da668f759eaea, 0x3f9364e72035e80a, 0xbf4d421975736447, 0xbf6cc98454e96141, 0x3f4a8860fdf17259 ], + [ 0x3fe999d4192a5715, 0xbc8c888a5759a92c, 0x3fdfc3ee5d1524b0, 0xbc527e60faac0278, 0xbfdcc990045b293f, 0x3fbb37338e6ac814, 0x3fba0d11fe9ba61a, 0xbfb19bb2ca3816ba, 0xbf7a0b7d94791f03, 0x3f9274a59774d5e6, 0xbf664adea7b36f57, 0xbf683684bd8ef173, 0x3f538905afd229ff ], + [ 0x3fea89c850b7d54d, 0xbc8e2752ebf0cd02, 0x3fdc40b0729ed548, 0xbc7c4c1c4927306d, 0xbfdb5eaaef09de9d, 0x3fc0847c7dad86af, 0x3fb47de0a4f796ca, 0xbfb1d9de8b54a3ec, 0x3f533252fb810c7c, 0x3f90ab3e329ded2f, 0xbf712d82076274ed, 0xbf6287bb4a78d728, 0x3f557d31bd574da0 ], + [ 0x3feb5e62fce16095, 0x3c7bc3cff4400364, 0x3fd8eed36b886d93, 0x3c7ea7e17b96436d, 0xbfd9b64a06e4b100, 0x3fc2bb6e2c74d4fe, 0x3fadee322c062364, 0xbfb169960d5a983d, 0x3f7feab4ad0bfc14, 0x3f8c76eb94b07a5f, 0xbf7584474ae8f994, 0xbf588df75be9251f, 0x3f54edef50317090 ], + [ 0x3fec194b1d49a184, 0xbc66770a58b27668, 0x3fd5d4fd33729015, 0xbc76db7d76e9e97b, 0xbfd7e0f4f0454d97, 0x3fc444bc66c35bc4, 0x3fa356dbb5432550, 0xbfb0643de6e8c574, 0x3f8b2e1f789415e4, 0x3f86ba6d9f4af32f, 0xbf78138bf4573a6a, 0xbf47e6e52a583322, 0x3f50f87322fa18a3 ], + [ 0x3fecbc54b476248d, 0x3c81a5083b01ec0d, 0x3fd2f7cc3fe6f423, 0x3c79fbb4b774e85d, 0xbfd5ee8429e30a49, 0x3fc52a8395f96270, 0x3f9313759f199499, 0xbfadcf844d90282c, 0x3f91e45f25ab54a1, 0x3f8091cb68a58665, 0xbf78ea40b0ac8b7b, 0xbee6b91b1bf985f2, 0x3f5158d9c0e1c327 ], + [ 0x3fed4970f9ce00d9, 0xbc756704209fca70, 0x3fd059f59af7a906, 0xbc70ce27da57f153, 0xbfd3eda354ddd5ff, 0x3fc57b85ad436067, 0x3f58e90c2a157e8d, 0xbfaa2893b28f4033, 0x3f94d6af4484a1cb, 0x3f74ccee8c8b1f57, 0xbf783304b9e2e312, 0x3f440cb679d0a832, 0x3f4d6b5f4bdef24b ], + [ 0x3fedc29fb60715af, 0x3c8ab029f047a087, 0x3fcbf8e1b1ca2279, 0x3be0426e10a38000, 0xbfd1eb7095e57e16, 0x3fc549ea6f7a013f, 0xbf8b10f20d110552, 0xbfa61420b5b34a55, 0x3f9677b7ea46c6f2, 0x3f624f9940ffd840, 0xbf76304445e5f6ca, 0x3f5222fabfa75bb0, 0x3f3fdcf55be3c03e ], + [ 0x3fee29e22a89d766, 0x3c8bcc9d569ed217, 0x3fc7bd5c7df3fe9c, 0x3c6488f3b06e1394, 0xbfcfe674493fde22, 0x3fc4a9feacf7e222, 0xbf9a0082c90a1b0d, 0xbfa1cf0e7655f99a, 0x3f96e3396f042620, 0xbf33a2d2cdd5650d, 0xbf7334add14b9a31, 0x3f57e12864580191, 0x3f3dae75c3e2be46 ], + [ 0x3fee812fc64db369, 0x3c83c66a6a23d9a5, 0x3fc3fda6bc016994, 0x3c6586ddaff31a18, 0xbfcc1cb27861fc79, 0x3fc3b1051230b982, 0xbfa1e645a2a638ff, 0xbf9b1f643b14fd89, 0x3f964297d7a66c20, 0xbf63e365adfbccae, 0xbf6f2aa2b3ef5ec2, 0x3f5b3339ee2c8c49, 0x3f20ef5710223110 ], + [ 0x3feeca6ccd709544, 0x3c6f3de8f1953470, 0x3fc0b3f52ce8c383, 0x3c6d1234b508bcfb, 0xbfc8885019f5df29, 0x3fc274275fc87eae, 0xbfa57f7386bfd263, 0xbf930769f45aaa8b, 0x3f94c8231709cfee, 0xbf70c2c99c75913f, 0xbf67514483efc090, 0x3f5c3ebcf121a533, 0x3eede2f1801b8480 ], + [ 0x3fef0762fde45ee6, 0x3c89c3612a14fb77, 0x3fbbb1c972f23e50, 0x3c5ba69c564971e1, 0xbfc5341e3c0177b6, 0x3fc107929f6e7528, 0xbfa7e1b362eacfe6, 0xbf873b61e487b8a9, 0x3f92aa763e0343a9, 0xbf759a388fd2272d, 0xbf5eea3c7f50e8de, 0x3f5b5026fd87d0ca, 0xbf30f2c660125dc6 ], + [ 0x3fef39bc242e43e6, 0xbc8dbae0fd9b967d, 0x3fb6c7e64e7281cb, 0x3c5aa87392dc4c20, 0xbfc2274b86833f6e, 0x3fbefb890e5b6633, 0xbfa92c7dbb880b5c, 0xbf74547708842f2b, 0x3f902047ab6c08c4, 0xbf7888355239e9ec, 0xbf50313bb85e86e1, 0x3f58ced9ddf3d834, 0xbf32d520499bd799 ], + [ 0x3fef62fe80272419, 0xbc8b7c2d17fc31d3, 0x3fb297db960e4f63, 0xbc522bea9385fad9, 0xbfbecb83b087b37b, 0x3fbbce18363bbbb9, 0xbfa985aaf97891cb, 0x3f3cd95f2aa8601a, 0x3f8ab9d43270d20f, 0xbf79b93410d46789, 0xbf29b530b472cadf, 0x3f552f54de527458, 0xbf36844d43c7d693 ], + [ 0x3fef848acb544e95, 0xbc8b27aa2c376c3c, 0x3fae1d4cf1e2450a, 0xbc4783e14555c1e9, 0xbfb9e12e1fde7354, 0x3fb8a27806de834f, 0xbfa91674e13a339a, 0x3f73bc75e8f9d448, 0x3f851b4d09ac47b8, 0xbf796dc7b5f9bd66, 0x3f3e16520532bde9, 0x3f50e742b323f434, 0xbf3ac319bfed91d4 ], + [ 0x3fef9f9ba8d3c733, 0x3c8cd5790ff03ab3, 0x3fa83298d717210e, 0x3c4740e2b04276bf, 0xbfb58d101f909971, 0x3fb58f1456f7db5e, 0xbfa808d17b33b814, 0x3f80c1bdce673b10, 0x3f7f5ff1c06e9df2, 0xbf77f26b8865f398, 0x3f4f87060e6f6460, 0x3f48c6056bea9223, 0xbf3e3499a90b84f5 ], + [ 0x3fefb54641aebbc9, 0xbc879975513f67e7, 0x3fa34ac36ad8dafe, 0x3c0902fb5363d360, 0xbfb1c8ec267fe9e2, 0x3fb2a52c5d83c050, 0xbfa68541b2c0582c, 0x3f85afe422155ad5, 0x3f756303c111cd8a, 0xbf7597ead749c06a, 0x3f557b0870a7b4cf, 0x3f3ffc0efb0ac024, 0xbf39e3ea349ab39e ], + [ 0x3fefc67bcf2d7b8f, 0xbc80d2748f976e8c, 0x3f9e85c449e377f3, 0xbc3cb7ccd2616394, 0xbfad177f166cce53, 0x3fafe23b75845cdf, 0xbfa4b120f9dde895, 0x3f88d9906d138bd5, 0x3f69201b7e469e83, 0xbf72aceacb2954f0, 0x3f58d4e8140dc518, 0x3f300a33f7e93047, 0xbf372b7adfeee575 ], + [ 0x3fefd40bd6d7a785, 0x3c860d45e630998f, 0x3f97f5188610ddc8, 0xbc360e8565137ecb, 0xbfa7954423f89a51, 0x3faaf5baae337ae6, 0xbfa2ad77b77d17dc, 0x3f8a7b8c4a8d53fe, 0x3f54593adc5d737a, 0xbf6ef1cf14455c9c, 0x3f5a1a04ce289b4b, 0x3f03d14f37840954, 0xbf350b861df174ee ], + [ 0x3fefdea6e062d0c9, 0xbc764c70f379f670, 0x3f92a875b5ffab56, 0x3c0531231987c3b8, 0xbfa2f3178cd7aa03, 0x3fa68d1c45b96efe, 0xbfa09648dd332653, 0x3f8ad8b148089c02, 0xbf2f00fa01e6ca19, 0xbf68718785b34600, 0x3f59a7b0da775387, 0xbf2090258ede6532, 0xbf2b3980b454d442 ], + [ 0x3fefe6e1742f7cf6, 0xbc8cebced8a49e04, 0x3f8cd5ec93c12432, 0xbc2bb85326a5eff3, 0xbf9e2ff3aaae31e4, 0x3fa2aa4e58242520, 0xbf9d049824fc44db, 0x3f8a34eda0fc336e, 0xbf5682d8d1801582, 0xbf6239bf51e17ea8, 0x3f57e761274bf059, 0xbf301e715d70d49f, 0xbf24d89f3d9c30d5 ], + [ 0x3fefed37386190fb, 0x3c872b1549ea44ee, 0x3f861beae53b72b7, 0x3bf401790f84b248, 0xbf97d6193f2417ad, 0x3f9e947279e4a43b, 0xbf99060301092cdc, 0x3f88d14d4bdaa7f4, 0xbf61f795ac880380, 0xbf59222edb6bd145, 0x3f553f95c7b01615, 0xbf3529b07d094e1d, 0xbf15b533d0382e20 ], + [ 0x3feff20e0a7ba8c2, 0xbc603f86c5a13f78, 0x3f80d1d69569b82d, 0xbc1a5e866bd1366e, 0xbf92a8ca0dc14852, 0x3f98cc071b719c43, 0xbf954a148886e917, 0x3f86e91361df3c9e, 0xbf665c02e0d08291, 0xbf4e94b0adc3b1ca, 0x3f5210781b57b089, 0xbf37b88f8c82fbff, 0xbf068df27e9a1688 ], + [ 0x3feff5b8fb26f5f6, 0xbc87e917ec20b615, 0x3f79646f35a76624, 0xbc1f771f32fd191b, 0xbf8cf68ed932f081, 0x3f93e8735b5b73b1, 0xbf91e1611aabcbea, 0x3f84afd8cd100d70, 0xbf68c72005b1cfcf, 0xbf3c6a7216b336aa, 0x3f4d577412afc2e2, 0xbf3836a0c0e10a99, 0x3eca8f39f410252a ], + [ 0x3feff87b1913e853, 0xbc73ca98afc58454, 0x3f730499b503957f, 0xbbfd1eabb1c04f50, 0xbf86496420203331, 0x3f8fa73d7eb1b70d, 0xbf8daa3005c2d3fe, 0x3f8250942c31c3ad, 0xbf6997578dc240a8, 0xbf03904177639e63, 0x3f46a6ed488a1f54, 0xbf371cf0c5789c7d, 0x3f043cb84231ab1c ], + [ 0x3feffa89fe5b3625, 0x3c8934b2bcb7f9a3, 0x3f6c4412bf4b8f0b, 0xbbcbbcc9dca4ec60, 0xbf8100f34713740d, 0x3f88ebda0768e8e6, 0xbf8850c68e8e5c3c, 0x3f7fdac8346071b3, 0xbf6929de70d00321, 0x3f310c7101bc52d8, 0x3f4070f7e89ec1e2, 0xbf34e4b3dcf4f08d, 0x3f0f0d43b9869b19 ], + [ 0x3feffc10194fcb64, 0x3c8ea14750ac9b59, 0x3f64d78bba8ca5fd, 0x3be4d9a93566b5b4, 0xbf79ba107a459ce4, 0x3f836f273fbd909b, 0xbf83b38708f7bef7, 0x3f7b3fdff1de2112, 0xbf67d55d55d262d8, 0x3f3eae5e05e74fcc, 0x3f35ebc1e53214a9, 0xbf31fd7c1cd5d63e, 0x3f149559a04c8568 ], + [ 0x3feffd2eae369a07, 0xbc683b09df7f7db4, 0x3f5e7f232d9e2630, 0x3bfa26ac725599e5, 0xbf734c7442de142b, 0x3f7e066bed09942f, 0xbf7f914f2c60b9bb, 0x3f76f4662f6be13b, 0xbf65e664591d6604, 0x3f43a1598d880f36, 0x3f2965b2e78a4544, 0xbf2d8db42b193729, 0x3f1449172919598e ], + [ 0x3feffdff92db56e5, 0xbc78aeef4ee0690a, 0x3f56235fbd7a4345, 0xbbe11380fe434056, 0xbf6cb5e029ba8f3d, 0x3f76fa4c7ef470e9, 0xbf7903a08305eeb0, 0x3f730f12c83fdb23, 0xbf639d769a774af1, 0x3f45d79439ceaefd, 0x3f15326883e7dfeb, 0xbf27199782285958, 0x3f147181c8911603 ], + [ 0x3feffe96a78a04a9, 0xbc82816fe4528f9b, 0x3f4fe41cd9bb4eee, 0x3bde3be508cae7ec, 0xbf652d7b2896626a, 0x3f716c192d8803dc, 0xbf739bfce9b4ecc2, 0x3f6f376a554e5dec, 0xbf612e67cb7aa486, 0x3f466d6e460b1614, 0xbed54f70e4bde32b, 0xbf210e125571fe1e, 0x3f12842d46eb9f29 ], + [ 0x3fefff0312b010b5, 0x3c8155dec9cdc96b, 0x3f46caa0d3582fe9, 0xbbc97d95851163fc, 0xbf5efb729f4be121, 0x3f6a2da7cec01564, 0xbf6e6c27ad2b1ce0, 0x3f693b1f34b17723, 0xbf5d8179cd2ad34f, 0x3f45cf51e0add9bb, 0xbf116d8f4b5119c7, 0xbf1768557564f5f5, 0x3f0f4fc9dde73f24 ], + [ 0x3fefff50456dab8c, 0xbc5a197a986f0de0, 0x3f40295ef6591848, 0xbbd262bd83520706, 0xbf5679880e93e5c4, 0x3f637d38e3a705af, 0xbf675b371a264745, 0x3f64231c3bfe3e65, 0xbf58e184d4921105, 0x3f445d5b5a7f77fa, 0xbf1bf8ece4afedd2, 0xbf0ccd677aaa82f7, 0x3f09e5241d5b6b15 ], + [ 0x3fefff86cfd3e657, 0xbc72e06adb26f84e, 0x3f36be02102b3520, 0x3bb448bcfd3cfe0c, 0xbf502b15777eb7c5, 0x3f5cc1d886874d5b, 0xbf61bff70664651d, 0x3f5fc0f76c943696, 0xbf54a22286622d3e, 0x3f4268887688a6e6, 0xbf20fa2692fd7da2, 0xbefcc13d1a82f742, 0x3f04153e6537aae5 ], + [ 0x3fefffad0b901755, 0x3c670d5c9a92b65c, 0x3f2fc0d55470cf51, 0xbbc6f2b03553d4c8, 0xbf47121aff59f6a1, 0x3f5506d6992fc8ff, 0xbf5ab596015fc183, 0x3f58bdd79a098723, 0xbf50d88da9deb868, 0x3f4031cdd07e4507, 0xbf222fc41430a37d, 0xbedb5cc9546afcec, 0x3efd7ea1c7b8fdb6 ], + [ 0x3fefffc7a37857d2, 0xbc797b30fd4b6b48, 0x3f25feada379d8b7, 0xbbc0546c4da57036, 0xbf405304df546ed8, 0x3f4e79c081b79ebc, 0xbf53e5dc1062db15, 0x3f530eb20ccc1f98, 0xbf4b1b06c20a060d, 0x3f3bd52fbd55e0ef, 0xbf2214afb8835b23, 0x3ee19ae9d16650a0, 0x3ef42d933ee154fd ], + [ 0x3fefffd9fdeabcce, 0x3c80c43c3bc59762, 0x3f1e3bcf436a1a95, 0xbba6458a28a3f9b6, 0xbf36e95311166825, 0x3f45e3edf674e2db, 0xbf4d5be6d15abe3a, 0x3f4d07da13e640c2, 0xbf458106cc648748, 0x3f376c840985e5eb, 0xbf2111de112b1a2e, 0x3ef315fc34053fbd, 0x3ee939439a75a553 ], + [ 0x3fefffe68f4fa777, 0x3c32f21786b76440, 0x3f149e17724f4d41, 0x3ba747684f0023e4, 0xbf2fe48c44d2ab81, 0x3f3f2bd95d72a532, 0xbf457389188a71a9, 0x3f45decc4058f7a1, 0xbf40d559cf0f2957, 0x3f33583904af6f83, 0xbf1efd7979333337, 0x3ef904cf9fa5c1f6, 0x3eda13a094bd56a2 ], + [ 0x3fefffef1960d85d, 0xbc8f7cc78053f6ad, 0x3f0be6abbb10a5aa, 0xbb9e50b219d40126, 0xbf260403819b22b8, 0x3f35fff1dde5305e, 0xbf3f0c93c73e7f42, 0x3f404cbf67af6c26, 0xbf3a04893510426c, 0x3f2f66b51a7bc4a0, 0xbf1b410d7f2fd319, 0x3efb99f9eb427956, 0x3ebf26fcffb14441 ], + [ 0x3feffff4db27f146, 0x3c8ddecdd5e1d408, 0x3f02bb5cc22e5db6, 0x3b9c5112eca8acde, 0xbf1e258948829ed1, 0x3f2ec8a8e59d9d5b, 0xbf36425722b9f3cd, 0x3f380a83a7103b4b, 0xbf33dbb9374004f9, 0x3f2913b301d37bde, 0xbf17563b0d94459f, 0x3efbc01eea9a10be, 0xbeb3df26463df6a5 ], + [ 0x3feffff8b500e77c, 0xbc71014e1f83ed4c, 0x3ef8f4ccca7fc90d, 0x3b9a5d4ec8b9de43, 0xbf1478cffe1cd2ed, 0x3f2559f04ad4de62, 0xbf2f9e163b15c466, 0x3f318bda8b8c1315, 0xbf2df381bd3c058e, 0x3f23b94f531bb6be, 0xbf1385f32481ed94, 0x3efa414bd2b7cb3c, 0xbecac2bbe30f8767 ], + [ 0x3feffffb43555b5f, 0x3c8c17f83b8d73a2, 0x3ef07ebd2a2d2844, 0x3b9d1bbdc704f49b, 0xbf0b93e442837f52, 0x3f1d5cf1514977f3, 0xbf263f5eb46877fd, 0x3f295a0411e668b1, 0xbf2652e5f2a88269, 0x3f1e950ddb7f5444, 0xbf0ffeb9383bdb3d, 0x3ef7c24392346fdd, 0xbed1f3b3254d7230 ], + [ 0x3feffffcf23ff5fc, 0xbc8b18a8b25039c4, 0x3ee5a2adfa0b4bc4, 0x3b8eb6d61aaaf95c, 0xbf026c8826ed9e85, 0x3f140473571d5383, 0xbf1f057dbf365c0a, 0x3f22217929fed933, 0xbf207324014ddb42, 0x3f1762758a56d654, 0xbf09ba250c662e90, 0x3ef4c25759179e3d, 0xbed3e800358f1a7b ], + [ 0x3feffffe0bd3e852, 0xbc5d7ece4ab53150, 0x3edc282cd3957eda, 0x3b6eb3cf4fd14280, 0xbef86ad6df7ba401, 0x3f0b0f313eeb65a6, 0xbf156e457745d637, 0x3f19ad1f65a78253, 0xbf17f92ad8542929, 0x3f11a5578c0d30b3, 0xbf04548d876bb0a3, 0x3ef19e60bf53b25a, 0xbed3f1745170e2d3 ], + [ 0x3feffffec2641a9e, 0xbc8e7ba4fdaaa8c8, 0x3ed22df298214423, 0xbb5a9d49552152a4, 0xbef00c902a4d5e27, 0x3f022234eb745941, 0xbf0d57a2be01db67, 0x3f1200c2ffad65f1, 0xbf1147585d43f49a, 0x3f0a4b07aec797e9, 0xbeff9d088bbeff64, 0x3eed2b2be4e42422, 0xbed2bb57c0cf2941 ], + [ 0x3fefffff37d63a36, 0xbc6753e3241c01b0, 0x3ec74adc8f4064d3, 0x3b6de8a904d5c372, 0xbee4ed4228b3da96, 0x3ef81918baca1979, 0xbf03e81c09c29601, 0x3f09004afed1bde9, 0xbf08a40e183ee3fc, 0x3f0359242a8b8c58, 0xbef834b953bcb845, 0x3ee79e345fb0b20d, 0xbed0bb2d323900ce ], + [ 0x3fefffff82cdcf1b, 0x3c8046bbe9897fd5, 0x3ebd9c73698fb1dc, 0x3b588de36481dfb5, 0xbedb11017e7d5893, 0x3eefc0dfadc2c6d6, 0xbefac4e1aa499ac6, 0x3f0131810ab2e2e3, 0xbf01629d94abc864, 0x3efc22a71036c259, 0xbef244452f74de31, 0x3ee2bf17664310c1, 0xbeccd1b31a8349be ], + [ 0x3fefffffb248c39d, 0x3c89b9a41713558c, 0x3eb2acee2f5ecdb8, 0xbb32d1692a9a105c, 0xbed15cc5700a2341, 0x3ee4be757b934819, 0xbef1d6ab6f8cbf7c, 0x3ef76c5a3035bdab, 0xbef847332578dfac, 0x3ef437f23f8d25ff, 0xbeeb305e625a092d, 0x3edd3886ff986fef, 0xbec81f2189b385a2 ], + [ 0x3fefffffd01f36af, 0xbc8d41915db812ef, 0x3ea75fa8dbc84bec, 0x3b3a5cd79572a1a6, 0xbec6186d9fc357c5, 0x3edae02322e08822, 0xbee79082befd50ca, 0x3eef9c26e211b174, 0xbef0c768235c378b, 0x3eecba7164e1064f, 0xbee3f75c28c31ac8, 0x3ed663fcfff77e44, 0xbec3a6da35f36ee6 ], + [ 0x3fefffffe2ba0ea5, 0xbc826cd7908cba2b, 0x3e9d06ad6ecdf971, 0xbb3020b74d9d30fb, 0xbebbe46aa879edb2, 0x3ed143860c49d129, 0xbededabcbc3e620d, 0x3ee52139c87e9c82, 0xbee6f567cd982028, 0x3ee42ebd266abd62, 0xbedcf2f0c6adfb3e, 0x3ed0e2c0ed67786c, 0xbebf50cb81b9b190 ], + [ 0x3fefffffee3cc32c, 0x3c7e429188c949b8, 0x3e91e1e857adc568, 0x3b32439f8a1649bb, 0xbeb1769ce59fb2c8, 0x3ec5fe5d47560794, 0xbed405da04875e51, 0x3edbfc96a938083d, 0xbedf19ff5e59cbe9, 0x3edc0c4d50d275bf, 0xbed4b9df120462ae, 0x3ec916640ee35de4, 0xbeb874483d99c37e ], + [ 0x3feffffff54dab72, 0xbc8a443df643729a, 0x3e85dcd669f2cd34, 0xbb1ceb1ec59e0c28, 0xbea5b11cbd1ee799, 0x3ebbc91a6b1c1839, 0xbec9c2c5d12dfa2c, 0x3ed25d1e3c70364f, 0xbed4dbe26c88e4f7, 0x3ed347bb8350b422, 0xbecd51d3280da8a0, 0x3ec25ed8e5b466b5, 0xbeb2b9c5d3390919 ], + [ 0x3feffffff99b79d2, 0xbc758ff1c425f8de, 0x3e7a854ea14102a9, 0xbb121745e4b4fcb3, 0xbe9aba593e8384ae, 0x3eb167c252a45678, 0xbec06d78ca0424a3, 0x3ec7e0f59fcfa53d, 0xbecbb4d48383b847, 0x3eca39f3ad9a397f, 0xbec47e836879c374, 0x3eba89244d14b829, 0xbeac33e15a6dbe37 ], + [ 0x3feffffffc355dfd, 0x3c688cb60fd4511c, 0x3e6febc107d5efab, 0xbaed9ed10902067c, 0xbe9055a3c70279a4, 0x3ea59ff37766e9a7, 0xbeb4c53adb9dcc4d, 0x3ebec49242997849, 0xbec23927ad6ac54f, 0x3ec1a6e0676c7463, 0xbebc5239f6a88a96, 0x3eb2e991308bf6fa, 0xbea4e276c09fe81b ], + [ 0x3feffffffdc4ad7a, 0xbc8d75de787812d4, 0x3e630f93c3699079, 0xbaf8f941ab38e9da, 0xbe83ce2f890bb01d, 0x3e9aa5010863c83b, 0xbeaa08ef1ca16360, 0x3eb3a4a6af3cafac, 0xbeb7be1e832218f0, 0x3eb784775c30c386, 0xbeb3593046482ce3, 0x3eaa9d448178fbfd, 0xbe9e77bb85451c65 ], + [ 0x3feffffffeb24467, 0x3c8bff89ef33d6dd, 0x3e56961b8d641d07, 0xbaf74a7fc97b1544, 0xbe77d2510f1f969d, 0x3e90476b165ac852, 0xbea02d3a3b9d195e, 0x3ea8db3567bef1df, 0xbeaea3ef4e3a126b, 0x3eaf03b0861a59ac, 0xbeaa250ca467705a, 0x3ea27e9995f6dfcd, 0xbe95e77b673c6d74 ], + [ 0x3fefffffff3e8892, 0x3c5befbf8d294678, 0x3e4a8e405e651ab7, 0x3ab167a2d8cf6b18, 0xbe6c6c40e5083698, 0x3e83ba47a17512fd, 0xbe93ee334beef6ec, 0x3e9f2bf9e6c43e99, 0xbea395c08ac8e281, 0x3ea43ee4b521ccad, 0xbea178f0deeb9b20, 0x3e9964e51b0f0532, 0xbe8f0cc4ecca5c2f ], + [ 0x3fefffffff90b2e3, 0xbc7d82d94a90f1e4, 0x3e3efac5187b2864, 0x3acf1301ae680614, 0xbe60d229044adeee, 0x3e77b5bc9db47d00, 0xbe88588212e670c2, 0x3e935f42db1989fa, 0xbe98cd98865c4ff0, 0x3e9a2b8587c48078, 0xbe971aa2de99af9c, 0x3e913a89805c15d9, 0xbe85b53ca1bcf01a ], + [ 0x3fefffffffc0748f, 0x3c66ef7a9caef280, 0x3e31edfa3c5f5ccb, 0x3ac368f60e2e6cfa, 0xbe53c025a6810c37, 0x3e6c42f78a0989ad, 0xbe7d7c6c3583c6e3, 0x3e87dd6ccb5c93b4, 0xbe8f1ec2f699fdcc, 0x3e90bf7a04407a8c, 0xbe8e3aafe6dfd4e0, 0x3e871bc3a55b63f4, 0xbe7df66b11724e7c ], + [ 0x3fefffffffdbff2a, 0x3c749438981099b2, 0x3e24979ac8b28928, 0xbacc2f44bcf3ce52, 0xbe47015eec37753a, 0x3e60b487791590cf, 0xbe71b44b64c3c995, 0x3e7d23ff3ef8dd83, 0xbe8357d673d1ccfc, 0x3e853a563ce0e9e3, 0xbe83921106a960f6, 0x3e7ea527d318f96e, 0xbe746bd6cea7103d ], + [ 0x3fefffffffebc1a9, 0x3c7e0e5facabfab4, 0x3e177756ec9f78fb, 0x3aae20366d0e0306, 0xbe3a9530780ca70c, 0x3e53962ecb10df65, 0xbe651494525dee64, 0x3e71a2961b90efb0, 0xbe77d35cd0b404bf, 0x3e7aa596d9d73afb, 0xbe791493d8d43ba2, 0x3e74184505343c2d, 0xbe6b7d977f1a3402 ], + [ 0x3feffffffff4b453, 0x3c859b25048a61cc, 0x3e0a887bd2b4404f, 0xba82556d8ad4dd44, 0xbe2e78be33fb01da, 0x3e46c6ef0b68629e, 0xbe58e36e9a44c497, 0x3e65286ee37c531e, 0xbe6d146395886537, 0x3e7090902855d5f0, 0xbe6fd0d1e8fcb6df, 0x3e6a10f65c3c5a7b, 0xbe624888c323daf3 ], + [ 0x3feffffffff9bec8, 0xbc76755054654b62, 0x3dfdc479de0ef004, 0xba9c3434581af3b8, 0xbe21535aee3eb1b2, 0x3e3a4547ed264758, 0xbe4d2308d0dead0f, 0x3e5929d46a9a7edc, 0xbe6195dbfd4afd19, 0x3e646630f49ccd2f, 0xbe63fa4637c64ebc, 0x3e60b98a6e0cfc02, 0xbe58093f032972f3 ], + [ 0x3feffffffffc901c, 0x3c69c951c943961c, 0x3df0916f04b6e18d, 0x3a81bdf9650721ea, 0xbe138b90f78fbe14, 0x3e2e0d7765326885, 0xbe40e9760d0ac127, 0x3e4daad91166722d, 0xbe5513c51b9838ed, 0x3e58e27fb85ba534, 0xbe58d6f6bd99eaff, 0x3e553c31e52fff08, 0xbe4f3bfd31796bc0 ], + [ 0x3feffffffffe202d, 0x3c8a54841f566a61, 0x3de24caf2c32af16, 0x3a802e3358112fa1, 0xbe05dfa962d49548, 0x3e210ca1ff2af812, 0xbe3377c7e98dd9b4, 0x3e4156649e0b5dd2, 0xbe49092f4db426c5, 0x3e4e12a29b227972, 0xbe4e94e18d5271a9, 0x3e4aae38927ee69b, 0xbe441121b0293be1 ], + [ 0x3feffffffffefc57, 0xbc68225a9658ef84, 0x3dd40dfd87456f4f, 0xba7a6d5c55f8e63b, 0xbdf848f101ce14c8, 0x3e132fed47f8dd28, 0xbe2638ff4a6975f2, 0x3e3416d25168a6b8, 0xbe3d78fb22f58668, 0x3e42009c6b4e61ea, 0xbe42a459e59c850b, 0x3e4096a3e8dac0ea, 0xbe397fba69de37d8 ], + [ 0x3fefffffffff748e, 0x3c6ae15e36044aac, 0x3dc5ce9ab1670dd6, 0x3a4cc9bbfb723fc4, 0xbdeabf69bd9866f7, 0x3e056ae1e8abbbbf, 0xbe1927ca04d1a7a8, 0x3e2713d3b07d7a36, 0xbe31318f5d7d717b, 0x3e355ab94fdfd1f4, 0xbe368216fb90717a, 0x3e346ad5ce577d65, 0xbe30065a20073e81 ], + [ 0x3fefffffffffb5b0, 0xbc850fb19119064f, 0x3db7872d9fa10ab2, 0xba57760afdf543a4, 0xbddd39eaac4a0b47, 0x3df7b67ab8af33d6, 0xbe0c3ced54e694ea, 0x3e1a4875d8a47f12, 0xbe23e213e6f5c296, 0x3e2919137301f897, 0xbe2aea6bd9b34930, 0x3e28e06e4ab5925f, 0xbe23ed1d979421b2 ], + [ 0x3fefffffffffd8b3, 0xbc65182469c211e0, 0x3da92ff33023d5c3, 0xba42932180032bd1, 0xbdcfae4fe28d12dd, 0x3dea0a80964d6e97, 0xbdff6f47be478e2a, 0x3e0dad968cdacb13, 0xbe16ca68a8bfdb81, 0x3e1d3a79e5305b4a, 0xbe1fe1534ebf69c7, 0x3e1e01ee76d92779, 0xbe1883ed9069f3fd ], + [ 0x3fefffffffffeb60, 0xbc74d3f53e684bf8, 0x3d9ac0f5f322937a, 0xba38e8ab19224e58, 0xbdc108dc99cf03e5, 0x3ddc5db17016a0c6, 0xbdf159f41ea079c3, 0x3e009ced3e9b7204, 0xbe09e4dace066800, 0x3e10dd5e0e9749b6, 0xbe12b3aa6599d0b5, 0x3e11eb5e8e4ffe8f, 0xbe0dd8955967ed31 ], + [ 0x3feffffffffff542, 0x3c6b57ed63ed8110, 0x3d8c324c20e337e5, 0x3a253fd8abf42ed9, 0xbdb22c6b11327305, 0x3dcea5f66f89cbd4, 0xbde2ff1e0a81bedc, 0x3df270ddbd8e501f, 0xbdfd2992b5c25c93, 0x3e03492d76bdf266, 0xbe05bc7361853dde, 0x3e053121ae3f1d2e, 0xbe01fb0f7e3f242b ], + [ 0x3feffffffffffa73, 0xbc76fead614b7934, 0x3d7d7c593130dd16, 0xba08e78574fe0514, 0xbda33c1e2f16e037, 0x3dc06c53fdc74764, 0xbdd4a029a87915ac, 0x3de44bd86238ff0d, 0xbdf0474ac3a80072, 0x3df5db2a89e9bc47, 0xbdf906f4b51a7f75, 0x3df8d189784c1f50, 0xbdf571a4760f483d ], + [ 0x3feffffffffffd27, 0x3c719e1a84064c56, 0x3d6e9810295890f9, 0x3a0f998d55766fdb, 0xbd943262ab4b77b2, 0x3db1756eae580a28, 0xbdc6359d5b0d251e, 0x3dd626391bd58994, 0xbde203efc6c9f556, 0x3de88c0b111be900, 0xbdec8ca211a38811, 0x3decc911f684d612, 0xbde950e3edf09a71 ], + [ 0x3feffffffffffe8d, 0x3c5e766e2c801398, 0x3d5f7f338086a87b, 0xb9ddfa0c27b527e0, 0xbd8509f766d9f287, 0x3da268e278ede221, 0xbdb7b7b43e9a1b0e, 0x3dc7f7aadab6b398, 0xbdd3c3cc6aafba0b, 0x3ddb52c69b4ab6de, 0xbde0222c438d1182, 0x3de0888e14314f83, 0xbddd96aaea63b362 ], + [ 0x3fefffffffffff45, 0xbc85948eec884df5, 0x3d501647ba79874e, 0x3986d5d39dabc300, 0xbd75be1cf20840dc, 0x3d93418096320daf, 0xbda91e9beb94b447, 0x3db9b762261756a7, 0xbdc57f320a630c91, 0x3dce24b78ce82b11, 0xbdd2112fff5c77aa, 0x3dd2cfdd93a41786, 0xbdd11ea1f35b4d2b ], + [ 0x3fefffffffffffa2, 0x3c6d07509a1a9440, 0x3d404e15ecc7f401, 0xb9d0858e34f7a6a6, 0xbd664ac1f9b95f96, 0x3d83fa8302ade993, 0xbd9a62b70897719e, 0x3dab5c619266e9f0, 0xbdb72de32129cbb8, 0x3dc07ae94305c398, 0xbdc40c45a9e95152, 0x3dc533d127efdf16, 0xbdc39dc242ba4cda ], + [ 0x3fefffffffffffd1, 0x3c83b6fc0b729759, 0x3d3065b9616170e1, 0xb9c49459f5147526, 0xbd56acaa58a8be12, 0x3d748fb92d0947e7, 0xbd8b7ce1a1ea8ea5, 0x3d9cddc552bbebeb, 0xbda8c751cc1a5784, 0x3db1dc79b52007b0, 0xbdb60b3d17e7714c, 0x3db7ac1d379afc28, 0xbdb641ca84798564 ], + [ 0x3fefffffffffffe9, 0xbc55fe91226dd510, 0x3d205ca50205d279, 0xb9c7a281f9edb8e6, 0xbd46e18ec0d42451, 0x3d64fdb051100a15, 0xbd7c66b3f3fe565e, 0x3d8e331281475b54, 0xbd9a42e6965b2b9a, 0x3da3301ef4931960, 0xbda804fcc1524d74, 0x3daa2ef0c13a3daa, 0xbda9028a915f98d3 ], + [ 0x3feffffffffffff5, 0xbc8238f8ed17d9b3, 0x3d10330f0fd69931, 0x39ba2c00e0c6dcba, 0xbd36e8334c65749d, 0x3d5541d561058477, 0xbd6d1ac042ada69e, 0x3d7f54864c5a530e, 0xbd8b984c73c1d301, 0x3d946ec7009c291f, 0xbd99efc2df737760, 0x3d9cb12ac38f37ca, 0xbd9bd54fcd67b8d4 ], + [ 0x3feffffffffffffb, 0xbc8efa4d64f59f62, 0x3cffd3de10d6287a, 0xb99e1fdae91c5cfe, 0xbd26c073be0916e6, 0x3d455a8eab9e129a, 0xbd5d94c87c1bc304, 0x3d701db0818bec24, 0xbd7cbfbe4c0ef6ee, 0x3d859179d8c519c4, 0xbd8bc172710440bd, 0x3d8f26a4f726814e, 0xbd8ead889e052555 ], + [ 0x3feffffffffffffd, 0x3c86be96953fe014, 0x3cef05e82aae2be2, 0xb98070a8237b4337, 0xbd166b44c6d7ddb6, 0x3d35474bd9d072f3, 0xbd4dd1e8c33100cc, 0x3d60711486984913, 0xbd6db2522b66a6ce, 0x3d76919a06329739, 0xbd7d6fe8f87926e8, 0x3d80c1488010ff5c, 0xbd80bf9fa407e9ab ], + [ 0x3fefffffffffffff, 0xbc80fecc5ed770de, 0x3cde00e9148a1d52, 0x394f7a503c7a2ad8, 0xbd05eaaa4200e355, 0x3d25088b6566fced, 0xbd3dd0b48e0f634e, 0x3d50a27116d7478e, 0xbd5e6a3e1d5c214f, 0x3d6769249755a4bc, 0xbd6ef16049050b69, 0x3d71dbf2744f66db, 0xbd721c636bd8f5a9 ], + [ 0x3fefffffffffffff, 0x3c8989c6c5d51227, 0x3ccccaaea71ab110, 0x394152f323a1f3b4, 0xbcf541a2f15eb476, 0x3d149fd53e85cdf3, 0xbd2d9144beee6b4a, 0x3d40b09b02f533a1, 0xbd4ee312fcf48076, 0x3d5812ed2f01f60a, 0xbd601e6391f47ad7, 0x3d62dce8f6b8c896, 0xbd6365d5011db0df ], +]; + +#[rustfmt::skip] +pub(crate) static ERF_POLY_C2: [[u64; 27]; 47] = [ + [ 0x3fcac45e37fe2526, 0x3c648d48536c61e3, 0x3ff16e2d7093cd8c, 0x3c9979a52f906b4d, 0xbfca254428ddb453, 0x3c69c98838a77aea, 0xbfd59b3da8e1e176, 0xbc41f650c25d97b0, 0x3fb988648fe88219, 0xbc55aecf0c7bb6c1, 0x3fb803427310d199, 0xbc5a14576e703eb2, 0xbfa09e7bce5592c9, 0x3c3eb7c7f3e76998, 0xbf9516b205318414, 0xbc2941aa998b1fa4, 0x3f8038d3f3a16b57, 0x3f6e19d52695ad59, 0xbf59542e7ed01428, 0xbf41f9b6e46418dc, 0x3f30796a08a400f4, 0x3f12610d97c70323, 0xbf025d31d73f96d1, 0xbee05e1fa9e02f11, 0x3ed1e616f979139c, 0x3ea9b3d54f1f222a, 0xbe97ad96beea439a ], + [ 0x3fd5da9f415ff23f, 0xbc4a72e51e191950, 0x3ff05fd3ecbec298, 0xbc9f17d49717adf8, 0xbfd477c8e7ee733d, 0xbc792236432236b7, 0xbfd1917b60acab73, 0x3c7c06e6c21b4b3b, 0x3fc322a728d4ed12, 0x3c3ffa8aef321410, 0x3fb04c50a9cd2c12, 0xbc4edd0562dce396, 0xbfa7ce764eeddd86, 0x3c29afeb391c029c, 0xbf868aac5801171d, 0x3c24f9655411fc03, 0x3f862aa895f51cd3, 0x3f56c003c3cedb10, 0xbf6079502dbbafff, 0xbf1d9c7cbb799b47, 0x3f345a995aede3f4, 0x3eb0c04ea8c98fc9, 0xbf057edfa53128d0, 0x3eba96286bf3ef56, 0x3ed3c8ab12e6d24b, 0xbe97454eba0cb203, 0xbe8f02a6f6847617 ], + [ 0x3fddb081ce6e2a48, 0xbc77ff0a3296d9cb, 0x3fedd167c4cf9d2a, 0x3c844f2832f90a97, 0xbfda173acc35a985, 0xbc3c5432c9a22740, 0xbfc889a80f4ad955, 0xbc6f6123bf467942, 0x3fc6c2eea0d17b39, 0xbc61f4935c3cf5b1, 0x3f9b0645438e5d17, 0x3c37a5f08ebaf9d0, 0xbfaa3fd9fcbb6d6d, 0x3c494a1b58b5916f, 0x3f2060b78c935b8e, 0x3bb9cec375875a1c, 0x3f8678b51a9c4b0a, 0xbf51e03bfc8eebb4, 0xbf5e653535cab33f, 0x3f355f31366d2c5c, 0x3f30dcf1445cbb88, 0xbf1098913ad4dcc7, 0xbeff6e252329eeed, 0x3ee41ad0a5afe51d, 0x3ec8fd4609222f1c, 0xbeb4465926de1a35, 0xbea407a1f42b46d4 ], + [ 0x3fe25b8a88b6dd7f, 0x3c89534a3b5bd215, 0x3fea5074e2157620, 0x3c7fad8c0ef6fae6, 0xbfdd9a837e5824e4, 0xbc71d19ec86adc7c, 0xbfb9c41d1d5fae55, 0x3c374c230d6afba4, 0x3fc75bebc1b18d1c, 0x3c501ece95d4dffc, 0xbf86410ad9332666, 0xbc216523d167a40c, 0xbfa7df8890b11fa7, 0x3c4d6a99d1387564, 0x3f84a54816d3608a, 0xbc2f810ad06699cc, 0x3f818f36eb18f3d7, 0xbf68d661c030e174, 0xbf53628ede23e249, 0x3f4438eb2b3c4d27, 0x3f1fd3c13e725e91, 0xbf1991b866a32c87, 0xbee1237c600dab6f, 0x3eea9c701140d4c0, 0x3e71801e61adfdda, 0xbeb785516863e6ce, 0xbe83e033ef590125 ], + [ 0x3fe569243d2b3a9b, 0x3c78eef7012e8df4, 0x3fe681ff24b4ab04, 0xbc5dba6493354c70, 0xbfdef2bed2786b25, 0xbc7ae3f6b6b2b679, 0xbf8a4254557d722f, 0xbc20ff7bffd10053, 0x3fc532415c267962, 0x3c62eacc4bd2e841, 0xbfa558b4c55a835c, 0x3c3c21c40815d70a, 0xbfa1b7ad5b777f1b, 0xbc42115b2bd8d644, 0x3f91201d3bd0e758, 0xbc0b39b845442560, 0x3f72995e3a88a890, 0xbf70294c3e93cdb0, 0xbf3159644a564f83, 0x3f463daf9b3858ef, 0xbf03beeb4a1255ac, 0xbf180c5178c36c72, 0x3eed4f6f5bab7dfa, 0x3ee521deb6d2f46e, 0xbec4ef3208231a8b, 0xbeae7d2b4e06e4a2, 0x3e921536d5b8bdf9 ], + [ 0x3fe7fb9bfaed8078, 0x3c766cf14bcad032, 0x3fe2a8dcede3673b, 0xbc77378e2c70325e, 0xbfde5267029187c0, 0x3c7add23841b110a, 0x3fafe0796bb9d05a, 0xbc37a992e13ce574, 0x3fc0fa23021ad0ac, 0xbc417f4228359928, 0xbfafa21ebca76761, 0x3c3278ca2820f66c, 0xbf931546d5c4edb4, 0x3c136fcf151892a0, 0x3f937e5469efb7a6, 0xbc39553630321d4f, 0x3f2097966e2e87ea, 0xbf6e82ab020887a7, 0x3f4318270c11ae74, 0x3f412652e433da97, 0xbf24dc9bd6368bb8, 0xbf0c441138d4ff53, 0x3efc91d8dc5b66ec, 0x3ecf3ba57b86d474, 0xbecdd3403d11a818, 0xbe731f497a106a7c, 0x3e9436dbcc93d342 ], + [ 0x3fea1551a16aaeaf, 0x3c6a558a46df5f68, 0x3fddfca26f5bbf88, 0xbc6ddcbaf85587b6, 0xbfdc1cd84866038f, 0xbc7200885b97f453, 0x3fbe4c9975da0987, 0xbc5f162e7576c79c, 0x3fb747e31bf47af3, 0xbc56178f12d62ed9, 0xbfb1d1f00109e42a, 0x3c5002b06e023544, 0xbf647654175ceb42, 0x3bd683389ccacfa8, 0x3f91a817c594b8cb, 0x3c336ac477166efb, 0xbf6cb8acd699cca6, 0xbf657b72bf874db6, 0x3f524493dca8b6fa, 0x3f2f556774c6aaf6, 0xbf2b09ec5c8ba626, 0xbed09bd1a09f38e8, 0x3efd149c3e776976, 0xbec8f7c2a6575e92, 0xbec8391d4afaf16a, 0x3ea5a7552081d1d5, 0x3e932d1bb2d1d0ca ], + [ 0x3febbef0fbde6221, 0xbc8322c1148e0d48, 0x3fd75a91a7f4d2ed, 0x3c56eb826a9df85c, 0xbfd8d03ac274201c, 0x3c57a5c56eb7f6a0, 0x3fc3954778d6a0df, 0xbc5863eca74d1838, 0x3fa88e0f7b183fc6, 0x3c4226527d05ce39, 0xbfb0f7c15f75ee13, 0xbc156f74f3513660, 0x3f85e22cfa1aab51, 0x3c24b49a250c6474, 0x3f89ad28c5557c22, 0x3c299920b730ecd5, 0xbf7704ec5d29fc83, 0xbf523360304f19ba, 0x3f543ca3fcdf079d, 0xbf0dcb97a9e04bd4, 0xbf2735e26c43d267, 0x3f0360c3b06ffbb4, 0x3ef29a6b5798e781, 0xbeddbc35e4cf98f5, 0xbeb2f6e8e81287bb, 0x3eaeeb2fdddad355, 0x3e81ae65e387ac52 ], + [ 0x3fed0580b2cfd249, 0x3c84fca6318dfee9, 0x3fd1a0dc51a9934d, 0xbc6ca89d2d78fba4, 0xbfd4ef05a0f95eeb, 0xbc65f7c55a00231c, 0x3fc5648b5dc47417, 0xbc6fb8fa09976e07, 0x3f840fbaba44504c, 0x3bf435c75f61f1e0, 0xbfac0db89d0a41a4, 0xbc11dd02d9441b98, 0x3f9388c3ec056942, 0x3c38e7498172c914, 0x3f7aecb7463cf446, 0xbbe0d6701a009d70, 0xbf78bca53327e075, 0x3f34add4a8239f4a, 0x3f505ce4abd10484, 0xbf3183f198a0b620, 0xbf19cd1a9b9fc69b, 0x3f0d30363021af83, 0x3ecda66f2161c4c6, 0xbedf41f1f238827d, 0x3ea725a07b1177b7, 0x3ea84c3b2483eb6a, 0x3e6e30e89d6e85cd ], + [ 0x3fedf85ea8db188e, 0xbc8f71e8254d11a9, 0x3fc9cb5bd549b111, 0xbc4973e73caa1edc, 0xbfd0ed7443f85c33, 0xbc574bf040302ad8, 0x3fc5066cda84bba9, 0x3c4beb86d9e281a8, 0xbf9419fa10b6ed7d, 0x3c35157491034c58, 0xbfa3f41761d5a941, 0x3c494a1c1f7af153, 0x3f96d1d724baaae4, 0x3c3c41090a704426, 0x3f4e377f5703f7ff, 0xbbea753be0c53963, 0xbf74cc916ad63c27, 0x3f5553ef0d12719f, 0x3f426240f55987fd, 0xbf36bbf0fffb7138, 0xbee320cf6663c40d, 0x3f0a9d4850aaa197, 0xbee17036c4011c91, 0xbed441ea26a91a02, 0x3ebd81eb8e2ef452, 0x3e917d7b798a4322, 0xbe4b7b0dfb2559d0 ], + [ 0x3feea7730ed0bbb9, 0x3c82c5bd7ce1388b, 0x3fc24a7b84d38971, 0x3c6aa0c5e788ed5e, 0xbfca4b118ef01593, 0xbc3238e3e6a99de0, 0x3fc319c7a75f9187, 0x3c4a8f8fff24b0ac, 0xbfa3db5bed47faf6, 0x3c429cf699c8512c, 0xbf97019bda6c2fdd, 0x3c1dd56b84622d88, 0x3f959d3aa402c32e, 0xbc08de701f1e95e8, 0xbf6b324eab9c87a9, 0xbbec3a4329771a44, 0xbf6b4774d37d0dd6, 0x3f5c01377485a844, 0x3f1a5db5f627539b, 0xbf340d9c429b8932, 0x3f0e720d935ef7db, 0x3effc8295ac052de, 0xbeed1ccde95c6551, 0xbeb251c256ca45cb, 0x3ebe892cc5397b1b, 0xbe88f6831febdf3d, 0xbe9aa5ef30a52421 ], + [ 0x3fef21c9f12f0677, 0xbc57efe429672268, 0x3fb92470a61b6965, 0x3c5c6acd40cee352, 0xbfc3a47801c56a57, 0xbc6033705aa16f01, 0x3fc0453f90d3bd35, 0xbc6686e281ba5405, 0xbfa8a7c6a239217b, 0x3c32a988808a7222, 0xbf8075c088031ee3, 0xbc1665bd0a645f40, 0x3f916f9c9c127b80, 0xbc1e1813af47374c, 0xbf774c2fc9bdfe97, 0x3c15cf2dbe53783b, 0xbf5760c522bd5bec, 0x3f5a3cdb656adb44, 0xbf302c3c1ab0a7ba, 0xbf292892013c7e15, 0x3f16e7b268d42034, 0x3ed970751eb9359f, 0xbeeb00b549bbdf58, 0x3ec033f8545bcc6a, 0x3eb2d8b6f0a2204a, 0xbe9c1c1335b105c5, 0x3e661bbb2d003b8a ], + [ 0x3fef74a6d9a38383, 0x3c8c33a329423946, 0x3fb0bf97e95f2a64, 0xbc5446051f6fef82, 0xbfbc435059d09788, 0xbc4b93aeb5e5cf84, 0x3fba3687c1eaf1ad, 0x3c564513fb767a13, 0xbfa9647a30b16824, 0xbc486357831221be, 0x3f66981061dfbb09, 0xbbfccc83193c8742, 0x3f87e8755da47040, 0xbbec1eaeb3371490, 0xbf79be731fdab95d, 0xbc0ab79fedbfccd2, 0x3f23a95ae0a75542, 0x3f5319f780e962d8, 0xbf3b88dd51a4f261, 0xbf1037f168a8f581, 0x3f153fc5e83e3199, 0xbee9d5bf30917222, 0xbee03045c999d17a, 0x3ecb5d376e96179f, 0x3e8c66d2e5aa2274, 0xbe9aef24a52bcaca, 0x3e7b20b678e8a0c6 ], + [ 0x3fefab0dd89d1309, 0xbc8ae61bd9db1bab, 0x3fa5a08e85af27e0, 0x3c4e4f9cfc8c2382, 0xbfb399812926bc23, 0xbc5b782644df6665, 0x3fb4140efb719cb0, 0x3c308fa5a48311e8, 0xbfa7535a61a4193d, 0x3c359e0501c376b2, 0x3f8374c88c7e6abd, 0x3bfc2578bd7e3f00, 0x3f7a40709e010e77, 0xbbf18c33197d9138, 0xbf76dc078888efa7, 0x3c02b49da4c86c70, 0x3f52ee6d200993b0, 0x3f444f175e22a161, 0xbf3c2fb051c92f92, 0x3f0523035ed3964b, 0x3f0bc7b666856fc1, 0xbef574549f39ee50, 0xbebc57f3c47b39d9, 0x3ec8acc76ac31fcd, 0xbe9f70e8b7deaa9a, 0xbe8e1a28a0c1a6a6, 0x3e6bfa0e5b606c5e ], + [ 0x3fefcdacca0bfb73, 0xbc82c33d88729e43, 0x3f9b1160991ff737, 0xbc2d940a504353bc, 0xbfaa38d59456f77d, 0xbc1d625808eb9778, 0x3fad5bd91b6b0123, 0x3c222b86f5e3e16c, 0xbfa3b35dcbc80146, 0x3c482838d776d958, 0x3f89d76b0a0535c7, 0x3c260fda06bca0a0, 0x3f614c887a83a0e6, 0x3be55ef222558d68, 0xbf7117f42cc6e9f4, 0x3bed4213a7e14a18, 0x3f59b477bdad8e08, 0x3f21d219fb0e1bc8, 0xbf35bb59d3ca4fa9, 0x3f18ca373c577821, 0x3ef4a9b74153a4a3, 0xbef424a8a8831410, 0x3ec6ce0877965abc, 0x3ebc1ed3c11b1dd1, 0xbea86b0a731d831a, 0xbe55cea3996396c5, 0x3e9640950bde5eb3 ], + [ 0x3fefe307f2b503d0, 0xbc68a555000387f8, 0x3f906ae13b0d3255, 0xbc388abd7f4be982, 0xbfa0ee3844e59be7, 0xbc40b0ec94b96d83, 0x3fa48b127f8ed8a5, 0x3c3b6a1f18c2c162, 0xbf9f155b4e7d8c3b, 0x3c3adb2d99b0c1fc, 0x3f8aa2c0753d569a, 0x3c29a37b9864b8e6, 0xbf4bbf7e2795837b, 0xbbe4784a66288abf, 0xbf65478d784d271c, 0x3be27115917a7ec0, 0x3f58eae08cdf9546, 0xbf292946556037e6, 0xbf290f27ae61444c, 0x3f1b076b78538f02, 0xbedb2906f1b92d5d, 0xbeea2f66822d4a01, 0x3ed3031c4f7c4a97, 0x3e941708ced2abd0, 0xbea45ffd6deae2a8, 0x3e7e844ebdc8456a, 0x3e7c0bbf2b711595 ], + [ 0x3fefefcce6813974, 0xbc5b27cf5025d1c8, 0x3f834d7dbc76d7e5, 0x3c23780d6e7eb351, 0xbf951cc18621fc23, 0x3c2969629e4b64a6, 0x3f9b925a99886bb7, 0x3c29c8f65efdd1f4, 0xbf971e7d408c8c6f, 0xbc3c5621deaf4cfc, 0x3f87ea58080a81ef, 0xbc22f25b7f384ff3, 0xbf646eb9d203e071, 0x3beff569e38360a4, 0xbf5403333682fa5e, 0xbbe36256a95953a6, 0x3f53b37d5bd14a40, 0xbf36be130822dbdf, 0xbf103d4bcdafd553, 0x3f155848476c8142, 0xbef5492bf3c6eee6, 0xbed3823d4328e9c5, 0x3ed152fefc353e5a, 0xbea5199dbf7bc4c6, 0xbe94dda2bebe08f2, 0x3e83fb850b47210a, 0x3e6bcd1b284c4798 ], + [ 0x3feff733814af88c, 0x3c70a87238cea4fa, 0x3f75ff2750fe7820, 0xbc15f184847ca667, 0xbf896f0575a63ae5, 0x3c295f4139297a96, 0x3f91c5a643f04363, 0xbc16ea87997fba3c, 0xbf904f5caaf2196f, 0x3c119502347d3b54, 0x3f8382a146afb9d2, 0xbc0f93bde902d2d0, 0xbf695cab93aa68d2, 0x3be0f716a5fc18c4, 0xbf2d2fd90fe62928, 0xbbb4e00d5fcc484a, 0x3f49f50fb94c0b86, 0xbf37d7378074399b, 0x3efcc0c9cb9ede1e, 0x3f092a3a29471895, 0xbef7c127858c909a, 0x3eb5a72fde935a48, 0x3ec57b9d90a92106, 0xbeafdb8443754cf7, 0xbe56c7d633eab55a, 0x3e7ddcfc714a2b67, 0xbe89fedf738e84b4 ], + [ 0x3feffb5bdf67fe6f, 0x3c14e830346f6e80, 0x3f684ba3004a50d0, 0xbbf90b93d4632206, 0xbf7d9c2ea85a927d, 0xbc10bcf1ea93cfdc, 0x3f860898536e104a, 0xbc1ab6aa911c445e, 0xbf85eb1c899f0b70, 0x3c21bc22eed1f1fb, 0x3f7d854f73e74c87, 0x3c07a977a3364c40, 0xbf6897719a9d257e, 0xbbeab523e3f93994, 0x3f388cdc8b807c97, 0x3b94875acc7c06a0, 0x3f3b325a11c1f45a, 0xbf3381548f692740, 0x3f12b1fd05559bfa, 0x3ef1ed31cd6feb26, 0xbef29cf593fdf00a, 0x3ed1cea99b59228c, 0x3eaceff221e3598a, 0xbeab0ad4b899b2d9, 0x3e83761b047e21d1, 0x3e696c31c2256049, 0xbe60a714c57f7adf ], + [ 0x3feffd9f78c7524a, 0x3c804ed6ff98e45d, 0x3f5a024365f771bd, 0x3bf3c8f5202cb405, 0xbf70a9732d5284dd, 0xbc11acbd0899ce7e, 0x3f7a4bf47a43042a, 0x3c0e6cb2580d0920, 0xbf7c23802d8a5bb7, 0xbbd9963700abfc80, 0x3f74f40070668329, 0xbc1e1fe1c0e1182a, 0xbf64c9a2c9dccd04, 0x3c080fb9c9cd78c1, 0x3f44f7a50b5bc019, 0xbbd40906b7a1de3a, 0x3f218b04eb90c737, 0xbf2a4c3880c0ea69, 0x3f14b7b82a86f423, 0xbed0bc762b1c2aaa, 0xbee589d6f8892acf, 0x3ed357ab63f7bdf9, 0xbe96675858bbff5e, 0xbe9ea96dcb12a15c, 0x3e88c572fcf5610e, 0xbe3700c93da86dee, 0x3e57ae9ceb75e26e ], + [ 0x3feffed167b12ac2, 0xbc8ddc0ce3ed8fcb, 0x3f4afc85e0f82e12, 0x3bd438f22895e03e, 0xbf6221a9f326bef4, 0xbbf99642b37af330, 0x3f6e3c9aab90bcf4, 0x3bb7dcdfdccc72a0, 0xbf714b1b98141f21, 0x3c1af6edf50eba66, 0x3f6c1c19b9e63d70, 0x3bd4d1e9411f1d28, 0xbf5feac3dbeb5124, 0x3be2400e6ffbc1c8, 0x3f463e88178b0e49, 0x3be3e4ae97774f91, 0xbf04441c86c93f39, 0xbf1c8ceebc5fc50b, 0x3f1125b77a79aa6c, 0xbeeda7be990bc718, 0xbece019960474aff, 0x3ecd229185ef6279, 0xbeacea9fa10885e7, 0xbe8044fd6a2e447a, 0x3e83695f88fc641d, 0xbe60c0dc0ba0d589, 0xbe89194748828b93 ], + [ 0x3fefff6dee89352e, 0x3c8b96c0ba13851d, 0x3f3b23a5a23e4210, 0x3bc727bce1be0014, 0xbf5315107613c673, 0xbbf823f8673f5b7a, 0x3f60c243329a9ca1, 0xbbf65e361cefe652, 0xbf64630116262084, 0xbc00ea6ee40daf79, 0x3f61e84d1022e8cb, 0xbbd9b77b85eed4f0, 0xbf56b41872716325, 0x3bd3e9e001100f64, 0x3f436edde582b265, 0xbbe1cb479a94e148, 0xbf1f7870ebc38e77, 0xbf051ecfdc37801d, 0x3f0711d817e0d3b6, 0xbef0ae90d500d1d8, 0x3eaa85b1bf54920c, 0x3ebfe73958205038, 0xbead222bfef33aa4, 0x3e7833f8b13b1a4e, 0x3e7233b5a19285db, 0xbe61adcf574b7db6, 0x3e7ab10bedc44532 ], + [ 0x3fefffbb8f1049c6, 0x3c7d2c6266b51f26, 0x3f2a740684026555, 0xbba7e24cc3ac5710, 0xbf436d34c8f1c26a, 0xbbe69d73e7d1c977, 0x3f51eb6e14974a25, 0xbbf99b78600e0664, 0xbf5714eb8cc0947f, 0x3bf3613f37c7410b, 0x3f55bec08c01b1d7, 0xbbf3e3a262f6c68a, 0xbf4e4621d82dad12, 0x3bc302878843e2cc, 0x3f3e1b7b564b0e79, 0x3bcf894fc1f14d54, 0xbf224564b69716aa, 0x3ebbf8e3b47f3ccd, 0x3ef8f55a9be1a264, 0xbeeb3b76e6203281, 0x3ec713c795a07e0c, 0x3ea3bb092cfd93e0, 0xbea473b0a8333dee, 0x3e8645526869c143, 0x3e41a343e004b33d, 0xbe576c7e253faad1, 0x3e7e16080963cffe ], + [ 0x3fefffe0e0140857, 0xbc66aa36f86c14dc, 0x3f18fdc1b2dcf7b9, 0x3b87050f50b8f308, 0xbf3322484cf12daa, 0x3bd4cc0408806d4f, 0x3f427dc1bc6cfef5, 0x3beffbb5229f6bb7, 0xbf49202f465eb421, 0x3ba8f3f063b40660, 0x3f493b4c9746835f, 0xbbe04e2d6df2fce5, 0xbf430e9e6142fe9b, 0xbbd0396045094744, 0x3f3555b9d5fb4825, 0x3bd9a40d2ca5ef0b, 0xbf2055983c4ac7a6, 0x3ef68e6c75a5d068, 0x3ee2d4a50d2757ce, 0xbee1de08b56479aa, 0x3ec9110ccc7fe6fd, 0xbe8bb3184d789af8, 0xbe94629a164e82a0, 0x3e8413b087ee5e4d, 0xbe5648d7786f9fbc, 0xbe4293289f8c327d, 0xbe6c283008e726f7 ], + [ 0x3feffff2436a21dc, 0xbc83607959a29d36, 0x3f06e2367dc27f95, 0x3b6d96e6f0151020, 0xbf223c436c36fdab, 0x3bbf0d77fc600a50, 0x3f326bf00867a835, 0xbbdc92e1aecdc750, 0xbf3a51fb50b15f22, 0x3ba248227c6d2260, 0x3f3c0825378fda08, 0x3bd5a8a09c053451, 0xbf36c3dbfe0cbe4a, 0xbbde65769c33f8a1, 0x3f2c1dd1438378df, 0x3ba91bd161f34158, 0xbf194c36a9d7c0dc, 0x3efbf0aab116ca41, 0x3e86bdbd2f103930, 0xbed2b32e8d43ef25, 0x3ec3a7403459770b, 0xbea17411873320fa, 0xbe735bb2691c9b29, 0x3e798313537ed069, 0xbe5cb4b60e85a341, 0x3e02be214cf4c9eb, 0xbe8350a1a851865a ], + [ 0x3feffffa1de8c582, 0x3c8832540129302a, 0x3ef44f21e49054f2, 0x3b8f338cf4086346, 0xbf10d18811478659, 0x3bb914a7a08b6a2b, 0x3f21b964d438f622, 0x3bca52c94c56aaaf, 0xbf2a8d7851f26bf0, 0x3bcc38dbf3ee1223, 0x3f2ddd6df9b6852d, 0xbbc3b0dd7eac9b91, 0xbf29e52b7aac1644, 0x3bc904036dfb5764, 0x3f2165b2034fcab2, 0x3bc27beac4bf3866, 0xbf11b75c3332673a, 0x3ef91a253c42f4e7, 0xbed020b498095051, 0xbebade63f30809ae, 0x3eb89bb0d75e59b7, 0xbea180c78d3dca28, 0x3e6cabfd39b38553, 0x3e66013ffba86cfd, 0xbe564f2b123e1f0b, 0x3e335bf3e5021105, 0xbe8177828ffd35af ], + [ 0x3feffffd8e1a2f22, 0xbc8c10adf6b19989, 0x3ee1783ceac28910, 0xbb87f19d8ee58337, 0xbefe06a8b37e5b93, 0x3b824e8db1358f2e, 0x3f107978c7b8496b, 0x3bbf163b5580927c, 0xbf19d039884f8be5, 0x3bbfce53cd30b1eb, 0x3f1e8d1145e94a54, 0xbbbd0f6e009a99ee, 0xbf1c1f7251172a87, 0xbb83ce0f013dfe90, 0x3f1458b9e0854d68, 0xbbb897cf3950b1a7, 0xbf06eb0557245429, 0x3ef33045cf65279e, 0xbed42c8adf18ab62, 0x3e491109b80f9918, 0x3ea83a9b44249fbf, 0xbe99bcbaf0a8dfd1, 0x3e7900325b58a857, 0x3e34a3cf9c161684, 0xbe50cbcc4d0a916a, 0x3e34275e1b91f084, 0x3e839180c75350e1 ], + [ 0x3fefffff039f9e8f, 0xbc89d1bcd6174e99, 0x3ecd21397ead99cb, 0xbb46abd9c029c47c, 0xbee9f19734d29cf9, 0x3b820c4383da36c1, 0x3efd982bd41d8954, 0x3b8d9bc9988e9666, 0xbf08320fc4836be5, 0x3b7526638b9926a8, 0x3f0e0a1cb1d071f3, 0x3b9d9f5d232bab90, 0xbf0d384223047b9c, 0xbba30d0b2b8a170d, 0x3f0696daf6422bd4, 0x3baba6ac732f399e, 0xbefbb6e2d311a93f, 0x3eea4fcb0ea87efb, 0xbed1c940c5303daf, 0x3ea7469913f4e9c6, 0x3e8ef4b4f8ab67ae, 0xbe8e189c28e8e041, 0x3e7678b281d5bc55, 0xbe49c3bf4e9f2b5d, 0xbe374c9ba997ffed, 0x3e2b4b843f8c7068, 0x3e6c901764507862 ], + [ 0x3fefffff9d446ccc, 0xbc6bb06bab98bc80, 0x3eb789fb715aae95, 0xbaf226d93bf89b40, 0xbed5b333cc7f98f1, 0xbb76bd1091d25440, 0x3ee9b12fdbf90f62, 0x3b8d4b6b0ee9cf46, 0xbef5e06923144d70, 0x3b4c593194857860, 0x3efc6a071925631d, 0xbb8835ef595952e4, 0xbefd178cb0388a82, 0xbb9039272760f01c, 0x3ef7e29d33ac92b6, 0x3b921ff8b0e9d5eb, 0xbeef9203429baad6, 0x3ee094dadeee395c, 0xbeca771cf3500d9f, 0x3eab8fd1c29c21ea, 0xbe5cc8573d7de110, 0xbe7b0362da1722cb, 0x3e6e5eae518f94e9, 0xbe507963addd99a6, 0xbe23f496093d0bef, 0x3e199078a326092d, 0x3e842681ecfe4da1 ], + [ 0x3fefffffda86faa9, 0xbc7d230252d68f26, 0x3ea26f9df8519bd7, 0xbb4e339871c015b7, 0xbec1926290adc888, 0xbb6e36d23dbb2644, 0x3ed5900c02d97304, 0x3b7fa7d21e3ed616, 0xbee3166de6a8c640, 0x3b8b014157867958, 0x3ee9dfcc328729e0, 0x3b820e9fee0b7665, 0xbeebcab1ed5ec38d, 0x3b6d9003794f0fe0, 0x3ee81cd74a57ce17, 0xbb8809fde9c0f6f5, 0xbee106e95b6bf556, 0x3ed379625a71385f, 0xbec1970a5b5bd443, 0x3ea74761c8333ff2, 0xbe80864e125c9951, 0xbe5b83bf9019aa3b, 0x3e60397611c35b28, 0xbe4a25392adb29ac, 0xbe17b832af40d9d4, 0x3df62a02eb79577b, 0x3e8a6da58ffe94f4 ], + [ 0x3feffffff233ee1d, 0x3c8db123ed17221d, 0x3e8bfd7555a3bd68, 0x3b20151cf177b53a, 0xbeab8d7f804d2e73, 0x3b482b366f0bc2dc, 0x3ec17f93e5149289, 0x3b391997bfd26568, 0xbed013b0457d08fa, 0xbb60d6d5a7f06298, 0x3ed6b245d7e1d829, 0xbb79985e02c8ce3b, 0xbed98077548c6951, 0x3b701cd3f1d12c93, 0x3ed7492048ab3ceb, 0xbb70368a0dc0750e, 0xbed17506c7b39cb0, 0x3ec57e94a4c5f5a6, 0xbeb570971200d7db, 0x3ea0a0f956947b21, 0xbe81a9b7bd5bba32, 0x3e451bfc00de3146, 0x3e495b6967f79cbe, 0xbe3fe3c43cb3cf84, 0x3e32f364a7a2dc5f, 0xbdf007442a10cc14, 0xbe7ef5ab6fc5e849 ], + [ 0x3feffffffb127525, 0x3c8504f382db4102, 0x3e74980cb3c80949, 0x3b17fbdd923f8057, 0xbe94ea6ce697296f, 0x3b3ea42f9c9de533, 0x3eab771d9b6f07b8, 0xbb1e9c1ca9662fe8, 0xbeba26c653fad5b8, 0xbb5146c4cee0e898, 0x3ec3302bb89379de, 0x3b64c55b83ef7a68, 0xbec67f42e5264334, 0xbb66779da26b4197, 0x3ec58b4adafb958e, 0x3b68351251b45e84, 0xbec10f576796285a, 0x3eb66ca44250dd07, 0xbea84ee0ada37543, 0x3e953b6065291e6b, 0xbe7c09ebfd0c581c, 0x3e563062625d59c0, 0x3e1e259c60eb7b83, 0xbe2e43802ad25514, 0x3e351bcdabe8cda5, 0xbdf930fc3df6e909, 0xbe881cdd770e1c81 ], + [ 0x3feffffffe4aed5e, 0x3c4389c0f32ad0f0, 0x3e5d5f3a8dea7357, 0x3affa07c18622dd2, 0xbe7ebfb14c9170c0, 0x3b19e40632b4145d, 0x3e94d9228525f449, 0x3b2d35bd7f959136, 0xbea48b536addac5f, 0xbb461ace22b32569, 0x3eaf48ccf23a68e2, 0xbb4ee1d13c79c281, 0xbeb3183b6134cf03, 0x3b4e1f4d5fe2a06c, 0x3eb31efde2215f01, 0xbb564a7021e23fba, 0xbeafd9eeb0f18fdb, 0x3ea63414459ae298, 0xbe99dda81be20b5a, 0x3e88da7d306423c5, 0xbe7303da86a4fc28, 0x3e54f5e1327706b9, 0xbe23efb5eefcbe53, 0xbe131bc5ce1ce65d, 0xbe13eafe1b05c93f, 0xbdf47fc2d9cc851e, 0x3e7d27265006a9df ], + [ 0x3fefffffff6d1e56, 0xbc864d969b4be4c4, 0x3e444d26de513197, 0x3ae76fc20fc4b365, 0xbe65e32de7af8977, 0xbaf888fd6ae18a1c, 0x3e7e9e05b3c8f38a, 0x3b17532141b12aa7, 0xbe8f2f6fa7db5b1d, 0x3b2b3bf498e3462c, 0x3e9899dcace485eb, 0x3b11885a0ae9e878, 0xbe9f34b7eef3c9b2, 0x3b3294a3b618b470, 0x3ea04be030272d14, 0xbb4df83095e40f79, 0xbe9c73bd22571559, 0x3e94edda838439f5, 0xbe89fc860b504677, 0x3e7b0d686a260420, 0xbe672370c2fdbe10, 0x3e4ee29f0d197d25, 0xbe2b4d88d500c5be, 0x3dc96014c45b0178, 0x3e0238f19dc8fd82, 0xbde8d34d46ae6567, 0xbe454105fe4a9cd8 ], + [ 0x3fefffffffd01f89, 0xbc735e8e39884f62, 0x3e2b334fac4b9f99, 0x3ac32178ed1a4971, 0xbe4e2cec6323e50e, 0xbac0e5693f9d4908, 0x3e65c027d5bba36a, 0xbaefc46fb3cc7ae0, 0xbe76df4d024fffbe, 0xbb090fd7226ec57a, 0x3e82aaf7c205b9ea, 0x3b2dbec2005b45a8, 0xbe88902edfbfefdd, 0xbb2c353aca58d08a, 0x3e8ab2ab1b338249, 0x3b2b498186c39105, 0xbe885abe0ff198d3, 0x3e82d32f7c3621eb, 0xbe78c141c71dbc95, 0x3e6b9fa6fbb9b198, 0xbe59db5fe2c2f5b9, 0x3e43b8e07840483e, 0xbe26d95e5070d91d, 0x3dfd7616168b0e49, 0x3e1f2be0744b3a5f, 0xbdd737a375809985, 0xbe7936d4936fb865 ], + [ 0x3feffffffff0dd2b, 0x3c80df73e7d2fc98, 0x3e11a94ff571654f, 0x3abfbf537b47967d, 0xbe34251f33f5578f, 0x3ad4c9cece8f41b2, 0x3e4de6bc1f75bb9b, 0x3a894afb459a3000, 0xbe6036b5fd1c4158, 0xbb0d582afa097896, 0x3e6b58f1385def96, 0xbaf8778854601996, 0xbe72a2347efb2133, 0xbb026f9e1ef0f378, 0x3e7508db866ffe00, 0x3b164de561a68a21, 0xbe73ffea934685b9, 0x3e702ff87b2e2576, 0xbe666e54eae5fa4b, 0x3e5a9ea2195c567d, 0xbe4ae3b91fecafa1, 0x3e36bb883d2e5ed1, 0xbe1ee10e97715c11, 0x3dfe2873d2b77f1f, 0xbdeaf385ae29d57b, 0xbdbd793eecfc2513, 0x3e420d80dcfa68d1 ], + [ 0x3feffffffffb5be5, 0xbc7729d6819c7f34, 0x3df63ac6b4edc88e, 0xba7c45991835da24, 0xbe1a0ce0dc06a706, 0xbab1b72d11da9dab, 0x3e33e380dd7593a5, 0xbad8ad868a7b5674, 0xbe4638bc4fb02cba, 0x3a87a84506fcda40, 0x3e535753ad4c5875, 0x3aead190ab170366, 0xbe5b41f33cafccba, 0x3af0e3539bf61116, 0x3e5fe694e371a659, 0xbad3a84e01866ea8, 0xbe5f8af0121aa0ab, 0x3e5aa77274dab3d8, 0xbe53616fe8f6a259, 0x3e484fddf4c681a1, 0xbe3a3de05d1b8a31, 0x3e2822529aca9f83, 0xbe126c3dfba84378, 0x3df64c287a84aa09, 0xbe0107d2dac5d83b, 0xbd4e251d1ab1d873, 0x3e58f37005f17b42 ], + [ 0x3feffffffffe9eb0, 0xbc5ea527e0bef1e8, 0x3ddb1e5acf351d87, 0x3a5dc96583ba19f0, 0xbe005042a0a5f3c3, 0xbaa2023f0f13867c, 0x3e199ac8fd63c66c, 0xbaabf57c5fd0501a, 0xbe2d72344378e114, 0x3acc77758959af41, 0x3e3a6be9a123435b, 0x3acdab4af8807c36, 0xbe433aacb4bf6dea, 0x3aebd241ea49ac35, 0x3e474b732e7ceaa7, 0x3adc7c89730b0264, 0xbe47e7eab6531ccb, 0x3e450959f2daae39, 0xbe3ffed4cef94261, 0x3e351c7f99f908a2, 0xbe282b5fd5fbedfc, 0x3e17e1c8e715c978, 0xbe051536822c861b, 0x3debe7e4c220ca82, 0x3e2f5bb67c461296, 0x3da1d7cf04529bf0, 0xbe8acc021ab828c4 ], + [ 0x3fefffffffff9a1b, 0xbc66a87270d2450c, 0x3dc0084ff125639d, 0xba58ad61debedc86, 0xbde3ca42adaa26f6, 0x3a8c20c6583dccdd, 0x3dffe73513c67bf8, 0x3a920d28c0c7e686, 0xbe12dd9aa5a2bee3, 0x3aad76d7235461be, 0x3e216ef6b93944a8, 0xbacf07bd785566de, 0xbe2a2d58e9b22b26, 0xbab19e6ea91dd55e, 0x3e306389b9748f25, 0x3adfbcc52565c0be, 0xbe316cdd9eb58ba2, 0x3e2fdd861b55c500, 0xbe29457846c943d2, 0x3e2178f3905f435c, 0xbe1518cf20c53de2, 0x3e06329939a34b66, 0xbdf5ef3ad85e5d3b, 0x3ddf2b41494e49e9, 0x3e2bad43bc0b622d, 0x3da21a45fa9dcebf, 0xbe8790b3d88f69fe ], + [ 0x3fefffffffffe380, 0x3c87ce07114e4fe0, 0x3da25f9ee0b923dc, 0xba4174c43a73a4d1, 0xbdc74105146a5162, 0xba47d0740e56625c, 0x3de33cde4f35d941, 0xba72a344950797c6, 0xbdf760fe7b666392, 0x3a9a8b77c82ed644, 0x3e063a70fd66d485, 0x3aa6b87715649d6d, 0xbe11324f6fb6dfa1, 0x3ab3fc045e39915f, 0x3e163a31a36b815c, 0xba502dec9bc1a700, 0xbe18724ca8970b91, 0x3e172e290891e5de, 0xbe131fc03858aab1, 0x3e0b9e8b0e7fa253, 0xbe01821a002637bd, 0x3df37ba5f3fba5eb, 0xbde3578bf23dc654, 0x3dcfdaf2015d7b54, 0x3df7f6a435069067, 0x3d99d14ee557ec62, 0xbe555f4c743ee571 ], + [ 0x3feffffffffff845, 0x3c7b0edc5a89ab8e, 0x3d846897d4b69fc6, 0x3a2a74852415bb49, 0xbdaa77a4e7dcd735, 0xba434edb43ab7de6, 0x3dc67543695dcc12, 0xba329ae577004af8, 0xbddc05c1e2fc710e, 0x3a5dbbf42d2537a8, 0x3deb639419fedf8e, 0xba8ed72eb9e7a59e, 0xbdf5cfd7eb9bfe87, 0xba7e97db27125fc0, 0x3dfd11578959ba45, 0xba8c0635ac2b5768, 0xbe0082f9e9f7eb37, 0x3e00354ceadad8b3, 0xbdfbc2dee0154fc6, 0x3df4e11efdc66eae, 0xbdebb357c0253f64, 0x3de035f9889bc29c, 0xbdc8e7bdb10b7441, 0x3dbe364571102661, 0xbe212cffcf49a2e8, 0x3d8ee9362bcfec26, 0x3e7cc5b58dd85301 ], + [ 0x3feffffffffffdf8, 0xbc8dcf8b10ff973b, 0x3d65f8b87a31bd85, 0x39d65b265455b658, 0xbd8d2e55024a0fb5, 0x3a2444e1d84cea02, 0x3da9612cc225df4b, 0xba4c784edb664ce7, 0xbdc03ee5f38b9b4d, 0xba691ca8efa41a30, 0x3dd04f2f71e2e96b, 0xba633f36a4e51350, 0xbddab7099f99ced9, 0xba54af7a67f2110c, 0x3de2554b8f609fd1, 0xba729e641eb44218, 0xbde57c87529ca968, 0x3de5cd182c967671, 0xbde3580a2517d57a, 0x3dde3be72b1be982, 0xbdd4e9908689ad08, 0x3dc9a61979d3395b, 0xbdb7b826aadd1c89, 0x3daad3a9fc4a0d1e, 0xbe00e9325ed20970, 0x3d80722198ff452c, 0x3e5c2ef85611aa11 ], + [ 0x3fefffffffffff7b, 0x3c800fa07f7fb612, 0x3d46ed2f2515e933, 0x39d2bc1802a42b92, 0xbd6f2a6c1669c901, 0xba07b3e174cc1840, 0x3d8bc42ba38a13f8, 0x3a2460463d59d3df, 0xbda2391e135afae4, 0xba3bd08c8c5f7b18, 0x3db2c6c24550f64f, 0xba3fdc861a487110, 0xbdbf9a3c1b0d63ec, 0xba5843dc8d9ad3d5, 0x3dc6502546ab341a, 0x3a645f812e48eb98, 0xbdcaf223186006d1, 0x3dcc388dd1764f41, 0xbdc9e65a242b52aa, 0x3dc4fcd2787781eb, 0xbdbe3cbdb20a48d6, 0x3db35639e9fcd410, 0xbd55b8e97774b2c9, 0x3d966ffe6a100bc9, 0xbe15706c390c113e, 0x3d6ff0d11cf61949, 0x3e72054de347e3f8 ], + [ 0x3fefffffffffffdf, 0x3c75669e670f914c, 0x3d272fd93e036cdc, 0x39b1c553d12fbbd0, 0xbd501f450d1e61b2, 0x39cbed807e60c078, 0x3d6d68fb81b2ed89, 0x39dc7ea3c4444cc0, 0xbd83c706aa4d2328, 0x3a2d6d2d51dd414d, 0x3d94e6479565838e, 0x3a350580f36c14c1, 0xbda20e9eb83b3dd9, 0xba104b6334a32fd0, 0x3daa35b9d2fcac80, 0x3a1c07c6978bf2f0, 0xbdb04a134f6e3dcb, 0x3db196579f27ddbe, 0xbdb0ab97aa74c700, 0x3dabf68355f542b1, 0xbda49da25a547134, 0x3d9bd64993a3958e, 0xbdc1193990186399, 0x3d81c0e98335ae18, 0x3e2e08edb685494a, 0x3d5cb9fcc058465b, 0xbe894cacccfb8964 ], + [ 0x3feffffffffffff8, 0x3c70160ef15c497e, 0x3d06ba91ac734786, 0xb9af81d6fa69b5b2, 0xbd3028a39099f4db, 0xb9c83ed68de15404, 0x3d4e292863e1795e, 0xb9db292e812abb68, 0xbd64c4e690fbdd14, 0xba080991e1d4ef25, 0x3d767e6e5ac60fd1, 0x3a01d2ca68dcf0e8, 0xbd83f00d80afa00c, 0xba23e174dc7225ac, 0x3d8db88ee63eb28a, 0x3a28abd97527892f, 0xbd92fe58a1f19368, 0x3d951dbeae22a5c8, 0xbd94a4d54823e0fc, 0x3d91e432d674cfba, 0xbd8b001e26c6e764, 0x3d8328ce695259fe, 0xbdb4e492cf7d4f4c, 0x3d6aaa77d339dc00, 0x3e2366538db382e5, 0x3d4826ad7d581503, 0xbe8056e0810b14da ], + [ 0x3feffffffffffffe, 0x3c759ab24e589a30, 0x3ce5982008db1304, 0xb981cf9bda64b38a, 0xbd0f610e8cde57ac, 0xb99884dcd86f98c8, 0x3d2df2dac2f2d47f, 0xb997f27bf279d988, 0xbd451b17f95fc0b4, 0xb9e063e04485c3e7, 0x3d576996ddc975d7, 0xb9e21489d6648428, 0xbd6546155a972b18, 0xb9b9d3fb518aa7c0, 0x3d70456ed89c4f24, 0x3a1eee772fc32c5e, 0xbd755d6295aa388a, 0x3d786ead99977388, 0xbd789b3d387efa6e, 0x3d76011e175e64f8, 0xbd70cd70515af47b, 0x3d69402199dfdde7, 0xbda806743bc32b08, 0x3d530e561550364a, 0x3e170093985e2c1b, 0x3d331999a27ace63, 0xbe735f54db0f4dbc ], + [ 0x3ff0000000000000, 0xbc8a6d7d18831888, 0x3cc3e296303b2297, 0x39668cf648cfed1c, 0xbced8456ef97c744, 0x398fcded17005500, 0x3d0ccb92e6c24c8d, 0xb9aa704dc202cff2, 0xbd24c1aa8cf1229b, 0x39c652efa61e4ec2, 0x3d37918b6b83c0fb, 0x39b2fb01fb8836dc, 0xbd45f073659de44d, 0xb9e9ceb48a2d1931, 0x3d5134d070b5921e, 0x39d9af3038fcc184, 0xbd5730a2938c09dd, 0x3d5b4091041f5905, 0xbd5c3c44ab8c8421, 0x3d5a06b4f4c3044d, 0xbd5704f511555fe7, 0x3d4fe51fcfc1acba, 0x3d95e7229a07e7cd, 0x3d39f8121f6c3146, 0xbe0692b2f9b3f445, 0x3d1c8c34f73d3823, 0x3e6301e540260d52 ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,960 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::dd_fmla; +use crate::double_double::DoubleDouble; +use crate::err::erf::{Erf, erf_accurate, erf_fast}; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1, ldexp}; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +static ASYMPTOTIC_POLY: [[u64; 13]; 6] = [ + [ + 0x3fe20dd750429b6d, + 0x3c61a1feb75a48a8, + 0xbfd20dd750429b6c, + 0x3fdb14c2f863e403, + 0xbff0ecf9db3af35d, + 0x400d9eb53ca6eeed, + 0xc030a945830d95c8, + 0x4056e8a963e2f1f5, + 0xc0829b7ccc8f396f, + 0x40b15e716e83c27e, + 0xc0e1cfdcfbcaf22a, + 0x4111986cc7a7e8fe, + 0xc1371f7540590a91, + ], + [ + 0x3fe20dd750429ae7, + 0x3c863da89e801fd4, + 0xbfd20dd750400795, + 0x3fdb14c2f57c490c, + 0xbff0ecf95c8c9014, + 0x400d9e981f2321ef, + 0xc030a81482de1506, + 0x4056d662420a604b, + 0xc08233c96fff7772, + 0x40af5d62018d3e37, + 0xc0d9ae55e9554450, + 0x410052901e10d139, + 0xc1166465df1385f0, + ], + [ + 0x3fe20dd75041e3fc, + 0xbc7c9b491c4920fc, + 0xbfd20dd74e5f1526, + 0x3fdb14c1d35a40e0, + 0xbff0ecdecd30e86b, + 0x400d9b4e7f725263, + 0xc030958b5ca8fb39, + 0x40563e3179bf609c, + 0xc0806bbd1cd2d0fd, + 0x40a7b66eb6d1d2f2, + 0xc0cce5a4b1afab75, + 0x40e8b5c6ae6f773c, + 0xc0f5475860326f86, + ], + [ + 0x3fe20dd75025cfe9, + 0x3c55a92eef32fb20, + 0xbfd20dd71eb9d4e7, + 0x3fdb14af4c25db28, + 0xbff0ebc78a22b3d8, + 0x400d85287a0b3399, + 0xc03045f751e5ca1d, + 0x4054a0d87ddea589, + 0xc07ac6a0981d1eee, + 0x409f44822f567956, + 0xc0bcba372de71349, + 0x40d1a4a19f550ca4, + 0xc0d52a580455ed79, + ], + [ + 0x3fe20dd74eb31d84, + 0xbc439c4054b7c090, + 0xbfd20dd561af98c4, + 0x3fdb1435165d9df1, + 0xbff0e6b60308e940, + 0x400d3ce30c140882, + 0xc02f2083e404c299, + 0x40520f113d89b42a, + 0xc0741433ebd89f19, + 0x4092f35b6a3154f6, + 0xc0ab020a4313cf3b, + 0x40b90f07e92da7ee, + 0xc0b6565e1d7665c3, + ], + [ + 0x3fe20dd744b3517b, + 0xbc6f77ab25e01ab4, + 0xbfd20dcc62ec4024, + 0x3fdb125bfa4f66c1, + 0xbff0d80e65381970, + 0x400ca11fbcfa65b2, + 0xc02cd9eaffb88315, + 0x404e010db42e0da7, + 0xc06c5c85250ef6a3, + 0x4085e118d9c1eeaf, + 0xc098d74be13d3d30, + 0x40a211b1b2b5ac83, + 0xc09900be759fc663, + ], +]; + +static ASYMPTOTIC_POLY_ACCURATE: [[u64; 30]; 10] = [ + [ + 0x3fe20dd750429b6d, + 0x3c61ae3a912b08f0, + 0xbfd20dd750429b6d, + 0xbc51ae34c0606d68, + 0x3fdb14c2f863e924, + 0xbc796c0f4c848fc8, + 0xbff0ecf9db3e71b6, + 0x3c645d756bd288b0, + 0x400d9eb53fad4672, + 0xbcac61629de9adf2, + 0xc030a945f3d147ea, + 0x3cb8fec5ad7ece20, + 0x4056e8c02f27ca6d, + 0xc0829d1c21c363e0, + 0x40b17349b70be627, + 0xc0e28a6bb4686182, + 0x411602d1662523ca, + 0xc14ccae7625c4111, + 0x4184237d064f6e0d, + 0xc1bb1e5466ca3a2f, + 0x41e90ae06a0f6cc1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd750429b6d, + 0x3c61adaa62435c10, + 0xbfd20dd750429b6d, + 0xbc441516126827c8, + 0x3fdb14c2f863e90b, + 0x3c7a535780ba5ed4, + 0xbff0ecf9db3e65d6, + 0xbc9089edde27ad07, + 0x400d9eb53fa52f20, + 0xbcabc9737e9464ac, + 0xc030a945f2cd7621, + 0xbcc589f28b700332, + 0x4056e8bffd7e194e, + 0xc0829d18716876e2, + 0x40b17312abe18250, + 0xc0e287e73592805c, + 0x4115ebf7394a39c1, + 0xc14c2f14d46d0cf9, + 0x4182af3d256f955e, + 0xc1b7041659ebd7aa, + 0x41e6039c232e2f71, + 0xc2070ca15c5a07cb, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd750429b6d, + 0x3c5d3c35b5d37410, + 0xbfd20dd750429b56, + 0xbc7c028415f6f81b, + 0x3fdb14c2f863c1cf, + 0x3c51bb0de6470dbc, + 0xbff0ecf9db33c363, + 0x3c80f8068459eb16, + 0x400d9eb53b9ce57b, + 0x3ca20cce33e7d84a, + 0xc030a945aa2ec4fa, + 0xbcdf6e0fcd7c6030, + 0x4056e8b824d2bfaa, + 0xc0829cc372a6d0b0, + 0x40b1703a99ddd429, + 0xc0e2749f9a267cc6, + 0x4115856a17271849, + 0xc14a8bcb4ba9753f, + 0x418035dcce882940, + 0xc1b1e5d8c5e6e043, + 0x41dfe3b4f365386e, + 0xc20398fdef2b98fe, + 0x42184234d4f4ea12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd750429b6a, + 0x3c8ae622b765e9fd, + 0xbfd20dd750428f0e, + 0x3c703c6c67d69513, + 0x3fdb14c2f8563e8e, + 0x3c6766a6bd7aa89c, + 0xbff0ecf9d8dedd48, + 0x3c90af52e90336e3, + 0x400d9eb4aad086fe, + 0x3ca640d371d54a19, + 0xc030a93f1d01cfe0, + 0xbcc68dbd8d9c522c, + 0x4056e842e9fd5898, + 0xc08299886ef1fb80, + 0x40b15e0f0162c9a0, + 0xc0e222dbc6b04cd8, + 0x411460268db1ebdf, + 0xc1474f53ce065fb3, + 0x417961ca8553f870, + 0xc1a8788395d13798, + 0x41d35e37b25d0e81, + 0xc1f707b7457c8f5e, + 0x4211ff852df1c023, + 0xc21b75d0ec56e2cd, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd750429a8f, + 0xbc766d8dda59bcea, + 0xbfd20dd7503fdbab, + 0x3c6707bdffc2b3fe, + 0x3fdb14c2f6526025, + 0xbc27fa4bb9541140, + 0xbff0ecf99c417d45, + 0xbc9748645ef7af94, + 0x400d9eaa9c712a7d, + 0x3ca79e478994ebb4, + 0xc030a8ef11fbf141, + 0x3cbb5c72d69f8954, + 0x4056e4653e0455b1, + 0xc08286909448e6cf, + 0x40b113424ce76821, + 0xc0e1346d859e76de, + 0x4111f9f6cf2293bf, + 0xc14258e6e3b337db, + 0x41714029ecd465fb, + 0xc19c530df5337a6f, + 0x41c34bc4bbccd336, + 0xc1e4a37c52641688, + 0x420019707cec2974, + 0xc21031fe736ea169, + 0x420f6b3003de3ddf, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd75042756b, + 0x3c84ad9178b56910, + 0xbfd20dd74feda9e8, + 0xbc78141c70bbc8d6, + 0x3fdb14c2cb128467, + 0xbc709aebaa106821, + 0xbff0ecf603921a0b, + 0x3c97d3cb5bceaf0b, + 0x400d9e3e1751ca59, + 0x3c76622ae5642670, + 0xc030a686af57f547, + 0x3cc083b320aff6b6, + 0x4056cf0b6c027326, + 0xc0823afcb69443d3, + 0x40b03ab450d9f1b9, + 0xc0de74cdb76bcab4, + 0x410c671b60e607f1, + 0xc138f1376d324ce4, + 0x4163b64276234676, + 0xc18aff0ce13c5a8e, + 0x41aef20247251e87, + 0xc1cc9f5662f721f6, + 0x41e4687858e185e1, + 0xc1f4fa507be073c2, + 0x41fb99ac35ee4acc, + 0xc1f16cb585ee3fa9, + 0, + 0, + 0, + 0, + ], + [ + 0x3fe20dd7503e730d, + 0x3c84e524a098a467, + 0xbfd20dd7498fa6b2, + 0x3c260a4e27751c80, + 0x3fdb14c061bd2a0c, + 0x3c695a8f847d2fc2, + 0xbff0ecd0f11b8c7d, + 0xbc94126deea76061, + 0x400d9b1344463548, + 0x3cafe09a4eca9b0e, + 0xc030996ea52a87ed, + 0xbca924f920db26c0, + 0x40567a2264b556b0, + 0xc0815dfc2c86b6b5, + 0x40accc291b62efe4, + 0xc0d81375a78e746a, + 0x41033a6f15546329, + 0xc12c1e9dc1216010, + 0x4152397ea3d43fda, + 0xc174661e5b2ea512, + 0x4193412367ca5d45, + 0xc1ade56b9d7f37c4, + 0x41c2851d9722146d, + 0xc1d19027baf0c3fe, + 0x41d7e7b8b6ab58ac, + 0xc1d4c446d56aaf22, + 0x41c1492190400505, + 0, + 0, + 0, + ], + [ + 0x3fe20dd74ff10852, + 0x3c8a32f26deff875, + 0xbfd20dd6f06c491c, + 0x3c770c16e1793358, + 0x3fdb14a7d5e7fd4a, + 0x3c7479998b54db5b, + 0xbff0ebbdb3889c5f, + 0xbc759b853e11369c, + 0x400d89dd249d7ef8, + 0xbc84b5edf0c8c314, + 0xc0306526fb386114, + 0xbc840d04eed7c7e0, + 0x40557ff657e429ce, + 0xc07ef63e90d38630, + 0x40a6d4f34c4ea3da, + 0xc0d04542b9e36a54, + 0x40f577bf19097738, + 0xc119702fe47c736d, + 0x413a7ae12b54fdc6, + 0xc157ca3f0f7c4fa9, + 0x417225d983963cbf, + 0xc1871a6eac612f9e, + 0x4198086324225e1e, + 0xc1a3de68670a7716, + 0x41a91674de4dcbe9, + 0xc1a6b44cc15b76c2, + 0x419a36dae0f30d80, + 0xc17cffc1747ea3dc, + 0, + 0, + ], + [ + 0x3fe20dd74ba8f300, + 0xbc59dd256871d210, + 0xbfd20dd3593675bc, + 0x3c7ec0e7ffa91ad9, + 0x3fdb13eef86a077a, + 0xbc74fb5d78d411b8, + 0xbff0e5cf52a11f3a, + 0xbc851f36c779dc8c, + 0x400d4417a08b39d5, + 0x3c91be9fb5956638, + 0xc02f91b9f6ce80c3, + 0xbccc9c99dd42829c, + 0x405356439f45bb43, + 0xc078c0ca12819b48, + 0x409efcad2ecd6671, + 0xc0c21b0af6fc1039, + 0x40e327d215ee30c9, + 0xc101fabda96167b0, + 0x411d82e4373b315d, + 0xc134ed9e2ff591e9, + 0x41495c85dcd8eab5, + 0xc159f016f0a3d62a, + 0x41660e89d918b96f, + 0xc16e97be202cba64, + 0x4170d8a081619793, + 0xc16c5422b4fcfc65, + 0x4161131a9dc6aed1, + 0xc14a457d9dced257, + 0x4123605e980e8b86, + 0, + ], + [ + 0x3fe20dd7319d4d25, + 0x3c82b02992c3b7ab, + 0xbfd20dc29c13ab1b, + 0xbc7d78d79b4ad767, + 0x3fdb115a57b5ab13, + 0xbc6aa8c45be0aa2e, + 0xbff0d58ec437efd7, + 0xbc5994f00a15e850, + 0x400cb1742e229f23, + 0xbca8000471d54399, + 0xc02d99a5edf7b946, + 0xbcbaf76ed7e35cde, + 0x4050a8b71058eb28, + 0xc072d88289da5bfc, + 0x40943ddf24168edb, + 0xc0b3e9dfc38b6d1a, + 0x40d18d4df97ab3df, + 0xc0eb550fc62dcab5, + 0x41029cb71f116ed1, + 0xc115fc9cc4e854e3, + 0x41265915fd0567b1, + 0xc1335eb5fca0e46d, + 0x413c5261ecc0d789, + 0xc14138932dc4eafc, + 0x414117d4eb18facd, + 0xc13af96163e35eca, + 0x4130454a3a63c766, + 0xc11c2ebc1d39b44a, + 0x40ff3327698e0e6b, + 0xc0d094febc3dff35, + ], +]; + +// Approximation for the fast path of exp(z) for z=zh+zl, +// with |z| < 0.000130273 < 2^-12.88 and |zl| < 2^-42.6 +// (assuming x^y does not overflow or underflow) +#[inline] +fn q_1(z_dd: DoubleDouble) -> DoubleDouble { + const C: [u64; 5] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555995d37, + 0x3fa55555558489dc, + ]; + let z = z_dd.to_f64(); + let mut q = dd_fmla(f64::from_bits(C[4]), z_dd.hi, f64::from_bits(C[3])); + + q = dd_fmla(q, z, f64::from_bits(C[2])); + + let mut v = DoubleDouble::from_exact_add(f64::from_bits(C[1]), q * z); + v = DoubleDouble::quick_mult(z_dd, v); + DoubleDouble::f64_add(f64::from_bits(C[0]), v) +} + +#[inline] +fn exp_1(x: DoubleDouble) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); /* |INVLOG2-2^12/log(2)| < 2^-43.4 */ + let k = (x.hi * INVLOG2).cpu_round_ties_even(); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3bbabc9e3b39803f), + f64::from_bits(0x3f262e42fefa39ef), + ); + let k_dd = DoubleDouble::quick_f64_mult(k, LOG2_DD); + let mut y_dd = DoubleDouble::from_exact_add(x.hi - k_dd.hi, x.lo); + y_dd.lo -= k_dd.lo; + + let ki: i64 = k as i64; /* Note: k is an integer, this is just a conversion. */ + let mi = (ki >> 12).wrapping_add(0x3ff); + let i2: i64 = (ki >> 6) & 0x3f; + let i1: i64 = ki & 0x3f; + let t1 = DoubleDouble::new( + f64::from_bits(EXP_REDUCE_T0[i2 as usize].0), + f64::from_bits(EXP_REDUCE_T0[i2 as usize].1), + ); + let t2 = DoubleDouble::new( + f64::from_bits(EXP_REDUCE_T1[i1 as usize].0), + f64::from_bits(EXP_REDUCE_T1[i1 as usize].1), + ); + let mut v = DoubleDouble::quick_mult(t2, t1); + let q = q_1(y_dd); + v = DoubleDouble::quick_mult(v, q); + + let scale = f64::from_bits((mi as u64) << 52); + v.hi *= scale; + v.lo *= scale; + v +} + +struct Exp { + e: i32, + result: DoubleDouble, +} + +fn exp_accurate(x_dd: DoubleDouble) -> Exp { + static E2: [u64; 28] = [ + 0x3ff0000000000000, + 0xb960000000000000, + 0x3ff0000000000000, + 0xb9be200000000000, + 0x3fe0000000000000, + 0x3a03c00000000000, + 0x3fc5555555555555, + 0x3c655555555c78d9, + 0x3fa5555555555555, + 0x3c455555545616e2, + 0x3f81111111111111, + 0x3c011110121fc314, + 0x3f56c16c16c16c17, + 0xbbef49e06ee3a56e, + 0x3f2a01a01a01a01a, + 0x3b6b053e1eeab9c0, + 0x3efa01a01a01a01a, + 0x3ec71de3a556c733, + 0x3e927e4fb7789f66, + 0x3e5ae64567f54abe, + 0x3e21eed8eff8958b, + 0x3de6124613837216, + 0x3da93974aaf26a57, + 0x3d6ae7f4fd6d0bd9, + 0x3d2ae7e982620b25, + 0x3ce94e4ca59460d8, + 0x3ca69a2a4b7ef36d, + 0x3c6abfe1602308c9, + ]; + const LOG2INV: f64 = f64::from_bits(0x3ff71547652b82fe); + let k: i32 = unsafe { + (x_dd.hi * LOG2INV) + .cpu_round_ties_even() + .to_int_unchecked::() + }; + + const LOG2_H: f64 = f64::from_bits(0x3fe62e42fefa39ef); + /* we approximate LOG2Lacc ~ log(2) - LOG2H with 38 bits, so that + k*LOG2Lacc is exact (k has at most 11 bits) */ + const LOG2_L: f64 = f64::from_bits(0x3c7abc9e3b398000); + const LOG2_TINY: f64 = f64::from_bits(0x398f97b57a079a19); + let yh = dd_fmla(-k as f64, LOG2_H, x_dd.hi); + /* since |xh+xl| >= 2.92 we have |k| >= 4; + (|k|-1/2)*log(2) <= |x| <= (|k|+1/2)*log(2) thus + 1-1/(2|k|) <= |x/(k*log(2))| <= 1+1/(2|k|) thus by Sterbenz theorem + yh is exact too */ + let mut t = DoubleDouble::from_full_exact_add(-k as f64 * LOG2_L, x_dd.lo); + let mut y_dd = DoubleDouble::from_exact_add(yh, t.hi); + y_dd.lo = dd_fmla(-k as f64, LOG2_TINY, y_dd.lo + t.lo); + /* now yh+yl approximates xh + xl - k*log(2), and we approximate p(yh+yl) + in h + l */ + /* Since |xh| <= 742, we assume |xl| <= ulp(742) = 2^-43. Then since + |k| <= round(742/log(2)) = 1070, |yl| <= 1070*LOG2L + 2^-42 < 2^-42.7. + Since |yh| <= log(2)/2, the contribution of yl is negligible as long + as |i*p[i]*yh^(i-1)*yl| < 2^-104, which holds for i >= 16. + Thus for coefficients of degree 16 or more, we don't take yl into account. + */ + let mut h = f64::from_bits(E2[19 + 8]); // degree 19 + for a in (16..=18).rev() { + h = dd_fmla(h, y_dd.hi, f64::from_bits(E2[a + 8])); // degree i + } + /* degree 15: h*(yh+yl)+E2[15 + 8] */ + t = DoubleDouble::from_exact_mult(h, y_dd.hi); + t.lo = dd_fmla(h, y_dd.lo, t.lo); + let mut v = DoubleDouble::from_exact_add(f64::from_bits(E2[15 + 8]), t.hi); + v.lo += t.lo; + for a in (8..=14).rev() { + /* degree i: (h+l)*(yh+yl)+E2[i+8] */ + t = DoubleDouble::quick_mult(v, y_dd); + v = DoubleDouble::from_exact_add(f64::from_bits(E2[a + 8]), t.hi); + v.lo += t.lo; + } + for a in (0..=7).rev() { + /* degree i: (h+l)*(yh+yl)+E2[2i]+E2[2i+1] */ + t = DoubleDouble::quick_mult(v, y_dd); + v = DoubleDouble::from_exact_add(f64::from_bits(E2[2 * a]), t.hi); + v.lo += t.lo + f64::from_bits(E2[2 * a + 1]); + } + + Exp { e: k, result: v } +} + +#[cold] +fn erfc_asympt_accurate(x: f64) -> f64 { + /* subnormal exceptions */ + if x == f64::from_bits(0x403a8f7bfbd15495) { + return dd_fmla( + f64::from_bits(0x0000000000000001), + -0.25, + f64::from_bits(0x000667bd620fd95b), + ); + } + let u_dd = DoubleDouble::from_exact_mult(x, x); + let exp_result = exp_accurate(DoubleDouble::new(-u_dd.lo, -u_dd.hi)); + + /* compute 1/x as double-double */ + let yh = 1.0 / x; + /* Newton's iteration for 1/x is y -> y + y*(1-x*y) */ + let yl = yh * dd_fmla(-x, yh, 1.0); + // yh+yl approximates 1/x + static THRESHOLD: [u64; 10] = [ + 0x3fb4500000000000, + 0x3fbe000000000000, + 0x3fc3f00000000000, + 0x3fc9500000000000, + 0x3fcf500000000000, + 0x3fd3100000000000, + 0x3fd7100000000000, + 0x3fdbc00000000000, + 0x3fe0b00000000000, + 0x3fe3000000000000, + ]; + let mut i = 0usize; + while i < THRESHOLD.len() && yh > f64::from_bits(THRESHOLD[i]) { + i += 1; + } + let p = ASYMPTOTIC_POLY_ACCURATE[i]; + let mut u_dd = DoubleDouble::from_exact_mult(yh, yh); + u_dd.lo = dd_fmla(2.0 * yh, yl, u_dd.lo); + /* the polynomial p has degree 29+2i, and its coefficient of largest + degree is p[14+6+i] */ + let mut z_dd = DoubleDouble::new(0., f64::from_bits(p[14 + 6 + i])); + for a in (13..=27 + 2 * i).rev().step_by(2) { + /* degree j: (zh+zl)*(uh+ul)+p[(j-1)/2+6]] */ + let v = DoubleDouble::quick_mult(z_dd, u_dd); + z_dd = DoubleDouble::from_full_exact_add(f64::from_bits(p[(a - 1) / 2 + 6]), v.hi); + z_dd.lo += v.lo; + } + for a in (1..=11).rev().step_by(2) { + let v = DoubleDouble::quick_mult(z_dd, u_dd); + z_dd = DoubleDouble::from_full_exact_add(f64::from_bits(p[a - 1]), v.hi); + z_dd.lo += v.lo + f64::from_bits(p[a]); + } + + /* multiply by yh+yl */ + u_dd = DoubleDouble::quick_mult(z_dd, DoubleDouble::new(yl, yh)); + /* now uh+ul approximates p(1/x), i.e., erfc(x)*exp(x^2) */ + /* now multiply (uh+ul)*(eh+el), after normalizing uh+ul to reduce the + number of exceptional cases */ + u_dd = DoubleDouble::from_exact_add(u_dd.hi, u_dd.lo); + let v = DoubleDouble::quick_mult(u_dd, exp_result.result); + /* multiply by 2^e */ + /* multiply by 2^e */ + let mut res = ldexp(v.to_f64(), exp_result.e); + if res < f64::from_bits(0x0010000000000000) { + /* for erfc(x) in the subnormal range, we have to perform a special + rounding */ + let mut corr = v.hi - ldexp(res, -exp_result.e); + corr += v.lo; + /* add corr*2^e */ + res += ldexp(corr, exp_result.e); + } + res +} + +#[cold] +fn erfc_accurate(x: f64) -> f64 { + if x < 0. { + let mut v_dd = erf_accurate(-x); + let t = DoubleDouble::from_exact_add(1.0, v_dd.hi); + v_dd.hi = t.hi; + v_dd.lo += t.lo; + return v_dd.to_f64(); + } else if x <= f64::from_bits(0x3ffb59ffb450828c) { + // erfc(x) >= 2^-6 + let mut v_dd = erf_accurate(x); + let t = DoubleDouble::from_exact_add(1.0, -v_dd.hi); + v_dd.hi = t.hi; + v_dd.lo = t.lo - v_dd.lo; + return v_dd.to_f64(); + } + // now 0x1.b59ffb450828cp+0 < x < 0x1.b39dc41e48bfdp+4 + erfc_asympt_accurate(x) +} + +/* Fast path for 0x1.713786d9c7c09p+1 < x < 0x1.b39dc41e48bfdp+4, +using the asymptotic formula erfc(x) = exp(-x^2) * p(1/x)*/ +fn erfc_asympt_fast(x: f64) -> Erf { + /* for x >= 0x1.9db1bb14e15cap+4, erfc(x) < 2^-970, and we might encounter + underflow issues in the computation of l, thus we delegate this case + to the accurate path */ + if x >= f64::from_bits(0x4039db1bb14e15ca) { + return Erf { + err: 1.0, + result: DoubleDouble::default(), + }; + } + + let mut u = DoubleDouble::from_exact_mult(x, x); + let e_dd = exp_1(DoubleDouble::new(-u.lo, -u.hi)); + + /* the assumptions from exp_1 are satisfied: + * a_mul ensures |ul| <= ulp(uh), thus |ul/uh| <= 2^-52 + * since |x| < 0x1.9db1bb14e15cap+4 we have + |ul| < ulp(0x1.9db1bb14e15cap+4^2) = 2^-43 */ + /* eh+el approximates exp(-x^2) with maximal relative error 2^-74.139 */ + + /* compute 1/x as double-double */ + let yh = 1.0 / x; + /* Assume 1 <= x < 2, then 0.5 <= yh <= 1, + and yh = 1/x + eps with |eps| <= 2^-53. */ + /* Newton's iteration for 1/x is y -> y + y*(1-x*y) */ + let yl = yh * dd_fmla(-x, yh, 1.0); + /* x*yh-1 = x*(1/x+eps)-1 = x*eps + with |x*eps| <= 2^-52, thus the error on the FMA is bounded by + ulp(2^-52.1) = 2^-105. + Now |yl| <= |yh| * 2^-52 <= 2^-52, thus the rounding error on + yh * __builtin_fma (-x, yh, 1.0) is bounded also by ulp(2^-52.1) = 2^-105. + From [6], Lemma 3.7, if yl was computed exactly, then yh+yl would differ + from 1/x by at most yh^2/theta^3*(1/x-yh)^2 for some theta in [yh,1/x] + or [1/x,yh]. + Since yh, 1/x <= 1, this gives eps^2 <= 2^-106. + Adding the rounding errors, we have: + |yh + yl - 1/x| <= 2^-105 + 2^-105 + 2^-106 < 2^-103.67. + For the relative error, since |yh| >= 1/2, this gives: + |yh + yl - 1/x| < 2^-102.67 * |yh+yl| + */ + const THRESHOLD: [u64; 6] = [ + 0x3fbd500000000000, + 0x3fc59da6ca291ba6, + 0x3fcbc00000000000, + 0x3fd0c00000000000, + 0x3fd3800000000000, + 0x3fd6300000000000, + ]; + let mut i = 0usize; + while i < THRESHOLD.len() && yh > f64::from_bits(THRESHOLD[i]) { + i += 1; + } + let p = ASYMPTOTIC_POLY[i]; + u = DoubleDouble::from_exact_mult(yh, yh); + /* Since |yh| <= 1, we have |uh| <= 1 and |ul| <= 2^-53. */ + u.lo = dd_fmla(2.0 * yh, yl, u.lo); + /* uh+ul approximates (yh+yl)^2, with absolute error bounded by + ulp(ul) + yl^2, where ulp(ul) is the maximal rounding error in + the FMA, and yl^2 is the neglected term. + Since |ul| <= 2^-53, ulp(ul) <= 2^-105, and since |yl| <= 2^-52, + this yields |uh + ul - yh^2| <= 2^-105 + 2^-104 < 2^-103.41. + For the relative error, since |(yh+yl)^2| >= 1/4: + |uh + ul - yh^2| < 2^-101.41 * |uh+ul|. + And relatively to 1/x^2: + yh + yl = 1/x * (1 + eps1) with |eps1| < 2^-102.67 + uh + ul = (yh+yl)^2 * (1 + eps2) with |eps2| < 2^-101.41 + This yields: + |uh + ul - 1/x| < 2^-100.90 * |uh+ul|. + */ + + /* evaluate p(uh+ul) */ + let mut zh: f64 = f64::from_bits(p[12]); // degree 23 + zh = dd_fmla(zh, u.hi, f64::from_bits(p[11])); // degree 21 + zh = dd_fmla(zh, u.hi, f64::from_bits(p[10])); // degree 19 + + /* degree 17: zh*(uh+ul)+p[i] */ + let mut v = DoubleDouble::quick_f64_mult(zh, u); + let mut z_dd = DoubleDouble::from_exact_add(f64::from_bits(p[9]), v.hi); + z_dd.lo += v.lo; + + for a in (3..=15).rev().step_by(2) { + v = DoubleDouble::quick_mult(z_dd, u); + z_dd = DoubleDouble::from_exact_add(f64::from_bits(p[((a + 1) / 2) as usize]), v.hi); + z_dd.lo += v.lo; + } + + /* degree 1: (zh+zl)*(uh+ul)+p[0]+p[1] */ + v = DoubleDouble::quick_mult(z_dd, u); + z_dd = DoubleDouble::from_exact_add(f64::from_bits(p[0]), v.hi); + z_dd.lo += v.lo + f64::from_bits(p[1]); + /* multiply by yh+yl */ + u = DoubleDouble::quick_mult(z_dd, DoubleDouble::new(yl, yh)); + /* now uh+ul approximates p(1/x) */ + /* now multiply (uh+ul)*(eh+el) */ + v = DoubleDouble::quick_mult(u, e_dd); + + /* Write y = 1/x. We have the following errors: + * the maximal mathematical error is: + |erfc(x)*exp(x^2) - p(y)| < 2^-71.804 * |p(y)| (for i=3) thus + |erfc(x) - exp(-x^2)*p(y)| < 2^-71.804 * |exp(-x^2)*p(y)| + * the error in approximating exp(-x^2) by eh+el: + |eh + el - exp(-x^2)| < 2^-74.139 * |eh + el| + * the fact that we evaluate p on yh+yl instead of 1/x + this error is bounded by |p'| * |yh+yl - 1/x|, where + |yh+yl - 1/x| < 2^-102.67 * |yh+yl|, and the relative + error is bounded by |p'/p| * |yh+yl - 1/x|. + Since the maximal value of |p'/p| is bounded by 27.2 (for i=0), + this yields 27.2 * 2^-102.67 < 2^-97.9 + * the rounding errors when evaluating p on yh+yl: this error is bounded + (relatively) by 2^-67.184 (for i=5), see analyze_erfc_asympt_fast() + in erfc.sage + * the rounding error in (uh+ul)*(eh+el): we assume this error is bounded + by 2^-80 (relatively) + This yields a global relative bound of: + (1+2^-71.804)*(1+2^-74.139)*(1+2^-97.9)*(1+2^-67.184)*(1+2^-80)-1 + < 2^-67.115 + */ + if v.hi >= f64::from_bits(0x044151b9a3fdd5c9) { + Erf { + err: f64::from_bits(0x3bbd900000000000) * v.hi, + result: v, + } /* 2^-67.115 < 0x1.d9p-68 */ + } else { + Erf { + result: v, + err: f64::from_bits(0x0010000000000000), + } // this overestimates 0x1.d9p-68 * h + } +} + +#[inline] +fn erfc_fast(x: f64) -> Erf { + if x < 0. + // erfc(x) = 1 - erf(x) = 1 + erf(-x) + { + let res = erf_fast(-x); + /* h+l approximates erf(-x), with relative error bounded by err, + where err <= 0x1.78p-69 */ + let err = res.err * res.result.hi; /* convert into absolute error */ + let mut t = DoubleDouble::from_exact_add(1.0, res.result.hi); + t.lo += res.result.lo; + // since h <= 2, the fast_two_sum() error is bounded by 2^-105*h <= 2^-104 + /* After the fast_two_sum() call, we have |t| <= ulp(h) <= ulp(2) = 2^-51 + thus assuming |l| <= 2^-51 after the cr_erf_fast() call, + we have |t| <= 2^-50 here, thus the rounding + error on t -= *l is bounded by ulp(2^-50) = 2^-102. + The absolute error is thus bounded by err + 2^-104 + 2^-102 + = err + 0x1.4p-102. + The maximal value of err here is for |x| < 0.0625, where cr_erf_fast() + returns 0x1.78p-69, and h=1/2, yielding err = 0x1.78p-70 here. + Adding 0x1.4p-102 is thus exact. */ + return Erf { + err: err + f64::from_bits(0x3994000000000000), + result: t, + }; + } else if x <= f64::from_bits(0x400713786d9c7c09) { + let res = erf_fast(x); + /* h+l approximates erf(x), with relative error bounded by err, + where err <= 0x1.78p-69 */ + let err = res.err * res.result.hi; /* convert into absolute error */ + let mut t = DoubleDouble::from_exact_add(1.0, -res.result.hi); + t.lo -= res.result.lo; + /* for x >= 0x1.e861fbb24c00ap-2, erf(x) >= 1/2, thus 1-h is exact + by Sterbenz theorem, thus t = 0 in fast_two_sum(), and we have t = -l + here, thus the absolute error is err */ + if x >= f64::from_bits(0x3fde861fbb24c00a) { + return Erf { err, result: t }; + } + /* for x < 0x1.e861fbb24c00ap-2, the error in fast_two_sum() is bounded + by 2^-105*h, and since h <= 1/2, this yields 2^-106. + After the fast_two_sum() call, we have |t| <= ulp(h) <= ulp(1/2) = 2^-53 + thus assuming |l| <= 2^-53 after the cr_erf_fast() call, + we have |t| <= 2^-52 here, thus the rounding + error on t -= *l is bounded by ulp(2^-52) = 2^-104. + The absolute error is thus bounded by err + 2^-106 + 2^-104 + The maximal value of err here is for x < 0.0625, where cr_erf_fast() + returns 0x1.78p-69, and h=1/2, yielding err = 0x1.78p-70 here. + Adding 0x1.4p-104 is thus exact. */ + return Erf { + err: err + f64::from_bits(0x3974000000000000), + result: t, + }; + } + /* Now THRESHOLD1 < x < 0x1.b39dc41e48bfdp+4 thus erfc(x) < 0.000046. */ + /* on a i7-8700 with gcc 12.2.0, for x in [THRESHOLD1,+5.0], + the average reciprocal throughput is about 111 cycles + (among which 20 cycles for exp_1) */ + erfc_asympt_fast(x) +} + +/// Complementary error function +/// +/// Max ulp 0.5 +pub fn f_erfc(x: f64) -> f64 { + let t: u64 = x.to_bits(); + let at: u64 = t & 0x7fff_ffff_ffff_ffff; + + if t >= 0x8000000000000000u64 + // x = -NaN or x <= 0 (excluding +0) + { + // for x <= -0x1.7744f8f74e94bp2, erfc(x) rounds to 2 (to nearest) + if t >= 0xc017744f8f74e94bu64 + // x = NaN or x <= -0x1.7744f8f74e94bp2 + { + if t >= 0xfff0000000000000u64 { + // -Inf or NaN + if t == 0xfff0000000000000u64 { + return 2.0; + } // -Inf + return x + x; // NaN + } + return black_box(2.0) - black_box(f64::from_bits(0x3c90000000000000)); // rounds to 2 or below(2) + } + + // for -9.8390953768041405e-17 <= x <= 0, erfc(x) rounds to 1 (to nearest) + if f64::from_bits(0xbc9c5bf891b4ef6a) <= x { + return dd_fmla(-x, f64::from_bits(0x3c90000000000000), 1.0); + } + } else + // x = +NaN or x >= 0 (excluding -0) + { + // for x >= 0x1.b39dc41e48bfdp+4, erfc(x) < 2^-1075: rounds to 0 or 2^-1074 + if at >= 0x403b39dc41e48bfdu64 + // x = NaN or x >= 0x1.b39dc41e48bfdp+4 + { + if at >= 0x7ff0000000000000u64 { + // +Inf or NaN + if at == 0x7ff0000000000000u64 { + return 0.0; + } // +Inf + return x + x; // NaN + } + return black_box(f64::from_bits(0x0000000000000001)) * black_box(0.25); // 0 or 2^-1074 wrt rounding + } + + // for 0 <= x <= 0x1.c5bf891b4ef6ap-55, erfc(x) rounds to 1 (to nearest) + if x <= f64::from_bits(0x3c8c5bf891b4ef6a) { + return dd_fmla(-x, f64::from_bits(0x3c90000000000000), 1.0); + } + } + + /* now -0x1.7744f8f74e94bp+2 < x < -0x1.c5bf891b4ef6ap-54 + or 0x1.c5bf891b4ef6ap-55 < x < 0x1.b39dc41e48bfdp+4 */ + + let result = erfc_fast(x); + + let left = result.result.hi + (result.result.lo - result.err); + let right = result.result.hi + (result.result.lo + result.err); + if left == right { + return left; + } + erfc_accurate(x) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_erfc() { + assert_eq!(f_erfc(1.0), 0.15729920705028513); + assert_eq!(f_erfc(0.5), 0.4795001221869535); + assert_eq!(f_erfc(0.000000005), 0.9999999943581042); + assert_eq!(f_erfc(-0.00000000000065465465423305), 1.0000000000007387); + assert!(f_erfc(f64::NAN).is_nan()); + assert_eq!(f_erfc(f64::INFINITY), 0.0); + assert_eq!(f_erfc(f64::NEG_INFINITY), 2.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfcx.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcx.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfcx.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcx.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,421 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::pow_exec::exp_dd_fast; + +#[inline] +fn core_erfcx(x: f64) -> DoubleDouble { + if x <= 8. { + // Rational approximant for erfcx generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 12] = [ + (0xbc836faeb9a312bb, 0x3ff000000000ee8e), + (0x3c91842f891bec6a, 0x4002ca20a78aaf8f), + (0x3c7916e8a1c30681, 0x4005e955f70aed5b), + (0x3cabad150d828d82, 0x4000646f5807ad07), + (0xbc6f482680d66d9c, 0x3ff1449e03ed381c), + (0xbc7188796156ae19, 0x3fdaa7e997e3b034), + (0xbc5c8af0642761e3, 0x3fbe836282058d4a), + (0xbc372829be2d072f, 0x3f99a2b2adc2ec05), + (0x3c020cc8b96000ab, 0x3f6e6cc3d120a955), + (0x3bdd138e6c136806, 0x3f3743d6735eaf13), + (0xbb9fbd22f0675122, 0x3ef1c1d36ebe29a2), + (0xb89093cc981c934c, 0xbc43c18bc6385c74), + ]; + + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = x2 * x2; + let x8 = x4 * x4; + + let e0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + x, + DoubleDouble::from_bit_pair(P[0]), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + x, + DoubleDouble::from_bit_pair(P[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + x, + DoubleDouble::from_bit_pair(P[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + x, + DoubleDouble::from_bit_pair(P[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + x, + DoubleDouble::from_bit_pair(P[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[11]), + x, + DoubleDouble::from_bit_pair(P[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + const Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc95d65be031374e, 0x400bd10c4fb1dbe5), + (0x3cb2d8f661db08a0, 0x4016a649ff973199), + (0x3ca32cbcfdc0ea93, 0x4016daab399c1ffc), + (0xbca2982868536578, 0x400fd61ab892d14c), + (0xbca2e29199e17fd9, 0x40001f56c4d495a3), + (0x3c412ce623a1790a, 0x3fe852b582135164), + (0x3c61152eaf4b0dc5, 0x3fcb760564da7cde), + (0xbc1b57ff91d81959, 0x3fa6e146988df835), + (0x3c17183d8445f19a, 0x3f7b06599b5e912f), + (0xbbd0ada61b85ff98, 0x3f449e39467b73d0), + (0xbb658d84fc735e67, 0x3eff794442532b51), + ]; + + let e0 = DoubleDouble::mul_f64_add_f64( + DoubleDouble::from_bit_pair(Q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[3]), + x, + DoubleDouble::from_bit_pair(Q[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[5]), + x, + DoubleDouble::from_bit_pair(Q[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + x, + DoubleDouble::from_bit_pair(Q[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[9]), + x, + DoubleDouble::from_bit_pair(Q[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[11]), + x, + DoubleDouble::from_bit_pair(Q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + return DoubleDouble::div(p_num, p_den); + } + + // for large x erfcx(x) ~ 1/sqrt(pi) / x * R(1/x) + const ONE_OVER_SQRT_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3c61ae3a914fed80, 0x3fe20dd750429b6d)); + let r = DoubleDouble::from_quick_recip(x); + // Rational approximant generated by Wolfram: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 9] = [ + (0xbb1d2ee37e46a4cd, 0x3ff0000000000000), + (0x3ca2e575a4ce3d30, 0x4001303ab00c8bac), + (0xbccf38381e5ee521, 0x4030a97aeed54c9f), + (0xbcc3a2842df0dd3d, 0x4036f7733c9fd2f9), + (0xbcfeaf46506f16ed, 0x4051c5f382750553), + (0x3ccbb9f5e11d176a, 0x404ac0081e0749e0), + (0xbcf374f8966ae2a5, 0x4052082526d99a5c), + (0x3cbb5530b924f224, 0x402feabbf6571c29), + (0xbcbcdd50a3ca4776, 0x40118726e1f2d204), + ]; + const Q: [(u64, u64); 9] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca2e4613c9e0017, 0x4001303ab00c8bac), + (0xbcce5f17cf14e51d, 0x4031297aeed54c9f), + (0xbcdf7e0fed176f92, 0x40380a76e7a09bb2), + (0x3cfc57b67a2797af, 0x4053bb22e04faf3e), + (0xbcd3e63b7410b46b, 0x404ff46317ae9483), + (0xbce122c15db2653f, 0x405925ef8a428c36), + (0x3ce174ebe3e52c8e, 0x4040f49acfe692e1), + (0xbcda0e267ce6e2e6, 0x40351a07878bfbd3), + ]; + let mut p_num = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[8]), + r, + DoubleDouble::from_bit_pair(P[7]), + ); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[0])); + + let mut p_den = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[8]), + r, + DoubleDouble::from_bit_pair(Q[7]), + ); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_add_f64(p_den, r, f64::from_bits(0x3ff0000000000000)); + + let v0 = DoubleDouble::quick_mult(ONE_OVER_SQRT_PI, r); + let v1 = DoubleDouble::div(p_num, p_den); + DoubleDouble::quick_mult(v0, v1) +} + +/// Scaled complementary error function (exp(x^2)*erfc(x)) +pub fn f_erfcx(x: f64) -> f64 { + let ux = x.to_bits().wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // x == NaN, x == inf, x == 0, |x| <= f64::EPSILON + if x.is_nan() { + return f64::NAN; + } + if x.to_bits().wrapping_shl(1) == 0 { + return 1.; + } + if x.is_infinite() { + return if x.is_sign_positive() { + 0. + } else { + f64::INFINITY + }; + } + + if ux <= 0x7888f5c28f5c28f6u64 { + // |x| <= 2.2204460492503131e-18 + return 1.; + } + + // |x| <= f64::EPSILON + use crate::common::f_fmla; + const M_TWO_OVER_SQRT_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc71ae3a914fed80, 0xbff20dd750429b6d)); + return f_fmla( + M_TWO_OVER_SQRT_PI.lo, + x, + f_fmla(M_TWO_OVER_SQRT_PI.hi, x, 1.), + ); + } + + if x.to_bits() >= 0xc03aa449ebc84dd6 { + // x <= -sqrt(709.783) ~ -26.6417 + return f64::INFINITY; + } + + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffffu64; + + if ax <= 0x3ff0000000000000u64 { + // |x| <= 1 + // Rational approximant generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 11] = [ + (0xbb488611350b1950, 0x3ff0000000000000), + (0xbc86ae482c7f2342, 0x3ff9c5d39e89602f), + (0x3c6702d70b807254, 0x3ff5a4c406d6468b), + (0x3c7fe41fc43cfed5, 0x3fe708e7f401bd0c), + (0x3c73a4a355172c6d, 0x3fd0d9a0c1a7126c), + (0x3c5f4c372faa270f, 0x3fb154722e30762e), + (0xbc04c0227976379e, 0x3f88ecebb62ce646), + (0xbbdc9ea151b9eb33, 0x3f580ea84143877b), + (0xbb6dae7001a91491, 0x3f1c3c5f95579b0a), + (0x3b6aca5e82c52897, 0x3ecea4db51968d9e), + (0x3a41c4edd175d2af, 0x3dbc0dccea7fc8ed), + ]; + + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = x2 * x2; + let x8 = x4 * x4; + + let q0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + x, + DoubleDouble::from_bit_pair(P[0]), + ); + let q1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + x, + DoubleDouble::from_bit_pair(P[2]), + ); + let q2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + x, + DoubleDouble::from_bit_pair(P[4]), + ); + let q3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + x, + DoubleDouble::from_bit_pair(P[6]), + ); + let q4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + x, + DoubleDouble::from_bit_pair(P[8]), + ); + + let r0 = DoubleDouble::mul_add(x2, q1, q0); + let r1 = DoubleDouble::mul_add(x2, q3, q2); + + let s0 = DoubleDouble::mul_add(x4, r1, r0); + let s1 = DoubleDouble::mul_add(x2, DoubleDouble::from_bit_pair(P[10]), q4); + let p_num = DoubleDouble::mul_add(x8, s1, s0); + + const Q: [(u64, u64); 11] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc7bae414cad99c8, 0x4005e9d57765fdce), + (0x3c8fa553bed15758, 0x400b8c670b3fbcda), + (0x3ca6c7ad610f1019, 0x4004f2ca59958153), + (0x3c87787f336cc4e6, 0x3ff55c267090315a), + (0xbc6ef55d4b2c4150, 0x3fde8b84b64b6f4e), + (0x3c570d63c94be3a3, 0x3fbf0d5e36017482), + (0x3c1882a745ef572e, 0x3f962f73633506c1), + (0xbc0850bb6fc82764, 0x3f65593e0dc46acd), + (0xbbb9dc0097d7d776, 0x3f290545603e2f94), + (0xbb776e5781e3889d, 0x3edb29c49d18cf89), + ]; + + let q0 = DoubleDouble::mul_f64_add_f64( + DoubleDouble::from_bit_pair(Q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let q1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[3]), + x, + DoubleDouble::from_bit_pair(Q[2]), + ); + let q2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[5]), + x, + DoubleDouble::from_bit_pair(Q[4]), + ); + let q3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + x, + DoubleDouble::from_bit_pair(Q[6]), + ); + let q4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[9]), + x, + DoubleDouble::from_bit_pair(Q[8]), + ); + + let r0 = DoubleDouble::mul_add(x2, q1, q0); + let r1 = DoubleDouble::mul_add(x2, q3, q2); + + let s0 = DoubleDouble::mul_add(x4, r1, r0); + let s1 = DoubleDouble::mul_add(x2, DoubleDouble::from_bit_pair(Q[10]), q4); + let p_den = DoubleDouble::mul_add(x8, s1, s0); + + let v = DoubleDouble::div(p_num, p_den); + return v.to_f64(); + } + + let mut erfcx_abs_x = core_erfcx(f64::from_bits(ax)); + if x < 0. { + // exp(x^2)erfc(-x) = 2*exp(x^2) - erfcx(|x|) + erfcx_abs_x = DoubleDouble::from_exact_add(erfcx_abs_x.hi, erfcx_abs_x.lo); + let d2x = DoubleDouble::from_exact_mult(x, x); + let expd2x = exp_dd_fast(d2x); + return DoubleDouble::mul_f64_add(expd2x, 2., -erfcx_abs_x).to_f64(); + } + erfcx_abs_x.to_f64() +} + +#[cfg(test)] +mod tests { + use crate::f_erfcx; + + #[test] + fn test_erfcx() { + assert_eq!(f_erfcx(2.2204460492503131e-18), 1.0); + assert_eq!(f_erfcx(-2.2204460492503131e-18), 1.0); + assert_eq!(f_erfcx(-f64::EPSILON), 1.0000000000000002); + assert_eq!(f_erfcx(f64::EPSILON), 0.9999999999999998); + assert_eq!(f_erfcx(-173.), f64::INFINITY); + assert_eq!(f_erfcx(-9.4324165432), 8.718049147018359e38); + assert_eq!(f_erfcx(9.4324165432), 0.059483265496416374); + assert_eq!(f_erfcx(-1.32432512125), 11.200579112797806); + assert_eq!(f_erfcx(1.32432512125), 0.3528722004785406); + assert_eq!(f_erfcx(-0.532431235), 2.0560589406595384); + assert_eq!(f_erfcx(0.532431235), 0.5994337293294584); + assert_eq!(f_erfcx(1e-26), 1.0); + assert_eq!(f_erfcx(-0.500000000023073), 1.952360489253639); + assert_eq!(f_erfcx(-175.), f64::INFINITY); + assert_eq!(f_erfcx(f64::INFINITY), 0.); + assert_eq!(f_erfcx(f64::NEG_INFINITY), f64::INFINITY); + assert!(f_erfcx(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfcxf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcxf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erfcxf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erfcxf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::exponents::core_expdf; +use crate::polyeval::{f_estrin_polyeval8, f_polyeval6}; + +#[inline] +fn core_erfcx(x: f32) -> f64 { + // x here is already always > 1 + let dx = x as f64; + if x < 8. { + // Rational approximant generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + dx, + f64::from_bits(0x3ff00000804c8f8f), + f64::from_bits(0x3ffb7307ea8fdbeb), + f64::from_bits(0x3ff7081ba7bc735c), + f64::from_bits(0x3fe767338b33532a), + f64::from_bits(0x3fce3c8288507fd6), + f64::from_bits(0x3fa7ca2cb4ae697f), + f64::from_bits(0x3f72b11b0dfb2348), + f64::from_bits(0xbd9f64f0c15c479b), + ); + let p_den = f_estrin_polyeval8( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4006c071e850132e), + f64::from_bits(0x400d30326bc347ee), + f64::from_bits(0x40060d8d56bada75), + f64::from_bits(0x3ff56643fc4580eb), + f64::from_bits(0x3fdb0e194e72a513), + f64::from_bits(0x3fb5154759b61be3), + f64::from_bits(0x3f8090b063cce524), + ); + return p_num / p_den; + } + // for large x erfcx(x) ~ 1/sqrt(pi) / x * R(1/x) + const ONE_OVER_SQRT_PI: f64 = f64::from_bits(0x3fe20dd750429b6d); + let r = 1. / dx; + // Rational approximant generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval6( + r, + f64::from_bits(0x3ff0000000000002), + f64::from_bits(0xbfd09caf2bb541c3), + f64::from_bits(0x40132238367ae454), + f64::from_bits(0xc0060bc62c3711b1), + f64::from_bits(0x40024a90d229158d), + f64::from_bits(0xc0013665d8ff3813), + ); + let p_den = f_polyeval6( + r, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfd09caf2bb5101d), + f64::from_bits(0x4015223836772f2c), + f64::from_bits(0xc00715911b5f5f5c), + f64::from_bits(0x4010b66411ec4e1f), + f64::from_bits(0xc00b325c767ed436), + ); + (r * ONE_OVER_SQRT_PI) * (p_num / p_den) +} + +/// Scaled complementary error function (exp(x^2)*erfc(x)) +/// +/// ulp 0.5 +pub fn f_erfcxf(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux <= 0x6499_999au32 { + // |x| == 0, |x| == inf, |x| == NaN, |x| <= 1.19209290e-08 + if ux <= 0x6499_999au32 { + // |x| == 0, |x| <= 1.19209290e-08 + return 1.; + } + if x.is_infinite() { + return if x.is_sign_positive() { + 0. + } else { + f32::INFINITY + }; + } + return f32::NAN; // x == NaN + } + let ax = x.to_bits() & 0x7fff_ffff; + if x <= -9.382415 { + // x <= -9.382415 + return f32::INFINITY; + } + if ax <= 0x34000000u32 { + // |x| < ulp(1) we use taylor series at 0 + // erfcx(x) ~ 1-(2 x)/Sqrt[\[Pi]]+x^2-(4 x^3)/(3 Sqrt[\[Pi]])+x^4/2-(8 x^5)/(15 Sqrt[\[Pi]])+O[x]^6 + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + const M_TWO_OVER_SQRT_PI: f32 = f32::from_bits(0xbf906ebb); + return f_fmlaf(x, M_TWO_OVER_SQRT_PI, 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::f_fmla; + const M_TWO_OVER_SQRT_PI: f64 = f64::from_bits(0xbff20dd750429b6d); + let dx = x as f64; + return f_fmla(dx, M_TWO_OVER_SQRT_PI, 1.) as f32; + } + } + + if ax <= 0x3f800000u32 { + // |x| <= 1 + let dx = x as f64; + // Generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[num,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // coeffs=CoefficientList[den,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + dx, + f64::from_bits(0x3feffffffffffff8), + f64::from_bits(0x3ff26c328bd2dc5f), + f64::from_bits(0x3fe6f91b9fa5f58c), + f64::from_bits(0x3fd09edf3fcf5ee1), + f64::from_bits(0x3faddb3bcedbff91), + f64::from_bits(0x3f7e43b5dd4b7587), + f64::from_bits(0x3f3baab6b3e61d7b), + f64::from_bits(0xbe83e7d629825321), + ); + let p_den = f_estrin_polyeval8( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x40023d04ee0abc28), + f64::from_bits(0x400252b377263d61), + f64::from_bits(0x3ff510af7f826479), + f64::from_bits(0x3fddfc089c4731ed), + f64::from_bits(0x3fba79b040e28b0a), + f64::from_bits(0x3f8aea2f3579235a), + f64::from_bits(0x3f485d2875b4f88c), + ); + return (p_num / p_den) as f32; + } + + let erfcx_abs_x = core_erfcx(f32::from_bits(ax)); + if x < 0. { + // exp(x^2)erfc(-x) = 2*exp(x^2) - erfcx(|x|) + let dx = x as f64; + return f_fmla(2., core_expdf(dx * dx), -erfcx_abs_x) as f32; + } + erfcx_abs_x as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_erfcx() { + assert_eq!(f_erfcxf(5.19209290e-09), 1.0); + assert_eq!(f_erfcxf(1.19209290e-08), 1.0); + assert_eq!(f_erfcxf(f32::EPSILON), 0.9999999); + assert_eq!(f_erfcxf(12.1), 0.046469606); + assert_eq!(f_erfcxf(7.1), 0.07869752); + assert_eq!(f_erfcxf(1.1), 0.40173045); + assert_eq!(f_erfcxf(-0.23), 1.3232007); + assert_eq!(f_erfcxf(-1.4325), 15.234794); + assert_eq!(f_erfcxf(-10.), f32::INFINITY); + assert_eq!(f_erfcxf(f32::INFINITY), 0.); + assert_eq!(f_erfcxf(f32::NEG_INFINITY), f32::INFINITY); + assert!(f_erfcxf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erff.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,472 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +// Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by Sollya +// with: +// > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|D...|], +// [k/8, (k + 1)/8]); +// for k = 0..31. +static COEFFS: [[u64; 8]; 32] = [ + [ + 0x3ff20dd750429b6d, + 0xbfd812746b037753, + 0x3fbce2f219e8596a, + 0xbf9b82cdacb78fda, + 0x3f756479297dfda5, + 0xbf48b3ac5455ef02, + 0xbf7126fcac367e3b, + 0x3fb2d0bdb3ba4984, + ], + [ + 0x3ff20dd750429b6d, + 0xbfd812746b0379a8, + 0x3fbce2f21a03cf2a, + 0xbf9b82ce30de083e, + 0x3f7565bcad3eb60f, + 0xbf4c02c66f659256, + 0x3f1f92f673385229, + 0xbeedef402648ae90, + ], + [ + 0x3ff20dd750429b34, + 0xbfd812746b032dce, + 0x3fbce2f219d84aae, + 0xbf9b82ce22dcf139, + 0x3f7565b9efcd4af1, + 0xbf4c021f1af414bc, + 0x3f1f7c6d177eff82, + 0xbeec9e4410dcf865, + ], + [ + 0x3ff20dd750426eab, + 0xbfd812746ae592c7, + 0x3fbce2f211525f14, + 0xbf9b82ccc125e63f, + 0x3f756596f261cfd3, + 0xbf4bfde1ff8eeecf, + 0x3f1f31a9d15dc5d8, + 0xbeea5a4362844b3c, + ], + [ + 0x3ff20dd75039c705, + 0xbfd812746777e74d, + 0x3fbce2f17af98a1b, + 0xbf9b82be4b817cbe, + 0x3f7564bec2e2962e, + 0xbf4bee86f9da3558, + 0x3f1e9443689dc0cc, + 0xbee79c0f230805d8, + ], + [ + 0x3ff20dd74f811211, + 0xbfd81274371a3e8f, + 0x3fbce2ec038262e5, + 0xbf9b8265b82c5e1f, + 0x3f75615a2e239267, + 0xbf4bc63ae023dceb, + 0x3f1d87c2102f7e06, + 0xbee49584bea41d62, + ], + [ + 0x3ff20dd746d063e3, + 0xbfd812729a8a950f, + 0x3fbce2cb0a2df232, + 0xbf9b80eca1f51278, + 0x3f75572e26c46815, + 0xbf4b715e5638b65e, + 0x3f1bfbb195484968, + 0xbee177a565c15c52, + ], + [ + 0x3ff20dd701b44486, + 0xbfd812691145f237, + 0x3fbce23a06b8cfd9, + 0xbf9b7c1dc7245288, + 0x3f753e92f7f397dd, + 0xbf4ad97cc4acf0b2, + 0x3f19f028b2b09b71, + 0xbedcdc4da08da8c1, + ], + [ + 0x3ff20dd5715ac332, + 0xbfd8123e680bd0eb, + 0x3fbce0457aded691, + 0xbf9b6f52d52bed40, + 0x3f750c291b84414c, + 0xbf49ea246b1ad4a9, + 0x3f177654674e0ca0, + 0xbed737c11a1bcebb, + ], + [ + 0x3ff20dce6593e114, + 0xbfd811a59c02eadc, + 0x3fbcdab53c7cd7d5, + 0xbf9b526d2e321eed, + 0x3f74b1d32cd8b994, + 0xbf48963143ec0a1e, + 0x3f14ad5700e4db91, + 0xbed231e100e43ef2, + ], + [ + 0x3ff20db48bfd5a62, + 0xbfd80fdd84f9e308, + 0x3fbccd340d462983, + 0xbf9b196a29287680, + 0x3f74210c2c13a0f7, + 0xbf46dbdfb4ff71ae, + 0x3f11bca2d17fbd71, + 0xbecbca36f90c7cf5, + ], + [ + 0x3ff20d64b2f8f508, + 0xbfd80b4d4f19fa8b, + 0x3fbcb088197262e3, + 0xbf9ab51fd02e5b99, + 0x3f734e1e5e81a632, + 0xbf44c66377b502ce, + 0x3f0d9ad25066213c, + 0xbec4b0df7dd0cfa1, + ], + [ + 0x3ff20c8fc1243576, + 0xbfd8010cb2009e27, + 0x3fbc7a47e9299315, + 0xbf9a155be5683654, + 0x3f7233502694997b, + 0xbf426c94b7d81300, + 0x3f08094f1de25fb9, + 0xbebe0e3d776c6eef, + ], + [ + 0x3ff20a9bd1611bc1, + 0xbfd7ec7fbce83f90, + 0x3fbc1d757d7317b7, + 0xbf992c160cd589f0, + 0x3f70d307269cc5c2, + 0xbf3fda5b0d2d1879, + 0x3f02fdd7b3b14a7f, + 0xbeb54eed4a26af5a, + ], + [ + 0x3ff20682834f943d, + 0xbfd7c73f747bf5a9, + 0x3fbb8c2db4a9ffd1, + 0xbf97f0e4ffe989ec, + 0x3f6e7061eae4166e, + 0xbf3ad36e873fff2d, + 0x3efd39222396128e, + 0xbead83dacec5ea6b, + ], + [ + 0x3ff1feb8d12676d7, + 0xbfd7898347284afe, + 0x3fbaba3466b34451, + 0xbf9663adc573e2f9, + 0x3f6ae99fb17c3e08, + 0xbf3602f950ad5535, + 0x3ef5e9717490609d, + 0xbea3fca107bbc8d5, + ], + [ + 0x3ff1f12fe3c536fa, + 0xbfd72b1d1f22e6d3, + 0x3fb99fc0eed4a896, + 0xbf948db0a87bd8c6, + 0x3f673e368895aa61, + 0xbf319b35d5301fc8, + 0x3ef007987e4bb033, + 0xbe9a7edcd4c2dc70, + ], + [ + 0x3ff1db7b0df84d5d, + 0xbfd6a4e4a41cde02, + 0x3fb83bbded16455d, + 0xbf92809b3b36977e, + 0x3f639c08bab44679, + 0xbf2b7b45a70ed119, + 0x3ee6e99b36410e7b, + 0xbe913619bb7ebc0c, + ], + [ + 0x3ff1bb1c85c4a527, + 0xbfd5f23b99a249a3, + 0x3fb694c91fa0d12c, + 0xbf9053e1ce11c72d, + 0x3f602bf72c50ea78, + 0xbf24f478fb56cb02, + 0x3ee005f80ecbe213, + 0xbe85f2446bde7f5b, + ], + [ + 0x3ff18dec3bd51f9d, + 0xbfd5123f58346186, + 0x3fb4b8a1ca536ab4, + 0xbf8c4243015cc723, + 0x3f5a1a8a01d351ef, + 0xbf1f466b34f1d86b, + 0x3ed5f835eea0bf6a, + 0xbe7b83165b939234, + ], + [ + 0x3ff152804c3369f4, + 0xbfd4084cd4afd4bc, + 0x3fb2ba2e836e47aa, + 0xbf8800f2dfc6904b, + 0x3f54a6daf0669c59, + 0xbf16e326ab872317, + 0x3ecd9761a6a755a5, + 0xbe70fca33f9dd4b5, + ], + [ + 0x3ff1087ad68356aa, + 0xbfd2dbb044707459, + 0x3fb0aea8ceaa0384, + 0xbf840b516d52b3d2, + 0x3f500c9e05f01d22, + 0xbf1076afb0dc0ff7, + 0x3ec39fadec400657, + 0xbe64b5761352e7e3, + ], + [ + 0x3ff0b0a7a8ba4a22, + 0xbfd196990d22d4a1, + 0x3fad5551e6ac0c4d, + 0xbf807cce1770bd1a, + 0x3f4890347b8848bf, + 0xbf0757ec96750b6a, + 0x3eb9b258a1e06bce, + 0xbe58fc6d22da7572, + ], + [ + 0x3ff04ce2be70fb47, + 0xbfd0449e4b0b9cac, + 0x3fa97f7424f4b0e7, + 0xbf7ac825439c42f4, + 0x3f428f5f65426dfb, + 0xbf005b699a90f90f, + 0x3eb0a888eecf4593, + 0xbe4deace2b32bb31, + ], + [ + 0x3fefbf9fb0e11cc8, + 0xbfcde2640856545a, + 0x3fa5f5b1f47f8510, + 0xbf7588bc71eb41b9, + 0x3f3bc6a0a772f56d, + 0xbef6b9fad1f1657a, + 0x3ea573204ba66504, + 0xbe41d38065c94e44, + ], + [ + 0x3feed8f18c99e031, + 0xbfcb4cb6acd903b4, + 0x3fa2c7f3dddd6fc1, + 0xbf713052067df4e0, + 0x3f34a5027444082f, + 0xbeef672bab0e2554, + 0x3e9b83c756348cc9, + 0xbe3534f1a1079499, + ], + [ + 0x3fedebd33044166d, + 0xbfc8d7cd9053f7d8, + 0x3f9ff9957fb3d6e7, + 0xbf6b50be55de0f36, + 0x3f2e92c8ec53a628, + 0xbee5a4b88d508007, + 0x3e91a27737559e26, + 0xbe2942ae62cb2c14, + ], + [ + 0x3fecfdbf0386f3bd, + 0xbfc68e33d93b0dc4, + 0x3f9b2683d58f53de, + 0xbf65a9174e70d26f, + 0x3f269ddd326d49cd, + 0xbeddd8f397a8219c, + 0x3e86a755016ad4dd, + 0xbe1e366e0139187d, + ], + [ + 0x3fec132adb8d7464, + 0xbfc475a899f61b46, + 0x3f970a431397a77c, + 0xbf612e3d35beeee2, + 0x3f20c16b05738333, + 0xbed4a47f873e144e, + 0x3e7d3d494c698c02, + 0xbe12302c59547fe5, + ], + [ + 0x3feb2f5fd05555e7, + 0xbfc28feefbe03ec7, + 0x3f93923acbb3a676, + 0xbf5b4ff793cd6358, + 0x3f18ea0eb8c913bc, + 0xbeccb31ec2baceb1, + 0x3e730011e7e80c04, + 0xbe0617710635cb1d, + ], + [ + 0x3fea54853cd9593e, + 0xbfc0dbdbaea4dc8e, + 0x3f90a93e2c20a0fd, + 0xbf55c969ff401ea8, + 0x3f129e0cc64fe627, + 0xbec4160d8e9d3c2a, + 0x3e68e7b67594624a, + 0xbdfb1cf2c975b09b, + ], + [ + 0x3fe983ceece09ff8, + 0xbfbeacc78f7a2d00, + 0x3f8c74418410655f, + 0xbf51756a050e441e, + 0x3f0bff3650f7f548, + 0xbebc56c0217d3ada, + 0x3e607b4918d0b489, + 0xbdf0d4be8c1c50f8, + ], +]; + +trait ErffBackend { + fn fma(&self, x: f64, y: f64, z: f64) -> f64; +} + +struct GenErffBackend {} + +impl ErffBackend for GenErffBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +struct FmaErffBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl ErffBackend for FmaErffBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } +} + +#[inline(always)] +fn erff_gen(x: f32, backend: B) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + + if x_abs >= 0x4080_0000u32 { + static ONE: [f32; 2] = [1.0, -1.0]; + static SMALL: [f32; 2] = [f32::from_bits(0xb3000000), f32::from_bits(0x33000000)]; + + let sign = x.is_sign_negative() as usize; + + if x_abs >= 0x7f80_0000u32 { + return if x_abs > 0x7f80_0000 { x } else { ONE[sign] }; + } + + return ONE[sign] + SMALL[sign]; + } + + // Polynomial approximation: + // erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14) + let xd = x as f64; + let xsq = xd * xd; + + const EIGHT: u32 = 3 << 23; + let idx = unsafe { f32::from_bits(x_abs.wrapping_add(EIGHT)).to_int_unchecked::() }; + + let c = COEFFS[idx]; + + let x4 = xsq * xsq; + let c0 = backend.fma(xsq, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c1 = backend.fma(xsq, f64::from_bits(c[3]), f64::from_bits(c[2])); + let c2 = backend.fma(xsq, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c3 = backend.fma(xsq, f64::from_bits(c[7]), f64::from_bits(c[6])); + + let x8 = x4 * x4; + let p0 = backend.fma(x4, c1, c0); + let p1 = backend.fma(x4, c3, c2); + + (xd * backend.fma(x8, p1, p0)) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn erff_fma_impl(x: f32) -> f32 { + erff_gen(x, FmaErffBackend {}) +} + +/// Error function +/// +/// Max ulp 0.5 +#[inline] +pub fn f_erff(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + crate::err::erff::erff_gen(x, GenErffBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + erff_fma_impl + } else { + fn def_erff(x: f32) -> f32 { + erff_gen(x, GenErffBackend {}) + } + def_erff + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_erff_test() { + assert_eq!(f_erff(0.0), 0.0); + assert_eq!(f_erff(1.0), 0.8427008); + assert_eq!(f_erff(0.5), 0.5204999); + assert_eq!(f_erff(f32::INFINITY), 1.0); + assert_eq!(f_erff(f32::NEG_INFINITY), -1.0); + assert!(f_erff(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erffc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erffc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/erffc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/erffc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,345 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use std::hint::black_box; + +static ERR0: [u64; 128] = [ + 0x3ff0000000000000, + 0x3ff0163da9fb3335, + 0x3ff02c9a3e778061, + 0x3ff04315e86e7f85, + 0x3ff059b0d3158574, + 0x3ff0706b29ddf6de, + 0x3ff0874518759bc8, + 0x3ff09e3ecac6f383, + 0x3ff0b5586cf9890f, + 0x3ff0cc922b7247f7, + 0x3ff0e3ec32d3d1a2, + 0x3ff0fb66affed31b, + 0x3ff11301d0125b51, + 0x3ff12abdc06c31cc, + 0x3ff1429aaea92de0, + 0x3ff15a98c8a58e51, + 0x3ff172b83c7d517b, + 0x3ff18af9388c8dea, + 0x3ff1a35beb6fcb75, + 0x3ff1bbe084045cd4, + 0x3ff1d4873168b9aa, + 0x3ff1ed5022fcd91d, + 0x3ff2063b88628cd6, + 0x3ff21f49917ddc96, + 0x3ff2387a6e756238, + 0x3ff251ce4fb2a63f, + 0x3ff26b4565e27cdd, + 0x3ff284dfe1f56381, + 0x3ff29e9df51fdee1, + 0x3ff2b87fd0dad990, + 0x3ff2d285a6e4030b, + 0x3ff2ecafa93e2f56, + 0x3ff306fe0a31b715, + 0x3ff32170fc4cd831, + 0x3ff33c08b26416ff, + 0x3ff356c55f929ff1, + 0x3ff371a7373aa9cb, + 0x3ff38cae6d05d866, + 0x3ff3a7db34e59ff7, + 0x3ff3c32dc313a8e5, + 0x3ff3dea64c123422, + 0x3ff3fa4504ac801c, + 0x3ff4160a21f72e2a, + 0x3ff431f5d950a897, + 0x3ff44e086061892d, + 0x3ff46a41ed1d0057, + 0x3ff486a2b5c13cd0, + 0x3ff4a32af0d7d3de, + 0x3ff4bfdad5362a27, + 0x3ff4dcb299fddd0d, + 0x3ff4f9b2769d2ca7, + 0x3ff516daa2cf6642, + 0x3ff5342b569d4f82, + 0x3ff551a4ca5d920f, + 0x3ff56f4736b527da, + 0x3ff58d12d497c7fd, + 0x3ff5ab07dd485429, + 0x3ff5c9268a5946b7, + 0x3ff5e76f15ad2148, + 0x3ff605e1b976dc09, + 0x3ff6247eb03a5585, + 0x3ff6434634ccc320, + 0x3ff6623882552225, + 0x3ff68155d44ca973, + 0x3ff6a09e667f3bcd, + 0x3ff6c012750bdabf, + 0x3ff6dfb23c651a2f, + 0x3ff6ff7df9519484, + 0x3ff71f75e8ec5f74, + 0x3ff73f9a48a58174, + 0x3ff75feb564267c9, + 0x3ff780694fde5d3f, + 0x3ff7a11473eb0187, + 0x3ff7c1ed0130c132, + 0x3ff7e2f336cf4e62, + 0x3ff80427543e1a12, + 0x3ff82589994cce13, + 0x3ff8471a4623c7ad, + 0x3ff868d99b4492ed, + 0x3ff88ac7d98a6699, + 0x3ff8ace5422aa0db, + 0x3ff8cf3216b5448c, + 0x3ff8f1ae99157736, + 0x3ff9145b0b91ffc6, + 0x3ff93737b0cdc5e5, + 0x3ff95a44cbc8520f, + 0x3ff97d829fde4e50, + 0x3ff9a0f170ca07ba, + 0x3ff9c49182a3f090, + 0x3ff9e86319e32323, + 0x3ffa0c667b5de565, + 0x3ffa309bec4a2d33, + 0x3ffa5503b23e255d, + 0x3ffa799e1330b358, + 0x3ffa9e6b5579fdbf, + 0x3ffac36bbfd3f37a, + 0x3ffae89f995ad3ad, + 0x3ffb0e07298db666, + 0x3ffb33a2b84f15fb, + 0x3ffb59728de5593a, + 0x3ffb7f76f2fb5e47, + 0x3ffba5b030a1064a, + 0x3ffbcc1e904bc1d2, + 0x3ffbf2c25bd71e09, + 0x3ffc199bdd85529c, + 0x3ffc40ab5fffd07a, + 0x3ffc67f12e57d14b, + 0x3ffc8f6d9406e7b5, + 0x3ffcb720dcef9069, + 0x3ffcdf0b555dc3fa, + 0x3ffd072d4a07897c, + 0x3ffd2f87080d89f2, + 0x3ffd5818dcfba487, + 0x3ffd80e316c98398, + 0x3ffda9e603db3285, + 0x3ffdd321f301b460, + 0x3ffdfc97337b9b5f, + 0x3ffe264614f5a129, + 0x3ffe502ee78b3ff6, + 0x3ffe7a51fbc74c83, + 0x3ffea4afa2a490da, + 0x3ffecf482d8e67f1, + 0x3ffefa1bee615a27, + 0x3fff252b376bba97, + 0x3fff50765b6e4540, + 0x3fff7bfdad9cbe14, + 0x3fffa7c1819e90d8, + 0x3fffd3c22b8f71f1, +]; + +static ERFC_COEFFS: [[u64; 16]; 2] = [ + [ + 0x3fec162355429b28, + 0x400d99999999999a, + 0x3fdda951cece2b85, + 0xbff70ef6cff4bcc4, + 0x4003d7f7b3d617de, + 0xc009d0aa47537c51, + 0x4009754ea9a3fcb1, + 0xc0027a5453fcc015, + 0x3ff1ef2e0531aeba, + 0xbfceca090f5a1c06, + 0xbfb7a3cd173a063c, + 0x3fb30fa68a68fddd, + 0x3f555ad9a326993a, + 0xbf907e7b0bb39fbf, + 0x3f52328706c0e950, + 0x3f6d6aa0b7b19cfe, + ], + [ + 0x401137c8983f8516, + 0x400799999999999a, + 0x3fc05b53aa241333, + 0xbfca3f53872bf870, + 0x3fbde4c30742c9d5, + 0xbfacb24bfa591986, + 0x3f9666aec059ca5f, + 0xbf7a61250eb26b0b, + 0x3f52b28b7924b34d, + 0x3f041b13a9d45013, + 0xbf16dd5e8a273613, + 0x3ef09ce8ea5e8da5, + 0x3ed33923b4102981, + 0xbec1dfd161e3f984, + 0xbe8c87618fcae3b3, + 0x3e8e8a6ffa0ba2c7, + ], +]; + +/// Complementary error function +/// +/// Max ULP 0.5 +pub fn f_erfcf(x: f32) -> f32 { + let ax = f32::from_bits(x.to_bits() & 0x7fff_ffff); + let axd = ax as f64; + let x2 = axd * axd; + let t = x.to_bits(); + let at = t & 0x7fff_ffff; + let sgn = t >> 31; + let i: i64 = (at > 0x40051000) as i64; + /* for x < -0x1.ea8f94p+1, erfc(x) rounds to 2 (to nearest) */ + if t > 0xc07547cau32 { + // x < -0x1.ea8f94p+1 + if t >= 0xff800000u32 { + // -Inf or NaN + if t == 0xff800000u32 { + return 2.0; + } // -Inf + return x + x; // NaN + } + return black_box(2.0) - black_box(f32::from_bits(0x33000000)); // rounds to 2 or nextbelow(2) + } + /* at is the absolute value of x + for x >= 0x1.41bbf8p+3, erfc(x) < 2^-150, thus rounds to 0 or to 2^-149 + depending on the rounding mode */ + if at >= 0x4120ddfcu32 { + // |x| >= 0x1.41bbf8p+3 + if at >= 0x7f800000u32 { + // +Inf or NaN + if at == 0x7f800000u32 { + return 0.0; + } // +Inf + return x + x; // NaN + } + // 0x1p-149f * 0.25f rounds to 0 or 2^-149 depending on rounding + return black_box(f32::from_bits(0x00000001)) * black_box(0.25); + } + if at <= 0x3db80000u32 { + // |x| <= 0x1.7p-4 + if t == 0xb76c9f62u32 { + // x = -0x1.d93ec4p-17 + return black_box(f32::from_bits(0x3f800085)) + black_box(f32::from_bits(0x33000000)); // exceptional case + } + /* for |x| <= 0x1.c5bf88p-26. erfc(x) rounds to 1 (to nearest) */ + if at <= 0x32e2dfc4u32 { + // |x| <= 0x1.c5bf88p-26 + if at == 0 { + return 1.0; + } + static D: [f32; 2] = [f32::from_bits(0xb2800000), f32::from_bits(0x33000000)]; + return 1.0 + D[sgn as usize]; + } + /* around 0, erfc(x) behaves as 1 - (odd polynomial) */ + const C: [u64; 5] = [ + 0x3ff20dd750429b6d, + 0xbfd812746b03610b, + 0x3fbce2f218831d2f, + 0xbf9b82c609607dcb, + 0x3f7553af09b8008e, + ]; + + let fw0 = f_fmla(x2, f64::from_bits(C[4]), f64::from_bits(C[3])); + let fw1 = f_fmla(x2, fw0, f64::from_bits(C[2])); + let fw2 = f_fmla(x2, fw1, f64::from_bits(C[1])); + + let f0 = x as f64 * f_fmla(x2, fw2, f64::from_bits(C[0])); + return (1.0 - f0) as f32; + } + + /* now -0x1.ea8f94p+1 <= x <= 0x1.41bbf8p+3, with |x| > 0x1.7p-4 */ + const ILN2: f64 = f64::from_bits(0x3ff71547652b82fe); + const LN2H: f64 = f64::from_bits(0x3f762e42fefa0000); + const LN2L: f64 = f64::from_bits(0x3d0cf79abd6f5dc8); + + let jt = dd_fmla(x2, ILN2, -(1024. + f64::from_bits(0x3f70000000000000))).to_bits(); + let j: i64 = ((jt << 12) as i64) >> 48; + let sf = ((j >> 7) as u64) + .wrapping_add(0x3ffu64 | (sgn as u64) << 11) + .wrapping_shl(52); + + const CH: [u64; 4] = [ + 0xbfdffffffffff333, + 0x3fc5555555556a14, + 0xbfa55556666659b4, + 0x3f81111074cc7b22, + ]; + let d = f_fmla(LN2L, j as f64, f_fmla(LN2H, j as f64, x2)); + let d2 = d * d; + let e0 = f64::from_bits(ERR0[(j & 127) as usize]); + + let fw0 = f_fmla(d, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let fw1 = f_fmla(d, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + let fw2 = f_fmla(d2, fw0, fw1); + + let f = f_fmla(d2, fw2, d); + + let ct = ERFC_COEFFS[i as usize]; + let z = (axd - f64::from_bits(ct[0])) / (axd + f64::from_bits(ct[1])); + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + let c = &ct[3..]; + + let sw0 = f_fmla(z, f64::from_bits(c[1]), f64::from_bits(c[0])); + let sw1 = f_fmla(z, f64::from_bits(c[3]), f64::from_bits(c[2])); + let sw2 = f_fmla(z, f64::from_bits(c[5]), f64::from_bits(c[4])); + let sw3 = f_fmla(z, f64::from_bits(c[7]), f64::from_bits(c[6])); + + let zw0 = f_fmla(z2, sw1, sw0); + let zw1 = f_fmla(z2, sw3, sw2); + + let sw4 = f_fmla(z, f64::from_bits(c[9]), f64::from_bits(c[8])); + let sw5 = f_fmla(z, f64::from_bits(c[11]), f64::from_bits(c[10])); + + let zw2 = f_fmla(z4, zw1, zw0); + let zw3 = f_fmla(z2, sw5, sw4); + let zw4 = f_fmla(z4, f64::from_bits(c[12]), zw3); + + let mut s = f_fmla(z8, zw4, zw2); + + s = f_fmla(z, s, f64::from_bits(ct[2])); + + static OFF: [f64; 2] = [0., 2.]; + + let r = (f64::from_bits(sf) * f_fmla(-f, e0, e0)) * s; + let y = OFF[sgn as usize] + r; + y as f32 +} + +#[cfg(test)] +mod tests { + use crate::f_erfcf; + + #[test] + fn test_erfc() { + assert_eq!(f_erfcf(0.0), 1.0); + assert_eq!(f_erfcf(0.5), 0.47950011); + assert_eq!(f_erfcf(1.0), 0.1572992); + assert!(f_erfcf(f32::NAN).is_nan()); + assert_eq!(f_erfcf(f32::INFINITY), 0.0); + assert_eq!(f_erfcf(f32::NEG_INFINITY), 2.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,692 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::fast_log_dd; +use crate::polyeval::{f_polyeval4, f_polyeval5}; + +#[cold] +fn inverf_0p06_to_0p75(x: f64) -> f64 { + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const P: [(u64, u64); 10] = [ + (0xbc3e06eda42202a0, 0x3f93c2fc5d00e0c8), + (0xbc6eb374406b33b4, 0xbfc76fcfd022e3ff), + (0xbc857822d7ffd282, 0x3fe6f8443546010a), + (0x3c68269c66dfb28a, 0xbff80996754ceb79), + (0x3c543dce8990a9f9, 0x3ffcf778d5ef0504), + (0xbc72fc55f73765f6, 0xbff433be821423d0), + (0xbc66d05fb37c8592, 0x3fdf15f19e9d8da4), + (0x3c56dfb85e83a2c5, 0xbfb770b6827e0829), + (0x3bff1472ecdfa403, 0x3f7a98a2980282bb), + (0x3baffb33d69d6276, 0xbf142a246fd2c07c), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let vz = DoubleDouble::full_add_f64(x2, -0.5625); + + let vx2 = vz * vz; + let vx4 = vx2 * vx2; + let vx8 = vx4 * vx4; + + let p0 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::mul_add(vx2, p1, p0); + let q1 = DoubleDouble::mul_add(vx2, p3, p2); + + let r0 = DoubleDouble::mul_add(vx4, q1, q0); + let num = DoubleDouble::mul_add(vx8, p4, r0); + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const Q: [(u64, u64); 10] = [ + (0xbc36337f24e57cb9, 0x3f92388d5d757e3a), + (0xbc63dfae43d60e0b, 0xbfc6ca7da581358c), + (0xbc77656389bd0e62, 0x3fe7c82ce417b4e0), + (0xbc93679667bef2f0, 0xbffad58651fd1a51), + (0x3ca2c6cb9eb17fb4, 0x4001bdb67e93a242), + (0xbc9b58961ba253bc, 0xbffbdaeff6fbb81c), + (0x3c7861f549c6aa61, 0x3fe91b12cf47da3a), + (0xbc696dfd665b2f5e, 0xbfc7c5d0ffb7f1da), + (0x3c1552b0ec0ba7b3, 0x3f939ada247f7609), + (0xbbcaa226fb7b30a8, 0xbf41be65038ccfe6), + ]; + + let p0 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let p1 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let p2 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let p3 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let p4 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + + let q0 = DoubleDouble::mul_add(vx2, p1, p0); + let q1 = DoubleDouble::mul_add(vx2, p3, p2); + + let r0 = DoubleDouble::mul_add(vx4, q1, q0); + let den = DoubleDouble::mul_add(vx8, p4, r0); + + let r = DoubleDouble::div(num, den); + let k = DoubleDouble::quick_mult_f64(r, x); + k.to_f64() +} + +#[inline] +fn inverf_asympt_small(z: DoubleDouble, zeta_sqrt: DoubleDouble, x: f64) -> f64 { + // Generated in Wolfram Mathematica: + // <90] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 11] = [ + (0x3c936555853a8b2c, 0x3ff0001df06a2515), + (0x3cea488e802db3c3, 0x404406ba373221da), + (0xbce27d42419754e3, 0x407b0442e38a9597), + (0xbd224a407624cbdf, 0x409c9277e31ef446), + (0x3d4f16ce65d6fea0, 0x40aec3ec005b1d8a), + (0x3d105bc37bc61b58, 0x40b46be8f860f4d9), + (0x3d5ca133dcdecaa0, 0x40b3826e6a32dad7), + (0x3d1d52013ba8aa38, 0x40aae93a603cf3ea), + (0xbd07a75306df0fc3, 0x4098ab8357dc2e51), + (0x3d1bb6770bb7a27e, 0x407ebead00879010), + (0xbbfcbff4a9737936, 0x3f8936117ccbff83), + ]; + + let z2 = DoubleDouble::quick_mult(z, z); + let z4 = DoubleDouble::quick_mult(z2, z2); + let z8 = DoubleDouble::quick_mult(z4, z4); + + let q0 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[1]), + z, + DoubleDouble::from_bit_pair(P[0]), + ); + let q1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[3]), + z, + DoubleDouble::from_bit_pair(P[2]), + ); + let q2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[5]), + z, + DoubleDouble::from_bit_pair(P[4]), + ); + let q3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[7]), + z, + DoubleDouble::from_bit_pair(P[6]), + ); + let q4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[9]), + z, + DoubleDouble::from_bit_pair(P[8]), + ); + + let r0 = DoubleDouble::mul_add(z2, q1, q0); + let r1 = DoubleDouble::mul_add(z2, q3, q2); + + let s0 = DoubleDouble::mul_add(z4, r1, r0); + let s1 = DoubleDouble::mul_add(z2, DoubleDouble::from_bit_pair(P[10]), q4); + let num = DoubleDouble::mul_add(z8, s1, s0); + + // See numerator generation above: + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const Q: [(u64, u64); 11] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc75b1109d4a3262, 0x40440782efaab17f), + (0x3d1f7775b207d84f, 0x407b2da74b0d39f2), + (0xbd3291fdbab49501, 0x409dac8d9e7c90b2), + (0xbd58d8fdd27707a9, 0x40b178dfeffa3192), + (0xbd57fc74ad705ce0, 0x40bad19b686f219f), + (0x3d4075510031f2cd, 0x40be70a598208cea), + (0xbd5442e109152efb, 0x40b9683ef36ae330), + (0x3d5398192933962e, 0x40b04b7c4c3ca8ee), + (0x3d2d04d03598e303, 0x409bd0080799fbf1), + (0x3d2a988eb552ef44, 0x40815a46f12bafe3), + ]; + + let q0 = DoubleDouble::mul_add_f64( + DoubleDouble::from_bit_pair(Q[1]), + z, + f64::from_bits(0x3ff0000000000000), + ); + let q1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[3]), + z, + DoubleDouble::from_bit_pair(Q[2]), + ); + let q2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[5]), + z, + DoubleDouble::from_bit_pair(Q[4]), + ); + let q3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[7]), + z, + DoubleDouble::from_bit_pair(Q[6]), + ); + let q4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[9]), + z, + DoubleDouble::from_bit_pair(Q[8]), + ); + + let r0 = DoubleDouble::mul_add(z2, q1, q0); + let r1 = DoubleDouble::mul_add(z2, q3, q2); + + let s0 = DoubleDouble::mul_add(z4, r1, r0); + let s1 = DoubleDouble::mul_add(z2, DoubleDouble::from_bit_pair(Q[10]), q4); + let den = DoubleDouble::mul_add(z8, s1, s0); + let r = DoubleDouble::div(num, den); + let k = DoubleDouble::quick_mult(r, zeta_sqrt); + f64::copysign(k.to_f64(), x) +} + +// branch for |x| > 0.9999 for extreme tail +#[cold] +fn inverf_asympt_long(z: DoubleDouble, zeta_sqrt: DoubleDouble, x: f64) -> f64 { + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 14] = [ + (0x3c97612f9b24a614, 0x3ff0000ba84cc7a5), + (0xbcee8fe2da463412, 0x40515246546f5d88), + (0x3d2fa4a2b891b526, 0x40956b6837159b11), + (0x3d5d673ffad4f817, 0x40c5a1aa3be58652), + (0x3d8867a1e5506f88, 0x40e65ebb1e1e7c75), + (0xbd9bbc0764ed8f5b, 0x40fd2064a652e5c2), + (0xbda78e569c0d237f, 0x410a385c627c461c), + (0xbdab3123ebc465d7, 0x4110f05ca2b65fe5), + (0x3d960def35955192, 0x4110bb079af2fe08), + (0xbd97904816054836, 0x410911c24610c11c), + (0xbd937745e9192593, 0x40fc603244adca35), + (0xbd65fbc476d63050, 0x40e6399103188c21), + (0xbd61016ef381cce6, 0x40c6482b44995b89), + (0x3c326105c49e5a1a, 0xbfab44bd8b4e3138), + ]; + + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + + let g0 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let g1 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let g2 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let g3 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let g4 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let g5 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + let g6 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[13]), + DoubleDouble::from_bit_pair(P[12]), + ); + + let h0 = DoubleDouble::mul_add(z2, g1, g0); + let h1 = DoubleDouble::mul_add(z2, g3, g2); + let h2 = DoubleDouble::mul_add(z2, g5, g4); + + let q0 = DoubleDouble::mul_add(z4, h1, h0); + let q1 = DoubleDouble::mul_add(z4, g6, h2); + + let num = DoubleDouble::mul_add(z8, q1, q0); + + // See numerator generation above: + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const Q: [(u64, u64); 14] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcfc7b886ee61417, 0x405152838f711f3c), + (0xbd33f933c14e831a, 0x409576cb78cab36e), + (0x3d33fb09e2c4898a, 0x40c5e8a2c7602ced), + (0x3d7be430c664bf7e, 0x40e766fdc8c7638c), + (0x3dac662e74cdfc0e, 0x4100276b5f47b5f1), + (0x3da67d06e82a8495, 0x410f843887f8a24a), + (0x3dbbf2e22fc2550a, 0x4116d04271703e08), + (0xbdb2fb3aed100853, 0x4119aff4ed32b74b), + (0x3dba75e7b7171c3c, 0x4116b5eb8bf386bd), + (0x3dab2d8b8c1937eb, 0x410f71c38e84cb34), + (0xbda4e2e8a50b7370, 0x4100ca04b0f36b94), + (0xbd86ed6df34fdaf9, 0x40e9151ded4cf4b7), + (0x3d6938ea702c0328, 0x40c923ee1ab270c4), + ]; + + let g0 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let g1 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let g2 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let g3 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let g4 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let g5 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + let g6 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[13]), + DoubleDouble::from_bit_pair(Q[12]), + ); + + let h0 = DoubleDouble::mul_add(z2, g1, g0); + let h1 = DoubleDouble::mul_add(z2, g3, g2); + let h2 = DoubleDouble::mul_add(z2, g5, g4); + + let q0 = DoubleDouble::mul_add(z4, h1, h0); + let q1 = DoubleDouble::mul_add(z4, g6, h2); + + let den = DoubleDouble::mul_add(z8, q1, q0); + let r = DoubleDouble::div(num, den); + + let k = DoubleDouble::quick_mult(r, zeta_sqrt); + f64::copysign(k.to_f64(), x) +} + +/// Inverse error function +/// +/// ulp 0.5 +pub fn f_erfinv(x: f64) -> f64 { + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + + if ax >= 0x3ff0000000000000u64 || ax <= 0x3cb0000000000000u64 { + // |x| >= 1, |x| == 0, |x| <= f64::EPSILON + if ax == 0 { + // |x| == 0 + return 0.; + } + + if ax <= 0x3cb0000000000000u64 { + // |x| <= f64::EPSILON + // inverf(x) ~ Sqrt[Pi]x/2+O[x]^3 + const SQRT_PI_OVER_2: f64 = f64::from_bits(0x3fec5bf891b4ef6b); + return x * SQRT_PI_OVER_2; + } + + // |x| > 1 + if ax == 0x3ff0000000000000u64 { + // |x| == 1 + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + return f64::NAN; // x == NaN, x = Inf, x > 1 + } + + let z = f64::from_bits(ax); + + if ax <= 0x3f8374bc6a7ef9db { + // 0.0095 + // for small |x| using taylor series first 3 terms + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let z2 = DoubleDouble::from_exact_mult(z, z); + let p = f_fmla( + z2.hi, + f64::from_bits(0x3fb62847c47dda48), + f64::from_bits(0x3fc053c2c0ab91c5), + ); + let mut r = DoubleDouble::mul_f64_add( + z2, + p, + DoubleDouble::from_bit_pair((0xbc33ea2ef8dde075, 0x3fcdb29fb2fee5e4)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b)), + ); + // (rh + rl) * z = rh * z + rl*z + let v = DoubleDouble::quick_mult_f64(r, z); + return f64::copysign(v.to_f64(), x); + } else if ax <= 0x3faeb851eb851eb8 { + // 0.06 + // for |x| < 0.06 using taylor series first 5 terms + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let z2 = DoubleDouble::from_exact_mult(z, z); + let p = f_polyeval4( + z2.hi, + f64::from_bits(0x3fb62847c47dda48), + f64::from_bits(0x3fb0a13189c6ef7a), + f64::from_bits(0x3faa7c85c89bb08b), + f64::from_bits(0x3fa5eeb1d488e312), + ); + let mut r = DoubleDouble::mul_f64_add( + z2, + p, + DoubleDouble::from_bit_pair((0x3c2cec68daff0d80, 0x3fc053c2c0ab91c5)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc33ea2ef8dde075, 0x3fcdb29fb2fee5e4)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b)), + ); + // (rh + rl) * z = rh * z + rl*z + let v = DoubleDouble::quick_mult_f64(r, z); + return f64::copysign(v.to_f64(), x); + } + + if ax <= 0x3fe8000000000000u64 { + // |x| < 0.75 + + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const P: [(u64, u64); 5] = [ + (0xbc3e06eda42202a0, 0x3f93c2fc5d00e0c8), + (0xbc6eb374406b33b4, 0xbfc76fcfd022e3ff), + (0xbc857822d7ffd282, 0x3fe6f8443546010a), + (0x3c68269c66dfb28a, 0xbff80996754ceb79), + (0x3c543dce8990a9f9, 0x3ffcf778d5ef0504), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let vz = DoubleDouble::full_add_f64(x2, -0.5625); + let ps_num = f_polyeval5( + vz.hi, + f64::from_bits(0xbff433be821423d0), + f64::from_bits(0x3fdf15f19e9d8da4), + f64::from_bits(0xbfb770b6827e0829), + f64::from_bits(0x3f7a98a2980282bb), + f64::from_bits(0xbf142a246fd2c07c), + ); + let mut num = DoubleDouble::mul_f64_add(vz, ps_num, DoubleDouble::from_bit_pair(P[4])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[3])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[2])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[1])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[0])); + + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const Q: [(u64, u64); 5] = [ + (0xbc36337f24e57cb9, 0x3f92388d5d757e3a), + (0xbc63dfae43d60e0b, 0xbfc6ca7da581358c), + (0xbc77656389bd0e62, 0x3fe7c82ce417b4e0), + (0xbc93679667bef2f0, 0xbffad58651fd1a51), + (0x3ca2c6cb9eb17fb4, 0x4001bdb67e93a242), + ]; + + let ps_den = f_polyeval5( + vz.hi, + f64::from_bits(0xbffbdaeff6fbb81c), + f64::from_bits(0x3fe91b12cf47da3a), + f64::from_bits(0xbfc7c5d0ffb7f1da), + f64::from_bits(0x3f939ada247f7609), + f64::from_bits(0xbf41be65038ccfe6), + ); + + let mut den = DoubleDouble::mul_f64_add(vz, ps_den, DoubleDouble::from_bit_pair(Q[4])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[3])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[2])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[1])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[0])); + let r = DoubleDouble::div(num, den); + let k = DoubleDouble::quick_mult_f64(r, z); + let err = f_fmla( + k.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3c40000000000000), // 2^-59 + ); + let ub = k.hi + (k.lo + err); + let lb = k.hi + (k.lo - err); + if ub == lb { + return f64::copysign(k.to_f64(), x); + } + return inverf_0p06_to_0p75(x); + } + + let q = DoubleDouble::from_full_exact_add(1.0, -z); + + let mut zeta = fast_log_dd(q); + zeta = DoubleDouble::from_exact_add(zeta.hi, zeta.lo); + zeta = -zeta; + let zeta_sqrt = zeta.fast_sqrt(); + let rz = zeta_sqrt.recip(); + + if z < 0.9999 { + inverf_asympt_small(rz, zeta_sqrt, x) + } else { + inverf_asympt_long(rz, zeta_sqrt, x) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_erfinv() { + assert!(f_erfinv(f64::NEG_INFINITY).is_nan()); + assert!(f_erfinv(f64::INFINITY).is_nan()); + assert!(f_erfinv(f64::NAN).is_nan()); + assert_eq!(f_erfinv(f64::EPSILON), 1.9678190753608283e-16); + assert_eq!(f_erfinv(-0.5435340000000265), -0.5265673336010599); + assert_eq!(f_erfinv(0.5435340000000265), 0.5265673336010599); + assert_eq!(f_erfinv(0.001000000000084706), 0.0008862271575416209); + assert_eq!(f_erfinv(-0.001000000000084706), -0.0008862271575416209); + assert_eq!(f_erfinv(0.71), 0.7482049711849852); + assert_eq!(f_erfinv(-0.71), -0.7482049711849852); + assert_eq!(f_erfinv(0.41), 0.381014610957532); + assert_eq!(f_erfinv(-0.41), -0.381014610957532); + assert_eq!(f_erfinv(0.32), 0.29165547581744206); + assert_eq!(f_erfinv(-0.32), -0.29165547581744206); + assert_eq!(f_erfinv(0.82), 0.9480569762323499); + assert_eq!(f_erfinv(-0.82), -0.9480569762323499); + assert_eq!(f_erfinv(0.05), 0.044340387910005497); + assert_eq!(f_erfinv(-0.05), -0.044340387910005497); + assert_eq!(f_erfinv(0.99), 1.8213863677184494); + assert_eq!(f_erfinv(-0.99), -1.8213863677184494); + assert_eq!(f_erfinv(0.9900000000867389), 1.8213863698392927); + assert_eq!(f_erfinv(-0.9900000000867389), -1.8213863698392927); + assert_eq!(f_erfinv(0.99999), 3.123413274341571); + assert_eq!(f_erfinv(-0.99999), -3.123413274341571); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverfc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverfc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,704 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::{fast_log_d_to_dd, fast_log_dd}; +use crate::polyeval::{f_polyeval4, f_polyeval5}; + +#[cold] +fn inverf_0p06_to_0p75(x: DoubleDouble) -> DoubleDouble { + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const P: [(u64, u64); 10] = [ + (0xbc3e06eda42202a0, 0x3f93c2fc5d00e0c8), + (0xbc6eb374406b33b4, 0xbfc76fcfd022e3ff), + (0xbc857822d7ffd282, 0x3fe6f8443546010a), + (0x3c68269c66dfb28a, 0xbff80996754ceb79), + (0x3c543dce8990a9f9, 0x3ffcf778d5ef0504), + (0xbc72fc55f73765f6, 0xbff433be821423d0), + (0xbc66d05fb37c8592, 0x3fdf15f19e9d8da4), + (0x3c56dfb85e83a2c5, 0xbfb770b6827e0829), + (0x3bff1472ecdfa403, 0x3f7a98a2980282bb), + (0x3baffb33d69d6276, 0xbf142a246fd2c07c), + ]; + let x2 = DoubleDouble::quick_mult(x, x); + let vz = DoubleDouble::full_add_f64(x2, -0.5625); + + let vx2 = vz * vz; + let vx4 = vx2 * vx2; + let vx8 = vx4 * vx4; + + let p0 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::mul_add(vx2, p1, p0); + let q1 = DoubleDouble::mul_add(vx2, p3, p2); + + let r0 = DoubleDouble::mul_add(vx4, q1, q0); + let num = DoubleDouble::mul_add(vx8, p4, r0); + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const Q: [(u64, u64); 10] = [ + (0xbc36337f24e57cb9, 0x3f92388d5d757e3a), + (0xbc63dfae43d60e0b, 0xbfc6ca7da581358c), + (0xbc77656389bd0e62, 0x3fe7c82ce417b4e0), + (0xbc93679667bef2f0, 0xbffad58651fd1a51), + (0x3ca2c6cb9eb17fb4, 0x4001bdb67e93a242), + (0xbc9b58961ba253bc, 0xbffbdaeff6fbb81c), + (0x3c7861f549c6aa61, 0x3fe91b12cf47da3a), + (0xbc696dfd665b2f5e, 0xbfc7c5d0ffb7f1da), + (0x3c1552b0ec0ba7b3, 0x3f939ada247f7609), + (0xbbcaa226fb7b30a8, 0xbf41be65038ccfe6), + ]; + + let p0 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let p1 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let p2 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let p3 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let p4 = DoubleDouble::mul_add( + vz, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + + let q0 = DoubleDouble::mul_add(vx2, p1, p0); + let q1 = DoubleDouble::mul_add(vx2, p3, p2); + + let r0 = DoubleDouble::mul_add(vx4, q1, q0); + let den = DoubleDouble::mul_add(vx8, p4, r0); + + let r = DoubleDouble::div(num, den); + DoubleDouble::quick_mult(r, x) +} + +#[inline] +fn inverf_asympt_small(z: DoubleDouble, zeta_sqrt: DoubleDouble) -> DoubleDouble { + // Generated in Wolfram Mathematica: + // <90] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 11] = [ + (0x3c936555853a8b2c, 0x3ff0001df06a2515), + (0x3cea488e802db3c3, 0x404406ba373221da), + (0xbce27d42419754e3, 0x407b0442e38a9597), + (0xbd224a407624cbdf, 0x409c9277e31ef446), + (0x3d4f16ce65d6fea0, 0x40aec3ec005b1d8a), + (0x3d105bc37bc61b58, 0x40b46be8f860f4d9), + (0x3d5ca133dcdecaa0, 0x40b3826e6a32dad7), + (0x3d1d52013ba8aa38, 0x40aae93a603cf3ea), + (0xbd07a75306df0fc3, 0x4098ab8357dc2e51), + (0x3d1bb6770bb7a27e, 0x407ebead00879010), + (0xbbfcbff4a9737936, 0x3f8936117ccbff83), + ]; + + let z2 = DoubleDouble::quick_mult(z, z); + let z4 = DoubleDouble::quick_mult(z2, z2); + let z8 = DoubleDouble::quick_mult(z4, z4); + + let q0 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[1]), + z, + DoubleDouble::from_bit_pair(P[0]), + ); + let q1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[3]), + z, + DoubleDouble::from_bit_pair(P[2]), + ); + let q2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[5]), + z, + DoubleDouble::from_bit_pair(P[4]), + ); + let q3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[7]), + z, + DoubleDouble::from_bit_pair(P[6]), + ); + let q4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(P[9]), + z, + DoubleDouble::from_bit_pair(P[8]), + ); + + let r0 = DoubleDouble::mul_add(z2, q1, q0); + let r1 = DoubleDouble::mul_add(z2, q3, q2); + + let s0 = DoubleDouble::mul_add(z4, r1, r0); + let s1 = DoubleDouble::mul_add(z2, DoubleDouble::from_bit_pair(P[10]), q4); + let num = DoubleDouble::mul_add(z8, s1, s0); + + // See numerator generation above: + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const Q: [(u64, u64); 11] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc75b1109d4a3262, 0x40440782efaab17f), + (0x3d1f7775b207d84f, 0x407b2da74b0d39f2), + (0xbd3291fdbab49501, 0x409dac8d9e7c90b2), + (0xbd58d8fdd27707a9, 0x40b178dfeffa3192), + (0xbd57fc74ad705ce0, 0x40bad19b686f219f), + (0x3d4075510031f2cd, 0x40be70a598208cea), + (0xbd5442e109152efb, 0x40b9683ef36ae330), + (0x3d5398192933962e, 0x40b04b7c4c3ca8ee), + (0x3d2d04d03598e303, 0x409bd0080799fbf1), + (0x3d2a988eb552ef44, 0x40815a46f12bafe3), + ]; + + let q0 = DoubleDouble::mul_add_f64( + DoubleDouble::from_bit_pair(Q[1]), + z, + f64::from_bits(0x3ff0000000000000), + ); + let q1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[3]), + z, + DoubleDouble::from_bit_pair(Q[2]), + ); + let q2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[5]), + z, + DoubleDouble::from_bit_pair(Q[4]), + ); + let q3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[7]), + z, + DoubleDouble::from_bit_pair(Q[6]), + ); + let q4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(Q[9]), + z, + DoubleDouble::from_bit_pair(Q[8]), + ); + + let r0 = DoubleDouble::mul_add(z2, q1, q0); + let r1 = DoubleDouble::mul_add(z2, q3, q2); + + let s0 = DoubleDouble::mul_add(z4, r1, r0); + let s1 = DoubleDouble::mul_add(z2, DoubleDouble::from_bit_pair(Q[10]), q4); + let den = DoubleDouble::mul_add(z8, s1, s0); + let r = DoubleDouble::div(num, den); + DoubleDouble::quick_mult(r, zeta_sqrt) +} + +// branch for |x| > 0.9999 for extreme tail +#[cold] +fn inverf_asympt_long(z: DoubleDouble, zeta_sqrt: DoubleDouble) -> DoubleDouble { + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 14] = [ + (0x3c97612f9b24a614, 0x3ff0000ba84cc7a5), + (0xbcee8fe2da463412, 0x40515246546f5d88), + (0x3d2fa4a2b891b526, 0x40956b6837159b11), + (0x3d5d673ffad4f817, 0x40c5a1aa3be58652), + (0x3d8867a1e5506f88, 0x40e65ebb1e1e7c75), + (0xbd9bbc0764ed8f5b, 0x40fd2064a652e5c2), + (0xbda78e569c0d237f, 0x410a385c627c461c), + (0xbdab3123ebc465d7, 0x4110f05ca2b65fe5), + (0x3d960def35955192, 0x4110bb079af2fe08), + (0xbd97904816054836, 0x410911c24610c11c), + (0xbd937745e9192593, 0x40fc603244adca35), + (0xbd65fbc476d63050, 0x40e6399103188c21), + (0xbd61016ef381cce6, 0x40c6482b44995b89), + (0x3c326105c49e5a1a, 0xbfab44bd8b4e3138), + ]; + + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + + let g0 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let g1 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let g2 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let g3 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let g4 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + let g5 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[11]), + DoubleDouble::from_bit_pair(P[10]), + ); + let g6 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(P[13]), + DoubleDouble::from_bit_pair(P[12]), + ); + + let h0 = DoubleDouble::mul_add(z2, g1, g0); + let h1 = DoubleDouble::mul_add(z2, g3, g2); + let h2 = DoubleDouble::mul_add(z2, g5, g4); + + let q0 = DoubleDouble::mul_add(z4, h1, h0); + let q1 = DoubleDouble::mul_add(z4, g6, h2); + + let num = DoubleDouble::mul_add(z8, q1, q0); + + // See numerator generation above: + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const Q: [(u64, u64); 14] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcfc7b886ee61417, 0x405152838f711f3c), + (0xbd33f933c14e831a, 0x409576cb78cab36e), + (0x3d33fb09e2c4898a, 0x40c5e8a2c7602ced), + (0x3d7be430c664bf7e, 0x40e766fdc8c7638c), + (0x3dac662e74cdfc0e, 0x4100276b5f47b5f1), + (0x3da67d06e82a8495, 0x410f843887f8a24a), + (0x3dbbf2e22fc2550a, 0x4116d04271703e08), + (0xbdb2fb3aed100853, 0x4119aff4ed32b74b), + (0x3dba75e7b7171c3c, 0x4116b5eb8bf386bd), + (0x3dab2d8b8c1937eb, 0x410f71c38e84cb34), + (0xbda4e2e8a50b7370, 0x4100ca04b0f36b94), + (0xbd86ed6df34fdaf9, 0x40e9151ded4cf4b7), + (0x3d6938ea702c0328, 0x40c923ee1ab270c4), + ]; + + let g0 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let g1 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let g2 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let g3 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let g4 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + let g5 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[11]), + DoubleDouble::from_bit_pair(Q[10]), + ); + let g6 = DoubleDouble::mul_add( + z, + DoubleDouble::from_bit_pair(Q[13]), + DoubleDouble::from_bit_pair(Q[12]), + ); + + let h0 = DoubleDouble::mul_add(z2, g1, g0); + let h1 = DoubleDouble::mul_add(z2, g3, g2); + let h2 = DoubleDouble::mul_add(z2, g5, g4); + + let q0 = DoubleDouble::mul_add(z4, h1, h0); + let q1 = DoubleDouble::mul_add(z4, g6, h2); + + let den = DoubleDouble::mul_add(z8, q1, q0); + let r = DoubleDouble::div(num, den); + + DoubleDouble::quick_mult(r, zeta_sqrt) +} + +#[inline] +fn erf_core(x: DoubleDouble) -> DoubleDouble { + // x is always positive, here, should be filtered out before the call + + if x.hi <= 0.0095 { + // 0.0095 + // for small |x| using taylor series first 3 terms + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let z2 = DoubleDouble::quick_mult(x, x); + let p = f_fmla( + z2.hi, + f64::from_bits(0x3fb62847c47dda48), + f64::from_bits(0x3fc053c2c0ab91c5), + ); + let mut r = DoubleDouble::mul_f64_add( + z2, + p, + DoubleDouble::from_bit_pair((0xbc33ea2ef8dde075, 0x3fcdb29fb2fee5e4)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b)), + ); + // (rh + rl) * z = rh * z + rl*z + let v = DoubleDouble::quick_mult(r, x); + return v; + } else if x.hi <= 0.06 { + // 0.06 + // for |x| < 0.06 using taylor series first 5 terms + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let z2 = DoubleDouble::quick_mult(x, x); + let p = f_polyeval4( + z2.hi, + f64::from_bits(0x3fb62847c47dda48), + f64::from_bits(0x3fb0a13189c6ef7a), + f64::from_bits(0x3faa7c85c89bb08b), + f64::from_bits(0x3fa5eeb1d488e312), + ); + let mut r = DoubleDouble::mul_f64_add( + z2, + p, + DoubleDouble::from_bit_pair((0x3c2cec68daff0d80, 0x3fc053c2c0ab91c5)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc33ea2ef8dde075, 0x3fcdb29fb2fee5e4)), + ); + r = DoubleDouble::mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b)), + ); + // (rh + rl) * z = rh * z + rl*z + let v = DoubleDouble::quick_mult(r, x); + return v; + } + + if x.hi <= 0.75 { + // |x| < 0.75 + + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const P: [(u64, u64); 5] = [ + (0xbc3e06eda42202a0, 0x3f93c2fc5d00e0c8), + (0xbc6eb374406b33b4, 0xbfc76fcfd022e3ff), + (0xbc857822d7ffd282, 0x3fe6f8443546010a), + (0x3c68269c66dfb28a, 0xbff80996754ceb79), + (0x3c543dce8990a9f9, 0x3ffcf778d5ef0504), + ]; + let x2 = DoubleDouble::quick_mult(x, x); + let vz = DoubleDouble::full_add_f64(x2, -0.5625); + let ps_num = f_polyeval5( + vz.hi, + f64::from_bits(0xbff433be821423d0), + f64::from_bits(0x3fdf15f19e9d8da4), + f64::from_bits(0xbfb770b6827e0829), + f64::from_bits(0x3f7a98a2980282bb), + f64::from_bits(0xbf142a246fd2c07c), + ); + let mut num = DoubleDouble::mul_f64_add(vz, ps_num, DoubleDouble::from_bit_pair(P[4])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[3])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[2])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[1])); + num = DoubleDouble::mul_add(vz, num, DoubleDouble::from_bit_pair(P[0])); + + // Generated in Wolfram Mathematica: + // <75, MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]; + const Q: [(u64, u64); 5] = [ + (0xbc36337f24e57cb9, 0x3f92388d5d757e3a), + (0xbc63dfae43d60e0b, 0xbfc6ca7da581358c), + (0xbc77656389bd0e62, 0x3fe7c82ce417b4e0), + (0xbc93679667bef2f0, 0xbffad58651fd1a51), + (0x3ca2c6cb9eb17fb4, 0x4001bdb67e93a242), + ]; + + let ps_den = f_polyeval5( + vz.hi, + f64::from_bits(0xbffbdaeff6fbb81c), + f64::from_bits(0x3fe91b12cf47da3a), + f64::from_bits(0xbfc7c5d0ffb7f1da), + f64::from_bits(0x3f939ada247f7609), + f64::from_bits(0xbf41be65038ccfe6), + ); + + let mut den = DoubleDouble::mul_f64_add(vz, ps_den, DoubleDouble::from_bit_pair(Q[4])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[3])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[2])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[1])); + den = DoubleDouble::mul_add(vz, den, DoubleDouble::from_bit_pair(Q[0])); + let r = DoubleDouble::div(num, den); + let k = DoubleDouble::quick_mult(r, x); + let err = f_fmla( + k.hi, + f64::from_bits(0x3c70000000000000), // 2^-56 + f64::from_bits(0x3c40000000000000), // 2^-59 + ); + let ub = k.hi + (k.lo + err); + let lb = k.hi + (k.lo - err); + if ub == lb { + return k; + } + return inverf_0p06_to_0p75(x); + } + + let q = DoubleDouble::full_add_f64(-x, 1.0); + + let mut zeta = fast_log_dd(q); + zeta = DoubleDouble::from_exact_add(zeta.hi, zeta.lo); + zeta = -zeta; + let zeta_sqrt = zeta.fast_sqrt(); + let rz = zeta_sqrt.recip(); + + if x.hi < 0.9999 { + inverf_asympt_small(rz, zeta_sqrt) + } else { + inverf_asympt_long(rz, zeta_sqrt) + } +} + +#[cold] +fn inverfc_extra_small(x: f64) -> DoubleDouble { + // Reversed order for erfinv with direct identity without subtraction. + let q = x; + + let mut zeta = fast_log_d_to_dd(q); + zeta = DoubleDouble::from_exact_add(zeta.hi, zeta.lo); + zeta = -zeta; + let zeta_sqrt = zeta.fast_sqrt(); + let rz = zeta_sqrt.recip(); + if x >= 0.0001 { + inverf_asympt_small(rz, zeta_sqrt) + } else { + inverf_asympt_long(rz, zeta_sqrt) + } +} + +/// Complementary inverse error function +pub fn f_erfcinv(x: f64) -> f64 { + let ix = x.to_bits(); + + if ix >= 0x4000000000000000u64 || ix == 0 { + // |x| == NaN, x == inf, |x| == 0, x < 0 + if ix.wrapping_shl(1) == 0 { + return f64::INFINITY; + } + if ix == 0x4000000000000000u64 { + return f64::NEG_INFINITY; + } + return f64::NAN; // x == NaN, x == Inf, x > 2 + } + + if x == 1. { + return 0.; + } + + // we compute erfcinv through identity + // erfcinv(x) = -erfinv(1-x) + + static SIGN: [f64; 2] = [1.0, -1.0]; + + if x < 0.1 { + return inverfc_extra_small(x).to_f64(); + } + + let dx = if x > 1. { + DoubleDouble::from_full_exact_sub(2., x) + } else { + DoubleDouble::new(0., x) + }; + let sign = SIGN[(x > 1.) as usize]; + + let mut dx = DoubleDouble::full_add_f64(-dx, 1.); + dx = DoubleDouble::from_exact_add(dx.hi, dx.lo); + erf_core(dx).to_f64() * sign +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_inverfc() { + assert_eq!(f_erfcinv(0.12), 1.0993909519492193); + assert_eq!(f_erfcinv(1.0000000000027623e-13), 5.261512368864527); + assert_eq!(f_erfcinv(1.0001200000182189), -0.00010634724760131264); + assert_eq!(f_erfcinv(0.7001200000182189), 0.2723481758403576); + assert_eq!(f_erfcinv(1.5231200000182189), -0.502985998867995); + assert_eq!(f_erfcinv(1.99545434324323243), -2.0064739778442213); + assert_eq!(f_erfcinv(1.), 0.); + assert!(f_erfcinv(2.05).is_nan()); + assert!(f_erfcinv(-0.01).is_nan()); + assert!(f_erfcinv(f64::NAN).is_nan()); + assert!(f_erfcinv(f64::NEG_INFINITY).is_nan()); + assert!(f_erfcinv(f64::INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverfcf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfcf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverfcf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverfcf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::err::inverff::erfinv_core; + +/// Complementary inverse error function +/// +/// Max ulp 0.5 +pub fn f_erfcinvf(x: f32) -> f32 { + let ix = x.to_bits(); + let ux = ix.wrapping_shl(1); + if ix >= 0x4000_0000u32 || ux == 0 { + if x.is_infinite() { + return f32::INFINITY; + } + if ux == 0 { + return f32::INFINITY; + } + + if ix == 0x3f80_0000u32 { + return 0.; + } + // x > 2 + if ix == 0x4000_0000u32 { + // x == 2. + return f32::NEG_INFINITY; + } + return f32::NAN; // x == NaN, x < 0 + } + + let z = x as f64; + static SIGN: [f32; 2] = [1.0, -1.0]; + // inferfc(x) = -inverf(1-x) + // ax doesn't need to be extremely accurate, + // it's just boundary detection so will do subtraction in f32 + erfinv_core(1. - z, (1. - x).abs().to_bits(), SIGN[(x > 1.) as usize]) +} + +#[cfg(test)] +mod tests { + use super::f_erfcinvf; + + #[test] + fn m_test() { + assert_eq!(f_erfcinvf(2.), f32::NEG_INFINITY); + assert!(f_erfcinvf(-1.).is_nan()); + assert_eq!(f_erfcinvf(0.), f32::INFINITY); + assert!(f_erfcinvf(2.1).is_nan()); + assert_eq!(f_erfcinvf(0.5), 0.47693628); + assert_eq!(f_erfcinvf(1.5), -0.47693628); + assert_eq!(f_erfcinvf(0.002), 2.1851242); + assert_eq!(f_erfcinvf(1.002), -0.0017724329); + assert!(f_erfcinvf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverff.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/inverff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/inverff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,359 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::logs::simple_fast_log; +use crate::polyeval::{ + f_estrin_polyeval7, f_estrin_polyeval8, f_estrin_polyeval9, f_polyeval3, f_polyeval5, + f_polyeval10, f_polyeval11, +}; + +#[inline] +pub(crate) fn erfinv_core(z: f64, ax: u32, sign: f32) -> f32 { + if ax <= 0x3c1ba5e3u32 { + // 0.0095 + // for small |x| using taylor series first 3 terms + let z2 = z * z; + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let p = f_polyeval3( + z2, + f64::from_bits(0x3fec5bf891b4ef6b), + f64::from_bits(0x3fcdb29fb2fee5e4), + f64::from_bits(0x3fc053c2c0ab91c5), + ) * z; + return f32::copysign(p as f32, sign); + } else if ax <= 0x3d75c28fu32 { + // 0.06 + // for |x| < 0.06 using taylor series first 5 terms + let z2 = z * z; + // Generated by SageMath: + // from mpmath import mp, erf + // + // mp.prec = 100 + // + // def inverf_series(n_terms): + // from mpmath import taylor + // series_erf = taylor(mp.erfinv, 0, n_terms) + // return series_erf + // + // ser = inverf_series(10) + // for i in range(1, len(ser), 2): + // k = ser[i] + // print("f64::from_bits(" + double_to_hex(RealField(100)(k)) + "),") + let p = f_polyeval5( + z2, + f64::from_bits(0x3fec5bf891b4ef6b), + f64::from_bits(0x3fcdb29fb2fee5e4), + f64::from_bits(0x3fc053c2c0ab91c5), + f64::from_bits(0x3fb62847c47dda48), + f64::from_bits(0x3fb0a13189c6ef7a), + ) * z; + return f32::copysign(p as f32, sign); + } + + if ax <= 0x3f400000u32 { + // |x| <= 0.75 + let z2 = z * z; + + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // + // <70] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let r = z2 - 0.5625; + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,8}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval9( + r, + f64::from_bits(0x3fa329348a73d9d4), + f64::from_bits(0xbfd2cb089b644580), + f64::from_bits(0x3fed229149f732d6), + f64::from_bits(0xbff6a233d2028bff), + f64::from_bits(0x3ff268adbfbb6023), + f64::from_bits(0xbfddac401c7d70f4), + f64::from_bits(0x3fb3b1bd759d5046), + f64::from_bits(0xbf67aeb45bad547e), + f64::from_bits(0xbf01ccc7434d381b), + ); + // x0=SetPrecision[0.5625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,7}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_den = f_estrin_polyeval8( + r, + f64::from_bits(0x3fa1aac2ee4b1413), + f64::from_bits(0xbfd279342e281c99), + f64::from_bits(0x3feef89a353c6d1b), + f64::from_bits(0xbffa8f1b7cd6d0a7), + f64::from_bits(0x3ff89ce6289819a1), + f64::from_bits(0xbfe7db5282a4a2e1), + f64::from_bits(0x3fc543f9a928db4a), + f64::from_bits(0xbf888fd2990e88db), + ); + let k = (p_num / p_den) * z; + f32::copysign(k as f32, sign) + } else if ax <= 0x3f580000u32 { + // |x| <= 0.84375 + let z2 = z * z; + + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // + // <70] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let r = z2 - 0.84375; + // x0=SetPrecision[0.84375,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval10( + r, + f64::from_bits(0x3f116d07e62cbb74), + f64::from_bits(0xbf5c38d390052412), + f64::from_bits(0x3f92d6f96f84efe3), + f64::from_bits(0xbfbac9189cae446b), + f64::from_bits(0x3fd5dd124fb25677), + f64::from_bits(0xbfe49845d46b80ab), + f64::from_bits(0x3fe556c4913f60f8), + f64::from_bits(0xbfd59e527704e33b), + f64::from_bits(0x3fb07614a5e6c9f1), + f64::from_bits(0xbf60ce54a2d8a789), + ); + // x0=SetPrecision[0.84375,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_den = f_polyeval10( + r, + f64::from_bits(0x3f09fbdd1c987d1e), + f64::from_bits(0xbf5602ad17d419f4), + f64::from_bits(0x3f8efe31ea5bc71d), + f64::from_bits(0xbfb77e5f1bd26730), + f64::from_bits(0x3fd4c3f03e4f5478), + f64::from_bits(0xbfe5aa87dfc5e757), + f64::from_bits(0x3fe9c6406f9abc0b), + f64::from_bits(0xbfdff2f008b4db05), + f64::from_bits(0x3fc1123be5319800), + f64::from_bits(0xbf83be49c2d5cb9e), + ); + let k = (p_num / p_den) * z; + f32::copysign(k as f32, sign) + } else if ax <= 0x3f700000u32 { + // |x| <= 0.9375 + // First step rational approximant is generated, but it's ill-conditioned, thus + // we're using taylor expansion to create Newton form at the point. + // + // <70] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let x2 = z * z; + let r = x2 - 0.87890625; + // x0=SetPrecision[0.87890625,75]; + // NumberForm[Series[num[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval11( + r, + f64::from_bits(0x3ec70f1cbf8a758b), + f64::from_bits(0xbf1c9dff87b698d0), + f64::from_bits(0x3f5dfe7be00cc21c), + f64::from_bits(0xbf913fd09c5a3682), + f64::from_bits(0x3fb7ab0095693976), + f64::from_bits(0xbfd3b3ca6a3c9919), + f64::from_bits(0x3fe3533be6d1d8c8), + f64::from_bits(0xbfe48208ef308ac7), + f64::from_bits(0x3fd361a82dab69d1), + f64::from_bits(0xbfa2401965a98195), + f64::from_bits(0xbf54ba4d14ca54e3), + ); + // x0=SetPrecision[0.87890625,75]; + // NumberForm[Series[den[x],{x,x0,50}], ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[den[x],{x,x0,k}],{k,0,9}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_den = f_polyeval10( + r, + f64::from_bits(0x3ec0699f391e2327), + f64::from_bits(0xbf151ec184941078), + f64::from_bits(0x3f5717bb379a3c6e), + f64::from_bits(0xbf8beed3755c3484), + f64::from_bits(0x3fb46148b4a431ef), + f64::from_bits(0xbfd25690b7bc76fa), + f64::from_bits(0x3fe3f1b2f4ee0d9d), + f64::from_bits(0xbfe888a7a4511975), + f64::from_bits(0x3fdd84db18f2a240), + f64::from_bits(0xbfb844807521be56), + ); + let f = z * (p_num / p_den); + f32::copysign(f as f32, sign) + } else { + // Rational approximation generated by Wolfram Mathematica: + // for inverf(x) = sqrt(-log(1-x))*R(1/sqrt(-log(1-x))) + // + // <90] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let zeta = -simple_fast_log(1. - z); + let zeta_sqrt = zeta.sqrt(); + let rcp_zeta = (1. / zeta) * zeta_sqrt; + let p_num = f_estrin_polyeval8( + rcp_zeta, + f64::from_bits(0x3ff00072876c578e), + f64::from_bits(0x40314e00c10282da), + f64::from_bits(0x404f4a1412af03f6), + f64::from_bits(0x404c895cc0d9b1b3), + f64::from_bits(0x404545794620bfaf), + f64::from_bits(0x403264d21ea21354), + f64::from_bits(0x3fc5a5141dd19237), + f64::from_bits(0xbf8c2e49707c21ec), + ); + let p_den = f_estrin_polyeval7( + rcp_zeta, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x403151312c313d77), + f64::from_bits(0x405032345fa3d0cd), + f64::from_bits(0x4053e0a81d4c5f09), + f64::from_bits(0x4054fa20c5e0731c), + f64::from_bits(0x404620d7f94d4804), + f64::from_bits(0x4035d7400867b81f), + ); + let r = zeta_sqrt * (p_num / p_den); + f32::copysign(r as f32, sign) + } +} + +/// Inverse error function +/// +/// Max ulp 0.5 +pub fn f_erfinvf(x: f32) -> f32 { + let ax = x.to_bits() & 0x7fff_ffff; + + if ax >= 0x3f800000u32 || ax <= 0x3400_0000u32 { + // |x| >= 1, |x| == 0, |x| <= f32::EPSILON + if ax == 0 { + // |x| == 0 + return 0.; + } + + if ax <= 0x3400_0000u32 { + // |x| <= f32::EPSILON + // inverf(x) ~ Sqrt[Pi]x/2+O[x]^3 + const SQRT_PI_OVER_2: f64 = f64::from_bits(0x3fec5bf891b4ef6b); + return (x as f64 * SQRT_PI_OVER_2) as f32; + } + + if ax == 0x3f800000u32 { + // |x| == 1 + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + + // |x| > 1 + return f32::NAN; // |x| == NaN, |x| == Inf, |x| > 1 + } + + let z = f32::from_bits(ax) as f64; + erfinv_core(z, ax, x) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_test_inv_erff() { + assert!(f_erfinvf(f32::NEG_INFINITY).is_nan()); + assert!(f_erfinvf(f32::INFINITY).is_nan()); + assert!(f_erfinvf(-1.1).is_nan()); + assert!(f_erfinvf(1.1).is_nan()); + assert_eq!(f_erfinvf(f32::EPSILON), 1.05646485e-7); + assert_eq!(f_erfinvf(-1.), f32::NEG_INFINITY); + assert_eq!(f_erfinvf(1.), f32::INFINITY); + assert_eq!(f_erfinvf(0.002), 0.0017724558); + assert_eq!(f_erfinvf(-0.002), -0.0017724558); + assert_eq!(f_erfinvf(0.02), 0.017726395); + assert_eq!(f_erfinvf(-0.02), -0.017726395); + assert_eq!(f_erfinvf(0.05), 0.044340387); + assert_eq!(f_erfinvf(-0.05), -0.044340387); + assert_eq!(f_erfinvf(0.5), 0.47693628); + assert_eq!(f_erfinvf(-0.5), -0.47693628); + assert_eq!(f_erfinvf(0.76), 0.8308411); + assert_eq!(f_erfinvf(-0.76), -0.8308411); + assert_eq!(f_erfinvf(0.92), 1.2379221); + assert_eq!(f_erfinvf(-0.92), -1.2379221); + assert_eq!(f_erfinvf(0.97), 1.5344859); + assert_eq!(f_erfinvf(-0.97), -1.5344859); + assert_eq!(f_erfinvf(0.99), 1.8213866); + assert_eq!(f_erfinvf(-0.99), -1.8213866); + assert_eq!(f_erfinvf(0.7560265), 0.82385886); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![deny(unreachable_pub)] +mod erf; +mod erf_poly; +mod erfc; +mod erfcx; +mod erfcxf; +mod erff; +mod erffc; +mod inverf; +mod inverfc; +mod inverfcf; +mod inverff; +mod rerf; +mod rerf_poly; +mod rerff; + +pub use erf::f_erf; +pub use erfc::f_erfc; +pub use erfcx::f_erfcx; +pub use erfcxf::f_erfcxf; +pub use erff::f_erff; +pub use erffc::f_erfcf; +pub use inverf::f_erfinv; +pub use inverfc::f_erfcinv; +pub use inverfcf::f_erfcinvf; +pub use inverff::f_erfinvf; +pub use rerf::f_rerf; +pub use rerff::f_rerff; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,233 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::err::rerf_poly::RERF_HARD; +use crate::polyeval::f_polyeval7; + +#[cold] +#[inline(never)] +fn rerf_poly_tiny_hard(x: f64, z2: DoubleDouble) -> f64 { + // Polynomial for x/erf(x) + // Generated by Sollya. + // d = [0, 1/16]; + // f = x/erf(x); + // Q = fpminimax(f, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18|], [|107...|], d); + // See ./notes/r_erf_tiny_hard.sollya + const C: [(u64, u64); 10] = [ + (0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b), + (0xbc6d7696fe4a7cd0, 0x3fd2e7fb0bcdf4f2), + (0xbc0cb8b926064434, 0x3f842aa561ecc102), + (0x3c1cd94c2f3e6f09, 0xbf75207c7ef80727), + (0xbbb35c4effe3c87c, 0x3f2db4a8d7c32472), + (0x3bbf1d1edd1e109a, 0x3f20faa7a99a4d3d), + (0xbb9e05d21f4e1755, 0xbef3adb84631c39c), + (0x3b6ee5dc31565280, 0xbec366647cacdcc9), + (0x3b3698f8162c5fac, 0x3eaabb9db9f3b048), + (0xbb026f5401fce891, 0xbe66cd40349520b6), + ]; + let mut p = DoubleDouble::mul_add( + z2, + DoubleDouble::from_bit_pair(C[9]), + DoubleDouble::from_bit_pair(C[8]), + ); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[7])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[6])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(C[0])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + let z = DoubleDouble::div_dd_f64(p, x); + z.to_f64() +} + +#[inline] +fn rerf_poly_tiny(z: f64, x: f64) -> f64 { + let z2 = DoubleDouble::from_exact_mult(z, z); + + // Polynomial for x/erf(x) + // Generated by Sollya. + // d = [0, 1/16]; + // f = x/erf(x); + // Q = fpminimax(f, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18|], [|107, 107, 107, D...|], d); + // See ./notes/r_erf_tiny.sollya + let p = f_polyeval7( + z2.hi, + f64::from_bits(0xbf75207c7ef80727), + f64::from_bits(0x3f2db4a8d7c36a03), + f64::from_bits(0x3f20faa7a8db7f27), + f64::from_bits(0xbef3adae94983bb2), + f64::from_bits(0xbec3b05fe5c49f32), + f64::from_bits(0x3ed67902690892be), + f64::from_bits(0xbf3090033375e5ee), + ); + let mut r = DoubleDouble::quick_mul_f64_add( + z2, + p, + DoubleDouble::from_bit_pair((0xbc0cb29fd910c494, 0x3f842aa561ecc102)), + ); + r = DoubleDouble::quick_mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc6d7696ff4f712a, 0x3fd2e7fb0bcdf4f2)), + ); + r = DoubleDouble::quick_mul_add( + z2, + r, + DoubleDouble::from_bit_pair((0xbc8618f13eb7ca11, 0x3fec5bf891b4ef6b)), + ); + r = DoubleDouble::from_exact_add(r.hi, r.lo); + r = DoubleDouble::div_dd_f64(r, x); + let err = f_fmla( + r.hi, + f64::from_bits(0x3c10000000000000), // 2^-62 + f64::from_bits(0x3b90000000000000), // 2^-70 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r.to_f64(); + } + rerf_poly_tiny_hard(x, z2) +} + +#[inline] +fn rerf_poly_hard(x: f64, z2: DoubleDouble, idx: usize) -> f64 { + let c = &RERF_HARD[idx]; + let mut p = DoubleDouble::mul_add( + z2, + DoubleDouble::from_bit_pair(c[10]), + DoubleDouble::from_bit_pair(c[9]), + ); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[8])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[7])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[6])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[5])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[4])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[3])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[2])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[1])); + p = DoubleDouble::mul_add(z2, p, DoubleDouble::from_bit_pair(c[0])); + p = DoubleDouble::from_exact_add(p.hi, p.lo); + let z = DoubleDouble::div_dd_f64(p, x); + z.to_f64() +} + +/// Computes 1/erf(x) +/// +/// Max ulp 0.5001 +pub fn f_rerf(x: f64) -> f64 { + let z = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + let t = z.to_bits(); + let ux = t; + /* 1/erf(x) rounds to +/-1 for RNDN for |x| > 0x4017afb48dc96626 */ + if ux > 0x4017afb48dc96626 + // |x| > 0x4017afb48dc96626 + { + let os = f64::copysign(1.0, x); + const MASK: u64 = 0x7ff0000000000000u64; + if ux > MASK { + return x + x; /* NaN */ + } + if ux == MASK { + return os; /* +/-Inf */ + } + return f_fmla(-f64::from_bits(0x3c90000000000000), os, os); + } + + /* now |x| <= 0x4017afb48dc96626 */ + if z < f64::from_bits(0x3c20000000000000) { + // |x| < 0.0000000000000000004336808689942018 + /* for x=-0 the code below returns +0 which is wrong */ + if x == 0. { + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if z.to_bits() <= 0x38b7f12369dedu64 { + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + /* double-double approximation of 2/sqrt(pi) to nearest */ + const SQRT_PI_OVER_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc8618f13eb7ca89), + f64::from_bits(0x3fec5bf891b4ef6b), + ); + + /* tiny x is Taylor Series: 1/erf(x) ~ sqrt(pi)/(2 * x) + O(x^3), where the ratio of the O(x^3) + term to the main term is in x^2/3, thus less than 2^-123 */ + /* scale x by 2^106 to get out the subnormal range */ + let sx = x * f64::from_bits(0x4690000000000000); + let mut prod = DoubleDouble::div_dd_f64(SQRT_PI_OVER_2, sx); + // scale back by 2^106, since we're performed the division + prod = DoubleDouble::quick_mult_f64(prod, f64::from_bits(0x4690000000000000)); + return prod.to_f64(); + } + + if z.to_bits() < 0x3fb0000000000000u64 { + return rerf_poly_tiny(z, x); + } + + const SIXTEEN: u64 = 4 << 52; + let idx = + unsafe { f64::from_bits(z.to_bits().wrapping_add(SIXTEEN)).to_int_unchecked::() }; + let z2 = DoubleDouble::from_exact_mult(z, z); + rerf_poly_hard(x, z2, idx) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_erf() { + assert_eq!(f_rerf(65.), 1.0); + assert_eq!(f_rerf(3.), 1.0000220909849995); + assert_eq!(f_rerf(-3.), -1.0000220909849995); + assert_eq!(f_rerf(-0.03723630312089732), -23.811078627277197); + assert_eq!( + f_rerf(0.0000000000000000002336808689942018), + 3.7924667486354975e18 + ); + assert_eq!(f_rerf(2.000225067138672), 1.004695025872889); + assert_eq!(f_rerf(0.), f64::INFINITY); + assert_eq!(f_rerf(-0.), f64::NEG_INFINITY); + assert!(f_rerf(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerf_poly.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf_poly.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerf_poly.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerf_poly.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1331 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Poly for x/erf(x) generated by Sollya and SageMath: +```python +def build_sollya_script(idx): + return f""" +d = [{idx}/16, {idx + 1}/16]; + +f = x/erf(x); +Q = fpminimax(f, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], [|107...|], d); + +for i from 0 to degree(Q) by 2 do {{ + write(coeff(Q, i)) >> "coefficients.txt"; + write("\\n") >> "coefficients.txt"; +}}; +""" + +def load_coefficients(filename): + with open(filename, "r") as f: + return [RealField(500)(line.strip()) for line in f if line.strip()] + +def call_sollya_on_interval(idx): + sollya_script = build_sollya_script(idx) + with open("tmp_interval.sollya", "w") as f: + f.write(sollya_script) + import subprocess + if os.path.exists("coefficients.txt"): + os.remove("coefficients.txt") + try: + result = subprocess.run( + ["sollya", "tmp_interval.sollya"], + check=True, + capture_output=True, + text=True + ) + except subprocess.CalledProcessError as e: + return + +def print_coeffs(poly): + print("[") + for i in range(len(poly)): + coeff = poly[i] + print_double_double("", coeff) + print("],") + +print(f"pub(crate) static RERF_HARD: [[(u64, u64); 11]; 96] = [") +for i in range(0, 96): + call_sollya_on_interval(i) + coeffs = load_coefficients(f"coefficients.txt") + print_coeffs(coeffs) +print("];") +``` +**/ +pub(crate) static RERF_HARD: [[(u64, u64); 11]; 96] = [ + [ + (0xbc8618f13eb7ca89, 0x3fec5bf891b4ef6b), + (0xbc6d7696fe4a8276, 0x3fd2e7fb0bcdf4f2), + (0xbc0cb8b8ee1a9698, 0x3f842aa561ecc102), + (0x3c1cd7ccb69e95dd, 0xbf75207c7ef80727), + (0xbbaa394a1107572c, 0x3f2db4a8d7c32477), + (0x3b947772cadb5350, 0x3f20faa7a99a39f6), + (0x3b82456978771f64, 0xbef3adb844cdd880), + (0x3b37f7e102aeadc8, 0xbec366744e62af3d), + (0xbb4abc03ab72db68, 0x3eaaf1daea64176d), + (0xbb198547c9f8a468, 0xbeab1e39a7a0e2e7), + (0x3b7f74a4a9ee36d8, 0x3f04a9e81d9c80b1), + ], + [ + (0xbc8618f13eb7ca80, 0x3fec5bf891b4ef6b), + (0xbc6d7696fe4b2b7e, 0x3fd2e7fb0bcdf4f2), + (0xbc0cb8b91c2650c4, 0x3f842aa561ecc102), + (0x3c1cdab546730682, 0xbf75207c7ef80727), + (0x3bbb63455d753552, 0x3f2db4a8d7c3246e), + (0xbbb424fd3813a0d0, 0x3f20faa7a99a56cc), + (0xbb974ceb097ab454, 0xbef3adb846a857a7), + (0x3b61d21be7b25ec5, 0xbec3666116b38c11), + (0x3b3682e9db421864, 0x3eaab4cd09f0d085), + (0x3aa5c983c010eade, 0x3e03700f5101836c), + (0xbae41b274c7a5708, 0xbe5a9d21ba05e7ff), + ], + [ + (0xbc8618f13eace57e, 0x3fec5bf891b4ef6b), + (0xbc6d76974e25c204, 0x3fd2e7fb0bcdf4f2), + (0xbc0ca83c7b5744b0, 0x3f842aa561ecc102), + (0x3c18ce0252a1d68a, 0xbf75207c7ef80727), + (0x3bce42420bd5d0b7, 0x3f2db4a8d7c32516), + (0xbbb957874ae4a150, 0x3f20faa7a99a30ee), + (0x3b8ddca7ef22dfae, 0xbef3adb8467833bb), + (0xbb651d1f2d5b7a26, 0xbec3666141b05fd7), + (0x3aeee8bd696a7e40, 0x3eaab4da0fa3f61f), + (0xbaaea92dba36c4b8, 0x3e00fecb2644094c), + (0x3ac784c24cdd6540, 0xbe5a2dbb95d32849), + ], + [ + (0xbc8618f0f4f60562, 0x3fec5bf891b4ef6b), + (0xbc6d77a534ca7ed6, 0x3fd2e7fb0bcdf4f2), + (0xbbb70f4c473c9e00, 0x3f842aa561ecc102), + (0xbc1a977c9db0b237, 0xbf75207c7ef80734), + (0xbbc2d4a01ff162d0, 0x3f2db4a8d7c36d59), + (0x3b9b8c9eea11c018, 0x3f20faa7a991fd98), + (0xbb9b38ca273e4e60, 0xbef3adb841391777), + (0xbb4cea6e9e663e28, 0xbec36663999cb0ce), + (0x3b2c61386dab24b4, 0x3eaab533e624d8da), + (0xba652f7751c8cde8, 0x3df1a4ff38724196), + (0x3af4e3db417be62c, 0xbe597d9d709c8e08), + ], + [ + (0xbc8618a3e2026a77, 0x3fec5bf891b4ef6b), + (0xbc6e20944e2ac138, 0x3fd2e7fb0bcdf4f2), + (0x3c2e12ce437042e0, 0x3f842aa561ecc10c), + (0x3c12502cccbcf6b0, 0xbf75207c7ef80a4e), + (0xbbcb4f065498051c, 0x3f2db4a8d7cd2219), + (0x3bbf4b458bdec052, 0x3f20faa7a8e99ec9), + (0x3b961dfc4148cd3a, 0xbef3adb801226409), + (0x3b5a733630a550c8, 0xbec366748a484948), + (0xbb4a24fac279758a, 0x3eaab6b15bf3135e), + (0xba3e1e7b6682ff00, 0xbdf6bd63ad5e418d), + (0xbafc10a24873a1e6, 0xbe5883474fe6d074), + ], + [ + (0xbc85fe3dd629df7a, 0x3fec5bf891b4ef6b), + (0x3c7db7a5dd1476d1, 0x3fd2e7fb0bcdf4f1), + (0xbc2f10bd47f8beb3, 0x3f842aa561ecc2a2), + (0xbc171085831fc822, 0xbf75207c7ef859cf), + (0xbbad645d9fde8344, 0x3f2db4a8d8721804), + (0x3bb7d0c1a80cb912, 0x3f20faa7a1860459), + (0x3b8144a625fe24f0, 0xbef3adb626814084), + (0xbb6d54a39e361631, 0xbec366c6f18511c4), + (0x3b418b036802bd18, 0x3eaabb6edc1c9627), + (0xbaa73c33c857a12e, 0xbe1a953fd40d7420), + (0x3ad8027476e07af0, 0xbe573402996dd2c2), + ], + [ + (0xbc81b66a7b5ccff1, 0x3fec5bf891b4ef6b), + (0xbc79bd60b5b426c0, 0x3fd2e7fb0bcdf4e9), + (0xbc0a204cd030c544, 0x3f842aa561ece3d6), + (0xbbe49cde86af7e88, 0xbf75207c7efcfa9b), + (0x3bb2554e3ad0acc8, 0x3f2db4a8df415e4a), + (0x3bae907c3c53747c, 0x3f20faa76a3ce3dd), + (0x3b576ef184d414a0, 0xbef3adac5933f5ab), + (0xbb56367067dc7e24, 0xbec367fa0f7f75b1), + (0xbb3995c8812c5cd2, 0x3eaac7daac27d5c7), + (0x3acb5505cddd0ffc, 0xbe303e14c38cf6a0), + (0xbafad790a7b16c40, 0xbe5585acf166b0ba), + ], + [ + (0x3c85d1c9c211e918, 0x3fec5bf891b4ef6c), + (0x3c7dc0f172d28f0b, 0x3fd2e7fb0bcdf448), + (0xbc2cd8e027009eae, 0x3f842aa561eea354), + (0xbc086a077cc659f6, 0xbf75207c7f2b7b51), + (0x3bc0b8cda4fe6154, 0x3f2db4a91237a04d), + (0x3ba9afd26de84c3c, 0x3f20faa63672fc62), + (0x3b7fbd4c6465a488, 0xbef3ad83cf5114fe), + (0x3b6a7dda1ef6dceb, 0xbec36ba8282105aa), + (0xbb32111eb49ac7ac, 0x3eaae41105399da2), + (0x3add98a71b27ea8a, 0xbe402d0a88af1d02), + (0x3ae0a91f20394204, 0xbe5370d92bcc2a46), + ], + [ + (0x3c803817d1372452, 0x3fec5bf891b4ef86), + (0xbc50267f5364549c, 0x3fd2e7fb0bcdec86), + (0xbc09a8c6f2bdfb78, 0x3f842aa561ff6c1f), + (0xbc1481492e0d9a28, 0xbf75207c8084dac4), + (0x3bcd3db423b0d83b, 0x3f2db4aa36bdbd16), + (0xbbacf5bc5b2c622c, 0x3f20faa0e2396b76), + (0x3b9659a867f69cff, 0xbef3acf933a983ac), + (0x3b51d6f1b465e7fe, 0xbec3755a4ed1ff4c), + (0xbaf686c63e3ebca0, 0x3eab1d46ecad9463), + (0x3ad9001d67537478, 0xbe4cbb6369bcf991), + (0xbac3dba508ae78c8, 0xbe50f32dbe9334db), + ], + [ + (0x3c7e25fe9d726860, 0x3fec5bf891b4f0b1), + (0xbc7ab06652d76f68, 0x3fd2e7fb0bcda52f), + (0xbc279366f3014478, 0x3f842aa5627a5113), + (0x3c191084f4962937, 0xbf75207c8861bf8f), + (0x3bcc7278fec26fd4, 0x3f2db4af82fa6c34), + (0x3b607855cfa9f9c0, 0x3f20fa8d3e0a083b), + (0xbb9ad1bff06c0295, 0xbef3ab635e1ce916), + (0xbb52ac297a882c52, 0xbec38be316fa087e), + (0x3b3566206093fe92, 0x3eab86bb787edab1), + (0x3ad927375753f59c, 0xbe57893e809642e0), + (0x3adec7fd7dac2bae, 0xbe4c238076f40165), + ], + [ + (0xbc7450f4e5a34d6a, 0x3fec5bf891b4faf9), + (0x3c6070254f6c97c2, 0x3fd2e7fb0bcba54d), + (0x3c1f8f97820f81aa, 0x3f842aa56548d807), + (0x3bc2d77ef02fd540, 0xbf75207cadd38a6f), + (0x3bc008d39e65c4c1, 0x3f2db4c40d23ef77), + (0x3bcdc5ae5472cba9, 0x3f20fa4f4740e11c), + (0xbb75e14939f85e6c, 0xbef3a7522154b882), + (0xbb60f6b3a1eb8a9a, 0xbec3bae123763846), + (0x3b491b16febd3218, 0x3eac395e796a3137), + (0xbb0bab30884bdbf8, 0xbe6212bc42b9a2e0), + (0xbab8eccd2fe224e0, 0xbe45b61fe119ad92), + ], + [ + (0x3c76cf1bebd8f6be, 0x3fec5bf891b542d1), + (0xbc733582099fcc3e, 0x3fd2e7fb0bc009ee), + (0x3c0b172518bbd9b8, 0x3f842aa572cff422), + (0x3bdd3ab1da49a7e0, 0xbf75207d439ef930), + (0xbbbf954393296a6c, 0x3f2db5083a0025ae), + (0xbbc233ee942ade70, 0x3f20f9a4b3181e2c), + (0xbb9431141736d564, 0xbef39e09cd205f73), + (0x3b5c0416708c428a, 0xbec413c0641365e8), + (0x3b311ec7c02434ac, 0x3ead513298bd2dd3), + (0xbb0076afa010fc38, 0xbe6a400d6bbe9756), + (0x3ab039de17d27b28, 0xbe3da0ada3cb2927), + ], + [ + (0xbc80961ba80fa981, 0x3fec5bf891b6dccf), + (0xbc27d2093e9c3580, 0x3fd2e7fb0b8828f0), + (0xbc1b60797c0d2948, 0x3f842aa5a9bda8d4), + (0x3c08a71b89c8f1ae, 0xbf75207f44782913), + (0x3bbc75fe3c50b94c, 0x3f2db5ccf9b43f81), + (0xbba70122edae31f0, 0x3f20f805df1b6c19), + (0x3b92da280ec6be23, 0xbef38b05a18fa724), + (0x3b6e03aa9603e78a, 0xbec4ad11ca8a9f23), + (0xbb207645aa426dd4, 0x3eaee794c191d1e9), + (0xbb1277f7834b907b, 0xbe721f2390f45efb), + (0xbac2bab97552f26b, 0xbe2ee44166bd4092), + ], + [ + (0xbc86412a39a97d22, 0x3fec5bf891be76b4), + (0x3c6bce7a45dd0c50, 0x3fd2e7fb0aa56f36), + (0x3c2557e7253abfae, 0x3f842aa6683a6171), + (0x3c1559b4aafa5f9c, 0xbf7520853439abe3), + (0xbb931b56d2d59ec0, 0x3f2db7bf11a6dcfd), + (0x3bb30078186be24c, 0x3f20f484e99876bd), + (0xbb94ca3a5181c4ee, 0xbef367e9a00dd18a), + (0x3b622de077c887c0, 0xbec59eb568b2aedc), + (0x3b5b0c17a3645969, 0x3eb08516c078c57d), + (0x3b0b158910694e5a, 0xbe77daf6997136dd), + (0xba909415002bf356, 0xbdf90b2f8adaf43d), + ], + [ + (0x3c8eebcc5fdc47b3, 0x3fec5bf891dcc345), + (0xbc7bdeb76ca780cf, 0x3fd2e7fb0797f73d), + (0x3c10bf8295c1d6f2, 0x3f842aa89fda59cf), + (0x3bf71f4b638009f4, 0xbf7520947eb352dd), + (0x3bc81c2b39c7cfa7, 0x3f2dbc13cf992042), + (0xbbcd2ae351951d22, 0x3f20edc7c5c2c729), + (0x3b715d146b0c26a8, 0xbef32d944e41faf6), + (0xbb6803167e74aae4, 0xbec6f973a7c3b9d4), + (0xbb5698b55b8efe74, 0x3eb1d7b8c937b349), + (0x3b1b643c9a997ac0, 0xbe7dfd096f4a5fa7), + (0xba8fb6dd2d7a7030, 0x3e267fb86eba06c2), + ], + [ + (0x3c86dc4ce01692a8, 0x3fec5bf892422403), + (0x3c6e1211450bce0e, 0x3fd2e7fafeac6014), + (0xbbfac1ba719423a8, 0x3f842aae4848982d), + (0x3bf7686d089e7c08, 0xbf7520b68fd53c70), + (0xbbbfc998753b244c, 0x3f2dc4802e8aeb22), + (0xbba4c102da8c2be4, 0x3f20e25750bd0372), + (0xbb62a950af6d7a38, 0xbef2d72aa1889a4a), + (0xbb5d08f83a362a90, 0xbec8b99e783f6f6c), + (0xbb5a15ec3de1bc4b, 0x3eb35589957ab913), + (0x3b238126ff764adf, 0xbe8202891efeec09), + (0xbace98afae47d9fe, 0x3e363d29bdcd0d91), + ], + [ + (0x3c87e39a19b3d0c6, 0x3fec5bf89359d0b8), + (0xbc74ed6ab85ab940, 0x3fd2e7fae8fcf8a7), + (0x3c236cc1abf3c943, 0x3f842aba66ba4606), + (0xbc175eb282d39023, 0xbf7520f6d89f5b09), + (0x3bc0d4196881a655, 0x3f2dd28079e0bef9), + (0x3bc21692d4ce8e46, 0x3f20d1982ee796d5), + (0x3b677efb5a2869f0, 0xbef267c3cd8ec55d), + (0x3b61b3a6e7d66719, 0xbecab655d18fe460), + (0xbb5c2fcc91af77b1, 0x3eb4d3150ddbaa9c), + (0x3b23a75514e0479a, 0xbe84a998a5fc1c26), + (0x3ad030148c0b6a26, 0x3e3ebef94909972c), + ], + [ + (0xbc885896855a57a0, 0x3fec5bf895afed62), + (0xbc7f2cb90899316b, 0x3fd2e7fabfc54d4d), + (0xbc1101eb755b3912, 0x3f842acedf24073a), + (0x3c1d800e32be466e, 0xbf75215754e511d7), + (0xbbbd7331487b23d4, 0x3f2de52c38f47908), + (0x3bc0f459fff1ce70, 0x3f20bdc1658e0283), + (0xbb3e9c5de054df00, 0xbef1f28a151cbecb), + (0x3b646ea1f49d631e, 0xbecc91c3df6254c0), + (0x3b3f922df375d0bc, 0x3eb60fbb57ac269e), + (0xbb2adf22ce6fd8d8, 0xbe869dfb539fe8e7), + (0x3ae7ff8ad5344063, 0x3e4227d4022456f1), + ], + [ + (0xbc8ae090bfd1cee8, 0x3fec5bf898aa52a7), + (0x3c62380fa44cbb08, 0x3fd2e7fa9085783d), + (0xbc2bb2a4c308cd8c, 0x3f842ae3f8e02952), + (0xbc1a80c30380f9a9, 0xbf7521b0bf608ac3), + (0xbbcc1f24fab1d546, 0x3f2df4b9f3f226b4), + (0xbbbe2b985bc87e80, 0x3f20aee6ee37d5fe), + (0xbb956ef789bc02ec, 0xbef1a3ac85b7c6fa), + (0x3b64f04fb6389bef, 0xbecdb12073729082), + (0xbb5c530a33a8d714, 0x3eb6bba58e548b6b), + (0xbb28aa08bba90045, 0xbe8791f4b89ddd8a), + (0x3add8797a6eed87e, 0x3e435face41bc747), + ], + [ + (0x3c76800e5118cba2, 0x3fec5bf8955c5890), + (0xbc66b79aa48d850a, 0x3fd2e7fabdaeecb1), + (0xbc1d060b60882aea, 0x3f842ad29f1d0d93), + (0xbc0b7f7e1852d7de, 0xbf75217193e7b656), + (0xbbb1dfda43c4090c, 0x3f2deb4c771372b5), + (0x3bc2e3b7bf2030ec, 0x3f20b69da01bfa8a), + (0xbb74d03bd81ad920, 0xbef1c6b6437d4791), + (0x3b578508c016669e, 0xbecd44137495d835), + (0x3b33cb45437e37c4, 0x3eb68402b52f1038), + (0x3b1be6ce572b06ec, 0xbe874ebcad44d73b), + (0x3ab4e75545af6170, 0x3e4316a8f4237932), + ], + [ + (0x3c8936981c457407, 0x3fec5bf86fa67e7e), + (0x3c5d1fc5562f5e74, 0x3fd2e7fc9a6db835), + (0x3c2f4b2630af6de9, 0x3f842a290204d06b), + (0x3c1a6b67044328aa, 0xbf751f35151a87ad), + (0x3bca01fb3f4b9119, 0x3f2d9bfe8abb12df), + (0x3ba530023186fc68, 0x3f20f2eaaebdb0aa), + (0xbb85c5b20b084330, 0xbef2c599ff9e90f6), + (0x3b6259424427f91e, 0xbeca60d00700323e), + (0xbb529d2845b8c334, 0x3eb52404388a56a8), + (0xbaf9bbc47316c558, 0xbe85c134d3d72756), + (0xbae4bd922e473c2e, 0x3e418254e80c1fe1), + ], + [ + (0x3c77b49c8708d95e, 0x3fec5bf7d439ccf3), + (0xbc695b6d321a65b0, 0x3fd2e803977ec913), + (0xbc2b99b73f650bb7, 0x3f8427e578b0c50f), + (0xbbba4050af501080, 0xbf7518400f97e451), + (0x3bc8b775372d0f1d, 0x3f2cbb5d411da776), + (0x3bc0be4772912425, 0x3f218e6db0bf59c7), + (0x3b777ca8e20895b4, 0xbef51c15be0f3a57), + (0xbb6e2f3c48e85db8, 0xbec434774a0a089a), + (0xbb3c765ffe5eadec, 0x3eb276f3778acc12), + (0xbb0e4efe64d76c5c, 0xbe8300d68f0489e4), + (0xbac93f2262acf544, 0x3e3dec41980b63a9), + ], + [ + (0xbc8e50b3604c6456, 0x3fec5bf5f9905958), + (0x3c73af2096783c36, 0x3fd2e8171399b082), + (0x3c26b66b5099742e, 0x3f8422226134cb30), + (0xbbf2cecc14e6c1fc, 0xbf750815c60e91f8), + (0x3bcdb6c9be6c6293, 0x3f2adeea8a272502), + (0xbbb73d5d9ccadd56, 0x3f22bb838b4d286e), + (0x3b7ab2b233005e94, 0xbef93dba1ccdcc99), + (0xbb298d7a22372b18, 0xbeb47ed03a750fd0), + (0xbb3c07e8e0e06602, 0x3ead0ce153b552f1), + (0x3b00cfb58d5874fc, 0xbe7e9cfd756ceaaf), + (0x3abaa30adaab76ec, 0x3e37acea6cf7ffff), + ], + [ + (0x3c30ec78f45292a0, 0x3fec5bf143d22204), + (0xbc65249f97c5b9fc, 0x3fd2e8446c72543a), + (0x3c201cc14aa2fa0b, 0x3f8415d93f136226), + (0x3c0b56c2e9770fae, 0xbf74e8827285303e), + (0xbbb6e48066484c1c, 0x3f278a5f412a35b2), + (0xbbbbbb0c95d58fe4, 0x3f24a9089131326b), + (0x3b7a0d70ba412e64, 0xbeff71b80a68e993), + (0xbb11a7a28f6d7794, 0x3e9b91b885fa211a), + (0xbb42339bfc23dfbc, 0x3ea32030cab757da), + (0xbb1cda1488302a7e, 0xbe76157aada72026), + (0xbadf9a0d5ca2457c, 0x3e31131ffd0ba6ca), + ], + [ + (0xbc7ece76656bab74, 0x3fec5be6e950c0b7), + (0x3c63bb57e740537e, 0x3fd2e8a012e0fa7b), + (0x3c0575dc0334f2f4, 0x3f83ff0526acf1d1), + (0x3c044dc560ec8f12, 0xbf74b291f390e4df), + (0xbba350c48d6165b4, 0x3f224f839f50e0d8), + (0xbbcf4d7854c8f79d, 0x3f277180d211eb44), + (0x3ba94de841c700c9, 0xbf03d68928731504), + (0xbb5b205425b9350c, 0x3ec426773f6ea48b), + (0xbb1144f74a129450, 0x3e8ffe1e219179b5), + (0xbabc5212976e4640, 0xbe6a9699317cdb6b), + (0xbab5cec1a7ad7650, 0x3e25a54cb77230ab), + ], + [ + (0x3c7d3f135943435e, 0x3fec5bd2eb61db6c), + (0xbc61a1b9a1340f02, 0x3fd2e94353bc742e), + (0x3c19472444a43534, 0x3f83d9826b0583dd), + (0xbbf12099cc113f3c, 0xbf7460d083cf2916), + (0x3bb25fb6f0143753, 0x3f15ff639d8c7e95), + (0x3bcede86c1446be7, 0x3f2b084187ccc491), + (0x3b9a4dd307e02614, 0xbf08bbc0c1452f04), + (0xbb3417e35857f4d0, 0x3ed33caa76ba5931), + (0x3b1f52eb65326bfc, 0xbe7a134a03fb3e51), + (0x3ad82ac5fbd7ed1c, 0xbe545f84b2d562ea), + (0xbaa952213eabb426, 0x3e15c65f270ddf3a), + ], + [ + (0x3c61314e0f36eae0, 0x3fec5bb0fabf7432), + (0x3c4a7c9c8f10f7f0, 0x3fd2ea43cf632902), + (0xbc2bb7ae41d5a847, 0x3f83a2f96236fd49), + (0xbbe33588677f3160, 0xbf73f2d3185d3b37), + (0xbb893c2f894e5ec9, 0x3eee57818d9bc48d), + (0xbbcfddea70d9e657, 0x3f2f2a9378e5af2f), + (0xbb63ef176f255500, 0xbf0df3787dbe8741), + (0x3b655f1aa127557e, 0x3edc459e3ece2d4d), + (0xbb1e1661ae65e8e0, 0xbe9b0fc5cfefa97b), + (0xbad66f3fc66c8a1e, 0x3e3d44dc6438f8b4), + (0x3a8d0e6f53fcebaa, 0x3df3e3080e36d5ab), + ], + [ + (0xbc83c010ea9374dc, 0x3fec5b7f0b87a9f9), + (0x3c6a6947b642049a, 0x3fd2eba2164b914b), + (0x3c2634e3ab1d746a, 0x3f835dd772e0ef48), + (0x3bf0782b17d77b30, 0xbf737167e3a38e85), + (0xbbb40bdd48addf07, 0xbf1016d6fb297d24), + (0x3bcf4fce5e515ae2, 0x3f31adaaa086b765), + (0xbb8667e90e887a10, 0xbf116e09c64e2aad), + (0x3b733b8f1b2232c6, 0x3ee2148b515bbd2b), + (0xbb3bb2c4ed26a2da, 0xbea5da89dcd96f7f), + (0xbafdf9fe30fc648c, 0x3e5c23c03edd43fc), + (0x3a68ee4c14603a48, 0xbdfb0412417cab57), + ], + [ + (0xbc773b1b718353b8, 0x3fec5b423b9914bf), + (0xbc7f621dd963a3cd, 0x3fd2ed2f4cdcf43d), + (0x3c1377fcfefe24aa, 0x3f8314d842c3c294), + (0x3be8e3cbd7aeb3f0, 0xbf72f22b0bee15ab), + (0x3bc496dcb0a74226, 0xbf2124f7dd94863f), + (0xbbc478f070fc4cca, 0x3f3376cd8b422ad4), + (0x3bb72b86098b27ca, 0xbf13609490beb9b4), + (0xbb8a94963c37f01f, 0x3ee4fe73c72cd39c), + (0x3b4eb88aba09a145, 0xbeab93d2727633c8), + (0x3ada9fc93c355918, 0x3e64bc38f4bdd701), + (0x3aacb4db95da1717, 0xbe0b7c042bc74acf), + ], + [ + (0x3c7468673688468e, 0x3fec5b0e0b4ba59c), + (0x3c63faba1ee6b95a, 0x3fd2ee6e13906790), + (0x3c25d66fa927da0f, 0x3f82de1072840d12), + (0x3c049a24d8185b76, 0xbf7298e1fdd2f328), + (0xbbcb7522c6abdf2b, 0xbf271d739ebb595c), + (0x3b781acdc996cf00, 0x3f348f3e4ad28bed), + (0xbbb072bf3c89d176, 0xbf147e86a40b207b), + (0xbb7326b6cefec84a, 0x3ee68e6da7092266), + (0xbb4ab0ed312c8bf6, 0xbeae725d99148642), + (0x3ae0aa816b363984, 0x3e67dbdaa9091ad7), + (0xbab2ce220dadff17, 0xbe10cdaf22c2927b), + ], + [ + (0x3c59b93c25ba7460, 0x3fec5b0cbe5e774e), + (0x3c76bace4b68f17f, 0x3fd2ee7808bb5f14), + (0x3c23621dcf18db27, 0x3f82dc0fb77c520e), + (0xbc02d3c316b92c3a, 0xbf729538f26e0dcd), + (0xbbb5af2640454844, 0xbf2761ad24928630), + (0xbbbf891c477ebd78, 0x3f349c95434125d0), + (0xbba67df7fbd6d762, 0xbf148cc92ace3e89), + (0xbb8134dd93b8d72a, 0x3ee6a3128d6f907c), + (0xbb480c96baa85bb3, 0xbeae99327a49a987), + (0xbb010257aa03b053, 0x3e6806c7c36a2043), + (0x3a8d675538737ba0, 0xbe10f818a58178e7), + ], + [ + (0x3c4a20c2ffd8c330, 0x3fec5b8650dc1b3c), + (0x3c62ceb5ea6912b2, 0x3fd2ebf4d4343027), + (0x3c16415358b3f530, 0x3f833bcb9ed1448b), + (0xbba8e783f7cfa180, 0xbf731c5b9abc5061), + (0xbbaae1179ef013fc, 0xbf1f1c82ab22093f), + (0x3bd7061ebab8bd73, 0x3f335e45d67f5aad), + (0xbbb3588d8714539f, 0xbf1373beb7a74ded), + (0x3b7fb635c236f1be, 0x3ee54eaf0a4c3c7d), + (0x3b4b413e2552f1f8, 0xbeac7bf3734a2753), + (0x3ad1966368233040, 0x3e6608a4dfca5ed0), + (0xbaabd52ab1c1dbd7, 0xbe0e8e7eadc45948), + ], + [ + (0xbc86c6b99854f4ba, 0x3fec5ce2559d0e27), + (0xbc4a9e39820df128, 0x3fd2e52f5edc3a75), + (0x3c27e98d97a9a153, 0x3f842eb29566ca99), + (0x3c11cc01d593a0ec, 0xbf745f29c9e85745), + (0x3b89afdb819cd2f2, 0x3ef05af782dbcf48), + (0x3bd94f533f217e09, 0x3f30bc4a31a29779), + (0xbbbfbe37dbbc71f8, 0xbf11437d0d41d892), + (0xbb67d7e84495e1e8, 0x3ee2cfcf4d336454), + (0x3b3d0270024aa634, 0xbea8bf815c6422e7), + (0xbb05654d572091fa, 0x3e62b7e50b8b90f7), + (0xba85f715ca71b7dc, 0xbe094267189abccb), + ], + [ + (0xbc8b568ee19f600b, 0x3fec5fa0fcc15e00), + (0xbc64ae1ca196be12, 0x3fd2d850584e3d92), + (0x3c0a1c38b8779b7c, 0x3f85e1633267448c), + (0xbc13b2df368daa76, 0xbf767f05f772e0a9), + (0xbba0052ee0bdb2ec, 0x3f2df5e6488ca6b4), + (0xbbc5d74cdcf0270c, 0x3f299bbf35dee9e2), + (0x3b96ad64b65e89ec, 0xbf0c5fcccc6c2660), + (0xbb7ddbaa4fd30031, 0x3edf04a61deebc6f), + (0xbb4641f56fdb0c8d, 0xbea417ec3b158cd4), + (0x3af812e2551e8ff5, 0x3e5da8ee1deb57d9), + (0xba9c21a62c8f20b2, 0xbe036932312c05a8), + ], + [ + (0xbc47652f2b249250, 0x3fec6448d67cfe05), + (0x3c5afdb8fb1ae7ac, 0x3fd2c3bb4abd265f), + (0x3bf6ea0e9295baa8, 0x3f8870b03cea9b85), + (0x3c16e6edb6eaa9ce, 0xbf7983ef9ac59092), + (0xbbd53706eee79aa0, 0x3f40d717aff12a16), + (0x3b976cca73ed1ac4, 0x3f1f5b3b385c1df1), + (0xbba92870918744ca, 0xbf050c70db59e05d), + (0xbb68ce6bbed5291e, 0x3ed79ad9cab6b863), + (0x3b25baf1eee468b0, 0xbe9e56911c6c7a65), + (0x3acd5d9a83435b80, 0x3e55e780d4a0464c), + (0x3a8a364d35d45748, 0xbdfbd379eb2ab90c), + ], + [ + (0xbc86c14b725ebb7e, 0x3fec6b4995c9de08), + (0x3c7fb4771aa6f28f, 0x3fd2a6801486dfd3), + (0xbc1ddfd7f1a153ba, 0x3f8bdf67d031f37d), + (0xbc1586107ba99f80, 0xbf7d567e256e9203), + (0xbbd112a73c31475e, 0x3f4c04519837759b), + (0x3ba970117820cdb0, 0x3f01e26fbfb35d5e), + (0x3b917088f90c92fd, 0xbefa7c64efae669b), + (0x3b65bd710079150c, 0x3ed025b4f44232c3), + (0xbb3f4dc2dd3bca5a, 0xbe94fbfe22e2526d), + (0xbad2bf7e2a4b5574, 0x3e4de68ff4d747db), + (0xba66c7d262b0b8a0, 0xbdf284a620b476c7), + ], + [ + (0xbc84f871309252ee, 0x3fec74d76f950dde), + (0x3c73834d4a6e7629, 0x3fd280c9b1a7e591), + (0x3c3fa12d907a2b1e, 0x3f9007b78ba255a7), + (0x3c16d44c8e8e4772, 0xbf80dfb353df5a7b), + (0x3bfb84839bc97e6c, 0x3f541ace9d6f0acb), + (0xbb9f14a16e84e7e6, 0xbf0c5b9486ce16f6), + (0xbb624dbbbdce6efc, 0xbee6845e8710cd70), + (0x3b6b59eb1f7dce35, 0x3ec289bd217664a3), + (0xbb1a89e7d7c9c484, 0xbe89a757f8976281), + (0x3acb4ae14dab0160, 0x3e426e9030e70fe7), + (0x3a66a0ff13406f8c, 0xbde685814eb9c1cd), + ], + [ + (0x3c809dc339e7995b, 0x3fec80c5a9555a89), + (0xbc7ac33f6b3ca912, 0x3fd25430220cdd40), + (0xbc1d4879d501b850, 0x3f92600eb46b8925), + (0xbc2356327e3c25bb, 0xbf8336697f13a6f5), + (0x3bda184d42970a70, 0x3f5a3a7bf90daf85), + (0xbbcf8a4f720606fa, 0xbf2216381ceaccf0), + (0xbb5d74978d8f4ff4, 0x3ec3acc294571d2d), + (0x3b40f758a5d05eff, 0x3eab35536442f032), + (0xbb1ec9e02f4c63ac, 0xbe78f2289217918e), + (0xbabce0fe6cf01f98, 0x3e3350c3425bfb87), + (0xba4f5a4d99818b90, 0xbdd8030b1ab1d204), + ], + [ + (0xbc8d02acc1cc01da, 0x3fec8e6875ca6326), + (0x3c68a17807900ab2, 0x3fd223d750e2a6ce), + (0x3c3163ca3d33dbaf, 0x3f94c9473e76f76e), + (0xbc098c145f9a6988, 0xbf857e3609470780), + (0x3be47f0b24ee33a0, 0x3f5fe44219ffd11d), + (0xbbc84789e8a20cf6, 0xbf2bbb7875215acb), + (0x3b826e3c4224937a, 0x3eebbd791e5dd7a0), + (0xbb3acd5f8da0e7f8, 0xbe93a6327ea04bd4), + (0xbae90714b4795a94, 0xbe54e507e484f249), + (0xbab1e85380873c6b, 0x3e1b7573e2bacf04), + (0xba3301dce6665228, 0xbdc3b8ad84d29515), + ], + [ + (0x3c8d598cc241ff55, 0x3fec9c85c70ba99b), + (0xbc65e89f36890f9c, 0x3fd1f44f0f0625b4), + (0x3c367cbc3334c914, 0x3f9709a35c721473), + (0xbc23c533c2439634, 0xbf8783fdd8cab2f6), + (0x3bff4430c6d372ec, 0x3f6254c211749b8b), + (0x3bd7b84698e1faad, 0xbf31b9854d15a252), + (0xbb8cd24e4e9b2656, 0x3ef68a7163ed7349), + (0x3aee567652b74700, 0xbeb24689d2fed6d7), + (0xbaaf24ed7d5f8040, 0x3e6096c6454ced2d), + (0x3a94b5bb048a5dc6, 0xbdf3d8ad529aec47), + (0x3a352f915f1c25ab, 0xbd91ca14681e58d4), + ], + [ + (0xbc74394db20486d4, 0x3feca95a4f0eb301), + (0x3c4a618c39437380, 0x3fd1cb356c162992), + (0xbbd69159680e11c0, 0x3f98e3b24dd576a4), + (0x3bb8f7d83288ce80, 0xbf891917845064d2), + (0xbbf78d9838298862, 0x3f641b308822fb3e), + (0xbbc321121160c9d8, 0xbf3474c17c3e0cfb), + (0x3b9671925655ca8f, 0x3efc6107868e72b2), + (0x3b46dc53b07e8e38, 0xbebad58367e4fcc3), + (0x3b0b188021c3c3b6, 0x3e7087856ee75ad1), + (0xbaad266b1a1b870e, 0xbe17bf1e1306c8f8), + (0x3a4abb0faac45373, 0x3dadad8d29b6235a), + ], + [ + (0xbc7b6735f38dcae0, 0x3fecb2b42a201841), + (0xbc71582a96911b64, 0x3fd1aea941ad3474), + (0xbc1a5e42a8fa5814, 0x3f9a1d7ee70c5812), + (0xbc2046c34fb353f0, 0xbf8a18a3b401e573), + (0x3bf7ffd5734be186, 0x3f652c60953fad12), + (0x3bdd67e65789eb7f, 0xbf360556f51f1a8d), + (0x3b9c078fde66a698, 0x3eff90fa5f587ec6), + (0xbb3b345af7af1394, 0xbebf495ae99135f7), + (0x3b1ef4298de4a753, 0x3e749ca3314eb91b), + (0x3ac0bc479cb04d48, 0xbe204f74fb426011), + (0x3a540203e5d5fe1e, 0x3db78557e884da1f), + ], + [ + (0x3c7b9948887e3e30, 0x3fecb620c520b78a), + (0xbc5cab423bfd4cb4, 0x3fd1a4a30f1a92da), + (0x3c2937d3e12e5ef0, 0x3f9a8725b90119cc), + (0x3c2a939091181278, 0xbf8a6b215fafec97), + (0x3b842353662cd800, 0x3f6580eb53280d97), + (0x3bd5dbe311f5e11e, 0xbf367c2d0446d766), + (0x3ba105d1260b0e81, 0x3f003c7ffe8bc37c), + (0xbb5bdc4485e10110, 0xbec04002440fd45b), + (0xbaf45c45a6300d6c, 0x3e75ada1d2518cd8), + (0x3a9e8e805aba9430, 0xbe216bcc91193d8a), + (0xba49ad660ab34b8e, 0x3db99a7a2668e27b), + ], + [ + (0xbc2947bf41bc9e00, 0x3fecb126f017035d), + (0xbc7899059f5b8bb1, 0x3fd1b25105f6bdf3), + (0xbc0895d0113bfb18, 0x3f99ffbf6823d4f5), + (0xbc0f10a553f5d368, 0xbf8a07d8fb6fb3de), + (0xbc0c7ec3a21f454e, 0x3f65215c13d9b6ff), + (0x3bd1b601cf9453e4, 0xbf35fe063a62e384), + (0x3b8827981ea2380a, 0x3eff91aca599febb), + (0xbb2fc16dac065cc8, 0xbebf5d1e288c9e5c), + (0xbaeef186161095a0, 0x3e74bd8a1c9555bc), + (0xbacc403521f2eaf1, 0xbe2080eb36ed965e), + (0xba3f86e752c89df8, 0x3db7fcd3a5bdb4d8), + ], + [ + (0x3c8bcee7c8181d39, 0x3feca18848848e82), + (0x3c69fc813308a73c, 0x3fd1db84d997da00), + (0x3c3c53850ba9a712, 0x3f98786cc1d7bdc5), + (0xbc2ca52fc8e5b866, 0xbf88f4811c08cd00), + (0x3bff40da3a5c6bdc, 0x3f64230b2277791f), + (0xbbca96457825fbbc, 0xbf34bbd65de2655f), + (0xbb8f50c40c736b46, 0x3efd5ab0bde82aa8), + (0xbb50eafc87b58e98, 0xbebcb0d4a3c5aff1), + (0x3b089e7298344bb0, 0x3e729f7e0e19e149), + (0xba7bdb04058a0820, 0xbe1d07eae288fa78), + (0xba4b0253c12941ea, 0x3db4a07f49c5130b), + ], + [ + (0xbc89edfc54aa2483, 0x3fec857c1cd41af6), + (0xbc5a659387945ca0, 0x3fd2225424e8bcf6), + (0x3c377fc2e3bc7889, 0x3f95f4c4f8ed59c3), + (0x3c2c4286b497cf7c, 0xbf87430db00b9afa), + (0x3c073f64e00247cb, 0x3f62a3e0f44a96a2), + (0xbbbd945716fa0818, 0xbf32eb40cc8f3c79), + (0xbb89740359a8ca0e, 0x3efa4c36e442171d), + (0xbb15318efd8f9b50, 0xbeb9290343025508), + (0x3b0452efb2ecf7c8, 0x3e6fe4933deba02f), + (0x3abe6d64af899514, 0xbe183869735ef3a0), + (0x3a34e4c2dbab070c, 0x3db0bc589c565cf5), + ], + [ + (0xbc79fbf2f033ddfa, 0x3fec5be1ae114ebf), + (0x3c62fd50833dbe24, 0x3fd286e5752eafab), + (0xbbd5a1098dc5b600, 0x3f92897c1dc47bc3), + (0x3c1904c95a070666, 0xbf850eaed8497ba0), + (0xbbd04ac48084a568, 0x3f60c6331075f2b6), + (0x3bbf3f5b46bed4bc, 0xbf30c0b464b7bc75), + (0xbb98f7dad74f10c4, 0x3ef6cdf21e81cb9a), + (0x3b44e287afdd458a, 0xbeb54c027ef829be), + (0xbb0e9493b04030bd, 0x3e6a48ce7c9a8f3a), + (0x3ab2e43f966ce1b5, 0xbe136513318f7913), + (0x3a1693d5d1266bc0, 0x3da9ff3e55e5505b), + ], + [ + (0x3c194781c55e3f00, 0x3fec24612d8075f9), + (0x3c42c7b224a571e8, 0x3fd3077421970e7e), + (0x3c2f8a4e5c0c1a72, 0x3f8cb2bb0e6bd65c), + (0x3c26ce9b18985937, 0xbf82784bfab50a33), + (0xbbf575cf19a4e653, 0x3f5d5a00e338fbc3), + (0x3bb58b5f972663f2, 0xbf2cd6470bd0df26), + (0xbb9d14973ed1a406, 0x3ef3329bb4ddacb9), + (0xbb594a948357e8a2, 0xbeb17992005b48da), + (0xbae1a67f3edd9b50, 0x3e64f7cb2aa0a2a1), + (0x3aa41767e302bcd7, 0xbe0e0619d8c4b803), + (0x3a42aa74db3d3d98, 0x3da37e072fc79210), + ], + [ + (0x3c8d85ecbc120409, 0x3febdf79b3f36264), + (0x3c4ae0e5eb5f4e28, 0x3fd3a081ec9e8dc3), + (0x3c263a71c416c207, 0x3f8322a212289954), + (0x3be52b87741ca630, 0xbf7f4624e1cf93c2), + (0x3beb1990f8049eec, 0x3f58f1f394dd9af0), + (0xbbc35bb151b25d75, 0xbf2822f4710adeee), + (0xbb887c15268e3c40, 0x3eef6e32a041feb1), + (0xbb4c7bc7c59ec68c, 0xbeabdf462f9e52f8), + (0x3b054e47e872ed22, 0x3e603f5ed0b63b43), + (0xba8c028decc6d7ec, 0xbe068f73246295da), + (0xba3dbbf54cb0eec2, 0x3d9c5cdde2869e86), + ], + [ + (0xbc5b64600e93c3c0, 0x3feb8e7bcdfa2551), + (0xbc5edb222388a5a4, 0x3fd44d2c26cbf7ab), + (0x3c150066d9ee763d, 0x3f718ffba24f3952), + (0x3c09a588d15d0ddc, 0xbf7962e4ef5c450f), + (0xbbfea7fbc24ad3bd, 0x3f548ce8089a5348), + (0xbbbb19fd9ed05e78, 0xbf23a326550eca65), + (0x3b4883cab8f6a4d0, 0x3ee908398ae19492), + (0xbb3dae34b83d0a7e, 0xbea5a1d18b74c1ad), + (0x3af6481f3bef8e86, 0x3e5881b400db6b43), + (0x3a9febede716e6a0, 0xbe007fd85744e496), + (0xba3e753baebb1cb9, 0x3d94159b20d20045), + ], + [ + (0xbc8e0384101b69ae, 0x3feb3372978b846c), + (0x3c7b389bd1e1869a, 0x3fd507973f33deca), + (0x3be2e93210bce21a, 0xbf4f4d350dde3443), + (0x3c1dbbd2ec26225d, 0xbf738585a37ac336), + (0x3be34b6c09c314de, 0x3f50587dfefd189d), + (0x3bacacf0dbcad6b4, 0xbf1f014a3f2c06fd), + (0xbb8fcbc2dcbf78a5, 0x3ee362604eb5e17c), + (0xbb454b555003d9a0, 0xbea0576c9981626c), + (0xbaf474992319e3e5, 0x3e5200504cc51756), + (0xba9a6909449d2d57, 0xbdf7846656305e2c), + (0xba2cc3f7de9c46f8, 0x3d8bbadfc202f815), + ], + [ + (0xbc8a3a50aa1d0747, 0x3fead0ff0244e221), + (0xbc7a4fcbad89546e, 0x3fd5c9637406d596), + (0x3c19bbcf5493a8bd, 0xbf795f996b9bda39), + (0x3c0b49da59645f55, 0xbf6bc68547b5094f), + (0xbbdb42f1472d8fc6, 0x3f48ed03525fcc78), + (0x3b773bee95e6a5c0, 0xbf17aa1e224a084b), + (0xbb7dce71fb3e3715, 0x3edd215cc70f90bc), + (0xbb2a0ef6b971411c, 0xbe980113baf025cd), + (0x3aee70cf25ebaad4, 0x3e49be8d01e22c7d), + (0xba94bf3997882434, 0xbdf054d1d63dc91a), + (0x3a20f0241013c27d, 0x3d82ab14512ab887), + ], + [ + (0xbc8f9b01fd279096, 0x3fea6a29d58c33b7), + (0xbc674dce8d0d0f3c, 0x3fd68c1eb8e2979d), + (0x3c1bfcc8cbb07d48, 0xbf870f223a0c0167), + (0xbbfb9ab59aae5a80, 0xbf614c2e57681df0), + (0xbbd2b24814ac2946, 0x3f41faa38f77e2dd), + (0xbbb53e8ed6013a54, 0xbf1158f6fd950634), + (0x3b682bf413594436, 0x3ed526b8cc5a388b), + (0xbb2f4bc0688a4900, 0xbe9117b230bc51cb), + (0xbae98263a8ee88cd, 0x3e41e2b3a3f437f8), + (0x3a78e8eb32b2b25c, 0xbde61231934d9184), + (0xba1a8267a0ec97a6, 0x3d787cedf94e959b), + ], + [ + (0x3c77d79c50a3711c, 0x3fea0231475ff3ae), + (0xbc76363fa4e751ce, 0x3fd749aa5223f7e6), + (0xbc3ba545d09d93bf, 0xbf9063ae7ef70c82), + (0x3bd3d8a5dcae02b8, 0xbf4f618f89fa450f), + (0xbbd20ab97faf56c8, 0x3f37e458b1e356d2), + (0xbb86ee12886504d4, 0xbf0821cfdc163182), + (0x3b2399e77fb2aac0, 0x3ecd75466a96fffa), + (0xbb2ba6075e89c324, 0xbe87796133348897), + (0x3ade02e57201493d, 0x3e380bfa3749564d), + (0xba46d184faf9c670, 0xbddcee3600927b2c), + (0x39f3dd4c231ece36, 0x3d6f362ec2a3967b), + ], + [ + (0x3c735b83158e076c, 0x3fe99c56d0c67edb), + (0xbc7a0b939d383a3d, 0x3fd7fc8d884ba6f2), + (0xbc258d70b80083a0, 0xbf94cedb0ec61a6e), + (0x3ba17e34a4e241e3, 0x3f0bcb4f74b08e2f), + (0xbbbd6ec88c065d10, 0x3f2b6b788359e8dd), + (0xbb940711b6ddbb99, 0xbeff16fca1811824), + (0x3b664cd0d6355e5b, 0x3ec3660dc6b130e1), + (0xbb1e6e3b0d706c32, 0xbe7ec91c367ea244), + (0x3ace61b5d0d8a422, 0x3e2f0cc3ffc61fb0), + (0xba4afae6d7bdc6e0, 0xbdd2476a6857058d), + (0x3a00d53a0573b0fc, 0x3d633a7716320ae7), + ], + [ + (0xbc79381c4b156290, 0x3fe93bb13b9992ac), + (0x3c7970515413bd0e, 0x3fd8a031c4b5878f), + (0x3c2031b5b4ec6b42, 0xbf98b46c9b7757e1), + (0xbbc736951053a998, 0x3f4de4c5bf840851), + (0x3ba8c149b58a4e02, 0x3f15754d3047c4dd), + (0xbb949f7b0a34b5b6, 0xbef18508262de66c), + (0xbb45552c936dac08, 0x3eb778e548c6b669), + (0xbb1a6048f183d296, 0xbe72eab94b8e28a2), + (0x3ac7391c2bf764c2, 0x3e22fc01dac54242), + (0xba57caf213001686, 0xbdc6050b8d7ebfb9), + (0x39ec1d99f5c2d0ac, 0x3d56b075f6914b50), + ], + [ + (0xbc6bef6c010a9dc8, 0x3fe8e305fd2cb54e), + (0x3c57932d301d71e4, 0x3fd9310711c87531), + (0x3c386a44ecd2809e, 0xbf9c0829c8db1297), + (0x3befcbf5dbe22972, 0x3f5a8ae87061dead), + (0xbb7c9eb3c41756f8, 0xbef44394ab78a55e), + (0xbb7a0c67c82446cc, 0xbedc78b9f90cda78), + (0xbb420fd732d8f516, 0x3ea847cae47a2a7b), + (0x3afb56e020c7a39e, 0xbe64e6bb322f4510), + (0xbab3903c2be6b225, 0x3e155d1a9adaec94), + (0x3a44a03f19abf2cc, 0xbdb8bcefe707e8fc), + (0xb9d2417a35fd5cf8, 0x3d492f55542093f8), + ], + [ + (0xbc862c4896b0b83d, 0x3fe894abe4a5b9dc), + (0x3c7fe5c1c461460b, 0x3fd9ac922ad51dca), + (0xbc33c291e0f24f05, 0xbf9ec58118c16c40), + (0x3c0cf0b67c87e94e, 0x3f61e13d56b8940f), + (0x3b6a790492e66540, 0xbf196af8349e4224), + (0x3b31fa44d2bbd27e, 0x3ea2c42b70c9face), + (0x3b2da20edbf59d2a, 0x3e9026f15ff2ee68), + (0x3ae76f3d337ed97c, 0xbe526e097fd57d38), + (0x3a9b983a79d51a18, 0x3e049a10a6c5b670), + (0x3a3dc119a1c2f37a, 0xbda8a67c2aff9c17), + (0xb9b2a4fe2b205130, 0x3d394c38265362bb), + ], + [ + (0x3c77751441c8d3b4, 0x3fe8527813695aa2), + (0x3c684eaa21e959ac, 0x3fda1166ea70106b), + (0xbbdf4a6612c53b00, 0xbfa07734e6653b74), + (0x3c0c7623498c8faa, 0x3f6563a6d917beff), + (0xbbbd20a58a820126, 0xbf2431a6af0bf8de), + (0x3b7d336f20d13d06, 0x3ed83dd6dda34654), + (0xbb0b79b53e2c9b8a, 0xbe785be48d0ea29c), + (0xbabeae4dddf12aee, 0xbe277cc09aefafd0), + (0x3a59b67c103ee0d0, 0x3de9bcf4059586a2), + (0x3a36708298b1f001, 0xbd92977be7d90308), + (0xb9995f674b559478, 0x3d24a39363573224), + ], + [ + (0x3c88059266015c63, 0x3fe81db53af85c81), + (0x3c789ce0c91db2ea, 0x3fda5f12f3ca50da), + (0x3c4fff4eb90f91b4, 0xbfa1450b1759f5fd), + (0xbc0a5bae5f820112, 0x3f67ea33ae8225ad), + (0x3bab3e1e966adef4, 0xbf296683eed1efcc), + (0x3b558fbcb75a4300, 0x3ee37b35afee8bcf), + (0x3b378b11a48054f7, 0xbe948b0f763cdd6e), + (0xbadc68d151c5bcb6, 0x3e3b2ec7f8804690), + (0x3a7a42b7c2cfda06, 0xbdd15431166629c5), + (0x39c2cae40190fb38, 0xbd4254e40504074e), + (0xb99f9b3ffd3df550, 0x3cfd32cfd9ee6824), + ], + [ + (0x3c87852e7149316e, 0x3fe7f7244909eafb), + (0x3c7d8b1870b59b84, 0x3fda95fcf538479f), + (0xbc2dd434dbc26fe4, 0xbfa1d1cca085a602), + (0x3c0f3d9182229bc7, 0x3f6995d566fe00f2), + (0xbbce4c25eba9cee0, 0xbf2cbb2cd72dbf60), + (0xbb6230a87de521a4, 0x3ee8091a0ed3ca17), + (0xbb335f025a60c368, 0xbe9d316349e5762a), + (0x3aed896b5a4d66cf, 0x3e48db6f436655ec), + (0xba8d11019695e34c, 0xbdebeca2e7bfe62e), + (0x3a13d9003f78f398, 0x3d825e2abee6700c), + (0xb990404712f30786, 0xbd04fd8e7f84648d), + ], + [ + (0xbc7d8fda24c8dc12, 0x3fe7df050ce33e3b), + (0x3c74e2e804ecc588, 0x3fdab73cea883ea5), + (0xbc2f5e041ad627c8, 0xbfa2244d670961da), + (0x3c084c14e3d4348d, 0x3f6a887a1549f65c), + (0xbbad4fb99d51b250, 0xbf2e8f85a842c421), + (0xbb6484129b1a6f58, 0x3eea7507df06e1f0), + (0xbb28afff859217ec, 0xbea0d29386ae890a), + (0xbad0e96cc5515e0e, 0x3e4e7874a63969fb), + (0xba9457f9482630cf, 0xbdf29b66626d984b), + (0x3a061faa1b0f8ae4, 0x3d8b7a97aa5e6073), + (0x39b8132f149882ca, 0xbd1289bc81c39d03), + ], + [ + (0x3c7858d5859b0790, 0x3fe7d524fa022593), + (0x3c7ab8681f9b2dda, 0x3fdac471728a6e5c), + (0xbc392a31bd2c45e0, 0xbfa24416aa73c1ed), + (0x3c0d03e98625a176, 0x3f6ae329e0be0f25), + (0x3bb3ba40a20c6278, 0xbf2f39530a88b387), + (0x3b683affc9a4f36c, 0x3eeb4f0eff41c408), + (0x3b4b93014e8d4280, 0xbea194ff496f4fa6), + (0x3affa9cc8e999f15, 0x3e502a0196d40303), + (0x3a87d9e18ef0015c, 0xbdf4191a6c0fa6f9), + (0x3a016447bf89fbf8, 0x3d8e50d97a2071b0), + (0x39a41134a604833c, 0xbd14f7987074c37a), + ], + [ + (0xbc8849b77320b1d6, 0x3fe7d8f21fcc2d5c), + (0x3c6e500d1903dbf0, 0x3fdabf9588f99816), + (0xbc41e8febc95a3f6, 0xbfa238e8af85956a), + (0x3bf7cb20d4422e6c, 0x3f6ac4adc7f7de78), + (0x3bcc4e80d908858a, 0xbf2f02c60cfb5d78), + (0x3b8e622bcfcd200d, 0x3eeb0c1f999348b0), + (0x3b38a070b3ab8ed8, 0xbea15bf677ada740), + (0x3abb3aa525a7aa40, 0x3e4fceb78e014b78), + (0xba88b19b0e21f96c, 0xbdf3b2e2d550cf5f), + (0xb9c60dd540ad3700, 0x3d8d970d5bc2a4c6), + (0xb9be83c8c31b4a6b, 0xbd145fa013479421), + ], + [ + (0x3c79295ebf3ef4c4, 0x3fe7e9900e8c4c05), + (0x3c717516935a5da6, 0x3fdaaad9baaf12a4), + (0x3c4c9b35ae24337b, 0xbfa20a56ed057c52), + (0x3c044bdda20e1933, 0x3f6a48b3b812e527), + (0x3ba9b9db34d0c628, 0xbf2e2a29e903ce84), + (0xbb8eca303b9b0d7d, 0x3eea0897d78deb13), + (0x3b2024794b273684, 0xbea08401e50fb51f), + (0xbae524c48f70dcb6, 0x3e4de1cd5f227b76), + (0x3a93df2981146671, 0xbdf241b2a7dd10b3), + (0x3a20275bd58bf3a8, 0x3d8b078eda0da34e), + (0xb975173cc6f8cdc0, 0xbd1253ddd72c126b), + ], + [ + (0x3c62ceb50bd97224, 0x3fe805ed671a8ed0), + (0x3c7b6351621a7e0a, 0x3fda888206fd30ef), + (0xbc4584aecef194b1, 0xbfa1bf7d67de3096), + (0xbc08df5dab1e3e31, 0x3f69875818cc1132), + (0xbb95e8f170b42d00, 0xbf2ce258acfa7ad8), + (0xbb7ce9c19cd3375a, 0x3ee88b766706b93c), + (0x3b3b55602543baa8, 0xbe9ea08995007a03), + (0xbad3cfda551ad0a4, 0x3e4b3836accb970b), + (0x3a7ce45c5bf4a770, 0xbdf052539f32ed36), + (0x3a0d7e61158a35fc, 0x3d87b2188a7de05d), + (0x39aab32ffc3fe31c, 0xbd0f7c473b9d736f), + ], + [ + (0xbc76c7483e675afc, 0x3fe82cd81ce66983), + (0xbc5ef5d3caaba448, 0x3fda5aca2a9e1224), + (0xbc4a4d027a0a8332, 0xbfa15ecf0dfd892e), + (0x3be2c1d3462002d8, 0x3f689503837e3442), + (0xbbc509f8a68e8ca2, 0xbf2b53b6f662cf45), + (0xbb60f335fd78f46c, 0x3ee6c9c7668886b1), + (0xbb3a5a0cabb87303, 0xbe9bdff1f2d05298), + (0xbae3d6fb4768ef6f, 0x3e484322f27254ec), + (0xba5cfbb17d2ed970, 0xbdec78e7274dd815), + (0x3a0fae6fdd22043c, 0x3d8435a56ec10a68), + (0x398a0afc8fdd84cc, 0xbd0a3d84b2a469ec), + ], + [ + (0x3c85275019a63bb1, 0x3fe85d0f9ead23a9), + (0xbc7974d5f2d0ab34, 0x3fda23d053d2b1f9), + (0x3c25be352012ca48, 0xbfa0edf91eeb8a5a), + (0xbbfa726a80174ca0, 0x3f678284e4bab95d), + (0xbbcceccff8d62cba, 0xbf299d7803f58699), + (0x3b20eb35873a9940, 0x3ee4e9f7283f6640), + (0x3b3641fc5b936877, 0xbe9906486da98e29), + (0x3aea438a4fcdd9f2, 0x3e454a362a3889a6), + (0xba82ae66c2606eaf, 0xbde867553e123f52), + (0xba231385b8b89c0f, 0x3d80e8b863b8cec3), + (0x399dbb221e9dfdb4, 0xbd056bb50a6179c5), + ], + [ + (0xbc8345a68bce03f8, 0x3fe895541a035cf4), + (0x3c6a9a13b818bbe8, 0x3fd9e58630317028), + (0x3c3e5e56ece03e20, 0xbfa071d825df20c5), + (0xbc043060f7b87f82, 0x3f665d556fbb2b9e), + (0x3bbb55c0244c2894, 0xbf27d6fef71eedec), + (0x3b806a3db3cffa6e, 0x3ee306dbc230ea08), + (0xbb2fcb3bd608fa04, 0xbe963cfb5eb7dc39), + (0x3ad8bdca1f8849c6, 0x3e4277fcbf00c0f2), + (0x3a79b5a7f6701dda, 0xbde4a77f1e97bc2a), + (0x39ee8bc647b19098, 0x3d7be97fa139ec70), + (0x39a742e93993d7e6, 0xbd013be949b0c1df), + ], + [ + (0x3c85a304157923b2, 0x3fe8d4728500ffee), + (0xbc71876145eae8b8, 0x3fd9a1a7b920519b), + (0xbc3d2ec62d32922e, 0xbf9fdcf4fe2e6866), + (0xbbcb05a4e91bc710, 0x3f652ff5c4a490a2), + (0xbbc9fb86475d7c78, 0xbf26113d24d89dd2), + (0x3b6e06275e8ce9b4, 0x3ee1325b7e36d29e), + (0x3b2e12813f06a494, 0xbe939d1a60ad6f51), + (0xbad3005982fa855a, 0x3e3fc676f4a347ee), + (0xba85afc3d21b71be, 0xbde152903c9bc0b8), + (0xba1be795cc3bb4cd, 0x3d76d08684fc4f40), + (0xb99979de162142b7, 0xbcfb72c9bdfebf2e), + ], + [ + (0xbc87e105ec9ca5f4, 0x3fe9194d6629e509), + (0xbc79c00221836f35, 0x3fd959b6e47cc1cb), + (0xbc26c9c009d62078, 0xbf9ece59214cf137), + (0xbbfe20f5fddc5310, 0x3f64025702ca8fc4), + (0xbba84afb784aa07c, 0xbf2457f85b9b3831), + (0x3b54ea926ad5167c, 0x3edeef4e272f250a), + (0xbb023defeec5e0a0, 0xbe913432dc663e67), + (0x3aae60197d5217c8, 0x3e3b2b72ce97aa39), + (0x3a63141e2e6f5022, 0xbddcde4ddf08d4ea), + (0x39eca6549fac9060, 0x3d72854850b02948), + (0xb939a6cb39aa2600, 0xbcf5b3efba807911), + ], + [ + (0xbc24d27ad1e68c80, 0x3fe962e2905556ed), + (0x3c69998b03a75cee, 0x3fd90efb3eca9aba), + (0x3c3c5ac4bdd68696, 0xbf9dbd168f65fb7e), + (0x3be519a7a0660ba4, 0x3f62da45c6e72103), + (0xbbc8b81ea1bc7080, 0xbf22b2ecd5924135), + (0x3b5e56067f09a9d4, 0x3edbba1394728855), + (0x3b28207c17005b80, 0xbe8e0ffed775f6e9), + (0xbadbacdffd118992, 0x3e372225c30c46fa), + (0x3a68218e8f652ab4, 0xbdd7f276a6d4d262), + (0x3a0144bf6c21cae7, 0x3d6dedf685adbda0), + (0xb99078cdaa8ca380, 0xbcf113f00b9fe725), + ], + [ + (0xbc712c24f9d2f218, 0x3fe9b04e3301ca38), + (0x3c7193d913e4e618, 0x3fd8c28470534676), + (0xbc3677a730753df1, 0xbf9cad33f35e2755), + (0x3bc11212e8675ef0, 0x3f61bbd0172a316b), + (0xbb93d13eee592c20, 0xbf2126c548b5619a), + (0xbb7f0f63eeeee01d, 0x3ed8cab1036d4dec), + (0xbb289ac10a4baa55, 0xbe8a32410f19bdd5), + (0x3ac451ab8a7a47d0, 0x3e33a420595d0d3a), + (0xba603784d0bf66a6, 0xbdd3ce7c43e80e82), + (0x39fe2bb244cfded2, 0x3d681c69081d1b37), + (0x395917e555865c68, 0xbceacbdfedaea1f7), + ], + [ + (0x3c8f0fa86a56e6ba, 0x3fea00cbb7e2c1e2), + (0xbc63acefc8cc1c66, 0x3fd8752ebfc07ba7), + (0x3c3e999a1b70ea47, 0xbf9ba1b2cc9437f4), + (0x3be3a460fc6ec980, 0x3f60a9a1d27c214e), + (0x3bb37b03b766db48, 0xbf1f6bd0acca9dd1), + (0xbb713d37e0e4001a, 0x3ed6221851224bca), + (0xbb207e1b7175b01f, 0xbe86ca231706849e), + (0x3ad2bf8297bed558, 0x3e30a5c736124de1), + (0xba727489396341d5, 0xbdd05a979295fac9), + (0x39f1756e19c37c9a, 0x3d6364167eb132f4), + (0x3983bb2d132598e9, 0xbce4fd25b8623a10), + ], + [ + (0x3c84f280c7337943, 0x3fea53b4eef9f5a5), + (0xbc69118e2061c5da, 0x3fd827a8c3a5cc4b), + (0x3c3ed707936633ac, 0xbf9a9cbc621418be), + (0x3bbc9603743be350, 0x3f5f4aaa94ee28c7), + (0xbbb7a8e3165c93dc, 0xbf1cc23b919438f8), + (0xbb7920595035541d, 0x3ed3be2ada53954c), + (0x3b24880c577104dd, 0xbe83cf0de829e720), + (0xbac9bba9b94d4f97, 0x3e2c32789bf32b44), + (0x3a6a7d6fb4480815, 0xbdcafc517db4919d), + (0x39ff848c09f51077, 0x3d5f2b62427707c6), + (0x398e7d47b82a2483, 0xbce06e6c75ffb9d2), + ], + [ + (0x3c874be4e30f55fd, 0x3feaa8800692a548), + (0xbc7983ddaa23edda, 0x3fd7da799a85a3a1), + (0x3c29fd6ca97884f0, 0xbf999fcb692e46c2), + (0x3bf0a8fd72f30686, 0x3f5d5f6e7ebe838d), + (0xbbb41d28e076799c, 0xbf1a501fd07cd87f), + (0x3b5a4d8bed2ad3cc, 0x3ed19aee4bf149cb), + (0x3b286b20ed1ac9b8, 0xbe8136b705548435), + (0xbaa2b95c9c1a2fd4, 0x3e27e05b60054049), + (0xba45b18e400c714c, 0xbdc643aab819d20d), + (0xb9f127bc1b8ba61b, 0x3d590e09ca6a23af), + (0xb97b1e2097b4cdce, 0xbcd9bc2e12b23103), + ], + [ + (0x3c7f2f0799382490, 0x3feafebcbfb3a5a6), + (0x3c727a6f0626ebe1, 0x3fd78e0728cbc72f), + (0xbc0989b2c393e360, 0xbf98abd10da484bf), + (0xbbf1c8cbe9077ebf, 0x3f5b91fd1b5e71f1), + (0x3bb2dddefa74558b, 0xbf18135c2255aff9), + (0x3b69dc72be6abee5, 0x3ecf66cede9d9f9f), + (0x3afb52ef032713c0, 0xbe7decaae15f192a), + (0xba9db8b3a1526ca8, 0x3e2439c768f9f33b), + (0xba6bcb4e3ca70c74, 0xbdc261268dbd2e9a), + (0x39f22f54fe950e34, 0x3d5427b26d8593fa), + (0xb96523c3104ba290, 0xbcd42c447ec0cc74), + ], + [ + (0x3c80f855a5653f06, 0x3feb56113d9e9fc0), + (0x3c7901a7f01610ff, 0x3fd7429c0204c3ba), + (0xbc2879c1b3ea956c, 0xbf97c154c2349766), + (0xbbd2c40ca2762fb4, 0x3f59e1f11efd1eec), + (0xbbaad9436855a79e, 0xbf1608ebbb454bde), + (0x3b5d9d26778908c0, 0x3ecc04604ee7154d), + (0x3b1604c163265ec0, 0xbe7a06c1e1593471), + (0x3ac14ff60c7c6164, 0x3e21259f614c0715), + (0xba22d4163461b648, 0xbdbe602ef33d6637), + (0x39fbfef523aa8104, 0x3d503bc5a16de542), + (0xb96ef0efa7439614, 0xbccfac1400ac6db2), + ], + [ + (0x3c817e5fae67811b, 0x3febae36bac7427c), + (0x3c416ec3c6a31ff8, 0x3fd6f86cc3b7fc0a), + (0x3be68b8723641480, 0xbf96e08ec82e7973), + (0x3bdb9567557c5bac, 0x3f584e572bac1437), + (0x3bbf4c36068c245d, 0xbf142d4fd9685b5f), + (0x3b6fd00e8a412202, 0x3ec903b46ab16552), + (0x3b1a26353b11a93a, 0xbe76a7ffb613d977), + (0x3a83fcc3e211ffd0, 0x3e1d1b24e667426f), + (0xba431eb4941eb958, 0xbdb9227627e5f349), + (0xb9e5b1fb0b09d692, 0x3d4a30f8c120e1fc), + (0x396256e383967df9, 0xbcc8e8aa37bc61f0), + ], + [ + (0xbc6af2a3b8a6417c, 0x3fec06f659b4d0a2), + (0x3c72c912d943a127, 0x3fd6af9cc36509a8), + (0x3c346b1c71fd9485, 0xbf96097db8eb9798), + (0xbbd6098a353eaa68, 0x3f56d5e207087908), + (0x3ba7ef357dae1da2, 0xbf127cd98a6a5063), + (0x3b59d23dfa50e50a, 0x3ec65a59b3e87f89), + (0xbb1b2a7ac925c26a, 0xbe73be7c669b60c4), + (0x3abf7a6f9aa49d38, 0x3e18bc66c4d33d25), + (0x3a598bd8cb8e83be, 0xbdb4d4aee38b7aa0), + (0x39e8c05a738afb6a, 0x3d452ae72a594d04), + (0xb9581feb7fc372c8, 0xbcc3a189a1f1d088), + ], + [ + (0xbc8b94a3f11b0b1b, 0x3fec6026362273c0), + (0x3c7a9433928985a8, 0x3fd6684205e2cfa8), + (0xbc316c22e2ee8975, 0xbf953bf793a414a0), + (0x3b8eaa45bca8e100, 0x3f5577111d8e7869), + (0x3bb37d8f271623f3, 0xbf10f3db4ed954fd), + (0xbb5cffa19b715950, 0x3ec3fe9093dddaa2), + (0x3b1fcf0f684df6f8, 0xbe713a42e1480d90), + (0x3abfa83b47f916ac, 0x3e150dad8bd02d20), + (0x3a59abbe7813943f, 0xbdb14b5382d39865), + (0xb9efe1edf8eeca76, 0x3d41245f6e4996be), + (0x3949af3eecb215a2, 0xbcbf03908246b7c6), + ], + [ + (0xbc80c31a8863f9d6, 0x3fecb9a6cb682a24), + (0x3c7fed51d74bff86, 0x3fd622688518051f), + (0xbc1591ef749caee4, 0xbf9477b6ed4c398b), + (0xbbce137d55208958, 0x3f54304c2141eeee), + (0xbbab7a179e1ae7dd, 0xbf0f1d91c60481ce), + (0x3b55449a00736a6e, 0x3ec1e76e7622605d), + (0xbaccb03dd24f7810, 0xbe6e1a99fac954a8), + (0xbab80ff44fecc168, 0x3e11f2a815bce70a), + (0xba3ce823a0233bd6, 0xbdacc51da262d834), + (0x397750c051a75c00, 0x3d3bd2e2e3a657bb), + (0xb95134cc93e44584, 0xbcb88ed08e872b27), + ], + [ + (0x3c78ddf4513624a6, 0x3fed1360b92664d6), + (0xbc6c375ce17d0080, 0x3fd5de14d2825f87), + (0x3c2f9ef6b2759e44, 0xbf93bc64e699f695), + (0xbbf5442d5bca96e1, 0x3f52fff6380176c4), + (0xbb949c6dfb89070a, 0xbf0c9494574d2471), + (0xbb65ac54bdb2df7f, 0x3ec00ce94926b534), + (0x3b07c40ed8f854a0, 0xbe6a56ccff5f9038), + (0xbaa6ab98e2498c16, 0x3e0ea6ea534c6311), + (0xba4cece43020bd1a, 0xbda7fa106c3a3ead), + (0xb9c623e1759261aa, 0x3d36a181cda3fbde), + (0xb957aa56acc34690, 0xbcb37e8b3f1b09f6), + ], + [ + (0xbc62a747ca07d630, 0x3fed6d42e652ce9a), + (0xbc789f5a03143863, 0x3fd59b462a4134b2), + (0xbc36139452148f43, 0xbf9309a084e7d879), + (0xbbede9bf011d0122, 0x3f51e47ac9c4c1e3), + (0x3bae3a191b4e3711, 0xbf0a468a447d21ea), + (0x3b516b9dbf20d3a0, 0x3ebccfa848c16ecb), + (0xbaf45f67850622dc, 0xbe671406d6247e7e), + (0xba9afce70816748e, 0x3e0a3815485d6074), + (0x3a4365c1867e0cf7, 0xbda405987f7f2f4b), + (0x39d30563667171d7, 0x3d3272e30e95ed90), + (0xb91280c86c884580, 0xbcaf073402f44315), + ], + [ + (0x3c8f60a249f7c00e, 0x3fedc740fcccedd7), + (0x3c53f9df06bc8f9c, 0x3fd559f80c631fe7), + (0xbc31921248d74572, 0xbf925f03faf7b7d2), + (0x3bdfe8b708962ff8, 0x3f50dc559c122c5c), + (0xbba1d03d8e55ebc1, 0xbf082dc34fb7663d), + (0x3b587dd0630cd995, 0x3eb9e3a65f1e1ccc), + (0xbad1b315f72bea20, 0xbe644022ea43612d), + (0x3a92aa9f91588038, 0x3e06774a0eae4e26), + (0x3a2dde6ed80a8ad4, 0xbda0c0b1b147b2e0), + (0x39b72f1e01edcf12, 0x3d2e25bd83b43837), + (0xb915c51aee817f28, 0xbca8c18518a470b6), + ], + [ + (0x3c6066aa803f0eb0, 0x3fee21523413f6d4), + (0x3c701a65181dd95a, 0x3fd51a2372016c24), + (0x3becd2eeb19f4fa0, 0xbf91bc285adfbae2), + (0x3bd585c64e7b0238, 0x3f4fcc2f1ab1d691), + (0xbb937747d5ec3df8, 0xbf064512bf089bca), + (0x3b5b3a729384d857, 0x3eb74a95ddbb9ed7), + (0xbb04bce0c7a6c35e, 0xbe61cb92c772ae76), + (0xba9bc777b30f579a, 0x3e03488a2c937069), + (0x3a2eef4771938cfe, 0xbd9c17387c41e64a), + (0xb9ba789ead7c145e, 0x3d28b025d52dcbff), + (0xb9471fb6ef94b8de, 0xbca3cd451511437b), + ], + [ + (0x3c6fdcfd2ad6b2cc, 0x3fee7b70600bc584), + (0xbc216caa13b9e460, 0x3fd4dbbfb210e2e8), + (0x3c339b6e95789745, 0xbf9120a815b6c918), + (0x3b956397b544cce0, 0x3f4e00d1e8922c76), + (0x3ba4c65063f6319c, 0xbf0487ca2ab8e00b), + (0x3b5b594e90f0637d, 0x3eb4fa9b5402f99a), + (0xbabb01e0da08d320, 0xbe5f520c220f27b0), + (0xbaa38014f8475a9c, 0x3e00947b1d1c07d5), + (0xba3a70f466ff0512, 0xbd979905fceffdcd), + (0x39aec257742e626c, 0x3d24434adc2f738f), + (0xb92109b402248df6, 0xbc9fc2116c6f4f4c), + ], + [ + (0xbc8ed7b55bc9a299, 0x3feed5973870ea62), + (0x3c7068e6a0c0c082, 0x3fd49ec32763cc12), + (0xbc3079ab6b76d441, 0xbf908c2099da4782), + (0xbbeea4f5224b5d84, 0x3f4c5414cbe78b75), + (0x3bac8ba9ee3c50e7, 0xbf02f1b182c9dcaf), + (0xbb594f6e7ccb3656, 0x3eb2eb11438a7ca9), + (0xbacdeb584cff4340, 0xbe5b9a34dc857c26), + (0xba805fa93f84a21c, 0x3dfc8f43f4c51beb), + (0xba3ae305c497455f, 0xbd93dcbcbc79e194), + (0x39c91204c96816ba, 0x3d20aaf5b3fed175), + (0x3931bf2dad1b074d, 0xbc9987b162a8d125), + ], + [ + (0xbc8708c57fc49fa0, 0x3fef2fc3ce35d863), + (0x3c6b3c877a15c102, 0x3fd46323a69e9f48), + (0xbc27369c4763b491, 0xbf8ffc669e0ee421), + (0x3bef1f26de28a2cd, 0x3f4ac3a8e2298377), + (0xbba1cae3482f37ad, 0xbf017efdb93d4bc3), + (0x3b53791a286e42a2, 0x3eb114642afe2ad3), + (0xbafcada319b6cbb6, 0xbe585c28eac84be9), + (0x3a4204182a290740, 0x3df8a37a4be247cb), + (0x3a1aec8200b2b59c, 0xbd90c016dbd0389b), + (0xb9bcbc705e49bce8, 0x3d1b7b30ce88ec83), + (0xb90e04b1b0d7a938, 0xbc9492d96e10325b), + ], + [ + (0xbc5a1c7d0cbb1620, 0x3fef89f42525e2f5), + (0xbc6820327b9fb348, 0x3fd428d6d02b7336), + (0xbc2028945818c390, 0xbf8eed0c4104b3e1), + (0xbbeb1e19744aaa74, 0x3f494d6d68346b7e), + (0xbb8648aa3d83ead0, 0xbf002c46ff7034db), + (0x3b45bd818ecdcdba, 0x3eaedfe28b22d4e0), + (0xbacb470408632410, 0xbe5587433a8ae1af), + (0xba84cce387f694ea, 0x3df54a716368ebb1), + (0xba16fd37fa555ba4, 0xbd8c4e3a86a2428b), + (0xb9b5bae13524103e, 0x3d16b4243fb6f92d), + (0x391f2bc487b07970, 0xbc909e8be69a15eb), + ], + [ + (0x3c86cbe5e98a98ab, 0x3fefe426e98d02ad), + (0xbc7374332a339b7b, 0x3fd3efd247baee74), + (0x3c1e64f9511446c0, 0xbf8de98772761246), + (0x3bebc8cddaed336e, 0x3f47ef6d292b758c), + (0x3b890892e5c34bdc, 0xbefdecfe560cf884), + (0x3b46edd1273601a7, 0x3eabefd0f34b6491), + (0xbafabe6880484076, 0xbe530d455c33b91b), + (0x3a87b53325d0c678, 0x3df26d73fda0c451), + (0xba2145ca4055c756, 0xbd87f5ea8424c217), + (0x3970bcc9a5266510, 0x3d12cbd951992e7f), + (0xb92875f59f8743e5, 0xbc8ae9d6bb861ef8), + ], + [ + (0x3c8e56531a4c0964, 0x3ff01f2d9d896b96), + (0x3c69dd28e00eeaea, 0x3fd3b80bd8b693ad), + (0x3c2112b49c2d929d, 0xbf8cf13718435314), + (0xbbd3e3f549a6c02a, 0x3f46a7db8fd4d886), + (0xbb9cfaf7080719dc, 0xbefbb5d132483335), + (0x3b129df2d8378b30, 0x3ea94e632358a780), + (0x3af34f526a85aadc, 0xbe50e1fbc80213d2), + (0x3a85db7b76383a49, 0x3deff2fc81c56fd6), + (0x3a1b4963ac2d4f62, 0xbd8451d234f7b2ee), + (0x3985ca3f55e40518, 0x3d0f2fe7398a45f0), + (0x392021e0641a748a, 0xbc85d7a01c5f7eb1), + ], + [ + (0x3c8d688d52eeb63c, 0x3ff04c4843a795cb), + (0x3c2e29d7b8b68640, 0x3fd381798d3b7124), + (0x3c113b1fae95b222, 0xbf8c038376b558a7), + (0x3bed5a3bd9d8951c, 0x3f457511992ea31d), + (0x3b7acaf014e5fd04, 0xbef9ae1b7af2711a), + (0x3b38fcf24e4c4314, 0x3ea6f2a944764535), + (0xbab02dd93f02bfe0, 0xbe4df5df7475d1b8), + (0x3a7be4558e764b58, 0x3debbd3b73f426e4), + (0x39f60932f017fc58, 0xbd814340b64a12fa), + (0x39962f7e531d98b0, 0x3d09ecf0c3cdff1f), + (0xb92d928723f3b280, 0xbc81c44f3088b25e), + ], + [ + (0x3c75eee764574b40, 0x3ff0796337eb156b), + (0xbc75feae40a1a90b, 0x3fd34c11bbbceb70), + (0x3c178be5b54d01d6, 0xbf8b1fddd6af094f), + (0x3bd64edc5974df88, 0x3f44558acfb2b08c), + (0x3b946505515a12bb, 0xbef7d172dfd1900f), + (0x3b287c83bbb858b0, 0x3ea4d4cac4417e94), + (0xbae9e442fc4b2618, 0xbe4a9e49b7c94308), + (0xba566f889cc2e640, 0x3de81eda24ccecac), + (0xba05ed5e30af5d38, 0xbd7d61fb394a66ad), + (0xb9a9d5b973f44a13, 0x3d05982d519e12cc), + (0xb906ddcc141d26be, 0xbc7cf7be237827b9), + ], + [ + (0xbc81b90566f6f908, 0x3ff0a67e5c3c200c), + (0xbc7d5212fc82f031, 0x3fd317cb0e502e4c), + (0x3c200bb08e842505, 0xbf8a45c0157745d2), + (0xbbebf591fc8f8179, 0x3f4347e266dfc96f), + (0xbb86d2b6b1fc969e, 0xbef61bdff626f11b), + (0xbb4b30acc251a2d5, 0x3ea2ede2579e5ca9), + (0xbabdf54fda20eff0, 0xbe47adc218497f29), + (0x3a64b88f981d6108, 0x3de5014d76da32ed), + (0xba0cf8965161f6a2, 0xbd790c89e7a51571), + (0x397940e2585c8c10, 0x3d020598950e90e1), + (0xb8fe7525e1f6db28, 0xbc77aa994d491ad0), + ], + [ + (0x3c8c4c890adae8f4, 0x3ff0d3999da52293), + (0xbc6b205b14d29e54, 0x3fd2e49c85c0476f), + (0xbc1fef66c53ee65e, 0xbf8974ac29e86d4f), + (0xbbc62f38b0b4df28, 0x3f424ad083d71fe1), + (0xbb945e74cd665950, 0xbef489d1c88dc8ce), + (0x3b4aa3a0566b6933, 0x3ea137deb7d59680), + (0x3ae507d700308bfb, 0xbe4516f993433b0f), + (0x3a63c8fe3c89e8ac, 0x3de2519519e74a92), + (0xba130f708fc4a0b1, 0xbd7563ea5df792c4), + (0xb976d5e23edcbf48, 0x3cfe234f6246180b), + (0xb8f27fdcff9e8dc4, 0xbc73605c0a952524), + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerff.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerff.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/err/rerff.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/err/rerff.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,468 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +// Polynomials approximating x/erf(x) on ( k/8, (k + 1)/8 ) generated by Sollya and SageMath +// ```text +// def build_sollya_script(idx): +// return f""" +// d = [{idx}/8, {idx + 1}/8]; +// +// f = x/erf(x); +// Q = fpminimax(f, [|0, 2, 4, 6, 8, 10, 12, 14|], [|D...|], d); +// +// for i from 0 to degree(Q) by 2 do {{ +// write(coeff(Q, i)) >> "coefficients.txt"; +// write("\\n") >> "coefficients.txt"; +// }}; +// """ +// +// def load_coefficients(filename): +// with open(filename, "r") as f: +// return [RealField(500)(line.strip()) for line in f if line.strip()] +// +// def call_sollya_on_interval(idx): +// sollya_script = build_sollya_script(idx) +// with open("tmp_interval.sollya", "w") as f: +// f.write(sollya_script) +// import subprocess +// if os.path.exists("coefficients.txt"): +// os.remove("coefficients.txt") +// try: +// result = subprocess.run( +// ["sollya", "tmp_interval.sollya"], +// check=True, +// capture_output=True, +// text=True +// ) +// except subprocess.CalledProcessError as e: +// return +// +// def print_coeffs(poly): +// print("[") +// for i in range(len(poly)): +// coeff = poly[i] +// print(double_to_hex(coeff), ",") +// print("],") +// +// print(f"static COEFFS: [[u64; 8]; 32] = [") +// for i in range(0, 32): +// call_sollya_on_interval(i) +// coeffs = load_coefficients(f"coefficients.txt") +// print_coeffs(coeffs) +// print("];") +// ``` +static COEFFS: [[u64; 8]; 32] = [ + [ + 0x3fec5bf891b4ef6b, + 0x3fd2e7fb0bcdee7f, + 0x3f842aa5641a200a, + 0xbf752081ae81d16e, + 0x3f2e1a191fb85592, + 0xbf203a20ad500043, + 0x3f861a864f719e76, + 0xbfc79f68bad20bd1, + ], + [ + 0x3fec5bf891b4ef6b, + 0x3fd2e7fb0bcdf45b, + 0x3f842aa561f35512, + 0xbf75207c8167ac1d, + 0x3f2db4b119b4ce20, + 0x3f20fa28737c4219, + 0xbef38e74cca2219a, + 0xbec5d70713fc621e, + ], + [ + 0x3fec5bf891b4ef30, + 0x3fd2e7fb0bce1c0f, + 0x3f842aa56138541f, + 0xbf75207c6197eb7c, + 0x3f2db4799120e074, + 0x3f20fc28d915a6e9, + 0xbef3ea5b479dc053, + 0xbebbffe6df8ec372, + ], + [ + 0x3fec5bf891b4bf18, + 0x3fd2e7fb0bde166f, + 0x3f842aa53c721766, + 0xbf7520796733bbec, + 0x3f2db21eebf4144f, + 0x3f210545cc78d0f0, + 0xbef48ad7e4aa2d10, + 0xbeb24a043ad31907, + ], + [ + 0x3fec5bf891ab16e9, + 0x3fd2e7fb0dc7b919, + 0x3f842aa29d8381e7, + 0xbf7520592585d601, + 0x3f2da30df1566e43, + 0x3f212780ff325aa6, + 0xbef5e98ea9819e42, + 0xbe9849d52099dcb9, + ], + [ + 0x3fec5bf890ddfa8d, + 0x3fd2e7fb28aab312, + 0x3f842a8a461f0eb7, + 0xbf751f93b2d27114, + 0x3f2d66789eed5f95, + 0x3f21818ff1832f50, + 0xbef84264724049ef, + 0x3e9df12b02e82a5a, + ], + [ + 0x3fec5bf887f64fa4, + 0x3fd2e7fbfcc05f75, + 0x3f842a02323e2099, + 0xbf751c86d291ced6, + 0x3f2cbd5653cde433, + 0x3f223299b32b8583, + 0xbefb7fc6e286cd94, + 0x3eb49676cb3da393, + ], + [ + 0x3fec5bf84f8e2488, + 0x3fd2e7ffe83d2974, + 0x3f842821c5cc659c, + 0xbf7514805a6196e3, + 0x3f2b723680f64bb5, + 0x3f233416dcfcd366, + 0xbefefe55300afaa7, + 0x3ebf0c475fb71e7a, + ], + [ + 0x3fec5bf7999e6afe, + 0x3fd2e809c6d4caa7, + 0x3f84247256be4a56, + 0xbf750838db0c0cf5, + 0x3f29e7e867267388, + 0x3f24226adee5ce74, + 0xbf00c0830af2bf01, + 0x3ec26fb6b18e628b, + ], + [ + 0x3fec5bf801fc5ad5, + 0x3fd2e80618e8941e, + 0x3f84254c04b0b234, + 0xbf7509d7cf351201, + 0x3f2a01829944820c, + 0x3f241d7bb0c7e2de, + 0xbf00c2d844916d26, + 0x3ec2817d39abc26b, + ], + [ + 0x3fec5c0938a12f13, + 0x3fd2e7706c510d79, + 0x3f8448392db86aae, + 0xbf75526e9c6046f0, + 0x3f2facd0bc0e7862, + 0x3f21fc4093e1e6b7, + 0xbefdf54af68ba968, + 0x3ebfe348fc246c15, + ], + [ + 0x3fec5c6dcdadc5d8, + 0x3fd2e495072afff3, + 0x3f84d6f390564d4d, + 0xbf764a7e85749c85, + 0x3f37effb62caee80, + 0x3f19cb39bc236ae6, + 0xbef6d7035785e8f3, + 0x3eb755aa2e58fc52, + ], + [ + 0x3fec5dd74381acff, + 0x3fd2dbe68140f116, + 0x3f86459e1acfda0f, + 0xbf7865203923a03d, + 0x3f43665053a48049, + 0x3f0409e353b761ea, + 0xbeeb0b00f567c9f8, + 0x3eabc33000611b25, + ], + [ + 0x3fec6175431226d1, + 0x3fd2c8dcbb0babcc, + 0x3f88f5bfd61e5d2e, + 0xbf7bc60de8dff620, + 0x3f4d9b7076c7767c, + 0xbf0106584fac3547, + 0xbed0a56cd1030deb, + 0x3e970ee11e7beb48, + ], + [ + 0x3fec68445d99a8e9, + 0x3fd2a9d608dbfea2, + 0x3f8cc072ddf22cb6, + 0xbf7fe5f2efdc5f5c, + 0x3f5431d1deff38bc, + 0xbf197220e4a1dda8, + 0x3ec9e2469e6c1c67, + 0x3e4be72535d53d7b, + ], + [ + 0x3fec713c415bf088, + 0x3fd28610e83aa38c, + 0x3f9049ee1942f46b, + 0xbf81c513d165d6fd, + 0x3f585bc13e0fcaba, + 0xbf22715362e30768, + 0x3ede6bfa3c69e8e3, + 0xbe852cd85f8dea5b, + ], + [ + 0x3fec770e08b47107, + 0x3fd2716324b22047, + 0x3f91460d403e6b9c, + 0xbf829ab46375f10d, + 0x3f5a0e7f00c76fb5, + 0xbf2484890f2d7eeb, + 0x3ee207b21bbd8496, + 0xbe8bbee036671b6a, + ], + [ + 0x3fec6f4a2d01088d, + 0x3fd288e494bc89b7, + 0x3f905203788a2821, + 0xbf81eab2727ce365, + 0x3f58ddba75a3c100, + 0xbf2347c9a317a175, + 0x3ee099c93ce5f44f, + 0xbe88e9f9c064f833, + ], + [ + 0x3fec4c9bbce50c7d, + 0x3fd2e8175b0e1837, + 0x3f89a2d1518c7a4c, + 0xbf7f3fa91859127e, + 0x3f55431c495b1077, + 0xbf1fc1af665bb1f8, + 0x3eda0f1d735195cb, + 0xbe827b8d6fa224ed, + ], + [ + 0x3fec03cce39d7213, + 0x3fd39c2316e290bf, + 0x3f7b674438899313, + 0xbf783644c88c71fb, + 0x3f5047a3da485180, + 0xbf1748b54f823d57, + 0x3ed20c86d3302f22, + 0xbe77f94cafe045a8, + ], + [ + 0x3feb913f0adf6c4b, + 0x3fd49c4cedae09fc, + 0xbf4a6dea9778f474, + 0xbf7006dc4e6c8125, + 0x3f461483c254fa5f, + 0xbf0e75052760bf18, + 0x3ec65425869bc096, + 0xbe6bc2df9fbc0f82, + ], + [ + 0x3feafbeda3b7d400, + 0x3fd5cb900ee1fb5e, + 0xbf8228d16e87de3d, + 0xbf6011d44e155bf5, + 0x3f3993b736442257, + 0xbf017c7ee5efa6ad, + 0x3eb886e337d2e3c2, + 0xbe5cba4b79e90043, + ], + [ + 0x3fea54849d309eba, + 0x3fd701afa55e3d21, + 0xbf90c72bb2e2799f, + 0xbf33c92573294e34, + 0x3f265284f7a6d53a, + 0xbef09f09298ed1e8, + 0x3ea7153a46cb2e27, + 0xbe49ef6ec79265fd, + ], + [ + 0x3fe9b128df667870, + 0x3fd816d295a867cb, + 0xbf9713f11ea84a26, + 0x3f4edcbdd63903bb, + 0x3ef44f54fc7a6024, + 0xbed45da547d2fcb8, + 0x3e9049754d57a9a7, + 0xbe32aba05ca26a69, + ], + [ + 0x3fe927f49edf4ace, + 0x3fd8ecd207c6a7d1, + 0xbf9b8cd215124008, + 0x3f5cbab209dd389d, + 0xbf12a8920ea6230f, + 0x3eb442dfce60b0e2, + 0x3e52494e415c7728, + 0xbe09a1b1bbb9cee4, + ], + [ + 0x3fe8ca3d7437d06f, + 0x3fd973c08b6d33fb, + 0xbf9e272ca1fccc06, + 0x3f61efd00e2016b6, + 0xbf1e6dab18e9d45a, + 0x3ed0b446e3469be1, + 0xbe7503c584488bed, + 0x3e069968660290a4, + ], + [ + 0x3fe8a1f4b154f663, + 0x3fd9a9a8b81692d4, + 0xbf9f1e9312dd4501, + 0x3f632b4d20599404, + 0xbf2119c1b5e43b24, + 0x3ed42b9874284d56, + 0xbe7c17cc1eef4b9d, + 0x3e117f0a9057a689, + ], + [ + 0x3fe8b15bfcf78f33, + 0x3fd99720c884ab33, + 0xbf9ed2265979f5a6, + 0x3f62d3c30432692b, + 0xbf20a17346c37362, + 0x3ed36538f2d21c31, + 0xbe7aac6bb10f8b90, + 0x3e1061d3a1737044, + ], + [ + 0x3fe8f479e98cb825, + 0x3fd94ab3f8d0c80c, + 0xbf9da7afe85abf94, + 0x3f618fe28f71a3d4, + 0xbf1df723b2a63e38, + 0x3ed0d190252a7f7c, + 0xbe7631fdd49272b0, + 0x3e0a17567cab4a94, + ], + [ + 0x3fe9636d647b61c0, + 0x3fd8d4aaba0e0212, + 0xbf9bf904574e56ea, + 0x3f5fb68684d8555d, + 0xbf19d06f9cf17bbf, + 0x3ecb92b9f0b8acf3, + 0xbe7145bde0c499ae, + 0x3e033cf1cb08ce4c, + ], + [ + 0x3fe9f4c3301b6d33, + 0x3fd844100b4598b3, + 0xbf9a0b94e19be990, + 0x3f5c0ed55c70532f, + 0xbf15a786c9e62b23, + 0x3ec5e3f05a04f5c6, + 0xbe69ea9db2e37883, + 0x3dfb3e5ad2cd0fb2, + ], + [ + 0x3fea9f469c75536c, + 0x3fd7a51b3d9eda10, + 0xbf980f63a2cb486c, + 0x3f5887f72a9f07e0, + 0xbf11e4d454f2f994, + 0x3ec113d0aed8bdef, + 0xbe6311f84083acf4, + 0x3df2e4dc2e50e3fa, + ], +]; + +/// Computes 1/erf(x) +/// +/// Max ulp 0.5 +pub fn f_rerff(x: f32) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + + if x == 0. { + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + + if x_abs >= 0x4080_0000u32 { + static ONE: [f32; 2] = [1.0, -1.0]; + static SMALL: [f32; 2] = [f32::from_bits(0xb3000000), f32::from_bits(0x33000000)]; + + let sign = x.is_sign_negative() as usize; + + if x_abs >= 0x7f80_0000u32 { + return if x_abs > 0x7f80_0000 { x } else { ONE[sign] }; + } + + return ONE[sign] + SMALL[sign]; + } + + // Polynomial approximation see [COEFFS] for generation: + // 1/erf(x) ~ (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14) / x + let xd = x as f64; + let xsq = xd * xd; + + const EIGHT: u32 = 3 << 23; + let idx = unsafe { f32::from_bits(x_abs.wrapping_add(EIGHT)).to_int_unchecked::() }; + + let c = COEFFS[idx]; + + let x4 = xsq * xsq; + let c0 = f_fmla(xsq, f64::from_bits(c[1]), f64::from_bits(c[0])); + let c1 = f_fmla(xsq, f64::from_bits(c[3]), f64::from_bits(c[2])); + let c2 = f_fmla(xsq, f64::from_bits(c[5]), f64::from_bits(c[4])); + let c3 = f_fmla(xsq, f64::from_bits(c[7]), f64::from_bits(c[6])); + + let x8 = x4 * x4; + let p0 = f_fmla(x4, c1, c0); + let p1 = f_fmla(x4, c3, c2); + + ((f_fmla(x8, p1, p0)) / xd) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_erff_test() { + assert!(f_rerff(f32::NAN).is_nan()); + assert_eq!(f_rerff(0.0), f32::INFINITY); + assert_eq!(f_rerff(-0.0), f32::NEG_INFINITY); + assert_eq!(f_rerff(0.015255669), 58.096153); + assert_eq!(f_rerff(1.0), 1.1866608); + assert_eq!(f_rerff(0.5), 1.9212301); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/auxiliary.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/auxiliary.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/auxiliary.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/auxiliary.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicSign, f64_from_parts}; + +#[inline] +pub(crate) fn ldexp(d: f64, i: i32) -> f64 { + let mut n = i; + let exp_max = 1023; + let exp_min = -1022; + + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + // 2 ^ Emax, maximum positive with null significand (0x1p1023 for f64) + let f_exp_max = f64_from_parts(DyadicSign::Pos, EXP_BIAS << 1, 0); + + // 2 ^ Emin, minimum positive normal with null significand (0x1p-1022 for f64) + let f_exp_min = f64_from_parts(DyadicSign::Pos, 1, 0); + + let mut x = d; + + if n < exp_min { + // 2 ^ sig_total_bits, moltiplier to normalize subnormals (0x1p53 for f64) + let f_pow_subnorm = f64_from_parts(DyadicSign::Pos, 52 + EXP_BIAS, 0); + + let mul = f_exp_min * f_pow_subnorm; + let add = -exp_min - 52i32; + + // Worse case negative `n`: `x` is the maximum positive value, the result is `F::MIN`. + // This must be reachable by three scaling multiplications (two here and one final). + debug_assert!(-exp_min + 52i32 + exp_max <= add * 2 + -exp_min); + + x *= mul; + n += add; + + if n < exp_min { + x *= mul; + n += add; + + if n < exp_min { + n = exp_min; + } + } + } else if n > exp_max { + x *= f_exp_max; + n -= exp_max; + if n > exp_max { + x *= f_exp_max; + n -= exp_max; + if n > exp_max { + n = exp_max; + } + } + } + + let scale = f64_from_parts(DyadicSign::Pos, (EXP_BIAS as i32 + n) as u64, 0); + x * scale +} + +#[inline] +pub(crate) fn fast_ldexp(d: f64, i: i32) -> f64 { + let mut u = d.to_bits(); + u = u.wrapping_add((i as u64).wrapping_shl(52)); + f64::from_bits(u) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,444 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, fmla, pow2i, rintk}; +use crate::double_double::DoubleDouble; +use crate::exponents::auxiliary::fast_ldexp; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; + +/// Exp for given value for const context. +/// This is simplified version just to make a good approximation on const context. +#[inline] +pub const fn exp(d: f64) -> f64 { + const EXP_POLY_1_D: f64 = 2f64; + const EXP_POLY_2_D: f64 = 0.16666666666666674f64; + const EXP_POLY_3_D: f64 = -0.0027777777777777614f64; + const EXP_POLY_4_D: f64 = 6.613756613755705e-5f64; + const EXP_POLY_5_D: f64 = -1.6534391534392554e-6f64; + const EXP_POLY_6_D: f64 = 4.17535139757361979584e-8f64; + + const L2_U: f64 = 0.693_147_180_559_662_956_511_601_805_686_950_683_593_75; + const L2_L: f64 = 0.282_352_905_630_315_771_225_884_481_750_134_360_255_254_120_68_e-12; + const R_LN2: f64 = + 1.442_695_040_888_963_407_359_924_681_001_892_137_426_645_954_152_985_934_135_449_406_931; + + let qf = rintk(d * R_LN2); + let q = qf as i32; + + let mut r = fmla(qf, -L2_U, d); + r = fmla(qf, -L2_L, r); + + let f = r * r; + // Poly for u = r*(exp(r)+1)/(exp(r)-1) + let mut u = EXP_POLY_6_D; + u = fmla(u, f, EXP_POLY_5_D); + u = fmla(u, f, EXP_POLY_4_D); + u = fmla(u, f, EXP_POLY_3_D); + u = fmla(u, f, EXP_POLY_2_D); + u = fmla(u, f, EXP_POLY_1_D); + let u = 1f64 + 2f64 * r / (u - r); + let i2 = pow2i(q); + u * i2 + // if d < -964f64 { + // r = 0f64; + // } + // if d > 709f64 { + // r = f64::INFINITY; + // } +} + +pub(crate) static EXP_REDUCE_T0: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc719083535b085e, 0x3ff02c9a3e778061), + (0x3c8d73e2a475b466, 0x3ff059b0d3158574), + (0x3c6186be4bb28500, 0x3ff0874518759bc8), + (0x3c98a62e4adc610a, 0x3ff0b5586cf9890f), + (0x3c403a1727c57b52, 0x3ff0e3ec32d3d1a2), + (0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xbc932fbf9af1369e, 0x3ff1429aaea92de0), + (0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75), + (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0x3c8dc775814a8494, 0x3ff2063b88628cd6), + (0x3c99b07eb6c70572, 0x3ff2387a6e756238), + (0x3c82bd339940e9da, 0x3ff26b4565e27cdd), + (0x3c8612e8afad1256, 0x3ff29e9df51fdee1), + (0x3c90024754db41d4, 0x3ff2d285a6e4030b), + (0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0x3c932721843659a6, 0x3ff33c08b26416ff), + (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0xbc75e436d661f5e2, 0x3ff3a7db34e59ff7), + (0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0xbc5ef3691c309278, 0x3ff4160a21f72e2a), + (0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0), + (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xbc94b309d25957e4, 0x3ff4f9b2769d2ca7), + (0xbc807abe1db13cac, 0x3ff5342b569d4f82), + (0x3c99bb2c011d93ac, 0x3ff56f4736b527da), + (0x3c96324c054647ac, 0x3ff5ab07dd485429), + (0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148), + (0xbc9383c17e40b496, 0x3ff6247eb03a5585), + (0xbc9bb60987591c34, 0x3ff6623882552225), + (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), + (0xbc6bbe3a683c88aa, 0x3ff6dfb23c651a2f), + (0xbc816e4786887a9a, 0x3ff71f75e8ec5f74), + (0xbc90245957316dd4, 0x3ff75feb564267c9), + (0xbc841577ee049930, 0x3ff7a11473eb0187), + (0x3c705d02ba15797e, 0x3ff7e2f336cf4e62), + (0xbc9d4c1dd41532d8, 0x3ff82589994cce13), + (0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed), + (0x3c96e9f156864b26, 0x3ff8ace5422aa0db), + (0x3c85cc13a2e3976c, 0x3ff8f1ae99157736), + (0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5), + (0xbc9d185b7c1b85d0, 0x3ff97d829fde4e50), + (0x3c7c7c46b071f2be, 0x3ff9c49182a3f090), + (0xbc9359495d1cd532, 0x3ffa0c667b5de565), + (0xbc9d2f6edb8d41e2, 0x3ffa5503b23e255d), + (0x3c90fac90ef7fd32, 0x3ffa9e6b5579fdbf), + (0x3c97a1cd345dcc82, 0x3ffae89f995ad3ad), + (0xbc62805e3084d708, 0x3ffb33a2b84f15fb), + (0xbc75584f7e54ac3a, 0x3ffb7f76f2fb5e47), + (0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2), + (0x3c811065895048de, 0x3ffc199bdd85529c), + (0x3c92884dff483cac, 0x3ffc67f12e57d14b), + (0x3c7503cbd1e949dc, 0x3ffcb720dcef9069), + (0xbc9cbc3743797a9c, 0x3ffd072d4a07897c), + (0x3c82ed02d75b3706, 0x3ffd5818dcfba487), + (0x3c9c2300696db532, 0x3ffda9e603db3285), + (0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f), + (0x3c839e8980a9cc90, 0x3ffe502ee78b3ff6), + (0xbc9e9c23179c2894, 0x3ffea4afa2a490da), + (0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27), + (0x3c99d3e12dd8a18a, 0x3fff50765b6e4540), + (0x3c874853f3a5931e, 0x3fffa7c1819e90d8), +]; + +pub(crate) static EXP_REDUCE_T1: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c9ae8e38c59c72a, 0x3ff000b175effdc7), + (0xbc57b5d0d58ea8f4, 0x3ff00162f3904052), + (0x3c94115cb6b16a8e, 0x3ff0021478e11ce6), + (0xbc8d7c96f201bb2e, 0x3ff002c605e2e8cf), + (0x3c984711d4c35ea0, 0x3ff003779a95f959), + (0xbc80484245243778, 0x3ff0042936faa3d8), + (0xbc94b237da2025fa, 0x3ff004dadb113da0), + (0xbc75e00e62d6b30e, 0x3ff0058c86da1c0a), + (0x3c9a1d6cedbb9480, 0x3ff0063e3a559473), + (0xbc94acf197a00142, 0x3ff006eff583fc3d), + (0xbc6eaf2ea42391a6, 0x3ff007a1b865a8ca), + (0x3c7da93f90835f76, 0x3ff0085382faef83), + (0xbc86a79084ab093c, 0x3ff00905554425d4), + (0x3c986364f8fbe8f8, 0x3ff009b72f41a12b), + (0xbc882e8e14e3110e, 0x3ff00a6910f3b6fd), + (0xbc84f6b2a7609f72, 0x3ff00b1afa5abcbf), + (0xbc7e1a258ea8f71a, 0x3ff00bcceb7707ec), + (0x3c74362ca5bc26f2, 0x3ff00c7ee448ee02), + (0x3c9095a56c919d02, 0x3ff00d30e4d0c483), + (0xbc6406ac4e81a646, 0x3ff00de2ed0ee0f5), + (0x3c9b5a6902767e08, 0x3ff00e94fd0398e0), + (0xbc991b2060859320, 0x3ff00f4714af41d3), + (0x3c8427068ab22306, 0x3ff00ff93412315c), + (0x3c9c1d0660524e08, 0x3ff010ab5b2cbd11), + (0xbc9e7bdfb3204be8, 0x3ff0115d89ff3a8b), + (0x3c8843aa8b9cbbc6, 0x3ff0120fc089ff63), + (0xbc734104ee7edae8, 0x3ff012c1fecd613b), + (0xbc72b6aeb6176892, 0x3ff0137444c9b5b5), + (0x3c7a8cd33b8a1bb2, 0x3ff01426927f5278), + (0x3c72edc08e5da99a, 0x3ff014d8e7ee8d2f), + (0x3c857ba2dc7e0c72, 0x3ff0158b4517bb88), + (0x3c9b61299ab8cdb8, 0x3ff0163da9fb3335), + (0xbc990565902c5f44, 0x3ff016f0169949ed), + (0x3c870fc41c5c2d54, 0x3ff017a28af25567), + (0x3c94b9a6e145d76c, 0x3ff018550706ab62), + (0xbc7008eff5142bfa, 0x3ff019078ad6a19f), + (0xbc977669f033c7de, 0x3ff019ba16628de2), + (0xbc909bb78eeead0a, 0x3ff01a6ca9aac5f3), + (0x3c9371231477ece6, 0x3ff01b1f44af9f9e), + (0x3c75e7626621eb5a, 0x3ff01bd1e77170b4), + (0xbc9bc72b100828a4, 0x3ff01c8491f08f08), + (0xbc6ce39cbbab8bbe, 0x3ff01d37442d5070), + (0x3c816996709da2e2, 0x3ff01de9fe280ac8), + (0xbc8c11f5239bf536, 0x3ff01e9cbfe113ef), + (0x3c8e1d4eb5edc6b4, 0x3ff01f4f8958c1c6), + (0xbc9afb99946ee3f0, 0x3ff020025a8f6a35), + (0xbc98f06d8a148a32, 0x3ff020b533856324), + (0xbc82bf310fc54eb6, 0x3ff02168143b0281), + (0xbc9c95a035eb4176, 0x3ff0221afcb09e3e), + (0xbc9491793e46834c, 0x3ff022cdece68c4f), + (0xbc73e8d0d9c49090, 0x3ff02380e4dd22ad), + (0xbc9314aa16278aa4, 0x3ff02433e494b755), + (0x3c848daf888e9650, 0x3ff024e6ec0da046), + (0x3c856dc8046821f4, 0x3ff02599fb483385), + (0x3c945b42356b9d46, 0x3ff0264d1244c719), + (0xbc7082ef51b61d7e, 0x3ff027003103b10e), + (0x3c72106ed0920a34, 0x3ff027b357854772), + (0xbc9fd4cf26ea5d0e, 0x3ff0286685c9e059), + (0xbc909f8775e78084, 0x3ff02919bbd1d1d8), + (0x3c564cbba902ca28, 0x3ff029ccf99d720a), + (0x3c94383ef231d206, 0x3ff02a803f2d170d), + (0x3c94a47a505b3a46, 0x3ff02b338c811703), + (0x3c9e471202234680, 0x3ff02be6e199c811), +]; + +// sets the exponent of a binary64 number to 0 (subnormal range) +#[inline] +pub(crate) fn to_denormal(x: f64) -> f64 { + let mut ix = x.to_bits(); + ix &= 0x000fffffffffffff; + f64::from_bits(ix) +} + +#[inline] +fn exp_poly_dd(z: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x39c712f72ecec2cf, 0x3fe0000000000000), + (0x3c65555555554d07, 0x3fc5555555555555), + (0x3c455194d28275da, 0x3fa5555555555555), + (0x3c012faa0e1c0f7b, 0x3f81111111111111), + (0xbbf4ba45ab25d2a3, 0x3f56c16c16da6973), + (0xbbc9091d845ecd36, 0x3f2a01a019eb7f31), + ]; + let mut r = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[6]), + z, + DoubleDouble::from_bit_pair(C[5]), + ); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[4])); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[3])); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[2])); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[1])); + DoubleDouble::quick_mul_add_f64(r, z, f64::from_bits(0x3ff0000000000000)) +} + +#[cold] +fn as_exp_accurate(x: f64, t: f64, tz: DoubleDouble, ie: i64) -> f64 { + let mut ix = x.to_bits(); + if ((ix >> 52) & 0x7ff) < 0x3c9 { + return 1. + x; + } + + /* Use Cody-Waite argument reduction: since |x| < 745, we have |t| < 2^23, + thus since l2h is exactly representable on 29 bits, l2h*t is exact. */ + const L2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d0718432a1b0e26), + f64::from_bits(0x3f262e42ff000000), + ); + const L2LL: f64 = f64::from_bits(0x3999ff0342542fc3); + let dx = f_fmla(-L2.hi, t, x); + let dx_dd = DoubleDouble::quick_mult_f64(DoubleDouble::new(L2LL, L2.lo), t); + let dz = DoubleDouble::full_add_f64(dx_dd, dx); + let mut f = exp_poly_dd(dz); + f = DoubleDouble::quick_mult(dz, f); + if ix > 0xc086232bdd7abcd2u64 { + // x < -708.396 + ix = 1i64.wrapping_sub(ie).wrapping_shl(52) as u64; + f = DoubleDouble::quick_mult(f, tz); + f = DoubleDouble::add(tz, f); + + let new_f = DoubleDouble::from_exact_add(f64::from_bits(ix), f.hi); + f.lo += new_f.lo; + f.hi = to_denormal(f.hi + f.lo); + } else { + if tz.hi == 1.0 { + let fhe = DoubleDouble::from_exact_add(tz.hi, f.hi); + let fhl = DoubleDouble::from_exact_add(fhe.lo, f.lo); + f.hi = fhe.hi; + f.lo = fhl.hi; + ix = f.lo.to_bits(); + if (ix & 0x000fffffffffffff) == 0 { + let v = fhl.lo.to_bits(); + let d: i64 = (((((ix as i64) >> 63) ^ ((v as i64) >> 63)) as u64).wrapping_shl(1) + as i64) + .wrapping_add(1); + ix = ix.wrapping_add(d as u64); + f.lo = f64::from_bits(ix); + } + } else { + f = DoubleDouble::quick_mult(f, tz); + f = DoubleDouble::add(tz, f); + } + f = DoubleDouble::from_exact_add(f.hi, f.lo); + f.hi = fast_ldexp(f.hi, ie as i32); + } + f.hi +} + +#[inline(always)] +fn exp_gen(x: f64, backend: B) -> f64 { + let mut ix = x.to_bits(); + let aix = ix & 0x7fffffffffffffff; + // exp(x) rounds to 1 to nearest for |x| <= 5.55112e-17 + if aix <= 0x3c90000000000000u64 { + // |x| <= 5.55112e-17 + return 1.0 + x; + } + if aix >= 0x40862e42fefa39f0u64 { + // |x| >= 709.783 + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + if aix == 0x7ff0000000000000u64 { + // |x| = inf + return if (ix >> 63) != 0 { + 0.0 // x = -inf + } else { + x // x = inf + }; + } + if (ix >> 63) == 0 { + // x >= 709.783 + let z = std::hint::black_box(f64::from_bits(0x7fe0000000000000)); + return z * z; + } + if aix >= 0x40874910d52d3052u64 { + // x <= -745.133 + return f64::from_bits(0x18000000000000) * f64::from_bits(0x3c80000000000000); + } + } + const S: f64 = f64::from_bits(0x40b71547652b82fe); + let t = backend.round(x * S); + let jt: i64 = unsafe { + t.to_int_unchecked::() // this is already finite here + }; + let i0: i64 = (jt >> 6) & 0x3f; + let i1 = jt & 0x3f; + let ie: i64 = jt >> 12; + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let tz = backend.quick_mult(t0, t1); + + const L2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d0718432a1b0e26), + f64::from_bits(0x3f262e42ff000000), + ); + + /* Use Cody-Waite argument reduction: since |x| < 745, we have |t| < 2^23, + thus since l2h is exactly representable on 29 bits, l2h*t is exact. */ + let dx = backend.fma(L2.lo, t, backend.fma(-L2.hi, t, x)); + let dx2 = dx * dx; + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc55555557e54ff, + 0x3fa55555553a12f4, + ]; + + let pw0 = backend.fma(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pw1 = backend.fma(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let p = backend.fma(dx2, pw0, pw1); + let mut f = DoubleDouble::new(backend.fma(tz.hi * dx, p, tz.lo), tz.hi); + const EPS: f64 = f64::from_bits(0x3c0833beace2b6fe); + if ix > 0xc086232bdd7abcd2u64 { + // subnormal case: x < -708.396 + ix = 1u64.wrapping_sub(ie as u64).wrapping_shl(52); + let sums = DoubleDouble::from_exact_add(f64::from_bits(ix), f.hi); + f.hi = sums.hi; + f.lo += sums.lo; + let ub = f.hi + (f.lo + EPS); + let lb = f.hi + (f.lo - EPS); + if ub != lb { + return as_exp_accurate(x, t, tz, ie); + } + f.hi = to_denormal(lb); + } else { + let ub = f.hi + (f.lo + EPS); + let lb = f.hi + (f.lo - EPS); + if ub != lb { + return as_exp_accurate(x, t, tz, ie); + } + f.hi = fast_ldexp(lb, ie as i32); + } + f.hi +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp_fma_impl(x: f64) -> f64 { + use crate::exponents::expf::FmaBackend; + exp_gen(x, FmaBackend {}) +} + +/// Computes exponent +/// +/// Max found ULP 0.5 +pub fn f_exp(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp_fma_impl + } else { + fn def_exp(x: f64) -> f64 { + exp_gen(x, GenericExpfBackend {}) + } + def_exp + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn exp_test() { + assert!( + (exp(0f64) - 1f64).abs() < 1e-8, + "Invalid result {}", + exp(0f64) + ); + assert!( + (exp(5f64) - 148.4131591025766034211155800405522796f64).abs() < 1e-8, + "Invalid result {}", + exp(5f64) + ); + } + + #[test] + fn f_exp_test() { + assert_eq!(f_exp(0.000000014901161193847656), 1.0000000149011614); + assert_eq!(f_exp(0.), 1.); + assert_eq!(f_exp(5f64), 148.4131591025766034211155800405522796f64); + assert_eq!(f_exp(f64::INFINITY), f64::INFINITY); + assert_eq!(f_exp(f64::NEG_INFINITY), 0.); + assert!(f_exp(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,271 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::exponents::auxiliary::fast_ldexp; +use crate::exponents::exp::{EXP_REDUCE_T0, EXP_REDUCE_T1, to_denormal}; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +#[inline] +fn exp10_poly_dd(z: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 6] = [ + (0xbcaf48ad494ea102, 0x40026bb1bbb55516), + (0xbcae2bfab318d399, 0x40053524c73cea69), + (0x3ca81f50779e162b, 0x4000470591de2ca4), + (0x3c931a5cc5d3d313, 0x3ff2bd7609fd98c4), + (0x3c8910de8c68a0c2, 0x3fe1429ffd336aa3), + (0xbc605e703d496537, 0x3fca7ed7086882b4), + ]; + + let mut r = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[5]), + z, + DoubleDouble::from_bit_pair(C[4]), + ); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[3])); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[2])); + r = DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[1])); + DoubleDouble::quick_mul_add(r, z, DoubleDouble::from_bit_pair(C[0])) +} + +#[cold] +fn as_exp10_accurate(x: f64) -> f64 { + let mut ix = x.to_bits(); + let t = (f64::from_bits(0x40ca934f0979a371) * x).cpu_round_ties_even(); + let jt: i64 = unsafe { + t.to_int_unchecked::() // t is already integer, this is just a conversion + }; + let i1 = jt & 0x3f; + let i0 = (jt >> 6) & 0x3f; + let ie = jt >> 12; + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let dt = DoubleDouble::quick_mult(t0, t1); + + const L0: f64 = f64::from_bits(0x3f13441350800000); + const L1: f64 = f64::from_bits(0xbd1f79fef311f12b); + const L2: f64 = f64::from_bits(0xb9aac0b7c917826b); + + let dx = x - L0 * t; + let dx_dd = DoubleDouble::quick_mult_f64(DoubleDouble::new(L2, L1), t); + let dz = DoubleDouble::full_add_f64(dx_dd, dx); + let mut f = exp10_poly_dd(dz); + f = DoubleDouble::quick_mult(dz, f); + + let mut zfh: f64; + + if ix < 0xc0733a7146f72a42u64 { + if (jt & 0xfff) == 0 { + f = DoubleDouble::from_exact_add(f.hi, f.lo); + let zt = DoubleDouble::from_exact_add(dt.hi, f.hi); + f.hi = zt.lo; + f = DoubleDouble::from_exact_add(f.hi, f.lo); + ix = f.hi.to_bits(); + if (ix.wrapping_shl(12)) == 0 { + let l = f.lo.to_bits(); + let sfh: i64 = ((ix as i64) >> 63) ^ ((l as i64) >> 63); + ix = ix.wrapping_add(((1i64 << 51) ^ sfh) as u64); + } + zfh = zt.hi + f64::from_bits(ix); + } else { + f = DoubleDouble::quick_mult(f, dt); + f = DoubleDouble::add(dt, f); + f = DoubleDouble::from_exact_add(f.hi, f.lo); + zfh = f.hi; + } + zfh = fast_ldexp(zfh, ie as i32); + } else { + ix = (1u64.wrapping_sub(ie as u64)) << 52; + f = DoubleDouble::quick_mult(f, dt); + f = DoubleDouble::add(dt, f); + + let zt = DoubleDouble::from_exact_add(f64::from_bits(ix), f.hi); + f.hi = zt.hi; + f.lo += zt.lo; + + zfh = to_denormal(f.to_f64()); + } + zfh +} + +#[inline(always)] +fn exp10_gen(x: f64, backend: B) -> f64 { + let mut ix = x.to_bits(); + let aix = ix & 0x7fff_ffff_ffff_ffff; + if aix > 0x40734413509f79feu64 { + // |x| > 0x40734413509f79fe + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + if aix == 0x7ff0000000000000u64 { + return if (ix >> 63) != 0 { 0.0 } else { x }; + } + if (ix >> 63) == 0 { + return f64::from_bits(0x7fe0000000000000) * 2.0; // x > 308.255 + } + if aix > 0x407439b746e36b52u64 { + // x < -323.607 + return black_box(f64::from_bits(0x0018000000000000)) + * black_box(f64::from_bits(0x3c80000000000000)); + } + } + + // check x integer to avoid a spurious inexact exception + if ix.wrapping_shl(16) == 0 && (aix >> 48) <= 0x4036 { + let kx = backend.round_ties_even(x); + if kx == x { + let k = kx as i64; + if k >= 0 { + let mut r = 1.0; + for _ in 0..k { + r *= 10.0; + } + return r; + } + } + } + /* avoid spurious underflow: for |x| <= 2.41082e-17 + exp10(x) rounds to 1 to nearest */ + if aix <= 0x3c7bcb7b1526e50eu64 { + return 1.0 + x; // |x| <= 2.41082e-17 + } + let t = backend.round_ties_even(f64::from_bits(0x40ca934f0979a371) * x); + let jt: i64 = unsafe { t.to_int_unchecked::() }; // t is already integer this is just a conversion + let i1 = jt & 0x3f; + let i0 = (jt >> 6) & 0x3f; + let ie = jt >> 12; + let t00 = EXP_REDUCE_T0[i0 as usize]; + let t01 = EXP_REDUCE_T1[i1 as usize]; + let t0 = DoubleDouble::from_bit_pair(t00); + let t1 = DoubleDouble::from_bit_pair(t01); + let mut tz = backend.quick_mult(t0, t1); + const L0: f64 = f64::from_bits(0x3f13441350800000); + const L1: f64 = f64::from_bits(0x3d1f79fef311f12b); + let dx = backend.fma(-L1, t, backend.fma(-L0, t, x)); + let dx2 = dx * dx; + + const CH: [u64; 4] = [ + 0x40026bb1bbb55516, + 0x40053524c73cea69, + 0x4000470591fd74e1, + 0x3ff2bd760a1f32a5, + ]; + + let p0 = backend.fma(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + let p1 = backend.fma(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + + let p = backend.fma(dx2, p1, p0); + + let mut fh = tz.hi; + let fx = tz.hi * dx; + let mut fl = backend.fma(fx, p, tz.lo); + const EPS: f64 = 1.63e-19; + if ix < 0xc0733a7146f72a42u64 { + // x > -307.653 + // x > -0x1.33a7146f72a42p+8 + let ub = fh + (fl + EPS); + let lb = fh + (fl - EPS); + + if lb != ub { + return as_exp10_accurate(x); + } + fh = fast_ldexp(fh + fl, ie as i32); + } else { + // x <= -307.653: exp10(x) < 2^-1022 + ix = 1u64.wrapping_sub(ie as u64).wrapping_shl(52); + tz = DoubleDouble::from_exact_add(f64::from_bits(ix), fh); + fl += tz.lo; + + let ub = fh + (fl + EPS); + let lb = fh + (fl - EPS); + + if lb != ub { + return as_exp10_accurate(x); + } + + fh = to_denormal(fh + fl); + } + fh +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp10_fma_impl(x: f64) -> f64 { + use crate::exponents::expf::FmaBackend; + exp10_gen(x, FmaBackend {}) +} + +/// Computes exp10 +/// +/// Max found ULP 0.5 +pub fn f_exp10(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp10_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp10_fma_impl + } else { + fn def_exp10(x: f64) -> f64 { + exp10_gen(x, GenericExpfBackend {}) + } + def_exp10 + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp10f() { + assert_eq!(f_exp10(-3.370739843267434), 0.00042585343701025656); + assert_eq!(f_exp10(1.), 10.0); + assert_eq!(f_exp10(2.), 100.0); + assert_eq!(f_exp10(3.), 1000.0); + assert_eq!(f_exp10(4.), 10000.0); + assert_eq!(f_exp10(5.), 100000.0); + assert_eq!(f_exp10(6.), 1000000.0); + assert_eq!(f_exp10(7.), 10000000.0); + assert_eq!(f_exp10(f64::INFINITY), f64::INFINITY); + assert_eq!(f_exp10(f64::NEG_INFINITY), 0.); + assert!(f_exp10(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,256 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; + +pub(crate) struct ExpBReduc { + pub(crate) hi: f64, + pub(crate) lo: f64, +} + +const MID_BITS: u32 = 5; +const MID_MASK: usize = (1 << MID_BITS) - 1; +const LOG2_B: f64 = f64::from_bits(0x400a934f0979a371) * (1 << MID_BITS) as f64; +const M_LOGB_2_HI: f64 = f64::from_bits(0xbfd34413509f8000) / (1 << MID_BITS) as f64; +const M_LOGB_2_LO: f64 = f64::from_bits(0x3d380433b83b532a) / (1 << MID_BITS) as f64; +const EXP_2_MID: [u64; 32] = [ + 0x3ff0000000000000, + 0x3ff059b0d3158574, + 0x3ff0b5586cf9890f, + 0x3ff11301d0125b51, + 0x3ff172b83c7d517b, + 0x3ff1d4873168b9aa, + 0x3ff2387a6e756238, + 0x3ff29e9df51fdee1, + 0x3ff306fe0a31b715, + 0x3ff371a7373aa9cb, + 0x3ff3dea64c123422, + 0x3ff44e086061892d, + 0x3ff4bfdad5362a27, + 0x3ff5342b569d4f82, + 0x3ff5ab07dd485429, + 0x3ff6247eb03a5585, + 0x3ff6a09e667f3bcd, + 0x3ff71f75e8ec5f74, + 0x3ff7a11473eb0187, + 0x3ff82589994cce13, + 0x3ff8ace5422aa0db, + 0x3ff93737b0cdc5e5, + 0x3ff9c49182a3f090, + 0x3ffa5503b23e255d, + 0x3ffae89f995ad3ad, + 0x3ffb7f76f2fb5e47, + 0x3ffc199bdd85529c, + 0x3ffcb720dcef9069, + 0x3ffd5818dcfba487, + 0x3ffdfc97337b9b5f, + 0x3ffea4afa2a490da, + 0x3fff50765b6e4540, +]; + +// Approximating 10^dx with degree-5 minimax polynomial generated by Sollya: +// > Q = fpminimax((10^x - 1)/x, 4, [|D...|], [-log10(2)/2^6, log10(2)/2^6]); +// Then: +// 10^dx ~ P(dx) = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5. +pub(crate) const EXP10F_COEFFS: [u64; 5] = [ + 0x40026bb1bbb55515, + 0x40053524c73bd3ea, + 0x4000470591dff149, + 0x3ff2bd7c0a9fbc4d, + 0x3fe1429e74a98f43, +]; + +/// Range reduction function equivalent to exp_b_range_reduc +#[inline(always)] +pub(crate) fn exp_b_range_reduc(x: f32, backend: &B) -> ExpBReduc { + let xd = x as f64; + + // kd = round(log2(b) * x) + let kd = backend.round(LOG2_B * xd); + let k = unsafe { kd.to_int_unchecked::() }; // it's already not indeterminate. + + // hi = floor(kd / 2^MID_BITS) + let exp_hi = (k.wrapping_shr(MID_BITS) as u64).wrapping_shl(52); // 52 = fraction bits in f64 + + // mh = 2^hi * 2^mid + let mid_index = (k as usize) & MID_MASK; + let mh_bits = EXP_2_MID[mid_index].wrapping_add(exp_hi); + let mh = f64::from_bits(mh_bits); + + // dx = x - (hi + mid) * log(2) + let z0 = backend.fma(kd, M_LOGB_2_HI, xd); + let dx = backend.fma(kd, M_LOGB_2_LO, z0); + + ExpBReduc { lo: dx, hi: mh } +} + +#[inline(always)] +fn exp10f_gen(x: f32, backend: B) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fffffff; + + // When |x| >= log10(2^128), or x is nan + if x_abs >= 0x421a209bu32 { + // When x < log10(2^-150) or nan + if x_u > 0xc2349e35u32 { + // exp(-Inf) = 0 + if x.is_infinite() { + return 0.0; + } + // exp(nan) = nan + if x.is_nan() { + return x; + } + return 0.0; + } + // x >= log10(2^128) or nan + if x > 0. && (x_u >= 0x421a209bu32) { + // x is +inf or nan + return x + f32::INFINITY; + } + } + + if x_abs <= 0x3d000000u32 { + // |x| < 1/32 + if x_abs <= 0x3b9a209bu32 { + if x_u == 0xb25e5bd9u32 { + // x = -1.2943e-08 + return 1.; + } + // |x| < 2^-25 + // 10^x ~ 1 + log(10) * x + if x_abs <= 0x32800000u32 { + return backend.fmaf(x, f32::from_bits(0x40135da2), 1.0); + } + } + + let xd = x as f64; + + // Special polynomial for small x. + // Generated by Sollya: + // d = [-1/32, 1/32]; + // f_exp10f = (10^y - 1)/y; + // Q = fpminimax(f_exp10f, 6, [|D...|], d, relative, floating); + + // See ./notes/exp10f_small.sollya + let p = backend.polyeval7( + xd, + f64::from_bits(0x40026bb1bbb55516), + f64::from_bits(0x40053524c73cfbf6), + f64::from_bits(0x4000470591de0b07), + f64::from_bits(0x3ff2bd760599f3a5), + f64::from_bits(0x3fe142a001511a6f), + f64::from_bits(0x3fca7feffa781d53), + f64::from_bits(0x3fb16e53492c0f0e), + ); + return backend.fma(p, xd, 1.) as f32; + } + + // Range reduction: 10^x = 2^(mid + hi) * 10^lo + // rr = (2^(mid + hi), lo) + let rr = exp_b_range_reduc(x, &backend); + + // The low part is approximated by a degree-5 minimax polynomial. + // 10^lo ~ 1 + COEFFS[0] * lo + ... + COEFFS[4] * lo^5 + let lo2 = rr.lo * rr.lo; + // c0 = 1 + COEFFS[0] * lo + let c0 = backend.fma(rr.lo, f64::from_bits(EXP10F_COEFFS[0]), 1.0); + // c1 = COEFFS[1] + COEFFS[2] * lo + let c1 = backend.fma( + rr.lo, + f64::from_bits(EXP10F_COEFFS[2]), + f64::from_bits(EXP10F_COEFFS[1]), + ); + // c2 = COEFFS[3] + COEFFS[4] * lo + let c2 = backend.fma( + rr.lo, + f64::from_bits(EXP10F_COEFFS[4]), + f64::from_bits(EXP10F_COEFFS[3]), + ); + // p = c1 + c2 * lo^2 + // = COEFFS[1] + COEFFS[2] * lo + COEFFS[3] * lo^2 + COEFFS[4] * lo^3 + let p = backend.fma(lo2, c2, c1); + // 10^lo ~ c0 + p * lo^2 + // 10^x = 2^(mid + hi) * 10^lo + // ~ mh * (c0 + p * lo^2) + // = (mh * c0) + p * (mh * lo^2) + backend.fma(p, lo2 * rr.hi, c0 * rr.hi) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp10f_fma_impl(x: f32) -> f32 { + use crate::exponents::expf::FmaBackend; + exp10f_gen(x, FmaBackend {}) +} + +/// Computes exp10 +/// +/// Max found ULP 0.49999508 +#[inline] +pub fn f_exp10f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp10f_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp10f_fma_impl + } else { + fn def_exp10f(x: f32) -> f32 { + exp10f_gen(x, GenericExpfBackend {}) + } + def_exp10f + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp10f() { + assert_eq!(f_exp10f(-1. / 64.), 0.9646616); + assert_eq!(f_exp10f(1. / 64.), 1.0366329); + assert_eq!(f_exp10f(1.), 10.0); + assert_eq!(f_exp10f(2.), 100.0); + assert_eq!(f_exp10f(3.), 1000.0); + assert_eq!(f_exp10f(f32::INFINITY), f32::INFINITY); + assert_eq!(f_exp10f(f32::NEG_INFINITY), 0.); + assert!(f_exp10f(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,591 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::exp2m1::{EXP_M1_2_TABLE1, EXP_M1_2_TABLE2}; +use crate::rounding::CpuFloor; +use crate::rounding::CpuRoundTiesEven; + +const LN10H: f64 = f64::from_bits(0x40026bb1bbb55516); +const LN10L: f64 = f64::from_bits(0xbcaf48ad494ea3e9); + +struct Exp10m1 { + exp: DoubleDouble, + err: f64, +} + +// Approximation for the fast path of exp(z) for z=zh+zl, +// with |z| < 0.000130273 < 2^-12.88 and |zl| < 2^-42.6 +// (assuming x^y does not overflow or underflow) +#[inline] +fn q_1(dz: DoubleDouble) -> DoubleDouble { + const Q_1: [u64; 5] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555995d37, + 0x3fa55555558489dc, + ]; + let z = dz.to_f64(); + let mut q = f_fmla(f64::from_bits(Q_1[4]), dz.hi, f64::from_bits(Q_1[3])); + q = f_fmla(q, z, f64::from_bits(Q_1[2])); + + let mut p0 = DoubleDouble::from_exact_add(f64::from_bits(Q_1[1]), q * z); + p0 = DoubleDouble::quick_mult(dz, p0); + p0 = DoubleDouble::f64_add(f64::from_bits(Q_1[0]), p0); + p0 +} + +#[inline] +fn exp1(x: DoubleDouble) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); /* |INVLOG2-2^12/log(2)| < 2^-43.4 */ + let k = (x.hi * INVLOG2).cpu_round_ties_even(); + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + let mut zk = DoubleDouble::from_exact_mult(LOG2H, k); + zk.lo = f_fmla(k, LOG2L, zk.lo); + + let mut yz = DoubleDouble::from_exact_add(x.hi - zk.hi, x.lo); + yz.lo -= zk.lo; + + let ik: i64 = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let im: i64 = (ik >> 12).wrapping_add(0x3ff); + let i2: i64 = (ik >> 6) & 0x3f; + let i1: i64 = ik & 0x3f; + + let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]); + let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]); + + let p0 = DoubleDouble::quick_mult(t2, t1); + + let mut q = q_1(yz); + q = DoubleDouble::quick_mult(p0, q); + + /* Scale by 2^k. Warning: for x near 1024, we can have k=2^22, thus + M = 2047, which encodes Inf */ + let mut du = (im as u64).wrapping_shl(52); + if im == 0x7ff { + q.hi *= 2.0; + q.lo *= 2.0; + du = (im.wrapping_sub(1) as u64).wrapping_shl(52); + } + q.hi *= f64::from_bits(du); + q.lo *= f64::from_bits(du); + q +} + +#[inline] +fn exp10m1_fast(x: f64, tiny: bool) -> Exp10m1 { + if tiny { + return exp10m1_fast_tiny(x); + } + /* now -54 < x < -0.125 or 0.125 < x < 1024: we approximate exp(x*log(2)) + and subtract 1 */ + let v = DoubleDouble::quick_mult_f64(DoubleDouble::new(LN10L, LN10H), x); + /* + The a_mul() call is exact, and the error of the fma() is bounded by + ulp(l). + We have |t| <= ulp(h) <= ulp(LN2H*1024) = 2^-43, + |t+x*LN2L| <= 2^-43 * 1024*LN2L < 2^-42.7, + thus |l| <= |t| + |x*LN2L| + ulp(t+x*LN2L) + <= 2^-42.7 + 2^-95 <= 2^-42.6, and ulp(l) <= 2^-95. + Thus: + |h + l - x*log(2)| <= |h + l - x*(LN2H+LN2L)| + |x|*|LN2H+LN2L-log(2)| + <= 2^-95 + 1024*2^-110.4 < 2^-94.9 */ + + let mut p = exp1(v); + + let zf: DoubleDouble = if x >= 0. { + // implies h >= 1 and the fast_two_sum pre-condition holds + DoubleDouble::from_exact_add(p.hi, -1.0) + } else { + DoubleDouble::from_exact_add(-1.0, p.hi) + }; + p.lo += zf.lo; + p.hi = zf.hi; + /* The error in the above fast_two_sum is bounded by 2^-105*|h|, + with the new value of h, thus the total absolute error is bounded + by eps1*|h_in|+2^-105*|h|. + Relatively to h this yields eps1*|h_in/h| + 2^-105, where the maximum + of |h_in/h| is obtained for x near -0.125, with |2^x/(2^x-1)| < 11.05. + We get a relative error bound of 2^-74.138*11.05 + 2^-105 < 2^-70.67. */ + Exp10m1 { + exp: p, + err: f64::from_bits(0x3b77a00000000000) * p.hi, /* 2^-70.67 < 0x1.42p-71 */ + } +} + +// Approximation for the accurate path of exp(z) for z=zh+zl, +// with |z| < 0.000130273 < 2^-12.88 and |zl| < 2^-42.6 +// (assuming x^y does not overflow or underflow) +#[inline] +fn q_2(dz: DoubleDouble) -> DoubleDouble { + /* Let q[0]..q[7] be the coefficients of degree 0..7 of Q_2. + The ulp of q[7]*z^7 is at most 2^-155, thus we can compute q[7]*z^7 + in double precision only. + The ulp of q[6]*z^6 is at most 2^-139, thus we can compute q[6]*z^6 + in double precision only. + The ulp of q[5]*z^5 is at most 2^-124, thus we can compute q[5]*z^5 + in double precision only. */ + + /* The following is a degree-7 polynomial generated by Sollya for exp(z) + over [-0.000130273,0.000130273] with absolute error < 2^-113.218 + (see file exp_accurate.sollya). Since we use this code only for + |x| > 0.125 in exp2m1(x), the corresponding relative error for exp2m1 + is about 2^-113.218/|exp2m1(-0.125)| which is about 2^-110. */ + const Q_2: [u64; 9] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555555555, + 0x3c655555555c4d26, + 0x3fa5555555555555, + 0x3f81111111111111, + 0x3f56c16c3fbb4213, + 0x3f2a01a023ede0d7, + ]; + + let z = dz.to_f64(); + let mut q = dd_fmla(f64::from_bits(Q_2[8]), dz.hi, f64::from_bits(Q_2[7])); + q = dd_fmla(q, z, f64::from_bits(Q_2[6])); + q = dd_fmla(q, z, f64::from_bits(Q_2[5])); + + // multiply q by z and add Q_2[3] + Q_2[4] + + let mut p = DoubleDouble::from_exact_mult(q, z); + let r0 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[3]), p.hi); + p.hi = r0.hi; + p.lo += r0.lo + f64::from_bits(Q_2[4]); + + // multiply hi+lo by zh+zl and add Q_2[2] + + p = DoubleDouble::quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[2]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + + // multiply hi+lo by zh+zl and add Q_2[1] + p = DoubleDouble::quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[1]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + + // multiply hi+lo by zh+zl and add Q_2[0] + p = DoubleDouble::quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[0]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + p +} + +// returns a double-double approximation hi+lo of exp(x*log(10)) +// assumes -0x1.041704c068efp+4 < x <= 0x1.34413509f79fep+8 +#[inline] +fn exp_2(x: f64) -> DoubleDouble { + let mut k = (x * f64::from_bits(0x40ca934f0979a371)).cpu_round_ties_even(); + if k == 4194304. { + k = 4194303.; // ensures M < 2047 below + } + // since |x| <= 745 we have k <= 3051520 + + const LOG2_10H: f64 = f64::from_bits(0x3f134413509f79ff); + const LOG2_10M: f64 = f64::from_bits(0xbb89dc1da9800000); + const LOG2_10L: f64 = f64::from_bits(0xb984fd20dba1f655); + + let yhh = dd_fmla(-k, LOG2_10H, x); // exact, |yh| <= 2^-13 + + let mut ky0 = DoubleDouble::from_exact_add(yhh, -k * LOG2_10M); + ky0.lo = dd_fmla(-k, LOG2_10L, ky0.lo); + + /* now x = k + yh, thus 2^x = 2^k * 2^yh, and we multiply yh by log(10) + to use the accurate path of exp() */ + + let ky = DoubleDouble::quick_mult(ky0, DoubleDouble::new(LN10L, LN10H)); + + let ik = unsafe { + k.to_int_unchecked::() // k is already integer, this is just a conversion + }; + let im = (ik >> 12).wrapping_add(0x3ff); + let i2 = (ik >> 6) & 0x3f; + let i1 = ik & 0x3f; + + let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]); + let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]); + + let p = DoubleDouble::quick_mult(t2, t1); + + let mut q = q_2(ky); + q = DoubleDouble::quick_mult(p, q); + let mut ud: u64 = (im as u64).wrapping_shl(52); + + if im == 0x7ff { + q.hi *= 2.0; + q.lo *= 2.0; + ud = (im.wrapping_sub(1) as u64).wrapping_shl(52); + } + q.hi *= f64::from_bits(ud); + q.lo *= f64::from_bits(ud); + q +} + +#[cold] +fn exp10m1_accurate_tiny(x: f64) -> f64 { + let x2 = x * x; + let x4 = x2 * x2; + /* The following is a degree-17 polynomial generated by Sollya + (file exp10m1_accurate.sollya), + which approximates exp10m1(x) with relative error bounded by 2^-107.506 + for |x| <= 0.0625. */ + + const Q: [u64; 25] = [ + 0x40026bb1bbb55516, + 0xbcaf48ad494ea3e9, + 0x40053524c73cea69, + 0xbcae2bfab318d696, + 0x4000470591de2ca4, + 0x3ca823527cebf918, + 0x3ff2bd7609fd98c4, + 0x3c931ea51f6641df, + 0x3fe1429ffd1d4d76, + 0x3c7117195be7f232, + 0x3fca7ed70847c8b6, + 0xbc54260c5e23d0c8, + 0x3fb16e4dfc333a87, + 0xbc533fd284110905, + 0x3f94116b05fdaa5d, + 0xbc20721de44d79a8, + 0x3f74897c45d93d43, + 0x3f52ea52b2d182ac, + 0x3f2facfd5d905b22, + 0x3f084fe12df8bde3, + 0x3ee1398ad75d01bf, + 0x3eb6a9e96fbf6be7, + 0x3e8bd456a29007c2, + 0x3e6006cf8378cf9b, + 0x3e368862b132b6e2, + ]; + let mut c13 = dd_fmla(f64::from_bits(Q[23]), x, f64::from_bits(Q[22])); // degree 15 + let c11 = dd_fmla(f64::from_bits(Q[21]), x, f64::from_bits(Q[20])); // degree 14 + c13 = dd_fmla(f64::from_bits(Q[24]), x2, c13); // degree 15 + // add Q[19]*x+c13*x2+c15*x4 to Q[18] (degree 11) + let mut p = DoubleDouble::from_exact_add( + f64::from_bits(Q[18]), + f_fmla(f64::from_bits(Q[19]), x, f_fmla(c11, x2, c13 * x4)), + ); + // multiply h+l by x and add Q[17] (degree 10) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[17]), p.hi); + p.lo += p0.lo; + p.hi = p0.hi; + + // multiply h+l by x and add Q[16] (degree 9) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[16]), p.hi); + p.lo += p0.lo; + p.hi = p0.hi; + // multiply h+l by x and add Q[14]+Q[15] (degree 8) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[14]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[15]); + p.hi = p0.hi; + // multiply h+l by x and add Q[12]+Q[13] (degree 7) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[12]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[13]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[10]+Q[11] (degree 6) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[10]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[11]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[8]+Q[9] (degree 5) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[8]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[9]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[6]+Q[7] (degree 4) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[6]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[7]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[4]+Q[5] (degree 3) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[4]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[5]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[2]+Q[3] (degree 2) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[2]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[3]); + p.hi = p0.hi; + + // multiply h+l by x and add Q[0]+Q[1] (degree 2) + p = DoubleDouble::quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[0]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[1]); + p.hi = p0.hi; + + // multiply h+l by x + p = DoubleDouble::quick_f64_mult(x, p); + p.to_f64() +} + +#[cold] +fn exp10m1_accurate(x: f64) -> f64 { + let t = x.to_bits(); + let ux = t; + let ax = ux & 0x7fffffffffffffffu64; + + if ax <= 0x3fc0000000000000u64 { + // |x| <= 0.125 + return exp10m1_accurate_tiny(x); + } + + let mut p = exp_2(x); + + let zf: DoubleDouble = DoubleDouble::from_full_exact_add(p.hi, -1.0); + p.lo += zf.lo; + p.hi = zf.hi; + p.to_f64() +} + +/* |x| <= 0.125, put in h + l a double-double approximation of exp2m1(x), +and return the maximal corresponding absolute error. +We also have |x| > 0x1.0527dbd87e24dp-51. +With xmin=RR("0x1.0527dbd87e24dp-51",16), the routine +exp2m1_fast_tiny_all(xmin,0.125,2^-65.73) in exp2m1.sage returns +1.63414352331297e-20 < 2^-65.73, and +exp2m1_fast_tiny_all(-0.125,-xmin,2^-65.62) returns +1.76283772822891e-20 < 2^-65.62, which proves the relative +error is bounded by 2^-65.62. */ +#[inline] +fn exp10m1_fast_tiny(x: f64) -> Exp10m1 { + /* The following is a degree-11 polynomial generated by Sollya + (file exp10m1_fast.sollya), + which approximates exp10m1(x) with relative error bounded by 2^-69.58 + for |x| <= 0.0625. */ + const P: [u64; 14] = [ + 0x40026bb1bbb55516, + 0xbcaf48abcf79e094, + 0x40053524c73cea69, + 0xbcae1badf796d704, + 0x4000470591de2ca4, + 0x3ca7db8caacb2cea, + 0x3ff2bd7609fd98ba, + 0x3fe1429ffd1d4d98, + 0x3fca7ed7084998e1, + 0x3fb16e4dfc30944b, + 0x3f94116ae4b57526, + 0x3f74897c6a90f61c, + 0x3f52ec689c32b3a0, + 0x3f2faced20d698fe, + ]; + let x2 = x * x; + let x4 = x2 * x2; + let mut c9 = dd_fmla(f64::from_bits(P[12]), x, f64::from_bits(P[11])); // degree 9 + let c7 = dd_fmla(f64::from_bits(P[10]), x, f64::from_bits(P[9])); // degree 7 + let mut c5 = dd_fmla(f64::from_bits(P[8]), x, f64::from_bits(P[7])); // degree 5 + c9 = dd_fmla(f64::from_bits(P[13]), x2, c9); // degree 9 + c5 = dd_fmla(c7, x2, c5); // degree 5 + c5 = dd_fmla(c9, x4, c5); // degree 5 + + let mut p = DoubleDouble::from_exact_mult(c5, x); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(P[6]), p.hi); + p.lo += p0.lo; + p.hi = p0.hi; + + p = DoubleDouble::quick_f64_mult(x, p); + + let p1 = DoubleDouble::from_exact_add(f64::from_bits(P[4]), p.hi); + p.lo += p1.lo + f64::from_bits(P[5]); + p.hi = p1.hi; + + p = DoubleDouble::quick_f64_mult(x, p); + + let p2 = DoubleDouble::from_exact_add(f64::from_bits(P[2]), p.hi); + p.lo += p2.lo + f64::from_bits(P[3]); + p.hi = p2.hi; + + p = DoubleDouble::quick_f64_mult(x, p); + + let p2 = DoubleDouble::from_exact_add(f64::from_bits(P[0]), p.hi); + p.lo += p2.lo + f64::from_bits(P[1]); + p.hi = p2.hi; + + p = DoubleDouble::quick_f64_mult(x, p); + + Exp10m1 { + exp: p, + err: f64::from_bits(0x3bb0a00000000000) * p.hi, // 2^-65.62 < 0x1.4ep-66 + } +} + +/// Computes 10^x - 1 +/// +/// Max found ULP 0.5 +pub fn f_exp10m1(d: f64) -> f64 { + let mut x = d; + let t = x.to_bits(); + let ux = t; + let ax = ux & 0x7fffffffffffffffu64; + + if ux >= 0xc03041704c068ef0u64 { + // x = -NaN or x <= -0x1.041704c068efp+4 + if (ux >> 52) == 0xfff { + // -NaN or -Inf + return if ux > 0xfff0000000000000u64 { + x + x + } else { + -1.0 + }; + } + // for x <= -0x1.041704c068efp+4, exp10m1(x) rounds to -1 to nearest + return -1.0 + f64::from_bits(0x3c90000000000000); + } else if ax > 0x40734413509f79feu64 { + // x = +NaN or x >= 1024 + if (ux >> 52) == 0x7ff { + // +NaN + return x + x; + } + return f64::from_bits(0x7fefffffffffffff) * x; + } else if ax <= 0x3c90000000000000u64 + // |x| <= 0x1.0527dbd87e24dp-51 + /* then the second term of the Taylor expansion of 2^x-1 at x=0 is + smaller in absolute value than 1/2 ulp(first term): + log(2)*x + log(2)^2*x^2/2 + ... */ + { + /* we use special code when log(2)*|x| is very small, in which case + the double-double approximation h+l has its lower part l + "truncated" */ + return if ax <= 0x3970000000000000u64 + // |x| <= 2^-104 + { + // special case for 0 + if x == 0. { + return x; + } + if x.abs() == f64::from_bits(0x000086c73059343c) { + return dd_fmla( + -f64::copysign(f64::from_bits(0x1e60010000000000), x), + f64::from_bits(0x1e50000000000000), + f64::copysign(f64::from_bits(0x000136568740cb56), x), + ); + } + if x.abs() == f64::from_bits(0x00013a7b70d0248c) { + return dd_fmla( + f64::copysign(f64::from_bits(0x1e5ffe0000000000), x), + f64::from_bits(0x1e50000000000000), + f64::copysign(f64::from_bits(0x0002d41f3b972fc7), x), + ); + } + + // scale x by 2^106 + x *= f64::from_bits(0x4690000000000000); + let mut z = DoubleDouble::from_exact_mult(LN10H, x); + z.lo = dd_fmla(LN10L, x, z.lo); + let mut h2 = z.to_f64(); // round to 53-bit precision + // scale back, hoping to avoid double rounding + h2 *= f64::from_bits(0x3950000000000000); + // now subtract back h2 * 2^106 from h to get the correction term + let mut h = dd_fmla(-h2, f64::from_bits(0x4690000000000000), z.hi); + // add l + h += z.lo; + /* add h2 + h * 2^-106. Warning: when h=0, 2^-106*h2 might be exact, + thus no underflow will be raised. We have underflow for + 0 < x <= 0x1.71547652b82fep-1022 for RNDZ, and for + 0 < x <= 0x1.71547652b82fdp-1022 for RNDN/RNDU. */ + dyad_fmla(h, f64::from_bits(0x3950000000000000), h2) + } else { + const C2: f64 = f64::from_bits(0x40053524c73cea69); // log(2)^2/2 + let mut z = DoubleDouble::quick_mult_f64(DoubleDouble::new(LN10L, LN10H), x); + /* h+l approximates the first term x*log(2) */ + /* we add C2*x^2 last, so that in case there is a cancellation in + LN10L*x+l, it will contribute more bits */ + z.lo = dd_fmla(C2 * x, x, z.lo); + z.to_f64() + }; + } + + /* now -0x1.041704c068efp+4 < x < -2^-54 + or 2^-54 < x <= 0x1.34413509f79fep+8 */ + + /* 10^x-1 is exact for x integer, 1 <= x <= 15 */ + if ux << 15 == 0 { + let i = unsafe { x.cpu_floor().to_int_unchecked::() }; + if x == i as f64 && 1 <= i && i <= 15 { + static EXP10_1_15: [u64; 16] = [ + 0x0000000000000000, + 0x4022000000000000, + 0x4058c00000000000, + 0x408f380000000000, + 0x40c3878000000000, + 0x40f869f000000000, + 0x412e847e00000000, + 0x416312cfe0000000, + 0x4197d783fc000000, + 0x41cdcd64ff800000, + 0x4202a05f1ff80000, + 0x42374876e7ff0000, + 0x426d1a94a1ffe000, + 0x42a2309ce53ffe00, + 0x42d6bcc41e8fffc0, + 0x430c6bf52633fff8, + ]; + return f64::from_bits(EXP10_1_15[i as usize]); + } + } + + let result = exp10m1_fast(x, ax <= 0x3fb0000000000000u64); + let left = result.exp.hi + (result.exp.lo - result.err); + let right = result.exp.hi + (result.exp.lo + result.err); + if left != right { + return exp10m1_accurate(x); + } + left +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp10m1() { + assert_eq!(f_exp10m1(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002364140972981833), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005443635762124408); + assert_eq!(99., f_exp10m1(2.0)); + assert_eq!(315.22776601683796, f_exp10m1(2.5)); + assert_eq!(-0.7056827241416722, f_exp10m1(-0.5311842449009418)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp10m1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::exp10f::EXP10F_COEFFS; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; + +#[cold] +#[inline(always)] +fn exp10m1f_small(x: f32, backend: &B) -> f32 { + let dx = x as f64; + let dx_sq = dx * dx; + let c0 = dx * f64::from_bits(EXP10F_COEFFS[0]); + let c1 = backend.fma( + dx, + f64::from_bits(EXP10F_COEFFS[2]), + f64::from_bits(EXP10F_COEFFS[1]), + ); + let c2 = backend.fma( + dx, + f64::from_bits(EXP10F_COEFFS[4]), + f64::from_bits(EXP10F_COEFFS[3]), + ); + // 10^dx - 1 ~ (1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5) - 1 + // = COEFFS[0] * dx + ... + COEFFS[4] * dx^5 + backend.polyeval3(dx_sq, c0, c1, c2) as f32 +} + +#[inline(always)] +fn exp10m1f_gen(x: f32, backend: B) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + + // When x >= log10(2^128), or x is nan + if x.is_sign_positive() && x_u >= 0x421a_209bu32 { + // x >= log10(2^128) and 10^x - 1 rounds to +inf, or x is +inf or nan + return x + f32::INFINITY; + } + + if x_abs <= 0x3b9a_209bu32 { + // |x| <= 0.004703594 + return exp10m1f_small(x, &backend); + } + + // When x <= log10(2^-25), or x is nan + if x_u >= 0xc0f0d2f1 { + // exp10m1(-inf) = -1 + if x.is_infinite() { + return -1.0; + } + // exp10m1(nan) = nan + if x.is_nan() { + return x; + } + + if x_u == 0xc0f0d2f1 { + return f32::from_bits(0xbf7fffff); // -1.0f + 0x1.0p-24f + } + return -1.0; + } + + // Exact outputs when x = 1, 2, ..., 10. + // Quick check mask: 0x800f'ffffU = ~(bits of 1.0f | ... | bits of 10.0f) + if x_u & 0x800f_ffffu32 == 0 { + match x_u { + 0x3f800000u32 => return 9.0, // x = 1.0f + 0x40000000u32 => return 99.0, // x = 2.0f + 0x40400000u32 => return 999.0, // x = 3.0f + 0x40800000u32 => return 9_999.0, // x = 4.0f + 0x40a00000u32 => return 99_999.0, // x = 5.0f + 0x40c00000u32 => return 999_999.0, // x = 6.0f + 0x40e00000u32 => return 9_999_999.0, // x = 7.0f + 0x41000000u32 => return 99_999_999.0, // x = 8.0f + 0x41100000u32 => return 999_999_999.0, // x = 9.0f + 0x41200000u32 => return 9_999_999_999.0, // x = 10.0f + _ => {} + } + } + + // Range reduction: 10^x = 2^(mid + hi) * 10^lo + // rr = (2^(mid + hi), lo) + let rr = crate::exponents::exp10f::exp_b_range_reduc(x, &backend); + + // The low part is approximated by a degree-5 minimax polynomial. + // 10^lo ~ 1 + COEFFS[0] * lo + ... + COEFFS[4] * lo^5 + let lo_sq = rr.lo * rr.lo; + let c0 = backend.fma(rr.lo, f64::from_bits(EXP10F_COEFFS[0]), 1.0); + let c1 = backend.fma( + rr.lo, + f64::from_bits(EXP10F_COEFFS[2]), + f64::from_bits(EXP10F_COEFFS[1]), + ); + let c2 = backend.fma( + rr.lo, + f64::from_bits(EXP10F_COEFFS[4]), + f64::from_bits(EXP10F_COEFFS[3]), + ); + let exp10_lo = backend.polyeval3(lo_sq, c0, c1, c2); + // 10^x - 1 = 2^(mid + hi) * 10^lo - 1 + // ~ mh * exp10_lo - 1 + backend.fma(exp10_lo, rr.hi, -1.0) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp10f_fma_impl(x: f32) -> f32 { + use crate::exponents::expf::FmaBackend; + exp10m1f_gen(x, FmaBackend {}) +} + +/// Computes 10^x - 1 +/// +/// Max ULP 0.5 +#[inline] +pub fn f_exp10m1f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp10m1f_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp10f_fma_impl + } else { + fn def_expf(x: f32) -> f32 { + exp10m1f_gen(x, GenericExpfBackend {}) + } + def_expf + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp10m1f() { + assert_eq!(f_exp10m1f(0.0), 0.0); + assert_eq!(f_exp10m1f(1.0), 9.0); + assert_eq!(f_exp10m1f(1.5), 30.622776); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,268 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::dd_fmla; +use crate::double_double::DoubleDouble; +use crate::exponents::auxiliary::fast_ldexp; +use crate::exponents::exp::{EXP_REDUCE_T0, EXP_REDUCE_T1, to_denormal}; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; +use crate::rounding::CpuRoundTiesEven; + +#[inline] +fn exp2_poly_dd(z: f64) -> DoubleDouble { + const C: [(u64, u64); 6] = [ + (0x3bbabc9e3b39873e, 0x3f262e42fefa39ef), + (0xbae5e43a53e44950, 0x3e4ebfbdff82c58f), + (0xba0d3a15710d3d83, 0x3d6c6b08d704a0c0), + (0x3914dd5d2a5e025a, 0x3c83b2ab6fba4e77), + (0xb83dc47e47beb9dd, 0x3b95d87fe7a66459), + (0xb744fcd51fcb7640, 0x3aa430912f9fb79d), + ]; + + let mut r = DoubleDouble::quick_mul_f64_add( + DoubleDouble::from_bit_pair(C[5]), + z, + DoubleDouble::from_bit_pair(C[4]), + ); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(C[3])); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(C[2])); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(C[1])); + DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(C[0])) +} + +#[cold] +fn exp2_accurate(x: f64) -> f64 { + let mut ix = x.to_bits(); + let sx = 4096.0 * x; + let fx = sx.cpu_round_ties_even(); + let z = sx - fx; + let k: i64 = unsafe { + fx.to_int_unchecked::() // this is already finite here + }; + let i1 = k & 0x3f; + let i0 = (k >> 6) & 0x3f; + let ie = k >> 12; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let dt = DoubleDouble::quick_mult(t0, t1); + + let mut f = exp2_poly_dd(z); + f = DoubleDouble::quick_mult_f64(f, z); + if ix <= 0xc08ff00000000000u64 { + // x >= -1022 + // for -0x1.71547652b82fep-54 <= x <= 0x1.71547652b82fdp-53, + // exp2(x) round to x to nearest + if f64::from_bits(0xbc971547652b82fe) <= x && x <= f64::from_bits(0x3ca71547652b82fd) { + return dd_fmla(x, 0.5, 1.0); + } else if (k & 0xfff) == 0 { + // 4096*x rounds to 4096*integer + let zf = DoubleDouble::from_exact_add(dt.hi, f.hi); + let zfl = DoubleDouble::from_exact_add(zf.lo, f.lo); + f.hi = zf.hi; + f.lo = zfl.hi; + ix = zfl.hi.to_bits(); + if ix & 0x000fffffffffffff == 0 { + // fl is a power of 2 + if ((ix >> 52) & 0x7ff) != 0 { + // |fl| is Inf + let v = zfl.lo.to_bits(); + let d: i64 = ((((ix as i64) >> 63) ^ ((v as i64) >> 63)) as u64) + .wrapping_shl(1) + .wrapping_add(1) as i64; + ix = ix.wrapping_add(d as u64); + f.lo = f64::from_bits(ix); + } + } + } else { + f = DoubleDouble::quick_mult(f, dt); + f = DoubleDouble::add(dt, f); + } + let hf = DoubleDouble::from_exact_add(f.hi, f.lo); + + fast_ldexp(hf.hi, ie as i32) + } else { + ix = 1u64.wrapping_sub(ie as u64).wrapping_shl(52); + f = DoubleDouble::quick_mult(f, dt); + f = DoubleDouble::add(dt, f); + let zve = DoubleDouble::from_exact_add(f64::from_bits(ix), f.hi); + f.hi = zve.hi; + f.lo += zve.lo; + + to_denormal(f.to_f64()) + } +} + +#[inline(always)] +fn exp2_gen(x: f64, backend: B) -> f64 { + let mut ix = x.to_bits(); + let ax = ix.wrapping_shl(1); + if ax == 0 { + return 1.0; + } + if ax >= 0x8120000000000000u64 { + // |x| >= 1024 + if ax > 0xffe0000000000000u64 { + return x + x; // nan + } + if ax == 0xffe0000000000000u64 { + return if (ix >> 63) != 0 { 0.0 } else { x }; + } + // +/-inf + if (ix >> 63) != 0 { + // x <= -1024 + if ix >= 0xc090cc0000000000u64 { + // x <= -1075 + const Z: f64 = f64::from_bits(0x0010000000000000); + return Z * Z; + } + } else { + // x >= 1024 + return f64::from_bits(0x7fe0000000000000) * x; + } + } + + // for |x| <= 0x1.71547652b82fep-54, 2^x rounds to 1 to nearest + // this avoids a spurious underflow in z*z below + if ax <= 0x792e2a8eca5705fcu64 { + return 1.0 + f64::copysign(f64::from_bits(0x3c90000000000000), x); + } + + let m = ix.wrapping_shl(12); + let ex = (ax >> 53).wrapping_sub(0x3ff); + let frac = ex >> 63 | m << (ex & 63); + let sx = 4096.0 * x; + let fx = backend.round_ties_even(sx); + let z = sx - fx; + let z2 = z * z; + let k = unsafe { + fx.to_int_unchecked::() // this already finite here + }; + let i1 = k & 0x3f; + let i0 = (k >> 6) & 0x3f; + let ie = k >> 12; + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let ti0 = backend.quick_mult(t0, t1); + const C: [u64; 4] = [ + 0x3f262e42fefa39ef, + 0x3e4ebfbdff82c58f, + 0x3d6c6b08d73b3e01, + 0x3c83b2ab6fdda001, + ]; + let tz = ti0.hi * z; + let mut fh = ti0.hi; + + let p0 = backend.fma(z, f64::from_bits(C[1]), f64::from_bits(C[0])); + let p1 = backend.fma(z, f64::from_bits(C[3]), f64::from_bits(C[2])); + let p2 = backend.fma(z2, p1, p0); + + let mut fl = backend.fma(tz, p2, ti0.lo); + + const EPS: f64 = f64::from_bits(0x3c0833beace2b6fe); + + if ix <= 0xc08ff00000000000u64 { + // x >= -1022 + if frac != 0 { + let ub = fh + (fl + EPS); + fh += fl - EPS; + if ub != fh { + return exp2_accurate(x); + } + } + fh = fast_ldexp(fh, ie as i32); + } else { + // subnormal case + ix = 1u64.wrapping_sub(ie as u64).wrapping_shl(52); + let rs = DoubleDouble::from_exact_add(f64::from_bits(ix), fh); + fl += rs.lo; + fh = rs.hi; + if frac != 0 { + let ub = fh + (fl + EPS); + fh += fl - EPS; + if ub != fh { + return exp2_accurate(x); + } + } + // when 2^x is exact, no underflow should be raised + fh = to_denormal(fh); + } + fh +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp2_fma_impl(x: f64) -> f64 { + use crate::exponents::expf::FmaBackend; + exp2_gen(x, FmaBackend {}) +} + +/// Computes exp2 +/// +/// Max found ULP 0.5 +pub fn f_exp2(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp2_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp2_fma_impl + } else { + fn def_exp2(x: f64) -> f64 { + exp2_gen(x, GenericExpfBackend {}) + } + def_exp2 + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp2d() { + assert_eq!(f_exp2(2.0), 4.0); + assert_eq!(f_exp2(3.0), 8.0); + assert_eq!(f_exp2(4.0), 16.0); + assert_eq!(f_exp2(0.35f64), 1.2745606273192622); + assert_eq!(f_exp2(-0.6f64), 0.6597539553864471); + assert_eq!(f_exp2(f64::INFINITY), f64::INFINITY); + assert_eq!(f_exp2(f64::NEG_INFINITY), 0.); + assert!(f_exp2(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,355 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, f_fmlaf, pow2if}; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; +use std::hint::black_box; + +const TBLSIZE: usize = 64; + +#[repr(align(64))] +struct Exp2Table([(u32, u32); TBLSIZE]); + +#[rustfmt::skip] +static EXP2FT: Exp2Table = Exp2Table([(0x3F3504F3, 0xB2D4175E),(0x3F36FD92, 0x3268D5EF),(0x3F38FBAF, 0xB30E8719),(0x3F3AFF5B, 0x3319E7DA),(0x3F3D08A4, 0x333CD82F),(0x3F3F179A, 0x330E1902),(0x3F412C4D, 0x32CCF4D7),(0x3F4346CD, 0x328F330E),(0x3F45672A, 0xB201B5B7),(0x3F478D75, 0x32CCCE34),(0x3F49B9BE, 0x335E937C),(0x3F4BEC15, 0x2FF41909),(0x3F4E248C, 0xB21760EA),(0x3F506334, 0x3283628B),(0x3F52A81E, 0x3340F500),(0x3F54F35B, 0x331202BD),(0x3F5744FD, 0x32B66A3E),(0x3F599D16, 0x32D0D9B1),(0x3F5BFBB8, 0x332ED93F),(0x3F5E60F5, 0x3350A709),(0x3F60CCDF, 0x32025744),(0x3F633F89, 0xB33A7C4D),(0x3F65B907, 0x321DA4E9),(0x3F68396A, 0xB2FF36A7),(0x3F6AC0C7, 0x3217E40E),(0x3F6D4F30, 0xB2400CBB),(0x3F6FE4BA, 0x331A2ACC),(0x3F728177, 0xB2B7D3E5),(0x3F75257D, 0xB1FED2BE),(0x3F77D0DF, 0xB32B73BA),(0x3F7A83B3, 0x32579081),(0x3F7D3E0C, 0xB19726B5),(0x3F800000, 0x00000000),(0x3F8164D2, 0x320C09FB),(0x3F82CD87, 0x3391E031),(0x3F843A29, 0x33287EEF),(0x3F85AAC3, 0xB38F6665),(0x3F871F62, 0x339004AB),(0x3F88980F, 0x33AC4561),(0x3F8A14D5, 0xB39CDAEA),(0x3F8B95C2, 0x32949D5C),(0x3F8D1ADF, 0xB36F79FA),(0x3F8EA43A, 0x33971DC2),(0x3F9031DC, 0xB32BD022),(0x3F91C3D3, 0xB3928952),(0x3F935A2B, 0xB2EBFECF),(0x3F94F4F0, 0x3357B8BB),(0x3F96942D, 0xB307353B),(0x3F9837F0, 0xB345DFE9),(0x3F99E046, 0x3382A804),(0x3F9B8D3A, 0x3326993E),(0x3F9D3EDA, 0x3350A029),(0x3F9EF532, 0xB3605F62),(0x3FA0B051, 0xB210909B),(0x3FA27043, 0xB0DDC369),(0x3FA43516, 0x33385844),(0x3FA5FED7, 0x33400757),(0x3FA7CD94, 0x3325446E),(0x3FA9A15B, 0x33237A50),(0x3FAB7A3A, 0x33201CA4),(0x3FAD583F, 0x32394687),(0x3FAF3B79, 0x332E1225),(0x3FB123F6, 0x33838969),(0x3FB311C4, 0xB219F2BA)]); + +/** +Generated by SageMath: +```python +print("[") +for k in range(64): + k = RealField(150)(2)**(RealField(150)(k) / RealField(150)(64)) + print(double_to_hex(k) + ",") +print("];") +``` +**/ +pub(crate) static EXP2F_TABLE: [u64; 64] = [ + 0x3ff0000000000000, + 0x3ff02c9a3e778061, + 0x3ff059b0d3158574, + 0x3ff0874518759bc8, + 0x3ff0b5586cf9890f, + 0x3ff0e3ec32d3d1a2, + 0x3ff11301d0125b51, + 0x3ff1429aaea92de0, + 0x3ff172b83c7d517b, + 0x3ff1a35beb6fcb75, + 0x3ff1d4873168b9aa, + 0x3ff2063b88628cd6, + 0x3ff2387a6e756238, + 0x3ff26b4565e27cdd, + 0x3ff29e9df51fdee1, + 0x3ff2d285a6e4030b, + 0x3ff306fe0a31b715, + 0x3ff33c08b26416ff, + 0x3ff371a7373aa9cb, + 0x3ff3a7db34e59ff7, + 0x3ff3dea64c123422, + 0x3ff4160a21f72e2a, + 0x3ff44e086061892d, + 0x3ff486a2b5c13cd0, + 0x3ff4bfdad5362a27, + 0x3ff4f9b2769d2ca7, + 0x3ff5342b569d4f82, + 0x3ff56f4736b527da, + 0x3ff5ab07dd485429, + 0x3ff5e76f15ad2148, + 0x3ff6247eb03a5585, + 0x3ff6623882552225, + 0x3ff6a09e667f3bcd, + 0x3ff6dfb23c651a2f, + 0x3ff71f75e8ec5f74, + 0x3ff75feb564267c9, + 0x3ff7a11473eb0187, + 0x3ff7e2f336cf4e62, + 0x3ff82589994cce13, + 0x3ff868d99b4492ed, + 0x3ff8ace5422aa0db, + 0x3ff8f1ae99157736, + 0x3ff93737b0cdc5e5, + 0x3ff97d829fde4e50, + 0x3ff9c49182a3f090, + 0x3ffa0c667b5de565, + 0x3ffa5503b23e255d, + 0x3ffa9e6b5579fdbf, + 0x3ffae89f995ad3ad, + 0x3ffb33a2b84f15fb, + 0x3ffb7f76f2fb5e47, + 0x3ffbcc1e904bc1d2, + 0x3ffc199bdd85529c, + 0x3ffc67f12e57d14b, + 0x3ffcb720dcef9069, + 0x3ffd072d4a07897c, + 0x3ffd5818dcfba487, + 0x3ffda9e603db3285, + 0x3ffdfc97337b9b5f, + 0x3ffe502ee78b3ff6, + 0x3ffea4afa2a490da, + 0x3ffefa1bee615a27, + 0x3fff50765b6e4540, + 0x3fffa7c1819e90d8, +]; + +/* ULP 0.508 method + let redux = f32::from_bits(0x4b400000) / TBLSIZE as f32; + + let ui = f32::to_bits(d + redux); + let mut i0 = ui; + i0 = i0.wrapping_add(TBLSIZE as u32 / 2); + let k = i0 / TBLSIZE as u32; + i0 &= TBLSIZE as u32 - 1; + let mut uf = f32::from_bits(ui); + uf -= redux; + + let item = EXP2FT.0[i0 as usize]; + let z0: f32 = f32::from_bits(item.0); + let z1: f32 = f32::from_bits(item.1); + + let f: f32 = d - uf - z1; + + let mut u = 0.055504108664458832; + u = f_fmlaf(u, f, 0.24022650695908768); + u = f_fmlaf(u, f, 0.69314718055994973); + u *= f; + + let i2 = pow2if(k as i32); + f_fmlaf(u, z0, z0) * i2 +*/ + +#[inline(always)] +fn exp2f_gen(x: f32, backend: B) -> f32 { + let mut t = x.to_bits(); + + if (t & 0xffff) == 0 { + // x maybe integer + let k: i32 = (((t >> 23) & 0xff) as i32).wrapping_sub(127); // 2^k <= |x| < 2^(k+1) + if k >= 0 && k < 9 && (t << (9i32.wrapping_add(k))) == 0 { + // x integer, with 1 <= |x| < 2^9 + let msk = (t as i32) >> 31; + let mut m: i32 = (((t & 0x7fffff) | (1 << 23)) >> (23 - k)) as i32; + m = (m ^ msk).wrapping_sub(msk).wrapping_add(127); + if m > 0 && m < 255 { + t = (m as u32).wrapping_shl(23); + return f32::from_bits(t); + } else if m <= 0 && m > -23 { + t = 1i32.wrapping_shl(22i32.wrapping_add(m) as u32) as u32; + return f32::from_bits(t); + } + } + } + let ux = t.wrapping_shl(1); + + if ux >= 0x86000000u32 || ux < 0x65000000u32 { + // |x| >= 128 or x=nan or |x| < 0x1p-26 + if ux < 0x65000000u32 { + return 1.0 + x; + } // |x| < 0x1p-26 + // if x < -149 or 128 <= x is special + if !(t >= 0xc3000000u32 && t < 0xc3150000u32) { + if ux >= 0xffu32 << 24 { + // x is inf or nan + if ux > (0xffu32 << 24) { + return x + x; + } // x = nan + static IR: [f32; 2] = [f32::INFINITY, 0.]; + return IR[(t >> 31) as usize]; // x = +-inf + } + if t >= 0xc3150000u32 { + // x < -149 + let z = x; + let mut y = f_fmla( + z as f64 + 149., + f64::from_bits(0x3690000000000000), + f64::from_bits(0x36a0000000000000), + ); + y = y.max(f64::from_bits(0x3680000000000000)); + return y as f32; + } + // now x >= 128 + let r = black_box(f64::from_bits(0x47e0000000000000)) + * black_box(f64::from_bits(0x47e0000000000000)); + return r as f32; + } + } + + if ux <= 0x7a000000u32 { + // |x| < 1/32 + + // Generated by Sollya exp2 on range [-1/32;1/32]: + // d = [-1/32, 1/32]; + // f_exp2f = (2^y - 1)/y; + // Q = fpminimax(f_exp2f, 5, [|D...|], d, relative, floating); + + // See ./notes/exp2f_small.sollya + const C: [u64; 6] = [ + 0x3fe62e42fefa39f3, + 0x3fcebfbdff82c57b, + 0x3fac6b08d6f2d7aa, + 0x3f83b2ab6fc92f5d, + 0x3f55d897cfe27125, + 0x3f243090e61e6af1, + ]; + let xd = x as f64; + let p = backend.polyeval6( + xd, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + ); + return backend.fma(p, xd, 1.) as f32; + } + + let x_d = x as f64; + let kf = backend.round(x_d * 64.); + let k = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + // dx = lo = x - (hi + mid) = x - kf * 2^(-6) + let dx = backend.fma(f64::from_bits(0xbf90000000000000), kf, x_d); + + const TABLE_BITS: u32 = 6; + const TABLE_MASK: u64 = (1u64 << TABLE_BITS) - 1; + + // hi = floor(kf * 2^(-5)) + // exp_hi = shift hi to the exponent field of double precision. + let exp_hi: i64 = ((k >> TABLE_BITS) as i64).wrapping_shl(52); + + // mh = 2^hi * 2^mid + // mh_bits = bit field of mh + let mh_bits = (EXP2F_TABLE[((k as u64) & TABLE_MASK) as usize] as i64).wrapping_add(exp_hi); + let mh = f64::from_bits(mh_bits as u64); + + // Degree-4 polynomial approximating (2^x - 1)/x generated by Sollya with: + // > P = fpminimax((2^y - 1)/y, 4, [|D...|], [-1/64. 1/64]); + // see ./notes/exp2f.sollya + const C: [u64; 5] = [ + 0x3fe62e42fefa39ef, + 0x3fcebfbdff8131c4, + 0x3fac6b08d7061695, + 0x3f83b2b1bee74b2a, + 0x3f55d88091198529, + ]; + let dx_sq = dx * dx; + let c1 = backend.fma(dx, f64::from_bits(C[0]), 1.0); + let c2 = backend.fma(dx, f64::from_bits(C[2]), f64::from_bits(C[1])); + let c3 = backend.fma(dx, f64::from_bits(C[4]), f64::from_bits(C[3])); + let p = backend.fma(dx_sq, c3, c2); + // 2^x = 2^(hi + mid + lo) + // = 2^(hi + mid) * 2^lo + // ~ mh * (1 + lo * P(lo)) + // = mh + (mh*lo) * P(lo) + backend.fma(p, dx_sq * mh, c1 * mh) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp2f_fma_impl(x: f32) -> f32 { + use crate::exponents::expf::FmaBackend; + exp2f_gen(x, FmaBackend {}) +} + +/// Computing exp2f +/// +/// ULP 0.4999994 +#[inline] +pub fn f_exp2f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp2f_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp2f_fma_impl + } else { + fn def_exp2f(x: f32) -> f32 { + exp2f_gen(x, GenericExpfBackend {}) + } + def_exp2f + } + }); + unsafe { q(x) } + } +} + +#[inline] +pub(crate) fn dirty_exp2f(d: f32) -> f32 { + let redux = f32::from_bits(0x4b400000) / TBLSIZE as f32; + + let ui = f32::to_bits(d + redux); + let mut i0 = ui; + i0 = i0.wrapping_add(TBLSIZE as u32 / 2); + let k = i0 / TBLSIZE as u32; + i0 &= TBLSIZE as u32 - 1; + let mut uf = f32::from_bits(ui); + uf -= redux; + + let item = EXP2FT.0[i0 as usize]; + let z0: f32 = f32::from_bits(item.0); + + let f: f32 = d - uf; + + let mut u = 0.24022650695908768; + u = f_fmlaf(u, f, 0.69314718055994973); + u *= f; + + let i2 = pow2if(k as i32); + f_fmlaf(u, z0, z0) * i2 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp2f() { + assert_eq!(f_exp2f(1. / 64.), 1.0108893); + assert_eq!(f_exp2f(2.0), 4.0); + assert_eq!(f_exp2f(3.0), 8.0); + assert_eq!(f_exp2f(4.0), 16.0); + assert_eq!(f_exp2f(10.0), 1024.0); + assert_eq!(f_exp2f(-10.0), 0.0009765625); + assert!(f_exp2f(f32::NAN).is_nan()); + assert_eq!(f_exp2f(-0.35), 0.7845841); + assert_eq!(f_exp2f(0.35), 1.2745606); + assert!(f_exp2f(f32::INFINITY).is_infinite()); + assert_eq!(f_exp2f(f32::NEG_INFINITY), 0.0); + } + + #[test] + fn test_dirty_exp2f() { + assert!((dirty_exp2f(0.35f32) - 0.35f32.exp2()).abs() < 1e-5); + assert!((dirty_exp2f(-0.6f32) - (-0.6f32).exp2()).abs() < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,696 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; +use crate::exponents::fast_ldexp; + +const LN2H: f64 = f64::from_bits(0x3fe62e42fefa39ef); +const LN2L: f64 = f64::from_bits(0x3c7abc9e3b39803f); + +struct Exp2m1 { + exp: DoubleDouble, + err: f64, +} + +/* For 0 <= i < 64, T1[i] = (h,l) such that h+l is the best double-double +approximation of 2^(i/64). The approximation error is bounded as follows: +|h + l - 2^(i/64)| < 2^-107. */ +pub(crate) static EXP_M1_2_TABLE1: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc719083535b085d, 0x3ff02c9a3e778061), + (0x3c8d73e2a475b465, 0x3ff059b0d3158574), + (0x3c6186be4bb284ff, 0x3ff0874518759bc8), + (0x3c98a62e4adc610b, 0x3ff0b5586cf9890f), + (0x3c403a1727c57b53, 0x3ff0e3ec32d3d1a2), + (0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xbc932fbf9af1369e, 0x3ff1429aaea92de0), + (0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75), + (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0x3c8dc775814a8495, 0x3ff2063b88628cd6), + (0x3c99b07eb6c70573, 0x3ff2387a6e756238), + (0x3c82bd339940e9d9, 0x3ff26b4565e27cdd), + (0x3c8612e8afad1255, 0x3ff29e9df51fdee1), + (0x3c90024754db41d5, 0x3ff2d285a6e4030b), + (0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0x3c932721843659a6, 0x3ff33c08b26416ff), + (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0xbc75e436d661f5e3, 0x3ff3a7db34e59ff7), + (0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0xbc5ef3691c309278, 0x3ff4160a21f72e2a), + (0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0), + (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xbc94b309d25957e3, 0x3ff4f9b2769d2ca7), + (0xbc807abe1db13cad, 0x3ff5342b569d4f82), + (0x3c99bb2c011d93ad, 0x3ff56f4736b527da), + (0x3c96324c054647ad, 0x3ff5ab07dd485429), + (0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148), + (0xbc9383c17e40b497, 0x3ff6247eb03a5585), + (0xbc9bb60987591c34, 0x3ff6623882552225), + (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), + (0xbc6bbe3a683c88ab, 0x3ff6dfb23c651a2f), + (0xbc816e4786887a99, 0x3ff71f75e8ec5f74), + (0xbc90245957316dd3, 0x3ff75feb564267c9), + (0xbc841577ee04992f, 0x3ff7a11473eb0187), + (0x3c705d02ba15797e, 0x3ff7e2f336cf4e62), + (0xbc9d4c1dd41532d8, 0x3ff82589994cce13), + (0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed), + (0x3c96e9f156864b27, 0x3ff8ace5422aa0db), + (0x3c85cc13a2e3976c, 0x3ff8f1ae99157736), + (0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5), + (0xbc9d185b7c1b85d1, 0x3ff97d829fde4e50), + (0x3c7c7c46b071f2be, 0x3ff9c49182a3f090), + (0xbc9359495d1cd533, 0x3ffa0c667b5de565), + (0xbc9d2f6edb8d41e1, 0x3ffa5503b23e255d), + (0x3c90fac90ef7fd31, 0x3ffa9e6b5579fdbf), + (0x3c97a1cd345dcc81, 0x3ffae89f995ad3ad), + (0xbc62805e3084d708, 0x3ffb33a2b84f15fb), + (0xbc75584f7e54ac3b, 0x3ffb7f76f2fb5e47), + (0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2), + (0x3c811065895048dd, 0x3ffc199bdd85529c), + (0x3c92884dff483cad, 0x3ffc67f12e57d14b), + (0x3c7503cbd1e949db, 0x3ffcb720dcef9069), + (0xbc9cbc3743797a9c, 0x3ffd072d4a07897c), + (0x3c82ed02d75b3707, 0x3ffd5818dcfba487), + (0x3c9c2300696db532, 0x3ffda9e603db3285), + (0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f), + (0x3c839e8980a9cc8f, 0x3ffe502ee78b3ff6), + (0xbc9e9c23179c2893, 0x3ffea4afa2a490da), + (0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27), + (0x3c99d3e12dd8a18b, 0x3fff50765b6e4540), + (0x3c874853f3a5931e, 0x3fffa7c1819e90d8), +]; + +/* For 0 <= i < 64, T2[i] = (h,l) such that h+l is the best double-double +approximation of 2^(i/2^12). The approximation error is bounded as follows: +|h + l - 2^(i/2^12)| < 2^-107. */ +pub(crate) static EXP_M1_2_TABLE2: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c9ae8e38c59c72a, 0x3ff000b175effdc7), + (0xbc57b5d0d58ea8f4, 0x3ff00162f3904052), + (0x3c94115cb6b16a8e, 0x3ff0021478e11ce6), + (0xbc8d7c96f201bb2f, 0x3ff002c605e2e8cf), + (0x3c984711d4c35e9f, 0x3ff003779a95f959), + (0xbc80484245243777, 0x3ff0042936faa3d8), + (0xbc94b237da2025f9, 0x3ff004dadb113da0), + (0xbc75e00e62d6b30d, 0x3ff0058c86da1c0a), + (0x3c9a1d6cedbb9481, 0x3ff0063e3a559473), + (0xbc94acf197a00142, 0x3ff006eff583fc3d), + (0xbc6eaf2ea42391a5, 0x3ff007a1b865a8ca), + (0x3c7da93f90835f75, 0x3ff0085382faef83), + (0xbc86a79084ab093c, 0x3ff00905554425d4), + (0x3c986364f8fbe8f8, 0x3ff009b72f41a12b), + (0xbc882e8e14e3110e, 0x3ff00a6910f3b6fd), + (0xbc84f6b2a7609f71, 0x3ff00b1afa5abcbf), + (0xbc7e1a258ea8f71b, 0x3ff00bcceb7707ec), + (0x3c74362ca5bc26f1, 0x3ff00c7ee448ee02), + (0x3c9095a56c919d02, 0x3ff00d30e4d0c483), + (0xbc6406ac4e81a645, 0x3ff00de2ed0ee0f5), + (0x3c9b5a6902767e09, 0x3ff00e94fd0398e0), + (0xbc991b2060859321, 0x3ff00f4714af41d3), + (0x3c8427068ab22306, 0x3ff00ff93412315c), + (0x3c9c1d0660524e08, 0x3ff010ab5b2cbd11), + (0xbc9e7bdfb3204be8, 0x3ff0115d89ff3a8b), + (0x3c8843aa8b9cbbc6, 0x3ff0120fc089ff63), + (0xbc734104ee7edae9, 0x3ff012c1fecd613b), + (0xbc72b6aeb6176892, 0x3ff0137444c9b5b5), + (0x3c7a8cd33b8a1bb3, 0x3ff01426927f5278), + (0x3c72edc08e5da99a, 0x3ff014d8e7ee8d2f), + (0x3c857ba2dc7e0c73, 0x3ff0158b4517bb88), + (0x3c9b61299ab8cdb7, 0x3ff0163da9fb3335), + (0xbc990565902c5f44, 0x3ff016f0169949ed), + (0x3c870fc41c5c2d53, 0x3ff017a28af25567), + (0x3c94b9a6e145d76c, 0x3ff018550706ab62), + (0xbc7008eff5142bf9, 0x3ff019078ad6a19f), + (0xbc977669f033c7de, 0x3ff019ba16628de2), + (0xbc909bb78eeead0a, 0x3ff01a6ca9aac5f3), + (0x3c9371231477ece5, 0x3ff01b1f44af9f9e), + (0x3c75e7626621eb5b, 0x3ff01bd1e77170b4), + (0xbc9bc72b100828a5, 0x3ff01c8491f08f08), + (0xbc6ce39cbbab8bbe, 0x3ff01d37442d5070), + (0x3c816996709da2e2, 0x3ff01de9fe280ac8), + (0xbc8c11f5239bf535, 0x3ff01e9cbfe113ef), + (0x3c8e1d4eb5edc6b3, 0x3ff01f4f8958c1c6), + (0xbc9afb99946ee3f0, 0x3ff020025a8f6a35), + (0xbc98f06d8a148a32, 0x3ff020b533856324), + (0xbc82bf310fc54eb6, 0x3ff02168143b0281), + (0xbc9c95a035eb4175, 0x3ff0221afcb09e3e), + (0xbc9491793e46834d, 0x3ff022cdece68c4f), + (0xbc73e8d0d9c49091, 0x3ff02380e4dd22ad), + (0xbc9314aa16278aa3, 0x3ff02433e494b755), + (0x3c848daf888e9651, 0x3ff024e6ec0da046), + (0x3c856dc8046821f4, 0x3ff02599fb483385), + (0x3c945b42356b9d47, 0x3ff0264d1244c719), + (0xbc7082ef51b61d7e, 0x3ff027003103b10e), + (0x3c72106ed0920a34, 0x3ff027b357854772), + (0xbc9fd4cf26ea5d0f, 0x3ff0286685c9e059), + (0xbc909f8775e78084, 0x3ff02919bbd1d1d8), + (0x3c564cbba902ca27, 0x3ff029ccf99d720a), + (0x3c94383ef231d207, 0x3ff02a803f2d170d), + (0x3c94a47a505b3a47, 0x3ff02b338c811703), + (0x3c9e47120223467f, 0x3ff02be6e199c811), +]; + +// Approximation for the fast path of exp(z) for z=zh+zl, +// with |z| < 0.000130273 < 2^-12.88 and |zl| < 2^-42.6 +// (assuming x^y does not overflow or underflow) +#[inline(always)] +fn q_1(dz: DoubleDouble, backend: &B) -> DoubleDouble { + const Q_1: [u64; 5] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555995d37, + 0x3fa55555558489dc, + ]; + let z = dz.to_f64(); + let mut q = backend.fma(f64::from_bits(Q_1[4]), dz.hi, f64::from_bits(Q_1[3])); + q = backend.fma(q, z, f64::from_bits(Q_1[2])); + + let mut p0 = DoubleDouble::from_exact_add(f64::from_bits(Q_1[1]), q * z); + p0 = backend.quick_mult(dz, p0); + p0 = DoubleDouble::f64_add(f64::from_bits(Q_1[0]), p0); + p0 +} + +#[inline(always)] +fn exp1(x: DoubleDouble, backend: &B) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); /* |INVLOG2-2^12/log(2)| < 2^-43.4 */ + let k = backend.round_ties_even(x.hi * INVLOG2); + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + const LOG2DD: DoubleDouble = DoubleDouble::new(LOG2L, LOG2H); + let zk = backend.quick_mult_f64(LOG2DD, k); + + let mut yz = DoubleDouble::from_exact_add(x.hi - zk.hi, x.lo); + yz.lo -= zk.lo; + + let ik: i64 = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let im: i64 = (ik >> 12).wrapping_add(0x3ff); + let i2: i64 = (ik >> 6) & 0x3f; + let i1: i64 = ik & 0x3f; + + let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]); + let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]); + + let p0 = backend.quick_mult(t2, t1); + + let mut q = q_1(yz, backend); + q = backend.quick_mult(p0, q); + + /* Scale by 2^k. Warning: for x near 1024, we can have k=2^22, thus + M = 2047, which encodes Inf */ + let mut du = (im as u64).wrapping_shl(52); + if im == 0x7ff { + q.hi *= 2.0; + q.lo *= 2.0; + du = (im.wrapping_sub(1) as u64).wrapping_shl(52); + } + q.hi *= f64::from_bits(du); + q.lo *= f64::from_bits(du); + q +} + +#[inline(always)] +fn exp2m1_fast(x: f64, tiny: bool, backend: &B) -> Exp2m1 { + if tiny { + return exp2m1_fast_tiny(x, backend); + } + /* now -54 < x < -0.125 or 0.125 < x < 1024: we approximate exp(x*log(2)) + and subtract 1 */ + let mut v = backend.exact_mult(LN2H, x); + v.lo = backend.fma(x, LN2L, v.lo); + /* + The a_mul() call is exact, and the error of the fma() is bounded by + ulp(l). + We have |t| <= ulp(h) <= ulp(LN2H*1024) = 2^-43, + |t+x*LN2L| <= 2^-43 * 1024*LN2L < 2^-42.7, + thus |l| <= |t| + |x*LN2L| + ulp(t+x*LN2L) + <= 2^-42.7 + 2^-95 <= 2^-42.6, and ulp(l) <= 2^-95. + Thus: + |h + l - x*log(2)| <= |h + l - x*(LN2H+LN2L)| + |x|*|LN2H+LN2L-log(2)| + <= 2^-95 + 1024*2^-110.4 < 2^-94.9 */ + + let mut p = exp1(v, backend); + + let zf: DoubleDouble = if x >= 0. { + // implies h >= 1 and the fast_two_sum pre-condition holds + DoubleDouble::from_exact_add(p.hi, -1.0) + } else { + DoubleDouble::from_exact_add(-1.0, p.hi) + }; + p.lo += zf.lo; + p.hi = zf.hi; + /* The error in the above fast_two_sum is bounded by 2^-105*|h|, + with the new value of h, thus the total absolute error is bounded + by eps1*|h_in|+2^-105*|h|. + Relatively to h this yields eps1*|h_in/h| + 2^-105, where the maximum + of |h_in/h| is obtained for x near -0.125, with |2^x/(2^x-1)| < 11.05. + We get a relative error bound of 2^-74.138*11.05 + 2^-105 < 2^-70.67. */ + Exp2m1 { + exp: p, + err: f64::from_bits(0x3b84200000000000) * p.hi, /* 2^-70.67 < 0x1.42p-71 */ + } +} + +// Approximation for the accurate path of exp(z) for z=zh+zl, +// with |z| < 0.000130273 < 2^-12.88 and |zl| < 2^-42.6 +// (assuming x^y does not overflow or underflow) +#[inline(always)] +fn q_2(dz: DoubleDouble, backend: &B) -> DoubleDouble { + /* Let q[0]..q[7] be the coefficients of degree 0..7 of Q_2. + The ulp of q[7]*z^7 is at most 2^-155, thus we can compute q[7]*z^7 + in double precision only. + The ulp of q[6]*z^6 is at most 2^-139, thus we can compute q[6]*z^6 + in double precision only. + The ulp of q[5]*z^5 is at most 2^-124, thus we can compute q[5]*z^5 + in double precision only. */ + + /* The following is a degree-7 polynomial generated by Sollya for exp(z) + over [-0.000130273,0.000130273] with absolute error < 2^-113.218 + (see file exp_accurate.sollya). Since we use this code only for + |x| > 0.125 in exp2m1(x), the corresponding relative error for exp2m1 + is about 2^-113.218/|exp2m1(-0.125)| which is about 2^-110. */ + const Q_2: [u64; 9] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555555555, + 0x3c655555555c4d26, + 0x3fa5555555555555, + 0x3f81111111111111, + 0x3f56c16c3fbb4213, + 0x3f2a01a023ede0d7, + ]; + + let z = dz.to_f64(); + let mut q = backend.dd_fma(f64::from_bits(Q_2[8]), dz.hi, f64::from_bits(Q_2[7])); + q = backend.dd_fma(q, z, f64::from_bits(Q_2[6])); + q = backend.dd_fma(q, z, f64::from_bits(Q_2[5])); + + // multiply q by z and add Q_2[3] + Q_2[4] + + let mut p = backend.exact_mult(q, z); + let r0 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[3]), p.hi); + p.hi = r0.hi; + p.lo += r0.lo + f64::from_bits(Q_2[4]); + + // multiply hi+lo by zh+zl and add Q_2[2] + + p = backend.quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[2]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + + // multiply hi+lo by zh+zl and add Q_2[1] + p = backend.quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[1]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + + // multiply hi+lo by zh+zl and add Q_2[0] + p = backend.quick_mult(p, dz); + let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[0]), p.hi); + p.hi = r1.hi; + p.lo += r1.lo; + p +} + +// returns a double-double approximation hi+lo of exp(x*log(2)) for |x| < 745 +#[inline(always)] +fn exp_2(x: f64, backend: &B) -> DoubleDouble { + let k = backend.round_ties_even(x * f64::from_bits(0x40b0000000000000)); + // since |x| <= 745 we have k <= 3051520 + + let yhh = backend.fma(-k, f64::from_bits(0x3f30000000000000), x); // exact, |yh| <= 2^-13 + + /* now x = k + yh, thus 2^x = 2^k * 2^yh, and we multiply yh by log(2) + to use the accurate path of exp() */ + let ky = backend.quick_f64_mult(yhh, DoubleDouble::new(LN2L, LN2H)); + + let ik: i64 = unsafe { + k.to_int_unchecked::() // k is already integer, this is just a conversion + }; + let im = (ik >> 12).wrapping_add(0x3ff); + let i2 = (ik >> 6) & 0x3f; + let i1 = ik & 0x3f; + + let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]); + let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]); + + let p = backend.quick_mult(t2, t1); + + let mut q = q_2(ky, backend); + q = backend.quick_mult(p, q); + let mut ud: u64 = (im as u64).wrapping_shl(52); + + if im == 0x7ff { + q.hi *= 2.0; + q.lo *= 2.0; + ud = (im.wrapping_sub(1) as u64).wrapping_shl(52); + } + q.hi *= f64::from_bits(ud); + q.lo *= f64::from_bits(ud); + q +} + +#[cold] +#[inline(always)] +pub(crate) fn exp2m1_accurate_tiny(x: f64, backend: &B) -> f64 { + let x2 = x * x; + let x4 = x2 * x2; + const Q: [u64; 22] = [ + 0x3fe62e42fefa39ef, + 0x3c7abc9e3b398040, + 0x3fcebfbdff82c58f, + 0xbc65e43a53e44dcf, + 0x3fac6b08d704a0c0, + 0xbc4d331627517168, + 0x3f83b2ab6fba4e77, + 0x3c14e65df0779f8c, + 0x3f55d87fe78a6731, + 0x3bd0717fbf4bd050, + 0x3f2430912f86c787, + 0x3bcbd2bdec9bcd42, + 0x3eeffcbfc588b0c7, + 0xbb8e60aa6d5e4aa9, + 0x3eb62c0223a5c824, + 0x3e7b5253d395e7d4, + 0x3e3e4cf5158b9160, + 0x3dfe8cac734c6058, + 0x3dbc3bd64f17199d, + 0x3d78161a17e05651, + 0x3d33150b3d792231, + 0x3cec184260bfad7e, + ]; + let mut c13 = backend.dd_fma(f64::from_bits(Q[20]), x, f64::from_bits(Q[19])); // degree 13 + let c11 = backend.dd_fma(f64::from_bits(Q[18]), x, f64::from_bits(Q[17])); // degree 11 + c13 = backend.dd_fma(f64::from_bits(Q[21]), x2, c13); // degree 13 + // add Q[16]*x+c11*x2+c13*x4 to Q[15] (degree 9) + let mut p = DoubleDouble::from_exact_add( + f64::from_bits(Q[15]), + backend.fma(f64::from_bits(Q[16]), x, backend.fma(c11, x2, c13 * x4)), + ); + // multiply h+l by x and add Q[14] (degree 8) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[14]), p.hi); + p.lo += p0.lo; + p.hi = p0.hi; + + // multiply h+l by x and add Q[12]+Q[13] (degree 7) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[12]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[13]); + p.hi = p0.hi; + // multiply h+l by x and add Q[10]+Q[11] (degree 6) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[10]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[11]); + p.hi = p0.hi; + // multiply h+l by x and add Q[8]+Q[9] (degree 5) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[8]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[9]); + p.hi = p0.hi; + // multiply h+l by x and add Q[6]+Q[7] (degree 4) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[6]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[7]); + p.hi = p0.hi; + // multiply h+l by x and add Q[4]+Q[5] (degree 3) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[4]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[5]); + p.hi = p0.hi; + // multiply h+l by x and add Q[2]+Q[3] (degree 2) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[2]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[3]); + p.hi = p0.hi; + // multiply h+l by x and add Q[0]+Q[1] (degree 2) + p = backend.quick_f64_mult(x, p); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[0]), p.hi); + p.lo += p0.lo + f64::from_bits(Q[1]); + p.hi = p0.hi; + // multiply h+l by x + p = backend.quick_f64_mult(x, p); + p.to_f64() +} + +#[cold] +#[inline(always)] +fn exp2m1_accurate(x: f64, backend: &B) -> f64 { + let t = x.to_bits(); + let ux = t; + let ax = ux & 0x7fffffffffffffffu64; + + if ax <= 0x3fc0000000000000u64 { + // |x| <= 0.125 + return exp2m1_accurate_tiny(x, backend); + } + + let mut p = exp_2(x, backend); + + let zf: DoubleDouble = DoubleDouble::from_full_exact_add(p.hi, -1.0); + p.lo += zf.lo; + p.hi = zf.hi; + p.to_f64() +} + +/* |x| <= 0.125, put in h + l a double-double approximation of exp2m1(x), +and return the maximal corresponding absolute error. +We also have |x| > 0x1.0527dbd87e24dp-51. +With xmin=RR("0x1.0527dbd87e24dp-51",16), the routine +exp2m1_fast_tiny_all(xmin,0.125,2^-65.73) in exp2m1.sage returns +1.63414352331297e-20 < 2^-65.73, and +exp2m1_fast_tiny_all(-0.125,-xmin,2^-65.62) returns +1.76283772822891e-20 < 2^-65.62, which proves the relative +error is bounded by 2^-65.62. */ +#[inline(always)] +fn exp2m1_fast_tiny(x: f64, backend: &B) -> Exp2m1 { + /* The maximal value of |c4*x^4/exp2m1(x)| over [-0.125,0.125] + is less than 2^-15.109, where c4 is the degree-4 coefficient, + thus we can compute the coefficients of degree 4 or higher + using double precision only. */ + const P: [u64; 12] = [ + 0x3fe62e42fefa39ef, + 0x3c7abd1697afcaf8, + 0x3fcebfbdff82c58f, + 0xbc65e5a1d09e1599, + 0x3fac6b08d704a0bf, + 0x3f83b2ab6fba4e78, + 0x3f55d87fe78a84e6, + 0x3f2430912f86a480, + 0x3eeffcbfbc1f2b36, + 0x3eb62c0226c7f6d1, + 0x3e7b539529819e63, + 0x3e3e4d552bed5b9c, + ]; + let x2 = x * x; + let x4 = x2 * x2; + let mut c8 = backend.dd_fma(f64::from_bits(P[10]), x, f64::from_bits(P[9])); // degree 8 + let c6 = backend.dd_fma(f64::from_bits(P[8]), x, f64::from_bits(P[7])); // degree 6 + let mut c4 = backend.dd_fma(f64::from_bits(P[6]), x, f64::from_bits(P[5])); // degree 4 + c8 = backend.dd_fma(f64::from_bits(P[11]), x2, c8); // degree 8 + c4 = backend.dd_fma(c6, x2, c4); // degree 4 + c4 = backend.dd_fma(c8, x4, c4); // degree 4 + + let mut p = backend.exact_mult(c4, x); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(P[4]), p.hi); + p.lo += p0.lo; + p.hi = p0.hi; + + p = backend.quick_f64_mult(x, p); + + let p1 = DoubleDouble::from_exact_add(f64::from_bits(P[2]), p.hi); + p.lo += p1.lo + f64::from_bits(P[3]); + p.hi = p1.hi; + + p = backend.quick_f64_mult(x, p); + let p2 = DoubleDouble::from_exact_add(f64::from_bits(P[0]), p.hi); + p.lo += p2.lo + f64::from_bits(P[1]); + p.hi = p2.hi; + + p = backend.quick_f64_mult(x, p); + + Exp2m1 { + exp: p, + err: f64::from_bits(0x3bd4e00000000000) * p.hi, // 2^-65.62 < 0x1.4ep-66 + } +} + +#[inline(always)] +fn exp2m1_gen(d: f64, backend: B) -> f64 { + let mut x = d; + let t = x.to_bits(); + let ux = t; + let ax = ux & 0x7fffffffffffffffu64; + + if ux >= 0xc04b000000000000u64 { + // x = -NaN or x <= -54 + if (ux >> 52) == 0xfff { + // -NaN or -Inf + return if ux > 0xfff0000000000000u64 { + x + x + } else { + -1.0 + }; + } + // for x <= -54, exp2m1(x) rounds to -1 to nearest + return -1.0 + f64::from_bits(0x3c90000000000000); + } else if ax >= 0x4090000000000000u64 { + // x = +NaN or x >= 1024 + if (ux >> 52) == 0x7ff { + // +NaN + return x + x; + } + /* for x >= 1024, exp2m1(x) rounds to +Inf to nearest, + but for RNDZ/RNDD, we should have no overflow for x=1024 */ + return backend.fma( + x, + f64::from_bits(0x7bffffffffffffff), + f64::from_bits(0x7fefffffffffffff), + ); + } else if ax <= 0x3cc0527dbd87e24du64 + // |x| <= 0x1.0527dbd87e24dp-51 + /* then the second term of the Taylor expansion of 2^x-1 at x=0 is + smaller in absolute value than 1/2 ulp(first term): + log(2)*x + log(2)^2*x^2/2 + ... */ + { + /* we use special code when log(2)*|x| is very small, in which case + the double-double approximation h+l has its lower part l + "truncated" */ + return if ax <= 0x3970000000000000u64 + // |x| <= 2^-104 + { + // special case for 0 + if x == 0. { + return x; + } + // scale x by 2^106 + x *= f64::from_bits(0x4690000000000000); + let z = backend.quick_mult_f64(DoubleDouble::new(LN2L, LN2H), x); + let mut h2 = z.to_f64(); // round to 53-bit precision + // scale back, hoping to avoid double rounding + h2 *= f64::from_bits(0x3950000000000000); + // now subtract back h2 * 2^106 from h to get the correction term + let mut h = backend.dd_fma(-h2, f64::from_bits(0x4690000000000000), z.hi); + // add l + h += z.lo; + /* add h2 + h * 2^-106. Warning: when h=0, 2^-106*h2 might be exact, + thus no underflow will be raised. We have underflow for + 0 < x <= 0x1.71547652b82fep-1022 for RNDZ, and for + 0 < x <= 0x1.71547652b82fdp-1022 for RNDN/RNDU. */ + backend.dyad_fma(h, f64::from_bits(0x3950000000000000), h2) + } else { + const C2: f64 = f64::from_bits(0x3fcebfbdff82c58f); // log(2)^2/2 + let mut z = backend.exact_mult(LN2H, x); + z.lo = backend.dyad_fma(LN2L, x, z.lo); + /* h+l approximates the first term x*log(2) */ + /* we add C2*x^2 last, so that in case there is a cancellation in + LN2L*x+l, it will contribute more bits */ + z.lo = backend.fma(C2, x * x, z.lo); + z.to_f64() + }; + } + + /* now -54 < x < -0x1.0527dbd87e24dp-51 + or 0x1.0527dbd87e24dp-51 < x < 1024 */ + + /* 2^x-1 is exact for x integer, -53 <= x <= 53 */ + if ux.wrapping_shl(17) == 0 { + let i = unsafe { backend.floor(x).to_int_unchecked::() }; + if x == i as f64 && -53 <= i && i <= 53 { + return if i >= 0 { + ((1u64 << i) - 1) as f64 + } else { + -1.0 + fast_ldexp(1.0, i) + }; + } + } + + let result = exp2m1_fast(x, ax <= 0x3fc0000000000000u64, &backend); + let left = result.exp.hi + (result.exp.lo - result.err); + let right = result.exp.hi + (result.exp.lo + result.err); + if left != right { + return exp2m1_accurate(x, &backend); + } + left +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp2m1_fma_impl(x: f64) -> f64 { + use crate::exponents::expf::FmaBackend; + exp2m1_gen(x, FmaBackend {}) +} + +/// Computes 2^x - 1 +/// +/// Max found ULP 0.5 +pub fn f_exp2m1(d: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp2m1_gen(d, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp2m1_fma_impl + } else { + fn def_exp2m1(x: f64) -> f64 { + exp2m1_gen(x, GenericExpfBackend {}) + } + def_exp2m1 + } + }); + unsafe { q(d) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp2m1() { + assert_eq!(f_exp2m1(5.4172231599824623E-312), 3.75493295981e-312); + assert_eq!(f_exp2m1( 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017800593653177087), 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012338431302992956); + assert_eq!(3., f_exp2m1(2.0)); + assert_eq!(4.656854249492381, f_exp2m1(2.5)); + assert_eq!(-0.30801352040368324, f_exp2m1(-0.5311842449009418)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp2m1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,188 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::exp2f::EXP2F_TABLE; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; + +#[inline(always)] +fn exp2m1f_gen(x: f32, backend: B) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + if x_abs >= 0x4300_0000u32 || x_abs <= 0x3d00_0000u32 { + // |x| <= 2^-5 + if x_abs <= 0x3d00_0000u32 { + // Minimax polynomial generated by Sollya with: + // > display = hexadecimal; + // > fpminimax((2^x - 1)/x, 5, [|D...|], [-2^-5, 2^-5]); + const C: [u64; 6] = [ + 0x3fe62e42fefa39f3, + 0x3fcebfbdff82c57b, + 0x3fac6b08d6f2d7aa, + 0x3f83b2ab6fc92f5d, + 0x3f55d897cfe27125, + 0x3f243090e61e6af1, + ]; + let xd = x as f64; + let xsq = xd * xd; + let c0 = backend.fma(xd, f64::from_bits(C[1]), f64::from_bits(C[0])); + let c1 = backend.fma(xd, f64::from_bits(C[3]), f64::from_bits(C[2])); + let c2 = backend.fma(xd, f64::from_bits(C[5]), f64::from_bits(C[4])); + let p = backend.polyeval3(xsq, c0, c1, c2); + return (p * xd) as f32; + } + + // x >= 128, or x is nan + if x.is_sign_positive() { + // x >= 128 and 2^x - 1 rounds to +inf, or x is +inf or nan + return x + f32::INFINITY; + } + } + + if x <= -25.0 { + // 2^(-inf) - 1 = -1 + if x.is_infinite() { + return -1.0; + } + // 2^nan - 1 = nan + if x.is_nan() { + return x; + } + return -1.0; + } + + // For -25 < x < 128, to compute 2^x, we perform the following range + // reduction: find hi, mid, lo such that: + // x = hi + mid + lo, in which: + // hi is an integer, + // 0 <= mid * 2^5 < 32 is an integer, + // -2^(-6) <= lo <= 2^(-6). + // In particular, + // hi + mid = round(x * 2^5) * 2^(-5). + // Then, + // 2^x = 2^(hi + mid + lo) = 2^hi * 2^mid * 2^lo. + // 2^mid is stored in the lookup table of 32 elements. + // 2^lo is computed using a degree-4 minimax polynomial generated by Sollya. + // We perform 2^hi * 2^mid by simply add hi to the exponent field of 2^mid. + + // kf = (hi + mid) * 2^5 = round(x * 2^5) + + let xd = x as f64; + + let kf = backend.roundf(x * 64.0); + let k = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + // dx = lo = x - (hi + mid) = x - kf * 2^(-6) + let dx = backend.fma(f64::from_bits(0xbf90000000000000), kf as f64, xd); + + const TABLE_BITS: u32 = 6; + const TABLE_MASK: u64 = (1u64 << TABLE_BITS) - 1; + + // hi = floor(kf * 2^(-5)) + // exp_hi = shift hi to the exponent field of double precision. + let exp_hi: i64 = ((k >> TABLE_BITS) as i64).wrapping_shl(52); + + // mh = 2^hi * 2^mid + // mh_bits = bit field of mh + let mh_bits = (EXP2F_TABLE[((k as u64) & TABLE_MASK) as usize] as i64).wrapping_add(exp_hi); + let mh = f64::from_bits(mh_bits as u64); + + // Degree-4 polynomial approximating (2^x - 1)/x generated by Sollya with: + // > P = fpminimax((2^y - 1)/y, 4, [|D...|], [-1/64. 1/64]); + // see ./notes/exp2f.sollya + const C: [u64; 5] = [ + 0x3fe62e42fefa39ef, + 0x3fcebfbdff8131c4, + 0x3fac6b08d7061695, + 0x3f83b2b1bee74b2a, + 0x3f55d88091198529, + ]; + let dx_sq = dx * dx; + let c1 = backend.fma(dx, f64::from_bits(C[0]), 1.0); + let c2 = backend.fma(dx, f64::from_bits(C[2]), f64::from_bits(C[1])); + let c3 = backend.fma(dx, f64::from_bits(C[4]), f64::from_bits(C[3])); + let p = backend.polyeval3(dx_sq, c1, c2, c3); + // 2^x = 2^(hi + mid + lo) + // = 2^(hi + mid) * 2^lo + // ~ mh * (1 + lo * P(lo)) + // = mh + (mh*lo) * P(lo) + backend.fma(p, mh, -1.) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn exp2m1f_fma_impl(x: f32) -> f32 { + use crate::exponents::expf::FmaBackend; + exp2m1f_gen(x, FmaBackend {}) +} + +/// Computes 2^x - 1 +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_exp2m1f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + exp2m1f_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + exp2m1f_fma_impl + } else { + fn def_exp2f(x: f32) -> f32 { + exp2m1f_gen(x, GenericExpfBackend {}) + } + def_exp2f + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exp2m1f() { + assert_eq!(f_exp2m1f(0.432423), 0.34949815); + assert_eq!(f_exp2m1f(-4.), -0.9375); + assert_eq!(f_exp2m1f(5.43122), 42.14795); + assert_eq!(f_exp2m1f(4.), 15.0); + assert_eq!(f_exp2m1f(3.), 7.); + assert_eq!(f_exp2m1f(0.1), 0.07177346); + assert_eq!(f_exp2m1f(0.0543432432), 0.038386293); + assert!(f_exp2m1f(f32::NAN).is_nan()); + assert_eq!(f_exp2m1f(f32::INFINITY), f32::INFINITY); + assert_eq!(f_exp2m1f(f32::NEG_INFINITY), -1.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp_f128.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp_f128.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/exp_f128.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/exp_f128.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,289 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +#[inline] +fn poly_exp_f128(x: DyadicFloat128) -> DyadicFloat128 { + static COEFFS_128: [DyadicFloat128; 8] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 1.0 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 1.0 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 0.5 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, // 1/6 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, // 1/24 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x88888888_88888888_88888888_88888889_u128, + }, // 1/120 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xb60b60b6_0b60b60b_60b60b60_b60b60b6_u128, + }, // 1/720 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0xd00d00d0_0d00d00d_00d00d00_d00d00d0_u128, + }, // 1/5040 + ]; + + let mut z = COEFFS_128[7]; + for i in (0..7).rev() { + z = x * z + COEFFS_128[i]; + } + z +} + +#[cold] +#[inline(never)] +pub(crate) fn rational128_exp(x: f64) -> DyadicFloat128 { + const LOG2_E: f64 = f64::from_bits(0x3ff71547652b82fe); + let tmp = f_fmla(x, LOG2_E, f64::from_bits(0x4148000000040000)); + let k = (tmp.to_bits() >> 19) as i32; + let kd = k as f64; + + let idx1: usize = ((k >> 6) & 0x3f) as usize; + let idx2 = (k & 0x3f) as usize; + + const MLOG_2_EXP2_M12_HI: f64 = f64::from_bits(0xbf262e42ff000000); + const MLOG_2_EXP2_M12_MID_30: f64 = f64::from_bits(0x3d0718432a000000); + const MLOG_2_EXP2_M12_LO: f64 = f64::from_bits(0x3b0b0e2633fe0685); + + let t1 = f_fmla(kd, MLOG_2_EXP2_M12_HI, x); // exact + let t2 = kd * MLOG_2_EXP2_M12_MID_30; // exact + let t3 = kd * MLOG_2_EXP2_M12_LO; // Error < 2^-133 + + let dx = DyadicFloat128::new_from_f64(t1) + + (DyadicFloat128::new_from_f64(t2) + DyadicFloat128::new_from_f64(t3)); + + let exp_mid1 = DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID1[idx1].2)) + + (DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID1[idx1].1)) + + DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID1[idx1].0))); + + let exp_mid2 = DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID2[idx2].2)) + + (DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID2[idx2].1)) + + DyadicFloat128::new_from_f64(f64::from_bits(TD_EXP2_MID2[idx2].0))); + + let exp_mid = exp_mid1 * exp_mid2; + + let p = poly_exp_f128(dx); + + let mut r = exp_mid * p; + + r.exponent += (kd as i64 >> 12) as i16; + + r +} + +// Lookup table for 2^(k * 2^-6) with k = 0..63. +// Generated by Sollya with: +// > display=hexadecimal; +// > prec = 500; +// > for i from 0 to 63 do { +// a = 2^(i * 2^-6); +// b = round(a, D, RN); +// c = round(a - b, D, RN); +// d = round(a - b - c, D, RN); +// print("{", d, ",", c, ",", b, "},"); +// }; +static TD_EXP2_MID1: [(u64, u64, u64); 64] = [ + (0x0000000000000000, 0x0000000000000000, 0x3ff0000000000000), + (0xb919085b0a3d74d5, 0xbc719083535b085d, 0x3ff02c9a3e778061), + (0x39105ff94f8d257e, 0x3c8d73e2a475b465, 0x3ff059b0d3158574), + (0x39015820d96b414f, 0x3c6186be4bb284ff, 0x3ff0874518759bc8), + (0xb9367c9bd6ebf74c, 0x3c98a62e4adc610b, 0x3ff0b5586cf9890f), + (0xb8e5aa76994e9ddb, 0x3c403a1727c57b53, 0x3ff0e3ec32d3d1a2), + (0x3929d58b988f562d, 0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xb932fe7bb4c76416, 0xbc932fbf9af1369e, 0x3ff1429aaea92de0), + (0x3924f2406aa13ff0, 0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x390ad36183926ae8, 0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75), + (0x391ea62d0881b918, 0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0xb90781dbc16f1ea4, 0x3c8dc775814a8495, 0x3ff2063b88628cd6), + (0xb924d89f9af532e0, 0x3c99b07eb6c70573, 0x3ff2387a6e756238), + (0x391277393a461b77, 0x3c82bd339940e9d9, 0x3ff26b4565e27cdd), + (0x390de54485604690, 0x3c8612e8afad1255, 0x3ff29e9df51fdee1), + (0xb91ee9d8f8cb9307, 0x3c90024754db41d5, 0x3ff2d285a6e4030b), + (0x3917b7b2f09cd0d9, 0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0xb93406a2ea6cfc6b, 0x3c932721843659a6, 0x3ff33c08b26416ff), + (0x39387e3e12516bfa, 0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0x3909b0b1ff17c296, 0xbc75e436d661f5e3, 0x3ff3a7db34e59ff7), + (0xb92808ba68fa8fb7, 0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0xb8d32b43eafc6518, 0xbc5ef3691c309278, 0x3ff4160a21f72e2a), + (0xb8d0ac312de3d922, 0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x390e1eebae743ac0, 0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0), + (0x38ec06c7745c2b39, 0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xb8f1aa1fd7b685cd, 0xbc94b309d25957e3, 0x3ff4f9b2769d2ca7), + (0x390fa733951f214c, 0xbc807abe1db13cad, 0x3ff5342b569d4f82), + (0xb90ff86852a613ff, 0x3c99bb2c011d93ad, 0x3ff56f4736b527da), + (0xb92744ee506fdafe, 0x3c96324c054647ad, 0x3ff5ab07dd485429), + (0xb9395f9ab75fa7d6, 0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148), + (0x3905d8e757cfb991, 0xbc9383c17e40b497, 0x3ff6247eb03a5585), + (0x3934a337f4dc0a3b, 0xbc9bb60987591c34, 0x3ff6623882552225), + (0x39357d3e3adec175, 0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), + (0x38ca59f88abbe778, 0xbc6bbe3a683c88ab, 0x3ff6dfb23c651a2f), + (0xb92269796953a4c3, 0xbc816e4786887a99, 0x3ff71f75e8ec5f74), + (0xb938f8e7fa19e5e8, 0xbc90245957316dd3, 0x3ff75feb564267c9), + (0xb8e4217a932d10d4, 0xbc841577ee04992f, 0x3ff7a11473eb0187), + (0x38f70a1427f8fcdf, 0x3c705d02ba15797e, 0x3ff7e2f336cf4e62), + (0x38f0f6ad65cbbac1, 0xbc9d4c1dd41532d8, 0x3ff82589994cce13), + (0xb92f16f65181d921, 0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed), + (0xb9130644a7836333, 0x3c96e9f156864b27, 0x3ff8ace5422aa0db), + (0x38d3bf26d2b85163, 0x3c85cc13a2e3976c, 0x3ff8f1ae99157736), + (0x390697e257ac0db2, 0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5), + (0x3937edb9d7144b6f, 0xbc9d185b7c1b85d1, 0x3ff97d829fde4e50), + (0x3916376b7943085c, 0x3c7c7c46b071f2be, 0x3ff9c49182a3f090), + (0x392354084551b4fb, 0xbc9359495d1cd533, 0x3ffa0c667b5de565), + (0xb90bfd7adfd63f48, 0xbc9d2f6edb8d41e1, 0x3ffa5503b23e255d), + (0x3928b16ae39e8cb9, 0x3c90fac90ef7fd31, 0x3ffa9e6b5579fdbf), + (0x393a7fbc3ae675ea, 0x3c97a1cd345dcc81, 0x3ffae89f995ad3ad), + (0x3902babc0edda4d9, 0xbc62805e3084d708, 0x3ffb33a2b84f15fb), + (0x390aa64481e1ab72, 0xbc75584f7e54ac3b, 0x3ffb7f76f2fb5e47), + (0x3929a164050e1258, 0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2), + (0x39199e51125928da, 0x3c811065895048dd, 0x3ffc199bdd85529c), + (0xb92fc44c329d5cb2, 0x3c92884dff483cad, 0x3ffc67f12e57d14b), + (0x391d8765566b032e, 0x3c7503cbd1e949db, 0x3ffcb720dcef9069), + (0xb93e7044039da0f6, 0xbc9cbc3743797a9c, 0x3ffd072d4a07897c), + (0xb90ab053b05531fc, 0x3c82ed02d75b3707, 0x3ffd5818dcfba487), + (0x3937f6246f0ec615, 0x3c9c2300696db532, 0x3ffda9e603db3285), + (0x393b7225a944efd6, 0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f), + (0x3921e92cb3c2d278, 0x3c839e8980a9cc8f, 0x3ffe502ee78b3ff6), + (0xb92fc0f242bbf3de, 0xbc9e9c23179c2893, 0x3ffea4afa2a490da), + (0x393f6dd5d229ff69, 0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27), + (0xb914019bffc80ef3, 0x3c99d3e12dd8a18b, 0x3fff50765b6e4540), + (0x38fdc060c36f7651, 0x3c874853f3a5931e, 0x3fffa7c1819e90d8), +]; + +// Lookup table for 2^(k * 2^-12) with k = 0..63. +// Generated by Sollya with: +// > display=hexadecimal; +// > prec = 500; +// > for i from 0 to 63 do { +// a = 2^(i * 2^-12); +// b = round(a, D, RN); +// c = round(a - b, D, RN); +// d = round(a - b - c, D, RN); +// print("{", d, ",", c, ",", b, "},"); +// }; +static TD_EXP2_MID2: [(u64, u64, u64); 64] = [ + (0x0000000000000000, 0x0000000000000000, 0x3ff0000000000000), + (0x39339726694630e3, 0x3c9ae8e38c59c72a, 0x3ff000b175effdc7), + (0x38fe5e06ddd31156, 0xbc57b5d0d58ea8f4, 0x3ff00162f3904052), + (0x3905a0768b51f609, 0x3c94115cb6b16a8e, 0x3ff0021478e11ce6), + (0x390d008403605217, 0xbc8d7c96f201bb2f, 0x3ff002c605e2e8cf), + (0x39289bc16f765708, 0x3c984711d4c35e9f, 0x3ff003779a95f959), + (0xb924535b7f8c1e2d, 0xbc80484245243777, 0x3ff0042936faa3d8), + (0xb938ba92f6b25456, 0xbc94b237da2025f9, 0x3ff004dadb113da0), + (0xb8e30c72e81f4294, 0xbc75e00e62d6b30d, 0x3ff0058c86da1c0a), + (0xb9134a5384e6f0b9, 0x3c9a1d6cedbb9481, 0x3ff0063e3a559473), + (0x393f8d0580865d2e, 0xbc94acf197a00142, 0x3ff006eff583fc3d), + (0xb90002bcb3ae9a99, 0xbc6eaf2ea42391a5, 0x3ff007a1b865a8ca), + (0x390c3c5aedee9851, 0x3c7da93f90835f75, 0x3ff0085382faef83), + (0x3927217851d1ec6e, 0xbc86a79084ab093c, 0x3ff00905554425d4), + (0xb9180cbca335a7c3, 0x3c986364f8fbe8f8, 0x3ff009b72f41a12b), + (0xb91706bd4eb22595, 0xbc882e8e14e3110e, 0x3ff00a6910f3b6fd), + (0xb90b55dd523f3c08, 0xbc84f6b2a7609f71, 0x3ff00b1afa5abcbf), + (0x39190a1e207cced1, 0xbc7e1a258ea8f71b, 0x3ff00bcceb7707ec), + (0x39178d0472db37c5, 0x3c74362ca5bc26f1, 0x3ff00c7ee448ee02), + (0xb92bcd4db3cb52fe, 0x3c9095a56c919d02, 0x3ff00d30e4d0c483), + (0xb8fcf1b131575ec2, 0xbc6406ac4e81a645, 0x3ff00de2ed0ee0f5), + (0xb8f6aaa1fa7ff913, 0x3c9b5a6902767e09, 0x3ff00e94fd0398e0), + (0x39168f236dff3218, 0xbc991b2060859321, 0x3ff00f4714af41d3), + (0xb92e8bb58067e60a, 0x3c8427068ab22306, 0x3ff00ff93412315c), + (0x393d4cd5e1d71fdf, 0x3c9c1d0660524e08, 0x3ff010ab5b2cbd11), + (0x393e4ecf350ebe88, 0xbc9e7bdfb3204be8, 0x3ff0115d89ff3a8b), + (0x3926a2aa2c89c4f8, 0x3c8843aa8b9cbbc6, 0x3ff0120fc089ff63), + (0x3911ca368a20ed05, 0xbc734104ee7edae9, 0x3ff012c1fecd613b), + (0x38dedb1095d925cf, 0xbc72b6aeb6176892, 0x3ff0137444c9b5b5), + (0xb90488c78eded75f, 0x3c7a8cd33b8a1bb3, 0x3ff01426927f5278), + (0xb8e7480f5ea1b3c9, 0x3c72edc08e5da99a, 0x3ff014d8e7ee8d2f), + (0xb90ae45989a04dd5, 0x3c857ba2dc7e0c73, 0x3ff0158b4517bb88), + (0x392bf48007d80987, 0x3c9b61299ab8cdb7, 0x3ff0163da9fb3335), + (0x3921aa91a059292c, 0xbc990565902c5f44, 0x3ff016f0169949ed), + (0x391b6663292855f5, 0x3c870fc41c5c2d53, 0x3ff017a28af25567), + (0x393e7fbca6793d94, 0x3c94b9a6e145d76c, 0x3ff018550706ab62), + (0xb915b9f5c7de3b93, 0xbc7008eff5142bf9, 0x3ff019078ad6a19f), + (0x3914638bf2f6acab, 0xbc977669f033c7de, 0x3ff019ba16628de2), + (0xb92ab237b9a069c5, 0xbc909bb78eeead0a, 0x3ff01a6ca9aac5f3), + (0x3933ab358be97cef, 0x3c9371231477ece5, 0x3ff01b1f44af9f9e), + (0xb914027b2294bb64, 0x3c75e7626621eb5b, 0x3ff01bd1e77170b4), + (0x390656394426c990, 0xbc9bc72b100828a5, 0x3ff01c8491f08f08), + (0x390bf9785189bdd8, 0xbc6ce39cbbab8bbe, 0x3ff01d37442d5070), + (0x3927c12f86114fe3, 0x3c816996709da2e2, 0x3ff01de9fe280ac8), + (0xb92653d5d24b5d28, 0xbc8c11f5239bf535, 0x3ff01e9cbfe113ef), + (0x39204a0cdc1d86d7, 0x3c8e1d4eb5edc6b3, 0x3ff01f4f8958c1c6), + (0x392c678c46149782, 0xbc9afb99946ee3f0, 0x3ff020025a8f6a35), + (0x39348524e1e9df70, 0xbc98f06d8a148a32, 0x3ff020b533856324), + (0x3929953ea727ff0b, 0xbc82bf310fc54eb6, 0x3ff02168143b0281), + (0xb93ccfbbec22d28e, 0xbc9c95a035eb4175, 0x3ff0221afcb09e3e), + (0x3939e2bb6e181de1, 0xbc9491793e46834d, 0x3ff022cdece68c4f), + (0x391f17609ae29308, 0xbc73e8d0d9c49091, 0x3ff02380e4dd22ad), + (0xb91c7dc2c476bfb8, 0xbc9314aa16278aa3, 0x3ff02433e494b755), + (0xb92fab994971d4a3, 0x3c848daf888e9651, 0x3ff024e6ec0da046), + (0x392848b62cbdd0af, 0x3c856dc8046821f4, 0x3ff02599fb483385), + (0xb92bf603ba715d0c, 0x3c945b42356b9d47, 0x3ff0264d1244c719), + (0x39189434e751e1aa, 0xbc7082ef51b61d7e, 0x3ff027003103b10e), + (0xb9103b54fd64e8ac, 0x3c72106ed0920a34, 0x3ff027b357854772), + (0x3927785ea0acc486, 0xbc9fd4cf26ea5d0f, 0x3ff0286685c9e059), + (0xb92ce447fdb35ff9, 0xbc909f8775e78084, 0x3ff02919bbd1d1d8), + (0x38f5b884aab5642a, 0x3c564cbba902ca27, 0x3ff029ccf99d720a), + (0xb93cfb3e46d7c1c0, 0x3c94383ef231d207, 0x3ff02a803f2d170d), + (0xb8f0d40cee4b81af, 0x3c94a47a505b3a47, 0x3ff02b338c811703), + (0x3926ae7d36d7c1f7, 0x3c9e47120223467f, 0x3ff02be6e199c811), +]; + +#[cfg(test)] +mod tests { + use crate::exponents::exp_f128::rational128_exp; + + #[test] + fn test_exp() { + assert_eq!(rational128_exp(2.).fast_as_f64(), 7.38905609893065); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,841 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(clippy::too_many_arguments)] +use crate::common::{dd_fmla, dyad_fmla, f_fmla, f_fmlaf, fmlaf, pow2if, rintfk}; +use crate::double_double::DoubleDouble; +use crate::rounding::{CpuFloor, CpuRound}; + +const L2U_F: f32 = 0.693_145_751_953_125; +const L2L_F: f32 = 1.428_606_765_330_187_045_e-6; +const R_LN2_F: f32 = std::f32::consts::LOG2_E; + +/// Exp for given value for const context. +/// This is simplified version just to make a good approximation on const context. +#[inline] +pub const fn expf(d: f32) -> f32 { + const EXP_POLY_1_S: f32 = 2f32; + const EXP_POLY_2_S: f32 = 0.16666707f32; + const EXP_POLY_3_S: f32 = -0.002775669f32; + let qf = rintfk(d * R_LN2_F); + let q = qf as i32; + let r = fmlaf(qf, -L2U_F, d); + let r = fmlaf(qf, -L2L_F, r); + + let f = r * r; + // Poly for u = r*(exp(r)+1)/(exp(r)-1) + let mut u = EXP_POLY_3_S; + u = fmlaf(u, f, EXP_POLY_2_S); + u = fmlaf(u, f, EXP_POLY_1_S); + let u = 1f32 + 2f32 * r / (u - r); + let i2 = pow2if(q); + u * i2 + // if d < -87f32 { + // r = 0f32; + // } + // if d > 88f32 { + // r = f32::INFINITY; + // } +} + +// Lookup table for exp(m) with m = -104, ..., 102. +// -104 = floor(log(single precision's min denormal)) +// 103 = ceil(log(single precision's max bessel K(n) that will be used)) +// Table is generated with SageMath as follows: +// for r in range(-104, 103): +// print(double_to_hex(RealField(180)(r).exp()) + ",") +pub(crate) static EXP_M1: [u64; 207] = [ + 0x368f1e6b68529e33, + 0x36a525be4e4e601d, + 0x36bcbe0a45f75eb1, + 0x36d3884e838aea68, + 0x36ea8c1f14e2af5d, + 0x37020a717e64a9bd, + 0x3718851d84118908, + 0x3730a9bdfb02d240, + 0x3746a5bea046b42e, + 0x375ec7f3b269efa8, + 0x3774eafb87eab0f2, + 0x378c6e2d05bbc000, + 0x37a35208867c2683, + 0x37ba425b317eeacd, + 0x37d1d8508fa8246a, + 0x37e840fbc08fdc8a, + 0x38007b7112bc1ffe, + 0x381666d0dad2961d, + 0x382e726c3f64d0fe, + 0x3844b0dc07cabf98, + 0x385c1f2daf3b6a46, + 0x38731c5957a47de2, + 0x3889f96445648b9f, + 0x38a1a6baeadb4fd1, + 0x38b7fd974d372e45, + 0x38d04da4d1452919, + 0x38e62891f06b3450, + 0x38fe1dd273aa8a4a, + 0x3914775e0840bfdd, + 0x392bd109d9d94bda, + 0x3942e73f53fba844, + 0x3959b138170d6bfe, + 0x397175af0cf60ec5, + 0x3987baee1bffa80b, + 0x39a02057d1245ceb, + 0x39b5eafffb34ba31, + 0x39cdca23bae16424, + 0x39e43e7fc88b8056, + 0x39fb83bf23a9a9eb, + 0x3a12b2b8dd05b318, + 0x3a2969d47321e4cc, + 0x3a41452b7723aed2, + 0x3a5778fe2497184c, + 0x3a6fe7116182e9cc, + 0x3a85ae191a99585a, + 0x3a9d775d87da854d, + 0x3ab4063f8cc8bb98, + 0x3acb374b315f87c1, + 0x3ae27ec458c65e3c, + 0x3af923372c67a074, + 0x3b11152eaeb73c08, + 0x3b2737c5645114b5, + 0x3b3f8e6c24b5592e, + 0x3b5571db733a9d61, + 0x3b6d257d547e083f, + 0x3b83ce9b9de78f85, + 0x3b9aebabae3a41b5, + 0x3bb24b6031b49bda, + 0x3bc8dd5e1bb09d7e, + 0x3be0e5b73d1ff53d, + 0x3bf6f741de1748ec, + 0x3c0f36bd37f42f3e, + 0x3c2536452ee2f75c, + 0x3c3cd480a1b74820, + 0x3c539792499b1a24, + 0x3c6aa0de4bf35b38, + 0x3c82188ad6ae3303, + 0x3c9898471fca6055, + 0x3cb0b6c3afdde064, + 0x3cc6b7719a59f0e0, + 0x3cdee001eed62aa0, + 0x3cf4fb547c775da8, + 0x3d0c8464f7616468, + 0x3d236121e24d3bba, + 0x3d3a56e0c2ac7f75, + 0x3d51e642baeb84a0, + 0x3d6853f01d6d53ba, + 0x3d80885298767e9a, + 0x3d967852a7007e42, + 0x3dae8a37a45fc32e, + 0x3dc4c1078fe9228a, + 0x3ddc3527e433fab1, + 0x3df32b48bf117da2, + 0x3e0a0db0d0ddb3ec, + 0x3e21b48655f37267, + 0x3e381056ff2c5772, + 0x3e505a628c699fa1, + 0x3e6639e3175a689d, + 0x3e7e355bbaee85cb, + 0x3e94875ca227ec38, + 0x3eabe6c6fdb01612, + 0x3ec2f6053b981d98, + 0x3ed9c54c3b43bc8b, + 0x3ef18354238f6764, + 0x3f07cd79b5647c9b, + 0x3f202cf22526545a, + 0x3f35fc21041027ad, + 0x3f4de16b9c24a98f, + 0x3f644e51f113d4d6, + 0x3f7b993fe00d5376, + 0x3f92c155b8213cf4, + 0x3fa97db0ccceb0af, + 0x3fc152aaa3bf81cc, + 0x3fd78b56362cef38, + 0x3ff0000000000000, + 0x4005bf0a8b145769, + 0x401d8e64b8d4ddae, + 0x403415e5bf6fb106, + 0x404b4c902e273a58, + 0x40628d389970338f, + 0x407936dc5690c08f, + 0x409122885aaeddaa, + 0x40a749ea7d470c6e, + 0x40bfa7157c470f82, + 0x40d5829dcf950560, + 0x40ed3c4488ee4f7f, + 0x4103de1654d37c9a, + 0x411b00b5916ac955, + 0x413259ac48bf05d7, + 0x4148f0ccafad2a87, + 0x4160f2ebd0a80020, + 0x417709348c0ea4f9, + 0x418f4f22091940bd, + 0x41a546d8f9ed26e1, + 0x41bceb088b68e804, + 0x41d3a6e1fd9eecfd, + 0x41eab5adb9c43600, + 0x420226af33b1fdc1, + 0x4218ab7fb5475fb7, + 0x4230c3d3920962c9, + 0x4246c932696a6b5d, + 0x425ef822f7f6731d, + 0x42750bba3796379a, + 0x428c9aae4631c056, + 0x42a370470aec28ed, + 0x42ba6b765d8cdf6d, + 0x42d1f43fcc4b662c, + 0x42e866f34a725782, + 0x4300953e2f3a1ef7, + 0x431689e221bc8d5b, + 0x432ea215a1d20d76, + 0x4344d13fbb1a001a, + 0x435c4b334617cc67, + 0x43733a43d282a519, + 0x438a220d397972eb, + 0x43a1c25c88df6862, + 0x43b8232558201159, + 0x43d0672a3c9eb871, + 0x43e64b41c6d37832, + 0x43fe4cf766fe49be, + 0x44149767bc0483e3, + 0x442bfc951eb8bb76, + 0x444304d6aeca254b, + 0x4459d97010884251, + 0x44719103e4080b45, + 0x4487e013cd114461, + 0x44a03996528e074c, + 0x44b60d4f6fdac731, + 0x44cdf8c5af17ba3b, + 0x44e45e3076d61699, + 0x44fbaed16a6e0da7, + 0x4512cffdfebde1a1, + 0x4529919cabefcb69, + 0x454160345c9953e3, + 0x45579dbc9dc53c66, + 0x45700c810d464097, + 0x4585d009394c5c27, + 0x459da57de8f107a8, + 0x45b425982cf597cd, + 0x45cb61e5ca3a5e31, + 0x45e29bb825dfcf87, + 0x45f94a90db0d6fe2, + 0x46112fec759586fd, + 0x46275c1dc469e3af, + 0x463fbfd219c43b04, + 0x4655936d44e1a146, + 0x466d531d8a7ee79c, + 0x4683ed9d24a2d51b, + 0x469b15cfe5b6e17b, + 0x46b268038c2c0e00, + 0x46c9044a73545d48, + 0x46e1002ab6218b38, + 0x46f71b3540cbf921, + 0x470f6799ea9c414a, + 0x47255779b984f3eb, + 0x473d01a210c44aa4, + 0x4753b63da8e91210, + 0x476aca8d6b0116b8, + 0x478234de9e0c74e9, + 0x4798bec7503ca477, + 0x47b0d0eda9796b90, + 0x47c6db0118477245, + 0x47df1056dc7bf22d, + 0x47f51c2cc3433801, + 0x480cb108ffbec164, + 0x48237f780991b584, + 0x483a801c0ea8ac4d, + 0x48520247cc4c46c1, + 0x48687a0553328015, + 0x4880a233dee4f9bb, + 0x48969b7f55b808ba, + 0x48aeba064644060a, + 0x48c4e184933d9364, + 0x48dc614fe2531841, + 0x48f3494a9b171bf5, + 0x490a36798b9d969b, + 0x4921d03d8c0c04af, +]; + +// Lookup table for exp(m * 2^(-7)) with m = 0, ..., 127. +// Table is generated with Sollya as follows: +// > display = hexadecimal; +// > for i from 0 to 127 do { D(exp(i / 128)); }; +pub(crate) static EXP_M2: [u64; 128] = [ + 0x3ff0000000000000, + 0x3ff0202015600446, + 0x3ff04080ab55de39, + 0x3ff06122436410dd, + 0x3ff08205601127ed, + 0x3ff0a32a84e9c1f6, + 0x3ff0c49236829e8c, + 0x3ff0e63cfa7ab09d, + 0x3ff1082b577d34ed, + 0x3ff12a5dd543ccc5, + 0x3ff14cd4fc989cd6, + 0x3ff16f9157587069, + 0x3ff192937074e0cd, + 0x3ff1b5dbd3f68122, + 0x3ff1d96b0eff0e79, + 0x3ff1fd41afcba45e, + 0x3ff2216045b6f5cd, + 0x3ff245c7613b8a9b, + 0x3ff26a7793f60164, + 0x3ff28f7170a755fd, + 0x3ff2b4b58b372c79, + 0x3ff2da4478b620c7, + 0x3ff3001ecf601af7, + 0x3ff32645269ea829, + 0x3ff34cb8170b5835, + 0x3ff373783a722012, + 0x3ff39a862bd3c106, + 0x3ff3c1e2876834aa, + 0x3ff3e98deaa11dcc, + 0x3ff41188f42c3e32, + 0x3ff439d443f5f159, + 0x3ff462707b2bac21, + 0x3ff48b5e3c3e8186, + 0x3ff4b49e2ae5ac67, + 0x3ff4de30ec211e60, + 0x3ff50817263c13cd, + 0x3ff5325180cfacf7, + 0x3ff55ce0a4c58c7c, + 0x3ff587c53c5a7af0, + 0x3ff5b2fff3210fd9, + 0x3ff5de9176045ff5, + 0x3ff60a7a734ab0e8, + 0x3ff636bb9a983258, + 0x3ff663559cf1bc7c, + 0x3ff690492cbf9433, + 0x3ff6bd96fdd034a2, + 0x3ff6eb3fc55b1e76, + 0x3ff719443a03acb9, + 0x3ff747a513dbef6a, + 0x3ff776630c678bc1, + 0x3ff7a57ede9ea23e, + 0x3ff7d4f946f0ba8d, + 0x3ff804d30347b546, + 0x3ff8350cd30ac390, + 0x3ff865a7772164c5, + 0x3ff896a3b1f66a0e, + 0x3ff8c802477b0010, + 0x3ff8f9c3fd29beaf, + 0x3ff92be99a09bf00, + 0x3ff95e73e6b1b75e, + 0x3ff99163ad4b1dcc, + 0x3ff9c4b9b995509b, + 0x3ff9f876d8e8c566, + 0x3ffa2c9bda3a3e78, + 0x3ffa61298e1e069c, + 0x3ffa9620c6cb3374, + 0x3ffacb82581eee54, + 0x3ffb014f179fc3b8, + 0x3ffb3787dc80f95f, + 0x3ffb6e2d7fa5eb18, + 0x3ffba540dba56e56, + 0x3ffbdcc2cccd3c85, + 0x3ffc14b431256446, + 0x3ffc4d15e873c193, + 0x3ffc85e8d43f7cd0, + 0x3ffcbf2dd7d490f2, + 0x3ffcf8e5d84758a9, + 0x3ffd3311bc7822b4, + 0x3ffd6db26d16cd67, + 0x3ffda8c8d4a66969, + 0x3ffde455df80e3c0, + 0x3ffe205a7bdab73e, + 0x3ffe5cd799c6a54e, + 0x3ffe99ce2b397649, + 0x3ffed73f240dc142, + 0x3fff152b7a07bb76, + 0x3fff539424d90f5e, + 0x3fff927a1e24bb76, + 0x3fffd1de6182f8c9, + 0x400008e0f64294ab, + 0x40002912df5ce72a, + 0x400049856cd84339, + 0x40006a39207f0a09, + 0x40008b2e7d2035cf, + 0x4000ac6606916501, + 0x4000cde041b0e9ae, + 0x4000ef9db467dcf8, + 0x4001119ee5ac36b6, + 0x400133e45d82e952, + 0x4001566ea50201d7, + 0x4001793e4652cc50, + 0x40019c53ccb3fc6b, + 0x4001bfafc47bda73, + 0x4001e352bb1a74ad, + 0x4002073d3f1bd518, + 0x40022b6fe02a3b9c, + 0x40024feb2f105cb8, + 0x400274afbdbba4a6, + 0x400299be1f3e7f1c, + 0x4002bf16e7d2a38c, + 0x4002e4baacdb6614, + 0x40030aaa04e80d05, + 0x400330e587b62b28, + 0x4003576dce33fead, + 0x40037e437282d4ee, + 0x4003a5670ff972ed, + 0x4003ccd9432682b4, + 0x4003f49aa9d30590, + 0x40041cabe304cb34, + 0x4004450d8f00edd4, + 0x40046dc04f4e5338, + 0x400496c4c6b832da, + 0x4004c01b9950a111, + 0x4004e9c56c731f5d, + 0x400513c2e6c731d7, + 0x40053e14b042f9ca, + 0x400568bb722dd593, + 0x400593b7d72305bb, +]; + +pub(crate) trait ExpfBackend { + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32; + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64; + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64; + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64; + fn polyeval5(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64; + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64; + fn polyeval7( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + ) -> f64; + fn roundf(&self, x: f32) -> f32; + fn round(&self, x: f64) -> f64; + fn floor(&self, x: f64) -> f64; + fn round_ties_even(&self, x: f64) -> f64; + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble; + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble; + fn quick_f64_mult(&self, x: f64, y: DoubleDouble) -> DoubleDouble; + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble; +} + +pub(crate) struct GenericExpfBackend {} + +impl ExpfBackend for GenericExpfBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f_fmlaf(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + use crate::common::f_fmla; + f_fmla(x, y, z) + } + #[inline(always)] + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64 { + dd_fmla(x, y, z) + } + #[inline(always)] + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64 { + dyad_fmla(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::f_polyeval3; + f_polyeval3(x, a0, a1, a2) + } + + #[inline(always)] + fn polyeval5(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 { + use crate::polyeval::f_polyeval5; + f_polyeval5(x, a0, a1, a2, a3, a4) + } + + #[inline(always)] + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 { + use crate::polyeval::f_polyeval6; + f_polyeval6(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn polyeval7( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + ) -> f64 { + use crate::polyeval::f_polyeval7; + f_polyeval7(x, a0, a1, a2, a3, a4, a5, a6) + } + + #[inline(always)] + fn roundf(&self, x: f32) -> f32 { + x.cpu_round() + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.cpu_round() + } + + #[inline(always)] + fn floor(&self, x: f64) -> f64 { + x.cpu_floor() + } + + #[inline(always)] + fn round_ties_even(&self, x: f64) -> f64 { + use crate::rounding::CpuRoundTiesEven; + x.cpu_round_ties_even() + } + + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult(x, y) + } + + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64(x, y) + } + + #[inline(always)] + fn quick_f64_mult(&self, x: f64, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_f64(y, x) + } + + #[inline(always)] + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult(x, y) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub(crate) struct FmaBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl ExpfBackend for FmaBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f32::mul_add(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + + #[inline(always)] + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + #[inline(always)] + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::d_polyeval3; + d_polyeval3(x, a0, a1, a2) + } + + #[inline(always)] + fn polyeval5(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 { + use crate::polyeval::d_polyeval5; + d_polyeval5(x, a0, a1, a2, a3, a4) + } + + #[inline(always)] + fn polyeval6(&self, x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 { + use crate::polyeval::d_polyeval6; + d_polyeval6(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn polyeval7( + &self, + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + ) -> f64 { + use crate::polyeval::d_polyeval7; + d_polyeval7(x, a0, a1, a2, a3, a4, a5, a6) + } + + #[inline(always)] + fn roundf(&self, x: f32) -> f32 { + x.round() + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.round() + } + + #[inline(always)] + fn floor(&self, x: f64) -> f64 { + x.floor() + } + + #[inline(always)] + fn round_ties_even(&self, x: f64) -> f64 { + x.round_ties_even() + } + + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_fma(x, y) + } + + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64_fma(x, y) + } + + #[inline(always)] + fn quick_f64_mult(&self, x: f64, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_f64_fma(y, x) + } + + #[inline(always)] + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult_fma(x, y) + } +} + +#[inline(always)] +fn expf_gen_impl(x: f32, backend: B) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + if x_abs >= 0x42b2_0000u32 || x_abs <= 0x3280_0000u32 { + let exp = ((x_u >> 23) & 0xFF) as i32; + // |x| < 2^-25 + if exp <= 101i32 { + return 1.0 + x; + } + + // When x < log(2^-150) or nan + if x_u >= 0xc2cf_f1b5u32 { + // exp(-Inf) = 0 + if x.is_infinite() { + return 0.0; + } + // exp(nan) = nan + if x.is_nan() { + return x; + } + return 0.0; + } + // x >= 89 or nan + if x.is_sign_positive() && (x_u >= 0x42b2_0000) { + // x is +inf or nan + return x + f32::INFINITY; + } + } + + // For -104 < x < 89, to compute exp(x), we perform the following range + // reduction: find hi, mid, lo such that: + // x = hi + mid + lo, in which + // hi is an integer, + // mid * 2^7 is an integer + // -2^(-8) <= lo < 2^-8. + // In particular, + // hi + mid = round(x * 2^7) * 2^(-7). + // Then, + // exp(x) = exp(hi + mid + lo) = exp(hi) * exp(mid) * exp(lo). + // We store exp(hi) and exp(mid) in the lookup tables EXP_M1 and EXP_M2 + // respectively. exp(lo) is computed using a degree-4 minimax polynomial + // generated by Sollya. + + // x_hi = (hi + mid) * 2^7 = round(x * 2^7). + let kf = backend.roundf(x * 128.); + // Subtract (hi + mid) from x to get lo. + let xd = backend.fmaf(kf, -0.0078125 /* - 1/128 */, x) as f64; + let mut x_hi = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + x_hi += 104 << 7; + // hi = x_hi >> 7 + let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); + // mid * 2^7 = x_hi & 0x0000'007fU; + let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); + // Degree-4 minimax polynomial generated by Sollya with the following + // commands: + // d = [-2^-8, 2^-8]; + // f_exp = expm1(x)/x; + // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); + let p = backend.polyeval5( + xd, + 1., + f64::from_bits(0x3feffffffffff777), + f64::from_bits(0x3fe000000000071c), + f64::from_bits(0x3fc555566668e5e7), + f64::from_bits(0x3fa55555555ef243), + ); + (p * exp_hi * exp_mid) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn expf_fma_impl(x: f32) -> f32 { + expf_gen_impl(x, FmaBackend {}) +} + +/// Computes exp +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_expf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + expf_gen_impl(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + expf_fma_impl + } else { + fn def_expf(x: f32) -> f32 { + expf_gen_impl(x, GenericExpfBackend {}) + } + def_expf + } + }); + unsafe { q(x) } + } +} + +#[inline] +pub(crate) fn core_expf(x: f32) -> f64 { + // x_hi = (hi + mid) * 2^7 = round(x * 2^7). + let kf = (x * 128.).cpu_round(); + // Subtract (hi + mid) from x to get lo. + let xd = f_fmlaf(kf, -0.0078125 /* - 1/128 */, x) as f64; + let mut x_hi = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + x_hi += 104 << 7; + // hi = x_hi >> 7 + let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); + // mid * 2^7 = x_hi & 0x0000'007fU; + let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); + // Degree-4 minimax polynomial generated by Sollya with the following + // commands: + // d = [-2^-8, 2^-8]; + // f_exp = expm1(x)/x; + // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); + use crate::polyeval::f_polyeval5; + let p = f_polyeval5( + xd, + 1., + f64::from_bits(0x3feffffffffff777), + f64::from_bits(0x3fe000000000071c), + f64::from_bits(0x3fc555566668e5e7), + f64::from_bits(0x3fa55555555ef243), + ); + p * exp_hi * exp_mid +} + +#[inline] +pub(crate) fn core_expdf(x: f64) -> f64 { + // x_hi = (hi + mid) * 2^7 = round(x * 2^7). + let kf = (x * 128.).cpu_round(); + // Subtract (hi + mid) from x to get lo. + let xd = f_fmla(kf, -0.0078125 /* - 1/128 */, x); + let mut x_hi = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + x_hi += 104 << 7; + // hi = x_hi >> 7 + let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); + // mid * 2^7 = x_hi & 0x0000'007fU; + let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); + // Degree-4 minimax polynomial generated by Sollya with the following + // commands: + // d = [-2^-8, 2^-8]; + // f_exp = expm1(x)/x; + // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); + use crate::polyeval::f_polyeval5; + let p = f_polyeval5( + xd, + 1., + f64::from_bits(0x3feffffffffff777), + f64::from_bits(0x3fe000000000071c), + f64::from_bits(0x3fc555566668e5e7), + f64::from_bits(0x3fa55555555ef243), + ); + p * exp_hi * exp_mid +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn expf_test() { + assert!( + (expf(0f32) - 1f32).abs() < 1e-6, + "Invalid result {}", + expf(0f32) + ); + assert!( + (expf(5f32) - 148.4131591025766f32).abs() < 1e-6, + "Invalid result {}", + expf(5f32) + ); + } + + #[test] + fn f_expf_test() { + assert_eq!(f_expf(-103.971596), 1e-45); + assert!( + (f_expf(0f32) - 1f32).abs() < 1e-6, + "Invalid result {}", + f_expf(0f32) + ); + assert!( + (f_expf(5f32) - 148.4131591025766f32).abs() < 1e-6, + "Invalid result {}", + f_expf(5f32) + ); + assert_eq!(f_expf(f32::INFINITY), f32::INFINITY); + assert_eq!(f_expf(f32::NEG_INFINITY), 0.); + assert!(f_expf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expm1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expm1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,542 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; +use crate::exponents::fast_ldexp; +use crate::rounding::CpuRoundTiesEven; +use crate::shared_eval::poly_dekker_generic; +use std::hint::black_box; + +static TZ: [(u64, u64); 65] = [ + (0xbc6797d4686c5393, 0xbfcc5041854df7d4), + (0xbc8ea1cb9d163339, 0xbfcb881a23aebb48), + (0x3c8f483a3e8cd60f, 0xbfcabe60e1f21838), + (0x3c7dffd920f493db, 0xbfc9f3129931fab0), + (0xbc851bfdbb129094, 0xbfc9262c1c3430a0), + (0x3c8cd3e5225e2206, 0xbfc857aa375db4e4), + (0x3c5e3a6bdaece8f9, 0xbfc78789b0a5e0c0), + (0xbc8daf2ae0c2d3d4, 0xbfc6b5c7478983d8), + (0xbc7fd36226fadd44, 0xbfc5e25fb4fde210), + (0x3c7d887cd0341ab0, 0xbfc50d4fab639758), + (0xbc8676a52a1a618b, 0xbfc43693d679612c), + (0x3c79776b420ad283, 0xbfc35e28db4ecd9c), + (0x3c73d5fd7d70a5ed, 0xbfc2840b5836cf68), + (0x3c5a94ad2c8fa0bf, 0xbfc1a837e4ba3760), + (0x3c26ad4c353465b0, 0xbfc0caab118a1278), + (0xbc78bba170e59b65, 0xbfbfd6c2d0e3d910), + (0xbc8e1e0a76cb0685, 0xbfbe14aed893eef0), + (0x3c8fe131f55e75f8, 0xbfbc4f1331d22d40), + (0xbc8b5beee8bcee31, 0xbfba85e8c62d9c10), + (0xbc77fe9b02c25e9b, 0xbfb8b92870fa2b58), + (0xbc832ae7bdaf1116, 0xbfb6e8caff341fe8), + (0x3c7a6cfe58cbd73b, 0xbfb514c92f634788), + (0x3c68798de3138a56, 0xbfb33d1bb17df2e8), + (0xbc3589321a7ef10b, 0xbfb161bb26cbb590), + (0xbc78d0e700fcfb65, 0xbfaf0540438fd5c0), + (0x3c8473ef07d5dd3b, 0xbfab3f864c080000), + (0xbc838e62149c16e2, 0xbfa7723950130400), + (0xbc508bb6309bd394, 0xbfa39d4a1a77e050), + (0xbc8bad3fd501a227, 0xbf9f8152aee94500), + (0x3c63d27ac39ed253, 0xbf97b88f290230e0), + (0xbc8b60bbd08aac55, 0xbf8fc055004416c0), + (0xbc4a00d03b3359de, 0xbf7fe0154aaeed80), + (0x0000000000000000, 0x0000000000000000), + (0x3c8861931c15e39b, 0x3f80100ab00222c0), + (0x3c77ab864b3e9045, 0x3f90202ad5778e40), + (0x3c74e5659d75e95b, 0x3f984890d9043740), + (0x3c78e0bd083aba81, 0x3fa040ac0224fd90), + (0x3c345cc1cf959b1b, 0x3fa465509d383eb0), + (0xbc8eb6980ce14da7, 0x3fa89246d053d180), + (0x3c77324137d6c342, 0x3facc79f4f5613a0), + (0xbc45272ff30eed1b, 0x3fb082b577d34ed8), + (0xbc81280f19dace1c, 0x3fb2a5dd543ccc50), + (0xbc8d550af31c8ec3, 0x3fb4cd4fc989cd68), + (0x3c87923b72aa582d, 0x3fb6f91575870690), + (0xbc776c2e732457f1, 0x3fb92937074e0cd8), + (0x3c881f5c92a5200f, 0x3fbb5dbd3f681220), + (0x3c8e8ac7a4d3206c, 0x3fbd96b0eff0e790), + (0xbc712db6f4bbe33b, 0x3fbfd41afcba45e8), + (0xbc58c4a5df1ec7e5, 0x3fc10b022db7ae68), + (0xbc6bd4b1c37ea8a2, 0x3fc22e3b09dc54d8), + (0x3c85aeb9860044d0, 0x3fc353bc9fb00b20), + (0xbc64c26602c63fda, 0x3fc47b8b853aafec), + (0xbc87f644c1f9d314, 0x3fc5a5ac59b963cc), + (0x3c8f5aa8ec61fc2d, 0x3fc6d223c5b10638), + (0x3c27ab912c69ffeb, 0x3fc800f67b00d7b8), + (0xbc5b3564bc0ec9cd, 0x3fc9322934f54148), + (0x3c86a7062465be33, 0x3fca65c0b85ac1a8), + (0xbc885718d2ff1bf4, 0x3fcb9bc1d3910094), + (0xbc8045cb0c685e08, 0x3fccd4315e9e0834), + (0xbc16e7fb859d5055, 0x3fce0f143b41a554), + (0x3c851bbdee020603, 0x3fcf4c6f5508ee5c), + (0x3c6e17611afc42c5, 0x3fd04623d0b0f8c8), + (0xbc71c5b2e8735a43, 0x3fd0e7510fd7c564), + (0xbc825fe139c4cffd, 0x3fd189c1ecaeb084), + (0xbc789843c4964554, 0x3fd22d78f0fa061a), +]; + +pub(crate) static EXPM1_T0: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc719083535b085e, 0x3ff02c9a3e778061), + (0x3c8d73e2a475b466, 0x3ff059b0d3158574), + (0x3c6186be4bb28500, 0x3ff0874518759bc8), + (0x3c98a62e4adc610a, 0x3ff0b5586cf9890f), + (0x3c403a1727c57b52, 0x3ff0e3ec32d3d1a2), + (0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xbc932fbf9af1369e, 0x3ff1429aaea92de0), + (0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75), + (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0x3c8dc775814a8494, 0x3ff2063b88628cd6), + (0x3c99b07eb6c70572, 0x3ff2387a6e756238), + (0x3c82bd339940e9da, 0x3ff26b4565e27cdd), + (0x3c8612e8afad1256, 0x3ff29e9df51fdee1), + (0x3c90024754db41d4, 0x3ff2d285a6e4030b), + (0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0x3c932721843659a6, 0x3ff33c08b26416ff), + (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0xbc75e436d661f5e2, 0x3ff3a7db34e59ff7), + (0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0xbc5ef3691c309278, 0x3ff4160a21f72e2a), + (0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0), + (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xbc94b309d25957e4, 0x3ff4f9b2769d2ca7), + (0xbc807abe1db13cac, 0x3ff5342b569d4f82), + (0x3c99bb2c011d93ac, 0x3ff56f4736b527da), + (0x3c96324c054647ac, 0x3ff5ab07dd485429), + (0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148), + (0xbc9383c17e40b496, 0x3ff6247eb03a5585), + (0xbc9bb60987591c34, 0x3ff6623882552225), + (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), + (0xbc6bbe3a683c88aa, 0x3ff6dfb23c651a2f), + (0xbc816e4786887a9a, 0x3ff71f75e8ec5f74), + (0xbc90245957316dd4, 0x3ff75feb564267c9), + (0xbc841577ee049930, 0x3ff7a11473eb0187), + (0x3c705d02ba15797e, 0x3ff7e2f336cf4e62), + (0xbc9d4c1dd41532d8, 0x3ff82589994cce13), + (0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed), + (0x3c96e9f156864b26, 0x3ff8ace5422aa0db), + (0x3c85cc13a2e3976c, 0x3ff8f1ae99157736), + (0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5), + (0xbc9d185b7c1b85d0, 0x3ff97d829fde4e50), + (0x3c7c7c46b071f2be, 0x3ff9c49182a3f090), + (0xbc9359495d1cd532, 0x3ffa0c667b5de565), + (0xbc9d2f6edb8d41e2, 0x3ffa5503b23e255d), + (0x3c90fac90ef7fd32, 0x3ffa9e6b5579fdbf), + (0x3c97a1cd345dcc82, 0x3ffae89f995ad3ad), + (0xbc62805e3084d708, 0x3ffb33a2b84f15fb), + (0xbc75584f7e54ac3a, 0x3ffb7f76f2fb5e47), + (0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2), + (0x3c811065895048de, 0x3ffc199bdd85529c), + (0x3c92884dff483cac, 0x3ffc67f12e57d14b), + (0x3c7503cbd1e949dc, 0x3ffcb720dcef9069), + (0xbc9cbc3743797a9c, 0x3ffd072d4a07897c), + (0x3c82ed02d75b3706, 0x3ffd5818dcfba487), + (0x3c9c2300696db532, 0x3ffda9e603db3285), + (0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f), + (0x3c839e8980a9cc90, 0x3ffe502ee78b3ff6), + (0xbc9e9c23179c2894, 0x3ffea4afa2a490da), + (0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27), + (0x3c99d3e12dd8a18a, 0x3fff50765b6e4540), + (0x3c874853f3a5931e, 0x3fffa7c1819e90d8), +]; + +pub(crate) static EXPM1_T1: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c9ae8e38c59c72a, 0x3ff000b175effdc7), + (0xbc57b5d0d58ea8f4, 0x3ff00162f3904052), + (0x3c94115cb6b16a8e, 0x3ff0021478e11ce6), + (0xbc8d7c96f201bb2e, 0x3ff002c605e2e8cf), + (0x3c984711d4c35ea0, 0x3ff003779a95f959), + (0xbc80484245243778, 0x3ff0042936faa3d8), + (0xbc94b237da2025fa, 0x3ff004dadb113da0), + (0xbc75e00e62d6b30e, 0x3ff0058c86da1c0a), + (0x3c9a1d6cedbb9480, 0x3ff0063e3a559473), + (0xbc94acf197a00142, 0x3ff006eff583fc3d), + (0xbc6eaf2ea42391a6, 0x3ff007a1b865a8ca), + (0x3c7da93f90835f76, 0x3ff0085382faef83), + (0xbc86a79084ab093c, 0x3ff00905554425d4), + (0x3c986364f8fbe8f8, 0x3ff009b72f41a12b), + (0xbc882e8e14e3110e, 0x3ff00a6910f3b6fd), + (0xbc84f6b2a7609f72, 0x3ff00b1afa5abcbf), + (0xbc7e1a258ea8f71a, 0x3ff00bcceb7707ec), + (0x3c74362ca5bc26f2, 0x3ff00c7ee448ee02), + (0x3c9095a56c919d02, 0x3ff00d30e4d0c483), + (0xbc6406ac4e81a646, 0x3ff00de2ed0ee0f5), + (0x3c9b5a6902767e08, 0x3ff00e94fd0398e0), + (0xbc991b2060859320, 0x3ff00f4714af41d3), + (0x3c8427068ab22306, 0x3ff00ff93412315c), + (0x3c9c1d0660524e08, 0x3ff010ab5b2cbd11), + (0xbc9e7bdfb3204be8, 0x3ff0115d89ff3a8b), + (0x3c8843aa8b9cbbc6, 0x3ff0120fc089ff63), + (0xbc734104ee7edae8, 0x3ff012c1fecd613b), + (0xbc72b6aeb6176892, 0x3ff0137444c9b5b5), + (0x3c7a8cd33b8a1bb2, 0x3ff01426927f5278), + (0x3c72edc08e5da99a, 0x3ff014d8e7ee8d2f), + (0x3c857ba2dc7e0c72, 0x3ff0158b4517bb88), + (0x3c9b61299ab8cdb8, 0x3ff0163da9fb3335), + (0xbc990565902c5f44, 0x3ff016f0169949ed), + (0x3c870fc41c5c2d54, 0x3ff017a28af25567), + (0x3c94b9a6e145d76c, 0x3ff018550706ab62), + (0xbc7008eff5142bfa, 0x3ff019078ad6a19f), + (0xbc977669f033c7de, 0x3ff019ba16628de2), + (0xbc909bb78eeead0a, 0x3ff01a6ca9aac5f3), + (0x3c9371231477ece6, 0x3ff01b1f44af9f9e), + (0x3c75e7626621eb5a, 0x3ff01bd1e77170b4), + (0xbc9bc72b100828a4, 0x3ff01c8491f08f08), + (0xbc6ce39cbbab8bbe, 0x3ff01d37442d5070), + (0x3c816996709da2e2, 0x3ff01de9fe280ac8), + (0xbc8c11f5239bf536, 0x3ff01e9cbfe113ef), + (0x3c8e1d4eb5edc6b4, 0x3ff01f4f8958c1c6), + (0xbc9afb99946ee3f0, 0x3ff020025a8f6a35), + (0xbc98f06d8a148a32, 0x3ff020b533856324), + (0xbc82bf310fc54eb6, 0x3ff02168143b0281), + (0xbc9c95a035eb4176, 0x3ff0221afcb09e3e), + (0xbc9491793e46834c, 0x3ff022cdece68c4f), + (0xbc73e8d0d9c49090, 0x3ff02380e4dd22ad), + (0xbc9314aa16278aa4, 0x3ff02433e494b755), + (0x3c848daf888e9650, 0x3ff024e6ec0da046), + (0x3c856dc8046821f4, 0x3ff02599fb483385), + (0x3c945b42356b9d46, 0x3ff0264d1244c719), + (0xbc7082ef51b61d7e, 0x3ff027003103b10e), + (0x3c72106ed0920a34, 0x3ff027b357854772), + (0xbc9fd4cf26ea5d0e, 0x3ff0286685c9e059), + (0xbc909f8775e78084, 0x3ff02919bbd1d1d8), + (0x3c564cbba902ca28, 0x3ff029ccf99d720a), + (0x3c94383ef231d206, 0x3ff02a803f2d170d), + (0x3c94a47a505b3a46, 0x3ff02b338c811703), + (0x3c9e471202234680, 0x3ff02be6e199c811), +]; + +static EXPM1_DD1: [(u64, u64); 11] = [ + (0x3c65555555555554, 0x3fc5555555555555), + (0x3c45555555555123, 0x3fa5555555555555), + (0x3c01111111118167, 0x3f81111111111111), + (0xbbef49f49e220cea, 0x3f56c16c16c16c17), + (0x3b6a019eff6f919c, 0x3f2a01a01a01a01a), + (0x3b39fcff48a75b41, 0x3efa01a01a01a01a), + (0xbb6c14f73758cd7f, 0x3ec71de3a556c734), + (0x3b3dfce97931018f, 0x3e927e4fb7789f5c), + (0x3afc513da9e4c9c5, 0x3e5ae64567f544e3), + (0x3acca00af84f2b60, 0x3e21eed8eff8d831), + (0x3a8f27ac6000898f, 0x3de6124613a86e8f), +]; + +static EXPM1_DD2: [(u64, u64); 7] = [ + (0x3ff0000000000000, 0x0000000000000000), + (0x3fe0000000000000, 0x39c712f72ecec2cf), + (0x3fc5555555555555, 0x3c65555555554d07), + (0x3fa5555555555555, 0x3c455194d28275da), + (0x3f81111111111111, 0x3c012faa0e1c0f7b), + (0x3f56c16c16da6973, 0xbbf4ba45ab25d2a3), + (0x3f2a01a019eb7f31, 0xbbc9091d845ecd36), +]; + +#[inline] +pub(crate) fn opoly_dd_generic( + x: DoubleDouble, + poly: [(u64, u64); N], +) -> DoubleDouble { + let zch = poly.last().unwrap(); + let p0 = DoubleDouble::from_exact_add(f64::from_bits(zch.0), x.lo); + let ach = p0.hi; + let acl = f64::from_bits(zch.1) + p0.lo; + let mut ch = DoubleDouble::new(acl, ach); + + for zch in poly.iter().rev().skip(1) { + ch = DoubleDouble::quick_mult_f64(ch, x.hi); + let z0 = DoubleDouble::from_bit_pair(*zch); + ch = DoubleDouble::add(z0, ch); + } + + ch +} + +#[cold] +fn as_expm1_accurate(x: f64) -> f64 { + let mut ix; + if x.abs() < 0.25 { + const CL: [u64; 6] = [ + 0x3da93974a8ca5354, + 0x3d6ae7f3e71e4908, + 0x3d2ae7f357341648, + 0x3ce952c7f96664cb, + 0x3ca686f8ce633aae, + 0x3c62f49b2fbfb5b6, + ]; + + let fl0 = f_fmla(x, f64::from_bits(CL[5]), f64::from_bits(CL[4])); + let fl1 = f_fmla(x, fl0, f64::from_bits(CL[3])); + let fl2 = f_fmla(x, fl1, f64::from_bits(CL[2])); + let fl3 = f_fmla(x, fl2, f64::from_bits(CL[1])); + + let fl = x * f_fmla(x, fl3, f64::from_bits(CL[0])); + let mut f = opoly_dd_generic(DoubleDouble::new(fl, x), EXPM1_DD1); + f = DoubleDouble::quick_mult_f64(f, x); + f = DoubleDouble::quick_mult_f64(f, x); + f = DoubleDouble::quick_mult_f64(f, x); + let hx = 0.5 * x; + let dx2dd = DoubleDouble::from_exact_mult(x, hx); + f = DoubleDouble::add(dx2dd, f); + let v0 = DoubleDouble::from_exact_add(x, f.hi); + let v1 = DoubleDouble::from_exact_add(v0.lo, f.lo); + let v2 = DoubleDouble::from_exact_add(v0.hi, v1.hi); + let mut v3 = DoubleDouble::from_exact_add(v2.lo, v1.lo); + ix = v3.hi.to_bits(); + if (ix & 0x000fffffffffffff) == 0 { + let v = v3.lo.to_bits(); + let d: i64 = ((((ix as i64) >> 63) ^ ((v as i64) >> 63)) as u64) + .wrapping_shl(1) + .wrapping_add(1) as i64; + ix = ix.wrapping_add(d as u64); + v3.hi = f64::from_bits(ix); + } + v3.hi + v2.hi + } else { + const S: f64 = f64::from_bits(0x40b71547652b82fe); + let t = (x * S).cpu_round_ties_even(); + let jt: i64 = t as i64; + let i0 = (jt >> 6) & 0x3f; + let i1 = jt & 0x3f; + let ie = jt >> 12; + let t0 = DoubleDouble::from_bit_pair(EXPM1_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXPM1_T1[i1 as usize]); + + let bt = DoubleDouble::quick_mult(t0, t1); + + const L2H: f64 = f64::from_bits(0x3f262e42ff000000); + const L2L: f64 = f64::from_bits(0x3d0718432a1b0e26); + const L2LL: f64 = f64::from_bits(0x3999ff0342542fc3); + + let dx = f_fmla(-L2H, t, x); + let dxl = L2L * t; + let dxll = f_fmla(L2LL, t, dd_fmla(L2L, t, -dxl)); + let dxh = dx + dxl; + let dxl = (dx - dxh) + dxl + dxll; + let mut f = poly_dekker_generic(DoubleDouble::new(dxl, dxh), EXPM1_DD2); + f = DoubleDouble::quick_mult(DoubleDouble::new(dxl, dxh), f); + f = DoubleDouble::quick_mult(f, bt); + f = DoubleDouble::add(bt, f); + let off: u64 = (2048i64 + 1023i64).wrapping_sub(ie).wrapping_shl(52) as u64; + let e: f64; + if ie < 53 { + let fhz = DoubleDouble::from_exact_add(f64::from_bits(off), f.hi); + f.hi = fhz.hi; + e = fhz.lo; + } else if ie < 104 { + let fhz = DoubleDouble::from_exact_add(f.hi, f64::from_bits(off)); + f.hi = fhz.hi; + e = fhz.lo; + } else { + e = 0.; + } + f.lo += e; + let dst = DoubleDouble::from_exact_add(f.hi, f.lo); + fast_ldexp(dst.hi, ie as i32) + } +} + +#[inline(always)] +fn expm1_gen(x: f64, backend: B) -> f64 { + let ix = x.to_bits(); + let aix: u64 = ix & 0x7fff_ffff_ffff_ffff; + if aix < 0x3fd0000000000000u64 { + if aix < 0x3ca0000000000000u64 { + if aix == 0 { + return x; + } + return backend.dyad_fma(f64::from_bits(0x3c90000000000000), x.abs(), x); + } + let sx = f64::from_bits(0x4060000000000000) * x; + let fx = backend.round_ties_even(sx); + let z = sx - fx; + let z2 = z * z; + let i: i64 = unsafe { + fx.to_int_unchecked::() // fx is already integer, this is just a conversion + }; + let t = DoubleDouble::from_bit_pair(TZ[i.wrapping_add(32) as usize]); + const C: [u64; 6] = [ + 0x3f80000000000000, + 0x3f00000000000000, + 0x3e755555555551ad, + 0x3de555555555599c, + 0x3d511111ad1ad69d, + 0x3cb6c16c168b1fb5, + ]; + let fh = z * f64::from_bits(C[0]); + + let fl0 = backend.fma(z, f64::from_bits(C[5]), f64::from_bits(C[4])); + let fl1 = backend.fma(z, f64::from_bits(C[2]), f64::from_bits(C[1])); + + let fw0 = backend.fma(z, fl0, f64::from_bits(C[3])); + + let fl = z2 * backend.fma(z2, fw0, fl1); + let mut f = DoubleDouble::new(fl, fh); + let e0 = f64::from_bits(0x3bea000000000000); + let eps = z2 * e0 + f64::from_bits(0x3970000000000000); + let mut r = DoubleDouble::from_exact_add(t.hi, f.hi); + r.lo += t.lo + f.lo; + f = backend.quick_mult(t, f); + f = DoubleDouble::add(r, f); + let ub = f.hi + (f.lo + eps); + let lb = f.hi + (f.lo - eps); + if ub != lb { + return as_expm1_accurate(x); + } + lb + } else { + if aix >= 0x40862e42fefa39f0u64 { + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + if aix == 0x7ff0000000000000u64 { + return if (ix >> 63) != 0 { -1.0 } else { x }; + } + if (ix >> 63) == 0 { + const Z: f64 = f64::from_bits(0x7fe0000000000000); + return black_box(Z) * black_box(Z); + } + } + if ix >= 0xc0425e4f7b2737fau64 { + if ix >= 0xc042b708872320e2u64 { + return black_box(-1.0) + black_box(f64::from_bits(0x3c80000000000000)); + } + return (f64::from_bits(0x40425e4f7b2737fa) + x + f64::from_bits(0x3cc8486612173c69)) + * f64::from_bits(0x3c971547652b82fe) + - f64::from_bits(0x3fefffffffffffff); + } + + const S: f64 = f64::from_bits(0x40b71547652b82fe); + let t = backend.round_ties_even(x * S); + let jt: i64 = unsafe { + t.to_int_unchecked::() // t is already integer, this is just a conversion + }; + let i0 = (jt >> 6) & 0x3f; + let i1 = jt & 0x3f; + let ie = jt >> 12; + let t0 = DoubleDouble::from_bit_pair(EXPM1_T0[i0 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXPM1_T1[i1 as usize]); + + let bt = backend.quick_mult(t0, t1); + + const L2H: f64 = f64::from_bits(0x3f262e42ff000000); + const L2L: f64 = f64::from_bits(0x3d0718432a1b0e26); + let dx = backend.dd_fma(L2L, t, backend.fma(-L2H, t, x)); + let dx2 = dx * dx; + + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc55555557e54ff, + 0x3fa55555553a12f4, + ]; + + let p0 = backend.fma(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let p1 = backend.fma(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let p = backend.fma(dx2, p0, p1); + let mut fh = bt.hi; + let tx = bt.hi * dx; + let mut fl = backend.fma(tx, p, bt.lo); + let eps = f64::from_bits(0x3c0833beace2b6fe) * bt.hi; + + let off: u64 = ((2048i64 + 1023i64).wrapping_sub(ie) as u64).wrapping_shl(52); + let e: f64; + if ie < 53 { + let flz = DoubleDouble::from_exact_add(f64::from_bits(off), fh); + e = flz.lo; + fh = flz.hi; + } else if ie < 75 { + let flz = DoubleDouble::from_exact_add(fh, f64::from_bits(off)); + e = flz.lo; + fh = flz.hi; + } else { + e = 0.; + } + fl += e; + let ub = fh + (fl + eps); + let lb = fh + (fl - eps); + if ub != lb { + return as_expm1_accurate(x); + } + fast_ldexp(lb, ie as i32) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn expm1_fma_impl(x: f64) -> f64 { + use crate::exponents::expf::FmaBackend; + expm1_gen(x, FmaBackend {}) +} + +/// Computes e^x - 1 +/// +/// Max found ULP 0.5 +pub fn f_expm1(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + expm1_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + expm1_fma_impl + } else { + fn def_expm1(x: f64) -> f64 { + expm1_gen(x, GenericExpfBackend {}) + } + def_expm1 + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_expm1() { + assert_eq!(f_expm1(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028321017343872864), + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028321017343872864 ); + assert_eq!(f_expm1(36.52188110363568), 7265264535836525.); + assert_eq!(f_expm1(2.), 6.38905609893065); + assert_eq!(f_expm1(0.4321321), 0.5405386068701713); + assert_eq!(f_expm1(-0.0000004321321), -4.321320066309375e-7); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expm1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/expm1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/expm1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::expf::{ExpfBackend, GenericExpfBackend}; + +#[inline(always)] +fn expm1f_gen(x: f32, backend: B) -> f32 { + let x_u: u32 = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + + // When |x| > 25*log(2), or nan + if x_abs >= 0x418a_a123u32 { + // x < log(2^-25) + if x.is_sign_negative() { + // exp(-Inf) = 0 + if x.is_infinite() { + return -1.0; + } + // exp(nan) = nan + if x.is_nan() { + return x; + } + return -1.0; + } else { + // x >= 89 or nan + if x_u >= 0x42b2_0000 { + return x + f32::INFINITY; + } + } + } + + // |x| < 2^-4 + if x_abs < 0x3d80_0000u32 { + // |x| < 2^-25 + if x_abs < 0x3300_0000u32 { + // x = -0.0f + if x_u == 0x8000_0000u32 { + return x; + } + // When |x| < 2^-25, the relative error of the approximation e^x - 1 ~ x + // is: + // |(e^x - 1) - x| / |e^x - 1| < |x^2| / |x| + // = |x| + // < 2^-25 + // < epsilon(1)/2. + // To simplify the rounding decision and make it more efficient, we use + // fma(x, x, x) ~ x + x^2 instead. + // Note: to use the formula x + x^2 to decide the correct rounding, we + // do need fma(x, x, x) to prevent underflow caused by x*x when |x| < + // 2^-76. For targets without FMA instructions, we simply use double for + // intermediate results as it is more efficient than using an emulated + // version of FMA. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + return backend.fmaf(x, x, x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let xd = x as f64; + return backend.fma(xd, xd, xd) as f32; + } + } + + const C: [u64; 7] = [ + 0x3fe0000000000000, + 0x3fc55555555557dd, + 0x3fa55555555552fa, + 0x3f8111110fcd58b7, + 0x3f56c16c1717660b, + 0x3f2a0241f0006d62, + 0x3efa01e3f8d3c060, + ]; + + // 2^-25 <= |x| < 2^-4 + let xd = x as f64; + let xsq = xd * xd; + // Degree-8 minimax polynomial generated by Sollya with: + // > display = hexadecimal; + // > P = fpminimax((expm1(x) - x)/x^2, 6, [|D...|], [-2^-4, 2^-4]); + + return backend.fma( + backend.polyeval7( + xd, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + ), + xsq, + xd, + ) as f32; + } + + // For -104 < x < 89, to compute expm1(x), we perform the following range + // reduction: find hi, mid, lo such that: + // x = hi + mid + lo, in which + // hi is an integer, + // mid * 2^7 is an integer + // -2^(-8) <= lo < 2^-8. + // In particular, + // hi + mid = round(x * 2^7) * 2^(-7). + // Then, + // expm1(x) = expm1(hi + mid + lo) = exp(hi) * exp(mid) * exp(lo) - 1. + // We store exp(hi) and exp(mid) in the lookup tables EXP_M1 and EXP_M2 + // respectively. exp(lo) is computed using a degree-4 minimax polynomial + // generated by Sollya. + + // x_hi = (hi + mid) * 2^7 = round(x * 2^7). + let kf = backend.roundf(x * 128.); + // Subtract (hi + mid) from x to get lo. + let xd = backend.fmaf(kf, -0.0078125 /* - 1/128 */, x) as f64; + let mut x_hi = unsafe { kf.to_int_unchecked::() }; // it's already not indeterminate. + x_hi += 104 << 7; + // hi = x_hi >> 7 + let exp_hi = f64::from_bits(crate::exponents::expf::EXP_M1[(x_hi >> 7) as usize]); + // mid * 2^7 = x_hi & 0x0000'007fU; + let exp_mid = f64::from_bits(crate::exponents::expf::EXP_M2[(x_hi & 0x7f) as usize]); + // Degree-4 minimax polynomial generated by Sollya with the following + // commands: + // d = [-2^-8, 2^-8]; + // f_exp = expm1(x)/x; + // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); + let p = backend.polyeval5( + xd, + 1., + f64::from_bits(0x3feffffffffff777), + f64::from_bits(0x3fe000000000071c), + f64::from_bits(0x3fc555566668e5e7), + f64::from_bits(0x3fa55555555ef243), + ); + backend.fma(p * exp_hi, exp_mid, -1.) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn expm1f_fma_impl(x: f32) -> f32 { + use crate::exponents::expf::FmaBackend; + expm1f_gen(x, FmaBackend {}) +} + +/// Computes e^x - 1 +/// +/// Max ULP 0.5 +#[inline] +pub fn f_expm1f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + expm1f_gen(x, GenericExpfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + expm1f_fma_impl + } else { + fn def_expm1f(x: f32) -> f32 { + expm1f_gen(x, GenericExpfBackend {}) + } + def_expm1f + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use crate::f_expm1f; + + #[test] + fn test_expm1f() { + assert_eq!(f_expm1f(-3.0923562e-5), -3.0923085e-5); + assert_eq!(f_expm1f(2.213121), 8.144211); + assert_eq!(f_expm1f(-3.213121), -0.9597691); + assert_eq!(f_expm1f(-2.35099e-38), -2.35099e-38); + assert_eq!( + f_expm1f(0.00000000000000000000000000000000000004355616), + 0.00000000000000000000000000000000000004355616 + ); + assert_eq!(f_expm1f(25.12315), 81441420000.0); + assert_eq!(f_expm1f(12.986543), 436498.6); + assert_eq!(f_expm1f(-12.986543), -0.99999774); + assert_eq!(f_expm1f(-25.12315), -1.0); + assert_eq!(f_expm1f(f32::INFINITY), f32::INFINITY); + assert_eq!(f_expm1f(f32::NEG_INFINITY), -1.); + assert!(f_expm1f(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/logistic.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logistic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/logistic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logistic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0_exp; +use crate::double_double::DoubleDouble; + +/// Logistic function +/// +/// Computes 1/(1+exp(-x)) +pub fn f_logistic(x: f64) -> f64 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffff_ffff_ffffu64; + if x_abs <= 0x3c90000000000000u64 { + // |x| <= 5.55112e-17 + return 1. / (2. + -x); + } + if x_abs >= 0x4043800000000000u64 { + // |x| >= 39.0 + if x_abs > 0x7ff0000000000000u64 { + // x == NaN + return x + x; + } + if x_abs == 0x7ff0000000000000u64 { + // |x| = inf + return if (x.to_bits() >> 63) != 0 { + 0.0 // x = -inf + } else { + 1.0 // x = inf + }; + } + if (x.to_bits() >> 63) == 0 { + // x >= 39.0 + return 1.0; + } + if x_abs >= 0x40874910d52d3052u64 { + // x <= -745.133 + return 1.0; + } + } + // e^x/(1+e^x) + let num = i0_exp(x); + let den = DoubleDouble::full_add_f64(num, 1.0); + let v = DoubleDouble::div(num, den); + v.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_logistic() { + assert_eq!(f_logistic(6.), 0.9975273768433652); + assert_eq!(f_logistic(39.), 1.0); + assert_eq!(f_logistic(35.), 0.9999999999999993); + assert_eq!(f_logistic(30.), 0.9999999999999064); + assert_eq!(f_logistic(40.), 1.); + assert_eq!(f_logistic(-89.), 2.2273635617957438e-39); + assert_eq!(f_logistic(-104.), 6.813556821545298e-46); + assert_eq!(f_logistic(-103.), 1.8521167695179754e-45); + assert_eq!(f_logistic(-88.9), 2.4616174324780325e-39); + assert_eq!(f_logistic(-88.), 6.054601895401186e-39); + assert_eq!(f_logistic(-80.), 1.8048513878454153e-35); + assert_eq!(f_logistic(-60.), 8.75651076269652e-27); + assert_eq!(f_logistic(-40.), 4.248354255291589e-18); + assert_eq!(f_logistic(-20.), 2.0611536181902037e-9); + assert_eq!(f_logistic(-1.591388e29), 1.0); + assert_eq!(f_logistic(-3.), 0.04742587317756678); + assert_eq!(f_logistic(3.), 0.9525741268224333); + assert_eq!(f_logistic(20.), 0.9999999979388464); + assert_eq!(f_logistic(55.), 1.); + assert_eq!(f_logistic(-104.), 6.813556821545298e-46); + assert_eq!(f_logistic(-90.), 8.194012623990515e-40); + assert_eq!(f_logistic(0.00000000000524323), 0.5000000000013108); + assert_eq!(f_logistic(0.00000000524323), 0.5000000013108075); + assert_eq!(f_logistic(0.02), 0.5049998333399998); + assert_eq!(f_logistic(-0.02), 0.4950001666600003); + assert_eq!(f_logistic(90.), 1.); + assert_eq!(f_logistic(105.), 1.); + assert_eq!(f_logistic(f64::INFINITY), 1.0); + assert_eq!(f_logistic(f64::NEG_INFINITY), 0.); + assert!(f_logistic(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/logisticf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logisticf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/logisticf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/logisticf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::core_expf; +use crate::polyeval::f_polyeval6; + +/// Logistic function +/// +/// Computes 1/(1+exp(-x)) +pub fn f_logisticf(x: f32) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffffu32; + if x_abs >= 0x42b2_0000u32 || x_abs <= 0x3d00_0000u32 { + // |x| >= 89 or |x| <= 2^-5 + let exp = ((x_u >> 23) & 0xFF) as i32; + // |x| < 2^-25 + if exp <= 101i32 { + return (1. / (2. + -x as f64)) as f32; + } + + if x_abs <= 0x3400_0000u32 { + // |x| < f32::EPSILON + // logistic(x) ~ 0.5 + x / 4 + O(x^3) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(0.25, x, 0.5); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::f_fmla; + return f_fmla(0.25, x as f64, 0.5) as f32; + } + } + + // When x < log(2^-150) or nan + if x_u >= 0xc2cf_f1b5u32 { + // logistic(-Inf) = 0 + if x.is_infinite() { + return 0.0; + } + // logistic(nan) = nan + if x.is_nan() { + return x; + } + return if x.is_sign_positive() { + f32::INFINITY + } else { + 0. + }; + } + if x.is_sign_positive() && x_u >= 0x42d0_0000u32 { + // x >= 104 + if x.is_nan() { + return f32::NAN; + } + return 1.; + } + if x.is_sign_negative() && x_u >= 0xc2cb_fe00u32 { + // x <= -101.99609 + return 0.; + } + + if x_abs <= 0x3d00_0000u32 { + // |x| <= 2^-5 + + // Polynomial for logistics function generated by Sollya: + // d = [-2^-5, 2^-5]; + // f_logistic = 1/(1+exp(-x)); + // Q = fpminimax(f_logistic, 5, [|D...|], d); + + let dx = x as f64; + let p = f_polyeval6( + dx, + f64::from_bits(0x3fe0000000000000), + f64::from_bits(0x3fcffffffffffcf5), + f64::from_bits(0x3cfbce9c01a4987c), + f64::from_bits(0xbf955555524c34a4), + f64::from_bits(0xbda6322b5fac64d4), + f64::from_bits(0x3f61104f3a0dedc3), + ); + return p as f32; + } + } + + let v_exp = core_expf(-x); + let logistic = 1. / (1. + v_exp); + logistic as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_logisticf() { + assert_eq!(f_logisticf(-89.), 2.227364e-39); + assert_eq!(f_logisticf(-104.), 0.); + assert_eq!(f_logisticf(-103.), 0.); + assert_eq!(f_logisticf(-88.9), 2.461613e-39); + assert_eq!(f_logisticf(-88.), 6.054601e-39); + assert_eq!(f_logisticf(-80.), 1.8048513e-35); + assert_eq!(f_logisticf(-60.), 8.756511e-27); + assert_eq!(f_logisticf(-40.), 4.248354e-18); + assert_eq!(f_logisticf(-20.), 2.0611537e-9); + assert_eq!(f_logisticf(-1.591388e29), 0.); + assert_eq!(f_logisticf(-3.), 0.047425874); + assert_eq!(f_logisticf(3.), 0.95257413); + assert_eq!(f_logisticf(20.), 1.); + assert_eq!(f_logisticf(55.), 1.); + assert_eq!(f_logisticf(-104.), 0.); + assert_eq!(f_logisticf(-90.), 8.19401e-40); + assert_eq!(f_logisticf(0.00000000000524323), 0.5); + assert_eq!(f_logisticf(0.00000000524323), 0.5); + assert_eq!(f_logisticf(0.02), 0.5049998); + assert_eq!(f_logisticf(-0.02), 0.49500015); + assert_eq!(f_logisticf(90.), 1.); + assert_eq!(f_logisticf(105.), 1.); + assert_eq!(f_logisticf(150.), 1.); + assert_eq!(f_logisticf(f32::INFINITY), 1.0); + assert_eq!(f_logisticf(f32::NEG_INFINITY), 0.); + assert!(f_logisticf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/exponents/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/exponents/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![deny(unreachable_pub)] +mod auxiliary; +mod exp; +mod exp10; +mod exp10f; +mod exp10m1; +mod exp10m1f; +mod exp2; +mod exp2f; +mod exp2m1; +mod exp2m1f; +mod exp_f128; +mod expf; +mod expm1; +mod expm1f; +mod logistic; +mod logisticf; + +pub(crate) use auxiliary::{fast_ldexp, ldexp}; +pub(crate) use exp::{EXP_REDUCE_T0, EXP_REDUCE_T1}; +pub use exp::{exp, f_exp}; +pub(crate) use exp_f128::rational128_exp; +pub use exp2::f_exp2; +pub(crate) use exp2f::dirty_exp2f; +pub use exp2f::f_exp2f; +pub(crate) use exp2m1::exp2m1_accurate_tiny; +pub use exp2m1::f_exp2m1; +pub use exp2m1f::f_exp2m1f; +pub use exp10::f_exp10; +pub use exp10f::f_exp10f; +pub use exp10m1::f_exp10m1; +pub use exp10m1f::f_exp10m1f; +pub(crate) use expf::GenericExpfBackend; +pub(crate) use expf::{core_expdf, core_expf}; +pub use expf::{expf, f_expf}; +pub use expm1::f_expm1; +pub(crate) use expm1::{EXPM1_T0, EXPM1_T1}; +pub use expm1f::f_expm1f; +pub use logistic::f_logistic; +pub use logisticf::f_logisticf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/beta.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/beta.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/beta.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/beta.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::f_exp; +use crate::gamma::lgamma::lgamma_core; + +/// Computes beta function +pub fn f_beta(a: f64, b: f64) -> f64 { + let ax = a.to_bits(); + let bx = b.to_bits(); + + if ax >= 0x7ffu64 << 52 || ax == 0 || bx >= 0x7ffu64 << 52 || bx == 0 { + if (ax >> 63) != 0 || (bx >> 63) != 0 { + // |a| < 0 or |b| < 0 + return f64::NAN; + } + if ax.wrapping_shl(1) == 0 || bx.wrapping_shl(1) == 0 { + // |a| == 0 || |b| == 0 + if ax.wrapping_shl(1) != 0 || bx.wrapping_shl(1) != 0 { + return f64::INFINITY; + } + return f64::NAN; + } + if a.is_infinite() || b.is_infinite() { + // |a| == inf or |b| == inf + return 0.; + } + return a + f64::NAN; // nan + } + + let mut sign = 1i32; + let (mut y, sgngamf) = lgamma_core(DoubleDouble::from_full_exact_add(a, b).to_f64()); + sign *= sgngamf; /* keep track of the sign */ + let (y1, sgngamf) = lgamma_core(b); + y = DoubleDouble::quick_dd_sub(y1, y); + sign *= sgngamf; + let (y1, sgngamf) = lgamma_core(a); + y = DoubleDouble::quick_dd_add(y1, y); + sign *= sgngamf; + f_exp(y.to_f64()) * (sign as f64) +} + +#[cfg(test)] +mod tests { + use crate::f_beta; + + #[test] + fn test_beta() { + assert!(f_beta(-5., 15.).is_nan()); + assert!(f_beta(5., -15.).is_nan()); + assert!(f_beta(f64::NAN, 15.).is_nan()); + assert!(f_beta(15., f64::NAN).is_nan()); + assert_eq!(f_beta(f64::INFINITY, 0.), f64::INFINITY); + assert_eq!(f_beta(f64::INFINITY, 1.), 0.); + assert_eq!(f_beta(1., f64::INFINITY), 0.); + assert_eq!(f_beta(5., 3.), 0.009523809523809526); + assert_eq!(f_beta(3., 5.), 0.009523809523809526); + assert_eq!(f_beta(12., 23.), 1.5196994506201402e-10); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::exponents::core_expdf; +use crate::gamma::lgamma_rf::lgamma_coref; + +/// Computes beta function +pub fn f_betaf(a: f32, b: f32) -> f32 { + let ax = a.to_bits(); + let bx = b.to_bits(); + + if ax >= 0xffu32 << 23 || ax == 0 || bx >= 0xffu32 << 23 || bx == 0 { + if (ax >> 31) != 0 || (bx >> 31) != 0 { + // |a| < 0 or |b| < 0 + return f32::NAN; + } + if ax.wrapping_shl(1) == 0 || bx.wrapping_shl(1) == 0 { + // |a| == 0 || |b| == 0 + if ax.wrapping_shl(1) != 0 || bx.wrapping_shl(1) != 0 { + return f32::INFINITY; + } + return f32::NAN; + } + if a.is_infinite() || b.is_infinite() { + // |a| == inf or |b| == inf + return 0.; + } + return a + f32::NAN; // nan + } + + let mut sign = 1i32; + let (mut y, sgngamf) = lgamma_coref(a + b); + sign *= sgngamf; /* keep track of the sign */ + let (y1, sgngamf) = lgamma_coref(b); + y = y1 - y; + sign *= sgngamf; + let (y1, sgngamf) = lgamma_coref(a); + y += y1; + sign *= sgngamf; + if y <= -104. { + return 0.; + } + if y >= 89. { + // x > 89 + return f32::INFINITY; + } + (core_expdf(y) * (sign as f64)) as f32 +} + +#[cfg(test)] +mod tests { + use crate::f_betaf; + + #[test] + fn test_betaf() { + assert_eq!(f_betaf(f32::INFINITY, 1.), 0.); + assert_eq!(f_betaf(f32::INFINITY, 0.), f32::INFINITY); + assert!(f_betaf(0., 0.).is_nan()); + assert_eq!(f_betaf(0., f32::INFINITY), f32::INFINITY); + assert!(f_betaf(-5., 15.).is_nan()); + assert!(f_betaf(5., -15.).is_nan()); + assert!(f_betaf(f32::NAN, 15.).is_nan()); + assert!(f_betaf(15., f32::NAN).is_nan()); + assert_eq!(f_betaf(f32::INFINITY, 1.), 0.); + assert_eq!(f_betaf(1., f32::INFINITY), 0.); + assert_eq!(f_betaf(5., 3.), 0.00952381); + assert_eq!(f_betaf(3., 5.), 0.00952381); + assert_eq!(f_betaf(12., 23.), 1.5196995e-10); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betainc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betainc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betainc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betainc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0_exp; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::f_pow; +use crate::gamma::lnbeta::lnbeta_core; +use crate::logs::{fast_log_dd, log1p_fast_dd}; + +/// Regularized incomplete beta +pub fn f_betainc_reg(a: f64, b: f64, x: f64) -> f64 { + let aa = a.to_bits(); + let ab = b.to_bits(); + let ax = x.to_bits(); + + if aa >= 0x7ffu64 << 52 + || aa == 0 + || ab >= 0x7ffu64 << 52 + || ab == 0 + || ax == 0 + || ax >= 0x3ff0000000000000 + { + if (aa >> 63) != 0 || (ab >> 63) != 0 || (ax >> 63) != 0 { + // |a| < 0 or |b| < 0 + return f64::NAN; + } + if ax >= 0x3ff0000000000000 { + // |x| > 1 + if ax == 0x3ff0000000000000 { + // x == 1 + return 1.; + } + return f64::NAN; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ab.wrapping_shl(1) == 0 { + // |b| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == inf + return 0.; + } + if b.is_infinite() { + // |b| == inf + return 1.; + } + return a + f64::NAN; // nan + } + + if ab == 0x3ff0000000000000 { + // b == 1 + return f_pow(x, a); + } + + /*The continued fraction converges nicely for x < (a+1)/(a+b+2)*/ + /*Use the fact that beta is symmetrical.*/ + let mut return_inverse = false; + let mut dx = DoubleDouble::new(0., x); + let mut a = a; + let mut b = b; + if x > (a + 1.0) / (a + b + 2.0) { + std::mem::swap(&mut a, &mut b); + dx = DoubleDouble::from_full_exact_sub(1.0, x); + return_inverse = true; + } + /*Find the first part before the continued fraction.*/ + let da = a; + let db = b; + let ln_beta_ab = lnbeta_core(a, b); + let log_dx = fast_log_dd(dx); + let mut log1p_dx = log1p_fast_dd(-dx.hi); + log1p_dx.lo += -dx.lo / dx.hi; + let z1 = DoubleDouble::mul_f64_add(log1p_dx, db, -ln_beta_ab); + let w0 = DoubleDouble::mul_f64_add(log_dx, da, z1); + let front = DoubleDouble::div_dd_f64(i0_exp(w0.to_f64()), da); + + /*Use Lentz's algorithm to evaluate the continued fraction.*/ + let mut f = 1.0; + let mut c = 1.0; + let mut d = 0.0; + + const TINY: f64 = 1.0e-31; + const STOP: f64 = f64::EPSILON; + + for i in 0..200 { + let m = i / 2; + let numerator: f64 = if i == 0 { + 1.0 /*First numerator is 1.0.*/ + } else if i % 2 == 0 { + let m = m as f64; + let c0 = f_fmla(2.0, m, da); + (m * (db - m) * dx.hi) / ((c0 - 1.0) * c0) /*Even term.*/ + } else { + let m = m as f64; + let c0 = f_fmla(2.0, m, da); + -((da + m) * (da + db + m) * dx.hi) / (c0 * (c0 + 1.)) /*Odd term.*/ + }; + + /*Do an iteration of Lentz's algorithm.*/ + d = f_fmla(numerator, d, 1.0); + if d.abs() < TINY { + d = TINY; + } + d = 1.0 / d; + + c = 1.0 + numerator / c; + if c.abs() < TINY { + c = TINY; + } + + let cd = c * d; + f *= cd; + + /*Check for stop.*/ + if (1.0 - cd).abs() < STOP { + let r = DoubleDouble::from_full_exact_sub(f, 1.0); + return if return_inverse { + DoubleDouble::mul_add_f64(-front, r, 1.).to_f64() + } else { + DoubleDouble::quick_mult(front, r).to_f64() + }; + } + } + + let r = DoubleDouble::from_full_exact_sub(f, 1.0); + if return_inverse { + DoubleDouble::mul_add_f64(-front, r, 1.).to_f64() + } else { + DoubleDouble::quick_mult(front, r).to_f64() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_betainc() { + assert_eq!(f_betainc_reg(0.5, 2.5, 0.5), 0.9244131815783875); + assert_eq!(f_betainc_reg(2.5, 1.0, 0.5), 0.1767766952966368811); + assert_eq!(f_betainc_reg(0.5, 0., 1.), 1.); + assert_eq!(f_betainc_reg(5., 1.4324, 0.1312), 8.872581630413704e-5); + assert_eq!(f_betainc_reg(7., 42., 0.4324), 0.9999954480481231); + assert_eq!(f_betainc_reg(5., 2., 1.), 1.); + assert_eq!(f_betainc_reg(5., 2., 0.), 0.); + assert_eq!(f_betainc_reg(5., 2., 0.5), 0.10937500000000006); + assert!(f_betainc_reg(5., 2., -1.).is_nan()); + assert!(f_betainc_reg(5., 2., 1.1).is_nan()); + assert!(f_betainc_reg(5., 2., f64::INFINITY).is_nan()); + assert!(f_betainc_reg(5., 2., f64::NEG_INFINITY).is_nan()); + assert!(f_betainc_reg(5., 2., f64::NAN).is_nan()); + assert!(f_betainc_reg(-5., 2., 0.432).is_nan()); + assert!(f_betainc_reg(5., -2., 0.432).is_nan()); + assert!(f_betainc_reg(5., 2., -0.432).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betaincf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaincf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/betaincf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/betaincf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,187 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::gamma::lnbetaf::lnbetaf_core; +use crate::{f_exp, f_log, f_log1p, f_pow, f_powf}; + +/// Regularized incomplete beta +pub fn f_betainc_regf(a: f32, b: f32, x: f32) -> f32 { + let aa = a.to_bits(); + let ab = b.to_bits(); + let ax = x.to_bits(); + + if aa >= 0xffu32 << 23 + || aa == 0 + || ab >= 0xffu32 << 23 + || ab == 0 + || ax == 0 + || ax >= 0x3f800000 + { + if (aa >> 31) != 0 || (ab >> 31) != 0 || (ax >> 31) != 0 { + // |a| < 0 or |b| < 0 + return f32::NAN; + } + if ax >= 0x3f800000 { + // |x| > 1 + if ax == 0x3f800000 { + // |x| == 1 + return 1.; + } + return f32::NAN; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ab.wrapping_shl(1) == 0 { + // |b| == 0 + return 0.; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == inf + return 0.; + } + if b.is_infinite() { + // |b| == inf + return 1.; + } + return a + f32::NAN; // nan + } + + if aa == 0x3f800000 { + // a == 1 + return (1. - f_pow(1. - x as f64, b as f64)) as f32; + } + + if ab == 0x3f800000 { + // b == 1 + return f_powf(x, a); + } + + /*The continued fraction converges nicely for x < (a+1)/(a+b+2)*/ + /*Use the fact that beta is symmetrical.*/ + let mut return_inverse = false; + let mut dx = x as f64; + let mut a = a; + let mut b = b; + if x > (a + 1.0) / (a + b + 2.0) { + std::mem::swap(&mut a, &mut b); + dx = 1.0 - dx; + return_inverse = true; + } + /*Find the first part before the continued fraction.*/ + let da = a as f64; + let db = b as f64; + let w0 = f_fmla(f_log(dx), da, f_fmla(f_log1p(-dx), db, -lnbetaf_core(a, b))); + let front = f_exp(w0) / da; + + /*Use Lentz's algorithm to evaluate the continued fraction.*/ + let mut f = 1.0; + let mut c = 1.0; + let mut d = 0.0; + + const TINY: f64 = 1.0e-30; + const STOP: f64 = 1.0e-8; + + for i in 0..200 { + let m = i / 2; + let numerator: f64 = if i == 0 { + 1.0 /*First numerator is 1.0.*/ + } else if i % 2 == 0 { + let m = m as f64; + let c0 = f_fmla(2.0, m, da); + (m * (db - m) * dx) / ((c0 - 1.0) * c0) /*Even term.*/ + } else { + let m = m as f64; + let c0 = f_fmla(2.0, m, da); + -((da + m) * (da + db + m) * dx) / (c0 * (c0 + 1.)) /*Odd term.*/ + }; + + /*Do an iteration of Lentz's algorithm.*/ + d = f_fmla(numerator, d, 1.0); + if d.abs() < TINY { + d = TINY; + } + d = 1.0 / d; + + c = 1.0 + numerator / c; + if c.abs() < TINY { + c = TINY; + } + + let cd = c * d; + f *= cd; + + /*Check for stop.*/ + if (1.0 - cd).abs() < STOP { + return if return_inverse { + f_fmla(-front, f - 1.0, 1.) as f32 + } else { + (front * (f - 1.0)) as f32 + }; + } + } + + if return_inverse { + f_fmla(-front, f - 1.0, 1.) as f32 + } else { + (front * (f - 1.0)) as f32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_betaincf() { + assert_eq!(f_betainc_regf(0.5, 2.5, 0.5), 0.9244131815783875); + assert_eq!(f_betainc_regf(2.5, 1.0, 0.5), 0.1767766952966368811); + assert_eq!(f_betainc_regf(0.5, 0.5, 0.5), 0.5); + assert_eq!(f_betainc_regf(54221., 23124., 0.64534), 0.0); + assert_eq!(f_betainc_regf(5., 1.4324, 0.1312), 8.872578e-5); + assert_eq!(f_betainc_regf(7., 42., 0.4324), 0.99999547); + assert_eq!(f_betainc_regf(0.5, 0., 1.), 1.); + assert_eq!(f_betainc_regf(5., 2., 1.), 1.); + assert_eq!(f_betainc_regf(5., 2., 0.), 0.); + assert_eq!(f_betainc_regf(5., 2., 0.5), 0.109375); + assert!(f_betainc_regf(5., 2., -1.).is_nan()); + assert!(f_betainc_regf(5., 2., 1.1).is_nan()); + assert!(f_betainc_regf(5., 2., f32::INFINITY).is_nan()); + assert!(f_betainc_regf(5., 2., f32::NEG_INFINITY).is_nan()); + assert!(f_betainc_regf(5., 2., f32::NAN).is_nan()); + assert!(f_betainc_regf(-5., 2., 0.432).is_nan()); + assert!(f_betainc_regf(5., -2., 0.432).is_nan()); + assert!(f_betainc_regf(5., 2., -0.432).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digamma.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digamma.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,455 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::is_integer; +use crate::double_double::DoubleDouble; +use crate::gamma::digamma_coeffs::digamma_coeefs; +use crate::logs::fast_log_d_to_dd; +use crate::tangent::cotpi_core; + +#[inline] +fn approx_digamma_hard(x: f64) -> DoubleDouble { + if x <= 12. { + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + let (p, q) = digamma_coeefs(x); + + let e0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[1]), + x, + DoubleDouble::from_bit_pair(p[0]), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[3]), + x, + DoubleDouble::from_bit_pair(p[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[5]), + x, + DoubleDouble::from_bit_pair(p[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[7]), + x, + DoubleDouble::from_bit_pair(p[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[9]), + x, + DoubleDouble::from_bit_pair(p[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[11]), + x, + DoubleDouble::from_bit_pair(p[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + let rcp = DoubleDouble::from_quick_recip(x); + + let e0 = DoubleDouble::mul_f64_add_f64( + DoubleDouble::from_bit_pair(q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[3]), + x, + DoubleDouble::from_bit_pair(q[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[5]), + x, + DoubleDouble::from_bit_pair(q[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[7]), + x, + DoubleDouble::from_bit_pair(q[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[9]), + x, + DoubleDouble::from_bit_pair(q[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[11]), + x, + DoubleDouble::from_bit_pair(q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let q = DoubleDouble::div(p_num, p_den); + let r = DoubleDouble::quick_dd_sub(q, rcp); + return r; + } + // digamma asymptotic expansion + // digamma(x) ~ ln(z)+1/(2z)-sum_(n=1)^(infty)(Bernoulli(2n))/(2nz^(2n)) + // Generated in SageMath: + // var('x') + // + // def bernoulli_terms(x, N): + // S = 0 + // S += QQ(1)/QQ(2)/x + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / QQ(2*k))*x**(-2*k) + // S += term + // return S + // + // terms = bernoulli_terms(x, 9) + // + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(1, 13): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + const C: [(u64, u64); 10] = [ + (0x3c55555555555555, 0x3fb5555555555555), + (0xbc01111111111111, 0xbf81111111111111), + (0x3c10410410410410, 0x3f70410410410410), + (0xbbf1111111111111, 0xbf71111111111111), + (0xbc0f07c1f07c1f08, 0x3f7f07c1f07c1f08), + (0x3c39a99a99a99a9a, 0xbf95995995995996), + (0x3c55555555555555, 0x3fb5555555555555), + (0xbc77979797979798, 0xbfdc5e5e5e5e5e5e), + (0xbc69180646019180, 0x40086e7f9b9fe6e8), + (0x3ccad759ad759ad7, 0xc03a74ca514ca515), + ]; + + let rcp = DoubleDouble::from_quick_recip(x); + let rcp_sqr = DoubleDouble::quick_mult(rcp, rcp); + + let rx = rcp_sqr; + let x2 = DoubleDouble::quick_mult(rx, rx); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let q0 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[1]), + rx, + DoubleDouble::from_bit_pair(C[0]), + ); + let q1 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[3]), + rx, + DoubleDouble::from_bit_pair(C[2]), + ); + let q2 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[5]), + rx, + DoubleDouble::from_bit_pair(C[4]), + ); + let q3 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[7]), + rx, + DoubleDouble::from_bit_pair(C[6]), + ); + let q4 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[9]), + rx, + DoubleDouble::from_bit_pair(C[8]), + ); + + let q0 = DoubleDouble::quick_mul_add(x2, q1, q0); + let q1 = DoubleDouble::quick_mul_add(x2, q3, q2); + + let r0 = DoubleDouble::quick_mul_add(x4, q1, q0); + let mut p = DoubleDouble::quick_mul_add(x8, q4, r0); + p = DoubleDouble::quick_mul_f64_add( + rcp, + f64::from_bits(0x3fe0000000000000), + DoubleDouble::quick_mult(p, rcp_sqr), + ); + + let v_log = fast_log_d_to_dd(x); + DoubleDouble::quick_dd_sub(v_log, p) +} + +#[inline] +fn approx_digamma_hard_dd(x: DoubleDouble) -> DoubleDouble { + if x.hi <= 12. { + let x2 = DoubleDouble::quick_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + let (p, q) = digamma_coeefs(x.hi); + + let e0 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[1]), + x, + DoubleDouble::from_bit_pair(p[0]), + ); + let e1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[3]), + x, + DoubleDouble::from_bit_pair(p[2]), + ); + let e2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[5]), + x, + DoubleDouble::from_bit_pair(p[4]), + ); + let e3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[7]), + x, + DoubleDouble::from_bit_pair(p[6]), + ); + let e4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[9]), + x, + DoubleDouble::from_bit_pair(p[8]), + ); + let e5 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[11]), + x, + DoubleDouble::from_bit_pair(p[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + let rcp = x.recip(); + + let e0 = DoubleDouble::mul_add_f64( + DoubleDouble::from_bit_pair(q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[3]), + x, + DoubleDouble::from_bit_pair(q[2]), + ); + let e2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[5]), + x, + DoubleDouble::from_bit_pair(q[4]), + ); + let e3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[7]), + x, + DoubleDouble::from_bit_pair(q[6]), + ); + let e4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[9]), + x, + DoubleDouble::from_bit_pair(q[8]), + ); + let e5 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[11]), + x, + DoubleDouble::from_bit_pair(q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let q = DoubleDouble::div(p_num, p_den); + let r = DoubleDouble::quick_dd_sub(q, rcp); + return r; + } + // digamma asymptotic expansion + // digamma(x) ~ ln(z)+1/(2z)-sum_(n=1)^(infty)(Bernoulli(2n))/(2nz^(2n)) + // Generated in SageMath: + // var('x') + // + // def bernoulli_terms(x, N): + // S = 0 + // S += QQ(1)/QQ(2)/x + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / QQ(2*k))*x**(-2*k) + // S += term + // return S + // + // terms = bernoulli_terms(x, 9) + // + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(1, 13): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + const C: [(u64, u64); 10] = [ + (0x3c55555555555555, 0x3fb5555555555555), + (0xbc01111111111111, 0xbf81111111111111), + (0x3c10410410410410, 0x3f70410410410410), + (0xbbf1111111111111, 0xbf71111111111111), + (0xbc0f07c1f07c1f08, 0x3f7f07c1f07c1f08), + (0x3c39a99a99a99a9a, 0xbf95995995995996), + (0x3c55555555555555, 0x3fb5555555555555), + (0xbc77979797979798, 0xbfdc5e5e5e5e5e5e), + (0xbc69180646019180, 0x40086e7f9b9fe6e8), + (0x3ccad759ad759ad7, 0xc03a74ca514ca515), + ]; + + let rcp = x.recip(); + let rcp_sqr = DoubleDouble::quick_mult(rcp, rcp); + + let rx = rcp_sqr; + let x2 = DoubleDouble::quick_mult(rx, rx); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let q0 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[1]), + rx, + DoubleDouble::from_bit_pair(C[0]), + ); + let q1 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[3]), + rx, + DoubleDouble::from_bit_pair(C[2]), + ); + let q2 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[5]), + rx, + DoubleDouble::from_bit_pair(C[4]), + ); + let q3 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[7]), + rx, + DoubleDouble::from_bit_pair(C[6]), + ); + let q4 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[9]), + rx, + DoubleDouble::from_bit_pair(C[8]), + ); + + let q0 = DoubleDouble::quick_mul_add(x2, q1, q0); + let q1 = DoubleDouble::quick_mul_add(x2, q3, q2); + + let r0 = DoubleDouble::quick_mul_add(x4, q1, q0); + let mut p = DoubleDouble::quick_mul_add(x8, q4, r0); + p = DoubleDouble::quick_mul_f64_add( + rcp, + f64::from_bits(0x3fe0000000000000), + DoubleDouble::quick_mult(p, rcp_sqr), + ); + + let mut v_log = fast_log_d_to_dd(x.hi); + v_log.lo += x.lo / x.hi; + DoubleDouble::quick_dd_sub(v_log, p) +} + +/// Computes digamma(x) +/// +pub fn f_digamma(x: f64) -> f64 { + let xb = x.to_bits(); + if !x.is_normal() { + if x.is_infinite() { + return if x.is_sign_negative() { + f64::NAN + } else { + f64::INFINITY + }; + } + if x.is_nan() { + return f64::NAN; + } + if xb.wrapping_shl(1) == 0 { + // |x| == 0 + return f64::INFINITY; + } + } + + let dx = x; + + if x.abs() <= f64::EPSILON { + // |x| < ulp(1) + // digamma near where x -> 1 ~ Digamma[x] = -euler + O(x) + // considering identity Digamma[x+1] = Digamma[x] + 1/x, + // hence x < ulp(1) then x+1 ~= 1 that gives + // Digamma[x] = Digamma[x+1] - 1/x = -euler - 1/x + // euler is dropped since 1/x >> euler + // that gives: + // Digamma[x] = Digamma[x+1] - 1/x = -1/x + return -1. / x; + } + + if x < 0. { + // at negative integers it's inf + if is_integer(x) { + return f64::NAN; + } + + // reflection Gamma(1-x) + Gamma(x) = Pi/tan(PI*x) + const PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let r = DoubleDouble::from_full_exact_sub(1., x); + let mut result = PI * cotpi_core(-x); + let app = approx_digamma_hard_dd(r); + result = DoubleDouble::quick_dd_add(result, app); + result.to_f64() + } else { + let app = approx_digamma_hard(dx); + app.to_f64() + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_digamma() { + assert_eq!(f_digamma(0.0019531200000040207), -512.5753182109892); + assert_eq!(f_digamma(-13.999000000012591), -997.3224450000563); + assert_eq!(f_digamma(13.999000000453323), 2.602844047257257); + assert_eq!(f_digamma(0.), f64::INFINITY); + assert_eq!(f_digamma(-0.), f64::INFINITY); + assert!(f_digamma(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digamma_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digamma_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digamma_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,839 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +Poly numerators for digamma with step 0.25 from 0 to 1: [-0.99999999,-0.75], [-0.75, -0.5] etc. +Generated by Wolfram: +<75,MaxIterations->100] +num=Numerator[approx]; +den=Denominator[approx]; +poly=num; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +poly=den; +coeffs=CoefficientList[poly,z]; +TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +*/ +static DIGAMMA_P: [[(u64, u64); 12]; 5] = [ + [ + (0x3c56cb8ed2e8f89d, 0xbfe2788cfc6fb619), + (0xbc3f4a887143e1a0, 0x3face2294e40a23d), + (0x3c66cbeeb663e02b, 0x3ff93da24c048557), + (0xbc99dce69443c3a1, 0x3ffb9ca4e7e3b448), + (0x3c86642ccc010b7c, 0x3febdebcbbc26740), + (0xbc6b0b2f44dae75c, 0x3fcfec9b12222c41), + (0xbbf4498c8a1b0940, 0x3fa62080e59486a8), + (0x3c0b9dc350a33198, 0x3f72bc74facca682), + (0xbbcd99184e051c10, 0x3f32c94b7b2fb002), + (0xbb8738e809ec0cee, 0x3ee48ad4af286d1f), + (0x3b130f69e7502da5, 0x3e84788fd8c782e7), + (0xbaabf9ce6f6a39c0, 0x3e075df82b55c605), + ], + [ + (0x3c56cb907008b543, 0xbfe2788cfc6fb619), + (0xbc100842dc7f9e7f, 0x3fb01301a3e98b73), + (0xbc823b1b4a0eb7aa, 0x3ff938b063dae04f), + (0xbc9ad21ad2ab96c5, 0x3ffb55c29a135ea7), + (0xbc7d5ba993767236, 0x3feb4f810b04c753), + (0x3c64772eb3244da3, 0x3fcee4afd0031184), + (0x3c31c1810f303099, 0x3fa513f613ed0729), + (0x3c0bd0845bf7f471, 0x3f717f05f5d10c47), + (0xbbd5725001e2660d, 0x3f311a7e461bfdbc), + (0xbb8598e1d6bf14c5, 0x3ee21971cbf5769f), + (0x3b2c987b53229a3f, 0x3e81461991174455), + (0xbaa40e6fc1c3cdbd, 0x3e029575e1cf2d2e), + ], + [ + (0x3c56cb90701fbfa6, 0xbfe2788cfc6fb619), + (0xbc5fccfe13017bdd, 0x3fb1afc092258787), + (0xbc5e1697dc2cc4ab, 0x3ff9337b6bb944de), + (0x3c7ec613451b31b9, 0x3ffb0fd93c22113b), + (0x3c69294dd477ad47, 0x3feac3c7b64adea4), + (0xbc69ac8bff5565b5, 0x3fcde66e558d148f), + (0x3c41acf6837637f5, 0x3fa4154b581a555a), + (0xbc000c1483343db8, 0x3f70580604407f51), + (0x3bbc673a5ee2174f, 0x3f2f290c93113075), + (0x3b7ea2e3314e056e, 0x3edfed2db5039158), + (0xbaf8d7013fff21f7, 0x3e7d35fdf2716965), + (0xba739bf5ff69075f, 0x3dfdb070ae4d9275), + ], + [ + (0x3c56cb90701fbfab, 0xbfe2788cfc6fb619), + (0x3c32d7bac835354c, 0x3fb34c4468e4cca5), + (0x3c83dfd7ab2663ee, 0x3ff92df4d81668e8), + (0x3c99f27ceb6a6462, 0x3ffaca12fb44387d), + (0xbc873d42ae8bf0ee, 0x3fea39db2aa6755c), + (0x3c6f0709b773a576, 0x3fccee948fe7d9a3), + (0xbc319c78a343f2ba, 0x3fa320f0d611b675), + (0xbba5feb85ab5acbc, 0x3f6e855445cb1dae), + (0x3bba9b56af9b20c5, 0x3f2c5ecc73cbcdd8), + (0xbb79a32258828ace, 0x3edc257fc6ffd42d), + (0x3b1efad7acd7d7f1, 0x3e78b3710a7cc9b4), + (0xba9b941fb3ff6b0c, 0x3df7c1965f2d7194), + ], + [ + (0x3c56cb90701fbfab, 0xbfe2788cfc6fb619), + (0xbc0f99d5dc5f8b06, 0x3fb4e913ab76f9ab), + (0x3c3191e63046dc0e, 0x3ff9281aa8398c82), + (0xbc8dca8def824c6e, 0x3ffa845a59ce1115), + (0xbc84dbb9117bcea5, 0x3fe9b18e7fe7829a), + (0xbc5e38525daac915, 0x3fcbfcbc6601a1fe), + (0x3c4df8dcb4769fe3, 0x3fa2364b5ab136dd), + (0x3c03a220e74edede, 0x3f6c7b78bf3817d2), + (0xbb831144f7e90d73, 0x3f29d06f3db25586), + (0x3b7b4bf8f2ec756c, 0x3ed8cd0278bee187), + (0x3b0c2bf25bbf39b5, 0x3e74e2f6a044ec34), + (0x3a942086a4928038, 0x3df3096d2199706d), + ], +]; + +static DIGAMMA_Q: [[(u64, u64); 12]; 5] = [ + [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbca6adb0ceca2bb2, 0x4006042dff16f40e), + (0xbc85b67e7a730640, 0x4008379d3bb3e8e0), + (0xbc9f004eb95ee438, 0x3ffc7e68e904512d), + (0xbc86ee1922dc4c80, 0x3fe407ea97357260), + (0xbc4a51002b1b8870, 0x3fc1a70e08dee4dd), + (0x3c3c858930786915, 0x3f93c1e4eef4b20b), + (0x3be9a73c7d428d88, 0x3f5baa2f04f498b1), + (0x3bbad1b8117f7756, 0x3f171c5667c8dffc), + (0x3b173ce742b4d895, 0x3ec4e29a45581499), + (0xbadceb3243cdae8f, 0x3e60a2d5d1c5f8e4), + (0xba72b2562de7b14b, 0x3ddb303e7518d74b), + ], + [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c91779e812448f8, 0x4005ed8db27be60e), + (0x3ca08f641dca5f12, 0x4007fb6b0dcbcebe), + (0xbc9b5b059968427b, 0x3ffc005c8adea86d), + (0x3c7a6c4119840b60, 0x3fe37d5ff5b97171), + (0xbc530ac1661d05de, 0x3fc0f56578da17ee), + (0xbc0418ed2bc636c5, 0x3f92ad4e7387f851), + (0xbbc1f659b88045fd, 0x3f599f72920bc12d), + (0x3bba548ec376cb95, 0x3f14dae97a930698), + (0x3b440fec06d88466, 0x3ec239fbc98052c7), + (0xbae8bd7909c83aaf, 0x3e5bcab555b96b0c), + (0x3a7da912eade2739, 0x3dd5684408d505b7), + ], + [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbca91be54288a0e0, 0x4005d735308bb4dd), + (0xbcad30b7bbf2b783, 0x4007c03f8e4c4fe6), + (0xbc9eeb30365815fb, 0x3ffb854f0db08baa), + (0x3c782d2becaf6172, 0x3fe2f7622383d14d), + (0xbc5e010ee89a3662, 0x3fc04badf9bdbed9), + (0x3c2af3eb8a7d2bde, 0x3f91a94aee0050b0), + (0xbbd2450502e41cf9, 0x3f57be27fec5860c), + (0xbb4d401f4b8a5f96, 0x3f12d5723c46d383), + (0xbb56834644f0201f, 0x3ebfda938f459b86), + (0x3ada0645f44a4bcd, 0x3e574563cf974833), + (0xba7147ae6edcbc3d, 0x3dd0f0bfcad5f047), + ], + [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc9045b43a44ffbd, 0x4005c0dfe199018b), + (0x3cadc1c9c8ce4d30, 0x40078563dd87aa1b), + (0xbc7ee1018a57916d, 0x3ffb0bbe462659fc), + (0x3c84b1e3cb3c10f4, 0x3fe2743f18457656), + (0x3c5ce0b8927bff8a, 0x3fbf4f3f5d1d2c88), + (0x3c227cc874c2781a, 0x3f90b1f8cc772eb7), + (0x3bea9648da0df3bd, 0x3f55fdcf409bac26), + (0x3bbc08910e142370, 0x3f11003e3494b94d), + (0x3b5a6e0762b57f19, 0x3ebbd3ea01684109), + (0xbae425ecbc8c7993, 0x3e537e51126d11b7), + (0xba656f95223fc44f, 0x3dcadec5fd0f622c), + ], + [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3caa0a86221a0755, 0x4005aa867d56dca4), + (0xbcac770719607c75, 0x40074ac4f6ca5a47), + (0x3c90d03a36128d7f, 0x3ffa93815f190569), + (0x3c4d48dbdc6c9a7c, 0x3fe1f3c3b4044619), + (0x3c55f2ca2ba72f08, 0x3fbe11c76c6789f6), + (0x3c07ca0eacaa9a9c, 0x3f8f8d146c709524), + (0xbbd3ae3ef7bb9792, 0x3f545be615cbebf2), + (0xbb86e82ec7f13b7f, 0x3f0ead31c1a5b093), + (0xbb3275f4a13e5259, 0x3eb84d337c38d867), + (0xbaf557dfebeee67e, 0x3e505544e8f1eb85), + (0xba664f9845fcddf2, 0x3dc559cc156a72a5), + ], +]; + +#[inline] +#[allow(clippy::type_complexity)] +pub(crate) fn digamma_coeefs(x: f64) -> (&'static [(u64, u64); 12], &'static [(u64, u64); 12]) { + if x < 1.25 { + const FOUR: u64 = 2 << 52; + let idx = f64::from_bits(x.to_bits().wrapping_add(FOUR)) as usize; + let p = &DIGAMMA_P[idx]; + let q = &DIGAMMA_Q[idx]; + (p, q) + } else if x <= 1.461632144 { + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c56cb90701fbfac, 0xbfe2788cfc6fb619), + (0x3c519fc5fe329992, 0x3fb66b6f7ca77b95), + (0x3c934d7e8434b86d, 0x3ff92255627f42b7), + (0x3c637005ae2e1665, 0x3ffa43326e6dda36), + (0x3c3cadafce6428f4, 0x3fe9338d9b2539f1), + (0xbc5934a30d152b54, 0x3fcb1febac693a97), + (0xbc3d4ec7808fa04f, 0x3fa1636286a89dfe), + (0xbbf577e9f832bec3, 0x3f6aafbc9ad0d5ad), + (0xbbcd6cc934d6ba4e, 0x3f279eaf8168ee05), + (0xbb774ef4099bad0c, 0x3ed605efaec77016), + (0xbb13d911fcebafac, 0x3e71dae45db651bb), + (0x3a8f943200c1fd92, 0x3deefe67af5b7c69), + ]; + + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // den=Denominator[approx]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca0fb55209ad44d, 0x4005959bb2d38810), + (0xbc4a7dccb43a2a97, 0x40071428acb23be5), + (0xbc8b9d316e4d2eac, 0x3ffa24400e09040c), + (0xbc82963c4efb8cd1, 0x3fe17dfa742912bc), + (0x3c57e765f5582745, 0x3fbcf24965915c1f), + (0xbc2bfe1e01bc34f0, 0x3f8de96be6a73955), + (0x3bff6a6cc1679110, 0x3f52ef034cdc300f), + (0xbb95e707835497ae, 0x3f0bd94abae4b483), + (0xbb435b31a77f1eac, 0x3eb5673711efb89a), + (0xbab7879ef73e896a, 0x3e4bb1a59a808117), + (0xba50ff72e575b8bd, 0x3dc13fef9cd36cd7), + ]; + (&P, &Q) + } else if x <= 1.75 { + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c56cb907020a112, 0xbfe2788cfc6fb619), + (0xbc3cc4d6d2ddccf8, 0x3fb8010bfcb83141), + (0x3c953d47923ee59b, 0x3ff91bf87a8009ef), + (0x3c856cf1c819abcd, 0x3ff9fee67ab017a1), + (0xbc7e5e24a77dd53e, 0x3fe8b0e3f74e8969), + (0xbc60cf6e08c2898c, 0x3fca3dc2ac288997), + (0xbc4d6745fb4dd03b, 0x3fa08eb928fceb5d), + (0x3c0153615a07e895, 0x3f68e95d5669dc9c), + (0x3bcc104646590a9e, 0x3f25818c7facb551), + (0xbb6ce130dd405fa2, 0x3ed36f27c8982809), + (0xbae5a7d3777ea48d, 0x3e6e4b3d604133f4), + (0xba86b002676d830d, 0x3de9027ae9347c77), + ]; + + // Generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // den=Denominator[approx]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca13038b3e9b2fe, 0x40057fa6128d0d08), + (0xbcacf21951ec09a9, 0x4006db1750ade888), + (0x3c9fd268ab672291, 0x3ff9b0c5a589896f), + (0xbc4b818d4493b88a, 0x3fe104d8aeed391e), + (0xbc5531e244a9d256, 0x3fbbce38cef1dcd3), + (0x3c14e017cdbf9c7b, 0x3f8c45ceb3fbe0a3), + (0x3bff3d4bd6748d1c, 0x3f51898acc32fa08), + (0xbb6c0ebdb9714f4b, 0x3f09266424ad60b1), + (0x3b30abd2021dc5ea, 0x3eb2ba49a890927f), + (0xba9629f3ce206d76, 0x3e474b9f374cf052), + (0x39f3beca069e2142, 0x3dbba0c4466d2dcd), + ]; + (&P, &Q) + } else if x <= 2. { + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c56cb907bb52809, 0xbfe2788cfc6fb619), + (0xbc420cb940ff1bad, 0x3fb9b8ce99af6686), + (0xbc9554bebef623c7, 0x3ff914b779852ffb), + (0x3c81daceacffe906, 0x3ff9b4fb845f87b4), + (0xbc589d02262e231e, 0x3fe8251c504ee4e7), + (0xbc48b053e0ac1f18, 0x3fc94f0c5b394803), + (0xbc12b44611d0cc3d, 0x3f9f6411022b8fee), + (0x3bf71626c3a722d6, 0x3f671bef7af39602), + (0x3bca802abbe6c032, 0x3f236afc88364acd), + (0xbb73ba0bffc04b11, 0x3ed0f71a4569fdd2), + (0x3ae6866974b3745b, 0x3e695b19eb1a11d0), + (0x3a53fcd00ba0f0cd, 0x3de3dbee8f81e7d1), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca79b06fde08bf7, 0x400567d727c212e8), + (0xbc9b0efe8b146dee, 0x40069d86c47f0240), + (0xbc8299a0687d2bc4, 0x3ff9351a45c9504d), + (0xbc7146fcb08e6211, 0x3fe0846a56e8c617), + (0xbc482c27fd2b0de3, 0x3fba9ca29930f546), + (0x3beaea4e7ed3058f, 0x3f8a96406d35271a), + (0x3bf776396bc4adbd, 0x3f5021eb0152afad), + (0xbb96d179aedf8a7a, 0x3f0682935c1f4e53), + (0xbb469533a5f262d4, 0x3eb033bbf3243fc1), + (0x3ad33e062bbd7ac2, 0x3e43535be5d463ef), + (0x3a5a7d127f1db626, 0x3db5c4427025e959), + ]; + (&P, &Q) + } else if x <= 3. { + // x <= 3 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c56d1cc8bcd2834, 0xbfe2788cfc6fb619), + (0x3c50701f78e64a63, 0x3fbd8bb4f2220f15), + (0xbc6f91b861a7c3f1, 0x3ff903416798b207), + (0x3c8c53da657116b3, 0x3ff910f28e38ea3f), + (0xbc8720408446640c, 0x3fe6f4e66e069dae), + (0xbc34e63b5e59b9bd, 0x3fc75316d7a07060), + (0xbc22cfa33a314334, 0x3f9bd312bdf809fb), + (0xbbfd6f2d0a941d18, 0x3f638321ec193179), + (0xbbbd1cabd7d7d204, 0x3f1edf0eeec2ed8f), + (0x3b62b3641fcc9055, 0x3ec908c824d24ebd), + (0x3b09f21b5bfbaac3, 0x3e61119012a56c3c), + (0xba7ccbf11ca33a44, 0x3dd7e364822d6038), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca8ae32e83e7971, 0x400532d7f57a1fb8), + (0x3ca7e06fe036f034, 0x4006159f6c8559a6), + (0x3c696aeb79408ada, 0x3ff8276de15b9949), + (0x3c6b4b6c4100ee75, 0x3fdee20a3a9510d1), + (0xbc5366197ca045c2, 0x3fb81bb8b46e3ac9), + (0x3c2f178bb9cecf1c, 0x3f8726ac2011b61b), + (0x3be51ce661a77196, 0x3f4abe5166a64e0d), + (0xbb84cb13a26b099d, 0x3f018de8d20c9ae7), + (0xbb4f127e563d4fce, 0x3ea772bc233a7f3d), + (0xbad8391ca6522a23, 0x3e398817e8c8a3f5), + (0x3a46dbfc8fc0a31f, 0x3da9c1eb2bb8a09d), + ]; + (&P, &Q) + } else if x <= 4. { + // x <= 4 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc1138539f5170ce, 0xbfe2788cfc6fb617), + (0x3c5c28276512f306, 0x3fc1fc2364555134), + (0xbc6a09be4de1611c, 0x3ff8e1befdb6bc25), + (0x3c74ca0e29a4c28f, 0x3ff7ff202fdee96b), + (0xbc81af890e1880a0, 0x3fe50bb10d8d3f83), + (0xbc63ea18b51ff6b6, 0x3fc444e2fde41a82), + (0x3c3778d316f51d1e, 0x3f969f9868302eb9), + (0x3be358e50a96a230, 0x3f5d3a1baf51425c), + (0x3bbc38a174d2733f, 0x3f14e8fe4a7dddfb), + (0x3b5f5ed1876db6a7, 0x3ebe07d4dbcc1ad4), + (0x3af907af35fa32d0, 0x3e51b3f54fae106f), + (0x3a62af4ca3fd0f35, 0x3dc4d88e2dc21ca8), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c9648605b16dd34, 0x4004d9ced1a59873), + (0x3c7dc6b76d368927, 0x400534eafce36582), + (0xbc3ce3eb41ed98ed, 0x3ff673eeb71c9f83), + (0xbc66f13de6a48d20, 0x3fdb84d7f538c20d), + (0x3c5035f4fefd130a, 0x3fb45b63620b1db4), + (0x3c1923173b36285f, 0x3f8246e776c12954), + (0x3be4c733ad174a92, 0x3f436ec81a059c76), + (0x3b8012652ce0bc96, 0x3ef70fe1dc481482), + (0x3b2d0670cd6004bc, 0x3e9b497296f5f46e), + (0xba85189a8dab3039, 0x3e29bb6d630a41ac), + (0x3a3cb2bee18cf77a, 0x3d95f146af7f3514), + ]; + (&P, &Q) + } else if x <= 5. { + // x <= 5 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c82777617606035, 0xbfe2788cfc6fb22a), + (0x3c6a89168e92a2bd, 0x3fc5286b343ecbe5), + (0xbc7562c3f1327b91, 0x3ff8bb7dfd30d653), + (0xbc8167bf7208ef96, 0x3ff6f31495ad9560), + (0x3c82d2177e694dd6, 0x3fe3431bda031b31), + (0xbc6be5da70840171, 0x3fc19291a81dd8a2), + (0x3c3bf690d21eb357, 0x3f9258218b3ef7bf), + (0xbbffd8d4b0692fbb, 0x3f55d7a5623a2dcf), + (0x3babb591eb87dd6c, 0x3f0c56ac18bd4d6b), + (0xbb5c8b806eef4ae7, 0x3eb2209eb7acd22b), + (0xbad36fc4d27a4168, 0x3e42af070578d594), + (0xb9dfe0085849fd5a, 0x3db2d9b6d2913a2a), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbca9a57355580b15, 0x400481dafdd7bdb2), + (0x3c8c54a5f9c29d95, 0x40045b68f0902217), + (0xbc795347ec01fbd2, 0x3ff4daef6b912517), + (0x3c699ae8f19cf3ec, 0x3fd87d05ac8eb769), + (0x3c59ea5ce4904986, 0x3fb12877d62826ca), + (0x3be6bd7425bdd967, 0x3f7cce33e2dd0530), + (0xbbc460e353f4c8bc, 0x3f3c38bcf76c94b5), + (0xbb712ad762f9ec9d, 0x3eee601d38ab6d9b), + (0xbb23ce6868791dc5, 0x3e9006213ba059aa), + (0xbab95abdc33a7321, 0x3e1a7ac297a0a53d), + (0xba174f07c41d8cfd, 0x3d836fa7694a651d), + ]; + (&P, &Q) + } else if x <= 6. { + // x <= 6 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc8032a1d2c0ad13, 0xbfe2788cfc6e9dbe), + (0x3c38696772d75917, 0x3fc849d273d05d75), + (0x3c954ca48d09b1aa, 0x3ff890aef7dc27e1), + (0xbc963b4b7c9a58af, 0x3ff5ed5797be10f8), + (0x3c87390c0470f3c6, 0x3fe19a75e3a5dbe3), + (0xbc4a8fca8acf4f1f, 0x3fbe68afab720ce8), + (0x3c1ed20f546b9104, 0x3f8db0bf34ed5e72), + (0xbbd6b67d3f6d936e, 0x3f504f9138773832), + (0x3bae68dee81a333d, 0x3f033ff5436fb4e3), + (0xbb1fad498922c758, 0x3ea61338f9837209), + (0x3ad4cdce5341705f, 0x3e341863900b259b), + (0xba1368ab344aa52f, 0x3da1a36dc66478ff), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc8415c937927b80, 0x40042b14ac1de31a), + (0xbca02e650cfc91cb, 0x4003893428b832f0), + (0x3c85d3d357beac28, 0x3ff35bb913ab979e), + (0x3c763ef88de8bbf4, 0x3fd5c47e7c28af74), + (0x3c4624d0ce63afac, 0x3face2a04d07592f), + (0x3befca3faad26d95, 0x3f76adbb8f0c9e71), + (0x3bd6bb21845ab51f, 0x3f3482259071c038), + (0xbb888fad8984adb0, 0x3ee4182fa08710cd), + (0xbb2ec0c609c2589a, 0x3e83082e53b39cd4), + (0xbaa2954cc8fe5ef2, 0x3e0bd8dfedf43944), + (0x39e30166e0cac476, 0x3d71dc88357652c3), + ]; + (&P, &Q) + } else if x <= 7. { + // x <= 7 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc81dfd5a5534592, 0xbfe2788cfc565c6c), + (0x3c5ee519bbeafb4a, 0x3fcb5e9b249cc2ae), + (0x3c8df433a8ab926f, 0x3ff86195ebe61e55), + (0xbc9c26e874cedb94, 0x3ff4eeb2d59b9e46), + (0xbc8b629f64d30eb4, 0x3fe011547d3b4deb), + (0x3c4877eafbf1d0bf, 0x3fba461689f2d09b), + (0xbc02cb677bd729e7, 0x3f8801390c64edcd), + (0x3be6bb411d2772bf, 0x3f4861722dbdb621), + (0x3b95c312dfadf0f8, 0x3efa4589f0866235), + (0x3b2e65576c0b0642, 0x3e9b2d2386424cdf), + (0x3acbcd0ab8139043, 0x3e260e89319914dd), + (0x3a2bde33fa1ac8f3, 0x3d9110236b17c522), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c8ff6dd498c91b2, 0x4003d5ac26d888b6), + (0x3c9acb90be620fba, 0x4002be9b5e78f13f), + (0x3c80944df7c8a780, 0x3ff1f5e5ec0c3d71), + (0x3c50f7c451bbdd2e, 0x3fd355e0f87c5218), + (0xbc4cd8f8f78b44a1, 0x3fa84c8863aae54b), + (0xbc13df2d02c4d3c4, 0x3f71dc00f5ff8e9c), + (0x3bc942f7fa51682f, 0x3f2de1134f7b2de6), + (0xbb5bcf5da39fb215, 0x3edac2e18af5b8d1), + (0xbb11b483e6820b4e, 0x3e76e765628dffe0), + (0x3a89bf8734fc1f0e, 0x3dfdf503240dffa2), + (0xb9fcaf5858297b35, 0x3d610182e7d328a5), + ]; + (&P, &Q) + } else if x <= 8. { + // x <= 8 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc8162f86e7bad36, 0xbfe2788cfb513f92), + (0xbc6ddc13d58b297e, 0x3fce652fd3cec73c), + (0x3c701fd75f0e2153, 0x3ff82e7ee851190e), + (0x3c86494ccd407812, 0x3ff3f7d8f2cc7221), + (0x3c71d5a4a3016802, 0x3fdd4df807c7f6a2), + (0xbc55bd847484e7bd, 0x3fb6aeaa992b7e5e), + (0x3c1d99552c28a292, 0x3f8368db68048c4f), + (0xbbecf51acbe60763, 0x3f42437beb7b56ec), + (0x3b7ec2e94f896a2d, 0x3ef20a7a9ea0accc), + (0x3a9a0a1b60fffd51, 0x3e90f02feda221d2), + (0x3ab8a5da0c600246, 0x3e18b9818d3b86a1), + (0xba1dc40c982b9669, 0x3d810bda1d0bde80), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c95f4382d9f9dbc, 0x400381cd52a27389), + (0x3ca36a2a63377659, 0x4001fbd9cbbdde5b), + (0xbc83cb5796f6bba0, 0x3ff0a8db1d651315), + (0x3c779f72905d08e8, 0x3fd12b8a9f02c16c), + (0xbc4dacaf20322afe, 0x3fa47160278b25ee), + (0xbc0262fab0a08a3c, 0x3f6c2a94e4e5cf4f), + (0x3bc553f072d7f874, 0x3f25d9d7c995af31), + (0x3b62f92e30dbacb9, 0x3ed1f75f5d275707), + (0x3b02b661ecc2ba69, 0x3e6bf75615fe0e2f), + (0x3a571b7290df94bc, 0x3df07d3db0951aef), + (0xb9f18f3d33a27e32, 0x3d50bfea8f77e0c3), + ]; + (&P, &Q) + } else if x <= 9. { + // x <= 9 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0x3c8efd7fe9db6e79, 0xbfe2788cf4b3267f), + (0x3c6a2e8811472031, 0x3fd0ae258336bb2b), + (0x3c7399e3844d1e5f, 0x3ff7f7b99c5c43be), + (0x3c822ee42e5fe80d, 0x3ff30958a7e8d80e), + (0x3c6848d741adf8c4, 0x3fdab4b23acdeb18), + (0x3c5aa072e08707aa, 0x3fb393aa5016e08a), + (0xbc18b1985dc2c38c, 0x3f7f6b771fa6e163), + (0x3bdc86329c365200, 0x3f3b75a61ceee8c8), + (0x3b8e8f8ff597b2e6, 0x3ee8f7bf1b272a81), + (0x3b19b561962f8b4e, 0x3e8566c7b18e4a14), + (0x3aadf125c1ad7adb, 0x3e0c4f51c4444e9a), + (0x39f1e1df7a4c3a8b, 0x3d7190106017b110), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ca684bdc1b74b83, 0x40032f9b62c83c86), + (0x3ca5d8d28ceedbb4, 0x4001410ed7fd4814), + (0x3c7686b33443b989, 0x3feee782a9ab5027), + (0x3c53620c43b8821f, 0x3fce7f4d1d2ffe3c), + (0xbc33e2abe9a40984, 0x3fa1362ff4c8e4cb), + (0xbbef2639d9860de0, 0x3f66430cca12747e), + (0xbbb8084e63a55a7b, 0x3f200faaa577da43), + (0x3b6b0dea347bf9f3, 0x3ec859b423a711e8), + (0x3b04cb8df32e9178, 0x3e61563b86bed1a2), + (0xba801506c55d0eb4, 0x3de292d18eb8fd2f), + (0xb9d06300f4b9226a, 0x3d4109bff966bb51), + ]; + (&P, &Q) + } else if x <= 10. { + // x <= 10 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc8593c1df8ef6c7, 0xbfe2788cd6e083bb), + (0x3c6415b1331fd1e0, 0x3fd2217df51ae592), + (0x3c9c29eeb5fe4731, 0x3ff7bd965beb1b87), + (0xbc85fe7985564d6e, 0x3ff2239b9feaa8a7), + (0xbc5cc9b9441046be, 0x3fd8541d3ac20fdc), + (0xbc243a1d71c1b7e2, 0x3fb0e6b0237a2f28), + (0xbc1534c74442766c, 0x3f797a05781bf99b), + (0xbbd8ba51ad9881fe, 0x3f34bc78d4108de1), + (0xbb81efd29f25726f, 0x3ee16d09b7ddc32f), + (0xba96ec9993a947f2, 0x3e7b6c967312dff2), + (0xbaa2a0b4acd633ea, 0x3e008d27d632d14c), + (0xb9ff596e6d378d22, 0x3d62a21a99d77977), + ]; + // Generated by Wolfram Mathematica: + //<75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c6f1ef07b1b5dc9, 0x4002df30458e626a), + (0xbc960127cb9e2eab, 0x40008e3f3217718d), + (0x3c8412d2aabe8bf8, 0x3fecab1dc0e9bcac), + (0x3c64edc0f7754efe, 0x3fcb18b1038e24f6), + (0xbc3abc16284838a3, 0x3f9d05522b423e2f), + (0xbc0e44998e55a65f, 0x3f61a64c0a74479e), + (0xbbb190403d2a5a61, 0x3f17c0a8b1842890), + (0x3b598fe19ed917ac, 0x3ec0ab7613d6b90e), + (0xbaf7c33460b01c25, 0x3e55d581be9c2732), + (0xba7278196b41c6f6, 0x3dd565843701949d), + (0x39912fb123ad4ce0, 0x3d31de54105a6ae4), + ]; + (&P, &Q) + } else if x <= 11. { + // x <= 11 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc7002de428656f8, 0xbfe2788c706086ea), + (0xbc7e5dea366e1224, 0x3fd38c4fa29daad3), + (0x3c95297f4120d6e1, 0x3ff780642930e686), + (0xbc7cdcec6276d962, 0x3ff146e905a85e7c), + (0xbc4dde11481dc9d7, 0x3fd629105bd7a86b), + (0x3c29f43835822d7e, 0x3fad342a0507d56a), + (0x3c1f98d2402273b2, 0x3f74b55e06fd0100), + (0x3bc61bf252df59de, 0x3f2f7b95f117d541), + (0x3b4f7f3c66a58c10, 0x3ed88c81b5a7bffc), + (0xbb1ba95a86f7955a, 0x3e71d2d46e31e04c), + (0xb9feae47109db197, 0x3df3c1020acf06fb), + (0xb9ed26ed15eff6d5, 0x3d5453226c1a47c8), + ]; + // Generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc8f67d2f15a73c9, 0x4002909d472a6258), + (0x3c94a8e3edcab93b, 0x3fffc6b132050914), + (0xbc5b982f33a20a73, 0x3fea9a2aba70b06e), + (0x3c619d024f5cdba4, 0x3fc817cd43625de8), + (0xbc3dc40df7f1ecbb, 0x3f9882a708f4756f), + (0x3b88f0ba3ff4834f, 0x3f5c16f3fb9fe3e9), + (0xbb8ed7db88e71ba0, 0x3f11ae1da151fd8f), + (0x3b3437f8aa73a246, 0x3eb711185a5568ff), + (0x3ab876889e88ff72, 0x3e4bee89a4622cb4), + (0xba6ac2419dbe0e2f, 0x3dc930ba3560eb64), + (0xb9b2124aaf27b632, 0x3d234925cfe9d5d8), + ]; + (&P, &Q) + } else { + // x <= 12 + // Polynomial generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static P: [(u64, u64); 12] = [ + (0xbc88aa87989ef5a1, 0xbfe2788b51df7906), + (0xbc7af1e1932b591c, 0x3fd4ee69b56504f9), + (0x3c740a2c04d19bfc, 0x3ff7406f9cf46140), + (0xbc917572eb9329ef, 0x3ff07369547283f5), + (0x3c54e46eaf6429e3, 0x3fd4301a4c091a22), + (0x3c3c3ba8aa15ca20, 0x3fa9426e448ee7db), + (0xbc1f041777b9f035, 0x3f70e2032a465789), + (0xbbb783cb47e19f83, 0x3f28099ad5f73d16), + (0xbb6932c40b32e5e0, 0x3ed175058b1e67e6), + (0x3b024c00ae6427d0, 0x3e677fd917aaa847), + (0x3a50b5029ff4eadf, 0x3de80bf02bf0e221), + (0x39e405e48a7d9326, 0x3d46c1a62ef66417), + ]; + // Generated by Wolfram Mathematica: + // <75,MaxIterations->100] + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + static Q: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c67856052188c26, 0x400243ec3166f349), + (0x3c2b34f0f808ddac, 0x3ffe806cb15a71b3), + (0xbc823b5d5bc54e38, 0x3fe8b21e296d1320), + (0xbc52f7423180111c, 0x3fc571b5d26833f9), + (0xbc33e19defee24d6, 0x3f94bf1ad662d38a), + (0x3beb180e8d55583a, 0x3f56723080074543), + (0xbb7d192d116623ad, 0x3f0a818d001404be), + (0x3b194b9889dea9d1, 0x3eb021f1a8b7f978), + (0x3a8ca7cbf623a001, 0x3e4224e2c71fae88), + (0xba4d8314f1a91e06, 0x3dbe48212e08d6f2), + (0xb9a210925f26ebb8, 0x3d15627ecb7e02ac), + ]; + (&P, &Q) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digammaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digammaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/digammaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/digammaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,416 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf}; +use crate::logs::simple_fast_log; +use crate::polyeval::{ + f_estrin_polyeval7, f_estrin_polyeval8, f_estrin_polyeval9, f_polyeval4, f_polyeval6, + f_polyeval10, +}; +use crate::tangent::cotpif_core; + +#[inline] +fn approx_digamma(x: f64) -> f64 { + if x <= 1. { + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval10( + x, + f64::from_bits(0xbfe2788cfc6fb619), + f64::from_bits(0x3fca347925788707), + f64::from_bits(0x3ff887e0f068df69), + f64::from_bits(0x3ff543446198b4d2), + f64::from_bits(0x3fe03e4455fbad95), + f64::from_bits(0x3fb994be8389e4f6), + f64::from_bits(0x3f84eb98b830c9b1), + f64::from_bits(0x3f4025193ac4ad97), + f64::from_bits(0x3ee18c1d683d866a), + f64::from_bits(0x3e457cb5b4a07c95), + ); + let p_den = f_estrin_polyeval9( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4003f5f42d95aca8), + f64::from_bits(0x4002f96e541d0513), + f64::from_bits(0x3ff22c34843313fa), + f64::from_bits(0x3fd33574180109bf), + f64::from_bits(0x3fa6c07b99ebb277), + f64::from_bits(0x3f6cdd7b8fa68926), + f64::from_bits(0x3f212b74d39e287f), + f64::from_bits(0x3ebabd247f366583), + ); + return p_num / p_den - 1. / x; + } else if x < 1.461632144 { + // exception + if x == 1.4616321325302124 { + return -1.2036052e-8; + } + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval9( + x, + f64::from_bits(0xbfe2788cfc6fb619), + f64::from_bits(0x3fd0ad221e8c3b8b), + f64::from_bits(0x3ff813be4dee2e90), + f64::from_bits(0x3ff2f64cbfa7d1a4), + f64::from_bits(0x3fd9a8c4798f426c), + f64::from_bits(0x3fb111a34898f6bf), + f64::from_bits(0x3f75dd3efac1e579), + f64::from_bits(0x3f272596b2582f0d), + f64::from_bits(0x3eb9b074f4ca6263), + ); + let p_den = f_estrin_polyeval9( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x40032fd3a1fe3a25), + f64::from_bits(0x40012969bcd7fef3), + f64::from_bits(0x3fee1a267ee7a97a), + f64::from_bits(0x3fcc1522178a69a6), + f64::from_bits(0x3f9bd89421334af0), + f64::from_bits(0x3f5b40bc3203df4c), + f64::from_bits(0x3f05ac6be0b79fac), + f64::from_bits(0x3e9047c3d8071f18), + ); + return p_num / p_den - 1. / x; + } else if x <= 2. { + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + x, + f64::from_bits(0xbfe2788cfc6fb613), + f64::from_bits(0x3fd690553caa1c6b), + f64::from_bits(0x3ff721cf4d9e008f), + f64::from_bits(0x3fee9f4096f34b09), + f64::from_bits(0x3fd055e88830fc71), + f64::from_bits(0x3f9e66bceee16960), + f64::from_bits(0x3f55d436778b3403), + f64::from_bits(0x3eeef6bc214819b3), + ); + let p_den = f_estrin_polyeval8( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4001e96eaab05729), + f64::from_bits(0x3ffcb1aa289077da), + f64::from_bits(0x3fe5499e89b757b6), + f64::from_bits(0x3fbee531a912bca9), + f64::from_bits(0x3f84d46f2121ceb7), + f64::from_bits(0x3f35abd7eb7440e6), + f64::from_bits(0x3ec43bf7c110aad1), + ); + return p_num / p_den - 1. / x; + } else if x <= 3. { + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + x, + f64::from_bits(0xbfe2788cfc63695f), + f64::from_bits(0x3fdb63791eb688ea), + f64::from_bits(0x3ff625ed84968583), + f64::from_bits(0x3fe900ea36e59e02), + f64::from_bits(0x3fc5319409f4fec6), + f64::from_bits(0x3f8b6e7cacff2a59), + f64::from_bits(0x3f34a7e591bf2af3), + f64::from_bits(0x3e9c323866d138db), + ); + let p_den = f_estrin_polyeval7( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4000ddf448e34181), + f64::from_bits(0x3ff87188f2414f79), + f64::from_bits(0x3fdeff74d18f811a), + f64::from_bits(0x3fb1a0cddeb3a320), + f64::from_bits(0x3f701050c1344800), + f64::from_bits(0x3f10480a4ea8cf57), + ); + return p_num / p_den - 1. / x; + } else if x <= 8. { + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + x, + f64::from_bits(0xbfe2788c3725fd5e), + f64::from_bits(0x3fde39f54e5a651a), + f64::from_bits(0x3ff56983b839b94f), + f64::from_bits(0x3fe60d6118d8fc08), + f64::from_bits(0x3fc0e889ace69a30), + f64::from_bits(0x3f844e10e399bd93), + f64::from_bits(0x3f3099741afda7cb), + f64::from_bits(0x3eb74a15144af8e9), + ); + let p_den = f_estrin_polyeval8( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4000409ed08c0553), + f64::from_bits(0x3ff63746cb6183e3), + f64::from_bits(0x3fda1196b1a75351), + f64::from_bits(0x3fab4ba9fad2d187), + f64::from_bits(0x3f67de6e6987e3a3), + f64::from_bits(0x3f0c9d85ca31182e), + f64::from_bits(0x3e8b269f154c8f12), + ); + return p_num / p_den - 1. / x; + } else if x <= 15. { + // Generated in Wolfram Mathematica: + // <75,MaxIterations->100] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_estrin_polyeval8( + x, + f64::from_bits(0xbfe272e75f131710), + f64::from_bits(0x3fe53fce507de081), + f64::from_bits(0x3ff182957d4f961a), + f64::from_bits(0x3fd6d1652dea00e9), + f64::from_bits(0x3fa45e16488abe0f), + f64::from_bits(0x3f5a52a8f3f3663f), + f64::from_bits(0x3ef5b767554d208e), + f64::from_bits(0x3e6d2393b100353d), + ); + let p_den = f_estrin_polyeval8( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3ffb1f295c6e5fc5), + f64::from_bits(0x3feb88eb913eb117), + f64::from_bits(0x3fc570f3aed83ff7), + f64::from_bits(0x3f8afe819fdfa5a5), + f64::from_bits(0x3f3a2cec9041f361), + f64::from_bits(0x3ed0549335964bb9), + f64::from_bits(0x3e3ebdcb0002d63e), + ); + return p_num / p_den - 1. / x; + } + // digamma asymptotic expansion + // digamma(x) ~ ln(z)+1/(2z)-sum_(n=1)^(infty)(Bernoulli(2n))/(2nz^(2n)) + // Generated in SageMath: + // var('x') + // + // def bernoulli_terms(x, N): + // S = 0 + // S += QQ(1)/QQ(2)/x + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / QQ(2*k))*x**(-2*k) + // S += term + // return S + // + // terms = bernoulli_terms(x, 5) + // + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(1, 13): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + let rcp = 1. / x; + let rcp_sqr = rcp * rcp; + let p = f_polyeval6( + rcp_sqr, + f64::from_bits(0x3fb5555555555555), + f64::from_bits(0xbf81111111111111), + f64::from_bits(0x3f70410410410410), + f64::from_bits(0xbf71111111111111), + f64::from_bits(0x3f7f07c1f07c1f08), + f64::from_bits(0xbf95995995995996), + ); + let v_log = simple_fast_log(x); + v_log - f_fmla(rcp, f64::from_bits(0x3fe0000000000000), p * rcp_sqr) +} + +/// Computes digamma(x) +pub fn f_digammaf(x: f32) -> f32 { + let xb = x.to_bits(); + // filter out exceptional cases + if xb >= 0xffu32 << 23 || xb == 0 { + if x.is_infinite() { + return if x.is_sign_negative() { + f32::NAN + } else { + f32::INFINITY + }; + } + if x.is_nan() { + return f32::NAN; + } + if xb == 0 { + return f32::INFINITY; + } + } + + let ax = x.to_bits() & 0x7fff_ffff; + + if ax <= 0x32abcc77u32 { + // |x| < 2e-8 + // digamma near where x -> 1 ~ Digamma[x] = -euler + O(x) + // considering identity Digamma[x+1] = Digamma[x] + 1/x, + // hence x < ulp(1) then x+1 ~= 1 that gives + // Digamma[x] = Digamma[x+1] - 1/x = -euler - 1/x + const EULER: f64 = f64::from_bits(0x3fe2788cfc6fb619); + return (-EULER - 1. / x as f64) as f32; + } else if ax <= 0x377ba882u32 { + // |x| <= 0.000015 + // Laurent series of digamma(x) + // Generated by SageMath: + // from mpmath import mp + // mp.prec = 150 + // R = RealField(150) + // var('x') + // def laurent_terms(x, N): + // S = 0 + // S += -1/x - R(mp.euler) + // S1 = 0 + // for k in range(1, N+1): + // zet = R(mp.zeta(k + 1)) + // term = zet*(-x)**k + // S1 += term + // return S - S1 + // + // terms = laurent_terms(x, 4) + // + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(1, 13): + // c = terms.coefficient(x, k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + const EULER: f64 = f64::from_bits(0x3fe2788cfc6fb619); + let dx = x as f64; + let start = -1. / dx; + let neg_dx = -dx; + let z = f_polyeval4( + neg_dx, + f64::from_bits(0x3ffa51a6625307d3), + f64::from_bits(0xbff33ba004f00621), + f64::from_bits(0x3ff151322ac7d848), + f64::from_bits(0xbff097418eca7cce), + ); + let r = f_fmla(z, dx, -EULER) + start; + return r as f32; + } + + let mut dx = x as f64; + let mut result: f64 = 0.; + if x < 0. { + // at negative integers it's inf + if is_integerf(x) { + return f32::NAN; + } + + // reflection Gamma(1-x) + Gamma(x) = Pi/tan(PI*x) + const PI: f64 = f64::from_bits(0x400921fb54442d18); + let cot_x_angle = -dx; + dx = 1. - dx; + result = PI * cotpif_core(cot_x_angle); + } + let approx = approx_digamma(dx); + result += approx; + result as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_digamma() { + assert_eq!(f_digammaf(-13.999000000012591), -996.9182); + assert_eq!(f_digammaf(15.3796425), 2.700182); + assert_eq!(f_digammaf(0.0005187988), -1928.1058); + assert_eq!(f_digammaf(0.0019531252), -512.574); + assert_eq!(f_digammaf(-96.353516), 6.1304626); + assert_eq!(f_digammaf(-31.06964), 17.582127); + assert_eq!(f_digammaf(-0.000000000000001191123), 839543830000000.); + assert_eq!(f_digammaf(f32::INFINITY), f32::INFINITY); + assert_eq!(f_digammaf(0.), f32::INFINITY); + assert_eq!(f_digammaf(-0.), f32::INFINITY); + assert!(f_digammaf(f32::NEG_INFINITY).is_nan()); + assert!(f_digammaf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_p.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_p.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_p.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_p.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0_exp; +use crate::double_double::DoubleDouble; +use crate::gamma::lgamma::lgamma_core; +use crate::logs::fast_log_d_to_dd; + +/// Regularized lower incomplete gamma +pub fn f_gamma_p(a: f64, x: f64) -> f64 { + let aa = a.to_bits(); + let ax = x.to_bits(); + + if aa >= 0x7ffu64 << 52 || aa == 0 || ax >= 0x7ffu64 << 52 || ax == 0 { + if (aa >> 63) != 0 || (ax >> 63) != 0 { + // |a| < 0 or |b| < 0 + return f64::NAN; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == infinity + return f64::INFINITY; + } + if x.is_infinite() { + // |x| == infinity + return f64::INFINITY; + } + return a + f64::NAN; + } + + let big = 4503599627370496.0; + let big_inv = 2.22044604925031308085e-16; + + const EPS: f64 = f64::EPSILON; + + let da = a; + let dx = x; + + let r = DoubleDouble::full_add_f64(-lgamma_core(a).0, -dx); + let ax = DoubleDouble::mul_f64_add(fast_log_d_to_dd(x), da, r).to_f64(); + + if ax <= -709.78271289338399 { + if a < x { + return 1.0; + } + return 0.0; + } + if ax >= 709.783 { + return f64::INFINITY; + } + + if x <= 1.0 || x <= a { + let mut r2 = DoubleDouble::new(0., da); + let mut c2 = DoubleDouble::new(0., 1.0); + let mut ans2 = DoubleDouble::new(0., 1.0); + let v_e = i0_exp(ax); + for _ in 0..200 { + r2 = DoubleDouble::full_add_f64(r2, 1.0); + c2 = DoubleDouble::quick_mult(DoubleDouble::from_f64_div_dd(dx, r2), c2); + c2 = DoubleDouble::from_exact_add(c2.hi, c2.lo); + ans2 = DoubleDouble::add(ans2, c2); + + if c2.hi / ans2.hi <= EPS { + break; + } + } + let v0 = DoubleDouble::quick_mult(v_e, ans2); + return DoubleDouble::div_dd_f64(v0, da).to_f64(); + } + + let v_e = i0_exp(ax); + + let mut y = 1.0 - da; + let mut z = dx + y + 1.0; + let mut c = 0i32; + + let mut p3 = 1.0; + let mut q3 = dx; + let mut p2 = dx + 1.0; + let mut q2 = z * dx; + let mut ans = p2 / q2; + + for _ in 0..200 { + y += 1.0; + z += 2.0; + c += 1; + let yc = y * c as f64; + + let p = p2 * z - p3 * yc; + let q = q2 * z - q3 * yc; + + p3 = p2; + p2 = p; + q3 = q2; + q2 = q; + + if p.abs() > big { + p3 *= big_inv; + p2 *= big_inv; + q3 *= big_inv; + q2 *= big_inv; + } + + if q != 0.0 { + let nextans = p / q; + let error = ((ans - nextans) / nextans).abs(); + ans = nextans; + + if error <= EPS { + break; + } + } + } + + DoubleDouble::mul_f64_add_f64(-v_e, ans, 1.0).to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_f_beta_pf() { + assert_eq!(f_gamma_p(1., f64::INFINITY), f64::INFINITY); + assert_eq!(f_gamma_p(23.421, 41.), 0.9988694746117834); + assert_eq!(f_gamma_p(0.764, 0.432123), 0.47752996395412817); + assert_eq!(f_gamma_p(0.421, 1.), 0.8727868618082306); + assert!(f_gamma_p(-1., 12.).is_nan()); + assert!(f_gamma_p(1., -12.).is_nan()); + assert!(f_gamma_p(f64::NAN, 12.).is_nan()); + assert!(f_gamma_p(1., f64::NAN).is_nan()); + assert_eq!(f_gamma_p(f64::INFINITY, f64::INFINITY), f64::INFINITY); + assert_eq!(f_gamma_p(f64::INFINITY, 5.32), f64::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_pf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_pf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_pf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_pf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,163 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::exponents::core_expdf; +use crate::gamma::lgamma_rf::lgamma_coref; +use crate::logs::fast_logf; + +/// Regularized lower incomplete gamma +pub fn f_gamma_pf(a: f32, x: f32) -> f32 { + let aa = a.to_bits(); + let ax = x.to_bits(); + + if aa >= 0xffu32 << 23 || aa == 0 || ax >= 0xffu32 << 23 || ax == 0 { + if (aa >> 31) != 0 || (ax >> 31) != 0 { + // |a| < 0 or |b| < 0 + return f32::NAN; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == infinity + return f32::INFINITY; + } + if x.is_infinite() { + // |x| == infinity + return f32::INFINITY; + } + return a + f32::NAN; + } + core_gamma_pf(a, x) as f32 +} + +#[inline] +pub(crate) fn core_gamma_pf(a: f32, x: f32) -> f64 { + const BIG: f64 = 4503599627370496.0; + const BIG_INV: f64 = 2.22044604925031308085e-16; + + const EPS: f64 = 1e-9; + + let da = a as f64; + let dx = x as f64; + + let ax = f_fmla(da, fast_logf(x), -dx - lgamma_coref(a).0); + if ax <= -104. { + if a < x { + return 1.0; + } + return 0.0; + } + if ax >= 89. { + return f64::INFINITY; + } + + if x <= 1.0 || x <= a { + let mut r2 = da; + let mut c2 = 1.0; + let mut ans2 = 1.0; + for _ in 0..200 { + r2 += 1.0; + c2 *= dx / r2; + ans2 += c2; + + if c2 / ans2 <= EPS { + break; + } + } + return core_expdf(ax) * ans2 / da; + } + + let mut y = 1.0 - da; + let mut z = dx + y + 1.0; + let mut c = 0i32; + + let mut p3 = 1.0; + let mut q3 = dx; + let mut p2 = dx + 1.0; + let mut q2 = z * dx; + let mut ans = p2 / q2; + + for _ in 0..200 { + y += 1.0; + z += 2.0; + c += 1; + let yc = y * c as f64; + + let p = p2 * z - p3 * yc; + let q = q2 * z - q3 * yc; + + p3 = p2; + p2 = p; + q3 = q2; + q2 = q; + + if p.abs() > BIG { + p3 *= BIG_INV; + p2 *= BIG_INV; + q3 *= BIG_INV; + q2 *= BIG_INV; + } + + if q != 0.0 { + let nextans = p / q; + let error = ((ans - nextans) / nextans).abs(); + ans = nextans; + + if error <= EPS { + break; + } + } + } + + f_fmla(-core_expdf(ax), ans, 1.0) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_f_beta_pf() { + assert_eq!(f_gamma_pf(23.421, 41.), 0.9988695); + assert_eq!(f_gamma_pf(0.764, 0.432123), 0.47752997); + assert_eq!(f_gamma_pf(0.421, 1.), 0.8727869); + assert!(f_gamma_pf(-1., 12.).is_nan()); + assert!(f_gamma_pf(1., -12.).is_nan()); + assert!(f_gamma_pf(f32::NAN, 12.).is_nan()); + assert!(f_gamma_pf(1., f32::NAN).is_nan()); + assert_eq!(f_gamma_pf(1., f32::INFINITY), f32::INFINITY); + assert_eq!(f_gamma_pf(f32::INFINITY, f32::INFINITY), f32::INFINITY); + assert_eq!(f_gamma_pf(f32::INFINITY, 5.32), f32::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_q.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_q.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_q.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_q.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,241 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bessel::i0_exp; +use crate::double_double::DoubleDouble; +use crate::gamma::lgamma::lgamma_core; +use crate::logs::fast_log_d_to_dd; + +fn core_gamma_p(a: f64, x: f64) -> (DoubleDouble, Option) { + const BIG: f64 = 4503599627370496.0; + const BIG_INV: f64 = 2.22044604925031308085e-16; + + const EPS: f64 = f64::EPSILON; + + let da = a; + let dx = x; + + let r = DoubleDouble::full_add_f64(-lgamma_core(a).0, -dx); + let ax = DoubleDouble::mul_f64_add(fast_log_d_to_dd(x), da, r).to_f64(); + + if ax <= -709.78271289338399 { + if a < x { + return (DoubleDouble::default(), Some(1.0)); + } + return (DoubleDouble::default(), Some(0.0)); + } + if ax >= 709.783 { + return (DoubleDouble::default(), Some(f64::INFINITY)); + } + + if x <= 1.0 || x <= a { + let mut r2 = DoubleDouble::new(0., da); + let mut c2 = DoubleDouble::new(0., 1.0); + let mut ans2 = DoubleDouble::new(0., 1.0); + let v_e = i0_exp(ax); + for _ in 0..200 { + r2 = DoubleDouble::full_add_f64(r2, 1.0); + c2 = DoubleDouble::quick_mult(DoubleDouble::from_f64_div_dd(dx, r2), c2); + c2 = DoubleDouble::from_exact_add(c2.hi, c2.lo); + ans2 = DoubleDouble::add(ans2, c2); + + if c2.hi / ans2.hi <= EPS { + break; + } + } + let v0 = DoubleDouble::quick_mult(v_e, ans2); + return (DoubleDouble::div_dd_f64(v0, da), None); + } + + let v_e = i0_exp(ax); + + let mut y = 1.0 - da; + let mut z = dx + y + 1.0; + let mut c = 0i32; + + let mut p3 = 1.0; + let mut q3 = dx; + let mut p2 = dx + 1.0; + let mut q2 = z * dx; + let mut ans = p2 / q2; + + for _ in 0..200 { + y += 1.0; + z += 2.0; + c += 1; + let yc = y * c as f64; + + let p = p2 * z - p3 * yc; + let q = q2 * z - q3 * yc; + + p3 = p2; + p2 = p; + q3 = q2; + q2 = q; + + if p.abs() > BIG { + p3 *= BIG_INV; + p2 *= BIG_INV; + q3 *= BIG_INV; + q2 *= BIG_INV; + } + + if q != 0.0 { + let nextans = p / q; + let error = ((ans - nextans) / nextans).abs(); + ans = nextans; + + if error <= EPS { + break; + } + } + } + + (DoubleDouble::mul_f64_add_f64(-v_e, ans, 1.0), None) +} + +/// Regularized upper incomplete gamma +pub fn f_gamma_q(a: f64, x: f64) -> f64 { + let aa = a.to_bits(); + let ax = x.to_bits(); + + if aa >= 0x7ffu64 << 52 || aa == 0 || ax >= 0x7ffu64 << 52 || ax == 0 { + if (aa >> 63) != 0 || (ax >> 63) != 0 { + // |a| < 0 or |b| < 0 + return f64::NAN; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == infinity + return f64::INFINITY; + } + if x.is_infinite() { + // |x| == infinity + return f64::INFINITY; + } + return a + f64::NAN; + } + + const EPS: f64 = f64::EPSILON; + + const BIG: f64 = 4503599627370496.0; + const BIG_INV: f64 = 2.22044604925031308085e-16; + + if x < 1.0 || x <= a { + let gamma_p = core_gamma_p(a, x); + return match gamma_p.1 { + None => { + let z = DoubleDouble::full_add_f64(-gamma_p.0, 1.); + z.to_f64() + } + Some(v) => v, + }; + } + + let da = a; + let dx = x; + + let r = DoubleDouble::full_add_f64(-lgamma_core(a).0, -dx); + let ax = DoubleDouble::mul_f64_add(fast_log_d_to_dd(x), da, r).to_f64(); + + if ax <= -709.78271289338399 { + if a < x { + return 1.0; + } + return 0.0; + } + if ax >= 709.783 { + return f64::INFINITY; + } + + let mut y = 1.0 - da; + let mut z = dx + y + 1.0; + let mut c = 0.0; + let mut pkm2 = 1.0; + let mut qkm2 = dx; + let mut pkm1 = dx + 1.0; + let mut qkm1 = z * dx; + let mut ans = pkm1 / qkm1; + for _ in 0..200 { + y += 1.0; + z += 2.0; + c += 1.0; + let yc = y * c; + let pk = pkm1 * z - pkm2 * yc; + let qk = qkm1 * z - qkm2 * yc; + + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if pk.abs() > BIG { + pkm2 *= BIG_INV; + pkm1 *= BIG_INV; + qkm2 *= BIG_INV; + qkm1 *= BIG_INV; + } + + if qk != 0.0 { + let r = pk / qk; + let t = ((ans - r) / r).abs(); + ans = r; + + if t <= EPS { + break; + } + } + } + let v_exp = i0_exp(ax); + DoubleDouble::quick_mult_f64(v_exp, ans).to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_f_beta_pf() { + assert_eq!(f_gamma_q(1., f64::INFINITY), f64::INFINITY); + assert_eq!(f_gamma_q(23.421, 41.), 0.0011305253882165434); + assert_eq!(f_gamma_q(0.764, 0.432123), 0.5224700360458718); + assert_eq!(f_gamma_q(0.421, 1.), 0.12721313819176905); + assert!(f_gamma_q(-1., 12.).is_nan()); + assert!(f_gamma_q(1., -12.).is_nan()); + assert!(f_gamma_q(f64::NAN, 12.).is_nan()); + assert!(f_gamma_q(1., f64::NAN).is_nan()); + assert_eq!(f_gamma_q(f64::INFINITY, f64::INFINITY), f64::INFINITY); + assert_eq!(f_gamma_q(f64::INFINITY, 5.32), f64::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_qf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_qf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_qf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/gamma_qf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::exponents::core_expdf; +use crate::gamma::gamma_pf::core_gamma_pf; +use crate::gamma::lgamma_rf::lgamma_coref; +use crate::logs::fast_logf; + +/// Regularized upper incomplete gamma +pub fn f_gamma_qf(a: f32, x: f32) -> f32 { + let aa = a.to_bits(); + let ax = x.to_bits(); + + if aa >= 0xffu32 << 23 || aa == 0 || ax >= 0xffu32 << 23 || ax == 0 { + if (aa >> 31) != 0 || (ax >> 31) != 0 { + // |a| < 0 or |b| < 0 + return f32::NAN; + } + if aa.wrapping_shl(1) == 0 { + // |a| == 0 + return 1.0; + } + if ax.wrapping_shl(1) == 0 { + // |x| == 0 + return 0.; + } + if a.is_infinite() { + // |a| == infinity + return f32::INFINITY; + } + if x.is_infinite() { + // |x| == infinity + return f32::INFINITY; + } + return a + f32::NAN; + } + + const EPS: f64 = 1e-9; + + const BIG: f64 = 4503599627370496.0; + const BIG_INV: f64 = 2.22044604925031308085e-16; + + if x < 1.0 || x <= a { + return (1.0 - core_gamma_pf(a, x)) as f32; + } + + let da = a as f64; + let dx = x as f64; + + let ax = f_fmla(da, fast_logf(x), -dx - lgamma_coref(a).0); + if ax <= -104. { + if a < x { + return 0.0; + } + return 1.0; + } + if ax >= 89. { + return f32::INFINITY; + } + + let mut y = 1.0 - da; + let mut z = dx + y + 1.0; + let mut c = 0.0; + let mut pkm2 = 1.0; + let mut qkm2 = dx; + let mut pkm1 = dx + 1.0; + let mut qkm1 = z * dx; + let mut ans = pkm1 / qkm1; + for _ in 0..200 { + y += 1.0; + z += 2.0; + c += 1.0; + let yc = y * c; + let pk = pkm1 * z - pkm2 * yc; + let qk = qkm1 * z - qkm2 * yc; + + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if pk.abs() > BIG { + pkm2 *= BIG_INV; + pkm1 *= BIG_INV; + qkm2 *= BIG_INV; + qkm1 *= BIG_INV; + } + + if qk != 0.0 { + let r = pk / qk; + let t = ((ans - r) / r).abs(); + ans = r; + + if t <= EPS { + break; + } + } + } + (ans * core_expdf(ax)) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_f_beta_qf() { + assert_eq!(f_gamma_qf(23.421, 41.), 0.001130525); + assert_eq!(f_gamma_qf(0.764, 0.432123), 0.52247006); + assert_eq!(f_gamma_qf(0.421, 1.), 0.12721314); + assert!(f_gamma_qf(-1., 12.).is_nan()); + assert!(f_gamma_qf(1., -12.).is_nan()); + assert!(f_gamma_qf(f32::NAN, 12.).is_nan()); + assert!(f_gamma_qf(1., f32::NAN).is_nan()); + assert_eq!(f_gamma_qf(1., f32::INFINITY), f32::INFINITY); + assert_eq!(f_gamma_qf(f32::INFINITY, f32::INFINITY), f32::INFINITY); + assert_eq!(f_gamma_qf(f32::INFINITY, 5.32), f32::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1129 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integer, is_odd_integer}; +use crate::double_double::DoubleDouble; +use crate::f_log; +use crate::logs::{fast_log_d_to_dd, fast_log_dd, log_dd}; +use crate::polyeval::{f_polyeval4, f_polyeval5, f_polyeval6, f_polyeval10}; +use crate::rounding::CpuFloor; +use crate::sincospi::f_fast_sinpi_dd; + +#[inline] +fn apply_sign_and_sum(z: DoubleDouble, parity: f64, s: DoubleDouble) -> DoubleDouble { + if parity >= 0. { + z + } else { + DoubleDouble::full_dd_sub(s, z) + } +} + +#[inline] +fn apply_sign_and_sum_quick(z: DoubleDouble, parity: f64, s: DoubleDouble) -> DoubleDouble { + if parity >= 0. { + z + } else { + DoubleDouble::quick_dd_sub(s, z) + } +} + +#[cold] +fn lgamma_0p5(dx: f64, v_log: DoubleDouble, f_res: DoubleDouble, sum_parity: f64) -> DoubleDouble { + // Log[Gamma[x+1]] + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 9] = [ + (0x349d90fba23c9118, 0xb7f552eee31fa8d2), + (0x3c56cb95ec26b8b0, 0xbfe2788cfc6fb619), + (0xbc98554b6e8ebe5c, 0xbff15a4f25fcc40b), + (0x3c51b37126e8f9ee, 0xbfc2d93ef9720645), + (0xbc85a532dd358f5d, 0x3fec506397ef590a), + (0x3c7dc535e77ac796, 0x3fe674f6812154ca), + (0x3c4ff02dbae30f4d, 0x3fc9aacc2b0173a0), + (0xbc3aa29e4d4e6c9d, 0x3f95d8cbe81572b6), + (0x3bed03960179ad28, 0x3f429e0ecfd47eb2), + ]; + + let mut p_num = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[8]), + dx, + DoubleDouble::from_bit_pair(P[7]), + ); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 8] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc93d5d3e154eb7a, 0x400a6e37d475364e), + (0xbcb465441d96e6c2, 0x401112f3f3b083a7), + (0x3ca1b893e8188325, 0x4005cbfc6085847f), + (0xbc8608a5840fb86b, 0x3fec920358d35f3a), + (0x3c5dc5b89a3624bd, 0x3fc21011cbbc6923), + (0x3bfbe999bea0b965, 0x3f822ae49ffa14ce), + (0x3b90cb3bd523bf32, 0x3f20d6565fe86116), + ]; + + let mut p_den = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + dx, + DoubleDouble::from_bit_pair(Q[6]), + ); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + let v0 = DoubleDouble::full_dd_sub(DoubleDouble::div(p_num, p_den), v_log); + apply_sign_and_sum(v0, sum_parity, f_res) +} + +#[cold] +fn lgamma_0p5_to_1( + dx: f64, + v_log: DoubleDouble, + f_res: DoubleDouble, + sum_parity: f64, +) -> DoubleDouble { + // Log[Gamma[x+1]] + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 10] = [ + (0xb967217bfcc647c2, 0xbcc9b2c47481ff4f), + (0xbc7eff78623354d7, 0xbfe2788cfc6fb552), + (0xbc9886c6f42886e0, 0xbff3c6a7f676cf4c), + (0x3c77ed956ff8e661, 0xbfdaf57ee2a64253), + (0x3c8723f3a5de4fd5, 0x3feb961a3d8bbe89), + (0x3c8848ddf2e2726f, 0x3fedc9f11015d4ca), + (0xbc799f3b76da571b, 0x3fd7ac6e82c07787), + (0xbc5cb131b054a5f5, 0x3fb103e7e288f4da), + (0x3bfe93ab961d39a4, 0x3f74789410ab2cf5), + (0x3babcb1e8a573475, 0x3f1d74e78621d316), + ]; + + let mut p_num = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + dx, + DoubleDouble::from_bit_pair(P[8]), + ); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[7])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbca99871cf68ff41, 0x400c87945e972c56), + (0xbc8292764aa01c02, 0x401477d734273be4), + (0xbcaf0f1758e16cb3, 0x400e53c84c87f686), + (0xbc901825b170e576, 0x3ff8c99df9c66865), + (0x3c78af0564323160, 0x3fd629441413e902), + (0x3c3293dd176164f3, 0x3fa42e466fd1464e), + (0xbbf3fbc18666280b, 0x3f5f9cd4c60c4e7d), + (0xbb4036ba7be37458, 0x3efb2d3ed43aab6f), + (0xbaf7a3a7d5321f53, 0xbe665e3fadf143a6), + ]; + + let mut p_den = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[9]), + dx, + DoubleDouble::from_bit_pair(Q[8]), + ); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[7])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + let v0 = DoubleDouble::full_dd_sub(DoubleDouble::div(p_num, p_den), v_log); + apply_sign_and_sum(v0, sum_parity, f_res) +} + +#[cold] +fn lgamma_1_to_4( + dx: f64, + v_log: DoubleDouble, + f_res: DoubleDouble, + sum_parity: f64, +) -> DoubleDouble { + // Log[Gamma[x+1]] + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 14] = [ + (0x398e8eb32d541d21, 0xbcf55335b06a5df1), + (0xbc60fc919ad95ffb, 0xbfe2788cfc6fb2c4), + (0x3c98d8e5e64ea307, 0xbffb5e5c82450af5), + (0x3c778a3bdabcdb1f, 0xbff824ecfcecbcd5), + (0x3c77768d59db11a0, 0x3fd6a097c5fa0036), + (0x3c9f4a74ad888f08, 0x3ff9297ba86cc14e), + (0xbc97e1e1819d78bd, 0x3ff3dd0025109756), + (0xbc6f1b00b6ce8a2a, 0x3fdfded97a03f2f3), + (0xbc55487a80e322fe, 0x3fbd5639f2258856), + (0x3bede86c7e0323ce, 0x3f8f7261ccd00da5), + (0x3bcde1ee8e81b7b5, 0x3f52fbfb5a8c7221), + (0x3ba8ed54c3db7fde, 0x3f07d48361a072b6), + (0xbb4c30e2cdaa48f2, 0x3eaa8661f0313183), + (0xbac575d303dd9b93, 0x3e3205d52df415e6), + ]; + + let mut p_num = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[13]), + dx, + DoubleDouble::from_bit_pair(P[12]), + ); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[11])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[10])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[9])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[8])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[7])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 14] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cbde8d771be8aba, 0x40118da297250deb), + (0xbccdbba67547f5dc, 0x4020589156c4058c), + (0x3caca498a3ea822e, 0x4020e9442d441e22), + (0xbca6a7d3651d1b42, 0x40156480b1dc22fe), + (0x3ca79ba727e70ad6, 0x40013006d1e5d08c), + (0x3c8c2b824cfce390, 0x3fe1b0eb2f75de3f), + (0xbc5208ab1ad4d8e0, 0x3fb709e145993376), + (0xbc21d64934aab809, 0x3f825ee5a8799658), + (0x3bc29531f5a4518d, 0x3f40ed532b6bffdd), + (0x3b994fb11dace77e, 0x3ef052da92364c6d), + (0xbb1f0fb3869f715e, 0x3e8b6bbbe7aae5eb), + (0x3a81d8373548a8a8, 0x3e09b5304c6d77ba), + (0x3992e1e6b163e1f7, 0xbd50eee2d9d4e7b9), + ]; + + let mut p_den = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[13]), + dx, + DoubleDouble::from_bit_pair(Q[12]), + ); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[11])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[10])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[9])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[8])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[7])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + let mut k = DoubleDouble::div(p_num, p_den); + k = DoubleDouble::from_exact_add(k.hi, k.lo); + let v0 = DoubleDouble::full_dd_sub(k, v_log); + apply_sign_and_sum(v0, sum_parity, f_res) +} + +#[cold] +fn lgamma_4_to_12(dx: f64, f_res: DoubleDouble, sum_parity: f64) -> DoubleDouble { + // Log[Gamma[x+1]] + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 11] = [ + (0x3c9a767426b2d1e8, 0x400e45c3573057bb), + (0xbcccc22bbae40ac4, 0x403247d3a1b9b0e9), + (0xbc82c1d4989e7813, 0x3ffe955db10dd744), + (0x3cb4669cf9238f48, 0xc036a67a52498757), + (0x3cb4c4039d4da434, 0xc01a8d26ec4b2f7b), + (0x3ca43834ea54b437, 0x400c92b79f85b787), + (0x3c930746944a1bc1, 0x3ff8b3afe3e0525c), + (0xbc68499f7a8b0f87, 0x3fc8059ff9cb3e10), + (0x3c0e16d9f08b7e18, 0x3f81c282c77a3862), + (0xbbcec78600b42cd0, 0x3f22fe2577cf1017), + (0x3b1c222faf24d4a1, 0x3ea5511d126ad883), + ]; + + let mut p_num = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[10]), + dx, + DoubleDouble::from_bit_pair(P[9]), + ); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[8])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[7])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[6])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[5])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[4])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[3])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[2])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[1])); + p_num = DoubleDouble::mul_f64_add(p_num, dx, DoubleDouble::from_bit_pair(P[0])); + + const Q: [(u64, u64); 11] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3ccaa60b201a29f2, 0x40288b76f18d51d8), + (0xbcd831f5042551f9, 0x403d383173e1839d), + (0x3cb2b77730673e36, 0x4037e8a6dda469df), + (0x3cb8c229012ae276, 0x40207ddd53aa3098), + (0xbc8aba961299355d, 0x3ff4c90761849336), + (0xbc3e844b2b1f0edb, 0x3fb832c6fba5ff26), + (0xbbc70261cd94cb90, 0x3f68b185e16f05c1), + (0xbb6c1c2dfe90e592, 0x3f0303509bbb9cf8), + (0xbb0f160d6b147ae5, 0x3e7d1bd86b15f52e), + (0x3a5714448b9c17d2, 0xbdba82d4d2ccf533), + ]; + + let mut p_den = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[10]), + dx, + DoubleDouble::from_bit_pair(Q[9]), + ); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[8])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[7])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[6])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[5])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[4])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[3])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[2])); + p_den = DoubleDouble::mul_f64_add(p_den, dx, DoubleDouble::from_bit_pair(Q[1])); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + apply_sign_and_sum(DoubleDouble::div(p_num, p_den), sum_parity, f_res) +} + +#[cold] +fn stirling_accurate(dx: f64, parity: f64, f_res: DoubleDouble) -> DoubleDouble { + let y_recip = DoubleDouble::from_quick_recip(dx); + let y_sqr = DoubleDouble::mult(y_recip, y_recip); + // Bernoulli coefficients generated by SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / (2*k*(2*k-1))) * x**((2*k-1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 10) + const BERNOULLI_C: [(u64, u64); 10] = [ + (0x3c55555555555555, 0x3fb5555555555555), + (0x3bff49f49f49f49f, 0xbf66c16c16c16c17), + (0x3b8a01a01a01a01a, 0x3f4a01a01a01a01a), + (0x3befb1fb1fb1fb20, 0xbf43813813813814), + (0x3be5c3a9ce01b952, 0x3f4b951e2b18ff23), + (0x3bff82553c999b0e, 0xbf5f6ab0d9993c7d), + (0x3c10690690690690, 0x3f7a41a41a41a41a), + (0x3c21efcdab896745, 0xbf9e4286cb0f5398), + (0xbc279e2405a71f88, 0x3fc6fe96381e0680), + (0x3c724246319da678, 0xbff6476701181f3a), + ]; + let bernoulli_poly = f_polyeval10( + y_sqr, + DoubleDouble::from_bit_pair(BERNOULLI_C[0]), + DoubleDouble::from_bit_pair(BERNOULLI_C[1]), + DoubleDouble::from_bit_pair(BERNOULLI_C[2]), + DoubleDouble::from_bit_pair(BERNOULLI_C[3]), + DoubleDouble::from_bit_pair(BERNOULLI_C[4]), + DoubleDouble::from_bit_pair(BERNOULLI_C[5]), + DoubleDouble::from_bit_pair(BERNOULLI_C[6]), + DoubleDouble::from_bit_pair(BERNOULLI_C[7]), + DoubleDouble::from_bit_pair(BERNOULLI_C[8]), + DoubleDouble::from_bit_pair(BERNOULLI_C[9]), + ); + + // Log[Gamma(x)] = x*log(x) - x + 1/2*Log(2*PI/x) + bernoulli_terms + const LOG2_PI_OVER_2: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc865b5a1b7ff5df, 0x3fed67f1c864beb5)); + let mut log_gamma = DoubleDouble::add( + DoubleDouble::mul_add_f64(bernoulli_poly, y_recip, -dx), + LOG2_PI_OVER_2, + ); + let dy_log = log_dd(dx); + log_gamma = DoubleDouble::mul_add( + DoubleDouble::from_exact_add(dy_log.hi, dy_log.lo), + DoubleDouble::from_full_exact_add(dx, -0.5), + log_gamma, + ); + apply_sign_and_sum(log_gamma, parity, f_res) +} + +/// due to log(x) leading terms cancellation happens around 2, +/// hence we're using different approximation around LogGamma(2). +/// Coefficients are ill-conditioned here so Minimal Newton form is used +#[cold] +fn lgamma_around_2(x: f64, parity: f64, f_res: DoubleDouble) -> DoubleDouble { + let dx = DoubleDouble::from_full_exact_sub(x, 2.); + + // Generated by Wolfram Mathematica: + // <90] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // x0=SetPrecision[2,90]; + // NumberForm[Series[num,{x,x0,9}],ExponentFunction->(Null&)] + // coeffs=Table[SeriesCoefficient[num,{x,x0,k}],{k,0,10}]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=Table[SeriesCoefficient[den,{x,x0,k}],{k,0,10}]; + // NumberForm[Series[den,{x,x0,9}],ExponentFunction->(Null&)] + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + const P: [(u64, u64); 10] = [ + (0xbd8ef0f02676337a, 0x41000f48befb1b70), + (0x3dae9e186ab39649, 0x411aeb5de0ba157d), + (0xbdcfe4bca8f58298, 0x4122d673e1f69e2c), + (0x3db1e3de8e53cfce, 0x411d0fdd168e56a8), + (0x3d9114d199dacd01, 0x410b4a1ce996f910), + (0x3d9172663132c0b6, 0x40f02d95ceca2c8a), + (0x3d52988b7d30cfd3, 0x40c83a4c6e145abc), + (0xbd14327346a3db7b, 0x409632fe8dc80419), + (0x3cfe9f975e5e9984, 0x4057219509ba1d62), + (0xbca0fdd3506bf429, 0x4007988259d795c4), + ]; + + let dx2 = dx * dx; + let dx4 = dx2 * dx2; + let dx8 = dx4 * dx4; + + let p0 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(P[1]), + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(P[3]), + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(P[5]), + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(P[7]), + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(P[9]), + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::quick_mul_add(dx2, p1, p0); + let q1 = DoubleDouble::quick_mul_add(dx2, p3, p2); + + let r0 = DoubleDouble::quick_mul_add(dx4, q1, q0); + let mut p_num = DoubleDouble::quick_mul_add(dx8, p4, r0); + p_num = DoubleDouble::quick_mult(p_num, dx); + + const Q: [(u64, u64); 11] = [ + (0x3da0f8e36723f959, 0x4112fe27249fc6f1), + (0xbdc289e4a571ddb8, 0x412897be1a39b97b), + (0xbdb8d18ab489860f, 0x412b4fcbc6d9cb44), + (0x3da0550c9f65a5ef, 0x4120fe765c0f6a79), + (0xbd90a121e792bf7f, 0x4109fa9eaa0f816a), + (0xbd7168de8e78812e, 0x40e9269d002372a5), + (0x3d4e4d052cd6982a, 0x40beab7f948d82f0), + (0xbd0cebe53b7e81bf, 0x4086a91c01d7241f), + (0xbcd2edf097020841, 0x4042a780e9d1b74b), + (0xbc73d1a40910845f, 0x3fecd007ff47224f), + (0xbc06e4de631047f3, 0x3f7ad97267872491), + ]; + + let q0 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let q1 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let q2 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + let q3 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(Q[7]), + DoubleDouble::from_bit_pair(Q[6]), + ); + let q4 = DoubleDouble::quick_mul_add( + dx, + DoubleDouble::from_bit_pair(Q[9]), + DoubleDouble::from_bit_pair(Q[8]), + ); + + let r0 = DoubleDouble::quick_mul_add(dx2, q1, q0); + let r1 = DoubleDouble::quick_mul_add(dx2, q3, q2); + + let s0 = DoubleDouble::quick_mul_add(dx4, r1, r0); + let s1 = DoubleDouble::quick_mul_add(dx2, DoubleDouble::from_bit_pair(Q[10]), q4); + let p_den = DoubleDouble::quick_mul_add(dx8, s1, s0); + apply_sign_and_sum_quick(DoubleDouble::div(p_num, p_den), parity, f_res) +} + +#[inline] +pub(crate) fn lgamma_core(x: f64) -> (DoubleDouble, i32) { + let ax = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + let dx = ax; + + let is_positive = x.is_sign_positive(); + let mut sum_parity = 1f64; + + let mut signgam = 1i32; + + if ax < f64::EPSILON { + if !is_positive { + signgam = -1i32; + } + return (DoubleDouble::new(0., -f_log(dx)), signgam); + } + + let mut f_res = DoubleDouble::default(); + // For negative x, since (G is gamma function) + // -x*G(-x)*G(x) = pi/sin(pi*x), + // we have + // G(x) = pi/(sin(pi*x)*(-x)*G(-x)) + // since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 + // Hence, for x<0, signgam = sign(sin(pi*x)) and + // lgamma(x) = log(|Gamma(x)|) = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); + if !is_positive { + let y1 = ax.cpu_floor(); + let fraction = ax - y1; // excess over the boundary + + let a = f_fast_sinpi_dd(fraction); + + sum_parity = -1.; + const LOG_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3c67abf2ad8d5088, 0x3ff250d048e7a1bd)); + let mut den = DoubleDouble::quick_mult_f64(a, dx); + den = DoubleDouble::from_exact_add(den.hi, den.lo); + f_res = fast_log_dd(den); + f_res = DoubleDouble::from_exact_add(f_res.hi, f_res.lo); + f_res = DoubleDouble::quick_dd_sub(LOG_PI, f_res); + + // gamma(x) is negative in (-2n-1,-2n), thus when fx is odd + let is_odd = (!is_odd_integer(y1)) as i32; + signgam = 1 - (is_odd << 1); + } + + if ax <= 0.5 { + // Log[Gamma[x + 1]] poly generated by Wolfram + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let ps_num = f_polyeval4( + dx, + f64::from_bits(0x3fea8287cc94dc31), + f64::from_bits(0x3fe000cbc75a2ab7), + f64::from_bits(0x3fba69bac2495765), + f64::from_bits(0x3f78eb3984eb55ee), + ); + let ps_den = f_polyeval5( + dx, + f64::from_bits(0x3ffee073402b349e), + f64::from_bits(0x3fe04c62232d12ec), + f64::from_bits(0x3fad09ff23ffb930), + f64::from_bits(0x3f5c253f6e8af7d2), + f64::from_bits(0xbee18a68b4ed9516), + ); + let mut p_num = DoubleDouble::f64_mul_f64_add( + ps_num, + dx, + DoubleDouble::from_bit_pair((0x3c4d671927a50f5b, 0x3fb184cdffda39b0)), + ); + p_num = DoubleDouble::mul_f64_add( + p_num, + dx, + DoubleDouble::from_bit_pair((0xbc8055e20f9945f5, 0xbfedba6e22cced8a)), + ); + p_num = DoubleDouble::mul_f64_add( + p_num, + dx, + DoubleDouble::from_bit_pair((0x3c56cc8e006896be, 0xbfe2788cfc6fb619)), + ); + p_num = DoubleDouble::mul_f64_add( + p_num, + dx, + DoubleDouble::from_bit_pair((0x34c1e175ecd02e7e, 0xb84ed528d8df1c88)), + ); + let mut p_den = DoubleDouble::f64_mul_f64_add( + ps_den, + dx, + DoubleDouble::from_bit_pair((0xbc70ab0b3b299408, 0x400c16483bffaf57)), + ); + p_den = DoubleDouble::mul_f64_add( + p_den, + dx, + DoubleDouble::from_bit_pair((0xbcac74fbe90fa7cb, 0x400846598b0e4750)), + ); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + let d_log = fast_log_d_to_dd(dx); + let v0 = DoubleDouble::sub(DoubleDouble::div(p_num, p_den), d_log); + let l_res = f_res; + f_res = apply_sign_and_sum_quick(v0, sum_parity, f_res); + let err = f_fmla( + f_res.hi.abs(), + f64::from_bits(0x3c56a09e667f3bcd), // 2^-57.5 + f64::from_bits(0x3c20000000000000), // 2^-61 + ); + let ub = f_res.hi + (f_res.lo + err); + let lb = f_res.hi + (f_res.lo - err); + if ub == lb { + return (f_res, signgam); + } + return (lgamma_0p5(dx, d_log, l_res, sum_parity), signgam); + } else if ax <= 1. { + let distance_to_2 = ax - 2.; + if distance_to_2.abs() < 0.05 { + return (lgamma_around_2(ax, sum_parity, f_res), signgam); + } + + // Log[Gamma[x+1]] + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + + const P: [(u64, u64); 10] = [ + (0xb967217bfcc647c2, 0xbcc9b2c47481ff4f), + (0xbc7eff78623354d7, 0xbfe2788cfc6fb552), + (0xbc9886c6f42886e0, 0xbff3c6a7f676cf4c), + (0x3c77ed956ff8e661, 0xbfdaf57ee2a64253), + (0x3c8723f3a5de4fd5, 0x3feb961a3d8bbe89), + (0x3c8848ddf2e2726f, 0x3fedc9f11015d4ca), + (0xbc799f3b76da571b, 0x3fd7ac6e82c07787), + (0xbc5cb131b054a5f5, 0x3fb103e7e288f4da), + (0x3bfe93ab961d39a4, 0x3f74789410ab2cf5), + (0x3babcb1e8a573475, 0x3f1d74e78621d316), + ]; + + let ps_den = f_polyeval4( + dx, + f64::from_bits(0x3fa42e466fd1464e), + f64::from_bits(0x3f5f9cd4c60c4e7d), + f64::from_bits(0x3efb2d3ed43aab6f), + f64::from_bits(0xbe665e3fadf143a6), + ); + + let dx2 = DoubleDouble::from_exact_mult(dx, dx); + let dx4 = DoubleDouble::quick_mult(dx2, dx2); + let dx8 = DoubleDouble::quick_mult(dx4, dx4); + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + dx, + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + dx, + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + dx, + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + dx, + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + dx, + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::mul_add(dx2, p1, p0); + let q1 = DoubleDouble::mul_add(dx2, p3, p2); + + let r0 = DoubleDouble::mul_add(dx4, q1, q0); + let p_num = DoubleDouble::mul_add(dx8, p4, r0); + + let mut p_den = DoubleDouble::f64_mul_f64_add( + ps_den, + dx, + DoubleDouble::from_bit_pair((0x3c78af0564323160, 0x3fd629441413e902)), + ); + p_den = DoubleDouble::mul_f64_add( + p_den, + dx, + DoubleDouble::from_bit_pair((0xbc901825b170e576, 0x3ff8c99df9c66865)), + ); + p_den = DoubleDouble::mul_f64_add( + p_den, + dx, + DoubleDouble::from_bit_pair((0xbcaf0f1758e16cb3, 0x400e53c84c87f686)), + ); + p_den = DoubleDouble::mul_f64_add( + p_den, + dx, + DoubleDouble::from_bit_pair((0xbc8292764aa01c02, 0x401477d734273be4)), + ); + p_den = DoubleDouble::mul_f64_add( + p_den, + dx, + DoubleDouble::from_bit_pair((0xbca99871cf68ff41, 0x400c87945e972c56)), + ); + p_den = DoubleDouble::mul_f64_add_f64(p_den, dx, f64::from_bits(0x3ff0000000000000)); + let d_log = fast_log_d_to_dd(dx); + let v0 = DoubleDouble::sub(DoubleDouble::div(p_num, p_den), d_log); + let l_res = f_res; + f_res = apply_sign_and_sum_quick(v0, sum_parity, f_res); + let err = f_fmla( + f_res.hi.abs(), + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3c20000000000000), // 2^-61 + ); + let ub = f_res.hi + (f_res.lo + err); + let lb = f_res.hi + (f_res.lo - err); + if ub == lb { + return (f_res, signgam); + } + return (lgamma_0p5_to_1(dx, d_log, l_res, sum_parity), signgam); + } else if ax <= 4. { + let distance_to_2 = ax - 2.; + if distance_to_2.abs() < 0.05 { + return (lgamma_around_2(ax, sum_parity, f_res), signgam); + } + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + const P: [(u64, u64); 10] = [ + (0x3a8ea8c71173ba1f, 0xbde8c6619bc06d43), + (0x3c8f2502d288b7e1, 0xbfe2788cfb0f13f7), + (0xbc873b33ddea3333, 0xbfebd290912f0200), + (0x3c223d47fd7b2e30, 0x3fb52786e934492b), + (0xbc8f4e91d7f48aa5, 0x3fe8204c68bc38f4), + (0x3c5356ff82d857c6, 0x3fde676d587374a4), + (0x3c5d8deef0e6c21f, 0x3fbef2e284faabe5), + (0xbc24ea363b4779fb, 0x3f8bb45183525b51), + (0xbbec808b7b332822, 0x3f43b11bd314773b), + (0xbb777d551025e6da, 0x3edf7931f7cb9cd1), + ]; + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + dx, + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + dx, + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + dx, + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + dx, + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + dx, + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let r0 = DoubleDouble::mul_add(x4, q1, q0); + let p_num = DoubleDouble::mul_add(x8, p4, r0); + + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc9ad7b53d7da072, 0x4007730c69fb4a20), + (0xbc93d2a47740a995, 0x400ab6d03e2d6528), + (0x3c9cd643c37f1205, 0x3ffe2cccacb6740b), + (0xbc7b616646543538, 0x3fe1f36f793ad9c6), + (0xbc483b2cb83a34ba, 0x3fb630083527c66f), + (0x3c1089007cac404c, 0x3f7a6b85d9c297ea), + (0xbbcfc269fc4a2c55, 0x3f298d01a660c3d9), + (0xbb43342127aafe5a, 0x3eb9c8ba657b4b0a), + (0xbaac5e3aa213d878, 0xbe14186c41f01fd1), + ]; + + let p0 = DoubleDouble::mul_f64_add_f64( + DoubleDouble::from_bit_pair(Q[1]), + dx, + f64::from_bits(0x3ff0000000000000), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[3]), + dx, + DoubleDouble::from_bit_pair(Q[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[5]), + dx, + DoubleDouble::from_bit_pair(Q[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + dx, + DoubleDouble::from_bit_pair(Q[6]), + ); + let p4 = DoubleDouble::f64_mul_f64_add( + f64::from_bits(0xbe14186c41f01fd1), // Q[9].hi + dx, + DoubleDouble::from_bit_pair(Q[8]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let r0 = DoubleDouble::mul_add(x4, q1, q0); + let p_den = DoubleDouble::mul_add(x8, p4, r0); + + let d_log = fast_log_d_to_dd(dx); + let prod = DoubleDouble::div(p_num, p_den); + let v0 = DoubleDouble::sub(prod, d_log); + let l_res = f_res; + f_res = apply_sign_and_sum_quick(v0, sum_parity, f_res); + let err = f_fmla( + f_res.hi.abs(), + f64::from_bits(0x3c40000000000000), // 2^-59 + f64::from_bits(0x3c00000000000000), // 2^-63 + ); + let ub = f_res.hi + (f_res.lo + err); + let lb = f_res.hi + (f_res.lo - err); + if ub == lb { + return (f_res, signgam); + } + return (lgamma_1_to_4(dx, d_log, l_res, sum_parity), signgam); + } else if ax <= 12. { + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + const P: [(u64, u64); 10] = [ + (0x3ca9a6c909e67304, 0x400c83f8e5e68934), + (0xbcc3a71a296d1f00, 0x40278d8a2abd6aec), + (0xbca623fa8857b35a, 0xc0144dd0190486d6), + (0x3cc1845532bca122, 0xc02920aaae63c5a7), + (0x3c57111721fd9df2, 0xbfc9a27952cac38f), + (0xbca78a77f8acae38, 0x400043078ac20503), + (0xbc721a88d770af7e, 0x3fdbeba4a1a95bfd), + (0xbc09c9e5917a665e, 0x3f9e18ff2504fd11), + (0xbbeb6e5c1cdf8c87, 0x3f45b0595f7eb903), + (0xbaf149d407d419d3, 0x3ecf5336ddb96b5f), + ]; + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[1]), + dx, + DoubleDouble::from_bit_pair(P[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[3]), + dx, + DoubleDouble::from_bit_pair(P[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[5]), + dx, + DoubleDouble::from_bit_pair(P[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[7]), + dx, + DoubleDouble::from_bit_pair(P[6]), + ); + let p4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + dx, + DoubleDouble::from_bit_pair(P[8]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let r0 = DoubleDouble::mul_add(x4, q1, q0); + let p_num = DoubleDouble::mul_add(x8, p4, r0); + + const Q: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cc5e0cfc2a3ed2f, 0x4023561fd4efbbb2), + (0x3c829f67da778215, 0x403167ff0d04f99a), + (0x3ca3c8e7b81b165f, 0x4024f2d3c7d9439f), + (0xbca90199265d1bfc, 0x40045530db97bad5), + (0xbc3e89169d10977f, 0x3fd0d9f46084a388), + (0x3c1c2b7582566435, 0x3f872f7f248227bd), + (0x3ba8f3f0294e144f, 0x3f271e198971c58e), + (0x3b4d13ceca0a9bf7, 0x3ea62e85cd267c65), + (0xba896f9fc0c4f644, 0xbde99e5ee24ff6ba), + ]; + + let p0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[1]), + dx, + DoubleDouble::from_bit_pair(Q[0]), + ); + let p1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[3]), + dx, + DoubleDouble::from_bit_pair(Q[2]), + ); + let p2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[5]), + dx, + DoubleDouble::from_bit_pair(Q[4]), + ); + let p3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(Q[7]), + dx, + DoubleDouble::from_bit_pair(Q[6]), + ); + let p4 = DoubleDouble::f64_mul_f64_add( + f64::from_bits(0xbde99e5ee24ff6ba), //Q[9].hi + dx, + DoubleDouble::from_bit_pair(Q[8]), + ); + + let q0 = DoubleDouble::mul_add(x2, p1, p0); + let q1 = DoubleDouble::mul_add(x2, p3, p2); + + let r0 = DoubleDouble::mul_add(x4, q1, q0); + let p_den = DoubleDouble::mul_add(x8, p4, r0); + + let l_res = f_res; + f_res = apply_sign_and_sum_quick(DoubleDouble::div(p_num, p_den), sum_parity, f_res); + let err = f_fmla( + f_res.hi.abs(), + f64::from_bits(0x3c50000000000000), // 2^-58 + f64::from_bits(0x3bd0000000000000), // 2^-66 + ); + let ub = f_res.hi + (f_res.lo + err); + let lb = f_res.hi + (f_res.lo - err); + if ub == lb { + return (f_res, signgam); + } + return (lgamma_4_to_12(dx, l_res, sum_parity), signgam); + } + // Stirling's approximation of Log(Gamma) and then Exp[Log[Gamma]] + let y_recip = DoubleDouble::from_quick_recip(dx); + let y_sqr = DoubleDouble::mult(y_recip, y_recip); + // Bernoulli coefficients generated by SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / (2*k*(2*k-1))) * x**((2*k-1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 7) + let bernoulli_poly_s = f_polyeval6( + y_sqr.hi, + f64::from_bits(0xbf66c16c16c16c17), + f64::from_bits(0x3f4a01a01a01a01a), + f64::from_bits(0xbf43813813813814), + f64::from_bits(0x3f4b951e2b18ff23), + f64::from_bits(0xbf5f6ab0d9993c7d), + f64::from_bits(0x3f7a41a41a41a41a), + ); + let bernoulli_poly = DoubleDouble::mul_f64_add( + y_sqr, + bernoulli_poly_s, + DoubleDouble::from_bit_pair((0x3c55555555555555, 0x3fb5555555555555)), + ); + // Log[Gamma(x)] = x*log(x) - x + 1/2*Log(2*PI/x) + bernoulli_terms + const LOG2_PI_OVER_2: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc865b5a1b7ff5df, 0x3fed67f1c864beb5)); + let mut log_gamma = DoubleDouble::add( + DoubleDouble::mul_add_f64(bernoulli_poly, y_recip, -dx), + LOG2_PI_OVER_2, + ); + let dy_log = fast_log_d_to_dd(dx); + log_gamma = DoubleDouble::mul_add( + DoubleDouble::from_exact_add(dy_log.hi, dy_log.lo), + DoubleDouble::from_full_exact_add(dx, -0.5), + log_gamma, + ); + let l_res = f_res; + f_res = apply_sign_and_sum_quick(log_gamma, sum_parity, f_res); + let err = f_fmla( + f_res.hi.abs(), + f64::from_bits(0x3c30000000000000), // 2^-60 + f64::from_bits(0x3bc0000000000000), // 2^-67 + ); + let ub = f_res.hi + (f_res.lo + err); + let lb = f_res.hi + (f_res.lo - err); + if ub == lb { + return (f_res, signgam); + } + (stirling_accurate(dx, sum_parity, l_res), signgam) +} + +/// Computes log(gamma(x)) +/// +/// ulp 0.52 +pub fn f_lgamma(x: f64) -> f64 { + let nx = x.to_bits().wrapping_shl(1); + if nx >= 0xfeaea9b24f16a34cu64 || nx == 0 { + // |x| >= 0x1.006df1bfac84ep+1015 + if x.is_infinite() { + return f64::INFINITY; + } + if x.is_nan() { + return f64::NAN; + } + return f64::INFINITY; + } + + if is_integer(x) { + if x == 2. || x == 1. { + return 0.; + } + if x.is_sign_negative() { + return f64::INFINITY; + } + } + + lgamma_core(x).0.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_lgamma() { + assert_eq!(f_lgamma(0.), f64::INFINITY); + assert_eq!(f_lgamma(-0.), f64::INFINITY); + assert_eq!(f_lgamma(-4.039410591125488), -0.001305303022594149); + assert_eq!(f_lgamma(-2.000001907348633), 12.47664749001284); + assert_eq!( + f_lgamma(0.0000000000000006939032951805219), + 34.90419906721559 + ); + assert_eq!(f_lgamma(0.9743590354901843), 0.01534797880086699); + assert_eq!(f_lgamma(1.9533844296518055), -0.019000687007583488); + assert_eq!(f_lgamma(1.9614259600725743), -0.015824770893504085); + assert_eq!(f_lgamma(1.961426168688831), -0.015824687947423532); + assert_eq!(f_lgamma(2.0000000026484486), 0.0000000011197225706325235); + assert_eq!(f_lgamma(f64::INFINITY), f64::INFINITY); + assert!(f_lgamma(f64::NAN).is_nan()); + // assert_eq!(f_lgamma(1.2902249255008019e301), + // 8932652024571557000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!( + f_lgamma(2.000000000000014), + 0.000000000000006008126761947661 + ); + assert_eq!(f_lgamma(-2.74999999558122), 0.004487888879321723); + assert_eq!( + f_lgamma(0.00000000000001872488985570349), + 31.608922747730112 + ); + assert_eq!(f_lgamma(-2.7484742253727745), 0.0015213685011468314); + assert_eq!(f_lgamma(0.9759521409866919), 0.014362097695996162); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_r.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_r.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_r.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_r.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{is_integer, is_odd_integer}; +use crate::gamma::lgamma::lgamma_core; + +/// Computes log(gamma(x)) +/// +/// Returns gamma value + sign. +pub fn f_lgamma_r(x: f64) -> (f64, i32) { + // filter out exceptional cases + let xb = x.to_bits().wrapping_shl(1); + if xb >= 0x7ffu64 << 53 || xb == 0 { + if x.is_nan() { + return (f64::NAN, 1); + } + if xb == 0 { + return (f64::INFINITY, 1 - 2 * ((x.to_bits() >> 63) as i32)); + } + if xb.wrapping_shl(11) == 0 { + return (f64::INFINITY, 1); + } + } + + if is_integer(x) { + if x == 2. || x == 1. { + return (0., 1); + } + if x.is_sign_negative() { + let is_odd = (!is_odd_integer(x)) as i32; + return (f64::INFINITY, 1 - (is_odd << 1)); + } + } + + let (r, sign_gam) = lgamma_core(x); + (r.to_f64(), sign_gam) +} + +#[cfg(test)] +mod tests { + use crate::f_lgamma_r; + + #[test] + fn test_lgamma_rf() { + assert_eq!(f_lgamma_r(-0.), (f64::INFINITY, -1)); + assert_eq!(f_lgamma_r(f64::NEG_INFINITY), (f64::INFINITY, 1)); + assert_eq!(f_lgamma_r(f64::INFINITY), (f64::INFINITY, 1)); + assert_eq!(f_lgamma_r(0.), (f64::INFINITY, 1)); + assert_eq!(f_lgamma_r(5.), (3.1780538303479458, 1)); + assert_eq!(f_lgamma_r(-4.5), (-2.813084081769316, -1)); + assert_eq!(f_lgamma_r(-2.0015738), (5.759666328573806, -1)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_rf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_rf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_rf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgamma_rf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,279 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf, is_odd_integerf}; +use crate::logs::simple_fast_log; +use crate::polyeval::{f_estrin_polyeval4, f_polyeval5, f_polyeval7, f_polyeval8}; +use crate::rounding::CpuFloor; +use crate::sin_cosf::fast_sinpif; + +#[inline] +pub(crate) fn lgamma_coref(x: f32) -> (f64, i32) { + let ax = f32::from_bits(x.to_bits() & 0x7fff_ffff); + let dx = ax as f64; + + let is_positive = x.is_sign_positive(); + let mut sum_parity = 1f64; + + let mut f_res = 0f64; + + let mut signgam: i32 = 1i32; + + // For negative x, since (G is gamma function) + // -x*G(-x)*G(x) = pi/sin(pi*x), + // we have + // G(x) = pi/(sin(pi*x)*(-x)*G(-x)) + // since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 + // Hence, for x<0, signgam = sign(sin(pi*x)) and + // lgamma(x) = log(|Gamma(x)|) + // = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); + if !is_positive { + let y1 = ax.cpu_floor(); + let fraction = ax - y1; // excess over the boundary + + let a = fast_sinpif(fraction); + + sum_parity = -1.; + const LOG_PI: f64 = f64::from_bits(0x3ff250d048e7a1bd); + f_res = LOG_PI - simple_fast_log(a * dx); + // gamma(x) is negative in (-2n-1,-2n), thus when fx is odd + let is_odd = (!is_odd_integerf(y1)) as i32; + signgam = 1 - (is_odd << 1); + } + + if ax <= 0.007 { + // Generated by Wolfram Mathematica: + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,x]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,x]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let num = f_estrin_polyeval4( + dx, + f64::from_bits(0xbb49bbc47e595350), + f64::from_bits(0xbfe2788cfc6fb2d3), + f64::from_bits(0x3fc829299b97c525), + f64::from_bits(0x3fd8e2e8aab1247c), + ); + let den = f_estrin_polyeval4( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3ff190e5bf5a8162), + f64::from_bits(0x3fc927632366c502), + f64::from_bits(0xbf8b4ea7bd1b808e), + ); + f_res = f_fmla(num / den - simple_fast_log(dx), sum_parity, f_res); + } else if ax < 1. { + // Poly for loggamma(x + 1) - log(x) generated by Wolfram Mathematica + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let num = f_polyeval7( + dx, + f64::from_bits(0xbd24e4cf78c8818a), + f64::from_bits(0xbfe2788cfc6f64e6), + f64::from_bits(0xbfe1ea632fe853b2), + f64::from_bits(0x3fd988d2daad3806), + f64::from_bits(0x3fe1f4870eaafdf4), + f64::from_bits(0x3fc51e12d5b97330), + f64::from_bits(0x3f889ebeb9f0c8ff), + ); + let den = f_polyeval7( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4003289872066f33), + f64::from_bits(0x4000373d88c32fe5), + f64::from_bits(0x3fe71e95bc874164), + f64::from_bits(0x3fb9936a0e008be7), + f64::from_bits(0x3f6cba20a1988a60), + f64::from_bits(0xbef3ca884ba4237a), + ); + f_res = f_fmla(num / den - simple_fast_log(dx), sum_parity, f_res); + } else if ax <= 4. { + // Poly for loggamma(x + 1) - log(x) generated by Wolfram Mathematica + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let num = f_polyeval8( + dx, + f64::from_bits(0xbe630847302a205f), + f64::from_bits(0xbfe2788c24a7deff), + f64::from_bits(0xbfdd0f61b8171907), + f64::from_bits(0x3fdab4ec27801e42), + f64::from_bits(0x3fde11fd49427a3c), + f64::from_bits(0x3fc0dbce39c660da), + f64::from_bits(0x3f88e0b4cd3e97f7), + f64::from_bits(0x3f328fcd9e9ee94e), + ); + let den = f_polyeval8( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4001b135a31bffae), + f64::from_bits(0x3ffbbecb5e39f4ea), + f64::from_bits(0x3fe2e4da095d10bd), + f64::from_bits(0x3fb63cb7548d0d30), + f64::from_bits(0x3f73a67613163399), + f64::from_bits(0x3f10edd4e2b80e6f), + f64::from_bits(0xbe77f4e4068f9d32), + ); + f_res = f_fmla(num / den - simple_fast_log(dx), sum_parity, f_res); + } else if ax <= 12. { + // Poly for loggamma(x) generated by Wolfram Mathematica + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let num = f_polyeval8( + dx, + f64::from_bits(0x40086069fcc21690), + f64::from_bits(0x4008c8ef8602e78d), + f64::from_bits(0xc0186323149757ae), + f64::from_bits(0xbff6a9ded42d3f31), + f64::from_bits(0x3ff1adb5566cd807), + f64::from_bits(0x3fcff023390dead6), + f64::from_bits(0x3f8977a5454ec393), + f64::from_bits(0x3f21361088f694dc), + ); + let den = f_polyeval8( + dx, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4016096b397dbe73), + f64::from_bits(0x401478926593a395), + f64::from_bits(0x3ff6a931f9e31511), + f64::from_bits(0x3fc0fbe57bf263a4), + f64::from_bits(0x3f7023f51ba39a98), + f64::from_bits(0x3efabd75ebfbde40), + f64::from_bits(0xbe4b2c9e2e4e7daa), + ); + f_res = f_fmla(num / den, sum_parity, f_res); + } else { + // Stirling's approximation of Log(Gamma) and then Exp[Log[Gamma]] + let y_recip = 1. / dx; + let y_sqr = y_recip * y_recip; + // Bernoulli coefficients generated by SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / (2*k*(2*k-1))) * x**((2*k-1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 5) + let bernoulli_poly = f_polyeval5( + y_sqr, + f64::from_bits(0x3fb5555555555555), + f64::from_bits(0xbf66c16c16c16c17), + f64::from_bits(0x3f4a01a01a01a01a), + f64::from_bits(0xbf43813813813814), + f64::from_bits(0x3f4b951e2b18ff23), + ); + // Log[Gamma(x)] = x*log(x) - x + 1/2*Log(2*PI/x) + bernoulli_terms + const LOG2_PI_OVER_2: f64 = f64::from_bits(0x3fed67f1c864beb5); + let mut log_gamma = f_fmla(bernoulli_poly, y_recip, -dx) + LOG2_PI_OVER_2; + log_gamma = f_fmla(simple_fast_log(dx), dx - 0.5, log_gamma); + f_res = f_fmla(log_gamma, sum_parity, f_res); + } + + (f_res, signgam) +} + +/// Computes log(gamma(x)) +/// +/// Returns gamma value + sign. +/// +/// ulp 0.5 +pub fn f_lgamma_rf(x: f32) -> (f32, i32) { + // filter out exceptional cases + let xb = x.to_bits().wrapping_shl(1); + if xb >= 0xffu32 << 24 || xb == 0 { + if x.is_infinite() { + return (f32::INFINITY, 1); + } + if x.is_nan() { + return (f32::NAN, 1); + } + if xb == 0 { + return (f32::INFINITY, 1 - 2 * (x.to_bits() >> 31) as i32); + } + } + + if is_integerf(x) { + if x == 2. || x == 1. { + return (0., 1); + } + if x.is_sign_negative() { + let is_odd = (!is_odd_integerf(x)) as i32; + return (f32::INFINITY, 1 - (is_odd << 1)); + } + } + let c_gamma = lgamma_coref(x); + let fx = c_gamma.0 as f32; + (fx, c_gamma.1) +} + +#[cfg(test)] +mod tests { + use crate::f_lgamma_rf; + + #[test] + fn test_lgamma_rf() { + assert_eq!(f_lgamma_rf(f32::NEG_INFINITY), (f32::INFINITY, 1)); + assert_eq!(f_lgamma_rf(f32::INFINITY), (f32::INFINITY, 1)); + assert_eq!(f_lgamma_rf(0.), (f32::INFINITY, 1)); + assert_eq!(f_lgamma_rf(-0.), (f32::INFINITY, -1)); + assert_eq!(f_lgamma_rf(5.), (3.1780539, 1)); + assert_eq!(f_lgamma_rf(-4.5), (-2.8130841, -1)); + assert_eq!(f_lgamma_rf(-2.0015738), (5.7596655, -1)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgammaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgammaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lgammaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lgammaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::is_integerf; +use crate::gamma::lgamma_rf::lgamma_coref; + +/// Computes log(gamma(x)) +/// +/// ulp 0.5 +pub fn f_lgammaf(x: f32) -> f32 { + let xb = x.to_bits(); + if xb >= 0xffu32 << 23 || xb == 0 { + if x.is_infinite() { + return f32::INFINITY; + } + if x.is_nan() { + return f32::NAN; + } + if xb.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + } + + if is_integerf(x) { + if x == 2. || x == 1. { + return 0.; + } + if x.is_sign_negative() { + return f32::INFINITY; + } + } + + lgamma_coref(x).0 as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lgammaf() { + assert_eq!(f_lgammaf(0.006919047), 4.969523); + assert_eq!( + f_lgammaf(0.000000000000000000000000000000000000000015425), + 93.97255 + ); + assert_eq!(f_lgammaf(0.0), f32::INFINITY); + assert_eq!(f_lgammaf(1.7506484), -0.0842405); + assert_eq!(f_lgammaf(7.095007e-8), 16.461288); + assert!(f_lgammaf(-12.).is_infinite()); + assert_eq!(f_lgammaf(2.), 0.); + assert_eq!(f_lgammaf(1.), 0.); + assert_eq!(f_lgammaf(0.53), 0.5156078); + assert_eq!(f_lgammaf(1.53), -0.11927056); + assert_eq!(f_lgammaf(4.53), 2.4955146); + assert_eq!(f_lgammaf(11.77), 16.94281); + assert_eq!(f_lgammaf(22.77), 47.756233); + assert_eq!(f_lgammaf(-0.53), 1.2684484); + assert_eq!(f_lgammaf(-1.53), 0.84318066); + assert_eq!(f_lgammaf(-4.53), -2.8570588); + assert_eq!(f_lgammaf(-11.77), -17.850103); + assert_eq!(f_lgammaf(-22.77), -49.323418); + assert_eq!(f_lgammaf(f32::NEG_INFINITY), f32::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lnbeta.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbeta.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lnbeta.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbeta.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::gamma::lgamma::lgamma_core; + +/// Computes log(beta(x)) function +pub fn f_lnbeta(a: f64, b: f64) -> f64 { + let ax = a.to_bits(); + let bx = b.to_bits(); + + if ax >= 0x7ffu64 << 52 || ax == 0 || bx >= 0x7ffu64 << 52 || bx == 0 { + if (ax >> 63) != 0 || (bx >> 63) != 0 { + // |a| < 0 or |b| < 0 + return f64::NAN; + } + if ax.wrapping_shl(1) == 0 || bx.wrapping_shl(1) == 0 { + // |a| == 0 || |b| == 0 + if ax == 0 || bx == 0 { + // |a| == 0 || |b| == 0 + if ax.wrapping_shl(1) != 0 || bx.wrapping_shl(1) != 0 { + return f64::INFINITY; + } + return f64::NAN; + } + return f64::NAN; + } + if a.is_infinite() || b.is_infinite() { + // |a| == inf or |b| == inf + return f64::NEG_INFINITY; + } + return a + f64::NAN; // nan + } + + let (mut y, _) = lgamma_core(DoubleDouble::from_full_exact_add(a, b).to_f64()); + let (y1, _) = lgamma_core(b); + y = DoubleDouble::quick_dd_sub(y1, y); + let (y1, _) = lgamma_core(a); + y = DoubleDouble::quick_dd_add(y1, y); + y.to_f64() +} + +pub(crate) fn lnbeta_core(a: f64, b: f64) -> DoubleDouble { + let (mut y, _) = lgamma_core(DoubleDouble::from_full_exact_add(a, b).to_f64()); + let (y1, _) = lgamma_core(b); + y = DoubleDouble::quick_dd_sub(y1, y); + let (y1, _) = lgamma_core(a); + DoubleDouble::quick_dd_add(y1, y) +} + +#[cfg(test)] +mod tests { + use crate::f_lnbeta; + + #[test] + fn test_beta() { + assert_eq!(f_lnbeta(f64::INFINITY, 0.), f64::INFINITY); + assert!(f_lnbeta(0., 0.).is_nan()); + assert_eq!(f_lnbeta(0., f64::INFINITY), f64::INFINITY); + assert!(f_lnbeta(-5., 15.).is_nan()); + assert!(f_lnbeta(5., -15.).is_nan()); + assert!(f_lnbeta(f64::NAN, 15.).is_nan()); + assert!(f_lnbeta(15., f64::NAN).is_nan()); + assert_eq!(f_lnbeta(f64::INFINITY, 1.), f64::NEG_INFINITY); + assert_eq!(f_lnbeta(1., f64::INFINITY), f64::NEG_INFINITY); + assert_eq!(f_lnbeta(5., 3.), -4.653960350157523); + assert_eq!(f_lnbeta(3., 5.), -4.653960350157523); + assert_eq!(f_lnbeta(12., 23.), -22.607338344488568); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lnbetaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbetaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/lnbetaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/lnbetaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +use crate::gamma::lgamma_rf::lgamma_coref; + +/// Computes log(beta(x)) function +pub fn f_lnbetaf(a: f32, b: f32) -> f32 { + let ax = a.to_bits(); + let bx = b.to_bits(); + + if ax >= 0xffu32 << 23 || ax == 0 || bx >= 0xffu32 << 23 || bx == 0 { + if (ax >> 31) != 0 || (bx >> 31) != 0 { + // |a| < 0 or |b| < 0 + return f32::NAN; + } + if ax.wrapping_shl(1) == 0 || bx.wrapping_shl(1) == 0 { + // |a| == 0 || |b| == 0 + if ax.wrapping_shl(1) != 0 || bx.wrapping_shl(1) != 0 { + return f32::INFINITY; + } + return f32::NAN; + } + if a.is_infinite() || b.is_infinite() { + // |a| == inf or |b| == inf + return f32::NEG_INFINITY; + } + return a + f32::NAN; // nan + } + + let (mut y, _) = lgamma_coref(a + b); + let (y1, _) = lgamma_coref(b); + y = y1 - y; + let (y1, _) = lgamma_coref(a); + y += y1; + y as f32 +} + +pub(crate) fn lnbetaf_core(a: f32, b: f32) -> f64 { + let (mut y, _) = lgamma_coref(a + b); + let (y1, _) = lgamma_coref(b); + y = y1 - y; + let (y1, _) = lgamma_coref(a); + y += y1; + y +} + +#[cfg(test)] +mod tests { + use crate::f_lnbetaf; + + #[test] + fn test_betaf() { + assert_eq!(f_lnbetaf(1., f32::INFINITY), f32::NEG_INFINITY); + assert_eq!(f_lnbetaf(f32::INFINITY, 0.), f32::INFINITY); + assert!(f_lnbetaf(0., 0.).is_nan()); + assert_eq!(f_lnbetaf(0., f32::INFINITY), f32::INFINITY); + assert!(f_lnbetaf(-5., 15.).is_nan()); + assert!(f_lnbetaf(5., -15.).is_nan()); + assert!(f_lnbetaf(f32::NAN, 15.).is_nan()); + assert!(f_lnbetaf(15., f32::NAN).is_nan()); + assert_eq!(f_lnbetaf(f32::INFINITY, 1.), f32::NEG_INFINITY); + assert_eq!(f_lnbetaf(5., 3.), -4.65396); + assert_eq!(f_lnbetaf(3., 5.), -4.65396); + assert_eq!(f_lnbetaf(12., 23.), -22.607338); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod beta; +mod betaf; +mod betainc; +mod betaincf; +mod digamma; +mod digamma_coeffs; +mod digammaf; +mod gamma_p; +mod gamma_pf; +mod gamma_q; +mod gamma_qf; +mod lgamma; +mod lgamma_r; +mod lgamma_rf; +mod lgammaf; +mod lnbeta; +mod lnbetaf; +mod tgamma; +mod tgammaf; +mod trigamma; +mod trigammaf; + +pub use beta::f_beta; +pub use betaf::f_betaf; +pub use betainc::f_betainc_reg; +pub use betaincf::f_betainc_regf; +pub use digamma::f_digamma; +pub use digammaf::f_digammaf; +pub use gamma_p::f_gamma_p; +pub use gamma_pf::f_gamma_pf; +pub use gamma_q::f_gamma_q; +pub use gamma_qf::f_gamma_qf; +pub use lgamma::f_lgamma; +pub use lgamma_r::f_lgamma_r; +pub use lgamma_rf::f_lgamma_rf; +pub use lgammaf::f_lgammaf; +pub use lnbeta::f_lnbeta; +pub use lnbetaf::f_lnbetaf; +pub use tgamma::f_tgamma; +pub use tgammaf::f_tgammaf; +pub use trigamma::f_trigamma; +pub use trigammaf::f_trigammaf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/tgamma.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgamma.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/tgamma.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgamma.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,344 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integer}; +use crate::double_double::DoubleDouble; +use crate::logs::fast_log_dd; +use crate::polyeval::{f_polyeval6, f_polyeval7, f_polyeval8}; +use crate::pow_exec::exp_dd_fast; +use crate::rounding::CpuFloor; +use crate::sincospi::f_fast_sinpi_dd; + +/// Computes gamma(x) +/// +/// ulp 1 +pub fn f_tgamma(x: f64) -> f64 { + let x_a = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffff); + + if !x.is_normal() { + if x == 0.0 { + return f64::INFINITY; + } + + if x.is_nan() { + return x + x; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f64::NAN; + } + return x; + } + } + + if x >= 171.624 { + return f64::INFINITY; + } + + if is_integer(x) { + if x < 0. { + return f64::NAN; + } + if x < 38. { + let mut t = DoubleDouble::new(0., 1.); + let k = x as i64; + let mut x0 = 1.0; + for _i in 1..k { + t = DoubleDouble::quick_mult_f64(t, x0); + t = DoubleDouble::from_exact_add(t.hi, t.lo); + x0 += 1.0; + } + return t.to_f64(); + } + } + + if x <= -184.0 { + /* negative non-integer */ + /* For x <= -184, x non-integer, |gamma(x)| < 2^-1078. */ + static SIGN: [f64; 2] = [ + f64::from_bits(0x0010000000000000), + f64::from_bits(0x8010000000000000), + ]; + let k = x as i64; + return f64::from_bits(0x0010000000000000) * SIGN[((k & 1) != 0) as usize]; + } + + const EULER_DD: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc56cb90701fbfab, 0x3fe2788cfc6fb619)); + + if x_a < 0.006 { + if x_a.to_bits() < (0x71e0000000000000u64 >> 1) { + // |x| < 0x1p-112 + return 1. / x; + } + if x_a < 2e-10 { + // x is tiny then Gamma(x) = 1/x - euler + let p = DoubleDouble::full_dd_sub(DoubleDouble::from_quick_recip(x), EULER_DD); + return p.to_f64(); + } else if x_a < 2e-6 { + // x is small then Gamma(x) = 1/x - euler + a2*x + // a2 = 1/12 * (6 * euler^2 + pi^2) + const A2: DoubleDouble = + DoubleDouble::from_bit_pair((0x3c8dd92b465a8221, 0x3fefa658c23b1578)); + let rcp = DoubleDouble::from_quick_recip(x); + let p = DoubleDouble::full_dd_add(DoubleDouble::mul_f64_add(A2, x, -EULER_DD), rcp); + return p.to_f64(); + } + + // Laurent series of Gamma(x) + const C: [(u64, u64); 8] = [ + (0x3c8dd92b465a8221, 0x3fefa658c23b1578), + (0x3c53a4f483760950, 0xbfed0a118f324b63), + (0x3c7fabe4f7369157, 0x3fef6a51055096b5), + (0x3c8c9fc795fc6142, 0xbfef6c80ec38b67b), + (0xbc5042339d62e721, 0x3fefc7e0a6eb310b), + (0xbc86fd0d8bdc0c1e, 0xbfefdf3f157b7a39), + (0xbc89b912df09395d, 0x3feff07b5a17ff6c), + (0x3c4e626faf780ff9, 0xbfeff803d68a0bd4), + ]; + let rcp = DoubleDouble::from_quick_recip(x); + let mut p = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(C[7]), + x, + DoubleDouble::from_bit_pair(C[6]), + ); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[0])); + let z = DoubleDouble::mul_f64_add(p, x, DoubleDouble::full_dd_sub(rcp, EULER_DD)); + return z.to_f64(); + } + + let mut fact = DoubleDouble::new(0., 0.0f64); + let mut parity = 1.0; + const PI: DoubleDouble = DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let mut dy = DoubleDouble::new(0., x); + let mut result: DoubleDouble; + + // reflection + if dy.hi < 0. { + if dy.hi.cpu_floor() == dy.hi { + return f64::NAN; + } + dy.hi = f64::from_bits(dy.hi.to_bits() & 0x7fff_ffff_ffff_ffff); + let y1 = x_a.cpu_floor(); + let fraction = x_a - y1; + if fraction != 0.0 + // is it an integer? + { + // is it odd or even? + if y1 != (y1 * 0.5).cpu_floor() * 2.0 { + parity = -1.0; + } + fact = DoubleDouble::div(-PI, f_fast_sinpi_dd(fraction)); + fact = DoubleDouble::from_exact_add(fact.hi, fact.lo); + dy = DoubleDouble::from_full_exact_add(dy.hi, 1.0); + } + } + + if dy.hi < 12.0 { + let y1 = dy; + let z: DoubleDouble; + let mut n = 0; + // x is in (0.06, 1.0). + if dy.hi < 1.0 { + z = dy; + dy = DoubleDouble::full_add_f64(dy, 1.0); + } else + // x is in [1.0, max]. + { + n = dy.hi as i32 - 1; + dy = DoubleDouble::full_add_f64(dy, -n as f64); + z = DoubleDouble::full_add_f64(dy, -1.0); + } + + // Gamma(x+1) on [1;2] generated by Wolfram Mathematica: + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let ps_num = f_polyeval8( + z.hi, + f64::from_bits(0x3fb38b80568a42aa), + f64::from_bits(0xbf8e7685b00d63a6), + f64::from_bits(0xbf80629ed2c48f1a), + f64::from_bits(0xbf6dfc4cdbcee96a), + f64::from_bits(0xbf471816939dc42b), + f64::from_bits(0xbf24bede7d8b3c20), + f64::from_bits(0xbeef56936d891e42), + f64::from_bits(0xbec3e2b405350813), + ); + let mut p_num = DoubleDouble::mul_f64_add( + z, + ps_num, + DoubleDouble::from_bit_pair((0xbc700f441aea2edb, 0x3fd218bdde7878b8)), + ); + p_num = DoubleDouble::mul_add( + z, + p_num, + DoubleDouble::from_bit_pair((0x3b7056a45a2fa50e, 0x3ff0000000000000)), + ); + p_num = DoubleDouble::from_exact_add(p_num.hi, p_num.lo); + + let ps_den = f_polyeval7( + z.hi, + f64::from_bits(0xbfdaa4f09f0caab1), + f64::from_bits(0xbfc960ba48423f9d), + f64::from_bits(0x3fb6873b64e8ccd6), + f64::from_bits(0x3f69ea1ca5b8a225), + f64::from_bits(0xbf77b166f68a2e63), + f64::from_bits(0x3f4fd1eff9193728), + f64::from_bits(0xbf0c1a43f4985c97), + ); + let mut p_den = DoubleDouble::mul_f64_add( + z, + ps_den, + DoubleDouble::from_bit_pair((0xbc759594c51ad8b7, 0x3feb84ebebabf275)), + ); + p_den = DoubleDouble::mul_add_f64(z, p_den, f64::from_bits(0x3ff0000000000000)); + p_den = DoubleDouble::from_exact_add(p_den.hi, p_den.lo); + result = DoubleDouble::div(p_num, p_den); + if y1.hi < dy.hi { + result = DoubleDouble::div(result, y1); + } else if y1.hi > dy.hi { + for _ in 0..n { + result = DoubleDouble::mult(result, dy); + dy = DoubleDouble::full_add_f64(dy, 1.0); + } + } + } else { + if x > 171.624e+0 { + return f64::INFINITY; + } + // Stirling's approximation of Log(Gamma) and then Exp[Log[Gamma]] + let y_recip = dy.recip(); + let y_sqr = DoubleDouble::mult(y_recip, y_recip); + // Bernoulli coefficients generated by SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / (2*k*(2*k-1))) * x**((2*k-1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 7) + let bernoulli_poly_s = f_polyeval6( + y_sqr.hi, + f64::from_bits(0xbf66c16c16c16c17), + f64::from_bits(0x3f4a01a01a01a01a), + f64::from_bits(0xbf43813813813814), + f64::from_bits(0x3f4b951e2b18ff23), + f64::from_bits(0xbf5f6ab0d9993c7d), + f64::from_bits(0x3f7a41a41a41a41a), + ); + let bernoulli_poly = DoubleDouble::mul_f64_add( + y_sqr, + bernoulli_poly_s, + DoubleDouble::from_bit_pair((0x3c55555555555555, 0x3fb5555555555555)), + ); + // Log[Gamma(x)] = x*log(x) - x + 1/2*Log(2*PI/x) + bernoulli_terms + const LOG2_PI_OVER_2: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc865b5a1b7ff5df, 0x3fed67f1c864beb5)); + let mut log_gamma = DoubleDouble::add( + DoubleDouble::mul_add(bernoulli_poly, y_recip, -dy), + LOG2_PI_OVER_2, + ); + let dy_log = fast_log_dd(dy); + log_gamma = DoubleDouble::mul_add( + DoubleDouble::from_exact_add(dy_log.hi, dy_log.lo), + DoubleDouble::add_f64(dy, -0.5), + log_gamma, + ); + let log_prod = log_gamma.to_f64(); + if log_prod >= 690. { + // underflow/overflow case + log_gamma = DoubleDouble::quick_mult_f64(log_gamma, 0.5); + result = exp_dd_fast(log_gamma); + let exp_result = result; + result.hi *= parity; + result.lo *= parity; + if fact.lo != 0. && fact.hi != 0. { + // y / x = y / (z*z) = y / z * 1/z + result = DoubleDouble::from_exact_add(result.hi, result.lo); + result = DoubleDouble::div(fact, result); + result = DoubleDouble::div(result, exp_result); + } else { + result = DoubleDouble::quick_mult(result, exp_result); + } + + let err = f_fmla( + result.hi.abs(), + f64::from_bits(0x3c20000000000000), // 2^-61 + f64::from_bits(0x3bd0000000000000), // 2^-65 + ); + let ub = result.hi + (result.lo + err); + let lb = result.hi + (result.lo - err); + if ub == lb { + return result.to_f64(); + } + return result.to_f64(); + } + result = exp_dd_fast(log_gamma); + } + + if fact.lo != 0. && fact.hi != 0. { + // y / x = y / (z*z) = y / z * 1/z + result = DoubleDouble::from_exact_add(result.hi, result.lo); + result = DoubleDouble::div(fact, result); + } + result.to_f64() * parity +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tgamma() { + // assert_eq!(f_tgamma(6.757812502211891), 459.54924419209556); + assert_eq!(f_tgamma(-1.70000000042915), 2.513923520668069); + assert_eq!(f_tgamma(5.), 24.); + assert_eq!(f_tgamma(24.), 25852016738884980000000.); + assert_eq!(f_tgamma(6.4324324), 255.1369211339094); + assert_eq!(f_tgamma(f64::INFINITY), f64::INFINITY); + assert_eq!(f_tgamma(0.), f64::INFINITY); + assert_eq!(f_tgamma(-0.), f64::INFINITY); + assert!(f_tgamma(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/tgammaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgammaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/tgammaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/tgammaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,233 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integer}; +use crate::f_exp; +use crate::logs::simple_fast_log; +use crate::polyeval::{f_polyeval5, f_polyeval18}; +use crate::rounding::CpuFloor; +use crate::sin_cosf::fast_sinpif; + +/// True gamma function +/// +/// ulp 0.5 +pub fn f_tgammaf(x: f32) -> f32 { + let xb = x.to_bits(); + // filter out exceptional cases + if xb >= 0xffu32 << 23 || xb == 0 { + if xb.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + + if x.is_nan() { + return x + x; + } + + if x.is_infinite() { + if x.is_sign_negative() { + return f32::NAN; + } + return x; + } + } + + let x_a = f32::from_bits(x.to_bits() & 0x7fff_ffff); + if x.is_sign_positive() && x_a.to_bits() >= 0x420c2910u32 { + // x >= 35.0401 + return f32::INFINITY; + } else if x.is_sign_negative() && x_a.to_bits() >= 0x421a67dau32 { + // x <= -38.601418 + if x == x.cpu_floor() { + // integer where x < 0 + return f32::NAN; + } + return -0.0; + } + + if x_a < 2e-8 { + // x is tiny then Gamma(x) = 1/x - euler + const EULER: f64 = f64::from_bits(0x3fe2788cfc6fb619); + let dx = x as f64; + let p = 1. / dx - EULER; + return p as f32; + } else if x_a < 2e-6 { + // x is small then Gamma(x) = 1/x - euler + a2*x + // a2 = 1/12 * (6 * euler^2 + pi^2) + const EULER: f64 = f64::from_bits(0x3fe2788cfc6fb619); + const A2: f64 = f64::from_bits(0x3fefa658c23b1578); + let dx = x as f64; + let p = 1. / dx + f_fmla(dx, A2, -EULER); + return p as f32; + } + + let mut fact = 1.0f64; + let mut parity = 1.0; + const PI: f64 = f64::from_bits(0x400921fb54442d18); + let mut dy = x as f64; + let mut result; + + // reflection + if dy < 0. { + if is_integer(dy) { + return f32::NAN; + } + dy = f64::from_bits(dy.to_bits() & 0x7fff_ffff_ffff_ffff); + // x < ulp(x) + if x_a < f32::EPSILON { + return (1. / x as f64) as f32; + } + let y1 = x_a.cpu_floor(); + let fraction = x_a - y1; + if fraction != 0.0 + // is it an integer? + { + // is it odd or even? + if y1 != (y1 * 0.5).cpu_floor() * 2.0 { + parity = -1.0; + } + fact = -PI / fast_sinpif(fraction); + dy += 1.0; + } + } + + if dy < 12.0 { + let y1 = dy; + let z; + let mut n = 0; + // x is in (eps, 1.0). + if dy < 1.0 { + z = dy; + dy += 1.0; + } else + // x is in [1.0, max]. + { + n = dy as i32 - 1; + dy -= n as f64; + z = dy - 1.0; + } + + // Gamma(x+1) on [1;2] generated by Wolfram Mathematica: + // <90] + // num=Numerator[approx][[1]]; + // den=Denominator[approx][[1]]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]], {50,50}, ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + result = f_polyeval18( + z, + f64::from_bits(0x3fefffffffffff19), + f64::from_bits(0xbfe2788cfc6d59a6), + f64::from_bits(0x3fefa658c133abd2), + f64::from_bits(0xbfed0a116184e1d0), + f64::from_bits(0x3fef6a4cd2befb54), + f64::from_bits(0xbfef6c4479fe9aca), + f64::from_bits(0x3fefc59bfa97e9bf), + f64::from_bits(0xbfefcfde03bfb0d9), + f64::from_bits(0x3fefa3ee5eab6681), + f64::from_bits(0xbfeed8130a67dd46), + f64::from_bits(0x3fecb6e603fdb5ed), + f64::from_bits(0xbfe8801e901b4c10), + f64::from_bits(0x3fe2356219082d3e), + f64::from_bits(0xbfd64ad556b6062a), + f64::from_bits(0x3fc5219e235288f4), + f64::from_bits(0xbfacad444cb0f4ec), + f64::from_bits(0x3f888ea3bfa9155a), + f64::from_bits(0xbf53d1776abc9eaa), + ); + if y1 < dy { + result /= y1; + } else if y1 > dy { + for _ in 0..n { + result *= dy; + dy += 1.0; + } + } + } else { + // Stirling's approximation of Log(Gamma) and then Exp[Log[Gamma]] + let y_recip = 1. / dy; + let y_sqr = y_recip * y_recip; + // Bernoulli coefficients generated by SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = (B / (2*k*(2*k-1))) * x**((2*k-1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 5) + let bernoulli_poly = f_polyeval5( + y_sqr, + f64::from_bits(0x3fb5555555555555), + f64::from_bits(0xbf66c16c16c16c17), + f64::from_bits(0x3f4a01a01a01a01a), + f64::from_bits(0xbf43813813813814), + f64::from_bits(0x3f4b951e2b18ff23), + ); + // Log[Gamma(x)] = x*log(x) - x + 1/2*Log(2*PI/x) + bernoulli_terms + const LOG2_PI_OVER_2: f64 = f64::from_bits(0x3fed67f1c864beb5); + let mut log_gamma = f_fmla(bernoulli_poly, y_recip, -dy) + LOG2_PI_OVER_2; + log_gamma = f_fmla(simple_fast_log(dy), dy - 0.5, log_gamma); + result = f_exp(log_gamma); + } + + result *= parity; + if fact != 1.0 { + result = fact / result; + } + + result as f32 +} + +#[cfg(test)] +mod tests { + use crate::f_tgammaf; + + #[test] + fn test_gammaf() { + assert!(f_tgammaf(-3.).is_nan()); + assert_eq!(f_tgammaf(12.58038769), 167149000.0); + assert_eq!(f_tgammaf(4.566854e-7), 2189690.8); + assert_eq!(f_tgammaf(4.9587783e-8), 20166258.0); + assert_eq!(f_tgammaf(-46.1837), -0.0); + assert_eq!(f_tgammaf(1.1502532e-19), 8.6937384e18); + assert_eq!(f_tgammaf(0.04038769), 24.221333); + assert_eq!(f_tgammaf(2.58038769), 1.4088479); + assert_eq!(f_tgammaf(-1.3559477), 2.892815); + assert_eq!(f_tgammaf(-2.3559477), -1.2278775); + assert_eq!(f_tgammaf(0.0), f32::INFINITY); + assert_eq!(f_tgammaf(-0.0), f32::INFINITY); + assert_eq!(f_tgammaf(f32::INFINITY), f32::INFINITY); + assert!(f_tgammaf(f32::NEG_INFINITY).is_nan()); + assert!(f_tgammaf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/trigamma.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigamma.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/trigamma.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigamma.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,602 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::is_integer; +use crate::double_double::DoubleDouble; +use crate::sincospi::f_fast_sinpi_dd; + +// Generated in Wolfram Mathematica: +// <75,MaxIterations->100] +// num=Numerator[approx][[1]]; +// poly=num; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static P_1: [(u64, u64); 12] = [ + (0x3c81873d89121fec, 0x3ffa51a6625307d3), + (0x3cb78bf7af507504, 0x4016a65cbac476ca), + (0xbc94179c65e021c2, 0x40218234a0a79582), + (0x3cb842a8ab5e0994, 0x401fde32175f8515), + (0xbc8768b33f5776b7, 0x4012de6bde49abff), + (0x3c8e06354a27f081, 0x3ffe5d6ef3a2eac6), + (0xbc8b391d09fed17a, 0x3fe0d186688252cf), + (0xbc59a5c46bb8b8cc, 0x3fb958f9a0f156b7), + (0x3c2ac44c6a197244, 0x3f88e605f24e1a89), + (0x3bd2d05fa8be27f2, 0x3f4cd369f5d68104), + (0x3b84ad0a748fdd22, 0x3efde955ebb17874), + (0xb96aa8b9a65e0899, 0xbce053d04459ead7), +]; + +// Generated by Wolfram Mathematica: +// <75,MaxIterations->100] +// num=Numerator[approx][[1]]; +// poly=num; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static P_2: [(u64, u64); 12] = [ + (0x3c81873d8912236c, 0x3ffa51a6625307d3), + (0xbcbc731a62342288, 0x40176c23f7ea51e6), + (0xbcc45a6fd00e67a8, 0x4022cb5ae67657ef), + (0x3cc0876fde7fe4e6, 0x4021d766062b9550), + (0xbcaec4a4859cba1d, 0x401629f91cd4f291), + (0x3c76184014e4d7e3, 0x4002d43da3352004), + (0x3c812c7609483e0e, 0x3fe62e3266eef8c7), + (0xbc5f991047f52d2b, 0x3fc1eacb910b951c), + (0x3c28b9f38d603f2f, 0x3f930960a301df34), + (0x3bf9b620eb930504, 0x3f5814f8e057b14b), + (0xbb990860b88b54e4, 0x3f0b9f67c71aa3bf), + (0x38e5cb6acfbaab77, 0xbc4194b8c01afe9a), +]; + +// Generated by Wolfram Mathematica: +// <75,MaxIterations->100] +// num=Numerator[approx]; +// poly=num; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static P_3: [(u64, u64); 12] = [ + (0x3c9cd56dbb295efc, 0x3ffa51a662556db9), + (0x3c9f4ee74f5f9daf, 0x4018ff913088cb34), + (0x3ccf08737350609c, 0x402593d55686b8b1), + (0xbcc6cd4ed33afebb, 0x402641d10de4def5), + (0xbcb24d1957c1303c, 0x401e682c37e8e2cf), + (0x3ca30ac79162ceb2, 0x400ccfc7c4566f55), + (0x3c9efea5ff293dc9, 0x3ff33eb2c6e89d0b), + (0x3c74670a11068abc, 0x3fd1fbf456e5c6f0), + (0x3c47b5dcdea19c36, 0x3fa6a6a2148c482c), + (0xbc14642012a1cc1e, 0x3f71851e927f52e7), + (0x3bc7db88a4ec5478, 0x3f29a45059a43475), + (0xb7bc31e55271eab0, 0xbb375518529c52fb), +]; + +// Generated in Wolfram Mathematica: +// <75,MaxIterations->100] +// den=Denominator[approx][[1]]; +// poly=den; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static Q_1: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbcb84c43a11fc28a, 0x40139d9587da0fb5), + (0x3ca1cf3dbcddbb57, 0x402507cb6225f0f0), + (0x3cb01aa6ddcc3cfd, 0x402a1b416d0ed4e6), + (0xbcbc31c216b5ff66, 0x4024ec8829e535d4), + (0xbcb335c23022f43e, 0x4016d2ba6d1a18e6), + (0x3cafbfffc03ad28a, 0x400158c4611ed51f), + (0xbc8d1fb10a031a27, 0x3fe26f15bb52f89b), + (0x3c56a9fea160eecb, 0x3fbaec13f663049d), + (0xbc2f4ee869ba9364, 0x3f89cde0500cd68f), + (0x3be3f23afc9398b6, 0x3f4d4b0f4dcf3eb8), + (0x3b67a3ed4795d33e, 0x3efde955eafac9c2), +]; + +// Generated by Wolfram Mathematica: +// <75,MaxIterations->100] +// den=Denominator[approx][[1]]; +// poly=den; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static Q_2: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc81a3e4e026b7b1, 0x401415d1a20a9339), + (0x3cc279576dfe3ec9, 0x402627c1a95d33d2), + (0x3c9a94b5cf0cae88, 0x402c724dc5cf4577), + (0xbc8aa1fa0c3820a8, 0x4027b7a332bb07f4), + (0xbc96968367088d66, 0x401b14376177bdd7), + (0x3ca2d3dfa5847f4d, 0x4005b0511cd98f2c), + (0xbc8cfad394d41dd1, 0x3fe877bc2d02c7f3), + (0xbc51592b8ec81a92, 0x3fc31f52afc72b95), + (0x3c2cbef277d587e9, 0x3f93cb2f0e574376), + (0xbbfbb670fd94f6ba, 0x3f5883767f745a92), + (0xbb931b04d74e5893, 0x3f0b9f67c71a60f3), +]; + +// Generated by Wolfram Mathematica: +// <75,MaxIterations->100] +// den=Denominator[approx]; +// poly=den; +// coeffs=CoefficientList[poly,z]; +// TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] +static Q_3: [(u64, u64); 12] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3cbafcb4b6d646d9, 0x40150b12a79fc9cf), + (0x3c989ef814b8dd2a, 0x40288c1d26ffdca5), + (0x3cb0282cfea9c473, 0x4030d737c893cd5f), + (0x3cc955b8aaadb37d, 0x402e5c289b6de3e0), + (0x3cb377161f8861d2, 0x4022fb66d87bd522), + (0xbcb4b0e4cff46ad6, 0x4010e5d13c2a5907), + (0xbc8824539e4b1bd6, 0x3ff58c8fe8f26fca), + (0xbc7d34220d810ea0, 0x3fd36c1351f43e66), + (0xbc4cbdbe85570017, 0x3fa7c1170466605e), + (0xbc0c3afb98775c53, 0x3f71ebafd3e5e3b9), + (0x3bc0b0b7f16afd0a, 0x3f29a45059a43475), +]; + +#[inline] +fn approx_trigamma(x: f64) -> DoubleDouble { + if x <= 10. { + let (p, q) = if x <= 1. { + (&P_1, &Q_1) + } else if x <= 4. { + (&P_2, &Q_2) + } else { + (&P_3, &Q_3) + }; + let x2 = DoubleDouble::from_exact_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[1]), + x, + DoubleDouble::from_bit_pair(p[0]), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[3]), + x, + DoubleDouble::from_bit_pair(p[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[5]), + x, + DoubleDouble::from_bit_pair(p[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[7]), + x, + DoubleDouble::from_bit_pair(p[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[9]), + x, + DoubleDouble::from_bit_pair(p[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(p[11]), + x, + DoubleDouble::from_bit_pair(p[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + let rcp = DoubleDouble::from_quick_recip(x); + let rcp2 = DoubleDouble::quick_mult(rcp, rcp); + + let e0 = DoubleDouble::mul_f64_add_f64( + DoubleDouble::from_bit_pair(q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[3]), + x, + DoubleDouble::from_bit_pair(q[2]), + ); + let e2 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[5]), + x, + DoubleDouble::from_bit_pair(q[4]), + ); + let e3 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[7]), + x, + DoubleDouble::from_bit_pair(q[6]), + ); + let e4 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[9]), + x, + DoubleDouble::from_bit_pair(q[8]), + ); + let e5 = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(q[11]), + x, + DoubleDouble::from_bit_pair(q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let q = DoubleDouble::div(p_num, p_den); + let r = DoubleDouble::quick_dd_add(q, rcp2); + return r; + } + // asymptotic expansion Trigamma[x] = 1/x + 1/x^2 + sum(Bernoulli(2*k)/x^(2*k + 1)) + // Generated in SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = B*x**(-(2*k+1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 10) + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(0, 14): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + const C: [(u64, u64); 10] = [ + (0x3c65555555555555, 0x3fc5555555555555), + (0xbc21111111111111, 0xbfa1111111111111), + (0x3c38618618618618, 0x3f98618618618618), + (0xbc21111111111111, 0xbfa1111111111111), + (0xbc4364d9364d9365, 0x3fb364d9364d9365), + (0xbc6981981981981a, 0xbfd0330330330330), + (0xbc95555555555555, 0x3ff2aaaaaaaaaaab), + (0xbcb7979797979798, 0xc01c5e5e5e5e5e5e), + (0xbcac3b070ec1c3b0, 0x404b7c4f8f13e3c5), + (0x3cc8d3018d3018d3, 0xc08088fe72cfe72d), + ]; + + let rcp = DoubleDouble::from_quick_recip(x); + + let q = DoubleDouble::quick_mult(rcp, rcp); + + let q2 = DoubleDouble::quick_mult(q, q); + let q4 = q2 * q2; + let q8 = q4 * q4; + + let e0 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[1]), + q, + DoubleDouble::from_bit_pair(C[0]), + ); + let e1 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[3]), + q, + DoubleDouble::from_bit_pair(C[2]), + ); + let e2 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[5]), + q, + DoubleDouble::from_bit_pair(C[4]), + ); + let e3 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[7]), + q, + DoubleDouble::from_bit_pair(C[6]), + ); + let e4 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[9]), + q, + DoubleDouble::from_bit_pair(C[8]), + ); + + let q0 = DoubleDouble::quick_mul_add(q2, e1, e0); + let q1 = DoubleDouble::quick_mul_add(q2, e3, e2); + + let r0 = DoubleDouble::quick_mul_add(q4, q1, q0); + let mut p = DoubleDouble::quick_mul_add(q8, e4, r0); + + let q_over_2 = DoubleDouble::quick_mult_f64(q, 0.5); + p = DoubleDouble::quick_mult(p, q); + p = DoubleDouble::quick_mult(p, rcp); + p = DoubleDouble::quick_dd_add(q_over_2, p); + p = DoubleDouble::quick_dd_add(p, rcp); + p +} + +#[inline] +fn approx_trigamma_dd(x: DoubleDouble) -> DoubleDouble { + if x.hi <= 10. { + let (p, q) = if x.hi <= 1. { + (&P_1, &Q_1) + } else if x.hi <= 4. { + (&P_2, &Q_2) + } else { + (&P_3, &Q_3) + }; + let x2 = DoubleDouble::quick_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let e0 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[1]), + x, + DoubleDouble::from_bit_pair(p[0]), + ); + let e1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[3]), + x, + DoubleDouble::from_bit_pair(p[2]), + ); + let e2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[5]), + x, + DoubleDouble::from_bit_pair(p[4]), + ); + let e3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[7]), + x, + DoubleDouble::from_bit_pair(p[6]), + ); + let e4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[9]), + x, + DoubleDouble::from_bit_pair(p[8]), + ); + let e5 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(p[11]), + x, + DoubleDouble::from_bit_pair(p[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_num = DoubleDouble::mul_add(x8, f2, g0); + + let rcp = x.recip(); + let rcp2 = DoubleDouble::quick_mult(rcp, rcp); + + let e0 = DoubleDouble::mul_add_f64( + DoubleDouble::from_bit_pair(q[1]), + x, + f64::from_bits(0x3ff0000000000000), + ); + let e1 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[3]), + x, + DoubleDouble::from_bit_pair(q[2]), + ); + let e2 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[5]), + x, + DoubleDouble::from_bit_pair(q[4]), + ); + let e3 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[7]), + x, + DoubleDouble::from_bit_pair(q[6]), + ); + let e4 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[9]), + x, + DoubleDouble::from_bit_pair(q[8]), + ); + let e5 = DoubleDouble::mul_add( + DoubleDouble::from_bit_pair(q[11]), + x, + DoubleDouble::from_bit_pair(q[10]), + ); + + let f0 = DoubleDouble::mul_add(x2, e1, e0); + let f1 = DoubleDouble::mul_add(x2, e3, e2); + let f2 = DoubleDouble::mul_add(x2, e5, e4); + + let g0 = DoubleDouble::mul_add(x4, f1, f0); + + let p_den = DoubleDouble::mul_add(x8, f2, g0); + + let q = DoubleDouble::div(p_num, p_den); + let r = DoubleDouble::quick_dd_add(q, rcp2); + return r; + } + // asymptotic expansion Trigamma[x] = 1/x + 1/x^2 + sum(Bernoulli(2*k)/x^(2*k + 1)) + // Generated in SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = B*x**(-(2*k+1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 10) + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(0, 14): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + const C: [(u64, u64); 10] = [ + (0x3c65555555555555, 0x3fc5555555555555), + (0xbc21111111111111, 0xbfa1111111111111), + (0x3c38618618618618, 0x3f98618618618618), + (0xbc21111111111111, 0xbfa1111111111111), + (0xbc4364d9364d9365, 0x3fb364d9364d9365), + (0xbc6981981981981a, 0xbfd0330330330330), + (0xbc95555555555555, 0x3ff2aaaaaaaaaaab), + (0xbcb7979797979798, 0xc01c5e5e5e5e5e5e), + (0xbcac3b070ec1c3b0, 0x404b7c4f8f13e3c5), + (0x3cc8d3018d3018d3, 0xc08088fe72cfe72d), + ]; + + let rcp = x.recip(); + + let q = DoubleDouble::quick_mult(rcp, rcp); + + let q2 = DoubleDouble::quick_mult(q, q); + let q4 = q2 * q2; + let q8 = q4 * q4; + + let e0 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[1]), + q, + DoubleDouble::from_bit_pair(C[0]), + ); + let e1 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[3]), + q, + DoubleDouble::from_bit_pair(C[2]), + ); + let e2 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[5]), + q, + DoubleDouble::from_bit_pair(C[4]), + ); + let e3 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[7]), + q, + DoubleDouble::from_bit_pair(C[6]), + ); + let e4 = DoubleDouble::quick_mul_add( + DoubleDouble::from_bit_pair(C[9]), + q, + DoubleDouble::from_bit_pair(C[8]), + ); + + let q0 = DoubleDouble::quick_mul_add(q2, e1, e0); + let q1 = DoubleDouble::quick_mul_add(q2, e3, e2); + + let r0 = DoubleDouble::quick_mul_add(q4, q1, q0); + let mut p = DoubleDouble::quick_mul_add(q8, e4, r0); + + let q_over_2 = DoubleDouble::quick_mult_f64(q, 0.5); + p = DoubleDouble::quick_mult(p, q); + p = DoubleDouble::quick_mult(p, rcp); + p = DoubleDouble::quick_dd_add(q_over_2, p); + p = DoubleDouble::quick_dd_add(p, rcp); + p +} + +/// Computes the trigamma function ψ₁(x). +/// +/// The trigamma function is the second derivative of the logarithm of the gamma function. +pub fn f_trigamma(x: f64) -> f64 { + let xb = x.to_bits(); + if !x.is_normal() { + if x.is_infinite() { + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + 0. + }; + } + if x.is_nan() { + return f64::NAN; + } + if xb == 0 { + return f64::INFINITY; + } + } + + let x_e = (x.to_bits() >> 52) & 0x7ff; + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 52 { + // |x| < 2^-52 + let dx = x; + return 1. / (dx * dx); + } + + if x < 0. { + if is_integer(x) { + return f64::INFINITY; + } + // reflection formula + // Trigamma[1-x] + Trigamma[x] = PI^2 / sinpi^2(x) + const SQR_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3cc692b71366cc05, 0x4023bd3cc9be45de)); // pi^2 + let sinpi_ax = f_fast_sinpi_dd(-x); + let dx = DoubleDouble::from_full_exact_sub(1., x); + let result = DoubleDouble::div(SQR_PI, DoubleDouble::quick_mult(sinpi_ax, sinpi_ax)); + let trigamma_x = approx_trigamma_dd(dx); + return DoubleDouble::quick_dd_sub(result, trigamma_x).to_f64(); + } + + approx_trigamma(x).to_f64() +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_trigamma() { + assert_eq!(f_trigamma(-27.058018), 300.35629698636757); + assert_eq!(f_trigamma(27.058018), 0.037648965757704725); + assert_eq!(f_trigamma(8.058018), 0.13211796975281037); + assert_eq!(f_trigamma(-8.058018), 300.2758629255111); + assert_eq!(f_trigamma(2.23432), 0.5621320243666134); + assert_eq!(f_trigamma(-2.4653), 9.653674003034206); + assert_eq!(f_trigamma(0.123541), 66.91128231455282); + assert_eq!(f_trigamma(-0.54331), 9.154415950366596); + assert_eq!(f_trigamma(-5.), f64::INFINITY); + assert_eq!(f_trigamma(f64::INFINITY), 0.0); + assert_eq!(f_trigamma(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert!(f_trigamma(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/trigammaf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigammaf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/gamma/trigammaf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/gamma/trigammaf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,266 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf}; +use crate::polyeval::{f_polyeval6, f_polyeval10}; +use crate::sin_cosf::fast_sinpif; + +#[inline] +fn approx_trigamma(x: f64) -> f64 { + if x <= 1. { + // Polynomial for Trigamma[x+1] + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval10( + x, + f64::from_bits(0x3ffa51a6625307d3), + f64::from_bits(0x40142fc9c4f02b3f), + f64::from_bits(0x401b30a762805b44), + f64::from_bits(0x4014dc84c95656bd), + f64::from_bits(0x4003e44f4c820b4c), + f64::from_bits(0x3fe81f37523197d3), + f64::from_bits(0x3fc22bffe2490221), + f64::from_bits(0x3f8f221a6329ea36), + f64::from_bits(0x3f47406930b9563c), + f64::from_bits(0xbd99cd44c6ad497a), + ); + let p_den = f_polyeval10( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x40121e3db4e0a2f3), + f64::from_bits(0x40218e97a5430c4f), + f64::from_bits(0x402329897737b159), + f64::from_bits(0x401a0fdc27807c2d), + f64::from_bits(0x4006ff242e1f3a51), + f64::from_bits(0x3fea6eda129c4e85), + f64::from_bits(0x3fc32700b2ae2e88), + f64::from_bits(0x3f8fdc1dc6116d41), + f64::from_bits(0x3f4740690261cfbc), + ); + return p_num / p_den + 1. / (x * x); + } else if x <= 4. { + // Polynomial for Trigamma[x+1] + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval10( + x, + f64::from_bits(0x3ffa51a6625307d3), + f64::from_bits(0x4015167fa2d2b5a8), + f64::from_bits(0x401dd40865d5985e), + f64::from_bits(0x4018353d9425fb58), + f64::from_bits(0x4008a12aa45851fa), + f64::from_bits(0x3ff018736d0c5dbe), + f64::from_bits(0x3fca715702bdb519), + f64::from_bits(0x3f9908a9d73d983c), + f64::from_bits(0x3f54fd9cbbb46314), + f64::from_bits(0xbd00b8a28c578ab5), + ); + let p_den = f_polyeval10( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4012aa7f041a768b), + f64::from_bits(0x4022c2604e5f9c7a), + f64::from_bits(0x4025655b63c2db22), + f64::from_bits(0x401eaa8e59c8295d), + f64::from_bits(0x400cc8724a58809c), + f64::from_bits(0x3ff1c7a91c8e3c40), + f64::from_bits(0x3fcc05613a11183e), + f64::from_bits(0x3f99b096bd3ce542), + f64::from_bits(0x3f54fd9cbb9c6167), + ); + return p_num / p_den + 1. / (x * x); + } else if x <= 10. { + // Polynomial for Trigamma[x+1] + // <75,MaxIterations->100] + // num=Numerator[approx]; + // den=Denominator[approx]; + // poly=num; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + // poly=den; + // coeffs=CoefficientList[poly,z]; + // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]] + let p_num = f_polyeval10( + x, + f64::from_bits(0x3ffa51a664b1b211), + f64::from_bits(0x4016d7f75881312a), + f64::from_bits(0x4021b10defb47bcc), + f64::from_bits(0x401fe9633665e1bf), + f64::from_bits(0x4012601cce6766d7), + f64::from_bits(0x3ffbd0ece1c435f1), + f64::from_bits(0x3fdb3fd0e233c485), + f64::from_bits(0x3faffdedea90b870), + f64::from_bits(0x3f71a4bbf0d00147), + f64::from_bits(0xbc0aae286498a357), + ); + let p_den = f_polyeval10( + x, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x4013bbbd604d685d), + f64::from_bits(0x40253a4fca05438e), + f64::from_bits(0x402a4aba4634f14f), + f64::from_bits(0x4024cdd23bd6284a), + f64::from_bits(0x4015fbe371275c3f), + f64::from_bits(0x3fff4d7ebf7d1ed0), + f64::from_bits(0x3fdd459154d7bc72), + f64::from_bits(0x3fb08c1cd4cedca3), + f64::from_bits(0x3f71a4bbf0d0012d), + ); + return p_num / p_den + 1. / (x * x); + } + // asymptotic expansion Trigamma[x] = 1/x + 1/x^2 + sum(Bernoulli(2*k)/x^(2*k + 1)) + // Generated in SageMath: + // var('x') + // def bernoulli_terms(x, N): + // S = 0 + // for k in range(1, N+1): + // B = bernoulli(2*k) + // term = B*x**(-(2*k+1)) + // S += term + // return S + // + // terms = bernoulli_terms(x, 7) + // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] + // for k in range(0, 14): + // c = terms.coefficient(x, -k) # coefficient of x^(-k) + // if c == 0: + // continue + // print("f64::from_bits(" + double_to_hex(c) + "),") + let r = 1. / x; + let r2 = r * r; + let p = f_polyeval6( + r2, + f64::from_bits(0x3fc5555555555555), + f64::from_bits(0xbfa1111111111111), + f64::from_bits(0x3f98618618618618), + f64::from_bits(0xbfa1111111111111), + f64::from_bits(0x3fb364d9364d9365), + f64::from_bits(0xbfd0330330330330), + ); + f_fmla(p, r2 * r, f_fmla(r2, 0.5, r)) +} + +/// Computes the trigamma function ψ₁(x). +/// +/// The trigamma function is the second derivative of the logarithm of the gamma function. +pub fn f_trigammaf(x: f32) -> f32 { + let xb = x.to_bits(); + // filter out exceptional cases + if xb >= 0xffu32 << 23 || xb == 0 { + if x.is_infinite() { + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + 0. + }; + } + if x.is_nan() { + return f32::NAN; + } + if xb.wrapping_shl(1) == 0 { + return f32::INFINITY; + } + } + + let ax = x.to_bits() & 0x7fff_ffff; + + if ax <= 0x34000000u32 { + // |x| < f32::EPSILON + let dx = x as f64; + return (1. / (dx * dx)) as f32; + } + + let mut dx = x as f64; + + let mut result = 0.; + let mut sum_parity: f64 = 1.0; + + if x < 0. { + // singularity at negative integers + if is_integerf(x) { + return f32::INFINITY; + } + // reflection formula + // Trigamma[1-x] + Trigamma[x] = PI^2 / sinpi^2(x) + const SQR_PI: f64 = f64::from_bits(0x4023bd3cc9be45de); // pi^2 + let sinpi_ax = fast_sinpif(-x); + dx = 1. - dx; + result = SQR_PI / (sinpi_ax * sinpi_ax); + sum_parity = -1.; + } + + let r = approx_trigamma(dx) * sum_parity; + result += r; + result as f32 +} + +#[cfg(test)] +mod tests { + use crate::f_trigammaf; + + #[test] + fn test_trigamma() { + assert_eq!(f_trigammaf(-27.058018), 300.35904); + assert_eq!(f_trigammaf(27.058018), 0.037648965); + assert_eq!(f_trigammaf(8.058018), 0.13211797); + assert_eq!(f_trigammaf(-8.058018), 300.27863); + assert_eq!(f_trigammaf(2.23432), 0.56213206); + assert_eq!(f_trigammaf(-2.4653), 9.653673); + assert_eq!(f_trigammaf(0.123541), 66.911285); + assert_eq!(f_trigammaf(-0.54331), 9.154416); + assert_eq!(f_trigammaf(-5.), f32::INFINITY); + assert_eq!(f_trigammaf(-0.), f32::INFINITY); + assert_eq!(f_trigammaf(0.), f32::INFINITY); + assert_eq!(f_trigammaf(f32::INFINITY), 0.0); + assert_eq!(f_trigammaf(f32::NEG_INFINITY), f32::NEG_INFINITY); + assert!(f_trigammaf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acosh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acosh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acosh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acosh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,693 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; + +pub(crate) static ACOSH_ASINH_LL: [[(u64, u64, u64); 17]; 4] = [ + [ + (0x0000000000000000, 0x0000000000000000, 0x0000000000000000), + (0x3f962e432b240000, 0xbd5745af34bb54b8, 0xb9e17e3ec05cde70), + (0x3fa62e42e4a80000, 0x3d3111a4eadf3120, 0x3a2cff3027abb119), + (0x3fb0a2b233f10000, 0xbd588ac4ec78af80, 0x3a24fa087ca75dfd), + (0x3fb62e43056c0000, 0x3d16bd65e8b0b700, 0xba0b18e160362c24), + (0x3fbbb9d3cbd60000, 0x3d5de14aa55ec2b0, 0xba1c6ac3f1862a6b), + (0x3fc0a2b244da0000, 0x3d594def487fea70, 0xba1dead1a4581acf), + (0x3fc3687aa9b78000, 0x3d49cec9a50db220, 0x3a234a70684f8e0e), + (0x3fc62e42faba0000, 0xbd3d69047a3aeb00, 0xba04e061f79144e2), + (0x3fc8f40b56d28000, 0x3d5de7d755fd2e20, 0x3a1bdc7ecf001489), + (0x3fcbb9d3b61f0000, 0x3d1c14f1445b1200, 0x3a2a1d78cbdc5b58), + (0x3fce7f9c11f08000, 0xbd46e3e0000dae70, 0x3a16a4559fadde98), + (0x3fd0a2b242ec4000, 0x3d5bb7cf852a5fe8, 0x3a2a6aef11ee43bd), + (0x3fd205966c764000, 0x3d2ad3a5f2142940, 0x3a25cc344fa10652), + (0x3fd3687a98aac000, 0x3d21623671842f00, 0xba10b428fe1f9e43), + (0x3fd4cb5ec93f4000, 0x3d53d50980ea5130, 0x3a267f0ea083b1c4), + (0x3fd62e42fefa4000, 0xbd38432a1b0e2640, 0x3a2803f2f6af40f3), + ], + [ + (0x0000000000000000, 0x0000000000000000, 0x0000000000000000), + (0x3f562e462b400000, 0x3d5061d003b97318, 0x3a2d7faee66a2e1e), + (0x3f662e44c9200000, 0x3d595a7bff5e2390, 0xba0f7e788a871350), + (0x3f70a2b1e3300000, 0x3d42a3a1a65aa3a0, 0xba254599c9605442), + (0x3f762e4367c00000, 0xbd24a995b6d9ddc0, 0xb9b56bb79b254f33), + (0x3f7bb9d449a00000, 0x3d58a119c42e9bc0, 0xba28ecf7d8d661f1), + (0x3f80a2b1f1900000, 0x3d58863771bd10a8, 0x3a1e9731de7f0155), + (0x3f83687ad1100000, 0x3d5e026a347ca1c8, 0x39efadc62522444d), + (0x3f862e436f280000, 0x3d525b84f71b70b8, 0xb9ffcb3f98612d27), + (0x3f88f40b7b380000, 0xbd462a0a4fd47580, 0x3a23cb3c35d9f6a1), + (0x3f8bb9d3abb00000, 0xbd50ec48f94d7860, 0xba26b47d410e4cc7), + (0x3f8e7f9bb2300000, 0x3d4e4415cbc97a00, 0xba23729fdb677231), + (0x3f90a2b224780000, 0xbd5cb73f4505b030, 0xba21b3b3a3bc370a), + (0x3f92059691e80000, 0xbd4abcc3412f2640, 0xba0fe6e998e48673), + (0x3f93687a76800000, 0xbd543901e5c97a90, 0x39fb54cdd52a5d88), + (0x3f94cb5eb5d80000, 0xbd58f106f00f13b8, 0xba28f793f5fce148), + (0x3f962e432b240000, 0xbd5745af34bb54b8, 0xb9e17e3ec05cde70), + ], + [ + (0x0000000000000000, 0x0000000000000000, 0x0000000000000000), + (0x3f162e7b00000000, 0xbd3868625640a680, 0xba234bf0db910f65), + (0x3f262e35f6000000, 0xbd42ee3d96b696a0, 0x3a1a2948cd558655), + (0x3f30a2b4b2000000, 0x3d053edbcf116500, 0xb9ecfc26ccf6d0e4), + (0x3f362e4be1000000, 0x3cb783e334614000, 0xba204b96da30e63a), + (0x3f3bb9e085000000, 0xbd460785f20acb20, 0xb9ff33369bf7dff1), + (0x3f40a2b94d000000, 0x3d5fd4b3a2733530, 0xb9f685a35575eff1), + (0x3f4368810f800000, 0x3d07ded26dc81300, 0xb9f4c4d1abca79bf), + (0x3f462e4787800000, 0x3d57d2bee9a1f630, 0x3a2860233b7ad130), + (0x3f48f40cb4800000, 0xbd5af034eaf471c0, 0x3a1ae748822d57b7), + (0x3f4bb9d094000000, 0xbd57a223013a20f0, 0xba21e499087075b6), + (0x3f4e7fa32c800000, 0xbd4b2e67b1b59bd0, 0xba254a41eda30fa6), + (0x3f50a2b237000000, 0xbd37ad97ff4ac7a0, 0x3a2f932da91371dd), + (0x3f52059a33800000, 0xbd396422d90df400, 0xba190800fbbf2ed3), + (0x3f53687982400000, 0x3d30f90540018120, 0x3a29567e01e48f9a), + (0x3f54cb602c000000, 0xbd40d709a5ec0b50, 0x3a1253dfd44635d2), + (0x3f562e462b400000, 0x3d5061d003b97318, 0x3a2d7faee66a2e1e), + ], + [ + (0x0000000000000000, 0x0000000000000000, 0x0000000000000000), + (0x3ed63007c0000000, 0xbd4db0e38e5aaaa0, 0x3a2259a7b94815b9), + (0x3ee6300f60000000, 0x3d32b1c755804380, 0x3a278cabba01e3e4), + (0x3ef0a21150000000, 0xbd55ff2237307590, 0x3a08074feacfe49d), + (0x3ef62e1ec0000000, 0xbd285d6f6487ce40, 0x3a205485074b9276), + (0x3efbba3010000000, 0xbd4af5d58a7c9210, 0xba230a8c0fd2ff5f), + (0x3f00a32298000000, 0x3d4590faa0883bd0, 0x3a295e9bda999947), + (0x3f03682f10000000, 0x3d5f0224376efaf8, 0xba25843c0db50d10), + (0x3f062e3d80000000, 0xbd4142c13daed4a0, 0x3a2c68a61183ce87), + (0x3f08f44dd8000000, 0xbd4aa489f3999310, 0x3a111c5c376854ea), + (0x3f0bb96010000000, 0x3d59904d8b6a3638, 0x3a28c89554493c8f), + (0x3f0e7f7440000000, 0x3d55785ddbe7cba8, 0x3a1e7ff3cde7d70c), + (0x3f10a2c530000000, 0xbd46d9e8780d0d50, 0x3a1ad9c178106693), + (0x3f1205d134000000, 0xbd4214a2e893fcc0, 0x3a2548a9500c9822), + (0x3f13685e28000000, 0x3d4e235886461030, 0x3a12a97b26da2d88), + (0x3f14cb6c18000000, 0x3d52b7cfcea9e0d8, 0xba25095048a6b824), + (0x3f162e7b00000000, 0xbd3868625640a680, 0xba234bf0db910f65), + ], +]; + +pub(crate) static ACOSH_SINH_REFINE_T1: [u64; 17] = [ + 0x3ff0000000000000, + 0x3feea4afa0000000, + 0x3fed5818e0000000, + 0x3fec199be0000000, + 0x3feae89f98000000, + 0x3fe9c49180000000, + 0x3fe8ace540000000, + 0x3fe7a11470000000, + 0x3fe6a09e68000000, + 0x3fe5ab07e0000000, + 0x3fe4bfdad8000000, + 0x3fe3dea650000000, + 0x3fe306fe08000000, + 0x3fe2387a70000000, + 0x3fe172b840000000, + 0x3fe0b55870000000, + 0x3fe0000000000000, +]; + +pub(crate) static ACOSH_ASINH_REFINE_T2: [u64; 16] = [ + 0x3ff0000000000000, + 0x3fefe9d968000000, + 0x3fefd3c228000000, + 0x3fefbdba38000000, + 0x3fefa7c180000000, + 0x3fef91d800000000, + 0x3fef7bfdb0000000, + 0x3fef663278000000, + 0x3fef507658000000, + 0x3fef3ac948000000, + 0x3fef252b38000000, + 0x3fef0f9c20000000, + 0x3feefa1bf0000000, + 0x3feee4aaa0000000, + 0x3feecf4830000000, + 0x3feeb9f488000000, +]; + +pub(crate) static ACOSH_SINH_REFINE_T3: [u64; 16] = [ + 0x3ff0000000000000, + 0x3feffe9d20000000, + 0x3feffd3a58000000, + 0x3feffbd798000000, + 0x3feffa74e8000000, + 0x3feff91248000000, + 0x3feff7afb8000000, + 0x3feff64d38000000, + 0x3feff4eac8000000, + 0x3feff38868000000, + 0x3feff22618000000, + 0x3feff0c3d0000000, + 0x3fefef61a0000000, + 0x3fefedff78000000, + 0x3fefec9d68000000, + 0x3fefeb3b60000000, +]; + +pub(crate) static ACOSH_ASINH_REFINE_T4: [u64; 16] = [ + 0x3ff0000000000000, + 0x3fefffe9d0000000, + 0x3fefffd3a0000000, + 0x3fefffbd78000000, + 0x3fefffa748000000, + 0x3fefff9118000000, + 0x3fefff7ae8000000, + 0x3fefff64c0000000, + 0x3fefff4e90000000, + 0x3fefff3860000000, + 0x3fefff2238000000, + 0x3fefff0c08000000, + 0x3feffef5d8000000, + 0x3feffedfa8000000, + 0x3feffec980000000, + 0x3feffeb350000000, +]; + +#[cold] +fn acosh_refine(x: f64, a: f64) -> f64 { + let ix = x.to_bits(); + + let z: DoubleDouble = if ix < 0x4190000000000000u64 { + let dx2 = DoubleDouble::from_exact_mult(x, x); + let w = DoubleDouble::from_exact_add(dx2.hi - 1., dx2.lo); + let sh = w.hi.sqrt(); + let ish = 0.5 / w.hi; + let sl = (ish * sh) * (w.lo - dd_fmla(sh, sh, -w.hi)); + let mut p = DoubleDouble::from_exact_add(x, sh); + p.lo += sl; + DoubleDouble::from_exact_add(p.hi, p.lo) + } else if ix < 0x4330000000000000 { + DoubleDouble::new(-0.5 / x, 2. * x) + } else { + DoubleDouble::new(0., x) + }; + + let mut t = z.hi.to_bits(); + let ex: i32 = (t >> 52) as i32; + let e = ex.wrapping_sub(0x3ff) + if z.lo == 0.0 { 1i32 } else { 0i32 }; + t &= 0x000fffffffffffff; + t |= 0x3ffu64 << 52; + let ed = e as f64; + let v = (a - ed + f64::from_bits(0x3ff0000800000000)).to_bits(); + let i = (v.wrapping_sub(0x3ffu64 << 52)) >> (52 - 16); + let i1 = (i >> 12) & 0x1f; + let i2 = (i >> 8) & 0xf; + let i3 = (i >> 4) & 0xf; + let i4 = i & 0xf; + const L20: f64 = f64::from_bits(0x3fd62e42fefa3800); + const L21: f64 = f64::from_bits(0x3d1ef35793c76800); + const L22: f64 = f64::from_bits(0xba49ff0342542fc3); + let el2 = L22 * ed; + let el1 = L21 * ed; + let el0 = L20 * ed; + let mut dl0: f64; + + let ll0i1 = ACOSH_ASINH_LL[0][i1 as usize]; + let ll1i2 = ACOSH_ASINH_LL[1][i2 as usize]; + let ll2i3 = ACOSH_ASINH_LL[2][i3 as usize]; + let ll3i4 = ACOSH_ASINH_LL[3][i4 as usize]; + + dl0 = f64::from_bits(ll0i1.0) + + f64::from_bits(ll1i2.0) + + (f64::from_bits(ll2i3.0) + f64::from_bits(ll3i4.0)); + let dl1 = f64::from_bits(ll0i1.1) + + f64::from_bits(ll1i2.1) + + (f64::from_bits(ll2i3.1) + f64::from_bits(ll3i4.1)); + let dl2 = f64::from_bits(ll0i1.2) + + f64::from_bits(ll1i2.2) + + (f64::from_bits(ll2i3.2) + f64::from_bits(ll3i4.2)); + dl0 += el0; + let t12 = f64::from_bits(ACOSH_SINH_REFINE_T1[i1 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T2[i2 as usize]); + let t34 = f64::from_bits(ACOSH_SINH_REFINE_T3[i3 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T4[i4 as usize]); + let th = t12 * t34; + let tl = dd_fmla(t12, t34, -th); + let dh = th * f64::from_bits(t); + let dl = dd_fmla(th, f64::from_bits(t), -dh); + let sh = tl * f64::from_bits(t); + let sl = dd_fmla(tl, f64::from_bits(t), -sh); + + let mut dx = DoubleDouble::from_exact_add(dh - 1., dl); + if z.lo != 0.0 { + t = z.lo.to_bits(); + t = t.wrapping_sub((e as i64).wrapping_shl(52) as u64); + dx.lo += th * f64::from_bits(t); + } + dx = DoubleDouble::add(dx, DoubleDouble::new(sl, sh)); + const CL: [u64; 3] = [0xbfc0000000000000, 0x3fb9999999a0754f, 0xbfb55555555c3157]; + let sl = dx.hi + * (f64::from_bits(CL[0]) + dx.hi * (f64::from_bits(CL[1]) + dx.hi * f64::from_bits(CL[2]))); + const CH: [(u64, u64); 3] = [ + (0x39024b67ee516e3b, 0x3fe0000000000000), + (0xb91932ce43199a8d, 0xbfd0000000000000), + (0x3c655540c15cf91f, 0x3fc5555555555555), + ]; + let mut s = lpoly_xd_generic(dx, CH, sl); + s = DoubleDouble::quick_mult(dx, s); + s = DoubleDouble::add(s, DoubleDouble::new(el2, el1)); + s = DoubleDouble::add(s, DoubleDouble::new(dl2, dl1)); + let mut v02 = DoubleDouble::from_exact_add(dl0, s.hi); + let mut v12 = DoubleDouble::from_exact_add(v02.lo, s.lo); + v02.hi *= 2.; + v12.hi *= 2.; + v12.lo *= 2.; + t = v12.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = v12.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + v12.hi = f64::from_bits(t); + } + v02.hi + v12.hi +} + +pub(crate) static ACOSH_ASINH_B: [[i32; 2]; 32] = [ + [301, 27565], + [7189, 24786], + [13383, 22167], + [18923, 19696], + [23845, 17361], + [28184, 15150], + [31969, 13054], + [35231, 11064], + [37996, 9173], + [40288, 7372], + [42129, 5657], + [43542, 4020], + [44546, 2457], + [45160, 962], + [45399, -468], + [45281, -1838], + [44821, -3151], + [44032, -4412], + [42929, -5622], + [41522, -6786], + [39825, -7905], + [37848, -8982], + [35602, -10020], + [33097, -11020], + [30341, -11985], + [27345, -12916], + [24115, -13816], + [20661, -14685], + [16989, -15526], + [13107, -16339], + [9022, -17126], + [4740, -17889], +]; + +pub(crate) static ACOSH_ASINH_R1: [u64; 33] = [ + 0x3ff0000000000000, + 0x3fef507600000000, + 0x3feea4b000000000, + 0x3fedfc9800000000, + 0x3fed581800000000, + 0x3fecb72000000000, + 0x3fec199c00000000, + 0x3feb7f7600000000, + 0x3feae8a000000000, + 0x3fea550400000000, + 0x3fe9c49200000000, + 0x3fe9373800000000, + 0x3fe8ace600000000, + 0x3fe8258a00000000, + 0x3fe7a11400000000, + 0x3fe71f7600000000, + 0x3fe6a09e00000000, + 0x3fe6247e00000000, + 0x3fe5ab0800000000, + 0x3fe5342c00000000, + 0x3fe4bfda00000000, + 0x3fe44e0800000000, + 0x3fe3dea600000000, + 0x3fe371a800000000, + 0x3fe306fe00000000, + 0x3fe29e9e00000000, + 0x3fe2387a00000000, + 0x3fe1d48800000000, + 0x3fe172b800000000, + 0x3fe1130200000000, + 0x3fe0b55800000000, + 0x3fe059b000000000, + 0x3fe0000000000000, +]; + +pub(crate) static ACOSH_ASINH_R2: [u64; 33] = [ + 0x3ff0000000000000, + 0x3feffa7400000000, + 0x3feff4ea00000000, + 0x3fefef6200000000, + 0x3fefe9da00000000, + 0x3fefe45200000000, + 0x3fefdecc00000000, + 0x3fefd94600000000, + 0x3fefd3c200000000, + 0x3fefce3e00000000, + 0x3fefc8bc00000000, + 0x3fefc33a00000000, + 0x3fefbdba00000000, + 0x3fefb83a00000000, + 0x3fefb2bc00000000, + 0x3fefad3e00000000, + 0x3fefa7c200000000, + 0x3fefa24600000000, + 0x3fef9cca00000000, + 0x3fef975000000000, + 0x3fef91d800000000, + 0x3fef8c6000000000, + 0x3fef86e800000000, + 0x3fef817200000000, + 0x3fef7bfe00000000, + 0x3fef768a00000000, + 0x3fef711600000000, + 0x3fef6ba400000000, + 0x3fef663200000000, + 0x3fef60c200000000, + 0x3fef5b5200000000, + 0x3fef55e400000000, + 0x3fef507600000000, +]; + +pub(crate) static ACOSH_ASINH_L1: [(u64, u64); 33] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbd1269e2038315b3, 0x3f962e4eacd40000), + (0xbd23f2558bddfc47, 0x3fa62e3ce7218000), + (0x3d207ea13c34efb5, 0x3fb0a2ab6d3ec000), + (0x3d38f3e77084d3ba, 0x3fb62e4a86d8c000), + (0xbd18d92a005f1a7e, 0x3fbbb9db7062c000), + (0x3d358239e799bfe5, 0x3fc0a2b1a22cc000), + (0xbd3a93fcf5f593b7, 0x3fc3687f0a298000), + (0xbd1db4cac32fd2b5, 0x3fc62e4116b64000), + (0xbd10e65a92ee0f3b, 0x3fc8f409e4df6000), + (0xbd38261383d475f1, 0x3fcbb9d15001c000), + (0xbd3359886207513b, 0x3fce7f9a8c940000), + (0x3d3811f87496ceb7, 0x3fd0a2b052ddb000), + (0x3d34991ec6cb435c, 0x3fd205955ef73000), + (0xbd34581abfeb8927, 0x3fd3687bd9121000), + (0x3d3cab48f6942703, 0x3fd4cb5e8f2b5000), + (0xbd0df2c452fde132, 0x3fd62e4420e20000), + (0x3d26109f4fdb74bd, 0x3fd791292c46a000), + (0xbd36b95fbdac7696, 0x3fd8f40af84e7000), + (0x3d17394fa880cbda, 0x3fda56ed8f865000), + (0xbd150b06a94eccab, 0x3fdbb9d6505b4000), + (0xbd3be2abf0b38989, 0x3fdd1cb91e728000), + (0xbd37d6bf1e34da04, 0x3fde7f9d139e2000), + (0xbd3423c1e14de6ed, 0x3fdfe27db9b0e000), + (0x3d3c46f1a0efbbc2, 0x3fe0a2b25060a800), + (0x3d2834fe4e3e6018, 0x3fe154244482a000), + (0x3d16a03d0f02b650, 0x3fe2059731298800), + (0x3d3d437056526f30, 0x3fe2b707145de000), + (0xbd2a0233728405c5, 0x3fe3687b0e0b2800), + (0xbd24dbdda10d2bf1, 0x3fe419ec5d3f6800), + (0x3d3f7d0a25d154f2, 0x3fe4cb5f9fc02000), + (0x3d315ede4d803b18, 0x3fe57cd28421a800), + (0x3d2ef35793c76730, 0x3fe62e42fefa3800), +]; + +pub(crate) static ACOSH_ASINH_L2: [(u64, u64); 33] = [ + (0x0000000000000000, 0x0000000000000000), + (0x3d35abdac3638e99, 0x3f4631ec81e00000), + (0xbd216b8be9bbe239, 0x3f562fd812700000), + (0xbd3364c6315542eb, 0x3f60a25205080000), + (0x3d2734abe459c900, 0x3f662dadc1d00000), + (0x3d30cf8a761431bf, 0x3f6bb9ff94d00000), + (0x3d2da2718eb78708, 0x3f70a2a2def80000), + (0x3d334ada62c59b93, 0x3f7368c0fae40000), + (0x3d3d09ab376682d4, 0x3f762e58e4f80000), + (0xbd23cb7b94329211, 0x3f78f46bd28c0000), + (0xbd2eec5c297c41d0, 0x3f7bb9f831200000), + (0xbd36411b9395d150, 0x3f7e7fff8f300000), + (0xbd31c0e59a43053c, 0x3f80a2c0006e0000), + (0x3d16506596e077b6, 0x3f8205bdb6f00000), + (0x3d3e256bce6faa27, 0x3f836877c86e0000), + (0x3ccbd42467b0c8d1, 0x3f84cb6f55780000), + (0xbd3c4f92132ff0f0, 0x3f862e230e8c0000), + (0xbd380be08bfab390, 0x3f87911440f60000), + (0xbd3f0b1319ceb1f7, 0x3f88f443020a0000), + (0x3d2a65fcfb8de99b, 0x3f8a572dbef40000), + (0x3d14233885d3779c, 0x3f8bb9d449a60000), + (0x3d3f46a59e646edb, 0x3f8d1cb8491c0000), + (0xbd3c3d2f11c11446, 0x3f8e7fd9d2aa0000), + (0x3d27763f78a1e0cc, 0x3f8fe2b6f9780000), + (0x3d3b4c37fc60c043, 0x3f90a2a7c7a50000), + (0xbd15b8a822859be3, 0x3f915412ca860000), + (0xbd3f2d8c9fc06400, 0x3f92059c90050000), + (0xbd3e80e79c20378d, 0x3f92b703f49b0000), + (0x3d368256e4329bdb, 0x3f93688a1a8d0000), + (0x3d37e9741da248c3, 0x3f9419edc7ba0000), + (0x3d2e330dccce602b, 0x3f94cb7034fa0000), + (0x3ce2f32b5d18eefb, 0x3f957cd011870000), + (0xbd1269e2038315b3, 0x3f962e4eacd40000), +]; + +#[inline] +pub(crate) fn lpoly_xd_generic( + x: DoubleDouble, + poly: [(u64, u64); N], + l: f64, +) -> DoubleDouble { + let zch = poly.last().unwrap(); + + let tch = f64::from_bits(zch.1) + l; + + let mut ch = DoubleDouble::new( + ((f64::from_bits(zch.1) - tch) + l) + f64::from_bits(zch.0), + tch, + ); + + for zch in poly.iter().rev().skip(1) { + ch = DoubleDouble::mult(ch, x); + let th = ch.hi + f64::from_bits(zch.1); + let tl = (f64::from_bits(zch.1) - th) + ch.hi; + ch.hi = th; + ch.lo += tl + f64::from_bits(zch.0); + } + + ch +} + +#[cold] +fn as_acosh_one(x: f64, sh: f64, sl: f64) -> f64 { + static CH: [(u64, u64); 10] = [ + (0xbc55555555554af1, 0xbfb5555555555555), + (0x3c29999998933f0e, 0x3f93333333333333), + (0x3c024929b16ec6b7, 0xbf76db6db6db6db7), + (0x3bdc56d45e265e2c, 0x3f5f1c71c71c71c7), + (0x3be6d50ce7188d3d, 0xbf46e8ba2e8ba2e9), + (0x3bdc6791d1cf399a, 0x3f31c4ec4ec4ec43), + (0x3bbee0d9408a2e2a, 0xbf1c99999999914f), + (0xbba1cea281e08012, 0x3f07a878787648e2), + (0x3b70335101403d9d, 0xbef3fde50d0cb4b9), + (0x3aff9c6b51787043, 0x3ee12ef3bf8a0a74), + ]; + + const CL: [u64; 6] = [ + 0xbecdf3b9d1296ea9, + 0x3eba681d7d2298eb, + 0xbea77ead7b1ca449, + 0x3e94edd2ddb3721f, + 0xbe81bf173531ee23, + 0x3e6613229230e255, + ]; + + let yw0 = f_fmla(x, f64::from_bits(CL[5]), f64::from_bits(CL[4])); + let yw1 = f_fmla(x, yw0, f64::from_bits(CL[3])); + let yw2 = f_fmla(x, yw1, f64::from_bits(CL[2])); + let yw3 = f_fmla(x, yw2, f64::from_bits(CL[1])); + + let y2 = x * f_fmla(x, yw3, f64::from_bits(CL[0])); + let mut y1 = lpoly_xd_generic(DoubleDouble::new(0., x), CH, y2); + y1 = DoubleDouble::mult_f64(y1, x); + let y0 = DoubleDouble::from_exact_add(1., y1.hi); + let yl = y0.lo + y1.lo; + let p = DoubleDouble::quick_mult(DoubleDouble::new(yl, y0.hi), DoubleDouble::new(sl, sh)); + p.to_f64() +} + +/// Huperbolic acos +/// +/// Max ULP 0.5 +pub fn f_acosh(x: f64) -> f64 { + let ix = x.to_bits(); + if ix >= 0x7ff0000000000000u64 { + let aix = ix.wrapping_shl(1); + if ix == 0x7ff0000000000000u64 || aix > (0x7ffu64 << 53) { + return x + x; + } // +inf or nan + + return f64::NAN; + } + + if ix <= 0x3ff0000000000000u64 { + if ix == 0x3ff0000000000000u64 { + return 0.; + } + return f64::NAN; + } + let mut off: i32 = 0x3fe; + let mut t = ix; + let g = if ix < 0x3ff1e83e425aee63u64 { + let z = x - 1.; + let iz = (-0.25) / z; + let zt = 2. * z; + let sh = zt.sqrt(); + let sl = dd_fmla(sh, sh, -zt) * (sh * iz); + const CL: [u64; 9] = [ + 0xbfb5555555555555, + 0x3f93333333332f95, + 0xbf76db6db6d5534c, + 0x3f5f1c71c1e04356, + 0xbf46e8b8e3e40d58, + 0x3f31c4ba825ac4fe, + 0xbf1c9045534e6d9e, + 0x3f071fedae26a76b, + 0xbeef1f4f8cc65342, + ]; + let z2 = z * z; + let z4 = z2 * z2; + + let ds0 = f_fmla(z, f64::from_bits(CL[8]), f64::from_bits(CL[7])); + let ds1 = f_fmla(z, f64::from_bits(CL[6]), f64::from_bits(CL[5])); + let ds2 = f_fmla(z, f64::from_bits(CL[4]), f64::from_bits(CL[3])); + let ds3 = f_fmla(z, f64::from_bits(CL[2]), f64::from_bits(CL[1])); + + let dsw0 = f_fmla(z2, ds0, ds1); + let dsw1 = f_fmla(z2, ds2, ds3); + let dsw2 = f_fmla(z4, dsw0, dsw1); + + let mut ds = (sh * z) * f_fmla(z, dsw2, f64::from_bits(CL[0])); + + let eps = ds * f64::from_bits(0x3ccfc00000000000) - f64::from_bits(0x3970000000000000) * sh; + ds += sl; + let lb = sh + (ds - eps); + let ub = sh + (ds + eps); + if lb == ub { + return lb; + } + return as_acosh_one(z, sh, sl); + } else if ix < 0x405bf00000000000u64 { + off = 0x3ff; + let x2h = x * x; + let wh = x2h - 1.; + let wl = dd_fmla(x, x, -x2h); + let sh = wh.sqrt(); + let ish = 0.5 / wh; + let sl = (wl - dd_fmla(sh, sh, -wh)) * (sh * ish); + let mut pt = DoubleDouble::from_exact_add(x, sh); + pt.lo += sl; + t = pt.hi.to_bits(); + pt.lo / pt.hi + } else if ix < 0x4087100000000000u64 { + const CL: [u64; 4] = [ + 0x3bd5c4b6148816e2, + 0xbfd000000000005c, + 0xbfb7fffffebf3e6c, + 0xbfaaab6691f2bae7, + ]; + let z = 1. / (x * x); + let zw0 = f_fmla(z, f64::from_bits(CL[3]), f64::from_bits(CL[2])); + let zw1 = f_fmla(z, zw0, f64::from_bits(CL[1])); + f_fmla(z, zw1, f64::from_bits(CL[0])) + } else if ix < 0x40e0100000000000u64 { + const CL: [u64; 3] = [0xbbc7f77c8429c6c6, 0xbfcffffffffff214, 0xbfb8000268641bfe]; + let z = 1. / (x * x); + let zw0 = f_fmla(z, f64::from_bits(CL[2]), f64::from_bits(CL[1])); + f_fmla(z, zw0, f64::from_bits(CL[0])) + } else if ix < 0x41ea000000000000u64 { + const CL: [u64; 2] = [0x3bc7a0ed2effdd10, 0xbfd000000017d048]; + let z = 1. / (x * x); + f_fmla(z, f64::from_bits(CL[1]), f64::from_bits(CL[0])) + } else { + 0. + }; + let ex: i32 = (t >> 52) as i32; + let e = ex - off; + t &= 0x000fffffffffffff; + let ed = e; + let i: u64 = t >> (52 - 5); + let d: i64 = (t & 0x00007fffffffffff) as i64; + let b_i = ACOSH_ASINH_B[i as usize]; + let j: u64 = t + .wrapping_add((b_i[0] as u64).wrapping_shl(33)) + .wrapping_add((b_i[1] as i64).wrapping_mul(d >> 16) as u64) + >> (52 - 10); + t |= 0x3ffu64 << 52; + let i1: i32 = (j >> 5) as i32; + let i2 = j & 0x1f; + let r = + f64::from_bits(ACOSH_ASINH_R1[i1 as usize]) * f64::from_bits(ACOSH_ASINH_R2[i2 as usize]); + let dx = dd_fmla(r, f64::from_bits(t), -1.); + let dx2 = dx * dx; + + const C: [u64; 5] = [ + 0xbfe0000000000000, + 0x3fd5555555555530, + 0xbfcfffffffffffa0, + 0x3fc99999e33a6366, + 0xbfc555559ef9525f, + ]; + + let fw0 = f_fmla(dx, f64::from_bits(C[3]), f64::from_bits(C[2])); + let fw1 = f_fmla(dx, f64::from_bits(C[1]), f64::from_bits(C[0])); + let fw2 = f_fmla(dx2, f64::from_bits(C[4]), fw0); + + let f = dx2 * f_fmla(dx2, fw2, fw1); + const L2H: f64 = f64::from_bits(0x3fe62e42fefa3800); + const L2L: f64 = f64::from_bits(0x3d2ef35793c76730); + let l1r = ACOSH_ASINH_L1[i1 as usize]; + let l2r = ACOSH_ASINH_L2[i2 as usize]; + let lh = f_fmla( + L2H, + ed as f64, + f64::from_bits(l1r.1) + f64::from_bits(l2r.1), + ); + let mut ll = f_fmla(L2L, ed as f64, dx); + ll += g; + ll += f64::from_bits(l1r.0) + f64::from_bits(l2r.0); + ll += f; + let eps = 2.8e-19; + let lb = lh + (ll - eps); + let ub = lh + (ll + eps); + if lb == ub { + return lb; + } + acosh_refine(x, f64::from_bits(0x3ff71547652b82fe) * lb) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + assert_eq!(f_acosh(1.52), 0.9801016289951905); + assert_eq!(f_acosh(1.86), 1.2320677765479648); + assert_eq!(f_acosh(4.52), 2.189191592518765); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acoshf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acoshf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acoshf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/acoshf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::hyperbolic::asinhf::log_eval; + +/// Hyperbolic arc cosine function +/// +/// Max ULP 0.5 +#[inline] +pub fn f_acoshf(x: f32) -> f32 { + if x <= 1.0 { + if x == 1.0 { + return 0.0; + } + // x < 1. + return f32::NAN; + } + + if !x.is_finite() { + return x; + } + let x_d = x as f64; + // acosh(x) = log(x + sqrt(x^2 - 1)) + log_eval(x_d + (f_fmla(x_d, x_d, -1.0).sqrt())) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_acoshf() { + assert_eq!(f_acoshf(2.0), 1.316958); + assert!(f_acoshf(0.5).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::hyperbolic::acosh::{ + ACOSH_ASINH_B, ACOSH_ASINH_L1, ACOSH_ASINH_L2, ACOSH_ASINH_LL, ACOSH_ASINH_R1, ACOSH_ASINH_R2, + ACOSH_ASINH_REFINE_T2, ACOSH_ASINH_REFINE_T4, ACOSH_SINH_REFINE_T1, ACOSH_SINH_REFINE_T3, + lpoly_xd_generic, +}; + +#[cold] +fn asinh_refine(x: f64, a: f64, z: DoubleDouble) -> f64 { + let mut t = z.hi.to_bits(); + let ex: i32 = (t >> 52) as i32; + let e = ex.wrapping_sub(0x3ff) + if z.lo == 0.0 { 1i32 } else { 0i32 }; + t &= 0x000fffffffffffff; + t |= 0x3ffu64 << 52; + let ed = e as f64; + let v = (a - ed + f64::from_bits(0x3ff0000800000000)).to_bits(); + let i = (v.wrapping_sub(0x3ffu64 << 52)) >> (52 - 16); + let i1 = (i >> 12) & 0x1f; + let i2 = (i >> 8) & 0xf; + let i3 = (i >> 4) & 0xf; + let i4 = i & 0xf; + const L20: f64 = f64::from_bits(0x3fd62e42fefa3800); + const L21: f64 = f64::from_bits(0x3d1ef35793c76800); + const L22: f64 = f64::from_bits(0xba49ff0342542fc3); + let el2 = L22 * ed; + let el1 = L21 * ed; + let el0 = L20 * ed; + let mut dl0: f64; + + let ll0i1 = ACOSH_ASINH_LL[0][i1 as usize]; + let ll1i2 = ACOSH_ASINH_LL[1][i2 as usize]; + let ll2i3 = ACOSH_ASINH_LL[2][i3 as usize]; + let ll3i4 = ACOSH_ASINH_LL[3][i4 as usize]; + + dl0 = f64::from_bits(ll0i1.0) + + f64::from_bits(ll1i2.0) + + (f64::from_bits(ll2i3.0) + f64::from_bits(ll3i4.0)); + let dl1 = f64::from_bits(ll0i1.1) + + f64::from_bits(ll1i2.1) + + (f64::from_bits(ll2i3.1) + f64::from_bits(ll3i4.1)); + let dl2 = f64::from_bits(ll0i1.2) + + f64::from_bits(ll1i2.2) + + (f64::from_bits(ll2i3.2) + f64::from_bits(ll3i4.2)); + dl0 += el0; + let t12 = f64::from_bits(ACOSH_SINH_REFINE_T1[i1 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T2[i2 as usize]); + let t34 = f64::from_bits(ACOSH_SINH_REFINE_T3[i3 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T4[i4 as usize]); + let th = t12 * t34; + let tl = dd_fmla(t12, t34, -th); + let dh = th * f64::from_bits(t); + let dl = dd_fmla(th, f64::from_bits(t), -dh); + let sh = tl * f64::from_bits(t); + let sl = dd_fmla(tl, f64::from_bits(t), -sh); + + let mut dx = DoubleDouble::from_exact_add(dh - 1., dl); + if z.lo != 0.0 { + t = z.lo.to_bits(); + t = t.wrapping_sub((e as i64).wrapping_shl(52) as u64); + dx.lo += th * f64::from_bits(t); + } + dx = DoubleDouble::add(dx, DoubleDouble::new(sl, sh)); + const CL: [u64; 3] = [0xbfc0000000000000, 0x3fb9999999a0754f, 0xbfb55555555c3157]; + + let sl0 = f_fmla(dx.hi, f64::from_bits(CL[2]), f64::from_bits(CL[1])); + let sl1 = f_fmla(dx.hi, sl0, f64::from_bits(CL[0])); + + let sl = dx.hi * sl1; + const CH: [(u64, u64); 3] = [ + (0x39024b67ee516e3b, 0x3fe0000000000000), + (0xb91932ce43199a8d, 0xbfd0000000000000), + (0x3c655540c15cf91f, 0x3fc5555555555555), + ]; + let mut s = lpoly_xd_generic(dx, CH, sl); + s = DoubleDouble::quick_mult(dx, s); + s = DoubleDouble::add(s, DoubleDouble::new(el2, el1)); + s = DoubleDouble::add(s, DoubleDouble::new(dl2, dl1)); + let mut v02 = DoubleDouble::from_exact_add(dl0, s.hi); + let mut v12 = DoubleDouble::from_exact_add(v02.lo, s.lo); + let scale = f64::copysign(2., x); + v02.hi *= scale; + v12.hi *= scale; + v12.lo *= scale; + t = v12.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = v12.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + v12.hi = f64::from_bits(t); + } + v02.hi + v12.hi +} + +#[cold] +fn as_asinh_zero(x: f64, x2h: f64, x2l: f64) -> f64 { + static CH: [(u64, u64); 12] = [ + (0xbc65555555555555, 0xbfc5555555555555), + (0x3c499999999949df, 0x3fb3333333333333), + (0x3c32492496091b0c, 0xbfa6db6db6db6db7), + (0x3c1c71a35cfa0671, 0x3f9f1c71c71c71c7), + (0x3c317f937248cf81, 0xbf96e8ba2e8ba2e9), + (0xbc374e3c1dfd4c3d, 0x3f91c4ec4ec4ec4f), + (0xbc238e7a467ecc55, 0xbf8c999999999977), + (0x3c2a83c7bace55eb, 0x3f87a87878786c7e), + (0xbc2d024df7fa0542, 0xbf83fde50d764083), + (0xbc2ba9c13deb261f, 0x3f812ef3ceae4d12), + (0xbc1546da9bc5b32a, 0xbf7df3bd104aa267), + (0x3c140d284a1d67f9, 0x3f7a685fc5de7a04), + ]; + + const CL: [u64; 5] = [ + 0xbf77828d553ec800, + 0x3f751712f7bee368, + 0xbf72e6d98527bcc6, + 0x3f70095da47b392c, + 0xbf63b92d6368192c, + ]; + + let yw0 = f_fmla(x2h, f64::from_bits(CL[4]), f64::from_bits(CL[3])); + let yw1 = f_fmla(x2h, yw0, f64::from_bits(CL[2])); + let yw2 = f_fmla(x2h, yw1, f64::from_bits(CL[1])); + + let y2 = x2h * f_fmla(x2h, yw2, f64::from_bits(CL[0])); + let mut y1 = lpoly_xd_generic(DoubleDouble::new(x2l, x2h), CH, y2); + y1 = DoubleDouble::quick_mult(y1, DoubleDouble::new(x2l, x2h)); + y1 = DoubleDouble::quick_mult_f64(y1, x); + + let y0 = DoubleDouble::from_exact_add(x, y1.hi); + let mut p = DoubleDouble::from_exact_add(y0.lo, y1.lo); + + let mut t = p.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = p.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + p.hi = f64::from_bits(t); + } + y0.hi + p.hi +} + +/// Huperbolic sine function +/// +/// Max ULP 0.5 +pub fn f_asinh(x: f64) -> f64 { + let ax = x.abs(); + let ix = ax.to_bits(); + let u = ix; + if u < 0x3fbb000000000000u64 { + // |x| < 0x1.bp-4 + // for |x| < 0x1.7137449123ef7p-26, asinh(x) rounds to x to nearest + // for |x| < 0x1p-1022 we have underflow but not for 0x1p-1022 (to nearest) + if u < 0x3e57137449123ef7u64 { + // |x| < 0x1.7137449123ef7p-26 + if u == 0 { + return x; + } + let res = f_fmla(f64::from_bits(0xbc30000000000000), x, x); + return res; + } + let x2h = x * x; + let x2l = dd_fmla(x, x, -x2h); + let x3h = x2h * x; + let sl; + if u < 0x3f93000000000000u64 { + // |x| < 0x1.3p-6 + if u < 0x3f30000000000000u64 { + // |x| < 0x1p-12 + if u < 0x3e5a000000000000u64 { + // |x| < 0x1.ap-26 + sl = x3h * f64::from_bits(0xbfc5555555555555); + } else { + const CL: [u64; 2] = [0xbfc5555555555555, 0x3fb3333327c57c60]; + let sl0 = f_fmla(x2h, f64::from_bits(CL[1]), f64::from_bits(CL[0])); + sl = x3h * sl0; + } + } else { + const CL: [u64; 4] = [ + 0xbfc5555555555555, + 0x3fb333333332f2ff, + 0xbfa6db6d9a665159, + 0x3f9f186866d775f0, + ]; + let sl0 = f_fmla(x2h, f64::from_bits(CL[3]), f64::from_bits(CL[2])); + let sl1 = f_fmla(x2h, sl0, f64::from_bits(CL[1])); + sl = x3h * f_fmla(x2h, sl1, f64::from_bits(CL[0])); + } + } else { + const CL: [u64; 7] = [ + 0xbfc5555555555555, + 0x3fb3333333333310, + 0xbfa6db6db6da466c, + 0x3f9f1c71c2ea7be4, + 0xbf96e8b651b09d72, + 0x3f91c309fc0e69c2, + 0xbf8bab7833c1e000, + ]; + let c1 = f_fmla(x2h, f64::from_bits(CL[2]), f64::from_bits(CL[1])); + let c3 = f_fmla(x2h, f64::from_bits(CL[4]), f64::from_bits(CL[3])); + let c5 = f_fmla(x2h, f64::from_bits(CL[6]), f64::from_bits(CL[5])); + let x4 = x2h * x2h; + + let sl0 = f_fmla(x4, c5, c3); + let sl1 = f_fmla(x4, sl0, c1); + + sl = x3h * f_fmla(x2h, sl1, f64::from_bits(CL[0])); + } + let eps = f64::from_bits(0x3ca6000000000000) * x3h; + let lb = x + (sl - eps); + let ub = x + (sl + eps); + if lb == ub { + return lb; + } + return as_asinh_zero(x, x2h, x2l); + } + + // |x| >= 0x1.bp-4 + let mut x2h: f64 = 0.; + let mut x2l: f64 = 0.; + let mut off: i32 = 0x3ff; + + let va: DoubleDouble = if u < 0x4190000000000000 { + // x < 0x1p+26 + x2h = x * x; + x2l = dd_fmla(x, x, -x2h); + let mut dt = if u < 0x3ff0000000000000 { + DoubleDouble::from_exact_add(1., x2h) + } else { + DoubleDouble::from_exact_add(x2h, 1.) + }; + dt.lo += x2l; + + let ah = dt.hi.sqrt(); + let rs = 0.5 / dt.hi; + let al = (dt.lo - dd_fmla(ah, ah, -dt.hi)) * (rs * ah); + let mut ma = DoubleDouble::from_exact_add(ah, ax); + ma.lo += al; + ma + } else if u < 0x4330000000000000 { + DoubleDouble::new(0.5 / ax, 2. * ax) + } else { + if u >= 0x7ff0000000000000u64 { + return x + x; + } // +-inf or nan + off = 0x3fe; + DoubleDouble::new(0., ax) + }; + + let mut t = va.hi.to_bits(); + let ex = (t >> 52) as i32; + let e = ex.wrapping_sub(off); + t &= 0x000fffffffffffff; + let ed = e as f64; + let i = t >> (52 - 5); + let d = (t & 0x00007fffffffffff) as i64; + let b_i = ACOSH_ASINH_B[i as usize]; + let j: u64 = t + .wrapping_add((b_i[0] as u64).wrapping_shl(33)) + .wrapping_add((b_i[1] as i64).wrapping_mul(d >> 16) as u64) + >> (52 - 10); + t |= 0x3ffu64 << 52; + let i1 = (j >> 5) as i32; + let i2 = j & 0x1f; + let r = + f64::from_bits(ACOSH_ASINH_R1[i1 as usize]) * f64::from_bits(ACOSH_ASINH_R2[i2 as usize]); + let dx = dd_fmla(r, f64::from_bits(t), -1.); + let dx2 = dx * dx; + const C: [u64; 5] = [ + 0xbfe0000000000000, + 0x3fd5555555555530, + 0xbfcfffffffffffa0, + 0x3fc99999e33a6366, + 0xbfc555559ef9525f, + ]; + + let fw0 = f_fmla(dx, f64::from_bits(C[3]), f64::from_bits(C[2])); + let fw1 = f_fmla(dx, f64::from_bits(C[1]), f64::from_bits(C[0])); + let fw2 = f_fmla(dx2, f64::from_bits(C[4]), fw0); + + let f = dx2 * f_fmla(dx2, fw2, fw1); + const L2H: f64 = f64::from_bits(0x3fe62e42fefa3800); + const L2L: f64 = f64::from_bits(0x3d2ef35793c76730); + let l1i1 = ACOSH_ASINH_L1[i1 as usize]; + let l1i2 = ACOSH_ASINH_L2[i2 as usize]; + let mut lh = f_fmla(L2H, ed, f64::from_bits(l1i1.1) + f64::from_bits(l1i2.1)); + let mut ll = f_fmla( + L2L, + ed, + f64::from_bits(l1i1.0) + f64::from_bits(l1i2.0) + va.lo / va.hi + f, + ); + ll += dx; + lh *= f64::copysign(1., x); + ll *= f64::copysign(1., x); + let eps = 1.63e-19; + let lb = lh + (ll - eps); + let ub = lh + (ll + eps); + if lb == ub { + return lb; + } + if ax < f64::from_bits(0x3fd0000000000000) { + return as_asinh_zero(x, x2h, x2l); + } + asinh_refine(x, f64::from_bits(0x3ff71547652b82fe) * lb.abs(), va) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_asinh() { + assert_eq!(f_asinh(-0.05268859863273256), -0.05266425100170862); + assert_eq!(f_asinh(1.05268859863273256), 0.9181436936151385); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinhf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinhf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinhf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/asinhf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,400 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::{get_exponent_f64, set_exponent_f64}; +use crate::common::f_fmla; +use crate::polyeval::{f_polyeval4, f_polyeval10}; + +// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127. +static ONE_OVER_F: [u64; 128] = [ + 0x3ff0000000000000, + 0x3fefc07f01fc07f0, + 0x3fef81f81f81f820, + 0x3fef44659e4a4271, + 0x3fef07c1f07c1f08, + 0x3feecc07b301ecc0, + 0x3fee9131abf0b767, + 0x3fee573ac901e574, + 0x3fee1e1e1e1e1e1e, + 0x3fede5d6e3f8868a, + 0x3fedae6076b981db, + 0x3fed77b654b82c34, + 0x3fed41d41d41d41d, + 0x3fed0cb58f6ec074, + 0x3fecd85689039b0b, + 0x3feca4b3055ee191, + 0x3fec71c71c71c71c, + 0x3fec3f8f01c3f8f0, + 0x3fec0e070381c0e0, + 0x3febdd2b899406f7, + 0x3febacf914c1bad0, + 0x3feb7d6c3dda338b, + 0x3feb4e81b4e81b4f, + 0x3feb2036406c80d9, + 0x3feaf286bca1af28, + 0x3feac5701ac5701b, + 0x3fea98ef606a63be, + 0x3fea6d01a6d01a6d, + 0x3fea41a41a41a41a, + 0x3fea16d3f97a4b02, + 0x3fe9ec8e951033d9, + 0x3fe9c2d14ee4a102, + 0x3fe999999999999a, + 0x3fe970e4f80cb872, + 0x3fe948b0fcd6e9e0, + 0x3fe920fb49d0e229, + 0x3fe8f9c18f9c18fa, + 0x3fe8d3018d3018d3, + 0x3fe8acb90f6bf3aa, + 0x3fe886e5f0abb04a, + 0x3fe8618618618618, + 0x3fe83c977ab2bedd, + 0x3fe8181818181818, + 0x3fe7f405fd017f40, + 0x3fe7d05f417d05f4, + 0x3fe7ad2208e0ecc3, + 0x3fe78a4c8178a4c8, + 0x3fe767dce434a9b1, + 0x3fe745d1745d1746, + 0x3fe724287f46debc, + 0x3fe702e05c0b8170, + 0x3fe6e1f76b4337c7, + 0x3fe6c16c16c16c17, + 0x3fe6a13cd1537290, + 0x3fe6816816816817, + 0x3fe661ec6a5122f9, + 0x3fe642c8590b2164, + 0x3fe623fa77016240, + 0x3fe6058160581606, + 0x3fe5e75bb8d015e7, + 0x3fe5c9882b931057, + 0x3fe5ac056b015ac0, + 0x3fe58ed2308158ed, + 0x3fe571ed3c506b3a, + 0x3fe5555555555555, + 0x3fe5390948f40feb, + 0x3fe51d07eae2f815, + 0x3fe5015015015015, + 0x3fe4e5e0a72f0539, + 0x3fe4cab88725af6e, + 0x3fe4afd6a052bf5b, + 0x3fe49539e3b2d067, + 0x3fe47ae147ae147b, + 0x3fe460cbc7f5cf9a, + 0x3fe446f86562d9fb, + 0x3fe42d6625d51f87, + 0x3fe4141414141414, + 0x3fe3fb013fb013fb, + 0x3fe3e22cbce4a902, + 0x3fe3c995a47babe7, + 0x3fe3b13b13b13b14, + 0x3fe3991c2c187f63, + 0x3fe3813813813814, + 0x3fe3698df3de0748, + 0x3fe3521cfb2b78c1, + 0x3fe33ae45b57bcb2, + 0x3fe323e34a2b10bf, + 0x3fe30d190130d190, + 0x3fe2f684bda12f68, + 0x3fe2e025c04b8097, + 0x3fe2c9fb4d812ca0, + 0x3fe2b404ad012b40, + 0x3fe29e4129e4129e, + 0x3fe288b01288b013, + 0x3fe27350b8812735, + 0x3fe25e22708092f1, + 0x3fe2492492492492, + 0x3fe23456789abcdf, + 0x3fe21fb78121fb78, + 0x3fe20b470c67c0d9, + 0x3fe1f7047dc11f70, + 0x3fe1e2ef3b3fb874, + 0x3fe1cf06ada2811d, + 0x3fe1bb4a4046ed29, + 0x3fe1a7b9611a7b96, + 0x3fe19453808ca29c, + 0x3fe1811811811812, + 0x3fe16e0689427379, + 0x3fe15b1e5f75270d, + 0x3fe1485f0e0acd3b, + 0x3fe135c81135c811, + 0x3fe12358e75d3033, + 0x3fe1111111111111, + 0x3fe0fef010fef011, + 0x3fe0ecf56be69c90, + 0x3fe0db20a88f4696, + 0x3fe0c9714fbcda3b, + 0x3fe0b7e6ec259dc8, + 0x3fe0a6810a6810a7, + 0x3fe0953f39010954, + 0x3fe0842108421084, + 0x3fe073260a47f7c6, + 0x3fe0624dd2f1a9fc, + 0x3fe05197f7d73404, + 0x3fe0410410410410, + 0x3fe03091b51f5e1a, + 0x3fe0204081020408, + 0x3fe0101010101010, +]; + +// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127. +static LOG_F: [u64; 128] = [ + 0x0000000000000000, + 0x3f7fe02a6b106788, + 0x3f8fc0a8b0fc03e3, + 0x3f97b91b07d5b11a, + 0x3f9f829b0e783300, + 0x3fa39e87b9febd5f, + 0x3fa77458f632dcfc, + 0x3fab42dd711971be, + 0x3faf0a30c01162a6, + 0x3fb16536eea37ae0, + 0x3fb341d7961bd1d0, + 0x3fb51b073f06183f, + 0x3fb6f0d28ae56b4b, + 0x3fb8c345d6319b20, + 0x3fba926d3a4ad563, + 0x3fbc5e548f5bc743, + 0x3fbe27076e2af2e5, + 0x3fbfec9131dbeaba, + 0x3fc0d77e7cd08e59, + 0x3fc1b72ad52f67a0, + 0x3fc29552f81ff523, + 0x3fc371fc201e8f74, + 0x3fc44d2b6ccb7d1e, + 0x3fc526e5e3a1b437, + 0x3fc5ff3070a793d3, + 0x3fc6d60fe719d21c, + 0x3fc7ab890210d909, + 0x3fc87fa06520c910, + 0x3fc9525a9cf456b4, + 0x3fca23bc1fe2b563, + 0x3fcaf3c94e80bff2, + 0x3fcbc286742d8cd6, + 0x3fcc8ff7c79a9a21, + 0x3fcd5c216b4fbb91, + 0x3fce27076e2af2e5, + 0x3fcef0adcbdc5936, + 0x3fcfb9186d5e3e2a, + 0x3fd0402594b4d040, + 0x3fd0a324e27390e3, + 0x3fd1058bf9ae4ad5, + 0x3fd1675cababa60e, + 0x3fd1c898c16999fa, + 0x3fd22941fbcf7965, + 0x3fd2895a13de86a3, + 0x3fd2e8e2bae11d30, + 0x3fd347dd9a987d54, + 0x3fd3a64c556945e9, + 0x3fd404308686a7e3, + 0x3fd4618bc21c5ec2, + 0x3fd4be5f957778a0, + 0x3fd51aad872df82d, + 0x3fd5767717455a6c, + 0x3fd5d1bdbf5809ca, + 0x3fd62c82f2b9c795, + 0x3fd686c81e9b14ae, + 0x3fd6e08eaa2ba1e3, + 0x3fd739d7f6bbd006, + 0x3fd792a55fdd47a2, + 0x3fd7eaf83b82afc3, + 0x3fd842d1da1e8b17, + 0x3fd89a3386c1425a, + 0x3fd8f11e873662c7, + 0x3fd947941c2116fa, + 0x3fd99d958117e08a, + 0x3fd9f323ecbf984b, + 0x3fda484090e5bb0a, + 0x3fda9cec9a9a0849, + 0x3fdaf1293247786b, + 0x3fdb44f77bcc8f62, + 0x3fdb9858969310fb, + 0x3fdbeb4d9da71b7b, + 0x3fdc3dd7a7cdad4d, + 0x3fdc8ff7c79a9a21, + 0x3fdce1af0b85f3eb, + 0x3fdd32fe7e00ebd5, + 0x3fdd83e7258a2f3e, + 0x3fddd46a04c1c4a0, + 0x3fde24881a7c6c26, + 0x3fde744261d68787, + 0x3fdec399d2468cc0, + 0x3fdf128f5faf06ec, + 0x3fdf6123fa7028ac, + 0x3fdfaf588f78f31e, + 0x3fdffd2e0857f498, + 0x3fe02552a5a5d0fe, + 0x3fe04bdf9da926d2, + 0x3fe0723e5c1cdf40, + 0x3fe0986f4f573520, + 0x3fe0be72e4252a82, + 0x3fe0e44985d1cc8b, + 0x3fe109f39e2d4c96, + 0x3fe12f719593efbc, + 0x3fe154c3d2f4d5e9, + 0x3fe179eabbd899a0, + 0x3fe19ee6b467c96e, + 0x3fe1c3b81f713c24, + 0x3fe1e85f5e7040d0, + 0x3fe20cdcd192ab6d, + 0x3fe23130d7bebf42, + 0x3fe2555bce98f7cb, + 0x3fe2795e1289b11a, + 0x3fe29d37fec2b08a, + 0x3fe2c0e9ed448e8b, + 0x3fe2e47436e40268, + 0x3fe307d7334f10be, + 0x3fe32b1339121d71, + 0x3fe34e289d9ce1d3, + 0x3fe37117b54747b5, + 0x3fe393e0d3562a19, + 0x3fe3b68449fffc22, + 0x3fe3d9026a7156fa, + 0x3fe3fb5b84d16f42, + 0x3fe41d8fe84672ae, + 0x3fe43f9fe2f9ce67, + 0x3fe4618bc21c5ec2, + 0x3fe48353d1ea88df, + 0x3fe4a4f85db03ebb, + 0x3fe4c679afccee39, + 0x3fe4e7d811b75bb0, + 0x3fe50913cc01686b, + 0x3fe52a2d265bc5aa, + 0x3fe54b2467999497, + 0x3fe56bf9d5b3f399, + 0x3fe58cadb5cd7989, + 0x3fe5ad404c359f2c, + 0x3fe5cdb1dc6c1764, + 0x3fe5ee02a9241675, + 0x3fe60e32f44788d8, +]; + +#[inline] +pub(crate) fn log_eval(x: f64) -> f64 { + let ex = get_exponent_f64(x); + + // p1 is the leading 7 bits of mx, i.e. + // p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7). + let p1 = ((x.to_bits() & ((1u64 << 52) - 1)) >> (52 - 7)) as i32; + + // Set bs to (1 + (mx - p1*2^(-7)) + let mut bs = x.to_bits() & (((1u64 << 52) - 1) >> 7); + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + bs = set_exponent_f64(bs, EXP_BIAS); + // dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)). + let dx = (f64::from_bits(bs) - 1.0) * f64::from_bits(ONE_OVER_F[p1 as usize]); + + // Minimax polynomial of log(1 + dx) generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]); + const COEFFS: [u64; 6] = [ + 0xbfdffffffffffffc, + 0x3fd5555555552dde, + 0xbfcffffffefe562d, + 0x3fc9999817d3a50f, + 0xbfc554317b3f67a5, + 0x3fc1dc5c45e09c18, + ]; + let dx2 = dx * dx; + let c1 = f_fmla(dx, f64::from_bits(COEFFS[1]), f64::from_bits(COEFFS[0])); + let c2 = f_fmla(dx, f64::from_bits(COEFFS[3]), f64::from_bits(COEFFS[2])); + let c3 = f_fmla(dx, f64::from_bits(COEFFS[5]), f64::from_bits(COEFFS[4])); + + let p = f_polyeval4(dx2, dx, c1, c2, c3); + f_fmla( + ex as f64, + /*log(2)*/ f64::from_bits(0x3fe62e42fefa39ef), + f64::from_bits(LOG_F[p1 as usize]) + p, + ) +} + +/// Hyperbolic arcsine function +/// +/// Max ULP 0.5 +#[inline] +pub fn f_asinhf(x: f32) -> f32 { + let x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffff; + + // |x| <= 2^-3 + if x_abs <= 0x3e80_0000u32 { + // |x| <= 2^-26 + if x_abs <= 0x3280_0000u32 { + return if x_abs == 0 { + x + } else { + (x as f64 - f64::from_bits(0x3fc5555555555555) * x as f64 * x as f64 * x as f64) + as f32 + }; + } + + let x_d = x as f64; + let x_sq = x_d * x_d; + // Generated by Sollya with: + // R = remez(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18|], [0, 2^-3]); + // P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18|], [|D...|], [0, 2^-3], absolute, floating, R); + // See `./notes/asinhf.sollya + let p = f_polyeval10( + x_sq, + 0.0, + f64::from_bits(0xbfc5555555555555), + f64::from_bits(0x3fb3333333333333), + f64::from_bits(0xbfa6db6db6db6d8e), + f64::from_bits(0x3f9f1c71c71beb52), + f64::from_bits(0xbf96e8ba2e0dde02), + f64::from_bits(0x3f91c4ec071a2f97), + f64::from_bits(0xbf8c9966fc6b6fda), + f64::from_bits(0x3f879da45ad06ce8), + f64::from_bits(0xbf82b3657f620c14), + ); + return f_fmla(x_d, p, x_d) as f32; + } + + static SIGN: [f64; 2] = [1.0, -1.0]; + let x_sign = SIGN[(x_u >> 31) as usize]; + let x_d = x as f64; + + if !x.is_finite() { + return x; + } + + // asinh(x) = log(x + sqrt(x^2 + 1)) + (x_sign * log_eval(f_fmla(x_d, x_sign, f_fmla(x_d, x_d, 1.0).sqrt()))) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_asinhf() { + assert_eq!(f_asinhf(-0.24319594), -0.2408603); + assert_eq!(f_asinhf(2.0), 1.4436355); + assert_eq!(f_asinhf(-2.0), -1.4436355); + assert_eq!(f_asinhf(1.054234), 0.9192077); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,407 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::hyperbolic::acosh::{ + ACOSH_ASINH_B, ACOSH_ASINH_LL, ACOSH_ASINH_R1, ACOSH_ASINH_R2, ACOSH_ASINH_REFINE_T2, + ACOSH_ASINH_REFINE_T4, ACOSH_SINH_REFINE_T1, ACOSH_SINH_REFINE_T3, lpoly_xd_generic, +}; + +static ATANH_L1: [(u64, u64); 33] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbe4532c1269e2038, 0x3f862e5000000000), + (0x3e4ce42d81b54e84, 0x3f962e3c00000000), + (0xbe525826f815ec3d, 0x3fa0a2ac00000000), + (0x3e50db1b1e7cee11, 0x3fa62e4a00000000), + (0xbe51f3a8c6c95003, 0x3fabb9dc00000000), + (0xbe5774cd4fb8c30d, 0x3fb0a2b200000000), + (0x3e2452e56c030a0a, 0x3fb3687f00000000), + (0x3e36b63c4966a79a, 0x3fb62e4100000000), + (0xbe3b20a21ccb525e, 0x3fb8f40a00000000), + (0x3e54006cfb3d8f85, 0x3fbbb9d100000000), + (0xbe5cdb026b310c41, 0x3fbe7f9b00000000), + (0xbe569124fdc0f16d, 0x3fc0a2b080000000), + (0xbe5084656cdc2727, 0x3fc2059580000000), + (0xbe5376fa8b0357fd, 0x3fc3687c00000000), + (0x3e3e56ae55a47b4a, 0x3fc4cb5e80000000), + (0x3e5070ff8834eeb4, 0x3fc62e4400000000), + (0x3e5623516109f4fe, 0x3fc7912900000000), + (0xbe2ec656b95fbdac, 0x3fc8f40b00000000), + (0x3e3f0ca2e729f510, 0x3fca56ed80000000), + (0xbe57d260a858354a, 0x3fcbb9d680000000), + (0x3e4e7279075503d3, 0x3fcd1cb900000000), + (0x3e439e1a0a503873, 0x3fce7f9d00000000), + (0x3e5cd86d7b87c3d6, 0x3fcfe27d80000000), + (0x3e5060ab88de341e, 0x3fd0a2b240000000), + (0x3e320a860d3f9390, 0x3fd1542440000000), + (0xbe4dacee95fc2f10, 0x3fd2059740000000), + (0x3e545de3a86e0aca, 0x3fd2b70700000000), + (0x3e4c164cbfb991af, 0x3fd3687b00000000), + (0x3e5d3f66b24225ef, 0x3fd419ec40000000), + (0x3e5fc023efa144ba, 0x3fd4cb5f80000000), + (0x3e3086a8af6f26c0, 0x3fd57cd280000000), + (0xbe105c610ca86c39, 0x3fd62e4300000000), +]; + +static ATANH_L2: [(u64, u64); 33] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbe337e152a129e4e, 0x3f36320000000000), + (0xbe53f6c916b8be9c, 0x3f46300000000000), + (0x3e520505936739d5, 0x3f50a24000000000), + (0xbe523e2e8cb541ba, 0x3f562dc000000000), + (0xbdfacb7983ac4f5e, 0x3f5bba0000000000), + (0x3e36f7c7689c63ae, 0x3f60a2a000000000), + (0x3e1f5ca695b4c58b, 0x3f6368c000000000), + (0xbe4c6c18bd953226, 0x3f662e6000000000), + (0x3e57a516c34846bd, 0x3f68f46000000000), + (0xbe4f3b83dd8b8530, 0x3f6bba0000000000), + (0xbe0c3459046e4e57, 0x3f6e800000000000), + (0x3d9b5c7e34cb79f6, 0x3f70a2c000000000), + (0xbe42487e9af9a692, 0x3f7205c000000000), + (0x3e5f21bbc4ad79ce, 0x3f73687000000000), + (0xbe2550ffc857b731, 0x3f74cb7000000000), + (0x3e487458ec1b7b34, 0x3f762e2000000000), + (0x3e5103d4fe83ee81, 0x3f77911000000000), + (0x3e4810483d3b398c, 0x3f78f44000000000), + (0xbe42085cb340608e, 0x3f7a573000000000), + (0x3e512698a119c42f, 0x3f7bb9d000000000), + (0xbe5edb8c172b4c33, 0x3f7d1cc000000000), + (0xbe58b55b87a5e238, 0x3f7e7fe000000000), + (0x3e5be5e17763f78a, 0x3f7fe2b000000000), + (0xbe1c2d496790073e, 0x3f80a2a800000000), + (0x3e56542f523abeec, 0x3f81541000000000), + (0xbe5b7fdbe5b193f8, 0x3f8205a000000000), + (0x3e5fa4d42fe30c7c, 0x3f82b70000000000), + (0x3e50d46ad04adc86, 0x3f83688800000000), + (0xbe51c22d02d17c4c, 0x3f8419f000000000), + (0x3e1a7d1e330dccce, 0x3f84cb7000000000), + (0x3e0187025e656ba3, 0x3f857cd000000000), + (0xbe4532c1269e2038, 0x3f862e5000000000), +]; + +#[cold] +fn as_atanh_zero(x: f64) -> f64 { + static CH: [(u64, u64); 13] = [ + (0x3c75555555555555, 0x3fd5555555555555), + (0xbc6999999999611c, 0x3fc999999999999a), + (0x3c62492490f76b25, 0x3fc2492492492492), + (0x3c5c71cd5c38a112, 0x3fbc71c71c71c71c), + (0xbc47556c4165f4ca, 0x3fb745d1745d1746), + (0xbc4b893c3b36052e, 0x3fb3b13b13b13b14), + (0x3c44e1afd723ed1f, 0x3fb1111111111105), + (0xbc4f86ea96fb1435, 0x3fae1e1e1e1e2678), + (0x3c31e51a6e54fde9, 0x3faaf286bc9f90cc), + (0xbc2ab913de95c3bf, 0x3fa8618618c779b6), + (0x3c4632e747641b12, 0x3fa642c84aa383eb), + (0xbc30c9617e7bcff2, 0x3fa47ae2d205013c), + (0x3c23adb3e2b7f35e, 0x3fa2f664d60473f9), + ]; + + const CL: [u64; 5] = [ + 0x3fa1a9a91fd692af, + 0x3fa06dfbb35e7f44, + 0x3fa037bed4d7588f, + 0x3f95aca6d6d720d6, + 0x3fa99ea5700d53a5, + ]; + + let dx2 = DoubleDouble::from_exact_mult(x, x); + + let yw0 = f_fmla(dx2.hi, f64::from_bits(CL[4]), f64::from_bits(CL[3])); + let yw1 = f_fmla(dx2.hi, yw0, f64::from_bits(CL[2])); + let yw2 = f_fmla(dx2.hi, yw1, f64::from_bits(CL[1])); + + let y2 = dx2.hi * f_fmla(dx2.hi, yw2, f64::from_bits(CL[0])); + + let mut y1 = lpoly_xd_generic(dx2, CH, y2); + y1 = DoubleDouble::quick_mult_f64(y1, x); + y1 = DoubleDouble::quick_mult(y1, dx2); + + let y0 = DoubleDouble::from_exact_add(x, y1.hi); + let mut p = DoubleDouble::from_exact_add(y0.lo, y1.lo); + + let mut t = p.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = p.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + p.hi = f64::from_bits(t); + } + y0.hi + p.hi +} + +#[cold] +fn atanh_refine(x: f64, a: f64, z: DoubleDouble) -> f64 { + let mut t = z.hi.to_bits(); + let ex: i32 = (t >> 52) as i32; + let e = ex.wrapping_sub(0x3ff); + t &= 0x000fffffffffffff; + t |= 0x3ffu64 << 52; + let ed = e as f64; + let v = (a - ed + f64::from_bits(0x3ff0000800000000)).to_bits(); + let i = (v.wrapping_sub(0x3ffu64 << 52)) >> (52 - 16); + let i1: i32 = ((i >> 12) as i32) & 0x1f; + let i2 = (i >> 8) & 0xf; + let i3 = (i >> 4) & 0xf; + let i4 = i & 0xf; + + const L20: f64 = f64::from_bits(0x3fd62e42fefa3a00); + const L21: f64 = f64::from_bits(0xbcd0ca86c3898d00); + const L22: f64 = f64::from_bits(0x397f97b57a079a00); + + let el2 = L22 * ed; + let el1 = L21 * ed; + let el0 = L20 * ed; + + let ll0i1 = ACOSH_ASINH_LL[0][i1 as usize]; + let ll1i2 = ACOSH_ASINH_LL[1][i2 as usize]; + let ll2i3 = ACOSH_ASINH_LL[2][i3 as usize]; + let ll3i4 = ACOSH_ASINH_LL[3][i4 as usize]; + + let mut dl0 = f64::from_bits(ll0i1.0) + + f64::from_bits(ll1i2.0) + + (f64::from_bits(ll2i3.0) + f64::from_bits(ll3i4.0)); + let dl1 = f64::from_bits(ll0i1.1) + + f64::from_bits(ll1i2.1) + + (f64::from_bits(ll2i3.1) + f64::from_bits(ll3i4.1)); + let dl2 = f64::from_bits(ll0i1.2) + + f64::from_bits(ll1i2.2) + + (f64::from_bits(ll2i3.2) + f64::from_bits(ll3i4.2)); + dl0 += el0; + + let t12 = f64::from_bits(ACOSH_SINH_REFINE_T1[i1 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T2[i2 as usize]); + let t34 = f64::from_bits(ACOSH_SINH_REFINE_T3[i3 as usize]) + * f64::from_bits(ACOSH_ASINH_REFINE_T4[i4 as usize]); + let th = t12 * t34; + let tl = f_fmla(t12, t34, -th); + let dh = th * f64::from_bits(t); + let dl = f_fmla(th, f64::from_bits(t), -dh); + let sh = tl * f64::from_bits(t); + let sl = f_fmla(tl, f64::from_bits(t), -sh); + let mut dx = DoubleDouble::from_exact_add(dh - 1., dl); + + t = z.lo.to_bits(); + t = t.wrapping_sub(((e as i64) << 52) as u64); + dx.lo += th * f64::from_bits(t); + + dx = DoubleDouble::add(dx, DoubleDouble::new(sl, sh)); + const CL: [u64; 3] = [0xbfc0000000000000, 0x3fb9999999a0754f, 0xbfb55555555c3157]; + + let slw0 = f_fmla(dx.hi, f64::from_bits(CL[2]), f64::from_bits(CL[1])); + + let sl = dx.hi * f_fmla(dx.hi, slw0, f64::from_bits(CL[0])); + + static CH: [(u64, u64); 3] = [ + (0x39024b67ee516e3b, 0x3fe0000000000000), + (0xb91932ce43199a8d, 0xbfd0000000000000), + (0x3c655540c15cf91f, 0x3fc5555555555555), + ]; + + let mut s = lpoly_xd_generic(dx, CH, sl); + s = DoubleDouble::mult(dx, s); + s = DoubleDouble::add(s, DoubleDouble::new(el2, el1)); + s = DoubleDouble::add(s, DoubleDouble::new(dl2, dl1)); + let mut v02 = DoubleDouble::from_exact_add(dl0, s.hi); + let mut v12 = DoubleDouble::from_exact_add(v02.lo, s.lo); + t = v12.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = v12.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + v12.hi = f64::from_bits(t); + } + v02.hi *= f64::copysign(1., x); + v12.hi *= f64::copysign(1., x); + + v02.hi + v12.hi +} + +/// Hyperbolic arc tangent +/// +/// Max ULP 0.5 +pub fn f_atanh(x: f64) -> f64 { + let ax = x.abs(); + let ix = ax.to_bits(); + let aix = ix; + if aix >= 0x3ff0000000000000u64 { + // |x| >= 1 + if aix == 0x3ff0000000000000u64 { + // |x| = 1 + return f64::copysign(1., x) / 0.0; + } + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + return (-1.0f64).sqrt(); + } + + if aix < 0x3fd0000000000000u64 { + // |x| < 0x1p-2 + // atanh(x) rounds to x to nearest for |x| < 0x1.d12ed0af1a27fp-27 + if aix < 0x3e4d12ed0af1a27fu64 { + // |x| < 0x1.d12ed0af1a27fp-27 + /* We have underflow exactly when 0 < |x| < 2^-1022: + for RNDU, atanh(2^-1022-2^-1074) would round to 2^-1022-2^-1075 + with unbounded exponent range */ + return f_fmla(x, f64::from_bits(0x3c80000000000000), x); + } + let x2 = x * x; + const C: [u64; 9] = [ + 0x3fc999999999999a, + 0x3fc2492492492244, + 0x3fbc71c71c79715f, + 0x3fb745d16f777723, + 0x3fb3b13ca4174634, + 0x3fb110c9724989bd, + 0x3fae2d17608a5b2e, + 0x3faa0b56308cba0b, + 0x3fafb6341208ad2e, + ]; + let dx2: f64 = dd_fmla(x, x, -x2); + + let x4 = x2 * x2; + let x3 = x2 * x; + let x8 = x4 * x4; + + let zdx3: f64 = dd_fmla(x2, x, -x3); + + let dx3 = f_fmla(dx2, x, zdx3); + + let pw0 = f_fmla(x2, f64::from_bits(C[7]), f64::from_bits(C[6])); + let pw1 = f_fmla(x2, f64::from_bits(C[5]), f64::from_bits(C[4])); + let pw2 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let pw3 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + + let pw4 = f_fmla(x4, pw0, pw1); + let pw5 = f_fmla(x8, f64::from_bits(C[8]), pw4); + let pw6 = f_fmla(x4, pw2, pw3); + + let p = f_fmla(x8, pw5, pw6); + let t = f64::from_bits(0x3c75555555555555) + x2 * p; + let mut p = DoubleDouble::from_exact_add(f64::from_bits(0x3fd5555555555555), t); + p = DoubleDouble::mult(p, DoubleDouble::new(dx3, x3)); + let z0 = DoubleDouble::from_exact_add(x, p.hi); + p.lo += z0.lo; + p.hi = z0.hi; + let eps = x * f_fmla( + x4, + f64::from_bits(0x3cad000000000000), + f64::from_bits(0x3980000000000000), + ); + let lb = p.hi + (p.lo - eps); + let ub = p.hi + (p.lo + eps); + if lb == ub { + return lb; + } + return as_atanh_zero(x); + } + + let p = DoubleDouble::from_exact_add(1.0, ax); + let q = DoubleDouble::from_exact_sub(1.0, ax); + let iqh = 1.0 / q.hi; + let th = p.hi * iqh; + let tl = dd_fmla(p.hi, iqh, -th) + (p.lo + p.hi * (dd_fmla(-q.hi, iqh, 1.) - q.lo * iqh)) * iqh; + + const C: [u64; 5] = [ + 0xbff0000000000000, + 0x3ff5555555555530, + 0xbfffffffffffffa0, + 0x40099999e33a6366, + 0xc01555559ef9525f, + ]; + + let mut t = th.to_bits(); + let ex: i32 = (t >> 52) as i32; + let e = ex.wrapping_sub(0x3ff); + t &= 0x000fffffffffffff; + let ed = e as f64; + let i = t >> (52 - 5); + let d: i64 = (t & 0x00007fffffffffff) as i64; + let b_i = ACOSH_ASINH_B[i as usize]; + let j: u64 = t + .wrapping_add((b_i[0] as u64).wrapping_shl(33)) + .wrapping_add((b_i[1] as i64).wrapping_mul(d >> 16) as u64) + >> (52 - 10); + t |= 0x3ffu64 << 52; + let i1: i32 = (j >> 5) as i32; + let i2 = j & 0x1f; + let r = (0.5 * f64::from_bits(ACOSH_ASINH_R1[i1 as usize])) + * f64::from_bits(ACOSH_ASINH_R2[i2 as usize]); + let dx = dd_fmla(r, f64::from_bits(t), -0.5); + let dx2 = dx * dx; + let rx = r * f64::from_bits(t); + let dxl = dd_fmla(r, f64::from_bits(t), -rx); + + let fw0 = f_fmla(dx, f64::from_bits(C[3]), f64::from_bits(C[2])); + let fw2 = f_fmla(dx, f64::from_bits(C[1]), f64::from_bits(C[0])); + let fw1 = f_fmla(dx2, f64::from_bits(C[4]), fw0); + + let f = dx2 * f_fmla(dx2, fw1, fw2); + const L2H: f64 = f64::from_bits(0x3fd62e42fefa3a00); + const L2L: f64 = f64::from_bits(0xbcd0ca86c3898d00); + let l1i1 = ATANH_L1[i1 as usize]; + let l1i2 = ATANH_L2[i2 as usize]; + let lh = f_fmla(L2H, ed, f64::from_bits(l1i1.1) + f64::from_bits(l1i2.1)); + let mut zl = DoubleDouble::from_exact_add(lh, rx - 0.5); + + zl.lo += f_fmla(L2L, ed, f64::from_bits(l1i1.0) + f64::from_bits(l1i2.0)) + dxl + 0.5 * tl / th; + zl.lo += f; + zl.hi *= f64::copysign(1., x); + zl.lo *= f64::copysign(1., x); + let eps = 31e-24 + dx2 * f64::from_bits(0x3ce0000000000000); + let lb = zl.hi + (zl.lo - eps); + let ub = zl.hi + (zl.lo + eps); + if lb == ub { + return lb; + } + let t = DoubleDouble::from_exact_add(th, tl); + atanh_refine( + x, + f64::from_bits(0x40071547652b82fe) * (zl.hi + zl.lo).abs(), + t, + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_atanh() { + assert_eq!(f_atanh(-0.5000824928283691), -0.5494161408216048); + assert_eq!(f_atanh(-0.24218760943040252), -0.24709672810738792); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanhf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanhf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanhf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/atanhf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::hyperbolic::asinhf::log_eval; +use crate::polyeval::f_polyeval6; + +/// Hyperbolic atan +/// +/// Max ULP 0.5 +#[inline] +pub fn f_atanhf(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffff; + + // |x| >= 1.0 + if x_abs >= 0x3F80_0000u32 { + if x.is_nan() { + return x; + } + // |x| == 1.0 + return if x_abs == 0x3F80_0000u32 { + if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NEG_INFINITY + } + } else { + f32::NAN + }; + } + + // |x| < ~0.10 + if x_abs <= 0x3dcc_0000u32 { + // |x| <= 2^-26 + if x_abs <= 0x3280_0000u32 { + return if x_abs == 0 { + x + } else { + (x as f64 + f64::from_bits(0x3fd5555555555555) * x as f64 * x as f64 * x as f64) + as f32 + }; + } + + let xdbl = x as f64; + let x2 = xdbl * xdbl; + // Pure Taylor series. + let pe = f_polyeval6( + x2, + 0.0, + f64::from_bits(0x3fd5555555555555), + f64::from_bits(0x3fc999999999999a), + f64::from_bits(0x3fc2492492492492), + f64::from_bits(0x3fbc71c71c71c71c), + f64::from_bits(0x3fb745d1745d1746), + ); + return f_fmla(xdbl, pe, xdbl) as f32; + } + let xdbl = x as f64; + (0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_atanhf() { + assert_eq!(f_atanhf(0.0), 0.0); + assert_eq!(f_atanhf(1.0), f32::INFINITY); + assert!(f_atanhf(-1.5).is_nan()); + assert_eq!(f_atanhf(0.25), 0.25541282); + assert_eq!(f_atanhf(0.124121), 0.12476436); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/cosh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/cosh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/cosh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/cosh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,291 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1}; +use crate::hyperbolic::acosh::lpoly_xd_generic; +use crate::hyperbolic::sinh::hyperbolic_exp_accurate; + +#[cold] +fn as_cosh_zero(x: f64) -> f64 { + static CH: [(u64, u64); 4] = [ + (0xb90c7e8db669f624, 0x3fe0000000000000), + (0x3c45555555556135, 0x3fa5555555555555), + (0xbbef49f4a6e838f2, 0x3f56c16c16c16c17), + (0x3b3a4ffbe15316aa, 0x3efa01a01a01a01a), + ]; + const CL: [u64; 4] = [ + 0x3e927e4fb7789f5c, + 0x3e21eed8eff9089c, + 0x3da939749ce13dad, + 0x3d2ae9891efb6691, + ]; + + let dx2 = DoubleDouble::from_exact_mult(x, x); + + let yw0 = f_fmla(dx2.hi, f64::from_bits(CL[3]), f64::from_bits(CL[2])); + let yw1 = f_fmla(dx2.hi, yw0, f64::from_bits(CL[1])); + + let y2 = dx2.hi * f_fmla(dx2.hi, yw1, f64::from_bits(CL[0])); + + let mut y1 = lpoly_xd_generic(dx2, CH, y2); + y1 = DoubleDouble::quick_mult(y1, dx2); // y2 = y1.l + let y0 = DoubleDouble::from_exact_add(1.0, y1.hi); // y0 = y0.hi + let mut p = DoubleDouble::from_exact_add(y0.lo, y1.lo); + let mut t = p.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = p.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + p.hi = f64::from_bits(t); + } + y0.hi + p.hi +} + +/// Hyperbolic cosine function +/// +/// Max ULP 0.5 +pub fn f_cosh(x: f64) -> f64 { + /* + The function sinh(x) is approximated by a minimax polynomial + cosh(x)~1+x^2*P(x^2) for |x|<0.125. For other arguments the + identity cosh(x)=(exp(|x|)+exp(-|x|))/2 is used. For |x|<5 both + exponents are calculated with slightly higher precision than + double. For 5<|x|<36.736801 the exp(-|x|) is rather small and is + calculated with double precision but exp(|x|) is calculated with + higher than double precision. For 36.736801<|x|<710.47586 + exp(-|x|) becomes too small and only exp(|x|) is calculated. + */ + + const S: f64 = f64::from_bits(0x40b71547652b82fe); + let ax = x.abs(); + let v0 = f_fmla(ax, S, f64::from_bits(0x4198000002000000)); + let jt = v0.to_bits(); + let mut v = v0.to_bits(); + v &= 0xfffffffffc000000; + let t = f64::from_bits(v) - f64::from_bits(0x4198000000000000); + let ix = ax.to_bits(); + let aix = ix; + if aix < 0x3fc0000000000000u64 { + if aix < 0x3e50000000000000u64 { + return f_fmla(ax, f64::from_bits(0x3c80000000000000), 1.); + } + const C: [u64; 5] = [ + 0x3fe0000000000000, + 0x3fa555555555554e, + 0x3f56c16c16c26737, + 0x3efa019ffbbcdbda, + 0x3e927ffe2df106cb, + ]; + let x2 = x * x; + let x4 = x2 * x2; + + let p0 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let p1 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let p2 = f_fmla(x4, f64::from_bits(C[4]), p0); + + let p = x2 * f_fmla(x4, p2, p1); + let e = x2 * (4. * f64::from_bits(0x3ca0000000000000)); + let lb = 1. + (p - e); + let ub = 1. + (p + e); + if lb == ub { + return lb; + } + return as_cosh_zero(x); + } + + // treat large values apart to avoid a spurious invalid exception + if aix > 0x408633ce8fb9f87du64 { + // |x| > 0x1.633ce8fb9f87dp+9 + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + if aix == 0x7ff0000000000000u64 { + return x.abs(); + } // inf + return f64::from_bits(0x7fe0000000000000) * 2.0; + } + + let il: i64 = ((jt.wrapping_shl(14)) >> 40) as i64; + let jl: i64 = -il; + let i1 = il & 0x3f; + let i0 = (il >> 6) & 0x3f; + let ie = il >> 12; + let j1 = jl & 0x3f; + let j0 = (jl >> 6) & 0x3f; + let je = jl >> 12; + let mut sp = (1022i64.wrapping_add(ie) as u64).wrapping_shl(52); + let sm = (1022i64.wrapping_add(je) as u64).wrapping_shl(52); + let sn0 = EXP_REDUCE_T0[i0 as usize]; + let sn1 = EXP_REDUCE_T1[i1 as usize]; + let t0h = f64::from_bits(sn0.1); + let t0l = f64::from_bits(sn0.0); + let t1h = f64::from_bits(sn1.1); + let t1l = f64::from_bits(sn1.0); + let mut th = t0h * t1h; + let mut tl = f_fmla(t0h, t1l, t1h * t0l) + dd_fmla(t0h, t1h, -th); + + const L2H: f64 = f64::from_bits(0x3f262e42ff000000); + const L2L: f64 = f64::from_bits(0x3d0718432a1b0e26); + let dx = f_fmla(L2L, t, f_fmla(-L2H, t, ax)); + let dx2 = dx * dx; + let mx = -dx; + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555aaaaae, + 0x3fa55555551c98c0, + ]; + + let pw0 = f_fmla(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pw1 = f_fmla(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pp = dx * f_fmla(dx2, pw0, pw1); + let (mut rh, mut rl); + if aix > 0x4014000000000000u64 { + // |x| > 5 + if aix > 0x40425e4f7b2737fau64 { + // |x| >~ 36.736801 + sp = (1021i64.wrapping_add(ie) as u64).wrapping_shl(52); + rh = th; + rl = f_fmla(th, pp, tl); + let e = 0.11e-18 * th; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return (lb * f64::from_bits(sp)) * 2.; + } + + let mut tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + tt = DoubleDouble::from_exact_add(tt.hi, tt.lo); + th = tt.hi; + tl = tt.lo; + th += tl; + th *= 2.; + th *= f64::from_bits(sp); + return th; + } + + let q0h = f64::from_bits(EXP_REDUCE_T0[j0 as usize].1); + let q1h = f64::from_bits(EXP_REDUCE_T1[j1 as usize].1); + let mut qh = q0h * q1h; + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + qh *= f64::from_bits(sm); + + let pmw0 = f_fmla(mx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pmw1 = f_fmla(mx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pm = mx * f_fmla(dx2, pmw0, pmw1); + let em = f_fmla(qh, pm, qh); + rh = th; + rl = f_fmla(th, pp, tl + em); + let e = 0.09e-18 * rh; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return lb; + } + let tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + th = tt.hi; + tl = tt.lo; + if aix > 0x403f666666666666u64 { + rh = th + qh; + rl = ((th - rh) + qh) + tl; + } else { + qh = q0h * q1h; + let q0l = f64::from_bits(EXP_REDUCE_T0[j0 as usize].0); + let q1l = f64::from_bits(EXP_REDUCE_T1[j1 as usize].0); + let mut ql = f_fmla(q0h, q1l, q1h * q0l) + dd_fmla(q0h, q1h, -qh); + qh *= f64::from_bits(sm); + ql *= f64::from_bits(sm); + let qq = hyperbolic_exp_accurate(-ax, -t, DoubleDouble::new(ql, qh)); + qh = qq.hi; + ql = qq.lo; + rh = th + qh; + rl = (((th - rh) + qh) + ql) + tl; + } + } else { + let tq0 = EXP_REDUCE_T0[j0 as usize]; + let tq1 = EXP_REDUCE_T1[j1 as usize]; + let q0h = f64::from_bits(tq0.1); + let q0l = f64::from_bits(tq0.0); + let q1h = f64::from_bits(tq1.1); + let q1l = f64::from_bits(tq1.0); + let mut qh = q0h * q1h; + let mut ql = f_fmla(q0h, q1l, q1h * q0l) + dd_fmla(q0h, q1h, -qh); + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + qh *= f64::from_bits(sm); + ql *= f64::from_bits(sm); + + let pmw0 = f_fmla(mx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pmw1 = f_fmla(mx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pm = mx * f_fmla(dx2, pmw0, pmw1); + let fph = th; + let fpl = f_fmla(th, pp, tl); + let fmh = qh; + let fml = f_fmla(qh, pm, ql); + + rh = fph + fmh; + rl = ((fph - rh) + fmh) + fml + fpl; + let e = 0.28e-18 * rh; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return lb; + } + let tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + let qq = hyperbolic_exp_accurate(-ax, -t, DoubleDouble::new(ql, qh)); + rh = tt.hi + qq.hi; + rl = ((tt.hi - rh) + qq.hi) + qq.lo + tt.lo; + } + let r = DoubleDouble::from_exact_add(rh, rl); + rh = r.hi; + rl = r.lo; + rh += rl; + rh +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_cosh() { + assert_eq!(f_cosh(1.), 1.5430806348152437); + assert_eq!(f_cosh(1.5454354343), 2.451616191647056); + assert_eq!(f_cosh(15.5454354343), 2820115.088877147); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/coshf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/coshf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/coshf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/coshf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::rounding::CpuRoundTiesEven; +use std::hint::black_box; + +static TB: [u64; 32] = [ + 0x3fe0000000000000, + 0x3fe059b0d3158574, + 0x3fe0b5586cf9890f, + 0x3fe11301d0125b51, + 0x3fe172b83c7d517b, + 0x3fe1d4873168b9aa, + 0x3fe2387a6e756238, + 0x3fe29e9df51fdee1, + 0x3fe306fe0a31b715, + 0x3fe371a7373aa9cb, + 0x3fe3dea64c123422, + 0x3fe44e086061892d, + 0x3fe4bfdad5362a27, + 0x3fe5342b569d4f82, + 0x3fe5ab07dd485429, + 0x3fe6247eb03a5585, + 0x3fe6a09e667f3bcd, + 0x3fe71f75e8ec5f74, + 0x3fe7a11473eb0187, + 0x3fe82589994cce13, + 0x3fe8ace5422aa0db, + 0x3fe93737b0cdc5e5, + 0x3fe9c49182a3f090, + 0x3fea5503b23e255d, + 0x3feae89f995ad3ad, + 0x3feb7f76f2fb5e47, + 0x3fec199bdd85529c, + 0x3fecb720dcef9069, + 0x3fed5818dcfba487, + 0x3fedfc97337b9b5f, + 0x3feea4afa2a490da, + 0x3fef50765b6e4540, +]; + +#[cold] +fn coshf_accurate(z: f64, ia: f64, sp: u64, sm: u64) -> f32 { + const CH: [u64; 7] = [ + 0x3ff0000000000000, + 0x3f962e42fefa39ef, + 0x3f2ebfbdff82c58f, + 0x3ebc6b08d702e0ed, + 0x3e43b2ab6fb92e5e, + 0x3dc5d886e6d54203, + 0x3d4430976b8ce6ef, + ]; + + const ILN2H: f64 = f64::from_bits(0x4047154765000000); + const ILN2L: f64 = f64::from_bits(0x3e55c17f0bbbe880); + let h = f_fmla(ILN2L, z, f_fmla(ILN2H, z, -ia)); + let h2 = h * h; + + let q0 = f_fmla(h2, f64::from_bits(CH[6]), f64::from_bits(CH[4])); + let q1 = f_fmla(h2, f64::from_bits(CH[2]), f64::from_bits(CH[0])); + + let te = f_fmla(h2 * h2, q0, q1); + + let j0 = f_fmla(h2, f64::from_bits(CH[5]), f64::from_bits(CH[3])); + + let to = f_fmla(h2, j0, f64::from_bits(CH[1])); + + let z0 = f_fmla(h, to, te); + let z1 = f_fmla(-h, to, te); + f_fmla(f64::from_bits(sp), z0, f64::from_bits(sm) * z1) as f32 +} + +/// Hyperbolic cos +/// +/// Max found ULP 0.4999996 +#[inline] +pub fn f_coshf(x: f32) -> f32 { + const C: [u64; 4] = [ + 0x3ff0000000000000, + 0x3f962e42fef4c4e7, + 0x3f2ebfd1b232f475, + 0x3ebc6b19384ecd93, + ]; + + const I_LN2: f64 = f64::from_bits(0x40471547652b82fe); + let t = x.to_bits(); + let z = x as f64; + let ax = t.wrapping_shl(1); + if ax > 0x8565a9f8u32 { + // |x| >~ 89.4 + if ax >= 0xff000000u32 { + if ax.wrapping_shl(8) != 0 { + return x + x; + } // nan + return f32::INFINITY; // +-inf + } + let r = black_box(2.0) * black_box(f64::from_bits(0x47efffffe0000000) as f32); + return r; + } + if ax < 0x7c000000u32 { + // |x| < 0.125 + if ax < 0x74000000u32 { + // |x| < 0.000488281 + if ax < 0x66000000u32 { + // |x| < 5.96046e-08 + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x.abs(), f64::from_bits(0x3e60000000000000) as f32, 1.0); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + return f_fmla(dx.abs(), f64::from_bits(0x3e60000000000000), 1.0) as f32; + } + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(0.5 * x, x, 1.0); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + return f_fmla(0.5 * dx, dx, 1.0) as f32; + } + } + const CP: [u64; 4] = [ + 0x3fdfffffffffffe3, + 0x3fa55555555723cf, + 0x3f56c16bee4a5986, + 0x3efa0483fc0328f7, + ]; + let z2 = z * z; + let z4 = z2 * z2; + let w0 = f_fmla(z2, f64::from_bits(CP[1]), f64::from_bits(CP[0])); + let w1 = f_fmla(z2, f64::from_bits(CP[3]), f64::from_bits(CP[2])); + return f_fmla(z2, f_fmla(z4, w1, w0), 1.0) as f32; + } + let a = I_LN2 * z; + let ia = a.cpu_round_ties_even(); + let h = a - ia; + let h2 = h * h; + let ja = (ia + f64::from_bits(0x4338000000000000)).to_bits(); + let jp: i64 = ja as i64; + let jm = -jp; + let sp = TB[(jp & 31) as usize].wrapping_add(jp.wrapping_shr(5).wrapping_shl(52) as u64); + let sm = TB[(jm & 31) as usize].wrapping_add(jm.wrapping_shr(5).wrapping_shl(52) as u64); + let te = f_fmla(h2, f64::from_bits(C[2]), f64::from_bits(C[0])); + let to = f_fmla(h2, f64::from_bits(C[3]), f64::from_bits(C[1])); + let rp = f64::from_bits(sp) * f_fmla(h, to, te); + let rm = f64::from_bits(sm) * f_fmla(-h, to, te); + let r = rp + rm; + let ub = r; + let lb = r - f64::from_bits(0x3de3edbbe4560327) * r; + // Ziv's accuracy test + if ub != lb { + return coshf_accurate(z, ia, sp, sm); + } + ub as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_coshf() { + assert_eq!(f_coshf(-0.5), 1.127626); + assert_eq!(f_coshf(0.5), 1.127626); + assert_eq!(f_coshf(7.), 548.317); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![deny(unreachable_pub)] +mod acosh; +mod acoshf; +mod asinh; +mod asinhf; +mod atanh; +mod atanhf; +mod cosh; +mod coshf; +mod sinh; +mod sinhf; +mod tanh; +mod tanhf; + +pub use acosh::f_acosh; +pub use acoshf::f_acoshf; +pub use asinh::f_asinh; +pub use asinhf::f_asinhf; +pub use atanh::f_atanh; +pub use atanhf::f_atanhf; +pub use cosh::f_cosh; +pub use coshf::f_coshf; +pub use sinh::f_sinh; +pub use sinhf::f_sinhf; +pub use tanh::f_tanh; +pub use tanhf::f_tanhf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,329 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1}; +use crate::hyperbolic::acosh::lpoly_xd_generic; + +#[cold] +pub(crate) fn hyperbolic_exp_accurate(x: f64, t: f64, zt: DoubleDouble) -> DoubleDouble { + static CH: [(u64, u64); 3] = [ + (0x3a16c16bd194535d, 0x3ff0000000000000), + (0xba28259d904fd34f, 0x3fe0000000000000), + (0x3c653e93e9f26e62, 0x3fc5555555555555), + ]; + const L2H: f64 = f64::from_bits(0x3f262e42ff000000); + const L2L: f64 = f64::from_bits(0x3d0718432a1b0e26); + const L2LL: f64 = f64::from_bits(0x3999ff0342542fc3); + let dx = x - L2H * t; + let mut dxl = L2L * t; + let dxll = f_fmla(L2LL, t, dd_fmla(L2L, t, -dxl)); + let dxh = dx + dxl; + dxl = ((dx - dxh) + dxl) + dxll; + + let fl0 = f_fmla( + dxh, + f64::from_bits(0x3f56c16c169400a7), + f64::from_bits(0x3f811111113e93e9), + ); + + let fl = dxh * f_fmla(dxh, fl0, f64::from_bits(0x3fa5555555555555)); + let mut f = lpoly_xd_generic(DoubleDouble::new(dxl, dxh), CH, fl); + f = DoubleDouble::quick_mult(DoubleDouble::new(dxl, dxh), f); + f = DoubleDouble::quick_mult(zt, f); + let zh = zt.hi + f.hi; + let zl = (zt.hi - zh) + f.hi; + let uh = zh + zt.lo; + let ul = ((zh - uh) + zt.lo) + zl; + let vh = uh + f.lo; + let vl = ((uh - vh) + f.lo) + ul; + DoubleDouble::new(vl, vh) +} + +#[cold] +fn as_sinh_zero(x: f64) -> f64 { + static CH: [(u64, u64); 5] = [ + (0x3c6555555555552f, 0x3fc5555555555555), + (0x3c011111115cf00d, 0x3f81111111111111), + (0x3b6a0011c925b85c, 0x3f2a01a01a01a01a), + (0xbb6b4e2835532bcd, 0x3ec71de3a556c734), + (0xbaedefcf17a6ab79, 0x3e5ae64567f54482), + ]; + let d2x = DoubleDouble::from_exact_mult(x, x); + + let yw0 = f_fmla( + d2x.hi, + f64::from_bits(0x3ce95785063cd974), + f64::from_bits(0x3d6ae7f36beea815), + ); + + let y2 = d2x.hi * f_fmla(d2x.hi, yw0, f64::from_bits(0x3de6124613aef206)); + let mut y1 = lpoly_xd_generic(d2x, CH, y2); + y1 = DoubleDouble::quick_mult_f64(y1, x); + y1 = DoubleDouble::quick_mult(y1, d2x); // y2 = y1.l + let y0 = DoubleDouble::from_exact_add(x, y1.hi); // y0 = y0.hi + let mut p = DoubleDouble::from_exact_add(y0.lo, y1.lo); + let mut t = p.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = p.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + p.hi = f64::from_bits(t); + } + y0.hi + p.hi +} + +/// Hyperbolic sine function +/// +/// Max ULP 0.5 +pub fn f_sinh(x: f64) -> f64 { + /* + The function sinh(x) is approximated by a minimax polynomial for + |x|<0.25. For other arguments the identity + sinh(x)=(exp(|x|)-exp(-|x|))/2*copysign(1,x) is used. For |x|<5 + both exponents are calculated with slightly higher precision than + double. For 5<|x|<36.736801 the exp(-|x|) is small and is + calculated with double precision but exp(|x|) is calculated with + higher than double precision. For 36.736801<|x|<710.47586 + exp(-|x|) becomes too small and only exp(|x|) is calculated. + */ + + const S: f64 = f64::from_bits(0x40b71547652b82fe); + let ax = x.abs(); + let v0 = dd_fmla(ax, S, f64::from_bits(0x4198000002000000)); + let jt = v0.to_bits(); + let v = v0.to_bits() & 0xfffffffffc000000; + let t = f64::from_bits(v) - f64::from_bits(0x4198000000000000); + let ix = ax.to_bits(); + let aix = ix; + if aix < 0x3fd0000000000000u64 { + // |x| < 0x1p-2 + if aix < 0x3e57137449123ef7u64 { + // |x| < 0x1.7137449123ef7p-26 + /* We have underflow exactly when 0 < |x| < 2^-1022: + for RNDU, sinh(2^-1022-2^-1074) would round to 2^-1022-2^-1075 + with unbounded exponent range */ + return dd_fmla(x, f64::from_bits(0x3c80000000000000), x); + } + const C: [u64; 5] = [ + 0x3fc5555555555555, + 0x3f81111111111087, + 0x3f2a01a01a12e1c3, + 0x3ec71de2e415aa36, + 0x3e5aed2bff4269e6, + ]; + let x2 = x * x; + let x3 = x2 * x; + let x4 = x2 * x2; + + let pw0 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let pw1 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let pw2 = f_fmla(x4, f64::from_bits(C[4]), pw0); + + let p = x3 * f_fmla(x4, pw2, pw1); + let e = x3 * f64::from_bits(0x3ca9000000000000); + let lb = x + (p - e); + let ub = x + (p + e); + if lb == ub { + return lb; + } + return as_sinh_zero(x); + } + + if aix > 0x408633ce8fb9f87du64 { + // |x| >~ 710.47586 + if aix >= 0x7ff0000000000000u64 { + return x + x; + } // nan Inf + return f64::copysign(f64::from_bits(0x7fe0000000000000), x) * 2.0; + } + let il: i64 = ((jt.wrapping_shl(14)) >> 40) as i64; + let jl = -il; + let i1 = il & 0x3f; + let i0 = (il >> 6) & 0x3f; + let ie = il >> 12; + let j1 = jl & 0x3f; + let j0 = (jl >> 6) & 0x3f; + let je = jl >> 12; + let mut sp = (1022i64.wrapping_add(ie) as u64).wrapping_shl(52); + let sm = (1022i64.wrapping_add(je) as u64).wrapping_shl(52); + + let sn0 = EXP_REDUCE_T0[i0 as usize]; + let sn1 = EXP_REDUCE_T1[i1 as usize]; + let t0h = f64::from_bits(sn0.1); + let t0l = f64::from_bits(sn0.0); + let t1h = f64::from_bits(sn1.1); + let t1l = f64::from_bits(sn1.0); + let mut th = t0h * t1h; + let mut tl = f_fmla(t0h, t1l, t1h * t0l) + dd_fmla(t0h, t1h, -th); + const L2H: f64 = f64::from_bits(0x3f262e42ff000000); + const L2L: f64 = f64::from_bits(0x3d0718432a1b0e26); + let dx = f_fmla(L2L, t, f_fmla(-L2H, t, ax)); + let dx2 = dx * dx; + let mx = -dx; + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555aaaaae, + 0x3fa55555551c98c0, + ]; + + let (mut rl, mut rh); + + let pp0 = f_fmla(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pp1 = f_fmla(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pp = dx * f_fmla(dx2, pp0, pp1); + if aix > 0x4014000000000000u64 { + // |x| > 5 + if aix > 0x40425e4f7b2737fau64 { + // |x| >~ 36.736801 + sp = (1021i64.wrapping_add(ie) as u64).wrapping_shl(52); + let mut rh = th; + let mut rl = tl + th * pp; + rh *= f64::copysign(1., x); + rl *= f64::copysign(1., x); + let e = 0.11e-18 * th; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return (lb * f64::from_bits(sp)) * 2.; + } + let mut tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + tt = DoubleDouble::from_exact_add(tt.hi, tt.lo); + th = tt.hi; + tl = tt.lo; + th *= f64::copysign(1., x); + tl *= f64::copysign(1., x); + th += tl; + th *= 2.; + th *= f64::from_bits(sp); + return th; + } + + let q0h = f64::from_bits(EXP_REDUCE_T0[j0 as usize].1); + let q1h = f64::from_bits(EXP_REDUCE_T1[j1 as usize].1); + let mut qh = q0h * q1h; + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + qh *= f64::from_bits(sm); + + let pm0 = f_fmla(mx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pm1 = f_fmla(mx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pm = mx * f_fmla(dx2, pm0, pm1); + let em = f_fmla(qh, pm, qh); + rh = th; + rl = f_fmla(th, pp, tl - em); + + rh *= f64::copysign(1., x); + rl *= f64::copysign(1., x); + let e = 0.09e-18 * rh; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return lb; + } + + let tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + th = tt.hi; + tl = tt.lo; + if aix > 0x403f666666666666u64 { + rh = th - qh; + rl = ((th - rh) - qh) + tl; + } else { + qh = q0h * q1h; + let q0l = f64::from_bits(EXP_REDUCE_T0[j0 as usize].0); + let q1l = f64::from_bits(EXP_REDUCE_T1[j1 as usize].0); + let mut ql = f_fmla(q0h, q1l, q1h * q0l) + dd_fmla(q0h, q1h, -qh); + qh *= f64::from_bits(sm); + ql *= f64::from_bits(sm); + let qq = hyperbolic_exp_accurate(-ax, -t, DoubleDouble::new(ql, qh)); + rh = th - qq.hi; + rl = (((th - rh) - qq.hi) - qq.lo) + tl; + } + } else { + let tq0 = EXP_REDUCE_T0[j0 as usize]; + let tq1 = EXP_REDUCE_T1[j1 as usize]; + let q0h = f64::from_bits(tq0.1); + let q0l = f64::from_bits(tq0.0); + let q1h = f64::from_bits(tq1.1); + let q1l = f64::from_bits(tq1.0); + let mut qh = q0h * q1h; + let mut ql = f_fmla(q0h, q1l, q1h * q0l) + dd_fmla(q0h, q1h, -qh); + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + qh *= f64::from_bits(sm); + ql *= f64::from_bits(sm); + + let pm0 = f_fmla(mx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pm1 = f_fmla(mx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let pm = mx * f_fmla(dx2, pm0, pm1); + let fph = th; + let fpl = f_fmla(th, pp, tl); + let fmh = qh; + let fml = f_fmla(qh, pm, ql); + + rh = fph - fmh; + rl = ((fph - rh) - fmh) - fml + fpl; + rh *= f64::copysign(1., x); + rl *= f64::copysign(1., x); + let e = 0.28e-18 * rh; + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return lb; + } + let tt = hyperbolic_exp_accurate(ax, t, DoubleDouble::new(tl, th)); + let qq = hyperbolic_exp_accurate(-ax, -t, DoubleDouble::new(ql, qh)); + rh = tt.hi - qq.hi; + rl = ((tt.hi - rh) - qq.hi) - qq.lo + tt.lo; + } + let r = DoubleDouble::from_exact_add(rh, rl); + rh = r.hi; + rl = r.lo; + rh *= f64::copysign(1., x); + rl *= f64::copysign(1., x); + rh += rl; + rh +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_sinh() { + assert_eq!(f_sinh(1.), 1.1752011936438014); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinhf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinhf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinhf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/sinhf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, f_fmlaf}; +use crate::rounding::CpuRoundTiesEven; + +static TB: [u64; 32] = [ + 0x3fe0000000000000, + 0x3fe059b0d3158574, + 0x3fe0b5586cf9890f, + 0x3fe11301d0125b51, + 0x3fe172b83c7d517b, + 0x3fe1d4873168b9aa, + 0x3fe2387a6e756238, + 0x3fe29e9df51fdee1, + 0x3fe306fe0a31b715, + 0x3fe371a7373aa9cb, + 0x3fe3dea64c123422, + 0x3fe44e086061892d, + 0x3fe4bfdad5362a27, + 0x3fe5342b569d4f82, + 0x3fe5ab07dd485429, + 0x3fe6247eb03a5585, + 0x3fe6a09e667f3bcd, + 0x3fe71f75e8ec5f74, + 0x3fe7a11473eb0187, + 0x3fe82589994cce13, + 0x3fe8ace5422aa0db, + 0x3fe93737b0cdc5e5, + 0x3fe9c49182a3f090, + 0x3fea5503b23e255d, + 0x3feae89f995ad3ad, + 0x3feb7f76f2fb5e47, + 0x3fec199bdd85529c, + 0x3fecb720dcef9069, + 0x3fed5818dcfba487, + 0x3fedfc97337b9b5f, + 0x3feea4afa2a490da, + 0x3fef50765b6e4540, +]; + +#[cold] +fn sinhf_accurate(z: f64, ia: f64, sp: u64, sm: u64) -> f32 { + const CH: [u64; 7] = [ + 0x3ff0000000000000, + 0x3f962e42fefa39ef, + 0x3f2ebfbdff82c58f, + 0x3ebc6b08d702e0ed, + 0x3e43b2ab6fb92e5e, + 0x3dc5d886e6d54203, + 0x3d4430976b8ce6ef, + ]; + const ILN2H: f64 = f64::from_bits(0x4047154765000000); + const ILN2L: f64 = f64::from_bits(0x3e55c17f0bbbe880); + let h = f_fmla(ILN2L, z, f_fmla(ILN2H, z, -ia)); + let h2 = h * h; + + let q0 = f_fmla(h2, f64::from_bits(CH[6]), f64::from_bits(CH[4])); + let q1 = f_fmla(h2, f64::from_bits(CH[2]), f64::from_bits(CH[0])); + + let te = f_fmla(h2 * h2, q0, q1); + + let q2 = f_fmla(h2, f64::from_bits(CH[5]), f64::from_bits(CH[3])); + + let to = f_fmla(h2, q2, f64::from_bits(CH[1])); + + let b0 = f_fmla(h, to, te); + let b1 = f_fmla(-h, to, te); + + f_fmla(f64::from_bits(sp), b0, -f64::from_bits(sm) * b1) as f32 +} + +/// Huperbolic sine function +/// +/// Max found ULP 0.4954563 +#[inline] +pub fn f_sinhf(x: f32) -> f32 { + const C: [u64; 4] = [ + 0x3ff0000000000000, + 0x3f962e42fef4c4e7, + 0x3f2ebfd1b232f475, + 0x3ebc6b19384ecd93, + ]; + + const ST: [(u32, u32, u32); 1] = [(0x74250bfeu32, 0x3a1285ff, 0x2d800000)]; + const ILN2: f64 = f64::from_bits(0x40471547652b82fe); + let t = x.to_bits(); + let z: f64 = x as f64; + let ux = t.wrapping_shl(1); + if ux > 0x8565a9f8u32 { + // |x| > 89.416 + let sgn = f32::copysign(2.0, x); + if ux >= 0xff000000u32 { + if ux.wrapping_shl(8) != 0 { + return x + x; + } // nan + return sgn * f32::INFINITY; // +-inf + } + let r = sgn * f64::from_bits(0x47efffffe0000000) as f32; + + return r; + } + if ux < 0x7c000000u32 { + // |x| < 0.125 + if ux <= 0x74250bfeu32 { + // |x| <= 0.000558942 + if ux < 0x66000000u32 { + // |x| < 5.96046e-08 + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, x.abs(), x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + return f_fmla(dx, dx.abs(), dx) as f32; + } + } + if ST[0].0 == ux { + let sgn = f32::copysign(1.0, x); + return f_fmlaf(sgn, f32::from_bits(ST[0].1), sgn * f32::from_bits(ST[0].2)); + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x * f64::from_bits(0x3fc5555560000000) as f32, x * x, x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + return f_fmla(dx * f64::from_bits(0x3fc5555560000000), dx * dx, dx) as f32; + } + } + const CP: [u64; 4] = [ + 0x3fc5555555555555, + 0x3f811111111146e1, + 0x3f2a01a00930dda6, + 0x3ec71f92198aa6e9, + ]; + let z2 = z * z; + let z4 = z2 * z2; + + let w0 = f_fmla(z2, f64::from_bits(CP[3]), f64::from_bits(CP[2])); + let w1 = f_fmla(z2, f64::from_bits(CP[1]), f64::from_bits(CP[0])); + let w2 = f_fmla(z4, w0, w1); + + return f_fmla(z2 * z, w2, z) as f32; + } + let a = ILN2 * z; + let ia = a.cpu_round_ties_even(); + let h = a - ia; + let h2 = h * h; + let ja = (ia + f64::from_bits(0x4338000000000000)).to_bits(); + let jp: i64 = ja as i64; + let jm = -jp; + let sp = TB[(jp & 31) as usize].wrapping_add(jp.wrapping_shr(5).wrapping_shl(52) as u64); + let sm = TB[(jm & 31) as usize].wrapping_add(jm.wrapping_shr(5).wrapping_shl(52) as u64); + let te = f_fmla(h2, f64::from_bits(C[2]), f64::from_bits(C[0])); + let to = f_fmla(h2, f64::from_bits(C[3]), f64::from_bits(C[1])); + let rp = f64::from_bits(sp) * f_fmla(h, to, te); + let rm = f64::from_bits(sm) * f_fmla(-h, to, te); + let r = rp - rm; + let ub = r; + let lb = r - f64::from_bits(0x3de4e406496685f4) * r; + // Ziv's accuracy test + if ub != lb { + return sinhf_accurate(z, ia, sp, sm); + } + ub as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sinhf() { + assert_eq!(f_sinhf(-0.5), -0.5210953); + assert_eq!(f_sinhf(0.5), 0.5210953); + assert_eq!(f_sinhf(7.), 548.3161); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanh.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanh.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanh.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanh.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,277 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1}; +use crate::hyperbolic::acosh::lpoly_xd_generic; +use crate::hyperbolic::sinh::hyperbolic_exp_accurate; + +#[cold] +fn as_tanh_zero(x: f64) -> f64 { + static CH: [(u64, u64); 10] = [ + (0xbc75555555555555, 0xbfd5555555555555), + (0x3c41111111110916, 0x3fc1111111111111), + (0x3c47917917a46f2c, 0xbfaba1ba1ba1ba1c), + (0xbc09a52a06f1e599, 0x3f9664f4882c10fa), + (0x3c2c297394c24e38, 0xbf8226e355e6c23d), + (0xbc0311087e5b1526, 0x3f6d6d3d0e157de0), + (0xbbe2868cde54ea0c, 0xbf57da36452b75e1), + (0x3bd2cd8fc406c3f7, 0x3f4355824803667b), + (0x3b9da22861b4ca80, 0xbf2f57d7734c821d), + (0xbbb0831108273a74, 0x3f1967e18ad3facf), + ]; + let dx2 = DoubleDouble::from_exact_mult(x, x); + const CL: [u64; 6] = [ + 0xbf0497d8e6462927, + 0x3ef0b1318c243bd7, + 0xbedb0f2935e9a120, + 0x3ec5e9444536e654, + 0xbeb174ff2a31908c, + 0x3e9749698c8d338d, + ]; + + let yw0 = f_fmla(dx2.hi, f64::from_bits(CL[5]), f64::from_bits(CL[4])); + let yw1 = f_fmla(dx2.hi, yw0, f64::from_bits(CL[3])); + let yw2 = f_fmla(dx2.hi, yw1, f64::from_bits(CL[2])); + let yw3 = f_fmla(dx2.hi, yw2, f64::from_bits(CL[1])); + let yw4 = f_fmla(dx2.hi, yw3, f64::from_bits(CL[0])); + + let y2 = dx2.hi * yw4; + + let mut y1 = lpoly_xd_generic(dx2, CH, y2); + y1 = DoubleDouble::quick_mult_f64(y1, x); + y1 = DoubleDouble::quick_mult(y1, dx2); // y2 = y1.l + let y0 = DoubleDouble::from_exact_add(x, y1.hi); // y0 = y0.hi + let mut p = DoubleDouble::from_exact_add(y0.lo, y1.lo); + let mut t = p.hi.to_bits(); + if (t & 0x000fffffffffffff) == 0 { + let w = p.lo.to_bits(); + if ((w ^ t) >> 63) != 0 { + t = t.wrapping_sub(1); + } else { + t = t.wrapping_add(1); + } + p.hi = f64::from_bits(t); + } + y0.hi + p.hi +} + +/// Hyperbolic tan +/// +/// Max ULP 0.5 +pub fn f_tanh(x: f64) -> f64 { + /* + The function tanh(x) is approximated by minimax polynomial for + |x|<0.25. For other values we use this identity tanh(|x|) = 1 - + 2*exp(-2*|x|)/(1 + exp(-2*|x|)). For large |x|>3.683 the term + 2*exp(-2*|x|)/(1 + exp(-2*|x|)) becomes small and we can use less + precise formula for exponent. + */ + let ax = x.abs(); + let ix = ax.to_bits(); + let aix: u64 = ix; + /* for |x| >= 0x1.30fc1931f09cap+4, tanh(x) rounds to +1 or -1 to nearest, + this avoid a spurious overflow in the computation of v0 below */ + if aix >= 0x40330fc1931f09cau64 { + if aix > 0x7ff0000000000000u64 { + return x + x; + } // nan + let f = f64::copysign(1.0, x); + if aix == 0x7ff0000000000000u64 { + return f; + } + let df = f64::copysign(f64::from_bits(0x3c80000000000000), x); + return f - df; + } + const S: f64 = f64::from_bits(0xc0c71547652b82fe); + let v0 = dd_fmla(ax, S, f64::from_bits(0x4188000004000000)); + let jt = v0.to_bits(); + let v = v0.to_bits() & 0xfffffffff8000000; + let t = f64::from_bits(v) - f64::from_bits(0x4188000000000000); + + let i1: i64 = ((jt >> 27) & 0x3f) as i64; + let i0 = (jt >> 33) & 0x3f; + let ie = ((jt.wrapping_shl(13)) >> 52) as i64; + let sp = (1023i64.wrapping_add(ie) as u64).wrapping_shl(52); + const CH: [u64; 4] = [ + 0x4000000000000000, + 0x4000000000000000, + 0x3ff55555557e54ff, + 0x3fe55555553a12f4, + ]; + let t0h = f64::from_bits(EXP_REDUCE_T0[i0 as usize].1); + let t1h = f64::from_bits(EXP_REDUCE_T1[i1 as usize].1); + let mut th = t0h * t1h; + let mut tl; + if aix < 0x400d76c8b4395810u64 { + // |x| ~< 3.683 + if aix < 0x3fd0000000000000u64 { + // |x| < 0x1p-2 + if aix < 0x3e10000000000000u64 { + // |x| < 0x1p-30 + if aix < 0x3df0000000000000u64 { + // |x| < 0x1p-32 + if aix == 0 { + return x; + } + /* We have underflow when 0 < |x| < 2^-1022 or when |x| = 2^-1022 + and rounding towards zero. */ + let res = dd_fmla(x, f64::from_bits(0xbc80000000000000), x); + return res; + } + let x3 = x * x * x; + return x - x3 / 3.; + } + + const C: [u64; 8] = [ + 0xbfd5555555555554, + 0x3fc1111111110d61, + 0xbfaba1ba1b983d8b, + 0x3f9664f4820e99f0, + 0xbf8226e11e4ac7cf, + 0x3f6d6c4ab70668b6, + 0xbf57bbecb57ce996, + 0x3f41451443697dd8, + ]; + let x2 = x * x; + let x3 = x2 * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let p1w0 = f_fmla(x2, f64::from_bits(C[7]), f64::from_bits(C[6])); + let p1w1 = f_fmla(x2, f64::from_bits(C[5]), f64::from_bits(C[4])); + + let p0w0 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let p0w1 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + + let p1 = f_fmla(x4, p1w0, p1w1); + let mut p0 = f_fmla(x4, p0w0, p0w1); + p0 += x8 * p1; + p0 *= x3; + let r = DoubleDouble::from_exact_add(x, p0); + let e = x3 * f64::from_bits(0x3cba000000000000); + let lb = r.hi + (r.lo - e); + let ub = r.hi + (r.lo + e); + if lb == ub { + return lb; + } + return as_tanh_zero(x); + } + + let t0l = f64::from_bits(EXP_REDUCE_T0[i0 as usize].0); + let t1l = f64::from_bits(EXP_REDUCE_T1[i1 as usize].0); + tl = f_fmla(t0h, t1l, t1h * t0l) + dd_fmla(t0h, t1h, -th); + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + const L2H: f64 = f64::from_bits(0xbf162e42ff000000); + const L2L: f64 = f64::from_bits(0xbcf718432a1b0e26); + let dx = f_fmla(-L2L, t, f_fmla(L2H, t, -ax)); + let dx2 = dx * dx; + + let pw0 = f_fmla(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pw1 = f_fmla(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let p = dx * f_fmla(dx2, pw0, pw1); + let mut rh = th; + let mut rl = tl + rh * p; + let mut r = DoubleDouble::from_exact_add(rh, rl); + + let ph = r.hi; + let pl = r.lo; + let mut qh = r.hi; + let mut ql = r.lo; + let qq = DoubleDouble::from_exact_add(1.0, qh); + qh = qq.hi; + ql += qq.lo; + + let rqh = 1.0 / qh; + let rql = f_fmla(ql, rqh, dd_fmla(rqh, qh, -1.)) * -rqh; + let p = DoubleDouble::mult(DoubleDouble::new(pl, ph), DoubleDouble::new(rql, rqh)); + + let e = r.hi * f64::from_bits(0x3c10000000000000); + r = DoubleDouble::from_exact_sub(0.5, p.hi); + r.lo -= p.lo; + rh = r.hi * f64::copysign(2., x); + rl = r.lo * f64::copysign(2., x); + let lb = rh + (rl - e); + let ub = rh + (rl + e); + if lb == ub { + return lb; + } + } else { + const L2: f64 = f64::from_bits(0xbf162e42fefa39ef); + let dx = dd_fmla(L2, t, -ax); + let dx2 = dx * dx; + + let pw0 = f_fmla(dx, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let pw1 = f_fmla(dx, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let p = dx * f_fmla(dx2, pw0, pw1); + let mut rh = th * f64::from_bits(sp); + rh += (p + ((2. * f64::from_bits(0x3c83000000000000)) * ax)) * rh; + let e = rh * f64::from_bits(0x3ce1000000000000); + rh = (2. * rh) / (1. + rh); + let one = f64::copysign(1., x); + rh = f64::copysign(rh, x); + let lb = one - (rh + e); + let ub = one - (rh - e); + if lb == ub { + return lb; + } + + let t0l = f64::from_bits(EXP_REDUCE_T0[i0 as usize].0); + let t1l = f64::from_bits(EXP_REDUCE_T1[i1 as usize].0); + tl = f_fmla(t0h, t1l, t1h * t0l) + dd_fmla(t0h, t1h, -th); + th *= f64::from_bits(sp); + tl *= f64::from_bits(sp); + } + + let mut r = hyperbolic_exp_accurate(-2. * ax, t, DoubleDouble::new(tl, th)); + let mut q = DoubleDouble::from_exact_add(1.0, r.hi); + q.lo += r.lo; + q = DoubleDouble::from_exact_add(q.hi, q.lo); + let rqh = 1. / q.hi; + let rql = f_fmla(q.lo, rqh, dd_fmla(rqh, q.hi, -1.)) * -rqh; + let p = DoubleDouble::mult(r, DoubleDouble::new(rql, rqh)); + r = DoubleDouble::from_exact_sub(0.5, p.hi); + r.lo -= p.lo; + r = DoubleDouble::from_exact_add(r.hi, r.lo); + f_fmla(f64::copysign(2., x), r.hi, f64::copysign(2., x) * r.lo) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tanh() { + assert_eq!(f_tanh(4.799980150947863), 0.9998645463239773); + assert_eq!(f_tanh(2.549980150947863), 0.9878799187977153); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanhf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanhf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanhf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/hyperbolic/tanhf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +/// Hyperbolic tangent +/// +/// Max found ULP 0.4999994 +#[inline] +pub fn f_tanhf(x: f32) -> f32 { + let z = x as f64; + let t = x.to_bits(); + let ux = t; + let e = ux.wrapping_shr(23) & 0xff; + if e == 0xff { + if ux << 9 != 0 { + return x + x; + } // x = nan + const IR: [f32; 2] = [1.0, -1.0]; + return IR[ux.wrapping_shr(31) as usize]; // x = +-inf + } + if e < 115 { + // |x| < 2^-13 + if e < 102 { + // |x| < 2^-26 + if ux.wrapping_shl(1) == 0 { + return x; + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + let res = f_fmlaf(-x, x.abs(), x); + return res; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + let res = f_fmla(-dx, dx.abs(), dx); + return res as f32; + } + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + let x2 = x * x; + return f_fmlaf(x, -f64::from_bits(0x3fd5555560000000) as f32 * x2, x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let dx = x as f64; + let x2 = dx * dx; + return f_fmla(dx, -f64::from_bits(0x3fd5555560000000) * x2, dx) as f32; + } + } + if ux.wrapping_shl(1) > (0x41102cb3u32 << 1) { + return f32::copysign(1.0, x) - f32::copysign(f64::from_bits(0x3e60000000000000) as f32, x); + } + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + const CN: [u64; 8] = [ + 0x3ff0000000000000, + 0x3fc30877b8b72d33, + 0x3f7694aa09ae9e5e, + 0x3f14101377abb729, + 0x3e9e0392b1db0018, + 0x3e12533756e546f7, + 0x3d6d62e5abe6ae8a, + 0x3c9b06be534182de, + ]; + const CD: [u64; 8] = [ + 0x3ff0000000000000, + 0x3fded99131b0ebea, + 0x3fa0d27ed6c95a69, + 0x3f47cbdaca0e9fcc, + 0x3edb4e60b892578e, + 0x3e5a6f707c5c71ab, + 0x3dc35a8b6e2cd94c, + 0x3d0ca8230677aa01, + ]; + let mut n0 = f_fmla(z2, f64::from_bits(CN[1]), f64::from_bits(CN[0])); + let n2 = f_fmla(z2, f64::from_bits(CN[3]), f64::from_bits(CN[2])); + let mut n4 = f_fmla(z2, f64::from_bits(CN[5]), f64::from_bits(CN[4])); + let n6 = f_fmla(z2, f64::from_bits(CN[7]), f64::from_bits(CN[6])); + n0 = f_fmla(z4, n2, n0); + n4 = f_fmla(z4, n6, n4); + n0 = f_fmla(z8, n4, n0); + let mut d0 = f_fmla(z2, f64::from_bits(CD[1]), f64::from_bits(CD[0])); + let d2 = f_fmla(z2, f64::from_bits(CD[3]), f64::from_bits(CD[2])); + let mut d4 = f_fmla(z2, f64::from_bits(CD[5]), f64::from_bits(CD[4])); + let d6 = f_fmla(z2, f64::from_bits(CD[7]), f64::from_bits(CD[6])); + d0 = f_fmla(z4, d2, d0); + d4 = f_fmla(z4, d6, d4); + d0 = f_fmla(z8, d4, d0); + let r = z * n0 / d0; + r as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tanhf() { + assert_eq!(f_tanhf(-0.5), -0.46211717); + assert_eq!(f_tanhf(0.5), 0.46211717); + assert_eq!(f_tanhf(7.), 0.99999833); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// #![forbid(unsafe_code)] +#![deny(unreachable_pub)] +#![allow( + clippy::excessive_precision, + clippy::approx_constant, + clippy::manual_range_contains +)] +#![deny( + clippy::print_stdout, + clippy::print_stderr, + clippy::print_literal, + clippy::print_in_format_impl +)] +mod acos; +mod acosf; +mod acospi; +mod acospif; +mod asin; +mod asin_eval_dyadic; +mod asinf; +mod asinpi; +mod asinpif; +mod bessel; +mod bits; +mod common; +mod compound; +mod cosm1; +mod csc; +mod cube_roots; +mod double_double; +mod dyadic_float; +mod err; +mod exponents; +mod gamma; +mod hyperbolic; +mod logs; +mod polyeval; +mod pow; +mod pow_exec; +mod pow_tables; +mod powf; +mod powf_tables; +mod rounding; +mod sec; +mod shared_eval; +mod sin; +mod sin_cosf; +mod sin_helper; +mod sin_table; +mod sinc; +mod sincos; +mod sincos_dyadic; +mod sincos_reduce; +mod sincos_reduce_tables; +mod sincospi; +mod sincospi_tables; +mod sincpi; +mod sinmx; +mod square_root; +mod tangent; +mod triangle; +mod triple_double; + +pub use acos::f_acos; +pub use acosf::f_acosf; +pub use acospi::f_acospi; +pub use acospif::f_acospif; +pub use asin::f_asin; +pub use asinf::f_asinf; +pub use asinpi::f_asinpi; +pub use asinpif::f_asinpif; +pub use bessel::{ + f_i0, f_i0e, f_i0ef, f_i0f, f_i1, f_i1e, f_i1ef, f_i1f, f_i2, f_i2f, f_j0, f_j0f, f_j1, f_j1f, + f_jincpi, f_jincpif, f_k0, f_k0e, f_k0ef, f_k0f, f_k1, f_k1e, f_k1ef, f_k1f, f_k2f, f_y0, + f_y0f, f_y1, f_y1f, +}; +pub use common::{copysignfk, copysignk}; +pub use compound::{f_compound, f_compound_m1, f_compound_m1f, f_compoundf, f_powm1, f_powm1f}; +pub use cosm1::f_cosm1; +pub use csc::f_csc; +pub use cube_roots::{cbrtf, f_cbrt, f_cbrtf, f_rcbrt, f_rcbrtf}; +pub use err::{ + f_erf, f_erfc, f_erfcf, f_erfcinv, f_erfcinvf, f_erfcx, f_erfcxf, f_erff, f_erfinv, f_erfinvf, + f_rerf, f_rerff, +}; +pub use exponents::{ + exp, expf, f_exp, f_exp2, f_exp2f, f_exp2m1, f_exp2m1f, f_exp10, f_exp10f, f_exp10m1, + f_exp10m1f, f_expf, f_expm1, f_expm1f, f_logistic, f_logisticf, +}; +pub use gamma::{ + f_beta, f_betaf, f_betainc_reg, f_betainc_regf, f_digamma, f_digammaf, f_gamma_p, f_gamma_pf, + f_gamma_q, f_gamma_qf, f_lgamma, f_lgamma_r, f_lgamma_rf, f_lgammaf, f_lnbeta, f_lnbetaf, + f_tgamma, f_tgammaf, f_trigamma, f_trigammaf, +}; +pub use hyperbolic::{ + f_acosh, f_acoshf, f_asinh, f_asinhf, f_atanh, f_atanhf, f_cosh, f_coshf, f_sinh, f_sinhf, + f_tanh, f_tanhf, +}; +pub use logs::{ + f_log, f_log1p, f_log1pf, f_log1pmx, f_log1pmxf, f_log2, f_log2f, f_log2p1, f_log2p1f, f_log10, + f_log10f, f_log10p1, f_log10p1f, f_logf, f_logit, f_logitf, log, logf, +}; +pub use pow::{f_pow, pow}; +pub use powf::{dirty_powf, f_powf, powf}; +pub use rounding::{ceil, ceilf}; +pub use rounding::{floor, floorf}; +pub use rounding::{rint, rintf, round, roundf, trunc, truncf}; +pub use rounding::{round_ties_even, roundf_ties_even}; +pub use sec::f_sec; +pub use sin::{f_cos, f_sin}; +pub use sin_cosf::{ + f_cosf, f_cosm1f, f_cospif, f_cscf, f_secf, f_sincf, f_sincosf, f_sincospif, f_sincpif, f_sinf, + f_sinmxf, f_sinpif, +}; +pub use sinc::f_sinc; +pub use sincos::f_sincos; +pub use sincospi::{f_cospi, f_sincospi, f_sinpi}; +pub use sincpi::f_sincpi; +pub use sinmx::f_sinmx; +pub use square_root::{f_rsqrt, f_rsqrtf, f_sqrt1pm1, f_sqrt1pm1f, sqrtf}; +pub use tangent::{ + f_atan, f_atan2, f_atan2f, f_atan2pi, f_atan2pif, f_atanf, f_atanpi, f_atanpif, f_cot, f_cotf, + f_cotpi, f_cotpif, f_tan, f_tanf, f_tanpi, f_tanpif, +}; +pub use triangle::{f_cathetus, f_cathetusf, f_hypot, f_hypot3f, f_hypotf}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/fast_log.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/fast_log.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::{LOG_COEFFS, LOG_R_DD, LOG_RANGE_REDUCTION}; +use crate::polyeval::f_polyeval4; + +#[inline] +pub(crate) fn simple_fast_log(x: f64) -> f64 { + let x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + let e_x = x_e as f64; + + const LOG_2_HI: f64 = f64::from_bits(0x3fe62e42fefa3800); + const LOG_2_LO: f64 = f64::from_bits(0x3d2ef35793c76730); + + let log_r_dd = LOG_R_DD[index as usize]; + + // hi is exact + let hi = f_fmla(e_x, LOG_2_HI, f64::from_bits(log_r_dd.1)); + // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err + // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo)) + let lo = f_fmla(e_x, LOG_2_LO, f64::from_bits(log_r_dd.0)); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + let r1 = DoubleDouble::from_exact_add(hi, u); + + let u_sq = u * u; + + // Degree-7 minimax polynomial + // Minimax polynomial for (log(1 + x) - x)/x^2, generated by sollya with: + // > P = fpminimax((log(1 + x) - x)/x^2, 5, [|D...|], [-2^-8, 2^-7]); + let p0 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[1]), + f64::from_bits(LOG_COEFFS[0]), + ); + let p1 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[3]), + f64::from_bits(LOG_COEFFS[2]), + ); + let p2 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[5]), + f64::from_bits(LOG_COEFFS[4]), + ); + let p = f_polyeval4(u_sq, lo + r1.lo, p0, p1, p2); + r1.hi + p +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/fast_log_dd.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log_dd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/fast_log_dd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/fast_log_dd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,369 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Given 2^-1074 <= x <= 0x1.fffffffffffffp+1023, this routine puts in h+l + an approximation of log(x) such that |l| < 2^-23.89*|h| and + + | h + l - log(x) | <= elog * |log x| + + with elog = 2^-73.527 if x < 1/sqrt(2) or sqrt(2) < x, + and elog = 2^-67.0544 if 1/sqrt(2) < x < sqrt(2) + (note that x cannot equal 1/sqrt(2) nor sqrt(2)). +*/ +use crate::common::dd_fmla; +use crate::double_double::DoubleDouble; +use crate::pow_exec::log_poly_1; +use crate::pow_tables::POW_INVERSE; + +// Generated by SageMath: +// values = POW_INVERSE +// R = RealField(150) +// +// def hex_to_float(h): +// return struct.unpack('>d', struct.pack('>Q', h))[0] +// +// real_array = [R(hex_to_float(h)) for h in values] +// +// for r in real_array: +// print_double_double("", -RealField(180)(r).log()) +pub(crate) static FAST_LOG_DD_INV: [(u64, u64); 182] = [ + (0x3c6bc60efafc6f6e, 0xbfd5ff3070a793d4), + (0x3c78ebcb7dee9a3d, 0xbfd5a42ab0f4cfe2), + (0x3c6819cf7e308ddb, 0xbfd548a2c3add263), + (0x3c742a87d977dc5e, 0xbfd4ec973260026a), + (0x3c69ffc341f177dc, 0xbfd49006804009d1), + (0x3c729931715ac903, 0xbfd432ef2a04e814), + (0x3c70bcfb6082ce6d, 0xbfd404308686a7e4), + (0x3c6c68651945f97c, 0xbfd3a64c556945ea), + (0x3c64dd4c580919f8, 0xbfd347dd9a987d55), + (0x3c78f4cdb95ebdf9, 0xbfd2e8e2bae11d31), + (0xbc77ad24c13f040e, 0xbfd2895a13de86a3), + (0x3c776f5eb09628af, 0xbfd22941fbcf7966), + (0x3c7c9fdf9a0c4b07, 0xbfd1f8ff9e48a2f3), + (0xbc79d3d1b0e4d147, 0xbfd1980d2dd4236f), + (0xbc77b66298edd24a, 0xbfd136870293a8b0), + (0xbc589fa0ab4cb31d, 0xbfd1058bf9ae4ad5), + (0xbc77dcfde8061c03, 0xbfd0a324e27390e3), + (0x3c628ec217a5022d, 0xbfd0402594b4d041), + (0x3c6caaae64f21acb, 0xbfcfb9186d5e3e2b), + (0xbc2c5f6dfd018c37, 0xbfcf550a564b7b37), + (0x3c46e03a39bfc89b, 0xbfce8c0252aa5a60), + (0x3c461578001e0162, 0xbfce27076e2af2e6), + (0xbc66e443597e4d40, 0xbfcd5c216b4fbb91), + (0x3c64f689f8434012, 0xbfcc8ff7c79a9a22), + (0x3c673dee38a3fb6b, 0xbfcc2968558c18c1), + (0xbc6ba27fdc19e1a0, 0xbfcb5b519e8fb5a4), + (0x3c5398cff3641985, 0xbfcaf3c94e80bff3), + (0xbc493711b07a998c, 0xbfca23bc1fe2b563), + (0xbc6575e31f003e0c, 0xbfc9bb362e7dfb83), + (0x3c6569d851a56770, 0xbfc8e928de886d41), + (0x3c6bf7fdbfa08d9a, 0xbfc87fa06520c911), + (0xbc4be36b2d6a0608, 0xbfc7ab890210d909), + (0x3c5b264062a84cdb, 0xbfc740f8f54037a5), + (0x3c6caae268ecd179, 0xbfc6d60fe719d21d), + (0x3c5bc60efafc6f6e, 0xbfc5ff3070a793d4), + (0x3c565d22aa8ad7cf, 0xbfc59338d9982086), + (0xbc668981bcc36756, 0xbfc4ba36f39a55e5), + (0xbc69f4f6543e1f88, 0xbfc44d2b6ccb7d1e), + (0x3c5ab3a8e7d81017, 0xbfc3dfc2b0ecc62a), + (0x3c06b9c7d96091fa, 0xbfc303d718e47fd3), + (0xbc6301771c407dbf, 0xbfc29552f81ff523), + (0xbc6f547bf1809e88, 0xbfc2266f190a5acb), + (0xbc6a28813e3a7f07, 0xbfc14785846742ac), + (0xbc69a5dc5e9030ac, 0xbfc0d77e7cd08e59), + (0xbc550c647eb86499, 0xbfc0671512ca596e), + (0xbc585f325c5bbacd, 0xbfbf0a30c01162a6), + (0x3c361578001e0162, 0xbfbe27076e2af2e6), + (0xbc5790dd951d90fa, 0xbfbd4313d66cb35d), + (0xbc35d617ef8161b1, 0xbfbc5e548f5bc743), + (0xbc5942f48aa70ea9, 0xbfba926d3a4ad563), + (0x3c42099e1c184e8e, 0xbfb9ab42462033ad), + (0x3c24a697ab3424a9, 0xbfb8c345d6319b21), + (0x3c5eeedfcdd94131, 0xbfb7da766d7b12cd), + (0x3c5388458ec21b6a, 0xbfb60658a93750c4), + (0xbc5a49e39a1a8be4, 0xbfb51b073f06183f), + (0xbc4ddd4f935996c9, 0xbfb42edcbea646f0), + (0x3c5b599f227becbb, 0xbfb341d7961bd1d1), + (0x3c1c125963fc4cfd, 0xbfb253f62f0a1417), + (0x3c379da3e8c22cda, 0xbfb16536eea37ae1), + (0xbc485f325c5bbacd, 0xbfaf0a30c01162a6), + (0xbc21e3c53257fd47, 0xbfad276b8adb0b52), + (0x3c3eb9759c130499, 0xbfab42dd711971bf), + (0xbc4f5a0e80520bf2, 0xbfa95c830ec8e3eb), + (0xbc418d3ca87b9296, 0xbfa77458f632dcfc), + (0x3c4ce55c2b4e2b72, 0xbfa58a5bafc8e4d5), + (0x3c45bfa937f551bb, 0xbfa39e87b9febd60), + (0x3c3e9ae889bac481, 0xbfa1b0d98923d980), + (0xbc333e3f04f1ef23, 0xbf9f829b0e783300), + (0x3bf0ae69229dc868, 0xbf9b9fc027af9198), + (0x3c35b602ace3a510, 0xbf97b91b07d5b11b), + (0x3c10cb5a902b3a1c, 0xbf93cea44346a575), + (0x3c183092c59642a1, 0xbf8fc0a8b0fc03e4), + (0x3c116d7687d3df21, 0xbf87dc475f810a77), + (0x3bce44b7e3711ebf, 0xbf7fe02a6b106789), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3bec14b9f9377a1d, 0x3f78121214586b54), + (0xbc2c5517f64bc223, 0x3f841929f96832f0), + (0x3c2806208c04c220, 0x3f8c317384c75f06), + (0xbc2cd7b66e01c26d, 0x3f9228fb1fea2e28), + (0xbbf8ed4d357c9c97, 0x3f963d6178690bd6), + (0x3c1ec1a5f86d41f9, 0x3f9a55f548c5c43f), + (0x3c375b44595cab18, 0x3f9e72bf2813ce51), + (0x3c4c05cf1d753622, 0x3fa0415d89e74444), + (0xbc4947f792615916, 0x3fa252f32f8d183f), + (0xbc4cdd6f7f4a137e, 0x3fa466aed42de3ea), + (0x3c40413e6505e603, 0x3fa67c94f2d4bb58), + (0x3c3a8be97660a23d, 0x3fa894aa149fb343), + (0x3c2a353bb42e0add, 0x3faaaef2d0fb10fc), + (0x3c3e5cf3a0f56f72, 0x3fabbcebfc68f420), + (0x3c44e6c986f44c55, 0x3fadda8adc67ee4e), + (0xbc4cd9f1f95c2eed, 0x3faffa6911ab9301), + (0xbc5a4a128d192686, 0x3fb10e45b3cae831), + (0xbc5cc0fbce104eaa, 0x3fb2207b5c78549e), + (0xbc5d15d38d2fa3f7, 0x3fb2aa04a44717a5), + (0x3c47a976d3b5b45f, 0x3fb3bdf5a7d1ee64), + (0x3c5769f42c7842cc, 0x3fb4d3115d207eac), + (0xbc545f9d61c68c1b, 0x3fb55e10050e0384), + (0xbc59acd8b33f8fdc, 0x3fb674f089365a7a), + (0x3c5abca5b4fdb880, 0x3fb78d02263d82d3), + (0x3c3b9f2dffbeed43, 0x3fb8197e2f40e3f0), + (0xbc5478a85704ccb7, 0x3fb9335e5d594989), + (0xbc55b5ca203e4259, 0x3fba4e7640b1bc38), + (0x3c537d8f39bee659, 0x3fbadc77ee5aea8c), + (0xbc4cdc9f6f5f38c7, 0x3fbbf968769fca11), + (0x3c49daf7df76ad2a, 0x3fbd179788219364), + (0x3c5401fa71733019, 0x3fbda727638446a2), + (0xbc4a2bf991780d3f, 0x3fbec739830a1120), + (0xbc59361574fb24e2, 0x3fbf57bc7d9005db), + (0x3c639e2d3f8b7d10, 0x3fc03cdc0a51ec0d), + (0xbc6dd7009902bf32, 0x3fc08598b59e3a07), + (0xbc50e63a5f01c691, 0x3fc1178e8227e47c), + (0xbc62d56ff61c2bfb, 0x3fc160c8024b27b1), + (0x3c462c9ef939ac5d, 0x3fc1f3b925f25d41), + (0xbc66e38161051d69, 0x3fc23d712a49c202), + (0xbc5499a3f25af95f, 0x3fc2d1610c86813a), + (0xbc5c4716bdfc0cc9, 0x3fc31b994d3a4f85), + (0x3c370d6cdf05266c, 0x3fc3b08b6757f2a9), + (0xbc6d87e6a354d056, 0x3fc3fb45a59928cc), + (0xbc50d5604930f135, 0x3fc4913d8333b561), + (0xbc6927d47803c5f4, 0x3fc4dc7b897bc1c8), + (0x3c64f4d710fec38e, 0x3fc5737cc9018cdd), + (0xbc21f5b44c0df7e7, 0x3fc5bf406b543db2), + (0xbc3d34f0f4621bed, 0x3fc6574ebe8c133a), + (0x3c696332bd4b341f, 0x3fc6a399dabbd383), + (0xbc68de59c21e166c, 0x3fc6f0128b756abc), + (0x3c5ef8f6ebcfb201, 0x3fc7898d85444c73), + (0xbc4ac5f0c075b847, 0x3fc7d6903caf5ad0), + (0x3c6d685f35eea2a0, 0x3fc871213750e994), + (0x3c555aa8b6997a40, 0x3fc8beafeb38fe8c), + (0x3c6054473941ad99, 0x3fc90c6db9fcbcd9), + (0x3c6f47dfd871f87f, 0x3fc9a8778debaa38), + (0x3c435a19605e67ef, 0x3fc9f6c407089664), + (0x3c5df207dc5c34c6, 0x3fca454082e6ab05), + (0x3c6ab5ca9eaa088a, 0x3fcae2ca6f672bd4), + (0xbc66353ab386a94d, 0x3fcb31d8575bce3d), + (0x3c3a0ee735d9f0ec, 0x3fcb811730b823d2), + (0x3c3dd355f6a516d7, 0x3fcbd087383bd8ad), + (0xbc68e58b2c57a4a5, 0x3fcc6ffbc6f00f71), + (0x3c653d154280394f, 0x3fccc000c9db3c52), + (0x3c660629242471a2, 0x3fcd1037f2655e7b), + (0x3c5aa11d49f96cb9, 0x3fcdb13db0d48940), + (0x3c5fea48dd7b81d1, 0x3fce020cc6235ab5), + (0x3c42276041f43042, 0x3fce530effe71012), + (0xbc6d33919ab94074, 0x3fcea4449f04aaf5), + (0xbc527c77ded76aad, 0x3fcf474b134df229), + (0x3c6f665066f980a2, 0x3fcf991c6cb3b379), + (0x3c28de00938b4c40, 0x3fcfeb2233ea07cd), + (0xbc418290bd2932e2, 0x3fd01eae5626c691), + (0xbc70779634061cbc, 0x3fd047e60cde83b8), + (0x3c643c2e68684d53, 0x3fd09aa572e6c6d4), + (0x3c5162c79d5d11ee, 0x3fd0c42d676162e3), + (0xbc692b49ef282b09, 0x3fd0edd060b78081), + (0xbc60e63a5f01c691, 0x3fd1178e8227e47c), + (0x3c1e0936abd4fa6e, 0x3fd14167ef367783), + (0x3c766fbd28b40935, 0x3fd16b5ccbacfb73), + (0xbc612aeb84249223, 0x3fd1bf99635a6b95), + (0x3c7512c3749a1e4e, 0x3fd1e9e1678899f4), + (0x3c6f7ae91aeba60a, 0x3fd214456d0eb8d4), + (0x3c3bb75d1addf870, 0x3fd23ec5991eba49), + (0x3c7e0efadd9db02b, 0x3fd269621134db92), + (0xbc6856e61c515740, 0x3fd2941afb186b7c), + (0xbc782dad7fd86088, 0x3fd2bef07cdc9354), + (0xbc73d69909e5c3dc, 0x3fd314f1e1d35ce4), + (0xbc5cd55b8a4746c0, 0x3fd3401e12aecba1), + (0xbc5324f0e883858e, 0x3fd36b6776be1117), + (0xbc5ce2b31b31e8b0, 0x3fd396ce359bbf54), + (0xbc72ad27e50a8ec6, 0x3fd3c25277333184), + (0x3c783d680d3c1084, 0x3fd3edf463c1683e), + (0x3c60dbb243827392, 0x3fd419b423d5e8c7), + (0xbc72b125247b0fa5, 0x3fd44591e0539f49), + (0x3c38fb4c14c56eef, 0x3fd4718dc271c41b), + (0xbc69964a168ccaca, 0x3fd49da7f3bcc41f), + (0xbc5123615b147a5d, 0x3fd4c9e09e172c3c), + (0xbc758cb3124b9245, 0x3fd4f637ebba9810), + (0xbc68f7e9b38a6979, 0x3fd522ae0738a3d8), + (0xbc7aacfdbbdab914, 0x3fd54f431b7be1a9), + (0xbc60908d15f88b63, 0x3fd57bf753c8d1fb), + (0xbc5e6c2bdfb3e037, 0x3fd5a8cadbbedfa1), + (0xbc76541148cbb8a2, 0x3fd5d5bddf595f30), + (0xbc56e8920c09b73f, 0x3fd602d08af091ec), + (0x3c6dc18ce51fff99, 0x3fd630030b3aac49), +]; + +#[inline] +pub(crate) fn fast_log_dd(ddx: DoubleDouble) -> DoubleDouble { + // We'll compute log((z+1)+1) as log(xh+xl) = log(xh) + log(1+xl/xh). + // since xl/xh < ulp(xh) we'll use for log(1+xl/xh) + // one taylor term what means that log(1+xl/xh) = log_lo + O(x^2) + let log_lo = if ddx.hi <= f64::from_bits(0x7fd0000000000000) || ddx.lo.abs() >= 4.0 { + ddx.lo / ddx.hi + } else { + 0. + }; // avoid spurious underflow + + let x_u = ddx.hi.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; /* i/2^8 <= t < (i+1)/2^8 */ + /* when c=1, we have 0x16a09e667f3bcd <= m < 2^53, thus 90 <= i <= 127; + when c=0, we have 2^52 <= m < 0x16a09e667f3bcd, thus 128 <= i <= 181 */ + t *= CY[c]; + /* now 0x1.6a09e667f3bcdp-1 <= t < 0x1.6a09e667f3bcdp+0, + and log(x) = E * log(2) + log(t) */ + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(FAST_LOG_DD_INV[(i - 181) as usize]); + + let z = dd_fmla(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let dt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let mut v = DoubleDouble::f64_add(dt.hi, DoubleDouble::new(dt.lo, z)); + let p = log_poly_1(z); + v = DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo + log_lo, p.hi)); + + v +} + +#[inline] +pub(crate) fn fast_log_d_to_dd(ddx: f64) -> DoubleDouble { + // We'll compute log((z+1)+1) as log(xh+xl) = log(xh) + log(1+xl/xh). + // since xl/xh < ulp(xh) we'll use for log(1+xl/xh) + // one taylor term what means that log(1+xl/xh) = log_lo + O(x^2) + + let x_u = ddx.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; /* i/2^8 <= t < (i+1)/2^8 */ + /* when c=1, we have 0x16a09e667f3bcd <= m < 2^53, thus 90 <= i <= 127; + when c=0, we have 2^52 <= m < 0x16a09e667f3bcd, thus 128 <= i <= 181 */ + t *= CY[c]; + /* now 0x1.6a09e667f3bcdp-1 <= t < 0x1.6a09e667f3bcdp+0, + and log(x) = E * log(2) + log(t) */ + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(FAST_LOG_DD_INV[(i - 181) as usize]); + + let z = dd_fmla(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let dt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let mut v = DoubleDouble::f64_add(dt.hi, DoubleDouble::new(dt.lo, z)); + let p = log_poly_1(z); + v = DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)); + + DoubleDouble::from_exact_add(v.hi, v.lo) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,465 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, fmla, min_normal_f64}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log_dyadic::{LOG_STEP_1, LOG_STEP_2, LOG_STEP_3, LOG_STEP_4}; +use crate::logs::log_range_reduction::log_range_reduction; +use crate::logs::log_td::log_td; +use crate::logs::log2::LOG_RANGE_REDUCTION; +use crate::logs::log10::LOG_R_DD; +use crate::logs::{LOG_COEFFS, log_dd}; +use crate::polyeval::f_polyeval4; + +/// Assumes that NaN and infinities, negatives were filtered out +pub(crate) fn log_dyadic(x: f64) -> DyadicFloat128 { + let mut x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + const MAX_NORMAL: u64 = f64::to_bits(f64::MAX); + + if x_u == 1f64.to_bits() { + // log2(1.0) = +0.0 + return DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0u128, + }; + } + if x_u < min_normal_f64().to_bits() || x_u > MAX_NORMAL { + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4330000000000000)).to_bits(); + x_e -= 52; + } + + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log2::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + log_accurate(x_e, index, u) +} + +// Reuse the output of the fast pass range reduction. +// -2^-8 <= m_x < 2^-7 +#[cold] +fn log_accurate(e_x: i32, index: i32, m_x: f64) -> DyadicFloat128 { + // > P = fpminimax((log(1 + x) - x)/x^2, 2, [|1, 128...|], + // [-0x1.0002143p-29 , 0x1p-29]); + // > P; + // > dirtyinfnorm(log(1 + x)/x - x*P, [-0x1.0002143p-29 , 0x1p-29]); + // 0x1.99a3...p-121 + const BIG_COEFFS: [DyadicFloat128; 3] = [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x8000_0000_0006_a710_b59c_58e5_554d_581c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaaaa_aaaa_aaaa_aabd_de05_c7c9_4ae9_cbae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + ]; + + const LOG_2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb17217f7_d1cf79ab_c9e3b398_03f2f6af_u128, + }; + + let e_x_f128 = DyadicFloat128::new_from_f64(e_x as f64); + let mut sum = LOG_2 * e_x_f128; + sum = sum + LOG_STEP_1[index as usize]; + + let (v_f128, mut sum) = log_range_reduction( + m_x, + &[&LOG_STEP_1, &LOG_STEP_2, &LOG_STEP_3, &LOG_STEP_4], + sum, + ); + + sum = sum + v_f128; + + // Polynomial approximation + let mut p = v_f128 * BIG_COEFFS[0]; + + p = v_f128 * (p + BIG_COEFFS[1]); + p = v_f128 * (p + BIG_COEFFS[2]); + p = v_f128 * p; + + sum + p +} + +/// Natural logarithm +/// +/// Max found ULP 0.5 +pub fn f_log(x: f64) -> f64 { + let mut x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + const MAX_NORMAL: u64 = f64::to_bits(f64::MAX); + + if x_u == 1f64.to_bits() { + // log2(1.0) = +0.0 + return 0.0; + } + if x_u < min_normal_f64().to_bits() || x_u > MAX_NORMAL { + if x == 0.0 { + return f64::NEG_INFINITY; + } + if x < 0. || x.is_nan() { + return f64::NAN; + } + if x.is_infinite() || x.is_nan() { + return x + x; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4330000000000000)).to_bits(); + x_e -= 52; + } + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + let e_x = x_e as f64; + + const LOG_2_HI: f64 = f64::from_bits(0x3fe62e42fefa3800); + const LOG_2_LO: f64 = f64::from_bits(0x3d2ef35793c76730); + + let log_r_dd = LOG_R_DD[index as usize]; + + // hi is exact + let hi = f_fmla(e_x, LOG_2_HI, f64::from_bits(log_r_dd.1)); + // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err + // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo)) + let lo = f_fmla(e_x, LOG_2_LO, f64::from_bits(log_r_dd.0)); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log2::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + let r1 = DoubleDouble::from_exact_add(hi, u); + + let u_sq = u * u; + + // Degree-7 minimax polynomial + // Minimax polynomial for (log(1 + x) - x)/x^2, generated by sollya with: + // > P = fpminimax((log(1 + x) - x)/x^2, 5, [|D...|], [-2^-8, 2^-7]); + + let p0 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[1]), + f64::from_bits(LOG_COEFFS[0]), + ); + let p1 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[3]), + f64::from_bits(LOG_COEFFS[2]), + ); + let p2 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[5]), + f64::from_bits(LOG_COEFFS[4]), + ); + let p = f_polyeval4(u_sq, lo + r1.lo, p0, p1, p2); + + const HI_ERR: f64 = f64::from_bits(0x3aa0000000000000); + + // Extra errors from P is from using x^2 to reduce evaluation latency. + const P_ERR: f64 = f64::from_bits(0x3cd0000000000000); + + // Technicallly error of r1.lo is bounded by: + // hi*ulp(log(2)_lo) + C*ulp(u^2) + // To simplify the error computation a bit, we replace |hi|*ulp(log(2)_lo) + // with the upper bound: 2^11 * ulp(log(2)_lo) = 2^-85. + // Total error is bounded by ~ C * ulp(u^2) + 2^-85. + let err = f_fmla(u_sq, P_ERR, HI_ERR); + + // Lower bound from the result + let left = r1.hi + (p - err); + // Upper bound from the result + let right = r1.hi + (p + err); + + // Ziv's test if fast pass is accurate enough. + if left == right { + return left; + } + + log_accurate_slow(x) +} + +#[cold] +#[inline(never)] +fn log_accurate_slow(x: f64) -> f64 { + let r = log_dd(x); + let err = f_fmla( + r.hi, + f64::from_bits(0x3b50000000000000), // 2^-74 + f64::from_bits(0x3990000000000000), // 2^-102 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r.to_f64(); + } + log_accurate_slow_td(x) +} + +#[cold] +#[inline(never)] +fn log_accurate_slow_td(x: f64) -> f64 { + log_td(x).to_f64() +} + +/// Log for given value for const context. +/// This is simplified version just to make a good approximation on const context. +#[inline] +pub const fn log(d: f64) -> f64 { + const LN_POLY_2_D: f64 = 0.6666666666666762678e+0; + const LN_POLY_3_D: f64 = 0.3999999999936908641e+0; + const LN_POLY_4_D: f64 = 0.2857142874046159249e+0; + const LN_POLY_5_D: f64 = 0.2222219947428228041e+0; + const LN_POLY_6_D: f64 = 0.1818349302807168999e+0; + const LN_POLY_7_D: f64 = 0.1531633000781658996e+0; + const LN_POLY_8_D: f64 = 0.1476969208015536904e+0; + + let e = d.to_bits().wrapping_shr(52).wrapping_sub(0x3ff); + if e >= 0x400 || e == 0x00000000fffffc01 { + let minf = 0xfffu64 << 52; + if e == 0x400 || (e == 0xc00 && d != f64::from_bits(minf)) { + /* +Inf or NaN */ + return d + d; + } + if d <= 0. { + return if d < 0. { f64::NAN } else { f64::NEG_INFINITY }; + } + } + + // reduce into [sqrt(2)/2;sqrt(2)] + let mut ui: u64 = d.to_bits(); + let mut hx = (ui >> 32) as u32; + hx = hx.wrapping_add(0x3ff00000 - 0x3fe6a09e); + let n = (hx >> 20) as i32 - 0x3ff; + hx = (hx & 0x000fffff).wrapping_add(0x3fe6a09e); + ui = (hx as u64) << 32 | (ui & 0xffffffff); + let a = f64::from_bits(ui); + + let m = a - 1.; + + let x = m / (a + 1.); + let x2 = x * x; + let f = x2; + + const LN2_H: f64 = 0.6931471805599453; + const LN2_L: f64 = 2.3190468138462996e-17; + + let mut u = LN_POLY_8_D; + u = fmla(u, f, LN_POLY_7_D); + u = fmla(u, f, LN_POLY_6_D); + u = fmla(u, f, LN_POLY_5_D); + u = fmla(u, f, LN_POLY_4_D); + u = fmla(u, f, LN_POLY_3_D); + u = fmla(u, f, LN_POLY_2_D); + u *= f; + + let t = m * m * 0.5; + let r = fmla(x, t, fmla(x, u, LN2_L * n as f64)) - t + m; + fmla(LN2_H, n as f64, r) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn log_test() { + assert!( + (log(1f64) - 0f64).abs() < 1e-8, + "Invalid result {}", + log(1f64) + ); + assert!( + (log(5f64) - 1.60943791243410037460f64).abs() < 1e-8, + "Invalid result {}", + log(5f64) + ); + } + + #[test] + fn f_log_test() { + assert_eq!(f_log(1.99999999779061), 0.693147179455250308807056); + assert_eq!(f_log(0.9999999999999999), -1.1102230246251565e-16); + assert!( + (f_log(1f64) - 0f64).abs() < 1e-8, + "Invalid result {}", + f_log(1f64) + ); + assert!( + (f_log(5f64) - 5f64.ln()).abs() < 1e-8, + "Invalid result {}, expected {}", + f_log(5f64), + 5f64.ln() + ); + assert_eq!( + f_log(23f64), + 3.13549421592914969080675283181019611844238031484043574199863537748299324598, + "Invalid result {}, expected {}", + f_log(23f64), + 3.13549421592914969080675283181019611844238031484043574199863537748299324598, + ); + assert_eq!(f_log(0.), f64::NEG_INFINITY); + assert!(f_log(-1.).is_nan()); + assert!(f_log(f64::NAN).is_nan()); + assert!(f_log(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_log(f64::INFINITY), f64::INFINITY); + } + + #[test] + fn log_control_values() { + assert_eq!( + f_log(f64::from_bits(0x3ff1211bef8f68e9)), + 0.06820362355801819 + ); + assert_eq!( + f_log(f64::from_bits(0x3ff008000db2e8be)), + 0.0019512710640270448 + ); + assert_eq!( + f_log(f64::from_bits(0x3ff10803885617a6)), + 0.062464334544603616 + ); + assert_eq!( + f_log(f64::from_bits(0x3ff48ae5a67204f5)), + 0.24991043470757288 + ); + assert_eq!( + f_log(f64::from_bits(0x3fedc0b586f2b260)), + -0.07281366978582131 + ); + assert_eq!( + f_log(f64::from_bits(0x3fe490af72a25a81)), + -0.44213668842326787 + ); + assert_eq!( + f_log(f64::from_bits(0x4015b6e7e4e96f86)), + 1.6916847703128641 + ); + assert_eq!( + f_log(f64::from_bits(0x3ff0ffc349469a2f)), + 0.06057012512237759 + ); + assert_eq!( + f_log(f64::from_bits(0x3fe69e7aa6da2df5)), + -0.3469430325599064 + ); + assert_eq!( + f_log(f64::from_bits(0x3fe5556123e8a2b0)), + -0.4054566631657151 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,500 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, min_normal_f64}; +use crate::double_double::DoubleDouble; +use crate::logs::log2::LOG_COEFFS; +use crate::logs::log10dd::log10_dd; +use crate::logs::log10td::log10_td; +use crate::polyeval::f_polyeval4; + +// Generated by SageMath with: +// print("[") +// for i in range(128): +// R = RealField(200) +// r = R(2)**(-8) * ( R(2)**8 * (R(1) - R(2)**(-8)) / (R(1) + R(i)*R(2)**-7) ).ceil() +// b = float((r.log10()*R(2)**43).round() * R(2)**-43) +// c = (r.log10() - R(b)) +// if i == 0 or i == 127: +// print("(", double_to_hex(0), ",", double_to_hex(0), "),") +// else: +// print("(", double_to_hex(-c), ",", double_to_hex(-b), "),") +// print("];") +// static LOG10_R_DD: [(u64, u64); 128] = [ +// (0x0000000000000000, 0x0000000000000000), +// (0xbd16079e5269431b, 0x3f6be76bd77c0000), +// (0xbcffac7d2ae08e4f, 0x3f7c03a80ae60000), +// (0x3d2fabf59b5d80b8, 0x3f851824c7580000), +// (0x3d2310272fe17537, 0x3f8c3d0837780000), +// (0xbd165201646ebccd, 0x3f91b85d60450000), +// (0xbd2e22fab794a816, 0x3f9559bd24070000), +// (0x3d2421bab5f034a4, 0x3f9902c31d628000), +// (0x3d2fedb4b594a31b, 0x3f9cb38fccd88000), +// (0xbd026ac877784097, 0x3f9e8eeb09f30000), +// (0xbd2df23ed2ebe477, 0x3fa125d0432ec000), +// (0xbd000c12f7a1b586, 0x3fa30838cdc30000), +// (0x3d083662f181f53f, 0x3fa3faf7c6630000), +// (0x3d22951bb9cd2fb7, 0x3fa5e3966b7e8000), +// (0x3d1fae96a708581e, 0x3fa7d070145f4000), +// (0x3d20744e2ea4f128, 0x3fa8c878eeb04000), +// (0xbcfb0197d2cb982e, 0x3faabbcebd850000), +// (0xbd2b1aad42a57f54, 0x3fabb7209d1e4000), +// (0xbd240bcd23c3e44c, 0x3fadb11ed766c000), +// (0xbcf626d2c723bf3b, 0x3faeafd05035c000), +// (0x3cf77c3e779b9fcf, 0x3fb0585283764000), +// (0x3cef3735158d42c3, 0x3fb0d966cc650000), +// (0xbd2d227d61f9e88d, 0x3fb1dd5460c8c000), +// (0xbcdf74be7c4de292, 0x3fb2603072a26000), +// (0xbd1df5de49ddb160, 0x3fb367ba3aaa2000), +// (0xbd1e5e3b38ac267a, 0x3fb3ec6ad5408000), +// (0x3d275da8a5871b9a, 0x3fb4f7aad9bbc000), +// (0x3d2ef5f3c10990f4, 0x3fb57e3d47c3a000), +// (0x3d17c3cf23a17d9f, 0x3fb605735ee98000), +// (0xbd141149840eaa65, 0x3fb715d0ce368000), +// (0xbd1ff281b9601ce6, 0x3fb79efb57b10000), +// (0x3d00a581f3edc493, 0x3fb828cfed29a000), +// (0xbcf80743406505e6, 0x3fb93e7de0fc4000), +// (0xbce76b169f6b4949, 0x3fb9ca5aa172a000), +// (0xbd0bc8889d0fe1a0, 0x3fba56e8325f6000), +// (0xbd25e950adf89934, 0x3fbae4285509a000), +// (0xbd203ad4133e8c4c, 0x3fbb721cd1716000), +// (0xbd2ddd18dedb6656, 0x3fbc902a19e66000), +// (0x3d05e533080ecf32, 0x3fbd204698cb4000), +// (0x3d27e865b8783768, 0x3fbdb11ed766a000), +// (0x3d25e50ff38d4de9, 0x3fbe42b4c16ca000), +// (0x3d25f7ef576ada0c, 0x3fbed50a4a26e000), +// (0xbd1ff229f20ed3d2, 0x3fbffbfc2bbc8000), +// (0xbd26f30673aae7ef, 0x3fc0484e4942b000), +// (0x3d2dae5ed5e3f34c, 0x3fc093025a199000), +// (0xbd23eea49e637bb3, 0x3fc0de1b56357000), +// (0x3d182c6326f70b35, 0x3fc1299a4fb3e000), +// (0x3d2f04d633b79054, 0x3fc175805d158000), +// (0x3cf8b891b6d05a73, 0x3fc1c1ce9955c000), +// (0xbcc35ca658049a0a, 0x3fc20e8624039000), +// (0x3d2ff081a4e81f0b, 0x3fc25ba8215af000), +// (0x3d21e3f04f63ee01, 0x3fc2a935ba5f1000), +// (0xbd2e1471e5cb397e, 0x3fc2f7301cf4f000), +// (0xbd25bd54fd6eb7d9, 0x3fc345987bfef000), +// (0x3d1fe93f791a7264, 0x3fc394700f795000), +// (0xbd28aebce3ec8738, 0x3fc3e3b814974000), +// (0x3d2b0722aa2559f2, 0x3fc43371cde07000), +// (0xbd1bcb784188a058, 0x3fc4839e83507000), +// (0x3d220ca9a2bcc728, 0x3fc4d43f8275a000), +// (0x3d2bb95ec8fd8f68, 0x3fc525561e925000), +// (0x3cf4e036062e2e73, 0x3fc576e3b0bde000), +// (0xbcce560b5e7a02b4, 0x3fc5c8e998073000), +// (0x3ce1e472c751a4c0, 0x3fc61b6939983000), +// (0xbcf1116ad28239b0, 0x3fc66e6400da4000), +// (0x3d19ad1d9e405fb9, 0x3fc6c1db5f9bb000), +// (0x3d19ad1d9e405fb9, 0x3fc6c1db5f9bb000), +// (0xbd241149840eaa65, 0x3fc715d0ce368000), +// (0x3d2bfb1de334b1cb, 0x3fc76a45cbb7e000), +// (0xbcf9fc01708d86e7, 0x3fc7bf3bde09a000), +// (0x3d24adaf7fe992b6, 0x3fc814b4921bd000), +// (0xbd1c0b434f5d2b7a, 0x3fc86ab17c10c000), +// (0xbd1c0b434f5d2b7a, 0x3fc86ab17c10c000), +// (0x3d24c7acd659652f, 0x3fc8c13437695000), +// (0x3d23e99da1b485cf, 0x3fc9183e67339000), +// (0xbd1fb7d8e74e02a0, 0x3fc96fd1b63a0000), +// (0x3d17c9690248757e, 0x3fc9c7efd734a000), +// (0xbcb0cee0ed4ca7e9, 0x3fca209a84fbd000), +// (0xbcb0cee0ed4ca7e9, 0x3fca209a84fbd000), +// (0x3d0d924eb1fec6c5, 0x3fca79d382bc2000), +// (0x3cefe6eb5a4df1df, 0x3fcad39c9c2c6000), +// (0x3d14c9cce6dd603b, 0x3fcb2df7a5c50000), +// (0x3d14c9cce6dd603b, 0x3fcb2df7a5c50000), +// (0xbd2a01b9bb0ebf1b, 0x3fcb88e67cf98000), +// (0x3d22ee896e06dbe8, 0x3fcbe46b08735000), +// (0xbceff2381071d23e, 0x3fcc4087384f5000), +// (0xbceff2381071d23e, 0x3fcc4087384f5000), +// (0xbd22f9fd61140aa6, 0x3fcc9d3d065c6000), +// (0xbd22386ad8b819b8, 0x3fccfa8e765cc000), +// (0xbd22386ad8b819b8, 0x3fccfa8e765cc000), +// (0x3d2d63da3ac9f0d5, 0x3fcd587d96494000), +// (0x3d2fcc16f3ba09cb, 0x3fcdb70c7e96e000), +// (0x3d2fcc16f3ba09cb, 0x3fcdb70c7e96e000), +// (0xbd2cc52c1ba2d838, 0x3fce163d527e7000), +// (0x3d1f97877007c127, 0x3fce76124046b000), +// (0x3d1f97877007c127, 0x3fce76124046b000), +// (0x3d0fbd42fdc335fd, 0x3fced68d81919000), +// (0xbd2cbc0789055864, 0x3fcf37b15bab1000), +// (0xbd2cbc0789055864, 0x3fcf37b15bab1000), +// (0x3d22737df7f29668, 0x3fcf99801fdb7000), +// (0xbd2ff229f20ed3d2, 0x3fcffbfc2bbc8000), +// (0xbd2ff229f20ed3d2, 0x3fcffbfc2bbc8000), +// (0x3d100809c16ae3ec, 0x3fd02f93f4c87000), +// (0xbd2aa1358e87a6b4, 0x3fd06182e84fd800), +// (0xbd2aa1358e87a6b4, 0x3fd06182e84fd800), +// (0xbcff171b2c5f2274, 0x3fd093cc32c91000), +// (0xbcff171b2c5f2274, 0x3fd093cc32c91000), +// (0xbd242d6ae59e7d9c, 0x3fd0c6711d6ac000), +// (0x3d2eac1871dbdbbf, 0x3fd0f972f87ff000), +// (0x3d2eac1871dbdbbf, 0x3fd0f972f87ff000), +// (0x3d1feed957c16a44, 0x3fd12cd31b9c9800), +// (0x3d1feed957c16a44, 0x3fd12cd31b9c9800), +// (0x3d1a6023a51d15b6, 0x3fd16092e5d3a800), +// (0x3d2cefc5208422d8, 0x3fd194b3bdef6800), +// (0x3d2cefc5208422d8, 0x3fd194b3bdef6800), +// (0xbc81d4f1e8c2daff, 0x3fd1c93712abc800), +// (0xbc81d4f1e8c2daff, 0x3fd1c93712abc800), +// (0x3d140eb9b53054c3, 0x3fd1fe1e5af2c000), +// (0x3d140eb9b53054c3, 0x3fd1fe1e5af2c000), +// (0x3d29bbc8038401fc, 0x3fd2336b161b3000), +// (0x3d29bbc8038401fc, 0x3fd2336b161b3000), +// (0x3cf09ca54daae9f9, 0x3fd2691ecc29f000), +// (0x3cf09ca54daae9f9, 0x3fd2691ecc29f000), +// (0x3cf2b528446968a4, 0x3fd29f3b0e155800), +// (0x3cf2b528446968a4, 0x3fd29f3b0e155800), +// (0xbd14548507c3dd04, 0x3fd2d5c1760b8800), +// (0xbd14548507c3dd04, 0x3fd2d5c1760b8800), +// (0xbd1db59b99249f3a, 0x3fd30cb3a7bb3800), +// (0x0000000000000000, 0x0000000000000000), +// ]; + +// Generated by Sollya with: +// for i from 0 to 127 do { +// r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^-7) ); +// b = nearestint(log(r)*2^43) * 2^-43; +// c = round(log(r) - b, D, RN); +// print("{", -c, ",", -b, "},"); +// }; +// We replace LOG_R[0] with log10(1.0) == 0.0 +pub(crate) static LOG_R_DD: [(u64, u64); 128] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbd10c76b999d2be8, 0x3f80101575890000), + (0xbd23dc5b06e2f7d2, 0x3f90205658938000), + (0xbd2aa0ba325a0c34, 0x3f98492528c90000), + (0x3d0111c05cf1d753, 0x3fa0415d89e74000), + (0xbd2c167375bdfd28, 0x3fa466aed42e0000), + (0xbd197995d05a267d, 0x3fa894aa149fc000), + (0xbd1a68f247d82807, 0x3faccb73cdddc000), + (0xbd17e5dd7009902c, 0x3fb08598b59e4000), + (0xbd25325d560d9e9b, 0x3fb1973bd1466000), + (0x3d2cc85ea5db4ed7, 0x3fb3bdf5a7d1e000), + (0xbd2c69063c5d1d1e, 0x3fb5e95a4d97a000), + (0x3cec1e8da99ded32, 0x3fb700d30aeac000), + (0x3d23115c3abd47da, 0x3fb9335e5d594000), + (0xbd1390802bf768e5, 0x3fbb6ac88dad6000), + (0x3d2646d1c65aacd3, 0x3fbc885801bc4000), + (0xbd2dc068afe645e0, 0x3fbec739830a2000), + (0xbd2534d64fa10afd, 0x3fbfe89139dbe000), + (0x3d21ef78ce2d07f2, 0x3fc1178e8227e000), + (0x3d2ca78e44389934, 0x3fc1aa2b7e23f000), + (0x3d039d6ccb81b4a1, 0x3fc2d1610c868000), + (0x3cc62fa8234b7289, 0x3fc365fcb0159000), + (0x3d25837954fdb678, 0x3fc4913d8333b000), + (0x3d2633e8e5697dc7, 0x3fc527e5e4a1b000), + (0x3d19cf8b2c3c2e78, 0x3fc6574ebe8c1000), + (0xbd25118de59c21e1, 0x3fc6f0128b757000), + (0x3d1e0ddb9a631e83, 0x3fc823c16551a000), + (0xbd073d54aae92cd1, 0x3fc8beafeb390000), + (0x3d07f22858a0ff6f, 0x3fc95a5adcf70000), + (0xbd28724350562169, 0x3fca93ed3c8ae000), + (0xbd0c358d4eace1aa, 0x3fcb31d8575bd000), + (0xbd2d4bc4595412b6, 0x3fcbd087383be000), + (0xbd084a7e75b6f6e4, 0x3fcd1037f2656000), + (0xbd2aff2af715b035, 0x3fcdb13db0d49000), + (0x3cc212276041f430, 0x3fce530effe71000), + (0xbcca211565bb8e11, 0x3fcef5ade4dd0000), + (0x3d1bcbecca0cdf30, 0x3fcf991c6cb3b000), + (0x3cf89cdb16ed4e91, 0x3fd07138604d5800), + (0x3d27188b163ceae9, 0x3fd0c42d67616000), + (0xbd2c210e63a5f01c, 0x3fd1178e8227e800), + (0x3d2b9acdf7a51681, 0x3fd16b5ccbacf800), + (0x3d2ca6ed5147bdb7, 0x3fd1bf99635a6800), + (0x3d2c93c1df5bb3b6, 0x3fd269621134d800), + (0x3d2a9cfa4a5004f4, 0x3fd2bef07cdc9000), + (0xbd28e27ad3213cb8, 0x3fd314f1e1d36000), + (0x3d116ecdb0f177c8, 0x3fd36b6776be1000), + (0x3d183b54b606bd5c, 0x3fd3c25277333000), + (0x3d08e436ec90e09d, 0x3fd419b423d5e800), + (0xbd2f27ce0967d675, 0x3fd4718dc271c800), + (0xbd2e20891b0ad8a4, 0x3fd4c9e09e173000), + (0x3d2ebe708164c759, 0x3fd522ae0738a000), + (0x3d1fadedee5d40ef, 0x3fd57bf753c8d000), + (0xbd0a0b2a08a465dc, 0x3fd5d5bddf596000), + (0xbd2db623e731ae00, 0x3fd630030b3ab000), + (0x3d20a0d32756eba0, 0x3fd68ac83e9c6800), + (0x3d1721657c222d87, 0x3fd6e60ee6af1800), + (0x3d2d8b0949dc60b3, 0x3fd741d876c67800), + (0x3d29ec7d2efd1778, 0x3fd79e26687cf800), + (0xbd272090c812566a, 0x3fd7fafa3bd81800), + (0x3d2fd56f3333778a, 0x3fd85855776dc800), + (0xbd205ae1e5e70470, 0x3fd8b639a88b3000), + (0xbd1766b52ee6307d, 0x3fd914a8635bf800), + (0xbd152313a502d9f0, 0x3fd973a343135800), + (0xbd26279e10d0c0b0, 0x3fd9d32bea15f000), + (0x3d23c6457f9d79f5, 0x3fda33440224f800), + (0x3d23c6457f9d79f5, 0x3fda33440224f800), + (0x3d1e36f2bea77a5d, 0x3fda93ed3c8ad800), + (0xbd217cc552774458, 0x3fdaf5295248d000), + (0x3d1095252d841995, 0x3fdb56fa04462800), + (0x3d27d85bf40a666d, 0x3fdbb9611b80e000), + (0x3d2cec807fe8e180, 0x3fdc1c60693fa000), + (0x3d2cec807fe8e180, 0x3fdc1c60693fa000), + (0xbd29b6ddc15249ae, 0x3fdc7ff9c7455800), + (0xbd0797c33ec7a6b0, 0x3fdce42f18064800), + (0x3d235bafe9a767a8, 0x3fdd490246def800), + (0xbd1ea42d60dc616a, 0x3fddae75484c9800), + (0xbd1326b207322938, 0x3fde148a1a272800), + (0xbd1326b207322938, 0x3fde148a1a272800), + (0xbd2465505372bd08, 0x3fde7b42c3ddb000), + (0x3d2f27f45a470251, 0x3fdee2a156b41000), + (0x3d12cde56f014a8b, 0x3fdf4aa7ee031800), + (0x3d12cde56f014a8b, 0x3fdf4aa7ee031800), + (0x3d0085fa3c164935, 0x3fdfb358af7a4800), + (0xbd053ba3b1727b1c, 0x3fe00e5ae5b20800), + (0xbd04c45fe79539e0, 0x3fe04360be760400), + (0xbd04c45fe79539e0, 0x3fe04360be760400), + (0x3d26812241edf5fd, 0x3fe078bf0533c400), + (0x3d1f486b887e7e27, 0x3fe0ae76e2d05400), + (0x3d1f486b887e7e27, 0x3fe0ae76e2d05400), + (0x3d1c299807801742, 0x3fe0e4898611cc00), + (0xbd258647bb9ddcb2, 0x3fe11af823c75c00), + (0xbd258647bb9ddcb2, 0x3fe11af823c75c00), + (0xbd2edd97a293ae49, 0x3fe151c3f6f29800), + (0x3d14cc4ef8ab4650, 0x3fe188ee40f23c00), + (0x3d14cc4ef8ab4650, 0x3fe188ee40f23c00), + (0x3cccacdeed70e667, 0x3fe1c07849ae6000), + (0xbd2a7242c9fe81d3, 0x3fe1f8635fc61800), + (0xbd2a7242c9fe81d3, 0x3fe1f8635fc61800), + (0x3d12fc066e48667b, 0x3fe230b0d8bebc00), + (0xbd0b61f105226250, 0x3fe269621134dc00), + (0xbd0b61f105226250, 0x3fe269621134dc00), + (0x3d206d2be797882d, 0x3fe2a2786d0ec000), + (0xbd17a6e507b9dc11, 0x3fe2dbf557b0e000), + (0xbd17a6e507b9dc11, 0x3fe2dbf557b0e000), + (0xbd274e93c5a0ed9c, 0x3fe315da44340800), + (0xbd274e93c5a0ed9c, 0x3fe315da44340800), + (0x3d10b83f9527e6ac, 0x3fe35028ad9d8c00), + (0xbd218b7abb5569a4, 0x3fe38ae217197800), + (0xbd218b7abb5569a4, 0x3fe38ae217197800), + (0xbd02b7367cfe13c2, 0x3fe3c6080c36c000), + (0xbd02b7367cfe13c2, 0x3fe3c6080c36c000), + (0xbd26ce7930f0c74c, 0x3fe4019c2125cc00), + (0xbcfd984f481051f7, 0x3fe43d9ff2f92400), + (0xbcfd984f481051f7, 0x3fe43d9ff2f92400), + (0xbd22cb6af94d60aa, 0x3fe47a1527e8a400), + (0xbd22cb6af94d60aa, 0x3fe47a1527e8a400), + (0x3cef7115ed4c541c, 0x3fe4b6fd6f970c00), + (0x3cef7115ed4c541c, 0x3fe4b6fd6f970c00), + (0xbd2e6c516d93b8fb, 0x3fe4f45a835a5000), + (0xbd2e6c516d93b8fb, 0x3fe4f45a835a5000), + (0x3d05ccc45d257531, 0x3fe5322e26867800), + (0x3d05ccc45d257531, 0x3fe5322e26867800), + (0x3d09980bff3303dd, 0x3fe5707a26bb8c00), + (0x3d09980bff3303dd, 0x3fe5707a26bb8c00), + (0x3d2dfa63ac10c9fb, 0x3fe5af405c364800), + (0x3d2dfa63ac10c9fb, 0x3fe5af405c364800), + (0x3d2202380cda46be, 0x3fe5ee82aa241800), + (0x0000000000000000, 0x0000000000000000), +]; + +/// Logarithm of base 10 +/// +/// Max found ULP 0.5 +pub fn f_log10(x: f64) -> f64 { + let mut x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i64 = -(E_BIAS as i64); + + const MAX_NORMAL: u64 = f64::to_bits(f64::MAX); + + if x_u == 1f64.to_bits() { + // log2(1.0) = +0.0 + return 0.0; + } + if x_u < min_normal_f64().to_bits() || x_u > MAX_NORMAL { + if x == 0.0 { + return f64::NEG_INFINITY; + } + if x < 0. || x.is_nan() { + return f64::NAN; + } + if x.is_infinite() || x.is_nan() { + return x + x; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4330000000000000)).to_bits(); + x_e -= 52; + } + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i64; + let index = shifted & 0x7F; + let r = f64::from_bits(crate::logs::log2::LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i64); + let e_x = x_e as f64; + + const LOG_2_HI: f64 = f64::from_bits(0x3fe62e42fefa3800); + const LOG_2_LO: f64 = f64::from_bits(0x3d2ef35793c76730); + + let log_r_dd = LOG_R_DD[index as usize]; + + // hi is exact + let hi = f_fmla(e_x, LOG_2_HI, f64::from_bits(log_r_dd.1)); + // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err + // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo)) + let lo = f_fmla(e_x, LOG_2_LO, f64::from_bits(log_r_dd.0)); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log2::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + let u_sq = u * u; + // Degree-7 minimax polynomial + let p0 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[1]), + f64::from_bits(LOG_COEFFS[0]), + ); + let p1 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[3]), + f64::from_bits(LOG_COEFFS[2]), + ); + let p2 = f_fmla( + u, + f64::from_bits(LOG_COEFFS[5]), + f64::from_bits(LOG_COEFFS[4]), + ); + let p = f_polyeval4(u_sq, lo, p0, p1, p2); + + // Exact sum: + // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u + let mut r1 = DoubleDouble::from_exact_add(hi, u); + r1.lo += p; + + // Quick double-double multiplication: + // r2.hi + r2.lo ~ r1 * log10(e), + // with error bounded by: + // 4*ulp( ulp(r2.hi) ) + const LOG10_E: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c695355baaafad3), + f64::from_bits(0x3fdbcb7b1526e50e), + ); + let r2 = DoubleDouble::quick_mult(r1, LOG10_E); + + const HI_ERR: f64 = f64::from_bits(0x3aa0000000000000); + + // Extra errors from P is from using x^2 to reduce evaluation latency. + const P_ERR: f64 = f64::from_bits(0x3cc0000000000000); + + // Technicallly error of r1.lo is bounded by: + // |hi|*ulp(log(2)_lo) + C*ulp(u^2) + // To simplify the error computation a bit, we replace |hi|*ulp(log(2)_lo) + // with the upper bound: 2^11 * ulp(log(2)_lo) = 2^-85. + // Total error is bounded by ~ C * ulp(u^2) + 2^-85. + let err = f_fmla(u_sq, P_ERR, HI_ERR); + + // Lower bound from the result + let left = r2.hi + (r2.lo - err); + // Upper bound from the result + let right = r2.hi + (r2.lo + err); + + // Ziv's test if fast pass is accurate enough. + if left == right { + return left; + } + + log10_dd_accurate(x) +} + +#[cold] +#[inline(never)] +fn log10_dd_accurate(x: f64) -> f64 { + let r = log10_dd(x); + let err = f_fmla( + r.hi, + f64::from_bits(0x3b50000000000000), // 2^-74 + f64::from_bits(0x3990000000000000), // 2^-102 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r.to_f64(); + } + log10_dd_accurate_slow(x) +} + +#[cold] +#[inline(never)] +fn log10_dd_accurate_slow(x: f64) -> f64 { + log10_td(x).to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10d() { + assert_eq!(f_log10(0.35), -0.4559319556497244); + assert_eq!(f_log10(0.9), -0.045757490560675115); + assert_eq!(f_log10(10.), 1.); + assert_eq!(f_log10(0.), f64::NEG_INFINITY); + assert!(f_log10(-1.).is_nan()); + assert!(f_log10(f64::NAN).is_nan()); + assert!(f_log10(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_log10(f64::INFINITY), f64::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10dd.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10dd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::log10dd_coeffs::LOG10_NEG_DD; +use crate::pow_tables::POW_INVERSE; + +#[inline(always)] +fn log10_poly(z: f64) -> DoubleDouble { + /* + See ./notes/dd_log10.sollya + */ + const P: [(u64, u64); 10] = [ + (0x3c695355baabd6d2, 0x3fdbcb7b1526e50e), + (0xbc595355bababc0c, 0xbfcbcb7b1526e50e), + (0xbc59c8c251be5fee, 0x3fc287a7636f435f), + (0xbc49515e0a562cbe, 0xbfbbcb7b1526e50e), + (0xbc5603802582ebad, 0x3fb63c62775250e2), + (0x3c37a0e7de39c80c, 0xbfb287a7636f4371), + (0x3c2c4afd722dc9ec, 0x3fafc3fa611f0291), + (0xbc4a52f6541b67ee, 0xbfabcb7b14e178e5), + (0x3c3ef541147ede8e, 0x3fa8b514ee02cfad), + (0xbc28b9ea54e8f3b4, 0xbfa63c9d960501f1), + ]; + let mut t = DoubleDouble::quick_mul_f64_add( + DoubleDouble::from_bit_pair(P[9]), + z, + DoubleDouble::from_bit_pair(P[8]), + ); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[7])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[6])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[5])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[4])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[3])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[2])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[1])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[0])); + DoubleDouble::quick_mult_f64(t, z) +} + +#[inline] +pub(crate) fn log10_dd(x: f64) -> DoubleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log10(x) = log10(t) + E · log10(e) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log10_r = DoubleDouble::from_bit_pair(LOG10_NEG_DD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG10_2_DD: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc49dc1da994fd21, 0x3fd34413509f79ff)); + + let v = DoubleDouble::mul_f64_add(LOG10_2_DD, be as f64, log10_r); + + let p = log10_poly(z); + DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10_dd() { + assert_eq!(log10_dd(10.).to_f64(), 1.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10dd_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10dd_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10dd_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,230 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by SageMath: + +```python +values = POW_INVERSE +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_double_double("", -RealField(180)(r).log10()) + +``` +**/ +pub(crate) static LOG10_NEG_DD: [(u64, u64); 182] = [ + (0xbc0b420b9b202edd, 0xbfc31b3055c47118), + (0xbc662219537667a2, 0xbfc2cc20b1734279), + (0xbc4386d677ad2ead, 0xbfc27c9ffae729c1), + (0x3c6fb908b0ca4062, 0xbfc22cacece26ead), + (0xbc61b4170b1c73f0, 0xbfc1dc463ca41df8), + (0x3c5d6679f737585c, 0xbfc18b6a99c7f679), + (0x3c6c6397435bc5b6, 0xbfc162d082ac9d10), + (0x3c4b8c4f1b08949b, 0xbfc11142f0811357), + (0xbc5e17a06836db63, 0xbfc0bf3d0937c41c), + (0xbc65163143f60061, 0xbfc06cbd67a6c3b6), + (0xbc6c5e9d9a0e1fd9, 0xbfc019c2a064b486), + (0x3c5ec7f2dac60a5c, 0xbfbf8c9683468191), + (0x3c54a69937a2d705, 0xbfbf38c0c8325d86), + (0x3c53cbb5a6ee659b, 0xbfbe9056bcb315e8), + (0x3c51bf355bb72ca1, 0xbfbde6ec0f392b05), + (0x3c5ce84c9eaee37a, 0xbfbd91d5866aa99c), + (0x3c26f0603909a181, 0xbfbce6e41e463da5), + (0x3c58b9190212e5ba, 0xbfbc3aea4a5c6eff), + (0x3c2446d00b829ad4, 0xbfbb8de4d3ab3d98), + (0x3c5aa2aeaa7bc18d, 0xbfbb36fcb5f8be8a), + (0x3c5dd366189ac022, 0xbfba885fa2d6151e), + (0x3c4ebf33e9410429, 0xbfba30a9d609efea), + (0xbc5c81cca3dd9b7b, 0xbfb9806d9414a209), + (0x3c5935d381a0844f, 0xbfb8cf183886480d), + (0x3c3666804e99aabc, 0xbfb8760307d355ab), + (0xbc21064a1f6dc0c5, 0xbfb7c30164a60836), + (0x3c5ac4c370ae3c1d, 0xbfb769140a2526fd), + (0xbc5643835531d8ee, 0xbfb6b45df6f3e2c9), + (0x3c59d9c8eaf88500, 0xbfb659944f8ba02d), + (0xbc48cb0dc78c3961, 0xbfb5a32167b32f02), + (0x3c5e1bcfb0476f5d, 0xbfb5477731973e85), + (0xbc5782120ed9fd02, 0xbfb48f3ed1df48fb), + (0x3c51960cbdfcb2d3, 0xbfb432afab5dd3ff), + (0x3c4a83d8a6eb8e2e, 0xbfb3d5d335c53179), + (0xbbfb420b9b202edd, 0xbfb31b3055c47118), + (0xbc59f5fa977fa091, 0xbfb2bd68e4621371), + (0x3c5c2f24fb8a820d, 0xbfb200eb639a3173), + (0x3c4f990c2c07d3b5, 0xbfb1a23445501816), + (0x3c4114d5dc0b3275, 0xbfb1432c31917d08), + (0x3c3ccc49eb0a89d8, 0xbfb08426fcdb1ee7), + (0x3c35943d4373d44a, 0xbfb02428c1f08016), + (0x3c31436f936096a0, 0xbfaf87aebb43ce06), + (0x3c4d4d643174a412, 0xbfae0471aa1868f5), + (0x3c47f9dc537bfbfb, 0xbfad41d5164facb4), + (0x3c4073b6859dc799, 0xbfac7e8d993509f9), + (0x3c46487d64961833, 0xbfaaf5f92b00e610), + (0x3c3ebf33e9410429, 0xbfaa30a9d609efea), + (0x3c41c8c309cdac54, 0xbfa96aaacfefcf3c), + (0x3c4b144b06126f68, 0xbfa8a3fadeb847f4), + (0x3c38f0f77fcff1d9, 0xbfa71483427d2a99), + (0xbc2eff9decc696f6, 0xbfa64bb912d65c07), + (0xbc4efd454f7ea69a, 0xbfa58238eeb353da), + (0xbc443795bbf70657, 0xbfa4b8018b21ed4f), + (0x3c492b9251ee5832, 0xbfa32167c82bdcda), + (0x3c4ff894a084ae68, 0xbfa25502c0fc314c), + (0xbc49adc1c7f97f4a, 0xbfa187e12aad8077), + (0xbc35f1d45244f437, 0xbfa0ba01a8170000), + (0x3c3e7ffa709828ef, 0xbf9fd6c5b0851c4c), + (0xbc0af3eb3b443356, 0xbf9e3806acbd058f), + (0x3c36487d64961833, 0xbf9af5f92b00e610), + (0x3c1f21279ca1bd16, 0xbf9952a4f22c5ae9), + (0xbc1b980714c596a3, 0xbf97adc3df3b1ff8), + (0xbc36ea248137e395, 0xbf960753003a94ef), + (0xbc3dda7897a55eb5, 0xbf945f4f5acb8be0), + (0xbc15bcd6d3458191, 0xbf92b5b5ec0209d3), + (0x3c37b9fd5428084f, 0xbf910a83a8446c78), + (0xbc1b57b9aec33450, 0xbf8ebb6af653e2ee), + (0xbbff2e9fe367a511, 0xbf8b5e908eb13790), + (0xbc28d4a223a5f7c9, 0xbf87fe71ccc4e6b0), + (0x3c18f207a6d0d0b1, 0xbf849b0851443684), + (0x3c29383502395c53, 0xbf81344daa2d7553), + (0x3c03b252df477a75, 0xbf7b9476a4fcd10f), + (0xbbefb495d6440f14, 0xbf74b99563d2a1bd), + (0xbc09706ea523f0a5, 0xbf6bafd47221ed26), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3c0dcbdc594292c0, 0x3f64e84e793a474a), + (0x3c11e6c1240ced74, 0x3f7175085ab85ff0), + (0x3c0e1d6052707e0e, 0x3f787cff9d9147a5), + (0xbbee4f45b8df7d67, 0x3f7f8c1b6b0c8d4e), + (0x3c22495d8b8e25b7, 0x3f8351352a8e733f), + (0x3c1bc0294772c57f, 0x3f86dffd8d3bbf70), + (0xbc2b41d4e4ac05d4, 0x3f8a726e53a6056e), + (0xbc28d01e8ac8a78b, 0x3f8c3d0837784c41), + (0x3c27d5b73769b64c, 0x3f8fd503c3904f1d), + (0xbbd646ebcccb6894, 0x3f91b85d6044e9ae), + (0x3c37b38a223627b5, 0x3f93881a7b818f9e), + (0x3c0521ad5fa98432, 0x3f9559bd2406c3ba), + (0xbc29fc37c4e4e576, 0x3f972d4956ca2067), + (0x3c3c830373882139, 0x3f9817c846828bbd), + (0x3c0be24ddca8b835, 0x3f99ee3a5e9f57e8), + (0x3c0999ccc6d592f0, 0x3f9bc6a03117eb97), + (0xbc34a65cdeb626ca, 0x3f9da0fde8038de9), + (0xbc29dc1111e3b44c, 0x3f9f7d57badb4ee8), + (0x3c47db4db93811b8, 0x3fa0362241e638ec), + (0xbc3f6975f23b8a99, 0x3fa125d0432ea20e), + (0x3c463610c66f42b2, 0x3fa21681b5c8c213), + (0x3c3c756ef644213d, 0x3fa28f3c69912a74), + (0xbc11b16a272d4ddf, 0x3fa381772a00e604), + (0xbc2197beb0be1c78, 0x3fa474baeb77e904), + (0xbc0978c592e6c139, 0x3fa4eec0e2458f30), + (0x3c2bb9cd2fb75402, 0x3fa5e3966b7e9295), + (0x3c377b340fa390ec, 0x3fa6d97ab3ba5e10), + (0x3c3ea90ccf791593, 0x3fa754d31b1b179c), + (0x3c454596cc7150a8, 0x3fa84c51ebee8d15), + (0xbc476df54932f73e, 0x3fa944e56a0d3450), + (0xbc286148dd4cfbf5, 0x3fa9c197abf00dd7), + (0xbc397d2cb982dac2, 0x3faabbcebd84fca0), + (0x3c36591c969ff97b, 0x3fab39542ba23d73), + (0xbc40859ccb55560e, 0x3fac3534628016dd), + (0x3c4a5aca518d962e, 0x3facb38fccd8bfdb), + (0x3c396e1e0dda0b3d, 0x3fadb11ed766abf4), + (0x3c332de632195123, 0x3fae30531c76c34a), + (0xbc23a73e99099cbd, 0x3faf2f96c6754aee), + (0x3c262f731cfeb27b, 0x3fafafa6d397efdb), + (0xbc4e0c43230184dc, 0x3fb0585283764178), + (0x3c5466dc013d46a9, 0x3fb098c9ec61b3ff), + (0xbc5cae3496ce9852, 0x3fb11a294f2569f6), + (0xbc56a232c37f20c5, 0x3fb15b11a094a1aa), + (0xbc4f587e7a233c80, 0x3fb1dd5460c8b16f), + (0x3c5a0dec3a5a500c, 0x3fb21eaf28f57941), + (0x3c585a155bb65408, 0x3fb2a1d86b49f1e2), + (0xbc5aef53f2ecddb9, 0x3fb2e3a740b7800f), + (0xbc5de49ddb15fb04, 0x3fb367ba3aaa1883), + (0xbc5514fb6a33e70f, 0x3fb3a9febc60540a), + (0x3c5c4c753d98645a, 0x3fb3ec6ad5407868), + (0x3c2ce8e795b6ed98, 0x3fb471ba8a7de2b7), + (0xbc54f0487863efe6, 0x3fb4b49e86b11e5f), + (0x3c4bc478d6071be0, 0x3fb53adfb462ce16), + (0xbc187decde1893f1, 0x3fb57e3d47c3af7b), + (0x3c481f647ea24688, 0x3fb5c1c3c5557799), + (0x3c5ad1738d96af06, 0x3fb6494c46ac6e4d), + (0x3c54c74f6a7880e3, 0x3fb68d4eaf26d7ee), + (0xbc52a2d69cfac78f, 0x3fb6d17acb3e5f5e), + (0x3c4e4ba167ee73dd, 0x3fb75a50ebb1624a), + (0x3c57e469fe31a42f, 0x3fb79efb57b0f803), + (0xbc4d12e032a3b7af, 0x3fb7e3d04697b704), + (0xbc53f06091db6450, 0x3fb828cfed29a215), + (0x3c4da13d5c8cb232, 0x3fb8b350364c6257), + (0x3be2034e6320e8c0, 0x3fb8f8d144557bdf), + (0xbc5d0d01941798b6, 0x3fb93e7de0fc3e80), + (0xbc562d3ed69292b0, 0x3fb9ca5aa1729f45), + (0x3c5ba75ea17687d3, 0x3fba108b33edb005), + (0xbc3113a1fc340179, 0x3fba56e8325f5c87), + (0xbc4f648977febad9, 0x3fba9d71d5258484), + (0x3c45689de26b43ff, 0x3fbb2b0beb419ad0), + (0xbc5a8267d18975f3, 0x3fbb721cd17157e3), + (0xbc5cb0a198331caf, 0x3fbbb95b41ab5ce6), + (0xbc5b1e2e67b6f4bf, 0x3fbc00c7767225cb), + (0xbc5b6b51fca7a9a5, 0x3fbc4861aab93a23), + (0xbc58f377e27bbe25, 0x3fbcd820ffd278f3), + (0xbc5667bf89866cca, 0x3fbd204698cb42bd), + (0xbc1100072d011b81, 0x3fbd689b2193f133), + (0x3c496e1e0dda0b3d, 0x3fbdb11ed766abf4), + (0x3c55c6bc5d06e932, 0x3fbdf9d1f7f5b674), + (0xbc5e018e5642e2ef, 0x3fbe42b4c16caaf3), + (0xbc20a89525f3e005, 0x3fbed50a4a26eafc), + (0x3c50955b9d99c1b8, 0x3fbf1e7d882b689a), + (0xbc5c42f76e4345b0, 0x3fbf68216c9cc727), + (0xbc46749ac407ee87, 0x3fbfb1f6381856f4), + (0x3c5d60df12c2e13d, 0x3fbffbfc2bbc7803), + (0x3c4ef8dd8b73f78d, 0x3fc02319c494f951), + (0x3c5f318aa3021710, 0x3fc0484e4942aa43), + (0xbc6a12a1c0cb3d7f, 0x3fc093025a19976c), + (0xbc609801174f88fd, 0x3fc0b88229b71227), + (0x3c65b619c844d28b, 0x3fc0de1b56356b04), + (0x3c4dbdf176a1440a, 0x3fc103ce01fae223), + (0xbc6ce6c847a6598d, 0x3fc1299a4fb3e306), + (0xbc61f5da9e930834, 0x3fc14f806253c3ed), + (0x3c5ac676f20a87ab, 0x3fc175805d1587c1), + (0xbc6e785b3b894bd7, 0x3fc19b9a637ca295), + (0xbc5db924be9633b4, 0x3fc1c1ce9955c0c6), + (0x3c6db81c3374e59e, 0x3fc1e81d22b790d4), + (0xbc67299601268298, 0x3fc20e8624038fed), + (0x3c6ea54c137b0aea, 0x3fc23509c1e6d937), + (0x3c50349d03e16325, 0x3fc25ba8215af7fc), + (0x3c6557d4cdeffe3f, 0x3fc2826167a6bc9c), + (0xbc1f613823fd2a19, 0x3fc2a935ba5f1479), + (0xbc63dda694b5fe22, 0x3fc2d0253f67e4cb), + (0xbc4c7972ce5f8b57, 0x3fc2f7301cf4e87b), + (0x3c54b79d1957630a, 0x3fc31e56798a910a), + (0xbc654fd6eb7d970e, 0x3fc345987bfeea91), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,281 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::logs::logf::{GenLogfBackend, LogfBackend}; + +static LOG10_R: [u64; 128] = [ + 0x0000000000000000, + 0x3f6be76bd77b4fc3, + 0x3f7c03a80ae5e054, + 0x3f851824c7587eb0, + 0x3f8c3d0837784c41, + 0x3f91b85d6044e9ae, + 0x3f9559bd2406c3ba, + 0x3f9902c31d62a843, + 0x3f9cb38fccd8bfdb, + 0x3f9e8eeb09f2f6cb, + 0x3fa125d0432ea20e, + 0x3fa30838cdc2fbfd, + 0x3fa3faf7c663060e, + 0x3fa5e3966b7e9295, + 0x3fa7d070145f4fd7, + 0x3fa8c878eeb05074, + 0x3faabbcebd84fca0, + 0x3fabb7209d1e24e5, + 0x3fadb11ed766abf4, + 0x3faeafd05035bd3b, + 0x3fb0585283764178, + 0x3fb0d966cc6500fa, + 0x3fb1dd5460c8b16f, + 0x3fb2603072a25f82, + 0x3fb367ba3aaa1883, + 0x3fb3ec6ad5407868, + 0x3fb4f7aad9bbcbaf, + 0x3fb57e3d47c3af7b, + 0x3fb605735ee985f1, + 0x3fb715d0ce367afc, + 0x3fb79efb57b0f803, + 0x3fb828cfed29a215, + 0x3fb93e7de0fc3e80, + 0x3fb9ca5aa1729f45, + 0x3fba56e8325f5c87, + 0x3fbae4285509950b, + 0x3fbb721cd17157e3, + 0x3fbc902a19e65111, + 0x3fbd204698cb42bd, + 0x3fbdb11ed766abf4, + 0x3fbe42b4c16caaf3, + 0x3fbed50a4a26eafc, + 0x3fbffbfc2bbc7803, + 0x3fc0484e4942aa43, + 0x3fc093025a19976c, + 0x3fc0de1b56356b04, + 0x3fc1299a4fb3e306, + 0x3fc175805d1587c1, + 0x3fc1c1ce9955c0c6, + 0x3fc20e8624038fed, + 0x3fc25ba8215af7fc, + 0x3fc2a935ba5f1479, + 0x3fc2f7301cf4e87b, + 0x3fc345987bfeea91, + 0x3fc394700f7953fd, + 0x3fc3e3b8149739d4, + 0x3fc43371cde076c2, + 0x3fc4839e83506c87, + 0x3fc4d43f8275a483, + 0x3fc525561e9256ee, + 0x3fc576e3b0bde0a7, + 0x3fc5c8e998072fe2, + 0x3fc61b6939983048, + 0x3fc66e6400da3f77, + 0x3fc6c1db5f9bb336, + 0x3fc6c1db5f9bb336, + 0x3fc715d0ce367afc, + 0x3fc76a45cbb7e6ff, + 0x3fc7bf3bde099f30, + 0x3fc814b4921bd52b, + 0x3fc86ab17c10bc7f, + 0x3fc86ab17c10bc7f, + 0x3fc8c13437695532, + 0x3fc9183e673394fa, + 0x3fc96fd1b639fc09, + 0x3fc9c7efd734a2f9, + 0x3fca209a84fbcff8, + 0x3fca209a84fbcff8, + 0x3fca79d382bc21d9, + 0x3fcad39c9c2c6080, + 0x3fcb2df7a5c50299, + 0x3fcb2df7a5c50299, + 0x3fcb88e67cf97980, + 0x3fcbe46b087354bc, + 0x3fcc4087384f4f80, + 0x3fcc4087384f4f80, + 0x3fcc9d3d065c5b42, + 0x3fccfa8e765cbb72, + 0x3fccfa8e765cbb72, + 0x3fcd587d96494759, + 0x3fcdb70c7e96e7f3, + 0x3fcdb70c7e96e7f3, + 0x3fce163d527e68cf, + 0x3fce76124046b3f3, + 0x3fce76124046b3f3, + 0x3fced68d819191fc, + 0x3fcf37b15bab08d1, + 0x3fcf37b15bab08d1, + 0x3fcf99801fdb749d, + 0x3fcffbfc2bbc7803, + 0x3fcffbfc2bbc7803, + 0x3fd02f93f4c87101, + 0x3fd06182e84fd4ac, + 0x3fd06182e84fd4ac, + 0x3fd093cc32c90f84, + 0x3fd093cc32c90f84, + 0x3fd0c6711d6abd7a, + 0x3fd0f972f87ff3d6, + 0x3fd0f972f87ff3d6, + 0x3fd12cd31b9c99ff, + 0x3fd12cd31b9c99ff, + 0x3fd16092e5d3a9a6, + 0x3fd194b3bdef6b9e, + 0x3fd194b3bdef6b9e, + 0x3fd1c93712abc7ff, + 0x3fd1c93712abc7ff, + 0x3fd1fe1e5af2c141, + 0x3fd1fe1e5af2c141, + 0x3fd2336b161b3337, + 0x3fd2336b161b3337, + 0x3fd2691ecc29f042, + 0x3fd2691ecc29f042, + 0x3fd29f3b0e15584b, + 0x3fd29f3b0e15584b, + 0x3fd2d5c1760b86bb, + 0x3fd2d5c1760b86bb, + 0x3fd30cb3a7bb3625, + 0x3fd34413509f79ff, +]; + +#[inline(always)] +fn log10f_gen(x: f32, backend: B) -> f32 { + let mut x_u = x.to_bits(); + + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + + let mut m = -(E_BIAS as i32); + if x_u < f32::MIN_POSITIVE.to_bits() || x_u > f32::MAX.to_bits() { + if x == 0.0 { + return f32::NEG_INFINITY; + } + if x_u == 0x80000000u32 { + return f32::NEG_INFINITY; + } + if x.is_sign_negative() && !x.is_nan() { + return f32::NAN + x; + } + // x is +inf or nan + if x.is_nan() || x.is_infinite() { + return x + x; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4160000000000000) as f32).to_bits(); + m -= 23; + } + + m = m.wrapping_add(x_u.wrapping_shr(23) as i32); + let index = (x_u >> 16) & 0x7F; + x_u = set_exponent_f32(x_u, 0x7F); + + let u = f32::from_bits(x_u); + + let v = if B::HAS_FMA { + backend.fmaf( + u, + f32::from_bits(crate::logs::logf::LOG_REDUCTION_F32.0[index as usize]), + -1.0, + ) as f64 // Exact. + } else { + backend.fma( + u as f64, + f32::from_bits(crate::logs::logf::LOG_REDUCTION_F32.0[index as usize]) as f64, + -1.0, + ) // Exact + }; + // Degree-5 polynomial approximation of log10 generated by: + // > P = fpminimax(log10(1 + x)/x, 4, [|D...|], [-2^-8, 2^-7]); + const COEFFS: [u64; 5] = [ + 0x3fdbcb7b1526e2e5, + 0xbfcbcb7b1528d43d, + 0x3fc287a77eb4ca0d, + 0xbfbbcb8110a181b5, + 0x3fb60e7e3e747129, + ]; + let v2 = v * v; // Exact + let p2 = backend.fma(v, f64::from_bits(COEFFS[4]), f64::from_bits(COEFFS[3])); + let p1 = backend.fma(v, f64::from_bits(COEFFS[2]), f64::from_bits(COEFFS[1])); + let p0 = backend.fma( + v, + f64::from_bits(COEFFS[0]), + f64::from_bits(LOG10_R[index as usize]), + ); + const LOG_10_2: f64 = f64::from_bits(0x3fd34413509f79ff); + let r = backend.fma(m as f64, LOG_10_2, backend.polyeval3(v2, p0, p1, p2)); + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn log10f_fma_impl(x: f32) -> f32 { + use crate::logs::logf::FmaLogfBackend; + log10f_gen(x, FmaLogfBackend {}) +} + +/// Logarithm of base 10 +/// +/// Max found ULP 0.5 +pub fn f_log10f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + log10f_gen(x, GenLogfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + log10f_fma_impl + } else { + fn def_log10f(x: f32) -> f32 { + log10f_gen(x, GenLogfBackend {}) + } + def_log10f + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10f() { + assert_eq!(f_log10f(0.35), -0.45593196f32); + assert_eq!(f_log10f(0.9), -4.5757502e-2); + assert_eq!(f_log10f(10.), 1.); + assert_eq!(f_log10f(100.), 2.); + assert_eq!(f_log10f(0.), f32::NEG_INFINITY); + assert!(f_log10f(-1.).is_nan()); + assert!(f_log10f(f32::NAN).is_nan()); + assert!(f_log10f(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_log10f(f32::INFINITY), f32::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,269 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log2p1::{log_fast, log_p_1a, log2_dyadic}; +use crate::logs::log10p1_tables::{LOG10P1_EXACT_INT_S_TABLE, LOG10P1_EXACT_INT_TABLE}; + +const INV_LOG10_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c695355baaafad3), + f64::from_bits(0x3fdbcb7b1526e50e), +); + +/* deal with |x| < 2^-900, then log10p1(x) ~ x/log(10) */ +#[cold] +fn log10p1_accurate_tiny(x: f64) -> f64 { + /* first scale x to avoid truncation of l in the underflow region */ + let sx = x * f64::from_bits(0x4690000000000000); + let mut px = DoubleDouble::quick_f64_mult(sx, INV_LOG10_DD); + + let res = px.to_f64() * f64::from_bits(0x3950000000000000); // expected result + px.lo += dd_fmla(-res, f64::from_bits(0x4690000000000000), px.hi); + // the correction to apply to res is l*2^-106 + /* For RNDN, we have underflow for |x| <= 0x1.26bb1bbb55515p-1021, + and for rounding away, for |x| < 0x1.26bb1bbb55515p-1021. */ + + dyad_fmla(px.lo, f64::from_bits(0x3950000000000000), res) +} + +fn log10p1_accurate_small(x: f64) -> f64 { + /* the following is a degree-17 polynomial approximating log10p1(x) for + |x| <= 2^-5 with relative error < 2^-105.067*/ + + static P_ACC: [u64; 25] = [ + 0x3fdbcb7b1526e50e, + 0x3c695355baaafad4, + 0xbfcbcb7b1526e50e, + 0xbc595355baaae078, + 0x3fc287a7636f435f, + 0xbc59c871838f83ac, + 0xbfbbcb7b1526e50e, + 0xbc495355e23285f2, + 0x3fb63c62775250d8, + 0x3c4442abd5831422, + 0xbfb287a7636f435f, + 0x3c49d116f225c4e4, + 0x3fafc3fa615105c7, + 0x3c24e1d7b4790510, + 0xbfabcb7b1526e512, + 0x3c49f884199ab0ce, + 0x3fa8b4df2f3f0486, + 0xbfa63c6277522391, + 0x3fa436e526a79e5c, + 0xbfa287a764c5a762, + 0x3fa11ac1e784daec, + 0xbf9fc3eedc920817, + 0x3f9da5cac3522edb, + 0xbf9be5ca1f9a97cd, + 0x3f9a44b64ca06e9b, + ]; + + /* for degree 11 or more, ulp(c[d]*x^d) < 2^-105.7*|log10p1(x)| + where c[d] is the degree-d coefficient of Pacc, thus we can compute + with a double only, and even with degree 10 (this does not increase + the number of exceptional cases) */ + + let mut h = dd_fmla(f64::from_bits(P_ACC[24]), x, f64::from_bits(P_ACC[23])); // degree 16 + for i in (10..=15).rev() { + h = dd_fmla(h, x, f64::from_bits(P_ACC[(i + 7) as usize])); // degree i + } + + // degree 9 + let px = DoubleDouble::from_exact_mult(x, h); + let hl = DoubleDouble::from_exact_add(f64::from_bits(P_ACC[9 + 7]), px.hi); + h = hl.hi; + let mut l = px.lo + hl.lo; + + for i in (1..=8).rev() { + let mut p = DoubleDouble::quick_f64_mult(x, DoubleDouble::new(l, h)); + l = p.lo; + p = DoubleDouble::from_exact_add(f64::from_bits(P_ACC[(2 * i - 2) as usize]), p.hi); + h = p.hi; + l += p.lo + f64::from_bits(P_ACC[(2 * i - 1) as usize]); + } + let pz = DoubleDouble::quick_f64_mult(x, DoubleDouble::new(l, h)); + pz.to_f64() +} + +#[cold] +fn log10p1_accurate(x: f64) -> f64 { + let ax = x.abs(); + + if ax < f64::from_bits(0x3fa0000000000000) { + return if ax < f64::from_bits(0x07b0000000000000) { + log10p1_accurate_tiny(x) + } else { + log10p1_accurate_small(x) + }; + } + let dx = if x > 1.0 { + DoubleDouble::from_exact_add(x, 1.0) + } else { + DoubleDouble::from_exact_add(1.0, x) + }; + let x_d = DyadicFloat128::new_from_f64(dx.hi); + let mut y = log2_dyadic(x_d, dx.hi); + let mut c = DyadicFloat128::from_div_f64(dx.lo, dx.hi); + let mut bx = c * c; + /* multiply X by -1/2 */ + bx.exponent -= 1; + bx.sign = DyadicSign::Neg; + /* C <- C - C^2/2 */ + c = c + bx; + /* |C-log(1+xl/xh)| ~ 2e-64 */ + y = y + c; + + // Sage Math: + // from sage.all import * + // + // def format_hex2(value): + // l = hex(value)[2:] + // n = 4 + // x = [l[i:i + n] for i in range(0, len(l), n)] + // return "0x" + "_".join(x) + "_u128" + // (s, m, e) = (RealField(128)(1)/RealField(128)(10)).log().sign_mantissa_exponent(); + // print(format_hex2(m)); + const LOG10_INV: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xde5b_d8a9_3728_7195_355b_aaaf_ad33_dc32_u128, + }; + y = y * LOG10_INV; + y.fast_as_f64() +} + +#[inline] +fn log10p1_fast(x: f64, e: i32) -> (DoubleDouble, f64) { + if e < -5 + /* e <= -6 thus |x| < 2^-5 */ + { + if e <= -968 { + /* then |x| might be as small as 2^-968, thus h=x/log(10) might in the + binade [2^-970,2^-969), with ulp(h) = 2^-1022, and if |l| < ulp(h), + then l.ulp() might be smaller than 2^-1074. We defer that case to + the accurate path. */ + let ax = x.abs(); + let result = if ax < f64::from_bits(0x07b0000000000000) { + log10p1_accurate_tiny(x) + } else { + log10p1_accurate_small(x) + }; + return (DoubleDouble::new(0.0, result), 0.0); + } + let mut p = log_p_1a(x); + let p_lo = p.lo; + p = DoubleDouble::from_exact_add(x, p.hi); + p.lo += p_lo; + p = DoubleDouble::quick_mult(p, INV_LOG10_DD); + return (p, f64::from_bits(0x3c1d400000000000) * p.hi); /* 2^-61.13 < 0x1.d4p-62 */ + } + + /* (xh,xl) <- 1+x */ + let zx = DoubleDouble::from_full_exact_add(x, 1.0); + + let mut v_u = zx.hi.to_bits(); + let e = ((v_u >> 52) as i32).wrapping_sub(0x3ff); + v_u = (0x3ffu64 << 52) | (v_u & 0xfffffffffffff); + let mut p = log_fast(e, v_u); + + /* log(xh+xl) = log(xh) + log(1+xl/xh) */ + let c = if zx.hi <= f64::from_bits(0x7fd0000000000000) || zx.lo.abs() >= 4.0 { + zx.lo / zx.hi + } else { + 0. + }; // avoid spurious underflow + + /* Since |xl| < ulp(xh), we have |xl| < 2^-52 |xh|, + thus |c| < 2^-52, and since |log(1+x)-x| < x^2 for |x| < 0.5, + we have |log(1+c)-c)| < c^2 < 2^-104. */ + p.lo += c; + + /* now multiply h+l by 1/log(2) */ + p = DoubleDouble::quick_mult(p, INV_LOG10_DD); + (p, f64::from_bits(0x3bb0a00000000000)) /* 2^-67.92 < 0x1.0ap-68 */ +} + +/// Computes log10(x+1) +/// +/// Max ULP 0.5 +pub fn f_log10p1(x: f64) -> f64 { + let x_u = x.to_bits(); + let e = (((x_u >> 52) & 0x7ff) as i32).wrapping_sub(0x3ff); + if e == 0x400 || x == 0. || x <= -1.0 { + /* case NaN/Inf, +/-0 or x <= -1 */ + if e == 0x400 && x.to_bits() != 0xfffu64 << 52 { + /* NaN or + Inf*/ + return x + x; + } + if x <= -1.0 + /* we use the fact that NaN < -1 is false */ + { + /* log2p(x<-1) is NaN, log2p(-1) is -Inf and raises DivByZero */ + return if x < -1.0 { + f64::NAN + } else { + // x=-1 + f64::NEG_INFINITY + }; + } + return x + x; /* +/-0 */ + } + + /* check x=10^n-1 for 1 <= n <= 15, where log10p1(x) is exact, + and we shouldn't raise the inexact flag */ + if 3 <= e && e <= 49 && x == f64::from_bits(LOG10P1_EXACT_INT_TABLE[e as usize]) { + return LOG10P1_EXACT_INT_S_TABLE[e as usize] as f64; + } + + /* now x = m*2^e with 1 <= m < 2 (m = v.f) and -1074 <= e <= 1023 */ + let (p, err) = log10p1_fast(x, e); + let left = p.hi + (p.lo - err); + let right = p.hi + (p.lo + err); + if left == right { + return left; + } + + log10p1_accurate(x) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10p1() { + assert_eq!(f_log10p1(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013904929147106097), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006038833999843867 ); + assert!(f_log10p1(-2.0).is_nan()); + assert_eq!(f_log10p1(9.0), 1.0); + assert_eq!(f_log10p1(2.0), 0.47712125471966244); + assert_eq!(f_log10p1(-0.5), -0.3010299956639812); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* LOG10P1_EXACT_INT_TABLE[e] is zero if there is no value of the form 10^n-1 in the range +[2^e, 2^(e+1)), otherwise it is this (unique) value. */ +pub(crate) static LOG10P1_EXACT_INT_TABLE: [u64; 50] = [ + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x4022000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x4058c00000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x408f380000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x40c3878000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x40f869f000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x412e847e00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x416312cfe0000000, + 0x0000000000000000, + 0x0000000000000000, + 0x4197d783fc000000, + 0x0000000000000000, + 0x0000000000000000, + 0x41cdcd64ff800000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x4202a05f1ff80000, + 0x0000000000000000, + 0x0000000000000000, + 0x42374876e7ff0000, + 0x0000000000000000, + 0x0000000000000000, + 0x426d1a94a1ffe000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x42a2309ce53ffe00, + 0x0000000000000000, + 0x0000000000000000, + 0x42d6bcc41e8fffc0, + 0x0000000000000000, + 0x0000000000000000, + 0x430c6bf52633fff8, +]; + +// LOG10P1_EXACT_INT_S_TABLE[e] is the integer n such that LOG10P1_EXACT_INT_TABLE[e] = 10^n-1 when LOG10P1_EXACT_INT_TABLE[e] is not zero +pub(crate) static LOG10P1_EXACT_INT_S_TABLE: [u32; 50] = [ + 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, + 0, 10, 0, 0, 11, 0, 0, 12, 0, 0, 0, 13, 0, 0, 14, 0, 0, 15, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10p1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10p1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,332 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::logs::LOG_RANGE_REDUCTION; +use crate::polyeval::{f_estrin_polyeval7, f_polyeval6}; + +// Generated by SageMath: +// print("[") +// for i in range(128): +// R = RealField(200) +// r = R(2)**(-8) * ( R(2)**8 * (R(1) - R(2)**(-8)) / (R(1) + R(i)*R(2)**-7) ).ceil() +// +// if i == 0 or i == 127: +// print(double_to_hex(0), ",") +// else: +// print(double_to_hex(-r.log10()), ",") +// print("];") +static LOG10_D: [u64; 128] = [ + 0x0000000000000000, + 0x3f6be76bd77b4fc3, + 0x3f7c03a80ae5e054, + 0x3f851824c7587eb0, + 0x3f8c3d0837784c41, + 0x3f91b85d6044e9ae, + 0x3f9559bd2406c3ba, + 0x3f9902c31d62a843, + 0x3f9cb38fccd8bfdb, + 0x3f9e8eeb09f2f6cb, + 0x3fa125d0432ea20e, + 0x3fa30838cdc2fbfd, + 0x3fa3faf7c663060e, + 0x3fa5e3966b7e9295, + 0x3fa7d070145f4fd7, + 0x3fa8c878eeb05074, + 0x3faabbcebd84fca0, + 0x3fabb7209d1e24e5, + 0x3fadb11ed766abf4, + 0x3faeafd05035bd3b, + 0x3fb0585283764178, + 0x3fb0d966cc6500fa, + 0x3fb1dd5460c8b16f, + 0x3fb2603072a25f82, + 0x3fb367ba3aaa1883, + 0x3fb3ec6ad5407868, + 0x3fb4f7aad9bbcbaf, + 0x3fb57e3d47c3af7b, + 0x3fb605735ee985f1, + 0x3fb715d0ce367afc, + 0x3fb79efb57b0f803, + 0x3fb828cfed29a215, + 0x3fb93e7de0fc3e80, + 0x3fb9ca5aa1729f45, + 0x3fba56e8325f5c87, + 0x3fbae4285509950b, + 0x3fbb721cd17157e3, + 0x3fbc902a19e65111, + 0x3fbd204698cb42bd, + 0x3fbdb11ed766abf4, + 0x3fbe42b4c16caaf3, + 0x3fbed50a4a26eafc, + 0x3fbffbfc2bbc7803, + 0x3fc0484e4942aa43, + 0x3fc093025a19976c, + 0x3fc0de1b56356b04, + 0x3fc1299a4fb3e306, + 0x3fc175805d1587c1, + 0x3fc1c1ce9955c0c6, + 0x3fc20e8624038fed, + 0x3fc25ba8215af7fc, + 0x3fc2a935ba5f1479, + 0x3fc2f7301cf4e87b, + 0x3fc345987bfeea91, + 0x3fc394700f7953fd, + 0x3fc3e3b8149739d4, + 0x3fc43371cde076c2, + 0x3fc4839e83506c87, + 0x3fc4d43f8275a483, + 0x3fc525561e9256ee, + 0x3fc576e3b0bde0a7, + 0x3fc5c8e998072fe2, + 0x3fc61b6939983048, + 0x3fc66e6400da3f77, + 0x3fc6c1db5f9bb336, + 0x3fc6c1db5f9bb336, + 0x3fc715d0ce367afc, + 0x3fc76a45cbb7e6ff, + 0x3fc7bf3bde099f30, + 0x3fc814b4921bd52b, + 0x3fc86ab17c10bc7f, + 0x3fc86ab17c10bc7f, + 0x3fc8c13437695532, + 0x3fc9183e673394fa, + 0x3fc96fd1b639fc09, + 0x3fc9c7efd734a2f9, + 0x3fca209a84fbcff8, + 0x3fca209a84fbcff8, + 0x3fca79d382bc21d9, + 0x3fcad39c9c2c6080, + 0x3fcb2df7a5c50299, + 0x3fcb2df7a5c50299, + 0x3fcb88e67cf97980, + 0x3fcbe46b087354bc, + 0x3fcc4087384f4f80, + 0x3fcc4087384f4f80, + 0x3fcc9d3d065c5b42, + 0x3fccfa8e765cbb72, + 0x3fccfa8e765cbb72, + 0x3fcd587d96494759, + 0x3fcdb70c7e96e7f3, + 0x3fcdb70c7e96e7f3, + 0x3fce163d527e68cf, + 0x3fce76124046b3f3, + 0x3fce76124046b3f3, + 0x3fced68d819191fc, + 0x3fcf37b15bab08d1, + 0x3fcf37b15bab08d1, + 0x3fcf99801fdb749d, + 0x3fcffbfc2bbc7803, + 0x3fcffbfc2bbc7803, + 0x3fd02f93f4c87101, + 0x3fd06182e84fd4ac, + 0x3fd06182e84fd4ac, + 0x3fd093cc32c90f84, + 0x3fd093cc32c90f84, + 0x3fd0c6711d6abd7a, + 0x3fd0f972f87ff3d6, + 0x3fd0f972f87ff3d6, + 0x3fd12cd31b9c99ff, + 0x3fd12cd31b9c99ff, + 0x3fd16092e5d3a9a6, + 0x3fd194b3bdef6b9e, + 0x3fd194b3bdef6b9e, + 0x3fd1c93712abc7ff, + 0x3fd1c93712abc7ff, + 0x3fd1fe1e5af2c141, + 0x3fd1fe1e5af2c141, + 0x3fd2336b161b3337, + 0x3fd2336b161b3337, + 0x3fd2691ecc29f042, + 0x3fd2691ecc29f042, + 0x3fd29f3b0e15584b, + 0x3fd29f3b0e15584b, + 0x3fd2d5c1760b86bb, + 0x3fd2d5c1760b86bb, + 0x3fd30cb3a7bb3625, + 0x0000000000000000, +]; + +#[inline] +pub(crate) fn core_log10f(x: f64) -> f64 { + let x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + let e_x = x_e as f64; + + const LOG_10_2_HI: f64 = f64::from_bits(0x3fd34413509f79ff); + + let log_r_dd = LOG10_D[index as usize]; + + // hi is exact + let hi = f_fmla(e_x, LOG_10_2_HI, f64::from_bits(log_r_dd)); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + // Polynomial for log(1+x)/x generated in Sollya: + // d = [-2^-8, 2^-7]; + // f_log10 = log10(1 + x)/x; + // Q = fpminimax(f_log10, 6, [|D...|], d); + // See ./notes/log10pf_core.sollya + let p = f_polyeval6( + u, + f64::from_bits(0x3fdbcb7b1526e50e), + f64::from_bits(0xbfcbcb7b1526e4e2), + f64::from_bits(0x3fc287a763707f60), + f64::from_bits(0xbfbbcb7b16f1858d), + f64::from_bits(0x3fb63c613ca2ee0f), + f64::from_bits(0xbfb28617a50029a9), + ); + f_fmla(p, u, hi) +} + +/// Computes log10(x+1) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_log10p1f(x: f32) -> f32 { + let z = x as f64; + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + return x; + } + if x.is_infinite() { + return if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NAN + }; + } + return x + f32::NAN; + } + + let ax = x.to_bits() & 0x7fff_ffffu32; + + // Use log10p1(x) = log10(1 + x) for |x| > 2^-6; + if ax > 0x3c80_0000u32 { + if x == -1. { + return f32::NEG_INFINITY; + } + let x1p = z + 1.; + if x1p <= 0. { + if x1p == 0. { + return f32::NEG_INFINITY; + } + return f32::NAN; + } + return core_log10f(x1p) as f32; + } + + // log10p1 is expected to be used near zero: + // Polynomial generated by Sollya: + // d = [-2^-6; 2^-6]; + // f_log10pf = log10(1+x)/x; + // Q = fpminimax(f_log10pf, 6, [|D...|], d); + const C: [u64; 7] = [ + 0x3fdbcb7b1526e50e, + 0xbfcbcb7b1526f138, + 0x3fc287a7636f8798, + 0xbfbbcb7b08fcfcad, + 0x3fb63c625d2472a4, + 0xbfb2892c9b620de1, + 0x3fafc7d3af2f4b6c, + ]; + let p = f_estrin_polyeval7( + z, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + ); + (p * z) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10p1f() { + assert_eq!(f_log10p1f(0.0), 0.0); + assert_eq!(f_log10p1f(1.0), 0.30103); + assert_eq!(f_log10p1f(-0.0432432), -0.019198442); + assert_eq!(f_log10p1f(-0.009874634), -0.0043098135); + assert_eq!(f_log10p1f(-0.000000054233), -2.3553092e-8); + assert_eq!(f_log10p1f(1.2443), 0.35108092); + assert_eq!(f_log10p1f(f32::INFINITY), f32::INFINITY); + assert!(f_log10p1f(f32::NEG_INFINITY).is_nan()); + assert!(f_log10p1f(-1.0432432).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10td.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10td.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,132 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::log10td_coeffs::LOG10_NEG_TD; +use crate::pow_tables::POW_INVERSE; +use crate::triple_double::TripleDouble; + +#[inline(always)] +fn log10_poly(z: f64) -> TripleDouble { + /* + Poly generated by Sollya: + + d = [-0.0040283203125,0.0040283203125]; + f = log10(1+x)/x; + pf = fpminimax(f, 10, [|157...|], d, absolute, floating); + + See ./notes/td_log10.sollya + */ + const P: [(u64, u64, u64); 11] = [ + (0xb8f29c4663277dc0, 0x3c695355baaafad3, 0x3fdbcb7b1526e50e), + (0x38ee76408ee1b680, 0xbc595355bab3a517, 0xbfcbcb7b1526e50e), + (0x38f58fe4d121c480, 0xbc59c8718361a853, 0x3fc287a7636f435f), + (0xb8e80f425616e240, 0xbc49520fd0630f7e, 0xbfbbcb7b1526e50e), + (0x38eb058acb9ab2c0, 0x3c443f5b242c637b, 0x3fb63c62775250d8), + (0x38c32c088e8da180, 0xbc4a6666386cc60e, 0xbfb287a7636f436c), + (0x38bb2e95bc6a3a80, 0x3c45ac4260107e46, 0x3fafc3fa615105f6), + (0xb8e14f1e5b926690, 0x3c421ee12f4a23de, 0xbfabcb7b14ed42da), + (0x38d4b4d370b610e0, 0x3c47e2c6f24d3d30, 0x3fa8b4df2ef1a288), + (0x38bd632a8b3a6500, 0xbc1a922cdefb3bb1, 0xbfa63c98a8c44069), + (0xb8c077b6551291c0, 0x3c4337142dd97816, 0x3fa4372045637cca), + ]; + let mut t = TripleDouble::f64_mul_add( + z, + TripleDouble::from_bit_pair(P[9]), + TripleDouble::from_bit_pair(P[8]), + ); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[7])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[6])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[5])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[4])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[3])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[2])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[1])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[0])); + TripleDouble::quick_mult_f64(t, z) +} + +#[inline] +pub(crate) fn log10_td(x: f64) -> TripleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log10(x) = log10(t) + E · log10(e) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log10_r = TripleDouble::from_bit_pair(LOG10_NEG_TD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG10_2_DD: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc49dc1da994fd21, 0x3fd34413509f79ff)); + + let v = TripleDouble::f64_mul_dd_add(be as f64, LOG10_2_DD, log10_r); + + let p = log10_poly(z); + TripleDouble::add_f64(v.hi, TripleDouble::new(v.lo + p.lo, v.mid + p.mid, p.hi)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log10_dd() { + assert_eq!(log10_td(10.).to_f64(), 1.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10td_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log10td_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log10td_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,227 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by SageMath: +```python +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_triple_double("", -RealField(180)(r).log10()) +``` +**/ +pub(crate) static LOG10_NEG_TD: [(u64, u64, u64); 182] = [ + (0xb89002c845c3b128, 0xbc0b420b9b202edd, 0xbfc31b3055c47118), + (0x38e5607e92cc3d86, 0xbc662219537667a2, 0xbfc2cc20b1734279), + (0xb8c53b02f2c219ad, 0xbc4386d677ad2ead, 0xbfc27c9ffae729c1), + (0x390c4925ec4ba355, 0x3c6fb908b0ca4062, 0xbfc22cacece26ead), + (0xb907310487c79786, 0xbc61b4170b1c73f0, 0xbfc1dc463ca41df8), + (0x38fdec83a542321d, 0x3c5d6679f737585c, 0xbfc18b6a99c7f679), + (0x39075e156bc06274, 0x3c6c6397435bc5b6, 0xbfc162d082ac9d10), + (0x38b62066cf807969, 0x3c4b8c4f1b08949b, 0xbfc11142f0811357), + (0xb8eb79f0297d79fd, 0xbc5e17a06836db63, 0xbfc0bf3d0937c41c), + (0xb8baf3f94b418d28, 0xbc65163143f60061, 0xbfc06cbd67a6c3b6), + (0x3907cb66c266da5e, 0xbc6c5e9d9a0e1fd9, 0xbfc019c2a064b486), + (0xb8fc8f49451b2b9c, 0x3c5ec7f2dac60a5c, 0xbfbf8c9683468191), + (0x38a21551cf561003, 0x3c54a69937a2d705, 0xbfbf38c0c8325d86), + (0x38f32dcc7f6a5efc, 0x3c53cbb5a6ee659b, 0xbfbe9056bcb315e8), + (0x38ff4e6aafdeb6a5, 0x3c51bf355bb72ca1, 0xbfbde6ec0f392b05), + (0xb8c5949c22c5c13e, 0x3c5ce84c9eaee37a, 0xbfbd91d5866aa99c), + (0xb8c0d2e29710fa1a, 0x3c26f0603909a181, 0xbfbce6e41e463da5), + (0x38fcbad44d58c56f, 0x3c58b9190212e5ba, 0xbfbc3aea4a5c6eff), + (0x38c3c3b861649e91, 0x3c2446d00b829ad4, 0xbfbb8de4d3ab3d98), + (0x38eeab77ea5ae5c0, 0x3c5aa2aeaa7bc18d, 0xbfbb36fcb5f8be8a), + (0x38f866aee06a4002, 0x3c5dd366189ac022, 0xbfba885fa2d6151e), + (0xb8da496755361f14, 0x3c4ebf33e9410429, 0xbfba30a9d609efea), + (0xb8eb9d973d5a81ee, 0xbc5c81cca3dd9b7b, 0xbfb9806d9414a209), + (0xb8f25cbc5fc36d82, 0x3c5935d381a0844f, 0xbfb8cf183886480d), + (0x38ce162025d7f34a, 0x3c3666804e99aabc, 0xbfb8760307d355ab), + (0x38b60052fa072a91, 0xbc21064a1f6dc0c5, 0xbfb7c30164a60836), + (0xb8c07c05e9fdb823, 0x3c5ac4c370ae3c1d, 0xbfb769140a2526fd), + (0x38f5b5c030bcef17, 0xbc5643835531d8ee, 0xbfb6b45df6f3e2c9), + (0x38d21688e77d5afb, 0x3c59d9c8eaf88500, 0xbfb659944f8ba02d), + (0xb8efde3e6ebdf069, 0xbc48cb0dc78c3961, 0xbfb5a32167b32f02), + (0x38f5f10707d2333c, 0x3c5e1bcfb0476f5d, 0xbfb5477731973e85), + (0x38e3d7d43d84e36e, 0xbc5782120ed9fd02, 0xbfb48f3ed1df48fb), + (0xb8f268b21a5b88f8, 0x3c51960cbdfcb2d3, 0xbfb432afab5dd3ff), + (0x38c42231800bf01c, 0x3c4a83d8a6eb8e2e, 0xbfb3d5d335c53179), + (0xb88002c845c3b128, 0xbbfb420b9b202edd, 0xbfb31b3055c47118), + (0x38c136f6506c3113, 0xbc59f5fa977fa091, 0xbfb2bd68e4621371), + (0x38f1c66402538718, 0x3c5c2f24fb8a820d, 0xbfb200eb639a3173), + (0xb8e8305d344af3bf, 0x3c4f990c2c07d3b5, 0xbfb1a23445501816), + (0xb8d0911e570f1772, 0x3c4114d5dc0b3275, 0xbfb1432c31917d08), + (0xb8d0c670f62a43c9, 0x3c3ccc49eb0a89d8, 0xbfb08426fcdb1ee7), + (0x38c282a6187110fe, 0x3c35943d4373d44a, 0xbfb02428c1f08016), + (0xb8dae3378c046c6a, 0x3c31436f936096a0, 0xbfaf87aebb43ce06), + (0xb8eb644705b7affb, 0x3c4d4d643174a412, 0xbfae0471aa1868f5), + (0x38e7097d514f05cc, 0x3c47f9dc537bfbfb, 0xbfad41d5164facb4), + (0x38efea466ac41bfd, 0x3c4073b6859dc799, 0xbfac7e8d993509f9), + (0x38e735cc6aa10798, 0x3c46487d64961833, 0xbfaaf5f92b00e610), + (0xb8ca496755361f14, 0x3c3ebf33e9410429, 0xbfaa30a9d609efea), + (0xb8e423cab9979886, 0x3c41c8c309cdac54, 0xbfa96aaacfefcf3c), + (0xb8e8d323b0a8265c, 0x3c4b144b06126f68, 0xbfa8a3fadeb847f4), + (0xb8d443df1e952f54, 0x3c38f0f77fcff1d9, 0xbfa71483427d2a99), + (0xb8c0f02a728b0923, 0xbc2eff9decc696f6, 0xbfa64bb912d65c07), + (0x38df7639a3c4fefb, 0xbc4efd454f7ea69a, 0xbfa58238eeb353da), + (0xb8d020031b665cbc, 0xbc443795bbf70657, 0xbfa4b8018b21ed4f), + (0xb8e5f6d30622464a, 0x3c492b9251ee5832, 0xbfa32167c82bdcda), + (0x38dc9bdb87272974, 0x3c4ff894a084ae68, 0xbfa25502c0fc314c), + (0xb8cc98efd443d8bd, 0xbc49adc1c7f97f4a, 0xbfa187e12aad8077), + (0x38dd736bbeb20108, 0xbc35f1d45244f437, 0xbfa0ba01a8170000), + (0x38d9223bf675f3cd, 0x3c3e7ffa709828ef, 0xbf9fd6c5b0851c4c), + (0xb89b88f11b4d4ea9, 0xbc0af3eb3b443356, 0xbf9e3806acbd058f), + (0x38d735cc6aa10798, 0x3c36487d64961833, 0xbf9af5f92b00e610), + (0xb8b16ecc6dcb33a1, 0x3c1f21279ca1bd16, 0xbf9952a4f22c5ae9), + (0xb8b049f2508d0405, 0xbc1b980714c596a3, 0xbf97adc3df3b1ff8), + (0xb8c31b155a73c7e0, 0xbc36ea248137e395, 0xbf960753003a94ef), + (0x38bab270fa22426e, 0xbc3dda7897a55eb5, 0xbf945f4f5acb8be0), + (0xb8b2011a6d02a2f9, 0xbc15bcd6d3458191, 0xbf92b5b5ec0209d3), + (0x38d9567819f06222, 0x3c37b9fd5428084f, 0xbf910a83a8446c78), + (0xb8b695431959f8e4, 0xbc1b57b9aec33450, 0xbf8ebb6af653e2ee), + (0x387790ad1c32f033, 0xbbff2e9fe367a511, 0xbf8b5e908eb13790), + (0x38b94f863e314105, 0xbc28d4a223a5f7c9, 0xbf87fe71ccc4e6b0), + (0xb8a983539059615f, 0x3c18f207a6d0d0b1, 0xbf849b0851443684), + (0x38c01a8492cb45d3, 0x3c29383502395c53, 0xbf81344daa2d7553), + (0x38a86d6805b5b078, 0x3c03b252df477a75, 0xbf7b9476a4fcd10f), + (0xb88d03d2f51efac9, 0xbbefb495d6440f14, 0xbf74b99563d2a1bd), + (0x38ae415215a90a2b, 0xbc09706ea523f0a5, 0xbf6bafd47221ed26), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0x38a5c7c42656edc5, 0x3c0dcbdc594292c0, 0x3f64e84e793a474a), + (0xb8baa27d025eefb8, 0x3c11e6c1240ced74, 0x3f7175085ab85ff0), + (0xb892d9a16b70963f, 0x3c0e1d6052707e0e, 0x3f787cff9d9147a5), + (0xb884e8e710379609, 0xbbee4f45b8df7d67, 0x3f7f8c1b6b0c8d4e), + (0xb8c08a4af7bab81f, 0x3c22495d8b8e25b7, 0x3f8351352a8e733f), + (0xb87e8055cf668c67, 0x3c1bc0294772c57f, 0x3f86dffd8d3bbf70), + (0xb8b9b54309dabea5, 0xbc2b41d4e4ac05d4, 0x3f8a726e53a6056e), + (0x389370d9e5682f63, 0xbc28d01e8ac8a78b, 0x3f8c3d0837784c41), + (0x380107b2c9d18b62, 0x3c27d5b73769b64c, 0x3f8fd503c3904f1d), + (0x3879c1318df4f5fb, 0xbbd646ebcccb6894, 0x3f91b85d6044e9ae), + (0x38d23a2b392f494f, 0x3c37b38a223627b5, 0x3f93881a7b818f9e), + (0xb87266701d45d395, 0x3c0521ad5fa98432, 0x3f9559bd2406c3ba), + (0x38c07782809ecaf6, 0xbc29fc37c4e4e576, 0x3f972d4956ca2067), + (0xb8d9f4886964e9f2, 0x3c3c830373882139, 0x3f9817c846828bbd), + (0x38aa4fd0d6840595, 0x3c0be24ddca8b835, 0x3f99ee3a5e9f57e8), + (0xb8a1f073a0185b5c, 0x3c0999ccc6d592f0, 0x3f9bc6a03117eb97), + (0x38c1ba31ff0ebcf6, 0xbc34a65cdeb626ca, 0x3f9da0fde8038de9), + (0xb8c2ae25e3c7af79, 0xbc29dc1111e3b44c, 0x3f9f7d57badb4ee8), + (0x38e2862d635fc3a1, 0x3c47db4db93811b8, 0x3fa0362241e638ec), + (0x38da4725a086a87e, 0xbc3f6975f23b8a99, 0x3fa125d0432ea20e), + (0x38e747dcf984a4ce, 0x3c463610c66f42b2, 0x3fa21681b5c8c213), + (0xb8ba8f5a9e1afc55, 0x3c3c756ef644213d, 0x3fa28f3c69912a74), + (0x38b20caa6a9c4119, 0xbc11b16a272d4ddf, 0x3fa381772a00e604), + (0x38c15a731b8c76f0, 0xbc2197beb0be1c78, 0x3fa474baeb77e904), + (0xb89fcd308117f994, 0xbc0978c592e6c139, 0x3fa4eec0e2458f30), + (0xb8c59c1417fe9b19, 0x3c2bb9cd2fb75402, 0x3fa5e3966b7e9295), + (0x38c469a2211e96d7, 0x3c377b340fa390ec, 0x3fa6d97ab3ba5e10), + (0x38d48e0de01f1b66, 0x3c3ea90ccf791593, 0x3fa754d31b1b179c), + (0xb8d369beaa748363, 0x3c454596cc7150a8, 0x3fa84c51ebee8d15), + (0xb8d20cdb1f079c35, 0xbc476df54932f73e, 0x3fa944e56a0d3450), + (0x38cc0a24a6aece0c, 0xbc286148dd4cfbf5, 0x3fa9c197abf00dd7), + (0x38c68fdc7ccadc86, 0xbc397d2cb982dac2, 0x3faabbcebd84fca0), + (0x38ad7e11b8460553, 0x3c36591c969ff97b, 0x3fab39542ba23d73), + (0xb8c42c09b578a1bb, 0xbc40859ccb55560e, 0x3fac3534628016dd), + (0x38e912371677ce89, 0x3c4a5aca518d962e, 0x3facb38fccd8bfdb), + (0x38cbad1cb83cff56, 0x3c396e1e0dda0b3d, 0x3fadb11ed766abf4), + (0x38d5fbe0cd351aa2, 0x3c332de632195123, 0x3fae30531c76c34a), + (0xb8cc92b7b45b9557, 0xbc23a73e99099cbd, 0x3faf2f96c6754aee), + (0x38c78cf7437c1a1c, 0x3c262f731cfeb27b, 0x3fafafa6d397efdb), + (0xb8ea24ca8acd4629, 0xbc4e0c43230184dc, 0x3fb0585283764178), + (0xb8e8bbcb792f081a, 0x3c5466dc013d46a9, 0x3fb098c9ec61b3ff), + (0xb8e5f8e913fb6a30, 0xbc5cae3496ce9852, 0x3fb11a294f2569f6), + (0xb8fbd9f731f71bf6, 0xbc56a232c37f20c5, 0x3fb15b11a094a1aa), + (0xb8d2ff33eb29a068, 0xbc4f587e7a233c80, 0x3fb1dd5460c8b16f), + (0xb8e8dde97ac3bf82, 0x3c5a0dec3a5a500c, 0x3fb21eaf28f57941), + (0x38b95b4fde7f0e0e, 0x3c585a155bb65408, 0x3fb2a1d86b49f1e2), + (0x38d56074eaea7505, 0xbc5aef53f2ecddb9, 0x3fb2e3a740b7800f), + (0x38f07fc540f1ffd6, 0xbc5de49ddb15fb04, 0x3fb367ba3aaa1883), + (0xb8f3c847b2f2b20a, 0xbc5514fb6a33e70f, 0x3fb3a9febc60540a), + (0x38f5b10bf359af28, 0x3c5c4c753d98645a, 0x3fb3ec6ad5407868), + (0x38cc8292ede0aa76, 0x3c2ce8e795b6ed98, 0x3fb471ba8a7de2b7), + (0xb8e4c088deea25e6, 0xbc54f0487863efe6, 0x3fb4b49e86b11e5f), + (0x389fb62394a838a4, 0x3c4bc478d6071be0, 0x3fb53adfb462ce16), + (0x38b8294b7967031c, 0xbc187decde1893f1, 0x3fb57e3d47c3af7b), + (0x38dfaf3384ac8a3b, 0x3c481f647ea24688, 0x3fb5c1c3c5557799), + (0xb8f02e1b4c45d28c, 0x3c5ad1738d96af06, 0x3fb6494c46ac6e4d), + (0xb8c0efee9b397b5e, 0x3c54c74f6a7880e3, 0x3fb68d4eaf26d7ee), + (0xb88bdf7c6a6a3fa8, 0xbc52a2d69cfac78f, 0x3fb6d17acb3e5f5e), + (0xb8dfad5df4f01a6b, 0x3c4e4ba167ee73dd, 0x3fb75a50ebb1624a), + (0x38effc4a2a1bc2cb, 0x3c57e469fe31a42f, 0x3fb79efb57b0f803), + (0xb8accdbd86c1b5c3, 0xbc4d12e032a3b7af, 0x3fb7e3d04697b704), + (0xb8e0e96abe790a21, 0xbc53f06091db6450, 0x3fb828cfed29a215), + (0xb8e6b1083c5aa70b, 0x3c4da13d5c8cb232, 0x3fb8b350364c6257), + (0x388318cf6f2052dc, 0x3be2034e6320e8c0, 0x3fb8f8d144557bdf), + (0xb8f19142bff65cf6, 0xbc5d0d01941798b6, 0x3fb93e7de0fc3e80), + (0xb8ff3ddeebf83378, 0xbc562d3ed69292b0, 0x3fb9ca5aa1729f45), + (0xb8f46354ffa76f1d, 0x3c5ba75ea17687d3, 0x3fba108b33edb005), + (0xb8beeaa25ea54d75, 0xbc3113a1fc340179, 0x3fba56e8325f5c87), + (0x38d5b7ac1e1aef0c, 0xbc4f648977febad9, 0x3fba9d71d5258484), + (0x38ceeebae16520f4, 0x3c45689de26b43ff, 0x3fbb2b0beb419ad0), + (0xb886dbc50eaa6c95, 0xbc5a8267d18975f3, 0x3fbb721cd17157e3), + (0xb8f10917d4228654, 0xbc5cb0a198331caf, 0x3fbbb95b41ab5ce6), + (0xb8cdb7e880ea8bbb, 0xbc5b1e2e67b6f4bf, 0x3fbc00c7767225cb), + (0xb8e783952280cc1c, 0xbc5b6b51fca7a9a5, 0x3fbc4861aab93a23), + (0x38f01f84186661a4, 0xbc58f377e27bbe25, 0x3fbcd820ffd278f3), + (0xb8f64617184a7a75, 0xbc5667bf89866cca, 0x3fbd204698cb42bd), + (0xb885683b90b4f393, 0xbc1100072d011b81, 0x3fbd689b2193f133), + (0x38dbad1cb83cff56, 0x3c496e1e0dda0b3d, 0x3fbdb11ed766abf4), + (0xb8dbaceb968c6347, 0x3c55c6bc5d06e932, 0x3fbdf9d1f7f5b674), + (0xb8fc9b4a9a70f158, 0xbc5e018e5642e2ef, 0x3fbe42b4c16caaf3), + (0x38cefcd22b519828, 0xbc20a89525f3e005, 0x3fbed50a4a26eafc), + (0xb8f06cab49f1568b, 0x3c50955b9d99c1b8, 0x3fbf1e7d882b689a), + (0xb8d3723ccec39b76, 0xbc5c42f76e4345b0, 0x3fbf68216c9cc727), + (0xb8cf28885cbbad03, 0xbc46749ac407ee87, 0x3fbfb1f6381856f4), + (0xb8dd7ad76a7a7b71, 0x3c5d60df12c2e13d, 0x3fbffbfc2bbc7803), + (0xb8d84e30bcb6c96c, 0x3c4ef8dd8b73f78d, 0x3fc02319c494f951), + (0x38d7dcb3f42ceed7, 0x3c5f318aa3021710, 0x3fc0484e4942aa43), + (0x390a877fa28d48a3, 0xbc6a12a1c0cb3d7f, 0x3fc093025a19976c), + (0x38ff47213a55d67d, 0xbc609801174f88fd, 0x3fc0b88229b71227), + (0x38f8cdc0d1c23d2c, 0x3c65b619c844d28b, 0x3fc0de1b56356b04), + (0x38e4d94a39e28f45, 0x3c4dbdf176a1440a, 0x3fc103ce01fae223), + (0xb8e86ff50e0d3676, 0xbc6ce6c847a6598d, 0x3fc1299a4fb3e306), + (0x39030b6b1dc04f65, 0xbc61f5da9e930834, 0x3fc14f806253c3ed), + (0x38f0cf7ad7cc99dc, 0x3c5ac676f20a87ab, 0x3fc175805d1587c1), + (0x389beb9c10205d5f, 0xbc6e785b3b894bd7, 0x3fc19b9a637ca295), + (0xb8ff10f27308fe1f, 0xbc5db924be9633b4, 0x3fc1c1ce9955c0c6), + (0xb8fb96f43aca9222, 0x3c6db81c3374e59e, 0x3fc1e81d22b790d4), + (0x390a3faccc5a1d64, 0xbc67299601268298, 0x3fc20e8624038fed), + (0x38f3bb0b56ef561a, 0x3c6ea54c137b0aea, 0x3fc23509c1e6d937), + (0x38ca3a8ffda52a42, 0x3c50349d03e16325, 0x3fc25ba8215af7fc), + (0xb8d4ef96e017818e, 0x3c6557d4cdeffe3f, 0x3fc2826167a6bc9c), + (0x38a1dc76a8836a07, 0xbc1f613823fd2a19, 0x3fc2a935ba5f1479), + (0xb8c261e40d93238d, 0xbc63dda694b5fe22, 0x3fc2d0253f67e4cb), + (0xb8eed469920e8a20, 0xbc4c7972ce5f8b57, 0x3fc2f7301cf4e87b), + (0x38e43330d48115cd, 0x3c54b79d1957630a, 0x3fc31e56798a910a), + (0x38ffcf787a5e0b91, 0xbc654fd6eb7d970e, 0x3fc345987bfeea91), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,814 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::{EXP_MASK, get_exponent_f64}; +use crate::common::{dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::DyadicFloat128; +use crate::logs::log1p_dd::log1p_dd; +use crate::logs::log1p_dyadic::log1p_accurate; +use crate::polyeval::f_polyeval4; + +// R1[i] = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7) ) +pub(crate) static R1: [u64; 129] = [ + 0x3ff0000000000000, + 0x3fefc00000000000, + 0x3fef800000000000, + 0x3fef400000000000, + 0x3fef000000000000, + 0x3feec00000000000, + 0x3feea00000000000, + 0x3fee600000000000, + 0x3fee200000000000, + 0x3fede00000000000, + 0x3feda00000000000, + 0x3fed800000000000, + 0x3fed400000000000, + 0x3fed000000000000, + 0x3fece00000000000, + 0x3feca00000000000, + 0x3fec800000000000, + 0x3fec400000000000, + 0x3fec000000000000, + 0x3febe00000000000, + 0x3feba00000000000, + 0x3feb800000000000, + 0x3feb400000000000, + 0x3feb200000000000, + 0x3feb000000000000, + 0x3feac00000000000, + 0x3feaa00000000000, + 0x3fea600000000000, + 0x3fea400000000000, + 0x3fea200000000000, + 0x3fe9e00000000000, + 0x3fe9c00000000000, + 0x3fe9a00000000000, + 0x3fe9800000000000, + 0x3fe9400000000000, + 0x3fe9200000000000, + 0x3fe9000000000000, + 0x3fe8e00000000000, + 0x3fe8a00000000000, + 0x3fe8800000000000, + 0x3fe8600000000000, + 0x3fe8400000000000, + 0x3fe8200000000000, + 0x3fe8000000000000, + 0x3fe7e00000000000, + 0x3fe7a00000000000, + 0x3fe7800000000000, + 0x3fe7600000000000, + 0x3fe7400000000000, + 0x3fe7200000000000, + 0x3fe7000000000000, + 0x3fe6e00000000000, + 0x3fe6c00000000000, + 0x3fe6a00000000000, + 0x3fe6800000000000, + 0x3fe6600000000000, + 0x3fe6400000000000, + 0x3fe6200000000000, + 0x3fe6000000000000, + 0x3fe5e00000000000, + 0x3fe5c00000000000, + 0x3fe5a00000000000, + 0x3fe5800000000000, + 0x3fe5800000000000, + 0x3fe5600000000000, + 0x3fe5400000000000, + 0x3fe5200000000000, + 0x3fe5000000000000, + 0x3fe4e00000000000, + 0x3fe4c00000000000, + 0x3fe4a00000000000, + 0x3fe4a00000000000, + 0x3fe4800000000000, + 0x3fe4600000000000, + 0x3fe4400000000000, + 0x3fe4200000000000, + 0x3fe4200000000000, + 0x3fe4000000000000, + 0x3fe3e00000000000, + 0x3fe3c00000000000, + 0x3fe3c00000000000, + 0x3fe3a00000000000, + 0x3fe3800000000000, + 0x3fe3600000000000, + 0x3fe3600000000000, + 0x3fe3400000000000, + 0x3fe3200000000000, + 0x3fe3000000000000, + 0x3fe3000000000000, + 0x3fe2e00000000000, + 0x3fe2c00000000000, + 0x3fe2c00000000000, + 0x3fe2a00000000000, + 0x3fe2800000000000, + 0x3fe2800000000000, + 0x3fe2600000000000, + 0x3fe2400000000000, + 0x3fe2400000000000, + 0x3fe2200000000000, + 0x3fe2000000000000, + 0x3fe2000000000000, + 0x3fe1e00000000000, + 0x3fe1c00000000000, + 0x3fe1c00000000000, + 0x3fe1a00000000000, + 0x3fe1a00000000000, + 0x3fe1800000000000, + 0x3fe1600000000000, + 0x3fe1600000000000, + 0x3fe1400000000000, + 0x3fe1400000000000, + 0x3fe1200000000000, + 0x3fe1200000000000, + 0x3fe1000000000000, + 0x3fe0e00000000000, + 0x3fe0e00000000000, + 0x3fe0c00000000000, + 0x3fe0c00000000000, + 0x3fe0a00000000000, + 0x3fe0a00000000000, + 0x3fe0800000000000, + 0x3fe0800000000000, + 0x3fe0600000000000, + 0x3fe0600000000000, + 0x3fe0400000000000, + 0x3fe0400000000000, + 0x3fe0200000000000, + 0x3fe0200000000000, + 0x3fe0000000000000, +]; + +// Extra constants for exact range reduction when FMA instructions are not +// available: +// r * c - 1 for r = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7)) +// and c = 1 + i * 2^-7 +// with i = 0..128. +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +)))] +pub(crate) static RCM1: [u64; 129] = [ + 0x0000000000000000, + 0xbf10000000000000, + 0xbf30000000000000, + 0xbf42000000000000, + 0xbf50000000000000, + 0xbf59000000000000, + 0x3f5f000000000000, + 0x3f52800000000000, + 0x3f30000000000000, + 0xbf49000000000000, + 0xbf5f000000000000, + 0x3f52000000000000, + 0xbf30000000000000, + 0xbf5c000000000000, + 0x3f51000000000000, + 0xbf45000000000000, + 0x3f60000000000000, + 0x3f10000000000000, + 0xbf60000000000000, + 0x3f3a000000000000, + 0xbf5e000000000000, + 0x3f38000000000000, + 0xbf61000000000000, + 0xbf00000000000000, + 0x3f60000000000000, + 0xbf4a000000000000, + 0x3f51000000000000, + 0xbf5f800000000000, + 0xbf30000000000000, + 0x3f56800000000000, + 0xbf5f000000000000, + 0xbf3c000000000000, + 0x3f50000000000000, + 0x3f63000000000000, + 0xbf56000000000000, + 0xbf24000000000000, + 0x3f50000000000000, + 0x3f60c00000000000, + 0xbf60800000000000, + 0xbf52000000000000, + 0xbf30000000000000, + 0x3f42000000000000, + 0x3f55000000000000, + 0x3f60000000000000, + 0x3f65000000000000, + 0xbf61c00000000000, + 0xbf5c000000000000, + 0xbf55800000000000, + 0xbf50000000000000, + 0xbf47000000000000, + 0xbf40000000000000, + 0xbf36000000000000, + 0xbf30000000000000, + 0xbf2c000000000000, + 0xbf30000000000000, + 0xbf36000000000000, + 0xbf40000000000000, + 0xbf47000000000000, + 0xbf50000000000000, + 0xbf55800000000000, + 0xbf5c000000000000, + 0xbf61c00000000000, + 0xbf66000000000000, + 0x3f65000000000000, + 0x3f60000000000000, + 0x3f55000000000000, + 0x3f42000000000000, + 0xbf30000000000000, + 0xbf52000000000000, + 0xbf60800000000000, + 0xbf68800000000000, + 0x3f60c00000000000, + 0x3f50000000000000, + 0xbf24000000000000, + 0xbf56000000000000, + 0xbf65400000000000, + 0x3f63000000000000, + 0x3f50000000000000, + 0xbf3c000000000000, + 0xbf5f000000000000, + 0x3f68000000000000, + 0x3f56800000000000, + 0xbf30000000000000, + 0xbf5f800000000000, + 0x3f67000000000000, + 0x3f51000000000000, + 0xbf4a000000000000, + 0xbf66000000000000, + 0x3f60000000000000, + 0xbf00000000000000, + 0xbf61000000000000, + 0x3f64800000000000, + 0x3f38000000000000, + 0xbf5e000000000000, + 0x3f66000000000000, + 0x3f3a000000000000, + 0xbf60000000000000, + 0x3f64800000000000, + 0x3f10000000000000, + 0xbf64000000000000, + 0x3f60000000000000, + 0xbf45000000000000, + 0xbf6b000000000000, + 0x3f51000000000000, + 0xbf5c000000000000, + 0x3f65400000000000, + 0xbf30000000000000, + 0xbf69c00000000000, + 0x3f52000000000000, + 0xbf5f000000000000, + 0x3f63000000000000, + 0xbf49000000000000, + 0x3f6c000000000000, + 0x3f30000000000000, + 0xbf68800000000000, + 0x3f52800000000000, + 0xbf62000000000000, + 0x3f5f000000000000, + 0xbf59000000000000, + 0x3f64c00000000000, + 0xbf50000000000000, + 0x3f69000000000000, + 0xbf42000000000000, + 0x3f6c400000000000, + 0xbf30000000000000, + 0x3f6e800000000000, + 0xbf10000000000000, + 0x3f6fc00000000000, + 0x0000000000000000, +]; + +pub(crate) static LOG_R1_DD: [(u64, u64); 129] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbd10c76b999d2be8, 0x3f80101575890000), + (0xbd23dc5b06e2f7d2, 0x3f90205658938000), + (0xbd2aa0ba325a0c34, 0x3f98492528c90000), + (0x3d0111c05cf1d753, 0x3fa0415d89e74000), + (0xbd2c167375bdfd28, 0x3fa466aed42e0000), + (0xbd029efbec19afa2, 0x3fa67c94f2d4c000), + (0x3d20fc1a353bb42e, 0x3faaaef2d0fb0000), + (0xbd0e113e4fc93b7b, 0x3faeea31c006c000), + (0xbd25325d560d9e9b, 0x3fb1973bd1466000), + (0x3d2cc85ea5db4ed7, 0x3fb3bdf5a7d1e000), + (0xbcf53a2582f4e1ef, 0x3fb4d3115d208000), + (0x3cec1e8da99ded32, 0x3fb700d30aeac000), + (0x3d23115c3abd47da, 0x3fb9335e5d594000), + (0xbd0e42b6b94407c8, 0x3fba4e7640b1c000), + (0x3d2646d1c65aacd3, 0x3fbc885801bc4000), + (0x3d1a89401fa71733, 0x3fbda72763844000), + (0xbd2534d64fa10afd, 0x3fbfe89139dbe000), + (0x3d21ef78ce2d07f2, 0x3fc1178e8227e000), + (0x3d2ca78e44389934, 0x3fc1aa2b7e23f000), + (0x3d039d6ccb81b4a1, 0x3fc2d1610c868000), + (0x3cc62fa8234b7289, 0x3fc365fcb0159000), + (0x3d25837954fdb678, 0x3fc4913d8333b000), + (0x3d2633e8e5697dc7, 0x3fc527e5e4a1b000), + (0xbd127023eb68981c, 0x3fc5bf406b544000), + (0xbd25118de59c21e1, 0x3fc6f0128b757000), + (0xbd1c661070914305, 0x3fc7898d85445000), + (0xbd073d54aae92cd1, 0x3fc8beafeb390000), + (0x3d07f22858a0ff6f, 0x3fc95a5adcf70000), + (0x3d29904d6865817a, 0x3fc9f6c407089000), + (0xbd0c358d4eace1aa, 0x3fcb31d8575bd000), + (0xbd2d4bc4595412b6, 0x3fcbd087383be000), + (0xbcf1ec72c5962bd2, 0x3fcc6ffbc6f01000), + (0xbd084a7e75b6f6e4, 0x3fcd1037f2656000), + (0x3cc212276041f430, 0x3fce530effe71000), + (0xbcca211565bb8e11, 0x3fcef5ade4dd0000), + (0x3d1bcbecca0cdf30, 0x3fcf991c6cb3b000), + (0xbd16f08c1485e94a, 0x3fd01eae5626c800), + (0x3d27188b163ceae9, 0x3fd0c42d67616000), + (0xbd2c210e63a5f01c, 0x3fd1178e8227e800), + (0x3d2b9acdf7a51681, 0x3fd16b5ccbacf800), + (0x3d2ca6ed5147bdb7, 0x3fd1bf99635a6800), + (0x3d0a87deba46baea, 0x3fd214456d0eb800), + (0x3d2c93c1df5bb3b6, 0x3fd269621134d800), + (0x3d2a9cfa4a5004f4, 0x3fd2bef07cdc9000), + (0x3d116ecdb0f177c8, 0x3fd36b6776be1000), + (0x3d183b54b606bd5c, 0x3fd3c25277333000), + (0x3d08e436ec90e09d, 0x3fd419b423d5e800), + (0xbd2f27ce0967d675, 0x3fd4718dc271c800), + (0xbd2e20891b0ad8a4, 0x3fd4c9e09e173000), + (0x3d2ebe708164c759, 0x3fd522ae0738a000), + (0x3d1fadedee5d40ef, 0x3fd57bf753c8d000), + (0xbd0a0b2a08a465dc, 0x3fd5d5bddf596000), + (0xbd2db623e731ae00, 0x3fd630030b3ab000), + (0x3d20a0d32756eba0, 0x3fd68ac83e9c6800), + (0x3d1721657c222d87, 0x3fd6e60ee6af1800), + (0x3d2d8b0949dc60b3, 0x3fd741d876c67800), + (0x3d29ec7d2efd1778, 0x3fd79e26687cf800), + (0xbd272090c812566a, 0x3fd7fafa3bd81800), + (0x3d2fd56f3333778a, 0x3fd85855776dc800), + (0xbd205ae1e5e70470, 0x3fd8b639a88b3000), + (0xbd1766b52ee6307d, 0x3fd914a8635bf800), + (0xbd152313a502d9f0, 0x3fd973a343135800), + (0xbd152313a502d9f0, 0x3fd973a343135800), + (0xbd26279e10d0c0b0, 0x3fd9d32bea15f000), + (0x3d23c6457f9d79f5, 0x3fda33440224f800), + (0x3d1e36f2bea77a5d, 0x3fda93ed3c8ad800), + (0xbd217cc552774458, 0x3fdaf5295248d000), + (0x3d1095252d841995, 0x3fdb56fa04462800), + (0x3d27d85bf40a666d, 0x3fdbb9611b80e000), + (0x3d2cec807fe8e180, 0x3fdc1c60693fa000), + (0x3d2cec807fe8e180, 0x3fdc1c60693fa000), + (0xbd29b6ddc15249ae, 0x3fdc7ff9c7455800), + (0xbd0797c33ec7a6b0, 0x3fdce42f18064800), + (0x3d235bafe9a767a8, 0x3fdd490246def800), + (0xbd1ea42d60dc616a, 0x3fddae75484c9800), + (0xbd1ea42d60dc616a, 0x3fddae75484c9800), + (0xbd1326b207322938, 0x3fde148a1a272800), + (0xbd2465505372bd08, 0x3fde7b42c3ddb000), + (0x3d2f27f45a470251, 0x3fdee2a156b41000), + (0x3d2f27f45a470251, 0x3fdee2a156b41000), + (0x3d12cde56f014a8b, 0x3fdf4aa7ee031800), + (0x3d0085fa3c164935, 0x3fdfb358af7a4800), + (0xbd053ba3b1727b1c, 0x3fe00e5ae5b20800), + (0xbd053ba3b1727b1c, 0x3fe00e5ae5b20800), + (0xbd04c45fe79539e0, 0x3fe04360be760400), + (0x3d26812241edf5fd, 0x3fe078bf0533c400), + (0x3d1f486b887e7e27, 0x3fe0ae76e2d05400), + (0x3d1f486b887e7e27, 0x3fe0ae76e2d05400), + (0x3d1c299807801742, 0x3fe0e4898611cc00), + (0xbd258647bb9ddcb2, 0x3fe11af823c75c00), + (0xbd258647bb9ddcb2, 0x3fe11af823c75c00), + (0xbd2edd97a293ae49, 0x3fe151c3f6f29800), + (0x3d14cc4ef8ab4650, 0x3fe188ee40f23c00), + (0x3d14cc4ef8ab4650, 0x3fe188ee40f23c00), + (0x3cccacdeed70e667, 0x3fe1c07849ae6000), + (0xbd2a7242c9fe81d3, 0x3fe1f8635fc61800), + (0xbd2a7242c9fe81d3, 0x3fe1f8635fc61800), + (0x3d12fc066e48667b, 0x3fe230b0d8bebc00), + (0xbd0b61f105226250, 0x3fe269621134dc00), + (0xbd0b61f105226250, 0x3fe269621134dc00), + (0x3d206d2be797882d, 0x3fe2a2786d0ec000), + (0xbd17a6e507b9dc11, 0x3fe2dbf557b0e000), + (0xbd17a6e507b9dc11, 0x3fe2dbf557b0e000), + (0xbd274e93c5a0ed9c, 0x3fe315da44340800), + (0xbd274e93c5a0ed9c, 0x3fe315da44340800), + (0x3d10b83f9527e6ac, 0x3fe35028ad9d8c00), + (0xbd218b7abb5569a4, 0x3fe38ae217197800), + (0xbd218b7abb5569a4, 0x3fe38ae217197800), + (0xbd02b7367cfe13c2, 0x3fe3c6080c36c000), + (0xbd02b7367cfe13c2, 0x3fe3c6080c36c000), + (0xbd26ce7930f0c74c, 0x3fe4019c2125cc00), + (0xbd26ce7930f0c74c, 0x3fe4019c2125cc00), + (0xbcfd984f481051f7, 0x3fe43d9ff2f92400), + (0xbd22cb6af94d60aa, 0x3fe47a1527e8a400), + (0xbd22cb6af94d60aa, 0x3fe47a1527e8a400), + (0x3cef7115ed4c541c, 0x3fe4b6fd6f970c00), + (0x3cef7115ed4c541c, 0x3fe4b6fd6f970c00), + (0xbd2e6c516d93b8fb, 0x3fe4f45a835a5000), + (0xbd2e6c516d93b8fb, 0x3fe4f45a835a5000), + (0x3d05ccc45d257531, 0x3fe5322e26867800), + (0x3d05ccc45d257531, 0x3fe5322e26867800), + (0x3d09980bff3303dd, 0x3fe5707a26bb8c00), + (0x3d09980bff3303dd, 0x3fe5707a26bb8c00), + (0x3d2dfa63ac10c9fb, 0x3fe5af405c364800), + (0x3d2dfa63ac10c9fb, 0x3fe5af405c364800), + (0x3d2202380cda46be, 0x3fe5ee82aa241800), + (0x3d2202380cda46be, 0x3fe5ee82aa241800), + (0x0000000000000000, 0x0000000000000000), +]; + +#[inline] +pub(crate) fn log1p_f64_dyadic(x: f64) -> DyadicFloat128 { + let mut x_u = x.to_bits(); + + let mut x_dd = DoubleDouble::default(); + + let x_exp: u16 = ((x_u >> 52) & 0x7ff) as u16; + + if x_exp >= EXP_BIAS { + // |x| >= 1 + if x_u >= 0x4650_0000_0000_0000u64 { + x_dd.hi = x; + } else { + x_dd = DoubleDouble::from_exact_add(x, 1.0); + } + } else { + // |x| < 1 + x_dd = DoubleDouble::from_exact_add(1.0, x); + } + + const EXP_BIAS: u16 = (1u16 << (11 - 1u16)) - 1u16; + + // At this point, x_dd is the exact sum of 1 + x: + // x_dd.hi + x_dd.lo = x + 1.0 exactly. + // |x_dd.hi| >= 2^-54 + // |x_dd.lo| < ulp(x_dd.hi) + + let xhi_bits = x_dd.hi.to_bits(); + let xhi_frac = xhi_bits & ((1u64 << 52) - 1); + x_u = xhi_bits; + // Range reduction: + // Find k such that |x_hi - k * 2^-7| <= 2^-8. + let idx: i32 = ((xhi_frac.wrapping_add(1u64 << (52 - 8))) >> (52 - 7)) as i32; + let x_e = (get_exponent_f64(f64::from_bits(xhi_bits)) as i32).wrapping_add(idx >> 7); + + // Scale x_dd by 2^(-xh_bits.get_exponent()). + let s_u: i64 = (x_u & EXP_MASK) as i64 - (EXP_BIAS as i64).wrapping_shl(52); + // Normalize arguments: + // 1 <= m_dd.hi < 2 + // |m_dd.lo| < 2^-52. + // This is exact. + let m_hi = 1f64.to_bits() | xhi_frac; + + let m_lo = if x_dd.lo.abs() > x_dd.hi * f64::from_bits(0x3800000000000000) { + (x_dd.lo.to_bits() as i64).wrapping_sub(s_u) + } else { + 0 + }; + + let m_dd = DoubleDouble::new(f64::from_bits(m_lo as u64), f64::from_bits(m_hi)); + + // Perform range reduction: + // r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1 + // = (r * m_dd.hi - 1) + r * m_dd.lo + // = v_hi + (v_lo.hi + v_lo.lo) + // where: + // v_hi = r * m_dd.hi - 1 (exact) + // v_lo.hi + v_lo.lo = r * m_dd.lo (exact) + // Bounds on the values: + // -0x1.69000000000edp-8 < r * m - 1 < 0x1.7f00000000081p-8 + // |v_lo.hi| <= |r| * |m_dd.lo| < 2^-52 + // |v_lo.lo| < ulp(v_lo.hi) <= 2^(-52 - 53) = 2^(-105) + let r = R1[idx as usize]; + let v_hi; + let v_lo = DoubleDouble::from_exact_mult(m_dd.lo, f64::from_bits(r)); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v_hi = f_fmla(f64::from_bits(r), m_dd.hi, -1.0); // Exact. + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let c = f64::from_bits( + (idx as u64) + .wrapping_shl(52 - 7) + .wrapping_add(0x3FF0_0000_0000_0000u64), + ); + v_hi = f_fmla( + f64::from_bits(r), + m_dd.hi - c, + f64::from_bits(RCM1[idx as usize]), + ); // Exact + } + + // Range reduction output: + // -0x1.69000000000edp-8 < v_hi + v_lo < 0x1.7f00000000081p-8 + // |v_dd.lo| < ulp(v_dd.hi) <= 2^(-7 - 53) = 2^-60 + let mut v_dd = DoubleDouble::from_exact_add(v_hi, v_lo.hi); + v_dd.lo += v_lo.lo; + + log1p_accurate(x_e, idx as usize, v_dd) +} + +/// Computes log(x+1) +/// +/// Max ULP 0.5 +pub fn f_log1p(x: f64) -> f64 { + let mut x_u = x.to_bits(); + + let mut x_dd = DoubleDouble::default(); + + let x_exp: u16 = ((x_u >> 52) & 0x7ff) as u16; + + const EXP_BIAS: u16 = (1u16 << (11 - 1u16)) - 1u16; + + let e = (((x_u >> 52) & 0x7ff) as i32).wrapping_sub(0x3ff); + + if e == 0x400 || x == 0. || x <= -1.0 { + /* case NaN/Inf, +/-0 or x <= -1 */ + if e == 0x400 && x.to_bits() != 0xfffu64 << 52 { + /* NaN or + Inf*/ + return x + x; + } + if x <= -1.0 + /* we use the fact that NaN < -1 is false */ + { + /* log2p(x<-1) is NaN, log2p(-1) is -Inf and raises DivByZero */ + return if x < -1.0 { + f64::NAN + } else { + // x=-1 + f64::NEG_INFINITY + }; + } + return x + x; /* +/-0 */ + } + + let ax = x_u.wrapping_shl(1); + + if ax < 0x7f60000000000000u64 { + // |x| < 0.0625 + // check case x tiny first to avoid spurious underflow in x*x + if ax < 0x7940000000000000u64 { + // |x| < 0x1p-53 + if ax == 0 { + return x; + } + /* we have underflow when |x| < 2^-1022, or when |x| = 2^-1022 and + the result is smaller than 2^-1022 in absolute value */ + let res = dyad_fmla(x.abs(), f64::from_bits(0xbc90000000000000), x); + return res; + } + } + + if x_exp >= EXP_BIAS { + // |x| >= 1 + if x_u >= 0x4650_0000_0000_0000u64 { + x_dd.hi = x; + } else { + x_dd = DoubleDouble::from_exact_add(x, 1.0); + } + } else { + // |x| < 1 + if x_exp < EXP_BIAS - 52 - 1 { + // Quick return when |x| < 2^-53. + // Since log(1 + x) = x - x^2/2 + x^3/3 - ..., + // for |x| < 2^-53, + // x > log(1 + x) > x - x^2 > x(1 - 2^-54) > x - ulp(x)/2 + // Thus, + // log(1 + x) = nextafter(x, -inf) for FE_DOWNWARD, or + // FE_TOWARDZERO and x > 0, + // = x otherwise. + if x == 0.0 { + return x + x; + } + + let tp = 1.0f32; + let tn = -1.0f32; + let rdp = tp - f32::from_bits(0x3d594caf) != tp; + let rdn = tn - f32::from_bits(0x33800000) != tn; + + if x > 0. && rdp { + return f64::from_bits(x_u - 1); + } + + if x < 0. && rdn { + return f64::from_bits(x_u + 1); + } + + return if x + x == 0.0 { x + x } else { x }; + } + x_dd = DoubleDouble::from_exact_add(1.0, x); + } + + // At this point, x_dd is the exact sum of 1 + x: + // x_dd.hi + x_dd.lo = x + 1.0 exactly. + // |x_dd.hi| >= 2^-54 + // |x_dd.lo| < ulp(x_dd.hi) + + let xhi_bits = x_dd.hi.to_bits(); + let xhi_frac = xhi_bits & ((1u64 << 52) - 1); + x_u = xhi_bits; + // Range reduction: + // Find k such that |x_hi - k * 2^-7| <= 2^-8. + let idx: i32 = ((xhi_frac.wrapping_add(1u64 << (52 - 8))) >> (52 - 7)) as i32; + let x_e = (get_exponent_f64(f64::from_bits(xhi_bits)) as i32).wrapping_add(idx >> 7); + let e_x = x_e as f64; + + const LOG_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d2ef35793c76730), + f64::from_bits(0x3fe62e42fefa3800), + ); + + // hi is exact + // ulp(hi) = ulp(LOG_2_HI) = ulp(LOG_R1_DD[idx].hi) = 2^-43 + + let r_dd = LOG_R1_DD[idx as usize]; + + let hi = f_fmla(e_x, LOG_2.hi, f64::from_bits(r_dd.1)); + // lo errors < |e_x| * ulp(LOG_2_LO) + ulp(LOG_R1[idx].lo) + // <= 2^11 * 2^(-43-53) = 2^-85 + let lo = f_fmla(e_x, LOG_2.lo, f64::from_bits(r_dd.0)); + + // Scale x_dd by 2^(-xh_bits.get_exponent()). + let s_u: i64 = (x_u & EXP_MASK) as i64 - (EXP_BIAS as i64).wrapping_shl(52); + // Normalize arguments: + // 1 <= m_dd.hi < 2 + // |m_dd.lo| < 2^-52. + // This is exact. + let m_hi = 1f64.to_bits() | xhi_frac; + + let m_lo = if x_dd.lo.abs() > x_dd.hi * f64::from_bits(0x3800000000000000) { + (x_dd.lo.to_bits() as i64).wrapping_sub(s_u) + } else { + 0 + }; + + let m_dd = DoubleDouble::new(f64::from_bits(m_lo as u64), f64::from_bits(m_hi)); + + // Perform range reduction: + // r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1 + // = (r * m_dd.hi - 1) + r * m_dd.lo + // = v_hi + (v_lo.hi + v_lo.lo) + // where: + // v_hi = r * m_dd.hi - 1 (exact) + // v_lo.hi + v_lo.lo = r * m_dd.lo (exact) + // Bounds on the values: + // -0x1.69000000000edp-8 < r * m - 1 < 0x1.7f00000000081p-8 + // |v_lo.hi| <= |r| * |m_dd.lo| < 2^-52 + // |v_lo.lo| < ulp(v_lo.hi) <= 2^(-52 - 53) = 2^(-105) + let r = R1[idx as usize]; + let v_hi; + let v_lo = DoubleDouble::from_exact_mult(m_dd.lo, f64::from_bits(r)); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v_hi = f_fmla(f64::from_bits(r), m_dd.hi, -1.0); // Exact. + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let c = f64::from_bits( + (idx as u64) + .wrapping_shl(52 - 7) + .wrapping_add(0x3FF0_0000_0000_0000u64), + ); + v_hi = f_fmla( + f64::from_bits(r), + m_dd.hi - c, + f64::from_bits(RCM1[idx as usize]), + ); // Exact + } + + // Range reduction output: + // -0x1.69000000000edp-8 < v_hi + v_lo < 0x1.7f00000000081p-8 + // |v_dd.lo| < ulp(v_dd.hi) <= 2^(-7 - 53) = 2^-60 + let mut v_dd = DoubleDouble::from_exact_add(v_hi, v_lo.hi); + v_dd.lo += v_lo.lo; + + // Exact sum: + // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u + let r1 = DoubleDouble::from_exact_add(hi, v_dd.hi); + + // Degree-7 minimax polynomial log(1 + v) ~ v - v^2 / 2 + ... + // generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 6, [|1, 1, D...|], + // [-0x1.69000000000edp-8, 0x1.7f00000000081p-8]); + const P_COEFFS: [u64; 6] = [ + 0xbfe0000000000000, + 0x3fd5555555555166, + 0xbfcfffffffdb7746, + 0x3fc99999a8718a60, + 0xbfc555874ce8ce22, + 0x3fc24335555ddbe5, + ]; + + // C * ulp(v_sq) + err_hi + let v_sq = v_dd.hi * v_dd.hi; + let p0 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[1]), + f64::from_bits(P_COEFFS[0]), + ); + let p1 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[3]), + f64::from_bits(P_COEFFS[2]), + ); + let p2 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[5]), + f64::from_bits(P_COEFFS[4]), + ); + let p = f_polyeval4(v_sq, (v_dd.lo + r1.lo) + lo, p0, p1, p2); + + const ERR_HI: [f64; 2] = [f64::from_bits(0x3aa0000000000000), 0.0]; + let err_hi = ERR_HI[if hi == 0.0 { 1 } else { 0 }]; + + let err = f_fmla(v_sq, f64::from_bits(0x3ce0000000000000), err_hi); + + let left = r1.hi + (p - err); + let right = r1.hi + (p + err); + // Ziv's test to see if fast pass is accurate enough. + if left == right { + return left; + } + log1p_accurate_dd(x) +} + +#[cold] +fn log1p_accurate_dd(x: f64) -> f64 { + log1p_dd(x).to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log1p() { + assert_eq!( + f_log1p(-0.0000000000000003834186599935256), + -0.00000000000000038341865999352564 + ); + assert_eq!(f_log1p(0.000032417476177515677), 0.000032416950742490306); + assert_eq!(f_log1p(-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001866527236137164), + -0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001866527236137164); + assert_eq!(f_log1p(-0.0016481876264151651), -0.0016495473819346394); + assert_eq!(f_log1p(-0.55), -0.7985076962177717); + assert_eq!(f_log1p(-0.65), -1.0498221244986778); + assert_eq!(f_log1p(1.65), 0.9745596399981308); + assert!(f_log1p(-2.).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dd.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,258 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::dd_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::log_dd::log_poly; +use crate::logs::log_dd_coeffs::LOG_NEG_DD; +use crate::polyeval::{f_estrin_polyeval7, f_polyeval3}; +use crate::pow_tables::POW_INVERSE; + +#[inline(always)] +pub(crate) fn log1p_tiny(z: f64) -> DoubleDouble { + // See ./notes/log1p_tiny.sollya for generation + const Q_1: [(u64, u64); 7] = [ + (0xbc85555555555555, 0x3fd5555555555556), + (0x0000000000000000, 0xbfd0000000000000), + (0xbc6999999999999a, 0x3fc999999999999a), + (0x3c75555555555555, 0xbfc5555555555556), + (0x3c62492492492492, 0x3fc2492492492492), + (0x0000000000000000, 0xbfc0000000000000), + (0x3c5c71c71c71c71c, 0x3fbc71c71c71c71c), + ]; + let mut r = DoubleDouble::quick_mul_f64_add_f64( + DoubleDouble::from_bit_pair(Q_1[6]), + z, + f64::from_bits(0xbfc0000000000000), + ); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(Q_1[4])); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(Q_1[3])); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(Q_1[2])); + r = DoubleDouble::quick_mul_f64_add_f64(r, z, f64::from_bits(0xbfd0000000000000)); + r = DoubleDouble::quick_mul_f64_add(r, z, DoubleDouble::from_bit_pair(Q_1[0])); + r = DoubleDouble::quick_mul_f64_add_f64(r, z, f64::from_bits(0xbfe0000000000000)); + r = DoubleDouble::quick_mul_f64_add_f64(r, z, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::quick_mult_f64(r, z) +} + +#[inline(always)] +fn log1p_poly_fast(z: f64) -> DoubleDouble { + // Polynomial generated by Sollya + // d = [-0.0040283203125,0.0040283203125]; + // f = log(1+x); + // p0 = x-x^2/2; + // w = 1; + // pf = p0+fpminimax(f-p0, [|3,4,5,6,7,8,9|], [|D...|], d, absolute, floating); + // See ./notes/dd_log1p_fast.sollya + const Q: [f64; 7] = [ + f64::from_bits(0x3fd5555555555556), + f64::from_bits(0xbfcfffffffffffdc), + f64::from_bits(0x3fc99999998fd488), + f64::from_bits(0xbfc5555555d90fc7), + f64::from_bits(0x3fc24936d06d3bf8), + f64::from_bits(0xbfbfff46726d8e88), + f64::from_bits(0x3fa1847e2faea348), + ]; + let x2 = DoubleDouble::from_exact_mult(z, z); + let p = f_estrin_polyeval7(z, Q[0], Q[1], Q[2], Q[3], Q[4], Q[5], Q[6]); + let mut t = DoubleDouble::quick_mult_f64(x2, p); + t = DoubleDouble::quick_mult_f64(t, z); + DoubleDouble::mul_f64_add(x2, -0.5, t) +} + +#[inline(always)] +fn log1p_tiny_fast(z: f64) -> DoubleDouble { + // Polynomial generated by Sollya + // d = [-2^-12,2^-12]; + // f = log(1+x); + // p0 = x-x^2/2; + // w = 1; + // pf = p0+fpminimax(f-p0, [|3,4,5,6|], [|107, D...|], d, absolute, floating); + // See ./notes/dd_log1p_tiny_fast.sollya + let x2 = DoubleDouble::from_exact_mult(z, z); + let p = f_polyeval3( + z, + f64::from_bits(0xbfcffffffffffff4), + f64::from_bits(0x3fc99999b4d2481f), + f64::from_bits(0xbfc55555714a3cb8), + ); + let DoubleDouble { hi: h, lo: r } = DoubleDouble::from_exact_mult(z, p); + let DoubleDouble { hi: ph, lo: q } = DoubleDouble::add_f64( + DoubleDouble::from_bit_pair((0xbc77e8068b994170, 0x3fd5555555555551)), + h, + ); + let p = DoubleDouble::new(r + q, ph); + let mut t = DoubleDouble::quick_mult(x2, p); + t = DoubleDouble::quick_mult_f64(t, z); + let f = DoubleDouble::f64_add(z, DoubleDouble::mul_f64_add(x2, -0.5, t)); + DoubleDouble::from_exact_add(f.hi, f.lo) +} + +#[inline] +pub(crate) fn log1p_dd(z: f64) -> DoubleDouble { + let ax = z.to_bits().wrapping_shl(1); + if ax < 0x7e60000000000000u64 { + // |x| < 0x1p-12 + return log1p_tiny(z); + } + let dz = DoubleDouble::from_full_exact_add(z, 1.0); + + // We'll compute log((z+1)+1) as log(xh+xl) = log(xh) + log(1+xl/xh). + // since xl/xh < ulp(xh) we'll use for log(1+xl/xh) + // one taylor term what means that log(1+xl/xh) = log_lo + O(x^2) + + let log_lo = if dz.hi <= f64::from_bits(0x7fd0000000000000) || dz.lo.abs() >= 4.0 { + dz.lo / dz.hi + } else { + 0. + }; // avoid spurious underflow + + let x_u = dz.hi.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(LOG_NEG_DD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let tt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let v = DoubleDouble::full_add_f64(tt, z); + let mut p = log_poly(z); + // adding log(1+xl/xh) lower term + p.lo += log_lo; + DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)) +} + +#[inline] +pub(crate) fn log1p_fast_dd(z: f64) -> DoubleDouble { + let ax = z.to_bits().wrapping_shl(1); + if ax < 0x7e60000000000000u64 { + // |x| < 2^-12 + return log1p_tiny_fast(z); + } + let dz = DoubleDouble::from_full_exact_add(z, 1.0); + + // We'll compute log((z+1)+1) as log(xh+xl) = log(xh) + log(1+xl/xh). + // since xl/xh < ulp(xh) we'll use for log(1+xl/xh) + // one taylor term what means that log(1+xl/xh) = log_lo + O(x^2) + + let log_lo = if dz.hi <= f64::from_bits(0x7fd0000000000000) || dz.lo.abs() >= 4.0 { + dz.lo / dz.hi + } else { + 0. + }; // avoid spurious underflow + + let x_u = dz.hi.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(LOG_NEG_DD[(i - 181) as usize]); + + let z = dd_fmla(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let tt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let v = DoubleDouble::full_add_f64(tt, z); + let mut p = log1p_poly_fast(z); + // adding log(1+xl/xh) lower term + p.lo += log_lo; + DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log1p_dyadic_tables::{LOG1P_R1, LOG1P_R2, LOG1P_S2, LOG1P_S3, LOGP1_R3}; + +#[cold] +pub(crate) fn log1p_accurate(e_x: i32, index: usize, m_x: DoubleDouble) -> DyadicFloat128 { + // Minimax polynomial generated by Sollya with: + // > P = fpminimax((log(1 + x) - x)/x^2, 3, [|1, 128...|], + // [-0x1.01928p-22 , 0x1p-22]); + // > P; + // > dirtyinfnorm(log(1 + x)/x - 1 - x*P, [-0x1.01928p-22 , 0x1p-22]); + // 0x1.ce1e...p-116 + const BIG_COEFFS: [DyadicFloat128; 4] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xccccccd7_4818e397_7ed78465_d460315b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x80000000_000478b0_c6388a23_871ce156_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaaaaaaaa_aaaaaaaa_aa807bd8_67763262_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, + ]; + + // log(2) with 128-bit precision generated by SageMath with: + // def format_hex(value): + // l = hex(value)[2:] + // n = 4 + // x = [l[i:i + n] for i in range(0, len(l), n)] + // return "0x" + "_".join(x) + "_u128" + // (s, m, e) = RealField(128)(2).log().sign_mantissa_exponent(); + // print(format_hex(m)); + const LOG_2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb172_17f7_d1cf_79ab_c9e3_b398_03f2_f6af_u128, + }; + + let e_x_f128 = DyadicFloat128::new_from_f64(e_x as f64); + let mut sum = LOG_2 * e_x_f128; + sum = sum + LOG1P_R1[index]; + + let mut v = DyadicFloat128::new_from_f64(m_x.hi) + DyadicFloat128::new_from_f64(m_x.lo); + + // Skip 2nd range reduction step if |m_x| <= 2^-15. + if m_x.hi > f64::from_bits(0x3f00000000000000) || m_x.hi < f64::from_bits(0xbf00000000000000) { + // Range reduction - Step 2. + // For k such that: k * 2^-14 - 2^-15 <= m_x.hi < k * 2^-14 + 2^-15, + // Let s_k = 2^-18 * round( 2^18 / (1 + k*2^-14) ) - 1 + // Then the 2nd reduced argument is: + // (1 + s_k) * (1 + m_x) - 1 = + // = s_k + m_x + s_k * m_x + // Output range: + // -0x1.1037c00000040271p-15 <= v2.hi + v2.lo <= 0x1.108480000008096cp-15 + let idx2: i32 = (f64::from_bits(0x40d0000000000000) + * (m_x.hi + + (91. * f64::from_bits(0x3f10000000000000) + f64::from_bits(0x3f00000000000000)))) + as i32; + sum = sum + LOG1P_R2[idx2 as usize]; + let s2 = DyadicFloat128::new_from_f64(f64::from_bits(LOG1P_S2[idx2 as usize])); + v = (v + s2) + (v * s2); + } + + // Skip 3rd range reduction step if |v| <= 2^-22. + if v.exponent > -150 { + // Range reduction - Step 3. + // For k such that: k * 2^-21 - 2^-22 <= v2.hi < k * 2^-21 + 2^-22, + // Let s_k = 2^-21 * round( 2^21 / (1 + k*2^-21) ) - 1 + // Then the 3rd reduced argument is: + // v3.hi + v3.lo ~ (1 + s_k) * (1 + v2.hi + v2.lo) - 1 + // Output range: + // -0x1.012bb800000800114p-22 <= v3.hi + v3.lo <= 0x1p-22 + let zv = v.fast_as_f64(); + let idx3 = (f64::from_bits(0x4140000000000000) + * (zv + + (69. * f64::from_bits(0x3ea0000000000000) + f64::from_bits(0x3e90000000000000)))) + as i32; + sum = sum + LOGP1_R3[idx3 as usize]; + let s3 = DyadicFloat128::new_from_f64(f64::from_bits(LOG1P_S3[idx3 as usize])); + v = (v + s3) + (v * s3); + } + + let mut p = v * BIG_COEFFS[0]; + p = v * (p + BIG_COEFFS[1]); + p = v * (p + BIG_COEFFS[2]); + p = v * (p + BIG_COEFFS[3]); + p = v + (v * p); + + sum + p +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1p_dyadic_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,865 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +// Logarithm range reduction - Step 3: +// s(k) = 2^-21 round( 2^21 / (1 + k*2^-21) ) - 1 for k = -69 .. 69 +// Output range: +// [-0x1.012bb800000800114p-22, 0x1p-22 ] +pub(crate) static LOG1P_S3: [u64; 139] = [ + 0x3f01400000000000, + 0x3f01000000000000, + 0x3f00c00000000000, + 0x3f00800000000000, + 0x3f00400000000000, + 0x3f00000000000000, + 0x3eff800000000000, + 0x3eff000000000000, + 0x3efe800000000000, + 0x3efe000000000000, + 0x3efd800000000000, + 0x3efd000000000000, + 0x3efc800000000000, + 0x3efc000000000000, + 0x3efb800000000000, + 0x3efb000000000000, + 0x3efa800000000000, + 0x3efa000000000000, + 0x3ef9800000000000, + 0x3ef9000000000000, + 0x3ef8800000000000, + 0x3ef8000000000000, + 0x3ef7800000000000, + 0x3ef7000000000000, + 0x3ef6800000000000, + 0x3ef6000000000000, + 0x3ef5800000000000, + 0x3ef5000000000000, + 0x3ef4800000000000, + 0x3ef4000000000000, + 0x3ef3800000000000, + 0x3ef3000000000000, + 0x3ef2800000000000, + 0x3ef2000000000000, + 0x3ef1800000000000, + 0x3ef1000000000000, + 0x3ef0800000000000, + 0x3ef0000000000000, + 0x3eef000000000000, + 0x3eee000000000000, + 0x3eed000000000000, + 0x3eec000000000000, + 0x3eeb000000000000, + 0x3eea000000000000, + 0x3ee9000000000000, + 0x3ee8000000000000, + 0x3ee7000000000000, + 0x3ee6000000000000, + 0x3ee5000000000000, + 0x3ee4000000000000, + 0x3ee3000000000000, + 0x3ee2000000000000, + 0x3ee1000000000000, + 0x3ee0000000000000, + 0x3ede000000000000, + 0x3edc000000000000, + 0x3eda000000000000, + 0x3ed8000000000000, + 0x3ed6000000000000, + 0x3ed4000000000000, + 0x3ed2000000000000, + 0x3ed0000000000000, + 0x3ecc000000000000, + 0x3ec8000000000000, + 0x3ec4000000000000, + 0x3ec0000000000000, + 0x3eb8000000000000, + 0x3eb0000000000000, + 0x3ea0000000000000, + 0x0000000000000000, + 0xbea0000000000000, + 0xbeb0000000000000, + 0xbeb8000000000000, + 0xbec0000000000000, + 0xbec4000000000000, + 0xbec8000000000000, + 0xbecc000000000000, + 0xbed0000000000000, + 0xbed2000000000000, + 0xbed4000000000000, + 0xbed6000000000000, + 0xbed8000000000000, + 0xbeda000000000000, + 0xbedc000000000000, + 0xbede000000000000, + 0xbee0000000000000, + 0xbee1000000000000, + 0xbee2000000000000, + 0xbee3000000000000, + 0xbee4000000000000, + 0xbee5000000000000, + 0xbee6000000000000, + 0xbee7000000000000, + 0xbee8000000000000, + 0xbee9000000000000, + 0xbeea000000000000, + 0xbeeb000000000000, + 0xbeec000000000000, + 0xbeed000000000000, + 0xbeee000000000000, + 0xbeef000000000000, + 0xbef0000000000000, + 0xbef0800000000000, + 0xbef1000000000000, + 0xbef1800000000000, + 0xbef2000000000000, + 0xbef2800000000000, + 0xbef3000000000000, + 0xbef3800000000000, + 0xbef4000000000000, + 0xbef4800000000000, + 0xbef5000000000000, + 0xbef5800000000000, + 0xbef6000000000000, + 0xbef6800000000000, + 0xbef7000000000000, + 0xbef7800000000000, + 0xbef8000000000000, + 0xbef8800000000000, + 0xbef9000000000000, + 0xbef9800000000000, + 0xbefa000000000000, + 0xbefa800000000000, + 0xbefb000000000000, + 0xbefb800000000000, + 0xbefc000000000000, + 0xbefc800000000000, + 0xbefd000000000000, + 0xbefd800000000000, + 0xbefe000000000000, + 0xbefe800000000000, + 0xbeff000000000000, + 0xbeff800000000000, + 0xbf00000000000000, + 0xbf00400000000000, + 0xbf00800000000000, + 0xbf00c00000000000, + 0xbf01000000000000, + 0xbf01400000000000, +]; + +// Logarithm range reduction - Step 2: +// s(k) = 2^-18 round( 2^18 / (1 + k*2^-14) ) - 1 for k = -91 .. 96 +// Output range: +// [-0x1.1037c00000040271p-15 , 0x1.108480000008096cp-15] +pub(crate) static LOG1P_S2: [u64; 188] = [ + 0x3f76e00000000000, + 0x3f76a00000000000, + 0x3f76600000000000, + 0x3f76200000000000, + 0x3f75dc0000000000, + 0x3f759c0000000000, + 0x3f755c0000000000, + 0x3f751c0000000000, + 0x3f74dc0000000000, + 0x3f749c0000000000, + 0x3f74580000000000, + 0x3f74180000000000, + 0x3f73d80000000000, + 0x3f73980000000000, + 0x3f73580000000000, + 0x3f73180000000000, + 0x3f72d80000000000, + 0x3f72940000000000, + 0x3f72540000000000, + 0x3f72140000000000, + 0x3f71d40000000000, + 0x3f71940000000000, + 0x3f71540000000000, + 0x3f71140000000000, + 0x3f70d00000000000, + 0x3f70900000000000, + 0x3f70500000000000, + 0x3f70100000000000, + 0x3f6fa00000000000, + 0x3f6f200000000000, + 0x3f6ea00000000000, + 0x3f6e200000000000, + 0x3f6d980000000000, + 0x3f6d180000000000, + 0x3f6c980000000000, + 0x3f6c180000000000, + 0x3f6b980000000000, + 0x3f6b180000000000, + 0x3f6a980000000000, + 0x3f6a180000000000, + 0x3f69980000000000, + 0x3f69100000000000, + 0x3f68900000000000, + 0x3f68100000000000, + 0x3f67900000000000, + 0x3f67100000000000, + 0x3f66900000000000, + 0x3f66100000000000, + 0x3f65900000000000, + 0x3f65100000000000, + 0x3f64900000000000, + 0x3f64100000000000, + 0x3f63880000000000, + 0x3f63080000000000, + 0x3f62880000000000, + 0x3f62080000000000, + 0x3f61880000000000, + 0x3f61080000000000, + 0x3f60880000000000, + 0x3f60080000000000, + 0x3f5f100000000000, + 0x3f5e100000000000, + 0x3f5d100000000000, + 0x3f5c100000000000, + 0x3f5b100000000000, + 0x3f5a100000000000, + 0x3f59100000000000, + 0x3f58100000000000, + 0x3f57100000000000, + 0x3f56000000000000, + 0x3f55000000000000, + 0x3f54000000000000, + 0x3f53000000000000, + 0x3f52000000000000, + 0x3f51000000000000, + 0x3f50000000000000, + 0x3f4e000000000000, + 0x3f4c000000000000, + 0x3f4a000000000000, + 0x3f48000000000000, + 0x3f46000000000000, + 0x3f44000000000000, + 0x3f42000000000000, + 0x3f40000000000000, + 0x3f3c000000000000, + 0x3f38000000000000, + 0x3f34000000000000, + 0x3f30000000000000, + 0x3f28000000000000, + 0x3f20000000000000, + 0x3f10000000000000, + 0x0000000000000000, + 0xbf10000000000000, + 0xbf20000000000000, + 0xbf28000000000000, + 0xbf30000000000000, + 0xbf34000000000000, + 0xbf38000000000000, + 0xbf3c000000000000, + 0xbf40000000000000, + 0xbf42000000000000, + 0xbf44000000000000, + 0xbf46000000000000, + 0xbf48000000000000, + 0xbf4a000000000000, + 0xbf4c000000000000, + 0xbf4e000000000000, + 0xbf50000000000000, + 0xbf51000000000000, + 0xbf52000000000000, + 0xbf53000000000000, + 0xbf54000000000000, + 0xbf55000000000000, + 0xbf56000000000000, + 0xbf56f00000000000, + 0xbf57f00000000000, + 0xbf58f00000000000, + 0xbf59f00000000000, + 0xbf5af00000000000, + 0xbf5bf00000000000, + 0xbf5cf00000000000, + 0xbf5df00000000000, + 0xbf5ef00000000000, + 0xbf5ff00000000000, + 0xbf60780000000000, + 0xbf60f80000000000, + 0xbf61780000000000, + 0xbf61f80000000000, + 0xbf62780000000000, + 0xbf62f80000000000, + 0xbf63780000000000, + 0xbf63f00000000000, + 0xbf64700000000000, + 0xbf64f00000000000, + 0xbf65700000000000, + 0xbf65f00000000000, + 0xbf66700000000000, + 0xbf66f00000000000, + 0xbf67700000000000, + 0xbf67f00000000000, + 0xbf68700000000000, + 0xbf68f00000000000, + 0xbf69680000000000, + 0xbf69e80000000000, + 0xbf6a680000000000, + 0xbf6ae80000000000, + 0xbf6b680000000000, + 0xbf6be80000000000, + 0xbf6c680000000000, + 0xbf6ce80000000000, + 0xbf6d680000000000, + 0xbf6de00000000000, + 0xbf6e600000000000, + 0xbf6ee00000000000, + 0xbf6f600000000000, + 0xbf6fe00000000000, + 0xbf70300000000000, + 0xbf70700000000000, + 0xbf70b00000000000, + 0xbf70f00000000000, + 0xbf712c0000000000, + 0xbf716c0000000000, + 0xbf71ac0000000000, + 0xbf71ec0000000000, + 0xbf722c0000000000, + 0xbf726c0000000000, + 0xbf72ac0000000000, + 0xbf72e80000000000, + 0xbf73280000000000, + 0xbf73680000000000, + 0xbf73a80000000000, + 0xbf73e80000000000, + 0xbf74280000000000, + 0xbf74640000000000, + 0xbf74a40000000000, + 0xbf74e40000000000, + 0xbf75240000000000, + 0xbf75640000000000, + 0xbf75a40000000000, + 0xbf75e00000000000, + 0xbf76200000000000, + 0xbf76600000000000, + 0xbf76a00000000000, + 0xbf76e00000000000, + 0xbf77200000000000, + 0xbf775c0000000000, + 0xbf779c0000000000, + 0xbf77dc0000000000, +]; + +//def format_hex(value): +// l = hex(value)[2:] +// n = 8 +// x = [l[i:i + n] for i in range(0, len(l), n)] +// return "0x" + "_".join(x) + "_u128" +// for i in range(129): +// r = 2^-8 * round( 2^8 / (1 + i*2^(-7)) ); +// s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); +// print("DyadicFloat {sign: DyadicDyadicSign::Pos, exponent: ", e, ",mantissa:", format_hex(m), "},"); +#[rustfmt::skip] +pub(crate) static LOG1P_R1: [DyadicFloat128; 129] = [ +DyadicFloat128 {sign: DyadicSign::Pos,exponent: 0, mantissa: 0_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -134,mantissa: 0x8080abac_46f38946_662d417c_ed007a46_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -133,mantissa: 0x8102b2c4_9ac23a4f_91d082dc_e3ddcd38_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -133,mantissa: 0xc2492946_4655f45c_da5f3cc0_b3251dbd_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -132,mantissa: 0x820aec4f_3a222380_b9e3aea6_c444ef07_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -132,mantissa: 0xa33576a1_6f1f4c64_521016bd_904dc968_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -132,mantissa: 0xb3e4a796_a5dac208_27cca0bc_c06c2f92_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -132,mantissa: 0xd5779687_d887e0d1_a9dda170_56e45ed5_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -132,mantissa: 0xf7518e00_35c3dd83_606d8909_3278a939_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0x8cb9de8a_32ab368a_a7c98595_30a45153_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0x9defad3e_8f73217a_976d3b5b_45f6ca0b_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xa6988ae9_03f562ed_3e858f08_597b3a69_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xb8069857_560707a3_6a677b4c_8bec22e1_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xc99af2ea_ca4c4570_eaf51f66_692844ba_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xd273b205_8de1bd49_46bbf837_b4d320c6_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xe442c00d_e2591b47_196ab34c_e0bccd12_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xed393b1c_22351280_3f4e2e66_0317d55f_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -131,mantissa: 0xff4489ce_deab2ca6_c17bd40d_8d9291ec_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0x88bc7411_3f23def1_9c5a0fe3_96f40f1e_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0x8d515bf1_1fb94f1c_88713268_840cbcc0_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0x968b0864_3409ceb6_65c0da50_6a088484_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0x9b2fe580_ac80b17d_411a5b94_4aca8708_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xa489ec19_9dab06f2_a9fb6cf0_ecb411b7_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xa93f2f25_0dac67d1_cad2fb8d_48054ae0_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xadfa035a_a1ed8fdc_149767e4_10316d2c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xb780945b_ab55dce4_34c7bc3d_32750fde_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xbc4c6c2a_226399ef_8f6ebcfb_2016a439_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xc5f57f59_c7f46155_aa8b6997_a402bf30_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xcad2d6e7_b80bf914_2c507fb7_a3d0bf6a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xcfb62038_44b3209a_d0cb02f3_3f79c16c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xd98ec2ba_de71e539_58a98f2a_d65bee9b_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xde8439c1_dec56877_4d57da94_5b5d0aaa_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xe37fde37_807b84e3_4e9a750b_6b68781d_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xe881bf93_2af3dac0_c524848e_3443e040_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xf29877ff_38809091_3b020fa1_820c9492_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xf7ad6f26_e7ff2ef7_54d2238f_75f969b1_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -130,mantissa: 0xfcc8e365_9d9bcbec_ca0cdf30_1431b60f_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x80f572b1_363487b9_f5bd0b5b_3479d5f4_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x86216b3b_0b17188b_163ceae8_8f720f1e_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x88bc7411_3f23def1_9c5a0fe3_96f40f1e_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x8b5ae65d_67db9acd_f7a51681_26a58b9a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x8dfccb1a_d35ca6ed_5147bdb6_ddcaf59c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x90a22b68_75c6a1f7_ae91aeba_609c8877_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x95f783e6_e49a9cfa_4a5004f3_ef063313_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x9b5b3bb5_f088b766_d878bbe3_d392be25_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0x9e1293b9_998c1daa_5b035eae_273a855f_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xa0cda11e_af46390d_bb243827_3918db7e_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xa38c6e13_8e20d831_f698298a_dddd7f32_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xa64f04f0_b961df76_e4f5275c_2d15c21f_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xa9157039_c51ebe70_8164c759_686a2209_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xabdfba9e_468fd6f6_f72ea077_49ce6bd3_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xaeadeefa_caf97d35_7dd6e688_ebb13b03_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xb1801859_d56249dc_18ce51ff_f99479cd_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xb45641f4_e350a0d3_2756eba0_0bc33978_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xb7307735_78cb90b2_be1116c3_466beb6d_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xba0ec3b6_33dd8b09_49dc60b2_b059a60b_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xbcf13343_e7d9ec7d_2efd1778_1bb3afec_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xbfd7d1de_c0a8df6f_37eda996_244bccb0_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xc2c2abbb_6e5fd56f_33337789_d592e296_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xc5b1cd44_596fa51e_1a18fb8f_9f9ef280_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xc8a5431a_dfb44ca5_688ce7c1_a75e341a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xcb9d1a18_9ab56e76_2d7e9307_c70c0668_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xcb9d1a18_9ab56e76_2d7e9307_c70c0668_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xce995f50_af69d861_ef2f3f4f_861ad6a9_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xd19a2011_27d3c645_7f9d79f5_1dcc7301_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xd49f69e4_56cf1b79_5f53bd2e_406e66e7_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xd7a94a92_466e833a_ad88bba7_d0cee8e0_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xdab7d022_31484a92_96c20cca_6efe2ac5_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xddcb08dc_0717d85b_f40a666c_87842843_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xe0e30349_fd1cec80_7fe8e180_2aba24d6_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xe0e30349_fd1cec80_7fe8e180_2aba24d6_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xe3ffce3a_2aa64922_3eadb651_b49ac53a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xe72178c0_323a1a0f_304e1653_e71d9973_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xea481236_f7d35baf_e9a767a8_0d6d97e8_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xed73aa42_64b0ade9_4f91cf4b_33e42998_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xed73aa42_64b0ade9_4f91cf4b_33e42998_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xf0a450d1_39366ca6_fc66eb64_08ff6433_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xf3da161e_ed6b9aaf_ac8d42f7_8d3e65d3_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xf7150ab5_a09f27f4_5a470250_d40ebe90_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xf7150ab5_a09f27f4_5a470250_d40ebe90_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xfa553f70_18c966f2_b780a545_a1b54dcf_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -129,mantissa: 0xfd9ac57b_d244217e_8f05924d_258c14c5_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8072d72d_903d588b_89d1b09c_70c4010a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8072d72d_903d588b_89d1b09c_70c4010a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x821b05f3_b01d6774_030d58c3_f7e2ea1f_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x83c5f829_9e2b4091_20f6fafe_8fbb68b9_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8573b716_82a7d21a_e21f9f89_c1ab80b2_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8573b716_82a7d21a_e21f9f89_c1ab80b2_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x87244c30_8e670a66_01e005d0_6dbfa8f8_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x88d7c11e_3ad53cdc_223111a7_07b6de2c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x88d7c11e_3ad53cdc_223111a7_07b6de2c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8a8e1fb7_94b09134_2eb628db_a173c82d_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8c477207_91e53313_be2ad194_15fe25a5_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8c477207_91e53313_be2ad194_15fe25a5_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8e03c24d_73003959_bddae1cc_ce247838_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8fc31afe_30b2c6de_9b00bf16_7e95da67_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x8fc31afe_30b2c6de_9b00bf16_7e95da67_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x918586c5_f5e4bf01_9b92199e_d1a4bab1_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9513c368_76083695_f3cbc416_a2418012_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x96dfaabd_86fa1646_be1188fb_c94e2f15_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x96dfaabd_86fa1646_be1188fb_c94e2f15_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x98aed221_a03458b6_1d2f8932_1647b358_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x98aed221_a03458b6_1d2f8932_1647b358_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9a81456c_ec642e0f_e549f9aa_ea3cb5e1_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9c5710b8_cbb73a42_a2554b2d_d4619e63_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9c5710b8_cbb73a42_a2554b2d_d4619e63_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9e304061_b5fda919_30603d87_b6df81ad_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0x9e304061_b5fda919_30603d87_b6df81ad_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa00ce109_2e5498c3_67879c5a_30cd1242_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa00ce109_2e5498c3_67879c5a_30cd1242_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa1ecff97_c91e267b_0b7efae0_8e597e16_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa3d0a93f_45169a4a_83594fab_088c0d65_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa3d0a93f_45169a4a_83594fab_088c0d65_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa5b7eb7c_b860fb88_af6a62a0_dec6e073_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa5b7eb7c_b860fb88_af6a62a0_dec6e073_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa7a2d41a_d270c9d7_49362382_a768847a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa7a2d41a_d270c9d7_49362382_a768847a_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa9917134_33c2b998_8ba4aea6_14d05701_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xa9917134_33c2b998_8ba4aea6_14d05701_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xab83d135_dc633301_7fe6607b_a902ef3c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xab83d135_dc633301_7fe6607b_a902ef3c_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xad7a02e1_b24efd31_d60864fd_949b4bd3_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xad7a02e1_b24efd31_d60864fd_949b4bd3_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xaf741551_20c9011c_066d235e_e63073dd_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: -128,mantissa: 0xaf741551_20c9011c_066d235e_e63073dd_u128}, +DyadicFloat128 {sign: DyadicSign::Pos,exponent: 0, mantissa: 0_u128} +]; + +// -log(r) for the second step, generated by SageMath with: +// def format_hex(value): +// l = hex(value)[2:] +// n = 8 +// x = [l[i:i + n] for i in range(0, len(l), n)] +// return "0x" + "_".join(x) + "_u128" +// for i in range(-91, 97): +// r = 2^-18 * round( 2^18 / (1 + i*2^(-14)) ); +// s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); +// print("{sign: DyadicDyadicSign::Pos," if (s == -1) else "{sign: DyadicDyadicSign::Neg, exponent: ", e, ", mantissa: " +// format_hex(m), "},"); +#[rustfmt::skip] +pub(crate) static LOG1P_R2: [DyadicFloat128; 188] = [ + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xb67dab2a_1a5742a4_a0e061c5_f7431c5e_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xb4807f24_af682939_5d5bfe7b_969ed6ec_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xb2834b35_b4d54d5f_4d08702d_dfabc23f_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xb0860f5c_eba9be95_d4d36650_8b9953df_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xae68f71a_a09e8847_ac18a289_f8f214a9_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xac6baaee_d676e8f1_d5b42054_abb88c45_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xaa6e56d8_7cd632d6_09809d58_ee484964_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xa870fad7_54bb8791_b9e6fc7c_72f06d73_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xa67396eb_1f231892_6f78d6d0_105c00e2_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xa4762b13_9d0626e7_028f7126_29209148_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xa258dfd1_0aedaa67_c98d898e_f172df02_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0xa05b63a3_73e60a83_fcc37c3c_3062bfa1_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x9e5ddf89_cf42f501_3eb450db_05763c36_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x9c605383_ddf1b88c_7146a86f_d458b775_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x9a62bf91_60dcb286_c20a0c92_81474436_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x986523b2_18eb4ed6_cdc57316_ec4aebc3_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x96677fe5_c70207b9_c060dad7_4cef4273_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x9449f92d_2ff44633_ed8def1a_3e433499_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x924c4507_3220b5e0_3ce7a1f8_5c27b4fc_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x904e88f3_68fea63f_f2ca8934_49f7f2cb_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x8e50c4f1_956699ed_8d77d9fa_bd2853cf_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x8c52f901_782e20ec_93e828d7_5b58ded4_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x8a552522_d227d87a_9f9605b0_53c5acf0_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x88574955_64236ae0_62a14939_3bca7241_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x86398719_b66bac7c_aea6b56c_e89203d4_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x843b9aef_044e4dcc_0242bd86_d00609b2_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x823da6d4_c89c6927_daabf927_74bac84e_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -135, mantissa: 0x803faaca_c419abf2_a1c6f3fc_242ef8d0_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xfc834da1_6f0d9f57_a225ebc0_2e6d9dd4_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xf88735cc_c7433381_c33f6ad3_40ae18a9_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xf48b0e17_1249b6bc_70b2a4d3_8a242244_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xf08ed67f_d190e280_1d548190_48b811b0_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xec52ca07_ed95f236_9c21b650_afe9ede0_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xe85671ad_ecd28aac_935519c9_6d30e463_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xe45a0970_dc912ca7_ba88f6f2_e2672cfe_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xe05d9150_3e298bc8_0b1a8b84_657ae069_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xdc61094b_92ed70ef_ea3bff8d_197b20a1_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xd8647162_5c28b9e5_cdbb931d_6fecc249_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xd467c994_1b2158f5_d971d560_d5f00820_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xd06b11e0_51175493_75563561_244c090b_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xcc6e4a46_7f44c6fa_dc393c9a_3f3b380f_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xc831a4c6_f6fa709d_e6abe6e9_e4ee2096_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xc434bc61_24a0f16e_3ce3c822_8583a66e_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xc037c413_c61bfd93_b96a79f5_c5a4963a_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xbc3abbde_5c8d9bde_aaef2733_7008679f_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xb83da3c0_6911e509_a49a3fca_ddc8bc5a_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xb4407bb9_6cbf035a_e0254feb_785362fa_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xb04343c8_e8a53245_9893a4e2_5ab9dc95_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xac45fbee_5dcebe0b_5d8b0f40_a3708915_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xa848a429_4d40035d_5f4c11c2_c7a58c69_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xa44b3c79_37f76efd_b348cc5d_f706ffba_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0xa04dc4dd_9eed7d60_9159f2c5_5a18befd_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x9c106456_3058bef3_bdfdee41_fe6a5a02_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x9812cbe3_46475a24_4580ddf8_9853254d_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x94152383_53489ffb_ac75e10d_61fc3ee8_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x90176b35_d83ce8e2_cad9b30b_29736155_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x8c19a2fa_55fe9b14_6f881deb_98fc45f3_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x881bcad0_4d622a3e_70a04b63_b7248c96_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x841de2b7_3f361722_b4823fb4_8035eddd_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -136, mantissa: 0x801feaae_ac42ef38_3364ccb5_b13cd47f_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xf843c56c_2a969897_e306977b_049f0ad5_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xf0479599_f617a843_e3c4d9e9_619bc045_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xe84b45e5_bc76702c_4356d525_b5e6432d_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xe04ed64e_7f14697a_7839dcd7_989339ab_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xd85246d3_3f47230b_4e21f045_ecb76f23_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xd0559772_fe5840b0_902e248d_d4ba9b28_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xc858c82c_bd857a72_a4444906_7ef92e01_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xc05bd8ff_7e009bd2_17926207_cc22e4e6_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xb85ec9ea_40ef8309_1c349622_f3fa5d82_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xafe1c6ec_e1a058dd_97fa2fd0_c9dc723e_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0xa7e47606_048b1a65_983e8089_7cf1e60f_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0x9fe70534_1d236102_7199cd06_ae5d39b3_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0x97e97476_2c5e8f58_43cd18a7_2a051a96_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0x8febc3cb_332616ff_7b6d1248_c3e1fd40_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -137, mantissa: 0x87edf332_325777c5_f5572a88_14c703af_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xffe00554_55887de0_26828c92_649a3a39_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xefe3e464_3a640cf3_82c550bd_1216d82a_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xdfe78392_14b4e8ae_da6959f7_f0e01bf0_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xcfeae2db_e5d6736d_da93e2fa_85a8f214_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xbfee023f_af0c2480_b47505bf_a5a03b06_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0xaff0e1bb_718186ad_b1475a51_80a43520_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0x9ff3814d_2e4a36b2_a8740b91_c95df537_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -138, mantissa: 0x8ff5e0f2_e661e1c6_57d895d3_5921b59c_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -139, mantissa: 0xfff00155_35588833_3c56c598_c659c2a3_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -139, mantissa: 0xdff3c0e4_97ea4eb1_2ef8ec33_ed9d782a_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -139, mantissa: 0xbff7008f_f5e0c257_379eba7e_6465ff63_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -139, mantissa: 0x9ff9c053_5073a370_3f972b78_3fcab757_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -140, mantissa: 0xfff80055_51558885_de026e27_1ee0549d_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -140, mantissa: 0xbffb8023_febc0c25_eceb47ea_01f6c632_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -141, mantissa: 0xfffc0015_54d55888_7333c578_57e1ed52_u128}, + DyadicFloat128 { sign: DyadicSign::Neg, exponent: -142, mantissa: 0xfffe0005_55455588_87dde026_fa704374_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: 0, mantissa: 0_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -141, mantissa: 0x80010002_aab2aac4_44999abe_2fe2cc65_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -140, mantissa: 0x8002000a_aaeaac44_4eef3815_81464ccb_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -140, mantissa: 0xc0048024_01440c26_dfeb4850_85f6f454_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -139, mantissa: 0x8004002a_acaac445_99abe3be_3a1c6e93_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -139, mantissa: 0xa0064053_5a37a37a_6bc1e20e_ac8448b4_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -139, mantissa: 0xc0090090_0a20c275_979eedc0_64c242fd_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -139, mantissa: 0xe00c40e4_bd6e4efd_c72446cc_1bf728bd_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0x800800aa_baac446e_f381b821_bbb569e5_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0x900a20f3_19a3e273_569b26aa_a485ea5c_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xa00c814d_7c6a37f8_2dcf56c8_3c80b028_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xb00f21bb_e3e388ee_5f697682_84463b9b_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xc0120240_510c284c_b48ea6c0_5e2773a1_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xd01522dc_c4f87991_14d9d761_96d8043a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xe0188393_40d4f241_e016a611_a4415d72_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -138, mantissa: 0xf01c2465_c5e61b6f_661e135f_49a47c40_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0x801002ab_2ac4499a_be6bf0fa_435e8383_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0x88121333_7898871e_9a31ba0c_bc030353_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0x901443cc_cd362c9f_54b57dfe_0c4c840f_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0x98169478_296fad41_7ad1e9c3_15328f7e_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xa0190536_8e2389b3_1f3f686c_f3d6be22_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xa81b9608_fc3c50ec_f105b66e_c4703ede_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xb01e46f0_74b0a0f3_610848c6_8df4d233_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xb7a0e9ed_7613acb0_2e0efddf_33a20464_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xbfa3d900_8e042ffb_c2cdb3c7_50f127b4_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xc7a6e82b_a36a7073_bd953378_6d3f4c49_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xcfaa176f_b76c8eb1_82e237c9_a4d450e3_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xd7ad66cd_cb3cbe14_c00b46a4_d0e3dfd0_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xdfb0d646_e0194584_ea999c0d_f8546710_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xe7b465db_f74c8032_cec6c2a9_ad974f4f_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xefb8158e_122cde5a_2d2045da_1570a07c_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xf7bbe55e_321ce603_6752e9b2_381e3edc_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -137, mantissa: 0xffbfd54d_588b33c5_3c1ed527_28e00e40_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x83e1f2ae_43793dc3_493b0d87_3fb9a340_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x87e40ac6_5f6cc4a0_29e38750_c9d26893_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x8be632ef_80e9a0df_aab9e832_7258ac3f_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x8fe86b2a_28bf51b3_28bc403d_8a5f3c63_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x93eab376_d7c36377_f720c1c9_7227fcdc_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x97ed0bd6_0ed17018_6ad9a3e3_d11b66c1_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x9bef7448_4ecb1f6c_edb27b79_c90b4019_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0x9fb1c4cd_27012e19_a092a0d7_ab21722a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xa3b44c65_b71c2d85_535d52f0_939a4d02_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xa7b6e412_cadcb3dc_90a57e11_edc1864e_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xabb98bd4_e33c4381_68e9c901_60031159_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xafbc43ac_813a6ea3_bf60594f_929adeb8_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xb3bf0b9a_25dcd7a2_8a421588_86775205_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xb7c1e39e_522f316d_1ab45417_663dee9e_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xbbc4cbb9_87433fe4_6c51ae3c_e1aea68a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xbfc7c3ec_4630d83c_7c52ae8b_40ebabb7_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xc3cacc37_1015e15d_a857126f_7cfaaa67_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xc7cde49a_66165446_14d05662_cd29464a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xcb90da16_44d29bb7_8379db06_ef3cd6bb_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xcf9411aa_99ddb7de_9025f4c6_7dd38bb6_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xd3975958_f681086d_d6f8a61c_892032ee_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xd79ab121_dbf8714c_9a2f20b4_e2332d47_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xdb9e1905_cb85ea59_3c767d61_f51d375b_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xdfa19105_46717fca_d4b2bd65_bb25493c_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xe3a51920_ce095292_c96c1254_a30ef91f_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xe7a8b158_e3a198be_73e324ce_0946b214_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xebac59ae_08949dd8_cacd125a_12bac62c_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xef6fd620_b2b7a503_cafdc272_27b71eaa_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xf3739daf_959aaafc_688d4282_f6026aa3_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xf777755d_03f4e0b6_e54e9e38_04464cdd_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xfb7b5d29_7f388a12_cb78b383_f4b59dce_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -136, mantissa: 0xff7f5515_88de024f_ee055fc5_15062c04_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x81c1ae90_d131de38_207812b4_3382acdd_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x83c3baa7_26a721cc_dc90c4c4_b61f3a87_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x85c5cece_05941dbc_1a03f13f_b2c978b1_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x87c7eb05_aec1304f_b36f282e_83a7dc36_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x89a9eccd_56a980c0_d82a4661_6d4c393f_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x8bac18a6_40185360_bc6ff847_13c9babd_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x8dae4c90_b22574f4_9f7942a5_16fc2d8a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x8fb0888c_eda546ab_15e50cfd_9b29b427_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x91b2cc9b_336f3718_9f465296_ae7dd49a_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x93b518bb_c45dc268_b49c1eb9_b348e6e4_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x95b76cee_e14e728e_daa320cd_64c9d9c7_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x9799a333_de49b963_75a91950_ffe1e3b5_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x999c070b_a32068cd_5c6abcbf_43f03f14_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x9b9e72f6_b295ad4f_5a9e7f26_5d1ed157_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x9da0e6f5_4d9318fd_efeb98d0_2a195c17_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0x9fa36307_b5054ca8_2aa503a3_110ab5a7_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xa1a5e72e_29dbf808_d0fe7e05_869eb825_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xa3884a68_a750cb10_e80a28f4_e1e500d2_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xa58ade36_aeef9f0b_53106415_1ca6e30b_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xa78d7a19_82c4b08f_27c01ffa_8e2e3c4b_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xa9901e11_63cbbbf5_7ba9408d_c857d568_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xab92ca1e_93038d76_104d1e33_31d3b4fa_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xad957e41_516e0158_9343c846_fcdf9137_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xaf780e79_b2514889_3977e89a_ec59bfa2_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xb17ad246_ef3713bc_913d4e3d_c55c3e6e_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xb37d9e2a_7a56b09d_777b52a9_e70d8bcc_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xb5807224_94be0c91_55de916f_d30591de_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xb7834e35_7f7e2600_e79cfb37_be2861e4_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xb986325d_7bab0c89_90983104_d3805389_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xbb68ef9c_254aa378_59e3b2ec_71ce64f4_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xbd6be371_8c77636f_e83183bf_3dd612ef_u128}, + DyadicFloat128 { sign: DyadicSign::Pos, exponent: -135, mantissa: 0xbf6edf5e_c44d9d35_c4e3b0ac_2fd52b7f_u128}, +]; + +// -log(r) for the third step, generated by SageMath with: +// +// for i in range(-69, 70): +// r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) ); +// s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); +// print("{sign: DyadicDyadicSign::Pos," if (s == -1) else "{sign: DyadicDyadicSign::Neg, exponent: ", e, ", mantissa:" +// format_hex(m), "},"); +#[rustfmt::skip] +pub(crate) static LOGP1_R3: [DyadicFloat128; 139] =[ + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -142, mantissa: 0x89ff6b38_d5de2622_e39d3faf_42340ed7_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -142, mantissa: 0x87ff6f80_ccb40f16_7ff33266_82c02485_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -142, mantissa: 0x85ff73b8_c3cdf731_5caf4fbe_343cf928_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -142, mantissa: 0x83ff77e0_bb2ade79_cdb6e554_348f7fe8_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -142, mantissa: 0x81ff7bf8_b2c9c4f6_0ef009c2_457de25d_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xffff0001_55535558_8883333c_57b57c74_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xfbff07f1_45931f44_f32668f3_9c70d183_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xf7ff0fc1_3650e7bd_459a73c6_a6486fe3_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xf3ff1771_278aaecd_37b18cca_7dd3a29f_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xefff1f01_193e7480_513f610d_21bcfc78_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xebff2671_0b6a38e1_ea190b95_c0690b7b_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xe7ff2dc0_fe0bfbfd_2a150f64_f0ad1743_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xe3ff34f0_f121bddd_090b5174_e995e9d1_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xdfff3c00_e4a97e8c_4ed512b9_b93ea2bf_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xdbff42f0_d8a13e15_934cea21_7ab794a2_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xd7ff49c0_cd06fc83_3e4ebe94_8afd2c76_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xd3ff5070_c1d8b9df_87b7c0f5_bcfee2e1_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xcfff5700_b7147634_77666622_8cb6371b_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xcbff5d70_acb8318b_e53a60f3_514db358_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xc7ff63c0_a2c1ebef_79149c3b_6e57fa86_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xc3ff69f0_992fa568_aad734c9_8416df2a_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xbfff7000_8fff5e00_c2657367_9ed28334_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xbbff75f0_872f15c0_d7a3c6db_6540809f_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xb7ff7bc0_7ebcccb1_d277bde6_45fb1aad_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xb3ff8170_76a682dc_6ac80145_a4087793_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xafff8700_6eea3849_287c4db3_0271e265_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xabff8c70_6785ed00_637d6de4_2eeb151e_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xa7ff91c0_6077a10a_43b5348b_6b898a8c_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0xa3ff96f0_59bd546e_c10e7657_978bd7f6_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x9fff9c00_53550735_a37503f4_57310e59_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x9bffa0f0_4d3cb966_82d5a40a_3aa022ff_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x97ffa5c0_47726b08_c71e0d3e_e3df5f4d_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x93ffaa70_41f41c23_a83ce035_2bdbd79b_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x8fffaf00_3cbfccbe_2e21a18d_4680e8e4_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x8bffb370_37d37cdf_30bcb3e4_e5dfbd28_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x87ffb7c0_332d2c8d_57ff51d7_5c66d64a_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -143, mantissa: 0x83ffbbf0_2ecadbcf_1bdb87fd_be299f43_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xffff8000_55551555_88885dde_02700703_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xf7ff87e0_4d94724c_d259ca80_3a0c1870_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xefff8f80_464fce8f_e5141308_51c7070a_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xe7ff96e0_3f832a2a_30a16898_f3073a64_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xdfff9e00_392a8526_c4ed6451_7b2949ce_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xd7ffa4e0_3341df90_51e4fb4e_32cf6350_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xcfffab80_2dc53971_277672a8_8350bcce_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xc7ffb1e0_28b092d3_35915377_2a490f06_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xbfffb800_23ffebc0_0c265ece_6b481a0e_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xb7ffbde0_1faf4440_db2781c0_3fa132f6_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xafffc380_1bba9c5e_7287c95c_845ada33_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0xa7ffc8e0_181df421_423b56b1_263e5a77_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0x9fffce00_14d54b91_5a3752ca_4c076fa3_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0x97ffd2e0_11dca2b6_6a71e2b2_7eb3f573_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0x8fffd780_0f2ff997_c2e21b72_cff39d8f_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -144, mantissa: 0x87ffdbe0_0ccb503c_537ff612_feb7ac9e_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xffffc000_15554d55_58888733_33c57c18_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xefffc7c0_1193f9d1_fa514218_42311c42_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xdfffcf00_0e4aa5fa_2c4ed6de_475b942c_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xcfffd5c0_0b7151d8_ce77678c_bb6fcb88_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xbfffdc00_08fffd78_00c26629_a679ed3b_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0xafffe1c0_06eea8e1_23287cb9_d3072728_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0x9fffe700_0535541c_d5a37540_fd057315_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -145, mantissa: 0x8fffebc0_03cbff32_f82e21c1_fce36810_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -146, mantissa: 0xffffe000_05555455_5588887d_dde02702_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -146, mantissa: 0xdfffe780_0392aa14_9ac4ed72_adf5b295_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -146, mantissa: 0xbfffee00_023fffaf_000c2664_8066b482_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -146, mantissa: 0x9ffff380_014d552e_455a3754_b292c077_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -147, mantissa: 0xfffff000_01555535_55588888_33333c58_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -147, mantissa: 0xbffff700_008ffff5_e000c266_5736679f_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -148, mantissa: 0xfffff800_00555551_55558888_85ddde02_u128}, + DyadicFloat128 {sign: DyadicSign::Neg, exponent: -149, mantissa: 0xfffffc00_00155554_d5555888_88733334_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: 0, mantissa: 0_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -148, mantissa: 0x80000200_000aaaaa_eaaaac44_444eeeef_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -147, mantissa: 0x80000400_002aaaac_aaaac444_459999ac_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -147, mantissa: 0xc0000900_0090000a_2000c266_7596679f_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -146, mantissa: 0x80000800_00aaaaba_aaac4444_6eeef381_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -146, mantissa: 0xa0000c80_014d557c_655a3755_f81815cc_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -146, mantissa: 0xc0001200_02400051_000c2668_4c66b482_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -146, mantissa: 0xe0001880_0392ab40_bac4ed7c_40fb07eb_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0x80001000_02aaab2a_aac44449_999abe2c_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0x90001440_03cc00cd_082e21d7_9cbb6812_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xa0001900_0535568d_d5a37569_adb01dc3_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xb0001e40_06eeac74_33287d01_e8c9d1d9_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xc0002400_09000288_00c266a3_2679ed48_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xd0002a40_0b7158d1_de776851_22b2764b_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xe0003100_0e4aaf5b_2c4ed810_a8063f03_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -145, mantissa: 0xf0003840_1194062e_0a5143e7_be891c8f_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0x80002000_0aaaaeaa_ac4444ee_ef3813a1_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0x88002420_0ccb5a6e_5b7ff7fe_1339025b_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0x90002880_0f300668_42e21e26_caf39e33_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0x98002d20_11dcb29e_f271e66f_a5554bc6_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xa0003200_14d55f19_5a3757e0_615cc676_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xa8003720_181e0bde_ca3b5d82_10ca5cab_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xb0003c80_1bbab8f6_f287d25f_3cb032bb_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xb8004220_1faf6669_e3278d84_0be28cdb_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xc0004800_24001440_0c266dfe_6b482076_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xc8004e20_28b0c282_3d9166de_380a6d3d_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xd0005480_2dc57139_a7768b35_6ba61e4b_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xd8005b20_3342206f_d9e51a18_49db73c1_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xe0006200_392ad02e_c4ed8a9d_907eb521_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xe8006920_3f838080_b8a197de_a928acd7_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xf0007080_46503170_65144cf7_dcc72d3b_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -144, mantissa: 0xf8007820_4d94e308_da5a1108_890d9f6a_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x80004000_2aaacaaa_c4445999_abe2ce2c_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x84004410_2ecb2431_1fdbbb4f_3bffc832_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x88004840_332d7e1d_97ff8f39_ec91b4ee_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x8c004c90_37d3d876_74bcfcf0_b3f0a95d_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x90005100_3cc03342_2e21f80c_a6813aff_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x94005590_41f48e87_6c3d4629_170ce87f_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x98005a40_4772ea4d_071e84e3_b80a8881_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0x9c005f10_4d3d469a_06d62fdc_bdd6bec3_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xa0006400_5355a375_a375a6b7_01dc77c0_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xa4006910_59be00e7_450f3318_26ad6b05_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xa8006e40_60785ef6_83b60ea8_bd0aa459_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xac007390_6786bdab_277e6914_69dd13f5_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xb0007900_6eeb1d0d_287d6e0a_0d1e25eb_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xb4007e90_76a77d24_aec94b3b_e9b060f5_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xb8008440_7ebdddfa_1279365f_ce280cce_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xbc008a10_87303f95_dba5732f_3e83e04a_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xc0009000_9000a200_c2675967_9ed5b754_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xc4009610_99310543_aed95aca_5edb5109_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xc8009c40_a2c36967_b917091d_2687160f_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xcc00a290_acb9ce76_293d1c2a_0378e75d_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xd000a900_b7163478_776977bf_9766f5a7_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xd400af90_c1da9b78_4bbb31b1_4776a18b_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xd800b640_cd09037f_7e5297d7_6c8564ba_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xdc00bd10_d8a36c98_1751360f_8461c447_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xe000c400_e4abd6cc_4ed9dc3c_63f44c41_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xe400cb10_f1244226_8d10a446_6a5894d5_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xe800d240_fe0eaeb1_6a1af81b_b4e6510e_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xec00d991_0b6d1c77_ae1f97b0_542a677a_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xf000e101_19418b84_51469efe_81d014cc_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xf400e891_278dfbe2_7bb98c06_d77a18b4_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xf800f041_36546d9d_85a344d0_868bed17_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -143, mantissa: 0xfc00f811_4596e0c0_f7301d69_90e307cc_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x80008000_aaabaaac_4446eef3_8140138f_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x82008408_b2cbe5b8_10f5e432_96105497_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x84008820_bb2d2189_edbd4f83_ef63f730_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x86008c48_c3d05e27_feb654fd_541c638e_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x88009080_ccb69b98_7ffadeb8_882f7674_u128}, + DyadicFloat128 {sign: DyadicSign::Pos, exponent: -142, mantissa: 0x8a0094c8_d5e0d9e1_c5a59fd3_6bd44397_u128}, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::logs::{LOG_R_DD, LOG_RANGE_REDUCTION}; +use crate::polyeval::{f_estrin_polyeval8, f_polyeval6}; + +#[inline] +pub(crate) fn core_logf(x: f64) -> f64 { + let x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + let e_x = x_e as f64; + + const LOG_2_HI: f64 = f64::from_bits(0x3fe62e42fefa3800); + const LOG_2_LO: f64 = f64::from_bits(0x3d2ef35793c76730); + + let log_r_dd = LOG_R_DD[index as usize]; + + // hi is exact + let hi = f_fmla(e_x, LOG_2_HI, f64::from_bits(log_r_dd.1)); + let lo = f_fmla(e_x, LOG_2_LO, f64::from_bits(log_r_dd.0)); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + let r1 = hi; + // Polynomial for log(1+x)/x generated in Sollya: + // d = [-2^-8, 2^-7]; + // f_log = log(1 + x)/x; + // Q = fpminimax(f_log, 5, [|D...|], d); + // See ./notes/log1pf_core.sollya + let p = f_polyeval6( + u, + f64::from_bits(0x3fefffffffffffff), + f64::from_bits(0xbfdffffffffff3e6), + f64::from_bits(0x3fd5555555626b74), + f64::from_bits(0xbfd0000026aeecc8), + f64::from_bits(0x3fc9999114d16c06), + f64::from_bits(0xbfc51e433a85278a), + ); + f_fmla(p, u, r1) + lo +} + +/// Computes log(x+1) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_log1pf(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + return x; + } + if x.is_infinite() { + return if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NAN + }; + } + return x + f32::NAN; + } + + let xd = x as f64; + let ax = x.to_bits() & 0x7fff_ffffu32; + + // Use log1p(x) = log(1 + x) for |x| > 2^-6; + if ax > 0x3c80_0000u32 { + if x == -1. { + return f32::NEG_INFINITY; + } + let x1p = xd + 1.; + if x1p <= 0. { + if x1p == 0. { + return f32::NEG_INFINITY; + } + return f32::NAN; + } + return core_logf(x1p) as f32; + } + + // log(1+x) is expected to be used near zero + // Polynomial generated by Sollya: + // d = [-2^-6; 2^-6]; + // f_log1pf = log(1+x)/x; + // Q = fpminimax(f_log1pf, 7, [|0, D...|], d); + // See ./notes/log1pf.sollya + + let p = f_estrin_polyeval8( + xd, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfe0000000000000), + f64::from_bits(0x3fd5555555556aad), + f64::from_bits(0xbfd000000000181a), + f64::from_bits(0x3fc999998998124e), + f64::from_bits(0xbfc55555452e2a2b), + f64::from_bits(0x3fc24adb8cde4aa7), + f64::from_bits(0xbfc0019db915ef6f), + ) * xd; + p as f32 +} + +#[inline] +pub(crate) fn core_log1pf(x: f32) -> f64 { + let xd = x as f64; + let ax = x.to_bits() & 0x7fff_ffffu32; + + // Use log1p(x) = log(1 + x) for |x| > 2^-6; + if ax > 0x3c80_0000u32 { + let x1p = xd + 1.; + return core_logf(x1p); + } + + // log(1+x) is expected to be used near zero + // Polynomial generated by Sollya: + // d = [-2^-6; 2^-6]; + // f_log1pf = log(1+x)/x; + // Q = fpminimax(f_log1pf, 7, [|0, D...|], d); + // See ./notes/log1pf.sollya + + f_estrin_polyeval8( + xd, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfe0000000000000), + f64::from_bits(0x3fd5555555556aad), + f64::from_bits(0xbfd000000000181a), + f64::from_bits(0x3fc999998998124e), + f64::from_bits(0xbfc55555452e2a2b), + f64::from_bits(0x3fc24adb8cde4aa7), + f64::from_bits(0xbfc0019db915ef6f), + ) * xd +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn log1pf_works() { + assert!(f_log1pf(f32::from_bits(0xffefb9a7)).is_nan()); + assert!(f_log1pf(f32::NAN).is_nan()); + assert_eq!(f_log1pf(f32::from_bits(0x41078feb)), 2.2484074); + assert_eq!(f_log1pf(-0.0000014305108), -0.0000014305118); + assert_eq!(f_log1pf(0.0), 0.0); + assert_eq!(f_log1pf(2.0), 1.0986123); + assert_eq!(f_log1pf(-0.7), -1.2039728); + assert_eq!(f_log1pf(-0.0000000000043243), -4.3243e-12); + assert_eq!(f_log1pf(f32::INFINITY), f32::INFINITY); + assert!(f_log1pf(-2.0).is_nan()); + assert!(f_log1pf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pmx.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmx.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pmx.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmx.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,392 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::{EXP_MASK, get_exponent_f64}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::logs::log1p::{LOG_R1_DD, R1}; +use crate::logs::log1p_dd; +use crate::polyeval::{f_estrin_polyeval8, f_polyeval4, f_polyeval5}; + +#[cold] +fn tiny_hard(x: f64) -> f64 { + // d = [-2^-10; 2^-10]; + // f_log1pf = (log(1+x) - x)/x^2; + // Q = fpminimax(f_log1pf, 7, [|0, 107...|], d); + // See ./notes/log1pmx_at_zero_hard.sollya + + let x2 = DoubleDouble::from_exact_mult(x, x); + + const C: [(u64, u64); 7] = [ + (0x3c755555555129de, 0x3fd5555555555555), + (0xbbd333352fe28400, 0xbfd0000000000000), + (0xbc698cb3ef1ea2dd, 0x3fc999999999999a), + (0x3c4269700b3f95d0, 0xbfc55555555546ef), + (0x3c61290e9261823e, 0x3fc2492492491565), + (0x3c6fb0a243c2a59c, 0xbfc000018af8cb7e), + (0x3c3b271ceb5c60a0, 0x3fbc71ca10b30518), + ]; + + let mut r = DoubleDouble::mul_f64_add( + DoubleDouble::from_bit_pair(C[6]), + x, + DoubleDouble::from_bit_pair(C[5]), + ); + r = DoubleDouble::mul_f64_add(r, x, DoubleDouble::from_bit_pair(C[4])); + r = DoubleDouble::mul_f64_add(r, x, DoubleDouble::from_bit_pair(C[3])); + r = DoubleDouble::mul_f64_add(r, x, DoubleDouble::from_bit_pair(C[2])); + r = DoubleDouble::mul_f64_add(r, x, DoubleDouble::from_bit_pair(C[1])); + r = DoubleDouble::mul_f64_add(r, x, DoubleDouble::from_bit_pair(C[0])); + r = DoubleDouble::mul_f64_add_f64(r, x, f64::from_bits(0xbfe0000000000000)); + r = DoubleDouble::quick_mult(r, x2); + r.to_f64() +} + +fn log1pmx_big(x: f64) -> f64 { + let mut x_u = x.to_bits(); + + let mut x_dd = DoubleDouble::default(); + + let x_exp: u16 = ((x_u >> 52) & 0x7ff) as u16; + + const EXP_BIAS: u16 = (1u16 << (11 - 1u16)) - 1u16; + + if x_exp >= EXP_BIAS { + // |x| >= 1 + if x_u >= 0x4650_0000_0000_0000u64 { + x_dd.hi = x; + } else { + x_dd = DoubleDouble::from_exact_add(x, 1.0); + } + } else { + // |x| < 1 + x_dd = DoubleDouble::from_exact_add(1.0, x); + } + + // At this point, x_dd is the exact sum of 1 + x: + // x_dd.hi + x_dd.lo = x + 1.0 exactly. + // |x_dd.hi| >= 2^-54 + // |x_dd.lo| < ulp(x_dd.hi) + + let xhi_bits = x_dd.hi.to_bits(); + let xhi_frac = xhi_bits & ((1u64 << 52) - 1); + x_u = xhi_bits; + // Range reduction: + // Find k such that |x_hi - k * 2^-7| <= 2^-8. + let idx: i32 = ((xhi_frac.wrapping_add(1u64 << (52 - 8))) >> (52 - 7)) as i32; + let x_e = (get_exponent_f64(f64::from_bits(xhi_bits)) as i32).wrapping_add(idx >> 7); + let e_x = x_e as f64; + + const LOG_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d2ef35793c76730), + f64::from_bits(0x3fe62e42fefa3800), + ); + + // hi is exact + // ulp(hi) = ulp(LOG_2_HI) = ulp(LOG_R1_DD[idx].hi) = 2^-43 + + let r_dd = LOG_R1_DD[idx as usize]; + + let hi = f_fmla(e_x, LOG_2.hi, f64::from_bits(r_dd.1)); + // lo errors < |e_x| * ulp(LOG_2_LO) + ulp(LOG_R1[idx].lo) + // <= 2^11 * 2^(-43-53) = 2^-85 + let lo = f_fmla(e_x, LOG_2.lo, f64::from_bits(r_dd.0)); + + // Scale x_dd by 2^(-xh_bits.get_exponent()). + let s_u: i64 = (x_u & EXP_MASK) as i64 - (EXP_BIAS as i64).wrapping_shl(52); + // Normalize arguments: + // 1 <= m_dd.hi < 2 + // |m_dd.lo| < 2^-52. + // This is exact. + let m_hi = 1f64.to_bits() | xhi_frac; + + let m_lo = if x_dd.lo.abs() > x_dd.hi * f64::from_bits(0x3800000000000000) { + (x_dd.lo.to_bits() as i64).wrapping_sub(s_u) + } else { + 0 + }; + + let m_dd = DoubleDouble::new(f64::from_bits(m_lo as u64), f64::from_bits(m_hi)); + + // Perform range reduction: + // r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1 + // = (r * m_dd.hi - 1) + r * m_dd.lo + // = v_hi + (v_lo.hi + v_lo.lo) + // where: + // v_hi = r * m_dd.hi - 1 (exact) + // v_lo.hi + v_lo.lo = r * m_dd.lo (exact) + // Bounds on the values: + // -0x1.69000000000edp-8 < r * m - 1 < 0x1.7f00000000081p-8 + // |v_lo.hi| <= |r| * |m_dd.lo| < 2^-52 + // |v_lo.lo| < ulp(v_lo.hi) <= 2^(-52 - 53) = 2^(-105) + let r = R1[idx as usize]; + let v_hi; + let v_lo = DoubleDouble::from_exact_mult(m_dd.lo, f64::from_bits(r)); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v_hi = f_fmla(f64::from_bits(r), m_dd.hi, -1.0); // Exact. + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log1p::RCM1; + let c = f64::from_bits( + (idx as u64) + .wrapping_shl(52 - 7) + .wrapping_add(0x3FF0_0000_0000_0000u64), + ); + v_hi = f_fmla( + f64::from_bits(r), + m_dd.hi - c, + f64::from_bits(RCM1[idx as usize]), + ); // Exact + } + + // Range reduction output: + // -0x1.69000000000edp-8 < v_hi + v_lo < 0x1.7f00000000081p-8 + // |v_dd.lo| < ulp(v_dd.hi) <= 2^(-7 - 53) = 2^-60 + let mut v_dd = DoubleDouble::from_exact_add(v_hi, v_lo.hi); + v_dd.lo += v_lo.lo; + + // Exact sum: + // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u + let mut r1 = DoubleDouble::from_exact_add(hi, v_dd.hi); + + // Degree-7 minimax polynomial log(1 + v) ~ v - v^2 / 2 + ... + // generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 6, [|1, 1, D...|], + // [-0x1.69000000000edp-8, 0x1.7f00000000081p-8]); + const P_COEFFS: [u64; 6] = [ + 0xbfe0000000000000, + 0x3fd5555555555166, + 0xbfcfffffffdb7746, + 0x3fc99999a8718a60, + 0xbfc555874ce8ce22, + 0x3fc24335555ddbe5, + ]; + + // C * ulp(v_sq) + err_hi + let v_sq = v_dd.hi * v_dd.hi; + let p0 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[1]), + f64::from_bits(P_COEFFS[0]), + ); + let p1 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[3]), + f64::from_bits(P_COEFFS[2]), + ); + let p2 = f_fmla( + v_dd.hi, + f64::from_bits(P_COEFFS[5]), + f64::from_bits(P_COEFFS[4]), + ); + let p = f_polyeval4(v_sq, (v_dd.lo + r1.lo) + lo, p0, p1, p2); + + const ERR_HI: [f64; 2] = [f64::from_bits(0x3aa0000000000000), 0.0]; + let err_hi = ERR_HI[if hi == 0.0 { 1 } else { 0 }]; + + let err = f_fmla(v_sq, f64::from_bits(0x3ce0000000000000), err_hi); + + r1.lo = p; + r1 = DoubleDouble::from_exact_add(r1.hi, r1.lo); + r1 = DoubleDouble::full_add_f64(r1, -x); + + let left = r1.hi + (r1.lo - err); + let right = r1.hi + (r1.lo + err); + // Ziv's test to see if fast pass is accurate enough. + if left == right { + return left; + } + log1pmx_accurate_dd(x) +} + +#[cold] +fn log1pmx_accurate_dd(x: f64) -> f64 { + let r = log1p_dd(x); + DoubleDouble::full_add_f64(r, -x).to_f64() +} + +/// Computes log(1+x) - x +/// +/// ulp 0.5 +pub fn f_log1pmx(x: f64) -> f64 { + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffffu64; + + let x_e = (x.to_bits() >> 52) & 0x7ff; + + if !x.is_normal() { + if x.is_nan() { + return x + x; + } + if x.is_infinite() { + return f64::NAN; + } + if x == 0. { + return x; + } + } + + if ax > 0x3f90000000000000u64 { + // |x| > 2^-6 + if x <= -1. { + if x == -1. { + return f64::NEG_INFINITY; + } + return f64::NAN; + } + return log1pmx_big(x); + } + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + // log(1+x) is expected to be used near zero + + if x_e < E_BIAS - 10 { + if x_e < E_BIAS - 100 { + // |x| < 2^-100 + // taylor series log(1+x) - x ~ -x^2/2 + x^3/3 + let x2 = x * x; + let dx2 = f_fmla(x, x, -x2); + let rl = dx2 * -0.5; + return f_fmla(x2, -0.5, rl); + } + + // Polynomial generated by Sollya in form log(1+x) - x = x^2 * R(x): + // d = [-2^-10; 2^-10]; + // f_log1pf = (log(1+x) - x)/x^2; + // Q = fpminimax(f_log1pf, 7, [|0, 107, 107, D...|], d); + // See ./notes/log1pmx_at_zero.sollya + + let p = f_polyeval5( + x, + f64::from_bits(0x3fc999999999999a), + f64::from_bits(0xbfc55555555546ef), + f64::from_bits(0x3fc24924923d3abf), + f64::from_bits(0xbfc000018af7f637), + f64::from_bits(0x3fbc72984db24b6a), + ); + + let x2 = DoubleDouble::from_exact_mult(x, x); + + let mut r = DoubleDouble::f64_mul_f64_add( + x, + p, + DoubleDouble::from_bit_pair((0xbbd3330899095800, 0xbfd0000000000000)), + ); + r = DoubleDouble::mul_f64_add( + r, + x, + DoubleDouble::from_bit_pair((0x3c75555538509407, 0x3fd5555555555555)), + ); + r = DoubleDouble::mul_f64_add_f64(r, x, f64::from_bits(0xbfe0000000000000)); + r = DoubleDouble::quick_mult(r, x2); + const ERR: f64 = f64::from_bits(0x3af0000000000000); // 2^-80 + let ub = r.hi + (r.lo + ERR); + let lb = r.hi + (r.lo - ERR); + if lb == ub { + return r.to_f64(); + } + return tiny_hard(x); + } + + // Polynomial generated by Sollya in form log(1+x) - x = x^2 * R(x): + // d = [-2^-6; 2^-6]; + // f_log1pf = (log(1+x) - x)/x^2; + // Q = fpminimax(f_log1pf, 10, [|0, 107, 107, D...|], d); + // See ./notes/log1pmx.sollya + + let p = f_estrin_polyeval8( + x, + f64::from_bits(0x3fc9999999999997), + f64::from_bits(0xbfc5555555555552), + f64::from_bits(0x3fc249249249fb64), + f64::from_bits(0xbfc000000000f450), + f64::from_bits(0x3fbc71c6e2591149), + f64::from_bits(0xbfb999995cf14d86), + f64::from_bits(0x3fb7494eb6c2c544), + f64::from_bits(0xbfb558bf05690e85), + ); + + let x2 = DoubleDouble::from_exact_mult(x, x); + + let mut r = DoubleDouble::f64_mul_f64_add( + x, + p, + DoubleDouble::from_bit_pair((0xbb9d89dc15a38000, 0xbfd0000000000000)), + ); + r = DoubleDouble::mul_f64_add( + r, + x, + DoubleDouble::from_bit_pair((0x3c7555a15a94e505, 0x3fd5555555555555)), + ); + r = DoubleDouble::mul_f64_add_f64(r, x, f64::from_bits(0xbfe0000000000000)); + r = DoubleDouble::quick_mult(r, x2); + + r.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log1pmx() { + assert_eq!( + f_log1pmx(0.00000000000000005076835735015165), + -0.0000000000000000000000000000000012887130540163486 + ); + assert_eq!(f_log1pmx(5.), -3.208240530771945); + assert_eq!(f_log1pmx(-0.99), -3.6151701859880907); + assert_eq!(f_log1pmx(-1.), f64::NEG_INFINITY); + assert_eq!( + f_log1pmx(1.0000000000008708e-13), + -0.0000000000000000000000000050000000000083744 + ); + assert_eq!( + f_log1pmx(1.0000000000008708e-26), + -0.00000000000000000000000000000000000000000000000000005000000000008707 + ); + assert_eq!(f_log1pmx(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012890176556069385), + -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830783258233204); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pmxf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmxf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log1pmxf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log1pmxf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::polyeval::f_estrin_polyeval7; + +/// Computes log(1+x) - x +/// +/// ulp 0.5 +pub fn f_log1pmxf(x: f32) -> f32 { + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + return x; + } + if x.is_infinite() { + return f32::NAN; + } + return x + f32::NAN; + } + + let ax = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // Use log1p(x) = log(1 + x) for |x| > 2^-6; + if ax > 0x3c80_0000u32 { + if x == -1. { + return f32::NEG_INFINITY; + } + let x1p = xd + 1.; + if x1p <= 0. { + if x1p == 0. { + return f32::NEG_INFINITY; + } + return f32::NAN; + } + return (crate::logs::log1pf::core_logf(x1p) - xd) as f32; + } + + // log(1+x) is expected to be used near zero + // Polynomial generated by Sollya in form log(1+x) - x = x^2 * R(x): + // d = [-2^-6; 2^-6]; + // f_log1pf = (log(1+x) - x)/x^2; + // Q = fpminimax(f_log1pf, 6, [|0, D...|], d); + // See ./notes/log1pmxf.sollya + + let xd_sqr = xd * xd; + let p = f_estrin_polyeval7( + xd, + f64::from_bits(0xbfe0000000000000), + f64::from_bits(0x3fd55555555561c8), + f64::from_bits(0xbfd0000000000f5a), + f64::from_bits(0x3fc999998d26deab), + f64::from_bits(0xbfc555554878739c), + f64::from_bits(0x3fc24ab2e3c10eca), + f64::from_bits(0xbfc0017973fafec4), + ) * xd_sqr; + p as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log1pmxfm() { + assert_eq!(f_log1pmxf(-0.0000014305108), -1.0231815e-12); + assert_eq!(f_log1pmxf(0.0), 0.0); + assert_eq!(f_log1pmxf(2.0), -0.9013877); + assert_eq!(f_log1pmxf(-0.7), -0.50397277); + assert_eq!( + f_log1pmxf(-0.0000000000043243), + -0.000000000000000000000009349785 + ); + assert!(f_log1pmxf(f32::INFINITY).is_nan()); + assert!(f_log1pmxf(f32::NAN).is_nan()); + assert!(f_log1pmxf(f32::NEG_INFINITY).is_nan()); + assert!(f_log1pmxf(-2.0).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,678 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, min_normal_f64}; +use crate::double_double::DoubleDouble; +use crate::logs::log2dd::log2_dd; +use crate::logs::log2td::log2_td; +use crate::polyeval::f_polyeval6; + +pub(crate) static LOG_RANGE_REDUCTION: [u64; 128] = [ + 0x3ff0000000000000, + 0x3fefc00000000000, + 0x3fef800000000000, + 0x3fef400000000000, + 0x3fef000000000000, + 0x3feec00000000000, + 0x3fee800000000000, + 0x3fee400000000000, + 0x3fee000000000000, + 0x3fede00000000000, + 0x3feda00000000000, + 0x3fed600000000000, + 0x3fed400000000000, + 0x3fed000000000000, + 0x3fecc00000000000, + 0x3feca00000000000, + 0x3fec600000000000, + 0x3fec400000000000, + 0x3fec000000000000, + 0x3febe00000000000, + 0x3feba00000000000, + 0x3feb800000000000, + 0x3feb400000000000, + 0x3feb200000000000, + 0x3feae00000000000, + 0x3feac00000000000, + 0x3fea800000000000, + 0x3fea600000000000, + 0x3fea400000000000, + 0x3fea000000000000, + 0x3fe9e00000000000, + 0x3fe9c00000000000, + 0x3fe9800000000000, + 0x3fe9600000000000, + 0x3fe9400000000000, + 0x3fe9200000000000, + 0x3fe9000000000000, + 0x3fe8c00000000000, + 0x3fe8a00000000000, + 0x3fe8800000000000, + 0x3fe8600000000000, + 0x3fe8400000000000, + 0x3fe8000000000000, + 0x3fe7e00000000000, + 0x3fe7c00000000000, + 0x3fe7a00000000000, + 0x3fe7800000000000, + 0x3fe7600000000000, + 0x3fe7400000000000, + 0x3fe7200000000000, + 0x3fe7000000000000, + 0x3fe6e00000000000, + 0x3fe6c00000000000, + 0x3fe6a00000000000, + 0x3fe6800000000000, + 0x3fe6600000000000, + 0x3fe6400000000000, + 0x3fe6200000000000, + 0x3fe6000000000000, + 0x3fe5e00000000000, + 0x3fe5c00000000000, + 0x3fe5a00000000000, + 0x3fe5800000000000, + 0x3fe5600000000000, + 0x3fe5400000000000, + 0x3fe5400000000000, + 0x3fe5200000000000, + 0x3fe5000000000000, + 0x3fe4e00000000000, + 0x3fe4c00000000000, + 0x3fe4a00000000000, + 0x3fe4a00000000000, + 0x3fe4800000000000, + 0x3fe4600000000000, + 0x3fe4400000000000, + 0x3fe4200000000000, + 0x3fe4000000000000, + 0x3fe4000000000000, + 0x3fe3e00000000000, + 0x3fe3c00000000000, + 0x3fe3a00000000000, + 0x3fe3a00000000000, + 0x3fe3800000000000, + 0x3fe3600000000000, + 0x3fe3400000000000, + 0x3fe3400000000000, + 0x3fe3200000000000, + 0x3fe3000000000000, + 0x3fe3000000000000, + 0x3fe2e00000000000, + 0x3fe2c00000000000, + 0x3fe2c00000000000, + 0x3fe2a00000000000, + 0x3fe2800000000000, + 0x3fe2800000000000, + 0x3fe2600000000000, + 0x3fe2400000000000, + 0x3fe2400000000000, + 0x3fe2200000000000, + 0x3fe2000000000000, + 0x3fe2000000000000, + 0x3fe1e00000000000, + 0x3fe1c00000000000, + 0x3fe1c00000000000, + 0x3fe1a00000000000, + 0x3fe1a00000000000, + 0x3fe1800000000000, + 0x3fe1600000000000, + 0x3fe1600000000000, + 0x3fe1400000000000, + 0x3fe1400000000000, + 0x3fe1200000000000, + 0x3fe1000000000000, + 0x3fe1000000000000, + 0x3fe0e00000000000, + 0x3fe0e00000000000, + 0x3fe0c00000000000, + 0x3fe0c00000000000, + 0x3fe0a00000000000, + 0x3fe0a00000000000, + 0x3fe0800000000000, + 0x3fe0800000000000, + 0x3fe0600000000000, + 0x3fe0600000000000, + 0x3fe0400000000000, + 0x3fe0400000000000, + 0x3fe0200000000000, + 0x3fe0000000000000, +]; + +/** +Generated by SageMath: +```python +values = LOG_RANGE_REDUCTION + +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_double_double("", -RealField(180)(r).log2()) +``` +**/ +static LOG2_DD: [(u64, u64); 128] = [ + (0x0, 0x0), + (0x3c26d746128b1857, 0x3f872c7ba20f7327), + (0x3c2b2a41b08fbe06, 0x3f9743ee861f3556), + (0x3c3491f06c085bc2, 0x3fa184b8e4c56af8), + (0x3c477970e03f821c, 0x3fa77394c9d958d5), + (0x3c0155660710eb2a, 0x3fad6ebd1f1febfe), + (0x3c298c5452bbce74, 0x3fb1bb32a600549d), + (0x3c2c141e66faaaad, 0x3fb4c560fe68af88), + (0x3c59ced1447e30ad, 0x3fb7d60496cfbb4c), + (0xbc321ba488a62577, 0x3fb960caf9abb7ca), + (0xbc17936311889913, 0x3fbc7b528b70f1c5), + (0xbc36cd4d2ae3a2f6, 0x3fbf9c95dc1d1165), + (0x3c55d243efd93259, 0x3fc097e38ce60649), + (0xbc5696e2866c718e, 0x3fc22dadc2ab3497), + (0xbc67a6ed4e1b0936, 0x3fc3c6fb650cde51), + (0xbc61562d61af73f8, 0x3fc494f863b8df35), + (0x3c354fae008fbb59, 0x3fc633a8bf437ce1), + (0xbc60798d1aa21694, 0x3fc7046031c79f85), + (0x3c699aa6df8b7d83, 0x3fc8a8980abfbd32), + (0xbc6e95734abd2fcc, 0x3fc97c1cb13c7ec1), + (0xbc6cc865b3dd0dbb, 0x3fcb2602497d5346), + (0x3c2bc0af7b82e7d7, 0x3fcbfc67a7fff4cc), + (0xbc0ba8b1f646ab12, 0x3fcdac22d3e441d3), + (0xbc6086fce864a1f6, 0x3fce857d3d361368), + (0x3c7768994400ca0a, 0x3fd01d9bbcfa61d4), + (0xbc53d56efe4338fe, 0x3fd08bce0d95fa38), + (0x3c7c8d43e017579b, 0x3fd169c05363f158), + (0x3c6ae9804237ec8e, 0x3fd1d982c9d52708), + (0x3c734107c0e54aed, 0x3fd249cd2b13cd6c), + (0x3c7968925e378d68, 0x3fd32bfee370ee68), + (0x3c7fcad2f4710e00, 0x3fd39de8e1559f6f), + (0xbc7c658d602e66b0, 0x3fd4106017c3eca3), + (0x3c7e393a16b94b52, 0x3fd4f6fbb2cec598), + (0xbc78d86531d55da2, 0x3fd56b22e6b578e5), + (0x3c710b5b643a6ecb, 0x3fd5dfdcf1eeae0e), + (0x3c7ac9080333c605, 0x3fd6552b49986277), + (0x3c2b6d40900b2502, 0x3fd6cb0f6865c8ea), + (0x3c68f89e2eb553b2, 0x3fd7b89f02cf2aad), + (0x3c651d58525aad39, 0x3fd8304d90c11fd3), + (0x3c799aa6df8b7d83, 0x3fd8a8980abfbd32), + (0x3c7fdc46af571993, 0x3fd921800924dd3b), + (0x3c7bca36fd02def0, 0x3fd99b072a96c6b2), + (0x3c5817fd3b7d7e5d, 0x3fda8ff971810a5e), + (0xbc45e13b838eba7d, 0x3fdb0b67f4f46810), + (0xbc501d98c3531027, 0x3fdb877c57b1b070), + (0x3c7edf515c63dd87, 0x3fdc043859e2fdb3), + (0x3c6c4aec56233279, 0x3fdc819dc2d45fe4), + (0x3c78a38b4175d665, 0x3fdcffae611ad12b), + (0xbc6e15a52a31604a, 0x3fdd7e6c0abc3579), + (0x3c438c8946414c6a, 0x3fddfdd89d586e2b), + (0x3c73bed456b24ed1, 0x3fde7df5fe538ab3), + (0x3c76d261f1753e0b, 0x3fdefec61b011f85), + (0xbc79ca1a3202b3d7, 0x3fdf804ae8d0cd02), + (0xbc87398fe685f171, 0x3fe0014332be0033), + (0xbc89c32630008a1f, 0x3fe042bd4b9a7c99), + (0xbc7f47806a0e4105, 0x3fe08494c66b8ef0), + (0xbc48a33c25e8e226, 0x3fe0c6caaf0c5597), + (0xbc73aec658457c41, 0x3fe1096015dee4da), + (0xbc8fc7d7c3320aab, 0x3fe14c560fe68af9), + (0xbc892ba145dcf40b, 0x3fe18fadb6e2d3c2), + (0xbc7f9fb952bbbccc, 0x3fe1d368296b5255), + (0xbc8568859c64022e, 0x3fe217868b0c37e8), + (0xbc84828ddf1fb145, 0x3fe25c0a0463beb0), + (0xbc8c348e4aab18b8, 0x3fe2a0f3c340705c), + (0xbc83af881af2f3d9, 0x3fe2e644fac04fd8), + (0xbc83af881af2f3d9, 0x3fe2e644fac04fd8), + (0x3c8968925e378d68, 0x3fe32bfee370ee68), + (0xbc869656a0ad70d4, 0x3fe37222bb70747c), + (0x3c76d266d6cdc959, 0x3fe3b8b1c68fa6ed), + (0xbc69575b04fa6fbd, 0x3fe3ffad4e74f1d6), + (0x3c5b90132aeddb58, 0x3fe44716a2c08262), + (0x3c5b90132aeddb58, 0x3fe44716a2c08262), + (0xbc75e35482d13dc1, 0x3fe48eef19317991), + (0xbc8ca44f1db913d3, 0x3fe4d7380dcc422d), + (0x3c7817fd3b7d7e5d, 0x3fe51ff2e30214bc), + (0x3c804613e33c06c9, 0x3fe5692101d9b4a6), + (0xbc8fc9257edfe9b6, 0x3fe5b2c3da19723b), + (0xbc8fc9257edfe9b6, 0x3fe5b2c3da19723b), + (0x3c8149a1977b5b99, 0x3fe5fcdce2727ddb), + (0xbc8b32266d92c0fe, 0x3fe6476d98ad990a), + (0x3c821d90b84e7218, 0x3fe6927781d932a8), + (0x3c821d90b84e7218, 0x3fe6927781d932a8), + (0x3c7f6e91ad16ecff, 0x3fe6ddfc2a78fc63), + (0xbc74a31ce1b7e328, 0x3fe729fd26b707c8), + (0x3c6a7b47d2c352d9, 0x3fe7767c12967a45), + (0x3c6a7b47d2c352d9, 0x3fe7767c12967a45), + (0x3c821f9cb2cc5575, 0x3fe7c37a9227e7fb), + (0x3c8dc572667587b1, 0x3fe810fa51bf65fd), + (0x3c8dc572667587b1, 0x3fe810fa51bf65fd), + (0xbc78f93e7aa3bdf8, 0x3fe85efd062c656d), + (0x3c5b85a54d7ee2fd, 0x3fe8ad846cf369a4), + (0x3c5b85a54d7ee2fd, 0x3fe8ad846cf369a4), + (0x3c8bf1d926766301, 0x3fe8fc924c89ac84), + (0x3c401ee1343fe7ca, 0x3fe94c287492c4db), + (0x3c401ee1343fe7ca, 0x3fe94c287492c4db), + (0x3c7fa0a62e6add1b, 0x3fe99c48be2063c8), + (0x3c8022ddb71189c5, 0x3fe9ecf50bf43f13), + (0x3c8022ddb71189c5, 0x3fe9ecf50bf43f13), + (0x3c7ac7fc60a51031, 0x3fea3e2f4ac43f60), + (0x3c6817fd3b7d7e5d, 0x3fea8ff971810a5e), + (0x3c6817fd3b7d7e5d, 0x3fea8ff971810a5e), + (0xbc83138e941643f7, 0x3feae255819f022d), + (0x3c8e0ae0d3f8a58b, 0x3feb35458761d479), + (0x3c8e0ae0d3f8a58b, 0x3feb35458761d479), + (0x3c742b7579f0f8d4, 0x3feb88cb9a2ab521), + (0x3c742b7579f0f8d4, 0x3feb88cb9a2ab521), + (0x3c6a7610e40bd6ab, 0x3febdce9dcc96187), + (0xbc80e5edaecee150, 0x3fec31a27dd00b4a), + (0xbc80e5edaecee150, 0x3fec31a27dd00b4a), + (0xbc831d962d3728cc, 0x3fec86f7b7ea4a89), + (0xbc831d962d3728cc, 0x3fec86f7b7ea4a89), + (0xbc857391924a6d9d, 0x3fecdcebd2373995), + (0x3c78333ac7d9ebbb, 0x3fed338120a6dd9d), + (0x3c78333ac7d9ebbb, 0x3fed338120a6dd9d), + (0xbc86c0268890da53, 0x3fed8aba045b01c8), + (0xbc86c0268890da53, 0x3fed8aba045b01c8), + (0xbc859e7ba5d5ccc9, 0x3fede298ec0bac0d), + (0xbc859e7ba5d5ccc9, 0x3fede298ec0bac0d), + (0x3c60b07079619c47, 0x3fee3b20546f554a), + (0x3c60b07079619c47, 0x3fee3b20546f554a), + (0xbc8cc4d81bc25adf, 0x3fee9452c8a71028), + (0xbc8cc4d81bc25adf, 0x3fee9452c8a71028), + (0xbc776c0a2827d49a, 0x3feeee32e2aeccbf), + (0xbc776c0a2827d49a, 0x3feeee32e2aeccbf), + (0xbc8314dc4fc42302, 0x3fef48c34bd1e96f), + (0xbc8314dc4fc42302, 0x3fef48c34bd1e96f), + (0xbc817f8e37b00179, 0x3fefa406bd2443df), + (0x0, 0x0), +]; + +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +)))] +pub(crate) static LOG_CD: [u64; 128] = [ + 0x0000000000000000, + 0xbf10000000000000, + 0xbf30000000000000, + 0xbf42000000000000, + 0xbf50000000000000, + 0xbf59000000000000, + 0xbf62000000000000, + 0xbf68800000000000, + 0xbf70000000000000, + 0xbf49000000000000, + 0xbf5f000000000000, + 0xbf69c00000000000, + 0xbf30000000000000, + 0xbf5c000000000000, + 0xbf6b000000000000, + 0xbf45000000000000, + 0xbf64000000000000, + 0x3f10000000000000, + 0xbf60000000000000, + 0x3f3a000000000000, + 0xbf5e000000000000, + 0x3f38000000000000, + 0xbf61000000000000, + 0xbf00000000000000, + 0xbf66000000000000, + 0xbf4a000000000000, + 0xbf6e000000000000, + 0xbf5f800000000000, + 0xbf30000000000000, + 0xbf6c000000000000, + 0xbf5f000000000000, + 0xbf3c000000000000, + 0xbf70000000000000, + 0xbf65400000000000, + 0xbf56000000000000, + 0xbf24000000000000, + 0x3f50000000000000, + 0xbf68800000000000, + 0xbf60800000000000, + 0xbf52000000000000, + 0xbf30000000000000, + 0x3f42000000000000, + 0xbf70000000000000, + 0xbf6ac00000000000, + 0xbf66000000000000, + 0xbf61c00000000000, + 0xbf5c000000000000, + 0xbf55800000000000, + 0xbf50000000000000, + 0xbf47000000000000, + 0xbf40000000000000, + 0xbf36000000000000, + 0xbf30000000000000, + 0xbf2c000000000000, + 0xbf30000000000000, + 0xbf36000000000000, + 0xbf40000000000000, + 0xbf47000000000000, + 0xbf50000000000000, + 0xbf55800000000000, + 0xbf5c000000000000, + 0xbf61c00000000000, + 0xbf66000000000000, + 0xbf6ac00000000000, + 0xbf70000000000000, + 0x3f55000000000000, + 0x3f42000000000000, + 0xbf30000000000000, + 0xbf52000000000000, + 0xbf60800000000000, + 0xbf68800000000000, + 0x3f60c00000000000, + 0x3f50000000000000, + 0xbf24000000000000, + 0xbf56000000000000, + 0xbf65400000000000, + 0xbf70000000000000, + 0x3f50000000000000, + 0xbf3c000000000000, + 0xbf5f000000000000, + 0xbf6c000000000000, + 0x3f56800000000000, + 0xbf30000000000000, + 0xbf5f800000000000, + 0xbf6e000000000000, + 0x3f51000000000000, + 0xbf4a000000000000, + 0xbf66000000000000, + 0x3f60000000000000, + 0xbf00000000000000, + 0xbf61000000000000, + 0x3f64800000000000, + 0x3f38000000000000, + 0xbf5e000000000000, + 0x3f66000000000000, + 0x3f3a000000000000, + 0xbf60000000000000, + 0x3f64800000000000, + 0x3f10000000000000, + 0xbf64000000000000, + 0x3f60000000000000, + 0xbf45000000000000, + 0xbf6b000000000000, + 0x3f51000000000000, + 0xbf5c000000000000, + 0x3f65400000000000, + 0xbf30000000000000, + 0xbf69c00000000000, + 0x3f52000000000000, + 0xbf5f000000000000, + 0x3f63000000000000, + 0xbf49000000000000, + 0xbf70000000000000, + 0x3f30000000000000, + 0xbf68800000000000, + 0x3f52800000000000, + 0xbf62000000000000, + 0x3f5f000000000000, + 0xbf59000000000000, + 0x3f64c00000000000, + 0xbf50000000000000, + 0x3f69000000000000, + 0xbf42000000000000, + 0x3f6c400000000000, + 0xbf30000000000000, + 0x3f6e800000000000, + 0xbf10000000000000, + 0xbf70000000000000, +]; + +pub(crate) const LOG_COEFFS: [u64; 6] = [ + 0xbfdfffffffffffff, + 0x3fd5555555554a9b, + 0xbfd0000000094567, + 0x3fc99999dcc9823c, + 0xbfc55550ac2e537a, + 0x3fc21a02c4e624d7, +]; + +/// Log2(x) +/// +/// Max found ULP 0.5 +pub fn f_log2(x: f64) -> f64 { + let mut x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i64 = -(E_BIAS as i64); + + const MAX_NORMAL: u64 = f64::to_bits(f64::MAX); + + if x_u == 1f64.to_bits() { + // log2(1.0) = +0.0 + return 0.0; + } + if x_u < min_normal_f64().to_bits() || x_u > MAX_NORMAL { + if x == 0.0 { + return f64::NEG_INFINITY; + } + if x < 0. || x.is_nan() { + return f64::NAN; + } + if x.is_infinite() || x.is_nan() { + return x + x; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4330000000000000)).to_bits(); + x_e -= 52; + } + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i64; + let index = shifted & 0x7F; + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i64); + let e_x = x_e as f64; + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + // Exact sum: + let log_vals = DoubleDouble::from_bit_pair(LOG2_DD[index as usize]); + + /* + Poly generated in Sollya; + d = [-2^-8, 2^-7]; + f = (log2(1 + x))/x; + pf = fpminimax(f, 5, [|D...|], [-2^-8, 2^-7]); + + See ./notes/log2.sollya + */ + const C: [u64; 6] = [ + 0x3ff71547652b82fe, + 0xbfe71547652b7a07, + 0x3fdec709dc458db1, + 0xbfd715479c2266c9, + 0x3fd2776ae1ddf8f0, + 0xbfce7b2178870157, + ]; + + // Degree-7 minimax polynomial + let p = f_fmla( + f_polyeval6( + u, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + ), + u, + log_vals.lo, + ); + + // log2(x) = e + log2(r) + log2(index) + + let rr = DoubleDouble::from_full_exact_add(log_vals.hi, e_x); + let r3 = DoubleDouble::add_f64(rr, p); + + let err = f_fmla( + r3.hi, + f64::from_bits(0x3bf0000000000000), // 2^-64 + f64::from_bits(0x3c60000000000000), // 2^-57 + ); + + // Lower bound from the result + let left = r3.hi + (r3.lo - err); + // Upper bound from the result + let right = r3.hi + (r3.lo + err); + + // Ziv's test if fast pass is accurate enough. + if left == right { + return left; + } + + log2_hard(x) +} + +#[cold] +#[inline(never)] +fn log2_hard(x: f64) -> f64 { + let r = log2_dd(x); + let err = f_fmla( + r.hi, + f64::from_bits(0x3b50000000000000), // 2^-74 + f64::from_bits(0x3990000000000000), // 2^-102 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return r.to_f64(); + } + log2_hard_slow(x) +} + +#[cold] +#[inline(never)] +fn log2_hard_slow(x: f64) -> f64 { + log2_td(x).to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log2d() { + assert_eq!(f_log2(0.7500000000000461), -0.4150374992787552); + assert_eq!(f_log2(1.99999999779061), 0.999999998406262); + assert_eq!(f_log2(0.7812499981882864), -0.35614381357087554); + assert_eq!(f_log2(0.5937499997089616), -0.7520724872635803); + assert_eq!(f_log2(0.9983015060407214), -0.0024524921736992287); + assert_eq!(f_log2(0.2284926469437778), -2.129780355811612); + assert_eq!(f_log2(24.), 4.584962500721156181453738943); + assert!((f_log2(0.35) - 0.35f64.log2()).abs() < 1e-8); + assert!((f_log2(0.9) - 0.9f64.log2()).abs() < 1e-8); + assert_eq!(f_log2(0.), f64::NEG_INFINITY); + assert!(f_log2(-1.).is_nan()); + assert!(f_log2(f64::NAN).is_nan()); + assert!(f_log2(f64::NEG_INFINITY).is_nan()); + assert_eq!(f_log2(f64::INFINITY), f64::INFINITY); + } + + #[test] + fn test_log2_control_values() { + assert_eq!( + f_log2(f64::from_bits(0x3ff1406d79e1b574)), + 0.10866415915666149 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ffb4ebe40c95a01)), + 0.7712301192941611 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff0b541b6746bd1)), + 0.062470074690080965 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff68d778f076021)), + 0.4952222169409832 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff67eaf07ce24d1)), + 0.4915233709893074 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff0b53197bd66c8)), + 0.062448835548542664 + ); + assert_eq!( + f_log2(f64::from_bits(0x3fe6b015f8d9a784)), + -0.496152942566177 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff160732376ad7f)), + 0.11908694357502585 + ); + assert_eq!( + f_log2(f64::from_bits(0x3ff0b53f741fb8c4)), + 0.062467098188572705 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2dd.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2dd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::log2dd_coeffs::LOG2_NEG_DD; +use crate::pow_tables::POW_INVERSE; + +#[inline(always)] +fn log2_poly(z: f64) -> DoubleDouble { + /* + See ./notes/dd_log2.sollya + */ + const P: [(u64, u64); 10] = [ + (0x3c7777d0ffdb7a88, 0x3ff71547652b82fe), + (0xbc6777d0fff4382c, 0xbfe71547652b82fe), + (0x3c7d27ad39ed5b3e, 0x3fdec709dc3a03fd), + (0xbc57748c64010a70, 0xbfd71547652b82fe), + (0x3c771aed4208f9c1, 0x3fd2776c50ef9c06), + (0x3c6dd0178c438bee, 0xbfcec709dc3a041c), + (0x3c6054a5812d9fc4, 0x3fca61762a515608), + (0x3c5662d846baea2e, 0xbfc7154764f1db89), + (0x3c66b62df1fd3c4b, 0x3fc484dddfe20481), + (0xbc6b16c93b93c1e3, 0xbfc2779d6a07c6b3), + ]; + let mut t = DoubleDouble::from_bit_pair(P[9]); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[8])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[7])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[6])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[5])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[4])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[3])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[2])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[1])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[0])); + DoubleDouble::quick_mult_f64(t, z) +} + +#[inline] +pub(crate) fn log2_dd(x: f64) -> DoubleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log2(x) = log2(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let idx = (i - 181) as usize; + + let r = f64::from_bits(POW_INVERSE[idx]); + let log_r = DoubleDouble::from_bit_pair(LOG2_NEG_DD[idx]); + + let z = f64::mul_add(r, t, -1.0); + + let v = DoubleDouble::full_add_f64(log_r, be as f64); + let p = log2_poly(z); + let z0 = DoubleDouble::new(v.lo + p.lo, p.hi); + DoubleDouble::full_add_f64(z0, v.hi) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn log2dd_test() { + assert_eq!(log2_dd(0.0040283203125 / 2.).to_f64(), -8.955605880641546); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2dd_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2dd_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2dd_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,228 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by Sage: +from POW_INV +```python +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_double_double("", -RealField(120)(r).log2()) +``` +**/ +pub(crate) static LOG2_NEG_DD: [(u64, u64); 182] = [ + (0xbc61d46ccc53c278, 0xbfdfbc16b902680a), + (0x3c6780e41697a095, 0xbfdf38c567bcc541), + (0xbc74f9727980f5ed, 0xbfdeb4b847d15bce), + (0xbc4be44aae7442ab, 0xbfde2fed3d097298), + (0xbc1274a5715611b7, 0xbfddaa6222064fb9), + (0xbc74856fb52a53d2, 0xbfdd2414c80bf27d), + (0x3c6b517ae88c2fd3, 0xbfdce0a4923a587d), + (0xbc7f9fb952bbbccc, 0xbfdc592fad295b56), + (0x3c752ef4c737fba5, 0xbfdbd0f2e9e79031), + (0x3c76fae441c09d76, 0xbfdb47ebf73882a1), + (0x3c5e5b8daaa73a43, 0xbfdabe18797f1f49), + (0x3c78a0efca1a184f, 0xbfda33760a7f6051), + (0x3c7dc938c18e544d, 0xbfd9edd6759b25e0), + (0x3c7cc298a148e6ca, 0xbfd961f90527409c), + (0x3c7530bdb6949302, 0xbfd8d54673b5c372), + (0x3c76d266d6cdc959, 0xbfd88e9c72e0b226), + (0xbc69575b04fa6fbd, 0xbfd800a563161c54), + (0x3c5b90132aeddb58, 0xbfd771d2ba7efb3c), + (0xbc75e35482d13dc1, 0xbfd6e221cd9d0cde), + (0xbc7a3152150d2dbf, 0xbfd699f5248cd4b8), + (0x3c7a43fc62b7e690, 0xbfd608f1b42948ae), + (0x3c7817fd3b7d7e5d, 0xbfd5c01a39fbd688), + (0xbc7f73d83987f26d, 0xbfd52dbdfc4c96b3), + (0x3c1b6d40900b2502, 0xbfd49a784bcd1b8b), + (0x3c7aca97d800ce47, 0xbfd4507cfedd4fc4), + (0x3c7a9f3c8bc9672e, 0xbfd3bbd3a0a1dcfb), + (0x3c63376649b4fc09, 0xbfd37124cea4cded), + (0xbc7bc4de8f631bcf, 0xbfd2db10fc4d9aaf), + (0xbc78c0e85a908be6, 0xbfd28fab35b32683), + (0xbc65f43469fbe6ea, 0xbfd1f825f6d88e13), + (0xbc74a31ce1b7e328, 0xbfd1ac05b291f070), + (0x3c6a7b47d2c352d9, 0xbfd11307dad30b76), + (0x3c76c13816f9f480, 0xbfd0c62975542a8f), + (0xbc7bc0c69a675517, 0xbfd0790adbb03009), + (0xbc51d46ccc53c278, 0xbfcfbc16b902680a), + (0xbc61dd4a99cc633b, 0xbfcf205339208f27), + (0x3c4e41bd8c32e1be, 0xbfcde73fe3b1480f), + (0x3c5b85a54d7ee2fd, 0xbfcd49ee4c325970), + (0x3c6a4ecd69d3b872, 0xbfccac163c770dc9), + (0xbc6afb63338bed1f, 0xbfcb6ecf175f95e9), + (0x3c401ee1343fe7ca, 0xbfcacf5e2db4ec94), + (0x3c5ae3bd6c6d42f0, 0xbfca2f632320b86b), + (0x3c628caf799ad993, 0xbfc8edcae8352b6c), + (0x3c116edb88c4e2b5, 0xbfc84c2bd02f03b3), + (0x3c3d0364be23e873, 0xbfc7a9fec7d05ddf), + (0xbc6f3314e0985116, 0xbfc663f6fac91316), + (0x3c6817fd3b7d7e5d, 0xbfc5c01a39fbd688), + (0xbc622c022616fdff, 0xbfc51bab907a5c8a), + (0xbc589c74a0b21fb6, 0xbfc476a9f983f74d), + (0xbc4f51f2c075a74c, 0xbfc32ae9e278ae1a), + (0x3c6ca25d54d6f775, 0xbfc284294b07a640), + (0xbc67a9150c1e0e58, 0xbfc1dcd197552b7b), + (0x3bf94b7dfe0d99a5, 0xbfc134e1b489062e), + (0x3c5becb2e71abdc8, 0xbfbfc66a0f0b00a5), + (0xbc3cbdb5d9dc29f2, 0xbfbe72ec117fa5b2), + (0xbc5342ce3cc8f2f9, 0xbfbd1e34e35b82da), + (0xbc58ecb169b9465f, 0xbfbbc84240adabba), + (0x3c34bba7e1c43d2c, 0xbfba7111df348494), + (0x3c5463736dac9317, 0xbfb918a16e46335b), + (0xbc5f3314e0985116, 0xbfb663f6fac91316), + (0x3c458696424b2e96, 0xbfb507b836033bb7), + (0x3c43fd9776f25acf, 0xbfb3aa2fdd27f1c3), + (0x3c5d974c32ba8269, 0xbfb24b5b7e135a3d), + (0x3c530c22d15199b8, 0xbfb0eb389fa29f9b), + (0x3c478cbe51121a94, 0xbfaf1389833253a0), + (0x3c160e0f2c3388f0, 0xbfac4dfab90aab5f), + (0xbc482838ed43de84, 0xbfa985bfc3495194), + (0xbc389b03784b5be1, 0xbfa6bad3758efd87), + (0xbc3013a5b81fc494, 0xbfa3ed3094685a26), + (0x3c227ebafb056cb9, 0xbfa11cd1d5133413), + (0xbc399ba03dc5d34f, 0xbf9c9363ba850f86), + (0x3c3d6476077b9fbd, 0xbf96e79685c2d22a), + (0xbc32ed069b244452, 0xbf91363117a97b0c), + (0xbc2fe38dec005e54, 0xbf86fe50b6ef0851), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3c0456006875bd76, 0x3f815cfe8eaec830), + (0x3c2ae48169cf4cdb, 0x3f8cfee70c5ce5dc), + (0x3c37910667a9b5f8, 0x3f94564a62192834), + (0xbc361176ce5d0a51, 0x3f9a330fd028f75f), + (0xbc493cced296b87d, 0x3fa00ae7f502c1c4), + (0xbc4c3f1d5c0cfec8, 0x3fa2ff4b77413dcb), + (0x3c2c62a2f6e13b06, 0x3fa5f6b8a11c3c61), + (0x3c477970e03f821c, 0x3fa77394c9d958d5), + (0xbc486446a6eb19b1, 0x3faa6f9c377dd31b), + (0x3c0155660710eb2a, 0x3fad6ebd1f1febfe), + (0xbc57de9078d157a3, 0x3fb0387efbca869e), + (0x3c298c5452bbce74, 0x3fb1bb32a600549d), + (0xbc3e20375a3220ba, 0x3fb33f7cde14cf5a), + (0xbc4e40a005e7a3e0, 0x3fb4023b7b26ac9e), + (0x3c5a489c555db4a8, 0x3fb588edd4d1ceaa), + (0xbc524e45ed01d67c, 0x3fb7113f3259e07a), + (0x3c34ea44821c1dc2, 0x3fb89b33091d6fe8), + (0xbc5d9af608a7a4d8, 0x3fba26ccd9981853), + (0x3c540238de7ea9f1, 0x3fbaed391ab6674e), + (0xbc17936311889913, 0x3fbc7b528b70f1c5), + (0x3c592ce9636c90a0, 0x3fbe0b1ae8f2fd56), + (0xbc56fb7d020ef0e0, 0x3fbed3a1d4cdbebb), + (0x3c3905c241a252f9, 0x3fc032fbbaee6d65), + (0xbc61d536b72e64f7, 0x3fc0fd02a03727ea), + (0xbc5df0fdbc295d19, 0x3fc162593186da70), + (0xbc5696e2866c718e, 0x3fc22dadc2ab3497), + (0xbc6978b98f7dedf9, 0x3fc2f9e32d5bfdd1), + (0xbc4b5ac8d9739e01, 0x3fc36052d01c3dd7), + (0x3c648a7168f01501, 0x3fc42ddd2ba1b4a9), + (0x3c67c2c3172b86af, 0x3fc4fc4d4d9bb313), + (0x3c390e41bca6ef96, 0x3fc563dc29ffacb2), + (0x3c354fae008fbb59, 0x3fc633a8bf437ce1), + (0x3c6a1981a877433e, 0x3fc69be6fbb3aa6f), + (0x3c6519f7ed9559d4, 0x3fc76d14a4601225), + (0x3c69ced1447e30ad, 0x3fc7d60496cfbb4c), + (0x3c699aa6df8b7d83, 0x3fc8a8980abfbd32), + (0xbc40b273219ed335, 0x3fc9123c1528c6ce), + (0xbc45359413e77d86, 0x3fc9e63a24971f46), + (0x3c6013b6eaceb921, 0x3fca5094b54d2828), + (0xbc6cc865b3dd0dbb, 0x3fcb2602497d5346), + (0x3c569a95f528f2c7, 0x3fcb9115db83a3dd), + (0xbc4fab00c0500189, 0x3fcc67f7f770a67e), + (0x3c592eeaf409cc88, 0x3fccd3c712d31109), + (0xbc0ba8b1f646ab12, 0x3fcdac22d3e441d3), + (0x3c29bf75f08df8fb, 0x3fce18b00e13123d), + (0x3c506313e79cf1dc, 0x3fcef28aacd72231), + (0xbc6bdc0426c3c274, 0x3fcf5fd8a9063e35), + (0x3c7768994400ca0a, 0x3fd01d9bbcfa61d4), + (0x3c7fdee226b2d7aa, 0x3fd054a474bf0eb7), + (0xbc53d56efe4338fe, 0x3fd08bce0d95fa38), + (0x3c40de07b685556f, 0x3fd0fa848044b351), + (0x3c790ea4cc5a44e3, 0x3fd13211a9b38424), + (0x3c7a3174c8d0586b, 0x3fd1a190a5d674a0), + (0x3c6ae9804237ec8e, 0x3fd1d982c9d52708), + (0xbc7343f87991ca1f, 0x3fd21196e87473d1), + (0xbc57154f4085d044, 0x3fd28225bb5e64a4), + (0xbc50132ae5e417cd, 0x3fd2baa0c34be1ec), + (0xbc7bc5dc0ebe6308, 0x3fd2f33e6d2120f2), + (0xbc687bf1007a1695, 0x3fd364e2511cc821), + (0x3c7fcad2f4710e00, 0x3fd39de8e1559f6f), + (0xbc69cee46ebe3a2d, 0x3fd3d712bf9c9def), + (0xbc7c658d602e66b0, 0x3fd4106017c3eca3), + (0xbc75759f8091112d, 0x3fd48365e695d797), + (0xbc75e341793e8e12, 0x3fd4bd1eb680e548), + (0x3c7e393a16b94b52, 0x3fd4f6fbb2cec598), + (0xbc78d86531d55da2, 0x3fd56b22e6b578e5), + (0x3c7885b23dbdaaf1, 0x3fd5a56d7a370ded), + (0x3c710b5b643a6ecb, 0x3fd5dfdcf1eeae0e), + (0x3c515f01e8fdf6ad, 0x3fd61a717cac1983), + (0x3c3d3cd794eee08b, 0x3fd6900a8836d0d5), + (0x3c2b6d40900b2502, 0x3fd6cb0f6865c8ea), + (0x3c6cbc6f17205b76, 0x3fd7063a1a5fb4f2), + (0xbc726bfff0133975, 0x3fd7418acebbf18f), + (0xbc76d8d6e54d428b, 0x3fd77d01b66fbd37), + (0x3c6412d04e355531, 0x3fd7f462e58e1688), + (0x3c651d58525aad39, 0x3fd8304d90c11fd3), + (0xbc71660ad9487503, 0x3fd86c5f36dea3dc), + (0x3c799aa6df8b7d83, 0x3fd8a8980abfbd32), + (0xbc740df0e173c574, 0x3fd8e4f83fa145ee), + (0x3c7fdc46af571993, 0x3fd921800924dd3b), + (0x3c7bca36fd02def0, 0x3fd99b072a96c6b2), + (0xbc7cf91d2080a35b, 0x3fd9d806ebc9921c), + (0xbc64278cd1699312, 0x3fda152f142981b4), + (0x3c6b56b1d743ac01, 0x3fda527fd95fd8ff), + (0x3c5817fd3b7d7e5d, 0x3fda8ff971810a5e), + (0x3c77061311743a68, 0x3fdacd9c130dd53f), + (0xbc45e13b838eba7d, 0x3fdb0b67f4f46810), + (0xbc501d98c3531027, 0x3fdb877c57b1b070), + (0xbc78a87a168550fe, 0x3fdbc5c5489254cc), + (0x3c7edf515c63dd87, 0x3fdc043859e2fdb3), + (0xbc687a4c86c71df7, 0x3fdc42d5c4c688b4), + (0x3c6c4aec56233279, 0x3fdc819dc2d45fe4), + (0x3c5d3c79567f954e, 0x3fdcc0908e19b7bd), + (0x3c78a38b4175d665, 0x3fdcffae611ad12b), + (0xbc4e2b378ff59cbb, 0x3fdd3ef776d43ff4), + (0xbc6e15a52a31604a, 0x3fdd7e6c0abc3579), + (0xbc76a568b022e9a3, 0x3fddbe0c58c3cff2), + (0x3c438c8946414c6a, 0x3fddfdd89d586e2b), + (0xbc63aeabca24fd25, 0x3fde3dd1156507de), + (0x3c73bed456b24ed1, 0x3fde7df5fe538ab3), + (0x3c7ff93949a1897d, 0x3fdebe47960e3c08), + (0x3c76d261f1753e0b, 0x3fdefec61b011f85), + (0xbc7f4c8f8f9cbfe1, 0x3fdf3f71cc1b629c), + (0xbc79ca1a3202b3d7, 0x3fdf804ae8d0cd02), + (0x3c5b9a81085cd3b3, 0x3fdfc151b11b3640), + (0xbc87398fe685f171, 0x3fe0014332be0033), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,395 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, f_fmlaf, set_exponent_f32}; +use crate::logs::logf::{GenLogfBackend, LogfBackend}; +use crate::polyeval::f_polyeval3; + +pub(crate) static LOG2_R: [u64; 128] = [ + 0x0000000000000000, + 0x3f872c7ba20f7327, + 0x3f9743ee861f3556, + 0x3fa184b8e4c56af8, + 0x3fa77394c9d958d5, + 0x3fad6ebd1f1febfe, + 0x3fb1bb32a600549d, + 0x3fb4c560fe68af88, + 0x3fb7d60496cfbb4c, + 0x3fb960caf9abb7ca, + 0x3fbc7b528b70f1c5, + 0x3fbf9c95dc1d1165, + 0x3fc097e38ce60649, + 0x3fc22dadc2ab3497, + 0x3fc3c6fb650cde51, + 0x3fc494f863b8df35, + 0x3fc633a8bf437ce1, + 0x3fc7046031c79f85, + 0x3fc8a8980abfbd32, + 0x3fc97c1cb13c7ec1, + 0x3fcb2602497d5346, + 0x3fcbfc67a7fff4cc, + 0x3fcdac22d3e441d3, + 0x3fce857d3d361368, + 0x3fd01d9bbcfa61d4, + 0x3fd08bce0d95fa38, + 0x3fd169c05363f158, + 0x3fd1d982c9d52708, + 0x3fd249cd2b13cd6c, + 0x3fd32bfee370ee68, + 0x3fd39de8e1559f6f, + 0x3fd4106017c3eca3, + 0x3fd4f6fbb2cec598, + 0x3fd56b22e6b578e5, + 0x3fd5dfdcf1eeae0e, + 0x3fd6552b49986277, + 0x3fd6cb0f6865c8ea, + 0x3fd7b89f02cf2aad, + 0x3fd8304d90c11fd3, + 0x3fd8a8980abfbd32, + 0x3fd921800924dd3b, + 0x3fd99b072a96c6b2, + 0x3fda8ff971810a5e, + 0x3fdb0b67f4f46810, + 0x3fdb877c57b1b070, + 0x3fdc043859e2fdb3, + 0x3fdc819dc2d45fe4, + 0x3fdcffae611ad12b, + 0x3fdd7e6c0abc3579, + 0x3fddfdd89d586e2b, + 0x3fde7df5fe538ab3, + 0x3fdefec61b011f85, + 0x3fdf804ae8d0cd02, + 0x3fe0014332be0033, + 0x3fe042bd4b9a7c99, + 0x3fe08494c66b8ef0, + 0x3fe0c6caaf0c5597, + 0x3fe1096015dee4da, + 0x3fe14c560fe68af9, + 0x3fe18fadb6e2d3c2, + 0x3fe1d368296b5255, + 0x3fe217868b0c37e8, + 0x3fe25c0a0463beb0, + 0x3fe2a0f3c340705c, + 0x3fe2e644fac04fd8, + 0x3fe2e644fac04fd8, + 0x3fe32bfee370ee68, + 0x3fe37222bb70747c, + 0x3fe3b8b1c68fa6ed, + 0x3fe3ffad4e74f1d6, + 0x3fe44716a2c08262, + 0x3fe44716a2c08262, + 0x3fe48eef19317991, + 0x3fe4d7380dcc422d, + 0x3fe51ff2e30214bc, + 0x3fe5692101d9b4a6, + 0x3fe5b2c3da19723b, + 0x3fe5b2c3da19723b, + 0x3fe5fcdce2727ddb, + 0x3fe6476d98ad990a, + 0x3fe6927781d932a8, + 0x3fe6927781d932a8, + 0x3fe6ddfc2a78fc63, + 0x3fe729fd26b707c8, + 0x3fe7767c12967a45, + 0x3fe7767c12967a45, + 0x3fe7c37a9227e7fb, + 0x3fe810fa51bf65fd, + 0x3fe810fa51bf65fd, + 0x3fe85efd062c656d, + 0x3fe8ad846cf369a4, + 0x3fe8ad846cf369a4, + 0x3fe8fc924c89ac84, + 0x3fe94c287492c4db, + 0x3fe94c287492c4db, + 0x3fe99c48be2063c8, + 0x3fe9ecf50bf43f13, + 0x3fe9ecf50bf43f13, + 0x3fea3e2f4ac43f60, + 0x3fea8ff971810a5e, + 0x3fea8ff971810a5e, + 0x3feae255819f022d, + 0x3feb35458761d479, + 0x3feb35458761d479, + 0x3feb88cb9a2ab521, + 0x3feb88cb9a2ab521, + 0x3febdce9dcc96187, + 0x3fec31a27dd00b4a, + 0x3fec31a27dd00b4a, + 0x3fec86f7b7ea4a89, + 0x3fec86f7b7ea4a89, + 0x3fecdcebd2373995, + 0x3fed338120a6dd9d, + 0x3fed338120a6dd9d, + 0x3fed8aba045b01c8, + 0x3fed8aba045b01c8, + 0x3fede298ec0bac0d, + 0x3fede298ec0bac0d, + 0x3fee3b20546f554a, + 0x3fee3b20546f554a, + 0x3fee9452c8a71028, + 0x3fee9452c8a71028, + 0x3feeee32e2aeccbf, + 0x3feeee32e2aeccbf, + 0x3fef48c34bd1e96f, + 0x3fef48c34bd1e96f, + 0x3fefa406bd2443df, + 0x3ff0000000000000, +]; + +#[inline(always)] +fn log2f_gen(x: f32, backend: B) -> f32 { + let mut x_u = x.to_bits(); + + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + + let mut m = -(E_BIAS as i32); + if x_u < f32::MIN_POSITIVE.to_bits() || x_u > f32::MAX.to_bits() { + if x == 0.0 { + return f32::NEG_INFINITY; + } + if x_u == 0x80000000u32 { + return f32::NEG_INFINITY; + } + if x.is_sign_negative() && !x.is_nan() { + return f32::NAN + x; + } + // x is +inf or nan + if x.is_nan() || x.is_infinite() { + return x + x; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4160000000000000) as f32).to_bits(); + m -= 23; + } + + m = m.wrapping_add(x_u.wrapping_shr(23) as i32); + let mant = x_u & 0x007F_FFFF; + let index = mant.wrapping_shr(16); + + x_u = set_exponent_f32(x_u, 0x7F); + + let u = f32::from_bits(x_u); + + let v = if B::HAS_FMA { + use crate::logs::logf::LOG_REDUCTION_F32; + backend.fmaf(u, f32::from_bits(LOG_REDUCTION_F32.0[index as usize]), -1.0) as f64 // Exact. + } else { + use crate::logs::LOG_RANGE_REDUCTION; + backend.fma( + u as f64, + f64::from_bits(LOG_RANGE_REDUCTION[index as usize]), + -1.0, + ) // Exact + }; + // Degree-5 polynomial approximation of log2 generated by Sollya with: + // > P = fpminimax(log2(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]); + + let extra_factor = m as f64 + f64::from_bits(LOG2_R[index as usize]); + + const COEFFS: [u64; 5] = [ + 0x3ff71547652b8133, + 0xbfe71547652d1e33, + 0x3fdec70a098473de, + 0xbfd7154c5ccdf121, + 0x3fd2514fd90a130a, + ]; + let v2 = v * v; // Exact + let c0 = backend.fma(v, f64::from_bits(COEFFS[0]), extra_factor); + let c1 = backend.fma(v, f64::from_bits(COEFFS[2]), f64::from_bits(COEFFS[1])); + let c2 = backend.fma(v, f64::from_bits(COEFFS[4]), f64::from_bits(COEFFS[3])); + + let r = backend.polyeval3(v2, c0, c1, c2); + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn log2f_fma_impl(x: f32) -> f32 { + use crate::logs::logf::FmaLogfBackend; + log2f_gen(x, FmaLogfBackend {}) +} + +/// Logarithm of base 2 +/// +/// Max found ULP 0.4999996 +pub fn f_log2f(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + log2f_gen(x, GenLogfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + log2f_fma_impl + } else { + fn def_log2f(x: f32) -> f32 { + log2f_gen(x, GenLogfBackend {}) + } + def_log2f + } + }); + unsafe { q(x) } + } +} + +/// Natural logarithm using FMA +/// +/// Max found ULP 0.4999996 +#[inline(always)] +#[allow(dead_code)] +pub(crate) fn f_log2fx(x: f32) -> f64 { + let mut x_u = x.to_bits(); + + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + + let mut m = -(E_BIAS as i32); + if x_u == 0x3f80_0000u32 { + return 0.0; + } + + if x_u < f32::MIN_POSITIVE.to_bits() || x_u > f32::MAX.to_bits() { + if x == 0.0 { + return f64::NEG_INFINITY; + } + if x_u == 0x80000000u32 { + return f64::NEG_INFINITY; + } + if x.is_sign_negative() && !x.is_nan() { + return f64::NAN + x as f64; + } + // x is +inf or nan + if x.is_nan() || x.is_infinite() { + return (x + x) as f64; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4160000000000000) as f32).to_bits(); + m -= 23; + } + + m = m.wrapping_add(x_u.wrapping_shr(23) as i32); + let mant = x_u & 0x007F_FFFF; + let index = mant.wrapping_shr(16); + + x_u = set_exponent_f32(x_u, 0x7F); + + let v; + let u = f32::from_bits(x_u); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::logs::logf::LOG_REDUCTION_F32; + v = f_fmlaf(u, f32::from_bits(LOG_REDUCTION_F32.0[index as usize]), -1.0) as f64; // Exact. + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log2::LOG_RANGE_REDUCTION; + v = f_fmla( + u as f64, + f64::from_bits(LOG_RANGE_REDUCTION[index as usize]), + -1.0, + ); // Exact + } + // Degree-5 polynomial approximation of log2 generated by Sollya with: + // > P = fpminimax(log2(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]); + + let extra_factor = m as f64 + f64::from_bits(LOG2_R[index as usize]); + + const COEFFS: [u64; 5] = [ + 0x3ff71547652b8133, + 0xbfe71547652d1e33, + 0x3fdec70a098473de, + 0xbfd7154c5ccdf121, + 0x3fd2514fd90a130a, + ]; + let v2 = v * v; // Exact + let c0 = f_fmla(v, f64::from_bits(COEFFS[0]), extra_factor); + let c1 = f_fmla(v, f64::from_bits(COEFFS[2]), f64::from_bits(COEFFS[1])); + let c2 = f_fmla(v, f64::from_bits(COEFFS[4]), f64::from_bits(COEFFS[3])); + + f_polyeval3(v2, c0, c1, c2) +} + +/// Dirty log2 using FMA +#[inline(always)] +#[allow(dead_code)] +pub(crate) fn dirty_log2f(d: f32) -> f32 { + let mut ix = d.to_bits(); + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix = ix.wrapping_add(0x3f800000 - 0x3f3504f3); + let n = (ix >> 23) as i32 - 0x7f; + ix = (ix & 0x007fffff).wrapping_add(0x3f3504f3); + let a = f32::from_bits(ix); + + let x = (a - 1.) / (a + 1.); + + let x2 = x * x; + let mut u = 0.4121985850084821691e+0; + u = f_fmlaf(u, x2, 0.5770780163490337802e+0); + u = f_fmlaf(u, x2, 0.9617966939259845749e+0); + f_fmlaf(x2 * x, u, f_fmlaf(x, 0.2885390081777926802e+1, n as f32)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log2f() { + assert!((f_log2f(0.35f32) - 0.35f32.log2()).abs() < 1e-5); + assert!((f_log2f(0.9f32) - 0.9f32.log2()).abs() < 1e-5); + assert_eq!(f_log2f(0.), f32::NEG_INFINITY); + assert_eq!(f_log2f(1.0), 0.0); + assert!(f_log2f(-1.).is_nan()); + assert!(f_log2f(f32::NAN).is_nan()); + assert!(f_log2f(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_log2f(f32::INFINITY), f32::INFINITY); + } + + #[test] + fn test_dirty_log2f() { + assert!((dirty_log2f(0.35f32) - 0.35f32.log2()).abs() < 1e-5); + assert!((dirty_log2f(0.9f32) - 0.9f32.log2()).abs() < 1e-5); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,486 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::{biased_exponent_f64, get_exponent_f64, mantissa_f64}; +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::logs::log2p1_dyadic_tables::{LOG2P1_F128_POLY, LOG2P1_INVERSE_2, LOG2P1_LOG_INV_2}; +use crate::logs::log2p1_tables::{LOG2P1_EXACT, LOG2P1_INVERSE, LOG2P1_LOG_DD_INVERSE}; + +/* put in h+l a double-double approximation of log(z)-z for +|z| < 0.03125, with absolute error bounded by 2^-67.14 +(see analyze_p1a(-0.03125,0.03125) from log1p.sage) */ +#[inline] +pub(crate) fn log_p_1a(z: f64) -> DoubleDouble { + let z2: DoubleDouble = if z.abs() >= f64::from_bits(0x3000000000000000) { + DoubleDouble::from_exact_mult(z, z) + } else { + // avoid spurious underflow + DoubleDouble::default() + }; + let z4h = z2.hi * z2.hi; + /* The following is a degree-11 polynomial generated by Sollya + approximating log(1+x) for |x| < 0.03125, + with absolute error < 2^-73.441 and relative error < 2^-67.088 + (see file Pabs_a.sollya). + The polynomial is P[0]*x + P[1]*x^2 + ... + P[10]*x^11. + The algorithm assumes that the degree-1 coefficient P[0] is 1 + and the degree-2 coefficient P[1] is -0.5. */ + const PA: [u64; 11] = [ + 0x3ff0000000000000, + 0xbfe0000000000000, + 0x3fd5555555555555, + 0xbfcffffffffffe5f, + 0x3fc999999999aa82, + 0xbfc555555583a8c8, + 0x3fc2492491c359e6, + 0xbfbffffc728edeea, + 0x3fbc71c961f34980, + 0xbfb9a82ac77c05f4, + 0x3fb74b40dd1707d3, + ]; + let p910 = dd_fmla(f64::from_bits(PA[10]), z, f64::from_bits(PA[9])); + let p78 = dd_fmla(f64::from_bits(PA[8]), z, f64::from_bits(PA[7])); + let p56 = dd_fmla(f64::from_bits(PA[6]), z, f64::from_bits(PA[5])); + let p34 = dd_fmla(f64::from_bits(PA[4]), z, f64::from_bits(PA[3])); + let p710 = dd_fmla(p910, z2.hi, p78); + let p36 = dd_fmla(p56, z2.hi, p34); + let mut ph = dd_fmla(p710, z4h, p36); + ph = dd_fmla(ph, z, f64::from_bits(PA[2])); + ph *= z2.hi; + let mut p = DoubleDouble::from_exact_add(-0.5 * z2.hi, ph * z); + p.lo += -0.5 * z2.lo; + p +} + +/* put in h+l a double-double approximation of log(z)-z for +|z| < 0.00212097167968735, with absolute error bounded by 2^-78.25 +(see analyze_p1(-0.00212097167968735,0.00212097167968735) +from accompanying file log1p.sage, which also yields |l| < 2^-69.99) */ +#[inline] +fn p_1(z: f64) -> DoubleDouble { + const P: [u64; 7] = [ + 0x3ff0000000000000, + 0xbfe0000000000000, + 0x3fd5555555555550, + 0xbfcfffffffff572d, + 0x3fc999999a2d7868, + 0xbfc5555c0d31b08e, + 0x3fc2476b9058e396, + ]; + let z2 = DoubleDouble::from_exact_mult(z, z); + let p56 = dd_fmla(f64::from_bits(P[6]), z, f64::from_bits(P[5])); + let p34 = dd_fmla(f64::from_bits(P[4]), z, f64::from_bits(P[3])); + let mut ph = dd_fmla(p56, z2.hi, p34); + /* ph approximates P[3]+P[4]*z+P[5]*z^2+P[6]*z^3 */ + ph = dd_fmla(ph, z, f64::from_bits(P[2])); + /* ph approximates P[2]+P[3]*z+P[4]*z^2+P[5]*z^3+P[6]*z^4 */ + ph *= z2.hi; + /* ph approximates P[2]*z^2+P[3]*z^3+P[4]*z^4+P[5]*z^5+P[6]*z^6 */ + let mut p = DoubleDouble::from_exact_add(-0.5 * z2.hi, ph * z); + + p.lo += -0.5 * z2.lo; + p +} + +#[inline] +pub(crate) fn log_fast(e: i32, v_u: u64) -> DoubleDouble { + let m: u64 = 0x10000000000000u64.wrapping_add(v_u & 0xfffffffffffff); + /* x = m/2^52 */ + /* if x > sqrt(2), we divide it by 2 to avoid cancellation */ + let c: i32 = if m >= 0x16a09e667f3bcd { 1 } else { 0 }; + let e = e.wrapping_add(c); /* now -1074 <= e <= 1024 */ + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u32; 2] = [43, 44]; + + let i: i32 = (m >> CM[c as usize]) as i32; + let y = f64::from_bits(v_u) * CY[c as usize]; + const OFFSET: i32 = 362; + let r = f64::from_bits(LOG2P1_INVERSE[(i - OFFSET) as usize]); + let log2_inv_dd = LOG2P1_LOG_DD_INVERSE[(i - OFFSET) as usize]; + let l1 = f64::from_bits(log2_inv_dd.1); + let l2 = f64::from_bits(log2_inv_dd.0); + let z = dd_fmla(r, y, -1.0); /* exact */ + /* evaluate P(z), for |z| < 0.00212097167968735 */ + + let p = p_1(z); + + /* Add e*log(2) to (h,l), where -1074 <= e <= 1023, thus e has at most + 11 bits. log2_h is an integer multiple of 2^-42, so that e*log2_h + is exact. */ + const LOG2_H: f64 = f64::from_bits(0x3fe62e42fefa3800); + const LOG2_L: f64 = f64::from_bits(0x3d2ef35793c76730); + + let ee = e as f64; + let mut vl = DoubleDouble::from_exact_add(f_fmla(ee, LOG2_H, l1), z); + vl.lo = p.hi + (vl.lo + (l2 + p.lo)); + + vl.lo = dd_fmla(ee, LOG2_L, vl.lo); + + vl +} + +const INV_LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7777d0ffda0d24), + f64::from_bits(0x3ff71547652b82fe), +); + +fn log2p1_accurate_small(x: f64) -> f64 { + static P_ACC: [u64; 24] = [ + 0x3ff71547652b82fe, + 0x3c7777d0ffda0d24, + 0xbfe71547652b82fe, + 0xbc6777d0ffd9ddb8, + 0x3fdec709dc3a03fd, + 0x3c7d27f055481523, + 0xbfd71547652b82fe, + 0xbc5777d1456a14c4, + 0x3fd2776c50ef9bfe, + 0x3c7e4b2a04f81513, + 0xbfcec709dc3a03fd, + 0xbc6d2072e751087a, + 0x3fca61762a7aded9, + 0x3c5f90f4895378ac, + 0xbfc71547652b8301, + 0x3fc484b13d7c02ae, + 0xbfc2776c50ef7591, + 0x3fc0c9a84993cabb, + 0xbfbec709de7b1612, + 0x3fbc68f56ba73fd1, + 0xbfba616c83da87e7, + 0x3fb89f3042097218, + 0xbfb72b376930a3fa, + 0x3fb5d0211d5ab530, + ]; + + /* for degree 11 or more, ulp(c[d]*x^d) < 2^-105.5*|log2p1(x)| + where c[d] is the degree-d coefficient of Pacc, thus we can compute + with a double only */ + + let mut h = dd_fmla(f64::from_bits(P_ACC[23]), x, f64::from_bits(P_ACC[22])); // degree 16 + for i in (11..=15).rev() { + h = dd_fmla(h, x, f64::from_bits(P_ACC[(i + 6) as usize])); // degree i + } + let mut l = 0.; + for i in (8..=10).rev() { + let mut p = DoubleDouble::quick_f64_mult(x, DoubleDouble::new(l, h)); + l = p.lo; + p = DoubleDouble::from_exact_add(f64::from_bits(P_ACC[(i + 6) as usize]), p.hi); + h = p.hi; + l += p.lo; + } + for i in (1..=7).rev() { + let mut p = DoubleDouble::quick_f64_mult(x, DoubleDouble::new(l, h)); + l = p.lo; + p = DoubleDouble::from_exact_add(f64::from_bits(P_ACC[(2 * i - 2) as usize]), p.hi); + h = p.hi; + l += p.lo + f64::from_bits(P_ACC[(2 * i - 1) as usize]); + } + let pz = DoubleDouble::quick_f64_mult(x, DoubleDouble::new(l, h)); + pz.to_f64() +} + +/* deal with |x| < 2^-900, then log2p1(x) ~ x/log(2) */ +#[cold] +fn log2p1_accurate_tiny(x: f64) -> f64 { + // exceptional values + if x.abs() == f64::from_bits(0x0002c316a14459d8) { + return if x > 0. { + dd_fmla( + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x0003fc1ce8b1583f), + ) + } else { + dd_fmla( + f64::from_bits(0x9a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x8003fc1ce8b1583f), + ) + }; + } + + /* first scale x to avoid truncation of l in the underflow region */ + let sx = x * f64::from_bits(0x4690000000000000); + let mut zh = DoubleDouble::quick_f64_mult(sx, INV_LOG2_DD); + + let res = zh.to_f64() * f64::from_bits(0x3950000000000000); // expected result + zh.lo += dd_fmla(-res, f64::from_bits(0x4690000000000000), zh.hi); + // the correction to apply to res is l*2^-106 + /* For all rounding modes, we have underflow + for |x| <= 0x1.62e42fefa39eep-1023 */ + dyad_fmla(zh.lo, f64::from_bits(0x3950000000000000), res) +} + +/* Given x > -1, put in (h,l) a double-double approximation of log2(1+x), + and return a bound err on the maximal absolute error so that: + |h + l - log2(1+x)| < err. + We have x = m*2^e with 1 <= m < 2 (m = v.f) and -1074 <= e <= 1023. + This routine is adapted from cr_log1p_fast. +*/ +#[inline] +fn log2p1_fast(x: f64, e: i32) -> (DoubleDouble, f64) { + if e < -5 + /* e <= -6 thus |x| < 2^-5 */ + { + if e <= -969 { + /* then |x| might be as small as 2^-969, thus h=x/log(2) might in the + binade [2^-969,2^-968), with ulp(h) = 2^-1021, and if |l| < ulp(h), + then l.ulp() might be smaller than 2^-1074. We defer that case to + the accurate path. */ + // *h = *l = 0; + // return 1; + let ax = x.abs(); + let result = if ax < f64::from_bits(0x3960000000000000) { + log2p1_accurate_tiny(x) + } else { + log2p1_accurate_small(x) + }; + return (DoubleDouble::new(0.0, result), 0.0); + } + let mut p = log_p_1a(x); + let p_lo = p.lo; + p = DoubleDouble::from_exact_add(x, p.hi); + p.lo += p_lo; + p = DoubleDouble::quick_mult(p, INV_LOG2_DD); + return (p, f64::from_bits(0x3c1d400000000000) * p.hi); /* 2^-61.13 < 0x1.d4p-62 */ + } + + /* (xh,xl) <- 1+x */ + let zx = DoubleDouble::from_full_exact_add(1.0, x); + let mut v_u = zx.hi.to_bits(); + let e = ((v_u >> 52) as i32).wrapping_sub(0x3ff); + v_u = (0x3ffu64 << 52) | (v_u & 0xfffffffffffff); + let mut p = log_fast(e, v_u); + + /* log(xh+xl) = log(xh) + log(1+xl/xh) */ + let c = if zx.hi <= f64::from_bits(0x7fd0000000000000) || zx.lo.abs() >= 4.0 { + zx.lo / zx.hi + } else { + 0. + }; // avoid spurious underflow + + /* Since |xl| < ulp(xh), we have |xl| < 2^-52 |xh|, + thus |c| < 2^-52, and since |log(1+x)-x| < x^2 for |x| < 0.5, + we have |log(1+c)-c)| < c^2 < 2^-104. */ + p.lo += c; + + /* now multiply h+l by 1/log(2) */ + p = DoubleDouble::quick_mult(p, INV_LOG2_DD); + + (p, f64::from_bits(0x3bb2300000000000)) /* 2^-67.82 < 0x1.23p-68 */ +} + +fn log_dyadic_taylor_poly(x: DyadicFloat128) -> DyadicFloat128 { + let mut r = LOG2P1_F128_POLY[12]; + for i in (0..12).rev() { + r = x * r + LOG2P1_F128_POLY[i]; + } + r * x +} + +pub(crate) fn log2_dyadic(d: DyadicFloat128, x: f64) -> DyadicFloat128 { + let biased_exp = biased_exponent_f64(x); + let e = get_exponent_f64(x); + let base_mant = mantissa_f64(x); + let mant = base_mant + if biased_exp != 0 { 1u64 << 52 } else { 0 }; + let lead = mant.leading_zeros(); + + let kk = e - (if lead > 11 { lead - 12 } else { 0 }) as i64; + let mut fe: i16 = kk as i16; + + let adjusted_mant = mant << lead; + + // Find the lookup index + let mut i: i16 = (adjusted_mant >> 55) as i16; + + if adjusted_mant > 0xb504f333f9de6484 { + fe = fe.wrapping_add(1); + i >>= 1; + } + + let mut x = d; + + x.exponent = x.exponent.wrapping_sub(fe); + let inverse_2 = LOG2P1_INVERSE_2[(i - 128) as usize]; + let mut z = x * inverse_2; + + const F128_MINUS_ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }; + + z = z + F128_MINUS_ONE; + + const LOG2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb172_17f7_d1cf_79ab_c9e3_b398_03f2_f6af_u128, + }; + + // E·log(2) + let r = LOG2.mul_int64(fe as i64); + + let mut p = log_dyadic_taylor_poly(z); + p = LOG2P1_LOG_INV_2[(i - 128) as usize] + p; + p + r +} + +#[cold] +fn log2p1_accurate(x: f64) -> f64 { + let ax = x.abs(); + + if ax < f64::from_bits(0x3fa0000000000000) { + return if ax < f64::from_bits(0x3960000000000000) { + log2p1_accurate_tiny(x) + } else { + log2p1_accurate_small(x) + }; + } + let dx = if x > 1.0 { + DoubleDouble::from_exact_add(x, 1.0) + } else { + DoubleDouble::from_exact_add(1.0, x) + }; + /* log2p1(x) is exact when 1+x = 2^e, thus when 2^e-1 is exactly + representable. This can only occur when xl=0 here. */ + let mut t: u64 = x.to_bits(); + if dx.lo == 0. { + /* check if xh is a power of two */ + t = dx.hi.to_bits(); + if (t.wrapping_shl(12)) == 0 { + let e = ((t >> 52) as i32).wrapping_sub(0x3ff); + return e as f64; + } + } + /* if x=2^e, the accurate path will fail for directed roundings */ + if (t.wrapping_shl(12)) == 0 { + let e: i32 = ((t >> 52) as i32).wrapping_sub(0x3ff); // x = 2^e + + /* for e >= 49, log2p1(x) rounds to e for rounding to nearest; + for e >= 48, log2p1(x) rounds to e for rounding toward zero; + for e >= 48, log2p1(x) rounds to nextabove(e) for rounding up; + for e >= 48, log2p1(x) rounds to e for rounding down. */ + if e >= 49 { + return e as f64 + f64::from_bits(0x3cf0000000000000); // 0x1p-48 = 1/2 ulp(49) + } + } + let x_d = DyadicFloat128::new_from_f64(dx.hi); + let mut y = log2_dyadic(x_d, dx.hi); + let mut c = DyadicFloat128::from_div_f64(dx.lo, dx.hi); + let mut bx = c * c; + /* multiply X by -1/2 */ + bx.exponent -= 1; + bx.sign = DyadicSign::Neg; + /* C <- C - C^2/2 */ + c = c + bx; + /* |C-log(1+xl/xh)| ~ 2e-64 */ + y = y + c; + const LOG2_INV: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xb8aa_3b29_5c17_f0bb_be87_fed0_691d_3e89_u128, + }; + y = y * LOG2_INV; + y.exponent -= 12; + y.fast_as_f64() +} + +/// Computes log2(x+1) +/// +/// Max ULP 0.5 +pub fn f_log2p1(x: f64) -> f64 { + let x_u = x.to_bits(); + let e = (((x_u >> 52) & 0x7ff) as i32).wrapping_sub(0x3ff); + if e == 0x400 || x == 0. || x <= -1.0 { + /* case NaN/Inf, +/-0 or x <= -1 */ + if e == 0x400 && x.to_bits() != 0xfffu64 << 52 { + /* NaN or + Inf*/ + return x + x; + } + if x <= -1.0 + /* we use the fact that NaN < -1 is false */ + { + /* log2p(x<-1) is NaN, log2p(-1) is -Inf and raises DivByZero */ + return if x < -1.0 { + f64::NAN + } else { + // x=-1 + f64::NEG_INFINITY + }; + } + return x + x; /* +/-0 */ + } + + /* now x > -1 */ + + /* check x=2^n-1 for 0 <= n <= 53, where log2p1(x) is exact, + and we shouldn't raise the inexact flag */ + if 0 <= e && e <= 52 { + /* T[e]=2^(e+1)-1, i.e., the unique value of the form 2^n-1 + in the interval [2^e, 2^(e+1)). */ + if x == f64::from_bits(LOG2P1_EXACT[e as usize]) { + return (e + 1) as f64; + } + } + + /* For x=2^k-1, -53 <= k <= -1, log2p1(x) = k is also exact. */ + if e == -1 && x < 0. { + // -1 < x <= -1/2 + let w = (1.0 + x).to_bits(); // 1+x is exact + if w.wrapping_shl(12) == 0 { + // 1+x = 2^k + let k: i32 = ((w >> 52) as i32).wrapping_sub(0x3ff); + return k as f64; + } + } + + /* now x = m*2^e with 1 <= m < 2 (m = v.f) and -1074 <= e <= 1023 */ + let (p, err) = log2p1_fast(x, e); + let left = p.hi + (p.lo - err); + let right = p.hi + (p.lo + err); + if left == right { + return left; + } + log2p1_accurate(x) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_log2p1() { + assert_eq!(f_log2p1(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008344095884546873), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012037985753337781); + assert_eq!(f_log2p1(0.00006669877554532304), 0.00009622278377734607); + assert_eq!(f_log2p1(1.00006669877554532304), 1.0000481121941047); + assert_eq!(f_log2p1(-0.90006669877554532304), -3.322890675865049); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_dyadic_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_dyadic_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_dyadic_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_dyadic_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2503 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +pub(crate) static LOG2P1_F128_POLY: [DyadicFloat128; 13] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ebd8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaaaa_aaaa_aaaa_aaaa_aaaa_aaaa_a5c4_8b54_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xffff_ffff_ffff_ffff_ffff_ff22_4582_3ae0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcccc_cccc_cccc_cccc_ccc2_ca18_b08f_e343_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xaaaa_aaaa_aaaa_aaaa_6637_fd4b_1974_3eec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9249_2492_4924_911d_862b_c3d3_3abb_3649_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xffff_ffff_fff9_24cc_05b3_08e3_9fa7_dfb5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe38e_38e3_807c_fa4b_c976_e6cb_d22e_203f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xcccc_ccb9_ec01_7492_f934_e28d_924e_76d4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xba2e_7a1e_af85_6174_70e5_c5a5_ebbe_0226_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xaaa0_2d43_f696_c3e4_4dbe_7546_67b6_bc48_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x99df_88a0_4308_13ca_a1cf_fb6e_966a_70f6_u128, + }, +]; + +pub(crate) static LOG2P1_INVERSE_2: [DyadicFloat128; 240] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xfe03_f80f_e03f_80ff_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xfc0f_c0fc_0fc0_fc10_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xfa23_2cf2_5213_8ac0_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf83e_0f83_e0f8_3e10_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf660_3d98_0f66_03da_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf489_8d5f_85bb_3951_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf2b9_d648_0f2b_9d65_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf0f0_f0f0_f0f0_f0f1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xef2e_b71f_c434_5239_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xed73_03b5_cc0e_d731_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xebbd_b2a5_c161_9c8c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xea0e_a0ea_0ea0_ea0f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe865_ac7b_7603_a197_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe6c2_b448_1cd8_568a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe525_982a_f70c_880f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe38e_38e3_8e38_e38f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe1fc_780e_1fc7_80e2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe070_381c_0e07_0382_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xdee9_5c4c_a037_ba58_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xdd67_c8a6_0dd6_7c8b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xdbeb_61ee_d19c_5958_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xda74_0da7_40da_740e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd901_b203_6406_c80e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd794_35e5_0d79_435f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd62b_80d6_2b80_d62c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd4c7_7b03_531d_ec0e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd368_0d36_80d3_680e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd20d_20d2_0d20_d20e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd0b6_9fcb_d258_0d0c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xcf64_74a8_819e_c8ea_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xce16_8a77_2508_0ce2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xcccc_cccc_cccc_cccd_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xcb87_27c0_65c3_93e1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xca45_87e6_b74f_032a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc907_da4e_8711_46ad_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc7ce_0c7c_e0c7_ce0d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc698_0c69_80c6_980d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc565_c87b_5f9d_4d1c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc437_2f85_5d82_4ca6_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc30c_30c3_0c30_c30d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc1e4_bbd5_95f6_e948_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc0c0_c0c0_c0c0_c0c1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbfa0_2fe8_0bfa_02ff_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbe82_fa0b_e82f_a0bf_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbd69_1047_0766_1aa3_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbc52_640b_c526_40bd_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbb3e_e721_a54d_880c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xba2e_8ba2_e8ba_2e8c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb921_43fa_36f5_e02f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb817_02e0_5c0b_8171_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb70f_bb5a_19be_3659_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb60b_60b6_0b60_b60c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb509_e68a_9b94_8220_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb40b_40b4_0b40_b40c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb30f_6352_8917_c80c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb216_42c8_590b_2165_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb11f_d3b8_0b11_fd3c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb02c_0b02_c0b0_2c0c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xaf3a_ddc6_80af_3ade_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xae4c_415c_9882_b932_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xad60_2b58_0ad6_02b6_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xac76_9184_0ac7_6919_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xab8f_69e2_8359_cd12_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xaaaa_aaaa_aaaa_aaab_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa9c8_4a47_a07f_5638_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa8e8_3f57_17c0_a8e9_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa80a_80a8_0a80_a80b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa72f_0539_7829_cbc2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa655_c439_2d7b_73a8_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa57e_b502_95fa_d40b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa4a9_cf1d_9683_3752_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa3d7_0a3d_70a3_d70b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa306_5e3f_ae7c_d0e1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa237_c32b_16cf_d773_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa16b_312e_a8fc_377d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa0a0_a0a0_a0a0_a0a1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9fd8_09fd_809f_d80a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9f11_65e7_2548_13e3_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9e4c_ad23_dd5f_3a21_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9d89_d89d_89d8_9d8a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9cc8_e160_c3fb_19b9_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9c09_c09c_09c0_9c0a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9b4c_6f9e_f03a_3caa_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9a90_e7d9_5bc6_09aa_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x99d7_22da_bde5_8f07_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x991f_1a51_5885_fb38_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9868_c809_868c_8099_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x97b4_25ed_097b_425f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9701_2e02_5c04_b80a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x964f_da6c_0964_fda7_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x95a0_2568_095a_0257_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x94f2_094f_2094_f20a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9445_8094_4580_9446_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x939a_85c4_0939_a85d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x92f1_1384_0497_889d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9249_2492_4924_924a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x91a2_b3c4_d5e6_f80a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x90fd_bc09_0fdb_c091_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x905a_3863_3e06_c43b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8fb8_23ee_08fb_823f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8f17_79d9_fdc3_a219_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8e78_356d_1408_e784_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8dda_5202_3769_4809_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8d3d_cb08_d3dc_b08e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8ca2_9c04_6514_e024_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8c08_c08c_08c0_8c09_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8b70_344a_139b_c75b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8ad8_f2fb_a938_6823_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8a42_f870_5669_db47_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x89ae_4089_ae40_89af_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x891a_c73a_e981_9b51_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8888_8888_8888_8889_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x87f7_8087_f780_87f8_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8767_ab5f_34e4_7ef2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x86d9_0544_7a34_acc7_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x864b_8a7d_e6d1_d609_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x85bf_3761_2cee_3c9b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8534_0853_4085_3409_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x84a9_f9c8_084a_9f9d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8421_0842_1084_2109_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8399_3052_3fbe_3368_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8312_6e97_8d4f_df3c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x828c_bfbe_b9a0_20a4_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8208_2082_0820_8209_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8184_8da8_faf0_d278_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8102_0408_1020_4082_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xff00_ff00_ff00_ff02_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfe03_f80f_e03f_80ff_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfd08_e550_0fd0_8e56_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfc0f_c0fc_0fc0_fc11_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfb18_8565_06dd_aba7_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfa23_2cf2_5213_8ac1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf92f_b221_1855_a866_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf83e_0f83_e0f8_3e11_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf74e_3fc2_2c70_0f76_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf660_3d98_0f66_03db_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf574_03d5_d00f_5741_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf489_8d5f_85bb_3951_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf3a0_d52c_ba87_2337_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf2b9_d648_0f2b_9d66_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf1d4_8bce_e0d3_99fb_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf0f0_f0f0_f0f0_f0f2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf00f_00f0_0f00_f010_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xef2e_b71f_c434_5239_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xee50_0ee5_00ee_5010_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xed73_03b5_cc0e_d731_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xec97_9118_f3fc_4da3_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xebbd_b2a5_c161_9c8d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xeae5_6403_ab95_9010_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xea0e_a0ea_0ea0_ea10_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe939_651f_e2d8_d35d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe865_ac7b_7603_a198_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe793_72e2_25fe_30da_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe6c2_b448_1cd8_568a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe5f3_6cb0_0e5f_36cc_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe525_982a_f70c_880f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe459_32d7_dc52_100f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe38e_38e3_8e38_e38f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe2c4_a688_6a4c_2e11_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe1fc_780e_1fc7_80e3_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe135_a9c9_7500_e137_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe070_381c_0e07_0383_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdfac_1f74_346c_5760_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdee9_5c4c_a037_ba58_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xde27_eb2c_41f3_d9d2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdd67_c8a6_0dd6_7c8b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdca8_f158_c7f9_1ab9_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdbeb_61ee_d19c_5959_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdb2f_171d_f770_291a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xda74_0da7_40da_740f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd9ba_4256_c036_6e92_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd901_b203_6406_c80f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd84a_598e_c915_1f44_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd794_35e5_0d79_435f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd6df_43fc_a482_f00e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd62b_80d6_2b80_d62d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd578_e97c_3f5f_e552_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd4c7_7b03_531d_ec0e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd417_3289_870a_c52f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd368_0d36_80d3_680e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd2ba_083b_4452_50ac_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd20d_20d2_0d20_d20e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd161_543e_28e5_0275_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd0b6_9fcb_d258_0d0c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd00d_00d0_0d00_d00e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcf64_74a8_819e_c8ea_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcebc_f8bb_5b41_69cc_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xce16_8a77_2508_0ce2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcd71_2752_a886_d243_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcccc_cccc_cccc_ccce_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcc29_786c_7607_f9a0_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcb87_27c0_65c3_93e1_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcae5_d85f_1bbd_6c96_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xca45_87e6_b74f_032a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc9a6_33fc_d967_300e_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc907_da4e_8711_46ae_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc86a_7890_0c86_a78a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc7ce_0c7c_e0c7_ce0d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc732_93d7_89b9_f839_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc698_0c69_80c6_980d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc5fe_7403_17f9_d00d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc565_c87b_5f9d_4d1d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc4ce_07b0_0c4c_e07c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc437_2f85_5d82_4ca7_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc3a1_3de6_0495_c774_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc30c_30c3_0c30_c30d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc278_0613_c030_9e03_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc1e4_bbd5_95f6_e948_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc152_500c_1525_00c2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc0c0_c0c0_c0c0_c0c2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc030_0c03_00c0_300d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbfa0_2fe8_0bfa_0300_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbf11_2a8a_d278_e8de_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbe82_fa0b_e82f_a0c0_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbdf5_9c91_700b_df5b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbd69_1047_0766_1aa4_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbcdd_535d_b1cc_5b7c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbc52_640b_c526_40bd_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbbc8_408c_d630_69a2_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbb3e_e721_a54d_880d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbab6_5610_0bab_6562_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xba2e_8ba2_e8ba_2e8d_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb9a7_862a_0ff4_6589_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb921_43fa_36f5_e02f_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb89b_c36c_e3e0_453b_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb817_02e0_5c0b_8171_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb793_00b7_9300_b794_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb70f_bb5a_19be_365a_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb68d_3134_0e43_07d9_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb60b_60b6_0b60_b60c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb58a_4855_18d1_e7e5_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb509_e68a_9b94_8220_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb48a_39d4_4685_fe98_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb40b_40b4_0b40_b40c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb38c_f9b0_0b38_cf9c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb30f_6352_8917_c80c_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb292_7c29_da55_19d0_0000_0000_0000_0000_u128, + }, +]; + +pub(crate) static LOG2P1_LOG_INV_2: [DyadicFloat128; 240] = [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xb172_17f7_d1cf_79ab_c9e3_b398_03f2_f6af_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xaf74_1551_20c9_011d_046d_235e_e630_73dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xad7a_02e1_b24e_fd32_1608_64fd_949b_4bd3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xab83_d135_dc63_3301_ffe6_607b_a902_ef3b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa991_7134_33c2_b999_0ba4_aea6_14d0_5700_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa7a2_d41a_d270_c9d7_cd36_2382_a768_8479_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa5b7_eb7c_b860_fb89_7b6a_62a0_dec6_e072_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa3d0_a93f_4516_9a4b_0959_4fab_088c_0d64_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa1ec_ff97_c91e_267b_1b7e_fae0_8e59_7e16_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0xa00c_e109_2e54_98c4_6987_9c5a_30cd_1241_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x9e30_4061_b5fd_a91a_0460_3d87_b6df_81ac_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x9c57_10b8_cbb7_3a42_aa55_4b2d_d461_9e63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x9a81_456c_ec64_2e10_4d49_f9aa_ea3c_b5e0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x98ae_d221_a034_58b6_732f_8932_1647_b358_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x96df_aabd_86fa_1647_d611_88fb_c94e_2f14_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x9513_c368_7608_3696_b5cb_c416_a241_8011_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x934b_1089_a6dc_93c2_bf5b_b3b6_0554_e151_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x9185_86c5_f5e4_bf01_9f92_199e_d1a4_bab0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8fc3_1afe_30b2_c6de_e300_bf16_7e95_da66_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8e03_c24d_7300_395a_cdda_e1cc_ce24_7837_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8c47_7207_91e5_3314_762a_d194_15fe_25a5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8a8e_1fb7_94b0_9134_9eb6_28db_a173_c82d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x88d7_c11e_3ad5_3cdc_8a31_11a7_07b6_de2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8724_4c30_8e67_0a66_85e0_05d0_6dbf_a8f7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8573_b716_82a7_d21b_b21f_9f89_c1ab_80b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x83c5_f829_9e2b_4091_b8f6_fafe_8fbb_68b8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x821b_05f3_b01d_6774_db0d_58c3_f7e2_ea1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x8072_d72d_903d_588c_7dd1_b09c_70c4_0109_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xfd9a_c57b_d244_2180_af05_924d_258c_14c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xfa55_3f70_18c9_66f4_2780_a545_a1b5_4dce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xf715_0ab5_a09f_27f6_0a47_0250_d40e_be8e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xf3da_161e_ed6b_9ab1_248d_42f7_8d3e_65d2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xf0a4_50d1_3936_6ca7_7c66_eb64_08ff_6432_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xed73_aa42_64b0_adeb_5391_cf4b_33e4_2996_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xea48_1236_f7d3_5bb2_39a7_67a8_0d6d_97e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xe721_78c0_323a_1a0f_cc4e_1653_e71d_9973_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xe3ff_ce3a_2aa6_4923_8ead_b651_b49a_c539_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xe0e3_0349_fd1c_ec82_03e8_e180_2aba_24d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xddcb_08dc_0717_d85c_940a_666c_8784_2842_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xdab7_d022_3148_4a93_bec2_0cca_6efe_2ac4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xd7a9_4a92_466e_833c_cd88_bba7_d0ce_e8df_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xd49f_69e4_56cf_1b7b_7f53_bd2e_406e_66e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xd19a_2011_27d3_c646_279d_79f5_1dcc_7301_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xce99_5f50_af69_d863_432f_3f4f_861a_d6a8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xcb9d_1a18_9ab5_6e77_7d7e_9307_c70c_0667_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xc8a5_431a_dfb4_4ca6_048c_e7c1_a75e_341a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xc5b1_cd44_596f_a51f_f218_fb8f_9f9e_f27f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xc2c2_abbb_6e5f_d570_0333_7789_d592_e296_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xbfd7_d1de_c0a8_df70_37ed_a996_244b_ccaf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xbcf1_3343_e7d9_ec7f_2afd_1778_1bb3_afea_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xba0e_c3b6_33dd_8b0b_91dc_60b2_b059_a609_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xb730_7735_78cb_90b3_aa11_16c3_466b_eb6c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xb456_41f4_e350_a0d4_e756_eba0_0bc3_3976_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xb180_1859_d562_49de_98ce_51ff_f994_79cb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xaead_eefa_caf9_7d37_9dd6_e688_ebb1_3b01_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xabdf_ba9e_468f_d6f9_472e_a077_49ce_6bd1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xa915_7039_c51e_be72_e164_c759_686a_2207_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xa64f_04f0_b961_df78_54f5_275c_2d15_c21e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xa38c_6e13_8e20_d834_d698_298a_dddd_7f30_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xa0cd_a11e_af46_390e_6324_3827_3918_db7d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x9e12_93b9_998c_1dad_3b03_5eae_273a_855c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x9b5b_3bb5_f088_b768_5078_bbe3_d392_be24_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x98a7_8f0e_9ae7_1d87_64de_c347_8470_7838_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x95f7_83e6_e49a_9cfc_0250_04f3_ef06_3312_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x934b_1089_a6dc_93c2_df5b_b3b6_0554_e151_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x90a2_2b68_75c6_a1f8_8e91_aeba_609c_8876_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x8dfc_cb1a_d35c_a6ef_9947_bdb6_ddca_f59a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x8b5a_e65d_67db_9acf_7ba5_1681_26a5_8b99_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x88bc_7411_3f23_def3_bc5a_0fe3_96f4_0f1c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x8621_6b3b_0b17_188c_363c_eae8_8f72_0f1d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x8389_c302_6ac3_139d_6add_a9d2_270f_a1f3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0x80f5_72b1_3634_87bc_edbd_0b5b_3479_d5f2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xfcc8_e365_9d9b_cbf1_8a0c_df30_1431_b60b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xf7ad_6f26_e7ff_2efc_9cd2_238f_75f9_69ad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xf298_77ff_3880_9097_2b02_0fa1_820c_948d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xed89_ed86_a44a_01ab_09d4_9f96_cb88_317a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xe881_bf93_2af3_dac3_2524_848e_3443_e03f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xe37f_de37_807b_84e3_5e9a_750b_6b68_781c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xde84_39c1_dec5_687c_9d57_da94_5b5d_0aa6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xd98e_c2ba_de71_e53e_d0a9_8f2a_d65b_ee96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xd49f_69e4_56cf_1b7a_5f53_bd2e_406e_66e7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xcfb6_2038_44b3_209b_18cb_02f3_3f79_c16b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xcad2_d6e7_b80b_f915_cc50_7fb7_a3d0_bf69_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xc5f5_7f59_c7f4_6156_9a8b_6997_a402_bf30_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xc11e_0b2a_8d1e_0de1_da63_1e83_0fd3_08fe_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xbc4c_6c2a_2263_99f6_276e_bcfb_2016_a433_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xb780_945b_ab55_dcea_b4c7_bc3d_3275_0fd9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xb2ba_75f4_6099_cf8f_243c_2e77_904a_fa76_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xadfa_035a_a1ed_8fdd_5497_67e4_1031_6d2b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xa93f_2f25_0dac_67d5_9ad2_fb8d_4805_4add_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xa489_ec19_9dab_06f4_59fb_6cf0_ecb4_11b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x9fda_2d2c_c946_5c52_6b2b_9565_f535_5180_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x9b2f_e580_ac80_b182_011a_5b94_4aca_8705_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x968b_0864_3409_ceb9_d5c0_da50_6a08_8482_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x91eb_8952_4e10_0d28_bfd3_df5c_52d6_7e77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x8d51_5bf1_1fb9_4f22_a071_3268_840c_bcbb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x88bc_7411_3f23_def7_9c5a_0fe3_96f4_0f19_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x842c_c5ac_f1d0_344b_6fec_dfa8_19b9_6092_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xff44_89ce_deab_2ca6_e17b_d40d_8d92_91ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xf639_cc18_5088_fe62_5066_e87f_2c0f_733d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xed39_3b1c_2235_1281_ff4e_2e66_0317_d55f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xe442_c00d_e259_1b4c_e96a_b34c_e0bc_cd10_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xdb56_446d_6ad8_df09_2811_2e35_a60e_636f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xd273_b205_8de1_bd4b_36bb_f837_b4d3_20c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xc99a_f2ea_ca4c_457b_eaf5_1f66_6928_44b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xc0cb_f17a_071f_80e9_396f_fdf7_6a14_7cc2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xb806_9857_5607_07a7_0a67_7b4c_8bec_22e0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xaf4a_d26c_bc8e_5bef_9e8b_8b88_a14f_f0c9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0xa698_8ae9_03f5_62f1_7e85_8f08_597b_3a68_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x9def_ad3e_8f73_2186_476d_3b5b_45f6_ca02_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x9550_2522_38bd_2468_658e_5a0b_811c_596d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x8cb9_de8a_32ab_3694_97c9_8595_30a4_514c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -131, + mantissa: 0x842c_c5ac_f1d0_344c_1fec_dfa8_19b9_6094_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xf751_8e00_35c3_dd92_606d_8909_3278_a931_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xe65b_9e6e_ed96_5c4f_609f_5fe2_058d_5ff2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xd577_9687_d887_e0ee_49dd_a170_56e4_5ebb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xc4a5_50a4_fd9a_19bb_3e97_660a_23cc_5402_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xb3e4_a796_a5da_c213_07cc_a0bc_c06c_2f8e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0xa335_76a1_6f1f_4c79_1210_16bd_904d_c95a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0x9297_997c_68c1_f4e6_610d_b3d4_dd42_3bc9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -132, + mantissa: 0x820a_ec4f_3a22_2397_b9e3_aea6_c444_eef6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -133, + mantissa: 0xe31e_9760_a557_8c6d_f9eb_2f28_4f31_c35a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -133, + mantissa: 0xc249_2946_4655_f482_da5f_3cc0_b325_1da6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -133, + mantissa: 0xa195_492c_c066_0519_4a18_dff7_cdb4_ae33_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -133, + mantissa: 0x8102_b2c4_9ac2_3a86_91d0_82dc_e3dd_cd08_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -134, + mantissa: 0xc122_451c_4515_5150_b161_37f0_9a00_2b0e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -134, + mantissa: 0x8080_abac_46f3_89c4_662d_417c_ed00_79c9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0x0000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0x0000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xff80_5515_885e_014e_435a_b4da_6a5b_b50f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xff01_5358_833c_4762_bb48_1c8e_e141_6999_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xbee2_3afc_0853_b6a8_a897_82c2_0df3_50c2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xfe05_4587_e01f_1e2b_f6d3_a69b_d5ea_b72f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x9e75_221a_352b_a751_452b_7ea6_2f21_98ea_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xbdc8_d83e_ad88_d518_7faa_638b_5e00_ee90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xdcfe_013d_7c8c_bfc5_632d_bac4_6f30_d009_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xfc14_d873_c198_0236_c7e0_9e3d_e453_f5fc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x8d86_cc49_1ecb_fe03_f177_6453_b7e8_2558_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x9cf4_3dcf_f5ea_fd2f_2ad9_0155_c8a7_236a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xac52_dd7e_4726_a456_a47a_963a_91bb_3018_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xbba2_c7b1_96e7_e224_e795_0f72_52c1_63cf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xcae4_1876_471f_5bde_91d0_0a41_7e33_0f8e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xda16_eb88_cb8d_f5fb_28a6_3ecf_b66e_94c0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe93b_5c56_d85a_9083_ce29_92bf_ea38_e76b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xf851_8600_8b15_32f9_e64b_8b77_5997_8998_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x83ac_c1ac_c723_8978_5a53_33c4_5b7f_442e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x8b29_b775_1bd7_073b_02e0_b9ee_992f_2372_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x929f_b178_50a0_b7be_5b4d_3807_6605_16a4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9a0e_bcb0_de8e_848e_2c1b_b082_689b_a814_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa176_e5f5_3237_81d2_dcf9_3599_6c92_e8d4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xa8d8_39f8_30c1_fb40_4c73_4351_7c8a_c264_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb032_c549_ba86_1d83_774e_27bc_92ce_3373_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb786_9457_2b5a_5cd3_24cd_cf68_cdb2_067c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xbed3_b36b_d896_6419_7c06_44d7_d9ed_08b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc61a_2eb1_8cd9_07a1_e5a1_532f_6d5a_1ac1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xcd5a_1231_019d_66d7_761e_3e7b_171e_44b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xd493_69d2_56ab_1b1f_9e91_54e1_d526_3cda_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xdbc6_415d_876d_0839_3e33_c0c9_f882_4f54_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe2f2_a47a_de3a_18a8_a0bf_7c0b_0d8b_b4ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xea18_9eb3_659a_eaeb_93b2_a3b2_1f44_8259_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xf138_3b71_5797_2f48_543f_ff0f_f4f0_aaf1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xf851_8600_8b15_3302_5e4b_8b77_5997_8993_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xff64_898e_df55_d548_428c_cfc9_9271_dffa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x8338_a896_52cb_714a_b247_eb86_498c_2ce7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x86bb_f3e6_8472_cb2f_0b8b_d206_1574_7126_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x8a3c_2c23_3a15_6341_9027_c74f_e0e6_f64f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x8db9_56a9_7b3d_0143_f023_472c_d739_f9e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9133_78c8_52d6_5be6_977e_3013_d10f_7525_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x94aa_97c0_ffa9_1a5d_4ee3_880f_b7d3_4429_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x981e_b8c7_23fe_97f2_1f1c_134f_b702_d433_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9b8f_e100_f47b_a1d8_04b6_2af1_89fc_ba0d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9efe_1587_6631_4e4f_4d71_827e_fe89_2fc8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa269_5b66_5be8_f338_4eca_87c3_f0f0_6211_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa5d1_b79c_d2af_2aca_8837_986c_eabf_bed6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa937_2f1d_0da1_bd10_580e_b71e_58cd_36e5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xac99_c6cc_c104_2e94_3dd5_5752_8315_838d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaff9_8385_3c9e_9e40_5f10_5039_091d_d7f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb356_6a13_956a_86f4_471b_1e15_74d9_fd55_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb6b0_7f38_ce90_e463_7bb2_e265_d0de_37e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xba07_c7aa_01bd_2648_43f9_d57b_324b_d05f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xbd5c_4810_86c8_48db_bb59_6b50_3040_3242_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc0ae_050a_1abf_56ad_2f7f_8c5f_a9c5_0d76_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc3fd_0329_0648_847d_3048_0bee_4cbb_d698_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc749_46f4_436a_054e_f4f5_cb53_1201_c0d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xca92_d4e7_a2b5_a3ad_c983_a9c5_c4b3_b135_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcdd9_b173_efdc_1aaa_8863_e007_c184_a1e7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd11d_e0ff_15ab_18c6_d88d_83d4_cc61_3f21_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd45f_67e4_4178_c612_5486_e73c_6151_58b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd79e_4a74_05ff_96c3_1300_c9be_67ae_5da0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xdada_8cf4_7dad_236d_dffb_833c_3409_ee7e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xde14_33a1_6c66_b14c_de74_4870_f54f_0f18_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe14b_42ac_60c6_0512_4e38_eb80_92a0_1f06_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe47f_be3c_d4d1_0d5b_2ec0_f797_fdcd_125c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe7b1_aa70_4e2e_e240_b40f_aab6_d2ad_0841_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xeae1_0b5a_7ddc_8ad8_806b_2fc9_a803_8790_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xee0d_e505_5f63_eb01_90a3_3316_df83_ba5a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf138_3b71_5797_2f4a_b43f_ff0f_f4f0_aaf1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf460_1295_52d2_ff41_e62e_3201_bb2b_bdce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf785_6e5e_e2c9_b28a_76f2_a1b8_4190_a7dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xfaa8_52b2_5bd9_b833_a6db_fa03_186e_0666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xfdc8_c36a_f1f1_5468_0a33_61bc_a696_504a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8073_622d_6a80_e631_e897_0090_1531_6073_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8201_2ca5_a682_06d5_8fde_85af_dd2b_c88a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x838d_c2fe_6ac8_68e7_1a3f_cbde_f401_00cb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8519_2713_9c87_1af8_67bd_00c3_8061_c51f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x86a3_5abc_d5ba_5901_5481_c3cb_d925_ccd2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x882c_5fcd_7256_a8c1_3905_5a65_98e7_c29e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x89b4_3814_9d45_82f5_3453_1dba_493e_b5a6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8b3a_e55d_5d30_701a_c63e_ab88_3717_0480_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8cc0_696e_a11b_7b36_9436_1c9a_28d3_8a6a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8e44_c60b_4ccf_d7dc_1473_aa01_c777_8679_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8fc7_fcf2_4517_946a_380c_be76_9f2c_6793_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x914a_0fde_7bcb_2d0e_c429_ed3a_ea19_7a60_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x92cb_0086_fbb1_cf75_a29d_47c5_0b11_82d0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x944a_d09e_f435_1af1_a498_27e0_81cb_16ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x95c9_81d5_c4e9_24ea_4540_4f5a_a577_d6b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9747_15d7_08e9_84dd_6648_d428_40d9_e6fb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x98c3_8e4a_a20c_27d2_8467_67ec_990d_7333_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9a3e_ecd4_c3ea_a6ae_db3a_7f6e_6087_b947_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9bb9_3315_fec2_d790_7f58_9fba_0865_790f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9d32_62ab_4a2f_4e37_a1ae_6ba0_6846_fae0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9eaa_7d2e_0fb8_7c35_ff47_2bc6_ce64_8a7d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa021_8434_353f_1de4_d493_efa6_3253_0acc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa197_7950_2740_9daa_1dd1_d4a6_df96_0357_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa30c_5e10_e2f6_13e4_9bd9_bd99_e39a_20b3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa480_3402_004e_865c_31cb_e0e8_8241_16cd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa5f2_fcab_bbc5_06d8_68ca_4fb7_ec32_3d74_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa764_b993_0013_4d79_0d04_d104_7430_1862_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa8d5_6c39_6fc1_684c_01eb_067d_578c_4756_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaa45_161d_6e93_167b_9b08_1cf7_2249_f5b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xabb3_b8ba_2ad3_62a1_1db6_506c_c17a_01f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xad21_5587_a67f_0cdf_e890_422c_b86b_7cb1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xae8d_edfa_c04e_5282_ac70_7b8f_fc22_b3e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaff9_8385_3c9e_9e3f_c510_5039_091d_d7f8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb164_1795_ce3c_a978_faf9_1530_0e51_7393_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb2cd_ab98_1f0f_940b_c857_c77d_c1df_600f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb436_40f4_d8a5_761f_f5f0_80a7_1c34_b25d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb59d_d911_aca1_ec48_1d26_64cf_09a0_c1bf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb704_7551_5d0f_1c5e_4c98_c6b8_be17_818d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb86a_1713_c491_aeaa_d37e_e287_2a6f_1cd6_u128, + }, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,822 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +pub(crate) static LOG2P1_EXACT: [u64; 53] = [ + 0x3ff0000000000000, + 0x4008000000000000, + 0x401c000000000000, + 0x402e000000000000, + 0x403f000000000000, + 0x404f800000000000, + 0x405fc00000000000, + 0x406fe00000000000, + 0x407ff00000000000, + 0x408ff80000000000, + 0x409ffc0000000000, + 0x40affe0000000000, + 0x40bfff0000000000, + 0x40cfff8000000000, + 0x40dfffc000000000, + 0x40efffe000000000, + 0x40fffff000000000, + 0x410ffff800000000, + 0x411ffffc00000000, + 0x412ffffe00000000, + 0x413fffff00000000, + 0x414fffff80000000, + 0x415fffffc0000000, + 0x416fffffe0000000, + 0x417ffffff0000000, + 0x418ffffff8000000, + 0x419ffffffc000000, + 0x41affffffe000000, + 0x41bfffffff000000, + 0x41cfffffff800000, + 0x41dfffffffc00000, + 0x41efffffffe00000, + 0x41fffffffff00000, + 0x420ffffffff80000, + 0x421ffffffffc0000, + 0x422ffffffffe0000, + 0x423fffffffff0000, + 0x424fffffffff8000, + 0x425fffffffffc000, + 0x426fffffffffe000, + 0x427ffffffffff000, + 0x428ffffffffff800, + 0x429ffffffffffc00, + 0x42affffffffffe00, + 0x42bfffffffffff00, + 0x42cfffffffffff80, + 0x42dfffffffffffc0, + 0x42efffffffffffe0, + 0x42fffffffffffff0, + 0x430ffffffffffff8, + 0x431ffffffffffffc, + 0x432ffffffffffffe, + 0x433fffffffffffff, +]; + +/* For 362 <= i <= 724, r[i] = LOG2P1_INVERSE[i-362] is a 10-bit approximation of +1/x[i], where i*2^-9 <= x[i] < (i+1)*2^-9. +More precisely r[i] is a 10-bit value such that r[i]*y-1 is representable +exactly on 53 bits for any y, i*2^-9 <= y < (i+1)*2^-9. +Moreover |r[i]*y-1| <= 0.00212097167968735. */ + +pub(crate) static LOG2P1_INVERSE: [u64; 363] = [ + 0x3ff6980000000000, + 0x3ff6880000000000, + 0x3ff6780000000000, + 0x3ff6680000000000, + 0x3ff6580000000000, + 0x3ff6480000000000, + 0x3ff6380000000000, + 0x3ff6300000000000, + 0x3ff6200000000000, + 0x3ff6100000000000, + 0x3ff6000000000000, + 0x3ff5f00000000000, + 0x3ff5e00000000000, + 0x3ff5d00000000000, + 0x3ff5c00000000000, + 0x3ff5b00000000000, + 0x3ff5a80000000000, + 0x3ff5980000000000, + 0x3ff5880000000000, + 0x3ff5780000000000, + 0x3ff5680000000000, + 0x3ff5600000000000, + 0x3ff5500000000000, + 0x3ff5400000000000, + 0x3ff5300000000000, + 0x3ff5200000000000, + 0x3ff5180000000000, + 0x3ff5080000000000, + 0x3ff4f80000000000, + 0x3ff4f00000000000, + 0x3ff4e00000000000, + 0x3ff4d00000000000, + 0x3ff4c00000000000, + 0x3ff4b80000000000, + 0x3ff4a80000000000, + 0x3ff4a00000000000, + 0x3ff4900000000000, + 0x3ff4800000000000, + 0x3ff4780000000000, + 0x3ff4680000000000, + 0x3ff4580000000000, + 0x3ff4500000000000, + 0x3ff4400000000000, + 0x3ff4300000000000, + 0x3ff4280000000000, + 0x3ff4180000000000, + 0x3ff4100000000000, + 0x3ff4000000000000, + 0x3ff3f80000000000, + 0x3ff3e80000000000, + 0x3ff3e00000000000, + 0x3ff3d00000000000, + 0x3ff3c00000000000, + 0x3ff3b80000000000, + 0x3ff3a80000000000, + 0x3ff3a00000000000, + 0x3ff3900000000000, + 0x3ff3880000000000, + 0x3ff3780000000000, + 0x3ff3700000000000, + 0x3ff3600000000000, + 0x3ff3580000000000, + 0x3ff3500000000000, + 0x3ff3400000000000, + 0x3ff3380000000000, + 0x3ff3280000000000, + 0x3ff3200000000000, + 0x3ff3100000000000, + 0x3ff3080000000000, + 0x3ff3000000000000, + 0x3ff2f00000000000, + 0x3ff2e80000000000, + 0x3ff2d80000000000, + 0x3ff2d00000000000, + 0x3ff2c80000000000, + 0x3ff2b80000000000, + 0x3ff2b00000000000, + 0x3ff2a00000000000, + 0x3ff2980000000000, + 0x3ff2900000000000, + 0x3ff2800000000000, + 0x3ff2780000000000, + 0x3ff2700000000000, + 0x3ff2600000000000, + 0x3ff2580000000000, + 0x3ff2500000000000, + 0x3ff2400000000000, + 0x3ff2380000000000, + 0x3ff2300000000000, + 0x3ff2280000000000, + 0x3ff2180000000000, + 0x3ff2100000000000, + 0x3ff2080000000000, + 0x3ff2000000000000, + 0x3ff1f00000000000, + 0x3ff1e80000000000, + 0x3ff1e00000000000, + 0x3ff1d00000000000, + 0x3ff1c80000000000, + 0x3ff1c00000000000, + 0x3ff1b80000000000, + 0x3ff1b00000000000, + 0x3ff1a00000000000, + 0x3ff1980000000000, + 0x3ff1900000000000, + 0x3ff1880000000000, + 0x3ff1800000000000, + 0x3ff1700000000000, + 0x3ff1680000000000, + 0x3ff1600000000000, + 0x3ff1580000000000, + 0x3ff1500000000000, + 0x3ff1400000000000, + 0x3ff1380000000000, + 0x3ff1300000000000, + 0x3ff1280000000000, + 0x3ff1200000000000, + 0x3ff1180000000000, + 0x3ff1100000000000, + 0x3ff1000000000000, + 0x3ff0f80000000000, + 0x3ff0f00000000000, + 0x3ff0e80000000000, + 0x3ff0e00000000000, + 0x3ff0d80000000000, + 0x3ff0d00000000000, + 0x3ff0c80000000000, + 0x3ff0c00000000000, + 0x3ff0b00000000000, + 0x3ff0a80000000000, + 0x3ff0a00000000000, + 0x3ff0980000000000, + 0x3ff0900000000000, + 0x3ff0880000000000, + 0x3ff0800000000000, + 0x3ff0780000000000, + 0x3ff0700000000000, + 0x3ff0680000000000, + 0x3ff0600000000000, + 0x3ff0580000000000, + 0x3ff0500000000000, + 0x3ff0480000000000, + 0x3ff0400000000000, + 0x3ff0380000000000, + 0x3ff0300000000000, + 0x3ff0280000000000, + 0x3ff0200000000000, + 0x3ff0180000000000, + 0x3ff0100000000000, + 0x3ff0080000000000, + 0x3feff80000000000, + 0x3fefe80000000000, + 0x3fefd80000000000, + 0x3fefc80000000000, + 0x3fefb80000000000, + 0x3fefa80000000000, + 0x3fef980000000000, + 0x3fef880000000000, + 0x3fef780000000000, + 0x3fef680000000000, + 0x3fef580000000000, + 0x3fef500000000000, + 0x3fef400000000000, + 0x3fef300000000000, + 0x3fef200000000000, + 0x3fef100000000000, + 0x3fef000000000000, + 0x3feef00000000000, + 0x3feee00000000000, + 0x3feed00000000000, + 0x3feec80000000000, + 0x3feeb80000000000, + 0x3feea80000000000, + 0x3fee980000000000, + 0x3fee880000000000, + 0x3fee780000000000, + 0x3fee700000000000, + 0x3fee600000000000, + 0x3fee500000000000, + 0x3fee400000000000, + 0x3fee300000000000, + 0x3fee280000000000, + 0x3fee180000000000, + 0x3fee080000000000, + 0x3fedf80000000000, + 0x3fedf00000000000, + 0x3fede00000000000, + 0x3fedd00000000000, + 0x3fedc00000000000, + 0x3fedb80000000000, + 0x3feda80000000000, + 0x3fed980000000000, + 0x3fed900000000000, + 0x3fed800000000000, + 0x3fed700000000000, + 0x3fed600000000000, + 0x3fed580000000000, + 0x3fed480000000000, + 0x3fed380000000000, + 0x3fed300000000000, + 0x3fed200000000000, + 0x3fed100000000000, + 0x3fed080000000000, + 0x3fecf80000000000, + 0x3fece80000000000, + 0x3fece00000000000, + 0x3fecd00000000000, + 0x3fecc80000000000, + 0x3fecb80000000000, + 0x3feca80000000000, + 0x3feca00000000000, + 0x3fec900000000000, + 0x3fec880000000000, + 0x3fec780000000000, + 0x3fec680000000000, + 0x3fec600000000000, + 0x3fec500000000000, + 0x3fec480000000000, + 0x3fec380000000000, + 0x3fec300000000000, + 0x3fec200000000000, + 0x3fec180000000000, + 0x3fec080000000000, + 0x3febf80000000000, + 0x3febf00000000000, + 0x3febe00000000000, + 0x3febd80000000000, + 0x3febc80000000000, + 0x3febc00000000000, + 0x3febb00000000000, + 0x3feba80000000000, + 0x3feb980000000000, + 0x3feb900000000000, + 0x3feb800000000000, + 0x3feb780000000000, + 0x3feb680000000000, + 0x3feb600000000000, + 0x3feb580000000000, + 0x3feb480000000000, + 0x3feb400000000000, + 0x3feb300000000000, + 0x3feb280000000000, + 0x3feb180000000000, + 0x3feb100000000000, + 0x3feb000000000000, + 0x3feaf80000000000, + 0x3feaf00000000000, + 0x3feae00000000000, + 0x3fead80000000000, + 0x3feac80000000000, + 0x3feac00000000000, + 0x3feab80000000000, + 0x3feaa80000000000, + 0x3feaa00000000000, + 0x3fea900000000000, + 0x3fea880000000000, + 0x3fea800000000000, + 0x3fea700000000000, + 0x3fea680000000000, + 0x3fea600000000000, + 0x3fea500000000000, + 0x3fea480000000000, + 0x3fea400000000000, + 0x3fea300000000000, + 0x3fea280000000000, + 0x3fea200000000000, + 0x3fea100000000000, + 0x3fea080000000000, + 0x3fea000000000000, + 0x3fe9f00000000000, + 0x3fe9e80000000000, + 0x3fe9e00000000000, + 0x3fe9d00000000000, + 0x3fe9c80000000000, + 0x3fe9c00000000000, + 0x3fe9b00000000000, + 0x3fe9a80000000000, + 0x3fe9a00000000000, + 0x3fe9980000000000, + 0x3fe9880000000000, + 0x3fe9800000000000, + 0x3fe9780000000000, + 0x3fe9680000000000, + 0x3fe9600000000000, + 0x3fe9580000000000, + 0x3fe9500000000000, + 0x3fe9400000000000, + 0x3fe9380000000000, + 0x3fe9300000000000, + 0x3fe9280000000000, + 0x3fe9200000000000, + 0x3fe9100000000000, + 0x3fe9080000000000, + 0x3fe9000000000000, + 0x3fe8f80000000000, + 0x3fe8e80000000000, + 0x3fe8e00000000000, + 0x3fe8d80000000000, + 0x3fe8d00000000000, + 0x3fe8c80000000000, + 0x3fe8b80000000000, + 0x3fe8b00000000000, + 0x3fe8a80000000000, + 0x3fe8a00000000000, + 0x3fe8980000000000, + 0x3fe8880000000000, + 0x3fe8800000000000, + 0x3fe8780000000000, + 0x3fe8700000000000, + 0x3fe8680000000000, + 0x3fe8600000000000, + 0x3fe8500000000000, + 0x3fe8480000000000, + 0x3fe8400000000000, + 0x3fe8380000000000, + 0x3fe8300000000000, + 0x3fe8280000000000, + 0x3fe8200000000000, + 0x3fe8100000000000, + 0x3fe8080000000000, + 0x3fe8000000000000, + 0x3fe7f80000000000, + 0x3fe7f00000000000, + 0x3fe7e80000000000, + 0x3fe7e00000000000, + 0x3fe7d80000000000, + 0x3fe7c80000000000, + 0x3fe7c00000000000, + 0x3fe7b80000000000, + 0x3fe7b00000000000, + 0x3fe7a80000000000, + 0x3fe7a00000000000, + 0x3fe7980000000000, + 0x3fe7900000000000, + 0x3fe7880000000000, + 0x3fe7800000000000, + 0x3fe7780000000000, + 0x3fe7700000000000, + 0x3fe7600000000000, + 0x3fe7580000000000, + 0x3fe7500000000000, + 0x3fe7480000000000, + 0x3fe7400000000000, + 0x3fe7380000000000, + 0x3fe7300000000000, + 0x3fe7280000000000, + 0x3fe7200000000000, + 0x3fe7180000000000, + 0x3fe7100000000000, + 0x3fe7080000000000, + 0x3fe7000000000000, + 0x3fe6f80000000000, + 0x3fe6f00000000000, + 0x3fe6e80000000000, + 0x3fe6e00000000000, + 0x3fe6d80000000000, + 0x3fe6d00000000000, + 0x3fe6c80000000000, + 0x3fe6c00000000000, + 0x3fe6b80000000000, + 0x3fe6b00000000000, + 0x3fe6a80000000000, + 0x3fe6a00000000000, +]; + +pub(crate) static LOG2P1_LOG_DD_INVERSE: [(u64, u64); 363] = [ + (0xbd13c7ca90bc04b2, 0xbfd615ddb4bec000), + (0xbd3527d18f7738fa, 0xbfd5e87b20c29000), + (0x3d339ae8f873fa41, 0xbfd5baf846aa2000), + (0xbd2791f30a795215, 0xbfd58d54f86e0000), + (0x3d11e64778df4a62, 0xbfd55f9107a44000), + (0xbd3df83b7d931501, 0xbfd531ac457ee000), + (0x3d2a68c8f16f9b5d, 0xbfd503a682cb2000), + (0xbd234d7aaf04d104, 0xbfd4ec9732600000), + (0x3d3d7c92cd9ad824, 0xbfd4be5f95778000), + (0x3d38bccffe1a0f8c, 0xbfd4900680401000), + (0x3d13d82f484c84cc, 0xbfd4618bc21c6000), + (0x3d3fb129931715ad, 0xbfd432ef2a04f000), + (0xbd3f8ef43049f7d3, 0xbfd404308686a000), + (0xbd3c3e1cd9a395e3, 0xbfd3d54fa5c1f000), + (0xbd37a71cbcd735d0, 0xbfd3a64c55694000), + (0x3d3e9436ac53b023, 0xbfd3772662bfe000), + (0x3d3b07de4ea1a54a, 0xbfd35f865c933000), + (0xbd36217dc2a3e08b, 0xbfd3302c16586000), + (0xbd342f568b75fcac, 0xbfd300aead063000), + (0xbd360c61f7088353, 0xbfd2d10dec508000), + (0x3d30dbbf51f3aadc, 0xbfd2a1499f763000), + (0xbd3a8d7ad24c13f0, 0xbfd2895a13de8000), + (0xbd38e7bc224ea3e3, 0xbfd2596010df7000), + (0x3d3a6976f5eb0963, 0xbfd22941fbcf8000), + (0xbd27946c040cbe77, 0xbfd1f8ff9e48a000), + (0x3d381410e5c62aff, 0xbfd1c898c169a000), + (0x3d32dd466dc55e2d, 0xbfd1b05791f08000), + (0x3d3a8a8ba74a2684, 0xbfd17fb98e151000), + (0x3d3e97a65dfc9794, 0xbfd14ef67f887000), + (0x3d3d3e8499d67123, 0xbfd136870293b000), + (0x3d34ab9d817d52cd, 0xbfd1058bf9ae5000), + (0xbd3d2c81f640e1e6, 0xbfd0d46b579ab000), + (0xbd0c6bee7ef4030e, 0xbfd0a324e2739000), + (0xbd3ebc1d40c5a329, 0xbfd08a73667c5000), + (0x3d30e866bcd236ad, 0xbfd058f3c703f000), + (0xbcf036b89ef42d7f, 0xbfd0402594b4d000), + (0xbcdcc68d52e01203, 0xbfd00e6c45ad5000), + (0x3d0d572aab993c87, 0xbfcfb9186d5e4000), + (0x3d3f75fd6a526efe, 0xbfcf871b28956000), + (0x3d3f454f1417e41f, 0xbfcf22e5e72f2000), + (0x3d23d45330fdca4d, 0xbfcebe61f4dd8000), + (0x3d26805b80e8e6ff, 0xbfce8c0252aa6000), + (0x3d3a342c2af0003c, 0xbfce27076e2b0000), + (0xbd38fac1a628ccc6, 0xbfcdc1bca0abe000), + (0x3d15105fc364c784, 0xbfcd8ef91af32000), + (0x3d383270128aaa5f, 0xbfcd293581b6c000), + (0xbd2771239a07d55b, 0xbfccf6354e09c000), + (0x3d27794f689f8434, 0xbfcc8ff7c79aa000), + (0xbd20929decb454fc, 0xbfcc5cba543ae000), + (0xbd2386a947c378b5, 0xbfcbf601bb0e4000), + (0xbd39ac53f39d121c, 0xbfcbc286742d8000), + (0x3d34b722ec011f31, 0xbfcb5b519e8fc000), + (0x3cba4e633fcd9066, 0xbfcaf3c94e80c000), + (0x3d3b68f5395f139d, 0xbfcabfe5ae462000), + (0xbd3b99c8ca1d9abb, 0xbfca57df28244000), + (0x3d3539cd91dc9f0b, 0xbfca23bc1fe2c000), + (0x3d21f2a8a1ce0ffc, 0xbfc9bb362e7e0000), + (0xbcf93b564dd44000, 0xbfc986d322818000), + (0xbd37bc6abddeff46, 0xbfc91dcc8c340000), + (0xbd3a8154b13d72d5, 0xbfc8e928de886000), + (0xbd322120401202fc, 0xbfc87fa06520c000), + (0x3d3d8daadf4e2bd2, 0xbfc84abb75866000), + (0x3d302a52f9201ce8, 0xbfc815c0a1436000), + (0x3d2bdb9072534a58, 0xbfc7ab890210e000), + (0xbd0274903479e3d1, 0xbfc7764c128f2000), + (0xbd34ea64f6a95bef, 0xbfc70b8f97a1a000), + (0x3d3bc6e557134767, 0xbfc6d60fe719e000), + (0xbd3aa1bdbfc6c785, 0xbfc66acd4272a000), + (0xbd2d5ec0ab8163af, 0xbfc6350a28aaa000), + (0x3d38586f183bebf2, 0xbfc5ff3070a7a000), + (0xbcf0ba68b7555d4a, 0xbfc59338d9982000), + (0xbd3add94dda647e8, 0xbfc55d1ad4232000), + (0x3d3e9bf2fafeaf27, 0xbfc4f099f4a24000), + (0x3d34354bb3f219e5, 0xbfc4ba36f39a6000), + (0xbd1eea52723f6369, 0xbfc483bccce6e000), + (0x3d210047081f849d, 0xbfc41682bf728000), + (0xbd28a72a62b8c13f, 0xbfc3dfc2b0ecc000), + (0xbd3ee8779b2d8abc, 0xbfc371fc201e8000), + (0xbd3c9ecca2fe72a5, 0xbfc33af575770000), + (0x3cd680b5ce3ecb05, 0xbfc303d718e48000), + (0x3d35b967f4471dfc, 0xbfc29552f8200000), + (0xbd35a3854f176449, 0xbfc25ded0abc6000), + (0x3d24d20ab840e7f6, 0xbfc2266f190a6000), + (0xbd2e80a41811a396, 0xbfc1b72ad52f6000), + (0xbd2843fad093c8dc, 0xbfc17f6458fca000), + (0xbd1563451027c750, 0xbfc1478584674000), + (0xbd3cb2cd2ee2f482, 0xbfc0d77e7cd08000), + (0x3d28f3057157d1a8, 0xbfc09f561ee72000), + (0x3d2a47579cdc0a3d, 0xbfc0671512ca6000), + (0x3d15a8fa5ce00e5d, 0xbfc02ebb42bf4000), + (0x3d010987e897ed01, 0xbfbf7b79fec38000), + (0x3d3d599e83368e91, 0xbfbf0a30c0118000), + (0xbd34677489c50e97, 0xbfbe98b549670000), + (0x3d2a342c2af0003c, 0xbfbe27076e2b0000), + (0x3d29454379135713, 0xbfbd4313d66cc000), + (0xbd33e14db50dd743, 0xbfbcd0cdbf8c0000), + (0xbd1d0c57585fbe06, 0xbfbc5e548f5bc000), + (0x3d325ef7bc3987e7, 0xbfbb78c82bb10000), + (0xbd0ff22c18f84a5e, 0xbfbb05b49bee4000), + (0xbd3563650bd22a9c, 0xbfba926d3a4ac000), + (0xbd3cd4176df97bcb, 0xbfba1ef1d8060000), + (0x3d28a64826787061, 0xbfb9ab4246204000), + (0xbd3b20f5acb42a66, 0xbfb8c345d6318000), + (0x3d37d5cd246977c9, 0xbfb84ef898e84000), + (0xbd32cc844480c89b, 0xbfb7da766d7b0000), + (0x3cfecbc035c4256a, 0xbfb765bf23a6c000), + (0x3d34b4641b664613, 0xbfb6f0d28ae58000), + (0xbd30c3b1dee9c4f8, 0xbfb60658a9374000), + (0xbd3c284f5722abaa, 0xbfb590cafdf00000), + (0xbd383f69278e686a, 0xbfb51b073f060000), + (0x3d2f7fe1308973e2, 0xbfb4a50d3aa1c000), + (0xbd1bc0eeea7c9acd, 0xbfb42edcbea64000), + (0xbd31d09299837610, 0xbfb341d7961bc000), + (0xbd3e1ee2ca657021, 0xbfb2cb0283f5c000), + (0xbd3416f8fb69a701, 0xbfb253f62f0a0000), + (0xbd39444f5e9e8981, 0xbfb1dcb263db0000), + (0x3d147c5e768fa309, 0xbfb16536eea38000), + (0x3d3901f46d48abb4, 0xbfb0ed839b554000), + (0x3d3b8ecfe4b59987, 0xbfb0759835990000), + (0x3d2d599e83368e91, 0xbfaf0a30c0118000), + (0x3d2fea4664629e86, 0xbfae19070c278000), + (0xbd16a423c78a64b0, 0xbfad276b8adb0000), + (0xbd2f2ccc9abf8388, 0xbfac355dd0920000), + (0x3d1c827ae5d6704c, 0xbfab42dd71198000), + (0x3d36e584a0402925, 0xbfaa4fe9ffa40000), + (0x3d2c148297c5feb8, 0xbfa95c830ec90000), + (0x3d12623a134ac693, 0xbfa868a830840000), + (0x3d3181dce586af09, 0xbfa77458f6330000), + (0x3d2b2b739570ad39, 0xbfa58a5bafc90000), + (0xbd211c78a56fd247, 0xbfa494acc34d8000), + (0xbd3eafd480ad9015, 0xbfa39e87b9fe8000), + (0x3d278ce77a9163fe, 0xbfa2a7ec22150000), + (0x3d33401e9ae889bb, 0xbfa1b0d989240000), + (0x3d2e89896f022783, 0xbfa0b94f7c198000), + (0xbd2980267c7e09e4, 0xbf9f829b0e780000), + (0xbd2e61f1658cfb9a, 0xbf9d91a66c540000), + (0x3d3b9a010ae6922a, 0xbf9b9fc027b00000), + (0x3d2d75d97ec7c410, 0xbf99ace7551d0000), + (0x3d33b955b602ace4, 0xbf97b91b07d60000), + (0x3d263bb6216d87d8, 0xbf95c45a51b90000), + (0x3d36a2c432d6a40b, 0xbf93cea443470000), + (0x3d14193a83fcc7a6, 0xbf91d7f7eb9f0000), + (0xbcdf1e7cf6d3a69c, 0xbf8fc0a8b0fc0000), + (0xbd1c25e097bd9771, 0xbf8bcf712c740000), + (0x3d3eb1245b5da1f5, 0xbf87dc475f820000), + (0x3d2609c1ff29a114, 0xbf83e7295d260000), + (0xbd19e23f0dda40e4, 0xbf7fe02a6b100000), + (0xbd0749d3c2d23a07, 0xbf77ee11ebd80000), + (0xbd20bc04a086b56a, 0xbf6ff00aa2b00000), + (0x3d33bc661d61c5eb, 0xbf5ff802a9b00000), + (0x3d356224cd5f35f8, 0x3f50020055600000), + (0x3d285c0696a70c0c, 0x3f68090482880000), + (0x3d1e3871df070002, 0x3f740c8a74780000), + (0xbd3d805512588560, 0x3f7c189cbb100000), + (0x3d3e3d1238c4ea00, 0x3f82145e939e0000), + (0xbd38073eeaf8eaf3, 0x3f861e77e8b60000), + (0xbd3f73bc4d6d3472, 0x3f8a2a9c6c180000), + (0xbd39de88a3da281a, 0x3f8e38ce30340000), + (0x3d3fdbe5fed4b393, 0x3f912487a5500000), + (0x3d2710cb130895fc, 0x3f932db0ea130000), + (0x3d2ab259d2d7f253, 0x3f9537e3f45f0000), + (0x3d07abf389596542, 0x3f963d6178690000), + (0xbd2aa0ba325a0c34, 0x3f98492528c90000), + (0xbd2de0709f2d03c9, 0x3f9a55f548c60000), + (0xbd35439ce030a687, 0x3f9c63d2ec150000), + (0xbd28d75149774d47, 0x3f9e72bf28140000), + (0xbd3dddc7f461c516, 0x3fa0415d89e78000), + (0xbd32b98a9a4168fd, 0x3fa149e3e4008000), + (0x3d283e9ae021b67b, 0x3fa252f32f8d0000), + (0x3d38357d5ef9eb35, 0x3fa35c8bfaa10000), + (0x3d3748ed3f6e378e, 0x3fa3e18c1ca08000), + (0xbd2d9150f73be773, 0x3fa4ebf4334a0000), + (0xbd20485a8012494c, 0x3fa5f6e730790000), + (0xbd2888df11fd5ce7, 0x3fa70265a5510000), + (0xbd399dc16f28bf45, 0x3fa80e7023d90000), + (0xbd19d7c53f76ca96, 0x3fa91b073efd8000), + (0xbd30c22e4ec4d90d, 0x3fa9a187b5740000), + (0x3d20fc1a353bb42e, 0x3faaaef2d0fb0000), + (0xbd17bf868c317c2a, 0x3fabbcebfc690000), + (0x3d3965c36e09f5fe, 0x3faccb73cddd8000), + (0xbd21b1ac64d9e42f, 0x3fadda8adc680000), + (0xbd30f25c74676689, 0x3fae624c4a0b8000), + (0xbd3d6eb0dd5610d3, 0x3faf723b51800000), + (0x3d1111c05cf1d753, 0x3fb0415d89e74000), + (0x3d2c2da80974d976, 0x3fb0c9e615ac4000), + (0xbd37cf69284a3465, 0x3fb10e45b3cb0000), + (0x3d3566d154f930b3, 0x3fb1973bd1464000), + (0x3d349d8cfc10c7bf, 0x3fb2207b5c784000), + (0x3d37a48ba8b1cb41, 0x3fb2aa04a4470000), + (0x3d08081edd77c860, 0x3fb2eee507b40000), + (0x3d37141128f1faca, 0x3fb378dd7f748000), + (0x3d26fd84aa8157c0, 0x3fb403207b414000), + (0x3d3fad46e8d26ab7, 0x3fb4485e03dbc000), + (0xbcf53a2582f4e1ef, 0x3fb4d3115d208000), + (0x3d0c1d740c53c72e, 0x3fb55e10050e0000), + (0x3d31cb7ce1d17171, 0x3fb5e95a4d978000), + (0xbd2179957ed63c4e, 0x3fb62f1be7d78000), + (0x3d0daf3cc08926ae, 0x3fb6bad83c188000), + (0xbd3126d16e1e21d2, 0x3fb746e100228000), + (0x3d069b5794b69fb7, 0x3fb78d02263d8000), + (0xbd3c0fe460d20041, 0x3fb8197e2f410000), + (0x3d3c28c0af9bd6df, 0x3fb8a6477a91c000), + (0xbd222f39be67f7aa, 0x3fb8ecc933aec000), + (0xbcf8bcc1732093ce, 0x3fb97a07024cc000), + (0xbd0a9ce6c9ad51bf, 0x3fba0792e9278000), + (0xbd0e42b6b94407c8, 0x3fba4e7640b1c000), + (0xbd3573b209c31904, 0x3fbadc77ee5b0000), + (0xbceff64eea137079, 0x3fbb23965a530000), + (0xbd368ba835459b8e, 0x3fbbb20e936d8000), + (0x3d3cb1121d1930dd, 0x3fbc40d6425a4000), + (0x3d2646d1c65aacd3, 0x3fbc885801bc4000), + (0x3d336433b5efbeed, 0x3fbd179788218000), + (0x3d30e239cc185469, 0x3fbd5f5565920000), + (0xbd324750412e9a74, 0x3fbdef0d8d468000), + (0xbd32c1c59bc77bfa, 0x3fbe7f1691a34000), + (0x3d311fcba80cdd10, 0x3fbec739830a0000), + (0x3d176a6c9ea8b04e, 0x3fbf57bc7d900000), + (0xbd08f351fa48a730, 0x3fbfa01c9db58000), + (0x3d03f9651cff9dfe, 0x3fc0188d2ecf6000), + (0x3d381a9cf169fc5c, 0x3fc03cdc0a51e000), + (0xbd27e5dd7009902c, 0x3fc08598b59e4000), + (0xbd345519d7032129, 0x3fc0aa0691268000), + (0xbd3e09b441ae86c5, 0x3fc0f301717d0000), + (0xbd2cf5fdd94f6509, 0x3fc13c2605c3a000), + (0x3d2ec2d2a9009e3d, 0x3fc160c8024b2000), + (0xbd31ac38dde3b366, 0x3fc1aa2b7e240000), + (0xbd315c1c39192af9, 0x3fc1ceed09854000), + (0xbd3b3a1e7f50c701, 0x3fc2188fd9808000), + (0x3d100d238fd3df5c, 0x3fc23d712a49c000), + (0x3d37494e359302e6, 0x3fc28753bc11a000), + (0xbd1d3466d0c6c8a8, 0x3fc2ac55095f6000), + (0x3d352b302160f40d, 0x3fc2f677cbbc0000), + (0x3d3f098ee3a50810, 0x3fc31b994d3a4000), + (0xbd3fd3a0afb9691b, 0x3fc365fcb015a000), + (0xbd370ef0545c17f9, 0x3fc38b3e9e028000), + (0x3d13fb2f85096c4b, 0x3fc3d5e3126bc000), + (0x3d319713c0cae559, 0x3fc3fb45a5992000), + (0xbd116282c85a0884, 0x3fc420b327410000), + (0xbd1249cd0790841a, 0x3fc46baf0f9f6000), + (0xbd353e43558124c4, 0x3fc4913d8333c000), + (0x3d0c79b60ae1ff0f, 0x3fc4dc7b897bc000), + (0x3d348a05ff36a25b, 0x3fc5022b292f6000), + (0x3d2746fee5c8d0d8, 0x3fc54dabc2610000), + (0x3d39baa7a6b887f6, 0x3fc5737cc9018000), + (0xbd127023eb68981c, 0x3fc5bf406b544000), + (0xbd31ce0bf3b290ea, 0x3fc5e533144c2000), + (0xbd371456c988f814, 0x3fc60b3100b0a000), + (0xbd398c1d34f0f462, 0x3fc6574ebe8c2000), + (0xbd311e8830a706d3, 0x3fc67d6e9d786000), + (0xbcdc73fafd9b2dca, 0x3fc6c9d07d204000), + (0x3d3577390d31ef0f, 0x3fc6f0128b756000), + (0x3ce51b157cec3838, 0x3fc716600c914000), + (0xbd25e77dc7c5f3e1, 0x3fc7631d82936000), + (0x3d38e67be3dbaf3f, 0x3fc7898d85444000), + (0xbd24c06b17c301d7, 0x3fc7d6903caf6000), + (0xbd158bebf457b7d2, 0x3fc7fd22ff59a000), + (0x3d1e0ddb9a631e83, 0x3fc823c16551a000), + (0x3d3328eb42f9af75, 0x3fc871213750e000), + (0xbd296b37380cbe9e, 0x3fc897e2b17b2000), + (0xbd073d54aae92cd1, 0x3fc8beafeb390000), + (0xbd1935f57718d7ca, 0x3fc90c6db9fcc000), + (0x3d33115c3abd47da, 0x3fc9335e5d594000), + (0x3d07f22858a0ff6f, 0x3fc95a5adcf70000), + (0x3d3470fa3efec390, 0x3fc9a8778deba000), + (0x3d3d862f10c414e3, 0x3fc9cf97cdce0000), + (0xbd3337d94bcd3f43, 0x3fc9f6c40708a000), + (0x3d360a77c81f7171, 0x3fca454082e6a000), + (0xbd3f63b7f037b0c6, 0x3fca6c90d44b8000), + (0xbd28724350562169, 0x3fca93ed3c8ae000), + (0x3d37a8d5ae54f550, 0x3fcae2ca6f672000), + (0xbd22e72d5c3998ed, 0x3fcb0a4b48fc2000), + (0x3d3c794e562a63cb, 0x3fcb31d8575bc000), + (0x3d1e90683b9cd768, 0x3fcb811730b82000), + (0x3d3a32e7f44432da, 0x3fcba8c90ae4a000), + (0xbd2d4bc4595412b6, 0x3fcbd087383be000), + (0xbd292e0ee55c7ac6, 0x3fcc2028ab180000), + (0x3d39a294d5e44e76, 0x3fcc480c0005c000), + (0x3d3ee138d3a69d43, 0x3fcc6ffbc6f00000), + (0x3d23b161a8c6e6c5, 0x3fcc97f8079d4000), + (0xbd29e0aba2099515, 0x3fcce816157f2000), + (0xbd084a7e75b6f6e4, 0x3fcd1037f2656000), + (0xbd373650b38932bc, 0x3fcd386668720000), + (0xbd375f280234bf51, 0x3fcd88e93fb30000), + (0x3d32806a847527e6, 0x3fcdb13db0d48000), + (0xbd302ec669c756eb, 0x3fcdd99edaf6e000), + (0xbd252b00adb91424, 0x3fce020cc6236000), + (0xbd3fdbdbb13f7c18, 0x3fce530effe72000), + (0xbd0d5eee23793649, 0x3fce7ba35eb78000), + (0x3d35e91663732a36, 0x3fcea4449f04a000), + (0xbd3bec63a3e75640, 0x3fceccf2c8fea000), + (0xbcca211565bb8e11, 0x3fcef5ade4dd0000), + (0xbd3bae49f1df7b5e, 0x3fcf474b134e0000), + (0xbd10819516673e23, 0x3fcf702d36778000), + (0xbd390d04cd7cc834, 0x3fcf991c6cb3c000), + (0x3d34bba46f1cf6a0, 0x3fcfc218be620000), + (0x3d31cd8d688b9e18, 0x3fd00a1c6adda000), + (0x3d3a43dcfade85ae, 0x3fd01eae5626c000), + (0x3cf89ff8a966395c, 0x3fd03346e0106000), + (0x3d2dbdf10d397f3c, 0x3fd047e60cde8000), + (0x3d2ad0f1c77ccb58, 0x3fd05c8be0d96000), + (0x3d3e5d513f45fe7b, 0x3fd085eb8f8ae000), + (0x3d3b50a1e1734342, 0x3fd09aa572e6c000), + (0x3d23c7c3f528d80a, 0x3fd0af660eb9e000), + (0x3d27188b163ceae9, 0x3fd0c42d67616000), + (0x3d1ee8c88753fa35, 0x3fd0d8fb813eb000), + (0xbd2f1fbddfdfd686, 0x3fd102ac0a35d000), + (0x3d31ef78ce2d07f2, 0x3fd1178e8227e000), + (0x3d13b2948a11f797, 0x3fd12c77cd007000), + (0x3d3e0c07824daaf5, 0x3fd14167ef367000), + (0xbcee75adfb6aba25, 0x3fd1565eed456000), + (0xbd323299042d74bf, 0x3fd16b5ccbad0000), + (0x3d27d2f73ad1aa14, 0x3fd1956d3b9bc000), + (0x3d29f60a9616f7a0, 0x3fd1aa7fd638d000), + (0xbd31ac89575c2125, 0x3fd1bf99635a7000), + (0x3d222a667c42e56d, 0x3fd1d4b9e796c000), + (0xbd382eaed3c8b65e, 0x3fd1e9e16788a000), + (0x3d3e9d5b513ff0c1, 0x3fd1ff0fe7cf4000), + (0xbd3caf0428b728a3, 0x3fd214456d0ec000), + (0xbd36dbe448a2e522, 0x3fd23ec5991ec000), + (0x3d3b1d7ac0ef77f2, 0x3fd25410494e5000), + (0xbd31b61f10522625, 0x3fd269621134e000), + (0xbd2b198800b4bda7, 0x3fd27ebaf58d9000), + (0xbd3210c2b730e28b, 0x3fd2941afb187000), + (0xbd22058e557285cf, 0x3fd2a982269a4000), + (0x3d2a9cfa4a5004f4, 0x3fd2bef07cdc9000), + (0xbd288d0ddcd54196, 0x3fd2d46602add000), + (0xbd38aed2541e6e2e, 0x3fd2ff66b04eb000), + (0xbd28e27ad3213cb8, 0x3fd314f1e1d36000), + (0x3d04f928139af5d6, 0x3fd32a8456512000), + (0xbd317c73556e291d, 0x3fd3401e12aed000), + (0xbd2ba99b8964f0e8, 0x3fd355bf1bd83000), + (0x3d116ecdb0f177c8, 0x3fd36b6776be1000), + (0xbd2a71e493a0702b, 0x3fd3811728565000), + (0xbd05839c5663663d, 0x3fd396ce359bc000), + (0xbd2d0befbc02be4a, 0x3fd3ac8ca38e6000), + (0x3d183b54b606bd5c, 0x3fd3c25277333000), + (0xbd222c7c2a9d37a4, 0x3fd3d81fb5947000), + (0xbd3f067c297f2c3f, 0x3fd3edf463c17000), + (0xbd3ce379226de3ec, 0x3fd419b423d5f000), + (0x3d3906440f7d3354, 0x3fd42f9f3ff62000), + (0xbd06e95892923d88, 0x3fd44591e053a000), + (0xbd0d9120e7d0a853, 0x3fd45b8c0a17e000), + (0x3d306c18fb4c14c5, 0x3fd4718dc271c000), + (0x3d3dc1b8465cf25f, 0x3fd487970e958000), + (0x3d307b334daf4b9a, 0x3fd49da7f3bcc000), + (0xbd165b4681052b9f, 0x3fd4b3c077268000), + (0xbd2e20891b0ad8a4, 0x3fd4c9e09e173000), + (0xbd34d692a1e44788, 0x3fd4e0086dd8c000), + (0xbd3fc158cb3124b9, 0x3fd4f637ebbaa000), + (0xbd3a0e6b7e827c2c, 0x3fd50c6f1d11c000), + (0x3d2ebe708164c759, 0x3fd522ae0738a000), + (0x3d27ec02e45547ce, 0x3fd538f4af8f7000), + (0x3d1a8954c0910952, 0x3fd54f431b7be000), + (0x3d14c5fd2badc774, 0x3fd5659950695000), + (0x3d1fadedee5d40ef, 0x3fd57bf753c8d000), + (0xbd369bf5a7a56f34, 0x3fd5925d2b113000), + (0xbcf7c79b0af7ecf8, 0x3fd5a8cadbbee000), + (0xbd227023eb68981c, 0x3fd5bf406b544000), + (0xbd0a0b2a08a465dc, 0x3fd5d5bddf596000), + (0x3d36b71a1229d17f, 0x3fd5ec433d5c3000), + (0x3d1ebe9176df3f65, 0x3fd602d08af09000), + (0xbd2f08ad603c488e, 0x3fd61965cdb03000), + (0xbd2db623e731ae00, 0x3fd630030b3ab000), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2p1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2p1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,329 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::logs::LOG_RANGE_REDUCTION; +use crate::polyeval::{f_estrin_polyeval7, f_polyeval6}; + +// Generated in SageMath: +// print("[") +// for i in range(128): +// R = RealField(200) +// r = R(2)**(-8) * ( R(2)**8 * (R(1) - R(2)**(-8)) / (R(1) + R(i)*R(2)**-7) ).ceil() +// +// if i == 0 or i == 127: +// print(double_to_hex(0), ",") +// else: +// print(double_to_hex(-r.log2()), ",") +// print("];") +static LOG2_D: [u64; 128] = [ + 0x0000000000000000, + 0x3f872c7ba20f7327, + 0x3f9743ee861f3556, + 0x3fa184b8e4c56af8, + 0x3fa77394c9d958d5, + 0x3fad6ebd1f1febfe, + 0x3fb1bb32a600549d, + 0x3fb4c560fe68af88, + 0x3fb7d60496cfbb4c, + 0x3fb960caf9abb7ca, + 0x3fbc7b528b70f1c5, + 0x3fbf9c95dc1d1165, + 0x3fc097e38ce60649, + 0x3fc22dadc2ab3497, + 0x3fc3c6fb650cde51, + 0x3fc494f863b8df35, + 0x3fc633a8bf437ce1, + 0x3fc7046031c79f85, + 0x3fc8a8980abfbd32, + 0x3fc97c1cb13c7ec1, + 0x3fcb2602497d5346, + 0x3fcbfc67a7fff4cc, + 0x3fcdac22d3e441d3, + 0x3fce857d3d361368, + 0x3fd01d9bbcfa61d4, + 0x3fd08bce0d95fa38, + 0x3fd169c05363f158, + 0x3fd1d982c9d52708, + 0x3fd249cd2b13cd6c, + 0x3fd32bfee370ee68, + 0x3fd39de8e1559f6f, + 0x3fd4106017c3eca3, + 0x3fd4f6fbb2cec598, + 0x3fd56b22e6b578e5, + 0x3fd5dfdcf1eeae0e, + 0x3fd6552b49986277, + 0x3fd6cb0f6865c8ea, + 0x3fd7b89f02cf2aad, + 0x3fd8304d90c11fd3, + 0x3fd8a8980abfbd32, + 0x3fd921800924dd3b, + 0x3fd99b072a96c6b2, + 0x3fda8ff971810a5e, + 0x3fdb0b67f4f46810, + 0x3fdb877c57b1b070, + 0x3fdc043859e2fdb3, + 0x3fdc819dc2d45fe4, + 0x3fdcffae611ad12b, + 0x3fdd7e6c0abc3579, + 0x3fddfdd89d586e2b, + 0x3fde7df5fe538ab3, + 0x3fdefec61b011f85, + 0x3fdf804ae8d0cd02, + 0x3fe0014332be0033, + 0x3fe042bd4b9a7c99, + 0x3fe08494c66b8ef0, + 0x3fe0c6caaf0c5597, + 0x3fe1096015dee4da, + 0x3fe14c560fe68af9, + 0x3fe18fadb6e2d3c2, + 0x3fe1d368296b5255, + 0x3fe217868b0c37e8, + 0x3fe25c0a0463beb0, + 0x3fe2a0f3c340705c, + 0x3fe2e644fac04fd8, + 0x3fe2e644fac04fd8, + 0x3fe32bfee370ee68, + 0x3fe37222bb70747c, + 0x3fe3b8b1c68fa6ed, + 0x3fe3ffad4e74f1d6, + 0x3fe44716a2c08262, + 0x3fe44716a2c08262, + 0x3fe48eef19317991, + 0x3fe4d7380dcc422d, + 0x3fe51ff2e30214bc, + 0x3fe5692101d9b4a6, + 0x3fe5b2c3da19723b, + 0x3fe5b2c3da19723b, + 0x3fe5fcdce2727ddb, + 0x3fe6476d98ad990a, + 0x3fe6927781d932a8, + 0x3fe6927781d932a8, + 0x3fe6ddfc2a78fc63, + 0x3fe729fd26b707c8, + 0x3fe7767c12967a45, + 0x3fe7767c12967a45, + 0x3fe7c37a9227e7fb, + 0x3fe810fa51bf65fd, + 0x3fe810fa51bf65fd, + 0x3fe85efd062c656d, + 0x3fe8ad846cf369a4, + 0x3fe8ad846cf369a4, + 0x3fe8fc924c89ac84, + 0x3fe94c287492c4db, + 0x3fe94c287492c4db, + 0x3fe99c48be2063c8, + 0x3fe9ecf50bf43f13, + 0x3fe9ecf50bf43f13, + 0x3fea3e2f4ac43f60, + 0x3fea8ff971810a5e, + 0x3fea8ff971810a5e, + 0x3feae255819f022d, + 0x3feb35458761d479, + 0x3feb35458761d479, + 0x3feb88cb9a2ab521, + 0x3feb88cb9a2ab521, + 0x3febdce9dcc96187, + 0x3fec31a27dd00b4a, + 0x3fec31a27dd00b4a, + 0x3fec86f7b7ea4a89, + 0x3fec86f7b7ea4a89, + 0x3fecdcebd2373995, + 0x3fed338120a6dd9d, + 0x3fed338120a6dd9d, + 0x3fed8aba045b01c8, + 0x3fed8aba045b01c8, + 0x3fede298ec0bac0d, + 0x3fede298ec0bac0d, + 0x3fee3b20546f554a, + 0x3fee3b20546f554a, + 0x3fee9452c8a71028, + 0x3fee9452c8a71028, + 0x3feeee32e2aeccbf, + 0x3feeee32e2aeccbf, + 0x3fef48c34bd1e96f, + 0x3fef48c34bd1e96f, + 0x3fefa406bd2443df, + 0x0000000000000000, +]; + +#[inline] +pub(crate) fn core_log2f(x: f64) -> f64 { + let x_u = x.to_bits(); + + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let mut x_e: i32 = -(E_BIAS as i32); + + // log2(x) = log2(2^x_e * x_m) + // = x_e + log2(x_m) + // Range reduction for log2(x_m): + // For each x_m, we would like to find r such that: + // -2^-8 <= r * x_m - 1 < 2^-7 + let shifted = (x_u >> 45) as i32; + let index = shifted & 0x7F; + let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]); + + // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are + // all 1's. + x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i32); + let e_x = x_e as f64; + + let log_r_dd = LOG2_D[index as usize]; + + // hi is exact + let hi = e_x + f64::from_bits(log_r_dd); + + // Set m = 1.mantissa. + let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64; + let m = f64::from_bits(x_m); + + let u; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + u = f_fmla(r, m, -1.0); // exact + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::LOG_CD; + let c_m = x_m & 0x3FFF_E000_0000_0000u64; + let c = f64::from_bits(c_m); + u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact + } + + // Polynomial for log(1+x)/x generated in Sollya: + // d = [-2^-8, 2^-7]; + // f_log2p1 = log2(1 + x)/x; + // Q = fpminimax(f_log2p1, 6, [|D...|], d); + // See ./notes/log10pf_core.sollya + let p = f_polyeval6( + u, + f64::from_bits(0x3ff71547652b82fe), + f64::from_bits(0xbfe71547652b82e7), + f64::from_bits(0x3fdec709dc3b1fd5), + f64::from_bits(0xbfd7154766124214), + f64::from_bits(0x3fd2776bd902599e), + f64::from_bits(0xbfcec586c6f55d08), + ); + f_fmla(p, u, hi) +} + +/// Computes log2(x+1) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_log2p1f(x: f32) -> f32 { + let z = x as f64; + let ux = x.to_bits().wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux == 0 { + // |x| == 0, |x| == inf, x == NaN + if ux == 0 { + return x; + } + if x.is_infinite() { + return if x.is_sign_positive() { + f32::INFINITY + } else { + f32::NAN + }; + } + return x + f32::NAN; + } + + let ax = x.to_bits() & 0x7fff_ffffu32; + + // Use log2p1(x) = log10(1 + x) for |x| > 2^-6; + if ax > 0x3c80_0000u32 { + if x == -1. { + return f32::NEG_INFINITY; + } + let x1p = z + 1.; + if x1p <= 0. { + if x1p == 0. { + return f32::NEG_INFINITY; + } + return f32::NAN; + } + return core_log2f(x1p) as f32; + } + + // log2p1 is expected to be used near zero: + // Polynomial generated by Sollya: + // d = [-2^-6; 2^-6]; + // f_log2pf = log2(1+x)/x; + // Q = fpminimax(f_log2pf, 6, [|D...|], d); + const C: [u64; 7] = [ + 0x3ff71547652b82fe, + 0xbfe71547652b8d18, + 0x3fdec709dc3a501c, + 0xbfd715475b117c95, + 0x3fd2776c3fd833bd, + 0xbfcec9905627faa6, + 0x3fca64536a0ad148, + ]; + let p = f_estrin_polyeval7( + z, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + ); + (p * z) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log2p1f() { + assert_eq!(f_log2p1f(0.0), 0.0); + assert_eq!(f_log2p1f(1.0), 1.0); + assert_eq!(f_log2p1f(-0.0432432), -0.063775845); + assert_eq!(f_log2p1f(-0.009874634), -0.01431689); + assert_eq!(f_log2p1f(1.2443), 1.1662655); + assert_eq!(f_log2p1f(f32::INFINITY), f32::INFINITY); + assert!(f_log2p1f(f32::NEG_INFINITY).is_nan()); + assert!(f_log2p1f(-1.0432432).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2td.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2td.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,119 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::logs::log2td_coeffs::LOG2_NEG_TD; +use crate::pow_tables::POW_INVERSE; +use crate::triple_double::TripleDouble; + +#[inline(always)] +fn log2_poly(z: f64) -> TripleDouble { + /* + See ./notes/dd_log.sollya + */ + const P: [(u64, u64, u64); 11] = [ + (0x38cb46674646bfff, 0x3c7777d0ffda0d23, 0x3ff71547652b82fe), + (0xb90ea6e2f55cd900, 0xbc6777d0ffe87198, 0xbfe71547652b82fe), + (0x391e004d54467330, 0x3c7d27f0556d8546, 0x3fdec709dc3a03fd), + (0xb8b2d21aeeb27bff, 0xbc5775b3aa82c433, 0xbfd71547652b82fe), + (0xb9164a4a186a0c00, 0x3c7e49c9bdb8b680, 0x3fd2776c50ef9bfe), + (0xb8efe23702b5a940, 0x3c6195ba6326b1bf, 0xbfcec709dc3a0414), + (0x38d7695a46fb4b00, 0x3c6f82e7add9bb4d, 0x3fca61762a7adf00), + (0xb8c00e9d3285e000, 0x3c2caf76a9ee1e78, 0xbfc7154764fba5e4), + (0xb8d1ff2b356eee80, 0xbc3f6102bc5ddc49, 0x3fc484b13d3bbed8), + (0xb8edd22b4add09c0, 0x3c4c1da4a1a32f3b, 0xbfc2779952952c26), + (0x388875bd65660001, 0x3c58e09839d588dd, 0x3fc0c9d962b39a7d), + ]; + let mut t = TripleDouble::from_bit_pair(P[10]); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[9])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[8])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[7])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[6])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[5])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[4])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[3])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[2])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[1])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[0])); + TripleDouble::quick_mult_f64(t, z) +} + +#[inline] +pub(crate) fn log2_td(x: f64) -> TripleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log2(x) = log2(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = TripleDouble::from_bit_pair(LOG2_NEG_TD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + let v = TripleDouble::add_f64(be as f64, log_r); + let p = log2_poly(z); + TripleDouble::add_f64(v.hi, TripleDouble::new(v.lo + p.lo, v.mid + p.mid, p.hi)) +} + +#[cfg(test)] +mod tests { + use crate::logs::log2td::log2_td; + + #[test] + fn log2td_test() { + assert_eq!(log2_td(0.0040283203125 / 2.).to_f64(), -8.955605880641546); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2td_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log2td_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log2td_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by SageMath: +```python +values = POW_INV + +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_triple_double("", -RealField(180)(r).log2()) +``` +**/ +pub(crate) static LOG2_NEG_TD: [(u64, u64, u64); 182] = [ + (0x390941b6615224a5, 0xbc61d46ccc53c278, 0xbfdfbc16b902680a), + (0x38f07da8aa70916c, 0x3c6780e41697a095, 0xbfdf38c567bcc541), + (0x391d3c8f5fd3dc67, 0xbc74f9727980f5ed, 0xbfdeb4b847d15bce), + (0xb8e739d205efb04e, 0xbc4be44aae7442ab, 0xbfde2fed3d097298), + (0x3898c9127b6c16fb, 0xbc1274a5715611b7, 0xbfddaa6222064fb9), + (0xb9196a462f40def6, 0xbc74856fb52a53d2, 0xbfdd2414c80bf27d), + (0x390bea8fdeb55632, 0x3c6b517ae88c2fd3, 0xbfdce0a4923a587d), + (0xb908a7815661988f, 0xbc7f9fb952bbbccc, 0xbfdc592fad295b56), + (0xb8e453488bf5b6cc, 0x3c752ef4c737fba5, 0xbfdbd0f2e9e79031), + (0x38fc548eb57fa11c, 0x3c76fae441c09d76, 0xbfdb47ebf73882a1), + (0xb8fc786e3d2aafcf, 0x3c5e5b8daaa73a43, 0xbfdabe18797f1f49), + (0xb91b1fdcc00753ce, 0x3c78a0efca1a184f, 0xbfda33760a7f6051), + (0x38fa1959f815466e, 0x3c7dc938c18e544d, 0xbfd9edd6759b25e0), + (0xb9153e596854d8d8, 0x3c7cc298a148e6ca, 0xbfd961f90527409c), + (0xb8ebb343d8cce6ac, 0x3c7530bdb6949302, 0xbfd8d54673b5c372), + (0x38f53bc13892380d, 0x3c76d266d6cdc959, 0xbfd88e9c72e0b226), + (0xb90911b0bd8dfc92, 0xbc69575b04fa6fbd, 0xbfd800a563161c54), + (0x38ac786dcf6b587c, 0x3c5b90132aeddb58, 0xbfd771d2ba7efb3c), + (0x38edde6c0edf5f9b, 0xbc75e35482d13dc1, 0xbfd6e221cd9d0cde), + (0x390079b0d8796cf7, 0xbc7a3152150d2dbf, 0xbfd699f5248cd4b8), + (0xb9015c2742b99e22, 0x3c7a43fc62b7e690, 0xbfd608f1b42948ae), + (0x38f48bb6c3065717, 0x3c7817fd3b7d7e5d, 0xbfd5c01a39fbd688), + (0xb912cbbddfbc3c96, 0xbc7f73d83987f26d, 0xbfd52dbdfc4c96b3), + (0x38b2cc9a4ea80721, 0x3c1b6d40900b2502, 0xbfd49a784bcd1b8b), + (0x390e110ddda53ed5, 0x3c7aca97d800ce47, 0xbfd4507cfedd4fc4), + (0xb91d40a85c203c0a, 0x3c7a9f3c8bc9672e, 0xbfd3bbd3a0a1dcfb), + (0xb8f186e41376f461, 0x3c63376649b4fc09, 0xbfd37124cea4cded), + (0xb90b8ee38b380b8c, 0xbc7bc4de8f631bcf, 0xbfd2db10fc4d9aaf), + (0x391f0463d2dc68ee, 0xbc78c0e85a908be6, 0xbfd28fab35b32683), + (0x390dfcf160587090, 0xbc65f43469fbe6ea, 0xbfd1f825f6d88e13), + (0xb91a061db1cd272d, 0xbc74a31ce1b7e328, 0xbfd1ac05b291f070), + (0xb903f833b9cd87fa, 0x3c6a7b47d2c352d9, 0xbfd11307dad30b76), + (0xb90ea304fc9566d2, 0x3c76c13816f9f480, 0xbfd0c62975542a8f), + (0x38f4999ebc7b5be1, 0xbc7bc0c69a675517, 0xbfd0790adbb03009), + (0x38f941b6615224a5, 0xbc51d46ccc53c278, 0xbfcfbc16b902680a), + (0x390b074c63fc2e10, 0xbc61dd4a99cc633b, 0xbfcf205339208f27), + (0x38bd01b29154c9bc, 0x3c4e41bd8c32e1be, 0xbfcde73fe3b1480f), + (0x38f77c80fa9696aa, 0x3c5b85a54d7ee2fd, 0xbfcd49ee4c325970), + (0xb902de32e0e76d80, 0x3c6a4ecd69d3b872, 0xbfccac163c770dc9), + (0x38bfcd52b1405dd8, 0xbc6afb63338bed1f, 0xbfcb6ecf175f95e9), + (0xb8da5a90415f750a, 0x3c401ee1343fe7ca, 0xbfcacf5e2db4ec94), + (0xb8edc57adc0d07e5, 0x3c5ae3bd6c6d42f0, 0xbfca2f632320b86b), + (0xb8fbd5bde9064fc5, 0x3c628caf799ad993, 0xbfc8edcae8352b6c), + (0x38b1e10526896a05, 0x3c116edb88c4e2b5, 0xbfc84c2bd02f03b3), + (0x38d23d3d07963ee8, 0x3c3d0364be23e873, 0xbfc7a9fec7d05ddf), + (0x38f4a786b5f060aa, 0xbc6f3314e0985116, 0xbfc663f6fac91316), + (0x38e48bb6c3065717, 0x3c6817fd3b7d7e5d, 0xbfc5c01a39fbd688), + (0x390a35613d82ada7, 0xbc622c022616fdff, 0xbfc51bab907a5c8a), + (0xb8c3eeadb3c7c4e9, 0xbc589c74a0b21fb6, 0xbfc476a9f983f74d), + (0x38e66c9ab03b4ece, 0xbc4f51f2c075a74c, 0xbfc32ae9e278ae1a), + (0xb8d9632ea3495efa, 0x3c6ca25d54d6f775, 0xbfc284294b07a640), + (0xb90575a87dd48ab4, 0xbc67a9150c1e0e58, 0xbfc1dcd197552b7b), + (0x38536121d3d82a7d, 0x3bf94b7dfe0d99a5, 0xbfc134e1b489062e), + (0x38f9009af5640e65, 0x3c5becb2e71abdc8, 0xbfbfc66a0f0b00a5), + (0xb893a950ee2d9c26, 0xbc3cbdb5d9dc29f2, 0xbfbe72ec117fa5b2), + (0xb8f8af0cb05a0a5c, 0xbc5342ce3cc8f2f9, 0xbfbd1e34e35b82da), + (0x38f47869be3af7ef, 0xbc58ecb169b9465f, 0xbfbbc84240adabba), + (0x38d3b67d8a9115c0, 0x3c34bba7e1c43d2c, 0xbfba7111df348494), + (0x38d737dca6ec6478, 0x3c5463736dac9317, 0xbfb918a16e46335b), + (0x38e4a786b5f060aa, 0xbc5f3314e0985116, 0xbfb663f6fac91316), + (0xb8d0a7b1e526a7c3, 0x3c458696424b2e96, 0xbfb507b836033bb7), + (0xb8dda9b52342f8f1, 0x3c43fd9776f25acf, 0xbfb3aa2fdd27f1c3), + (0x38ff4924636e235a, 0x3c5d974c32ba8269, 0xbfb24b5b7e135a3d), + (0xb8f7066b9150f3c8, 0x3c530c22d15199b8, 0xbfb0eb389fa29f9b), + (0xb8decbebcad152bd, 0x3c478cbe51121a94, 0xbfaf1389833253a0), + (0xb8b42bd2b182fdab, 0x3c160e0f2c3388f0, 0xbfac4dfab90aab5f), + (0xb8d5c7c92fd4f7f3, 0xbc482838ed43de84, 0xbfa985bfc3495194), + (0x38dedbe726436947, 0xbc389b03784b5be1, 0xbfa6bad3758efd87), + (0xb8dea50c8ba63a79, 0xbc3013a5b81fc494, 0xbfa3ed3094685a26), + (0xb8c4bcdabff7514c, 0x3c227ebafb056cb9, 0xbfa11cd1d5133413), + (0x38ce9f581ff32546, 0xbc399ba03dc5d34f, 0xbf9c9363ba850f86), + (0x38d06b9f56890d24, 0x3c3d6476077b9fbd, 0xbf96e79685c2d22a), + (0xb8b1b179cc231c2a, 0xbc32ed069b244452, 0xbf91363117a97b0c), + (0x38b777c664136e1b, 0xbc2fe38dec005e54, 0xbf86fe50b6ef0851), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0xb8a7dbe5813706e0, 0x3c0456006875bd76, 0x3f815cfe8eaec830), + (0x38c7f9509188db9f, 0x3c2ae48169cf4cdb, 0x3f8cfee70c5ce5dc), + (0xb8d79e2d0f7ae4d0, 0x3c37910667a9b5f8, 0x3f94564a62192834), + (0xb8d813d8377012b5, 0xbc361176ce5d0a51, 0x3f9a330fd028f75f), + (0xb8d685445ab0c8b5, 0xbc493cced296b87d, 0x3fa00ae7f502c1c4), + (0xb8ebcdc68a46e891, 0xbc4c3f1d5c0cfec8, 0x3fa2ff4b77413dcb), + (0x38a63b39766a5ce1, 0x3c2c62a2f6e13b06, 0x3fa5f6b8a11c3c61), + (0x38ed757f27c1c5b2, 0x3c477970e03f821c, 0x3fa77394c9d958d5), + (0x38d0bf5248279df2, 0xbc486446a6eb19b1, 0x3faa6f9c377dd31b), + (0x387223b831459354, 0x3c0155660710eb2a, 0x3fad6ebd1f1febfe), + (0x38f423e28c15d772, 0xbc57de9078d157a3, 0x3fb0387efbca869e), + (0xb8c9cfd3de88693e, 0x3c298c5452bbce74, 0x3fb1bb32a600549d), + (0xb8d9456e30e04c8b, 0xbc3e20375a3220ba, 0x3fb33f7cde14cf5a), + (0xb8dd9b5327c61668, 0xbc4e40a005e7a3e0, 0x3fb4023b7b26ac9e), + (0xb8d8302738bd7244, 0x3c5a489c555db4a8, 0x3fb588edd4d1ceaa), + (0x38d15de8817f9652, 0xbc524e45ed01d67c, 0x3fb7113f3259e07a), + (0xb8c297cc436527f1, 0x3c34ea44821c1dc2, 0x3fb89b33091d6fe8), + (0xb8d163823d724b8c, 0xbc5d9af608a7a4d8, 0x3fba26ccd9981853), + (0xb8f030b03172242b, 0x3c540238de7ea9f1, 0x3fbaed391ab6674e), + (0xb898fd98ad57a6d5, 0xbc17936311889913, 0x3fbc7b528b70f1c5), + (0xb8f80f8712f10464, 0x3c592ce9636c90a0, 0x3fbe0b1ae8f2fd56), + (0x38ec0a4d34a2fd5c, 0xbc56fb7d020ef0e0, 0x3fbed3a1d4cdbebb), + (0xb8b8adf1dbb4847f, 0x3c3905c241a252f9, 0x3fc032fbbaee6d65), + (0xb903fe7b94dd3deb, 0xbc61d536b72e64f7, 0x3fc0fd02a03727ea), + (0xb8f06547268dda91, 0xbc5df0fdbc295d19, 0x3fc162593186da70), + (0x38e31c1f44f6723a, 0xbc5696e2866c718e, 0x3fc22dadc2ab3497), + (0x38fd32863d2685d2, 0xbc6978b98f7dedf9, 0x3fc2f9e32d5bfdd1), + (0x38ec6ccb73071d8f, 0xbc4b5ac8d9739e01, 0x3fc36052d01c3dd7), + (0xb90321b9c961872d, 0x3c648a7168f01501, 0x3fc42ddd2ba1b4a9), + (0x390f41f9b48ee641, 0x3c67c2c3172b86af, 0x3fc4fc4d4d9bb313), + (0xb8b9b5bedec4594c, 0x3c390e41bca6ef96, 0x3fc563dc29ffacb2), + (0x38dd601656701a20, 0x3c354fae008fbb59, 0x3fc633a8bf437ce1), + (0xb905adb0d2530905, 0x3c6a1981a877433e, 0x3fc69be6fbb3aa6f), + (0xb90f3e5eefe085d3, 0x3c6519f7ed9559d4, 0x3fc76d14a4601225), + (0x38fc9f6eab582c70, 0x3c69ced1447e30ad, 0x3fc7d60496cfbb4c), + (0x3902bdc639cad5c0, 0x3c699aa6df8b7d83, 0x3fc8a8980abfbd32), + (0xb8ca47539e091f76, 0xbc40b273219ed335, 0x3fc9123c1528c6ce), + (0xb8cd48f7f45b5018, 0xbc45359413e77d86, 0x3fc9e63a24971f46), + (0xb8b73b65f96477cb, 0x3c6013b6eaceb921, 0x3fca5094b54d2828), + (0xb9055f0f3a28066a, 0xbc6cc865b3dd0dbb, 0x3fcb2602497d5346), + (0x38f53cf448ae828c, 0x3c569a95f528f2c7, 0x3fcb9115db83a3dd), + (0xb8e2102812a3d1b1, 0xbc4fab00c0500189, 0x3fcc67f7f770a67e), + (0x38fa40fe032a2c66, 0x3c592eeaf409cc88, 0x3fccd3c712d31109), + (0xb887c5ffe75deb96, 0xbc0ba8b1f646ab12, 0x3fcdac22d3e441d3), + (0xb8811c83ec58557f, 0x3c29bf75f08df8fb, 0x3fce18b00e13123d), + (0x38ea7fea131ac432, 0x3c506313e79cf1dc, 0x3fcef28aacd72231), + (0xb9084b9b76dd9f57, 0xbc6bdc0426c3c274, 0x3fcf5fd8a9063e35), + (0x3902c0ac2d3510c7, 0x3c7768994400ca0a, 0x3fd01d9bbcfa61d4), + (0xb90ead7402dbb16c, 0x3c7fdee226b2d7aa, 0x3fd054a474bf0eb7), + (0x38f7ea4900b7ca9f, 0xbc53d56efe4338fe, 0x3fd08bce0d95fa38), + (0xb8ef4d89ee4185a6, 0x3c40de07b685556f, 0x3fd0fa848044b351), + (0xb918d4aa56ccb3b2, 0x3c790ea4cc5a44e3, 0x3fd13211a9b38424), + (0x38fa379cb518805e, 0x3c7a3174c8d0586b, 0x3fd1a190a5d674a0), + (0xb90af38b63e590a5, 0x3c6ae9804237ec8e, 0x3fd1d982c9d52708), + (0x3907a7fd81201c43, 0xbc7343f87991ca1f, 0x3fd21196e87473d1), + (0x38fc178bd3a1edca, 0xbc57154f4085d044, 0x3fd28225bb5e64a4), + (0x38e7ab84f442d263, 0xbc50132ae5e417cd, 0x3fd2baa0c34be1ec), + (0x39026a2436846fab, 0xbc7bc5dc0ebe6308, 0x3fd2f33e6d2120f2), + (0xb9047b4beb18bc59, 0xbc687bf1007a1695, 0x3fd364e2511cc821), + (0xb919992a2440dc93, 0x3c7fcad2f4710e00, 0x3fd39de8e1559f6f), + (0x38ead80ac1494e37, 0xbc69cee46ebe3a2d, 0x3fd3d712bf9c9def), + (0xb9134ed7c8d82134, 0xbc7c658d602e66b0, 0x3fd4106017c3eca3), + (0x38f81bffac5a3040, 0xbc75759f8091112d, 0x3fd48365e695d797), + (0x390122141b6e6cce, 0xbc75e341793e8e12, 0x3fd4bd1eb680e548), + (0xb90844a77a231cf3, 0x3c7e393a16b94b52, 0x3fd4f6fbb2cec598), + (0x390784ce0b08724e, 0xbc78d86531d55da2, 0x3fd56b22e6b578e5), + (0x38fdb88067f0d789, 0x3c7885b23dbdaaf1, 0x3fd5a56d7a370ded), + (0x391c3aeac5cdb196, 0x3c710b5b643a6ecb, 0x3fd5dfdcf1eeae0e), + (0x38f9a8ddc498a5b0, 0x3c515f01e8fdf6ad, 0x3fd61a717cac1983), + (0x38d9002dddd7f2ce, 0x3c3d3cd794eee08b, 0x3fd6900a8836d0d5), + (0x38c2cc9a4ea80721, 0x3c2b6d40900b2502, 0x3fd6cb0f6865c8ea), + (0x38cf01842d4b2f59, 0x3c6cbc6f17205b76, 0x3fd7063a1a5fb4f2), + (0xb915071dd6fa27c2, 0xbc726bfff0133975, 0x3fd7418acebbf18f), + (0xb914f2a5689dd709, 0xbc76d8d6e54d428b, 0x3fd77d01b66fbd37), + (0xb8e0b434dd18e7de, 0x3c6412d04e355531, 0x3fd7f462e58e1688), + (0x38f6527e7e840122, 0x3c651d58525aad39, 0x3fd8304d90c11fd3), + (0x38e516a4b1855739, 0xbc71660ad9487503, 0x3fd86c5f36dea3dc), + (0x3912bdc639cad5c0, 0x3c799aa6df8b7d83, 0x3fd8a8980abfbd32), + (0xb91995b025e39b60, 0xbc740df0e173c574, 0x3fd8e4f83fa145ee), + (0x38f93dd58663d90f, 0x3c7fdc46af571993, 0x3fd921800924dd3b), + (0xb8f0939e6edc060c, 0x3c7bca36fd02def0, 0x3fd99b072a96c6b2), + (0xb91659657a3f4cd6, 0xbc7cf91d2080a35b, 0x3fd9d806ebc9921c), + (0x390d166fe5d876b2, 0xbc64278cd1699312, 0x3fda152f142981b4), + (0xb8fec39dceb08f82, 0x3c6b56b1d743ac01, 0x3fda527fd95fd8ff), + (0x38d48bb6c3065717, 0x3c5817fd3b7d7e5d, 0x3fda8ff971810a5e), + (0xb8e711410d392f17, 0x3c77061311743a68, 0x3fdacd9c130dd53f), + (0x38c45703d2c5dcbe, 0xbc45e13b838eba7d, 0x3fdb0b67f4f46810), + (0xb8fd917ff9c35ae9, 0xbc501d98c3531027, 0x3fdb877c57b1b070), + (0x3907193712b6e51c, 0xbc78a87a168550fe, 0x3fdbc5c5489254cc), + (0x391d391561769b34, 0x3c7edf515c63dd87, 0x3fdc043859e2fdb3), + (0xb905c1e916668206, 0xbc687a4c86c71df7, 0x3fdc42d5c4c688b4), + (0x38efe382a72aa9a4, 0x3c6c4aec56233279, 0x3fdc819dc2d45fe4), + (0xb8ff56b5607ee8e4, 0x3c5d3c79567f954e, 0x3fdcc0908e19b7bd), + (0x390e73e7b9e3ba70, 0x3c78a38b4175d665, 0x3fdcffae611ad12b), + (0x38ef3d2624494be1, 0xbc4e2b378ff59cbb, 0x3fdd3ef776d43ff4), + (0xb90611295daec3b0, 0xbc6e15a52a31604a, 0x3fdd7e6c0abc3579), + (0x38f6dcd082b5ed11, 0xbc76a568b022e9a3, 0x3fddbe0c58c3cff2), + (0x38c4b12ca495197c, 0x3c438c8946414c6a, 0x3fddfdd89d586e2b), + (0x38f9351168f2db59, 0xbc63aeabca24fd25, 0x3fde3dd1156507de), + (0x38eeaaf81af2c453, 0x3c73bed456b24ed1, 0x3fde7df5fe538ab3), + (0x391a697a348a408c, 0x3c7ff93949a1897d, 0x3fdebe47960e3c08), + (0xb8fe170ccb0f7762, 0x3c76d261f1753e0b, 0x3fdefec61b011f85), + (0xb900da9304567477, 0xbc7f4c8f8f9cbfe1, 0x3fdf3f71cc1b629c), + (0x391c1a6aa9135b96, 0xbc79ca1a3202b3d7, 0x3fdf804ae8d0cd02), + (0xb8f5b4fa1d9fe122, 0x3c5b9a81085cd3b3, 0x3fdfc151b11b3640), + (0x391dd3a12d527b9c, 0xbc87398fe685f171, 0x3fe0014332be0033), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dd.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,218 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::log_dd_coeffs::LOG_NEG_DD; +use crate::polyeval::f_polyeval7; +use crate::pow_tables::POW_INVERSE; + +#[inline(always)] +pub(crate) fn log_poly(z: f64) -> DoubleDouble { + /* + See ./notes/dd_log.sollya + */ + const P: [(u64, u64); 9] = [ + (0x3c755555556a4311, 0x3fd5555555555555), + (0x3b8ffa82859b4000, 0xbfd0000000000000), + (0xbc699b6b44796cd4, 0x3fc999999999999a), + (0x3c489642b3424250, 0xbfc5555555555563), + (0x3c60e3ef2c7fc443, 0x3fc24924924924ad), + (0x3c535269fe0ce5df, 0xbfbfffffffc0b25c), + (0x3c24f14f55e95858, 0x3fbc71c71c187ea4), + (0x3c5b15951c5e1a17, 0xbfb999d71e5042d5), + (0x3c5ecb0133e43410, 0x3fb74615b842a94d), + ]; + let x2 = DoubleDouble::from_exact_mult(z, z); + let mut t = DoubleDouble::quick_mul_f64_add( + DoubleDouble::from_bit_pair(P[8]), + z, + DoubleDouble::from_bit_pair(P[7]), + ); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[6])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[5])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[4])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[3])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[2])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[1])); + t = DoubleDouble::quick_mul_f64_add(t, z, DoubleDouble::from_bit_pair(P[0])); + t = DoubleDouble::quick_mult(t, x2); + t = DoubleDouble::quick_mult_f64(t, z); + DoubleDouble::mul_f64_add(x2, -0.5, t) +} + +#[inline(always)] +pub(crate) fn log_poly_fast(z: f64) -> DoubleDouble { + /* + See ./notes/dd_log_fast.sollya + */ + let x2 = DoubleDouble::from_exact_mult(z, z); + let r = f_polyeval7( + z, + f64::from_bits(0xbfc5555555555555), + f64::from_bits(0x3fc24924924924aa), + f64::from_bits(0xbfc000000000bc96), + f64::from_bits(0x3fbc71c71c202bf0), + f64::from_bits(0xbfb9999839f1aa36), + f64::from_bits(0x3fb74612adef67e0), + f64::from_bits(0xbfb5cb6ab20b8efa), + ); + let mut p = DoubleDouble::f64_mul_f64_add( + z, + r, + DoubleDouble::from_bit_pair((0xbc699b293fa3344b, 0x3fc999999999999a)), + ); + p = DoubleDouble::mul_f64_add( + p, + z, + DoubleDouble::from_bit_pair((0xbb3b08905e500000, 0xbfd0000000000000)), + ); + p = DoubleDouble::mul_f64_add( + p, + z, + DoubleDouble::from_bit_pair((0x3c7555555567a1b0, 0x3fd5555555555555)), + ); + let mut t = DoubleDouble::quick_mult(x2, p); + t = DoubleDouble::quick_mult_f64(t, z); + DoubleDouble::mul_f64_add(x2, -0.5, t) +} + +#[inline] +pub(crate) fn log_dd(x: f64) -> DoubleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(LOG_NEG_DD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let tt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let v = DoubleDouble::full_add_f64(tt, z); + let p = log_poly(z); + DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)) +} + +#[inline] +pub(crate) fn log_dd_fast(x: f64) -> DoubleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let log_r = DoubleDouble::from_bit_pair(LOG_NEG_DD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c7abc9e3b39803f), + f64::from_bits(0x3fe62e42fefa39ef), + ); + + let tt = DoubleDouble::mul_f64_add(LOG2_DD, be as f64, log_r); + + let v = DoubleDouble::full_add_f64(tt, z); + let p = log_poly_fast(z); + DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log_dd() { + assert_eq!(log_dd(std::f64::consts::E).to_f64(), 1.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dd_coeffs.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd_coeffs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dd_coeffs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dd_coeffs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,228 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by Sage: +from POW_INV +```python +R = RealField(150) + +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +real_array = [R(hex_to_float(h)) for h in values] + +for r in real_array: + print_double_double("", -RealField(120)(r).log()) +``` +**/ +pub(crate) static LOG_NEG_DD: [(u64, u64); 182] = [ + (0x3c6bc60efafc6f6e, 0xbfd5ff3070a793d4), + (0x3c78ebcb7dee9a3d, 0xbfd5a42ab0f4cfe2), + (0x3c6819cf7e308ddb, 0xbfd548a2c3add263), + (0x3c742a87d977dc5e, 0xbfd4ec973260026a), + (0x3c69ffc341f177dc, 0xbfd49006804009d1), + (0x3c729931715ac903, 0xbfd432ef2a04e814), + (0x3c70bcfb6082ce6d, 0xbfd404308686a7e4), + (0x3c6c68651945f97c, 0xbfd3a64c556945ea), + (0x3c64dd4c580919f8, 0xbfd347dd9a987d55), + (0x3c78f4cdb95ebdf9, 0xbfd2e8e2bae11d31), + (0xbc77ad24c13f040e, 0xbfd2895a13de86a3), + (0x3c776f5eb09628af, 0xbfd22941fbcf7966), + (0x3c7c9fdf9a0c4b07, 0xbfd1f8ff9e48a2f3), + (0xbc79d3d1b0e4d147, 0xbfd1980d2dd4236f), + (0xbc77b66298edd24a, 0xbfd136870293a8b0), + (0xbc589fa0ab4cb31d, 0xbfd1058bf9ae4ad5), + (0xbc77dcfde8061c03, 0xbfd0a324e27390e3), + (0x3c628ec217a5022d, 0xbfd0402594b4d041), + (0x3c6caaae64f21acb, 0xbfcfb9186d5e3e2b), + (0xbc2c5f6dfd018c37, 0xbfcf550a564b7b37), + (0x3c46e03a39bfc89b, 0xbfce8c0252aa5a60), + (0x3c461578001e0162, 0xbfce27076e2af2e6), + (0xbc66e443597e4d40, 0xbfcd5c216b4fbb91), + (0x3c64f689f8434012, 0xbfcc8ff7c79a9a22), + (0x3c673dee38a3fb6b, 0xbfcc2968558c18c1), + (0xbc6ba27fdc19e1a0, 0xbfcb5b519e8fb5a4), + (0x3c5398cff3641985, 0xbfcaf3c94e80bff3), + (0xbc493711b07a998c, 0xbfca23bc1fe2b563), + (0xbc6575e31f003e0c, 0xbfc9bb362e7dfb83), + (0x3c6569d851a56770, 0xbfc8e928de886d41), + (0x3c6bf7fdbfa08d9a, 0xbfc87fa06520c911), + (0xbc4be36b2d6a0608, 0xbfc7ab890210d909), + (0x3c5b264062a84cdb, 0xbfc740f8f54037a5), + (0x3c6caae268ecd179, 0xbfc6d60fe719d21d), + (0x3c5bc60efafc6f6e, 0xbfc5ff3070a793d4), + (0x3c565d22aa8ad7cf, 0xbfc59338d9982086), + (0xbc668981bcc36756, 0xbfc4ba36f39a55e5), + (0xbc69f4f6543e1f88, 0xbfc44d2b6ccb7d1e), + (0x3c5ab3a8e7d81017, 0xbfc3dfc2b0ecc62a), + (0x3c06b9c7d96091fa, 0xbfc303d718e47fd3), + (0xbc6301771c407dbf, 0xbfc29552f81ff523), + (0xbc6f547bf1809e88, 0xbfc2266f190a5acb), + (0xbc6a28813e3a7f07, 0xbfc14785846742ac), + (0xbc69a5dc5e9030ac, 0xbfc0d77e7cd08e59), + (0xbc550c647eb86499, 0xbfc0671512ca596e), + (0xbc585f325c5bbacd, 0xbfbf0a30c01162a6), + (0x3c361578001e0162, 0xbfbe27076e2af2e6), + (0xbc5790dd951d90fa, 0xbfbd4313d66cb35d), + (0xbc35d617ef8161b1, 0xbfbc5e548f5bc743), + (0xbc5942f48aa70ea9, 0xbfba926d3a4ad563), + (0x3c42099e1c184e8e, 0xbfb9ab42462033ad), + (0x3c24a697ab3424a9, 0xbfb8c345d6319b21), + (0x3c5eeedfcdd94131, 0xbfb7da766d7b12cd), + (0x3c5388458ec21b6a, 0xbfb60658a93750c4), + (0xbc5a49e39a1a8be4, 0xbfb51b073f06183f), + (0xbc4ddd4f935996c9, 0xbfb42edcbea646f0), + (0x3c5b599f227becbb, 0xbfb341d7961bd1d1), + (0x3c1c125963fc4cfd, 0xbfb253f62f0a1417), + (0x3c379da3e8c22cda, 0xbfb16536eea37ae1), + (0xbc485f325c5bbacd, 0xbfaf0a30c01162a6), + (0xbc21e3c53257fd47, 0xbfad276b8adb0b52), + (0x3c3eb9759c130499, 0xbfab42dd711971bf), + (0xbc4f5a0e80520bf2, 0xbfa95c830ec8e3eb), + (0xbc418d3ca87b9296, 0xbfa77458f632dcfc), + (0x3c4ce55c2b4e2b72, 0xbfa58a5bafc8e4d5), + (0x3c45bfa937f551bb, 0xbfa39e87b9febd60), + (0x3c3e9ae889bac481, 0xbfa1b0d98923d980), + (0xbc333e3f04f1ef23, 0xbf9f829b0e783300), + (0x3bf0ae69229dc868, 0xbf9b9fc027af9198), + (0x3c35b602ace3a510, 0xbf97b91b07d5b11b), + (0x3c10cb5a902b3a1c, 0xbf93cea44346a575), + (0x3c183092c59642a1, 0xbf8fc0a8b0fc03e4), + (0x3c116d7687d3df21, 0xbf87dc475f810a77), + (0x3bce44b7e3711ebf, 0xbf7fe02a6b106789), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3bec14b9f9377a1d, 0x3f78121214586b54), + (0xbc2c5517f64bc223, 0x3f841929f96832f0), + (0x3c2806208c04c220, 0x3f8c317384c75f06), + (0xbc2cd7b66e01c26d, 0x3f9228fb1fea2e28), + (0xbbf8ed4d357c9c97, 0x3f963d6178690bd6), + (0x3c1ec1a5f86d41f9, 0x3f9a55f548c5c43f), + (0x3c375b44595cab18, 0x3f9e72bf2813ce51), + (0x3c4c05cf1d753622, 0x3fa0415d89e74444), + (0xbc4947f792615916, 0x3fa252f32f8d183f), + (0xbc4cdd6f7f4a137e, 0x3fa466aed42de3ea), + (0x3c40413e6505e603, 0x3fa67c94f2d4bb58), + (0x3c3a8be97660a23d, 0x3fa894aa149fb343), + (0x3c2a353bb42e0add, 0x3faaaef2d0fb10fc), + (0x3c3e5cf3a0f56f72, 0x3fabbcebfc68f420), + (0x3c44e6c986f44c55, 0x3fadda8adc67ee4e), + (0xbc4cd9f1f95c2eed, 0x3faffa6911ab9301), + (0xbc5a4a128d192686, 0x3fb10e45b3cae831), + (0xbc5cc0fbce104eaa, 0x3fb2207b5c78549e), + (0xbc5d15d38d2fa3f7, 0x3fb2aa04a44717a5), + (0x3c47a976d3b5b45f, 0x3fb3bdf5a7d1ee64), + (0x3c5769f42c7842cc, 0x3fb4d3115d207eac), + (0xbc545f9d61c68c1b, 0x3fb55e10050e0384), + (0xbc59acd8b33f8fdc, 0x3fb674f089365a7a), + (0x3c5abca5b4fdb880, 0x3fb78d02263d82d3), + (0x3c3b9f2dffbeed43, 0x3fb8197e2f40e3f0), + (0xbc5478a85704ccb7, 0x3fb9335e5d594989), + (0xbc55b5ca203e4259, 0x3fba4e7640b1bc38), + (0x3c537d8f39bee659, 0x3fbadc77ee5aea8c), + (0xbc4cdc9f6f5f38c7, 0x3fbbf968769fca11), + (0x3c49daf7df76ad2a, 0x3fbd179788219364), + (0x3c5401fa71733019, 0x3fbda727638446a2), + (0xbc4a2bf991780d3f, 0x3fbec739830a1120), + (0xbc59361574fb24e2, 0x3fbf57bc7d9005db), + (0x3c639e2d3f8b7d10, 0x3fc03cdc0a51ec0d), + (0xbc6dd7009902bf32, 0x3fc08598b59e3a07), + (0xbc50e63a5f01c691, 0x3fc1178e8227e47c), + (0xbc62d56ff61c2bfb, 0x3fc160c8024b27b1), + (0x3c462c9ef939ac5d, 0x3fc1f3b925f25d41), + (0xbc66e38161051d69, 0x3fc23d712a49c202), + (0xbc5499a3f25af95f, 0x3fc2d1610c86813a), + (0xbc5c4716bdfc0cc9, 0x3fc31b994d3a4f85), + (0x3c370d6cdf05266c, 0x3fc3b08b6757f2a9), + (0xbc6d87e6a354d056, 0x3fc3fb45a59928cc), + (0xbc50d5604930f135, 0x3fc4913d8333b561), + (0xbc6927d47803c5f4, 0x3fc4dc7b897bc1c8), + (0x3c64f4d710fec38e, 0x3fc5737cc9018cdd), + (0xbc21f5b44c0df7e7, 0x3fc5bf406b543db2), + (0xbc3d34f0f4621bed, 0x3fc6574ebe8c133a), + (0x3c696332bd4b341f, 0x3fc6a399dabbd383), + (0xbc68de59c21e166c, 0x3fc6f0128b756abc), + (0x3c5ef8f6ebcfb201, 0x3fc7898d85444c73), + (0xbc4ac5f0c075b847, 0x3fc7d6903caf5ad0), + (0x3c6d685f35eea2a0, 0x3fc871213750e994), + (0x3c555aa8b6997a40, 0x3fc8beafeb38fe8c), + (0x3c6054473941ad99, 0x3fc90c6db9fcbcd9), + (0x3c6f47dfd871f87f, 0x3fc9a8778debaa38), + (0x3c435a19605e67ef, 0x3fc9f6c407089664), + (0x3c5df207dc5c34c6, 0x3fca454082e6ab05), + (0x3c6ab5ca9eaa088a, 0x3fcae2ca6f672bd4), + (0xbc66353ab386a94d, 0x3fcb31d8575bce3d), + (0x3c3a0ee735d9f0ec, 0x3fcb811730b823d2), + (0x3c3dd355f6a516d7, 0x3fcbd087383bd8ad), + (0xbc68e58b2c57a4a5, 0x3fcc6ffbc6f00f71), + (0x3c653d154280394f, 0x3fccc000c9db3c52), + (0x3c660629242471a2, 0x3fcd1037f2655e7b), + (0x3c5aa11d49f96cb9, 0x3fcdb13db0d48940), + (0x3c5fea48dd7b81d1, 0x3fce020cc6235ab5), + (0x3c42276041f43042, 0x3fce530effe71012), + (0xbc6d33919ab94074, 0x3fcea4449f04aaf5), + (0xbc527c77ded76aad, 0x3fcf474b134df229), + (0x3c6f665066f980a2, 0x3fcf991c6cb3b379), + (0x3c28de00938b4c40, 0x3fcfeb2233ea07cd), + (0xbc418290bd2932e2, 0x3fd01eae5626c691), + (0xbc70779634061cbc, 0x3fd047e60cde83b8), + (0x3c643c2e68684d53, 0x3fd09aa572e6c6d4), + (0x3c5162c79d5d11ee, 0x3fd0c42d676162e3), + (0xbc692b49ef282b09, 0x3fd0edd060b78081), + (0xbc60e63a5f01c691, 0x3fd1178e8227e47c), + (0x3c1e0936abd4fa6e, 0x3fd14167ef367783), + (0x3c766fbd28b40935, 0x3fd16b5ccbacfb73), + (0xbc612aeb84249223, 0x3fd1bf99635a6b95), + (0x3c7512c3749a1e4e, 0x3fd1e9e1678899f4), + (0x3c6f7ae91aeba60a, 0x3fd214456d0eb8d4), + (0x3c3bb75d1addf870, 0x3fd23ec5991eba49), + (0x3c7e0efadd9db02b, 0x3fd269621134db92), + (0xbc6856e61c515740, 0x3fd2941afb186b7c), + (0xbc782dad7fd86088, 0x3fd2bef07cdc9354), + (0xbc73d69909e5c3dc, 0x3fd314f1e1d35ce4), + (0xbc5cd55b8a4746c0, 0x3fd3401e12aecba1), + (0xbc5324f0e883858e, 0x3fd36b6776be1117), + (0xbc5ce2b31b31e8b0, 0x3fd396ce359bbf54), + (0xbc72ad27e50a8ec6, 0x3fd3c25277333184), + (0x3c783d680d3c1084, 0x3fd3edf463c1683e), + (0x3c60dbb243827392, 0x3fd419b423d5e8c7), + (0xbc72b125247b0fa5, 0x3fd44591e0539f49), + (0x3c38fb4c14c56eef, 0x3fd4718dc271c41b), + (0xbc69964a168ccaca, 0x3fd49da7f3bcc41f), + (0xbc5123615b147a5d, 0x3fd4c9e09e172c3c), + (0xbc758cb3124b9245, 0x3fd4f637ebba9810), + (0xbc68f7e9b38a6979, 0x3fd522ae0738a3d8), + (0xbc7aacfdbbdab914, 0x3fd54f431b7be1a9), + (0xbc60908d15f88b63, 0x3fd57bf753c8d1fb), + (0xbc5e6c2bdfb3e037, 0x3fd5a8cadbbedfa1), + (0xbc76541148cbb8a2, 0x3fd5d5bddf595f30), + (0xbc56e8920c09b73f, 0x3fd602d08af091ec), + (0x3c6dc18ce51fff99, 0x3fd630030b3aac49), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dyadic.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dyadic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_dyadic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_dyadic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3134 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +pub(crate) static LOG_STEP_1: [DyadicFloat128; 128] = [ + // -log(r) with 128-bit precision generated by SageMath with: + // for i in range(128): + // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) ); + // s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); + // print("{RationalSign::Pos,", e, ", format_hex(m), "},"); + /* .step_1= */ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x8080abac_46f38946_662d417c_ed007a46_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0x8102b2c4_9ac23a4f_91d082dc_e3ddcd38_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc2492946_4655f45c_da5f3cc0_b3251dbd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0x820aec4f_3a222380_b9e3aea6_c444ef07_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xa33576a1_6f1f4c64_521016bd_904dc968_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc4a550a4_fd9a19a8_be97660a_23cc540d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xe65b9e6e_ed965c36_e09f5fe2_058d6006_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x842cc5ac_f1d03445_1fecdfa8_19b96098_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x8cb9de8a_32ab368a_a7c98595_30a45153_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9defad3e_8f73217a_976d3b5b_45f6ca0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xaf4ad26c_bc8e5be7_0e8b8b88_a14ff0ce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xb8069857_560707a3_6a677b4c_8bec22e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc99af2ea_ca4c4570_eaf51f66_692844ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xdb56446d_6ad8deff_a8112e35_a60e6375_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe442c00d_e2591b47_196ab34c_e0bccd12_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xf639cc18_5088fe5d_4066e87f_2c0f7340_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xff4489ce_deab2ca6_c17bd40d_8d9291ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x88bc7411_3f23def1_9c5a0fe3_96f40f1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x8d515bf1_1fb94f1c_88713268_840cbcc0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x968b0864_3409ceb6_65c0da50_6a088484_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9b2fe580_ac80b17d_411a5b94_4aca8708_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa489ec19_9dab06f2_a9fb6cf0_ecb411b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xa93f2f25_0dac67d1_cad2fb8d_48054ae0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb2ba75f4_6099cf8b_2c3c2e77_904afa78_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xb780945b_ab55dce4_34c7bc3d_32750fde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc11e0b2a_8d1e0ddb_9a631e83_0fd30904_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc5f57f59_c7f46155_aa8b6997_a402bf30_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcad2d6e7_b80bf914_2c507fb7_a3d0bf6a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd49f69e4_56cf1b79_5f53bd2e_406e66e7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xd98ec2ba_de71e539_58a98f2a_d65bee9b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xde8439c1_dec56877_4d57da94_5b5d0aaa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe881bf93_2af3dac0_c524848e_3443e040_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xed89ed86_a44a01aa_11d49f96_cb88317b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf29877ff_38809091_3b020fa1_820c9492_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf7ad6f26_e7ff2ef7_54d2238f_75f969b1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xfcc8e365_9d9bcbec_ca0cdf30_1431b60f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8389c302_6ac3139b_62dda9d2_270fa1f4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x86216b3b_0b17188b_163ceae8_8f720f1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x88bc7411_3f23def1_9c5a0fe3_96f40f1e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8b5ae65d_67db9acd_f7a51681_26a58b9a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8dfccb1a_d35ca6ed_5147bdb6_ddcaf59c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x95f783e6_e49a9cfa_4a5004f3_ef063313_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x98a78f0e_9ae71d85_2cdec347_84707839_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9b5b3bb5_f088b766_d878bbe3_d392be25_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9e1293b9_998c1daa_5b035eae_273a855f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa0cda11e_af46390d_bb243827_3918db7e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa38c6e13_8e20d831_f698298a_dddd7f32_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa64f04f0_b961df76_e4f5275c_2d15c21f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa9157039_c51ebe70_8164c759_686a2209_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xabdfba9e_468fd6f6_f72ea077_49ce6bd3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xaeadeefa_caf97d35_7dd6e688_ebb13b03_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb1801859_d56249dc_18ce51ff_f99479cd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb45641f4_e350a0d3_2756eba0_0bc33978_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb7307735_78cb90b2_be1116c3_466beb6d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xba0ec3b6_33dd8b09_49dc60b2_b059a60b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xbcf13343_e7d9ec7d_2efd1778_1bb3afec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xbfd7d1de_c0a8df6f_37eda996_244bccb0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xc2c2abbb_6e5fd56f_33337789_d592e296_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xc5b1cd44_596fa51e_1a18fb8f_9f9ef280_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xc8a5431a_dfb44ca5_688ce7c1_a75e341a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcb9d1a18_9ab56e76_2d7e9307_c70c0668_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xce995f50_af69d861_ef2f3f4f_861ad6a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd19a2011_27d3c645_7f9d79f5_1dcc7301_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd19a2011_27d3c645_7f9d79f5_1dcc7301_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd49f69e4_56cf1b79_5f53bd2e_406e66e7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd7a94a92_466e833a_ad88bba7_d0cee8e0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xdab7d022_31484a92_96c20cca_6efe2ac5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xddcb08dc_0717d85b_f40a666c_87842843_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe0e30349_fd1cec80_7fe8e180_2aba24d6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe0e30349_fd1cec80_7fe8e180_2aba24d6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe3ffce3a_2aa64922_3eadb651_b49ac53a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe72178c0_323a1a0f_304e1653_e71d9973_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xea481236_f7d35baf_e9a767a8_0d6d97e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xed73aa42_64b0ade9_4f91cf4b_33e42998_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf0a450d1_39366ca6_fc66eb64_08ff6433_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf0a450d1_39366ca6_fc66eb64_08ff6433_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf3da161e_ed6b9aaf_ac8d42f7_8d3e65d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf7150ab5_a09f27f4_5a470250_d40ebe90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xfa553f70_18c966f2_b780a545_a1b54dcf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xfa553f70_18c966f2_b780a545_a1b54dcf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xfd9ac57b_d244217e_8f05924d_258c14c5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8072d72d_903d588b_89d1b09c_70c4010a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x821b05f3_b01d6774_030d58c3_f7e2ea1f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x821b05f3_b01d6774_030d58c3_f7e2ea1f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x83c5f829_9e2b4091_20f6fafe_8fbb68b9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8573b716_82a7d21a_e21f9f89_c1ab80b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8573b716_82a7d21a_e21f9f89_c1ab80b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x87244c30_8e670a66_01e005d0_6dbfa8f8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x88d7c11e_3ad53cdc_223111a7_07b6de2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x88d7c11e_3ad53cdc_223111a7_07b6de2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8a8e1fb7_94b09134_2eb628db_a173c82d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8c477207_91e53313_be2ad194_15fe25a5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8c477207_91e53313_be2ad194_15fe25a5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8e03c24d_73003959_bddae1cc_ce247838_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8fc31afe_30b2c6de_9b00bf16_7e95da67_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8fc31afe_30b2c6de_9b00bf16_7e95da67_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x918586c5_f5e4bf01_9b92199e_d1a4bab1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x934b1089_a6dc93c1_df5bb3b6_0554e152_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9513c368_76083695_f3cbc416_a2418012_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x96dfaabd_86fa1646_be1188fb_c94e2f15_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x96dfaabd_86fa1646_be1188fb_c94e2f15_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x98aed221_a03458b6_1d2f8932_1647b358_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x98aed221_a03458b6_1d2f8932_1647b358_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9a81456c_ec642e0f_e549f9aa_ea3cb5e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9c5710b8_cbb73a42_a2554b2d_d4619e63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9c5710b8_cbb73a42_a2554b2d_d4619e63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9e304061_b5fda919_30603d87_b6df81ad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9e304061_b5fda919_30603d87_b6df81ad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa00ce109_2e5498c3_67879c5a_30cd1242_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa1ecff97_c91e267b_0b7efae0_8e597e16_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa1ecff97_c91e267b_0b7efae0_8e597e16_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa3d0a93f_45169a4a_83594fab_088c0d65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa3d0a93f_45169a4a_83594fab_088c0d65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa5b7eb7c_b860fb88_af6a62a0_dec6e073_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa5b7eb7c_b860fb88_af6a62a0_dec6e073_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa7a2d41a_d270c9d7_49362382_a768847a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa7a2d41a_d270c9d7_49362382_a768847a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa9917134_33c2b998_8ba4aea6_14d05701_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa9917134_33c2b998_8ba4aea6_14d05701_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xab83d135_dc633301_7fe6607b_a902ef3c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xab83d135_dc633301_7fe6607b_a902ef3c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xad7a02e1_b24efd31_d60864fd_949b4bd3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xad7a02e1_b24efd31_d60864fd_949b4bd3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xaf741551_20c9011c_066d235e_e63073dd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0_u128, + }, +]; + +pub(crate) static LOG_STEP_2: [DyadicFloat128; 193] = + // -log(r) for the second step, generated by SageMath with: + // + // for i in range(-2^6, 2^7 + 1): + // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) ); + // s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); + // print("{RationalSign::Pos," if s == -1 else "{RationalSign::Neg,", e, ", + // format_hex(m), "},"); + /* .step_2 = */ + [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -135, + mantissa: 0x803faaca_c419abf2_a1c6f3fc_242ef8d0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xfc834da1_6f0d9f57_a225ebc0_2e6d9dd4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xf88735cc_c7433381_c33f6ad3_40ae18a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xf48b0e17_1249b6bc_70b2a4d3_8a242244_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xf08ed67f_d190e280_1d548190_48b811b0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xec928f06_86828706_aee59837_01d2a02b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xe89637aa_b2828aed_40abb8ab_72afa2d2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xe499d06b_d6eeead5_deb547a0_d4a26ef9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xe09d5949_751fb909_39c5bdfb_cf6087a0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xdca0d243_0e671d18_53ea9bf1_52de635f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xd8a43b58_2411537e_25b82043_6f5f4352_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xd4a79488_3764ad41_3c2d13ea_1d0be058_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xd0aaddd2_c9a18f95_4f3cfa62_bcb3ce3a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xccae1737_5c02737c_d0fff6cd_f14a86c7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xc8b140b5_6fbbe56a_7587b5f0_453ac3d2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xc4b45a4c_85fc84e2_b358ad16_dfd0d085_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xc0b763fc_1fed041d_3c86fdce_5dbe7314_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xbcba5dc3_beb027a6_70764e46_ac18a96d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xb8bd47a2_e362c600_c63be62b_8f285882_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xb3c0d59a_244325a4_72e7b5a3_86e5e31b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xafc39bac_66434f27_c3ea2cd9_3f316b34_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xabc651d4_91a7b438_1dfb11a7_cc892843_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xa7c8f812_2773f38d_fc679a28_e9d9f212_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0xa3cb8e64_a8a5bbe6_e7bc977e_eec42254_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x9fce14cb_9634cba6_b20f215b_d3b58c61_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x9bd08b46_7112f078_abe28625_08d67a98_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x97d2f1d4_ba2c06f0_d1aacedc_efe9d377_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x93d54875_f265fa2c_f1eb25e7_7d05f58d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x8fd78f29_9aa0c375_cbef6fac_33691e95_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x8bd9c5ef_33b669e0_27206404_62a0f8ad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x87dbecc6_3e7b01ed_e2f17751_34c8da75_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -136, + mantissa: 0x83de03ae_3bbcad2e_ff67e201_c8c50d67_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xffc0154d_588733c5_3c742a7c_76356396_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xf7c4035e_21a4052f_f90dd6b2_4aa686ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xefc7d18d_d4485b9e_ca47c52b_7d7ffce2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xe7cb7fdb_71e0db36_3703617a_d3d8311f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xdfcf0e45_fbce3e80_7e4cfbd8_30393b88_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xd7d27ccc_736555af_4f7a29cf_0fc2c38e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xcfd5cb6d_d9ef05dd_7370ae83_f9e72748_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xc7d8fa29_30a84850_671486eb_4cd76f65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xbfdc08fd_78c229b9_e6dbb624_f9739782_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xb7def7e9_b361c979_6b866e09_e57d9079_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xafe1c6ec_e1a058dd_97fa2fd0_c9dc723e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xa7e47606_048b1a65_983e8089_7cf1e60f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0x9fe70534_1d236102_7199cd06_ae5d39b3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0x97e97476_2c5e8f58_43cd18a7_2a051a96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0x8febc3cb_332616ff_7b6d1248_c3e1fd40_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0x87edf332_325777c5_f5572a88_14c703af_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xffe00554_55887de0_26828c92_649a3a39_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xefe3e464_3a640cf3_82c550bd_1216d82a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xdfe78392_14b4e8ae_da6959f7_f0e01bf0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xcfeae2db_e5d6736d_da93e2fa_85a8f214_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xbfee023f_af0c2480_b47505bf_a5a03b06_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0xaff0e1bb_718186ad_b1475a51_80a43520_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0x9ff3814d_2e4a36b2_a8740b91_c95df537_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -138, + mantissa: 0x8ff5e0f2_e661e1c6_57d895d3_5921b59c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -139, + mantissa: 0xfff00155_35588833_3c56c598_c659c2a3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -139, + mantissa: 0xdff3c0e4_97ea4eb1_2ef8ec33_ed9d782a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -139, + mantissa: 0xbff7008f_f5e0c257_379eba7e_6465ff63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -139, + mantissa: 0x9ff9c053_5073a370_3f972b78_3fcab757_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -140, + mantissa: 0xfff80055_51558885_de026e27_1ee0549d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -140, + mantissa: 0xbffb8023_febc0c25_eceb47ea_01f6c632_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -141, + mantissa: 0xfffc0015_54d55888_7333c578_57e1ed52_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0xfffe0005_55455588_87dde026_fa704374_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: 0, + mantissa: 0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -141, + mantissa: 0x80010002_aab2aac4_44999abe_2fe2cc65_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0x8002000a_aaeaac44_4eef3815_81464ccb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0xc0048024_01440c26_dfeb4850_85f6f454_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0x8004002a_acaac445_99abe3be_3a1c6e93_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xa0064053_5a37a37a_6bc1e20e_ac8448b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xc0090090_0a20c275_979eedc0_64c242fd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -139, + mantissa: 0xe00c40e4_bd6e4efd_c72446cc_1bf728bd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0x800800aa_baac446e_f381b821_bbb569e5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0x900a20f3_19a3e273_569b26aa_a485ea5c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xa00c814d_7c6a37f8_2dcf56c8_3c80b028_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xb00f21bb_e3e388ee_5f697682_84463b9b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xc0120240_510c284c_b48ea6c0_5e2773a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xd01522dc_c4f87991_14d9d761_96d8043a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xe0188393_40d4f241_e016a611_a4415d72_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -138, + mantissa: 0xf01c2465_c5e61b6f_661e135f_49a47c40_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0x801002ab_2ac4499a_be6bf0fa_435e8383_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0x88121333_7898871e_9a31ba0c_bc030353_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0x901443cc_cd362c9f_54b57dfe_0c4c840f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0x98169478_296fad41_7ad1e9c3_15328f7e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xa0190536_8e2389b3_1f3f686c_f3d6be22_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xa81b9608_fc3c50ec_f105b66e_c4703ede_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xb01e46f0_74b0a0f3_610848c6_8df4d233_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xb82117ed_f8832797_d6aef30c_d312169a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xc0240902_88c2a339_f3ac3796_08053d9d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xc8271a2f_2689e388_e6e2acf8_f4d4c24a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xd02a4b74_d2ffca44_ce6ae474_d860359f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xd82d9cd4_8f574c00_28bb3cd9_f2a65fb5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xe0310e4f_5ccf70e1_54f30dbe_f38a8066_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xe8349fe6_3cb35564_224a96f5_a7471c46_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xf038519a_305a2b1b_6ea92059_1aa02e1b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xf83c236c_39273972_d462b637_56c87e80_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x80200aae_ac44ef38_338f7760_5fe77f2a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x842213b7_47fec7bb_3ff51287_882500ed_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x88242cd0_7084ed02_cc394b3e_f0ebeb12_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x8c2655fa_a6a1323f_1ab9679b_55f78a6b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x90288f36_6b237771_7025697d_10af0436_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x942ad884_3ee1a9cd_17e4b7ac_6c600cb4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x982d31e4_a2b7c418_7013925a_9a8da7f3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0x9c2f9b58_1787cf0d_fd1a09c8_48e3950e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xa03214df_1e39e1bd_84dd2de6_e3d90a37_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xa4349e7a_37bc21ed_318b2ddd_9d0a33b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xa8373829_e502c47a_bc031e6f_5acfd4a8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xac39e1ee_a7080dbc_9dd91e52_c79fd070_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xb03c9bc8_fecc51e3_4af78fa1_cb48a12d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xb43f65b9_6d55f55a_72de1d99_ce252efd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xb74187bc_8ccffa84_efb1dbe7_21934877_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xbb446dd4_d9bca499_b4b080f2_30c87598_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xbf476404_a05f88f2_da6a7cd1_9c7fa4f2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xc34a6a4c_61d5cc3c_df00e378_3b50ecfb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xc74d80ac_9f42a52d_da2e5e02_ab4e183c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xcb50a725_d9cf5ce6_ea5f6ee9_9d30c626_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xcf53ddb8_92ab4f55_a96d5956_531d7d8b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xd3572465_4b0beb95_a8fc636e_b36afa75_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xd75a7b2c_842cb451_f67e2b82_7bfc4421_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xdb5de20e_bf4f4026_a6d8c817_516303e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xdf61590c_7dbb3a02_69b36ae5_962e85f4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xe364e026_40be6188_24693eec_2a831cc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xe768775c_89ac8b70_94a339d5_6a55ab4a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xeb6c1eaf_d9dfa1eb_fa9998fb_f9703bf4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xef6fd620_b2b7a503_cafdc272_27b71eaa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xf3739daf_959aaafc_688d4282_f6026aa3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xf777755d_03f4e0b6_e54e9e38_04464cdd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xfb7b5d29_7f388a12_cb78b383_f4b59dce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -136, + mantissa: 0xff7f5515_88de024f_ee055fc5_15062c04_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x81c1ae90_d131de38_207812b4_3382acdd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x83c3baa7_26a721cc_dc90c4c4_b61f3a87_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x85c5cece_05941dbc_1a03f13f_b2c978b1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x87c7eb05_aec1304f_b36f282e_83a7dc36_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x89ca0f4e_62f9c476_6ad14c3d_fa414391_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x8bcc3ba8_630c51f4_e8dd4ea0_d48b88e5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x8dce7013_efca5d96_c02515af_e8caeb90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x8fd0ac91_4a08795f_741ceaf3_349f3cf1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x91d2f120_b29e44bb_83f7cd49_29d2c28c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x93d53dc2_6a666cb1_795d03eb_c2fd03fa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x95d79276_b23eac12_faf74f1d_1ad16acc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x97d9ef3d_cb07cbad_e2de134f_72fee429_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x99dc5417_f5a5a27d_58d8dba6_cadac5d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x9bdec105_72ff15da_f07d90bc_5aae40a4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x9d609804_6659ea6b_1deaf79d_9fc40374_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0x9f631314_50b07988_7ba63e67_69b81999_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa1659638_404d5f92_59ebfc93_35094e59_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa3682170_7622f97a_16aae012_b5026f71_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa56ab4bd_3326b378_ff5d4f2c_0e4b9cae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa76d501e_b8510941_855838b5_119dcb28_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xa96ff395_469d8630_75f70cbb_e9cf1603_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xab729f21_1f0ac57e_36a53ad4_d5541cc9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xad7552c2_829a7270_04c5934e_c32d20d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xaf780e79_b2514889_3977e89a_ec59bfa2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xb17ad246_ef3713bc_913d4e3d_c55c3e6e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xb37d9e2a_7a56b09d_777b52a9_e70d8bcc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xb5807224_94be0c91_55de916f_d30591de_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xb7834e35_7f7e2600_e79cfb37_be2861e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xb986325d_7bab0c89_90983104_d3805389_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xbb891e9c_ca5be12e_b860504b_aa6f984d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xbd8c12f3_acaad68b_29178d6f_f5712b96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xbf8f0f62_63b53102_7236fa47_ba19a198_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc19213e9_309b46f2_4f34d64c_afcc50e3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc3952088_548080e4_120cc62e_b0a8db3e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc5983540_108b59be_11aa5084_779060e3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc79b5210_a5e55ef5_1c35fd62_36c8dcf1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xc99e76fa_55bb30bd_ed4576a7_e4b878fe_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xcb20d7fa_3a336081_6caf4bb8_fd2c1131_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xcd240b10_753e78de_3f24a6cb_b09c654f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xcf274640_7e0ff09f_78bc003b_b81e40f3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd12a898a_95dff002_56647301_edfd8e8b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd32dd4ee_fde9b2ef_28fe1c4d_04ca4ed9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd531286d_f76b892a_e1ea9ea6_cbf57379_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd7348407_c3a6d688_a3832028_141a5cc2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xd937e7bc_a3e0131b_557421dd_379d3ead_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xdb3b538c_d95ecb67_3cff8e87_a99bcaf0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xdd3ec778_a56da093_99255ef3_4bd0801f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xdf424380_495a489c_42b33220_abfa15cd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe145c7a4_06758e83_503b378f_aa97dbc0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe34953e4_1e135282_bdf2ca00_6f59b544_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe54ce840_d18a8a3e_1979190a_f37ed16f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe75084ba_623540f4_31863ff7_cf898c9c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xe9542951_117097b0_c983284f_60293647_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xeb57d605_209cc57e_510a969e_be03f804_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xed5b8ad6_d11d1797_9f53bffc_6d23fe30_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xef5f47c6_6457f199_b286c6e1_13337886_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf0e21acd_d6e7d412_b6ed8085_2ae6fd63_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf2e5e5f2_5450c5a2_df437fb0_f616082d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf4e9b935_685dbe0b_f237cff1_acb306b3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf6ed9497_5480b696_52dbfafb_4121a092_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xf8f17818_5a2ebfd9_0d816482_49cece4c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xfaf563b8_bae001eb_ad95e6b0_b96903d3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xfcf95778_b80fbc98_176cd568_87ac7fe9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -135, + mantissa: 0xfefd5358_933c478c_65f4c739_7f1f478d_u128, + }, + ]; + +pub(crate) static LOG_STEP_3: [DyadicFloat128; 161] = + // -log(r) for the third step, generated by SageMath with: + // + // for i in range(-80, 81): + // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) ); + // s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); + // print("{RationalSign::Pos," if (s == -1) else "{RationalSign::Neg,", e, ", + // format_hex(m), "},"); + /* .step_3 = */ + [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x9fff3801_4d52e45a_374b2940_76d669c3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x9dff3cf9_40fad85a_7f6f05dc_dbeb776e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x9bff41e1_34f1cb36_3d55e21d_41bbadf9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x99ff46b9_2936bcf4_ccdba2d5_4aadbc5c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x97ff4b81_1dc8ad9d_71dd16d3_073f79b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x95ff5039_12a69d37_5837f3df_1a58dd48_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x93ff54e1_07cf8bc9_93cad3bc_dd26fd6d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x91ff5978_fd42795b_2075312a_827f14fa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x8fff5e00_f2fe65f2_e21764e1_39c98f60_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x8dff6278_e9025197_a492a295_51751b4c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x8bff66e0_df4d3c50_1bc8f5f6_58f1c3a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x89ff6b38_d5de2622_e39d3faf_42340ed7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x87ff6f80_ccb40f16_7ff33266_82c02485_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x85ff73b8_c3cdf731_5caf4fbe_343cf928_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x83ff77e0_bb2ade79_cdb6e554_348f7fe8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -142, + mantissa: 0x81ff7bf8_b2c9c4f6_0ef009c2_457de25d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xffff0001_55535558_8883333c_57b57c74_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xfbff07f1_45931f44_f32668f3_9c70d183_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xf7ff0fc1_3650e7bd_459a73c6_a6486fe3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xf3ff1771_278aaecd_37b18cca_7dd3a29f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xefff1f01_193e7480_513f610d_21bcfc78_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xebff2671_0b6a38e1_ea190b95_c0690b7b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xe7ff2dc0_fe0bfbfd_2a150f64_f0ad1743_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xe3ff34f0_f121bddd_090b5174_e995e9d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xdfff3c00_e4a97e8c_4ed512b9_b93ea2bf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xdbff42f0_d8a13e15_934cea21_7ab794a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xd7ff49c0_cd06fc83_3e4ebe94_8afd2c76_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xd3ff5070_c1d8b9df_87b7c0f5_bcfee2e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xcfff5700_b7147634_77666622_8cb6371b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xcbff5d70_acb8318b_e53a60f3_514db358_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xc7ff63c0_a2c1ebef_79149c3b_6e57fa86_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xc3ff69f0_992fa568_aad734c9_8416df2a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xbfff7000_8fff5e00_c2657367_9ed28334_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xbbff75f0_872f15c0_d7a3c6db_6540809f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xb7ff7bc0_7ebcccb1_d277bde6_45fb1aad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xb3ff8170_76a682dc_6ac80145_a4087793_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xafff8700_6eea3849_287c4db3_0271e265_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xabff8c70_6785ed00_637d6de4_2eeb151e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xa7ff91c0_6077a10a_43b5348b_6b898a8c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0xa3ff96f0_59bd546e_c10e7657_978bd7f6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x9fff9c00_53550735_a37503f4_57310e59_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x9bffa0f0_4d3cb966_82d5a40a_3aa022ff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x97ffa5c0_47726b08_c71e0d3e_e3df5f4d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x93ffaa70_41f41c23_a83ce035_2bdbd79b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x8fffaf00_3cbfccbe_2e21a18d_4680e8e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x8bffb370_37d37cdf_30bcb3e4_e5dfbd28_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x87ffb7c0_332d2c8d_57ff51d7_5c66d64a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -143, + mantissa: 0x83ffbbf0_2ecadbcf_1bdb87fd_be299f43_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xffff8000_55551555_88885dde_02700703_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xf7ff87e0_4d94724c_d259ca80_3a0c1870_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xefff8f80_464fce8f_e5141308_51c7070a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xe7ff96e0_3f832a2a_30a16898_f3073a64_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xdfff9e00_392a8526_c4ed6451_7b2949ce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xd7ffa4e0_3341df90_51e4fb4e_32cf6350_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xcfffab80_2dc53971_277672a8_8350bcce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xc7ffb1e0_28b092d3_35915377_2a490f06_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xbfffb800_23ffebc0_0c265ece_6b481a0e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xb7ffbde0_1faf4440_db2781c0_3fa132f6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xafffc380_1bba9c5e_7287c95c_845ada33_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0xa7ffc8e0_181df421_423b56b1_263e5a77_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0x9fffce00_14d54b91_5a3752ca_4c076fa3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0x97ffd2e0_11dca2b6_6a71e2b2_7eb3f573_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0x8fffd780_0f2ff997_c2e21b72_cff39d8f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -144, + mantissa: 0x87ffdbe0_0ccb503c_537ff612_feb7ac9e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xffffc000_15554d55_58888733_33c57c18_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xefffc7c0_1193f9d1_fa514218_42311c42_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xdfffcf00_0e4aa5fa_2c4ed6de_475b942c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xcfffd5c0_0b7151d8_ce77678c_bb6fcb88_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xbfffdc00_08fffd78_00c26629_a679ed3b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0xafffe1c0_06eea8e1_23287cb9_d3072728_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0x9fffe700_0535541c_d5a37540_fd057315_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -145, + mantissa: 0x8fffebc0_03cbff32_f82e21c1_fce36810_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -146, + mantissa: 0xffffe000_05555455_5588887d_dde02702_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -146, + mantissa: 0xdfffe780_0392aa14_9ac4ed72_adf5b295_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -146, + mantissa: 0xbfffee00_023fffaf_000c2664_8066b482_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -146, + mantissa: 0x9ffff380_014d552e_455a3754_b292c077_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -147, + mantissa: 0xfffff000_01555535_55588888_33333c58_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -147, + mantissa: 0xbffff700_008ffff5_e000c266_5736679f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -148, + mantissa: 0xfffff800_00555551_55558888_85ddde02_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -149, + mantissa: 0xfffffc00_00155554_d5555888_88733334_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -148, + mantissa: 0x80000200_000aaaaa_eaaaac44_444eeeef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -147, + mantissa: 0x80000400_002aaaac_aaaac444_459999ac_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -147, + mantissa: 0xc0000900_0090000a_2000c266_7596679f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0x80000800_00aaaaba_aaac4444_6eeef381_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0xa0000c80_014d557c_655a3755_f81815cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0xc0001200_02400051_000c2668_4c66b482_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0xe0001880_0392ab40_bac4ed7c_40fb07eb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0x80001000_02aaab2a_aac44449_999abe2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0x90001440_03cc00cd_082e21d7_9cbb6812_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xa0001900_0535568d_d5a37569_adb01dc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xb0001e40_06eeac74_33287d01_e8c9d1d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xc0002400_09000288_00c266a3_2679ed48_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xd0002a40_0b7158d1_de776851_22b2764b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xe0003100_0e4aaf5b_2c4ed810_a8063f03_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -145, + mantissa: 0xf0003840_1194062e_0a5143e7_be891c8f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0x80002000_0aaaaeaa_ac4444ee_ef3813a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0x88002420_0ccb5a6e_5b7ff7fe_1339025b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0x90002880_0f300668_42e21e26_caf39e33_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0x98002d20_11dcb29e_f271e66f_a5554bc6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xa0003200_14d55f19_5a3757e0_615cc676_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xa8003720_181e0bde_ca3b5d82_10ca5cab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xb0003c80_1bbab8f6_f287d25f_3cb032bb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xb8004220_1faf6669_e3278d84_0be28cdb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xc0004800_24001440_0c266dfe_6b482076_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xc8004e20_28b0c282_3d9166de_380a6d3d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xd0005480_2dc57139_a7768b35_6ba61e4b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xd8005b20_3342206f_d9e51a18_49db73c1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xe0006200_392ad02e_c4ed8a9d_907eb521_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xe8006920_3f838080_b8a197de_a928acd7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xf0007080_46503170_65144cf7_dcc72d3b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -144, + mantissa: 0xf8007820_4d94e308_da5a1108_890d9f6a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x80004000_2aaacaaa_c4445999_abe2ce2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x84004410_2ecb2431_1fdbbb4f_3bffc832_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x88004840_332d7e1d_97ff8f39_ec91b4ee_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x8c004c90_37d3d876_74bcfcf0_b3f0a95d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x90005100_3cc03342_2e21f80c_a6813aff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x94005590_41f48e87_6c3d4629_170ce87f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x98005a40_4772ea4d_071e84e3_b80a8881_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0x9c005f10_4d3d469a_06d62fdc_bdd6bec3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xa0006400_5355a375_a375a6b7_01dc77c0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xa4006910_59be00e7_450f3318_26ad6b05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xa8006e40_60785ef6_83b60ea8_bd0aa459_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xac007390_6786bdab_277e6914_69dd13f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xb0007900_6eeb1d0d_287d6e0a_0d1e25eb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xb4007e90_76a77d24_aec94b3b_e9b060f5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xb8008440_7ebdddfa_1279365f_ce280cce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xbc008a10_87303f95_dba5732f_3e83e04a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xc0009000_9000a200_c2675967_9ed5b754_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xc4009610_99310543_aed95aca_5edb5109_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xc8009c40_a2c36967_b917091d_2687160f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xcc00a290_acb9ce76_293d1c2a_0378e75d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xd000a900_b7163478_776977bf_9766f5a7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xd400af90_c1da9b78_4bbb31b1_4776a18b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xd800b640_cd09037f_7e5297d7_6c8564ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xdc00bd10_d8a36c98_1751360f_8461c447_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xe000c400_e4abd6cc_4ed9dc3c_63f44c41_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xe400cb10_f1244226_8d10a446_6a5894d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xe800d240_fe0eaeb1_6a1af81b_b4e6510e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xec00d991_0b6d1c77_ae1f97b0_542a677a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xf000e101_19418b84_51469efe_81d014cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xf400e891_278dfbe2_7bb98c06_d77a18b4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xf800f041_36546d9d_85a344d0_868bed17_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xfc00f811_4596e0c0_f7301d69_90e307cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x80008000_aaabaaac_4446eef3_8140138f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x82008408_b2cbe5b8_10f5e432_96105497_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x84008820_bb2d2189_edbd4f83_ef63f730_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x86008c48_c3d05e27_feb654fd_541c638e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x88009080_ccb69b98_7ffadeb8_882f7674_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x8a0094c8_d5e0d9e1_c5a59fd3_6bd44397_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x8c009920_df50190a_3bd21770_1b27dddb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x8e009d88_e9055918_669c93b5_0e4a2595_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9000a200_f3019a12_e22234cd_39f29cd4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9200a688_fd45dc00_6280efe8_307d41d9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9400ab21_07d31ee7_b3d7923a_436f6fc4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9600afc9_12aa62cf_ba45c3fc_a574c5a0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9800b481_1dcca7bf_71ec0b6d_8cd413d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9a00b949_293aedbd_eeebcfd0_565c5006_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9c00be21_34f634d2_5d675c6d_a8c98fc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0x9e00c309_40ff7d04_0181e393_98a2099a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -142, + mantissa: 0xa000c801_4d57c65a_375f8195_cc8b1d29_u128, + }, + ]; + +pub(crate) static LOG_STEP_4: [DyadicFloat128; 130] = + // -log(r) for the fourth step, generated by SageMath with: + // + // for i in range(-65, 65): + // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) ); + // s, m, e = RealField(128)(r).log().sign_mantissa_exponent(); + // print("{RationalSign::Pos," if (s == -1) else "{RationalSign::Neg,", e, ", + // format_hex(m), "},"); + /* .step_4 = */ + [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -149, + mantissa: 0x81fffef7_f002cb2b_4cd24d68_ff2f11ae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xfffffe00_00055555_45555588_8887ddde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xfbfffe0f_e0051653_f0fa101f_52b3971f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xf7fffe1f_8004d94a_9c9329d6_59ed3734_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xf3fffe2e_e0049e31_4821006d_9b58462e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xeffffe3e_000464ff_f3a3f025_142f8c21_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xebfffe4c_e0042dae_9f1c53bc_c1c4b11c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xe7fffe5b_8003f835_4a8a8474_a17fdd30_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xe3fffe69_e003c48b_f5eeda0c_b0df586d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xdffffe78_000392aa_a149aac4_ed772adf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xdbfffe85_e0036289_4c9b4b5d_54f0bc96_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xd7fffe93_8003341f_f7e40f15_e50a759f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xd3fffea0_e0030766_a32447ae_9b975e05_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xcffffeae_0002dc55_4e5c4567_767ebdd5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xcbfffeba_e002b2e3_f98c5700_73bbbd19_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xc7fffec7_80028b0a_a4b4c9b9_915d03dd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xc3fffed3_e00264c1_4fd5e952_cd845a28_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xbffffee0_00023fff_faf0000c_26664806_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xbbfffeeb_e0021cbe_a60356a5_9a49b57f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xb7fffef7_8001faf5_5110345f_27878a9b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xb3ffff02_e001da9b_fc16def8_cc8a4f61_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xafffff0e_0001bbaa_a7179ab2_87cdcbd8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xabffff18_e0019e19_5212aa4c_57dea809_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xa7ffff23_800181df_fd084f06_3b5a0bf8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0xa3ffff2d_e00166f6_a7f8c8a0_30ed3fab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x9fffff38_00014d55_52e4555a_37554b29_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x9bffff41_e00134f3_fdcb31f4_4d5e9676_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x97ffff4b_80011dca_a8ad99ae_71e48997_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x93ffff54_e00107d1_538bc648_a3d12c90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x8fffff5e_0000f2ff_fe65f002_e21cc765_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x8bffff66_e000df4e_a93c4d9d_2bcd821a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x87ffff6f_8000ccb5_540f1457_7ff704b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -150, + mantissa: 0x83ffff77_e000bb2b_fede77f1_ddba1731_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xffffff00_00015555_53555558_88888333_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xf7ffff0f_c0013652_a8e7ba8d_659ed7dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xefffff1f_0001193f_fe747e02_5142fc61_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xe7ffff2d_c000fe0d_53fbfb37_4a1800c7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xdfffff3c_0000e4aa_a97e8aac_4ed77513_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xd7ffff49_c000cd07_fefc81e1_5e50a947_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xcfffff57_0000b715_54763356_7767ed66_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xc7ffff63_c000a2c2_a9ebee8b_9915d174_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xbfffff70_00008fff_ff5e0000_c2666573_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xb7ffff7b_c0007ebd_54ccb135_f2787966_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xafffff87_00006eea_aa3848ab_287cdd4e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0xa7ffff91_c0006077_ffa109e0_63b5a12d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0x9fffff9c_00005355_55073555_a3755504_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0x97ffffa5_c0004772_aa6b088a_e71e48d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0x8fffffaf_00003cbf_ffccbe00_2e21cca2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -151, + mantissa: 0x87ffffb7_c000332d_552c8d35_77ff706a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xffffff80_00005555_55155555_8888885e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xefffff8f_8000464f_ffce8fc0_25142fe3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xdfffff9e_0000392a_aa8526aa_c4ed7764_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xcfffffab_80002dc5_55397115_67767ee3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xbfffffb8_000023ff_ffebc000_0c26665f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0xafffffc3_80001bba_aa9c5e6a_b287cdd9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0x9fffffce_000014d5_554b9155_5a375553_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -152, + mantissa: 0x8fffffd7_80000f2f_fff997c0_02e21ccb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -153, + mantissa: 0xffffffc0_00001555_554d5555_58888887_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -153, + mantissa: 0xdfffffcf_00000e4a_aaa5fa2a_ac4ed777_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -153, + mantissa: 0xbfffffdc_000008ff_fffd7800_00c26666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -153, + mantissa: 0x9fffffe7_00000535_55541cd5_55a37555_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -154, + mantissa: 0xffffffe0_00000555_55545555_55888888_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -154, + mantissa: 0xbfffffee_0000023f_ffffaf00_000c2666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -155, + mantissa: 0xfffffff0_00000155_55553555_55588889_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -156, + mantissa: 0xfffffff8_00000055_55555155_55558889_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -155, + mantissa: 0x80000004_0000002a_aaaaacaa_aaaac444_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -154, + mantissa: 0x80000008_000000aa_aaaabaaa_aaac4444_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -154, + mantissa: 0xc0000012_00000240_00005100_000c2666_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -153, + mantissa: 0x80000010_000002aa_aaab2aaa_aac44444_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -153, + mantissa: 0xa0000019_00000535_55568dd5_55a37555_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -153, + mantissa: 0xc0000024_00000900_00028800_00c26667_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -153, + mantissa: 0xe0000031_00000e4a_aaaf5b2a_ac4ed778_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0x80000020_00000aaa_aaaeaaaa_ac444445_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0x90000028_80000f30_00066840_02e21cce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xa0000032_000014d5_555f1955_5a375558_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xb000003c_80001bba_aab8f6ea_b287cde2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xc0000048_00002400_00144000_0c26666e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xd0000054_80002dc5_55713995_67767efb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xe0000062_0000392a_aad02eaa_c4ed778b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -152, + mantissa: 0xf0000070_80004650_00317040_2514301d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0x80000040_00002aaa_aacaaaaa_c444445a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0x88000048_4000332d_557e1d75_77ff70a7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0x90000051_00003cc0_00334200_2e21ccf8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0x9800005a_40004772_aaea4cca_e71e494d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xa0000064_00005355_55a37555_a37555a7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xa800006e_40006078_005ef620_63b5a207_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xb0000079_00006eea_ab1d0cab_287cde6e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xb8000084_40007ebd_55ddf975_f2787ade_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xc0000090_00009000_00a20000_c2666759_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xc800009c_4000a2c2_ab6966cb_9915d3e1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xd00000a9_0000b715_56347756_7767f078_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xd80000b6_4000cd08_01037e21_5e50ad20_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xe00000c4_0000e4aa_abd6caac_4ed779dc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xe80000d2_4000fe0d_56aeaf77_4a1806b0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xf00000e1_00011940_018b8202_5143039f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -151, + mantissa: 0xf80000f0_40013652_ac6d9acd_659ee0ad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x80000080_0000aaaa_abaaaaac_444446ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x84000088_2000bb2c_01218811_ddba1d9b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x88000090_8000ccb5_569b9657_7ff70c5f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x8c000099_2000df4e_ac1907bd_2bcd8b3b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x900000a2_0000f300_019a1002_e21cd235_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x940000ab_200107d1_571ee468_a3d1394e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x980000b4_80011dca_aca7bbae_71e4988b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0x9c0000be_200134f4_0234ce14_4d5ea7f0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xa00000c8_00014d55_57c6555a_37555f82_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xa40000d2_200166f6_ad5c8cc0_30ed5744_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xa80000dc_800181e0_02f7b106_3b5a273b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xac0000e7_20019e19_5898006c_57dec76f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xb00000f2_0001bbaa_ae3dbab2_87cdefe3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xb40000fd_2001da9c_03e92118_cc8a789f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xb8000108_8001faf5_599a765f_2787b9aa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xbc000114_20021cbe_af51fec5_9a49eb0a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xc0000120_00024000_0510000c_266684c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xc400012c_200264c1_5ad4c172_cd849ee9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xc8000138_80028b0a_b0a08bb9_915d5179_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xcc000145_2002b2e4_0673a920_73bc1480_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xd0000152_0002dc55_5c4e6567_767f2009_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xd400015f_20030766_b2310dce_9b97cc1d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xd800016c_80033420_081bf115_e50af0c7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xdc00017a_20036289_5e0f5f7d_54f14614_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xe0000188_000392aa_b40baac4_ed77c410_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xe4000196_2003c48c_0a11262c_b0e002c7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xe80001a4_8003f835_60202674_a1809a47_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xec0001b3_20042dae_b63901dc_c1c582a0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xf00001c2_00046500_0c5c1025_143073df_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xf40001d1_20049e31_6289aa8d_9b594616_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xf80001e0_8004d94a_b8c22bd6_59ee5155_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -150, + mantissa: 0xfc0001f0_20051654_0f05f03f_52b4cdae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -149, + mantissa: 0x80000100_0002aaaa_b2aaaac4_4444999a_u128, + }, + ]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_range_reduction.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_range_reduction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_range_reduction.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_range_reduction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,163 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +// Logarithm range reduction - Step 3: +// r(k) = 2^-21 round(2^21 / (1 + k*2^-21)) for k = -80 .. 80. +// Output range: +// [-0x1.01928p-22 , 0x1p-22] +// We store S[i] = 2^21 (r(i - 80) - 1). +static S3: [i32; 161] = [ + 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, + 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, + 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, + 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, + 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, -0x1, + -0x2, -0x3, -0x4, -0x5, -0x6, -0x7, -0x8, -0x9, -0xa, -0xb, -0xc, -0xd, -0xe, -0xf, -0x10, + -0x11, -0x12, -0x13, -0x14, -0x15, -0x16, -0x17, -0x18, -0x19, -0x1a, -0x1b, -0x1c, -0x1d, + -0x1e, -0x1f, -0x20, -0x21, -0x22, -0x23, -0x24, -0x25, -0x26, -0x27, -0x28, -0x29, -0x2a, + -0x2b, -0x2c, -0x2d, -0x2e, -0x2f, -0x30, -0x31, -0x32, -0x33, -0x34, -0x35, -0x36, -0x37, + -0x38, -0x39, -0x3a, -0x3b, -0x3c, -0x3d, -0x3e, -0x3f, -0x40, -0x41, -0x42, -0x43, -0x44, + -0x45, -0x46, -0x47, -0x48, -0x49, -0x4a, -0x4b, -0x4c, -0x4d, -0x4e, -0x4f, -0x50, +]; + +// Logarithm range reduction - Step 4 +// r(k) = 2^-28 round(2^28 / (1 + k*2^-28)) for k = -65 .. 64. +// Output range: +// [-0x1.0002143p-29 , 0x1p-29] +// We store S[i] = 2^28 (r(i - 65) - 1). +static S4: [i32; 130] = [ + 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, + 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, + -0x1, -0x2, -0x3, -0x4, -0x5, -0x6, -0x7, -0x8, -0x9, -0xa, -0xb, -0xc, -0xd, -0xe, -0xf, + -0x10, -0x11, -0x12, -0x13, -0x14, -0x15, -0x16, -0x17, -0x18, -0x19, -0x1a, -0x1b, -0x1c, + -0x1d, -0x1e, -0x1f, -0x20, -0x21, -0x22, -0x23, -0x24, -0x25, -0x26, -0x27, -0x28, -0x29, + -0x2a, -0x2b, -0x2c, -0x2d, -0x2e, -0x2f, -0x30, -0x31, -0x32, -0x33, -0x34, -0x35, -0x36, + -0x37, -0x38, -0x39, -0x3a, -0x3b, -0x3c, -0x3d, -0x3e, -0x3f, -0x40, +]; + +// Logarithm range reduction - Step 2: +// r(k) = 2^-16 round(2^16 / (1 + k*2^-14)) for k = -2^6 .. 2^7. +// Output range: +// [-0x1.3ffcp-15, 0x1.3e3dp-15] +// We store S2[i] = 2^16 (r(i - 2^6) - 1). +static S2: [i32; 193] = [ + 0x101, 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, 0xe5, 0xe1, 0xdd, 0xd9, 0xd5, 0xd1, 0xcd, 0xc9, + 0xc5, 0xc1, 0xbd, 0xb9, 0xb4, 0xb0, 0xac, 0xa8, 0xa4, 0xa0, 0x9c, 0x98, 0x94, 0x90, 0x8c, 0x88, + 0x84, 0x80, 0x7c, 0x78, 0x74, 0x70, 0x6c, 0x68, 0x64, 0x60, 0x5c, 0x58, 0x54, 0x50, 0x4c, 0x48, + 0x44, 0x40, 0x3c, 0x38, 0x34, 0x30, 0x2c, 0x28, 0x24, 0x20, 0x1c, 0x18, 0x14, 0x10, 0xc, 0x8, + 0x4, 0x0, -0x4, -0x8, -0xc, -0x10, -0x14, -0x18, -0x1c, -0x20, -0x24, -0x28, -0x2c, -0x30, + -0x34, -0x38, -0x3c, -0x40, -0x44, -0x48, -0x4c, -0x50, -0x54, -0x58, -0x5c, -0x60, -0x64, + -0x68, -0x6c, -0x70, -0x74, -0x78, -0x7c, -0x80, -0x84, -0x88, -0x8c, -0x90, -0x94, -0x98, + -0x9c, -0xa0, -0xa4, -0xa8, -0xac, -0xb0, -0xb4, -0xb7, -0xbb, -0xbf, -0xc3, -0xc7, -0xcb, + -0xcf, -0xd3, -0xd7, -0xdb, -0xdf, -0xe3, -0xe7, -0xeb, -0xef, -0xf3, -0xf7, -0xfb, -0xff, + -0x103, -0x107, -0x10b, -0x10f, -0x113, -0x117, -0x11b, -0x11f, -0x123, -0x127, -0x12b, -0x12f, + -0x133, -0x137, -0x13a, -0x13e, -0x142, -0x146, -0x14a, -0x14e, -0x152, -0x156, -0x15a, -0x15e, + -0x162, -0x166, -0x16a, -0x16e, -0x172, -0x176, -0x17a, -0x17e, -0x182, -0x186, -0x18a, -0x18e, + -0x192, -0x195, -0x199, -0x19d, -0x1a1, -0x1a5, -0x1a9, -0x1ad, -0x1b1, -0x1b5, -0x1b9, -0x1bd, + -0x1c1, -0x1c5, -0x1c9, -0x1cd, -0x1d1, -0x1d5, -0x1d9, -0x1dd, -0x1e0, -0x1e4, -0x1e8, -0x1ec, + -0x1f0, -0x1f4, -0x1f8, -0x1fc, +]; + +// Perform logarithm range reduction steps 2-4. +// Inputs from the first step of range reduction: +// m_x : the reduced argument after the first step of range reduction +// satisfying -2^-8 <= m_x < 2^-7 and ulp(m_x) >= 2^-60. +// idx1: index of the -log(r1) table from the first step. +// Outputs of the extra range reduction steps: +// sum: adding -log(r1) - log(r2) - log(r3) - log(r4) to the resulted sum. +// return value: the reduced argument v satisfying: +// -0x1.0002143p-29 <= v < 0x1p-29, and ulp(v) >= 2^(-125). +pub(crate) fn log_range_reduction( + m_x: f64, + log_table: &[&[DyadicFloat128]; 4], + sum: DyadicFloat128, +) -> (DyadicFloat128, DyadicFloat128) { + let v = (m_x * f64::from_bits(0x43b0000000000000)) as i64; // ulp = 2^-60 + + // Range reduction - Step 2 + // Output range: vv2 in [-0x1.3ffcp-15, 0x1.3e3dp-15]. + // idx2 = trunc(2^14 * (v + 2^-8 + 2^-15)) + let idx2 = ((v.wrapping_add(0x10_2000_0000_0000)) >> 46) as usize; + let z0 = log_table[1][idx2]; + let mut sum = sum + z0; + + let s2: i64 = S2[idx2] as i64; // |s| <= 2^-7, ulp = 2^-16 + let sv2 = s2 * v; // |s*v| < 2^-14, ulp = 2^(-60-16) = 2^-76 + let spv2 = s2.wrapping_shl(44).wrapping_add(v); // |s + v| < 2^-14, ulp = 2^-60 + let vv2 = spv2.wrapping_shl(16).wrapping_add(sv2); // |vv2| < 2^-14, ulp = 2^-76 + + // Range reduction - Step 3 + // Output range: vv3 in [-0x1.01928p-22 , 0x1p-22] + // idx3 = trunc(2^21 * (v + 80*2^-21 + 2^-22)) + let idx3 = vv2.wrapping_add(0x2840_0000_0000_0000).wrapping_shr(55) as usize; + sum = sum + log_table[2][idx3]; + + let s3 = S3[idx3] as i64; // |s| < 2^-13, ulp = 2^-21 + let spv3: i64 = s3.wrapping_shl(55).wrapping_add(vv2); // |s + v| < 2^-21, ulp = 2^-76 + // |s*v| < 2^-27, ulp = 2^(-76-21) = 2^-97 + let sv3: i128 = s3 as i128 * vv2 as i128; + // |vv3| < 2^-21, ulp = 2^-97 + let vv3 = (spv3 as i128).wrapping_shl(21).wrapping_add(sv3); + + // Range reduction - Step 4 + // Output range: vv4 in [-0x1.0002143p-29 , 0x1p-29] + // idx4 = trunc(2^21 * (v + 65*2^-28 + 2^-29)) + let idx4 = ((((vv3 >> 68) as i32).wrapping_add(131)) >> 1) as usize; + + let z4 = log_table[3][idx4]; + sum = sum + z4; + + let s4: i128 = S4[idx4] as i128; // |s| < 2^-21, ulp = 2^-28 + // |s + v| < 2^-28, ulp = 2^-97 + let spv4 = s4.wrapping_shl(69).wrapping_add(vv3); + // |s*v| < 2^-42, ulp = 2^(-97-28) = 2^-125 + let sv4 = s4 * vv3; + // |vv4| < 2^-28, ulp = 2^-125 + let vv4 = spv4.wrapping_shl(28).wrapping_add(sv4); + + let mut z0 = if vv4 < 0 { + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -125, + mantissa: (-vv4) as u128, + } + } else { + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -125, + mantissa: vv4 as u128, + } + }; + z0.normalize(); + + (z0, sum) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_td.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_td.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::log_td_table::LOG_NEG_TD; +use crate::pow_tables::POW_INVERSE; +use crate::triple_double::TripleDouble; + +#[inline(always)] +fn log_td_poly(z: f64) -> TripleDouble { + /* + See ./notes/td_log.sollya + */ + const P: [(u64, u64, u64); 10] = [ + (0x38fc6038ddcc5680, 0x3c755555556795ff, 0x3fd5555555555555), + (0x372720effda9e638, 0xba86f68986749d55, 0xbfd0000000000000), + (0x38deb738e67c5280, 0xbc699b2852652c20, 0x3fc999999999999a), + (0x3900b719d69f9950, 0xbc65526cf5c3f935, 0xbfc5555555555555), + (0xb8ad0f51dccb7c02, 0xbc34fc5a6b8b9f2d, 0x3fc24924924924aa), + (0xb8faeee1e6f2b960, 0xbc52e65780d7da8f, 0xbfc0000000000023), + (0xb8f306e8001c6280, 0x3c5d0f68afb70c37, 0x3fbc71c71c2042d4), + (0x38d6940b092bf340, 0xbc3280fbebf81ea0, 0xbfb999999934f78b), + (0xb8daa1cce08da780, 0x3c48da171d2f9c73, 0x3fb74612a55c4784), + (0x38e9232517db1c80, 0x3c553b70480fc993, 0xbfb5559a592ab15c), + ]; + let x2 = DoubleDouble::from_exact_mult(z, z); + let mut t = TripleDouble::f64_mul_add( + z, + TripleDouble::from_bit_pair(P[9]), + TripleDouble::from_bit_pair(P[8]), + ); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[7])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[6])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[5])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[4])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[3])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[2])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[1])); + t = TripleDouble::f64_mul_add(z, t, TripleDouble::from_bit_pair(P[0])); + t = TripleDouble::quick_mult_dd(t, x2); + t = TripleDouble::quick_mult_f64(t, z); + TripleDouble::f64_mul_dd_add(-0.5, x2, t) +} + +#[inline] +pub(crate) fn log_td(x: f64) -> TripleDouble { + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; + t *= CY[c]; + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + + let log_r = TripleDouble::from_bit_pair(LOG_NEG_TD[(i - 181) as usize]); + + let z = f64::mul_add(r, t, -1.0); + + const LOG2_DD: TripleDouble = + TripleDouble::from_bit_pair((0x3907b57a079a1934, 0x3c7abc9e3b39803f, 0x3fe62e42fefa39ef)); + + let tt = TripleDouble::f64_mul_add(be as f64, LOG2_DD, log_r); + + let v = TripleDouble::add_f64(z, tt); + let p = log_td_poly(z); + TripleDouble::add_f64(v.hi, TripleDouble::new(v.lo + p.lo, v.mid + p.mid, p.hi)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log_td() { + assert_eq!(log_td(184467440737095500000.).to_f64(), 46.66400464883055); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_td_table.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td_table.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/log_td_table.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/log_td_table.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by Sage: +from POW_INV +```python +R = RealField(150) +def hex_to_float(h): + return struct.unpack('>d', struct.pack('>Q', h))[0] + +# Convert each hex value to RealField +real_array = [R(hex_to_float(h)) for h in values] + +# Show results +for r in real_array: + print_triple_double("", -RealField(180)(r).log()) +``` +**/ +pub(crate) static LOG_NEG_TD: [(u64, u64, u64); 182] = [ + (0x38f1406554719540, 0x3c6bc60efafc6f6e, 0xbfd5ff3070a793d4), + (0xb916f95d595cbf2e, 0x3c78ebcb7dee9a3d, 0xbfd5a42ab0f4cfe2), + (0x3908294131dd7142, 0x3c6819cf7e308ddb, 0xbfd548a2c3add263), + (0x391fcf3e64c8cd74, 0x3c742a87d977dc5e, 0xbfd4ec973260026a), + (0xb8e16c8675ad963d, 0x3c69ffc341f177dc, 0xbfd49006804009d1), + (0x3913f95697c9bfc2, 0x3c729931715ac903, 0xbfd432ef2a04e814), + (0x3919ea6f9f60989c, 0x3c70bcfb6082ce6d, 0xbfd404308686a7e4), + (0xb90beb7a3cee7e03, 0x3c6c68651945f97c, 0xbfd3a64c556945ea), + (0xb90ee510a580b3b3, 0x3c64dd4c580919f8, 0xbfd347dd9a987d55), + (0x390864244294826f, 0x3c78f4cdb95ebdf9, 0xbfd2e8e2bae11d31), + (0xb9162d6a3aacbe58, 0xbc77ad24c13f040e, 0xbfd2895a13de86a3), + (0x390a168b2a9642c4, 0x3c776f5eb09628af, 0xbfd22941fbcf7966), + (0xb918cf23e43622b1, 0x3c7c9fdf9a0c4b07, 0xbfd1f8ff9e48a2f3), + (0x3918eb33aa901486, 0xbc79d3d1b0e4d147, 0xbfd1980d2dd4236f), + (0x38e4a5b394627b29, 0xbc77b66298edd24a, 0xbfd136870293a8b0), + (0x38beb31a74640ec7, 0xbc589fa0ab4cb31d, 0xbfd1058bf9ae4ad5), + (0xb8ec51bc06b5f7c1, 0xbc77dcfde8061c03, 0xbfd0a324e27390e3), + (0x3900dddc4cf9a1f9, 0x3c628ec217a5022d, 0xbfd0402594b4d041), + (0x39035f6dfd3ddd52, 0x3c6caaae64f21acb, 0xbfcfb9186d5e3e2b), + (0xb8798a014b61d510, 0xbc2c5f6dfd018c37, 0xbfcf550a564b7b37), + (0xb8edee364d35208a, 0x3c46e03a39bfc89b, 0xbfce8c0252aa5a60), + (0xb8c55db94ebc4018, 0x3c461578001e0162, 0xbfce27076e2af2e6), + (0xb8ec3c6ce7a257f4, 0xbc66e443597e4d40, 0xbfcd5c216b4fbb91), + (0xb90a24ae3b2f53a1, 0x3c64f689f8434012, 0xbfcc8ff7c79a9a22), + (0xb89f00f527d33467, 0x3c673dee38a3fb6b, 0xbfcc2968558c18c1), + (0xb903dcf06e27bef1, 0xbc6ba27fdc19e1a0, 0xbfcb5b519e8fb5a4), + (0x38da262591d1968b, 0x3c5398cff3641985, 0xbfcaf3c94e80bff3), + (0xb8d3f1f8db36c599, 0xbc493711b07a998c, 0xbfca23bc1fe2b563), + (0xb8f28792ae1aabc8, 0xbc6575e31f003e0c, 0xbfc9bb362e7dfb83), + (0xb8dc0d0e377c6294, 0x3c6569d851a56770, 0xbfc8e928de886d41), + (0x38f0a5aa8fb49481, 0x3c6bf7fdbfa08d9a, 0xbfc87fa06520c911), + (0xb8a91ff852536204, 0xbc4be36b2d6a0608, 0xbfc7ab890210d909), + (0x38f0be957f10f5fb, 0x3c5b264062a84cdb, 0xbfc740f8f54037a5), + (0x38dc825cda7da31d, 0x3c6caae268ecd179, 0xbfc6d60fe719d21d), + (0x38e1406554719540, 0x3c5bc60efafc6f6e, 0xbfc5ff3070a793d4), + (0xb8f60e1f10db27cb, 0x3c565d22aa8ad7cf, 0xbfc59338d9982086), + (0x38b04bfef68b5ce2, 0xbc668981bcc36756, 0xbfc4ba36f39a55e5), + (0x390f3be9a8337458, 0xbc69f4f6543e1f88, 0xbfc44d2b6ccb7d1e), + (0x38fb40efe811e153, 0x3c5ab3a8e7d81017, 0xbfc3dfc2b0ecc62a), + (0x38a5e72f6cc4e614, 0x3c06b9c7d96091fa, 0xbfc303d718e47fd3), + (0x390977b021b7c784, 0xbc6301771c407dbf, 0xbfc29552f81ff523), + (0xb90eea44ec5389a5, 0xbc6f547bf1809e88, 0xbfc2266f190a5acb), + (0xb8fbd933781e73cd, 0xbc6a28813e3a7f07, 0xbfc14785846742ac), + (0x39071dbd9a581398, 0xbc69a5dc5e9030ac, 0xbfc0d77e7cd08e59), + (0x38ee98f4812aa997, 0xbc550c647eb86499, 0xbfc0671512ca596e), + (0x38f0ece597165991, 0xbc585f325c5bbacd, 0xbfbf0a30c01162a6), + (0xb8b55db94ebc4018, 0x3c361578001e0162, 0xbfbe27076e2af2e6), + (0xb8e20959368928d5, 0xbc5790dd951d90fa, 0xbfbd4313d66cb35d), + (0xb8dda7659abe370e, 0xbc35d617ef8161b1, 0xbfbc5e548f5bc743), + (0xb8e8f353ecfc45da, 0xbc5942f48aa70ea9, 0xbfba926d3a4ad563), + (0x38cbb52cb975cbeb, 0x3c42099e1c184e8e, 0xbfb9ab42462033ad), + (0x38ce547ecfe0df94, 0x3c24a697ab3424a9, 0xbfb8c345d6319b21), + (0xb8fa115d17a663c2, 0x3c5eeedfcdd94131, 0xbfb7da766d7b12cd), + (0xb8fc66d48ed8883f, 0x3c5388458ec21b6a, 0xbfb60658a93750c4), + (0xb8f584bc9c7e09bc, 0xbc5a49e39a1a8be4, 0xbfb51b073f06183f), + (0xb8d7465d8f6866cf, 0xbc4ddd4f935996c9, 0xbfb42edcbea646f0), + (0x38e15fbcbe26b491, 0x3c5b599f227becbb, 0xbfb341d7961bd1d1), + (0x38bd2c3f5a497e44, 0x3c1c125963fc4cfd, 0xbfb253f62f0a1417), + (0x38bb925bd6fa5998, 0x3c379da3e8c22cda, 0xbfb16536eea37ae1), + (0x38e0ece597165991, 0xbc485f325c5bbacd, 0xbfaf0a30c01162a6), + (0xb8acecc7db99d86a, 0xbc21e3c53257fd47, 0xbfad276b8adb0b52), + (0x38b6b5431d9cbf04, 0x3c3eb9759c130499, 0xbfab42dd711971bf), + (0x38e9e0ef8448a202, 0xbc4f5a0e80520bf2, 0xbfa95c830ec8e3eb), + (0xb8b63c9bf701b2a9, 0xbc418d3ca87b9296, 0xbfa77458f632dcfc), + (0x38d33fb67ae4f6ce, 0x3c4ce55c2b4e2b72, 0xbfa58a5bafc8e4d5), + (0xb8dc8d57ae1e11bd, 0x3c45bfa937f551bb, 0xbfa39e87b9febd60), + (0x38df6acb8073198b, 0x3c3e9ae889bac481, 0xbfa1b0d98923d980), + (0x38d814544147acc9, 0xbc333e3f04f1ef23, 0xbf9f829b0e783300), + (0xb899ffdb5331f453, 0x3bf0ae69229dc868, 0xbf9b9fc027af9198), + (0xb89dcd4f102a521d, 0x3c35b602ace3a510, 0xbf97b91b07d5b11b), + (0xb8a98d0797189a4d, 0x3c10cb5a902b3a1c, 0xbf93cea44346a575), + (0x38b52414fc416fc2, 0x3c183092c59642a1, 0xbf8fc0a8b0fc03e4), + (0xb8aa850a4a1800ea, 0x3c116d7687d3df21, 0xbf87dc475f810a77), + (0xb86a567b6587df34, 0x3bce44b7e3711ebf, 0xbf7fe02a6b106789), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0x0000000000000000, 0x0000000000000000, 0x8000000000000000), + (0x387b59b52a5681bd, 0x3bec14b9f9377a1d, 0x3f78121214586b54), + (0x38c6b69dd1ac0a31, 0xbc2c5517f64bc223, 0x3f841929f96832f0), + (0xb8bf713b529d3d76, 0x3c2806208c04c220, 0x3f8c317384c75f06), + (0xb8b3e8da8eba2824, 0xbc2cd7b66e01c26d, 0x3f9228fb1fea2e28), + (0xb86484372b0fc178, 0xbbf8ed4d357c9c97, 0x3f963d6178690bd6), + (0xb8aee63a49c74224, 0x3c1ec1a5f86d41f9, 0x3f9a55f548c5c43f), + (0x38ce166b9e0c701b, 0x3c375b44595cab18, 0x3f9e72bf2813ce51), + (0x38d3bc1c184cef0a, 0x3c4c05cf1d753622, 0x3fa0415d89e74444), + (0x38c1de8382dc46eb, 0xbc4947f792615916, 0x3fa252f32f8d183f), + (0x38eb92d06f3fe3af, 0xbc4cdd6f7f4a137e, 0x3fa466aed42de3ea), + (0x38e85f24bc417540, 0x3c40413e6505e603, 0x3fa67c94f2d4bb58), + (0xb8cd5f973f27591e, 0x3c3a8be97660a23d, 0x3fa894aa149fb343), + (0xb8cd0957659a8681, 0x3c2a353bb42e0add, 0x3faaaef2d0fb10fc), + (0x38cb1c2ce23545f5, 0x3c3e5cf3a0f56f72, 0x3fabbcebfc68f420), + (0xb8dc4ea8dab3d31c, 0x3c44e6c986f44c55, 0x3fadda8adc67ee4e), + (0x38e915fc13249a8b, 0xbc4cd9f1f95c2eed, 0x3faffa6911ab9301), + (0x38db4cbd380a58f0, 0xbc5a4a128d192686, 0x3fb10e45b3cae831), + (0xb8f531cc3e70565e, 0xbc5cc0fbce104eaa, 0x3fb2207b5c78549e), + (0xb8dd345728d4891b, 0xbc5d15d38d2fa3f7, 0x3fb2aa04a44717a5), + (0x38eb282b433139ab, 0x3c47a976d3b5b45f, 0x3fb3bdf5a7d1ee64), + (0xb8e3165ac490d812, 0x3c5769f42c7842cc, 0x3fb4d3115d207eac), + (0xb8fdf1f1f9a97a34, 0xbc545f9d61c68c1b, 0x3fb55e10050e0384), + (0x38edb15b559f2b8c, 0xbc59acd8b33f8fdc, 0x3fb674f089365a7a), + (0xb8eb73942ba54569, 0x3c5abca5b4fdb880, 0x3fb78d02263d82d3), + (0xb8dc199e47fc4f1b, 0x3c3b9f2dffbeed43, 0x3fb8197e2f40e3f0), + (0x38f089735832ff2f, 0xbc5478a85704ccb7, 0x3fb9335e5d594989), + (0xb8f9be73856e63dd, 0xbc55b5ca203e4259, 0x3fba4e7640b1bc38), + (0xb8fd1dc4ae609d89, 0x3c537d8f39bee659, 0x3fbadc77ee5aea8c), + (0x38ec5646e7873ff4, 0xbc4cdc9f6f5f38c7, 0x3fbbf968769fca11), + (0xb8ca4a0195f6076f, 0x3c49daf7df76ad2a, 0x3fbd179788219364), + (0xb8f0554118a2fe2d, 0x3c5401fa71733019, 0x3fbda727638446a2), + (0xb8b1980fad2b8c8f, 0xbc4a2bf991780d3f, 0x3fbec739830a1120), + (0xb8eba1da9ea4e2ac, 0xbc59361574fb24e2, 0x3fbf57bc7d9005db), + (0x38d491637376842d, 0x3c639e2d3f8b7d10, 0x3fc03cdc0a51ec0d), + (0xb8fa7da07274e01d, 0xbc6dd7009902bf32, 0x3fc08598b59e3a07), + (0x38f03c776a3fb0f1, 0xbc50e63a5f01c691, 0x3fc1178e8227e47c), + (0x390a1136855b465f, 0xbc62d56ff61c2bfb, 0x3fc160c8024b27b1), + (0xb8dc641c1655b965, 0x3c462c9ef939ac5d, 0x3fc1f3b925f25d41), + (0xb9030309bfb61ce3, 0xbc66e38161051d69, 0x3fc23d712a49c202), + (0xb8fdedef6e5214fa, 0xbc5499a3f25af95f, 0x3fc2d1610c86813a), + (0xb8ab9d980d8c440b, 0xbc5c4716bdfc0cc9, 0x3fc31b994d3a4f85), + (0xb8c44d5c95f5d241, 0x3c370d6cdf05266c, 0x3fc3b08b6757f2a9), + (0xb9055cfc4715d0cf, 0xbc6d87e6a354d056, 0x3fc3fb45a59928cc), + (0x38f046ddd0c4995f, 0xbc50d5604930f135, 0x3fc4913d8333b561), + (0xb90e5aae7083b870, 0xbc6927d47803c5f4, 0x3fc4dc7b897bc1c8), + (0xb8fcb60e1eb82c6c, 0x3c64f4d710fec38e, 0x3fc5737cc9018cdd), + (0xb8c25a7abe3c6675, 0xbc21f5b44c0df7e7, 0x3fc5bf406b543db2), + (0xb8d0587f8805bff2, 0xbc3d34f0f4621bed, 0x3fc6574ebe8c133a), + (0x38ef4165ace952df, 0x3c696332bd4b341f, 0x3fc6a399dabbd383), + (0xb905e04327207755, 0xbc68de59c21e166c, 0x3fc6f0128b756abc), + (0x38fa90e246a61446, 0x3c5ef8f6ebcfb201, 0x3fc7898d85444c73), + (0x38ee9d5bdc04215b, 0xbc4ac5f0c075b847, 0x3fc7d6903caf5ad0), + (0xb8ea55c7d1bf59b5, 0x3c6d685f35eea2a0, 0x3fc871213750e994), + (0x38e5f9812ac08ffd, 0x3c555aa8b6997a40, 0x3fc8beafeb38fe8c), + (0x39025a9fa0ff7316, 0x3c6054473941ad99, 0x3fc90c6db9fcbcd9), + (0xb90b9f17794734cf, 0x3c6f47dfd871f87f, 0x3fc9a8778debaa38), + (0x38dc16be326ac41a, 0x3c435a19605e67ef, 0x3fc9f6c407089664), + (0x38f185cfa0a62d77, 0x3c5df207dc5c34c6, 0x3fca454082e6ab05), + (0xb8f307466a8570bb, 0x3c6ab5ca9eaa088a, 0x3fcae2ca6f672bd4), + (0xb8f0459563c86e85, 0xbc66353ab386a94d, 0x3fcb31d8575bce3d), + (0x38dac5281fdd139f, 0x3c3a0ee735d9f0ec, 0x3fcb811730b823d2), + (0x38d0aaa7d9462021, 0x3c3dd355f6a516d7, 0x3fcbd087383bd8ad), + (0x3900f039c9a8a2e5, 0xbc68e58b2c57a4a5, 0x3fcc6ffbc6f00f71), + (0xb8e7196d3db630d3, 0x3c653d154280394f, 0x3fccc000c9db3c52), + (0x38ef01fe115ec7f7, 0x3c660629242471a2, 0x3fcd1037f2655e7b), + (0xb8ff3a153d8d4fe0, 0x3c5aa11d49f96cb9, 0x3fcdb13db0d48940), + (0xb8de287e4407f374, 0x3c5fea48dd7b81d1, 0x3fce020cc6235ab5), + (0xb8eb5b6e7d96592d, 0x3c42276041f43042, 0x3fce530effe71012), + (0xb8b755b33ca06006, 0xbc6d33919ab94074, 0x3fcea4449f04aaf5), + (0xb8f96415b209f7c5, 0xbc527c77ded76aad, 0x3fcf474b134df229), + (0xb90c93e26ec48e0e, 0x3c6f665066f980a2, 0x3fcf991c6cb3b379), + (0xb878c9ae634d3c77, 0x3c28de00938b4c40, 0x3fcfeb2233ea07cd), + (0x38ed5f4501b8b4a6, 0xbc418290bd2932e2, 0x3fd01eae5626c691), + (0x3902e2a91d8de3c6, 0xbc70779634061cbc, 0x3fd047e60cde83b8), + (0xb90f2a6f815b079c, 0x3c643c2e68684d53, 0x3fd09aa572e6c6d4), + (0x38f078ecd47fd065, 0x3c5162c79d5d11ee, 0x3fd0c42d676162e3), + (0x390349ab8071c6f5, 0xbc692b49ef282b09, 0x3fd0edd060b78081), + (0x39003c776a3fb0f1, 0xbc60e63a5f01c691, 0x3fd1178e8227e47c), + (0x38b86b8fcae82457, 0x3c1e0936abd4fa6e, 0x3fd14167ef367783), + (0x39062e66c6742717, 0x3c766fbd28b40935, 0x3fd16b5ccbacfb73), + (0xb904298ef6ad5800, 0xbc612aeb84249223, 0x3fd1bf99635a6b95), + (0x391fb7583fdc5cd1, 0x3c7512c3749a1e4e, 0x3fd1e9e1678899f4), + (0xb8fbbc46cf6d5b05, 0x3c6f7ae91aeba60a, 0x3fd214456d0eb8d4), + (0xb8d69da0a6f43fa8, 0x3c3bb75d1addf870, 0x3fd23ec5991eba49), + (0xb9163d5cf0b6f233, 0x3c7e0efadd9db02b, 0x3fd269621134db92), + (0xb8ba9b5dfcb5442c, 0xbc6856e61c515740, 0x3fd2941afb186b7c), + (0x3908cc4b2b27c162, 0xbc782dad7fd86088, 0x3fd2bef07cdc9354), + (0xb91f0f8d6f3c6a8e, 0xbc73d69909e5c3dc, 0x3fd314f1e1d35ce4), + (0xb8f954216e4fd4b3, 0xbc5cd55b8a4746c0, 0x3fd3401e12aecba1), + (0x38f5f12812782422, 0xbc5324f0e883858e, 0x3fd36b6776be1117), + (0x38e44a223cab7ad9, 0xbc5ce2b31b31e8b0, 0x3fd396ce359bbf54), + (0xb905ea8429f9f46d, 0xbc72ad27e50a8ec6, 0x3fd3c25277333184), + (0x390cccb5749e39eb, 0x3c783d680d3c1084, 0x3fd3edf463c1683e), + (0xb90c920829097668, 0x3c60dbb243827392, 0x3fd419b423d5e8c7), + (0x3913cee6bc2e326b, 0xbc72b125247b0fa5, 0x3fd44591e0539f49), + (0xb8d019b2f322342b, 0x3c38fb4c14c56eef, 0x3fd4718dc271c41b), + (0x38fc6086c0bb1e94, 0xbc69964a168ccaca, 0x3fd49da7f3bcc41f), + (0xb8f1ef0823bae5d2, 0xbc5123615b147a5d, 0x3fd4c9e09e172c3c), + (0xb8e658171677adeb, 0xbc758cb3124b9245, 0x3fd4f637ebba9810), + (0xb90777dce76e5542, 0xbc68f7e9b38a6979, 0x3fd522ae0738a3d8), + (0xb9125eeb277e3f77, 0xbc7aacfdbbdab914, 0x3fd54f431b7be1a9), + (0xb8e942cd558167e2, 0xbc60908d15f88b63, 0x3fd57bf753c8d1fb), + (0xb8f6a2ed327a4daa, 0xbc5e6c2bdfb3e037, 0x3fd5a8cadbbedfa1), + (0xb91d89fab3e76435, 0xbc76541148cbb8a2, 0x3fd5d5bddf595f30), + (0xb8e72adc1a985ccf, 0xbc56e8920c09b73f, 0x3fd602d08af091ec), + (0x3901e7352eee5ee9, 0x3c6dc18ce51fff99, 0x3fd630030b3aac49), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,528 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::min_normal_f32; +use crate::common::*; +use crate::polyeval::f_polyeval3; +use std::hint::black_box; + +#[repr(C, align(8))] +pub(crate) struct LogReductionF32Aligned(pub(crate) [u32; 128]); + +pub(crate) static LOG_REDUCTION_F32: LogReductionF32Aligned = LogReductionF32Aligned([ + 0x3f800000, 0x3f7e0000, 0x3f7c0000, 0x3f7a0000, 0x3f780000, 0x3f760000, 0x3f740000, 0x3f720000, + 0x3f700000, 0x3f6f0000, 0x3f6d0000, 0x3f6b0000, 0x3f6a0000, 0x3f680000, 0x3f660000, 0x3f650000, + 0x3f630000, 0x3f620000, 0x3f600000, 0x3f5f0000, 0x3f5d0000, 0x3f5c0000, 0x3f5a0000, 0x3f590000, + 0x3f570000, 0x3f560000, 0x3f540000, 0x3f530000, 0x3f520000, 0x3f500000, 0x3f4f0000, 0x3f4e0000, + 0x3f4c0000, 0x3f4b0000, 0x3f4a0000, 0x3f490000, 0x3f480000, 0x3f460000, 0x3f450000, 0x3f440000, + 0x3f430000, 0x3f420000, 0x3f400000, 0x3f3f0000, 0x3f3e0000, 0x3f3d0000, 0x3f3c0000, 0x3f3b0000, + 0x3f3a0000, 0x3f390000, 0x3f380000, 0x3f370000, 0x3f360000, 0x3f350000, 0x3f340000, 0x3f330000, + 0x3f320000, 0x3f310000, 0x3f300000, 0x3f2f0000, 0x3f2e0000, 0x3f2d0000, 0x3f2c0000, 0x3f2b0000, + 0x3f2a0000, 0x3f2a0000, 0x3f290000, 0x3f280000, 0x3f270000, 0x3f260000, 0x3f250000, 0x3f250000, + 0x3f240000, 0x3f230000, 0x3f220000, 0x3f210000, 0x3f200000, 0x3f200000, 0x3f1f0000, 0x3f1e0000, + 0x3f1d0000, 0x3f1d0000, 0x3f1c0000, 0x3f1b0000, 0x3f1a0000, 0x3f1a0000, 0x3f190000, 0x3f180000, + 0x3f180000, 0x3f170000, 0x3f160000, 0x3f160000, 0x3f150000, 0x3f140000, 0x3f140000, 0x3f130000, + 0x3f120000, 0x3f120000, 0x3f110000, 0x3f100000, 0x3f100000, 0x3f0f0000, 0x3f0e0000, 0x3f0e0000, + 0x3f0d0000, 0x3f0d0000, 0x3f0c0000, 0x3f0b0000, 0x3f0b0000, 0x3f0a0000, 0x3f0a0000, 0x3f090000, + 0x3f080000, 0x3f080000, 0x3f070000, 0x3f070000, 0x3f060000, 0x3f060000, 0x3f050000, 0x3f050000, + 0x3f040000, 0x3f040000, 0x3f030000, 0x3f030000, 0x3f020000, 0x3f020000, 0x3f010000, 0x3f000000, +]); + +static LOG_R: [u64; 128] = [ + 0x0000000000000000, + 0x3f8010157588de71, + 0x3f90205658935847, + 0x3f98492528c8cabf, + 0x3fa0415d89e74444, + 0x3fa466aed42de3ea, + 0x3fa894aa149fb343, + 0x3faccb73cdddb2cc, + 0x3fb08598b59e3a07, + 0x3fb1973bd1465567, + 0x3fb3bdf5a7d1ee64, + 0x3fb5e95a4d9791cb, + 0x3fb700d30aeac0e1, + 0x3fb9335e5d594989, + 0x3fbb6ac88dad5b1c, + 0x3fbc885801bc4b23, + 0x3fbec739830a1120, + 0x3fbfe89139dbd566, + 0x3fc1178e8227e47c, + 0x3fc1aa2b7e23f72a, + 0x3fc2d1610c86813a, + 0x3fc365fcb0159016, + 0x3fc4913d8333b561, + 0x3fc527e5e4a1b58d, + 0x3fc6574ebe8c133a, + 0x3fc6f0128b756abc, + 0x3fc823c16551a3c2, + 0x3fc8beafeb38fe8c, + 0x3fc95a5adcf7017f, + 0x3fca93ed3c8ad9e3, + 0x3fcb31d8575bce3d, + 0x3fcbd087383bd8ad, + 0x3fcd1037f2655e7b, + 0x3fcdb13db0d48940, + 0x3fce530effe71012, + 0x3fcef5ade4dcffe6, + 0x3fcf991c6cb3b379, + 0x3fd07138604d5862, + 0x3fd0c42d676162e3, + 0x3fd1178e8227e47c, + 0x3fd16b5ccbacfb73, + 0x3fd1bf99635a6b95, + 0x3fd269621134db92, + 0x3fd2bef07cdc9354, + 0x3fd314f1e1d35ce4, + 0x3fd36b6776be1117, + 0x3fd3c25277333184, + 0x3fd419b423d5e8c7, + 0x3fd4718dc271c41b, + 0x3fd4c9e09e172c3c, + 0x3fd522ae0738a3d8, + 0x3fd57bf753c8d1fb, + 0x3fd5d5bddf595f30, + 0x3fd630030b3aac49, + 0x3fd68ac83e9c6a14, + 0x3fd6e60ee6af1972, + 0x3fd741d876c67bb1, + 0x3fd79e26687cfb3e, + 0x3fd7fafa3bd8151c, + 0x3fd85855776dcbfb, + 0x3fd8b639a88b2df5, + 0x3fd914a8635bf68a, + 0x3fd973a3431356ae, + 0x3fd9d32bea15ed3b, + 0x3fda33440224fa79, + 0x3fda33440224fa79, + 0x3fda93ed3c8ad9e3, + 0x3fdaf5295248cdd0, + 0x3fdb56fa04462909, + 0x3fdbb9611b80e2fb, + 0x3fdc1c60693fa39e, + 0x3fdc1c60693fa39e, + 0x3fdc7ff9c74554c9, + 0x3fdce42f18064743, + 0x3fdd490246defa6b, + 0x3fddae75484c9616, + 0x3fde148a1a2726ce, + 0x3fde148a1a2726ce, + 0x3fde7b42c3ddad73, + 0x3fdee2a156b413e5, + 0x3fdf4aa7ee03192d, + 0x3fdf4aa7ee03192d, + 0x3fdfb358af7a4884, + 0x3fe00e5ae5b207ab, + 0x3fe04360be7603ad, + 0x3fe04360be7603ad, + 0x3fe078bf0533c568, + 0x3fe0ae76e2d054fa, + 0x3fe0ae76e2d054fa, + 0x3fe0e4898611cce1, + 0x3fe11af823c75aa8, + 0x3fe11af823c75aa8, + 0x3fe151c3f6f29612, + 0x3fe188ee40f23ca6, + 0x3fe188ee40f23ca6, + 0x3fe1c07849ae6007, + 0x3fe1f8635fc61659, + 0x3fe1f8635fc61659, + 0x3fe230b0d8bebc98, + 0x3fe269621134db92, + 0x3fe269621134db92, + 0x3fe2a2786d0ec107, + 0x3fe2dbf557b0df43, + 0x3fe2dbf557b0df43, + 0x3fe315da4434068b, + 0x3fe315da4434068b, + 0x3fe35028ad9d8c86, + 0x3fe38ae2171976e7, + 0x3fe38ae2171976e7, + 0x3fe3c6080c36bfb5, + 0x3fe3c6080c36bfb5, + 0x3fe4019c2125ca93, + 0x3fe43d9ff2f923c5, + 0x3fe43d9ff2f923c5, + 0x3fe47a1527e8a2d3, + 0x3fe47a1527e8a2d3, + 0x3fe4b6fd6f970c1f, + 0x3fe4b6fd6f970c1f, + 0x3fe4f45a835a4e19, + 0x3fe4f45a835a4e19, + 0x3fe5322e26867857, + 0x3fe5322e26867857, + 0x3fe5707a26bb8c66, + 0x3fe5707a26bb8c66, + 0x3fe5af405c3649e0, + 0x3fe5af405c3649e0, + 0x3fe5ee82aa241920, + 0x0000000000000000, +]; + +pub(crate) trait LogfBackend { + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32; + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64; + const HAS_FMA: bool; +} + +pub(crate) struct GenLogfBackend {} + +impl LogfBackend for GenLogfBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f_fmlaf(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::f_polyeval3; + f_polyeval3(x, a0, a1, a2) + } + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + const HAS_FMA: bool = true; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + const HAS_FMA: bool = false; +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub(crate) struct FmaLogfBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl LogfBackend for FmaLogfBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f32::mul_add(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::d_polyeval3; + d_polyeval3(x, a0, a1, a2) + } + + const HAS_FMA: bool = true; +} + +#[inline(always)] +fn logf_gen(x: f32, backend: B) -> f32 { + let mut x_u = x.to_bits(); + + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + + let mut m = -(E_BIAS as i32); + if x_u < 0x4c5d65a5u32 { + if x_u == 0x3f7f4d6fu32 { + return black_box(f64::from_bits(0xbf6659ec80000000) as f32) + min_normal_f32(true); + } else if x_u == 0x41178febu32 { + return black_box(f64::from_bits(0x4001fcbce0000000) as f32) + min_normal_f32(true); + } else if x_u == 0x3f800000u32 { + return 0.; + } else if x_u == 0x1e88452du32 { + return black_box(f64::from_bits(0xc046d7b180000000) as f32) + min_normal_f32(true); + } + if x_u < f32::MIN_POSITIVE.to_bits() { + if x == 0.0 { + return f32::NEG_INFINITY; + } + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4160000000000000) as f32).to_bits(); + m -= 23; + } + } else { + if x_u == 0x4c5d65a5u32 { + return black_box(f32::from_bits(0x418f034b)) + min_normal_f32(true); + } else if x_u == 0x65d890d3u32 { + return black_box(f32::from_bits(0x4254d1f9)) + min_normal_f32(true); + } else if x_u == 0x6f31a8ecu32 { + return black_box(f32::from_bits(0x42845a89)) + min_normal_f32(true); + } else if x_u == 0x7a17f30au32 { + return black_box(f32::from_bits(0x42a28a1b)) + min_normal_f32(true); + } else if x_u == 0x500ffb03u32 { + return black_box(f32::from_bits(0x41b7ee9a)) + min_normal_f32(true); + } else if x_u == 0x5cd69e88u32 { + return black_box(f32::from_bits(0x4222e0a3)) + min_normal_f32(true); + } else if x_u == 0x5ee8984eu32 { + return black_box(f32::from_bits(0x422e4a21)) + min_normal_f32(true); + } + + if x_u > f32::MAX.to_bits() { + if x_u == 0x80000000u32 { + return f32::NEG_INFINITY; + } + if x.is_sign_negative() && !x.is_nan() { + return f32::NAN + x; + } + // x is +inf or nan + if x.is_nan() { + return f32::NAN; + } + + return x; + } + } + + let mant = x_u & 0x007F_FFFF; + // Extract 7 leading fractional bits of the mantissa + let index = mant.wrapping_shr(16); + // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are + // all 1's. + m = m.wrapping_add(x_u.wrapping_add(1 << 16).wrapping_shr(23) as i32); + x_u = set_exponent_f32(x_u, 0x7F); + + let u = f32::from_bits(x_u); + + let v = if B::HAS_FMA { + backend.fmaf(u, f32::from_bits(LOG_REDUCTION_F32.0[index as usize]), -1.0) as f64 // Exact. + } else { + use crate::logs::log2::LOG_RANGE_REDUCTION; + backend.fma( + u as f64, + f64::from_bits(LOG_RANGE_REDUCTION[index as usize]), + -1.0, + ) // Exact + }; + // Degree-5 polynomial approximation of log generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]); + const COEFFS: [u64; 4] = [ + 0xbfe000000000fe63, + 0x3fd555556e963c16, + 0xbfd000028dedf986, + 0x3fc966681bfda7f7, + ]; + let v2 = v * v; // Exact + let p2 = backend.fma(v, f64::from_bits(COEFFS[3]), f64::from_bits(COEFFS[2])); + let p1 = backend.fma(v, f64::from_bits(COEFFS[1]), f64::from_bits(COEFFS[0])); + let p0 = f64::from_bits(LOG_R[index as usize]) + v; + const LOG_2: f64 = f64::from_bits(0x3fe62e42fefa39ef); + let r = backend.fma(m as f64, LOG_2, backend.polyeval3(v2, p0, p1, p2)); + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn logf_fma_impl(x: f32) -> f32 { + logf_gen(x, FmaLogfBackend {}) +} + +/// Natural logarithm +/// +/// Max found ULP 0.4999988 +pub fn f_logf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + logf_gen(x, GenLogfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + logf_fma_impl + } else { + fn def_logf(x: f32) -> f32 { + logf_gen(x, GenLogfBackend {}) + } + def_logf + } + }); + unsafe { q(x) } + } +} + +#[inline] +pub(crate) fn fast_logf(x: f32) -> f64 { + let mut x_u = x.to_bits(); + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + let mut m = -(E_BIAS as i32); + if x_u < f32::MIN_POSITIVE.to_bits() { + // Normalize denormal inputs. + x_u = (x * f64::from_bits(0x4160000000000000) as f32).to_bits(); + m -= 23; + } + + let mant = x_u & 0x007F_FFFF; + // Extract 7 leading fractional bits of the mantissa + let index = mant.wrapping_shr(16); + // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are + // all 1's. + m = m.wrapping_add(x_u.wrapping_add(1 << 16).wrapping_shr(23) as i32); + x_u = set_exponent_f32(x_u, 0x7F); + + let v; + let u = f32::from_bits(x_u); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v = f_fmlaf(u, f32::from_bits(LOG_REDUCTION_F32.0[index as usize]), -1.0) as f64; // Exact. + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::logs::log2::LOG_RANGE_REDUCTION; + v = f_fmla( + u as f64, + f64::from_bits(LOG_RANGE_REDUCTION[index as usize]), + -1.0, + ); // Exact + } + // Degree-5 polynomial approximation of log generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]); + const COEFFS: [u64; 4] = [ + 0xbfe000000000fe63, + 0x3fd555556e963c16, + 0xbfd000028dedf986, + 0x3fc966681bfda7f7, + ]; + let v2 = v * v; // Exact + let p2 = f_fmla(v, f64::from_bits(COEFFS[3]), f64::from_bits(COEFFS[2])); + let p1 = f_fmla(v, f64::from_bits(COEFFS[1]), f64::from_bits(COEFFS[0])); + let p0 = f64::from_bits(LOG_R[index as usize]) + v; + const LOG_2: f64 = f64::from_bits(0x3fe62e42fefa39ef); + f_fmla(m as f64, LOG_2, f_polyeval3(v2, p0, p1, p2)) +} + +/// Log for given value for const context. +/// This is simplified version just to make a good approximation on const context. +#[inline] +pub const fn logf(d: f32) -> f32 { + let ux = d.to_bits(); + #[allow(clippy::collapsible_if)] + if ux < (1 << 23) || ux >= 0x7f800000u32 { + if ux == 0 || ux >= 0x7f800000u32 { + if ux == 0x7f800000u32 { + return d; + } + let ax = ux.wrapping_shl(1); + if ax == 0u32 { + // -0.0 + return f32::NEG_INFINITY; + } + if ax > 0xff000000u32 { + return d + d; + } // nan + return f32::NAN; + } + } + + let mut ix = d.to_bits(); + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + let n = (ix >> 23) as i32 - 0x7f; + ix = (ix & 0x007fffff) + 0x3f3504f3; + let a = f32::from_bits(ix) as f64; + + let x = (a - 1.) / (a + 1.); + let x2 = x * x; + let mut u = 0.2222220222147750310e+0; + u = fmla(u, x2, 0.2857142871244668543e+0); + u = fmla(u, x2, 0.3999999999950960318e+0); + u = fmla(u, x2, 0.6666666666666734090e+0); + u = fmla(u, x2, 2.); + fmla(x, u, std::f64::consts::LN_2 * (n as f64)) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_logf() { + assert!( + (logf(1f32) - 0f32).abs() < 1e-6, + "Invalid result {}", + logf(1f32) + ); + assert!( + (logf(5f32) - 1.60943791243410037460f32).abs() < 1e-6, + "Invalid result {}", + logf(5f32) + ); + assert_eq!(logf(0.), f32::NEG_INFINITY); + assert!(logf(-1.).is_nan()); + assert!(logf(f32::NAN).is_nan()); + assert!(logf(f32::NEG_INFINITY).is_nan()); + assert_eq!(logf(f32::INFINITY), f32::INFINITY); + } + + #[test] + fn test_flogf() { + assert!( + (f_logf(1f32) - 0f32).abs() < 1e-6, + "Invalid result {}", + f_logf(1f32) + ); + assert!( + (f_logf(5f32) - 1.60943791243410037460f32).abs() < 1e-6, + "Invalid result {}", + f_logf(5f32) + ); + assert_eq!(f_logf(0.), f32::NEG_INFINITY); + assert!(f_logf(-1.).is_nan()); + assert!(f_logf(f32::NAN).is_nan()); + assert!(f_logf(f32::NEG_INFINITY).is_nan()); + assert_eq!(f_logf(f32::INFINITY), f32::INFINITY); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logit.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::logs::{fast_log_d_to_dd, log1p_fast_dd}; + +/// Inverse logistic function +pub fn f_logit(x: f64) -> f64 { + let ux = x.to_bits(); + if ux >= 0x3ff0000000000000u64 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0, x >= 1 + if ux.wrapping_shl(1) == 0 { + return 0.; + } + if ux == 0x3ff0000000000000u64 { + // x == 1 + return f64::INFINITY; + } + return f64::NAN; + } + // logit(x) = log(x/(1-p)) = log(x) - log(1-p) + let v0 = fast_log_d_to_dd(x); + let v1 = log1p_fast_dd(-x); + let product = DoubleDouble::quick_dd_sub(v0, v1); + product.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_logit() { + assert_eq!(f_logit(0.70000000000007534), 0.8472978603875624); + assert_eq!(f_logit(0.234), -1.1858610543828898); + assert_eq!(f_logit(0.142112), -1.7978580757271523); + assert_eq!(f_logit(0.86543), 1.8611419834868623); + assert_eq!(f_logit(0.21312), -1.3062203716758034); + assert_eq!(f_logit(0.128765), -1.91192270767172); + assert_eq!(f_logit(1.), f64::INFINITY); + assert!(f_logit(-0.00123).is_nan()); + assert!(f_logit(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logitf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logitf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/logitf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/logitf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::logs::log1pf::{core_log1pf, core_logf}; + +/// Inverse logistic function +pub fn f_logitf(x: f32) -> f32 { + let ux = x.to_bits(); + if ux >= 0x3f80_0000u32 || ux == 0 { + // |x| == 0, |x| == inf, |x| == NaN, x < 0, x >= 1 + if ux.wrapping_shl(1) == 0 { + return 0.; + } + if ux == 0x3f80_0000u32 { + // x == 1 + return f32::INFINITY; + } + return f32::NAN; + } + // logit(x) = log(x/(1-p)) = log(x) - log(1-p) + let v0 = core_logf(x as f64); + let v1 = core_log1pf(-x); + (v0 - v1) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_logit() { + assert_eq!(f_logitf(0.234), -1.1858611); + assert_eq!(f_logitf(0.142112), -1.7978581); + assert_eq!(f_logitf(0.86543), 1.8611419); + assert_eq!(f_logitf(0.21312), -1.3062204); + assert_eq!(f_logitf(0.128765), -1.9119227); + assert_eq!(f_logitf(1.), f32::INFINITY); + assert!(f_logitf(-0.00123).is_nan()); + assert!(f_logitf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/logs/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/logs/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,104 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![deny(unreachable_pub)] +mod fast_log; +mod fast_log_dd; +mod log; +mod log10; +mod log10dd; +mod log10dd_coeffs; +mod log10f; +mod log10p1; +mod log10p1_tables; +mod log10p1f; +mod log10td; +mod log10td_coeffs; +mod log1p; +mod log1p_dd; +mod log1p_dyadic; +mod log1p_dyadic_tables; +mod log1pf; +mod log1pmx; +mod log1pmxf; +mod log2; +mod log2dd; +mod log2dd_coeffs; +mod log2f; +mod log2p1; +mod log2p1_dyadic_tables; +mod log2p1_tables; +mod log2p1f; +mod log2td; +mod log2td_coeffs; +mod log_dd; +mod log_dd_coeffs; +mod log_dyadic; +mod log_range_reduction; +mod log_td; +mod log_td_table; +mod logf; +mod logit; +mod logitf; + +pub(crate) use fast_log::simple_fast_log; +pub(crate) use fast_log_dd::{fast_log_d_to_dd, fast_log_dd}; +pub(crate) use log::log_dyadic; +pub use log::{f_log, log}; +pub(crate) use log_dd::{log_dd, log_dd_fast}; +pub use log1p::f_log1p; +pub(crate) use log1p::log1p_f64_dyadic; +pub(crate) use log1p_dd::{log1p_dd, log1p_fast_dd}; +pub use log1pf::f_log1pf; +pub use log1pmx::f_log1pmx; +pub use log1pmxf::f_log1pmxf; +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +)))] +pub(crate) use log2::LOG_CD; +pub use log2::f_log2; +pub(crate) use log2::{LOG_COEFFS, LOG_RANGE_REDUCTION}; +pub use log2f::f_log2f; +pub(crate) use log2f::{LOG2_R, dirty_log2f}; +pub use log2p1::f_log2p1; +pub use log2p1f::f_log2p1f; +pub(crate) use log10::LOG_R_DD; +pub use log10::f_log10; +pub use log10f::f_log10f; +pub use log10p1::f_log10p1; +pub use log10p1f::f_log10p1f; +#[allow(unused)] +pub(crate) use logf::LOG_REDUCTION_F32; +pub(crate) use logf::fast_logf; +pub use logf::{f_logf, logf}; +pub use logit::f_logit; +pub use logitf::f_logitf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/polyeval.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/polyeval.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/polyeval.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/polyeval.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1074 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, f_fmlaf}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::DyadicFloat128; +use std::ops::Mul; + +pub(crate) trait PolyevalMla { + fn polyeval_mla(a: Self, b: Self, c: Self) -> Self; +} + +impl PolyevalMla for f64 { + #[inline(always)] + fn polyeval_mla(a: Self, b: Self, c: Self) -> Self { + f_fmla(a, b, c) + } +} + +impl PolyevalMla for f32 { + #[inline(always)] + fn polyeval_mla(a: Self, b: Self, c: Self) -> Self { + f_fmlaf(a, b, c) + } +} + +impl PolyevalMla for DoubleDouble { + #[inline(always)] + fn polyeval_mla(a: Self, b: Self, c: Self) -> Self { + DoubleDouble::mul_add(a, b, c) + } +} + +impl PolyevalMla for DyadicFloat128 { + #[inline(always)] + fn polyeval_mla(a: Self, b: Self, c: Self) -> Self { + c.quick_add(&a.quick_mul(&b)) + } +} + +// impl PolyevalMla for DyadicFloat256 { +// #[inline(always)] +// fn polyeval_mla(a: Self, b: Self, c: Self) -> Self { +// c.quick_add(&a.quick_mul(&b)) +// } +// } + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval6>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, +) -> T { + let x2 = x * x; + + let u0 = T::polyeval_mla(x, a5, a4); + let u1 = T::polyeval_mla(x, a3, a2); + let u2 = T::polyeval_mla(x, a1, a0); + + let v0 = T::polyeval_mla(x2, u0, u1); + + T::polyeval_mla(x2, v0, u2) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn dd_quick_polyeval6( + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, +) -> DoubleDouble { + let x2 = DoubleDouble::quick_mult(x, x); + + let u0 = DoubleDouble::quick_mul_add(x, a5, a4); + let u1 = DoubleDouble::quick_mul_add(x, a3, a2); + let u2 = DoubleDouble::quick_mul_add(x, a1, a0); + + let v0 = DoubleDouble::quick_mul_add(x2, u0, u1); + + DoubleDouble::quick_mul_add(x2, v0, u2) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn dd_quick_polyeval6_fma( + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, +) -> DoubleDouble { + let x2 = DoubleDouble::quick_mult_fma(x, x); + + let u0 = DoubleDouble::quick_mul_add_fma(x, a5, a4); + let u1 = DoubleDouble::quick_mul_add_fma(x, a3, a2); + let u2 = DoubleDouble::quick_mul_add_fma(x, a1, a0); + + let v0 = DoubleDouble::quick_mul_add_fma(x2, u0, u1); + + DoubleDouble::quick_mul_add_fma(x2, v0, u2) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn d_polyeval6(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 { + let x2 = x * x; + + let u0 = f64::mul_add(x, a5, a4); + let u1 = f64::mul_add(x, a3, a2); + let u2 = f64::mul_add(x, a1, a0); + + let v0 = f64::mul_add(x2, u0, u1); + + f64::mul_add(x2, v0, u2) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval9>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, +) -> T { + let mut acc = a8; + acc = T::polyeval_mla(x, acc, a7); + acc = T::polyeval_mla(x, acc, a6); + acc = T::polyeval_mla(x, acc, a5); + acc = T::polyeval_mla(x, acc, a4); + acc = T::polyeval_mla(x, acc, a3); + acc = T::polyeval_mla(x, acc, a2); + acc = T::polyeval_mla(x, acc, a1); + T::polyeval_mla(x, acc, a0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_estrin_polyeval9>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + let p0 = T::polyeval_mla(x, a1, a0); + let p1 = T::polyeval_mla(x, a3, a2); + let p2 = T::polyeval_mla(x, a5, a4); + let p3 = T::polyeval_mla(x, a7, a6); + + let q0 = T::polyeval_mla(x2, p1, p0); + let q1 = T::polyeval_mla(x2, p3, p2); + let r0 = T::polyeval_mla(x4, q1, q0); + T::polyeval_mla(x8, a8, r0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval10>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let p0 = T::polyeval_mla(x, a1, a0); + let p1 = T::polyeval_mla(x, a3, a2); + let p2 = T::polyeval_mla(x, a5, a4); + let p3 = T::polyeval_mla(x, a7, a6); + let p4 = T::polyeval_mla(x, a9, a8); + + let q0 = T::polyeval_mla(x2, p1, p0); + let q1 = T::polyeval_mla(x2, p3, p2); + + let r0 = T::polyeval_mla(x4, q1, q0); + T::polyeval_mla(x8, p4, r0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn dd_quick_polyeval10( + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + a6: DoubleDouble, + a7: DoubleDouble, + a8: DoubleDouble, + a9: DoubleDouble, +) -> DoubleDouble { + let x2 = DoubleDouble::quick_mult(x, x); + let x4 = DoubleDouble::quick_mult(x2, x2); + let x8 = DoubleDouble::quick_mult(x4, x4); + + let p0 = DoubleDouble::quick_mul_add(x, a1, a0); + let p1 = DoubleDouble::quick_mul_add(x, a3, a2); + let p2 = DoubleDouble::quick_mul_add(x, a5, a4); + let p3 = DoubleDouble::quick_mul_add(x, a7, a6); + let p4 = DoubleDouble::quick_mul_add(x, a9, a8); + + let q0 = DoubleDouble::quick_mul_add(x2, p1, p0); + let q1 = DoubleDouble::quick_mul_add(x2, p3, p2); + + let r0 = DoubleDouble::quick_mul_add(x4, q1, q0); + DoubleDouble::quick_mul_add(x8, p4, r0) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn dd_quick_polyeval10_fma( + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + a6: DoubleDouble, + a7: DoubleDouble, + a8: DoubleDouble, + a9: DoubleDouble, +) -> DoubleDouble { + let x2 = DoubleDouble::quick_mult_fma(x, x); + let x4 = DoubleDouble::quick_mult_fma(x2, x2); + let x8 = DoubleDouble::quick_mult_fma(x4, x4); + + let p0 = DoubleDouble::quick_mul_add_fma(x, a1, a0); + let p1 = DoubleDouble::quick_mul_add_fma(x, a3, a2); + let p2 = DoubleDouble::quick_mul_add_fma(x, a5, a4); + let p3 = DoubleDouble::quick_mul_add_fma(x, a7, a6); + let p4 = DoubleDouble::quick_mul_add_fma(x, a9, a8); + + let q0 = DoubleDouble::quick_mul_add_fma(x2, p1, p0); + let q1 = DoubleDouble::quick_mul_add_fma(x2, p3, p2); + + let r0 = DoubleDouble::quick_mul_add_fma(x4, q1, q0); + DoubleDouble::quick_mul_add_fma(x8, p4, r0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval11>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let q0 = T::polyeval_mla(x, a1, a0); + let q1 = T::polyeval_mla(x, a3, a2); + let q2 = T::polyeval_mla(x, a5, a4); + let q3 = T::polyeval_mla(x, a7, a6); + let q4 = T::polyeval_mla(x, a9, a8); + + let r0 = T::polyeval_mla(x2, q1, q0); + let r1 = T::polyeval_mla(x2, q3, q2); + + let s0 = T::polyeval_mla(x4, r1, r0); + let s1 = T::polyeval_mla(x2, a10, q4); + T::polyeval_mla(x8, s1, s0) +} + +#[inline(always)] +pub(crate) fn f_polyeval3(x: T, a0: T, a1: T, a2: T) -> T { + T::polyeval_mla(x, T::polyeval_mla(x, a2, a1), a0) +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn d_polyeval3(x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + f64::mul_add(x, f64::mul_add(x, a2, a1), a0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval4(x: T, a0: T, a1: T, a2: T, a3: T) -> T { + let t2 = T::polyeval_mla(x, a3, a2); + let t5 = T::polyeval_mla(x, t2, a1); + T::polyeval_mla(x, t5, a0) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn d_polyeval4(x: f64, a0: f64, a1: f64, a2: f64, a3: f64) -> f64 { + let t2 = f64::mul_add(x, a3, a2); + let t5 = f64::mul_add(x, t2, a1); + f64::mul_add(x, t5, a0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_estrin_polyeval4>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, +) -> T { + let x2 = x * x; + + let p01 = T::polyeval_mla(x, a1, a0); + let p23 = T::polyeval_mla(x, a3, a2); + + T::polyeval_mla(x2, p23, p01) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval13>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let t0 = T::polyeval_mla(x, a3, a2); + let t1 = T::polyeval_mla(x, a1, a0); + let t2 = T::polyeval_mla(x, a7, a6); + let t3 = T::polyeval_mla(x, a5, a4); + let t4 = T::polyeval_mla(x, a11, a10); + let t5 = T::polyeval_mla(x, a9, a8); + + let q0 = T::polyeval_mla(x2, t0, t1); + let q1 = T::polyeval_mla(x2, t2, t3); + + let q2 = T::polyeval_mla(x2, t4, t5); + + let q3 = a12; + + let r0 = T::polyeval_mla(x4, q1, q0); + let r1 = T::polyeval_mla(x4, q3, q2); + + T::polyeval_mla(x8, r1, r0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval12>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let e0 = T::polyeval_mla(x, a1, a0); + let e1 = T::polyeval_mla(x, a3, a2); + let e2 = T::polyeval_mla(x, a5, a4); + let e3 = T::polyeval_mla(x, a7, a6); + let e4 = T::polyeval_mla(x, a9, a8); + let e5 = T::polyeval_mla(x, a11, a10); + + let f0 = T::polyeval_mla(x2, e1, e0); + let f1 = T::polyeval_mla(x2, e3, e2); + let f2 = T::polyeval_mla(x2, e5, e4); + + let g0 = T::polyeval_mla(x4, f1, f0); + + T::polyeval_mla(x8, f2, g0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval14>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let g0 = T::polyeval_mla(x, a1, a0); + let g1 = T::polyeval_mla(x, a3, a2); + let g2 = T::polyeval_mla(x, a5, a4); + let g3 = T::polyeval_mla(x, a7, a6); + let g4 = T::polyeval_mla(x, a9, a8); + let g5 = T::polyeval_mla(x, a11, a10); + let g6 = T::polyeval_mla(x, a13, a12); + + let h0 = T::polyeval_mla(x2, g1, g0); + let h1 = T::polyeval_mla(x2, g3, g2); + let h2 = T::polyeval_mla(x2, g5, g4); + + let q0 = T::polyeval_mla(x4, h1, h0); + let q1 = T::polyeval_mla(x4, g6, h2); + + T::polyeval_mla(x8, q1, q0) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn d_polyeval14( + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, + a7: f64, + a8: f64, + a9: f64, + a10: f64, + a11: f64, + a12: f64, + a13: f64, +) -> f64 { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let g0 = f64::mul_add(x, a1, a0); + let g1 = f64::mul_add(x, a3, a2); + let g2 = f64::mul_add(x, a5, a4); + let g3 = f64::mul_add(x, a7, a6); + let g4 = f64::mul_add(x, a9, a8); + let g5 = f64::mul_add(x, a11, a10); + let g6 = f64::mul_add(x, a13, a12); + + let h0 = f64::mul_add(x2, g1, g0); + let h1 = f64::mul_add(x2, g3, g2); + let h2 = f64::mul_add(x2, g5, g4); + + let q0 = f64::mul_add(x4, h1, h0); + let q1 = f64::mul_add(x4, g6, h2); + + f64::mul_add(x8, q1, q0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval7( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, +) -> T { + let t1 = T::polyeval_mla(x, a6, a5); + let t2 = T::polyeval_mla(x, t1, a4); + let t3 = T::polyeval_mla(x, t2, a3); + let t4 = T::polyeval_mla(x, t3, a2); + let t5 = T::polyeval_mla(x, t4, a1); + T::polyeval_mla(x, t5, a0) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn d_polyeval7( + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, +) -> f64 { + let t1 = f64::mul_add(x, a6, a5); + let t2 = f64::mul_add(x, t1, a4); + let t3 = f64::mul_add(x, t2, a3); + let t4 = f64::mul_add(x, t3, a2); + let t5 = f64::mul_add(x, t4, a1); + f64::mul_add(x, t5, a0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_estrin_polyeval7>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + + let b0 = T::polyeval_mla(x, a1, a0); + let b1 = T::polyeval_mla(x, a3, a2); + let b2 = T::polyeval_mla(x, a5, a4); + + let c0 = T::polyeval_mla(x2, b1, b0); + let c1 = T::polyeval_mla(x2, a6, b2); + + T::polyeval_mla(x4, c1, c0) +} + +#[inline(always)] +#[allow(unused)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn d_estrin_polyeval7( + x: f64, + a0: f64, + a1: f64, + a2: f64, + a3: f64, + a4: f64, + a5: f64, + a6: f64, +) -> f64 { + let x2 = x * x; + let x4 = x2 * x2; + + let b0 = f64::mul_add(x, a1, a0); + let b1 = f64::mul_add(x, a3, a2); + let b2 = f64::mul_add(x, a5, a4); + + let c0 = f64::mul_add(x2, b1, b0); + let c1 = f64::mul_add(x2, a6, b2); + + f64::mul_add(x4, c1, c0) +} + +#[allow(clippy::too_many_arguments)] +#[inline(always)] +pub(crate) fn f_polyeval5(x: T, a0: T, a1: T, a2: T, a3: T, a4: T) -> T { + let mut acc = a4; + acc = T::polyeval_mla(x, acc, a3); + acc = T::polyeval_mla(x, acc, a2); + acc = T::polyeval_mla(x, acc, a1); + T::polyeval_mla(x, acc, a0) +} + +#[allow(clippy::too_many_arguments)] +#[inline(always)] +#[allow(unused)] +pub(crate) fn d_polyeval5(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 { + let mut acc = a4; + acc = f64::mul_add(x, acc, a3); + acc = f64::mul_add(x, acc, a2); + acc = f64::mul_add(x, acc, a1); + f64::mul_add(x, acc, a0) +} + +#[allow(clippy::too_many_arguments)] +#[inline(always)] +pub(crate) fn f_estrin_polyeval5>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, +) -> T { + let x2 = x * x; + let p01 = T::polyeval_mla(x, a1, a0); + let p23 = T::polyeval_mla(x, a3, a2); + let t = T::polyeval_mla(x2, a4, p23); + T::polyeval_mla(x2, t, p01) +} + +#[allow(clippy::too_many_arguments)] +#[inline(always)] +#[allow(unused)] +pub(crate) fn d_estrin_polyeval5(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 { + let x2 = x * x; + let p01 = f64::mul_add(x, a1, a0); + let p23 = f64::mul_add(x, a3, a2); + let t = f64::mul_add(x2, a4, p23); + f64::mul_add(x2, t, p01) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval8( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, +) -> T { + let z0 = T::polyeval_mla(x, a7, a6); + let t1 = T::polyeval_mla(x, z0, a5); + let t2 = T::polyeval_mla(x, t1, a4); + let t3 = T::polyeval_mla(x, t2, a3); + let t4 = T::polyeval_mla(x, t3, a2); + let t5 = T::polyeval_mla(x, t4, a1); + T::polyeval_mla(x, t5, a0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_estrin_polyeval8>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + + let p0 = T::polyeval_mla(x, a1, a0); + let p1 = T::polyeval_mla(x, a3, a2); + let p2 = T::polyeval_mla(x, a5, a4); + let p3 = T::polyeval_mla(x, a7, a6); + + let q0 = T::polyeval_mla(x2, p1, p0); + let q1 = T::polyeval_mla(x2, p3, p2); + + T::polyeval_mla(x4, q1, q0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval16>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, + a15: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let q0 = T::polyeval_mla(x, a1, a0); + let q1 = T::polyeval_mla(x, a3, a2); + let q2 = T::polyeval_mla(x, a5, a4); + let q3 = T::polyeval_mla(x, a7, a6); + let q4 = T::polyeval_mla(x, a9, a8); + let q5 = T::polyeval_mla(x, a11, a10); + let q6 = T::polyeval_mla(x, a13, a12); + let q7 = T::polyeval_mla(x, a15, a14); + + let r0 = T::polyeval_mla(x2, q1, q0); + let r1 = T::polyeval_mla(x2, q3, q2); + let r2 = T::polyeval_mla(x2, q5, q4); + let r3 = T::polyeval_mla(x2, q7, q6); + + let s0 = T::polyeval_mla(x4, r1, r0); + let s1 = T::polyeval_mla(x4, r3, r2); + + T::polyeval_mla(x8, s1, s0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval15>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + + let e0 = T::polyeval_mla(x, a1, a0); + let e1 = T::polyeval_mla(x, a3, a2); + let e2 = T::polyeval_mla(x, a5, a4); + let e3 = T::polyeval_mla(x, a7, a6); + let e4 = T::polyeval_mla(x, a9, a8); + let e5 = T::polyeval_mla(x, a11, a10); + let e6 = T::polyeval_mla(x, a13, a12); + + // Level 2 + let f0 = T::polyeval_mla(x2, e1, e0); + let f1 = T::polyeval_mla(x2, e3, e2); + let f2 = T::polyeval_mla(x2, e5, e4); + let f3 = T::polyeval_mla(x2, a14, e6); + + // Level 3 + let g0 = T::polyeval_mla(x4, f1, f0); + let g1 = T::polyeval_mla(x4, f3, f2); + + // Final + T::polyeval_mla(x8, g1, g0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval18>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, + a15: T, + a16: T, + a17: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + let x16 = x8 * x8; + + let q0 = T::polyeval_mla(x, a1, a0); + let q1 = T::polyeval_mla(x, a3, a2); + let q2 = T::polyeval_mla(x, a5, a4); + let q3 = T::polyeval_mla(x, a7, a6); + let q4 = T::polyeval_mla(x, a9, a8); + let q5 = T::polyeval_mla(x, a11, a10); + let q6 = T::polyeval_mla(x, a13, a12); + let q7 = T::polyeval_mla(x, a15, a14); + let q8 = T::polyeval_mla(x, a17, a16); + + let r0 = T::polyeval_mla(x2, q1, q0); + let r1 = T::polyeval_mla(x2, q3, q2); + let r2 = T::polyeval_mla(x2, q5, q4); + let r3 = T::polyeval_mla(x2, q7, q6); + + let s0 = T::polyeval_mla(x4, r1, r0); + let s1 = T::polyeval_mla(x4, r3, r2); + + let t0 = T::polyeval_mla(x8, s1, s0); + + T::polyeval_mla(x16, q8, t0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval19>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, + a15: T, + a16: T, + a17: T, + a18: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + let x16 = x8 * x8; + + // Level 0: pairs + let e0 = T::polyeval_mla(x, a1, a0); // a0 + a1·x + let e1 = T::polyeval_mla(x, a3, a2); // a2 + a3·x + let e2 = T::polyeval_mla(x, a5, a4); + let e3 = T::polyeval_mla(x, a7, a6); + let e4 = T::polyeval_mla(x, a9, a8); + let e5 = T::polyeval_mla(x, a11, a10); + let e6 = T::polyeval_mla(x, a13, a12); + let e7 = T::polyeval_mla(x, a15, a14); + let e8 = T::polyeval_mla(x, a17, a16); + + // Level 1: combine with x² + let f0 = T::polyeval_mla(x2, e1, e0); + let f1 = T::polyeval_mla(x2, e3, e2); + let f2 = T::polyeval_mla(x2, e5, e4); + let f3 = T::polyeval_mla(x2, e7, e6); + + // Level 2: combine with x⁴ + let g0 = T::polyeval_mla(x4, f1, f0); + let g1 = T::polyeval_mla(x4, f3, f2); + + // Level 3: combine with x⁸ + let h0 = T::polyeval_mla(x8, g1, g0); + + // Final: combine with x¹⁶ + let final_poly = T::polyeval_mla(x16, e8, h0); + + // Degree 18: Add a18·x¹⁸ + // This assumes `x18 = x16 * x2`, since x² already computed + let x18 = x16 * x2; + T::polyeval_mla(x18, a18, final_poly) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval22>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, + a15: T, + a16: T, + a17: T, + a18: T, + a19: T, + a20: T, + a21: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + let x16 = x8 * x8; + + let p0 = T::polyeval_mla(x, a1, a0); // a1·x + a0 + let p1 = T::polyeval_mla(x, a3, a2); // a3·x + a2 + let p2 = T::polyeval_mla(x, a5, a4); + let p3 = T::polyeval_mla(x, a7, a6); + let p4 = T::polyeval_mla(x, a9, a8); + let p5 = T::polyeval_mla(x, a11, a10); + let p6 = T::polyeval_mla(x, a13, a12); + let p7 = T::polyeval_mla(x, a15, a14); + let p8 = T::polyeval_mla(x, a17, a16); + let p9 = T::polyeval_mla(x, a19, a18); + let p10 = T::polyeval_mla(x, a21, a20); + + let q0 = T::polyeval_mla(x2, p1, p0); // (a3·x + a2)·x² + (a1·x + a0) + let q1 = T::polyeval_mla(x2, p3, p2); + let q2 = T::polyeval_mla(x2, p5, p4); + let q3 = T::polyeval_mla(x2, p7, p6); + let q4 = T::polyeval_mla(x2, p9, p8); + let r0 = T::polyeval_mla(x4, q1, q0); // q1·x⁴ + q0 + let r1 = T::polyeval_mla(x4, q3, q2); + let s0 = T::polyeval_mla(x8, r1, r0); // r1·x⁸ + r0 + let r2 = T::polyeval_mla(x4, p10, q4); // p10·x⁴ + q4 + T::polyeval_mla(x16, r2, s0) +} + +#[inline(always)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn f_polyeval24>( + x: T, + a0: T, + a1: T, + a2: T, + a3: T, + a4: T, + a5: T, + a6: T, + a7: T, + a8: T, + a9: T, + a10: T, + a11: T, + a12: T, + a13: T, + a14: T, + a15: T, + a16: T, + a17: T, + a18: T, + a19: T, + a20: T, + a21: T, + a22: T, + a23: T, +) -> T { + let x2 = x * x; + let x4 = x2 * x2; + let x8 = x4 * x4; + let x16 = x8 * x8; + + // Group degree 0–1 + let e0 = T::polyeval_mla(x, a1, a0); + // Group degree 2–3 + let e1 = T::polyeval_mla(x, a3, a2); + // Group degree 4–5 + let e2 = T::polyeval_mla(x, a5, a4); + // Group degree 6–7 + let e3 = T::polyeval_mla(x, a7, a6); + // Group degree 8–9 + let e4 = T::polyeval_mla(x, a9, a8); + // Group degree 10–11 + let e5 = T::polyeval_mla(x, a11, a10); + // Group degree 12–13 + let e6 = T::polyeval_mla(x, a13, a12); + // Group degree 14–15 + let e7 = T::polyeval_mla(x, a15, a14); + // Group degree 16–17 + let e8 = T::polyeval_mla(x, a17, a16); + // Group degree 18–19 + let e9 = T::polyeval_mla(x, a19, a18); + // Group degree 20–21 + let e10 = T::polyeval_mla(x, a21, a20); + // Group degree 22–23 + let e11 = T::polyeval_mla(x, a23, a22); + + // Now group into x2 terms + let f0 = T::polyeval_mla(x2, e1, e0); + let f1 = T::polyeval_mla(x2, e3, e2); + let f2 = T::polyeval_mla(x2, e5, e4); + let f3 = T::polyeval_mla(x2, e7, e6); + let f4 = T::polyeval_mla(x2, e9, e8); + let f5 = T::polyeval_mla(x2, e11, e10); + + // Now group into x4 terms + let g0 = T::polyeval_mla(x4, f1, f0); + let g1 = T::polyeval_mla(x4, f3, f2); + let g2 = T::polyeval_mla(x4, f5, f4); + + // Now group into x8 terms + let h0 = T::polyeval_mla(x8, g1, g0); + let h1 = g2; + + // Final step (x16 term) + T::polyeval_mla(x16, h1, h0) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,562 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::get_exponent_f64; +use crate::common::{f_fmla, is_integer, is_odd_integer}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::exp; +use crate::logs::log_dyadic; +use crate::pow_exec::{exp_dyadic, pow_exp_1, pow_log_1}; +use crate::triple_double::TripleDouble; +use crate::{f_exp2, f_exp10, log}; + +#[cold] +fn pow_exp10_fallback(x: f64) -> f64 { + f_exp10(x) +} + +#[cold] +fn pow_exp2_fallback(x: f64) -> f64 { + f_exp2(x) +} + +#[cold] +#[inline(never)] +fn f_powi(x: f64, y: f64) -> f64 { + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + let mut s = DoubleDouble::new(0., x); + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { + s + } else { + DoubleDouble::new(0., 1.) + }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = DoubleDouble::mult(s, s); + if iter_count % 2 != 0 { + acc = DoubleDouble::mult(acc, s); + } + } + + let dz = if y.is_sign_negative() { + acc.recip() + } else { + acc + }; + let ub = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), -dz.hi, dz.lo); // 2^-59 + let lb = dz.hi + f_fmla(f64::from_bits(0x3c40000000000000), dz.hi, dz.lo); // 2^-59 + if ub == lb { + return dz.to_f64(); + } + f_powi_hard(x, y) +} + +#[cold] +#[inline(never)] +fn f_powi_hard(x: f64, y: f64) -> f64 { + let mut iter_count = unsafe { y.abs().to_int_unchecked::() }; + + let mut s = TripleDouble::new(0., 0., x); + + // exponentiation by squaring: O(log(y)) complexity + let mut acc = if iter_count % 2 != 0 { + s + } else { + TripleDouble::new(0., 0., 1.) + }; + + while { + iter_count >>= 1; + iter_count + } != 0 + { + s = TripleDouble::quick_mult(s, s); + if iter_count % 2 != 0 { + acc = TripleDouble::quick_mult(acc, s); + } + } + + let dz = if y.is_sign_negative() { + acc.recip() + } else { + acc + }; + dz.to_f64() +} + +/// Power function +/// +/// max found ULP 0.5 +pub fn f_pow(x: f64, y: f64) -> f64 { + let mut y = y; + let x_sign = x.is_sign_negative(); + let y_sign = y.is_sign_negative(); + + let x_abs = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_abs = y.to_bits() & 0x7fff_ffff_ffff_ffff; + + const MANTISSA_MASK: u64 = (1u64 << 52) - 1; + + let y_mant = y.to_bits() & MANTISSA_MASK; + let x_u = x.to_bits(); + let x_a = x_abs; + let y_a = y_abs; + + let mut x = x; + + // If x or y is signaling NaN + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + + let mut s = 1.0; + + // The double precision number that is closest to 1 is (1 - 2^-53), which has + // log2(1 - 2^-53) ~ -1.715...p-53. + // So if |y| > |1075 / log2(1 - 2^-53)|, and x is finite: + // |y * log2(x)| = 0 or > 1075. + // Hence, x^y will either overflow or underflow if x is not zero. + if y_mant == 0 + || y_a > 0x43d7_4910_d52d_3052 + || x_u == 1f64.to_bits() + || x_u >= f64::INFINITY.to_bits() + || x_u < f64::MIN.to_bits() + { + // Exceptional exponents. + if y == 0.0 { + return 1.0; + } + + match y_a { + 0x3fe0_0000_0000_0000 => { + if x == 0.0 || x_u == f64::NEG_INFINITY.to_bits() { + // pow(-0, 1/2) = +0 + // pow(-inf, 1/2) = +inf + return if y_sign { 1.0 / (x * x) } else { x * x }; + } + return if y_sign { + if x.is_infinite() { + return if x.is_sign_positive() { 0. } else { f64::NAN }; + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let r = x.sqrt() / x; + let rx = r * x; + let drx = f_fmla(r, x, -rx); + let h = f_fmla(r, rx, -1.0) + r * drx; + let dr = (r * 0.5) * h; + r - dr + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let r = x.sqrt() / x; + let d2x = DoubleDouble::from_exact_mult(r, x); + let DoubleDouble { hi: h, lo: pr } = DoubleDouble::quick_mult_f64(d2x, r); + let DoubleDouble { hi: p, lo: q } = + DoubleDouble::from_full_exact_add(-1.0, h); + let h = DoubleDouble::from_exact_add(p, pr + q); + let dr = DoubleDouble::quick_mult_f64(h, r * 0.5); + r - dr.hi - dr.lo + } + } else { + x.sqrt() + }; + } + 0x3ff0_0000_0000_0000 => { + return if y_sign { 1.0 / x } else { x }; + } + 0x4000_0000_0000_0000 => { + let x_e = get_exponent_f64(x); + if x_e > 511 { + return if y_sign { 0. } else { f64::INFINITY }; + } + // not enough precision to make 0.5 ULP for subnormals + if x_e.abs() < 70 { + let x_sqr = DoubleDouble::from_exact_mult(x, x); + return if y_sign { + let recip = x_sqr.recip(); + recip.to_f64() + } else { + x_sqr.to_f64() + }; + } + } + _ => {} + } + + // |y| > |1075 / log2(1 - 2^-53)|. + if y_a > 0x43d7_4910_d52d_3052 { + if y_a >= 0x7ff0_0000_0000_0000 { + // y is inf or nan + if y_mant != 0 { + // y is NaN + // pow(1, NaN) = 1 + // pow(x, NaN) = NaN + return if x_u == 1f64.to_bits() { 1.0 } else { y }; + } + + // Now y is +-Inf + if f64::from_bits(x_abs).is_nan() { + // pow(NaN, +-Inf) = NaN + return x; + } + + if x_a == 0x3ff0_0000_0000_0000 { + // pow(+-1, +-Inf) = 1.0 + return 1.0; + } + + if x == 0.0 && y_sign { + // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO + return f64::INFINITY; + } + // pow (|x| < 1, -inf) = +inf + // pow (|x| < 1, +inf) = 0.0 + // pow (|x| > 1, -inf) = 0.0 + // pow (|x| > 1, +inf) = +inf + return if (x_a < 1f64.to_bits()) == y_sign { + f64::INFINITY + } else { + 0.0 + }; + } + // x^y will overflow / underflow in double precision. Set y to a + // large enough exponent but not too large, so that the computations + // won't overflow in double precision. + y = if y_sign { + f64::from_bits(0xc630000000000000) + } else { + f64::from_bits(0x4630000000000000) + }; + } + + // y is finite and non-zero. + + if x_u == 1f64.to_bits() { + // pow(1, y) = 1 + return 1.0; + } + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } else if x == 2.0 { + return pow_exp2_fallback(y); + } else if x == 10.0 { + return pow_exp10_fallback(y); + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return if out_is_neg { -0.0 } else { 0.0 }; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + + // x is finite and negative, and y is a finite integer. + + let is_y_integer = is_integer(y); + // y is integer and in [-102;102] and |x|<2^10 + + // this is correct only for positive exponent number without FMA, + // otherwise reciprocal may overflow. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + if is_y_integer + && y_a <= 0x4059800000000000u64 + && x_a <= 0x4090000000000000u64 + && x_a > 0x3cc0_0000_0000_0000 + { + return f_powi(x, y); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + if is_y_integer + && y_a <= 0x4059800000000000u64 + && x_a <= 0x4090000000000000u64 + && x_a > 0x3cc0_0000_0000_0000 + && y.is_sign_positive() + { + return f_powi(x, y); + } + + if x_sign { + if is_y_integer { + x = -x; + if is_odd_integer(y) { + // sign = -1.0; + static CS: [f64; 2] = [1.0, -1.0]; + + // set sign to 1 for y even, to -1 for y odd + let y_parity = if (y.abs()) >= f64::from_bits(0x4340000000000000) { + 0usize + } else { + (y as i64 & 0x1) as usize + }; + s = CS[y_parity]; + } + } else { + // pow( negative, non-integer ) = NaN + return f64::NAN; + } + } + + // y is finite and non-zero. + + if x_u == 1f64.to_bits() { + // pow(1, y) = 1 + return 1.0; + } + + if x == 0.0 { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + // pow(0, negative number) = inf + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } + + if x_a == f64::INFINITY.to_bits() { + let out_is_neg = x_sign && is_odd_integer(y); + if y_sign { + return if out_is_neg { -0.0 } else { 0.0 }; + } + return if out_is_neg { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_a > f64::INFINITY.to_bits() { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + } + + // approximate log(x) + let (mut l, cancel) = pow_log_1(x); + + /* We should avoid a spurious underflow/overflow in y*log(x). + Underflow: for x<>1, the smallest absolute value of log(x) is obtained + for x=1-2^-53, with |log(x)| ~ 2^-53. Thus to avoid a spurious underflow + we require |y| >= 2^-969. + Overflow: the largest absolute value of log(x) is obtained for x=2^-1074, + with |log(x)| < 745. Thus to avoid a spurious overflow we require + |y| < 2^1014. */ + let ey = ((y.to_bits() >> 52) & 0x7ff) as i32; + if ey < 0x36 || ey >= 0x7f5 { + l.lo = f64::NAN; + l.hi = f64::NAN; + } + + let r = DoubleDouble::quick_mult_f64(l, y); + let res = pow_exp_1(r, s); + static ERR: [u64; 2] = [0x3bf2700000000000, 0x3c55700000000000]; + let res_min = res.hi + f_fmla(f64::from_bits(ERR[cancel as usize]), -res.hi, res.lo); + let res_max = res.hi + f_fmla(f64::from_bits(ERR[cancel as usize]), res.hi, res.lo); + if res_min == res_max { + return res_max; + } + pow_rational128(x, y, s) +} + +#[cold] +fn pow_rational128(x: f64, y: f64, s: f64) -> f64 { + let f_y = DyadicFloat128::new_from_f64(y); + + let r = log_dyadic(x) * f_y; + let mut result = exp_dyadic(r); + + // 2^R.ex <= R < 2^(R.ex+1) + + // /* case R < 2^-1075: underflow case */ + // if result.exponent < -1075 { + // return 0.5 * (s * f64::from_bits(0x0000000000000001)); + // } + + result.sign = if s == -1.0 { + DyadicSign::Neg + } else { + DyadicSign::Pos + }; + + result.fast_as_f64() +} + +/// Pow for given value for const context. +/// This is simplified version just to make a good approximation on const context. +pub const fn pow(d: f64, n: f64) -> f64 { + let value = d.abs(); + + let r = n * log(value); + let c = exp(r); + if n == 0. { + return 1.; + } + if d < 0.0 { + let y = n as i32; + if y % 2 == 0 { c } else { -c } + } else { + c + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn powf_test() { + assert!( + (pow(2f64, 3f64) - 8f64).abs() < 1e-9, + "Invalid result {}", + pow(2f64, 3f64) + ); + assert!( + (pow(0.5f64, 2f64) - 0.25f64).abs() < 1e-9, + "Invalid result {}", + pow(0.5f64, 2f64) + ); + } + + #[test] + fn f_pow_test() { + assert_eq!(f_pow( + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135264499699371, + -0.5, + ), 27189929701044785000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_pow( + 0.000000000000000000000000000000000000000000000000000021798599361155193, + -2., + ),2104470396771397700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!( + f_pow(-25192281723900620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000., + -2.), + 0. + ); + assert_eq!( + f_pow(0.000000000000000000000000000000000000000000000000000021799650661798696, + -2.), + 2104267423084451500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000. + ); + assert_eq!( + f_pow(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014916691520383755, + -2.), + 44942267764413600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000. + ); + assert_eq!( + f_pow( + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135264499699371, + -0.5, + ), + 27189929701044785000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000. + ); + assert_eq!(f_pow(1., f64::INFINITY), 1.); + assert_eq!(f_pow(2., f64::INFINITY), f64::INFINITY); + assert_eq!(f_pow(f64::INFINITY, -0.5), 0.); + assert!( + (f_pow(2f64, 3f64) - 8f64).abs() < 1e-9, + "Invalid result {}", + f_pow(2f64, 3f64) + ); + assert!( + (f_pow(0.5f64, 2f64) - 0.25f64).abs() < 1e-9, + "Invalid result {}", + f_pow(0.5f64, 2f64) + ); + assert_eq!(f_pow(2.1f64, 2.7f64), 7.412967494768546); + assert_eq!(f_pow(27., 1. / 3.), 3.); + } + + #[test] + fn powi_test() { + assert_eq!(f_pow(f64::from_bits(0x3cc0_0000_0000_0000), 102.), 0.0); + assert_eq!(f_pow(3., 3.), 27.); + assert_eq!(f_pow(3., -3.), 1. / 27.); + assert_eq!(f_pow(3., 102.), 4.638397686588102e48); + assert_eq!(f_pow(0.000000000000011074474670636028, -22.), 10589880229528372000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow_exec.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_exec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow_exec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_exec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,772 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::dd_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::exponents::{EXP_REDUCE_T0, EXP_REDUCE_T1, ldexp}; +use crate::exponents::{EXPM1_T0, EXPM1_T1}; +use crate::polyeval::f_polyeval6; +use crate::pow_tables::{EXP_T1_2_DYADIC, EXP_T2_2_DYADIC, POW_INVERSE, POW_LOG_INV}; +use crate::rounding::CpuRound; +use crate::rounding::CpuRoundTiesEven; + +#[inline(always)] +pub(crate) fn log_poly_1(z: f64) -> DoubleDouble { + /* The following is a degree-8 polynomial generated by Sollya for + log(1+x)-x+x^2/2 over [-0.0040283203125,0.0040283203125] + with absolute error < 2^-81.63 + and relative error < 2^-72.423 (see sollya/P_1.sollya). + The relative error is for x - x^2/2 + P(x) with respect to log(1+x). */ + const P_1: [u64; 6] = [ + 0x3fd5555555555558, + 0xbfd0000000000003, + 0x3fc999999981f535, + 0xbfc55555553d1eb4, + 0x3fc2494526fd4a06, + 0xbfc0001f0c80e8ce, + ]; + let w = DoubleDouble::from_exact_mult(z, z); + let t = dd_fmla(f64::from_bits(P_1[5]), z, f64::from_bits(P_1[4])); + let mut u = dd_fmla(f64::from_bits(P_1[3]), z, f64::from_bits(P_1[2])); + let mut v = dd_fmla(f64::from_bits(P_1[1]), z, f64::from_bits(P_1[0])); + u = dd_fmla(t, w.hi, u); + v = dd_fmla(u, w.hi, v); + u = v * w.hi; + DoubleDouble::new(dd_fmla(u, z, -0.5 * w.lo), -0.5 * w.hi) +} + +/* Given 2^-1074 <= x <= 0x1.fffffffffffffp+1023, this routine puts in h+l + an approximation of log(x) such that |l| < 2^-23.89*|h| and + + | h + l - log(x) | <= elog * |log x| + + with elog = 2^-73.527 if x < 1/sqrt(2) or sqrt(2) < x, + and elog = 2^-67.0544 if 1/sqrt(2) < x < sqrt(2) + (note that x cannot equal 1/sqrt(2) nor sqrt(2)). +*/ +#[inline] +pub(crate) fn pow_log_1(x: f64) -> (DoubleDouble, bool) { + /* for 181 <= i <= 362, r[i] = _INVERSE[i-181] is a 9-bit approximation of + 1/x[i], where i*2^-8 <= x[i] < (i+1)*2^-8. + More precisely r[i] is a 9-bit value such that r[i]*y-1 is representable + exactly on 53 bits for for any y, i*2^-8 <= y < (i+1)*2^-8. + Moreover |r[i]*y-1| < 0.0040283203125. + Table generated with the accompanying pow.sage file, + with l=inverse_centered(k=8,prec=9,maxbits=53,verbose=false) */ + let x_u = x.to_bits(); + let mut m = x_u & 0xfffffffffffff; + let mut e: i64 = ((x_u >> 52) & 0x7ff) as i64; + + let t; + if e != 0 { + t = m | (0x3ffu64 << 52); + m = m.wrapping_add(1u64 << 52); + e -= 0x3ff; + } else { + /* x is a subnormal double */ + let k = m.leading_zeros() - 11; + + e = -0x3fei64 - k as i64; + m = m.wrapping_shl(k); + t = m | (0x3ffu64 << 52); + } + + /* now |x| = 2^_e*_t = 2^(_e-52)*m with 1 <= _t < 2, + and 2^52 <= _m < 2^53 */ + + // log(x) = log(t) + E · log(2) + let mut t = f64::from_bits(t); + + // If m > sqrt(2) we divide it by 2 so ensure 1/sqrt(2) < t < sqrt(2) + let c: usize = (m >= 0x16a09e667f3bcd) as usize; + static CY: [f64; 2] = [1.0, 0.5]; + static CM: [u64; 2] = [44, 45]; + + e = e.wrapping_add(c as i64); + let be = e; + let i = m >> CM[c]; /* i/2^8 <= t < (i+1)/2^8 */ + /* when c=1, we have 0x16a09e667f3bcd <= m < 2^53, thus 90 <= i <= 127; + when c=0, we have 2^52 <= m < 0x16a09e667f3bcd, thus 128 <= i <= 181 */ + t *= CY[c]; + /* now 0x1.6a09e667f3bcdp-1 <= t < 0x1.6a09e667f3bcdp+0, + and log(x) = E * log(2) + log(t) */ + + let r = f64::from_bits(POW_INVERSE[(i - 181) as usize]); + let l1 = f64::from_bits(POW_LOG_INV[(i - 181) as usize].1); + let l2 = f64::from_bits(POW_LOG_INV[(i - 181) as usize].0); + + let z = dd_fmla(r, t, -1.0); + + const LOG2_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3d2ef35793c76730), + f64::from_bits(0x3fe62e42fefa3800), + ); + + let th = dd_fmla(be as f64, LOG2_DD.hi, l1); + let tl = dd_fmla(be as f64, LOG2_DD.lo, l2); + + let mut v = DoubleDouble::f64_add(th, DoubleDouble::new(tl, z)); + let p = log_poly_1(z); + v = DoubleDouble::f64_add(v.hi, DoubleDouble::new(v.lo + p.lo, p.hi)); + + if e == 0 && v.lo.abs() > (v.hi.abs()) * f64::from_bits(0x3e70000000000000) { + v = DoubleDouble::from_exact_add(v.hi, v.lo); + return (v, true); + } + + (v, false) +} + +/* Given z such that |z| < 2^-12.905, + this routine puts in qh+ql an approximation of exp(z) such that + + | (qh+ql) / exp(z) - 1 | < 2^-64.902632 + + and |ql| <= 2^-51.999. +*/ +#[inline(always)] +fn exp_poly_1(z: f64) -> DoubleDouble { + /* The following is a degree-4 polynomial generated by Sollya for exp(x) + over [-2^-12.905,2^-12.905] + with absolute error < 2^-74.34 (see sollya/Q_1.sollya). */ + const Q_1: [u64; 5] = [ + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fe0000000000000, + 0x3fc5555555997996, + 0x3fa5555555849d8d, + ]; + let mut q = dd_fmla(f64::from_bits(Q_1[4]), z, f64::from_bits(Q_1[3])); + q = dd_fmla(q, z, f64::from_bits(Q_1[2])); + let h0 = dd_fmla(q, z, f64::from_bits(Q_1[1])); + + let v1 = DoubleDouble::from_exact_mult(z, h0); + DoubleDouble::f64_add(f64::from_bits(Q_1[0]), v1) +} + +/* Given z such that |z| < 2^-12.905, + this routine puts in qh+ql an approximation of exp(z) such that + + | (qh+ql) / exp(z) - 1 | < 2^-64.902632 + + and |ql| <= 2^-51.999. +*/ + +// #[inline(always)] +// fn exp_poly_dd(z: DoubleDouble) -> DoubleDouble { +// /* The following is a degree-4 polynomial generated by Sollya for exp(x) +// over [-2^-12.905,2^-12.905] */ +// const Q_1: [(u64, u64); 7] = [ +// (0x0000000000000000, 0x3ff0000000000000), +// (0x3a20e40000000000, 0x3ff0000000000000), +// (0x3a04820000000000, 0x3fe0000000000000), +// (0xbc756423c5338a66, 0x3fc5555555555556), +// (0xbc5560f74db5556c, 0x3fa5555555555556), +// (0x3c3648eca89bc6ac, 0x3f8111111144fbee), +// (0xbbd53d924ae90c8c, 0x3f56c16c16ffeecc), +// ]; +// let mut p = DoubleDouble::mult(z, DoubleDouble::from_bit_pair(Q_1[6])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[5])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[4])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[3])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[2])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[1])); +// p = DoubleDouble::quick_mul_add(z, p, DoubleDouble::from_bit_pair(Q_1[0])); +// p +// } + +#[inline] +pub(crate) fn pow_exp_1(r: DoubleDouble, s: f64) -> DoubleDouble { + const RHO0: f64 = f64::from_bits(0xc0874910ee4e8a27); + // #define RHO1 -0x1.577453f1799a6p+9 + /* We increase the initial value of RHO1 to avoid spurious underflow in + the result value el. However, it is not possible to obtain a lower + bound on |el| from the input value rh, thus this modified value of RHO1 + is obtained experimentally. */ + const RHO1: f64 = f64::from_bits(0xc08483b8cca421af); + const RHO2: f64 = f64::from_bits(0x40862e42e709a95b); + const RHO3: f64 = f64::from_bits(0x40862e4316ea5df9); + + // use !(rh <= RHO2) instead of rh < RHO2 to catch rh = NaN too + #[allow(clippy::neg_cmp_op_on_partial_ord)] + if !(r.hi <= RHO2) { + return if r.hi > RHO3 { + /* If rh > RHO3, we are sure there is overflow, + For s=1 we return eh = el = DBL_MAX, which yields + res_min = res_max = +Inf for rounding up or to nearest, + and res_min = res_max = DBL_MAX for rounding down or toward zero, + which will yield the correct rounding. + For s=-1 we return eh = el = -DBL_MAX, which similarly gives + res_min = res_max = -Inf or res_min = res_max = -DBL_MAX, + which is the correct rounding. */ + DoubleDouble::new( + f64::from_bits(0x7fefffffffffffff) * s, + f64::from_bits(0x7fefffffffffffff) * s, + ) + } else { + /* If RHO2 < rh <= RHO3, we are in the intermediate region + where there might be overflow or not, thus we set eh = el = NaN, + which will set res_min = res_max = NaN, the comparison + res_min == res_max will fail: we defer to the 2nd phase. */ + DoubleDouble::new(f64::NAN, f64::NAN) + }; + } + + if r.hi < RHO1 { + return if r.hi < RHO0 { + /* For s=1, we have eh=el=+0 except for rounding up, + thus res_min=+0 or -0, res_max=+0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=1 and rounding up, we have eh=+0, el=2^-1074, + thus res_min = res_max = 2^-1074, which is the expected result too. + For s=-1, we have eh=el=-0 except for rounding down, + thus res_min=-0 or +0, res_max=-0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=-1 and rounding down, we have eh=-0, el=-2^-1074, + thus res_min = res_max = -2^-1074, which is the expected result too. + */ + DoubleDouble::new(f64::from_bits(0x0000000000000001) * (0.5 * s), 0.0 * s) + } else { + /* RHO0 <= rh < RHO1 or s < 0: we defer to the 2nd phase */ + DoubleDouble::new(f64::NAN, f64::NAN) + }; + } + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r.hi * INVLOG2).cpu_round(); + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + + let zh = dd_fmla(LOG2H, -k, r.hi); + let zl = dd_fmla(LOG2L, -k, r.lo); + + let bk = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let mut de = DoubleDouble::quick_mult(t1, t0); + let q = exp_poly_1(zh + zl); + de = DoubleDouble::quick_mult(de, q); + /* we should have 1 < M < 2047 here, since we filtered out + potential underflow/overflow cases at the beginning of this function */ + + let mut du = (mk as u64).wrapping_shl(52); + du = (f64::from_bits(du) * s).to_bits(); + de.hi *= f64::from_bits(du); + de.lo *= f64::from_bits(du); + de +} + +#[inline] +pub(crate) fn exp_dd_fast(r: DoubleDouble) -> DoubleDouble { + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r.hi * INVLOG2).cpu_round(); + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + + let mut z = DoubleDouble::mul_f64_add(DoubleDouble::new(LOG2L, LOG2H), -k, r); + z = DoubleDouble::from_exact_add(z.hi, z.lo); + + let bk = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let mut de = DoubleDouble::quick_mult(t1, t0); + // exp(hi + lo) = exp(hi) * exp(lo) + let q_hi = exp_poly_1(z.hi); + // Taylor series exp(x) ~ 1 + x since z.lo < ulp(z.h) + let q_lo = DoubleDouble::from_exact_add(1., z.lo); + let q = DoubleDouble::quick_mult(q_hi, q_lo); + de = DoubleDouble::quick_mult(de, q); + /* we should have 1 < M < 2047 here, since we filtered out + potential underflow/overflow cases at the beginning of this function */ + + let du = (mk as u64).wrapping_shl(52); + de.hi *= f64::from_bits(du); + de.lo *= f64::from_bits(du); + de +} + +#[inline] +pub(crate) fn pow_exp_dd(r: DoubleDouble, s: f64) -> DoubleDouble { + const RHO0: f64 = f64::from_bits(0xc0874910ee4e8a27); + // #define RHO1 -0x1.577453f1799a6p+9 + /* We increase the initial value of RHO1 to avoid spurious underflow in + the result value el. However, it is not possible to obtain a lower + bound on |el| from the input value rh, thus this modified value of RHO1 + is obtained experimentally. */ + const RHO1: f64 = f64::from_bits(0xc08483b8cca421af); + const RHO2: f64 = f64::from_bits(0x40862e42e709a95b); + const RHO3: f64 = f64::from_bits(0x40862e4316ea5df9); + + // use !(rh <= RHO2) instead of rh < RHO2 to catch rh = NaN too + #[allow(clippy::neg_cmp_op_on_partial_ord)] + if !(r.hi <= RHO2) { + return if r.hi > RHO3 { + /* If rh > RHO3, we are sure there is overflow, + For s=1 we return eh = el = DBL_MAX, which yields + res_min = res_max = +Inf for rounding up or to nearest, + and res_min = res_max = DBL_MAX for rounding down or toward zero, + which will yield the correct rounding. + For s=-1 we return eh = el = -DBL_MAX, which similarly gives + res_min = res_max = -Inf or res_min = res_max = -DBL_MAX, + which is the correct rounding. */ + DoubleDouble::new( + f64::from_bits(0x7fefffffffffffff) * s, + f64::from_bits(0x7fefffffffffffff) * s, + ) + } else { + /* If RHO2 < rh <= RHO3, we are in the intermediate region + where there might be overflow or not, thus we set eh = el = NaN, + which will set res_min = res_max = NaN, the comparison + res_min == res_max will fail: we defer to the 2nd phase. */ + DoubleDouble::new(f64::NAN, f64::NAN) + }; + } + + if r.hi < RHO1 { + return if r.hi < RHO0 { + /* For s=1, we have eh=el=+0 except for rounding up, + thus res_min=+0 or -0, res_max=+0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=1 and rounding up, we have eh=+0, el=2^-1074, + thus res_min = res_max = 2^-1074, which is the expected result too. + For s=-1, we have eh=el=-0 except for rounding down, + thus res_min=-0 or +0, res_max=-0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=-1 and rounding down, we have eh=-0, el=-2^-1074, + thus res_min = res_max = -2^-1074, which is the expected result too. + */ + DoubleDouble::new(f64::from_bits(0x0000000000000001) * (0.5 * s), 0.0 * s) + } else { + /* RHO0 <= rh < RHO1 or s < 0: we defer to the 2nd phase */ + DoubleDouble::new(f64::NAN, f64::NAN) + }; + } + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r.hi * INVLOG2).cpu_round(); + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + + let z = DoubleDouble::mul_f64_add(DoubleDouble::new(LOG2L, LOG2H), -k, r); + + let bk = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXP_REDUCE_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXP_REDUCE_T1[i1 as usize]); + let mut de = DoubleDouble::quick_mult(t1, t0); + let q = exp_poly_1(z.to_f64()); + de = DoubleDouble::quick_mult(de, q); + /* we should have 1 < M < 2047 here, since we filtered out + potential underflow/overflow cases at the beginning of this function */ + + let mut du = (mk as u64).wrapping_shl(52); + du = (f64::from_bits(du) * s).to_bits(); + de.hi *= f64::from_bits(du); + de.lo *= f64::from_bits(du); + de +} +/* +#[inline(always)] +pub(crate) fn expm1_poly_dd(z: DoubleDouble) -> DoubleDouble { + /* + Sollya: + pretty = proc(u) { + return ~(floor(u*1000)/1000); + }; + + d = [-2^-12.905,2^-12.905]; + f = expm1(x); + w = 1; + pf = fpminimax(f, [|1,2,3,4,5,6,7|], [|1, 1, 107...|], d, absolute, floating); + err_p = -log2(dirtyinfnorm(pf*w-f, d)); + display = decimal; + + for i from 1 to degree(pf) do print(coeff(pf, i)); + + print (pf); + display = decimal; + print ("absolute error:",pretty(err_p)); + f = 1; + w = 1/expm1(x); + err_p = -log2(dirtyinfnorm(pf*w-f, d)); + print ("relative error:",pretty(err_p)); + */ + const Q: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0x3fe0000000000000), + (0xbc75555554d7c48c, 0x3fc5555555555556), + (0xbc555a40ffb472d9, 0x3fa5555555555556), + (0x3c24866314c38093, 0x3f8111111111110e), + (0x3be34665978dddb8, 0x3f56c16c16efac90), + (0x3baeab43b813ef24, 0x3f2a01a1e12d253c), + ]; + let z2 = z * z; + let z4 = z2 * z2; + + let b0 = DoubleDouble::quick_mul_add( + z, + DoubleDouble::from_bit_pair(Q[1]), + DoubleDouble::from_bit_pair(Q[0]), + ); + let b1 = DoubleDouble::quick_mul_add( + z, + DoubleDouble::from_bit_pair(Q[3]), + DoubleDouble::from_bit_pair(Q[2]), + ); + let b2 = DoubleDouble::quick_mul_add( + z, + DoubleDouble::from_bit_pair(Q[5]), + DoubleDouble::from_bit_pair(Q[4]), + ); + + let c0 = DoubleDouble::quick_mul_add(z2, b1, b0); + let c1 = DoubleDouble::quick_mul_add(z2, DoubleDouble::from_bit_pair(Q[6]), b2); + + let p = DoubleDouble::quick_mul_add(z4, c1, c0); + DoubleDouble::quick_mult(p, z) +} +*/ +#[inline(always)] +pub(crate) fn expm1_poly_fast(z: DoubleDouble) -> DoubleDouble { + // Polynomial generated by Sollya: + // d = [-2^-12.905,2^-12.905]; + // f = expm1(x); + // w = 1; + // pf = fpminimax(f, [|1,2,3,4,5,6,7|], [|1, 1, D...|], d, absolute, floating); + // See ./notes/compound_m1_expm1_fast.sollya + let p = f_polyeval6( + z.hi, + f64::from_bits(0x3fe0000000000000), + f64::from_bits(0x3fc5555555555555), + f64::from_bits(0x3fa55555555553de), + f64::from_bits(0x3f81111144995a9a), + f64::from_bits(0x3f56c241f9a791c5), + f64::from_bits(0xbfad9209c6d8b9e1), + ); + let px = DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_mult(z.hi, p), z.hi); + // expm1(hi + lo) = expm1(hi) + expm1(lo)(1 + expm1(hi)) = expm1(hi) + expm1(lo)expm1(hi) + expm1(lo) + // expm1(lo) ~ lo + let expm1_hi = DoubleDouble::f64_add(z.hi, px); + let mut lowest_part = DoubleDouble::quick_mult_f64(expm1_hi, z.lo); + lowest_part = DoubleDouble::full_add_f64(lowest_part, z.lo); + DoubleDouble::quick_dd_add(expm1_hi, lowest_part) +} + +/// |z.hi| < 2^-7 +#[inline(always)] +pub(crate) fn expm1_poly_dd_tiny(z: DoubleDouble) -> DoubleDouble { + // Polynomial generated in Sollya + // d = [-2^-7,2^-7]; + // f = expm1(x); + // w = 1; + // pf = fpminimax(f, [|1,2,3,4,5,6,7,8,9|], [|1, 1, 107...|], d, absolute, floating); + // See ./notes/compound_expm1_tiny.sollya + const Q: [(u64, u64); 9] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0x3fe0000000000000), + (0x3c6555564150ff16, 0x3fc5555555555555), + (0x3c4586275c26f8a5, 0x3fa5555555555555), + (0xbc19e6193ac658a6, 0x3f81111111111111), + (0xbbf025e72dc21051, 0x3f56c16c16c1500a), + (0x3bc2d641a7b7b9b8, 0x3f2a01a01a07dc46), + (0xbb42cc8aaeeb3d00, 0x3efa01a29fef3e6f), + (0x3b52b1589125ce82, 0x3ec71db6af553255), + ]; + let z = DoubleDouble::from_exact_add(z.hi, z.lo); + let mut d = DoubleDouble::quick_mul_add( + z, + DoubleDouble::from_bit_pair(Q[8]), + DoubleDouble::from_bit_pair(Q[7]), + ); + d = DoubleDouble::quick_mul_add(z, d, DoubleDouble::from_bit_pair(Q[6])); + d = DoubleDouble::quick_mul_add(z, d, DoubleDouble::from_bit_pair(Q[5])); + d = DoubleDouble::quick_mul_add(z, d, DoubleDouble::from_bit_pair(Q[4])); + d = DoubleDouble::quick_mul_add(z, d, DoubleDouble::from_bit_pair(Q[3])); + d = DoubleDouble::quick_mul_add(z, d, DoubleDouble::from_bit_pair(Q[2])); + d = DoubleDouble::quick_mul_add_f64(z, d, f64::from_bits(0x3fe0000000000000)); + d = DoubleDouble::quick_mul_add_f64(z, d, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::quick_mult(d, z) +} + +#[inline] +pub(crate) fn pow_expm1_1(r: DoubleDouble, s: f64) -> DoubleDouble { + const RHO0: f64 = f64::from_bits(0xc0874910ee4e8a27); + // #define RHO1 -0x1.577453f1799a6p+9 + /* We increase the initial value of RHO1 to avoid spurious underflow in + the result value el. However, it is not possible to obtain a lower + bound on |el| from the input value rh, thus this modified value of RHO1 + is obtained experimentally. */ + const RHO1: f64 = f64::from_bits(0xc08483b8cca421af); + const RHO2: f64 = f64::from_bits(0x40862e42e709a95b); + const RHO3: f64 = f64::from_bits(0x40862e4316ea5df9); + + // use !(rh <= RHO2) instead of rh < RHO2 to catch rh = NaN too + #[allow(clippy::neg_cmp_op_on_partial_ord)] + if !(r.hi <= RHO2) { + return if r.hi > RHO3 { + /* If rh > RHO3, we are sure there is overflow, + For s=1 we return eh = el = DBL_MAX, which yields + res_min = res_max = +Inf for rounding up or to nearest, + and res_min = res_max = DBL_MAX for rounding down or toward zero, + which will yield the correct rounding. + For s=-1 we return eh = el = -DBL_MAX, which similarly gives + res_min = res_max = -Inf or res_min = res_max = -DBL_MAX, + which is the correct rounding. */ + DoubleDouble::new( + f64::from_bits(0x7fefffffffffffff) * s, + f64::from_bits(0x7fefffffffffffff) * s, + ) + } else { + /* If RHO2 < rh <= RHO3, we are in the intermediate region + where there might be overflow or not, thus we set eh = el = NaN, + which will set res_min = res_max = NaN, the comparison + res_min == res_max will fail: we defer to the 2nd phase. */ + DoubleDouble::new(f64::NAN, f64::NAN) + }; + } + + if r.hi < RHO1 { + if r.hi < RHO0 { + /* For s=1, we have eh=el=+0 except for rounding up, + thus res_min=+0 or -0, res_max=+0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=1 and rounding up, we have eh=+0, el=2^-1074, + thus res_min = res_max = 2^-1074, which is the expected result too. + For s=-1, we have eh=el=-0 except for rounding down, + thus res_min=-0 or +0, res_max=-0 in the main code, + the rounding test succeeds, and we return res_max which is the + expected result in the underflow case. + For s=-1 and rounding down, we have eh=-0, el=-2^-1074, + thus res_min = res_max = -2^-1074, which is the expected result too. + */ + return DoubleDouble::full_add_f64( + DoubleDouble::new(f64::from_bits(0x0000000000000001) * (0.5 * s), 0.0 * s), + -1.0, + ); + } else { + /* RHO0 <= rh < RHO1 or s < 0: we return -1 */ + return DoubleDouble::new(0., -1.); + }; + } + + let ax = r.hi.to_bits() & 0x7fffffffffffffffu64; + + const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef); + const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f); + + if ax <= 0x3f80000000000000 { + // |x| < 2^-7 + if ax < 0x3970000000000000 { + // |x| < 2^-104 + return r; + } + let d = expm1_poly_dd_tiny(r); + return d; + } + + const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); + + let k = (r.hi * INVLOG2).cpu_round_ties_even(); + + let z = DoubleDouble::mul_f64_add(DoubleDouble::new(LOG2L, LOG2H), -k, r); + + let bk = unsafe { k.to_int_unchecked::() }; /* Note: k is an integer, this is just a conversion. */ + let mk = (bk >> 12) + 0x3ff; + let i2 = (bk >> 6) & 0x3f; + let i1 = bk & 0x3f; + + let t0 = DoubleDouble::from_bit_pair(EXPM1_T0[i2 as usize]); + let t1 = DoubleDouble::from_bit_pair(EXPM1_T1[i1 as usize]); + let tbh = DoubleDouble::quick_mult(t1, t0); + let mut de = tbh; + // exp(k)=2^k*exp(r) + (2^k - 1) + let q = expm1_poly_fast(z); + de = DoubleDouble::quick_mult(de, q); + de = DoubleDouble::add(tbh, de); + + let ie = mk - 0x3ff; + + let off: f64 = f64::from_bits((2048i64 + 1023i64).wrapping_sub(ie).wrapping_shl(52) as u64); + + let e: f64; + if ie < 53 { + let fhz = DoubleDouble::from_exact_add(off, de.hi); + de.hi = fhz.hi; + e = fhz.lo; + } else if ie < 104 { + let fhz = DoubleDouble::from_exact_add(de.hi, off); + de.hi = fhz.hi; + e = fhz.lo; + } else { + e = 0.; + } + de.lo += e; + de.hi = ldexp(de.to_f64(), ie as i32); + de.lo = 0.; + de +} + +fn exp_dyadic_poly(x: DyadicFloat128) -> DyadicFloat128 { + const Q_2: [DyadicFloat128; 8] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffd0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0088_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8000_0000_0000_0000_0000_000c_06f3_cd29_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaaaa_aaaa_aaaa_aaaa_aaaa_aa6a_1e07_76ae_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xaaaa_aaaa_aaaa_aaa3_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x8888_8888_8888_8897_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -137, + mantissa: 0xb60b_60b9_3214_6a54_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -140, + mantissa: 0xd00d_00cd_9841_6862_0000_0000_0000_0000_u128, + }, + ]; + let mut p = Q_2[7]; + for i in (0..7).rev() { + p = x * p + Q_2[i]; + } + p +} + +/* put in r an approximation of exp(x), for |x| < 744.45, +with relative error < 2^-121.70 */ +#[inline] +pub(crate) fn exp_dyadic(x: DyadicFloat128) -> DyadicFloat128 { + let ex = x.exponent + 127; + if ex >= 10 + // underflow or overflow + { + return DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: if x.sign == DyadicSign::Neg { + -1076 + } else { + 1025 + }, + mantissa: x.mantissa, + }; + } + + const LOG2_INV: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -115, + mantissa: 0xb8aa_3b29_5c17_f0bc_0000_0000_0000_0000_u128, + }; + + const LOG2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb172_17f7_d1cf_79ab_c9e3_b398_03f2_f6af_u128, + }; + + let mut bk = x * LOG2_INV; + let k = bk.trunc_to_i64(); /* k = trunc(K) [rounded towards zero, exact] */ + /* The rounding error of mul_dint_int64() is bounded by 6 ulps, thus since + |K| <= 4399162*log(2) < 3049267, the error on K is bounded by 2^-103.41. + This error is divided by 2^12 below, thus yields < 2^-115.41. */ + bk = LOG2.mul_int64(k); + bk.exponent -= 12; + bk.sign = bk.sign.negate(); + let y = x + bk; + + let bm = k >> 12; + let i2 = (k >> 6) & 0x3f; + let i1 = k & 0x3f; + let mut r = exp_dyadic_poly(y); + r = EXP_T1_2_DYADIC[i2 as usize] * r; + r = EXP_T2_2_DYADIC[i1 as usize] * r; + r.exponent += bm as i16; /* exact */ + r +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::f_expm1; + #[test] + fn test_log() { + let k = DyadicFloat128::new_from_f64(2.5); + assert_eq!(exp_dyadic(k).fast_as_f64(), 12.182493960703473); + } + + #[test] + fn test_exp() { + let k = pow_expm1_1(DoubleDouble::new(0., 2.543543543543), 1.); + println!("{}", k.to_f64()); + println!("{}", f_expm1(2.543543543543)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/pow_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/pow_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1118 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + +pub(crate) static POW_INVERSE: [u64; 182] = [ + 0x3ff6900000000000, + 0x3ff6700000000000, + 0x3ff6500000000000, + 0x3ff6300000000000, + 0x3ff6100000000000, + 0x3ff5f00000000000, + 0x3ff5e00000000000, + 0x3ff5c00000000000, + 0x3ff5a00000000000, + 0x3ff5800000000000, + 0x3ff5600000000000, + 0x3ff5400000000000, + 0x3ff5300000000000, + 0x3ff5100000000000, + 0x3ff4f00000000000, + 0x3ff4e00000000000, + 0x3ff4c00000000000, + 0x3ff4a00000000000, + 0x3ff4800000000000, + 0x3ff4700000000000, + 0x3ff4500000000000, + 0x3ff4400000000000, + 0x3ff4200000000000, + 0x3ff4000000000000, + 0x3ff3f00000000000, + 0x3ff3d00000000000, + 0x3ff3c00000000000, + 0x3ff3a00000000000, + 0x3ff3900000000000, + 0x3ff3700000000000, + 0x3ff3600000000000, + 0x3ff3400000000000, + 0x3ff3300000000000, + 0x3ff3200000000000, + 0x3ff3000000000000, + 0x3ff2f00000000000, + 0x3ff2d00000000000, + 0x3ff2c00000000000, + 0x3ff2b00000000000, + 0x3ff2900000000000, + 0x3ff2800000000000, + 0x3ff2700000000000, + 0x3ff2500000000000, + 0x3ff2400000000000, + 0x3ff2300000000000, + 0x3ff2100000000000, + 0x3ff2000000000000, + 0x3ff1f00000000000, + 0x3ff1e00000000000, + 0x3ff1c00000000000, + 0x3ff1b00000000000, + 0x3ff1a00000000000, + 0x3ff1900000000000, + 0x3ff1700000000000, + 0x3ff1600000000000, + 0x3ff1500000000000, + 0x3ff1400000000000, + 0x3ff1300000000000, + 0x3ff1200000000000, + 0x3ff1000000000000, + 0x3ff0f00000000000, + 0x3ff0e00000000000, + 0x3ff0d00000000000, + 0x3ff0c00000000000, + 0x3ff0b00000000000, + 0x3ff0a00000000000, + 0x3ff0900000000000, + 0x3ff0800000000000, + 0x3ff0700000000000, + 0x3ff0600000000000, + 0x3ff0500000000000, + 0x3ff0400000000000, + 0x3ff0300000000000, + 0x3ff0200000000000, + 0x3ff0000000000000, + 0x3ff0000000000000, + 0x3fefd00000000000, + 0x3fefb00000000000, + 0x3fef900000000000, + 0x3fef700000000000, + 0x3fef500000000000, + 0x3fef300000000000, + 0x3fef100000000000, + 0x3fef000000000000, + 0x3feee00000000000, + 0x3feec00000000000, + 0x3feea00000000000, + 0x3fee800000000000, + 0x3fee600000000000, + 0x3fee500000000000, + 0x3fee300000000000, + 0x3fee100000000000, + 0x3fedf00000000000, + 0x3fedd00000000000, + 0x3fedc00000000000, + 0x3feda00000000000, + 0x3fed800000000000, + 0x3fed700000000000, + 0x3fed500000000000, + 0x3fed300000000000, + 0x3fed200000000000, + 0x3fed000000000000, + 0x3fece00000000000, + 0x3fecd00000000000, + 0x3fecb00000000000, + 0x3fec900000000000, + 0x3fec800000000000, + 0x3fec600000000000, + 0x3fec500000000000, + 0x3fec300000000000, + 0x3fec200000000000, + 0x3fec000000000000, + 0x3febf00000000000, + 0x3febd00000000000, + 0x3febc00000000000, + 0x3feba00000000000, + 0x3feb900000000000, + 0x3feb700000000000, + 0x3feb600000000000, + 0x3feb400000000000, + 0x3feb300000000000, + 0x3feb100000000000, + 0x3feb000000000000, + 0x3feae00000000000, + 0x3fead00000000000, + 0x3feac00000000000, + 0x3feaa00000000000, + 0x3fea900000000000, + 0x3fea700000000000, + 0x3fea600000000000, + 0x3fea500000000000, + 0x3fea300000000000, + 0x3fea200000000000, + 0x3fea100000000000, + 0x3fe9f00000000000, + 0x3fe9e00000000000, + 0x3fe9d00000000000, + 0x3fe9c00000000000, + 0x3fe9a00000000000, + 0x3fe9900000000000, + 0x3fe9800000000000, + 0x3fe9600000000000, + 0x3fe9500000000000, + 0x3fe9400000000000, + 0x3fe9300000000000, + 0x3fe9100000000000, + 0x3fe9000000000000, + 0x3fe8f00000000000, + 0x3fe8e00000000000, + 0x3fe8d00000000000, + 0x3fe8b00000000000, + 0x3fe8a00000000000, + 0x3fe8900000000000, + 0x3fe8800000000000, + 0x3fe8700000000000, + 0x3fe8600000000000, + 0x3fe8400000000000, + 0x3fe8300000000000, + 0x3fe8200000000000, + 0x3fe8100000000000, + 0x3fe8000000000000, + 0x3fe7f00000000000, + 0x3fe7e00000000000, + 0x3fe7c00000000000, + 0x3fe7b00000000000, + 0x3fe7a00000000000, + 0x3fe7900000000000, + 0x3fe7800000000000, + 0x3fe7700000000000, + 0x3fe7600000000000, + 0x3fe7500000000000, + 0x3fe7400000000000, + 0x3fe7300000000000, + 0x3fe7200000000000, + 0x3fe7100000000000, + 0x3fe7000000000000, + 0x3fe6f00000000000, + 0x3fe6e00000000000, + 0x3fe6d00000000000, + 0x3fe6c00000000000, + 0x3fe6b00000000000, + 0x3fe6a00000000000, +]; + +pub(crate) static POW_LOG_INV: [(u64, u64); 182] = [ + (0xbd2e9e439f105039, 0xbfd5ff3070a79000), + (0x3cde63af2df7ba69, 0xbfd5a42ab0f4d000), + (0xbd23167e63081cf7, 0xbfd548a2c3add000), + (0xbd234d7aaf04d104, 0xbfd4ec9732600000), + (0x3d38bccffe1a0f8c, 0xbfd4900680401000), + (0x3d3fb129931715ad, 0xbfd432ef2a04f000), + (0xbd3f8ef43049f7d3, 0xbfd404308686a000), + (0xbd37a71cbcd735d0, 0xbfd3a64c55694000), + (0x3d25594dd4c58092, 0xbfd347dd9a988000), + (0x3d267b1e99b72bd8, 0xbfd2e8e2bae12000), + (0xbd3a8d7ad24c13f0, 0xbfd2895a13de8000), + (0x3d3a6976f5eb0963, 0xbfd22941fbcf8000), + (0xbd27946c040cbe77, 0xbfd1f8ff9e48a000), + (0xbd2b7b3a7a361c9a, 0xbfd1980d2dd42000), + (0x3d3d3e8499d67123, 0xbfd136870293b000), + (0x3d34ab9d817d52cd, 0xbfd1058bf9ae5000), + (0xbd0c6bee7ef4030e, 0xbfd0a324e2739000), + (0xbcf036b89ef42d7f, 0xbfd0402594b4d000), + (0x3d0d572aab993c87, 0xbfcfb9186d5e4000), + (0x3d2323e3a09202fe, 0xbfcf550a564b8000), + (0x3d26805b80e8e6ff, 0xbfce8c0252aa6000), + (0x3d3a342c2af0003c, 0xbfce27076e2b0000), + (0x3d21ba91bbca681b, 0xbfcd5c216b4fc000), + (0x3d27794f689f8434, 0xbfcc8ff7c79aa000), + (0x3d2cfd73dee38a40, 0xbfcc2968558c2000), + (0x3d34b722ec011f31, 0xbfcb5b519e8fc000), + (0x3cba4e633fcd9066, 0xbfcaf3c94e80c000), + (0x3d3539cd91dc9f0b, 0xbfca23bc1fe2c000), + (0x3d21f2a8a1ce0ffc, 0xbfc9bb362e7e0000), + (0xbd3a8154b13d72d5, 0xbfc8e928de886000), + (0xbd322120401202fc, 0xbfc87fa06520c000), + (0x3d2bdb9072534a58, 0xbfc7ab890210e000), + (0x3d30b66c99018aa1, 0xbfc740f8f5404000), + (0x3d3bc6e557134767, 0xbfc6d60fe719e000), + (0x3d38586f183bebf2, 0xbfc5ff3070a7a000), + (0xbcf0ba68b7555d4a, 0xbfc59338d9982000), + (0x3d34354bb3f219e5, 0xbfc4ba36f39a6000), + (0x3d170cc16135783c, 0xbfc44d2b6ccb8000), + (0xbd28a72a62b8c13f, 0xbfc3dfc2b0ecc000), + (0x3cd680b5ce3ecb05, 0xbfc303d718e48000), + (0x3d35b967f4471dfc, 0xbfc29552f8200000), + (0x3d24d20ab840e7f6, 0xbfc2266f190a6000), + (0xbd1563451027c750, 0xbfc1478584674000), + (0xbd3cb2cd2ee2f482, 0xbfc0d77e7cd08000), + (0x3d2a47579cdc0a3d, 0xbfc0671512ca6000), + (0x3d3d599e83368e91, 0xbfbf0a30c0118000), + (0x3d2a342c2af0003c, 0xbfbe27076e2b0000), + (0x3d29454379135713, 0xbfbd4313d66cc000), + (0xbd1d0c57585fbe06, 0xbfbc5e548f5bc000), + (0xbd3563650bd22a9c, 0xbfba926d3a4ac000), + (0x3d28a64826787061, 0xbfb9ab4246204000), + (0xbd3b20f5acb42a66, 0xbfb8c345d6318000), + (0xbd32cc844480c89b, 0xbfb7da766d7b0000), + (0xbd30c3b1dee9c4f8, 0xbfb60658a9374000), + (0xbd383f69278e686a, 0xbfb51b073f060000), + (0xbd1bc0eeea7c9acd, 0xbfb42edcbea64000), + (0xbd31d09299837610, 0xbfb341d7961bc000), + (0xbd3416f8fb69a701, 0xbfb253f62f0a0000), + (0x3d147c5e768fa309, 0xbfb16536eea38000), + (0x3d2d599e83368e91, 0xbfaf0a30c0118000), + (0xbd16a423c78a64b0, 0xbfad276b8adb0000), + (0x3d1c827ae5d6704c, 0xbfab42dd71198000), + (0x3d2c148297c5feb8, 0xbfa95c830ec90000), + (0x3d3181dce586af09, 0xbfa77458f6330000), + (0x3d2b2b739570ad39, 0xbfa58a5bafc90000), + (0xbd3eafd480ad9015, 0xbfa39e87b9fe8000), + (0x3d33401e9ae889bb, 0xbfa1b0d989240000), + (0xbd2980267c7e09e4, 0xbf9f829b0e780000), + (0x3d3b9a010ae6922a, 0xbf9b9fc027b00000), + (0x3d33b955b602ace4, 0xbf97b91b07d60000), + (0x3d36a2c432d6a40b, 0xbf93cea443470000), + (0xbcdf1e7cf6d3a69c, 0xbf8fc0a8b0fc0000), + (0x3d3eb1245b5da1f5, 0xbf87dc475f820000), + (0xbd19e23f0dda40e4, 0xbf7fe02a6b100000), + (0x0000000000000000, 0x0000000000000000), + (0x0000000000000000, 0x0000000000000000), + (0x3d1ad50382973f27, 0x3f78121214580000), + (0x3d1977c755d01368, 0x3f841929f9680000), + (0xbd341f33fcefb9fe, 0x3f8c317384c80000), + (0x3d2713e3284991fe, 0x3f9228fb1fea0000), + (0x3d07abf389596542, 0x3f963d6178690000), + (0xbd2de0709f2d03c9, 0x3f9a55f548c60000), + (0xbd28d75149774d47, 0x3f9e72bf28140000), + (0xbd3dddc7f461c516, 0x3fa0415d89e78000), + (0x3d283e9ae021b67b, 0x3fa252f32f8d0000), + (0xbd2c167375bdfd28, 0x3fa466aed42e0000), + (0x3d3dac20827cca0c, 0x3fa67c94f2d48000), + (0x3d39a19a8be97661, 0x3fa894aa149f8000), + (0x3d20fc1a353bb42e, 0x3faaaef2d0fb0000), + (0xbd17bf868c317c2a, 0x3fabbcebfc690000), + (0xbd21b1ac64d9e42f, 0x3fadda8adc680000), + (0x3d23008c98381a8f, 0x3faffa6911ab8000), + (0xbd37cf69284a3465, 0x3fb10e45b3cb0000), + (0x3d349d8cfc10c7bf, 0x3fb2207b5c784000), + (0x3d37a48ba8b1cb41, 0x3fb2aa04a4470000), + (0xbd319bd0ad125895, 0x3fb3bdf5a7d20000), + (0xbcf53a2582f4e1ef, 0x3fb4d3115d208000), + (0x3d0c1d740c53c72e, 0x3fb55e10050e0000), + (0x3d3a79994c9d3302, 0x3fb674f089364000), + (0x3d069b5794b69fb7, 0x3fb78d02263d8000), + (0xbd3c0fe460d20041, 0x3fb8197e2f410000), + (0x3d23115c3abd47da, 0x3fb9335e5d594000), + (0xbd0e42b6b94407c8, 0x3fba4e7640b1c000), + (0xbd3573b209c31904, 0x3fbadc77ee5b0000), + (0x3d24218c8d824283, 0x3fbbf968769fc000), + (0x3d336433b5efbeed, 0x3fbd179788218000), + (0x3d1a89401fa71733, 0x3fbda72763844000), + (0x3d311fcba80cdd10, 0x3fbec739830a0000), + (0x3d176a6c9ea8b04e, 0x3fbf57bc7d900000), + (0x3d381a9cf169fc5c, 0x3fc03cdc0a51e000), + (0xbd27e5dd7009902c, 0x3fc08598b59e4000), + (0x3d21ef78ce2d07f2, 0x3fc1178e8227e000), + (0x3d2ec2d2a9009e3d, 0x3fc160c8024b2000), + (0xbd15f74e9b083633, 0x3fc1f3b925f26000), + (0x3d100d238fd3df5c, 0x3fc23d712a49c000), + (0x3d039d6ccb81b4a1, 0x3fc2d1610c868000), + (0x3d3f098ee3a50810, 0x3fc31b994d3a4000), + (0xbd3aade8f29320fb, 0x3fc3b08b67580000), + (0x3d319713c0cae559, 0x3fc3fb45a5992000), + (0xbd353e43558124c4, 0x3fc4913d8333c000), + (0x3d0c79b60ae1ff0f, 0x3fc4dc7b897bc000), + (0x3d39baa7a6b887f6, 0x3fc5737cc9018000), + (0xbd127023eb68981c, 0x3fc5bf406b544000), + (0xbd398c1d34f0f462, 0x3fc6574ebe8c2000), + (0xbd38f934e66a15a6, 0x3fc6a399dabbe000), + (0x3d3577390d31ef0f, 0x3fc6f0128b756000), + (0x3d38e67be3dbaf3f, 0x3fc7898d85444000), + (0xbd24c06b17c301d7, 0x3fc7d6903caf6000), + (0x3d3328eb42f9af75, 0x3fc871213750e000), + (0xbd073d54aae92cd1, 0x3fc8beafeb390000), + (0xbd1935f57718d7ca, 0x3fc90c6db9fcc000), + (0x3d3470fa3efec390, 0x3fc9a8778deba000), + (0xbd3337d94bcd3f43, 0x3fc9f6c40708a000), + (0x3d360a77c81f7171, 0x3fca454082e6a000), + (0x3d37a8d5ae54f550, 0x3fcae2ca6f672000), + (0x3d3c794e562a63cb, 0x3fcb31d8575bc000), + (0x3d1e90683b9cd768, 0x3fcb811730b82000), + (0xbd2d4bc4595412b6, 0x3fcbd087383be000), + (0x3d3ee138d3a69d43, 0x3fcc6ffbc6f00000), + (0xbd1d6d585d57aff9, 0x3fccc000c9db4000), + (0xbd084a7e75b6f6e4, 0x3fcd1037f2656000), + (0x3d32806a847527e6, 0x3fcdb13db0d48000), + (0xbd252b00adb91424, 0x3fce020cc6236000), + (0xbd3fdbdbb13f7c18, 0x3fce530effe72000), + (0x3d35e91663732a36, 0x3fcea4449f04a000), + (0xbd3bae49f1df7b5e, 0x3fcf474b134e0000), + (0xbd390d04cd7cc834, 0x3fcf991c6cb3c000), + (0x3d2f3418de00938b, 0x3fcfeb2233ea0000), + (0x3d3a43dcfade85ae, 0x3fd01eae5626c000), + (0x3d2dbdf10d397f3c, 0x3fd047e60cde8000), + (0x3d3b50a1e1734342, 0x3fd09aa572e6c000), + (0x3d27188b163ceae9, 0x3fd0c42d67616000), + (0x3d0019b52d8435f5, 0x3fd0edd060b78000), + (0x3d31ef78ce2d07f2, 0x3fd1178e8227e000), + (0x3d3e0c07824daaf5, 0x3fd14167ef367000), + (0xbd323299042d74bf, 0x3fd16b5ccbad0000), + (0xbd31ac89575c2125, 0x3fd1bf99635a7000), + (0xbd382eaed3c8b65e, 0x3fd1e9e16788a000), + (0xbd3caf0428b728a3, 0x3fd214456d0ec000), + (0xbd36dbe448a2e522, 0x3fd23ec5991ec000), + (0xbd31b61f10522625, 0x3fd269621134e000), + (0xbd3210c2b730e28b, 0x3fd2941afb187000), + (0x3d2a9cfa4a5004f4, 0x3fd2bef07cdc9000), + (0xbd28e27ad3213cb8, 0x3fd314f1e1d36000), + (0xbd317c73556e291d, 0x3fd3401e12aed000), + (0x3d116ecdb0f177c8, 0x3fd36b6776be1000), + (0xbd05839c5663663d, 0x3fd396ce359bc000), + (0x3d183b54b606bd5c, 0x3fd3c25277333000), + (0xbd3f067c297f2c3f, 0x3fd3edf463c17000), + (0xbd3ce379226de3ec, 0x3fd419b423d5f000), + (0xbd06e95892923d88, 0x3fd44591e053a000), + (0x3d306c18fb4c14c5, 0x3fd4718dc271c000), + (0x3d307b334daf4b9a, 0x3fd49da7f3bcc000), + (0xbd2e20891b0ad8a4, 0x3fd4c9e09e173000), + (0xbd3fc158cb3124b9, 0x3fd4f637ebbaa000), + (0x3d2ebe708164c759, 0x3fd522ae0738a000), + (0x3d1a8954c0910952, 0x3fd54f431b7be000), + (0x3d1fadedee5d40ef, 0x3fd57bf753c8d000), + (0xbcf7c79b0af7ecf8, 0x3fd5a8cadbbee000), + (0xbd0a0b2a08a465dc, 0x3fd5d5bddf596000), + (0x3d1ebe9176df3f65, 0x3fd602d08af09000), + (0xbd2db623e731ae00, 0x3fd630030b3ab000), +]; + +pub(crate) static EXP2_MID1: [(u64, u64); 64] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc719083535b085d, 0x3ff02c9a3e778061), + (0x3c8d73e2a475b465, 0x3ff059b0d3158574), + (0x3c6186be4bb284ff, 0x3ff0874518759bc8), + (0x3c98a62e4adc610b, 0x3ff0b5586cf9890f), + (0x3c403a1727c57b53, 0x3ff0e3ec32d3d1a2), + (0xbc96c51039449b3a, 0x3ff11301d0125b51), + (0xbc932fbf9af1369e, 0x3ff1429aaea92de0), + (0xbc819041b9d78a76, 0x3ff172b83c7d517b), + (0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75), + (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa), + (0x3c8dc775814a8495, 0x3ff2063b88628cd6), + (0x3c99b07eb6c70573, 0x3ff2387a6e756238), + (0x3c82bd339940e9d9, 0x3ff26b4565e27cdd), + (0x3c8612e8afad1255, 0x3ff29e9df51fdee1), + (0x3c90024754db41d5, 0x3ff2d285a6e4030b), + (0x3c86f46ad23182e4, 0x3ff306fe0a31b715), + (0x3c932721843659a6, 0x3ff33c08b26416ff), + (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb), + (0xbc75e436d661f5e3, 0x3ff3a7db34e59ff7), + (0x3c8ada0911f09ebc, 0x3ff3dea64c123422), + (0xbc5ef3691c309278, 0x3ff4160a21f72e2a), + (0x3c489b7a04ef80d0, 0x3ff44e086061892d), + (0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0), + (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27), + (0xbc94b309d25957e3, 0x3ff4f9b2769d2ca7), + (0xbc807abe1db13cad, 0x3ff5342b569d4f82), + (0x3c99bb2c011d93ad, 0x3ff56f4736b527da), + (0x3c96324c054647ad, 0x3ff5ab07dd485429), + (0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148), + (0xbc9383c17e40b497, 0x3ff6247eb03a5585), + (0xbc9bb60987591c34, 0x3ff6623882552225), + (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd), + (0xbc6bbe3a683c88ab, 0x3ff6dfb23c651a2f), + (0xbc816e4786887a99, 0x3ff71f75e8ec5f74), + (0xbc90245957316dd3, 0x3ff75feb564267c9), + (0xbc841577ee04992f, 0x3ff7a11473eb0187), + (0x3c705d02ba15797e, 0x3ff7e2f336cf4e62), + (0xbc9d4c1dd41532d8, 0x3ff82589994cce13), + (0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed), + (0x3c96e9f156864b27, 0x3ff8ace5422aa0db), + (0x3c85cc13a2e3976c, 0x3ff8f1ae99157736), + (0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5), + (0xbc9d185b7c1b85d1, 0x3ff97d829fde4e50), + (0x3c7c7c46b071f2be, 0x3ff9c49182a3f090), + (0xbc9359495d1cd533, 0x3ffa0c667b5de565), + (0xbc9d2f6edb8d41e1, 0x3ffa5503b23e255d), + (0x3c90fac90ef7fd31, 0x3ffa9e6b5579fdbf), + (0x3c97a1cd345dcc81, 0x3ffae89f995ad3ad), + (0xbc62805e3084d708, 0x3ffb33a2b84f15fb), + (0xbc75584f7e54ac3b, 0x3ffb7f76f2fb5e47), + (0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2), + (0x3c811065895048dd, 0x3ffc199bdd85529c), + (0x3c92884dff483cad, 0x3ffc67f12e57d14b), + (0x3c7503cbd1e949db, 0x3ffcb720dcef9069), + (0xbc9cbc3743797a9c, 0x3ffd072d4a07897c), + (0x3c82ed02d75b3707, 0x3ffd5818dcfba487), + (0x3c9c2300696db532, 0x3ffda9e603db3285), + (0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f), + (0x3c839e8980a9cc8f, 0x3ffe502ee78b3ff6), + (0xbc9e9c23179c2893, 0x3ffea4afa2a490da), + (0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27), + (0x3c99d3e12dd8a18b, 0x3fff50765b6e4540), + (0x3c874853f3a5931e, 0x3fffa7c1819e90d8), +]; + +/* for 0 <= i < 64, T1_2[i] is a 128-bit nearest approximation of 2^(i/64), +with error bounded by 2^-128 (both absolutely and relatively). */ +#[rustfmt::skip] +pub(crate) static EXP_T1_2_DYADIC: [DyadicFloat128; 64] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8164_d1f3_bc03_0773_7be5_6527_bd14_def5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x82cd_8698_ac2b_a1d7_3e2a_475b_4652_0bff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x843a_28c3_acde_4046_1af9_2eca_13fd_1582_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x85aa_c367_cc48_7b14_c5c9_5b8c_2154_c1b2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x871f_6196_9e8d_1010_3a17_27c5_7b52_a956_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8898_0e80_92da_8527_5df8_d76c_98c6_7563_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8a14_d575_496e_fd9a_080c_a1d9_2c36_80c2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8b95_c1e3_ea8b_d6e6_fbe4_6287_58a5_3c90_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8d1a_df5b_7e5b_a9e5_b4c7_b496_8e41_ad36_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8ea4_398b_45cd_53c0_2dc0_144c_8783_d4c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9031_dc43_1466_b1dc_7758_14a8_494e_87e2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x91c3_d373_ab11_c336_0fd6_d8e0_ae5a_c9d8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x935a_2b2f_13e6_e92b_d339_940e_9d92_4ee7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x94f4_efa8_fef7_0961_2e8a_fad1_2551_de54_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9694_2d37_2018_5a00_48ea_9b68_3a9c_22c5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9837_f051_8db8_a96f_46ad_2318_2e42_f6f6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x99e0_4593_20b7_fa64_e430_86cb_34b5_fcaf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9b8d_39b9_d54e_5538_a2a8_17a2_a3cc_3f1f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9d3e_d9a7_2cff_b750_de49_4cf0_50e9_9b0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x9ef5_3260_91a1_11ad_a091_1f09_ebb9_fdd1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa0b0_510f_b971_4fc2_192d_c79e_db0f_d9a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa270_4303_0c49_6818_9b7a_04ef_80cf_dea8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa435_15ae_09e6_809e_0d1d_b483_1781_e1ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa5fe_d6a9_b151_38ea_1cbd_7f62_1710_701b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa7cd_93b4_e965_3569_9ec5_b4d5_039f_72af_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xa9a1_5ab4_ea7c_0ef8_541e_24ec_3531_fa73_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xab7a_39b5_a93e_d337_6580_23b2_759e_0079_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xad58_3eea_42a1_4ac6_4980_a8c8_f59a_2ec4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xaf3b_78ad_690a_4374_df26_101c_cbb3_5033_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb123_f581_d2ac_258f_87d0_37e9_6d21_5d8e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb311_c412_a911_2489_3ecf_14dc_798a_519c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb504_f333_f9de_6484_597d_89b3_754a_be9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb6fd_91e3_28d1_7791_0716_5f0d_dd54_1a5a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xb8fb_af47_62fb_9ee9_1b87_9778_566b_65a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbaff_5ab2_133e_45fb_74d5_19d2_4593_838c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbd08_a39f_580c_36be_a881_1fb6_6d0f_af7a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xbf17_99b6_7a73_1082_e815_d0ab_cbf0_b851_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc12c_4cca_6670_9456_7c45_7d59_a500_87b5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc346_ccda_2497_6407_20ec_8561_28b8_3a42_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc567_2a11_5506_dadd_3e2a_d0c9_64dd_9f37_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc78d_74c8_abb9_b15c_c13a_2e39_76c0_277e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc9b9_bd86_6e2f_27a2_80e1_f92a_0511_697e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xcbec_14fe_f272_7c5c_f490_7c8f_45eb_f6dd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xce24_8c15_1f84_80e3_e235_838f_95f2_c6ed_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd063_33da_ef2b_2594_d6d4_5c65_59a4_d502_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd2a8_1d91_f12a_e45a_1224_8e57_c3de_4028_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd4f3_5aab_cfed_fa1f_5921_deff_a626_2c5b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd744_fcca_d69d_6af4_39a6_8bb9_902d_3fde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xd99d_15c2_78af_d7b5_fe87_3dec_a3e1_2bac_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xdbfb_b797_daf2_3755_3d84_0d5a_9e29_aa64_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xde60_f482_5e0e_9123_dd07_a2d9_e846_6859_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe0cc_deec_2a94_e111_0658_9504_8dd3_33ca_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe33f_8972_be8a_5a51_09bf_e907_9598_0eed_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe5b9_06e7_7c83_48a8_1e5e_8f4a_4edb_b0ed_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xe839_6a50_3c4b_dc68_7917_90d0_ac70_c7de_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xeac0_c6e7_dd24_392e_d02d_75b3_706e_54fb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xed4f_301e_d994_2b84_600d_2db6_a64b_fb12_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xefe4_b99b_dcda_f5cb_4656_1cf6_948d_b913_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf281_773c_59ff_b139_e898_0a9c_c8f4_7a4b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf525_7d15_2486_cc2c_7b9d_0c7a_ed98_0fc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xf7d0_df73_0ad1_3bb8_fe90_d496_d60f_b6eb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xfa83_b2db_722a_033a_7c25_bb14_315d_7fcd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xfd3e_0c0c_f486_c174_853f_3a59_31e0_ee03_u128, + }, +]; + +/* for 0 <= i < 64, T2_2[i] is a 128-bit nearest approximation of 2^(i/2^12), +with error bounded by 2^-128 (both absolutely and relatively). */ +#[rustfmt::skip] +pub(crate) static EXP_T2_2_DYADIC: [DyadicFloat128; 64] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8005_8baf_7fee_3b5d_1c71_8b38_e549_cb93_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x800b_179c_8202_8fd0_945e_54e2_ae18_f2f0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8010_a3c7_08e7_3282_2b96_d62d_51c1_5a07_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8016_302f_1746_7628_3690_dfe4_4d11_d008_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x801b_bcd4_afca_cb08_e23a_986b_d3e6_26f0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8021_49b7_d51e_befb_7bdb_adbc_888a_eb29_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8026_d6d8_89ec_fd69_b904_bbfb_40d3_a2b7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x802c_6436_d0e0_4f50_ff8c_e94a_6797_b3ce_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8031_f1d2_aca3_9b43_ad9d_b772_901d_96b6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8037_7fac_1fe1_e56a_61cd_0bff_d7cf_c683_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x803d_0dc3_2d46_4f85_4345_6f71_b96a_ffd4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8042_9c17_d77c_18ed_49fc_841a_fba9_c3c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8048_2aaa_212e_9e95_86f7_b54f_6c45_c85e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x804d_b97a_0d09_5b0c_6c9f_1f7d_1efc_fe68_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8053_4887_9db7_e67d_171e_b1ce_ef1d_1f28_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8058_d7d2_d5e5_f6b0_94d5_89f6_08ee_4aa2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x805e_675b_b83f_5f0f_2ed3_8ab8_472b_2144_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8063_f722_4770_10a1_b165_2de1_378a_f1a1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8069_8726_8624_1a12_b4ad_9233_a039_0cad_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x806f_1768_7707_a7af_e54e_c5f9_66eb_1872_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8074_a7e8_1cc7_036b_4d20_4ecf_c11f_4aab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x807a_38a5_7a0e_94dc_9bf3_ef4d_9be2_d1e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x807f_c9a0_918a_e142_7068_ab22_3058_5d13_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8085_5ad9_65e8_8b83_a0cc_0a49_c10e_a66b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x808a_ec4f_f9d4_5430_8409_9bf6_830f_2768_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8090_7e04_4ffb_1984_3aa8_b9cb_bc65_a8ab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8096_0ff6_6b09_d765_f7d8_8c09_28ba_3947_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x809b_a226_4dad_a76a_4a8a_4f44_bb70_3db6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80a1_3493_fa93_c0d4_6699_dc50_dd96_b774_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80a6_c73f_7469_7897_6e04_72ed_4ccf_a2e0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80ac_5a28_bddc_4157_ba2d_c7e0_c72e_51ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80b1_ed4f_d999_ab6c_2533_5719_b6e6_fd20_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80b7_80b4_ca4f_64df_534d_fa74_1784_6aa4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80bd_1457_92ab_3970_fc41_c5c2_d533_6ccc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80c2_a838_355b_1297_34dc_28ba_ed8f_3fde_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80c8_3c56_b50c_f77f_b880_575e_a035_48c1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80cd_d0b3_146f_0d11_32c1_f987_0442_8c71_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80d3_654d_562f_95ec_890e_222a_5eb9_5372_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80d8_fa25_7cfc_f26e_2462_8efd_9ca9_d59b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80de_8f3b_8b85_a0af_3b13_310f_5ad5_7fb1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80e4_248f_8478_3c87_1a9d_fefa_eb61_6564_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80e9_ba21_6a83_7f8c_718d_1151_d109_bf98_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80ef_4ff1_4056_4116_9967_09da_2e25_f04c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80f4_e5ff_089f_763e_e0ad_c640_acaa_6b0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80fa_7c4a_c60e_31e1_d4eb_5edc_6b34_1283_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8100_12d4_7b51_a4a0_8ccd_7223_8207_19e3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8105_a99c_2b19_1ce1_f24e_bd6e_b9ca_4292_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x810b_40a1_d814_06d4_0cef_03ab_14a6_6550_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8110_d7e5_84f1_ec6d_4bf9_4297_d151_9822_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8116_6f67_3462_756d_d0d8_372f_966c_f15e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x811c_0726_e915_6760_b979_31db_7b7b_e2ec_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8121_9f24_a5ba_a59d_6abd_3b0e_ab9c_7048_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8127_3760_6d02_3148_daf8_88e9_6508_151a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x812c_cfda_419c_2956_dc80_4682_1f46_122e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8132_6892_2638_ca8b_6846_ad73_a8d9_027f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8138_0188_1d88_6f7b_e885_724f_1413_1287_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x813d_9abc_2a3b_9090_8376_8490_519d_f895_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8143_342e_4f02_c405_661b_22b4_5e25_de18_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8148_cdde_8e8e_bdec_0f11_430f_ef78_c6ee_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x814e_67cc_eb90_502c_9977_5205_944e_adc4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8154_01f9_68b8_6a87_07de_463a_40d1_8261_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8159_9c64_08b8_1a94_8f4a_0b67_48df_7960_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x815f_370c_ce40_8bc8_e240_4468_cfe5_ab9f_u128, + }, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/powf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/powf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,895 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(clippy::too_many_arguments)] +use crate::bits::biased_exponent_f64; +use crate::common::*; +use crate::double_double::DoubleDouble; +use crate::exponents::expf; +use crate::logf; +use crate::logs::LOG2_R; +use crate::pow_tables::EXP2_MID1; +use crate::powf_tables::{LOG2_R_TD, LOG2_R2_DD, POWF_R2}; +use crate::rounding::CpuRound; + +/// Power function for given value for const context. +/// This is simplified version just to make a good approximation on const context. +pub const fn powf(d: f32, n: f32) -> f32 { + let value = d.abs(); + let c = expf(n * logf(value)); + if n == 1. { + return d; + } + if d < 0.0 { + let y = n as i32; + if y % 2 == 0 { c } else { -c } + } else { + c + } +} + +pub(crate) trait PowfBackend { + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32; + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64; + fn integerf(&self, x: f32) -> bool; + fn odd_integerf(&self, x: f32) -> bool; + fn round(&self, x: f64) -> f64; + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble; + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble; + fn dd_polyeval6( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + ) -> DoubleDouble; + fn dd_polyeval10( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + a6: DoubleDouble, + a7: DoubleDouble, + a8: DoubleDouble, + a9: DoubleDouble, + ) -> DoubleDouble; + const HAS_FMA: bool; + const ERR: u64; +} + +pub(crate) struct GenPowfBackend {} + +impl PowfBackend for GenPowfBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f_fmlaf(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::f_polyeval3; + f_polyeval3(x, a0, a1, a2) + } + + #[inline(always)] + fn integerf(&self, x: f32) -> bool { + is_integerf(x) + } + + #[inline(always)] + fn odd_integerf(&self, x: f32) -> bool { + is_odd_integerf(x) + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.cpu_round() + } + + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult(x, y) + } + + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64(x, y) + } + + #[inline(always)] + fn dd_polyeval6( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + ) -> DoubleDouble { + use crate::polyeval::dd_quick_polyeval6; + dd_quick_polyeval6(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn dd_polyeval10( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + a6: DoubleDouble, + a7: DoubleDouble, + a8: DoubleDouble, + a9: DoubleDouble, + ) -> DoubleDouble { + use crate::polyeval::dd_quick_polyeval10; + dd_quick_polyeval10(x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) + } + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + const HAS_FMA: bool = true; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + const HAS_FMA: bool = false; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + const ERR: u64 = 64; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + const ERR: u64 = 128; +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub(crate) struct FmaPowfBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl PowfBackend for FmaPowfBackend { + #[inline(always)] + fn fmaf(&self, x: f32, y: f32, z: f32) -> f32 { + f32::mul_add(x, y, z) + } + + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::d_polyeval3; + d_polyeval3(x, a0, a1, a2) + } + + #[inline(always)] + fn integerf(&self, x: f32) -> bool { + x.round_ties_even() == x + } + + #[inline(always)] + fn odd_integerf(&self, x: f32) -> bool { + use crate::common::is_odd_integerf_fast; + is_odd_integerf_fast(x) + } + + #[inline(always)] + fn round(&self, x: f64) -> f64 { + x.round() + } + + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_fma(x, y) + } + + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64_fma(x, y) + } + + #[inline(always)] + fn dd_polyeval6( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + ) -> DoubleDouble { + use crate::polyeval::dd_quick_polyeval6_fma; + dd_quick_polyeval6_fma(x, a0, a1, a2, a3, a4, a5) + } + + #[inline(always)] + fn dd_polyeval10( + &self, + x: DoubleDouble, + a0: DoubleDouble, + a1: DoubleDouble, + a2: DoubleDouble, + a3: DoubleDouble, + a4: DoubleDouble, + a5: DoubleDouble, + a6: DoubleDouble, + a7: DoubleDouble, + a8: DoubleDouble, + a9: DoubleDouble, + ) -> DoubleDouble { + use crate::polyeval::dd_quick_polyeval10_fma; + dd_quick_polyeval10_fma(x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) + } + + const HAS_FMA: bool = true; + + const ERR: u64 = 64; +} + +#[inline] +const fn larger_exponent(a: f64, b: f64) -> bool { + biased_exponent_f64(a) >= biased_exponent_f64(b) +} + +// Calculate 2^(y * log2(x)) in double-double precision. +// At this point we can reuse the following values: +// idx_x: index for extra precision of log2 for the middle part of log2(x). +// dx: the reduced argument for log2(x) +// y6: 2^6 * y. +// lo6_hi: the high part of 2^6 * (y - (hi + mid)) +// exp2_hi_mid: high part of 2^(hi + mid) +#[cold] +#[inline(always)] +fn powf_dd( + idx_x: i32, + dx: f64, + y6: f64, + lo6_hi: f64, + exp2_hi_mid: DoubleDouble, + backend: &B, +) -> f64 { + // Perform a second range reduction step: + // idx2 = round(2^14 * (dx + 2^-8)) = round ( dx * 2^14 + 2^6) + // dx2 = (1 + dx) * r2 - 1 + // Output range: + // -0x1.3ffcp-15 <= dx2 <= 0x1.3e3dp-15 + let idx2 = backend.round(backend.fma( + dx, + f64::from_bits(0x40d0000000000000), + f64::from_bits(0x4050000000000000), + )) as usize; + let dx2 = backend.fma(1.0 + dx, f64::from_bits(POWF_R2[idx2]), -1.0); // Exact + + const COEFFS: [(u64, u64); 6] = [ + (0x3c7777d0ffda25e0, 0x3ff71547652b82fe), + (0xbc6777d101cf0a84, 0xbfe71547652b82fe), + (0x3c7ce04b5140d867, 0x3fdec709dc3a03fd), + (0x3c7137b47e635be5, 0xbfd71547652b82fb), + (0xbc5b5a30b3bdb318, 0x3fd2776c516a92a2), + (0x3c62d2fbd081e657, 0xbfcec70af1929ca6), + ]; + let dx_dd = DoubleDouble::new(0.0, dx2); + let p = backend.dd_polyeval6( + dx_dd, + DoubleDouble::from_bit_pair(COEFFS[0]), + DoubleDouble::from_bit_pair(COEFFS[1]), + DoubleDouble::from_bit_pair(COEFFS[2]), + DoubleDouble::from_bit_pair(COEFFS[3]), + DoubleDouble::from_bit_pair(COEFFS[4]), + DoubleDouble::from_bit_pair(COEFFS[5]), + ); + // log2(1 + dx2) ~ dx2 * P(dx2) + let log2_x_lo = backend.quick_mult_f64(p, dx2); + // Lower parts of (e_x - log2(r1)) of the first range reduction constant + let log2_r_td = LOG2_R_TD[idx_x as usize]; + let log2_x_mid = DoubleDouble::new(f64::from_bits(log2_r_td.0), f64::from_bits(log2_r_td.1)); + // -log2(r2) + lower part of (e_x - log2(r1)) + let log2_x_m = DoubleDouble::add(DoubleDouble::from_bit_pair(LOG2_R2_DD[idx2]), log2_x_mid); + // log2(1 + dx2) - log2(r2) + lower part of (e_x - log2(r1)) + // Since we don't know which one has larger exponent to apply Fast2Sum + // algorithm, we need to check them before calling double-double addition. + let log2_x = if larger_exponent(log2_x_m.hi, log2_x_lo.hi) { + DoubleDouble::add(log2_x_m, log2_x_lo) + } else { + DoubleDouble::add(log2_x_lo, log2_x_m) + }; + let lo6_hi_dd = DoubleDouble::new(0.0, lo6_hi); + // 2^6 * y * (log2(1 + dx2) - log2(r2) + lower part of (e_x - log2(r1))) + let prod = backend.quick_mult_f64(log2_x, y6); + // 2^6 * (y * log2(x) - (hi + mid)) = 2^6 * lo + let lo6 = if larger_exponent(prod.hi, lo6_hi) { + DoubleDouble::add(prod, lo6_hi_dd) + } else { + DoubleDouble::add(lo6_hi_dd, prod) + }; + + const EXP2_COEFFS: [(u64, u64); 10] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c1abc9e3b398024, 0x3f862e42fefa39ef), + (0xbba5e43a5429bddb, 0x3f0ebfbdff82c58f), + (0xbb2d33162491268f, 0x3e8c6b08d704a0c0), + (0x3a94fb32d240a14e, 0x3e03b2ab6fba4e77), + (0x39ee84e916be83e0, 0x3d75d87fe78a6731), + (0xb989a447bfddc5e6, 0x3ce430912f86bfb8), + (0xb8e31a55719de47f, 0x3c4ffcbfc588ded9), + (0xb850ba57164eb36b, 0x3bb62c034beb8339), + (0xb7b8483eabd9642d, 0x3b1b5251ff97bee1), + ]; + + let pp = backend.dd_polyeval10( + lo6, + DoubleDouble::from_bit_pair(EXP2_COEFFS[0]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[1]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[2]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[3]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[4]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[5]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[6]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[7]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[8]), + DoubleDouble::from_bit_pair(EXP2_COEFFS[9]), + ); + let rr = backend.quick_mult(exp2_hi_mid, pp); + + // Make sure the sum is normalized: + let r = DoubleDouble::from_exact_add(rr.hi, rr.lo); + + const FRACTION_MASK: u64 = (1u64 << 52) - 1; + + let mut r_bits = r.hi.to_bits(); + if ((r_bits & 0xfff_ffff) == 0) && (r.lo != 0.0) { + let hi_sign = r.hi.to_bits() >> 63; + let lo_sign = r.lo.to_bits() >> 63; + if hi_sign == lo_sign { + r_bits = r_bits.wrapping_add(1); + } else if (r_bits & FRACTION_MASK) > 0 { + r_bits = r_bits.wrapping_sub(1); + } + } + + f64::from_bits(r_bits) +} + +#[inline(always)] +fn powf_gen(x: f32, y: f32, backend: B) -> f32 { + let mut x_u = x.to_bits(); + let x_abs = x_u & 0x7fff_ffff; + let mut y = y; + let y_u = y.to_bits(); + let y_abs = y_u & 0x7fff_ffff; + let mut x = x; + + if ((y_abs & 0x0007_ffff) == 0) || (y_abs > 0x4f170000) { + // y is signaling NaN + if x.is_nan() || y.is_nan() { + if y.abs() == 0. { + return 1.; + } + if x == 1. { + return 1.; + } + return f32::NAN; + } + + // Exceptional exponents. + if y == 0.0 { + return 1.0; + } + + match y_abs { + 0x7f80_0000 => { + if x_abs > 0x7f80_0000 { + // pow(NaN, +-Inf) = NaN + return x; + } + if x_abs == 0x3f80_0000 { + // pow(+-1, +-Inf) = 1.0f + return 1.0; + } + if x == 0.0 && y_u == 0xff80_0000 { + // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO + return f32::INFINITY; + } + // pow (|x| < 1, -inf) = +inf + // pow (|x| < 1, +inf) = 0.0f + // pow (|x| > 1, -inf) = 0.0f + // pow (|x| > 1, +inf) = +inf + return if (x_abs < 0x3f80_0000) == (y_u == 0xff80_0000) { + f32::INFINITY + } else { + 0. + }; + } + _ => { + match y_u { + 0x3f00_0000 => { + // pow(x, 1/2) = sqrt(x) + if x == 0.0 || x_u == 0xff80_0000 { + // pow(-0, 1/2) = +0 + // pow(-inf, 1/2) = +inf + // Make sure it is correct for FTZ/DAZ. + return x * x; + } + let r = x.sqrt(); + return if r.to_bits() != 0x8000_0000 { r } else { 0.0 }; + } + 0x3f80_0000 => { + return x; + } // y = 1.0f + 0x4000_0000 => return x * x, // y = 2.0f + _ => { + let is_int = backend.integerf(y); + if is_int && (y_u > 0x4000_0000) && (y_u <= 0x41c0_0000) { + // Check for exact cases when 2 < y < 25 and y is an integer. + let mut msb: i32 = if x_abs == 0 { + 32 - 2 + } else { + x_abs.leading_zeros() as i32 + }; + msb = if msb > 8 { msb } else { 8 }; + let mut lsb: i32 = if x_abs == 0 { + 0 + } else { + x_abs.trailing_zeros() as i32 + }; + lsb = if lsb > 23 { 23 } else { lsb }; + let extra_bits: i32 = 32 - 2 - lsb - msb; + let iter = y as i32; + + if extra_bits * iter <= 23 + 2 { + // The result is either exact or exactly half-way. + // But it is exactly representable in double precision. + let x_d = x as f64; + let mut result = x_d; + for _ in 1..iter { + result *= x_d; + } + return result as f32; + } + } + + if y_abs > 0x4f17_0000 { + // if y is NaN + if y_abs > 0x7f80_0000 { + if x_u == 0x3f80_0000 { + // x = 1.0f + // pow(1, NaN) = 1 + return 1.0; + } + // pow(x, NaN) = NaN + return y; + } + // x^y will be overflow / underflow in single precision. Set y to a + // large enough exponent but not too large, so that the computations + // won't be overflow in double precision. + y = f32::from_bits((y_u & 0x8000_0000).wrapping_add(0x4f800000u32)); + } + } + } + } + } + } + + const E_BIAS: u32 = (1u32 << (8 - 1u32)) - 1u32; + let mut ex = -(E_BIAS as i32); + let mut sign: u64 = 0; + + if ((x_u & 0x801f_ffffu32) == 0) || x_u >= 0x7f80_0000u32 || x_u < 0x0080_0000u32 { + if x.is_nan() { + return f32::NAN; + } + + if x_u == 0x3f80_0000 { + return 1.; + } + + let x_is_neg = x.to_bits() > 0x8000_0000; + + if x == 0.0 { + let out_is_neg = x_is_neg && backend.odd_integerf(f32::from_bits(y_u)); + if y_u > 0x8000_0000u32 { + // pow(0, negative number) = inf + return if x_is_neg { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + // pow(0, positive number) = 0 + return if out_is_neg { -0.0 } else { 0.0 }; + } + + if x_abs == 0x7f80_0000u32 { + // x = +-Inf + let out_is_neg = x_is_neg && backend.odd_integerf(f32::from_bits(y_u)); + if y_u >= 0x7fff_ffff { + return if out_is_neg { -0.0 } else { 0.0 }; + } + return if out_is_neg { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + + if x_abs > 0x7f80_0000 { + // x is NaN. + // pow (aNaN, 0) is already taken care above. + return x; + } + + // Normalize denormal inputs. + if x_abs < 0x0080_0000u32 { + ex = ex.wrapping_sub(64); + x *= f32::from_bits(0x5f800000); + } + + // x is finite and negative, and y is a finite integer. + if x.is_sign_negative() { + if backend.integerf(y) { + x = -x; + if backend.odd_integerf(y) { + sign = 0x8000_0000_0000_0000u64; + } + } else { + // pow( negative, non-integer ) = NaN + return f32::NAN; + } + } + } + + // x^y = 2^( y * log2(x) ) + // = 2^( y * ( e_x + log2(m_x) ) ) + // First we compute log2(x) = e_x + log2(m_x) + x_u = x.to_bits(); + + // Extract exponent field of x. + ex = ex.wrapping_add((x_u >> 23) as i32); + let e_x = ex as f64; + // Use the highest 7 fractional bits of m_x as the index for look up tables. + let x_mant = x_u & ((1u32 << 23) - 1); + let idx_x = (x_mant >> (23 - 7)) as i32; + // Add the hidden bit to the mantissa. + // 1 <= m_x < 2 + let m_x = f32::from_bits(x_mant | 0x3f800000); + + // Reduced argument for log2(m_x): + // dx = r * m_x - 1. + // The computation is exact, and -2^-8 <= dx < 2^-7. + // Then m_x = (1 + dx) / r, and + // log2(m_x) = log2( (1 + dx) / r ) + // = log2(1 + dx) - log2(r). + + let dx = if B::HAS_FMA { + use crate::logs::LOG_REDUCTION_F32; + backend.fmaf( + m_x, + f32::from_bits(LOG_REDUCTION_F32.0[idx_x as usize]), + -1.0, + ) as f64 // Exact. + } else { + use crate::logs::LOG_RANGE_REDUCTION; + backend.fma( + m_x as f64, + f64::from_bits(LOG_RANGE_REDUCTION[idx_x as usize]), + -1.0, + ) // Exact + }; + + // Degree-5 polynomial approximation: + // dx * P(dx) ~ log2(1 + dx) + // Generated by Sollya with: + // > P = fpminimax(log2(1 + x)/x, 5, [|D...|], [-2^-8, 2^-7]); + // > dirtyinfnorm(log2(1 + x)/x - P, [-2^-8, 2^-7]); + // 0x1.653...p-52 + const COEFFS: [u64; 6] = [ + 0x3ff71547652b82fe, + 0xbfe71547652b7a07, + 0x3fdec709dc458db1, + 0xbfd715479c2266c9, + 0x3fd2776ae1ddf8f0, + 0xbfce7b2178870157, + ]; + + let dx2 = dx * dx; // Exact + let c0 = backend.fma(dx, f64::from_bits(COEFFS[1]), f64::from_bits(COEFFS[0])); + let c1 = backend.fma(dx, f64::from_bits(COEFFS[3]), f64::from_bits(COEFFS[2])); + let c2 = backend.fma(dx, f64::from_bits(COEFFS[5]), f64::from_bits(COEFFS[4])); + + let p = backend.polyeval3(dx2, c0, c1, c2); + + // s = e_x - log2(r) + dx * P(dx) + // Approximation errors: + // |log2(x) - s| < ulp(e_x) + (bounds on dx) * (error bounds of P(dx)) + // = ulp(e_x) + 2^-7 * 2^-51 + // < 2^8 * 2^-52 + 2^-7 * 2^-43 + // ~ 2^-44 + 2^-50 + let s = backend.fma(dx, p, f64::from_bits(LOG2_R[idx_x as usize]) + e_x); + + // To compute 2^(y * log2(x)), we break the exponent into 3 parts: + // y * log(2) = hi + mid + lo, where + // hi is an integer + // mid * 2^6 is an integer + // |lo| <= 2^-7 + // Then: + // x^y = 2^(y * log2(x)) = 2^hi * 2^mid * 2^lo, + // In which 2^mid is obtained from a look-up table of size 2^6 = 64 elements, + // and 2^lo ~ 1 + lo * P(lo). + // Thus, we have: + // hi + mid = 2^-6 * round( 2^6 * y * log2(x) ) + // If we restrict the output such that |hi| < 150, (hi + mid) uses (8 + 6) + // bits, hence, if we use double precision to perform + // round( 2^6 * y * log2(x)) + // the lo part is bounded by 2^-7 + 2^(-(52 - 14)) = 2^-7 + 2^-38 + + // In the following computations: + // y6 = 2^6 * y + // hm = 2^6 * (hi + mid) = round(2^6 * y * log2(x)) ~ round(y6 * s) + // lo6 = 2^6 * lo = 2^6 * (y - (hi + mid)) = y6 * log2(x) - hm. + let y6 = (y * f32::from_bits(0x42800000)) as f64; // Exact. + let hm = backend.round(s * y6); + + // let log2_rr = LOG2_R2_DD[idx_x as usize]; + + // // lo6 = 2^6 * lo. + // let lo6_hi = f_fmla(y6, e_x + f64::from_bits(log2_rr.1), -hm); // Exact + // // Error bounds: + // // | (y*log2(x) - hm * 2^-6 - lo) / y| < err(dx * p) + err(LOG2_R_DD.lo) + // // < 2^-51 + 2^-75 + // let lo6 = f_fmla(y6, f_fmla(dx, p, f64::from_bits(log2_rr.0)), lo6_hi); + + // lo6 = 2^6 * lo. + let lo6_hi = backend.fma(y6, e_x + f64::from_bits(LOG2_R_TD[idx_x as usize].2), -hm); // Exact + // Error bounds: + // | (y*log2(x) - hm * 2^-6 - lo) / y| < err(dx * p) + err(LOG2_R_DD.lo) + // < 2^-51 + 2^-75 + let lo6 = backend.fma( + y6, + backend.fma(dx, p, f64::from_bits(LOG2_R_TD[idx_x as usize].1)), + lo6_hi, + ); + + // |2^(hi + mid) - exp2_hi_mid| <= ulp(exp2_hi_mid) / 2 + // Clamp the exponent part into smaller range that fits double precision. + // For those exponents that are out of range, the final conversion will round + // them correctly to inf/max float or 0/min float accordingly. + let mut hm_i = unsafe { hm.to_int_unchecked::() }; + hm_i = if hm_i > (1i64 << 15) { + 1 << 15 + } else if hm_i < (-(1i64 << 15)) { + -(1 << 15) + } else { + hm_i + }; + + let idx_y = hm_i & 0x3f; + + // 2^hi + let exp_hi_i = (hm_i >> 6).wrapping_shl(52); + // 2^mid + let exp_mid_i = EXP2_MID1[idx_y as usize].1; + // (-1)^sign * 2^hi * 2^mid + // Error <= 2^hi * 2^-53 + let exp2_hi_mid_i = (exp_hi_i.wrapping_add(exp_mid_i as i64) as u64).wrapping_add(sign); + let exp2_hi_mid = f64::from_bits(exp2_hi_mid_i); + + // Degree-5 polynomial approximation P(lo6) ~ 2^(lo6 / 2^6) = 2^(lo). + // Generated by Sollya with: + // > P = fpminimax(2^(x/64), 5, [|1, D...|], [-2^-1, 2^-1]); + // > dirtyinfnorm(2^(x/64) - P, [-0.5, 0.5]); + // 0x1.a2b77e618f5c4c176fd11b7659016cde5de83cb72p-60 + const EXP2_COEFFS: [u64; 6] = [ + 0x3ff0000000000000, + 0x3f862e42fefa39ef, + 0x3f0ebfbdff82a23a, + 0x3e8c6b08d7076268, + 0x3e03b2ad33f8b48b, + 0x3d75d870c4d84445, + ]; + + let lo6_sqr = lo6 * lo6; + let d0 = backend.fma( + lo6, + f64::from_bits(EXP2_COEFFS[1]), + f64::from_bits(EXP2_COEFFS[0]), + ); + let d1 = backend.fma( + lo6, + f64::from_bits(EXP2_COEFFS[3]), + f64::from_bits(EXP2_COEFFS[2]), + ); + let d2 = backend.fma( + lo6, + f64::from_bits(EXP2_COEFFS[5]), + f64::from_bits(EXP2_COEFFS[4]), + ); + let pp = backend.polyeval3(lo6_sqr, d0, d1, d2); + + let r = pp * exp2_hi_mid; + let r_u = r.to_bits(); + + let r_upper = f64::from_bits(r_u + B::ERR) as f32; + let r_lower = f64::from_bits(r_u - B::ERR) as f32; + if r_upper == r_lower { + return r_upper; + } + + // Scale lower part of 2^(hi + mid) + let exp2_hi_mid_dd = DoubleDouble { + lo: if idx_y != 0 { + f64::from_bits((exp_hi_i as u64).wrapping_add(EXP2_MID1[idx_y as usize].0)) + } else { + 0. + }, + hi: exp2_hi_mid, + }; + + let r_dd = powf_dd(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd, &backend); + r_dd as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn powf_fma_impl(x: f32, y: f32) -> f32 { + powf_gen(x, y, FmaPowfBackend {}) +} + +/// Power function +/// +/// Max found ULP 0.5 +pub fn f_powf(x: f32, y: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + powf_gen(x, y, GenPowfBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + powf_fma_impl + } else { + fn def_powf(x: f32, y: f32) -> f32 { + powf_gen(x, y, GenPowfBackend {}) + } + def_powf + } + }); + unsafe { q(x, y) } + } +} + +/// Dirty fast pow +#[inline] +pub fn dirty_powf(d: f32, n: f32) -> f32 { + use crate::exponents::dirty_exp2f; + use crate::logs::dirty_log2f; + let value = d.abs(); + let lg = dirty_log2f(value); + let c = dirty_exp2f(n * lg); + if d < 0.0 { + let y = n as i32; + if y % 2 == 0 { c } else { -c } + } else { + c + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn powf_test() { + assert!( + (powf(2f32, 3f32) - 8f32).abs() < 1e-6, + "Invalid result {}", + powf(2f32, 3f32) + ); + assert!( + (powf(0.5f32, 2f32) - 0.25f32).abs() < 1e-6, + "Invalid result {}", + powf(0.5f32, 2f32) + ); + } + + #[test] + fn f_powf_test() { + assert!( + (f_powf(2f32, 3f32) - 8f32).abs() < 1e-6, + "Invalid result {}", + f_powf(2f32, 3f32) + ); + assert!( + (f_powf(0.5f32, 2f32) - 0.25f32).abs() < 1e-6, + "Invalid result {}", + f_powf(0.5f32, 2f32) + ); + assert_eq!(f_powf(0.5f32, 1.5432f32), 0.34312353); + assert_eq!( + f_powf(f32::INFINITY, 0.00000000000000000000000000000000038518824), + f32::INFINITY + ); + assert_eq!(f_powf(f32::NAN, 0.0), 1.); + assert_eq!(f_powf(1., f32::NAN), 1.); + } + + #[test] + fn dirty_powf_test() { + assert!( + (dirty_powf(2f32, 3f32) - 8f32).abs() < 1e-6, + "Invalid result {}", + dirty_powf(2f32, 3f32) + ); + assert!( + (dirty_powf(0.5f32, 2f32) - 0.25f32).abs() < 1e-6, + "Invalid result {}", + dirty_powf(0.5f32, 2f32) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/powf_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/powf_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/powf_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,560 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +pub(crate) static POWF_R2: [u64; 193] = [ + 0x3ff0101000000000, + 0x3ff00fd000000000, + 0x3ff00f9000000000, + 0x3ff00f5000000000, + 0x3ff00f1000000000, + 0x3ff00ed000000000, + 0x3ff00e9000000000, + 0x3ff00e5000000000, + 0x3ff00e1000000000, + 0x3ff00dd000000000, + 0x3ff00d9000000000, + 0x3ff00d5000000000, + 0x3ff00d1000000000, + 0x3ff00cd000000000, + 0x3ff00c9000000000, + 0x3ff00c5000000000, + 0x3ff00c1000000000, + 0x3ff00bd000000000, + 0x3ff00b9000000000, + 0x3ff00b4000000000, + 0x3ff00b0000000000, + 0x3ff00ac000000000, + 0x3ff00a8000000000, + 0x3ff00a4000000000, + 0x3ff00a0000000000, + 0x3ff009c000000000, + 0x3ff0098000000000, + 0x3ff0094000000000, + 0x3ff0090000000000, + 0x3ff008c000000000, + 0x3ff0088000000000, + 0x3ff0084000000000, + 0x3ff0080000000000, + 0x3ff007c000000000, + 0x3ff0078000000000, + 0x3ff0074000000000, + 0x3ff0070000000000, + 0x3ff006c000000000, + 0x3ff0068000000000, + 0x3ff0064000000000, + 0x3ff0060000000000, + 0x3ff005c000000000, + 0x3ff0058000000000, + 0x3ff0054000000000, + 0x3ff0050000000000, + 0x3ff004c000000000, + 0x3ff0048000000000, + 0x3ff0044000000000, + 0x3ff0040000000000, + 0x3ff003c000000000, + 0x3ff0038000000000, + 0x3ff0034000000000, + 0x3ff0030000000000, + 0x3ff002c000000000, + 0x3ff0028000000000, + 0x3ff0024000000000, + 0x3ff0020000000000, + 0x3ff001c000000000, + 0x3ff0018000000000, + 0x3ff0014000000000, + 0x3ff0010000000000, + 0x3ff000c000000000, + 0x3ff0008000000000, + 0x3ff0004000000000, + 0x3ff0000000000000, + 0x3fefff8000000000, + 0x3fefff0000000000, + 0x3feffe8000000000, + 0x3feffe0000000000, + 0x3feffd8000000000, + 0x3feffd0000000000, + 0x3feffc8000000000, + 0x3feffc0000000000, + 0x3feffb8000000000, + 0x3feffb0000000000, + 0x3feffa8000000000, + 0x3feffa0000000000, + 0x3feff98000000000, + 0x3feff90000000000, + 0x3feff88000000000, + 0x3feff80000000000, + 0x3feff78000000000, + 0x3feff70000000000, + 0x3feff68000000000, + 0x3feff60000000000, + 0x3feff58000000000, + 0x3feff50000000000, + 0x3feff48000000000, + 0x3feff40000000000, + 0x3feff38000000000, + 0x3feff30000000000, + 0x3feff28000000000, + 0x3feff20000000000, + 0x3feff18000000000, + 0x3feff10000000000, + 0x3feff08000000000, + 0x3feff00000000000, + 0x3fefef8000000000, + 0x3fefef0000000000, + 0x3fefee8000000000, + 0x3fefee0000000000, + 0x3fefed8000000000, + 0x3fefed0000000000, + 0x3fefec8000000000, + 0x3fefec0000000000, + 0x3fefeb8000000000, + 0x3fefeb0000000000, + 0x3fefea8000000000, + 0x3fefea0000000000, + 0x3fefe98000000000, + 0x3fefe92000000000, + 0x3fefe8a000000000, + 0x3fefe82000000000, + 0x3fefe7a000000000, + 0x3fefe72000000000, + 0x3fefe6a000000000, + 0x3fefe62000000000, + 0x3fefe5a000000000, + 0x3fefe52000000000, + 0x3fefe4a000000000, + 0x3fefe42000000000, + 0x3fefe3a000000000, + 0x3fefe32000000000, + 0x3fefe2a000000000, + 0x3fefe22000000000, + 0x3fefe1a000000000, + 0x3fefe12000000000, + 0x3fefe0a000000000, + 0x3fefe02000000000, + 0x3fefdfa000000000, + 0x3fefdf2000000000, + 0x3fefdea000000000, + 0x3fefde2000000000, + 0x3fefdda000000000, + 0x3fefdd2000000000, + 0x3fefdca000000000, + 0x3fefdc2000000000, + 0x3fefdba000000000, + 0x3fefdb2000000000, + 0x3fefdaa000000000, + 0x3fefda2000000000, + 0x3fefd9a000000000, + 0x3fefd92000000000, + 0x3fefd8c000000000, + 0x3fefd84000000000, + 0x3fefd7c000000000, + 0x3fefd74000000000, + 0x3fefd6c000000000, + 0x3fefd64000000000, + 0x3fefd5c000000000, + 0x3fefd54000000000, + 0x3fefd4c000000000, + 0x3fefd44000000000, + 0x3fefd3c000000000, + 0x3fefd34000000000, + 0x3fefd2c000000000, + 0x3fefd24000000000, + 0x3fefd1c000000000, + 0x3fefd14000000000, + 0x3fefd0c000000000, + 0x3fefd04000000000, + 0x3fefcfc000000000, + 0x3fefcf4000000000, + 0x3fefcec000000000, + 0x3fefce4000000000, + 0x3fefcdc000000000, + 0x3fefcd6000000000, + 0x3fefcce000000000, + 0x3fefcc6000000000, + 0x3fefcbe000000000, + 0x3fefcb6000000000, + 0x3fefcae000000000, + 0x3fefca6000000000, + 0x3fefc9e000000000, + 0x3fefc96000000000, + 0x3fefc8e000000000, + 0x3fefc86000000000, + 0x3fefc7e000000000, + 0x3fefc76000000000, + 0x3fefc6e000000000, + 0x3fefc66000000000, + 0x3fefc5e000000000, + 0x3fefc56000000000, + 0x3fefc4e000000000, + 0x3fefc46000000000, + 0x3fefc40000000000, + 0x3fefc38000000000, + 0x3fefc30000000000, + 0x3fefc28000000000, + 0x3fefc20000000000, + 0x3fefc18000000000, + 0x3fefc10000000000, + 0x3fefc08000000000, +]; + +pub(crate) static LOG2_R_TD: [(u64, u64, u64); 128] = [ + (0x0000000000000000, 0x0000000000000000, 0x0000000000000000), + (0x3b084a2c615b70ad, 0xbe6177c23362928c, 0x3f872c8000000000), + (0xbb3f27b820fd03ea, 0xbe9179e0caa9c9ab, 0x3f97440000000000), + (0xbb2f27ef487c8f34, 0xbe8c6cea541f5b70, 0x3fa184c000000000), + (0xbb3e3f80fbc71454, 0xbe966c4d4e554434, 0x3fa773a000000000), + (0xbb09f8ef14d5f6ee, 0xbe770700a00fdd55, 0x3fad6ec000000000), + (0x3b2452bbce7398c1, 0x3e853002a4e86631, 0x3fb1bb3000000000), + (0xbae990555535afd0, 0x3e6fcd15f101c142, 0x3fb4c56000000000), + (0x3b1447e30ad393ee, 0x3e925b3eed319ced, 0x3fb7d60000000000), + (0x3b3b7759da88a2da, 0xbe94195120d8486f, 0x3fb960d000000000), + (0x3b1cee7766ece702, 0x3e845b878e27d0d9, 0x3fbc7b5000000000), + (0xbb2a55c745ecdc2f, 0x3e9770744593a4cb, 0x3fbf9c9000000000), + (0x3b2f7ec992caa67f, 0x3e9c673032495d24, 0x3fc097e000000000), + (0xbb2433638c6ece3e, 0xbe91eaa65b49696e, 0x3fc22db000000000), + (0x3b358f27b6518824, 0x3e9b2866f2850b22, 0x3fc3c6f800000000), + (0xbb086bdcfdfd4a4c, 0x3e68ee37cd2ea9d3, 0x3fc494f800000000), + (0xbafff7044a68a7fa, 0x3e77e86f9c2154fb, 0x3fc633a800000000), + (0xbaeaa21694561327, 0x3e58e3cfc25f0ce6, 0x3fc7046000000000), + (0xba8d209f2d4239c6, 0x3e357f7a64ccd537, 0x3fc8a89800000000), + (0xbb3a55e97e60e632, 0xbe9a761c09fbd2ae, 0x3fc97c2000000000), + (0x3b3261179225541e, 0x3e924bea9a2c66f3, 0x3fcb260000000000), + (0xbad08fa30510fca9, 0xbe660002ccfe43f5, 0x3fcbfc6800000000), + (0xbb363ec8d56242f9, 0x3e969f220e97f22c, 0x3fcdac2000000000), + (0x3b38bcdaf0534365, 0xbe96164f64c210e0, 0x3fce858000000000), + (0x3b11003282896056, 0xbe70c1678ae89767, 0x3fd01d9c00000000), + (0x3b101bcc7025fa92, 0xbe9f26a05c813d57, 0x3fd08bd000000000), + (0xbaffe8a8648e9ebc, 0x3e74d8fc561c8d44, 0x3fd169c000000000), + (0x3b008dfb23650c75, 0xbe9362ad8f7ca2d0, 0x3fd1d98400000000), + (0xbb0f8d5a89861a5e, 0x3e92b13cd6c4d042, 0x3fd249cc00000000), + (0xbb3a1c872983511e, 0xbe91c8f11979a5db, 0x3fd32c0000000000), + (0x3b2e8e21bff3336b, 0x3e8c2ab3edefe569, 0x3fd39de800000000), + (0x3affd1994fb2c4a1, 0x3e57c3eca28e69ca, 0x3fd4106000000000), + (0x3af6b94b51cf76b1, 0xbe734c4e99e1c6c6, 0x3fd4f6fc00000000), + (0xbb331d55da1d0f66, 0xbe9194a871b63619, 0x3fd56b2400000000), + (0xbb2378b22691e28b, 0x3e8e3dd5c1c885ae, 0x3fd5dfdc00000000), + (0x3ac99e302970e411, 0xbe86ccf3b1129b7c, 0x3fd6552c00000000), + (0x3ad20164a049664d, 0xbe82f346e2bf924b, 0x3fd6cb1000000000), + (0xbb2d14aac4d864c3, 0xbe8fa61aaa59c1d8, 0x3fd7b8a000000000), + (0x3b0496ab4e4b293f, 0x3e990c11fd32a3ab, 0x3fd8304c00000000), + (0xba9d209f2d4239c6, 0x3e457f7a64ccd537, 0x3fd8a89800000000), + (0x3aeeae3326327bab, 0x3e4249ba76fee235, 0x3fd9218000000000), + (0x3b2fa05bddfded8c, 0xbe8aad2729b21ae5, 0x3fd99b0800000000), + (0xbb2624140d175ba2, 0x3e971810a5e18180, 0x3fda8ff800000000), + (0x3aef1c5160c515c1, 0xbe46172fe015e13c, 0x3fdb0b6800000000), + (0xbb086a6204eec8c0, 0x3e75ec6c1bfbf89a, 0x3fdb877c00000000), + (0x3b1718f761dd3915, 0x3e7678bf6cdedf51, 0x3fdc043800000000), + (0xbb3d4ee66c3700e4, 0x3e9c2d45fe43895e, 0x3fdc819c00000000), + (0xbb27d14533586306, 0xbe99ee52ed49d71d, 0x3fdcffb000000000), + (0x3ae5ce9fb5a7bb5b, 0x3e45786af187a96b, 0x3fdd7e6c00000000), + (0xbb2ae6face57ad3b, 0x3e83ab0dc56138c9, 0x3fddfdd800000000), + (0x3b15ac93b443d55f, 0x3e9fe538ab34efb5, 0x3fde7df400000000), + (0x3b3f1753e0ae1e8f, 0xbe9e4fee07aa4b68, 0x3fdefec800000000), + (0x3b3cdfd4c297069b, 0xbe9172f32fe67287, 0x3fdf804c00000000), + (0x3b097a0e8f3ba742, 0xbe99a83ff9ab9cc8, 0x3fe0014400000000), + (0xbb1800450f5b2357, 0xbe968cb06cece193, 0x3fe042be00000000), + (0xbb1a839041241fe7, 0x3e98cd71ddf82e20, 0x3fe0849400000000), + (0x3b1ed0b8eeccca86, 0x3e95e18ab2df3ae6, 0x3fe0c6ca00000000), + (0x3b03dd41df9689b3, 0x3e65dee4d9d8a273, 0x3fe1096000000000), + (0xbad990555535afd0, 0x3e5fcd15f101c142, 0x3fe14c5600000000), + (0xbb21773d02c9055c, 0xbe82474b0f992ba1, 0x3fe18fae00000000), + (0xbb14aeef330c53c1, 0x3e74b5a92a606047, 0x3fe1d36800000000), + (0x3b28e6ff749ebacb, 0x3e916186fcf54bbd, 0x3fe2178600000000), + (0x3abc09d761c548eb, 0x3e418efabeb7d722, 0x3fe25c0a00000000), + (0x3b1aaa73a428e1e4, 0xbe7e5fc7d238691d, 0x3fe2a0f400000000), + (0xbb0af2f3d8b63fba, 0x3e9f5809faf6283c, 0x3fe2e64400000000), + (0xbb0af2f3d8b63fba, 0x3e9f5809faf6283c, 0x3fe2e64400000000), + (0x3b278de359f2bb88, 0x3e9c6e1dcd0cb449, 0x3fe32bfe00000000), + (0xbb3415ae1a715618, 0x3e976e0e8f74b4d5, 0x3fe3722200000000), + (0xbb04991b5375621f, 0xbe7cb82c89692d99, 0x3fe3b8b200000000), + (0xbb3827d37deb2236, 0xbe963161c5432aeb, 0x3fe3ffae00000000), + (0x3b29576edac01c78, 0x3e9458104c41b901, 0x3fe4471600000000), + (0x3b29576edac01c78, 0x3e9458104c41b901, 0x3fe4471600000000), + (0xbb205a27b81e2219, 0xbe9cd9d0cde578d5, 0x3fe48ef000000000), + (0x3ad237616778b4ba, 0x3e5b9884591add87, 0x3fe4d73800000000), + (0x3b33b7d7e5d148bb, 0x3e9c6042978605ff, 0x3fe51ff200000000), + (0xbb0cc3f936a5977c, 0xbe9fc4c96b37dcf6, 0x3fe5692200000000), + (0x3ac20164a049664d, 0xbe72f346e2bf924b, 0x3fe5b2c400000000), + (0x3ac20164a049664d, 0xbe72f346e2bf924b, 0x3fe5b2c400000000), + (0xbb2a212919a92f7a, 0x3e9c4e4fbb68a4d1, 0x3fe5fcdc00000000), + (0xbb2b64b03f7230dd, 0xbe89d499bd9b3226, 0x3fe6476e00000000), + (0xbb21ec6379e6e3b9, 0xbe8f89b355ede26f, 0x3fe6927800000000), + (0xbb21ec6379e6e3b9, 0xbe8f89b355ede26f, 0x3fe6927800000000), + (0xbb14ba44c03bfbbd, 0x3e753c7e319f6e92, 0x3fe6ddfc00000000), + (0xbb2c36fc650d030f, 0xbe9b291f070528c7, 0x3fe729fe00000000), + (0xbaf69e5693a7f067, 0x3e62967a451a7b48, 0x3fe7767c00000000), + (0xbaf69e5693a7f067, 0x3e62967a451a7b48, 0x3fe7767c00000000), + (0x3b36598aae91499a, 0x3e9244fcff690fce, 0x3fe7c37a00000000), + (0x3b299d61ec432837, 0x3e846fd97f5dc572, 0x3fe810fa00000000), + (0x3b299d61ec432837, 0x3e846fd97f5dc572, 0x3fe810fa00000000), + (0x3b3855c42078f81b, 0xbe9f3a7352663e50, 0x3fe85efe00000000), + (0xbb259408e8151070, 0x3e8b3cda690370b5, 0x3fe8ad8400000000), + (0xbb259408e8151070, 0x3e8b3cda690370b5, 0x3fe8ad8400000000), + (0x3b133b318085e50a, 0x3e83226b211bf1d9, 0x3fe8fc9200000000), + (0x3b0343fe7c9cb4ae, 0x3e8d24b136c101ee, 0x3fe94c2800000000), + (0x3b0343fe7c9cb4ae, 0x3e8d24b136c101ee, 0x3fe94c2800000000), + (0xbb3d19522e56fe60, 0x3e97c40c7907e82a, 0x3fe99c4800000000), + (0xbb223b9d8ea55c3e, 0xbe9e81781d97ee91, 0x3fe9ecf600000000), + (0xbb223b9d8ea55c3e, 0xbe9e81781d97ee91, 0x3fe9ecf600000000), + (0x3b1829440c24aeb6, 0xbe96a77813f94e01, 0x3fea3e3000000000), + (0xbb3624140d175ba2, 0xbe91cfdeb43cfd00, 0x3fea8ffa00000000), + (0xbb3624140d175ba2, 0xbe91cfdeb43cfd00, 0x3fea8ffa00000000), + (0x3b2afa6f024fb045, 0xbe8f983f74d3138f, 0x3feae25600000000), + (0xbb1603ad3a5d326d, 0xbe8e278ae1a1f51f, 0x3feb354600000000), + (0xbb1603ad3a5d326d, 0xbe8e278ae1a1f51f, 0x3feb354600000000), + (0xbb20c1e0e5855d6a, 0xbe897552b7b5ea45, 0x3feb88cc00000000), + (0xbb20c1e0e5855d6a, 0xbe897552b7b5ea45, 0x3feb88cc00000000), + (0x3b1c817ad56baa16, 0xbe719b4f3c72c4f8, 0x3febdcea00000000), + (0x3b244c47ac1bf62b, 0x3e8f7402d26f1a12, 0x3fec31a200000000), + (0x3b244c47ac1bf62b, 0x3e8f7402d26f1a12, 0x3fec31a200000000), + (0xbb169b9465eae1e6, 0xbe82056d5dd31d96, 0x3fec86f800000000), + (0xbb169b9465eae1e6, 0xbe82056d5dd31d96, 0x3fec86f800000000), + (0xbb024a6d9d1d1904, 0xbe76e46335aae723, 0x3fecdcec00000000), + (0xbb33826144575ac4, 0xbe9beb244c59f331, 0x3fed338200000000), + (0xbb33826144575ac4, 0xbe9beb244c59f331, 0x3fed338200000000), + (0x3aedbc96b3b12b25, 0x3e416c071e93fd97, 0x3fed8aba00000000), + (0x3aedbc96b3b12b25, 0x3e416c071e93fd97, 0x3fed8aba00000000), + (0x3b268a8ccdbd1f33, 0x3e9d8175819530c2, 0x3fede29800000000), + (0x3b268a8ccdbd1f33, 0x3e9d8175819530c2, 0x3fede29800000000), + (0x3b0e586711df5ea1, 0x3e851bd552842c1c, 0x3fee3b2000000000), + (0x3b0e586711df5ea1, 0x3e851bd552842c1c, 0x3fee3b2000000000), + (0xbb0bc25adf042483, 0x3e9914e204f19d94, 0x3fee945200000000), + (0xbb0bc25adf042483, 0x3e9914e204f19d94, 0x3fee945200000000), + (0x3b3d7d82b65c5686, 0x3e9c55d997da24fd, 0x3feeee3200000000), + (0x3b3d7d82b65c5686, 0x3e9c55d997da24fd, 0x3feeee3200000000), + (0xbb23f108c0857ca3, 0xbe9685c2d2298a6e, 0x3fef48c400000000), + (0xbb23f108c0857ca3, 0xbe9685c2d2298a6e, 0x3fef48c400000000), + (0xbb1bd800bca7a221, 0x3e97a4887bd74039, 0x3fefa40600000000), + (0x0000000000000000, 0x0000000000000000, 0x3ff0000000000000), +]; + +// Look up table for the second range reduction step: +// Generated by Sollya with: +// > for i from -64 to 128 do { +// r = 2^-16 * nearestint(2^16 / (1 + i * 2^-14) ); +// a = -log2(r); +// b = round(a, D, RN); +// c = round(a - b, D, RN); +// print("{", c, ", ", b, "},"); +// }; +pub(crate) static LOG2_R2_DD: [(u64, u64); 193] = [ + (0x3c1ff25180953e64, 0xbf7720c2ab2312a9), + (0xbc115ffd79560d8f, 0xbf76c4c92b1478ff), + (0x3c1b8d6d6f2e3579, 0xbf7668ce3c873549), + (0xbc15bfc3f0d5ef71, 0xbf760cd1df6fde91), + (0xbbfd1f7a8777984a, 0xbf75b0d413c30b5e), + (0x3bd8e858515b8343, 0xbf7554d4d97551ab), + (0x3c1e165c4014c1f2, 0xbf74f8d4307b46ec), + (0x3c00f84b2cc14c7e, 0xbf749cd218c9800b), + (0x3c1de618ed0db9a6, 0xbf7440ce9254916c), + (0xbc1f6b8587e64f22, 0xbf73e4c99d110ee7), + (0xbbf7f793c84cfa63, 0xbf7388c338f38bd0), + (0xbbe7d7ecf6258c9a, 0xbf732cbb65f09aee), + (0xbc1810bc5ac188f5, 0xbf72d0b223fcce81), + (0xbc1950035fc5b67c, 0xbf7274a7730cb841), + (0x3c14f47f3048cdad, 0xbf72189b5314e95d), + (0x3bb269519861e298, 0xbf71bc8dc409f279), + (0xbc15c2b0a46a7e2f, 0xbf71607ec5e063b3), + (0x3c05001ac8f0bda8, 0xbf71046e588ccca0), + (0x3c1106f246af5d41, 0xbf70a85c7c03bc4a), + (0x3bd82a00583b34ba, 0xbf70354423e3c666), + (0x3beb6f37deb31370, 0xbf6fb25e19f11aec), + (0xbc044a2140444811, 0xbf6efa310d6550ec), + (0x3c0f5e68a763133f, 0xbf6e4201220d4858), + (0x3c0692083115f0b9, 0xbf6d89ce57d219a6), + (0x3c0144bb17b9ac9c, 0xbf6cd198ae9cdc3d), + (0x3c0ee7f086d32c05, 0xbf6c19602656a671), + (0xbc0d4f1167538dbe, 0xbf6b6124bee88d82), + (0x3c07df8d226c67e0, 0xbf6aa8e6783ba5a2), + (0x3c060545d61b9512, 0xbf69f0a5523901eb), + (0x3c054c99c2917020, 0xbf6938614cc9b468), + (0xbbfa7e678d7280de, 0xbf68801a67d6ce10), + (0xbbf6d419bbeb223a, 0xbf67c7d0a3495ec9), + (0x3bfce2b9892e27e9, 0xbf670f83ff0a7565), + (0xbc0a4db4eff7bd61, 0xbf6657347b031fa2), + (0x3c05bb04682fab82, 0xbf659ee2171c6a2f), + (0xbbf78b8bfe6a3ade, 0xbf64e68cd33f60a3), + (0x3c0574c3ce9b89b1, 0xbf642e34af550d87), + (0x3c008fb216647b7b, 0xbf6375d9ab467a4d), + (0x3bded5a50e7b919c, 0xbf62bd7bc6fcaf56), + (0x3c091ad7a23f86fe, 0xbf62051b0260b3f0), + (0x3bf3ab2c932b8b0a, 0xbf614cb75d5b8e54), + (0xbc0c63bcdf120f7a, 0xbf609450d7d643a9), + (0x3bf8af8c4ab4e82d, 0xbf5fb7cee373b008), + (0x3bea52c2ca9d8b9b, 0xbf5e46f655de9cc6), + (0xbbf460b177a58742, 0xbf5cd61806bf5166), + (0x3bd611089de8d12a, 0xbf5b6533f5e7cf9b), + (0xbba4209853cee70c, 0xbf59f44a232a16ee), + (0x3bf964e032541a28, 0xbf58835a8e5824c3), + (0xbbdfa9f94392637b, 0xbf5712653743f454), + (0xbbf3293693721a53, 0xbf55a16a1dbf7eb6), + (0xbbb6e2af03c83c6e, 0xbf543069419cbad5), + (0xbbeb5f05b9d5bd29, 0xbf52bf62a2ad9d74), + (0x3bf3db883c072f72, 0xbf514e5640c41930), + (0xbbba675a1c045304, 0xbf4fba8837643cf6), + (0x3bd3b9c2aeb00068, 0xbf4cd85866933743), + (0xbbd2911a381901eb, 0xbf49f61d0eb8f98b), + (0xbbb5ea75a74def03, 0xbf4713d62f7957c3), + (0xbbc305b92f93ffe0, 0xbf443183c878218d), + (0x3bbb7c8c8dd40d35, 0xbf414f25d959223a), + (0x3bddc915d58a62f6, 0xbf3cd978c3804191), + (0x3bdc7bc3fe53cd94, 0xbf37148ec2a1bfc9), + (0xbbc427ce595cc53c, 0xbf314f8daf5e3bcf), + (0xbbcd523885ac824c, 0xbf2714eb11fa5363), + (0xbba945957f63330a, 0xbf1715193b17d35d), + (0x0000000000000000, 0x0000000000000000), + (0xbb988fb2ea8bf9ea, 0x3f17157590356aee), + (0xbbb5aeaee345d04e, 0x3f2715a3bc3593d5), + (0xbbd7fce430230132, 0x3f31505d6ee104c5), + (0xbb99a480f204ff09, 0x3f3716001718cb2b), + (0xbbb00e7233f2d8bd, 0x3f3cdbb9d77ae5a8), + (0x3bc09d379fa18c5d, 0x3f4150c5586012b8), + (0x3beb6b9d90a104d3, 0x3f4433b951d0b231), + (0x3be4d9a3ea651885, 0x3f4716b8d86bc285), + (0xbbc7590b3a76f0f9, 0x3f49f9c3ec8db94f), + (0x3bef183ca5b21bfe, 0x3f4cdcda8e93107f), + (0xbbda7e3465ba1270, 0x3f4fbffcbed8465f), + (0xbbf7821f738d1221, 0x3f5151953edceec6), + (0x3be3bb4c0fb95359, 0x3f52c331e5ca2e7d), + (0x3bf236028e962f80, 0x3f5434d4546227fc), + (0x3bdaaaa64d30f184, 0x3f55a67c8ad32315), + (0xbbfa821b7cc57a7a, 0x3f57182a894b69c6), + (0xbbf13d9d78aace21, 0x3f5889de4ff94838), + (0xbbf2f249a6b923a0, 0x3f59fb97df0b0cc2), + (0xbbbd47dc3664be7a, 0x3f5b6d5736af07e6), + (0x3bfbd1522c6418fb, 0x3f5cdf1c57138c53), + (0xbbfbacdbb22d2163, 0x3f5e50e74066eee6), + (0xbbfca7604812d77b, 0x3f5fc2b7f2d786a5), + (0xbc02b6832f8830bf, 0x3f609a473749d663), + (0x3be4e712033d0457, 0x3f61533559e4de55), + (0xbbd473dd044017b5, 0x3f620c26615409f1), + (0xbc0e033bcac726d3, 0x3f62c51a4dae8915), + (0xbc04a47a2b18a0fa, 0x3f637e111f0b8cb5), + (0x3bd6f3615771c17b, 0x3f64370ad58246dd), + (0x3bec0ee6c32d6236, 0x3f64f0077129eab0), + (0x3bffa94c99761b8f, 0x3f65a906f219ac67), + (0xbbf979e6b473fbf8, 0x3f6662095868c153), + (0x3bf30edde8d24c7b, 0x3f671b0ea42e5fda), + (0xbbfd01594fe1421c, 0x3f67d416d581bf7c), + (0x3c050bf7b995b49a, 0x3f688d21ec7a18cd), + (0xbc028ea2bcec5018, 0x3f69462fe92ea57c), + (0x3beed6add489c30b, 0x3f69ff40cbb6a04b), + (0x3bf201d5c3bbeb69, 0x3f6ab85494294517), + (0xbbfa05d0d4461ea9, 0x3f6b716b429dd0d3), + (0xbc07c974c8a392fd, 0x3f6c2a84d72b8189), + (0xbbff068238451bde, 0x3f6ce3a151e9965b), + (0xbbd5e4d95c6259c3, 0x3f6d9cc0b2ef4f83), + (0xbc01fc262efaad6c, 0x3f6e55e2fa53ee53), + (0x3c049eee7abc7716, 0x3f6f0f08282eb533), + (0xbbe903de284d2782, 0x3f6fc8303c96e7a6), + (0xbc0ec564845134cb, 0x3f7040ad9bd1e522), + (0xbbd7692b7791cf1f, 0x3f70861eadabc3dc), + (0xbc137829afb11c10, 0x3f70e2b6b51e4f7e), + (0x3c16706b91c3b0ba, 0x3f713f5030033459), + (0xbc17558ccd710756, 0x3f719beb1e6616c9), + (0x3c179f72a5bbe9de, 0x3f71f88780529bb1), + (0xbc1e1297c110b250, 0x3f72552555d46886), + (0x3c129930d567ca26, 0x3f72b1c49ef72343), + (0x3bea08cbd7592a17, 0x3f730e655bc67275), + (0x3c1e4f9d4ac5db83, 0x3f736b078c4dfd31), + (0xbc1ed1b0aafd30c2, 0x3f73c7ab30996b1c), + (0x3c1e78f0aa014b32, 0x3f74245048b46462), + (0x3ba8594548038a0f, 0x3f7480f6d4aa91c2), + (0x3c03df498168a333, 0x3f74dd9ed4879c82), + (0x3c1b1c502544f82a, 0x3f753a4848572e77), + (0xbc0dc50552fe0da9, 0x3f7596f33024f203), + (0xbc1671d85c357d5e, 0x3f75f39f8bfc9212), + (0x3bf1c670cabccefa, 0x3f76504d5be9ba1e), + (0xbc19983a9e98f318, 0x3f76acfc9ff8162f), + (0x3c1ae1a26af3eebe, 0x3f7709ad583352d6), + (0x3c1655eb510bfda3, 0x3f77665f84a71d35), + (0xbbfe287bc0192e15, 0x3f77c313255f22f8), + (0x3c0cc4944139ccbf, 0x3f781fc83a671257), + (0x3c14e09b4cb8645b, 0x3f787c7ec3ca9a19), + (0xbbf5becc991e3a5f, 0x3f78d936c1956991), + (0xbc1ddfa3f1e15ba8, 0x3f7935f033d3309e), + (0xbc1b7b06ea3fb362, 0x3f7992ab1a8f9fac), + (0x3c132d614904e46c, 0x3f79ef6775d667b4), + (0xbbf7186892b5bfae, 0x3f7a4c2545b33a3e), + (0xbc1d4de10b28dfd8, 0x3f7aa8e48a31c95c), + (0x3c14bb4b3bdc8175, 0x3f7b05a5435dc7ad), + (0x3c19cedbd1d7fba5, 0x3f7b62677142e860), + (0xbbd0ed3379beaffd, 0x3f7bbf2b13ecdf2f), + (0x3c16e86a125567a6, 0x3f7c1bf02b676060), + (0xbc135038e0c0a52c, 0x3f7c6184f1b326d9), + (0x3bc05ef8bf5adf5e, 0x3f7cbe4c95b6c5ab), + (0xbbeb7338b99a6b26, 0x3f7d1b15aeab217c), + (0x3c09e901c30c427e, 0x3f7d77e03c9bf0a4), + (0xbc11f28a9c0b3d47, 0x3f7dd4ac3f94ea0a), + (0xbc1140ef760d3b63, 0x3f7e3179b7a1c520), + (0xbc0ab65b1037f517, 0x3f7e8e48a4ce39e7), + (0xbc076940c457ce6d, 0x3f7eeb19072600ed), + (0x3bfda3ae65a605cf, 0x3f7f47eadeb4d34d), + (0x3c1b15d0bce2ede6, 0x3f7fa4be2b866ab0), + (0x3c2e02aa1fa9dc57, 0x3f8000c976d340a6), + (0x3c16be971a5565b9, 0x3f802f34929068f3), + (0xbbf8a9319a6ed164, 0x3f805da069008be7), + (0x3c1825079f1e0ec5, 0x3f808c0cfa298771), + (0x3c060d5749321466, 0x3f80ba7a461139c8), + (0xbc25b8f4c479e2e0, 0x3f80e8e84cbd8169), + (0xbc1e3e1248004e29, 0x3f8117570e343d17), + (0x3c09ac06487c3750, 0x3f8145c68a7b4bdd), + (0x3c1f657ea5c03ea4, 0x3f817436c1988d0d), + (0xbc25a965659a05e2, 0x3f81a2a7b391e040), + (0xbc221ce9b9bfc512, 0x3f81d119606d2554), + (0xbc230fda247ad0e1, 0x3f81ff8bc8303c70), + (0xbc1382c78a45cdea, 0x3f822dfeeae10601), + (0x3c246ae4a64073d4, 0x3f8250d5bf952374), + (0xbc1dcad2cec3b84b, 0x3f827f4a29740a2f), + (0xbc2413fbeb0b0635, 0x3f82adbf4e50cdf9), + (0x3c2f28e6a48bcb90, 0x3f82dc352e315049), + (0xbc296f286e1eb086, 0x3f830aabc91b72e0), + (0xbc2f88c04206dfa1, 0x3f8339231f1517c1), + (0xbc211ea20e195841, 0x3f83679b30242139), + (0xbc0d6e71452b674a, 0x3f839613fc4e71dc), + (0xbc257c578233b1b3, 0x3f83c48d8399ec85), + (0xbc0ec430f03b76e0, 0x3f83f307c60c7455), + (0x3c2e00dd1902ffb9, 0x3f842182c3abecb5), + (0xbc2f22bcd96afe38, 0x3f844ffe7c7e3957), + (0x3c208fd90f841d30, 0x3f847e7af0893e2f), + (0x3c109594c5552bcc, 0x3f84acf81fd2df7e), + (0xbc201a8a652e5602, 0x3f84db760a6101c9), + (0xbbf826168febb3d0, 0x3f8509f4b03989dc), + (0xbc17eb21a35021e3, 0x3f85387411625ccc), + (0xbc266cbc818e1750, 0x3f8566f42de15ff4), + (0x3bf9b784dd6cebda, 0x3f85957505bc78f6), + (0x3c22b121ab482456, 0x3f85b8562298c65b), + (0xbc15d29869dd8233, 0x3f85e6d842633702), + (0xbc2572a1b6cd63cf, 0x3f86155b1d99f672), + (0xbc1a1f355360e877, 0x3f8643deb442eb59), + (0xbc2b6f1cd2e1c03f, 0x3f8672630663fcad), + (0xbc22aaa11ccddcae, 0x3f86a0e8140311aa), + (0x3c23d979ddf4746c, 0x3f86cf6ddd2611d4), + (0xbc0dc930484501f8, 0x3f86fdf461d2e4f8), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/ceil.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/ceil.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/ceil.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/ceil.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn ceilf(x: f32) -> f32 { + /* Use generic implementation. */ + let mut i0: i32 = x.to_bits() as i32; + let j0 = ((i0 >> 23) & 0xff) - 0x7f; + if j0 < 23 { + if j0 < 0 { + /* return 0 * sign (x) if |x| < 1 */ + if i0 < 0 { + i0 = 0x80000000u32 as i32; + } else if i0 != 0 { + i0 = 0x3f800000u32 as i32; + } + } else { + let i = (0x007fffff) >> j0; + if (i0 & i) == 0 { + return x; /* x is integral */ + } + if i0 > 0 { + i0 = i0.wrapping_add((0x00800000) >> j0); + } + i0 &= !i; + } + } else { + return if j0 == 0x80 { + x + x /* inf or NaN */ + } else { + x /* x is integral */ + }; + } + f32::from_bits(i0 as u32) +} + +#[inline] +pub const fn ceil(x: f64) -> f64 { + let mut i0: i64 = x.to_bits() as i64; + let j0: i32 = (((i0 >> 52) & 0x7ff) - 0x3ff) as i32; + if j0 <= 51 { + if j0 < 0 { + /* return 0 * sign(x) if |x| < 1 */ + if i0 < 0 { + i0 = 0x8000000000000000u64 as i64; + } else if i0 != 0 { + i0 = 0x3ff0000000000000u64 as i64; + } + } else { + let i = (0x000fffffffffffffu64 as i64) >> j0; + if (i0 & i) == 0 { + return x; /* x is integral */ + } + if i0 > 0 { + i0 = i0.wrapping_add((0x0010000000000000u64 >> j0) as i64); + } + i0 &= !i; + } + } else { + return if j0 == 0x400 { + x + x /* inf or NaN */ + } else { + x /* x is integral */ + }; + } + f64::from_bits(i0 as u64) +} + +pub(crate) trait CpuCeil { + fn cpu_ceil(self) -> Self; +} + +impl CpuCeil for f32 { + #[inline] + fn cpu_ceil(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.ceil() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + ceilf(self) + } + } +} + +impl CpuCeil for f64 { + #[inline] + fn cpu_ceil(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.ceil() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + ceil(self) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ceilf() { + assert_eq!(ceilf(0.0), 0.0); + assert_eq!(ceilf(10.0), 10.0); + assert_eq!(ceilf(10.1), 11.0); + assert_eq!(ceilf(-9.0), -9.0); + assert_eq!(ceilf(-9.5), -9.0); + } + + #[test] + fn test_ceil() { + assert_eq!(ceil(0.0), 0.0); + assert_eq!(ceil(10.0), 10.0); + assert_eq!(ceil(10.1), 11.0); + assert_eq!(ceil(-9.0), -9.0); + assert_eq!(ceil(-9.5), -9.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/floor.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/floor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/floor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/floor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/// Round to integer towards minus infinity +#[inline] +pub const fn floorf(x: f32) -> f32 { + let mut i0 = x.to_bits() as i32; + let j0 = ((i0 >> 23) & 0xff) - 0x7f; + if j0 < 23 { + if j0 < 0 { + /* return 0 * sign (x) if |x| < 1 */ + if i0 >= 0 { + i0 = 0; + } else if (i0 & 0x7fffffff) != 0 { + i0 = 0xbf800000u32 as i32; + } + } else { + let i = (0x007fffff) >> j0; + if (i0 & i) == 0 { + return x; /* x is integral */ + } + if i0 < 0 { + i0 = i0.wrapping_add((0x00800000) >> j0); + } + i0 &= !i; + } + } else { + return if j0 == 0x80 { + x + x /* inf or NaN */ + } else { + x /* x is integral */ + }; + } + f32::from_bits(i0 as u32) +} + +/// Floors value +#[inline] +pub const fn floor(x: f64) -> f64 { + let mut i0 = x.to_bits() as i64; + let j0 = (((i0 >> 52) & 0x7ff) as i32) - 0x3ff; + let mut x = x; + if j0 < 52 { + if j0 < 0 { + /* return 0 * sign (x) if |x| < 1 */ + if i0 >= 0 { + i0 = 0; + } else if (i0 & 0x7fffffffffffffffi64) != 0 { + i0 = 0xbff0000000000000u64 as i64; + } + } else { + let i = 0x000fffffffffffffi64 >> j0; + if (i0 & i) == 0 { + return x; /* x is integral */ + } + if i0 < 0 { + i0 = i0.wrapping_add((0x0010000000000000u64 >> j0) as i64); + } + i0 &= !i; + } + x = f64::from_bits(i0 as u64); + } else if j0 == 0x400 { + return x + x; /* inf or NaN */ + } + x +} + +pub(crate) trait CpuFloor { + fn cpu_floor(self) -> Self; +} + +impl CpuFloor for f32 { + #[inline] + fn cpu_floor(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.floor() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + floorf(self) + } + } +} + +impl CpuFloor for f64 { + #[inline] + fn cpu_floor(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.floor() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + floor(self) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_floorf() { + assert_eq!(floorf(-1.0), -1.0); + assert_eq!(floorf(1.0), 1.0); + assert_eq!(floorf(0.0), 0.0); + assert_eq!(floorf(0.324), 0.0); + assert_eq!(floorf(-0.324), -1.0); + assert_eq!(floorf(1.234211), 1.0); + assert_eq!(floorf(-1.234211), -2.0); + assert_eq!(floorf(f32::INFINITY), f32::INFINITY); + assert_eq!(floorf(f32::NEG_INFINITY), f32::NEG_INFINITY); + assert!(floorf(f32::NAN).is_nan()); + } + + #[test] + fn test_floor() { + assert_eq!(floor(-1.0), -1.0); + assert_eq!(floor(1.0), 1.0); + assert_eq!(floor(0.0), 0.0); + assert_eq!(floor(0.324), 0.0); + assert_eq!(floor(-0.324), -1.0); + assert_eq!(floor(1.234211), 1.0); + assert_eq!(floor(-1.234211), -2.0); + assert_eq!(floor(f64::INFINITY), f64::INFINITY); + assert_eq!(floor(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert!(floor(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod ceil; +mod floor; +mod rint; +mod rintf; +mod round; +mod round_ties_even; +mod trunc; +mod truncf; + +pub(crate) use ceil::CpuCeil; +pub use ceil::{ceil, ceilf}; +pub(crate) use floor::CpuFloor; +pub use floor::{floor, floorf}; +pub use rint::rint; +pub use rintf::rintf; +pub(crate) use round::CpuRound; +pub use round::{round, roundf}; +pub(crate) use round_ties_even::CpuRoundTiesEven; +pub use round_ties_even::{round_ties_even, roundf_ties_even}; +pub use trunc::trunc; +pub use truncf::truncf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/rint.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rint.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/rint.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rint.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn rint(x: f64) -> f64 { + /* Use generic implementation. */ + static TWO52: [f64; 2] = [ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ + ]; + let mut i0: i64 = x.to_bits() as i64; + let sx = (i0 >> 63) & 1; + let j0: i32 = (((i0 >> 52) & 0x7ff) - 0x3ff) as i32; + if j0 < 52 { + if j0 < 0 { + let w = TWO52[sx as usize] + x; + let t = w - TWO52[sx as usize]; + i0 = t.to_bits() as i64; + let u = (i0 & (0x7fffffffffffffffu64 as i64)) | (sx << 63); + return f64::from_bits(u as u64); + } + } else { + return if j0 == 0x400 { + x + x /* inf or NaN */ + } else { + x /* x is integral */ + }; + } + let w = TWO52[sx as usize] + x; + w - TWO52[sx as usize] +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_rintf() { + assert_eq!(rint(0f64), 0.0f64.round()); + assert_eq!(rint(1f64), 1.0f64.round()); + assert_eq!(rint(1.2f64), 1.2f64.round()); + assert_eq!(rint(-1.2f64), (-1.2f64).round()); + assert_eq!(rint(-1.6f64), (-1.6f64).round()); + assert_eq!(rint(-1.5f64), (-1.5f64).round()); + assert_eq!(rint(1.6f64), 1.6f64.round()); + assert_eq!(rint(1.5f64), 1.5f64.round()); + assert_eq!(rint(2.5f64), 2.0f64); + assert_eq!(rint(3.5f64), 4.0f64); + assert_eq!(rint(-2.5f64), -2.0f64); + assert_eq!(rint(-3.5f64), -4.0f64); + assert_eq!(rint(f64::INFINITY), f64::INFINITY); + assert_eq!(rint(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert!(rint(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/rintf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rintf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/rintf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/rintf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn rintf(x: f32) -> f32 { + /* Use generic implementation. */ + static TWO23: [f32; 2] = [ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ + ]; + let mut i0: i32 = x.to_bits() as i32; + let sx = (i0 >> 31) & 1; + let j0 = ((i0 >> 23) & 0xff) - 0x7f; + if j0 < 23 { + if j0 < 0 { + let w = TWO23[sx as usize] + x; + let t = w - TWO23[sx as usize]; + i0 = t.to_bits() as i32; + let u = (i0 & 0x7fffffff) | (sx << 31); + return f32::from_bits(u as u32); + } + } else { + return if j0 == 0x80 { + x + x /* inf or NaN */ + } else { + x /* x is integral */ + }; + } + let w = TWO23[sx as usize] + x; + w - TWO23[sx as usize] +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_rintf() { + assert_eq!(rintf(0f32), 0.0f32.round()); + assert_eq!(rintf(1f32), 1.0f32.round()); + assert_eq!(rintf(1.2f32), 1.2f32.round()); + assert_eq!(rintf(-1.2f32), (-1.2f32).round()); + assert_eq!(rintf(-1.6f32), (-1.6f32).round()); + assert_eq!(rintf(-1.5f32), (-1.5f32).round()); + assert_eq!(rintf(1.6f32), 1.6f32.round()); + assert_eq!(rintf(1.5f32), 1.5f32.round()); + assert_eq!(rintf(2.5f32), 2.0f32); + assert_eq!(rintf(3.5f32), 4.0f32); + assert_eq!(rintf(-2.5f32), -2.0f32); + assert_eq!(rintf(-3.5f32), -4.0f32); + assert_eq!(rintf(f32::INFINITY), f32::INFINITY); + assert_eq!(rintf(f32::NEG_INFINITY), f32::NEG_INFINITY); + assert!(rintf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/round.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/round.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,189 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn roundf(x: f32) -> f32 { + let mut i0 = x.to_bits() as i32; + let j0 = ((i0 >> 23) & 0xff) - 0x7f; + if j0 < 23 { + if j0 < 0 { + i0 &= 0x80000000u32 as i32; + if j0 == -1 { + i0 |= 0x3f800000; + } + } else { + let i = 0x007fffff >> j0; + if (i0 & i) == 0 { + /* X is integral. */ + return x; + } + + i0 += 0x00400000 >> j0; + i0 &= !i; + } + } else { + return if j0 == 0x80 { + /* Inf or NaN. */ + x + x + } else { + x + }; + } + f32::from_bits(i0 as u32) +} + +// infinity, NaNs are assumed already handled somewhere +#[inline(always)] +pub(crate) fn froundf_finite(x: f32) -> f32 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + x.round() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + roundf(x) + } +} + +#[inline] +pub const fn round(x: f64) -> f64 { + let mut i0: i64 = x.to_bits() as i64; + let j0: i32 = (((i0 >> 52) & 0x7ff) - 0x3ff) as i32; + if j0 < 52 { + if j0 < 0 { + i0 &= 0x8000000000000000u64 as i64; + if j0 == -1 { + i0 |= 0x3ff0000000000000u64 as i64; + } + } else { + let i = (0x000fffffffffffffu64 >> j0) as i64; + if (i0 & i) == 0 { + /* X is integral. */ + return x; + } + + i0 += (0x0008000000000000u64 >> j0) as i64; + i0 &= !i; + } + } else { + return if j0 == 0x400 { + /* Inf or NaN. */ + x + x + } else { + x + }; + } + f64::from_bits(i0 as u64) +} + +// infinity, NaNs are assumed already handled somewhere +#[inline] +pub(crate) fn fround_finite(x: f64) -> f64 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + x.round() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + round(x) + } +} + +pub(crate) trait CpuRound { + fn cpu_round(self) -> Self; +} + +impl CpuRound for f32 { + #[inline(always)] + fn cpu_round(self) -> Self { + froundf_finite(self) + } +} + +impl CpuRound for f64 { + #[inline(always)] + fn cpu_round(self) -> Self { + fround_finite(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_roundf() { + assert_eq!(roundf(0f32), 0.0f32.round()); + assert_eq!(roundf(1f32), 1.0f32.round()); + assert_eq!(roundf(1.2f32), 1.2f32.round()); + assert_eq!(roundf(-1.2f32), (-1.2f32).round()); + assert_eq!(roundf(-1.6f32), (-1.6f32).round()); + assert_eq!(roundf(-1.5f32), (-1.5f32).round()); + assert_eq!(roundf(1.6f32), 1.6f32.round()); + assert_eq!(roundf(1.5f32), 1.5f32.round()); + assert_eq!(roundf(2.5f32), 2.5f32.round()); + } + + #[test] + fn test_round() { + assert_eq!(round(0.), 0.0f64.round()); + assert_eq!(round(1.), 1.0f64.round()); + assert_eq!(round(1.2), 1.2f64.round()); + assert_eq!(round(-1.2), (-1.2f64).round()); + assert_eq!(round(-1.6), (-1.6f64).round()); + assert_eq!(round(-1.5), (-1.5f64).round()); + assert_eq!(round(1.6), 1.6f64.round()); + assert_eq!(round(1.5), 1.5f64.round()); + assert_eq!(round(2.5), 2.5f64.round()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/round_ties_even.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round_ties_even.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/round_ties_even.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/round_ties_even.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +pub const fn roundf_ties_even(x: f32) -> f32 { + const BIAS: i32 = 0x7f; + const MANT_DIG: i32 = 24; + const MAX_EXP: i32 = 2 * BIAS + 1; + let mut ix: u32 = x.to_bits(); + let ux: u32 = ix & 0x7fffffff; + let exponent: i32 = (ux >> (MANT_DIG - 1)) as i32; + if exponent >= BIAS + MANT_DIG - 1 { + /* Integer, infinity or NaN. */ + if exponent == MAX_EXP { + /* Infinity or NaN; quiet signaling NaNs. */ + return x + x; + } else { + return x; + } + } else if exponent >= BIAS { + /* At least 1; not necessarily an integer. Locate the bits with + exponents 0 and -1 (when the unbiased exponent is 0, the bit + with exponent 0 is implicit, but as the bias is odd it is OK + to take it from the low bit of the exponent). */ + let int_pos: i32 = (BIAS + MANT_DIG - 1) - exponent; + let half_pos: i32 = int_pos - 1; + let half_bit: u32 = 1u32 << half_pos; + let int_bit: u32 = 1u32 << int_pos; + if (ix & (int_bit | (half_bit - 1))) != 0 { + /* Carry into the exponent works correctly. No need to test + whether HALF_BIT is set. */ + ix = ix.wrapping_add(half_bit); + } + ix &= !(int_bit - 1); + } else if exponent == BIAS - 1 && ux > 0x3f000000 { + /* Interval (0.5, 1). */ + ix = (ix & 0x80000000) | 0x3f800000; + } else { + /* Rounds to 0. */ + ix &= 0x80000000; + } + f32::from_bits(ix) +} + +pub const fn round_ties_even(x: f64) -> f64 { + let mut ix: u64 = x.to_bits(); + let ux = ix & 0x7fffffffffffffffu64; + const BIAS: i32 = 0x3ff; + const MANT_DIG: i32 = 53; + const MAX_EXP: i32 = 2 * BIAS + 1; + let exponent: i32 = (ux >> (MANT_DIG - 1)) as i32; + if exponent >= BIAS + MANT_DIG - 1 { + /* Integer, infinity or NaN. */ + return if exponent == MAX_EXP { + /* Infinity or NaN; quiet signaling NaNs. */ + x + x + } else { + x + }; + } else if exponent >= BIAS { + /* At least 1; not necessarily an integer. Locate the bits with + exponents 0 and -1 (when the unbiased exponent is 0, the bit + with exponent 0 is implicit, but as the bias is odd it is OK + to take it from the low bit of the exponent). */ + let int_pos: i32 = (BIAS + MANT_DIG - 1) - exponent; + let half_pos: i32 = int_pos - 1; + let half_bit: u64 = 1u64 << half_pos; + let int_bit: u64 = 1u64 << int_pos; + if (ix & (int_bit | (half_bit - 1))) != 0 { + /* Carry into the exponent works correctly. No need to test + whether HALF_BIT is set. */ + ix = ix.wrapping_add(half_bit); + } + ix &= !(int_bit - 1); + } else if exponent == BIAS - 1 && ux > 0x3fe0000000000000u64 { + /* Interval (0.5, 1). */ + ix = (ix & 0x8000000000000000u64) | 0x3ff0000000000000u64; + } else { + /* Rounds to 0. */ + ix &= 0x8000000000000000u64; + } + f64::from_bits(ix) +} + +pub(crate) trait CpuRoundTiesEven { + fn cpu_round_ties_even(self) -> Self; +} + +impl CpuRoundTiesEven for f32 { + #[inline] + fn cpu_round_ties_even(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.round_ties_even() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + roundf_ties_even(self) + } + } +} + +impl CpuRoundTiesEven for f64 { + #[inline] + fn cpu_round_ties_even(self) -> Self { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + ))] + { + self.round_ties_even() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" + ), + target_arch = "aarch64" + )))] + { + round_ties_even(self) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_roundf_ties_even() { + assert_eq!(roundf_ties_even(0f32), 0.0f32.round_ties_even()); + assert_eq!(roundf_ties_even(0.5f32), 0.5f32.round_ties_even()); + assert_eq!(roundf_ties_even(-0.5), (-0.5f32).round_ties_even()); + assert_eq!(roundf_ties_even(1f32), 1.0f32.round_ties_even()); + assert_eq!(roundf_ties_even(1.2f32), 1.2f32.round_ties_even()); + assert_eq!(roundf_ties_even(-1.2f32), (-1.2f32).round_ties_even()); + assert_eq!(roundf_ties_even(-1.6f32), (-1.6f32).round_ties_even()); + assert_eq!(roundf_ties_even(-1.5f32), (-1.5f32).round_ties_even()); + assert_eq!(roundf_ties_even(1.6f32), 1.6f32.round_ties_even()); + assert_eq!(roundf_ties_even(1.5f32), 1.5f32.round_ties_even()); + assert_eq!(roundf_ties_even(2.5f32), 2.5f32.round_ties_even()); + assert_eq!( + roundf_ties_even(f32::INFINITY), + f32::INFINITY.round_ties_even() + ); + assert_eq!( + roundf_ties_even(f32::NEG_INFINITY), + f32::NEG_INFINITY.round_ties_even() + ); + assert!(roundf_ties_even(f32::NAN).is_nan()); + } + + #[test] + fn test_round_ties_even() { + assert_eq!( + round_ties_even(5.6916e-320), + (5.6916e-320f64).round_ties_even() + ); + assert_eq!(round_ties_even(3f64), 3f64.round_ties_even()); + assert_eq!(round_ties_even(2f64), 2f64.round_ties_even()); + assert_eq!(round_ties_even(0.), 0.0f64.round_ties_even()); + assert_eq!(round_ties_even(0.5), 0.5f64.round_ties_even()); + assert_eq!(round_ties_even(-0.5), (-0.5f64).round_ties_even()); + assert_eq!(round_ties_even(1.), 1.0f64.round_ties_even()); + assert_eq!(round_ties_even(1.2), 1.2f64.round_ties_even()); + assert_eq!(round_ties_even(-1.2), (-1.2f64).round_ties_even()); + assert_eq!(round_ties_even(-1.6), (-1.6f64).round_ties_even()); + assert_eq!(round_ties_even(-1.5), (-1.5f64).round_ties_even()); + assert_eq!(round_ties_even(1.6), 1.6f64.round_ties_even()); + assert_eq!(round_ties_even(1.5), 1.5f64.round_ties_even()); + assert_eq!(round_ties_even(2.5), 2.5f64.round_ties_even()); + assert_eq!(round_ties_even(-2.5), (-2.5f64).round_ties_even()); + assert_eq!( + round_ties_even(f64::INFINITY), + f64::INFINITY.round_ties_even() + ); + assert_eq!( + round_ties_even(f64::NEG_INFINITY), + f64::NEG_INFINITY.round_ties_even() + ); + assert!(round_ties_even(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/trunc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/trunc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/trunc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/trunc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn trunc(x: f64) -> f64 { + let i0 = x.to_bits() as i64; + let sx = i0 & (0x8000000000000000u64 as i64); + let j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; + if j0 < 52 { + return if j0 < 0 { + /* The magnitude of the number is < 1 so the result is +-0. */ + f64::from_bits(sx as u64) + } else { + f64::from_bits((sx | (i0 & (!(0x000fffffffffffffu64 >> j0) as i64))) as u64) + }; + } else if j0 == 0x400 { + /* x is inf or NaN. */ + return x + x; + } + + x +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_trunc() { + assert_eq!(trunc(-1.0), -1.0); + assert_eq!(trunc(1.0), 1.0); + assert_eq!(trunc(1.234211), 1.0); + assert_eq!(trunc(-1.234211), -1.0); + assert_eq!(trunc(f64::INFINITY), f64::INFINITY); + assert_eq!(trunc(f64::NEG_INFINITY), f64::NEG_INFINITY); + assert!(trunc(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/truncf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/truncf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/rounding/truncf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/rounding/truncf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#[inline] +pub const fn truncf(x: f32) -> f32 { + let i0 = x.to_bits() as i32; + let sx = i0 & (0x80000000u32 as i32); + let j0 = ((i0 >> 23) & 0xff) - 0x7f; + if j0 < 23 { + return if j0 < 0 { + /* The magnitude of the number is < 1 so the result is +-0. */ + f32::from_bits(sx as u32) + } else { + f32::from_bits((sx | (i0 & !(0x007fffff >> j0))) as u32) + }; + } else if j0 == 0x80 { + /* x is inf or NaN. */ + return x + x; + } + + x +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_truncf() { + assert_eq!(truncf(-1.0), -1.0); + assert_eq!(truncf(1.0), 1.0); + assert_eq!(truncf(1.234211), 1.0); + assert_eq!(truncf(-1.234211), -1.0); + assert_eq!(truncf(f32::INFINITY), f32::INFINITY); + assert_eq!(truncf(f32::NEG_INFINITY), f32::NEG_INFINITY); + assert!(truncf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sec.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,149 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::sin::{get_sin_k_rational, range_reduction_small, sincos_eval}; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_dyadic::{range_reduction_small_f128, sincos_eval_dyadic}; +use crate::sincos_reduce::LargeArgumentReduction; + +#[cold] +fn sec_accurate(x: f64, argument_reduction: &mut LargeArgumentReduction, x_e: u64, k: u64) -> f64 { + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + let u_f128 = if x_e < EXP_BIAS + 16 { + range_reduction_small_f128(x) + } else { + argument_reduction.accurate() + }; + + let sin_cos = sincos_eval_dyadic(&u_f128); + + // -sin(k * pi/128) = sin((k + 128) * pi/128) + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let msin_k_f128 = get_sin_k_rational(k.wrapping_add(128)); + let cos_k_f128 = get_sin_k_rational(k.wrapping_add(64)); + + // cos(x) = cos((k * pi/128 + u) + // = cos(u) * cos(k*pi/128) - sin(u) * sin(k*pi/128) + let r = (cos_k_f128 * sin_cos.v_cos) + (msin_k_f128 * sin_cos.v_sin); + r.reciprocal().fast_as_f64() +} + +/// Secant for double precision +/// +/// ULP 0.5 +pub fn f_sec(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + if x_e < E_BIAS + 16 { + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS - 7 { + // |x| < 2^-7 + if x_e < E_BIAS - 27 { + // |x| < 2^-27 + if x == 0.0 { + // Signed zeros. + return 1.0; + } + // taylor series for sec(x) ~ 1 + x^2/2 + O(x^4) + return f_fmla(x, x * 0.5, 1.); + } + k = 0; + y = DoubleDouble::new(0.0, x); + } else { + // Small range reduction. + (y, k) = range_reduction_small(x); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sec(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + let r_sincos = sincos_eval(y); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k.wrapping_add(128) & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + let msin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let cos_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, cos_k); + let cos_k_msin_y = DoubleDouble::quick_mult(r_sincos.v_sin, msin_k); + + // cos_k_cos_y is always >> cos_k_msin_y + let mut rr = DoubleDouble::from_exact_add(cos_k_cos_y.hi, cos_k_msin_y.hi); + rr.lo += cos_k_cos_y.lo + cos_k_msin_y.lo; + + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = rr.recip(); + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + + sec_accurate(x, &mut argument_reduction, x_e, k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sec() { + assert_eq!(f_sec(-175432.), 1.461049620895326); + assert_eq!(f_sec(175432.), 1.461049620895326); + assert_eq!(f_sec(-10.), -1.1917935066878957); + assert_eq!(f_sec(10.), -1.1917935066878957); + assert_eq!(f_sec(5.), 3.5253200858160882); + assert_eq!(f_sec(-5.), 3.5253200858160882); + assert_eq!(f_sec(0.), 1.0); + assert!(f_sec(f64::NAN).is_nan()); + assert!(f_sec(f64::INFINITY).is_nan()); + assert!(f_sec(f64::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/shared_eval.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/shared_eval.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/shared_eval.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/shared_eval.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; + +#[inline] +pub(crate) fn poly_dd_3(x: DoubleDouble, poly: [(u64, u64); 3], l: f64) -> DoubleDouble { + let zch = poly[2]; + let ach = f64::from_bits(zch.0) + l; + let acl = (f64::from_bits(zch.0) - ach) + l + f64::from_bits(zch.1); + let mut ch = DoubleDouble::new(acl, ach); + + let zch = poly[1]; + ch = DoubleDouble::quick_mult(ch, x); + let th = ch.hi + f64::from_bits(zch.0); + let tl = (f64::from_bits(zch.0) - th) + ch.hi; + ch.hi = th; + ch.lo += tl + f64::from_bits(zch.1); + + let zch = poly[0]; + ch = DoubleDouble::quick_mult(ch, x); + let th = ch.hi + f64::from_bits(zch.0); + let tl = (f64::from_bits(zch.0) - th) + ch.hi; + ch.hi = th; + ch.lo += tl + f64::from_bits(zch.1); + + ch +} + +#[inline] +pub(crate) fn poly_dekker_generic( + x: DoubleDouble, + poly: [(u64, u64); N], +) -> DoubleDouble { + let zch = poly.last().unwrap(); + let ach = f64::from_bits(zch.0); + let acl = f64::from_bits(zch.1); + let mut ch = DoubleDouble::new(acl, ach); + + for zch in poly.iter().rev().skip(1) { + ch = DoubleDouble::quick_mult(ch, x); + let th = ch.hi + f64::from_bits(zch.0); + let tl = (f64::from_bits(zch.0) - th) + ch.hi; + ch.hi = th; + ch.lo += tl + f64::from_bits(zch.1); + } + + ch +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,524 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dyad_fmla, f_fmla, min_normal_f64}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; +use crate::sin_helper::sincos_eval_dd; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_dyadic::SIN_K_PI_OVER_128_F128; +use crate::sincos_reduce::LargeArgumentReduction; + +// For 2^-7 < |x| < 2^16, return k and u such that: +// k = round(x * 128/pi) +// x mod pi/128 = x - k * pi/128 ~ u.hi + u.lo +// Error bound: +// |(x - k * pi/128) - (u_hi + u_lo)| <= max(ulp(ulp(u_hi)), 2^-119) +// <= 2^-111. +#[inline] +pub(crate) fn range_reduction_small(x: f64) -> (DoubleDouble, u64) { + const MPI_OVER_128: [u64; 3] = [0xbf9921fb54400000, 0xbd70b4611a600000, 0xbb43198a2e037073]; + const ONE_TWENTY_EIGHT_OVER_PI_D: f64 = f64::from_bits(0x40445f306dc9c883); + let prod_hi = x * ONE_TWENTY_EIGHT_OVER_PI_D; + let kd = prod_hi.cpu_round(); + + // Let y = x - k * (pi/128) + // Then |y| < pi / 256 + // With extra rounding errors, we can bound |y| < 1.6 * 2^-7. + let y_hi = f_fmla(kd, f64::from_bits(MPI_OVER_128[0]), x); // Exact + // |u.hi| < 1.6*2^-7 + let u_hi = f_fmla(kd, f64::from_bits(MPI_OVER_128[1]), y_hi); + + let u0 = y_hi - u_hi; // Exact + // |u.lo| <= max(ulp(u.hi), |kd * MPI_OVER_128[2]|) + let u1 = f_fmla(kd, f64::from_bits(MPI_OVER_128[1]), u0); // Exact + let u_lo = f_fmla(kd, f64::from_bits(MPI_OVER_128[2]), u1); + // Error bound: + // |x - k * pi/128| - (u.hi + u.lo) <= ulp(u.lo) + // <= ulp(max(ulp(u.hi), kd*MPI_OVER_128[2])) + // <= 2^(-7 - 104) = 2^-111. + (DoubleDouble::new(u_lo, u_hi), unsafe { + kd.to_int_unchecked::() as u64 // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) +} + +#[inline] +pub(crate) fn get_sin_k_rational(kk: u64) -> DyadicFloat128 { + let idx = if (kk & 64) != 0 { + 64 - (kk & 63) + } else { + kk & 63 + }; + let mut ans = SIN_K_PI_OVER_128_F128[idx as usize]; + if (kk & 128) != 0 { + ans.sign = DyadicSign::Neg; + } + ans +} + +pub(crate) struct SinCos { + pub(crate) v_sin: DoubleDouble, + pub(crate) v_cos: DoubleDouble, + pub(crate) err: f64, +} + +#[inline] +pub(crate) fn sincos_eval(u: DoubleDouble) -> SinCos { + // Evaluate sin(y) = sin(x - k * (pi/128)) + // We use the degree-7 Taylor approximation: + // sin(y) ~ y - y^3/3! + y^5/5! - y^7/7! + // Then the error is bounded by: + // |sin(y) - (y - y^3/3! + y^5/5! - y^7/7!)| < |y|^9/9! < 2^-54/9! < 2^-72. + // For y ~ u_hi + u_lo, fully expanding the polynomial and drop any terms + // < ulp(u_hi^3) gives us: + // y - y^3/3! + y^5/5! - y^7/7! = ... + // ~ u_hi + u_hi^3 * (-1/6 + u_hi^2 * (1/120 - u_hi^2 * 1/5040)) + + // + u_lo (1 + u_hi^2 * (-1/2 + u_hi^2 / 24)) + let u_hi_sq = u.hi * u.hi; // Error < ulp(u_hi^2) < 2^(-6 - 52) = 2^-58. + // p1 ~ 1/120 + u_hi^2 / 5040. + let p1 = f_fmla( + u_hi_sq, + f64::from_bits(0xbf2a01a01a01a01a), + f64::from_bits(0x3f81111111111111), + ); + // q1 ~ -1/2 + u_hi^2 / 24. + let q1 = f_fmla( + u_hi_sq, + f64::from_bits(0x3fa5555555555555), + f64::from_bits(0xbfe0000000000000), + ); + let u_hi_3 = u_hi_sq * u.hi; + // p2 ~ -1/6 + u_hi^2 (1/120 - u_hi^2 * 1/5040) + let p2 = f_fmla(u_hi_sq, p1, f64::from_bits(0xbfc5555555555555)); + // q2 ~ 1 + u_hi^2 (-1/2 + u_hi^2 / 24) + let q2 = f_fmla(u_hi_sq, q1, 1.0); + let sin_lo = f_fmla(u_hi_3, p2, u.lo * q2); + // Overall, |sin(y) - (u_hi + sin_lo)| < 2*ulp(u_hi^3) < 2^-69. + + // Evaluate cos(y) = cos(x - k * (pi/128)) + // We use the degree-8 Taylor approximation: + // cos(y) ~ 1 - y^2/2 + y^4/4! - y^6/6! + y^8/8! + // Then the error is bounded by: + // |cos(y) - (...)| < |y|^10/10! < 2^-81 + // For y ~ u_hi + u_lo, fully expanding the polynomial and drop any terms + // < ulp(u_hi^3) gives us: + // 1 - y^2/2 + y^4/4! - y^6/6! + y^8/8! = ... + // ~ 1 - u_hi^2/2 + u_hi^4(1/24 + u_hi^2 (-1/720 + u_hi^2/40320)) + + // + u_hi u_lo (-1 + u_hi^2/6) + // We compute 1 - u_hi^2 accurately: + // v_hi + v_lo ~ 1 - u_hi^2/2 + // with error <= 2^-105. + let u_hi_neg_half = (-0.5) * u.hi; + + let (mut v_lo, v_hi); + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + v_hi = f_fmla(u.hi, u_hi_neg_half, 1.0); + v_lo = 1.0 - v_hi; // Exact + v_lo = f_fmla(u.hi, u_hi_neg_half, v_lo); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let u_hi_sq_neg_half = DoubleDouble::from_exact_mult(u.hi, u_hi_neg_half); + let v = DoubleDouble::from_exact_add(1.0, u_hi_sq_neg_half.hi); + v_lo = v.lo; + v_lo += u_hi_sq_neg_half.lo; + v_hi = v.hi; + } + + // r1 ~ -1/720 + u_hi^2 / 40320 + let r1 = f_fmla( + u_hi_sq, + f64::from_bits(0x3efa01a01a01a01a), + f64::from_bits(0xbf56c16c16c16c17), + ); + // s1 ~ -1 + u_hi^2 / 6 + let s1 = f_fmla(u_hi_sq, f64::from_bits(0x3fc5555555555555), -1.0); + let u_hi_4 = u_hi_sq * u_hi_sq; + let u_hi_u_lo = u.hi * u.lo; + // r2 ~ 1/24 + u_hi^2 (-1/720 + u_hi^2 / 40320) + let r2 = f_fmla(u_hi_sq, r1, f64::from_bits(0x3fa5555555555555)); + // s2 ~ v_lo + u_hi * u_lo * (-1 + u_hi^2 / 6) + let s2 = f_fmla(u_hi_u_lo, s1, v_lo); + let cos_lo = f_fmla(u_hi_4, r2, s2); + // Overall, |cos(y) - (v_hi + cos_lo)| < 2*ulp(u_hi^4) < 2^-75. + + let sin_u = DoubleDouble::from_exact_add(u.hi, sin_lo); + let cos_u = DoubleDouble::from_exact_add(v_hi, cos_lo); + + let err = f_fmla( + u_hi_3, + f64::from_bits(0x3cc0000000000000), + f64::from_bits(0x3960000000000000), + ); + + SinCos { + v_sin: sin_u, + v_cos: cos_u, + err, + } +} + +#[cold] +#[inline(never)] +fn sin_accurate(y: DoubleDouble, sin_k: DoubleDouble, cos_k: DoubleDouble) -> f64 { + let r_sincos = sincos_eval_dd(y); + + // k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + let rr = DoubleDouble::full_dd_add(sin_k_cos_y, cos_k_sin_y); + rr.to_f64() +} + +#[cold] +pub(crate) fn sin_accurate_near_zero(x: f64) -> f64 { + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_sin = sin(y)/y; + // Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10, 12|], [|107...|], d, relative, floating); + const C: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc65555555555217, 0xbfc5555555555555), + (0x3c011110f7d49e8c, 0x3f81111111111111), + (0xbb65e5b30986fc80, 0xbf2a01a01a01a01a), + (0xbb689e86245bd566, 0x3ec71de3a556c6e5), + (0xbaccb3d55ccfca58, 0xbe5ae64567954935), + (0x3a6333ef7a00ce40, 0x3de6120ca00ce3a2), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[6]), + DoubleDouble::from_bit_pair(C[5]), + ); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::quick_mul_add_f64(x2, p, f64::from_bits(0x3ff0000000000000)); + p = DoubleDouble::quick_mult_f64(p, x); + p.to_f64() +} + +/// Sine for double precision +/// +/// ULP 0.5 +pub fn f_sin(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + if x_e < E_BIAS + 16 { + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + if ax <= 0x3fa921fbd34a9550 { + // |x| <= 0.0490874 + if x_e < E_BIAS - 26 { + // |x| < 2^-26 + if x == 0.0 { + // Signed zeros. + return x; + } + + // For |x| < 2^-26, |sin(x) - x| < ulp(x)/2. + return dyad_fmla(x, f64::from_bits(0xbc90000000000000), x); + } + + // Polynomial for sin(x)/x + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_sin = sin(y)/y; + // Q = fpminimax(f_sin, [|0, 2, 4, 6, 8|], [|1, D...|], d, relative, floating); + + let x2 = x * x; + let x4 = x2 * x2; + const C: [u64; 4] = [ + 0xbfc5555555555555, + 0x3f8111111110e45a, + 0xbf2a019ffd7fdaaf, + 0x3ec71819b9bf01ef, + ]; + let p01 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let p23 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let w0 = f_fmla(x4, p23, p01); + let w1 = x2 * w0 * x; + let r = DoubleDouble::from_exact_add(x, w1); + let err = f_fmla( + x2, + f64::from_bits(0x3cb0000000000000), // 2^-52 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return ub; + } + return sin_accurate_near_zero(x); + } + + // Small range reduction. + (y, k) = range_reduction_small(x); + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sin(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let r_sincos = sincos_eval(y); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + + sin_accurate(y, sin_k, cos_k) +} + +#[cold] +#[inline(never)] +fn cos_accurate(y: DoubleDouble, msin_k: DoubleDouble, cos_k: DoubleDouble) -> f64 { + let r_sincos = sincos_eval_dd(y); + + // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128). + // So k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, cos_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, msin_k); + + let rr = DoubleDouble::full_dd_add(sin_k_cos_y, cos_k_sin_y); + rr.to_f64() +} + +#[cold] +pub(crate) fn cos_accurate_near_zero(x: f64) -> f64 { + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_sin = sin(y)/y; + // Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|107...|], d, relative, floating); + const C: [(u64, u64); 6] = [ + (0xba2fa1c000000000, 0x3ff0000000000000), + (0x3b1cd6ead3800000, 0xbfe0000000000000), + (0x3c45112931063916, 0x3fa5555555555555), + (0xbba1c1e3ab3b09e0, 0xbf56c16c16c16b2b), + (0x3b937bc2f4ea7db6, 0x3efa01a019495fca), + (0x3b307fd5e1b021b3, 0xbe927e0d57d894f8), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[5]), + DoubleDouble::from_bit_pair(C[4]), + ); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p.to_f64() +} + +/// Cosine for double precision +/// +/// ULP 0.5 +pub fn f_cos(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + if x_e < E_BIAS + 16 { + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + if ax <= 0x3fa921fbd34a9550 { + // |x| <= 0.0490874 + if x_e < E_BIAS - 27 { + // |x| < 2^-27 + if x == 0.0 { + // Signed zeros. + return 1.0; + } + // For |x| < 2^-26, |sin(x) - x| < ulp(x)/2. + return 1.0 - min_normal_f64(); + } + + // Polynomial for cos(x) + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_cos = cos(y); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|1, D...|], d, relative, floating); + + let x2 = x * x; + let x4 = x2 * x2; + const C: [u64; 4] = [ + 0xbfe0000000000000, + 0x3fa55555555554a4, + 0xbf56c16c1619b84a, + 0x3efa013d3d01cf7f, + ]; + let p01 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let p23 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let w0 = f_fmla(x4, p23, p01); + let w1 = x2 * w0; + let r = DoubleDouble::from_exact_add(1., w1); + let err = f_fmla( + x2, + f64::from_bits(0x3cb0000000000000), // 2^-52 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return ub; + } + return cos_accurate_near_zero(x); + } else { + // // Small range reduction. + (y, k) = range_reduction_small(x); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // cos(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + let r_sincos = sincos_eval(y); + + // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128). + // So k is an integer and -pi / 256 <= y <= pi / 256. + // Then cos(x) = cos((k * pi/128 + y) + // = cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128) + let sk = SIN_K_PI_OVER_128[(k.wrapping_add(128) & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + let msin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let cos_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, cos_k); + let cos_k_msin_y = DoubleDouble::quick_mult(r_sincos.v_sin, msin_k); + + // cos_k_cos_y is always >> cos_k_msin_y + let mut rr = DoubleDouble::from_exact_add(cos_k_cos_y.hi, cos_k_msin_y.hi); + rr.lo += cos_k_cos_y.lo + cos_k_msin_y.lo; + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + cos_accurate(y, msin_k, cos_k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cos_test() { + assert_eq!(f_cos(0.0), 1.0); + assert_eq!(f_cos(0.0024312312), 0.9999970445588818); + assert_eq!(f_cos(1.0), 0.5403023058681398); + assert_eq!(f_cos(-0.5), 0.8775825618903728); + assert!(f_cos(f64::INFINITY).is_nan()); + assert!(f_cos(f64::NEG_INFINITY).is_nan()); + assert!(f_cos(f64::NAN).is_nan()); + } + + #[test] + fn sin_test() { + assert_eq!(f_sin(0.00000002149119332890786), 0.00000002149119332890786); + assert_eq!(f_sin(2.8477476437362989E-306), 2.8477476437362989E-306); + assert_eq!(f_sin(0.0024312312), 0.002431228804879309); + assert_eq!(f_sin(0.0), 0.0); + assert_eq!(f_sin(1.0), 0.8414709848078965); + assert_eq!(f_sin(-0.5), -0.479425538604203); + assert!(f_sin(f64::INFINITY).is_nan()); + assert!(f_sin(f64::NEG_INFINITY).is_nan()); + assert!(f_sin(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,434 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::get_exponent_f32; +use crate::common::f_fmla; +use crate::rounding::CpuRound; + +#[derive(Debug, Copy, Clone)] +pub(crate) struct ArgumentReducer { + pub(crate) x: f64, + pub(crate) x_abs: u32, +} + +impl ArgumentReducer { + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + #[inline] + pub(crate) fn reduce_small(self) -> (f64, i64) { + /* + Generated in SageMath: + z = RealField(300)(32) / RealField(300).pi() + n = 53 + x_hi = RealField(n)(z) # convert to f64 + x_mid = RealField(n)(z - RealField(300)(x_hi)) + x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + print(double_to_hex(x_hi), ",") + print(double_to_hex(x_mid), ",") + print(double_to_hex(x_lo), ",") + */ + const THIRTYTWO_OVER_PI: [u64; 3] = + [0x40245f306dc9c883, 0xbcc6b01ec5417056, 0xb966447e493ad4ce]; + + let kd = (self.x * f64::from_bits(THIRTYTWO_OVER_PI[0])).cpu_round(); + let mut y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[0]), -kd); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), y); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + #[inline(always)] + pub(crate) fn reduce_small(self) -> (f64, i64) { + /* + Generated in SageMath: + z = RealField(300)(32) / RealField(300).pi() + n = 28 + x_hi = RealField(n)(z) # convert to f64 + x_mid = RealField(n)(z - RealField(300)(x_hi)) + x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + print(double_to_hex(x_hi), ",") + print(double_to_hex(x_mid), ",") + print(double_to_hex(x_lo), ",") + */ + const THIRTYTWO_OVER_PI: [u64; 3] = + [0x40245f306e000000, 0xbe3b1bbeae000000, 0x3c63f84eb0000000]; + let prod = self.x * f64::from_bits(THIRTYTWO_OVER_PI[0]); + let kd = prod.cpu_round(); + let mut y = prod - kd; + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), y); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[2]), y); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + #[inline(always)] + pub(crate) fn reduce_small_fma(self) -> (f64, i64) { + /* + Generated in SageMath: + z = RealField(300)(32) / RealField(300).pi() + n = 53 + x_hi = RealField(n)(z) # convert to f64 + x_mid = RealField(n)(z - RealField(300)(x_hi)) + x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + print(double_to_hex(x_hi), ",") + print(double_to_hex(x_mid), ",") + print(double_to_hex(x_lo), ",") + */ + const THIRTYTWO_OVER_PI: [u64; 3] = + [0x40245f306dc9c883, 0xbcc6b01ec5417056, 0xb966447e493ad4ce]; + + let kd = (self.x * f64::from_bits(THIRTYTWO_OVER_PI[0])).round(); + let mut y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[0]), -kd); + y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), y); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + #[inline] + pub(crate) fn reduce_large(self, exponent: i32) -> (f64, i64) { + /* + Generated in SageMath: + z = RealField(300)(32) / RealField(300).pi() + n = 53 + x_hi = RealField(n)(z) # convert to f64 + x_mid = RealField(n)(z - RealField(300)(x_hi)) + x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + x_lo_2 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo)) + x_lo_3 = z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2) + print(double_to_hex(x_hi), ",") + print(double_to_hex(x_mid), ",") + print(double_to_hex(x_lo), ",") + print(double_to_hex(x_lo_2), ",") + print(double_to_hex(x_lo_3), ",") + */ + const THIRTYTWO_OVER_PI: [u64; 5] = [ + 0x40245f306dc9c883, + 0xbcc6b01ec5417056, + 0xb966447e493ad4ce, + 0x360e21c820ff28b2, + 0xb29508510ea79237, + ]; + + // 2^45 <= |x| < 2^99 + if exponent < 99 { + // - When x < 2^99, the full exact product of x * THIRTYTWO_OVER_PI[0] + // contains at least one integral bit <= 2^5. + // - When 2^45 <= |x| < 2^55, the lowest 6 unit bits are contained + // in the last 12 bits of double(x * THIRTYTWO_OVER_PI[0]). + // - When |x| >= 2^55, the LSB of double(x * THIRTYTWO_OVER_PI[0]) is at + // least 2^6. + let mut prod_hi = self.x * f64::from_bits(THIRTYTWO_OVER_PI[0]); + prod_hi = f64::from_bits( + prod_hi.to_bits() + & (if exponent < 55 { + 0xfffffffffffff000 + } else { + 0xffffffffffffffff + }), + ); // |x| < 2^55 + let k_hi = prod_hi.cpu_round(); + let truncated_prod = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[0]), -k_hi); + let prod_lo = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), truncated_prod); + let k_lo = prod_lo.cpu_round(); + let mut y = f_fmla( + self.x, + f64::from_bits(THIRTYTWO_OVER_PI[1]), + truncated_prod - k_lo, + ); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[2]), y); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[3]), y); + + return (y, k_lo as i64); + } + + // - When x >= 2^110, the full exact product of x * THIRTYTWO_OVER_PI[0] does + // not contain any of the lowest 6 unit bits, so we can ignore it completely. + // - When 2^99 <= |x| < 2^110, the lowest 6 unit bits are contained + // in the last 12 bits of double(x * THIRTYTWO_OVER_PI[1]). + // - When |x| >= 2^110, the LSB of double(x * THIRTYTWO_OVER_PI[1]) is at + // least 64. + let mut prod_hi = self.x * f64::from_bits(THIRTYTWO_OVER_PI[1]); + prod_hi = f64::from_bits( + prod_hi.to_bits() + & (if exponent < 110 { + 0xfffffffffffff000 + } else { + 0xffffffffffffffff + }), + ); // |x| < 2^110 + let k_hi = prod_hi.cpu_round(); + let truncated_prod = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), -k_hi); + let prod_lo = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[2]), truncated_prod); + let k_lo = prod_lo.cpu_round(); + let mut y = f_fmla( + self.x, + f64::from_bits(THIRTYTWO_OVER_PI[2]), + truncated_prod - k_lo, + ); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[3]), y); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[4]), y); + + (y, k_lo as i64) + } + + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[inline(always)] + #[allow(unused)] + pub(crate) fn reduce_large_fma(self, exponent: i32) -> (f64, i64) { + /* + Generated in SageMath: + z = RealField(300)(32) / RealField(300).pi() + n = 53 + x_hi = RealField(n)(z) # convert to f64 + x_mid = RealField(n)(z - RealField(300)(x_hi)) + x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + x_lo_2 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo)) + x_lo_3 = z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2) + print(double_to_hex(x_hi), ",") + print(double_to_hex(x_mid), ",") + print(double_to_hex(x_lo), ",") + print(double_to_hex(x_lo_2), ",") + print(double_to_hex(x_lo_3), ",") + */ + const THIRTYTWO_OVER_PI: [u64; 5] = [ + 0x40245f306dc9c883, + 0xbcc6b01ec5417056, + 0xb966447e493ad4ce, + 0x360e21c820ff28b2, + 0xb29508510ea79237, + ]; + + // 2^45 <= |x| < 2^99 + if exponent < 99 { + // - When x < 2^99, the full exact product of x * THIRTYTWO_OVER_PI[0] + // contains at least one integral bit <= 2^5. + // - When 2^45 <= |x| < 2^55, the lowest 6 unit bits are contained + // in the last 12 bits of double(x * THIRTYTWO_OVER_PI[0]). + // - When |x| >= 2^55, the LSB of double(x * THIRTYTWO_OVER_PI[0]) is at + // least 2^6. + let mut prod_hi = self.x * f64::from_bits(THIRTYTWO_OVER_PI[0]); + prod_hi = f64::from_bits( + prod_hi.to_bits() + & (if exponent < 55 { + 0xfffffffffffff000 + } else { + 0xffffffffffffffff + }), + ); // |x| < 2^55 + let k_hi = prod_hi.round(); + let truncated_prod = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[0]), -k_hi); + let prod_lo = + f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), truncated_prod); + let k_lo = prod_lo.round(); + let mut y = f64::mul_add( + self.x, + f64::from_bits(THIRTYTWO_OVER_PI[1]), + truncated_prod - k_lo, + ); + y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[2]), y); + y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[3]), y); + + return (y, k_lo as i64); + } + + // - When x >= 2^110, the full exact product of x * THIRTYTWO_OVER_PI[0] does + // not contain any of the lowest 6 unit bits, so we can ignore it completely. + // - When 2^99 <= |x| < 2^110, the lowest 6 unit bits are contained + // in the last 12 bits of double(x * THIRTYTWO_OVER_PI[1]). + // - When |x| >= 2^110, the LSB of double(x * THIRTYTWO_OVER_PI[1]) is at + // least 64. + let mut prod_hi = self.x * f64::from_bits(THIRTYTWO_OVER_PI[1]); + prod_hi = f64::from_bits( + prod_hi.to_bits() + & (if exponent < 110 { + 0xfffffffffffff000 + } else { + 0xffffffffffffffff + }), + ); // |x| < 2^110 + let k_hi = prod_hi.round(); + let truncated_prod = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[1]), -k_hi); + let prod_lo = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[2]), truncated_prod); + let k_lo = prod_lo.round(); + let mut y = f64::mul_add( + self.x, + f64::from_bits(THIRTYTWO_OVER_PI[2]), + truncated_prod - k_lo, + ); + y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[3]), y); + y = f64::mul_add(self.x, f64::from_bits(THIRTYTWO_OVER_PI[4]), y); + + (y, k_lo as i64) + } + + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + #[inline] + pub(crate) fn reduce_large(self, exponent: i32) -> (f64, i64) { + // For large range, there are at most 2 parts of THIRTYTWO_OVER_PI_28 + // contributing to the lowest 6 binary digits (k & 63). If the least + // significant bit of x * the least significant bit of THIRTYTWO_OVER_PI_28[i] + // >= 64, we can completely ignore THIRTYTWO_OVER_PI_28[i]. + + // Generated by SageMath: + // z = RealField(300)(32) / RealField(300).pi() + // n = 28 + // x_hi = RealField(n)(z) # convert to f64 + // x_mid = RealField(n)(z - RealField(300)(x_hi)) + // x_lo = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid)) + // x_lo_2 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo)) + // x_lo_3 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2)) + // x_lo_4 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2) - RealField(300)(x_lo_3)) + // x_lo_5 = RealField(n)(z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2) - RealField(300)(x_lo_3) - RealField(300)(x_lo_4)) + // x_lo_6 = (z - RealField(300)(x_hi) - RealField(300)(x_mid) - RealField(300)(x_lo) - RealField(300)(x_lo_2) - RealField(300)(x_lo_3) - RealField(300)(x_lo_4) - RealField(300)(x_lo_5)) + // + // + // print(double_to_hex(x_hi), ",") + // print(double_to_hex(x_mid), ",") + // print(double_to_hex(x_lo), ",") + // print(double_to_hex(x_lo_2), ",") + // print(double_to_hex(x_lo_3), ",") + // print(double_to_hex(x_lo_4), ",") + // print(double_to_hex(x_lo_5), ",") + // print(double_to_hex(x_lo_6), ",") + static THIRTYTWO_OVER_PI: [u64; 8] = [ + 0x40245f306e000000, + 0xbe3b1bbeae000000, + 0x3c63f84eb0000000, + 0xba87056592000000, + 0x38bc0db62a000000, + 0xb6e4cd8778000000, + 0xb51bef806c000000, + 0x33363abdebbc561b, + ]; + + let mut idx = 0; + const FRACTION_LEN: i32 = 23; + let x_lsb_exp_m4 = exponent - FRACTION_LEN; + + // Exponents of the least significant bits of the corresponding entries in + // THIRTYTWO_OVER_PI_28. + static THIRTYTWO_OVER_PI_28_LSB_EXP: [i32; 8] = + [-24, -55, -81, -114, -143, -170, -200, -230]; + + // Skipping the first parts of 32/pi such that: + // LSB of x * LSB of THIRTYTWO_OVER_PI_28[i] >= 32. + while x_lsb_exp_m4 + THIRTYTWO_OVER_PI_28_LSB_EXP[idx] > 5 { + idx += 1; + } + + let prod_hi = self.x * f64::from_bits(THIRTYTWO_OVER_PI[idx]); + // Get the integral part of x * THIRTYTWO_OVER_PI_28[idx] + let k_hi = prod_hi.cpu_round(); + // Get the fractional part of x * THIRTYTWO_OVER_PI_28[idx] + let frac = prod_hi - k_hi; + let prod_lo = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[idx + 1]), frac); + let k_lo = prod_lo.cpu_round(); + + // Now y is the fractional parts. + let mut y = prod_lo - k_lo; + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[idx + 2]), y); + y = f_fmla(self.x, f64::from_bits(THIRTYTWO_OVER_PI[idx + 3]), y); + + (y, (k_hi as i64).wrapping_add(k_lo as i64)) + } + + #[inline(always)] + pub(crate) fn reduce(self) -> (f64, i64) { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + const SMALL_PASS_BOUND: u32 = 0x5600_0000u32; + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + const SMALL_PASS_BOUND: u32 = 0x4a80_0000u32; + if self.x_abs < SMALL_PASS_BOUND { + // 2^45 + self.reduce_small() + } else { + self.reduce_large(get_exponent_f32(f32::from_bits(self.x_abs))) + } + } + + #[inline(always)] + #[allow(unused)] + pub(crate) fn reduce_fma(self) -> (f64, i64) { + const SMALL_PASS_BOUND: u32 = 0x5600_0000u32; + if self.x_abs < SMALL_PASS_BOUND { + // 2^45 + self.reduce_small_fma() + } else { + self.reduce_large_fma(get_exponent_f32(f32::from_bits(self.x_abs))) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction_pi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction_pi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction_pi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/argument_reduction_pi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::rounding::CpuRound; + +#[derive(Debug, Copy, Clone)] +pub(crate) struct ArgumentReducerPi { + pub(crate) x: f64, +} + +impl ArgumentReducerPi { + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[inline(always)] + pub(crate) fn reduce(self) -> (f64, i64) { + let kd = (self.x * 32.).cpu_round(); + let y = f_fmla(self.x, 32.0, -kd); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // Return k and y, where + // k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + #[inline(always)] + #[allow(unused)] + pub(crate) fn reduce_fma(self) -> (f64, i64) { + let kd = (self.x * 32.).round(); + let y = f64::mul_add(self.x, 32.0, -kd); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // Return k and y, where + // k = round(x * 2 / pi) and y = (x * 2 / pi) - k. + #[inline(always)] + pub(crate) fn reduce_0p25(self) -> (f64, i64) { + let kd = (self.x + self.x).cpu_round(); + let y = f_fmla(kd, -0.5, self.x); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // Return k and y, where + // k = round(x * 2 / pi) and y = (x * 2 / pi) - k. + #[inline(always)] + #[allow(unused)] + pub(crate) fn reduce_0p25_fma(self) -> (f64, i64) { + let kd = (self.x + self.x).round(); + let y = f64::mul_add(kd, -0.5, self.x); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) + } + + // + // // Return k and y, where + // // k = round(x * 2 / pi) and y = (x * 2 / pi) - k. + // #[inline] + // pub(crate) fn reduce_0p10(self) -> (f64, i64) { + // let kd = (self.x * 4.).round(); + // let y = f_fmla(kd, -0.25, self.x); + // (y, kd as i64) + // } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,208 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +#[inline(always)] +fn cosf_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, f32::from_bits(0xb3000000), 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + return f_fmla(xd, f64::from_bits(0xbe60000000000000), 1.) as f32; + } + } + + // Cosine + // Generated poly by Sollya: + // f_cos_16 = cos(x); + // + // Q = fpminimax(f_cos_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + // See ./notes/cosf.sollya + + let x2 = xd * xd; + let p = f_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfdffffffffffcea), + f64::from_bits(0x3fa55555553d611a), + f64::from_bits(0xbf56c16b2e26561a), + f64::from_bits(0x3ef9faa67b9da80b), + ); + return p as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + + let rs = sincosf_eval(xd, x_abs); + f_fmla(rs.sin_y, -rs.sin_k, f_fmla(rs.cosm1_y, rs.cos_k, rs.cos_k)) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cosf_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + return f32::mul_add(x, f32::from_bits(0xb3000000), 1.); + } + + // Cosine + // Generated poly by Sollya: + // f_cos_16 = cos(x); + // + // Q = fpminimax(f_cos_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + // See ./notes/cosf.sollya + + let x2 = xd * xd; + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfdffffffffffcea), + f64::from_bits(0x3fa55555553d611a), + f64::from_bits(0xbf56c16b2e26561a), + f64::from_bits(0x3ef9faa67b9da80b), + ); + return p as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + use crate::sin_cosf::sincosf_eval::sincosf_eval_fma; + let rs = sincosf_eval_fma(xd, x_abs); + f64::mul_add( + rs.sin_y, + -rs.sin_k, + f64::mul_add(rs.cosm1_y, rs.cos_k, rs.cos_k), + ) as f32 +} + +/// Computes cosine function +/// +/// ULP 0.5 +/// +#[inline] +pub fn f_cosf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cosf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cosf_fma_impl + } else { + cosf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_cosf_test() { + assert_eq!(f_cosf(0.0), 1.0); + assert_eq!(f_cosf(std::f32::consts::PI), -1f32); + assert_eq!(f_cosf(0.5), 0.87758255); + assert_eq!(f_cosf(0.7), 0.7648422); + assert_eq!(f_cosf(1.7), -0.12884454); + assert!(f_cosf(f32::INFINITY).is_nan()); + assert!(f_cosf(f32::NEG_INFINITY).is_nan()); + assert!(f_cosf(f32::NAN).is_nan()); + assert_eq!(f_cosf(0.0002480338), 0.9999999692396206); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosm1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosm1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosm1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cosm1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval4; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +/// Computes cos(x) - 1 +/// +/// ULP 0.5 +pub fn f_cosm1f(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + let xd = x as f64; + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + // Taylor expansion for small cos(x) - 1 ~ -x^2/2 + x^4/24 + O(x^6) + let x_sqr = xd * xd; + const R: f64 = 1. / 2.; + return (-x_sqr * R) as f32; + } + + // Cosine + // Generated poly by Sollya: + // Polynomial cos(x) - 1 = x^2 * P(x^2) + // + // d = [0.0000000000001, pi/16]; + // f_cosm1 = cos(x) - 1; + // Q = fpminimax(f_cosm1, [|2,4,6,8|], [|0, D...|], d); + + let x2 = xd * xd; + let p = f_polyeval4( + x2, + f64::from_bits(0xbfe0000000000000), + f64::from_bits(0x3fa55555554ed21a), + f64::from_bits(0xbf56c16b981a61d0), + f64::from_bits(0x3ef9fc205e761f45), + ); + return (p * x2) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // cos(x) - 1 = -2*sin^2(x/2) + // Hence we're computing sin using formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let x_abs = (x * 0.5).to_bits(); + let xd = f32::from_bits(x_abs) as f64; + + let rs = sincosf_eval(xd, x_abs); + let sin_x_over_2 = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)); + let sin_sqr = sin_x_over_2 * sin_x_over_2; + let cosm1x = -2. * sin_sqr; + cosm1x as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_cosm1f_test() { + assert_eq!(f_cosm1f(0.00015928394), -1.2685687e-8); + assert_eq!(f_cosm1f(0.0), 0.0); + assert_eq!(f_cosm1f(std::f32::consts::PI), -2.); + assert_eq!(f_cosm1f(0.5), -0.122417435); + assert_eq!(f_cosm1f(0.7), -0.2351578); + assert_eq!(f_cosm1f(1.7), -1.1288445); + assert!(f_cosm1f(f32::INFINITY).is_nan()); + assert!(f_cosm1f(f32::NEG_INFINITY).is_nan()); + assert!(f_cosm1f(f32::NAN).is_nan()); + assert_eq!(f_cosm1f(0.0002480338), -3.076038e-8); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cospif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cospif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cospif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cospif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,218 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{is_integerf, is_odd_integerf}; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::argument_reduction_pi::ArgumentReducerPi; +use crate::sin_cosf::sincosf_eval::{cospif_eval, sinpif_eval}; + +#[inline(always)] +fn cospif_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.00000009546391 + if x_abs < 0x38a2_f984u32 { + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, f32::from_bits(0xb3000000), 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::f_fmla; + return f_fmla(xd, f64::from_bits(0xbe60000000000000), 1.) as f32; + } + } + + // Cos(x*PI) + // Generated poly by Sollya: + // d = [0, 1/16]; + // f_cos = cos(y*pi); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // + // See ./notes/cospif.sollya + + let x2 = xd * xd; + let p = f_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be43f7), + f64::from_bits(0x40103c1f08091fe0), + f64::from_bits(0xbff55d3ba3d94835), + f64::from_bits(0x3fce173c2a00e74e), + ); + return p as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || is_integerf(x) { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + if x_abs < 0x4b80_0000u32 { + static CF: [f32; 2] = [1., -1.]; + return CF[is_odd_integerf(x) as usize]; + } + return 1.; + } + + // We're computing cos(y) after argument reduction then return valid value + // based on quadrant + let reducer = ArgumentReducerPi { x: x as f64 }; + let (y, k) = reducer.reduce_0p25(); + // Decide based on quadrant what kernel function to use + (match k & 3 { + 0 => cospif_eval(y), + 1 => sinpif_eval(-y), + 2 => -cospif_eval(y), + _ => sinpif_eval(y), + }) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cospif_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.00000009546391 + if x_abs < 0x38a2_f984u32 { + return f32::mul_add(x, f32::from_bits(0xb3000000), 1.); + } + + // Cos(x*PI) + // Generated poly by Sollya: + // d = [0, 1/16]; + // f_cos = cos(y*pi); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // + // See ./notes/cospif.sollya + + let x2 = xd * xd; + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be43f7), + f64::from_bits(0x40103c1f08091fe0), + f64::from_bits(0xbff55d3ba3d94835), + f64::from_bits(0x3fce173c2a00e74e), + ); + return p as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || x.round_ties_even() == x { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + if x_abs < 0x4b80_0000u32 { + static CF: [f32; 2] = [1., -1.]; + let is_odd_integer = unsafe { (x.to_int_unchecked::() & 1) != 0 }; + return CF[is_odd_integer as usize]; + } + return 1.; + } + + // We're computing cos(y) after argument reduction then return valid value + // based on quadrant + let reducer = ArgumentReducerPi { x: x as f64 }; + let (y, k) = reducer.reduce_0p25_fma(); + // Decide based on quadrant what kernel function to use + use crate::sin_cosf::sincosf_eval::{cospif_eval_fma, sinpif_eval_fma}; + (match k & 3 { + 0 => cospif_eval_fma(y), + 1 => sinpif_eval_fma(-y), + 2 => -cospif_eval_fma(y), + _ => sinpif_eval_fma(y), + }) as f32 +} + +/// Computes cos(PI*x) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_cospif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cospif_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cospif_fma_impl + } else { + cospif_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_cospif() { + assert_eq!(f_cospif(1.), -1.); + assert_eq!(f_cospif(-3.5), 0.0); + assert_eq!(f_cospif(3.), -1.); + assert_eq!(f_cospif(-3.), -1.); + assert_eq!(f_cospif(2.), 1.); + assert_eq!(f_cospif(-2.), 1.); + assert_eq!(f_cospif(115.30706), -0.5696978); + assert!(f_cospif(f32::INFINITY).is_nan()); + assert!(f_cospif(f32::NAN).is_nan()); + assert!(f_cospif(f32::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cscf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cscf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cscf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/cscf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::{f_polyeval3, f_polyeval5}; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +#[inline(always)] +fn cscf_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + if x_abs == 0u32 { + // For signed zeros. + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + let dx = x as f64; + let c_term = 1. / dx; + let x2 = dx * dx; + // Maclaurin series + // 1/x + x/6 + (7 x^3)/360 + (31 x^5)/15120 + O(x^7) + let p = f_polyeval3( + x2, + f64::from_bits(0x3fc5555555555555), + f64::from_bits(0x3f93e93e93e93e94), + f64::from_bits(0x3f60b2463814bc5f), + ); + return f_fmla(dx, p, c_term) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f = 1 / sin(x) - 1/x; + + d = [0.000443633; pi/16]; + pf = fpminimax(f, [|1, 3, 5, 7, 9|], [|D...|], d, relative, floating); + + See ./notes/cscf.sollya + */ + + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3fc5555555555562), + f64::from_bits(0x3f93e93e93e730a3), + f64::from_bits(0x3f60cbb77382ae6f), + f64::from_bits(0x3f2b85bfd4188934), + f64::from_bits(0x3ef697a32ebe822d), + ); + return f_fmla(xd, p, 1. / xd) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let rs = sincosf_eval(xd, x_abs); + (1. / f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k))) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cscf_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + if x_abs == 0u32 { + // For signed zeros. + return if x.is_sign_negative() { + f32::NEG_INFINITY + } else { + f32::INFINITY + }; + } + let dx = x as f64; + let c_term = 1. / dx; + let x2 = dx * dx; + // Maclaurin series + // 1/x + x/6 + (7 x^3)/360 + (31 x^5)/15120 + O(x^7) + use crate::polyeval::d_polyeval3; + let p = d_polyeval3( + x2, + f64::from_bits(0x3fc5555555555555), + f64::from_bits(0x3f93e93e93e93e94), + f64::from_bits(0x3f60b2463814bc5f), + ); + return f64::mul_add(dx, p, c_term) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f = 1 / sin(x) - 1/x; + + d = [0.000443633; pi/16]; + pf = fpminimax(f, [|1, 3, 5, 7, 9|], [|D...|], d, relative, floating); + + See ./notes/cscf.sollya + */ + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + xsqr, + f64::from_bits(0x3fc5555555555562), + f64::from_bits(0x3f93e93e93e730a3), + f64::from_bits(0x3f60cbb77382ae6f), + f64::from_bits(0x3f2b85bfd4188934), + f64::from_bits(0x3ef697a32ebe822d), + ); + return f64::mul_add(xd, p, 1. / xd) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + use crate::sin_cosf::sincosf_eval::sincosf_eval_fma; + let rs = sincosf_eval_fma(xd, x_abs); + (1. / f64::mul_add( + rs.sin_y, + rs.cos_k, + f64::mul_add(rs.cosm1_y, rs.sin_k, rs.sin_k), + )) as f32 +} + +/// Cosecant ( 1 / sin(x) ) +/// +/// ULP 0.5 +#[inline] +pub fn f_cscf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cscf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cscf_fma_impl + } else { + cscf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_cscf_test() { + assert_eq!(f_cscf(0.04915107), 20.353632); + assert_eq!(f_cscf(0.5), 2.0858297); + assert_eq!(f_cscf(0.07), 14.297387); + assert_eq!(f_cscf(3.6171106e-5), 27646.375); + assert_eq!(f_cscf(-5.535772e-10), -1806432800.0); + assert_eq!(f_cscf(0.0), f32::INFINITY); + assert_eq!(f_cscf(-0.0), f32::NEG_INFINITY); + assert_eq!(f_cscf(-1.0854926e-19), -9.2124077e18); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod argument_reduction; +mod argument_reduction_pi; +mod cosf; +mod cosm1f; +mod cospif; +mod cscf; +mod secf; +mod sincf; +mod sincosf; +mod sincosf_eval; +mod sincospif; +mod sincpif; +mod sinf; +mod sinmxf; +mod sinpif; + +pub(crate) use argument_reduction::ArgumentReducer; +pub(crate) use argument_reduction_pi::ArgumentReducerPi; +pub use cosf::f_cosf; +pub use cosm1f::f_cosm1f; +pub use cospif::f_cospif; +pub use cscf::f_cscf; +pub use secf::f_secf; +pub use sincf::f_sincf; +pub use sincosf::f_sincosf; +pub use sincospif::f_sincospif; +pub use sincpif::f_sincpif; +pub use sinf::f_sinf; +pub use sinmxf::f_sinmxf; +pub use sinpif::f_sinpif; +pub(crate) use sinpif::fast_sinpif; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/secf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/secf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/secf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/secf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval6; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +#[inline(always)] +fn secf_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + // taylor series for sec(x) ~ 1 + x^2/2 + O(x^4) + // for such small interval just doing 2 first coefficients from taylor series + // FMA availability is mandatory to perform it in f32 without upcasting to f64. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, x * f32::from_bits(0x3f000000), 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let x2 = xd * xd; + return f_fmla(x2, f64::from_bits(0x3fe0000000000000), 1.) as f32; + } + } + + // Secant + // Generated poly by Sollya: + // f = 1 / cos(x); + // d = [0.000244141; pi/16]; + // pf = fpminimax(f, [|0, 2, 4, 6, 8, 10|], [|1, D...|], d, relative, floating); + // + // See ./notes/secf.sollya + + let x2 = xd * xd; + let p = f_polyeval6( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3fe000000001c0fb), + f64::from_bits(0x3fcaaaaaa0b8a71b), + f64::from_bits(0x3fb5b06437bc5a13), + f64::from_bits(0x3fa192a33a9fca4f), + f64::from_bits(0x3f8dde280c29af37), + ); + return p as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + // then sec(x) = 1/cos(x) + + let rs = sincosf_eval(xd, x_abs); + (1. / f_fmla(rs.sin_y, -rs.sin_k, f_fmla(rs.cosm1_y, rs.cos_k, rs.cos_k))) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn secf_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let x = f32::from_bits(x_abs); + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + // taylor series for sec(x) ~ 1 + x^2/2 + O(x^4) + // for such small interval just doing 2 first coefficients from taylor series + // FMA availability is mandatory to perform it in f32 without upcasting to f64. + return f32::mul_add(x, x * f32::from_bits(0x3f000000), 1.); + } + + // Secant + // Generated poly by Sollya: + // f = 1 / cos(x); + // d = [0.000244141; pi/16]; + // pf = fpminimax(f, [|0, 2, 4, 6, 8, 10|], [|1, D...|], d, relative, floating); + // + // See ./notes/secf.sollya + + let x2 = xd * xd; + use crate::polyeval::d_polyeval6; + let p = d_polyeval6( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3fe000000001c0fb), + f64::from_bits(0x3fcaaaaaa0b8a71b), + f64::from_bits(0x3fb5b06437bc5a13), + f64::from_bits(0x3fa192a33a9fca4f), + f64::from_bits(0x3f8dde280c29af37), + ); + return p as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + // then sec(x) = 1/cos(x) + use crate::sin_cosf::sincosf_eval::sincosf_eval_fma; + let rs = sincosf_eval_fma(xd, x_abs); + (1. / f64::mul_add( + rs.sin_y, + -rs.sin_k, + f64::mul_add(rs.cosm1_y, rs.cos_k, rs.cos_k), + )) as f32 +} + +/// Computes secant ( 1 / cos(x) ) +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_secf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + secf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + secf_fma_impl + } else { + secf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_secf() { + assert_eq!(f_secf(0.0), 1.0); + assert_eq!(f_secf(0.5), 1.139494); + assert_eq!(f_secf(-0.5), 1.139494); + assert_eq!(f_secf(1.5), 14.136833); + assert_eq!(f_secf(-1.5), 14.136833); + assert!(f_secf(f32::INFINITY).is_nan()); + assert!(f_secf(f32::NEG_INFINITY).is_nan()); + assert!(f_secf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,115 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +/// Computes sinc(x) +/// +/// Max found ULP 0.5 +pub fn f_sincf(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + if x_abs == 0u32 { + // For signed zeros. + return 1.; + } + /* + Generated by Sollya: + f = sin(x) / x; + + d = [0.0; 0.000443633]; + pf = fpminimax(f, [|0, 2|], [|1, D...|], d, relative, floating); + + See ./notes/sincf.sollya + */ + return f_fmla( + xd * xd, + f64::from_bits(0xbfc555555265f618), + f64::from_bits(0x3ff0000000000000), + ) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_sinpi_16 = sin(x)/x; + Q = fpminimax(f_sinpi_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + + See ./notes/sincosf.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfc55555555554c6), + f64::from_bits(0x3f81111111085e65), + f64::from_bits(0xbf2a019f70fb4d4f), + f64::from_bits(0x3ec718d179815e74), + ); + return p as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let rs = sincosf_eval(xd, x_abs); + let v_sin = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)); + (v_sin / xd) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_sincf() { + assert_eq!(f_sincf(-7.991783e37), -1.1754942946874968e-38); + assert_eq!(f_sincf(-8.04695e37), 1.1754942974913884e-38); + assert_eq!(f_sincf(-0.00044236073), 0.9999999673861641); + assert_eq!(f_sincf(0.0), 1.0); + assert_eq!(f_sincf(0.2), 0.99334663); + assert!(f_sincf(f32::INFINITY).is_nan()); + assert!(f_sincf(f32::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,267 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_estrin_polyeval5; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +#[inline(always)] +fn sincosf_gen_impl(x: f32) -> (f32, f32) { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x3980_0000u32 { + if x_abs == 0u32 { + // For signed zeros. + return (x, 1.0); + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + let sf = f_fmlaf(x, f32::from_bits(0xb3000000), x); + let cf = f_fmlaf(f32::from_bits(x_abs), f32::from_bits(0xb3000000), 1.); + return (sf, cf); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let sf = f_fmla(xd, f64::from_bits(0xbe60000000000000), xd) as f32; + let cf = f_fmla(xd, f64::from_bits(0xbe60000000000000), 1.) as f32; + return (sf, cf); + } + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_sinpi_16 = sin(x)/x; + Q = fpminimax(f_sinpi_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + + See ./notes/sincosf.sollya + */ + let p = f_estrin_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfc55555555554c6), + f64::from_bits(0x3f81111111085e65), + f64::from_bits(0xbf2a019f70fb4d4f), + f64::from_bits(0x3ec718d179815e74), + ); + let sf = (xd * p) as f32; + + // Cosine + // Generated poly by Sollya: + // f_cos_16 = cos(x); + // + // Q = fpminimax(f_cos_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + let cf = f_estrin_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfdffffffffffcea), + f64::from_bits(0x3fa55555553d611a), + f64::from_bits(0xbf56c16b2e26561a), + f64::from_bits(0x3ef9faa67b9da80b), + ); + return (sf, cf as f32); + } + + if x_abs >= 0x7f80_0000u32 { + return (x + f32::NAN, x + f32::NAN); + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let rs = sincosf_eval(xd, x_abs); + let sf = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)) as f32; + let cf = f_fmla(rs.sin_y, -rs.sin_k, f_fmla(rs.cosm1_y, rs.cos_k, rs.cos_k)) as f32; + (sf, cf) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sincosf_fma_impl(x: f32) -> (f32, f32) { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x3980_0000u32 { + if x_abs == 0u32 { + // For signed zeros. + return (x, 1.0); + } + let sf = f32::mul_add(x, f32::from_bits(0xb3000000), x); + let cf = f32::mul_add(f32::from_bits(x_abs), f32::from_bits(0xb3000000), 1.); + return (sf, cf); + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_sinpi_16 = sin(x)/x; + Q = fpminimax(f_sinpi_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + + See ./notes/sincosf.sollya + */ + use crate::polyeval::d_estrin_polyeval5; + let p = d_estrin_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfc55555555554c6), + f64::from_bits(0x3f81111111085e65), + f64::from_bits(0xbf2a019f70fb4d4f), + f64::from_bits(0x3ec718d179815e74), + ); + let sf = (xd * p) as f32; + + // Cosine + // Generated poly by Sollya: + // f_cos_16 = cos(x); + // + // Q = fpminimax(f_cos_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + let cf = d_estrin_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfdffffffffffcea), + f64::from_bits(0x3fa55555553d611a), + f64::from_bits(0xbf56c16b2e26561a), + f64::from_bits(0x3ef9faa67b9da80b), + ); + return (sf, cf as f32); + } + + if x_abs >= 0x7f80_0000u32 { + return (x + f32::NAN, x + f32::NAN); + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + use crate::sin_cosf::sincosf_eval::sincosf_eval_fma; + let rs = sincosf_eval_fma(xd, x_abs); + let sf = f64::mul_add( + rs.sin_y, + rs.cos_k, + f64::mul_add(rs.cosm1_y, rs.sin_k, rs.sin_k), + ) as f32; + let cf = f64::mul_add( + rs.sin_y, + -rs.sin_k, + f64::mul_add(rs.cosm1_y, rs.cos_k, rs.cos_k), + ) as f32; + (sf, cf) +} + +/// Sine and cosine +/// +/// Max found ULP on working range 0.49999967 +#[inline] +pub fn f_sincosf(x: f32) -> (f32, f32) { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sincosf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock (f32, f32)> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sincosf_fma_impl + } else { + sincosf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_sincosf_test() { + let sincos0 = f_sincosf(0.0); + assert!(sincos0.0 < 1e-8); + assert_eq!(sincos0.1, 1.0); + let sincos_pi = f_sincosf(std::f32::consts::PI); + assert!(sincos_pi.0 < 1e-8); + let sincos_pi_0_5 = f_sincosf(0.5); + assert_eq!(sincos_pi_0_5.0, 0.47942555); + assert_eq!(sincos_pi_0_5.1, 0.87758255); + let sincos_pi_n0_5 = f_sincosf(-0.5); + assert_eq!(sincos_pi_n0_5.0, -0.47942555); + assert_eq!(sincos_pi_n0_5.1, 0.87758255); + let v_z = f_sincosf(0.0002480338); + assert_eq!(v_z.1, 0.9999999692396206); + } + + #[test] + fn f_sincosf_edge_test() { + let s0 = f_sincosf(f32::INFINITY); + assert!(s0.0.is_nan()); + assert!(s0.1.is_nan()); + let s1 = f_sincosf(f32::NEG_INFINITY); + assert!(s1.0.is_nan()); + assert!(s1.1.is_nan()); + let s2 = f_sincosf(f32::NAN); + assert!(s2.0.is_nan()); + assert!(s2.1.is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf_eval.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf_eval.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf_eval.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincosf_eval.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,453 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::polyeval::{f_estrin_polyeval7, f_polyeval3, f_polyeval4, f_polyeval6}; +use crate::sin_cosf::argument_reduction::ArgumentReducer; +use crate::sin_cosf::argument_reduction_pi::ArgumentReducerPi; + +/** +Generated in SageMath: + +```text +print("[") +for k in range(64): + k = RealField(150)(k) * RealField(150).pi() / RealField(150)(32) + print(double_to_hex(k.sin()) + ",") +print("];") +``` +**/ +static SIN_K_PI_OVER32: [u64; 64] = [ + 0x0000000000000000, + 0x3fb917a6bc29b42c, + 0x3fc8f8b83c69a60b, + 0x3fd294062ed59f06, + 0x3fd87de2a6aea963, + 0x3fde2b5d3806f63b, + 0x3fe1c73b39ae68c8, + 0x3fe44cf325091dd6, + 0x3fe6a09e667f3bcd, + 0x3fe8bc806b151741, + 0x3fea9b66290ea1a3, + 0x3fec38b2f180bdb1, + 0x3fed906bcf328d46, + 0x3fee9f4156c62dda, + 0x3fef6297cff75cb0, + 0x3fefd88da3d12526, + 0x3ff0000000000000, + 0x3fefd88da3d12526, + 0x3fef6297cff75cb0, + 0x3fee9f4156c62dda, + 0x3fed906bcf328d46, + 0x3fec38b2f180bdb1, + 0x3fea9b66290ea1a3, + 0x3fe8bc806b151741, + 0x3fe6a09e667f3bcd, + 0x3fe44cf325091dd6, + 0x3fe1c73b39ae68c8, + 0x3fde2b5d3806f63b, + 0x3fd87de2a6aea963, + 0x3fd294062ed59f06, + 0x3fc8f8b83c69a60b, + 0x3fb917a6bc29b42c, + 0xb69f77598338bfdf, + 0xbfb917a6bc29b42c, + 0xbfc8f8b83c69a60b, + 0xbfd294062ed59f06, + 0xbfd87de2a6aea963, + 0xbfde2b5d3806f63b, + 0xbfe1c73b39ae68c8, + 0xbfe44cf325091dd6, + 0xbfe6a09e667f3bcd, + 0xbfe8bc806b151741, + 0xbfea9b66290ea1a3, + 0xbfec38b2f180bdb1, + 0xbfed906bcf328d46, + 0xbfee9f4156c62dda, + 0xbfef6297cff75cb0, + 0xbfefd88da3d12526, + 0xbff0000000000000, + 0xbfefd88da3d12526, + 0xbfef6297cff75cb0, + 0xbfee9f4156c62dda, + 0xbfed906bcf328d46, + 0xbfec38b2f180bdb1, + 0xbfea9b66290ea1a3, + 0xbfe8bc806b151741, + 0xbfe6a09e667f3bcd, + 0xbfe44cf325091dd6, + 0xbfe1c73b39ae68c8, + 0xbfde2b5d3806f63b, + 0xbfd87de2a6aea963, + 0xbfd294062ed59f06, + 0xbfc8f8b83c69a60b, + 0xbfb917a6bc29b42c, +]; + +pub(crate) struct SinCosf { + pub(crate) sin_k: f64, + pub(crate) cos_k: f64, + pub(crate) sin_y: f64, + pub(crate) cosm1_y: f64, +} + +#[inline] +pub(crate) fn sincosf_eval(x: f64, x_abs: u32) -> SinCosf { + let argument_reduction = ArgumentReducer { x, x_abs }; + + let (y, k) = argument_reduction.reduce(); + + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + // Then sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + + let sin_k = f64::from_bits(SIN_K_PI_OVER32[((k as u64) & 63) as usize]); + // cos(k * pi/32) = sin(k * pi/32 + pi/2) = sin((k + 16) * pi/32). + // cos_k = cos(k * pi/32) + let cos_k = f64::from_bits(SIN_K_PI_OVER32[((k.wrapping_add(16) as u64) & 63) as usize]); + + // Degree-6 minimax even polynomial for sin(y*pi/32)/y generated by Sollya + // with: + // > Q = fpminimax(sin(y*pi/32)/y, [|0, 2, 4, 6|], [|D...|], [0, 0.5]); + // + // See ./notes/sincosf.sollya + let sin_y = y * f_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442d18), + f64::from_bits(0xbf24abbce625abb1), + f64::from_bits(0x3e7466bc624f2776), + f64::from_bits(0xbdb32c3a619d4a7e), + ); + // Degree-6 minimax even polynomial for cos(y*pi/32) generated by Sollya with: + // > P = fpminimax(cos(x*pi/32), [|0, 2, 4, 6|], [|1, D...|], [0, 0.5]); + // Note that cosm1_y = cos(y*pi/32) - 1. + // + // See ./notes/sincosf.sollya + let cosm1_y = y_sqr + * f_polyeval3( + y_sqr, + f64::from_bits(0xbf73bd3cc9be430b), + f64::from_bits(0x3ed03c1f070c2e27), + f64::from_bits(0xbe155cc84bd94200), + ); + + SinCosf { + sin_k, + cos_k, + sin_y, + cosm1_y, + } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn sincosf_eval_fma(x: f64, x_abs: u32) -> SinCosf { + let argument_reduction = ArgumentReducer { x, x_abs }; + + let (y, k) = argument_reduction.reduce_fma(); + + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + // Then sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + + let sin_k = f64::from_bits(SIN_K_PI_OVER32[((k as u64) & 63) as usize]); + // cos(k * pi/32) = sin(k * pi/32 + pi/2) = sin((k + 16) * pi/32). + // cos_k = cos(k * pi/32) + let cos_k = f64::from_bits(SIN_K_PI_OVER32[((k.wrapping_add(16) as u64) & 63) as usize]); + + // Degree-6 minimax even polynomial for sin(y*pi/32)/y generated by Sollya + // with: + // > Q = fpminimax(sin(y*pi/32)/y, [|0, 2, 4, 6|], [|D...|], [0, 0.5]); + // + // See ./notes/sincosf.sollya + use crate::polyeval::d_polyeval4; + let sin_y = y * d_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442d18), + f64::from_bits(0xbf24abbce625abb1), + f64::from_bits(0x3e7466bc624f2776), + f64::from_bits(0xbdb32c3a619d4a7e), + ); + // Degree-6 minimax even polynomial for cos(y*pi/32) generated by Sollya with: + // > P = fpminimax(cos(x*pi/32), [|0, 2, 4, 6|], [|1, D...|], [0, 0.5]); + // Note that cosm1_y = cos(y*pi/32) - 1. + // + // See ./notes/sincosf.sollya + use crate::polyeval::d_polyeval3; + let cosm1_y = y_sqr + * d_polyeval3( + y_sqr, + f64::from_bits(0xbf73bd3cc9be430b), + f64::from_bits(0x3ed03c1f070c2e27), + f64::from_bits(0xbe155cc84bd94200), + ); + + SinCosf { + sin_k, + cos_k, + sin_y, + cosm1_y, + } +} + +#[inline(always)] +pub(crate) fn sincospif_eval(x: f64) -> SinCosf { + let argument_reduction = ArgumentReducerPi { x }; + + let (y, k) = argument_reduction.reduce(); + + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + // Then sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + + let sin_k = f64::from_bits(SIN_K_PI_OVER32[((k as u64) & 63) as usize]); + // cos(k * pi/32) = sin(k * pi/32 + pi/2) = sin((k + 16) * pi/32). + // cos_k = cos(k * pi/32) + let cos_k = f64::from_bits(SIN_K_PI_OVER32[((k.wrapping_add(16) as u64) & 63) as usize]); + + // Degree-6 minimax even polynomial for sin(y*pi/32)/y generated by Sollya + // with: + // > Q = fpminimax(sin(y*pi/32)/y, [|0, 2, 4, 6|], [|D...|], [0, 0.5]); + // + // See ./notes/sincosf.sollya + let sin_y = y * f_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442d18), + f64::from_bits(0xbf24abbce625abb1), + f64::from_bits(0x3e7466bc624f2776), + f64::from_bits(0xbdb32c3a619d4a7e), + ); + // Degree-6 minimax even polynomial for cos(y*pi/32) generated by Sollya with: + // > P = fpminimax(cos(x*pi/32), [|0, 2, 4, 6|], [|1, D...|], [0, 0.5]); + // Note that cosm1_y = cos(y*pi/32) - 1. + // + // See ./notes/sincosf.sollya + let cosm1_y = y_sqr + * f_polyeval3( + y_sqr, + f64::from_bits(0xbf73bd3cc9be430b), + f64::from_bits(0x3ed03c1f070c2e27), + f64::from_bits(0xbe155cc84bd94200), + ); + + SinCosf { + sin_k, + cos_k, + sin_y, + cosm1_y, + } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn sincospif_eval_fma(x: f64) -> SinCosf { + let argument_reduction = ArgumentReducerPi { x }; + + let (y, k) = argument_reduction.reduce_fma(); + + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + // Then sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + + let sin_k = f64::from_bits(SIN_K_PI_OVER32[((k as u64) & 63) as usize]); + // cos(k * pi/32) = sin(k * pi/32 + pi/2) = sin((k + 16) * pi/32). + // cos_k = cos(k * pi/32) + let cos_k = f64::from_bits(SIN_K_PI_OVER32[((k.wrapping_add(16) as u64) & 63) as usize]); + + use crate::polyeval::{d_polyeval3, d_polyeval4}; + + // Degree-6 minimax even polynomial for sin(y*pi/32)/y generated by Sollya + // with: + // > Q = fpminimax(sin(y*pi/32)/y, [|0, 2, 4, 6|], [|D...|], [0, 0.5]); + // + // See ./notes/sincosf.sollya + let sin_y = y * d_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442d18), + f64::from_bits(0xbf24abbce625abb1), + f64::from_bits(0x3e7466bc624f2776), + f64::from_bits(0xbdb32c3a619d4a7e), + ); + // Degree-6 minimax even polynomial for cos(y*pi/32) generated by Sollya with: + // > P = fpminimax(cos(x*pi/32), [|0, 2, 4, 6|], [|1, D...|], [0, 0.5]); + // Note that cosm1_y = cos(y*pi/32) - 1. + // + // See ./notes/sincosf.sollya + let cosm1_y = y_sqr + * d_polyeval3( + y_sqr, + f64::from_bits(0xbf73bd3cc9be430b), + f64::from_bits(0x3ed03c1f070c2e27), + f64::from_bits(0xbe155cc84bd94200), + ); + + SinCosf { + sin_k, + cos_k, + sin_y, + cosm1_y, + } +} + +/** +Poly for sin(pi*y) on [-0.25; 0.25]. +Generated by Sollya: +```text +d = [0,0.25]; +f_sin = sin(y*pi)/y; +Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|D...|], d, relative, floating); +``` +See ./notes/sinpif_0p25.sollya +**/ +#[inline(always)] +pub(crate) fn sinpif_eval(y: f64) -> f64 { + let y2 = y * y; + f_polyeval6( + y2, + f64::from_bits(0x400921fb54442cf8), + f64::from_bits(0xc014abbce6257778), + f64::from_bits(0x400466bc670fa464), + f64::from_bits(0xbfe32d2c627f47da), + f64::from_bits(0x3fb5071be0a2d3da), + f64::from_bits(0xbf7dd4e0ae5b9fcd), + ) * y +} + +/** +Poly for sin(pi*y) on [-0.25; 0.25]. +Generated by Sollya: +```text +d = [0,0.25]; +f_sin = sin(y*pi)/y; +Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|D...|], d, relative, floating); +``` +See ./notes/sinpif_0p25.sollya +**/ +#[inline(always)] +#[allow(unused)] +pub(crate) fn sinpif_eval_fma(y: f64) -> f64 { + let y2 = y * y; + use crate::polyeval::d_polyeval6; + d_polyeval6( + y2, + f64::from_bits(0x400921fb54442cf8), + f64::from_bits(0xc014abbce6257778), + f64::from_bits(0x400466bc670fa464), + f64::from_bits(0xbfe32d2c627f47da), + f64::from_bits(0x3fb5071be0a2d3da), + f64::from_bits(0xbf7dd4e0ae5b9fcd), + ) * y +} + +/** +Poly for sin(pi*y) on [-0.25; 0.25]. +Generated by Sollya: +```text +d = [0,0.25]; +f_sin = sin(y*pi)/y; +Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10, 12|], [|D...|], d, relative, floating); +``` +See ./notes/sinpif_0p25_2.sollya +**/ +#[inline] +pub(crate) fn sinpif_eval2(y: f64) -> f64 { + let y2 = y * y; + f_estrin_polyeval7( + y2, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625be09), + f64::from_bits(0x400466bc67754fff), + f64::from_bits(0xbfe32d2ccdfe9424), + f64::from_bits(0x3fb50782d5f14825), + f64::from_bits(0xbf7e2fe76fdffd2b), + f64::from_bits(0x3f3e357ef99eb0bb), + ) * y +} + +/** +Poly for cos(pi*y) on [-0.25; 0.25]. +Generated by Sollya: +```text +d = [0, 0.25]; +f_cos = cos(y*pi); +Q = fpminimax(f_cos, [|0, 2, 4, 6, 8, 10|], [|1, D...|], d, relative, floating); +``` +See ./notes/cospif_0p25.sollya +**/ +#[inline(always)] +pub(crate) fn cospif_eval(y: f64) -> f64 { + let y2 = y * y; + f_estrin_polyeval7( + y2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be459b), + f64::from_bits(0x40103c1f081b0c98), + f64::from_bits(0xbff55d3c7dc25308), + f64::from_bits(0x3fce1f4fb6e12563), + f64::from_bits(0xbf9a6c9c101c1182), + f64::from_bits(0x3f5f3d9faffda250), + ) +} + +/** +Poly for cos(pi*y) on [-0.25; 0.25]. +Generated by Sollya: +```text +d = [0, 0.25]; +f_cos = cos(y*pi); +Q = fpminimax(f_cos, [|0, 2, 4, 6, 8, 10|], [|1, D...|], d, relative, floating); +``` +See ./notes/cospif_0p25.sollya +**/ +#[inline(always)] +#[allow(unused)] +pub(crate) fn cospif_eval_fma(y: f64) -> f64 { + let y2 = y * y; + use crate::polyeval::d_estrin_polyeval7; + d_estrin_polyeval7( + y2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be459b), + f64::from_bits(0x40103c1f081b0c98), + f64::from_bits(0xbff55d3c7dc25308), + f64::from_bits(0x3fce1f4fb6e12563), + f64::from_bits(0xbf9a6c9c101c1182), + f64::from_bits(0x3f5f3d9faffda250), + ) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincospif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincospif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincospif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincospif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,313 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf, is_odd_integerf}; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincospif_eval; + +#[inline(always)] +fn sincospif_gen_impl(x: f32) -> (f32, f32) { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.00000009546391 + if x_abs < 0x38a2_f984u32 { + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const MPI_E3_OVER_6: f64 = f64::from_bits(0xc014abbce625be53); + + // Small values approximated with Taylor poly for sine + // x = pi * x - pi^3*x^3/6 + let x2 = xd * xd; + let p = f_fmla(x2, MPI_E3_OVER_6, PI); + let sf = (xd * p) as f32; + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + let cs = f_fmlaf(x, f32::from_bits(0xb3000000), 1.); + return (sf, cs); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let cs = f_fmla(xd, f64::from_bits(0xbe60000000000000), 1.) as f32; + return (sf, cs); + } + } + + // Cos(x*PI) + // Generated poly by Sollya: + // d = [0, 1/16]; + // f_cos = cos(y*pi); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // + // See ./notes/cospif.sollya + + let x2 = xd * xd; + let cs = f_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be43f7), + f64::from_bits(0x40103c1f08091fe0), + f64::from_bits(0xbff55d3ba3d94835), + f64::from_bits(0x3fce173c2a00e74e), + ) as f32; + /* + Sin(x*PI) + Generated by Sollya: + d = [0, 1/16]; + f_sin = sin(y*pi)/y; + Q = fpminimax(sin(y*pi)/y, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + + See ./notes/sinpif.sollya + */ + let p = f_polyeval5( + x2, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625bbf2), + f64::from_bits(0x400466bc675e116a), + f64::from_bits(0xbfe32d2c0b62d41c), + f64::from_bits(0x3fb501ec4497cb7d), + ); + let sf = (xd * p) as f32; + + return (sf, cs); + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || is_integerf(x) { + if x_abs >= 0x7f80_0000u32 { + return (x + f32::NAN, x + f32::NAN); + } + static SF: [f32; 2] = [0., -0.]; + let sf = SF[x.is_sign_negative() as usize]; + if x_abs < 0x4b80_0000u32 { + static CF: [f32; 2] = [1., -1.]; + let cs = CF[is_odd_integerf(x) as usize]; + return (sf, cs); + } + return (sf, 1.); + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + + let rs = sincospif_eval(xd); + let cs = f_fmla(rs.sin_y, -rs.sin_k, f_fmla(rs.cosm1_y, rs.cos_k, rs.cos_k)) as f32; + let sf = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)) as f32; + (sf, cs) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sincospif_fma_impl(x: f32) -> (f32, f32) { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.00000009546391 + if x_abs < 0x38a2_f984u32 { + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const MPI_E3_OVER_6: f64 = f64::from_bits(0xc014abbce625be53); + + // Small values approximated with Taylor poly for sine + // x = pi * x - pi^3*x^3/6 + let x2 = xd * xd; + let p = f64::mul_add(x2, MPI_E3_OVER_6, PI); + let sf = (xd * p) as f32; + let cs = f32::mul_add(x, f32::from_bits(0xb3000000), 1.); + return (sf, cs); + } + + use crate::polyeval::d_polyeval5; + + // Cos(x*PI) + // Generated poly by Sollya: + // d = [0, 1/16]; + // f_cos = cos(y*pi); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // + // See ./notes/cospif.sollya + + let x2 = xd * xd; + let cs = d_polyeval5( + x2, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xc013bd3cc9be43f7), + f64::from_bits(0x40103c1f08091fe0), + f64::from_bits(0xbff55d3ba3d94835), + f64::from_bits(0x3fce173c2a00e74e), + ) as f32; + /* + Sin(x*PI) + Generated by Sollya: + d = [0, 1/16]; + f_sin = sin(y*pi)/y; + Q = fpminimax(sin(y*pi)/y, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + + See ./notes/sinpif.sollya + */ + let p = d_polyeval5( + x2, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625bbf2), + f64::from_bits(0x400466bc675e116a), + f64::from_bits(0xbfe32d2c0b62d41c), + f64::from_bits(0x3fb501ec4497cb7d), + ); + let sf = (xd * p) as f32; + + return (sf, cs); + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || x.round_ties_even() == x { + if x_abs >= 0x7f80_0000u32 { + return (x + f32::NAN, x + f32::NAN); + } + static SF: [f32; 2] = [0., -0.]; + let sf = SF[x.is_sign_negative() as usize]; + if x_abs < 0x4b80_0000u32 { + static CF: [f32; 2] = [1., -1.]; + let is_odd_integer = unsafe { (x.to_int_unchecked::() & 1) != 0 }; + let cs = CF[is_odd_integer as usize]; + return (sf, cs); + } + return (sf, 1.); + } + + // Formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + // Combine the results with the sine of sum formula: + // cos(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = cosm1_y * cos_k + sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k + + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + use crate::sin_cosf::sincosf_eval::sincospif_eval_fma; + let rs = sincospif_eval_fma(xd); + let cs = f64::mul_add( + rs.sin_y, + -rs.sin_k, + f64::mul_add(rs.cosm1_y, rs.cos_k, rs.cos_k), + ) as f32; + let sf = f64::mul_add( + rs.sin_y, + rs.cos_k, + f64::mul_add(rs.cosm1_y, rs.sin_k, rs.sin_k), + ) as f32; + (sf, cs) +} + +/// Computes sin(x) and cos(x) at the same time +/// +/// Max ULP 0.5 +#[inline] +pub fn f_sincospif(x: f32) -> (f32, f32) { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sincospif_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock (f32, f32)> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sincospif_fma_impl + } else { + sincospif_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{f_cospif, f_sinpif}; + + #[test] + fn test_sincospif() { + let v0 = f_sincospif(-5.); + assert_eq!(v0.0, f_sinpif(-5.)); + assert_eq!(v0.1, f_cospif(-5.)); + + let v0 = f_sincospif(-4.); + assert_eq!(v0.0, f_sinpif(-4.)); + assert_eq!(v0.1, f_cospif(-4.)); + + let v0 = f_sincospif(4.); + assert_eq!(v0.0, f_sinpif(4.)); + assert_eq!(v0.1, f_cospif(4.)); + + let v0 = f_sincospif(-8489897.0); + assert_eq!(v0.0, f_sinpif(-8489897.0)); + assert_eq!(v0.1, f_cospif(-8489897.0)); + + let v1 = f_sincospif(3.23); + assert_eq!(v1.0, f_sinpif(3.23)); + assert_eq!(v1.1, f_cospif(3.23)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sincpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf}; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincospif_eval; + +#[inline(always)] +fn sincpif_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + if x_abs <= 0x3d80_0000u32 { + // |x| <= 1/16 + if x_abs < 0x3580_2126u32 { + // |x| < 0.0000009546391 + if x_abs == 0u32 { + // Signed zeros. + return 1.; + } + + // Small values approximated with Taylor poly + // sincpi(x) ~ 1 - x^2*Pi^2/6 + O(x^4) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + const M_SQR_PI_OVER_6: f32 = f32::from_bits(0xbfd28d33); + return f_fmlaf(x, M_SQR_PI_OVER_6 * x, 1.); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + const M_SQR_PI_OVER_6: f64 = f64::from_bits(0xbffa51a6625307d3); + let x2 = xd * xd; + let p = f_fmla(x2, M_SQR_PI_OVER_6, 1.); + return p as f32; + } + } + + let xsqr = xd * xd; + + // Generated by Sollya: + // d = [0, 1/16]; + // f_sincpif = sin(y*pi)/(y*pi); + // Q = fpminimax(f_sincpif, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // See ./notes/sincpif.sollya + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbffa51a662530723), + f64::from_bits(0x3fe9f9cb401e8e85), + f64::from_bits(0xbfc86a8da89c9234), + f64::from_bits(0x3f9ac0a16798157e), + ); + return p as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + // integers are always 0 + if x_abs >= 0x4b00_0000u32 || is_integerf(x) { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + return if x.is_sign_negative() { -0. } else { 0. }; + } + + const PI: f64 = f64::from_bits(0x400921fb54442d18); + let rs = sincospif_eval(xd); + let sf = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)); + (sf / (PI * xd)) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sincpif_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + if x_abs <= 0x3d80_0000u32 { + // |x| <= 1/16 + if x_abs < 0x3580_2126u32 { + // |x| < 0.0000009546391 + if x_abs == 0u32 { + // Signed zeros. + return 1.; + } + + // Small values approximated with Taylor poly + // sincpi(x) ~ 1 - x^2*Pi^2/6 + O(x^4) + const M_SQR_PI_OVER_6: f32 = f32::from_bits(0xbfd28d33); + return f32::mul_add(x, M_SQR_PI_OVER_6 * x, 1.); + } + + let xsqr = xd * xd; + + // Generated by Sollya: + // d = [0, 1/16]; + // f_sincpif = sin(y*pi)/(y*pi); + // Q = fpminimax(f_sincpif, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + // See ./notes/sincpif.sollya + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbffa51a662530723), + f64::from_bits(0x3fe9f9cb401e8e85), + f64::from_bits(0xbfc86a8da89c9234), + f64::from_bits(0x3f9ac0a16798157e), + ); + return p as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + // integers are always 0 + if x_abs >= 0x4b00_0000u32 || x == x.round_ties_even() { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + return if x.is_sign_negative() { -0. } else { 0. }; + } + + const PI: f64 = f64::from_bits(0x400921fb54442d18); + use crate::sin_cosf::sincosf_eval::sincospif_eval_fma; + let rs = sincospif_eval_fma(xd); + let sf = f64::mul_add( + rs.sin_y, + rs.cos_k, + f64::mul_add(rs.cosm1_y, rs.sin_k, rs.sin_k), + ); + (sf / (PI * xd)) as f32 +} + +/// Computes sin(PI\*x)/(PI\*x) +/// +/// Produces normalized sinc. +/// +/// ulp 0.5 +pub fn f_sincpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sincpif_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sincpif_fma_impl + } else { + sincpif_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sincpif_eval() { + assert_eq!(f_sincpif(1.0), 0.); + assert_eq!(f_sincpif(2.0), 0.); + assert_eq!(f_sincpif(3.0), 0.); + assert_eq!(f_sincpif(0.0543242), 0.99515265); + assert_eq!(f_sincpif(0.002134242), 0.9999925); + assert_eq!(f_sincpif(0.00000005421321), 1.0); + assert!(f_sincpif(f32::INFINITY).is_nan()); + assert!(f_sincpif(f32::NEG_INFINITY).is_nan()); + assert!(f_sincpif(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,206 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +#[inline(always)] +fn sinf_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + if x_abs == 0u32 { + // For signed zeros. + return x; + } + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, f32::from_bits(0xb3000000), x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + return f_fmla(xd, f64::from_bits(0xbe60000000000000), xd) as f32; + } + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_sinpi_16 = sin(x)/x; + Q = fpminimax(f_sinpi_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + + See ./notes/sinf.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfc55555555554c6), + f64::from_bits(0x3f81111111085e65), + f64::from_bits(0xbf2a019f70fb4d4f), + f64::from_bits(0x3ec718d179815e74), + ); + return (xd * p) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let rs = sincosf_eval(xd, x_abs); + f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sinf_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + if x_abs == 0u32 { + // For signed zeros. + return x; + } + return f32::mul_add(x, f32::from_bits(0xb3000000), x); + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_sinpi_16 = sin(x)/x; + Q = fpminimax(f_sinpi_16, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]); + + See ./notes/sinf.sollya + */ + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfc55555555554c6), + f64::from_bits(0x3f81111111085e65), + f64::from_bits(0xbf2a019f70fb4d4f), + f64::from_bits(0x3ec718d179815e74), + ); + return (xd * p) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + use crate::sin_cosf::sincosf_eval::sincosf_eval_fma; + let rs = sincosf_eval_fma(xd, x_abs); + f64::mul_add( + rs.sin_y, + rs.cos_k, + f64::mul_add(rs.cosm1_y, rs.sin_k, rs.sin_k), + ) as f32 +} + +/// Sine function +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_sinf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sinf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sinf_fma_impl + } else { + sinf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_sinf_test() { + assert_eq!(f_sinf(0.0), 0.0); + assert_eq!(f_sinf(1.0), 0.84147096); + assert_eq!(f_sinf(0.3), 0.29552022); + assert_eq!(f_sinf(-1.0), -0.84147096); + assert_eq!(f_sinf(-0.3), -0.29552022); + assert_eq!(f_sinf(std::f32::consts::PI / 2.), 1.); + assert!(f_sinf(f32::INFINITY).is_nan()); + assert!(f_sinf(f32::NEG_INFINITY).is_nan()); + assert!((f_sinf(std::f32::consts::PI) - 0f32).abs() < 1e-6); + assert!((f_sinf(std::f32::consts::FRAC_PI_2) - 1f32).abs() < 1e-6); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinmxf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinmxf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinmxf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinmxf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::sincosf_eval::sincosf_eval; + +/// Computes sin(x) - x +pub fn f_sinmxf(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + let ax: u32 = x.to_bits().wrapping_shl(1); + if ax == 0 || ax >= 0xffu32 << 24 { + if x_abs == 0u32 { + // For signed zeros. + return x; + } + return f32::NAN; // x == inf or x == NaN + } + + // |x| <= pi/16 + if x_abs <= 0x3e49_0fdbu32 { + // |x| < 0.000443633 + if x_abs < 0x39e8_9769u32 { + // sin(x) - x ~ -x^3/6 + x^5/120 + O(x^7) + let dx = x as f64; + let x2 = dx * dx; + let c = f_fmla( + x2, + f64::from_bits(0x3f81111111111111), + f64::from_bits(0xbfc5555555555555), + ) * x2; + return (c * dx) as f32; + } + + let xsqr = xd * xd; + + // Generated by Sollya: + // d = [2^-10, pi/16]; + // f_sinmx = (sin(x) - x)/x; + // Q = fpminimax(f_sinmx, [|0, 2, 4, 6, 8|], [|D...|], d); + // See ./notes/sinmxf.sollya + let p = f_polyeval5( + xsqr, + f64::from_bits(0xbb8f6a339382f07f), + f64::from_bits(0xbfc5555555555545), + f64::from_bits(0x3f811111110ddf5c), + f64::from_bits(0xbf2a019fb330c620), + f64::from_bits(0x3ec719bc2a614884), + ); + return (xd * p) as f32; + } + + // Formula: + // sin(x) = sin((k + y)*pi/32) + // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + let rs = sincosf_eval(xd, x_abs); + let sinx = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k)); + (sinx - xd) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_sinf_test() { + assert_eq!(f_sinmxf(0.00016344387), -0.00000000000072770376); + assert_eq!(f_sinmxf(0.0), 0.0); + assert_eq!(f_sinmxf(-0.0), 0.0); + assert_eq!(f_sinmxf(1.0), -0.15852901); + assert_eq!(f_sinmxf(0.3), -0.004479794); + assert_eq!(f_sinmxf(-1.0), 0.15852901); + assert_eq!(f_sinmxf(-0.3), 0.004479794); + assert_eq!(f_sinmxf(std::f32::consts::PI / 2.), -0.5707964); + assert!(f_sinmxf(f32::INFINITY).is_nan()); + assert!(f_sinmxf(f32::NEG_INFINITY).is_nan()); + assert!(f_sinmxf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_cosf/sinpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,264 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, is_integerf}; +use crate::polyeval::f_polyeval5; +use crate::sin_cosf::argument_reduction_pi::ArgumentReducerPi; +use crate::sin_cosf::sincosf_eval::{cospif_eval, sinpif_eval, sinpif_eval2}; + +#[inline(always)] +fn sinpif_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.0000009546391 + if x_abs < 0x3580_2126u32 { + if x_abs == 0u32 { + // For signed zeros. + return x; + } + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const MPI_E3_OVER_6: f64 = f64::from_bits(0xc014abbce625be53); + + // Small values approximated with Taylor poly + // x = pi * x - pi^3*x^3/6 + let x2 = xd * xd; + let p = f_fmla(x2, MPI_E3_OVER_6, PI); + return (xd * p) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + d = [0, 1/16]; + f_sin = sin(y*pi)/y; + Q = fpminimax(sin(y*pi)/y, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + + See ./notes/sinpif.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625bbf2), + f64::from_bits(0x400466bc675e116a), + f64::from_bits(0xbfe32d2c0b62d41c), + f64::from_bits(0x3fb501ec4497cb7d), + ); + return (xd * p) as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || is_integerf(x) { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + return if x.is_sign_negative() { -0. } else { 0. }; + } + + // We're computing sin(y) after argument reduction then return valid value + // based on quadrant + + let reducer = ArgumentReducerPi { x: x as f64 }; + let (y, k) = reducer.reduce_0p25(); + // Decide based on quadrant what kernel function to use + (match k & 3 { + 0 => sinpif_eval(y), + 1 => cospif_eval(y), + 2 => sinpif_eval(-y), + _ => -cospif_eval(y), + }) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sinpif_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.0000009546391 + if x_abs < 0x3580_2126u32 { + if x_abs == 0u32 { + // For signed zeros. + return x; + } + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const MPI_E3_OVER_6: f64 = f64::from_bits(0xc014abbce625be53); + + // Small values approximated with Taylor poly + // x = pi * x - pi^3*x^3/6 + let x2 = xd * xd; + let p = f64::mul_add(x2, MPI_E3_OVER_6, PI); + return (xd * p) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + d = [0, 1/16]; + f_sin = sin(y*pi)/y; + Q = fpminimax(sin(y*pi)/y, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + + See ./notes/sinpif.sollya + */ + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + xsqr, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625bbf2), + f64::from_bits(0x400466bc675e116a), + f64::from_bits(0xbfe32d2c0b62d41c), + f64::from_bits(0x3fb501ec4497cb7d), + ); + return (xd * p) as f32; + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if x_abs >= 0x4b00_0000u32 || x.round_ties_even() == x { + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + return if x.is_sign_negative() { -0. } else { 0. }; + } + + // We're computing sin(y) after argument reduction then return valid value + // based on quadrant + + let reducer = ArgumentReducerPi { x: x as f64 }; + let (y, k) = reducer.reduce_0p25_fma(); + // Decide based on quadrant what kernel function to use + use crate::sin_cosf::sincosf_eval::{cospif_eval_fma, sinpif_eval_fma}; + (match k & 3 { + 0 => sinpif_eval_fma(y), + 1 => cospif_eval_fma(y), + 2 => sinpif_eval_fma(-y), + _ => -cospif_eval_fma(y), + }) as f32 +} + +/// Computes sin(PI*x) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_sinpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sinpif_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sinpif_fma_impl + } else { + sinpif_gen_impl + } + }); + unsafe { q(x) } + } +} + +pub(crate) fn fast_sinpif(x: f32) -> f64 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| <= 1/16 + if x_abs <= 0x3d80_0000u32 { + // |x| < 0.0000009546391 + if x_abs < 0x3580_2126u32 { + if x_abs == 0u32 { + // For signed zeros. + return x as f64; + } + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const MPI_E3_OVER_6: f64 = f64::from_bits(0xc014abbce625be53); + + // Small values approximated with Taylor poly + // x = pi * x - pi^3*x^3/6 + let x2 = xd * xd; + let p = f_fmla(x2, MPI_E3_OVER_6, PI); + return xd * p; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + d = [0, 1/16]; + f_sin = sin(y*pi)/y; + Q = fpminimax(sin(y*pi)/y, [|0, 2, 4, 6, 8|], [|D...|], d, relative, floating); + + See ./notes/sinpif.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x400921fb54442d18), + f64::from_bits(0xc014abbce625bbf2), + f64::from_bits(0x400466bc675e116a), + f64::from_bits(0xbfe32d2c0b62d41c), + f64::from_bits(0x3fb501ec4497cb7d), + ); + return xd * p; + } + + let reducer = ArgumentReducerPi { x: x as f64 }; + let (y, k) = reducer.reduce_0p25(); + // Decide based on quadrant what kernel function to use + match k & 3 { + 0 => sinpif_eval2(y), + 1 => cospif_eval(y), + 2 => sinpif_eval2(-y), + _ => -cospif_eval(y), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_f_sinpif() { + assert_eq!(f_sinpif(3.), 0.); + assert_eq!(f_sinpif(1.12199515e-7), 3.524852e-7); + assert_eq!(f_sinpif(-0.31706), -0.83934295); + assert_eq!(f_sinpif(0.30706), 0.8218538); + assert_eq!(f_sinpif(115.30706), -0.82185423); + assert!(f_sinpif(f32::INFINITY).is_nan()); + assert!(f_sinpif(f32::NEG_INFINITY).is_nan()); + assert!(f_sinpif(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_helper.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_helper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_helper.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_helper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,294 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::dyadic_float::DyadicFloat128; +use crate::rounding::CpuRound; +use crate::sin::{SinCos, get_sin_k_rational, sincos_eval}; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_dyadic::{range_reduction_small_f128_f128, sincos_eval_dyadic}; + +#[inline] +fn sin_eval_dd(z: DoubleDouble) -> DoubleDouble { + const SIN_C: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc65555555555555, 0xbfc5555555555555), + (0x3c01111111111111, 0x3f81111111111111), + (0xbb6a01a01a01a01a, 0xbf2a01a01a01a01a), + (0xbb6c154f8ddc6c00, 0x3ec71de3a556c734), + ]; + let x2 = DoubleDouble::quick_mult(z, z); + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(SIN_C[4]), + DoubleDouble::from_bit_pair(SIN_C[3]), + ); + + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[2])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[1])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[0])); + DoubleDouble::quick_mult(p, z) +} + +pub(crate) fn sin_dd_small(z: DoubleDouble) -> DoubleDouble { + let x_e = (z.hi.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 8 { + return sin_eval_dd(z); + } + + let (u_f128, k) = range_reduction_small_dd(z); + + let sin_cos = sincos_eval_dd(u_f128); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(sin_cos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(sin_cos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + rr +} + +pub(crate) fn sin_dd_small_fast(z: DoubleDouble) -> DoubleDouble { + let x_e = (z.hi.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 8 { + return sin_eval_dd(z); + } + + let (u_f128, k) = range_reduction_small_dd(z); + + let sin_cos = sincos_eval(u_f128); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(sin_cos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(sin_cos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + rr +} + +#[inline] +fn cos_eval_dd(z: DoubleDouble) -> DoubleDouble { + let x2 = DoubleDouble::quick_mult(z, z); + const COS_C: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0xbfe0000000000000), + (0x3c45555555555555, 0x3fa5555555555555), + (0x3bef49f49f49f49f, 0xbf56c16c16c16c17), + (0x3b3a01a01a01a01a, 0x3efa01a01a01a01a), + ]; + + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(COS_C[4]), + DoubleDouble::from_bit_pair(COS_C[3]), + ); + + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[2])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[1])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[0])); + + p +} + +pub(crate) fn cos_dd_small(z: DoubleDouble) -> DoubleDouble { + let x_e = (z.hi.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 8 { + return cos_eval_dd(z); + } + + let (u_f128, k) = range_reduction_small_dd(z); + + let sin_cos = sincos_eval_dd(u_f128); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k.wrapping_add(128) & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + let msin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let cos_k_cos_y = DoubleDouble::quick_mult(sin_cos.v_cos, cos_k); + let cos_k_msin_y = DoubleDouble::quick_mult(sin_cos.v_sin, msin_k); + + // cos_k_cos_y is always >> cos_k_msin_y + let mut rr = DoubleDouble::from_exact_add(cos_k_cos_y.hi, cos_k_msin_y.hi); + rr.lo += cos_k_cos_y.lo + cos_k_msin_y.lo; + + rr +} + +pub(crate) fn cos_dd_small_fast(z: DoubleDouble) -> DoubleDouble { + let x_e = (z.hi.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + if x_e < E_BIAS - 8 { + return cos_eval_dd(z); + } + + let (u_f128, k) = range_reduction_small_dd(z); + + let sin_cos = sincos_eval(u_f128); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k.wrapping_add(128) & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + let msin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let cos_k_cos_y = DoubleDouble::quick_mult(sin_cos.v_cos, cos_k); + let cos_k_msin_y = DoubleDouble::quick_mult(sin_cos.v_sin, msin_k); + + // cos_k_cos_y is always >> cos_k_msin_y + let mut rr = DoubleDouble::from_exact_add(cos_k_cos_y.hi, cos_k_msin_y.hi); + rr.lo += cos_k_cos_y.lo + cos_k_msin_y.lo; + + rr +} + +pub(crate) fn sin_f128_small(z: DyadicFloat128) -> DyadicFloat128 { + let (u_f128, k) = range_reduction_small_f128_f128(z); + + let sin_cos = sincos_eval_dyadic(&u_f128); + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sin_k_f128 = get_sin_k_rational(k as u64); + let cos_k_f128 = get_sin_k_rational((k as u64).wrapping_add(64)); + + // sin(x) = sin(k * pi/128 + u) + // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) + (sin_k_f128 * sin_cos.v_cos) + (cos_k_f128 * sin_cos.v_sin) +} + +pub(crate) fn cos_f128_small(z: DyadicFloat128) -> DyadicFloat128 { + let (u_f128, k) = range_reduction_small_f128_f128(z); + + let sin_cos = sincos_eval_dyadic(&u_f128); + // -sin(k * pi/128) = sin((k + 128) * pi/128) + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let msin_k_f128 = get_sin_k_rational((k as u64).wrapping_add(128)); + let cos_k_f128 = get_sin_k_rational((k as u64).wrapping_add(64)); + + // cos(x) = cos((k * pi/128 + u) + // = cos(u) * cos(k*pi/128) - sin(u) * sin(k*pi/128) + (cos_k_f128 * sin_cos.v_cos) + (msin_k_f128 * sin_cos.v_sin) +} + +#[inline] +pub(crate) fn sincos_eval_dd(u: DoubleDouble) -> SinCos { + const SIN_C: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0xbc65555555555555, 0xbfc5555555555555), + (0x3c01111111111111, 0x3f81111111111111), + (0xbb6a01a01a01a01a, 0xbf2a01a01a01a01a), + (0xbb6c154f8ddc6c00, 0x3ec71de3a556c734), + ]; + let x2 = DoubleDouble::quick_mult(u, u); + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(SIN_C[4]), + DoubleDouble::from_bit_pair(SIN_C[3]), + ); + + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[1])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(SIN_C[0])); + let sin_u = DoubleDouble::quick_mult(p, u); + + const COS_C: [(u64, u64); 5] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x0000000000000000, 0xbfe0000000000000), + (0x3c45555555555555, 0x3fa5555555555555), + (0x3bef49f49f49f49f, 0xbf56c16c16c16c17), + (0x3b3a01a01a01a01a, 0x3efa01a01a01a01a), + ]; + + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(COS_C[4]), + DoubleDouble::from_bit_pair(COS_C[3]), + ); + + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[1])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(COS_C[0])); + + let cos_u = p; + SinCos { + v_sin: sin_u, + v_cos: cos_u, + err: 0., + } +} + +#[inline] +pub(crate) fn range_reduction_small_dd(x: DoubleDouble) -> (DoubleDouble, i64) { + const MPI_OVER_128: [u64; 5] = [ + 0xbf9921fb54400000, + 0xbd70b4611a600000, + 0xbb43198a2e000000, + 0xb91b839a25200000, + 0xb6b2704453400000, + ]; + const ONE_TWENTY_EIGHT_OVER_PI_D: f64 = f64::from_bits(0x40445f306dc9c883); + let prod_hi = DoubleDouble::quick_mult_f64(x, ONE_TWENTY_EIGHT_OVER_PI_D); + let kd = prod_hi.to_f64().cpu_round(); + + let p_hi = f64::from_bits(MPI_OVER_128[0]); // hi + let p_mid = f64::from_bits(MPI_OVER_128[1]); // mid + let p_lo = f64::from_bits(MPI_OVER_128[2]); // lo + let p_lo_lo = f64::from_bits(MPI_OVER_128[3]); // lo_lo + + let mut q = DoubleDouble::f64_mul_f64_add(kd, p_hi, x); + q = DoubleDouble::f64_mul_f64_add(kd, p_mid, q); + q = DoubleDouble::f64_mul_f64_add(kd, p_lo, q); + q = DoubleDouble::f64_mul_f64_add(kd, p_lo_lo, q); + + (q, unsafe { kd.to_int_unchecked::() }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_table.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_table.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sin_table.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sin_table.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,287 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +pub(crate) static SIN_K_PI_OVER_128: [(u64, u64); 256] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbbfb1d63091a0130, 0x3f992155f7a3667e), + (0xbc2912bd0d569a90, 0x3fa91f65f10dd814), + (0xbc49a088a8bf6b2c, 0x3fb2d52092ce19f6), + (0xbc3e2718d26ed688, 0x3fb917a6bc29b42c), + (0x3c4a2704729ae56d, 0x3fbf564e56a9730e), + (0x3c513000a89a11e0, 0x3fc2c8106e8e613a), + (0x3c6531ff779ddac6, 0x3fc5e214448b3fc6), + (0xbc626d19b9ff8d82, 0x3fc8f8b83c69a60b), + (0xbc1af1439e521935, 0x3fcc0b826a7e4f63), + (0xbc642deef11da2c4, 0x3fcf19f97b215f1b), + (0x3c7824c20ab7aa9a, 0x3fd111d262b1f677), + (0xbc75d28da2c4612d, 0x3fd294062ed59f06), + (0x3c70c97c4afa2518, 0x3fd4135c94176601), + (0xbc1efdc0d58cf620, 0x3fd58f9a75ab1fdd), + (0xbc744b19e0864c5d, 0x3fd7088530fa459f), + (0xbc672cedd3d5a610, 0x3fd87de2a6aea963), + (0x3c66da81290bdbab, 0x3fd9ef7943a8ed8a), + (0x3c65b362cb974183, 0x3fdb5d1009e15cc0), + (0x3c56850e59c37f8f, 0x3fdcc66e9931c45e), + (0x3c5e0d891d3c6841, 0x3fde2b5d3806f63b), + (0xbc32ec1fc1b776b8, 0x3fdf8ba4dbf89aba), + (0xbc8a5a014347406c, 0x3fe073879922ffee), + (0xbc8ef23b69abe4f1, 0x3fe11eb3541b4b23), + (0x3c8b25dd267f6600, 0x3fe1c73b39ae68c8), + (0xbc85da743ef3770c, 0x3fe26d054cdd12df), + (0xbc6efcc626f74a6f, 0x3fe30ff7fce17035), + (0x3c7e3e25e3954964, 0x3fe3affa292050b9), + (0x3c68076a2cfdc6b3, 0x3fe44cf325091dd6), + (0x3c63c293edceb327, 0x3fe4e6cabbe3e5e9), + (0xbc875720992bfbb2, 0x3fe57d69348ceca0), + (0xbc7251b352ff2a37, 0x3fe610b7551d2cdf), + (0xbc8bdd3413b26456, 0x3fe6a09e667f3bcd), + (0x3c80d4ef0f1d915c, 0x3fe72d0837efff96), + (0xbc70f537acdf0ad7, 0x3fe7b5df226aafaf), + (0xbc76f420f8ea3475, 0x3fe83b0e0bff976e), + (0xbc82c5e12ed1336d, 0x3fe8bc806b151741), + (0x3c83d419a920df0b, 0x3fe93a22499263fb), + (0xbc830ee286712474, 0x3fe9b3e047f38741), + (0xbc7128bb015df175, 0x3fea29a7a0462782), + (0x3c39f630e8b6dac8, 0x3fea9b66290ea1a3), + (0xbc8926da300ffcce, 0x3feb090a58150200), + (0xbc8bc69f324e6d61, 0x3feb728345196e3e), + (0xbc8825a732ac700a, 0x3febd7c0ac6f952a), + (0xbc76e0b1757c8d07, 0x3fec38b2f180bdb1), + (0xbc52fb761e946603, 0x3fec954b213411f5), + (0xbc5e7b6bb5ab58ae, 0x3feced7af43cc773), + (0xbc84ef5295d25af2, 0x3fed4134d14dc93a), + (0x3c7457e610231ac2, 0x3fed906bcf328d46), + (0x3c883c37c6107db3, 0x3feddb13b6ccc23c), + (0xbc8014c76c126527, 0x3fee212104f686e5), + (0xbc616b56f2847754, 0x3fee6288ec48e112), + (0x3c8760b1e2e3f81e, 0x3fee9f4156c62dda), + (0x3c7e82c791f59cc2, 0x3feed740e7684963), + (0x3c752c7adc6b4989, 0x3fef0a7efb9230d7), + (0xbc7d7bafb51f72e6, 0x3fef38f3ac64e589), + (0x3c7562172a361fd3, 0x3fef6297cff75cb0), + (0x3c7ab256778ffcb6, 0x3fef8764fa714ba9), + (0xbc87a0a8ca13571f, 0x3fefa7557f08a517), + (0x3c81ec8668ecacee, 0x3fefc26470e19fd3), + (0xbc887df6378811c7, 0x3fefd88da3d12526), + (0x3c6521ecd0c67e35, 0x3fefe9cdad01883a), + (0xbc6c57bc2e24aa15, 0x3feff621e3796d7e), + (0xbc81354d4556e4cb, 0x3feffd886084cd0d), + (0x0000000000000000, 0x3ff0000000000000), + (0xbc81354d4556e4cb, 0x3feffd886084cd0d), + (0xbc6c57bc2e24aa15, 0x3feff621e3796d7e), + (0x3c6521ecd0c67e35, 0x3fefe9cdad01883a), + (0xbc887df6378811c7, 0x3fefd88da3d12526), + (0x3c81ec8668ecacee, 0x3fefc26470e19fd3), + (0xbc87a0a8ca13571f, 0x3fefa7557f08a517), + (0x3c7ab256778ffcb6, 0x3fef8764fa714ba9), + (0x3c7562172a361fd3, 0x3fef6297cff75cb0), + (0xbc7d7bafb51f72e6, 0x3fef38f3ac64e589), + (0x3c752c7adc6b4989, 0x3fef0a7efb9230d7), + (0x3c7e82c791f59cc2, 0x3feed740e7684963), + (0x3c8760b1e2e3f81e, 0x3fee9f4156c62dda), + (0xbc616b56f2847754, 0x3fee6288ec48e112), + (0xbc8014c76c126527, 0x3fee212104f686e5), + (0x3c883c37c6107db3, 0x3feddb13b6ccc23c), + (0x3c7457e610231ac2, 0x3fed906bcf328d46), + (0xbc84ef5295d25af2, 0x3fed4134d14dc93a), + (0xbc5e7b6bb5ab58ae, 0x3feced7af43cc773), + (0xbc52fb761e946603, 0x3fec954b213411f5), + (0xbc76e0b1757c8d07, 0x3fec38b2f180bdb1), + (0xbc8825a732ac700a, 0x3febd7c0ac6f952a), + (0xbc8bc69f324e6d61, 0x3feb728345196e3e), + (0xbc8926da300ffcce, 0x3feb090a58150200), + (0x3c39f630e8b6dac8, 0x3fea9b66290ea1a3), + (0xbc7128bb015df175, 0x3fea29a7a0462782), + (0xbc830ee286712474, 0x3fe9b3e047f38741), + (0x3c83d419a920df0b, 0x3fe93a22499263fb), + (0xbc82c5e12ed1336d, 0x3fe8bc806b151741), + (0xbc76f420f8ea3475, 0x3fe83b0e0bff976e), + (0xbc70f537acdf0ad7, 0x3fe7b5df226aafaf), + (0x3c80d4ef0f1d915c, 0x3fe72d0837efff96), + (0xbc8bdd3413b26456, 0x3fe6a09e667f3bcd), + (0xbc7251b352ff2a37, 0x3fe610b7551d2cdf), + (0xbc875720992bfbb2, 0x3fe57d69348ceca0), + (0x3c63c293edceb327, 0x3fe4e6cabbe3e5e9), + (0x3c68076a2cfdc6b3, 0x3fe44cf325091dd6), + (0x3c7e3e25e3954964, 0x3fe3affa292050b9), + (0xbc6efcc626f74a6f, 0x3fe30ff7fce17035), + (0xbc85da743ef3770c, 0x3fe26d054cdd12df), + (0x3c8b25dd267f6600, 0x3fe1c73b39ae68c8), + (0xbc8ef23b69abe4f1, 0x3fe11eb3541b4b23), + (0xbc8a5a014347406c, 0x3fe073879922ffee), + (0xbc32ec1fc1b776b8, 0x3fdf8ba4dbf89aba), + (0x3c5e0d891d3c6841, 0x3fde2b5d3806f63b), + (0x3c56850e59c37f8f, 0x3fdcc66e9931c45e), + (0x3c65b362cb974183, 0x3fdb5d1009e15cc0), + (0x3c66da81290bdbab, 0x3fd9ef7943a8ed8a), + (0xbc672cedd3d5a610, 0x3fd87de2a6aea963), + (0xbc744b19e0864c5d, 0x3fd7088530fa459f), + (0xbc1efdc0d58cf620, 0x3fd58f9a75ab1fdd), + (0x3c70c97c4afa2518, 0x3fd4135c94176601), + (0xbc75d28da2c4612d, 0x3fd294062ed59f06), + (0x3c7824c20ab7aa9a, 0x3fd111d262b1f677), + (0xbc642deef11da2c4, 0x3fcf19f97b215f1b), + (0xbc1af1439e521935, 0x3fcc0b826a7e4f63), + (0xbc626d19b9ff8d82, 0x3fc8f8b83c69a60b), + (0x3c6531ff779ddac6, 0x3fc5e214448b3fc6), + (0x3c513000a89a11e0, 0x3fc2c8106e8e613a), + (0x3c4a2704729ae56d, 0x3fbf564e56a9730e), + (0xbc3e2718d26ed688, 0x3fb917a6bc29b42c), + (0xbc49a088a8bf6b2c, 0x3fb2d52092ce19f6), + (0xbc2912bd0d569a90, 0x3fa91f65f10dd814), + (0xbbfb1d63091a0130, 0x3f992155f7a3667e), + (0x0000000000000000, 0x0000000000000000), + (0x3bfb1d63091a0130, 0xbf992155f7a3667e), + (0x3c2912bd0d569a90, 0xbfa91f65f10dd814), + (0x3c49a088a8bf6b2c, 0xbfb2d52092ce19f6), + (0x3c3e2718d26ed688, 0xbfb917a6bc29b42c), + (0xbc4a2704729ae56d, 0xbfbf564e56a9730e), + (0xbc513000a89a11e0, 0xbfc2c8106e8e613a), + (0xbc6531ff779ddac6, 0xbfc5e214448b3fc6), + (0x3c626d19b9ff8d82, 0xbfc8f8b83c69a60b), + (0x3c1af1439e521935, 0xbfcc0b826a7e4f63), + (0x3c642deef11da2c4, 0xbfcf19f97b215f1b), + (0xbc7824c20ab7aa9a, 0xbfd111d262b1f677), + (0x3c75d28da2c4612d, 0xbfd294062ed59f06), + (0xbc70c97c4afa2518, 0xbfd4135c94176601), + (0x3c1efdc0d58cf620, 0xbfd58f9a75ab1fdd), + (0x3c744b19e0864c5d, 0xbfd7088530fa459f), + (0x3c672cedd3d5a610, 0xbfd87de2a6aea963), + (0xbc66da81290bdbab, 0xbfd9ef7943a8ed8a), + (0xbc65b362cb974183, 0xbfdb5d1009e15cc0), + (0xbc56850e59c37f8f, 0xbfdcc66e9931c45e), + (0xbc5e0d891d3c6841, 0xbfde2b5d3806f63b), + (0x3c32ec1fc1b776b8, 0xbfdf8ba4dbf89aba), + (0x3c8a5a014347406c, 0xbfe073879922ffee), + (0x3c8ef23b69abe4f1, 0xbfe11eb3541b4b23), + (0xbc8b25dd267f6600, 0xbfe1c73b39ae68c8), + (0x3c85da743ef3770c, 0xbfe26d054cdd12df), + (0x3c6efcc626f74a6f, 0xbfe30ff7fce17035), + (0xbc7e3e25e3954964, 0xbfe3affa292050b9), + (0xbc68076a2cfdc6b3, 0xbfe44cf325091dd6), + (0xbc63c293edceb327, 0xbfe4e6cabbe3e5e9), + (0x3c875720992bfbb2, 0xbfe57d69348ceca0), + (0x3c7251b352ff2a37, 0xbfe610b7551d2cdf), + (0x3c8bdd3413b26456, 0xbfe6a09e667f3bcd), + (0xbc80d4ef0f1d915c, 0xbfe72d0837efff96), + (0x3c70f537acdf0ad7, 0xbfe7b5df226aafaf), + (0x3c76f420f8ea3475, 0xbfe83b0e0bff976e), + (0x3c82c5e12ed1336d, 0xbfe8bc806b151741), + (0xbc83d419a920df0b, 0xbfe93a22499263fb), + (0x3c830ee286712474, 0xbfe9b3e047f38741), + (0x3c7128bb015df175, 0xbfea29a7a0462782), + (0xbc39f630e8b6dac8, 0xbfea9b66290ea1a3), + (0x3c8926da300ffcce, 0xbfeb090a58150200), + (0x3c8bc69f324e6d61, 0xbfeb728345196e3e), + (0x3c8825a732ac700a, 0xbfebd7c0ac6f952a), + (0x3c76e0b1757c8d07, 0xbfec38b2f180bdb1), + (0x3c52fb761e946603, 0xbfec954b213411f5), + (0x3c5e7b6bb5ab58ae, 0xbfeced7af43cc773), + (0x3c84ef5295d25af2, 0xbfed4134d14dc93a), + (0xbc7457e610231ac2, 0xbfed906bcf328d46), + (0xbc883c37c6107db3, 0xbfeddb13b6ccc23c), + (0x3c8014c76c126527, 0xbfee212104f686e5), + (0x3c616b56f2847754, 0xbfee6288ec48e112), + (0xbc8760b1e2e3f81e, 0xbfee9f4156c62dda), + (0xbc7e82c791f59cc2, 0xbfeed740e7684963), + (0xbc752c7adc6b4989, 0xbfef0a7efb9230d7), + (0x3c7d7bafb51f72e6, 0xbfef38f3ac64e589), + (0xbc7562172a361fd3, 0xbfef6297cff75cb0), + (0xbc7ab256778ffcb6, 0xbfef8764fa714ba9), + (0x3c87a0a8ca13571f, 0xbfefa7557f08a517), + (0xbc81ec8668ecacee, 0xbfefc26470e19fd3), + (0x3c887df6378811c7, 0xbfefd88da3d12526), + (0xbc6521ecd0c67e35, 0xbfefe9cdad01883a), + (0x3c6c57bc2e24aa15, 0xbfeff621e3796d7e), + (0x3c81354d4556e4cb, 0xbfeffd886084cd0d), + (0x0000000000000000, 0xbff0000000000000), + (0x3c81354d4556e4cb, 0xbfeffd886084cd0d), + (0x3c6c57bc2e24aa15, 0xbfeff621e3796d7e), + (0xbc6521ecd0c67e35, 0xbfefe9cdad01883a), + (0x3c887df6378811c7, 0xbfefd88da3d12526), + (0xbc81ec8668ecacee, 0xbfefc26470e19fd3), + (0x3c87a0a8ca13571f, 0xbfefa7557f08a517), + (0xbc7ab256778ffcb6, 0xbfef8764fa714ba9), + (0xbc7562172a361fd3, 0xbfef6297cff75cb0), + (0x3c7d7bafb51f72e6, 0xbfef38f3ac64e589), + (0xbc752c7adc6b4989, 0xbfef0a7efb9230d7), + (0xbc7e82c791f59cc2, 0xbfeed740e7684963), + (0xbc8760b1e2e3f81e, 0xbfee9f4156c62dda), + (0x3c616b56f2847754, 0xbfee6288ec48e112), + (0x3c8014c76c126527, 0xbfee212104f686e5), + (0xbc883c37c6107db3, 0xbfeddb13b6ccc23c), + (0xbc7457e610231ac2, 0xbfed906bcf328d46), + (0x3c84ef5295d25af2, 0xbfed4134d14dc93a), + (0x3c5e7b6bb5ab58ae, 0xbfeced7af43cc773), + (0x3c52fb761e946603, 0xbfec954b213411f5), + (0x3c76e0b1757c8d07, 0xbfec38b2f180bdb1), + (0x3c8825a732ac700a, 0xbfebd7c0ac6f952a), + (0x3c8bc69f324e6d61, 0xbfeb728345196e3e), + (0x3c8926da300ffcce, 0xbfeb090a58150200), + (0xbc39f630e8b6dac8, 0xbfea9b66290ea1a3), + (0x3c7128bb015df175, 0xbfea29a7a0462782), + (0x3c830ee286712474, 0xbfe9b3e047f38741), + (0xbc83d419a920df0b, 0xbfe93a22499263fb), + (0x3c82c5e12ed1336d, 0xbfe8bc806b151741), + (0x3c76f420f8ea3475, 0xbfe83b0e0bff976e), + (0x3c70f537acdf0ad7, 0xbfe7b5df226aafaf), + (0xbc80d4ef0f1d915c, 0xbfe72d0837efff96), + (0x3c8bdd3413b26456, 0xbfe6a09e667f3bcd), + (0x3c7251b352ff2a37, 0xbfe610b7551d2cdf), + (0x3c875720992bfbb2, 0xbfe57d69348ceca0), + (0xbc63c293edceb327, 0xbfe4e6cabbe3e5e9), + (0xbc68076a2cfdc6b3, 0xbfe44cf325091dd6), + (0xbc7e3e25e3954964, 0xbfe3affa292050b9), + (0x3c6efcc626f74a6f, 0xbfe30ff7fce17035), + (0x3c85da743ef3770c, 0xbfe26d054cdd12df), + (0xbc8b25dd267f6600, 0xbfe1c73b39ae68c8), + (0x3c8ef23b69abe4f1, 0xbfe11eb3541b4b23), + (0x3c8a5a014347406c, 0xbfe073879922ffee), + (0x3c32ec1fc1b776b8, 0xbfdf8ba4dbf89aba), + (0xbc5e0d891d3c6841, 0xbfde2b5d3806f63b), + (0xbc56850e59c37f8f, 0xbfdcc66e9931c45e), + (0xbc65b362cb974183, 0xbfdb5d1009e15cc0), + (0xbc66da81290bdbab, 0xbfd9ef7943a8ed8a), + (0x3c672cedd3d5a610, 0xbfd87de2a6aea963), + (0x3c744b19e0864c5d, 0xbfd7088530fa459f), + (0x3c1efdc0d58cf620, 0xbfd58f9a75ab1fdd), + (0xbc70c97c4afa2518, 0xbfd4135c94176601), + (0x3c75d28da2c4612d, 0xbfd294062ed59f06), + (0xbc7824c20ab7aa9a, 0xbfd111d262b1f677), + (0x3c642deef11da2c4, 0xbfcf19f97b215f1b), + (0x3c1af1439e521935, 0xbfcc0b826a7e4f63), + (0x3c626d19b9ff8d82, 0xbfc8f8b83c69a60b), + (0xbc6531ff779ddac6, 0xbfc5e214448b3fc6), + (0xbc513000a89a11e0, 0xbfc2c8106e8e613a), + (0xbc4a2704729ae56d, 0xbfbf564e56a9730e), + (0x3c3e2718d26ed688, 0xbfb917a6bc29b42c), + (0x3c49a088a8bf6b2c, 0xbfb2d52092ce19f6), + (0x3c2912bd0d569a90, 0xbfa91f65f10dd814), + (0x3bfb1d63091a0130, 0xbf992155f7a3667e), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sinc.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sinc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::DyadicFloat128; +use crate::sin::{get_sin_k_rational, range_reduction_small, sincos_eval}; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_dyadic::{range_reduction_small_f128, sincos_eval_dyadic}; +use crate::sincos_reduce::LargeArgumentReduction; + +#[cold] +#[inline(never)] +fn sinc_refine(argument_reduction: &mut LargeArgumentReduction, x: f64, x_e: u64, k: u64) -> f64 { + const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + let u_f128 = if x_e < EXP_BIAS + 16 { + range_reduction_small_f128(x) + } else { + argument_reduction.accurate() + }; + + let sin_cos = sincos_eval_dyadic(&u_f128); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sin_k_f128 = get_sin_k_rational(k); + let cos_k_f128 = get_sin_k_rational(k.wrapping_add(64)); + + // sin(x) = sin(k * pi/128 + u) + // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) + let r = (sin_k_f128 * sin_cos.v_cos) + (cos_k_f128 * sin_cos.v_sin); + + let reciprocal = DyadicFloat128::accurate_reciprocal(x); + (r * reciprocal).fast_as_f64() +} + +/// Computes sinc(x) +/// +/// Max ULP 0.5 +pub fn f_sinc(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS + 16 { + // |x| < 2^-26 + if x_e < E_BIAS - 26 { + // Signed zeros. + if x == 0.0 { + return 1.0; + } + + // For |x| < 2^-26, sinc(x) ~ 1 - x^2/6 + const M_ONE_OVER_6: f64 = f64::from_bits(0xbfc5555555555555); + return f_fmla(x, x * M_ONE_OVER_6, 1.); + } + + // // Small range reduction. + (y, k) = range_reduction_small(x); + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sin(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let r_sincos = sincos_eval(y); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = DoubleDouble::div_dd_f64(rr, x); + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return r_upper; + } + sinc_refine(&mut argument_reduction, x, x_e, k) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_sinc() { + assert_eq!(f_sinc(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004764135737289025), 1.); + assert_eq!(f_sinc(0.1), 0.9983341664682815); + assert_eq!(f_sinc(0.9), 0.870363232919426); + assert_eq!(f_sinc(-0.1), 0.9983341664682815); + assert_eq!(f_sinc(-0.9), 0.870363232919426); + assert!(f_sinc(f64::INFINITY).is_nan()); + assert!(f_sinc(f64::NEG_INFINITY).is_nan()); + assert!(f_sinc(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,253 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::*; +use crate::double_double::DoubleDouble; +use crate::sin::{ + cos_accurate_near_zero, range_reduction_small, sin_accurate_near_zero, sincos_eval, +}; +use crate::sin_helper::sincos_eval_dd; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_reduce::LargeArgumentReduction; +use std::hint::black_box; + +/// Sine and cosine for double precision +/// +/// ULP 0.5 +pub fn f_sincos(x: f64) -> (f64, f64) { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS + 16 { + // |x| < 2^-26 + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + if ax <= 0x3fa921fbd34a9550 { + // |x| <= 0.0490874 + if x_e < E_BIAS - 27 { + // Signed zeros. + if x == 0.0 { + return (x, 1.0); + } + // For |x| < 2^-26, |sin(x) - x| < ulp(x)/2. + let s_sin = dyad_fmla(x, f64::from_bits(0xbc90000000000000), x); + let s_cos = black_box(1.0) - min_normal_f64(); + return (s_sin, s_cos); + } + + // Polynomial for sin(x)/x + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_sin = sin(y)/y; + // Q = fpminimax(f_sin, [|0, 2, 4, 6, 8|], [|1, D...|], d, relative, floating); + const SIN_C: [u64; 4] = [ + 0xbfc5555555555555, + 0x3f8111111110e45a, + 0xbf2a019ffd7fdaaf, + 0x3ec71819b9bf01ef, + ]; + + let x2 = x * x; + let x4 = x2 * x2; + + let p01 = f_fmla(x2, f64::from_bits(SIN_C[1]), f64::from_bits(SIN_C[0])); + let p23 = f_fmla(x2, f64::from_bits(SIN_C[3]), f64::from_bits(SIN_C[2])); + let w0 = f_fmla(x4, p23, p01); + let w1 = x2 * w0 * x; + let r_sin = DoubleDouble::from_exact_add(x, w1); + + // Polynomial for cos(x) + // Generated by Sollya: + // d = [0, 0.0490874]; + // f_cos = cos(y); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|1, D...|], d, relative, floating); + const COS_C: [u64; 4] = [ + 0xbfe0000000000000, + 0x3fa55555555554a4, + 0xbf56c16c1619b84a, + 0x3efa013d3d01cf7f, + ]; + let p01 = f_fmla(x2, f64::from_bits(COS_C[1]), f64::from_bits(COS_C[0])); + let p23 = f_fmla(x2, f64::from_bits(COS_C[3]), f64::from_bits(COS_C[2])); + let w0 = f_fmla(x4, p23, p01); + let w1 = x2 * w0; + let r_cos = DoubleDouble::from_exact_add(1., w1); + + let err = f_fmla( + x2, + f64::from_bits(0x3cb0000000000000), // 2^-52 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + + let sin_ub = r_sin.hi + (r_sin.lo + err); + let sin_lb = r_sin.hi + (r_sin.lo - err); + let sin_x = if sin_ub == sin_lb { + sin_ub + } else { + sin_accurate_near_zero(x) + }; + + let cos_ub = r_cos.hi + (r_cos.lo + err); + let cos_lb = r_cos.hi + (r_cos.lo - err); + let cos_x = if cos_ub == cos_lb { + cos_ub + } else { + cos_accurate_near_zero(x) + }; + return (sin_x, cos_x); + } else { + // // Small range reduction. + (y, k) = range_reduction_small(x); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sin(+-Inf) = NaN + return (x + f64::NAN, x + f64::NAN); + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let r_sincos = sincos_eval(y); + let (sin_y, cos_y) = (r_sincos.v_sin, r_sincos.v_cos); + + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let msin_k = -sin_k; + + // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128). + // So k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + let sin_k_cos_y = DoubleDouble::quick_mult(cos_y, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(sin_y, cos_k); + // cos(x) = cos((k * pi/128 + y) + // = cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128) + let cos_k_cos_y = DoubleDouble::quick_mult(cos_y, cos_k); + let msin_k_sin_y = DoubleDouble::quick_mult(sin_y, msin_k); + + // cos_k_sin_y is always >> sin_k_cos_y + let mut sin_dd = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + // cos_k_cos_y is always >> msin_k_sin_y + let mut cos_dd = DoubleDouble::from_exact_add(cos_k_cos_y.hi, msin_k_sin_y.hi); + sin_dd.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + cos_dd.lo += msin_k_sin_y.lo + cos_k_cos_y.lo; + + let sin_lp = sin_dd.lo + r_sincos.err; + let sin_lm = sin_dd.lo - r_sincos.err; + let cos_lp = cos_dd.lo + r_sincos.err; + let cos_lm = cos_dd.lo - r_sincos.err; + + let sin_upper = sin_dd.hi + sin_lp; + let sin_lower = sin_dd.hi + sin_lm; + let cos_upper = cos_dd.hi + cos_lp; + let cos_lower = cos_dd.hi + cos_lm; + + // Ziv's rounding test. + if sin_upper == sin_lower && cos_upper == cos_lower { + return (sin_upper, cos_upper); + } + + sincos_hard(y, sin_k, cos_k, sin_upper, sin_lower, cos_upper, cos_lower) +} + +#[cold] +#[inline(never)] +#[allow(clippy::too_many_arguments)] +fn sincos_hard( + y: DoubleDouble, + sin_k: DoubleDouble, + cos_k: DoubleDouble, + sin_upper: f64, + sin_lower: f64, + cos_upper: f64, + cos_lower: f64, +) -> (f64, f64) { + let r_sincos = sincos_eval_dd(y); + + let msin_k = -sin_k; + + let sin_x = if sin_upper == sin_lower { + sin_upper + } else { + // sin(x) = sin((k * pi/128 + u) + // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) + + DoubleDouble::mul_add(sin_k, r_sincos.v_cos, cos_k * r_sincos.v_sin).to_f64() + }; + + let cos_x = if cos_upper == cos_lower { + cos_upper + } else { + // cos(x) = cos((k * pi/128 + u) + // = cos(u) * cos(k*pi/128) - sin(u) * sin(k*pi/128) + DoubleDouble::mul_add(cos_k, r_sincos.v_cos, msin_k * r_sincos.v_sin).to_f64() + }; + (sin_x, cos_x) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_sincos_test() { + let subnormal = f_sincos(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015708065354637772); + assert_eq!(subnormal.0, 1.5708065354637772e-307); + assert_eq!(subnormal.1, 1.0); + let zx_0 = f_sincos(0.0); + assert_eq!(zx_0.0, 0.0); + assert_eq!(zx_0.1, 1.0); + let zx_1 = f_sincos(1.0); + assert_eq!(zx_1.0, 0.8414709848078965); + assert_eq!(zx_1.1, 0.5403023058681398); + let zx_0_p5 = f_sincos(-0.5); + assert_eq!(zx_0_p5.0, -0.479425538604203); + assert_eq!(zx_0_p5.1, 0.8775825618903728); + + let zx_1 = f_sincos(0.002341235432); + assert_eq!(zx_1.0, 0.0023412332931324344); + assert_eq!(zx_1.1, 0.9999972593095778); + + let zx_1 = f_sincos(0.0198676543432); + assert_eq!(zx_1.0, 0.019866347330026367); + assert_eq!(zx_1.1, 0.9998026446473137); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_dyadic.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_dyadic.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_dyadic.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_dyadic.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,558 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; +use crate::sincos_reduce_tables::ONE_TWENTY_EIGHT_OVER_PI; + +pub(crate) fn range_reduction_small_f128(x: f64) -> DyadicFloat128 { + const PI_OVER_128_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc90f_daa2_2168_c234_c4c6_628b_80dc_1cd1_u128, + }; + const ONE_TWENTY_EIGHT_OVER_PI_D: f64 = f64::from_bits(0x40445f306dc9c883); + let prod_hi = x * ONE_TWENTY_EIGHT_OVER_PI_D; + let kd = prod_hi.cpu_round(); + + let mk_f128 = DyadicFloat128::new_from_f64(-kd); + let x_f128 = DyadicFloat128::new_from_f64(x); + let over_pi3 = ONE_TWENTY_EIGHT_OVER_PI[3]; + let p_hi = x_f128.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.0))); + let p_mid = x_f128.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.1))); + let p_lo = x_f128.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.2))); + let s_hi = p_hi.quick_add(&mk_f128); + let s_lo = p_mid.quick_add(&p_lo); + let y = s_hi.quick_add(&s_lo); + y.quick_mul(&PI_OVER_128_F128) +} + +pub(crate) fn range_reduction_small_f128_f128(x: DyadicFloat128) -> (DyadicFloat128, i64) { + const PI_OVER_128_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc90f_daa2_2168_c234_c4c6_628b_80dc_1cd1_u128, + }; + const ONE_TWENTY_EIGHT_OVER_PI_D: f64 = f64::from_bits(0x40445f306dc9c883); + let prod_hi = x.fast_as_f64() * ONE_TWENTY_EIGHT_OVER_PI_D; + let kd = prod_hi.cpu_round(); + + let mk_f128 = DyadicFloat128::new_from_f64(-kd); + let over_pi3 = ONE_TWENTY_EIGHT_OVER_PI[3]; + let p_hi = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.0))); + let p_mid = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.1))); + let p_lo = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.2))); + let p_lo_lo = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.3))); + let s_hi = p_hi.quick_add(&mk_f128); + let s_lo = p_mid.quick_add(&p_lo); + let y = (s_hi + s_lo) + p_lo_lo; + (y.quick_mul(&PI_OVER_128_F128), kd as i64) +} + +// pub(crate) fn range_reduction_small_f128_f128(x: DyadicFloat128) -> (DyadicFloat128, u64) { +// const PI_OVER_128_F128: DyadicFloat128 = DyadicFloat128 { +// sign: DyadicSign::Pos, +// exponent: -133, +// mantissa: 0xc90f_daa2_2168_c234_c4c6_628b_80dc_1cd1_u128, +// }; +// const ONE_TWENTY_EIGHT_OVER_PI_D: f64 = f64::from_bits(0x40445f306dc9c883); +// let prod_hi = x.fast_as_f64() * ONE_TWENTY_EIGHT_OVER_PI_D; +// let kd = prod_hi.round(); +// +// let mk_f128 = DyadicFloat128::new_from_f64(-kd); +// let over_pi3 = ONE_TWENTY_EIGHT_OVER_PI[3]; +// let p_hi = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.0))); +// let p_mid = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.1))); +// let p_lo = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.2))); +// let p_lo_lo = x.quick_mul(&DyadicFloat128::new_from_f64(f64::from_bits(over_pi3.3))); +// let s_hi = p_hi.quick_add(&mk_f128); +// let s_lo = p_mid.quick_add(&p_lo); +// let s_lo_lo = p_lo_lo.quick_add(&p_lo_lo); +// let y = s_hi.quick_add(&s_lo).quick_add(&s_lo_lo); +// (y.quick_mul(&PI_OVER_128_F128), (kd as i64) as u64) +// } + +pub(crate) struct SinCosDyadic { + pub(crate) v_sin: DyadicFloat128, + pub(crate) v_cos: DyadicFloat128, +} + +#[cold] +pub(crate) fn sincos_eval_dyadic(u: &DyadicFloat128) -> SinCosDyadic { + let u_sq = u.quick_mul(u); + + // sin(u) ~ x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - x^11/11! + x^13/13! + static SIN_COEFFS: [DyadicFloat128; 7] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 1 + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, // -1/3! + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0x88888888_88888888_88888888_88888889_u128, + }, // 1/5! + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -140, + mantissa: 0xd00d00d0_0d00d00d_00d00d00_d00d00d0_u128, + }, // -1/7! + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -146, + mantissa: 0xb8ef1d2a_b6399c7d_560e4472_800b8ef2_u128, + }, // 1/9! + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -153, + mantissa: 0xd7322b3f_aa271c7f_3a3f25c1_bee38f10_u128, + }, // -1/11! + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -160, + mantissa: 0xb092309d_43684be5_1c198e91_d7b4269e_u128, + }, // 1/13! + ]; + + // cos(u) ~ 1 - x^2/2 + x^4/4! - x^6/6! + x^8/8! - x^10/10! + x^12/12! + static COS_COEFFS: [DyadicFloat128; 7] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 1.0 + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -128, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }, // 1/2 + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, // 1/4! + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -137, + mantissa: 0xb60b60b6_0b60b60b_60b60b60_b60b60b6_u128, + }, // 1/6! + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -143, + mantissa: 0xd00d00d0_0d00d00d_00d00d00_d00d00d0_u128, + }, // 1/8! + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -149, + mantissa: 0x93f27dbb_c4fae397_780b69f5_333c725b_u128, + }, // 1/10! + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -156, + mantissa: 0x8f76c77f_c6c4bdaa_26d4c3d6_7f425f60_u128, + }, // 1/12! + ]; + + let mut sin_u = SIN_COEFFS[6]; + for i in (0..7).rev() { + sin_u = sin_u * u_sq + SIN_COEFFS[i]; + } + sin_u = sin_u * *u; + + let mut cos_u = COS_COEFFS[6]; + for i in (0..7).rev() { + cos_u = cos_u * u_sq + COS_COEFFS[i]; + } + + SinCosDyadic { + v_sin: sin_u, + v_cos: cos_u, + } +} + +/* + Sage math: + # Sin K PI over 128 + R = RealField(128) + π = R.pi() + + def format_hex(value): + l = hex(value)[2:] + n = 4 + x = [l[i:i + n] for i in range(0, len(l), n)] + return "0x" + "_".join(x) + "_u128" + + def print_dyadic(value): + (s, m, e) = RealField(128)(value).sign_mantissa_exponent(); + print("DyadicFloat128 {") + print(f" sign: DyadicSign::{'Pos' if s >= 0 else 'Neg'},") + print(f" exponent: {e},") + print(f" mantissa: {format_hex(m)},") + print("},") + + # Generate array entries + print("pub(crate) static SIN_K_PI_OVER_128_F128: [DyadicFloat128; 65] = [") + for k in range(65): + value = R(k) * π / 128 + print_dyadic(value.sin()) + + print("];") +*/ +pub(crate) static SIN_K_PI_OVER_128_F128: [DyadicFloat128; 65] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0x0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc90a_afbd_1b33_efc9_c539_edcb_fda0_cf2c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xc8fb_2f88_6ec0_9f37_6a17_954b_2b7c_5171_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x96a9_0496_70cf_ae65_f775_7409_4d3c_35c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xc8bd_35e1_4da1_5f0e_c739_6c89_4bbf_7389_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xfab2_72b5_4b98_71a2_7047_29ae_56d7_8a37_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9640_8374_7309_d113_000a_89a1_1e07_c1ff_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xaf10_a224_59fe_32a6_3fee_f3bb_58b1_f10d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xc7c5_c1e3_4d30_55b2_5cc8_c00e_4fcc_d850_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xe05c_1353_f27b_17e5_0ebc_61ad_e6ca_83cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xf8cf_cbd9_0af8_d57a_4221_dc4b_a772_598d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x888e_9315_8fb3_bb04_9841_56f5_5334_4306_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x94a0_3176_acf8_2d45_ae4b_a773_da6b_f754_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa09a_e4a0_bb30_0a19_2f89_5f44_a303_cc0b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xac7c_d3ad_58fe_e7f0_811f_9539_84ef_f83e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb844_2987_d22c_f576_9cc3_ef36_746d_e3b8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xc3ef_1535_754b_168d_3122_c2a5_9efd_dc37_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcf7b_ca1d_476c_516d_a812_90bd_baad_62e4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xdae8_804f_0ae6_015b_362c_b974_182e_3030_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe633_74c9_8e22_f0b4_2872_ce1b_fc7a_d1cc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf15a_e9c0_37b1_d8f0_6c48_e9e3_420b_0f1d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xfc5d_26df_c4d5_cfda_27c0_7c91_1290_b8d1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x839c_3cc9_17ff_6cb4_bfd7_9717_f288_0abf_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x88f5_9aa0_da59_1421_b892_ca83_61d8_c84c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8e39_d9cd_7346_4364_bba4_cfec_bff5_4868_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9368_2a66_e896_f544_b178_2191_1e71_c16e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x987f_bfe7_0b81_a708_19ce_c845_ac87_a5c6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9d7f_d149_0285_c9e3_e25e_3954_9638_ae67_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa267_9928_48ee_b0c0_3b51_67ee_359a_234e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa736_55df_1f2f_489e_149f_6e75_9934_68a2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xabeb_49a4_6764_fd15_1bec_da80_89c1_a94c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb085_baa8_e966_f6da_e4ca_d00d_5c94_bcd1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb504_f333_f9de_6484_597d_89b3_754a_be9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb968_41bf_7ffc_b21a_9de1_e3b2_2b8b_f4db_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbdae_f913_557d_76f0_ac85_320f_528d_6d5c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc1d8_705f_fcbb_6e90_bdf0_715c_b8b2_0bd7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc5e4_0358_a8ba_05a7_43da_25d9_9267_326b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc9d1_124c_931f_da7a_8335_241b_e169_3225_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xcd9f_023f_9c3a_059e_23af_31db_7179_a4a9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd14d_3d02_313c_0eed_744f_ea20_e8ab_ef92_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd4db_3148_750d_1819_f630_e8b6_dac8_3e68_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xd848_52c0_a80f_fcdb_24b9_fe00_6635_74a4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdb94_1a28_cb71_ec87_2c19_b632_53da_43fb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xdebe_0563_7ca9_4cfb_4b19_aa71_fec3_ae6c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe1c5_978c_05ed_8691_f4e8_a837_2f8c_5810_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe4aa_5909_a08f_a7b4_1227_85ae_67f5_515c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xe76b_d7a1_e63b_9786_1251_2952_9d48_a92f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xea09_a68a_6e49_cd62_15ad_45b4_a1b5_e823_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xec83_5e79_946a_3145_7e61_0231_ac1d_6181_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xeed8_9db6_6611_e307_86f8_c20f_b664_b01b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf109_0827_b437_25fd_6712_7db3_5b28_7315_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf314_4762_4708_8f74_a548_6bdc_455d_56a3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf4fa_0ab6_316e_d2ec_163c_5c7f_03b7_18c5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf6ba_073b_424b_19e8_2c79_1f59_cc1f_fc23_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf853_f7dc_9186_b952_c7ad_c6b4_9888_91ba_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xf9c7_9d63_272c_4628_4504_ae08_d19b_2981_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfb14_be7f_bae5_8156_2172_a361_fd2a_722f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfc3b_27d3_8a5d_49ab_2567_78ff_cb5c_1769_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfd3a_abf8_4528_b50b_eae6_bd95_1c1d_abbd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfe13_2387_0cfe_9a3d_90cd_1d95_9db6_74ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xfec4_6d1e_8929_2cf0_4139_0efd_c726_e9ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xff4e_6d68_0c41_d0a9_0f66_8633_f1ab_858a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xffb1_0f1b_cb6b_ef1d_421e_8eda_af59_453e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xffec_4304_2668_65d9_5657_5523_6696_1732_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0x8000_0000_0000_0000_0000_0000_0000_0000_u128, + }, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_reduce.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_reduce.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,555 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::set_exponent_f64; +use crate::common::{dd_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::rounding::CpuRound; +use crate::sincos_reduce_tables::ONE_TWENTY_EIGHT_OVER_PI; + +#[derive(Debug)] +pub(crate) struct AngleReduced { + pub(crate) angle: DoubleDouble, +} + +#[derive(Default)] +pub(crate) struct LargeArgumentReduction { + x_reduced: f64, + idx: u64, + y_hi: f64, + y_lo: f64, + // Low part of x * ONE_TWENTY_EIGHT_OVER_PI[idx][1]. + y_mid: DoubleDouble, +} + +// For large range |x| >= 2^16, we perform the range reduction computations as: +// u = x - k * pi/128 = (pi/128) * (x * (128/pi) - k). +// We use the exponent of x to find 4 double-chunks of 128/pi: +// c_hi, c_mid, c_lo, c_lo_2 such that: +// 1) ulp(round(x * c_hi, D, RN)) >= 2^8 = 256, +// 2) If x * c_hi = ph_hi + ph_lo and x * c_mid = pm_hi + pm_lo, then +// min(ulp(ph_lo), ulp(pm_hi)) >= 2^-53. +// This will allow us to drop the high part ph_hi and the addition: +// (ph_lo + pm_hi) mod 1 +// can be exactly representable in a double precision. +// This will allow us to do split the computations as: +// (x * 256/pi) ~ x * (c_hi + c_mid + c_lo + c_lo_2) (mod 256) +// ~ (ph_lo + pm_hi) + (pm_lo + x * c_lo) + x * c_lo_2. +// Then, +// round(x * 128/pi) = round(ph_lo + pm_hi) (mod 256) +// And the high part of fractional part of (x * 128/pi) can simply be: +// {x * 128/pi}_hi = {ph_lo + pm_hi}. +// To prevent overflow when x is very large, we simply scale up +// (c_hi, c_mid, c_lo, c_lo_2) by a fixed power of 2 (based on the index) and +// scale down x by the same amount. +impl LargeArgumentReduction { + #[cold] + pub(crate) fn accurate(&self) -> DyadicFloat128 { + // Sage math: + // R = RealField(128) + // π = R.pi() + // + // def format_hex(value): + // l = hex(value)[2:] + // n = 4 + // x = [l[i:i + n] for i in range(0, len(l), n)] + // return "0x" + "_".join(x) + "_u128" + // + // def print_dyadic(value): + // (s, m, e) = RealField(128)(value).sign_mantissa_exponent(); + // print("DyadicFloat128 {") + // print(f" sign: DyadicSign::{'Pos' if s >= 0 else 'Neg'},") + // print(f" exponent: {e},") + // print(f" mantissa: {format_hex(m)},") + // print("};") + // + // print_dyadic(π/128) + const PI_OVER_128_F128: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xc90f_daa2_2168_c234_c4c6_628b_80dc_1cd1_u128, + }; + + // y_lo = x * c_lo + pm.lo + let one_pi_rot = ONE_TWENTY_EIGHT_OVER_PI[self.idx as usize]; + let y_lo_0 = DyadicFloat128::new_from_f64(self.x_reduced * f64::from_bits(one_pi_rot.3)); + let y_lo_1 = DyadicFloat128::new_from_f64(self.y_lo) + y_lo_0; + let y_mid_f128 = DyadicFloat128::new_from_f64(self.y_mid.lo) + y_lo_1; + let y_hi_f128 = + DyadicFloat128::new_from_f64(self.y_hi) + DyadicFloat128::new_from_f64(self.y_mid.hi); + let y = y_hi_f128 + y_mid_f128; + + y * PI_OVER_128_F128 + } + + pub(crate) fn reduce(&mut self, x: f64) -> (u64, DoubleDouble) { + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + let mut xbits = x.to_bits(); + let x_e = ((x.to_bits() >> 52) & 0x7ff) as i64; + let x_e_m62 = x_e.wrapping_sub(E_BIAS as i64 + 62); + self.idx = (x_e_m62 >> 4).wrapping_add(3) as u64; + // Scale x down by 2^(-(16 * (idx - 3)) + xbits = set_exponent_f64( + xbits, + (x_e_m62 & 15) + .wrapping_add(E_BIAS as i64) + .wrapping_add(62i64) as u64, + ); + // 2^62 <= |x_reduced| < 2^(62 + 16) = 2^78 + self.x_reduced = f64::from_bits(xbits); + // x * c_hi = ph.hi + ph.lo exactly. + let one_pi = ONE_TWENTY_EIGHT_OVER_PI[self.idx as usize]; + let ph = DoubleDouble::from_exact_mult(self.x_reduced, f64::from_bits(one_pi.0)); + // x * c_mid = pm.hi + pm.lo exactly. + let pm = DoubleDouble::from_exact_mult(self.x_reduced, f64::from_bits(one_pi.1)); + // x * c_lo = pl.hi + pl.lo exactly. + let pl = DoubleDouble::from_exact_mult(self.x_reduced, f64::from_bits(one_pi.2)); + // Extract integral parts and fractional parts of (ph.lo + pm.hi). + let sum_hi = ph.lo + pm.hi; + let kd = sum_hi.cpu_round(); + + // x * 128/pi mod 1 ~ y_hi + y_mid + y_lo + self.y_hi = (ph.lo - kd) + pm.hi; // Exact + self.y_mid = DoubleDouble::from_exact_add(pm.lo, pl.hi); + self.y_lo = pl.lo; + + // y_l = x * c_lo_2 + pl.lo + let y_l = dd_fmla(self.x_reduced, f64::from_bits(one_pi.3), self.y_lo); + let mut y = DoubleDouble::from_exact_add(self.y_hi, self.y_mid.hi); + y.lo += self.y_mid.lo + y_l; + + // Digits of pi/128, generated by SageMath with: + // import struct + // from sage.all import * + // + // def double_to_hex(f): + // return "0x" + format(struct.unpack('() as u64 }, u) + } +} + +// Generated by SageMath +// nwords = 20 +// prec = nwords * 64 + 150 +// R = RealField(prec) +// invpi = R(1) / (R(2) * R.pi()) +// +// scale = R(2)**64 +// +// words = [] +// x = invpi +// for i in range(nwords): +// y = floor(x * scale) +// words.append(int(y)) +// x = x * scale - y +// +// for w in words: +// print("0x{:016x},".format(w)) +static INVPI_2_64: [u64; 20] = [ + 0x28be60db9391054a, + 0x7f09d5f47d4d3770, + 0x36d8a5664f10e410, + 0x7f9458eaf7aef158, + 0x6dc91b8e909374b8, + 0x1924bba82746487, + 0x3f877ac72c4a69cf, + 0xba208d7d4baed121, + 0x3a671c09ad17df90, + 0x4e64758e60d4ce7d, + 0x272117e2ef7e4a0e, + 0xc7fe25fff7816603, + 0xfbcbc462d6829b47, + 0xdb4d9fb3c9f2c26d, + 0xd3d18fd9a797fa8b, + 0x5d49eeb1faf97c5e, + 0xcf41ce7de294a4ba, + 0x9afed7ec47e35742, + 0x1580cc11bf1edaea, + 0xfc33ef0826bd0d87, +]; + +#[inline] +fn create_dd(c1: u64, c0: u64) -> DoubleDouble { + let mut c1 = c1; + let mut c0 = c0; + if c1 != 0 { + let e = c1.leading_zeros(); + if e != 0 { + c1 = (c1 << e) | (c0 >> (64 - e)); + c0 = c0.wrapping_shl(e); + } + let f = 0x3fe - e; + let t_u = ((f as u64) << 52) | ((c1 << 1) >> 12); + let hi = f64::from_bits(t_u); + c0 = (c1 << 53) | (c0 >> 11); + let l = if c0 != 0 { + let g = c0.leading_zeros(); + if (g) != 0 { + c0 = c0.wrapping_shl(g); + } + let t_u = (((f - 53 - g) as u64) << 52) | ((c0 << 1) >> 12); + f64::from_bits(t_u) + } else { + 0. + }; + DoubleDouble::new(l, hi) + } else if c0 != 0 { + let e = c0.leading_zeros(); + let f = 0x3fe - 64 - e; + c0 = c0.wrapping_shl(e + 1); // most significant bit shifted out + + /* put the upper 52 bits of c0 into h */ + let t_u = ((f as u64) << 52) | (c0 >> 12); + let hi = f64::from_bits(t_u); + /* put the lower 12 bits of c0 into l */ + c0 = c0.wrapping_shl(52); + let l = if c0 != 0 { + let g = c0.leading_zeros(); + c0 = c0.wrapping_shl(g + 1); + let t_u = (((f - 64 - g) as u64) << 52) | (c0 >> 12); + f64::from_bits(t_u) + } else { + 0. + }; + DoubleDouble::new(l, hi) + } else { + DoubleDouble::default() + } +} + +#[inline] +fn frac_2pi(x: f64) -> DoubleDouble { + if x <= f64::from_bits(0x401921fb54442d17) + // x < 2*pi + { + /* | CH+CL - 1/(2pi) | < 2^-110.523 */ + const C: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc66b01ec5417056), + f64::from_bits(0x3fc45f306dc9c883), + ); + let mut z = DoubleDouble::quick_mult_f64(C, x); + z.lo = f_fmla(C.lo, x, z.lo); + z + } else + // x > 0x1.921fb54442d17p+2 + { + let t = x.to_bits(); + let mut e = ((t >> 52) & 0x7ff) as i32; /* 1025 <= e <= 2046 */ + let m = (1u64 << 52) | (t & 0xfffffffffffffu64); + let mut c0: u64; + let mut c1: u64; + let mut c2: u64; + // x = m/2^53 * 2^(e-1022) + if e <= 1074 + // 1025 <= e <= 1074: 2^2 <= x < 2^52 + { + let mut u = m as u128 * INVPI_2_64[1] as u128; + c0 = u as u64; + c1 = (u >> 64) as u64; + u = m as u128 * INVPI_2_64[0] as u128; + c1 = c1.wrapping_add(u as u64); + c2 = (u >> 64) as u64 + (c1 < (u as u64)) as u64; + e = 1075 - e; // 1 <= e <= 50 + } else + // 1075 <= e <= 2046, 2^52 <= x < 2^1024 + { + let i = (e - 1138 + 63) / 64; // i = ceil((e-1138)/64), 0 <= i <= 15 + let mut u = m as u128 * INVPI_2_64[i as usize + 2] as u128; + c0 = u as u64; + c1 = (u >> 64) as u64; + u = m as u128 * INVPI_2_64[i as usize + 1] as u128; + c1 = c1.wrapping_add(u as u64); + c2 = (u >> 64) as u64 + ((c1) < (u as u64)) as u64; + u = m as u128 * INVPI_2_64[i as usize] as u128; + c2 = c2.wrapping_add(u as u64); + e = 1139 + (i << 6) - e; // 1 <= e <= 64 + } + if e == 64 { + c0 = c1; + c1 = c2; + } else { + c0 = (c1 << (64 - e)) | c0 >> e; + c1 = (c2 << (64 - e)) | c1 >> e; + } + create_dd(c1, c0) + } +} + +/// Returns x mod 2*PI +#[inline] +pub(crate) fn rem2pi_any(x: f64) -> AngleReduced { + const TWO_PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3cb1a62633145c07), + f64::from_bits(0x401921fb54442d18), + ); + let a = frac_2pi(x); + let z = DoubleDouble::quick_mult(a, TWO_PI); + AngleReduced { angle: z } +} + +/** +Generated by SageMath: +```python +def triple_double_split(x, n): + VR = RealField(1000) + R32 = RealField(n) + hi = R32(x) + rem1 = x - VR(hi) + med = R32(rem1) + rem2 = rem1 - VR(med) + lo = R32(rem2) + rem2 = rem1 - VR(med) + lo = R32(rem2) + return (hi, med, lo) + +hi, med, lo = triple_double_split((RealField(600).pi() * RealField(600)(2)), 51) + +print(double_to_hex(hi)) +print(double_to_hex(med)) +print(double_to_hex(lo)) +``` + **/ +#[inline] +fn rem2pif_small(x: f32) -> f64 { + const ONE_OVER_PI_2: f64 = f64::from_bits(0x3fc45f306dc9c883); + const TWO_PI: [u64; 3] = [0x401921fb54440000, 0x3da68c234c4c0000, 0x3b498a2e03707345]; + let dx = x as f64; + let kd = (dx * ONE_OVER_PI_2).cpu_round(); + let mut y = dd_fmla(-kd, f64::from_bits(TWO_PI[0]), dx); + y = dd_fmla(-kd, f64::from_bits(TWO_PI[1]), y); + y = dd_fmla(-kd, f64::from_bits(TWO_PI[2]), y); + y +} + +#[inline] +pub(crate) fn rem2pif_any(x: f32) -> f64 { + let x_abs = x.abs(); + if x_abs.to_bits() < 0x5600_0000u32 { + rem2pif_small(x_abs) + } else { + let p = rem2pi_any(x_abs as f64); + p.angle.to_f64() + } +} + +pub(crate) fn frac2pi_d128(x: DyadicFloat128) -> DyadicFloat128 { + let e = x.biased_exponent(); + + let mut fe = x; + + if e <= 1 + // |X| < 2 + { + /* multiply by T[0]/2^64 + T[1]/2^128, where + |T[0]/2^64 + T[1]/2^128 - 1/(2pi)| < 2^-130.22 */ + let mut x_hi = (x.mantissa >> 64) as u64; + let mut x_lo: u64; + let mut u: u128 = x_hi as u128 * INVPI_2_64[1] as u128; + let tiny: u64 = u as u64; + x_lo = (u >> 64) as u64; + u = x_hi as u128 * INVPI_2_64[0] as u128; + x_lo = x_lo.wrapping_add(u as u64); + x_hi = (u >> 64) as u64 + (x_lo < u as u64) as u64; + /* hi + lo/2^64 + tiny/2^128 = hi_in * (T[0]/2^64 + T[1]/2^128) thus + |hi + lo/2^64 + tiny/2^128 - hi_in/(2*pi)| < hi_in * 2^-130.22 + Since X is normalized at input, hi_in >= 2^63, and since T[0] >= 2^61, + we have hi >= 2^(63+61-64) = 2^60, thus the normalize() below + perform a left shift by at most 3 bits */ + let mut e = x.exponent; + fe.mantissa = (x_hi as u128).wrapping_shl(64) | (x_lo as u128); + fe.normalize(); + e -= fe.exponent; + // put the upper e bits of tiny into X->lo + if (e) != 0 { + x_hi = (fe.mantissa >> 64) as u64; + x_lo = (fe.mantissa & 0xffff_ffff_ffff_ffff) as u64; + x_lo |= tiny >> (64 - e); + fe.mantissa = (x_hi as u128).wrapping_shl(64) | (x_lo as u128); + } + /* The error is bounded by 2^-130.22 (relative) + ulp(lo) (absolute). + Since now X->hi >= 2^63, the absolute error of ulp(lo) converts into + a relative error of less than 2^-127. + This yields a maximal relative error of: + (1 + 2^-130.22) * (1 + 2^-127) - 1 < 2^-126.852. + */ + return fe; + } + + // now 2 <= e <= 1024 + + /* The upper 64-bit word X->hi corresponds to hi/2^64*2^e, if multiplied by + T[i]/2^((i+1)*64) it yields hi*T[i]/2^128 * 2^(e-i*64). + If e-64i <= -128, it contributes to less than 2^-128; + if e-64i >= 128, it yields an integer, which is 0 modulo 1. + We thus only consider the values of i such that -127 <= e-64i <= 127, + i.e., (-127+e)/64 <= i <= (127+e)/64. + Up to 4 consecutive values of T[i] can contribute (only 3 when e is a + multiple of 64). */ + let i = (if e < 127 { 0 } else { (e - 127 + 64 - 1) / 64 }) as usize; // ceil((e-127)/64) + // 0 <= i <= 15 + let mut c: [u64; 5] = [0u64; 5]; + + let mut x_hi = (x.mantissa >> 64) as u64; + let mut x_lo: u64; + + let mut u: u128 = x_hi as u128 * INVPI_2_64[i + 3] as u128; // i+3 <= 18 + c[0] = u as u64; + c[1] = (u >> 64) as u64; + u = x_hi as u128 * INVPI_2_64[i + 2] as u128; + c[1] = c[1].wrapping_add(u as u64); + c[2] = (u >> 64) as u64 + (c[1] < u as u64) as u64; + u = x_hi as u128 * INVPI_2_64[i + 1] as u128; + c[2] = c[2].wrapping_add(u as u64); + c[3] = (u >> 64) as u64 + (c[2] < u as u64) as u64; + u = x_hi as u128 * INVPI_2_64[i] as u128; + c[3] = c[3].wrapping_add(u as u64); + c[4] = (u >> 64) as u64 + (c[3] < u as u64) as u64; + + let f = e as i32 - 64 * i as i32; // hi*T[i]/2^128 is multiplied by 2^f + + /* {c, 5} = hi*(T[i]+T[i+1]/2^64+T[i+2]/2^128+T[i+3]/2^192) */ + /* now shift c[0..4] by f bits to the left */ + let tiny; + if f < 64 { + x_hi = (c[4] << f) | (c[3] >> (64 - f)); + x_lo = (c[3] << f) | (c[2] >> (64 - f)); + tiny = (c[2] << f) | (c[1] >> (64 - f)); + /* the ignored part was less than 1 in c[1], + thus less than 2^(f-64) <= 1/2 in tiny */ + } else if f == 64 { + x_hi = c[3]; + x_lo = c[2]; + tiny = c[1]; + /* the ignored part was less than 1 in c[1], + thus less than 1 in tiny */ + } else + /* 65 <= f <= 127: this case can only occur when e >= 65 */ + { + let g = f - 64; /* 1 <= g <= 63 */ + /* we compute an extra term */ + u = x_hi as u128 * INVPI_2_64[i + 4] as u128; // i+4 <= 19 + u >>= 64; + c[0] = c[0].wrapping_add(u as u64); + c[1] += (c[0] < u as u64) as u64; + c[2] += ((c[0] < u as u64) && c[1] == 0) as u64; + c[3] += ((c[0] < u as u64) && c[1] == 0 && c[2] == 0) as u64; + c[4] += ((c[0] < u as u64) && c[1] == 0 && c[2] == 0 && c[3] == 0) as u64; + x_hi = (c[3] << g) | (c[2] >> (64 - g)); + x_lo = (c[2] << g) | (c[1] >> (64 - g)); + tiny = (c[1] << g) | (c[0] >> (64 - g)); + /* the ignored part was less than 1 in c[0], + thus less than 1/2 in tiny */ + } + let mut fe = x; + fe.exponent = -127; + fe.mantissa = (x_hi as u128).wrapping_shl(64) | (x_lo as u128); + fe.normalize(); + let ze = fe.biased_exponent(); + if ze < 0 { + x_hi = (fe.mantissa >> 64) as u64; + x_lo = (fe.mantissa & 0xffff_ffff_ffff_ffff) as u64; + x_lo |= tiny >> (64 + ze); + fe.mantissa = (x_hi as u128).wrapping_shl(64) | (x_lo as u128); + } + fe +} + +pub(crate) fn rem2pi_f128(x: DyadicFloat128) -> DyadicFloat128 { + /* + Generated by SageMath: + ```python + def double_to_hex(f): + # Converts Python float (f64) to hex string + packed = struct.pack('>d', float(f)) + return '0x' + packed.hex() + + def format_dyadic_hex(value): + l = hex(value)[2:] + n = 8 + x = [l[i:i + n] for i in range(0, len(l), n)] + return "0x" + "_".join(x) + "_u128" + + def print_dyadic(value): + (s, m, e) = RealField(128)(value).sign_mantissa_exponent(); + print("DyadicFloat128 {") + print(f" sign: DyadicSign::{'Pos' if s >= 0 else 'Neg'},") + print(f" exponent: {e},") + print(f" mantissa: {format_dyadic_hex(m)},") + print("},") + + print_dyadic(RealField(300).pi() * 2) + ``` + */ + const TWO_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -125, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + let frac2pi = frac2pi_d128(x); + TWO_PI * frac2pi +} +// +// #[cfg(test)] +// mod tests { +// use crate::dyadic_float::DyadicFloat128; +// use crate::sincos_reduce::{frac_2pi, frac2pi_d128}; +// +// #[test] +// fn test_reduce() { +// let x = 1.8481363e36f32; +// let reduced = frac_2pi(x as f64); +// let to_reduced2 = DyadicFloat128::new_from_f64(x as f64); +// let reduced2 = frac2pi_d128(to_reduced2); +// println!("{:?}", reduced); +// println!("{:?}", reduced2.fast_as_f64()); +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_reduce_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincos_reduce_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincos_reduce_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,817 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Digits of 2^(16*i) / pi, generated by Sollya with: +// > procedure ulp(x, n) { return 2^(floor(log2(abs(x))) - n); }; +// > for i from 0 to 63 do { +// if i < 3 then { pi_inv = 0.25 + 2^(16*(i - 3)) / pi; } +// else { pi_inv = 2^(16*(i-3)) / pi; }; +// pn = nearestint(pi_inv); +// pi_frac = pi_inv - pn; +// a = round(pi_frac, 51, RN); +// b = round(pi_frac - a, 51, RN); +// c = round(pi_frac - a - b, 51, RN); +// d = round(pi_frac - a - b - c, D, RN); +// print("{", 2^7 * a, ",", 2^7 * b, ",", 2^7 * c, ",", 2^7 * d, "},"); +// }; +// +// Notice that for [0..2] the leading bit of 2^(16*(i - 3)) / pi is very small, +// so we add 0.25 so that the conditions for the algorithms are still satisfied, +// and one of those conditions guarantees that ulp(0.25 * x_reduced) >= 2, and +// will safely be discarded. +pub(crate) static ONE_TWENTY_EIGHT_OVER_PI: [(u64, u64, u64, u64); 128] = [ + ( + 0x4040000000000014, + 0x3ce7cc1b727220a9, + 0x3983f84eafa3ea6a, + 0xb6211f924eb53362, + ), + ( + 0x4040000000145f30, + 0x3ceb727220a94fe1, + 0x397d5f47d4d37703, + 0x361b6295993c4390, + ), + ( + 0x404000145f306dca, + 0xbcdbbead603d8a83, + 0x395f534ddc0db629, + 0x35f664f10e4107f9, + ), + ( + 0x40445f306dc9c883, + 0xbce6b01ec5417056, + 0xb986447e493ad4ce, + 0x362e21c820ff28b2, + ), + ( + 0xc03f246c6efab581, + 0x3ca3abe8fa9a6ee0, + 0x394b6c52b3278872, + 0x35b07f9458eaf7af, + ), + ( + 0x403391054a7f09d6, + 0xbca70565911f924f, + 0x3942b32788720840, + 0xb5dae9c5421443aa, + ), + ( + 0x401529fc2757d1f5, + 0x3caa6ee06db14acd, + 0xb948778df7c035d4, + 0x35ed5ef5de2b0db9, + ), + ( + 0xbfeec54170565912, + 0x3c4b6c52b3278872, + 0x38b07f9458eaf7af, + 0xb52d4f246dc8e2df, + ), + ( + 0xc04505c1596447e5, + 0x3ceb14acc9e21c82, + 0x395fe5163abdebbc, + 0x35f586dc91b8e909, + ), + ( + 0xc00596447e493ad5, + 0x3c993c439041fe51, + 0x3938eaf7aef1586e, + 0xb5cb7238b7b645a4, + ), + ( + 0x404bb81b6c52b328, + 0xbcede37df00d74e3, + 0x3987bd778ac36e49, + 0xb611c5bdb22d1ffa, + ), + ( + 0x404b6c52b3278872, + 0x3cb07f9458eaf7af, + 0xb92d4f246dc8e2df, + 0x35b374b801924bbb, + ), + ( + 0x4042b32788720840, + 0xbcdae9c5421443aa, + 0x395b7246e3a424dd, + 0x35e700324977504f, + ), + ( + 0xc048778df7c035d4, + 0x3ced5ef5de2b0db9, + 0x3971b8e909374b80, + 0x35f924bba8274648, + ), + ( + 0xc03bef806ba71508, + 0xbcd443a9e48db91c, + 0xb976f6c8b47fe6db, + 0xb61115f62e6de302, + ), + ( + 0xbfdae9c5421443aa, + 0x3c5b7246e3a424dd, + 0x38e700324977504f, + 0xb58cdbc603c429c7, + ), + ( + 0xc0438a84288753c9, + 0xbccb7238b7b645a4, + 0x38f924bba8274648, + 0x359cfe1deb1cb12a, + ), + ( + 0xc020a21d4f246dc9, + 0x3cad2126e9700325, + 0xb94a22bec5cdbc60, + 0xb5de214e34ed658c, + ), + ( + 0xc02d4f246dc8e2df, + 0x3cb374b801924bbb, + 0xb95f62e6de301e21, + 0xb5f38d3b5963045e, + ), + ( + 0xc03236e4716f6c8b, + 0xbcd1ff9b6d115f63, + 0x395921cfe1deb1cb, + 0x35d29a73ee88235f, + ), + ( + 0x403b8e909374b802, + 0xbcdb6d115f62e6de, + 0xb9680f10a71a76b3, + 0x35fcfba208d7d4bb, + ), + ( + 0x40309374b801924c, + 0xbcd15f62e6de301e, + 0xb960a71a76b2c609, + 0x3601046bea5d7689, + ), + ( + 0xc0268ffcdb688afb, + 0xbca736f180f10a72, + 0x39462534e7dd1047, + 0xb5e0568a25dbd8b3, + ), + ( + 0x3ff924bba8274648, + 0x3c9cfe1deb1cb12a, + 0xb9363045df7282b4, + 0xb5d44bb7b16638fe, + ), + ( + 0xc04a22bec5cdbc60, + 0xbcde214e34ed658c, + 0xb95177dca0ad144c, + 0x35f213a671c09ad1, + ), + ( + 0x4003a32439fc3bd6, + 0x3c9cb129a73ee882, + 0x392afa975da24275, + 0xb5b8e3f652e82070, + ), + ( + 0xc03b78c0788538d4, + 0x3cd29a73ee88235f, + 0x3974baed1213a672, + 0xb60fb29741037d8d, + ), + ( + 0x404fc3bd63962535, + 0xbcc822efb9415a29, + 0x396a24274ce38136, + 0xb60741037d8cdc54, + ), + ( + 0xc014e34ed658c117, + 0xbcbf7282b4512edf, + 0x394d338e04d68bf0, + 0xb5dbec66e29c67cb, + ), + ( + 0x40462534e7dd1047, + 0xbce0568a25dbd8b3, + 0xb96c7eca5d040df6, + 0xb5f9b8a719f2b318, + ), + ( + 0xc0363045df7282b4, + 0xbcd44bb7b16638fe, + 0x397ad17df904e647, + 0x361639835339f49d, + ), + ( + 0x404d1046bea5d769, + 0xbcebd8b31c7eca5d, + 0xb94037d8cdc538d0, + 0x35ea99cfa4e422fc, + ), + ( + 0x402afa975da24275, + 0xbcb8e3f652e82070, + 0x3953991d63983534, + 0xb5f82d8dee81d108, + ), + ( + 0xc04a28976f62cc72, + 0x3ca35a2fbf209cc9, + 0xb924e33e566305b2, + 0x35c08bf177bf2507, + ), + ( + 0xc0476f62cc71fb29, + 0xbced040df633714e, + 0xb979f2b3182d8def, + 0x361f8bbdf9283b20, + ), + ( + 0x404d338e04d68bf0, + 0xbcdbec66e29c67cb, + 0x3969cfa4e422fc5e, + 0xb5e036be27003b40, + ), + ( + 0x403c09ad17df904e, + 0x3cd91d639835339f, + 0x397272117e2ef7e5, + 0xb617c4e007680022, + ), + ( + 0x40468befc827323b, + 0xbcdc67cacc60b638, + 0x39717e2ef7e4a0ec, + 0x361ff897ffde0598, + ), + ( + 0xc04037d8cdc538d0, + 0x3cea99cfa4e422fc, + 0x39877bf250763ff1, + 0x3617ffde05980fef, + ), + ( + 0xc048cdc538cf9599, + 0x3cdf49c845f8bbe0, + 0xb97b5f13801da001, + 0x361e05980fef2f12, + ), + ( + 0xc024e33e566305b2, + 0x3cc08bf177bf2507, + 0x3968ffc4bffef02d, + 0xb5ffc04343b9d298, + ), + ( + 0xc03f2b3182d8dee8, + 0xbcbd1081b5f13802, + 0x3942fffbc0b301fe, + 0xb5ca1dce94beb25c, + ), + ( + 0xc048c16c6f740e88, + 0xbce036be27003b40, + 0xb920fd33f8086877, + 0xb5bd297d64b824b2, + ), + ( + 0x4043908bf177bf25, + 0x3cad8ffc4bffef03, + 0xb939fc04343b9d29, + 0xb5df592e092c9813, + ), + ( + 0x4037e2ef7e4a0ec8, + 0xbc7da00087e99fc0, + 0xb910d0ee74a5f593, + 0x359f6d367ecf27cb, + ), + ( + 0xc03081b5f13801da, + 0xbc20fd33f8086877, + 0xb8bd297d64b824b2, + 0xb558130d834f648b, + ), + ( + 0xc04af89c00ed0004, + 0xbcdfa67f010d0ee7, + 0xb97297d64b824b26, + 0xb5d30d834f648b0c, + ), + ( + 0xc04c00ed00043f4d, + 0x3c8fde5e2316b415, + 0xb912e092c98130d8, + 0xb5aa7b24585ce04d, + ), + ( + 0x4042fffbc0b301fe, + 0xbcca1dce94beb25c, + 0xb9425930261b069f, + 0x35db74f463f669e6, + ), + ( + 0xc020fd33f8086877, + 0xbcbd297d64b824b2, + 0xb958130d834f648b, + 0xb5c738132c3402ba, + ), + ( + 0xc039fc04343b9d29, + 0xbcdf592e092c9813, + 0xb94b069ec9161738, + 0xb5c32c3402ba515b, + ), + ( + 0xc010d0ee74a5f593, + 0x3c9f6d367ecf27cb, + 0x39036e9e8c7ecd3d, + 0xb5a00ae9456c229c, + ), + ( + 0xc04dce94beb25c12, + 0xbce64c0986c1a7b2, + 0xb98161738132c340, + 0xb615d28ad8453814, + ), + ( + 0xc044beb25c125930, + 0xbcd30d834f648b0c, + 0x3978fd9a797fa8b6, + 0xb605b08a7028341d, + ), + ( + 0x403b47db4d9fb3ca, + 0xbcaa7b24585ce04d, + 0x3943cbfd45aea4f7, + 0x35e63f5f2f8bd9e8, + ), + ( + 0xc0425930261b069f, + 0x3cdb74f463f669e6, + 0xb915d28ad8453814, + 0xb59a0e84c2f8c608, + ), + ( + 0x403fb3c9f2c26dd4, + 0xbcc738132c3402ba, + 0xb96456c229c0a0d0, + 0xb60d0985f18c10eb, + ), + ( + 0xc04b069ec9161738, + 0xbcc32c3402ba515b, + 0xb9314e050683a131, + 0x35d0739f78a5292f, + ), + ( + 0xc04ec9161738132c, + 0xbcda015d28ad8454, + 0x397faf97c5ecf41d, + 0xb5f821d6b5b45650, + ), + ( + 0xc0461738132c3403, + 0x3ce16ba93dd63f5f, + 0x3977c5ecf41ce7de, + 0x3604a525d4d7f6bf, + ), + ( + 0x402fb34f2ff516bb, + 0xbccb08a7028341d1, + 0x3969e839cfbc5295, + 0xb60a2b2809409dc1, + ), + ( + 0x4043cbfd45aea4f7, + 0x3ce63f5f2f8bd9e8, + 0x397ce7de294a4baa, + 0xb61404a04ee072a3, + ), + ( + 0xc015d28ad8453814, + 0xbc9a0e84c2f8c608, + 0xb93d6b5b45650128, + 0xb5b3b81ca8bdea7f, + ), + ( + 0xc0415b08a7028342, + 0x3cd7b3d0739f78a5, + 0x396497535fdafd89, + 0xb5bca8bdea7f33ee, + ), + ( + 0x0000000000000000, + 0x0000000000000000, + 0x3c5f938a73db97fb, + 0x3f992155f7a3667c, + ), + ( + 0xbc2912bd0d569a90, + 0x3fa91f65f10dd814, + 0x3c7ccbeeeae8129a, + 0x3fb2d52092ce19f4, + ), + ( + 0xbc3e2718d26ed688, + 0x3fb917a6bc29b42c, + 0xbc7cbb1f71aca352, + 0x3fbf564e56a97310, + ), + ( + 0xbc8dd9ffeaecbdc4, + 0x3fc2c8106e8e613c, + 0xbc8ab3802218894f, + 0x3fc5e214448b3fc8, + ), + ( + 0xbc849b466e7fe360, + 0x3fc8f8b83c69a60c, + 0xbc8035e2873ca432, + 0x3fcc0b826a7e4f64, + ), + ( + 0xbc850b7bbc4768b1, + 0x3fcf19f97b215f1c, + 0xbc83ed9efaa42ab3, + 0x3fd111d262b1f678, + ), + ( + 0x3c9a8b5c974ee7b5, + 0x3fd294062ed59f04, + 0x3c94325f12be8946, + 0x3fd4135c94176600, + ), + ( + 0x3c8fc2047e54e614, + 0x3fd58f9a75ab1fdc, + 0xbc9512c678219317, + 0x3fd7088530fa45a0, + ), + ( + 0xbc92e59dba7ab4c2, + 0x3fd87de2a6aea964, + 0xbc9d24afdade848b, + 0x3fd9ef7943a8ed8c, + ), + ( + 0x3c65b362cb974183, + 0x3fdb5d1009e15cc0, + 0xbc9e97af1a63c807, + 0x3fdcc66e9931c460, + ), + ( + 0xbc8c3e4edc5872f8, + 0x3fde2b5d3806f63c, + 0x3c9fb44f80f92225, + 0x3fdf8ba4dbf89ab8, + ), + ( + 0x3ca9697faf2e2fe5, + 0x3fe073879922ffec, + 0xbca7bc8eda6af93c, + 0x3fe11eb3541b4b24, + ), + ( + 0x3c8b25dd267f6600, + 0x3fe1c73b39ae68c8, + 0xbca5769d0fbcddc3, + 0x3fe26d054cdd12e0, + ), + ( + 0x3c9c20673b2116b2, + 0x3fe30ff7fce17034, + 0x3ca3c7c4bc72a92c, + 0x3fe3affa292050b8, + ), + ( + 0xbcae7f895d302395, + 0x3fe44cf325091dd8, + 0x3ca13c293edceb32, + 0x3fe4e6cabbe3e5e8, + ), + ( + 0xbc875720992bfbb2, + 0x3fe57d69348ceca0, + 0xbca24a366a5fe547, + 0x3fe610b7551d2ce0, + ), + ( + 0x3c921165f626cdd5, + 0x3fe6a09e667f3bcc, + 0xbcabcac43c389ba9, + 0x3fe72d0837efff98, + ), + ( + 0xbca21ea6f59be15b, + 0x3fe7b5df226aafb0, + 0x3cad217be0e2b971, + 0x3fe83b0e0bff976c, + ), + ( + 0x3c969d0f6897664a, + 0x3fe8bc806b151740, + 0xbc9615f32b6f907a, + 0x3fe93a22499263fc, + ), + ( + 0x3c96788ebcc76dc6, + 0x3fe9b3e047f38740, + 0x3caddae89fd441d1, + 0x3fea29a7a0462780, + ), + ( + 0xbc9f98273c5d2495, + 0x3fea9b66290ea1a4, + 0xbc8926da300ffcce, + 0x3feb090a58150200, + ), + ( + 0x3ca90e58336c64a8, + 0x3feb728345196e3c, + 0x3ca9f6963354e3fe, + 0x3febd7c0ac6f9528, + ), + ( + 0x3c9a47d3a2a0dcbe, + 0x3fec38b2f180bdb0, + 0x3c9ed0489e16b9a0, + 0x3fec954b213411f4, + ), + ( + 0xbca0f3db5dad5ac5, + 0x3feced7af43cc774, + 0x3caac42b5a8b6943, + 0x3fed4134d14dc938, + ), + ( + 0xbcad75033dfb9ca8, + 0x3fed906bcf328d48, + 0x3c883c37c6107db3, + 0x3feddb13b6ccc23c, + ), + ( + 0x3c97f59c49f6cd6d, + 0x3fee212104f686e4, + 0x3caee94a90d7b88b, + 0x3fee6288ec48e110, + ), + ( + 0xbcaa27d3874701f9, + 0x3fee9f4156c62ddc, + 0xbc985f4e1b8298d0, + 0x3feed740e7684964, + ), + ( + 0xbc9ab4e148e52d9e, + 0x3fef0a7efb9230d8, + 0x3c98a11412b82346, + 0x3fef38f3ac64e588, + ), + ( + 0x3c7562172a361fd3, + 0x3fef6297cff75cb0, + 0x3ca3564acef1ff97, + 0x3fef8764fa714ba8, + ), + ( + 0xbca5e82a3284d5c8, + 0x3fefa7557f08a518, + 0xbc9709bccb89a989, + 0x3fefc26470e19fd4, + ), + ( + 0x3ca9e082721dfb8e, + 0x3fefd88da3d12524, + 0xbcaeade132f3981d, + 0x3fefe9cdad01883c, + ), + ( + 0x3cae3a843d1db55f, + 0x3feff621e3796d7c, + 0x3c9765595d548d9a, + 0x3feffd886084cd0c, + ), + ( + 0x0000000000000000, + 0x3ff0000000000000, + 0x3c9765595d548d9a, + 0x3feffd886084cd0c, + ), + ( + 0x3cae3a843d1db55f, + 0x3feff621e3796d7c, + 0xbcaeade132f3981d, + 0x3fefe9cdad01883c, + ), + ( + 0x3ca9e082721dfb8e, + 0x3fefd88da3d12524, + 0xbc9709bccb89a989, + 0x3fefc26470e19fd4, + ), + ( + 0xbca5e82a3284d5c8, + 0x3fefa7557f08a518, + 0x3ca3564acef1ff97, + 0x3fef8764fa714ba8, + ), + ( + 0x3c7562172a361fd3, + 0x3fef6297cff75cb0, + 0x3c98a11412b82346, + 0x3fef38f3ac64e588, + ), + ( + 0xbc9ab4e148e52d9e, + 0x3fef0a7efb9230d8, + 0xbc985f4e1b8298d0, + 0x3feed740e7684964, + ), + ( + 0xbcaa27d3874701f9, + 0x3fee9f4156c62ddc, + 0x3caee94a90d7b88b, + 0x3fee6288ec48e110, + ), + ( + 0x3c97f59c49f6cd6d, + 0x3fee212104f686e4, + 0x3c883c37c6107db3, + 0x3feddb13b6ccc23c, + ), + ( + 0xbcad75033dfb9ca8, + 0x3fed906bcf328d48, + 0x3caac42b5a8b6943, + 0x3fed4134d14dc938, + ), + ( + 0xbca0f3db5dad5ac5, + 0x3feced7af43cc774, + 0x3c9ed0489e16b9a0, + 0x3fec954b213411f4, + ), + ( + 0x3c9a47d3a2a0dcbe, + 0x3fec38b2f180bdb0, + 0x3ca9f6963354e3fe, + 0x3febd7c0ac6f9528, + ), + ( + 0x3ca90e58336c64a8, + 0x3feb728345196e3c, + 0xbc8926da300ffcce, + 0x3feb090a58150200, + ), + ( + 0xbc9f98273c5d2495, + 0x3fea9b66290ea1a4, + 0x3caddae89fd441d1, + 0x3fea29a7a0462780, + ), + ( + 0x3c96788ebcc76dc6, + 0x3fe9b3e047f38740, + 0xbc9615f32b6f907a, + 0x3fe93a22499263fc, + ), + ( + 0x3c969d0f6897664a, + 0x3fe8bc806b151740, + 0x3cad217be0e2b971, + 0x3fe83b0e0bff976c, + ), + ( + 0xbca21ea6f59be15b, + 0x3fe7b5df226aafb0, + 0xbcabcac43c389ba9, + 0x3fe72d0837efff98, + ), + ( + 0x3c921165f626cdd5, + 0x3fe6a09e667f3bcc, + 0xbca24a366a5fe547, + 0x3fe610b7551d2ce0, + ), + ( + 0xbc875720992bfbb2, + 0x3fe57d69348ceca0, + 0x3ca13c293edceb32, + 0x3fe4e6cabbe3e5e8, + ), + ( + 0xbcae7f895d302395, + 0x3fe44cf325091dd8, + 0x3ca3c7c4bc72a92c, + 0x3fe3affa292050b8, + ), + ( + 0x3c9c20673b2116b2, + 0x3fe30ff7fce17034, + 0xbca5769d0fbcddc3, + 0x3fe26d054cdd12e0, + ), + ( + 0x3c8b25dd267f6600, + 0x3fe1c73b39ae68c8, + 0xbca7bc8eda6af93c, + 0x3fe11eb3541b4b24, + ), + ( + 0x3ca9697faf2e2fe5, + 0x3fe073879922ffec, + 0x3c9fb44f80f92225, + 0x3fdf8ba4dbf89ab8, + ), + ( + 0xbc8c3e4edc5872f8, + 0x3fde2b5d3806f63c, + 0xbc9e97af1a63c807, + 0x3fdcc66e9931c460, + ), + ( + 0x3c65b362cb974183, + 0x3fdb5d1009e15cc0, + 0xbc9d24afdade848b, + 0x3fd9ef7943a8ed8c, + ), + ( + 0xbc92e59dba7ab4c2, + 0x3fd87de2a6aea964, + 0xbc9512c678219317, + 0x3fd7088530fa45a0, + ), + ( + 0x3c8fc2047e54e614, + 0x3fd58f9a75ab1fdc, + 0x3c94325f12be8946, + 0x3fd4135c94176600, + ), + ( + 0x3c9a8b5c974ee7b5, + 0x3fd294062ed59f04, + 0xbc83ed9efaa42ab3, + 0x3fd111d262b1f678, + ), + ( + 0xbc850b7bbc4768b1, + 0x3fcf19f97b215f1c, + 0xbc8035e2873ca432, + 0x3fcc0b826a7e4f64, + ), + ( + 0xbc849b466e7fe360, + 0x3fc8f8b83c69a60c, + 0xbc8ab3802218894f, + 0x3fc5e214448b3fc8, + ), + ( + 0xbc8dd9ffeaecbdc4, + 0x3fc2c8106e8e613c, + 0xbc7cbb1f71aca352, + 0x3fbf564e56a97310, + ), + ( + 0xbc3e2718d26ed688, + 0x3fb917a6bc29b42c, + 0x3c7ccbeeeae8129a, + 0x3fb2d52092ce19f4, + ), + ( + 0xbc2912bd0d569a90, + 0x3fa91f65f10dd814, + 0x3c5f938a73db97fb, + 0x3f992155f7a3667c, + ), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincospi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincospi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1274 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, dyad_fmla, f_fmla, is_odd_integer}; +use crate::double_double::DoubleDouble; +use crate::polyeval::{f_polyeval3, f_polyeval4}; +use crate::rounding::CpuRound; +use crate::sin::SinCos; +use crate::sincospi_tables::SINPI_K_PI_OVER_64; + +/** +Cospi(x) on [0; 0.000244140625] + +Generated by Sollya: +```text +d = [0, 0.000244140625]; +f_cos = cos(y*pi); +Q = fpminimax(f_cos, [|0, 2, 4, 6, 8, 10|], [|107...|], d, relative, floating); +``` + +See ./notes/cospi_zero_dd.sollya +**/ +#[cold] +#[inline(always)] +fn as_cospi_zero(x: f64, backend: &B) -> f64 { + const C: [(u64, u64); 5] = [ + (0xbcb692b71366cc04, 0xc013bd3cc9be45de), + (0xbcb32b33fb803bd5, 0x40103c1f081b5ac4), + (0xbc9f5b752e98b088, 0xbff55d3c7e3cbff9), + (0x3c30023d540b9350, 0x3fce1f506446cb66), + (0x3c1a5d47937787d2, 0xbf8a9b062a36ba1c), + ]; + let x2 = backend.exact_mult(x, x); + let mut p = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[3]), + DoubleDouble::from_bit_pair(C[3]), + ); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p = backend.mul_add_f64(x2, p, 1.); + p.to_f64() +} + +/** +Sinpi on range [0.0, 0.03515625] + +Generated poly by Sollya: +```text +d = [0, 0.03515625]; + +f_sin = sin(y*pi)/y; +Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|107...|], d, relative, floating); +``` +See ./notes/sinpi_zero_dd.sollya +**/ +#[cold] +#[inline(always)] +fn as_sinpi_zero(x: f64, backend: &B) -> f64 { + const C: [(u64, u64); 6] = [ + (0x3ca1a626311d9056, 0x400921fb54442d18), + (0x3cb055f12c462211, 0xc014abbce625be53), + (0xbc9789ea63534250, 0x400466bc6775aae1), + (0xbc78b86de6962184, 0xbfe32d2cce62874e), + (0x3c4eddf7cd887302, 0x3fb507833e2b781f), + (0x3bf180c9d4af2894, 0xbf7e2ea4e143707e), + ]; + let x2 = backend.exact_mult(x, x); + let mut p = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[5]), + DoubleDouble::from_bit_pair(C[4]), + ); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p = backend.quick_mult_f64(p, x); + p.to_f64() +} + +// Return k and y, where +// k = round(x * 64 / pi) and y = (x * 64 / pi) - k. +#[inline] +pub(crate) fn reduce_pi_64(x: f64) -> (f64, i64) { + let kd = (x * 64.).cpu_round(); + let y = dd_fmla(kd, -1. / 64., x); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) +} + +// Return k and y, where +// k = round(x * 64 / pi) and y = (x * 64 / pi) - k. +#[inline(always)] +#[allow(unused)] +pub(crate) fn reduce_pi_64_fma(x: f64) -> (f64, i64) { + let kd = (x * 64.).round(); + let y = f64::mul_add(kd, -1. / 64., x); + (y, unsafe { + kd.to_int_unchecked::() // indeterminate values is always filtered out before this call, as well only lowest bits are used + }) +} + +pub(crate) trait SinCosPiBackend { + fn fma(&self, x: f64, y: f64, z: f64) -> f64; + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64; + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64; + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64; + fn arg_reduce_pi_64(&self, x: f64) -> (f64, i64); + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble; + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble; + fn odd_integer(&self, x: f64) -> bool; + fn div(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble; + fn mul_add_f64(&self, a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble; + fn quick_mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble; + fn mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble; + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble; +} + +pub(crate) struct GenSinCosPiBackend {} + +impl SinCosPiBackend for GenSinCosPiBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f_fmla(x, y, z) + } + #[inline(always)] + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64 { + dd_fmla(x, y, z) + } + #[inline(always)] + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64 { + dyad_fmla(x, y, z) + } + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::f_polyeval3; + f_polyeval3(x, a0, a1, a2) + } + #[inline(always)] + fn arg_reduce_pi_64(&self, x: f64) -> (f64, i64) { + reduce_pi_64(x) + } + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64(x, y) + } + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult(x, y) + } + + #[inline(always)] + fn odd_integer(&self, x: f64) -> bool { + is_odd_integer(x) + } + + #[inline(always)] + fn div(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::div(x, y) + } + + #[inline(always)] + fn mul_add_f64(&self, a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble { + DoubleDouble::mul_add_f64(a, b, c) + } + + #[inline(always)] + fn quick_mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mul_add(a, b, c) + } + + #[inline(always)] + fn mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble { + DoubleDouble::mul_add(a, b, c) + } + + #[inline(always)] + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult(x, y) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub(crate) struct FmaSinCosPiBackend {} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl SinCosPiBackend for FmaSinCosPiBackend { + #[inline(always)] + fn fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + #[inline(always)] + fn dd_fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + #[inline(always)] + fn dyad_fma(&self, x: f64, y: f64, z: f64) -> f64 { + f64::mul_add(x, y, z) + } + #[inline(always)] + fn polyeval3(&self, x: f64, a0: f64, a1: f64, a2: f64) -> f64 { + use crate::polyeval::d_polyeval3; + d_polyeval3(x, a0, a1, a2) + } + #[inline(always)] + fn arg_reduce_pi_64(&self, x: f64) -> (f64, i64) { + reduce_pi_64_fma(x) + } + #[inline(always)] + fn quick_mult_f64(&self, x: DoubleDouble, y: f64) -> DoubleDouble { + DoubleDouble::quick_mult_f64_fma(x, y) + } + #[inline(always)] + fn quick_mult(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mult_fma(x, y) + } + + #[inline(always)] + fn odd_integer(&self, x: f64) -> bool { + use crate::common::is_odd_integer_fast; + is_odd_integer_fast(x) + } + + #[inline(always)] + fn div(&self, x: DoubleDouble, y: DoubleDouble) -> DoubleDouble { + DoubleDouble::div_fma(x, y) + } + + #[inline(always)] + fn mul_add_f64(&self, a: DoubleDouble, b: DoubleDouble, c: f64) -> DoubleDouble { + DoubleDouble::mul_add_f64_fma(a, b, c) + } + + #[inline(always)] + fn quick_mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble { + DoubleDouble::quick_mul_add_fma(a, b, c) + } + + #[inline(always)] + fn mul_add(&self, a: DoubleDouble, b: DoubleDouble, c: DoubleDouble) -> DoubleDouble { + DoubleDouble::mul_add_fma(a, b, c) + } + + #[inline(always)] + fn exact_mult(&self, x: f64, y: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult_fma(x, y) + } +} + +#[inline(always)] +pub(crate) fn sincospi_eval(x: f64, backend: &B) -> SinCos { + let x2 = x * x; + /* + sinpi(pi*x) poly generated by Sollya: + d = [0, 0.0078128]; + f_sin = sin(y*pi)/y; + Q = fpminimax(f_sin, [|0, 2, 4, 6|], [|107, D...|], d, relative, floating); + See ./notes/sinpi.sollya + */ + let sin_lop = backend.polyeval3( + x2, + f64::from_bits(0xc014abbce625be4d), + f64::from_bits(0x400466bc6767f259), + f64::from_bits(0xbfe32d176b0b3baf), + ) * x2; + // We're splitting polynomial in two parts, since first term dominates + // we compute: (a0_lo + a0_hi) * x + x * (a1 * x^2 + a2 + x^4) ... + let sin_lo = backend.dd_fma(f64::from_bits(0x3ca1a5c04563817a), x, sin_lop * x); + let sin_hi = x * f64::from_bits(0x400921fb54442d18); + + /* + cospi(pi*x) poly generated by Sollya: + d = [0, 0.015625]; + f_cos = cos(y*pi); + Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|107, D...|], d, relative, floating); + See ./notes/cospi.sollya + */ + let p = backend.polyeval3( + x2, + f64::from_bits(0xc013bd3cc9be45cf), + f64::from_bits(0x40103c1f08085ad1), + f64::from_bits(0xbff55d1e43463fc3), + ); + + // We're splitting polynomial in two parts, since first term dominates + // we compute: (a0_lo + a0_hi) + (a1 * x^2 + a2 + x^4)... + let cos_lo = backend.dd_fma(p, x2, f64::from_bits(0xbbdf72adefec0800)); + let cos_hi = f64::from_bits(0x3ff0000000000000); + + let err = backend.fma( + x2, + f64::from_bits(0x3cb0000000000000), // 2^-52 + f64::from_bits(0x3c40000000000000), // 2^-59 + ); + SinCos { + v_sin: DoubleDouble::from_exact_add(sin_hi, sin_lo), + v_cos: DoubleDouble::from_exact_add(cos_hi, cos_lo), + err, + } +} + +#[inline(always)] +pub(crate) fn sincospi_eval_dd(x: f64, backend: &B) -> SinCos { + let x2 = backend.exact_mult(x, x); + // Sin coeffs + // poly sin(pi*x) generated by Sollya: + // d = [0, 0.0078128]; + // f_sin = sin(y*pi)/y; + // Q = fpminimax(f_sin, [|0, 2, 4, 6, 8|], [|107...|], d, relative, floating); + // see ./notes/sinpi_dd.sollya + const SC: [(u64, u64); 5] = [ + (0x3ca1a626330ccf19, 0x400921fb54442d18), + (0x3cb05540f6323de9, 0xc014abbce625be53), + (0xbc9050fdd1229756, 0x400466bc6775aadf), + (0xbc780d406f3472e8, 0xbfe32d2cce5a7bf1), + (0x3c4cfcf8b6b817f2, 0x3fb5077069d8a182), + ]; + + let mut sin_y = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(SC[4]), + DoubleDouble::from_bit_pair(SC[3]), + ); + sin_y = backend.quick_mul_add(x2, sin_y, DoubleDouble::from_bit_pair(SC[2])); + sin_y = backend.quick_mul_add(x2, sin_y, DoubleDouble::from_bit_pair(SC[1])); + sin_y = backend.quick_mul_add(x2, sin_y, DoubleDouble::from_bit_pair(SC[0])); + sin_y = backend.quick_mult_f64(sin_y, x); + + // Cos coeffs + // d = [0, 0.0078128]; + // f_cos = cos(y*pi); + // Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|107...|], d, relative, floating); + // See ./notes/cospi_dd.sollya + const CC: [(u64, u64); 5] = [ + (0xbaaa70a580000000, 0x3ff0000000000000), + (0xbcb69211d8dd1237, 0xc013bd3cc9be45de), + (0xbcbd96cfd637eeb7, 0x40103c1f081b5abf), + (0x3c994d75c577f029, 0xbff55d3c7e2e4ba5), + (0xbc5c542d998a4e48, 0x3fce1f2f5f747411), + ]; + + let mut cos_y = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(CC[4]), + DoubleDouble::from_bit_pair(CC[3]), + ); + cos_y = backend.quick_mul_add(x2, cos_y, DoubleDouble::from_bit_pair(CC[2])); + cos_y = backend.quick_mul_add(x2, cos_y, DoubleDouble::from_bit_pair(CC[1])); + cos_y = backend.quick_mul_add(x2, cos_y, DoubleDouble::from_bit_pair(CC[0])); + SinCos { + v_sin: sin_y, + v_cos: cos_y, + err: 0., + } +} + +#[cold] +#[inline(always)] +fn sinpi_dd( + x: f64, + sin_k: DoubleDouble, + cos_k: DoubleDouble, + backend: &B, +) -> f64 { + let r_sincos = sincospi_eval_dd(x, backend); + let cos_k_sin_y = backend.quick_mult(cos_k, r_sincos.v_sin); + let rr = backend.mul_add(sin_k, r_sincos.v_cos, cos_k_sin_y); + rr.to_f64() +} + +#[cold] +#[inline(always)] +fn sincospi_dd( + x: f64, + sin_sin_k: DoubleDouble, + sin_cos_k: DoubleDouble, + cos_sin_k: DoubleDouble, + cos_cos_k: DoubleDouble, + backend: &B, +) -> (f64, f64) { + let r_sincos = sincospi_eval_dd(x, backend); + + let cos_k_sin_y = backend.quick_mult(sin_cos_k, r_sincos.v_sin); + let rr_sin = backend.mul_add(sin_sin_k, r_sincos.v_cos, cos_k_sin_y); + + let cos_k_sin_y = backend.quick_mult(cos_cos_k, r_sincos.v_sin); + let rr_cos = backend.mul_add(cos_sin_k, r_sincos.v_cos, cos_k_sin_y); + + (rr_sin.to_f64(), rr_cos.to_f64()) +} + +// [sincospi_eval] gives precision around 2^-66 what is not enough for DD case this method gives 2^-84 +#[inline] +fn sincospi_eval_extended(x: f64) -> SinCos { + let x2 = DoubleDouble::from_exact_mult(x, x); + /* + sinpi(pi*x) poly generated by Sollya: + d = [0, 0.0078128]; + f_sin = sin(y*pi)/y; + Q = fpminimax(f_sin, [|0, 2, 4, 6, 8|], [|107, 107, D...|], d, relative, floating); + See ./notes/sinpi.sollya + */ + let sin_lop = f_polyeval3( + x2.hi, + f64::from_bits(0x400466bc67763662), + f64::from_bits(0xbfe32d2cce5aad86), + f64::from_bits(0x3fb5077099a1f35b), + ); + let mut v_sin = DoubleDouble::mul_f64_add( + x2, + sin_lop, + DoubleDouble::from_bit_pair((0x3cb0553d6ee5e8ec, 0xc014abbce625be53)), + ); + v_sin = DoubleDouble::mul_add( + x2, + v_sin, + DoubleDouble::from_bit_pair((0x3ca1a626330dd130, 0x400921fb54442d18)), + ); + v_sin = DoubleDouble::quick_mult_f64(v_sin, x); + + /* + cospi(pi*x) poly generated by Sollya: + d = [0, 0.015625]; + f_cos = cos(y*pi); + Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|107, 107, D...|], d, relative, floating); + See ./notes/cospi_fast_dd.sollya + */ + let p = f_polyeval3( + x2.hi, + f64::from_bits(0x40103c1f081b5abf), + f64::from_bits(0xbff55d3c7e2edd89), + f64::from_bits(0x3fce1f2fd9d79484), + ); + + let mut v_cos = DoubleDouble::mul_f64_add( + x2, + p, + DoubleDouble::from_bit_pair((0xbcb69236a9b3ed73, 0xc013bd3cc9be45de)), + ); + v_cos = DoubleDouble::mul_add_f64(x2, v_cos, f64::from_bits(0x3ff0000000000000)); + + SinCos { + v_sin: DoubleDouble::from_exact_add(v_sin.hi, v_sin.lo), + v_cos: DoubleDouble::from_exact_add(v_cos.hi, v_cos.lo), + err: 0., + } +} + +pub(crate) fn f_fast_sinpi_dd(x: f64) -> DoubleDouble { + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return DoubleDouble::new(0., 0.); + } + let e: i32 = (ax >> 52) as i32; + let m0 = (ix & 0x000fffffffffffff) | (1u64 << 52); + let sgn: i64 = (ix as i64) >> 63; + let m = ((m0 as i64) ^ sgn).wrapping_sub(sgn); + let mut s: i32 = 1063i32.wrapping_sub(e); + if s < 0 { + s = -s - 1; + if s > 10 { + return DoubleDouble::new(0., f64::copysign(0.0, x)); + } + let iq: u64 = (m as u64).wrapping_shl(s as u32); + if (iq & 2047) == 0 { + return DoubleDouble::new(0., f64::copysign(0.0, x)); + } + } + + if ax <= 0x3fa2000000000000u64 { + // |x| <= 0.03515625 + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + if ax < 0x3c90000000000000 { + // for x near zero, sinpi(x) = pi*x + O(x^3), thus worst cases are those + // of the function pi*x, and if x is a worst case, then 2*x is another + // one in the next binade. For this reason, worst cases are only included + // for the binade [2^-1022, 2^-1021). For larger binades, + // up to [2^-54,2^-53), worst cases should be deduced by multiplying + // by some power of 2. + if ax < 0x0350000000000000 { + let t = x * f64::from_bits(0x4690000000000000); + let z = DoubleDouble::quick_mult_f64(PI, t); + let r = z.to_f64(); + let rs = r * f64::from_bits(0x3950000000000000); + let rt = rs * f64::from_bits(0x4690000000000000); + return DoubleDouble::new( + 0., + dyad_fmla((z.hi - rt) + z.lo, f64::from_bits(0x3950000000000000), rs), + ); + } + let z = DoubleDouble::quick_mult_f64(PI, x); + return z; + } + + /* + Poly generated by Sollya: + d = [0, 0.03515625]; + f_sin = sin(y*pi)/y; + Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|107, 107, D...|], d, relative, floating); + + See ./notes/sinpi_zero_fast_dd.sollya + */ + const C: [u64; 4] = [ + 0xbfe32d2cce62bd85, + 0x3fb50783487eb73d, + 0xbf7e3074f120ad1f, + 0x3f3e8d9011340e5a, + ]; + + let x2 = DoubleDouble::from_exact_mult(x, x); + + const C_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a626331457a4, 0x400921fb54442d18)); + + let p = f_polyeval4( + x2.hi, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + ); + let mut r = DoubleDouble::mul_f64_add( + x2, + p, + DoubleDouble::from_bit_pair((0xbc96dd7ae221e58c, 0x400466bc6775aae2)), + ); + r = DoubleDouble::mul_add( + x2, + r, + DoubleDouble::from_bit_pair((0x3cb05511c8a6c478, 0xc014abbce625be53)), + ); + r = DoubleDouble::mul_add(r, x2, C_PI); + r = DoubleDouble::quick_mult_f64(r, x); + let k = DoubleDouble::from_exact_add(r.hi, r.lo); + return k; + } + + let si = e.wrapping_sub(1011); + if si >= 0 && (m0.wrapping_shl(si.wrapping_add(1) as u32)) == 0 { + // x is integer or half-integer + if (m0.wrapping_shl(si as u32)) == 0 { + return DoubleDouble::new(0., f64::copysign(0.0, x)); // x is integer + } + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // t = 0 if |x| = 1/2 mod 2, t = 1 if |x| = 3/2 mod 2 + return DoubleDouble::new( + 0., + if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }, + ); + } + + let (y, k) = reduce_pi_64(x); + + // // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let sin_k = DoubleDouble::from_bit_pair(SINPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + + let r_sincos = sincospi_eval_extended(y); + + let sin_k_cos_y = DoubleDouble::quick_mult(sin_k, r_sincos.v_cos); + let cos_k_sin_y = DoubleDouble::quick_mult(cos_k, r_sincos.v_sin); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + DoubleDouble::from_exact_add(rr.hi, rr.lo) +} + +#[inline(always)] +fn sinpi_gen_impl(x: f64, backend: B) -> f64 { + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return x; + } + let e: i32 = (ax >> 52) as i32; + let m0 = (ix & 0x000fffffffffffff) | (1u64 << 52); + let sgn: i64 = (ix as i64) >> 63; + let m = ((m0 as i64) ^ sgn).wrapping_sub(sgn); + let mut s: i32 = 1063i32.wrapping_sub(e); + if s < 0 { + if e == 0x7ff { + if (ix << 12) == 0 { + return f64::NAN; + } + return x + x; // case x=NaN + } + s = -s - 1; + if s > 10 { + return f64::copysign(0.0, x); + } + let iq: u64 = (m as u64).wrapping_shl(s as u32); + if (iq & 2047) == 0 { + return f64::copysign(0.0, x); + } + } + + if ax <= 0x3fa2000000000000u64 { + // |x| <= 0.03515625 + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + + if ax < 0x3c90000000000000 { + // for x near zero, sinpi(x) = pi*x + O(x^3), thus worst cases are those + // of the function pi*x, and if x is a worst case, then 2*x is another + // one in the next binade. For this reason, worst cases are only included + // for the binade [2^-1022, 2^-1021). For larger binades, + // up to [2^-54,2^-53), worst cases should be deduced by multiplying + // by some power of 2. + if ax < 0x0350000000000000 { + let t = x * f64::from_bits(0x4690000000000000); + let z = backend.quick_mult_f64(PI, t); + let r = z.to_f64(); + let rs = r * f64::from_bits(0x3950000000000000); + let rt = rs * f64::from_bits(0x4690000000000000); + return backend.dyad_fma( + (z.hi - rt) + z.lo, + f64::from_bits(0x3950000000000000), + rs, + ); + } + let z = backend.quick_mult_f64(PI, x); + return z.to_f64(); + } + + /* + Poly generated by Sollya: + d = [0, 0.03515625]; + f_sin = sin(y*pi)/y; + Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|107, D...|], d, relative, floating); + + See ./notes/sinpi_zero.sollya + */ + + let x2 = x * x; + let x3 = x2 * x; + let x4 = x2 * x2; + + let eps = x * backend.fma( + x2, + f64::from_bits(0x3d00000000000000), // 2^-47 + f64::from_bits(0x3bd0000000000000), // 2^-66 + ); + + const C: [u64; 4] = [ + 0xc014abbce625be51, + 0x400466bc67754b46, + 0xbfe32d2cc12a51f4, + 0x3fb5060540058476, + ]; + + const C_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a67088eb1a46, 0x400921fb54442d18)); + + let mut z = backend.quick_mult_f64(C_PI, x); + + let zl0 = backend.fma(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let zl1 = backend.fma(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + + z.lo = backend.fma(x3, backend.fma(x4, zl1, zl0), z.lo); + let lb = z.hi + (z.lo - eps); + let ub = z.hi + (z.lo + eps); + if lb == ub { + return lb; + } + return as_sinpi_zero(x, &backend); + } + + let si = e.wrapping_sub(1011); + if si >= 0 && (m0.wrapping_shl(si.wrapping_add(1) as u32)) == 0 { + // x is integer or half-integer + if (m0.wrapping_shl(si as u32)) == 0 { + return f64::copysign(0.0, x); // x is integer + } + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // t = 0 if |x| = 1/2 mod 2, t = 1 if |x| = 3/2 mod 2 + return if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }; + } + + let (y, k) = backend.arg_reduce_pi_64(x); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let sin_k = DoubleDouble::from_bit_pair(SINPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + + let r_sincos = sincospi_eval(y, &backend); + + let sin_k_cos_y = backend.quick_mult(sin_k, r_sincos.v_cos); + let cos_k_sin_y = backend.quick_mult(cos_k, r_sincos.v_sin); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + let ub = rr.hi + (rr.lo + r_sincos.err); // (rr.lo + ERR); + let lb = rr.hi + (rr.lo - r_sincos.err); // (rr.lo - ERR); + + if ub == lb { + return rr.to_f64(); + } + sinpi_dd(y, sin_k, cos_k, &backend) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sinpi_fma_impl(x: f64) -> f64 { + sinpi_gen_impl(x, FmaSinCosPiBackend {}) +} + +/// Computes sin(PI*x) +/// +/// Max ULP 0.5 +pub fn f_sinpi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sinpi_gen_impl(x, GenSinCosPiBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sinpi_fma_impl + } else { + fn def_sinpi(x: f64) -> f64 { + sinpi_gen_impl(x, GenSinCosPiBackend {}) + } + def_sinpi + } + }); + unsafe { q(x) } + } +} + +#[inline(always)] +fn cospi_gen_impl(x: f64, backend: B) -> f64 { + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return 1.0; + } + let e: i32 = (ax >> 52) as i32; + // e is the unbiased exponent, we have 2^(e-1023) <= |x| < 2^(e-1022) + let m: i64 = ((ix & 0x000fffffffffffff) | (1u64 << 52)) as i64; + let mut s = 1063i32.wrapping_sub(e); // 2^(40-s) <= |x| < 2^(41-s) + if s < 0 { + // |x| >= 2^41 + if e == 0x7ff { + // NaN or Inf + if ix.wrapping_shl(12) == 0 { + return f64::NAN; + } + return x + x; // NaN + } + s = -s - 1; // now 2^(41+s) <= |x| < 2^(42+s) + if s > 11 { + return 1.0; + } // |x| >= 2^53 + let iq: u64 = (m as u64).wrapping_shl(s as u32).wrapping_add(1024); + if (iq & 2047) == 0 { + return 0.0; + } + } + if ax <= 0x3f30000000000000u64 { + // |x| <= 2^-12, |x| <= 0.000244140625 + if ax <= 0x3e2ccf6429be6621u64 { + return 1.0 - f64::from_bits(0x3c80000000000000); + } + let x2 = x * x; + let x4 = x2 * x2; + let eps = x2 * f64::from_bits(0x3cfa000000000000); + + /* + Generated by Sollya: + d = [0, 0.000244140625]; + f_cos = cos(y*pi); + Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|107, 107, D...|], d, relative, floating); + + See ./notes/cospi.sollya + */ + + const C: [u64; 4] = [ + 0xc013bd3cc9be45de, + 0x40103c1f081b5ac4, + 0xbff55d3c7ff79b60, + 0x3fd24c7b6f7d0690, + ]; + + let p0 = backend.fma(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let p1 = backend.fma(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + + let p = x2 * backend.fma(x4, p0, p1); + let lb = (p - eps) + 1.; + let ub = (p + eps) + 1.; + if lb == ub { + return lb; + } + return as_cospi_zero(x, &backend); + } + + let si: i32 = e.wrapping_sub(1011); + if si >= 0 && ((m as u64).wrapping_shl(si as u32) ^ 0x8000000000000000u64) == 0 { + return 0.0; + } + + let (y, k) = backend.arg_reduce_pi_64(x); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let msin_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(64) & 127) as usize], + ); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + + let r_sincos = sincospi_eval(y, &backend); + + let cos_k_cos_y = backend.quick_mult(r_sincos.v_cos, cos_k); + let cos_k_msin_y = backend.quick_mult(r_sincos.v_sin, msin_k); + + // cos_k_cos_y is always >> cos_k_msin_y + let mut rr = DoubleDouble::from_exact_add(cos_k_cos_y.hi, cos_k_msin_y.hi); + rr.lo += cos_k_cos_y.lo + cos_k_msin_y.lo; + + let ub = rr.hi + (rr.lo + r_sincos.err); // (rr.lo + ERR); + let lb = rr.hi + (rr.lo - r_sincos.err); // (rr.lo - ERR); + + if ub == lb { + return rr.to_f64(); + } + sinpi_dd(y, cos_k, msin_k, &backend) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cospi_fma_impl(x: f64) -> f64 { + cospi_gen_impl(x, FmaSinCosPiBackend {}) +} + +/// Computes cos(PI*x) +/// +/// Max found ULP 0.5 +pub fn f_cospi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cospi_gen_impl(x, GenSinCosPiBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cospi_fma_impl + } else { + fn def_cospi(x: f64) -> f64 { + cospi_gen_impl(x, GenSinCosPiBackend {}) + } + def_cospi + } + }); + unsafe { q(x) } + } +} + +#[inline(always)] +fn sincospi_gen_impl(x: f64, backend: B) -> (f64, f64) { + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return (x, 1.0); + } + let e: i32 = (ax >> 52) as i32; + // e is the unbiased exponent, we have 2^(e-1023) <= |x| < 2^(e-1022) + let m0 = (ix & 0x000fffffffffffff) | (1u64 << 52); + let m: i64 = ((ix & 0x000fffffffffffff) | (1u64 << 52)) as i64; + let mut s = 1063i32.wrapping_sub(e); // 2^(40-s) <= |x| < 2^(41-s) + if s < 0 { + // |x| >= 2^41 + if e == 0x7ff { + // NaN or Inf + if ix.wrapping_shl(12) == 0 { + return (f64::NAN, f64::NAN); + } + return (x + x, x + x); // NaN + } + s = -s - 1; + if s > 10 { + static CF: [f64; 2] = [1., -1.]; + let is_odd = backend.odd_integer(f64::from_bits(ax)); + let cos_x = CF[is_odd as usize]; + return (f64::copysign(0.0, x), cos_x); + } // |x| >= 2^53 + let iq: u64 = (m as u64).wrapping_shl(s as u32); + + // sinpi = 0 when multiple of 2048 + let sin_zero = (iq & 2047) == 0; + + // cospi = 0 when offset-by-half multiple of 2048 + let cos_zero = ((m as u64).wrapping_shl(s as u32).wrapping_add(1024) & 2047) == 0; + + if sin_zero && cos_zero { + // both zero (only possible if NaN or something degenerate) + } else if sin_zero { + static CF: [f64; 2] = [1., -1.]; + let is_odd = backend.odd_integer(f64::from_bits(ax)); + let cos_x = CF[is_odd as usize]; + return (0.0, cos_x); // sin = 0, cos = ±1 + } else if cos_zero { + // x = k / 2 * PI + let si = e.wrapping_sub(1011); + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // making sin decision based on quadrant + return if t == 0 { + (f64::copysign(1.0, x), 0.0) + } else { + (-f64::copysign(1.0, x), 0.0) + }; // sin = ±1, cos = 0 + } + } + + if ax <= 0x3f30000000000000u64 { + // |x| <= 2^-12, |x| <= 0.000244140625 + if ax <= 0x3c90000000000000u64 { + const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), + ); + let sin_x = if ax < 0x0350000000000000 { + let t = x * f64::from_bits(0x4690000000000000); + let z = backend.quick_mult_f64(PI, t); + let r = z.to_f64(); + let rs = r * f64::from_bits(0x3950000000000000); + let rt = rs * f64::from_bits(0x4690000000000000); + backend.dyad_fma((z.hi - rt) + z.lo, f64::from_bits(0x3950000000000000), rs) + } else { + let z = backend.quick_mult_f64(PI, x); + z.to_f64() + }; + return (sin_x, 1.0 - f64::from_bits(0x3c80000000000000)); + } + let x2 = x * x; + let x4 = x2 * x2; + let cos_eps = x2 * f64::from_bits(0x3cfa000000000000); + + /* + Generated by Sollya: + d = [0, 0.000244140625]; + f_cos = cos(y*pi); + Q = fpminimax(f_cos, [|0, 2, 4, 6, 8|], [|107, 107, D...|], d, relative, floating); + + See ./notes/cospi.sollya + */ + + const COS_C: [u64; 4] = [ + 0xc013bd3cc9be45de, + 0x40103c1f081b5ac4, + 0xbff55d3c7ff79b60, + 0x3fd24c7b6f7d0690, + ]; + + let p0 = backend.fma(x2, f64::from_bits(COS_C[3]), f64::from_bits(COS_C[2])); + let p1 = backend.fma(x2, f64::from_bits(COS_C[1]), f64::from_bits(COS_C[0])); + + let p = x2 * backend.fma(x4, p0, p1); + let cos_lb = (p - cos_eps) + 1.; + let cos_ub = (p + cos_eps) + 1.; + let cos_x = if cos_lb == cos_ub { + cos_lb + } else { + as_cospi_zero(x, &backend) + }; + + /* + Poly generated by Sollya: + d = [0, 0.03515625]; + f_sin = sin(y*pi)/y; + Q = fpminimax(f_sin, [|0, 2, 4, 6, 8, 10|], [|107, D...|], d, relative, floating); + + See ./notes/sinpi_zero.sollya + */ + + const SIN_C: [u64; 4] = [ + 0xc014abbce625be51, + 0x400466bc67754b46, + 0xbfe32d2cc12a51f4, + 0x3fb5060540058476, + ]; + + const C_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a67088eb1a46, 0x400921fb54442d18)); + + let mut z = backend.quick_mult_f64(C_PI, x); + + let x3 = x2 * x; + + let zl0 = backend.fma(x2, f64::from_bits(SIN_C[1]), f64::from_bits(SIN_C[0])); + let zl1 = backend.fma(x2, f64::from_bits(SIN_C[3]), f64::from_bits(SIN_C[2])); + + let sin_eps = x * backend.fma( + x2, + f64::from_bits(0x3d00000000000000), // 2^-47 + f64::from_bits(0x3bd0000000000000), // 2^-66 + ); + + z.lo = backend.fma(x3, backend.fma(x4, zl1, zl0), z.lo); + let sin_lb = z.hi + (z.lo - sin_eps); + let sin_ub = z.hi + (z.lo + sin_eps); + let sin_x = if sin_lb == sin_ub { + sin_lb + } else { + as_sinpi_zero(x, &backend) + }; + return (sin_x, cos_x); + } + + let si = e.wrapping_sub(1011); + if si >= 0 && (m0.wrapping_shl(si.wrapping_add(1) as u32)) == 0 { + // x is integer or half-integer + if (m0.wrapping_shl(si as u32)) == 0 { + static CF: [f64; 2] = [1., -1.]; + let is_odd = backend.odd_integer(f64::from_bits(ax)); + let cos_x = CF[is_odd as usize]; + return (f64::copysign(0.0, x), cos_x); // x is integer + } + // x is half-integer + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // t = 0 if |x| = 1/2 mod 2, t = 1 if |x| = 3/2 mod 2 + return if t == 0 { + (f64::copysign(1.0, x), 0.0) + } else { + (-f64::copysign(1.0, x), 0.0) + }; + } + + let (y, k) = backend.arg_reduce_pi_64(x); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let sin_k = DoubleDouble::from_bit_pair(SINPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + let msin_k = -sin_k; + + let r_sincos = sincospi_eval(y, &backend); + + let sin_k_cos_y = backend.quick_mult(sin_k, r_sincos.v_cos); + let cos_k_sin_y = backend.quick_mult(cos_k, r_sincos.v_sin); + + let cos_k_cos_y = backend.quick_mult(r_sincos.v_cos, cos_k); + let msin_k_sin_y = backend.quick_mult(r_sincos.v_sin, msin_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr_sin = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr_sin.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + let sin_ub = rr_sin.hi + (rr_sin.lo + r_sincos.err); // (rr.lo + ERR); + let sin_lb = rr_sin.hi + (rr_sin.lo - r_sincos.err); // (rr.lo - ERR); + + let mut rr_cos = DoubleDouble::from_exact_add(cos_k_cos_y.hi, msin_k_sin_y.hi); + rr_cos.lo += cos_k_cos_y.lo + msin_k_sin_y.lo; + + let cos_ub = rr_cos.hi + (rr_cos.lo + r_sincos.err); // (rr.lo + ERR); + let cos_lb = rr_cos.hi + (rr_cos.lo - r_sincos.err); // (rr.lo - ERR); + + if sin_ub == sin_lb && cos_lb == cos_ub { + return (rr_sin.to_f64(), rr_cos.to_f64()); + } + + sincospi_dd(y, sin_k, cos_k, cos_k, msin_k, &backend) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sincospi_fma_impl(x: f64) -> (f64, f64) { + sincospi_gen_impl(x, FmaSinCosPiBackend {}) +} + +/// Computes sin(PI*x) and cos(PI*x) +/// +/// Max found ULP 0.5 +pub fn f_sincospi(x: f64) -> (f64, f64) { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sincospi_gen_impl(x, GenSinCosPiBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock (f64, f64)> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sincospi_fma_impl + } else { + fn def_sincospi(x: f64) -> (f64, f64) { + sincospi_gen_impl(x, GenSinCosPiBackend {}) + } + def_sincospi + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sinpi() { + assert_eq!(f_sinpi(262143.50006870925), -0.9999999767029883); + assert_eq!(f_sinpi(7124076477593855.), 0.); + assert_eq!(f_sinpi(-11235582092889474000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), -0.); + assert_eq!(f_sinpi(-2.7430620343968443e303), -0.0); + assert_eq!(f_sinpi(0.00003195557007273919), 0.00010039138401316004); + assert_eq!(f_sinpi(-0.038357843137253766), -0.12021328061499763); + assert_eq!(f_sinpi(1.0156097449358867), -0.04901980680173724); + assert_eq!(f_sinpi(74.8593852519989), 0.42752597787896457); + assert_eq!(f_sinpi(0.500091552734375), 0.9999999586369661); + assert_eq!(f_sinpi(0.5307886532952182), 0.9953257438106751); + assert_eq!(f_sinpi(3.1415926535897936), -0.43030121700009316); + assert_eq!(f_sinpi(-0.5305172747685276), -0.9954077178320563); + assert_eq!(f_sinpi(-0.03723630312089732), -0.1167146713267927); + assert_eq!( + f_sinpi(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022946074000077123), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007208721750737005 + ); + assert_eq!( + f_sinpi(0.000000000000000000000000000000000000007413093439574428), + 2.3288919890141717e-38 + ); + assert_eq!(f_sinpi(0.0031909299901270445), 0.0100244343161398578); + assert_eq!(f_sinpi(0.11909245901270445), 0.36547215190661003); + assert_eq!(f_sinpi(0.99909245901270445), 0.0028511202357662186); + assert!(f_sinpi(f64::INFINITY).is_nan()); + assert!(f_sinpi(f64::NEG_INFINITY).is_nan()); + assert!(f_sinpi(f64::NAN).is_nan()); + } + + #[test] + fn test_sincospi() { + let v0 = f_sincospi(1.0156097449358867); + assert_eq!(v0.0, f_sinpi(1.0156097449358867)); + assert_eq!(v0.1, f_cospi(1.0156097449358867)); + + let v1 = f_sincospi(4503599627370496.); + assert_eq!(v1.0, f_sinpi(4503599627370496.)); + assert_eq!(v1.1, f_cospi(4503599627370496.)); + + let v1 = f_sincospi(-108.); + assert_eq!(v1.0, f_sinpi(-108.)); + assert_eq!(v1.1, f_cospi(-108.)); + + let v1 = f_sincospi(3.); + assert_eq!(v1.0, f_sinpi(3.)); + assert_eq!(v1.1, f_cospi(3.)); + + let v1 = f_sincospi(13.5); + assert_eq!(v1.0, f_sinpi(13.5)); + assert_eq!(v1.1, f_cospi(13.5)); + + let v1 = f_sincospi(7124076477593855.); + assert_eq!(v1.0, f_sinpi(7124076477593855.)); + assert_eq!(v1.1, f_cospi(7124076477593855.)); + + let v1 = f_sincospi(2533419148247186.5); + assert_eq!(v1.0, f_sinpi(2533419148247186.5)); + assert_eq!(v1.1, f_cospi(2533419148247186.5)); + + let v1 = f_sincospi(2.2250653705240375E-308); + assert_eq!(v1.0, f_sinpi(2.2250653705240375E-308)); + assert_eq!(v1.1, f_cospi(2.2250653705240375E-308)); + + let v1 = f_sincospi(2533420818956351.); + assert_eq!(v1.0, f_sinpi(2533420818956351.)); + assert_eq!(v1.1, f_cospi(2533420818956351.)); + + let v1 = f_sincospi(2533822406803233.5); + assert_eq!(v1.0, f_sinpi(2533822406803233.5)); + assert_eq!(v1.1, f_cospi(2533822406803233.5)); + + let v1 = f_sincospi(-3040685725640478.5); + assert_eq!(v1.0, f_sinpi(-3040685725640478.5)); + assert_eq!(v1.1, f_cospi(-3040685725640478.5)); + + let v1 = f_sincospi(2533419148247186.5); + assert_eq!(v1.0, f_sinpi(2533419148247186.5)); + assert_eq!(v1.1, f_cospi(2533419148247186.5)); + + let v1 = f_sincospi(2533420819267583.5); + assert_eq!(v1.0, f_sinpi(2533420819267583.5)); + assert_eq!(v1.1, f_cospi(2533420819267583.5)); + + let v1 = f_sincospi(6979704728846336.); + assert_eq!(v1.0, f_sinpi(6979704728846336.)); + assert_eq!(v1.1, f_cospi(6979704728846336.)); + + let v1 = f_sincospi(7124076477593855.); + assert_eq!(v1.0, f_sinpi(7124076477593855.)); + assert_eq!(v1.1, f_cospi(7124076477593855.)); + + let v1 = f_sincospi(-0.00000000002728839192371484); + assert_eq!(v1.0, f_sinpi(-0.00000000002728839192371484)); + assert_eq!(v1.1, f_cospi(-0.00000000002728839192371484)); + + let v1 = f_sincospi(0.00002465398569495569); + assert_eq!(v1.0, f_sinpi(0.00002465398569495569)); + assert_eq!(v1.1, f_cospi(0.00002465398569495569)); + } + + #[test] + fn test_cospi() { + assert_eq!(0.9999497540959953, f_cospi(0.0031909299901270445)); + assert_eq!(0.9308216542079669, f_cospi(0.11909299901270445)); + assert_eq!(-0.1536194873288318, f_cospi(0.54909299901270445)); + assert!(f_cospi(f64::INFINITY).is_nan()); + assert!(f_cospi(f64::NEG_INFINITY).is_nan()); + assert!(f_cospi(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincospi_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincospi_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincospi_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** +Generated by Sollya: +```python +print("[") +for k in range(128): + k = RealField(150)(k) * RealField(150).pi() / RealField(150)(64) + print_double_double("", k.sin()) +print("];") +``` +**/ +pub(crate) static SINPI_K_PI_OVER_64: [(u64, u64); 128] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbc2912bd0d569a90, 0x3fa91f65f10dd814), + (0xbc3e2718d26ed688, 0x3fb917a6bc29b42c), + (0x3c513000a89a11e0, 0x3fc2c8106e8e613a), + (0xbc626d19b9ff8d82, 0x3fc8f8b83c69a60b), + (0xbc642deef11da2c4, 0x3fcf19f97b215f1b), + (0xbc75d28da2c4612d, 0x3fd294062ed59f06), + (0xbc1efdc0d58cf620, 0x3fd58f9a75ab1fdd), + (0xbc672cedd3d5a610, 0x3fd87de2a6aea963), + (0x3c65b362cb974183, 0x3fdb5d1009e15cc0), + (0x3c5e0d891d3c6841, 0x3fde2b5d3806f63b), + (0xbc8a5a014347406c, 0x3fe073879922ffee), + (0x3c8b25dd267f6600, 0x3fe1c73b39ae68c8), + (0xbc6efcc626f74a6f, 0x3fe30ff7fce17035), + (0x3c68076a2cfdc6b3, 0x3fe44cf325091dd6), + (0xbc875720992bfbb2, 0x3fe57d69348ceca0), + (0xbc8bdd3413b26456, 0x3fe6a09e667f3bcd), + (0xbc70f537acdf0ad7, 0x3fe7b5df226aafaf), + (0xbc82c5e12ed1336d, 0x3fe8bc806b151741), + (0xbc830ee286712474, 0x3fe9b3e047f38741), + (0x3c39f630e8b6dac8, 0x3fea9b66290ea1a3), + (0xbc8bc69f324e6d61, 0x3feb728345196e3e), + (0xbc76e0b1757c8d07, 0x3fec38b2f180bdb1), + (0xbc5e7b6bb5ab58ae, 0x3feced7af43cc773), + (0x3c7457e610231ac2, 0x3fed906bcf328d46), + (0xbc8014c76c126527, 0x3fee212104f686e5), + (0x3c8760b1e2e3f81e, 0x3fee9f4156c62dda), + (0x3c752c7adc6b4989, 0x3fef0a7efb9230d7), + (0x3c7562172a361fd3, 0x3fef6297cff75cb0), + (0xbc87a0a8ca13571f, 0x3fefa7557f08a517), + (0xbc887df6378811c7, 0x3fefd88da3d12526), + (0xbc6c57bc2e24aa15, 0x3feff621e3796d7e), + (0x0000000000000000, 0x3ff0000000000000), + (0xbc6c57bc2e24aa15, 0x3feff621e3796d7e), + (0xbc887df6378811c7, 0x3fefd88da3d12526), + (0xbc87a0a8ca13571f, 0x3fefa7557f08a517), + (0x3c7562172a361fd3, 0x3fef6297cff75cb0), + (0x3c752c7adc6b4989, 0x3fef0a7efb9230d7), + (0x3c8760b1e2e3f81e, 0x3fee9f4156c62dda), + (0xbc8014c76c126527, 0x3fee212104f686e5), + (0x3c7457e610231ac2, 0x3fed906bcf328d46), + (0xbc5e7b6bb5ab58ae, 0x3feced7af43cc773), + (0xbc76e0b1757c8d07, 0x3fec38b2f180bdb1), + (0xbc8bc69f324e6d61, 0x3feb728345196e3e), + (0x3c39f630e8b6dac8, 0x3fea9b66290ea1a3), + (0xbc830ee286712474, 0x3fe9b3e047f38741), + (0xbc82c5e12ed1336d, 0x3fe8bc806b151741), + (0xbc70f537acdf0ad7, 0x3fe7b5df226aafaf), + (0xbc8bdd3413b26456, 0x3fe6a09e667f3bcd), + (0xbc875720992bfbb2, 0x3fe57d69348ceca0), + (0x3c68076a2cfdc6b3, 0x3fe44cf325091dd6), + (0xbc6efcc626f74a6f, 0x3fe30ff7fce17035), + (0x3c8b25dd267f6600, 0x3fe1c73b39ae68c8), + (0xbc8a5a014347406c, 0x3fe073879922ffee), + (0x3c5e0d891d3c6841, 0x3fde2b5d3806f63b), + (0x3c65b362cb974183, 0x3fdb5d1009e15cc0), + (0xbc672cedd3d5a610, 0x3fd87de2a6aea963), + (0xbc1efdc0d58cf620, 0x3fd58f9a75ab1fdd), + (0xbc75d28da2c4612d, 0x3fd294062ed59f06), + (0xbc642deef11da2c4, 0x3fcf19f97b215f1b), + (0xbc626d19b9ff8d82, 0x3fc8f8b83c69a60b), + (0x3c513000a89a11e0, 0x3fc2c8106e8e613a), + (0xbc3e2718d26ed688, 0x3fb917a6bc29b42c), + (0xbc2912bd0d569a90, 0x3fa91f65f10dd814), + (0xb331056713b19377, 0xb69f77598338bfdf), + (0x3c2912bd0d569a90, 0xbfa91f65f10dd814), + (0x3c3e2718d26ed688, 0xbfb917a6bc29b42c), + (0xbc513000a89a11e0, 0xbfc2c8106e8e613a), + (0x3c626d19b9ff8d82, 0xbfc8f8b83c69a60b), + (0x3c642deef11da2c4, 0xbfcf19f97b215f1b), + (0x3c75d28da2c4612d, 0xbfd294062ed59f06), + (0x3c1efdc0d58cf620, 0xbfd58f9a75ab1fdd), + (0x3c672cedd3d5a610, 0xbfd87de2a6aea963), + (0xbc65b362cb974183, 0xbfdb5d1009e15cc0), + (0xbc5e0d891d3c6841, 0xbfde2b5d3806f63b), + (0x3c8a5a014347406c, 0xbfe073879922ffee), + (0xbc8b25dd267f6600, 0xbfe1c73b39ae68c8), + (0x3c6efcc626f74a6f, 0xbfe30ff7fce17035), + (0xbc68076a2cfdc6b3, 0xbfe44cf325091dd6), + (0x3c875720992bfbb2, 0xbfe57d69348ceca0), + (0x3c8bdd3413b26456, 0xbfe6a09e667f3bcd), + (0x3c70f537acdf0ad7, 0xbfe7b5df226aafaf), + (0x3c82c5e12ed1336d, 0xbfe8bc806b151741), + (0x3c830ee286712474, 0xbfe9b3e047f38741), + (0xbc39f630e8b6dac8, 0xbfea9b66290ea1a3), + (0x3c8bc69f324e6d61, 0xbfeb728345196e3e), + (0x3c76e0b1757c8d07, 0xbfec38b2f180bdb1), + (0x3c5e7b6bb5ab58ae, 0xbfeced7af43cc773), + (0xbc7457e610231ac2, 0xbfed906bcf328d46), + (0x3c8014c76c126527, 0xbfee212104f686e5), + (0xbc8760b1e2e3f81e, 0xbfee9f4156c62dda), + (0xbc752c7adc6b4989, 0xbfef0a7efb9230d7), + (0xbc7562172a361fd3, 0xbfef6297cff75cb0), + (0x3c87a0a8ca13571f, 0xbfefa7557f08a517), + (0x3c887df6378811c7, 0xbfefd88da3d12526), + (0x3c6c57bc2e24aa15, 0xbfeff621e3796d7e), + (0x0000000000000000, 0xbff0000000000000), + (0x3c6c57bc2e24aa15, 0xbfeff621e3796d7e), + (0x3c887df6378811c7, 0xbfefd88da3d12526), + (0x3c87a0a8ca13571f, 0xbfefa7557f08a517), + (0xbc7562172a361fd3, 0xbfef6297cff75cb0), + (0xbc752c7adc6b4989, 0xbfef0a7efb9230d7), + (0xbc8760b1e2e3f81e, 0xbfee9f4156c62dda), + (0x3c8014c76c126527, 0xbfee212104f686e5), + (0xbc7457e610231ac2, 0xbfed906bcf328d46), + (0x3c5e7b6bb5ab58ae, 0xbfeced7af43cc773), + (0x3c76e0b1757c8d07, 0xbfec38b2f180bdb1), + (0x3c8bc69f324e6d61, 0xbfeb728345196e3e), + (0xbc39f630e8b6dac8, 0xbfea9b66290ea1a3), + (0x3c830ee286712474, 0xbfe9b3e047f38741), + (0x3c82c5e12ed1336d, 0xbfe8bc806b151741), + (0x3c70f537acdf0ad7, 0xbfe7b5df226aafaf), + (0x3c8bdd3413b26456, 0xbfe6a09e667f3bcd), + (0x3c875720992bfbb2, 0xbfe57d69348ceca0), + (0xbc68076a2cfdc6b3, 0xbfe44cf325091dd6), + (0x3c6efcc626f74a6f, 0xbfe30ff7fce17035), + (0xbc8b25dd267f6600, 0xbfe1c73b39ae68c8), + (0x3c8a5a014347406c, 0xbfe073879922ffee), + (0xbc5e0d891d3c6841, 0xbfde2b5d3806f63b), + (0xbc65b362cb974183, 0xbfdb5d1009e15cc0), + (0x3c672cedd3d5a610, 0xbfd87de2a6aea963), + (0x3c1efdc0d58cf620, 0xbfd58f9a75ab1fdd), + (0x3c75d28da2c4612d, 0xbfd294062ed59f06), + (0x3c642deef11da2c4, 0xbfcf19f97b215f1b), + (0x3c626d19b9ff8d82, 0xbfc8f8b83c69a60b), + (0xbc513000a89a11e0, 0xbfc2c8106e8e613a), + (0x3c3e2718d26ed688, 0xbfb917a6bc29b42c), + (0x3c2912bd0d569a90, 0xbfa91f65f10dd814), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sincpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sincpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,485 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::polyeval::f_estrin_polyeval5; +use crate::sincospi::{GenSinCosPiBackend, SinCosPiBackend, reduce_pi_64}; +use crate::sincospi_tables::SINPI_K_PI_OVER_64; + +/** +Sinpi on range [0.0, 0.03515625] + +Generated poly by Sollya: +```text +d = [0, 0.03515625]; +f_sincpi = sin(y*pi)/(y*pi); +Q = fpminimax(f_sincpi, [|0, 2, 4, 6, 8, 10, 12|], [|107...|], d, relative, floating); +``` +See ./notes/sincpi_at_zero_dd.sollya +**/ +#[cold] +fn as_sincpi_zero(x: f64, backend: &B) -> f64 { + const C: [(u64, u64); 7] = [ + (0xb9d3080000000000, 0x3ff0000000000000), + (0xbc81873d86314302, 0xbffa51a6625307d3), + (0x3c84871b4ffeefae, 0x3fe9f9cb402bc46c), + (0xbc5562d6ae037010, 0xbfc86a8e4720db66), + (0xbc386c93f4549bac, 0x3f9ac6805cf31ffd), + (0x3c0dbda368edfa40, 0xbf633816a3399d4e), + (0xbbcf22ccc18f27a9, 0x3f23736e6a59edd9), + ]; + let x2 = backend.exact_mult(x, x); + let mut p = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[6]), + DoubleDouble::from_bit_pair(C[5]), + ); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = backend.quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p.to_f64() +} + +#[inline(always)] +fn sincpi_gen_impl(x: f64) -> f64 { + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return 1.; + } + let e: i32 = (ax >> 52) as i32; + let m0 = (ix & 0x000fffffffffffff) | (1u64 << 52); + let sgn: i64 = (ix as i64) >> 63; + let m = ((m0 as i64) ^ sgn).wrapping_sub(sgn); + let mut s: i32 = 1063i32.wrapping_sub(e); + if s < 0 { + if e == 0x7ff { + if (ix << 12) == 0 { + return f64::NAN; + } + return x + x; // case x=NaN + } + s = -s - 1; + if s > 10 { + return f64::copysign(0.0, x); + } + let iq: u64 = (m as u64).wrapping_shl(s as u32); + if (iq & 2047) == 0 { + return f64::copysign(0.0, x); + } + } + + if ax <= 0x3fa2000000000000u64 { + // |x| <= 0.03515625 + + if ax < 0x3c90000000000000u64 { + // |x| < f64::EPSILON + if ax <= 0x3b05798ee2308c3au64 { + // |x| <= 2.2204460492503131e-24 + return 1.; + } + // Small values approximated with Taylor poly + // sincpi(x) ~ 1 - x^2*Pi^2/6 + O(x^4) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + const M_SQR_PI_OVER_6: f64 = f64::from_bits(0xbffa51a6625307d3); + let p = f_fmla(x, M_SQR_PI_OVER_6 * x, 1.); + return p; + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::min_normal_f64; + return 1. - min_normal_f64(); + } + } + + // Poly generated by Sollya: + // d = [0, 0.03515625]; + // f_sincpi = sin(y*pi)/(y*pi); + // Q = fpminimax(f_sincpi, [|0, 2, 4, 6, 8, 10|], [|107, D...|], d, relative, floating); + // See ./notes/sincpi_at_zero.sollya + + let x2 = x * x; + + let eps = x * f_fmla( + x2, + f64::from_bits(0x3d00000000000000), // 2^-47 + f64::from_bits(0x3bd0000000000000), // 2^-66 + ); + + const C: [u64; 5] = [ + 0xbffa51a6625307d3, + 0x3fe9f9cb402bbeaa, + 0xbfc86a8e466bbb5b, + 0x3f9ac66d887e2f38, + 0xbf628473a38d289a, + ]; + + const F: DoubleDouble = + DoubleDouble::from_bit_pair((0xbb93f0a925810000, 0x3ff0000000000000)); + + let p = f_estrin_polyeval5( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + ); + let v = DoubleDouble::from_exact_mult(p, x2); + let z = DoubleDouble::add(F, v); + + let lb = z.hi + (z.lo - eps); + let ub = z.hi + (z.lo + eps); + if lb == ub { + return lb; + } + return as_sincpi_zero(x, &GenSinCosPiBackend {}); + } + + let si = e.wrapping_sub(1011); + if si >= 0 && (m0.wrapping_shl(si.wrapping_add(1) as u32)) == 0 { + // x is integer or half-integer + if (m0.wrapping_shl(si as u32)) == 0 { + return f64::copysign(0.0, x); // x is integer + } + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // t = 0 if |x| = 1/2 mod 2, t = 1 if |x| = 3/2 mod 2 + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let num = if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }; + const PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let r = DoubleDouble::quick_mult_f64(PI, x); + let v = DoubleDouble::from_f64_div_dd(num, r); + return v.to_f64(); + } + + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::two_product_compatible; + return if two_product_compatible(x) { + let num = if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }; + const PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let r = DoubleDouble::quick_mult_f64(PI, x); + let v = DoubleDouble::from_f64_div_dd(num, r); + v.to_f64() + } else { + use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + let num = DyadicFloat128::new_from_f64(if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }); + const PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -126, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + let dx = DyadicFloat128::new_from_f64(x); + let r = (PI * dx).reciprocal(); + (num * r).fast_as_f64() + }; + } + } + + let (y, k) = reduce_pi_64(x); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let sin_k = DoubleDouble::from_bit_pair(SINPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + + let r_sincos = crate::sincospi::sincospi_eval(y, &GenSinCosPiBackend {}); + + const PI: DoubleDouble = DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let scale = DoubleDouble::quick_mult_f64(PI, x); + + let sin_k_cos_y = DoubleDouble::quick_mult(sin_k, r_sincos.v_cos); + let cos_k_sin_y = DoubleDouble::quick_mult(cos_k, r_sincos.v_sin); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + rr = DoubleDouble::div(rr, scale); + + let ub = rr.hi + (rr.lo + r_sincos.err); // (rr.lo + ERR); + let lb = rr.hi + (rr.lo - r_sincos.err); // (rr.lo - ERR); + + if ub == lb { + return rr.to_f64(); + } + sincpi_dd(y, sin_k, cos_k, scale, &GenSinCosPiBackend {}) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn sincpi_fma_impl(x: f64) -> f64 { + use crate::sincospi::FmaSinCosPiBackend; + let ix = x.to_bits(); + let ax = ix & 0x7fff_ffff_ffff_ffff; + if ax == 0 { + return 1.; + } + let e: i32 = (ax >> 52) as i32; + let m0 = (ix & 0x000fffffffffffff) | (1u64 << 52); + let sgn: i64 = (ix as i64) >> 63; + let m = ((m0 as i64) ^ sgn).wrapping_sub(sgn); + let mut s: i32 = 1063i32.wrapping_sub(e); + if s < 0 { + if e == 0x7ff { + if (ix << 12) == 0 { + return f64::NAN; + } + return x + x; // case x=NaN + } + s = -s - 1; + if s > 10 { + return f64::copysign(0.0, x); + } + let iq: u64 = (m as u64).wrapping_shl(s as u32); + if (iq & 2047) == 0 { + return f64::copysign(0.0, x); + } + } + + if ax <= 0x3fa2000000000000u64 { + // |x| <= 0.03515625 + + if ax < 0x3c90000000000000u64 { + // |x| < f64::EPSILON + if ax <= 0x3b05798ee2308c3au64 { + // |x| <= 2.2204460492503131e-24 + return 1.; + } + // Small values approximated with Taylor poly + // sincpi(x) ~ 1 - x^2*Pi^2/6 + O(x^4) + const M_SQR_PI_OVER_6: f64 = f64::from_bits(0xbffa51a6625307d3); + return f64::mul_add(x, M_SQR_PI_OVER_6 * x, 1.); + } + + // Poly generated by Sollya: + // d = [0, 0.03515625]; + // f_sincpi = sin(y*pi)/(y*pi); + // Q = fpminimax(f_sincpi, [|0, 2, 4, 6, 8, 10|], [|107, D...|], d, relative, floating); + // See ./notes/sincpi_at_zero.sollya + + let x2 = x * x; + + let eps = x * f64::mul_add( + x2, + f64::from_bits(0x3d00000000000000), // 2^-47 + f64::from_bits(0x3bd0000000000000), // 2^-66 + ); + + const C: [u64; 5] = [ + 0xbffa51a6625307d3, + 0x3fe9f9cb402bbeaa, + 0xbfc86a8e466bbb5b, + 0x3f9ac66d887e2f38, + 0xbf628473a38d289a, + ]; + + const F: DoubleDouble = + DoubleDouble::from_bit_pair((0xbb93f0a925810000, 0x3ff0000000000000)); + + use crate::polyeval::d_estrin_polyeval5; + let p = d_estrin_polyeval5( + x2, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + ); + let v = DoubleDouble::from_exact_mult_fma(p, x2); + let z = DoubleDouble::add(F, v); + + let lb = z.hi + (z.lo - eps); + let ub = z.hi + (z.lo + eps); + if lb == ub { + return lb; + } + return as_sincpi_zero(x, &FmaSinCosPiBackend {}); + } + + let si = e.wrapping_sub(1011); + if si >= 0 && (m0.wrapping_shl(si.wrapping_add(1) as u32)) == 0 { + // x is integer or half-integer + if (m0.wrapping_shl(si as u32)) == 0 { + return f64::copysign(0.0, x); // x is integer + } + let t = (m0.wrapping_shl((si - 1) as u32)) >> 63; + // t = 0 if |x| = 1/2 mod 2, t = 1 if |x| = 3/2 mod 2 + let num = if t == 0 { + f64::copysign(1.0, x) + } else { + -f64::copysign(1.0, x) + }; + const PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let r = DoubleDouble::quick_mult_f64_fma(PI, x); + let v = DoubleDouble::from_f64_div_dd_fma(num, r); + return v.to_f64(); + } + + use crate::sincospi::reduce_pi_64_fma; + + let (y, k) = reduce_pi_64_fma(x); + + // cos(k * pi/64) = sin(k * pi/64 + pi/2) = sin((k + 32) * pi/64). + let sin_k = DoubleDouble::from_bit_pair(SINPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + let cos_k = DoubleDouble::from_bit_pair( + SINPI_K_PI_OVER_64[((k as u64).wrapping_add(32) & 127) as usize], + ); + + let r_sincos = crate::sincospi::sincospi_eval(y, &FmaSinCosPiBackend {}); + + const PI: DoubleDouble = DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + let scale = DoubleDouble::quick_mult_f64_fma(PI, x); + + let sin_k_cos_y = DoubleDouble::quick_mult_fma(sin_k, r_sincos.v_cos); + let cos_k_sin_y = DoubleDouble::quick_mult_fma(cos_k, r_sincos.v_sin); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + rr = DoubleDouble::div_fma(rr, scale); + + let ub = rr.hi + (rr.lo + r_sincos.err); // (rr.lo + ERR); + let lb = rr.hi + (rr.lo - r_sincos.err); // (rr.lo - ERR); + + if ub == lb { + return rr.to_f64(); + } + sincpi_dd(y, sin_k, cos_k, scale, &FmaSinCosPiBackend {}) +} + +/// Computes sin(PI\*x)/(PI\*x) +/// +/// Produces normalized sinc. +/// +/// Max ULP 0.5 +pub fn f_sincpi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + sincpi_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + sincpi_fma_impl + } else { + fn def_sincpi(x: f64) -> f64 { + sincpi_gen_impl(x) + } + def_sincpi + } + }); + unsafe { q(x) } + } +} + +#[cold] +#[inline(always)] +fn sincpi_dd( + x: f64, + sin_k: DoubleDouble, + cos_k: DoubleDouble, + scale: DoubleDouble, + backend: &B, +) -> f64 { + let r_sincos = crate::sincospi::sincospi_eval_dd(x, backend); + let cos_k_sin_y = backend.quick_mult(cos_k, r_sincos.v_sin); + let mut rr = backend.mul_add(sin_k, r_sincos.v_cos, cos_k_sin_y); + rr = backend.div(rr, scale); + rr.to_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sincpi_zero() { + assert_eq!(f_sincpi(2.2204460492503131e-24), 1.0); + assert_eq!(f_sincpi(f64::EPSILON), 1.0); + assert_eq!(f_sincpi(0.007080019335262543), 0.9999175469662566); + assert_eq!(f_sincpi(0.05468860710998057), 0.9950875152844803); + assert_eq!(f_sincpi(0.5231231231), 0.6068750737806441); + assert_eq!(f_sincpi(1.), 0.); + assert_eq!(f_sincpi(-1.), 0.); + assert_eq!(f_sincpi(-2.), 0.); + assert_eq!(f_sincpi(-3.), 0.); + assert!(f_sincpi(f64::INFINITY).is_nan()); + assert!(f_sincpi(f64::NEG_INFINITY).is_nan()); + assert!(f_sincpi(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sinmx.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinmx.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/sinmx.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/sinmx.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::polyeval::f_estrin_polyeval5; +use crate::sin::{range_reduction_small, sincos_eval}; +use crate::sin_helper::sincos_eval_dd; +use crate::sin_table::SIN_K_PI_OVER_128; +use crate::sincos_reduce::LargeArgumentReduction; + +#[cold] +#[inline(never)] +fn sinmx_accurate(y: DoubleDouble, sin_k: DoubleDouble, cos_k: DoubleDouble, x: f64) -> f64 { + let r_sincos = sincos_eval_dd(y); + + // k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + let mut rr = DoubleDouble::full_dd_add(sin_k_cos_y, cos_k_sin_y); + rr = DoubleDouble::full_add_f64(rr, -x); + rr.to_f64() +} + +#[cold] +fn sinmx_near_zero_hard(x: f64) -> f64 { + const C: [(u64, u64); 8] = [ + (0xb37137ef120d4bbd, 0xb6db8d4e2aa9f813), + (0xbc6555555554e720, 0xbfc5555555555555), + (0x3c01110fff8e3ea0, 0x3f81111111111111), + (0xbb6314569388b856, 0xbf2a01a01a01a01a), + (0xbb61f946e615f3cd, 0x3ec71de3a556c723), + (0x3a8998bc94bd3bf0, 0xbe5ae64567f2d4df), + (0xba702e73490290eb, 0x3de61245e54b6747), + (0xba0182df5b1ffd4c, 0xbd6ae4894bb27213), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut p = DoubleDouble::mul_add( + x2, + DoubleDouble::from_bit_pair(C[7]), + DoubleDouble::from_bit_pair(C[6]), + ); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::mul_add(x2, p, DoubleDouble::from_bit_pair(C[0])); + p = DoubleDouble::quick_mult_f64(p, x); + p.to_f64() +} + +/// Computes sin(x) - x +/// +/// ULP 0.5 +pub fn f_sinmx(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + // |x| < 2^32 (with FMA) or |x| < 2^23 (w/o FMA) + if x_e < E_BIAS + 16 { + if x_e < E_BIAS - 6 { + // |x| < 2^-6 + if x_e < E_BIAS - 32 { + // |x| < 2^-32 + // Signed zeros. + if x == 0.0 { + return x; + } + + // For |x| < 2^-32, taylor series sin(x) - x ~ -x^3/6 + let x2 = x * x; + let c = f_fmla( + x2, + f64::from_bits(0x3f81111111111111), + f64::from_bits(0xbfc5555555555555), + ) * x2; + return c * x; + } + + // Generated by Sollya: + // d = [2^-26, pi/16]; + // f_sinmx = (sin(x) - x)/x; + // Q = fpminimax(f_sinmx, [|0, 2, 4, 6, 8, 10, 12|], [|127, 127, D...|], d); + let x2 = DoubleDouble::from_exact_mult(x, x); + let p = f_estrin_polyeval5( + x2.hi, + f64::from_bits(0x3f81111111111111), + f64::from_bits(0xbf2a01a01a019d2f), + f64::from_bits(0x3ec71de3a5269512), + f64::from_bits(0xbe5ae642b76ba0f5), + f64::from_bits(0x3de6035da3c7eaed), + ); + let mut c = DoubleDouble::mul_f64_add( + x2, + p, + DoubleDouble::from_bit_pair((0xbc655542976eb2af, 0xbfc5555555555555)), + ); + c = DoubleDouble::mul_add( + x2, + c, + DoubleDouble::from_bit_pair((0x34b215c35dc9e9be, 0xb832bde584573661)), + ); + c = DoubleDouble::quick_mult_f64(c, x); + let err = f_fmla( + x2.hi, + f64::from_bits(0x3cc0000000000000), // 2^-51 + f64::from_bits(0x3bc0000000000000), // 2^-67 + ); + let ub = c.hi + (c.lo + err); + let lb = c.hi + (c.lo - err); + if ub == lb { + return c.to_f64(); + } + return sinmx_near_zero_hard(x); + } + // // Small range reduction. + (y, k) = range_reduction_small(x); + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + // sin(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let r_sincos = sincos_eval(y); + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + let sk = SIN_K_PI_OVER_128[(k & 255) as usize]; + let ck = SIN_K_PI_OVER_128[((k.wrapping_add(64)) & 255) as usize]; + + let sin_k = DoubleDouble::from_bit_pair(sk); + let cos_k = DoubleDouble::from_bit_pair(ck); + + let sin_k_cos_y = DoubleDouble::quick_mult(r_sincos.v_cos, sin_k); + let cos_k_sin_y = DoubleDouble::quick_mult(r_sincos.v_sin, cos_k); + + // sin_k_cos_y is always >> cos_k_sin_y + let mut rr = DoubleDouble::from_exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + rr.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + + rr = DoubleDouble::from_exact_add(rr.hi, rr.lo); + rr = DoubleDouble::full_add_f64(rr, -x); + + let rlp = rr.lo + r_sincos.err; + let rlm = rr.lo - r_sincos.err; + + let r_upper = rr.hi + rlp; // (rr.lo + ERR); + let r_lower = rr.hi + rlm; // (rr.lo - ERR); + + // Ziv's accuracy test + if r_upper == r_lower { + return rr.to_f64(); + } + + sinmx_accurate(y, sin_k, cos_k, x) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_sinf_test() { + assert_eq!(f_sinmx(0.0), 0.0); + assert_eq!(f_sinmx(1.0), -0.1585290151921035); + assert_eq!(f_sinmx(0.3), -0.0044797933386604245); + assert_eq!(f_sinmx(-1.0), 0.1585290151921035); + assert_eq!(f_sinmx(-0.3), 0.0044797933386604245); + assert_eq!(f_sinmx(std::f64::consts::PI / 2.), -0.5707963267948966); + assert!(f_sinmx(f64::INFINITY).is_nan()); + assert!(f_sinmx(f64::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod rsqrt; +mod rsqrtf; +mod sqrt1pm1; +mod sqrt1pm1f; +mod sqrtf; + +pub use rsqrt::f_rsqrt; +pub use rsqrtf::f_rsqrtf; +pub use sqrt1pm1::f_sqrt1pm1; +pub use sqrt1pm1f::f_sqrt1pm1f; +pub use sqrtf::sqrtf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrt.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,149 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; + +/// Computes 1/sqrt(x) +/// +/// Max ULP 0.5 +pub fn f_rsqrt(x: f64) -> f64 { + let ix = x.to_bits(); + let r: f64 = if ix < 1u64 << 52 { + // 0 <= x < 0x1p-1022 + if ix != 0 { + // x <> +0 + x.sqrt() / x + } else { + return f64::INFINITY; // case x = +0 + } + } else if ix >= 0x7ffu64 << 52 { + // NaN, Inf, x <= 0 + if ix.wrapping_shl(1) == 0 { + return f64::NEG_INFINITY; // x=-0 + } + if ix > 0xfff0000000000000u64 { + return x + x; + } // -NaN + if (ix >> 63) != 0 { + // x < 0 + return f64::NAN; + } + if ix.wrapping_shl(12) == 0 { + return 0.0; + } // +/-Inf + return x + x; // +NaN + } else { + // 0x1p-1022 <= x < 2^1024 + if ix > 0x7fd000000000000u64 { + // x > 2^1022 + // avoid spurious underflow in 1/x + (4.0 / x) * (0.25 * x.sqrt()) + } else { + (1.0 / x) * x.sqrt() + } + }; + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let d2x = DoubleDouble::from_exact_mult(r, x); + use crate::common::f_fmla; + let h = f_fmla(r, d2x.lo, f_fmla(r, d2x.hi, -1.0)); + let dr = (r * 0.5) * h; + r - dr + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::two_product_compatible; + if !two_product_compatible(x) { + recip_hard_dyadic(x, r) + } else { + let d2x = DoubleDouble::from_exact_mult(r, x); + let DoubleDouble { hi: h, lo: pr } = DoubleDouble::quick_mult_f64(d2x, r); + let DoubleDouble { hi: p, lo: q } = DoubleDouble::from_full_exact_add(-1.0, h); + let h = DoubleDouble::from_exact_add(p, pr + q); + let dr = DoubleDouble::quick_mult_f64(h, r * 0.5); + r - dr.hi - dr.lo + } + } +} + +#[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" +)))] +#[cold] +#[inline(never)] +fn recip_hard_dyadic(x: f64, r: f64) -> f64 { + use crate::dyadic_float::{DyadicFloat128, DyadicSign}; + let dx = DyadicFloat128::new_from_f64(x); + let dr = DyadicFloat128::new_from_f64(r); + const M_ONE: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0x80000000_00000000_00000000_00000000_u128, + }; + let d2 = dx * dr; + let h = d2 * dr + M_ONE; + let mut half_dr = dr; + half_dr.exponent -= 1; // * 0.5; + let ddr = half_dr * h; + (dr - ddr).fast_as_f64() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_rsqrt() { + assert_eq!(f_rsqrt(7518001163502890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011533172976634968); + assert_eq!(f_rsqrt(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001984274103353), + 709903255474595300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.); + assert_eq!(f_rsqrt(0.0), f64::INFINITY); + assert_eq!(f_rsqrt(4.0), 0.5); + assert_eq!(f_rsqrt(9.0), 1. / 3.); + assert_eq!(f_rsqrt(-0.0), f64::NEG_INFINITY); + assert!(f_rsqrt(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrtf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrtf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrtf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/rsqrtf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/// Computes 1/sqrt(x) +/// +/// Max ULP 0.5 +#[inline] +pub fn f_rsqrtf(x: f32) -> f32 { + let ix = x.to_bits(); + + // filter out exceptional cases + if ix >= 0xffu32 << 23 || ix == 0 { + if ix.wrapping_shl(1) == 0 { + return 1.0 / x; // +/-0 + } + if (ix >> 31) != 0 { + // x < 0 + return f32::NAN; + } + if ix.wrapping_shl(9) == 0 { + // |x| == Inf + return 0.; + } + return x + x; // nan + } + + let dx = x as f64; + ((1. / dx) * dx.sqrt()) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_rsqrtf() { + assert_eq!(f_rsqrtf(0.0), f32::INFINITY); + assert_eq!(f_rsqrtf(4.0), 0.5); + assert_eq!(f_rsqrtf(9.0), 1. / 3.); + assert_eq!(f_rsqrtf(-0.0), f32::NEG_INFINITY); + assert!(f_rsqrtf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,225 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::polyeval::f_polyeval6; + +#[cold] +fn sqrt1pm1_near_zero_hard(x: f64) -> f64 { + const C: [(u64, u64); 10] = [ + (0x3af2bd7b2a000000, 0x3fe0000000000000), + (0xbb1e743d7fe00000, 0xbfc0000000000000), + (0xbc18d267496ae7f8, 0x3fb0000000000000), + (0x3c2d7a2a887e1af8, 0xbfa4000000000000), + (0xbc3a4965117e40c8, 0x3f9c00000000150b), + (0x3c3dc057cb5bf82c, 0xbf9500000000209e), + (0x3c02d0756979aa48, 0x3f907ffff9c1db3d), + (0xbbe30b3d9b8a1020, 0xbf8acffff10fbdbc), + (0xbc16d26d5f2efc04, 0x3f8659830d1bf014), + (0x3c212aabd12c483e, 0xbf82ff830f9799c4), + ]; + let mut p = DoubleDouble::quick_mul_f64_add( + DoubleDouble::from_bit_pair(C[9]), + x, + DoubleDouble::from_bit_pair(C[8]), + ); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[7])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[6])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[5])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::quick_mul_f64_add(p, x, DoubleDouble::from_bit_pair(C[0])); + p = DoubleDouble::quick_mult_f64(p, x); + p.to_f64() +} + +/// Computes sqrt(1+x) - 1 +pub fn f_sqrt1pm1(x: f64) -> f64 { + let ix = x.to_bits(); + let ux = ix.wrapping_shl(1); + + if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 { + // |x| == NaN, x == inf, |x| == 0, |x| <= f64::EPSILON + if ux == 0 { + // |x| == 0 + return 0.; + } + if ux.wrapping_shl(11) == 0 { + // |x| == Inf + return if x.is_sign_negative() { + f64::NAN + } else { + f64::INFINITY + }; + } + + if ux <= 0x7960000000000000u64 { + // |x| <= f64::EPSILON + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + return f_fmla(-0.25 * x, 0.25 * x, x * 0.5); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::dyad_fmla; + return if x < 1e-150 { + dyad_fmla(-0.25 * x, 0.25 * x, x * 0.5) + } else { + f_fmla(-0.25 * x, 0.25 * x, x * 0.5) + }; + } + } + + return f64::NAN; // x == NaN + } + + if (ix >> 63) != 0 && ux >= 0x7fe0000000000000u64 { + // x < 0 and x >= 1 + if ux == 0x7fe0000000000000u64 { + // x == -1 + return -1.; + } + return f64::NAN; + } + + if ux <= 0x7f1126e978d4fdf4u64 { + // |x| <= 0.012 + + // Polynomial generated by Sollya: + // d = [-0.012, 0.012]; + // sqrt1pm1 = sqrt(x + 1) - 1; + // Q = fpminimax(sqrt1pm1, [|1,2,3,4,5,6,7|], [|1, D...|], d); + const C: [u64; 7] = [ + 0x3fe0000000000000, + 0xbfc000000000009a, + 0x3fb0000000000202, + 0xbfa3fffffdf5a853, + 0x3f9bfffffb3c75fe, + 0xbf9500dd6aee8501, + 0x3f9080d2ece21348, + ]; + let p = f_polyeval6( + x, + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + f64::from_bits(C[6]), + ) * x; + let r = DoubleDouble::from_exact_add(f64::from_bits(C[0]), p); + let q = DoubleDouble::quick_mult_f64(r, x); + let err = f_fmla( + q.hi, + f64::from_bits(0x3c50000000000000), // 2^-58 + f64::from_bits(0x3bf0000000000000), // 2^-64 + ); + let ub = q.hi + (q.lo + err); + let lb = q.hi + (q.lo - err); + // Ziv's accuracy test + if ub == lb { + return ub; + } + return sqrt1pm1_near_zero_hard(x); + } + // |x| > 0.012 + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let r = DoubleDouble::from_full_exact_add(x, 1.0); + let v_sqrt = r.fast_sqrt(); + let q = DoubleDouble::full_add_f64(v_sqrt, -1.0); + q.to_f64() + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::two_product_compatible; + if !two_product_compatible(x) { + // x is very big, thus adding + 1 is negligible in ulp terms + let r = x + 1.; + let v_sqrt = r.sqrt(); + DoubleDouble::from_full_exact_sub(v_sqrt, 1.0).to_f64() + } else { + let r = DoubleDouble::from_full_exact_add(x, 1.0); + let v_sqrt = r.fast_sqrt(); + let q = DoubleDouble::full_add_f64(v_sqrt, -1.0); + q.to_f64() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sqrt1pm1() { + assert_eq!(f_sqrt1pm1(15.), 3.0); + assert_eq!(f_sqrt1pm1(24.), 4.0); + assert_eq!(f_sqrt1pm1(8.), 2.0); + assert_eq!(f_sqrt1pm1(-0.75), -0.5); + assert_eq!(f_sqrt1pm1(0.5), 0.22474487139158905); + assert_eq!(f_sqrt1pm1(0.0005233212), 0.00026162637581973774); + assert_eq!(f_sqrt1pm1(-0.0005233212), -0.0002616948420951896); + assert_eq!(f_sqrt1pm1(-0.00000000000000000000005233212), -2.616606e-23); + assert_eq!(f_sqrt1pm1(0.00000000000000000000005233212), 2.616606e-23); + assert_eq!(f_sqrt1pm1(0.), 0.); + assert_eq!(f_sqrt1pm1(-0.), 0.); + assert_eq!(f_sqrt1pm1(f64::INFINITY), f64::INFINITY); + assert!(f_sqrt1pm1(f64::NEG_INFINITY).is_nan()); + assert!(f_sqrt1pm1(f64::NAN).is_nan()); + assert!(f_sqrt1pm1(-1.0001).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrt1pm1f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::polyeval::f_polyeval6; + +/// Computes sqrt(1+x) - 1 +pub fn f_sqrt1pm1f(x: f32) -> f32 { + // filter out exceptional cases + let ix = x.to_bits(); + let ux = ix.wrapping_shl(1); + if ux >= 0xffu32 << 24 || ux <= 0x68000000u32 { + // |x| <= f32::EPSILON, |x| == inf, x == NaN + if ux == 0 { + // |x| == 0 + return 0.; + } + if ux.wrapping_shl(8) == 0 { + // |x| == Inf + return if x.is_sign_negative() { + f32::NAN + } else { + f32::INFINITY + }; + } + + if ux <= 0x68000000u32 { + // |x| <= f32::EPSILON + // Sqrt(1+x) - 1 ~ x/2-x^2/8 + O(x^3) + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(-0.25 * x, 0.25 * x, x * 0.5); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::common::f_fmla; + let dx = x as f64; + return f_fmla(-0.25 * dx, 0.25 * dx, dx * 0.5) as f32; + } + } + + return f32::NAN; // x == NaN + } + if (ix >> 31) != 0 && ux >= 0x7f00_0000 { + // x < 0 and x >= 1 + if ux == 0x7f00_0000u32 { + // x == -1 + return -1.; + } + return f32::NAN; + } + + if ux <= 0x78eb_851eu32 { + // |x| <= 0.015 + + // Polynomial generated by Sollya: + // d = [-0.015, 0.015]; + // sqrt1pm1 = sqrt(x + 1) - 1; + // Q = fpminimax(sqrt1pm1, [|1,2,3,4,5,6|], [|D...|], d); + const C: [u64; 6] = [ + 0x3fe0000000000034, + 0xbfc00000000002ee, + 0x3faffffffc0d541c, + 0xbfa3fffffa546ce5, + 0x3f9c016d2be05c25, + 0xbf95016d1ae9e058, + ]; + let dx = x as f64; + let p = f_polyeval6( + dx, + f64::from_bits(C[0]), + f64::from_bits(C[1]), + f64::from_bits(C[2]), + f64::from_bits(C[3]), + f64::from_bits(C[4]), + f64::from_bits(C[5]), + ) * dx; + return p as f32; + } + + let dx = x as f64; + ((dx + 1.).sqrt() - 1.) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sqrt1pm1f() { + assert_eq!(f_sqrt1pm1f(-0.9), -0.6837722); + assert_eq!(f_sqrt1pm1f(24.), 4.); + assert_eq!(f_sqrt1pm1f(-0.75), -0.5); + assert_eq!(f_sqrt1pm1f(8.), 2.); + assert_eq!(f_sqrt1pm1f(9.), 2.1622777); + assert_eq!(f_sqrt1pm1f(12.31), 2.6482873); + assert_eq!(f_sqrt1pm1f(0.005231), 0.0026120886); + assert_eq!(f_sqrt1pm1f(0.00000000005231), 2.6155e-11); + assert_eq!(f_sqrt1pm1f(-0.00000000005231), -2.6155e-11); + assert_eq!(f_sqrt1pm1f(0.), 0.); + assert_eq!(f_sqrt1pm1f(-0.), 0.); + assert_eq!(f_sqrt1pm1f(f32::INFINITY), f32::INFINITY); + assert!(f_sqrt1pm1f(f32::NEG_INFINITY).is_nan()); + assert!(f_sqrt1pm1f(f32::NAN).is_nan()); + assert!(f_sqrt1pm1f(-1.0001).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrtf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrtf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/square_root/sqrtf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/square_root/sqrtf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/// Computes Square root. +/// Most of CPU have built-in instruction with higher precision, +/// prefer use this only for const contexts. +#[inline] +pub const fn sqrtf(d: f32) -> f32 { + let mut q = 0.5f32; + + let mut d = if d < 0f32 { f32::NAN } else { d }; + + if d < 5.2939559203393770e-23f32 { + d *= 1.8889465931478580e+22f32; + q = 7.2759576141834260e-12f32; + } + + if d > 1.8446744073709552e+19f32 { + d *= 5.4210108624275220e-20f32; + q = 4294967296.0f32; + } + + // http://en.wikipedia.org/wiki/Fast_inverse_square_root + let mut x = f32::from_bits(0x5f375a86 - ((d + 1e-45).to_bits() >> 1)) as f64; + + x = x * (1.5 - 0.5 * (d as f64) * x * x); + x = x * (1.5 - 0.5 * (d as f64) * x * x); + x = x * (1.5 - 0.5 * (d as f64) * x * x) * (d as f64); + + let d2 = ((d as f64) + x * x) * (1. / x); + + if d.is_infinite() { + return f32::INFINITY; + } + (d2 * q as f64) as f32 +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn sqrtf_test() { + assert!( + (sqrtf(4f32) - 2f32).abs() < 1e-6, + "Invalid result {}", + sqrtf(4f32) + ); + assert!( + (sqrtf(9f32) - 3f32).abs() < 1e-6, + "Invalid result {}", + sqrtf(9f32) + ); + assert_eq!(sqrtf(4.), 2.); + assert_eq!(sqrtf(9.), 3.); + assert_eq!(sqrtf(16.), 4.); + assert_eq!(sqrtf(25.), 5.); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,419 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::shared_eval::poly_dd_3; + +pub(crate) static ATAN_CIRCLE: [[u16; 3]; 31] = [ + [419, 81, 0], + [500, 81, 0], + [582, 163, 0], + [745, 163, 0], + [908, 326, 0], + [1234, 326, 0], + [1559, 651, 0], + [2210, 650, 1], + [2860, 1299, 3], + [4156, 1293, 4], + [5444, 2569, 24], + [7989, 2520, 32], + [10476, 4917, 168], + [15224, 4576, 200], + [19601, 8341, 838], + [27105, 6648, 731], + [33036, 10210, 1998], + [41266, 6292, 1117], + [46469, 7926, 2048], + [52375, 4038, 849], + [55587, 4591, 1291], + [58906, 2172, 479], + [60612, 2390, 688], + [62325, 1107, 247], + [63192, 1207, 349], + [64056, 556, 124], + [64491, 605, 175], + [64923, 278, 62], + [65141, 303, 88], + [65358, 139, 31], + [65467, 151, 44], +]; + +pub(crate) static ATAN_REDUCE: [(u64, u64); 129] = [ + (0x0000000000000000, 0x0000000000000000), + (0x3f89224e047e368e, 0x3c1a3ca6c727c59d), + (0x3f992346247a91f0, 0x3bf138b0ef96a186), + (0x3fa2dbaae9a05db0, 0x3c436e7f8a3f5e42), + (0x3fa927278a3b1162, 0xbbfac986efb92662), + (0x3faf7495ea3f3783, 0x3c406ec8011ee816), + (0x3fb2e239ccff3831, 0xbc5858437d431332), + (0x3fb60b9f7597fdec, 0xbc3cebd13eb7c513), + (0x3fb936bb8c5b2da2, 0xbc5840cac0d81db5), + (0x3fbc63ce377fc802, 0x3c5400b0fdaa109e), + (0x3fbf93183a8db9e9, 0x3c40e04e06c86e72), + (0x3fc1626d85a91e70, 0x3c4f7ad829163ca7), + (0x3fc2fcac73a60640, 0xbc52680735ce2cd8), + (0x3fc4986a74cf4e57, 0xbc690559690b42e4), + (0x3fc635c990ce0d36, 0x3c591d29110b41aa), + (0x3fc7d4ec54fb5968, 0xbc4ea90e27182780), + (0x3fc975f5e0553158, 0xbc2dc82ac14e3e1c), + (0x3fcb1909efd8b762, 0xbc573a10fd13daaf), + (0x3fccbe4ceb4b4cf2, 0xbc63a7ffbeabda0b), + (0x3fce65e3f27c9f2a, 0xbc6db6627a24d523), + (0x3fd007fa758626ae, 0xbc645f97dd3099f6), + (0x3fd0de53475f3b3c, 0xbc66293f68741816), + (0x3fd1b6103d3597e9, 0xbc6ab240d40633e9), + (0x3fd28f459ecad74d, 0xbc2de34d14e832e0), + (0x3fd36a08355c63dc, 0x3c6af540d9fb4926), + (0x3fd4466d542bac92, 0x3c6da60fdbc82ac4), + (0x3fd5248ae1701b17, 0xbc792a601170138a), + (0x3fd604775fbb27df, 0xbc67f1fca1d5d15b), + (0x3fd6e649f7d78649, 0xbc64e223ea716c7b), + (0x3fd7ca1a832d0f84, 0x3c7b24c824ac51fc), + (0x3fd8b00196b3d022, 0x3c64314cd132ba43), + (0x3fd998188e816bf0, 0xbc711f1e0817879a), + (0x3fda827999fcef32, 0xbc6c3dea4dbad538), + (0x3fdb6f3fc8c61e5b, 0x3c660d1b780ee3eb), + (0x3fdc5e87185e67b6, 0xbc4ab5edb7dfa545), + (0x3fdd506c82a2c800, 0xbc68e1437048b5bd), + (0x3fde450e0d273e7a, 0xbc706951c97b050f), + (0x3fdf3c8ad985d9ee, 0xbc414af9522ab518), + (0x3fe01b819b5a7cf7, 0xbc7aba0d7d97d1f2), + (0x3fe09a4c59bd0d4d, 0x3c4095bc4ebc2c42), + (0x3fe11ab7190834ec, 0x3c8798826fa27774), + (0x3fe19cd3fe8e405d, 0x3c8008f6258fc98f), + (0x3fe220b5ef047825, 0xbc5462af7ceb7de6), + (0x3fe2a6709a74f289, 0xbc71184dfd78b472), + (0x3fe32e1889047ffd, 0x3c79141876dc40c5), + (0x3fe3b7c3289ed6f3, 0x3c8481c20189726c), + (0x3fe44386db9ce5db, 0x3c82e851bd025441), + (0x3fe4d17b087b265d, 0x3c713ada9b8bc419), + (0x3fe561b82ab7f990, 0xbc805b4c3c4cbee8), + (0x3fe5f457e4f4812e, 0xbc85619249bd96f1), + (0x3fe6897514751db6, 0xbc6b0a0fbcafc671), + (0x3fe7212be621be6d, 0xbc819ff2dc66da45), + (0x3fe7bb99ed2990cf, 0x3c81320449592d92), + (0x3fe858de3b716571, 0xbc81fddcd2f3da8e), + (0x3fe8f9197bf85eeb, 0x3c6d44a42e35cc97), + (0x3fe99c6e0f634394, 0xbc7585a178b4a18d), + (0x3fea43002ae42850, 0x3c6f95a531b3a970), + (0x3feaecf5f9ba35a6, 0xbc396c2d43ca3392), + (0x3feb9a77c18c1af2, 0xbc6a5bed94b05def), + (0x3fec4bb009e77983, 0x3c454509d2bff511), + (0x3fed00cbc7384d2e, 0xbc6b4c867cef300c), + (0x3fedb9fa89953fcf, 0xbc1ddfac663d6bc6), + (0x3fee776eafc91706, 0xbc7a510683ff7cb6), + (0x3fef395d9f0e3c92, 0x3c44fdcd8e4e8710), + (0x3ff0000000000000, 0x0000000000000000), + (0x3ff065c900aaf2d8, 0xbc8deec7fc9042ad), + (0x3ff0ce29d0883c99, 0xbc8395ae45e0657d), + (0x3ff139447e6a86ee, 0x3c8332cf301a97f3), + (0x3ff1a73d55278c4b, 0xbc86cc8c4b78213b), + (0x3ff2183b0c4573ff, 0x3c870a90841da57a), + (0x3ff28c66fdaf8f09, 0xbc6ba39bad450ee0), + (0x3ff303ed61109e20, 0xbc88692946d9f93c), + (0x3ff37efd8d87607e, 0x3c63b711bf765b58), + (0x3ff3fdca42847507, 0x3c7c21387985b081), + (0x3ff48089f8bf42cc, 0xbc87ddb19d3d0efc), + (0x3ff507773c537ead, 0xbc7f5e354cf971f3), + (0x3ff592d11142fa55, 0xbc700f0ad675330d), + (0x3ff622db63c8ecc2, 0xbc82c93f50ab2c0e), + (0x3ff6b7df86265200, 0x3c7bec391adc37d5), + (0x3ff7522cbdd428a8, 0xbc69686ddc9ffcf5), + (0x3ff7f218e25a7461, 0xbc78d16529514246), + (0x3ff89801106cc709, 0xbc8092f51e9c2803), + (0x3ff9444a7462122a, 0xbc807c06755404c4), + (0x3ff9f7632fa9e871, 0x3c802e0d43abc92b), + (0x3ffab1c35d8a74ea, 0x3c5d0184e48af6f7), + (0x3ffb73ee3c3ef16a, 0x3c773be957380bc2), + (0x3ffc3e738086bc0f, 0xbc702b6e26c84462), + (0x3ffd11f0dae40609, 0x3c525c4f3ffa6e1f), + (0x3ffdef13b73c1406, 0xbc5e302db3c6823f), + (0x3ffed69b4153a45d, 0x3c73207830326c0e), + (0x3fffc95abad6cf4a, 0xbc66308cee7927bf), + (0x4000641e192ceab3, 0xbc70147ebf0df4c5), + (0x4000ea21d716fbf7, 0xbc7168533cc41d8b), + (0x40017749711a6679, 0xbc652a0b0333e9c5), + (0x40020c36c6a7f38e, 0x3c68659eece35395), + (0x4002a99f50fd4f4f, 0x3c820fcad18cb36f), + (0x4003504f333f9de6, 0xbc752afdbd5a8c74), + (0x4004012ce2586a17, 0xbc79747a792907d7), + (0x4004bd3d87fe0650, 0x3c790c59393b52c8), + (0x400585aa4e1530fa, 0x3c7af6934f13a3a8), + (0x40065bc6cc825147, 0xbc48534dcab5ad3e), + (0x40074118e4b6a7c8, 0xbc7555aa8bfca9a1), + (0x400837626d70fdb8, 0xbc556b3fee9ca72b), + (0x400940ad30abc792, 0x3c54b3fdd4fdc06c), + (0x400a5f59e90600dd, 0x3c6285d367c55ddc), + (0x400b9633283b6d14, 0xbc48712976f17a16), + (0x400ce885653127e7, 0xbc3abe8ab65d49fc), + (0x400e5a3de972a377, 0x3c5cd9be81ad764b), + (0x400ff01305ecd8dc, 0x3c4742c2922656fa), + (0x4010d7dc7cff4c9e, 0xbc77c842978bee09), + (0x4011d0143e71565f, 0x3c67bc7dea7c3c03), + (0x4012e4ff1626b949, 0x3c4aefbe25b404e9), + (0x40141bfee2424771, 0xbc34bcfaaa95cb2c), + (0x40157be4eaa5e11b, 0x3c50fe741e4ec679), + (0x40170d751908c1b1, 0x3c5fe74a5b0ec709), + (0x4018dc25c117782b, 0x3c50ca1c19f710ef), + (0x401af73f4ca3310f, 0x3c52867b40ba77d6), + (0x401d7398d15e70db, 0x3c60fd4e0d4b1547), + (0x4020372fb36b87e2, 0x3c5c16c9ecc1621d), + (0x402208dbdae055ef, 0x3c56b81a36e75e8c), + (0x40244e6c595afdcc, 0xbc57c22045771848), + (0x4027398c57f3f1ad, 0x3c5970503be105c0), + (0x402b1d03c03d2f7f, 0xbc3f299d010aead2), + (0x403046e9fe60a77e, 0x3c5d2b61deff33ec), + (0x40345affed201b55, 0x3bf0e84d9567203a), + (0x403b267195b1ffae, 0xbbfad44b44b92653), + (0x40445e2455e4aaa7, 0xbc3296d577b5e21d), + (0x40545eed6854ce99, 0x3c02db53886013ca), + (0x0000000000000000, 0x0000000000000000), +]; + +#[cold] +fn atan_refine(x: f64, a: f64) -> f64 { + const CH: [(u64, u64); 3] = [ + (0xbfd5555555555555, 0xbc75555555555555), + (0x3fc999999999999a, 0xbc6999999999bcb8), + (0xbfc2492492492492, 0xbc6249242093c016), + ]; + const CL: [u64; 4] = [ + 0x3fbc71c71c71c71c, + 0xbfb745d1745d1265, + 0x3fb3b13b115bcbc4, + 0xbfb1107c41ad3253, + ]; + let phi = f_fmla(a.abs(), f64::from_bits(0x40545f306dc9c883), 256.5).to_bits(); + let i = ((phi >> (52 - 8)) & 0xff) as i64; + let h: DoubleDouble = if i == 128 { + DoubleDouble::from_quick_recip(-x) + } else { + let ta = f64::copysign(f64::from_bits(ATAN_REDUCE[i as usize].0), x); + let dzt = DoubleDouble::from_exact_mult(x, ta); + let zmta = x - ta; + let v = 1.0 + dzt.hi; + let d = 1.0 - v; + let ev = (d + dzt.hi) - ((d + v) - 1.0) + dzt.lo; + let r = 1.0 / v; + let rl = f_fmla(-ev, r, dd_fmla(r, -v, 1.0)) * r; + DoubleDouble::quick_mult_f64(DoubleDouble::new(rl, r), zmta) + }; + let h2 = DoubleDouble::quick_mult(h, h); + let h3 = DoubleDouble::quick_mult(h, h2); + let h4 = h2.hi * h2.hi; + + let zw0 = f_fmla(h2.hi, f64::from_bits(CL[3]), f64::from_bits(CL[2])); + let zw1 = f_fmla(h2.hi, f64::from_bits(CL[1]), f64::from_bits(CL[0])); + let zfl = f_fmla(h2.hi, zw1, h4 * zw0); + + let mut f = poly_dd_3(h2, CH, zfl); + f = DoubleDouble::quick_mult(h3, f); + let (ah, mut az); + if i == 0 { + ah = h.hi; + az = f; + } else { + let mut df = 0.; + if i < 128 { + df = f64::copysign(1.0, x) * f64::from_bits(ATAN_REDUCE[i as usize].1); + } + let id = f64::copysign(i as f64, x); + ah = f64::from_bits(0x3f8921fb54442d00) * id; + az = DoubleDouble::new( + f64::from_bits(0xb97fc8f8cbb5bf80) * id, + f64::from_bits(0x3c88469898cc5180) * id, + ); + az = DoubleDouble::add(az, DoubleDouble::new(0., df)); + az = DoubleDouble::add(az, h); + az = DoubleDouble::add(az, f); + } + let v0 = DoubleDouble::from_exact_add(ah, az.hi); + let v1 = DoubleDouble::from_exact_add(v0.lo, az.lo); + + v1.hi + v0.hi +} + +/// fma - fma +/// dd_fma - DD fma fallback +/// dyad_fma - mandatory fma fallback +#[inline(always)] +fn atan_gen_impl< + Q: Fn(f64, f64, f64) -> f64, + F: Fn(f64, f64, f64) -> f64, + D: Fn(f64, f64, f64) -> f64, +>( + x: f64, + fma: Q, + dd_fma: F, + dyad_fma: D, +) -> f64 { + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0xbfd555555555552b, + 0x3fc9999999069c20, + 0xbfc248d2c8444ac6, + ]; + let t = x.to_bits(); + let at = t & 0x7fffffffffffffff; // at encodes |x| + let mut i = (at.wrapping_shr(51) as i64).wrapping_sub(2030i64); // -2030 <= i <= 2065 + if at < 0x3f7b21c475e6362au64 { + // |x| < 0x1.b21c475e6362ap-8 + if at == 0 { + return x; + } // atan(+/-0) = +/-0 + const CH2: [u64; 4] = [ + 0xbfd5555555555555, + 0x3fc99999999998c1, + 0xbfc249249176aec0, + 0x3fbc711fd121ae80, + ]; + if at < 0x3e40000000000000u64 { + // |x| < 0x1p-27 + /* underflow when 0 < |x| < 2^-1022 or when |x| = 2^-1022 + and rounding towards zero. */ + return dyad_fma(f64::from_bits(0xbc90000000000000), x, x); + } + let x2 = x * x; + let x3 = x * x2; + let x4 = x2 * x2; + + let w0 = fma(x2, f64::from_bits(CH2[3]), f64::from_bits(CH2[2])); + let w1 = fma(x2, f64::from_bits(CH2[1]), f64::from_bits(CH2[0])); + + let f = x3 * fma(x4, w0, w1); + let ub = fma(f, f64::from_bits(0x3cd2000000000000), f) + x; + let lb = fma(-f, f64::from_bits(0x3cc4000000000000), f) + x; + // Ziv's accuracy test + if ub != lb { + return atan_refine(x, ub); + } + return ub; + } + let h; + let ah; + let mut al; + if at > 0x4062ded8e34a9035u64 { + // |x| > 0x4062ded8e34a9035 + ah = f64::copysign(f64::from_bits(0x3ff921fb54442d18), x); + al = f64::copysign(f64::from_bits(0x3c91a62633145c07), x); + if at >= 0x434d02967c31cdb5u64 { + // |x| >= 1.63312e+16 + if at > (0x7ffu64 << 52) { + return x + x; + } // NaN + return ah + al; + } + h = -1.0 / x; + } else { + // now 0.006624 <= |x| <= 150.964 thus 1<=i<=30 + let u: u64 = t & 0x0007ffffffffffff; + let ut: u64 = u.wrapping_shr(51 - 16); + let ut2: u64 = (ut * ut).wrapping_shr(16); + let lc = ATAN_CIRCLE[i as usize]; + i = (((lc[0] as u64) + .wrapping_shl(16) + .wrapping_add(ut * lc[1] as u64) + .wrapping_sub(ut2 * lc[2] as u64)) + >> (16 + 9)) as i64; + let la = ATAN_REDUCE[i as usize]; + let ta = f64::copysign(1.0, x) * f64::from_bits(la.0); + let id = f64::copysign(1.0, x) * i as f64; + al = dd_fma( + f64::copysign(1.0, x), + f64::from_bits(la.1), + f64::from_bits(0x3c88469898cc5170) * id, + ); + h = (x - ta) / fma(x, ta, 1.0); + ah = f64::from_bits(0x3f8921fb54442d00) * id; + } + let h2 = h * h; + let h4 = h2 * h2; + + let f0 = fma(h2, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let f1 = fma(h2, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let f = fma(h4, f0, f1); + al = dd_fma(h, f, al); + let ub = fma(h, f64::from_bits(0x3ccf800000000000), al) + ah; + let lb = fma(-h, f64::from_bits(0x3ccf800000000000), al) + ah; + // Ziv's accuracy test + if lb != ub { + return atan_refine(x, ub); + } + ub +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atan_fma_impl(x: f64) -> f64 { + atan_gen_impl(x, f64::mul_add, f64::mul_add, f64::mul_add) +} + +/// Computes atan in double precision +/// +/// ULP 0.5 +pub fn f_atan(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atan_gen_impl(x, f_fmla, dd_fmla, dyad_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atan_fma_impl + } else { + fn def_atan(x: f64) -> f64 { + atan_gen_impl(x, f_fmla, dd_fmla, dyad_fmla) + } + def_atan + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn atan_test() { + assert_eq!(f_atan(7.7877585082074305E-308), 7.78775850820743e-308); + assert_eq!(f_atan(0.0), 0.0); + assert_eq!(f_atan(1.0), 0.7853981633974483096156608458198); + assert_eq!(f_atan(35.9), 1.542948374599341097473183563168947); + assert_eq!(f_atan(-35.9), -1.542948374599341097473183563168947); + assert_eq!(f_atan(f64::INFINITY), 1.5707963267948966); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1029 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::{DyadicFloat128, DyadicSign}; +use crate::polyeval::f_polyeval4; +use crate::rounding::CpuRound; + +// atan(i/64) with i = 0..64, generated by Sollya with: +// > for i from 0 to 64 do { +// a = round(atan(i/64), D, RN); +// b = round(atan(i/64) - a, D, RN); +// print("{", b, ",", a, "},"); +// }; +pub(crate) static ATAN_I: [(u64, u64); 65] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbc2220c39d4dff50, 0x3f8fff555bbb729b), + (0xbc35ec431444912c, 0x3f9ffd55bba97625), + (0xbc086ef8f794f105, 0x3fa7fb818430da2a), + (0xbc3c934d86d23f1d, 0x3faff55bb72cfdea), + (0x3c5ac4ce285df847, 0x3fb3f59f0e7c559d), + (0xbc5cfb654c0c3d98, 0x3fb7ee182602f10f), + (0x3c5f7b8f29a05987, 0x3fbbe39ebe6f07c3), + (0xbc4cd37686760c17, 0x3fbfd5ba9aac2f6e), + (0xbc4b485914dacf8c, 0x3fc1e1fafb043727), + (0x3c661a3b0ce9281b, 0x3fc3d6eee8c6626c), + (0xbc5054ab2c010f3d, 0x3fc5c9811e3ec26a), + (0x3c5347b0b4f881ca, 0x3fc7b97b4bce5b02), + (0x3c4cf601e7b4348e, 0x3fc9a6a8e96c8626), + (0x3c217b10d2e0e5ab, 0x3fcb90d7529260a2), + (0x3c6c648d1534597e, 0x3fcd77d5df205736), + (0x3c68ab6e3cf7afbd, 0x3fcf5b75f92c80dd), + (0x3c762e47390cb865, 0x3fd09dc597d86362), + (0x3c630ca4748b1bf9, 0x3fd18bf5a30bf178), + (0xbc7077cdd36dfc81, 0x3fd278372057ef46), + (0xbc6963a544b672d8, 0x3fd362773707ebcc), + (0xbc75d5e43c55b3ba, 0x3fd44aa436c2af0a), + (0xbc62566480884082, 0x3fd530ad9951cd4a), + (0xbc7a725715711f00, 0x3fd614840309cfe2), + (0xbc7c63aae6f6e918, 0x3fd6f61941e4def1), + (0x3c769c885c2b249a, 0x3fd7d5604b63b3f7), + (0x3c7b6d0ba3748fa8, 0x3fd8b24d394a1b25), + (0x3c79e6c988fd0a77, 0x3fd98cd5454d6b18), + (0xbc724dec1b50b7ff, 0x3fda64eec3cc23fd), + (0x3c7ae187b1ca5040, 0x3fdb3a911da65c6c), + (0xbc7cc1ce70934c34, 0x3fdc0db4c94ec9f0), + (0xbc7a2cfa4418f1ad, 0x3fdcde53432c1351), + (0x3c7a2b7f222f65e2, 0x3fddac670561bb4f), + (0x3c70e53dc1bf3435, 0x3fde77eb7f175a34), + (0xbc6a3992dc382a23, 0x3fdf40dd0b541418), + (0xbc8b32c949c9d593, 0x3fe0039c73c1a40c), + (0xbc7d5b495f6349e6, 0x3fe0657e94db30d0), + (0x3c5974fa13b5404f, 0x3fe0c6145b5b43da), + (0xbc52bdaee1c0ee35, 0x3fe1255d9bfbd2a9), + (0x3c8c621cec00c301, 0x3fe1835a88be7c13), + (0xbc5928df287a668f, 0x3fe1e00babdefeb4), + (0x3c6c421c9f38224e, 0x3fe23b71e2cc9e6a), + (0xbc709e73b0c6c087, 0x3fe2958e59308e31), + (0x3c8c5d5e9ff0cf8d, 0x3fe2ee628406cbca), + (0x3c81021137c71102, 0x3fe345f01cce37bb), + (0xbc82304331d8bf46, 0x3fe39c391cd4171a), + (0x3c7ecf8b492644f0, 0x3fe3f13fb89e96f4), + (0xbc7f76d0163f79c8, 0x3fe445065b795b56), + (0x3c72419a87f2a458, 0x3fe4978fa3269ee1), + (0x3c84a33dbeb3796c, 0x3fe4e8de5bb6ec04), + (0xbc81bb74abda520c, 0x3fe538f57b89061f), + (0xbc75e5c9d8c5a950, 0x3fe587d81f732fbb), + (0x3c60028e4bc5e7ca, 0x3fe5d58987169b18), + (0xbc62b785350ee8c1, 0x3fe6220d115d7b8e), + (0xbc76ea6febe8bbba, 0x3fe66d663923e087), + (0xbc8a80386188c50e, 0x3fe6b798920b3d99), + (0xbc78c34d25aadef6, 0x3fe700a7c5784634), + (0x3c47b2a6165884a1, 0x3fe748978fba8e0f), + (0x3c8406a089803740, 0x3fe78f6bbd5d315e), + (0x3c8560821e2f3aa9, 0x3fe7d528289fa093), + (0xbc7bf76229d3b917, 0x3fe819d0b7158a4d), + (0x3c66b66e7fc8b8c3, 0x3fe85d69576cc2c5), + (0xbc855b9a5e177a1b, 0x3fe89ff5ff57f1f8), + (0xbc7ec182ab042f61, 0x3fe8e17aa99cc05e), + (0x3c81a62633145c07, 0x3fe921fb54442d18), +]; + +// Sage math: +// print("pub(crate) static ATAN_RATIONAL_128: [DyadicFloat128; 65] = [") +// for i in range(65): +// x = D3(i)/D3(64) +// v = atan(x) +// print_dyadic(v) +// +// print("];") +pub(crate) static ATAN_RATIONAL_128: [DyadicFloat128; 65] = [ + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0x0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -134, + mantissa: 0xfffaaadd_db94d5bb_e78c5640_15f76048_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -133, + mantissa: 0xffeaaddd_4bb12542_779d776d_da8c6214_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xbfdc0c21_86d14fcf_220e10d6_1df56ec7_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -132, + mantissa: 0xffaaddb9_67ef4e36_cb2792dc_0e2e0d51_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0x9facf873_e2aceb58_99c50bbf_08e6cdf6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xbf70c130_17887460_93567e78_4cf83676_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xdf1cf5f3_783e1bef_71e5340b_30e5d9ef_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xfeadd4d5_617b6e32_c897989f_3e888ef8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x8f0fd7d8_21b93725_bd375929_83a0af9a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0x9eb77746_331362c3_47619d25_0360fe85_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xae4c08f1_f6134efa_b54d3fef_0c2de994_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xbdcbda5e_72d81134_7b0b4f88_1c9c7488_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcd35474b_643130e7_b00f3da1_a46eeb3b_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xdc86ba94_93051022_f621a5c1_cb552f03_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xebbeaef9_02b9b38c_91a2a68b_2fbd78e8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xfadbafc9_6406eb15_6dc79ef5_f7a217e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x84ee2cbe_c31b12c5_c8e72197_0cabd3a3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x8c5fad18_5f8bc130_ca4748b1_bf88298d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x93c1b902_bf7a2df1_06459240_6fe1447a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0x9b13b9b8_3f5e5e69_c5abb498_d27af328_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa25521b6_15784d45_43787549_88b8d9e3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xa9856cca_8e6a4eda_99b7f77b_f7d9e8c1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb0a42018_4e7f0cb1_b51d51dc_200a0fc3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xb7b0ca0f_26f78473_8aa32122_dcfe4483_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xbeab025b_1d9fbad3_910b8564_93411026_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xc59269ca_50d92b6d_a1746e91_f50a28de_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xcc66aa2a_6b58c33c_d9311fa1_4ed9b7c4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd327761e_611fe5b6_427c95e9_001e7136_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xd9d488ed_32e3635c_30f6394a_0806345d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe06da64a_764f7c67_c631ed96_798cb804_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xe6f29a19_609a84ba_60b77ce1_ca6dc2c8_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xed63382b_0dda7b45_6fe445ec_bc3a8d03_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xf3bf5bf8_bad1a21c_a7b837e6_86adf3fa_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -129, + mantissa: 0xfa06e85a_a0a0be5c_66d23c7d_5dc8ecc2_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x801ce39e_0d205c99_a6d6c6c5_4d938596_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x832bf4a6_d9867e2a_4b6a09cb_61a515c1_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8630a2da_da1ed065_d3e84ed5_013ca37e_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x892aecdf_de9547b5_094478fc_472b4afc_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8c1ad445_f3e09b8c_439d8018_60205921_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x8f005d5e_f7f59f9b_5c835e16_65c43748_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x91db8f16_64f350e2_10e4f9c1_126e0220_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x94ac72c9_847186f6_18c4f393_f78a32f9_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x97731420_365e538b_abd3fe19_f1aeb6b3_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9a2f80e6_71bdda20_4226f8e2_204ff3bd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9ce1c8e6_a0b8cdb9_f799c4e8_174cf11c_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0x9f89fdc4_f4b7a1ec_f8b49264_4f0701e0_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa22832db_cadaae08_92fe9c08_637af0e6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa4bc7d19_34f70924_19a87f2a_457dac9f_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa746f2dd_b7602294_67b7d66f_2d74e019_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xa9c7abdc_4830f5c8_916a84b5_be7933f6_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xac3ec0fb_997dd6a1_a36273a5_6afa8ef4_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xaeac4c38_b4d8c080_14725e2f_3e52070a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb110688a_ebdc6f6a_43d65788_b9f6a7b5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb36b31c9_1f043691_59014174_4462f93a_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb5bcc490_59ecc4af_f8f3cee7_5e3907d5_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xb8053e2b_c2319e73_cb2da552_10a4443d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xba44bc7d_d470782f_654c2cb1_0942e386_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbc7b5dea_e98af280_d4113006_e80fb290_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xbea94144_fd049aac_1043c5e7_55282e7d_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc0ce85b8_ac526640_89dd62c4_6e92fa25_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc2eb4abb_661628b5_b373fe45_c61bb9fb_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc4ffaffa_bf8fbd54_8cb43d10_bc9e0221_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc70bd54c_e602ee13_e7d54fbd_09f2be38_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -128, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }, +]; + +// Approximate atan(x) for |x| <= 2^-7. +// Using degree-9 Taylor polynomial: +// P = x - x^3/3 + x^5/5 -x^7/7 + x^9/9; +// Then the absolute error is bounded by: +// |atan(x) - P(x)| < |x|^11/11 < 2^(-7*11) / 11 < 2^-80. +// And the relative error is bounded by: +// |(atan(x) - P(x))/atan(x)| < |x|^10 / 10 < 2^-73. +// For x = x_hi + x_lo, fully expand the polynomial and drop any terms less than +// ulp(x_hi^3 / 3) gives us: +// P(x) ~ x_hi - x_hi^3/3 + x_hi^5/5 - x_hi^7/7 + x_hi^9/9 + +// + x_lo * (1 - x_hi^2 + x_hi^4) +// Since p.lo is ~ x^3/3, the relative error from rounding is bounded by: +// |(atan(x) - P(x))/atan(x)| < ulp(x^2) <= 2^(-14-52) = 2^-66. +#[inline] +pub(crate) fn atan_eval(x: DoubleDouble) -> DoubleDouble { + let p_hi = x.hi; + let x_hi_sq = x.hi * x.hi; + // c0 ~ x_hi^2 * 1/5 - 1/3 + let c0 = f_fmla( + x_hi_sq, + f64::from_bits(0x3fc999999999999a), + f64::from_bits(0xbfd5555555555555), + ); + // c1 ~ x_hi^2 * 1/9 - 1/7 + let c1 = f_fmla( + x_hi_sq, + f64::from_bits(0x3fbc71c71c71c71c), + f64::from_bits(0xbfc2492492492492), + ); + // x_hi^3 + let x_hi_3 = x_hi_sq * x.hi; + // x_hi^4 + let x_hi_4 = x_hi_sq * x_hi_sq; + // d0 ~ 1/3 - x_hi^2 / 5 + x_hi^4 / 7 - x_hi^6 / 9 + let d0 = f_fmla(x_hi_4, c1, c0); + // x_lo - x_lo * x_hi^2 + x_lo * x_hi^4 + let d1 = f_fmla(x_hi_4 - x_hi_sq, x.lo, x.lo); + // p.lo ~ -x_hi^3/3 + x_hi^5/5 - x_hi^7/7 + x_hi^9/9 + + // + x_lo * (1 - x_hi^2 + x_hi^4) + let p_lo = f_fmla(x_hi_3, d0, d1); + DoubleDouble::new(p_lo, p_hi) +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn atan_eval_fma(x: DoubleDouble) -> DoubleDouble { + let p_hi = x.hi; + let x_hi_sq = x.hi * x.hi; + // c0 ~ x_hi^2 * 1/5 - 1/3 + let c0 = f64::mul_add( + x_hi_sq, + f64::from_bits(0x3fc999999999999a), + f64::from_bits(0xbfd5555555555555), + ); + // c1 ~ x_hi^2 * 1/9 - 1/7 + let c1 = f64::mul_add( + x_hi_sq, + f64::from_bits(0x3fbc71c71c71c71c), + f64::from_bits(0xbfc2492492492492), + ); + // x_hi^3 + let x_hi_3 = x_hi_sq * x.hi; + // x_hi^4 + let x_hi_4 = x_hi_sq * x_hi_sq; + // d0 ~ 1/3 - x_hi^2 / 5 + x_hi^4 / 7 - x_hi^6 / 9 + let d0 = f64::mul_add(x_hi_4, c1, c0); + // x_lo - x_lo * x_hi^2 + x_lo * x_hi^4 + let d1 = f64::mul_add(x_hi_4 - x_hi_sq, x.lo, x.lo); + // p.lo ~ -x_hi^3/3 + x_hi^5/5 - x_hi^7/7 + x_hi^9/9 + + // + x_lo * (1 - x_hi^2 + x_hi^4) + let p_lo = f64::mul_add(x_hi_3, d0, d1); + DoubleDouble::new(p_lo, p_hi) +} + +#[inline] +fn atan_eval_hard(x: DyadicFloat128) -> DyadicFloat128 { + // let x_hi_sq = x * x; + // c0 ~ x_hi^2 * 1/5 - 1/3 + const C: [DyadicFloat128; 4] = [ + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -129, + mantissa: 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaab_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -130, + mantissa: 0xcccccccc_cccccccc_cccccccc_cccccccd_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -130, + mantissa: 0x92492492_49249249_24924924_92492492_u128, + }, + DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -131, + mantissa: 0xe38e38e3_8e38e38e_38e38e38_e38e38e4_u128, + }, + ]; + let dx2 = x * x; + // Taylor polynomial + // P = x - x^3/3 + x^5/5 -x^7/7 + x^9/9; + let p = f_polyeval4(dx2, C[0], C[1], C[2], C[3]); + x + dx2 * x * p +} + +#[cold] +#[inline(never)] +pub(crate) fn atan2_hard(y: f64, x: f64) -> DyadicFloat128 { + /* + Sage math: + from sage.all import * + + def format_dyadic_hex(value): + l = hex(value)[2:] + n = 8 + x = [l[i:i + n] for i in range(0, len(l), n)] + return "0x" + "_".join(x) + "_u128" + + def print_dyadic(value): + (s, m, e) = RealField(128)(value).sign_mantissa_exponent(); + print("DyadicFloat128 {") + print(f" sign: DyadicSign::{'Pos' if s >= 0 else 'Neg'},") + print(f" exponent: {e},") + print(f" mantissa: {format_dyadic_hex(m)},") + print("},") + + D3 = RealField(157) + + print("Minus Pi") + print_dyadic(-D3.pi()) + + print("\nPI over 2") + print_dyadic(D3.pi() / 2) + + print("\nMinus PI over 2") + print_dyadic(-D3.pi() / 2) + */ + static ZERO: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: 0, + mantissa: 0_u128, + }; + static MINUS_PI: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -126, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + static PI_OVER_2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Pos, + exponent: -127, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + static MPI_OVER_2: DyadicFloat128 = DyadicFloat128 { + sign: DyadicSign::Neg, + exponent: -127, + mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128, + }; + static CONST_ADJ: [[[DyadicFloat128; 2]; 2]; 2] = [ + [[ZERO, MPI_OVER_2], [ZERO, MPI_OVER_2]], + [[MINUS_PI, PI_OVER_2], [MINUS_PI, PI_OVER_2]], + ]; + + let x_sign = x.is_sign_negative() as usize; + let y_sign = y.is_sign_negative() as usize; + let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff; + let x_abs = x_bits; + let y_abs = y_bits; + let recip = x_abs < y_abs; + + let min_abs = if recip { x_abs } else { y_abs }; + let max_abs = if !recip { x_abs } else { y_abs }; + let min_exp = min_abs.wrapping_shr(52); + let max_exp = max_abs.wrapping_shr(52); + + let mut num = f64::from_bits(min_abs); + let mut den = f64::from_bits(max_abs); + + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // by some large enough power of 2 to normalize denormal inputs. + if scale_up { + num *= f64::from_bits(0x43f0000000000000); + if !scale_down { + den *= f64::from_bits(0x43f0000000000000) + } + } else if scale_down { + den *= f64::from_bits(0x3bf0000000000000); + if !scale_up { + num *= f64::from_bits(0x3bf0000000000000); + } + } + } + + static IS_NEG: [DyadicSign; 2] = [DyadicSign::Pos, DyadicSign::Neg]; + + let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize]; + let const_term = CONST_ADJ[x_sign][y_sign][recip as usize]; + + let num = DyadicFloat128::new_from_f64(num); + let den = DyadicFloat128::new_from_f64(den); + + let den_recip0 = den.reciprocal(); + + let mut k_product = num * den_recip0; + k_product.exponent += 6; + + let mut k = k_product.round_to_nearest_f64(); + let idx = k as u64; + // k = idx / 64 + k *= f64::from_bits(0x3f90000000000000); + + // Range reduction: + // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64))) + // = atan((n - d * k/64)) / (d + n * k/64)) + let k_rational128 = DyadicFloat128::new_from_f64(k); + let num_k = num * k_rational128; + let den_k = den * k_rational128; + + // num_dd = n - d * k + let num_rational128 = num - den_k; + // den_dd = d + n * k + let den_rational128 = den + num_k; + + // q = (n - d * k) / (d + n * k) + let den_rational128_recip = den_rational128.reciprocal(); + let q = num_rational128 * den_rational128_recip; + + let p = atan_eval_hard(q); + + let vl = ATAN_RATIONAL_128[idx as usize]; + let mut r = p + vl + const_term; + r.sign = r.sign.mult(final_sign); + + r +} + +static IS_NEG: [f64; 2] = [1.0, -1.0]; +const ZERO: DoubleDouble = DoubleDouble::new(0.0, 0.0); +const MZERO: DoubleDouble = DoubleDouble::new(-0.0, -0.0); +const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), +); +const MPI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbca1a62633145c07), + f64::from_bits(0xc00921fb54442d18), +); +const PI_OVER_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), +); +const MPI_OVER_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc91a62633145c07), + f64::from_bits(0xbff921fb54442d18), +); +const PI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c81a62633145c07), + f64::from_bits(0x3fe921fb54442d18), +); +const THREE_PI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c9a79394c9e8a0a), + f64::from_bits(0x4002d97c7f3321d2), +); + +// Adjustment for constant term: +// CONST_ADJ[x_sign][y_sign][recip] +static CONST_ADJ: [[[DoubleDouble; 2]; 2]; 2] = [ + [[ZERO, MPI_OVER_2], [MZERO, MPI_OVER_2]], + [[MPI, PI_OVER_2], [MPI, PI_OVER_2]], +]; + +// Exceptional cases: +// EXCEPT[y_except][x_except][x_is_neg] +// with x_except & y_except: +// 0: zero +// 1: finite, non-zero +// 2: infinity +static EXCEPTS: [[[DoubleDouble; 2]; 3]; 3] = [ + [[ZERO, PI], [ZERO, PI], [ZERO, PI]], + [[PI_OVER_2, PI_OVER_2], [ZERO, ZERO], [ZERO, PI]], + [ + [PI_OVER_2, PI_OVER_2], + [PI_OVER_2, PI_OVER_2], + [PI_OVER_4, THREE_PI_OVER_4], + ], +]; + +#[inline(always)] +fn atan2_gen_fma(y: f64, x: f64) -> f64 { + let x_sign = x.is_sign_negative() as usize; + let y_sign = y.is_sign_negative() as usize; + let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff; + let x_abs = x_bits; + let y_abs = y_bits; + let recip = x_abs < y_abs; + let mut min_abs = if recip { x_abs } else { y_abs }; + let mut max_abs = if !recip { x_abs } else { y_abs }; + let mut min_exp = min_abs.wrapping_shr(52); + let mut max_exp = max_abs.wrapping_shr(52); + + let mut num = f64::from_bits(min_abs); + let mut den = f64::from_bits(max_abs); + + // Check for exceptional cases, whether inputs are 0, inf, nan, or close to + // overflow, or close to underflow. + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + let x_except = if x == 0.0 { + 0 + } else if x.is_infinite() { + 2 + } else { + 1 + }; + let y_except = if y == 0.0 { + 0 + } else if y.is_infinite() { + 2 + } else { + 1 + }; + + if (x_except != 1) || (y_except != 1) { + let r = EXCEPTS[y_except][x_except][x_sign]; + return f_fmla(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo); + } + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // by some large enough power of 2 to normalize denormal inputs. + // if scale_up || scale_down { + // return atan2_hard(y, x).fast_as_f64(); + // } + if scale_up { + num *= f64::from_bits(0x43f0000000000000); + if !scale_down { + den *= f64::from_bits(0x43f0000000000000); + } + } else if scale_down { + den *= f64::from_bits(0x3bf0000000000000); + if !scale_up { + num *= f64::from_bits(0x3bf0000000000000); + } + } + + min_abs = num.to_bits(); + max_abs = den.to_bits(); + min_exp = min_abs.wrapping_shr(52); + max_exp = max_abs.wrapping_shr(52); + } + let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize]; + let const_term = CONST_ADJ[x_sign][y_sign][recip as usize]; + let exp_diff = max_exp - min_exp; + // We have the following bound for normalized n and d: + // 2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1). + if exp_diff > 54 { + return f_fmla( + final_sign, + const_term.hi, + final_sign * (const_term.lo + num / den), + ); + } + + let mut k = (64.0 * num / den).cpu_round(); + let idx = k as u64; + // k = idx / 64 + k *= f64::from_bits(0x3f90000000000000); + + // Range reduction: + // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64))) + // = atan((n - d * k/64)) / (d + n * k/64)) + let num_k = DoubleDouble::from_exact_mult(num, k); + let den_k = DoubleDouble::from_exact_mult(den, k); + + // num_dd = n - d * k + let num_dd = DoubleDouble::from_exact_add(num - den_k.hi, -den_k.lo); + // den_dd = d + n * k + let mut den_dd = DoubleDouble::from_exact_add(den, num_k.hi); + den_dd.lo += num_k.lo; + + // q = (n - d * k) / (d + n * k) + let q = DoubleDouble::div(num_dd, den_dd); + // p ~ atan(q) + let p = atan_eval(q); + + let vl = ATAN_I[idx as usize]; + let vlo = DoubleDouble::from_bit_pair(vl); + let mut r = DoubleDouble::add(const_term, DoubleDouble::add(vlo, p)); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3bd0000000000000), + f64::from_bits(0x3c00000000000000), + ); + + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + + if ub == lb { + r.hi *= final_sign; + r.lo *= final_sign; + + return r.to_f64(); + } + atan2_hard(y, x).fast_as_f64() +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atan2_fma_impl(y: f64, x: f64) -> f64 { + let x_sign = x.is_sign_negative() as usize; + let y_sign = y.is_sign_negative() as usize; + let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff; + let x_abs = x_bits; + let y_abs = y_bits; + let recip = x_abs < y_abs; + let mut min_abs = if recip { x_abs } else { y_abs }; + let mut max_abs = if !recip { x_abs } else { y_abs }; + let mut min_exp = min_abs.wrapping_shr(52); + let mut max_exp = max_abs.wrapping_shr(52); + + let mut num = f64::from_bits(min_abs); + let mut den = f64::from_bits(max_abs); + + // Check for exceptional cases, whether inputs are 0, inf, nan, or close to + // overflow, or close to underflow. + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + let x_except = if x == 0.0 { + 0 + } else if x.is_infinite() { + 2 + } else { + 1 + }; + let y_except = if y == 0.0 { + 0 + } else if y.is_infinite() { + 2 + } else { + 1 + }; + + if (x_except != 1) || (y_except != 1) { + let r = EXCEPTS[y_except][x_except][x_sign]; + return f64::mul_add(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo); + } + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // by some large enough power of 2 to normalize denormal inputs. + // if scale_up || scale_down { + // return atan2_hard(y, x).fast_as_f64(); + // } + if scale_up { + num *= f64::from_bits(0x43f0000000000000); + if !scale_down { + den *= f64::from_bits(0x43f0000000000000); + } + } else if scale_down { + den *= f64::from_bits(0x3bf0000000000000); + if !scale_up { + num *= f64::from_bits(0x3bf0000000000000); + } + } + + min_abs = num.to_bits(); + max_abs = den.to_bits(); + min_exp = min_abs.wrapping_shr(52); + max_exp = max_abs.wrapping_shr(52); + } + let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize]; + let const_term = CONST_ADJ[x_sign][y_sign][recip as usize]; + let exp_diff = max_exp - min_exp; + // We have the following bound for normalized n and d: + // 2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1). + if exp_diff > 54 { + return f64::mul_add( + final_sign, + const_term.hi, + final_sign * (const_term.lo + num / den), + ); + } + + let mut k = (64.0 * num / den).round(); + let idx = k as u64; + // k = idx / 64 + k *= f64::from_bits(0x3f90000000000000); + + // Range reduction: + // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64))) + // = atan((n - d * k/64)) / (d + n * k/64)) + let num_k = DoubleDouble::from_exact_mult_fma(num, k); + let den_k = DoubleDouble::from_exact_mult_fma(den, k); + + // num_dd = n - d * k + let num_dd = DoubleDouble::from_exact_add(num - den_k.hi, -den_k.lo); + // den_dd = d + n * k + let mut den_dd = DoubleDouble::from_exact_add(den, num_k.hi); + den_dd.lo += num_k.lo; + + // q = (n - d * k) / (d + n * k) + let q = DoubleDouble::div_fma(num_dd, den_dd); + // p ~ atan(q) + let p = atan_eval_fma(q); + + let vl = ATAN_I[idx as usize]; + let vlo = DoubleDouble::from_bit_pair(vl); + let mut r = DoubleDouble::add(const_term, DoubleDouble::add(vlo, p)); + + let err = f64::mul_add( + p.hi, + f64::from_bits(0x3bd0000000000000), + f64::from_bits(0x3c00000000000000), + ); + + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + + if ub == lb { + r.hi *= final_sign; + r.lo *= final_sign; + + return r.to_f64(); + } + atan2_hard(y, x).fast_as_f64() +} + +/// Computes atan(x) +/// +/// Max found ULP 0.5 +pub fn f_atan2(y: f64, x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atan2_gen_fma(y, x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atan2_fma_impl + } else { + fn def_atan2pi(y: f64, x: f64) -> f64 { + atan2_gen_fma(y, x) + } + def_atan2pi + } + }); + unsafe { q(y, x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_atan2() { + assert_eq!( + f_atan2(0.05474853958030223, 0.9999995380640253), + 0.05469396182367716 + ); + assert_eq!(f_atan2(-5., 2.), -1.1902899496825317); + assert_eq!(f_atan2(2., -5.), 2.761086276477428); + assert_eq!( + f_atan2(1.220342145227879E-321, 6.9806238698201653E-309), + 0.00000000000017481849301519772 + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,323 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::shared_eval::poly_dekker_generic; + +static ATAN2F_TABLE: [(u64, u64); 32] = [ + (0x3ff0000000000000, 0xba88c1dac5492248), + (0xbfd5555555555555, 0xbc755553bf3a2abe), + (0x3fc999999999999a, 0xbc699deed1ec9071), + (0xbfc2492492492492, 0xbc5fd99c8d18269a), + (0x3fbc71c71c71c717, 0xbc2651eee4c4d9d0), + (0xbfb745d1745d1649, 0xbc5632683d6c44a6), + (0x3fb3b13b13b11c63, 0x3c5bf69c1f8af41d), + (0xbfb11111110e6338, 0x3c23c3e431e8bb68), + (0x3fae1e1e1dc45c4a, 0xbc4be2db05c77bbf), + (0xbfaaf286b8164b4f, 0x3c2a4673491f0942), + (0x3fa86185e9ad4846, 0x3c4e12e32d79fcee), + (0xbfa642c6d5161fae, 0x3c43ce76c1ca03f0), + (0x3fa47ad6f277e5bf, 0xbc3abd8d85bdb714), + (0xbfa2f64a2ee8896d, 0x3c2ef87d4b615323), + (0x3fa1a6a2b31741b5, 0x3c1a5d9d973547ee), + (0xbfa07fbdad65e0a6, 0xbc265ac07f5d35f4), + (0x3f9ee9932a9a5f8b, 0x3c2f8b9623f6f55a), + (0xbf9ce8b5b9584dc6, 0x3c2fe5af96e8ea2d), + (0x3f9ac9cb288087b7, 0xbc3450cdfceaf5ca), + (0xbf984b025351f3e6, 0x3c2579561b0d73da), + (0x3f952f5b8ecdd52b, 0x3c3036bd2c6fba47), + (0xbf9163a8c44909dc, 0x3c318f735ffb9f16), + (0x3f8a400dce3eea6f, 0xbc2c90569c0c1b5c), + (0xbf81caa78ae6db3a, 0xbc24c60f8161ea09), + (0x3f752672453c0731, 0x3c1834efb598c338), + (0xbf65850c5be137cf, 0xbc0445fc150ca7f5), + (0x3f523eb98d22e1ca, 0xbbf388fbaf1d7830), + (0xbf38f4e974a40741, 0x3bd271198a97da34), + (0x3f1a5cf2e9cf76e5, 0xbbb887eb4a63b665), + (0xbef420c270719e32, 0x3b8efd595b27888b), + (0x3ec3ba2d69b51677, 0xbb64fb06829cdfc7), + (0xbe829b7e6f676385, 0xbb2a783b6de718fb), +]; + +const M: [f64; 2] = [0., 1.]; +const PI: f64 = f64::from_bits(0x400921fb54442d18); +const PI2: f64 = f64::from_bits(0x3ff921fb54442d18); +const PI2L: f64 = f64::from_bits(0x3c91a62633145c07); +static OFF: [f64; 8] = [0.0, PI2, PI, PI2, -0.0, -PI2, -PI, -PI2]; +static OFFL: [f64; 8] = [0.0, PI2L, 2. * PI2L, PI2L, -0.0, -PI2L, -2. * PI2L, -PI2L]; +static SGN: [f64; 2] = [1., -1.]; + +#[cold] +fn atan2f_tiny(y: f32, x: f32) -> f32 { + let dy = y as f64; + let dx = x as f64; + let z = dy / dx; + let mut e = f_fmla(-z, x as f64, y as f64); + /* z * x + e = y thus y/x = z + e/x */ + const C: f64 = f64::from_bits(0xbfd5555555555555); /* -1/3 rounded to nearest */ + let zz = z * z; + let cz = C * z; + e = e / x as f64 + cz * zz; + let mut t = z.to_bits(); + if (t & 0xfffffffu64) == 0 { + /* boundary case */ + /* If z and e are of same sign (resp. of different signs), we increase + (resp. decrease) the significand of t by 1 to avoid a double-rounding + issue when rounding t.f to binary32. */ + if z * e > 0. { + t = t.wrapping_add(1); + } else { + t = t.wrapping_sub(1); + } + } + f64::from_bits(t) as f32 +} + +#[allow(clippy::too_many_arguments)] +#[cold] +fn atan2f_refine(ay: u32, ax: u32, y: f32, x: f32, zy: f64, zx: f64, gt: usize, i: u32) -> f32 { + const PI: f64 = f64::from_bits(0x400921fb54442d18); + const PI2: f64 = f64::from_bits(0x3ff921fb54442d18); + const PI2L: f64 = f64::from_bits(0x3c91a62633145c07); + static OFF: [f64; 8] = [0.0, PI2, PI, PI2, -0.0, -PI2, -PI, -PI2]; + static OFFL: [f64; 8] = [0.0, PI2L, 2. * PI2L, PI2L, -0.0, -PI2L, -2. * PI2L, -PI2L]; + static SGN: [f64; 2] = [1., -1.]; + /* check tiny y/x */ + if ay < ax && ((ax - ay) >> 23 >= 25) { + return atan2f_tiny(y, x); + } + let mut zh; + let mut zl; + if gt == 0 { + zh = zy / zx; + zl = f_fmla(zh, -zx, zy) / zx; + } else { + zh = zx / zy; + zl = f_fmla(zh, -zy, zx) / zy; + } + let z2 = DoubleDouble::quick_mult(DoubleDouble::new(zl, zh), DoubleDouble::new(zl, zh)); + let mut p = poly_dekker_generic(z2, ATAN2F_TABLE); + zh *= SGN[gt]; + zl *= SGN[gt]; + p = DoubleDouble::quick_mult(DoubleDouble::new(zl, zh), p); + let sh = p.hi + OFF[i as usize]; + let sl = ((OFF[i as usize] - sh) + p.hi) + p.lo + OFFL[i as usize]; + let rf = sh as f32; + let th = rf as f64; + let dh = sh - th; + let mut tm: f64 = dh + sl; + let mut tth = th.to_bits(); + if th + th * f64::from_bits(0x3c30000000000000) == th - th * f64::from_bits(0x3c30000000000000) + { + tth &= 0x7ffu64 << 52; + tth = tth.wrapping_sub(24 << 52); + if tm.abs() > f64::from_bits(tth) { + tm *= 1.25; + } else { + tm *= 0.75; + } + } + let r = th + tm; + r as f32 +} + +#[inline(always)] +fn atan2f_gen_impl f64>(y: f32, x: f32, fma: Q) -> f32 { + let tx = x.to_bits(); + let ty = y.to_bits(); + let ux = tx; + let uy = ty; + let ax = ux & 0x7fffffff; + let ay = uy & 0x7fffffff; + if ay >= (0xff << 23) || ax >= (0xff << 23) { + // x or y is nan or inf + /* we use x+y below so that the invalid exception is set + for (x,y) = (qnan,snan) or (snan,qnan) */ + if ay > (0xff << 23) { + return x + y; + } // case y nan + if ax > (0xff << 23) { + return x + y; + } // case x nan + let yinf = ay == (0xff << 23); + let xinf = ax == (0xff << 23); + if yinf & xinf { + return if (ux >> 31) != 0 { + (f64::from_bits(0x4002d97c7f3321d2) * SGN[(uy >> 31) as usize]) as f32 // +/-3pi/4 + } else { + (f64::from_bits(0x3fe921fb54442d18) * SGN[(uy >> 31) as usize]) as f32 // +/-pi/4 + }; + } + if xinf { + return if (ux >> 31) != 0 { + (PI * SGN[(uy >> 31) as usize]) as f32 + } else { + (0.0 * SGN[(uy >> 31) as usize]) as f32 + }; + } + if yinf { + return (PI2 * SGN[(uy >> 31) as usize]) as f32; + } + } + if ay == 0 { + if ax == 0 { + let i = (uy >> 31) + .wrapping_mul(4) + .wrapping_add((ux >> 31).wrapping_mul(2)); + return if (ux >> 31) != 0 { + (OFF[i as usize] + OFFL[i as usize]) as f32 + } else { + OFF[i as usize] as f32 + }; + } + if (ux >> 31) == 0 { + return (0.0 * SGN[(uy >> 31) as usize]) as f32; + } + } + let gt = (ay > ax) as usize; + let i = (uy >> 31) + .wrapping_mul(4) + .wrapping_add((ux >> 31).wrapping_mul(2)) + .wrapping_add(gt as u32); + + let zx = x as f64; + let zy = y as f64; + let mut z = fma(M[gt], zx, M[1usize.wrapping_sub(gt)] * zy) + / fma(M[gt], zy, M[1usize.wrapping_sub(gt)] * zx); + // z = x/y if |y| > |x|, and z = y/x otherwise + let mut r; + + let d = ax as i32 - ay as i32; + if d < (27 << 23) && d > (-(27 << 23)) { + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + /* z2 cannot underflow, since for |y|=0x1p-149 and |x|=0x1.fffffep+127 + we get |z| > 2^-277 thus z2 > 2^-554, but z4 and z8 might underflow, + which might give spurious underflow exceptions. */ + + const CN: [u64; 7] = [ + 0x3ff0000000000000, + 0x40040e0698f94c35, + 0x400248c5da347f0d, + 0x3fed873386572976, + 0x3fc46fa40b20f1d0, + 0x3f833f5e041eed0f, + 0x3f1546bbf28667c5, + ]; + const CD: [u64; 7] = [ + 0x3ff0000000000000, + 0x4006b8b143a3f6da, + 0x4008421201d18ed5, + 0x3ff8221d086914eb, + 0x3fd670657e3a07ba, + 0x3fa0f4951fd1e72d, + 0x3f4b3874b8798286, + ]; + + let mut cn0 = fma(z2, f64::from_bits(CN[1]), f64::from_bits(CN[0])); + let cn2 = fma(z2, f64::from_bits(CN[3]), f64::from_bits(CN[2])); + let mut cn4 = fma(z2, f64::from_bits(CN[5]), f64::from_bits(CN[4])); + let cn6 = f64::from_bits(CN[6]); + cn0 = fma(z4, cn2, cn0); + cn4 = fma(z4, cn6, cn4); + cn0 = fma(z8, cn4, cn0); + let mut cd0 = fma(z2, f64::from_bits(CD[1]), f64::from_bits(CD[0])); + let cd2 = fma(z2, f64::from_bits(CD[3]), f64::from_bits(CD[2])); + let mut cd4 = fma(z2, f64::from_bits(CD[5]), f64::from_bits(CD[4])); + let cd6 = f64::from_bits(CD[6]); + cd0 = fma(z4, cd2, cd0); + cd4 = fma(z4, cd6, cd4); + cd0 = fma(z8, cd4, cd0); + r = cn0 / cd0; + } else { + r = 1.; + } + z *= SGN[gt]; + r = fma(z, r, OFF[i as usize]); + let res = r.to_bits(); + if ((res.wrapping_add(8)) & 0xfffffff) <= 16 { + return atan2f_refine(ay, ax, y, x, zy, zx, gt, i); + } + + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atan2f_fma_impl(y: f32, x: f32) -> f32 { + atan2f_gen_impl(y, x, f64::mul_add) +} + +/// Computes atan2 +/// +/// Max found ULP 0.49999842 +#[inline] +pub fn f_atan2f(y: f32, x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atan2f_gen_impl(y, x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atan2f_fma_impl + } else { + fn def_atan2f(y: f32, x: f32) -> f32 { + atan2f_gen_impl(y, x, f_fmla) + } + def_atan2f + } + }); + unsafe { q(y, x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_atan2_test() { + assert_eq!( + f_atan2f( + 0.000000000000000000000000000000000000017907922, + 170141180000000000000000000000000000000. + ), + 0. + ); + assert_eq!(f_atan2f(-3590000000., -15437000.), -1.5750962); + assert_eq!(f_atan2f(-5., 2.), -1.19029); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,445 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::acospi::{INV_PI_DD, INV_PI_F128}; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::dyadic_float::DyadicFloat128; +use crate::rounding::CpuRound; +use crate::tangent::atan2::{ATAN_I, atan_eval, atan2_hard}; + +/// If one of arguments is too huge or too small, extended precision is required for +/// case with big exponent difference +#[cold] +fn atan2pi_big_exp_difference_hard( + num: f64, + den: f64, + x_sign: usize, + y_sign: usize, + recip: bool, + final_sign: f64, +) -> f64 { + const ZERO: DoubleDouble = DoubleDouble::new(0.0, 0.0); + const MZERO: DoubleDouble = DoubleDouble::new(-0.0, -0.0); + static CONST_ADJ_INV_PI: [[[DoubleDouble; 2]; 2]; 2] = [ + [ + [ZERO, DoubleDouble::new(0., -1. / 2.)], + [MZERO, DoubleDouble::new(0., -1. / 2.)], + ], + [ + [DoubleDouble::new(0., -1.), DoubleDouble::new(0., 1. / 2.)], + [DoubleDouble::new(0., -1.), DoubleDouble::new(0., 1. / 2.)], + ], + ]; + let const_term = CONST_ADJ_INV_PI[x_sign][y_sign][recip as usize]; + let scaled_div = DyadicFloat128::from_div_f64(num, den) * INV_PI_F128; + let sign_f128 = DyadicFloat128::new_from_f64(final_sign); + let p = DyadicFloat128::new_from_f64(const_term.hi * final_sign); + let p1 = sign_f128 * (DyadicFloat128::new_from_f64(const_term.lo) + scaled_div); + let r = p + p1; + r.fast_as_f64() +} + +static IS_NEG: [f64; 2] = [1.0, -1.0]; +const ZERO: DoubleDouble = DoubleDouble::new(0.0, 0.0); +const MZERO: DoubleDouble = DoubleDouble::new(-0.0, -0.0); +const PI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3ca1a62633145c07), + f64::from_bits(0x400921fb54442d18), +); +const MPI: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbca1a62633145c07), + f64::from_bits(0xc00921fb54442d18), +); +const PI_OVER_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c91a62633145c07), + f64::from_bits(0x3ff921fb54442d18), +); +const MPI_OVER_2: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc91a62633145c07), + f64::from_bits(0xbff921fb54442d18), +); +const PI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c81a62633145c07), + f64::from_bits(0x3fe921fb54442d18), +); +const THREE_PI_OVER_4: DoubleDouble = DoubleDouble::new( + f64::from_bits(0x3c9a79394c9e8a0a), + f64::from_bits(0x4002d97c7f3321d2), +); + +// Adjustment for constant term: +// CONST_ADJ[x_sign][y_sign][recip] +static CONST_ADJ: [[[DoubleDouble; 2]; 2]; 2] = [ + [[ZERO, MPI_OVER_2], [MZERO, MPI_OVER_2]], + [[MPI, PI_OVER_2], [MPI, PI_OVER_2]], +]; + +#[inline(always)] +fn atan2pi_gen_impl(y: f64, x: f64) -> f64 { + let x_sign = x.is_sign_negative() as usize; + let y_sign = y.is_sign_negative() as usize; + let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff; + let x_abs = x_bits; + let y_abs = y_bits; + let recip = x_abs < y_abs; + let mut min_abs = if recip { x_abs } else { y_abs }; + let mut max_abs = if !recip { x_abs } else { y_abs }; + let mut min_exp = min_abs.wrapping_shr(52); + let mut max_exp = max_abs.wrapping_shr(52); + + let mut num = f64::from_bits(min_abs); + let mut den = f64::from_bits(max_abs); + + // Check for exceptional cases, whether inputs are 0, inf, nan, or close to + // overflow, or close to underflow. + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + let x_except = if x == 0.0 { + 0 + } else if x.is_infinite() { + 2 + } else { + 1 + }; + let y_except = if y == 0.0 { + 0 + } else if y.is_infinite() { + 2 + } else { + 1 + }; + + // Exceptional cases: + // EXCEPT[y_except][x_except][x_is_neg] + // with x_except & y_except: + // 0: zero + // 1: finite, non-zero + // 2: infinity + static EXCEPTS: [[[DoubleDouble; 2]; 3]; 3] = [ + [[ZERO, PI], [ZERO, PI], [ZERO, PI]], + [[PI_OVER_2, PI_OVER_2], [ZERO, ZERO], [ZERO, PI]], + [ + [PI_OVER_2, PI_OVER_2], + [PI_OVER_2, PI_OVER_2], + [PI_OVER_4, THREE_PI_OVER_4], + ], + ]; + + if (x_except != 1) || (y_except != 1) { + let mut r = EXCEPTS[y_except][x_except][x_sign]; + r = DoubleDouble::quick_mult(r, INV_PI_DD); + return f_fmla(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo); + } + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // by some large enough power of 2 to normalize denormal inputs. + if scale_up { + num *= f64::from_bits(0x43f0000000000000); + if !scale_down { + den *= f64::from_bits(0x43f0000000000000); + } + } else if scale_down { + den *= f64::from_bits(0x3bf0000000000000); + if !scale_up { + num *= f64::from_bits(0x3bf0000000000000); + } + } + + min_abs = num.to_bits(); + max_abs = den.to_bits(); + min_exp = min_abs.wrapping_shr(52); + max_exp = max_abs.wrapping_shr(52); + } + + let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize]; + let const_term = CONST_ADJ[x_sign][y_sign][recip as usize]; + let exp_diff = max_exp - min_exp; + // We have the following bound for normalized n and d: + // 2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1). + if exp_diff > 54 { + if max_exp >= 1075 || min_exp < 970 { + return atan2pi_big_exp_difference_hard(num, den, x_sign, y_sign, recip, final_sign); + } + let z = DoubleDouble::from_exact_mult(final_sign, const_term.hi); + let mut divided = DoubleDouble::from_exact_div(num, den); + divided = DoubleDouble::f64_add(const_term.lo, divided); + divided = DoubleDouble::quick_mult_f64(divided, final_sign); + let r = DoubleDouble::add(z, divided); + let p = DoubleDouble::quick_mult(INV_PI_DD, r); + return p.to_f64(); + } + + let mut k = (64.0 * num / den).cpu_round(); + let idx = k as u64; + // k = idx / 64 + k *= f64::from_bits(0x3f90000000000000); + + // Range reduction: + // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64))) + // = atan((n - d * k/64)) / (d + n * k/64)) + let num_k = DoubleDouble::from_exact_mult(num, k); + let den_k = DoubleDouble::from_exact_mult(den, k); + + // num_dd = n - d * k + let num_dd = DoubleDouble::from_exact_add(num - den_k.hi, -den_k.lo); + // den_dd = d + n * k + let mut den_dd = DoubleDouble::from_exact_add(den, num_k.hi); + den_dd.lo += num_k.lo; + + // q = (n - d * k) / (d + n * k) + let q = DoubleDouble::div(num_dd, den_dd); + // p ~ atan(q) + let p = atan_eval(q); + + let vl = ATAN_I[idx as usize]; + let vlo = DoubleDouble::from_bit_pair(vl); + let mut r = DoubleDouble::add(const_term, DoubleDouble::add(vlo, p)); + + r = DoubleDouble::quick_mult(r, INV_PI_DD); + + let err = f_fmla( + p.hi, + f64::from_bits(0x3bd0000000000000), + f64::from_bits(0x3c00000000000000), + ); + + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + + if ub == lb { + r.hi *= final_sign; + r.lo *= final_sign; + + return r.to_f64(); + } + + (atan2_hard(y, x) * INV_PI_F128).fast_as_f64() +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atan2pi_fma_impl(y: f64, x: f64) -> f64 { + let x_sign = x.is_sign_negative() as usize; + let y_sign = y.is_sign_negative() as usize; + let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff; + let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff; + let x_abs = x_bits; + let y_abs = y_bits; + let recip = x_abs < y_abs; + let mut min_abs = if recip { x_abs } else { y_abs }; + let mut max_abs = if !recip { x_abs } else { y_abs }; + let mut min_exp = min_abs.wrapping_shr(52); + let mut max_exp = max_abs.wrapping_shr(52); + + let mut num = f64::from_bits(min_abs); + let mut den = f64::from_bits(max_abs); + + // Check for exceptional cases, whether inputs are 0, inf, nan, or close to + // overflow, or close to underflow. + if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 { + if x.is_nan() || y.is_nan() { + return f64::NAN; + } + let x_except = if x == 0.0 { + 0 + } else if x.is_infinite() { + 2 + } else { + 1 + }; + let y_except = if y == 0.0 { + 0 + } else if y.is_infinite() { + 2 + } else { + 1 + }; + + // Exceptional cases: + // EXCEPT[y_except][x_except][x_is_neg] + // with x_except & y_except: + // 0: zero + // 1: finite, non-zero + // 2: infinity + static EXCEPTS: [[[DoubleDouble; 2]; 3]; 3] = [ + [[ZERO, PI], [ZERO, PI], [ZERO, PI]], + [[PI_OVER_2, PI_OVER_2], [ZERO, ZERO], [ZERO, PI]], + [ + [PI_OVER_2, PI_OVER_2], + [PI_OVER_2, PI_OVER_2], + [PI_OVER_4, THREE_PI_OVER_4], + ], + ]; + + if (x_except != 1) || (y_except != 1) { + let mut r = EXCEPTS[y_except][x_except][x_sign]; + r = DoubleDouble::quick_mult_fma(r, INV_PI_DD); + return f64::mul_add(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo); + } + let scale_up = min_exp < 128u64; + let scale_down = max_exp > 0x7ffu64 - 128u64; + // At least one input is denormal, multiply both numerator and denominator + // by some large enough power of 2 to normalize denormal inputs. + if scale_up { + num *= f64::from_bits(0x43f0000000000000); + if !scale_down { + den *= f64::from_bits(0x43f0000000000000); + } + } else if scale_down { + den *= f64::from_bits(0x3bf0000000000000); + if !scale_up { + num *= f64::from_bits(0x3bf0000000000000); + } + } + + min_abs = num.to_bits(); + max_abs = den.to_bits(); + min_exp = min_abs.wrapping_shr(52); + max_exp = max_abs.wrapping_shr(52); + } + + let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize]; + let const_term = CONST_ADJ[x_sign][y_sign][recip as usize]; + let exp_diff = max_exp - min_exp; + // We have the following bound for normalized n and d: + // 2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1). + if exp_diff > 54 { + if max_exp >= 1075 || min_exp < 970 { + return atan2pi_big_exp_difference_hard(num, den, x_sign, y_sign, recip, final_sign); + } + let z = DoubleDouble::from_exact_mult_fma(final_sign, const_term.hi); + let mut divided = DoubleDouble::from_exact_div_fma(num, den); + divided = DoubleDouble::f64_add(const_term.lo, divided); + divided = DoubleDouble::quick_mult_f64_fma(divided, final_sign); + let r = DoubleDouble::add(z, divided); + let p = DoubleDouble::quick_mult_fma(INV_PI_DD, r); + return p.to_f64(); + } + + let mut k = (64.0 * num / den).round(); + let idx = k as u64; + // k = idx / 64 + k *= f64::from_bits(0x3f90000000000000); + + // Range reduction: + // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64))) + // = atan((n - d * k/64)) / (d + n * k/64)) + let num_k = DoubleDouble::from_exact_mult_fma(num, k); + let den_k = DoubleDouble::from_exact_mult_fma(den, k); + + // num_dd = n - d * k + let num_dd = DoubleDouble::from_exact_add(num - den_k.hi, -den_k.lo); + // den_dd = d + n * k + let mut den_dd = DoubleDouble::from_exact_add(den, num_k.hi); + den_dd.lo += num_k.lo; + + // q = (n - d * k) / (d + n * k) + let q = DoubleDouble::div_fma(num_dd, den_dd); + // p ~ atan(q) + use crate::tangent::atan2::atan_eval_fma; + let p = atan_eval_fma(q); + + let vl = ATAN_I[idx as usize]; + let vlo = DoubleDouble::from_bit_pair(vl); + let mut r = DoubleDouble::add(const_term, DoubleDouble::add(vlo, p)); + + r = DoubleDouble::quick_mult_fma(r, INV_PI_DD); + + let err = f64::mul_add( + p.hi, + f64::from_bits(0x3bd0000000000000), + f64::from_bits(0x3c00000000000000), + ); + + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + + if ub == lb { + r.hi *= final_sign; + r.lo *= final_sign; + + return r.to_f64(); + } + + (atan2_hard(y, x) * INV_PI_F128).fast_as_f64() +} + +/// Computes atan(x)/PI +/// +/// Max found ULP 0.5 +pub fn f_atan2pi(y: f64, x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atan2pi_gen_impl(y, x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atan2pi_fma_impl + } else { + fn def_atan2pi(y: f64, x: f64) -> f64 { + atan2pi_gen_impl(y, x) + } + def_atan2pi + } + }); + unsafe { q(y, x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_atan2pi() { + assert_eq!( + f_atan2pi(-0.000000000000010659658919444194, 2088960.4374061823), + -0.0000000000000000000016242886924270424 + ); + assert_eq!(f_atan2pi(-3.9999999981625933, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003577142133480227), -0.5); + assert_eq!(f_atan2pi(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000472842255026406, + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008045886150098693 + ),1.8706499392673612e-162); + assert_eq!(f_atan2pi(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002670088630208647, + 2.0000019071157054 + ), 4.249573987697093e-307); + assert_eq!(f_atan2pi(-5., 2.), -0.3788810584091566); + assert_eq!(f_atan2pi(2., -5.), 0.8788810584091566); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atan2pif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,185 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +static OFF: [f32; 8] = [0.0, 0.5, 1.0, 0.5, -0.0, -0.5, -1.0, -0.5]; +static SGNF: [f32; 2] = [1., -1.]; +static SGN: [f64; 2] = [1., -1.]; + +#[inline(always)] +fn atan2pif_gen_impl f64>(y: f32, x: f32, fma: Q) -> f32 { + let tx = x.to_bits(); + let ty: u32 = y.to_bits(); + let ux: u32 = tx; + let uy: u32 = ty; + let ax: u32 = ux & 0x7fff_ffff; + let ay = uy & 0x7fff_ffff; + if ay >= (0xff << 23) || ax >= (0xff << 23) { + if ay > (0xff << 23) { + return x + y; + } // nan + if ax > (0xff << 23) { + return x + y; + } // nan + let yinf = ay == (0xff << 23); + let xinf = ax == (0xff << 23); + if yinf & xinf { + return if (ux >> 31) != 0 { + 0.75 * SGNF[(uy >> 31) as usize] + } else { + 0.25 * SGNF[(uy >> 31) as usize] + }; + } + if xinf { + return if (ux >> 31) != 0 { + SGNF[(uy >> 31) as usize] + } else { + 0.0 * SGNF[(uy >> 31) as usize] + }; + } + if yinf { + return 0.5 * SGNF[(uy >> 31) as usize]; + } + } + if ay == 0 { + if (ay | ax) == 0 { + let i: u32 = (uy >> 31) * 4 + (ux >> 31) * 2; + return OFF[i as usize]; + } + if (ux >> 31) == 0 { + return 0.0 * SGNF[(uy >> 31) as usize]; + } + } + if ax == ay { + static S: [f32; 4] = [0.25, 0.75, -0.25, -0.75]; + let i = (uy >> 31) * 2 + (ux >> 31); + return S[i as usize]; + } + let gt: usize = (ay > ax) as usize; + let i: u32 = (uy >> 31) * 4 + (ux >> 31) * 2 + gt as u32; + + let zx = x as f64; + let zy = y as f64; + static M: [f64; 2] = [0., 1.]; + + let mut z = fma(M[gt], zx, M[1 - gt] * zy) / fma(M[gt], zy, M[1 - gt] * zx); + + const CN: [u64; 7] = [ + 0x3fd45f306dc9c883, + 0x3fe988d83a142ada, + 0x3fe747bebf492057, + 0x3fd2cc5645094ff3, + 0x3faa0521c711ab66, + 0x3f6881b8058b9a0d, + 0x3efb16ff514a0af0, + ]; + + let mut r = f64::from_bits(CN[0]); + let z2 = z * z; + z *= SGN[gt]; + // avoid spurious underflow in the polynomial evaluation excluding tiny arguments + if z2 > f64::from_bits(0x3c90000000000000) { + let z4 = z2 * z2; + let z8 = z4 * z4; + let mut cn0 = fma(z2, f64::from_bits(CN[1]), r); + let cn2 = fma(z2, f64::from_bits(CN[3]), f64::from_bits(CN[2])); + let mut cn4 = fma(z2, f64::from_bits(CN[5]), f64::from_bits(CN[4])); + let cn6 = f64::from_bits(CN[6]); + cn0 += z4 * cn2; + cn4 += z4 * cn6; + cn0 += z8 * cn4; + + const CD: [u64; 7] = [ + 0x3ff0000000000000, + 0x4006b8b143a3f6da, + 0x4008421201d18ed5, + 0x3ff8221d086914eb, + 0x3fd670657e3a07ba, + 0x3fa0f4951fd1e72d, + 0x3f4b3874b8798286, + ]; + + let mut cd0 = fma(z2, f64::from_bits(CD[1]), f64::from_bits(CD[0])); + let cd2 = fma(z2, f64::from_bits(CD[3]), f64::from_bits(CD[2])); + let mut cd4 = fma(z2, f64::from_bits(CD[5]), f64::from_bits(CD[4])); + let cd6 = f64::from_bits(CD[6]); + cd0 = fma(z4, cd2, cd0); + cd4 = fma(z4, cd6, cd4); + cd0 = fma(z8, cd4, cd0); + + r = cn0 / cd0; + } + fma(z, r, OFF[i as usize] as f64) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atan2pif_fma_impl(y: f32, x: f32) -> f32 { + atan2pif_gen_impl(y, x, f64::mul_add) +} + +/// Computes atan(x/y) / PI +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_atan2pif(y: f32, x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atan2pif_gen_impl(y, x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atan2pif_fma_impl + } else { + fn def_atan2pif(y: f32, x: f32) -> f32 { + atan2pif_gen_impl(y, x, f_fmla) + } + def_atan2pif + } + }); + unsafe { q(y, x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_atan2pif() { + assert_eq!(f_atan2pif(0.32131, 0.987565), 0.10012555); + assert_eq!(f_atan2pif(532.32131, 12.987565), 0.49223542); + assert_eq!(f_atan2pif(-754.32131, 12.987565), -0.494520042); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{f_fmla, f_fmlaf}; + +#[inline(always)] +fn atanf_gen_impl f64>(x: f32, fma: Q) -> f32 { + const PI2: f64 = f64::from_bits(0x3ff921fb54442d18); + let t = x.to_bits(); + let e = (t >> 23) & 0xff; + let gt = e >= 127; + let ta = t & 0x7fffffff; + if ta >= 0x4c700518u32 { + // |x| >= 6.29198e+07 + if ta > 0x7f800000u32 { + return x + x; + } // nan + return f32::copysign(PI2 as f32, x); // inf or |x| >= 6.29198e+07 + } + if e < 127 - 13 { + // |x| < 2^-13 + if e < 127 - 25 { + // |x| < 2^-25 + if t << 1 == 0 { + return x; + } + let res = f_fmlaf(-x, x.abs(), x); + return res; + } + return f_fmlaf(-f64::from_bits(0x3fd5555560000000) as f32 * x, x * x, x); + } + /* now |x| >= 0.00012207 */ + let mut z = x as f64; + if gt { + z = 1.0 / z; + } /* gt is non-zero for |x| >= 1 */ + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + /* polynomials generated using rminimax + (https://gitlab.inria.fr/sfilip/rminimax) with the following command: + ./ratapprox --function="atan(x)" --dom=[0.000122070,1] --num=[x,x^3,x^5,x^7,x^9,x^11,x^13] --den=[1,x^2,x^4,x^6,x^8,x^10,x^12] --output=atanf.sollya --log + (see output atanf.sollya) + The coefficient cd[0] was slightly reduced from the original value + 0.330005 to avoid an exceptional case for |x| = 0.069052 + and rounding to nearest. + */ + const CN: [u64; 7] = [ + 0x3fd51eccde075d67, + 0x3fea76bb5637f2f2, + 0x3fe81e0eed20de88, + 0x3fd376c8ca67d11d, + 0x3faaec7b69202ac6, + 0x3f69561899acc73e, + 0x3efbf9fa5b67e600, + ]; + const CD: [u64; 7] = [ + 0x3fd51eccde075d66, + 0x3fedfbdd7b392d28, + 0x3ff0000000000000, + 0x3fdfd22bf0e89b54, + 0x3fbd91ff8b576282, + 0x3f8653ea99fc9bb0, + 0x3f31e7fcc202340a, + ]; + let mut cn0 = fma(z2, f64::from_bits(CN[1]), f64::from_bits(CN[0])); + let cn2 = fma(z2, f64::from_bits(CN[3]), f64::from_bits(CN[2])); + let mut cn4 = fma(z2, f64::from_bits(CN[5]), f64::from_bits(CN[4])); + let cn6 = f64::from_bits(CN[6]); + cn0 = fma(z4, cn2, cn0); + cn4 = fma(z4, cn6, cn4); + cn0 = fma(z8, cn4, cn0); + cn0 *= z; + let mut cd0 = fma(z2, f64::from_bits(CD[1]), f64::from_bits(CD[0])); + let cd2 = fma(z2, f64::from_bits(CD[3]), f64::from_bits(CD[2])); + let mut cd4 = fma(z2, f64::from_bits(CD[5]), f64::from_bits(CD[4])); + let cd6 = f64::from_bits(CD[6]); + cd0 = fma(z4, cd2, cd0); + cd4 = fma(z4, cd6, cd4); + cd0 = fma(z8, cd4, cd0); + let r = cn0 / cd0; + if !gt { + return r as f32; + } /* for |x| < 1, (float) r is correctly rounded */ + + const PI_OVER2_H: f64 = f64::from_bits(0x3ff9000000000000); + const PI_OVER2_L: f64 = f64::from_bits(0x3f80fdaa22168c23); + /* now r approximates atan(1/x), we use atan(x) + atan(1/x) = sign(x)*pi/2, + where PI_OVER2_H + PI_OVER2_L approximates pi/2. + With sign(z)*L + (-r + sign(z)*H), it fails for x=0x1.98c252p+12 and + rounding upward. + With sign(z)*PI - r, where PI is a double approximation of pi to nearest, + it fails for x=0x1.ddf9f6p+0 and rounding upward. */ + ((f64::copysign(PI_OVER2_L, z) - r) + f64::copysign(PI_OVER2_H, z)) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atanf_fma_impl(x: f32) -> f32 { + atanf_gen_impl(x, f64::mul_add) +} + +/// Computes atan +/// +/// Max found ULP 0.49999973 +#[inline] +pub fn f_atanf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atanf_gen_impl(x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atanf_fma_impl + } else { + fn def_atanf(x: f32) -> f32 { + atanf_gen_impl(x, f_fmla) + } + def_atanf + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_atan_test() { + assert!( + (f_atanf(1.0) - std::f32::consts::PI / 4f32).abs() < 1e-6, + "Invalid result {}", + f_atanf(1f32) + ); + assert!( + (f_atanf(2f32) - 1.107148717794090503017065f32).abs() < 1e-6, + "Invalid result {}", + f_atanf(2f32) + ); + assert!( + (f_atanf(5f32) - 1.3734007669450158608612719264f32).abs() < 1e-6, + "Invalid result {}", + f_atanf(5f32) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,471 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dd_fmla, dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::shared_eval::poly_dd_3; +use crate::tangent::atan::{ATAN_CIRCLE, ATAN_REDUCE}; + +const ONE_OVER_PI_DD: DoubleDouble = DoubleDouble::new( + f64::from_bits(0xbc76b01ec5417056), + f64::from_bits(0x3fd45f306dc9c883), +); + +const ONE_OVER_3PI: f64 = f64::from_bits(0x3fbb2995e7b7b604); // approximates 1/(3pi) + +fn atanpi_small(x: f64) -> f64 { + if x == 0. { + return x; + } + if x.abs() == f64::from_bits(0x0015cba89af1f855) { + return if x > 0. { + f_fmla( + f64::from_bits(0x9a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x0006f00f7cd3a40b), + ) + } else { + f_fmla( + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x8006f00f7cd3a40b), + ) + }; + } + // generic worst case + let mut v = x.to_bits(); + if (v & 0xfffffffffffff) == 0x59af9a1194efe + // +/-0x1.59af9a1194efe*2^e + { + let e = v >> 52; + if (e & 0x7ff) > 2 { + v = ((e - 2) << 52) | 0xb824198b94a89; + return if x > 0. { + dd_fmla( + f64::from_bits(0x9a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(v), + ) + } else { + dd_fmla( + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(v), + ) + }; + } + } + let h = x * ONE_OVER_PI_DD.hi; + /* Assuming h = x*ONE_OVER_PI_DD.hi - e, the correction term is + e + x * ONE_OVER_PIL, but we need to scale values to avoid underflow. */ + let mut corr = dd_fmla( + x * f64::from_bits(0x4690000000000000), + ONE_OVER_PI_DD.hi, + -h * f64::from_bits(0x4690000000000000), + ); + corr = dd_fmla( + x * f64::from_bits(0x4690000000000000), + ONE_OVER_PI_DD.lo, + corr, + ); + // now return h + corr * 2^-106 + + dyad_fmla(corr, f64::from_bits(0x3950000000000000), h) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atanpi_small_fma(x: f64) -> f64 { + if x == 0. { + return x; + } + if x.abs() == f64::from_bits(0x0015cba89af1f855) { + return if x > 0. { + f64::mul_add( + f64::from_bits(0x9a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x0006f00f7cd3a40b), + ) + } else { + f64::mul_add( + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x8006f00f7cd3a40b), + ) + }; + } + // generic worst case + let mut v = x.to_bits(); + if (v & 0xfffffffffffff) == 0x59af9a1194efe + // +/-0x1.59af9a1194efe*2^e + { + let e = v >> 52; + if (e & 0x7ff) > 2 { + v = ((e - 2) << 52) | 0xb824198b94a89; + return if x > 0. { + f64::mul_add( + f64::from_bits(0x9a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(v), + ) + } else { + f64::mul_add( + f64::from_bits(0x1a70000000000000), + f64::from_bits(0x1a70000000000000), + f64::from_bits(v), + ) + }; + } + } + let h = x * ONE_OVER_PI_DD.hi; + /* Assuming h = x*ONE_OVER_PI_DD.hi - e, the correction term is + e + x * ONE_OVER_PIL, but we need to scale values to avoid underflow. */ + let mut corr = f64::mul_add( + x * f64::from_bits(0x4690000000000000), + ONE_OVER_PI_DD.hi, + -h * f64::from_bits(0x4690000000000000), + ); + corr = f64::mul_add( + x * f64::from_bits(0x4690000000000000), + ONE_OVER_PI_DD.lo, + corr, + ); + // now return h + corr * 2^-106 + + f64::mul_add(corr, f64::from_bits(0x3950000000000000), h) +} + +/* Deal with the case where |x| is large: +for x > 0, atanpi(x) = 1/2 - 1/pi * 1/x + 1/(3pi) * 1/x^3 + O(1/x^5) +for x < 0, atanpi(x) = -1/2 - 1/pi * 1/x + 1/(3pi) * 1/x^3 + O(1/x^5). +The next term 1/5*x^5/pi is smaller than 2^-107 * atanpi(x) +when |x| > 0x1.bep20. */ +fn atanpi_asympt(x: f64) -> f64 { + let h = f64::copysign(0.5, x); + // approximate 1/x as yh + yl + let rcy = DoubleDouble::from_quick_recip(x); + let mut m = DoubleDouble::quick_mult(rcy, ONE_OVER_PI_DD); + // m + l ~ 1/pi * 1/x + m.hi = -m.hi; + m.lo = dd_fmla(ONE_OVER_3PI * rcy.hi, rcy.hi * rcy.hi, -m.lo); + // m + l ~ - 1/pi * 1/x + 1/(3pi) * 1/x^3 + let vh = DoubleDouble::from_exact_add(h, m.hi); + m.hi = vh.hi; + m = DoubleDouble::from_exact_add(vh.lo, m.lo); + if m.hi.abs() == f64::from_bits(0x3c80000000000000) { + // this is 1/2 ulp(atan(x)) + m.hi = if m.hi * m.lo > 0. { + f64::copysign(f64::from_bits(0x3c80000000000001), m.hi) + } else { + f64::copysign(f64::from_bits(0x3c7fffffffffffff), m.hi) + }; + } + vh.hi + m.hi +} + +#[inline] +fn atanpi_tiny(x: f64) -> f64 { + let mut dx = DoubleDouble::quick_mult_f64(ONE_OVER_PI_DD, x); + dx.lo = dd_fmla(-ONE_OVER_3PI * x, x * x, dx.lo); + dx.to_f64() +} + +#[cold] +fn as_atanpi_refine2(x: f64, a: f64) -> f64 { + if x.abs() > f64::from_bits(0x413be00000000000) { + return atanpi_asympt(x); + } + if x.abs() < f64::from_bits(0x3e4c700000000000) { + return atanpi_tiny(x); + } + const CH: [(u64, u64); 3] = [ + (0xbfd5555555555555, 0xbc75555555555555), + (0x3fc999999999999a, 0xbc6999999999bcb8), + (0xbfc2492492492492, 0xbc6249242093c016), + ]; + const CL: [u64; 4] = [ + 0x3fbc71c71c71c71c, + 0xbfb745d1745d1265, + 0x3fb3b13b115bcbc4, + 0xbfb1107c41ad3253, + ]; + let phi = ((a.abs()) * f64::from_bits(0x40545f306dc9c883) + 256.5).to_bits(); + let i: i64 = ((phi >> (52 - 8)) & 0xff) as i64; + let dh: DoubleDouble = if i == 128 { + DoubleDouble::from_quick_recip(-x) + } else { + let ta = f64::copysign(f64::from_bits(ATAN_REDUCE[i as usize].0), x); + let dzta = DoubleDouble::from_exact_mult(x, ta); + let zmta = x - ta; + let v = 1. + dzta.hi; + let d = 1. - v; + let ev = (d + dzta.hi) - ((d + v) - 1.) + dzta.lo; + let r = 1.0 / v; + let rl = f_fmla(-ev, r, dd_fmla(r, -v, 1.0)) * r; + DoubleDouble::quick_mult_f64(DoubleDouble::new(rl, r), zmta) + }; + let d2 = DoubleDouble::quick_mult(dh, dh); + let h4 = d2.hi * d2.hi; + let h3 = DoubleDouble::quick_mult(dh, d2); + + let fl0 = f_fmla(d2.hi, f64::from_bits(CL[1]), f64::from_bits(CL[0])); + let fl1 = f_fmla(d2.hi, f64::from_bits(CL[3]), f64::from_bits(CL[2])); + + let fl = d2.hi * f_fmla(h4, fl1, fl0); + let mut f = poly_dd_3(d2, CH, fl); + f = DoubleDouble::quick_mult(h3, f); + let (ah, mut al, mut at); + if i == 0 { + ah = dh.hi; + al = f.hi; + at = f.lo; + } else { + let mut df = 0.; + if i < 128 { + df = f64::copysign(1.0, x) * f64::from_bits(ATAN_REDUCE[i as usize].1); + } + let id = f64::copysign(i as f64, x); + ah = f64::from_bits(0x3f8921fb54442d00) * id; + al = f64::from_bits(0x3c88469898cc5180) * id; + at = f64::from_bits(0xb97fc8f8cbb5bf80) * id; + let v0 = DoubleDouble::add(DoubleDouble::new(at, al), DoubleDouble::new(0., df)); + let v1 = DoubleDouble::add(v0, dh); + let v2 = DoubleDouble::add(v1, f); + al = v2.hi; + at = v2.lo; + } + + let v2 = DoubleDouble::from_exact_add(ah, al); + let v1 = DoubleDouble::from_exact_add(v2.lo, at); + + let z0 = DoubleDouble::quick_mult(DoubleDouble::new(v1.hi, v2.hi), ONE_OVER_PI_DD); + // atanpi_end + z0.to_f64() +} + +#[inline(always)] +/// fma - fma +/// dd_fma - mandatory fma fallback +fn atanpi_gen_impl< + Q: Fn(f64, f64, f64) -> f64, + F: Fn(f64, f64, f64) -> f64, + DdMul: Fn(DoubleDouble, DoubleDouble) -> DoubleDouble, + AtanpiSmall: Fn(f64) -> f64, +>( + x: f64, + fma: Q, + dd_fma: F, + dd_mul: DdMul, + atanpi_small: AtanpiSmall, +) -> f64 { + const CH: [u64; 4] = [ + 0x3ff0000000000000, + 0xbfd555555555552b, + 0x3fc9999999069c20, + 0xbfc248d2c8444ac6, + ]; + let t = x.to_bits(); + let at: u64 = t & 0x7fff_ffff_ffff_ffff; + let mut i = (at >> 51).wrapping_sub(2030u64); + if at < 0x3f7b21c475e6362au64 { + // |x| < 0.006624 + if at < 0x3c90000000000000u64 { + // |x| < 2^-54 + return atanpi_small(x); + } + if x == 0. { + return x; + } + const CH2: [u64; 4] = [ + 0xbfd5555555555555, + 0x3fc99999999998c1, + 0xbfc249249176aec0, + 0x3fbc711fd121ae80, + ]; + let x2 = x * x; + let x3 = x * x2; + let x4 = x2 * x2; + + let f0 = fma(x2, f64::from_bits(CH2[3]), f64::from_bits(CH2[2])); + let f1 = fma(x2, f64::from_bits(CH2[1]), f64::from_bits(CH2[0])); + + let f = x3 * dd_fma(x4, f0, f1); + // begin_atanpi + /* Here x+f approximates atan(x), with absolute error bounded by + 0x4.8p-52*f (see atan.c). After multiplying by 1/pi this error + will be bounded by 0x1.6fp-52*f. For |x| < 0x1.b21c475e6362ap-8 + we have |f| < 2^-16*|x|, thus the error is bounded by + 0x1.6fp-52*2^-16*|x| < 0x1.6fp-68. */ + // multiply x + f by 1/pi + let hy = dd_mul(DoubleDouble::new(f, x), ONE_OVER_PI_DD); + /* The rounding error in muldd and the approximation error between + 1/pi and ONE_OVER_PIH + ONE_OVER_PIL are covered by the difference + between 0x4.8p-52*pi and 0x1.6fp-52, which is > 2^-61.8. */ + let mut ub = hy.hi + dd_fma(f64::from_bits(0x3bb6f00000000000), x, hy.lo); + let lb = hy.hi + dd_fma(f64::from_bits(0xbbb6f00000000000), x, hy.lo); + if ub == lb { + return ub; + } + // end_atanpi + ub = (f + f * f64::from_bits(0x3cd2000000000000)) + x; // atanpi_specific, original value in atan + return as_atanpi_refine2(x, ub); + } + // now |x| >= 0x1.b21c475e6362ap-8 + let h; + let mut a: DoubleDouble; + if at > 0x4062ded8e34a9035u64 { + // |x| > 0x1.2ded8e34a9035p+7, atanpi|x| > 0.49789 + if at >= 0x43445f306dc9c883u64 { + // |x| >= 0x1.45f306dc9c883p+53, atanpi|x| > 0.5 - 0x1p-55 + if at >= (0x7ffu64 << 52) { + // case Inf or NaN + if at == 0x7ffu64 << 52 { + // Inf + return f64::copysign(0.5, x); + } // atanpi_specific + return x + x; // NaN + } + return f64::copysign(0.5, x) - f64::copysign(f64::from_bits(0x3c70000000000000), x); + } + h = -1.0 / x; + a = DoubleDouble::new( + f64::copysign(f64::from_bits(0x3c91a62633145c07), x), + f64::copysign(f64::from_bits(0x3ff921fb54442d18), x), + ); + } else { + // 0x1.b21c475e6362ap-8 <= |x| <= 0x1.2ded8e34a9035p+7 + /* we need to deal with |x| = 1 separately since in this case + h=0 below, and the error is measured in terms of multiple of h */ + if at == 0x3ff0000000000000 { + // |x| = 1 + return f64::copysign(f64::from_bits(0x3fd0000000000000), x); + } + let u: u64 = t & 0x0007ffffffffffff; + let ut = u >> (51 - 16); + let ut2 = (ut * ut) >> 16; + let vc = ATAN_CIRCLE[i as usize]; + i = (((vc[0] as u64).wrapping_shl(16)) + ut * (vc[1] as u64) - ut2 * (vc[2] as u64)) + >> (16 + 9); + let va = ATAN_REDUCE[i as usize]; + let ta = f64::copysign(1.0, x) * f64::from_bits(va.0); + let id = f64::copysign(1.0, x) * i as f64; + h = (x - ta) / fma(x, ta, 1.); + a = DoubleDouble::new( + fma( + f64::copysign(1.0, x), + f64::from_bits(va.1), + f64::from_bits(0x3c88469898cc5170) * id, + ), + f64::from_bits(0x3f8921fb54442d00) * id, + ); + } + let h2 = h * h; + let h4 = h2 * h2; + + let f0 = fma(h2, f64::from_bits(CH[3]), f64::from_bits(CH[2])); + let f1 = fma(h2, f64::from_bits(CH[1]), f64::from_bits(CH[0])); + + let f = fma(h4, f0, f1); + a.lo = dd_fma(h, f, a.lo); + // begin_atanpi + /* Now ah + al approximates atan(x) with error bounded by 0x3.fp-52*h + (see atan.c), thus by 0x1.41p-52*h after multiplication by 1/pi. + We normalize ah+al so that the rounding error in muldd is negligible + below. */ + let e0 = h * f64::from_bits(0x3ccf800000000000); // original value in atan.c + let ub0 = (a.lo + e0) + a.hi; // original value in atan.c + a = DoubleDouble::from_exact_add(a.hi, a.lo); + a = dd_mul(a, ONE_OVER_PI_DD); + /* The rounding error in muldd() and the approximation error between 1/pi + and ONE_OVER_PIH+ONE_OVER_PIL are absorbed when rounding up 0x3.fp-52*pi + to 0x1.41p-52. */ + let e = h * f64::from_bits(0x3cb4100000000000); // atanpi_specific + // end_atanpi + let ub = (a.lo + e) + a.hi; + let lb = (a.lo - e) + a.hi; + if ub == lb { + return ub; + } + as_atanpi_refine2(x, ub0) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atanpi_fma_impl(x: f64) -> f64 { + atanpi_gen_impl( + x, + f64::mul_add, + f64::mul_add, + DoubleDouble::quick_mult_fma, + |x| unsafe { atanpi_small_fma(x) }, + ) +} + +/// Computes atan(x)/pi +/// +/// Max ULP 0.5 +pub fn f_atanpi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atanpi_gen_impl(x, f_fmla, dd_fmla, DoubleDouble::quick_mult, atanpi_small) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atanpi_fma_impl + } else { + fn def_atanpi(x: f64) -> f64 { + atanpi_gen_impl(x, f_fmla, dd_fmla, DoubleDouble::quick_mult, atanpi_small) + } + def_atanpi + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn atanpi_test() { + assert_eq!(f_atanpi(119895888825197.97), 0.49999999999999734); + assert_eq!(f_atanpi(1.5610674235815122E-307), 4.969031939254545e-308); + assert_eq!(f_atanpi(0.00004577636903266291), 0.000014571070806516354); + assert_eq!(f_atanpi(-0.00004577636903266291), -0.000014571070806516354); + assert_eq!(f_atanpi(-0.4577636903266291), -0.13664770469904508); + assert_eq!(f_atanpi(0.9876636903266291), 0.24802445507819193); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/atanpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/atanpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; + +#[inline(always)] +fn atanpif_gen_impl f64>(x: f32, fma: Q) -> f32 { + let t = x.to_bits(); + let e: i32 = ((t >> 23) & 0xff) as i32; + let gt = e >= 127; + if e > 127 + 24 { + // |x| >= 2^25 + let f = f32::copysign(0.5, x); + if e == 0xff { + if (t.wrapping_shl(9)) != 0 { + return x + x; + } // nan + return f; // inf + } + // Warning: 0x1.45f306p-2f / x underflows for |x| >= 0x1.45f306p+124 + return if x.abs() >= f32::from_bits(0x7da2f983) { + f - f32::copysign(f32::from_bits(0x32800000), x) + } else { + f - f32::from_bits(0x3ea2f983) / x + }; + } + let mut z = x as f64; + if e < 127 - 13 { + // |x| < 2^-13 + let sx = z * f64::from_bits(0x3fd45f306dc9c883); + if e < 127 - 25 { + // |x| < 2^-25 + return sx as f32; + } + let zz0 = sx - (f64::from_bits(0x3fd5555555555555) * sx) * (x as f64 * x as f64); + return zz0 as f32; + } + let ax = t & 0x7fff_ffff; + if ax == 0x3fa267ddu32 { + return f32::copysign(f32::from_bits(0x3e933802), x) + - f32::copysign(f32::from_bits(0x24000000), x); + }; + if ax == 0x3f693531u32 { + return f32::copysign(f32::from_bits(0x3e70d331), x) + + f32::copysign(f32::from_bits(0x31800000), x); + }; + if ax == 0x3f800000u32 { + return f32::copysign(f32::from_bits(0x3e800000), x); + }; + if gt { + z = 1. / z; + } + let z2 = z * z; + let z4 = z2 * z2; + let z8 = z4 * z4; + const CN: [u64; 6] = [ + 0x3fd45f306dc9c882, + 0x3fe733b561bc23d5, + 0x3fe28d9805bdfbf2, + 0x3fc8c3ba966ae287, + 0x3f994a7f81ee634b, + 0x3f4a6bbf6127a6df, + ]; + let mut cn0 = fma(z2, f64::from_bits(CN[1]), f64::from_bits(CN[0])); + let cn2 = fma(z2, f64::from_bits(CN[3]), f64::from_bits(CN[2])); + let cn4 = fma(z2, f64::from_bits(CN[5]), f64::from_bits(CN[4])); + cn0 += z4 * cn2; + cn0 += z8 * cn4; + cn0 *= z; + + const CD: [u64; 7] = [ + 0x3ff0000000000000, + 0x4004e3b3ecc2518f, + 0x4003ef4a360ff063, + 0x3ff0f1dc55bad551, + 0x3fc8da0fecc018a4, + 0x3f88fa87803776bf, + 0x3f1dadf2ca0acb43, + ]; + + let mut cd0 = fma(z2, f64::from_bits(CD[1]), f64::from_bits(CD[0])); + let cd2 = fma(z2, f64::from_bits(CD[3]), f64::from_bits(CD[2])); + let mut cd4 = fma(z2, f64::from_bits(CD[5]), f64::from_bits(CD[4])); + let cd6 = f64::from_bits(CD[6]); + cd0 += z4 * cd2; + cd4 += z4 * cd6; + cd0 = fma(z8, cd4, cd0); + let mut r = cn0 / cd0; + if gt { + r = f64::copysign(0.5, z) - r; + } + r as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn atanpif_fma_impl(x: f32) -> f32 { + atanpif_gen_impl(x, f64::mul_add) +} + +/// Computes atan(x)/PI +/// +/// Max ULP 0.5 +#[inline] +pub fn f_atanpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + atanpif_gen_impl(x, f_fmla) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + atanpif_fma_impl + } else { + fn def_atanpif(x: f32) -> f32 { + atanpif_gen_impl(x, f_fmla) + } + def_atanpif + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_atanpif() { + assert_eq!(f_atanpif(0.0), 0.0); + assert_eq!(f_atanpif(1.0), 0.25); + assert_eq!(f_atanpif(1.5), 0.31283295); + assert_eq!(f_atanpif(-1.0), -0.25); + assert_eq!(f_atanpif(-1.5), -0.31283295); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cot.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cot.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cot.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cot.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::EXP_MASK; +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use crate::sin::range_reduction_small; +use crate::sincos_reduce::LargeArgumentReduction; +use crate::tangent::tan::{tan_eval, tan_eval_dd}; +use crate::tangent::tanpi_table::TAN_K_PI_OVER_128; + +#[cold] +fn cot_accurate(y: DoubleDouble, tan_k: DoubleDouble) -> f64 { + // Computes tan(x) through identities + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y) + tan(k*pi/128)) / (1 - tan(y)*tan(k*pi/128)) + let tan_y = tan_eval_dd(y); + + // num = tan(y) + tan(k*pi/64) + let num_dd = DoubleDouble::full_dd_add(tan_y, tan_k); + // den = 1 - tan(y)*tan(k*pi/64) + let den_dd = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + + let cot_x = DoubleDouble::div(den_dd, num_dd); + cot_x.to_f64() +} + +/// Cotangent in double precision +/// +/// ULP 0.5 +pub fn f_cot(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + if x_e < E_BIAS + 16 { + // |x| < 2^16 + if x_e < E_BIAS - 7 { + // |x| < 2^-7 + if x_e < E_BIAS - 27 { + // |x| < 2^-27, |cot(x) - x| < ulp(x)/2. + if x == 0.0 { + // Signed zeros. + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + + if x_e < E_BIAS - 53 { + return 1. / x; + } + + let dx = DoubleDouble::from_quick_recip(x); + // taylor order 3 + return DoubleDouble::f64_mul_f64_add(x, f64::from_bits(0xbfd5555555555555), dx) + .to_f64(); + } + // No range reduction needed. + k = 0; + y = DoubleDouble::new(0., x); + } else { + // Small range reduction. + (y, k) = range_reduction_small(x); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + if x.is_nan() { + return f64::NAN; + } + // tan(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let (tan_y, err) = tan_eval(y); + + // Computes tan(x) through identities. + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y) + tan(k*pi/128)) / (1 - tan(y)*tan(k*pi/128)) + let tan_k = DoubleDouble::from_bit_pair(TAN_K_PI_OVER_128[(k & 255) as usize]); + + // num = tan(y) + tan(k*pi/64) + let num_dd = DoubleDouble::add(tan_y, tan_k); + // den = 1 - tan(y)*tan(k*pi/64) + let den_dd = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + + // num and den shifted for cot + let cot_x = DoubleDouble::div(den_dd, num_dd); + + // Simple error bound: |1 / den_dd| < 2^(1 + floor(-log2(den_dd)))). + let den_inv = ((E_BIAS + 1) << (52 + 1)) - (den_dd.hi.to_bits() & EXP_MASK); + // For tan_x = (num_dd + err) / (den_dd + err), the error is bounded by: + // | tan_x - num_dd / den_dd | <= err * ( 1 + | tan_x * den_dd | ). + let tan_err = err * f_fmla(f64::from_bits(den_inv), cot_x.hi.abs(), 1.0); + + let err_higher = cot_x.lo + tan_err; + let err_lower = cot_x.lo - tan_err; + + let tan_upper = cot_x.hi + err_higher; + let tan_lower = cot_x.hi + err_lower; + + // Ziv_s rounding test. + if tan_upper == tan_lower { + return tan_upper; + } + + cot_accurate(y, tan_k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cot_test() { + assert_eq!(f_cot(2.3006805685393681E-308), 4.346539948546049e307); + assert_eq!(f_cot(5070552515158872000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.), 25.068466719883585); + assert_eq!(f_cot(4.9406564584124654E-324), f64::INFINITY); + assert_eq!(f_cot(0.0), f64::INFINITY); + assert_eq!(f_cot(1.0), 0.6420926159343308); + assert_eq!(f_cot(-0.5), -1.830487721712452); + assert_eq!(f_cot(12.0), -1.5726734063976893); + assert_eq!(f_cot(-12.0), 1.5726734063976893); + assert!(f_cot(f64::INFINITY).is_nan()); + assert!(f_cot(f64::NEG_INFINITY).is_nan()); + assert!(f_cot(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; + +/// Computes cotangent +/// +/// Max found ULP 0.4999999 +#[inline] +pub fn f_cotf(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| < pi/32 + if x_abs <= 0x3dc9_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + if x_abs == 0 { + return 1. / x; + } + + // When |x| < 2^-12, the relative error of the approximation cot(x) + // is: + let ddx = x as f64; + let dx = 1. / ddx; + // taylor order 3 + return f_fmla(ddx, f64::from_bits(0xbfd5555555555555), dx) as f32; + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_cotf = x/tan(x); + Q = fpminimax(f_cotf, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/32]); + + See ./notes/cotf.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0xbfd5555555555466), + f64::from_bits(0xbf96c16c16fb8937), + f64::from_bits(0xbf6156688756cd43), + f64::from_bits(0xbf2bce669d7cd742), + ); + return (p / xd) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // For |x| >= pi/32, we use the definition of cot(x) function: + // cot(a+b) = (1 - tan(a)tan(b)) / (tan(a) + tan(b)) + // tanf_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + let rs = crate::tangent::evalf::tanf_eval(xd, x_abs); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f_fmla(rs.tan_y, -rs.tan_k, 1.); + (den / num) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cotf_test() { + assert_eq!(f_cotf(0.0010348097), 966.36084); + assert_eq!(f_cotf(0.0020286469), 492.93872); + assert_eq!(f_cotf(-0.0020286469), -492.93872); + assert_eq!(f_cotf(1.0020286469), 0.63923126); + assert_eq!(f_cotf(-1.0020286469), -0.63923126); + assert_eq!(f_cotf(0.0), f32::INFINITY); + assert_eq!(f_cotf(-0.0), f32::NEG_INFINITY); + assert!(f_cotf(f32::INFINITY).is_nan()); + assert!(f_cotf(f32::NEG_INFINITY).is_nan()); + assert!(f_cotf(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::sincospi::{GenSinCosPiBackend, SinCosPiBackend, reduce_pi_64}; +use crate::tangent::tanpi::tanpi_eval; +use crate::tangent::tanpi_table::TANPI_K_PI_OVER_64; + +#[cold] +fn cotpi_hard(x: f64, tan_k: DoubleDouble) -> DoubleDouble { + const C: [(u64, u64); 6] = [ + (0x3ca1a62632712fc8, 0x400921fb54442d18), + (0xbcc052338fbb4528, 0x4024abbce625be53), + (0x3ced42454c5f85b3, 0x404466bc6775aad9), + (0xbd00c7d6a971a560, 0x40645fff9b4b244d), + (0x3d205970eff53274, 0x40845f46e96c3a0b), + (0xbd3589489ad24fc4, 0x40a4630551cd123d), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut tan_y = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[5]), + DoubleDouble::from_bit_pair(C[4]), + ); + tan_y = DoubleDouble::quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[3])); + tan_y = DoubleDouble::quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[2])); + tan_y = DoubleDouble::quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[1])); + tan_y = DoubleDouble::quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[0])); + tan_y = DoubleDouble::quick_mult_f64(tan_y, x); + + // num = tan(y*pi/64) + tan(k*pi/64) + let num = DoubleDouble::full_dd_add(tan_y, tan_k); + // den = 1 - tan(y*pi/64)*tan(k*pi/64) + let den = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + // cot = den / num + DoubleDouble::div(den, num) +} + +#[inline(always)] +fn cotpi_gen_impl(x: f64, backend: B) -> f64 { + if x == 0. { + return if x.is_sign_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + }; + } + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + if ax >= (0x7ffu64 << 52) { + // NaN, Inf + if ax > (0x7ffu64 << 52) { + return x + x; + } // NaN + return f64::NAN; // x=Inf + } + let e: i32 = (ax >> 52) as i32 - 1023; + if e > 0 { + if e >= 52 { + // when |x| > 2^53 it's always an integer + return f64::copysign(f64::INFINITY, x); + } + // |x| > 1 and |x| < 2^53 + let m = (ax & ((1u64 << 52) - 1)) | (1u64 << 52); // mantissa with hidden 1 + let shift = 52 - e; + + let frac = m & ((1u64 << shift) - 1); + if frac == (1u64 << (shift - 1)) { + // |x| is always integer.5 means it's inf + return f64::copysign(0., x); + } + } + + if ax <= 0x3cb0000000000000 { + // for tiny x ( |x| < f64::EPSILON ) just small taylor expansion + // cot(PI*x) ~ 1/(PI*x) + O(x^3) + const ONE_OVER_PI: DoubleDouble = + DoubleDouble::from_bit_pair((0xbc76b01ec5417056, 0x3fd45f306dc9c883)); + if ax <= 0x3ca0000000000000 { + // |x| <= 2^-53, renormalize value + let e: i32 = (ax >> 52) as i32; + let sc = f64::from_bits((2045i64 - e as i64).wrapping_shl(52) as u64); + let dx = x * sc; + let q0 = backend.quick_mult(ONE_OVER_PI, DoubleDouble::from_quick_recip(dx)); + let r = q0.to_f64() * sc; + return r; + } + let q0 = backend.quick_mult(ONE_OVER_PI, DoubleDouble::from_quick_recip(x)); + let r = q0.to_f64(); + return r; + } + + // argument reduction + let (y, k) = backend.arg_reduce_pi_64(x); + + if y == 0.0 { + let km = (k.abs() & 63) as i32; // k mod 64 + + match km { + 0 => return f64::copysign(f64::INFINITY, x), // cotpi(n) = 0 + 32 => return f64::copysign(0., x), // cotpi(n+0.5) = ±∞ + 16 => return f64::copysign(1.0, x), // cotpi(n+0.25) = ±1 + 48 => return -f64::copysign(1.0, x), // cotpi(n+0.75) = ∓1 + _ => {} + } + } + + let tan_k = DoubleDouble::from_bit_pair(TANPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + + // Computes tan(pi*x) through identities + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y*pi/64) + tan(k*pi/64)) / (1 - tan(y*pi/64)*tan(k*pi/64)) + let tan_y = tanpi_eval(y, &backend); + // num = tan(y*pi/64) + tan(k*pi/64) + let num = DoubleDouble::add(tan_k, tan_y); + // den = 1 - tan(y*pi/64)*tan(k*pi/64) + let den = backend.mul_add_f64(tan_y, -tan_k, 1.); + // cot = den / num + let tan_value = backend.div(den, num); + + let err = backend.fma( + tan_value.hi, + f64::from_bits(0x3bf0000000000000), // 2^-64 + f64::from_bits(0x3b60000000000000), // 2^-73 + ); + let ub = tan_value.hi + (tan_value.lo + err); + let lb = tan_value.hi + (tan_value.lo - err); + if ub == lb { + return tan_value.to_f64(); + } + cotpi_hard(y, tan_k).to_f64() +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn cotpi_fma_impl(x: f64) -> f64 { + use crate::sincospi::FmaSinCosPiBackend; + cotpi_gen_impl(x, FmaSinCosPiBackend {}) +} + +/// Computes cotangent 1/tan(PI*x) +/// +/// ulp 0.5 +pub fn f_cotpi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + cotpi_gen_impl(x, GenSinCosPiBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + cotpi_fma_impl + } else { + fn def_cotpi(x: f64) -> f64 { + cotpi_gen_impl(x, GenSinCosPiBackend {}) + } + def_cotpi + } + }); + unsafe { q(x) } + } +} + +#[inline] +pub(crate) fn cotpi_core(x: f64) -> DoubleDouble { + // argument reduction + let (y, k) = reduce_pi_64(x); + + let tan_k = DoubleDouble::from_bit_pair(TANPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + + // Computes tan(pi*x) through identities. + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y*pi/64) + tan(k*pi/64)) / (1 - tan(y*pi/64)*tan(k*pi/64)) + let tan_y = tanpi_eval(y, &GenSinCosPiBackend {}); + // num = tan(y*pi/64) + tan(k*pi/64) + let num = DoubleDouble::add(tan_k, tan_y); + // den = 1 - tan(y*pi/64)*tan(k*pi/64) + let den = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + // cot = den / num + DoubleDouble::div(den, num) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_cotpi() { + assert_eq!(f_cotpi(3.382112265043898e-306), 9.411570676518013e304); + assert_eq!(f_cotpi(0.0431431231), 7.332763436038805); + assert_eq!(f_cotpi(-0.0431431231), -7.332763436038805); + assert_eq!(f_cotpi(0.52324), -0.07314061937774036); + assert!(f_cotpi(f64::INFINITY).is_nan()); + assert!(f_cotpi(f64::NAN).is_nan()); + assert!(f_cotpi(f64::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/cotpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/cotpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +use crate::common::f_fmla; +use crate::sin_cosf::ArgumentReducerPi; +use crate::tangent::evalf::tanpif_eval; + +/// Computes 1/tan(PI*x) +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_cotpif(x: f32) -> f32 { + let ix = x.to_bits(); + let e = ix & (0xff << 23); + if e > (150 << 23) { + // |x| > 2^23 + if e == (0xff << 23) { + // x = nan or inf + if (ix.wrapping_shl(9)) == 0 { + // x = inf + return f32::NAN; + } + return x + x; // x = nan + } + return f32::INFINITY; + } + + let argument_reduction = ArgumentReducerPi { x: x as f64 }; + + let (y, k) = argument_reduction.reduce(); + + if y == 0.0 { + let km = (k.abs() & 31) as i32; // k mod 32 + + match km { + 0 => return f32::copysign(f32::INFINITY, x), // cotpi(n) = ∞ + 16 => return 0.0f32.copysign(x), // cotpi(n+0.5) = 0 + 8 => return f32::copysign(1.0, x), // cotpi(n+0.25) = 1 + 24 => return -f32::copysign(1.0, x), // cotpi(n+0.75) = -1 + _ => {} + } + } + + let ax = ix & 0x7fff_ffff; + if ax < 0x3bc49ba6u32 { + // taylor series for cot(PI*x) where |x| < 0.006 + let dx = x as f64; + let dx_sqr = dx * dx; + // cot(PI*x) ~ 1/(PI*x) - PI*x/3 - PI^3*x^3/45 + O(x^5) + const ONE_OVER_PI: f64 = f64::from_bits(0x3fd45f306dc9c883); + let r = f_fmla( + dx_sqr, + f64::from_bits(0xbfe60c8539c1dc14), + f64::from_bits(0xbff0c152382d7366), + ); + let rcp = 1. / dx; + return f_fmla(rcp, ONE_OVER_PI, r * dx) as f32; + } + + // tanpif_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + let rs = tanpif_eval(y, k); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f_fmla(rs.tan_y, -rs.tan_k, 1.); + // cotangent is tangent in inverse order + (den / num) as f32 +} + +#[inline] +pub(crate) fn cotpif_core(x: f64) -> f64 { + let argument_reduction = ArgumentReducerPi { x }; + + let (y, k) = argument_reduction.reduce(); + + // tanpif_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + let rs = tanpif_eval(y, k); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f_fmla(rs.tan_y, -rs.tan_k, 1.); + // cotangent is tangent in inverse order + den / num +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_cotpif() { + assert_eq!(f_cotpif(0.00046277765), 687.82416); + assert_eq!(f_cotpif(2.3588752e-6), 134941.39); + assert_eq!(f_cotpif(10775313000000000000000000000000.), f32::INFINITY); + assert_eq!(f_cotpif(5.5625), -0.19891237); + assert_eq!(f_cotpif(-29.75), 1.0); + assert_eq!(f_cotpif(-21.5625), 0.19891237); + assert_eq!(f_cotpif(-15.611655), 0.3659073); + assert_eq!(f_cotpif(115.30706), 0.693186); + assert_eq!(f_cotpif(0.), f32::INFINITY); + assert!(f_cotpif(f32::INFINITY).is_nan()); + assert!(f_cotpif(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/evalf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/evalf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/evalf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/evalf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::polyeval::f_polyeval4; +use crate::sin_cosf::ArgumentReducer; + +// Generated in SageMath: +// print("[") +// for k in range(64): +// k = RealField(150)(k) * RealField(150).pi() / RealField(150)(32) +// print(double_to_hex(k.tan()) + ",") +// print("];") +pub(crate) static TAN_K_PI_OVER32: [u64; 64] = [ + 0x0000000000000000, + 0x3fb936bb8c5b2da2, + 0x3fc975f5e0553158, + 0x3fd36a08355c63dc, + 0x3fda827999fcef32, + 0x3fe11ab7190834ec, + 0x3fe561b82ab7f990, + 0x3fea43002ae42850, + 0x3ff0000000000000, + 0x3ff37efd8d87607e, + 0x3ff7f218e25a7461, + 0x3ffdef13b73c1406, + 0x4003504f333f9de6, + 0x400a5f59e90600dd, + 0x40141bfee2424771, + 0x40244e6c595afdcc, + 0xc950457bf6be49c7, + 0xc0244e6c595afdcc, + 0xc0141bfee2424771, + 0xc00a5f59e90600dd, + 0xc003504f333f9de6, + 0xbffdef13b73c1406, + 0xbff7f218e25a7461, + 0xbff37efd8d87607e, + 0xbff0000000000000, + 0xbfea43002ae42850, + 0xbfe561b82ab7f990, + 0xbfe11ab7190834ec, + 0xbfda827999fcef32, + 0xbfd36a08355c63dc, + 0xbfc975f5e0553158, + 0xbfb936bb8c5b2da2, + 0x369f77598338bfdf, + 0x3fb936bb8c5b2da2, + 0x3fc975f5e0553158, + 0x3fd36a08355c63dc, + 0x3fda827999fcef32, + 0x3fe11ab7190834ec, + 0x3fe561b82ab7f990, + 0x3fea43002ae42850, + 0x3ff0000000000000, + 0x3ff37efd8d87607e, + 0x3ff7f218e25a7461, + 0x3ffdef13b73c1406, + 0x4003504f333f9de6, + 0x400a5f59e90600dd, + 0x40141bfee2424771, + 0x40244e6c595afdcc, + 0xc935b1fa9e530d0a, + 0xc0244e6c595afdcc, + 0xc0141bfee2424771, + 0xc00a5f59e90600dd, + 0xc003504f333f9de6, + 0xbffdef13b73c1406, + 0xbff7f218e25a7461, + 0xbff37efd8d87607e, + 0xbff0000000000000, + 0xbfea43002ae42850, + 0xbfe561b82ab7f990, + 0xbfe11ab7190834ec, + 0xbfda827999fcef32, + 0xbfd36a08355c63dc, + 0xbfc975f5e0553158, + 0xbfb936bb8c5b2da2, +]; + +pub(crate) struct TanfEval { + pub(crate) tan_k: f64, + pub(crate) tan_y: f64, +} + +#[inline] +pub(crate) fn tanpif_eval(y: f64, k: i64) -> TanfEval { + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + + // picking minus sin and cos according to quadrant + let tan_k = f64::from_bits(TAN_K_PI_OVER32[((k as u64) & 63) as usize]); + + // tan(x*pi/32) generated by Sollya: + // d = [0, 0.5]; + // f_tan = tan(y*pi/32)/y; + // Q = fpminimax(f_tan, [|0, 2, 4, 6|], [|D...|], d, relative, floating); + // See ./notes/tanpif.sollya + let tan_y = f_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442cef), + f64::from_bits(0x3f34abbce63a363e), + f64::from_bits(0x3eb466baced705e8), + f64::from_bits(0x3e346a33cde88184), + ) * y; + TanfEval { tan_y, tan_k } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn tanpif_eval_fma(y: f64, k: i64) -> TanfEval { + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + + // picking minus sin and cos according to quadrant + let tan_k = f64::from_bits(TAN_K_PI_OVER32[((k as u64) & 63) as usize]); + + // tan(x*pi/32) generated by Sollya: + // d = [0, 0.5]; + // f_tan = tan(y*pi/32)/y; + // Q = fpminimax(f_tan, [|0, 2, 4, 6|], [|D...|], d, relative, floating); + // See ./notes/tanpif.sollya + use crate::polyeval::d_polyeval4; + let tan_y = d_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442cef), + f64::from_bits(0x3f34abbce63a363e), + f64::from_bits(0x3eb466baced705e8), + f64::from_bits(0x3e346a33cde88184), + ) * y; + TanfEval { tan_y, tan_k } +} + +#[inline(always)] +pub(crate) fn tanf_eval(x: f64, x_abs: u32) -> TanfEval { + let (y, k) = ArgumentReducer { x, x_abs }.reduce(); + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + + // picking minus sin and cos according to quadrant + let tan_k = f64::from_bits(TAN_K_PI_OVER32[(k & 63) as usize]); + + // tan(x*pi/32) generated by Sollya: + // d = [0, 0.5]; + // f_tan = tan(x*pi/32)/x; + // Q = fpminimax(f_tan, [|0, 2, 4, 6|], [|D...|], d); + // See ./notes/tanf.sollya + let tan_y = f_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442cef), + f64::from_bits(0x3f34abbce63a363e), + f64::from_bits(0x3eb466baced705e8), + f64::from_bits(0x3e346a33cde88184), + ) * y; + TanfEval { tan_y, tan_k } +} + +#[inline(always)] +#[allow(unused)] +pub(crate) fn tanf_eval_fma(x: f64, x_abs: u32) -> TanfEval { + let (y, k) = ArgumentReducer { x, x_abs }.reduce_fma(); + let y_sqr = y * y; + + // After range reduction, k = round(x * 32 / pi) and y = (x * 32 / pi) - k. + // So k is an integer and -0.5 <= y <= 0.5. + + // picking minus sin and cos according to quadrant + let tan_k = f64::from_bits(TAN_K_PI_OVER32[(k & 63) as usize]); + + // tan(x*pi/32) generated by Sollya: + // d = [0, 0.5]; + // f_tan = tan(x*pi/32)/x; + // Q = fpminimax(f_tan, [|0, 2, 4, 6|], [|D...|], d); + // See ./notes/tanf.sollya + use crate::polyeval::d_polyeval4; + let tan_y = d_polyeval4( + y_sqr, + f64::from_bits(0x3fb921fb54442cef), + f64::from_bits(0x3f34abbce63a363e), + f64::from_bits(0x3eb466baced705e8), + f64::from_bits(0x3e346a33cde88184), + ) * y; + TanfEval { tan_y, tan_k } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod atan; +mod atan2; +mod atan2f; +mod atan2pi; +mod atan2pif; +mod atanf; +mod atanpi; +mod atanpif; +mod cot; +mod cotf; +mod cotpi; +mod cotpif; +mod evalf; +mod tan; +mod tanf; +mod tanpi; +mod tanpi_table; +mod tanpif; + +pub use atan::f_atan; +pub use atan2::f_atan2; +pub use atan2f::f_atan2f; +pub use atan2pi::f_atan2pi; +pub use atan2pif::f_atan2pif; +pub use atanf::f_atanf; +pub use atanpi::f_atanpi; +pub use atanpif::f_atanpif; +pub use cot::f_cot; +pub use cotf::f_cotf; +pub(crate) use cotpi::cotpi_core; +pub use cotpi::f_cotpi; +pub(crate) use cotpif::cotpif_core; +pub use cotpif::f_cotpif; +pub use tan::f_tan; +pub use tanf::f_tanf; +pub use tanpi::f_tanpi; +pub use tanpif::f_tanpif; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tan.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tan.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tan.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tan.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,279 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::bits::EXP_MASK; +use crate::common::{dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use crate::sin::range_reduction_small; +use crate::sincos_reduce::LargeArgumentReduction; +use crate::tangent::tanpi_table::TAN_K_PI_OVER_128; + +#[inline] +pub(crate) fn tan_eval(u: DoubleDouble) -> (DoubleDouble, f64) { + // Evaluate tan(y) = tan(x - k * (pi/128)) + // We use the degree-9 Taylor approximation: + // tan(y) ~ P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835 + // Then the error is bounded by: + // |tan(y) - P(y)| < 2^-6 * |y|^11 < 2^-6 * 2^-66 = 2^-72. + // For y ~ u_hi + u_lo, fully expanding the polynomial and drop any terms + // < ulp(u_hi^3) gives us: + // P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835 = ... + // ~ u_hi + u_hi^3 * (1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 + + // + u_hi^2 * 62/2835))) + + // + u_lo (1 + u_hi^2 * (1 + u_hi^2 * 2/3)) + let u_hi_sq = u.hi * u.hi; // Error < ulp(u_hi^2) < 2^(-6 - 52) = 2^-58. + // p1 ~ 17/315 + u_hi^2 62 / 2835. + let p1 = f_fmla( + u_hi_sq, + f64::from_bits(0x3f9664f4882c10fa), + f64::from_bits(0x3faba1ba1ba1ba1c), + ); + // p2 ~ 1/3 + u_hi^2 2 / 15. + let p2 = f_fmla( + u_hi_sq, + f64::from_bits(0x3fc1111111111111), + f64::from_bits(0x3fd5555555555555), + ); + // q1 ~ 1 + u_hi^2 * 2/3. + let q1 = f_fmla(u_hi_sq, f64::from_bits(0x3fe5555555555555), 1.0); + let u_hi_3 = u_hi_sq * u.hi; + let u_hi_4 = u_hi_sq * u_hi_sq; + // p3 ~ 1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 + u_hi^2 * 62/2835)) + let p3 = f_fmla(u_hi_4, p1, p2); + // q2 ~ 1 + u_hi^2 * (1 + u_hi^2 * 2/3) + let q2 = f_fmla(u_hi_sq, q1, 1.0); + let tan_lo = f_fmla(u_hi_3, p3, u.lo * q2); + // Overall, |tan(y) - (u_hi + tan_lo)| < ulp(u_hi^3) <= 2^-71. + // And the relative errors is: + // |(tan(y) - (u_hi + tan_lo)) / tan(y) | <= 2*ulp(u_hi^2) < 2^-64 + let err = f_fmla( + u_hi_3.abs(), + f64::from_bits(0x3cc0000000000000), + f64::from_bits(0x3990000000000000), + ); + (DoubleDouble::from_exact_add(u.hi, tan_lo), err) +} + +#[inline] +pub(crate) fn tan_eval_dd(x: DoubleDouble) -> DoubleDouble { + // Generated by Sollya: + // d = [0, pi/128]; + // f_tan = tan(x)/x; + // Q = fpminimax(f_tan, [|0, 2, 4, 6, 8, 10, 12|], [|107...|], d); + const C: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c75555549d35a4b, 0x3fd5555555555555), + (0x3c413dd6ea580288, 0x3fc1111111111111), + (0x3c4e100b946f0c89, 0x3faba1ba1ba1b9fe), + (0xbc3c180dfac2b8c3, 0x3f9664f488307189), + (0x3c1fd691c256a14a, 0x3f8226e300c1988e), + (0x3bec7b08c90fdfc0, 0x3f6d739baeacd204), + ]; + let x2 = DoubleDouble::quick_mult(x, x); + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[6]), + DoubleDouble::from_bit_pair(C[5]), + ); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::quick_mul_add_f64(x2, p, f64::from_bits(0x3ff0000000000000)); + let r = DoubleDouble::quick_mult(p, x); + DoubleDouble::from_exact_add(r.hi, r.lo) +} + +#[cold] +fn tan_accurate(y: DoubleDouble, tan_k: DoubleDouble) -> f64 { + // Computes tan(x) through identities + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y) + tan(k*pi/128)) / (1 - tan(y)*tan(k*pi/128)) + let tan_y = tan_eval_dd(y); + + // num = tan(y) + tan(k*pi/64) + let num_dd = DoubleDouble::full_dd_add(tan_y, tan_k); + // den = 1 - tan(y)*tan(k*pi/64) + let den_dd = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + + let tan_x = DoubleDouble::div(num_dd, den_dd); + tan_x.to_f64() +} + +#[cold] +fn tan_near_zero_hard(x: f64) -> DoubleDouble { + // Generated by Sollya: + // d = [0, 0.03125]; + // f_tan = tan(x)/x; + // Q = fpminimax(f_tan, [|0, 2, 4, 6, 8, 10, 12|], [|1, 107...|], d); + const C: [(u64, u64); 7] = [ + (0x0000000000000000, 0x3ff0000000000000), + (0x3c7555548455da94, 0x3fd5555555555555), + (0x3c4306a6358cc810, 0x3fc1111111111111), + (0x3c2ca9cd025ea98c, 0x3faba1ba1ba1b952), + (0x3c3cb012803c55a5, 0x3f9664f4883eb962), + (0x3c28afc1adb8f202, 0x3f8226e276097461), + (0xbbdf8f911392f348, 0x3f6d7791601277ea), + ]; + let x2 = DoubleDouble::from_exact_mult(x, x); + let mut p = DoubleDouble::quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[6]), + DoubleDouble::from_bit_pair(C[5]), + ); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[4])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[3])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[2])); + p = DoubleDouble::quick_mul_add(x2, p, DoubleDouble::from_bit_pair(C[1])); + p = DoubleDouble::quick_mul_add_f64(x2, p, f64::from_bits(0x3ff0000000000000)); + DoubleDouble::quick_mult_f64(p, x) +} + +/// Tangent in double precision +/// +/// ULP 0.5 +pub fn f_tan(x: f64) -> f64 { + let x_e = (x.to_bits() >> 52) & 0x7ff; + const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64; + + let y: DoubleDouble; + let k; + + let mut argument_reduction = LargeArgumentReduction::default(); + + if x_e < E_BIAS + 16 { + // |x| < 2^16 + if x_e < E_BIAS - 5 { + // |x| < 2^-5 + if x_e < E_BIAS - 27 { + // |x| < 2^-27, |tan(x) - x| < ulp(x)/2. + if x == 0.0 { + // Signed zeros. + return x + x; + } + return dyad_fmla(x, f64::from_bits(0x3c90000000000000), x); + } + let x2 = x * x; + let x4 = x2 * x2; + // Generated by Sollya: + // d = [0, 0.03125]; + // f_tan = tan(x)/x; + // Q = fpminimax(f_tan, [|0, 2, 4, 6, 8|], [|D...|], d); + const C: [u64; 4] = [ + 0x3fd555555555554b, + 0x3fc1111111142d5b, + 0x3faba1b9860ed843, + 0x3f966a802210f5bb, + ]; + let p01 = f_fmla(x2, f64::from_bits(C[1]), f64::from_bits(C[0])); + let p23 = f_fmla(x2, f64::from_bits(C[3]), f64::from_bits(C[2])); + let w0 = f_fmla(x4, p23, p01); + let w1 = x2 * w0 * x; + let r = DoubleDouble::from_exact_add(x, w1); + let err = f_fmla( + x2, + f64::from_bits(0x3cb0000000000000), // 2^-52 + f64::from_bits(0x3be0000000000000), // 2^-65 + ); + let ub = r.hi + (r.lo + err); + let lb = r.hi + (r.lo - err); + if ub == lb { + return ub; + } + return tan_near_zero_hard(x).to_f64(); + } else { + // Small range reduction. + (y, k) = range_reduction_small(x); + } + } else { + // Inf or NaN + if x_e > 2 * E_BIAS { + if x.is_nan() { + return f64::NAN; + } + // tan(+-Inf) = NaN + return x + f64::NAN; + } + + // Large range reduction. + (k, y) = argument_reduction.reduce(x); + } + + let (tan_y, err) = tan_eval(y); + + // Computes tan(x) through identities. + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y) + tan(k*pi/128)) / (1 - tan(y)*tan(k*pi/128)) + let tan_k = DoubleDouble::from_bit_pair(TAN_K_PI_OVER_128[(k & 255) as usize]); + + // num = tan(y) + tan(k*pi/64) + let num_dd = DoubleDouble::add(tan_y, tan_k); + // den = 1 - tan(y)*tan(k*pi/64) + let den_dd = DoubleDouble::mul_add_f64(tan_y, -tan_k, 1.); + + let tan_x = DoubleDouble::div(num_dd, den_dd); + + // Simple error bound: |1 / den_dd| < 2^(1 + floor(-log2(den_dd)))). + let den_inv = ((E_BIAS + 1) << (52 + 1)) - (den_dd.hi.to_bits() & EXP_MASK); + // For tan_x = (num_dd + err) / (den_dd + err), the error is bounded by: + // | tan_x - num_dd / den_dd | <= err * ( 1 + | tan_x * den_dd | ). + let tan_err = err * f_fmla(f64::from_bits(den_inv), tan_x.hi.abs(), 1.0); + + let err_higher = tan_x.lo + tan_err; + let err_lower = tan_x.lo - tan_err; + + let tan_upper = tan_x.hi + err_higher; + let tan_lower = tan_x.hi + err_lower; + + // Ziv_s rounding test. + if tan_upper == tan_lower { + return tan_upper; + } + + tan_accurate(y, tan_k) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tan_test() { + assert_eq!(f_tan(0.0003242153424), 0.0003242153537600293); + assert_eq!(f_tan(-0.3242153424), -0.3360742441422686); + assert_eq!(f_tan(0.3242153424), 0.3360742441422686); + assert_eq!(f_tan(-97301943219974110.), 0.000000000000000481917514979303); + assert_eq!(f_tan(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007291122019556397), + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007291122019556397); + assert_eq!(f_tan(0.0), 0.0); + assert_eq!(f_tan(0.4324324324), 0.4615683710506729); + assert_eq!(f_tan(1.0), 1.5574077246549023); + assert_eq!(f_tan(-0.5), -0.5463024898437905); + assert!(f_tan(f64::INFINITY).is_nan()); + assert!(f_tan(f64::NEG_INFINITY).is_nan()); + assert!(f_tan(f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,216 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::polyeval::f_polyeval5; +use crate::tangent::evalf::tanf_eval; + +#[inline(always)] +fn tanf_gen_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| < pi/32 + if x_abs <= 0x3dc9_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + if x_abs == 0 { + return x; + } + + // When |x| < 2^-12, the relative error of the approximation tan(x) ~ x + // is: + // |tan(x) - x| / |tan(x)| < |x^3| / (3|x|) + // = x^2 / 3 + // < 2^-25 + // < epsilon(1)/2. + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmlaf; + return f_fmlaf(x, f32::from_bits(0xb3000000), x); + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + return f_fmla(xd, f64::from_bits(0xbe60000000000000), xd) as f32; + } + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_tan = tan(x)/x; + Q = fpminimax(f_tan, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/32]); + + See ./notes/tanf_at_zero.sollya + */ + let p = f_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3fd555555553d022), + f64::from_bits(0x3fc111111ce442c1), + f64::from_bits(0x3faba180a6bbdecd), + f64::from_bits(0x3f969c0a88a0b71f), + ); + return (xd * p) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // For |x| >= pi/32, we use the definition of tan(x) function: + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) + // tanf_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + let rs = tanf_eval(xd, x_abs); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f_fmla(rs.tan_y, -rs.tan_k, 1.); + (num / den) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn tanf_fma_impl(x: f32) -> f32 { + let x_abs = x.to_bits() & 0x7fff_ffffu32; + let xd = x as f64; + + // |x| < pi/32 + if x_abs <= 0x3dc9_0fdbu32 { + // |x| < 0.000244141 + if x_abs < 0x3980_0000u32 { + if x_abs == 0 { + return x; + } + + // When |x| < 2^-12, the relative error of the approximation tan(x) ~ x + // is: + // |tan(x) - x| / |tan(x)| < |x^3| / (3|x|) + // = x^2 / 3 + // < 2^-25 + // < epsilon(1)/2. + return f32::mul_add(x, f32::from_bits(0xb3000000), x); + } + + let xsqr = xd * xd; + + /* + Generated by Sollya: + f_tan = tan(x)/x; + Q = fpminimax(f_tan, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/32]); + + See ./notes/tanf_at_zero.sollya + */ + use crate::polyeval::d_polyeval5; + let p = d_polyeval5( + xsqr, + f64::from_bits(0x3ff0000000000000), + f64::from_bits(0x3fd555555553d022), + f64::from_bits(0x3fc111111ce442c1), + f64::from_bits(0x3faba180a6bbdecd), + f64::from_bits(0x3f969c0a88a0b71f), + ); + return (xd * p) as f32; + } + + if x_abs >= 0x7f80_0000u32 { + return x + f32::NAN; + } + + // For |x| >= pi/32, we use the definition of tan(x) function: + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) + // tanf_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + use crate::tangent::evalf::tanf_eval_fma; + let rs = tanf_eval_fma(xd, x_abs); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f64::mul_add(rs.tan_y, -rs.tan_k, 1.); + (num / den) as f32 +} + +/// Computes tan +/// +/// Max found ULP 0.4999999 +#[inline] +pub fn f_tanf(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + tanf_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + tanf_fma_impl + } else { + tanf_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn f_tanf_test() { + assert_eq!(f_tanf(0.0), 0.0); + assert_eq!(f_tanf(1.0), 1.5574077); + assert_eq!(f_tanf(-1.0), -1.5574077); + assert_eq!(f_tanf(10.0), 0.64836085); + assert_eq!(f_tanf(-10.0), -0.64836085); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; +use crate::sincospi::{GenSinCosPiBackend, SinCosPiBackend}; +use crate::tangent::tanpi_table::TANPI_K_PI_OVER_64; + +#[inline] +pub(crate) fn tanpi_eval(x: f64, backend: &B) -> DoubleDouble { + let x2 = DoubleDouble::from_exact_mult(x, x); + // tan(pi*x) generated by Sollya: + // d = [0, 0.0078128]; + // f_tan = tan(y*pi)/y; + // Q = fpminimax(f_tan, [|0, 2, 4, 6, 8|], [|107, D...|], d, relative, floating); + const C: [u64; 4] = [ + 0x4024abbce625be51, + 0x404466bc677698e5, + 0x40645fff70379ae3, + 0x4084626b091b7fd0, + ]; + const C0: DoubleDouble = DoubleDouble::from_bit_pair((0x3ca1a6444aa5b996, 0x400921fb54442d18)); + + // polyeval 4, estrin scheme + let u0 = backend.fma(x2.hi, f64::from_bits(C[1]), f64::from_bits(C[0])); + let u1 = backend.fma(x2.hi, f64::from_bits(C[3]), f64::from_bits(C[2])); + let tan_poly_lo = backend.fma(x2.hi * x2.hi, u1, u0); + + // We're splitting polynomial in two parts, since first term dominates + // we compute: (a0_lo + a0_hi) * x + x * (a1 * x^2 + a2 + x^4) ... + let r_lo = backend.quick_mult_f64(x2, tan_poly_lo); + let tan_lo = backend.fma(r_lo.lo, x, r_lo.hi * x); + let tan_hi = backend.quick_mult_f64(C0, x); + DoubleDouble::full_add_f64(tan_hi, tan_lo) +} + +#[cold] +fn tanpi_hard(x: f64, tan_k: DoubleDouble, backend: &B) -> DoubleDouble { + const C: [(u64, u64); 6] = [ + (0x3ca1a62632712fc8, 0x400921fb54442d18), + (0xbcc052338fbb4528, 0x4024abbce625be53), + (0x3ced42454c5f85b3, 0x404466bc6775aad9), + (0xbd00c7d6a971a560, 0x40645fff9b4b244d), + (0x3d205970eff53274, 0x40845f46e96c3a0b), + (0xbd3589489ad24fc4, 0x40a4630551cd123d), + ]; + let x2 = backend.exact_mult(x, x); + let mut tan_y = backend.quick_mul_add( + x2, + DoubleDouble::from_bit_pair(C[5]), + DoubleDouble::from_bit_pair(C[4]), + ); + tan_y = backend.quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[3])); + tan_y = backend.quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[2])); + tan_y = backend.quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[1])); + tan_y = backend.quick_mul_add(x2, tan_y, DoubleDouble::from_bit_pair(C[0])); + tan_y = backend.quick_mult_f64(tan_y, x); + + // num = tan(y*pi/64) + tan(k*pi/64) + let num = DoubleDouble::full_dd_add(tan_y, tan_k); + // den = 1 - tan(y*pi/64)*tan(k*pi/64) + let den = backend.mul_add_f64(tan_y, -tan_k, 1.); + // tan = num / den + backend.div(num, den) +} + +#[inline(always)] +fn tanpi_gen_impl(x: f64, backend: B) -> f64 { + if x == 0. { + return x; + } + let ax = x.to_bits() & 0x7fff_ffff_ffff_ffff; + if ax >= (0x7ffu64 << 52) { + // NaN, Inf + if ax > (0x7ffu64 << 52) { + return x + x; + } // NaN + return f64::NAN; // x=Inf + } + let e: i32 = (ax >> 52) as i32 - 1023; + if e > 0 { + if e >= 52 { + // when |x| > 2^53 it's always an integer + return f64::copysign(0., x); + } + // |x| > 1 and |x| < 2^53 + let m = (ax & ((1u64 << 52) - 1)) | (1u64 << 52); // mantissa with hidden 1 + let shift = 52 - e; + + let frac = m & ((1u64 << shift) - 1); + if frac == (1u64 << (shift - 1)) { + // |x| is always integer.5 means it's inf + return f64::INFINITY; + } + } + + if ax <= 0x3cb0000000000000 { + // for tiny x ( |x| < f64::EPSILON ) just small taylor expansion + // tan(PI*x) ~ PI*x + PI^3*x^3/3 + O(x^5) + const PI: DoubleDouble = + DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); + if ax <= 0x3ca0000000000000 { + // |x| <= 2^-53, renormalize value + let e: i32 = (ax >> 52) as i32; + let sc = f64::from_bits((2045i64 - e as i64).wrapping_shl(52) as u64); + let isc = f64::from_bits(1i64.wrapping_add(e as i64).wrapping_shl(52) as u64); + let dx = x * sc; + let q0 = backend.quick_mult_f64(PI, dx); + let r = q0.to_f64() * isc; + return r; + } + let q0 = backend.quick_mult_f64(PI, x); + let r = q0.to_f64(); + return r; + } + + // argument reduction + let (y, k) = backend.arg_reduce_pi_64(x); + + if y == 0.0 { + let km = (k.abs() & 63) as i32; // k mod 64 + + match km { + 0 => return f64::copysign(0f64, x), // tanpi(n) = 0 + 32 => return f64::copysign(f64::INFINITY, x), // tanpi(n+0.5) = ±∞ + 16 => return f64::copysign(1.0, x), // tanpi(n+0.25) = ±1 + 48 => return -f64::copysign(1.0, x), // tanpi(n+0.75) = ∓1 + _ => {} + } + } + + let tan_k = DoubleDouble::from_bit_pair(TANPI_K_PI_OVER_64[((k as u64) & 127) as usize]); + + // Computes tan(pi*x) through identities. + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a)tan(b)) = (tan(y*pi/64) + tan(k*pi/64)) / (1 - tan(y*pi/64)*tan(k*pi/64)) + let tan_y = tanpi_eval(y, &backend); + // num = tan(y*pi/64) + tan(k*pi/64) + let num = DoubleDouble::add(tan_k, tan_y); + // den = 1 - tan(y*pi/64)*tan(k*pi/64) + let den = backend.mul_add_f64(tan_y, -tan_k, 1.); + // tan = num / den + let tan_value = backend.div(num, den); + let err = backend.fma( + tan_value.hi, + f64::from_bits(0x3bf0000000000000), // 2^-64 + f64::from_bits(0x3b60000000000000), // 2^-73 + ); + let ub = tan_value.hi + (tan_value.lo + err); + let lb = tan_value.hi + (tan_value.lo - err); + if ub == lb { + return tan_value.to_f64(); + } + tanpi_hard(y, tan_k, &backend).to_f64() +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn tanpi_fma_impl(x: f64) -> f64 { + use crate::sincospi::FmaSinCosPiBackend; + tanpi_gen_impl(x, FmaSinCosPiBackend {}) +} + +/// Computes tan(PI*x) +/// +/// Max found ULP 0.5 +pub fn f_tanpi(x: f64) -> f64 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + tanpi_gen_impl(x, GenSinCosPiBackend {}) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f64> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + tanpi_fma_impl + } else { + fn def_tanpi(x: f64) -> f64 { + tanpi_gen_impl(x, GenSinCosPiBackend {}) + } + def_tanpi + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tanpi() { + assert_eq!(f_tanpi(0.4999999999119535), 3615246871.564404); + assert_eq!(f_tanpi(7119681148991743.0), 0.); + assert_eq!(f_tanpi(63.5), f64::INFINITY); + assert_eq!(f_tanpi(63.99935913085936), -0.0020133525045719896); + assert_eq!(f_tanpi(3.3821122649309461E-306), 1.0625219045122997E-305); + assert_eq!(f_tanpi(1.8010707049867402E-255), 5.6582304953821333E-255); + assert_eq!(f_tanpi(1.001000000061801), 0.0031416031832113213); + assert_eq!(f_tanpi(-0.5000000000000226), 14054316517702.594); + assert_eq!(f_tanpi(0.5000000000000001), -2867080569611329.5); + assert_eq!(f_tanpi(0.02131), 0.06704753721009375); + assert!(f_tanpi(f64::INFINITY).is_nan()); + assert!(f_tanpi(f64::NAN).is_nan()); + assert!(f_tanpi(f64::NEG_INFINITY).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi_table.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi_table.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi_table.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpi_table.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,430 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Generated by SageMath: +// print("[") +// for k in range(128): +// k = RealField(150)(k) * RealField(150).pi() / RealField(150)(64) +// print_double_double("", k.tan()) +// print("];") +pub(crate) static TANPI_K_PI_OVER_64: [(u64, u64); 128] = [ + (0x0000000000000000, 0x0000000000000000), + (0x3bfada13ceebab9d, 0x3fa927278a3b1162), + (0x3c587d054f689d7a, 0x3fb936bb8c5b2da2), + (0x3c52cfb5a746f62c, 0x3fc2fcac73a60640), + (0x3c2ef5d367441946, 0x3fc975f5e0553158), + (0x3c65a6d6c3c8b6a7, 0x3fd007fa758626ae), + (0xbc6d704d1bfdb6e8, 0x3fd36a08355c63dc), + (0x3c678e945dc3913c, 0x3fd6e649f7d78649), + (0x3c708b2fb1366ea9, 0x3fda827999fcef32), + (0x3c741522f15e53c5, 0x3fde450e0d273e7a), + (0xbc8e564bcd1e635d, 0x3fe11ab7190834ec), + (0xbc810b4421e6a4f8, 0x3fe32e1889047ffd), + (0x3c87a8c52172b675, 0x3fe561b82ab7f990), + (0xbc8aa7538e44e996, 0x3fe7bb99ed2990cf), + (0xbc7a6db80fe796fe, 0x3fea43002ae42850), + (0x3c78dcad85e60fbe, 0x3fed00cbc7384d2e), + (0x0000000000000000, 0x3ff0000000000000), + (0x3c9946cc0b66979f, 0x3ff1a73d55278c4b), + (0xbc787e5ad9735569, 0x3ff37efd8d87607e), + (0x3c86a085e3bc3af6, 0x3ff592d11142fa55), + (0x3c9419fa6954928f, 0x3ff7f218e25a7461), + (0xbc7b6fb77846d763, 0x3ffab1c35d8a74ea), + (0x3c80fb3e75c7098e, 0x3ffdef13b73c1406), + (0x3c97ce6cb463c972, 0x4000ea21d716fbf7), + (0x3ca21165f626cdd5, 0x4003504f333f9de6), + (0x3c7aca947bfb1dcc, 0x40065bc6cc825147), + (0xbc9b7a14d0d691be, 0x400a5f59e90600dd), + (0xbc889fcd637fbf3b, 0x400ff01305ecd8dc), + (0x3c810706fed37f0e, 0x40141bfee2424771), + (0xbcaae397239c5a0d, 0x401af73f4ca3310f), + (0x3cc351daea79411d, 0x40244e6c595afdcc), + (0xbc7b6e6b4de0cd24, 0x40345affed201b55), + (0xc5f4a74167598ceb, 0xc950457bf6be49c7), + (0x3c7b6e6b4de0cd24, 0xc0345affed201b55), + (0xbcc351daea79411d, 0xc0244e6c595afdcc), + (0x3caae397239c5a0d, 0xc01af73f4ca3310f), + (0xbc810706fed37f0e, 0xc0141bfee2424771), + (0x3c889fcd637fbf3b, 0xc00ff01305ecd8dc), + (0x3c9b7a14d0d691be, 0xc00a5f59e90600dd), + (0xbc7aca947bfb1dcc, 0xc0065bc6cc825147), + (0xbca21165f626cdd5, 0xc003504f333f9de6), + (0xbc97ce6cb463c972, 0xc000ea21d716fbf7), + (0xbc80fb3e75c7098e, 0xbffdef13b73c1406), + (0x3c7b6fb77846d763, 0xbffab1c35d8a74ea), + (0xbc9419fa6954928f, 0xbff7f218e25a7461), + (0xbc86a085e3bc3af6, 0xbff592d11142fa55), + (0x3c787e5ad9735569, 0xbff37efd8d87607e), + (0xbc9946cc0b66979f, 0xbff1a73d55278c4b), + (0x36a8000000000000, 0xbff0000000000000), + (0xbc78dcad85e60fbe, 0xbfed00cbc7384d2e), + (0x3c7a6db80fe796fe, 0xbfea43002ae42850), + (0x3c8aa7538e44e996, 0xbfe7bb99ed2990cf), + (0xbc87a8c52172b675, 0xbfe561b82ab7f990), + (0x3c810b4421e6a4f8, 0xbfe32e1889047ffd), + (0x3c8e564bcd1e635d, 0xbfe11ab7190834ec), + (0xbc741522f15e53c5, 0xbfde450e0d273e7a), + (0xbc708b2fb1366ea9, 0xbfda827999fcef32), + (0xbc678e945dc3913c, 0xbfd6e649f7d78649), + (0x3c6d704d1bfdb6e8, 0xbfd36a08355c63dc), + (0xbc65a6d6c3c8b6a7, 0xbfd007fa758626ae), + (0xbc2ef5d367441946, 0xbfc975f5e0553158), + (0xbc52cfb5a746f62c, 0xbfc2fcac73a60640), + (0xbc587d054f689d7a, 0xbfb936bb8c5b2da2), + (0xbbfada13ceebab9d, 0xbfa927278a3b1162), + (0x3331056713b19377, 0x369f77598338bfdf), + (0x3bfada13ceebab9d, 0x3fa927278a3b1162), + (0x3c587d054f689d7a, 0x3fb936bb8c5b2da2), + (0x3c52cfb5a746f62c, 0x3fc2fcac73a60640), + (0x3c2ef5d367441946, 0x3fc975f5e0553158), + (0x3c65a6d6c3c8b6a7, 0x3fd007fa758626ae), + (0xbc6d704d1bfdb6e8, 0x3fd36a08355c63dc), + (0x3c678e945dc3913c, 0x3fd6e649f7d78649), + (0x3c708b2fb1366ea9, 0x3fda827999fcef32), + (0x3c741522f15e53c5, 0x3fde450e0d273e7a), + (0xbc8e564bcd1e635d, 0x3fe11ab7190834ec), + (0xbc810b4421e6a4f8, 0x3fe32e1889047ffd), + (0x3c87a8c52172b675, 0x3fe561b82ab7f990), + (0xbc8aa7538e44e996, 0x3fe7bb99ed2990cf), + (0xbc7a6db80fe796fe, 0x3fea43002ae42850), + (0x3c78dcad85e60fbe, 0x3fed00cbc7384d2e), + (0x36b0000000000000, 0x3ff0000000000000), + (0x3c9946cc0b66979f, 0x3ff1a73d55278c4b), + (0xbc787e5ad9735569, 0x3ff37efd8d87607e), + (0x3c86a085e3bc3af6, 0x3ff592d11142fa55), + (0x3c9419fa6954928f, 0x3ff7f218e25a7461), + (0xbc7b6fb77846d763, 0x3ffab1c35d8a74ea), + (0x3c80fb3e75c7098e, 0x3ffdef13b73c1406), + (0x3c97ce6cb463c972, 0x4000ea21d716fbf7), + (0x3ca21165f626cdd5, 0x4003504f333f9de6), + (0x3c7aca947bfb1dcc, 0x40065bc6cc825147), + (0xbc9b7a14d0d691be, 0x400a5f59e90600dd), + (0xbc889fcd637fbf3b, 0x400ff01305ecd8dc), + (0x3c810706fed37f0e, 0x40141bfee2424771), + (0xbcaae397239c5a0d, 0x401af73f4ca3310f), + (0x3cc351daea79411d, 0x40244e6c595afdcc), + (0xbc7b6e6b4de0cd24, 0x40345affed201b55), + (0x45ce41fc41bbdd8e, 0xc935b1fa9e530d0a), + (0x3c7b6e6b4de0cd24, 0xc0345affed201b55), + (0xbcc351daea79411d, 0xc0244e6c595afdcc), + (0x3caae397239c5a0d, 0xc01af73f4ca3310f), + (0xbc810706fed37f0e, 0xc0141bfee2424771), + (0x3c889fcd637fbf3b, 0xc00ff01305ecd8dc), + (0x3c9b7a14d0d691be, 0xc00a5f59e90600dd), + (0xbc7aca947bfb1dcc, 0xc0065bc6cc825147), + (0xbca21165f626cdd5, 0xc003504f333f9de6), + (0xbc97ce6cb463c972, 0xc000ea21d716fbf7), + (0xbc80fb3e75c7098e, 0xbffdef13b73c1406), + (0x3c7b6fb77846d763, 0xbffab1c35d8a74ea), + (0xbc9419fa6954928f, 0xbff7f218e25a7461), + (0xbc86a085e3bc3af6, 0xbff592d11142fa55), + (0x3c787e5ad9735569, 0xbff37efd8d87607e), + (0xbc9946cc0b66979f, 0xbff1a73d55278c4b), + (0x36ce000000000000, 0xbff0000000000000), + (0xbc78dcad85e60fbe, 0xbfed00cbc7384d2e), + (0x3c7a6db80fe796fe, 0xbfea43002ae42850), + (0x3c8aa7538e44e996, 0xbfe7bb99ed2990cf), + (0xbc87a8c52172b675, 0xbfe561b82ab7f990), + (0x3c810b4421e6a4f8, 0xbfe32e1889047ffd), + (0x3c8e564bcd1e635d, 0xbfe11ab7190834ec), + (0xbc741522f15e53c5, 0xbfde450e0d273e7a), + (0xbc708b2fb1366ea9, 0xbfda827999fcef32), + (0xbc678e945dc3913c, 0xbfd6e649f7d78649), + (0x3c6d704d1bfdb6e8, 0xbfd36a08355c63dc), + (0xbc65a6d6c3c8b6a7, 0xbfd007fa758626ae), + (0xbc2ef5d367441946, 0xbfc975f5e0553158), + (0xbc52cfb5a746f62c, 0xbfc2fcac73a60640), + (0xbc587d054f689d7a, 0xbfb936bb8c5b2da2), + (0xbbfada13ceebab9d, 0xbfa927278a3b1162), +]; + +// Generated by Sollya: +// print("[") +// for k in range(256): +// k = RealField(150)(k) * RealField(150).pi() / RealField(150)(128) +// print_double_double("", k.tan()) +// print("];") +pub(crate) static TAN_K_PI_OVER_128: [(u64, u64); 256] = [ + (0x0000000000000000, 0x0000000000000000), + (0xbbf13b5915a8e316, 0x3f992346247a91f0), + (0x3bfada13ceebab9d, 0x3fa927278a3b1162), + (0x3c587a2cb08f812c, 0x3fb2e239ccff3831), + (0x3c587d054f689d7a, 0x3fb936bb8c5b2da2), + (0xbc412206d2ac3013, 0x3fbf93183a8db9e9), + (0x3c52cfb5a746f62c, 0x3fc2fcac73a60640), + (0xbc59debab5988b6b, 0x3fc635c990ce0d36), + (0x3c2ef5d367441946, 0x3fc975f5e0553158), + (0x3c64a5be32c624f4, 0x3fccbe4ceb4b4cf2), + (0x3c65a6d6c3c8b6a7, 0x3fd007fa758626ae), + (0x3c6cbda4f63658a0, 0x3fd1b6103d3597e9), + (0xbc6d704d1bfdb6e8, 0x3fd36a08355c63dc), + (0x3c7be976387851c1, 0x3fd5248ae1701b17), + (0x3c678e945dc3913c, 0x3fd6e649f7d78649), + (0xbc67327a64e1229d, 0x3fd8b00196b3d022), + (0x3c708b2fb1366ea9, 0x3fda827999fcef32), + (0x3c4ff57fa14eec2f, 0x3fdc5e87185e67b6), + (0x3c741522f15e53c5, 0x3fde450e0d273e7a), + (0x3c80bfceebbe8797, 0x3fe01b819b5a7cf7), + (0xbc8e564bcd1e635d, 0x3fe11ab7190834ec), + (0x3c5aed6fb930f332, 0x3fe220b5ef047825), + (0xbc810b4421e6a4f8, 0x3fe32e1889047ffd), + (0xbc8a7d457cee5076, 0x3fe44386db9ce5db), + (0x3c87a8c52172b675, 0x3fe561b82ab7f990), + (0x3c7439bc2d43ebfc, 0x3fe6897514751db6), + (0xbc8aa7538e44e996, 0x3fe7bb99ed2990cf), + (0xbc778bf71a952738, 0x3fe8f9197bf85eeb), + (0xbc7a6db80fe796fe, 0x3fea43002ae42850), + (0x3c76fc7e578d57ab, 0x3feb9a77c18c1af2), + (0x3c78dcad85e60fbe, 0x3fed00cbc7384d2e), + (0x3c8915eabb7f20cb, 0x3fee776eafc91706), + (0x0000000000000000, 0x3ff0000000000000), + (0x3c94986267a7063b, 0x3ff0ce29d0883c99), + (0x3c9946cc0b66979f, 0x3ff1a73d55278c4b), + (0x3c80322c95986960, 0x3ff28c66fdaf8f09), + (0xbc787e5ad9735569, 0x3ff37efd8d87607e), + (0x3c9f86b7ea4ce3dc, 0x3ff48089f8bf42cc), + (0x3c86a085e3bc3af6, 0x3ff592d11142fa55), + (0xbc950debdd3e20b2, 0x3ff6b7df86265200), + (0x3c9419fa6954928f, 0x3ff7f218e25a7461), + (0x3c9ccbeeba3801a8, 0x3ff9444a7462122a), + (0xbc7b6fb77846d763, 0x3ffab1c35d8a74ea), + (0x3c90a392d9ac6a3b, 0x3ffc3e738086bc0f), + (0x3c80fb3e75c7098e, 0x3ffdef13b73c1406), + (0x3c8b7127cf34b46c, 0x3fffc95abad6cf4a), + (0x3c97ce6cb463c972, 0x4000ea21d716fbf7), + (0xbc9291fd400280bf, 0x40020c36c6a7f38e), + (0x3ca21165f626cdd5, 0x4003504f333f9de6), + (0xbca82c5b9ae77a8b, 0x4004bd3d87fe0650), + (0x3c7aca947bfb1dcc, 0x40065bc6cc825147), + (0x3c8b35c6e3b49ecd, 0x400837626d70fdb8), + (0xbc9b7a14d0d691be, 0x400a5f59e90600dd), + (0x3c777f638a8d7d8a, 0x400ce885653127e7), + (0xbc889fcd637fbf3b, 0x400ff01305ecd8dc), + (0xbcaee737686fd43e, 0x4011d0143e71565f), + (0x3c810706fed37f0e, 0x40141bfee2424771), + (0xbcb10e285b56fe74, 0x40170d751908c1b1), + (0xbcaae397239c5a0d, 0x401af73f4ca3310f), + (0xbcbd4a376685482f, 0x4020372fb36b87e2), + (0x3cc351daea79411d, 0x40244e6c595afdcc), + (0x3cb67e518f25e3f8, 0x402b1d03c03d2f7f), + (0xbc7b6e6b4de0cd24, 0x40345affed201b55), + (0x3cde2447b82ca2f3, 0x40445e2455e4aaa7), + (0xc5f4a74167598ceb, 0xc950457bf6be49c7), + (0xbcde2447b82ca2f3, 0xc0445e2455e4aaa7), + (0x3c7b6e6b4de0cd24, 0xc0345affed201b55), + (0xbcb67e518f25e3f8, 0xc02b1d03c03d2f7f), + (0xbcc351daea79411d, 0xc0244e6c595afdcc), + (0x3cbd4a376685482f, 0xc020372fb36b87e2), + (0x3caae397239c5a0d, 0xc01af73f4ca3310f), + (0x3cb10e285b56fe74, 0xc0170d751908c1b1), + (0xbc810706fed37f0e, 0xc0141bfee2424771), + (0x3caee737686fd43e, 0xc011d0143e71565f), + (0x3c889fcd637fbf3b, 0xc00ff01305ecd8dc), + (0xbc777f638a8d7d8a, 0xc00ce885653127e7), + (0x3c9b7a14d0d691be, 0xc00a5f59e90600dd), + (0xbc8b35c6e3b49ecd, 0xc00837626d70fdb8), + (0xbc7aca947bfb1dcc, 0xc0065bc6cc825147), + (0x3ca82c5b9ae77a8b, 0xc004bd3d87fe0650), + (0xbca21165f626cdd5, 0xc003504f333f9de6), + (0x3c9291fd400280bf, 0xc0020c36c6a7f38e), + (0xbc97ce6cb463c972, 0xc000ea21d716fbf7), + (0xbc8b7127cf34b46c, 0xbfffc95abad6cf4a), + (0xbc80fb3e75c7098e, 0xbffdef13b73c1406), + (0xbc90a392d9ac6a3b, 0xbffc3e738086bc0f), + (0x3c7b6fb77846d763, 0xbffab1c35d8a74ea), + (0xbc9ccbeeba3801a8, 0xbff9444a7462122a), + (0xbc9419fa6954928f, 0xbff7f218e25a7461), + (0x3c950debdd3e20b2, 0xbff6b7df86265200), + (0xbc86a085e3bc3af6, 0xbff592d11142fa55), + (0xbc9f86b7ea4ce3dc, 0xbff48089f8bf42cc), + (0x3c787e5ad9735569, 0xbff37efd8d87607e), + (0xbc80322c95986960, 0xbff28c66fdaf8f09), + (0xbc9946cc0b66979f, 0xbff1a73d55278c4b), + (0xbc94986267a7063b, 0xbff0ce29d0883c99), + (0x36a8000000000000, 0xbff0000000000000), + (0xbc8915eabb7f20cb, 0xbfee776eafc91706), + (0xbc78dcad85e60fbe, 0xbfed00cbc7384d2e), + (0xbc76fc7e578d57ab, 0xbfeb9a77c18c1af2), + (0x3c7a6db80fe796fe, 0xbfea43002ae42850), + (0x3c778bf71a952738, 0xbfe8f9197bf85eeb), + (0x3c8aa7538e44e996, 0xbfe7bb99ed2990cf), + (0xbc7439bc2d43ebfc, 0xbfe6897514751db6), + (0xbc87a8c52172b675, 0xbfe561b82ab7f990), + (0x3c8a7d457cee5076, 0xbfe44386db9ce5db), + (0x3c810b4421e6a4f8, 0xbfe32e1889047ffd), + (0xbc5aed6fb930f332, 0xbfe220b5ef047825), + (0x3c8e564bcd1e635d, 0xbfe11ab7190834ec), + (0xbc80bfceebbe8797, 0xbfe01b819b5a7cf7), + (0xbc741522f15e53c5, 0xbfde450e0d273e7a), + (0xbc4ff57fa14eec2f, 0xbfdc5e87185e67b6), + (0xbc708b2fb1366ea9, 0xbfda827999fcef32), + (0x3c67327a64e1229d, 0xbfd8b00196b3d022), + (0xbc678e945dc3913c, 0xbfd6e649f7d78649), + (0xbc7be976387851c1, 0xbfd5248ae1701b17), + (0x3c6d704d1bfdb6e8, 0xbfd36a08355c63dc), + (0xbc6cbda4f63658a0, 0xbfd1b6103d3597e9), + (0xbc65a6d6c3c8b6a7, 0xbfd007fa758626ae), + (0xbc64a5be32c624f4, 0xbfccbe4ceb4b4cf2), + (0xbc2ef5d367441946, 0xbfc975f5e0553158), + (0x3c59debab5988b6b, 0xbfc635c990ce0d36), + (0xbc52cfb5a746f62c, 0xbfc2fcac73a60640), + (0x3c412206d2ac3013, 0xbfbf93183a8db9e9), + (0xbc587d054f689d7a, 0xbfb936bb8c5b2da2), + (0xbc587a2cb08f812c, 0xbfb2e239ccff3831), + (0xbbfada13ceebab9d, 0xbfa927278a3b1162), + (0x3bf13b5915a8e316, 0xbf992346247a91f0), + (0x3331056713b19377, 0x369f77598338bfdf), + (0xbbf13b5915a8e316, 0x3f992346247a91f0), + (0x3bfada13ceebab9d, 0x3fa927278a3b1162), + (0x3c587a2cb08f812c, 0x3fb2e239ccff3831), + (0x3c587d054f689d7a, 0x3fb936bb8c5b2da2), + (0xbc412206d2ac3013, 0x3fbf93183a8db9e9), + (0x3c52cfb5a746f62c, 0x3fc2fcac73a60640), + (0xbc59debab5988b6b, 0x3fc635c990ce0d36), + (0x3c2ef5d367441946, 0x3fc975f5e0553158), + (0x3c64a5be32c624f4, 0x3fccbe4ceb4b4cf2), + (0x3c65a6d6c3c8b6a7, 0x3fd007fa758626ae), + (0x3c6cbda4f63658a0, 0x3fd1b6103d3597e9), + (0xbc6d704d1bfdb6e8, 0x3fd36a08355c63dc), + (0x3c7be976387851c1, 0x3fd5248ae1701b17), + (0x3c678e945dc3913c, 0x3fd6e649f7d78649), + (0xbc67327a64e1229d, 0x3fd8b00196b3d022), + (0x3c708b2fb1366ea9, 0x3fda827999fcef32), + (0x3c4ff57fa14eec2f, 0x3fdc5e87185e67b6), + (0x3c741522f15e53c5, 0x3fde450e0d273e7a), + (0x3c80bfceebbe8797, 0x3fe01b819b5a7cf7), + (0xbc8e564bcd1e635d, 0x3fe11ab7190834ec), + (0x3c5aed6fb930f332, 0x3fe220b5ef047825), + (0xbc810b4421e6a4f8, 0x3fe32e1889047ffd), + (0xbc8a7d457cee5076, 0x3fe44386db9ce5db), + (0x3c87a8c52172b675, 0x3fe561b82ab7f990), + (0x3c7439bc2d43ebfc, 0x3fe6897514751db6), + (0xbc8aa7538e44e996, 0x3fe7bb99ed2990cf), + (0xbc778bf71a952738, 0x3fe8f9197bf85eeb), + (0xbc7a6db80fe796fe, 0x3fea43002ae42850), + (0x3c76fc7e578d57ab, 0x3feb9a77c18c1af2), + (0x3c78dcad85e60fbe, 0x3fed00cbc7384d2e), + (0x3c8915eabb7f20cb, 0x3fee776eafc91706), + (0x36b0000000000000, 0x3ff0000000000000), + (0x3c94986267a7063b, 0x3ff0ce29d0883c99), + (0x3c9946cc0b66979f, 0x3ff1a73d55278c4b), + (0x3c80322c95986960, 0x3ff28c66fdaf8f09), + (0xbc787e5ad9735569, 0x3ff37efd8d87607e), + (0x3c9f86b7ea4ce3dc, 0x3ff48089f8bf42cc), + (0x3c86a085e3bc3af6, 0x3ff592d11142fa55), + (0xbc950debdd3e20b2, 0x3ff6b7df86265200), + (0x3c9419fa6954928f, 0x3ff7f218e25a7461), + (0x3c9ccbeeba3801a8, 0x3ff9444a7462122a), + (0xbc7b6fb77846d763, 0x3ffab1c35d8a74ea), + (0x3c90a392d9ac6a3b, 0x3ffc3e738086bc0f), + (0x3c80fb3e75c7098e, 0x3ffdef13b73c1406), + (0x3c8b7127cf34b46c, 0x3fffc95abad6cf4a), + (0x3c97ce6cb463c972, 0x4000ea21d716fbf7), + (0xbc9291fd400280bf, 0x40020c36c6a7f38e), + (0x3ca21165f626cdd5, 0x4003504f333f9de6), + (0xbca82c5b9ae77a8b, 0x4004bd3d87fe0650), + (0x3c7aca947bfb1dcc, 0x40065bc6cc825147), + (0x3c8b35c6e3b49ecd, 0x400837626d70fdb8), + (0xbc9b7a14d0d691be, 0x400a5f59e90600dd), + (0x3c777f638a8d7d8a, 0x400ce885653127e7), + (0xbc889fcd637fbf3b, 0x400ff01305ecd8dc), + (0xbcaee737686fd43e, 0x4011d0143e71565f), + (0x3c810706fed37f0e, 0x40141bfee2424771), + (0xbcb10e285b56fe74, 0x40170d751908c1b1), + (0xbcaae397239c5a0d, 0x401af73f4ca3310f), + (0xbcbd4a376685482f, 0x4020372fb36b87e2), + (0x3cc351daea79411d, 0x40244e6c595afdcc), + (0x3cb67e518f25e3f8, 0x402b1d03c03d2f7f), + (0xbc7b6e6b4de0cd24, 0x40345affed201b55), + (0x3cde2447b82ca2f3, 0x40445e2455e4aaa7), + (0x45ce41fc41bbdd8e, 0xc935b1fa9e530d0a), + (0xbcde2447b82ca2f3, 0xc0445e2455e4aaa7), + (0x3c7b6e6b4de0cd24, 0xc0345affed201b55), + (0xbcb67e518f25e3f8, 0xc02b1d03c03d2f7f), + (0xbcc351daea79411d, 0xc0244e6c595afdcc), + (0x3cbd4a376685482f, 0xc020372fb36b87e2), + (0x3caae397239c5a0d, 0xc01af73f4ca3310f), + (0x3cb10e285b56fe74, 0xc0170d751908c1b1), + (0xbc810706fed37f0e, 0xc0141bfee2424771), + (0x3caee737686fd43e, 0xc011d0143e71565f), + (0x3c889fcd637fbf3b, 0xc00ff01305ecd8dc), + (0xbc777f638a8d7d8a, 0xc00ce885653127e7), + (0x3c9b7a14d0d691be, 0xc00a5f59e90600dd), + (0xbc8b35c6e3b49ecd, 0xc00837626d70fdb8), + (0xbc7aca947bfb1dcc, 0xc0065bc6cc825147), + (0x3ca82c5b9ae77a8b, 0xc004bd3d87fe0650), + (0xbca21165f626cdd5, 0xc003504f333f9de6), + (0x3c9291fd400280bf, 0xc0020c36c6a7f38e), + (0xbc97ce6cb463c972, 0xc000ea21d716fbf7), + (0xbc8b7127cf34b46c, 0xbfffc95abad6cf4a), + (0xbc80fb3e75c7098e, 0xbffdef13b73c1406), + (0xbc90a392d9ac6a3b, 0xbffc3e738086bc0f), + (0x3c7b6fb77846d763, 0xbffab1c35d8a74ea), + (0xbc9ccbeeba3801a8, 0xbff9444a7462122a), + (0xbc9419fa6954928f, 0xbff7f218e25a7461), + (0x3c950debdd3e20b2, 0xbff6b7df86265200), + (0xbc86a085e3bc3af6, 0xbff592d11142fa55), + (0xbc9f86b7ea4ce3dc, 0xbff48089f8bf42cc), + (0x3c787e5ad9735569, 0xbff37efd8d87607e), + (0xbc80322c95986960, 0xbff28c66fdaf8f09), + (0xbc9946cc0b66979f, 0xbff1a73d55278c4b), + (0xbc94986267a7063b, 0xbff0ce29d0883c99), + (0x36ce000000000000, 0xbff0000000000000), + (0xbc8915eabb7f20cb, 0xbfee776eafc91706), + (0xbc78dcad85e60fbe, 0xbfed00cbc7384d2e), + (0xbc76fc7e578d57ab, 0xbfeb9a77c18c1af2), + (0x3c7a6db80fe796fe, 0xbfea43002ae42850), + (0x3c778bf71a952738, 0xbfe8f9197bf85eeb), + (0x3c8aa7538e44e996, 0xbfe7bb99ed2990cf), + (0xbc7439bc2d43ebfc, 0xbfe6897514751db6), + (0xbc87a8c52172b675, 0xbfe561b82ab7f990), + (0x3c8a7d457cee5076, 0xbfe44386db9ce5db), + (0x3c810b4421e6a4f8, 0xbfe32e1889047ffd), + (0xbc5aed6fb930f332, 0xbfe220b5ef047825), + (0x3c8e564bcd1e635d, 0xbfe11ab7190834ec), + (0xbc80bfceebbe8797, 0xbfe01b819b5a7cf7), + (0xbc741522f15e53c5, 0xbfde450e0d273e7a), + (0xbc4ff57fa14eec2f, 0xbfdc5e87185e67b6), + (0xbc708b2fb1366ea9, 0xbfda827999fcef32), + (0x3c67327a64e1229d, 0xbfd8b00196b3d022), + (0xbc678e945dc3913c, 0xbfd6e649f7d78649), + (0xbc7be976387851c1, 0xbfd5248ae1701b17), + (0x3c6d704d1bfdb6e8, 0xbfd36a08355c63dc), + (0xbc6cbda4f63658a0, 0xbfd1b6103d3597e9), + (0xbc65a6d6c3c8b6a7, 0xbfd007fa758626ae), + (0xbc64a5be32c624f4, 0xbfccbe4ceb4b4cf2), + (0xbc2ef5d367441946, 0xbfc975f5e0553158), + (0x3c59debab5988b6b, 0xbfc635c990ce0d36), + (0xbc52cfb5a746f62c, 0xbfc2fcac73a60640), + (0x3c412206d2ac3013, 0xbfbf93183a8db9e9), + (0xbc587d054f689d7a, 0xbfb936bb8c5b2da2), + (0xbc587a2cb08f812c, 0xbfb2e239ccff3831), + (0xbbfada13ceebab9d, 0xbfa927278a3b1162), + (0x3bf13b5915a8e316, 0xbf992346247a91f0), +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpif.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpif.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/tangent/tanpif.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/tangent/tanpif.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 6/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::sin_cosf::ArgumentReducerPi; +use crate::tangent::evalf::tanpif_eval; + +#[inline(always)] +fn tanpif_gen_impl(x: f32) -> f32 { + let ix = x.to_bits(); + let e = ix & (0xff << 23); + if e > (150 << 23) { + // |x| > 2^23 + if e == (0xff << 23) { + // x = nan or inf + if (ix.wrapping_shl(9)) == 0 { + // x = inf + return f32::NAN; + } + return x + x; // x = nan + } + return f32::copysign(0.0, x); + } + + let argument_reduction = ArgumentReducerPi { x: x as f64 }; + + let (y, k) = argument_reduction.reduce(); + + if y == 0.0 { + let km = (k.abs() & 31) as i32; // k mod 32 + + match km { + 0 => return 0.0f32.copysign(x), // tanpi(n) = 0 + 16 => return f32::copysign(f32::INFINITY, x), // tanpi(n+0.5) = ±∞ + 8 => return f32::copysign(1.0, x), // tanpi(n+0.25) = ±1 + 24 => return -f32::copysign(1.0, x), // tanpi(n+0.75) = ∓1 + _ => {} + } + } + + let ax = ix & 0x7fff_ffff; + if ax < 0x38d1b717u32 { + // taylor series for tan(PI*x) where |x| < 0.0001 + let dx = x as f64; + let dx_sqr = dx * dx; + // tan(PI*x) ~ PI*x + PI^3*x^3/3 + O(x^5) + let r = f_fmla( + dx_sqr, + f64::from_bits(0x4024abbce625be53), + f64::from_bits(0x400921fb54442d18), + ); + return (r * dx) as f32; + } + + // tanpif_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + let rs = tanpif_eval(y, k); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f_fmla(rs.tan_y, -rs.tan_k, 1.); + (num / den) as f32 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx", enable = "fma")] +unsafe fn tanpif_fma_impl(x: f32) -> f32 { + let ix = x.to_bits(); + let e = ix & (0xff << 23); + if e > (150 << 23) { + // |x| > 2^23 + if e == (0xff << 23) { + // x = nan or inf + if (ix.wrapping_shl(9)) == 0 { + // x = inf + return f32::NAN; + } + return x + x; // x = nan + } + return f32::copysign(0.0, x); + } + + let argument_reduction = ArgumentReducerPi { x: x as f64 }; + + let (y, k) = argument_reduction.reduce_fma(); + + if y == 0.0 { + let km = (k.abs() & 31) as i32; // k mod 32 + + match km { + 0 => return 0.0f32.copysign(x), // tanpi(n) = 0 + 16 => return f32::copysign(f32::INFINITY, x), // tanpi(n+0.5) = ±∞ + 8 => return f32::copysign(1.0, x), // tanpi(n+0.25) = ±1 + 24 => return -f32::copysign(1.0, x), // tanpi(n+0.75) = ∓1 + _ => {} + } + } + + let ax = ix & 0x7fff_ffff; + if ax < 0x38d1b717u32 { + // taylor series for tan(PI*x) where |x| < 0.0001 + let dx = x as f64; + let dx_sqr = dx * dx; + // tan(PI*x) ~ PI*x + PI^3*x^3/3 + O(x^5) + let r = f64::mul_add( + dx_sqr, + f64::from_bits(0x4024abbce625be53), + f64::from_bits(0x400921fb54442d18), + ); + return (r * dx) as f32; + } + + // tanpif_eval returns: + // - rs.tan_y = tan(pi/32 * y) -> tangent of the remainder + // - rs.tan_k = tan(pi/32 * k) -> tan of the main angle multiple + use crate::tangent::evalf::tanpif_eval_fma; + let rs = tanpif_eval_fma(y, k); + + // Then computing tan through identities + // num = tan(k*pi/32) + tan(y*pi/32) + let num = rs.tan_y + rs.tan_k; + // den = 1 - tan(k*pi/32) * tan(y*pi/32) + let den = f64::mul_add(rs.tan_y, -rs.tan_k, 1.); + (num / den) as f32 +} + +/// Computes tan(PI*x) +/// +/// Max found ULP 0.5 +#[inline] +pub fn f_tanpif(x: f32) -> f32 { + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + tanpif_gen_impl(x) + } + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use std::sync::OnceLock; + static EXECUTOR: OnceLock f32> = OnceLock::new(); + let q = EXECUTOR.get_or_init(|| { + if std::arch::is_x86_feature_detected!("avx") + && std::arch::is_x86_feature_detected!("fma") + { + tanpif_fma_impl + } else { + tanpif_gen_impl + } + }); + unsafe { q(x) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tanpif() { + assert_eq!(f_tanpif(3.666738e-5), 0.00011519398); + assert_eq!(f_tanpif(1.0355987e-25), 3.2534293e-25); + assert_eq!(f_tanpif(5.5625), -5.0273395); + assert_eq!(f_tanpif(-29.75), 1.0); + assert_eq!(f_tanpif(-21.5625), 5.0273395); + assert_eq!(f_tanpif(-15.611655), 2.7329326); + assert_eq!(f_tanpif(115.30706), 1.4426143); + assert!(f_tanpif(f32::INFINITY).is_nan()); + assert!(f_tanpif(f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/cathetus.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetus.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/cathetus.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetus.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::double_double::DoubleDouble; + +/// Computes the missing leg of a right triangle +/// +/// Given a hypotenuse `x` and a known leg `y`, returns +/// `sqrt(x^2 - y^2)` = the length of the other leg. +/// +/// Domain: requires `|x| >= |y|`. Returns NaN if the input +/// is outside this range. +pub fn f_cathetus(x: f64, y: f64) -> f64 { + let x_abs = f64::from_bits(x.to_bits() & 0x7fff_ffff_ffff_ffffu64); + let y_abs = f64::from_bits(y.to_bits() & 0x7fff_ffff_ffff_ffffu64); + + let x_bits = x_abs.to_bits(); + let y_bits = y_abs.to_bits(); + + let a_u = x_bits.max(y_bits); + + let mut dx = x; + let mut dy = y; + + const EXP_MASK_F64: u64 = 0x7FF0_0000_0000_0000; + if a_u >= EXP_MASK_F64 { + // x or y is inf or nan + if f64::from_bits(x_bits).is_nan() || f64::from_bits(y_bits).is_nan() { + return f64::NAN; + } + if f64::from_bits(x_bits).is_infinite() || f64::from_bits(y_bits).is_infinite() { + if f64::from_bits(x_bits).is_infinite() && f64::from_bits(y_bits).is_infinite() { + // ∞² - ∞² is undefined + return f64::NAN; + } + return f64::INFINITY; + } + return f64::from_bits(x_bits); + } + if x_abs < y_abs { + // Would yield sqrt(negative), undefined + return f64::NAN; + } + if x_abs == y_abs { + // sqrt(c² - c²) = 0 + return 0.0; + } + + let e_x = x_bits >> 52; + let e_y = y_bits >> 52; + let unbiased_e_x = (e_x as i32).wrapping_sub(1023); + let mut scale = 1f64; + + if e_y == 0 { + if e_x - e_y > 52 { + // y is too small to make difference, so result is just |x| + return x_abs; + } + dx *= f64::from_bits(0x6bb0000000000000); // 2^700 + dy *= f64::from_bits(0x6bb0000000000000); // 2^700 + scale = f64::from_bits(0x1430000000000000); // 2^(-700 / 2) + } else if unbiased_e_x >= 510 { + dx *= f64::from_bits(0x1430000000000000); // 2^-700 + dy *= f64::from_bits(0x1430000000000000); // 2^-700 + scale = f64::from_bits(0x6bb0000000000000); // 2^(700 / 2) + } else if unbiased_e_x <= -450 { + dx *= f64::from_bits(0x6bb0000000000000); // 2^700 + dy *= f64::from_bits(0x6bb0000000000000); // 2^700 + scale = f64::from_bits(0x1430000000000000); // 2^(-700) + } + + let dy2 = DoubleDouble::from_exact_mult(dy, dy); + let dx2 = DoubleDouble::from_exact_mult(dx, dx); + let p = DoubleDouble::sub(dx2, dy2); + let cath = p.fast_sqrt(); // sqrt(x^2 - y^2) + cath.to_f64() * scale +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_cathethus() { + assert_eq!( + f_cathetus(0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002248996583584318, + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002842248694776204), + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002248996583584318 + ); + assert_eq!( + f_cathetus(0.00003241747618121237, 0.00003241747618121195), + 5.219099637789996e-12 + ); + assert_eq!(f_cathetus(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003382112264930946, + -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005284550413954603), + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003381699384228079); + assert_eq!(f_cathetus(5., 3.), 4.); + assert_eq!(f_cathetus(5., 4.), 3.); + assert_eq!(f_cathetus(13., 12.), 5.); + assert_eq!(f_cathetus(65., 16.), 63.); + assert_eq!(f_cathetus(25., 24.), 7.); + assert!(f_cathetus(24., 25.).is_nan()); + } + + #[test] + fn test_cathetus_edge_cases() { + assert_eq!(f_cathetus(0.0, 0.0), 0.0); + assert_eq!(f_cathetus(f64::INFINITY, 0.0), f64::INFINITY); + assert_eq!(f_cathetus(0.0, f64::INFINITY), f64::INFINITY); + assert!(f_cathetus(f64::INFINITY, f64::INFINITY).is_nan()); + assert_eq!(f_cathetus(f64::NEG_INFINITY, 0.0), f64::INFINITY); + assert_eq!(f_cathetus(0.0, f64::NEG_INFINITY), f64::INFINITY); + assert!(f_cathetus(f64::NEG_INFINITY, f64::NEG_INFINITY).is_nan()); + assert!(f_cathetus(f64::NAN, 1.0).is_nan()); + assert!(f_cathetus(1.0, f64::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/cathetusf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetusf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/cathetusf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/cathetusf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::EXP_MASK_F32; + +/// Computes the missing leg of a right triangle +/// +/// Given a hypotenuse `x` and a known leg `y`, returns +/// `sqrt(x^2 - y^2)` = the length of the other leg. +/// +/// Domain: requires `|x| >= |y|`. Returns NaN if the input +/// is outside this range. +pub fn f_cathetusf(x: f32, y: f32) -> f32 { + let x_abs = f32::from_bits(x.to_bits() & 0x7fff_ffffu32); + let y_abs = f32::from_bits(y.to_bits() & 0x7fff_ffffu32); + + let x_bits = x_abs.to_bits(); + let y_bits = y_abs.to_bits(); + + let a_u = x_bits.max(y_bits); + + if a_u >= EXP_MASK_F32 { + // x or y is inf or nan + if f32::from_bits(x_bits).is_nan() || f32::from_bits(y_bits).is_nan() { + return f32::NAN; + } + if f32::from_bits(x_bits).is_infinite() || f32::from_bits(y_bits).is_infinite() { + if f32::from_bits(x_bits).is_infinite() && f32::from_bits(y_bits).is_infinite() { + // ∞² - ∞² is undefined + return f32::NAN; + } + return f32::INFINITY; + } + return f32::from_bits(x_bits); + } + if x_abs < y_abs { + // Would yield sqrt(negative), undefined + return f32::NAN; + } + if x_abs == y_abs { + // sqrt(c² - c²) = 0 + return 0.0; + } + + let dx = x as f64; + let dy = y as f64; + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + use crate::common::f_fmla; + // for FMA environment we're using Kahan style summation which is short and reliable. + let w = dy * dy; // RN(bc) + let e = f_fmla(-dy, dy, w); // RN(w − bc) + let f = f_fmla(dx, dx, -w); // RN(ad − w) + let r = e + f; // RN(f + e) + let cath = r.sqrt(); // sqrt(x^2 - y^2) + cath as f32 + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + use crate::double_double::DoubleDouble; + let dy2 = DoubleDouble::from_exact_mult(dy, dy); + let fdx = DoubleDouble::from_exact_mult(dx, dx); + // element must follow condition |x| > |y| so it always follows fasttwosum requirements + let f = DoubleDouble::add_f64(fdx, -dy2.hi).to_f64(); + let r = dy2.lo + f; + let cath = r.sqrt(); + cath as f32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_cathetusf_edge() { + assert_eq!(f_cathetusf(5., 3.), 4.); + assert_eq!(f_cathetusf(5., 4.), 3.); + assert_eq!(f_cathetusf(13., 12.), 5.); + assert_eq!(f_cathetusf(65., 16.), 63.); + assert_eq!(f_cathetusf(25., 24.), 7.); + assert!(f_cathetusf(24., 25.).is_nan()); + } + + #[test] + fn test_cathetusf_edge_cases() { + assert_eq!(f_cathetusf(0.0, 0.0), 0.0); + assert_eq!(f_cathetusf(f32::INFINITY, 0.0), f32::INFINITY); + assert_eq!(f_cathetusf(0.0, f32::INFINITY), f32::INFINITY); + assert!(f_cathetusf(f32::INFINITY, f32::INFINITY).is_nan()); + assert_eq!(f_cathetusf(f32::NEG_INFINITY, 0.0), f32::INFINITY); + assert_eq!(f_cathetusf(0.0, f32::NEG_INFINITY), f32::INFINITY); + assert!(f_cathetusf(f32::NEG_INFINITY, f32::NEG_INFINITY).is_nan()); + assert!(f_cathetusf(f32::NAN, 1.0).is_nan()); + assert!(f_cathetusf(1.0, f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypot.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypot.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::{dyad_fmla, f_fmla}; +use crate::double_double::DoubleDouble; +use std::hint::black_box; + +// case hypot(x,y) >= 2^1024 +#[cold] +fn hypot_overflow() -> f64 { + const Z: f64 = f64::from_bits(0x7fefffffffffffff); + black_box(Z) + black_box(Z) +} + +#[cold] +fn hypot_denorm(a: u64, b: u64) -> f64 { + let mut a = a; + let mut b = b; + let af = (a as i64) as f64; + let bf = (b as i64) as f64; + let mut underflow; + // af and bf are x and y multiplied by 2^1074, thus integers + a = a.wrapping_shl(1); + b = b.wrapping_shl(1); + let mut rm = f_fmla(af, af, bf * bf).sqrt() as u64; + let mut tm: i64 = rm.wrapping_shl(1) as i64; + let mut denom: i64 = a + .wrapping_mul(a) + .wrapping_add(b.wrapping_mul(b)) + .wrapping_sub((tm as u64).wrapping_mul(tm as u64)) as i64; + // D = a^2+b^2 - tm^2 + while denom > 2 * tm { + // tm too small + denom -= 2 * tm + 1; // (tm+1)^2 = tm^2 + 2*tm + 1 + tm = tm.wrapping_add(1); + } + while denom < 0 { + // tm too large + denom += 2 * tm - 1; // (tm-1)^2 = tm^2 - 2*tm + 1 + tm = tm.wrapping_sub(1); + } + // tm = floor(sqrt(a^2+b^2)) and 0 <= D = a^2+b^2 - tm^2 < 2*tm+1 + // if D=0 and tm is even, the result is exact + // if D=0 and tm is odd, the result is a midpoint + let rb: i32 = (tm & 1) as i32; // round bit for rm + let rb2: i32 = (denom >= tm) as i32; // round bit for tm + let sb: i32 = (denom != 0) as i32; // sticky bit for rm + rm = (tm >> 1) as u64; // truncate the low bit + underflow = rm < 0x10000000000000u64; + if rb != 0 || sb != 0 { + let op = 1.0 + f64::from_bits(0x3c90000000000000); + let om = 1.0 - f64::from_bits(0x3c90000000000000); + if op == om { + // rounding to nearest + if sb != 0 { + rm = rm.wrapping_add(rb as u64); + // we have no underflow when rm is now 2^52 and rb2 != 0 + // Remark: we cannot have a^2+b^2 = (tm+1/2)^2 exactly + // since this would mean a^2+b^2 = tm^2+tm+1/4, + // thus a^2+b^2 would be an odd multiple of 2^-1077 + // (since ulp(tm) = 2^-1075) + if rm >> 52 != 0 && rb2 != 0 { + underflow = false; + } + } else { + // sticky bit is 0, round bit is 1: underflow doos not change + rm += rm & 1; // even rounding + } + } else if op > 1.0 { + // rounding upwards + rm = rm.wrapping_add(1); + // we have no underflow when rm is now 2^52 and tm was odd + if (rm >> 52) != 0 && (tm & 1) != 0 { + underflow = false; + } + } + if underflow { + // trigger underflow exception _after_ rounding for inexact results + let trig_uf = black_box(f64::from_bits(0x0010000000000000)); + _ = black_box(black_box(trig_uf) * black_box(trig_uf)); // triggers underflow + } + } + // else the result is exact, and we have no underflow + f64::from_bits(rm) +} + +/* Here the square root is refined by Newton iterations: x^2+y^2 is exact +and fits in a 128-bit integer, so the approximation is squared (which +also fits in a 128-bit integer), compared and adjusted if necessary using +the exact value of x^2+y^2. */ +#[cold] +fn hypot_hard(x: f64, y: f64) -> f64 { + let op = 1.0 + f64::from_bits(0x3c90000000000000); + let om = 1.0 - f64::from_bits(0x3c90000000000000); + let mut xi = x.to_bits(); + let yi = y.to_bits(); + let mut bm = (xi & 0x000fffffffffffff) | (1u64 << 52); + let mut lm = (yi & 0x000fffffffffffff) | (1u64 << 52); + let be: i32 = (xi >> 52) as i32; + let le: i32 = (yi >> 52) as i32; + let ri = f_fmla(x, x, y * y).sqrt().to_bits(); + const BS: u32 = 2; + let mut rm: u64 = ri & 0x000fffffffffffff; + let mut re: i32 = ((ri >> 52) as i32).wrapping_sub(0x3ff); + rm |= 1u64 << 52; + for _ in 0..3 { + if rm == (1u64 << 52) { + rm = 0x001fffffffffffff; + re = re.wrapping_sub(1); + } else { + rm = rm.wrapping_sub(1); + } + } + bm = bm.wrapping_shl(BS); + let mut m2: u64 = bm.wrapping_mul(bm); + let de: i32 = be.wrapping_sub(le); + let mut ls: i32 = (BS as i32).wrapping_sub(de); + if ls >= 0 { + lm <<= ls; + m2 = m2.wrapping_add(lm.wrapping_mul(lm)); + } else { + let lm2: u128 = (lm as u128).wrapping_mul(lm as u128); + ls = ls.wrapping_mul(2); + m2 = m2.wrapping_add((lm2 >> -ls) as u64); // since ls < 0, the shift by -ls is legitimate + m2 |= ((lm2.wrapping_shl((128 + ls) as u32)) != 0) as u64; + } + let k: i32 = (BS as i32).wrapping_add(re); + let mut denom: i64; + loop { + rm += 1 + (rm >= (1u64 << 53)) as u64; + let tm: u64 = rm.wrapping_shl(k as u32); + let rm2: u64 = tm.wrapping_mul(tm); + denom = (m2 as i64).wrapping_sub(rm2 as i64); + if denom <= 0 { + break; + } + } + if denom != 0 { + if op == om { + let ssm = if rm <= (1u64 << 53) { 1 } else { 0 }; + let tm: u64 = (rm << k) - (1 << (k - ssm)); + denom = (m2 as i64).wrapping_sub(tm.wrapping_mul(tm) as i64); + if denom != 0 { + rm = rm.wrapping_add((denom >> 63) as u64); + } else { + rm = rm.wrapping_sub(rm & 1); + } + } else { + let ssm = if rm > (1u64 << 53) { 1u32 } else { 0 }; + let pdm = if op == 1. { 1u64 } else { 0 }; + rm = rm.wrapping_sub(pdm.wrapping_shl(ssm)); + } + } + if rm >= (1u64 << 53) { + rm >>= 1; + re = re.wrapping_add(1); + } + + let e: i64 = be.wrapping_sub(1).wrapping_add(re) as i64; + xi = (e as u64).wrapping_shl(52).wrapping_add(rm); + f64::from_bits(xi) +} + +/// Computes hypot +/// +/// Max ULP 0.5 +pub fn f_hypot(x: f64, y: f64) -> f64 { + let xi = x.to_bits(); + let yi = y.to_bits(); + let emsk = 0x7ffu64 << 52; + let mut ex = xi & emsk; + let mut ey = yi & emsk; + let mut x = x.abs(); + let mut y = y.abs(); + if ex == emsk || ey == emsk { + /* Either x or y is NaN or Inf */ + let wx = xi.wrapping_shl(1); + let wy = yi.wrapping_shl(1); + let wm = emsk.wrapping_shl(1); + let ninf: i32 = ((wx == wm) ^ (wy == wm)) as i32; + let nqnn: i32 = (((wx >> 52) == 0xfff) ^ ((wy >> 52) == 0xfff)) as i32; + /* ninf is 1 when only one of x and y is +/-Inf + nqnn is 1 when only one of x and y is qNaN + IEEE 754 says that hypot(+/-Inf,qNaN)=hypot(qNaN,+/-Inf)=+Inf. */ + if ninf != 0 && nqnn != 0 { + return if wx == wm { x * x } else { y * y }; + } + return x + y; /* inf, nan */ + } + + let u = f64::max(x, y); + let v = f64::min(x, y); + let mut xd = u.to_bits(); + let mut yd = v.to_bits(); + ey = yd; + if (ey >> 52) == 0 { + // y is subnormal + if (yd) == 0 { + return f64::from_bits(xd); + } + ex = xd; + if (ex >> 52) == 0 { + // x is subnormal too + if ex == 0 { + return 0.; + } + return hypot_denorm(ex, ey); + } + let nz = ey.leading_zeros(); + ey = ey.wrapping_shl(nz - 11); + ey &= u64::MAX >> 12; + ey = ey.wrapping_sub(((nz as u64).wrapping_sub(12u64)) << 52); + let t = ey; + yd = t; + } + + let de = xd.wrapping_sub(yd); + if de > (27u64 << 52) { + return dyad_fmla(f64::from_bits(0x3e40000000000000), v, u); + } + let off: i64 = ((0x3ffu64 << 52) as i64).wrapping_sub((xd & emsk) as i64); + xd = xd.wrapping_add(off as u64); + yd = yd.wrapping_add(off as u64); + x = f64::from_bits(xd); + y = f64::from_bits(yd); + let x2 = DoubleDouble::from_exact_mult(x, x); + let y2 = DoubleDouble::from_exact_mult(y, y); + let r2 = x2.hi + y2.hi; + let ir2 = 0.5 / r2; + let dr2 = ((x2.hi - r2) + y2.hi) + (x2.lo + y2.lo); + let mut th = r2.sqrt(); + let rsqrt = DoubleDouble::from_exact_mult(th, ir2); + let dz = dr2 - rsqrt.lo; + let mut tl = rsqrt.hi * dz; + let p = DoubleDouble::from_exact_add(th, tl); + th = p.hi; + tl = p.lo; + let mut thd = th.to_bits(); + let tld = tl.abs().to_bits(); + ex = thd; + ey = tld; + ex &= 0x7ffu64 << 52; + let aidr = ey.wrapping_add(0x3feu64 << 52).wrapping_sub(ex); + let mid = (aidr.wrapping_sub(0x3c90000000000000).wrapping_add(16)) >> 5; + if mid == 0 || aidr < 0x39b0000000000000u64 || aidr > 0x3c9fffffffffff80u64 { + thd = hypot_hard(x, y).to_bits(); + } + thd = thd.wrapping_sub(off as u64); + if thd >= (0x7ffu64 << 52) { + return hypot_overflow(); + } + f64::from_bits(thd) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_hypot() { + assert_eq!( + f_hypot(2.8480945070593211E-306, 2.1219950320804403E-314), + 2.848094507059321e-306 + ); + assert_eq!( + f_hypot(3.5601181736115222E-307, 1.0609978954826362E-314), + 3.560118173611524e-307 + ); + assert_eq!(f_hypot(2., 4.), 4.47213595499958); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypot3f.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot3f.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypot3f.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypot3f.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::EXP_MASK_F32; + +pub fn f_hypot3f(x: f32, y: f32, z: f32) -> f32 { + let x_abs = f32::from_bits(x.to_bits() & 0x7fff_ffffu32); + let y_abs = f32::from_bits(y.to_bits() & 0x7fff_ffffu32); + let z_abs = f32::from_bits(z.to_bits() & 0x7fff_ffffu32); + + let a_bits = x_abs.to_bits().max(y_abs.to_bits()).max(z_abs.to_bits()); + let b_bits = x_abs.to_bits().min(y_abs.to_bits()).min(z_abs.to_bits()); + + let a_u = a_bits; + let b_u = b_bits; + + if a_u >= EXP_MASK_F32 { + // x or y is inf or nan + if x_abs.is_nan() || y_abs.is_nan() || z_abs.is_nan() { + return f32::NAN; + } + if x_abs.is_infinite() || y_abs.is_infinite() || z_abs.is_infinite() { + return f32::INFINITY; + } + return f32::from_bits(a_bits); + } + + if a_u.wrapping_sub(b_u) >= ((23u32 + 2) << 23) { + return x_abs + y_abs + z_abs; + } + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let ad = x as f64; + let bd = y as f64; + let cd = z as f64; + use crate::common::f_fmla; + // for FMA environment we're using Kahan style summation which is short and reliable. + let w = bd * bd; // RN(bc) + let e = f_fmla(-bd, bd, w); // RN(w − bc) + let f = f_fmla(ad, ad, w); // RN(ad + w) + let f0 = f_fmla(cd, cd, f); // RN(cd + f) + let r = e + f0; // RN(f + e) + let hyp = r.sqrt(); // sqrt(x^2 + y^2) + hyp as f32 + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let ad = x_abs as f64; + let bd = y_abs as f64; + let cd = z_abs as f64; + use crate::double_double::DoubleDouble; + let da = DoubleDouble::from_exact_mult(bd, bd); + let db = DoubleDouble::from_exact_mult(ad, ad); + let dc = DoubleDouble::from_exact_mult(cd, cd); + let f = DoubleDouble::add(DoubleDouble::add(da, db), dc); + let cath = f.to_f64().sqrt(); + cath as f32 + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_hypot3f() { + assert_eq!(f_hypot3f(3.0, 4.0, 12.0), 13.0); + assert_eq!(f_hypot3f(6.0, 8.0, 24.0), 26.0); + assert_eq!(f_hypot3f(5.0, 12.0, 84.0), 85.0); + assert_eq!(f_hypot3f(9.0, 12.0, 20.0), 25.0); + assert_eq!(f_hypot3f(1e20, 3.0, 4.0), 1e20); + assert_eq!(f_hypot3f(1e-20, 1e-20, 1.0), 1.); + assert_eq!( + f_hypot3f(f32::MIN_POSITIVE, f32::MIN_POSITIVE, 0.0), + 1.6624e-38 + ); + assert_eq!(f_hypot3f(f32::MAX, f32::MAX, 0.), f32::INFINITY); + assert_eq!(f_hypot3f(f32::MAX, 0., 0.), 3.4028235e38); + assert_eq!(f_hypot3f(f32::INFINITY, 0., 0.), f32::INFINITY); + assert_eq!(f_hypot3f(0., f32::INFINITY, 0.), f32::INFINITY); + assert_eq!(f_hypot3f(0., 0., f32::INFINITY), f32::INFINITY); + assert!(f_hypot3f(f32::NAN, 0., 0.).is_nan()); + assert!(f_hypot3f(0., f32::NAN, 0.).is_nan()); + assert!(f_hypot3f(0., 0., f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypotf.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypotf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/hypotf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/hypotf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::EXP_MASK_F32; + +/// Hypot function +/// +/// Max ULP 0.5 +#[inline] +pub fn f_hypotf(x: f32, y: f32) -> f32 { + let x_abs = f32::from_bits(x.to_bits() & 0x7fff_ffffu32); + let y_abs = f32::from_bits(y.to_bits() & 0x7fff_ffffu32); + + let a_bits = x_abs.to_bits().max(y_abs.to_bits()); + let b_bits = x_abs.to_bits().min(y_abs.to_bits()); + + let a_u = a_bits; + let b_u = b_bits; + + if a_u >= EXP_MASK_F32 { + // x or y is inf or nan + if f32::from_bits(a_bits).is_nan() || f32::from_bits(b_bits).is_nan() { + return f32::NAN; + } + if f32::from_bits(a_bits).is_infinite() || f32::from_bits(b_bits).is_infinite() { + return f32::INFINITY; + } + return f32::from_bits(a_bits); + } + + if a_u.wrapping_sub(b_u) >= ((23u32 + 2) << 23) { + return x_abs + y_abs; + } + + #[cfg(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + ))] + { + let ad = x as f64; + let bd = y as f64; + use crate::common::f_fmla; + // for FMA environment we're using Kahan style summation which is short and reliable. + let w = bd * bd; // RN(bc) + let e = f_fmla(-bd, bd, w); // RN(w − bc) + let f = f_fmla(ad, ad, w); // RN(ad + w) + let r = e + f; // RN(f + e) + let hyp = r.sqrt(); // sqrt(x^2 + y^2) + hyp as f32 + } + #[cfg(not(any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "fma" + ), + target_arch = "aarch64" + )))] + { + let ad = f32::from_bits(a_bits) as f64; + let bd = f32::from_bits(b_bits) as f64; + use crate::double_double::DoubleDouble; + let dy2 = DoubleDouble::from_exact_mult(bd, bd); + let fdx = DoubleDouble::from_exact_mult(ad, ad); + // elements are always sorted thus fdx.hi > dy2.hi, thus fasttwosum requirements is fulfilled + let f = DoubleDouble::add_f64(fdx, dy2.hi).to_f64(); + let r = dy2.lo + f; + let cath = r.sqrt(); + cath as f32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_hypotf() { + assert_eq!( + f_hypotf( + 0.000000000000000000000000000000000000000091771, + 0.000000000000000000000000000000000000011754585 + ), + 0.000000000000000000000000000000000000011754944 + ); + assert_eq!( + f_hypotf(9.177e-41, 1.1754585e-38), + 0.000000000000000000000000000000000000011754944 + ); + let dx = (f_hypotf(1f32, 1f32) - (1f32 * 1f32 + 1f32 * 1f32).sqrt()).abs(); + assert!(dx < 1e-5); + let dx = (f_hypotf(5f32, 5f32) - (5f32 * 5f32 + 5f32 * 5f32).sqrt()).abs(); + assert!(dx < 1e-5); + } + + #[test] + fn test_hypotf_edge_cases() { + assert_eq!(f_hypotf(-1.0, -3.0), 3.1622777); + assert_eq!(f_hypotf(0.0, 0.0), 0.0); + assert_eq!(f_hypotf(f32::INFINITY, 0.0), f32::INFINITY); + assert_eq!(f_hypotf(0.0, f32::INFINITY), f32::INFINITY); + assert_eq!(f_hypotf(f32::INFINITY, f32::INFINITY), f32::INFINITY); + assert_eq!(f_hypotf(f32::NEG_INFINITY, 0.0), f32::INFINITY); + assert_eq!(f_hypotf(0.0, f32::NEG_INFINITY), f32::INFINITY); + assert_eq!( + f_hypotf(f32::NEG_INFINITY, f32::NEG_INFINITY), + f32::INFINITY + ); + assert!(f_hypotf(f32::NAN, 1.0).is_nan()); + assert!(f_hypotf(1.0, f32::NAN).is_nan()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triangle/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triangle/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +mod cathetus; +mod cathetusf; +mod hypot; +mod hypot3f; +mod hypotf; + +pub use cathetus::f_cathetus; +pub use cathetusf::f_cathetusf; +pub use hypot::f_hypot; +pub use hypot3f::f_hypot3f; +pub use hypotf::f_hypotf; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triple_double.rs clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triple_double.rs --- clamav-1.4.3+dfsg/.cargo/vendor/pxfm/src/triple_double.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/pxfm/src/triple_double.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,389 @@ +/* + * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved. + * // + * // Redistribution and use in source and binary forms, with or without modification, + * // are permitted provided that the following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this + * // list of conditions and the following disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, + * // this list of conditions and the following disclaimer in the documentation + * // and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its + * // contributors may be used to endorse or promote products derived from + * // this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +use crate::common::f_fmla; +use crate::double_double::DoubleDouble; +use std::ops::Neg; + +#[derive(Clone, Copy, Debug)] +pub(crate) struct TripleDouble { + pub(crate) hi: f64, + pub(crate) mid: f64, + pub(crate) lo: f64, +} + +// impl TripleDouble { +// #[inline] +// pub(crate) fn mul_dd_add_f64(p0: TripleDouble, p1: DoubleDouble, p2: f64) -> TripleDouble { +// let q0 = TripleDouble::quick_mul_dd(p0, p1); +// TripleDouble::add_f64(p2, q0) +// } +// } + +impl TripleDouble { + // #[inline] + // pub(crate) fn mul_dd_add(p0: TripleDouble, p1: DoubleDouble, p2: TripleDouble) -> TripleDouble { + // let q0 = TripleDouble::quick_mul_dd(p0, p1); + // TripleDouble::add(q0, p2) + // } + + // #[inline] + // pub(crate) fn mul_dd_add_dd( + // p0: TripleDouble, + // p1: DoubleDouble, + // p2: DoubleDouble, + // ) -> TripleDouble { + // let q0 = TripleDouble::quick_mul_dd(p0, p1); + // TripleDouble::add_dd(p2, q0) + // } +} + +impl TripleDouble { + #[inline] + pub(crate) fn f64_mul_dd_add(p0: f64, p1: DoubleDouble, p2: TripleDouble) -> TripleDouble { + let q0 = TripleDouble::from_quick_mult_dd_f64(p1, p0); + TripleDouble::add(q0, p2) + } + + #[inline] + pub(crate) fn f64_mul_add(p0: f64, p1: TripleDouble, p2: TripleDouble) -> TripleDouble { + let q0 = TripleDouble::quick_mult_f64(p1, p0); + TripleDouble::add(q0, p2) + } +} + +impl TripleDouble { + #[inline] + pub(crate) const fn from_bit_pair(p0: (u64, u64, u64)) -> TripleDouble { + TripleDouble { + hi: f64::from_bits(p0.2), + mid: f64::from_bits(p0.1), + lo: f64::from_bits(p0.0), + } + } +} + +#[inline] +fn add12(a: f64, b: f64) -> DoubleDouble { + DoubleDouble::from_full_exact_add(a, b) +} + +#[inline] +fn mul12(a: f64, b: f64) -> DoubleDouble { + DoubleDouble::from_exact_mult(a, b) +} + +#[inline] +pub(crate) fn add22(a: DoubleDouble, b: DoubleDouble) -> DoubleDouble { + let DoubleDouble { hi: v1, lo: v2 } = DoubleDouble::from_full_exact_add(a.hi, b.hi); + let v3 = a.lo + b.lo; + let v4 = v2 + v3; + DoubleDouble::from_full_exact_add(v1, v4) +} + +impl TripleDouble { + // #[inline] + // pub(crate) fn from_quick_mult_dd(a: DoubleDouble, b: DoubleDouble) -> TripleDouble { + // /* + // (rh , t1) ← Mul12 (ah , bh ) + // (t2, t3) ← Mul12 (ah , bl ) + // (t4, t5) ← Mul12 (al , bh ) + // t6 ← al ⊗ bl + // (t7, t8) ← Add22 (t2, t3, t4, t5) + // (t9, t10) ← Add12 (t1, t6) + // (rm , rl ) ← Add22 (t7, t8, t9, t10) + // */ + // let DoubleDouble { hi: rh, lo: t1 } = mul12(a.hi, b.hi); + // let r0 = mul12(a.hi, b.lo); + // let r1 = mul12(a.lo, b.hi); + // let t6 = a.lo * b.lo; + // let q0 = add22(r0, r1); + // let q1 = add12(t1, t6); + // let DoubleDouble { hi: rm, lo: rl } = add22(q0, q1); + // TripleDouble { + // hi: rh, + // mid: rm, + // lo: rl, + // } + // } + + #[inline] + pub(crate) fn from_quick_mult_dd_f64(a: DoubleDouble, b: f64) -> TripleDouble { + let DoubleDouble { hi: rh, lo: t1 } = mul12(a.hi, b); + let DoubleDouble { hi: t2, lo: t3 } = mul12(a.lo, b); + let DoubleDouble { hi: t5, lo: t4 } = add12(t1, t2); + let t6 = t3 + t4; + let DoubleDouble { hi: rm, lo: rl } = add12(t5, t6); + TripleDouble::new(rl, rm, rh) + } + + #[inline] + pub(crate) fn quick_mult_f64(a: TripleDouble, b: f64) -> TripleDouble { + let DoubleDouble { hi: rh, lo: t2 } = mul12(a.hi, b); + let DoubleDouble { hi: t3, lo: t4 } = mul12(a.mid, b); + let DoubleDouble { hi: t9, lo: t7 } = add12(t2, t3); + let t8 = f_fmla(a.lo, b, t4); + let t10 = t7 + t8; + let DoubleDouble { hi: rm, lo: rl } = add12(t9, t10); + TripleDouble::new(rl, rm, rh) + } + + #[inline] + pub(crate) fn quick_mult(b: TripleDouble, a: TripleDouble) -> TripleDouble { + /* Mul12((resh),&_t1,(ah),(bh)); + Mul12(&_t2,&_t3,(ah),(bm)); + Mul12(&_t4,&_t5,(am),(bh)); + Mul12(&_t6,&_t7,(am),(bm)); + _t8 = (ah) * (bl); + _t9 = (al) * (bh); + _t10 = (am) * (bl); + _t11 = (al) * (bm); + _t12 = _t8 + _t9; + _t13 = _t10 + _t11; + Add12Cond(_t14,_t15,_t1,_t6); + _t16 = _t7 + _t15; + _t17 = _t12 + _t13; + _t18 = _t16 + _t17; + Add12Cond(_t19,_t20,_t14,_t18); + Add22Cond(&_t21,&_t22,_t2,_t3,_t4,_t5); + Add22Cond((resm),(resl),_t21,_t22,_t19,_t20); */ + let DoubleDouble { hi: rh, lo: t1 } = DoubleDouble::from_exact_mult(a.hi, b.hi); + let DoubleDouble { hi: t2, lo: t3 } = DoubleDouble::from_exact_mult(a.hi, b.mid); + let DoubleDouble { hi: t4, lo: t5 } = DoubleDouble::from_exact_mult(a.mid, b.hi); + let DoubleDouble { hi: t6, lo: t7 } = DoubleDouble::from_exact_mult(a.mid, b.mid); + let t12 = f_fmla(a.hi, b.lo, a.lo * b.hi); + let t13 = f_fmla(a.mid, b.lo, a.lo * b.mid); + let DoubleDouble { hi: t14, lo: t15 } = add12(t1, t6); + let t16 = t7 + t15; + let t17 = t12 + t13; + let t18 = t16 + t17; + let DoubleDouble { hi: t19, lo: t20 } = add12(t14, t18); + let DoubleDouble { hi: t21, lo: t22 } = + add22(DoubleDouble::new(t3, t2), DoubleDouble::new(t4, t5)); + let DoubleDouble { hi: rm, lo: rl } = + add22(DoubleDouble::new(t22, t21), DoubleDouble::new(t20, t19)); + TripleDouble::new(rl, rm, rh) + } + + #[inline] + pub(crate) fn quick_mult_dd(b: TripleDouble, a: DoubleDouble) -> TripleDouble { + /* + (rh , t1) ← Mul12 (ah , bh ) + (t2, t3) ← Mul12 (ah , bm ) + (t4, t5) ← Mul12 (ah , bl ) + (t6, t7) ← Mul12 (al , bh ) + (t8, t9) ← Mul12 (al , bm ) + t10 ← al ⊗ bl + (t11, t12) ← Add22 (t2, t3, t4, t5) + (t13, t14) ← Add22 (t6, t7, t8, t9) + (t15, t16) ← Add22 (t11, t12, t13, t14) + (t17, t18) ← Add12 (t1, t10) + (rm , rl ) ← Add22 (t17, t18, t15, t16) + */ + let DoubleDouble { hi: rh, lo: t1 } = mul12(a.hi, b.hi); + let DoubleDouble { hi: t2, lo: t3 } = mul12(a.hi, b.mid); + let DoubleDouble { hi: t4, lo: t5 } = mul12(a.hi, b.lo); + let DoubleDouble { hi: t6, lo: t7 } = mul12(a.lo, b.hi); + let DoubleDouble { hi: t8, lo: t9 } = mul12(a.lo, b.mid); + let t10 = a.lo * b.lo; + let z0 = add22(DoubleDouble::new(t3, t2), DoubleDouble::new(t4, t5)); + let z1 = add22(DoubleDouble::new(t6, t7), DoubleDouble::new(t8, t9)); + let q0 = add22(z0, z1); + let q1 = add12(t1, t10); + let DoubleDouble { hi: rm, lo: rl } = add22(q1, q0); + TripleDouble { + hi: rh, + mid: rm, + lo: rl, + } + } + + pub(crate) fn add(a: TripleDouble, b: TripleDouble) -> TripleDouble { + /* + (rh , t1) ← Add12 (ah , bh ) + (t2, t3) ← Add12 (am , bm ) + (t7, t4) ← Add12 (t1, t2) + t6 ← al ⊕ bl + t5 ← t3 ⊕ t4 + t8 ← t5 ⊕ t6 + (rm , rl ) ← Add12 (t7, t8) + */ + let DoubleDouble { hi: rh, lo: t1 } = add12(a.hi, b.hi); + let DoubleDouble { hi: t2, lo: t3 } = add12(a.mid, b.mid); + let t6 = a.lo + b.lo; + let DoubleDouble { hi: t7, lo: t4 } = add12(t1, t2); + let t5 = t3 + t4; + let t8 = t5 + t6; + let DoubleDouble { hi: rm, lo: rl } = add12(t7, t8); + TripleDouble { + hi: rh, + mid: rm, + lo: rl, + } + } + + // #[inline] + // pub(crate) fn add_dd(a: DoubleDouble, b: TripleDouble) -> TripleDouble { + // /* + // (rh , t1) ← Add12 (ah , bh ) + // (t2, t3) ← Add12 (al , bm ) + // (t4, t5) ← Add12 (t1, t2) + // t6 ← t3 ⊕ bl + // t7 ← t6 ⊕ t5 + // (rm , rl ) ← Add12 (t4, t7) + // */ + // let DoubleDouble { hi: rh, lo: t1 } = add12(a.hi, b.hi); + // let DoubleDouble { hi: t2, lo: t3 } = add12(a.hi, b.mid); + // let DoubleDouble { hi: t4, lo: t5 } = add12(t1, t2); + // let t6 = t3 + b.lo; + // let t7 = t6 + t5; + // let DoubleDouble { hi: rm, lo: rl } = add12(t4, t7); + // TripleDouble { + // hi: rh, + // mid: rm, + // lo: rl, + // } + // } + + #[inline] + pub(crate) fn add_f64(a: f64, b: TripleDouble) -> TripleDouble { + let DoubleDouble { hi: rh, lo: t1 } = add12(a, b.hi); + let DoubleDouble { hi: t2, lo: t3 } = add12(t1, b.mid); + let t4 = t3 + b.lo; + let DoubleDouble { hi: rm, lo: rl } = add12(t2, t4); + TripleDouble::new(rl, rm, rh) + } + + // #[inline] + // pub(crate) fn to_dd(self) -> DoubleDouble { + // let DoubleDouble { hi: t1, lo: t2 } = add12(self.hi, self.mid); + // let t3 = t2 + self.lo; + // DoubleDouble::new(t3, t1) + // } + + #[inline] + pub(crate) const fn new(lo: f64, mid: f64, hi: f64) -> Self { + Self { hi, mid, lo } + } + + #[inline] + pub(crate) fn to_f64(self) -> f64 { + let DoubleDouble { hi: t1, lo: t2 } = add12(self.hi, self.mid); + let t3 = t2 + self.lo; + t1 + t3 + } + + #[inline] + pub(crate) fn from_full_exact_add(a: f64, b: f64) -> Self { + let DoubleDouble { hi: rh, lo: t1 } = add12(a, b); + TripleDouble::new(0., t1, rh).renormalize() + } + + #[inline] + pub(crate) fn renormalize(self) -> Self { + /* + double _t1h, _t1l, _t2l; + + Add12(_t1h, _t1l, (am), (al)); + Add12((*(resh)), _t2l, (ah), (_t1h)); + Add12((*(resm)), (*(resl)), _t2l, _t1l); + */ + let DoubleDouble { hi: t1h, lo: t1l } = DoubleDouble::from_exact_add(self.mid, self.lo); + let DoubleDouble { hi: rh, lo: t2l } = DoubleDouble::from_exact_add(self.hi, t1h); + let zml = DoubleDouble::from_exact_add(t2l, t1l); + TripleDouble::new(zml.lo, zml.hi, rh) + } + + #[inline] + pub(crate) fn recip(self) -> Self { + /* + _rec_r1 = 1.0 / (dh); + Mul12(&_rec_t1,&_rec_t2,_rec_r1,(dh)); + _rec_t3 = _rec_t1 - 1.0; + Add12Cond(_rec_t4,_rec_t5,_rec_t3,_rec_t2); + Mul12(&_rec_t6,&_rec_t7,_rec_r1,(dm)); + Add12(_rec_t8,_rec_t9,-1.0,_rec_t6); + _rec_t10 = _rec_t9 + _rec_t7; + Add12(_rec_t11,_rec_t12,_rec_t8,_rec_t10); + _rec_r1 = -_rec_r1; + Add22Cond(&_rec_t13,&_rec_t14,_rec_t4,_rec_t5,_rec_t11,_rec_t12); + Mul122(&_rec_r2h,&_rec_r2l,_rec_r1,_rec_t13,_rec_t14); + Mul233(&_rec_t15,&_rec_t16,&_rec_t17,_rec_r2h,_rec_r2l,(dh),(dm),(dl)); + Renormalize3(&_rec_t18,&_rec_t19,&_rec_t20,_rec_t15,_rec_t16,_rec_t17); + _rec_t18 = -1.0; + Mul233(&_rec_t21,&_rec_t22,&_rec_t23,_rec_r2h,_rec_r2l,_rec_t18,_rec_t19,_rec_t20); + _rec_t21 = -_rec_t21; _rec_t22 = -_rec_t22; _rec_t23 = -_rec_t23; + Renormalize3((resh),(resm),(resl),_rec_t21,_rec_t22,_rec_t23); + */ + let mut r1 = 1. / self.hi; + let DoubleDouble { + hi: rec_t1, + lo: rec_t2, + } = DoubleDouble::from_exact_mult(r1, self.hi); + let rec_t3 = rec_t1 - 1.0; + let DoubleDouble { + hi: rec_t4, + lo: rec_t5, + } = add12(rec_t3, rec_t2); + let DoubleDouble { + hi: rec_t6, + lo: rec_t7, + } = mul12(r1, self.mid); + let DoubleDouble { + hi: rec_t8, + lo: rec_t9, + } = add12(-1.0, rec_t6); + let rec_t10 = rec_t9 + rec_t7; + r1 = -r1; + let DoubleDouble { + hi: rec_t11, + lo: rec_t12, + } = add12(rec_t8, rec_t10); + let z0 = add22( + DoubleDouble::new(rec_t5, rec_t4), + DoubleDouble::new(rec_t12, rec_t11), + ); + let r2hl = DoubleDouble::quick_mult_f64(z0, r1); + let rec15_16_17 = TripleDouble::quick_mult_dd(self, r2hl); + let rec18_19_20 = rec15_16_17.renormalize(); + let rec_t18 = -1.0; + let rec_21_22_23 = -TripleDouble::quick_mult_dd( + TripleDouble::new(rec18_19_20.lo, rec18_19_20.mid, rec_t18), + r2hl, + ); + rec_21_22_23.renormalize() + } +} + +impl Neg for TripleDouble { + type Output = Self; + #[inline] + fn neg(self) -> Self::Output { + TripleDouble::new(-self.lo, -self.mid, -self.hi) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"e6f613e9dd318adea544e29260f6c2dd72703b1f0a2c0a9609c917efd11c03c5","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"45adbcb6d50e4b2875f22f2b997bbf6689c6825fbf7e8285a29ed35896dbfa21","README.md":"256b9e41c253272c580bc7564853f513a2656b62850907222437abb32d913a36","doc/qoi-specification.pdf":"86a3362ad7142cb1b8002f05c77ba8b11008d5f3d8c86b13a1c14bb403cfc821","ext/qoi/README.md":"75a41a1c128e26abd62cf2e99214205b3d8831ea285828f77f91a5b7e2d93c3c","ext/qoi/qoi.h":"68f8cdf35a7e0cb32bc5fe9e96d0c4f88fd0d6405c626374706bf79dbcdc4670","ext/qoi/qoibench.c":"11cd2215645ca19cd0c4d3fd8953f3478bba48909364cf35efa5a8d4b5336267","ext/qoi/qoiconv.c":"e0d5ff0bb446326109d972881870ba7e09a3ab699f0cf2109580eef6c12d3586","ext/qoi/qoifuzz.c":"fb088d0bc1d3c1afd2f9d1fb94c2b8c9374d200d31005e9b3e382031490878da","rustfmt.toml":"89171882f4be7243caf15d3bf0ad349e8adf756011ab35a72d29d19e43a8dfa3","src/consts.rs":"26c46452a2d4b9cd9c5cc704a5c211a6a458ee7cc03bd83ca3ed90fae5926bdb","src/decode.rs":"f23cc1210a4eecb795590d16bf30a8314a7a04b86e4cddf43d72a384b615629b","src/encode.rs":"73a88cc7671c904ce8e299c9cc06c83487060c792dbb90c5fdd5b6c86e5c7780","src/error.rs":"67b8d480e9f162ebc831ee511a30dd1a299f251511ef8e4059e1ce0c339bc299","src/header.rs":"3a088257e02c4f19980136392b0dce69339cc953ced77ac17609b1a302b141f9","src/lib.rs":"d7df06e0d887928ff2a82306ca22d7256991917fc488dbbdf1d7a3d1b75eadd4","src/pixel.rs":"b21e6af6eaaa40822b9df5b7696895b9d2cabe20c508bf43919e690ed81ac531","src/types.rs":"72a5172f2f74a06fc827dd731e5563129028f42fd828d1a79ca3691f1a31f0be","src/utils.rs":"b5fd3bbf35c732c4304d41a077966a7ef275a4c2e8bd42ae5e7d0b51135fa54c","tests/common.rs":"783e1ac35a08ea4efc92a9fbbfc3fe0f5622d4aade812d6070771e7843b29078","tests/test_chunks.rs":"b33ba0f1841240d14b965190874512d768cf9a8f1ebd6ce8cdd84a0df4e499a4","tests/test_gen.rs":"559eabc6324288c5e7cd4de492fc3d38c7f631ccb1f7065bd8e957d0aecaa8f8","tests/test_misc.rs":"00e2d43bdd7d105844340761a71f16309b43b84b95470d02fd9f53696a034d87","tests/test_ref.rs":"e9e6a174a54b268568b48f1bce7b8e293f50ad1f75c536d7fa1d66d104a61b9a"},"package":"7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"b20f99c89b2144867a5dbc0023b31f5713f32fce865ec387d2dccadcd8d211f4",".github/workflows/ci.yml":"8e11808b90798275e046b804e4ee837e32381af971e6c5c55ee1f2388ae7cfda",".gitmodules":"6fdf8e9a53b2781c6ee1016160f630a1596e7637a0028c9c866abfaedae7a5f7","Cargo.toml":"e6f613e9dd318adea544e29260f6c2dd72703b1f0a2c0a9609c917efd11c03c5","Cargo.toml.orig":"5d5e57ebc18e740a4d3d11162422e2378cd3ae3cdaa2fcc94defc3c2f9843fc5","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"45adbcb6d50e4b2875f22f2b997bbf6689c6825fbf7e8285a29ed35896dbfa21","README.md":"256b9e41c253272c580bc7564853f513a2656b62850907222437abb32d913a36","doc/qoi-specification.pdf":"86a3362ad7142cb1b8002f05c77ba8b11008d5f3d8c86b13a1c14bb403cfc821","ext/qoi/.gitignore":"3525edbddf663d969a390fdd126499783b4eb5da8a1a41323c62c25462a80302","ext/qoi/README.md":"75a41a1c128e26abd62cf2e99214205b3d8831ea285828f77f91a5b7e2d93c3c","ext/qoi/qoi.h":"68f8cdf35a7e0cb32bc5fe9e96d0c4f88fd0d6405c626374706bf79dbcdc4670","ext/qoi/qoibench.c":"11cd2215645ca19cd0c4d3fd8953f3478bba48909364cf35efa5a8d4b5336267","ext/qoi/qoiconv.c":"e0d5ff0bb446326109d972881870ba7e09a3ab699f0cf2109580eef6c12d3586","ext/qoi/qoifuzz.c":"fb088d0bc1d3c1afd2f9d1fb94c2b8c9374d200d31005e9b3e382031490878da","rustfmt.toml":"89171882f4be7243caf15d3bf0ad349e8adf756011ab35a72d29d19e43a8dfa3","src/consts.rs":"26c46452a2d4b9cd9c5cc704a5c211a6a458ee7cc03bd83ca3ed90fae5926bdb","src/decode.rs":"f23cc1210a4eecb795590d16bf30a8314a7a04b86e4cddf43d72a384b615629b","src/encode.rs":"73a88cc7671c904ce8e299c9cc06c83487060c792dbb90c5fdd5b6c86e5c7780","src/error.rs":"67b8d480e9f162ebc831ee511a30dd1a299f251511ef8e4059e1ce0c339bc299","src/header.rs":"3a088257e02c4f19980136392b0dce69339cc953ced77ac17609b1a302b141f9","src/lib.rs":"d7df06e0d887928ff2a82306ca22d7256991917fc488dbbdf1d7a3d1b75eadd4","src/pixel.rs":"b21e6af6eaaa40822b9df5b7696895b9d2cabe20c508bf43919e690ed81ac531","src/types.rs":"72a5172f2f74a06fc827dd731e5563129028f42fd828d1a79ca3691f1a31f0be","src/utils.rs":"b5fd3bbf35c732c4304d41a077966a7ef275a4c2e8bd42ae5e7d0b51135fa54c","tests/common.rs":"783e1ac35a08ea4efc92a9fbbfc3fe0f5622d4aade812d6070771e7843b29078","tests/test_chunks.rs":"b33ba0f1841240d14b965190874512d768cf9a8f1ebd6ce8cdd84a0df4e499a4","tests/test_gen.rs":"559eabc6324288c5e7cd4de492fc3d38c7f631ccb1f7065bd8e957d0aecaa8f8","tests/test_misc.rs":"00e2d43bdd7d105844340761a71f16309b43b84b95470d02fd9f53696a034d87","tests/test_ref.rs":"e9e6a174a54b268568b48f1bce7b8e293f50ad1f75c536d7fa1d66d104a61b9a"},"package":"7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e97077e527618a07413f7895a3792a6859afac59" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/qoi/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +on: + push: + branches: [master] + pull_request: + branches: [master] +name: CI +env: + CARGO_TERM_COLOR: always + HOST: x86_64-unknown-linux-gnu + RUSTFLAGS: "-D warnings" +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable, beta, nightly, 1.61.0] # MSRV=1.61 + steps: + - uses: actions/checkout@v2 + with: {submodules: true} + - uses: actions-rs/toolchain@v1 + with: {profile: minimal, toolchain: '${{ matrix.rust }}', override: true} + - run: cargo test + reference: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: {submodules: true} + - uses: actions-rs/toolchain@v1 + with: {profile: minimal, toolchain: stable, override: true} + - run: cargo test --features=reference + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: {profile: minimal, toolchain: beta, override: true, components: clippy} + - run: cargo clippy diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/.gitmodules clamav-1.4.6+dfsg/.cargo/vendor/qoi/.gitmodules --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/.gitmodules 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/.gitmodules 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +[submodule "ext/qoi"] + path = ext/qoi + url = https://github.com/phoboslab/qoi.git diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/qoi/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +[package] +name = "qoi" +version = "0.4.1" +description = "VERY fast encoder/decoder for QOI (Quite Okay Image) format" +authors = ["Ivan Smirnov "] +edition = "2021" +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/aldanor/qoi-rust" +homepage = "https://github.com/aldanor/qoi-rust" +documentation = "https://docs.rs/qoi" +categories = ["multimedia::images", "multimedia::encoding"] +keywords = ["qoi", "graphics", "image", "encoding"] +exclude = [ + "assets/*", +] +rust-version = "1.61.0" + +[features] +default = ["std"] +alloc = [] # provides access to `Vec` without enabling `std` mode +std = [] # std mode (enabled by default) - provides access to `std::io`, `Error` and `Vec` +reference = [] # follows reference encoder implementation precisely, but may be slightly slower + +[dependencies] +bytemuck = "1.12" + +[workspace] +members = ["libqoi", "bench"] + +[dev-dependencies] +anyhow = "1.0" +png = "0.17" +walkdir = "2.3" +cfg-if = "1.0" +rand = "0.8" +libqoi = { path = "libqoi"} + +[lib] +name = "qoi" +path = "src/lib.rs" +doctest = false + +[profile.test] +opt-level = 3 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/qoi/ext/qoi/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/qoi/ext/qoi/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/qoi/ext/qoi/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/qoi/ext/qoi/.gitignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +images/ +stb_image.h +stb_image_write.h +qoibench +qoiconv diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"27a3b8124e45550708ca600232fa1ffdcc364ca02e81835b51440317223193bb",".travis.yml":"f231f99557fdb5c3a215c0df9f9a67fd8660efcf71b965d050e7dcff2e753750","Cargo.lock":"09302fee277345a50382b68a54eaaa47714c4da9a85c3986a0bf74740fe655a9","Cargo.toml":"d36aca49b7f7fe25c35e8ef7c3a68f7a94fdc777ac80d52b8fe360608a7d9af1","Cargo.toml.orig":"6b481d76a3255932357a2d035fc2ddb2e9a8c783b9168fd6917d0acffb7ef5c1","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"058f01fe181608d027fcde7e528fc03ea3cf90f30903c407644b0a9bbc54f500","README.rst":"97f715a3a68ede33bca81c98ad791375b2bb7ad0d814377b0651f5c4de8f7d4a","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","examples/context.rs":"5045319e03fa5214c7b2f9ef28d6012ffd34f7095d2103b5579a4c8567ddab68","src/lib.rs":"f12c185679a3f45cb9e905bdd9a176c3cf638c892a380d34a230e3051c66f53d","vagga.yaml":"280ac771f03284bb3f7e1b5b50c0b8046e79cc5c54f40b7c738f7a8ebaa586f2"},"package":"a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "25ab982bb0c43130ae48485151f4a232eeab7d0c" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/.travis.yml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,31 @@ +sudo: false +dist: trusty +language: rust + +cache: +- cargo + +before_cache: +- rm -r $TRAVIS_BUILD_DIR/target/debug + +jobs: + include: + - os: linux + rust: stable + - os: linux + rust: beta + - os: linux + rust: nightly + + # deploy + - stage: publish + os: linux + rust: stable + install: true + script: true + + deploy: + - provider: script + script: 'cargo publish --verbose --token=$CARGO_TOKEN' + on: + tags: true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "quick-error" +version = "2.0.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "quick-error" +version = "2.0.1" +authors = ["Paul Colomiets ", "Colin Kiegel "] +description = " A macro which makes error types pleasant to write.\n" +homepage = "http://github.com/tailhook/quick-error" +documentation = "http://docs.rs/quick-error" +keywords = ["macro", "error", "type", "enum"] +categories = ["rust-patterns"] +license = "MIT/Apache-2.0" +repository = "http://github.com/tailhook/quick-error" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/Cargo.toml.orig 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,14 @@ +[package] +name = "quick-error" +description = """ + A macro which makes error types pleasant to write. +""" +license = "MIT/Apache-2.0" +version = "2.0.1" +edition = "2018" +keywords = ["macro", "error", "type", "enum"] +authors = ["Paul Colomiets ", "Colin Kiegel "] +homepage = "http://github.com/tailhook/quick-error" +repository = "http://github.com/tailhook/quick-error" +documentation = "http://docs.rs/quick-error" +categories = ["rust-patterns"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-APACHE 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + http://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. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/LICENSE-MIT 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,19 @@ +Copyright (c) 2015 The quick-error Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/README.rst clamav-1.4.6+dfsg/.cargo/vendor/quick-error/README.rst --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/README.rst 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/README.rst 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,66 @@ +=========== +Quick Error +=========== + +:Status: production-ready +:Documentation: https://docs.rs/quick-error/ + +A macro which makes error types pleasant to write. + +Features: + +* Define enum type with arbitrary parameters +* Concise notation of ``Display`` and ``Error`` traits +* Full control of ``Display`` and ``Error`` trait implementation +* Any number of ``From`` traits +* Support for all enum-variants ``Unit``, ``Tuple`` and ``Struct`` + +Here is the comprehensive example: + +.. code-block:: rust + + quick_error! { + #[derive(Debug)] + pub enum IoWrapper { + Io(err: io::Error) { + from() + display("I/O error: {}", err) + source(err) + } + Other(descr: &'static str) { + display("Error {}", descr) + } + IoAt { place: &'static str, err: io::Error } { + source(err) + display(me) -> ("io error at {}: {}", place, err) + from(s: String) -> { + place: "some string", + err: io::Error::new(io::ErrorKind::Other, s) + } + } + Discard { + from(&'static str) + } + } + } + +======= +License +======= + +Licensed under either of + + * Apache License, Version 2.0, (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT) + +at your option. + +------------ +Contribution +------------ + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/bulk.yaml clamav-1.4.6+dfsg/.cargo/vendor/quick-error/bulk.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/bulk.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/bulk.yaml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,8 @@ +minimum-bulk: v0.4.5 + +versions: + +- file: Cargo.toml + block-start: ^\[package\] + block-end: ^\[.*\] + regex: ^version\s*=\s*"(\S+)" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/examples/context.rs clamav-1.4.6+dfsg/.cargo/vendor/quick-error/examples/context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/examples/context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/examples/context.rs 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,43 @@ +use quick_error::{quick_error, ResultExt}; +use std::env; +use std::fs::File; +use std::io::{self, stderr, Read, Write}; +use std::num::ParseIntError; +use std::path::{Path, PathBuf}; + +quick_error! { + #[derive(Debug)] + pub enum Error { + NoFileName {} + Io(err: io::Error, path: PathBuf) { + display("could not read file {:?}: {}", path, err) + context(path: &'a Path, err: io::Error) + -> (err, path.to_path_buf()) + } + Parse(err: ParseIntError, path: PathBuf) { + display("could not parse file {:?}: {}", path, err) + context(path: &'a Path, err: ParseIntError) + -> (err, path.to_path_buf()) + } + } +} + +fn parse_file() -> Result { + let fname = env::args().skip(1).next().ok_or(Error::NoFileName)?; + let fname = Path::new(&fname); + let mut file = File::open(fname).context(fname)?; + let mut buf = String::new(); + file.read_to_string(&mut buf).context(fname)?; + Ok(buf.parse().context(fname)?) +} + +fn main() { + match parse_file() { + Ok(val) => { + println!("Read: {}", val); + } + Err(e) => { + writeln!(&mut stderr(), "Error: {}", e).ok(); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/quick-error/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/src/lib.rs 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,1336 @@ +#![warn(missing_docs, rust_2018_idioms)] +//! A macro which makes errors easy to write +//! +//! Minimum type is like this: +//! +//! ```rust +//! #[macro_use] extern crate quick_error; +//! # fn main() {} +//! +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Variant1 {} +//! } +//! } +//! ``` +//! Both ``pub`` and non-public types may be declared, and all meta attributes +//! (such as ``#[derive(Debug)]``) are forwarded as is. The `Debug` must be +//! implemented (but you may do that yourself if you like). The documentation +//! comments ``/// something`` (as well as other meta attrbiutes) on variants +//! are allowed. +//! +//! # Allowed Syntax +//! +//! You may add arbitrary parameters to any struct variant: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! /// IO Error +//! Io(err: std::io::Error) {} +//! /// Utf8 Error +//! Utf8(err: std::str::Utf8Error) {} +//! } +//! } +//! ``` +//! +//! Note unlike in normal Enum declarations you declare names of fields (which +//! are omitted from type). How they can be used is outlined below. +//! +//! Now you might have noticed trailing braces `{}`. They are used to define +//! implementations. By default: +//! +//! * `Error::source()` returns None (even if type wraps some value) +//! * `Display` outputs debug representation +//! * No `From` implementations are defined +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! display("{}", err) +//! } +//! Utf8(err: std::str::Utf8Error) { +//! display("utf8 error") +//! } +//! } +//! } +//! ``` +//! +//! To change `source` method to return some error, add `source(value)`, for +//! example: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! source(err) +//! } +//! Utf8(err: std::str::Utf8Error) { +//! display("utf8 error") +//! } +//! Other(err: Box) { +//! source(&**err) +//! } +//! } +//! } +//! ``` +//! Note you don't need to wrap value in `Some`, its implicit. In case you want +//! `None` returned just omit the `source`. You can't return `None` +//! conditionally. +//! +//! To change how each clause is `Display`ed add `display(pattern,..args)`, +//! for example: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! display("I/O error: {}", err) +//! } +//! Utf8(err: std::str::Utf8Error) { +//! display("Utf8 error, valid up to {}", err.valid_up_to()) +//! } +//! } +//! } +//! ``` +//! +//! If you need a reference to the error when `Display`ing, you can instead use +//! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference. +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! use std::error::Error; // put methods like `source()` of this trait into scope +//! +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! display(x) -> ("I/O: {}", err) +//! } +//! Utf8(err: std::str::Utf8Error) { +//! display(self_) -> ("UTF-8 error. Valid up to {}", err.valid_up_to()) +//! } +//! } +//! } +//! ``` +//! +//! To convert to the type from any other, use one of the three forms of +//! `from` clause. +//! +//! For example, to convert simple wrapper use bare `from()`: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! from() +//! } +//! } +//! } +//! ``` +//! +//! This implements ``From``. +//! +//! To convert to singleton enumeration type (discarding the value), use +//! the `from(type)` form: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! FormatError { +//! from(std::fmt::Error) +//! } +//! } +//! } +//! ``` +//! +//! And the most powerful form is `from(var: type) -> (arguments...)`. It +//! might be used to convert to type with multiple arguments or for arbitrary +//! value conversions: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! FailedOperation(s: &'static str, errno: i32) { +//! from(errno: i32) -> ("os error", errno) +//! from(e: std::io::Error) -> ("io error", e.raw_os_error().unwrap()) +//! } +//! /// Converts from both kinds of utf8 errors +//! Utf8(err: std::str::Utf8Error) { +//! from() +//! from(err: std::string::FromUtf8Error) -> (err.utf8_error()) +//! } +//! } +//! } +//! ``` +//! # Context +//! +//! Since quick-error 1.1 we also have a `context` declaration, which is +//! similar to (the longest form of) `from`, but allows adding some context to +//! the error. We need a longer example to demonstrate this: +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # use std::io; +//! # use std::fs::File; +//! # use std::path::{Path, PathBuf}; +//! # +//! use quick_error::ResultExt; +//! +//! quick_error! { +//! #[derive(Debug)] +//! pub enum Error { +//! File(filename: PathBuf, err: io::Error) { +//! context(path: &'a Path, err: io::Error) +//! -> (path.to_path_buf(), err) +//! } +//! } +//! } +//! +//! fn openfile(path: &Path) -> Result<(), Error> { +//! File::open(path).context(path)?; +//! +//! // If we didn't have context, the line above would be written as; +//! // +//! // File::open(path) +//! // .map_err(|err| Error::File(path.to_path_buf(), err))?; +//! +//! Ok(()) +//! } +//! +//! # fn main() { +//! # openfile(Path::new("/etc/somefile")).ok(); +//! # } +//! ``` +//! +//! Each `context(a: A, b: B)` clause implements +//! `From> for Error`. Which means multiple `context` clauses +//! are a subject to the normal coherence rules. Unfortunately, we can't +//! provide full support of generics for the context, but you may either use a +//! lifetime `'a` for references or `AsRef` (the latter means `A: +//! AsRef`, and `Type` must be concrete). It's also occasionally useful +//! to use a tuple as a type of the first argument. +//! +//! You also need to `use quick_error::ResultExt` extension trait to get +//! working `.context()` method. +//! +//! More info on context in [this article](http://bit.ly/1PsuxDt). +//! +//! All forms of `from`, `display`, `source`, and `context` +//! clauses can be combined and put in arbitrary order. Only `from` and +//! `context` can be used multiple times in single variant of enumeration. +//! Docstrings are also okay. Empty braces can be omitted as of quick_error +//! 0.1.3. +//! +//! # Private Enums +//! +//! Since quick-error 1.2.0 we have a way to make a private enum that is +//! wrapped by public structure: +//! +//! ```rust +//! #[macro_use] extern crate quick_error; +//! # fn main() {} +//! +//! quick_error! { +//! #[derive(Debug)] +//! pub enum PubError wraps ErrorEnum { +//! Variant1 {} +//! } +//! } +//! ``` +//! +//! This generates data structures like this +//! +//! ```rust +//! +//! pub struct PubError(ErrorEnum); +//! +//! enum ErrorEnum { +//! Variant1, +//! } +//! +//! ``` +//! +//! Which in turn allows you to export just `PubError` in your crate and keep +//! actual enumeration private to the crate. This is useful to keep backwards +//! compatibility for error types. Currently there is no shorcuts to define +//! error constructors for the inner type, but we consider adding some in +//! future versions. +//! +//! It's possible to declare internal enum as public too. +//! +//! + +/// Main macro that does all the work +#[macro_export] +macro_rules! quick_error { + + ( $(#[$meta:meta])* + pub enum $name:ident { $($chunks:tt)* } + ) => { + quick_error!(SORT [pub enum $name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + ( $(#[$meta:meta])* + enum $name:ident { $($chunks:tt)* } + ) => { + quick_error!(SORT [enum $name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + + ( $(#[$meta:meta])* + pub enum $name:ident wraps $enum_name:ident { $($chunks:tt)* } + ) => { + quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*); + quick_error!(SORT [enum $enum_name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + + ( $(#[$meta:meta])* + pub enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* } + ) => { + quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*); + quick_error!(SORT [pub enum $enum_name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + ( $(#[$meta:meta])* + enum $name:ident wraps $enum_name:ident { $($chunks:tt)* } + ) => { + quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*); + quick_error!(SORT [enum $enum_name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + + ( $(#[$meta:meta])* + enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* } + ) => { + quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*); + quick_error!(SORT [pub enum $enum_name $(#[$meta])* ] + items [] buf [] + queue [ $($chunks)* ]); + }; + + + ( + WRAPPER $internal:ident [ $($strdef:tt)* ] $strname:ident + $(#[$meta:meta])* + ) => { + $(#[$meta])* + $($strdef)* $strname ( $internal ); + + impl ::std::fmt::Display for $strname { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) + -> ::std::fmt::Result + { + ::std::fmt::Display::fmt(&self.0, f) + } + } + + impl From<$internal> for $strname { + fn from(err: $internal) -> Self { + $strname(err) + } + } + + impl ::std::error::Error for $strname { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.0.source() + } + } + }; + + // Queue is empty, can do the work + (SORT [enum $name:ident $( #[$meta:meta] )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [ ] + queue [ ] + ) => { + quick_error!(ENUM_DEFINITION [enum $name $( #[$meta] )*] + body [] + queue [$($( #[$imeta] )* + => $iitem: $imode [$( $ivar: $ityp ),*] )*] + ); + quick_error!(IMPLEMENTATIONS $name {$( + $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*} + )*}); + $( + quick_error!(ERROR_CHECK $imode $($ifuncs)*); + )* + }; + (SORT [pub enum $name:ident $( #[$meta:meta] )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [ ] + queue [ ] + ) => { + quick_error!(ENUM_DEFINITION [pub enum $name $( #[$meta] )*] + body [] + queue [$($( #[$imeta] )* + => $iitem: $imode [$( $ivar: $ityp ),*] )*] + ); + quick_error!(IMPLEMENTATIONS $name {$( + $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*} + )*}); + $( + quick_error!(ERROR_CHECK $imode $($ifuncs)*); + )* + }; + // Add meta to buffer + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )*] + queue [ #[$qmeta:meta] $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*] + buf [$( #[$bmeta] )* #[$qmeta] ] + queue [$( $tail )*]); + }; + // Add ident to buffer + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )*] + queue [ $qitem:ident $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* + => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*] + buf [$(#[$bmeta])* => $qitem : UNIT [ ] ] + queue [$( $tail )*]); + }; + // Flush buffer on meta after ident + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* + => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ] + queue [ #[$qmeta:meta] $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$($( #[$imeta:meta] )* + => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )* + $bitem: $bmode [$( $bvar:$btyp ),*] {} ] + buf [ #[$qmeta] ] + queue [$( $tail )*]); + }; + // Add tuple enum-variant + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ] + queue [($( $qvar:ident: $qtyp:ty ),+) $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*] + buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),+] ] + queue [$( $tail )*] + ); + }; + // Add struct enum-variant - e.g. { descr: &'static str } + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ] + queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*] + buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ] + queue [$( $tail )*]); + }; + // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, } + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ] + queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*] + buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ] + queue [$( $tail )*]); + }; + // Add braces and flush always on braces + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* + => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ] + queue [ {$( $qfuncs:tt )*} $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )* + $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ] + buf [ ] + queue [$( $tail )*]); + }; + // Flush buffer on double ident + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* + => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ] + queue [ $qitem:ident $( $tail:tt )*] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )* + $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ] + buf [ => $qitem : UNIT [ ] ] + queue [$( $tail )*]); + }; + // Flush buffer on end + (SORT [$( $def:tt )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [$( #[$bmeta:meta] )* + => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ] + queue [ ] + ) => { + quick_error!(SORT [$( $def )*] + items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )* + $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ] + buf [ ] + queue [ ]); + }; + // Public enum (Queue Empty) + (ENUM_DEFINITION [pub enum $name:ident $( #[$meta:meta] )*] + body [$($( #[$imeta:meta] )* + => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ] + queue [ ] + ) => { + #[allow(unknown_lints)] // no unused_doc_comments in older rust + #[allow(renamed_and_removed_lints)] + #[allow(unused_doc_comment)] + #[allow(unused_doc_comments)] + $(#[$meta])* + pub enum $name { + $( + $(#[$imeta])* + $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*, + )* + } + }; + // Private enum (Queue Empty) + (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*] + body [$($( #[$imeta:meta] )* + => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ] + queue [ ] + ) => { + #[allow(unknown_lints)] // no unused_doc_comments in older rust + #[allow(renamed_and_removed_lints)] + #[allow(unused_doc_comment)] + #[allow(unused_doc_comments)] + $(#[$meta])* + enum $name { + $( + $(#[$imeta])* + $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*, + )* + } + }; + // Unit variant + (ENUM_DEFINITION [$( $def:tt )*] + body [$($( #[$imeta:meta] )* + => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ] + queue [$( #[$qmeta:meta] )* + => $qitem:ident: UNIT [ ] $( $queue:tt )*] + ) => { + quick_error!(ENUM_DEFINITION [ $($def)* ] + body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )* + $( #[$qmeta] )* => $qitem () {} ] + queue [ $($queue)* ] + ); + }; + // Tuple variant + (ENUM_DEFINITION [$( $def:tt )*] + body [$($( #[$imeta:meta] )* + => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ] + queue [$( #[$qmeta:meta] )* + => $qitem:ident: TUPLE [$( $qvar:ident: $qtyp:ty ),+] $( $queue:tt )*] + ) => { + quick_error!(ENUM_DEFINITION [ $($def)* ] + body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )* + $( #[$qmeta] )* => $qitem (($( $qtyp ),+)) {} ] + queue [ $($queue)* ] + ); + }; + // Struct variant + (ENUM_DEFINITION [$( $def:tt )*] + body [$($( #[$imeta:meta] )* + => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ] + queue [$( #[$qmeta:meta] )* + => $qitem:ident: STRUCT [$( $qvar:ident: $qtyp:ty ),*] $( $queue:tt )*] + ) => { + quick_error!(ENUM_DEFINITION [ $($def)* ] + body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )* + $( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ] + queue [ $($queue)* ] + ); + }; + (IMPLEMENTATIONS + $name:ident {$( + $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*} + )*} + ) => { + #[allow(unused_variables)] + #[allow(unknown_lints)] // no unused_doc_comments in older rust + #[allow(renamed_and_removed_lints)] + #[allow(unused_doc_comment)] + #[allow(unused_doc_comments)] + impl ::std::fmt::Display for $name { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) + -> ::std::fmt::Result + { + match *self { + $( + $(#[$imeta])* + quick_error!(ITEM_PATTERN + $name $item: $imode [$( ref $var ),*] + ) => { + let display_fn = quick_error!(FIND_DISPLAY_IMPL + $name $item: $imode + {$( $funcs )*}); + + display_fn(self, fmt) + } + )* + } + } + } + #[allow(unused_variables)] + #[allow(unknown_lints)] // no unused_doc_comments in older rust + #[allow(renamed_and_removed_lints)] + #[allow(unused_doc_comment)] + #[allow(unused_doc_comments)] + impl ::std::error::Error for $name { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + $( + $(#[$imeta])* + quick_error!(ITEM_PATTERN + $name $item: $imode [$( ref $var ),*] + ) => { + quick_error!(FIND_SOURCE_IMPL + $item: $imode [$( $var ),*] + {$( $funcs )*}) + } + )* + } + } + } + $( + quick_error!(FIND_FROM_IMPL + $name $item: $imode [$( $var:$typ ),*] + {$( $funcs )*}); + )* + $( + quick_error!(FIND_CONTEXT_IMPL + $name $item: $imode [$( $var:$typ ),*] + {$( $funcs )*}); + )* + }; + (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt + { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*} + ) => { + |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $( $exprs )*) } + }; + (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt + { display($pattern:expr) $( $tail:tt )*} + ) => { + |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) } + }; + (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt + { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*} + ) => { + |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern, $( $exprs )*) } + }; + (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt + { $t:tt $( $tail:tt )*} + ) => { + quick_error!(FIND_DISPLAY_IMPL + $name $item: $imode + {$( $tail )*}) + }; + (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt + { } + ) => { + |self_: &$name, f: &mut ::std::fmt::Formatter<'_>| { + write!(f, "{:?}", self_) + } + }; + (FIND_SOURCE_IMPL $item:ident: $imode:tt + [$( $var:ident ),*] + { source($expr:expr) $( $tail:tt )*} + ) => { + Some($expr) + }; + (FIND_SOURCE_IMPL $item:ident: $imode:tt + [$( $var:ident ),*] + { $t:tt $( $tail:tt )*} + ) => { + quick_error!(FIND_SOURCE_IMPL + $item: $imode [$( $var ),*] + { $($tail)* }) + }; + (FIND_SOURCE_IMPL $item:ident: $imode:tt + [$( $var:ident ),*] + { } + ) => { + None + }; + // ----------------------------- FROM IMPL -------------------------- + (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt + [$( $var:ident: $typ:ty ),*] + { from() $( $tail:tt )*} + ) => { + $( + impl From<$typ> for $name { + fn from($var: $typ) -> $name { + $name::$item($var) + } + } + )* + quick_error!(FIND_FROM_IMPL + $name $item: $imode [$( $var:$typ ),*] + {$( $tail )*}); + }; + (FIND_FROM_IMPL $name:ident $item:ident: UNIT + [ ] + { from($ftyp:ty) $( $tail:tt )*} + ) => { + impl From<$ftyp> for $name { + fn from(_discarded_error: $ftyp) -> $name { + $name::$item + } + } + quick_error!(FIND_FROM_IMPL + $name $item: UNIT [ ] + {$( $tail )*}); + }; + (FIND_FROM_IMPL $name:ident $item:ident: TUPLE + [$( $var:ident: $typ:ty ),*] + { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*} + ) => { + impl From<$ftyp> for $name { + fn from($fvar: $ftyp) -> $name { + $name::$item($( $texpr ),*) + } + } + quick_error!(FIND_FROM_IMPL + $name $item: TUPLE [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_FROM_IMPL $name:ident $item:ident: STRUCT + [$( $var:ident: $typ:ty ),*] + { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*} + ) => { + impl From<$ftyp> for $name { + fn from($fvar: $ftyp) -> $name { + $name::$item { + $( $tvar: $texpr ),* + } + } + } + quick_error!(FIND_FROM_IMPL + $name $item: STRUCT [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt + [$( $var:ident: $typ:ty ),*] + { $t:tt $( $tail:tt )*} + ) => { + quick_error!(FIND_FROM_IMPL + $name $item: $imode [$( $var:$typ ),*] + {$( $tail )*} + ); + }; + (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt + [$( $var:ident: $typ:ty ),*] + { } + ) => { + }; + // ----------------------------- CONTEXT IMPL -------------------------- + (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE + [$( $var:ident: $typ:ty ),*] + { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty) + -> ($( $texpr:expr ),*) $( $tail:tt )* } + ) => { + impl> From<$crate::Context> for $name { + fn from( + $crate::Context($cvar, $fvar): $crate::Context) + -> $name + { + $name::$item($( $texpr ),*) + } + } + quick_error!(FIND_CONTEXT_IMPL + $name $item: TUPLE [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE + [$( $var:ident: $typ:ty ),*] + { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty) + -> ($( $texpr:expr ),*) $( $tail:tt )* } + ) => { + impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name { + fn from( + $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>) + -> $name + { + $name::$item($( $texpr ),*) + } + } + quick_error!(FIND_CONTEXT_IMPL + $name $item: TUPLE [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT + [$( $var:ident: $typ:ty ),*] + { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty) + -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* } + ) => { + impl> From<$crate::Context> for $name { + fn from( + $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>) + -> $name + { + $name::$item { + $( $tvar: $texpr ),* + } + } + } + quick_error!(FIND_CONTEXT_IMPL + $name $item: STRUCT [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT + [$( $var:ident: $typ:ty ),*] + { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty) + -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* } + ) => { + impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name { + fn from( + $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>) + -> $name + { + $name::$item { + $( $tvar: $texpr ),* + } + } + } + quick_error!(FIND_CONTEXT_IMPL + $name $item: STRUCT [$( $var:$typ ),*] + { $($tail)* }); + }; + (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt + [$( $var:ident: $typ:ty ),*] + { $t:tt $( $tail:tt )*} + ) => { + quick_error!(FIND_CONTEXT_IMPL + $name $item: $imode [$( $var:$typ ),*] + {$( $tail )*} + ); + }; + (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt + [$( $var:ident: $typ:ty ),*] + { } + ) => { + }; + // ----------------------------- ITEM IMPL -------------------------- + (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT + ) => { }; + (ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE + [$( $typ:ty ),*] + ) => { + ($( $typ ),*) + }; + (ITEM_BODY $(#[$imeta:meta])* $item:ident: STRUCT + [$( $var:ident: $typ:ty ),*] + ) => { + {$( $var:$typ ),*} + }; + (ITEM_PATTERN $name:ident $item:ident: UNIT [] + ) => { + $name::$item + }; + (ITEM_PATTERN $name:ident $item:ident: TUPLE + [$( ref $var:ident ),*] + ) => { + $name::$item ($( ref $var ),*) + }; + (ITEM_PATTERN $name:ident $item:ident: STRUCT + [$( ref $var:ident ),*] + ) => { + $name::$item {$( ref $var ),*} + }; + // This one should match all allowed sequences in "funcs" but not match + // anything else. + // This is to contrast FIND_* clauses which just find stuff they need and + // skip everything else completely + (ERROR_CHECK $imode:tt display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK $imode:tt display($pattern: expr) $( $tail:tt )*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK $imode:tt source($expr:expr) $($tail:tt)*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK $imode:tt from() $($tail:tt)*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*) + => { quick_error!(ERROR_CHECK $imode $($tail)*); }; + (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*) + => { quick_error!(ERROR_CHECK TUPLE $($tail)*); }; + (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*) + => { quick_error!(ERROR_CHECK STRUCT $($tail)*); }; + + (ERROR_CHECK TUPLE context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty) + -> ($( $e:expr ),*) $( $tail:tt )*) + => { quick_error!(ERROR_CHECK TUPLE $($tail)*); }; + (ERROR_CHECK STRUCT context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty) + -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*) + => { quick_error!(ERROR_CHECK STRUCT $($tail)*); }; + + (ERROR_CHECK $imode:tt ) => {}; + // Utility functions + (IDENT $ident:ident) => { $ident } +} + +/// Generic context type +/// +/// Used mostly as a transport for `ResultExt::context` method +#[derive(Debug)] +pub struct Context(pub X, pub E); + +/// Result extension trait adding a `context` method +pub trait ResultExt { + /// The method is use to add context information to current operation + /// + /// The context data is then used in error constructor to store additional + /// information within error. For example, you may add a filename as a + /// context for file operation. See crate documentation for the actual + /// example. + fn context(self, x: X) -> Result>; +} + +impl ResultExt for Result { + fn context(self, x: X) -> Result> { + self.map_err(|e| Context(x, e)) + } +} + +#[cfg(test)] +mod test { + use std::error::Error; + use std::num::{ParseFloatError, ParseIntError}; + use std::path::{Path, PathBuf}; + use std::str::Utf8Error; + use std::string::FromUtf8Error; + + use super::ResultExt; + + quick_error! { + #[derive(Debug)] + pub enum Bare { + One + Two + } + } + + #[test] + fn bare_item_direct() { + assert_eq!(format!("{}", Bare::One), "One".to_string()); + assert_eq!(format!("{:?}", Bare::One), "One".to_string()); + assert!(Bare::One.source().is_none()); + } + + #[test] + fn bare_item_trait() { + let err: &dyn Error = &Bare::Two; + assert_eq!(format!("{}", err), "Two".to_string()); + assert_eq!(format!("{:?}", err), "Two".to_string()); + assert!(err.source().is_none()); + } + + quick_error! { + #[derive(Debug)] + pub enum Wrapper wraps Wrapped { + One + Two(s: String) { + display("two: {}", s) + from() + } + } + } + + #[test] + fn wrapper() { + assert_eq!( + format!("{}", Wrapper::from(Wrapped::One)), + "One".to_string() + ); + assert_eq!( + format!("{}", Wrapper::from(Wrapped::from(String::from("hello")))), + "two: hello".to_string() + ); + assert_eq!( + format!("{:?}", Wrapper::from(Wrapped::One)), + "Wrapper(One)".to_string() + ); + } + + quick_error! { + #[derive(Debug, PartialEq)] + pub enum TupleWrapper { + /// ParseFloat Error + ParseFloatError(err: ParseFloatError) { + from() + display("parse float error: {err}", err=err) + source(err) + } + Other(descr: &'static str) { + display("Error: {}", descr) + } + /// FromUtf8 Error + FromUtf8Error(err: Utf8Error, source: Vec) { + source(err) + display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err) + from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes()) + } + Discard { + from(&'static str) + } + Singleton { + display("Just a string") + } + } + } + + #[test] + fn tuple_wrapper_err() { + let source = "one and a half times pi".parse::().unwrap_err(); + let err = TupleWrapper::ParseFloatError(source.clone()); + assert_eq!(format!("{}", err), format!("parse float error: {}", source)); + assert_eq!( + format!("{:?}", err), + format!("ParseFloatError({:?})", source) + ); + assert_eq!( + format!("{:?}", err.source().unwrap()), + format!("{:?}", source) + ); + } + + #[test] + fn tuple_wrapper_trait_str() { + let desc = "hello"; + let err: &dyn Error = &TupleWrapper::Other(desc); + assert_eq!(format!("{}", err), format!("Error: {}", desc)); + assert_eq!(format!("{:?}", err), format!("Other({:?})", desc)); + assert!(err.source().is_none()); + } + + #[test] + fn tuple_wrapper_trait_two_fields() { + let invalid_utf8: Vec = vec![0, 159, 146, 150]; + let source = String::from_utf8(invalid_utf8.clone()) + .unwrap_err() + .utf8_error(); + let err: &dyn Error = &TupleWrapper::FromUtf8Error(source.clone(), invalid_utf8.clone()); + assert_eq!( + format!("{}", err), + format!( + "{desc} at index {pos}: {source}", + desc = "utf8 error", + pos = source.valid_up_to(), + source = source + ) + ); + assert_eq!( + format!("{:?}", err), + format!("FromUtf8Error({:?}, {:?})", source, invalid_utf8) + ); + assert_eq!( + format!("{:?}", err.source().unwrap()), + format!("{:?}", source) + ); + } + + #[test] + fn tuple_wrapper_from() { + let source = "one and a half times pi".parse::().unwrap_err(); + let err = TupleWrapper::ParseFloatError(source.clone()); + let err_from: TupleWrapper = From::from(source); + assert_eq!(err_from, err); + } + + #[test] + fn tuple_wrapper_custom_from() { + let invalid_utf8: Vec = vec![0, 159, 146, 150]; + let source = String::from_utf8(invalid_utf8.clone()).unwrap_err(); + let err = TupleWrapper::FromUtf8Error(source.utf8_error().clone(), invalid_utf8); + let err_from: TupleWrapper = From::from(source); + assert_eq!(err_from, err); + } + + #[test] + fn tuple_wrapper_discard() { + let err: TupleWrapper = From::from("hello"); + assert_eq!(format!("{}", err), format!("Discard")); + assert_eq!(format!("{:?}", err), format!("Discard")); + assert!(err.source().is_none()); + } + + #[test] + fn tuple_wrapper_singleton() { + let err: TupleWrapper = TupleWrapper::Singleton; + assert_eq!(format!("{}", err), format!("Just a string")); + assert_eq!(format!("{:?}", err), format!("Singleton")); + assert!(err.source().is_none()); + } + + quick_error! { + #[derive(Debug, PartialEq)] + pub enum StructWrapper { + // Utf8 Error + Utf8Error{ err: Utf8Error, hint: Option<&'static str> } { + source(err) + display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err) + from(err: Utf8Error) -> { err: err, hint: None } + } + // Utf8 Error + ExcessComma { descr: &'static str, } { + display("Error: {}", descr) + } + } + } + + #[test] + fn struct_wrapper_err() { + let invalid_utf8: Vec = vec![0, 159, 146, 150]; + let source = String::from_utf8(invalid_utf8.clone()) + .unwrap_err() + .utf8_error(); + let err: &dyn Error = &StructWrapper::Utf8Error { + err: source.clone(), + hint: Some("nonsense"), + }; + assert_eq!( + format!("{}", err), + format!( + "{desc} at index {pos}: {source}", + desc = "utf8 error", + pos = source.valid_up_to(), + source = source + ) + ); + assert_eq!( + format!("{:?}", err), + format!( + "Utf8Error {{ err: {:?}, hint: {:?} }}", + source, + Some("nonsense") + ) + ); + assert_eq!( + format!("{:?}", err.source().unwrap()), + format!("{:?}", source) + ); + } + + #[test] + fn struct_wrapper_struct_from() { + let invalid_utf8: Vec = vec![0, 159, 146, 150]; + let source = String::from_utf8(invalid_utf8.clone()) + .unwrap_err() + .utf8_error(); + let err = StructWrapper::Utf8Error { + err: source.clone(), + hint: None, + }; + let err_from: StructWrapper = From::from(source); + assert_eq!(err_from, err); + } + + #[test] + fn struct_wrapper_excess_comma() { + let descr = "hello"; + let err = StructWrapper::ExcessComma { descr: descr }; + assert_eq!(format!("{}", err), format!("Error: {}", descr)); + assert_eq!( + format!("{:?}", err), + format!("ExcessComma {{ descr: {:?} }}", descr) + ); + assert!(err.source().is_none()); + } + + quick_error! { + #[derive(Debug)] + pub enum ContextErr { + Float(src: String, err: ParseFloatError) { + context(s: &'a str, e: ParseFloatError) -> (s.to_string(), e) + display("Float error {:?}: {}", src, err) + } + Int { src: String, err: ParseIntError } { + context(s: &'a str, e: ParseIntError) + -> {src: s.to_string(), err: e} + display("Int error {:?}: {}", src, err) + } + Utf8(path: PathBuf, err: Utf8Error) { + context(p: AsRef, e: Utf8Error) + -> (p.as_ref().to_path_buf(), e) + display("Path error at {:?}: {}", path, err) + } + Utf8Str(s: String, err: ::std::io::Error) { + context(s: AsRef, e: ::std::io::Error) + -> (s.as_ref().to_string(), e) + display("Str error {:?}: {}", s, err) + } + } + } + + #[test] + fn parse_float_error() { + fn parse_float(s: &str) -> Result { + Ok(s.parse().context(s)?) + } + assert_eq!( + format!("{}", parse_float("12ab").unwrap_err()), + r#"Float error "12ab": invalid float literal"# + ); + } + + #[test] + fn parse_int_error() { + fn parse_int(s: &str) -> Result { + Ok(s.parse().context(s)?) + } + assert_eq!( + format!("{}", parse_int("12.5").unwrap_err()), + r#"Int error "12.5": invalid digit found in string"# + ); + } + + #[test] + fn debug_context() { + fn parse_int(s: &str) -> i32 { + s.parse().context(s).unwrap() + } + assert_eq!(parse_int("12"), 12); + assert_eq!( + format!("{:?}", "x".parse::().context("x")), + r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"# + ); + } + + #[test] + fn path_context() { + fn parse_utf>(s: &[u8], p: P) -> Result<(), ContextErr> { + ::std::str::from_utf8(s).context(p)?; + Ok(()) + } + let etext = parse_utf(b"a\x80\x80", "/etc").unwrap_err().to_string(); + assert!(etext.starts_with("Path error at \"/etc\": invalid utf-8")); + let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp")) + .unwrap_err() + .to_string(); + assert!(etext.starts_with("Path error at \"/tmp\": invalid utf-8")); + } + + #[test] + fn conditional_compilation() { + quick_error! { + #[allow(dead_code)] + #[derive(Debug)] + pub enum Test { + #[cfg(feature = "foo")] + Variant + } + } + } + + #[test] + #[allow(deprecated)] + fn cause_struct_wrapper_err() { + let invalid_utf8: Vec = vec![0, 159, 146, 150]; + let cause = String::from_utf8(invalid_utf8.clone()) + .unwrap_err() + .utf8_error(); + let err: &dyn Error = &StructWrapper::Utf8Error { + err: cause.clone(), + hint: Some("nonsense"), + }; + assert_eq!( + format!("{}", err), + format!( + "{desc} at index {pos}: {cause}", + desc = "utf8 error", + pos = cause.valid_up_to(), + cause = cause + ) + ); + assert_eq!( + format!("{:?}", err), + format!( + "Utf8Error {{ err: {:?}, hint: {:?} }}", + cause, + Some("nonsense") + ) + ); + assert_eq!( + format!("{:?}", err.cause().unwrap()), + format!("{:?}", cause) + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quick-error/vagga.yaml clamav-1.4.6+dfsg/.cargo/vendor/quick-error/vagga.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/quick-error/vagga.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quick-error/vagga.yaml 1970-01-01 00:00:01.000000000 +0000 @@ -0,0 +1,36 @@ +commands: + + cargo: !Command + description: Run any cargo command + container: ubuntu + run: [cargo] + + test: !Command + description: Run unit tests + container: ubuntu + run: [cargo, test] + + _bulk: !Command + description: Run `bulk` command (for version bookkeeping) + container: ubuntu + run: [bulk] + +containers: + + ubuntu: + setup: + - !Ubuntu xenial + - !Install [ca-certificates, build-essential, vim] + + - !TarInstall + url: "https://static.rust-lang.org/dist/rust-1.31.0-x86_64-unknown-linux-gnu.tar.gz" + script: "./install.sh --prefix=/usr \ + --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo" + - &bulk !Tar + url: "https://github.com/tailhook/bulk/releases/download/v0.4.10/bulk-v0.4.10.tar.gz" + sha256: 481513f8a0306a9857d045497fb5b50b50a51e9ff748909ecf7d2bda1de275ab + path: / + + environ: + HOME: /work/target + USER: pc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quote/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/quote/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"0a98ab1241e7b64caa29c6ff868e2e96e0f74c1ef8b265727f1863a960fa322c","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"626e7079eab0baacf0fcaf3e244f407b2014ebaeca45905d72e8fb8bed18aaea","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"9881576cac3e476a4bf04f9b601cf9a53b79399fb0ca9634e8b861ac91709843","src/format.rs":"c595015418f35e6992e710441b9999f09b2afe4678b138039d670d100c0bdd86","src/ident_fragment.rs":"0b3e6c2129e55910fd2d240e1e7efba6f1796801d24352d1c0bfbceb0e8b678f","src/lib.rs":"abbc178821e46d0bcd224904a7542ac4582d189f57cd4daf02a54fd772e52a55","src/runtime.rs":"7f37326edaeac2c42ed806b447eeba12e36dd4b1bc25fbf52f8eb23140f3be7a","src/spanned.rs":"3ccf5120593f35787442c0a37d243e802c5262e7f8b35aed503873008ec035c5","src/to_tokens.rs":"1c76311fcc82098e630056d71fd6f3929194ee31b0840e2aa643ed7e78026e3e","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"3be80741f84a707376c230d9cf70ce9537caa359691d8d4c34968e28175e4ad7","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"90a4bdb9267535f5d2785940148338d6b7d905548051d2c9c5dcbd58f2c11d8e","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"ae7c2739554c862b331705e82781aa4687a4375210cef6ae899a4be4a4ec2d97","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"03fd560979ebcd5aa6f83858bc2c3c01ba6546c16335101275505304895c1ae9","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"d6da483c29e232ced72059bbdf05d31afb1df9e02954edaa9cfaea1ec6df72dc","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"1b5ad13712a35f2f25a159c003956762941b111d540b20ad6a258cdb079a9c95","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"bbfb702638374001061251f81d63476851ac28ed743f13db9d65e30dd9bdcf52","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"cad072e40e0ecc04f375122ae41aede2f0da2a9244492b3fcf70249e59d1b128"},"package":"0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5afa3c7eb1330479c34de42d8564f864d7c57da0fd3389d275f7c74ae2560e7a",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"0a4eec2e7c7eb933db239cbb92d4c5fc866f5d56d8646ffae8c817201912236e","Cargo.toml":"0a98ab1241e7b64caa29c6ff868e2e96e0f74c1ef8b265727f1863a960fa322c","Cargo.toml.orig":"692d312e91718f875a36b5018b9df713bb7b02b37247b9bbd17dca2eca46dd07","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"626e7079eab0baacf0fcaf3e244f407b2014ebaeca45905d72e8fb8bed18aaea","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"9881576cac3e476a4bf04f9b601cf9a53b79399fb0ca9634e8b861ac91709843","src/format.rs":"c595015418f35e6992e710441b9999f09b2afe4678b138039d670d100c0bdd86","src/ident_fragment.rs":"0b3e6c2129e55910fd2d240e1e7efba6f1796801d24352d1c0bfbceb0e8b678f","src/lib.rs":"abbc178821e46d0bcd224904a7542ac4582d189f57cd4daf02a54fd772e52a55","src/runtime.rs":"7f37326edaeac2c42ed806b447eeba12e36dd4b1bc25fbf52f8eb23140f3be7a","src/spanned.rs":"3ccf5120593f35787442c0a37d243e802c5262e7f8b35aed503873008ec035c5","src/to_tokens.rs":"1c76311fcc82098e630056d71fd6f3929194ee31b0840e2aa643ed7e78026e3e","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"3be80741f84a707376c230d9cf70ce9537caa359691d8d4c34968e28175e4ad7","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"90a4bdb9267535f5d2785940148338d6b7d905548051d2c9c5dcbd58f2c11d8e","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"ae7c2739554c862b331705e82781aa4687a4375210cef6ae899a4be4a4ec2d97","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"03fd560979ebcd5aa6f83858bc2c3c01ba6546c16335101275505304895c1ae9","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"d6da483c29e232ced72059bbdf05d31afb1df9e02954edaa9cfaea1ec6df72dc","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"1b5ad13712a35f2f25a159c003956762941b111d540b20ad6a258cdb079a9c95","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"bbfb702638374001061251f81d63476851ac28ed743f13db9d65e30dd9bdcf52","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"cad072e40e0ecc04f375122ae41aede2f0da2a9244492b3fcf70249e59d1b128"},"package":"0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quote/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/quote/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quote/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5d4880c4255b5c7f5ea0a9ac3cf9f985c418a1e7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quote/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/quote/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quote/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/quote/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quote/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,104 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, stable, beta, 1.56.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + - run: cargo run --manifest-path benches/Cargo.toml + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --tests --workspace -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/quote/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/quote/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/quote/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/quote/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +[package] +name = "quote" +version = "1.0.36" # don't forget to update html_root_url, version in readme for breaking changes +authors = ["David Tolnay "] +autobenches = false +categories = ["development-tools::procedural-macro-helpers"] +description = "Quasi-quoting macro quote!(...)" +documentation = "https://docs.rs/quote/" +edition = "2018" +keywords = ["macros", "syn"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/quote" +rust-version = "1.56" + +[dependencies] +proc-macro2 = { version = "1.0.74", default-features = false } + +[dev-dependencies] +rustversion = "1.0" +trybuild = { version = "1.0.66", features = ["diff"] } + +[features] +default = ["proc-macro"] +# Disabling the proc-macro feature removes the dynamic library dependency on +# libproc_macro in the rustc compiler. +proc-macro = ["proc-macro2/proc-macro"] + +[lib] +doc-scrape-examples = false + +[workspace] +members = ["benches"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"50e0c72ee0164f182d7b5db0213cdb1626bad950f2443b05d006c28c7f0641b5",".github/workflows/publish.yml":"431c68b9d566180134e8771ea9cb9339d72ec77c3010b4cedfd423e271dc7386",".github/workflows/rust-tests.yml":"ca7ba173da0a6510676770b103119ce57029d424afe9e1027541d529af6c7f3f","AUTHORS":"ff92bed461f50338dd703a9ba9aee496a425957873df1d91192776e4bdf5dda7","Cargo.lock":"cc335892128a13fb1431213f65cfd3281ff098cf47b97882ca097f0206d7e0b0","Cargo.toml":"dba000c0173b09b1e3b69afa42a715b5ab64355e6502ce6d9d1767c7845cf402","Cargo.toml.orig":"57b6d9b9a1b6524f6b4dcc1dd24970ac03e6959786a6cfedaec9ba52878b4d3e","Makefile":"b445cfadd750b564ba8ef072754a4eed5aa127f12faa6e5b15a35b748d28b6fb","NEWS.md":"a8924309f9b5d8cf035b12ee47d4afe99c3ca57ea60061239263ac0b0e2161ba","README.md":"420f65fec3ba2e89d49da51b222d2881d26959037a7b7d3794143db4bd4627b1","examples/freestanding.rs":"0be5eb60397228306aa9f8afc533e32926d210205a7359e14da903159482416d","examples/gop-query.rs":"3257c55d6ae4572db1bfcaf20bc05990ea92d46c5d292eb99c278242f1007e2c","examples/hello-world.rs":"1a398f93a54bfddaab6ba3e0145cf70496266c44b9748a11ff569a9a18063bc4","src/base.rs":"e0f0b69967dc436e302f37230f5aff0e8bf748f6a1159b968180e6d0ac0b9644","src/hii.rs":"d0b19b7cc7b0c2c4d70e2891554ed6d7f941388709476eab6fa7bad129c583ed","src/lib.rs":"289fdfa8384062616aa39b49c4094b93849ff0a2e5f6d7125b40124299a0837e","src/protocols.rs":"a8f1c0d9abf2af2d7962fce68160a3bf8083165bb70861808423afedadee6602","src/protocols/absolute_pointer.rs":"46ad9792ea021f47e4fedf8d3c07769872e056c39936c9647492a52455558b41","src/protocols/block_io.rs":"4f70d38453f057bb240988d7fac593ffa0f38a0057c6e8855f34ff37801e7f3d","src/protocols/bus_specific_driver_override.rs":"a695a18e6729020919f99880fb14c2a26f565471f15d6300cb67475d33ec6087","src/protocols/debug_support.rs":"a03fc44a2ad151e58eff3bd72f910b63bfadd5802ac2fc157fc94c2030bd9fa9","src/protocols/debugport.rs":"bc491b03444ec35593a9cde519d0ab5fc863a046073dd813f1eb58c075da45dc","src/protocols/decompress.rs":"a4c67d958f0b9a392840a53eef69369acc6f545f90369685b3cae3c32e5cbc51","src/protocols/device_path.rs":"1a8c897f8e392fd7fe60d829b7852d22dd847f5f64bf1382e58e7776d9a176a2","src/protocols/device_path_from_text.rs":"e972d7699fb031df9da2c4d5623ae289d4cc282116b634218039b97d1e7628fe","src/protocols/device_path_to_text.rs":"9929d0797ab4892051bd15ac831dc2566f7106ec9edec0fd289b3c780a2b0976","src/protocols/device_path_utilities.rs":"7d7e9ba66e9f8add3c77718bd605e6e434598f2834236e7805aba57b531eba30","src/protocols/disk_io.rs":"01a68686dae958b4fbd9fd5bbc556cf41b61e7da281a0b4ea56e62e61822d843","src/protocols/disk_io2.rs":"33aeb807ab9b78534787f44e0a3a8c52afe057e23b48ecb6703195cd0b135a8e","src/protocols/driver_binding.rs":"f48363c5afd21aac39cbd2644be0e861acc4b182bc14c68a4f84e94a5f001f8d","src/protocols/driver_diagnostics2.rs":"62b0ffe6760ae0e90e51652c667ec623cef3bbd44c17fb89881a24167b1b446c","src/protocols/driver_family_override.rs":"004aceae8540766d87eb2cef9c8c37ab5aa3755920af6d960cb9171a41acb4a1","src/protocols/file.rs":"25f09f54cf3ebd69366bde5160218247c6712ae19dac17a36ec4e2881b214f93","src/protocols/graphics_output.rs":"9e9b7ac05b92ac0a9680506edb3ed36ebbac2dc9c800268b2c54cbf539e9dd9e","src/protocols/hii_database.rs":"faa82d420085dee851f8a332db00c888e7ed1685d43e2c286790a34b2ecfdf7a","src/protocols/hii_font.rs":"092f45c74335c524ee379508e2b6925ed9033c7c10928e64b2489ca3778a4723","src/protocols/hii_font_ex.rs":"2400b2092c14da2aa09c62266356321d4b96838dc41c5918a2f3e0e1e3920318","src/protocols/hii_package_list.rs":"6bb29d076697bb3b672913b98f55995f9efcba830b4ab6bfed29bd8402aa70ab","src/protocols/hii_string.rs":"1327ba9e108900ddafec98c02534c81104c3c47cad32a7d17c7b7a7ee723c86f","src/protocols/ip4.rs":"252d244ec9b098fcee6a185ffa98cbdee34164c7872fe30b07d5e8dfdf7a8fe3","src/protocols/ip6.rs":"72a51653aa4535f7b136a7bacaa1718e0a68be847d4a716c6e76b7f75a94e6ea","src/protocols/load_file.rs":"8aa4a43db3da6c71398eb9408b2be9b893eb2147e5317a0f977e998db2910cba","src/protocols/load_file2.rs":"5be9c5d501b4f10a44ba91448fce5d4a20c01eab9a8f7fb3c63eaa62cbb1c2f4","src/protocols/loaded_image.rs":"508cf1514071e611f3c70776463a19f53685b3569c52a2350f307cbeac9cbbcc","src/protocols/loaded_image_device_path.rs":"66e8fe3477785dadf96401da10e203ba729e54d7eddedaffc4d17acc9a0daf7f","src/protocols/managed_network.rs":"592111dee58137a21f3b49211baf0d9c73a14ca9de95fa31d7e87435ded3808d","src/protocols/memory_attribute.rs":"c512ae777b95248127fc39b63eb99d746aaf8a5dc2cfda167d15ea5aa627653c","src/protocols/mp_services.rs":"509e7d483df52ab1ba1f9241bb7b286ffe205c4328557b3115cd290b4c9f8278","src/protocols/pci_io.rs":"43dac18dfa284d83836ff1ccfb8e40d48ef94533b72cdb99ce30a768f70be67c","src/protocols/platform_driver_override.rs":"f0ada483bccd90f31a6f0ce8831ea00885b66ca558e34e347ec775cbc171534c","src/protocols/rng.rs":"279ce976d190889064d0159b10586bab9a2e5670368b460be4497ead523d6dda","src/protocols/service_binding.rs":"256920333ea26fabd3b62ba8a8b25068349acab6da01a807dfba3307a45d79a0","src/protocols/shell.rs":"3259b0bf2574da6b2343da0b9ce46980d296a8e6d8c2fe36df3a07d0629ad653","src/protocols/shell_dynamic_command.rs":"9c2f977fe4e0757b633de49627a9645d81c821a39e752cb329f6285d376fe52d","src/protocols/shell_parameters.rs":"fb88c63822a14dc94e96f7912fa5409f68b669105fb81459b969ec066002e352","src/protocols/simple_file_system.rs":"e3d870bdaf3ae0f0cded7817a4eda6d5dea2e0b77855cd21c7ac05046c77b564","src/protocols/simple_network.rs":"8b8c49872488cc0e759efe74c04fc65f5d7637dca7d9a0a1cedb5dafb2597acb","src/protocols/simple_text_input.rs":"d9a7e8cbf508daedaa26dc8301e52be957edfcc12be9e962b8504584aee669a8","src/protocols/simple_text_input_ex.rs":"84ccd2ff2c354c0447a9c46406ad76de018495d5f85979cf35d78b7070a8f63c","src/protocols/simple_text_output.rs":"05857880b5c0a6fb6ce83eedcc7fa25107f368950ab18a3d0ef1ed669d3456df","src/protocols/tcp4.rs":"2131cf06fd856017ea45135fb59264a43fabc3db1b7ddc90cd19c169ccdacae9","src/protocols/tcp6.rs":"98c24c43632acc60f2dc558c13a03657f93edca735435c50b9f2cc5625f7d3bb","src/protocols/timestamp.rs":"118cc4a54da4f53a4bb2fbf66cde8c433208266a22b59b4e370393f5a40c20a9","src/protocols/udp4.rs":"c4d344a40c674524383be51621a485d15ccfffaa94a1050c7a4642199fa91bf6","src/protocols/udp6.rs":"ea4ee2154e045a4e5992688e6cafed2d5a5de41f2796f5c070e739818b361550","src/system.rs":"2428de82301085a5c99b1b54411530adf2c895aa311a58c94c1b8e9eb247b18f","src/vendor.rs":"6cc53fe0e98220fe627d82c9b27f1468095358bb26634a8c19274495888138af","src/vendor/intel/console_control.rs":"03a7fdf97ab1836353266786811ac47171d1c425dcead707f5ed0e2e834873fb"},"package":"69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "97b55bed1c2c91dcbf787674849f05337ff80b33" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.github/workflows/publish.yml clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/publish.yml --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.github/workflows/publish.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/publish.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +# +# Publish Releases +# +# This workflow can be manually triggered and will then publish the +# specified release to the configured release channels. +# + +name: "Publish Releases" + +on: + workflow_dispatch: + inputs: + tag: + description: "Git-Tag to Publish" + default: "" + required: true + verify: + description: "Verify package before publishing" + default: "yes" + required: false + +defaults: + run: + shell: "bash" + +jobs: + publish: + name: "Publish Crate" + uses: readaheadeu/rae-actions/.github/workflows/lib-publish-rust.yml@v1 + + permissions: + contents: write + + secrets: + ciotoken: ${{ secrets.DEPLOY_CRATESIO_TOKEN }} + + with: + tag: ${{ github.event.inputs.tag }} + verify: ${{ github.event.inputs.verify == 'yes' || false }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.github/workflows/rust-tests.yml clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/rust-tests.yml --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/.github/workflows/rust-tests.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/.github/workflows/rust-tests.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +# +# Rust Test Suite +# +# This workflow builds the project via Cargo, configures a suitable test +# environment, and then runs the test-suite defined in Cargo. +# + +name: "Rust Test Suite" + +on: + pull_request: + push: + branches-ignore: ["pr/**"] + tags: ["**"] + workflow_dispatch: + +defaults: + run: + shell: "bash" + +jobs: + # + # CI with Default Configuration + # + # This simply runs `cargo build && cargo test` on all sources. We want to + # explicitly ensure that this project stays compatible to the stable channel + # and the standard build setup. + # + ci: + name: "Default - rust-${{ matrix.rust }}@${{ matrix.os }}" + + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + rust: ["nightly", "stable"] + + runs-on: ${{ matrix.os }} + + steps: + - name: "Fetch Sources" + uses: actions/checkout@v3 + - name: "Install Rust Components" + run: rustup default "${{ matrix.rust }}" + - name: "Build Project" + run: cargo build --verbose --all-targets + - name: "Run Tests" + run: cargo test --verbose + + # + # Cross-Compilation to UEFI Target + # + # This cross-compiles all sources (including the examples) for native UEFI + # targets. This test ensures that we can actually compile for our main target + # platforms. + # + ci-cross: + name: "Cross-Compilation - ${{ matrix.target }}/rust-${{ matrix.rust }}@${{ matrix.os }}" + + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + rust: ["nightly", "stable"] + target: + - "aarch64-unknown-uefi" + - "i686-unknown-uefi" + - "x86_64-unknown-uefi" + + runs-on: ${{ matrix.os }} + + steps: + - name: "Fetch Sources" + uses: actions/checkout@v3 + - name: "Install Rust Components" + run: | + rustup default "${{ matrix.rust }}" + rustup target add --toolchain "${{ matrix.rust }}" "${{ matrix.target }}" + - name: "Build Project" + run: | + cargo build \ + --examples \ + --features native \ + --lib \ + --target "${{ matrix.target }}" \ + --verbose + + # + # Bootstrap to UEFI Target + # + # This uses the `-Zbuild-std` feature to fully bootstrap a native UEFI target + # via cross-compilation. This currently requires a nightly compiler. + # + ci-bootstrap: + name: "Bootstrap - ${{ matrix.target }}/rust-${{ matrix.rust }}@${{ matrix.os }}" + + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + rust: ["nightly"] + target: + - "aarch64-unknown-uefi" + - "i686-unknown-uefi" + - "x86_64-unknown-uefi" + + runs-on: ${{ matrix.os }} + + steps: + - name: "Fetch Sources" + uses: actions/checkout@v3 + - name: "Install Rust Components" + run: | + rustup default "${{ matrix.rust }}" + rustup component add --toolchain "${{ matrix.rust }}" rust-src + - name: "Build Project" + run: | + cargo build \ + -Zbuild-std=core,compiler_builtins,alloc \ + -Zbuild-std-features=compiler-builtins-mem \ + --examples \ + --features native \ + --lib \ + --target "${{ matrix.target }}" \ + --verbose diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/AUTHORS clamav-1.4.6+dfsg/.cargo/vendor/r-efi/AUTHORS --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/AUTHORS 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/AUTHORS 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +LICENSE: + This project is triple-licensed under the MIT License, the Apache + License, Version 2.0, and the GNU Lesser General Public License, + Version 2.1+. + +AUTHORS-MIT: + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +AUTHORS-ASL: + 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 + + http://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. + +AUTHORS-LGPL: + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; If not, see . + +COPYRIGHT: (ordered alphabetically) + Copyright (C) 2017-2023 Red Hat, Inc. + Copyright (C) 2019-2023 Microsoft Corporation + Copyright (C) 2022-2023 David Rheinsberg + +AUTHORS: (ordered alphabetically) + Alex James + Ayush Singh + Boris-Chengbiao Zhou + Bret Barkelew + Christopher Zurcher + David Rheinsberg + Dmitry Mostovenko + Hiroki Tokunaga + Joe Richey + John Schock + Michael Kubacki + Oliver Smith-Denny + Richard Wiedenhöft + Rob Bradford , + Tom Gundersen + Trevor Gross diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "r-efi" +version = "5.3.0" +dependencies = [ + "rustc-std-workspace-core", +] + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9c45b374136f52f2d6311062c7146bff20fec063c3f5d46a410bd937746955" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.68" +name = "r-efi" +version = "5.3.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "UEFI Reference Specification Protocol Constants and Definitions" +homepage = "https://github.com/r-efi/r-efi/wiki" +readme = "README.md" +keywords = [ + "boot", + "efi", + "firmware", + "specification", + "uefi", +] +categories = [ + "embedded", + "hardware-support", + "no-std", + "os", +] +license = "MIT OR Apache-2.0 OR LGPL-2.1-or-later" +repository = "https://github.com/r-efi/r-efi" + +[features] +efiapi = [] +examples = ["native"] +native = [] +rustc-dep-of-std = ["core"] + +[lib] +name = "r_efi" +path = "src/lib.rs" + +[[example]] +name = "freestanding" +path = "examples/freestanding.rs" +required-features = ["native"] + +[[example]] +name = "gop-query" +path = "examples/gop-query.rs" +required-features = ["native"] + +[[example]] +name = "hello-world" +path = "examples/hello-world.rs" +required-features = ["native"] + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +[package] +name = "r-efi" +version = "5.3.0" + +categories = [ + "embedded", + "hardware-support", + "no-std", + "os", +] +description = "UEFI Reference Specification Protocol Constants and Definitions" +edition = "2018" +homepage = "https://github.com/r-efi/r-efi/wiki" +keywords = [ + "boot", + "efi", + "firmware", + "specification", + "uefi", +] +license = "MIT OR Apache-2.0 OR LGPL-2.1-or-later" +readme = "README.md" +repository = "https://github.com/r-efi/r-efi" +rust-version = "1.68" + +[dependencies] +# Required setup to build as part of rustc. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } + +[features] +# No-op for backwards compatibility. +efiapi = [] +# Maps to `native` for backwards compatibility. +examples = ['native'] +# We feature-gate all native code, since it will not link correctly, unless you +# use a UEFI target configuration. To make `cargo test` work, we exclude all +# these from normal runs. +native = [] +rustc-dep-of-std = ['core'] + +[[example]] +name = "freestanding" +required-features = ["native"] + +[[example]] +name = "gop-query" +required-features = ["native"] + +[[example]] +name = "hello-world" +required-features = ["native"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Makefile clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Makefile --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/Makefile 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +# +# Maintenance Makefile +# + +# Enforce bash with fatal errors. +SHELL := /bin/bash -eo pipefail + +# Keep intermediates around on failures for better caching. +.SECONDARY: + +# Default build and source directories. +BUILDDIR ?= ./build +SRCDIR ?= . + +# +# Target: help +# + +.PHONY: help +help: + @# 80-width marker: + @# 01234567012345670123456701234567012345670123456701234567012345670123456701234567 + @echo "make [TARGETS...]" + @echo + @echo "The following targets are provided by this maintenance makefile:" + @echo + @echo " help: Print this usage information" + @echo + @echo " publish-github: Publish a release to GitHub" + +# +# Target: BUILDDIR +# + +$(BUILDDIR)/: + mkdir -p "$@" + +$(BUILDDIR)/%/: + mkdir -p "$@" + +# +# Target: FORCE +# +# Used as alternative to `.PHONY` if the target is not fixed. +# + +.PHONY: FORCE +FORCE: + +# +# Target: publish-* +# + +PUBLISH_REPO ?= r-efi/r-efi +PUBLISH_VERSION ?= + +define PUBLISH_RELNOTES_PY +with open('NEWS.md', 'r') as f: + notes = f.read().split("\n## CHANGES WITH ")[1:] + notes = dict(map(lambda v: (v[:v.find(":")], v), notes)) + notes = notes["$(PUBLISH_VERSION)"].strip() +print(" # r-efi - UEFI Reference Specification Protocol Constants and Definitions\n") +print(" ## CHANGES WITH", notes) +endef + +export PUBLISH_RELNOTES_PY +export PUBLISH_REPO +export PUBLISH_VERSION + +.PHONY: publish-github +publish-github: + test ! -z "$${PUBLISH_REPO}" + test ! -z "$${PUBLISH_VERSION}" + python \ + - \ + <<<"$${PUBLISH_RELNOTES_PY}" \ + | gh \ + release \ + --repo "$${PUBLISH_REPO}" \ + create \ + --verify-tag \ + --title \ + "r-efi-$${PUBLISH_VERSION}" \ + --notes-file - \ + "v$${PUBLISH_VERSION}" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/NEWS.md clamav-1.4.6+dfsg/.cargo/vendor/r-efi/NEWS.md --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/NEWS.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/NEWS.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,301 @@ +# r-efi - UEFI Reference Specification Protocol Constants and Definitions + +## CHANGES WITH 5.3.0: + + * Remove the optional dependency on `compiler-builtins`, which was + needed to build r-efi as part of rustc. This is no longer necessary. + + Contributions from: David Rheinsberg, Trevor Gross + + - Dußlingen, 2025-06-17 + +## CHANGES WITH 5.2.0: + + * Add the memory attribute protocol. + + Contributions from: David Rheinsberg, Oliver Smith-Denny + + - Dußlingen, 2024-12-22 + +## CHANGES WITH 5.1.0: + + * Mark `Guid::as_bytes` and `Guid::from_bytes` as `const fn`, aligning + them with the other methods on `Guid`. This helps creating constant + GUIDs via macros or other external helpers. + + Contributions from: Christopher Zurcher, David Rheinsberg + + - Dußlingen, 2024-09-01 + +## CHANGES WITH 5.0.0: + + * Change the type of the `unload` function-pointer of the Loaded Image + Protocol to `Option`, given that it can be `NULL` to indicate + that the image cannot be unloaded. + This is a major API break, but any users very likely need to adjust + anyway to avoid NULL-derefs. + + Contributions from: David Rheinsberg, John Schock + + - Dußlingen, 2024-07-30 + +## CHANGES WITH 4.5.0: + + * Implement or derive more standard traits for UEFI base types. In + particular, implement `[Partial]Eq`, `Hash`, `[Partial]Ord` for + `Boolean`, `Status`, `Guid`, and network address types. + + * Fix the signature of `BootUninstallMultipleProtocolInterfaces` to + match the UEFI specification. Note that it uses var-args and is thus + not fully usable from stable Rust. + + Contributions from: Ayush Singh, David Rheinsberg, John Schock + + - Dußlingen, 2024-05-23 + +## CHANGES WITH 4.4.0: + + * Add definitions for `UNACCEPTED_MEMORY_TYPE`, media device subtypes + for device paths, before-EBS and after-RTB event groups, missing + memory attributes. + + * Add memory masks for common memory attribute classes. The symbol + names are takend from EDK2, yet their purpose is defined in the + specification. + + * New protocols: platform_driver_override, bus_specific_driver_override, + driver_family_override, load_file, load_file2, pci-io + + Contributions from: David Rheinsberg, Dmitry Mostovenko, John Schock, + Michael Kubacki + + - Dußlingen, 2024-03-27 + +## CHANGES WITH 4.3.0: + + * Change alignment of `Guid` to 4 (was 8 before). This deviates from + the specification, but aligns with EDK2. This should fix alignment + mismatches when combining r-efi with EDK2, or other UEFI + implementations. + + * `Guid` gained a new constructor `from_bytes()` to allow creating + GUID-abstractions from foreign types based on the standardized + memory representation. + + * Add all configuration-table GUIDs mentioned in the spec. These are + often rooted in external specifications, but are strongly related + to UEFI. + + * Add configuration-table definitions for RT_PROPERTIES and + CONFORMANCE_PROFILES. + + * New protocols: hii_package_list, absolute_pointer + + Contributions from: David Rheinsberg, John Schock, Michael Kubacki, + Nicholas Bishop + + - Dußlingen, 2023-10-18 + +## CHANGES WITH 4.2.0: + + * Bump required compiler version to: rust-1.68 + + * New Protocols: debugport, debug-support, driver-diagnostics2, + mp-services, shell, shell-dynamic-command, + shell-parameters, udp-4, udp-6 + + * Use const-generics instead of ZSTs to represent dynamic trailing + members in C structs. + + * The `examples` feature has been renamed to `native` (a backwards + compatible feature is left in place). + + * Add support for riscv64. + + * Use the official rust `efiapi` calling convention. This was + stabilized with rust-1.68. + + Contributions from: Ayush Singh, David Rheinsberg, Rob Bradford + + - Dußlingen, 2023-03-20 + +## CHANGES WITH 4.1.0: + + * New Protocols: device-path-{from,to}-text, ip4, ip6, managed-network, + rng, service-binding, tcp4, tcp6, timestamp + + * `ImageEntryPoint` is now correctly annotated as `eficall`. + + * `Time` now derives `Default`. + + * Fix nullable function pointers to use `Option`. + + * Function prototypes now have an explicit type definition and can be + used independent of their protocol definition. + + * The new `rust-dep-of-std` feature option allows pulling in r-efi + into the rust standard library. It prepares the crate workspace to + be suitable for the standard library. It has no use outside of this. + + * Adopt the MIT license as 3rd licensing option to allow for + integration into the rust compiler and ecosystem. + + Contributions from: Ayush Singh, David Rheinsberg, Joe Richey + + - Tübingen, 2022-08-23 + +## CHANGES WITH 4.0.0: + + * Convert all enums to constants with type-aliases. This is an API + break, but it is needed for spec-compliance. With the old enums, one + couldn't encode all the possible values defined by the spec. + Especially, the vendor-reserved ranges were unable to be encoded in + a safe manner. Also see commit 401a91901e860 for a detailed + discussion. + API users likely need to convert their CamelCase enum usage to the + new UPPER_CASE constants. + + * Convert all incomplete types to empty arrays. This affects all + structures that use trailing unbound arrays. These are actually ABI + incompatible with UEFI, since rust represents raw-pointers to such + types as fat-pointers. Such arrays have now been converted to empty + arrays, which should still allow accessing the memory location and + retaining structure properties, but avoids fat-pointers. + This is an API break, so you might have to adjust your accessors of + those trailing structure members. + + * Implement `Clone` and `Copy` for most basic structures. Since these + are used as plain carriers, no higher clone/copy logic is needed. It + should be clear from the project-description, that only basic UEFI + compatibility is provided. + + * Add the console-control vendor protocol. This protocol allows + controlling console properties. It is not part of the UEFI + specification, but rather defined by the TianoCore project. + + * Add a new example showing how to use the GOP functions to query the + active graphics device. + + Contributions from: David Rheinsberg, GGRei, Hiroki Tokunaga, + Richard Wiedenhöft + + - Tübingen, 2021-06-23 + +## CHANGES WITH 3.2.0: + + * Add new protocols: DiskIo, DiskIo2, BlockIo, DriverBinding + + * Extend the Device-Path payload structure and add the HardDriveMedia + payload. + + * Add HII definitions: A new top-level module `hii` with all the basic + HII constants, as well as a handful of HII protocols (hii_database, + hii_font, hii_string) + + * Document new `-Zbuild-std` based cross-compilation, serving as + official rust alternative to cargo-xbuild. + + Contributions from: Alex James, Bret Barkelew, David Rheinsberg, + Michael Kubacki + + - Tübingen, 2020-10-23 + +## CHANGES WITH 3.1.0: + + * Add the basic networking types to `r_efi::base`. This includes MAC + and IP address types. + + * Add the EFI_SIMPLE_NETWORK_PROTOCOL definitions and all required + constants to make basic networking available. + + * Add a new uefi-cross example, which is copied from upstream rustc + sources, so we can test local modifications to it. + + Contributions from: Alex James, David Rheinsberg + + - Tübingen, 2020-09-10 + +## CHANGES WITH 3.0.0: + + * Fix a missing parameter in `BootServices::locate_device_path()`. The + prototype incorrectly had 2 arguments, while the official version + takes 3. The final `handle` argument was missing. + This is an API break in `r-efi`. It should have a limited impact, + since the function was mostly useless without a handle. + Thanks to Michael Kubacki for catching this! + + * Adjust the `device_path` parameter in a bunch of `BootServices` + calls. This used to take a `*mut c_void` parameter, since the device + path protocol was not implemented. + Since we have to bump the major version anyway, we use this to also + fix these argument-types to the correct device-path protocol type, + which has been implemented some time ago. + + Contributions from: David Rheinsberg, Michael Kubacki + + - Tübingen, 2020-04-24 + +## CHANGES WITH 2.2.0: + + * Provide `as_usize()` accessor for `efi::Status` types. This allows + accessing the raw underlying value of a status object. + + * The project moved to its new home at: github.com/r-efi/r-efi + + Contributions from: David Rheinsberg, Joe Richey + + - Tübingen, 2020-04-16 + +## CHANGES WITH 2.1.0: + + * Add the graphics-output-protocol. + + * Expose reserved fields in open structures, otherwise they cannot be + instantiated from outside the crate itself. + + Contributions from: David Herrmann, Richard Wiedenhöft, Rob Bradford + + - Tübingen, 2019-03-20 + +## CHANGES WITH 2.0.0: + + * Add a set of UEFI protocols, including simple-text-input, + file-protocol, simple-file-system, device-path, and more. + + * Fix signature of `BootServices::allocate_pages`. + + Contributions from: David Rheinsberg, Richard Wiedenhöft, Tom Gundersen + + - Tübingen, 2019-03-01 + +## CHANGES WITH 1.0.0: + + * Enhance the basic UEFI type integration with the rust ecosystem. Add + `Debug`, `Eq`, `Ord`, ... derivations, provide converters to/from the + core library, and document the internal workings. + + * Fix `Boolean` to use `newtype(u8)` to make it ABI compatible to UEFI. + This now accepts any byte value that UEFI accetps without any + conversion required. + + Contributions from: Boris-Chengbiao Zhou, David Rheinsberg, Tom + Gundersen + + - Tübingen, 2019-02-14 + +## CHANGES WITH 0.1.1: + + * Feature gate examples to make `cargo test` work on non-UEFI systems + like CI. + + Contributions from: David Herrmann + + - Tübingen, 2018-12-10 + +## CHANGES WITH 0.1.0: + + * Initial release of r-efi. + + Contributions from: David Herrmann + + - Tübingen, 2018-12-10 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/README.md clamav-1.4.6+dfsg/.cargo/vendor/r-efi/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +r-efi +===== + +UEFI Reference Specification Protocol Constants and Definitions + +The r-efi project provides the protocol constants and definitions of the +UEFI Reference Specification as native rust code. The scope of this project is +limited to those protocol definitions. The protocols are not actually +implemented. As such, this project serves as base for any UEFI application that +needs to interact with UEFI, or implement (parts of) the UEFI specification. + +### Project + + * **Website**: + * **Bug Tracker**: + +### Requirements + +The requirements for this project are: + + * `rustc >= 1.68.0` + +### Build + +To build this project, run: + +```sh +cargo build +``` + +Available configuration options are: + + * **native**: This feature-selector enables compilation of modules and + examples that require native UEFI targets. Those will not + compile on foreign targets and thus are guarded by this flag. + +##### Build via: official toolchains + +Starting with rust-version 1.68, rustup distributes pre-compiled toolchains for +many UEFI targets. You can enumerate and install them via `rustup`. This +example shows how to enumerate all available targets for your stable toolchain +and then install the UEFI target for the `x86_64` architecture: + +```sh +rustup target list --toolchain=stable +rustup target add --toolchain=stable x86_64-unknown-uefi +``` + +This project can then be compiled directly for the selected target: + +```sh +cargo +stable build \ + --examples \ + --features native \ + --lib \ + --target x86_64-unknown-uefi +``` + +##### Build via: cargo/rustc nightly with -Zbuild-std + +If no pre-compiled toolchains are available for your selected target, you can +compile the project and the required parts of the standard library via the +experimental `-Zbuild-std` feature of rustc. This requires a nightly compiler: + +```sh +cargo +nightly build \ + -Zbuild-std=core,compiler_builtins,alloc \ + -Zbuild-std-features=compiler-builtins-mem \ + --examples \ + --features native \ + --lib \ + --target x86_64-unknown-uefi +``` + +##### Build via: foreign target + +The project can be built for non-UEFI targets via the standard rust toolchains. +This allows non-UEFI targets to interact with UEFI systems or otherwise host +UEFI operations. Furthermore, this allows running the foreign test-suite of +this project as long as the target supports the full standard library: + +```sh +cargo +stable build --all-targets +cargo +stable test --all-targets +``` + +Note that the `native` feature must not be enabled for foreign targets as it +will not compile on non-UEFI systems. + +### Repository: + + - **web**: + - **https**: `https://github.com/r-efi/r-efi.git` + - **ssh**: `git@github.com:r-efi/r-efi.git` + +### License: + + - **MIT** OR **Apache-2.0** OR **LGPL-2.1-or-later** + - See AUTHORS file for details. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/freestanding.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/freestanding.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/freestanding.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/freestanding.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +// Example: Freestanding +// +// This example is a plain UEFI application without any external requirements +// but `core`. It immediately returns control to the caller upon execution, +// yielding the exit code 0. +// +// The `main` function serves as entry-point. Depending on your +// target-configuration, it must be exported with a pre-configured name so the +// linker will correctly mark it as entry-point. The target configurations +// shipped with upstream rust-lang use `efi_main` as symbol name. +// +// Additionally, a panic handler is provided. This is executed by rust on +// panic. For simplicity, we simply end up in an infinite loop. For real +// applications, this method should probably call into +// `SystemTable->boot_services->exit()` to exit the UEFI application. Note, +// however, that UEFI applications are likely to run in the same address space +// as the entire firmware. Hence, halting the machine might be a viable +// alternative. All that is out-of-scope for this example, though. +// +// Note that as of rust-1.31.0, all features used here are stabilized. No +// unstable features are required, nor do we rely on nightly compilers. + +#![no_main] +#![no_std] + +#[panic_handler] +fn panic_handler(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[export_name = "efi_main"] +pub extern "C" fn main(_h: *mut core::ffi::c_void, _st: *mut core::ffi::c_void) -> usize { + 0 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/gop-query.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/gop-query.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/gop-query.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/gop-query.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,188 @@ +// Example: Graphics Query +// +// This is a slightly more complex UEFI application than `hello-world`. It +// locates the graphics-output-protocol, queries its current mode and prints +// the current resolution to the UEFI console. +// +// This example should make everyone aware that UEFI programing in Rust really +// asks for helper layers. While the C/FFI/Spec API can be used directly, it +// is quite cumbersome. Especially the error handling is overly difficult. +// +// Nevertheless, this example shows how to find UEFI protocol and invoke +// their member functions. +// +// Like all the other r-efi examples, it is a standalone example. That is, no +// UTF-16 helpers are pulled in, nor any allocators or panic frameworks. For +// real world scenarios, you really should choose such helpers. + +#![no_main] +#![no_std] + +use r_efi::efi; + +#[panic_handler] +fn panic_handler(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +fn fail(_r: efi::Status) -> ! { + panic!(); +} + +// A simple `itoa()`-ish function that takes a u32 and turns it into a UTF-16 +// string. It always prints exactly 10 characters, so leading zeroes are used +// for small numbers. +fn utoa(mut u: u32, a: &mut [u16]) { + for i in 0..10 { + a[9 - i] = 0x0030u16 + ((u % 10) as u16); + u = u / 10; + } +} + +// A simple helper that takes two integers and prints them to the UEFI console +// with a short prefix. It uses a UTF-16 buffer and fills in the numbers before +// printing the entire buffer. +fn print_xy(st: *mut efi::SystemTable, x: u32, y: u32) { + let mut s = [ + 0x0058u16, 0x0059u16, 0x003au16, // "XY:" + 0x0020u16, // " " + 0x0020u16, 0x0020u16, 0x0020u16, 0x0020u16, // " " + 0x0020u16, 0x0020u16, 0x0020u16, 0x0020u16, // " " + 0x0020u16, 0x0020u16, // " " + 0x0078u16, // "x" + 0x0020u16, 0x0020u16, 0x0020u16, 0x0020u16, // " " + 0x0020u16, 0x0020u16, 0x0020u16, 0x0020u16, // " " + 0x0020u16, 0x0020u16, // " " + 0x000au16, // "\n" + 0x0000u16, // NUL + ]; + + utoa(x, &mut s[4..14]); + utoa(y, &mut s[15..25]); + + unsafe { + let r = ((*(*st).con_out).output_string)((*st).con_out, s.as_ptr() as *mut efi::Char16); + if r.is_error() { + fail(r); + } + } +} + +// This function locates singleton UEFI protocols. Those protocols do not +// require to register listener handles, but are globally available to all +// UEFI applications. It takes a GUID of the protocol to locate and returns +// the protocol pointer on success. +fn locate_singleton( + st: *mut efi::SystemTable, + guid: *const efi::Guid, +) -> Result<*mut core::ffi::c_void, efi::Status> { + let mut interface: *mut core::ffi::c_void = core::ptr::null_mut(); + let mut handles: *mut efi::Handle = core::ptr::null_mut(); + let mut n_handles: usize = 0; + let mut r: efi::Status; + + // Use `locate_handle_buffer()` to find all handles that support the + // specified protocol. + unsafe { + if (*st).hdr.revision < efi::SYSTEM_TABLE_REVISION_1_10 { + // We use `LocateHandleBuffer`, which was introduced in 1.10. + return Err(efi::Status::UNSUPPORTED); + } + + let r = ((*(*st).boot_services).locate_handle_buffer)( + efi::BY_PROTOCOL, + guid as *mut _, + core::ptr::null_mut(), + &mut n_handles, + &mut handles, + ); + match r { + efi::Status::SUCCESS => {} + efi::Status::NOT_FOUND => return Err(r), + efi::Status::OUT_OF_RESOURCES => return Err(r), + _ => panic!(), + }; + } + + // Now that we have all handles with the specified protocol, query it for + // the protocol interface. We loop here, even though every item should + // succeed. Lets be on the safe side. + // Secondly, we use `handle_protocol()` here, but really should be using + // `open_protocol()`. But for singleton protocols, this does not matter, + // so lets use the simple path for now. + unsafe { + r = efi::Status::NOT_FOUND; + for i in 0..n_handles { + r = ((*(*st).boot_services).handle_protocol)( + *handles.offset(core::convert::TryFrom::::try_from(i).unwrap()), + guid as *mut _, + &mut interface, + ); + match r { + efi::Status::SUCCESS => break, + efi::Status::UNSUPPORTED => continue, + _ => panic!(), + }; + } + } + + // Free the allocated buffer memory of `handles`. This was allocated on the + // pool by `locate_handle_buffer()`. + unsafe { + let r = ((*(*st).boot_services).free_pool)(handles as *mut core::ffi::c_void); + assert!(!r.is_error()); + } + + // In case we found nothing, return `NOT_FOUND`, otherwise return the + // interface identifier. + match r { + efi::Status::SUCCESS => Ok(interface), + _ => Err(efi::Status::NOT_FOUND), + } +} + +// A simple helper that queries the current mode of the GraphicsOutputProtocol +// and returns the x and y dimensions on success. +fn query_gop( + gop: *mut efi::protocols::graphics_output::Protocol, +) -> Result<(u32, u32), efi::Status> { + let mut info: *mut efi::protocols::graphics_output::ModeInformation = core::ptr::null_mut(); + let mut z_info: usize = 0; + + unsafe { + // We could just look at `gop->mode->info`, but lets query the mode + // instead to show how to query other modes than the active one. + let r = ((*gop).query_mode)(gop, (*(*gop).mode).mode, &mut z_info, &mut info); + match r { + efi::Status::SUCCESS => {} + efi::Status::DEVICE_ERROR => return Err(r), + _ => panic!(), + }; + if z_info < core::mem::size_of_val(&*info) { + return Err(efi::Status::UNSUPPORTED); + } + + Ok(((*info).horizontal_resolution, (*info).vertical_resolution)) + } +} + +// This is the UEFI application entrypoint. We use it to locate the GOP +// pointer, query the current mode, and then print it to the system console. +#[export_name = "efi_main"] +pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status { + let r = locate_singleton(st, &efi::protocols::graphics_output::PROTOCOL_GUID); + let gop = match r { + Ok(v) => v, + Err(r) => fail(r), + }; + + let r = query_gop(gop as _); + let v = match r { + Ok(v) => v, + Err(r) => fail(r), + }; + + print_xy(st, v.0, v.1); + + efi::Status::SUCCESS +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/hello-world.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/hello-world.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/examples/hello-world.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/examples/hello-world.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +// Example: Hello World! +// +// This is an example UEFI application that prints "Hello World!", then waits +// for key input before it exits. It serves as base example how to write UEFI +// applications without any helper modules other than the UEFI protocol +// definitions. +// +// This example builds upon the `freestanding.rs` example, using the same setup +// and rust integration. See there for details on the panic-handler and entry +// point configuration. +// +// Note that UEFI uses UTF-16 strings. Since rust literals are UTF-8, we have +// to use an open-coded, zero-terminated, UTF-16 array as argument to +// `output_string()`. Similarly to the panic handler, real applications should +// rather use UTF-16 modules. + +#![no_main] +#![no_std] + +use r_efi::efi; + +#[panic_handler] +fn panic_handler(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[export_name = "efi_main"] +pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status { + let s = [ + 0x0048u16, 0x0065u16, 0x006cu16, 0x006cu16, 0x006fu16, // "Hello" + 0x0020u16, // " " + 0x0057u16, 0x006fu16, 0x0072u16, 0x006cu16, 0x0064u16, // "World" + 0x0021u16, // "!" + 0x000au16, // "\n" + 0x0000u16, // NUL + ]; + + // Print "Hello World!". + let r = + unsafe { ((*(*st).con_out).output_string)((*st).con_out, s.as_ptr() as *mut efi::Char16) }; + if r.is_error() { + return r; + } + + // Wait for key input, by waiting on the `wait_for_key` event hook. + let r = unsafe { + let mut x: usize = 0; + ((*(*st).boot_services).wait_for_event)(1, &mut (*(*st).con_in).wait_for_key, &mut x) + }; + if r.is_error() { + return r; + } + + efi::Status::SUCCESS +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/base.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/base.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/base.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/base.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,993 @@ +//! UEFI Base Environment +//! +//! This module defines the base environment for UEFI development. It provides types and macros as +//! declared in the UEFI specification, as well as de-facto standard additions provided by the +//! reference implementation by Intel. +//! +//! # Target Configuration +//! +//! Wherever possible, native rust types are used to represent their UEFI counter-parts. However, +//! this means the ABI depends on the implementation of said rust types. Hence, native rust types +//! are only used where rust supports a stable ABI of said types, and their ABI matches the ABI +//! defined by the UEFI specification. +//! +//! Nevertheless, even if the ABI of a specific type is marked stable, this does not imply that it +//! is the same across architectures. For instance, rust's `u64` type has the same binary +//! representation as the `UINT64` type in UEFI. But this does not imply that it has the same +//! binary representation on `x86_64` and on `ppc64be`. As a result of this, the compilation of +//! this module is tied to the target-configuration you passed to the rust compiler. Wherever +//! possible and reasonable, any architecture differences are abstracted, though. This means that +//! in most cases you can use this module even though your target-configuration might not match +//! the native UEFI target-configuration. +//! +//! The recommend way to compile your code, is to use the native target-configuration for UEFI. +//! These configurations are not necessarily included in the upstream rust compiler. Hence, you +//! might have to craft one yourself. For all systems that we can test on, we make sure to push +//! the target configuration into upstream rust-lang. +//! +//! However, there are situations where you want to access UEFI data from a non-native host. For +//! instance, a UEFI boot loader might store data in boot variables, formatted according to types +//! declared in the UEFI specification. An OS booted thereafter might want to access these +//! variables, but it might be compiled with a different target-configuration than the UEFI +//! environment that it was booted from. A similar situation occurs when you call UEFI runtime +//! functions from your OS. In all those cases, you should very likely be able to use this module +//! to interact with UEFI as well. This is, because most bits of the target-configuration of UEFI +//! and your OS very likely match. In fact, to figure out whether this is safe, you need to make +//! sure that the rust ABI would match in both target-configurations. If it is, all other details +//! are handled within this module just fine. +//! +//! In case of doubt, contact us! +//! +//! # Core Primitives +//! +//! Several of the UEFI primitives are represented by native Rust. These have no type aliases or +//! other definitions here, but you are recommended to use native rust directly. These include: +//! +//! * `NULL`, `void *`: Void pointers have a native rust implementation in +//! [`c_void`](core::ffi::c_void). `NULL` is represented through +//! [`null`](core::ptr::null) and [`is_null()`](core::ptr) for +//! all pointer types. +//! * `uint8_t`..`uint64_t`, +//! `int8_t`..`int64_t`: Fixed-size integers are represented by their native rust equivalents +//! (`u8`..`u64`, `i8`..`i64`). +//! +//! * `UINTN`, `INTN`: Native-sized (or instruction-width sized) integers are represented by +//! their native rust equivalents (`usize`, `isize`). +//! +//! # UEFI Details +//! +//! The UEFI Specification describes its target environments in detail. Each supported +//! architecture has a separate section with details on calling conventions, CPU setup, and more. +//! You are highly recommended to conduct the UEFI Specification for details on the programming +//! environment. Following a summary of key parts relevant to rust developers: +//! +//! * Similar to rust, integers are either fixed-size, or native size. This maps nicely to the +//! native rust types. The common `long`, `int`, `short` types known from ISO-C are not used. +//! Whenever you refer to memory (either pointing to it, or remember the size of a memory +//! block), the native size integers should be your tool of choice. +//! +//! * Even though the CPU might run in any endianness, all stored data is little-endian. That +//! means, if you encounter integers split into byte-arrays (e.g., +//! `CEfiDevicePathProtocol.length`), you must assume it is little-endian encoded. But if you +//! encounter native integers, you must assume they are encoded in native endianness. +//! For now the UEFI specification only defines little-endian architectures, hence this did not +//! pop up as actual issue. Future extensions might change this, though. +//! +//! * The Microsoft calling-convention is used. That is, all external calls to UEFI functions +//! follow a calling convention that is very similar to that used on Microsoft Windows. All +//! such ABI functions must be marked with the right calling-convention. The UEFI Specification +//! defines some additional common rules for all its APIs, though. You will most likely not see +//! any of these mentioned in the individual API documentions. So here is a short reminder: +//! +//! * Pointers must reference physical-memory locations (no I/O mappings, no +//! virtual addresses, etc.). Once ExitBootServices() was called, and the +//! virtual address mapping was set, you must provide virtual-memory +//! locations instead. +//! * Pointers must be correctly aligned. +//! * NULL is disallowed, unless explicitly mentioned otherwise. +//! * Data referenced by pointers is undefined on error-return from a +//! function. +//! * You must not pass data larger than native-size (sizeof(CEfiUSize)) on +//! the stack. You must pass them by reference. +//! +//! * Stack size is at least 128KiB and 16-byte aligned. All stack space might be marked +//! non-executable! Once ExitBootServices() was called, you must guarantee at least 4KiB of +//! stack space, 16-byte aligned for all runtime services you call. +//! Details might differ depending on architectures. But the numbers here should serve as +//! ball-park figures. + +// Target Architecture +// +// The UEFI Specification explicitly lists all supported target architectures. While external +// implementors are free to port UEFI to other targets, we need information on the target +// architecture to successfully compile for it. This includes calling-conventions, register +// layouts, endianness, and more. Most of these details are hidden in the rust-target-declaration. +// However, some details are still left to the actual rust code. +// +// This initial check just makes sure the compilation is halted with a suitable error message if +// the target architecture is not supported. +// +// We try to minimize conditional compilations as much as possible. A simple search for +// `target_arch` should reveal all uses throughout the code-base. If you add your target to this +// error-check, you must adjust all other uses as well. +// +// Similarly, UEFI only defines configurations for little-endian architectures so far. Several +// bits of the specification are thus unclear how they would be applied on big-endian systems. We +// therefore mark it as unsupported. If you override this, you are on your own. +#[cfg(not(any( + target_arch = "arm", + target_arch = "aarch64", + target_arch = "riscv64", + target_arch = "x86", + target_arch = "x86_64" +)))] +compile_error!("The target architecture is not supported."); +#[cfg(not(target_endian = "little"))] +compile_error!("The target endianness is not supported."); + +// eficall_abi!() +// +// This macro is the architecture-dependent implementation of eficall!(). See the documentation of +// the eficall!() macro for a description. Nowadays, this simply maps to `extern "efiapi"`, since +// this has been stabilized with rust-1.68. + +#[macro_export] +#[doc(hidden)] +macro_rules! eficall_abi { + (($($prefix:tt)*),($($suffix:tt)*)) => { $($prefix)* extern "efiapi" $($suffix)* }; +} + +/// Annotate function with UEFI calling convention +/// +/// Since rust-1.68 you can use `extern "efiapi"` as calling-convention to achieve the same +/// behavior as this macro. This macro is kept for backwards-compatibility only, but will nowadays +/// map to `extern "efiapi"`. +/// +/// This macro takes a function-declaration as argument and produces the same function-declaration +/// but annotated with the correct calling convention. Since the default `extern "C"` annotation +/// depends on your compiler defaults, we cannot use it. Instead, this macro selects the default +/// for your target platform. +/// +/// Ideally, the macro would expand to `extern ""` so you would be able to write: +/// +/// ```ignore +/// // THIS DOES NOT WORK! +/// pub fn eficall!{} foobar() { +/// // ... +/// } +/// ``` +/// +/// However, macros are evaluated too late for this to work. Instead, the entire construct must be +/// wrapped in a macro, which then expands to the same construct but with `extern ""` +/// inserted at the correct place: +/// +/// ``` +/// use r_efi::{eficall, eficall_abi}; +/// +/// eficall!{pub fn foobar() { +/// // ... +/// }} +/// +/// type FooBar = eficall!{fn(u8) -> (u8)}; +/// ``` +/// +/// The `eficall!{}` macro takes either a function-type or function-definition as argument. It +/// inserts `extern ""` after the function qualifiers, but before the `fn` keyword. +/// +/// # Internals +/// +/// The `eficall!{}` macro tries to parse the function header so it can insert `extern ""` at +/// the right place. If, for whatever reason, this does not work with a particular syntax, you can +/// use the internal `eficall_abi!{}` macro. This macro takes two token-streams as input and +/// evaluates to the concatenation of both token-streams, but separated by the selected ABI. +/// +/// For instance, the following 3 type definitions are equivalent, assuming the selected ABI +/// is "C": +/// +/// ``` +/// use r_efi::{eficall, eficall_abi}; +/// +/// type FooBar1 = unsafe extern "C" fn(u8) -> (u8); +/// type FooBar2 = eficall!{unsafe fn(u8) -> (u8)}; +/// type FooBar3 = eficall_abi!{(unsafe), (fn(u8) -> (u8))}; +/// ``` +/// +/// # Calling Conventions +/// +/// The UEFI specification defines the calling convention for each platform individually. It +/// usually refers to other standards for details, but adds some restrictions on top. As of this +/// writing, it mentions: +/// +/// * aarch32 / arm: The `aapcs` calling-convention is used. It is native to aarch32 and described +/// in a document called +/// "Procedure Call Standard for the ARM Architecture". It is openly distributed +/// by ARM and widely known under the keyword `aapcs`. +/// * aarch64: The `aapcs64` calling-convention is used. It is native to aarch64 and described in +/// a document called +/// "Procedure Call Standard for the ARM 64-bit Architecture (AArch64)". It is openly +/// distributed by ARM and widely known under the keyword `aapcs64`. +/// * ia-64: The "P64 C Calling Convention" as described in the +/// "Itanium Software Conventions and Runtime Architecture Guide". It is also +/// standardized in the "Intel Itanium SAL Specification". +/// * RISC-V: The "Standard RISC-V C Calling Convention" is used. The UEFI specification +/// describes it in detail, but also refers to the official RISC-V resources for +/// detailed information. +/// * x86 / ia-32: The `cdecl` C calling convention is used. Originated in the C Language and +/// originally tightly coupled to C specifics. Unclear whether a formal +/// specification exists (does anyone know?). Most compilers support it under the +/// `cdecl` keyword, and in nearly all situations it is the default on x86. +/// * x86_64 / amd64 / x64: The `win64` calling-convention is used. It is similar to the `sysv64` +/// convention that is used on most non-windows x86_64 systems, but not +/// exactly the same. Microsoft provides open documentation on it. See +/// MSDN "x64 Software Conventions -> Calling Conventions". +/// The UEFI Specification does not directly refer to `win64`, but +/// contains a full specification of the calling convention itself. +/// +/// Note that in most cases the UEFI Specification adds several more restrictions on top of the +/// common calling-conventions. These restrictions usually do not affect how the compiler will lay +/// out the function calls. Instead, it usually only restricts the set of APIs that are allowed in +/// UEFI. Therefore, most compilers already support the calling conventions used on UEFI. +/// +/// # Variadics +/// +/// For some reason, the rust compiler allows variadics only in combination with the `"C"` calling +/// convention, even if the selected calling-convention matches what `"C"` would select on the +/// target platform. Hence, you will very likely be unable to use variadics with this macro. +/// Luckily, all of the UEFI functions that use variadics are wrappers around more low-level +/// accessors, so they are not necessarily required. +#[macro_export] +macro_rules! eficall { + // Muncher + // + // The `@munch()` rules are internal and should not be invoked directly. We walk through the + // input, moving one token after the other from the suffix into the prefix until we find the + // position where to insert `extern ""`. This muncher never drops any tokens, hence we + // can safely match invalid statements just fine, as the compiler will later print proper + // diagnostics when parsing the macro output. + // Once done, we invoke the `eficall_abi!{}` macro, which simply inserts the correct ABI. + (@munch(($($prefix:tt)*),(pub $($suffix:tt)*))) => { eficall!{@munch(($($prefix)* pub),($($suffix)*))} }; + (@munch(($($prefix:tt)*),(unsafe $($suffix:tt)*))) => { eficall!{@munch(($($prefix)* unsafe),($($suffix)*))} }; + (@munch(($($prefix:tt)*),($($suffix:tt)*))) => { eficall_abi!{($($prefix)*),($($suffix)*)} }; + + // Entry Point + // + // This captures the entire argument and invokes its own TT-muncher, but splits the input into + // prefix and suffix, so the TT-muncher can walk through it. Note that initially everything is + // in the suffix and the prefix is empty. + ($($arg:tt)*) => { eficall!{@munch((),($($arg)*))} }; +} + +/// Boolean Type +/// +/// This boolean type works very similar to the rust primitive type of [`bool`]. However, the rust +/// primitive type has no stable ABI, hence we provide this type to represent booleans on the FFI +/// interface. +/// +/// UEFI defines booleans to be 1-byte integers, which can only have the values of `0` or `1`. +/// However, in practice anything non-zero is considered `true` by nearly all UEFI systems. Hence, +/// this type implements a boolean over `u8` and maps `0` to `false`, everything else to `true`. +/// +/// The binary representation of this type is ABI. That is, you are allowed to transmute from and +/// to `u8`. Furthermore, this type never modifies its binary representation. If it was +/// initialized as, or transmuted from, a specific integer value, this value will be retained. +/// However, on the rust side you will never see the integer value. It instead behaves truly as a +/// boolean. If you need access to the integer value, you have to transmute it back to `u8`. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +// Manual impls for: Default, Eq, Hash, Ord, PartialEq, PartialOrd +pub struct Boolean(u8); + +/// Single-byte Character Type +/// +/// The `Char8` type represents single-byte characters. UEFI defines them to be ASCII compatible, +/// using the ISO-Latin-1 character set. +pub type Char8 = u8; + +/// Dual-byte Character Type +/// +/// The `Char16` type represents dual-byte characters. UEFI defines them to be UCS-2 encoded. +pub type Char16 = u16; + +/// Status Codes +/// +/// UEFI uses the `Status` type to represent all kinds of status codes. This includes return codes +/// from functions, but also complex state of different devices and drivers. It is a simple +/// `usize`, but wrapped in a rust-type to allow us to implement helpers on this type. Depending +/// on the context, different state is stored in it. Note that it is always binary compatible to a +/// usize! +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Status(usize); + +/// Object Handles +/// +/// Handles represent access to an opaque object. Handles are untyped by default, but get a +/// meaning when you combine them with an interface. Internally, they are simple void pointers. It +/// is the UEFI driver model that applies meaning to them. +pub type Handle = *mut core::ffi::c_void; + +/// Event Objects +/// +/// Event objects represent hooks into the main-loop of a UEFI environment. They allow to register +/// callbacks, to be invoked when a specific event happens. In most cases you use events to +/// register timer-based callbacks, as well as chaining events together. Internally, they are +/// simple void pointers. It is the UEFI task management that applies meaning to them. +pub type Event = *mut core::ffi::c_void; + +/// Logical Block Addresses +/// +/// The LBA type is used to denote logical block addresses of block devices. It is a simple 64-bit +/// integer, that is used to denote addresses when working with block devices. +pub type Lba = u64; + +/// Thread Priority Levels +/// +/// The process model of UEFI systems is highly simplified. Priority levels are used to order +/// execution of pending tasks. The TPL type denotes a priority level of a specific task. The +/// higher the number, the higher the priority. It is a simple integer type, but its range is +/// usually highly restricted. The UEFI task management provides constants and accessors for TPLs. +pub type Tpl = usize; + +/// Physical Memory Address +/// +/// A simple 64bit integer containing a physical memory address. +pub type PhysicalAddress = u64; + +/// Virtual Memory Address +/// +/// A simple 64bit integer containing a virtual memory address. +pub type VirtualAddress = u64; + +/// Application Entry Point +/// +/// This type defines the entry-point of UEFI applications. It is ABI and cannot be changed. +/// Whenever you load UEFI images, the entry-point is called with this signature. +/// +/// In most cases the UEFI image (or application) is unloaded when control returns from the entry +/// point. In case of UEFI drivers, they can request to stay loaded until an explicit unload. +/// +/// The system table is provided as mutable pointer. This is, because there is no guarantee that +/// timer interrupts do not modify the table. Furthermore, exiting boot services causes several +/// modifications on that table. And lastly, the system table lives longer than the function +/// invocation, if invoked as an UEFI driver. +/// In most cases it is perfectly fine to cast the pointer to a real rust reference. However, this +/// should be an explicit decision by the caller. +pub type ImageEntryPoint = eficall! {fn(Handle, *mut crate::system::SystemTable) -> Status}; + +/// Globally Unique Identifiers +/// +/// The `Guid` type represents globally unique identifiers as defined by RFC-4122 (i.e., only the +/// `10x` variant is used), with the caveat that LE is used instead of BE. +/// +/// Note that only the binary representation of Guids is stable. You are highly recommended to +/// interpret Guids as 128bit integers. +/// +/// The UEFI specification requires the type to be 64-bit aligned, yet EDK2 uses a mere 32-bit +/// alignment. Hence, for compatibility, a 32-bit alignment is used. +/// +/// UEFI uses the Microsoft-style Guid format. Hence, a lot of documentation and code refers to +/// these Guids. If you thusly cannot treat Guids as 128-bit integers, this Guid type allows you +/// to access the individual fields of the Microsoft-style Guid. A reminder of the Guid encoding: +/// +/// ```text +/// 0 1 2 3 +/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | time_low | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | time_mid | time_hi_and_version | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// |clk_seq_hi_res | clk_seq_low | node (0-1) | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | node (2-5) | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// ``` +/// +/// The individual fields are encoded as little-endian. Accessors are provided for the Guid +/// structure allowing access to these fields in native endian byte order. +#[repr(C, align(4))] +#[derive(Clone, Copy, Debug)] +#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Guid { + time_low: [u8; 4], + time_mid: [u8; 2], + time_hi_and_version: [u8; 2], + clk_seq_hi_res: u8, + clk_seq_low: u8, + node: [u8; 6], +} + +/// Network MAC Address +/// +/// This type encapsulates a single networking media access control address +/// (MAC). It is a simple 32 bytes buffer with no special alignment. Note that +/// no comparison function are defined by default, since trailing bytes of the +/// address might be random. +/// +/// The interpretation of the content differs depending on the protocol it is +/// used with. See each documentation for details. In most cases this contains +/// an Ethernet address. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct MacAddress { + pub addr: [u8; 32], +} + +/// IPv4 Address +/// +/// Binary representation of an IPv4 address. It is encoded in network byte +/// order (i.e., big endian). Note that no special alignment restrictions are +/// defined by the standard specification. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Ipv4Address { + pub addr: [u8; 4], +} + +/// IPv6 Address +/// +/// Binary representation of an IPv6 address, encoded in network byte order +/// (i.e., big endian). Similar to the IPv4 address, no special alignment +/// restrictions are defined by the standard specification. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Ipv6Address { + pub addr: [u8; 16], +} + +/// IP Address +/// +/// A union type over the different IP addresses available. Alignment is always +/// fixed to 4-bytes. Note that trailing bytes might be random, so no +/// comparison functions are derived. +#[repr(C, align(4))] +#[derive(Clone, Copy)] +pub union IpAddress { + pub addr: [u32; 4], + pub v4: Ipv4Address, + pub v6: Ipv6Address, +} + +impl Boolean { + /// Literal False + /// + /// This constant represents the `false` value of the `Boolean` type. + pub const FALSE: Boolean = Boolean(0u8); + + /// Literal True + /// + /// This constant represents the `true` value of the `Boolean` type. + pub const TRUE: Boolean = Boolean(1u8); +} + +impl From for Boolean { + fn from(v: u8) -> Self { + Boolean(v) + } +} + +impl From for Boolean { + fn from(v: bool) -> Self { + match v { + false => Boolean::FALSE, + true => Boolean::TRUE, + } + } +} + +impl Default for Boolean { + fn default() -> Self { + Self::FALSE + } +} + +impl From for u8 { + fn from(v: Boolean) -> Self { + match v.0 { + 0 => 0, + _ => 1, + } + } +} + +impl From for bool { + fn from(v: Boolean) -> Self { + match v.0 { + 0 => false, + _ => true, + } + } +} + +impl Eq for Boolean {} + +impl core::hash::Hash for Boolean { + fn hash(&self, state: &mut H) { + bool::from(*self).hash(state) + } +} + +impl Ord for Boolean { + fn cmp(&self, other: &Boolean) -> core::cmp::Ordering { + bool::from(*self).cmp(&(*other).into()) + } +} + +impl PartialEq for Boolean { + fn eq(&self, other: &Boolean) -> bool { + bool::from(*self).eq(&(*other).into()) + } +} + +impl PartialEq for Boolean { + fn eq(&self, other: &bool) -> bool { + bool::from(*self).eq(other) + } +} + +impl PartialOrd for Boolean { + fn partial_cmp(&self, other: &Boolean) -> Option { + bool::from(*self).partial_cmp(&(*other).into()) + } +} + +impl PartialOrd for Boolean { + fn partial_cmp(&self, other: &bool) -> Option { + bool::from(*self).partial_cmp(other) + } +} + +impl Status { + const WIDTH: usize = 8usize * core::mem::size_of::(); + const MASK: usize = 0xc0 << (Status::WIDTH - 8); + const ERROR_MASK: usize = 0x80 << (Status::WIDTH - 8); + const WARNING_MASK: usize = 0x00 << (Status::WIDTH - 8); + + /// Success Code + /// + /// This code represents a successfull function invocation. Its value is guaranteed to be 0. + /// However, note that warnings are considered success as well, so this is not the only code + /// that can be returned by UEFI functions on success. However, in nearly all situations + /// warnings are not allowed, so the effective result will be SUCCESS. + pub const SUCCESS: Status = Status::from_usize(0); + + // List of predefined error codes + pub const LOAD_ERROR: Status = Status::from_usize(1 | Status::ERROR_MASK); + pub const INVALID_PARAMETER: Status = Status::from_usize(2 | Status::ERROR_MASK); + pub const UNSUPPORTED: Status = Status::from_usize(3 | Status::ERROR_MASK); + pub const BAD_BUFFER_SIZE: Status = Status::from_usize(4 | Status::ERROR_MASK); + pub const BUFFER_TOO_SMALL: Status = Status::from_usize(5 | Status::ERROR_MASK); + pub const NOT_READY: Status = Status::from_usize(6 | Status::ERROR_MASK); + pub const DEVICE_ERROR: Status = Status::from_usize(7 | Status::ERROR_MASK); + pub const WRITE_PROTECTED: Status = Status::from_usize(8 | Status::ERROR_MASK); + pub const OUT_OF_RESOURCES: Status = Status::from_usize(9 | Status::ERROR_MASK); + pub const VOLUME_CORRUPTED: Status = Status::from_usize(10 | Status::ERROR_MASK); + pub const VOLUME_FULL: Status = Status::from_usize(11 | Status::ERROR_MASK); + pub const NO_MEDIA: Status = Status::from_usize(12 | Status::ERROR_MASK); + pub const MEDIA_CHANGED: Status = Status::from_usize(13 | Status::ERROR_MASK); + pub const NOT_FOUND: Status = Status::from_usize(14 | Status::ERROR_MASK); + pub const ACCESS_DENIED: Status = Status::from_usize(15 | Status::ERROR_MASK); + pub const NO_RESPONSE: Status = Status::from_usize(16 | Status::ERROR_MASK); + pub const NO_MAPPING: Status = Status::from_usize(17 | Status::ERROR_MASK); + pub const TIMEOUT: Status = Status::from_usize(18 | Status::ERROR_MASK); + pub const NOT_STARTED: Status = Status::from_usize(19 | Status::ERROR_MASK); + pub const ALREADY_STARTED: Status = Status::from_usize(20 | Status::ERROR_MASK); + pub const ABORTED: Status = Status::from_usize(21 | Status::ERROR_MASK); + pub const ICMP_ERROR: Status = Status::from_usize(22 | Status::ERROR_MASK); + pub const TFTP_ERROR: Status = Status::from_usize(23 | Status::ERROR_MASK); + pub const PROTOCOL_ERROR: Status = Status::from_usize(24 | Status::ERROR_MASK); + pub const INCOMPATIBLE_VERSION: Status = Status::from_usize(25 | Status::ERROR_MASK); + pub const SECURITY_VIOLATION: Status = Status::from_usize(26 | Status::ERROR_MASK); + pub const CRC_ERROR: Status = Status::from_usize(27 | Status::ERROR_MASK); + pub const END_OF_MEDIA: Status = Status::from_usize(28 | Status::ERROR_MASK); + pub const END_OF_FILE: Status = Status::from_usize(31 | Status::ERROR_MASK); + pub const INVALID_LANGUAGE: Status = Status::from_usize(32 | Status::ERROR_MASK); + pub const COMPROMISED_DATA: Status = Status::from_usize(33 | Status::ERROR_MASK); + pub const IP_ADDRESS_CONFLICT: Status = Status::from_usize(34 | Status::ERROR_MASK); + pub const HTTP_ERROR: Status = Status::from_usize(35 | Status::ERROR_MASK); + + // List of error codes from protocols + // UDP4 + pub const NETWORK_UNREACHABLE: Status = Status::from_usize(100 | Status::ERROR_MASK); + pub const HOST_UNREACHABLE: Status = Status::from_usize(101 | Status::ERROR_MASK); + pub const PROTOCOL_UNREACHABLE: Status = Status::from_usize(102 | Status::ERROR_MASK); + pub const PORT_UNREACHABLE: Status = Status::from_usize(103 | Status::ERROR_MASK); + // TCP4 + pub const CONNECTION_FIN: Status = Status::from_usize(104 | Status::ERROR_MASK); + pub const CONNECTION_RESET: Status = Status::from_usize(105 | Status::ERROR_MASK); + pub const CONNECTION_REFUSED: Status = Status::from_usize(106 | Status::ERROR_MASK); + + // List of predefined warning codes + pub const WARN_UNKNOWN_GLYPH: Status = Status::from_usize(1 | Status::WARNING_MASK); + pub const WARN_DELETE_FAILURE: Status = Status::from_usize(2 | Status::WARNING_MASK); + pub const WARN_WRITE_FAILURE: Status = Status::from_usize(3 | Status::WARNING_MASK); + pub const WARN_BUFFER_TOO_SMALL: Status = Status::from_usize(4 | Status::WARNING_MASK); + pub const WARN_STALE_DATA: Status = Status::from_usize(5 | Status::WARNING_MASK); + pub const WARN_FILE_SYSTEM: Status = Status::from_usize(6 | Status::WARNING_MASK); + pub const WARN_RESET_REQUIRED: Status = Status::from_usize(7 | Status::WARNING_MASK); + + /// Create Status Code from Integer + /// + /// This takes the literal value of a status code and turns it into a `Status` object. Note + /// that we want it as `const fn` so we cannot use `core::convert::From`. + pub const fn from_usize(v: usize) -> Status { + Status(v) + } + + /// Return Underlying Integer Representation + /// + /// This takes the `Status` object and returns the underlying integer representation as + /// defined by the UEFI specification. + pub const fn as_usize(&self) -> usize { + self.0 + } + + fn value(&self) -> usize { + self.0 + } + + fn mask(&self) -> usize { + self.value() & Status::MASK + } + + /// Check whether this is an error + /// + /// This returns true if the given status code is considered an error. Errors mean the + /// operation did not succeed, nor produce any valuable output. Output parameters must be + /// considered invalid if an error was returned. That is, its content is not well defined. + pub fn is_error(&self) -> bool { + self.mask() == Status::ERROR_MASK + } + + /// Check whether this is a warning + /// + /// This returns true if the given status code is considered a warning. Warnings are to be + /// treated as success, but might indicate data loss or other device errors. However, if an + /// operation returns with a warning code, it must be considered successfull, and the output + /// parameters are valid. + pub fn is_warning(&self) -> bool { + self.value() != 0 && self.mask() == Status::WARNING_MASK + } +} + +impl From for Result { + fn from(status: Status) -> Self { + if status.is_error() { + Err(status) + } else { + Ok(status) + } + } +} + +impl Guid { + const fn u32_to_bytes_le(num: u32) -> [u8; 4] { + [ + num as u8, + (num >> 8) as u8, + (num >> 16) as u8, + (num >> 24) as u8, + ] + } + + const fn u32_from_bytes_le(bytes: &[u8; 4]) -> u32 { + (bytes[0] as u32) + | ((bytes[1] as u32) << 8) + | ((bytes[2] as u32) << 16) + | ((bytes[3] as u32) << 24) + } + + const fn u16_to_bytes_le(num: u16) -> [u8; 2] { + [num as u8, (num >> 8) as u8] + } + + const fn u16_from_bytes_le(bytes: &[u8; 2]) -> u16 { + (bytes[0] as u16) | ((bytes[1] as u16) << 8) + } + + /// Initialize a Guid from its individual fields + /// + /// This function initializes a Guid object given the individual fields as specified in the + /// UEFI specification. That is, if you simply copy the literals from the specification into + /// your code, this function will correctly initialize the Guid object. + /// + /// In other words, this takes the individual fields in native endian and converts them to the + /// correct endianness for a UEFI Guid. + /// + /// Due to the fact that UEFI Guids use variant 2 of the UUID specification in a little-endian + /// (or even mixed-endian) format, the following transformation is likely applied from text + /// representation to binary representation: + /// + /// 00112233-4455-6677-8899-aabbccddeeff + /// => + /// 33 22 11 00 55 44 77 66 88 99 aa bb cc dd ee ff + /// + /// (Note that UEFI protocols often use `88-99` instead of `8899`) + /// The first 3 parts use little-endian notation, the last 2 use big-endian. + pub const fn from_fields( + time_low: u32, + time_mid: u16, + time_hi_and_version: u16, + clk_seq_hi_res: u8, + clk_seq_low: u8, + node: &[u8; 6], + ) -> Guid { + Guid { + time_low: Self::u32_to_bytes_le(time_low), + time_mid: Self::u16_to_bytes_le(time_mid), + time_hi_and_version: Self::u16_to_bytes_le(time_hi_and_version), + clk_seq_hi_res: clk_seq_hi_res, + clk_seq_low: clk_seq_low, + node: *node, + } + } + + /// Access a Guid as individual fields + /// + /// This decomposes a Guid back into the individual fields as given in the specification. The + /// individual fields are returned in native-endianness. + pub const fn as_fields(&self) -> (u32, u16, u16, u8, u8, &[u8; 6]) { + ( + Self::u32_from_bytes_le(&self.time_low), + Self::u16_from_bytes_le(&self.time_mid), + Self::u16_from_bytes_le(&self.time_hi_and_version), + self.clk_seq_hi_res, + self.clk_seq_low, + &self.node, + ) + } + + /// Initialize a Guid from its byte representation + /// + /// Create a new Guid object from its byte representation. This + /// reinterprets the bytes as a Guid and copies them into a new Guid + /// instance. Note that you can safely transmute instead. + /// + /// See `as_bytes()` for the inverse operation. + pub const fn from_bytes(bytes: &[u8; 16]) -> Self { + unsafe { core::mem::transmute::<[u8; 16], Guid>(*bytes) } + } + + /// Access a Guid as raw byte array + /// + /// This provides access to a Guid through a byte array. It is a simple re-interpretation of + /// the Guid value as a 128-bit byte array. No conversion is performed. This is a simple cast. + pub const fn as_bytes(&self) -> &[u8; 16] { + unsafe { core::mem::transmute::<&Guid, &[u8; 16]>(self) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::mem::{align_of, size_of}; + + // Helper to compute a hash of an object. + fn hash(v: &T) -> u64 { + let mut h = std::hash::DefaultHasher::new(); + v.hash(&mut h); + core::hash::Hasher::finish(&h) + } + + // Verify Type Size and Alignemnt + // + // Since UEFI defines explicitly the ABI of their types, we can verify that our implementation + // is correct by checking the size and alignment of the ABI types matches what the spec + // mandates. + #[test] + fn type_size_and_alignment() { + // + // Booleans + // + + assert_eq!(size_of::(), 1); + assert_eq!(align_of::(), 1); + + // + // Char8 / Char16 + // + + assert_eq!(size_of::(), 1); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + // + // Status + // + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + // + // Handles / Events + // + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + assert_eq!(size_of::(), size_of::<*mut ()>()); + assert_eq!(align_of::(), align_of::<*mut ()>()); + assert_eq!(size_of::(), size_of::<*mut ()>()); + assert_eq!(align_of::(), align_of::<*mut ()>()); + + // + // Lba / Tpl + // + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + // + // PhysicalAddress / VirtualAddress + // + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + // + // ImageEntryPoint + // + + assert_eq!(size_of::(), size_of::()); + assert_eq!(align_of::(), align_of::()); + + // + // Guid + // + + assert_eq!(size_of::(), 16); + assert_eq!(align_of::(), 4); + + // + // Networking Types + // + + assert_eq!(size_of::(), 32); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 4); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 16); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 16); + assert_eq!(align_of::(), 4); + } + + #[test] + fn eficall() { + // + // Make sure the eficall!{} macro can deal with all kinds of function callbacks. + // + + let _: eficall! {fn()}; + let _: eficall! {unsafe fn()}; + let _: eficall! {fn(i32)}; + let _: eficall! {fn(i32) -> i32}; + let _: eficall! {fn(i32, i32) -> (i32, i32)}; + + eficall! {fn _unused00() {}} + eficall! {unsafe fn _unused01() {}} + eficall! {pub unsafe fn _unused02() {}} + } + + // Verify Boolean ABI + // + // Even though booleans are strictly 1-bit, and thus 0 or 1, in practice all UEFI systems + // treat it more like C does, and a boolean formatted as `u8` now allows any value other than + // 0 to represent `true`. Make sure we support the same. + #[test] + fn booleans() { + // Verify PartialEq works. + assert_ne!(Boolean::FALSE, Boolean::TRUE); + + // Verify Boolean<->bool conversion and comparison works. + assert_eq!(Boolean::FALSE, false); + assert_eq!(Boolean::TRUE, true); + + // Iterate all possible values for `u8` and verify 0 behaves as `false`, and everything + // else behaves as `true`. We verify both, the natural constructor through `From`, as well + // as a transmute. + for i in 0u8..=255u8 { + let v1: Boolean = i.into(); + let v2: Boolean = unsafe { std::mem::transmute::(i) }; + + assert_eq!(v1, v2); + assert_eq!(v1, v1); + assert_eq!(v2, v2); + + match i { + 0 => { + assert_eq!(v1, Boolean::FALSE); + assert_eq!(v1, false); + assert_eq!(v2, Boolean::FALSE); + assert_eq!(v2, false); + + assert_ne!(v1, Boolean::TRUE); + assert_ne!(v1, true); + assert_ne!(v2, Boolean::TRUE); + assert_ne!(v2, true); + + assert!(v1 < Boolean::TRUE); + assert!(v1 < true); + assert!(v1 >= Boolean::FALSE); + assert!(v1 >= false); + assert!(v1 <= Boolean::FALSE); + assert!(v1 <= false); + assert_eq!(v1.cmp(&true.into()), core::cmp::Ordering::Less); + assert_eq!(v1.cmp(&false.into()), core::cmp::Ordering::Equal); + + assert_eq!(hash(&v1), hash(&false)); + } + _ => { + assert_eq!(v1, Boolean::TRUE); + assert_eq!(v1, true); + assert_eq!(v2, Boolean::TRUE); + assert_eq!(v2, true); + + assert_ne!(v1, Boolean::FALSE); + assert_ne!(v1, false); + assert_ne!(v2, Boolean::FALSE); + assert_ne!(v2, false); + + assert!(v1 <= Boolean::TRUE); + assert!(v1 <= true); + assert!(v1 >= Boolean::TRUE); + assert!(v1 >= true); + assert!(v1 > Boolean::FALSE); + assert!(v1 > false); + assert_eq!(v1.cmp(&true.into()), core::cmp::Ordering::Equal); + assert_eq!(v1.cmp(&false.into()), core::cmp::Ordering::Greater); + + assert_eq!(hash(&v1), hash(&true)); + } + } + } + } + + // Verify Guid Manipulations + // + // Test that creation of Guids from fields and bytes yields the expected + // values, and conversions work as expected. + #[test] + fn guid() { + let fields = ( + 0x550e8400, + 0xe29b, + 0x41d4, + 0xa7, + 0x16, + &[0x44, 0x66, 0x55, 0x44, 0x00, 0x00], + ); + #[rustfmt::skip] + let bytes = [ + 0x00, 0x84, 0x0e, 0x55, + 0x9b, 0xe2, + 0xd4, 0x41, + 0xa7, + 0x16, + 0x44, 0x66, 0x55, 0x44, 0x00, 0x00, + ]; + let (f0, f1, f2, f3, f4, f5) = fields; + let g_fields = Guid::from_fields(f0, f1, f2, f3, f4, f5); + let g_bytes = Guid::from_bytes(&bytes); + + assert_eq!(g_fields, g_bytes); + assert_eq!(g_fields.as_bytes(), &bytes); + assert_eq!(g_bytes.as_fields(), fields); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/hii.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/hii.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/hii.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/hii.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1300 @@ +//! Human Interface Infrastructure (HII) +//! +//! This module contains bindings and definitions copied from Section 33.3 of +//! the UEFI spec, as well as the core HII related definitions. + +// +// Core HII Definitions +// + +// This is the exception to the rule. It's defined in 34.8 (HII_DATABASE +// protocol), not 33.3, but it's used throughout the HII protocols, so it makes +// sense to be defined at the base. +pub type Handle = *mut core::ffi::c_void; + +// +// 33.3.1 Package Lists and Package Headers +// + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct PackageHeader { + pub length: [u8; 3], + pub r#type: u8, + pub data: [u8; N], +} + +pub const PACKAGE_TYPE_ALL: u8 = 0x00; +pub const PACKAGE_TYPE_GUID: u8 = 0x01; +pub const PACKAGE_FORMS: u8 = 0x02; +pub const PACKAGE_STRINGS: u8 = 0x04; +pub const PACKAGE_FONTS: u8 = 0x05; +pub const PACKAGE_IMAGES: u8 = 0x06; +pub const PACKAGE_SIMPLE_FONTS: u8 = 0x07; +pub const PACKAGE_DEVICE_PATH: u8 = 0x08; +pub const PACKAGE_KEYBOARD_LAYOUT: u8 = 0x09; +pub const PACKAGE_ANIMATIONS: u8 = 0x0A; +pub const PACKAGE_END: u8 = 0xDF; +pub const PACKAGE_TYPE_SYSTEM_BEGIN: u8 = 0xE0; +pub const PACKAGE_TYPE_SYSTEM_END: u8 = 0xFF; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct PackageListHeader { + pub package_list_guid: crate::base::Guid, + pub package_length: u32, +} + +// +// 33.3.3 Font Package +// + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FontPackageHdr { + pub header: PackageHeader, + pub hdr_size: u32, + pub glyph_block_offset: u32, + pub cell: GlyphInfo, + pub font_style: FontStyle, + pub font_family: [crate::base::Char16; N], +} + +pub type FontStyle = u32; + +pub const FONT_STYLE_NORMAL: FontStyle = 0x00000000; +pub const FONT_STYLE_BOLD: FontStyle = 0x00000001; +pub const FONT_STYLE_ITALIC: FontStyle = 0x00000002; +pub const FONT_STYLE_EMBOSS: FontStyle = 0x00010000; +pub const FONT_STYLE_OUTLINE: FontStyle = 0x00020000; +pub const FONT_STYLE_SHADOW: FontStyle = 0x00040000; +pub const FONT_STYLE_UNDERLINE: FontStyle = 0x00080000; +pub const FONT_STYLE_DBL_UNDER: FontStyle = 0x00100000; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GlyphBlock { + pub block_type: u8, + pub block_body: [u8; N], +} + +pub const GIBT_END: u8 = 0x00; +pub const GIBT_GLYPH: u8 = 0x10; +pub const GIBT_GLYPHS: u8 = 0x11; +pub const GIBT_GLYPH_DEFAULT: u8 = 0x12; +pub const GIBT_GLYPHS_DEFAULT: u8 = 0x13; +pub const GIBT_GLYPH_VARIABILITY: u8 = 0x14; +pub const GIBT_DUPLICATE: u8 = 0x20; +pub const GIBT_SKIP2: u8 = 0x21; +pub const GIBT_SKIP1: u8 = 0x22; +pub const GIBT_DEFAULTS: u8 = 0x23; +pub const GIBT_EXT1: u8 = 0x30; +pub const GIBT_EXT2: u8 = 0x31; +pub const GIBT_EXT4: u8 = 0x32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GlyphInfo { + pub width: u16, + pub height: u16, + pub offset_x: i16, + pub offset_y: i16, + pub advance_x: i16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtDefaultsBlock { + pub header: GlyphBlock, + pub cell: GlyphInfo, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtDuplicateBlock { + pub header: GlyphBlock, + pub char_value: crate::base::Char16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GlyphGibtEndBlock { + pub header: GlyphBlock, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtExt1Block { + pub header: GlyphBlock, + pub block_type_2: u8, + pub length: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtExt2Block { + pub header: GlyphBlock, + pub block_type_2: u8, + pub length: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtExt4Block { + pub header: GlyphBlock, + pub block_type_2: u8, + pub length: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtGlyphBlock { + pub header: GlyphBlock, + pub cell: GlyphInfo, + pub bitmap_data: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtGlyphsBlock { + pub header: GlyphBlock, + pub cell: GlyphInfo, + pub count: u16, + pub bitmap_data: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtGlyphDefaultBlock { + pub header: GlyphBlock, + pub bitmap_data: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtGlypshDefaultBlock { + pub header: GlyphBlock, + pub count: u16, + pub bitmap_data: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtSkip2Block { + pub header: GlyphBlock, + pub skip_count: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtSkip1Block { + pub header: GlyphBlock, + pub skip_count: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct GibtVariabilityBlock { + pub header: GlyphBlock, + pub cell: GlyphInfo, + pub glyph_pack_in_bits: u8, + pub bitmap_data: [u8; N], +} + +// +// 33.3.8 Forms Package +// + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FormPackageHdr { + pub header: PackageHeader, + pub op_code_header: IfrOpHeader, + // Op-Codes Follow... +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrOpHeader { + pub op_code: u8, + pub length_and_scope: u8, // Length:7, Scope:1 +} + +pub type QuestionId = u16; +pub type ImageId = u16; +pub type StringId = u16; +pub type FormId = u16; +pub type VarstoreId = u16; +pub type AnimationId = u16; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrQuestionHeader { + pub header: IfrStatementHeader, + pub question_id: QuestionId, + pub var_store_id: VarstoreId, + pub var_store_info: IfrQuestionHeaderVarstoreInfo, + pub flags: u8, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IfrQuestionHeaderVarstoreInfo { + pub var_name: StringId, + pub var_offset: u16, +} + +pub const IFR_FLAG_READ_ONLY: u8 = 0x01; +pub const IFR_FLAG_CALLBACK: u8 = 0x04; +pub const IFR_FLAG_RESET_REQUIRED: u8 = 0x10; +pub const IFR_FLAG_REST_STYLE: u8 = 0x20; +pub const IFR_FLAG_RECONNECT_REQUIRED: u8 = 0x40; +pub const IFR_FLAG_OPTIONS_ONLY: u8 = 0x80; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrStatementHeader { + pub prompt: StringId, + pub help: StringId, +} + +pub const IFR_FORM_OP: u8 = 0x01; +pub const IFR_SUBTITLE_OP: u8 = 0x02; +pub const IFR_TEXT_OP: u8 = 0x03; +pub const IFR_IMAGE_OP: u8 = 0x04; +pub const IFR_ONE_OF_OP: u8 = 0x05; +pub const IFR_CHECKBOX_OP: u8 = 0x06; +pub const IFR_NUMERIC_OP: u8 = 0x07; +pub const IFR_PASSWORD_OP: u8 = 0x08; +pub const IFR_ONE_OF_OPTION_OP: u8 = 0x09; +pub const IFR_SUPPRESS_IF_OP: u8 = 0x0A; +pub const IFR_LOCKED_OP: u8 = 0x0B; +pub const IFR_ACTION_OP: u8 = 0x0C; +pub const IFR_RESET_BUTTON_OP: u8 = 0x0D; +pub const IFR_FORM_SET_OP: u8 = 0x0E; +pub const IFR_REF_OP: u8 = 0x0F; +pub const IFR_NO_SUBMIT_IF_OP: u8 = 0x10; +pub const IFR_INCONSISTENT_IF_OP: u8 = 0x11; +pub const IFR_EQ_ID_VAL_OP: u8 = 0x12; +pub const IFR_EQ_ID_ID_OP: u8 = 0x13; +pub const IFR_EQ_ID_VAL_LIST_OP: u8 = 0x14; +pub const IFR_AND_OP: u8 = 0x15; +pub const IFR_OR_OP: u8 = 0x16; +pub const IFR_NOT_OP: u8 = 0x17; +pub const IFR_RULE_OP: u8 = 0x18; +pub const IFR_GRAY_OUT_IF_OP: u8 = 0x19; +pub const IFR_DATE_OP: u8 = 0x1A; +pub const IFR_TIME_OP: u8 = 0x1B; +pub const IFR_STRING_OP: u8 = 0x1C; +pub const IFR_REFRESH_OP: u8 = 0x1D; +pub const IFR_DISABLE_IF_OP: u8 = 0x1E; +pub const IFR_ANIMATION_OP: u8 = 0x1F; +pub const IFR_TO_LOWER_OP: u8 = 0x20; +pub const IFR_TO_UPPER_OP: u8 = 0x21; +pub const IFR_MAP_OP: u8 = 0x22; +pub const IFR_ORDERED_LIST_OP: u8 = 0x23; +pub const IFR_VARSTORE_OP: u8 = 0x24; +pub const IFR_VARSTORE_NAME_VALUE_OP: u8 = 0x25; +pub const IFR_VARSTORE_EFI_OP: u8 = 0x26; +pub const IFR_VARSTORE_DEVICE_OP: u8 = 0x27; +pub const IFR_VERSION_OP: u8 = 0x28; +pub const IFR_END_OP: u8 = 0x29; +pub const IFR_MATCH_OP: u8 = 0x2A; +pub const IFR_GET_OP: u8 = 0x2B; +pub const IFR_SET_OP: u8 = 0x2C; +pub const IFR_READ_OP: u8 = 0x2D; +pub const IFR_WRITE_OP: u8 = 0x2E; +pub const IFR_EQUAL_OP: u8 = 0x2F; +pub const IFR_NOT_EQUAL_OP: u8 = 0x30; +pub const IFR_GREATER_THAN_OP: u8 = 0x31; +pub const IFR_GREATER_EQUAL_OP: u8 = 0x32; +pub const IFR_LESS_THAN_OP: u8 = 0x33; +pub const IFR_LESS_EQUAL_OP: u8 = 0x34; +pub const IFR_BITWISE_AND_OP: u8 = 0x35; +pub const IFR_BITWISE_OR_OP: u8 = 0x36; +pub const IFR_BITWISE_NOT_OP: u8 = 0x37; +pub const IFR_SHIFT_LEFT_OP: u8 = 0x38; +pub const IFR_SHIFT_RIGHT_OP: u8 = 0x39; +pub const IFR_ADD_OP: u8 = 0x3A; +pub const IFR_SUBTRACT_OP: u8 = 0x3B; +pub const IFR_MULTIPLY_OP: u8 = 0x3C; +pub const IFR_DIVIDE_OP: u8 = 0x3D; +pub const IFR_MODULO_OP: u8 = 0x3E; +pub const IFR_RULE_REF_OP: u8 = 0x3F; +pub const IFR_QUESTION_REF1_OP: u8 = 0x40; +pub const IFR_QUESTION_REF2_OP: u8 = 0x41; +pub const IFR_UINT8_OP: u8 = 0x42; +pub const IFR_UINT16_OP: u8 = 0x43; +pub const IFR_UINT32_OP: u8 = 0x44; +pub const IFR_UINT64_OP: u8 = 0x45; +pub const IFR_TRUE_OP: u8 = 0x46; +pub const IFR_FALSE_OP: u8 = 0x47; +pub const IFR_TO_UINT_OP: u8 = 0x48; +pub const IFR_TO_STRING_OP: u8 = 0x49; +pub const IFR_TO_BOOLEAN_OP: u8 = 0x4A; +pub const IFR_MID_OP: u8 = 0x4B; +pub const IFR_FIND_OP: u8 = 0x4C; +pub const IFR_TOKEN_OP: u8 = 0x4D; +pub const IFR_STRING_REF1_OP: u8 = 0x4E; +pub const IFR_STRING_REF2_OP: u8 = 0x4F; +pub const IFR_CONDITIONAL_OP: u8 = 0x50; +pub const IFR_QUESTION_REF3_OP: u8 = 0x51; +pub const IFR_ZERO_OP: u8 = 0x52; +pub const IFR_ONE_OP: u8 = 0x53; +pub const IFR_ONES_OP: u8 = 0x54; +pub const IFR_UNDEFINED_OP: u8 = 0x55; +pub const IFR_LENGTH_OP: u8 = 0x56; +pub const IFR_DUP_OP: u8 = 0x57; +pub const IFR_THIS_OP: u8 = 0x58; +pub const IFR_SPAN_OP: u8 = 0x59; +pub const IFR_VALUE_OP: u8 = 0x5A; +pub const IFR_DEFAULT_OP: u8 = 0x5B; +pub const IFR_DEFAULTSTORE_OP: u8 = 0x5C; +pub const IFR_FORM_MAP_OP: u8 = 0x5D; +pub const IFR_CATENATE_OP: u8 = 0x5E; +pub const IFR_GUID_OP: u8 = 0x5F; +pub const IFR_SECURITY_OP: u8 = 0x60; +pub const IFR_MODAL_TAG_OP: u8 = 0x61; +pub const IFR_REFRESH_ID_OP: u8 = 0x62; +pub const IFR_WARNING_IF_OP: u8 = 0x63; +pub const IFR_MATCH2_OP: u8 = 0x64; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrAction { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub question_config: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrAction1 { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrAnimation { + pub header: IfrOpHeader, + pub id: AnimationId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrAdd { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrAnd { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrBitwiseAnd { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrBitwiseNot { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrBitwiseOr { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrCatenate { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrCheckbox { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub flags: u8, +} + +pub const IFR_CHECKBOX_DEFAULT: u8 = 0x01; +pub const IFR_CHECKBOX_DEFAULT_MFG: u8 = 0x02; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrConditional { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrDate { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub flags: u8, +} + +pub const QF_DATE_YEAR_SUPPRESS: u8 = 0x01; +pub const QF_DATE_MONTH_SUPPRESS: u8 = 0x02; +pub const QF_DATE_DAY_SUPPRESS: u8 = 0x04; +pub const QF_DATE_STORAGE: u8 = 0x30; + +pub const QF_DATE_STORAGE_NORMAL: u8 = 0x00; +pub const QF_DATE_STORAGE_TIME: u8 = 0x10; +pub const QF_DATE_STORAGE_WAKEUP: u8 = 0x20; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrDefault { + pub header: IfrOpHeader, + pub default_id: u16, + pub r#type: u8, + pub value: IfrTypeValue, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrDefault2 { + pub header: IfrOpHeader, + pub default_id: u16, + pub r#type: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrDefaultstore { + pub header: IfrOpHeader, + pub default_name: StringId, + pub default_id: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrDisableIf { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrDivide { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrDup { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrEnd { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrEqual { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrEqIdId { + pub header: IfrOpHeader, + pub question_id_1: QuestionId, + pub question_id_2: QuestionId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrEqIdValList { + pub header: IfrOpHeader, + pub question_id: QuestionId, + pub list_length: u16, + pub value_list: [u16; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrEqIdVal { + pub header: IfrOpHeader, + pub question_id: QuestionId, + pub value: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrFalse { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrFind { + pub header: IfrOpHeader, + pub format: u8, +} + +pub const IFR_FF_CASE_SENSITIVE: u8 = 0x00; +pub const IFR_FF_CASE_INSENSITIVE: u8 = 0x01; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrForm { + pub header: IfrOpHeader, + pub form_id: FormId, + pub form_title: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrFormMapMethod { + pub method_title: StringId, + pub method_identifier: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrFormMap { + pub header: IfrOpHeader, + pub form_id: FormId, + pub methods: [IfrFormMapMethod; N], +} + +pub const STANDARD_FORM_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3bd2f4ec, + 0xe524, + 0x46e4, + 0xa9, + 0xd8, + &[0x51, 0x01, 0x17, 0x42, 0x55, 0x62], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrFormSet { + pub header: IfrOpHeader, + pub guid: crate::base::Guid, + pub form_set_title: StringId, + pub help: StringId, + pub flags: u8, + pub class_guid: [crate::base::Guid; N], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrGet { + pub header: IfrOpHeader, + pub var_store_id: VarstoreId, + pub var_store_info: IfrGetVarStoreInfo, + pub var_store_type: u8, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IfrGetVarStoreInfo { + pub var_name: StringId, + pub var_offset: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrGrayOutIf { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrGreaterEqual { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrGreaterThan { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrGuid { + pub header: IfrOpHeader, + pub guid: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrImage { + pub id: ImageId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrInconsistentIf { + pub header: IfrOpHeader, + pub error: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrLength { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrLessEqual { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrLessThan { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrLocked { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrMap { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrMatch { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrMid { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrModalTag { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrModulo { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrMultiply { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNot { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNotEqual { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNoSubmitIf { + pub header: IfrOpHeader, + pub error: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNumericDataU8 { + pub min_value: u8, + pub max_value: u8, + pub step: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNumericDataU16 { + pub min_value: u16, + pub max_value: u16, + pub step: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNumericDataU32 { + pub min_value: u32, + pub max_value: u32, + pub step: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrNumericDataU64 { + pub min_value: u64, + pub max_value: u64, + pub step: u64, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IfrNumericData { + pub r#u8: IfrNumericDataU8, + pub r#u16: IfrNumericDataU16, + pub r#u32: IfrNumericDataU32, + pub r#u64: IfrNumericDataU64, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrNumeric { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub flags: u8, + pub data: IfrNumericData, +} + +pub const IFR_NUMERIC_SIZE: u8 = 0x03; +pub const IFR_NUMERIC_SIZE_1: u8 = 0x00; +pub const IFR_NUMERIC_SIZE_2: u8 = 0x01; +pub const IFR_NUMERIC_SIZE_4: u8 = 0x02; +pub const IFR_NUMERIC_SIZE_8: u8 = 0x03; + +pub const IFR_DISPLAY: u8 = 0x30; +pub const IFR_DISPLAY_INT_DEC: u8 = 0x00; +pub const IFR_DISPLAY_UINT_DEC: u8 = 0x10; +pub const IFR_DISPLAY_UINT_HEX: u8 = 0x20; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrOne { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrOnes { + pub header: IfrOpHeader, +} + +type IfrOneOfData = IfrNumericData; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrOneOf { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub flags: u8, + pub data: IfrOneOfData, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrOneOfOption { + pub header: IfrOpHeader, + pub option: StringId, + pub flags: u8, + pub r#type: u8, + pub value: IfrTypeValue, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IfrTypeValue { + pub r#u8: u8, + pub r#u16: u16, + pub r#u32: u32, + pub r#u64: u64, + pub b: crate::base::Boolean, + pub time: Time, + pub date: Date, + pub string: StringId, + pub r#ref: Ref, + pub buffer: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Time { + pub hour: u8, + pub minute: u8, + pub second: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Date { + pub year: u16, + pub month: u8, + pub day: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Ref { + pub question_id: QuestionId, + pub form_id: FormId, + pub form_set_guid: crate::base::Guid, + pub device_path: StringId, +} + +pub const IFR_TYPE_NUM_SIZE_8: u8 = 0x00; +pub const IFR_TYPE_NUM_SIZE_16: u8 = 0x01; +pub const IFR_TYPE_NUM_SIZE_32: u8 = 0x02; +pub const IFR_TYPE_NUM_SIZE_64: u8 = 0x03; +pub const IFR_TYPE_BOOLEAN: u8 = 0x04; +pub const IFR_TYPE_TIME: u8 = 0x05; +pub const IFR_TYPE_DATE: u8 = 0x06; +pub const IFR_TYPE_STRING: u8 = 0x07; +pub const IFR_TYPE_OTHER: u8 = 0x08; +pub const IFR_TYPE_UNDEFINED: u8 = 0x09; +pub const IFR_TYPE_ACTION: u8 = 0x0A; +pub const IFR_TYPE_BUFFER: u8 = 0x0B; +pub const IFR_TYPE_REF: u8 = 0x0C; + +pub const IFR_OPTION_DEFAULT: u8 = 0x10; +pub const IFR_OPTION_DEFAULT_MFG: u8 = 0x20; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrOr { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrOrderedList { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub max_containers: u8, + pub flags: u8, +} + +pub const IFR_UNIQUE_SET: u8 = 0x01; +pub const IFR_NO_EMPTY_SET: u8 = 0x02; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrPassword { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub min_size: u16, + pub max_size: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrQuestionRef1 { + pub header: IfrOpHeader, + pub question_id: QuestionId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrQuestionRef2 { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrQuestionRef3 { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrQuestionRef32 { + pub header: IfrOpHeader, + pub device_path: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrQuestionRef33 { + pub header: IfrOpHeader, + pub device_path: StringId, + pub guid: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrRead { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrRef { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub form_id: FormId, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrRef2 { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub form_id: FormId, + pub question_id: QuestionId, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrRef3 { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub form_id: FormId, + pub question_id: QuestionId, + pub form_set_id: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrRef4 { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub form_id: FormId, + pub question_id: QuestionId, + pub form_set_id: crate::base::Guid, + pub device_path: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrRef5 { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrRefresh { + pub header: IfrOpHeader, + pub refresh_interval: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrRefreshId { + pub header: IfrOpHeader, + pub refresh_event_group_id: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrResetButton { + pub header: IfrOpHeader, + pub statement: IfrStatementHeader, + pub deafult_id: DefaultId, +} + +pub type DefaultId = u16; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrRule { + pub header: IfrOpHeader, + pub rule_id: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrRuleRef { + pub header: IfrOpHeader, + pub rule_id: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrSecurity { + pub header: IfrOpHeader, + pub permissions: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IfrSetVarStoreInfo { + pub var_name: StringId, + pub var_offset: u16, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrSet { + pub header: IfrOpHeader, + pub var_store_id: VarstoreId, + pub var_store_info: IfrSetVarStoreInfo, + pub var_store_type: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrShiftLeft { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrShiftRight { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrSpan { + pub header: IfrOpHeader, + pub flags: u8, +} + +pub const IFR_FLAGS_FIRST_MATCHING: u8 = 0x00; +pub const IFR_FLAGS_FIRST_NON_MATCHING: u8 = 0x01; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrString { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub min_size: u8, + pub max_size: u8, + pub flags: u8, +} + +pub const IFR_STRING_MULTI_LINE: u8 = 0x01; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrStringRef1 { + pub header: IfrOpHeader, + pub string_id: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrStringRef2 { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrSubtitle { + pub header: IfrOpHeader, + pub statement: IfrStatementHeader, + pub flags: u8, +} + +pub const IFR_FLAGS_HORIZONTAL: u8 = 0x01; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrSubtract { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrSuppressIf { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrText { + pub header: IfrOpHeader, + pub statement: IfrStatementHeader, + pub text_two: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrThis { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IfrTime { + pub header: IfrOpHeader, + pub question: IfrQuestionHeader, + pub flags: u8, +} + +pub const QF_TIME_HOUR_SUPPRESS: u8 = 0x01; +pub const QF_TIME_MINUTE_SUPPRESS: u8 = 0x02; +pub const QF_TIME_SECOND_SUPPRESS: u8 = 0x04; +pub const QF_TIME_STORAGE: u8 = 0x30; + +pub const QF_TIME_STORAGE_NORMAL: u8 = 0x00; +pub const QF_TIME_STORAGE_TIME: u8 = 0x10; +pub const QF_TIME_STORAGE_WAKEUP: u8 = 0x20; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToken { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToBoolean { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToLower { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToString { + pub header: IfrOpHeader, + pub format: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToUint { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrToUpper { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrTrue { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrUint8 { + pub header: IfrOpHeader, + pub value: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrUint16 { + pub header: IfrOpHeader, + pub value: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrUint32 { + pub header: IfrOpHeader, + pub value: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrUint64 { + pub header: IfrOpHeader, + pub value: u64, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrUndefined { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrValue { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrVarstore { + pub header: IfrOpHeader, + pub guid: crate::base::Guid, + pub var_store_id: VarstoreId, + pub size: u16, + pub name: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrVarstoreNameValue { + pub header: IfrOpHeader, + pub var_store_id: VarstoreId, + pub guid: crate::base::Guid, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrVarstoreEfi { + pub header: IfrOpHeader, + pub var_store_id: VarstoreId, + pub guid: crate::base::Guid, + pub attributes: u32, + pub size: u16, + pub name: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrVarstoreDevice { + pub header: IfrOpHeader, + pub device_path: StringId, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrVersion { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrWrite { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrZero { + pub header: IfrOpHeader, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrWarningIf { + pub header: IfrOpHeader, + pub warning: StringId, + pub time_out: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IfrMatch2 { + pub header: IfrOpHeader, + pub syntax_type: crate::base::Guid, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,182 @@ +//! UEFI Reference Specification Protocol Constants and Definitions +//! +//! This project provides protocol constants and definitions as defined in the UEFI Reference +//! Specification. The aim is to provide all these constants as C-ABI compatible imports to rust. +//! Safe rust abstractions over the UEFI API are out of scope of this project. That is, the +//! purpose is really just to extract all the bits and pieces from the specification and provide +//! them as rust types and constants. +//! +//! While we strongly recommend using safe abstractions to interact with UEFI systems, this +//! project serves both as base to write those abstractions, but also as last resort if you have +//! to deal with quirks and peculiarities of UEFI systems directly. Therefore, several examples +//! are included, which show how to interact with UEFI systems from rust. These serve both as +//! documentation for anyone interested in how the system works, but also as base for anyone +//! implementing safe abstractions on top. +//! +//! # Target Configuration +//! +//! Rust code can be compiled natively for UEFI systems. However, you are quite unlikely to have a +//! rust compiler running in an UEFI environment. Therefore, you will most likely want to cross +//! compile your rust code for UEFI systems. To do this, you need a target-configuration for UEFI +//! systems. As of rust-1.61, upstream rust includes the following UEFI targets: +//! +//! * `aarch64-unknown-uefi`: A native UEFI target for aarch64 systems (64bit ARM). +//! * `i686-unknown-uefi`: A native UEFI target for i686 systems (32bit Intel x86). +//! * `x86_64-unknown-uefi`: A native UEFI target for x86-64 systems (64bit Intel x86). +//! +//! If none of these targets match your architecture, you have to create the target specification +//! yourself. Feel free to contact the `r-efi` project for help. +//! +//! # Transpose Guidelines +//! +//! The UEFI specification provides C language symbols and definitions of all +//! its protocols and features. Those are integral parts of the specification +//! and UEFI programming is often tightly coupled with the C language. For +//! better compatibility to existing UEFI documentation, all the rust symbols +//! are transposed from C following strict rules, aiming for close similarity +//! to specification. This section gives a rationale on some of the less +//! obvious choices and tries to describe as many of those rules as possible. +//! +//! * `no enums`: Rust enums do not allow random discriminant values. However, +//! many UEFI enumerations use reserved ranges for vendor defined values. +//! These cannot be represented with rust enums in an efficient manner. +//! Hence, any enumerations are turned into rust constants with an +//! accompanying type alias. +//! +//! A detailed discussion can be found in: +//! +//! ```gitlog +//! commit 401a91901e860a5c0cd0f92b75dda0a72cf65322 +//! Author: David Rheinsberg +//! Date: Wed Apr 21 12:07:07 2021 +0200 +//! +//! r-efi: convert enums to constants +//! ``` +//! +//! * `no incomplete types`: Several structures use incomplete structure types +//! by using an unbound array as last member. While rust can easily +//! represent those within its type-system, such structures become DSTs, +//! hence even raw pointers to them become fat-pointers, and would thus +//! violate the UEFI ABI. +//! +//! Instead, we use const-generics to allow compile-time adjustment of the +//! variable-sized structures, with a default value of 0. This allows +//! computing different sizes of the structures without any runtime overhead. +//! +//! * `nullable callbacks as Option`: Rust has no raw function pointers, but +//! just normal Rust function pointers. Those, however, have no valid null +//! value. The Rust ABI guarantees that `Option` is an C-ABI +//! compatible replacement for nullable function pointers, with `None` being +//! mapped to `NULL`. Hence, whenever UEFI APIs require nullable function +//! pointers, we use `Option`. +//! +//! * `prefer *mut over *const`: Whenever we transpose pointers from the +//! specification into Rust, we prefer `*mut` in almost all cases. `*const` +//! should only be used if the underlying value is known not to be accessible +//! via any other mutable pointer type. Since this is rarely the case in +//! UEFI, we avoid it. +//! +//! The reasoning is that Rust allows coercing immutable types into `*const` +//! pointers, without any explicit casting required. However, immutable Rust +//! references require that no other mutable reference exists simultaneously. +//! This is not a guarantee of `const`-pointers in C / UEFI, hence this +//! coercion is usually ill-advised or even wrong. +//! +//! Lastly, note that `*mut` and `*const` and be `as`-casted in both +//! directions without violating any Rust guarantees. Any UB concerns always +//! stem from the safety guarantees of the surrounding code, not of the +//! raw-pointer handling. +//! +//! # Specification Details +//! +//! This section lists errata of, and general comments on, the UEFI +//! specification relevant to the development of `r-efi`: +//! +//! * The `Unload` function-pointer of the LoadedImageProtocol can be `NULL`, +//! despite the protocol documentation lacking any mention of this. Other +//! parts of the specification refer to images lacking an unload function, +//! but there is no explicit documentation how this manifests in the +//! protocol structure. EDK2 assumes `NULL` indicates a lack of unload +//! function, and an errata has been submitted to the UEFI forum. +//! +//! * The specification mandates an 8-byte alignment for the `GUID` structure +//! However, all widespread implementations (including EDK2) use a 4-byte +//! alignment. An errata has been reported to EDK2 (still pending). +//! +//! # Examples +//! +//! To write free-standing UEFI applications, you need to disable the entry-point provided by rust +//! and instead provide your own. Most target-configurations look for a function called `efi_main` +//! during linking and set it as entry point. If you use the target-configurations provided with +//! upstream rust, they will pick the function called `efi_main` as entry-point. +//! +//! The following example shows a minimal UEFI application, which simply returns success upon +//! invocation. Note that you must provide your own panic-handler when running without `libstd`. +//! In our case, we use a trivial implementation that simply loops forever. +//! +//! ```ignore +//! #![no_main] +//! #![no_std] +//! +//! use r_efi::efi; +//! +//! #[panic_handler] +//! fn panic_handler(_info: &core::panic::PanicInfo) -> ! { +//! loop {} +//! } +//! +//! #[export_name = "efi_main"] +//! pub extern fn main(_h: efi::Handle, _st: *mut efi::SystemTable) -> efi::Status { +//! efi::Status::SUCCESS +//! } +//! ``` + +// Mark this crate as `no_std`. We have no std::* dependencies (and we better don't have them), +// so no reason to require it. This does not mean that you cannot use std::* with UEFI. You have +// to port it to UEFI first, though. +// +// In case of unit-test compilation, we pull in `std` and drop the `no_std` marker. This allows +// basic unit-tests on the compilation host. For integration tests, we have separate compilation +// units, so they will be unaffected by this. +#![cfg_attr(not(test), no_std)] + +// Import the different core modules. We separate them into different modules to make it easier to +// work on them and describe what each part implements. This is different to the reference +// implementation, which uses a flat namespace due to its origins in the C language. For +// compatibility, we provide this flat namespace as well. See the `efi` submodule. +#[macro_use] +pub mod base; +#[macro_use] +pub mod hii; +#[macro_use] +pub mod system; + +// Import the protocols. Each protocol is separated into its own module, readily imported by the +// meta `protocols` module. Note that this puts all symbols into their respective protocol +// namespace, thus clearly separating them (unlike the UEFI Specification, which more often than +// not violates its own namespacing). +pub mod protocols; + +// Import vendor protocols. They are just like protocols in `protocols`, but +// separated for better namespacing. +pub mod vendor; + +/// Flat EFI Namespace +/// +/// The EFI namespace re-exports all symbols in a single, flat namespace. This allows mirroring +/// the entire EFI namespace as given in the specification and makes it easier to refer to them +/// with the same names as the reference C implementation. +/// +/// Note that the individual protocols are put into submodules. The specification does this in +/// most parts as well (by prefixing all symbols). This is not true in all cases, as the +/// specification suffers from lack of namespaces in the reference C language. However, we decided +/// to namespace the remaining bits as well, for better consistency throughout the API. This +/// should be self-explanatory in nearly all cases. +pub mod efi { + pub use crate::base::*; + pub use crate::system::*; + + pub use crate::hii; + pub use crate::protocols; + pub use crate::vendor; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/absolute_pointer.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/absolute_pointer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/absolute_pointer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/absolute_pointer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +//! Absolute Pointer Protocol +//! +//! Provides a simple method for accessing absolute pointer devices. This +//! includes devices such as touch screens and digitizers. The Absolute Pointer +//! Protocol allows information about a pointer device to be retrieved. The +//! protocol is attached to the device handle of an absolute pointer device, +//! and can be used for input from the user in the preboot environment. +//! +//! Supported devices may return 1, 2, or 3 axis of information. The Z axis may +//! optionally be used to return pressure data measurements derived from user +//! pen force. +//! +//! All supported devices must support a touch-active status. Supported devices +//! may optionally support a second input button, for example a pen +//! side-button. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x8d59d32b, + 0xc655, + 0x4ae9, + 0x9b, + 0x15, + &[0xf2, 0x59, 0x04, 0x99, 0x2a, 0x43], +); + +pub const SUPPORTS_ALT_ACTIVE: u32 = 0x00000001; +pub const SUPPORTS_PRESSURE_AS_Z: u32 = 0x00000002; + +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct Mode { + pub absolute_min_x: u64, + pub absolute_min_y: u64, + pub absolute_min_z: u64, + pub absolute_max_x: u64, + pub absolute_max_y: u64, + pub absolute_max_z: u64, + pub attributes: u32, +} + +pub const TOUCH_ACTIVE: u32 = 0x00000001; +pub const ALT_ACTIVE: u32 = 0x00000002; + +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct State { + pub current_x: u64, + pub current_y: u64, + pub current_z: u64, + pub active_buttons: u32, +} + +pub type Reset = eficall! {fn( + this: *mut Protocol, + extended_verification: bool, +) -> crate::base::Status}; + +pub type GetState = eficall! {fn( + this: *mut Protocol, + state: *mut State, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub reset: Reset, + pub get_state: GetState, + pub wait_for_input: crate::efi::Event, + pub mode: *mut Mode, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/block_io.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/block_io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/block_io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/block_io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +//! Block I/O Protocol +//! +//! Used to abstract mass storage devices to allow code running in the EFI boot services environment +//! to access the storage devices without specific knowledge of the type of device or controller that +//! manages the device. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x964e5b21, + 0x6459, + 0x11d2, + 0x8e, + 0x39, + &[0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub const REVISION: u64 = 0x0000000000010000u64; +pub const REVISION2: u64 = 0x0000000000020001u64; +pub const REVISION3: u64 = 0x000000000002001fu64; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Media { + pub media_id: u32, + pub removable_media: bool, + pub media_present: bool, + pub logical_partition: bool, + pub read_only: bool, + pub write_caching: bool, + pub block_size: u32, + pub io_align: u32, + pub last_block: crate::base::Lba, + pub lowest_aligned_lba: crate::base::Lba, + pub logical_blocks_per_physical_block: u32, + pub optimal_transfer_length_granularity: u32, +} + +pub type ProtocolReset = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolReadBlocks = eficall! {fn( + *mut Protocol, + u32, + crate::base::Lba, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolWriteBlocks = eficall! {fn( + *mut Protocol, + u32, + crate::base::Lba, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolFlushBlocks = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub media: *const Media, + pub reset: ProtocolReset, + pub read_blocks: ProtocolReadBlocks, + pub write_blocks: ProtocolWriteBlocks, + pub flush_blocks: ProtocolFlushBlocks, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/bus_specific_driver_override.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/bus_specific_driver_override.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/bus_specific_driver_override.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/bus_specific_driver_override.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +//! Bus Specific Driver Override Protocol +//! +//! This protocol matches one or more drivers to a controller. This protocol is +//! produced by a bus driver, and it is installed on the child handles of buses +//! that require a bus specific algorithm for matching drivers to controllers. +//! This protocol is used by the `EFI_BOOT_SERVICES.ConnectController()` boot +//! service to select the best driver for a controller. All of the drivers +//! returned by this protocol have a higher precedence than drivers found in +//! the general EFI Driver Binding search algorithm, but a lower precedence +//! than those drivers returned by the EFI Platform Driver Override Protocol. +//! If more than one driver image handle is returned by this protocol, then the +//! drivers image handles are returned in order from highest precedence to +//! lowest precedence. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3bc1b285, + 0x8a15, + 0x4a82, + 0xaa, + 0xbf, + &[0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65], +); + +pub type ProtocolGetDriver = eficall! {fn( + *mut Protocol, + *mut crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_driver: ProtocolGetDriver, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/debug_support.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debug_support.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/debug_support.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debug_support.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,835 @@ +//! Debug Support Protocol +//! +//! It provides the services to allow the debug agent to register callback functions that are +//! called either periodically or when specific processor exceptions occur. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x2755590c, + 0x6f3c, + 0x42fa, + 0x9e, + 0xa4, + &[0xa3, 0xba, 0x54, 0x3c, 0xda, 0x25], +); + +pub type InstructionSetArchitecture = u32; + +pub const ISA_IA32: InstructionSetArchitecture = 0x014c; +pub const ISA_X64: InstructionSetArchitecture = 0x8664; +pub const ISA_IPF: InstructionSetArchitecture = 0x0200; +pub const ISA_EBC: InstructionSetArchitecture = 0x0ebc; +pub const ISA_ARM: InstructionSetArchitecture = 0x1c2; +pub const ISA_AARCH64: InstructionSetArchitecture = 0xaa64; +pub const ISA_RISCV32: InstructionSetArchitecture = 0x5032; +pub const ISA_RISCV64: InstructionSetArchitecture = 0x5064; +pub const ISA_RISCV128: InstructionSetArchitecture = 0x5128; + +#[repr(C)] +#[derive(Clone, Copy)] +pub union SystemContext { + pub system_context_ebc: *mut SystemContextEbc, + pub system_context_ia32: *mut SystemContextIa32, + pub system_context_x64: *mut SystemContextX64, + pub system_context_ipf: *mut SystemContextIpf, + pub system_context_arm: *mut SystemContextArm, + pub system_context_aarch64: *mut SystemContextAArch64, + pub system_context_riscv32: *mut SystemContextRiscV32, + pub system_context_riscv64: *mut SystemContextRiscV64, + pub system_context_riscv128: *mut SystemContextRiscV128, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextEbc { + pub r0: u64, + pub r1: u64, + pub r2: u64, + pub r3: u64, + pub r4: u64, + pub r5: u64, + pub r6: u64, + pub r7: u64, + pub flags: u64, + pub control_flags: u64, + pub ip: u64, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextRiscV32 { + // Integer registers + pub zero: u32, + pub ra: u32, + pub sp: u32, + pub gp: u32, + pub tp: u32, + pub t0: u32, + pub t1: u32, + pub t2: u32, + pub s0fp: u32, + pub s1: u32, + pub a0: u32, + pub a1: u32, + pub a2: u32, + pub a3: u32, + pub a4: u32, + pub a5: u32, + pub a6: u32, + pub a7: u32, + pub s2: u32, + pub s3: u32, + pub s4: u32, + pub s5: u32, + pub s6: u32, + pub s7: u32, + pub s8: u32, + pub s9: u32, + pub s10: u32, + pub s11: u32, + pub t3: u32, + pub t4: u32, + pub t5: u32, + pub t6: u32, + // Floating registers for F, D and Q Standard Extensions + pub ft0: u128, + pub ft1: u128, + pub ft2: u128, + pub ft3: u128, + pub ft4: u128, + pub ft5: u128, + pub ft6: u128, + pub ft7: u128, + pub fs0: u128, + pub fs1: u128, + pub fa0: u128, + pub fa1: u128, + pub fa2: u128, + pub fa3: u128, + pub fa4: u128, + pub fa5: u128, + pub fa6: u128, + pub fa7: u128, + pub fs2: u128, + pub fs3: u128, + pub fs4: u128, + pub fs5: u128, + pub fs6: u128, + pub fs7: u128, + pub fs8: u128, + pub fs9: u128, + pub fs10: u128, + pub fs11: u128, + pub ft8: u128, + pub ft9: u128, + pub ft10: u128, + pub ft11: u128, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextRiscV64 { + // Integer registers + pub zero: u64, + pub ra: u64, + pub sp: u64, + pub gp: u64, + pub tp: u64, + pub t0: u64, + pub t1: u64, + pub t2: u64, + pub s0fp: u64, + pub s1: u64, + pub a0: u64, + pub a1: u64, + pub a2: u64, + pub a3: u64, + pub a4: u64, + pub a5: u64, + pub a6: u64, + pub a7: u64, + pub s2: u64, + pub s3: u64, + pub s4: u64, + pub s5: u64, + pub s6: u64, + pub s7: u64, + pub s8: u64, + pub s9: u64, + pub s10: u64, + pub s11: u64, + pub t3: u64, + pub t4: u64, + pub t5: u64, + pub t6: u64, + // Floating registers for F, D and Q Standard Extensions + pub ft0: u128, + pub ft1: u128, + pub ft2: u128, + pub ft3: u128, + pub ft4: u128, + pub ft5: u128, + pub ft6: u128, + pub ft7: u128, + pub fs0: u128, + pub fs1: u128, + pub fa0: u128, + pub fa1: u128, + pub fa2: u128, + pub fa3: u128, + pub fa4: u128, + pub fa5: u128, + pub fa6: u128, + pub fa7: u128, + pub fs2: u128, + pub fs3: u128, + pub fs4: u128, + pub fs5: u128, + pub fs6: u128, + pub fs7: u128, + pub fs8: u128, + pub fs9: u128, + pub fs10: u128, + pub fs11: u128, + pub ft8: u128, + pub ft9: u128, + pub ft10: u128, + pub ft11: u128, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextRiscV128 { + // Integer registers + pub zero: u128, + pub ra: u128, + pub sp: u128, + pub gp: u128, + pub tp: u128, + pub t0: u128, + pub t1: u128, + pub t2: u128, + pub s0fp: u128, + pub s1: u128, + pub a0: u128, + pub a1: u128, + pub a2: u128, + pub a3: u128, + pub a4: u128, + pub a5: u128, + pub a6: u128, + pub a7: u128, + pub s2: u128, + pub s3: u128, + pub s4: u128, + pub s5: u128, + pub s6: u128, + pub s7: u128, + pub s8: u128, + pub s9: u128, + pub s10: u128, + pub s11: u128, + pub t3: u128, + pub t4: u128, + pub t5: u128, + pub t6: u128, + // Floating registers for F, D and Q Standard Extensions + pub ft0: u128, + pub ft1: u128, + pub ft2: u128, + pub ft3: u128, + pub ft4: u128, + pub ft5: u128, + pub ft6: u128, + pub ft7: u128, + pub fs0: u128, + pub fs1: u128, + pub fa0: u128, + pub fa1: u128, + pub fa2: u128, + pub fa3: u128, + pub fa4: u128, + pub fa5: u128, + pub fa6: u128, + pub fa7: u128, + pub fs2: u128, + pub fs3: u128, + pub fs4: u128, + pub fs5: u128, + pub fs6: u128, + pub fs7: u128, + pub fs8: u128, + pub fs9: u128, + pub fs10: u128, + pub fs11: u128, + pub ft8: u128, + pub ft9: u128, + pub ft10: u128, + pub ft11: u128, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextIa32 { + // ExceptionData is additional data pushed on the stack by some types of IA-32 exceptions + pub exception_data: u32, + pub fx_save_state: FxSaveStateIA32, + pub dr0: u32, + pub dr1: u32, + pub dr2: u32, + pub dr3: u32, + pub dr6: u32, + pub dr7: u32, + pub cr0: u32, + // Reserved + pub cr1: u32, + pub cr2: u32, + pub cr3: u32, + pub cr4: u32, + pub eflags: u32, + pub ldtr: u32, + pub tr: u32, + pub gdtr: [u32; 2], + pub idtr: [u32; 2], + pub eip: u32, + pub gs: u32, + pub fs: u32, + pub es: u32, + pub ds: u32, + pub cs: u32, + pub ss: u32, + pub edi: u32, + pub esi: u32, + pub ebp: u32, + pub esp: u32, + pub ebx: u32, + pub edx: u32, + pub ecx: u32, + pub eax: u32, +} + +// FXSAVE_STATE - FP / MMX / XMM registers +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FxSaveStateIA32 { + pub fcw: u16, + pub fsw: u16, + pub ftw: u16, + pub opcode: u16, + pub eip: u32, + pub cs: u16, + pub reserved_1: u16, + pub data_offset: u32, + pub ds: u16, + pub reserved_2: [u8; 10], + pub st0mm0: [u8; 10], + pub reserved_3: [u8; 6], + pub st1mm1: [u8; 10], + pub reserved_4: [u8; 6], + pub st2mm2: [u8; 10], + pub reserved_5: [u8; 6], + pub st3mm3: [u8; 10], + pub reserved_6: [u8; 6], + pub st4mm4: [u8; 10], + pub reserved_7: [u8; 6], + pub st5mm5: [u8; 10], + pub reserved_8: [u8; 6], + pub st6mm6: [u8; 10], + pub reserved_9: [u8; 6], + pub st7mm7: [u8; 10], + pub reserved_10: [u8; 6], + pub xmm0: [u8; 16], + pub xmm1: [u8; 16], + pub xmm2: [u8; 16], + pub xmm3: [u8; 16], + pub xmm4: [u8; 16], + pub xmm5: [u8; 16], + pub xmm6: [u8; 16], + pub xmm7: [u8; 16], + pub reserved_11: [u8; 14 * 16], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextX64 { + // ExceptionData is additional data pushed on the stack by some types of x64 64-bit mode exceptions + pub exception_data: u64, + pub fx_save_state: FxSaveStateX64, + pub dr0: u64, + pub dr1: u64, + pub dr2: u64, + pub dr3: u64, + pub dr6: u64, + pub dr7: u64, + pub cr0: u64, + // Reserved + pub cr1: u64, + pub cr2: u64, + pub cr3: u64, + pub cr4: u64, + pub cr8: u64, + pub rflags: u64, + pub ldtr: u64, + pub tr: u64, + pub gdtr: [u64; 2], + pub idtr: [u64; 2], + pub rip: u64, + pub gs: u64, + pub fs: u64, + pub es: u64, + pub ds: u64, + pub cs: u64, + pub ss: u64, + pub rdi: u64, + pub rsi: u64, + pub rbp: u64, + pub rsp: u64, + pub rbx: u64, + pub rdx: u64, + pub rcx: u64, + pub rax: u64, + pub r8: u64, + pub r9: u64, + pub r10: u64, + pub r11: u64, + pub r12: u64, + pub r13: u64, + pub r14: u64, + pub r15: u64, +} + +// FXSAVE_STATE – FP / MMX / XMM registers +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FxSaveStateX64 { + pub fcw: u16, + pub fsw: u16, + pub ftw: u16, + pub opcode: u16, + pub rip: u64, + pub data_offset: u64, + pub reserved_1: [u8; 8], + pub st0mm0: [u8; 10], + pub reserved_2: [u8; 6], + pub st1mm1: [u8; 10], + pub reserved_3: [u8; 6], + pub st2mm2: [u8; 10], + pub reserved_4: [u8; 6], + pub st3mm3: [u8; 10], + pub reserved_5: [u8; 6], + pub st4mm4: [u8; 10], + pub reserved_6: [u8; 6], + pub st5mm5: [u8; 10], + pub reserved_7: [u8; 6], + pub st6mm6: [u8; 10], + pub reserved_8: [u8; 6], + pub st7mm7: [u8; 10], + pub reserved_9: [u8; 6], + pub xmm0: [u8; 16], + pub xmm1: [u8; 16], + pub xmm2: [u8; 16], + pub xmm3: [u8; 16], + pub xmm4: [u8; 16], + pub xmm5: [u8; 16], + pub xmm6: [u8; 16], + pub xmm7: [u8; 16], + pub reserved_11: [u8; 14 * 16], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextIpf { + pub reserved: u64, + pub r1: u64, + pub r2: u64, + pub r3: u64, + pub r4: u64, + pub r5: u64, + pub r6: u64, + pub r7: u64, + pub r8: u64, + pub r9: u64, + pub r10: u64, + pub r11: u64, + pub r12: u64, + pub r13: u64, + pub r14: u64, + pub r15: u64, + pub r16: u64, + pub r17: u64, + pub r18: u64, + pub r19: u64, + pub r20: u64, + pub r21: u64, + pub r22: u64, + pub r23: u64, + pub r24: u64, + pub r25: u64, + pub r26: u64, + pub r27: u64, + pub r28: u64, + pub r29: u64, + pub r30: u64, + pub r31: u64, + pub f2: [u64; 2], + pub f3: [u64; 2], + pub f4: [u64; 2], + pub f5: [u64; 2], + pub f6: [u64; 2], + pub f7: [u64; 2], + pub f8: [u64; 2], + pub f9: [u64; 2], + pub f10: [u64; 2], + pub f11: [u64; 2], + pub f12: [u64; 2], + pub f13: [u64; 2], + pub f14: [u64; 2], + pub f15: [u64; 2], + pub f16: [u64; 2], + pub f17: [u64; 2], + pub f18: [u64; 2], + pub f19: [u64; 2], + pub f20: [u64; 2], + pub f21: [u64; 2], + pub f22: [u64; 2], + pub f23: [u64; 2], + pub f24: [u64; 2], + pub f25: [u64; 2], + pub f26: [u64; 2], + pub f27: [u64; 2], + pub f28: [u64; 2], + pub f29: [u64; 2], + pub f30: [u64; 2], + pub f31: [u64; 2], + pub pr: u64, + pub b0: u64, + pub b1: u64, + pub b2: u64, + pub b3: u64, + pub b4: u64, + pub b5: u64, + pub b6: u64, + pub b7: u64, + // application registers + pub ar_rsc: u64, + pub ar_bsp: u64, + pub ar_bspstore: u64, + pub ar_rnat: u64, + pub ar_fcr: u64, + pub ar_eflag: u64, + pub ar_csd: u64, + pub ar_ssd: u64, + pub ar_cflg: u64, + pub ar_fsr: u64, + pub ar_fir: u64, + pub ar_fdr: u64, + pub ar_ccv: u64, + pub ar_unat: u64, + pub ar_fpsr: u64, + pub ar_pfs: u64, + pub ar_lc: u64, + pub ar_ec: u64, + // control registers + pub cr_dcr: u64, + pub cr_itm: u64, + pub cr_iva: u64, + pub cr_pta: u64, + pub cr_ipsr: u64, + pub cr_isr: u64, + pub cr_iip: u64, + pub cr_ifa: u64, + pub cr_itir: u64, + pub cr_iipa: u64, + pub cr_ifs: u64, + pub cr_iim: u64, + pub cr_iha: u64, + // debug registers + pub dbr0: u64, + pub dbr1: u64, + pub dbr2: u64, + pub dbr3: u64, + pub dbr4: u64, + pub dbr5: u64, + pub dbr6: u64, + pub dbr7: u64, + pub ibr0: u64, + pub ibr1: u64, + pub ibr2: u64, + pub ibr3: u64, + pub ibr4: u64, + pub ibr5: u64, + pub ibr6: u64, + pub ibr7: u64, + // virtual Registers + pub int_nat: u64, // nat bits for r1-r31 +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextArm { + pub r0: u32, + pub r1: u32, + pub r2: u32, + pub r3: u32, + pub r4: u32, + pub r5: u32, + pub r6: u32, + pub r7: u32, + pub r8: u32, + pub r9: u32, + pub r10: u32, + pub r11: u32, + pub r12: u32, + pub sp: u32, + pub lr: u32, + pub pc: u32, + pub cpsr: u32, + pub dfsr: u32, + pub dfar: u32, + pub ifsr: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemContextAArch64 { + // General Purpose Registers + pub x0: u64, + pub x1: u64, + pub x2: u64, + pub x3: u64, + pub x4: u64, + pub x5: u64, + pub x6: u64, + pub x7: u64, + pub x8: u64, + pub x9: u64, + pub x10: u64, + pub x11: u64, + pub x12: u64, + pub x13: u64, + pub x14: u64, + pub x15: u64, + pub x16: u64, + pub x17: u64, + pub x18: u64, + pub x19: u64, + pub x20: u64, + pub x21: u64, + pub x22: u64, + pub x23: u64, + pub x24: u64, + pub x25: u64, + pub x26: u64, + pub x27: u64, + pub x28: u64, + pub fp: u64, // x29 - Frame Pointer + pub lr: u64, // x30 - Link Register + pub sp: u64, // x31 - Stack Pointer + // FP/SIMD Registers + pub v0: [u64; 2], + pub v1: [u64; 2], + pub v2: [u64; 2], + pub v3: [u64; 2], + pub v4: [u64; 2], + pub v5: [u64; 2], + pub v6: [u64; 2], + pub v7: [u64; 2], + pub v8: [u64; 2], + pub v9: [u64; 2], + pub v10: [u64; 2], + pub v11: [u64; 2], + pub v12: [u64; 2], + pub v13: [u64; 2], + pub v14: [u64; 2], + pub v15: [u64; 2], + pub v16: [u64; 2], + pub v17: [u64; 2], + pub v18: [u64; 2], + pub v19: [u64; 2], + pub v20: [u64; 2], + pub v21: [u64; 2], + pub v22: [u64; 2], + pub v23: [u64; 2], + pub v24: [u64; 2], + pub v25: [u64; 2], + pub v26: [u64; 2], + pub v27: [u64; 2], + pub v28: [u64; 2], + pub v29: [u64; 2], + pub v30: [u64; 2], + pub v31: [u64; 2], + pub elr: u64, // Exception Link Register + pub spsr: u64, // Saved Processor Status Register + pub fpsr: u64, // Floating Point Status Register + pub esr: u64, // Exception Syndrome Register + pub far: u64, // Fault Address Register +} + +pub type ExceptionType = isize; + +// EBC Exception types +pub const EXCEPT_EBC_UNDEFINED: ExceptionType = 0; +pub const EXCEPT_EBC_DIVIDE_ERROR: ExceptionType = 1; +pub const EXCEPT_EBC_DEBUG: ExceptionType = 2; +pub const EXCEPT_EBC_BREAKPOINT: ExceptionType = 3; +pub const EXCEPT_EBC_OVERFLOW: ExceptionType = 4; +pub const EXCEPT_EBC_INVALID_OPCODE: ExceptionType = 5; +pub const EXCEPT_EBC_STACK_FAULT: ExceptionType = 6; +pub const EXCEPT_EBC_ALIGNMENT_CHECK: ExceptionType = 7; +pub const EXCEPT_EBC_INSTRUCTION_ENCODING: ExceptionType = 8; +pub const EXCEPT_EBC_BAD_BREAK: ExceptionType = 9; +pub const EXCEPT_EBC_SINGLE_STEP: ExceptionType = 10; + +// IA-32 Exception types +pub const EXCEPT_IA32_DIVIDE_ERROR: ExceptionType = 0; +pub const EXCEPT_IA32_DEBUG: ExceptionType = 1; +pub const EXCEPT_IA32_NMI: ExceptionType = 2; +pub const EXCEPT_IA32_BREAKPOINT: ExceptionType = 3; +pub const EXCEPT_IA32_OVERFLOW: ExceptionType = 4; +pub const EXCEPT_IA32_BOUND: ExceptionType = 5; +pub const EXCEPT_IA32_INVALID_OPCODE: ExceptionType = 6; +pub const EXCEPT_IA32_DOUBLE_FAULT: ExceptionType = 8; +pub const EXCEPT_IA32_INVALID_TSS: ExceptionType = 10; +pub const EXCEPT_IA32_SEG_NOT_PRESENT: ExceptionType = 11; +pub const EXCEPT_IA32_STACK_FAULT: ExceptionType = 12; +pub const EXCEPT_IA32_GP_FAULT: ExceptionType = 13; +pub const EXCEPT_IA32_PAGE_FAULT: ExceptionType = 14; +pub const EXCEPT_IA32_FP_ERROR: ExceptionType = 16; +pub const EXCEPT_IA32_ALIGNMENT_CHECK: ExceptionType = 17; +pub const EXCEPT_IA32_MACHINE_CHECK: ExceptionType = 18; +pub const EXCEPT_IA32_SIMD: ExceptionType = 19; + +// X64 Exception types +pub const EXCEPT_X64_DIVIDE_ERROR: ExceptionType = 0; +pub const EXCEPT_X64_DEBUG: ExceptionType = 1; +pub const EXCEPT_X64_NMI: ExceptionType = 2; +pub const EXCEPT_X64_BREAKPOINT: ExceptionType = 3; +pub const EXCEPT_X64_OVERFLOW: ExceptionType = 4; +pub const EXCEPT_X64_BOUND: ExceptionType = 5; +pub const EXCEPT_X64_INVALID_OPCODE: ExceptionType = 6; +pub const EXCEPT_X64_DOUBLE_FAULT: ExceptionType = 8; +pub const EXCEPT_X64_INVALID_TSS: ExceptionType = 10; +pub const EXCEPT_X64_SEG_NOT_PRESENT: ExceptionType = 11; +pub const EXCEPT_X64_STACK_FAULT: ExceptionType = 12; +pub const EXCEPT_X64_GP_FAULT: ExceptionType = 13; +pub const EXCEPT_X64_PAGE_FAULT: ExceptionType = 14; +pub const EXCEPT_X64_FP_ERROR: ExceptionType = 16; +pub const EXCEPT_X64_ALIGNMENT_CHECK: ExceptionType = 17; +pub const EXCEPT_X64_MACHINE_CHECK: ExceptionType = 18; +pub const EXCEPT_X64_SIMD: ExceptionType = 19; + +// Itanium Processor Family Exception types +pub const EXCEPT_IPF_VHTP_TRANSLATION: ExceptionType = 0; +pub const EXCEPT_IPF_INSTRUCTION_TLB: ExceptionType = 1; +pub const EXCEPT_IPF_DATA_TLB: ExceptionType = 2; +pub const EXCEPT_IPF_ALT_INSTRUCTION_TLB: ExceptionType = 3; +pub const EXCEPT_IPF_ALT_DATA_TLB: ExceptionType = 4; +pub const EXCEPT_IPF_DATA_NESTED_TLB: ExceptionType = 5; +pub const EXCEPT_IPF_INSTRUCTION_KEY_MISSED: ExceptionType = 6; +pub const EXCEPT_IPF_DATA_KEY_MISSED: ExceptionType = 7; +pub const EXCEPT_IPF_DIRTY_BIT: ExceptionType = 8; +pub const EXCEPT_IPF_INSTRUCTION_ACCESS_BIT: ExceptionType = 9; +pub const EXCEPT_IPF_DATA_ACCESS_BIT: ExceptionType = 10; +pub const EXCEPT_IPF_BREAKPOINT: ExceptionType = 11; +pub const EXCEPT_IPF_EXTERNAL_INTERRUPT: ExceptionType = 12; +// 13 - 19 reserved +pub const EXCEPT_IPF_PAGE_NOT_PRESENT: ExceptionType = 20; +pub const EXCEPT_IPF_KEY_PERMISSION: ExceptionType = 21; +pub const EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS: ExceptionType = 22; +pub const EXCEPT_IPF_DATA_ACCESS_RIGHTS: ExceptionType = 23; +pub const EXCEPT_IPF_GENERAL_EXCEPTION: ExceptionType = 24; +pub const EXCEPT_IPF_DISABLED_FP_REGISTER: ExceptionType = 25; +pub const EXCEPT_IPF_NAT_CONSUMPTION: ExceptionType = 26; +pub const EXCEPT_IPF_SPECULATION: ExceptionType = 27; +// 28 reserved +pub const EXCEPT_IPF_DEBUG: ExceptionType = 29; +pub const EXCEPT_IPF_UNALIGNED_REFERENCE: ExceptionType = 30; +pub const EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE: ExceptionType = 31; +pub const EXCEPT_IPF_FP_FAULT: ExceptionType = 32; +pub const EXCEPT_IPF_FP_TRAP: ExceptionType = 33; +pub const EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP: ExceptionType = 34; +pub const EXCEPT_IPF_TAKEN_BRANCH: ExceptionType = 35; +pub const EXCEPT_IPF_SINGLE_STEP: ExceptionType = 36; +// 37 - 44 reserved +pub const EXCEPT_IPF_IA32_EXCEPTION: ExceptionType = 45; +pub const EXCEPT_IPF_IA32_INTERCEPT: ExceptionType = 46; +pub const EXCEPT_IPF_IA32_INTERRUPT: ExceptionType = 47; + +// ARM processor exception types +pub const EXCEPT_ARM_RESET: ExceptionType = 0; +pub const EXCEPT_ARM_UNDEFINED_INSTRUCTION: ExceptionType = 1; +pub const EXCEPT_ARM_SOFTWARE_INTERRUPT: ExceptionType = 2; +pub const EXCEPT_ARM_PREFETCH_ABORT: ExceptionType = 3; +pub const EXCEPT_ARM_DATA_ABORT: ExceptionType = 4; +pub const EXCEPT_ARM_RESERVED: ExceptionType = 5; +pub const EXCEPT_ARM_IRQ: ExceptionType = 6; +pub const EXCEPT_ARM_FIQ: ExceptionType = 7; +pub const MAX_ARM_EXCEPTION: ExceptionType = EXCEPT_ARM_FIQ; + +// AARCH64 processor exception types. +pub const EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS: ExceptionType = 0; +pub const EXCEPT_AARCH64_IRQ: ExceptionType = 1; +pub const EXCEPT_AARCH64_FIQ: ExceptionType = 2; +pub const EXCEPT_AARCH64_SERROR: ExceptionType = 3; +pub const MAX_AARCH64_EXCEPTION: ExceptionType = EXCEPT_AARCH64_SERROR; + +// RISC-V processor exception types. +pub const EXCEPT_RISCV_INST_MISALIGNED: ExceptionType = 0; +pub const EXCEPT_RISCV_INST_ACCESS_FAULT: ExceptionType = 1; +pub const EXCEPT_RISCV_ILLEGAL_INST: ExceptionType = 2; +pub const EXCEPT_RISCV_BREAKPOINT: ExceptionType = 3; +pub const EXCEPT_RISCV_LOAD_ADDRESS_MISALIGNED: ExceptionType = 4; +pub const EXCEPT_RISCV_LOAD_ACCESS_FAULT: ExceptionType = 5; +pub const EXCEPT_RISCV_STORE_AMO_ADDRESS_MISALIGNED: ExceptionType = 6; +pub const EXCEPT_RISCV_STORE_AMO_ACCESS_FAULT: ExceptionType = 7; +pub const EXCEPT_RISCV_ENV_CALL_FROM_UMODE: ExceptionType = 8; +pub const EXCEPT_RISCV_ENV_CALL_FROM_SMODE: ExceptionType = 9; +pub const EXCEPT_RISCV_ENV_CALL_FROM_MMODE: ExceptionType = 11; +pub const EXCEPT_RISCV_INST_PAGE_FAULT: ExceptionType = 12; +pub const EXCEPT_RISCV_LOAD_PAGE_FAULT: ExceptionType = 13; +pub const EXCEPT_RISCV_STORE_AMO_PAGE_FAULT: ExceptionType = 15; + +// RISC-V processor interrupt types. +pub const EXCEPT_RISCV_SUPERVISOR_SOFTWARE_INT: ExceptionType = 1; +pub const EXCEPT_RISCV_MACHINE_SOFTWARE_INT: ExceptionType = 3; +pub const EXCEPT_RISCV_SUPERVISOR_TIMER_INT: ExceptionType = 5; +pub const EXCEPT_RISCV_MACHINE_TIMER_INT: ExceptionType = 7; +pub const EXCEPT_RISCV_SUPERVISOR_EXTERNAL_INT: ExceptionType = 9; +pub const EXCEPT_RISCV_MACHINE_EXTERNAL_INT: ExceptionType = 11; + +pub type GetMaximumProcessorIndex = eficall! {fn( + *mut Protocol, + *mut usize, +) -> crate::base::Status}; + +pub type PeriodicCallback = eficall! {fn(SystemContext)}; + +pub type RegisterPeriodicCallback = eficall! {fn( + *mut Protocol, + usize, + Option, +) -> crate::base::Status}; + +pub type ExceptionCallback = eficall! {fn(ExceptionType, SystemContext)}; + +pub type RegisterExceptionCallback = eficall! {fn( + *mut Protocol, + usize, + Option, + ExceptionType, +) -> crate::base::Status}; + +pub type InvalidateInstructionCache = eficall! {fn( + *mut Protocol, + usize, + *mut core::ffi::c_void, + u64, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub isa: InstructionSetArchitecture, + pub get_maximum_processor_index: GetMaximumProcessorIndex, + pub register_periodic_callback: RegisterPeriodicCallback, + pub register_exception_callback: RegisterExceptionCallback, + pub invalidate_instruction_cache: InvalidateInstructionCache, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/debugport.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debugport.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/debugport.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/debugport.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +//! Debug Port Protocol +//! +//! It provides the communication link between the debug agent and the remote host. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeba4e8d2, + 0x3858, + 0x41ec, + 0xa2, + 0x81, + &[0x26, 0x47, 0xba, 0x96, 0x60, 0xd0], +); + +pub type Reset = eficall! {fn( + *mut Protocol, +) -> *mut crate::base::Status}; + +pub type Write = eficall! {fn( + *mut Protocol, + u32, + *mut usize, + *mut core::ffi::c_void +) -> *mut crate::base::Status}; + +pub type Read = eficall! {fn( + *mut Protocol, + u32, + *mut usize, + *mut core::ffi::c_void +) -> *mut crate::base::Status}; + +pub type Poll = eficall! {fn( + *mut Protocol, +) -> *mut crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub reset: Reset, + pub write: Write, + pub read: Read, + pub poll: Poll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/decompress.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/decompress.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/decompress.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/decompress.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +//! Decompress Protocol +//! +//! The decompress protocol provides a decompression service that allows a compressed source +//! buffer in memory to be decompressed into a destination buffer in memory. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xd8117cfe, + 0x94a6, + 0x11d4, + 0x9a, + 0x3a, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub type ProtocolGetInfo = eficall! {fn( + *mut Protocol, + *mut core::ffi::c_void, + u32, + *mut u32, + *mut u32, +) -> crate::base::Status}; + +pub type ProtocolDecompress = eficall! {fn( + *mut Protocol, + *mut core::ffi::c_void, + u32, + *mut core::ffi::c_void, + u32, + *mut core::ffi::c_void, + u32, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_info: ProtocolGetInfo, + pub decompress: ProtocolDecompress, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,82 @@ +//! Device Path Protocol +//! +//! The device path protocol defines how to obtain generic path/location information +//! concerning the phisycal or logical device. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x09576e91, + 0x6d3f, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub const TYPE_HARDWARE: u8 = 0x01; +pub const TYPE_ACPI: u8 = 0x02; +pub const TYPE_MESSAGING: u8 = 0x03; +pub const TYPE_MEDIA: u8 = 0x04; +pub const TYPE_BIOS: u8 = 0x05; +pub const TYPE_END: u8 = 0x7f; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Protocol { + pub r#type: u8, + pub sub_type: u8, + pub length: [u8; 2], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct End { + pub header: Protocol, +} + +impl End { + pub const SUBTYPE_INSTANCE: u8 = 0x01; + pub const SUBTYPE_ENTIRE: u8 = 0xff; +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Hardware { + pub header: Protocol, +} + +impl Hardware { + pub const SUBTYPE_PCI: u8 = 0x01; + pub const SUBTYPE_PCCARD: u8 = 0x02; + pub const SUBTYPE_MMAP: u8 = 0x03; + pub const SUBTYPE_VENDOR: u8 = 0x04; + pub const SUBTYPE_CONTROLLER: u8 = 0x05; + pub const SUBTYPE_BMC: u8 = 0x06; +} + +#[repr(C, packed)] +#[derive(Clone, Copy, Debug)] +pub struct HardDriveMedia { + pub header: Protocol, + pub partition_number: u32, + pub partition_start: u64, + pub partition_size: u64, + pub partition_signature: [u8; 16], + pub partition_format: u8, + pub signature_type: u8, +} + +pub struct Media { + pub header: Protocol, +} + +impl Media { + pub const SUBTYPE_HARDDRIVE: u8 = 0x01; + pub const SUBTYPE_CDROM: u8 = 0x02; + pub const SUBTYPE_VENDOR: u8 = 0x03; + pub const SUBTYPE_FILE_PATH: u8 = 0x04; + pub const SUBTYPE_MEDIA_PROTOCOL: u8 = 0x05; + pub const SUBTYPE_PIWG_FIRMWARE_FILE: u8 = 0x06; + pub const SUBTYPE_PIWG_FIRMWARE_VOLUME: u8 = 0x07; + pub const SUBTYPE_RELATIVE_OFFSET_RANGE: u8 = 0x08; + pub const SUBTYPE_RAM_DISK: u8 = 0x09; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_from_text.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_from_text.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_from_text.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_from_text.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +//! Device Path From Text Protocol +//! +//! Convert text to device paths and device nodes. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x5c99a21, + 0xc70f, + 0x4ad2, + 0x8a, + 0x5f, + &[0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e], +); + +pub type DevicePathFromTextNode = eficall! {fn( + *const crate::base::Char16, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type DevicePathFromTextPath = eficall! {fn( + *const crate::base::Char16, +) -> *mut crate::protocols::device_path::Protocol}; + +#[repr(C)] +pub struct Protocol { + pub convert_text_to_device_node: DevicePathFromTextNode, + pub convert_text_to_device_path: DevicePathFromTextPath, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_to_text.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_to_text.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_to_text.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_to_text.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +//! Device Path to Text Protocol +//! +//! Convert device nodes and paths to text. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x8b843e20, + 0x8132, + 0x4852, + 0x90, + 0xcc, + &[0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c], +); + +pub type DevicePathToTextNode = eficall! {fn( + *mut crate::protocols::device_path::Protocol, + crate::base::Boolean, + crate::base::Boolean, +) -> *mut crate::base::Char16}; + +pub type DevicePathToTextPath = eficall! {fn( + *mut crate::protocols::device_path::Protocol, + crate::base::Boolean, + crate::base::Boolean, +) -> *mut crate::base::Char16}; + +#[repr(C)] +pub struct Protocol { + pub convert_device_node_to_text: DevicePathToTextNode, + pub convert_device_path_to_text: DevicePathToTextPath, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_utilities.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_utilities.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_utilities.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/device_path_utilities.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +//! Device Path Utilities Protocol +//! +//! The device-path utilities protocol provides common utilities for creating and manipulating +//! device paths and device nodes. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x379be4e, + 0xd706, + 0x437d, + 0xb0, + 0x37, + &[0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4], +); + +pub type ProtocolGetDevicePathSize = eficall! {fn( + *const crate::protocols::device_path::Protocol, +) -> usize}; + +pub type ProtocolDuplicateDevicePath = eficall! {fn( + *const crate::protocols::device_path::Protocol, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type ProtocolAppendDevicePath = eficall! {fn( + *const crate::protocols::device_path::Protocol, + *const crate::protocols::device_path::Protocol, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type ProtocolAppendDeviceNode = eficall! {fn( + *const crate::protocols::device_path::Protocol, + *const crate::protocols::device_path::Protocol, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type ProtocolAppendDevicePathInstance = eficall! {fn( + *const crate::protocols::device_path::Protocol, + *const crate::protocols::device_path::Protocol, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type ProtocolGetNextDevicePathInstance = eficall! {fn( + *mut *mut crate::protocols::device_path::Protocol, + *mut usize, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type ProtocolIsDevicePathMultiInstance = eficall! {fn( + *const crate::protocols::device_path::Protocol, +) -> crate::base::Boolean}; + +pub type ProtocolCreateDeviceNode = eficall! {fn( + u8, + u8, + u16, +) -> *mut crate::protocols::device_path::Protocol}; + +#[repr(C)] +pub struct Protocol { + pub get_device_path_size: ProtocolGetDevicePathSize, + pub duplicate_device_path: ProtocolDuplicateDevicePath, + pub append_device_path: ProtocolAppendDevicePath, + pub append_device_node: ProtocolAppendDeviceNode, + pub append_device_path_instance: ProtocolAppendDevicePathInstance, + pub get_next_device_path_instance: ProtocolGetNextDevicePathInstance, + pub is_device_path_multi_instance: ProtocolIsDevicePathMultiInstance, + pub create_device_node: ProtocolCreateDeviceNode, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +//! Disk I/O Protocol +//! +//! Abstracts block accesses of the Block I/O protocol to a more general offset-length protocol. +//! Firmware is responsible for adding this protocol to any Block I/O interface that appears +//! in the system that does not already have a Disk I/O protocol. File systems and other disk +//! access code utilize the Disk I/O protocol. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xce345171, + 0xba0b, + 0x11d2, + 0x8e, + 0x4f, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub const REVISION: u64 = 0x0000000000010000u64; + +pub type ProtocolReadDisk = eficall! {fn( + *mut Protocol, + u32, + u64, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolWriteDisk = eficall! {fn( + *mut Protocol, + u32, + u64, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub read_disk: ProtocolReadDisk, + pub write_disk: ProtocolWriteDisk, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io2.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/disk_io2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,58 @@ +//! Disk I/O 2 Protocol +//! +//! Extends the Disk I/O protocol interface to enable non-blocking / +//! asynchronous byte-oriented disk operation. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x151c8eae, + 0x7f2c, + 0x472c, + 0x9e, + 0x54, + &[0x98, 0x28, 0x19, 0x4f, 0x6a, 0x88], +); + +pub const REVISION: u64 = 0x0000000000020000u64; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Token { + event: crate::base::Event, + transaction_status: crate::base::Status, +} + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolReadDiskEx = eficall! {fn( + *mut Protocol, + u32, + u64, + *mut Token, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolWriteDiskEx = eficall! {fn( + *mut Protocol, + u32, + u64, + *mut Token, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolFlushDiskEx = eficall! {fn( + *mut Protocol, + *mut Token, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub cancel: ProtocolCancel, + pub read_disk_ex: ProtocolReadDiskEx, + pub write_disk_ex: ProtocolWriteDiskEx, + pub flush_disk_ex: ProtocolFlushDiskEx, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_binding.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_binding.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_binding.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_binding.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +//! Driver Binding Protocol +//! +//! Provides the services required to determine if a driver supports a given controller. If +//! a controller is supported, then it also provides routines to start and stop the controller. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x18a031ab, + 0xb443, + 0x4d1a, + 0xa5, + 0xc0, + &[0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71], +); + +pub type ProtocolSupported = eficall! {fn( + *mut Protocol, + crate::base::Handle, + *mut crate::protocols::device_path::Protocol, +) -> crate::base::Status}; + +pub type ProtocolStart = eficall! {fn( + *mut Protocol, + crate::base::Handle, + *mut crate::protocols::device_path::Protocol, +) -> crate::base::Status}; + +pub type ProtocolStop = eficall! {fn( + *mut Protocol, + crate::base::Handle, + usize, + *mut crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub supported: ProtocolSupported, + pub start: ProtocolStart, + pub stop: ProtocolStop, + pub version: u32, + pub image_handle: crate::base::Handle, + pub driver_binding_handle: crate::base::Handle, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_diagnostics2.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_diagnostics2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_diagnostics2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_diagnostics2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +//! Driver Diagnostics Protocol +//! +//! Defined in UEFI Specification, Section 11.4 +//! Used to perform diagnostics on a controller that a UEFI driver is managing. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x4d330321, + 0x025f, + 0x4aac, + 0x90, + 0xd8, + &[0x5e, 0xd9, 0x00, 0x17, 0x3b, 0x63], +); + +pub type Type = u32; + +pub const TYPE_STANDARD: Type = 0; +pub const TYPE_EXTENDED: Type = 1; +pub const TYPE_MANUFACTURING: Type = 2; +pub const TYPE_CANCEL: Type = 3; +pub const TYPE_MAXIMUM: Type = 4; + +pub type RunDiagnostics = eficall! {fn( + *mut Protocol, + crate::base::Handle, + crate::base::Handle, + Type, + *mut crate::base::Char8, + *mut *mut crate::base::Guid, + *mut usize, + *mut *mut crate::base::Char16, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub run_diagnostics: RunDiagnostics, + pub supported_languages: *mut crate::base::Char8, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_family_override.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_family_override.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/driver_family_override.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/driver_family_override.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +//! Driver Family Override Protocol +//! +//! When installed, the Driver Family Override Protocol informs the UEFI Boot +//! Service `ConnectController()` that this driver is higher priority than the +//! list of drivers returned by the Bus Specific Driver Override Protocol. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xb1ee129e, + 0xda36, + 0x4181, + 0x91, + 0xf8, + &[0x04, 0xa4, 0x92, 0x37, 0x66, 0xa7], +); + +pub type ProtocolGetVersion = eficall! {fn( + *mut Protocol, +) -> u32}; + +#[repr(C)] +pub struct Protocol { + pub get_version: ProtocolGetVersion, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/file.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/file.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +//! File Protocol +//! +//! Provides an interface to interact with both files and directories. This protocol is typically +//! obtained via an EFI_SIMPLE_FILE_SYSTEM protocol or via another EFI_FILE_PROTOCOL. + +pub const REVISION: u64 = 0x0000_0000_0001_0000u64; +pub const REVISION2: u64 = 0x0000_0000_0002_0000u64; +pub const LATEST_REVISION: u64 = REVISION2; + +pub const MODE_READ: u64 = 0x0000000000000001u64; +pub const MODE_WRITE: u64 = 0x0000000000000002u64; +pub const MODE_CREATE: u64 = 0x8000000000000000u64; + +pub const READ_ONLY: u64 = 0x0000000000000001u64; +pub const HIDDEN: u64 = 0x0000000000000002u64; +pub const SYSTEM: u64 = 0x0000000000000004u64; +pub const RESERVED: u64 = 0x0000000000000008u64; +pub const DIRECTORY: u64 = 0x0000000000000010u64; +pub const ARCHIVE: u64 = 0x0000000000000020u64; +pub const VALID_ATTR: u64 = 0x0000000000000037u64; + +pub const INFO_ID: crate::base::Guid = crate::base::Guid::from_fields( + 0x09576e92, + 0x6d3f, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); +pub const SYSTEM_INFO_ID: crate::base::Guid = crate::base::Guid::from_fields( + 0x09576e93, + 0x6d3f, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); +pub const SYSTEM_VOLUME_LABEL_ID: crate::base::Guid = crate::base::Guid::from_fields( + 0xdb47d7d3, + 0xfe81, + 0x11d3, + 0x9a, + 0x35, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IoToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub buffer_size: usize, + pub buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Info { + pub size: u64, + pub file_size: u64, + pub physical_size: u64, + pub create_time: crate::system::Time, + pub last_access_time: crate::system::Time, + pub modification_time: crate::system::Time, + pub attribute: u64, + pub file_name: [crate::base::Char16; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemInfo { + pub size: u64, + pub read_only: crate::base::Boolean, + pub volume_size: u64, + pub free_space: u64, + pub block_size: u32, + pub volume_label: [crate::base::Char16; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct SystemVolumeLabel { + pub volume_label: [crate::base::Char16; N], +} + +pub type ProtocolOpen = eficall! {fn( + *mut Protocol, + *mut *mut Protocol, + *mut crate::base::Char16, + u64, + u64, +) -> crate::base::Status}; + +pub type ProtocolClose = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolDelete = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolRead = eficall! {fn( + *mut Protocol, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolWrite = eficall! {fn( + *mut Protocol, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolGetPosition = eficall! {fn( + *mut Protocol, + *mut u64, +) -> crate::base::Status}; + +pub type ProtocolSetPosition = eficall! {fn( + *mut Protocol, + u64, +) -> crate::base::Status}; + +pub type ProtocolGetInfo = eficall! {fn( + *mut Protocol, + *mut crate::base::Guid, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolSetInfo = eficall! {fn( + *mut Protocol, + *mut crate::base::Guid, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolFlush = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolOpenEx = eficall! {fn( + *mut Protocol, + *mut *mut Protocol, + *mut crate::base::Char16, + u64, + u64, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolReadEx = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolWriteEx = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolFlushEx = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub open: ProtocolOpen, + pub close: ProtocolClose, + pub delete: ProtocolDelete, + pub read: ProtocolRead, + pub write: ProtocolWrite, + pub get_position: ProtocolGetPosition, + pub set_position: ProtocolSetPosition, + pub get_info: ProtocolGetInfo, + pub set_info: ProtocolSetInfo, + pub flush: ProtocolFlush, + pub open_ex: ProtocolOpenEx, + pub read_ex: ProtocolReadEx, + pub write_ex: ProtocolWriteEx, + pub flush_ex: ProtocolFlushEx, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/graphics_output.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/graphics_output.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/graphics_output.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/graphics_output.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,103 @@ +//! Graphics Output Protocol +//! +//! Provides means to configure graphics hardware and get access to +//! framebuffers. Replaces the old UGA interface from EFI with a +//! VGA-independent API. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x9042a9de, + 0x23dc, + 0x4a38, + 0x96, + 0xfb, + &[0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct PixelBitmask { + pub red_mask: u32, + pub green_mask: u32, + pub blue_mask: u32, + pub reserved_mask: u32, +} + +pub type GraphicsPixelFormat = u32; + +pub const PIXEL_RED_GREEN_BLUE_RESERVED_8_BIT_PER_COLOR: GraphicsPixelFormat = 0x00000000; +pub const PIXEL_BLUE_GREEN_RED_RESERVED_8_BIT_PER_COLOR: GraphicsPixelFormat = 0x00000001; +pub const PIXEL_BIT_MASK: GraphicsPixelFormat = 0x00000002; +pub const PIXEL_BLT_ONLY: GraphicsPixelFormat = 0x00000003; +pub const PIXEL_FORMAT_MAX: GraphicsPixelFormat = 0x00000004; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ModeInformation { + pub version: u32, + pub horizontal_resolution: u32, + pub vertical_resolution: u32, + pub pixel_format: GraphicsPixelFormat, + pub pixel_information: PixelBitmask, + pub pixels_per_scan_line: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Mode { + pub max_mode: u32, + pub mode: u32, + pub info: *mut ModeInformation, + pub size_of_info: usize, + pub frame_buffer_base: crate::base::PhysicalAddress, + pub frame_buffer_size: usize, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct BltPixel { + pub blue: u8, + pub green: u8, + pub red: u8, + pub reserved: u8, +} + +pub type BltOperation = u32; + +pub const BLT_VIDEO_FILL: BltOperation = 0x00000000; +pub const BLT_VIDEO_TO_BLT_BUFFER: BltOperation = 0x00000001; +pub const BLT_BUFFER_TO_VIDEO: BltOperation = 0x00000002; +pub const BLT_VIDEO_TO_VIDEO: BltOperation = 0x00000003; +pub const BLT_OPERATION_MAX: BltOperation = 0x00000004; + +pub type ProtocolQueryMode = eficall! {fn( + *mut Protocol, + u32, + *mut usize, + *mut *mut ModeInformation, +) -> crate::base::Status}; + +pub type ProtocolSetMode = eficall! {fn( + *mut Protocol, + u32, +) -> crate::base::Status}; + +pub type ProtocolBlt = eficall! {fn( + *mut Protocol, + *mut BltPixel, + BltOperation, + usize, + usize, + usize, + usize, + usize, + usize, + usize, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub query_mode: ProtocolQueryMode, + pub set_mode: ProtocolSetMode, + pub blt: ProtocolBlt, + pub mode: *mut Mode, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_database.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_database.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_database.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_database.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,299 @@ +//! Human Interface Infrastructure (HII) Protocol +//! +//! Database manager for HII-related data structures. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xef9fc172, + 0xa1b2, + 0x4693, + 0xb3, + 0x27, + &[0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42], +); + +pub const SET_KEYBOARD_LAYOUT_EVENT_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x14982a4f, + 0xb0ed, + 0x45b8, + 0xa8, + 0x11, + &[0x5a, 0x7a, 0x9b, 0xc2, 0x32, 0xdf], +); + +pub type ProtocolNewPackageList = eficall! {fn( + *const Protocol, + *const crate::hii::PackageListHeader, + crate::base::Handle, + *mut crate::hii::Handle, +) -> crate::base::Status}; + +pub type ProtocolRemovePackageList = eficall! {fn( + *const Protocol, + crate::hii::Handle, +) -> crate::base::Status}; + +pub type ProtocolUpdatePackageList = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *const crate::hii::PackageListHeader, +) -> crate::base::Status}; + +pub type ProtocolListPackageLists = eficall! {fn( + *const Protocol, + u8, + *const crate::base::Guid, + *mut usize, + *mut crate::hii::Handle, +) -> crate::base::Status}; + +pub type ProtocolExportPackageLists = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *mut usize, + *mut crate::hii::PackageListHeader, +) -> crate::base::Status}; + +pub type ProtocolRegisterPackageNotify = eficall! {fn( + *const Protocol, + u8, + *const crate::base::Guid, + Notify, + NotifyType, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type ProtocolUnregisterPackageNotify = eficall! {fn( + *const Protocol, + crate::base::Handle, +) -> crate::base::Status}; + +pub type ProtocolFindKeyboardLayouts = eficall! {fn( + *const Protocol, + *mut u16, + *mut crate::base::Guid, +) -> crate::base::Status}; + +pub type ProtocolGetKeyboardLayout = eficall! {fn( + *const Protocol, + *const crate::base::Guid, + *mut u16, + *mut KeyboardLayout, +) -> crate::base::Status}; + +pub type ProtocolSetKeyboardLayout = eficall! {fn( + *const Protocol, + *mut crate::base::Guid, +) -> crate::base::Status}; + +pub type ProtocolGetPackageListHandle = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *mut crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub new_package_list: ProtocolNewPackageList, + pub remove_package_list: ProtocolRemovePackageList, + pub update_package_list: ProtocolUpdatePackageList, + pub list_package_lists: ProtocolListPackageLists, + pub export_package_lists: ProtocolExportPackageLists, + pub register_package_notify: ProtocolRegisterPackageNotify, + pub unregister_package_notify: ProtocolUnregisterPackageNotify, + pub find_keyboard_layouts: ProtocolFindKeyboardLayouts, + pub get_keyboard_layout: ProtocolGetKeyboardLayout, + pub set_keyboard_layout: ProtocolSetKeyboardLayout, + pub get_package_list_handle: ProtocolGetPackageListHandle, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct KeyboardLayout { + pub layout_length: u16, + pub guid: crate::base::Guid, + pub layout_descriptor_string_offset: u32, + pub descriptor_count: u8, + pub descriptors: [KeyDescriptor; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct KeyDescriptor { + pub key: Key, + pub unicode: crate::base::Char16, + pub shifted_unicode: crate::base::Char16, + pub alt_gr_unicode: crate::base::Char16, + pub shifted_alt_gr_unicode: crate::base::Char16, + pub modifier: u16, + pub affected_attribute: u16, +} + +pub const AFFECTED_BY_STANDARD_SHIFT: u16 = 0x0001; +pub const AFFECTED_BY_CAPS_LOCK: u16 = 0x0002; +pub const AFFECTED_BY_NUM_LOCK: u16 = 0x0004; + +pub type Key = u32; + +pub const EFI_KEY_LCTRL: Key = 0x00000000; +pub const EFI_KEY_A0: Key = 0x00000001; +pub const EFI_KEY_LALT: Key = 0x00000002; +pub const EFI_KEY_SPACE_BAR: Key = 0x00000003; +pub const EFI_KEY_A2: Key = 0x00000004; +pub const EFI_KEY_A3: Key = 0x00000005; +pub const EFI_KEY_A4: Key = 0x00000006; +pub const EFI_KEY_RCTRL: Key = 0x00000007; +pub const EFI_KEY_LEFT_ARROW: Key = 0x00000008; +pub const EFI_KEY_DOWN_ARROW: Key = 0x00000009; +pub const EFI_KEY_RIGHT_ARROW: Key = 0x0000000a; +pub const EFI_KEY_ZERO: Key = 0x0000000b; +pub const EFI_KEY_PERIOD: Key = 0x0000000c; +pub const EFI_KEY_ENTER: Key = 0x0000000d; +pub const EFI_KEY_LSHIFT: Key = 0x0000000e; +pub const EFI_KEY_B0: Key = 0x0000000f; +pub const EFI_KEY_B1: Key = 0x00000010; +pub const EFI_KEY_B2: Key = 0x00000011; +pub const EFI_KEY_B3: Key = 0x00000012; +pub const EFI_KEY_B4: Key = 0x00000013; +pub const EFI_KEY_B5: Key = 0x00000014; +pub const EFI_KEY_B6: Key = 0x00000015; +pub const EFI_KEY_B7: Key = 0x00000016; +pub const EFI_KEY_B8: Key = 0x00000017; +pub const EFI_KEY_B9: Key = 0x00000018; +pub const EFI_KEY_B10: Key = 0x00000019; +pub const EFI_KEY_RSHIFT: Key = 0x0000001a; +pub const EFI_KEY_UP_ARROW: Key = 0x0000001b; +pub const EFI_KEY_ONE: Key = 0x0000001c; +pub const EFI_KEY_TWO: Key = 0x0000001d; +pub const EFI_KEY_THREE: Key = 0x0000001e; +pub const EFI_KEY_CAPS_LOCK: Key = 0x0000001f; +pub const EFI_KEY_C1: Key = 0x00000020; +pub const EFI_KEY_C2: Key = 0x00000021; +pub const EFI_KEY_C3: Key = 0x00000022; +pub const EFI_KEY_C4: Key = 0x00000023; +pub const EFI_KEY_C5: Key = 0x00000024; +pub const EFI_KEY_C6: Key = 0x00000025; +pub const EFI_KEY_C7: Key = 0x00000026; +pub const EFI_KEY_C8: Key = 0x00000027; +pub const EFI_KEY_C9: Key = 0x00000028; +pub const EFI_KEY_C10: Key = 0x00000029; +pub const EFI_KEY_C11: Key = 0x0000002a; +pub const EFI_KEY_C12: Key = 0x0000002b; +pub const EFI_KEY_FOUR: Key = 0x0000002c; +pub const EFI_KEY_FIVE: Key = 0x0000002d; +pub const EFI_KEY_SIX: Key = 0x0000002e; +pub const EFI_KEY_PLUS: Key = 0x0000002f; +pub const EFI_KEY_TAB: Key = 0x00000030; +pub const EFI_KEY_D1: Key = 0x00000031; +pub const EFI_KEY_D2: Key = 0x00000032; +pub const EFI_KEY_D3: Key = 0x00000033; +pub const EFI_KEY_D4: Key = 0x00000034; +pub const EFI_KEY_D5: Key = 0x00000035; +pub const EFI_KEY_D6: Key = 0x00000036; +pub const EFI_KEY_D7: Key = 0x00000037; +pub const EFI_KEY_D8: Key = 0x00000038; +pub const EFI_KEY_D9: Key = 0x00000039; +pub const EFI_KEY_D10: Key = 0x0000003a; +pub const EFI_KEY_D11: Key = 0x0000003b; +pub const EFI_KEY_D12: Key = 0x0000003c; +pub const EFI_KEY_D13: Key = 0x0000003d; +pub const EFI_KEY_DEL: Key = 0x0000003e; +pub const EFI_KEY_END: Key = 0x0000003f; +pub const EFI_KEY_PGDN: Key = 0x00000040; +pub const EFI_KEY_SEVEN: Key = 0x00000041; +pub const EFI_KEY_EIGHT: Key = 0x00000042; +pub const EFI_KEY_NINE: Key = 0x00000043; +pub const EFI_KEY_E0: Key = 0x00000044; +pub const EFI_KEY_E1: Key = 0x00000045; +pub const EFI_KEY_E2: Key = 0x00000046; +pub const EFI_KEY_E3: Key = 0x00000047; +pub const EFI_KEY_E4: Key = 0x00000048; +pub const EFI_KEY_E5: Key = 0x00000049; +pub const EFI_KEY_E6: Key = 0x0000004a; +pub const EFI_KEY_E7: Key = 0x0000004b; +pub const EFI_KEY_E8: Key = 0x0000004c; +pub const EFI_KEY_E9: Key = 0x0000004d; +pub const EFI_KEY_E10: Key = 0x0000004e; +pub const EFI_KEY_E11: Key = 0x0000004f; +pub const EFI_KEY_E12: Key = 0x00000050; +pub const EFI_KEY_BACK_SPACE: Key = 0x00000051; +pub const EFI_KEY_INS: Key = 0x00000052; +pub const EFI_KEY_HOME: Key = 0x00000053; +pub const EFI_KEY_PGUP: Key = 0x00000054; +pub const EFI_KEY_NLCK: Key = 0x00000055; +pub const EFI_KEY_SLASH: Key = 0x00000056; +pub const EFI_KEY_ASTERISK: Key = 0x00000057; +pub const EFI_KEY_MINUS: Key = 0x00000058; +pub const EFI_KEY_ESC: Key = 0x00000059; +pub const EFI_KEY_F1: Key = 0x0000005a; +pub const EFI_KEY_F2: Key = 0x0000005b; +pub const EFI_KEY_F3: Key = 0x0000005c; +pub const EFI_KEY_F4: Key = 0x0000005d; +pub const EFI_KEY_F5: Key = 0x0000005e; +pub const EFI_KEY_F6: Key = 0x0000005f; +pub const EFI_KEY_F7: Key = 0x00000060; +pub const EFI_KEY_F8: Key = 0x00000061; +pub const EFI_KEY_F9: Key = 0x00000062; +pub const EFI_KEY_F10: Key = 0x00000063; +pub const EFI_KEY_F11: Key = 0x00000064; +pub const EFI_KEY_F12: Key = 0x00000065; +pub const EFI_KEY_PRINT: Key = 0x00000066; +pub const EFI_KEY_SLCK: Key = 0x00000067; +pub const EFI_KEY_PAUSE: Key = 0x00000068; + +pub const NULL_MODIFIER: u16 = 0x0000; +pub const LEFT_CONTROL_MODIFIER: u16 = 0x0001; +pub const RIGHT_CONTROL_MODIFIER: u16 = 0x0002; +pub const LEFT_ALT_MODIFIER: u16 = 0x0003; +pub const RIGHT_ALT_MODIFIER: u16 = 0x0004; +pub const ALT_GR_MODIFIER: u16 = 0x0005; +pub const INSERT_MODIFIER: u16 = 0x0006; +pub const DELETE_MODIFIER: u16 = 0x0007; +pub const PAGE_DOWN_MODIFIER: u16 = 0x0008; +pub const PAGE_UP_MODIFIER: u16 = 0x0009; +pub const HOME_MODIFIER: u16 = 0x000A; +pub const END_MODIFIER: u16 = 0x000B; +pub const LEFT_SHIFT_MODIFIER: u16 = 0x000C; +pub const RIGHT_SHIFT_MODIFIER: u16 = 0x000D; +pub const CAPS_LOCK_MODIFIER: u16 = 0x000E; +pub const NUM_LOCK_MODIFIER: u16 = 0x000F; +pub const LEFT_ARROW_MODIFIER: u16 = 0x0010; +pub const RIGHT_ARROW_MODIFIER: u16 = 0x0011; +pub const DOWN_ARROW_MODIFIER: u16 = 0x0012; +pub const UP_ARROW_MODIFIER: u16 = 0x0013; +pub const NS_KEY_MODIFIER: u16 = 0x0014; +pub const NS_KEY_DEPENDENCY_MODIFIER: u16 = 0x0015; +pub const FUNCTION_KEY_ONE_MODIFIER: u16 = 0x0016; +pub const FUNCTION_KEY_TWO_MODIFIER: u16 = 0x0017; +pub const FUNCTION_KEY_THREE_MODIFIER: u16 = 0x0018; +pub const FUNCTION_KEY_FOUR_MODIFIER: u16 = 0x0019; +pub const FUNCTION_KEY_FIVE_MODIFIER: u16 = 0x001A; +pub const FUNCTION_KEY_SIX_MODIFIER: u16 = 0x001B; +pub const FUNCTION_KEY_SEVEN_MODIFIER: u16 = 0x001C; +pub const FUNCTION_KEY_EIGHT_MODIFIER: u16 = 0x001D; +pub const FUNCTION_KEY_NINE_MODIFIER: u16 = 0x001E; +pub const FUNCTION_KEY_TEN_MODIFIER: u16 = 0x001F; +pub const FUNCTION_KEY_ELEVEN_MODIFIER: u16 = 0x0020; +pub const FUNCTION_KEY_TWELVE_MODIFIER: u16 = 0x0021; +pub const PRINT_MODIFIER: u16 = 0x0022; +pub const SYS_REQUEST_MODIFIER: u16 = 0x0023; +pub const SCROLL_LOCK_MODIFIER: u16 = 0x0024; +pub const PAUSE_MODIFIER: u16 = 0x0025; +pub const BREAK_MODIFIER: u16 = 0x0026; +pub const LEFT_LOGO_MODIFIER: u16 = 0x0027; +pub const RIGHT_LOGO_MODIFIER: u16 = 0x0028; +pub const MENU_MODIFIER: u16 = 0x0029; + +pub type Notify = eficall! {fn( + u8, + *const crate::base::Guid, + *const crate::hii::PackageHeader, + crate::hii::Handle, + NotifyType, +) -> crate::base::Status}; + +pub type NotifyType = usize; + +pub const NOTIFY_NEW_PACK: NotifyType = 0x00000001; +pub const NOTIFY_REMOVE_PACK: NotifyType = 0x00000002; +pub const NOTIFY_EXPORT_PACK: NotifyType = 0x00000004; +pub const NOTIFY_ADD_PACK: NotifyType = 0x00000008; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,87 @@ +//! HII Font Protocol + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xe9ca4775, + 0x8657, + 0x47fc, + 0x97, + 0xe7, + &[0x7e, 0xd6, 0x5a, 0x08, 0x43, 0x24], +); + +pub type ProtocolStringToImage = eficall! {fn( + *const Protocol, + OutFlags, + String, + *const super::hii_font_ex::DisplayInfo, + *mut *mut super::hii_font_ex::ImageOutput, + usize, + usize, + *mut *mut RowInfo, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolStringIdToImage = eficall! {fn( + *const Protocol, + OutFlags, + crate::hii::Handle, + crate::hii::StringId, + *const crate::base::Char8, + *const super::hii_font_ex::DisplayInfo, + *mut *mut super::hii_font_ex::ImageOutput, + usize, + usize, + *mut *mut RowInfo, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolGetGlyph = eficall! {fn( + *const Protocol, + crate::base::Char16, + *const super::hii_font_ex::DisplayInfo, + *mut *mut super::hii_font_ex::ImageOutput, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolGetFontInfo = eficall! {fn( + *const Protocol, + *mut Handle, + *const super::hii_font_ex::DisplayInfo, + *mut *mut super::hii_font_ex::DisplayInfo, + String, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub string_to_image: ProtocolStringToImage, + pub string_id_to_image: ProtocolStringIdToImage, + pub get_glyph: ProtocolGetGlyph, + pub get_font_info: ProtocolGetFontInfo, +} + +pub type OutFlags = u32; + +pub const OUT_FLAG_CLIP: OutFlags = 0x00000001; +pub const OUT_FLAG_WRAP: OutFlags = 0x00000002; +pub const OUT_FLAG_CLIP_CLEAN_Y: OutFlags = 0x00000004; +pub const OUT_FLAG_CLIP_CLEAN_X: OutFlags = 0x00000008; +pub const OUT_FLAG_TRANSPARENT: OutFlags = 0x00000010; +pub const IGNORE_IF_NO_GLYPH: OutFlags = 0x00000020; +pub const IGNORE_LINE_BREAK: OutFlags = 0x00000040; +pub const DIRECT_TO_SCREEN: OutFlags = 0x00000080; + +pub type String = *mut crate::base::Char16; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct RowInfo { + pub start_index: usize, + pub end_index: usize, + pub line_height: usize, + pub line_width: usize, + pub baseline_offset: usize, +} + +pub type Handle = *mut core::ffi::c_void; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font_ex.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font_ex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font_ex.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_font_ex.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,107 @@ +//! HII Font Ex Protocol + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x849e6875, + 0xdb35, + 0x4df8, + 0xb4, + 0x1e, + &[0xc8, 0xf3, 0x37, 0x18, 0x07, 0x3f], +); + +pub type ProtocolStringToImageEx = eficall! {fn( + *const Protocol, + super::hii_font::OutFlags, + super::hii_font::String, + *const DisplayInfo, + *mut *mut ImageOutput, + usize, + usize, + *mut *mut super::hii_font::RowInfo, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolStringIdToImageEx = eficall! {fn( + *const Protocol, + super::hii_font::OutFlags, + crate::hii::Handle, + crate::hii::StringId, + *const crate::base::Char8, + *const DisplayInfo, + *mut *mut ImageOutput, + usize, + usize, + *mut *mut super::hii_font::RowInfo, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolGetGlyphEx = eficall! {fn( + *const Protocol, + crate::base::Char16, + *const DisplayInfo, + *mut *mut ImageOutput, + usize, +) -> crate::base::Status}; + +pub type ProtocolGetFontInfoEx = eficall! {fn( + *const Protocol, + *mut super::hii_font::Handle, + *const DisplayInfo, + *mut *mut DisplayInfo, + super::hii_font::String, +) -> crate::base::Status}; + +pub type ProtocolGetGlyphInfo = eficall! {fn( + *const Protocol, + crate::base::Char16, + *const DisplayInfo, + *mut crate::hii::GlyphInfo, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub string_to_image_ex: ProtocolStringToImageEx, + pub string_id_to_image_ex: ProtocolStringIdToImageEx, + pub get_glyph_ex: ProtocolGetGlyphEx, + pub get_font_info_ex: ProtocolGetFontInfoEx, + pub get_glyph_info: ProtocolGetGlyphInfo, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct DisplayInfo { + pub foreground_color: super::graphics_output::BltPixel, + pub background_color: super::graphics_output::BltPixel, + pub font_info_mask: InfoMask, + pub font_info: super::hii_string::Info, +} + +pub type InfoMask = u32; + +pub const INFO_SYS_FONT: InfoMask = 0x00000001; +pub const INFO_SYS_SIZE: InfoMask = 0x00000002; +pub const INFO_SYS_STYLE: InfoMask = 0x00000004; +pub const INFO_SYS_FORE_COLOR: InfoMask = 0x00000010; +pub const INFO_SYS_BACK_COLOR: InfoMask = 0x00000020; +pub const INFO_RESIZE: InfoMask = 0x00001000; +pub const INFO_RESTYLE: InfoMask = 0x00002000; +pub const INFO_ANY_FONT: InfoMask = 0x00010000; +pub const INFO_ANY_SIZE: InfoMask = 0x00020000; +pub const INFO_ANY_STYLE: InfoMask = 0x00040000; + +#[repr(C)] +#[derive(Clone, Copy)] +pub union ImageOutputImage { + pub bitmap: *mut super::graphics_output::BltPixel, + pub screen: *mut super::graphics_output::Protocol, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ImageOutput { + pub width: u16, + pub height: u16, + pub image: ImageOutputImage, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_package_list.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_package_list.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_package_list.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_package_list.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +//! Human Interface Infrastructure (HII) Package List Protocol +//! +//! Installed onto an image handle during load if the image contains a custom PE/COFF +//! resource with type 'HII'. The protocol's interface pointer points to the HII package +//! list which is contained in the resource's data. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x6a1ee763, + 0xd47a, + 0x43b4, + 0xaa, + 0xbe, + &[0xef, 0x1d, 0xe2, 0xab, 0x56, 0xfc], +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_string.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_string.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/hii_string.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/hii_string.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,71 @@ +//! HII String Protocol + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xfd96974, + 0x23aa, + 0x4cdc, + 0xb9, + 0xcb, + &[0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a], +); + +pub type ProtocolNewString = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *mut crate::hii::StringId, + *const crate::base::Char8, + *const crate::base::Char16, + super::hii_font::String, + *const Info, +) -> crate::base::Status}; + +pub type ProtocolGetString = eficall! {fn( + *const Protocol, + *const crate::base::Char8, + crate::hii::Handle, + crate::hii::StringId, + super::hii_font::String, + *mut usize, + *mut *mut Info, +) -> crate::base::Status}; + +pub type ProtocolSetString = eficall! {fn( + *const Protocol, + crate::hii::Handle, + crate::hii::StringId, + *const crate::base::Char8, + super::hii_font::String, + *const Info, +) -> crate::base::Status}; + +pub type ProtocolGetLanguages = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *mut crate::base::Char8, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolGetSecondaryLanguages = eficall! {fn( + *const Protocol, + crate::hii::Handle, + *const crate::base::Char8, + *mut crate::base::Char8, + *mut usize, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub new_string: ProtocolNewString, + pub get_string: ProtocolGetString, + pub set_string: ProtocolSetString, + pub get_languages: ProtocolGetLanguages, + pub get_secondary_languages: ProtocolGetSecondaryLanguages, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Info { + pub font_style: crate::hii::FontStyle, + pub font_size: u16, + pub font_name: [crate::base::Char16; N], +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/ip4.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/ip4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,202 @@ +//! IPv4 Protocol +//! +//! It implements a simple packet-oriented interface that can be used by +//! drivers, daemons, and applications to transmit and receive network packets. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x41d94cd2, + 0x35b6, + 0x455a, + 0x82, + 0x58, + &[0xd4, 0xe5, 0x13, 0x34, 0xaa, 0xdd], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xc51711e7, + 0xb4bf, + 0x404a, + 0xbf, + 0xb8, + &[0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub default_protocol: u8, + pub accept_any_protocol: crate::base::Boolean, + pub accept_icmp_errors: crate::base::Boolean, + pub accept_broadcast: crate::base::Boolean, + pub accept_promiscuous: crate::base::Boolean, + pub use_default_address: crate::base::Boolean, + pub station_address: crate::base::Ipv4Address, + pub subnet_mask: crate::base::Ipv4Address, + pub type_of_service: u8, + pub time_to_live: u8, + pub do_not_fragment: crate::base::Boolean, + pub raw_data: crate::base::Boolean, + pub receive_timeout: u32, + pub transmit_timeout: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct RouteTable { + pub subnet_address: crate::base::Ipv4Address, + pub subnet_mask: crate::base::Ipv4Address, + pub gateway_address: crate::base::Ipv4Address, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IcmpType { + pub r#type: u8, + pub code: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ModeData { + pub is_started: crate::base::Boolean, + pub max_packet_size: u32, + pub config_data: ConfigData, + pub is_configured: crate::base::Boolean, + pub group_count: u32, + pub group_table: *mut crate::base::Ipv4Address, + pub route_count: u32, + pub route_table: *mut RouteTable, + pub icmp_type_count: u32, + pub icmp_type_list: *mut IcmpType, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub packet: CompletionTokenPacket, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CompletionTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ReceiveData { + pub time_stamp: crate::system::Time, + pub recycle_signal: crate::base::Event, + pub header_length: u32, + pub header: *mut Header, + pub options_length: u32, + pub options: *mut core::ffi::c_void, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TransmitData { + pub destination_address: crate::base::Ipv4Address, + pub override_data: *mut OverrideData, + pub options_length: u32, + pub options_buffer: *mut core::ffi::c_void, + pub total_data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Header { + pub header_length_and_version: u8, + pub type_of_service: u8, + pub total_length: u16, + pub identification: u16, + pub fragmentation: u16, + pub time_to_live: u8, + pub protocol: u8, + pub checksum: u16, + pub source_address: crate::base::Ipv4Address, + pub destination_address: crate::base::Ipv4Address, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct OverrideData { + pub source_address: crate::base::Ipv4Address, + pub gateway_address: crate::base::Ipv4Address, + pub protocol: u8, + pub type_of_service: u8, + pub time_to_live: u8, + pub do_not_fragment: crate::base::Boolean, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolGroups = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv4Address, +) -> crate::base::Status}; + +pub type ProtocolRoutes = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub groups: ProtocolGroups, + pub routes: ProtocolRoutes, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/ip6.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip6.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/ip6.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/ip6.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,264 @@ +//! IPv6 Protocol +//! +//! It implements a simple packet-oriented interface that can be used by +//! drivers, daemons, and applications to transmit and receive network packets. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x2c8759d5, + 0x5c2d, + 0x66ef, + 0x92, + 0x5f, + &[0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xec835dd3, + 0xfe0f, + 0x617b, + 0xa6, + 0x21, + &[0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ModeData { + pub is_started: crate::base::Boolean, + pub max_packet_size: u32, + pub config_data: ConfigData, + pub is_configured: crate::base::Boolean, + pub address_count: u32, + pub address_list: *mut AddressInfo, + pub group_count: u32, + pub group_table: *mut crate::base::Ipv6Address, + pub route_count: u32, + pub route_table: *mut RouteTable, + pub neighbor_count: u32, + pub neighbor_cache: *mut NeighborCache, + pub prefix_count: u32, + pub prefix_table: *mut AddressInfo, + pub icmp_type_count: u32, + pub icmp_type_list: *mut IcmpType, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub default_protocol: u8, + pub accept_any_protocol: crate::base::Boolean, + pub accept_icmp_errors: crate::base::Boolean, + pub accept_promiscuous: crate::base::Boolean, + pub destination_address: crate::base::Ipv6Address, + pub station_address: crate::base::Ipv6Address, + pub traffic_class: u8, + pub hop_limit: u8, + pub flow_lable: u32, + pub receive_timeout: u32, + pub transmit_timeout: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct AddressInfo { + pub address: crate::base::Ipv6Address, + pub prefix_length: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct RouteTable { + pub gateway: crate::base::Ipv6Address, + pub destination: crate::base::Ipv6Address, + pub prefix_length: u8, +} + +pub type NeighborState = u32; + +pub const NEIGHBOR_IN_COMPLETE: NeighborState = 0x00000000; +pub const NEIGHBOR_REACHABLE: NeighborState = 0x00000001; +pub const NEIGHBOR_STATE: NeighborState = 0x00000002; +pub const NEIGHBOR_DELAY: NeighborState = 0x00000003; +pub const NEIGHBOR_PROBE: NeighborState = 0x00000004; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct NeighborCache { + pub neighbor: crate::base::Ipv6Address, + pub link_address: crate::base::MacAddress, + pub state: NeighborState, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct IcmpType { + pub r#type: u8, + pub code: u8, +} + +pub const ICMP_V6_DEST_UNREACHABLE: u8 = 0x01; +pub const ICMP_V6_PACKET_TOO_BIG: u8 = 0x02; +pub const ICMP_V6_TIME_EXCEEDED: u8 = 0x03; +pub const ICMP_V6_PARAMETER_PROBLEM: u8 = 0x04; + +pub const ICMP_V6_ECHO_REQUEST: u8 = 0x80; +pub const ICMP_V6_ECHO_REPLY: u8 = 0x81; +pub const ICMP_V6_LISTENER_QUERY: u8 = 0x82; +pub const ICMP_V6_LISTENER_REPORT: u8 = 0x83; +pub const ICMP_V6_LISTENER_DONE: u8 = 0x84; +pub const ICMP_V6_ROUTER_SOLICIT: u8 = 0x85; +pub const ICMP_V6_ROUTER_ADVERTISE: u8 = 0x86; +pub const ICMP_V6_NEIGHBOR_SOLICIT: u8 = 0x87; +pub const ICMP_V6_NEIGHBOR_ADVERTISE: u8 = 0x88; +pub const ICMP_V6_REDIRECT: u8 = 0x89; +pub const ICMP_V6_LISTENER_REPORT_2: u8 = 0x8f; + +pub const ICMP_V6_NO_ROUTE_TO_DEST: u8 = 0x00; +pub const ICMP_V6_COMM_PROHIBITED: u8 = 0x01; +pub const ICMP_V6_BEYOND_SCOPE: u8 = 0x02; +pub const ICMP_V6_ADDR_UNREACHABLE: u8 = 0x03; +pub const ICMP_V6_PORT_UNREACHABLE: u8 = 0x04; +pub const ICMP_V6_SOURCE_ADDR_FAILED: u8 = 0x05; +pub const ICMP_V6_ROUTE_REJECTED: u8 = 0x06; + +pub const ICMP_V6_TIMEOUT_HOP_LIMIT: u8 = 0x00; +pub const ICMP_V6_TIMEOUT_REASSEMBLE: u8 = 0x01; + +pub const ICMP_V6_ERRONEOUS_HEADER: u8 = 0x00; +pub const ICMP_V6_UNRECOGNIZE_NEXT_HDR: u8 = 0x01; +pub const ICMP_V6_UNRECOGNIZE_OPTION: u8 = 0x02; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub packet: CompletionTokenPacket, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CompletionTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ReceiveData { + pub time_stamp: crate::system::Time, + pub recycle_signal: crate::base::Event, + pub header_length: u32, + pub header: *mut Header, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Header { + pub traffic_class_h_version: u8, + pub flow_label_h_traffic_class_l: u8, + pub flow_label_l: u16, + pub payload_length: u16, + pub next_header: u8, + pub hop_limit: u8, + pub source_address: crate::base::Ipv6Address, + pub destination_address: crate::base::Ipv6Address, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TransmitData { + pub destination_address: *mut crate::base::Ipv6Address, + pub override_data: *mut OverrideData, + pub ext_hdrs_length: u32, + pub ext_hdrs: *mut core::ffi::c_void, + pub next_header: u8, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct OverrideData { + pub protocol: u8, + pub hop_limit: u8, + pub flow_label: u32, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolGroups = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv6Address, +) -> crate::base::Status}; + +pub type ProtocolRoutes = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv6Address, + u8, + *mut crate::base::Ipv6Address, +) -> crate::base::Status}; + +pub type ProtocolNeighbors = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv6Address, + *mut crate::base::MacAddress, + u32, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub groups: ProtocolGroups, + pub routes: ProtocolRoutes, + pub neighbors: ProtocolNeighbors, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/load_file.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/load_file.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +//! Load File Protocol +//! +//! The Load File protocol is used to obtain files, that are primarily boot +//! options, from arbitrary devices. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x56ec3091, + 0x954c, + 0x11d2, + 0x8e, + 0x3f, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub type ProtocolLoadFile = eficall! {fn( + *mut Protocol, + *mut crate::protocols::device_path::Protocol, + crate::base::Boolean, + *mut usize, + *mut core::ffi::c_void +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub load_file: ProtocolLoadFile, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/load_file2.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/load_file2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/load_file2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +//! Load File 2 Protocol +//! +//! The Load File 2 protocol is used to obtain files from arbitrary devices +//! that are not boot options. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x4006c0c1, + 0xfcb3, + 0x403e, + 0x99, + 0x6d, + &[0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d], +); + +pub type Protocol = crate::protocols::load_file::Protocol; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +//! Loaded Image Protocol +//! +//! The loaded image protocol defines how to obtain information about a loaded image from an +//! image handle. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x5b1b31a1, + 0x9562, + 0x11d2, + 0x8e, + 0x3f, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub const REVISION: u32 = 0x00001000u32; + +pub type ProtocolUnload = eficall! {fn( + crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u32, + pub parent_handle: crate::base::Handle, + pub system_table: *mut crate::system::SystemTable, + + pub device_handle: crate::base::Handle, + pub file_path: *mut crate::protocols::device_path::Protocol, + pub reserved: *mut core::ffi::c_void, + + pub load_options_size: u32, + pub load_options: *mut core::ffi::c_void, + + pub image_base: *mut core::ffi::c_void, + pub image_size: u64, + pub image_code_type: crate::system::MemoryType, + pub image_data_type: crate::system::MemoryType, + pub unload: Option, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image_device_path.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image_device_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image_device_path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/loaded_image_device_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +//! Loaded Image Device Path Protocol +//! +//! The loaded image device path protocol provides the device path of a loaded image, using the +//! protocol structures of the device-path and loaded-image protocols. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xbc62157e, + 0x3e33, + 0x4fec, + 0x99, + 0x20, + &[0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf], +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/managed_network.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/managed_network.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/managed_network.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/managed_network.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +//! Managed Network Protocol +//! +//! It provides raw (unformatted) asynchronous network packet I/O services. +//! These services make it possible for multiple-event-driven drivers and +//! applications to access and use the system network interfaces at the same +//! time. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x7ab33a91, + 0xace5, + 0x4326, + 0xb5, + 0x72, + &[0xe7, 0xee, 0x33, 0xd3, 0x9f, 0x16], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xf36ff770, + 0xa7e1, + 0x42cf, + 0x9e, + 0xd2, + &[0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub received_queue_timeout_value: u32, + pub transmit_queue_timeout_value: u32, + pub protocol_type_filter: u16, + pub enable_unicast_receive: crate::base::Boolean, + pub enable_multicast_receive: crate::base::Boolean, + pub enable_broadcast_receive: crate::base::Boolean, + pub enable_promiscuous_receive: crate::base::Boolean, + pub flush_queues_on_reset: crate::base::Boolean, + pub enable_receive_timestamps: crate::base::Boolean, + pub disable_background_polling: crate::base::Boolean, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub packet: CompletionTokenPacket, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CompletionTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ReceiveData { + pub timestamp: crate::system::Time, + pub recycle_event: crate::base::Event, + pub packet_length: u32, + pub header_length: u32, + pub address_length: u32, + pub data_length: u32, + pub broadcast_flag: crate::base::Boolean, + pub multicast_flag: crate::base::Boolean, + pub promiscuous_flag: crate::base::Boolean, + pub protocol_type: u16, + pub destination_address: *mut core::ffi::c_void, + pub source_address: *mut core::ffi::c_void, + pub media_header: *mut core::ffi::c_void, + pub packet_data: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TransmitData { + pub destination_address: *mut crate::base::MacAddress, + pub source_address: *mut crate::base::MacAddress, + pub protocol_type: u16, + pub data_length: u32, + pub header_length: u16, + pub fragment_count: u16, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolMcastIpToMac = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::IpAddress, + *mut crate::base::MacAddress, +) -> crate::base::Status}; + +pub type ProtocolGroups = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::MacAddress, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub mcast_ip_to_mac: ProtocolMcastIpToMac, + pub groups: ProtocolGroups, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/memory_attribute.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/memory_attribute.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/memory_attribute.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/memory_attribute.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +//! Memory Attribute Protocol +//! +//! Provides an interface to abstract setting or getting of memory attributes in the UEFI environment. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xf4560cf6, + 0x40ec, + 0x4b4a, + 0xa1, + 0x92, + &[0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89], +); + +pub type GetMemoryAttributes = eficall! {fn( + *mut Protocol, + crate::base::PhysicalAddress, + u64, + *mut u64, +) -> crate::base::Status}; + +pub type SetMemoryAttributes = eficall! {fn( + *mut Protocol, + crate::base::PhysicalAddress, + u64, + u64, +) -> crate::base::Status}; + +pub type ClearMemoryAttributes = eficall! {fn( + *mut Protocol, + crate::base::PhysicalAddress, + u64, + u64, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_memory_attributes: GetMemoryAttributes, + pub set_memory_attributes: SetMemoryAttributes, + pub clear_memory_attributes: ClearMemoryAttributes, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/mp_services.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/mp_services.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/mp_services.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/mp_services.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +//! Multi-Processor Services Protocol +//! +//! This Protocol is defined in the UEFI Platform Integration Specification, +//! Section 13.4. +//! +//! This provides a generalized way of performing the following tasks: +//! - Retrieving information of multi-processor environments. +//! - Dispatching user-provided function to APs. +//! - Maintain MP-related processor status. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3fdda605, + 0xa76e, + 0x4f46, + 0xad, + 0x29, + &[0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08], +); + +pub const PROCESSOR_AS_BSP_BIT: u32 = 0x00000001; +pub const PROCESSOR_ENABLED_BIT: u32 = 0x00000002; +pub const PROCESSOR_HEALTH_STATUS_BIT: u32 = 0x00000004; + +pub const END_OF_CPU_LIST: usize = usize::MAX; + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct CpuPhysicalLocation { + pub package: u32, + pub core: u32, + pub thread: u32, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct CpuPhysicalLocation2 { + pub package: u32, + pub module: u32, + pub tile: u32, + pub die: u32, + pub core: u32, + pub thread: u32, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union ExtendedProcessorInformation { + pub location2: CpuPhysicalLocation2, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ProcessorInformation { + pub processor_id: u64, + pub status_flag: u32, + pub location: CpuPhysicalLocation, + pub extended_information: ExtendedProcessorInformation, +} + +pub type ApProcedure = eficall! {fn(*mut core::ffi::c_void)}; + +pub type GetNumberOfProcessors = eficall! {fn( + *mut Protocol, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type GetProcessorInfo = eficall! {fn( + *mut Protocol, + usize, + *mut ProcessorInformation, +) -> crate::base::Status}; + +pub type StartupAllAps = eficall! {fn( + *mut Protocol, + ApProcedure, + crate::base::Boolean, + crate::base::Event, + usize, + *mut core::ffi::c_void, + *mut *mut usize, +) -> crate::base::Status}; + +pub type StartupThisAp = eficall! {fn( + *mut Protocol, + ApProcedure, + usize, + crate::base::Event, + usize, + *mut core::ffi::c_void, + *mut crate::base::Boolean, +) -> crate::base::Status}; + +pub type SwitchBsp = eficall! {fn( + *mut Protocol, + usize, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type EnableDisableAp = eficall! {fn( + *mut Protocol, + usize, + crate::base::Boolean, + *mut u32, +) -> crate::base::Status}; + +pub type WhoAmI = eficall! {fn( + *mut Protocol, + *mut usize, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_number_of_processors: GetNumberOfProcessors, + pub get_processor_info: GetProcessorInfo, + pub startup_all_aps: StartupAllAps, + pub startup_this_ap: StartupThisAp, + pub switch_bsp: SwitchBsp, + pub enable_disable_ap: EnableDisableAp, + pub who_am_i: WhoAmI, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/pci_io.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/pci_io.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/pci_io.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/pci_io.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,203 @@ +//! PCI I/O Protocol +//! +//! Used by code, typically drivers, running in the EFI boot services +//! environment to access memory and I/O on a PCI controller. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x4cf5b200, + 0x68b8, + 0x4ca5, + 0x9e, + 0xec, + &[0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a], +); + +pub type Width = u32; + +pub const WIDTH_UINT8: Width = 0x00000000; +pub const WIDTH_UINT16: Width = 0x00000001; +pub const WIDTH_UINT32: Width = 0x00000002; +pub const WIDTH_UINT64: Width = 0x00000003; +pub const WIDTH_FIFO_UINT8: Width = 0x00000004; +pub const WIDTH_FIFO_UINT16: Width = 0x00000005; +pub const WIDTH_FIFO_UINT32: Width = 0x00000006; +pub const WIDTH_FIFO_UINT64: Width = 0x00000007; +pub const WIDTH_FILL_UINT8: Width = 0x00000008; +pub const WIDTH_FILL_UINT16: Width = 0x00000009; +pub const WIDTH_FILL_UINT32: Width = 0x0000000a; +pub const WIDTH_FILL_UINT64: Width = 0x0000000b; +pub const WIDTH_MAXIMUM: Width = 0x0000000c; + +pub type Operation = u32; + +pub const OPERATION_BUS_MASTER_READ: Operation = 0x00000000; +pub const OPERATION_BUS_MASTER_WRITE: Operation = 0x00000001; +pub const OPERATION_BUS_MASTER_COMMON_BUFFER: Operation = 0x00000002; +pub const OPERATION_MAXIMUM: Operation = 0x00000003; + +pub type Attribute = u64; + +pub const ATTRIBUTE_ISA_MOTHERBOARD_IO: Attribute = 0x00000001; +pub const ATTRIBUTE_ISA_IO: Attribute = 0x00000002; +pub const ATTRIBUTE_VGA_PALETTE_IO: Attribute = 0x00000004; +pub const ATTRIBUTE_VGA_MEMORY: Attribute = 0x00000008; +pub const ATTRIBUTE_VGA_IO: Attribute = 0x00000010; +pub const ATTRIBUTE_IDE_PRIMARY_IO: Attribute = 0x00000020; +pub const ATTRIBUTE_IDE_SECONDARY_IO: Attribute = 0x00000040; +pub const ATTRIBUTE_MEMORY_WRITE_COMBINE: Attribute = 0x00000080; +pub const ATTRIBUTE_IO: Attribute = 0x00000100; +pub const ATTRIBUTE_MEMORY: Attribute = 0x00000200; +pub const ATTRIBUTE_BUS_MASTER: Attribute = 0x00000400; +pub const ATTRIBUTE_MEMORY_CACHED: Attribute = 0x00000800; +pub const ATTRIBUTE_MEMORY_DISABLE: Attribute = 0x00001000; +pub const ATTRIBUTE_EMBEDDED_DEVICE: Attribute = 0x00002000; +pub const ATTRIBUTE_EMBEDDED_ROM: Attribute = 0x00004000; +pub const ATTRIBUTE_DUAL_ADDRESS_CYCLE: Attribute = 0x00008000; +pub const ATTRIBUTE_ISA_IO_16: Attribute = 0x00010000; +pub const ATTRIBUTE_VGA_PALETTE_IO_16: Attribute = 0x00020000; +pub const ATTRIBUTE_VGA_IO_16: Attribute = 0x00040000; + +pub type AttributeOperation = u32; + +pub const ATTRIBUTE_OPERATION_GET: AttributeOperation = 0x00000000; +pub const ATTRIBUTE_OPERATION_SET: AttributeOperation = 0x00000001; +pub const ATTRIBUTE_OPERATION_ENABLE: AttributeOperation = 0x00000002; +pub const ATTRIBUTE_OPERATION_DISABLE: AttributeOperation = 0x00000003; +pub const ATTRIBUTE_OPERATION_SUPPORTED: AttributeOperation = 0x00000004; +pub const ATTRIBUTE_OPERATION_MAXIMUM: AttributeOperation = 0x00000005; + +pub const PASS_THROUGH_BAR: u8 = 0xff; + +pub type ProtocolPollIoMem = eficall! {fn( + *mut Protocol, + Width, + u8, + u64, + u64, + u64, + u64, + *mut u64, +) -> crate::base::Status}; + +pub type ProtocolIoMem = eficall! {fn( + *mut Protocol, + Width, + u8, + u64, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolConfig = eficall! {fn( + *mut Protocol, + Width, + u32, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolCopyMem = eficall! {fn( + *mut Protocol, + Width, + u8, + u64, + u8, + u64, + usize, +) -> crate::base::Status}; + +pub type ProtocolMap = eficall! {fn( + *mut Protocol, + Operation, + *mut core::ffi::c_void, + *mut usize, + *mut crate::base::PhysicalAddress, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolUnmap = eficall! {fn( + *mut Protocol, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolAllocateBuffer = eficall! {fn( + *mut Protocol, + crate::system::AllocateType, + crate::system::MemoryType, + usize, + *mut *mut core::ffi::c_void, + Attribute, +) -> crate::base::Status}; + +pub type ProtocolFreeBuffer = eficall! {fn( + *mut Protocol, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolFlush = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolGetLocation = eficall! {fn( + *mut Protocol, + *mut usize, + *mut usize, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolAttributes = eficall! {fn( + *mut Protocol, + AttributeOperation, + Attribute, + *mut Attribute, +) -> crate::base::Status}; + +pub type ProtocolGetBarAttributes = eficall! {fn( + *mut Protocol, + u8, + *mut Attribute, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolSetBarAttributes = eficall! {fn( + *mut Protocol, + Attribute, + u8, + *mut u64, + *mut u64, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Access { + pub read: ProtocolIoMem, + pub write: ProtocolIoMem, +} + +#[repr(C)] +pub struct ConfigAccess { + pub read: ProtocolConfig, + pub write: ProtocolConfig, +} + +#[repr(C)] +pub struct Protocol { + pub poll_mem: ProtocolPollIoMem, + pub poll_io: ProtocolPollIoMem, + pub mem: Access, + pub io: Access, + pub pci: ConfigAccess, + pub copy_mem: ProtocolCopyMem, + pub map: ProtocolMap, + pub unmap: ProtocolUnmap, + pub allocate_buffer: ProtocolAllocateBuffer, + pub free_buffer: ProtocolFreeBuffer, + pub flush: ProtocolFlush, + pub get_location: ProtocolGetLocation, + pub attributes: ProtocolAttributes, + pub get_bar_attributes: ProtocolGetBarAttributes, + pub set_bar_attributes: ProtocolSetBarAttributes, + pub rom_size: u64, + pub rom_image: *mut core::ffi::c_void, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/platform_driver_override.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/platform_driver_override.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/platform_driver_override.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/platform_driver_override.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +//! Platform Driver Override Protocol +//! +//! This protocol matches one or more drivers to a controller. A platform driver +//! produces this protocol, and it is installed on a separate handle. This +//! protocol is used by the `EFI_BOOT_SERVICES.ConnectController()` boot service +//! to select the best driver for a controller. All of the drivers returned by +//! this protocol have a higher precedence than drivers found from an EFI Bus +//! Specific Driver Override Protocol or drivers found from the general UEFI +//! driver binding search algorithm. If more than one driver is returned by this +//! protocol, then the drivers are returned in order from highest precedence to +//! lowest precedence. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x6b30c738, + 0xa391, + 0x11d4, + 0x9a, + 0x3b, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub type ProtocolGetDriver = eficall! {fn( + *mut Protocol, + crate::base::Handle, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type ProtocolGetDriverPath = eficall! {fn( + *mut Protocol, + crate::base::Handle, + *mut *mut crate::protocols::device_path::Protocol +) -> crate::base::Status}; + +pub type ProtocolDriverLoaded = eficall! {fn( + *mut Protocol, + crate::base::Handle, + *mut crate::protocols::device_path::Protocol, + crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_driver: ProtocolGetDriver, + pub get_driver_path: ProtocolGetDriverPath, + pub driver_loaded: ProtocolDriverLoaded, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/rng.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/rng.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/rng.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/rng.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,83 @@ +//! Random Number Generator Protocol +//! +//! This protocol is used to provide random numbers for use in applications, or +//! entropy for seeding other random number generators. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3152bca5, + 0xeade, + 0x433d, + 0x86, + 0x2e, + &[0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44], +); + +pub type Algorithm = crate::base::Guid; + +pub const ALGORITHM_SP800_90_HASH_256_GUID: Algorithm = crate::base::Guid::from_fields( + 0xa7af67cb, + 0x603b, + 0x4d42, + 0xba, + 0x21, + &[0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96], +); +pub const ALGORITHM_SP800_90_HMAC_256_GUID: Algorithm = crate::base::Guid::from_fields( + 0xc5149b43, + 0xae85, + 0x4f53, + 0x99, + 0x82, + &[0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7], +); +pub const ALGORITHM_SP800_90_CTR_256_GUID: Algorithm = crate::base::Guid::from_fields( + 0x44f0de6e, + 0x4d8c, + 0x4045, + 0xa8, + 0xc7, + &[0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e], +); +pub const ALGORITHM_X9_31_3DES_GUID: Algorithm = crate::base::Guid::from_fields( + 0x63c4785a, + 0xca34, + 0x4012, + 0xa3, + 0xc8, + &[0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46], +); +pub const ALGORITHM_X9_31_AES_GUID: Algorithm = crate::base::Guid::from_fields( + 0xacd03321, + 0x777e, + 0x4d3d, + 0xb1, + 0xc8, + &[0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9], +); +pub const ALGORITHM_RAW: Algorithm = crate::base::Guid::from_fields( + 0xe43176d7, + 0xb6e8, + 0x4827, + 0xb7, + 0x84, + &[0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61], +); + +pub type ProtocolGetInfo = eficall! {fn( + *mut Protocol, + *mut usize, + *mut Algorithm, +) -> crate::base::Status}; + +pub type ProtocolGetRng = eficall! {fn( + *mut Protocol, + *mut Algorithm, + usize, + *mut u8, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_info: ProtocolGetInfo, + pub get_rng: ProtocolGetRng, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/service_binding.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/service_binding.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/service_binding.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/service_binding.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +//! Service Binding Protocol +//! +//! Provides services that are required to create and destroy child handles +//! that support a given set of protocols. + +pub type ProtocolCreateChild = eficall! {fn( + *mut Protocol, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type ProtocolDestroyChild = eficall! {fn( + *mut Protocol, + crate::base::Handle, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub create_child: ProtocolCreateChild, + pub destroy_child: ProtocolDestroyChild, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,295 @@ +//! Shell Protocol +//! +//! Provides shell services to UEFI applications. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x6302d008, + 0x7f9b, + 0x4f30, + 0x87, + 0xac, + &[0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e], +); + +pub const MAJOR_VERSION: u32 = 0x00000002; +pub const MINOR_VERSION: u32 = 0x00000002; + +pub type FileHandle = *mut core::ffi::c_void; + +pub type DeviceNameFlags = u32; +pub const DEVICE_NAME_USE_COMPONENT_NAME: DeviceNameFlags = 0x00000001; +pub const DEVICE_NAME_USE_DEVICE_PATH: DeviceNameFlags = 0x00000002; + +#[repr(C)] +pub struct ListEntry { + pub flink: *mut ListEntry, + pub blink: *mut ListEntry, +} + +#[repr(C)] +pub struct FileInfo { + pub link: ListEntry, + pub status: crate::base::Status, + pub full_name: *mut crate::base::Char16, + pub file_name: *mut crate::base::Char16, + pub handle: FileHandle, + pub info: *mut crate::protocols::file::Info, +} + +pub type Execute = eficall! {fn( + *mut crate::base::Handle, + *mut crate::base::Char16, + *mut *mut crate::base::Char16, + *mut crate::base::Status, +) -> crate::base::Status}; + +pub type GetEnv = eficall! {fn( + *mut crate::base::Char16, +) -> *mut crate::base::Char16}; + +pub type SetEnv = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Char16, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type GetAlias = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Boolean, +) -> *mut crate::base::Char16}; + +pub type SetAlias = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Char16, + crate::base::Boolean, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type GetHelpText = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Char16, + *mut *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetDevicePathFromMap = eficall! {fn( + *mut crate::base::Char16, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type GetMapFromDevicePath = eficall! {fn( + *mut *mut crate::protocols::device_path::Protocol, +) -> *mut crate::base::Char16}; + +pub type GetDevicePathFromFilePath = eficall! {fn( + *mut crate::base::Char16, +) -> *mut crate::protocols::device_path::Protocol}; + +pub type GetFilePathFromDevicePath = eficall! {fn( + *mut crate::protocols::device_path::Protocol, +) -> *mut crate::base::Char16}; + +pub type SetMap = eficall! {fn( + *mut crate::protocols::device_path::Protocol, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetCurDir = eficall! {fn( + *mut crate::base::Char16, +) -> *mut crate::base::Char16}; + +pub type SetCurDir = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type OpenFileList = eficall! {fn( + *mut crate::base::Char16, + u64, + *mut *mut FileInfo, +) -> crate::base::Status}; + +pub type FreeFileList = eficall! {fn( + *mut *mut FileInfo, +) -> crate::base::Status}; + +pub type RemoveDupInFileList = eficall! {fn( + *mut *mut FileInfo, +) -> crate::base::Status}; + +pub type BatchIsActive = eficall! {fn() -> crate::base::Boolean}; + +pub type IsRootShell = eficall! {fn() -> crate::base::Boolean}; + +pub type EnablePageBreak = eficall! {fn()}; + +pub type DisablePageBreak = eficall! {fn()}; + +pub type GetPageBreak = eficall! {fn() -> crate::base::Boolean}; + +pub type GetDeviceName = eficall! {fn( + crate::base::Handle, + DeviceNameFlags, + *mut crate::base::Char8, + *mut *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetFileInfo = eficall! {fn( + FileHandle, +) -> *mut crate::protocols::file::Info}; + +pub type SetFileInfo = eficall! {fn( + FileHandle, + *mut crate::protocols::file::Info +) -> crate::base::Status}; + +pub type OpenFileByName = eficall! {fn( + *mut crate::base::Char16, + *mut FileHandle, + u64, +) -> crate::base::Status}; + +pub type CloseFile = eficall! {fn( + FileHandle, +) -> crate::base::Status}; + +pub type CreateFile = eficall! {fn( + *mut crate::base::Char16, + u64, + *mut FileHandle, +) -> crate::base::Status}; + +pub type ReadFile = eficall! {fn( + FileHandle, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type WriteFile = eficall! {fn( + FileHandle, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type DeleteFile = eficall! {fn( + FileHandle, +) -> crate::base::Status}; + +pub type DeleteFileByName = eficall! {fn( + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetFilePosition = eficall! {fn( + FileHandle, + *mut u64, +) -> crate::base::Status}; + +pub type SetFilePosition = eficall! {fn( + FileHandle, + u64, +) -> crate::base::Status}; + +pub type FlushFile = eficall! {fn( + FileHandle, +) -> crate::base::Status}; + +pub type FindFiles = eficall! {fn( + *mut crate::base::Char16, + *mut *mut FileInfo, +) -> crate::base::Status}; + +pub type FindFilesInDir = eficall! {fn( + FileHandle, + *mut *mut FileInfo, +) -> crate::base::Status}; + +pub type GetFileSize = eficall! {fn( + FileHandle, + *mut u64, +) -> crate::base::Status}; + +pub type OpenRoot = eficall! {fn( + *mut crate::protocols::device_path::Protocol, + *mut FileHandle, +) -> crate::base::Status}; + +pub type OpenRootByHandle = eficall! {fn( + crate::base::Handle, + *mut FileHandle, +) -> crate::base::Status}; + +pub type RegisterGuidName = eficall! {fn( + *mut crate::base::Guid, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetGuidName = eficall! {fn( + *mut crate::base::Guid, + *mut *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type GetGuidFromName = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Guid, +) -> crate::base::Status}; + +pub type GetEnvEx = eficall! {fn( + *mut crate::base::Char16, + *mut u32, +) -> *mut crate::base::Char16}; + +#[repr(C)] +pub struct Protocol { + pub execute: Execute, + pub get_env: GetEnv, + pub set_env: SetEnv, + pub get_alias: GetAlias, + pub set_alias: SetAlias, + pub get_help_text: GetHelpText, + pub get_device_path_from_map: GetDevicePathFromMap, + pub get_map_from_device_path: GetMapFromDevicePath, + pub get_device_path_from_file_path: GetDevicePathFromFilePath, + pub get_file_path_from_device_path: GetFilePathFromDevicePath, + pub set_map: SetMap, + + pub get_cur_dir: GetCurDir, + pub set_cur_dir: SetCurDir, + pub open_file_list: OpenFileList, + pub free_file_list: FreeFileList, + pub remove_dup_in_file_list: RemoveDupInFileList, + + pub batch_is_active: BatchIsActive, + pub is_root_shell: IsRootShell, + pub enable_page_break: EnablePageBreak, + pub disable_page_break: DisablePageBreak, + pub get_page_break: GetPageBreak, + pub get_device_name: GetDeviceName, + + pub get_file_info: GetFileInfo, + pub set_file_info: SetFileInfo, + pub open_file_by_name: OpenFileByName, + pub close_file: CloseFile, + pub create_file: CreateFile, + pub read_file: ReadFile, + pub write_file: WriteFile, + pub delete_file: DeleteFile, + pub delete_file_by_name: DeleteFileByName, + pub get_file_position: GetFilePosition, + pub set_file_position: SetFilePosition, + pub flush_file: FlushFile, + pub find_files: FindFiles, + pub find_files_in_dir: FindFilesInDir, + pub get_file_size: GetFileSize, + + pub open_root: OpenRoot, + pub open_root_by_handle: OpenRootByHandle, + + pub execution_break: crate::base::Event, + + pub major_version: u32, + pub minor_version: u32, + pub register_guid_name: RegisterGuidName, + pub get_guid_name: GetGuidName, + pub get_guid_from_name: GetGuidFromName, + + // Shell 2.1 + pub get_env_ex: GetEnvEx, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell_dynamic_command.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_dynamic_command.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell_dynamic_command.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_dynamic_command.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +//! Shell Dynamic Command Protocol +//! +//! Defined in UEFI Shell Specification, Section 2.4 + +use super::{shell, shell_parameters}; + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3c7200e9, + 0x005f, + 0x4ea4, + 0x87, + 0xde, + &[0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3], +); + +pub type CommandHandler = eficall! {fn( + *mut Protocol, + *mut crate::system::SystemTable, + *mut shell_parameters::Protocol, + *mut shell::Protocol, +) -> crate::base::Status}; + +pub type CommandGetHelp = eficall! {fn( + *mut Protocol, + *mut crate::base::Char8, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub command_name: *mut crate::base::Char16, + pub handler: CommandHandler, + pub get_help: CommandGetHelp, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell_parameters.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_parameters.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/shell_parameters.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/shell_parameters.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +//! Shell Parameters Protocol +//! +//! Defined in the UEFI Shell Specification, Section 2.3. + +use super::shell; + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x752f3136, + 0x4e16, + 0x4fdc, + 0xa2, + 0x2a, + &[0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca], +); + +#[repr(C)] +pub struct Protocol { + pub argv: *mut *mut crate::base::Char16, + pub argc: usize, + pub std_in: shell::FileHandle, + pub std_out: shell::FileHandle, + pub std_err: shell::FileHandle, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_file_system.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_file_system.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_file_system.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_file_system.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +//! Simple File System Protocol +//! +//! Provides the `open_volume` function returning a file protocol representing the root directory +//! of a filesystem. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x964e5b22, + 0x6459, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +pub const REVISION: u64 = 0x0000000000010000u64; + +pub type ProtocolOpenVolume = eficall! {fn( + *mut Protocol, + *mut *mut crate::protocols::file::Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub open_volume: ProtocolOpenVolume, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_network.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_network.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_network.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_network.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,196 @@ +//! Simple Network Protocol +//! +//! The simple network protcol provides services to initialize a network interface, transmit +//! packets, receive packets, and close a network interface. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xa19832b9, + 0xac25, + 0x11d3, + 0x9a, + 0x2d, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub const REVISION: u64 = 0x0000000000010000u64; + +pub const MAX_MCAST_FILTER_CNT: usize = 16; + +pub const RECEIVE_UNICAST: u32 = 0x00000001u32; +pub const RECEIVE_MULTICAST: u32 = 0x00000002u32; +pub const RECEIVE_BROADCAST: u32 = 0x00000004u32; +pub const RECEIVE_PROMISCUOUS: u32 = 0x00000008u32; +pub const RECEIVE_PROMISCUOUS_MULTICAST: u32 = 0x00000010u32; + +pub const RECEIVE_INTERRUPT: u32 = 0x00000001u32; +pub const TRANSMIT_INTERRUPT: u32 = 0x00000002u32; +pub const COMMAND_INTERRUPT: u32 = 0x00000004u32; +pub const SOFTWARE_INTERRUPT: u32 = 0x000000008u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Mode { + pub state: u32, + pub hw_address_size: u32, + pub media_header_size: u32, + pub max_packet_size: u32, + pub nvram_size: u32, + pub nvram_access_size: u32, + pub receive_filter_mask: u32, + pub receive_filter_setting: u32, + pub max_mcast_filter_count: u32, + pub mcast_filter_count: u32, + pub mcast_filter: [crate::base::MacAddress; MAX_MCAST_FILTER_CNT], + pub current_address: crate::base::MacAddress, + pub broadcast_address: crate::base::MacAddress, + pub permanent_address: crate::base::MacAddress, + pub if_type: u8, + pub mac_address_changeable: crate::base::Boolean, + pub multiple_tx_supported: crate::base::Boolean, + pub media_present_supported: crate::base::Boolean, + pub media_present: crate::base::Boolean, +} + +pub type State = u32; + +pub const STOPPED: State = 0x00000000; +pub const STARTED: State = 0x00000001; +pub const INITIALIZED: State = 0x00000002; +pub const MAX_STATE: State = 0x00000003; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Statistics { + pub rx_total_frames: u64, + pub rx_good_frames: u64, + pub rx_undersize_frames: u64, + pub rx_oversize_frames: u64, + pub rx_dropped_frames: u64, + pub rx_unicast_frames: u64, + pub rx_broadcast_frames: u64, + pub rx_multicast_frames: u64, + pub rx_crc_error_frames: u64, + pub rx_total_bytes: u64, + pub tx_total_frames: u64, + pub tx_good_frames: u64, + pub tx_undersize_frames: u64, + pub tx_oversize_frames: u64, + pub tx_dropped_frames: u64, + pub tx_unicast_frames: u64, + pub tx_broadcast_frames: u64, + pub tx_multicast_frames: u64, + pub tx_crc_error_frames: u64, + pub tx_total_bytes: u64, + pub collisions: u64, + pub unsupported_protocol: u64, + pub rx_duplicated_frames: u64, + pub rx_decrypt_error_frames: u64, + pub tx_error_frames: u64, + pub tx_retry_frames: u64, +} + +pub type ProtocolStart = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolStop = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolInitialize = eficall! {fn( + *mut Protocol, + usize, + usize, +) -> crate::base::Status}; + +pub type ProtocolReset = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolShutdown = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolReceiveFilters = eficall! {fn( + *mut Protocol, + u32, + u32, + crate::base::Boolean, + usize, + *mut crate::base::MacAddress, +) -> crate::base::Status}; + +pub type ProtocolStationAddress = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::MacAddress, +) -> crate::base::Status}; + +pub type ProtocolStatistics = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut usize, + *mut Statistics, +) -> crate::base::Status}; + +pub type ProtocolMcastIpToMac = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::IpAddress, + *mut crate::base::MacAddress, +) -> crate::base::Status}; + +pub type ProtocolNvData = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + usize, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolGetStatus = eficall! {fn( + *mut Protocol, + *mut u32, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + usize, + usize, + *mut core::ffi::c_void, + *mut crate::base::MacAddress, + *mut crate::base::MacAddress, + *mut u16, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut usize, + *mut usize, + *mut core::ffi::c_void, + *mut crate::base::MacAddress, + *mut crate::base::MacAddress, + *mut u16, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub revision: u64, + pub start: ProtocolStart, + pub stop: ProtocolStop, + pub initialize: ProtocolInitialize, + pub reset: ProtocolReset, + pub shutdown: ProtocolShutdown, + pub receive_filters: ProtocolReceiveFilters, + pub station_address: ProtocolStationAddress, + pub statistics: ProtocolStatistics, + pub mcast_ip_to_mac: ProtocolMcastIpToMac, + pub nv_data: ProtocolNvData, + pub get_status: ProtocolGetStatus, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub wait_for_packet: crate::base::Event, + pub mode: *mut Mode, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +//! Simple Text Input Protocol +//! +//! The simple-text-input protocol defines how to read basic key-strokes. It is limited to +//! non-modifiers and lacks any detailed reporting. It is mostly useful for debugging and admin +//! interaction. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x387477c1, + 0x69c7, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct InputKey { + pub scan_code: u16, + pub unicode_char: crate::base::Char16, +} + +pub type ProtocolReset = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolReadKeyStroke = eficall! {fn( + *mut Protocol, + *mut InputKey, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub reset: ProtocolReset, + pub read_key_stroke: ProtocolReadKeyStroke, + pub wait_for_key: crate::base::Event, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input_ex.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input_ex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input_ex.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_input_ex.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +//! Extended Simple Text Input Protocol +//! +//! The simple-text-input-ex protocol extends the simple-text-input protocol by allowing more +//! details reporting about modifiers, etc. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xdd9e7534, + 0x7762, + 0x4698, + 0x8c, + 0x14, + &[0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa], +); + +pub const SHIFT_STATE_VALID: u32 = 0x80000000u32; +pub const RIGHT_SHIFT_PRESSED: u32 = 0x00000001u32; +pub const LEFT_SHIFT_PRESSED: u32 = 0x00000002u32; +pub const RIGHT_CONTROL_PRESSED: u32 = 0x00000004u32; +pub const LEFT_CONTROL_PRESSED: u32 = 0x00000008u32; +pub const RIGHT_ALT_PRESSED: u32 = 0x00000010u32; +pub const LEFT_ALT_PRESSED: u32 = 0x00000020u32; +pub const RIGHT_LOGO_PRESSED: u32 = 0x00000040u32; +pub const LEFT_LOGO_PRESSED: u32 = 0x00000080u32; +pub const MENU_KEY_PRESSED: u32 = 0x00000100u32; +pub const SYS_REQ_PRESSED: u32 = 0x00000200u32; + +pub const TOGGLE_STATE_VALID: u8 = 0x80u8; +pub const KEY_STATE_EXPOSED: u8 = 0x40u8; +pub const SCROLL_LOCK_ACTIVE: u8 = 0x01u8; +pub const NUM_LOCK_ACTIVE: u8 = 0x02u8; +pub const CAPS_LOCK_ACTIVE: u8 = 0x04u8; + +pub type KeyToggleState = u8; +pub type KeyNotifyFunction = eficall! {fn(*mut KeyData) -> crate::base::Status}; + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct KeyState { + pub key_shift_state: u32, + pub key_toggle_state: KeyToggleState, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct KeyData { + pub key: crate::protocols::simple_text_input::InputKey, + pub key_state: KeyState, +} + +pub type ProtocolReset = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolReadKeyStrokeEx = eficall! {fn( + *mut Protocol, + *mut KeyData, +) -> crate::base::Status}; + +pub type ProtocolSetState = eficall! {fn( + *mut Protocol, + *mut KeyToggleState, +) -> crate::base::Status}; + +pub type ProtocolRegisterKeyNotify = eficall! {fn( + *mut Protocol, + *mut KeyData, + KeyNotifyFunction, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type ProtocolUnregisterKeyNotify = eficall! {fn( + *mut Protocol, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub reset: ProtocolReset, + pub read_key_stroke_ex: ProtocolReadKeyStrokeEx, + pub wait_for_key_ex: crate::base::Event, + pub set_state: ProtocolSetState, + pub register_key_notify: ProtocolRegisterKeyNotify, + pub unregister_key_notify: ProtocolUnregisterKeyNotify, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_output.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_output.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_output.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/simple_text_output.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +//! Simple Text Output Protocol +//! +//! The simple-text-output protocol provides a simple way to print text on screen. It is modeled +//! around the old VGA-consoles, but does not carry all the old cruft. It expects a rectangular +//! text array and allows you to move the cursor around to write Unicode symbols to screen. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x387477c2, + 0x69c7, + 0x11d2, + 0x8e, + 0x39, + &[0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Mode { + pub max_mode: i32, + pub mode: i32, + pub attribute: i32, + pub cursor_column: i32, + pub cursor_row: i32, + pub cursor_visible: crate::base::Boolean, +} + +pub type ProtocolReset = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type ProtocolOutputString = eficall! {fn( + *mut Protocol, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type ProtocolTestString = eficall! {fn( + *mut Protocol, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type ProtocolQueryMode = eficall! {fn( + *mut Protocol, + usize, + *mut usize, + *mut usize, +) -> crate::base::Status}; + +pub type ProtocolSetMode = eficall! {fn( + *mut Protocol, + usize, +) -> crate::base::Status}; + +pub type ProtocolSetAttribute = eficall! {fn( + *mut Protocol, + usize, +) -> crate::base::Status}; + +pub type ProtocolClearScreen = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +pub type ProtocolSetCursorPosition = eficall! {fn( + *mut Protocol, + usize, + usize, +) -> crate::base::Status}; + +pub type ProtocolEnableCursor = eficall! {fn( + *mut Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub reset: ProtocolReset, + pub output_string: ProtocolOutputString, + pub test_string: ProtocolTestString, + pub query_mode: ProtocolQueryMode, + pub set_mode: ProtocolSetMode, + pub set_attribute: ProtocolSetAttribute, + pub clear_screen: ProtocolClearScreen, + pub set_cursor_position: ProtocolSetCursorPosition, + pub enable_cursor: ProtocolEnableCursor, + pub mode: *mut Mode, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/tcp4.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/tcp4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +//! Transmission Control Protocol version 4 +//! +//! It provides services to send and receive data streams. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x65530bc7, + 0xa359, + 0x410f, + 0xb0, + 0x10, + &[0x5a, 0xad, 0xc7, 0xec, 0x2b, 0x62], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x00720665, + 0x67eb, + 0x4a99, + 0xba, + 0xf7, + &[0xd3, 0xc3, 0x3a, 0x1c, 0x7c, 0xc9], +); + +pub type ConnectionState = u32; + +pub const STATE_CLOSED: ConnectionState = 0x00000000; +pub const STATE_LISTEN: ConnectionState = 0x00000001; +pub const STATE_SYN_SENT: ConnectionState = 0x00000002; +pub const STATE_SYN_RECEIVED: ConnectionState = 0x00000003; +pub const STATE_ESTABLISHED: ConnectionState = 0x00000004; +pub const STATE_FIN_WAIT1: ConnectionState = 0x00000005; +pub const STATE_FIN_WAIT2: ConnectionState = 0x00000006; +pub const STATE_CLOSING: ConnectionState = 0x00000007; +pub const STATE_TIME_WAIT: ConnectionState = 0x00000008; +pub const STATE_CLOSE_WAIT: ConnectionState = 0x00000009; +pub const STATE_LAST_ACK: ConnectionState = 0x0000000a; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub type_of_service: u8, + pub time_to_live: u8, + pub access_point: AccessPoint, + pub control_option: *mut r#Option, +} + +impl Default for ConfigData { + fn default() -> Self { + Self { + type_of_service: Default::default(), + time_to_live: Default::default(), + access_point: Default::default(), + control_option: core::ptr::null_mut(), + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct AccessPoint { + pub use_default_address: crate::base::Boolean, + pub station_address: crate::base::Ipv4Address, + pub subnet_mask: crate::base::Ipv4Address, + pub station_port: u16, + pub remote_address: crate::base::Ipv4Address, + pub remote_port: u16, + pub active_flag: crate::base::Boolean, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct r#Option { + pub receive_buffer_size: u32, + pub send_buffer_size: u32, + pub max_syn_back_log: u32, + pub connection_timeout: u32, + pub data_retries: u32, + pub fin_timeout: u32, + pub time_wait_timeout: u32, + pub keep_alive_probes: u32, + pub keep_alive_time: u32, + pub keep_alive_interval: u32, + pub enable_nagle: crate::base::Boolean, + pub enable_time_stamp: crate::base::Boolean, + pub enable_window_scaling: crate::base::Boolean, + pub enable_selective_ack: crate::base::Boolean, + pub enable_path_mtu_discovery: crate::base::Boolean, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConnectionToken { + pub completion_token: CompletionToken, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ListenToken { + pub completion_token: CompletionToken, + pub new_child_handle: crate::base::Handle, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IoToken { + pub completion_token: CompletionToken, + pub packet: IoTokenPacket, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IoTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ReceiveData { + pub urgent_flag: crate::base::Boolean, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TransmitData { + pub push: crate::base::Boolean, + pub urgent: crate::base::Boolean, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CloseToken { + pub completion_token: CompletionToken, + pub abort_on_close: crate::base::Boolean, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ConnectionState, + *mut ConfigData, + *mut crate::protocols::ip4::ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolRoutes = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, +) -> crate::base::Status}; + +pub type ProtocolConnect = eficall! {fn( + *mut Protocol, + *mut ConnectionToken, +) -> crate::base::Status}; + +pub type ProtocolAccept = eficall! {fn( + *mut Protocol, + *mut ListenToken, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolClose = eficall! {fn( + *mut Protocol, + *mut CloseToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub routes: ProtocolRoutes, + pub connect: ProtocolConnect, + pub accept: ProtocolAccept, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub close: ProtocolClose, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/tcp6.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp6.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/tcp6.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/tcp6.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,202 @@ +//! Transmission Control Protocol version 6 +//! +//! It provides services to send and receive data streams. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x46e44855, + 0xbd60, + 0x4ab7, + 0xab, + 0x0d, + &[0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xec20eb79, + 0x6c1a, + 0x4664, + 0x9a, + 0x0d, + &[0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct AccessPoint { + pub station_address: crate::base::Ipv6Address, + pub station_port: u16, + pub remote_address: crate::base::Ipv6Address, + pub remote_port: u16, + pub active_flag: crate::base::Boolean, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct r#Option { + pub receive_buffer_size: u32, + pub send_buffer_size: u32, + pub max_syn_back_log: u32, + pub connection_timeout: u32, + pub data_retries: u32, + pub fin_timeout: u32, + pub time_wait_timeout: u32, + pub keep_alive_probes: u32, + pub keep_alive_time: u32, + pub keep_alive_interval: u32, + pub enable_nagle: crate::base::Boolean, + pub enable_time_stamp: crate::base::Boolean, + pub enable_window_scaling: crate::base::Boolean, + pub enable_selective_ack: crate::base::Boolean, + pub enable_path_mtu_discovery: crate::base::Boolean, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub traffic_class: u8, + pub hop_limit: u8, + pub access_point: AccessPoint, + pub control_option: *mut r#Option, +} + +pub type ConnectionState = u32; + +pub const STATE_CLOSED: ConnectionState = 0x00000000; +pub const STATE_LISTEN: ConnectionState = 0x00000001; +pub const STATE_SYN_SENT: ConnectionState = 0x00000002; +pub const STATE_SYN_RECEIVED: ConnectionState = 0x00000003; +pub const STATE_ESTABLISHED: ConnectionState = 0x00000004; +pub const STATE_FIN_WAIT1: ConnectionState = 0x00000005; +pub const STATE_FIN_WAIT2: ConnectionState = 0x00000006; +pub const STATE_CLOSING: ConnectionState = 0x00000007; +pub const STATE_TIME_WAIT: ConnectionState = 0x00000008; +pub const STATE_CLOSE_WAIT: ConnectionState = 0x00000009; +pub const STATE_LAST_ACK: ConnectionState = 0x0000000a; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConnectionToken { + pub completion_token: CompletionToken, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ListenToken { + pub completion_token: CompletionToken, + pub new_child_handle: crate::base::Handle, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IoToken { + pub completion_token: CompletionToken, + pub packet: IoTokenPacket, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union IoTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ReceiveData { + pub urgent_flag: crate::base::Boolean, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TransmitData { + pub push: crate::base::Boolean, + pub urgent: crate::base::Boolean, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CloseToken { + pub completion_token: CompletionToken, + pub abort_on_close: crate::base::Boolean, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ConnectionState, + *mut ConfigData, + *mut crate::protocols::ip6::ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolConnect = eficall! {fn( + *mut Protocol, + *mut ConnectionToken, +) -> crate::base::Status}; + +pub type ProtocolAccept = eficall! {fn( + *mut Protocol, + *mut ListenToken, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut IoToken, +) -> crate::base::Status}; + +pub type ProtocolClose = eficall! {fn( + *mut Protocol, + *mut CloseToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub connect: ProtocolConnect, + pub accept: ProtocolAccept, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub close: ProtocolClose, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/timestamp.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/timestamp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/timestamp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/timestamp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +//! EFI Timestamp Protocol +//! +//! The Timestamp protocol provides a platform independent interface for +//! retrieving a high resolution timestamp counter. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xafbfde41, + 0x2e6e, + 0x4262, + 0xba, + 0x65, + &[0x62, 0xb9, 0x23, 0x6e, 0x54, 0x95], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct Properties { + pub frequency: u64, + pub end_value: u64, +} + +pub type ProtocolGetTimestamp = eficall! {fn() -> u64}; + +pub type ProtocolGetProperties = eficall! {fn( + *mut Properties, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_timestamp: ProtocolGetTimestamp, + pub get_properties: ProtocolGetProperties, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/udp4.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp4.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/udp4.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp4.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,151 @@ +//! User Datagram Protocol V4 +//! +//! It provides simple packet-oriented services to transmit and receive UDP packets. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x3ad9df29, + 0x4501, + 0x478d, + 0xb1, + 0xf8, + &[0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x83f01464, + 0x99bd, + 0x45e5, + 0xb3, + 0x83, + &[0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub accept_broadcast: crate::base::Boolean, + pub accept_promiscuous: crate::base::Boolean, + pub accept_any_port: crate::base::Boolean, + pub allow_duplicate_port: crate::base::Boolean, + pub type_of_service: u8, + pub time_to_live: u8, + pub do_not_fragment: crate::base::Boolean, + pub receive_timeout: u32, + pub transmit_timeout: u32, + pub use_default_address: crate::base::Boolean, + pub station_address: crate::base::Ipv4Address, + pub subnet_mask: crate::base::Ipv4Address, + pub station_port: u16, + pub remote_address: crate::base::Ipv4Address, + pub remote_port: u16, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct SessionData { + pub source_address: crate::base::Ipv4Address, + pub source_port: u16, + pub destination_address: crate::base::Ipv4Address, + pub destination_port: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ReceiveData { + pub time_stamp: crate::system::Time, + pub recycle_signal: crate::base::Event, + pub udp_session: SessionData, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct TransmitData { + pub udp_session_data: *mut SessionData, + pub gateway_address: *mut crate::base::Ipv4Address, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CompletionTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub packet: CompletionTokenPacket, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ConfigData, + *mut crate::protocols::ip4::ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolGroups = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv4Address, +) -> crate::base::Status}; + +pub type ProtocolRoutes = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, + *mut crate::base::Ipv4Address, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub groups: ProtocolGroups, + pub routes: ProtocolRoutes, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/udp6.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp6.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols/udp6.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols/udp6.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,137 @@ +//! User Datagram Protocol V6 +//! +//! It provides simple packet-oriented services to transmit and receive UDP packets. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x4f948815, + 0xb4b9, + 0x43cb, + 0x8a, + 0x33, + &[0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55], +); + +pub const SERVICE_BINDING_PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x66ed4721, + 0x3c98, + 0x4d3e, + 0x81, + 0xe3, + &[0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigData { + pub accept_promiscuous: crate::base::Boolean, + pub accept_any_port: crate::base::Boolean, + pub allow_duplicate_port: crate::base::Boolean, + pub traffic_class: u8, + pub hop_limit: u8, + pub receive_timeout: u32, + pub transmit_timeout: u32, + pub station_address: crate::base::Ipv6Address, + pub station_port: u16, + pub remote_address: crate::base::Ipv6Address, + pub remote_port: u16, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct SessionData { + pub source_address: crate::base::Ipv6Address, + pub source_port: u16, + pub destination_address: crate::base::Ipv6Address, + pub destination_port: u16, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct FragmentData { + pub fragment_length: u32, + pub fragment_buffer: *mut core::ffi::c_void, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ReceiveData { + pub time_stamp: crate::system::Time, + pub recycle_signal: crate::base::Event, + pub udp_session: SessionData, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct TransmitData { + pub udp_session_data: *mut SessionData, + pub data_length: u32, + pub fragment_count: u32, + pub fragment_table: [FragmentData; N], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CompletionTokenPacket { + pub rx_data: *mut ReceiveData, + pub tx_data: *mut TransmitData, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CompletionToken { + pub event: crate::base::Event, + pub status: crate::base::Status, + pub packet: CompletionTokenPacket, +} + +pub type ProtocolGetModeData = eficall! {fn( + *mut Protocol, + *mut ConfigData, + *mut crate::protocols::ip6::ModeData, + *mut crate::protocols::managed_network::ConfigData, + *mut crate::protocols::simple_network::Mode, +) -> crate::base::Status}; + +pub type ProtocolConfigure = eficall! {fn( + *mut Protocol, + *mut ConfigData, +) -> crate::base::Status}; + +pub type ProtocolGroups = eficall! {fn( + *mut Protocol, + crate::base::Boolean, + *mut crate::base::Ipv6Address, +) -> crate::base::Status}; + +pub type ProtocolTransmit = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolReceive = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolCancel = eficall! {fn( + *mut Protocol, + *mut CompletionToken, +) -> crate::base::Status}; + +pub type ProtocolPoll = eficall! {fn( + *mut Protocol, +) -> crate::base::Status}; + +#[repr(C)] +pub struct Protocol { + pub get_mode_data: ProtocolGetModeData, + pub configure: ProtocolConfigure, + pub groups: ProtocolGroups, + pub transmit: ProtocolTransmit, + pub receive: ProtocolReceive, + pub cancel: ProtocolCancel, + pub poll: ProtocolPoll, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/protocols.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/protocols.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +//! UEFI Protocols +//! +//! The UEFI Specification splits most of its non-core parts into separate protocols. They can +//! refer to each other, but their documentation and implementation is split apart. We provide +//! each protocol as a separate module, so it is clearly defined where a symbol belongs to. + +pub mod absolute_pointer; +pub mod block_io; +pub mod bus_specific_driver_override; +pub mod debug_support; +pub mod debugport; +pub mod decompress; +pub mod device_path; +pub mod device_path_from_text; +pub mod device_path_to_text; +pub mod device_path_utilities; +pub mod disk_io; +pub mod disk_io2; +pub mod driver_binding; +pub mod driver_diagnostics2; +pub mod driver_family_override; +pub mod file; +pub mod graphics_output; +pub mod hii_database; +pub mod hii_font; +pub mod hii_font_ex; +pub mod hii_package_list; +pub mod hii_string; +pub mod ip4; +pub mod ip6; +pub mod load_file; +pub mod load_file2; +pub mod loaded_image; +pub mod loaded_image_device_path; +pub mod managed_network; +pub mod memory_attribute; +pub mod mp_services; +pub mod pci_io; +pub mod platform_driver_override; +pub mod rng; +pub mod service_binding; +pub mod shell; +pub mod shell_dynamic_command; +pub mod shell_parameters; +pub mod simple_file_system; +pub mod simple_network; +pub mod simple_text_input; +pub mod simple_text_input_ex; +pub mod simple_text_output; +pub mod tcp4; +pub mod tcp6; +pub mod timestamp; +pub mod udp4; +pub mod udp6; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/system.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/system.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/system.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/system.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1130 @@ +//! UEFI System Integration +//! +//! This header defines the structures and types of the surrounding system of an UEFI application. +//! It contains the definitions of the system table, the runtime and boot services, as well as +//! common types. +//! +//! We do not document the behavior of each of these types and functions. They follow the UEFI +//! specification, which does a well-enough job of documenting each. This file just provides you +//! the rust definitions of each symbol and some limited hints on some pecularities. + +// +// Time Management +// +// UEFI time management is modeled around the EFI_TIME structure, which represents any arbitrary +// timestamp. The runtime and boot services provide helper functions to query and set the system +// time. +// + +pub const TIME_ADJUST_DAYLIGHT: u8 = 0x01u8; +pub const TIME_IN_DAYLIGHT: u8 = 0x02u8; + +pub const UNSPECIFIED_TIMEZONE: i16 = 0x07ffi16; + +// Cannot derive `Eq` etc. due to uninitialized `pad2` field. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct Time { + pub year: u16, + pub month: u8, + pub day: u8, + pub hour: u8, + pub minute: u8, + pub second: u8, + pub pad1: u8, + pub nanosecond: u32, + pub timezone: i16, + pub daylight: u8, + pub pad2: u8, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TimeCapabilities { + pub resolution: u32, + pub accuracy: u32, + pub sets_to_zero: crate::base::Boolean, +} + +// +// UEFI Variables +// +// UEFI systems provide a way to store global variables. These can be persistent or volatile. The +// variable store must be provided by the platform, but persistent storage might not be available. +// + +pub const VARIABLE_NON_VOLATILE: u32 = 0x00000001u32; +pub const VARIABLE_BOOTSERVICE_ACCESS: u32 = 0x00000002u32; +pub const VARIABLE_RUNTIME_ACCESS: u32 = 0x00000004u32; +pub const VARIABLE_HARDWARE_ERROR_RECORD: u32 = 0x00000008u32; +pub const VARIABLE_AUTHENTICATED_WRITE_ACCESS: u32 = 0x00000010u32; +pub const VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS: u32 = 0x00000020u32; +pub const VARIABLE_APPEND_WRITE: u32 = 0x00000040u32; +pub const VARIABLE_ENHANCED_AUTHENTICATED_ACCESS: u32 = 0x00000080u32; + +pub const VARIABLE_AUTHENTICATION_3_CERT_ID_SHA256: u32 = 0x1u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct VariableAuthentication3CertId { + pub r#type: u8, + pub id_size: u32, + pub id: [u8; N], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct VariableAuthentication { + pub monotonic_count: u64, + pub auth_info: [u8; N], // WIN_CERTIFICATE_UEFI_ID from PE/COFF +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct VariableAuthentication2 { + pub timestamp: Time, + pub auth_info: [u8; N], // WIN_CERTIFICATE_UEFI_ID from PE/COFF +} + +pub const VARIABLE_AUTHENTICATION_3_TIMESTAMP_TYPE: u32 = 0x1u32; +pub const VARIABLE_AUTHENTICATION_3_NONCE_TYPE: u32 = 0x2u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct VariableAuthentication3 { + pub version: u8, + pub r#type: u8, + pub metadata_size: u32, + pub flags: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct VariableAuthentication3Nonce { + pub nonce_size: u32, + pub nonce: [u8; N], +} + +pub const HARDWARE_ERROR_VARIABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x414E6BDD, + 0xE47B, + 0x47cc, + 0xB2, + 0x44, + &[0xBB, 0x61, 0x02, 0x0C, 0xF5, 0x16], +); + +// +// Virtual Mappings +// +// UEFI runs in an 1-to-1 mapping from virtual to physical addresses. But once you exit boot +// services, you can apply any address mapping you want, as long as you inform UEFI about it (or, +// alternatively, stop using the UEFI runtime services). +// + +pub const OPTIONAL_POINTER: u32 = 0x00000001u32; + +// +// System Reset +// +// UEFI provides access to firmware functions to reset the system. This includes a wide variety of +// different possible resets. +// + +pub type ResetType = u32; + +pub const RESET_COLD: ResetType = 0x00000000; +pub const RESET_WARM: ResetType = 0x00000001; +pub const RESET_SHUTDOWN: ResetType = 0x00000002; +pub const RESET_PLATFORM_SPECIFIC: ResetType = 0x00000003; + +// +// Update Capsules +// +// The process of firmware updates is generalized in UEFI. There are small blobs called capsules +// that you can push into the firmware to be run either immediately or on next reboot. +// + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CapsuleBlockDescriptorUnion { + pub data_block: crate::base::PhysicalAddress, + pub continuation_pointer: crate::base::PhysicalAddress, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CapsuleBlockDescriptor { + pub length: u64, + pub data: CapsuleBlockDescriptorUnion, +} + +pub const CAPSULE_FLAGS_PERSIST_ACROSS_RESET: u32 = 0x00010000u32; +pub const CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE: u32 = 0x00020000u32; +pub const CAPSULE_FLAGS_INITIATE_RESET: u32 = 0x00040000u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CapsuleHeader { + pub capsule_guid: crate::base::Guid, + pub header_size: u32, + pub flags: u32, + pub capsule_image_size: u32, +} + +pub const OS_INDICATIONS_BOOT_TO_FW_UI: u64 = 0x0000000000000001u64; +pub const OS_INDICATIONS_TIMESTAMP_REVOCATION: u64 = 0x0000000000000002u64; +pub const OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED: u64 = 0x0000000000000004u64; +pub const OS_INDICATIONS_FMP_CAPSULE_SUPPORTED: u64 = 0x0000000000000008u64; +pub const OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED: u64 = 0x0000000000000010u64; +pub const OS_INDICATIONS_START_OS_RECOVERY: u64 = 0x0000000000000020u64; +pub const OS_INDICATIONS_START_PLATFORM_RECOVERY: u64 = 0x0000000000000040u64; + +pub const CAPSULE_REPORT_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x39b68c46, + 0xf7fb, + 0x441b, + 0xb6, + 0xec, + &[0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CapsuleResultVariableHeader { + pub variable_total_size: u32, + pub reserved: u32, + pub capsule_guid: crate::base::Guid, + pub capsule_processed: Time, + pub capsule_status: crate::base::Status, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct CapsuleResultVariableFMP { + pub version: u16, + pub payload_index: u8, + pub update_image_index: u8, + pub update_image_type_id: crate::base::Guid, + pub capsule_file_name_and_target: [crate::base::Char16; N], +} + +// +// Tasks +// +// UEFI uses a simplified task model, and only ever runs on a single CPU. Usually, there is only +// one single task running on the system, which is the current execution. No interrupts are +// supported, other than timer interrupts. That is, all device management must be reliant on +// polling. +// +// You can, however, register callbacks to be run by the UEFI core. That is, either when execution +// is returned to the UEFI core, or when a timer interrupt fires, the scheduler will run the +// highest priority task next, interrupting the current task. You can use simple +// task-priority-levels (TPL) to adjust the priority of your callbacks and current task. +// + +pub const EVT_TIMER: u32 = 0x80000000u32; +pub const EVT_RUNTIME: u32 = 0x40000000u32; +pub const EVT_NOTIFY_WAIT: u32 = 0x00000100u32; +pub const EVT_NOTIFY_SIGNAL: u32 = 0x00000200u32; +pub const EVT_SIGNAL_EXIT_BOOT_SERVICES: u32 = 0x00000201u32; +pub const EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE: u32 = 0x60000202u32; + +pub type EventNotify = eficall! {fn(crate::base::Event, *mut core::ffi::c_void)}; + +pub const EVENT_GROUP_EXIT_BOOT_SERVICES: crate::base::Guid = crate::base::Guid::from_fields( + 0x27abf055, + 0xb1b8, + 0x4c26, + 0x80, + 0x48, + &[0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf], +); +pub const EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES: crate::base::Guid = crate::base::Guid::from_fields( + 0x8be0e274, + 0x3970, + 0x4b44, + 0x80, + 0xc5, + &[0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc], +); +pub const EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE: crate::base::Guid = crate::base::Guid::from_fields( + 0x13fa7698, + 0xc831, + 0x49c7, + 0x87, + 0xea, + &[0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96], +); +pub const EVENT_GROUP_MEMORY_MAP_CHANGE: crate::base::Guid = crate::base::Guid::from_fields( + 0x78bee926, + 0x692f, + 0x48fd, + 0x9e, + 0xdb, + &[0x1, 0x42, 0x2e, 0xf0, 0xd7, 0xab], +); +pub const EVENT_GROUP_READY_TO_BOOT: crate::base::Guid = crate::base::Guid::from_fields( + 0x7ce88fb3, + 0x4bd7, + 0x4679, + 0x87, + 0xa8, + &[0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b], +); +pub const EVENT_GROUP_AFTER_READY_TO_BOOT: crate::base::Guid = crate::base::Guid::from_fields( + 0x3a2a00ad, + 0x98b9, + 0x4cdf, + 0xa4, + 0x78, + &[0x70, 0x27, 0x77, 0xf1, 0xc1, 0x0b], +); +pub const EVENT_GROUP_RESET_SYSTEM: crate::base::Guid = crate::base::Guid::from_fields( + 0x62da6a56, + 0x13fb, + 0x485a, + 0xa8, + 0xda, + &[0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b], +); + +pub type TimerDelay = u32; + +pub const TIMER_CANCEL: TimerDelay = 0x00000000; +pub const TIMER_PERIODIC: TimerDelay = 0x00000001; +pub const TIMER_RELATIVE: TimerDelay = 0x00000002; + +pub const TPL_APPLICATION: crate::base::Tpl = 4; +pub const TPL_CALLBACK: crate::base::Tpl = 8; +pub const TPL_NOTIFY: crate::base::Tpl = 16; +pub const TPL_HIGH_LEVEL: crate::base::Tpl = 31; + +// +// Memory management +// +// The UEFI boot services provide you pool-allocation helpers to reserve memory. The region for +// each allocation can be selected by the caller, allowing to reserve memory that even survives +// beyond boot services. However, dynamic allocations can only performed via boot services, so no +// dynamic modifications can be done once you exit boot services. +// + +pub type AllocateType = u32; + +pub const ALLOCATE_ANY_PAGES: AllocateType = 0x00000000; +pub const ALLOCATE_MAX_ADDRESS: AllocateType = 0x00000001; +pub const ALLOCATE_ADDRESS: AllocateType = 0x00000002; + +pub type MemoryType = u32; + +pub const RESERVED_MEMORY_TYPE: MemoryType = 0x00000000; +pub const LOADER_CODE: MemoryType = 0x00000001; +pub const LOADER_DATA: MemoryType = 0x00000002; +pub const BOOT_SERVICES_CODE: MemoryType = 0x00000003; +pub const BOOT_SERVICES_DATA: MemoryType = 0x00000004; +pub const RUNTIME_SERVICES_CODE: MemoryType = 0x00000005; +pub const RUNTIME_SERVICES_DATA: MemoryType = 0x00000006; +pub const CONVENTIONAL_MEMORY: MemoryType = 0x00000007; +pub const UNUSABLE_MEMORY: MemoryType = 0x00000008; +pub const ACPI_RECLAIM_MEMORY: MemoryType = 0x00000009; +pub const ACPI_MEMORY_NVS: MemoryType = 0x0000000a; +pub const MEMORY_MAPPED_IO: MemoryType = 0x0000000b; +pub const MEMORY_MAPPED_IO_PORT_SPACE: MemoryType = 0x0000000c; +pub const PAL_CODE: MemoryType = 0x0000000d; +pub const PERSISTENT_MEMORY: MemoryType = 0x0000000e; +pub const UNACCEPTED_MEMORY_TYPE: MemoryType = 0x0000000f; + +pub const MEMORY_UC: u64 = 0x0000000000000001u64; +pub const MEMORY_WC: u64 = 0x0000000000000002u64; +pub const MEMORY_WT: u64 = 0x0000000000000004u64; +pub const MEMORY_WB: u64 = 0x0000000000000008u64; +pub const MEMORY_UCE: u64 = 0x0000000000000010u64; +pub const MEMORY_WP: u64 = 0x0000000000001000u64; +pub const MEMORY_RP: u64 = 0x0000000000002000u64; +pub const MEMORY_XP: u64 = 0x0000000000004000u64; +pub const MEMORY_NV: u64 = 0x0000000000008000u64; +pub const MEMORY_MORE_RELIABLE: u64 = 0x0000000000010000u64; +pub const MEMORY_RO: u64 = 0x0000000000020000u64; +pub const MEMORY_SP: u64 = 0x0000000000040000u64; +pub const MEMORY_CPU_CRYPTO: u64 = 0x0000000000080000u64; +pub const MEMORY_RUNTIME: u64 = 0x8000000000000000u64; +pub const MEMORY_ISA_VALID: u64 = 0x4000000000000000u64; +pub const MEMORY_ISA_MASK: u64 = 0x0FFFF00000000000u64; + +/// Mask of memory attributes that specify cacheability attributes. No symbol +/// is defined by the spec, but the attributes are annotated in the spec. Note +/// that `MEMORY_WP`, despite its name, is treated as cacheability attribute. +/// Use `MEMORY_RO` as replacement access attribute (see the spec for details). +pub const CACHE_ATTRIBUTE_MASK: u64 = + MEMORY_UC | MEMORY_WC | MEMORY_WT | MEMORY_WB | MEMORY_UCE | MEMORY_WP; + +/// Mask of memory attributes that specify access protection attributes. No +/// symbol is defined by the spec, but the attributes are annotated in the +/// spec. Note that `MEMORY_WP` is treated as cacheability attribute, and its +/// access protection functionality is replaced by `MEMORY_RO`. +pub const MEMORY_ACCESS_MASK: u64 = MEMORY_RP | MEMORY_XP | MEMORY_RO; + +/// Mask of memory attributes that specify properties of a memory region that +/// can be managed via the CPU architecture protocol. +pub const MEMORY_ATTRIBUTE_MASK: u64 = MEMORY_ACCESS_MASK | MEMORY_SP | MEMORY_CPU_CRYPTO; + +pub const MEMORY_DESCRIPTOR_VERSION: u32 = 0x00000001u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct MemoryDescriptor { + pub r#type: u32, + pub physical_start: crate::base::PhysicalAddress, + pub virtual_start: crate::base::VirtualAddress, + pub number_of_pages: u64, + pub attribute: u64, +} + +// +// Protocol Management +// +// The UEFI driver model provides ways to have bus-drivers, device-drivers, and applications as +// separate, independent entities. They use protocols to communicate, and handles to refer to +// common state. Drivers and devices can be registered dynamically at runtime, and can support +// hotplugging. +// + +pub type InterfaceType = u32; + +pub const NATIVE_INTERFACE: InterfaceType = 0x00000000; + +pub type LocateSearchType = u32; + +pub const ALL_HANDLES: LocateSearchType = 0x00000000; +pub const BY_REGISTER_NOTIFY: LocateSearchType = 0x00000001; +pub const BY_PROTOCOL: LocateSearchType = 0x00000002; + +pub const OPEN_PROTOCOL_BY_HANDLE_PROTOCOL: u32 = 0x00000001u32; +pub const OPEN_PROTOCOL_GET_PROTOCOL: u32 = 0x00000002u32; +pub const OPEN_PROTOCOL_TEST_PROTOCOL: u32 = 0x00000004u32; +pub const OPEN_PROTOCOL_BY_CHILD_CONTROLLER: u32 = 0x00000008u32; +pub const OPEN_PROTOCOL_BY_DRIVER: u32 = 0x00000010u32; +pub const OPEN_PROTOCOL_EXCLUSIVE: u32 = 0x00000020u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct OpenProtocolInformationEntry { + pub agent_handle: crate::base::Handle, + pub controller_handle: crate::base::Handle, + pub attributes: u32, + pub open_count: u32, +} + +// +// Configuration Tables +// +// The system table contains an array of auxiliary tables, indexed by their GUID, called +// configuration tables. Each table uses the generic ConfigurationTable structure as header. +// + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConfigurationTable { + pub vendor_guid: crate::base::Guid, + pub vendor_table: *mut core::ffi::c_void, +} + +pub const RT_PROPERTIES_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeb66918a, + 0x7eef, + 0x402a, + 0x84, + 0x2e, + &[0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9], +); + +pub const RT_PROPERTIES_TABLE_VERSION: u16 = 0x0001; + +pub const RT_SUPPORTED_GET_TIME: u32 = 0x0000001; +pub const RT_SUPPORTED_SET_TIME: u32 = 0x0000002; +pub const RT_SUPPORTED_GET_WAKEUP_TIME: u32 = 0x0000004; +pub const RT_SUPPORTED_SET_WAKEUP_TIME: u32 = 0x0000008; +pub const RT_SUPPORTED_GET_VARIABLE: u32 = 0x00000010; +pub const RT_SUPPORTED_GET_NEXT_VARIABLE_NAME: u32 = 0x00000020; +pub const RT_SUPPORTED_SET_VARIABLE: u32 = 0x00000040; +pub const RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP: u32 = 0x00000080; +pub const RT_SUPPORTED_CONVERT_POINTER: u32 = 0x00000100; +pub const RT_SUPPORTED_GET_NEXT_HIGH_MONOTONIC_COUNT: u32 = 0x00000200; +pub const RT_SUPPORTED_RESET_SYSTEM: u32 = 0x00000400; +pub const RT_SUPPORTED_UPDATE_CAPSULE: u32 = 0x00000800; +pub const RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES: u32 = 0x00001000; +pub const RT_SUPPORTED_QUERY_VARIABLE_INFO: u32 = 0x00002000; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct RtPropertiesTable { + pub version: u16, + pub length: u16, + pub runtime_services_supported: u32, +} + +pub const PROPERTIES_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x880aaca3, + 0x4adc, + 0x4a04, + 0x90, + 0x79, + &[0xb7, 0x47, 0x34, 0x8, 0x25, 0xe5], +); + +pub const PROPERTIES_TABLE_VERSION: u32 = 0x00010000u32; + +pub const PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA: u64 = 0x1u64; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct PropertiesTable { + pub version: u32, + pub length: u32, + pub memory_protection_attribute: u64, +} + +pub const MEMORY_ATTRIBUTES_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xdcfa911d, + 0x26eb, + 0x469f, + 0xa2, + 0x20, + &[0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20], +); + +pub const MEMORY_ATTRIBUTES_TABLE_VERSION: u32 = 0x00000001u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct MemoryAttributesTable { + pub version: u32, + pub number_of_entries: u32, + pub descriptor_size: u32, + pub reserved: u32, + pub entry: [MemoryDescriptor; N], +} + +pub const CONFORMANCE_PROFILES_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x36122546, + 0xf7e7, + 0x4c8f, + 0xbd, + 0x9b, + &[0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b], +); + +pub const CONFORMANCE_PROFILES_TABLE_VERSION: u16 = 0x0001; + +pub const CONFORMANCE_PROFILES_UEFI_SPEC_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x523c91af, + 0xa195, + 0x4382, + 0x81, + 0x8d, + &[0x29, 0x5f, 0xe4, 0x00, 0x64, 0x65], +); + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ConformanceProfilesTable { + pub version: u16, + pub number_of_profiles: u16, + pub conformance_profiles: [crate::base::Guid; N], +} + +// +// External Configuration Tables +// +// This lists the Guids of configuration tables of other industry standards, as listed in +// the UEFI specification. See each standard for details on the data included in each table. +// + +pub const ACPI_10_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeb9d2d30, + 0x2d88, + 0x11d3, + 0x9a, + 0x16, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub const ACPI_20_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x8868e871, + 0xe4f1, + 0x11d3, + 0xbc, + 0x22, + &[0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81], +); + +pub const DTB_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xb1b621d5, + 0xf19c, + 0x41a5, + 0x83, + 0x0b, + &[0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0], +); + +pub const JSON_CAPSULE_DATA_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x35e7a725, + 0x8dd2, + 0x4cac, + 0x80, + 0x11, + &[0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56], +); + +pub const JSON_CAPSULE_RESULT_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xdbc461c3, + 0xb3de, + 0x422a, + 0xb9, + 0xb4, + &[0x98, 0x86, 0xfd, 0x49, 0xa1, 0xe5], +); + +pub const JSON_CONFIG_DATA_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0x87367f87, + 0x1119, + 0x41ce, + 0xaa, + 0xec, + &[0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a], +); + +pub const MPS_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeb9d2d2f, + 0x2d88, + 0x11d3, + 0x9a, + 0x16, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub const SAL_SYSTEM_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeb9d2d32, + 0x2d88, + 0x11d3, + 0x9a, + 0x16, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub const SMBIOS_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xeb9d2d31, + 0x2d88, + 0x11d3, + 0x9a, + 0x16, + &[0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d], +); + +pub const SMBIOS3_TABLE_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xf2fd1544, + 0x9794, + 0x4a2c, + 0x99, + 0x2e, + &[0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94], +); + +// +// Global Tables +// +// UEFI uses no global state, so all access to UEFI internal state is done through vtables you get +// passed to your entry-point. The global entry is the system-table, which encorporates several +// sub-tables, including the runtime and boot service tables, and configuration tables (including +// vendor extensions). +// + +pub const SPECIFICATION_REVISION: u32 = SYSTEM_TABLE_REVISION; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct TableHeader { + pub signature: u64, + pub revision: u32, + pub header_size: u32, + pub crc32: u32, + pub reserved: u32, +} + +pub const RUNTIME_SERVICES_SIGNATURE: u64 = 0x56524553544e5552u64; // "RUNTSERV" +pub const RUNTIME_SERVICES_REVISION: u32 = SPECIFICATION_REVISION; + +pub type RuntimeGetTime = eficall! {fn( + *mut Time, + *mut TimeCapabilities, +) -> crate::base::Status}; + +pub type RuntimeSetTime = eficall! {fn( + *mut Time, +) -> crate::base::Status}; + +pub type RuntimeGetWakeupTime = eficall! {fn( + *mut crate::base::Boolean, + *mut crate::base::Boolean, + *mut Time, +) -> crate::base::Status}; + +pub type RuntimeSetWakeupTime = eficall! {fn( + crate::base::Boolean, + *mut Time, +) -> crate::base::Status}; + +pub type RuntimeSetVirtualAddressMap = eficall! {fn( + usize, + usize, + u32, + *mut MemoryDescriptor, +) -> crate::base::Status}; + +pub type RuntimeConvertPointer = eficall! {fn( + usize, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type RuntimeGetVariable = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Guid, + *mut u32, + *mut usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type RuntimeGetNextVariableName = eficall! {fn( + *mut usize, + *mut crate::base::Char16, + *mut crate::base::Guid, +) -> crate::base::Status}; + +pub type RuntimeSetVariable = eficall! {fn( + *mut crate::base::Char16, + *mut crate::base::Guid, + u32, + usize, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type RuntimeGetNextHighMonoCount = eficall! {fn( + *mut u32, +) -> crate::base::Status}; + +pub type RuntimeResetSystem = eficall! {fn( + ResetType, + crate::base::Status, + usize, + *mut core::ffi::c_void, +)}; + +pub type RuntimeUpdateCapsule = eficall! {fn( + *mut *mut CapsuleHeader, + usize, + crate::base::PhysicalAddress, +) -> crate::base::Status}; + +pub type RuntimeQueryCapsuleCapabilities = eficall! {fn( + *mut *mut CapsuleHeader, + usize, + *mut u64, + *mut ResetType, +) -> crate::base::Status}; + +pub type RuntimeQueryVariableInfo = eficall! {fn( + u32, + *mut u64, + *mut u64, + *mut u64, +) -> crate::base::Status}; + +#[repr(C)] +pub struct RuntimeServices { + pub hdr: TableHeader, + + pub get_time: RuntimeGetTime, + pub set_time: RuntimeSetTime, + pub get_wakeup_time: RuntimeGetWakeupTime, + pub set_wakeup_time: RuntimeSetWakeupTime, + + pub set_virtual_address_map: RuntimeSetVirtualAddressMap, + pub convert_pointer: RuntimeConvertPointer, + + pub get_variable: RuntimeGetVariable, + pub get_next_variable_name: RuntimeGetNextVariableName, + pub set_variable: RuntimeSetVariable, + + pub get_next_high_mono_count: RuntimeGetNextHighMonoCount, + pub reset_system: RuntimeResetSystem, + + pub update_capsule: RuntimeUpdateCapsule, + pub query_capsule_capabilities: RuntimeQueryCapsuleCapabilities, + pub query_variable_info: RuntimeQueryVariableInfo, +} + +pub const BOOT_SERVICES_SIGNATURE: u64 = 0x56524553544f4f42u64; // "BOOTSERV" +pub const BOOT_SERVICES_REVISION: u32 = SPECIFICATION_REVISION; + +pub type BootRaiseTpl = eficall! {fn( + crate::base::Tpl, +) -> crate::base::Tpl}; + +pub type BootRestoreTpl = eficall! {fn( + crate::base::Tpl, +)}; + +pub type BootAllocatePages = eficall! {fn( + AllocateType, + MemoryType, + usize, + *mut crate::base::PhysicalAddress, +) -> crate::base::Status}; + +pub type BootFreePages = eficall! {fn( + crate::base::PhysicalAddress, + usize, +) -> crate::base::Status}; + +pub type BootGetMemoryMap = eficall! {fn( + *mut usize, + *mut MemoryDescriptor, + *mut usize, + *mut usize, + *mut u32, +) -> crate::base::Status}; + +pub type BootAllocatePool = eficall! {fn( + MemoryType, + usize, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootFreePool = eficall! {fn( + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootCreateEvent = eficall! {fn( + u32, + crate::base::Tpl, + Option, + *mut core::ffi::c_void, + *mut crate::base::Event, +) -> crate::base::Status}; + +pub type BootSetTimer = eficall! {fn( + crate::base::Event, + TimerDelay, + u64, +) -> crate::base::Status}; + +pub type BootWaitForEvent = eficall! {fn( + usize, + *mut crate::base::Event, + *mut usize, +) -> crate::base::Status}; + +pub type BootSignalEvent = eficall! {fn( + crate::base::Event, +) -> crate::base::Status}; + +pub type BootCloseEvent = eficall! {fn( + crate::base::Event, +) -> crate::base::Status}; + +pub type BootCheckEvent = eficall! {fn( + crate::base::Event, +) -> crate::base::Status}; + +pub type BootInstallProtocolInterface = eficall! {fn( + *mut crate::base::Handle, + *mut crate::base::Guid, + InterfaceType, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootReinstallProtocolInterface = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + *mut core::ffi::c_void, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootUninstallProtocolInterface = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootHandleProtocol = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootRegisterProtocolNotify = eficall! {fn( + *mut crate::base::Guid, + crate::base::Event, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootLocateHandle = eficall! {fn( + LocateSearchType, + *mut crate::base::Guid, + *mut core::ffi::c_void, + *mut usize, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type BootLocateDevicePath = eficall! {fn( + *mut crate::base::Guid, + *mut *mut crate::protocols::device_path::Protocol, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type BootInstallConfigurationTable = eficall! {fn( + *mut crate::base::Guid, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootLoadImage = eficall! {fn( + crate::base::Boolean, + crate::base::Handle, + *mut crate::protocols::device_path::Protocol, + *mut core::ffi::c_void, + usize, + *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type BootStartImage = eficall! {fn( + crate::base::Handle, + *mut usize, + *mut *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type BootExit = eficall! {fn( + crate::base::Handle, + crate::base::Status, + usize, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type BootUnloadImage = eficall! {fn( + crate::base::Handle, +) -> crate::base::Status}; + +pub type BootExitBootServices = eficall! {fn( + crate::base::Handle, + usize, +) -> crate::base::Status}; + +pub type BootGetNextMonotonicCount = eficall! {fn( + *mut u64, +) -> crate::base::Status}; + +pub type BootStall = eficall! {fn( + usize, +) -> crate::base::Status}; + +pub type BootSetWatchdogTimer = eficall! {fn( + usize, + u64, + usize, + *mut crate::base::Char16, +) -> crate::base::Status}; + +pub type BootConnectController = eficall! {fn( + crate::base::Handle, + *mut crate::base::Handle, + *mut crate::protocols::device_path::Protocol, + crate::base::Boolean, +) -> crate::base::Status}; + +pub type BootDisconnectController = eficall! {fn( + crate::base::Handle, + crate::base::Handle, + crate::base::Handle, +) -> crate::base::Status}; + +pub type BootOpenProtocol = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + *mut *mut core::ffi::c_void, + crate::base::Handle, + crate::base::Handle, + u32, +) -> crate::base::Status}; + +pub type BootCloseProtocol = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + crate::base::Handle, + crate::base::Handle, +) -> crate::base::Status}; + +pub type BootOpenProtocolInformation = eficall! {fn( + crate::base::Handle, + *mut crate::base::Guid, + *mut *mut OpenProtocolInformationEntry, + *mut usize, +) -> crate::base::Status}; + +pub type BootProtocolsPerHandle = eficall! {fn( + crate::base::Handle, + *mut *mut *mut crate::base::Guid, + *mut usize, +) -> crate::base::Status}; + +pub type BootLocateHandleBuffer = eficall! {fn( + LocateSearchType, + *mut crate::base::Guid, + *mut core::ffi::c_void, + *mut usize, + *mut *mut crate::base::Handle, +) -> crate::base::Status}; + +pub type BootLocateProtocol = eficall! {fn( + *mut crate::base::Guid, + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootInstallMultipleProtocolInterfaces = eficall! {fn( + *mut crate::base::Handle, + // XXX: Actual definition is variadic. See eficall!{} for details. + *mut core::ffi::c_void, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootUninstallMultipleProtocolInterfaces = eficall! {fn( + crate::base::Handle, + // XXX: Actual definition is variadic. See eficall!{} for details. + *mut core::ffi::c_void, + *mut core::ffi::c_void, +) -> crate::base::Status}; + +pub type BootCalculateCrc32 = eficall! {fn( + *mut core::ffi::c_void, + usize, + *mut u32, +) -> crate::base::Status}; + +pub type BootCopyMem = eficall! {fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + usize, +)}; + +pub type BootSetMem = eficall! {fn( + *mut core::ffi::c_void, + usize, + u8, +)}; + +pub type BootCreateEventEx = eficall! {fn( + u32, + crate::base::Tpl, + Option, + *const core::ffi::c_void, + *const crate::base::Guid, + *mut crate::base::Event, +) -> crate::base::Status}; + +#[repr(C)] +pub struct BootServices { + pub hdr: TableHeader, + + pub raise_tpl: BootRaiseTpl, + pub restore_tpl: BootRestoreTpl, + + pub allocate_pages: BootAllocatePages, + pub free_pages: BootFreePages, + pub get_memory_map: BootGetMemoryMap, + pub allocate_pool: BootAllocatePool, + pub free_pool: BootFreePool, + + pub create_event: BootCreateEvent, + pub set_timer: BootSetTimer, + pub wait_for_event: BootWaitForEvent, + pub signal_event: BootSignalEvent, + pub close_event: BootCloseEvent, + pub check_event: BootCheckEvent, + + pub install_protocol_interface: BootInstallProtocolInterface, + pub reinstall_protocol_interface: BootReinstallProtocolInterface, + pub uninstall_protocol_interface: BootUninstallProtocolInterface, + pub handle_protocol: BootHandleProtocol, + pub reserved: *mut core::ffi::c_void, + pub register_protocol_notify: BootRegisterProtocolNotify, + pub locate_handle: BootLocateHandle, + pub locate_device_path: BootLocateDevicePath, + + pub install_configuration_table: BootInstallConfigurationTable, + + pub load_image: BootLoadImage, + pub start_image: BootStartImage, + pub exit: BootExit, + pub unload_image: BootUnloadImage, + pub exit_boot_services: BootExitBootServices, + + pub get_next_monotonic_count: BootGetNextMonotonicCount, + pub stall: BootStall, + pub set_watchdog_timer: BootSetWatchdogTimer, + + // 1.1+ + pub connect_controller: BootConnectController, + pub disconnect_controller: BootDisconnectController, + + pub open_protocol: BootOpenProtocol, + pub close_protocol: BootCloseProtocol, + pub open_protocol_information: BootOpenProtocolInformation, + + pub protocols_per_handle: BootProtocolsPerHandle, + pub locate_handle_buffer: BootLocateHandleBuffer, + pub locate_protocol: BootLocateProtocol, + pub install_multiple_protocol_interfaces: BootInstallMultipleProtocolInterfaces, + pub uninstall_multiple_protocol_interfaces: BootUninstallMultipleProtocolInterfaces, + + pub calculate_crc32: BootCalculateCrc32, + + pub copy_mem: BootCopyMem, + pub set_mem: BootSetMem, + + // 2.0+ + pub create_event_ex: BootCreateEventEx, +} + +pub const SYSTEM_TABLE_REVISION_2_70: u32 = (2 << 16) | (70); +pub const SYSTEM_TABLE_REVISION_2_60: u32 = (2 << 16) | (60); +pub const SYSTEM_TABLE_REVISION_2_50: u32 = (2 << 16) | (50); +pub const SYSTEM_TABLE_REVISION_2_40: u32 = (2 << 16) | (40); +pub const SYSTEM_TABLE_REVISION_2_31: u32 = (2 << 16) | (31); +pub const SYSTEM_TABLE_REVISION_2_30: u32 = (2 << 16) | (30); +pub const SYSTEM_TABLE_REVISION_2_20: u32 = (2 << 16) | (20); +pub const SYSTEM_TABLE_REVISION_2_10: u32 = (2 << 16) | (10); +pub const SYSTEM_TABLE_REVISION_2_00: u32 = (2 << 16) | (0); +pub const SYSTEM_TABLE_REVISION_1_10: u32 = (1 << 16) | (10); +pub const SYSTEM_TABLE_REVISION_1_02: u32 = (1 << 16) | (2); + +pub const SYSTEM_TABLE_SIGNATURE: u64 = 0x5453595320494249u64; // "IBI SYST" +pub const SYSTEM_TABLE_REVISION: u32 = SYSTEM_TABLE_REVISION_2_70; + +#[repr(C)] +pub struct SystemTable { + pub hdr: TableHeader, + pub firmware_vendor: *mut crate::base::Char16, + pub firmware_revision: u32, + + pub console_in_handle: crate::base::Handle, + pub con_in: *mut crate::protocols::simple_text_input::Protocol, + pub console_out_handle: crate::base::Handle, + pub con_out: *mut crate::protocols::simple_text_output::Protocol, + pub standard_error_handle: crate::base::Handle, + pub std_err: *mut crate::protocols::simple_text_output::Protocol, + + pub runtime_services: *mut RuntimeServices, + pub boot_services: *mut BootServices, + + pub number_of_table_entries: usize, + pub configuration_table: *mut ConfigurationTable, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/vendor/intel/console_control.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor/intel/console_control.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/vendor/intel/console_control.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor/intel/console_control.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +//! Console Control Protocol +//! +//! The console-control protocols allows modifying the behavior of the default +//! console device. It is supported by TianoCore and widely adopted. + +pub const PROTOCOL_GUID: crate::base::Guid = crate::base::Guid::from_fields( + 0xf42f7782, + 0x012e, + 0x4c12, + 0x99, + 0x56, + &[0x49, 0xf9, 0x43, 0x04, 0xf7, 0x21], +); + +pub type ScreenMode = u32; + +pub const SCREEN_TEXT: ScreenMode = 0x00000000; +pub const SCREEN_GRAPHICS: ScreenMode = 0x00000001; +pub const SCREEN_MAX_VALUE: ScreenMode = 0x00000002; + +#[repr(C)] +pub struct Protocol { + pub get_mode: eficall! {fn( + *mut Protocol, + *mut ScreenMode, + *mut crate::base::Boolean, + *mut crate::base::Boolean, + ) -> crate::base::Status}, + pub set_mode: eficall! {fn( + *mut Protocol, + ScreenMode, + ) -> crate::base::Status}, + pub lock_std_in: eficall! {fn( + *mut Protocol, + *mut crate::base::Char16, + ) -> crate::base::Status}, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/vendor.rs clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor.rs --- clamav-1.4.3+dfsg/.cargo/vendor/r-efi/src/vendor.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/r-efi/src/vendor.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +//! UEFI Vendor Protocols +//! +//! Many vendor protocols are not part of the official specification. But we +//! still allow importing them here, so we have a central place to collect +//! them. Note that we separate them by vendor-name, which is not the best +//! name-space but should be acceptible. + +pub mod intel { + pub mod console_control; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"28370f46fa1ba5a47467f6229692e80a312ad1336f93b9b6ee0330b9596b1408","CHANGELOG.md":"3a56b7876eff2d0dd9d0975844b251236af71e385f413ac06c241e6996038cd7","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.lock":"59ca872218694f45284dfc098dddaf38b2a3d7cf91aff668984c53193471b086","Cargo.toml":"2af4bbbb05a303fb72404597e803b64cb081d03b5aee2098490567afd54a2358","Cargo.toml.orig":"d05b11fa9efee1d69cb375e11f0e505a5a7fb86e9a3637ee6b2d0a30570210b1","LICENSE-APACHE":"35242e7a83f69875e6edeff02291e688c97caafe2f8902e4e19b49d3e78b4cab","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"b7f58a24b8d2107a2ed4ce2e392ecf20c62430bf75331c077b900a2e51451ae5","src/distr/bernoulli.rs":"8e11cf18fd021abeac46675def322bd004839c830241ae3ea6143fe809ce64d1","src/distr/distribution.rs":"3f5904afd9d0f7492b1746b9cc45759a477a5dd2cc5802dbc4f09f1391eaeb96","src/distr/float.rs":"486f2c8ead197d283593689e7b9026626ca83ab3fe7ebf9a89c8e701a4767c2e","src/distr/integer.rs":"69ac205b6fed57ae09e2f8f1b15ae3d2049b85874bc4da3f246a18188b42d8ea","src/distr/mod.rs":"de901e07e7ee11f4375a02fff29d77ac26d1df2721214b162dafcec1e47b2d67","src/distr/other.rs":"b98748667af9415d65c8eaa6e51aee2d42a1d31c7970c22be7491adcb18a45a7","src/distr/slice.rs":"e29eb71308f30aee13a4b1454da1ab70c2cc307738445172a27246df2dfa75ce","src/distr/uniform.rs":"04efcc061e1904b824e3feb68541c4e8259a46ecd2c118af6fb383b3ad37f73c","src/distr/uniform_float.rs":"62271f5fb4be087538d1fae743ad95027c66589740762521f97d20d358463d6b","src/distr/uniform_int.rs":"1fb3ade156995a45b33853c04eb28c4031d7b0f73e731145182adb69de0c5880","src/distr/uniform_other.rs":"2e8eb7e10b3a052b784da842c0f1999d6ec73acb1eec849fb243ee44d6c3e8f1","src/distr/utils.rs":"a631940e728257c9b0cb753bc64fa631958c92ce52d5b2265c7ed06a46567b8f","src/distr/weighted/mod.rs":"52379f09ea06c8ac54bdb4ecaed93fd7fc08f85866b5e3fcb4e40d0f1576bdfe","src/distr/weighted/weighted_index.rs":"b4559037354bcb9e0b1eab569c867dd70053de382232c7ed4d9aef3d5b049003","src/lib.rs":"2e3f24aa60f62454780ea30a5652568518f97d7c5e2884adf632c60a38ac3352","src/prelude.rs":"ba69a78b5ebf3f7acb648ee57b8a8aa5403868852e6da082e8d87869d9dd18ce","src/rng.rs":"19a29d58ea169c50ae7fea0a941c405e4a8f3a9b2ac0dc0edd9f7a55e9431703","src/rngs/mock.rs":"330e6d7d7f30c6c9f6d64fe3f3a493b6c9574b075599b34b4871ebd4a9061015","src/rngs/mod.rs":"3868d87e88892a30ae0a8f2cbafdca299cea02d2aa6b3589300751cd8840a530","src/rngs/reseeding.rs":"23b45039f4184c556db85154a9e564aa6c14f55ea03276a0f4fd27f0a22d6347","src/rngs/small.rs":"d043d5c8f11aa8c5e9f8cbdaf7812486a1ccd64133a0721b8bf7d0f2097b651a","src/rngs/std.rs":"7d804c97f1633fc0928de4ceb77292e8b3f630158a4922ee82d0dd6633bcfcc0","src/rngs/thread.rs":"4f8b9472d0140d4d729b8188f73849acca5d45967992ca6e3aec58b95c524fad","src/rngs/xoshiro128plusplus.rs":"4d5dcad38c9126ea133055d49953549e50063a1f8385e05b9434911358c2fcca","src/rngs/xoshiro256plusplus.rs":"3f386364f569f5b2dc7fb8f5b58152e075abeefb2ad5af86f715657f2bece0fd","src/seq/coin_flipper.rs":"db57ebb4679144df94a6714d3fb1a9b5cb3dae7355d337d98ebc8dafbcf959c3","src/seq/increasing_uniform.rs":"73b1bf2b30c4e5972f2e902dbb30b90518006bae7eb2628d1ab2547eaeca8ea3","src/seq/index.rs":"d4f80b1dcb643cbec7caf8bf36d6dabd9c65d2db39bbf0b62d839aea79c553e1","src/seq/iterator.rs":"e19443f5ca4cd02d9cad97706626cc3e5efe9bc21c0c578d08d1edb75f34406c","src/seq/mod.rs":"04511fff0b199d84c6ff2ca7a394ad87197bcf6a9f2ba4fa2d139dae63f64913","src/seq/slice.rs":"8212a23bbc284b74b981ef8d5fc177c460926415f9d747a5a127453b7fa0f9e2"},"package":"6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "98473ee6f9b44eb85154b59b67adade7f2a9b8a1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/rand/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,822 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). + +You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. + +## [0.9.2 — 2025-07-20] +### Deprecated +- Deprecate `rand::rngs::mock` module and `StepRng` generator (#1634) + +### Additions +- Enable `WeightedIndex` (de)serialization (#1646) + +## [0.9.1] - 2025-04-17 +### Security and unsafe +- Revise "not a crypto library" policy again (#1565) +- Remove `zerocopy` dependency from `rand` (#1579) + +### Fixes +- Fix feature `simd_support` for recent nightly rust (#1586) + +### Changes +- Allow `fn rand::seq::index::sample_weighted` and `fn IndexedRandom::choose_multiple_weighted` to return fewer than `amount` results (#1623), reverting an undocumented change (#1382) to the previous release. + +### Additions +- Add `rand::distr::Alphabetic` distribution. (#1587) +- Re-export `rand_core` (#1604) + +## [0.9.0] - 2025-01-27 +### Security and unsafe +- Policy: "rand is not a crypto library" (#1514) +- Remove fork-protection from `ReseedingRng` and `ThreadRng`. Instead, it is recommended to call `ThreadRng::reseed` on fork. (#1379) +- Use `zerocopy` to replace some `unsafe` code (#1349, #1393, #1446, #1502) + +### Dependencies +- Bump the MSRV to 1.63.0 (#1207, #1246, #1269, #1341, #1416, #1536); note that 1.60.0 may work for dependents when using `--ignore-rust-version` +- Update to `rand_core` v0.9.0 (#1558) + +### Features +- Support `std` feature without `getrandom` or `rand_chacha` (#1354) +- Enable feature `small_rng` by default (#1455) +- Remove implicit feature `rand_chacha`; use `std_rng` instead. (#1473) +- Rename feature `serde1` to `serde` (#1477) +- Rename feature `getrandom` to `os_rng` (#1537) +- Add feature `thread_rng` (#1547) + +### API changes: rand_core traits +- Add fn `RngCore::read_adapter` implementing `std::io::Read` (#1267) +- Add trait `CryptoBlockRng: BlockRngCore`; make `trait CryptoRng: RngCore` (#1273) +- Add traits `TryRngCore`, `TryCryptoRng` (#1424, #1499) +- Rename `fn SeedableRng::from_rng` -> `try_from_rng` and add infallible variant `fn from_rng` (#1424) +- Rename `fn SeedableRng::from_entropy` -> `from_os_rng` and add fallible variant `fn try_from_os_rng` (#1424) +- Add bounds `Clone` and `AsRef` to associated type `SeedableRng::Seed` (#1491) + +### API changes: Rng trait and top-level fns +- Rename fn `rand::thread_rng()` to `rand::rng()` and remove from the prelude (#1506) +- Remove fn `rand::random()` from the prelude (#1506) +- Add top-level fns `random_iter`, `random_range`, `random_bool`, `random_ratio`, `fill` (#1488) +- Re-introduce fn `Rng::gen_iter` as `random_iter` (#1305, #1500) +- Rename fn `Rng::gen` to `random` to avoid conflict with the new `gen` keyword in Rust 2024 (#1438) +- Rename fns `Rng::gen_range` to `random_range`, `gen_bool` to `random_bool`, `gen_ratio` to `random_ratio` (#1505) +- Annotate panicking methods with `#[track_caller]` (#1442, #1447) + +### API changes: RNGs +- Fix `::Seed` size to 256 bits (#1455) +- Remove first parameter (`rng`) of `ReseedingRng::new` (#1533) + +### API changes: Sequences +- Split trait `SliceRandom` into `IndexedRandom`, `IndexedMutRandom`, `SliceRandom` (#1382) +- Add `IndexedRandom::choose_multiple_array`, `index::sample_array` (#1453, #1469) + +### API changes: Distributions: renames +- Rename module `rand::distributions` to `rand::distr` (#1470) +- Rename distribution `Standard` to `StandardUniform` (#1526) +- Move `distr::Slice` -> `distr::slice::Choose`, `distr::EmptySlice` -> `distr::slice::Empty` (#1548) +- Rename trait `distr::DistString` -> `distr::SampleString` (#1548) +- Rename `distr::DistIter` -> `distr::Iter`, `distr::DistMap` -> `distr::Map` (#1548) + +### API changes: Distributions +- Relax `Sized` bound on `Distribution for &D` (#1278) +- Remove impl of `Distribution>` for `StandardUniform` (#1526) +- Let distribution `StandardUniform` support all `NonZero*` types (#1332) +- Fns `{Uniform, UniformSampler}::{new, new_inclusive}` return a `Result` (instead of potentially panicking) (#1229) +- Distribution `Uniform` implements `TryFrom` instead of `From` for ranges (#1229) +- Add `UniformUsize` (#1487) +- Remove support for generating `isize` and `usize` values with `StandardUniform`, `Uniform` (except via `UniformUsize`) and `Fill` and usage as a `WeightedAliasIndex` weight (#1487) +- Add impl `DistString` for distributions `Slice` and `Uniform` (#1315) +- Add fn `Slice::num_choices` (#1402) +- Add fn `p()` for distribution `Bernoulli` to access probability (#1481) + +### API changes: Weighted distributions +- Add `pub` module `rand::distr::weighted`, moving `WeightedIndex` there (#1548) +- Add trait `weighted::Weight`, allowing `WeightedIndex` to trap overflow (#1353) +- Add fns `weight, weights, total_weight` to distribution `WeightedIndex` (#1420) +- Rename enum `WeightedError` to `weighted::Error`, revising variants (#1382) and mark as `#[non_exhaustive]` (#1480) + +### API changes: SIMD +- Switch to `std::simd`, expand SIMD & docs (#1239) + +### Reproducibility-breaking changes +- Make `ReseedingRng::reseed` discard remaining data from the last block generated (#1379) +- Change fn `SmallRng::seed_from_u64` implementation (#1203) +- Allow `UniformFloat::new` samples and `UniformFloat::sample_single` to yield `high` (#1462) +- Fix portability of distribution `Slice` (#1469) +- Make `Uniform` for `usize` portable via `UniformUsize` (#1487) +- Fix `IndexdRandom::choose_multiple_weighted` for very small seeds and optimize for large input length / low memory (#1530) + +### Reproducibility-breaking optimisations +- Optimize fn `sample_floyd`, affecting output of `rand::seq::index::sample` and `rand::seq::SliceRandom::choose_multiple` (#1277) +- New, faster algorithms for `IteratorRandom::choose` and `choose_stable` (#1268) +- New, faster algorithms for `SliceRandom::shuffle` and `partial_shuffle` (#1272) +- Optimize distribution `Uniform`: use Canon's method (single sampling) / Lemire's method (distribution sampling) for faster sampling (breaks value stability; #1287) +- Optimize fn `sample_single_inclusive` for floats (+~20% perf) (#1289) + +### Other optimisations +- Improve `SmallRng` initialization performance (#1482) +- Optimise SIMD widening multiply (#1247) + +### Other +- Add `Cargo.lock.msrv` file (#1275) +- Reformat with `rustfmt` and enforce (#1448) +- Apply Clippy suggestions and enforce (#1448, #1474) +- Move all benchmarks to new `benches` crate (#1329, #1439) and migrate to Criterion (#1490) + +### Documentation +- Improve `ThreadRng` related docs (#1257) +- Docs: enable experimental `--generate-link-to-definition` feature (#1327) +- Better doc of crate features, use `doc_auto_cfg` (#1411, #1450) + +## [0.8.5] - 2021-08-20 +### Fixes +- Fix build on non-32/64-bit architectures (#1144) +- Fix "min_const_gen" feature for `no_std` (#1173) +- Check `libc::pthread_atfork` return value with panic on error (#1178) +- More robust reseeding in case `ReseedingRng` is used from a fork handler (#1178) +- Fix nightly: remove unused `slice_partition_at_index` feature (#1215) +- Fix nightly + `simd_support`: update `packed_simd` (#1216) + +### Rngs +- `StdRng`: Switch from HC128 to ChaCha12 on emscripten (#1142). + We now use ChaCha12 on all platforms. + +### Documentation +- Added docs about rand's use of const generics (#1150) +- Better random chars example (#1157) + + +## [0.8.4] - 2021-06-15 +### Additions +- Use const-generics to support arrays of all sizes (#1104) +- Implement `Clone` and `Copy` for `Alphanumeric` (#1126) +- Add `Distribution::map` to derive a distribution using a closure (#1129) +- Add `Slice` distribution (#1107) +- Add `DistString` trait with impls for `Standard` and `Alphanumeric` (#1133) + +### Other +- Reorder asserts in `Uniform` float distributions for easier debugging of non-finite arguments + (#1094, #1108) +- Add range overflow check in `Uniform` float distributions (#1108) +- Deprecate `rngs::adapter::ReadRng` (#1130) + +## [0.8.3] - 2021-01-25 +### Fixes +- Fix `no-std` + `alloc` build by gating `choose_multiple_weighted` on `std` (#1088) + +## [0.8.2] - 2021-01-12 +### Fixes +- Fix panic in `UniformInt::sample_single_inclusive` and `Rng::gen_range` when + providing a full integer range (eg `0..=MAX`) (#1087) + +## [0.8.1] - 2020-12-31 +### Other +- Enable all stable features in the playground (#1081) + +## [0.8.0] - 2020-12-18 +### Platform support +- The minimum supported Rust version is now 1.36 (#1011) +- `getrandom` updated to v0.2 (#1041) +- Remove `wasm-bindgen` and `stdweb` feature flags. For details of WASM support, + see the [getrandom documentation](https://docs.rs/getrandom/latest). (#948) +- `ReadRng::next_u32` and `next_u64` now use little-Endian conversion instead + of native-Endian, affecting results on Big-Endian platforms (#1061) +- The `nightly` feature no longer implies the `simd_support` feature (#1048) +- Fix `simd_support` feature to work on current nightlies (#1056) + +### Rngs +- `ThreadRng` is no longer `Copy` to enable safe usage within thread-local destructors (#1035) +- `gen_range(a, b)` was replaced with `gen_range(a..b)`. `gen_range(a..=b)` is + also supported. Note that `a` and `b` can no longer be references or SIMD types. (#744, #1003) +- Replace `AsByteSliceMut` with `Fill` and add support for `[bool], [char], [f32], [f64]` (#940) +- Restrict `rand::rngs::adapter` to `std` (#1027; see also #928) +- `StdRng`: add new `std_rng` feature flag (enabled by default, but might need + to be used if disabling default crate features) (#948) +- `StdRng`: Switch from ChaCha20 to ChaCha12 for better performance (#1028) +- `SmallRng`: Replace PCG algorithm with xoshiro{128,256}++ (#1038) + +### Sequences +- Add `IteratorRandom::choose_stable` as an alternative to `choose` which does + not depend on size hints (#1057) +- Improve accuracy and performance of `IteratorRandom::choose` (#1059) +- Implement `IntoIterator` for `IndexVec`, replacing the `into_iter` method (#1007) +- Add value stability tests for `seq` module (#933) + +### Misc +- Support `PartialEq` and `Eq` for `StdRng`, `SmallRng` and `StepRng` (#979) +- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974) +- Drop some unsafe code (#962, #963, #1011) +- Reduce packaged crate size (#983) +- Migrate to GitHub Actions from Travis+AppVeyor (#1073) + +### Distributions +- `Alphanumeric` samples bytes instead of chars (#935) +- `Uniform` now supports `char`, enabling `rng.gen_range('A'..='Z')` (#1068) +- Add `UniformSampler::sample_single_inclusive` (#1003) + +#### Weighted sampling +- Implement weighted sampling without replacement (#976, #1013) +- `rand::distributions::alias_method::WeightedIndex` was moved to `rand_distr::WeightedAliasIndex`. + The simpler alternative `rand::distribution::WeightedIndex` remains. (#945) +- Improve treatment of rounding errors in `WeightedIndex::update_weights` (#956) +- `WeightedIndex`: return error on NaN instead of panic (#1005) + +### Documentation +- Document types supported by `random` (#994) +- Document notes on password generation (#995) +- Note that `SmallRng` may not be the best choice for performance and in some + other cases (#1038) +- Use `doc(cfg)` to annotate feature-gated items (#1019) +- Adjust README (#1065) + +## [0.7.3] - 2020-01-10 +### Fixes +- The `Bernoulli` distribution constructors now reports an error on NaN and on + `denominator == 0`. (#925) +- Use `std::sync::Once` to register fork handler, avoiding possible atomicity violation (#928) +- Fix documentation on the precision of generated floating-point values + +### Changes +- Unix: make libc dependency optional; only use fork protection with std feature (#928) + +### Additions +- Implement `std::error::Error` for `BernoulliError` (#919) + +## [0.7.2] - 2019-09-16 +### Fixes +- Fix dependency on `rand_core` 0.5.1 (#890) + +### Additions +- Unit tests for value stability of distributions added (#888) + +## [0.7.1] - 2019-09-13 +### Yanked +This release was yanked since it depends on `rand_core::OsRng` added in 0.5.1 +but specifies a dependency on version 0.5.0 (#890), causing a broken builds +when updating from `rand 0.7.0` without also updating `rand_core`. + +### Fixes +- Fix `no_std` behaviour, appropriately enable c2-chacha's `std` feature (#844) +- `alloc` feature in `no_std` is available since Rust 1.36 (#856) +- Fix or squelch issues from Clippy lints (#840) + +### Additions +- Add a `no_std` target to CI to continuously evaluate `no_std` status (#844) +- `WeightedIndex`: allow adjusting a sub-set of weights (#866) + +## [0.7.0] - 2019-06-28 + +### Fixes +- Fix incorrect pointer usages revealed by Miri testing (#780, #781) +- Fix (tiny!) bias in `Uniform` for 8- and 16-bit ints (#809) + +### Crate +- Bumped MSRV (min supported Rust version) to 1.32.0 +- Updated to Rust Edition 2018 (#823, #824) +- Removed dependence on `rand_xorshift`, `rand_isaac`, `rand_jitter` crates (#759, #765) +- Remove dependency on `winapi` (#724) +- Removed all `build.rs` files (#824) +- Removed code already deprecated in version 0.6 (#757) +- Removed the serde1 feature (It's still available for backwards compatibility, but it does not do anything. #830) +- Many documentation changes + +### rand_core +- Updated to `rand_core` 0.5.0 +- `Error` type redesigned with new API (#800) +- Move `from_entropy` method to `SeedableRng` and remove `FromEntropy` (#800) +- `SeedableRng::from_rng` is now expected to be value-stable (#815) + +### Standard RNGs +- OS interface moved from `rand_os` to new `getrandom` crate (#765, [getrandom](https://github.com/rust-random/getrandom)) +- Use ChaCha for `StdRng` and `ThreadRng` (#792) +- Feature-gate `SmallRng` (#792) +- `ThreadRng` now supports `Copy` (#758) +- Deprecated `EntropyRng` (#765) +- Enable fork protection of ReseedingRng without `std` (#724) + +### Distributions +- Many distributions have been moved to `rand_distr` (#761) +- `Bernoulli::new` constructor now returns a `Result` (#803) +- `Distribution::sample_iter` adjusted for more flexibility (#758) +- Added `distributions::weighted::alias_method::WeightedIndex` for `O(1)` sampling (#692) +- Support sampling `NonZeroU*` types with the `Standard` distribution (#728) +- Optimised `Binomial` distribution sampling (#735, #740, #752) +- Optimised SIMD float sampling (#739) + +### Sequences +- Make results portable across 32- and 64-bit by using `u32` samples for `usize` where possible (#809) + +## [0.6.5] - 2019-01-28 +### Crates +- Update `rand_core` to 0.4 (#703) +- Move `JitterRng` to its own crate (#685) +- Add a wasm-bindgen test crate (#696) + +### Platforms +- Fuchsia: Replaced fuchsia-zircon with fuchsia-cprng + +### Doc +- Use RFC 1946 for doc links (#691) +- Fix some doc links and notes (#711) + +## [0.6.4] - 2019-01-08 +### Fixes +- Move wasm-bindgen shims to correct crate (#686) +- Make `wasm32-unknown-unknown` compile but fail at run-time if missing bindingsg (#686) + +## [0.6.3] - 2019-01-04 +### Fixes +- Make the `std` feature require the optional `rand_os` dependency (#675) +- Re-export the optional WASM dependencies of `rand_os` from `rand` to avoid breakage (#674) + +## [0.6.2] - 2019-01-04 +### Additions +- Add `Default` for `ThreadRng` (#657) +- Move `rngs::OsRng` to `rand_os` sub-crate; clean up code; use as dependency (#643) ##BLOCKER## +- Add `rand_xoshiro` sub-crate, plus benchmarks (#642, #668) + +### Fixes +- Fix bias in `UniformInt::sample_single` (#662) +- Use `autocfg` instead of `rustc_version` for rustc version detection (#664) +- Disable `i128` and `u128` if the `target_os` is `emscripten` (#671: work-around Emscripten limitation) +- CI fixes (#660, #671) + +### Optimisations +- Optimise memory usage of `UnitCircle` and `UnitSphereSurface` distributions (no PR) + +## [0.6.1] - 2018-11-22 +- Support sampling `Duration` also for `no_std` (only since Rust 1.25) (#649) +- Disable default features of `libc` (#647) + +## [0.6.0] - 2018-11-14 + +### Project organisation +- Rand has moved from [rust-lang-nursery](https://github.com/rust-lang-nursery/rand) + to [rust-random](https://github.com/rust-random/rand)! (#578) +- Created [The Rust Random Book](https://rust-random.github.io/book/) + ([source](https://github.com/rust-random/book)) +- Update copyright and licence notices (#591, #611) +- Migrate policy documentation from the wiki (#544) + +### Platforms +- Add fork protection on Unix (#466) +- Added support for wasm-bindgen. (#541, #559, #562, #600) +- Enable `OsRng` for powerpc64, sparc and sparc64 (#609) +- Use `syscall` from `libc` on Linux instead of redefining it (#629) + +### RNGs +- Switch `SmallRng` to use PCG (#623) +- Implement `Pcg32` and `Pcg64Mcg` generators (#632) +- Move ISAAC RNGs to a dedicated crate (#551) +- Move Xorshift RNG to its own crate (#557) +- Move ChaCha and HC128 RNGs to dedicated crates (#607, #636) +- Remove usage of `Rc` from `ThreadRng` (#615) + +### Sampling and distributions +- Implement `Rng.gen_ratio()` and `Bernoulli::new_ratio()` (#491) +- Make `Uniform` strictly respect `f32` / `f64` high/low bounds (#477) +- Allow `gen_range` and `Uniform` to work on non-`Copy` types (#506) +- `Uniform` supports inclusive ranges: `Uniform::from(a..=b)`. This is + automatically enabled for Rust >= 1.27. (#566) +- Implement `TrustedLen` and `FusedIterator` for `DistIter` (#620) + +#### New distributions +- Add the `Dirichlet` distribution (#485) +- Added sampling from the unit sphere and circle. (#567) +- Implement the triangular distribution (#575) +- Implement the Weibull distribution (#576) +- Implement the Beta distribution (#574) + +#### Optimisations + +- Optimise `Bernoulli::new` (#500) +- Optimise `char` sampling (#519) +- Optimise sampling of `std::time::Duration` (#583) + +### Sequences +- Redesign the `seq` module (#483, #515) +- Add `WeightedIndex` and `choose_weighted` (#518, #547) +- Optimised and changed return type of the `sample_indices` function. (#479) +- Use `Iterator::size_hint()` to speed up `IteratorRandom::choose` (#593) + +### SIMD +- Support for generating SIMD types (#523, #542, #561, #630) + +### Other +- Revise CI scripts (#632, #635) +- Remove functionality already deprecated in 0.5 (#499) +- Support for `i128` and `u128` is automatically enabled for Rust >= 1.26. This + renders the `i128_support` feature obsolete. It still exists for backwards + compatibility but does not have any effect. This breaks programs using Rand + with `i128_support` on nightlies older than Rust 1.26. (#571) + + +## [0.5.5] - 2018-08-07 +### Documentation +- Fix links in documentation (#582) + + +## [0.5.4] - 2018-07-11 +### Platform support +- Make `OsRng` work via WASM/stdweb for WebWorkers + + +## [0.5.3] - 2018-06-26 +### Platform support +- OpenBSD, Bitrig: fix compilation (broken in 0.5.1) (#530) + + +## [0.5.2] - 2018-06-18 +### Platform support +- Hide `OsRng` and `JitterRng` on unsupported platforms (#512; fixes #503). + + +## [0.5.1] - 2018-06-08 + +### New distributions +- Added Cauchy distribution. (#474, #486) +- Added Pareto distribution. (#495) + +### Platform support and `OsRng` +- Remove blanket Unix implementation. (#484) +- Remove Wasm unimplemented stub. (#484) +- Dragonfly BSD: read from `/dev/random`. (#484) +- Bitrig: use `getentropy` like OpenBSD. (#484) +- Solaris: (untested) use `getrandom` if available, otherwise `/dev/random`. (#484) +- Emscripten, `stdweb`: split the read up in chunks. (#484) +- Emscripten, Haiku: don't do an extra blocking read from `/dev/random`. (#484) +- Linux, NetBSD, Solaris: read in blocking mode on first use in `fill_bytes`. (#484) +- Fuchsia, CloudABI: fix compilation (broken in Rand 0.5). (#484) + + +## [0.5.0] - 2018-05-21 + +### Crate features and organisation +- Minimum Rust version update: 1.22.0. (#239) +- Create a separate `rand_core` crate. (#288) +- Deprecate `rand_derive`. (#256) +- Add `prelude` (and module reorganisation). (#435) +- Add `log` feature. Logging is now available in `JitterRng`, `OsRng`, `EntropyRng` and `ReseedingRng`. (#246) +- Add `serde1` feature for some PRNGs. (#189) +- `stdweb` feature for `OsRng` support on WASM via stdweb. (#272, #336) + +### `Rng` trait +- Split `Rng` in `RngCore` and `Rng` extension trait. + `next_u32`, `next_u64` and `fill_bytes` are now part of `RngCore`. (#265) +- Add `Rng::sample`. (#256) +- Deprecate `Rng::gen_weighted_bool`. (#308) +- Add `Rng::gen_bool`. (#308) +- Remove `Rng::next_f32` and `Rng::next_f64`. (#273) +- Add optimized `Rng::fill` and `Rng::try_fill` methods. (#247) +- Deprecate `Rng::gen_iter`. (#286) +- Deprecate `Rng::gen_ascii_chars`. (#279) + +### `rand_core` crate +- `rand` now depends on new `rand_core` crate (#288) +- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288) +- Add modules to help implementing RNGs `impl` and `le`. (#209, #228) +- Add `Error` and `ErrorKind`. (#225) +- Add `CryptoRng` marker trait. (#273) +- Add `BlockRngCore` trait. (#281) +- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325) +- Revise the `SeedableRng` trait. (#233) +- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288) +- Add `RngCore::try_fill_bytes`. (#225) + +### Other traits and types +- Add `FromEntropy` trait. (#233, #375) +- Add `SmallRng` wrapper. (#296) +- Rewrite `ReseedingRng` to only work with `BlockRngCore` (substantial performance improvement). (#281) +- Deprecate `weak_rng`. Use `SmallRng` instead. (#296) +- Deprecate `AsciiGenerator`. (#279) + +### Random number generators +- Switch `StdRng` and `thread_rng` to HC-128. (#277) +- `StdRng` must now be created with `from_entropy` instead of `new` +- Change `thread_rng` reseeding threshold to 32 MiB. (#277) +- PRNGs no longer implement `Copy`. (#209) +- `Debug` implementations no longer show internals. (#209) +- Implement `Clone` for `ReseedingRng`, `JitterRng`, OsRng`. (#383, #384) +- Implement serialization for `XorShiftRng`, `IsaacRng` and `Isaac64Rng` under the `serde1` feature. (#189) +- Implement `BlockRngCore` for `ChaChaCore` and `Hc128Core`. (#281) +- All PRNGs are now portable across big- and little-endian architectures. (#209) +- `Isaac64Rng::next_u32` no longer throws away half the results. (#209) +- Add `IsaacRng::new_from_u64` and `Isaac64Rng::new_from_u64`. (#209) +- Add the HC-128 CSPRNG `Hc128Rng`. (#210) +- Change ChaCha20 to have 64-bit counter and 64-bit stream. (#349) +- Changes to `JitterRng` to get its size down from 2112 to 24 bytes. (#251) +- Various performance improvements to all PRNGs. + +### Platform support and `OsRng` +- Add support for CloudABI. (#224) +- Remove support for NaCl. (#225) +- WASM support for `OsRng` via stdweb, behind the `stdweb` feature. (#272, #336) +- Use `getrandom` on more platforms for Linux, and on Android. (#338) +- Use the `SecRandomCopyBytes` interface on macOS. (#322) +- On systems that do not have a syscall interface, only keep a single file descriptor open for `OsRng`. (#239) +- On Unix, first try a single read from `/dev/random`, then `/dev/urandom`. (#338) +- Better error handling and reporting in `OsRng` (using new error type). (#225) +- `OsRng` now uses non-blocking when available. (#225) +- Add `EntropyRng`, which provides `OsRng`, but has `JitterRng` as a fallback. (#235) + +### Distributions +- New `Distribution` trait. (#256) +- Add `Distribution::sample_iter` and `Rng::::sample_iter`. (#361) +- Deprecate `Rand`, `Sample` and `IndependentSample` traits. (#256) +- Add a `Standard` distribution (replaces most `Rand` implementations). (#256) +- Add `Binomial` and `Poisson` distributions. (#96) +- Add `Bernoulli` dsitribution. (#411) +- Add `Alphanumeric` distribution. (#279) +- Remove `Closed01` distribution, add `OpenClosed01`. (#274, #420) +- Rework `Range` type, making it possible to implement it for user types. (#274) +- Rename `Range` to `Uniform`. (#395) +- Add `Uniform::new_inclusive` for inclusive ranges. (#274) +- Use widening multiply method for much faster integer range reduction. (#274) +- `Standard` distribution for `char` uses `Uniform` internally. (#274) +- `Standard` distribution for `bool` uses sign test. (#274) +- Implement `Standard` distribution for `Wrapping`. (#436) +- Implement `Uniform` distribution for `Duration`. (#427) + + +## [0.4.3] - 2018-08-16 +### Fixed +- Use correct syscall number for PowerPC (#589) + + +## [0.4.2] - 2018-01-06 +### Changed +- Use `winapi` on Windows +- Update for Fuchsia OS +- Remove dev-dependency on `log` + + +## [0.4.1] - 2017-12-17 +### Added +- `no_std` support + + +## [0.4.0-pre.0] - 2017-12-11 +### Added +- `JitterRng` added as a high-quality alternative entropy source using the + system timer +- new `seq` module with `sample_iter`, `sample_slice`, etc. +- WASM support via dummy implementations (fail at run-time) +- Additional benchmarks, covering generators and new seq code + +### Changed +- `thread_rng` uses `JitterRng` if seeding from system time fails + (slower but more secure than previous method) + +### Deprecated + - `sample` function deprecated (replaced by `sample_iter`) + + +## [0.3.20] - 2018-01-06 +### Changed +- Remove dev-dependency on `log` +- Update `fuchsia-zircon` dependency to 0.3.2 + + +## [0.3.19] - 2017-12-27 +### Changed +- Require `log <= 0.3.8` for dev builds +- Update `fuchsia-zircon` dependency to 0.3 +- Fix broken links in docs (to unblock compiler docs testing CI) + + +## [0.3.18] - 2017-11-06 +### Changed +- `thread_rng` is seeded from the system time if `OsRng` fails +- `weak_rng` now uses `thread_rng` internally + + +## [0.3.17] - 2017-10-07 +### Changed + - Fuchsia: Magenta was renamed Zircon + +## [0.3.16] - 2017-07-27 +### Added +- Implement Debug for mote non-public types +- implement `Rand` for (i|u)i128 +- Support for Fuchsia + +### Changed +- Add inline attribute to SampleRange::construct_range. + This improves the benchmark for sample in 11% and for shuffle in 16%. +- Use `RtlGenRandom` instead of `CryptGenRandom` + + +## [0.3.15] - 2016-11-26 +### Added +- Add `Rng` trait method `choose_mut` +- Redox support + +### Changed +- Use `arc4rand` for `OsRng` on FreeBSD. +- Use `arc4random(3)` for `OsRng` on OpenBSD. + +### Fixed +- Fix filling buffers 4 GiB or larger with `OsRng::fill_bytes` on Windows + + +## [0.3.14] - 2016-02-13 +### Fixed +- Inline definitions from winapi/advapi32, which decreases build times + + +## [0.3.13] - 2016-01-09 +### Fixed +- Compatible with Rust 1.7.0-nightly (needed some extra type annotations) + + +## [0.3.12] - 2015-11-09 +### Changed +- Replaced the methods in `next_f32` and `next_f64` with the technique described + Saito & Matsumoto at MCQMC'08. The new method should exhibit a slightly more + uniform distribution. +- Depend on libc 0.2 + +### Fixed +- Fix iterator protocol issue in `rand::sample` + + +## [0.3.11] - 2015-08-31 +### Added +- Implement `Rand` for arrays with n <= 32 + + +## [0.3.10] - 2015-08-17 +### Added +- Support for NaCl platforms + +### Changed +- Allow `Rng` to be `?Sized`, impl for `&mut R` and `Box` where `R: ?Sized + Rng` + + +## [0.3.9] - 2015-06-18 +### Changed +- Use `winapi` for Windows API things + +### Fixed +- Fixed test on stable/nightly +- Fix `getrandom` syscall number for aarch64-unknown-linux-gnu + + +## [0.3.8] - 2015-04-23 +### Changed +- `log` is a dev dependency + +### Fixed +- Fix race condition of atomics in `is_getrandom_available` + + +## [0.3.7] - 2015-04-03 +### Fixed +- Derive Copy/Clone changes + + +## [0.3.6] - 2015-04-02 +### Changed +- Move to stable Rust! + + +## [0.3.5] - 2015-04-01 +### Fixed +- Compatible with Rust master + + +## [0.3.4] - 2015-03-31 +### Added +- Implement Clone for `Weighted` + +### Fixed +- Compatible with Rust master + + +## [0.3.3] - 2015-03-26 +### Fixed +- Fix compile on Windows + + +## [0.3.2] - 2015-03-26 + + +## [0.3.1] - 2015-03-26 +### Fixed +- Fix compile on Windows + + +## [0.3.0] - 2015-03-25 +### Changed +- Update to use log version 0.3.x + + +## [0.2.1] - 2015-03-22 +### Fixed +- Compatible with Rust master +- Fixed iOS compilation + + +## [0.2.0] - 2015-03-06 +### Fixed +- Compatible with Rust master (move from `old_io` to `std::io`) + + +## [0.1.4] - 2015-03-04 +### Fixed +- Compatible with Rust master (use wrapping ops) + + +## [0.1.3] - 2015-02-20 +### Fixed +- Compatible with Rust master + +### Removed +- Removed Copy implementations from RNGs + + +## [0.1.2] - 2015-02-03 +### Added +- Imported functionality from `std::rand`, including: + - `StdRng`, `SeedableRng`, `TreadRng`, `weak_rng()` + - `ReaderRng`: A wrapper around any Reader to treat it as an RNG. +- Imported documentation from `std::rand` +- Imported tests from `std::rand` + + +## [0.1.1] - 2015-02-03 +### Added +- Migrate to a cargo-compatible directory structure. + +### Fixed +- Do not use entropy during `gen_weighted_bool(1)` + + +## [Rust 0.12.0] - 2014-10-09 +### Added +- Impl Rand for tuples of arity 11 and 12 +- Include ChaCha pseudorandom generator +- Add `next_f64` and `next_f32` to Rng +- Implement Clone for PRNGs + +### Changed +- Rename `TaskRng` to `ThreadRng` and `task_rng` to `thread_rng` (since a + runtime is removed from Rust). + +### Fixed +- Improved performance of ISAAC and ISAAC64 by 30% and 12 % respectively, by + informing the optimiser that indexing is never out-of-bounds. + +### Removed +- Removed the Deprecated `choose_option` + + +## [Rust 0.11.0] - 2014-07-02 +### Added +- document when to use `OSRng` in cryptographic context, and explain why we use `/dev/urandom` instead of `/dev/random` +- `Rng::gen_iter()` which will return an infinite stream of random values +- `Rng::gen_ascii_chars()` which will return an infinite stream of random ascii characters + +### Changed +- Now only depends on libcore! +- Remove `Rng.choose()`, rename `Rng.choose_option()` to `.choose()` +- Rename OSRng to OsRng +- The WeightedChoice structure is no longer built with a `Vec>`, + but rather a `&mut [Weighted]`. This means that the WeightedChoice + structure now has a lifetime associated with it. +- The `sample` method on `Rng` has been moved to a top-level function in the + `rand` module due to its dependence on `Vec`. + +### Removed +- `Rng::gen_vec()` was removed. Previous behavior can be regained with + `rng.gen_iter().take(n).collect()` +- `Rng::gen_ascii_str()` was removed. Previous behavior can be regained with + `rng.gen_ascii_chars().take(n).collect()` +- {IsaacRng, Isaac64Rng, XorShiftRng}::new() have all been removed. These all + relied on being able to use an OSRng for seeding, but this is no longer + available in librand (where these types are defined). To retain the same + functionality, these types now implement the `Rand` trait so they can be + generated with a random seed from another random number generator. This allows + the stdlib to use an OSRng to create seeded instances of these RNGs. +- Rand implementations for `Box` and `@T` were removed. These seemed to be + pretty rare in the codebase, and it allows for librand to not depend on + liballoc. Additionally, other pointer types like Rc and Arc were not + supported. +- Remove a slew of old deprecated functions + + +## [Rust 0.10] - 2014-04-03 +### Changed +- replace `Rng.shuffle's` functionality with `.shuffle_mut` +- bubble up IO errors when creating an OSRng + +### Fixed +- Use `fill()` instead of `read()` +- Rewrite OsRng in Rust for windows + +## [0.10-pre] - 2014-03-02 +### Added +- Separate `rand` out of the standard library diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/COPYRIGHT clamav-1.4.6+dfsg/.cargo/vendor/rand/COPYRIGHT --- clamav-1.4.3+dfsg/.cargo/vendor/rand/COPYRIGHT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/COPYRIGHT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +dependencies = [ + "bincode", + "log", + "rand_chacha", + "rand_core", + "rand_pcg", + "rayon", + "serde", + "serde_json", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "rand_pcg" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b48ac3f7ffaab7fac4d2376632268aa5f89abdb55f7ebf8f4d11fffccb2320f7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63" +name = "rand" +version = "0.9.2" +authors = [ + "The Rand Project Developers", + "The Rust Project Developers", +] +build = false +include = [ + "src/", + "LICENSE-*", + "README.md", + "CHANGELOG.md", + "COPYRIGHT", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Random number generators and other randomness functionality. +""" +homepage = "https://rust-random.github.io/book" +documentation = "https://docs.rs/rand" +readme = "README.md" +keywords = [ + "random", + "rng", +] +categories = [ + "algorithms", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.playground] +features = [ + "small_rng", + "serde", +] + +[features] +alloc = [] +default = [ + "std", + "std_rng", + "os_rng", + "small_rng", + "thread_rng", +] +log = ["dep:log"] +nightly = [] +os_rng = ["rand_core/os_rng"] +serde = [ + "dep:serde", + "rand_core/serde", +] +simd_support = [] +small_rng = [] +std = [ + "rand_core/std", + "rand_chacha?/std", + "alloc", +] +std_rng = ["dep:rand_chacha"] +thread_rng = [ + "std", + "std_rng", + "os_rng", +] +unbiased = [] + +[lib] +name = "rand" +path = "src/lib.rs" + +[dependencies.log] +version = "0.4.4" +optional = true + +[dependencies.rand_chacha] +version = "0.9.0" +optional = true +default-features = false + +[dependencies.rand_core] +version = "0.9.0" +default-features = false + +[dependencies.serde] +version = "1.0.103" +features = ["derive"] +optional = true + +[dev-dependencies.bincode] +version = "1.2.1" + +[dev-dependencies.rand_pcg] +version = "0.9.0" + +[dev-dependencies.rayon] +version = "1.7" + +[dev-dependencies.serde_json] +version = "1.0.140" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rand/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +[package] +name = "rand" +version = "0.9.2" +authors = ["The Rand Project Developers", "The Rust Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-random/rand" +documentation = "https://docs.rs/rand" +homepage = "https://rust-random.github.io/book" +description = """ +Random number generators and other randomness functionality. +""" +keywords = ["random", "rng"] +categories = ["algorithms", "no-std"] +autobenches = true +edition = "2021" +rust-version = "1.63" +include = ["src/", "LICENSE-*", "README.md", "CHANGELOG.md", "COPYRIGHT"] + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg docsrs -Zunstable-options --generate-link-to-definition" cargo +nightly doc --all --all-features --no-deps --open +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.playground] +features = ["small_rng", "serde"] + +[features] +# Meta-features: +default = ["std", "std_rng", "os_rng", "small_rng", "thread_rng"] +nightly = [] # some additions requiring nightly Rust +serde = ["dep:serde", "rand_core/serde"] + +# Option (enabled by default): without "std" rand uses libcore; this option +# enables functionality expected to be available on a standard platform. +std = ["rand_core/std", "rand_chacha?/std", "alloc"] + +# Option: "alloc" enables support for Vec and Box when not using "std" +alloc = [] + +# Option: enable OsRng +os_rng = ["rand_core/os_rng"] + +# Option (requires nightly Rust): experimental SIMD support +simd_support = [] + +# Option (enabled by default): enable StdRng +std_rng = ["dep:rand_chacha"] + +# Option: enable SmallRng +small_rng = [] + +# Option: enable ThreadRng and rng() +thread_rng = ["std", "std_rng", "os_rng"] + +# Option: use unbiased sampling for algorithms supporting this option: Uniform distribution. +# By default, bias affecting no more than one in 2^48 samples is accepted. +# Note: enabling this option is expected to affect reproducibility of results. +unbiased = [] + +# Option: enable logging +log = ["dep:log"] + +[workspace] +members = [ + "rand_core", + "rand_chacha", + "rand_pcg", +] +exclude = ["benches", "distr_test"] + +[dependencies] +rand_core = { path = "rand_core", version = "0.9.0", default-features = false } +log = { version = "0.4.4", optional = true } +serde = { version = "1.0.103", features = ["derive"], optional = true } +rand_chacha = { path = "rand_chacha", version = "0.9.0", default-features = false, optional = true } + +[dev-dependencies] +rand_pcg = { path = "rand_pcg", version = "0.9.0" } +# Only to test serde +bincode = "1.2.1" +rayon = "1.7" +serde_json = "1.0.140" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/rand/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/rand/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/README.md clamav-1.4.6+dfsg/.cargo/vendor/rand/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +# Rand + +[![Test Status](https://github.com/rust-random/rand/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Crate](https://img.shields.io/crates/v/rand.svg)](https://crates.io/crates/rand) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand) +[![API](https://docs.rs/rand/badge.svg)](https://docs.rs/rand) + +Rand is a set of crates supporting (pseudo-)random generators: + +- Built over a standard RNG trait: [`rand_core::RngCore`](https://docs.rs/rand_core/latest/rand_core/trait.RngCore.html) +- With fast implementations of both [strong](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and + [small](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators: [`rand::rngs`](https://docs.rs/rand/latest/rand/rngs/index.html), and more RNGs: [`rand_chacha`](https://docs.rs/rand_chacha), [`rand_xoshiro`](https://docs.rs/rand_xoshiro/), [`rand_pcg`](https://docs.rs/rand_pcg/), [rngs repo](https://github.com/rust-random/rngs/) +- [`rand::rng`](https://docs.rs/rand/latest/rand/fn.rng.html) is an asymptotically-fast, automatically-seeded and reasonably strong generator available on all `std` targets +- Direct support for seeding generators from the [getrandom] crate + +With broad support for random value generation and random processes: + +- [`StandardUniform`](https://docs.rs/rand/latest/rand/distr/struct.StandardUniform.html) random value sampling, + [`Uniform`](https://docs.rs/rand/latest/rand/distr/struct.Uniform.html)-ranged value sampling + and [more](https://docs.rs/rand/latest/rand/distr/index.html) +- Samplers for a large number of non-uniform random number distributions via our own + [`rand_distr`](https://docs.rs/rand_distr) and via + the [`statrs`](https://docs.rs/statrs) +- Random processes (mostly choose and shuffle) via [`rand::seq`](https://docs.rs/rand/latest/rand/seq/index.html) traits + +All with: + +- [Portably reproducible output](https://rust-random.github.io/book/portability.html) +- `#[no_std]` compatibility (partial) +- *Many* performance optimisations thanks to contributions from the wide + user-base + +Rand **is not**: + +- Small (LoC). Most low-level crates are small, but the higher-level `rand` + and `rand_distr` each contain a lot of functionality. +- Simple (implementation). We have a strong focus on correctness, speed and flexibility, but + not simplicity. If you prefer a small-and-simple library, there are + alternatives including [fastrand](https://crates.io/crates/fastrand) + and [oorandom](https://crates.io/crates/oorandom). +- Primarily a cryptographic library. `rand` does provide some generators which + aim to support unpredictable value generation under certain constraints; + see [SECURITY.md](https://github.com/rust-random/rand/blob/master/SECURITY.md) for details. + Users are expected to determine for themselves + whether `rand`'s functionality meets their own security requirements. + +Documentation: + +- [The Rust Rand Book](https://rust-random.github.io/book) +- [API reference (master branch)](https://rust-random.github.io/rand) +- [API reference (docs.rs)](https://docs.rs/rand) + + +## Versions + +Rand is *mature* (suitable for general usage, with infrequent breaking releases +which minimise breakage) but not yet at 1.0. Current `MAJOR.MINOR` versions are: + +- Version 0.9 was released in January 2025. + +See the [CHANGELOG](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) or [Upgrade Guide](https://rust-random.github.io/book/update.html) for more details. + +## Crate Features + +Rand is built with these features enabled by default: + +- `std` enables functionality dependent on the `std` lib +- `alloc` (implied by `std`) enables functionality requiring an allocator +- `os_rng` (implied by `std`) enables `rngs::OsRng`, using the [getrandom] crate +- `std_rng` enables inclusion of `StdRng`, `ThreadRng` +- `small_rng` enables inclusion of the `SmallRng` PRNG + +Optionally, the following dependencies can be enabled: + +- `log` enables logging via [log](https://crates.io/crates/log) + +Additionally, these features configure Rand: + +- `nightly` includes some additions requiring nightly Rust +- `simd_support` (experimental) enables sampling of SIMD values + (uniformly random SIMD integers and floats), requiring nightly Rust +- `unbiased` use unbiased sampling for algorithms supporting this option: Uniform distribution. + + (By default, bias affecting no more than one in 2^48 samples is accepted.) + + Note: enabling this option is expected to affect reproducibility of results. + +Note that nightly features are not stable and therefore not all library and +compiler versions will be compatible. This is especially true of Rand's +experimental `simd_support` feature. + +Rand supports limited functionality in `no_std` mode (enabled via +`default-features = false`). In this case, `OsRng` and `from_os_rng` are +unavailable (unless `os_rng` is enabled), large parts of `seq` are +unavailable (unless `alloc` is enabled), and `ThreadRng` is unavailable. + +## Portability and platform support + +Many (but not all) algorithms are intended to have reproducible output. Read more in the book: [Portability](https://rust-random.github.io/book/portability.html). + +The Rand library supports a variety of CPU architectures. Platform integration is outsourced to [getrandom]. + +### WebAssembly support + +The [WASI](https://github.com/WebAssembly/WASI/tree/main) and Emscripten +targets are directly supported. The `wasm32-unknown-unknown` target is not +*automatically* supported. To enable support for this target, refer to the +[`getrandom` documentation for WebAssembly](https://docs.rs/getrandom/latest/getrandom/#webassembly-support). +Alternatively, the `os_rng` feature may be disabled. + +# License + +Rand is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](https://github.com/rust-random/rand/blob/master/LICENSE-APACHE) and [LICENSE-MIT](https://github.com/rust-random/rand/blob/master/LICENSE-MIT), and +[COPYRIGHT](https://github.com/rust-random/rand/blob/master/COPYRIGHT) for details. + +[getrandom]: https://crates.io/crates/getrandom diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/bernoulli.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/bernoulli.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/bernoulli.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/bernoulli.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,243 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The Bernoulli distribution `Bernoulli(p)`. + +use crate::distr::Distribution; +use crate::Rng; +use core::fmt; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// The [Bernoulli distribution](https://en.wikipedia.org/wiki/Bernoulli_distribution) `Bernoulli(p)`. +/// +/// This distribution describes a single boolean random variable, which is true +/// with probability `p` and false with probability `1 - p`. +/// It is a special case of the Binomial distribution with `n = 1`. +/// +/// # Plot +/// +/// The following plot shows the Bernoulli distribution with `p = 0.1`, +/// `p = 0.5`, and `p = 0.9`. +/// +/// ![Bernoulli distribution](https://raw.githubusercontent.com/rust-random/charts/main/charts/bernoulli.svg) +/// +/// # Example +/// +/// ```rust +/// use rand::distr::{Bernoulli, Distribution}; +/// +/// let d = Bernoulli::new(0.3).unwrap(); +/// let v = d.sample(&mut rand::rng()); +/// println!("{} is from a Bernoulli distribution", v); +/// ``` +/// +/// # Precision +/// +/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`), +/// so only probabilities that are multiples of 2-64 can be +/// represented. +#[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Bernoulli { + /// Probability of success, relative to the maximal integer. + p_int: u64, +} + +// To sample from the Bernoulli distribution we use a method that compares a +// random `u64` value `v < (p * 2^64)`. +// +// If `p == 1.0`, the integer `v` to compare against can not represented as a +// `u64`. We manually set it to `u64::MAX` instead (2^64 - 1 instead of 2^64). +// Note that value of `p < 1.0` can never result in `u64::MAX`, because an +// `f64` only has 53 bits of precision, and the next largest value of `p` will +// result in `2^64 - 2048`. +// +// Also there is a 100% theoretical concern: if someone consistently wants to +// generate `true` using the Bernoulli distribution (i.e. by using a probability +// of `1.0`), just using `u64::MAX` is not enough. On average it would return +// false once every 2^64 iterations. Some people apparently care about this +// case. +// +// That is why we special-case `u64::MAX` to always return `true`, without using +// the RNG, and pay the performance price for all uses that *are* reasonable. +// Luckily, if `new()` and `sample` are close, the compiler can optimize out the +// extra check. +const ALWAYS_TRUE: u64 = u64::MAX; + +// This is just `2.0.powi(64)`, but written this way because it is not available +// in `no_std` mode. +const SCALE: f64 = 2.0 * (1u64 << 63) as f64; + +/// Error type returned from [`Bernoulli::new`]. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BernoulliError { + /// `p < 0` or `p > 1`. + InvalidProbability, +} + +impl fmt::Display for BernoulliError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BernoulliError::InvalidProbability => "p is outside [0, 1] in Bernoulli distribution", + }) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for BernoulliError {} + +impl Bernoulli { + /// Construct a new `Bernoulli` with the given probability of success `p`. + /// + /// # Precision + /// + /// For `p = 1.0`, the resulting distribution will always generate true. + /// For `p = 0.0`, the resulting distribution will always generate false. + /// + /// This method is accurate for any input `p` in the range `[0, 1]` which is + /// a multiple of 2-64. (Note that not all multiples of + /// 2-64 in `[0, 1]` can be represented as a `f64`.) + #[inline] + pub fn new(p: f64) -> Result { + if !(0.0..1.0).contains(&p) { + if p == 1.0 { + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); + } + return Err(BernoulliError::InvalidProbability); + } + Ok(Bernoulli { + p_int: (p * SCALE) as u64, + }) + } + + /// Construct a new `Bernoulli` with the probability of success of + /// `numerator`-in-`denominator`. I.e. `new_ratio(2, 3)` will return + /// a `Bernoulli` with a 2-in-3 chance, or about 67%, of returning `true`. + /// + /// return `true`. If `numerator == 0` it will always return `false`. + /// For `numerator > denominator` and `denominator == 0`, this returns an + /// error. Otherwise, for `numerator == denominator`, samples are always + /// true; for `numerator == 0` samples are always false. + #[inline] + pub fn from_ratio(numerator: u32, denominator: u32) -> Result { + if numerator > denominator || denominator == 0 { + return Err(BernoulliError::InvalidProbability); + } + if numerator == denominator { + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); + } + let p_int = ((f64::from(numerator) / f64::from(denominator)) * SCALE) as u64; + Ok(Bernoulli { p_int }) + } + + #[inline] + /// Returns the probability (`p`) of the distribution. + /// + /// This value may differ slightly from the input due to loss of precision. + pub fn p(&self) -> f64 { + if self.p_int == ALWAYS_TRUE { + 1.0 + } else { + (self.p_int as f64) / SCALE + } + } +} + +impl Distribution for Bernoulli { + #[inline] + fn sample(&self, rng: &mut R) -> bool { + // Make sure to always return true for p = 1.0. + if self.p_int == ALWAYS_TRUE { + return true; + } + let v: u64 = rng.random(); + v < self.p_int + } +} + +#[cfg(test)] +mod test { + use super::Bernoulli; + use crate::distr::Distribution; + use crate::Rng; + + #[test] + #[cfg(feature = "serde")] + fn test_serializing_deserializing_bernoulli() { + let coin_flip = Bernoulli::new(0.5).unwrap(); + let de_coin_flip: Bernoulli = + bincode::deserialize(&bincode::serialize(&coin_flip).unwrap()).unwrap(); + + assert_eq!(coin_flip.p_int, de_coin_flip.p_int); + } + + #[test] + fn test_trivial() { + // We prefer to be explicit here. + #![allow(clippy::bool_assert_comparison)] + + let mut r = crate::test::rng(1); + let always_false = Bernoulli::new(0.0).unwrap(); + let always_true = Bernoulli::new(1.0).unwrap(); + for _ in 0..5 { + assert_eq!(r.sample::(&always_false), false); + assert_eq!(r.sample::(&always_true), true); + assert_eq!(Distribution::::sample(&always_false, &mut r), false); + assert_eq!(Distribution::::sample(&always_true, &mut r), true); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_average() { + const P: f64 = 0.3; + const NUM: u32 = 3; + const DENOM: u32 = 10; + let d1 = Bernoulli::new(P).unwrap(); + let d2 = Bernoulli::from_ratio(NUM, DENOM).unwrap(); + const N: u32 = 100_000; + + let mut sum1: u32 = 0; + let mut sum2: u32 = 0; + let mut rng = crate::test::rng(2); + for _ in 0..N { + if d1.sample(&mut rng) { + sum1 += 1; + } + if d2.sample(&mut rng) { + sum2 += 1; + } + } + let avg1 = (sum1 as f64) / (N as f64); + assert!((avg1 - P).abs() < 5e-3); + + let avg2 = (sum2 as f64) / (N as f64); + assert!((avg2 - (NUM as f64) / (DENOM as f64)).abs() < 5e-3); + } + + #[test] + fn value_stability() { + let mut rng = crate::test::rng(3); + let distr = Bernoulli::new(0.4532).unwrap(); + let mut buf = [false; 10]; + for x in &mut buf { + *x = rng.sample(distr); + } + assert_eq!( + buf, + [true, false, false, true, false, false, true, true, true, true] + ); + } + + #[test] + fn bernoulli_distributions_can_be_compared() { + assert_eq!(Bernoulli::new(1.0), Bernoulli::new(1.0)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/distribution.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/distribution.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/distribution.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/distribution.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,269 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Distribution trait and associates + +use crate::Rng; +#[cfg(feature = "alloc")] +use alloc::string::String; +use core::iter; + +/// Types (distributions) that can be used to create a random instance of `T`. +/// +/// It is possible to sample from a distribution through both the +/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and +/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which +/// produces an iterator that samples from the distribution. +/// +/// All implementations are expected to be immutable; this has the significant +/// advantage of not needing to consider thread safety, and for most +/// distributions efficient state-less sampling algorithms are available. +/// +/// Implementations are typically expected to be portable with reproducible +/// results when used with a PRNG with fixed seed; see the +/// [portability chapter](https://rust-random.github.io/book/portability.html) +/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize` +/// type requires different sampling on 32-bit and 64-bit machines. +/// +/// [`sample_iter`]: Distribution::sample_iter +pub trait Distribution { + /// Generate a random value of `T`, using `rng` as the source of randomness. + fn sample(&self, rng: &mut R) -> T; + + /// Create an iterator that generates random values of `T`, using `rng` as + /// the source of randomness. + /// + /// Note that this function takes `self` by value. This works since + /// `Distribution` is impl'd for `&D` where `D: Distribution`, + /// however borrowing is not automatic hence `distr.sample_iter(...)` may + /// need to be replaced with `(&distr).sample_iter(...)` to borrow or + /// `(&*distr).sample_iter(...)` to reborrow an existing reference. + /// + /// # Example + /// + /// ``` + /// use rand::distr::{Distribution, Alphanumeric, Uniform, StandardUniform}; + /// + /// let mut rng = rand::rng(); + /// + /// // Vec of 16 x f32: + /// let v: Vec = StandardUniform.sample_iter(&mut rng).take(16).collect(); + /// + /// // String: + /// let s: String = Alphanumeric + /// .sample_iter(&mut rng) + /// .take(7) + /// .map(char::from) + /// .collect(); + /// + /// // Dice-rolling: + /// let die_range = Uniform::new_inclusive(1, 6).unwrap(); + /// let mut roll_die = die_range.sample_iter(&mut rng); + /// while roll_die.next().unwrap() != 6 { + /// println!("Not a 6; rolling again!"); + /// } + /// ``` + fn sample_iter(self, rng: R) -> Iter + where + R: Rng, + Self: Sized, + { + Iter { + distr: self, + rng, + phantom: core::marker::PhantomData, + } + } + + /// Map sampled values to type `S` + /// + /// # Example + /// + /// ``` + /// use rand::distr::{Distribution, Uniform}; + /// + /// let die = Uniform::new_inclusive(1, 6).unwrap(); + /// let even_number = die.map(|num| num % 2 == 0); + /// while !even_number.sample(&mut rand::rng()) { + /// println!("Still odd; rolling again!"); + /// } + /// ``` + fn map(self, func: F) -> Map + where + F: Fn(T) -> S, + Self: Sized, + { + Map { + distr: self, + func, + phantom: core::marker::PhantomData, + } + } +} + +impl + ?Sized> Distribution for &D { + fn sample(&self, rng: &mut R) -> T { + (*self).sample(rng) + } +} + +/// An iterator over a [`Distribution`] +/// +/// This iterator yields random values of type `T` with distribution `D` +/// from a random generator of type `R`. +/// +/// Construct this `struct` using [`Distribution::sample_iter`] or +/// [`Rng::sample_iter`]. It is also used by [`Rng::random_iter`] and +/// [`crate::random_iter`]. +#[derive(Debug)] +pub struct Iter { + distr: D, + rng: R, + phantom: core::marker::PhantomData, +} + +impl Iterator for Iter +where + D: Distribution, + R: Rng, +{ + type Item = T; + + #[inline(always)] + fn next(&mut self) -> Option { + // Here, self.rng may be a reference, but we must take &mut anyway. + // Even if sample could take an R: Rng by value, we would need to do this + // since Rng is not copyable and we cannot enforce that this is "reborrowable". + Some(self.distr.sample(&mut self.rng)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + +impl iter::FusedIterator for Iter +where + D: Distribution, + R: Rng, +{ +} + +/// A [`Distribution`] which maps sampled values to type `S` +/// +/// This `struct` is created by the [`Distribution::map`] method. +/// See its documentation for more. +#[derive(Debug)] +pub struct Map { + distr: D, + func: F, + phantom: core::marker::PhantomData S>, +} + +impl Distribution for Map +where + D: Distribution, + F: Fn(T) -> S, +{ + fn sample(&self, rng: &mut R) -> S { + (self.func)(self.distr.sample(rng)) + } +} + +/// Sample or extend a [`String`] +/// +/// Helper methods to extend a [`String`] or sample a new [`String`]. +#[cfg(feature = "alloc")] +pub trait SampleString { + /// Append `len` random chars to `string` + /// + /// Note: implementations may leave `string` with excess capacity. If this + /// is undesirable, consider calling [`String::shrink_to_fit`] after this + /// method. + fn append_string(&self, rng: &mut R, string: &mut String, len: usize); + + /// Generate a [`String`] of `len` random chars + /// + /// Note: implementations may leave the string with excess capacity. If this + /// is undesirable, consider calling [`String::shrink_to_fit`] after this + /// method. + #[inline] + fn sample_string(&self, rng: &mut R, len: usize) -> String { + let mut s = String::new(); + self.append_string(rng, &mut s, len); + s + } +} + +#[cfg(test)] +mod tests { + use crate::distr::{Distribution, Uniform}; + use crate::Rng; + + #[test] + fn test_distributions_iter() { + use crate::distr::Open01; + let mut rng = crate::test::rng(210); + let distr = Open01; + let mut iter = Distribution::::sample_iter(distr, &mut rng); + let mut sum: f32 = 0.; + for _ in 0..100 { + sum += iter.next().unwrap(); + } + assert!(0. < sum && sum < 100.); + } + + #[test] + fn test_distributions_map() { + let dist = Uniform::new_inclusive(0, 5).unwrap().map(|val| val + 15); + + let mut rng = crate::test::rng(212); + let val = dist.sample(&mut rng); + assert!((15..=20).contains(&val)); + } + + #[test] + fn test_make_an_iter() { + fn ten_dice_rolls_other_than_five(rng: &mut R) -> impl Iterator + '_ { + Uniform::new_inclusive(1, 6) + .unwrap() + .sample_iter(rng) + .filter(|x| *x != 5) + .take(10) + } + + let mut rng = crate::test::rng(211); + let mut count = 0; + for val in ten_dice_rolls_other_than_five(&mut rng) { + assert!((1..=6).contains(&val) && val != 5); + count += 1; + } + assert_eq!(count, 10); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_dist_string() { + use crate::distr::{Alphabetic, Alphanumeric, SampleString, StandardUniform}; + use core::str; + let mut rng = crate::test::rng(213); + + let s1 = Alphanumeric.sample_string(&mut rng, 20); + assert_eq!(s1.len(), 20); + assert_eq!(str::from_utf8(s1.as_bytes()), Ok(s1.as_str())); + + let s2 = StandardUniform.sample_string(&mut rng, 20); + assert_eq!(s2.chars().count(), 20); + assert_eq!(str::from_utf8(s2.as_bytes()), Ok(s2.as_str())); + + let s3 = Alphabetic.sample_string(&mut rng, 20); + assert_eq!(s3.len(), 20); + assert_eq!(str::from_utf8(s3.as_bytes()), Ok(s3.as_str())); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/float.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/float.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,344 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Basic floating-point number distributions + +use crate::distr::utils::{FloatAsSIMD, FloatSIMDUtils, IntAsSIMD}; +use crate::distr::{Distribution, StandardUniform}; +use crate::Rng; +use core::mem; +#[cfg(feature = "simd_support")] +use core::simd::prelude::*; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A distribution to sample floating point numbers uniformly in the half-open +/// interval `(0, 1]`, i.e. including 1 but not 0. +/// +/// All values that can be generated are of the form `n * ε/2`. For `f32` +/// the 24 most significant random bits of a `u32` are used and for `f64` the +/// 53 most significant bits of a `u64` are used. The conversion uses the +/// multiplicative method. +/// +/// See also: [`StandardUniform`] which samples from `[0, 1)`, [`Open01`] +/// which samples from `(0, 1)` and [`Uniform`] which samples from arbitrary +/// ranges. +/// +/// # Example +/// ``` +/// use rand::Rng; +/// use rand::distr::OpenClosed01; +/// +/// let val: f32 = rand::rng().sample(OpenClosed01); +/// println!("f32 from (0, 1): {}", val); +/// ``` +/// +/// [`StandardUniform`]: crate::distr::StandardUniform +/// [`Open01`]: crate::distr::Open01 +/// [`Uniform`]: crate::distr::uniform::Uniform +#[derive(Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct OpenClosed01; + +/// A distribution to sample floating point numbers uniformly in the open +/// interval `(0, 1)`, i.e. not including either endpoint. +/// +/// All values that can be generated are of the form `n * ε + ε/2`. For `f32` +/// the 23 most significant random bits of an `u32` are used, for `f64` 52 from +/// an `u64`. The conversion uses a transmute-based method. +/// +/// See also: [`StandardUniform`] which samples from `[0, 1)`, [`OpenClosed01`] +/// which samples from `(0, 1]` and [`Uniform`] which samples from arbitrary +/// ranges. +/// +/// # Example +/// ``` +/// use rand::Rng; +/// use rand::distr::Open01; +/// +/// let val: f32 = rand::rng().sample(Open01); +/// println!("f32 from (0, 1): {}", val); +/// ``` +/// +/// [`StandardUniform`]: crate::distr::StandardUniform +/// [`OpenClosed01`]: crate::distr::OpenClosed01 +/// [`Uniform`]: crate::distr::uniform::Uniform +#[derive(Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Open01; + +// This trait is needed by both this lib and rand_distr hence is a hidden export +#[doc(hidden)] +pub trait IntoFloat { + type F; + + /// Helper method to combine the fraction and a constant exponent into a + /// float. + /// + /// Only the least significant bits of `self` may be set, 23 for `f32` and + /// 52 for `f64`. + /// The resulting value will fall in a range that depends on the exponent. + /// As an example the range with exponent 0 will be + /// [20..21), which is [1..2). + fn into_float_with_exponent(self, exponent: i32) -> Self::F; +} + +macro_rules! float_impls { + ($($meta:meta)?, $ty:ident, $uty:ident, $f_scalar:ident, $u_scalar:ty, + $fraction_bits:expr, $exponent_bias:expr) => { + $(#[cfg($meta)])? + impl IntoFloat for $uty { + type F = $ty; + #[inline(always)] + fn into_float_with_exponent(self, exponent: i32) -> $ty { + // The exponent is encoded using an offset-binary representation + let exponent_bits: $u_scalar = + (($exponent_bias + exponent) as $u_scalar) << $fraction_bits; + $ty::from_bits(self | $uty::splat(exponent_bits)) + } + } + + $(#[cfg($meta)])? + impl Distribution<$ty> for StandardUniform { + fn sample(&self, rng: &mut R) -> $ty { + // Multiply-based method; 24/53 random bits; [0, 1) interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + let float_size = mem::size_of::<$f_scalar>() as $u_scalar * 8; + let precision = $fraction_bits + 1; + let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); + + let value: $uty = rng.random(); + let value = value >> $uty::splat(float_size - precision); + $ty::splat(scale) * $ty::cast_from_int(value) + } + } + + $(#[cfg($meta)])? + impl Distribution<$ty> for OpenClosed01 { + fn sample(&self, rng: &mut R) -> $ty { + // Multiply-based method; 24/53 random bits; (0, 1] interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + let float_size = mem::size_of::<$f_scalar>() as $u_scalar * 8; + let precision = $fraction_bits + 1; + let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); + + let value: $uty = rng.random(); + let value = value >> $uty::splat(float_size - precision); + // Add 1 to shift up; will not overflow because of right-shift: + $ty::splat(scale) * $ty::cast_from_int(value + $uty::splat(1)) + } + } + + $(#[cfg($meta)])? + impl Distribution<$ty> for Open01 { + fn sample(&self, rng: &mut R) -> $ty { + // Transmute-based method; 23/52 random bits; (0, 1) interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + let float_size = mem::size_of::<$f_scalar>() as $u_scalar * 8; + + let value: $uty = rng.random(); + let fraction = value >> $uty::splat(float_size - $fraction_bits); + fraction.into_float_with_exponent(0) - $ty::splat(1.0 - $f_scalar::EPSILON / 2.0) + } + } + } +} + +float_impls! { , f32, u32, f32, u32, 23, 127 } +float_impls! { , f64, u64, f64, u64, 52, 1023 } + +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f32x2, u32x2, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f32x4, u32x4, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f32x8, u32x8, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f32x16, u32x16, f32, u32, 23, 127 } + +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f64x2, u64x2, f64, u64, 52, 1023 } +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f64x4, u64x4, f64, u64, 52, 1023 } +#[cfg(feature = "simd_support")] +float_impls! { feature = "simd_support", f64x8, u64x8, f64, u64, 52, 1023 } + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::const_rng; + + const EPSILON32: f32 = f32::EPSILON; + const EPSILON64: f64 = f64::EPSILON; + + macro_rules! test_f32 { + ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { + #[test] + fn $fnn() { + let two = $ty::splat(2.0); + + // StandardUniform + let mut zeros = const_rng(0); + assert_eq!(zeros.random::<$ty>(), $ZERO); + let mut one = const_rng(1 << 8 | 1 << (8 + 32)); + assert_eq!(one.random::<$ty>(), $EPSILON / two); + let mut max = const_rng(!0); + assert_eq!(max.random::<$ty>(), $ty::splat(1.0) - $EPSILON / two); + + // OpenClosed01 + let mut zeros = const_rng(0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), $ZERO + $EPSILON / two); + let mut one = const_rng(1 << 8 | 1 << (8 + 32)); + assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); + let mut max = const_rng(!0); + assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + $ty::splat(1.0)); + + // Open01 + let mut zeros = const_rng(0); + assert_eq!(zeros.sample::<$ty, _>(Open01), $ZERO + $EPSILON / two); + let mut one = const_rng(1 << 9 | 1 << (9 + 32)); + assert_eq!( + one.sample::<$ty, _>(Open01), + $EPSILON / two * $ty::splat(3.0) + ); + let mut max = const_rng(!0); + assert_eq!( + max.sample::<$ty, _>(Open01), + $ty::splat(1.0) - $EPSILON / two + ); + } + }; + } + test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 } + #[cfg(feature = "simd_support")] + test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) } + + macro_rules! test_f64 { + ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { + #[test] + fn $fnn() { + let two = $ty::splat(2.0); + + // StandardUniform + let mut zeros = const_rng(0); + assert_eq!(zeros.random::<$ty>(), $ZERO); + let mut one = const_rng(1 << 11); + assert_eq!(one.random::<$ty>(), $EPSILON / two); + let mut max = const_rng(!0); + assert_eq!(max.random::<$ty>(), $ty::splat(1.0) - $EPSILON / two); + + // OpenClosed01 + let mut zeros = const_rng(0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), $ZERO + $EPSILON / two); + let mut one = const_rng(1 << 11); + assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); + let mut max = const_rng(!0); + assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + $ty::splat(1.0)); + + // Open01 + let mut zeros = const_rng(0); + assert_eq!(zeros.sample::<$ty, _>(Open01), $ZERO + $EPSILON / two); + let mut one = const_rng(1 << 12); + assert_eq!( + one.sample::<$ty, _>(Open01), + $EPSILON / two * $ty::splat(3.0) + ); + let mut max = const_rng(!0); + assert_eq!( + max.sample::<$ty, _>(Open01), + $ty::splat(1.0) - $EPSILON / two + ); + } + }; + } + test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 } + #[cfg(feature = "simd_support")] + test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) } + #[cfg(feature = "simd_support")] + test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) } + #[cfg(feature = "simd_support")] + test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, + zero: T, + expected: &[T], + ) { + let mut rng = crate::test::rng(0x6f44f5646c2a7334); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(distr); + } + assert_eq!(&buf, expected); + } + + test_samples( + &StandardUniform, + 0f32, + &[0.0035963655, 0.7346052, 0.09778172], + ); + test_samples( + &StandardUniform, + 0f64, + &[0.7346051961657583, 0.20298547462974248, 0.8166436635290655], + ); + + test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]); + test_samples( + &OpenClosed01, + 0f64, + &[0.7346051961657584, 0.2029854746297426, 0.8166436635290656], + ); + + test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]); + test_samples( + &Open01, + 0f64, + &[0.7346051961657584, 0.20298547462974248, 0.8166436635290656], + ); + + #[cfg(feature = "simd_support")] + { + // We only test a sub-set of types here. Values are identical to + // non-SIMD types; we assume this pattern continues across all + // SIMD types. + + test_samples( + &StandardUniform, + f32x2::from([0.0, 0.0]), + &[ + f32x2::from([0.0035963655, 0.7346052]), + f32x2::from([0.09778172, 0.20298547]), + f32x2::from([0.34296435, 0.81664366]), + ], + ); + + test_samples( + &StandardUniform, + f64x2::from([0.0, 0.0]), + &[ + f64x2::from([0.7346051961657583, 0.20298547462974248]), + f64x2::from([0.8166436635290655, 0.7423708925400552]), + f64x2::from([0.16387782224016323, 0.9087068770169618]), + ], + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/integer.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/integer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/integer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/integer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,307 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The implementations of the `StandardUniform` distribution for integer types. + +use crate::distr::{Distribution, StandardUniform}; +use crate::Rng; +#[cfg(all(target_arch = "x86", feature = "simd_support"))] +use core::arch::x86::__m512i; +#[cfg(target_arch = "x86")] +use core::arch::x86::{__m128i, __m256i}; +#[cfg(all(target_arch = "x86_64", feature = "simd_support"))] +use core::arch::x86_64::__m512i; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::{__m128i, __m256i}; +use core::num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16, + NonZeroU32, NonZeroU64, NonZeroU8, +}; +#[cfg(feature = "simd_support")] +use core::simd::*; + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> u8 { + rng.next_u32() as u8 + } +} + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> u16 { + rng.next_u32() as u16 + } +} + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> u32 { + rng.next_u32() + } +} + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> u64 { + rng.next_u64() + } +} + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> u128 { + // Use LE; we explicitly generate one value before the next. + let x = u128::from(rng.next_u64()); + let y = u128::from(rng.next_u64()); + (y << 64) | x + } +} + +macro_rules! impl_int_from_uint { + ($ty:ty, $uty:ty) => { + impl Distribution<$ty> for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> $ty { + rng.random::<$uty>() as $ty + } + } + }; +} + +impl_int_from_uint! { i8, u8 } +impl_int_from_uint! { i16, u16 } +impl_int_from_uint! { i32, u32 } +impl_int_from_uint! { i64, u64 } +impl_int_from_uint! { i128, u128 } + +macro_rules! impl_nzint { + ($ty:ty, $new:path) => { + impl Distribution<$ty> for StandardUniform { + fn sample(&self, rng: &mut R) -> $ty { + loop { + if let Some(nz) = $new(rng.random()) { + break nz; + } + } + } + } + }; +} + +impl_nzint!(NonZeroU8, NonZeroU8::new); +impl_nzint!(NonZeroU16, NonZeroU16::new); +impl_nzint!(NonZeroU32, NonZeroU32::new); +impl_nzint!(NonZeroU64, NonZeroU64::new); +impl_nzint!(NonZeroU128, NonZeroU128::new); + +impl_nzint!(NonZeroI8, NonZeroI8::new); +impl_nzint!(NonZeroI16, NonZeroI16::new); +impl_nzint!(NonZeroI32, NonZeroI32::new); +impl_nzint!(NonZeroI64, NonZeroI64::new); +impl_nzint!(NonZeroI128, NonZeroI128::new); + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl Distribution<__m128i> for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> __m128i { + // NOTE: It's tempting to use the u128 impl here, but confusingly this + // results in different code (return via rdx, r10 instead of rax, rdx + // with u128 impl) and is much slower (+130 time). This version calls + // impls::fill_bytes_via_next but performs well. + + let mut buf = [0_u8; core::mem::size_of::<__m128i>()]; + rng.fill_bytes(&mut buf); + // x86 is little endian so no need for conversion + + // SAFETY: All byte sequences of `buf` represent values of the output type. + unsafe { core::mem::transmute(buf) } + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl Distribution<__m256i> for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> __m256i { + let mut buf = [0_u8; core::mem::size_of::<__m256i>()]; + rng.fill_bytes(&mut buf); + // x86 is little endian so no need for conversion + + // SAFETY: All byte sequences of `buf` represent values of the output type. + unsafe { core::mem::transmute(buf) } + } +} + +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + feature = "simd_support" +))] +impl Distribution<__m512i> for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> __m512i { + let mut buf = [0_u8; core::mem::size_of::<__m512i>()]; + rng.fill_bytes(&mut buf); + // x86 is little endian so no need for conversion + + // SAFETY: All byte sequences of `buf` represent values of the output type. + unsafe { core::mem::transmute(buf) } + } +} + +#[cfg(feature = "simd_support")] +macro_rules! simd_impl { + ($($ty:ty),+) => {$( + /// Requires nightly Rust and the [`simd_support`] feature + /// + /// [`simd_support`]: https://github.com/rust-random/rand#crate-features + #[cfg(feature = "simd_support")] + impl Distribution> for StandardUniform + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn sample(&self, rng: &mut R) -> Simd<$ty, LANES> { + let mut vec = Simd::default(); + rng.fill(vec.as_mut_array().as_mut_slice()); + vec + } + } + )+}; +} + +#[cfg(feature = "simd_support")] +simd_impl!(u8, i8, u16, i16, u32, i32, u64, i64); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_integers() { + let mut rng = crate::test::rng(806); + + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[test] + fn x86_integers() { + let mut rng = crate::test::rng(807); + + rng.sample::<__m128i, _>(StandardUniform); + rng.sample::<__m256i, _>(StandardUniform); + #[cfg(feature = "simd_support")] + rng.sample::<__m512i, _>(StandardUniform); + } + + #[test] + fn value_stability() { + fn test_samples(zero: T, expected: &[T]) + where + StandardUniform: Distribution, + { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(StandardUniform); + } + assert_eq!(&buf, expected); + } + + test_samples(0u8, &[9, 247, 111]); + test_samples(0u16, &[32265, 42999, 38255]); + test_samples(0u32, &[2220326409, 2575017975, 2018088303]); + test_samples( + 0u64, + &[ + 11059617991457472009, + 16096616328739788143, + 1487364411147516184, + ], + ); + test_samples( + 0u128, + &[ + 296930161868957086625409848350820761097, + 145644820879247630242265036535529306392, + 111087889832015897993126088499035356354, + ], + ); + + test_samples(0i8, &[9, -9, 111]); + // Skip further i* types: they are simple reinterpretation of u* samples + + #[cfg(feature = "simd_support")] + { + // We only test a sub-set of types here and make assumptions about the rest. + + test_samples( + u8x4::default(), + &[ + u8x4::from([9, 126, 87, 132]), + u8x4::from([247, 167, 123, 153]), + u8x4::from([111, 149, 73, 120]), + ], + ); + test_samples( + u8x8::default(), + &[ + u8x8::from([9, 126, 87, 132, 247, 167, 123, 153]), + u8x8::from([111, 149, 73, 120, 68, 171, 98, 223]), + u8x8::from([24, 121, 1, 50, 13, 46, 164, 20]), + ], + ); + + test_samples( + i64x8::default(), + &[ + i64x8::from([ + -7387126082252079607, + -2350127744969763473, + 1487364411147516184, + 7895421560427121838, + 602190064936008898, + 6022086574635100741, + -5080089175222015595, + -4066367846667249123, + ]), + i64x8::from([ + 9180885022207963908, + 3095981199532211089, + 6586075293021332726, + 419343203796414657, + 3186951873057035255, + 5287129228749947252, + 444726432079249540, + -1587028029513790706, + ]), + i64x8::from([ + 6075236523189346388, + 1351763722368165432, + -6192309979959753740, + -7697775502176768592, + -4482022114172078123, + 7522501477800909500, + -1837258847956201231, + -586926753024886735, + ]), + ], + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,214 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Generating random samples from probability distributions +//! +//! This module is the home of the [`Distribution`] trait and several of its +//! implementations. It is the workhorse behind some of the convenient +//! functionality of the [`Rng`] trait, e.g. [`Rng::random`] and of course +//! [`Rng::sample`]. +//! +//! Abstractly, a [probability distribution] describes the probability of +//! occurrence of each value in its sample space. +//! +//! More concretely, an implementation of `Distribution` for type `X` is an +//! algorithm for choosing values from the sample space (a subset of `T`) +//! according to the distribution `X` represents, using an external source of +//! randomness (an RNG supplied to the `sample` function). +//! +//! A type `X` may implement `Distribution` for multiple types `T`. +//! Any type implementing [`Distribution`] is stateless (i.e. immutable), +//! but it may have internal parameters set at construction time (for example, +//! [`Uniform`] allows specification of its sample space as a range within `T`). +//! +//! +//! # The Standard Uniform distribution +//! +//! The [`StandardUniform`] distribution is important to mention. This is the +//! distribution used by [`Rng::random`] and represents the "default" way to +//! produce a random value for many different types, including most primitive +//! types, tuples, arrays, and a few derived types. See the documentation of +//! [`StandardUniform`] for more details. +//! +//! Implementing [`Distribution`] for [`StandardUniform`] for user types `T` makes it +//! possible to generate type `T` with [`Rng::random`], and by extension also +//! with the [`random`] function. +//! +//! ## Other standard uniform distributions +//! +//! [`Alphanumeric`] is a simple distribution to sample random letters and +//! numbers of the `char` type; in contrast [`StandardUniform`] may sample any valid +//! `char`. +//! +//! There's also an [`Alphabetic`] distribution which acts similarly to [`Alphanumeric`] but +//! doesn't include digits. +//! +//! For floats (`f32`, `f64`), [`StandardUniform`] samples from `[0, 1)`. Also +//! provided are [`Open01`] (samples from `(0, 1)`) and [`OpenClosed01`] +//! (samples from `(0, 1]`). No option is provided to sample from `[0, 1]`; it +//! is suggested to use one of the above half-open ranges since the failure to +//! sample a value which would have a low chance of being sampled anyway is +//! rarely an issue in practice. +//! +//! # Parameterized Uniform distributions +//! +//! The [`Uniform`] distribution provides uniform sampling over a specified +//! range on a subset of the types supported by the above distributions. +//! +//! Implementations support single-value-sampling via +//! [`Rng::random_range(Range)`](Rng::random_range). +//! Where a fixed (non-`const`) range will be sampled many times, it is likely +//! faster to pre-construct a [`Distribution`] object using +//! [`Uniform::new`], [`Uniform::new_inclusive`] or `From`. +//! +//! # Non-uniform sampling +//! +//! Sampling a simple true/false outcome with a given probability has a name: +//! the [`Bernoulli`] distribution (this is used by [`Rng::random_bool`]). +//! +//! For weighted sampling of discrete values see the [`weighted`] module. +//! +//! This crate no longer includes other non-uniform distributions; instead +//! it is recommended that you use either [`rand_distr`] or [`statrs`]. +//! +//! +//! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution +//! [`rand_distr`]: https://crates.io/crates/rand_distr +//! [`statrs`]: https://crates.io/crates/statrs + +//! [`random`]: crate::random +//! [`rand_distr`]: https://crates.io/crates/rand_distr +//! [`statrs`]: https://crates.io/crates/statrs + +mod bernoulli; +mod distribution; +mod float; +mod integer; +mod other; +mod utils; + +#[doc(hidden)] +pub mod hidden_export { + pub use super::float::IntoFloat; // used by rand_distr +} +pub mod slice; +pub mod uniform; +#[cfg(feature = "alloc")] +pub mod weighted; + +pub use self::bernoulli::{Bernoulli, BernoulliError}; +#[cfg(feature = "alloc")] +pub use self::distribution::SampleString; +pub use self::distribution::{Distribution, Iter, Map}; +pub use self::float::{Open01, OpenClosed01}; +pub use self::other::{Alphabetic, Alphanumeric}; +#[doc(inline)] +pub use self::uniform::Uniform; + +#[allow(unused)] +use crate::Rng; + +/// The Standard Uniform distribution +/// +/// This [`Distribution`] is the *standard* parameterization of [`Uniform`]. Bounds +/// are selected according to the output type. +/// +/// Assuming the provided `Rng` is well-behaved, these implementations +/// generate values with the following ranges and distributions: +/// +/// * Integers (`i8`, `i32`, `u64`, etc.) are uniformly distributed +/// over the whole range of the type (thus each possible value may be sampled +/// with equal probability). +/// * `char` is uniformly distributed over all Unicode scalar values, i.e. all +/// code points in the range `0...0x10_FFFF`, except for the range +/// `0xD800...0xDFFF` (the surrogate code points). This includes +/// unassigned/reserved code points. +/// For some uses, the [`Alphanumeric`] or [`Alphabetic`] distribution will be more +/// appropriate. +/// * `bool` samples `false` or `true`, each with probability 0.5. +/// * Floating point types (`f32` and `f64`) are uniformly distributed in the +/// half-open range `[0, 1)`. See also the [notes below](#floating-point-implementation). +/// * Wrapping integers ([`Wrapping`]), besides the type identical to their +/// normal integer variants. +/// * Non-zero integers ([`NonZeroU8`]), which are like their normal integer +/// variants but cannot sample zero. +/// +/// The `StandardUniform` distribution also supports generation of the following +/// compound types where all component types are supported: +/// +/// * Tuples (up to 12 elements): each element is sampled sequentially and +/// independently (thus, assuming a well-behaved RNG, there is no correlation +/// between elements). +/// * Arrays `[T; n]` where `T` is supported. Each element is sampled +/// sequentially and independently. Note that for small `T` this usually +/// results in the RNG discarding random bits; see also [`Rng::fill`] which +/// offers a more efficient approach to filling an array of integer types +/// with random data. +/// * SIMD types (requires [`simd_support`] feature) like x86's [`__m128i`] +/// and `std::simd`'s [`u32x4`], [`f32x4`] and [`mask32x4`] types are +/// effectively arrays of integer or floating-point types. Each lane is +/// sampled independently, potentially with more efficient random-bit-usage +/// (and a different resulting value) than would be achieved with sequential +/// sampling (as with the array types above). +/// +/// ## Custom implementations +/// +/// The [`StandardUniform`] distribution may be implemented for user types as follows: +/// +/// ``` +/// # #![allow(dead_code)] +/// use rand::Rng; +/// use rand::distr::{Distribution, StandardUniform}; +/// +/// struct MyF32 { +/// x: f32, +/// } +/// +/// impl Distribution for StandardUniform { +/// fn sample(&self, rng: &mut R) -> MyF32 { +/// MyF32 { x: rng.random() } +/// } +/// } +/// ``` +/// +/// ## Example usage +/// ``` +/// use rand::prelude::*; +/// use rand::distr::StandardUniform; +/// +/// let val: f32 = rand::rng().sample(StandardUniform); +/// println!("f32 from [0, 1): {}", val); +/// ``` +/// +/// # Floating point implementation +/// The floating point implementations for `StandardUniform` generate a random value in +/// the half-open interval `[0, 1)`, i.e. including 0 but not 1. +/// +/// All values that can be generated are of the form `n * ε/2`. For `f32` +/// the 24 most significant random bits of a `u32` are used and for `f64` the +/// 53 most significant bits of a `u64` are used. The conversion uses the +/// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`. +/// +/// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which +/// samples from `(0, 1]` and `Rng::random_range(0..1)` which also samples from +/// `[0, 1)`. Note that `Open01` uses transmute-based methods which yield 1 bit +/// less precision but may perform faster on some architectures (on modern Intel +/// CPUs all methods have approximately equal performance). +/// +/// [`Uniform`]: uniform::Uniform +/// [`Wrapping`]: std::num::Wrapping +/// [`NonZeroU8`]: std::num::NonZeroU8 +/// [`__m128i`]: https://doc.rust-lang.org/core/arch/x86/struct.__m128i.html +/// [`u32x4`]: std::simd::u32x4 +/// [`f32x4`]: std::simd::f32x4 +/// [`mask32x4`]: std::simd::mask32x4 +/// [`simd_support`]: https://github.com/rust-random/rand#crate-features +#[derive(Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct StandardUniform; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/other.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/other.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/other.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/other.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,444 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The implementations of the `StandardUniform` distribution for other built-in types. + +#[cfg(feature = "alloc")] +use alloc::string::String; +use core::array; +use core::char; +use core::num::Wrapping; + +#[cfg(feature = "alloc")] +use crate::distr::SampleString; +use crate::distr::{Distribution, StandardUniform, Uniform}; +use crate::Rng; + +#[cfg(feature = "simd_support")] +use core::simd::prelude::*; +#[cfg(feature = "simd_support")] +use core::simd::{LaneCount, MaskElement, SupportedLaneCount}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +// ----- Sampling distributions ----- + +/// Sample a `u8`, uniformly distributed over ASCII letters and numbers: +/// a-z, A-Z and 0-9. +/// +/// # Example +/// +/// ``` +/// use rand::Rng; +/// use rand::distr::Alphanumeric; +/// +/// let mut rng = rand::rng(); +/// let chars: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect(); +/// println!("Random chars: {}", chars); +/// ``` +/// +/// The [`SampleString`] trait provides an easier method of generating +/// a random [`String`], and offers more efficient allocation: +/// ``` +/// use rand::distr::{Alphanumeric, SampleString}; +/// let string = Alphanumeric.sample_string(&mut rand::rng(), 16); +/// println!("Random string: {}", string); +/// ``` +/// +/// # Passwords +/// +/// Users sometimes ask whether it is safe to use a string of random characters +/// as a password. In principle, all RNGs in Rand implementing `CryptoRng` are +/// suitable as a source of randomness for generating passwords (if they are +/// properly seeded), but it is more conservative to only use randomness +/// directly from the operating system via the `getrandom` crate, or the +/// corresponding bindings of a crypto library. +/// +/// When generating passwords or keys, it is important to consider the threat +/// model and in some cases the memorability of the password. This is out of +/// scope of the Rand project, and therefore we defer to the following +/// references: +/// +/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength) +/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware) +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Alphanumeric; + +/// Sample a [`u8`], uniformly distributed over letters: +/// a-z and A-Z. +/// +/// # Example +/// +/// You're able to generate random Alphabetic characters via mapping or via the +/// [`SampleString::sample_string`] method like so: +/// +/// ``` +/// use rand::Rng; +/// use rand::distr::{Alphabetic, SampleString}; +/// +/// // Manual mapping +/// let mut rng = rand::rng(); +/// let chars: String = (0..7).map(|_| rng.sample(Alphabetic) as char).collect(); +/// println!("Random chars: {}", chars); +/// +/// // Using [`SampleString::sample_string`] +/// let string = Alphabetic.sample_string(&mut rand::rng(), 16); +/// println!("Random string: {}", string); +/// ``` +/// +/// # Passwords +/// +/// Refer to [`Alphanumeric#Passwords`]. +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Alphabetic; + +// ----- Implementations of distributions ----- + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> char { + // A valid `char` is either in the interval `[0, 0xD800)` or + // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in + // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is + // reserved for surrogates. This is the size of that gap. + const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1; + + // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used, but it + // seemed slower. + let range = Uniform::new(GAP_SIZE, 0x11_0000).unwrap(); + + let mut n = range.sample(rng); + if n <= 0xDFFF { + n -= GAP_SIZE; + } + // SAFETY: We ensure above that `n` represents a `char`. + unsafe { char::from_u32_unchecked(n) } + } +} + +#[cfg(feature = "alloc")] +impl SampleString for StandardUniform { + fn append_string(&self, rng: &mut R, s: &mut String, len: usize) { + // A char is encoded with at most four bytes, thus this reservation is + // guaranteed to be sufficient. We do not shrink_to_fit afterwards so + // that repeated usage on the same `String` buffer does not reallocate. + s.reserve(4 * len); + s.extend(Distribution::::sample_iter(self, rng).take(len)); + } +} + +impl Distribution for Alphanumeric { + fn sample(&self, rng: &mut R) -> u8 { + const RANGE: u32 = 26 + 26 + 10; + const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + // We can pick from 62 characters. This is so close to a power of 2, 64, + // that we can do better than `Uniform`. Use a simple bitshift and + // rejection sampling. We do not use a bitmask, because for small RNGs + // the most significant bits are usually of higher quality. + loop { + let var = rng.next_u32() >> (32 - 6); + if var < RANGE { + return GEN_ASCII_STR_CHARSET[var as usize]; + } + } + } +} + +impl Distribution for Alphabetic { + fn sample(&self, rng: &mut R) -> u8 { + const RANGE: u8 = 26 + 26; + + let offset = rng.random_range(0..RANGE) + b'A'; + + // Account for upper-cases + offset + (offset > b'Z') as u8 * (b'a' - b'Z' - 1) + } +} + +#[cfg(feature = "alloc")] +impl SampleString for Alphanumeric { + fn append_string(&self, rng: &mut R, string: &mut String, len: usize) { + // SAFETY: `self` only samples alphanumeric characters, which are valid UTF-8. + unsafe { + let v = string.as_mut_vec(); + v.extend( + self.sample_iter(rng) + .take(len) + .inspect(|b| debug_assert!(b.is_ascii_alphanumeric())), + ); + } + } +} + +#[cfg(feature = "alloc")] +impl SampleString for Alphabetic { + fn append_string(&self, rng: &mut R, string: &mut String, len: usize) { + // SAFETY: With this distribution we guarantee that we're working with valid ASCII + // characters. + // See [#1590](https://github.com/rust-random/rand/issues/1590). + unsafe { + let v = string.as_mut_vec(); + v.reserve_exact(len); + v.extend(self.sample_iter(rng).take(len)); + } + } +} + +impl Distribution for StandardUniform { + #[inline] + fn sample(&self, rng: &mut R) -> bool { + // We can compare against an arbitrary bit of an u32 to get a bool. + // Because the least significant bits of a lower quality RNG can have + // simple patterns, we compare against the most significant bit. This is + // easiest done using a sign test. + (rng.next_u32() as i32) < 0 + } +} + +/// Note that on some hardware like x86/64 mask operations like [`_mm_blendv_epi8`] +/// only care about a single bit. This means that you could use uniform random bits +/// directly: +/// +/// ```ignore +/// // this may be faster... +/// let x = unsafe { _mm_blendv_epi8(a.into(), b.into(), rng.random::<__m128i>()) }; +/// +/// // ...than this +/// let x = rng.random::().select(b, a); +/// ``` +/// +/// Since most bits are unused you could also generate only as many bits as you need, i.e.: +/// ``` +/// #![feature(portable_simd)] +/// use std::simd::prelude::*; +/// use rand::prelude::*; +/// let mut rng = rand::rng(); +/// +/// let x = u16x8::splat(rng.random::() as u16); +/// let mask = u16x8::splat(1) << u16x8::from([0, 1, 2, 3, 4, 5, 6, 7]); +/// let rand_mask = (x & mask).simd_eq(mask); +/// ``` +/// +/// [`_mm_blendv_epi8`]: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_blendv_epi8&ig_expand=514/ +/// [`simd_support`]: https://github.com/rust-random/rand#crate-features +#[cfg(feature = "simd_support")] +impl Distribution> for StandardUniform +where + T: MaskElement + Default, + LaneCount: SupportedLaneCount, + StandardUniform: Distribution>, + Simd: SimdPartialOrd>, +{ + #[inline] + fn sample(&self, rng: &mut R) -> Mask { + // `MaskElement` must be a signed integer, so this is equivalent + // to the scalar `i32 < 0` method + let var = rng.random::>(); + var.simd_lt(Simd::default()) + } +} + +/// Implement `Distribution<(A, B, C, ...)> for StandardUniform`, using the list of +/// identifiers +macro_rules! tuple_impl { + ($($tyvar:ident)*) => { + impl< $($tyvar,)* > Distribution<($($tyvar,)*)> for StandardUniform + where $( + StandardUniform: Distribution< $tyvar >, + )* + { + #[inline] + fn sample(&self, rng: &mut R) -> ( $($tyvar,)* ) { + let out = ($( + // use the $tyvar's to get the appropriate number of + // repeats (they're not actually needed) + rng.random::<$tyvar>() + ,)*); + + // Suppress the unused variable warning for empty tuple + let _rng = rng; + + out + } + } + } +} + +/// Looping wrapper for `tuple_impl`. Given (A, B, C), it also generates +/// implementations for (A, B) and (A,) +macro_rules! tuple_impls { + ($($tyvar:ident)*) => {tuple_impls!{[] $($tyvar)*}}; + + ([$($prefix:ident)*] $head:ident $($tail:ident)*) => { + tuple_impl!{$($prefix)*} + tuple_impls!{[$($prefix)* $head] $($tail)*} + }; + + + ([$($prefix:ident)*]) => { + tuple_impl!{$($prefix)*} + }; + +} + +tuple_impls! {A B C D E F G H I J K L} + +impl Distribution<[T; N]> for StandardUniform +where + StandardUniform: Distribution, +{ + #[inline] + fn sample(&self, rng: &mut R) -> [T; N] { + array::from_fn(|_| rng.random()) + } +} + +impl Distribution> for StandardUniform +where + StandardUniform: Distribution, +{ + #[inline] + fn sample(&self, rng: &mut R) -> Wrapping { + Wrapping(rng.random()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::RngCore; + + #[test] + fn test_misc() { + let rng: &mut dyn RngCore = &mut crate::test::rng(820); + + rng.sample::(StandardUniform); + rng.sample::(StandardUniform); + } + + #[cfg(feature = "alloc")] + #[test] + fn test_chars() { + use core::iter; + let mut rng = crate::test::rng(805); + + // Test by generating a relatively large number of chars, so we also + // take the rejection sampling path. + let word: String = iter::repeat(()) + .map(|()| rng.random::()) + .take(1000) + .collect(); + assert!(!word.is_empty()); + } + + #[test] + fn test_alphanumeric() { + let mut rng = crate::test::rng(806); + + // Test by generating a relatively large number of chars, so we also + // take the rejection sampling path. + let mut incorrect = false; + for _ in 0..100 { + let c: char = rng.sample(Alphanumeric).into(); + incorrect |= !c.is_ascii_alphanumeric(); + } + assert!(!incorrect); + } + + #[test] + fn test_alphabetic() { + let mut rng = crate::test::rng(806); + + // Test by generating a relatively large number of chars, so we also + // take the rejection sampling path. + let mut incorrect = false; + for _ in 0..100 { + let c: char = rng.sample(Alphabetic).into(); + incorrect |= !c.is_ascii_alphabetic(); + } + assert!(!incorrect); + } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, + zero: T, + expected: &[T], + ) { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 5]; + for x in &mut buf { + *x = rng.sample(distr); + } + assert_eq!(&buf, expected); + } + + test_samples( + &StandardUniform, + 'a', + &[ + '\u{8cdac}', + '\u{a346a}', + '\u{80120}', + '\u{ed692}', + '\u{35888}', + ], + ); + test_samples(&Alphanumeric, 0, &[104, 109, 101, 51, 77]); + test_samples(&Alphabetic, 0, &[97, 102, 89, 116, 75]); + test_samples(&StandardUniform, false, &[true, true, false, true, false]); + test_samples( + &StandardUniform, + Wrapping(0i32), + &[ + Wrapping(-2074640887), + Wrapping(-1719949321), + Wrapping(2018088303), + Wrapping(-547181756), + Wrapping(838957336), + ], + ); + + // We test only sub-sets of tuple and array impls + test_samples(&StandardUniform, (), &[(), (), (), (), ()]); + test_samples( + &StandardUniform, + (false,), + &[(true,), (true,), (false,), (true,), (false,)], + ); + test_samples( + &StandardUniform, + (false, false), + &[ + (true, true), + (false, true), + (false, false), + (true, false), + (false, false), + ], + ); + + test_samples(&StandardUniform, [0u8; 0], &[[], [], [], [], []]); + test_samples( + &StandardUniform, + [0u8; 3], + &[ + [9, 247, 111], + [68, 24, 13], + [174, 19, 194], + [172, 69, 213], + [149, 207, 29], + ], + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/slice.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/slice.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/slice.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/slice.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,167 @@ +// Copyright 2021 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Distributions over slices + +use core::num::NonZeroUsize; + +use crate::distr::uniform::{UniformSampler, UniformUsize}; +use crate::distr::Distribution; +#[cfg(feature = "alloc")] +use alloc::string::String; + +/// A distribution to uniformly sample elements of a slice +/// +/// Like [`IndexedRandom::choose`], this uniformly samples elements of a slice +/// without modification of the slice (so called "sampling with replacement"). +/// This distribution object may be a little faster for repeated sampling (but +/// slower for small numbers of samples). +/// +/// ## Examples +/// +/// Since this is a distribution, [`Rng::sample_iter`] and +/// [`Distribution::sample_iter`] may be used, for example: +/// ``` +/// use rand::distr::{Distribution, slice::Choose}; +/// +/// let vowels = ['a', 'e', 'i', 'o', 'u']; +/// let vowels_dist = Choose::new(&vowels).unwrap(); +/// +/// // build a string of 10 vowels +/// let vowel_string: String = vowels_dist +/// .sample_iter(&mut rand::rng()) +/// .take(10) +/// .collect(); +/// +/// println!("{}", vowel_string); +/// assert_eq!(vowel_string.len(), 10); +/// assert!(vowel_string.chars().all(|c| vowels.contains(&c))); +/// ``` +/// +/// For a single sample, [`IndexedRandom::choose`] may be preferred: +/// ``` +/// use rand::seq::IndexedRandom; +/// +/// let vowels = ['a', 'e', 'i', 'o', 'u']; +/// let mut rng = rand::rng(); +/// +/// println!("{}", vowels.choose(&mut rng).unwrap()); +/// ``` +/// +/// [`IndexedRandom::choose`]: crate::seq::IndexedRandom::choose +/// [`Rng::sample_iter`]: crate::Rng::sample_iter +#[derive(Debug, Clone, Copy)] +pub struct Choose<'a, T> { + slice: &'a [T], + range: UniformUsize, + num_choices: NonZeroUsize, +} + +impl<'a, T> Choose<'a, T> { + /// Create a new `Choose` instance which samples uniformly from the slice. + /// + /// Returns error [`Empty`] if the slice is empty. + pub fn new(slice: &'a [T]) -> Result { + let num_choices = NonZeroUsize::new(slice.len()).ok_or(Empty)?; + + Ok(Self { + slice, + range: UniformUsize::new(0, num_choices.get()).unwrap(), + num_choices, + }) + } + + /// Returns the count of choices in this distribution + pub fn num_choices(&self) -> NonZeroUsize { + self.num_choices + } +} + +impl<'a, T> Distribution<&'a T> for Choose<'a, T> { + fn sample(&self, rng: &mut R) -> &'a T { + let idx = self.range.sample(rng); + + debug_assert!( + idx < self.slice.len(), + "Uniform::new(0, {}) somehow returned {}", + self.slice.len(), + idx + ); + + // Safety: at construction time, it was ensured that the slice was + // non-empty, and that the `Uniform` range produces values in range + // for the slice + unsafe { self.slice.get_unchecked(idx) } + } +} + +/// Error: empty slice +/// +/// This error is returned when [`Choose::new`] is given an empty slice. +#[derive(Debug, Clone, Copy)] +pub struct Empty; + +impl core::fmt::Display for Empty { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "Tried to create a `rand::distr::slice::Choose` with an empty slice" + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Empty {} + +#[cfg(feature = "alloc")] +impl super::SampleString for Choose<'_, char> { + fn append_string(&self, rng: &mut R, string: &mut String, len: usize) { + // Get the max char length to minimize extra space. + // Limit this check to avoid searching for long slice. + let max_char_len = if self.slice.len() < 200 { + self.slice + .iter() + .try_fold(1, |max_len, char| { + // When the current max_len is 4, the result max_char_len will be 4. + Some(max_len.max(char.len_utf8())).filter(|len| *len < 4) + }) + .unwrap_or(4) + } else { + 4 + }; + + // Split the extension of string to reuse the unused capacities. + // Skip the split for small length or only ascii slice. + let mut extend_len = if max_char_len == 1 || len < 100 { + len + } else { + len / 4 + }; + let mut remain_len = len; + while extend_len > 0 { + string.reserve(max_char_len * extend_len); + string.extend(self.sample_iter(&mut *rng).take(extend_len)); + remain_len -= extend_len; + extend_len = extend_len.min(remain_len); + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use core::iter; + + #[test] + fn value_stability() { + let rng = crate::test::rng(651); + let slice = Choose::new(b"escaped emus explore extensively").unwrap(); + let expected = b"eaxee"; + assert!(iter::zip(slice.sample_iter(rng), expected).all(|(a, b)| a == b)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,622 @@ +// Copyright 2018-2020 Developers of the Rand project. +// Copyright 2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A distribution uniformly sampling numbers within a given range. +//! +//! [`Uniform`] is the standard distribution to sample uniformly from a range; +//! e.g. `Uniform::new_inclusive(1, 6).unwrap()` can sample integers from 1 to 6, like a +//! standard die. [`Rng::random_range`] is implemented over [`Uniform`]. +//! +//! # Example usage +//! +//! ``` +//! use rand::Rng; +//! use rand::distr::Uniform; +//! +//! let mut rng = rand::rng(); +//! let side = Uniform::new(-10.0, 10.0).unwrap(); +//! +//! // sample between 1 and 10 points +//! for _ in 0..rng.random_range(1..=10) { +//! // sample a point from the square with sides -10 - 10 in two dimensions +//! let (x, y) = (rng.sample(side), rng.sample(side)); +//! println!("Point: {}, {}", x, y); +//! } +//! ``` +//! +//! # Extending `Uniform` to support a custom type +//! +//! To extend [`Uniform`] to support your own types, write a back-end which +//! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] +//! helper trait to "register" your back-end. See the `MyF32` example below. +//! +//! At a minimum, the back-end needs to store any parameters needed for sampling +//! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. +//! Those methods should include an assertion to check the range is valid (i.e. +//! `low < high`). The example below merely wraps another back-end. +//! +//! The `new`, `new_inclusive`, `sample_single` and `sample_single_inclusive` +//! functions use arguments of +//! type `SampleBorrow` to support passing in values by reference or +//! by value. In the implementation of these functions, you can choose to +//! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose +//! to copy or clone the value, whatever is appropriate for your type. +//! +//! ``` +//! use rand::prelude::*; +//! use rand::distr::uniform::{Uniform, SampleUniform, +//! UniformSampler, UniformFloat, SampleBorrow, Error}; +//! +//! struct MyF32(f32); +//! +//! #[derive(Clone, Copy, Debug)] +//! struct UniformMyF32(UniformFloat); +//! +//! impl UniformSampler for UniformMyF32 { +//! type X = MyF32; +//! +//! fn new(low: B1, high: B2) -> Result +//! where B1: SampleBorrow + Sized, +//! B2: SampleBorrow + Sized +//! { +//! UniformFloat::::new(low.borrow().0, high.borrow().0).map(UniformMyF32) +//! } +//! fn new_inclusive(low: B1, high: B2) -> Result +//! where B1: SampleBorrow + Sized, +//! B2: SampleBorrow + Sized +//! { +//! UniformFloat::::new_inclusive(low.borrow().0, high.borrow().0).map(UniformMyF32) +//! } +//! fn sample(&self, rng: &mut R) -> Self::X { +//! MyF32(self.0.sample(rng)) +//! } +//! } +//! +//! impl SampleUniform for MyF32 { +//! type Sampler = UniformMyF32; +//! } +//! +//! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); +//! let uniform = Uniform::new(low, high).unwrap(); +//! let x = uniform.sample(&mut rand::rng()); +//! ``` +//! +//! [`SampleUniform`]: crate::distr::uniform::SampleUniform +//! [`UniformSampler`]: crate::distr::uniform::UniformSampler +//! [`UniformInt`]: crate::distr::uniform::UniformInt +//! [`UniformFloat`]: crate::distr::uniform::UniformFloat +//! [`UniformDuration`]: crate::distr::uniform::UniformDuration +//! [`SampleBorrow::borrow`]: crate::distr::uniform::SampleBorrow::borrow + +#[path = "uniform_float.rs"] +mod float; +#[doc(inline)] +pub use float::UniformFloat; + +#[path = "uniform_int.rs"] +mod int; +#[doc(inline)] +pub use int::{UniformInt, UniformUsize}; + +#[path = "uniform_other.rs"] +mod other; +#[doc(inline)] +pub use other::{UniformChar, UniformDuration}; + +use core::fmt; +use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive}; + +use crate::distr::Distribution; +use crate::{Rng, RngCore}; + +/// Error type returned from [`Uniform::new`] and `new_inclusive`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Error { + /// `low > high`, or equal in case of exclusive range. + EmptyRange, + /// Input or range `high - low` is non-finite. Not relevant to integer types. + NonFinite, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::EmptyRange => "low > high (or equal if exclusive) in uniform distribution", + Error::NonFinite => "Non-finite range in uniform distribution", + }) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// Sample values uniformly between two bounds. +/// +/// # Construction +/// +/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform +/// distribution sampling from the given `low` and `high` limits. `Uniform` may +/// also be constructed via [`TryFrom`] as in `Uniform::try_from(1..=6).unwrap()`. +/// +/// Constructors may do extra work up front to allow faster sampling of multiple +/// values. Where only a single sample is required it is suggested to use +/// [`Rng::random_range`] or one of the `sample_single` methods instead. +/// +/// When sampling from a constant range, many calculations can happen at +/// compile-time and all methods should be fast; for floating-point ranges and +/// the full range of integer types, this should have comparable performance to +/// the [`StandardUniform`](super::StandardUniform) distribution. +/// +/// # Provided implementations +/// +/// - `char` ([`UniformChar`]): samples a range over the implementation for `u32` +/// - `f32`, `f64` ([`UniformFloat`]): samples approximately uniformly within a +/// range; bias may be present in the least-significant bit of the significand +/// and the limits of the input range may be sampled even when an open +/// (exclusive) range is used +/// - Integer types ([`UniformInt`]) may show a small bias relative to the +/// expected uniform distribution of output. In the worst case, bias affects +/// 1 in `2^n` samples where n is 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96 +/// (`i32` and `u32`), 64 (`i64` and `u64`), 128 (`i128` and `u128`). +/// The `unbiased` feature flag fixes this bias. +/// - `usize` ([`UniformUsize`]) is handled specially, using the `u32` +/// implementation where possible to enable portable results across 32-bit and +/// 64-bit CPU architectures. +/// - `Duration` ([`UniformDuration`]): samples a range over the implementation +/// for `u32` or `u64` +/// - SIMD types (requires [`simd_support`] feature) like x86's [`__m128i`] +/// and `std::simd`'s [`u32x4`], [`f32x4`] and [`mask32x4`] types are +/// effectively arrays of integer or floating-point types. Each lane is +/// sampled independently from its own range, potentially with more efficient +/// random-bit-usage than would be achieved with sequential sampling. +/// +/// # Example +/// +/// ``` +/// use rand::distr::{Distribution, Uniform}; +/// +/// let between = Uniform::try_from(10..10000).unwrap(); +/// let mut rng = rand::rng(); +/// let mut sum = 0; +/// for _ in 0..1000 { +/// sum += between.sample(&mut rng); +/// } +/// println!("{}", sum); +/// ``` +/// +/// For a single sample, [`Rng::random_range`] may be preferred: +/// +/// ``` +/// use rand::Rng; +/// +/// let mut rng = rand::rng(); +/// println!("{}", rng.random_range(0..10)); +/// ``` +/// +/// [`new`]: Uniform::new +/// [`new_inclusive`]: Uniform::new_inclusive +/// [`Rng::random_range`]: Rng::random_range +/// [`__m128i`]: https://doc.rust-lang.org/core/arch/x86/struct.__m128i.html +/// [`u32x4`]: std::simd::u32x4 +/// [`f32x4`]: std::simd::f32x4 +/// [`mask32x4`]: std::simd::mask32x4 +/// [`simd_support`]: https://github.com/rust-random/rand#crate-features +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(bound(serialize = "X::Sampler: Serialize")))] +#[cfg_attr( + feature = "serde", + serde(bound(deserialize = "X::Sampler: Deserialize<'de>")) +)] +pub struct Uniform(X::Sampler); + +impl Uniform { + /// Create a new `Uniform` instance, which samples uniformly from the half + /// open range `[low, high)` (excluding `high`). + /// + /// For discrete types (e.g. integers), samples will always be strictly less + /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), + /// samples may equal `high` due to loss of precision but may not be + /// greater than `high`. + /// + /// Fails if `low >= high`, or if `low`, `high` or the range `high - low` is + /// non-finite. In release mode, only the range is checked. + pub fn new(low: B1, high: B2) -> Result, Error> + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + X::Sampler::new(low, high).map(Uniform) + } + + /// Create a new `Uniform` instance, which samples uniformly from the closed + /// range `[low, high]` (inclusive). + /// + /// Fails if `low > high`, or if `low`, `high` or the range `high - low` is + /// non-finite. In release mode, only the range is checked. + pub fn new_inclusive(low: B1, high: B2) -> Result, Error> + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + X::Sampler::new_inclusive(low, high).map(Uniform) + } +} + +impl Distribution for Uniform { + fn sample(&self, rng: &mut R) -> X { + self.0.sample(rng) + } +} + +/// Helper trait for creating objects using the correct implementation of +/// [`UniformSampler`] for the sampling type. +/// +/// See the [module documentation] on how to implement [`Uniform`] range +/// sampling for a custom type. +/// +/// [module documentation]: crate::distr::uniform +pub trait SampleUniform: Sized { + /// The `UniformSampler` implementation supporting type `X`. + type Sampler: UniformSampler; +} + +/// Helper trait handling actual uniform sampling. +/// +/// See the [module documentation] on how to implement [`Uniform`] range +/// sampling for a custom type. +/// +/// Implementation of [`sample_single`] is optional, and is only useful when +/// the implementation can be faster than `Self::new(low, high).sample(rng)`. +/// +/// [module documentation]: crate::distr::uniform +/// [`sample_single`]: UniformSampler::sample_single +pub trait UniformSampler: Sized { + /// The type sampled by this implementation. + type X; + + /// Construct self, with inclusive lower bound and exclusive upper bound `[low, high)`. + /// + /// For discrete types (e.g. integers), samples will always be strictly less + /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), + /// samples may equal `high` due to loss of precision but may not be + /// greater than `high`. + /// + /// Usually users should not call this directly but prefer to use + /// [`Uniform::new`]. + fn new(low: B1, high: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; + + /// Construct self, with inclusive bounds `[low, high]`. + /// + /// Usually users should not call this directly but prefer to use + /// [`Uniform::new_inclusive`]. + fn new_inclusive(low: B1, high: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; + + /// Sample a value. + fn sample(&self, rng: &mut R) -> Self::X; + + /// Sample a single value uniformly from a range with inclusive lower bound + /// and exclusive upper bound `[low, high)`. + /// + /// For discrete types (e.g. integers), samples will always be strictly less + /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), + /// samples may equal `high` due to loss of precision but may not be + /// greater than `high`. + /// + /// By default this is implemented using + /// `UniformSampler::new(low, high).sample(rng)`. However, for some types + /// more optimal implementations for single usage may be provided via this + /// method (which is the case for integers and floats). + /// Results may not be identical. + /// + /// Note that to use this method in a generic context, the type needs to be + /// retrieved via `SampleUniform::Sampler` as follows: + /// ``` + /// use rand::distr::uniform::{SampleUniform, UniformSampler}; + /// # #[allow(unused)] + /// fn sample_from_range(lb: T, ub: T) -> T { + /// let mut rng = rand::rng(); + /// ::Sampler::sample_single(lb, ub, &mut rng).unwrap() + /// } + /// ``` + fn sample_single( + low: B1, + high: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let uniform: Self = UniformSampler::new(low, high)?; + Ok(uniform.sample(rng)) + } + + /// Sample a single value uniformly from a range with inclusive lower bound + /// and inclusive upper bound `[low, high]`. + /// + /// By default this is implemented using + /// `UniformSampler::new_inclusive(low, high).sample(rng)`. However, for + /// some types more optimal implementations for single usage may be provided + /// via this method. + /// Results may not be identical. + fn sample_single_inclusive( + low: B1, + high: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let uniform: Self = UniformSampler::new_inclusive(low, high)?; + Ok(uniform.sample(rng)) + } +} + +impl TryFrom> for Uniform { + type Error = Error; + + fn try_from(r: Range) -> Result, Error> { + Uniform::new(r.start, r.end) + } +} + +impl TryFrom> for Uniform { + type Error = Error; + + fn try_from(r: ::core::ops::RangeInclusive) -> Result, Error> { + Uniform::new_inclusive(r.start(), r.end()) + } +} + +/// Helper trait similar to [`Borrow`] but implemented +/// only for [`SampleUniform`] and references to [`SampleUniform`] +/// in order to resolve ambiguity issues. +/// +/// [`Borrow`]: std::borrow::Borrow +pub trait SampleBorrow { + /// Immutably borrows from an owned value. See [`Borrow::borrow`] + /// + /// [`Borrow::borrow`]: std::borrow::Borrow::borrow + fn borrow(&self) -> &Borrowed; +} +impl SampleBorrow for Borrowed +where + Borrowed: SampleUniform, +{ + #[inline(always)] + fn borrow(&self) -> &Borrowed { + self + } +} +impl SampleBorrow for &Borrowed +where + Borrowed: SampleUniform, +{ + #[inline(always)] + fn borrow(&self) -> &Borrowed { + self + } +} + +/// Range that supports generating a single sample efficiently. +/// +/// Any type implementing this trait can be used to specify the sampled range +/// for `Rng::random_range`. +pub trait SampleRange { + /// Generate a sample from the given range. + fn sample_single(self, rng: &mut R) -> Result; + + /// Check whether the range is empty. + fn is_empty(&self) -> bool; +} + +impl SampleRange for Range { + #[inline] + fn sample_single(self, rng: &mut R) -> Result { + T::Sampler::sample_single(self.start, self.end, rng) + } + + #[inline] + fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +impl SampleRange for RangeInclusive { + #[inline] + fn sample_single(self, rng: &mut R) -> Result { + T::Sampler::sample_single_inclusive(self.start(), self.end(), rng) + } + + #[inline] + fn is_empty(&self) -> bool { + !(self.start() <= self.end()) + } +} + +macro_rules! impl_sample_range_u { + ($t:ty) => { + impl SampleRange<$t> for RangeTo<$t> { + #[inline] + fn sample_single(self, rng: &mut R) -> Result<$t, Error> { + <$t as SampleUniform>::Sampler::sample_single(0, self.end, rng) + } + + #[inline] + fn is_empty(&self) -> bool { + 0 == self.end + } + } + + impl SampleRange<$t> for RangeToInclusive<$t> { + #[inline] + fn sample_single(self, rng: &mut R) -> Result<$t, Error> { + <$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng) + } + + #[inline] + fn is_empty(&self) -> bool { + false + } + } + }; +} + +impl_sample_range_u!(u8); +impl_sample_range_u!(u16); +impl_sample_range_u!(u32); +impl_sample_range_u!(u64); +impl_sample_range_u!(u128); +impl_sample_range_u!(usize); + +#[cfg(test)] +mod tests { + use super::*; + use core::time::Duration; + + #[test] + #[cfg(feature = "serde")] + fn test_uniform_serialization() { + let unit_box: Uniform = Uniform::new(-1, 1).unwrap(); + let de_unit_box: Uniform = + bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + assert_eq!(unit_box.0, de_unit_box.0); + + let unit_box: Uniform = Uniform::new(-1., 1.).unwrap(); + let de_unit_box: Uniform = + bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + assert_eq!(unit_box.0, de_unit_box.0); + } + + #[test] + fn test_custom_uniform() { + use crate::distr::uniform::{SampleBorrow, SampleUniform, UniformFloat, UniformSampler}; + #[derive(Clone, Copy, PartialEq, PartialOrd)] + struct MyF32 { + x: f32, + } + #[derive(Clone, Copy, Debug)] + struct UniformMyF32(UniformFloat); + impl UniformSampler for UniformMyF32 { + type X = MyF32; + + fn new(low: B1, high: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + UniformFloat::::new(low.borrow().x, high.borrow().x).map(UniformMyF32) + } + + fn new_inclusive(low: B1, high: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + UniformSampler::new(low, high) + } + + fn sample(&self, rng: &mut R) -> Self::X { + MyF32 { + x: self.0.sample(rng), + } + } + } + impl SampleUniform for MyF32 { + type Sampler = UniformMyF32; + } + + let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 }); + let uniform = Uniform::new(low, high).unwrap(); + let mut rng = crate::test::rng(804); + for _ in 0..100 { + let x: MyF32 = rng.sample(uniform); + assert!(low <= x && x < high); + } + } + + #[test] + fn value_stability() { + fn test_samples( + lb: T, + ub: T, + expected_single: &[T], + expected_multiple: &[T], + ) where + Uniform: Distribution, + { + let mut rng = crate::test::rng(897); + let mut buf = [lb; 3]; + + for x in &mut buf { + *x = T::Sampler::sample_single(lb, ub, &mut rng).unwrap(); + } + assert_eq!(&buf, expected_single); + + let distr = Uniform::new(lb, ub).unwrap(); + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected_multiple); + } + + test_samples( + 0f32, + 1e-2f32, + &[0.0003070104, 0.0026630748, 0.00979833], + &[0.008194133, 0.00398172, 0.007428536], + ); + test_samples( + -1e10f64, + 1e10f64, + &[-4673848682.871551, 6388267422.932352, 4857075081.198343], + &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], + ); + + test_samples( + Duration::new(2, 0), + Duration::new(4, 0), + &[ + Duration::new(2, 532615131), + Duration::new(3, 638826742), + Duration::new(3, 485707508), + ], + &[ + Duration::new(3, 117337521), + Duration::new(3, 191764285), + Duration::new(3, 236507617), + ], + ); + } + + #[test] + fn uniform_distributions_can_be_compared() { + assert_eq!( + Uniform::new(1.0, 2.0).unwrap(), + Uniform::new(1.0, 2.0).unwrap() + ); + + // To cover UniformInt + assert_eq!( + Uniform::new(1_u32, 2_u32).unwrap(), + Uniform::new(1_u32, 2_u32).unwrap() + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_float.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_float.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_float.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_float.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,454 @@ +// Copyright 2018-2020 Developers of the Rand project. +// Copyright 2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! `UniformFloat` implementation + +use super::{Error, SampleBorrow, SampleUniform, UniformSampler}; +use crate::distr::float::IntoFloat; +use crate::distr::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, IntAsSIMD}; +use crate::Rng; + +#[cfg(feature = "simd_support")] +use core::simd::prelude::*; +// #[cfg(feature = "simd_support")] +// use core::simd::{LaneCount, SupportedLaneCount}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// The back-end implementing [`UniformSampler`] for floating-point types. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// # Implementation notes +/// +/// `UniformFloat` implementations convert RNG output to a float in the range +/// `[1, 2)` via transmutation, map this to `[0, 1)`, then scale and translate +/// to the desired range. Values produced this way have what equals 23 bits of +/// random digits for an `f32` and 52 for an `f64`. +/// +/// # Bias and range errors +/// +/// Bias may be expected within the least-significant bit of the significand. +/// It is not guaranteed that exclusive limits of a range are respected; i.e. +/// when sampling the range `[a, b)` it is not guaranteed that `b` is never +/// sampled. +/// +/// [`new`]: UniformSampler::new +/// [`new_inclusive`]: UniformSampler::new_inclusive +/// [`StandardUniform`]: crate::distr::StandardUniform +/// [`Uniform`]: super::Uniform +#[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct UniformFloat { + low: X, + scale: X, +} + +macro_rules! uniform_float_impl { + ($($meta:meta)?, $ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => { + $(#[cfg($meta)])? + impl UniformFloat<$ty> { + /// Construct, reducing `scale` as required to ensure that rounding + /// can never yield values greater than `high`. + /// + /// Note: though it may be tempting to use a variant of this method + /// to ensure that samples from `[low, high)` are always strictly + /// less than `high`, this approach may be very slow where + /// `scale.abs()` is much smaller than `high.abs()` + /// (example: `low=0.99999999997819644, high=1.`). + fn new_bounded(low: $ty, high: $ty, mut scale: $ty) -> Self { + let max_rand = <$ty>::splat(1.0 as $f_scalar - $f_scalar::EPSILON); + + loop { + let mask = (scale * max_rand + low).gt_mask(high); + if !mask.any() { + break; + } + scale = scale.decrease_masked(mask); + } + + debug_assert!(<$ty>::splat(0.0).all_le(scale)); + + UniformFloat { low, scale } + } + } + + $(#[cfg($meta)])? + impl SampleUniform for $ty { + type Sampler = UniformFloat<$ty>; + } + + $(#[cfg($meta)])? + impl UniformSampler for UniformFloat<$ty> { + type X = $ty; + + fn new(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + #[cfg(debug_assertions)] + if !(low.all_finite()) || !(high.all_finite()) { + return Err(Error::NonFinite); + } + if !(low.all_lt(high)) { + return Err(Error::EmptyRange); + } + + let scale = high - low; + if !(scale.all_finite()) { + return Err(Error::NonFinite); + } + + Ok(Self::new_bounded(low, high, scale)) + } + + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + #[cfg(debug_assertions)] + if !(low.all_finite()) || !(high.all_finite()) { + return Err(Error::NonFinite); + } + if !low.all_le(high) { + return Err(Error::EmptyRange); + } + + let max_rand = <$ty>::splat(1.0 as $f_scalar - $f_scalar::EPSILON); + let scale = (high - low) / max_rand; + if !scale.all_finite() { + return Err(Error::NonFinite); + } + + Ok(Self::new_bounded(low, high, scale)) + } + + fn sample(&self, rng: &mut R) -> Self::X { + // Generate a value in the range [1, 2) + let value1_2 = (rng.random::<$uty>() >> $uty::splat($bits_to_discard)).into_float_with_exponent(0); + + // Get a value in the range [0, 1) to avoid overflow when multiplying by scale + let value0_1 = value1_2 - <$ty>::splat(1.0); + + // We don't use `f64::mul_add`, because it is not available with + // `no_std`. Furthermore, it is slower for some targets (but + // faster for others). However, the order of multiplication and + // addition is important, because on some platforms (e.g. ARM) + // it will be optimized to a single (non-FMA) instruction. + value0_1 * self.scale + self.low + } + + #[inline] + fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + Self::sample_single_inclusive(low_b, high_b, rng) + } + + #[inline] + fn sample_single_inclusive(low_b: B1, high_b: B2, rng: &mut R) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + #[cfg(debug_assertions)] + if !low.all_finite() || !high.all_finite() { + return Err(Error::NonFinite); + } + if !low.all_le(high) { + return Err(Error::EmptyRange); + } + let scale = high - low; + if !scale.all_finite() { + return Err(Error::NonFinite); + } + + // Generate a value in the range [1, 2) + let value1_2 = + (rng.random::<$uty>() >> $uty::splat($bits_to_discard)).into_float_with_exponent(0); + + // Get a value in the range [0, 1) to avoid overflow when multiplying by scale + let value0_1 = value1_2 - <$ty>::splat(1.0); + + // Doing multiply before addition allows some architectures + // to use a single instruction. + Ok(value0_1 * scale + low) + } + } + }; +} + +uniform_float_impl! { , f32, u32, f32, u32, 32 - 23 } +uniform_float_impl! { , f64, u64, f64, u64, 64 - 52 } + +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f32x2, u32x2, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f32x4, u32x4, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f32x8, u32x8, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f32x16, u32x16, f32, u32, 32 - 23 } + +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f64x2, u64x2, f64, u64, 64 - 52 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f64x4, u64x4, f64, u64, 64 - 52 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { feature = "simd_support", f64x8, u64x8, f64, u64, 64 - 52 } + +#[cfg(test)] +mod tests { + use super::*; + use crate::distr::{utils::FloatSIMDScalarUtils, Uniform}; + use crate::test::{const_rng, step_rng}; + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_floats() { + let mut rng = crate::test::rng(252); + let mut zero_rng = const_rng(0); + let mut max_rng = const_rng(0xffff_ffff_ffff_ffff); + macro_rules! t { + ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ + let v: &[($f_scalar, $f_scalar)] = &[ + (0.0, 100.0), + (-1e35, -1e25), + (1e-35, 1e-25), + (-1e35, 1e35), + (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), + (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), + (-<$f_scalar>::from_bits(5), 0.0), + (-<$f_scalar>::from_bits(7), -0.0), + (0.1 * $f_scalar::MAX, $f_scalar::MAX), + (-$f_scalar::MAX * 0.2, $f_scalar::MAX * 0.7), + ]; + for &(low_scalar, high_scalar) in v.iter() { + for lane in 0..<$ty>::LEN { + let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); + let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); + let my_uniform = Uniform::new(low, high).unwrap(); + let my_incl_uniform = Uniform::new_inclusive(low, high).unwrap(); + for _ in 0..100 { + let v = rng.sample(my_uniform).extract_lane(lane); + assert!(low_scalar <= v && v <= high_scalar); + let v = rng.sample(my_incl_uniform).extract_lane(lane); + assert!(low_scalar <= v && v <= high_scalar); + let v = + <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng) + .unwrap() + .extract_lane(lane); + assert!(low_scalar <= v && v <= high_scalar); + let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive( + low, high, &mut rng, + ) + .unwrap() + .extract_lane(lane); + assert!(low_scalar <= v && v <= high_scalar); + } + + assert_eq!( + rng.sample(Uniform::new_inclusive(low, low).unwrap()) + .extract_lane(lane), + low_scalar + ); + + assert_eq!(zero_rng.sample(my_uniform).extract_lane(lane), low_scalar); + assert_eq!( + zero_rng.sample(my_incl_uniform).extract_lane(lane), + low_scalar + ); + assert_eq!( + <$ty as SampleUniform>::Sampler::sample_single( + low, + high, + &mut zero_rng + ) + .unwrap() + .extract_lane(lane), + low_scalar + ); + assert_eq!( + <$ty as SampleUniform>::Sampler::sample_single_inclusive( + low, + high, + &mut zero_rng + ) + .unwrap() + .extract_lane(lane), + low_scalar + ); + + assert!(max_rng.sample(my_uniform).extract_lane(lane) <= high_scalar); + assert!(max_rng.sample(my_incl_uniform).extract_lane(lane) <= high_scalar); + // sample_single cannot cope with max_rng: + // assert!(<$ty as SampleUniform>::Sampler + // ::sample_single(low, high, &mut max_rng).unwrap() + // .extract(lane) <= high_scalar); + assert!( + <$ty as SampleUniform>::Sampler::sample_single_inclusive( + low, + high, + &mut max_rng + ) + .unwrap() + .extract_lane(lane) + <= high_scalar + ); + + // Don't run this test for really tiny differences between high and low + // since for those rounding might result in selecting high for a very + // long time. + if (high_scalar - low_scalar) > 0.0001 { + let mut lowering_max_rng = + step_rng(0xffff_ffff_ffff_ffff, (-1i64 << $bits_shifted) as u64); + assert!( + <$ty as SampleUniform>::Sampler::sample_single( + low, + high, + &mut lowering_max_rng + ) + .unwrap() + .extract_lane(lane) + <= high_scalar + ); + } + } + } + + assert_eq!( + rng.sample(Uniform::new_inclusive($f_scalar::MAX, $f_scalar::MAX).unwrap()), + $f_scalar::MAX + ); + assert_eq!( + rng.sample(Uniform::new_inclusive(-$f_scalar::MAX, -$f_scalar::MAX).unwrap()), + -$f_scalar::MAX + ); + }}; + } + + t!(f32, f32, 32 - 23); + t!(f64, f64, 64 - 52); + #[cfg(feature = "simd_support")] + { + t!(f32x2, f32, 32 - 23); + t!(f32x4, f32, 32 - 23); + t!(f32x8, f32, 32 - 23); + t!(f32x16, f32, 32 - 23); + t!(f64x2, f64, 64 - 52); + t!(f64x4, f64, 64 - 52); + t!(f64x8, f64, 64 - 52); + } + } + + #[test] + fn test_float_overflow() { + assert_eq!(Uniform::try_from(f64::MIN..f64::MAX), Err(Error::NonFinite)); + } + + #[test] + #[should_panic] + fn test_float_overflow_single() { + let mut rng = crate::test::rng(252); + rng.random_range(f64::MIN..f64::MAX); + } + + #[test] + #[cfg(all(feature = "std", panic = "unwind"))] + fn test_float_assertions() { + use super::SampleUniform; + fn range(low: T, high: T) -> Result { + let mut rng = crate::test::rng(253); + T::Sampler::sample_single(low, high, &mut rng) + } + + macro_rules! t { + ($ty:ident, $f_scalar:ident) => {{ + let v: &[($f_scalar, $f_scalar)] = &[ + ($f_scalar::NAN, 0.0), + (1.0, $f_scalar::NAN), + ($f_scalar::NAN, $f_scalar::NAN), + (1.0, 0.5), + ($f_scalar::MAX, -$f_scalar::MAX), + ($f_scalar::INFINITY, $f_scalar::INFINITY), + ($f_scalar::NEG_INFINITY, $f_scalar::NEG_INFINITY), + ($f_scalar::NEG_INFINITY, 5.0), + (5.0, $f_scalar::INFINITY), + ($f_scalar::NAN, $f_scalar::INFINITY), + ($f_scalar::NEG_INFINITY, $f_scalar::NAN), + ($f_scalar::NEG_INFINITY, $f_scalar::INFINITY), + ]; + for &(low_scalar, high_scalar) in v.iter() { + for lane in 0..<$ty>::LEN { + let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); + let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); + assert!(range(low, high).is_err()); + assert!(Uniform::new(low, high).is_err()); + assert!(Uniform::new_inclusive(low, high).is_err()); + assert!(Uniform::new(low, low).is_err()); + } + } + }}; + } + + t!(f32, f32); + t!(f64, f64); + #[cfg(feature = "simd_support")] + { + t!(f32x2, f32); + t!(f32x4, f32); + t!(f32x8, f32); + t!(f32x16, f32); + t!(f64x2, f64); + t!(f64x4, f64); + t!(f64x8, f64); + } + } + + #[test] + fn test_uniform_from_std_range() { + let r = Uniform::try_from(2.0f64..7.0).unwrap(); + assert_eq!(r.0.low, 2.0); + assert_eq!(r.0.scale, 5.0); + } + + #[test] + fn test_uniform_from_std_range_bad_limits() { + #![allow(clippy::reversed_empty_ranges)] + assert!(Uniform::try_from(100.0..10.0).is_err()); + assert!(Uniform::try_from(100.0..100.0).is_err()); + } + + #[test] + fn test_uniform_from_std_range_inclusive() { + let r = Uniform::try_from(2.0f64..=7.0).unwrap(); + assert_eq!(r.0.low, 2.0); + assert!(r.0.scale > 5.0); + assert!(r.0.scale < 5.0 + 1e-14); + } + + #[test] + fn test_uniform_from_std_range_inclusive_bad_limits() { + #![allow(clippy::reversed_empty_ranges)] + assert!(Uniform::try_from(100.0..=10.0).is_err()); + assert!(Uniform::try_from(100.0..=99.0).is_err()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_int.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_int.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_int.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_int.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,903 @@ +// Copyright 2018-2020 Developers of the Rand project. +// Copyright 2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! `UniformInt` implementation + +use super::{Error, SampleBorrow, SampleUniform, UniformSampler}; +use crate::distr::utils::WideningMultiply; +#[cfg(feature = "simd_support")] +use crate::distr::{Distribution, StandardUniform}; +use crate::Rng; + +#[cfg(feature = "simd_support")] +use core::simd::prelude::*; +#[cfg(feature = "simd_support")] +use core::simd::{LaneCount, SupportedLaneCount}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// The back-end implementing [`UniformSampler`] for integer types. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// # Implementation notes +/// +/// For simplicity, we use the same generic struct `UniformInt` for all +/// integer types `X`. This gives us only one field type, `X`; to store unsigned +/// values of this size, we take use the fact that these conversions are no-ops. +/// +/// For a closed range, the number of possible numbers we should generate is +/// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of +/// our sample space, `zone`, is a multiple of `range`; other values must be +/// rejected (by replacing with a new random sample). +/// +/// As a special case, we use `range = 0` to represent the full range of the +/// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`). +/// +/// The optimum `zone` is the largest product of `range` which fits in our +/// (unsigned) target type. We calculate this by calculating how many numbers we +/// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large) +/// product of `range` will suffice, thus in `sample_single` we multiply by a +/// power of 2 via bit-shifting (faster but may cause more rejections). +/// +/// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we +/// use `u32` for our `zone` and samples (because it's not slower and because +/// it reduces the chance of having to reject a sample). In this case we cannot +/// store `zone` in the target type since it is too large, however we know +/// `ints_to_reject < range <= $uty::MAX`. +/// +/// An alternative to using a modulus is widening multiply: After a widening +/// multiply by `range`, the result is in the high word. Then comparing the low +/// word against `zone` makes sure our distribution is uniform. +/// +/// # Bias +/// +/// Unless the `unbiased` feature flag is used, outputs may have a small bias. +/// In the worst case, bias affects 1 in `2^n` samples where n is +/// 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96 (`i32` and `u32`), 64 (`i64` +/// and `u64`), 128 (`i128` and `u128`). +/// +/// [`Uniform`]: super::Uniform +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct UniformInt { + pub(super) low: X, + pub(super) range: X, + thresh: X, // effectively 2.pow(max(64, uty_bits)) % range +} + +macro_rules! uniform_int_impl { + ($ty:ty, $uty:ty, $sample_ty:ident) => { + impl SampleUniform for $ty { + type Sampler = UniformInt<$ty>; + } + + impl UniformSampler for UniformInt<$ty> { + // We play free and fast with unsigned vs signed here + // (when $ty is signed), but that's fine, since the + // contract of this macro is for $ty and $uty to be + // "bit-equal", so casting between them is a no-op. + + type X = $ty; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low < high) { + return Err(Error::EmptyRange); + } + UniformSampler::new_inclusive(low, high - 1) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + + let range = high.wrapping_sub(low).wrapping_add(1) as $uty; + let thresh = if range > 0 { + let range = $sample_ty::from(range); + (range.wrapping_neg() % range) + } else { + 0 + }; + + Ok(UniformInt { + low, + range: range as $ty, // type: $uty + thresh: thresh as $uty as $ty, // type: $sample_ty + }) + } + + /// Sample from distribution, Lemire's method, unbiased + #[inline] + fn sample(&self, rng: &mut R) -> Self::X { + let range = self.range as $uty as $sample_ty; + if range == 0 { + return rng.random(); + } + + let thresh = self.thresh as $uty as $sample_ty; + let hi = loop { + let (hi, lo) = rng.random::<$sample_ty>().wmul(range); + if lo >= thresh { + break hi; + } + }; + self.low.wrapping_add(hi as $ty) + } + + #[inline] + fn sample_single( + low_b: B1, + high_b: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low < high) { + return Err(Error::EmptyRange); + } + Self::sample_single_inclusive(low, high - 1, rng) + } + + /// Sample single value, Canon's method, biased + /// + /// In the worst case, bias affects 1 in `2^n` samples where n is + /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`). + #[cfg(not(feature = "unbiased"))] + #[inline] + fn sample_single_inclusive( + low_b: B1, + high_b: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty; + if range == 0 { + // Range is MAX+1 (unrepresentable), so we need a special case + return Ok(rng.random()); + } + + // generate a sample using a sensible integer type + let (mut result, lo_order) = rng.random::<$sample_ty>().wmul(range); + + // if the sample is biased... + if lo_order > range.wrapping_neg() { + // ...generate a new sample to reduce bias... + let (new_hi_order, _) = (rng.random::<$sample_ty>()).wmul(range as $sample_ty); + // ... incrementing result on overflow + let is_overflow = lo_order.checked_add(new_hi_order as $sample_ty).is_none(); + result += is_overflow as $sample_ty; + } + + Ok(low.wrapping_add(result as $ty)) + } + + /// Sample single value, Canon's method, unbiased + #[cfg(feature = "unbiased")] + #[inline] + fn sample_single_inclusive( + low_b: B1, + high_b: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow<$ty> + Sized, + B2: SampleBorrow<$ty> + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty; + if range == 0 { + // Range is MAX+1 (unrepresentable), so we need a special case + return Ok(rng.random()); + } + + let (mut result, mut lo) = rng.random::<$sample_ty>().wmul(range); + + // In contrast to the biased sampler, we use a loop: + while lo > range.wrapping_neg() { + let (new_hi, new_lo) = (rng.random::<$sample_ty>()).wmul(range); + match lo.checked_add(new_hi) { + Some(x) if x < $sample_ty::MAX => { + // Anything less than MAX: last term is 0 + break; + } + None => { + // Overflow: last term is 1 + result += 1; + break; + } + _ => { + // Unlikely case: must check next sample + lo = new_lo; + continue; + } + } + } + + Ok(low.wrapping_add(result as $ty)) + } + } + }; +} + +uniform_int_impl! { i8, u8, u32 } +uniform_int_impl! { i16, u16, u32 } +uniform_int_impl! { i32, u32, u32 } +uniform_int_impl! { i64, u64, u64 } +uniform_int_impl! { i128, u128, u128 } +uniform_int_impl! { u8, u8, u32 } +uniform_int_impl! { u16, u16, u32 } +uniform_int_impl! { u32, u32, u32 } +uniform_int_impl! { u64, u64, u64 } +uniform_int_impl! { u128, u128, u128 } + +#[cfg(feature = "simd_support")] +macro_rules! uniform_simd_int_impl { + ($ty:ident, $unsigned:ident) => { + // The "pick the largest zone that can fit in an `u32`" optimization + // is less useful here. Multiple lanes complicate things, we don't + // know the PRNG's minimal output size, and casting to a larger vector + // is generally a bad idea for SIMD performance. The user can still + // implement it manually. + + #[cfg(feature = "simd_support")] + impl SampleUniform for Simd<$ty, LANES> + where + LaneCount: SupportedLaneCount, + Simd<$unsigned, LANES>: + WideningMultiply, Simd<$unsigned, LANES>)>, + StandardUniform: Distribution>, + { + type Sampler = UniformInt>; + } + + #[cfg(feature = "simd_support")] + impl UniformSampler for UniformInt> + where + LaneCount: SupportedLaneCount, + Simd<$unsigned, LANES>: + WideningMultiply, Simd<$unsigned, LANES>)>, + StandardUniform: Distribution>, + { + type X = Simd<$ty, LANES>; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Result + where B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low.simd_lt(high).all()) { + return Err(Error::EmptyRange); + } + UniformSampler::new_inclusive(low, high - Simd::splat(1)) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low.simd_le(high).all()) { + return Err(Error::EmptyRange); + } + + // NOTE: all `Simd` operations are inherently wrapping, + // see https://doc.rust-lang.org/std/simd/struct.Simd.html + let range: Simd<$unsigned, LANES> = ((high - low) + Simd::splat(1)).cast(); + + // We must avoid divide-by-zero by using 0 % 1 == 0. + let not_full_range = range.simd_gt(Simd::splat(0)); + let modulo = not_full_range.select(range, Simd::splat(1)); + let ints_to_reject = range.wrapping_neg() % modulo; + + Ok(UniformInt { + low, + // These are really $unsigned values, but store as $ty: + range: range.cast(), + thresh: ints_to_reject.cast(), + }) + } + + fn sample(&self, rng: &mut R) -> Self::X { + let range: Simd<$unsigned, LANES> = self.range.cast(); + let thresh: Simd<$unsigned, LANES> = self.thresh.cast(); + + // This might seem very slow, generating a whole new + // SIMD vector for every sample rejection. For most uses + // though, the chance of rejection is small and provides good + // general performance. With multiple lanes, that chance is + // multiplied. To mitigate this, we replace only the lanes of + // the vector which fail, iteratively reducing the chance of + // rejection. The replacement method does however add a little + // overhead. Benchmarking or calculating probabilities might + // reveal contexts where this replacement method is slower. + let mut v: Simd<$unsigned, LANES> = rng.random(); + loop { + let (hi, lo) = v.wmul(range); + let mask = lo.simd_ge(thresh); + if mask.all() { + let hi: Simd<$ty, LANES> = hi.cast(); + // wrapping addition + let result = self.low + hi; + // `select` here compiles to a blend operation + // When `range.eq(0).none()` the compare and blend + // operations are avoided. + let v: Simd<$ty, LANES> = v.cast(); + return range.simd_gt(Simd::splat(0)).select(result, v); + } + // Replace only the failing lanes + v = mask.select(v, rng.random()); + } + } + } + }; + + // bulk implementation + ($(($unsigned:ident, $signed:ident)),+) => { + $( + uniform_simd_int_impl!($unsigned, $unsigned); + uniform_simd_int_impl!($signed, $unsigned); + )+ + }; +} + +#[cfg(feature = "simd_support")] +uniform_simd_int_impl! { (u8, i8), (u16, i16), (u32, i32), (u64, i64) } + +/// The back-end implementing [`UniformSampler`] for `usize`. +/// +/// # Implementation notes +/// +/// Sampling a `usize` value is usually used in relation to the length of an +/// array or other memory structure, thus it is reasonable to assume that the +/// vast majority of use-cases will have a maximum size under [`u32::MAX`]. +/// In part to optimise for this use-case, but mostly to ensure that results +/// are portable across 32-bit and 64-bit architectures (as far as is possible), +/// this implementation will use 32-bit sampling when possible. +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(all(feature = "serde"), derive(Serialize))] +// To be able to deserialize on 32-bit we need to replace this with a custom +// implementation of the Deserialize trait, to be able to: +// - panic when `mode64` is `true` on 32-bit, +// - assign the default value to `mode64` when it's missing on 64-bit, +// - panic when the `usize` fields are greater than `u32::MAX` on 32-bit. +#[cfg_attr( + all(feature = "serde", target_pointer_width = "64"), + derive(Deserialize) +)] +pub struct UniformUsize { + /// The lowest possible value. + low: usize, + /// The number of possible values. `0` has a special meaning: all. + range: usize, + /// Threshold used when sampling to obtain a uniform distribution. + thresh: usize, + /// Whether the largest possible value is greater than `u32::MAX`. + #[cfg(target_pointer_width = "64")] + // Handle missing field when deserializing on 64-bit an object serialized + // on 32-bit. Can be removed when switching to a custom deserializer. + #[cfg_attr(feature = "serde", serde(default))] + mode64: bool, +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +impl SampleUniform for usize { + type Sampler = UniformUsize; +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +impl UniformSampler for UniformUsize { + type X = usize; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low < high) { + return Err(Error::EmptyRange); + } + + UniformSampler::new_inclusive(low, high - 1) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + + #[cfg(target_pointer_width = "64")] + let mode64 = high > (u32::MAX as usize); + #[cfg(target_pointer_width = "32")] + let mode64 = false; + + let (range, thresh); + if cfg!(target_pointer_width = "64") && !mode64 { + let range32 = (high as u32).wrapping_sub(low as u32).wrapping_add(1); + range = range32 as usize; + thresh = if range32 > 0 { + (range32.wrapping_neg() % range32) as usize + } else { + 0 + }; + } else { + range = high.wrapping_sub(low).wrapping_add(1); + thresh = if range > 0 { + range.wrapping_neg() % range + } else { + 0 + }; + } + + Ok(UniformUsize { + low, + range, + thresh, + #[cfg(target_pointer_width = "64")] + mode64, + }) + } + + #[inline] + fn sample(&self, rng: &mut R) -> usize { + #[cfg(target_pointer_width = "32")] + let mode32 = true; + #[cfg(target_pointer_width = "64")] + let mode32 = !self.mode64; + + if mode32 { + let range = self.range as u32; + if range == 0 { + return rng.random::() as usize; + } + + let thresh = self.thresh as u32; + let hi = loop { + let (hi, lo) = rng.random::().wmul(range); + if lo >= thresh { + break hi; + } + }; + self.low.wrapping_add(hi as usize) + } else { + let range = self.range as u64; + if range == 0 { + return rng.random::() as usize; + } + + let thresh = self.thresh as u64; + let hi = loop { + let (hi, lo) = rng.random::().wmul(range); + if lo >= thresh { + break hi; + } + }; + self.low.wrapping_add(hi as usize) + } + } + + #[inline] + fn sample_single( + low_b: B1, + high_b: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low < high) { + return Err(Error::EmptyRange); + } + + if cfg!(target_pointer_width = "64") && high > (u32::MAX as usize) { + return UniformInt::::sample_single(low as u64, high as u64, rng) + .map(|x| x as usize); + } + + UniformInt::::sample_single(low as u32, high as u32, rng).map(|x| x as usize) + } + + #[inline] + fn sample_single_inclusive( + low_b: B1, + high_b: B2, + rng: &mut R, + ) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + + if cfg!(target_pointer_width = "64") && high > (u32::MAX as usize) { + return UniformInt::::sample_single_inclusive(low as u64, high as u64, rng) + .map(|x| x as usize); + } + + UniformInt::::sample_single_inclusive(low as u32, high as u32, rng).map(|x| x as usize) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::distr::{Distribution, Uniform}; + use core::fmt::Debug; + use core::ops::Add; + + #[test] + fn test_uniform_bad_limits_equal_int() { + assert_eq!(Uniform::new(10, 10), Err(Error::EmptyRange)); + } + + #[test] + fn test_uniform_good_limits_equal_int() { + let mut rng = crate::test::rng(804); + let dist = Uniform::new_inclusive(10, 10).unwrap(); + for _ in 0..20 { + assert_eq!(rng.sample(dist), 10); + } + } + + #[test] + fn test_uniform_bad_limits_flipped_int() { + assert_eq!(Uniform::new(10, 5), Err(Error::EmptyRange)); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_integers() { + let mut rng = crate::test::rng(251); + macro_rules! t { + ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{ + for &(low, high) in $v.iter() { + let my_uniform = Uniform::new(low, high).unwrap(); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $lt(v, high)); + } + + let my_uniform = Uniform::new_inclusive(low, high).unwrap(); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $le(v, high)); + } + + let my_uniform = Uniform::new(&low, high).unwrap(); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $lt(v, high)); + } + + let my_uniform = Uniform::new_inclusive(&low, &high).unwrap(); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $le(v, high)); + } + + for _ in 0..1000 { + let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng).unwrap(); + assert!($le(low, v) && $lt(v, high)); + } + + for _ in 0..1000 { + let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng).unwrap(); + assert!($le(low, v) && $le(v, high)); + } + } + }}; + + // scalar bulk + ($($ty:ident),*) => {{ + $(t!( + $ty, + [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)], + |x, y| x <= y, + |x, y| x < y + );)* + }}; + + // simd bulk + ($($ty:ident),* => $scalar:ident) => {{ + $(t!( + $ty, + [ + ($ty::splat(0), $ty::splat(10)), + ($ty::splat(10), $ty::splat(127)), + ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)), + ], + |x: $ty, y| x.simd_le(y).all(), + |x: $ty, y| x.simd_lt(y).all() + );)* + }}; + } + t!(i8, i16, i32, i64, i128, u8, u16, u32, u64, usize, u128); + + #[cfg(feature = "simd_support")] + { + t!(u8x4, u8x8, u8x16, u8x32, u8x64 => u8); + t!(i8x4, i8x8, i8x16, i8x32, i8x64 => i8); + t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16); + t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16); + t!(u32x2, u32x4, u32x8, u32x16 => u32); + t!(i32x2, i32x4, i32x8, i32x16 => i32); + t!(u64x2, u64x4, u64x8 => u64); + t!(i64x2, i64x4, i64x8 => i64); + } + } + + #[test] + fn test_uniform_from_std_range() { + let r = Uniform::try_from(2u32..7).unwrap(); + assert_eq!(r.0.low, 2); + assert_eq!(r.0.range, 5); + } + + #[test] + fn test_uniform_from_std_range_bad_limits() { + #![allow(clippy::reversed_empty_ranges)] + assert!(Uniform::try_from(100..10).is_err()); + assert!(Uniform::try_from(100..100).is_err()); + } + + #[test] + fn test_uniform_from_std_range_inclusive() { + let r = Uniform::try_from(2u32..=6).unwrap(); + assert_eq!(r.0.low, 2); + assert_eq!(r.0.range, 5); + } + + #[test] + fn test_uniform_from_std_range_inclusive_bad_limits() { + #![allow(clippy::reversed_empty_ranges)] + assert!(Uniform::try_from(100..=10).is_err()); + assert!(Uniform::try_from(100..=99).is_err()); + } + + #[test] + fn value_stability() { + fn test_samples>( + lb: T, + ub: T, + ub_excl: T, + expected: &[T], + ) where + Uniform: Distribution, + { + let mut rng = crate::test::rng(897); + let mut buf = [lb; 6]; + + for x in &mut buf[0..3] { + *x = T::Sampler::sample_single_inclusive(lb, ub, &mut rng).unwrap(); + } + + let distr = Uniform::new_inclusive(lb, ub).unwrap(); + for x in &mut buf[3..6] { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + + let mut rng = crate::test::rng(897); + + for x in &mut buf[0..3] { + *x = T::Sampler::sample_single(lb, ub_excl, &mut rng).unwrap(); + } + + let distr = Uniform::new(lb, ub_excl).unwrap(); + for x in &mut buf[3..6] { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + } + + test_samples(-105i8, 111, 112, &[-99, -48, 107, 72, -19, 56]); + test_samples(2i16, 1352, 1353, &[43, 361, 1325, 1109, 539, 1005]); + test_samples( + -313853i32, + 13513, + 13514, + &[-303803, -226673, 6912, -45605, -183505, -70668], + ); + test_samples( + 131521i64, + 6542165, + 6542166, + &[1838724, 5384489, 4893692, 3712948, 3951509, 4094926], + ); + test_samples( + -0x8000_0000_0000_0000_0000_0000_0000_0000i128, + -1, + 0, + &[ + -30725222750250982319765550926688025855, + -75088619368053423329503924805178012357, + -64950748766625548510467638647674468829, + -41794017901603587121582892414659436495, + -63623852319608406524605295913876414006, + -17404679390297612013597359206379189023, + ], + ); + test_samples(11u8, 218, 219, &[17, 66, 214, 181, 93, 165]); + test_samples(11u16, 218, 219, &[17, 66, 214, 181, 93, 165]); + test_samples(11u32, 218, 219, &[17, 66, 214, 181, 93, 165]); + test_samples(11u64, 218, 219, &[66, 181, 165, 127, 134, 139]); + test_samples(11u128, 218, 219, &[181, 127, 139, 167, 141, 197]); + test_samples(11usize, 218, 219, &[17, 66, 214, 181, 93, 165]); + + #[cfg(feature = "simd_support")] + { + let lb = Simd::from([11u8, 0, 128, 127]); + let ub = Simd::from([218, 254, 254, 254]); + let ub_excl = ub + Simd::splat(1); + test_samples( + lb, + ub, + ub_excl, + &[ + Simd::from([13, 5, 237, 130]), + Simd::from([126, 186, 149, 161]), + Simd::from([103, 86, 234, 252]), + Simd::from([35, 18, 225, 231]), + Simd::from([106, 153, 246, 177]), + Simd::from([195, 168, 149, 222]), + ], + ); + } + } + + #[test] + fn test_uniform_usize_empty_range() { + assert_eq!(UniformUsize::new(10, 10), Err(Error::EmptyRange)); + assert!(UniformUsize::new(10, 11).is_ok()); + + assert_eq!(UniformUsize::new_inclusive(10, 9), Err(Error::EmptyRange)); + assert!(UniformUsize::new_inclusive(10, 10).is_ok()); + } + + #[test] + fn test_uniform_usize_constructors() { + assert_eq!( + UniformUsize::new_inclusive(u32::MAX as usize, u32::MAX as usize), + Ok(UniformUsize { + low: u32::MAX as usize, + range: 1, + thresh: 0, + #[cfg(target_pointer_width = "64")] + mode64: false + }) + ); + assert_eq!( + UniformUsize::new_inclusive(0, u32::MAX as usize), + Ok(UniformUsize { + low: 0, + range: 0, + thresh: 0, + #[cfg(target_pointer_width = "64")] + mode64: false + }) + ); + #[cfg(target_pointer_width = "64")] + assert_eq!( + UniformUsize::new_inclusive(0, u32::MAX as usize + 1), + Ok(UniformUsize { + low: 0, + range: u32::MAX as usize + 2, + thresh: 1, + mode64: true + }) + ); + #[cfg(target_pointer_width = "64")] + assert_eq!( + UniformUsize::new_inclusive(u32::MAX as usize, u64::MAX as usize), + Ok(UniformUsize { + low: u32::MAX as usize, + range: u64::MAX as usize - u32::MAX as usize + 1, + thresh: u32::MAX as usize, + mode64: true + }) + ); + } + + // This could be run also on 32-bit when deserialization is implemented. + #[cfg(all(feature = "serde", target_pointer_width = "64"))] + #[test] + fn test_uniform_usize_deserialization() { + use serde_json; + let original = UniformUsize::new_inclusive(10, 100).expect("creation"); + let serialized = serde_json::to_string(&original).expect("serialization"); + let deserialized: UniformUsize = + serde_json::from_str(&serialized).expect("deserialization"); + assert_eq!(deserialized, original); + } + + #[cfg(all(feature = "serde", target_pointer_width = "64"))] + #[test] + fn test_uniform_usize_deserialization_from_32bit() { + use serde_json; + let serialized_on_32bit = r#"{"low":10,"range":91,"thresh":74}"#; + let deserialized: UniformUsize = + serde_json::from_str(&serialized_on_32bit).expect("deserialization"); + assert_eq!( + deserialized, + UniformUsize::new_inclusive(10, 100).expect("creation") + ); + } + + #[cfg(all(feature = "serde", target_pointer_width = "64"))] + #[test] + fn test_uniform_usize_deserialization_64bit() { + use serde_json; + let original = UniformUsize::new_inclusive(1, u64::MAX as usize - 1).expect("creation"); + assert!(original.mode64); + let serialized = serde_json::to_string(&original).expect("serialization"); + let deserialized: UniformUsize = + serde_json::from_str(&serialized).expect("deserialization"); + assert_eq!(deserialized, original); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_other.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_other.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/uniform_other.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/uniform_other.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,319 @@ +// Copyright 2018-2020 Developers of the Rand project. +// Copyright 2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! `UniformChar`, `UniformDuration` implementations + +use super::{Error, SampleBorrow, SampleUniform, Uniform, UniformInt, UniformSampler}; +use crate::distr::Distribution; +use crate::Rng; +use core::time::Duration; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +impl SampleUniform for char { + type Sampler = UniformChar; +} + +/// The back-end implementing [`UniformSampler`] for `char`. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// This differs from integer range sampling since the range `0xD800..=0xDFFF` +/// are used for surrogate pairs in UCS and UTF-16, and consequently are not +/// valid Unicode code points. We must therefore avoid sampling values in this +/// range. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct UniformChar { + sampler: UniformInt, +} + +/// UTF-16 surrogate range start +const CHAR_SURROGATE_START: u32 = 0xD800; +/// UTF-16 surrogate range size +const CHAR_SURROGATE_LEN: u32 = 0xE000 - CHAR_SURROGATE_START; + +/// Convert `char` to compressed `u32` +fn char_to_comp_u32(c: char) -> u32 { + match c as u32 { + c if c >= CHAR_SURROGATE_START => c - CHAR_SURROGATE_LEN, + c => c, + } +} + +impl UniformSampler for UniformChar { + type X = char; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = char_to_comp_u32(*low_b.borrow()); + let high = char_to_comp_u32(*high_b.borrow()); + let sampler = UniformInt::::new(low, high); + sampler.map(|sampler| UniformChar { sampler }) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = char_to_comp_u32(*low_b.borrow()); + let high = char_to_comp_u32(*high_b.borrow()); + let sampler = UniformInt::::new_inclusive(low, high); + sampler.map(|sampler| UniformChar { sampler }) + } + + fn sample(&self, rng: &mut R) -> Self::X { + let mut x = self.sampler.sample(rng); + if x >= CHAR_SURROGATE_START { + x += CHAR_SURROGATE_LEN; + } + // SAFETY: x must not be in surrogate range or greater than char::MAX. + // This relies on range constructors which accept char arguments. + // Validity of input char values is assumed. + unsafe { core::char::from_u32_unchecked(x) } + } +} + +#[cfg(feature = "alloc")] +impl crate::distr::SampleString for Uniform { + fn append_string( + &self, + rng: &mut R, + string: &mut alloc::string::String, + len: usize, + ) { + // Getting the hi value to assume the required length to reserve in string. + let mut hi = self.0.sampler.low + self.0.sampler.range - 1; + if hi >= CHAR_SURROGATE_START { + hi += CHAR_SURROGATE_LEN; + } + // Get the utf8 length of hi to minimize extra space. + let max_char_len = char::from_u32(hi).map(char::len_utf8).unwrap_or(4); + string.reserve(max_char_len * len); + string.extend(self.sample_iter(rng).take(len)) + } +} + +/// The back-end implementing [`UniformSampler`] for `Duration`. +/// +/// Unless you are implementing [`UniformSampler`] for your own types, this type +/// should not be used directly, use [`Uniform`] instead. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct UniformDuration { + mode: UniformDurationMode, + offset: u32, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +enum UniformDurationMode { + Small { + secs: u64, + nanos: Uniform, + }, + Medium { + nanos: Uniform, + }, + Large { + max_secs: u64, + max_nanos: u32, + secs: Uniform, + }, +} + +impl SampleUniform for Duration { + type Sampler = UniformDuration; +} + +impl UniformSampler for UniformDuration { + type X = Duration; + + #[inline] + fn new(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low < high) { + return Err(Error::EmptyRange); + } + UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) + } + + #[inline] + fn new_inclusive(low_b: B1, high_b: B2) -> Result + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + if !(low <= high) { + return Err(Error::EmptyRange); + } + + let low_s = low.as_secs(); + let low_n = low.subsec_nanos(); + let mut high_s = high.as_secs(); + let mut high_n = high.subsec_nanos(); + + if high_n < low_n { + high_s -= 1; + high_n += 1_000_000_000; + } + + let mode = if low_s == high_s { + UniformDurationMode::Small { + secs: low_s, + nanos: Uniform::new_inclusive(low_n, high_n)?, + } + } else { + let max = high_s + .checked_mul(1_000_000_000) + .and_then(|n| n.checked_add(u64::from(high_n))); + + if let Some(higher_bound) = max { + let lower_bound = low_s * 1_000_000_000 + u64::from(low_n); + UniformDurationMode::Medium { + nanos: Uniform::new_inclusive(lower_bound, higher_bound)?, + } + } else { + // An offset is applied to simplify generation of nanoseconds + let max_nanos = high_n - low_n; + UniformDurationMode::Large { + max_secs: high_s, + max_nanos, + secs: Uniform::new_inclusive(low_s, high_s)?, + } + } + }; + Ok(UniformDuration { + mode, + offset: low_n, + }) + } + + #[inline] + fn sample(&self, rng: &mut R) -> Duration { + match self.mode { + UniformDurationMode::Small { secs, nanos } => { + let n = nanos.sample(rng); + Duration::new(secs, n) + } + UniformDurationMode::Medium { nanos } => { + let nanos = nanos.sample(rng); + Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) + } + UniformDurationMode::Large { + max_secs, + max_nanos, + secs, + } => { + // constant folding means this is at least as fast as `Rng::sample(Range)` + let nano_range = Uniform::new(0, 1_000_000_000).unwrap(); + loop { + let s = secs.sample(rng); + let n = nano_range.sample(rng); + if !(s == max_secs && n > max_nanos) { + let sum = n + self.offset; + break Duration::new(s, sum); + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(feature = "serde")] + fn test_serialization_uniform_duration() { + let distr = UniformDuration::new(Duration::from_secs(10), Duration::from_secs(60)).unwrap(); + let de_distr: UniformDuration = + bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); + assert_eq!(distr, de_distr); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_char() { + let mut rng = crate::test::rng(891); + let mut max = core::char::from_u32(0).unwrap(); + for _ in 0..100 { + let c = rng.random_range('A'..='Z'); + assert!(c.is_ascii_uppercase()); + max = max.max(c); + } + assert_eq!(max, 'Z'); + let d = Uniform::new( + core::char::from_u32(0xD7F0).unwrap(), + core::char::from_u32(0xE010).unwrap(), + ) + .unwrap(); + for _ in 0..100 { + let c = d.sample(&mut rng); + assert!((c as u32) < 0xD800 || (c as u32) > 0xDFFF); + } + #[cfg(feature = "alloc")] + { + use crate::distr::SampleString; + let string1 = d.sample_string(&mut rng, 100); + assert_eq!(string1.capacity(), 300); + let string2 = Uniform::new( + core::char::from_u32(0x0000).unwrap(), + core::char::from_u32(0x0080).unwrap(), + ) + .unwrap() + .sample_string(&mut rng, 100); + assert_eq!(string2.capacity(), 100); + let string3 = Uniform::new_inclusive( + core::char::from_u32(0x0000).unwrap(), + core::char::from_u32(0x0080).unwrap(), + ) + .unwrap() + .sample_string(&mut rng, 100); + assert_eq!(string3.capacity(), 200); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_durations() { + let mut rng = crate::test::rng(253); + + let v = &[ + (Duration::new(10, 50000), Duration::new(100, 1234)), + (Duration::new(0, 100), Duration::new(1, 50)), + (Duration::new(0, 0), Duration::new(u64::MAX, 999_999_999)), + ]; + for &(low, high) in v.iter() { + let my_uniform = Uniform::new(low, high).unwrap(); + for _ in 0..1000 { + let v = rng.sample(my_uniform); + assert!(low <= v && v < high); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/utils.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/utils.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,408 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Math helper functions + +#[cfg(feature = "simd_support")] +use core::simd::prelude::*; +#[cfg(feature = "simd_support")] +use core::simd::{LaneCount, SimdElement, SupportedLaneCount}; + +pub(crate) trait WideningMultiply { + type Output; + + fn wmul(self, x: RHS) -> Self::Output; +} + +macro_rules! wmul_impl { + ($ty:ty, $wide:ty, $shift:expr) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + let tmp = (self as $wide) * (x as $wide); + ((tmp >> $shift) as $ty, tmp as $ty) + } + } + }; + + // simd bulk implementation + ($(($ty:ident, $wide:ty),)+, $shift:expr) => { + $( + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + // For supported vectors, this should compile to a couple + // supported multiply & swizzle instructions (no actual + // casting). + // TODO: optimize + let y: $wide = self.cast(); + let x: $wide = x.cast(); + let tmp = y * x; + let hi: $ty = (tmp >> Simd::splat($shift)).cast(); + let lo: $ty = tmp.cast(); + (hi, lo) + } + } + )+ + }; +} +wmul_impl! { u8, u16, 8 } +wmul_impl! { u16, u32, 16 } +wmul_impl! { u32, u64, 32 } +wmul_impl! { u64, u128, 64 } + +// This code is a translation of the __mulddi3 function in LLVM's +// compiler-rt. It is an optimised variant of the common method +// `(a + b) * (c + d) = ac + ad + bc + bd`. +// +// For some reason LLVM can optimise the C version very well, but +// keeps shuffling registers in this Rust translation. +macro_rules! wmul_impl_large { + ($ty:ty, $half:expr) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, b: $ty) -> Self::Output { + const LOWER_MASK: $ty = !0 >> $half; + let mut low = (self & LOWER_MASK).wrapping_mul(b & LOWER_MASK); + let mut t = low >> $half; + low &= LOWER_MASK; + t += (self >> $half).wrapping_mul(b & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + let mut high = t >> $half; + t = low >> $half; + low &= LOWER_MASK; + t += (b >> $half).wrapping_mul(self & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + high += t >> $half; + high += (self >> $half).wrapping_mul(b >> $half); + + (high, low) + } + } + }; + + // simd bulk implementation + (($($ty:ty,)+) $scalar:ty, $half:expr) => { + $( + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, b: $ty) -> Self::Output { + // needs wrapping multiplication + let lower_mask = <$ty>::splat(!0 >> $half); + let half = <$ty>::splat($half); + let mut low = (self & lower_mask) * (b & lower_mask); + let mut t = low >> half; + low &= lower_mask; + t += (self >> half) * (b & lower_mask); + low += (t & lower_mask) << half; + let mut high = t >> half; + t = low >> half; + low &= lower_mask; + t += (b >> half) * (self & lower_mask); + low += (t & lower_mask) << half; + high += t >> half; + high += (self >> half) * (b >> half); + + (high, low) + } + } + )+ + }; +} +wmul_impl_large! { u128, 64 } + +macro_rules! wmul_impl_usize { + ($ty:ty) => { + impl WideningMultiply for usize { + type Output = (usize, usize); + + #[inline(always)] + fn wmul(self, x: usize) -> Self::Output { + let (high, low) = (self as $ty).wmul(x as $ty); + (high as usize, low as usize) + } + } + }; +} +#[cfg(target_pointer_width = "16")] +wmul_impl_usize! { u16 } +#[cfg(target_pointer_width = "32")] +wmul_impl_usize! { u32 } +#[cfg(target_pointer_width = "64")] +wmul_impl_usize! { u64 } + +#[cfg(feature = "simd_support")] +mod simd_wmul { + use super::*; + #[cfg(target_arch = "x86")] + use core::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64::*; + + wmul_impl! { + (u8x4, u16x4), + (u8x8, u16x8), + (u8x16, u16x16), + (u8x32, u16x32), + (u8x64, Simd),, + 8 + } + + wmul_impl! { (u16x2, u32x2),, 16 } + wmul_impl! { (u16x4, u32x4),, 16 } + #[cfg(not(target_feature = "sse2"))] + wmul_impl! { (u16x8, u32x8),, 16 } + #[cfg(not(target_feature = "avx2"))] + wmul_impl! { (u16x16, u32x16),, 16 } + #[cfg(not(target_feature = "avx512bw"))] + wmul_impl! { (u16x32, Simd),, 16 } + + // 16-bit lane widths allow use of the x86 `mulhi` instructions, which + // means `wmul` can be implemented with only two instructions. + #[allow(unused_macros)] + macro_rules! wmul_impl_16 { + ($ty:ident, $mulhi:ident, $mullo:ident) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + let hi = unsafe { $mulhi(self.into(), x.into()) }.into(); + let lo = unsafe { $mullo(self.into(), x.into()) }.into(); + (hi, lo) + } + } + }; + } + + #[cfg(target_feature = "sse2")] + wmul_impl_16! { u16x8, _mm_mulhi_epu16, _mm_mullo_epi16 } + #[cfg(target_feature = "avx2")] + wmul_impl_16! { u16x16, _mm256_mulhi_epu16, _mm256_mullo_epi16 } + #[cfg(target_feature = "avx512bw")] + wmul_impl_16! { u16x32, _mm512_mulhi_epu16, _mm512_mullo_epi16 } + + wmul_impl! { + (u32x2, u64x2), + (u32x4, u64x4), + (u32x8, u64x8), + (u32x16, Simd),, + 32 + } + + wmul_impl_large! { (u64x2, u64x4, u64x8,) u64, 32 } +} + +/// Helper trait when dealing with scalar and SIMD floating point types. +pub(crate) trait FloatSIMDUtils { + // `PartialOrd` for vectors compares lexicographically. We want to compare all + // the individual SIMD lanes instead, and get the combined result over all + // lanes. This is possible using something like `a.lt(b).all()`, but we + // implement it as a trait so we can write the same code for `f32` and `f64`. + // Only the comparison functions we need are implemented. + fn all_lt(self, other: Self) -> bool; + fn all_le(self, other: Self) -> bool; + fn all_finite(self) -> bool; + + type Mask; + fn gt_mask(self, other: Self) -> Self::Mask; + + // Decrease all lanes where the mask is `true` to the next lower value + // representable by the floating-point type. At least one of the lanes + // must be set. + fn decrease_masked(self, mask: Self::Mask) -> Self; + + // Convert from int value. Conversion is done while retaining the numerical + // value, not by retaining the binary representation. + type UInt; + fn cast_from_int(i: Self::UInt) -> Self; +} + +#[cfg(test)] +pub(crate) trait FloatSIMDScalarUtils: FloatSIMDUtils { + type Scalar; + + fn replace(self, index: usize, new_value: Self::Scalar) -> Self; + fn extract_lane(self, index: usize) -> Self::Scalar; +} + +/// Implement functions on f32/f64 to give them APIs similar to SIMD types +pub(crate) trait FloatAsSIMD: Sized { + #[cfg(test)] + const LEN: usize = 1; + + #[inline(always)] + fn splat(scalar: Self) -> Self { + scalar + } +} + +pub(crate) trait IntAsSIMD: Sized { + #[inline(always)] + fn splat(scalar: Self) -> Self { + scalar + } +} + +impl IntAsSIMD for u32 {} +impl IntAsSIMD for u64 {} + +pub(crate) trait BoolAsSIMD: Sized { + fn any(self) -> bool; +} + +impl BoolAsSIMD for bool { + #[inline(always)] + fn any(self) -> bool { + self + } +} + +macro_rules! scalar_float_impl { + ($ty:ident, $uty:ident) => { + impl FloatSIMDUtils for $ty { + type Mask = bool; + type UInt = $uty; + + #[inline(always)] + fn all_lt(self, other: Self) -> bool { + self < other + } + + #[inline(always)] + fn all_le(self, other: Self) -> bool { + self <= other + } + + #[inline(always)] + fn all_finite(self) -> bool { + self.is_finite() + } + + #[inline(always)] + fn gt_mask(self, other: Self) -> Self::Mask { + self > other + } + + #[inline(always)] + fn decrease_masked(self, mask: Self::Mask) -> Self { + debug_assert!(mask, "At least one lane must be set"); + <$ty>::from_bits(self.to_bits() - 1) + } + + #[inline] + fn cast_from_int(i: Self::UInt) -> Self { + i as $ty + } + } + + #[cfg(test)] + impl FloatSIMDScalarUtils for $ty { + type Scalar = $ty; + + #[inline] + fn replace(self, index: usize, new_value: Self::Scalar) -> Self { + debug_assert_eq!(index, 0); + new_value + } + + #[inline] + fn extract_lane(self, index: usize) -> Self::Scalar { + debug_assert_eq!(index, 0); + self + } + } + + impl FloatAsSIMD for $ty {} + }; +} + +scalar_float_impl!(f32, u32); +scalar_float_impl!(f64, u64); + +#[cfg(feature = "simd_support")] +macro_rules! simd_impl { + ($fty:ident, $uty:ident) => { + impl FloatSIMDUtils for Simd<$fty, LANES> + where + LaneCount: SupportedLaneCount, + { + type Mask = Mask<<$fty as SimdElement>::Mask, LANES>; + type UInt = Simd<$uty, LANES>; + + #[inline(always)] + fn all_lt(self, other: Self) -> bool { + self.simd_lt(other).all() + } + + #[inline(always)] + fn all_le(self, other: Self) -> bool { + self.simd_le(other).all() + } + + #[inline(always)] + fn all_finite(self) -> bool { + self.is_finite().all() + } + + #[inline(always)] + fn gt_mask(self, other: Self) -> Self::Mask { + self.simd_gt(other) + } + + #[inline(always)] + fn decrease_masked(self, mask: Self::Mask) -> Self { + // Casting a mask into ints will produce all bits set for + // true, and 0 for false. Adding that to the binary + // representation of a float means subtracting one from + // the binary representation, resulting in the next lower + // value representable by $fty. This works even when the + // current value is infinity. + debug_assert!(mask.any(), "At least one lane must be set"); + Self::from_bits(self.to_bits() + mask.to_int().cast()) + } + + #[inline] + fn cast_from_int(i: Self::UInt) -> Self { + i.cast() + } + } + + #[cfg(test)] + impl FloatSIMDScalarUtils for Simd<$fty, LANES> + where + LaneCount: SupportedLaneCount, + { + type Scalar = $fty; + + #[inline] + fn replace(mut self, index: usize, new_value: Self::Scalar) -> Self { + self.as_mut_array()[index] = new_value; + self + } + + #[inline] + fn extract_lane(self, index: usize) -> Self::Scalar { + self.as_array()[index] + } + } + }; +} + +#[cfg(feature = "simd_support")] +simd_impl!(f32, u32); +#[cfg(feature = "simd_support")] +simd_impl!(f64, u64); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/weighted/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/weighted/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,115 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Weighted (index) sampling +//! +//! Primarily, this module houses the [`WeightedIndex`] distribution. +//! See also [`rand_distr::weighted`] for alternative implementations supporting +//! potentially-faster sampling or a more easily modifiable tree structure. +//! +//! [`rand_distr::weighted`]: https://docs.rs/rand_distr/latest/rand_distr/weighted/index.html + +use core::fmt; +mod weighted_index; + +pub use weighted_index::WeightedIndex; + +/// Bounds on a weight +/// +/// See usage in [`WeightedIndex`]. +pub trait Weight: Clone { + /// Representation of 0 + const ZERO: Self; + + /// Checked addition + /// + /// - `Result::Ok`: On success, `v` is added to `self` + /// - `Result::Err`: Returns an error when `Self` cannot represent the + /// result of `self + v` (i.e. overflow). The value of `self` should be + /// discarded. + #[allow(clippy::result_unit_err)] + fn checked_add_assign(&mut self, v: &Self) -> Result<(), ()>; +} + +macro_rules! impl_weight_int { + ($t:ty) => { + impl Weight for $t { + const ZERO: Self = 0; + fn checked_add_assign(&mut self, v: &Self) -> Result<(), ()> { + match self.checked_add(*v) { + Some(sum) => { + *self = sum; + Ok(()) + } + None => Err(()), + } + } + } + }; + ($t:ty, $($tt:ty),*) => { + impl_weight_int!($t); + impl_weight_int!($($tt),*); + } +} +impl_weight_int!(i8, i16, i32, i64, i128, isize); +impl_weight_int!(u8, u16, u32, u64, u128, usize); + +macro_rules! impl_weight_float { + ($t:ty) => { + impl Weight for $t { + const ZERO: Self = 0.0; + + fn checked_add_assign(&mut self, v: &Self) -> Result<(), ()> { + // Floats have an explicit representation for overflow + *self += *v; + Ok(()) + } + } + }; +} +impl_weight_float!(f32); +impl_weight_float!(f64); + +/// Invalid weight errors +/// +/// This type represents errors from [`WeightedIndex::new`], +/// [`WeightedIndex::update_weights`] and other weighted distributions. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +// Marked non_exhaustive to allow a new error code in the solution to #1476. +#[non_exhaustive] +pub enum Error { + /// The input weight sequence is empty, too long, or wrongly ordered + InvalidInput, + + /// A weight is negative, too large for the distribution, or not a valid number + InvalidWeight, + + /// Not enough non-zero weights are available to sample values + /// + /// When attempting to sample a single value this implies that all weights + /// are zero. When attempting to sample `amount` values this implies that + /// less than `amount` weights are greater than zero. + InsufficientNonZero, + + /// Overflow when calculating the sum of weights + Overflow, +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match *self { + Error::InvalidInput => "Weights sequence is empty/too long/unordered", + Error::InvalidWeight => "A weight is negative, too large or not a valid number", + Error::InsufficientNonZero => "Not enough weights > zero", + Error::Overflow => "Overflow when summing weights", + }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/weighted/weighted_index.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/weighted_index.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/distr/weighted/weighted_index.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/distr/weighted/weighted_index.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,631 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::{Error, Weight}; +use crate::distr::uniform::{SampleBorrow, SampleUniform, UniformSampler}; +use crate::distr::Distribution; +use crate::Rng; + +// Note that this whole module is only imported if feature="alloc" is enabled. +use alloc::vec::Vec; +use core::fmt::{self, Debug}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A distribution using weighted sampling of discrete items. +/// +/// Sampling a `WeightedIndex` distribution returns the index of a randomly +/// selected element from the iterator used when the `WeightedIndex` was +/// created. The chance of a given element being picked is proportional to the +/// weight of the element. The weights can use any type `X` for which an +/// implementation of [`Uniform`] exists. The implementation guarantees that +/// elements with zero weight are never picked, even when the weights are +/// floating point numbers. +/// +/// # Performance +/// +/// Time complexity of sampling from `WeightedIndex` is `O(log N)` where +/// `N` is the number of weights. +/// See also [`rand_distr::weighted`] for alternative implementations supporting +/// potentially-faster sampling or a more easily modifiable tree structure. +/// +/// A `WeightedIndex` contains a `Vec` and a [`Uniform`] and so its +/// size is the sum of the size of those objects, possibly plus some alignment. +/// +/// Creating a `WeightedIndex` will allocate enough space to hold `N - 1` +/// weights of type `X`, where `N` is the number of weights. However, since +/// `Vec` doesn't guarantee a particular growth strategy, additional memory +/// might be allocated but not used. Since the `WeightedIndex` object also +/// contains an instance of `X::Sampler`, this might cause additional allocations, +/// though for primitive types, [`Uniform`] doesn't allocate any memory. +/// +/// Sampling from `WeightedIndex` will result in a single call to +/// `Uniform::sample` (method of the [`Distribution`] trait), which typically +/// will request a single value from the underlying [`RngCore`], though the +/// exact number depends on the implementation of `Uniform::sample`. +/// +/// # Example +/// +/// ``` +/// use rand::prelude::*; +/// use rand::distr::weighted::WeightedIndex; +/// +/// let choices = ['a', 'b', 'c']; +/// let weights = [2, 1, 1]; +/// let dist = WeightedIndex::new(&weights).unwrap(); +/// let mut rng = rand::rng(); +/// for _ in 0..100 { +/// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' +/// println!("{}", choices[dist.sample(&mut rng)]); +/// } +/// +/// let items = [('a', 0.0), ('b', 3.0), ('c', 7.0)]; +/// let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap(); +/// for _ in 0..100 { +/// // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c' +/// println!("{}", items[dist2.sample(&mut rng)].0); +/// } +/// ``` +/// +/// [`Uniform`]: crate::distr::Uniform +/// [`RngCore`]: crate::RngCore +/// [`rand_distr::weighted`]: https://docs.rs/rand_distr/latest/rand_distr/weighted/index.html +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct WeightedIndex { + cumulative_weights: Vec, + total_weight: X, + weight_distribution: X::Sampler, +} + +impl WeightedIndex { + /// Creates a new a `WeightedIndex` [`Distribution`] using the values + /// in `weights`. The weights can use any type `X` for which an + /// implementation of [`Uniform`] exists. + /// + /// Error cases: + /// - [`Error::InvalidInput`] when the iterator `weights` is empty. + /// - [`Error::InvalidWeight`] when a weight is not-a-number or negative. + /// - [`Error::InsufficientNonZero`] when the sum of all weights is zero. + /// - [`Error::Overflow`] when the sum of all weights overflows. + /// + /// [`Uniform`]: crate::distr::uniform::Uniform + pub fn new(weights: I) -> Result, Error> + where + I: IntoIterator, + I::Item: SampleBorrow, + X: Weight, + { + let mut iter = weights.into_iter(); + let mut total_weight: X = iter.next().ok_or(Error::InvalidInput)?.borrow().clone(); + + let zero = X::ZERO; + if !(total_weight >= zero) { + return Err(Error::InvalidWeight); + } + + let mut weights = Vec::::with_capacity(iter.size_hint().0); + for w in iter { + // Note that `!(w >= x)` is not equivalent to `w < x` for partially + // ordered types due to NaNs which are equal to nothing. + if !(w.borrow() >= &zero) { + return Err(Error::InvalidWeight); + } + weights.push(total_weight.clone()); + + if let Err(()) = total_weight.checked_add_assign(w.borrow()) { + return Err(Error::Overflow); + } + } + + if total_weight == zero { + return Err(Error::InsufficientNonZero); + } + let distr = X::Sampler::new(zero, total_weight.clone()).unwrap(); + + Ok(WeightedIndex { + cumulative_weights: weights, + total_weight, + weight_distribution: distr, + }) + } + + /// Update a subset of weights, without changing the number of weights. + /// + /// `new_weights` must be sorted by the index. + /// + /// Using this method instead of `new` might be more efficient if only a small number of + /// weights is modified. No allocations are performed, unless the weight type `X` uses + /// allocation internally. + /// + /// In case of error, `self` is not modified. Error cases: + /// - [`Error::InvalidInput`] when `new_weights` are not ordered by + /// index or an index is too large. + /// - [`Error::InvalidWeight`] when a weight is not-a-number or negative. + /// - [`Error::InsufficientNonZero`] when the sum of all weights is zero. + /// Note that due to floating-point loss of precision, this case is not + /// always correctly detected; usage of a fixed-point weight type may be + /// preferred. + /// + /// Updates take `O(N)` time. If you need to frequently update weights, consider + /// [`rand_distr::weighted_tree`](https://docs.rs/rand_distr/*/rand_distr/weighted_tree/index.html) + /// as an alternative where an update is `O(log N)`. + pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), Error> + where + X: for<'a> core::ops::AddAssign<&'a X> + + for<'a> core::ops::SubAssign<&'a X> + + Clone + + Default, + { + if new_weights.is_empty() { + return Ok(()); + } + + let zero = ::default(); + + let mut total_weight = self.total_weight.clone(); + + // Check for errors first, so we don't modify `self` in case something + // goes wrong. + let mut prev_i = None; + for &(i, w) in new_weights { + if let Some(old_i) = prev_i { + if old_i >= i { + return Err(Error::InvalidInput); + } + } + if !(*w >= zero) { + return Err(Error::InvalidWeight); + } + if i > self.cumulative_weights.len() { + return Err(Error::InvalidInput); + } + + let mut old_w = if i < self.cumulative_weights.len() { + self.cumulative_weights[i].clone() + } else { + self.total_weight.clone() + }; + if i > 0 { + old_w -= &self.cumulative_weights[i - 1]; + } + + total_weight -= &old_w; + total_weight += w; + prev_i = Some(i); + } + if total_weight <= zero { + return Err(Error::InsufficientNonZero); + } + + // Update the weights. Because we checked all the preconditions in the + // previous loop, this should never panic. + let mut iter = new_weights.iter(); + + let mut prev_weight = zero.clone(); + let mut next_new_weight = iter.next(); + let &(first_new_index, _) = next_new_weight.unwrap(); + let mut cumulative_weight = if first_new_index > 0 { + self.cumulative_weights[first_new_index - 1].clone() + } else { + zero.clone() + }; + for i in first_new_index..self.cumulative_weights.len() { + match next_new_weight { + Some(&(j, w)) if i == j => { + cumulative_weight += w; + next_new_weight = iter.next(); + } + _ => { + let mut tmp = self.cumulative_weights[i].clone(); + tmp -= &prev_weight; // We know this is positive. + cumulative_weight += &tmp; + } + } + prev_weight = cumulative_weight.clone(); + core::mem::swap(&mut prev_weight, &mut self.cumulative_weights[i]); + } + + self.total_weight = total_weight; + self.weight_distribution = X::Sampler::new(zero, self.total_weight.clone()).unwrap(); + + Ok(()) + } +} + +/// A lazy-loading iterator over the weights of a `WeightedIndex` distribution. +/// This is returned by [`WeightedIndex::weights`]. +pub struct WeightedIndexIter<'a, X: SampleUniform + PartialOrd> { + weighted_index: &'a WeightedIndex, + index: usize, +} + +impl Debug for WeightedIndexIter<'_, X> +where + X: SampleUniform + PartialOrd + Debug, + X::Sampler: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WeightedIndexIter") + .field("weighted_index", &self.weighted_index) + .field("index", &self.index) + .finish() + } +} + +impl Clone for WeightedIndexIter<'_, X> +where + X: SampleUniform + PartialOrd, +{ + fn clone(&self) -> Self { + WeightedIndexIter { + weighted_index: self.weighted_index, + index: self.index, + } + } +} + +impl Iterator for WeightedIndexIter<'_, X> +where + X: for<'b> core::ops::SubAssign<&'b X> + SampleUniform + PartialOrd + Clone, +{ + type Item = X; + + fn next(&mut self) -> Option { + match self.weighted_index.weight(self.index) { + None => None, + Some(weight) => { + self.index += 1; + Some(weight) + } + } + } +} + +impl WeightedIndex { + /// Returns the weight at the given index, if it exists. + /// + /// If the index is out of bounds, this will return `None`. + /// + /// # Example + /// + /// ``` + /// use rand::distr::weighted::WeightedIndex; + /// + /// let weights = [0, 1, 2]; + /// let dist = WeightedIndex::new(&weights).unwrap(); + /// assert_eq!(dist.weight(0), Some(0)); + /// assert_eq!(dist.weight(1), Some(1)); + /// assert_eq!(dist.weight(2), Some(2)); + /// assert_eq!(dist.weight(3), None); + /// ``` + pub fn weight(&self, index: usize) -> Option + where + X: for<'a> core::ops::SubAssign<&'a X>, + { + use core::cmp::Ordering::*; + + let mut weight = match index.cmp(&self.cumulative_weights.len()) { + Less => self.cumulative_weights[index].clone(), + Equal => self.total_weight.clone(), + Greater => return None, + }; + + if index > 0 { + weight -= &self.cumulative_weights[index - 1]; + } + Some(weight) + } + + /// Returns a lazy-loading iterator containing the current weights of this distribution. + /// + /// If this distribution has not been updated since its creation, this will return the + /// same weights as were passed to `new`. + /// + /// # Example + /// + /// ``` + /// use rand::distr::weighted::WeightedIndex; + /// + /// let weights = [1, 2, 3]; + /// let mut dist = WeightedIndex::new(&weights).unwrap(); + /// assert_eq!(dist.weights().collect::>(), vec![1, 2, 3]); + /// dist.update_weights(&[(0, &2)]).unwrap(); + /// assert_eq!(dist.weights().collect::>(), vec![2, 2, 3]); + /// ``` + pub fn weights(&self) -> WeightedIndexIter<'_, X> + where + X: for<'a> core::ops::SubAssign<&'a X>, + { + WeightedIndexIter { + weighted_index: self, + index: 0, + } + } + + /// Returns the sum of all weights in this distribution. + pub fn total_weight(&self) -> X { + self.total_weight.clone() + } +} + +impl Distribution for WeightedIndex +where + X: SampleUniform + PartialOrd, +{ + fn sample(&self, rng: &mut R) -> usize { + let chosen_weight = self.weight_distribution.sample(rng); + // Find the first item which has a weight *higher* than the chosen weight. + self.cumulative_weights + .partition_point(|w| w <= &chosen_weight) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[cfg(feature = "serde")] + #[test] + fn test_weightedindex_serde() { + let weighted_index = WeightedIndex::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap(); + + let ser_weighted_index = bincode::serialize(&weighted_index).unwrap(); + let de_weighted_index: WeightedIndex = + bincode::deserialize(&ser_weighted_index).unwrap(); + + assert_eq!( + de_weighted_index.cumulative_weights, + weighted_index.cumulative_weights + ); + assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight); + } + + #[test] + fn test_accepting_nan() { + assert_eq!( + WeightedIndex::new([f32::NAN, 0.5]).unwrap_err(), + Error::InvalidWeight, + ); + assert_eq!( + WeightedIndex::new([f32::NAN]).unwrap_err(), + Error::InvalidWeight, + ); + assert_eq!( + WeightedIndex::new([0.5, f32::NAN]).unwrap_err(), + Error::InvalidWeight, + ); + + assert_eq!( + WeightedIndex::new([0.5, 7.0]) + .unwrap() + .update_weights(&[(0, &f32::NAN)]) + .unwrap_err(), + Error::InvalidWeight, + ) + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_weightedindex() { + let mut r = crate::test::rng(700); + const N_REPS: u32 = 5000; + let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; + let total_weight = weights.iter().sum::() as f32; + + let verify = |result: [i32; 14]| { + for (i, count) in result.iter().enumerate() { + let exp = (weights[i] * N_REPS) as f32 / total_weight; + let mut err = (*count as f32 - exp).abs(); + if err != 0.0 { + err /= exp; + } + assert!(err <= 0.25); + } + }; + + // WeightedIndex from vec + let mut chosen = [0i32; 14]; + let distr = WeightedIndex::new(weights.to_vec()).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + // WeightedIndex from slice + chosen = [0i32; 14]; + let distr = WeightedIndex::new(&weights[..]).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + // WeightedIndex from iterator + chosen = [0i32; 14]; + let distr = WeightedIndex::new(weights.iter()).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + for _ in 0..5 { + assert_eq!(WeightedIndex::new([0, 1]).unwrap().sample(&mut r), 1); + assert_eq!(WeightedIndex::new([1, 0]).unwrap().sample(&mut r), 0); + assert_eq!( + WeightedIndex::new([0, 0, 0, 0, 10, 0]) + .unwrap() + .sample(&mut r), + 4 + ); + } + + assert_eq!( + WeightedIndex::new(&[10][0..0]).unwrap_err(), + Error::InvalidInput + ); + assert_eq!( + WeightedIndex::new([0]).unwrap_err(), + Error::InsufficientNonZero + ); + assert_eq!( + WeightedIndex::new([10, 20, -1, 30]).unwrap_err(), + Error::InvalidWeight + ); + assert_eq!( + WeightedIndex::new([-10, 20, 1, 30]).unwrap_err(), + Error::InvalidWeight + ); + assert_eq!(WeightedIndex::new([-10]).unwrap_err(), Error::InvalidWeight); + } + + #[test] + fn test_update_weights() { + let data = [ + ( + &[10u32, 2, 3, 4][..], + &[(1, &100), (2, &4)][..], // positive change + &[10, 100, 4, 4][..], + ), + ( + &[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], + &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element + &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..], + ), + ]; + + for (weights, update, expected_weights) in data.iter() { + let total_weight = weights.iter().sum::(); + let mut distr = WeightedIndex::new(weights.to_vec()).unwrap(); + assert_eq!(distr.total_weight, total_weight); + + distr.update_weights(update).unwrap(); + let expected_total_weight = expected_weights.iter().sum::(); + let expected_distr = WeightedIndex::new(expected_weights.to_vec()).unwrap(); + assert_eq!(distr.total_weight, expected_total_weight); + assert_eq!(distr.total_weight, expected_distr.total_weight); + assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights); + } + } + + #[test] + fn test_update_weights_errors() { + let data = [ + ( + &[1i32, 0, 0][..], + &[(0, &0)][..], + Error::InsufficientNonZero, + ), + ( + &[10, 10, 10, 10][..], + &[(1, &-11)][..], + Error::InvalidWeight, // A weight is negative + ), + ( + &[1, 2, 3, 4, 5][..], + &[(1, &5), (0, &5)][..], // Wrong order + Error::InvalidInput, + ), + ( + &[1][..], + &[(1, &1)][..], // Index too large + Error::InvalidInput, + ), + ]; + + for (weights, update, err) in data.iter() { + let total_weight = weights.iter().sum::(); + let mut distr = WeightedIndex::new(weights.to_vec()).unwrap(); + assert_eq!(distr.total_weight, total_weight); + match distr.update_weights(update) { + Ok(_) => panic!("Expected update_weights to fail, but it succeeded"), + Err(e) => assert_eq!(e, *err), + } + } + } + + #[test] + fn test_weight_at() { + let data = [ + &[1][..], + &[10, 2, 3, 4][..], + &[1, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], + &[u32::MAX][..], + ]; + + for weights in data.iter() { + let distr = WeightedIndex::new(weights.to_vec()).unwrap(); + for (i, weight) in weights.iter().enumerate() { + assert_eq!(distr.weight(i), Some(*weight)); + } + assert_eq!(distr.weight(weights.len()), None); + } + } + + #[test] + fn test_weights() { + let data = [ + &[1][..], + &[10, 2, 3, 4][..], + &[1, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], + &[u32::MAX][..], + ]; + + for weights in data.iter() { + let distr = WeightedIndex::new(weights.to_vec()).unwrap(); + assert_eq!(distr.weights().collect::>(), weights.to_vec()); + } + } + + #[test] + fn value_stability() { + fn test_samples( + weights: I, + buf: &mut [usize], + expected: &[usize], + ) where + I: IntoIterator, + I::Item: SampleBorrow, + { + assert_eq!(buf.len(), expected.len()); + let distr = WeightedIndex::new(weights).unwrap(); + let mut rng = crate::test::rng(701); + for r in buf.iter_mut() { + *r = rng.sample(&distr); + } + assert_eq!(buf, expected); + } + + let mut buf = [0; 10]; + test_samples( + [1i32, 1, 1, 1, 1, 1, 1, 1, 1], + &mut buf, + &[0, 6, 2, 6, 3, 4, 7, 8, 2, 5], + ); + test_samples( + [0.7f32, 0.1, 0.1, 0.1], + &mut buf, + &[0, 0, 0, 1, 0, 0, 2, 3, 0, 0], + ); + test_samples( + [1.0f64, 0.999, 0.998, 0.997], + &mut buf, + &[2, 2, 1, 3, 2, 1, 3, 3, 2, 1], + ); + } + + #[test] + fn weighted_index_distributions_can_be_compared() { + assert_eq!(WeightedIndex::new([1, 2]), WeightedIndex::new([1, 2])); + } + + #[test] + fn overflow() { + assert_eq!(WeightedIndex::new([2, usize::MAX]), Err(Error::Overflow)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,360 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utilities for random number generation +//! +//! Rand provides utilities to generate random numbers, to convert them to +//! useful types and distributions, and some randomness-related algorithms. +//! +//! # Quick Start +//! +//! ``` +//! // The prelude import enables methods we use below, specifically +//! // Rng::random, Rng::sample, SliceRandom::shuffle and IndexedRandom::choose. +//! use rand::prelude::*; +//! +//! // Get an RNG: +//! let mut rng = rand::rng(); +//! +//! // Try printing a random unicode code point (probably a bad idea)! +//! println!("char: '{}'", rng.random::()); +//! // Try printing a random alphanumeric value instead! +//! println!("alpha: '{}'", rng.sample(rand::distr::Alphanumeric) as char); +//! +//! // Generate and shuffle a sequence: +//! let mut nums: Vec = (1..100).collect(); +//! nums.shuffle(&mut rng); +//! // And take a random pick (yes, we didn't need to shuffle first!): +//! let _ = nums.choose(&mut rng); +//! ``` +//! +//! # The Book +//! +//! For the user guide and further documentation, please read +//! [The Rust Rand Book](https://rust-random.github.io/book). + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![no_std] +#![cfg_attr(feature = "simd_support", feature(portable_simd))] +#![cfg_attr( + all(feature = "simd_support", target_feature = "avx512bw"), + feature(stdarch_x86_avx512) +)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![allow( + clippy::float_cmp, + clippy::neg_cmp_op_on_partial_ord, + clippy::nonminimal_bool +)] +#![deny(clippy::undocumented_unsafe_blocks)] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +#[allow(unused)] +macro_rules! trace { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::trace!($($x)*) + } +) } +#[allow(unused)] +macro_rules! debug { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::debug!($($x)*) + } +) } +#[allow(unused)] +macro_rules! info { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::info!($($x)*) + } +) } +#[allow(unused)] +macro_rules! warn { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::warn!($($x)*) + } +) } +#[allow(unused)] +macro_rules! error { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::error!($($x)*) + } +) } + +// Re-export rand_core itself +pub use rand_core; + +// Re-exports from rand_core +pub use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore}; + +// Public modules +pub mod distr; +pub mod prelude; +mod rng; +pub mod rngs; +pub mod seq; + +// Public exports +#[cfg(feature = "thread_rng")] +pub use crate::rngs::thread::rng; + +/// Access the thread-local generator +/// +/// Use [`rand::rng()`](rng()) instead. +#[cfg(feature = "thread_rng")] +#[deprecated(since = "0.9.0", note = "Renamed to `rng`")] +#[inline] +pub fn thread_rng() -> crate::rngs::ThreadRng { + rng() +} + +pub use rng::{Fill, Rng}; + +#[cfg(feature = "thread_rng")] +use crate::distr::{Distribution, StandardUniform}; + +/// Generate a random value using the thread-local random number generator. +/// +/// This function is shorthand for [rng()].[random()](Rng::random): +/// +/// - See [`ThreadRng`] for documentation of the generator and security +/// - See [`StandardUniform`] for documentation of supported types and distributions +/// +/// # Examples +/// +/// ``` +/// let x = rand::random::(); +/// println!("{}", x); +/// +/// let y = rand::random::(); +/// println!("{}", y); +/// +/// if rand::random() { // generates a boolean +/// println!("Better lucky than good!"); +/// } +/// ``` +/// +/// If you're calling `random()` repeatedly, consider using a local `rng` +/// handle to save an initialization-check on each usage: +/// +/// ``` +/// use rand::Rng; // provides the `random` method +/// +/// let mut rng = rand::rng(); // a local handle to the generator +/// +/// let mut v = vec![1, 2, 3]; +/// +/// for x in v.iter_mut() { +/// *x = rng.random(); +/// } +/// ``` +/// +/// [`StandardUniform`]: distr::StandardUniform +/// [`ThreadRng`]: rngs::ThreadRng +#[cfg(feature = "thread_rng")] +#[inline] +pub fn random() -> T +where + StandardUniform: Distribution, +{ + rng().random() +} + +/// Return an iterator over [`random()`] variates +/// +/// This function is shorthand for +/// [rng()].[random_iter](Rng::random_iter)(). +/// +/// # Example +/// +/// ``` +/// let v: Vec = rand::random_iter().take(5).collect(); +/// println!("{v:?}"); +/// ``` +#[cfg(feature = "thread_rng")] +#[inline] +pub fn random_iter() -> distr::Iter +where + StandardUniform: Distribution, +{ + rng().random_iter() +} + +/// Generate a random value in the given range using the thread-local random number generator. +/// +/// This function is shorthand for +/// [rng()].[random_range](Rng::random_range)(range). +/// +/// # Example +/// +/// ``` +/// let y: f32 = rand::random_range(0.0..=1e9); +/// println!("{}", y); +/// +/// let words: Vec<&str> = "Mary had a little lamb".split(' ').collect(); +/// println!("{}", words[rand::random_range(..words.len())]); +/// ``` +/// Note that the first example can also be achieved (without `collect`'ing +/// to a `Vec`) using [`seq::IteratorRandom::choose`]. +#[cfg(feature = "thread_rng")] +#[inline] +pub fn random_range(range: R) -> T +where + T: distr::uniform::SampleUniform, + R: distr::uniform::SampleRange, +{ + rng().random_range(range) +} + +/// Return a bool with a probability `p` of being true. +/// +/// This function is shorthand for +/// [rng()].[random_bool](Rng::random_bool)(p). +/// +/// # Example +/// +/// ``` +/// println!("{}", rand::random_bool(1.0 / 3.0)); +/// ``` +/// +/// # Panics +/// +/// If `p < 0` or `p > 1`. +#[cfg(feature = "thread_rng")] +#[inline] +#[track_caller] +pub fn random_bool(p: f64) -> bool { + rng().random_bool(p) +} + +/// Return a bool with a probability of `numerator/denominator` of being +/// true. +/// +/// That is, `random_ratio(2, 3)` has chance of 2 in 3, or about 67%, of +/// returning true. If `numerator == denominator`, then the returned value +/// is guaranteed to be `true`. If `numerator == 0`, then the returned +/// value is guaranteed to be `false`. +/// +/// See also the [`Bernoulli`] distribution, which may be faster if +/// sampling from the same `numerator` and `denominator` repeatedly. +/// +/// This function is shorthand for +/// [rng()].[random_ratio](Rng::random_ratio)(numerator, denominator). +/// +/// # Panics +/// +/// If `denominator == 0` or `numerator > denominator`. +/// +/// # Example +/// +/// ``` +/// println!("{}", rand::random_ratio(2, 3)); +/// ``` +/// +/// [`Bernoulli`]: distr::Bernoulli +#[cfg(feature = "thread_rng")] +#[inline] +#[track_caller] +pub fn random_ratio(numerator: u32, denominator: u32) -> bool { + rng().random_ratio(numerator, denominator) +} + +/// Fill any type implementing [`Fill`] with random data +/// +/// This function is shorthand for +/// [rng()].[fill](Rng::fill)(dest). +/// +/// # Example +/// +/// ``` +/// let mut arr = [0i8; 20]; +/// rand::fill(&mut arr[..]); +/// ``` +/// +/// Note that you can instead use [`random()`] to generate an array of random +/// data, though this is slower for small elements (smaller than the RNG word +/// size). +#[cfg(feature = "thread_rng")] +#[inline] +#[track_caller] +pub fn fill(dest: &mut T) { + dest.fill(&mut rng()) +} + +#[cfg(test)] +mod test { + use super::*; + + /// Construct a deterministic RNG with the given seed + pub fn rng(seed: u64) -> impl RngCore { + // For tests, we want a statistically good, fast, reproducible RNG. + // PCG32 will do fine, and will be easy to embed if we ever need to. + const INC: u64 = 11634580027462260723; + rand_pcg::Pcg32::new(seed, INC) + } + + /// Construct a generator yielding a constant value + pub fn const_rng(x: u64) -> StepRng { + StepRng(x, 0) + } + + /// Construct a generator yielding an arithmetic sequence + pub fn step_rng(x: u64, increment: u64) -> StepRng { + StepRng(x, increment) + } + + #[derive(Clone)] + pub struct StepRng(u64, u64); + impl RngCore for StepRng { + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } + + fn next_u64(&mut self) -> u64 { + let res = self.0; + self.0 = self.0.wrapping_add(self.1); + res + } + + fn fill_bytes(&mut self, dst: &mut [u8]) { + rand_core::impls::fill_bytes_via_next(self, dst) + } + } + + #[test] + #[cfg(feature = "thread_rng")] + fn test_random() { + let _n: u64 = random(); + let _f: f32 = random(); + #[allow(clippy::type_complexity)] + let _many: ( + (), + [(u32, bool); 3], + (u8, i8, u16, i16, u32, i32, u64, i64), + (f32, (f64, (f64,))), + ) = random(); + } + + #[test] + #[cfg(feature = "thread_rng")] + fn test_range() { + let _n: usize = random_range(42..=43); + let _f: f32 = random_range(42.0..43.0); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/prelude.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/prelude.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/prelude.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/prelude.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Convenience re-export of common members +//! +//! Like the standard library's prelude, this module simplifies importing of +//! common items. Unlike the standard prelude, the contents of this module must +//! be imported manually: +//! +//! ``` +//! use rand::prelude::*; +//! # let mut r = StdRng::from_rng(&mut rand::rng()); +//! # let _: f32 = r.random(); +//! ``` + +#[doc(no_inline)] +pub use crate::distr::Distribution; +#[cfg(feature = "small_rng")] +#[doc(no_inline)] +pub use crate::rngs::SmallRng; +#[cfg(feature = "std_rng")] +#[doc(no_inline)] +pub use crate::rngs::StdRng; +#[doc(no_inline)] +#[cfg(feature = "thread_rng")] +pub use crate::rngs::ThreadRng; +#[doc(no_inline)] +pub use crate::seq::{IndexedMutRandom, IndexedRandom, IteratorRandom, SliceRandom}; +#[doc(no_inline)] +pub use crate::{CryptoRng, Rng, RngCore, SeedableRng}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rng.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rng.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rng.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rng.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,657 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! [`Rng`] trait + +use crate::distr::uniform::{SampleRange, SampleUniform}; +use crate::distr::{self, Distribution, StandardUniform}; +use core::num::Wrapping; +use core::{mem, slice}; +use rand_core::RngCore; + +/// User-level interface for RNGs +/// +/// [`RngCore`] is the `dyn`-safe implementation-level interface for Random +/// (Number) Generators. This trait, `Rng`, provides a user-level interface on +/// RNGs. It is implemented automatically for any `R: RngCore`. +/// +/// This trait must usually be brought into scope via `use rand::Rng;` or +/// `use rand::prelude::*;`. +/// +/// # Generic usage +/// +/// The basic pattern is `fn foo(rng: &mut R)`. Some +/// things are worth noting here: +/// +/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no +/// difference whether we use `R: Rng` or `R: RngCore`. +/// - The `+ ?Sized` un-bounding allows functions to be called directly on +/// type-erased references; i.e. `foo(r)` where `r: &mut dyn RngCore`. Without +/// this it would be necessary to write `foo(&mut r)`. +/// +/// An alternative pattern is possible: `fn foo(rng: R)`. This has some +/// trade-offs. It allows the argument to be consumed directly without a `&mut` +/// (which is how `from_rng(rand::rng())` works); also it still works directly +/// on references (including type-erased references). Unfortunately within the +/// function `foo` it is not known whether `rng` is a reference type or not, +/// hence many uses of `rng` require an extra reference, either explicitly +/// (`distr.sample(&mut rng)`) or implicitly (`rng.random()`); one may hope the +/// optimiser can remove redundant references later. +/// +/// Example: +/// +/// ``` +/// use rand::Rng; +/// +/// fn foo(rng: &mut R) -> f32 { +/// rng.random() +/// } +/// +/// # let v = foo(&mut rand::rng()); +/// ``` +pub trait Rng: RngCore { + /// Return a random value via the [`StandardUniform`] distribution. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// + /// let mut rng = rand::rng(); + /// let x: u32 = rng.random(); + /// println!("{}", x); + /// println!("{:?}", rng.random::<(f64, bool)>()); + /// ``` + /// + /// # Arrays and tuples + /// + /// The `rng.random()` method is able to generate arrays + /// and tuples (up to 12 elements), so long as all element types can be + /// generated. + /// + /// For arrays of integers, especially for those with small element types + /// (< 64 bit), it will likely be faster to instead use [`Rng::fill`], + /// though note that generated values will differ. + /// + /// ``` + /// use rand::Rng; + /// + /// let mut rng = rand::rng(); + /// let tuple: (u8, i32, char) = rng.random(); // arbitrary tuple support + /// + /// let arr1: [f32; 32] = rng.random(); // array construction + /// let mut arr2 = [0u8; 128]; + /// rng.fill(&mut arr2); // array fill + /// ``` + /// + /// [`StandardUniform`]: distr::StandardUniform + #[inline] + fn random(&mut self) -> T + where + StandardUniform: Distribution, + { + StandardUniform.sample(self) + } + + /// Return an iterator over [`random`](Self::random) variates + /// + /// This is a just a wrapper over [`Rng::sample_iter`] using + /// [`distr::StandardUniform`]. + /// + /// Note: this method consumes its argument. Use + /// `(&mut rng).random_iter()` to avoid consuming the RNG. + /// + /// # Example + /// + /// ``` + /// use rand::{rngs::SmallRng, Rng, SeedableRng}; + /// + /// let rng = SmallRng::seed_from_u64(0); + /// let v: Vec = rng.random_iter().take(5).collect(); + /// assert_eq!(v.len(), 5); + /// ``` + #[inline] + fn random_iter(self) -> distr::Iter + where + Self: Sized, + StandardUniform: Distribution, + { + StandardUniform.sample_iter(self) + } + + /// Generate a random value in the given range. + /// + /// This function is optimised for the case that only a single sample is + /// made from the given range. See also the [`Uniform`] distribution + /// type which may be faster if sampling from the same range repeatedly. + /// + /// All types support `low..high_exclusive` and `low..=high` range syntax. + /// Unsigned integer types also support `..high_exclusive` and `..=high` syntax. + /// + /// # Panics + /// + /// Panics if the range is empty, or if `high - low` overflows for floats. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// + /// let mut rng = rand::rng(); + /// + /// // Exclusive range + /// let n: u32 = rng.random_range(..10); + /// println!("{}", n); + /// let m: f64 = rng.random_range(-40.0..1.3e5); + /// println!("{}", m); + /// + /// // Inclusive range + /// let n: u32 = rng.random_range(..=10); + /// println!("{}", n); + /// ``` + /// + /// [`Uniform`]: distr::uniform::Uniform + #[track_caller] + fn random_range(&mut self, range: R) -> T + where + T: SampleUniform, + R: SampleRange, + { + assert!(!range.is_empty(), "cannot sample empty range"); + range.sample_single(self).unwrap() + } + + /// Return a bool with a probability `p` of being true. + /// + /// See also the [`Bernoulli`] distribution, which may be faster if + /// sampling from the same probability repeatedly. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// + /// let mut rng = rand::rng(); + /// println!("{}", rng.random_bool(1.0 / 3.0)); + /// ``` + /// + /// # Panics + /// + /// If `p < 0` or `p > 1`. + /// + /// [`Bernoulli`]: distr::Bernoulli + #[inline] + #[track_caller] + fn random_bool(&mut self, p: f64) -> bool { + match distr::Bernoulli::new(p) { + Ok(d) => self.sample(d), + Err(_) => panic!("p={:?} is outside range [0.0, 1.0]", p), + } + } + + /// Return a bool with a probability of `numerator/denominator` of being + /// true. + /// + /// That is, `random_ratio(2, 3)` has chance of 2 in 3, or about 67%, of + /// returning true. If `numerator == denominator`, then the returned value + /// is guaranteed to be `true`. If `numerator == 0`, then the returned + /// value is guaranteed to be `false`. + /// + /// See also the [`Bernoulli`] distribution, which may be faster if + /// sampling from the same `numerator` and `denominator` repeatedly. + /// + /// # Panics + /// + /// If `denominator == 0` or `numerator > denominator`. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// + /// let mut rng = rand::rng(); + /// println!("{}", rng.random_ratio(2, 3)); + /// ``` + /// + /// [`Bernoulli`]: distr::Bernoulli + #[inline] + #[track_caller] + fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool { + match distr::Bernoulli::from_ratio(numerator, denominator) { + Ok(d) => self.sample(d), + Err(_) => panic!( + "p={}/{} is outside range [0.0, 1.0]", + numerator, denominator + ), + } + } + + /// Sample a new value, using the given distribution. + /// + /// ### Example + /// + /// ``` + /// use rand::Rng; + /// use rand::distr::Uniform; + /// + /// let mut rng = rand::rng(); + /// let x = rng.sample(Uniform::new(10u32, 15).unwrap()); + /// // Type annotation requires two types, the type and distribution; the + /// // distribution can be inferred. + /// let y = rng.sample::(Uniform::new(10, 15).unwrap()); + /// ``` + fn sample>(&mut self, distr: D) -> T { + distr.sample(self) + } + + /// Create an iterator that generates values using the given distribution. + /// + /// Note: this method consumes its arguments. Use + /// `(&mut rng).sample_iter(..)` to avoid consuming the RNG. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// use rand::distr::{Alphanumeric, Uniform, StandardUniform}; + /// + /// let mut rng = rand::rng(); + /// + /// // Vec of 16 x f32: + /// let v: Vec = (&mut rng).sample_iter(StandardUniform).take(16).collect(); + /// + /// // String: + /// let s: String = (&mut rng).sample_iter(Alphanumeric) + /// .take(7) + /// .map(char::from) + /// .collect(); + /// + /// // Combined values + /// println!("{:?}", (&mut rng).sample_iter(StandardUniform).take(5) + /// .collect::>()); + /// + /// // Dice-rolling: + /// let die_range = Uniform::new_inclusive(1, 6).unwrap(); + /// let mut roll_die = (&mut rng).sample_iter(die_range); + /// while roll_die.next().unwrap() != 6 { + /// println!("Not a 6; rolling again!"); + /// } + /// ``` + fn sample_iter(self, distr: D) -> distr::Iter + where + D: Distribution, + Self: Sized, + { + distr.sample_iter(self) + } + + /// Fill any type implementing [`Fill`] with random data + /// + /// This method is implemented for types which may be safely reinterpreted + /// as an (aligned) `[u8]` slice then filled with random data. It is often + /// faster than using [`Rng::random`] but not value-equivalent. + /// + /// The distribution is expected to be uniform with portable results, but + /// this cannot be guaranteed for third-party implementations. + /// + /// # Example + /// + /// ``` + /// use rand::Rng; + /// + /// let mut arr = [0i8; 20]; + /// rand::rng().fill(&mut arr[..]); + /// ``` + /// + /// [`fill_bytes`]: RngCore::fill_bytes + #[track_caller] + fn fill(&mut self, dest: &mut T) { + dest.fill(self) + } + + /// Alias for [`Rng::random`]. + #[inline] + #[deprecated( + since = "0.9.0", + note = "Renamed to `random` to avoid conflict with the new `gen` keyword in Rust 2024." + )] + fn r#gen(&mut self) -> T + where + StandardUniform: Distribution, + { + self.random() + } + + /// Alias for [`Rng::random_range`]. + #[inline] + #[deprecated(since = "0.9.0", note = "Renamed to `random_range`")] + fn gen_range(&mut self, range: R) -> T + where + T: SampleUniform, + R: SampleRange, + { + self.random_range(range) + } + + /// Alias for [`Rng::random_bool`]. + #[inline] + #[deprecated(since = "0.9.0", note = "Renamed to `random_bool`")] + fn gen_bool(&mut self, p: f64) -> bool { + self.random_bool(p) + } + + /// Alias for [`Rng::random_ratio`]. + #[inline] + #[deprecated(since = "0.9.0", note = "Renamed to `random_ratio`")] + fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool { + self.random_ratio(numerator, denominator) + } +} + +impl Rng for R {} + +/// Types which may be filled with random data +/// +/// This trait allows arrays to be efficiently filled with random data. +/// +/// Implementations are expected to be portable across machines unless +/// clearly documented otherwise (see the +/// [Chapter on Portability](https://rust-random.github.io/book/portability.html)). +pub trait Fill { + /// Fill self with random data + fn fill(&mut self, rng: &mut R); +} + +macro_rules! impl_fill_each { + () => {}; + ($t:ty) => { + impl Fill for [$t] { + fn fill(&mut self, rng: &mut R) { + for elt in self.iter_mut() { + *elt = rng.random(); + } + } + } + }; + ($t:ty, $($tt:ty,)*) => { + impl_fill_each!($t); + impl_fill_each!($($tt,)*); + }; +} + +impl_fill_each!(bool, char, f32, f64,); + +impl Fill for [u8] { + fn fill(&mut self, rng: &mut R) { + rng.fill_bytes(self) + } +} + +/// Call target for unsafe macros +const unsafe fn __unsafe() {} + +/// Implement `Fill` for given type `$t`. +/// +/// # Safety +/// All bit patterns of `[u8; size_of::<$t>()]` must represent values of `$t`. +macro_rules! impl_fill { + () => {}; + ($t:ty) => {{ + // Force caller to wrap with an `unsafe` block + __unsafe(); + + impl Fill for [$t] { + fn fill(&mut self, rng: &mut R) { + if self.len() > 0 { + let size = mem::size_of_val(self); + rng.fill_bytes( + // SAFETY: `self` non-null and valid for reads and writes within its `size` + // bytes. `self` meets the alignment requirements of `&mut [u8]`. + // The contents of `self` are initialized. Both `[u8]` and `[$t]` are valid + // for all bit-patterns of their contents (note that the SAFETY requirement + // on callers of this macro). `self` is not borrowed. + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() + as *mut u8, + size + ) + } + ); + for x in self { + *x = x.to_le(); + } + } + } + } + + impl Fill for [Wrapping<$t>] { + fn fill(&mut self, rng: &mut R) { + if self.len() > 0 { + let size = self.len() * mem::size_of::<$t>(); + rng.fill_bytes( + // SAFETY: `self` non-null and valid for reads and writes within its `size` + // bytes. `self` meets the alignment requirements of `&mut [u8]`. + // The contents of `self` are initialized. Both `[u8]` and `[$t]` are valid + // for all bit-patterns of their contents (note that the SAFETY requirement + // on callers of this macro). `self` is not borrowed. + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() + as *mut u8, + size + ) + } + ); + for x in self { + *x = Wrapping(x.0.to_le()); + } + } + } + }} + }; + ($t:ty, $($tt:ty,)*) => {{ + impl_fill!($t); + // TODO: this could replace above impl once Rust #32463 is fixed + // impl_fill!(Wrapping<$t>); + impl_fill!($($tt,)*); + }} +} + +// SAFETY: All bit patterns of `[u8; size_of::<$t>()]` represent values of `u*`. +const _: () = unsafe { impl_fill!(u16, u32, u64, u128,) }; +// SAFETY: All bit patterns of `[u8; size_of::<$t>()]` represent values of `i*`. +const _: () = unsafe { impl_fill!(i8, i16, i32, i64, i128,) }; + +impl Fill for [T; N] +where + [T]: Fill, +{ + fn fill(&mut self, rng: &mut R) { + <[T] as Fill>::fill(self, rng) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test::{const_rng, rng}; + #[cfg(feature = "alloc")] + use alloc::boxed::Box; + + #[test] + fn test_fill_bytes_default() { + let mut r = const_rng(0x11_22_33_44_55_66_77_88); + + // check every remainder mod 8, both in small and big vectors. + let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; + for &n in lengths.iter() { + let mut buffer = [0u8; 87]; + let v = &mut buffer[0..n]; + r.fill_bytes(v); + + // use this to get nicer error messages. + for (i, &byte) in v.iter().enumerate() { + if byte == 0 { + panic!("byte {} of {} is zero", i, n) + } + } + } + } + + #[test] + fn test_fill() { + let x = 9041086907909331047; // a random u64 + let mut rng = const_rng(x); + + // Convert to byte sequence and back to u64; byte-swap twice if BE. + let mut array = [0u64; 2]; + rng.fill(&mut array[..]); + assert_eq!(array, [x, x]); + assert_eq!(rng.next_u64(), x); + + // Convert to bytes then u32 in LE order + let mut array = [0u32; 2]; + rng.fill(&mut array[..]); + assert_eq!(array, [x as u32, (x >> 32) as u32]); + assert_eq!(rng.next_u32(), x as u32); + + // Check equivalence using wrapped arrays + let mut warray = [Wrapping(0u32); 2]; + rng.fill(&mut warray[..]); + assert_eq!(array[0], warray[0].0); + assert_eq!(array[1], warray[1].0); + + // Check equivalence for generated floats + let mut array = [0f32; 2]; + rng.fill(&mut array); + let arr2: [f32; 2] = rng.random(); + assert_eq!(array, arr2); + } + + #[test] + fn test_fill_empty() { + let mut array = [0u32; 0]; + let mut rng = rng(1); + rng.fill(&mut array); + rng.fill(&mut array[..]); + } + + #[test] + fn test_random_range_int() { + let mut r = rng(101); + for _ in 0..1000 { + let a = r.random_range(-4711..17); + assert!((-4711..17).contains(&a)); + let a: i8 = r.random_range(-3..42); + assert!((-3..42).contains(&a)); + let a: u16 = r.random_range(10..99); + assert!((10..99).contains(&a)); + let a: i32 = r.random_range(-100..2000); + assert!((-100..2000).contains(&a)); + let a: u32 = r.random_range(12..=24); + assert!((12..=24).contains(&a)); + + assert_eq!(r.random_range(..1u32), 0u32); + assert_eq!(r.random_range(-12i64..-11), -12i64); + assert_eq!(r.random_range(3_000_000..3_000_001), 3_000_000); + } + } + + #[test] + fn test_random_range_float() { + let mut r = rng(101); + for _ in 0..1000 { + let a = r.random_range(-4.5..1.7); + assert!((-4.5..1.7).contains(&a)); + let a = r.random_range(-1.1..=-0.3); + assert!((-1.1..=-0.3).contains(&a)); + + assert_eq!(r.random_range(0.0f32..=0.0), 0.); + assert_eq!(r.random_range(-11.0..=-11.0), -11.); + assert_eq!(r.random_range(3_000_000.0..=3_000_000.0), 3_000_000.); + } + } + + #[test] + #[should_panic] + #[allow(clippy::reversed_empty_ranges)] + fn test_random_range_panic_int() { + let mut r = rng(102); + r.random_range(5..-2); + } + + #[test] + #[should_panic] + #[allow(clippy::reversed_empty_ranges)] + fn test_random_range_panic_usize() { + let mut r = rng(103); + r.random_range(5..2); + } + + #[test] + #[allow(clippy::bool_assert_comparison)] + fn test_random_bool() { + let mut r = rng(105); + for _ in 0..5 { + assert_eq!(r.random_bool(0.0), false); + assert_eq!(r.random_bool(1.0), true); + } + } + + #[test] + fn test_rng_mut_ref() { + fn use_rng(mut r: impl Rng) { + let _ = r.next_u32(); + } + + let mut rng = rng(109); + use_rng(&mut rng); + } + + #[test] + fn test_rng_trait_object() { + use crate::distr::{Distribution, StandardUniform}; + let mut rng = rng(109); + let mut r = &mut rng as &mut dyn RngCore; + r.next_u32(); + r.random::(); + assert_eq!(r.random_range(0..1), 0); + let _c: u8 = StandardUniform.sample(&mut r); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_rng_boxed_trait() { + use crate::distr::{Distribution, StandardUniform}; + let rng = rng(110); + let mut r = Box::new(rng) as Box; + r.next_u32(); + r.random::(); + assert_eq!(r.random_range(0..1), 0); + let _c: u8 = StandardUniform.sample(&mut r); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_gen_ratio_average() { + const NUM: u32 = 3; + const DENOM: u32 = 10; + const N: u32 = 100_000; + + let mut sum: u32 = 0; + let mut rng = rng(111); + for _ in 0..N { + if rng.random_ratio(NUM, DENOM) { + sum += 1; + } + } + // Have Binomial(N, NUM/DENOM) distribution + let expected = (NUM * N) / DENOM; // exact integer + assert!(((sum - expected) as i32).abs() < 500); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/mock.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mock.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/mock.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mock.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Mock random number generator + +#![allow(deprecated)] + +use rand_core::{impls, RngCore}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A mock generator yielding very predictable output +/// +/// This generates an arithmetic sequence (i.e. adds a constant each step) +/// over a `u64` number, using wrapping arithmetic. If the increment is 0 +/// the generator yields a constant. +/// +/// Other integer types (64-bit and smaller) are produced via cast from `u64`. +/// +/// Other types are produced via their implementation of [`Rng`](crate::Rng) or +/// [`Distribution`](crate::distr::Distribution). +/// Output values may not be intuitive and may change in future releases but +/// are considered +/// [portable](https://rust-random.github.io/book/portability.html). +/// (`bool` output is true when bit `1u64 << 31` is set.) +/// +/// # Example +/// +/// ``` +/// # #![allow(deprecated)] +/// use rand::Rng; +/// use rand::rngs::mock::StepRng; +/// +/// let mut my_rng = StepRng::new(2, 1); +/// let sample: [u64; 3] = my_rng.random(); +/// assert_eq!(sample, [2, 3, 4]); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[deprecated(since = "0.9.2", note = "Deprecated without replacement")] +pub struct StepRng { + v: u64, + a: u64, +} + +impl StepRng { + /// Create a `StepRng`, yielding an arithmetic sequence starting with + /// `initial` and incremented by `increment` each time. + pub fn new(initial: u64, increment: u64) -> Self { + StepRng { + v: initial, + a: increment, + } + } +} + +impl RngCore for StepRng { + #[inline] + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let res = self.v; + self.v = self.v.wrapping_add(self.a); + res + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + impls::fill_bytes_via_next(self, dst) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Random number generators and adapters +//! +//! This crate provides a small selection of non-[portable] generators. +//! See also [Types of generators] and [Our RNGs] in the book. +//! +//! ## Generators +//! +//! This crate provides a small selection of non-[portable] random number generators: +//! +//! - [`OsRng`] is a stateless interface over the operating system's random number +//! source. This is typically secure with some form of periodic re-seeding. +//! - [`ThreadRng`], provided by [`crate::rng()`], is a handle to a +//! thread-local generator with periodic seeding from [`OsRng`]. Because this +//! is local, it is typically much faster than [`OsRng`]. It should be +//! secure, but see documentation on [`ThreadRng`]. +//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security +//! (based on reviews, maturity and usage). The current algorithm is ChaCha12, +//! which is well established and rigorously analysed. +//! [`StdRng`] is the deterministic generator used by [`ThreadRng`] but +//! without the periodic reseeding or thread-local management. +//! - [`SmallRng`] is a relatively simple, insecure generator designed to be +//! fast, use little memory, and pass various statistical tests of +//! randomness quality. +//! +//! The algorithms selected for [`StdRng`] and [`SmallRng`] may change in any +//! release and may be platform-dependent, therefore they are not +//! [reproducible][portable]. +//! +//! ### Additional generators +//! +//! - The [`rdrand`] crate provides an interface to the RDRAND and RDSEED +//! instructions available in modern Intel and AMD CPUs. +//! - The [`rand_jitter`] crate provides a user-space implementation of +//! entropy harvesting from CPU timer jitter, but is very slow and has +//! [security issues](https://github.com/rust-random/rand/issues/699). +//! - The [`rand_chacha`] crate provides [portable] implementations of +//! generators derived from the [ChaCha] family of stream ciphers +//! - The [`rand_pcg`] crate provides [portable] implementations of a subset +//! of the [PCG] family of small, insecure generators +//! - The [`rand_xoshiro`] crate provides [portable] implementations of the +//! [xoshiro] family of small, insecure generators +//! +//! For more, search [crates with the `rng` tag]. +//! +//! ## Traits and functionality +//! +//! All generators implement [`RngCore`] and thus also [`Rng`][crate::Rng]. +//! See also the [Random Values] chapter in the book. +//! +//! Secure RNGs may additionally implement the [`CryptoRng`] trait. +//! +//! Use the [`rand_core`] crate when implementing your own RNGs. +//! +//! [portable]: https://rust-random.github.io/book/crate-reprod.html +//! [Types of generators]: https://rust-random.github.io/book/guide-gen.html +//! [Our RNGs]: https://rust-random.github.io/book/guide-rngs.html +//! [Random Values]: https://rust-random.github.io/book/guide-values.html +//! [`Rng`]: crate::Rng +//! [`RngCore`]: crate::RngCore +//! [`CryptoRng`]: crate::CryptoRng +//! [`SeedableRng`]: crate::SeedableRng +//! [`rdrand`]: https://crates.io/crates/rdrand +//! [`rand_jitter`]: https://crates.io/crates/rand_jitter +//! [`rand_chacha`]: https://crates.io/crates/rand_chacha +//! [`rand_pcg`]: https://crates.io/crates/rand_pcg +//! [`rand_xoshiro`]: https://crates.io/crates/rand_xoshiro +//! [crates with the `rng` tag]: https://crates.io/keywords/rng +//! [chacha]: https://cr.yp.to/chacha.html +//! [PCG]: https://www.pcg-random.org/ +//! [xoshiro]: https://prng.di.unimi.it/ + +mod reseeding; +pub use reseeding::ReseedingRng; + +#[deprecated(since = "0.9.2")] +pub mod mock; // Public so we don't export `StepRng` directly, making it a bit + // more clear it is intended for testing. + +#[cfg(feature = "small_rng")] +mod small; +#[cfg(all( + feature = "small_rng", + any(target_pointer_width = "32", target_pointer_width = "16") +))] +mod xoshiro128plusplus; +#[cfg(all(feature = "small_rng", target_pointer_width = "64"))] +mod xoshiro256plusplus; + +#[cfg(feature = "std_rng")] +mod std; +#[cfg(feature = "thread_rng")] +pub(crate) mod thread; + +#[cfg(feature = "small_rng")] +pub use self::small::SmallRng; +#[cfg(feature = "std_rng")] +pub use self::std::StdRng; +#[cfg(feature = "thread_rng")] +pub use self::thread::ThreadRng; + +#[cfg(feature = "os_rng")] +pub use rand_core::OsRng; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/reseeding.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/reseeding.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/reseeding.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/reseeding.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,295 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A wrapper around another PRNG that reseeds it after it +//! generates a certain number of random bytes. + +use core::mem::size_of_val; + +use rand_core::block::{BlockRng, BlockRngCore, CryptoBlockRng}; +use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore}; + +/// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the +/// ability to reseed it. +/// +/// `ReseedingRng` reseeds the underlying PRNG in the following cases: +/// +/// - On a manual call to [`reseed()`]. +/// - After `clone()`, the clone will be reseeded on first use. +/// - After the PRNG has generated a configurable number of random bytes. +/// +/// # When should reseeding after a fixed number of generated bytes be used? +/// +/// Reseeding after a fixed number of generated bytes is never strictly +/// *necessary*. Cryptographic PRNGs don't have a limited number of bytes they +/// can output, or at least not a limit reachable in any practical way. There is +/// no such thing as 'running out of entropy'. +/// +/// Occasionally reseeding can be seen as some form of 'security in depth'. Even +/// if in the future a cryptographic weakness is found in the CSPRNG being used, +/// or a flaw in the implementation, occasionally reseeding should make +/// exploiting it much more difficult or even impossible. +/// +/// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding +/// after a fixed number of generated bytes. +/// +/// # Error handling +/// +/// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will +/// never panic but try to handle the error intelligently through some +/// combination of retrying and delaying reseeding until later. +/// If handling the source error fails `ReseedingRng` will continue generating +/// data from the wrapped PRNG without reseeding. +/// +/// Manually calling [`reseed()`] will not have this retry or delay logic, but +/// reports the error. +/// +/// # Example +/// +/// ``` +/// use rand::prelude::*; +/// use rand_chacha::ChaCha20Core; // Internal part of ChaChaRng that +/// // implements BlockRngCore +/// use rand::rngs::OsRng; +/// use rand::rngs::ReseedingRng; +/// +/// let mut reseeding_rng = ReseedingRng::::new(0, OsRng).unwrap(); +/// +/// println!("{}", reseeding_rng.random::()); +/// +/// let mut cloned_rng = reseeding_rng.clone(); +/// assert!(reseeding_rng.random::() != cloned_rng.random::()); +/// ``` +/// +/// [`BlockRngCore`]: rand_core::block::BlockRngCore +/// [`ReseedingRng::new`]: ReseedingRng::new +/// [`reseed()`]: ReseedingRng::reseed +#[derive(Debug)] +pub struct ReseedingRng(BlockRng>) +where + R: BlockRngCore + SeedableRng, + Rsdr: TryRngCore; + +impl ReseedingRng +where + R: BlockRngCore + SeedableRng, + Rsdr: TryRngCore, +{ + /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG + /// to use as reseeder. + /// + /// `threshold` sets the number of generated bytes after which to reseed the + /// PRNG. Set it to zero to never reseed based on the number of generated + /// values. + pub fn new(threshold: u64, reseeder: Rsdr) -> Result { + Ok(ReseedingRng(BlockRng::new(ReseedingCore::new( + threshold, reseeder, + )?))) + } + + /// Immediately reseed the generator + /// + /// This discards any remaining random data in the cache. + pub fn reseed(&mut self) -> Result<(), Rsdr::Error> { + self.0.reset(); + self.0.core.reseed() + } +} + +// TODO: this should be implemented for any type where the inner type +// implements RngCore, but we can't specify that because ReseedingCore is private +impl RngCore for ReseedingRng +where + R: BlockRngCore + SeedableRng, + Rsdr: TryRngCore, +{ + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } +} + +impl Clone for ReseedingRng +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: TryRngCore + Clone, +{ + fn clone(&self) -> ReseedingRng { + // Recreating `BlockRng` seems easier than cloning it and resetting + // the index. + ReseedingRng(BlockRng::new(self.0.core.clone())) + } +} + +impl CryptoRng for ReseedingRng +where + R: BlockRngCore + SeedableRng + CryptoBlockRng, + Rsdr: TryCryptoRng, +{ +} + +#[derive(Debug)] +struct ReseedingCore { + inner: R, + reseeder: Rsdr, + threshold: i64, + bytes_until_reseed: i64, +} + +impl BlockRngCore for ReseedingCore +where + R: BlockRngCore + SeedableRng, + Rsdr: TryRngCore, +{ + type Item = ::Item; + type Results = ::Results; + + fn generate(&mut self, results: &mut Self::Results) { + if self.bytes_until_reseed <= 0 { + // We get better performance by not calling only `reseed` here + // and continuing with the rest of the function, but by directly + // returning from a non-inlined function. + return self.reseed_and_generate(results); + } + let num_bytes = size_of_val(results.as_ref()); + self.bytes_until_reseed -= num_bytes as i64; + self.inner.generate(results); + } +} + +impl ReseedingCore +where + R: BlockRngCore + SeedableRng, + Rsdr: TryRngCore, +{ + /// Create a new `ReseedingCore`. + /// + /// `threshold` is the maximum number of bytes produced by + /// [`BlockRngCore::generate`] before attempting reseeding. + fn new(threshold: u64, mut reseeder: Rsdr) -> Result { + // Because generating more values than `i64::MAX` takes centuries on + // current hardware, we just clamp to that value. + // Also we set a threshold of 0, which indicates no limit, to that + // value. + let threshold = if threshold == 0 { + i64::MAX + } else if threshold <= i64::MAX as u64 { + threshold as i64 + } else { + i64::MAX + }; + + let inner = R::try_from_rng(&mut reseeder)?; + + Ok(ReseedingCore { + inner, + reseeder, + threshold, + bytes_until_reseed: threshold, + }) + } + + /// Reseed the internal PRNG. + fn reseed(&mut self) -> Result<(), Rsdr::Error> { + R::try_from_rng(&mut self.reseeder).map(|result| { + self.bytes_until_reseed = self.threshold; + self.inner = result + }) + } + + #[inline(never)] + fn reseed_and_generate(&mut self, results: &mut ::Results) { + trace!("Reseeding RNG (periodic reseed)"); + + let num_bytes = size_of_val(results.as_ref()); + + if let Err(e) = self.reseed() { + warn!("Reseeding RNG failed: {}", e); + let _ = e; + } + + self.bytes_until_reseed = self.threshold - num_bytes as i64; + self.inner.generate(results); + } +} + +impl Clone for ReseedingCore +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: TryRngCore + Clone, +{ + fn clone(&self) -> ReseedingCore { + ReseedingCore { + inner: self.inner.clone(), + reseeder: self.reseeder.clone(), + threshold: self.threshold, + bytes_until_reseed: 0, // reseed clone on first use + } + } +} + +impl CryptoBlockRng for ReseedingCore +where + R: BlockRngCore + SeedableRng + CryptoBlockRng, + Rsdr: TryCryptoRng, +{ +} + +#[cfg(feature = "std_rng")] +#[cfg(test)] +mod test { + use crate::rngs::std::Core; + use crate::test::const_rng; + use crate::Rng; + + use super::ReseedingRng; + + #[test] + fn test_reseeding() { + let zero = const_rng(0); + let thresh = 1; // reseed every time the buffer is exhausted + let mut reseeding = ReseedingRng::::new(thresh, zero).unwrap(); + + // RNG buffer size is [u32; 64] + // Debug is only implemented up to length 32 so use two arrays + let mut buf = ([0u32; 32], [0u32; 32]); + reseeding.fill(&mut buf.0); + reseeding.fill(&mut buf.1); + let seq = buf; + for _ in 0..10 { + reseeding.fill(&mut buf.0); + reseeding.fill(&mut buf.1); + assert_eq!(buf, seq); + } + } + + #[test] + #[allow(clippy::redundant_clone)] + fn test_clone_reseeding() { + let zero = const_rng(0); + let mut rng1 = ReseedingRng::::new(32 * 4, zero).unwrap(); + + let first: u32 = rng1.random(); + for _ in 0..10 { + let _ = rng1.random::(); + } + + let mut rng2 = rng1.clone(); + assert_eq!(first, rng2.random::()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/small.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/small.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/small.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/small.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A small fast RNG + +use rand_core::{RngCore, SeedableRng}; + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] +type Rng = super::xoshiro128plusplus::Xoshiro128PlusPlus; +#[cfg(target_pointer_width = "64")] +type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus; + +/// A small-state, fast, non-crypto, non-portable PRNG +/// +/// This is the "standard small" RNG, a generator with the following properties: +/// +/// - Non-[portable]: any future library version may replace the algorithm +/// and results may be platform-dependent. +/// (For a small portable generator, use the [rand_pcg] or [rand_xoshiro] crate.) +/// - Non-cryptographic: output is easy to predict (insecure) +/// - [Quality]: statistically good quality +/// - Fast: the RNG is fast for both bulk generation and single values, with +/// consistent cost of method calls +/// - Fast initialization +/// - Small state: little memory usage (current state size is 16-32 bytes +/// depending on platform) +/// +/// The current algorithm is +/// `Xoshiro256PlusPlus` on 64-bit platforms and `Xoshiro128PlusPlus` on 32-bit +/// platforms. Both are also implemented by the [rand_xoshiro] crate. +/// +/// ## Seeding (construction) +/// +/// This generator implements the [`SeedableRng`] trait. All methods are +/// suitable for seeding, but note that, even with a fixed seed, output is not +/// [portable]. Some suggestions: +/// +/// 1. To automatically seed with a unique seed, use [`SeedableRng::from_rng`]: +/// ``` +/// use rand::SeedableRng; +/// use rand::rngs::SmallRng; +/// let rng = SmallRng::from_rng(&mut rand::rng()); +/// # let _: SmallRng = rng; +/// ``` +/// or [`SeedableRng::from_os_rng`]: +/// ``` +/// # use rand::SeedableRng; +/// # use rand::rngs::SmallRng; +/// let rng = SmallRng::from_os_rng(); +/// # let _: SmallRng = rng; +/// ``` +/// 2. To use a deterministic integral seed, use `seed_from_u64`. This uses a +/// hash function internally to yield a (typically) good seed from any +/// input. +/// ``` +/// # use rand::{SeedableRng, rngs::SmallRng}; +/// let rng = SmallRng::seed_from_u64(1); +/// # let _: SmallRng = rng; +/// ``` +/// 3. To seed deterministically from text or other input, use [`rand_seeder`]. +/// +/// See also [Seeding RNGs] in the book. +/// +/// ## Generation +/// +/// The generators implements [`RngCore`] and thus also [`Rng`][crate::Rng]. +/// See also the [Random Values] chapter in the book. +/// +/// [portable]: https://rust-random.github.io/book/crate-reprod.html +/// [Seeding RNGs]: https://rust-random.github.io/book/guide-seeding.html +/// [Random Values]: https://rust-random.github.io/book/guide-values.html +/// [Quality]: https://rust-random.github.io/book/guide-rngs.html#quality +/// [`StdRng`]: crate::rngs::StdRng +/// [rand_pcg]: https://crates.io/crates/rand_pcg +/// [rand_xoshiro]: https://crates.io/crates/rand_xoshiro +/// [`rand_chacha::ChaCha8Rng`]: https://docs.rs/rand_chacha/latest/rand_chacha/struct.ChaCha8Rng.html +/// [`rand_seeder`]: https://docs.rs/rand_seeder/latest/rand_seeder/ +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SmallRng(Rng); + +impl SeedableRng for SmallRng { + // Fix to 256 bits. Changing this is a breaking change! + type Seed = [u8; 32]; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + // This is for compatibility with 32-bit platforms where Rng::Seed has a different seed size + // With MSRV >= 1.77: let seed = *seed.first_chunk().unwrap() + const LEN: usize = core::mem::size_of::<::Seed>(); + let seed = (&seed[..LEN]).try_into().unwrap(); + SmallRng(Rng::from_seed(seed)) + } + + #[inline(always)] + fn seed_from_u64(state: u64) -> Self { + SmallRng(Rng::seed_from_u64(state)) + } +} + +impl RngCore for SmallRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/std.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The standard RNG + +use rand_core::{CryptoRng, RngCore, SeedableRng}; + +#[cfg(any(test, feature = "os_rng"))] +pub(crate) use rand_chacha::ChaCha12Core as Core; + +use rand_chacha::ChaCha12Rng as Rng; + +/// A strong, fast (amortized), non-portable RNG +/// +/// This is the "standard" RNG, a generator with the following properties: +/// +/// - Non-[portable]: any future library version may replace the algorithm +/// and results may be platform-dependent. +/// (For a portable version, use the [rand_chacha] crate directly.) +/// - [CSPRNG]: statistically good quality of randomness and [unpredictable] +/// - Fast ([amortized](https://en.wikipedia.org/wiki/Amortized_analysis)): +/// the RNG is fast for bulk generation, but the cost of method calls is not +/// consistent due to usage of an output buffer. +/// +/// The current algorithm used is the ChaCha block cipher with 12 rounds. Please +/// see this relevant [rand issue] for the discussion. This may change as new +/// evidence of cipher security and performance becomes available. +/// +/// ## Seeding (construction) +/// +/// This generator implements the [`SeedableRng`] trait. Any method may be used, +/// but note that `seed_from_u64` is not suitable for usage where security is +/// important. Also note that, even with a fixed seed, output is not [portable]. +/// +/// Using a fresh seed **direct from the OS** is the most secure option: +/// ``` +/// # use rand::{SeedableRng, rngs::StdRng}; +/// let rng = StdRng::from_os_rng(); +/// # let _: StdRng = rng; +/// ``` +/// +/// Seeding via [`rand::rng()`](crate::rng()) may be faster: +/// ``` +/// # use rand::{SeedableRng, rngs::StdRng}; +/// let rng = StdRng::from_rng(&mut rand::rng()); +/// # let _: StdRng = rng; +/// ``` +/// +/// Any [`SeedableRng`] method may be used, but note that `seed_from_u64` is not +/// suitable where security is required. See also [Seeding RNGs] in the book. +/// +/// ## Generation +/// +/// The generators implements [`RngCore`] and thus also [`Rng`][crate::Rng]. +/// See also the [Random Values] chapter in the book. +/// +/// [portable]: https://rust-random.github.io/book/crate-reprod.html +/// [Seeding RNGs]: https://rust-random.github.io/book/guide-seeding.html +/// [unpredictable]: https://rust-random.github.io/book/guide-rngs.html#security +/// [Random Values]: https://rust-random.github.io/book/guide-values.html +/// [CSPRNG]: https://rust-random.github.io/book/guide-gen.html#cryptographically-secure-pseudo-random-number-generator +/// [rand_chacha]: https://crates.io/crates/rand_chacha +/// [rand issue]: https://github.com/rust-random/rand/issues/932 +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StdRng(Rng); + +impl RngCore for StdRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dst: &mut [u8]) { + self.0.fill_bytes(dst) + } +} + +impl SeedableRng for StdRng { + // Fix to 256 bits. Changing this is a breaking change! + type Seed = [u8; 32]; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + StdRng(Rng::from_seed(seed)) + } +} + +impl CryptoRng for StdRng {} + +#[cfg(test)] +mod test { + use crate::rngs::StdRng; + use crate::{RngCore, SeedableRng}; + + #[test] + fn test_stdrng_construction() { + // Test value-stability of StdRng. This is expected to break any time + // the algorithm is changed. + #[rustfmt::skip] + let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; + + let target = [10719222850664546238, 14064965282130556830]; + + let mut rng0 = StdRng::from_seed(seed); + let x0 = rng0.next_u64(); + + let mut rng1 = StdRng::from_rng(&mut rng0); + let x1 = rng1.next_u64(); + + assert_eq!([x0, x1], target); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/thread.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/thread.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/thread.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/thread.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Thread-local random number generator + +use core::cell::UnsafeCell; +use std::fmt; +use std::rc::Rc; +use std::thread_local; + +use rand_core::{CryptoRng, RngCore}; + +use super::std::Core; +use crate::rngs::OsRng; +use crate::rngs::ReseedingRng; + +// Rationale for using `UnsafeCell` in `ThreadRng`: +// +// Previously we used a `RefCell`, with an overhead of ~15%. There will only +// ever be one mutable reference to the interior of the `UnsafeCell`, because +// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a +// single thread (which is the definition of `ThreadRng`), there will only ever +// be one of these methods active at a time. +// +// A possible scenario where there could be multiple mutable references is if +// `ThreadRng` is used inside `next_u32` and co. But the implementation is +// completely under our control. We just have to ensure none of them use +// `ThreadRng` internally, which is nonsensical anyway. We should also never run +// `ThreadRng` in destructors of its implementation, which is also nonsensical. + +// Number of generated bytes after which to reseed `ThreadRng`. +// According to benchmarks, reseeding has a noticeable impact with thresholds +// of 32 kB and less. We choose 64 kB to avoid significant overhead. +const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64; + +/// A reference to the thread-local generator +/// +/// This type is a reference to a lazily-initialized thread-local generator. +/// An instance can be obtained via [`rand::rng()`][crate::rng()] or via +/// [`ThreadRng::default()`]. +/// The handle cannot be passed between threads (is not `Send` or `Sync`). +/// +/// # Security +/// +/// Security must be considered relative to a threat model and validation +/// requirements. The Rand project can provide no guarantee of fitness for +/// purpose. The design criteria for `ThreadRng` are as follows: +/// +/// - Automatic seeding via [`OsRng`] and periodically thereafter (see +/// ([`ReseedingRng`] documentation). Limitation: there is no automatic +/// reseeding on process fork (see [below](#fork)). +/// - A rigorusly analyzed, unpredictable (cryptographic) pseudo-random generator +/// (see [the book on security](https://rust-random.github.io/book/guide-rngs.html#security)). +/// The currently selected algorithm is ChaCha (12-rounds). +/// See also [`StdRng`] documentation. +/// - Not to leak internal state through [`Debug`] or serialization +/// implementations. +/// - No further protections exist to in-memory state. In particular, the +/// implementation is not required to zero memory on exit (of the process or +/// thread). (This may change in the future.) +/// - Be fast enough for general-purpose usage. Note in particular that +/// `ThreadRng` is designed to be a "fast, reasonably secure generator" +/// (where "reasonably secure" implies the above criteria). +/// +/// We leave it to the user to determine whether this generator meets their +/// security requirements. For an alternative, see [`OsRng`]. +/// +/// # Fork +/// +/// `ThreadRng` is not automatically reseeded on fork. It is recommended to +/// explicitly call [`ThreadRng::reseed`] immediately after a fork, for example: +/// ```ignore +/// fn do_fork() { +/// let pid = unsafe { libc::fork() }; +/// if pid == 0 { +/// // Reseed ThreadRng in child processes: +/// rand::rng().reseed(); +/// } +/// } +/// ``` +/// +/// Methods on `ThreadRng` are not reentrant-safe and thus should not be called +/// from an interrupt (e.g. a fork handler) unless it can be guaranteed that no +/// other method on the same `ThreadRng` is currently executing. +/// +/// [`ReseedingRng`]: crate::rngs::ReseedingRng +/// [`StdRng`]: crate::rngs::StdRng +#[derive(Clone)] +pub struct ThreadRng { + // Rc is explicitly !Send and !Sync + rng: Rc>>, +} + +impl ThreadRng { + /// Immediately reseed the generator + /// + /// This discards any remaining random data in the cache. + pub fn reseed(&mut self) -> Result<(), rand_core::OsError> { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.reseed() + } +} + +/// Debug implementation does not leak internal state +impl fmt::Debug for ThreadRng { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "ThreadRng {{ .. }}") + } +} + +thread_local!( + // We require Rc<..> to avoid premature freeing when ThreadRng is used + // within thread-local destructors. See #968. + static THREAD_RNG_KEY: Rc>> = { + let rng = ReseedingRng::new(THREAD_RNG_RESEED_THRESHOLD, + OsRng).unwrap_or_else(|err| + panic!("could not initialize ThreadRng: {}", err)); + Rc::new(UnsafeCell::new(rng)) + } +); + +/// Access a fast, pre-initialized generator +/// +/// This is a handle to the local [`ThreadRng`]. +/// +/// See also [`crate::rngs`] for alternatives. +/// +/// # Example +/// +/// ``` +/// use rand::prelude::*; +/// +/// # fn main() { +/// +/// let mut numbers = [1, 2, 3, 4, 5]; +/// numbers.shuffle(&mut rand::rng()); +/// println!("Numbers: {numbers:?}"); +/// +/// // Using a local binding avoids an initialization-check on each usage: +/// let mut rng = rand::rng(); +/// +/// println!("True or false: {}", rng.random::()); +/// println!("A simulated die roll: {}", rng.random_range(1..=6)); +/// # } +/// ``` +/// +/// # Security +/// +/// Refer to [`ThreadRng#Security`]. +pub fn rng() -> ThreadRng { + let rng = THREAD_RNG_KEY.with(|t| t.clone()); + ThreadRng { rng } +} + +impl Default for ThreadRng { + fn default() -> ThreadRng { + rng() + } +} + +impl RngCore for ThreadRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.fill_bytes(dest) + } +} + +impl CryptoRng for ThreadRng {} + +#[cfg(test)] +mod test { + #[test] + fn test_thread_rng() { + use crate::Rng; + let mut r = crate::rng(); + r.random::(); + assert_eq!(r.random_range(0..1), 0); + } + + #[test] + fn test_debug_output() { + // We don't care about the exact output here, but it must not include + // private CSPRNG state or the cache stored by BlockRng! + assert_eq!(std::format!("{:?}", crate::rng()), "ThreadRng { .. }"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/xoshiro128plusplus.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro128plusplus.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/xoshiro128plusplus.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro128plusplus.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; +use rand_core::le::read_u32_into; +use rand_core::{RngCore, SeedableRng}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A xoshiro128++ random number generator. +/// +/// The xoshiro128++ algorithm is not suitable for cryptographic purposes, but +/// is very fast and has excellent statistical properties. +/// +/// The algorithm used here is translated from [the `xoshiro128plusplus.c` +/// reference source code](http://xoshiro.di.unimi.it/xoshiro128plusplus.c) by +/// David Blackman and Sebastiano Vigna. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Xoshiro128PlusPlus { + s: [u32; 4], +} + +impl SeedableRng for Xoshiro128PlusPlus { + type Seed = [u8; 16]; + + /// Create a new `Xoshiro128PlusPlus`. If `seed` is entirely 0, it will be + /// mapped to a different seed. + #[inline] + fn from_seed(seed: [u8; 16]) -> Xoshiro128PlusPlus { + let mut state = [0; 4]; + read_u32_into(&seed, &mut state); + // Check for zero on aligned integers for better code generation. + // Furtermore, seed_from_u64(0) will expand to a constant when optimized. + if state.iter().all(|&x| x == 0) { + return Self::seed_from_u64(0); + } + Xoshiro128PlusPlus { s: state } + } + + /// Create a new `Xoshiro128PlusPlus` from a `u64` seed. + /// + /// This uses the SplitMix64 generator internally. + #[inline] + fn seed_from_u64(mut state: u64) -> Self { + const PHI: u64 = 0x9e3779b97f4a7c15; + let mut s = [0; 4]; + for i in s.chunks_exact_mut(2) { + state = state.wrapping_add(PHI); + let mut z = state; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); + z = z ^ (z >> 31); + i[0] = z as u32; + i[1] = (z >> 32) as u32; + } + // By using a non-zero PHI we are guaranteed to generate a non-zero state + // Thus preventing a recursion between from_seed and seed_from_u64. + debug_assert_ne!(s, [0; 4]); + Xoshiro128PlusPlus { s } + } +} + +impl RngCore for Xoshiro128PlusPlus { + #[inline] + fn next_u32(&mut self) -> u32 { + let res = self.s[0] + .wrapping_add(self.s[3]) + .rotate_left(7) + .wrapping_add(self.s[0]); + + let t = self.s[1] << 9; + + self.s[2] ^= self.s[0]; + self.s[3] ^= self.s[1]; + self.s[1] ^= self.s[2]; + self.s[0] ^= self.s[3]; + + self.s[2] ^= t; + + self.s[3] = self.s[3].rotate_left(11); + + res + } + + #[inline] + fn next_u64(&mut self) -> u64 { + next_u64_via_u32(self) + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + fill_bytes_via_next(self, dst) + } +} + +#[cfg(test)] +mod tests { + use super::Xoshiro128PlusPlus; + use rand_core::{RngCore, SeedableRng}; + + #[test] + fn reference() { + let mut rng = + Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); + // These values were produced with the reference implementation: + // http://xoshiro.di.unimi.it/xoshiro128plusplus.c + let expected = [ + 641, 1573767, 3222811527, 3517856514, 836907274, 4247214768, 3867114732, 1355841295, + 495546011, 621204420, + ]; + for &e in &expected { + assert_eq!(rng.next_u32(), e); + } + } + + #[test] + fn stable_seed_from_u64_and_from_seed() { + // We don't guarantee value-stability for SmallRng but this + // could influence keeping stability whenever possible (e.g. after optimizations). + let mut rng = Xoshiro128PlusPlus::seed_from_u64(0); + // from_seed([0; 16]) should produce the same state as seed_from_u64(0). + let mut rng_from_seed_0 = Xoshiro128PlusPlus::from_seed([0; 16]); + let expected = [ + 1179900579, 1938959192, 3089844957, 3657088315, 1015453891, 479942911, 3433842246, + 669252886, 3985671746, 2737205563, + ]; + for &e in &expected { + assert_eq!(rng.next_u32(), e); + assert_eq!(rng_from_seed_0.next_u32(), e); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/xoshiro256plusplus.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro256plusplus.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/rngs/xoshiro256plusplus.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/rngs/xoshiro256plusplus.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,158 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rand_core::impls::fill_bytes_via_next; +use rand_core::le::read_u64_into; +use rand_core::{RngCore, SeedableRng}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A xoshiro256++ random number generator. +/// +/// The xoshiro256++ algorithm is not suitable for cryptographic purposes, but +/// is very fast and has excellent statistical properties. +/// +/// The algorithm used here is translated from [the `xoshiro256plusplus.c` +/// reference source code](http://xoshiro.di.unimi.it/xoshiro256plusplus.c) by +/// David Blackman and Sebastiano Vigna. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Xoshiro256PlusPlus { + s: [u64; 4], +} + +impl SeedableRng for Xoshiro256PlusPlus { + type Seed = [u8; 32]; + + /// Create a new `Xoshiro256PlusPlus`. If `seed` is entirely 0, it will be + /// mapped to a different seed. + #[inline] + fn from_seed(seed: [u8; 32]) -> Xoshiro256PlusPlus { + let mut state = [0; 4]; + read_u64_into(&seed, &mut state); + // Check for zero on aligned integers for better code generation. + // Furtermore, seed_from_u64(0) will expand to a constant when optimized. + if state.iter().all(|&x| x == 0) { + return Self::seed_from_u64(0); + } + Xoshiro256PlusPlus { s: state } + } + + /// Create a new `Xoshiro256PlusPlus` from a `u64` seed. + /// + /// This uses the SplitMix64 generator internally. + #[inline] + fn seed_from_u64(mut state: u64) -> Self { + const PHI: u64 = 0x9e3779b97f4a7c15; + let mut s = [0; 4]; + for i in s.iter_mut() { + state = state.wrapping_add(PHI); + let mut z = state; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); + z = z ^ (z >> 31); + *i = z; + } + // By using a non-zero PHI we are guaranteed to generate a non-zero state + // Thus preventing a recursion between from_seed and seed_from_u64. + debug_assert_ne!(s, [0; 4]); + Xoshiro256PlusPlus { s } + } +} + +impl RngCore for Xoshiro256PlusPlus { + #[inline] + fn next_u32(&mut self) -> u32 { + // The lowest bits have some linear dependencies, so we use the + // upper bits instead. + let val = self.next_u64(); + (val >> 32) as u32 + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let res = self.s[0] + .wrapping_add(self.s[3]) + .rotate_left(23) + .wrapping_add(self.s[0]); + + let t = self.s[1] << 17; + + self.s[2] ^= self.s[0]; + self.s[3] ^= self.s[1]; + self.s[1] ^= self.s[2]; + self.s[0] ^= self.s[3]; + + self.s[2] ^= t; + + self.s[3] = self.s[3].rotate_left(45); + + res + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + fill_bytes_via_next(self, dst) + } +} + +#[cfg(test)] +mod tests { + use super::Xoshiro256PlusPlus; + use rand_core::{RngCore, SeedableRng}; + + #[test] + fn reference() { + let mut rng = Xoshiro256PlusPlus::from_seed([ + 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, + ]); + // These values were produced with the reference implementation: + // http://xoshiro.di.unimi.it/xoshiro256plusplus.c + let expected = [ + 41943041, + 58720359, + 3588806011781223, + 3591011842654386, + 9228616714210784205, + 9973669472204895162, + 14011001112246962877, + 12406186145184390807, + 15849039046786891736, + 10450023813501588000, + ]; + for &e in &expected { + assert_eq!(rng.next_u64(), e); + } + } + + #[test] + fn stable_seed_from_u64_and_from_seed() { + // We don't guarantee value-stability for SmallRng but this + // could influence keeping stability whenever possible (e.g. after optimizations). + let mut rng = Xoshiro256PlusPlus::seed_from_u64(0); + // from_seed([0; 32]) should produce the same state as seed_from_u64(0). + let mut rng_from_seed_0 = Xoshiro256PlusPlus::from_seed([0; 32]); + let expected = [ + 5987356902031041503, + 7051070477665621255, + 6633766593972829180, + 211316841551650330, + 9136120204379184874, + 379361710973160858, + 15813423377499357806, + 15596884590815070553, + 5439680534584881407, + 1369371744833522710, + ]; + for &e in &expected { + assert_eq!(rng.next_u64(), e); + assert_eq!(rng_from_seed_0.next_u64(), e); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/coin_flipper.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/coin_flipper.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/coin_flipper.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/coin_flipper.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,160 @@ +// Copyright 2018-2023 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::RngCore; + +pub(crate) struct CoinFlipper { + pub rng: R, + chunk: u32, // TODO(opt): this should depend on RNG word size + chunk_remaining: u32, +} + +impl CoinFlipper { + pub fn new(rng: R) -> Self { + Self { + rng, + chunk: 0, + chunk_remaining: 0, + } + } + + #[inline] + /// Returns true with a probability of 1 / d + /// Uses an expected two bits of randomness + /// Panics if d == 0 + pub fn random_ratio_one_over(&mut self, d: usize) -> bool { + debug_assert_ne!(d, 0); + // This uses the same logic as `random_ratio` but is optimized for the case that + // the starting numerator is one (which it always is for `Sequence::Choose()`) + + // In this case (but not `random_ratio`), this way of calculating c is always accurate + let c = (usize::BITS - 1 - d.leading_zeros()).min(32); + + if self.flip_c_heads(c) { + let numerator = 1 << c; + self.random_ratio(numerator, d) + } else { + false + } + } + + #[inline] + /// Returns true with a probability of n / d + /// Uses an expected two bits of randomness + fn random_ratio(&mut self, mut n: usize, d: usize) -> bool { + // Explanation: + // We are trying to return true with a probability of n / d + // If n >= d, we can just return true + // Otherwise there are two possibilities 2n < d and 2n >= d + // In either case we flip a coin. + // If 2n < d + // If it comes up tails, return false + // If it comes up heads, double n and start again + // This is fair because (0.5 * 0) + (0.5 * 2n / d) = n / d and 2n is less than d + // (if 2n was greater than d we would effectively round it down to 1 + // by returning true) + // If 2n >= d + // If it comes up tails, set n to 2n - d and start again + // If it comes up heads, return true + // This is fair because (0.5 * 1) + (0.5 * (2n - d) / d) = n / d + // Note that if 2n = d and the coin comes up tails, n will be set to 0 + // before restarting which is equivalent to returning false. + + // As a performance optimization we can flip multiple coins at once + // This is efficient because we can use the `lzcnt` intrinsic + // We can check up to 32 flips at once but we only receive one bit of information + // - all heads or at least one tail. + + // Let c be the number of coins to flip. 1 <= c <= 32 + // If 2n < d, n * 2^c < d + // If the result is all heads, then set n to n * 2^c + // If there was at least one tail, return false + // If 2n >= d, the order of results matters so we flip one coin at a time so c = 1 + // Ideally, c will be as high as possible within these constraints + + while n < d { + // Find a good value for c by counting leading zeros + // This will either give the highest possible c, or 1 less than that + let c = n + .leading_zeros() + .saturating_sub(d.leading_zeros() + 1) + .clamp(1, 32); + + if self.flip_c_heads(c) { + // All heads + // Set n to n * 2^c + // If 2n >= d, the while loop will exit and we will return `true` + // If n * 2^c > `usize::MAX` we always return `true` anyway + n = n.saturating_mul(2_usize.pow(c)); + } else { + // At least one tail + if c == 1 { + // Calculate 2n - d. + // We need to use wrapping as 2n might be greater than `usize::MAX` + let next_n = n.wrapping_add(n).wrapping_sub(d); + if next_n == 0 || next_n > n { + // This will happen if 2n < d + return false; + } + n = next_n; + } else { + // c > 1 so 2n < d so we can return false + return false; + } + } + } + true + } + + /// If the next `c` bits of randomness all represent heads, consume them, return true + /// Otherwise return false and consume the number of heads plus one. + /// Generates new bits of randomness when necessary (in 32 bit chunks) + /// Has a 1 in 2 to the `c` chance of returning true + /// `c` must be less than or equal to 32 + fn flip_c_heads(&mut self, mut c: u32) -> bool { + debug_assert!(c <= 32); + // Note that zeros on the left of the chunk represent heads. + // It needs to be this way round because zeros are filled in when left shifting + loop { + let zeros = self.chunk.leading_zeros(); + + if zeros < c { + // The happy path - we found a 1 and can return false + // Note that because a 1 bit was detected, + // We cannot have run out of random bits so we don't need to check + + // First consume all of the bits read + // Using shl seems to give worse performance for size-hinted iterators + self.chunk = self.chunk.wrapping_shl(zeros + 1); + + self.chunk_remaining = self.chunk_remaining.saturating_sub(zeros + 1); + return false; + } else { + // The number of zeros is larger than `c` + // There are two possibilities + if let Some(new_remaining) = self.chunk_remaining.checked_sub(c) { + // Those zeroes were all part of our random chunk, + // throw away `c` bits of randomness and return true + self.chunk_remaining = new_remaining; + self.chunk <<= c; + return true; + } else { + // Some of those zeroes were part of the random chunk + // and some were part of the space behind it + // We need to take into account only the zeroes that were random + c -= self.chunk_remaining; + + // Generate a new chunk + self.chunk = self.rng.next_u32(); + self.chunk_remaining = 32; + // Go back to start of loop + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/increasing_uniform.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/increasing_uniform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/increasing_uniform.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/increasing_uniform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,108 @@ +// Copyright 2018-2023 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::{Rng, RngCore}; + +/// Similar to a Uniform distribution, +/// but after returning a number in the range [0,n], n is increased by 1. +pub(crate) struct IncreasingUniform { + pub rng: R, + n: u32, + // Chunk is a random number in [0, (n + 1) * (n + 2) *..* (n + chunk_remaining) ) + chunk: u32, + chunk_remaining: u8, +} + +impl IncreasingUniform { + /// Create a dice roller. + /// The next item returned will be a random number in the range [0,n] + pub fn new(rng: R, n: u32) -> Self { + // If n = 0, the first number returned will always be 0 + // so we don't need to generate a random number + let chunk_remaining = if n == 0 { 1 } else { 0 }; + Self { + rng, + n, + chunk: 0, + chunk_remaining, + } + } + + /// Returns a number in [0,n] and increments n by 1. + /// Generates new random bits as needed + /// Panics if `n >= u32::MAX` + #[inline] + pub fn next_index(&mut self) -> usize { + let next_n = self.n + 1; + + // There's room for further optimisation here: + // random_range uses rejection sampling (or other method; see #1196) to avoid bias. + // When the initial sample is biased for range 0..bound + // it may still be viable to use for a smaller bound + // (especially if small biases are considered acceptable). + + let next_chunk_remaining = self.chunk_remaining.checked_sub(1).unwrap_or_else(|| { + // If the chunk is empty, generate a new chunk + let (bound, remaining) = calculate_bound_u32(next_n); + // bound = (n + 1) * (n + 2) *..* (n + remaining) + self.chunk = self.rng.random_range(..bound); + // Chunk is a random number in + // [0, (n + 1) * (n + 2) *..* (n + remaining) ) + + remaining - 1 + }); + + let result = if next_chunk_remaining == 0 { + // `chunk` is a random number in the range [0..n+1) + // Because `chunk_remaining` is about to be set to zero + // we do not need to clear the chunk here + self.chunk as usize + } else { + // `chunk` is a random number in a range that is a multiple of n+1 + // so r will be a random number in [0..n+1) + let r = self.chunk % next_n; + self.chunk /= next_n; + r as usize + }; + + self.chunk_remaining = next_chunk_remaining; + self.n = next_n; + result + } +} + +#[inline] +/// Calculates `bound`, `count` such that bound (m)*(m+1)*..*(m + remaining - 1) +fn calculate_bound_u32(m: u32) -> (u32, u8) { + debug_assert!(m > 0); + #[inline] + const fn inner(m: u32) -> (u32, u8) { + let mut product = m; + let mut current = m + 1; + + loop { + if let Some(p) = u32::checked_mul(product, current) { + product = p; + current += 1; + } else { + // Count has a maximum value of 13 for when min is 1 or 2 + let count = (current - m) as u8; + return (product, count); + } + } + } + + const RESULT2: (u32, u8) = inner(2); + if m == 2 { + // Making this value a constant instead of recalculating it + // gives a significant (~50%) performance boost for small shuffles + return RESULT2; + } + + inner(m) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/index.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/index.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/index.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/index.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,696 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Low-level API for sampling indices +use alloc::vec::{self, Vec}; +use core::slice; +use core::{hash::Hash, ops::AddAssign}; +// BTreeMap is not as fast in tests, but better than nothing. +#[cfg(feature = "std")] +use super::WeightError; +use crate::distr::uniform::SampleUniform; +use crate::distr::{Distribution, Uniform}; +use crate::Rng; +#[cfg(not(feature = "std"))] +use alloc::collections::BTreeSet; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; +#[cfg(feature = "std")] +use std::collections::HashSet; + +#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] +compile_error!("unsupported pointer width"); + +/// A vector of indices. +/// +/// Multiple internal representations are possible. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum IndexVec { + #[doc(hidden)] + U32(Vec), + #[cfg(target_pointer_width = "64")] + #[doc(hidden)] + U64(Vec), +} + +impl IndexVec { + /// Returns the number of indices + #[inline] + pub fn len(&self) -> usize { + match self { + IndexVec::U32(v) => v.len(), + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => v.len(), + } + } + + /// Returns `true` if the length is 0. + #[inline] + pub fn is_empty(&self) -> bool { + match self { + IndexVec::U32(v) => v.is_empty(), + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => v.is_empty(), + } + } + + /// Return the value at the given `index`. + /// + /// (Note: we cannot implement [`std::ops::Index`] because of lifetime + /// restrictions.) + #[inline] + pub fn index(&self, index: usize) -> usize { + match self { + IndexVec::U32(v) => v[index] as usize, + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => v[index] as usize, + } + } + + /// Return result as a `Vec`. Conversion may or may not be trivial. + #[inline] + pub fn into_vec(self) -> Vec { + match self { + IndexVec::U32(v) => v.into_iter().map(|i| i as usize).collect(), + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => v.into_iter().map(|i| i as usize).collect(), + } + } + + /// Iterate over the indices as a sequence of `usize` values + #[inline] + pub fn iter(&self) -> IndexVecIter<'_> { + match self { + IndexVec::U32(v) => IndexVecIter::U32(v.iter()), + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => IndexVecIter::U64(v.iter()), + } + } +} + +impl IntoIterator for IndexVec { + type IntoIter = IndexVecIntoIter; + type Item = usize; + + /// Convert into an iterator over the indices as a sequence of `usize` values + #[inline] + fn into_iter(self) -> IndexVecIntoIter { + match self { + IndexVec::U32(v) => IndexVecIntoIter::U32(v.into_iter()), + #[cfg(target_pointer_width = "64")] + IndexVec::U64(v) => IndexVecIntoIter::U64(v.into_iter()), + } + } +} + +impl PartialEq for IndexVec { + fn eq(&self, other: &IndexVec) -> bool { + use self::IndexVec::*; + match (self, other) { + (U32(v1), U32(v2)) => v1 == v2, + #[cfg(target_pointer_width = "64")] + (U64(v1), U64(v2)) => v1 == v2, + #[cfg(target_pointer_width = "64")] + (U32(v1), U64(v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as u64 == *y)) + } + #[cfg(target_pointer_width = "64")] + (U64(v1), U32(v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as u64)) + } + } + } +} + +impl From> for IndexVec { + #[inline] + fn from(v: Vec) -> Self { + IndexVec::U32(v) + } +} + +#[cfg(target_pointer_width = "64")] +impl From> for IndexVec { + #[inline] + fn from(v: Vec) -> Self { + IndexVec::U64(v) + } +} + +/// Return type of `IndexVec::iter`. +#[derive(Debug)] +pub enum IndexVecIter<'a> { + #[doc(hidden)] + U32(slice::Iter<'a, u32>), + #[cfg(target_pointer_width = "64")] + #[doc(hidden)] + U64(slice::Iter<'a, u64>), +} + +impl Iterator for IndexVecIter<'_> { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + use self::IndexVecIter::*; + match self { + U32(iter) => iter.next().map(|i| *i as usize), + #[cfg(target_pointer_width = "64")] + U64(iter) => iter.next().map(|i| *i as usize), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + match self { + IndexVecIter::U32(v) => v.size_hint(), + #[cfg(target_pointer_width = "64")] + IndexVecIter::U64(v) => v.size_hint(), + } + } +} + +impl ExactSizeIterator for IndexVecIter<'_> {} + +/// Return type of `IndexVec::into_iter`. +#[derive(Clone, Debug)] +pub enum IndexVecIntoIter { + #[doc(hidden)] + U32(vec::IntoIter), + #[cfg(target_pointer_width = "64")] + #[doc(hidden)] + U64(vec::IntoIter), +} + +impl Iterator for IndexVecIntoIter { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + use self::IndexVecIntoIter::*; + match self { + U32(v) => v.next().map(|i| i as usize), + #[cfg(target_pointer_width = "64")] + U64(v) => v.next().map(|i| i as usize), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + use self::IndexVecIntoIter::*; + match self { + U32(v) => v.size_hint(), + #[cfg(target_pointer_width = "64")] + U64(v) => v.size_hint(), + } + } +} + +impl ExactSizeIterator for IndexVecIntoIter {} + +/// Randomly sample exactly `amount` distinct indices from `0..length`, and +/// return them in random order (fully shuffled). +/// +/// This method is used internally by the slice sampling methods, but it can +/// sometimes be useful to have the indices themselves so this is provided as +/// an alternative. +/// +/// The implementation used is not specified; we automatically select the +/// fastest available algorithm for the `length` and `amount` parameters +/// (based on detailed profiling on an Intel Haswell CPU). Roughly speaking, +/// complexity is `O(amount)`, except that when `amount` is small, performance +/// is closer to `O(amount^2)`, and when `length` is close to `amount` then +/// `O(length)`. +/// +/// Note that performance is significantly better over `u32` indices than over +/// `u64` indices. Because of this we hide the underlying type behind an +/// abstraction, `IndexVec`. +/// +/// If an allocation-free `no_std` function is required, it is suggested +/// to adapt the internal `sample_floyd` implementation. +/// +/// Panics if `amount > length`. +#[track_caller] +pub fn sample(rng: &mut R, length: usize, amount: usize) -> IndexVec +where + R: Rng + ?Sized, +{ + if amount > length { + panic!("`amount` of samples must be less than or equal to `length`"); + } + if length > (u32::MAX as usize) { + #[cfg(target_pointer_width = "32")] + unreachable!(); + + // We never want to use inplace here, but could use floyd's alg + // Lazy version: always use the cache alg. + #[cfg(target_pointer_width = "64")] + return sample_rejection(rng, length as u64, amount as u64); + } + let amount = amount as u32; + let length = length as u32; + + // Choice of algorithm here depends on both length and amount. See: + // https://github.com/rust-random/rand/pull/479 + // We do some calculations with f32. Accuracy is not very important. + + if amount < 163 { + const C: [[f32; 2]; 2] = [[1.6, 8.0 / 45.0], [10.0, 70.0 / 9.0]]; + let j = usize::from(length >= 500_000); + let amount_fp = amount as f32; + let m4 = C[0][j] * amount_fp; + // Short-cut: when amount < 12, floyd's is always faster + if amount > 11 && (length as f32) < (C[1][j] + m4) * amount_fp { + sample_inplace(rng, length, amount) + } else { + sample_floyd(rng, length, amount) + } + } else { + const C: [f32; 2] = [270.0, 330.0 / 9.0]; + let j = usize::from(length >= 500_000); + if (length as f32) < C[j] * (amount as f32) { + sample_inplace(rng, length, amount) + } else { + sample_rejection(rng, length, amount) + } + } +} + +/// Randomly sample `amount` distinct indices from `0..length` +/// +/// The result may contain less than `amount` indices if insufficient non-zero +/// weights are available. Results are returned in an arbitrary order (there is +/// no guarantee of shuffling or ordering). +/// +/// Function `weight` is called once for each index to provide weights. +/// +/// This method is used internally by the slice sampling methods, but it can +/// sometimes be useful to have the indices themselves so this is provided as +/// an alternative. +/// +/// Error cases: +/// - [`WeightError::InvalidWeight`] when a weight is not-a-number or negative. +/// +/// This implementation uses `O(length + amount)` space and `O(length)` time. +#[cfg(feature = "std")] +pub fn sample_weighted( + rng: &mut R, + length: usize, + weight: F, + amount: usize, +) -> Result +where + R: Rng + ?Sized, + F: Fn(usize) -> X, + X: Into, +{ + if length > (u32::MAX as usize) { + #[cfg(target_pointer_width = "32")] + unreachable!(); + + #[cfg(target_pointer_width = "64")] + { + let amount = amount as u64; + let length = length as u64; + sample_efraimidis_spirakis(rng, length, weight, amount) + } + } else { + assert!(amount <= u32::MAX as usize); + let amount = amount as u32; + let length = length as u32; + sample_efraimidis_spirakis(rng, length, weight, amount) + } +} + +/// Randomly sample `amount` distinct indices from `0..length` +/// +/// The result may contain less than `amount` indices if insufficient non-zero +/// weights are available. Results are returned in an arbitrary order (there is +/// no guarantee of shuffling or ordering). +/// +/// Function `weight` is called once for each index to provide weights. +/// +/// This implementation is based on the algorithm A-ExpJ as found in +/// [Efraimidis and Spirakis, 2005](https://doi.org/10.1016/j.ipl.2005.11.003). +/// It uses `O(length + amount)` space and `O(length)` time. +/// +/// Error cases: +/// - [`WeightError::InvalidWeight`] when a weight is not-a-number or negative. +#[cfg(feature = "std")] +fn sample_efraimidis_spirakis( + rng: &mut R, + length: N, + weight: F, + amount: N, +) -> Result +where + R: Rng + ?Sized, + F: Fn(usize) -> X, + X: Into, + N: UInt, + IndexVec: From>, +{ + use std::{cmp::Ordering, collections::BinaryHeap}; + + if amount == N::zero() { + return Ok(IndexVec::U32(Vec::new())); + } + + struct Element { + index: N, + key: f64, + } + + impl PartialOrd for Element { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl Ord for Element { + fn cmp(&self, other: &Self) -> Ordering { + // unwrap() should not panic since weights should not be NaN + // We reverse so that BinaryHeap::peek shows the smallest item + self.key.partial_cmp(&other.key).unwrap().reverse() + } + } + + impl PartialEq for Element { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } + } + + impl Eq for Element {} + + let mut candidates = BinaryHeap::with_capacity(amount.as_usize()); + let mut index = N::zero(); + while index < length && candidates.len() < amount.as_usize() { + let weight = weight(index.as_usize()).into(); + if weight > 0.0 { + // We use the log of the key used in A-ExpJ to improve precision + // for small weights: + let key = rng.random::().ln() / weight; + candidates.push(Element { index, key }); + } else if !(weight >= 0.0) { + return Err(WeightError::InvalidWeight); + } + + index += N::one(); + } + + if index < length { + let mut x = rng.random::().ln() / candidates.peek().unwrap().key; + while index < length { + let weight = weight(index.as_usize()).into(); + if weight > 0.0 { + x -= weight; + if x <= 0.0 { + let min_candidate = candidates.pop().unwrap(); + let t = (min_candidate.key * weight).exp(); + let key = rng.random_range(t..1.0).ln() / weight; + candidates.push(Element { index, key }); + + x = rng.random::().ln() / candidates.peek().unwrap().key; + } + } else if !(weight >= 0.0) { + return Err(WeightError::InvalidWeight); + } + + index += N::one(); + } + } + + Ok(IndexVec::from( + candidates.iter().map(|elt| elt.index).collect(), + )) +} + +/// Randomly sample exactly `amount` indices from `0..length`, using Floyd's +/// combination algorithm. +/// +/// The output values are fully shuffled. (Overhead is under 50%.) +/// +/// This implementation uses `O(amount)` memory and `O(amount^2)` time. +fn sample_floyd(rng: &mut R, length: u32, amount: u32) -> IndexVec +where + R: Rng + ?Sized, +{ + // Note that the values returned by `rng.random_range()` can be + // inferred from the returned vector by working backwards from + // the last entry. This bijection proves the algorithm fair. + debug_assert!(amount <= length); + let mut indices = Vec::with_capacity(amount as usize); + for j in length - amount..length { + let t = rng.random_range(..=j); + if let Some(pos) = indices.iter().position(|&x| x == t) { + indices[pos] = j; + } + indices.push(t); + } + IndexVec::from(indices) +} + +/// Randomly sample exactly `amount` indices from `0..length`, using an inplace +/// partial Fisher-Yates method. +/// Sample an amount of indices using an inplace partial fisher yates method. +/// +/// This allocates the entire `length` of indices and randomizes only the first `amount`. +/// It then truncates to `amount` and returns. +/// +/// This method is not appropriate for large `length` and potentially uses a lot +/// of memory; because of this we only implement for `u32` index (which improves +/// performance in all cases). +/// +/// Set-up is `O(length)` time and memory and shuffling is `O(amount)` time. +fn sample_inplace(rng: &mut R, length: u32, amount: u32) -> IndexVec +where + R: Rng + ?Sized, +{ + debug_assert!(amount <= length); + let mut indices: Vec = Vec::with_capacity(length as usize); + indices.extend(0..length); + for i in 0..amount { + let j: u32 = rng.random_range(i..length); + indices.swap(i as usize, j as usize); + } + indices.truncate(amount as usize); + debug_assert_eq!(indices.len(), amount as usize); + IndexVec::from(indices) +} + +trait UInt: Copy + PartialOrd + Ord + PartialEq + Eq + SampleUniform + Hash + AddAssign { + fn zero() -> Self; + #[cfg_attr(feature = "alloc", allow(dead_code))] + fn one() -> Self; + fn as_usize(self) -> usize; +} + +impl UInt for u32 { + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn one() -> Self { + 1 + } + + #[inline] + fn as_usize(self) -> usize { + self as usize + } +} + +#[cfg(target_pointer_width = "64")] +impl UInt for u64 { + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn one() -> Self { + 1 + } + + #[inline] + fn as_usize(self) -> usize { + self as usize + } +} + +/// Randomly sample exactly `amount` indices from `0..length`, using rejection +/// sampling. +/// +/// Since `amount <<< length` there is a low chance of a random sample in +/// `0..length` being a duplicate. We test for duplicates and resample where +/// necessary. The algorithm is `O(amount)` time and memory. +/// +/// This function is generic over X primarily so that results are value-stable +/// over 32-bit and 64-bit platforms. +fn sample_rejection(rng: &mut R, length: X, amount: X) -> IndexVec +where + R: Rng + ?Sized, + IndexVec: From>, +{ + debug_assert!(amount < length); + #[cfg(feature = "std")] + let mut cache = HashSet::with_capacity(amount.as_usize()); + #[cfg(not(feature = "std"))] + let mut cache = BTreeSet::new(); + let distr = Uniform::new(X::zero(), length).unwrap(); + let mut indices = Vec::with_capacity(amount.as_usize()); + for _ in 0..amount.as_usize() { + let mut pos = distr.sample(rng); + while !cache.insert(pos) { + pos = distr.sample(rng); + } + indices.push(pos); + } + + debug_assert_eq!(indices.len(), amount.as_usize()); + IndexVec::from(indices) +} + +#[cfg(test)] +mod test { + use super::*; + use alloc::vec; + + #[test] + #[cfg(feature = "serde")] + fn test_serialization_index_vec() { + let some_index_vec = IndexVec::from(vec![254_u32, 234, 2, 1]); + let de_some_index_vec: IndexVec = + bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); + assert_eq!(some_index_vec, de_some_index_vec); + } + + #[test] + fn test_sample_boundaries() { + let mut r = crate::test::rng(404); + + assert_eq!(sample_inplace(&mut r, 0, 0).len(), 0); + assert_eq!(sample_inplace(&mut r, 1, 0).len(), 0); + assert_eq!(sample_inplace(&mut r, 1, 1).into_vec(), vec![0]); + + assert_eq!(sample_rejection(&mut r, 1u32, 0).len(), 0); + + assert_eq!(sample_floyd(&mut r, 0, 0).len(), 0); + assert_eq!(sample_floyd(&mut r, 1, 0).len(), 0); + assert_eq!(sample_floyd(&mut r, 1, 1).into_vec(), vec![0]); + + // These algorithms should be fast with big numbers. Test average. + let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32).into_iter().sum(); + assert!(1 << 25 < sum && sum < (1 << 25) * 25); + + let sum: usize = sample_floyd(&mut r, 1 << 25, 10).into_iter().sum(); + assert!(1 << 25 < sum && sum < (1 << 25) * 25); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_sample_alg() { + let seed_rng = crate::test::rng; + + // We can't test which algorithm is used directly, but Floyd's alg + // should produce different results from the others. (Also, `inplace` + // and `cached` currently use different sizes thus produce different results.) + + // A small length and relatively large amount should use inplace + let (length, amount): (usize, usize) = (100, 50); + let v1 = sample(&mut seed_rng(420), length, amount); + let v2 = sample_inplace(&mut seed_rng(420), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + + // Test Floyd's alg does produce different results + let v3 = sample_floyd(&mut seed_rng(420), length as u32, amount as u32); + assert!(v1 != v3); + + // A large length and small amount should use Floyd + let (length, amount): (usize, usize) = (1 << 20, 50); + let v1 = sample(&mut seed_rng(421), length, amount); + let v2 = sample_floyd(&mut seed_rng(421), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + + // A large length and larger amount should use cache + let (length, amount): (usize, usize) = (1 << 20, 600); + let v1 = sample(&mut seed_rng(422), length, amount); + let v2 = sample_rejection(&mut seed_rng(422), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + } + + #[cfg(feature = "std")] + #[test] + fn test_sample_weighted() { + let seed_rng = crate::test::rng; + for &(amount, len) in &[(0, 10), (5, 10), (9, 10)] { + let v = sample_weighted(&mut seed_rng(423), len, |i| i as f64, amount).unwrap(); + match v { + IndexVec::U32(mut indices) => { + assert_eq!(indices.len(), amount); + indices.sort_unstable(); + indices.dedup(); + assert_eq!(indices.len(), amount); + for &i in &indices { + assert!((i as usize) < len); + } + } + #[cfg(target_pointer_width = "64")] + _ => panic!("expected `IndexVec::U32`"), + } + } + + let r = sample_weighted(&mut seed_rng(423), 10, |i| i as f64, 10); + assert_eq!(r.unwrap().len(), 9); + } + + #[test] + fn value_stability_sample() { + let do_test = |length, amount, values: &[u32]| { + let mut buf = [0u32; 8]; + let mut rng = crate::test::rng(410); + + let res = sample(&mut rng, length, amount); + let len = res.len().min(buf.len()); + for (x, y) in res.into_iter().zip(buf.iter_mut()) { + *y = x as u32; + } + assert_eq!( + &buf[0..len], + values, + "failed sampling {}, {}", + length, + amount + ); + }; + + do_test(10, 6, &[0, 9, 5, 4, 6, 8]); // floyd + do_test(25, 10, &[24, 20, 19, 9, 22, 16, 0, 14]); // floyd + do_test(300, 8, &[30, 283, 243, 150, 218, 240, 1, 189]); // floyd + do_test(300, 80, &[31, 289, 248, 154, 221, 243, 7, 192]); // inplace + do_test(300, 180, &[31, 289, 248, 154, 221, 243, 7, 192]); // inplace + + do_test( + 1_000_000, + 8, + &[103717, 963485, 826422, 509101, 736394, 807035, 5327, 632573], + ); // floyd + do_test( + 1_000_000, + 180, + &[103718, 963490, 826426, 509103, 736396, 807036, 5327, 632573], + ); // rejection + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/iterator.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/iterator.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/iterator.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/iterator.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,672 @@ +// Copyright 2018-2024 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! `IteratorRandom` + +use super::coin_flipper::CoinFlipper; +#[allow(unused)] +use super::IndexedRandom; +use crate::Rng; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +/// Extension trait on iterators, providing random sampling methods. +/// +/// This trait is implemented on all iterators `I` where `I: Iterator + Sized` +/// and provides methods for +/// choosing one or more elements. You must `use` this trait: +/// +/// ``` +/// use rand::seq::IteratorRandom; +/// +/// let faces = "😀😎😐😕😠😢"; +/// println!("I am {}!", faces.chars().choose(&mut rand::rng()).unwrap()); +/// ``` +/// Example output (non-deterministic): +/// ```none +/// I am 😀! +/// ``` +pub trait IteratorRandom: Iterator + Sized { + /// Uniformly sample one element + /// + /// Assuming that the [`Iterator::size_hint`] is correct, this method + /// returns one uniformly-sampled random element of the slice, or `None` + /// only if the slice is empty. Incorrect bounds on the `size_hint` may + /// cause this method to incorrectly return `None` if fewer elements than + /// the advertised `lower` bound are present and may prevent sampling of + /// elements beyond an advertised `upper` bound (i.e. incorrect `size_hint` + /// is memory-safe, but may result in unexpected `None` result and + /// non-uniform distribution). + /// + /// With an accurate [`Iterator::size_hint`] and where [`Iterator::nth`] is + /// a constant-time operation, this method can offer `O(1)` performance. + /// Where no size hint is + /// available, complexity is `O(n)` where `n` is the iterator length. + /// Partial hints (where `lower > 0`) also improve performance. + /// + /// Note further that [`Iterator::size_hint`] may affect the number of RNG + /// samples used as well as the result (while remaining uniform sampling). + /// Consider instead using [`IteratorRandom::choose_stable`] to avoid + /// [`Iterator`] combinators which only change size hints from affecting the + /// results. + /// + /// # Example + /// + /// ``` + /// use rand::seq::IteratorRandom; + /// + /// let words = "Mary had a little lamb".split(' '); + /// println!("{}", words.choose(&mut rand::rng()).unwrap()); + /// ``` + fn choose(mut self, rng: &mut R) -> Option + where + R: Rng + ?Sized, + { + let (mut lower, mut upper) = self.size_hint(); + let mut result = None; + + // Handling for this condition outside the loop allows the optimizer to eliminate the loop + // when the Iterator is an ExactSizeIterator. This has a large performance impact on e.g. + // seq_iter_choose_from_1000. + if upper == Some(lower) { + return match lower { + 0 => None, + 1 => self.next(), + _ => self.nth(rng.random_range(..lower)), + }; + } + + let mut coin_flipper = CoinFlipper::new(rng); + let mut consumed = 0; + + // Continue until the iterator is exhausted + loop { + if lower > 1 { + let ix = coin_flipper.rng.random_range(..lower + consumed); + let skip = if ix < lower { + result = self.nth(ix); + lower - (ix + 1) + } else { + lower + }; + if upper == Some(lower) { + return result; + } + consumed += lower; + if skip > 0 { + self.nth(skip - 1); + } + } else { + let elem = self.next(); + if elem.is_none() { + return result; + } + consumed += 1; + if coin_flipper.random_ratio_one_over(consumed) { + result = elem; + } + } + + let hint = self.size_hint(); + lower = hint.0; + upper = hint.1; + } + } + + /// Uniformly sample one element (stable) + /// + /// This method is very similar to [`choose`] except that the result + /// only depends on the length of the iterator and the values produced by + /// `rng`. Notably for any iterator of a given length this will make the + /// same requests to `rng` and if the same sequence of values are produced + /// the same index will be selected from `self`. This may be useful if you + /// need consistent results no matter what type of iterator you are working + /// with. If you do not need this stability prefer [`choose`]. + /// + /// Note that this method still uses [`Iterator::size_hint`] to skip + /// constructing elements where possible, however the selection and `rng` + /// calls are the same in the face of this optimization. If you want to + /// force every element to be created regardless call `.inspect(|e| ())`. + /// + /// [`choose`]: IteratorRandom::choose + // + // Clippy is wrong here: we need to iterate over all entries with the RNG to + // ensure that choosing is *stable*. + // "allow(unknown_lints)" can be removed when switching to at least + // rust-version 1.86.0, see: + // https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last + #[allow(unknown_lints)] + #[allow(clippy::double_ended_iterator_last)] + fn choose_stable(mut self, rng: &mut R) -> Option + where + R: Rng + ?Sized, + { + let mut consumed = 0; + let mut result = None; + let mut coin_flipper = CoinFlipper::new(rng); + + loop { + // Currently the only way to skip elements is `nth()`. So we need to + // store what index to access next here. + // This should be replaced by `advance_by()` once it is stable: + // https://github.com/rust-lang/rust/issues/77404 + let mut next = 0; + + let (lower, _) = self.size_hint(); + if lower >= 2 { + let highest_selected = (0..lower) + .filter(|ix| coin_flipper.random_ratio_one_over(consumed + ix + 1)) + .last(); + + consumed += lower; + next = lower; + + if let Some(ix) = highest_selected { + result = self.nth(ix); + next -= ix + 1; + debug_assert!(result.is_some(), "iterator shorter than size_hint().0"); + } + } + + let elem = self.nth(next); + if elem.is_none() { + return result; + } + + if coin_flipper.random_ratio_one_over(consumed + 1) { + result = elem; + } + consumed += 1; + } + } + + /// Uniformly sample `amount` distinct elements into a buffer + /// + /// Collects values at random from the iterator into a supplied buffer + /// until that buffer is filled. + /// + /// Although the elements are selected randomly, the order of elements in + /// the buffer is neither stable nor fully random. If random ordering is + /// desired, shuffle the result. + /// + /// Returns the number of elements added to the buffer. This equals the length + /// of the buffer unless the iterator contains insufficient elements, in which + /// case this equals the number of elements available. + /// + /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`IndexedRandom::choose_multiple`]. + fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize + where + R: Rng + ?Sized, + { + let amount = buf.len(); + let mut len = 0; + while len < amount { + if let Some(elem) = self.next() { + buf[len] = elem; + len += 1; + } else { + // Iterator exhausted; stop early + return len; + } + } + + // Continue, since the iterator was not exhausted + for (i, elem) in self.enumerate() { + let k = rng.random_range(..i + 1 + amount); + if let Some(slot) = buf.get_mut(k) { + *slot = elem; + } + } + len + } + + /// Uniformly sample `amount` distinct elements into a [`Vec`] + /// + /// This is equivalent to `choose_multiple_fill` except for the result type. + /// + /// Although the elements are selected randomly, the order of elements in + /// the buffer is neither stable nor fully random. If random ordering is + /// desired, shuffle the result. + /// + /// The length of the returned vector equals `amount` unless the iterator + /// contains insufficient elements, in which case it equals the number of + /// elements available. + /// + /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`IndexedRandom::choose_multiple`]. + #[cfg(feature = "alloc")] + fn choose_multiple(mut self, rng: &mut R, amount: usize) -> Vec + where + R: Rng + ?Sized, + { + let mut reservoir = Vec::with_capacity(amount); + reservoir.extend(self.by_ref().take(amount)); + + // Continue unless the iterator was exhausted + // + // note: this prevents iterators that "restart" from causing problems. + // If the iterator stops once, then so do we. + if reservoir.len() == amount { + for (i, elem) in self.enumerate() { + let k = rng.random_range(..i + 1 + amount); + if let Some(slot) = reservoir.get_mut(k) { + *slot = elem; + } + } + } else { + // Don't hang onto extra memory. There is a corner case where + // `amount` was much less than `self.len()`. + reservoir.shrink_to_fit(); + } + reservoir + } +} + +impl IteratorRandom for I where I: Iterator + Sized {} + +#[cfg(test)] +mod test { + use super::*; + #[cfg(all(feature = "alloc", not(feature = "std")))] + use alloc::vec::Vec; + + #[derive(Clone)] + struct UnhintedIterator { + iter: I, + } + impl Iterator for UnhintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.iter.next() + } + } + + #[derive(Clone)] + struct ChunkHintedIterator { + iter: I, + chunk_remaining: usize, + chunk_size: usize, + hint_total_size: bool, + } + impl Iterator for ChunkHintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + if self.chunk_remaining == 0 { + self.chunk_remaining = core::cmp::min(self.chunk_size, self.iter.len()); + } + self.chunk_remaining = self.chunk_remaining.saturating_sub(1); + + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + ( + self.chunk_remaining, + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) + } + } + + #[derive(Clone)] + struct WindowHintedIterator { + iter: I, + window_size: usize, + hint_total_size: bool, + } + impl Iterator for WindowHintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + ( + core::cmp::min(self.iter.len(), self.window_size), + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose() { + let r = &mut crate::test::rng(109); + fn test_iter + Clone>(r: &mut R, iter: Iter) { + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose(r).unwrap(); + chosen[picked] += 1; + } + for count in chosen.iter() { + // Samples should follow Binomial(1000, 1/9) + // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x + // Note: have seen 153, which is unlikely but not impossible. + assert!( + 72 < *count && *count < 154, + "count not close to 1000/9: {}", + count + ); + } + } + + test_iter(r, 0..9); + test_iter(r, [0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()); + #[cfg(feature = "alloc")] + test_iter(r, (0..9).collect::>().into_iter()); + test_iter(r, UnhintedIterator { iter: 0..9 }); + test_iter( + r, + ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }, + ); + test_iter( + r, + ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }, + ); + test_iter( + r, + WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }, + ); + test_iter( + r, + WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }, + ); + + assert_eq!((0..0).choose(r), None); + assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose_stable() { + let r = &mut crate::test::rng(109); + fn test_iter + Clone>(r: &mut R, iter: Iter) { + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose_stable(r).unwrap(); + chosen[picked] += 1; + } + for count in chosen.iter() { + // Samples should follow Binomial(1000, 1/9) + // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x + // Note: have seen 153, which is unlikely but not impossible. + assert!( + 72 < *count && *count < 154, + "count not close to 1000/9: {}", + count + ); + } + } + + test_iter(r, 0..9); + test_iter(r, [0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()); + #[cfg(feature = "alloc")] + test_iter(r, (0..9).collect::>().into_iter()); + test_iter(r, UnhintedIterator { iter: 0..9 }); + test_iter( + r, + ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }, + ); + test_iter( + r, + ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }, + ); + test_iter( + r, + WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }, + ); + test_iter( + r, + WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }, + ); + + assert_eq!((0..0).choose(r), None); + assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose_stable_stability() { + fn test_iter(iter: impl Iterator + Clone) -> [i32; 9] { + let r = &mut crate::test::rng(109); + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose_stable(r).unwrap(); + chosen[picked] += 1; + } + chosen + } + + let reference = test_iter(0..9); + assert_eq!( + test_iter([0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()), + reference + ); + + #[cfg(feature = "alloc")] + assert_eq!(test_iter((0..9).collect::>().into_iter()), reference); + assert_eq!(test_iter(UnhintedIterator { iter: 0..9 }), reference); + assert_eq!( + test_iter(ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }), + reference + ); + assert_eq!( + test_iter(ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }), + reference + ); + assert_eq!( + test_iter(WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }), + reference + ); + assert_eq!( + test_iter(WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }), + reference + ); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_sample_iter() { + let min_val = 1; + let max_val = 100; + + let mut r = crate::test::rng(401); + let vals = (min_val..max_val).collect::>(); + let small_sample = vals.iter().choose_multiple(&mut r, 5); + let large_sample = vals.iter().choose_multiple(&mut r, vals.len() + 5); + + assert_eq!(small_sample.len(), 5); + assert_eq!(large_sample.len(), vals.len()); + // no randomization happens when amount >= len + assert_eq!(large_sample, vals.iter().collect::>()); + + assert!(small_sample + .iter() + .all(|e| { **e >= min_val && **e <= max_val })); + } + + #[test] + fn value_stability_choose() { + fn choose>(iter: I) -> Option { + let mut rng = crate::test::rng(411); + iter.choose(&mut rng) + } + + assert_eq!(choose([].iter().cloned()), None); + assert_eq!(choose(0..100), Some(33)); + assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(27)); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: false, + }), + Some(91) + ); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: true, + }), + Some(91) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: false, + }), + Some(34) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: true, + }), + Some(34) + ); + } + + #[test] + fn value_stability_choose_stable() { + fn choose>(iter: I) -> Option { + let mut rng = crate::test::rng(411); + iter.choose_stable(&mut rng) + } + + assert_eq!(choose([].iter().cloned()), None); + assert_eq!(choose(0..100), Some(27)); + assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(27)); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: false, + }), + Some(27) + ); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: true, + }), + Some(27) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: false, + }), + Some(27) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: true, + }), + Some(27) + ); + } + + #[test] + fn value_stability_choose_multiple() { + fn do_test>(iter: I, v: &[u32]) { + let mut rng = crate::test::rng(412); + let mut buf = [0u32; 8]; + assert_eq!( + iter.clone().choose_multiple_fill(&mut rng, &mut buf), + v.len() + ); + assert_eq!(&buf[0..v.len()], v); + + #[cfg(feature = "alloc")] + { + let mut rng = crate::test::rng(412); + assert_eq!(iter.choose_multiple(&mut rng, v.len()), v); + } + } + + do_test(0..4, &[0, 1, 2, 3]); + do_test(0..8, &[0, 1, 2, 3, 4, 5, 6, 7]); + do_test(0..100, &[77, 95, 38, 23, 25, 8, 58, 40]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +// Copyright 2018-2023 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Sequence-related functionality +//! +//! This module provides: +//! +//! * [`IndexedRandom`] for sampling slices and other indexable lists +//! * [`IndexedMutRandom`] for sampling slices and other mutably indexable lists +//! * [`SliceRandom`] for mutating slices +//! * [`IteratorRandom`] for sampling iterators +//! * [`index::sample`] low-level API to choose multiple indices from +//! `0..length` +//! +//! Also see: +//! +//! * [`crate::distr::weighted::WeightedIndex`] distribution which provides +//! weighted index sampling. +//! +//! In order to make results reproducible across 32-64 bit architectures, all +//! `usize` indices are sampled as a `u32` where possible (also providing a +//! small performance boost in some cases). + +mod coin_flipper; +mod increasing_uniform; +mod iterator; +mod slice; + +#[cfg(feature = "alloc")] +#[path = "index.rs"] +mod index_; + +#[cfg(feature = "alloc")] +#[doc(no_inline)] +pub use crate::distr::weighted::Error as WeightError; +pub use iterator::IteratorRandom; +#[cfg(feature = "alloc")] +pub use slice::SliceChooseIter; +pub use slice::{IndexedMutRandom, IndexedRandom, SliceRandom}; + +/// Low-level API for sampling indices +pub mod index { + use crate::Rng; + + #[cfg(feature = "alloc")] + #[doc(inline)] + pub use super::index_::*; + + /// Randomly sample exactly `N` distinct indices from `0..len`, and + /// return them in random order (fully shuffled). + /// + /// This is implemented via Floyd's algorithm. Time complexity is `O(N^2)` + /// and memory complexity is `O(N)`. + /// + /// Returns `None` if (and only if) `N > len`. + pub fn sample_array(rng: &mut R, len: usize) -> Option<[usize; N]> + where + R: Rng + ?Sized, + { + if N > len { + return None; + } + + // Floyd's algorithm + let mut indices = [0; N]; + for (i, j) in (len - N..len).enumerate() { + let t = rng.random_range(..j + 1); + if let Some(pos) = indices[0..i].iter().position(|&x| x == t) { + indices[pos] = j; + } + indices[i] = t; + } + Some(indices) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/slice.rs clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/slice.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand/src/seq/slice.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand/src/seq/slice.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,770 @@ +// Copyright 2018-2023 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! `IndexedRandom`, `IndexedMutRandom`, `SliceRandom` + +use super::increasing_uniform::IncreasingUniform; +use super::index; +#[cfg(feature = "alloc")] +use crate::distr::uniform::{SampleBorrow, SampleUniform}; +#[cfg(feature = "alloc")] +use crate::distr::weighted::{Error as WeightError, Weight}; +use crate::Rng; +use core::ops::{Index, IndexMut}; + +/// Extension trait on indexable lists, providing random sampling methods. +/// +/// This trait is implemented on `[T]` slice types. Other types supporting +/// [`std::ops::Index`] may implement this (only [`Self::len`] must be +/// specified). +pub trait IndexedRandom: Index { + /// The length + fn len(&self) -> usize; + + /// True when the length is zero + #[inline] + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Uniformly sample one element + /// + /// Returns a reference to one uniformly-sampled random element of + /// the slice, or `None` if the slice is empty. + /// + /// For slices, complexity is `O(1)`. + /// + /// # Example + /// + /// ``` + /// use rand::seq::IndexedRandom; + /// + /// let choices = [1, 2, 4, 8, 16, 32]; + /// let mut rng = rand::rng(); + /// println!("{:?}", choices.choose(&mut rng)); + /// assert_eq!(choices[..0].choose(&mut rng), None); + /// ``` + fn choose(&self, rng: &mut R) -> Option<&Self::Output> + where + R: Rng + ?Sized, + { + if self.is_empty() { + None + } else { + Some(&self[rng.random_range(..self.len())]) + } + } + + /// Uniformly sample `amount` distinct elements from self + /// + /// Chooses `amount` elements from the slice at random, without repetition, + /// and in random order. The returned iterator is appropriate both for + /// collection into a `Vec` and filling an existing buffer (see example). + /// + /// In case this API is not sufficiently flexible, use [`index::sample`]. + /// + /// For slices, complexity is the same as [`index::sample`]. + /// + /// # Example + /// ``` + /// use rand::seq::IndexedRandom; + /// + /// let mut rng = &mut rand::rng(); + /// let sample = "Hello, audience!".as_bytes(); + /// + /// // collect the results into a vector: + /// let v: Vec = sample.choose_multiple(&mut rng, 3).cloned().collect(); + /// + /// // store in a buffer: + /// let mut buf = [0u8; 5]; + /// for (b, slot) in sample.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) { + /// *slot = *b; + /// } + /// ``` + #[cfg(feature = "alloc")] + fn choose_multiple( + &self, + rng: &mut R, + amount: usize, + ) -> SliceChooseIter<'_, Self, Self::Output> + where + Self::Output: Sized, + R: Rng + ?Sized, + { + let amount = core::cmp::min(amount, self.len()); + SliceChooseIter { + slice: self, + _phantom: Default::default(), + indices: index::sample(rng, self.len(), amount).into_iter(), + } + } + + /// Uniformly sample a fixed-size array of distinct elements from self + /// + /// Chooses `N` elements from the slice at random, without repetition, + /// and in random order. + /// + /// For slices, complexity is the same as [`index::sample_array`]. + /// + /// # Example + /// ``` + /// use rand::seq::IndexedRandom; + /// + /// let mut rng = &mut rand::rng(); + /// let sample = "Hello, audience!".as_bytes(); + /// + /// let a: [u8; 3] = sample.choose_multiple_array(&mut rng).unwrap(); + /// ``` + fn choose_multiple_array(&self, rng: &mut R) -> Option<[Self::Output; N]> + where + Self::Output: Clone + Sized, + R: Rng + ?Sized, + { + let indices = index::sample_array(rng, self.len())?; + Some(indices.map(|index| self[index].clone())) + } + + /// Biased sampling for one element + /// + /// Returns a reference to one element of the slice, sampled according + /// to the provided weights. Returns `None` only if the slice is empty. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// For more information about the underlying algorithm, + /// see the [`WeightedIndex`] distribution. + /// + /// See also [`choose_weighted_mut`]. + /// + /// # Example + /// + /// ``` + /// use rand::prelude::*; + /// + /// let choices = [('a', 2), ('b', 1), ('c', 1), ('d', 0)]; + /// let mut rng = rand::rng(); + /// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c', + /// // and 'd' will never be printed + /// println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0); + /// ``` + /// [`choose`]: IndexedRandom::choose + /// [`choose_weighted_mut`]: IndexedMutRandom::choose_weighted_mut + /// [`WeightedIndex`]: crate::distr::weighted::WeightedIndex + #[cfg(feature = "alloc")] + fn choose_weighted( + &self, + rng: &mut R, + weight: F, + ) -> Result<&Self::Output, WeightError> + where + R: Rng + ?Sized, + F: Fn(&Self::Output) -> B, + B: SampleBorrow, + X: SampleUniform + Weight + PartialOrd, + { + use crate::distr::{weighted::WeightedIndex, Distribution}; + let distr = WeightedIndex::new((0..self.len()).map(|idx| weight(&self[idx])))?; + Ok(&self[distr.sample(rng)]) + } + + /// Biased sampling of `amount` distinct elements + /// + /// Similar to [`choose_multiple`], but where the likelihood of each + /// element's inclusion in the output may be specified. Zero-weighted + /// elements are never returned; the result may therefore contain fewer + /// elements than `amount` even when `self.len() >= amount`. The elements + /// are returned in an arbitrary, unspecified order. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// This implementation uses `O(length + amount)` space and `O(length)` time. + /// See [`index::sample_weighted`] for details. + /// + /// # Example + /// + /// ``` + /// use rand::prelude::*; + /// + /// let choices = [('a', 2), ('b', 1), ('c', 1)]; + /// let mut rng = rand::rng(); + /// // First Draw * Second Draw = total odds + /// // ----------------------- + /// // (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'b']` in some order. + /// // (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'c']` in some order. + /// // (25% * 33%) + (25% * 33%) = 16.6% chance that the output is `['b', 'c']` in some order. + /// println!("{:?}", choices.choose_multiple_weighted(&mut rng, 2, |item| item.1).unwrap().collect::>()); + /// ``` + /// [`choose_multiple`]: IndexedRandom::choose_multiple + // Note: this is feature-gated on std due to usage of f64::powf. + // If necessary, we may use alloc+libm as an alternative (see PR #1089). + #[cfg(feature = "std")] + fn choose_multiple_weighted( + &self, + rng: &mut R, + amount: usize, + weight: F, + ) -> Result, WeightError> + where + Self::Output: Sized, + R: Rng + ?Sized, + F: Fn(&Self::Output) -> X, + X: Into, + { + let amount = core::cmp::min(amount, self.len()); + Ok(SliceChooseIter { + slice: self, + _phantom: Default::default(), + indices: index::sample_weighted( + rng, + self.len(), + |idx| weight(&self[idx]).into(), + amount, + )? + .into_iter(), + }) + } +} + +/// Extension trait on indexable lists, providing random sampling methods. +/// +/// This trait is implemented automatically for every type implementing +/// [`IndexedRandom`] and [`std::ops::IndexMut`]. +pub trait IndexedMutRandom: IndexedRandom + IndexMut { + /// Uniformly sample one element (mut) + /// + /// Returns a mutable reference to one uniformly-sampled random element of + /// the slice, or `None` if the slice is empty. + /// + /// For slices, complexity is `O(1)`. + fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Output> + where + R: Rng + ?Sized, + { + if self.is_empty() { + None + } else { + let len = self.len(); + Some(&mut self[rng.random_range(..len)]) + } + } + + /// Biased sampling for one element (mut) + /// + /// Returns a mutable reference to one element of the slice, sampled according + /// to the provided weights. Returns `None` only if the slice is empty. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// For more information about the underlying algorithm, + /// see the [`WeightedIndex`] distribution. + /// + /// See also [`choose_weighted`]. + /// + /// [`choose_mut`]: IndexedMutRandom::choose_mut + /// [`choose_weighted`]: IndexedRandom::choose_weighted + /// [`WeightedIndex`]: crate::distr::weighted::WeightedIndex + #[cfg(feature = "alloc")] + fn choose_weighted_mut( + &mut self, + rng: &mut R, + weight: F, + ) -> Result<&mut Self::Output, WeightError> + where + R: Rng + ?Sized, + F: Fn(&Self::Output) -> B, + B: SampleBorrow, + X: SampleUniform + Weight + PartialOrd, + { + use crate::distr::{weighted::WeightedIndex, Distribution}; + let distr = WeightedIndex::new((0..self.len()).map(|idx| weight(&self[idx])))?; + let index = distr.sample(rng); + Ok(&mut self[index]) + } +} + +/// Extension trait on slices, providing shuffling methods. +/// +/// This trait is implemented on all `[T]` slice types, providing several +/// methods for choosing and shuffling elements. You must `use` this trait: +/// +/// ``` +/// use rand::seq::SliceRandom; +/// +/// let mut rng = rand::rng(); +/// let mut bytes = "Hello, random!".to_string().into_bytes(); +/// bytes.shuffle(&mut rng); +/// let str = String::from_utf8(bytes).unwrap(); +/// println!("{}", str); +/// ``` +/// Example output (non-deterministic): +/// ```none +/// l,nmroHado !le +/// ``` +pub trait SliceRandom: IndexedMutRandom { + /// Shuffle a mutable slice in place. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// The resulting permutation is picked uniformly from the set of all possible permutations. + /// + /// # Example + /// + /// ``` + /// use rand::seq::SliceRandom; + /// + /// let mut rng = rand::rng(); + /// let mut y = [1, 2, 3, 4, 5]; + /// println!("Unshuffled: {:?}", y); + /// y.shuffle(&mut rng); + /// println!("Shuffled: {:?}", y); + /// ``` + fn shuffle(&mut self, rng: &mut R) + where + R: Rng + ?Sized; + + /// Shuffle a slice in place, but exit early. + /// + /// Returns two mutable slices from the source slice. The first contains + /// `amount` elements randomly permuted. The second has the remaining + /// elements that are not fully shuffled. + /// + /// This is an efficient method to select `amount` elements at random from + /// the slice, provided the slice may be mutated. + /// + /// If you only need to choose elements randomly and `amount > self.len()/2` + /// then you may improve performance by taking + /// `amount = self.len() - amount` and using only the second slice. + /// + /// If `amount` is greater than the number of elements in the slice, this + /// will perform a full shuffle. + /// + /// For slices, complexity is `O(m)` where `m = amount`. + fn partial_shuffle( + &mut self, + rng: &mut R, + amount: usize, + ) -> (&mut [Self::Output], &mut [Self::Output]) + where + Self::Output: Sized, + R: Rng + ?Sized; +} + +impl IndexedRandom for [T] { + fn len(&self) -> usize { + self.len() + } +} + +impl + ?Sized> IndexedMutRandom for IR {} + +impl SliceRandom for [T] { + fn shuffle(&mut self, rng: &mut R) + where + R: Rng + ?Sized, + { + if self.len() <= 1 { + // There is no need to shuffle an empty or single element slice + return; + } + self.partial_shuffle(rng, self.len()); + } + + fn partial_shuffle(&mut self, rng: &mut R, amount: usize) -> (&mut [T], &mut [T]) + where + R: Rng + ?Sized, + { + let m = self.len().saturating_sub(amount); + + // The algorithm below is based on Durstenfeld's algorithm for the + // [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) + // for an unbiased permutation. + // It ensures that the last `amount` elements of the slice + // are randomly selected from the whole slice. + + // `IncreasingUniform::next_index()` is faster than `Rng::random_range` + // but only works for 32 bit integers + // So we must use the slow method if the slice is longer than that. + if self.len() < (u32::MAX as usize) { + let mut chooser = IncreasingUniform::new(rng, m as u32); + for i in m..self.len() { + let index = chooser.next_index(); + self.swap(i, index); + } + } else { + for i in m..self.len() { + let index = rng.random_range(..i + 1); + self.swap(i, index); + } + } + let r = self.split_at_mut(m); + (r.1, r.0) + } +} + +/// An iterator over multiple slice elements. +/// +/// This struct is created by +/// [`IndexedRandom::choose_multiple`](trait.IndexedRandom.html#tymethod.choose_multiple). +#[cfg(feature = "alloc")] +#[derive(Debug)] +pub struct SliceChooseIter<'a, S: ?Sized + 'a, T: 'a> { + slice: &'a S, + _phantom: core::marker::PhantomData, + indices: index::IndexVecIntoIter, +} + +#[cfg(feature = "alloc")] +impl<'a, S: Index + ?Sized + 'a, T: 'a> Iterator for SliceChooseIter<'a, S, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + // TODO: investigate using SliceIndex::get_unchecked when stable + self.indices.next().map(|i| &self.slice[i]) + } + + fn size_hint(&self) -> (usize, Option) { + (self.indices.len(), Some(self.indices.len())) + } +} + +#[cfg(feature = "alloc")] +impl<'a, S: Index + ?Sized + 'a, T: 'a> ExactSizeIterator + for SliceChooseIter<'a, S, T> +{ + fn len(&self) -> usize { + self.indices.len() + } +} + +#[cfg(test)] +mod test { + use super::*; + #[cfg(feature = "alloc")] + use alloc::vec::Vec; + + #[test] + fn test_slice_choose() { + let mut r = crate::test::rng(107); + let chars = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + ]; + let mut chosen = [0i32; 14]; + // The below all use a binomial distribution with n=1000, p=1/14. + // binocdf(40, 1000, 1/14) ~= 2e-5; 1-binocdf(106, ..) ~= 2e-5 + for _ in 0..1000 { + let picked = *chars.choose(&mut r).unwrap(); + chosen[(picked as usize) - ('a' as usize)] += 1; + } + for count in chosen.iter() { + assert!(40 < *count && *count < 106); + } + + chosen.iter_mut().for_each(|x| *x = 0); + for _ in 0..1000 { + *chosen.choose_mut(&mut r).unwrap() += 1; + } + for count in chosen.iter() { + assert!(40 < *count && *count < 106); + } + + let mut v: [isize; 0] = []; + assert_eq!(v.choose(&mut r), None); + assert_eq!(v.choose_mut(&mut r), None); + } + + #[test] + fn value_stability_slice() { + let mut r = crate::test::rng(413); + let chars = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + ]; + let mut nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + + assert_eq!(chars.choose(&mut r), Some(&'l')); + assert_eq!(nums.choose_mut(&mut r), Some(&mut 3)); + + assert_eq!( + &chars.choose_multiple_array(&mut r), + &Some(['f', 'i', 'd', 'b', 'c', 'm', 'j', 'k']) + ); + + #[cfg(feature = "alloc")] + assert_eq!( + &chars + .choose_multiple(&mut r, 8) + .cloned() + .collect::>(), + &['h', 'm', 'd', 'b', 'c', 'e', 'n', 'f'] + ); + + #[cfg(feature = "alloc")] + assert_eq!(chars.choose_weighted(&mut r, |_| 1), Ok(&'i')); + #[cfg(feature = "alloc")] + assert_eq!(nums.choose_weighted_mut(&mut r, |_| 1), Ok(&mut 2)); + + let mut r = crate::test::rng(414); + nums.shuffle(&mut r); + assert_eq!(nums, [5, 11, 0, 8, 7, 12, 6, 4, 9, 3, 1, 2, 10]); + nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let res = nums.partial_shuffle(&mut r, 6); + assert_eq!(res.0, &mut [7, 12, 6, 8, 1, 9]); + assert_eq!(res.1, &mut [0, 11, 2, 3, 4, 5, 10]); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_shuffle() { + let mut r = crate::test::rng(108); + let empty: &mut [isize] = &mut []; + empty.shuffle(&mut r); + let mut one = [1]; + one.shuffle(&mut r); + let b: &[_] = &[1]; + assert_eq!(one, b); + + let mut two = [1, 2]; + two.shuffle(&mut r); + assert!(two == [1, 2] || two == [2, 1]); + + fn move_last(slice: &mut [usize], pos: usize) { + // use slice[pos..].rotate_left(1); once we can use that + let last_val = slice[pos]; + for i in pos..slice.len() - 1 { + slice[i] = slice[i + 1]; + } + *slice.last_mut().unwrap() = last_val; + } + let mut counts = [0i32; 24]; + for _ in 0..10000 { + let mut arr: [usize; 4] = [0, 1, 2, 3]; + arr.shuffle(&mut r); + let mut permutation = 0usize; + let mut pos_value = counts.len(); + for i in 0..4 { + pos_value /= 4 - i; + let pos = arr.iter().position(|&x| x == i).unwrap(); + assert!(pos < (4 - i)); + permutation += pos * pos_value; + move_last(&mut arr, pos); + assert_eq!(arr[3], i); + } + for (i, &a) in arr.iter().enumerate() { + assert_eq!(a, i); + } + counts[permutation] += 1; + } + for count in counts.iter() { + // Binomial(10000, 1/24) with average 416.667 + // Octave: binocdf(n, 10000, 1/24) + // 99.9% chance samples lie within this range: + assert!(352 <= *count && *count <= 483, "count: {}", count); + } + } + + #[test] + fn test_partial_shuffle() { + let mut r = crate::test::rng(118); + + let mut empty: [u32; 0] = []; + let res = empty.partial_shuffle(&mut r, 10); + assert_eq!((res.0.len(), res.1.len()), (0, 0)); + + let mut v = [1, 2, 3, 4, 5]; + let res = v.partial_shuffle(&mut r, 2); + assert_eq!((res.0.len(), res.1.len()), (2, 3)); + assert!(res.0[0] != res.0[1]); + // First elements are only modified if selected, so at least one isn't modified: + assert!(res.1[0] == 1 || res.1[1] == 2 || res.1[2] == 3); + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_weighted() { + let mut r = crate::test::rng(406); + const N_REPS: u32 = 3000; + let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; + let total_weight = weights.iter().sum::() as f32; + + let verify = |result: [i32; 14]| { + for (i, count) in result.iter().enumerate() { + let exp = (weights[i] * N_REPS) as f32 / total_weight; + let mut err = (*count as f32 - exp).abs(); + if err != 0.0 { + err /= exp; + } + assert!(err <= 0.25); + } + }; + + // choose_weighted + fn get_weight(item: &(u32, T)) -> u32 { + item.0 + } + let mut chosen = [0i32; 14]; + let mut items = [(0u32, 0usize); 14]; // (weight, index) + for (i, item) in items.iter_mut().enumerate() { + *item = (weights[i], i); + } + for _ in 0..N_REPS { + let item = items.choose_weighted(&mut r, get_weight).unwrap(); + chosen[item.1] += 1; + } + verify(chosen); + + // choose_weighted_mut + let mut items = [(0u32, 0i32); 14]; // (weight, count) + for (i, item) in items.iter_mut().enumerate() { + *item = (weights[i], 0); + } + for _ in 0..N_REPS { + items.choose_weighted_mut(&mut r, get_weight).unwrap().1 += 1; + } + for (ch, item) in chosen.iter_mut().zip(items.iter()) { + *ch = item.1; + } + verify(chosen); + + // Check error cases + let empty_slice = &mut [10][0..0]; + assert_eq!( + empty_slice.choose_weighted(&mut r, |_| 1), + Err(WeightError::InvalidInput) + ); + assert_eq!( + empty_slice.choose_weighted_mut(&mut r, |_| 1), + Err(WeightError::InvalidInput) + ); + assert_eq!( + ['x'].choose_weighted_mut(&mut r, |_| 0), + Err(WeightError::InsufficientNonZero) + ); + assert_eq!( + [0, -1].choose_weighted_mut(&mut r, |x| *x), + Err(WeightError::InvalidWeight) + ); + assert_eq!( + [-1, 0].choose_weighted_mut(&mut r, |x| *x), + Err(WeightError::InvalidWeight) + ); + } + + #[test] + #[cfg(feature = "std")] + fn test_multiple_weighted_edge_cases() { + use super::*; + + let mut rng = crate::test::rng(413); + + // Case 1: One of the weights is 0 + let choices = [('a', 2), ('b', 1), ('c', 0)]; + for _ in 0..100 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + + assert_eq!(result.len(), 2); + assert!(!result.iter().any(|val| val.0 == 'c')); + } + + // Case 2: All of the weights are 0 + let choices = [('a', 0), ('b', 0), ('c', 0)]; + let r = choices.choose_multiple_weighted(&mut rng, 2, |item| item.1); + assert_eq!(r.unwrap().len(), 0); + + // Case 3: Negative weights + let choices = [('a', -1), ('b', 1), ('c', 1)]; + let r = choices.choose_multiple_weighted(&mut rng, 2, |item| item.1); + assert_eq!(r.unwrap_err(), WeightError::InvalidWeight); + + // Case 4: Empty list + let choices = []; + let r = choices.choose_multiple_weighted(&mut rng, 0, |_: &()| 0); + assert_eq!(r.unwrap().count(), 0); + + // Case 5: NaN weights + let choices = [('a', f64::NAN), ('b', 1.0), ('c', 1.0)]; + let r = choices.choose_multiple_weighted(&mut rng, 2, |item| item.1); + assert_eq!(r.unwrap_err(), WeightError::InvalidWeight); + + // Case 6: +infinity weights + let choices = [('a', f64::INFINITY), ('b', 1.0), ('c', 1.0)]; + for _ in 0..100 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + assert_eq!(result.len(), 2); + assert!(result.iter().any(|val| val.0 == 'a')); + } + + // Case 7: -infinity weights + let choices = [('a', f64::NEG_INFINITY), ('b', 1.0), ('c', 1.0)]; + let r = choices.choose_multiple_weighted(&mut rng, 2, |item| item.1); + assert_eq!(r.unwrap_err(), WeightError::InvalidWeight); + + // Case 8: -0 weights + let choices = [('a', -0.0), ('b', 1.0), ('c', 1.0)]; + let r = choices.choose_multiple_weighted(&mut rng, 2, |item| item.1); + assert!(r.is_ok()); + } + + #[test] + #[cfg(feature = "std")] + fn test_multiple_weighted_distributions() { + use super::*; + + // The theoretical probabilities of the different outcomes are: + // AB: 0.5 * 0.667 = 0.3333 + // AC: 0.5 * 0.333 = 0.1667 + // BA: 0.333 * 0.75 = 0.25 + // BC: 0.333 * 0.25 = 0.0833 + // CA: 0.167 * 0.6 = 0.1 + // CB: 0.167 * 0.4 = 0.0667 + let choices = [('a', 3), ('b', 2), ('c', 1)]; + let mut rng = crate::test::rng(414); + + let mut results = [0i32; 3]; + let expected_results = [5833, 2667, 1500]; + for _ in 0..10000 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + + assert_eq!(result.len(), 2); + + match (result[0].0, result[1].0) { + ('a', 'b') | ('b', 'a') => { + results[0] += 1; + } + ('a', 'c') | ('c', 'a') => { + results[1] += 1; + } + ('b', 'c') | ('c', 'b') => { + results[2] += 1; + } + (_, _) => panic!("unexpected result"), + } + } + + let mut diffs = results + .iter() + .zip(&expected_results) + .map(|(a, b)| (a - b).abs()); + assert!(!diffs.any(|deviation| deviation > 100)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"7ba9b51f1f94aa2f9bdb8b5202a69f8ae495be4fa46b63ac2ac72f9496494ee7","CHANGELOG.md":"102f114ebb898692dee1abe1e9debdf5ced6e7def8774d739043bb5afd8709b9","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.lock":"87cfa1755f12538b04d4d98ebd45997b2fd53a1d1fdf315f787d182f76c0b2cd","Cargo.toml":"f413a8d1156cb6c7271427e5f406ed65e3056e2422224ad5d13f7d40a0c35803","Cargo.toml.orig":"1acccaeba470188c3a0286b17efe27e001f41ef8c9cb0041aa9e9113f894fe5c","LICENSE-APACHE":"35242e7a83f69875e6edeff02291e688c97caafe2f8902e4e19b49d3e78b4cab","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"13c20fa16d5cd5abf47d10cbec09ef3e488f4b2cce4c63711b8e4c021d2d97c4","src/chacha.rs":"8b7fb696f491afe9ca5830e5ed66f418f0cb6bee40dafb4e4d2404c50523a33a","src/guts.rs":"33d284279f5bacc5951a46de693a77758b662c341ef05bd8a4bcda84f34863a6","src/lib.rs":"a3eddc972be141f04118957200d23ec8b783ca53b382c0d886a9436229c8bec4"},"package":"d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "96f8df65ee6b4368d91a006f9c5b4a8050abae49" + }, + "path_in_vcs": "rand_chacha" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.9.0] - 2025-01-27 +### Dependencies and features +- Update to `rand_core` v0.9.0 (#1558) +- Feature `std` now implies feature `rand_core/std` (#1153) +- Rename feature `serde1` to `serde` (#1477) +- Rename feature `getrandom` to `os_rng` (#1537) + +### Other changes +- Remove usage of `unsafe` in `fn generate` (#1181) then optimise for AVX2 (~4-7%) (#1192) +- Revise crate docs (#1454) + +## [0.3.1] - 2021-06-09 +- add getters corresponding to existing setters: `get_seed`, `get_stream` (#1124) +- add serde support, gated by the `serde1` feature (#1124) +- ensure expected layout via `repr(transparent)` (#1120) + +## [0.3.0] - 2020-12-08 +- Bump `rand_core` version to 0.6.0 +- Bump MSRV to 1.36 (#1011) +- Remove usage of deprecated feature "simd" of `ppv-lite86` (#979), then revert + this change (#1023) since SIMD is only enabled by default from `ppv-lite86 v0.2.10` +- impl PartialEq+Eq for ChaChaXRng and ChaChaXCore (#979) +- Fix panic on block counter wrap that was occurring in debug builds (#980) + +## [0.2.2] - 2020-03-09 +- Integrate `c2-chacha`, reducing dependency count (#931) +- Add CryptoRng to ChaChaXCore (#944) + +## [0.2.1] - 2019-07-22 +- Force enable the `simd` feature of `c2-chacha` (#845) + +## [0.2.0] - 2019-06-06 +- Rewrite based on the much faster `c2-chacha` crate (#789) + +## [0.1.1] - 2019-01-04 +- Disable `i128` and `u128` if the `target_os` is `emscripten` (#671: work-around Emscripten limitation) +- Update readme and doc links + +## [0.1.0] - 2018-10-17 +- Pulled out of the Rand crate diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/COPYRIGHT clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/COPYRIGHT --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/COPYRIGHT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/COPYRIGHT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71393ecc86efbf00e4ca13953979ba8b94cfe549a4b74cc26d8b62f4d8feac2b" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +dependencies = [ + "ppv-lite86", + "rand_core", + "serde", + "serde_json", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom", + "zerocopy", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65238aacd5fb83fb03fcaf94823e71643e937000ec03c46e7da94234b10c870" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ca22c4ad176b37bd81a565f66635bde3d654fe6832730c3e52e1018ae1655ee" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,81 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63" +name = "rand_chacha" +version = "0.9.0" +authors = [ + "The Rand Project Developers", + "The Rust Project Developers", + "The CryptoCorrosion Contributors", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +ChaCha random number generator +""" +homepage = "https://rust-random.github.io/book" +documentation = "https://docs.rs/rand_chacha" +readme = "README.md" +keywords = [ + "random", + "rng", + "chacha", +] +categories = [ + "algorithms", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[features] +default = ["std"] +os_rng = ["rand_core/os_rng"] +serde = ["dep:serde"] +std = [ + "ppv-lite86/std", + "rand_core/std", +] + +[lib] +name = "rand_chacha" +path = "src/lib.rs" + +[dependencies.ppv-lite86] +version = "0.2.14" +features = ["simd"] +default-features = false + +[dependencies.rand_core] +version = "0.9.0" + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dev-dependencies.rand_core] +version = "0.9.0" +features = ["os_rng"] + +[dev-dependencies.serde_json] +version = "1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +[package] +name = "rand_chacha" +version = "0.9.0" +authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-random/rand" +documentation = "https://docs.rs/rand_chacha" +homepage = "https://rust-random.github.io/book" +description = """ +ChaCha random number generator +""" +keywords = ["random", "rng", "chacha"] +categories = ["algorithms", "no-std"] +edition = "2021" +rust-version = "1.63" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[dependencies] +rand_core = { path = "../rand_core", version = "0.9.0" } +ppv-lite86 = { version = "0.2.14", default-features = false, features = ["simd"] } +serde = { version = "1.0", features = ["derive"], optional = true } + +[dev-dependencies] +# Only to test serde +serde_json = "1.0" +rand_core = { path = "../rand_core", version = "0.9.0", features = ["os_rng"] } + +[features] +default = ["std"] +os_rng = ["rand_core/os_rng"] +std = ["ppv-lite86/std", "rand_core/std"] +serde = ["dep:serde"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/README.md clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +# rand_chacha + +[![Test Status](https://github.com/rust-random/rand/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Latest version](https://img.shields.io/crates/v/rand_chacha.svg)](https://crates.io/crates/rand_chacha) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_chacha) +[![API](https://docs.rs/rand_chacha/badge.svg)](https://docs.rs/rand_chacha) + +A cryptographically secure random number generator that uses the ChaCha +algorithm. + +ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use +as an RNG. It is an improved variant of the Salsa20 cipher family, which was +selected as one of the "stream ciphers suitable for widespread adoption" by +eSTREAM[^2]. + +The RNGs provided by this crate are implemented via the fast stream ciphers of +the [`c2-chacha`](https://crates.io/crates/c2-chacha) crate. + +Links: + +- [API documentation (master)](https://rust-random.github.io/rand/rand_chacha) +- [API documentation (docs.rs)](https://docs.rs/rand_chacha) +- [Changelog](https://github.com/rust-random/rand/blob/master/rand_chacha/CHANGELOG.md) + +[rand]: https://crates.io/crates/rand +[^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( + https://cr.yp.to/chacha.html) + +[^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( + http://www.ecrypt.eu.org/stream/) + + +## Crate Features + +`rand_chacha` is `no_std` compatible when disabling default features; the `std` +feature can be explicitly required to re-enable `std` support. Using `std` +allows detection of CPU features and thus better optimisation. Using `std` +also enables `os_rng` functionality, such as `ChaCha20Rng::from_os_rng()`. + + +# License + +`rand_chacha` is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/chacha.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/chacha.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/chacha.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/chacha.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,651 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generator. + +use crate::guts::ChaCha; +use core::fmt; +use rand_core::block::{BlockRng, BlockRngCore, CryptoBlockRng}; +use rand_core::{CryptoRng, RngCore, SeedableRng}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +// NB. this must remain consistent with some currently hard-coded numbers in this module +const BUF_BLOCKS: u8 = 4; +// number of 32-bit words per ChaCha block (fixed by algorithm definition) +const BLOCK_WORDS: u8 = 16; + +#[repr(transparent)] +pub struct Array64([T; 64]); +impl Default for Array64 +where + T: Default, +{ + #[rustfmt::skip] + fn default() -> Self { + Self([ + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + ]) + } +} +impl AsRef<[T]> for Array64 { + fn as_ref(&self) -> &[T] { + &self.0 + } +} +impl AsMut<[T]> for Array64 { + fn as_mut(&mut self) -> &mut [T] { + &mut self.0 + } +} +impl Clone for Array64 +where + T: Copy + Default, +{ + fn clone(&self) -> Self { + let mut new = Self::default(); + new.0.copy_from_slice(&self.0); + new + } +} +impl fmt::Debug for Array64 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Array64 {{}}") + } +} + +macro_rules! chacha_impl { + ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr, $abst:ident,) => { + #[doc=$doc] + #[derive(Clone, PartialEq, Eq)] + pub struct $ChaChaXCore { + state: ChaCha, + } + + // Custom Debug implementation that does not expose the internal state + impl fmt::Debug for $ChaChaXCore { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ChaChaXCore {{}}") + } + } + + impl BlockRngCore for $ChaChaXCore { + type Item = u32; + type Results = Array64; + + #[inline] + fn generate(&mut self, r: &mut Self::Results) { + self.state.refill4($rounds, &mut r.0); + } + } + + impl SeedableRng for $ChaChaXCore { + type Seed = [u8; 32]; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + $ChaChaXCore { + state: ChaCha::new(&seed, &[0u8; 8]), + } + } + } + + impl CryptoBlockRng for $ChaChaXCore {} + + /// A cryptographically secure random number generator that uses the ChaCha algorithm. + /// + /// ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use as an RNG. It is + /// an improved variant of the Salsa20 cipher family, which was selected as one of the "stream + /// ciphers suitable for widespread adoption" by eSTREAM[^2]. + /// + /// ChaCha uses add-rotate-xor (ARX) operations as its basis. These are safe against timing + /// attacks, although that is mostly a concern for ciphers and not for RNGs. We provide a SIMD + /// implementation to support high throughput on a variety of common hardware platforms. + /// + /// With the ChaCha algorithm it is possible to choose the number of rounds the core algorithm + /// should run. The number of rounds is a tradeoff between performance and security, where 8 + /// rounds is the minimum potentially secure configuration, and 20 rounds is widely used as a + /// conservative choice. + /// + /// We use a 64-bit counter and 64-bit stream identifier as in Bernstein's implementation[^1] + /// except that we use a stream identifier in place of a nonce. A 64-bit counter over 64-byte + /// (16 word) blocks allows 1 ZiB of output before cycling, and the stream identifier allows + /// 264 unique streams of output per seed. Both counter and stream are initialized + /// to zero but may be set via the `set_word_pos` and `set_stream` methods. + /// + /// The word layout is: + /// + /// ```text + /// constant constant constant constant + /// seed seed seed seed + /// seed seed seed seed + /// counter counter stream_id stream_id + /// ``` + /// + /// This implementation uses an output buffer of sixteen `u32` words, and uses + /// [`BlockRng`] to implement the [`RngCore`] methods. + /// + /// [^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( + /// https://cr.yp.to/chacha.html) + /// + /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( + /// http://www.ecrypt.eu.org/stream/) + #[derive(Clone, Debug)] + pub struct $ChaChaXRng { + rng: BlockRng<$ChaChaXCore>, + } + + impl SeedableRng for $ChaChaXRng { + type Seed = [u8; 32]; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + let core = $ChaChaXCore::from_seed(seed); + Self { + rng: BlockRng::new(core), + } + } + } + + impl RngCore for $ChaChaXRng { + #[inline] + fn next_u32(&mut self) -> u32 { + self.rng.next_u32() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.rng.next_u64() + } + + #[inline] + fn fill_bytes(&mut self, bytes: &mut [u8]) { + self.rng.fill_bytes(bytes) + } + } + + impl $ChaChaXRng { + // The buffer is a 4-block window, i.e. it is always at a block-aligned position in the + // stream but if the stream has been sought it may not be self-aligned. + + /// Get the offset from the start of the stream, in 32-bit words. + /// + /// Since the generated blocks are 16 words (24) long and the + /// counter is 64-bits, the offset is a 68-bit number. Sub-word offsets are + /// not supported, hence the result can simply be multiplied by 4 to get a + /// byte-offset. + #[inline] + pub fn get_word_pos(&self) -> u128 { + let buf_start_block = { + let buf_end_block = self.rng.core.state.get_block_pos(); + u64::wrapping_sub(buf_end_block, BUF_BLOCKS.into()) + }; + let (buf_offset_blocks, block_offset_words) = { + let buf_offset_words = self.rng.index() as u64; + let blocks_part = buf_offset_words / u64::from(BLOCK_WORDS); + let words_part = buf_offset_words % u64::from(BLOCK_WORDS); + (blocks_part, words_part) + }; + let pos_block = u64::wrapping_add(buf_start_block, buf_offset_blocks); + let pos_block_words = u128::from(pos_block) * u128::from(BLOCK_WORDS); + pos_block_words + u128::from(block_offset_words) + } + + /// Set the offset from the start of the stream, in 32-bit words. + /// + /// As with `get_word_pos`, we use a 68-bit number. Since the generator + /// simply cycles at the end of its period (1 ZiB), we ignore the upper + /// 60 bits. + #[inline] + pub fn set_word_pos(&mut self, word_offset: u128) { + let block = (word_offset / u128::from(BLOCK_WORDS)) as u64; + self.rng.core.state.set_block_pos(block); + self.rng + .generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize); + } + + /// Set the stream number. + /// + /// This is initialized to zero; 264 unique streams of output + /// are available per seed/key. + /// + /// Note that in order to reproduce ChaCha output with a specific 64-bit + /// nonce, one can convert that nonce to a `u64` in little-endian fashion + /// and pass to this function. In theory a 96-bit nonce can be used by + /// passing the last 64-bits to this function and using the first 32-bits as + /// the most significant half of the 64-bit counter (which may be set + /// indirectly via `set_word_pos`), but this is not directly supported. + #[inline] + pub fn set_stream(&mut self, stream: u64) { + self.rng.core.state.set_nonce(stream); + if self.rng.index() != 64 { + let wp = self.get_word_pos(); + self.set_word_pos(wp); + } + } + + /// Get the stream number. + #[inline] + pub fn get_stream(&self) -> u64 { + self.rng.core.state.get_nonce() + } + + /// Get the seed. + #[inline] + pub fn get_seed(&self) -> [u8; 32] { + self.rng.core.state.get_seed() + } + } + + impl CryptoRng for $ChaChaXRng {} + + impl From<$ChaChaXCore> for $ChaChaXRng { + fn from(core: $ChaChaXCore) -> Self { + $ChaChaXRng { + rng: BlockRng::new(core), + } + } + } + + impl PartialEq<$ChaChaXRng> for $ChaChaXRng { + fn eq(&self, rhs: &$ChaChaXRng) -> bool { + let a: $abst::$ChaChaXRng = self.into(); + let b: $abst::$ChaChaXRng = rhs.into(); + a == b + } + } + impl Eq for $ChaChaXRng {} + + #[cfg(feature = "serde")] + impl Serialize for $ChaChaXRng { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + $abst::$ChaChaXRng::from(self).serialize(s) + } + } + #[cfg(feature = "serde")] + impl<'de> Deserialize<'de> for $ChaChaXRng { + fn deserialize(d: D) -> Result + where + D: Deserializer<'de>, + { + $abst::$ChaChaXRng::deserialize(d).map(|x| Self::from(&x)) + } + } + + mod $abst { + #[cfg(feature = "serde")] + use serde::{Deserialize, Serialize}; + + // The abstract state of a ChaCha stream, independent of implementation choices. The + // comparison and serialization of this object is considered a semver-covered part of + // the API. + #[derive(Debug, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + pub(crate) struct $ChaChaXRng { + seed: [u8; 32], + stream: u64, + word_pos: u128, + } + + impl From<&super::$ChaChaXRng> for $ChaChaXRng { + // Forget all information about the input except what is necessary to determine the + // outputs of any sequence of pub API calls. + fn from(r: &super::$ChaChaXRng) -> Self { + Self { + seed: r.get_seed(), + stream: r.get_stream(), + word_pos: r.get_word_pos(), + } + } + } + + impl From<&$ChaChaXRng> for super::$ChaChaXRng { + // Construct one of the possible concrete RNGs realizing an abstract state. + fn from(a: &$ChaChaXRng) -> Self { + use rand_core::SeedableRng; + let mut r = Self::from_seed(a.seed); + r.set_stream(a.stream); + r.set_word_pos(a.word_pos); + r + } + } + } + }; +} + +chacha_impl!( + ChaCha20Core, + ChaCha20Rng, + 10, + "ChaCha with 20 rounds", + abstract20, +); +chacha_impl!( + ChaCha12Core, + ChaCha12Rng, + 6, + "ChaCha with 12 rounds", + abstract12, +); +chacha_impl!( + ChaCha8Core, + ChaCha8Rng, + 4, + "ChaCha with 8 rounds", + abstract8, +); + +#[cfg(test)] +mod test { + use rand_core::{RngCore, SeedableRng}; + + #[cfg(feature = "serde")] + use super::{ChaCha12Rng, ChaCha20Rng, ChaCha8Rng}; + + type ChaChaRng = super::ChaCha20Rng; + + #[cfg(feature = "serde")] + #[test] + fn test_chacha_serde_roundtrip() { + let seed = [ + 1, 0, 52, 0, 0, 0, 0, 0, 1, 0, 10, 0, 22, 32, 0, 0, 2, 0, 55, 49, 0, 11, 0, 0, 3, 0, 0, + 0, 0, 0, 2, 92, + ]; + let mut rng1 = ChaCha20Rng::from_seed(seed); + let mut rng2 = ChaCha12Rng::from_seed(seed); + let mut rng3 = ChaCha8Rng::from_seed(seed); + + let encoded1 = serde_json::to_string(&rng1).unwrap(); + let encoded2 = serde_json::to_string(&rng2).unwrap(); + let encoded3 = serde_json::to_string(&rng3).unwrap(); + + let mut decoded1: ChaCha20Rng = serde_json::from_str(&encoded1).unwrap(); + let mut decoded2: ChaCha12Rng = serde_json::from_str(&encoded2).unwrap(); + let mut decoded3: ChaCha8Rng = serde_json::from_str(&encoded3).unwrap(); + + assert_eq!(rng1, decoded1); + assert_eq!(rng2, decoded2); + assert_eq!(rng3, decoded3); + + assert_eq!(rng1.next_u32(), decoded1.next_u32()); + assert_eq!(rng2.next_u32(), decoded2.next_u32()); + assert_eq!(rng3.next_u32(), decoded3.next_u32()); + } + + // This test validates that: + // 1. a hard-coded serialization demonstrating the format at time of initial release can still + // be deserialized to a ChaChaRng + // 2. re-serializing the resultant object produces exactly the original string + // + // Condition 2 is stronger than necessary: an equivalent serialization (e.g. with field order + // permuted, or whitespace differences) would also be admissible, but would fail this test. + // However testing for equivalence of serialized data is difficult, and there shouldn't be any + // reason we need to violate the stronger-than-needed condition, e.g. by changing the field + // definition order. + #[cfg(feature = "serde")] + #[test] + fn test_chacha_serde_format_stability() { + let j = r#"{"seed":[4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8],"stream":27182818284,"word_pos":314159265359}"#; + let r: ChaChaRng = serde_json::from_str(j).unwrap(); + let j1 = serde_json::to_string(&r).unwrap(); + assert_eq!(j, j1); + } + + #[test] + fn test_chacha_construction() { + let seed = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, + ]; + let mut rng1 = ChaChaRng::from_seed(seed); + assert_eq!(rng1.next_u32(), 137206642); + + let mut rng2 = ChaChaRng::from_rng(&mut rng1); + assert_eq!(rng2.next_u32(), 1325750369); + } + + #[test] + fn test_chacha_true_values_a() { + // Test vectors 1 and 2 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, 0xb819d2bd, 0x1aed8da0, 0xccef36a8, + 0xc70d778b, 0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, 0xf4b8436a, 0x1ca11815, + 0x69b687c3, 0x8665eeb2, + ]; + assert_eq!(results, expected); + + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, 0xa0290fcb, 0x6965e348, 0x3e53c612, + 0xed7aee32, 0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, 0x281fed31, 0x45fb0a51, + 0x1f0ae1ac, 0x6f4d794b, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_values_b() { + // Test vector 3 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, + ]; + let mut rng = ChaChaRng::from_seed(seed); + + // Skip block 0 + for _ in 0..16 { + rng.next_u32(); + } + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0x2452eb3a, 0x9249f8ec, 0x8d829d9b, 0xddd4ceb1, 0xe8252083, 0x60818b01, 0xf38422b8, + 0x5aaa49c9, 0xbb00ca8e, 0xda3ba7b4, 0xc4b592d1, 0xfdf2732f, 0x4436274e, 0x2561b3c8, + 0xebdd4aa6, 0xa0136c00, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_values_c() { + // Test vector 4 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [ + 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]; + let expected = [ + 0xfb4dd572, 0x4bc42ef1, 0xdf922636, 0x327f1394, 0xa78dea8f, 0x5e269039, 0xa1bebbc1, + 0xcaf09aae, 0xa25ab213, 0x48a6b46c, 0x1b9d9bcb, 0x092c5be6, 0x546ca624, 0x1bec45d5, + 0x87f47473, 0x96f0992e, + ]; + let expected_end = 3 * 16; + let mut results = [0u32; 16]; + + // Test block 2 by skipping block 0 and 1 + let mut rng1 = ChaChaRng::from_seed(seed); + for _ in 0..32 { + rng1.next_u32(); + } + for i in results.iter_mut() { + *i = rng1.next_u32(); + } + assert_eq!(results, expected); + assert_eq!(rng1.get_word_pos(), expected_end); + + // Test block 2 by using `set_word_pos` + let mut rng2 = ChaChaRng::from_seed(seed); + rng2.set_word_pos(2 * 16); + for i in results.iter_mut() { + *i = rng2.next_u32(); + } + assert_eq!(results, expected); + assert_eq!(rng2.get_word_pos(), expected_end); + + // Test skipping behaviour with other types + let mut buf = [0u8; 32]; + rng2.fill_bytes(&mut buf[..]); + assert_eq!(rng2.get_word_pos(), expected_end + 8); + rng2.fill_bytes(&mut buf[0..25]); + assert_eq!(rng2.get_word_pos(), expected_end + 15); + rng2.next_u64(); + assert_eq!(rng2.get_word_pos(), expected_end + 17); + rng2.next_u32(); + rng2.next_u64(); + assert_eq!(rng2.get_word_pos(), expected_end + 20); + rng2.fill_bytes(&mut buf[0..1]); + assert_eq!(rng2.get_word_pos(), expected_end + 21); + } + + #[test] + fn test_chacha_multiple_blocks() { + let seed = [ + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, + ]; + let mut rng = ChaChaRng::from_seed(seed); + + // Store the 17*i-th 32-bit word, + // i.e., the i-th word of the i-th 16-word block + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + for _ in 0..16 { + rng.next_u32(); + } + } + let expected = [ + 0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, 0x49884684, 0x64efec72, 0x4be2d186, + 0x3615b384, 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, 0x2c5bad8f, 0x898881dc, + 0x5f1c86d9, 0xc1f8e7f4, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_bytes() { + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + let mut results = [0u8; 32]; + rng.fill_bytes(&mut results); + let expected = [ + 118, 184, 224, 173, 160, 241, 61, 144, 64, 93, 106, 229, 83, 134, 189, 40, 189, 210, + 25, 184, 160, 141, 237, 26, 168, 54, 239, 204, 139, 119, 13, 199, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_nonce() { + // Test vector 5 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + // Although we do not support setting a nonce, we try it here anyway so + // we can use this test vector. + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + // 96-bit nonce in LE order is: 0,0,0,0, 0,0,0,0, 0,0,0,2 + rng.set_stream(2u64 << (24 + 32)); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0x374dc6c2, 0x3736d58c, 0xb904e24a, 0xcd3f93ef, 0x88228b1a, 0x96a4dfb3, 0x5b76ab72, + 0xc727ee54, 0x0e0e978a, 0xf3145c95, 0x1b748ea8, 0xf786c297, 0x99c28f5f, 0x628314e8, + 0x398a19fa, 0x6ded1b53, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_clone_streams() { + let seed = [ + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, + ]; + let mut rng = ChaChaRng::from_seed(seed); + let mut clone = rng.clone(); + for _ in 0..16 { + assert_eq!(rng.next_u64(), clone.next_u64()); + } + + rng.set_stream(51); + for _ in 0..7 { + assert!(rng.next_u32() != clone.next_u32()); + } + clone.set_stream(51); // switch part way through block + for _ in 7..16 { + assert_eq!(rng.next_u32(), clone.next_u32()); + } + } + + #[test] + fn test_chacha_word_pos_wrap_exact() { + use super::{BLOCK_WORDS, BUF_BLOCKS}; + let mut rng = ChaChaRng::from_seed(Default::default()); + // refilling the buffer in set_word_pos will wrap the block counter to 0 + let last_block = (1 << 68) - u128::from(BUF_BLOCKS * BLOCK_WORDS); + rng.set_word_pos(last_block); + assert_eq!(rng.get_word_pos(), last_block); + } + + #[test] + fn test_chacha_word_pos_wrap_excess() { + use super::BLOCK_WORDS; + let mut rng = ChaChaRng::from_seed(Default::default()); + // refilling the buffer in set_word_pos will wrap the block counter past 0 + let last_block = (1 << 68) - u128::from(BLOCK_WORDS); + rng.set_word_pos(last_block); + assert_eq!(rng.get_word_pos(), last_block); + } + + #[test] + fn test_chacha_word_pos_zero() { + let mut rng = ChaChaRng::from_seed(Default::default()); + assert_eq!(rng.get_word_pos(), 0); + rng.set_word_pos(0); + assert_eq!(rng.get_word_pos(), 0); + } + + #[test] + fn test_trait_objects() { + use rand_core::CryptoRng; + + let mut rng1 = ChaChaRng::from_seed(Default::default()); + let rng2 = &mut rng1.clone() as &mut dyn CryptoRng; + for _ in 0..1000 { + assert_eq!(rng1.next_u64(), rng2.next_u64()); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/guts.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/guts.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/guts.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/guts.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,287 @@ +// Copyright 2019 The CryptoCorrosion Contributors +// Copyright 2020 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generator. + +use ppv_lite86::{dispatch, dispatch_light128}; + +pub use ppv_lite86::Machine; +use ppv_lite86::{ + vec128_storage, ArithOps, BitOps32, LaneWords4, MultiLane, StoreBytes, Vec4, Vec4Ext, Vector, +}; + +pub(crate) const BLOCK: usize = 16; +pub(crate) const BLOCK64: u64 = BLOCK as u64; +const LOG2_BUFBLOCKS: u64 = 2; +const BUFBLOCKS: u64 = 1 << LOG2_BUFBLOCKS; +pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS; +pub(crate) const BUFSZ: usize = BUFSZ64 as usize; + +const STREAM_PARAM_NONCE: u32 = 1; +const STREAM_PARAM_BLOCK: u32 = 0; + +#[derive(Clone, PartialEq, Eq)] +pub struct ChaCha { + pub(crate) b: vec128_storage, + pub(crate) c: vec128_storage, + pub(crate) d: vec128_storage, +} + +#[derive(Clone)] +pub struct State { + pub(crate) a: V, + pub(crate) b: V, + pub(crate) c: V, + pub(crate) d: V, +} + +#[inline(always)] +pub(crate) fn round(mut x: State) -> State { + x.a += x.b; + x.d = (x.d ^ x.a).rotate_each_word_right16(); + x.c += x.d; + x.b = (x.b ^ x.c).rotate_each_word_right20(); + x.a += x.b; + x.d = (x.d ^ x.a).rotate_each_word_right24(); + x.c += x.d; + x.b = (x.b ^ x.c).rotate_each_word_right25(); + x +} + +#[inline(always)] +pub(crate) fn diagonalize(mut x: State) -> State { + x.b = x.b.shuffle_lane_words3012(); + x.c = x.c.shuffle_lane_words2301(); + x.d = x.d.shuffle_lane_words1230(); + x +} +#[inline(always)] +pub(crate) fn undiagonalize(mut x: State) -> State { + x.b = x.b.shuffle_lane_words1230(); + x.c = x.c.shuffle_lane_words2301(); + x.d = x.d.shuffle_lane_words3012(); + x +} + +impl ChaCha { + #[inline(always)] + pub fn new(key: &[u8; 32], nonce: &[u8]) -> Self { + init_chacha(key, nonce) + } + + /// Produce 4 blocks of output, advancing the state + #[inline(always)] + pub fn refill4(&mut self, drounds: u32, out: &mut [u32; BUFSZ]) { + refill_wide(self, drounds, out) + } + + #[inline(always)] + pub fn set_block_pos(&mut self, value: u64) { + set_stream_param(self, STREAM_PARAM_BLOCK, value) + } + + #[inline(always)] + pub fn get_block_pos(&self) -> u64 { + get_stream_param(self, STREAM_PARAM_BLOCK) + } + + #[inline(always)] + pub fn set_nonce(&mut self, value: u64) { + set_stream_param(self, STREAM_PARAM_NONCE, value) + } + + #[inline(always)] + pub fn get_nonce(&self) -> u64 { + get_stream_param(self, STREAM_PARAM_NONCE) + } + + #[inline(always)] + pub fn get_seed(&self) -> [u8; 32] { + get_seed(self) + } +} + +// This implementation is platform-independent. +#[inline(always)] +#[cfg(target_endian = "big")] +fn add_pos(_m: Mach, d0: Mach::u32x4, i: u64) -> Mach::u32x4 { + let pos0 = ((d0.extract(1) as u64) << 32) | d0.extract(0) as u64; + let pos = pos0.wrapping_add(i); + d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0) +} +#[inline(always)] +#[cfg(target_endian = "big")] +fn d0123(m: Mach, d: vec128_storage) -> Mach::u32x4x4 { + let d0: Mach::u32x4 = m.unpack(d); + let mut pos = ((d0.extract(1) as u64) << 32) | d0.extract(0) as u64; + pos = pos.wrapping_add(1); + let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + Mach::u32x4x4::from_lanes([d0, d1, d2, d3]) +} + +// Pos is packed into the state vectors as a little-endian u64, +// so on LE platforms we can use native vector ops to increment it. +#[inline(always)] +#[cfg(target_endian = "little")] +fn add_pos(m: Mach, d: Mach::u32x4, i: u64) -> Mach::u32x4 { + let d0: Mach::u64x2 = m.unpack(d.into()); + let incr = m.vec([i, 0]); + m.unpack((d0 + incr).into()) +} +#[inline(always)] +#[cfg(target_endian = "little")] +fn d0123(m: Mach, d: vec128_storage) -> Mach::u32x4x4 { + let d0: Mach::u64x2 = m.unpack(d); + let incr = + Mach::u64x2x4::from_lanes([m.vec([0, 0]), m.vec([1, 0]), m.vec([2, 0]), m.vec([3, 0])]); + m.unpack((Mach::u64x2x4::from_lanes([d0, d0, d0, d0]) + incr).into()) +} + +#[allow(clippy::many_single_char_names)] +#[inline(always)] +fn refill_wide_impl( + m: Mach, + state: &mut ChaCha, + drounds: u32, + out: &mut [u32; BUFSZ], +) { + let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]); + let b = m.unpack(state.b); + let c = m.unpack(state.c); + let mut x = State { + a: Mach::u32x4x4::from_lanes([k, k, k, k]), + b: Mach::u32x4x4::from_lanes([b, b, b, b]), + c: Mach::u32x4x4::from_lanes([c, c, c, c]), + d: d0123(m, state.d), + }; + for _ in 0..drounds { + x = round(x); + x = undiagonalize(round(diagonalize(x))); + } + let kk = Mach::u32x4x4::from_lanes([k, k, k, k]); + let sb = m.unpack(state.b); + let sb = Mach::u32x4x4::from_lanes([sb, sb, sb, sb]); + let sc = m.unpack(state.c); + let sc = Mach::u32x4x4::from_lanes([sc, sc, sc, sc]); + let sd = d0123(m, state.d); + let results = Mach::u32x4x4::transpose4(x.a + kk, x.b + sb, x.c + sc, x.d + sd); + out[0..16].copy_from_slice(&results.0.to_scalars()); + out[16..32].copy_from_slice(&results.1.to_scalars()); + out[32..48].copy_from_slice(&results.2.to_scalars()); + out[48..64].copy_from_slice(&results.3.to_scalars()); + state.d = add_pos(m, sd.to_lanes()[0], 4).into(); +} + +dispatch!(m, Mach, { + fn refill_wide(state: &mut ChaCha, drounds: u32, out: &mut [u32; BUFSZ]) { + refill_wide_impl(m, state, drounds, out); + } +}); + +// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ +// and XChaCha's setup step. +dispatch!(m, Mach, { + fn refill_narrow_rounds(state: &mut ChaCha, drounds: u32) -> State { + let k: Mach::u32x4 = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]); + let mut x = State { + a: k, + b: m.unpack(state.b), + c: m.unpack(state.c), + d: m.unpack(state.d), + }; + for _ in 0..drounds { + x = round(x); + x = undiagonalize(round(diagonalize(x))); + } + State { + a: x.a.into(), + b: x.b.into(), + c: x.c.into(), + d: x.d.into(), + } + } +}); + +dispatch_light128!(m, Mach, { + fn set_stream_param(state: &mut ChaCha, param: u32, value: u64) { + let d: Mach::u32x4 = m.unpack(state.d); + state.d = d + .insert((value >> 32) as u32, (param << 1) | 1) + .insert(value as u32, param << 1) + .into(); + } +}); + +dispatch_light128!(m, Mach, { + fn get_stream_param(state: &ChaCha, param: u32) -> u64 { + let d: Mach::u32x4 = m.unpack(state.d); + ((d.extract((param << 1) | 1) as u64) << 32) | d.extract(param << 1) as u64 + } +}); + +dispatch_light128!(m, Mach, { + fn get_seed(state: &ChaCha) -> [u8; 32] { + let b: Mach::u32x4 = m.unpack(state.b); + let c: Mach::u32x4 = m.unpack(state.c); + let mut key = [0u8; 32]; + b.write_le(&mut key[..16]); + c.write_le(&mut key[16..]); + key + } +}); + +fn read_u32le(xs: &[u8]) -> u32 { + assert_eq!(xs.len(), 4); + u32::from(xs[0]) | (u32::from(xs[1]) << 8) | (u32::from(xs[2]) << 16) | (u32::from(xs[3]) << 24) +} + +dispatch_light128!(m, Mach, { + fn init_chacha(key: &[u8; 32], nonce: &[u8]) -> ChaCha { + let ctr_nonce = [ + 0, + if nonce.len() == 12 { + read_u32le(&nonce[0..4]) + } else { + 0 + }, + read_u32le(&nonce[nonce.len() - 8..nonce.len() - 4]), + read_u32le(&nonce[nonce.len() - 4..]), + ]; + let key0: Mach::u32x4 = m.read_le(&key[..16]); + let key1: Mach::u32x4 = m.read_le(&key[16..]); + ChaCha { + b: key0.into(), + c: key1.into(), + d: ctr_nonce.into(), + } + } +}); + +dispatch_light128!(m, Mach, { + fn init_chacha_x(key: &[u8; 32], nonce: &[u8; 24], rounds: u32) -> ChaCha { + let key0: Mach::u32x4 = m.read_le(&key[..16]); + let key1: Mach::u32x4 = m.read_le(&key[16..]); + let nonce0: Mach::u32x4 = m.read_le(&nonce[..16]); + let mut state = ChaCha { + b: key0.into(), + c: key1.into(), + d: nonce0.into(), + }; + let x = refill_narrow_rounds(&mut state, rounds); + let ctr_nonce1 = [0, 0, read_u32le(&nonce[16..20]), read_u32le(&nonce[20..24])]; + state.b = x.a; + state.c = x.d; + state.d = ctr_nonce1.into(); + state + } +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_chacha/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_chacha/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,106 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generators. +//! +//! These are native Rust implementations of RNGs derived from the +//! [ChaCha stream ciphers] by D J Bernstein. +//! +//! ## Generators +//! +//! This crate provides 8-, 12- and 20-round variants of generators via a "core" +//! implementation (of [`BlockRngCore`]), each with an associated "RNG" type +//! (implementing [`RngCore`]). +//! +//! These generators are all deterministic and portable (see [Reproducibility] +//! in the book), with testing against reference vectors. +//! +//! ## Cryptographic (secure) usage +//! +//! Where secure unpredictable generators are required, it is suggested to use +//! [`ChaCha12Rng`] or [`ChaCha20Rng`] and to seed via +//! [`SeedableRng::from_os_rng`]. +//! +//! See also the [Security] chapter in the rand book. The crate is provided +//! "as is", without any form of guarantee, and without a security audit. +//! +//! ## Seeding (construction) +//! +//! Generators implement the [`SeedableRng`] trait. Any method may be used, +//! but note that `seed_from_u64` is not suitable for usage where security is +//! important. Some suggestions: +//! +//! 1. With a fresh seed, **direct from the OS** (implies a syscall): +//! ``` +//! # use {rand_core::SeedableRng, rand_chacha::ChaCha12Rng}; +//! let rng = ChaCha12Rng::from_os_rng(); +//! # let _: ChaCha12Rng = rng; +//! ``` +//! 2. **From a master generator.** This could be [`rand::rng`] +//! (effectively a fresh seed without the need for a syscall on each usage) +//! or a deterministic generator such as [`ChaCha20Rng`]. +//! Beware that should a weak master generator be used, correlations may be +//! detectable between the outputs of its child generators. +//! ```ignore +//! let rng = ChaCha12Rng::from_rng(&mut rand::rng()); +//! ``` +//! +//! See also [Seeding RNGs] in the book. +//! +//! ## Generation +//! +//! Generators implement [`RngCore`], whose methods may be used directly to +//! generate unbounded integer or byte values. +//! ``` +//! use rand_core::{SeedableRng, RngCore}; +//! use rand_chacha::ChaCha12Rng; +//! +//! let mut rng = ChaCha12Rng::from_seed(Default::default()); +//! let x = rng.next_u64(); +//! assert_eq!(x, 0x53f955076a9af49b); +//! ``` +//! +//! It is often more convenient to use the [`rand::Rng`] trait, which provides +//! further functionality. See also the [Random Values] chapter in the book. +//! +//! [ChaCha stream ciphers]: https://cr.yp.to/chacha.html +//! [Reproducibility]: https://rust-random.github.io/book/crate-reprod.html +//! [Seeding RNGs]: https://rust-random.github.io/book/guide-seeding.html +//! [Security]: https://rust-random.github.io/book/guide-rngs.html#security +//! [Random Values]: https://rust-random.github.io/book/guide-values.html +//! [`BlockRngCore`]: rand_core::block::BlockRngCore +//! [`RngCore`]: rand_core::RngCore +//! [`SeedableRng`]: rand_core::SeedableRng +//! [`SeedableRng::from_os_rng`]: rand_core::SeedableRng::from_os_rng +//! [`rand::rng`]: https://docs.rs/rand/latest/rand/fn.rng.html +//! [`rand::Rng`]: https://docs.rs/rand/latest/rand/trait.Rng.html + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![forbid(unsafe_code)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(not(feature = "std"), no_std)] + +pub use rand_core; + +mod chacha; +mod guts; + +pub use crate::chacha::{ + ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng, +}; + +/// ChaCha with 20 rounds +pub type ChaChaRng = ChaCha20Rng; +/// ChaCha with 20 rounds, low-level interface +pub type ChaChaCore = ChaCha20Core; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"1a43bf9751b54237d9a1e3e049f26917c3010adaecbecc6185fbee6f2af8034d","CHANGELOG.md":"01ed6dbeab8975c68fd08e14f3579a964ad7579efa60998e70848cc3b6862647","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.lock":"016a63ba469879c3dc6a9fc1aea95f5a522914101a9cd7ee2c91a59c32cb6b33","Cargo.toml":"88d9db5184a8b48028072059c1fdd54ba7fcdadac452ebdadbfc16f7f50790ad","Cargo.toml.orig":"8a7c1c4a260fdcc9d1d63b979835322ba761b2029028dd0596da72ae9756c16f","LICENSE-APACHE":"6df43f6f4b5d4587f3d8d71e45532c688fd168afa5fe89d571cb32fa09c4ef51","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"dfb6edf96c969676326324b06c63db3732995675192268e2f8390cc7f579ce9e","src/block.rs":"105cb275cd8f38f5d4f51ea574beb2263ae1d510a8b1737a41d8d622f730ddbb","src/impls.rs":"145ec30e733af5aa0fd8556a706aa932723de45cfa964aacf284bc59e951ca5a","src/le.rs":"e1d01e111ce8d2b6fdc8c85e1fcf400b490b302db5c5f32e040c5b9e6b528013","src/lib.rs":"d72f3328eb8ddd4a289a38ec8dfe61ced7d59c4c1b65ffb61c251e42d9e165ef","src/os.rs":"10ef59c924aa6286b4ded0dd03086fb1b6b0b7a2fd106aada70d3270ee135fea"},"package":"99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "340849e53b71da0f15af448d10511c2e62e50ba1" + }, + "path_in_vcs": "rand_core" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/rand_core/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.9.3] — 2025-02-29 +### Other +- Remove `zerocopy` dependency (#1607) +- Deprecate `rand_core::impls::fill_via_u32_chunks`, `fill_via_u64_chunks` (#1607) + +## [0.9.2] - 2025-02-22 +### API changes +- Relax `Sized` bound on impls of `TryRngCore`, `TryCryptoRng` and `UnwrapMut` (#1593) +- Add `UnwrapMut::re` to reborrow the inner rng with a tighter lifetime (#1595) + +## [0.9.1] - 2025-02-16 +### API changes +- Add `TryRngCore::unwrap_mut`, providing an impl of `RngCore` over `&mut rng` (#1589) + +## [0.9.0] - 2025-01-27 +### Dependencies and features +- Bump the MSRV to 1.63.0 (#1207, #1246, #1269, #1341, #1416, #1536); note that 1.60.0 may work for dependents when using `--ignore-rust-version` +- Update to `getrandom` v0.3.0 (#1558) +- Use `zerocopy` to replace some `unsafe` code (#1349, #1393, #1446, #1502) +- Rename feature `serde1` to `serde` (#1477) +- Rename feature `getrandom` to `os_rng` (#1537) + +### API changes +- Allow `rand_core::impls::fill_via_u*_chunks` to mutate source (#1182) +- Add fn `RngCore::read_adapter` implementing `std::io::Read` (#1267) +- Add trait `CryptoBlockRng: BlockRngCore`; make `trait CryptoRng: RngCore` replacing `CryptoRngCore` (#1273) +- Add traits `TryRngCore`, `TryCryptoRng` (#1424, #1499) +- Rename `fn SeedableRng::from_rng` -> `try_from_rng` and add infallible variant `fn from_rng` (#1424) +- Rename `fn SeedableRng::from_entropy` -> `from_os_rng` and add fallible variant `fn try_from_os_rng` (#1424) +- Add bounds `Clone` and `AsRef` to associated type `SeedableRng::Seed` (#1491) + +## [0.6.4] - 2022-09-15 +- Fix unsoundness in `::next_u32` (#1160) +- Reduce use of `unsafe` and improve gen_bytes performance (#1180) +- Add `CryptoRngCore` trait (#1187, #1230) + +## [0.6.3] - 2021-06-15 +### Changed +- Improved bound for `serde` impls on `BlockRng` (#1130) +- Minor doc additions (#1118) + +## [0.6.2] - 2021-02-12 +### Fixed +- Fixed assertions in `le::read_u32_into` and `le::read_u64_into` which could + have allowed buffers not to be fully populated (#1096) + +## [0.6.1] - 2021-01-03 +### Fixed +- Avoid panic when using `RngCore::seed_from_u64` with a seed which is not a + multiple of four (#1082) +### Other +- Enable all stable features in the playground (#1081) + +## [0.6.0] - 2020-12-08 +### Breaking changes +- Bump MSRV to 1.36, various code improvements (#1011) +- Update to getrandom v0.2 (#1041) +- Fix: `next_u32_via_fill` and `next_u64_via_fill` now use LE as documented (#1061) + +### Other +- Reduce usage of `unsafe` (#962, #963, #1011) +- Annotate feature-gates in documentation (#1019) +- Document available error codes (#1061) +- Various documentation tweaks +- Fix some clippy warnings (#1036) +- Apply rustfmt (#926) + +## [0.5.1] - 2019-08-28 +- `OsRng` added to `rand_core` (#863) +- `Error::INTERNAL_START` and `Error::CUSTOM_START` constants (#864) +- `Error::raw_os_error` method (#864) +- `Debug` and `Display` formatting for `getrandom` error codes without `std` (#864) +### Changed +- `alloc` feature in `no_std` is available since Rust 1.36 (#856) +- Added `#[inline]` to `Error` conversion methods (#864) + +## [0.5.0] - 2019-06-06 +### Changed +- Enable testing with Miri and fix incorrect pointer usages (#779, #780, #781, #783, #784) +- Rewrite `Error` type and adjust API (#800) +- Adjust usage of `#[inline]` for `BlockRng` and `BlockRng64` + +## [0.4.0] - 2019-01-24 +### Changed +- Disable the `std` feature by default (#702) + +## [0.3.0] - 2018-09-24 +### Added +- Add `SeedableRng::seed_from_u64` for convenient seeding. (#537) + +## [0.2.1] - 2018-06-08 +### Added +- References to a `CryptoRng` now also implement `CryptoRng`. (#470) + +## [0.2.0] - 2018-05-21 +### Changed +- Enable the `std` feature by default. (#409) +- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public +- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419) +### Added +- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419) +- Implement `std::io::Read` for RngCore. (#434) + +## [0.1.0] - 2018-04-17 +(Split out of the Rand crate, changes here are relative to rand 0.4.2.) +### Added +- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288) +- Add modules to help implementing RNGs `impl` and `le`. (#209, #228) +- Add `Error` and `ErrorKind`. (#225) +- Add `CryptoRng` marker trait. (#273) +- Add `BlockRngCore` trait. (#281) +- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325) +- Add `RngCore::try_fill_bytes`. (#225) +### Changed +- Revise the `SeedableRng` trait. (#233) +- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288) + +## [0.0.1] - 2017-09-14 (yanked) +Experimental version as part of the rand crate refactor. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/COPYRIGHT clamav-1.4.6+dfsg/.cargo/vendor/rand_core/COPYRIGHT --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/COPYRIGHT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/COPYRIGHT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,178 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,67 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63" +name = "rand_core" +version = "0.9.3" +authors = [ + "The Rand Project Developers", + "The Rust Project Developers", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Core random number generator traits and tools for implementation. +""" +homepage = "https://rust-random.github.io/book" +documentation = "https://docs.rs/rand_core" +readme = "README.md" +keywords = [ + "random", + "rng", +] +categories = [ + "algorithms", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.playground] +all-features = true + +[features] +os_rng = ["dep:getrandom"] +serde = ["dep:serde"] +std = ["getrandom?/std"] + +[lib] +name = "rand_core" +path = "src/lib.rs" + +[dependencies.getrandom] +version = "0.3.0" +optional = true + +[dependencies.serde] +version = "1" +features = ["derive"] +optional = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +name = "rand_core" +version = "0.9.3" +authors = ["The Rand Project Developers", "The Rust Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-random/rand" +documentation = "https://docs.rs/rand_core" +homepage = "https://rust-random.github.io/book" +description = """ +Core random number generator traits and tools for implementation. +""" +keywords = ["random", "rng"] +categories = ["algorithms", "no-std"] +edition = "2021" +rust-version = "1.63" + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --no-deps --open +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.playground] +all-features = true + +[features] +std = ["getrandom?/std"] +os_rng = ["dep:getrandom"] +serde = ["dep:serde"] # enables serde for BlockRng wrapper + +[dependencies] +serde = { version = "1", features = ["derive"], optional = true } +getrandom = { version = "0.3.0", optional = true } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,187 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/README.md clamav-1.4.6+dfsg/.cargo/vendor/rand_core/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +# rand_core + +[![Test Status](https://github.com/rust-random/rand/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Latest version](https://img.shields.io/crates/v/rand_core.svg)](https://crates.io/crates/rand_core) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_core) +[![API](https://docs.rs/rand_core/badge.svg)](https://docs.rs/rand_core) + +Core traits and error types of the [rand] library, plus tools for implementing +RNGs. + +This crate is intended for use when implementing the core trait, `RngCore`; it +defines the core traits to be implemented as well as several small functions to +aid in their implementation and types required for error handling. + +The main [rand] crate re-exports most items defined in this crate, along with +tools to convert the integer samples generated by `RngCore` to many different +applications (including sampling from restricted ranges, conversion to floating +point, list permutations and secure initialisation of RNGs). Most users should +prefer to use the main [rand] crate. + +Links: + +- [API documentation (master)](https://rust-random.github.io/rand/rand_core) +- [API documentation (docs.rs)](https://docs.rs/rand_core) +- [Changelog](https://github.com/rust-random/rand/blob/master/rand_core/CHANGELOG.md) + +[rand]: https://crates.io/crates/rand + + +## Functionality + +The `rand_core` crate provides: + +- base random number generator traits +- error-reporting types +- functionality to aid implementation of RNGs + +The traits and error types are also available via `rand`. + +## Versions + +The current version is: + +```toml +rand_core = "0.9.0" +``` + + +# License + +`rand_core` is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/block.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/block.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/block.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/block.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,534 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The `BlockRngCore` trait and implementation helpers +//! +//! The [`BlockRngCore`] trait exists to assist in the implementation of RNGs +//! which generate a block of data in a cache instead of returning generated +//! values directly. +//! +//! Usage of this trait is optional, but provides two advantages: +//! implementations only need to concern themselves with generation of the +//! block, not the various [`RngCore`] methods (especially [`fill_bytes`], where +//! the optimal implementations are not trivial), and this allows +//! `ReseedingRng` (see [`rand`](https://docs.rs/rand) crate) perform periodic +//! reseeding with very low overhead. +//! +//! # Example +//! +//! ```no_run +//! use rand_core::{RngCore, SeedableRng}; +//! use rand_core::block::{BlockRngCore, BlockRng}; +//! +//! struct MyRngCore; +//! +//! impl BlockRngCore for MyRngCore { +//! type Item = u32; +//! type Results = [u32; 16]; +//! +//! fn generate(&mut self, results: &mut Self::Results) { +//! unimplemented!() +//! } +//! } +//! +//! impl SeedableRng for MyRngCore { +//! type Seed = [u8; 32]; +//! fn from_seed(seed: Self::Seed) -> Self { +//! unimplemented!() +//! } +//! } +//! +//! // optionally, also implement CryptoBlockRng for MyRngCore +//! +//! // Final RNG. +//! let mut rng = BlockRng::::seed_from_u64(0); +//! println!("First value: {}", rng.next_u32()); +//! ``` +//! +//! [`BlockRngCore`]: crate::block::BlockRngCore +//! [`fill_bytes`]: RngCore::fill_bytes + +use crate::impls::fill_via_chunks; +use crate::{CryptoRng, RngCore, SeedableRng, TryRngCore}; +use core::fmt; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A trait for RNGs which do not generate random numbers individually, but in +/// blocks (typically `[u32; N]`). This technique is commonly used by +/// cryptographic RNGs to improve performance. +/// +/// See the [module][crate::block] documentation for details. +pub trait BlockRngCore { + /// Results element type, e.g. `u32`. + type Item; + + /// Results type. This is the 'block' an RNG implementing `BlockRngCore` + /// generates, which will usually be an array like `[u32; 16]`. + type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default; + + /// Generate a new block of results. + fn generate(&mut self, results: &mut Self::Results); +} + +/// A marker trait used to indicate that an [`RngCore`] implementation is +/// supposed to be cryptographically secure. +/// +/// See [`CryptoRng`] docs for more information. +pub trait CryptoBlockRng: BlockRngCore {} + +/// A wrapper type implementing [`RngCore`] for some type implementing +/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement +/// a full RNG from just a `generate` function. +/// +/// The `core` field may be accessed directly but the results buffer may not. +/// PRNG implementations can simply use a type alias +/// (`pub type MyRng = BlockRng;`) but might prefer to use a +/// wrapper type (`pub struct MyRng(BlockRng);`); the latter must +/// re-implement `RngCore` but hides the implementation details and allows +/// extra functionality to be defined on the RNG +/// (e.g. `impl MyRng { fn set_stream(...){...} }`). +/// +/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods +/// reading values from the results buffer, as well as +/// calling [`BlockRngCore::generate`] directly on the output array when +/// [`fill_bytes`] is called on a large array. These methods also handle +/// the bookkeeping of when to generate a new batch of values. +/// +/// No whole generated `u32` values are thrown away and all values are consumed +/// in-order. [`next_u32`] simply takes the next available `u32` value. +/// [`next_u64`] is implemented by combining two `u32` values, least +/// significant first. [`fill_bytes`] consume a whole number of `u32` values, +/// converting each `u32` to a byte slice in little-endian order. If the requested byte +/// length is not a multiple of 4, some bytes will be discarded. +/// +/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is +/// no direct support for other buffer types. +/// +/// For easy initialization `BlockRng` also implements [`SeedableRng`]. +/// +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +/// [`fill_bytes`]: RngCore::fill_bytes +#[derive(Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "serde", + serde( + bound = "for<'x> R: Serialize + Deserialize<'x>, for<'x> R::Results: Serialize + Deserialize<'x>" + ) +)] +pub struct BlockRng { + results: R::Results, + index: usize, + /// The *core* part of the RNG, implementing the `generate` function. + pub core: R, +} + +// Custom Debug implementation that does not expose the contents of `results`. +impl fmt::Debug for BlockRng { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BlockRng") + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .finish() + } +} + +impl BlockRng { + /// Create a new `BlockRng` from an existing RNG implementing + /// `BlockRngCore`. Results will be generated on first use. + #[inline] + pub fn new(core: R) -> BlockRng { + let results_empty = R::Results::default(); + BlockRng { + core, + index: results_empty.as_ref().len(), + results: results_empty, + } + } + + /// Get the index into the result buffer. + /// + /// If this is equal to or larger than the size of the result buffer then + /// the buffer is "empty" and `generate()` must be called to produce new + /// results. + #[inline(always)] + pub fn index(&self) -> usize { + self.index + } + + /// Reset the number of available results. + /// This will force a new set of results to be generated on next use. + #[inline] + pub fn reset(&mut self) { + self.index = self.results.as_ref().len(); + } + + /// Generate a new set of results immediately, setting the index to the + /// given value. + #[inline] + pub fn generate_and_set(&mut self, index: usize) { + assert!(index < self.results.as_ref().len()); + self.core.generate(&mut self.results); + self.index = index; + } +} + +impl> RngCore for BlockRng { + #[inline] + fn next_u32(&mut self) -> u32 { + if self.index >= self.results.as_ref().len() { + self.generate_and_set(0); + } + + let value = self.results.as_ref()[self.index]; + self.index += 1; + value + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let read_u64 = |results: &[u32], index| { + let data = &results[index..=index + 1]; + (u64::from(data[1]) << 32) | u64::from(data[0]) + }; + + let len = self.results.as_ref().len(); + + let index = self.index; + if index < len - 1 { + self.index += 2; + // Read an u64 from the current index + read_u64(self.results.as_ref(), index) + } else if index >= len { + self.generate_and_set(2); + read_u64(self.results.as_ref(), 0) + } else { + let x = u64::from(self.results.as_ref()[len - 1]); + self.generate_and_set(1); + let y = u64::from(self.results.as_ref()[0]); + (y << 32) | x + } + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + let mut read_len = 0; + while read_len < dest.len() { + if self.index >= self.results.as_ref().len() { + self.generate_and_set(0); + } + let (consumed_u32, filled_u8) = + fill_via_chunks(&self.results.as_mut()[self.index..], &mut dest[read_len..]); + + self.index += consumed_u32; + read_len += filled_u8; + } + } +} + +impl SeedableRng for BlockRng { + type Seed = R::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + Self::new(R::from_seed(seed)) + } + + #[inline(always)] + fn seed_from_u64(seed: u64) -> Self { + Self::new(R::seed_from_u64(seed)) + } + + #[inline(always)] + fn from_rng(rng: &mut impl RngCore) -> Self { + Self::new(R::from_rng(rng)) + } + + #[inline(always)] + fn try_from_rng(rng: &mut S) -> Result { + R::try_from_rng(rng).map(Self::new) + } +} + +impl> CryptoRng for BlockRng {} + +/// A wrapper type implementing [`RngCore`] for some type implementing +/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement +/// a full RNG from just a `generate` function. +/// +/// This is similar to [`BlockRng`], but specialized for algorithms that operate +/// on `u64` values. +/// +/// No whole generated `u64` values are thrown away and all values are consumed +/// in-order. [`next_u64`] simply takes the next available `u64` value. +/// [`next_u32`] is however a bit special: half of a `u64` is consumed, leaving +/// the other half in the buffer. If the next function called is [`next_u32`] +/// then the other half is then consumed, however both [`next_u64`] and +/// [`fill_bytes`] discard the rest of any half-consumed `u64`s when called. +/// +/// [`fill_bytes`] consumes a whole number of `u64` values. If the requested length +/// is not a multiple of 8, some bytes will be discarded. +/// +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +/// [`fill_bytes`]: RngCore::fill_bytes +#[derive(Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct BlockRng64 { + results: R::Results, + index: usize, + half_used: bool, // true if only half of the previous result is used + /// The *core* part of the RNG, implementing the `generate` function. + pub core: R, +} + +// Custom Debug implementation that does not expose the contents of `results`. +impl fmt::Debug for BlockRng64 { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BlockRng64") + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .field("half_used", &self.half_used) + .finish() + } +} + +impl BlockRng64 { + /// Create a new `BlockRng` from an existing RNG implementing + /// `BlockRngCore`. Results will be generated on first use. + #[inline] + pub fn new(core: R) -> BlockRng64 { + let results_empty = R::Results::default(); + BlockRng64 { + core, + index: results_empty.as_ref().len(), + half_used: false, + results: results_empty, + } + } + + /// Get the index into the result buffer. + /// + /// If this is equal to or larger than the size of the result buffer then + /// the buffer is "empty" and `generate()` must be called to produce new + /// results. + #[inline(always)] + pub fn index(&self) -> usize { + self.index + } + + /// Reset the number of available results. + /// This will force a new set of results to be generated on next use. + #[inline] + pub fn reset(&mut self) { + self.index = self.results.as_ref().len(); + self.half_used = false; + } + + /// Generate a new set of results immediately, setting the index to the + /// given value. + #[inline] + pub fn generate_and_set(&mut self, index: usize) { + assert!(index < self.results.as_ref().len()); + self.core.generate(&mut self.results); + self.index = index; + self.half_used = false; + } +} + +impl> RngCore for BlockRng64 { + #[inline] + fn next_u32(&mut self) -> u32 { + let mut index = self.index - self.half_used as usize; + if index >= self.results.as_ref().len() { + self.core.generate(&mut self.results); + self.index = 0; + index = 0; + // `self.half_used` is by definition `false` + self.half_used = false; + } + + let shift = 32 * (self.half_used as usize); + + self.half_used = !self.half_used; + self.index += self.half_used as usize; + + (self.results.as_ref()[index] >> shift) as u32 + } + + #[inline] + fn next_u64(&mut self) -> u64 { + if self.index >= self.results.as_ref().len() { + self.core.generate(&mut self.results); + self.index = 0; + } + + let value = self.results.as_ref()[self.index]; + self.index += 1; + self.half_used = false; + value + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + let mut read_len = 0; + self.half_used = false; + while read_len < dest.len() { + if self.index >= self.results.as_ref().len() { + self.core.generate(&mut self.results); + self.index = 0; + } + + let (consumed_u64, filled_u8) = + fill_via_chunks(&self.results.as_mut()[self.index..], &mut dest[read_len..]); + + self.index += consumed_u64; + read_len += filled_u8; + } + } +} + +impl SeedableRng for BlockRng64 { + type Seed = R::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + Self::new(R::from_seed(seed)) + } + + #[inline(always)] + fn seed_from_u64(seed: u64) -> Self { + Self::new(R::seed_from_u64(seed)) + } + + #[inline(always)] + fn from_rng(rng: &mut impl RngCore) -> Self { + Self::new(R::from_rng(rng)) + } + + #[inline(always)] + fn try_from_rng(rng: &mut S) -> Result { + R::try_from_rng(rng).map(Self::new) + } +} + +impl> CryptoRng for BlockRng64 {} + +#[cfg(test)] +mod test { + use crate::block::{BlockRng, BlockRng64, BlockRngCore}; + use crate::{RngCore, SeedableRng}; + + #[derive(Debug, Clone)] + struct DummyRng { + counter: u32, + } + + impl BlockRngCore for DummyRng { + type Item = u32; + type Results = [u32; 16]; + + fn generate(&mut self, results: &mut Self::Results) { + for r in results { + *r = self.counter; + self.counter = self.counter.wrapping_add(3511615421); + } + } + } + + impl SeedableRng for DummyRng { + type Seed = [u8; 4]; + + fn from_seed(seed: Self::Seed) -> Self { + DummyRng { + counter: u32::from_le_bytes(seed), + } + } + } + + #[test] + fn blockrng_next_u32_vs_next_u64() { + let mut rng1 = BlockRng::::from_seed([1, 2, 3, 4]); + let mut rng2 = rng1.clone(); + let mut rng3 = rng1.clone(); + + let mut a = [0; 16]; + a[..4].copy_from_slice(&rng1.next_u32().to_le_bytes()); + a[4..12].copy_from_slice(&rng1.next_u64().to_le_bytes()); + a[12..].copy_from_slice(&rng1.next_u32().to_le_bytes()); + + let mut b = [0; 16]; + b[..4].copy_from_slice(&rng2.next_u32().to_le_bytes()); + b[4..8].copy_from_slice(&rng2.next_u32().to_le_bytes()); + b[8..].copy_from_slice(&rng2.next_u64().to_le_bytes()); + assert_eq!(a, b); + + let mut c = [0; 16]; + c[..8].copy_from_slice(&rng3.next_u64().to_le_bytes()); + c[8..12].copy_from_slice(&rng3.next_u32().to_le_bytes()); + c[12..].copy_from_slice(&rng3.next_u32().to_le_bytes()); + assert_eq!(a, c); + } + + #[derive(Debug, Clone)] + struct DummyRng64 { + counter: u64, + } + + impl BlockRngCore for DummyRng64 { + type Item = u64; + type Results = [u64; 8]; + + fn generate(&mut self, results: &mut Self::Results) { + for r in results { + *r = self.counter; + self.counter = self.counter.wrapping_add(2781463553396133981); + } + } + } + + impl SeedableRng for DummyRng64 { + type Seed = [u8; 8]; + + fn from_seed(seed: Self::Seed) -> Self { + DummyRng64 { + counter: u64::from_le_bytes(seed), + } + } + } + + #[test] + fn blockrng64_next_u32_vs_next_u64() { + let mut rng1 = BlockRng64::::from_seed([1, 2, 3, 4, 5, 6, 7, 8]); + let mut rng2 = rng1.clone(); + let mut rng3 = rng1.clone(); + + let mut a = [0; 16]; + a[..4].copy_from_slice(&rng1.next_u32().to_le_bytes()); + a[4..12].copy_from_slice(&rng1.next_u64().to_le_bytes()); + a[12..].copy_from_slice(&rng1.next_u32().to_le_bytes()); + + let mut b = [0; 16]; + b[..4].copy_from_slice(&rng2.next_u32().to_le_bytes()); + b[4..8].copy_from_slice(&rng2.next_u32().to_le_bytes()); + b[8..].copy_from_slice(&rng2.next_u64().to_le_bytes()); + assert_ne!(a, b); + assert_eq!(&a[..4], &b[..4]); + assert_eq!(&a[4..12], &b[8..]); + + let mut c = [0; 16]; + c[..8].copy_from_slice(&rng3.next_u64().to_le_bytes()); + c[8..12].copy_from_slice(&rng3.next_u32().to_le_bytes()); + c[12..].copy_from_slice(&rng3.next_u32().to_le_bytes()); + assert_eq!(b, c); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/impls.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Helper functions for implementing `RngCore` functions. +//! +//! For cross-platform reproducibility, these functions all use Little Endian: +//! least-significant part first. For example, `next_u64_via_u32` takes `u32` +//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32` +//! from `next_u64` in little-endian order, one should use `next_u64() as u32`. +//! +//! Byte-swapping (like the std `to_le` functions) is only needed to convert +//! to/from byte sequences, and since its purpose is reproducibility, +//! non-reproducible sources (e.g. `OsRng`) need not bother with it. + +use crate::RngCore; + +/// Implement `next_u64` via `next_u32`, little-endian order. +pub fn next_u64_via_u32(rng: &mut R) -> u64 { + // Use LE; we explicitly generate one value before the next. + let x = u64::from(rng.next_u32()); + let y = u64::from(rng.next_u32()); + (y << 32) | x +} + +/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order. +/// +/// The fastest way to fill a slice is usually to work as long as possible with +/// integers. That is why this method mostly uses `next_u64`, and only when +/// there are 4 or less bytes remaining at the end of the slice it uses +/// `next_u32` once. +pub fn fill_bytes_via_next(rng: &mut R, dest: &mut [u8]) { + let mut left = dest; + while left.len() >= 8 { + let (l, r) = { left }.split_at_mut(8); + left = r; + let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); + l.copy_from_slice(&chunk); + } + let n = left.len(); + if n > 4 { + let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); + left.copy_from_slice(&chunk[..n]); + } else if n > 0 { + let chunk: [u8; 4] = rng.next_u32().to_le_bytes(); + left.copy_from_slice(&chunk[..n]); + } +} + +pub(crate) trait Observable: Copy { + type Bytes: Sized + AsRef<[u8]>; + fn to_le_bytes(self) -> Self::Bytes; +} +impl Observable for u32 { + type Bytes = [u8; 4]; + + fn to_le_bytes(self) -> Self::Bytes { + Self::to_le_bytes(self) + } +} +impl Observable for u64 { + type Bytes = [u8; 8]; + + fn to_le_bytes(self) -> Self::Bytes { + Self::to_le_bytes(self) + } +} + +/// Fill dest from src +/// +/// Returns `(n, byte_len)`. `src[..n]` is consumed, +/// `dest[..byte_len]` is filled. `src[n..]` and `dest[byte_len..]` are left +/// unaltered. +pub(crate) fn fill_via_chunks(src: &[T], dest: &mut [u8]) -> (usize, usize) { + let size = core::mem::size_of::(); + + // Always use little endian for portability of results. + + let mut dest = dest.chunks_exact_mut(size); + let mut src = src.iter(); + + let zipped = dest.by_ref().zip(src.by_ref()); + let num_chunks = zipped.len(); + zipped.for_each(|(dest, src)| dest.copy_from_slice(src.to_le_bytes().as_ref())); + + let byte_len = num_chunks * size; + if let Some(src) = src.next() { + // We have consumed all full chunks of dest, but not src. + let dest = dest.into_remainder(); + let n = dest.len(); + if n > 0 { + dest.copy_from_slice(&src.to_le_bytes().as_ref()[..n]); + return (num_chunks + 1, byte_len + n); + } + } + (num_chunks, byte_len) +} + +/// Implement `fill_bytes` by reading chunks from the output buffer of a block +/// based RNG. +/// +/// The return values are `(consumed_u32, filled_u8)`. +/// +/// `src` is not modified; it is taken as a `&mut` reference for backward +/// compatibility with previous versions that did change it. +/// +/// `filled_u8` is the number of filled bytes in `dest`, which may be less than +/// the length of `dest`. +/// `consumed_u32` is the number of words consumed from `src`, which is the same +/// as `filled_u8 / 4` rounded up. +/// +/// # Example +/// (from `IsaacRng`) +/// +/// ```ignore +/// fn fill_bytes(&mut self, dest: &mut [u8]) { +/// let mut read_len = 0; +/// while read_len < dest.len() { +/// if self.index >= self.rsl.len() { +/// self.isaac(); +/// } +/// +/// let (consumed_u32, filled_u8) = +/// impls::fill_via_u32_chunks(&mut self.rsl[self.index..], +/// &mut dest[read_len..]); +/// +/// self.index += consumed_u32; +/// read_len += filled_u8; +/// } +/// } +/// ``` +#[deprecated(since = "0.9.3", note = "use BlockRng instead")] +pub fn fill_via_u32_chunks(src: &mut [u32], dest: &mut [u8]) -> (usize, usize) { + fill_via_chunks(src, dest) +} + +/// Implement `fill_bytes` by reading chunks from the output buffer of a block +/// based RNG. +/// +/// The return values are `(consumed_u64, filled_u8)`. +/// +/// `src` is not modified; it is taken as a `&mut` reference for backward +/// compatibility with previous versions that did change it. +/// +/// `filled_u8` is the number of filled bytes in `dest`, which may be less than +/// the length of `dest`. +/// `consumed_u64` is the number of words consumed from `src`, which is the same +/// as `filled_u8 / 8` rounded up. +/// +/// See `fill_via_u32_chunks` for an example. +#[deprecated(since = "0.9.3", note = "use BlockRng64 instead")] +pub fn fill_via_u64_chunks(src: &mut [u64], dest: &mut [u8]) -> (usize, usize) { + fill_via_chunks(src, dest) +} + +/// Implement `next_u32` via `fill_bytes`, little-endian order. +pub fn next_u32_via_fill(rng: &mut R) -> u32 { + let mut buf = [0; 4]; + rng.fill_bytes(&mut buf); + u32::from_le_bytes(buf) +} + +/// Implement `next_u64` via `fill_bytes`, little-endian order. +pub fn next_u64_via_fill(rng: &mut R) -> u64 { + let mut buf = [0; 8]; + rng.fill_bytes(&mut buf); + u64::from_le_bytes(buf) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_fill_via_u32_chunks() { + let src_orig = [1u32, 2, 3]; + + let mut src = src_orig; + let mut dst = [0u8; 11]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (3, 11)); + assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]); + + let mut src = src_orig; + let mut dst = [0u8; 13]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (3, 12)); + assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]); + + let mut src = src_orig; + let mut dst = [0u8; 5]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (2, 5)); + assert_eq!(dst, [1, 0, 0, 0, 2]); + } + + #[test] + fn test_fill_via_u64_chunks() { + let src_orig = [1u64, 2]; + + let mut src = src_orig; + let mut dst = [0u8; 11]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (2, 11)); + assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]); + + let mut src = src_orig; + let mut dst = [0u8; 17]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (2, 16)); + assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]); + + let mut src = src_orig; + let mut dst = [0u8; 5]; + assert_eq!(fill_via_chunks(&mut src, &mut dst), (1, 5)); + assert_eq!(dst, [1, 0, 0, 0, 0]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/le.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/le.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/le.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/le.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Little-Endian utilities +//! +//! Little-Endian order has been chosen for internal usage; this makes some +//! useful functions available. + +/// Reads unsigned 32 bit integers from `src` into `dst`. +/// +/// # Panics +/// +/// If `dst` has insufficient space (`4*dst.len() < src.len()`). +#[inline] +#[track_caller] +pub fn read_u32_into(src: &[u8], dst: &mut [u32]) { + assert!(src.len() >= 4 * dst.len()); + for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(4)) { + *out = u32::from_le_bytes(chunk.try_into().unwrap()); + } +} + +/// Reads unsigned 64 bit integers from `src` into `dst`. +/// +/// # Panics +/// +/// If `dst` has insufficient space (`8*dst.len() < src.len()`). +#[inline] +#[track_caller] +pub fn read_u64_into(src: &[u8], dst: &mut [u64]) { + assert!(src.len() >= 8 * dst.len()); + for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(8)) { + *out = u64::from_le_bytes(chunk.try_into().unwrap()); + } +} + +#[test] +fn test_read() { + let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + + let mut buf = [0u32; 4]; + read_u32_into(&bytes, &mut buf); + assert_eq!(buf[0], 0x04030201); + assert_eq!(buf[3], 0x100F0E0D); + + let mut buf = [0u32; 3]; + read_u32_into(&bytes[1..13], &mut buf); // unaligned + assert_eq!(buf[0], 0x05040302); + assert_eq!(buf[2], 0x0D0C0B0A); + + let mut buf = [0u64; 2]; + read_u64_into(&bytes, &mut buf); + assert_eq!(buf[0], 0x0807060504030201); + assert_eq!(buf[1], 0x100F0E0D0C0B0A09); + + let mut buf = [0u64; 1]; + read_u64_into(&bytes[7..15], &mut buf); // unaligned + assert_eq!(buf[0], 0x0F0E0D0C0B0A0908); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,771 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2017-2018 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Random number generation traits +//! +//! This crate is mainly of interest to crates publishing implementations of +//! [`RngCore`]. Other users are encouraged to use the [`rand`] crate instead +//! which re-exports the main traits and error types. +//! +//! [`RngCore`] is the core trait implemented by algorithmic pseudo-random number +//! generators and external random-number sources. +//! +//! [`SeedableRng`] is an extension trait for construction from fixed seeds and +//! other random number generators. +//! +//! The [`impls`] and [`le`] sub-modules include a few small functions to assist +//! implementation of [`RngCore`]. +//! +//! [`rand`]: https://docs.rs/rand + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![no_std] + +#[cfg(feature = "std")] +extern crate std; + +use core::{fmt, ops::DerefMut}; + +pub mod block; +pub mod impls; +pub mod le; +#[cfg(feature = "os_rng")] +mod os; + +#[cfg(feature = "os_rng")] +pub use os::{OsError, OsRng}; + +/// Implementation-level interface for RNGs +/// +/// This trait encapsulates the low-level functionality common to all +/// generators, and is the "back end", to be implemented by generators. +/// End users should normally use the [`rand::Rng`] trait +/// which is automatically implemented for every type implementing `RngCore`. +/// +/// Three different methods for generating random data are provided since the +/// optimal implementation of each is dependent on the type of generator. There +/// is no required relationship between the output of each; e.g. many +/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64` +/// values and drop any remaining unused bytes. The same can happen with the +/// [`next_u32`] and [`next_u64`] methods, implementations may discard some +/// random bits for efficiency. +/// +/// Implementers should produce bits uniformly. Pathological RNGs (e.g. always +/// returning the same value, or never setting certain bits) can break rejection +/// sampling used by random distributions, and also break other RNGs when +/// seeding them via [`SeedableRng::from_rng`]. +/// +/// Algorithmic generators implementing [`SeedableRng`] should normally have +/// *portable, reproducible* output, i.e. fix Endianness when converting values +/// to avoid platform differences, and avoid making any changes which affect +/// output (except by communicating that the release has breaking changes). +/// +/// Typically an RNG will implement only one of the methods available +/// in this trait directly, then use the helper functions from the +/// [`impls`] module to implement the other methods. +/// +/// Note that implementors of [`RngCore`] also automatically implement +/// the [`TryRngCore`] trait with the `Error` associated type being +/// equal to [`Infallible`]. +/// +/// It is recommended that implementations also implement: +/// +/// - `Debug` with a custom implementation which *does not* print any internal +/// state (at least, [`CryptoRng`]s should not risk leaking state through +/// `Debug`). +/// - `Serialize` and `Deserialize` (from Serde), preferably making Serde +/// support optional at the crate level in PRNG libs. +/// - `Clone`, if possible. +/// - *never* implement `Copy` (accidental copies may cause repeated values). +/// - *do not* implement `Default` for pseudorandom generators, but instead +/// implement [`SeedableRng`], to guide users towards proper seeding. +/// External / hardware RNGs can choose to implement `Default`. +/// - `Eq` and `PartialEq` could be implemented, but are probably not useful. +/// +/// # Example +/// +/// A simple example, obviously not generating very *random* output: +/// +/// ``` +/// #![allow(dead_code)] +/// use rand_core::{RngCore, impls}; +/// +/// struct CountingRng(u64); +/// +/// impl RngCore for CountingRng { +/// fn next_u32(&mut self) -> u32 { +/// self.next_u64() as u32 +/// } +/// +/// fn next_u64(&mut self) -> u64 { +/// self.0 += 1; +/// self.0 +/// } +/// +/// fn fill_bytes(&mut self, dst: &mut [u8]) { +/// impls::fill_bytes_via_next(self, dst) +/// } +/// } +/// ``` +/// +/// [`rand::Rng`]: https://docs.rs/rand/latest/rand/trait.Rng.html +/// [`fill_bytes`]: RngCore::fill_bytes +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +/// [`Infallible`]: core::convert::Infallible +pub trait RngCore { + /// Return the next random `u32`. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// using `self.next_u64() as u32` or via [`impls::next_u32_via_fill`]. + fn next_u32(&mut self) -> u32; + + /// Return the next random `u64`. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// via [`impls::next_u64_via_u32`] or via [`impls::next_u64_via_fill`]. + fn next_u64(&mut self) -> u64; + + /// Fill `dest` with random data. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// via [`impls::fill_bytes_via_next`]. + /// + /// This method should guarantee that `dest` is entirely filled + /// with new data, and may panic if this is impossible + /// (e.g. reading past the end of a file that is being used as the + /// source of randomness). + fn fill_bytes(&mut self, dst: &mut [u8]); +} + +impl RngCore for T +where + T::Target: RngCore, +{ + #[inline] + fn next_u32(&mut self) -> u32 { + self.deref_mut().next_u32() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.deref_mut().next_u64() + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + self.deref_mut().fill_bytes(dst); + } +} + +/// A marker trait over [`RngCore`] for securely unpredictable RNGs +/// +/// This marker trait indicates that the implementing generator is intended, +/// when correctly seeded and protected from side-channel attacks such as a +/// leaking of state, to be a cryptographically secure generator. This trait is +/// provided as a tool to aid review of cryptographic code, but does not by +/// itself guarantee suitability for cryptographic applications. +/// +/// Implementors of `CryptoRng` automatically implement the [`TryCryptoRng`] +/// trait. +/// +/// Implementors of `CryptoRng` should only implement [`Default`] if the +/// `default()` instances are themselves secure generators: for example if the +/// implementing type is a stateless interface over a secure external generator +/// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed. +/// +/// Formally, a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) +/// should satisfy an additional property over other generators: assuming that +/// the generator has been appropriately seeded and has unknown state, then +/// given the first *k* bits of an algorithm's output +/// sequence, it should not be possible using polynomial-time algorithms to +/// predict the next bit with probability significantly greater than 50%. +/// +/// An optional property of CSPRNGs is backtracking resistance: if the CSPRNG's +/// state is revealed, it will not be computationally-feasible to reconstruct +/// prior output values. This property is not required by `CryptoRng`. +pub trait CryptoRng: RngCore {} + +impl CryptoRng for T where T::Target: CryptoRng {} + +/// A potentially fallible variant of [`RngCore`] +/// +/// This trait is a generalization of [`RngCore`] to support potentially- +/// fallible IO-based generators such as [`OsRng`]. +/// +/// All implementations of [`RngCore`] automatically support this `TryRngCore` +/// trait, using [`Infallible`][core::convert::Infallible] as the associated +/// `Error` type. +/// +/// An implementation of this trait may be made compatible with code requiring +/// an [`RngCore`] through [`TryRngCore::unwrap_err`]. The resulting RNG will +/// panic in case the underlying fallible RNG yields an error. +pub trait TryRngCore { + /// The type returned in the event of a RNG error. + type Error: fmt::Debug + fmt::Display; + + /// Return the next random `u32`. + fn try_next_u32(&mut self) -> Result; + /// Return the next random `u64`. + fn try_next_u64(&mut self) -> Result; + /// Fill `dest` entirely with random data. + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error>; + + /// Wrap RNG with the [`UnwrapErr`] wrapper. + fn unwrap_err(self) -> UnwrapErr + where + Self: Sized, + { + UnwrapErr(self) + } + + /// Wrap RNG with the [`UnwrapMut`] wrapper. + fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self> { + UnwrapMut(self) + } + + /// Convert an [`RngCore`] to a [`RngReadAdapter`]. + #[cfg(feature = "std")] + fn read_adapter(&mut self) -> RngReadAdapter<'_, Self> + where + Self: Sized, + { + RngReadAdapter { inner: self } + } +} + +// Note that, unfortunately, this blanket impl prevents us from implementing +// `TryRngCore` for types which can be dereferenced to `TryRngCore`, i.e. `TryRngCore` +// will not be automatically implemented for `&mut R`, `Box`, etc. +impl TryRngCore for R { + type Error = core::convert::Infallible; + + #[inline] + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u32()) + } + + #[inline] + fn try_next_u64(&mut self) -> Result { + Ok(self.next_u64()) + } + + #[inline] + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> { + self.fill_bytes(dst); + Ok(()) + } +} + +/// A marker trait over [`TryRngCore`] for securely unpredictable RNGs +/// +/// This trait is like [`CryptoRng`] but for the trait [`TryRngCore`]. +/// +/// This marker trait indicates that the implementing generator is intended, +/// when correctly seeded and protected from side-channel attacks such as a +/// leaking of state, to be a cryptographically secure generator. This trait is +/// provided as a tool to aid review of cryptographic code, but does not by +/// itself guarantee suitability for cryptographic applications. +/// +/// Implementors of `TryCryptoRng` should only implement [`Default`] if the +/// `default()` instances are themselves secure generators: for example if the +/// implementing type is a stateless interface over a secure external generator +/// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed. +pub trait TryCryptoRng: TryRngCore {} + +impl TryCryptoRng for R {} + +/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`] +/// by panicking on potential errors. +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)] +pub struct UnwrapErr(pub R); + +impl RngCore for UnwrapErr { + #[inline] + fn next_u32(&mut self) -> u32 { + self.0.try_next_u32().unwrap() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.0.try_next_u64().unwrap() + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + self.0.try_fill_bytes(dst).unwrap() + } +} + +impl CryptoRng for UnwrapErr {} + +/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`] +/// by panicking on potential errors. +#[derive(Debug, Eq, PartialEq, Hash)] +pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R); + +impl<'r, R: TryRngCore + ?Sized> UnwrapMut<'r, R> { + /// Reborrow with a new lifetime + /// + /// Rust allows references like `&T` or `&mut T` to be "reborrowed" through + /// coercion: essentially, the pointer is copied under a new, shorter, lifetime. + /// Until rfcs#1403 lands, reborrows on user types require a method call. + #[inline(always)] + pub fn re<'b>(&'b mut self) -> UnwrapMut<'b, R> + where + 'r: 'b, + { + UnwrapMut(self.0) + } +} + +impl RngCore for UnwrapMut<'_, R> { + #[inline] + fn next_u32(&mut self) -> u32 { + self.0.try_next_u32().unwrap() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.0.try_next_u64().unwrap() + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + self.0.try_fill_bytes(dst).unwrap() + } +} + +impl CryptoRng for UnwrapMut<'_, R> {} + +/// A random number generator that can be explicitly seeded. +/// +/// This trait encapsulates the low-level functionality common to all +/// pseudo-random number generators (PRNGs, or algorithmic generators). +/// +/// A generator implementing `SeedableRng` will usually be deterministic, but +/// beware that portability and reproducibility of results **is not implied**. +/// Refer to documentation of the generator, noting that generators named after +/// a specific algorithm are usually tested for reproducibility against a +/// reference vector, while `SmallRng` and `StdRng` specifically opt out of +/// reproducibility guarantees. +/// +/// [`rand`]: https://docs.rs/rand +pub trait SeedableRng: Sized { + /// Seed type, which is restricted to types mutably-dereferenceable as `u8` + /// arrays (we recommend `[u8; N]` for some `N`). + /// + /// It is recommended to seed PRNGs with a seed of at least circa 100 bits, + /// which means an array of `[u8; 12]` or greater to avoid picking RNGs with + /// partially overlapping periods. + /// + /// For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`. + /// + /// + /// # Implementing `SeedableRng` for RNGs with large seeds + /// + /// Note that [`Default`] is not implemented for large arrays `[u8; N]` with + /// `N` > 32. To be able to implement the traits required by `SeedableRng` + /// for RNGs with such large seeds, the newtype pattern can be used: + /// + /// ``` + /// use rand_core::SeedableRng; + /// + /// const N: usize = 64; + /// #[derive(Clone)] + /// pub struct MyRngSeed(pub [u8; N]); + /// # #[allow(dead_code)] + /// pub struct MyRng(MyRngSeed); + /// + /// impl Default for MyRngSeed { + /// fn default() -> MyRngSeed { + /// MyRngSeed([0; N]) + /// } + /// } + /// + /// impl AsRef<[u8]> for MyRngSeed { + /// fn as_ref(&self) -> &[u8] { + /// &self.0 + /// } + /// } + /// + /// impl AsMut<[u8]> for MyRngSeed { + /// fn as_mut(&mut self) -> &mut [u8] { + /// &mut self.0 + /// } + /// } + /// + /// impl SeedableRng for MyRng { + /// type Seed = MyRngSeed; + /// + /// fn from_seed(seed: MyRngSeed) -> MyRng { + /// MyRng(seed) + /// } + /// } + /// ``` + type Seed: Clone + Default + AsRef<[u8]> + AsMut<[u8]>; + + /// Create a new PRNG using the given seed. + /// + /// PRNG implementations are allowed to assume that bits in the seed are + /// well distributed. That means usually that the number of one and zero + /// bits are roughly equal, and values like 0, 1 and (size - 1) are unlikely. + /// Note that many non-cryptographic PRNGs will show poor quality output + /// if this is not adhered to. If you wish to seed from simple numbers, use + /// `seed_from_u64` instead. + /// + /// All PRNG implementations should be reproducible unless otherwise noted: + /// given a fixed `seed`, the same sequence of output should be produced + /// on all runs, library versions and architectures (e.g. check endianness). + /// Any "value-breaking" changes to the generator should require bumping at + /// least the minor version and documentation of the change. + /// + /// It is not required that this function yield the same state as a + /// reference implementation of the PRNG given equivalent seed; if necessary + /// another constructor replicating behaviour from a reference + /// implementation can be added. + /// + /// PRNG implementations should make sure `from_seed` never panics. In the + /// case that some special values (like an all zero seed) are not viable + /// seeds it is preferable to map these to alternative constant value(s), + /// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad + /// seed"). This is assuming only a small number of values must be rejected. + fn from_seed(seed: Self::Seed) -> Self; + + /// Create a new PRNG using a `u64` seed. + /// + /// This is a convenience-wrapper around `from_seed` to allow construction + /// of any `SeedableRng` from a simple `u64` value. It is designed such that + /// low Hamming Weight numbers like 0 and 1 can be used and should still + /// result in good, independent seeds to the PRNG which is returned. + /// + /// This **is not suitable for cryptography**, as should be clear given that + /// the input size is only 64 bits. + /// + /// Implementations for PRNGs *may* provide their own implementations of + /// this function, but the default implementation should be good enough for + /// all purposes. *Changing* the implementation of this function should be + /// considered a value-breaking change. + fn seed_from_u64(mut state: u64) -> Self { + // We use PCG32 to generate a u32 sequence, and copy to the seed + fn pcg32(state: &mut u64) -> [u8; 4] { + const MUL: u64 = 6364136223846793005; + const INC: u64 = 11634580027462260723; + + // We advance the state first (to get away from the input value, + // in case it has low Hamming Weight). + *state = state.wrapping_mul(MUL).wrapping_add(INC); + let state = *state; + + // Use PCG output function with to_le to generate x: + let xorshifted = (((state >> 18) ^ state) >> 27) as u32; + let rot = (state >> 59) as u32; + let x = xorshifted.rotate_right(rot); + x.to_le_bytes() + } + + let mut seed = Self::Seed::default(); + let mut iter = seed.as_mut().chunks_exact_mut(4); + for chunk in &mut iter { + chunk.copy_from_slice(&pcg32(&mut state)); + } + let rem = iter.into_remainder(); + if !rem.is_empty() { + rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]); + } + + Self::from_seed(seed) + } + + /// Create a new PRNG seeded from an infallible `Rng`. + /// + /// This may be useful when needing to rapidly seed many PRNGs from a master + /// PRNG, and to allow forking of PRNGs. It may be considered deterministic. + /// + /// The master PRNG should be at least as high quality as the child PRNGs. + /// When seeding non-cryptographic child PRNGs, we recommend using a + /// different algorithm for the master PRNG (ideally a CSPRNG) to avoid + /// correlations between the child PRNGs. If this is not possible (e.g. + /// forking using small non-crypto PRNGs) ensure that your PRNG has a good + /// mixing function on the output or consider use of a hash function with + /// `from_seed`. + /// + /// Note that seeding `XorShiftRng` from another `XorShiftRng` provides an + /// extreme example of what can go wrong: the new PRNG will be a clone + /// of the parent. + /// + /// PRNG implementations are allowed to assume that a good RNG is provided + /// for seeding, and that it is cryptographically secure when appropriate. + /// As of `rand` 0.7 / `rand_core` 0.5, implementations overriding this + /// method should ensure the implementation satisfies reproducibility + /// (in prior versions this was not required). + /// + /// [`rand`]: https://docs.rs/rand + fn from_rng(rng: &mut impl RngCore) -> Self { + let mut seed = Self::Seed::default(); + rng.fill_bytes(seed.as_mut()); + Self::from_seed(seed) + } + + /// Create a new PRNG seeded from a potentially fallible `Rng`. + /// + /// See [`from_rng`][SeedableRng::from_rng] docs for more information. + fn try_from_rng(rng: &mut R) -> Result { + let mut seed = Self::Seed::default(); + rng.try_fill_bytes(seed.as_mut())?; + Ok(Self::from_seed(seed)) + } + + /// Creates a new instance of the RNG seeded via [`getrandom`]. + /// + /// This method is the recommended way to construct non-deterministic PRNGs + /// since it is convenient and secure. + /// + /// Note that this method may panic on (extremely unlikely) [`getrandom`] errors. + /// If it's not desirable, use the [`try_from_os_rng`] method instead. + /// + /// In case the overhead of using [`getrandom`] to seed *many* PRNGs is an + /// issue, one may prefer to seed from a local PRNG, e.g. + /// `from_rng(rand::rng()).unwrap()`. + /// + /// # Panics + /// + /// If [`getrandom`] is unable to provide secure entropy this method will panic. + /// + /// [`getrandom`]: https://docs.rs/getrandom + /// [`try_from_os_rng`]: SeedableRng::try_from_os_rng + #[cfg(feature = "os_rng")] + fn from_os_rng() -> Self { + match Self::try_from_os_rng() { + Ok(res) => res, + Err(err) => panic!("from_os_rng failed: {}", err), + } + } + + /// Creates a new instance of the RNG seeded via [`getrandom`] without unwrapping + /// potential [`getrandom`] errors. + /// + /// In case the overhead of using [`getrandom`] to seed *many* PRNGs is an + /// issue, one may prefer to seed from a local PRNG, e.g. + /// `from_rng(&mut rand::rng()).unwrap()`. + /// + /// [`getrandom`]: https://docs.rs/getrandom + #[cfg(feature = "os_rng")] + fn try_from_os_rng() -> Result { + let mut seed = Self::Seed::default(); + getrandom::fill(seed.as_mut())?; + let res = Self::from_seed(seed); + Ok(res) + } +} + +/// Adapter that enables reading through a [`io::Read`](std::io::Read) from a [`RngCore`]. +/// +/// # Examples +/// +/// ```no_run +/// # use std::{io, io::Read}; +/// # use std::fs::File; +/// # use rand_core::{OsRng, TryRngCore}; +/// +/// io::copy(&mut OsRng.read_adapter().take(100), &mut File::create("/tmp/random.bytes").unwrap()).unwrap(); +/// ``` +#[cfg(feature = "std")] +pub struct RngReadAdapter<'a, R: TryRngCore + ?Sized> { + inner: &'a mut R, +} + +#[cfg(feature = "std")] +impl std::io::Read for RngReadAdapter<'_, R> { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + self.inner.try_fill_bytes(buf).map_err(|err| { + std::io::Error::new(std::io::ErrorKind::Other, std::format!("RNG error: {err}")) + })?; + Ok(buf.len()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for RngReadAdapter<'_, R> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ReadAdapter").finish() + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_seed_from_u64() { + struct SeedableNum(u64); + impl SeedableRng for SeedableNum { + type Seed = [u8; 8]; + + fn from_seed(seed: Self::Seed) -> Self { + let mut x = [0u64; 1]; + le::read_u64_into(&seed, &mut x); + SeedableNum(x[0]) + } + } + + const N: usize = 8; + const SEEDS: [u64; N] = [0u64, 1, 2, 3, 4, 8, 16, -1i64 as u64]; + let mut results = [0u64; N]; + for (i, seed) in SEEDS.iter().enumerate() { + let SeedableNum(x) = SeedableNum::seed_from_u64(*seed); + results[i] = x; + } + + for (i1, r1) in results.iter().enumerate() { + let weight = r1.count_ones(); + // This is the binomial distribution B(64, 0.5), so chance of + // weight < 20 is binocdf(19, 64, 0.5) = 7.8e-4, and same for + // weight > 44. + assert!((20..=44).contains(&weight)); + + for (i2, r2) in results.iter().enumerate() { + if i1 == i2 { + continue; + } + let diff_weight = (r1 ^ r2).count_ones(); + assert!(diff_weight >= 20); + } + } + + // value-breakage test: + assert_eq!(results[0], 5029875928683246316); + } + + // A stub RNG. + struct SomeRng; + + impl RngCore for SomeRng { + fn next_u32(&mut self) -> u32 { + unimplemented!() + } + fn next_u64(&mut self) -> u64 { + unimplemented!() + } + fn fill_bytes(&mut self, _: &mut [u8]) { + unimplemented!() + } + } + + impl CryptoRng for SomeRng {} + + #[test] + fn dyn_rngcore_to_tryrngcore() { + // Illustrates the need for `+ ?Sized` bound in `impl TryRngCore for R`. + + // A method in another crate taking a fallible RNG + fn third_party_api(_rng: &mut (impl TryRngCore + ?Sized)) -> bool { + true + } + + // A method in our crate requiring an infallible RNG + fn my_api(rng: &mut dyn RngCore) -> bool { + // We want to call the method above + third_party_api(rng) + } + + assert!(my_api(&mut SomeRng)); + } + + #[test] + fn dyn_cryptorng_to_trycryptorng() { + // Illustrates the need for `+ ?Sized` bound in `impl TryCryptoRng for R`. + + // A method in another crate taking a fallible RNG + fn third_party_api(_rng: &mut (impl TryCryptoRng + ?Sized)) -> bool { + true + } + + // A method in our crate requiring an infallible RNG + fn my_api(rng: &mut dyn CryptoRng) -> bool { + // We want to call the method above + third_party_api(rng) + } + + assert!(my_api(&mut SomeRng)); + } + + #[test] + fn dyn_unwrap_mut_tryrngcore() { + // Illustrates the need for `+ ?Sized` bound in + // `impl RngCore for UnwrapMut<'_, R>`. + + fn third_party_api(_rng: &mut impl RngCore) -> bool { + true + } + + fn my_api(rng: &mut (impl TryRngCore + ?Sized)) -> bool { + let mut infallible_rng = rng.unwrap_mut(); + third_party_api(&mut infallible_rng) + } + + assert!(my_api(&mut SomeRng)); + } + + #[test] + fn dyn_unwrap_mut_trycryptorng() { + // Illustrates the need for `+ ?Sized` bound in + // `impl CryptoRng for UnwrapMut<'_, R>`. + + fn third_party_api(_rng: &mut impl CryptoRng) -> bool { + true + } + + fn my_api(rng: &mut (impl TryCryptoRng + ?Sized)) -> bool { + let mut infallible_rng = rng.unwrap_mut(); + third_party_api(&mut infallible_rng) + } + + assert!(my_api(&mut SomeRng)); + } + + #[test] + fn reborrow_unwrap_mut() { + struct FourRng; + + impl TryRngCore for FourRng { + type Error = core::convert::Infallible; + fn try_next_u32(&mut self) -> Result { + Ok(4) + } + fn try_next_u64(&mut self) -> Result { + unimplemented!() + } + fn try_fill_bytes(&mut self, _: &mut [u8]) -> Result<(), Self::Error> { + unimplemented!() + } + } + + let mut rng = FourRng; + let mut rng = rng.unwrap_mut(); + + assert_eq!(rng.next_u32(), 4); + let mut rng2 = rng.re(); + assert_eq!(rng2.next_u32(), 4); + drop(rng2); + assert_eq!(rng.next_u32(), 4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/os.rs clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/os.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rand_core/src/os.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rand_core/src/os.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,115 @@ +// Copyright 2019 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Interface to the random number generator of the operating system. + +use crate::{TryCryptoRng, TryRngCore}; + +/// An interface over the operating-system's random data source +/// +/// This is a zero-sized struct. It can be freely constructed with just `OsRng`. +/// +/// The implementation is provided by the [getrandom] crate. Refer to +/// [getrandom] documentation for details. +/// +/// This struct is available as `rand_core::OsRng` and as `rand::rngs::OsRng`. +/// In both cases, this requires the crate feature `os_rng` or `std` +/// (enabled by default in `rand` but not in `rand_core`). +/// +/// # Blocking and error handling +/// +/// It is possible that when used during early boot the first call to `OsRng` +/// will block until the system's RNG is initialised. It is also possible +/// (though highly unlikely) for `OsRng` to fail on some platforms, most +/// likely due to system mis-configuration. +/// +/// After the first successful call, it is highly unlikely that failures or +/// significant delays will occur (although performance should be expected to +/// be much slower than a user-space +/// [PRNG](https://rust-random.github.io/book/guide-gen.html#pseudo-random-number-generators)). +/// +/// # Usage example +/// ``` +/// use rand_core::{TryRngCore, OsRng}; +/// +/// let mut key = [0u8; 16]; +/// OsRng.try_fill_bytes(&mut key).unwrap(); +/// let random_u64 = OsRng.try_next_u64().unwrap(); +/// ``` +/// +/// [getrandom]: https://crates.io/crates/getrandom +#[derive(Clone, Copy, Debug, Default)] +pub struct OsRng; + +/// Error type of [`OsRng`] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OsError(getrandom::Error); + +impl core::fmt::Display for OsError { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.0.fmt(f) + } +} + +// NOTE: this can use core::error::Error from rustc 1.81.0 +#[cfg(feature = "std")] +impl std::error::Error for OsError { + #[inline] + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + std::error::Error::source(&self.0) + } +} + +impl OsError { + /// Extract the raw OS error code (if this error came from the OS) + /// + /// This method is identical to [`std::io::Error::raw_os_error()`][1], except + /// that it works in `no_std` contexts. If this method returns `None`, the + /// error value can still be formatted via the `Display` implementation. + /// + /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error + #[inline] + pub fn raw_os_error(self) -> Option { + self.0.raw_os_error() + } +} + +impl TryRngCore for OsRng { + type Error = OsError; + + #[inline] + fn try_next_u32(&mut self) -> Result { + getrandom::u32().map_err(OsError) + } + + #[inline] + fn try_next_u64(&mut self) -> Result { + getrandom::u64().map_err(OsError) + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> { + getrandom::fill(dest).map_err(OsError) + } +} + +impl TryCryptoRng for OsRng {} + +#[test] +fn test_os_rng() { + let x = OsRng.try_next_u64().unwrap(); + let y = OsRng.try_next_u64().unwrap(); + assert!(x != 0); + assert!(x != y); +} + +#[test] +fn test_construction() { + assert!(OsRng.try_next_u64().unwrap() != 0); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"85602e63910f3124f137a8d704c391e6943580af1456a28e9f6cd961a5960692","Cargo.lock":"8430018ef14a8af6e47ae13698abab174a24da8ca4e0adcf254dd8bdd2b0bcbc","Cargo.toml":"31addb537f320450c199e4e4154c785ad563fe31ebd4c475228dc11743b6dd60","Cargo.toml.orig":"1ebf698989fc1817e6c61f4293dea634cf5823f48c6bfccb615248257819a565","LICENSE":"2dd0a109751e939dec3f80ddcfbc1ba91553f18c574399e85c159632182a2c0a","PATENTS":"7b14a70c194b19dbd0625e7eac839a63200f67484521ce5e8d8244b127e8907a","README.md":"af38ab2fd5dcfd8dca0ffc2a1dbf37650fdc563686303ff0653e887a12c55b85","build.rs":"762a52a53ca01a04d5c173619555391ec0d4029377d43e31a177d14bb0562add","cbindgen.toml":"ca078f7f8c18729789dc6038a9813788dad2b0c946043099e776ee00a815b5be","src/activity.rs":"bc281d4c0f7d3f7b296f3924a7c1ad1035a422deb4b617f5b654e56918828cc4","src/api/channel/by_gop.rs":"7ea801b7c16a1bdac5943489416610f2eb19daa08273e5cb6d06a40ca1f90db3","src/api/channel/data.rs":"db32726a476b9fc6d83f47097d5c39ffbd2db640005a2048d961df2172273026","src/api/channel/mod.rs":"1e287f8917cf2e9cd9945c1644ca89d932fd0f3835772639afb46303404040c6","src/api/color.rs":"dbdb6991cbe31d73f99e777d2fe85c377c85c874409b8d70b72e62037f65d493","src/api/config/encoder.rs":"8a32381eb32e53cdae07b35a3af235aa29f65783af3a1982c22bb91ae7c61118","src/api/config/mod.rs":"aef63f97ec2652a778dc7957dbf698dd6de923974eb85df099279a58cc2c20a6","src/api/config/rate.rs":"d8a9484058c7360745524377134525e63a1dba89df595417489750c1b5cb9e1f","src/api/config/speedsettings.rs":"c5cfb6333783f4c20e845775b1e7e69e84058445be7c4db0c3698f882ded2b22","src/api/context.rs":"5038317d7ac177f05cc76ec995a589b98031db8e67452c7527ad69494aab67f9","src/api/internal.rs":"1be58d127731162d0f075b2fe3112a6cf443b6ec3cb05ab1abf1de2025d0b277","src/api/lookahead.rs":"31075a2d62d7db027e904b899bcb38f491dc8ede848b22af8b39663578976b78","src/api/mod.rs":"b12ec065f4583f4391f657e4e522302444369b5154219f2fce72235e31edc792","src/api/test.rs":"d6e5351e6fd5fcc039dec6de1b0b3e58c4b2f0b6de2a0ff40d1420cd720b5ad8","src/api/util.rs":"5220b7e455975e5bfe0520fb0f3a14837f0c8a075f1d8c2f3e300174e01137ba","src/arm/32/cdef.S":"0c7c2ad0d576267d85c5c0cc6775e31bc3ffd7adeb6eac928d9b5601d212d18e","src/arm/32/cdef16.S":"a397f597e7a0df7ff57087e8ab45592957a0db14b8bed3189d31b8f8c6299626","src/arm/32/cdef_tmpl.S":"9c75cd2ba14437cc5fc4258b0b97ca49dfe2ce964132699ba2bc253d50f10e6f","src/arm/32/ipred.S":"07ac3d761f8b46eec0ffeae9e70b23377865f5e636c3092f9932cb611403f558","src/arm/32/ipred16.S":"2602b9591239418c1e7963dfee9ea977611b6e5c0ecc71236c1c4afd1ba5f590","src/arm/32/itx.S":"a15f1081d1c661947f808899c178efadab41c17b8ddc41f1c44694b7506f7fcf","src/arm/32/itx16.S":"9cbfd8a6d10a88b558deba60423d70dbbde8f9f7d888638e711834ef7f87c14c","src/arm/32/loopfilter.S":"869d4ef354bfd93bbcf319d2b71d33adda0119e94a0a635c7e76448f9422c286","src/arm/32/loopfilter16.S":"09f1a62b3e84303e57757b70c84d4f46809f1a441a3b75205891ffb1d8ddc54e","src/arm/32/looprestoration.S":"826a4278c85df33972c28fef2f9e015e9ab09a7740a77e748a13ff3fc944edc9","src/arm/32/looprestoration16.S":"6590a208c3d5fa13edf8e2f648502acf01979c3af7d67490198a61664aefecd4","src/arm/32/looprestoration_common.S":"41538ec1d4268d6f4f93ea2cfa497f70724d0fd42f12d04fc49a779a3b42bec2","src/arm/32/looprestoration_tmpl.S":"3be6cabcb382b0a252141742aab862f2cb75895b13efd5cf99a93f9fd87311ab","src/arm/32/mc.S":"7ffe9d05a08444147bd7b0ba28a321688e209c83892388a524a8b75ab0176cac","src/arm/32/mc16.S":"fd4befd70829dd10622e4108e8dc9ac73fa9dddc7abfe1dcececed25ffe6fbea","src/arm/32/msac.S":"0cce43c54b720a29becfbd35c6e686c1001e24e66e56f0ba757ade0c76072a3b","src/arm/32/util.S":"ba0d2364dcd5bb0e063962d3fe56a52137dddb225532a757a51d5c715ffbd712","src/arm/64/cdef.S":"88d048cbed93f168e1655d5189479efebb0fb3b7d7ac8c4f105e555e384cbdca","src/arm/64/cdef16.S":"a22e30a3f79c7e7f8fe0d6c1521688ada880e475762b66b41336edb7a6c850fa","src/arm/64/cdef_dist.S":"60386c253cfb7e578f78b27d6dab4925f85039acca35dcbecd0d9da43ac9af10","src/arm/64/cdef_tmpl.S":"a224dd66d158e486bd3752603b7b1caa90db8f03849da541193361cb2bf31ae8","src/arm/64/ipred.S":"2292f9e0037ea5f8a46fdd3d012f4f05a0f8116bd0d4ed6a5c4bc05b4f17fe82","src/arm/64/ipred16.S":"8a681b9fb25fa0f78b0b8adf3e8527c13b2ea1e70537bb42da9fdb51e6dfe77c","src/arm/64/itx.S":"22be700d4886624baf1d7d5d620b3f01fb05859da8fdf344b26227bbd1a13515","src/arm/64/itx16.S":"1c605e3ea097862a7d0c97ea78083809d4ae326a83b30639cc007634a68a70a0","src/arm/64/loopfilter.S":"c90d8c5acfe1062b5adf6c29033df6e218624e9531c1418b4dfe4f8705d26ac1","src/arm/64/loopfilter16.S":"f93fdcf7c3578263792d57b47000822cc91e7b9031ea74a7b196fc7e12319d51","src/arm/64/looprestoration.S":"f173ec2b5aeeb99c1c63a1be1f7cf009487acba51a96fd909e8e2bb76709f2aa","src/arm/64/looprestoration16.S":"52b39d42e7516b2e6256cdeea7d8dfe0ca3e5f6ee0fa345ea57295fc8b5c6d2a","src/arm/64/looprestoration_common.S":"4d13ecd163c1d2d9cedab49cceaf67442c62f22be9c9884bad651215b25af138","src/arm/64/looprestoration_tmpl.S":"371b81ad148f4dce18148a841fbc52b15598ec3e49e542d5dc31008e79e2aacb","src/arm/64/mc.S":"4d82376de792eac4f34e4cac8599ce395011f7d27afc2afa4c9a1f6979c2b0df","src/arm/64/mc16.S":"ea320b551a413e29379a48ee64c3496090e321bef71a40743b45772f2f856611","src/arm/64/msac.S":"aa04b23aeabff9cfc6b053f8a59efe1a75a51a4d411fec6e5ee5437c9d09d0ce","src/arm/64/sad.S":"aefb53f1677ba8d81c1c4a8236267833c7c1d2a190b73eaecf7f04203658e762","src/arm/64/satd.S":"3221832a83a0a5e362f02ccd9da9c6ed010e1ba5ecb34dc976a126b15a102e60","src/arm/64/sse.S":"fec315250b2a71a12914fd141e4dadd98caff84d08013c2ab37657f99a989b78","src/arm/64/util.S":"ea1071c166aefe19e5623f3b28da1e76a4d4a61e0fd1683fc6deb92005711e11","src/arm/asm.S":"8216de47bc1833967894d6c00fe1b113b0a4dc70f45cba8761ff6e1716420225","src/arm/tables.S":"e973944751290e6d93427a83c6ba7e3e45f9c5f132b8395ceb8307a9d90f3323","src/asm/aarch64/cdef.rs":"ef169497e9f7a33a968e596bd7e48edf5c01b647e22e21846b34af1001efd9f9","src/asm/aarch64/dist/cdef_dist.rs":"199a06c20c06ef8931be87d64676f971fca851875ad518977d564beed71b7156","src/asm/aarch64/dist/mod.rs":"76f78fb7bd7896ed6e7c3df064da2e74ae38ee4fc3ce84533e9d56a02c114925","src/asm/aarch64/dist/sse.rs":"87f7d2579079bdd85658e7c536ba14d1057d2e194950869c643d0b34cfb5cdb6","src/asm/aarch64/mc.rs":"80145b6446902904b0b9a86597e55d43fa3ce0d1bbeb8adc7e54bd2f834dc1cb","src/asm/aarch64/mod.rs":"f54b512053b4cb4da172852ac85f72130714ebe9f6421eb7954a7d2a4d943f5d","src/asm/aarch64/predict.rs":"b5dd538e8d46fb45295e23d132b04fa8ba8d6fbf906ed3c9c2f4f62b0b6a9f71","src/asm/aarch64/transform/forward.rs":"d68be3f2c5c98564bd086d42b5828403b4d0e802496fd85dab1151ecd4abea46","src/asm/aarch64/transform/inverse.rs":"4ff9cbbc063f8fb80daedc340c985aa694b0bfe04735aedb785d76633bf54244","src/asm/aarch64/transform/mod.rs":"5b52893717242f4ee8051d16f7f7345049f33a8b97fa602b9b17af94586bd19d","src/asm/mod.rs":"0da6e5c195bcf7958298cbbe679f491855e3e3bb502cf93f1f3f58a5ddc5e7ea","src/asm/shared/dist/cdef_dist.rs":"eca11f6dec46b35e921b9b07ff7038056b613ad99e0511c92c2a54ddb0350a1b","src/asm/shared/dist/mod.rs":"8e77eb8b5be582de767a716fc7d1c1e4833acbe043274e67cb20dfdc7ddf2697","src/asm/shared/dist/sse.rs":"80abcac5798c43089a4797eef1157f25236f7941fe0e610f72ea71305e822b99","src/asm/shared/mod.rs":"7bced4371532fd1751d72f61f5611455ba1d795a256e5b52c40bd6236dea0e76","src/asm/shared/predict.rs":"f6821cc1ecbba91565a717a50adb4e25833492bcb98f64121ac15aa02476e25b","src/asm/shared/transform/forward.rs":"1ea1e64cd2235afb43db61b4639f9c6d6d183b8528de879becf10ebdce6331b8","src/asm/shared/transform/inverse.rs":"60e5d84634aea275f7f460bcf78e193cc6c638010d493c0f717301e93bea2656","src/asm/shared/transform/mod.rs":"22847d27d8385e087ddb9bb39748ac92a967b9d5116659f93f5c1c0acd17ccc3","src/asm/x86/cdef.rs":"a69c1572ab3d5006c0a1451c2e05c79bf78c22b252ca2526d82aefdbf675ca92","src/asm/x86/dist/cdef_dist.rs":"8785a62277746b41108958c055a145426096ec673da3af87f937ce0eb0f18714","src/asm/x86/dist/mod.rs":"f300ced3a655b96d8e2e4e21adcc7dea19f6b69523499b82752522451fe04e3d","src/asm/x86/dist/sse.rs":"b312bfc47be197a7ff9e85b623eb3b1179a3a36652e0bc020b79ec6f93b74706","src/asm/x86/ec.rs":"00a70e0382c44ca6ff23d4bfdf0fa74f065c5f762457aba3855614a6643ec48e","src/asm/x86/lrf.rs":"3e6770b9b1ddd87d7b51c6d5395e6fa7e4d5abf4d975b9d6436b85cd138cdabc","src/asm/x86/mc.rs":"dfed707078edd97cadfa2a104d563ebf754f2a068fbd260de2a2ca1aaa4249bb","src/asm/x86/mod.rs":"5db417146cd3b6816190d77a19aa7e9b92738be1a03becc89f3c12ee56cce196","src/asm/x86/predict.rs":"02b9779fdae79572c062c8c5fea1dfe07df8d43996e97292b3708f402e1f892a","src/asm/x86/quantize.rs":"a76df4cd08fd6d3d78a9701ba9e1886634c0f38573079459211071abc250502c","src/asm/x86/transform/forward.rs":"460494346f955c9892132ca16118a5bd3f317b3bc3a6564c08ae71684e01f2c8","src/asm/x86/transform/inverse.rs":"a7b39213311a9bb9471ea4a3629f519c079b95725c47493f9b4c25e61794561a","src/asm/x86/transform/mod.rs":"05a4bcfc4aa5d7d14bd683062af65e691b2593d20d8e16d0a97fd3cae6e0ab89","src/bin/common.rs":"bc418dae3fe06ba94482d6e856e8f4fea55986ca1764a3c48a1a0fdda2e924dd","src/bin/decoder/mod.rs":"86d895153f62356a7556aee922521060afdfa26f991bdb49903b8abd615767d5","src/bin/decoder/y4m.rs":"3dda2daeac45f1120e5a0623c43e1b437decdfb1c9966e820d713e9644e234a0","src/bin/error.rs":"8a7a0bffbc605293edb9c50217c443a5024f9242f8ad027d7f7016f54d1ba042","src/bin/kv.rs":"dac8fb66f4cb2dffa3c71569a0548cd508feddcdfbb3efae62701bab1f4d41d8","src/bin/muxer/ivf.rs":"aa7e22b77b2f21a84bf98d39595079534e3e154f852ca1c7d2ef55fc8dd5fa4a","src/bin/muxer/mod.rs":"c5346fc34a0eb693f94a5a218f3e83444da010926505d7d95b9ab270e81ea0cb","src/bin/muxer/y4m.rs":"81f629b106ebb58f7132429f83d81bb8f1893a3462919b9c2234c25e9deb4e5f","src/bin/rav1e-ch.rs":"28849d70bb200293eb1f5ec14f47e7d694ce858af65f870577284da287cd42ce","src/bin/rav1e.rs":"e1f559ef29580ee746365db34495d257f220c639d669848281b4af9e4515f1f6","src/bin/stats.rs":"70ae58b4ec4aca17107e2a430e63e88ca2b390cf6577986e783e596372a2e836","src/capi.rs":"a80345e481df2ed9e2b37f847d5244dad6321cded278ba14b82aefdf66b85be7","src/cdef.rs":"adbc144187b9d7cadfab7f810e41b41f496354f258a9639c8967917dcab31716","src/context/block_unit.rs":"a8798d6e4672185b8789ace8db77333b891d022fbe2d7561aa6eb23e8f90e232","src/context/cdf_context.rs":"76a83810aaf04205e3baf197dfc56ebb952ea7d27d42ae4d099c70c7d6ef3788","src/context/frame_header.rs":"c165c208dbb15f8220d708969d59fc3059042e758067229c2bd08e389a48e225","src/context/mod.rs":"a43c16ee70ce87d64bad17263d7b4f1e79feb94013b6ae93bebca59f154ca330","src/context/partition_unit.rs":"08925978dfa6cdd12518afffdcd3e5919f796f91d401da1abb58f7597edb3230","src/context/superblock_unit.rs":"97258775dd799d6e4ac406fb1faeba3cf1fdb6343b51db59d37d1698dccd8315","src/context/transform_unit.rs":"de23c07ac61229735b9cb369e2f08892ea5e42a06ac8af517cef687a0333e0fa","src/cpu_features/aarch64.rs":"02d50b4ae0632fc616b694043a59a58f85741af22bcbaa921c5eaca00227e0a1","src/cpu_features/mod.rs":"53c7134896c1c32aebe913fd218761899df80348d7f4bc88bf12e40041717019","src/cpu_features/rust.rs":"4cbc50cbfb638e8cf1bfd5bdd31778a0210d41243a45d2abca626a2ba3ff0896","src/cpu_features/x86.rs":"8405bbc1be302637cc7d08131ac5f713bf8ec51d4a4702e6c770fe5498b723a4","src/deblock.rs":"45f4ebebbfc1f5b26738d665dbe8e1254cebf6d635191210f592d62e859e7845","src/dist.rs":"7b78fe925932d7c74ea2fc470c18f980ee0aad6ba1f7a33367256889a4c981c1","src/ec.rs":"034eaf1c417d6328b6737755578960fbd0d414dc35cd6005907666176d667956","src/encoder.rs":"8fa30c6e5ebe6c6de7932e0c684b69187f599601bd906bd6f41db17b630bb4c0","src/entropymode.rs":"1777b8ae349a3fc590d402df7cda77fc0b87903d9b87c7cff67e5ba1055dd80f","src/ext/x86/x86inc.asm":"895a17d18b987f63153ea16b5823923bcc72d1a14e57e2b6cc55e077b749fda7","src/frame/mod.rs":"0bdcb76bb73c0997b7c045ddb0ff99959eeb963bea9044952479c6c8009a41d6","src/frame/plane.rs":"289c8c14e0c485babe0348d318d6ce63e9371d13550f2ff71f5bef5efa9ded89","src/fuzzing.rs":"e99cebc328ff3da8a453985f2ffd5a01f46ae37dc1ea50c8d80524e8cfc53d76","src/header.rs":"e3b9ec942cb49a2e503558832988e92271b2212098837894acbafc2028cfc38a","src/levels.rs":"60a3ef6b160721832e08ddc096f1f51537a00595e0887b122ffc2bd6fca8db97","src/lib.rs":"939b04a462c1dc2f453841f680731b0dfb97c867f4485603d0fd36b1e07ee016","src/lrf.rs":"a4d9e7eceac54f14f15ae781c3195f0fa8c4e29b23653c83933d122cff9082b8","src/mc.rs":"2a720fa6410c6df450529d9d304a74d076176a536cd09be97f4b2a40230acaf6","src/me.rs":"925279b0d34f92dc3b03f813dc75bbd663cffc9961a947a531e0da61530113cd","src/partition.rs":"901034b0ef836d9c2bd6db4c172b516187061967e59ddecd7bc77d0eba6a5ee6","src/predict.rs":"9706bb7b4904e6f8c5f83af7680bbccde07e38b4fb9026a69279730fd869facb","src/quantize/mod.rs":"66992dbbc068d049f41f558ada6a3881a805b9c9515ebf353764cc95feb2f09f","src/quantize/tables.rs":"574d287308c00a4cd1283c1f13bae8ffe828e4df6ad3b6c4462ff83a7354abd3","src/rate.rs":"0d1128bc147be23ed2365b4af23e587f6843cc2ae4866d91e91abb6dfa490c7c","src/rdo.rs":"be57e8c9d281c64385cafcf34b339bd42404cbcf3b4e8d1a6d1bb83e180b5488","src/rdo_tables.rs":"8c85774b3764ab076ed0576d588328aba533a311e5ebeaeecda0399e2b09ef6b","src/recon_intra.rs":"81fe4af0fd6e8ae7bac7e39804d63c793cd58d09460766068992b217f06c67bc","src/scan_order.rs":"064860962127ec2d31527fac7d0db536eb53c8b9ba35fdee7c8fadf9778ca0ef","src/segmentation.rs":"7558a1e697ce84ec2747e6b5d7a83ad371d6783484820bf482f71350ee6f55b4","src/stats.rs":"2923f57c0c6347ab77692aac9cc6c972ffaed7b425ca85502a7ebe1d57709f32","src/test_encode_decode/aom.rs":"25a7417fc92b6401f77c8637c7bf7e7a2d3dc43362b8db33e95477eb424cc568","src/test_encode_decode/dav1d.rs":"78433d0e4e9fea76e206811e38588f2fc15ad7eee9a79af2969aa59bc53bf31a","src/test_encode_decode/mod.rs":"2a216bcdae60555231305b79a579d6c3c365baebb7c74d7b6d2a61f984ab043f","src/tiling/mod.rs":"ea61173cd5d80b7c640720a75c5c52fe52dabfc71f07f42195227251c52a4675","src/tiling/plane_region.rs":"53c3838ec4ac433878aeb6d6f69f25ce1e914dfc7b046ab30eb63dc98774f4d1","src/tiling/tile.rs":"18d206fac40a82427695411a94bbd3ab4cc53b679f9f8e07205ba906baf8ea3b","src/tiling/tile_blocks.rs":"60cad312c9830542b909dc94c0efe8d987eff46e406013e65312b2eda28a54ff","src/tiling/tile_motion_stats.rs":"ad44a810d8a93dc4b6014ac816a564ee2069338ee5069f049e63eb2de80db2f9","src/tiling/tile_restoration_state.rs":"467eff75d0a0a831490b8db89fd3445a7c1f665cb17fdb264c3c5bdccf3d9ebb","src/tiling/tile_state.rs":"1fe8f1c228597fcee91ca16c5919975cbe80af88ed2db01f461c05a5e3fa7d11","src/tiling/tiler.rs":"b75754231da2810672ee6d970dd3e96f19bacc724d0358768659f1689e76ff13","src/token_cdfs.rs":"22387744a11ccb13b153772a74aefedf83490fab56562025b5ac184567eb1a6b","src/transform/forward.rs":"74ba3be129375d2b948600bae1af4febfcc2cc287d1f1c05ddc6762af9a05e9a","src/transform/forward_shared.rs":"3563b3cfcd3150e95180d2ededc9ab745427efa8c0e3976ca61df18df6d83815","src/transform/inverse.rs":"da56383d0cbc939fbda7cb128bd40e45e028238ed3f0bb942027f225d4aeedb9","src/transform/mod.rs":"58066ac6768ddde8b562b3e5c520e0de7ac6c0577e2de4f0acb9633b55db757f","src/util/align.rs":"3ed7babe9bc18dc25a7a1ab096ff9446c01b35d4ea8bdae784c2c33ac2937421","src/util/cdf.rs":"079f9820dcb804dfa2808113a3b3cf1d1610711c5572cf6f8d20632a9b01e542","src/util/kmeans.rs":"e9d643d9ce03d1cc8c607e56e5c155debed333de56abd4a79671cf7831f9512f","src/util/logexp.rs":"564ad87e44e4c90a69d8529adff410be2dbf129bb0dcdebb4874762ea3f7fc27","src/util/mod.rs":"774a15174dd9f82095257663d58d5fb07ad690a6114c51df7aa97eca2e1ac739","src/util/pixel.rs":"500f7e570ff100055403cab269625a38248a9d56cf526ee3682f5c873848285a","src/util/uninit.rs":"e44b82a909e7524ec121bd5d00f67510c393a98fb1441e9f7dfa95548f1ad720","src/x86/cdef16_avx2.asm":"75c933d106e5b4b3a30328f48782cd9ec56dd257ad022ead8f097a1d984068a9","src/x86/cdef16_avx512.asm":"099cd48bd2fd438076eb3a13ce77c5d953fc62637133a7cea7760fa54d33402c","src/x86/cdef16_sse.asm":"7a26a75632b7e706559afd6bb8403fb12c16a6ab7e42dff5b834ee2301131089","src/x86/cdef_avx2.asm":"78eaabf9574e972130acb62d78201aba67a4f86dea8b06cad809d41dca67d242","src/x86/cdef_avx512.asm":"4d46aec9e4caaa9a1024b8526fe513862c90b63bf71080b2167ac9eeb71a6775","src/x86/cdef_dist.asm":"857a927de9c70266d60cfe3c440734a340c5a1f129834181c826e7eb006291a2","src/x86/cdef_rav1e.asm":"dd5e53c997d0d84cc9c0e107279c50b88ec0ee616b5d4167886a928c76db2d88","src/x86/cdef_sse.asm":"3a514dc4436fc9f4b98fd6400efb2f363751014f3c563499b7b991e0d1c0320a","src/x86/filmgrain16_avx2.asm":"04fb27d3ef041b6dfbdb111739cf5fdbc0e935395acd8088bf8258d3d7f79a99","src/x86/filmgrain16_avx512.asm":"2684873bc647256f4293ac2a0a9732e0bc811977ada6618d5ce01eda7da4d0fc","src/x86/filmgrain16_sse.asm":"9d3c7665094e151195ac95f90dd2392acdedfcf1eb928a14e5b4f29c68b60507","src/x86/filmgrain_avx2.asm":"6016117798157db9c0dd4c14126acc457aa89a984cdffe481013946302eea831","src/x86/filmgrain_avx512.asm":"54d7ce1cf1bc0bb6f335068b71a0c0139de65792b22efb110caa64b9987f96fc","src/x86/filmgrain_common.asm":"46a6dd29b16e9b73f112df5f63a2dae1dd904f9822e47f0bb261c54fd55c6375","src/x86/filmgrain_sse.asm":"cc9d305d26a8baa03d22453a0f41fbc06fd154280bbd39571e1c9915c98e3e1c","src/x86/ipred16_avx2.asm":"3b88114a337c5a922b5bd634151a7111e5da03be4a2a9d47084531f39662f22f","src/x86/ipred16_avx512.asm":"13a6004a48a140893222629fb958adc4e52b49328258a47bfa6e07713079640c","src/x86/ipred16_sse.asm":"f83b072f0a344e5b41165a928c214c44184564a0150c660ae2ea6d11bd2e6d68","src/x86/ipred_avx2.asm":"4f19fc54840a159ee0f8e2f893c6bf96ee0b68664ac5bde9a14c814433d9d2a4","src/x86/ipred_avx512.asm":"cce8dccfcb533eb740a97ed35c0e20596a98503b6f2c50c030036a2afe5e2355","src/x86/ipred_sse.asm":"7e56eefb41c26918b3e3d8bc1eee779a1e73909dad948e28411bc29907baa04e","src/x86/itx16_avx2.asm":"8c6444d5005172b37a950e7acb2542c767951d57039802ea3d182259f6653dd4","src/x86/itx16_avx512.asm":"ef828c2a9f749d5cb2ed87834ce0f85502ba6ac1e7eae988f81fc51cb5ae31f4","src/x86/itx16_sse.asm":"384aca209a05f135bf0ddb610d14f5034de4e5c8a39511c6792d7f392ae2e954","src/x86/itx_avx2.asm":"341bf6d0facd2f61a67f9f16df7481229136660706eb64f8a6f01d9b0513a4f9","src/x86/itx_avx512.asm":"ddc854c641c104ec40eeaf2fa30a8ea98d777ded78241ec38e2361b97af085c0","src/x86/itx_sse.asm":"b207ebb4cbf84809a1d18b7f2107a2ec1a47a3b6e0ec6f89d0a1d2c921aeef38","src/x86/loopfilter16_avx2.asm":"489af057a53adf51ff8cf917ede7f4e932378a2fec6bb5d6e9c14854ab6a9190","src/x86/loopfilter16_avx512.asm":"939c504a05cf4922904f8f49edd8249fc29d384b4b4de343cfefe7e38dcbc6de","src/x86/loopfilter16_sse.asm":"e0502f9c5f05b14f8dd6f766d93b0e76827b3548369c76f33541978ea5692224","src/x86/loopfilter_avx2.asm":"721d1dce99e310fc73095ed4ef6322ae4e838a0d0d452c2d13d46902549f3717","src/x86/loopfilter_avx512.asm":"1272a874381f443dfbb59a396af9ba3de77bca3b2e2d81ea1f1c13c96281085d","src/x86/loopfilter_sse.asm":"7eb8e2261b975fab158af640447337d512187a811190ab13907b8a34570dd464","src/x86/looprestoration16_avx2.asm":"222a8ba5f3101907bc9331976ac109179523edc9433fe01f8447a27fb60c176b","src/x86/looprestoration16_avx512.asm":"94e058764a67966df161f352c051031490e683a87113503fee8071ac61da5fcc","src/x86/looprestoration16_sse.asm":"f4c0fa43810fb266c84809d11812bd24e5dce164b7ef55ecb18fc85a10aa883d","src/x86/looprestoration_avx2.asm":"aa92bb7d15ed7691d54f8d44a29355599625eba624670270339ba31958bc837c","src/x86/looprestoration_avx512.asm":"a4c90a8e225d17b60e701d7669d1389ca66eeba7fa6c7dfff69232c95d02f269","src/x86/looprestoration_sse.asm":"5a94ecfce582617b86b9097073c1f348b53206ecdd201071ddfe4b6a56b3b583","src/x86/mc16_avx2.asm":"157b509d0af32f04a8566ce01fe77d2781d0ddb4da61a9a1a7d3fdfd89c9c313","src/x86/mc16_avx512.asm":"02405721f1b7f80b1ab39ea5cf8ce11bee4d8a3dd57a4077854e038a1f77cbfa","src/x86/mc16_sse.asm":"c4fc182fcf7410d7427c32048b636f71e64f563993218be841bbe412526d370d","src/x86/mc_avx2.asm":"dd05303afb6fc45a8ceb342caa7652a67a7d40c767fddc7a844b169b1a84494a","src/x86/mc_avx512.asm":"55b608ade5c97e0f842576909dcccf21c7c8e40b1f341f79f7089ee550104647","src/x86/mc_sse.asm":"1f155f6c46c4ea334ed42e22f501faf4ee09e6529d8ad2a9368330577ece4dd3","src/x86/me.asm":"419d7e18f4df3f23bcebffcaae847e4da4f5ff4f17f698452bc829d8c0545c17","src/x86/msac.asm":"2c591d8bbc8250f8ca627003cdbf20117f5c657555435c4f0b6cabea465b9743","src/x86/sad_avx.asm":"b499fc5a8cf7de1e9ec664708a4bb78f30496cb98dfb1bfd5da8306cef45f4d2","src/x86/sad_sse2.asm":"a1488f2661d5afabc01aa2556a0bcfc91c4f0655f463e9d5b515d4fdd702d0c7","src/x86/satd.asm":"59e25c8466e834d18ceab23ec00f574e2287153ae8e6a829997791b72ccc40af","src/x86/satd16_avx2.asm":"a837e6b72d29d79d5f09eebdd3ab01749fe3e8448675f5a8dc08ed71c778147a","src/x86/sse.asm":"7d9d446b004b7b49c9601c887ab0fbb48ef888d08e6666574ca198d8ddcfcd5d","src/x86/tables.asm":"bfd4c4525e49a54c9d06d26b560653a94cea28bdc729b3db8f05344b7a2d0200"},"package":"43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38806721f718e7ae6919e72385bc305bf824ef81" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2523 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", + "serde", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "aom-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "623675d7dbe1d65db81582231b0971384277a4dd2006763021ba2436e86f812d" +dependencies = [ + "bindgen", + "system-deps", +] + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "assert_cmd" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av-metrics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "996ce95bbdb0203e5b91d4a0c9b81c0d67d11c80f884482a0c1ea19e732e3530" +dependencies = [ + "crossbeam", + "itertools 0.10.5", + "lab", + "num-traits", + "rayon", + "thiserror 1.0.69", + "v_frame", +] + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.12", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 7.1.3", + "num-rational", + "serde", + "v_frame", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.9.1", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitstream-io" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afa0fc725d5ac9efc66f47b4c533ee850eb34aa6105681b5349c27157346ffa" +dependencies = [ + "core2", +] + +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" +dependencies = [ + "git2", +] + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "git2" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" +dependencies = [ + "bitflags 2.9.1", + "libc", + "libgit2-sys", + "log", + "url", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "ivf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eedcbbb31f4e9f46566c543c0fb00b8f87ff9d88ba1a011aa262a5a1a2a505" +dependencies = [ + "bitstream-io", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libdav1d-sys" +version = "0.7.1+libdav1d.1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d875e9669d116a603412a126de599b7bf47789a365b79fcf461fbf9c18d141f" +dependencies = [ + "libc", +] + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libgit2-sys" +version = "0.18.1+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.0", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "nasm-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12fcfa1bd49e0342ec1d07ed2be83b59963e7acbeb9310e1bb2c07b69dadd959" +dependencies = [ + "jobserver", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "prettyplease" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", + "tracing", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger", + "log", + "rand 0.8.5", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +dependencies = [ + "aligned-vec", + "aom-sys", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "assert_cmd", + "av-metrics", + "av-scenechange", + "av1-grain", + "backtrace", + "bitstream-io", + "built", + "byteorder", + "cc", + "cfg-if", + "clap", + "clap_complete", + "console", + "criterion", + "crossbeam", + "fern", + "image", + "interpolate_name", + "itertools 0.14.0", + "ivf", + "libc", + "libdav1d-sys", + "libfuzzer-sys", + "log", + "maybe-rayon", + "nasm-rs", + "new_debug_unreachable", + "nom 8.0.0", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "pretty_assertions", + "profiling", + "quickcheck", + "rand 0.9.1", + "rand_chacha", + "scan_fmt", + "semver", + "serde", + "serde-big-array", + "signal-hook", + "simd_helpers", + "thiserror 2.0.12", + "toml", + "tracing", + "tracing-chrome", + "tracing-subscriber", + "v_frame", + "wasm-bindgen", + "y4m", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scan_fmt" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "terminal_size" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +dependencies = [ + "rustix 1.0.7", + "windows-sys", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-chrome" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,385 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.83.0" +name = "rav1e" +version = "0.8.1" +authors = ["Thomas Daede "] +build = "build.rs" +include = [ + "/Cargo.toml", + "/LICENSE", + "/PATENTS", + "/README.md", + "/build.rs", + "/cbindgen.toml", + "/src/**", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +default-run = "rav1e" +description = "The fastest and safest AV1 encoder" +readme = "README.md" +license = "BSD-2-Clause" +repository = "https://github.com/xiph/rav1e/" + +[package.metadata.docs.rs] +no-default-features = true + +[features] +asm = [ + "nasm-rs", + "cc", +] +bench = [] +binaries = [ + "ivf", + "y4m", + "clap", + "clap_complete", + "scan_fmt", + "fern", + "console", + "av-metrics", + "nom", +] +capi = ["scan_fmt"] +channel-api = ["crossbeam"] +check_asm = [] +decode_test = ["aom-sys"] +decode_test_dav1d = ["dav1d-sys"] +default = [ + "binaries", + "asm", + "threading", + "signal_support", + "git_version", +] +desync_finder = ["backtrace"] +dump_ivf = ["ivf"] +dump_lookahead_data = [ + "byteorder", + "image", +] +git_version = ["built/git2"] +quick_test = [] +serialize = [ + "serde", + "toml", + "v_frame/serialize", + "serde-big-array", + "av1-grain/serialize", +] +signal_support = ["signal-hook"] +threading = ["rayon/threads"] +tracing = [ + "profiling/profile-with-tracing", + "tracing-subscriber", + "tracing-chrome", + "dep:tracing", +] +unstable = [] +wasm = ["wasm-bindgen"] + +[lib] +name = "rav1e" +path = "src/lib.rs" +bench = false + +[[bin]] +name = "rav1e" +path = "src/bin/rav1e.rs" +bench = false +required-features = ["binaries"] + +[[bin]] +name = "rav1e-ch" +path = "src/bin/rav1e-ch.rs" +bench = false +required-features = [ + "binaries", + "channel-api", + "unstable", +] + +[dependencies.aligned-vec] +version = "0.6.0" + +[dependencies.aom-sys] +version = "0.3.3" +optional = true + +[dependencies.arg_enum_proc_macro] +version = "0.3.4" + +[dependencies.arrayvec] +version = "0.7" + +[dependencies.av-metrics] +version = "0.9.1" +optional = true +default-features = false + +[dependencies.av-scenechange] +version = "0.14.1" +default-features = false + +[dependencies.av1-grain] +version = "0.2.3" + +[dependencies.backtrace] +version = "0.3" +optional = true + +[dependencies.bitstream-io] +version = "4.1.0" + +[dependencies.byteorder] +version = "1.5.0" +optional = true + +[dependencies.cfg-if] +version = "1.0" + +[dependencies.clap] +version = "4.5" +features = [ + "color", + "std", + "wrap_help", + "derive", +] +optional = true +default-features = false + +[dependencies.clap_complete] +version = "4.5" +optional = true + +[dependencies.console] +version = "0.15" +optional = true + +[dependencies.crossbeam] +version = "0.8" +optional = true + +[dependencies.dav1d-sys] +version = "0.7.0" +optional = true +package = "libdav1d-sys" + +[dependencies.fern] +version = "0.7" +optional = true + +[dependencies.image] +version = "0.25.0" +features = ["png"] +optional = true +default-features = false + +[dependencies.itertools] +version = "0.14" + +[dependencies.ivf] +version = "0.1" +optional = true + +[dependencies.libc] +version = "0.2" + +[dependencies.log] +version = "0.4" + +[dependencies.new_debug_unreachable] +version = "1.0.4" + +[dependencies.nom] +version = "8.0.0" +optional = true + +[dependencies.noop_proc_macro] +version = "0.3.0" + +[dependencies.num-derive] +version = "0.4" + +[dependencies.num-traits] +version = "0.2" + +[dependencies.paste] +version = "1.0" + +[dependencies.profiling] +version = "1" + +[dependencies.rayon] +version = "0.1" +default-features = false +package = "maybe-rayon" + +[dependencies.scan_fmt] +version = "0.2.6" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dependencies.serde-big-array] +version = "0.5.1" +optional = true + +[dependencies.simd_helpers] +version = "0.1" + +[dependencies.thiserror] +version = "2.0" + +[dependencies.toml] +version = "0.8" +optional = true + +[dependencies.tracing] +version = "0.1.40" +optional = true + +[dependencies.tracing-chrome] +version = "0.7.1" +optional = true + +[dependencies.tracing-subscriber] +version = "0.3.18" +optional = true + +[dependencies.v_frame] +version = "0.3.7" + +[dependencies.wasm-bindgen] +version = "0.2.90" +optional = true + +[dependencies.y4m] +version = "0.8" +optional = true + +[dev-dependencies.interpolate_name] +version = "0.2.4" + +[dev-dependencies.nom] +version = "8.0.0" + +[dev-dependencies.pretty_assertions] +version = "1.4.0" + +[dev-dependencies.quickcheck] +version = "1.0" + +[dev-dependencies.rand] +version = "0.9" + +[dev-dependencies.rand_chacha] +version = "0.9" + +[dev-dependencies.semver] +version = "1.0" + +[build-dependencies.built] +version = "0.8.0" +features = [] + +[build-dependencies.cc] +version = "1.0" +features = ["parallel"] +optional = true + +[build-dependencies.nasm-rs] +version = "0.3" +features = ["parallel"] +optional = true + +[target."cfg(fuzzing)".dependencies.arbitrary] +version = "1.3" + +[target."cfg(fuzzing)".dependencies.interpolate_name] +version = "0.2.4" + +[target."cfg(fuzzing)".dependencies.libfuzzer-sys] +version = "0.4.7" + +[target."cfg(fuzzing)".dependencies.rand] +version = "0.9" + +[target."cfg(fuzzing)".dependencies.rand_chacha] +version = "0.9" + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.assert_cmd] +version = "2.0" + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.6" + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies.criterion] +version = "0.6" +default-features = false + +[target."cfg(unix)".dependencies.signal-hook] +version = "0.3" +optional = true + +[lints.clippy] +comparison_chain = "allow" +doc_link_with_quotes = "warn" +doc_markdown = "warn" +enum_variant_names = "allow" +missing_errors_doc = "warn" +missing_panics_doc = "warn" +missing_safety_doc = "warn" +needless_range_loop = "allow" +too_many_arguments = "allow" +upper_case_acronyms = "allow" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(nasm_x86_64)", + "cfg(asm_neon)", + "cfg(cargo_c)", + "cfg(fuzzing)", +] + +[profile.bench] +incremental = true + +[profile.dev] +opt-level = 1 + +[profile.release] +lto = "thin" +debug = 2 +incremental = true + +[profile.release-no-lto] +lto = "off" +inherits = "release" + +[profile.release-strip] +inherits = "release" +strip = "symbols" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,232 @@ +[package] +name = "rav1e" +version = "0.8.1" +authors = ["Thomas Daede "] +edition = "2021" +rust-version = "1.83.0" +build = "build.rs" +include = [ + "/Cargo.toml", + "/LICENSE", + "/PATENTS", + "/README.md", + "/build.rs", + "/cbindgen.toml", + "/src/**", +] +license = "BSD-2-Clause" +description = "The fastest and safest AV1 encoder" +readme = "README.md" +repository = "https://github.com/xiph/rav1e/" +autobenches = false +autobins = false +default-run = "rav1e" + +[features] +unstable = [] +channel-api = ["crossbeam"] +decode_test = ["aom-sys"] +decode_test_dav1d = ["dav1d-sys"] +binaries = [ + "ivf", + "y4m", + "clap", + "clap_complete", + "scan_fmt", + "fern", + "console", + "av-metrics", + "nom", +] +default = ["binaries", "asm", "threading", "signal_support", "git_version"] +git_version = ["built/git2"] +asm = ["nasm-rs", "cc"] +threading = ["rayon/threads"] +signal_support = ["signal-hook"] +dump_ivf = ["ivf"] +quick_test = [] +desync_finder = ["backtrace"] +bench = [] +check_asm = [] +capi = ["scan_fmt"] +tracing = [ + "profiling/profile-with-tracing", + "tracing-subscriber", + "tracing-chrome", + "dep:tracing", +] +serialize = [ + "serde", + "toml", + "v_frame/serialize", + "serde-big-array", + "av1-grain/serialize", +] +wasm = ["wasm-bindgen"] + +# Enables debug dumping of lookahead computation results, specifically: +# - i-qres.png: quarter-resolution luma planes, +# - i-hres.png: half-resolution luma planes, +# - i-mvs.bin: motion vectors, +# - i-imps.bin: block importances, +# - i-activity_scales.bin: spatial scales, +# - i-distortion_scales.bin: temporal scales, +# - i-spatiotemporal_scales.bin, +# - i-thresholds.bin: segmentation thresholds. +dump_lookahead_data = ["byteorder", "image"] + +[dependencies] +arg_enum_proc_macro = "0.3.4" +av-scenechange = { version = "0.14.1", default-features = false } +bitstream-io = "4.1.0" +cfg-if = "1.0" +clap = { version = "4.5", optional = true, default-features = false, features = [ + "color", + "std", + "wrap_help", + "derive", +] } +clap_complete = { version = "4.5", optional = true } +libc = "0.2" +y4m = { version = "0.8", optional = true } +backtrace = { version = "0.3", optional = true } +num-traits = "0.2" +num-derive = "0.4" +paste = "1.0" +noop_proc_macro = "0.3.0" +serde = { version = "1.0", features = ["derive"], optional = true } +dav1d-sys = { version = "0.7.0", package = "libdav1d-sys", optional = true } +aom-sys = { version = "0.3.3", optional = true } +scan_fmt = { version = "0.2.6", optional = true, default-features = false } +ivf = { version = "0.1", path = "ivf/", optional = true } +v_frame = "0.3.7" +av-metrics = { version = "0.9.1", optional = true, default-features = false } +rayon = { package = "maybe-rayon", version = "0.1", default-features = false } +crossbeam = { version = "0.8", optional = true } +toml = { version = "0.8", optional = true } +arrayvec = "0.7" +thiserror = "2.0" +byteorder = { version = "1.5.0", optional = true } +log = "0.4" +console = { version = "0.15", optional = true } +fern = { version = "0.7", optional = true } +itertools = "0.14" +simd_helpers = "0.1" +wasm-bindgen = { version = "0.2.90", optional = true } +nom = { version = "8.0.0", optional = true } +new_debug_unreachable = "1.0.4" +av1-grain = "0.2.3" +serde-big-array = { version = "0.5.1", optional = true } +profiling = { version = "1" } +tracing-subscriber = { version = "0.3.18", optional = true } +tracing-chrome = { version = "0.7.1", optional = true } +tracing = { version = "0.1.40", optional = true } +aligned-vec = "0.6.0" + +[dependencies.image] +version = "0.25.0" +optional = true +default-features = false +features = ["png"] + +[build-dependencies] +cc = { version = "1.0", optional = true, features = ["parallel"] } +built = { version = "0.8.0", features = [] } + +[build-dependencies.nasm-rs] +version = "0.3" +optional = true +features = ["parallel"] + +[target.'cfg(unix)'.dependencies] +signal-hook = { version = "0.3", optional = true } + +[dev-dependencies] +pretty_assertions = "1.4.0" +interpolate_name = "0.2.4" +nom = "8.0.0" +quickcheck = "1.0" +rand = "0.9" +rand_chacha = "0.9" +semver = "1.0" + +# Exclude dependencies and features that don't work on wasm32: +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +criterion = { version = "0.6", default-features = false } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +assert_cmd = "2.0" +criterion = "0.6" + +[target.'cfg(fuzzing)'.dependencies] +arbitrary = "1.3" +interpolate_name = "0.2.4" +libfuzzer-sys = "0.4.7" +rand = "0.9" +rand_chacha = "0.9" + +[lints.rust.unexpected_cfgs] +level = "warn" +# These custom cfgs are expected, so tell rustc not to output warnings for them +check-cfg = [ + 'cfg(nasm_x86_64)', + 'cfg(asm_neon)', + 'cfg(cargo_c)', + 'cfg(fuzzing)', +] + +[[bin]] +name = "rav1e" +required-features = ["binaries"] +bench = false + +[[bin]] +name = "rav1e-ch" +required-features = ["binaries", "channel-api", "unstable"] +bench = false + +[lib] +bench = false + +[[bench]] +name = "bench" +path = "benches/bench.rs" +required-features = ["bench"] +harness = false + +[profile.dev] +opt-level = 1 + +[profile.release] +debug = true +incremental = true +lto = "thin" + +[profile.release-no-lto] +inherits = "release" +lto = "off" + +[profile.release-strip] +inherits = "release" +strip = "symbols" + +[profile.bench] +incremental = true + +[workspace] +members = [".", "ivf"] + +[package.metadata.docs.rs] +no-default-features = true + +[lints.clippy] +doc_link_with_quotes = "warn" +doc_markdown = "warn" +missing_errors_doc = "warn" +missing_panics_doc = "warn" +missing_safety_doc = "warn" +comparison_chain = "allow" +enum_variant_names = "allow" +needless_range_loop = "allow" +too_many_arguments = "allow" +upper_case_acronyms = "allow" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/rav1e/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2017-2023, the rav1e contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/PATENTS clamav-1.4.6+dfsg/.cargo/vendor/rav1e/PATENTS --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/PATENTS 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/PATENTS 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,108 @@ +Alliance for Open Media Patent License 1.0 + +1. License Terms. + +1.1. Patent License. Subject to the terms and conditions of this License, each + Licensor, on behalf of itself and successors in interest and assigns, + grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as expressly stated in this + License) patent license to its Necessary Claims to make, use, sell, offer + for sale, import or distribute any Implementation. + +1.2. Conditions. + +1.2.1. Availability. As a condition to the grant of rights to Licensee to make, + sell, offer for sale, import or distribute an Implementation under + Section 1.1, Licensee must make its Necessary Claims available under + this License, and must reproduce this License with any Implementation + as follows: + + a. For distribution in source code, by including this License in the + root directory of the source code with its Implementation. + + b. For distribution in any other form (including binary, object form, + and/or hardware description code (e.g., HDL, RTL, Gate Level Netlist, + GDSII, etc.)), by including this License in the documentation, legal + notices, and/or other written materials provided with the + Implementation. + +1.2.2. Additional Conditions. This license is directly from Licensor to + Licensee. Licensee acknowledges as a condition of benefiting from it + that no rights from Licensor are received from suppliers, distributors, + or otherwise in connection with this License. + +1.3. Defensive Termination. If any Licensee, its Affiliates, or its agents + initiates patent litigation or files, maintains, or voluntarily + participates in a lawsuit against another entity or any person asserting + that any Implementation infringes Necessary Claims, any patent licenses + granted under this License directly to the Licensee are immediately + terminated as of the date of the initiation of action unless 1) that suit + was in response to a corresponding suit regarding an Implementation first + brought against an initiating entity, or 2) that suit was brought to + enforce the terms of this License (including intervention in a third-party + action by a Licensee). + +1.4. Disclaimers. The Reference Implementation and Specification are provided + "AS IS" and without warranty. The entire risk as to implementing or + otherwise using the Reference Implementation or Specification is assumed + by the implementer and user. Licensor expressly disclaims any warranties + (express, implied, or otherwise), including implied warranties of + merchantability, non-infringement, fitness for a particular purpose, or + title, related to the material. IN NO EVENT WILL LICENSOR BE LIABLE TO + ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, + INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF + ACTION OF ANY KIND WITH RESPECT TO THIS LICENSE, WHETHER BASED ON BREACH + OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR + NOT THE OTHER PARTRY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +2. Definitions. + +2.1. Affiliate. “Affiliate” means an entity that directly or indirectly + Controls, is Controlled by, or is under common Control of that party. + +2.2. Control. “Control” means direct or indirect control of more than 50% of + the voting power to elect directors of that corporation, or for any other + entity, the power to direct management of such entity. + +2.3. Decoder. "Decoder" means any decoder that conforms fully with all + non-optional portions of the Specification. + +2.4. Encoder. "Encoder" means any encoder that produces a bitstream that can + be decoded by a Decoder only to the extent it produces such a bitstream. + +2.5. Final Deliverable. “Final Deliverable” means the final version of a + deliverable approved by the Alliance for Open Media as a Final + Deliverable. + +2.6. Implementation. "Implementation" means any implementation, including the + Reference Implementation, that is an Encoder and/or a Decoder. An + Implementation also includes components of an Implementation only to the + extent they are used as part of an Implementation. + +2.7. License. “License” means this license. + +2.8. Licensee. “Licensee” means any person or entity who exercises patent + rights granted under this License. + +2.9. Licensor. "Licensor" means (i) any Licensee that makes, sells, offers + for sale, imports or distributes any Implementation, or (ii) a person + or entity that has a licensing obligation to the Implementation as a + result of its membership and/or participation in the Alliance for Open + Media working group that developed the Specification. + +2.10. Necessary Claims. "Necessary Claims" means all claims of patents or + patent applications, (a) that currently or at any time in the future, + are owned or controlled by the Licensor, and (b) (i) would be an + Essential Claim as defined by the W3C Policy as of February 5, 2004 + (https://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential) + as if the Specification was a W3C Recommendation; or (ii) are infringed + by the Reference Implementation. + +2.11. Reference Implementation. “Reference Implementation” means an Encoder + and/or Decoder released by the Alliance for Open Media as a Final + Deliverable. + +2.12. Specification. “Specification” means the specification designated by + the Alliance for Open Media as a Final Deliverable for which this + License was issued. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/README.md clamav-1.4.6+dfsg/.cargo/vendor/rav1e/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,188 @@ +# rav1e [![Actions Status][actions badge]][actions] [![CodeCov][codecov badge]][codecov] + +The fastest and safest AV1 encoder. + +
+Table of Content + +- [Overview](#overview) +- [Features](#features) +- [Documentation](#documentation) +- [Releases](#releases) +- [Building](#building) + - [Dependency: NASM](#dependency-nasm) + - [Release binary](#release-binary) + - [Unstable features](#unstable-features) + - [Target-specific builds](#target-specific-builds) + - [Building the C-API](#building-the-c-api) +- [Usage](#usage) + - [Compressing video](#compressing-video) + - [Decompressing video](#decompressing-video) + - [Configuring](#configuring) + - [Features](#features-1) +- [Contributing](#contributing) +- [Getting in Touch](#getting-in-touch) +
+ +## Overview +rav1e is an AV1 video encoder. It is designed to eventually cover all use cases, though in its current form it is most suitable for cases where libaom (the reference encoder) is too slow. + +## Features +* Intra, inter, and switch frames +* 64x64 superblocks +* 4x4 to 64x64 RDO-selected square and rectangular blocks +* DC, H, V, Paeth, smooth, and all directional prediction modes +* DCT, (FLIP-)ADST and identity transforms (up to 64x64, 16x16 and 32x32 respectively) +* 8-, 10- and 12-bit depth color +* 4:2:0, 4:2:2 and 4:4:4 chroma sampling +* 11 speed settings (0-10, exhaustive to near real-time) +* Constant quantizer and target bitrate (single- and multi-pass) encoding modes +* Still picture mode + +## Documentation +Find the documentation in [`doc/`](doc/README.md) + +## Releases +For the foreseeable future, a weekly pre-release of rav1e will be [published](https://github.com/xiph/rav1e/releases) every Tuesday. + +## Building + +### Toolchain: Rust + +rav1e currently requires Rust 1.74.0 or later to build. + +### Dependency: NASM +Some `x86_64`-specific optimizations require [NASM](https://nasm.us/) `2.14.02` or newer and are enabled by default. +`strip` will be used if available to remove the local symbols from the asm objects. + +The CI is testing against `nasm 2.15.05`, so bugs for other versions might happen. If you find one please open an issue! + +
+ +Install nasm + + +**ubuntu 20.04** (`nasm 2.14.02`) +```sh +sudo apt install nasm +``` +**ubuntu 18.04** (`nasm 2.14.02`) +```sh +sudo apt install nasm-mozilla +# link nasm into $PATH +sudo ln /usr/lib/nasm-mozilla/bin/nasm /usr/local/bin/ +``` +**fedora 31, 32** (`nasm 2.14.02`) +```sh +sudo dnf install nasm +``` +**windows** (`nasm 2.15.05`)
+Have a [NASM binary](https://www.nasm.us/pub/nasm/releasebuilds/) in your system PATH. +```sh +$NASM_VERSION="2.15.05" # or newer +$LINK="https://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/win64" +curl --ssl-no-revoke -LO "$LINK/nasm-$NASM_VERSION-win64.zip" +7z e -y "nasm-$NASM_VERSION-win64.zip" -o "C:\nasm" +# set path for the current sessions +set PATH="%PATH%;C:\nasm" +``` +**macOS** (`nasm 2.15.05`) +```sh +brew install nasm +``` + +
+ +### Release binary +To build release binary in `target/release/rav1e` run: + +```sh +cargo build --release +``` + +### Unstable features +Experimental API and Features can be enabled by using the `unstable` feature. + +```sh +cargo build --features ,unstable +``` + +#### Current unstable features +- Channel API: +```sh +cargo build --features channel-api,unstable +``` + + +Those Features and API are bound to change and evolve, do not rely on them staying the same over releases. + +### Target-specific builds +The rust compiler can produce a binary that is about 11%-13% faster if it can use `avx2`, `bmi1`, `bmi2`, `fma`, `lzcnt` and `popcnt` in the general code, you may allow it by issuing: + +```sh +RUSTFLAGS="-C target-cpu=native" cargo build --release +# or +RUSTFLAGS="-C target-cpu=x86-64-v3" cargo build --release +``` + +The resulting binary will not work on cpus that do not sport the same set of extensions enabled. + +> **NOTE** : You may use `rustc --print target-cpus` to check if the cpu is supported, if not `-C target-cpu=native` would be a no-op. + +### Building the C-API +**rav1e** provides a C-compatible set of library, header and pkg-config file. + +To build and install it you can use [cargo-c](https://crates.io/crates/cargo-c): + +```sh +cargo install cargo-c +cargo cinstall --release +``` + +Please refer to the cargo-c [installation](https://github.com/lu-zero/cargo-c#installation) instructions. + +## Usage +### Compressing video +Input videos must be in [y4m format](https://wiki.multimedia.cx/index.php/YUV4MPEG2). The monochrome color format is not supported. + +```sh +cargo run --release --bin rav1e -- input.y4m -o output.ivf +``` + +_(Find a y4m-file for testing at [`tests/small_input.y4m`](tests/small_input.y4m) or at http://ultravideo.cs.tut.fi/#testsequences)_ + +### Decompressing video +Encoder output should be compatible with any AV1 decoder compliant with the v1.0.0 specification. You can decode using [dav1d](https://code.videolan.org/videolan/dav1d), which is now packaged [![in over 40 repositories](https://repology.org/badge/tiny-repos/dav1d.svg)](https://repology.org/project/dav1d/versions). + +```sh +dav1d -i output.ivf -o output.y4m +``` + +### Configuring +rav1e has several optional features that can be enabled by passing `--features` to cargo. Passing `--all-features` is discouraged. + +#### Features +Find a full list in feature-table in [`Cargo.toml`](Cargo.toml) + +* `asm` - enabled by default. When enabled, assembly is built for the platforms supporting it. + * `x86_64`: Requires [`nasm`](#dependency-nasm). + * `aarch64` + * Requires `gas` + * Alternative: Use `clang` assembler by setting `CC=clang` + +**NOTE**: `SSE2` is always enabled on `x86_64`, `neon` is always enabled for aarch64, you may set the environment variable `RAV1E_CPU_TARGET` to `rust` to disable all the assembly-optimized routines at the runtime. + +## Contributing +Please read our guide to [contributing to rav1e](CONTRIBUTING.md). + +## Getting in Touch +Come chat with us on the IRC channel #daala on [Libera.Chat](https://libera.chat/)! You can also use a [web client](https://web.libera.chat/?channel=#daala) to join with a web browser. + + + +[actions]: https://github.com/xiph/rav1e/actions +[codecov]: https://codecov.io/gh/xiph/rav1e + + +[actions badge]: https://github.com/xiph/rav1e/workflows/rav1e/badge.svg +[codecov badge]: https://codecov.io/gh/xiph/rav1e/branch/master/graph/badge.svg diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/build.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,279 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(clippy::print_literal)] +#![allow(clippy::unused_io_amount)] + +#[allow(unused_imports)] +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; + +#[allow(dead_code)] +fn rerun_dir>(dir: P) { + for entry in fs::read_dir(dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + println!("cargo:rerun-if-changed={}", path.to_string_lossy()); + + if path.is_dir() { + rerun_dir(path); + } + } +} + +#[allow(dead_code)] +fn hash_changed( + files: &[&str], out_dir: &str, config: &Path, +) -> Option<([u8; 8], PathBuf)> { + use std::collections::hash_map::DefaultHasher; + use std::hash::Hasher; + + let mut hasher = DefaultHasher::new(); + + let paths = files + .iter() + .map(Path::new) + .chain(std::iter::once(config)) + .chain(std::iter::once(Path::new("build.rs"))); + + for path in paths { + if let Ok(buf) = std::fs::read(path) { + hasher.write(&buf); + } else { + panic!("Cannot open {}", path.display()); + } + } + + if let Some(cmd) = strip_command() { + hasher.write(cmd.as_bytes()); + } + + let hash = hasher.finish().to_be_bytes(); + + let hash_path = Path::new(&out_dir).join("asm.hash"); + + if let Ok(old_hash) = std::fs::read(&hash_path) { + if old_hash == hash { + return None; + } + } + + Some((hash, hash_path)) +} + +#[cfg(feature = "asm")] +fn build_nasm_files() { + let mut config = " +%pragma preproc sane_empty_expansion true +%define private_prefix rav1e +%define ARCH_X86_32 0 +%define ARCH_X86_64 1 +%define PIC 1 +%define STACK_ALIGNMENT 16 +%define HAVE_AVX512ICL 1 +" + .to_owned(); + + if env::var("CARGO_CFG_TARGET_VENDOR").unwrap() == "apple" { + config += "%define PREFIX 1\n"; + } + + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("config.asm"); + std::fs::write(&dest_path, config).expect("can write config.asm"); + + let asm_files = &[ + "src/x86/cdef_avx2.asm", + "src/x86/cdef_avx512.asm", + "src/x86/cdef_dist.asm", + "src/x86/cdef_rav1e.asm", + "src/x86/cdef_sse.asm", + "src/x86/cdef16_avx2.asm", + "src/x86/cdef16_avx512.asm", + "src/x86/cdef16_sse.asm", + "src/x86/ipred_avx2.asm", + "src/x86/ipred_avx512.asm", + "src/x86/ipred_sse.asm", + "src/x86/ipred16_avx2.asm", + "src/x86/ipred16_avx512.asm", + "src/x86/ipred16_sse.asm", + "src/x86/itx_avx2.asm", + "src/x86/itx_avx512.asm", + "src/x86/itx_sse.asm", + "src/x86/itx16_avx2.asm", + "src/x86/itx16_avx512.asm", + "src/x86/itx16_sse.asm", + "src/x86/looprestoration_avx2.asm", + "src/x86/looprestoration_avx512.asm", + "src/x86/looprestoration_sse.asm", + "src/x86/looprestoration16_avx2.asm", + "src/x86/looprestoration16_avx512.asm", + "src/x86/looprestoration16_sse.asm", + "src/x86/mc_avx2.asm", + "src/x86/mc_avx512.asm", + "src/x86/mc_sse.asm", + "src/x86/mc16_avx2.asm", + "src/x86/mc16_avx512.asm", + "src/x86/mc16_sse.asm", + "src/x86/me.asm", + "src/x86/sad_avx.asm", + "src/x86/sad_sse2.asm", + "src/x86/satd.asm", + "src/x86/satd16_avx2.asm", + "src/x86/sse.asm", + "src/x86/tables.asm", + ]; + + if let Some((hash, hash_path)) = + hash_changed(asm_files, &out_dir, &dest_path) + { + let obj = nasm_rs::Build::new() + .min_version(2, 15, 0) + .include(&out_dir) + .include("src") + .files(asm_files) + .compile_objects() + .unwrap_or_else(|e| { + panic!("NASM build failed. Make sure you have nasm installed or disable the \"asm\" feature.\n\ + You can get NASM from https://nasm.us or your system's package manager.\n\ + \n\ + error: {e}"); + }); + + // cc is better at finding the correct archiver + let mut cc = cc::Build::new(); + for o in obj { + cc.object(o); + } + cc.compile("rav1easm"); + + // Strip local symbols from the asm library since they + // confuse the debugger. + if let Some(strip) = strip_command() { + let _ = std::process::Command::new(strip) + .arg("-x") + .arg(Path::new(&out_dir).join("librav1easm.a")) + .status(); + } + + std::fs::write(hash_path, &hash[..]).unwrap(); + } else { + println!("cargo:rustc-link-search={out_dir}"); + } + println!("cargo:rustc-link-lib=static=rav1easm"); + rerun_dir("src/x86"); + rerun_dir("src/ext/x86"); +} + +fn strip_command() -> Option { + let target = env::var("TARGET").expect("TARGET"); + // follows Cargo's naming convention for the linker setting + let normalized_target = target.replace('-', "_").to_uppercase(); + let explicit_strip = + env::var(format!("CARGO_TARGET_{normalized_target}_STRIP")) + .ok() + .or_else(|| env::var("STRIP").ok()); + if explicit_strip.is_some() { + return explicit_strip; + } + + // strip command is target-specific, e.g. macOS's strip breaks MUSL's archives + let host = env::var("HOST").expect("HOST"); + if host != target { + return None; + } + + Some("strip".into()) +} + +#[cfg(feature = "asm")] +fn build_asm_files() { + let mut config = " +#define PRIVATE_PREFIX rav1e_ +#define ARCH_AARCH64 1 +#define ARCH_ARM 0 +#define CONFIG_LOG 1 +#define HAVE_ASM 1 +" + .to_owned(); + + if env::var("CARGO_CFG_TARGET_VENDOR").unwrap() == "apple" { + config += "#define PREFIX 1\n"; + } + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("config.h"); + std::fs::write(&dest_path, config).expect("can write config.h"); + + let asm_files = &[ + "src/arm/64/cdef.S", + "src/arm/64/cdef16.S", + "src/arm/64/cdef_dist.S", + "src/arm/64/mc.S", + "src/arm/64/mc16.S", + "src/arm/64/itx.S", + "src/arm/64/itx16.S", + "src/arm/64/ipred.S", + "src/arm/64/ipred16.S", + "src/arm/64/sad.S", + "src/arm/64/satd.S", + "src/arm/64/sse.S", + "src/arm/tables.S", + ]; + + if let Some((hash, hash_path)) = + hash_changed(asm_files, &out_dir, &dest_path) + { + cc::Build::new() + .files(asm_files) + .include(".") + .include(&out_dir) + .compile("rav1e-aarch64"); + + std::fs::write(hash_path, &hash[..]).unwrap(); + } else { + println!("cargo:rustc-link-search={out_dir}"); + println!("cargo:rustc-link-lib=static=rav1e-aarch64"); + } + rerun_dir("src/arm"); +} + +#[allow(unused_variables)] +fn main() { + built::write_built_file().expect("Failed to acquire build-time information"); + + let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + let os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + // let env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); + + #[cfg(feature = "asm")] + { + if arch == "x86_64" { + println!("cargo:rustc-cfg={}", "nasm_x86_64"); + build_nasm_files() + } + if arch == "aarch64" { + println!("cargo:rustc-cfg={}", "asm_neon"); + build_asm_files() + } + } + + if os == "windows" && cfg!(feature = "decode_test") { + panic!("Unsupported feature on this platform!"); + } + + println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + if let Ok(value) = env::var("CARGO_CFG_TARGET_FEATURE") { + println!("cargo:rustc-env=CARGO_CFG_TARGET_FEATURE={value}"); + } + println!( + "cargo:rustc-env=CARGO_ENCODED_RUSTFLAGS={}", + env::var("CARGO_ENCODED_RUSTFLAGS").unwrap() + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/cbindgen.toml clamav-1.4.6+dfsg/.cargo/vendor/rav1e/cbindgen.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/cbindgen.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +header = "// SPDX-License-Identifier: MIT" +sys_includes = ["stddef.h", "stdint.h", "stdlib.h"] +no_includes = true +include_guard = "RAV1E_H" +tab_width = 4 +style = "Type" +language = "C" +cpp_compat = true + +[parse] +parse_deps = true +include = ['rav1e', 'v_frame'] + +[export] +prefix = "Ra" +item_types = ["enums", "structs", "unions", "typedefs", "opaque", "functions"] + +[enum] +rename_variants = "ScreamingSnakeCase" +prefix_with_name = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/activity.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/activity.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/activity.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/activity.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,275 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::frame::*; +use crate::rdo::DistortionScale; +use crate::tiling::*; +use crate::util::*; +use itertools::izip; + +#[derive(Debug, Default, Clone)] +pub struct ActivityMask { + variances: Box<[u32]>, +} + +impl ActivityMask { + #[profiling::function] + pub fn from_plane(luma_plane: &Plane) -> ActivityMask { + let PlaneConfig { width, height, .. } = luma_plane.cfg; + + // Width and height are padded to 8×8 block size. + let w_in_imp_b = width.align_power_of_two_and_shift(3); + let h_in_imp_b = height.align_power_of_two_and_shift(3); + + let aligned_luma = Rect { + x: 0_isize, + y: 0_isize, + width: w_in_imp_b << 3, + height: h_in_imp_b << 3, + }; + let luma = PlaneRegion::new(luma_plane, aligned_luma); + + let mut variances = Vec::with_capacity(w_in_imp_b * h_in_imp_b); + + for y in 0..h_in_imp_b { + for x in 0..w_in_imp_b { + let block_rect = Area::Rect { + x: (x << 3) as isize, + y: (y << 3) as isize, + width: 8, + height: 8, + }; + + let block = luma.subregion(block_rect); + let variance = variance_8x8(&block); + variances.push(variance); + } + } + ActivityMask { variances: variances.into_boxed_slice() } + } + + #[profiling::function] + pub fn fill_scales( + &self, bit_depth: usize, activity_scales: &mut Box<[DistortionScale]>, + ) { + for (dst, &src) in activity_scales.iter_mut().zip(self.variances.iter()) { + *dst = ssim_boost(src, src, bit_depth); + } + } +} + +// Adapted from the source variance calculation in `cdef_dist_wxh_8x8`. +#[inline(never)] +fn variance_8x8(src: &PlaneRegion<'_, T>) -> u32 { + debug_assert!(src.plane_cfg.xdec == 0); + debug_assert!(src.plane_cfg.ydec == 0); + + // Sum into columns to improve auto-vectorization + let mut sum_s_cols: [u16; 8] = [0; 8]; + let mut sum_s2_cols: [u32; 8] = [0; 8]; + + // Check upfront that 8 rows are available. + let _row = &src[7]; + + for j in 0..8 { + let row = &src[j][0..8]; + for (sum_s, sum_s2, s) in izip!(&mut sum_s_cols, &mut sum_s2_cols, row) { + // Don't convert directly to u32 to allow better vectorization + let s: u16 = u16::cast_from(*s); + *sum_s += s; + + // Convert to u32 to avoid overflows when multiplying + let s: u32 = s as u32; + *sum_s2 += s * s; + } + } + + // Sum together the sum of columns + let sum_s = sum_s_cols.iter().copied().map(u64::from).sum::(); + let sum_s2 = sum_s2_cols.iter().copied().map(u64::from).sum::(); + + // Use sums to calculate variance + u32::try_from(sum_s2 - ((sum_s * sum_s + 32) >> 6)).unwrap_or(u32::MAX) +} + +/// `rsqrt` result stored in fixed point w/ scaling such that: +/// `rsqrt = output.rsqrt_norm / (1 << output.shift)` +struct RsqrtOutput { + norm: u16, + shift: u8, +} + +/// Fixed point `rsqrt` for `ssim_boost` +const fn ssim_boost_rsqrt(x: u64) -> RsqrtOutput { + const INSHIFT: u8 = 16; + const OUTSHIFT: u8 = 14; + + let k = (x.ilog2() >> 1) as i16; + /*t is x in the range [0.25, 1) in QINSHIFT, or x*2^(-s). + Shift by log2(x) - log2(0.25*(1 << INSHIFT)) to ensure 0.25 lower bound.*/ + let s: i16 = 2 * k - (INSHIFT as i16 - 2); + let t: u16 = if s > 0 { x >> s } else { x << -s } as u16; + + /*We want to express od_rsqrt() in terms of od_rsqrt_norm(), which is + defined as (2^OUTSHIFT)/sqrt(t*(2^-INSHIFT)) with t=x*(2^-s). + This simplifies to 2^(OUTSHIFT+(INSHIFT/2)+(s/2))/sqrt(x), so the caller + needs to shift right by OUTSHIFT + INSHIFT/2 + s/2.*/ + let rsqrt_shift: u8 = (OUTSHIFT as i16 + ((s + INSHIFT as i16) >> 1)) as u8; + + #[inline(always)] + const fn mult16_16_q15(a: i32, b: i32) -> i32 { + (a * b) >> 15 + } + + /* Reciprocal sqrt approximation where the input is in the range [0.25,1) in + Q16 and the output is in the range (1.0, 2.0] in Q14). */ + + /* Range of n is [-16384,32767] ([-0.5,1) in Q15). */ + let n: i32 = t as i32 - 32768; + debug_assert!(n >= -16384); + + /* Get a rough guess for the root. + The optimal minimax quadratic approximation (using relative error) is + r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485). + Coefficients here, and the final result r, are Q14. */ + let rsqrt: i32 = 23557 + mult16_16_q15(n, -13490 + mult16_16_q15(n, 6711)); + + debug_assert!(16384 <= rsqrt && rsqrt < 32768); + RsqrtOutput { norm: rsqrt as u16, shift: rsqrt_shift } +} + +#[inline(always)] +pub fn ssim_boost(svar: u32, dvar: u32, bit_depth: usize) -> DistortionScale { + DistortionScale(apply_ssim_boost( + DistortionScale::default().0, + svar, + dvar, + bit_depth, + )) +} + +/// Apply ssim boost to a given input +#[inline(always)] +pub const fn apply_ssim_boost( + input: u32, svar: u32, dvar: u32, bit_depth: usize, +) -> u32 { + let coeff_shift = bit_depth - 8; + + // Scale dvar and svar to lbd range to prevent overflows. + let svar = (svar >> (2 * coeff_shift)) as u64; + let dvar = (dvar >> (2 * coeff_shift)) as u64; + + // The constants are such that when source and destination variance are equal, + // ssim_boost ~= (x/2)^(-1/3) where x = variance / scale and the scale is + // (maximum variance / sample range) << (bit depth - 8). + // C2 is the variance floor, equivalent to a flat block of mean valued samples + // with a single maximum value sample. + const C1: u64 = 3355; + const C2: u64 = 16128; + const C3: u64 = 12338; + const RATIO_SHIFT: u8 = 14; + const RATIO: u64 = (((C1 << (RATIO_SHIFT + 1)) / C3) + 1) >> 1; + + // C1 (svar + dvar + C2) + // input * ---- * -------------------------- + // C3 sqrt(C1^2 + svar * dvar) + let rsqrt = ssim_boost_rsqrt((C1 * C1) + svar * dvar); + ((input as u64 + * (((RATIO * (svar + dvar + C2)) * rsqrt.norm as u64) >> RATIO_SHIFT)) + >> rsqrt.shift) as u32 +} + +#[cfg(test)] +mod ssim_boost_tests { + use super::*; + use interpolate_name::interpolate_test; + use rand::Rng; + + /// Test to make sure extreme values of `ssim_boost` don't overflow. + #[test] + fn overflow_test() { + // Test variance for 8x8 region with a bit depth of 12 + let max_pix_diff = (1 << 12) - 1; + let max_pix_sse = max_pix_diff * max_pix_diff; + let max_variance = max_pix_diff * 8 * 8 / 4; + apply_ssim_boost(max_pix_sse * 8 * 8, max_variance, max_variance, 12); + } + + /// Floating point reference version of `ssim_boost` + fn reference_ssim_boost(svar: u32, dvar: u32, bit_depth: usize) -> f64 { + let coeff_shift = bit_depth - 8; + let var_scale = 1f64 / (1 << (2 * coeff_shift)) as f64; + let svar = svar as f64 * var_scale; + let dvar = dvar as f64 * var_scale; + // These constants are from ssim boost and need to be updated if the + // constants in ssim boost change. + const C1: f64 = 3355f64; + const C2: f64 = 16128f64; + const C3: f64 = 12338f64; + const RATIO: f64 = C1 / C3; + + RATIO * (svar + dvar + C2) / f64::sqrt(C1.mul_add(C1, svar * dvar)) + } + + /// Test that `ssim_boost` has sufficient accuracy. + #[test] + fn accuracy_test() { + let mut rng = rand::rng(); + + let mut max_relative_error = 0f64; + let bd = 12; + + // Test different log scale ranges for the variance. + // Each scale is tested multiple times with randomized variances. + for scale in 0..(bd + 3 * 2 - 2) { + for _ in 0..40 { + let svar = rng.random_range(0..(1 << scale)); + let dvar = rng.random_range(0..(1 << scale)); + + let float = reference_ssim_boost(svar, dvar, 12); + let fixed = + apply_ssim_boost(1 << 23, svar, dvar, 12) as f64 / (1 << 23) as f64; + + // Compare the two versions + max_relative_error = + max_relative_error.max(f64::abs(1f64 - fixed / float)); + } + } + + assert!( + max_relative_error < 0.05, + "SSIM boost error too high. Measured max relative error: {}.", + max_relative_error + ); + } + + #[interpolate_test(8, 8)] + #[interpolate_test(10, 10)] + #[interpolate_test(12, 12)] + fn reciprocal_cube_root_test(bd: usize) { + let mut max_relative_error = 0f64; + + let scale = ((1 << bd) - 1) << (6 - 2 + bd - 8); + for svar in scale..(scale << 2) { + let float = ((scale << 1) as f64 / svar as f64).cbrt(); + let fixed = + apply_ssim_boost(1 << 23, svar, svar, bd) as f64 / (1 << 23) as f64; + + // Compare the two versions + max_relative_error = + max_relative_error.max(f64::abs(1f64 - fixed / float)); + } + + assert!( + max_relative_error < 0.0273, + "SSIM boost error too high. Measured max relative error: {}.", + max_relative_error + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/by_gop.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/by_gop.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/by_gop.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/by_gop.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,382 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::api::channel::data::*; +use crate::api::config::*; +use crate::api::util::*; +use crate::api::EncoderConfig; +use crate::api::InterConfig; + +use crossbeam::channel::*; + +use crate::frame::*; +use crate::util::Pixel; +use av_scenechange::SceneChangeDetector; + +use std::collections::BTreeMap; +use std::sync::Arc; + +struct SubGop { + frames: Vec>>, + end_gop: bool, +} + +/* +impl SubGop { + fn build_fi(&self) -> Vec> { + todo!() + } +} +*/ + +// TODO: Make the detector logic fitting the model +struct SceneChange { + frames: usize, + pyramid_size: usize, + processed: usize, + last_keyframe: usize, + detector: SceneChangeDetector, +} + +impl SceneChange { + fn new(pyramid_size: usize, enc: &EncoderConfig) -> Self { + let inter_cfg = InterConfig::new(enc); + let lookahead_distance = inter_cfg.keyframe_lookahead_distance() as usize; + let detector = SceneChangeDetector::new( + (enc.width, enc.height), + enc.bit_depth, + av_scenechange::Rational32::new( + enc.time_base.den as i32, + enc.time_base.num as i32, + ), + enc.chroma_sampling, + lookahead_distance, + match enc.speed_settings.scene_detection_mode { + super::SceneDetectionSpeed::Fast => { + av_scenechange::SceneDetectionSpeed::Fast + } + super::SceneDetectionSpeed::Standard => { + av_scenechange::SceneDetectionSpeed::Standard + } + super::SceneDetectionSpeed::None => { + av_scenechange::SceneDetectionSpeed::None + } + }, + enc.min_key_frame_interval as usize, + enc.max_key_frame_interval as usize, + av_scenechange::CpuFeatureLevel::default(), + ); + + Self { frames: 0, pyramid_size, processed: 0, last_keyframe: 0, detector } + } + + // Tell where to split the lookahead + // + fn split(&mut self, lookahead: &[Arc>]) -> Option<(usize, bool)> { + self.processed += 1; + + let lookahead_ref: Vec<_> = lookahead[self.frames..].iter().collect(); + + let new_gop = self.detector.analyze_next_frame( + &lookahead_ref, + self.processed, + self.last_keyframe, + ); + + if new_gop { + self.last_keyframe = self.processed; + } + + if self.frames > self.pyramid_size { + self.frames -= self.pyramid_size + 1; + Some((self.pyramid_size + 2, new_gop)) + } else if new_gop { + let frames = self.frames + 1; + self.frames = 0; + Some((frames, true)) + } else { + self.frames += 1; + None + } + } +} + +struct WorkLoad { + s_recv: Receiver>, + send: Sender>, +} + +struct WorkerPoolSend { + recv_workers: Receiver>>>, + send_reassemble: Sender<(usize, Receiver>)>, + count: usize, +} + +impl WorkerPoolSend { + fn get_worker(&mut self) -> Option>> { + self.recv_workers.recv().ok().map(|sender| { + let (s_send, s_recv) = unbounded(); + let (send, recv) = unbounded(); + + let _ = self.send_reassemble.send((self.count, recv)); + + let wl = WorkLoad { s_recv, send }; + + let _ = sender.send(Some(wl)); + + self.count += 1; + + s_send + }) + } +} + +struct WorkerPoolRecv { + recv_reassemble: Receiver<(usize, Receiver>)>, + recv_workers: Receiver>>>, +} + +// TODO: make it Drop ? +impl WorkerPoolRecv { + fn close(&self) { + for worker in self.recv_workers.iter() { + let _ = worker.send(None); + } + } +} + +fn workerpool( + s: &rayon::ScopeFifo, workers: usize, mut cfg: Config, +) -> (WorkerPoolSend, WorkerPoolRecv) { + let (send_workers, recv_workers) = bounded(workers); + let (send_reassemble, recv_reassemble) = unbounded(); + + // TODO: unpack send_frame in process + cfg.enc.speed_settings.scene_detection_mode = SceneDetectionSpeed::None; + + for _ in 0..workers { + let (send_workload, recv_workload) = unbounded::>>(); + let send_workload2 = send_workload.clone(); + let send_back = send_workers.clone(); + + let cfg = cfg.clone(); + s.spawn_fifo(move |_| { + for wl in recv_workload.iter() { + match wl { + Some(wl) => { + let mut inner = cfg.new_inner().unwrap(); + for s in wl.s_recv.iter() { + for f in s.frames { + while !inner.needs_more_fi_lookahead() { + let r = inner.receive_packet(); + match r { + Ok(p) => { + wl.send.send(p).unwrap(); + } + Err(EncoderStatus::Encoded) => {} + _ => todo!("Error management {:?}", r), + } + } + let _ = inner.send_frame(Some(f), None); + } + } + + inner.limit = Some(inner.frame_count); + let _ = inner.send_frame(None, None); + + loop { + match inner.receive_packet() { + Ok(p) => wl.send.send(p).unwrap(), + Err(EncoderStatus::LimitReached) => break, + Err(EncoderStatus::Encoded) => {} + _ => todo!("Error management"), + } + } + + let _ = send_back.send(send_workload2.clone()); + } + None => break, + } + } + }); + let _ = send_workers.send(send_workload); + } + + ( + WorkerPoolSend { + recv_workers: recv_workers.clone(), + send_reassemble, + count: 0, + }, + WorkerPoolRecv { recv_reassemble, recv_workers }, + ) +} + +fn reassemble( + pool: WorkerPoolRecv

, s: &rayon::ScopeFifo, + send_packet: Sender>, +) { + s.spawn_fifo(move |_| { + let mut pending = BTreeMap::new(); + let mut last_idx = 0; + let mut packet_index = 0; + for (idx, recv) in pool.recv_reassemble.iter() { + pending.insert(idx, recv); + while let Some(recv) = pending.remove(&last_idx) { + for mut p in recv { + // patch up the packet_index + p.input_frameno = packet_index; + let _ = send_packet.send(p); + packet_index += 1; + } + last_idx += 1; + } + } + + while !pending.is_empty() { + if let Some(recv) = pending.remove(&last_idx) { + for mut p in recv { + // patch up the packet_index + p.input_frameno = packet_index; + let _ = send_packet.send(p); + packet_index += 1; + } + } + last_idx += 1; + } + + pool.close(); + }); +} + +impl Config { + // Group the incoming frames in Gops, emit a SubGop at time. + fn scenechange( + &self, s: &rayon::ScopeFifo, r: Receiver>, + ) -> Receiver> { + let inter_cfg = InterConfig::new(&self.enc); + let pyramid_size = inter_cfg.keyframe_lookahead_distance() as usize; + let lookahead_distance = pyramid_size + 1 + 1; + let (send, recv) = bounded(lookahead_distance * 2); + + let mut sc = SceneChange::new(pyramid_size, &self.enc); + + s.spawn_fifo(move |_| { + let mut lookahead = Vec::new(); + for f in r.iter() { + let (frame, _params) = f; + + lookahead.push(frame.unwrap()); + + // we need at least lookahead_distance frames to reason + if lookahead.len() < lookahead_distance { + continue; + } + + if let Some((split_pos, end_gop)) = sc.split(&lookahead) { + let rem = lookahead.split_off(split_pos); + let _ = send.send(SubGop { frames: lookahead, end_gop }); + + lookahead = rem; + } + } + + while lookahead.len() > lookahead_distance { + if let Some((split_pos, end_gop)) = sc.split(&lookahead) { + let rem = lookahead.split_off(split_pos); + let _ = send.send(SubGop { frames: lookahead, end_gop }); + + lookahead = rem; + } + } + + if !lookahead.is_empty() { + let _ = send.send(SubGop { frames: lookahead, end_gop: true }); + } + }); + + recv + } + + /// Encode the subgops, dispatch each Gop to an available worker + fn encode( + &self, s: &rayon::ScopeFifo, workers: usize, r: Receiver>, + send_packet: Sender>, + ) { + let (mut workers, recv) = workerpool(s, workers, self.clone()); + + s.spawn_fifo(move |_| { + let mut sg_send = workers.get_worker().unwrap(); + for sb in r.iter() { + let end_gop = sb.end_gop; + let _ = sg_send.send(sb); + + if end_gop { + sg_send = workers.get_worker().unwrap(); + } + } + }); + + reassemble(recv, s, send_packet) + } + + /// Create a single pass by-gop encoder channel + /// + /// Drop the `FrameSender` endpoint to flush the encoder. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if configuration is invalid. + pub fn new_by_gop_channel( + &self, slots: usize, + ) -> Result, InvalidConfig> { + let rc = &self.rate_control; + + if rc.emit_pass_data || rc.summary.is_some() { + return Err(InvalidConfig::RateControlConfigurationMismatch); + } + + self.validate()?; + + // TODO: make it user-settable + let input_len = self.enc.speed_settings.rdo_lookahead_frames as usize * 4; + let frame_limit = i32::MAX as u64; + + let (send_frame, receive_frame) = bounded(input_len); + let (send_packet, receive_packet) = unbounded(); + + let cfg = self.clone(); + + let pool = self.new_thread_pool(); + + // TODO: move the accounting threads outside the threadpool + let run = move || { + let _ = rayon::scope_fifo(|s| { + let sg_recv = cfg.scenechange(s, receive_frame); + cfg.encode(s, slots, sg_recv, send_packet); + }); + }; + + if let Some(pool) = pool { + pool.spawn_fifo(run); + } else { + rayon::spawn_fifo(run); + } + + let channel = ( + FrameSender::new(frame_limit, send_frame, Arc::new(self.enc.clone())), + PacketReceiver { + receiver: receive_packet, + config: Arc::new(self.enc.clone()), + }, + ); + + Ok(channel) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/data.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/data.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/data.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/data.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,382 @@ +// Copyright (c) 2018-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::api::color::*; +use crate::api::config::EncoderConfig; +use crate::api::context::RcData; +use crate::api::util::*; +use crate::encoder::*; +use crate::frame::*; +use crate::util::Pixel; + +use bitstream_io::{BigEndian, BitWrite, BitWriter}; +use crossbeam::channel::{Receiver, Sender}; +use thiserror::Error; + +use std::io; +use std::sync::Arc; + +/// An error returned from the `send` methods. +/// +/// The message could not be sent because the channel is disconnected. +/// +/// The error contains the message so it can be recovered. +#[derive(PartialEq, Eq, Clone, Copy, Error)] +#[error("sending on a disconnected channel")] +pub struct SendError(pub T); + +/// An error returned from the `try_send` methods. +/// +/// The error contains the message being sent so it can be recovered. +#[derive(PartialEq, Eq, Clone, Copy, Error)] +pub enum TrySendError { + /// The message could not be sent because the channel is full. + #[error("sending on a full channel")] + Full(T), + + /// The message could not be sent because the channel is disconnected. + #[error("sending on a disconnected channel")] + Disconnected(T), +} + +/// An error returned from the `recv` methods. +/// +/// A message could not be received because the channel is empty and disconnected. +/// +#[derive(PartialEq, Eq, Clone, Copy, Debug, Error)] +#[error("receiving on an empty and disconnected channel")] +pub struct RecvError; + +/// An error returned from the `try_recv` methods. +/// +#[derive(PartialEq, Eq, Clone, Copy, Debug, Error)] +pub enum TryRecvError { + /// A message could not be received because the channel is empty. + #[error("receiving on an empty channel")] + Empty, + + /// The message could not be received because the channel is empty and disconnected. + #[error("receiving on an empty and disconnected channel")] + Disconnected, +} + +impl SendError { + fn from(value: crossbeam::channel::SendError) -> Self { + Self(value.0) + } +} + +impl TrySendError { + fn from(value: crossbeam::channel::TrySendError) -> Self { + use crossbeam::channel::TrySendError::*; + match value { + Full(v) => TrySendError::Full(v), + Disconnected(v) => TrySendError::Disconnected(v), + } + } +} +impl RecvError { + fn from(_: crossbeam::channel::RecvError) -> Self { + RecvError + } +} + +impl TryRecvError { + fn from(value: crossbeam::channel::TryRecvError) -> Self { + use crossbeam::channel::TryRecvError::*; + match value { + Empty => TryRecvError::Empty, + Disconnected => TryRecvError::Disconnected, + } + } +} + +/// Endpoint to send previous-pass statistics data +pub struct RcDataSender { + pub(crate) sender: Sender, + pub(crate) limit: u64, + pub(crate) count: u64, +} + +impl RcDataSender { + pub(crate) fn new(limit: u64, sender: Sender) -> RcDataSender { + Self { sender, limit, count: 0 } + } + + /// # Errors + /// + /// - `TrySendError::Full` if the message could not be sent because the channel is full. + /// - `TrySendError::Disconnected` if the message could not be sent + /// because the channel is disconnected. + pub fn try_send( + &mut self, data: RcData, + ) -> Result<(), TrySendError> { + if self.limit <= self.count { + Err(TrySendError::Full(data)) + } else { + let r = self.sender.try_send(data).map_err(TrySendError::from); + if r.is_ok() { + self.count += 1; + } + r + } + } + + /// # Errors + /// + /// - `SendError` if the message could not be sent because the channel is disconnected. + pub fn send(&mut self, data: RcData) -> Result<(), SendError> { + if self.limit <= self.count { + Err(SendError(data)) + } else { + let r = self.sender.send(data).map_err(SendError::from); + if r.is_ok() { + self.count += 1; + } + r + } + } + pub fn len(&self) -> usize { + self.sender.len() + } + pub fn is_empty(&self) -> bool { + self.sender.is_empty() + } + + // TODO: proxy more methods +} + +/// Endpoint to receive current-pass statistics data +pub struct RcDataReceiver(pub(crate) Receiver); + +impl RcDataReceiver { + /// Attempts to receive a message from the channel without blocking. + /// + /// This method will either receive a message from the channel immediately or return an error + /// if the channel is empty. + /// + /// If called on a zero-capacity channel, this method will receive a message only if there + /// happens to be a send operation on the other side of the channel at the same time. + /// + /// # Errors + /// + /// - `TryRecvError::Empty` if the channel is currently empty. + /// - `TryRecvError::Disconnected` if the channel is empty and has been disconnected. + pub fn try_recv(&self) -> Result { + self.0.try_recv().map_err(TryRecvError::from) + } + + /// Blocks the current thread until a message is received or the channel is empty and + /// disconnected. + /// + /// If the channel is empty and not disconnected, this call will block until the receive + /// operation can proceed. If the channel is empty and becomes disconnected, this call will + /// wake up and return an error. + /// + /// If called on a zero-capacity channel, this method will wait for a send operation to appear + /// on the other side of the channel. + /// + /// # Errors + /// + /// - `RecvError` if the channel is empty and has been disconnected. + pub fn recv(&self) -> Result { + self.0.recv().map_err(RecvError::from) + } + pub fn len(&self) -> usize { + self.0.len() + } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.0.iter() + } + + pub const fn summary_size(&self) -> usize { + crate::rate::TWOPASS_HEADER_SZ + } +} + +pub type PassDataChannel = (RcDataSender, RcDataReceiver); + +pub type FrameInput = (Option>>, Option); + +/// Endpoint to send frames +pub struct FrameSender { + sender: Sender>, + config: Arc, + limit: u64, + count: u64, +} + +// Proxy the crossbeam Sender +// +// TODO: enforce the limit +impl FrameSender { + pub(crate) fn new( + limit: u64, sender: Sender>, config: Arc, + ) -> FrameSender { + Self { sender, config, limit, count: 0 } + } + + /// # Errors + /// + /// - `TrySendError::Full` if the message could not be sent because the channel is full. + /// - `TrySendError::Disconnected` if the message could not be sent + /// because the channel is disconnected. + pub fn try_send>( + &mut self, frame: F, + ) -> Result<(), TrySendError>> { + if self.limit <= self.count { + Err(TrySendError::Full(frame.into())) + } else { + let r = self.sender.try_send(frame.into()).map_err(TrySendError::from); + if r.is_ok() { + self.count += 1; + } + r + } + } + + /// # Errors + /// + /// - `SendError` if the message could not be sent because the channel is disconnected. + pub fn send>( + &mut self, frame: F, + ) -> Result<(), SendError>> { + if self.limit <= self.count { + Err(SendError(frame.into())) + } else { + let r = self.sender.send(frame.into()).map_err(SendError::from); + if r.is_ok() { + self.count += 1; + } + r + } + } + pub fn len(&self) -> usize { + self.sender.len() + } + pub fn is_empty(&self) -> bool { + self.sender.is_empty() + } + // TODO: proxy more methods +} + +// Frame factory +impl FrameSender { + /// Helper to create a new frame with the current encoder configuration + #[inline] + pub fn new_frame(&self) -> Frame { + Frame::new( + self.config.width, + self.config.height, + self.config.chroma_sampling, + ) + } +} + +/// Endpoint to receive packets +pub struct PacketReceiver { + pub(crate) receiver: Receiver>, + pub(crate) config: Arc, +} + +impl PacketReceiver { + /// Attempts to receive a message from the channel without blocking. + /// + /// This method will either receive a message from the channel immediately or return an error + /// if the channel is empty. + /// + /// If called on a zero-capacity channel, this method will receive a message only if there + /// happens to be a send operation on the other side of the channel at the same time. + /// + /// # Errors + /// + /// - `TryRecvError::Empty` if the channel is currently empty. + /// - `TryRecvError::Disconnected` if the channel is empty and has been disconnected. + pub fn try_recv(&self) -> Result, TryRecvError> { + self.receiver.try_recv().map_err(TryRecvError::from) + } + /// Blocks the current thread until a message is received or the channel is empty and + /// disconnected. + /// + /// If the channel is empty and not disconnected, this call will block until the receive + /// operation can proceed. If the channel is empty and becomes disconnected, this call will + /// wake up and return an error. + /// + /// If called on a zero-capacity channel, this method will wait for a send operation to appear + /// on the other side of the channel. + /// + /// # Errors + /// + /// - `RecvError` if the channel is empty and has been disconnected. + pub fn recv(&self) -> Result, RecvError> { + self.receiver.recv().map_err(RecvError::from) + } + pub fn len(&self) -> usize { + self.receiver.len() + } + pub fn is_empty(&self) -> bool { + self.receiver.is_empty() + } + pub fn iter<'a>(&'a self) -> impl Iterator> + 'a { + self.receiver.iter() + } +} + +impl PacketReceiver { + /// Produces a sequence header matching the current encoding context. + /// + /// Its format is compatible with the AV1 Matroska and ISOBMFF specification. + /// Note that the returned header does not include any config OBUs which are + /// required for some uses. See [the specification]. + /// + /// [the specification]: + /// https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-section + /// + /// # Panics + /// + /// Panics if the header cannot be written in memory. This is unrecoverable, + /// and usually indicates the system is out of memory. + #[inline] + pub fn container_sequence_header(&self) -> Vec { + fn sequence_header_inner(seq: &Sequence) -> io::Result> { + let mut buf = Vec::new(); + + { + let mut bw = BitWriter::endian(&mut buf, BigEndian); + bw.write_bit(true)?; // marker + bw.write::<7, u8>(1)?; // version + bw.write::<3, u8>(seq.profile)?; + bw.write::<5, u8>(31)?; // level + bw.write_bit(false)?; // tier + bw.write_bit(seq.bit_depth > 8)?; // high_bitdepth + bw.write_bit(seq.bit_depth == 12)?; // twelve_bit + bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs400)?; // monochrome + bw.write_bit(seq.chroma_sampling != ChromaSampling::Cs444)?; // chroma_subsampling_x + bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs420)?; // chroma_subsampling_y + bw.write::<2, u8>(0)?; // chroma_sample_position + bw.write::<3, u8>(0)?; // reserved + bw.write_bit(false)?; // initial_presentation_delay_present + + bw.write::<4, u8>(0)?; // reserved + } + + Ok(buf) + } + + let seq = Sequence::new(&self.config); + + sequence_header_inner(&seq).unwrap() + } +} + +/// A channel modeling an encoding process +pub type VideoDataChannel = (FrameSender, PacketReceiver); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/channel/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/channel/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,368 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. +#![allow(missing_docs)] + +use crate::api::config::*; +use crate::api::context::RcData; +use crate::api::internal::ContextInner; +use crate::api::util::*; + +use crossbeam::channel::*; + +use crate::rate::RCState; +use crate::util::Pixel; + +use rayon::ThreadPool; +use std::sync::Arc; + +mod data; +pub use data::{ + FrameInput, FrameSender, PacketReceiver, PassDataChannel, RcDataReceiver, + RcDataSender, RecvError, SendError, TryRecvError, TrySendError, + VideoDataChannel, +}; + +mod by_gop; + +impl Config { + pub(crate) fn setup( + &self, + ) -> Result<(ContextInner, Option>), InvalidConfig> { + self.validate()?; + let inner = self.new_inner()?; + + let pool = self.new_thread_pool(); + + Ok((inner, pool)) + } +} + +impl Config { + /// Create a single pass encoder channel + /// + /// Drop the `FrameSender` endpoint to flush the encoder. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the configuration is invalid. + pub fn new_channel( + &self, + ) -> Result, InvalidConfig> { + let rc = &self.rate_control; + + if rc.emit_pass_data || rc.summary.is_some() { + return Err(InvalidConfig::RateControlConfigurationMismatch); + } + let v = if self.slots > 1 { + self.new_by_gop_channel(self.slots)? + } else { + self.new_channel_internal()?.0 + }; + + Ok(v) + } + + /// Create a first pass encoder channel + /// + /// The pass data information is emitted through this channel. + /// + /// Drop the `FrameSender` endpoint to flush the encoder. + /// The last buffer in the `PassDataReceiver` is the summary of the whole + /// encoding process. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the configuration is invalid. + /// + /// # Panics + /// + /// - If the channel cannot be created. An error should be raised before this, + /// so a panic indicates a development error. + pub fn new_firstpass_channel( + &self, + ) -> Result<(VideoDataChannel, RcDataReceiver), InvalidConfig> { + let rc = &self.rate_control; + + if !rc.emit_pass_data { + return Err(InvalidConfig::RateControlConfigurationMismatch); + } + + if self.slots > 1 { + log::warn!( + "Parallel gop encoding does not support multi pass rate control" + ); + } + + let (v, (_, r)) = self.new_channel_internal()?; + + Ok((v, r.unwrap())) + } + + /// Create a second pass encoder channel + /// + /// The encoding process require both frames and pass data to progress. + /// + /// Drop the `FrameSender` endpoint to flush the encoder. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the configuration is invalid. + /// + /// # Panics + /// + /// - If the channel cannot be created. An error should be raised before this, + /// so a panic indicates a development error. + pub fn new_secondpass_channel( + &self, + ) -> Result<(VideoDataChannel, RcDataSender), InvalidConfig> { + let rc = &self.rate_control; + if rc.emit_pass_data || rc.summary.is_none() { + return Err(InvalidConfig::RateControlConfigurationMismatch); + } + + if self.slots > 1 { + log::warn!( + "Parallel gop encoding does not support multi pass rate control" + ); + } + + let (v, (s, _)) = self.new_channel_internal()?; + + Ok((v, s.unwrap())) + } + + /// Create a multipass encoder channel + /// + /// The `PacketReceiver` may block if not enough pass statistics data + /// are sent through the `PassDataSender` endpoint + /// + /// Drop the `FrameSender` endpoint to flush the encoder. + /// The last buffer in the `PassDataReceiver` is the summary of the whole + /// encoding process. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the configuration is invalid. + /// + /// # Panics + /// + /// - If the channel cannot be created. An error should be raised before this, + /// so a panic indicates a development error. + pub fn new_multipass_channel( + &self, + ) -> Result<(VideoDataChannel, PassDataChannel), InvalidConfig> { + let rc = &self.rate_control; + if rc.summary.is_none() || !rc.emit_pass_data { + return Err(InvalidConfig::RateControlConfigurationMismatch); + } + + if self.slots > 1 { + log::warn!( + "Parallel gop encoding does not support multi pass rate control" + ); + } + + let (v, (s, r)) = self.new_channel_internal()?; + + Ok((v, (s.unwrap(), r.unwrap()))) + } +} + +trait RcFirstPass { + fn send_pass_data(&mut self, rc_state: &mut RCState); + fn send_pass_summary(&mut self, rc_state: &mut RCState); +} + +trait RcSecondPass { + fn feed_pass_data( + &mut self, inner: &mut ContextInner, + ) -> Result<(), ()>; +} + +impl RcFirstPass for Sender { + fn send_pass_data(&mut self, rc_state: &mut RCState) { + if let Some(data) = rc_state.emit_frame_data() { + let data = data.to_vec().into_boxed_slice(); + self.send(RcData::Frame(data)).unwrap(); + } else { + unreachable!( + "The encoder received more frames than its internal + limit allows" + ); + } + } + fn send_pass_summary(&mut self, rc_state: &mut RCState) { + let data = rc_state.emit_summary(); + let data = data.to_vec().into_boxed_slice(); + self.send(RcData::Summary(data)).unwrap(); + } +} + +impl RcFirstPass for Option> { + fn send_pass_data(&mut self, rc_state: &mut RCState) { + if let Some(s) = self.as_mut() { + s.send_pass_data(rc_state) + } + } + fn send_pass_summary(&mut self, rc_state: &mut RCState) { + if let Some(s) = self.as_mut() { + s.send_pass_summary(rc_state) + } + } +} + +impl RcSecondPass for Receiver { + fn feed_pass_data( + &mut self, inner: &mut ContextInner, + ) -> Result<(), ()> { + while inner.rc_state.twopass_in_frames_needed() > 0 + && !inner.done_processing() + { + if let Ok(RcData::Frame(data)) = self.recv() { + inner + .rc_state + .parse_frame_data_packet(data.as_ref()) + .unwrap_or_else(|_| todo!("Error reporting")); + } else { + todo!("Error reporting"); + } + } + + Ok(()) + } +} + +impl RcSecondPass for Option> { + fn feed_pass_data( + &mut self, inner: &mut ContextInner, + ) -> Result<(), ()> { + match self.as_mut() { + Some(s) => s.feed_pass_data(inner), + None => Ok(()), + } + } +} + +impl Config { + #[allow(clippy::type_complexity)] + fn new_channel_internal( + &self, + ) -> Result< + (VideoDataChannel, (Option, Option)), + InvalidConfig, + > { + // The inner context is already configured to use the summary at this point. + let (mut inner, pool) = self.setup()?; + + // TODO: make it user-settable + let input_len = self.enc.speed_settings.rdo_lookahead_frames as usize * 2; + + let (send_frame, receive_frame) = bounded(input_len); + let (send_packet, receive_packet) = unbounded(); + + let rc = &self.rate_control; + + let (mut send_rc_pass1, rc_data_receiver) = if rc.emit_pass_data { + let (send_rc_pass1, receive_rc_pass1) = unbounded(); + (Some(send_rc_pass1), Some(RcDataReceiver(receive_rc_pass1))) + } else { + (None, None) + }; + + let (rc_data_sender, mut receive_rc_pass2, frame_limit) = if rc + .summary + .is_some() + { + let (frame_limit, pass_limit) = + rc.summary.as_ref().map(|s| (s.ntus as u64, s.total as u64)).unwrap(); + + inner.limit = Some(frame_limit); + + let (send_rc_pass2, receive_rc_pass2) = unbounded(); + + ( + Some(RcDataSender::new(pass_limit, send_rc_pass2)), + Some(receive_rc_pass2), + frame_limit, + ) + } else { + (None, None, i32::MAX as u64) + }; + + let config = Arc::new(self.enc.clone()); + + let channel = ( + FrameSender::new(frame_limit, send_frame, config.clone()), + PacketReceiver { receiver: receive_packet, config }, + ); + + let pass_channel = (rc_data_sender, rc_data_receiver); + + let run = move || { + for f in receive_frame.iter() { + // info!("frame in {}", inner.frame_count); + while !inner.needs_more_fi_lookahead() { + receive_rc_pass2.feed_pass_data(&mut inner).unwrap(); + // needs_more_fi_lookahead() should guard for missing output_frameno + // already. + // + // this call should return either Ok or Err(Encoded) + let has_pass_data = match inner.receive_packet() { + Ok(p) => { + send_packet.send(p).unwrap(); + true + } + Err(EncoderStatus::Encoded) => true, + Err(EncoderStatus::NotReady) => todo!("Error reporting"), + _ => unreachable!(), + }; + if has_pass_data { + send_rc_pass1.send_pass_data(&mut inner.rc_state); + } + } + + let (frame, params) = f; + let _ = inner.send_frame(frame, params); // TODO make sure it cannot fail. + } + + inner.limit = Some(inner.frame_count); + let _ = inner.send_frame(None, None); + + loop { + receive_rc_pass2.feed_pass_data(&mut inner).unwrap(); + let r = inner.receive_packet(); + let has_pass_data = match r { + Ok(p) => { + // warn!("Sending out {}", p.input_frameno); + send_packet.send(p).unwrap(); + true + } + Err(EncoderStatus::LimitReached) => break, + Err(EncoderStatus::Encoded) => true, + Err(EncoderStatus::NotReady) => todo!("Error reporting"), + _ => unreachable!(), + }; + + if has_pass_data { + send_rc_pass1.send_pass_data(&mut inner.rc_state); + } + } + + send_rc_pass1.send_pass_summary(&mut inner.rc_state); + }; + + if let Some(pool) = pool { + pool.spawn(run); + } else { + rayon::spawn(run); + } + + Ok((channel, pass_channel)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/color.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/color.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/color.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/color.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,270 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::serialize::*; +use crate::wasm_bindgen::*; + +use arg_enum_proc_macro::ArgEnum; +use num_derive::FromPrimitive; + +/// Sample position for subsampled chroma +#[wasm_bindgen] +#[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, + Default, +)] +#[repr(C)] +pub enum ChromaSamplePosition { + /// The source video transfer function must be signaled + /// outside the AV1 bitstream. + #[default] + Unknown, + /// Horizontally co-located with (0, 0) luma sample, vertically positioned + /// in the middle between two luma samples. + Vertical, + /// Co-located with (0, 0) luma sample. + Colocated, +} + +pub use v_frame::pixel::ChromaSampling; + +/// Supported Color Primaries +/// +/// As defined by “Color primaries” section of ISO/IEC 23091-4/ITU-T H.273 +#[derive( + ArgEnum, + Debug, + Clone, + Copy, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, + Default, +)] +#[repr(C)] +pub enum ColorPrimaries { + /// BT.709 + BT709 = 1, + /// Unspecified, must be signaled or inferred outside of the bitstream + #[default] + Unspecified, + /// BT.470 System M (historical) + BT470M = 4, + /// BT.470 System B, G (historical) + BT470BG, + /// BT.601-7 525 (SMPTE 170 M) + BT601, + /// SMPTE 240M (historical) + SMPTE240, + /// Generic film + GenericFilm, + /// BT.2020, BT.2100 + BT2020, + /// SMPTE 248 (CIE 1921 XYZ) + XYZ, + /// SMPTE RP 431-2 + SMPTE431, + /// SMPTE EG 432-1 + SMPTE432, + /// EBU Tech. 3213-E + EBU3213 = 22, +} + +/// Supported Transfer Characteristics +/// +/// As defined by “Transfer characteristics” section of ISO/IEC 23091-4/ITU-TH.273. +#[derive( + ArgEnum, + Debug, + Clone, + Copy, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, + Default, +)] +#[repr(C)] +pub enum TransferCharacteristics { + /// BT.709 + BT709 = 1, + /// Unspecified, must be signaled or inferred outside of the bitstream + #[default] + Unspecified, + /// BT.470 System M (historical) + BT470M = 4, + /// BT.470 System B, G (historical) + BT470BG, + /// BT.601-7 525 (SMPTE 170 M) + BT601, + /// SMPTE 240 M + SMPTE240, + /// Linear + Linear, + /// Logarithmic (100:1 range) + Log100, + /// Logarithmic ((100 * √10):1 range) + Log100Sqrt10, + /// IEC 61966-2-4 + IEC61966, + /// BT.1361 extended color gamut system (historical) + BT1361, + /// sRGB or sYCC + SRGB, + /// BT.2020 10-bit systems + BT2020_10Bit, + /// BT.2020 12-bit systems + BT2020_12Bit, + /// SMPTE ST 2084, ITU BT.2100 PQ + SMPTE2084, + /// SMPTE ST 428 + SMPTE428, + /// BT.2100 HLG (Hybrid Log Gamma), ARIB STD-B67 + HLG, +} + +/// Matrix coefficients +/// +/// As defined by the “Matrix coefficients” section of ISO/IEC 23091-4/ITU-TH.273. +#[derive( + ArgEnum, + Debug, + Clone, + Copy, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, + Default, +)] +#[repr(C)] +pub enum MatrixCoefficients { + /// Identity matrix + Identity = 0, + /// BT.709 + BT709, + /// Unspecified, must be signaled or inferred outside of the bitstream. + #[default] + Unspecified, + /// US FCC 73.628 + FCC = 4, + /// BT.470 System B, G (historical) + BT470BG, + /// BT.601-7 525 (SMPTE 170 M) + BT601, + /// SMPTE 240 M + SMPTE240, + /// `YCgCo` + YCgCo, + /// BT.2020 non-constant luminance, BT.2100 `YCbCr` + BT2020NCL, + /// BT.2020 constant luminance + BT2020CL, + /// SMPTE ST 2085 `YDzDx` + SMPTE2085, + /// Chromaticity-derived non-constant luminance + ChromatNCL, + /// Chromaticity-derived constant luminance + ChromatCL, + /// BT.2020 `ICtCp` + ICtCp, +} + +/// Signal the content color description +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct ColorDescription { + /// Color primaries. + pub color_primaries: ColorPrimaries, + /// Transfer charasteristics. + pub transfer_characteristics: TransferCharacteristics, + /// Matrix coefficients. + pub matrix_coefficients: MatrixCoefficients, +} + +impl ColorDescription { + pub(crate) fn is_srgb_triple(self) -> bool { + self.color_primaries == ColorPrimaries::BT709 + && self.transfer_characteristics == TransferCharacteristics::SRGB + && self.matrix_coefficients == MatrixCoefficients::Identity + } +} + +/// Allowed pixel value range +/// +/// C.f. `VideoFullRangeFlag` variable specified in ISO/IEC 23091-4/ITU-T H.273 +#[wasm_bindgen] +#[derive( + ArgEnum, + Debug, + Clone, + Copy, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, + Default, +)] +#[repr(C)] +pub enum PixelRange { + /// Studio swing representation + #[default] + Limited, + /// Full swing representation + Full, +} + +/// High dynamic range content light level +/// +/// As defined by CEA-861.3, Appendix A. +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct ContentLight { + /// Maximum content light level + pub max_content_light_level: u16, + /// Maximum frame-average light level + pub max_frame_average_light_level: u16, +} + +/// Chromaticity coordinates as defined by CIE 1931, expressed as 0.16 +/// fixed-point values. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[repr(C)] +pub struct ChromaticityPoint { + /// The X coordinate. + pub x: u16, + /// The Y coordinate. + pub y: u16, +} + +/// High dynamic range mastering display color volume +/// +/// As defined by CIE 1931 +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct MasteringDisplay { + /// Chromaticity coordinates in Red, Green, Blue order + /// expressed as 0.16 fixed-point + pub primaries: [ChromaticityPoint; 3], + /// Chromaticity coordinates expressed as 0.16 fixed-point + pub white_point: ChromaticityPoint, + /// 24.8 fixed-point maximum luminance in candelas per square meter + pub max_luminance: u32, + /// 18.14 fixed-point minimum luminance in candelas per square meter + pub min_luminance: u32, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,347 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use itertools::*; + +use crate::api::color::*; +use crate::api::config::GrainTableSegment; +use crate::api::{Rational, SpeedSettings}; +use crate::encoder::Tune; +use crate::serialize::{Deserialize, Serialize}; + +use std::fmt; + +// We add 1 to rdo_lookahead_frames in a bunch of places. +pub(crate) const MAX_RDO_LOOKAHEAD_FRAMES: usize = usize::MAX - 1; +// Due to the math in RCState::new() regarding the reservoir frame delay. +pub(crate) const MAX_MAX_KEY_FRAME_INTERVAL: u64 = i32::MAX as u64 / 3; + +/// Encoder settings which impact the produced bitstream. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct EncoderConfig { + // output size + /// Width of the frames in pixels. + pub width: usize, + /// Height of the frames in pixels. + pub height: usize, + /// Sample aspect ratio (for anamorphic video). + pub sample_aspect_ratio: Rational, + /// Video time base. + pub time_base: Rational, + + // data format and ancillary color information + /// Bit depth. + pub bit_depth: usize, + /// Chroma subsampling. + pub chroma_sampling: ChromaSampling, + /// Chroma sample position. + pub chroma_sample_position: ChromaSamplePosition, + /// Pixel value range. + pub pixel_range: PixelRange, + /// Content color description (primaries, transfer characteristics, matrix). + pub color_description: Option, + /// HDR mastering display parameters. + pub mastering_display: Option, + /// HDR content light parameters. + pub content_light: Option, + + /// AV1 level index to target (0-31). + /// If None, allow the encoder to decide. + /// Currently, rav1e is unable to guarantee that the output bitstream + /// meets the rate limitations of the specified level. + pub level_idx: Option, + + /// Enable signaling timing info in the bitstream. + pub enable_timing_info: bool, + + /// Still picture mode flag. + pub still_picture: bool, + + /// Flag to force all frames to be error resilient. + pub error_resilient: bool, + + /// Interval between switch frames (0 to disable) + pub switch_frame_interval: u64, + + // encoder configuration + /// The *minimum* interval between two keyframes + pub min_key_frame_interval: u64, + /// The *maximum* interval between two keyframes + pub max_key_frame_interval: u64, + /// The number of temporal units over which to distribute the reservoir + /// usage. + pub reservoir_frame_delay: Option, + /// Flag to enable low latency mode. + /// + /// In this mode the frame reordering is disabled. + pub low_latency: bool, + /// The base quantizer to use. + pub quantizer: usize, + /// The minimum allowed base quantizer to use in bitrate mode. + pub min_quantizer: u8, + /// The target bitrate for the bitrate mode. + pub bitrate: i32, + /// Metric to tune the quality for. + pub tune: Tune, + /// Parameters for grain synthesis. + pub film_grain_params: Option>, + /// Number of tiles horizontally. Must be a power of two. + /// + /// Overridden by [`tiles`], if present. + /// + /// [`tiles`]: #structfield.tiles + pub tile_cols: usize, + /// Number of tiles vertically. Must be a power of two. + /// + /// Overridden by [`tiles`], if present. + /// + /// [`tiles`]: #structfield.tiles + pub tile_rows: usize, + /// Total number of tiles desired. + /// + /// Encoder will try to optimally split to reach this number of tiles, + /// rounded up. Overrides [`tile_cols`] and [`tile_rows`]. + /// + /// [`tile_cols`]: #structfield.tile_cols + /// [`tile_rows`]: #structfield.tile_rows + pub tiles: usize, + + /// Settings which affect the encoding speed vs. quality trade-off. + pub speed_settings: SpeedSettings, +} + +/// Default preset for `EncoderConfig`: it is a balance between quality and +/// speed. See [`with_speed_preset()`]. +/// +/// [`with_speed_preset()`]: struct.EncoderConfig.html#method.with_speed_preset +impl Default for EncoderConfig { + fn default() -> Self { + const DEFAULT_SPEED: u8 = 6; + Self::with_speed_preset(DEFAULT_SPEED) + } +} + +impl EncoderConfig { + /// This is a preset which provides default settings according to a speed + /// value in the specific range 0–10. Each speed value corresponds to a + /// different preset. See [`from_preset()`]. If the input value is greater + /// than 10, it will result in the same settings as 10. + /// + /// [`from_preset()`]: struct.SpeedSettings.html#method.from_preset + pub fn with_speed_preset(speed: u8) -> Self { + EncoderConfig { + width: 640, + height: 480, + sample_aspect_ratio: Rational { num: 1, den: 1 }, + time_base: Rational { num: 1, den: 30 }, + + bit_depth: 8, + chroma_sampling: ChromaSampling::Cs420, + chroma_sample_position: ChromaSamplePosition::Unknown, + pixel_range: Default::default(), + color_description: None, + mastering_display: None, + content_light: None, + + level_idx: None, + + enable_timing_info: false, + + still_picture: false, + + error_resilient: false, + switch_frame_interval: 0, + + min_key_frame_interval: 12, + max_key_frame_interval: 240, + min_quantizer: 0, + reservoir_frame_delay: None, + low_latency: false, + quantizer: 100, + bitrate: 0, + tune: Tune::default(), + film_grain_params: None, + tile_cols: 0, + tile_rows: 0, + tiles: 0, + speed_settings: SpeedSettings::from_preset(speed), + } + } + + /// Sets the minimum and maximum keyframe interval, handling special cases as needed. + pub fn set_key_frame_interval( + &mut self, min_interval: u64, max_interval: u64, + ) { + self.min_key_frame_interval = min_interval; + + // Map an input value of 0 to an infinite interval + self.max_key_frame_interval = if max_interval == 0 { + MAX_MAX_KEY_FRAME_INTERVAL + } else { + max_interval + }; + } + + /// Returns the video frame rate computed from [`time_base`]. + /// + /// [`time_base`]: #structfield.time_base + pub fn frame_rate(&self) -> f64 { + Rational::from_reciprocal(self.time_base).as_f64() + } + + /// Computes the render width and height of the stream based + /// on [`width`], [`height`], and [`sample_aspect_ratio`]. + /// + /// [`width`]: #structfield.width + /// [`height`]: #structfield.height + /// [`sample_aspect_ratio`]: #structfield.sample_aspect_ratio + pub fn render_size(&self) -> (usize, usize) { + let sar = self.sample_aspect_ratio.as_f64(); + + if sar > 1.0 { + ((self.width as f64 * sar).round() as usize, self.height) + } else { + (self.width, (self.height as f64 / sar).round() as usize) + } + } + + /// Is temporal RDO enabled ? + #[inline] + pub const fn temporal_rdo(&self) -> bool { + // Note: This function is called frequently, unlike most other functions here. + + // `compute_distortion_scale` computes a scaling factor for the distortion + // of an 8x8 block (4x4 blocks simply use the scaling of the enclosing 8x8 + // block). As long as distortion is always computed on <= 8x8 blocks, this + // has the property that the scaled distortion of a 2Nx2N block is always + // equal to the sum of the scaled distortions of the NxN sub-blocks it's + // made of, this is a necessary property to be able to do RDO between + // multiple partition sizes properly. Unfortunately, when tx domain + // distortion is used, distortion is only known at the tx block level which + // might be bigger than 8x8. So temporal RDO is always disabled in that case. + !self.speed_settings.transform.tx_domain_distortion + } + + /// Describes whether the output is targeted as HDR + pub fn is_hdr(&self) -> bool { + self + .color_description + .map(|colors| { + colors.transfer_characteristics == TransferCharacteristics::SMPTE2084 + }) + .unwrap_or(false) + } + + pub(crate) fn get_film_grain_at( + &self, timestamp: u64, + ) -> Option<&GrainTableSegment> { + self.film_grain_params.as_ref().and_then(|entries| { + entries.iter().find(|entry| { + timestamp >= entry.start_time && timestamp < entry.end_time + }) + }) + } + + pub(crate) fn get_film_grain_mut_at( + &mut self, timestamp: u64, + ) -> Option<&mut GrainTableSegment> { + self.film_grain_params.as_mut().and_then(|entries| { + entries.iter_mut().find(|entry| { + timestamp >= entry.start_time && timestamp < entry.end_time + }) + }) + } +} + +impl fmt::Display for EncoderConfig { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let pairs = [ + ("keyint_min", self.min_key_frame_interval.to_string()), + ("keyint_max", self.max_key_frame_interval.to_string()), + ("quantizer", self.quantizer.to_string()), + ("bitrate", self.bitrate.to_string()), + ("min_quantizer", self.min_quantizer.to_string()), + ("low_latency", self.low_latency.to_string()), + ("tune", self.tune.to_string()), + ( + "rdo_lookahead_frames", + self.speed_settings.rdo_lookahead_frames.to_string(), + ), + ( + "multiref", + (!self.low_latency || self.speed_settings.multiref).to_string(), + ), + ("fast_deblock", self.speed_settings.fast_deblock.to_string()), + ( + "scene_detection_mode", + self.speed_settings.scene_detection_mode.to_string(), + ), + ("cdef", self.speed_settings.cdef.to_string()), + ("lrf", self.speed_settings.lrf.to_string()), + ("enable_timing_info", self.enable_timing_info.to_string()), + ( + "min_block_size", + self.speed_settings.partition.partition_range.min.to_string(), + ), + ( + "max_block_size", + self.speed_settings.partition.partition_range.max.to_string(), + ), + ( + "encode_bottomup", + self.speed_settings.partition.encode_bottomup.to_string(), + ), + ( + "non_square_partition_max_threshold", + self + .speed_settings + .partition + .non_square_partition_max_threshold + .to_string(), + ), + ( + "reduced_tx_set", + self.speed_settings.transform.reduced_tx_set.to_string(), + ), + ( + "tx_domain_distortion", + self.speed_settings.transform.tx_domain_distortion.to_string(), + ), + ( + "tx_domain_rate", + self.speed_settings.transform.tx_domain_rate.to_string(), + ), + ( + "rdo_tx_decision", + self.speed_settings.transform.rdo_tx_decision.to_string(), + ), + ( + "prediction_modes", + self.speed_settings.prediction.prediction_modes.to_string(), + ), + ( + "fine_directional_intra", + self.speed_settings.prediction.fine_directional_intra.to_string(), + ), + ( + "include_near_mvs", + self.speed_settings.motion.include_near_mvs.to_string(), + ), + ( + "use_satd_subpel", + self.speed_settings.motion.use_satd_subpel.to_string(), + ), + ]; + write!( + f, + "{}", + pairs.iter().map(|pair| format!("{}={}", pair.0, pair.1)).join(" ") + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,458 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use thiserror::Error; + +use rayon::{ThreadPool, ThreadPoolBuilder}; +use std::sync::Arc; + +use crate::api::{ChromaSampling, Context, ContextInner, PixelRange}; +use crate::util::Pixel; + +mod encoder; +pub use encoder::*; + +pub use av1_grain::*; + +use crate::levels::*; + +mod rate; +pub use rate::Error as RateControlError; +pub use rate::{RateControlConfig, RateControlSummary}; + +mod speedsettings; +pub use speedsettings::*; + +pub use crate::tiling::TilingInfo; + +/// Enumeration of possible invalid configuration errors. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Error)] +#[non_exhaustive] +pub enum InvalidConfig { + /// The width is invalid. + #[error("invalid width {0} (expected >= 16, <= 65535)")] + InvalidWidth(usize), + /// The height is invalid. + #[error("invalid height {0} (expected >= 16, <= 65535)")] + InvalidHeight(usize), + /// Aspect ratio numerator is invalid. + #[error("invalid aspect ratio numerator {0} (expected > 0)")] + InvalidAspectRatioNum(usize), + /// Aspect ratio denominator is invalid. + #[error("invalid aspect ratio denominator {0} (expected > 0)")] + InvalidAspectRatioDen(usize), + /// The render width (width adjusted based on the aspect ratio) is invalid. + #[error("invalid render width {0} (expected >= 1, <= 65535")] + InvalidRenderWidth(usize), + /// The render height (height adjusted based on the aspect ratio) is invalid. + #[error("invalid render height {0} (expected >= 1, <= 65535")] + InvalidRenderHeight(usize), + /// RDO lookahead frame count is invalid. + #[error( + "invalid rdo lookahead frames {actual} (expected <= {max} and >= {min})" + )] + InvalidRdoLookaheadFrames { + /// The actual value. + actual: usize, + /// The maximal supported value. + max: usize, + /// The minimal supported value. + min: usize, + }, + /// Maximal keyframe interval is invalid. + #[error("invalid max keyframe interval {actual} (expected <= {max})")] + InvalidMaxKeyFrameInterval { + /// The actual value. + actual: u64, + /// The maximal supported value. + max: u64, + }, + /// Tile columns is invalid. + #[error("invalid tile cols {0} (expected power of 2)")] + InvalidTileCols(usize), + /// Tile rows is invalid. + #[error("invalid tile rows {0} (expected power of 2)")] + InvalidTileRows(usize), + /// Framerate numerator is invalid. + #[error("invalid framerate numerator {actual} (expected > 0, <= {max})")] + InvalidFrameRateNum { + /// The actual value. + actual: u64, + /// The maximal supported value. + max: u64, + }, + /// Framerate denominator is invalid. + #[error("invalid framerate denominator {actual} (expected > 0, <= {max})")] + InvalidFrameRateDen { + /// The actual value. + actual: u64, + /// The maximal supported value. + max: u64, + }, + /// Reservoir frame delay is invalid. + #[error("invalid reservoir frame delay {0} (expected >= 12, <= 131072)")] + InvalidReservoirFrameDelay(i32), + /// Reservoir frame delay is invalid. + #[error( + "invalid switch frame interval {0} (must only be used with low latency mode)" + )] + InvalidSwitchFrameInterval(u64), + + /// An option unsupported in still picture mode was enabled along with it. + #[error("invalid option {0} specified with still picture mode")] + InvalidOptionWithStillPicture(&'static str), + + /// The rate control needs a target bitrate in order to produce results + #[error("The rate control requires a target bitrate")] + TargetBitrateNeeded, + + /// The configuration + #[error("Mismatch in the rate control configuration")] + RateControlConfigurationMismatch, + + /// The color configuration mismatches AV1 constraints. + #[error("Mismatch in the color configuration")] + ColorConfigurationMismatch, + + /// The specified level is undefined in the current version of AV1. + #[error("Specified level is undefined")] + LevelUndefined, + + /// The configuration exceeded the specified level constraints. + #[error("Constraints exceeded for specified level")] + LevelConstraintsExceeded, +} + +/// Contains the encoder configuration. +#[derive(Clone, Debug, Default)] +pub struct Config { + /// Settings which impact the produced bitstream. + pub(crate) enc: EncoderConfig, + /// Rate control configuration + pub(crate) rate_control: RateControlConfig, + /// The number of threads in the threadpool. + pub(crate) threads: usize, + /// Shared thread pool + pub(crate) pool: Option>, + #[cfg(feature = "unstable")] + /// Number of parallel encoding slots + pub(crate) slots: usize, +} + +impl Config { + /// Create a default configuration + /// + /// same as `Default::default()` + pub fn new() -> Self { + Config::default() + } + + /// Set the encoder configuration + /// + /// `EncoderConfig` contains the settings impacting the + /// codec features used in the produced bitstream. + pub fn with_encoder_config(mut self, enc: EncoderConfig) -> Self { + self.enc = enc; + self + } + + /// Set the number of workers in the threadpool + /// + /// The threadpool is shared across all the different parallel + /// components in the encoder. + /// + /// If it is left unset, the encoder will use the default global + /// threadpool provided by Rayon instead. + pub const fn with_threads(mut self, threads: usize) -> Self { + self.threads = threads; + self + } + + /// Set the rate control configuration + /// + /// The default configuration is single pass + pub const fn with_rate_control( + mut self, rate_control: RateControlConfig, + ) -> Self { + self.rate_control = rate_control; + self + } + + #[cfg(feature = "unstable")] + /// Use the provided threadpool + /// + /// It takes priority over `with_threads()` + pub fn with_thread_pool(mut self, pool: Arc) -> Self { + self.pool = Some(pool); + self + } + + #[cfg(feature = "unstable")] + /// Set the maximum number of GOPs to encode in parallel + pub const fn with_parallel_gops(mut self, slots: usize) -> Self { + self.slots = slots; + self + } +} + +fn check_tile_log2(n: usize) -> bool { + let tile_log2 = TilingInfo::tile_log2(1, n); + if tile_log2.is_none() { + return false; + } + let tile_log2 = tile_log2.unwrap(); + + ((1 << tile_log2) - n) == 0 || n == 0 +} + +impl Config { + pub(crate) fn new_inner( + &self, + ) -> Result, InvalidConfig> { + assert!( + 8 * std::mem::size_of::() >= self.enc.bit_depth, + "The Pixel u{} does not match the Config bit_depth {}", + 8 * std::mem::size_of::(), + self.enc.bit_depth + ); + + self.validate()?; + + let mut config = self.enc.clone(); + config.set_key_frame_interval( + config.min_key_frame_interval, + config.max_key_frame_interval, + ); + + // FIXME: inter unsupported with 4:2:2 and 4:4:4 chroma sampling + let chroma_sampling = config.chroma_sampling; + + // FIXME: tx partition for intra not supported for chroma 422 + if chroma_sampling == ChromaSampling::Cs422 { + config.speed_settings.transform.rdo_tx_decision = false; + } + + let mut inner = ContextInner::new(&config); + + if let Some(ref s) = self.rate_control.summary { + inner.rc_state.init_second_pass(); + inner.rc_state.setup_second_pass(s); + } + + // First-pass parameters depend on whether second-pass is in effect. + // So `init_first_pass` must follow `init_second_pass`. + if self.rate_control.emit_pass_data { + let maybe_pass1_log_base_q = (self.rate_control.summary.is_none()) + .then(|| inner.rc_state.select_pass1_log_base_q(&inner, 0)); + inner.rc_state.init_first_pass(maybe_pass1_log_base_q); + } + + Ok(inner) + } + + /// Create a new threadpool with this configuration if set, + /// or return `None` if global threadpool should be used instead. + pub(crate) fn new_thread_pool(&self) -> Option> { + if let Some(ref p) = self.pool { + Some(p.clone()) + } else if self.threads != 0 { + let pool = + ThreadPoolBuilder::new().num_threads(self.threads).build().unwrap(); + Some(Arc::new(pool)) + } else { + None + } + } + + /// Creates a [`Context`] with this configuration. + /// + /// # Errors + /// + /// Returns `InvalidConfig` if the config is invalid. + /// + /// # Examples + /// + /// ``` + /// use rav1e::prelude::*; + /// + /// # fn main() -> Result<(), InvalidConfig> { + /// let cfg = Config::default(); + /// let ctx: Context = cfg.new_context()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`Context`]: struct.Context.html + pub fn new_context(&self) -> Result, InvalidConfig> { + let inner = self.new_inner()?; + let config = (*inner.config).clone(); + let pool = self.new_thread_pool(); + + Ok(Context { is_flushing: false, inner, pool, config }) + } + + /// Validates the configuration. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the tiling config is invalid. + pub fn validate(&self) -> Result<(), InvalidConfig> { + use InvalidConfig::*; + + let config = &self.enc; + + if (config.still_picture && config.width < 1) + || (!config.still_picture && config.width < 16) + || config.width > u16::MAX as usize + { + return Err(InvalidWidth(config.width)); + } + if (config.still_picture && config.height < 1) + || (!config.still_picture && config.height < 16) + || config.height > u16::MAX as usize + { + return Err(InvalidHeight(config.height)); + } + + if config.sample_aspect_ratio.num == 0 { + return Err(InvalidAspectRatioNum( + config.sample_aspect_ratio.num as usize, + )); + } + if config.sample_aspect_ratio.den == 0 { + return Err(InvalidAspectRatioDen( + config.sample_aspect_ratio.den as usize, + )); + } + + let (render_width, render_height) = config.render_size(); + if render_width == 0 || render_width > u16::MAX as usize { + return Err(InvalidRenderWidth(render_width)); + } + if render_height == 0 || render_height > u16::MAX as usize { + return Err(InvalidRenderHeight(render_height)); + } + + if config.speed_settings.rdo_lookahead_frames > MAX_RDO_LOOKAHEAD_FRAMES + || config.speed_settings.rdo_lookahead_frames < 1 + { + return Err(InvalidRdoLookaheadFrames { + actual: config.speed_settings.rdo_lookahead_frames, + max: MAX_RDO_LOOKAHEAD_FRAMES, + min: 1, + }); + } + if config.max_key_frame_interval > MAX_MAX_KEY_FRAME_INTERVAL { + return Err(InvalidMaxKeyFrameInterval { + actual: config.max_key_frame_interval, + max: MAX_MAX_KEY_FRAME_INTERVAL, + }); + } + + if !check_tile_log2(config.tile_cols) { + return Err(InvalidTileCols(config.tile_cols)); + } + if !check_tile_log2(config.tile_rows) { + return Err(InvalidTileRows(config.tile_rows)); + } + + if config.time_base.num == 0 || config.time_base.num > u32::MAX as u64 { + return Err(InvalidFrameRateNum { + actual: config.time_base.num, + max: u32::MAX as u64, + }); + } + if config.time_base.den == 0 || config.time_base.den > u32::MAX as u64 { + return Err(InvalidFrameRateDen { + actual: config.time_base.den, + max: u32::MAX as u64, + }); + } + + if let Some(delay) = config.reservoir_frame_delay { + if !(12..=131_072).contains(&delay) { + return Err(InvalidReservoirFrameDelay(delay)); + } + } + + if config.switch_frame_interval > 0 && !config.low_latency { + return Err(InvalidSwitchFrameInterval(config.switch_frame_interval)); + } + + if config.enable_timing_info && config.still_picture { + return Err(InvalidOptionWithStillPicture("enable_timing_info")); + } + + // + if let Some(color_description) = config.color_description { + if config.chroma_sampling != ChromaSampling::Cs400 + && color_description.is_srgb_triple() + { + if config.pixel_range != PixelRange::Full { + return Err(ColorConfigurationMismatch); + } + if config.chroma_sampling != ChromaSampling::Cs444 { + return Err(ColorConfigurationMismatch); + } + } + } + + if let Some(level_idx) = config.level_idx { + if level_idx > 31 { + return Err(LevelUndefined); + } + if level_idx < 31 { + if !AV1_LEVEL_DEFINED[level_idx as usize] { + return Err(LevelUndefined); + } + if config.width * config.height + > AV1_LEVEL_MAX_PIC_SIZE[level_idx as usize] + { + return Err(LevelConstraintsExceeded); + } + if config.width > AV1_LEVEL_MAX_H_SIZE[level_idx as usize] { + return Err(LevelConstraintsExceeded); + } + if config.height > AV1_LEVEL_MAX_V_SIZE[level_idx as usize] { + return Err(LevelConstraintsExceeded); + } + if ((config.width * config.height) as u64 * config.time_base.num) + .div_ceil(config.time_base.den) + > AV1_LEVEL_MAX_DISPLAY_RATE[level_idx as usize] as u64 + { + return Err(LevelConstraintsExceeded); + } + } + } + + // TODO: add more validation + let rc = &self.rate_control; + + if (rc.emit_pass_data || rc.summary.is_some()) && config.bitrate == 0 { + return Err(TargetBitrateNeeded); + } + + Ok(()) + } + + /// Provide the tiling information for the current Config + /// + /// Useful for reporting and debugging. + /// + /// # Errors + /// + /// - Returns `InvalidConfig` if the tiling config is invalid. + pub fn tiling_info(&self) -> Result { + self.validate()?; + + let seq = crate::encoder::Sequence::new(&self.enc); + + Ok(seq.tiling) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/rate.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/rate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/rate.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/rate.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use thiserror::Error; + +use crate::rate::*; + +/// Rate control errors +#[derive(Debug, Error)] +pub enum Error { + /// The summary provided is not compatible with the current encoder version + #[error("Incompatible version {0}")] + InvalidVersion(i64), + /// The summary provided is possibly corrupted + #[error("The summary content is invalid: {0}")] + CorruptedSummary(String), +} + +/// Rate control configuration +#[derive(Clone, Debug, Default)] +pub struct RateControlConfig { + pub(crate) emit_pass_data: bool, + pub(crate) summary: Option, +} + +pub use crate::rate::RCSummary as RateControlSummary; + +impl RateControlSummary { + /// Deserializes a byte slice into a `RateControlSummary` + pub(crate) fn from_slice(bytes: &[u8]) -> Result { + let mut de = RCDeserialize::default(); + let _ = de.buffer_fill(bytes, 0, TWOPASS_HEADER_SZ); + + de.parse_summary().map_err(Error::CorruptedSummary) + } +} + +impl RateControlConfig { + /// Create a rate control configuration from a serialized summary + /// + /// # Errors + /// + /// Returns an error if the serialized data is invalid. + pub fn from_summary_slice(bytes: &[u8]) -> Result { + Ok(Self { + summary: Some(RateControlSummary::from_slice(bytes)?), + ..Default::default() + }) + } + /// Create a default rate control configuration + /// + /// By default the encoder is in single pass mode. + pub fn new() -> Self { + Default::default() + } + + /// Set a rate control summary + /// + /// Enable the second pass encoding mode + pub const fn with_summary(mut self, summary: RateControlSummary) -> Self { + self.summary = Some(summary); + self + } + + /// Emit the current pass data + /// + /// The pass data will be used in a second pass encoding session + pub const fn with_emit_data(mut self, emit: bool) -> Self { + self.emit_pass_data = emit; + self + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/speedsettings.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/speedsettings.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/config/speedsettings.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/config/speedsettings.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,451 @@ +// Copyright (c) 2020-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use num_derive::*; + +use crate::partition::BlockSize; +use crate::serialize::{Deserialize, Serialize}; + +use std::fmt; + +// NOTE: Add Structures at the end. +/// Contains the speed settings. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[non_exhaustive] +pub struct SpeedSettings { + /// Enables inter-frames to have multiple reference frames. + /// + /// Enabled is slower. + pub multiref: bool, + + /// Enables fast deblocking filter. + pub fast_deblock: bool, + + /// The number of lookahead frames to be used for temporal RDO. + /// + /// Higher is slower. + pub rdo_lookahead_frames: usize, + + /// Which scene detection mode to use. Standard is slower, but best. + pub scene_detection_mode: SceneDetectionSpeed, + + /// Enables CDEF. + pub cdef: bool, + + /// Enables LRF. + pub lrf: bool, + + /// Enable searching loop restoration units when no transforms have been coded + /// restoration unit. + pub lru_on_skip: bool, + + /// The amount of search done for self guided restoration. + pub sgr_complexity: SGRComplexityLevel, + + /// Search level for segmentation. + /// + /// Full search is at least twice as slow. + pub segmentation: SegmentationLevel, + + // NOTE: put enums and basic type fields above + /// Speed settings related to partition decision + pub partition: PartitionSpeedSettings, + + /// Speed settings related to transform size and type decision + pub transform: TransformSpeedSettings, + + /// Speed settings related to intra prediction mode selection + pub prediction: PredictionSpeedSettings, + + /// Speed settings related to motion estimation and motion vector selection + pub motion: MotionSpeedSettings, +} + +impl Default for SpeedSettings { + /// The default settings are equivalent to speed 0 + fn default() -> Self { + SpeedSettings { + multiref: true, + fast_deblock: false, + rdo_lookahead_frames: 40, + scene_detection_mode: SceneDetectionSpeed::Standard, + cdef: true, + lrf: true, + lru_on_skip: true, + sgr_complexity: SGRComplexityLevel::Full, + segmentation: SegmentationLevel::Complex, + partition: PartitionSpeedSettings { + encode_bottomup: true, + non_square_partition_max_threshold: BlockSize::BLOCK_64X64, + partition_range: PartitionRange::new( + BlockSize::BLOCK_4X4, + BlockSize::BLOCK_64X64, + ), + }, + transform: TransformSpeedSettings { + reduced_tx_set: false, + // TX domain distortion is always faster, with no significant quality change, + // although it will be ignored when Tune == Psychovisual. + tx_domain_distortion: true, + tx_domain_rate: false, + rdo_tx_decision: true, + enable_inter_tx_split: false, + }, + prediction: PredictionSpeedSettings { + prediction_modes: PredictionModesSetting::ComplexAll, + fine_directional_intra: true, + }, + motion: MotionSpeedSettings { + include_near_mvs: true, + use_satd_subpel: true, + me_allow_full_search: true, + }, + } + } +} + +impl SpeedSettings { + /// Set the speed setting according to a numeric speed preset. + pub fn from_preset(speed: u8) -> Self { + // The default settings are equivalent to speed 0 + let mut settings = SpeedSettings::default(); + + if speed >= 1 { + settings.lru_on_skip = false; + settings.segmentation = SegmentationLevel::Simple; + } + + if speed >= 2 { + settings.partition.non_square_partition_max_threshold = + BlockSize::BLOCK_8X8; + + settings.prediction.prediction_modes = + PredictionModesSetting::ComplexKeyframes; + } + + if speed >= 3 { + settings.rdo_lookahead_frames = 30; + + settings.partition.partition_range = + PartitionRange::new(BlockSize::BLOCK_8X8, BlockSize::BLOCK_64X64); + } + + if speed >= 4 { + settings.partition.encode_bottomup = false; + } + + if speed >= 5 { + settings.sgr_complexity = SGRComplexityLevel::Reduced; + settings.motion.include_near_mvs = false; + } + + if speed >= 6 { + settings.rdo_lookahead_frames = 20; + + settings.transform.rdo_tx_decision = false; + settings.transform.reduced_tx_set = true; + + settings.motion.me_allow_full_search = false; + } + + if speed >= 7 { + settings.prediction.prediction_modes = PredictionModesSetting::Simple; + // Multiref is enabled automatically if low_latency is false. + // + // If low_latency is true, enabling multiref allows using multiple + // backwards references. low_latency false enables both forward and + // backwards references. + settings.multiref = false; + settings.fast_deblock = true; + } + + if speed >= 8 { + settings.rdo_lookahead_frames = 10; + settings.lrf = false; + } + + if speed >= 9 { + // 8x8 is fast enough to use until very high speed levels, + // because 8x8 with reduced TX set is faster but with equivalent + // or better quality compared to 16x16 (to which reduced TX set does not apply). + settings.partition.partition_range = + PartitionRange::new(BlockSize::BLOCK_16X16, BlockSize::BLOCK_32X32); + + // FIXME: With unknown reasons, inter_tx_split does not work if reduced_tx_set is false + settings.transform.enable_inter_tx_split = true; + } + + if speed >= 10 { + settings.scene_detection_mode = SceneDetectionSpeed::Fast; + + settings.partition.partition_range = + PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_32X32); + + settings.motion.use_satd_subpel = false; + } + + settings + } +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(Default))] +/// Speed settings related to transform size and type decision +pub struct TransformSpeedSettings { + /// Enables reduced transform set. + /// + /// Enabled is faster. + pub reduced_tx_set: bool, + + /// Enables using transform-domain distortion instead of pixel-domain. + /// + /// Enabled is faster. + pub tx_domain_distortion: bool, + + /// Enables using transform-domain rate estimation. + /// + /// Enabled is faster. + pub tx_domain_rate: bool, + + /// Enables searching transform size and type with RDO. + /// + /// Enabled is slower. + pub rdo_tx_decision: bool, + + /// Enable tx split for inter mode block. + pub enable_inter_tx_split: bool, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(Default))] +/// Speed settings related to partition decision +pub struct PartitionSpeedSettings { + /// Enables bottom-up encoding, rather than top-down. + /// + /// Enabled is slower. + pub encode_bottomup: bool, + + /// Allow non-square partition type outside of frame borders + /// on any blocks at or below this size. + pub non_square_partition_max_threshold: BlockSize, + + /// Range of partition sizes that can be used. Larger ranges are slower. + /// + /// Must be based on square block sizes, so e.g. 8×4 isn't allowed here. + pub partition_range: PartitionRange, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(Default))] +/// Speed settings related to motion estimation and motion vector selection +pub struct MotionSpeedSettings { + /// Use SATD instead of SAD for subpixel search. + /// + /// Enabled is slower. + pub use_satd_subpel: bool, + + /// Enables searching near motion vectors during RDO. + /// + /// Enabled is slower. + pub include_near_mvs: bool, + + /// Enable full search in some parts of motion estimation. Allowing full + /// search is slower. + pub me_allow_full_search: bool, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(Default))] +/// Speed settings related to intra prediction mode selection +pub struct PredictionSpeedSettings { + /// Prediction modes to search. + /// + /// Complex settings are slower. + pub prediction_modes: PredictionModesSetting, + + /// Use fine directional intra prediction + pub fine_directional_intra: bool, +} + +/// Range of block sizes to use. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct PartitionRange { + pub(crate) min: BlockSize, + pub(crate) max: BlockSize, +} + +impl PartitionRange { + /// Creates a new partition range with min and max partition sizes. + /// + /// # Panics + /// + /// - Panics if `max` is larger than `min`. + /// - Panics if either `min` or `max` are not square. + pub fn new(min: BlockSize, max: BlockSize) -> Self { + assert!(max >= min); + // Topdown search checks the min block size for PARTITION_SPLIT only, so + // the min block size must be square. + assert!(min.is_sqr()); + // Rectangular max partition sizes have not been tested. + assert!(max.is_sqr()); + + Self { min, max } + } +} + +#[cfg(test)] +impl Default for PartitionRange { + fn default() -> Self { + PartitionRange::new(BlockSize::BLOCK_4X4, BlockSize::BLOCK_64X64) + } +} + +/// Prediction modes to search. +#[derive( + Clone, + Copy, + Debug, + PartialOrd, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, +)] +pub enum SceneDetectionSpeed { + /// Fastest scene detection using pixel-wise comparison + Fast, + /// Scene detection using motion vectors and cost estimates + Standard, + /// Completely disable scene detection and only place keyframes + /// at fixed intervals. + None, +} + +impl fmt::Display for SceneDetectionSpeed { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + SceneDetectionSpeed::Fast => "Fast", + SceneDetectionSpeed::Standard => "Standard", + SceneDetectionSpeed::None => "None", + } + ) + } +} + +/// Prediction modes to search. +#[derive( + Clone, + Copy, + Debug, + PartialOrd, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, +)] +#[cfg_attr(test, derive(Default))] +pub enum PredictionModesSetting { + /// Only simple prediction modes. + #[cfg_attr(test, default)] + Simple, + /// Search all prediction modes on key frames and simple modes on other + /// frames. + ComplexKeyframes, + /// Search all prediction modes on all frames. + ComplexAll, +} + +impl fmt::Display for PredictionModesSetting { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + PredictionModesSetting::Simple => "Simple", + PredictionModesSetting::ComplexKeyframes => "Complex-KFs", + PredictionModesSetting::ComplexAll => "Complex-All", + } + ) + } +} + +/// Search level for self guided restoration +#[derive( + Clone, + Copy, + Debug, + PartialOrd, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, +)] +pub enum SGRComplexityLevel { + /// Search all sgr parameters + Full, + /// Search a reduced set of sgr parameters + Reduced, +} + +impl fmt::Display for SGRComplexityLevel { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + SGRComplexityLevel::Full => "Full", + SGRComplexityLevel::Reduced => "Reduced", + } + ) + } +} + +/// Search level for segmentation +#[derive( + Clone, + Copy, + Debug, + PartialOrd, + PartialEq, + Eq, + FromPrimitive, + Serialize, + Deserialize, +)] +pub enum SegmentationLevel { + /// No segmentation is signalled. + Disabled, + /// Segmentation index is derived from source statistics. + Simple, + /// Segmentation index range is derived from source statistics. + Complex, + /// Search all segmentation indices. + Full, +} + +impl fmt::Display for SegmentationLevel { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + SegmentationLevel::Disabled => "Disabled", + SegmentationLevel::Simple => "Simple", + SegmentationLevel::Complex => "Complex", + SegmentationLevel::Full => "Full", + } + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/context.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/context.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,471 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. +#![deny(missing_docs)] + +use std::fmt; +use std::io; +use std::sync::Arc; + +use bitstream_io::{BigEndian, BitWrite, BitWriter}; + +use crate::api::color::*; +use crate::api::config::*; +use crate::api::internal::*; +use crate::api::util::*; +use crate::encoder::*; +use crate::frame::*; +use crate::util::Pixel; + +/// The encoder context. +/// +/// Contains the encoding state. +pub struct Context { + pub(crate) inner: ContextInner, + pub(crate) config: EncoderConfig, + pub(crate) pool: Option>, + pub(crate) is_flushing: bool, +} + +impl Context { + /// Allocates and returns a new frame. + /// + /// # Examples + /// + /// ``` + /// use rav1e::prelude::*; + /// + /// # fn main() -> Result<(), InvalidConfig> { + /// let cfg = Config::default(); + /// let ctx: Context = cfg.new_context()?; + /// let frame = ctx.new_frame(); + /// # Ok(()) + /// # } + /// ``` + #[inline] + pub fn new_frame(&self) -> Frame { + Frame::new( + self.config.width, + self.config.height, + self.config.chroma_sampling, + ) + } + + /// Sends the frame for encoding. + /// + /// This method adds the frame into the frame queue and runs the first passes + /// of the look-ahead computation. + /// + /// Passing `None` is equivalent to calling [`flush`]. + /// + /// The caller is responsible for padding the invisible portion of the frame, + /// if multiple references to the frame are held. + /// Calling [`Plane::pad()`] after filling each plane or equivalent is required. + /// + /// # Errors + /// + /// If this method is called with a frame after the encoder has been flushed + /// or the encoder internal limit is hit (`std::i32::MAX` frames) the + /// [`EncoderStatus::EnoughData`] error is returned. + /// + /// # Examples + /// + /// ``` + /// use rav1e::prelude::*; + /// + /// # fn main() -> Result<(), Box> { + /// # if false { + /// let cfg = Config::default(); + /// let mut ctx: Context = cfg.new_context().unwrap(); + /// let f1 = ctx.new_frame(); + /// let f2 = f1.clone(); + /// let info = FrameParameters { + /// frame_type_override: FrameTypeOverride::Key, + /// opaque: None, + /// ..Default::default() + /// }; + /// + /// // Send the plain frame data + /// ctx.send_frame(f1)?; + /// // Send the data and the per-frame parameters + /// // In this case the frame is forced to be a keyframe. + /// ctx.send_frame((f2, info))?; + /// // Flush the encoder, it is equivalent to a call to `flush()` + /// ctx.send_frame(None)?; + /// # } + /// # Ok(()) + /// # } + /// ``` + /// + /// [`flush`]: #method.flush + /// [`EncoderStatus::EnoughData`]: enum.EncoderStatus.html#variant.EnoughData + #[inline] + pub fn send_frame(&mut self, frame: F) -> Result<(), EncoderStatus> + where + F: IntoFrame, + { + let (frame, params) = frame.into(); + + if frame.is_none() { + if self.is_flushing { + return Ok(()); + } + self.inner.limit = Some(self.inner.frame_count); + self.is_flushing = true; + } else if self.is_flushing + || (self.inner.config.still_picture && self.inner.frame_count > 0) + { + return Err(EncoderStatus::EnoughData); + // The rate control can process at most i32::MAX frames + } else if self.inner.frame_count == i32::MAX as u64 - 1 { + self.inner.limit = Some(self.inner.frame_count); + self.is_flushing = true; + } + + let inner = &mut self.inner; + let run = move || inner.send_frame(frame, params); + + match &self.pool { + Some(pool) => pool.install(run), + None => run(), + } + } + + /// Returns the first-pass data of a two-pass encode for the frame that was + /// just encoded. + /// + /// This should be called BEFORE every call to [`receive_packet`] (including + /// the very first one), even if no packet was produced by the last call to + /// [`receive_packet`], if any (i.e., [`EncoderStatus::Encoded`] was + /// returned). It needs to be called once more after + /// [`EncoderStatus::LimitReached`] is returned, to retrieve the header that + /// should be written to the front of the stats file (overwriting the + /// placeholder header that was emitted at the start of encoding). + /// + /// It is still safe to call this function when [`receive_packet`] returns + /// any other error. It will return `None` instead of returning a duplicate + /// copy of the previous frame's data. + /// + /// [`receive_packet`]: #method.receive_packet + /// [`EncoderStatus::Encoded`]: enum.EncoderStatus.html#variant.Encoded + /// [`EncoderStatus::LimitReached`]: + /// enum.EncoderStatus.html#variant.LimitReached + #[inline] + pub fn twopass_out(&mut self) -> Option<&[u8]> { + self.inner.rc_state.twopass_out(self.inner.done_processing()) + } + + /// Returns the number of bytes of the stats file needed before the next + /// frame of the second pass in a two-pass encode can be encoded. + /// + /// This is a lower bound (more might be required), but if `0` is returned, + /// then encoding can proceed. This is just a hint to the application, and + /// does not need to be called for encoding the second pass to work, so long + /// as the application continues to provide more data to [`twopass_in`] in a + /// loop until [`twopass_in`] returns `0`. + /// + /// [`twopass_in`]: #method.twopass_in + #[inline] + pub fn twopass_bytes_needed(&mut self) -> usize { + self.inner.rc_state.twopass_in(None).unwrap_or(0) + } + + /// Provides the stats data produced in the first pass of a two-pass encode + /// to the second pass. + /// + /// On success this returns the number of bytes of the data which were + /// consumed. When encoding the second pass of a two-pass encode, this should + /// be called repeatedly in a loop before every call to [`receive_packet`] + /// (including the very first one) until no bytes are consumed, or until + /// [`twopass_bytes_needed`] returns `0`. + /// + /// [`receive_packet`]: #method.receive_packet + /// [`twopass_bytes_needed`]: #method.twopass_bytes_needed + /// + /// # Errors + /// + /// Returns `Err(EncoderStatus::Failure)` if the two-pass data is invalid. + #[inline] + pub fn twopass_in(&mut self, buf: &[u8]) -> Result { + self.inner.rc_state.twopass_in(Some(buf)).or(Err(EncoderStatus::Failure)) + } + + /// Encodes the next frame and returns the encoded data. + /// + /// This method is where the main encoding work is done. + /// + /// # Errors + /// + /// May return `Err(EncoderStatus)`, which should be handled by the caller. + /// + /// # Examples + /// + /// Encoding a single frame: + /// + /// ``` + /// use rav1e::prelude::*; + /// + /// # fn main() -> Result<(), Box> { + /// # if false { + /// let cfg = Config::default(); + /// let mut ctx: Context = cfg.new_context()?; + /// let frame = ctx.new_frame(); + /// + /// ctx.send_frame(frame)?; + /// ctx.flush(); + /// + /// loop { + /// match ctx.receive_packet() { + /// Ok(packet) => { /* Mux the packet. */ }, + /// Err(EncoderStatus::Encoded) => (), + /// Err(EncoderStatus::LimitReached) => break, + /// Err(err) => Err(err)?, + /// } + /// } + /// # } + /// # Ok(()) + /// # } + /// ``` + /// + /// Encoding a sequence of frames: + /// + /// ``` + /// use std::sync::Arc; + /// use rav1e::prelude::*; + /// + /// fn encode_frames( + /// ctx: &mut Context, + /// mut frames: impl Iterator> + /// ) -> Result<(), EncoderStatus> { + /// // This is a slightly contrived example, intended to showcase the + /// // various statuses that can be returned from receive_packet(). + /// // Assume that, for example, there are a lot of frames in the + /// // iterator, which are produced lazily, so you don't want to send + /// // them all in at once as to not exhaust the memory. + /// loop { + /// match ctx.receive_packet() { + /// Ok(packet) => { /* Mux the packet. */ }, + /// Err(EncoderStatus::Encoded) => { + /// // A frame was encoded without emitting a packet. This is + /// // normal, just proceed as usual. + /// }, + /// Err(EncoderStatus::LimitReached) => { + /// // All frames have been encoded. Time to break out of the + /// // loop. + /// break; + /// }, + /// Err(EncoderStatus::NeedMoreData) => { + /// // The encoder has requested additional frames. Push the + /// // next frame in, or flush the encoder if there are no + /// // frames left (on None). + /// ctx.send_frame(frames.next().map(Arc::new))?; + /// }, + /// Err(EncoderStatus::EnoughData) => { + /// // Since we aren't trying to push frames after flushing, + /// // this should never happen in this example. + /// unreachable!(); + /// }, + /// Err(EncoderStatus::NotReady) => { + /// // We're not doing two-pass encoding, so this can never + /// // occur. + /// unreachable!(); + /// }, + /// Err(EncoderStatus::Failure) => { + /// return Err(EncoderStatus::Failure); + /// }, + /// } + /// } + /// + /// Ok(()) + /// } + /// # fn main() -> Result<(), Box> { + /// # if false { + /// # let mut enc = EncoderConfig::default(); + /// # // So it runs faster. + /// # enc.width = 16; + /// # enc.height = 16; + /// # let cfg = Config::new().with_encoder_config(enc); + /// # let mut ctx: Context = cfg.new_context()?; + /// # + /// # let frames = vec![ctx.new_frame(); 4].into_iter(); + /// # encode_frames(&mut ctx, frames); + /// # } + /// # Ok(()) + /// # } + /// ``` + #[inline] + pub fn receive_packet(&mut self) -> Result, EncoderStatus> { + let inner = &mut self.inner; + let mut run = move || inner.receive_packet(); + + match &self.pool { + Some(pool) => pool.install(run), + None => run(), + } + } + + /// Flushes the encoder. + /// + /// Flushing signals the end of the video. After the encoder has been + /// flushed, no additional frames are accepted. + /// + /// # Panics + /// + /// Panics if `send_frame` returns an `Err`. + /// This should never happen when calling it with `None` + /// and indicates a development error. + #[inline] + pub fn flush(&mut self) { + self.send_frame(None).unwrap(); + } + + /// Produces a sequence header matching the current encoding context. + /// + /// Its format is compatible with the AV1 Matroska and ISOBMFF specification. + /// Note that the returned header does not include any config OBUs which are + /// required for some uses. See [the specification]. + /// + /// [the specification]: + /// https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-section + /// + /// # Panics + /// + /// Panics if the header cannot be written in memory. This is unrecoverable, + /// and usually indicates the system is out of memory. + #[inline] + pub fn container_sequence_header(&self) -> Vec { + fn sequence_header_inner(seq: &Sequence) -> io::Result> { + let mut buf = Vec::new(); + + { + let mut bw = BitWriter::endian(&mut buf, BigEndian); + bw.write_bit(true)?; // marker + bw.write::<7, u8>(1)?; // version + bw.write::<3, u8>(seq.profile)?; + bw.write::<5, u8>(31)?; // level + bw.write_bit(false)?; // tier + bw.write_bit(seq.bit_depth > 8)?; // high_bitdepth + bw.write_bit(seq.bit_depth == 12)?; // twelve_bit + bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs400)?; // monochrome + bw.write_bit(seq.chroma_sampling != ChromaSampling::Cs444)?; // chroma_subsampling_x + bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs420)?; // chroma_subsampling_y + bw.write::<2, u8>(0)?; // chroma_sample_position + bw.write::<3, u8>(0)?; // reserved + bw.write_bit(false)?; // initial_presentation_delay_present + + bw.write::<4, u8>(0)?; // reserved + } + + Ok(buf) + } + + let seq = Sequence::new(&self.config); + + sequence_header_inner(&seq).unwrap() + } +} + +/// Rate Control Data +pub enum RcData { + /// A Rate Control Summary Packet + /// + /// It is emitted once, after the encoder is flushed. + /// + /// It contains a summary of the rate control information for the + /// encoding process that just terminated. + Summary(Box<[u8]>), + /// A Rate Control Frame-specific Packet + /// + /// It is emitted every time a frame is processed. + /// + /// The information contained is required to encode its matching + /// frame in a second pass encoding. + Frame(Box<[u8]>), +} + +impl Context { + /// Return the Rate Control Summary Packet size + /// + /// It is useful mainly to preserve space when saving + /// both Rate Control Summary and Frame Packets in a single file. + pub fn rc_summary_size(&self) -> usize { + crate::rate::TWOPASS_HEADER_SZ + } + + /// Return the first pass data + /// + /// Call it after `receive_packet`, it returns a packet or the encoder + /// lifecycle statuses [`EncoderStatus::Encoded`] and + /// [`EncoderStatus::LimitReached`]. + /// + /// [`EncoderStatus::Encoded`]: enum.EncoderStatus.html#variant.Encoded + /// [`EncoderStatus::LimitReached`]: + /// enum.EncoderStatus.html#variant.LimitReached + /// + /// It will return a `RcData::Summary` once the encoder is flushed. + pub fn rc_receive_pass_data(&mut self) -> Option { + if self.inner.done_processing() && self.inner.rc_state.pass1_data_retrieved + { + let data = self.inner.rc_state.emit_summary(); + Some(RcData::Summary(data.to_vec().into_boxed_slice())) + } else if self.inner.rc_state.pass1_data_retrieved { + None + } else if let Some(data) = self.inner.rc_state.emit_frame_data() { + Some(RcData::Frame(data.to_vec().into_boxed_slice())) + } else { + unreachable!( + "The encoder received more frames than its internal limit allows" + ) + } + } + + /// Lower bound number of pass data packets required to progress the + /// encoding process. + /// + /// It should be called iteratively until it returns 0. + pub fn rc_second_pass_data_required(&self) -> usize { + if self.inner.done_processing() { + 0 + } else { + self.inner.rc_state.twopass_in_frames_needed() as usize + } + } + + /// Feed the first pass Rate Control data to the encoder, + /// Frame-specific Packets only. + /// + /// Call it before `receive_packet()` + /// + /// # Errors + /// + /// Returns `EncoderStatus::Failure` if the data provided is incorrect + pub fn rc_send_pass_data( + &mut self, data: &[u8], + ) -> Result<(), EncoderStatus> { + self + .inner + .rc_state + .parse_frame_data_packet(data) + .map_err(|_| EncoderStatus::Failure) + } +} + +impl fmt::Debug for Context { + fn fmt( + &self, f: &mut fmt::Formatter<'_>, + ) -> std::result::Result<(), fmt::Error> { + write!( + f, + "{{ \ + config: {:?}, \ + is_flushing: {}, \ + }}", + self.config, self.is_flushing, + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/internal.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/internal.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/internal.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/internal.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1735 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. +#![deny(missing_docs)] + +use crate::activity::ActivityMask; +use crate::api::lookahead::*; +use crate::api::{ + EncoderConfig, EncoderStatus, FrameType, Opaque, Packet, T35, +}; +use crate::color::ChromaSampling::Cs400; +use crate::dist::get_satd; +use crate::encoder::*; +use crate::frame::*; +use crate::partition::*; +use crate::rate::{ + RCState, FRAME_NSUBTYPES, FRAME_SUBTYPE_I, FRAME_SUBTYPE_P, + FRAME_SUBTYPE_SEF, +}; +use crate::stats::EncoderStats; +use crate::tiling::Area; +use crate::util::Pixel; +use arrayvec::ArrayVec; +use av_scenechange::SceneChangeDetector; +use std::cmp; +use std::collections::{BTreeMap, BTreeSet}; +use std::env; +use std::fs; +use std::path::PathBuf; +use std::sync::Arc; + +/// The set of options that controls frame re-ordering and reference picture +/// selection. +/// The options stored here are invariant over the whole encode. +#[derive(Debug, Clone, Copy)] +pub struct InterConfig { + /// Whether frame re-ordering is enabled. + reorder: bool, + /// Whether P-frames can use multiple references. + pub(crate) multiref: bool, + /// The depth of the re-ordering pyramid. + /// The current code cannot support values larger than 2. + pub(crate) pyramid_depth: u64, + /// Number of input frames in group. + pub(crate) group_input_len: u64, + /// Number of output frames in group. + /// This includes both hidden frames and "show existing frame" frames. + group_output_len: u64, + /// Interval between consecutive S-frames. + /// Keyframes reset this interval. + /// This MUST be a multiple of `group_input_len`. + pub(crate) switch_frame_interval: u64, +} + +impl InterConfig { + pub(crate) fn new(enc_config: &EncoderConfig) -> InterConfig { + let reorder = !enc_config.low_latency; + // A group always starts with (group_output_len - group_input_len) hidden + // frames, followed by group_input_len shown frames. + // The shown frames iterate over the input frames in order, with frames + // already encoded as hidden frames now displayed with Show Existing + // Frame. + // For example, for a pyramid depth of 2, the group is as follows: + // |TU |TU |TU |TU + // idx_in_group_output: 0 1 2 3 4 5 + // input_frameno: 4 2 1 SEF 3 SEF + // output_frameno: 1 2 3 4 5 6 + // level: 0 1 2 1 2 0 + // ^^^^^ ^^^^^^^^^^^^^ + // hidden shown + // TODO: This only works for pyramid_depth <= 2 --- after that we need + // more hidden frames in the middle of the group. + let pyramid_depth = if reorder { 2 } else { 0 }; + let group_input_len = 1 << pyramid_depth; + let group_output_len = group_input_len + pyramid_depth; + let switch_frame_interval = enc_config.switch_frame_interval; + assert!(switch_frame_interval % group_input_len == 0); + InterConfig { + reorder, + multiref: reorder || enc_config.speed_settings.multiref, + pyramid_depth, + group_input_len, + group_output_len, + switch_frame_interval, + } + } + + /// Get the index of an output frame in its re-ordering group given the output + /// frame number of the frame in the current keyframe gop. + /// When re-ordering is disabled, this always returns 0. + pub(crate) fn get_idx_in_group_output( + &self, output_frameno_in_gop: u64, + ) -> u64 { + // The first frame in the GOP should be a keyframe and is not re-ordered, + // so we should not be calling this function on it. + debug_assert!(output_frameno_in_gop > 0); + (output_frameno_in_gop - 1) % self.group_output_len + } + + /// Get the order-hint of an output frame given the output frame number of the + /// frame in the current keyframe gop and the index of that output frame + /// in its re-ordering gorup. + pub(crate) fn get_order_hint( + &self, output_frameno_in_gop: u64, idx_in_group_output: u64, + ) -> u32 { + // The first frame in the GOP should be a keyframe, but currently this + // function only handles inter frames. + // We could return 0 for keyframes if keyframe support is needed. + debug_assert!(output_frameno_in_gop > 0); + // Which P-frame group in the current gop is this output frame in? + // Subtract 1 because the first frame in the gop is always a keyframe. + let group_idx = (output_frameno_in_gop - 1) / self.group_output_len; + // Get the offset to the corresponding input frame. + // TODO: This only works with pyramid_depth <= 2. + let offset = if idx_in_group_output < self.pyramid_depth { + self.group_input_len >> idx_in_group_output + } else { + idx_in_group_output - self.pyramid_depth + 1 + }; + // Construct the final order hint relative to the start of the group. + (self.group_input_len * group_idx + offset) as u32 + } + + /// Get the level of the current frame in the pyramid. + pub(crate) const fn get_level(&self, idx_in_group_output: u64) -> u64 { + if !self.reorder { + 0 + } else if idx_in_group_output < self.pyramid_depth { + // Hidden frames are output first (to be shown in the future). + idx_in_group_output + } else { + // Shown frames + // TODO: This only works with pyramid_depth <= 2. + pos_to_lvl( + idx_in_group_output - self.pyramid_depth + 1, + self.pyramid_depth, + ) + } + } + + pub(crate) const fn get_slot_idx(&self, level: u64, order_hint: u32) -> u32 { + // Frames with level == 0 are stored in slots 0..4, and frames with higher + // values of level in slots 4..8 + if level == 0 { + (order_hint >> self.pyramid_depth) & 3 + } else { + // This only works with pyramid_depth <= 4. + 3 + level as u32 + } + } + + pub(crate) const fn get_show_frame(&self, idx_in_group_output: u64) -> bool { + idx_in_group_output >= self.pyramid_depth + } + + pub(crate) const fn get_show_existing_frame( + &self, idx_in_group_output: u64, + ) -> bool { + // The self.reorder test here is redundant, but short-circuits the rest, + // avoiding a bunch of work when it's false. + self.reorder + && self.get_show_frame(idx_in_group_output) + && (idx_in_group_output - self.pyramid_depth + 1).count_ones() == 1 + && idx_in_group_output != self.pyramid_depth + } + + pub(crate) fn get_input_frameno( + &self, output_frameno_in_gop: u64, gop_input_frameno_start: u64, + ) -> u64 { + if output_frameno_in_gop == 0 { + gop_input_frameno_start + } else { + let idx_in_group_output = + self.get_idx_in_group_output(output_frameno_in_gop); + let order_hint = + self.get_order_hint(output_frameno_in_gop, idx_in_group_output); + gop_input_frameno_start + order_hint as u64 + } + } + + const fn max_reordering_latency(&self) -> u64 { + self.group_input_len + } + + pub(crate) const fn keyframe_lookahead_distance(&self) -> u64 { + self.max_reordering_latency() + 1 + } + + pub(crate) const fn allowed_ref_frames(&self) -> &[RefType] { + use crate::partition::RefType::*; + if self.reorder { + &ALL_INTER_REFS + } else if self.multiref { + &[LAST_FRAME, LAST2_FRAME, LAST3_FRAME, GOLDEN_FRAME] + } else { + &[LAST_FRAME] + } + } +} + +// Thin wrapper for frame-related data +// that gets cached and reused throughout the life of a frame. +#[derive(Clone)] +pub(crate) struct FrameData { + pub(crate) fi: FrameInvariants, + pub(crate) fs: FrameState, +} + +impl FrameData { + pub(crate) fn new(fi: FrameInvariants, frame: Arc>) -> Self { + let fs = FrameState::new_with_frame(&fi, frame); + FrameData { fi, fs } + } +} + +type FrameQueue = BTreeMap>>>; +type FrameDataQueue = BTreeMap>>; + +// the fields pub(super) are accessed only by the tests +pub(crate) struct ContextInner { + pub(crate) frame_count: u64, + pub(crate) limit: Option, + pub(crate) output_frameno: u64, + pub(super) inter_cfg: InterConfig, + pub(super) frames_processed: u64, + /// Maps *`input_frameno`* to frames + pub(super) frame_q: FrameQueue, + /// Maps *`output_frameno`* to frame data + pub(super) frame_data: FrameDataQueue, + /// A list of the `input_frameno` for keyframes in this encode. + /// Needed so that we don't need to keep all of the `frame_invariants` in + /// memory for the whole life of the encode. + // TODO: Is this needed at all? + keyframes: BTreeSet, + // TODO: Is this needed at all? + keyframes_forced: BTreeSet, + /// A storage space for reordered frames. + packet_data: Vec, + /// Maps `output_frameno` to `gop_output_frameno_start`. + gop_output_frameno_start: BTreeMap, + /// Maps `output_frameno` to `gop_input_frameno_start`. + pub(crate) gop_input_frameno_start: BTreeMap, + keyframe_detector: SceneChangeDetector, + pub(crate) config: Arc, + seq: Arc, + pub(crate) rc_state: RCState, + maybe_prev_log_base_q: Option, + /// The next `input_frameno` to be processed by lookahead. + next_lookahead_frame: u64, + /// The next `output_frameno` to be computed by lookahead. + next_lookahead_output_frameno: u64, + /// Optional opaque to be sent back to the user + opaque_q: BTreeMap, + /// Optional T35 metadata per frame + t35_q: BTreeMap>, +} + +impl ContextInner { + pub fn new(enc: &EncoderConfig) -> Self { + // initialize with temporal delimiter + let packet_data = TEMPORAL_DELIMITER.to_vec(); + let mut keyframes = BTreeSet::new(); + keyframes.insert(0); + + let maybe_ac_qi_max = + if enc.quantizer < 255 { Some(enc.quantizer as u8) } else { None }; + + let seq = Arc::new(Sequence::new(enc)); + let inter_cfg = InterConfig::new(enc); + let lookahead_distance = inter_cfg.keyframe_lookahead_distance() as usize; + let mut keyframe_detector = SceneChangeDetector::new( + (enc.width, enc.height), + enc.bit_depth, + av_scenechange::Rational32::new( + enc.time_base.den as i32, + enc.time_base.num as i32, + ), + enc.chroma_sampling, + lookahead_distance, + match enc.speed_settings.scene_detection_mode { + super::SceneDetectionSpeed::Fast => { + av_scenechange::SceneDetectionSpeed::Fast + } + super::SceneDetectionSpeed::Standard => { + av_scenechange::SceneDetectionSpeed::Standard + } + super::SceneDetectionSpeed::None => { + av_scenechange::SceneDetectionSpeed::None + } + }, + enc.min_key_frame_interval as usize, + enc.max_key_frame_interval as usize, + av_scenechange::CpuFeatureLevel::default(), + ); + keyframe_detector.enable_cache(); + + ContextInner { + frame_count: 0, + limit: None, + inter_cfg, + output_frameno: 0, + frames_processed: 0, + frame_q: BTreeMap::new(), + frame_data: BTreeMap::new(), + keyframes, + keyframes_forced: BTreeSet::new(), + packet_data, + gop_output_frameno_start: BTreeMap::new(), + gop_input_frameno_start: BTreeMap::new(), + keyframe_detector, + config: Arc::new(enc.clone()), + seq, + rc_state: RCState::new( + enc.width as i32, + enc.height as i32, + enc.time_base.den as i64, + enc.time_base.num as i64, + enc.bitrate, + maybe_ac_qi_max, + enc.min_quantizer, + enc.max_key_frame_interval as i32, + enc.reservoir_frame_delay, + ), + maybe_prev_log_base_q: None, + next_lookahead_frame: 1, + next_lookahead_output_frameno: 0, + opaque_q: BTreeMap::new(), + t35_q: BTreeMap::new(), + } + } + + #[profiling::function] + pub fn send_frame( + &mut self, mut frame: Option>>, + params: Option, + ) -> Result<(), EncoderStatus> { + if let Some(ref mut frame) = frame { + use crate::api::color::ChromaSampling; + let EncoderConfig { width, height, chroma_sampling, .. } = *self.config; + let planes = + if chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + // Try to add padding + if let Some(ref mut frame) = Arc::get_mut(frame) { + for plane in frame.planes[..planes].iter_mut() { + plane.pad(width, height); + } + } + // Enforce that padding is added + for (p, plane) in frame.planes[..planes].iter().enumerate() { + assert!( + plane.probe_padding(width, height), + "Plane {p} was not padded before passing Frame to send_frame()." + ); + } + } + + let input_frameno = self.frame_count; + let is_flushing = frame.is_none(); + if !is_flushing { + self.frame_count += 1; + } + self.frame_q.insert(input_frameno, frame); + + if let Some(params) = params { + if params.frame_type_override == FrameTypeOverride::Key { + self.keyframes_forced.insert(input_frameno); + } + if let Some(op) = params.opaque { + self.opaque_q.insert(input_frameno, op); + } + self.t35_q.insert(input_frameno, params.t35_metadata); + } + + if !self.needs_more_frame_q_lookahead(self.next_lookahead_frame) { + let lookahead_frames = self + .frame_q + .range(self.next_lookahead_frame - 1..) + .filter_map(|(&_input_frameno, frame)| frame.as_ref()) + .collect::>>>(); + + if is_flushing { + // This is the last time send_frame is called, process all the + // remaining frames. + for cur_lookahead_frames in + std::iter::successors(Some(&lookahead_frames[..]), |s| s.get(1..)) + { + if cur_lookahead_frames.len() < 2 { + // All frames have been processed + break; + } + + Self::compute_keyframe_placement( + cur_lookahead_frames, + &self.keyframes_forced, + &mut self.keyframe_detector, + &mut self.next_lookahead_frame, + &mut self.keyframes, + ); + } + } else { + Self::compute_keyframe_placement( + &lookahead_frames, + &self.keyframes_forced, + &mut self.keyframe_detector, + &mut self.next_lookahead_frame, + &mut self.keyframes, + ); + } + } + + self.compute_frame_invariants(); + + Ok(()) + } + + /// Indicates whether more frames need to be read into the frame queue + /// in order for frame queue lookahead to be full. + fn needs_more_frame_q_lookahead(&self, input_frameno: u64) -> bool { + let lookahead_end = self.frame_q.keys().last().cloned().unwrap_or(0); + let frames_needed = + input_frameno + self.inter_cfg.keyframe_lookahead_distance() + 1; + lookahead_end < frames_needed && self.needs_more_frames(lookahead_end) + } + + /// Indicates whether more frames need to be processed into `FrameInvariants` + /// in order for FI lookahead to be full. + pub fn needs_more_fi_lookahead(&self) -> bool { + let ready_frames = self.get_rdo_lookahead_frames().count(); + ready_frames < self.config.speed_settings.rdo_lookahead_frames + 1 + && self.needs_more_frames(self.next_lookahead_frame) + } + + pub fn needs_more_frames(&self, frame_count: u64) -> bool { + self.limit.map(|limit| frame_count < limit).unwrap_or(true) + } + + fn get_rdo_lookahead_frames( + &self, + ) -> impl Iterator)> { + self + .frame_data + .iter() + .skip_while(move |(&output_frameno, _)| { + output_frameno < self.output_frameno + }) + .filter_map(|(fno, data)| data.as_ref().map(|data| (fno, data))) + .filter(|(_, data)| !data.fi.is_show_existing_frame()) + .take(self.config.speed_settings.rdo_lookahead_frames + 1) + } + + fn next_keyframe_input_frameno( + &self, gop_input_frameno_start: u64, ignore_limit: bool, + ) -> u64 { + let next_detected = self + .keyframes + .iter() + .find(|&&input_frameno| input_frameno > gop_input_frameno_start) + .cloned(); + let mut next_limit = + gop_input_frameno_start + self.config.max_key_frame_interval; + if !ignore_limit && self.limit.is_some() { + next_limit = next_limit.min(self.limit.unwrap()); + } + if next_detected.is_none() { + return next_limit; + } + cmp::min(next_detected.unwrap(), next_limit) + } + + fn set_frame_properties( + &mut self, output_frameno: u64, + ) -> Result<(), EncoderStatus> { + let fi = self.build_frame_properties(output_frameno)?; + + self.frame_data.insert( + output_frameno, + fi.map(|fi| { + let frame = self + .frame_q + .get(&fi.input_frameno) + .as_ref() + .unwrap() + .as_ref() + .unwrap(); + FrameData::new(fi, frame.clone()) + }), + ); + + Ok(()) + } + + #[allow(unused)] + pub fn build_dump_properties() -> PathBuf { + let mut data_location = PathBuf::new(); + if env::var_os("RAV1E_DATA_PATH").is_some() { + data_location.push(env::var_os("RAV1E_DATA_PATH").unwrap()); + } else { + data_location.push(env::current_dir().unwrap()); + data_location.push(".lookahead_data"); + } + fs::create_dir_all(&data_location).unwrap(); + data_location + } + + fn build_frame_properties( + &mut self, output_frameno: u64, + ) -> Result>, EncoderStatus> { + let (prev_gop_output_frameno_start, prev_gop_input_frameno_start) = + if output_frameno == 0 { + (0, 0) + } else { + ( + self.gop_output_frameno_start[&(output_frameno - 1)], + self.gop_input_frameno_start[&(output_frameno - 1)], + ) + }; + + self + .gop_output_frameno_start + .insert(output_frameno, prev_gop_output_frameno_start); + self + .gop_input_frameno_start + .insert(output_frameno, prev_gop_input_frameno_start); + + let output_frameno_in_gop = + output_frameno - self.gop_output_frameno_start[&output_frameno]; + let mut input_frameno = self.inter_cfg.get_input_frameno( + output_frameno_in_gop, + self.gop_input_frameno_start[&output_frameno], + ); + + if self.needs_more_frame_q_lookahead(input_frameno) { + return Err(EncoderStatus::NeedMoreData); + } + + let t35_metadata = if let Some(t35) = self.t35_q.remove(&input_frameno) { + t35 + } else { + Box::new([]) + }; + + if output_frameno_in_gop > 0 { + let next_keyframe_input_frameno = self.next_keyframe_input_frameno( + self.gop_input_frameno_start[&output_frameno], + false, + ); + let prev_input_frameno = + self.get_previous_fi(output_frameno).input_frameno; + if input_frameno >= next_keyframe_input_frameno { + if !self.inter_cfg.reorder + || ((output_frameno_in_gop - 1) % self.inter_cfg.group_output_len + == 0 + && prev_input_frameno == (next_keyframe_input_frameno - 1)) + { + input_frameno = next_keyframe_input_frameno; + + // If we'll return early, do it before modifying the state. + match self.frame_q.get(&input_frameno) { + Some(Some(_)) => {} + _ => { + return Err(EncoderStatus::NeedMoreData); + } + } + + *self.gop_output_frameno_start.get_mut(&output_frameno).unwrap() = + output_frameno; + *self.gop_input_frameno_start.get_mut(&output_frameno).unwrap() = + next_keyframe_input_frameno; + } else { + let fi = FrameInvariants::new_inter_frame( + self.get_previous_coded_fi(output_frameno), + &self.inter_cfg, + self.gop_input_frameno_start[&output_frameno], + output_frameno_in_gop, + next_keyframe_input_frameno, + self.config.error_resilient, + t35_metadata, + ); + assert!(fi.is_none()); + return Ok(fi); + } + } + } + + match self.frame_q.get(&input_frameno) { + Some(Some(_)) => {} + _ => { + return Err(EncoderStatus::NeedMoreData); + } + } + + // Now that we know the input_frameno, look up the correct frame type + let frame_type = if self.keyframes.contains(&input_frameno) { + FrameType::KEY + } else { + FrameType::INTER + }; + if frame_type == FrameType::KEY { + *self.gop_output_frameno_start.get_mut(&output_frameno).unwrap() = + output_frameno; + *self.gop_input_frameno_start.get_mut(&output_frameno).unwrap() = + input_frameno; + } + + let output_frameno_in_gop = + output_frameno - self.gop_output_frameno_start[&output_frameno]; + if output_frameno_in_gop == 0 { + let fi = FrameInvariants::new_key_frame( + self.config.clone(), + self.seq.clone(), + self.gop_input_frameno_start[&output_frameno], + t35_metadata, + ); + Ok(Some(fi)) + } else { + let next_keyframe_input_frameno = self.next_keyframe_input_frameno( + self.gop_input_frameno_start[&output_frameno], + false, + ); + let fi = FrameInvariants::new_inter_frame( + self.get_previous_coded_fi(output_frameno), + &self.inter_cfg, + self.gop_input_frameno_start[&output_frameno], + output_frameno_in_gop, + next_keyframe_input_frameno, + self.config.error_resilient, + t35_metadata, + ); + assert!(fi.is_some()); + Ok(fi) + } + } + + fn get_previous_fi(&self, output_frameno: u64) -> &FrameInvariants { + let res = self + .frame_data + .iter() + .filter(|(fno, _)| **fno < output_frameno) + .rfind(|(_, fd)| fd.is_some()) + .unwrap(); + &res.1.as_ref().unwrap().fi + } + + fn get_previous_coded_fi(&self, output_frameno: u64) -> &FrameInvariants { + let res = self + .frame_data + .iter() + .filter(|(fno, _)| **fno < output_frameno) + .rfind(|(_, fd)| { + fd.as_ref().map(|fd| !fd.fi.is_show_existing_frame()).unwrap_or(false) + }) + .unwrap(); + &res.1.as_ref().unwrap().fi + } + + pub(crate) fn done_processing(&self) -> bool { + self.limit.map(|limit| self.frames_processed == limit).unwrap_or(false) + } + + /// Computes lookahead motion vectors and fills in `lookahead_mvs`, + /// `rec_buffer` and `lookahead_rec_buffer` on the `FrameInvariants`. This + /// function must be called after every new `FrameInvariants` is initially + /// computed. + #[profiling::function] + fn compute_lookahead_motion_vectors(&mut self, output_frameno: u64) { + let frame_data = self.frame_data.get(&output_frameno).unwrap(); + + // We're only interested in valid frames which are not show-existing-frame. + // Those two don't modify the rec_buffer so there's no need to do anything + // special about it either, it'll propagate on its own. + if frame_data + .as_ref() + .map(|fd| fd.fi.is_show_existing_frame()) + .unwrap_or(true) + { + return; + } + + let qps = { + let fti = frame_data.as_ref().unwrap().fi.get_frame_subtype(); + self.rc_state.select_qi( + self, + output_frameno, + fti, + self.maybe_prev_log_base_q, + 0, + ) + }; + + let frame_data = + self.frame_data.get_mut(&output_frameno).unwrap().as_mut().unwrap(); + let fs = &mut frame_data.fs; + let fi = &mut frame_data.fi; + let coded_data = fi.coded_frame_data.as_mut().unwrap(); + + #[cfg(feature = "dump_lookahead_data")] + { + let data_location = Self::build_dump_properties(); + let plane = &fs.input_qres; + let mut file_name = format!("{:010}-qres", fi.input_frameno); + let buf: Vec<_> = plane.iter().map(|p| p.as_()).collect(); + image::GrayImage::from_vec( + plane.cfg.width as u32, + plane.cfg.height as u32, + buf, + ) + .unwrap() + .save(data_location.join(file_name).with_extension("png")) + .unwrap(); + let plane = &fs.input_hres; + file_name = format!("{:010}-hres", fi.input_frameno); + let buf: Vec<_> = plane.iter().map(|p| p.as_()).collect(); + image::GrayImage::from_vec( + plane.cfg.width as u32, + plane.cfg.height as u32, + buf, + ) + .unwrap() + .save(data_location.join(file_name).with_extension("png")) + .unwrap(); + } + + // Do not modify the next output frame's FrameInvariants. + if self.output_frameno == output_frameno { + // We do want to propagate the lookahead_rec_buffer though. + let rfs = Arc::new(ReferenceFrame { + order_hint: fi.order_hint, + width: fi.width as u32, + height: fi.height as u32, + render_width: fi.render_width, + render_height: fi.render_height, + // Use the original frame contents. + frame: fs.input.clone(), + input_hres: fs.input_hres.clone(), + input_qres: fs.input_qres.clone(), + cdfs: fs.cdfs, + frame_me_stats: fs.frame_me_stats.clone(), + output_frameno, + segmentation: fs.segmentation, + }); + for i in 0..REF_FRAMES { + if (fi.refresh_frame_flags & (1 << i)) != 0 { + coded_data.lookahead_rec_buffer.frames[i] = Some(Arc::clone(&rfs)); + coded_data.lookahead_rec_buffer.deblock[i] = fs.deblock; + } + } + + return; + } + + // Our lookahead_rec_buffer should be filled with correct original frame + // data from the previous frames. Copy it into rec_buffer because that's + // what the MV search uses. During the actual encoding rec_buffer is + // overwritten with its correct values anyway. + fi.rec_buffer = coded_data.lookahead_rec_buffer.clone(); + + // Estimate lambda with rate-control dry-run + fi.set_quantizers(&qps); + + // TODO: as in the encoding code, key frames will have no references. + // However, for block importance purposes we want key frames to act as + // P-frames in this instance. + // + // Compute the motion vectors. + compute_motion_vectors(fi, fs, &self.inter_cfg); + + let coded_data = fi.coded_frame_data.as_mut().unwrap(); + + #[cfg(feature = "dump_lookahead_data")] + { + use crate::partition::RefType::*; + let data_location = Self::build_dump_properties(); + let file_name = format!("{:010}-mvs", fi.input_frameno); + let second_ref_frame = if !self.inter_cfg.multiref { + LAST_FRAME // make second_ref_frame match first + } else if fi.idx_in_group_output == 0 { + LAST2_FRAME + } else { + ALTREF_FRAME + }; + + // Use the default index, it corresponds to the last P-frame or to the + // backwards lower reference (so the closest previous frame). + let index = if second_ref_frame.to_index() != 0 { 0 } else { 1 }; + + let me_stats = &fs.frame_me_stats.read().expect("poisoned lock")[index]; + use byteorder::{NativeEndian, WriteBytesExt}; + // dynamic allocation: debugging only + let mut buf = vec![]; + buf.write_u64::(me_stats.rows as u64).unwrap(); + buf.write_u64::(me_stats.cols as u64).unwrap(); + for y in 0..me_stats.rows { + for x in 0..me_stats.cols { + let mv = me_stats[y][x].mv; + buf.write_i16::(mv.row).unwrap(); + buf.write_i16::(mv.col).unwrap(); + } + } + ::std::fs::write( + data_location.join(file_name).with_extension("bin"), + buf, + ) + .unwrap(); + } + + // Set lookahead_rec_buffer on this FrameInvariants for future + // FrameInvariants to pick it up. + let rfs = Arc::new(ReferenceFrame { + order_hint: fi.order_hint, + width: fi.width as u32, + height: fi.height as u32, + render_width: fi.render_width, + render_height: fi.render_height, + // Use the original frame contents. + frame: fs.input.clone(), + input_hres: fs.input_hres.clone(), + input_qres: fs.input_qres.clone(), + cdfs: fs.cdfs, + frame_me_stats: fs.frame_me_stats.clone(), + output_frameno, + segmentation: fs.segmentation, + }); + for i in 0..REF_FRAMES { + if (fi.refresh_frame_flags & (1 << i)) != 0 { + coded_data.lookahead_rec_buffer.frames[i] = Some(Arc::clone(&rfs)); + coded_data.lookahead_rec_buffer.deblock[i] = fs.deblock; + } + } + } + + /// Computes lookahead intra cost approximations and fills in + /// `lookahead_intra_costs` on the `FrameInvariants`. + fn compute_lookahead_intra_costs(&mut self, output_frameno: u64) { + let frame_data = self.frame_data.get(&output_frameno).unwrap(); + let fd = &frame_data.as_ref(); + + // We're only interested in valid frames which are not show-existing-frame. + if fd.map(|fd| fd.fi.is_show_existing_frame()).unwrap_or(true) { + return; + } + + let fi = &fd.unwrap().fi; + + self + .frame_data + .get_mut(&output_frameno) + .unwrap() + .as_mut() + .unwrap() + .fi + .coded_frame_data + .as_mut() + .unwrap() + .lookahead_intra_costs = self + .keyframe_detector + .intra_costs + .as_mut() + .and_then(|intra_costs| intra_costs.remove(&(fi.input_frameno as usize))) + .unwrap_or_else(|| { + // We use the cached values from scenechange above if available, + // otherwise we need to calculate them here. + let frame = self.frame_q[&fi.input_frameno].as_ref().unwrap(); + let mut temp_plane = frame.planes[0].clone(); + + estimate_intra_costs( + &mut temp_plane, + &**frame, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) + }); + } + + #[profiling::function] + pub fn compute_keyframe_placement( + lookahead_frames: &[&Arc>], keyframes_forced: &BTreeSet, + keyframe_detector: &mut SceneChangeDetector, + next_lookahead_frame: &mut u64, keyframes: &mut BTreeSet, + ) { + if keyframes_forced.contains(next_lookahead_frame) + || keyframe_detector.analyze_next_frame( + lookahead_frames, + *next_lookahead_frame as usize, + *keyframes.iter().last().unwrap() as usize, + ) + { + keyframes.insert(*next_lookahead_frame); + } + + *next_lookahead_frame += 1; + } + + #[profiling::function] + pub fn compute_frame_invariants(&mut self) { + while self.set_frame_properties(self.next_lookahead_output_frameno).is_ok() + { + self + .compute_lookahead_motion_vectors(self.next_lookahead_output_frameno); + if self.config.temporal_rdo() { + self.compute_lookahead_intra_costs(self.next_lookahead_output_frameno); + } + self.next_lookahead_output_frameno += 1; + } + } + + #[profiling::function] + fn update_block_importances( + fi: &FrameInvariants, me_stats: &crate::me::FrameMEStats, + frame: &Frame, reference_frame: &Frame, bit_depth: usize, + bsize: BlockSize, len: usize, + reference_frame_block_importances: &mut [f32], + ) { + let coded_data = fi.coded_frame_data.as_ref().unwrap(); + let plane_org = &frame.planes[0]; + let plane_ref = &reference_frame.planes[0]; + let lookahead_intra_costs_lines = + coded_data.lookahead_intra_costs.chunks_exact(coded_data.w_in_imp_b); + let block_importances_lines = + coded_data.block_importances.chunks_exact(coded_data.w_in_imp_b); + + lookahead_intra_costs_lines + .zip(block_importances_lines) + .zip(me_stats.rows_iter().step_by(2)) + .enumerate() + .flat_map( + |(y, ((lookahead_intra_costs, block_importances), me_stats_line))| { + lookahead_intra_costs + .iter() + .zip(block_importances.iter()) + .zip(me_stats_line.iter().step_by(2)) + .enumerate() + .map(move |(x, ((&intra_cost, &future_importance), &me_stat))| { + let mv = me_stat.mv; + + // Coordinates of the top-left corner of the reference block, in MV + // units. + let reference_x = + x as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.col as i64; + let reference_y = + y as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.row as i64; + + let region_org = plane_org.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let region_ref = plane_ref.region(Area::Rect { + x: reference_x as isize + / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + y: reference_y as isize + / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let inter_cost = get_satd( + ®ion_org, + ®ion_ref, + bsize.width(), + bsize.height(), + bit_depth, + fi.cpu_feature_level, + ) as f32; + + let intra_cost = intra_cost as f32; + // let intra_cost = lookahead_intra_costs[x] as f32; + // let future_importance = block_importances[x]; + + let propagate_fraction = if intra_cost <= inter_cost { + 0. + } else { + 1. - inter_cost / intra_cost + }; + + let propagate_amount = (intra_cost + future_importance) + * propagate_fraction + / len as f32; + (propagate_amount, reference_x, reference_y) + }) + }, + ) + .for_each(|(propagate_amount, reference_x, reference_y)| { + let mut propagate = + |block_x_in_mv_units, block_y_in_mv_units, fraction| { + let x = block_x_in_mv_units / IMP_BLOCK_SIZE_IN_MV_UNITS; + let y = block_y_in_mv_units / IMP_BLOCK_SIZE_IN_MV_UNITS; + + // TODO: propagate partially if the block is partially off-frame + // (possible on right and bottom edges)? + if x >= 0 + && y >= 0 + && (x as usize) < coded_data.w_in_imp_b + && (y as usize) < coded_data.h_in_imp_b + { + reference_frame_block_importances + [y as usize * coded_data.w_in_imp_b + x as usize] += + propagate_amount * fraction; + } + }; + + // Coordinates of the top-left corner of the block intersecting the + // reference block from the top-left. + let top_left_block_x = (reference_x + - if reference_x < 0 { IMP_BLOCK_SIZE_IN_MV_UNITS - 1 } else { 0 }) + / IMP_BLOCK_SIZE_IN_MV_UNITS + * IMP_BLOCK_SIZE_IN_MV_UNITS; + let top_left_block_y = (reference_y + - if reference_y < 0 { IMP_BLOCK_SIZE_IN_MV_UNITS - 1 } else { 0 }) + / IMP_BLOCK_SIZE_IN_MV_UNITS + * IMP_BLOCK_SIZE_IN_MV_UNITS; + + debug_assert!(reference_x >= top_left_block_x); + debug_assert!(reference_y >= top_left_block_y); + + let top_right_block_x = top_left_block_x + IMP_BLOCK_SIZE_IN_MV_UNITS; + let top_right_block_y = top_left_block_y; + let bottom_left_block_x = top_left_block_x; + let bottom_left_block_y = + top_left_block_y + IMP_BLOCK_SIZE_IN_MV_UNITS; + let bottom_right_block_x = top_right_block_x; + let bottom_right_block_y = bottom_left_block_y; + + let top_left_block_fraction = ((top_right_block_x - reference_x) + * (bottom_left_block_y - reference_y)) + as f32 + / IMP_BLOCK_AREA_IN_MV_UNITS as f32; + + propagate(top_left_block_x, top_left_block_y, top_left_block_fraction); + + let top_right_block_fraction = + ((reference_x + IMP_BLOCK_SIZE_IN_MV_UNITS - top_right_block_x) + * (bottom_left_block_y - reference_y)) as f32 + / IMP_BLOCK_AREA_IN_MV_UNITS as f32; + + propagate( + top_right_block_x, + top_right_block_y, + top_right_block_fraction, + ); + + let bottom_left_block_fraction = ((top_right_block_x - reference_x) + * (reference_y + IMP_BLOCK_SIZE_IN_MV_UNITS - bottom_left_block_y)) + as f32 + / IMP_BLOCK_AREA_IN_MV_UNITS as f32; + + propagate( + bottom_left_block_x, + bottom_left_block_y, + bottom_left_block_fraction, + ); + + let bottom_right_block_fraction = + ((reference_x + IMP_BLOCK_SIZE_IN_MV_UNITS - top_right_block_x) + * (reference_y + IMP_BLOCK_SIZE_IN_MV_UNITS - bottom_left_block_y)) + as f32 + / IMP_BLOCK_AREA_IN_MV_UNITS as f32; + + propagate( + bottom_right_block_x, + bottom_right_block_y, + bottom_right_block_fraction, + ); + }); + } + + /// Computes the block importances for the current output frame. + #[profiling::function] + fn compute_block_importances(&mut self) { + // SEF don't need block importances. + if self.frame_data[&self.output_frameno] + .as_ref() + .unwrap() + .fi + .is_show_existing_frame() + { + return; + } + + // Get a list of output_framenos that we want to propagate through. + let output_framenos = self + .get_rdo_lookahead_frames() + .map(|(&output_frameno, _)| output_frameno) + .collect::>(); + + // The first one should be the current output frame. + assert_eq!(output_framenos[0], self.output_frameno); + + // First, initialize them all with zeros. + for output_frameno in output_framenos.iter() { + let fi = &mut self + .frame_data + .get_mut(output_frameno) + .unwrap() + .as_mut() + .unwrap() + .fi; + for x in + fi.coded_frame_data.as_mut().unwrap().block_importances.iter_mut() + { + *x = 0.; + } + } + + // Now compute and propagate the block importances from the end. The + // current output frame will get its block importances from the future + // frames. + let bsize = BlockSize::from_width_and_height( + IMPORTANCE_BLOCK_SIZE, + IMPORTANCE_BLOCK_SIZE, + ); + + for &output_frameno in output_framenos.iter().skip(1).rev() { + // TODO: see comment above about key frames not having references. + if self + .frame_data + .get(&output_frameno) + .unwrap() + .as_ref() + .unwrap() + .fi + .frame_type + == FrameType::KEY + { + continue; + } + + // Remove fi from the map temporarily and put it back in in the end of + // the iteration. This is required because we need to mutably borrow + // referenced fis from the map, and that wouldn't be possible if this was + // an active borrow. + // + // Performance note: Contrary to intuition, + // removing the data and re-inserting it at the end + // is more performant because it avoids a very expensive clone. + let output_frame_data = + self.frame_data.remove(&output_frameno).unwrap().unwrap(); + { + let fi = &output_frame_data.fi; + let fs = &output_frame_data.fs; + + let frame = self.frame_q[&fi.input_frameno].as_ref().unwrap(); + + // There can be at most 3 of these. + let mut unique_indices = ArrayVec::<_, 3>::new(); + + for (mv_index, &rec_index) in fi.ref_frames.iter().enumerate() { + if !unique_indices.iter().any(|&(_, r)| r == rec_index) { + unique_indices.push((mv_index, rec_index)); + } + } + + let bit_depth = self.config.bit_depth; + let frame_data = &mut self.frame_data; + let len = unique_indices.len(); + + let lookahead_me_stats = + fs.frame_me_stats.read().expect("poisoned lock"); + + // Compute and propagate the importance, split evenly between the + // referenced frames. + unique_indices.iter().for_each(|&(mv_index, rec_index)| { + // Use rec_buffer here rather than lookahead_rec_buffer because + // rec_buffer still contains the reference frames for the current frame + // (it's only overwritten when the frame is encoded), while + // lookahead_rec_buffer already contains reference frames for the next + // frame (for the reference propagation to work correctly). + let reference = + fi.rec_buffer.frames[rec_index as usize].as_ref().unwrap(); + let reference_frame = &reference.frame; + let reference_output_frameno = reference.output_frameno; + let me_stats = &lookahead_me_stats[mv_index]; + + // We should never use frame as its own reference. + assert_ne!(reference_output_frameno, output_frameno); + + if let Some(reference_frame_block_importances) = + frame_data.get_mut(&reference_output_frameno).map(|data| { + &mut data + .as_mut() + .unwrap() + .fi + .coded_frame_data + .as_mut() + .unwrap() + .block_importances + }) + { + Self::update_block_importances( + fi, + me_stats, + frame, + reference_frame, + bit_depth, + bsize, + len, + reference_frame_block_importances, + ); + } + }); + } + self.frame_data.insert(output_frameno, Some(output_frame_data)); + } + + if !output_framenos.is_empty() { + let fi = &mut self + .frame_data + .get_mut(&output_framenos[0]) + .unwrap() + .as_mut() + .unwrap() + .fi; + let coded_data = fi.coded_frame_data.as_mut().unwrap(); + let block_importances = coded_data.block_importances.iter(); + let lookahead_intra_costs = coded_data.lookahead_intra_costs.iter(); + let distortion_scales = coded_data.distortion_scales.iter_mut(); + for ((&propagate_cost, &intra_cost), distortion_scale) in + block_importances.zip(lookahead_intra_costs).zip(distortion_scales) + { + *distortion_scale = crate::rdo::distortion_scale_for( + propagate_cost as f64, + intra_cost as f64, + ); + } + #[cfg(feature = "dump_lookahead_data")] + { + use byteorder::{NativeEndian, WriteBytesExt}; + + let coded_data = fi.coded_frame_data.as_ref().unwrap(); + + let mut buf = vec![]; + let data_location = Self::build_dump_properties(); + let file_name = format!("{:010}-imps", fi.input_frameno); + buf.write_u64::(coded_data.h_in_imp_b as u64).unwrap(); + buf.write_u64::(coded_data.w_in_imp_b as u64).unwrap(); + buf.write_u64::(fi.get_frame_subtype() as u64).unwrap(); + for y in 0..coded_data.h_in_imp_b { + for x in 0..coded_data.w_in_imp_b { + buf + .write_f32::(f64::from( + coded_data.distortion_scales[y * coded_data.w_in_imp_b + x], + ) as f32) + .unwrap(); + } + } + ::std::fs::write( + data_location.join(file_name).with_extension("bin"), + buf, + ) + .unwrap(); + } + } + } + + pub(crate) fn encode_packet( + &mut self, cur_output_frameno: u64, + ) -> Result, EncoderStatus> { + if self + .frame_data + .get(&cur_output_frameno) + .unwrap() + .as_ref() + .unwrap() + .fi + .is_show_existing_frame() + { + if !self.rc_state.ready() { + return Err(EncoderStatus::NotReady); + } + + self.encode_show_existing_packet(cur_output_frameno) + } else if let Some(Some(_)) = self.frame_q.get( + &self + .frame_data + .get(&cur_output_frameno) + .unwrap() + .as_ref() + .unwrap() + .fi + .input_frameno, + ) { + if !self.rc_state.ready() { + return Err(EncoderStatus::NotReady); + } + + self.encode_normal_packet(cur_output_frameno) + } else { + Err(EncoderStatus::NeedMoreData) + } + } + + #[profiling::function] + pub fn encode_show_existing_packet( + &mut self, cur_output_frameno: u64, + ) -> Result, EncoderStatus> { + let frame_data = + self.frame_data.get_mut(&cur_output_frameno).unwrap().as_mut().unwrap(); + let sef_data = encode_show_existing_frame( + &frame_data.fi, + &mut frame_data.fs, + &self.inter_cfg, + ); + let bits = (sef_data.len() * 8) as i64; + self.packet_data.extend(sef_data); + self.rc_state.update_state( + bits, + FRAME_SUBTYPE_SEF, + frame_data.fi.show_frame, + 0, + false, + false, + ); + let (rec, source) = if frame_data.fi.show_frame { + (Some(frame_data.fs.rec.clone()), Some(frame_data.fs.input.clone())) + } else { + (None, None) + }; + + self.output_frameno += 1; + + let input_frameno = frame_data.fi.input_frameno; + let frame_type = frame_data.fi.frame_type; + let qp = frame_data.fi.base_q_idx; + let enc_stats = frame_data.fs.enc_stats.clone(); + self.finalize_packet(rec, source, input_frameno, frame_type, qp, enc_stats) + } + + #[profiling::function] + pub fn encode_normal_packet( + &mut self, cur_output_frameno: u64, + ) -> Result, EncoderStatus> { + let mut frame_data = + self.frame_data.remove(&cur_output_frameno).unwrap().unwrap(); + + let mut log_isqrt_mean_scale = 0i64; + + if let Some(coded_data) = frame_data.fi.coded_frame_data.as_mut() { + if self.config.tune == Tune::Psychovisual { + let frame = + self.frame_q[&frame_data.fi.input_frameno].as_ref().unwrap(); + coded_data.activity_mask = ActivityMask::from_plane(&frame.planes[0]); + coded_data.activity_mask.fill_scales( + frame_data.fi.sequence.bit_depth, + &mut coded_data.activity_scales, + ); + log_isqrt_mean_scale = coded_data.compute_spatiotemporal_scores(); + } else { + coded_data.activity_mask = ActivityMask::default(); + log_isqrt_mean_scale = coded_data.compute_temporal_scores(); + } + #[cfg(feature = "dump_lookahead_data")] + { + use crate::encoder::Scales::*; + let input_frameno = frame_data.fi.input_frameno; + if self.config.tune == Tune::Psychovisual { + coded_data.dump_scales( + Self::build_dump_properties(), + ActivityScales, + input_frameno, + ); + coded_data.dump_scales( + Self::build_dump_properties(), + SpatiotemporalScales, + input_frameno, + ); + } + coded_data.dump_scales( + Self::build_dump_properties(), + DistortionScales, + input_frameno, + ); + } + } + + let fti = frame_data.fi.get_frame_subtype(); + let qps = self.rc_state.select_qi( + self, + cur_output_frameno, + fti, + self.maybe_prev_log_base_q, + log_isqrt_mean_scale, + ); + frame_data.fi.set_quantizers(&qps); + + if self.rc_state.needs_trial_encode(fti) { + let mut trial_fs = frame_data.fs.clone(); + let data = encode_frame(&frame_data.fi, &mut trial_fs, &self.inter_cfg); + self.rc_state.update_state( + (data.len() * 8) as i64, + fti, + frame_data.fi.show_frame, + qps.log_target_q, + true, + false, + ); + let qps = self.rc_state.select_qi( + self, + cur_output_frameno, + fti, + self.maybe_prev_log_base_q, + log_isqrt_mean_scale, + ); + frame_data.fi.set_quantizers(&qps); + } + + let data = + encode_frame(&frame_data.fi, &mut frame_data.fs, &self.inter_cfg); + #[cfg(feature = "dump_lookahead_data")] + { + let input_frameno = frame_data.fi.input_frameno; + let data_location = Self::build_dump_properties(); + frame_data.fs.segmentation.dump_threshold(data_location, input_frameno); + } + let enc_stats = frame_data.fs.enc_stats.clone(); + self.maybe_prev_log_base_q = Some(qps.log_base_q); + // TODO: Add support for dropping frames. + self.rc_state.update_state( + (data.len() * 8) as i64, + fti, + frame_data.fi.show_frame, + qps.log_target_q, + false, + false, + ); + self.packet_data.extend(data); + + let planes = + if frame_data.fi.sequence.chroma_sampling == Cs400 { 1 } else { 3 }; + + Arc::get_mut(&mut frame_data.fs.rec).unwrap().pad( + frame_data.fi.width, + frame_data.fi.height, + planes, + ); + + let (rec, source) = if frame_data.fi.show_frame { + (Some(frame_data.fs.rec.clone()), Some(frame_data.fs.input.clone())) + } else { + (None, None) + }; + + update_rec_buffer(cur_output_frameno, &mut frame_data.fi, &frame_data.fs); + + // Copy persistent fields into subsequent FrameInvariants. + let rec_buffer = frame_data.fi.rec_buffer.clone(); + for subsequent_fi in self + .frame_data + .iter_mut() + .skip_while(|(&output_frameno, _)| output_frameno <= cur_output_frameno) + // Here we want the next valid non-show-existing-frame inter frame. + // + // Copying to show-existing-frame frames isn't actually required + // for correct encoding, but it's needed for the reconstruction to + // work correctly. + .filter_map(|(_, frame_data)| frame_data.as_mut().map(|fd| &mut fd.fi)) + .take_while(|fi| fi.frame_type != FrameType::KEY) + { + subsequent_fi.rec_buffer = rec_buffer.clone(); + subsequent_fi.set_ref_frame_sign_bias(); + + // Stop after the first non-show-existing-frame. + if !subsequent_fi.is_show_existing_frame() { + break; + } + } + + self.frame_data.insert(cur_output_frameno, Some(frame_data)); + let frame_data = + self.frame_data.get(&cur_output_frameno).unwrap().as_ref().unwrap(); + let fi = &frame_data.fi; + + self.output_frameno += 1; + + if fi.show_frame { + let input_frameno = fi.input_frameno; + let frame_type = fi.frame_type; + let qp = fi.base_q_idx; + self.finalize_packet( + rec, + source, + input_frameno, + frame_type, + qp, + enc_stats, + ) + } else { + Err(EncoderStatus::Encoded) + } + } + + #[profiling::function] + pub fn receive_packet(&mut self) -> Result, EncoderStatus> { + if self.done_processing() { + return Err(EncoderStatus::LimitReached); + } + + if self.needs_more_fi_lookahead() { + return Err(EncoderStatus::NeedMoreData); + } + + // Find the next output_frameno corresponding to a non-skipped frame. + self.output_frameno = self + .frame_data + .iter() + .skip_while(|(&output_frameno, _)| output_frameno < self.output_frameno) + .find(|(_, data)| data.is_some()) + .map(|(&output_frameno, _)| output_frameno) + .ok_or(EncoderStatus::NeedMoreData)?; // TODO: doesn't play well with the below check? + + let input_frameno = + self.frame_data[&self.output_frameno].as_ref().unwrap().fi.input_frameno; + if !self.needs_more_frames(input_frameno) { + return Err(EncoderStatus::LimitReached); + } + + if self.config.temporal_rdo() { + // Compute the block importances for the current output frame. + self.compute_block_importances(); + } + + let cur_output_frameno = self.output_frameno; + + let mut ret = self.encode_packet(cur_output_frameno); + + if let Ok(ref mut pkt) = ret { + self.garbage_collect(pkt.input_frameno); + pkt.opaque = self.opaque_q.remove(&pkt.input_frameno); + } + + ret + } + + fn finalize_packet( + &mut self, rec: Option>>, source: Option>>, + input_frameno: u64, frame_type: FrameType, qp: u8, + enc_stats: EncoderStats, + ) -> Result, EncoderStatus> { + let data = self.packet_data.clone(); + self.packet_data.clear(); + if write_temporal_delimiter(&mut self.packet_data).is_err() { + return Err(EncoderStatus::Failure); + } + + self.frames_processed += 1; + Ok(Packet { + data, + rec, + source, + input_frameno, + frame_type, + qp, + enc_stats, + opaque: None, + }) + } + + #[profiling::function] + fn garbage_collect(&mut self, cur_input_frameno: u64) { + if cur_input_frameno == 0 { + return; + } + let frame_q_start = self.frame_q.keys().next().cloned().unwrap_or(0); + for i in frame_q_start..cur_input_frameno { + self.frame_q.remove(&i); + } + + if self.output_frameno < 2 { + return; + } + let fi_start = self.frame_data.keys().next().cloned().unwrap_or(0); + for i in fi_start..(self.output_frameno - 1) { + self.frame_data.remove(&i); + self.gop_output_frameno_start.remove(&i); + self.gop_input_frameno_start.remove(&i); + } + } + + /// Counts the number of output frames of each subtype in the next + /// `reservoir_frame_delay` temporal units (needed for rate control). + /// Returns the number of output frames (excluding SEF frames) and output TUs + /// until the last keyframe in the next `reservoir_frame_delay` temporal units, + /// or the end of the interval, whichever comes first. + /// The former is needed because it indicates the number of rate estimates we + /// will make. + /// The latter is needed because it indicates the number of times new bitrate + /// is added to the buffer. + pub(crate) fn guess_frame_subtypes( + &self, nframes: &mut [i32; FRAME_NSUBTYPES + 1], + reservoir_frame_delay: i32, + ) -> (i32, i32) { + for fti in 0..=FRAME_NSUBTYPES { + nframes[fti] = 0; + } + + // Two-pass calls this function before receive_packet(), and in particular + // before the very first send_frame(), when the following maps are empty. + // In this case, return 0 as the default value. + let mut prev_keyframe_input_frameno = *self + .gop_input_frameno_start + .get(&self.output_frameno) + .unwrap_or_else(|| { + assert!(self.output_frameno == 0); + &0 + }); + let mut prev_keyframe_output_frameno = *self + .gop_output_frameno_start + .get(&self.output_frameno) + .unwrap_or_else(|| { + assert!(self.output_frameno == 0); + &0 + }); + + let mut prev_keyframe_ntus = 0; + // Does not include SEF frames. + let mut prev_keyframe_nframes = 0; + let mut acc: [i32; FRAME_NSUBTYPES + 1] = [0; FRAME_NSUBTYPES + 1]; + // Updates the frame counts with the accumulated values when we hit a + // keyframe. + fn collect_counts( + nframes: &mut [i32; FRAME_NSUBTYPES + 1], + acc: &mut [i32; FRAME_NSUBTYPES + 1], + ) { + for fti in 0..=FRAME_NSUBTYPES { + nframes[fti] += acc[fti]; + acc[fti] = 0; + } + acc[FRAME_SUBTYPE_I] += 1; + } + let mut output_frameno = self.output_frameno; + let mut ntus = 0; + // Does not include SEF frames. + let mut nframes_total = 0; + while ntus < reservoir_frame_delay { + let output_frameno_in_gop = + output_frameno - prev_keyframe_output_frameno; + let is_kf = + if let Some(Some(frame_data)) = self.frame_data.get(&output_frameno) { + if frame_data.fi.frame_type == FrameType::KEY { + prev_keyframe_input_frameno = frame_data.fi.input_frameno; + // We do not currently use forward keyframes, so they should always + // end the current TU (thus we always increment ntus below). + debug_assert!(frame_data.fi.show_frame); + true + } else { + false + } + } else { + // It is possible to be invoked for the first time from twopass_out() + // before receive_packet() is called, in which case frame_invariants + // will not be populated. + // Force the first frame in each GOP to be a keyframe in that case. + output_frameno_in_gop == 0 + }; + if is_kf { + collect_counts(nframes, &mut acc); + prev_keyframe_output_frameno = output_frameno; + prev_keyframe_ntus = ntus; + prev_keyframe_nframes = nframes_total; + output_frameno += 1; + ntus += 1; + nframes_total += 1; + continue; + } + let idx_in_group_output = + self.inter_cfg.get_idx_in_group_output(output_frameno_in_gop); + let input_frameno = prev_keyframe_input_frameno + + self + .inter_cfg + .get_order_hint(output_frameno_in_gop, idx_in_group_output) + as u64; + // For rate control purposes, ignore any limit on frame count that has + // been set. + // We pretend that we will keep encoding frames forever to prevent the + // control loop from driving us into the rails as we come up against a + // hard stop (with no more chance to correct outstanding errors). + let next_keyframe_input_frameno = + self.next_keyframe_input_frameno(prev_keyframe_input_frameno, true); + // If we are re-ordering, we may skip some output frames in the final + // re-order group of the GOP. + if input_frameno >= next_keyframe_input_frameno { + // If we have encoded enough whole groups to reach the next keyframe, + // then start the next keyframe gop. + if 1 + + (output_frameno - prev_keyframe_output_frameno) + / self.inter_cfg.group_output_len + * self.inter_cfg.group_input_len + >= next_keyframe_input_frameno - prev_keyframe_input_frameno + { + collect_counts(nframes, &mut acc); + prev_keyframe_input_frameno = input_frameno; + prev_keyframe_output_frameno = output_frameno; + prev_keyframe_ntus = ntus; + prev_keyframe_nframes = nframes_total; + // We do not currently use forward keyframes, so they should always + // end the current TU. + output_frameno += 1; + ntus += 1; + } + output_frameno += 1; + continue; + } + if self.inter_cfg.get_show_existing_frame(idx_in_group_output) { + acc[FRAME_SUBTYPE_SEF] += 1; + } else { + // TODO: Implement golden P-frames. + let fti = FRAME_SUBTYPE_P + + (self.inter_cfg.get_level(idx_in_group_output) as usize); + acc[fti] += 1; + nframes_total += 1; + } + if self.inter_cfg.get_show_frame(idx_in_group_output) { + ntus += 1; + } + output_frameno += 1; + } + if prev_keyframe_output_frameno <= self.output_frameno { + // If there were no keyframes at all, or only the first frame was a + // keyframe, the accumulators never flushed and still contain counts for + // the entire buffer. + // In both cases, we return these counts. + collect_counts(nframes, &mut acc); + (nframes_total, ntus) + } else { + // Otherwise, we discard what remains in the accumulators as they contain + // the counts from and past the last keyframe. + (prev_keyframe_nframes, prev_keyframe_ntus) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/lookahead.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/lookahead.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/lookahead.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/lookahead.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,284 @@ +use crate::api::internal::InterConfig; +use crate::config::EncoderConfig; +use crate::context::{BlockOffset, FrameBlocks, TileBlockOffset}; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::get_satd; +use crate::encoder::{ + FrameInvariants, FrameState, Sequence, IMPORTANCE_BLOCK_SIZE, +}; +use crate::frame::{AsRegion, PlaneOffset}; +use crate::me::{estimate_tile_motion, RefMEStats}; +use crate::partition::{get_intra_edges, BlockSize}; +use crate::predict::{IntraParam, PredictionMode}; +use crate::tiling::{Area, PlaneRegion, TileRect}; +use crate::transform::TxSize; +use crate::util::Aligned; +use crate::Pixel; +use rayon::iter::*; +use std::sync::Arc; +use v_frame::frame::Frame; +use v_frame::pixel::CastFromPrimitive; +use v_frame::plane::Plane; + +pub(crate) const IMP_BLOCK_MV_UNITS_PER_PIXEL: i64 = 8; +pub(crate) const IMP_BLOCK_SIZE_IN_MV_UNITS: i64 = + IMPORTANCE_BLOCK_SIZE as i64 * IMP_BLOCK_MV_UNITS_PER_PIXEL; +pub(crate) const IMP_BLOCK_AREA_IN_MV_UNITS: i64 = + IMP_BLOCK_SIZE_IN_MV_UNITS * IMP_BLOCK_SIZE_IN_MV_UNITS; + +#[profiling::function] +pub(crate) fn estimate_intra_costs( + temp_plane: &mut Plane, frame: &Frame, bit_depth: usize, + cpu_feature_level: CpuFeatureLevel, +) -> Box<[u32]> { + let plane = &frame.planes[0]; + let plane_after_prediction = temp_plane; + + let bsize = BlockSize::from_width_and_height( + IMPORTANCE_BLOCK_SIZE, + IMPORTANCE_BLOCK_SIZE, + ); + let tx_size = bsize.tx_size(); + + let h_in_imp_b = plane.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane.cfg.width / IMPORTANCE_BLOCK_SIZE; + let mut intra_costs = Vec::with_capacity(h_in_imp_b * w_in_imp_b); + + for y in 0..h_in_imp_b { + for x in 0..w_in_imp_b { + let plane_org = plane.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + // TODO: other intra prediction modes. + let mut edge_buf = Aligned::uninit_array(); + let edge_buf = get_intra_edges( + &mut edge_buf, + &plane.as_region(), + TileBlockOffset(BlockOffset { x, y }), + 0, + 0, + bsize, + PlaneOffset { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + }, + TxSize::TX_8X8, + bit_depth, + Some(PredictionMode::DC_PRED), + false, + IntraParam::None, + ); + + let mut plane_after_prediction_region = plane_after_prediction + .region_mut(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + PredictionMode::DC_PRED.predict_intra( + TileRect { + x: x * IMPORTANCE_BLOCK_SIZE, + y: y * IMPORTANCE_BLOCK_SIZE, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }, + &mut plane_after_prediction_region, + tx_size, + bit_depth, + &[], // Not used by DC_PRED + IntraParam::None, + None, // Not used by DC_PRED + &edge_buf, + cpu_feature_level, + ); + + let plane_after_prediction_region = + plane_after_prediction.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let intra_cost = get_satd( + &plane_org, + &plane_after_prediction_region, + bsize.width(), + bsize.height(), + bit_depth, + cpu_feature_level, + ); + + intra_costs.push(intra_cost); + } + } + + intra_costs.into_boxed_slice() +} + +#[profiling::function] +pub(crate) fn estimate_importance_block_difference( + frame: Arc>, ref_frame: Arc>, +) -> f64 { + let plane_org = &frame.planes[0]; + let plane_ref = &ref_frame.planes[0]; + let h_in_imp_b = plane_org.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane_org.cfg.width / IMPORTANCE_BLOCK_SIZE; + + let mut imp_block_costs = 0; + + (0..h_in_imp_b).for_each(|y| { + (0..w_in_imp_b).for_each(|x| { + // Coordinates of the top-left corner of the reference block, in MV + // units. + let region_org = plane_org.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let region_ref = plane_ref.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let sum_8x8_block = |region: &PlaneRegion| { + region + .rows_iter() + .map(|row| { + // 16-bit precision is sufficient for an 8px row, as IMPORTANCE_BLOCK_SIZE * (2^12 - 1) < 2^16 - 1, + // so overflow is not possible + row.iter().map(|pixel| u16::cast_from(*pixel)).sum::() as i64 + }) + .sum::() + }; + + let histogram_org_sum = sum_8x8_block(®ion_org); + let histogram_ref_sum = sum_8x8_block(®ion_ref); + + let count = (IMPORTANCE_BLOCK_SIZE * IMPORTANCE_BLOCK_SIZE) as i64; + + let mean = (((histogram_org_sum + count / 2) / count) + - ((histogram_ref_sum + count / 2) / count)) + .abs(); + + imp_block_costs += mean as u64; + }); + }); + + imp_block_costs as f64 / (w_in_imp_b * h_in_imp_b) as f64 +} + +#[profiling::function] +pub(crate) fn estimate_inter_costs( + frame: Arc>, ref_frame: Arc>, bit_depth: usize, + mut config: EncoderConfig, sequence: Arc, buffer: RefMEStats, +) -> f64 { + config.low_latency = true; + config.speed_settings.multiref = false; + let inter_cfg = InterConfig::new(&config); + let last_fi = FrameInvariants::new_key_frame( + Arc::new(config), + sequence, + 0, + Box::new([]), + ); + let mut fi = FrameInvariants::new_inter_frame( + &last_fi, + &inter_cfg, + 0, + 1, + 2, + false, + Box::new([]), + ) + .unwrap(); + + // Compute the motion vectors. + let mut fs = FrameState::new_with_frame_and_me_stats_and_rec( + &fi, + Arc::clone(&frame), + buffer, + // We do not use this field, so we can avoid the expensive allocation + Arc::new(Frame { + planes: [ + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + Plane::new(0, 0, 0, 0, 0, 0), + ], + }), + ); + compute_motion_vectors(&mut fi, &mut fs, &inter_cfg); + + // Estimate inter costs + let plane_org = &frame.planes[0]; + let plane_ref = &ref_frame.planes[0]; + let h_in_imp_b = plane_org.cfg.height / IMPORTANCE_BLOCK_SIZE; + let w_in_imp_b = plane_org.cfg.width / IMPORTANCE_BLOCK_SIZE; + let stats = &fs.frame_me_stats.read().expect("poisoned lock")[0]; + let bsize = BlockSize::from_width_and_height( + IMPORTANCE_BLOCK_SIZE, + IMPORTANCE_BLOCK_SIZE, + ); + + let mut inter_costs = 0; + (0..h_in_imp_b).for_each(|y| { + (0..w_in_imp_b).for_each(|x| { + let mv = stats[y * 2][x * 2].mv; + + // Coordinates of the top-left corner of the reference block, in MV + // units. + let reference_x = x as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.col as i64; + let reference_y = y as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.row as i64; + + let region_org = plane_org.region(Area::Rect { + x: (x * IMPORTANCE_BLOCK_SIZE) as isize, + y: (y * IMPORTANCE_BLOCK_SIZE) as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + let region_ref = plane_ref.region(Area::Rect { + x: reference_x as isize / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + y: reference_y as isize / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, + width: IMPORTANCE_BLOCK_SIZE, + height: IMPORTANCE_BLOCK_SIZE, + }); + + inter_costs += get_satd( + ®ion_org, + ®ion_ref, + bsize.width(), + bsize.height(), + bit_depth, + fi.cpu_feature_level, + ) as u64; + }); + }); + inter_costs as f64 / (w_in_imp_b * h_in_imp_b) as f64 +} + +#[profiling::function] +pub(crate) fn compute_motion_vectors( + fi: &mut FrameInvariants, fs: &mut FrameState, inter_cfg: &InterConfig, +) { + let mut blocks = FrameBlocks::new(fi.w_in_b, fi.h_in_b); + fi.sequence + .tiling + .tile_iter_mut(fs, &mut blocks) + .collect::>() + .into_par_iter() + .for_each(|mut ctx| { + let ts = &mut ctx.ts; + estimate_tile_motion(fi, ts, inter_cfg); + }); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +// Copyright (c) 2018-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. +#![deny(missing_docs)] + +/// Channel-based encoder +#[cfg(all(feature = "channel-api", feature = "unstable"))] +pub mod channel; +/// Color model information +pub mod color; +/// Encoder Configuration +pub mod config; +/// Encoder Context +pub mod context; +/// Internal implementation +pub(crate) mod internal; +/// Lookahead-specific methods +pub(crate) mod lookahead; + +mod util; + +#[cfg(test)] +mod test; + +#[cfg(all(feature = "channel-api", feature = "unstable"))] +pub use channel::*; +pub use color::*; +pub use config::*; +pub use context::*; +pub(crate) use internal::*; +pub use util::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/test.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/test.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/test.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/test.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2381 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::encoder::FrameInvariants; +use crate::prelude::*; + +use std::sync::Arc; + +use interpolate_name::interpolate_test; + +fn setup_config( + w: usize, h: usize, speed: u8, quantizer: usize, bit_depth: usize, + chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64, + bitrate: i32, low_latency: bool, switch_frame_interval: u64, + no_scene_detection: bool, rdo_lookahead_frames: usize, + min_quantizer: Option, +) -> Config { + let mut enc = EncoderConfig::with_speed_preset(speed); + enc.quantizer = quantizer; + enc.min_key_frame_interval = min_keyint; + enc.max_key_frame_interval = max_keyint; + enc.low_latency = low_latency; + enc.switch_frame_interval = switch_frame_interval; + enc.width = w; + enc.height = h; + enc.bit_depth = bit_depth; + enc.chroma_sampling = chroma_sampling; + enc.bitrate = bitrate; + if no_scene_detection { + enc.speed_settings.scene_detection_mode = SceneDetectionSpeed::None; + } + enc.speed_settings.rdo_lookahead_frames = rdo_lookahead_frames; + if let Some(min_quantizer) = min_quantizer { + enc.min_quantizer = min_quantizer; + } + + Config::new().with_encoder_config(enc).with_threads(1) +} + +fn setup_encoder( + w: usize, h: usize, speed: u8, quantizer: usize, bit_depth: usize, + chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64, + bitrate: i32, low_latency: bool, switch_frame_interval: u64, + no_scene_detection: bool, rdo_lookahead_frames: usize, + min_quantizer: Option, +) -> Context { + let cfg = setup_config( + w, + h, + speed, + quantizer, + bit_depth, + chroma_sampling, + min_keyint, + max_keyint, + bitrate, + low_latency, + switch_frame_interval, + no_scene_detection, + rdo_lookahead_frames, + min_quantizer, + ); + cfg.new_context().unwrap() +} + +/* +fn fill_frame(ra: &mut ChaChaRng, frame: &mut Frame) { + for plane in frame.planes.iter_mut() { + let stride = plane.cfg.stride; + for row in plane.data.chunks_mut(stride) { + for pixel in row { + let v: u8 = ra.random(); + *pixel = T::cast_from(v); + } + } + } +} +*/ + +fn fill_frame_const(frame: &mut Frame, value: T) { + for plane in frame.planes.iter_mut() { + let stride = plane.cfg.stride; + for row in plane.data.chunks_mut(stride) { + for pixel in row { + *pixel = value; + } + } + } +} + +#[cfg(feature = "channel-api")] +mod channel { + use super::*; + + #[interpolate_test(low_latency_no_scene_change, true, true)] + #[interpolate_test(reorder_no_scene_change, false, true)] + #[interpolate_test(low_latency_scene_change_detection, true, false)] + #[interpolate_test(reorder_scene_change_detection, false, false)] + fn flush(low_lantency: bool, no_scene_detection: bool) { + let cfg = setup_config( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 150, + 200, + 0, + low_lantency, + 0, + no_scene_detection, + 10, + None, + ); + + let limit = 41; + + let (mut sf, rp) = cfg.new_channel::().unwrap(); + + for _ in 0..limit { + let input = sf.new_frame(); + let _ = sf.send(input); + } + + drop(sf); + + let mut count = 0; + + for _ in 0..limit { + let _ = rp + .recv() + .map(|_| { + eprintln!("Packet Received {}/{}", count, limit); + count += 1; + }) + .unwrap(); + } + + assert_eq!(limit, count); + } +} + +#[interpolate_test(low_latency_no_scene_change, true, true)] +#[interpolate_test(reorder_no_scene_change, false, true)] +#[interpolate_test(low_latency_scene_change_detection, true, false)] +#[interpolate_test(reorder_scene_change_detection, false, false)] +fn flush(low_lantency: bool, no_scene_detection: bool) { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 150, + 200, + 0, + low_lantency, + 0, + no_scene_detection, + 10, + None, + ); + let limit = 41; + + for _ in 0..limit { + let input = ctx.new_frame(); + let _ = ctx.send_frame(input); + } + + ctx.flush(); + + let mut count = 0; + + 'out: for _ in 0..limit { + loop { + match ctx.receive_packet() { + Ok(_) => { + eprintln!("Packet Received {}/{}", count, limit); + count += 1; + } + Err(EncoderStatus::EnoughData) => { + eprintln!("{:?}", EncoderStatus::EnoughData); + + break 'out; + } + Err(e) => { + eprintln!("{:?}", e); + break; + } + } + } + } + + assert_eq!(limit, count); +} + +#[interpolate_test(low_latency_no_scene_change, true, true)] +#[interpolate_test(reorder_no_scene_change, false, true)] +#[interpolate_test(low_latency_scene_change_detection, true, false)] +#[interpolate_test(reorder_scene_change_detection, false, false)] +fn flush_unlimited(low_lantency: bool, no_scene_detection: bool) { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 150, + 200, + 0, + low_lantency, + 0, + no_scene_detection, + 10, + None, + ); + let limit = 41; + + for _ in 0..limit { + let input = ctx.new_frame(); + let _ = ctx.send_frame(input); + } + + ctx.flush(); + + let mut count = 0; + + 'out: for _ in 0..limit { + loop { + match ctx.receive_packet() { + Ok(_) => { + eprintln!("Packet Received {}/{}", count, limit); + count += 1; + } + Err(EncoderStatus::EnoughData) => { + eprintln!("{:?}", EncoderStatus::EnoughData); + + break 'out; + } + Err(e) => { + eprintln!("{:?}", e); + break; + } + } + } + } + + assert_eq!(limit, count); +} + +fn send_frames( + ctx: &mut Context, limit: u64, scene_change_at: u64, +) { + for i in 0..limit { + if i < scene_change_at { + send_test_frame(ctx, T::min_value()); + } else { + send_test_frame(ctx, T::max_value()); + } + } +} + +fn send_test_frame(ctx: &mut Context, content_value: T) { + let mut input = ctx.new_frame(); + fill_frame_const(&mut input, content_value); + let _ = ctx.send_frame(Arc::new(input)); +} + +fn get_frame_invariants( + ctx: Context, +) -> impl Iterator>> { + ctx.inner.frame_data.into_values().map(|v| v.map(|v| v.fi)) +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +fn output_frameno_low_latency_minus(missing: u64) { + // Test output_frameno configurations when there are less frames + // than the perfect subgop size, in no-reorder mode. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + true, + 0, + true, + 10, + None, + ); + let limit = 10 - missing; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match missing { + 0 => { + &[ + Some(0), // I-frame + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + Some(6), + Some(7), + Some(8), + ][..] + } + _ => unreachable!(), + } + ); +} + +#[test] +fn switch_frame_interval() { + // Test output_frameno configurations when there are less frames + // than the perfect subgop size, in no-reorder mode. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + true, + 2, + true, + 10, + None, + ); + let limit = 10; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| (fi.input_frameno, fi.frame_type))) + .collect::>(); + + assert_eq!( + &data[..], + &[ + Some((0, FrameType::KEY)), + Some((1, FrameType::INTER)), + Some((2, FrameType::SWITCH)), + Some((3, FrameType::INTER)), + Some((4, FrameType::SWITCH)), + Some((5, FrameType::KEY)), + Some((6, FrameType::INTER)), + Some((7, FrameType::SWITCH)), + Some((8, FrameType::INTER)), + Some((9, FrameType::SWITCH)), + ][..] + ); +} + +#[test] +fn minimum_frame_delay() { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + true, + 0, + true, + 1, + None, + ); + + let limit = 4; // 4 frames in for 1 frame out (delay of 3 frames) + send_frames(&mut ctx, limit, 0); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| (fi.input_frameno, fi.frame_type))) + .collect::>(); + + assert_eq!(&data[..], &[Some((0, FrameType::KEY))][..]); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +fn pyramid_level_low_latency_minus(missing: u64) { + // Test pyramid_level configurations when there are less frames + // than the perfect subgop size, in no-reorder mode. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + true, + 0, + true, + 10, + None, + ); + let limit = 10 - missing; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + // data[output_frameno] = pyramid_level + + assert!(get_frame_invariants(ctx) + .map(|fi| fi.unwrap().pyramid_level) + .all(|pyramid_level| pyramid_level == 0)); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn output_frameno_reorder_minus(missing: u64) { + // Test output_frameno configurations when there are less frames + // than the perfect subgop size. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + false, + 0, + true, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10 - missing; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match missing { + 0 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + Some(9), + Some(7), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + Some(7), + Some(6), + Some(7), + Some(8), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + Some(7), + Some(6), + Some(7), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + None, + Some(6), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn pyramid_level_reorder_minus(missing: u64) { + // Test pyramid_level configurations when there are less frames + // than the perfect subgop size. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + false, + 0, + true, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10 - missing; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + // data[output_frameno] = pyramid_level + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.pyramid_level)) + .collect::>(); + + assert_eq!( + &data[..], + match missing { + 0 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), // I-frame + None, + Some(1), + Some(2), + Some(1), + Some(2), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), // I-frame + None, + Some(1), + Some(2), + Some(1), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), // I-frame + None, + None, + Some(2), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), // I-frame + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn output_frameno_reorder_scene_change_at(scene_change_at: u64) { + // Test output_frameno configurations when there's a scene change at the + // th frame. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10; + send_frames(&mut ctx, limit, scene_change_at); + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match scene_change_at { + 0 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), + Some(9), + Some(7), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(1), // I-frame + Some(5), + Some(3), + Some(2), + Some(3), + Some(4), + Some(5), + Some(6), + None, + Some(8), + Some(7), + Some(8), + Some(9), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + None, + None, + Some(1), + None, + None, + None, + Some(2), // I-frame + Some(6), + Some(4), + Some(3), + Some(4), + Some(5), + Some(6), + Some(7), + None, + Some(9), + Some(8), + Some(9), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + None, + None, + Some(3), // I-frame + Some(7), + Some(5), + Some(4), + Some(5), + Some(6), + Some(7), + Some(8), + None, + None, + Some(9), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + Some(3), + None, + Some(4), // I-frame + Some(8), + Some(6), + Some(5), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn pyramid_level_reorder_scene_change_at(scene_change_at: u64) { + // Test pyramid_level configurations when there's a scene change at the + // th frame. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10; + send_frames(&mut ctx, limit, scene_change_at); + ctx.flush(); + + // data[output_frameno] = pyramid_level + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.pyramid_level)) + .collect::>(); + + assert_eq!( + &data[..], + match scene_change_at { + 0 => { + &[ + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), + None, + Some(1), + Some(2), + Some(1), + Some(2), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + None, + None, + Some(2), + None, + None, + None, + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), + None, + Some(1), + Some(2), + Some(1), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + None, + Some(1), + Some(2), + Some(1), + None, + None, + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), + None, + None, + Some(2), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + None, + Some(1), + Some(2), + Some(1), + Some(2), + None, + Some(0), // I-frame + Some(0), + Some(1), + Some(2), + Some(1), + Some(2), + Some(0), + Some(0), + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn output_frameno_incremental_reorder_minus(missing: u64) { + // Test output_frameno configurations when there are less frames + // than the perfect subgop size, computing the lookahead data incrementally. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 5, + 5, + 0, + false, + 0, + true, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10 - missing; + for _ in 0..limit { + send_frames(&mut ctx, 1, 0); + } + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match missing { + 0 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + Some(9), + Some(7), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + Some(7), + Some(6), + Some(7), + Some(8), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + Some(7), + Some(6), + Some(7), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + None, + None, + Some(6), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), // I-frame + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn output_frameno_incremental_reorder_scene_change_at(scene_change_at: u64) { + // Test output_frameno configurations when there's a scene change at the + // th frame, computing the lookahead data incrementally. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 10; + for i in 0..limit { + send_frames(&mut ctx, 1, scene_change_at.saturating_sub(i)); + } + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match scene_change_at { + 0 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), + Some(9), + Some(7), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(1), // I-frame + Some(5), + Some(3), + Some(2), + Some(3), + Some(4), + Some(5), + Some(6), + None, + Some(8), + Some(7), + Some(8), + Some(9), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + None, + None, + Some(1), + None, + None, + None, + Some(2), // I-frame + Some(6), + Some(4), + Some(3), + Some(4), + Some(5), + Some(6), + Some(7), + None, + Some(9), + Some(8), + Some(9), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + None, + None, + Some(3), // I-frame + Some(7), + Some(5), + Some(4), + Some(5), + Some(6), + Some(7), + Some(8), + None, + None, + Some(9), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + Some(3), + None, + Some(4), // I-frame + Some(8), + Some(6), + Some(5), + Some(6), + Some(7), + Some(8), + Some(9), + ][..] + } + _ => unreachable!(), + } + ); +} + +fn send_frame_kf(ctx: &mut Context, keyframe: bool) { + let input = ctx.new_frame(); + + let frame_type_override = + if keyframe { FrameTypeOverride::Key } else { FrameTypeOverride::No }; + + let opaque = Some(Opaque::new(keyframe)); + + let fp = FrameParameters { + frame_type_override, + opaque, + t35_metadata: Box::new([]), + }; + + let _ = ctx.send_frame((input, fp)); +} + +#[test] +fn test_opaque_delivery() { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + let kf_at = 3; + + let limit = 5; + for i in 0..limit { + send_frame_kf(&mut ctx, kf_at == i); + } + ctx.flush(); + + while let Ok(pkt) = ctx.receive_packet() { + let Packet { opaque, input_frameno, .. } = pkt; + if let Some(opaque) = opaque { + let kf = opaque.downcast::().unwrap(); + assert_eq!(kf, Box::new(input_frameno == kf_at)); + } + } +} + +fn send_frame_t35(ctx: &mut Context) { + let input = ctx.new_frame(); + + let frame_type_override = FrameTypeOverride::No; + + let opaque = None; + + let t35_metadata = Box::new([T35 { + country_code: 0xFF, + country_code_extension_byte: 0x00, + data: Box::new(*b"AYAYA"), + }]); + + let fp = FrameParameters { frame_type_override, opaque, t35_metadata }; + + let _ = ctx.send_frame((input, fp)); +} + +#[test] +fn test_t35_parameter() { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + let limit = 2; + for _ in 0..limit { + send_frame_t35(&mut ctx); + } + ctx.flush(); + + while ctx.receive_packet().is_ok() {} +} + +#[interpolate_test(0, 0)] +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +#[interpolate_test(4, 4)] +fn output_frameno_incremental_reorder_keyframe_at(kf_at: u64) { + // Test output_frameno configurations when there's a forced keyframe at the + // th frame, computing the lookahead data incrementally. + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 5; + for i in 0..limit { + send_frame_kf(&mut ctx, kf_at == i); + } + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + match kf_at { + 0 => { + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + ][..] + } + 1 => { + &[ + Some(0), // I-frame + Some(1), // I-frame + None, + Some(3), + Some(2), + Some(3), + Some(4), + None, + ][..] + } + 2 => { + &[ + Some(0), // I-frame + None, + None, + Some(1), + None, + None, + None, + Some(2), // I-frame + None, + Some(4), + Some(3), + Some(4), + None, + None, + ][..] + } + 3 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + None, + None, + Some(3), // I-frame + None, + None, + Some(4), + None, + None, + None, + ][..] + } + 4 => { + &[ + Some(0), // I-frame + None, + Some(2), + Some(1), + Some(2), + Some(3), + None, + Some(4), // I-frame + ][..] + } + _ => unreachable!(), + } + ); +} + +#[interpolate_test(1, 1)] +#[interpolate_test(2, 2)] +#[interpolate_test(3, 3)] +fn output_frameno_no_scene_change_at_short_flash(flash_at: u64) { + // Test output_frameno configurations when there's a single-frame flash at the + // th frame. + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 5, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + + let limit = 5; + for i in 0..limit { + if i == flash_at { + send_test_frame(&mut ctx, u8::MIN); + } else { + send_test_frame(&mut ctx, u8::MAX); + } + } + ctx.flush(); + + // data[output_frameno] = (input_frameno, !invalid) + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + ] + ); +} + +#[test] +fn output_frameno_no_scene_change_at_flash_smaller_than_max_len_flash() { + // Test output_frameno configurations when there's a multi-frame flash + // with length equal to the max flash length + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 10, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + assert_eq!(ctx.inner.inter_cfg.group_input_len, 4); + + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + ctx.flush(); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + None, + Some(6), + Some(5), + Some(6), + Some(7), + None, + ] + ); +} + +#[test] +fn output_frameno_scene_change_before_flash_longer_than_max_flash_len() { + // Test output_frameno configurations when there's a multi-frame flash + // with length greater than the max flash length + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 10, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + assert_eq!(ctx.inner.inter_cfg.group_input_len, 4); + + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MAX); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + ctx.flush(); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + &[ + Some(0), // I-frame + None, + None, + Some(1), + None, + None, + None, + Some(2), // I-frame + Some(6), + Some(4), + Some(3), + Some(4), + Some(5), + Some(6), + Some(10), + Some(8), + Some(7), + Some(8), + Some(9), + Some(10), + None, + None, + Some(11), + None, + None, + None, + ] + ); +} + +#[test] +fn output_frameno_scene_change_after_multiple_flashes() { + // Test output_frameno configurations when there are multiple consecutive flashes + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 10, + 0, + false, + 0, + false, + 10, + None, + ); + + // TODO: when we support more pyramid depths, this test will need tweaks. + assert_eq!(ctx.inner.inter_cfg.pyramid_depth, 2); + assert_eq!(ctx.inner.inter_cfg.group_input_len, 4); + + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, u8::MIN); + send_test_frame(&mut ctx, 40); + send_test_frame(&mut ctx, 100); + send_test_frame(&mut ctx, 160); + send_test_frame(&mut ctx, 240); + send_test_frame(&mut ctx, 240); + send_test_frame(&mut ctx, 240); + send_test_frame(&mut ctx, 240); + send_test_frame(&mut ctx, 240); + send_test_frame(&mut ctx, 240); + ctx.flush(); + + let data = get_frame_invariants(ctx) + .map(|fi| fi.map(|fi| fi.input_frameno)) + .collect::>(); + + assert_eq!( + &data[..], + &[ + Some(0), // I-frame + Some(4), + Some(2), + Some(1), + Some(2), + Some(3), + Some(4), + Some(5), + Some(9), + Some(7), + Some(6), + Some(7), + Some(8), + Some(9), + None, + None, + Some(10), + None, + None, + None, + ] + ); +} + +#[derive(Clone, Copy)] +struct LookaheadTestExpectations { + pre_receive_frame_q_lens: [usize; 60], + pre_receive_fi_lens: [usize; 60], + post_receive_frame_q_lens: [usize; 60], + post_receive_fi_lens: [usize; 60], +} + +#[test] +fn lookahead_size_properly_bounded_8() { + const LOOKAHEAD_SIZE: usize = 8; + const EXPECTATIONS: LookaheadTestExpectations = LookaheadTestExpectations { + pre_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 19, 20, 20, 21, 19, 20, 20, 21, 19, 20, 20, 21, 19, 20, 20, 21, 19, + 20, 20, 21, 19, 20, 20, 21, 19, 20, 20, 21, 19, 20, 20, 21, 19, 20, 20, + 21, 19, 20, 20, + ], + pre_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 19, + 14, 20, 19, 19, 14, 20, 19, 19, 14, 20, 19, 19, 14, 20, 19, 19, 14, 20, + 19, 19, 14, 20, 19, 19, 14, 20, 19, 19, 14, 20, 19, 19, 14, 20, 19, 19, + 14, 20, 19, + ], + post_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 18, 19, 19, 20, 18, 19, 19, 20, 18, 19, 19, 20, 18, 19, 19, 20, 18, 19, + 19, 20, 18, 19, 19, 20, 18, 19, 19, 20, 18, 19, 19, 20, 18, 19, 19, 20, + 18, 19, 19, 20, + ], + post_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 14, + 14, 19, 19, 14, 14, 19, 19, 14, 14, 19, 19, 14, 14, 19, 19, 14, 14, 19, + 19, 14, 14, 19, 19, 14, 14, 19, 19, 14, 14, 19, 19, 14, 14, 19, 19, 14, + 14, 19, 19, + ], + }; + lookahead_size_properly_bounded(LOOKAHEAD_SIZE, false, &EXPECTATIONS); +} + +#[test] +fn lookahead_size_properly_bounded_10() { + const LOOKAHEAD_SIZE: usize = 10; + const EXPECTATIONS: LookaheadTestExpectations = LookaheadTestExpectations { + pre_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 20, 21, 22, 23, 20, 21, 22, 23, 20, 21, 22, 23, 20, 21, 22, + 23, 20, 21, 22, 23, 20, 21, 22, 23, 20, 21, 22, 23, 20, 21, 22, 23, 20, + 21, 22, 23, 20, + ], + pre_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 19, + 19, 25, 19, 19, 19, 25, 19, 19, 19, 25, 19, 19, 19, 25, 19, 19, 19, 25, + 19, 19, 19, 25, 19, 19, 19, 25, 19, 19, 19, 25, 19, 19, 19, 25, 19, 19, + 19, 25, 19, + ], + post_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 19, 20, 21, 22, 19, 20, 21, 22, 19, 20, 21, 22, 19, 20, 21, 22, + 19, 20, 21, 22, 19, 20, 21, 22, 19, 20, 21, 22, 19, 20, 21, 22, 19, 20, + 21, 22, 19, 20, + ], + post_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, + ], + }; + lookahead_size_properly_bounded(LOOKAHEAD_SIZE, false, &EXPECTATIONS); +} + +#[test] +fn lookahead_size_properly_bounded_16() { + const LOOKAHEAD_SIZE: usize = 16; + const EXPECTATIONS: LookaheadTestExpectations = LookaheadTestExpectations { + pre_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 27, 28, 28, 29, 27, 28, 28, 29, 27, + 28, 28, 29, 27, 28, 28, 29, 27, 28, 28, 29, 27, 28, 28, 29, 27, 28, 28, + 29, 27, 28, 28, + ], + pre_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 19, + 19, 25, 25, 25, 25, 31, 31, 31, 26, 32, 31, 31, 26, 32, 31, 31, 26, 32, + 31, 31, 26, 32, 31, 31, 26, 32, 31, 31, 26, 32, 31, 31, 26, 32, 31, 31, + 26, 32, 31, + ], + post_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 26, 27, 27, 28, 26, 27, 27, 28, 26, 27, + 27, 28, 26, 27, 27, 28, 26, 27, 27, 28, 26, 27, 27, 28, 26, 27, 27, 28, + 26, 27, 27, 28, + ], + post_receive_fi_lens: [ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 7, 7, 7, 7, 13, 13, 13, 13, 19, 19, 19, + 19, 25, 25, 25, 25, 31, 31, 26, 26, 31, 31, 26, 26, 31, 31, 26, 26, 31, + 31, 26, 26, 31, 31, 26, 26, 31, 31, 26, 26, 31, 31, 26, 26, 31, 31, 26, + 26, 31, 31, + ], + }; + lookahead_size_properly_bounded(LOOKAHEAD_SIZE, false, &EXPECTATIONS); +} + +#[test] +fn lookahead_size_properly_bounded_lowlatency_8() { + const LOOKAHEAD_SIZE: usize = 8; + const EXPECTATIONS: LookaheadTestExpectations = LookaheadTestExpectations { + pre_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, + ], + pre_receive_fi_lens: [ + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, + ], + post_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, + ], + post_receive_fi_lens: [ + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + ], + }; + lookahead_size_properly_bounded(LOOKAHEAD_SIZE, true, &EXPECTATIONS); +} + +#[test] +fn lookahead_size_properly_bounded_lowlatency_1() { + const LOOKAHEAD_SIZE: usize = 1; + const EXPECTATIONS: LookaheadTestExpectations = LookaheadTestExpectations { + pre_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + ], + pre_receive_fi_lens: [ + 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + ], + post_receive_frame_q_lens: [ + 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + ], + post_receive_fi_lens: [ + 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + ], + }; + lookahead_size_properly_bounded(LOOKAHEAD_SIZE, true, &EXPECTATIONS); +} + +fn lookahead_size_properly_bounded( + rdo_lookahead: usize, low_latency: bool, + expectations: &LookaheadTestExpectations, +) { + // Test that lookahead reads in the proper number of frames at once + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 100, + 8, + ChromaSampling::Cs420, + 0, + 100, + 0, + low_latency, + 0, + true, + rdo_lookahead, + None, + ); + + const LIMIT: usize = 60; + + let mut pre_receive_frame_q_lens = [0; LIMIT]; + let mut pre_receive_fi_lens = [0; LIMIT]; + let mut post_receive_frame_q_lens = [0; LIMIT]; + let mut post_receive_fi_lens = [0; LIMIT]; + + for i in 0..LIMIT { + let input = ctx.new_frame(); + let _ = ctx.send_frame(input); + pre_receive_frame_q_lens[i] = ctx.inner.frame_q.len(); + pre_receive_fi_lens[i] = ctx.inner.frame_data.len(); + while ctx.receive_packet().is_ok() { + // Receive packets until lookahead consumed, due to pyramids receiving frames in groups + } + post_receive_frame_q_lens[i] = ctx.inner.frame_q.len(); + post_receive_fi_lens[i] = ctx.inner.frame_data.len(); + } + + assert_eq!( + &pre_receive_frame_q_lens[..], + &expectations.pre_receive_frame_q_lens[..] + ); + assert_eq!(&pre_receive_fi_lens[..], &expectations.pre_receive_fi_lens[..]); + assert_eq!( + &post_receive_frame_q_lens[..], + &expectations.post_receive_frame_q_lens[..] + ); + assert_eq!( + &post_receive_fi_lens[..], + &expectations.post_receive_fi_lens[..] + ); + + ctx.flush(); + let end = ctx.inner.frame_q.get(&(LIMIT as u64)); + assert!(end.is_some()); + assert!(end.unwrap().is_none()); + + while let Ok(_) | Err(EncoderStatus::Encoded) = ctx.receive_packet() { + // Receive packets until all frames consumed + } + assert_eq!(ctx.inner.frames_processed, LIMIT as u64); +} + +#[test] +fn zero_frames() { + let config = Config::default(); + let mut ctx: Context = config.new_context().unwrap(); + ctx.flush(); + assert_eq!(ctx.receive_packet(), Err(EncoderStatus::LimitReached)); +} + +#[test] +fn tile_cols_overflow() { + let enc = EncoderConfig { tile_cols: usize::MAX, ..Default::default() }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn max_key_frame_interval_overflow() { + let enc = EncoderConfig { + max_key_frame_interval: i32::MAX as u64, + reservoir_frame_delay: None, + ..Default::default() + }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn target_bitrate_overflow() { + let enc = EncoderConfig { + bitrate: i32::MAX, + time_base: Rational::new(i64::MAX as u64, 1), + ..Default::default() + }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn time_base_den_divide_by_zero() { + let enc = + EncoderConfig { time_base: Rational::new(1, 0), ..Default::default() }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn large_width_assert() { + let enc = EncoderConfig { width: u32::MAX as usize, ..Default::default() }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn reservoir_max_overflow() { + let enc = EncoderConfig { + reservoir_frame_delay: Some(i32::MAX), + bitrate: i32::MAX, + time_base: Rational::new(i32::MAX as u64 * 2, 1), + ..Default::default() + }; + let config = Config::new().with_encoder_config(enc); + let _: Result, _> = config.new_context(); +} + +#[test] +fn zero_width() { + let enc = EncoderConfig { width: 0, ..Default::default() }; + let config = Config::new().with_encoder_config(enc); + let res: Result, _> = config.new_context(); + assert!(res.is_err()); +} + +#[test] +fn rdo_lookahead_frames_overflow() { + let enc = EncoderConfig { + speed_settings: SpeedSettings { + rdo_lookahead_frames: usize::MAX, + ..Default::default() + }, + ..Default::default() + }; + let config = Config::new().with_encoder_config(enc); + let res: Result, _> = config.new_context(); + assert!(res.is_err()); +} + +#[test] +fn log_q_exp_overflow() { + let enc = EncoderConfig { + width: 16, + height: 16, + sample_aspect_ratio: Rational::new(1, 1), + bit_depth: 8, + chroma_sampling: ChromaSampling::Cs420, + chroma_sample_position: ChromaSamplePosition::Unknown, + pixel_range: PixelRange::Limited, + color_description: None, + mastering_display: None, + content_light: None, + level_idx: Some(31), + enable_timing_info: false, + still_picture: false, + error_resilient: false, + switch_frame_interval: 0, + time_base: Rational { num: 1, den: 25 }, + min_key_frame_interval: 12, + max_key_frame_interval: 240, + reservoir_frame_delay: None, + low_latency: false, + quantizer: 100, + min_quantizer: 64, + bitrate: 1, + tune: Tune::Psychovisual, + film_grain_params: None, + tile_cols: 0, + tile_rows: 0, + tiles: 0, + speed_settings: SpeedSettings { + multiref: false, + fast_deblock: true, + rdo_lookahead_frames: 40, + scene_detection_mode: SceneDetectionSpeed::None, + cdef: true, + lrf: true, + partition: PartitionSpeedSettings { + partition_range: PartitionRange::new( + BlockSize::BLOCK_64X64, + BlockSize::BLOCK_64X64, + ), + encode_bottomup: false, + non_square_partition_max_threshold: BlockSize::BLOCK_4X4, + }, + transform: TransformSpeedSettings { + reduced_tx_set: true, + tx_domain_distortion: true, + tx_domain_rate: false, + rdo_tx_decision: false, + ..Default::default() + }, + prediction: PredictionSpeedSettings { + prediction_modes: PredictionModesSetting::Simple, + ..Default::default() + }, + motion: MotionSpeedSettings { + include_near_mvs: false, + use_satd_subpel: false, + ..Default::default() + }, + ..Default::default() + }, + }; + let config = Config::new().with_encoder_config(enc).with_threads(1); + + let mut ctx: Context = config.new_context().unwrap(); + for _ in 0..2 { + ctx.send_frame(ctx.new_frame()).unwrap(); + } + ctx.flush(); + + ctx.receive_packet().unwrap(); + let _ = ctx.receive_packet(); +} + +#[test] +fn guess_frame_subtypes_assert() { + let enc = EncoderConfig { + width: 16, + height: 16, + sample_aspect_ratio: Rational::new(1, 1), + bit_depth: 8, + chroma_sampling: ChromaSampling::Cs420, + chroma_sample_position: ChromaSamplePosition::Unknown, + pixel_range: PixelRange::Limited, + color_description: None, + mastering_display: None, + content_light: None, + level_idx: Some(31), + enable_timing_info: false, + still_picture: false, + error_resilient: false, + switch_frame_interval: 0, + time_base: Rational { num: 1, den: 25 }, + min_key_frame_interval: 0, + max_key_frame_interval: 1, + reservoir_frame_delay: None, + low_latency: false, + quantizer: 100, + min_quantizer: 0, + bitrate: 16384, + tune: Tune::Psychovisual, + film_grain_params: None, + tile_cols: 0, + tile_rows: 0, + tiles: 0, + speed_settings: SpeedSettings { + multiref: false, + fast_deblock: true, + rdo_lookahead_frames: 40, + scene_detection_mode: SceneDetectionSpeed::None, + cdef: true, + lrf: true, + partition: PartitionSpeedSettings { + partition_range: PartitionRange::new( + BlockSize::BLOCK_64X64, + BlockSize::BLOCK_64X64, + ), + encode_bottomup: false, + non_square_partition_max_threshold: BlockSize::BLOCK_4X4, + }, + transform: TransformSpeedSettings { + reduced_tx_set: true, + tx_domain_distortion: true, + tx_domain_rate: false, + rdo_tx_decision: false, + ..Default::default() + }, + prediction: PredictionSpeedSettings { + prediction_modes: PredictionModesSetting::Simple, + ..Default::default() + }, + motion: MotionSpeedSettings { + include_near_mvs: false, + use_satd_subpel: false, + ..Default::default() + }, + ..Default::default() + }, + }; + let config = Config::new().with_encoder_config(enc).with_threads(1); + + let mut ctx: Context = config.new_context().unwrap(); + ctx.send_frame(ctx.new_frame()).unwrap(); + ctx.flush(); + + ctx.receive_packet().unwrap(); +} + +#[test] +fn min_quantizer_bounds_correctly() { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 255, + 8, + ChromaSampling::Cs420, + 25, + 25, + 25000, + true, + 0, + true, + 1, + Some(100), + ); + + let limit = 25; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + for i in 0..limit { + ctx.inner.encode_packet(i).unwrap(); + let frame_data = ctx.inner.frame_data.get(&i).unwrap().as_ref().unwrap(); + if i == 0 { + assert_eq!(68, frame_data.fi.base_q_idx); + } else { + assert_eq!(96, frame_data.fi.base_q_idx); + } + } + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 255, + 8, + ChromaSampling::Cs420, + 25, + 25, + 2000, + true, + 0, + true, + 1, + Some(100), + ); + + let limit = 25; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + for i in 0..limit { + ctx.inner.encode_packet(i).unwrap(); + let frame_data = ctx.inner.frame_data.get(&i).unwrap().as_ref().unwrap(); + if i == 0 { + assert!(frame_data.fi.base_q_idx > 68); + } else { + assert!(frame_data.fi.base_q_idx > 96); + } + } +} + +#[test] +fn max_quantizer_bounds_correctly() { + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 120, + 8, + ChromaSampling::Cs420, + 25, + 25, + 2000, + true, + 0, + true, + 1, + None, + ); + + let limit = 25; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + for i in 0..limit { + ctx.inner.encode_packet(i).unwrap(); + let frame_data = ctx.inner.frame_data.get(&i).unwrap().as_ref().unwrap(); + if i == 0 { + assert_eq!(95, frame_data.fi.base_q_idx); + } else { + assert_eq!(115, frame_data.fi.base_q_idx); + } + } + + let mut ctx = setup_encoder::( + 64, + 80, + 10, + 120, + 8, + ChromaSampling::Cs420, + 25, + 25, + 20000, + true, + 0, + true, + 1, + None, + ); + + let limit = 25; + send_frames(&mut ctx, limit, 0); + ctx.flush(); + + for i in 0..limit { + ctx.inner.encode_packet(i).unwrap(); + let frame_data = ctx.inner.frame_data.get(&i).unwrap().as_ref().unwrap(); + if i == 0 { + assert!(frame_data.fi.base_q_idx < 95); + } else { + assert!(frame_data.fi.base_q_idx < 115); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/util.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/api/util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/api/util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,301 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. +#![deny(missing_docs)] + +use crate::frame::*; +use crate::serialize::{Deserialize, Serialize}; +use crate::stats::EncoderStats; +use crate::util::Pixel; + +use std::any::Any; +use std::fmt; +use std::sync::Arc; + +use thiserror::*; + +/// Opaque type to be passed from Frame to Packet +#[derive(Debug)] +pub struct Opaque(Box); + +impl Opaque { + /// Wrap a type in the opaque struct + pub fn new(t: T) -> Self { + Opaque(Box::new(t) as Box) + } + + /// Attempt to downcast the opaque to a concrete type. + /// + /// # Errors + /// + /// Returns `Err(Self)` if the value could not be downcast to `T`. + pub fn downcast(self) -> Result, Opaque> { + if self.0.is::() { + // SAFETY: We verified the type of `T` before this cast. + unsafe { + let raw: *mut (dyn Any + Send + Sync) = Box::into_raw(self.0); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +// TODO: use the num crate? +/// A rational number. +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct Rational { + /// Numerator. + pub num: u64, + /// Denominator. + pub den: u64, +} + +impl Rational { + /// Creates a rational number from the given numerator and denominator. + pub const fn new(num: u64, den: u64) -> Self { + Rational { num, den } + } + + /// Returns a rational number that is the reciprocal of the given one. + pub const fn from_reciprocal(reciprocal: Self) -> Self { + Rational { num: reciprocal.den, den: reciprocal.num } + } + + /// Returns the rational number as a floating-point number. + pub fn as_f64(self) -> f64 { + self.num as f64 / self.den as f64 + } +} + +#[cfg(feature = "serialize")] +impl serde::Serialize for Rational { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + (self.num, self.den).serialize(serializer) + } +} + +#[cfg(feature = "serialize")] +impl<'a> serde::Deserialize<'a> for Rational { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'a>, + { + let (num, den) = serde::Deserialize::deserialize(deserializer)?; + + Ok(Rational::new(num, den)) + } +} + +/// Possible types of a frame. +#[allow(dead_code, non_camel_case_types)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] +#[repr(C)] +pub enum FrameType { + /// Key frame. + KEY, + /// Inter-frame. + INTER, + /// Intra-only frame. + INTRA_ONLY, + /// Switching frame. + SWITCH, +} + +impl FrameType { + /// Returns whether frame can have inter blocks + #[inline] + pub fn has_inter(self) -> bool { + self == FrameType::INTER || self == FrameType::SWITCH + } + /// Returns whether frame is only intra blocks + #[inline] + pub fn all_intra(self) -> bool { + self == FrameType::KEY || self == FrameType::INTRA_ONLY + } +} + +impl fmt::Display for FrameType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use self::FrameType::*; + match self { + KEY => write!(f, "Key frame"), + INTER => write!(f, "Inter frame"), + INTRA_ONLY => write!(f, "Intra only frame"), + SWITCH => write!(f, "Switching frame"), + } + } +} + +/// A single T.35 metadata packet. +#[derive(Clone, Debug, Default)] +pub struct T35 { + /// Country code. + pub country_code: u8, + /// Country code extension bytes (if `country_code` == 0xFF) + pub country_code_extension_byte: u8, + /// T.35 payload. + pub data: Box<[u8]>, +} + +/// Status that can be returned by [`Context`] functions. +/// +/// [`Context`]: struct.Context.html +#[derive(Clone, Copy, Debug, Eq, PartialEq, Error)] +pub enum EncoderStatus { + /// The encoder needs more data to produce an output packet. + /// + /// May be emitted by [`Context::receive_packet()`] when frame reordering is + /// enabled. + /// + /// [`Context::receive_packet()`]: struct.Context.html#method.receive_packet + #[error("need more data")] + NeedMoreData, + /// There are enough frames in the queue. + /// + /// May be emitted by [`Context::send_frame()`] when trying to send a frame + /// after the encoder has been flushed. + /// + /// [`Context::send_frame()`]: struct.Context.html#method.send_frame + #[error("enough data")] + EnoughData, + /// The encoder has already produced the number of frames requested. + /// + /// May be emitted by [`Context::receive_packet()`] after a flush request had + /// been processed or the frame limit had been reached. + /// + /// [`Context::receive_packet()`]: struct.Context.html#method.receive_packet + #[error("limit reached")] + LimitReached, + /// A frame had been encoded but not emitted yet. + #[error("encoded")] + Encoded, + /// Generic fatal error. + #[error("failure")] + Failure, + /// A frame was encoded in the first pass of a 2-pass encode, but its stats + /// data was not retrieved with [`Context::twopass_out()`], or not enough + /// stats data was provided in the second pass of a 2-pass encode to encode + /// the next frame. + /// + /// [`Context::twopass_out()`]: struct.Context.html#method.twopass_out + #[error("not ready")] + NotReady, +} + +/// Represents a packet. +/// +/// A packet contains one shown frame together with zero or more additional +/// frames. +#[derive(Debug, Serialize, Deserialize)] +pub struct Packet { + /// The packet data. + pub data: Vec, + /// The reconstruction of the shown frame. + #[cfg_attr(feature = "serialize", serde(skip))] + pub rec: Option>>, + /// The Reference Frame + #[cfg_attr(feature = "serialize", serde(skip))] + pub source: Option>>, + /// The number of the input frame corresponding to the one shown frame in the + /// TU stored in this packet. Since AV1 does not explicitly reorder frames, + /// these will increase sequentially. + // TODO: When we want to add VFR support, we will need a more explicit time + // stamp here. + pub input_frameno: u64, + /// Type of the shown frame. + pub frame_type: FrameType, + /// QP selected for the frame. + pub qp: u8, + /// Block-level encoding stats for the frame + pub enc_stats: EncoderStats, + /// Optional user-provided opaque data + #[cfg_attr(feature = "serialize", serde(skip))] + pub opaque: Option, +} + +impl PartialEq for Packet { + fn eq(&self, other: &Self) -> bool { + self.data == other.data + && self.input_frameno == other.input_frameno + && self.frame_type == other.frame_type + && self.qp == other.qp + } +} + +impl fmt::Display for Packet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Frame {} - {} - {} bytes", + self.input_frameno, + self.frame_type, + self.data.len() + ) + } +} + +/// Types which can be converted into frames. +/// +/// This trait is used in [`Context::send_frame`] to allow for passing in +/// frames with optional frame parameters and optionally frames wrapped in +/// `Arc` (to allow for zero-copy, since the encoder uses frames in `Arc` +/// internally). +/// +/// [`Context::send_frame`]: struct.Context.html#method.send_frame +pub trait IntoFrame { + /// Converts the type into a tuple of frame and parameters. + fn into(self) -> (Option>>, Option); +} + +impl IntoFrame for Option>> { + fn into(self) -> (Option>>, Option) { + (self, None) + } +} + +impl IntoFrame for Arc> { + fn into(self) -> (Option>>, Option) { + (Some(self), None) + } +} + +impl IntoFrame for (Arc>, FrameParameters) { + fn into(self) -> (Option>>, Option) { + (Some(self.0), Some(self.1)) + } +} + +impl IntoFrame for (Arc>, Option) { + fn into(self) -> (Option>>, Option) { + (Some(self.0), self.1) + } +} + +impl IntoFrame for Frame { + fn into(self) -> (Option>>, Option) { + (Some(Arc::new(self)), None) + } +} + +impl IntoFrame for (Frame, FrameParameters) { + fn into(self) -> (Option>>, Option) { + (Some(Arc::new(self.0)), Some(self.1)) + } +} + +impl IntoFrame for (Frame, Option) { + fn into(self) -> (Option>>, Option) { + (Some(Arc::new(self.0)), self.1) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,540 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" +#include "cdef_tmpl.S" + +// n1 = s0/d0 +// w1 = d0/q0 +// n2 = s4/d2 +// w2 = d2/q1 +.macro pad_top_bottom s1, s2, w, stride, n1, w1, n2, w2, align, ret + tst r7, #1 // CDEF_HAVE_LEFT + beq 2f + // CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + ldrh r12, [\s1, #-2] + vldr \n1, [\s1] + vdup.16 d4, r12 + ldrh r12, [\s1, #\w] + vmov.16 d4[1], r12 + ldrh r12, [\s2, #-2] + vldr \n2, [\s2] + vmov.16 d4[2], r12 + ldrh r12, [\s2, #\w] + vmovl.u8 q0, d0 + vmov.16 d4[3], r12 + vmovl.u8 q1, d2 + vmovl.u8 q2, d4 + vstr s8, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s9, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s10, [r0, #-4] + vst1.16 {\w2}, [r0, :\align] + vstr s11, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ldrh r12, [\s1, #-2] + vldr \n1, [\s1] + vdup.16 d4, r12 + ldrh r12, [\s2, #-2] + vldr \n2, [\s2] + vmovl.u8 q0, d0 + vmov.16 d4[1], r12 + vmovl.u8 q1, d2 + vmovl.u8 q2, d4 + vstr s8, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s9, [r0, #-4] + vst1.16 {\w2}, [r0, :\align] + vstr s12, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +2: + // !CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + vldr \n1, [\s1] + ldrh r12, [\s1, #\w] + vldr \n2, [\s2] + vdup.16 d4, r12 + ldrh r12, [\s2, #\w] + vmovl.u8 q0, d0 + vmov.16 d4[1], r12 + vmovl.u8 q1, d2 + vmovl.u8 q2, d4 + vstr s12, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s8, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s12, [r0, #-4] + vst1.16 {\w2}, [r0, :\align] + vstr s9, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vldr \n1, [\s1] + vldr \n2, [\s2] + vmovl.u8 q0, d0 + vmovl.u8 q1, d2 + vstr s12, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s12, [r0, #-4] + vst1.16 {\w2}, [r0, :\align] + vstr s12, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride +.endif +3: +.endm + +.macro load_n_incr dst, src, incr, w +.if \w == 4 + vld1.32 {\dst\()[0]}, [\src, :32], \incr +.else + vld1.8 {\dst\()}, [\src, :64], \incr +.endif +.endm + +// void dav1d_cdef_paddingX_8bpc_neon(uint16_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +// n1 = s0/d0 +// w1 = d0/q0 +// n2 = s4/d2 +// w2 = d2/q1 +.macro padding_func w, stride, n1, w1, n2, w2, align +function cdef_padding\w\()_8bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + cmp r7, #0xf // fully edged + beq cdef_padding\w\()_edged_8bpc_neon + vmov.i16 q3, #0x8000 + tst r7, #4 // CDEF_HAVE_TOP + bne 1f + // !CDEF_HAVE_TOP + sub r12, r0, #2*(2*\stride+2) + vmov.i16 q2, #0x8000 + vst1.16 {q2,q3}, [r12]! +.if \w == 8 + vst1.16 {q2,q3}, [r12]! +.endif + b 3f +1: + // CDEF_HAVE_TOP + add r8, r4, r2 + sub r0, r0, #2*(2*\stride) + pad_top_bottom r4, r8, \w, \stride, \n1, \w1, \n2, \w2, \align, 0 + + // Middle section +3: + tst r7, #1 // CDEF_HAVE_LEFT + beq 2f + // CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + vld1.16 {d2[]}, [r3, :16]! + ldrh r12, [r1, #\w] + load_n_incr d0, r1, r2, \w + subs r6, r6, #1 + vmov.16 d2[1], r12 + vmovl.u8 q0, d0 + vmovl.u8 q1, d2 + vstr s4, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s5, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 0b + b 3f +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vld1.16 {d2[]}, [r3, :16]! + load_n_incr d0, r1, r2, \w + subs r6, r6, #1 + vmovl.u8 q0, d0 + vmovl.u8 q1, d2 + vstr s4, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 1b + b 3f +2: + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + ldrh r12, [r1, #\w] + load_n_incr d0, r1, r2, \w + vdup.16 d2, r12 + subs r6, r6, #1 + vmovl.u8 q0, d0 + vmovl.u8 q1, d2 + vstr s12, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s4, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 0b + b 3f +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + load_n_incr d0, r1, r2, \w + subs r6, r6, #1 + vmovl.u8 q0, d0 + vstr s12, [r0, #-4] + vst1.16 {\w1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 1b + +3: + tst r7, #8 // CDEF_HAVE_BOTTOM + bne 1f + // !CDEF_HAVE_BOTTOM + sub r12, r0, #4 + vmov.i16 q2, #0x8000 + vst1.16 {q2,q3}, [r12]! +.if \w == 8 + vst1.16 {q2,q3}, [r12]! +.endif + pop {r4-r8,pc} +1: + // CDEF_HAVE_BOTTOM + add r8, r5, r2 + pad_top_bottom r5, r8, \w, \stride, \n1, \w1, \n2, \w2, \align, 1 +endfunc +.endm + +padding_func 8, 16, d0, q0, d2, q1, 128 +padding_func 4, 8, s0, d0, s4, d2, 64 + +// void cdef_paddingX_edged_8bpc_neon(uint16_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +.macro padding_func_edged w, stride, reg, align +function cdef_padding\w\()_edged_8bpc_neon + sub r0, r0, #(2*\stride) + + ldrh r12, [r4, #-2] + vldr \reg, [r4] + add r8, r4, r2 + strh r12, [r0, #-2] + ldrh r12, [r4, #\w] + vstr \reg, [r0] + strh r12, [r0, #\w] + + ldrh r12, [r8, #-2] + vldr \reg, [r8] + strh r12, [r0, #\stride-2] + ldrh r12, [r8, #\w] + vstr \reg, [r0, #\stride] + strh r12, [r0, #\stride+\w] + add r0, r0, #2*\stride + +0: + ldrh r12, [r3], #2 + vldr \reg, [r1] + str r12, [r0, #-2] + ldrh r12, [r1, #\w] + add r1, r1, r2 + subs r6, r6, #1 + vstr \reg, [r0] + str r12, [r0, #\w] + add r0, r0, #\stride + bgt 0b + + ldrh r12, [r5, #-2] + vldr \reg, [r5] + add r8, r5, r2 + strh r12, [r0, #-2] + ldrh r12, [r5, #\w] + vstr \reg, [r0] + strh r12, [r0, #\w] + + ldrh r12, [r8, #-2] + vldr \reg, [r8] + strh r12, [r0, #\stride-2] + ldrh r12, [r8, #\w] + vstr \reg, [r0, #\stride] + strh r12, [r0, #\stride+\w] + + pop {r4-r8,pc} +endfunc +.endm + +padding_func_edged 8, 16, d0, 64 +padding_func_edged 4, 8, s0, 32 + +tables + +filter 8, 8 +filter 4, 8 + +find_dir 8 + +.macro load_px_8 d11, d12, d21, d22, w +.if \w == 8 + add r6, r2, r9 // x + off + sub r9, r2, r9 // x - off + vld1.8 {\d11}, [r6] // p0 + add r6, r6, #16 // += stride + vld1.8 {\d21}, [r9] // p1 + add r9, r9, #16 // += stride + vld1.8 {\d12}, [r6] // p0 + vld1.8 {\d22}, [r9] // p1 +.else + add r6, r2, r9 // x + off + sub r9, r2, r9 // x - off + vld1.32 {\d11[0]}, [r6] // p0 + add r6, r6, #8 // += stride + vld1.32 {\d21[0]}, [r9] // p1 + add r9, r9, #8 // += stride + vld1.32 {\d11[1]}, [r6] // p0 + add r6, r6, #8 // += stride + vld1.32 {\d21[1]}, [r9] // p1 + add r9, r9, #8 // += stride + vld1.32 {\d12[0]}, [r6] // p0 + add r6, r6, #8 // += stride + vld1.32 {\d22[0]}, [r9] // p1 + add r9, r9, #8 // += stride + vld1.32 {\d12[1]}, [r6] // p0 + vld1.32 {\d22[1]}, [r9] // p1 +.endif +.endm +.macro handle_pixel_8 s1, s2, thresh_vec, shift, tap, min +.if \min + vmin.u8 q3, q3, \s1 + vmax.u8 q4, q4, \s1 + vmin.u8 q3, q3, \s2 + vmax.u8 q4, q4, \s2 +.endif + vabd.u8 q8, q0, \s1 // abs(diff) + vabd.u8 q11, q0, \s2 // abs(diff) + vshl.u8 q9, q8, \shift // abs(diff) >> shift + vshl.u8 q12, q11, \shift // abs(diff) >> shift + vqsub.u8 q9, \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift)) + vqsub.u8 q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift)) + vcgt.u8 q10, q0, \s1 // px > p0 + vcgt.u8 q13, q0, \s2 // px > p1 + vmin.u8 q9, q9, q8 // imin(abs(diff), clip) + vmin.u8 q12, q12, q11 // imin(abs(diff), clip) + vneg.s8 q8, q9 // -imin() + vneg.s8 q11, q12 // -imin() + vbsl q10, q8, q9 // constrain() = imax(imin(diff, clip), -clip) + vdup.8 d18, \tap // taps[k] + vbsl q13, q11, q12 // constrain() = imax(imin(diff, clip), -clip) + vmlal.s8 q1, d20, d18 // sum += taps[k] * constrain() + vmlal.s8 q1, d26, d18 // sum += taps[k] * constrain() + vmlal.s8 q2, d21, d18 // sum += taps[k] * constrain() + vmlal.s8 q2, d27, d18 // sum += taps[k] * constrain() +.endm + +// void cdef_filterX_edged_neon(pixel *dst, ptrdiff_t dst_stride, +// const uint16_t *tmp, int pri_strength, +// int sec_strength, int dir, int damping, +// int h, size_t edges); +.macro filter_func_8 w, pri, sec, min, suffix +function cdef_filter\w\suffix\()_edged_neon +.if \pri + movrel_local r8, pri_taps + and r9, r3, #1 + add r8, r8, r9, lsl #1 +.endif + movrel_local r9, directions\w + add r5, r9, r5, lsl #1 + vmov.u8 d17, #7 + vdup.8 d16, r6 // damping + + vmov.8 d8[0], r3 + vmov.8 d8[1], r4 + vclz.i8 d8, d8 // clz(threshold) + vsub.i8 d8, d17, d8 // ulog2(threshold) + vqsub.u8 d8, d16, d8 // shift = imax(0, damping - ulog2(threshold)) + vneg.s8 d8, d8 // -shift +.if \sec + vdup.8 q6, d8[1] +.endif +.if \pri + vdup.8 q5, d8[0] +.endif + +1: +.if \w == 8 + add r12, r2, #16 + vld1.8 {d0}, [r2, :64] // px + vld1.8 {d1}, [r12, :64] // px +.else + add r12, r2, #8 + vld1.32 {d0[0]}, [r2, :32] // px + add r9, r2, #2*8 + vld1.32 {d0[1]}, [r12, :32] // px + add r12, r12, #2*8 + vld1.32 {d1[0]}, [r9, :32] // px + vld1.32 {d1[1]}, [r12, :32] // px +.endif + + vmov.u8 q1, #0 // sum + vmov.u8 q2, #0 // sum +.if \min + vmov.u16 q3, q0 // min + vmov.u16 q4, q0 // max +.endif + + // Instead of loading sec_taps 2, 1 from memory, just set it + // to 2 initially and decrease for the second round. + // This is also used as loop counter. + mov lr, #2 // sec_taps[0] + +2: +.if \pri + ldrsb r9, [r5] // off1 + + load_px_8 d28, d29, d30, d31, \w +.endif + +.if \sec + add r5, r5, #4 // +2*2 + ldrsb r9, [r5] // off2 +.endif + +.if \pri + ldrb r12, [r8] // *pri_taps + vdup.8 q7, r3 // threshold + + handle_pixel_8 q14, q15, q7, q5, r12, \min +.endif + +.if \sec + load_px_8 d28, d29, d30, d31, \w + + add r5, r5, #8 // +2*4 + ldrsb r9, [r5] // off3 + + vdup.8 q7, r4 // threshold + + handle_pixel_8 q14, q15, q7, q6, lr, \min + + load_px_8 d28, d29, d30, d31, \w + + handle_pixel_8 q14, q15, q7, q6, lr, \min + + sub r5, r5, #11 // r5 -= 2*(2+4); r5 += 1; +.else + add r5, r5, #1 // r5 += 1 +.endif + subs lr, lr, #1 // sec_tap-- (value) +.if \pri + add r8, r8, #1 // pri_taps++ (pointer) +.endif + bne 2b + + vshr.s16 q14, q1, #15 // -(sum < 0) + vshr.s16 q15, q2, #15 // -(sum < 0) + vadd.i16 q1, q1, q14 // sum - (sum < 0) + vadd.i16 q2, q2, q15 // sum - (sum < 0) + vrshr.s16 q1, q1, #4 // (8 + sum - (sum < 0)) >> 4 + vrshr.s16 q2, q2, #4 // (8 + sum - (sum < 0)) >> 4 + vaddw.u8 q1, q1, d0 // px + (8 + sum ...) >> 4 + vaddw.u8 q2, q2, d1 // px + (8 + sum ...) >> 4 + vqmovun.s16 d0, q1 + vqmovun.s16 d1, q2 +.if \min + vmin.u8 q0, q0, q4 + vmax.u8 q0, q0, q3 // iclip(px + .., min, max) +.endif +.if \w == 8 + vst1.8 {d0}, [r0, :64], r1 + add r2, r2, #2*16 // tmp += 2*tmp_stride + subs r7, r7, #2 // h -= 2 + vst1.8 {d1}, [r0, :64], r1 +.else + vst1.32 {d0[0]}, [r0, :32], r1 + add r2, r2, #4*8 // tmp += 4*tmp_stride + vst1.32 {d0[1]}, [r0, :32], r1 + subs r7, r7, #4 // h -= 4 + vst1.32 {d1[0]}, [r0, :32], r1 + vst1.32 {d1[1]}, [r0, :32], r1 +.endif + + // Reset pri_taps and directions back to the original point + sub r5, r5, #2 +.if \pri + sub r8, r8, #2 +.endif + + bgt 1b + vpop {q4-q7} + pop {r4-r9,pc} +endfunc +.endm + +.macro filter_8 w +filter_func_8 \w, pri=1, sec=0, min=0, suffix=_pri +filter_func_8 \w, pri=0, sec=1, min=0, suffix=_sec +filter_func_8 \w, pri=1, sec=1, min=1, suffix=_pri_sec +.endm + +filter_8 8 +filter_8 4 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,233 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" +#include "cdef_tmpl.S" + +// r1 = d0/q0 +// r2 = d2/q1 +.macro pad_top_bot_16 s1, s2, w, stride, r1, r2, align, ret + tst r7, #1 // CDEF_HAVE_LEFT + beq 2f + // CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + vldr s8, [\s1, #-4] + vld1.16 {\r1}, [\s1, :\align] + vldr s9, [\s1, #2*\w] + vldr s10, [\s2, #-4] + vld1.16 {\r2}, [\s2, :\align] + vldr s11, [\s2, #2*\w] + vstr s8, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s9, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s10, [r0, #-4] + vst1.16 {\r2}, [r0, :\align] + vstr s11, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vldr s8, [\s1, #-4] + vld1.16 {\r1}, [\s1, :\align] + vldr s9, [\s2, #-4] + vld1.16 {\r2}, [\s2, :\align] + vstr s8, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s9, [r0, #-4] + vst1.16 {\r2}, [r0, :\align] + vstr s12, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +2: + // !CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + vld1.16 {\r1}, [\s1, :\align] + vldr s8, [\s1, #2*\w] + vld1.16 {\r2}, [\s2, :\align] + vldr s9, [\s2, #2*\w] + vstr s12, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s8, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s12, [r0, #-4] + vst1.16 {\r2}, [r0, :\align] + vstr s9, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride + b 3f +.endif + +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vld1.16 {\r1}, [\s1, :\align] + vld1.16 {\r2}, [\s2, :\align] + vstr s12, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + vstr s12, [r0, #-4] + vst1.16 {\r2}, [r0, :\align] + vstr s12, [r0, #2*\w] +.if \ret + pop {r4-r8,pc} +.else + add r0, r0, #2*\stride +.endif +3: +.endm + +// void dav1d_cdef_paddingX_16bpc_neon(uint16_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +// r1 = d0/q0 +// r2 = d2/q1 +.macro padding_func_16 w, stride, r1, r2, align +function cdef_padding\w\()_16bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + vmov.i16 q3, #0x8000 + tst r7, #4 // CDEF_HAVE_TOP + bne 1f + // !CDEF_HAVE_TOP + sub r12, r0, #2*(2*\stride+2) + vmov.i16 q2, #0x8000 + vst1.16 {q2,q3}, [r12]! +.if \w == 8 + vst1.16 {q2,q3}, [r12]! +.endif + b 3f +1: + // CDEF_HAVE_TOP + add r8, r4, r2 + sub r0, r0, #2*(2*\stride) + pad_top_bot_16 r4, r8, \w, \stride, \r1, \r2, \align, 0 + + // Middle section +3: + tst r7, #1 // CDEF_HAVE_LEFT + beq 2f + // CDEF_HAVE_LEFT + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + vld1.32 {d2[]}, [r3, :32]! + vldr s5, [r1, #2*\w] + vld1.16 {\r1}, [r1, :\align], r2 + subs r6, r6, #1 + vstr s4, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s5, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 0b + b 3f +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vld1.32 {d2[]}, [r3, :32]! + vld1.16 {\r1}, [r1, :\align], r2 + subs r6, r6, #1 + vstr s4, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 1b + b 3f +2: + tst r7, #2 // CDEF_HAVE_RIGHT + beq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + vldr s4, [r1, #2*\w] + vld1.16 {\r1}, [r1, :\align], r2 + subs r6, r6, #1 + vstr s12, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s4, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 0b + b 3f +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + vld1.16 {\r1}, [r1, :\align], r2 + subs r6, r6, #1 + vstr s12, [r0, #-4] + vst1.16 {\r1}, [r0, :\align] + vstr s12, [r0, #2*\w] + add r0, r0, #2*\stride + bgt 1b + +3: + tst r7, #8 // CDEF_HAVE_BOTTOM + bne 1f + // !CDEF_HAVE_BOTTOM + sub r12, r0, #4 + vmov.i16 q2, #0x8000 + vst1.16 {q2,q3}, [r12]! +.if \w == 8 + vst1.16 {q2,q3}, [r12]! +.endif + pop {r4-r8,pc} +1: + // CDEF_HAVE_BOTTOM + add r8, r5, r2 + pad_top_bot_16 r5, r8, \w, \stride, \r1, \r2, \align, 1 +endfunc +.endm + +padding_func_16 8, 16, q0, q1, 128 +padding_func_16 4, 8, d0, d2, 64 + +tables + +filter 8, 16 +filter 4, 16 + +find_dir 16 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef_tmpl.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef_tmpl.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef_tmpl.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/cdef_tmpl.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,515 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro dir_table w, stride +const directions\w + .byte -1 * \stride + 1, -2 * \stride + 2 + .byte 0 * \stride + 1, -1 * \stride + 2 + .byte 0 * \stride + 1, 0 * \stride + 2 + .byte 0 * \stride + 1, 1 * \stride + 2 + .byte 1 * \stride + 1, 2 * \stride + 2 + .byte 1 * \stride + 0, 2 * \stride + 1 + .byte 1 * \stride + 0, 2 * \stride + 0 + .byte 1 * \stride + 0, 2 * \stride - 1 +// Repeated, to avoid & 7 + .byte -1 * \stride + 1, -2 * \stride + 2 + .byte 0 * \stride + 1, -1 * \stride + 2 + .byte 0 * \stride + 1, 0 * \stride + 2 + .byte 0 * \stride + 1, 1 * \stride + 2 + .byte 1 * \stride + 1, 2 * \stride + 2 + .byte 1 * \stride + 0, 2 * \stride + 1 +endconst +.endm + +.macro tables +dir_table 8, 16 +dir_table 4, 8 + +const pri_taps + .byte 4, 2, 3, 3 +endconst +.endm + +.macro load_px d11, d12, d21, d22, w +.if \w == 8 + add r6, r2, r9, lsl #1 // x + off + sub r9, r2, r9, lsl #1 // x - off + vld1.16 {\d11,\d12}, [r6] // p0 + vld1.16 {\d21,\d22}, [r9] // p1 +.else + add r6, r2, r9, lsl #1 // x + off + sub r9, r2, r9, lsl #1 // x - off + vld1.16 {\d11}, [r6] // p0 + add r6, r6, #2*8 // += stride + vld1.16 {\d21}, [r9] // p1 + add r9, r9, #2*8 // += stride + vld1.16 {\d12}, [r6] // p0 + vld1.16 {\d22}, [r9] // p1 +.endif +.endm +.macro handle_pixel s1, s2, thresh_vec, shift, tap, min +.if \min + vmin.u16 q2, q2, \s1 + vmax.s16 q3, q3, \s1 + vmin.u16 q2, q2, \s2 + vmax.s16 q3, q3, \s2 +.endif + vabd.u16 q8, q0, \s1 // abs(diff) + vabd.u16 q11, q0, \s2 // abs(diff) + vshl.u16 q9, q8, \shift // abs(diff) >> shift + vshl.u16 q12, q11, \shift // abs(diff) >> shift + vqsub.u16 q9, \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift)) + vqsub.u16 q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift)) + vsub.i16 q10, \s1, q0 // diff = p0 - px + vsub.i16 q13, \s2, q0 // diff = p1 - px + vneg.s16 q8, q9 // -clip + vneg.s16 q11, q12 // -clip + vmin.s16 q10, q10, q9 // imin(diff, clip) + vmin.s16 q13, q13, q12 // imin(diff, clip) + vdup.16 q9, \tap // taps[k] + vmax.s16 q10, q10, q8 // constrain() = imax(imin(diff, clip), -clip) + vmax.s16 q13, q13, q11 // constrain() = imax(imin(diff, clip), -clip) + vmla.i16 q1, q10, q9 // sum += taps[k] * constrain() + vmla.i16 q1, q13, q9 // sum += taps[k] * constrain() +.endm + +// void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride, +// const uint16_t *tmp, int pri_strength, +// int sec_strength, int dir, int damping, +// int h, size_t edges); +.macro filter_func w, bpc, pri, sec, min, suffix +function cdef_filter\w\suffix\()_\bpc\()bpc_neon +.if \bpc == 8 + cmp r8, #0xf + beq cdef_filter\w\suffix\()_edged_neon +.endif +.if \pri +.if \bpc == 16 + clz r9, r9 + sub r9, r9, #24 // -bitdepth_min_8 + neg r9, r9 // bitdepth_min_8 +.endif + movrel_local r8, pri_taps +.if \bpc == 16 + lsr r9, r3, r9 // pri_strength >> bitdepth_min_8 + and r9, r9, #1 // (pri_strength >> bitdepth_min_8) & 1 +.else + and r9, r3, #1 +.endif + add r8, r8, r9, lsl #1 +.endif + movrel_local r9, directions\w + add r5, r9, r5, lsl #1 + vmov.u16 d17, #15 + vdup.16 d16, r6 // damping + +.if \pri + vdup.16 q5, r3 // threshold +.endif +.if \sec + vdup.16 q7, r4 // threshold +.endif + vmov.16 d8[0], r3 + vmov.16 d8[1], r4 + vclz.i16 d8, d8 // clz(threshold) + vsub.i16 d8, d17, d8 // ulog2(threshold) + vqsub.u16 d8, d16, d8 // shift = imax(0, damping - ulog2(threshold)) + vneg.s16 d8, d8 // -shift +.if \sec + vdup.16 q6, d8[1] +.endif +.if \pri + vdup.16 q4, d8[0] +.endif + +1: +.if \w == 8 + vld1.16 {q0}, [r2, :128] // px +.else + add r12, r2, #2*8 + vld1.16 {d0}, [r2, :64] // px + vld1.16 {d1}, [r12, :64] // px +.endif + + vmov.u16 q1, #0 // sum +.if \min + vmov.u16 q2, q0 // min + vmov.u16 q3, q0 // max +.endif + + // Instead of loading sec_taps 2, 1 from memory, just set it + // to 2 initially and decrease for the second round. + // This is also used as loop counter. + mov lr, #2 // sec_taps[0] + +2: +.if \pri + ldrsb r9, [r5] // off1 + + load_px d28, d29, d30, d31, \w +.endif + +.if \sec + add r5, r5, #4 // +2*2 + ldrsb r9, [r5] // off2 +.endif + +.if \pri + ldrb r12, [r8] // *pri_taps + + handle_pixel q14, q15, q5, q4, r12, \min +.endif + +.if \sec + load_px d28, d29, d30, d31, \w + + add r5, r5, #8 // +2*4 + ldrsb r9, [r5] // off3 + + handle_pixel q14, q15, q7, q6, lr, \min + + load_px d28, d29, d30, d31, \w + + handle_pixel q14, q15, q7, q6, lr, \min + + sub r5, r5, #11 // r5 -= 2*(2+4); r5 += 1; +.else + add r5, r5, #1 // r5 += 1 +.endif + subs lr, lr, #1 // sec_tap-- (value) +.if \pri + add r8, r8, #1 // pri_taps++ (pointer) +.endif + bne 2b + + vshr.s16 q14, q1, #15 // -(sum < 0) + vadd.i16 q1, q1, q14 // sum - (sum < 0) + vrshr.s16 q1, q1, #4 // (8 + sum - (sum < 0)) >> 4 + vadd.i16 q0, q0, q1 // px + (8 + sum ...) >> 4 +.if \min + vmin.s16 q0, q0, q3 + vmax.s16 q0, q0, q2 // iclip(px + .., min, max) +.endif +.if \bpc == 8 + vmovn.u16 d0, q0 +.endif +.if \w == 8 + add r2, r2, #2*16 // tmp += tmp_stride + subs r7, r7, #1 // h-- +.if \bpc == 8 + vst1.8 {d0}, [r0, :64], r1 +.else + vst1.16 {q0}, [r0, :128], r1 +.endif +.else +.if \bpc == 8 + vst1.32 {d0[0]}, [r0, :32], r1 +.else + vst1.16 {d0}, [r0, :64], r1 +.endif + add r2, r2, #2*16 // tmp += 2*tmp_stride + subs r7, r7, #2 // h -= 2 +.if \bpc == 8 + vst1.32 {d0[1]}, [r0, :32], r1 +.else + vst1.16 {d1}, [r0, :64], r1 +.endif +.endif + + // Reset pri_taps and directions back to the original point + sub r5, r5, #2 +.if \pri + sub r8, r8, #2 +.endif + + bgt 1b + vpop {q4-q7} + pop {r4-r9,pc} +endfunc +.endm + +.macro filter w, bpc +filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri +filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec +filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec + +function cdef_filter\w\()_\bpc\()bpc_neon, export=1 + push {r4-r9,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #92] + ldrd r6, r7, [sp, #100] +.if \bpc == 16 + ldrd r8, r9, [sp, #108] +.else + ldr r8, [sp, #108] +.endif + cmp r3, #0 // pri_strength + bne 1f + b cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec +1: + cmp r4, #0 // sec_strength + bne 1f + b cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri +1: + b cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec +endfunc +.endm + +const div_table, align=4 + .short 840, 420, 280, 210, 168, 140, 120, 105 +endconst + +const alt_fact, align=4 + .short 420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0 +endconst + +.macro cost_alt dest, s1, s2, s3, s4, s5, s6 + vmull.s16 q1, \s1, \s1 // sum_alt[n]*sum_alt[n] + vmull.s16 q2, \s2, \s2 + vmull.s16 q3, \s3, \s3 + vmull.s16 q5, \s4, \s4 // sum_alt[n]*sum_alt[n] + vmull.s16 q12, \s5, \s5 + vmull.s16 q6, \s6, \s6 // q6 overlaps the first \s1-\s2 here + vmul.i32 q1, q1, q13 // sum_alt[n]^2*fact + vmla.i32 q1, q2, q14 + vmla.i32 q1, q3, q15 + vmul.i32 q5, q5, q13 // sum_alt[n]^2*fact + vmla.i32 q5, q12, q14 + vmla.i32 q5, q6, q15 + vadd.i32 d2, d2, d3 + vadd.i32 d3, d10, d11 + vpadd.i32 \dest, d2, d3 // *cost_ptr +.endm + +.macro find_best s1, s2, s3 +.ifnb \s2 + vmov.32 lr, \s2 +.endif + cmp r12, r1 // cost[n] > best_cost + itt gt + movgt r0, r3 // best_dir = n + movgt r1, r12 // best_cost = cost[n] +.ifnb \s2 + add r3, r3, #1 // n++ + cmp lr, r1 // cost[n] > best_cost + vmov.32 r12, \s3 + itt gt + movgt r0, r3 // best_dir = n + movgt r1, lr // best_cost = cost[n] + add r3, r3, #1 // n++ +.endif +.endm + +// int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride, +// unsigned *const var) +.macro find_dir bpc +function cdef_find_dir_\bpc\()bpc_neon, export=1 + push {lr} + vpush {q4-q7} +.if \bpc == 16 + clz r3, r3 // clz(bitdepth_max) + sub lr, r3, #24 // -bitdepth_min_8 +.endif + sub sp, sp, #32 // cost + mov r3, #8 + vmov.u16 q1, #0 // q0-q1 sum_diag[0] + vmov.u16 q3, #0 // q2-q3 sum_diag[1] + vmov.u16 q5, #0 // q4-q5 sum_hv[0-1] + vmov.u16 q8, #0 // q6,d16 sum_alt[0] + // q7,d17 sum_alt[1] + vmov.u16 q9, #0 // q9,d22 sum_alt[2] + vmov.u16 q11, #0 + vmov.u16 q10, #0 // q10,d23 sum_alt[3] + + +.irpc i, 01234567 +.if \bpc == 8 + vld1.8 {d30}, [r0, :64], r1 + vmov.u8 d31, #128 + vsubl.u8 q15, d30, d31 // img[x] - 128 +.else + vld1.16 {q15}, [r0, :128], r1 + vdup.16 q14, lr // -bitdepth_min_8 + vshl.u16 q15, q15, q14 + vmov.u16 q14, #128 + vsub.i16 q15, q15, q14 // img[x] - 128 +.endif + vmov.u16 q14, #0 + +.if \i == 0 + vmov q0, q15 // sum_diag[0] +.else + vext.8 q12, q14, q15, #(16-2*\i) + vext.8 q13, q15, q14, #(16-2*\i) + vadd.i16 q0, q0, q12 // sum_diag[0] + vadd.i16 q1, q1, q13 // sum_diag[0] +.endif + vrev64.16 q13, q15 + vswp d26, d27 // [-x] +.if \i == 0 + vmov q2, q13 // sum_diag[1] +.else + vext.8 q12, q14, q13, #(16-2*\i) + vext.8 q13, q13, q14, #(16-2*\i) + vadd.i16 q2, q2, q12 // sum_diag[1] + vadd.i16 q3, q3, q13 // sum_diag[1] +.endif + + vpadd.u16 d26, d30, d31 // [(x >> 1)] + vmov.u16 d27, #0 + vpadd.u16 d24, d26, d28 + vpadd.u16 d24, d24, d28 // [y] + vmov.u16 r12, d24[0] + vadd.i16 q5, q5, q15 // sum_hv[1] +.if \i < 4 + vmov.16 d8[\i], r12 // sum_hv[0] +.else + vmov.16 d9[\i-4], r12 // sum_hv[0] +.endif + +.if \i == 0 + vmov.u16 q6, q13 // sum_alt[0] +.else + vext.8 q12, q14, q13, #(16-2*\i) + vext.8 q14, q13, q14, #(16-2*\i) + vadd.i16 q6, q6, q12 // sum_alt[0] + vadd.i16 d16, d16, d28 // sum_alt[0] +.endif + vrev64.16 d26, d26 // [-(x >> 1)] + vmov.u16 q14, #0 +.if \i == 0 + vmov q7, q13 // sum_alt[1] +.else + vext.8 q12, q14, q13, #(16-2*\i) + vext.8 q13, q13, q14, #(16-2*\i) + vadd.i16 q7, q7, q12 // sum_alt[1] + vadd.i16 d17, d17, d26 // sum_alt[1] +.endif + +.if \i < 6 + vext.8 q12, q14, q15, #(16-2*(3-(\i/2))) + vext.8 q13, q15, q14, #(16-2*(3-(\i/2))) + vadd.i16 q9, q9, q12 // sum_alt[2] + vadd.i16 d22, d22, d26 // sum_alt[2] +.else + vadd.i16 q9, q9, q15 // sum_alt[2] +.endif +.if \i == 0 + vmov q10, q15 // sum_alt[3] +.elseif \i == 1 + vadd.i16 q10, q10, q15 // sum_alt[3] +.else + vext.8 q12, q14, q15, #(16-2*(\i/2)) + vext.8 q13, q15, q14, #(16-2*(\i/2)) + vadd.i16 q10, q10, q12 // sum_alt[3] + vadd.i16 d23, d23, d26 // sum_alt[3] +.endif +.endr + + vmov.u32 q15, #105 + + vmull.s16 q12, d8, d8 // sum_hv[0]*sum_hv[0] + vmlal.s16 q12, d9, d9 + vmull.s16 q13, d10, d10 // sum_hv[1]*sum_hv[1] + vmlal.s16 q13, d11, d11 + vadd.s32 d8, d24, d25 + vadd.s32 d9, d26, d27 + vpadd.s32 d8, d8, d9 // cost[2,6] (s16, s17) + vmul.i32 d8, d8, d30 // cost[2,6] *= 105 + + vrev64.16 q1, q1 + vrev64.16 q3, q3 + vext.8 q1, q1, q1, #10 // sum_diag[0][14-n] + vext.8 q3, q3, q3, #10 // sum_diag[1][14-n] + + vstr s16, [sp, #2*4] // cost[2] + vstr s17, [sp, #6*4] // cost[6] + + movrel_local r12, div_table + vld1.16 {q14}, [r12, :128] + + vmull.s16 q5, d0, d0 // sum_diag[0]*sum_diag[0] + vmull.s16 q12, d1, d1 + vmlal.s16 q5, d2, d2 + vmlal.s16 q12, d3, d3 + vmull.s16 q0, d4, d4 // sum_diag[1]*sum_diag[1] + vmull.s16 q1, d5, d5 + vmlal.s16 q0, d6, d6 + vmlal.s16 q1, d7, d7 + vmovl.u16 q13, d28 // div_table + vmovl.u16 q14, d29 + vmul.i32 q5, q5, q13 // cost[0] + vmla.i32 q5, q12, q14 + vmul.i32 q0, q0, q13 // cost[4] + vmla.i32 q0, q1, q14 + vadd.i32 d10, d10, d11 + vadd.i32 d0, d0, d1 + vpadd.i32 d0, d10, d0 // cost[0,4] = s0,s1 + + movrel_local r12, alt_fact + vld1.16 {d29, d30, d31}, [r12, :64] // div_table[2*m+1] + 105 + + vstr s0, [sp, #0*4] // cost[0] + vstr s1, [sp, #4*4] // cost[4] + + vmovl.u16 q13, d29 // div_table[2*m+1] + 105 + vmovl.u16 q14, d30 + vmovl.u16 q15, d31 + + cost_alt d14, d12, d13, d16, d14, d15, d17 // cost[1], cost[3] + cost_alt d15, d18, d19, d22, d20, d21, d23 // cost[5], cost[7] + vstr s28, [sp, #1*4] // cost[1] + vstr s29, [sp, #3*4] // cost[3] + + mov r0, #0 // best_dir + vmov.32 r1, d0[0] // best_cost + mov r3, #1 // n + + vstr s30, [sp, #5*4] // cost[5] + vstr s31, [sp, #7*4] // cost[7] + + vmov.32 r12, d14[0] + + find_best d14[0], d8[0], d14[1] + find_best d14[1], d0[1], d15[0] + find_best d15[0], d8[1], d15[1] + find_best d15[1] + + eor r3, r0, #4 // best_dir ^4 + ldr r12, [sp, r3, lsl #2] + sub r1, r1, r12 // best_cost - cost[best_dir ^ 4] + lsr r1, r1, #10 + str r1, [r2] // *var + + add sp, sp, #32 + vpop {q4-q7} + pop {pc} +endfunc +.endm diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2937 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * Copyright © 2019, B Krishnan Iyer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_128_8bpc_neon, export=1 + push {r4, lr} + ldr r4, [sp, #8] + clz r3, r3 + adr r2, L(ipred_dc_128_tbl) + sub r3, r3, #25 + ldr r3, [r2, r3, lsl #2] + vmov.i8 q0, #128 + add r2, r2, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r2 + + .align 2 +L(ipred_dc_128_tbl): + .word 640f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 320f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 16f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 8f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 4f - L(ipred_dc_128_tbl) + CONFIG_THUMB +4: + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + subs r4, r4, #4 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt 4b + pop {r4, pc} +8: + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt 8b + pop {r4, pc} +16: + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + bgt 16b + pop {r4, pc} +320: + vmov.i8 q1, #128 +32: + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 32b + pop {r4, pc} +640: + vmov.i8 q1, #128 + sub r1, r1, #32 +64: + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 64b + pop {r4, pc} +endfunc + +// void ipred_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_8bpc_neon, export=1 + push {r4, lr} + ldr lr, [sp, #8] + clz r3, r3 + adr r4, L(ipred_v_tbl) + sub r3, r3, #25 + ldr r3, [r4, r3, lsl #2] + add r2, r2, #1 + add r4, r4, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r4 + + .align 2 +L(ipred_v_tbl): + .word 640f - L(ipred_v_tbl) + CONFIG_THUMB + .word 320f - L(ipred_v_tbl) + CONFIG_THUMB + .word 160f - L(ipred_v_tbl) + CONFIG_THUMB + .word 80f - L(ipred_v_tbl) + CONFIG_THUMB + .word 40f - L(ipred_v_tbl) + CONFIG_THUMB +40: + vld1.32 {d0[]}, [r2] +4: + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + subs lr, lr, #4 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt 4b + pop {r4, pc} +80: + vld1.8 {d0}, [r2] +8: + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + subs lr, lr, #4 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt 8b + pop {r4, pc} +160: + vld1.8 {q0}, [r2] +16: + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + subs lr, lr, #4 + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + bgt 16b + pop {r4, pc} +320: + vld1.8 {q0, q1}, [r2] +32: + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs lr, lr, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 32b + pop {r4, pc} +640: + vld1.8 {q0, q1}, [r2]! + sub r1, r1, #32 + vld1.8 {q2, q3}, [r2] +64: + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d4, d5, d6, d7}, [r0, :128], r1 + vst1.8 {d4, d5, d6, d7}, [r12, :128], r1 + subs lr, lr, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d4, d5, d6, d7}, [r0, :128], r1 + vst1.8 {d4, d5, d6, d7}, [r12, :128], r1 + bgt 64b + pop {r4, pc} +endfunc + +// void ipred_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_8bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + clz r3, r3 + adr r5, L(ipred_h_tbl) + sub r3, r3, #25 + ldr r3, [r5, r3, lsl #2] + sub r2, r2, #4 + mov lr, #-4 + add r5, r5, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_h_tbl): + .word 640f - L(ipred_h_tbl) + CONFIG_THUMB + .word 320f - L(ipred_h_tbl) + CONFIG_THUMB + .word 160f - L(ipred_h_tbl) + CONFIG_THUMB + .word 8f - L(ipred_h_tbl) + CONFIG_THUMB + .word 4f - L(ipred_h_tbl) + CONFIG_THUMB +4: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], lr + vst1.32 {d3[0]}, [r0, :32], r1 + vst1.32 {d2[0]}, [r12, :32], r1 + subs r4, r4, #4 + vst1.32 {d1[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt 4b + pop {r4-r5, pc} +8: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], lr + vst1.8 {d3}, [r0, :64], r1 + vst1.8 {d2}, [r12, :64], r1 + subs r4, r4, #4 + vst1.8 {d1}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt 8b + pop {r4-r5, pc} +160: + add r2, r2, #3 + mov lr, #-1 +16: + vld1.8 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.8 {d2[], d3[]}, [r2], lr + vst1.8 {q0}, [r0, :128], r1 + vld1.8 {d4[], d5[]}, [r2], lr + vst1.8 {q1}, [r12, :128], r1 + vld1.8 {d6[], d7[]}, [r2], lr + vst1.8 {q2}, [r0, :128], r1 + vst1.8 {q3}, [r12, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + add r2, r2, #3 + mov lr, #-1 + sub r1, r1, #16 +32: + vld1.8 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.8 {d2[], d3[]}, [r2], lr + vst1.8 {q0}, [r0, :128]! + vld1.8 {d4[], d5[]}, [r2], lr + vst1.8 {q1}, [r12, :128]! + vld1.8 {d6[], d7[]}, [r2], lr + vst1.8 {q0}, [r0, :128], r1 + vst1.8 {q1}, [r12, :128], r1 + vst1.8 {q2}, [r0, :128]! + vst1.8 {q3}, [r12, :128]! + vst1.8 {q2}, [r0, :128], r1 + vst1.8 {q3}, [r12, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + add r2, r2, #3 + mov lr, #-1 + sub r1, r1, #48 +64: + vld1.8 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.8 {d2[], d3[]}, [r2], lr + vst1.8 {q0}, [r0, :128]! + vld1.8 {d4[], d5[]}, [r2], lr + vst1.8 {q1}, [r12, :128]! + vld1.8 {d6[], d7[]}, [r2], lr + vst1.8 {q0}, [r0, :128]! + vst1.8 {q1}, [r12, :128]! + vst1.8 {q0}, [r0, :128]! + vst1.8 {q1}, [r12, :128]! + vst1.8 {q0}, [r0, :128], r1 + vst1.8 {q1}, [r12, :128], r1 + vst1.8 {q2}, [r0, :128]! + vst1.8 {q3}, [r12, :128]! + vst1.8 {q2}, [r0, :128]! + vst1.8 {q3}, [r12, :128]! + vst1.8 {q2}, [r0, :128]! + vst1.8 {q3}, [r12, :128]! + vst1.8 {q2}, [r0, :128], r1 + vst1.8 {q3}, [r12, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_8bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + clz r3, r3 + adr r5, L(ipred_dc_top_tbl) + sub r3, r3, #25 + ldr r3, [r5, r3, lsl #2] + add r2, r2, #1 + add r5, r5, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_top_tbl): + .word 640f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 320f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 160f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 80f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 40f - L(ipred_dc_top_tbl) + CONFIG_THUMB +40: + vld1.32 {d0[]}, [r2] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #2 + vdup.8 d0, d0[0] +4: + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + subs r4, r4, #4 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt 4b + pop {r4-r5, pc} +80: + vld1.8 {d0}, [r2] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #3 + vdup.8 d0, d0[0] +8: + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt 8b + pop {r4-r5, pc} +160: + vld1.8 {d0, d1}, [r2] + vaddl.u8 q0, d0, d1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #4 + vdup.8 q0, d0[0] +16: + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + vld1.8 {d0, d1, d2, d3}, [r2] + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d4, q0, #5 + vdup.8 q0, d4[0] + vdup.8 q1, d4[0] +32: + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + vld1.8 {d0, d1, d2, d3}, [r2]! + vaddl.u8 q0, d0, d1 + vld1.8 {d4, d5, d6, d7}, [r2] + vaddl.u8 q1, d2, d3 + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.u16 q0, q0, q1 + vadd.u16 q1, q2, q3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d18, q0, #6 + vdup.8 q0, d18[0] + vdup.8 q1, d18[0] + sub r1, r1, #32 +64: + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_8bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + sub r2, r2, r4 + clz r3, r3 + clz lr, r4 + sub lr, lr, #25 + adr r5, L(ipred_dc_left_tbl) + sub r3, r3, #20 + ldr r3, [r5, r3, lsl #2] + ldr lr, [r5, lr, lsl #2] + add r3, r5, r3 + add r5, r5, lr + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_left_tbl): + .word L(ipred_dc_left_h64) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h32) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h16) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h8) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h4) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w64) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w32) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w16) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w8) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w4) - L(ipred_dc_left_tbl) + CONFIG_THUMB + +L(ipred_dc_left_h4): + vld1.32 {d0[]}, [r2, :32] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #2 + vdup.8 q0, d0[0] + bx r3 +L(ipred_dc_left_w4): + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + subs r4, r4, #4 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt L(ipred_dc_left_w4) + pop {r4-r5, pc} +L(ipred_dc_left_h8): + vld1.8 {d0}, [r2, :64] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #3 + vdup.8 q0, d0[0] + bx r3 +L(ipred_dc_left_w8): + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt L(ipred_dc_left_w8) + pop {r4-r5, pc} +L(ipred_dc_left_h16): + vld1.8 {d0, d1}, [r2, :128] + vaddl.u8 q0, d0, d1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #4 + vdup.8 q0, d0[0] + bx r3 +L(ipred_dc_left_w16): + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + bgt L(ipred_dc_left_w16) + pop {r4-r5, pc} +L(ipred_dc_left_h32): + vld1.8 {d0, d1, d2, d3}, [r2, :128] + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #5 + vdup.8 q0, d0[0] + bx r3 +L(ipred_dc_left_w32): + vmov.8 q1, q0 +1: + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 1b + pop {r4-r5, pc} +L(ipred_dc_left_h64): + vld1.8 {d0, d1, d2, d3}, [r2, :128]! + vld1.8 {d4, d5, d6, d7}, [r2, :128] + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.u16 q0, q0, q1 + vadd.u16 q1, q2, q3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshrn.u16 d0, q0, #6 + vdup.8 q0, d0[0] + bx r3 +L(ipred_dc_left_w64): + vmov.8 q1, q0 + sub r1, r1, #32 +1: + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 1b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_8bpc_neon, export=1 + push {r4-r6, lr} + ldr r4, [sp, #16] + sub r2, r2, r4 + add lr, r3, r4 // width + height + clz r3, r3 + clz r12, r4 + vdup.16 q15, lr // width + height + adr r5, L(ipred_dc_tbl) + rbit lr, lr // rbit(width + height) + sub r3, r3, #20 // 25 leading bits, minus table offset 5 + sub r12, r12, #25 + clz lr, lr // ctz(width + height) + ldr r3, [r5, r3, lsl #2] + ldr r12, [r5, r12, lsl #2] + neg lr, lr // -ctz(width + height) + add r3, r5, r3 + add r5, r5, r12 + vshr.u16 q15, q15, #1 // (width + height) >> 1 + vdup.16 q14, lr // -ctz(width + height) + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_tbl): + .word L(ipred_dc_h64) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h32) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h16) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h8) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h4) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w64) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w32) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w16) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w8) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w4) - L(ipred_dc_tbl) + CONFIG_THUMB + +L(ipred_dc_h4): + vld1.32 {d0[]}, [r2, :32]! + vpaddl.u8 d0, d0 + add r2, r2, #1 + vpadd.u16 d0, d0 + bx r3 +L(ipred_dc_w4): + vld1.32 {d1[]}, [r2] + vadd.s16 d0, d0, d30 + vpaddl.u8 d1, d1 + vpadd.u16 d1, d1 + cmp r4, #4 + vadd.s16 d0, d0, d1 + vshl.u16 d0, d0, d28 + beq 1f + // h = 8/16 + movw lr, #(0x3334/2) + movw r5, #(0x5556/2) + cmp r4, #16 + it ne + movne lr, r5 + vdup.16 d30, lr + vqdmulh.s16 d0, d0, d30 +1: + vdup.8 d0, d0[0] +2: + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + subs r4, r4, #4 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[0]}, [r12, :32], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h8): + vld1.8 {d0}, [r2, :64]! + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + add r2, r2, #1 + vpadd.u16 d0, d0 + bx r3 +L(ipred_dc_w8): + vld1.8 {d2}, [r2] + vadd.s16 d0, d0, d30 + vpaddl.u8 d2, d2 + vpadd.u16 d2, d2 + vpadd.u16 d2, d2 + cmp r4, #8 + vadd.s16 d0, d0, d2 + vshl.u16 d0, d0, d28 + beq 1f + // h = 4/16/32 + cmp r4, #32 + movw lr, #(0x3334/2) + movw r5, #(0x5556/2) + it ne + movne lr, r5 + vdup.16 d24, lr + vqdmulh.s16 d0, d0, d24 +1: + vdup.8 d0, d0[0] +2: + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d0}, [r12, :64], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h16): + vld1.8 {d0, d1}, [r2, :128]! + vaddl.u8 q0, d0, d1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + add r2, r2, #1 + vpadd.u16 d0, d0 + bx r3 +L(ipred_dc_w16): + vld1.8 {d2, d3}, [r2] + vadd.s16 d0, d0, d30 + vaddl.u8 q1, d2, d3 + vadd.u16 d2, d2, d3 + vpadd.u16 d2, d2 + vpadd.u16 d2, d2 + cmp r4, #16 + vadd.s16 d0, d0, d2 + vshl.u16 d0, d0, d28 + beq 1f + // h = 4/8/32/64 + tst r4, #(32+16+8) // 16 added to make a consecutive bitmask + movw lr, #(0x3334/2) + movw r5, #(0x5556/2) + it ne + movne lr, r5 + vdup.16 d24, lr + vqdmulh.s16 d0, d0, d24 +1: + vdup.8 q0, d0[0] +2: + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1}, [r0, :128], r1 + vst1.8 {d0, d1}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h32): + vld1.8 {d0, d1, d2, d3}, [r2, :128]! + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + add r2, r2, #1 + vpadd.u16 d0, d0 + bx r3 +L(ipred_dc_w32): + vld1.8 {d2, d3, d4, d5}, [r2] + vadd.s16 d0, d0, d30 + vaddl.u8 q1, d2, d3 + vaddl.u8 q2, d4, d5 + vadd.u16 q1, q1, q2 + vadd.u16 d2, d2, d3 + vpadd.u16 d2, d2 + vpadd.u16 d2, d2 + cmp r4, #32 + vadd.s16 d0, d0, d2 + vshl.u16 d4, d0, d28 + beq 1f + // h = 8/16/64 + cmp r4, #8 + movw lr, #(0x3334/2) + movw r5, #(0x5556/2) + it ne + movne lr, r5 + vdup.16 d24, lr + vqdmulh.s16 d4, d4, d24 +1: + vdup.8 q0, d4[0] + vdup.8 q1, d4[0] +2: + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h64): + vld1.8 {d0, d1, d2, d3}, [r2, :128]! + vaddl.u8 q0, d0, d1 + vld1.8 {d4, d5, d6, d7}, [r2, :128]! + vaddl.u8 q1, d2, d3 + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.u16 q0, q0, q1 + vadd.u16 q1, q2, q3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + add r2, r2, #1 + vpadd.u16 d0, d0 + bx r3 +L(ipred_dc_w64): + vld1.8 {d2, d3, d4, d5}, [r2]! + vadd.s16 d0, d0, d30 + vaddl.u8 q2, d4, d5 + vaddl.u8 q1, d2, d3 + vadd.u16 d4, d4, d5 + vadd.u16 d2, d2, d3 + vld1.8 {d16, d17, d18, d19}, [r2] + vpadd.u16 d4, d4 + vpadd.u16 d2, d2 + vpadd.u16 d4, d4 + vpadd.u16 d2, d2 + vaddl.u8 q8, d16, d17 + vaddl.u8 q9, d18, d19 + vadd.u16 d16, d16, d17 + vadd.u16 d18, d18, d19 + vpadd.u16 d16, d16 + vpadd.u16 d18, d18 + vpadd.u16 d16, d16 + vpadd.u16 d18, d18 + vadd.u16 d2, d2, d4 + vadd.u16 d3, d16, d18 + cmp r4, #64 + vadd.s16 d0, d0, d2 + vadd.s16 d0, d0, d3 + vshl.u16 d18, d0, d28 + beq 1f + // h = 16/32 + movw lr, #(0x5556/2) + movt lr, #(0x3334/2) + and r5, r4, #31 + lsr lr, lr, r5 + vdup.16 d30, lr + vqdmulh.s16 d18, d18, d30 +1: + sub r1, r1, #32 + vdup.8 q0, d18[0] + vdup.8 q1, d18[0] +2: + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.8 {d0, d1, d2, d3}, [r0, :128]! + vst1.8 {d0, d1, d2, d3}, [r12, :128]! + vst1.8 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.8 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} +endfunc + +// void ipred_paeth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_8bpc_neon, export=1 + push {r4-r8, lr} + ldr r4, [sp, #24] + clz lr, r3 + adr r5, L(ipred_paeth_tbl) + sub lr, lr, #25 + ldr lr, [r5, lr, lsl #2] + vld1.8 {d4[], d5[]}, [r2] + add r8, r2, #1 + sub r2, r2, #4 + add r5, r5, lr + mov r7, #-4 + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_paeth_tbl): + .word 640f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 320f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 160f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 80f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 40f - L(ipred_paeth_tbl) + CONFIG_THUMB + +40: + vld1.32 {d6[], d7[]}, [r8] + vsubl.u8 q8, d6, d4 // top - topleft +4: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], r7 + vzip.32 d0, d1 + vzip.32 d2, d3 + vaddw.u8 q9, q8, d0 + vaddw.u8 q10, q8, d2 + vqmovun.s16 d18, q9 // base + vqmovun.s16 d19, q10 + vmov d1, d2 + vabd.u8 q10, q3, q9 // tdiff + vabd.u8 q11, q2, q9 // tldiff + vabd.u8 q9, q0, q9 // ldiff + vmin.u8 q12, q10, q11 // min(tdiff, tldiff) + vcge.u8 q10, q11, q10 // tldiff >= tdiff + vcge.u8 q9, q12, q9 // min(tdiff, tldiff) >= ldiff + vbsl q10, q3, q2 // tdiff <= tldiff ? top : topleft + vbit q10, q0, q9 // ldiff <= min ? left : ... + vst1.32 {d21[1]}, [r0, :32], r1 + vst1.32 {d21[0]}, [r6, :32], r1 + subs r4, r4, #4 + vst1.32 {d20[1]}, [r0, :32], r1 + vst1.32 {d20[0]}, [r6, :32], r1 + bgt 4b + pop {r4-r8, pc} +80: + vld1.8 {d6}, [r8] + vsubl.u8 q8, d6, d4 // top - topleft + vmov d7, d6 +8: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], r7 + vaddw.u8 q9, q8, d0 + vaddw.u8 q10, q8, d1 + vaddw.u8 q11, q8, d2 + vaddw.u8 q12, q8, d3 + vqmovun.s16 d18, q9 // base + vqmovun.s16 d19, q10 + vqmovun.s16 d20, q11 + vqmovun.s16 d21, q12 + vabd.u8 q11, q3, q9 // tdiff + vabd.u8 q12, q3, q10 + vabd.u8 q13, q2, q9 // tldiff + vabd.u8 q14, q2, q10 + vabd.u8 q10, q1, q10 // ldiff + vabd.u8 q9, q0, q9 + vmin.u8 q15, q12, q14 // min(tdiff, tldiff) + vcge.u8 q12, q14, q12 // tldiff >= tdiff + vmin.u8 q14, q11, q13 // min(tdiff, tldiff) + vcge.u8 q11, q13, q11 // tldiff >= tdiff + vcge.u8 q10, q15, q10 // min(tdiff, tldiff) >= ldiff + vcge.u8 q9, q14, q9 + vbsl q12, q3, q2 // tdiff <= tldiff ? top : topleft + vbsl q11, q3, q2 + vbit q12, q1, q10 // ldiff <= min ? left : ... + vbit q11, q0, q9 + vst1.8 {d25}, [r0, :64], r1 + vst1.8 {d24}, [r6, :64], r1 + subs r4, r4, #4 + vst1.8 {d23}, [r0, :64], r1 + vst1.8 {d22}, [r6, :64], r1 + bgt 8b + pop {r4-r8, pc} +160: +320: +640: + vld1.8 {d6}, [r8]! + mov r12, r3 + // Set up pointers for four rows in parallel; r0, r6, r5, lr + add r5, r0, r1 + add lr, r6, r1 + lsl r1, r1, #1 + sub r1, r1, r3 +1: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], r7 +2: + vsubl.u8 q8, d6, d4 // top - topleft + vmov d7, d6 + vaddw.u8 q9, q8, d0 + vaddw.u8 q10, q8, d1 + vaddw.u8 q11, q8, d2 + vaddw.u8 q12, q8, d3 + vqmovun.s16 d18, q9 // base + vqmovun.s16 d19, q10 + vqmovun.s16 d20, q11 + vqmovun.s16 d21, q12 + vabd.u8 q11, q3, q9 // tdiff + vabd.u8 q12, q3, q10 + vabd.u8 q13, q2, q9 // tldiff + vabd.u8 q14, q2, q10 + vabd.u8 q10, q1, q10 // ldiff + vabd.u8 q9, q0, q9 + vmin.u8 q15, q12, q14 // min(tdiff, tldiff) + vcge.u8 q12, q14, q12 // tldiff >= tdiff + vmin.u8 q14, q11, q13 // min(tdiff, tldiff) + vcge.u8 q11, q13, q11 // tldiff >= tdiff + vcge.u8 q10, q15, q10 // min(tdiff, tldiff) >= ldiff + vcge.u8 q9, q14, q9 + vbsl q12, q3, q2 // tdiff <= tldiff ? top : topleft + vbsl q11, q3, q2 + vbit q12, q1, q10 // ldiff <= min ? left : ... + vbit q11, q0, q9 + subs r3, r3, #8 + vst1.8 {d25}, [r0, :64]! + vst1.8 {d24}, [r6, :64]! + vst1.8 {d23}, [r5, :64]! + vst1.8 {d22}, [lr, :64]! + ble 8f + vld1.8 {d6}, [r8]! + b 2b +8: + subs r4, r4, #4 + ble 9f + // End of horizontal loop, move pointers to next four rows + sub r8, r8, r12 + add r0, r0, r1 + add r6, r6, r1 + vld1.8 {d6}, [r8]! + add r5, r5, r1 + add lr, lr, r1 + mov r3, r12 + b 1b +9: + pop {r4-r8, pc} +endfunc + +// void ipred_smooth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_8bpc_neon, export=1 + push {r4-r10, lr} + ldr r4, [sp, #32] + movrel r10, X(sm_weights) + add r12, r10, r4 + add r10, r10, r3 + clz r9, r3 + adr r5, L(ipred_smooth_tbl) + sub lr, r2, r4 + sub r9, r9, #25 + ldr r9, [r5, r9, lsl #2] + vld1.8 {d4[]}, [lr] // bottom + add r8, r2, #1 + add r5, r5, r9 + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_tbl): + .word 640f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_tbl) + CONFIG_THUMB + +40: + vld1.32 {d16[]}, [r8] // top + vld1.32 {d18[]}, [r10, :32] // weights_hor + sub r2, r2, #4 + mov r7, #-4 + vdup.8 q3, d16[3] // right + vsubl.u8 q8, d16, d4 // top-bottom + vmovl.u8 q9, d18 // weights_hor +4: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], r7 // left + vld4.8 {d20[], d21[], d22[], d23[]}, [r12, :32]! // weights_ver + vshll.i8 q12, d6, #8 // right*256 + vshll.i8 q13, d6, #8 + vzip.32 d1, d0 // left, flipped + vzip.32 d3, d2 + vzip.32 d20, d21 // weights_ver + vzip.32 d22, d23 + vshll.i8 q14, d4, #8 // bottom*256 + vshll.i8 q15, d4, #8 + vsubl.u8 q0, d1, d6 // left-right + vsubl.u8 q1, d3, d6 + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 + vmla.i16 q12, q1, q9 // right*256 + (left-right)*weights_hor + vmla.i16 q13, q0, q9 // (left flipped) + vmla.i16 q14, q8, q10 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q15, q8, q11 + vhadd.u16 q12, q12, q14 + vhadd.u16 q13, q13, q15 + vrshrn.i16 d24, q12, #8 + vrshrn.i16 d25, q13, #8 + vst1.32 {d24[0]}, [r0, :32], r1 + vst1.32 {d24[1]}, [r6, :32], r1 + subs r4, r4, #4 + vst1.32 {d25[0]}, [r0, :32], r1 + vst1.32 {d25[1]}, [r6, :32], r1 + bgt 4b + pop {r4-r10, pc} +80: + vld1.8 {d16}, [r8] // top + vld1.8 {d18}, [r10, :64] // weights_hor + sub r2, r2, #2 + mov r7, #-2 + vdup.8 q3, d16[7] // right + vsubl.u8 q8, d16, d4 // top-bottom + vmovl.u8 q9, d18 // weights_hor +8: + vld2.8 {d0[], d1[]}, [r2, :16], r7 // left + vld2.8 {d20[], d22[]}, [r12, :16]! // weights_ver + vshll.i8 q12, d6, #8 // right*256 + vshll.i8 q13, d6, #8 + vshll.i8 q14, d4, #8 // bottom*256 + vshll.i8 q15, d4, #8 + vsubl.u8 q1, d0, d6 // left-right (left flipped) + vsubl.u8 q0, d1, d6 + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 + vmla.i16 q12, q0, q9 // right*256 + (left-right)*weights_hor + vmla.i16 q13, q1, q9 + vmla.i16 q14, q8, q10 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q15, q8, q11 + vhadd.u16 q12, q12, q14 + vhadd.u16 q13, q13, q15 + vrshrn.i16 d24, q12, #8 + vrshrn.i16 d25, q13, #8 + subs r4, r4, #2 + vst1.8 {d24}, [r0, :64], r1 + vst1.8 {d25}, [r6, :64], r1 + bgt 8b + pop {r4-r10, pc} +160: +320: +640: + add lr, r2, r3 + sub r2, r2, #2 + mov r7, #-2 + vld1.8 {d6[], d7[]}, [lr] // right + sub r1, r1, r3 + mov r9, r3 + +1: + vld2.8 {d0[], d1[]}, [r2, :16], r7 // left + vld2.8 {d20[], d22[]}, [r12, :16]! // weights_ver + vsubl.u8 q1, d0, d6 // left-right (left flipped) + vsubl.u8 q0, d1, d6 + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 +2: + vld1.8 {d16}, [r8]! // top + vld1.8 {d18}, [r10, :64]! // weights_hor + vshll.i8 q12, d6, #8 // right*256 + vshll.i8 q13, d6, #8 + vmovl.u8 q9, d18 // weights_hor + vshll.i8 q14, d4, #8 // bottom*256 + vshll.i8 q15, d4, #8 + vsubl.u8 q8, d16, d4 // top-bottom + vmla.i16 q12, q0, q9 // right*256 + (left-right)*weights_hor + vmla.i16 q13, q1, q9 + vmla.i16 q14, q8, q10 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q15, q8, q11 + vhadd.u16 q12, q12, q14 + vhadd.u16 q13, q13, q15 + vrshrn.i16 d24, q12, #8 + vrshrn.i16 d25, q13, #8 + subs r3, r3, #8 + vst1.8 {d24}, [r0, :64]! + vst1.8 {d25}, [r6, :64]! + bgt 2b + subs r4, r4, #2 + ble 9f + sub r8, r8, r9 + sub r10, r10, r9 + add r0, r0, r1 + add r6, r6, r1 + mov r3, r9 + b 1b +9: + pop {r4-r10, pc} +endfunc + +// void ipred_smooth_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_8bpc_neon, export=1 + push {r4-r7, lr} + ldr r4, [sp, #20] + movrel r7, X(sm_weights) + add r7, r7, r4 + clz lr, r3 + adr r5, L(ipred_smooth_v_tbl) + sub r12, r2, r4 + sub lr, lr, #25 + ldr lr, [r5, lr, lsl #2] + vld1.8 {d4[]}, [r12] // bottom + add r2, r2, #1 + add r5, r5, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_v_tbl): + .word 640f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + +40: + vld1.32 {d6[]}, [r2] // top + vsubl.u8 q3, d6, d4 // top-bottom +4: + vld4.8 {d16[], d17[], d18[], d19[]}, [r7, :32]! // weights_ver + vshll.i8 q10, d4, #8 // bottom*256 + vshll.i8 q11, d4, #8 + vzip.32 d16, d17 // weights_ver + vzip.32 d18, d19 + vmovl.u8 q8, d16 // weights_ver + vmovl.u8 q9, d18 + subs r4, r4, #4 + vmla.i16 q10, q3, q8 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q11, q3, q9 + vrshrn.i16 d20, q10, #8 + vrshrn.i16 d21, q11, #8 + vst1.32 {d20[0]}, [r0, :32], r1 + vst1.32 {d20[1]}, [r6, :32], r1 + vst1.32 {d21[0]}, [r0, :32], r1 + vst1.32 {d21[1]}, [r6, :32], r1 + bgt 4b + pop {r4-r7, pc} +80: + vld1.8 {d6}, [r2] // top + vsubl.u8 q3, d6, d4 // top-bottom +8: + vld4.8 {d16[], d18[], d20[], d22[]}, [r7, :32]! // weights_ver + vshll.i8 q12, d4, #8 // bottom*256 + vshll.i8 q13, d4, #8 + vshll.i8 q14, d4, #8 + vshll.i8 q15, d4, #8 + vmovl.u8 q8, d16 // weights_ver + vmovl.u8 q9, d18 + vmovl.u8 q10, d20 + vmovl.u8 q11, d22 + vmla.i16 q12, q3, q8 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q13, q3, q9 + vmla.i16 q14, q3, q10 + vmla.i16 q15, q3, q11 + vrshrn.i16 d24, q12, #8 + vrshrn.i16 d25, q13, #8 + vrshrn.i16 d26, q14, #8 + vrshrn.i16 d27, q15, #8 + vst1.8 {d24}, [r0, :64], r1 + vst1.8 {d25}, [r6, :64], r1 + subs r4, r4, #4 + vst1.8 {d26}, [r0, :64], r1 + vst1.8 {d27}, [r6, :64], r1 + bgt 8b + pop {r4-r7, pc} +160: +320: +640: + vpush {q4-q7} + // Set up pointers for four rows in parallel; r0, r6, r5, lr + add r5, r0, r1 + add lr, r6, r1 + lsl r1, r1, #1 + sub r1, r1, r3 + mov r12, r3 + +1: + vld4.8 {d8[], d10[], d12[], d14[]}, [r7, :32]! // weights_ver + vmovl.u8 q4, d8 // weights_ver + vmovl.u8 q5, d10 + vmovl.u8 q6, d12 + vmovl.u8 q7, d14 +2: + vld1.8 {q3}, [r2]! // top + vshll.i8 q8, d4, #8 // bottom*256 + vshll.i8 q9, d4, #8 + vshll.i8 q10, d4, #8 + vshll.i8 q11, d4, #8 + vsubl.u8 q0, d6, d4 // top-bottom + vsubl.u8 q1, d7, d4 + vshll.i8 q12, d4, #8 + vshll.i8 q13, d4, #8 + vshll.i8 q14, d4, #8 + vshll.i8 q15, d4, #8 + vmla.i16 q8, q0, q4 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q9, q1, q4 + vmla.i16 q10, q0, q5 + vmla.i16 q11, q1, q5 + vmla.i16 q12, q0, q6 // bottom*256 + (top-bottom)*weights_ver + vmla.i16 q13, q1, q6 + vmla.i16 q14, q0, q7 + vmla.i16 q15, q1, q7 + vrshrn.i16 d16, q8, #8 + vrshrn.i16 d17, q9, #8 + vrshrn.i16 d18, q10, #8 + vrshrn.i16 d19, q11, #8 + vrshrn.i16 d20, q12, #8 + vrshrn.i16 d21, q13, #8 + vrshrn.i16 d22, q14, #8 + vrshrn.i16 d23, q15, #8 + subs r3, r3, #16 + vst1.8 {q8}, [r0, :128]! + vst1.8 {q9}, [r6, :128]! + vst1.8 {q10}, [r5, :128]! + vst1.8 {q11}, [lr, :128]! + bgt 2b + subs r4, r4, #4 + ble 9f + sub r2, r2, r12 + add r0, r0, r1 + add r6, r6, r1 + add r5, r5, r1 + add lr, lr, r1 + mov r3, r12 + b 1b +9: + vpop {q4-q7} + pop {r4-r7, pc} +endfunc + +// void ipred_smooth_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_8bpc_neon, export=1 + push {r4-r8, lr} + ldr r4, [sp, #24] + movrel r8, X(sm_weights) + add r8, r8, r3 + clz lr, r3 + adr r5, L(ipred_smooth_h_tbl) + add r12, r2, r3 + sub lr, lr, #25 + ldr lr, [r5, lr, lsl #2] + vld1.8 {d4[]}, [r12] // right + add r5, r5, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_h_tbl): + .word 640f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + +40: + vld1.32 {d6[]}, [r8, :32] // weights_hor + sub r2, r2, #4 + mov r7, #-4 + vmovl.u8 q3, d6 // weights_hor +4: + vld4.8 {d0[], d1[], d2[], d3[]}, [r2, :32], r7 // left + vshll.i8 q8, d4, #8 // right*256 + vshll.i8 q9, d4, #8 + vzip.32 d3, d2 // left, flipped + vzip.32 d1, d0 + vsubl.u8 q1, d3, d4 // left-right + vsubl.u8 q0, d1, d4 + subs r4, r4, #4 + vmla.i16 q8, q1, q3 // right*256 + (left-right)*weights_hor + vmla.i16 q9, q0, q3 + vrshrn.i16 d16, q8, #8 + vrshrn.i16 d17, q9, #8 + vst1.32 {d16[0]}, [r0, :32], r1 + vst1.32 {d16[1]}, [r6, :32], r1 + vst1.32 {d17[0]}, [r0, :32], r1 + vst1.32 {d17[1]}, [r6, :32], r1 + bgt 4b + pop {r4-r8, pc} +80: + vld1.8 {d6}, [r8, :64] // weights_hor + sub r2, r2, #4 + mov r7, #-4 + vmovl.u8 q3, d6 // weights_hor +8: + vld4.8 {d16[], d18[], d20[], d22[]}, [r2, :32], r7 // left + vshll.i8 q12, d4, #8 // right*256 + vshll.i8 q13, d4, #8 + vshll.i8 q14, d4, #8 + vshll.i8 q15, d4, #8 + vsubl.u8 q11, d22, d4 // left-right + vsubl.u8 q10, d20, d4 + vsubl.u8 q9, d18, d4 + vsubl.u8 q8, d16, d4 + vmla.i16 q12, q11, q3 // right*256 + (left-right)*weights_hor + vmla.i16 q13, q10, q3 // (left flipped) + vmla.i16 q14, q9, q3 + vmla.i16 q15, q8, q3 + vrshrn.i16 d24, q12, #8 + vrshrn.i16 d25, q13, #8 + vrshrn.i16 d26, q14, #8 + vrshrn.i16 d27, q15, #8 + vst1.8 {d24}, [r0, :64], r1 + vst1.8 {d25}, [r6, :64], r1 + subs r4, r4, #4 + vst1.8 {d26}, [r0, :64], r1 + vst1.8 {d27}, [r6, :64], r1 + bgt 8b + pop {r4-r8, pc} +160: +320: +640: + vpush {q4-q7} + sub r2, r2, #4 + mov r7, #-4 + // Set up pointers for four rows in parallel; r0, r6, r5, lr + add r5, r0, r1 + add lr, r6, r1 + lsl r1, r1, #1 + sub r1, r1, r3 + mov r12, r3 + +1: + vld4.8 {d8[], d10[], d12[], d14[]}, [r2, :32], r7 // left + vsubl.u8 q4, d8, d4 // left-right + vsubl.u8 q5, d10, d4 + vsubl.u8 q6, d12, d4 + vsubl.u8 q7, d14, d4 +2: + vld1.8 {q1}, [r8, :128]! // weights_hor + vshll.i8 q8, d4, #8 // right*256 + vshll.i8 q9, d4, #8 + vshll.i8 q10, d4, #8 + vshll.i8 q11, d4, #8 + vmovl.u8 q0, d2 // weights_hor + vmovl.u8 q1, d3 + vshll.i8 q12, d4, #8 + vshll.i8 q13, d4, #8 + vshll.i8 q14, d4, #8 + vshll.i8 q15, d4, #8 + vmla.i16 q8, q7, q0 // right*256 + (left-right)*weights_hor + vmla.i16 q9, q7, q1 // (left flipped) + vmla.i16 q10, q6, q0 + vmla.i16 q11, q6, q1 + vmla.i16 q12, q5, q0 + vmla.i16 q13, q5, q1 + vmla.i16 q14, q4, q0 + vmla.i16 q15, q4, q1 + vrshrn.i16 d16, q8, #8 + vrshrn.i16 d17, q9, #8 + vrshrn.i16 d18, q10, #8 + vrshrn.i16 d19, q11, #8 + vrshrn.i16 d20, q12, #8 + vrshrn.i16 d21, q13, #8 + vrshrn.i16 d22, q14, #8 + vrshrn.i16 d23, q15, #8 + subs r3, r3, #16 + vst1.8 {q8}, [r0, :128]! + vst1.8 {q9}, [r6, :128]! + vst1.8 {q10}, [r5, :128]! + vst1.8 {q11}, [lr, :128]! + bgt 2b + subs r4, r4, #4 + ble 9f + sub r8, r8, r12 + add r0, r0, r1 + add r6, r6, r1 + add r5, r5, r1 + add lr, lr, r1 + mov r3, r12 + b 1b +9: + vpop {q4-q7} + pop {r4-r8, pc} +endfunc + +// void ipred_filter_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height); +function ipred_filter_8bpc_neon, export=1 + push {r4-r8, lr} + movw r12, #511 + ldrd r4, r5, [sp, #24] + and r5, r5, r12 // 511 + movrel r6, X(filter_intra_taps) + lsl r5, r5, #6 + add r6, r6, r5 + vld1.8 {d20, d21, d22, d23}, [r6, :128]! + clz lr, r3 + adr r5, L(ipred_filter_tbl) + vld1.8 {d27, d28, d29}, [r6, :64] + sub lr, lr, #26 + ldr lr, [r5, lr, lsl #2] + vmovl.s8 q8, d20 + vmovl.s8 q9, d21 + add r5, r5, lr + vmovl.s8 q10, d22 + vmovl.s8 q11, d23 + add r6, r0, r1 + lsl r1, r1, #1 + vmovl.s8 q12, d27 + vmovl.s8 q13, d28 + vmovl.s8 q14, d29 + add r8, r2, #1 + sub r2, r2, #2 + mov r7, #-2 + bx r5 + + .align 2 +L(ipred_filter_tbl): + .word 320f - L(ipred_filter_tbl) + CONFIG_THUMB + .word 160f - L(ipred_filter_tbl) + CONFIG_THUMB + .word 80f - L(ipred_filter_tbl) + CONFIG_THUMB + .word 40f - L(ipred_filter_tbl) + CONFIG_THUMB + +40: + vld1.32 {d0[]}, [r8] // top (0-3) + vmovl.u8 q0, d0 // top (0-3) +4: + vld1.32 {d2[]}, [r2], r7 // left (0-1) + topleft (2) + vmul.i16 q2, q9, d0[0] // p1(top[0]) * filter(1) + vmla.i16 q2, q10, d0[1] // p2(top[1]) * filter(2) + vmla.i16 q2, q11, d0[2] // p3(top[2]) * filter(3) + vmovl.u8 q1, d2 // left (0-1) + topleft (2) + vmla.i16 q2, q12, d0[3] // p4(top[3]) * filter(4) + vmla.i16 q2, q8, d2[2] // p0(topleft) * filter(0) + vmla.i16 q2, q13, d2[1] // p5(left[0]) * filter(5) + vmla.i16 q2, q14, d2[0] // p6(left[1]) * filter(6) + vqrshrun.s16 d4, q2, #4 + subs r4, r4, #2 + vst1.32 {d4[0]}, [r0, :32], r1 + vmovl.u8 q0, d4 + vst1.32 {d4[1]}, [r6, :32], r1 + vmov d0, d1 // move top from [4-7] to [0-3] + bgt 4b + pop {r4-r8, pc} +80: + vld1.8 {d0}, [r8] // top (0-7) + vmovl.u8 q0, d0 // top (0-7) +8: + vld1.32 {d2[]}, [r2], r7 // left (0-1) + topleft (2) + vmul.i16 q2, q9, d0[0] // p1(top[0]) * filter(1) + vmla.i16 q2, q10, d0[1] // p2(top[1]) * filter(2) + vmla.i16 q2, q11, d0[2] // p3(top[2]) * filter(3) + vmovl.u8 q1, d2 // left (0-1) + topleft (2) + vmla.i16 q2, q12, d0[3] // p4(top[3]) * filter(4) + vmla.i16 q2, q8, d2[2] // p0(topleft) * filter(0) + vmla.i16 q2, q13, d2[1] // p5(left[0]) * filter(5) + vmla.i16 q2, q14, d2[0] // p6(left[1]) * filter(6) + vmul.i16 q3, q9, d1[0] // p1(top[0]) * filter(1) + vmla.i16 q3, q10, d1[1] // p2(top[1]) * filter(2) + vmla.i16 q3, q11, d1[2] // p3(top[2]) * filter(3) + vqrshrun.s16 d4, q2, #4 + vmovl.u8 q1, d4 // first block, in 16 bit + vmla.i16 q3, q12, d1[3] // p4(top[3]) * filter(4) + vmla.i16 q3, q8, d0[3] // p0(topleft) * filter(0) + vmla.i16 q3, q13, d2[3] // p5(left[0]) * filter(5) + vmla.i16 q3, q14, d3[3] // p6(left[1]) * filter(6) + vqrshrun.s16 d5, q3, #4 + vzip.32 d4, d5 + subs r4, r4, #2 + vst1.8 {d4}, [r0, :64], r1 + vmovl.u8 q0, d5 + vst1.8 {d5}, [r6, :64], r1 + bgt 8b + pop {r4-r8, pc} +160: +320: + vpush {q4-q5} + sub r1, r1, r3 + mov lr, r3 + +1: + vld1.32 {d0[]}, [r2], r7 // left (0-1) + topleft (2) + vmovl.u8 q0, d0 // left (0-1) + topleft (2) +2: + vld1.8 {q2}, [r8]! // top(0-15) + vmul.i16 q3, q8, d0[2] // p0(topleft) * filter(0) + vmla.i16 q3, q13, d0[1] // p5(left[0]) * filter(5) + vmovl.u8 q1, d4 // top(0-7) + vmovl.u8 q2, d5 // top(8-15) + vmla.i16 q3, q14, d0[0] // p6(left[1]) * filter(6) + vmla.i16 q3, q9, d2[0] // p1(top[0]) * filter(1) + vmla.i16 q3, q10, d2[1] // p2(top[1]) * filter(2) + vmla.i16 q3, q11, d2[2] // p3(top[2]) * filter(3) + vmla.i16 q3, q12, d2[3] // p4(top[3]) * filter(4) + + vmul.i16 q4, q9, d3[0] // p1(top[0]) * filter(1) + vmla.i16 q4, q10, d3[1] // p2(top[1]) * filter(2) + vmla.i16 q4, q11, d3[2] // p3(top[2]) * filter(3) + vqrshrun.s16 d6, q3, #4 + vmovl.u8 q0, d6 // first block, in 16 bit + vmla.i16 q4, q12, d3[3] // p4(top[3]) * filter(4) + vmla.i16 q4, q8, d2[3] // p0(topleft) * filter(0) + vmla.i16 q4, q13, d0[3] // p5(left[0]) * filter(5) + vmla.i16 q4, q14, d1[3] // p6(left[1]) * filter(6) + + vmul.i16 q5, q9, d4[0] // p1(top[0]) * filter(1) + vmla.i16 q5, q10, d4[1] // p2(top[1]) * filter(2) + vmla.i16 q5, q11, d4[2] // p3(top[2]) * filter(3) + vqrshrun.s16 d7, q4, #4 + vmovl.u8 q0, d7 // second block, in 16 bit + vmla.i16 q5, q12, d4[3] // p4(top[3]) * filter(4) + vmla.i16 q5, q8, d3[3] // p0(topleft) * filter(0) + vmla.i16 q5, q13, d0[3] // p5(left[0]) * filter(5) + vmla.i16 q5, q14, d1[3] // p6(left[1]) * filter(6) + + vmul.i16 q15, q9, d5[0] // p1(top[0]) * filter(1) + vmla.i16 q15, q10, d5[1] // p2(top[1]) * filter(2) + vmla.i16 q15, q11, d5[2] // p3(top[2]) * filter(3) + vqrshrun.s16 d8, q5, #4 + vmovl.u8 q0, d8 // third block, in 16 bit + vmov.u8 r12, d5[6] + vmla.i16 q15, q12, d5[3] // p4(top[3]) * filter(4) + vmla.i16 q15, q8, d4[3] // p0(topleft) * filter(0) + vmla.i16 q15, q13, d0[3] // p5(left[0]) * filter(5) + vmla.i16 q15, q14, d1[3] // p6(left[1]) * filter(6) + vmov.8 d0[4], r12 + + subs r3, r3, #16 + vqrshrun.s16 d9, q15, #4 + + vst4.32 {d6[0], d7[0], d8[0], d9[0]}, [r0, :128]! + vst4.32 {d6[1], d7[1], d8[1], d9[1]}, [r6, :128]! + ble 8f + vmov.u8 r12, d9[7] + vmov.8 d0[0], r12 + vmov.u8 r12, d9[3] + vmov.8 d0[2], r12 + b 2b +8: + subs r4, r4, #2 + + ble 9f + sub r8, r6, lr + add r0, r0, r1 + add r6, r6, r1 + mov r3, lr + b 1b +9: + vpop {q4-q5} + pop {r4-r8, pc} +endfunc + +// void pal_pred_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_8bpc_neon, export=1 + push {r4-r5, lr} + ldrd r4, r5, [sp, #12] + vld1.16 {q0}, [r2, :128] + clz lr, r4 + adr r12, L(pal_pred_tbl) + sub lr, lr, #25 + ldr lr, [r12, lr, lsl #2] + vmovn.i16 d0, q0 + add r12, r12, lr + add r2, r0, r1 + bx r12 + + .align 2 +L(pal_pred_tbl): + .word 640f - L(pal_pred_tbl) + CONFIG_THUMB + .word 320f - L(pal_pred_tbl) + CONFIG_THUMB + .word 160f - L(pal_pred_tbl) + CONFIG_THUMB + .word 80f - L(pal_pred_tbl) + CONFIG_THUMB + .word 40f - L(pal_pred_tbl) + CONFIG_THUMB + +40: + lsl r1, r1, #1 +4: + vld1.8 {q1}, [r3, :128]! + subs r5, r5, #4 + vtbl.8 d2, {d0}, d2 + vtbl.8 d3, {d0}, d3 + vst1.32 {d2[0]}, [r0, :32], r1 + vst1.32 {d2[1]}, [r2, :32], r1 + vst1.32 {d3[0]}, [r0, :32], r1 + vst1.32 {d3[1]}, [r2, :32], r1 + bgt 4b + pop {r4-r5, pc} +80: + lsl r1, r1, #1 +8: + vld1.8 {q1, q2}, [r3, :128]! + subs r5, r5, #4 + vtbl.8 d2, {d0}, d2 + vtbl.8 d3, {d0}, d3 + vst1.8 {d2}, [r0, :64], r1 + vtbl.8 d4, {d0}, d4 + vst1.8 {d3}, [r2, :64], r1 + vtbl.8 d5, {d0}, d5 + vst1.8 {d4}, [r0, :64], r1 + vst1.8 {d5}, [r2, :64], r1 + bgt 8b + pop {r4-r5, pc} +160: + lsl r1, r1, #1 +16: + vld1.8 {q8, q9}, [r3, :128]! + subs r5, r5, #4 + vld1.8 {q10, q11}, [r3, :128]! + vtbl.8 d16, {d0}, d16 + vtbl.8 d17, {d0}, d17 + vtbl.8 d18, {d0}, d18 + vtbl.8 d19, {d0}, d19 + vtbl.8 d20, {d0}, d20 + vtbl.8 d21, {d0}, d21 + vst1.8 {q8}, [r0, :128], r1 + vtbl.8 d22, {d0}, d22 + vst1.8 {q9}, [r2, :128], r1 + vtbl.8 d23, {d0}, d23 + vst1.8 {q10}, [r0, :128], r1 + vst1.8 {q11}, [r2, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + lsl r1, r1, #1 +32: + vld1.8 {q8, q9}, [r3, :128]! + subs r5, r5, #2 + vld1.8 {q10, q11}, [r3, :128]! + vtbl.8 d16, {d0}, d16 + vtbl.8 d17, {d0}, d17 + vtbl.8 d18, {d0}, d18 + vtbl.8 d19, {d0}, d19 + vtbl.8 d20, {d0}, d20 + vtbl.8 d21, {d0}, d21 + vst1.8 {q8, q9}, [r0, :128], r1 + vtbl.8 d22, {d0}, d22 + vtbl.8 d23, {d0}, d23 + vst1.8 {q10, q11}, [r2, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + sub r1, r1, #32 +64: + vld1.8 {q8, q9}, [r3, :128]! + subs r5, r5, #1 + vld1.8 {q10, q11}, [r3, :128]! + vtbl.8 d16, {d0}, d16 + vtbl.8 d17, {d0}, d17 + vtbl.8 d18, {d0}, d18 + vtbl.8 d19, {d0}, d19 + vtbl.8 d20, {d0}, d20 + vtbl.8 d21, {d0}, d21 + vst1.8 {q8, q9}, [r0, :128]! + vtbl.8 d22, {d0}, d22 + vtbl.8 d23, {d0}, d23 + vst1.8 {q10, q11}, [r0, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_cfl_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_128_8bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz lr, r3 + adr r12, L(ipred_cfl_128_tbl) + sub lr, lr, #26 + ldr lr, [r12, lr, lsl #2] + vmov.i16 q0, #128 // dc + vdup.i16 q1, r6 // alpha + add r12, r12, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r12 + + .align 2 +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w8) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w4) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + +L(ipred_cfl_splat_w4): + vld1.16 {q2, q3}, [r5, :128]! + vmul.i16 q2, q2, q1 // diff = ac * alpha + vmul.i16 q3, q3, q1 + vshr.s16 q8, q2, #15 // sign = diff >> 15 + vshr.s16 q9, q3, #15 + vadd.i16 q2, q2, q8 // diff + sign + vadd.i16 q3, q3, q9 + vrshr.s16 q2, q2, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshr.s16 q3, q3, #6 + vadd.i16 q2, q2, q0 // dc + apply_sign() + vadd.i16 q3, q3, q0 + vqmovun.s16 d4, q2 // iclip_pixel(dc + apply_sign()) + vqmovun.s16 d5, q3 + vst1.32 {d4[0]}, [r0, :32], r1 + vst1.32 {d4[1]}, [r6, :32], r1 + subs r4, r4, #4 + vst1.32 {d5[0]}, [r0, :32], r1 + vst1.32 {d5[1]}, [r6, :32], r1 + bgt L(ipred_cfl_splat_w4) + pop {r4-r8, pc} +L(ipred_cfl_splat_w8): + vld1.16 {q8, q9}, [r5, :128]! + vld1.16 {q10, q11}, [r5, :128]! + vmul.i16 q8, q8, q1 // diff = ac * alpha + vmul.i16 q9, q9, q1 + vmul.i16 q10, q10, q1 + vmul.i16 q11, q11, q1 + vshr.s16 q12, q8, #15 // sign = diff >> 15 + vshr.s16 q13, q9, #15 + vshr.s16 q14, q10, #15 + vshr.s16 q15, q11, #15 + vadd.i16 q8, q8, q12 // diff + sign + vadd.i16 q9, q9, q13 + vadd.i16 q10, q10, q14 + vadd.i16 q11, q11, q15 + vrshr.s16 q8, q8, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshr.s16 q9, q9, #6 + vrshr.s16 q10, q10, #6 + vrshr.s16 q11, q11, #6 + vadd.i16 q8, q8, q0 // dc + apply_sign() + vadd.i16 q9, q9, q0 + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q0 + vqmovun.s16 d16, q8 // iclip_pixel(dc + apply_sign()) + vqmovun.s16 d17, q9 + vqmovun.s16 d18, q10 + vqmovun.s16 d19, q11 + vst1.8 {d16}, [r0, :64], r1 + vst1.8 {d17}, [r6, :64], r1 + subs r4, r4, #4 + vst1.8 {d18}, [r0, :64], r1 + vst1.8 {d19}, [r6, :64], r1 + bgt L(ipred_cfl_splat_w8) + pop {r4-r8, pc} +L(ipred_cfl_splat_w16): + add r12, r5, r3, lsl #1 + sub r1, r1, r3 + mov lr, r3 +1: + vld1.16 {q8, q9}, [r5, :128]! + vmul.i16 q8, q8, q1 // diff = ac * alpha + vld1.16 {q10, q11}, [r12, :128]! + vmul.i16 q9, q9, q1 + vmul.i16 q10, q10, q1 + vmul.i16 q11, q11, q1 + vshr.s16 q12, q8, #15 // sign = diff >> 15 + vshr.s16 q13, q9, #15 + vshr.s16 q14, q10, #15 + vshr.s16 q15, q11, #15 + vadd.i16 q8, q8, q12 // diff + sign + vadd.i16 q9, q9, q13 + vadd.i16 q10, q10, q14 + vadd.i16 q11, q11, q15 + vrshr.s16 q8, q8, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshr.s16 q9, q9, #6 + vrshr.s16 q10, q10, #6 + vrshr.s16 q11, q11, #6 + vadd.i16 q8, q8, q0 // dc + apply_sign() + vadd.i16 q9, q9, q0 + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q0 + vqmovun.s16 d16, q8 // iclip_pixel(dc + apply_sign()) + vqmovun.s16 d17, q9 + vqmovun.s16 d18, q10 + vqmovun.s16 d19, q11 + subs r3, r3, #16 + vst1.16 {q8}, [r0, :128]! + vst1.16 {q9}, [r6, :128]! + bgt 1b + subs r4, r4, #2 + add r5, r5, lr, lsl #1 + add r12, r12, lr, lsl #1 + add r0, r0, r1 + add r6, r6, r1 + mov r3, lr + bgt 1b + pop {r4-r8, pc} +endfunc + +// void ipred_cfl_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_top_8bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz lr, r3 + adr r12, L(ipred_cfl_top_tbl) + sub lr, lr, #26 + ldr lr, [r12, lr, lsl #2] + vdup.16 q1, r6 // alpha + add r2, r2, #1 + add r12, r12, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r12 + + .align 2 +L(ipred_cfl_top_tbl): + .word 32f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 16f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 8f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 4f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + +4: + vld1.32 {d0[]}, [r2] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w4) +8: + vld1.8 {d0}, [r2] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w8) +16: + vld1.8 {q0}, [r2] + vaddl.u8 q0, d0, d1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #4 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +32: + vld1.8 {q2, q3}, [r2] + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.u16 q0, q2, q3 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #5 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +endfunc + +// void ipred_cfl_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_left_8bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + sub r2, r2, r4 + clz lr, r3 + clz r8, r4 + adr r12, L(ipred_cfl_splat_tbl) + adr r7, L(ipred_cfl_left_tbl) + sub lr, lr, #26 + sub r8, r8, #26 + ldr lr, [r12, lr, lsl #2] + ldr r8, [r7, r8, lsl #2] + vdup.16 q1, r6 // alpha + add r12, r12, lr + add r7, r7, r8 + add r6, r0, r1 + lsl r1, r1, #1 + bx r7 + + .align 2 +L(ipred_cfl_left_tbl): + .word L(ipred_cfl_left_h32) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h16) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h8) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h4) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + +L(ipred_cfl_left_h4): + vld1.32 {d0[]}, [r2, :32] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h8): + vld1.8 {d0}, [r2, :64] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h16): + vld1.8 {q0}, [r2, :128] + vaddl.u8 q0, d0, d1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #4 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h32): + vld1.8 {q2, q3}, [r2, :128] + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.u16 q0, q2, q3 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0 + vpadd.u16 d0, d0 + vrshr.u16 d0, d0, #5 + vdup.16 q0, d0[0] + bx r12 +endfunc + +// void ipred_cfl_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_8bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + sub r2, r2, r4 + add r8, r3, r4 // width + height + vdup.16 q1, r6 // alpha + clz lr, r3 + clz r6, r4 + vdup.16 d16, r8 // width + height + adr r7, L(ipred_cfl_tbl) + rbit r8, r8 // rbit(width + height) + sub lr, lr, #22 // 26 leading bits, minus table offset 4 + sub r6, r6, #26 + clz r8, r8 // ctz(width + height) + ldr lr, [r7, lr, lsl #2] + ldr r6, [r7, r6, lsl #2] + neg r8, r8 // -ctz(width + height) + add r12, r7, lr + add r7, r7, r6 + vshr.u16 d16, d16, #1 // (width + height) >> 1 + vdup.16 d17, r8 // -ctz(width + height) + add r6, r0, r1 + lsl r1, r1, #1 + bx r7 + + .align 2 +L(ipred_cfl_tbl): + .word L(ipred_cfl_h32) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h16) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h8) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h4) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w32) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w16) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w8) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w4) - L(ipred_cfl_tbl) + CONFIG_THUMB + +L(ipred_cfl_h4): + vld1.32 {d0[]}, [r2, :32]! + vpaddl.u8 d0, d0 + add r2, r2, #1 + vpadd.i16 d0, d0 + bx r12 +L(ipred_cfl_w4): + vld1.32 {d1[]}, [r2] + vadd.i16 d0, d0, d16 + vpaddl.u8 d1, d1 + vpadd.u16 d1, d1 + cmp r4, #4 + vadd.i16 d0, d0, d1 + vshl.u16 d0, d0, d17 + beq 1f + // h = 8/16 + movw lr, #(0x3334/2) + movw r8, #(0x5556/2) + cmp r4, #16 + it ne + movne lr, r8 + vdup.16 d18, lr + vqdmulh.s16 d0, d0, d18 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + vld1.8 {d0}, [r2, :64]! + vpaddl.u8 d0, d0 + vpadd.i16 d0, d0 + add r2, r2, #1 + vpadd.i16 d0, d0 + bx r12 +L(ipred_cfl_w8): + vld1.8 {d1}, [r2] + vadd.i16 d0, d0, d16 + vpaddl.u8 d1, d1 + vpadd.i16 d1, d1 + vpadd.i16 d1, d1 + cmp r4, #8 + vadd.i16 d0, d0, d1 + vshl.u16 d0, d0, d17 + beq 1f + // h = 4/16/32 + cmp r4, #32 + movw lr, #(0x3334/2) + movw r8, #(0x5556/2) + it ne + movne lr, r8 + vdup.16 d18, lr + vqdmulh.s16 d0, d0, d18 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + vld1.8 {q0}, [r2, :128]! + vaddl.u8 q0, d0, d1 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0 + add r2, r2, #1 + vpadd.i16 d0, d0 + bx r12 +L(ipred_cfl_w16): + vld1.8 {q2}, [r2] + vadd.i16 d0, d0, d16 + vaddl.u8 q2, d4, d5 + vadd.i16 d4, d4, d5 + vpadd.i16 d4, d4 + vpadd.i16 d4, d4 + cmp r4, #16 + vadd.i16 d0, d0, d4 + vshl.u16 d0, d0, d17 + beq 1f + // h = 4/8/32/64 + tst r4, #(32+16+8) // 16 added to make a consecutive bitmask + movw lr, #(0x3334/2) + movw r8, #(0x5556/2) + it ne + movne lr, r8 + vdup.16 d18, lr + vqdmulh.s16 d0, d0, d18 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + vld1.8 {q2, q3}, [r2, :128]! + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.i16 q0, q2, q3 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0 + add r2, r2, #1 + vpadd.i16 d0, d0 + bx r12 +L(ipred_cfl_w32): + vld1.8 {q2, q3}, [r2] + vadd.i16 d0, d0, d16 + vaddl.u8 q2, d4, d5 + vaddl.u8 q3, d6, d7 + vadd.i16 q2, q2, q3 + vadd.i16 d4, d4, d5 + vpadd.i16 d4, d4 + vpadd.i16 d4, d4 + cmp r4, #32 + vadd.i16 d0, d0, d4 + vshl.u16 d0, d0, d17 + beq 1f + // h = 8/16/64 + cmp r4, #8 + movw lr, #(0x3334/2) + movw r8, #(0x5556/2) + it ne + movne lr, r8 + vdup.16 d18, lr + vqdmulh.s16 d0, d0, d18 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +endfunc + +// void cfl_ac_420_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_8bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_420_tbl) + sub r8, r8, #27 + ldr r8, [r7, r8, lsl #2] + vmov.i16 q8, #0 + vmov.i16 q9, #0 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_420_tbl): + .word L(ipred_cfl_ac_420_w16) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w8) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w4) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_420_w4): +1: // Copy and subsample input + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d2}, [r12, :64], r2 + vld1.8 {d1}, [r1, :64], r2 + vld1.8 {d3}, [r12, :64], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q1, q1 + vadd.i16 q0, q0, q1 + vshl.i16 q0, q0, #1 + subs r8, r8, #2 + vst1.16 {q0}, [r0, :128]! + vadd.i16 q8, q8, q0 + bgt 1b + cmp r4, #0 + vmov d0, d1 + vmov d2, d1 + vmov d3, d1 +L(ipred_cfl_ac_420_w4_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q8, q8, q1 + bgt 2b +3: +L(ipred_cfl_ac_420_w4_calc_subtract_dc): + // Aggregate the sums + vadd.i16 q0, q8, q9 + vadd.i16 q1, q10, q11 + vpaddl.u16 q0, q0 + vpaddl.u16 q1, q1 + vadd.i32 q0, q1 + vadd.i32 d0, d0, d1 + vpadd.i32 d0, d0, d0 // sum + sub r0, r0, r6, lsl #3 + vrshl.u32 d16, d0, d31 // (sum + (1 << (log2sz - 1))) >>= log2sz + vdup.16 q8, d16[0] +L(ipred_cfl_ac_420_w4_subtract_dc): +6: // Subtract dc from ac + vld1.16 {q0, q1}, [r0, :128] + subs r6, r6, #4 + vsub.i16 q0, q0, q8 + vsub.i16 q1, q1, q8 + vst1.16 {q0, q1}, [r0, :128]! + bgt 6b + pop {r4-r8, pc} + +L(ipred_cfl_ac_420_w8): + cmp r3, #0 + bne L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + vld1.8 {q0}, [r1, :128], r2 + vld1.8 {q1}, [r12, :128], r2 + vld1.8 {q2}, [r1, :128], r2 + vpaddl.u8 q0, q0 + vld1.8 {q3}, [r12, :128], r2 + vpaddl.u8 q1, q1 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vshl.i16 q0, q0, #1 + vshl.i16 q1, q2, #1 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + bgt 1b + cmp r4, #0 + vmov q0, q1 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + vld1.16 {d0}, [r1, :64], r2 + vld1.16 {d2}, [r12, :64], r2 + vld1.16 {d1}, [r1, :64], r2 + vld1.16 {d3}, [r12, :64], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q1, q1 + vadd.i16 q0, q0, q1 + vshl.i16 q0, q0, #1 + vdup.16 d3, d1[3] + vmov d2, d1 + vdup.16 d1, d0[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + bgt 1b + cmp r4, #0 + vmov q0, q1 + +L(ipred_cfl_ac_420_w8_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 2b +3: + + // Double the height and reuse the w4 summing/subtracting + lsl r6, r6, #1 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_w16): + adr r7, L(ipred_cfl_ac_420_w16_tbl) + ldr r3, [r7, r3, lsl #2] + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_420_w16_tbl): + .word L(ipred_cfl_ac_420_w16_wpad0) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad1) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad2) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad3) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_420_w16_wpad0): +1: // Copy and subsample input, without padding + vld1.8 {q0, q1}, [r1, :128], r2 + vld1.8 {q2, q3}, [r12, :128], r2 + vpaddl.u8 q0, q0 + vld1.8 {q12, q13}, [r1, :128], r2 + vpaddl.u8 q1, q1 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vadd.i16 q0, q0, q2 + vadd.i16 q1, q1, q3 + vld1.8 {q2, q3}, [r12, :128], r2 + vpaddl.u8 q12, q12 + vpaddl.u8 q13, q13 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vadd.i16 q12, q12, q2 + vadd.i16 q13, q13, q3 + vshl.i16 q0, q0, #1 + vshl.i16 q1, q1, #1 + vshl.i16 q2, q12, #1 + vshl.i16 q3, q13, #1 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): +1: // Copy and subsample input, padding 4 + vldr d2, [r1, #16] + vld1.8 {q0}, [r1, :128], r2 + vldr d6, [r12, #16] + vld1.8 {q2}, [r12, :128], r2 + vpaddl.u8 d2, d2 + vldr d26, [r1, #16] + vpaddl.u8 q0, q0 + vld1.8 {q12}, [r1, :128], r2 + vpaddl.u8 d6, d6 + vldr d30, [r12, #16] + vpaddl.u8 q2, q2 + vld1.8 {q14}, [r12, :128], r2 + vpaddl.u8 d26, d26 + vpaddl.u8 q12, q12 + vpaddl.u8 d30, d30 + vpaddl.u8 q14, q14 + vadd.i16 d2, d2, d6 + vadd.i16 q0, q0, q2 + vadd.i16 d26, d26, d30 + vadd.i16 q12, q12, q14 + vshl.i16 d2, d2, #1 + vshl.i16 q0, q0, #1 + vshl.i16 d6, d26, #1 + vshl.i16 q2, q12, #1 + vdup.16 d3, d2[3] + vdup.16 d7, d6[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): +1: // Copy and subsample input, padding 8 + vld1.8 {q0}, [r1, :128], r2 + vld1.8 {q1}, [r12, :128], r2 + vld1.8 {q2}, [r1, :128], r2 + vpaddl.u8 q0, q0 + vld1.8 {q3}, [r12, :128], r2 + vpaddl.u8 q1, q1 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vshl.i16 q0, q0, #1 + vshl.i16 q2, q2, #1 + vdup.16 q1, d1[3] + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): +1: // Copy and subsample input, padding 12 + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d1}, [r12, :64], r2 + vld1.8 {d4}, [r1, :64], r2 + vpaddl.u8 q0, q0 + vld1.8 {d5}, [r12, :64], r2 + vpaddl.u8 q2, q2 + vadd.i16 d0, d0, d1 + vadd.i16 d4, d4, d5 + vshl.i16 d0, d0, #1 + vshl.i16 d4, d4, #1 + vdup.16 q1, d0[3] + vdup.16 q3, d4[3] + vdup.16 d1, d0[3] + vdup.16 d5, d4[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 2b +3: + + // Quadruple the height and reuse the w4 summing/subtracting + lsl r6, r6, #2 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) +endfunc + +// void cfl_ac_422_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_8bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_422_tbl) + sub r8, r8, #27 + ldr r8, [r7, r8, lsl #2] + vmov.i16 q8, #0 + vmov.i16 q9, #0 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_422_tbl): + .word L(ipred_cfl_ac_422_w16) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w8) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w4) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_422_w4): +1: // Copy and subsample input + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d1}, [r12, :64], r2 + vld1.8 {d2}, [r1, :64], r2 + vld1.8 {d3}, [r12, :64], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q1, q1 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + bgt 1b + cmp r4, #0 + vmov d0, d3 + vmov d1, d3 + vmov d2, d3 + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + cmp r3, #0 + bne L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + vld1.8 {q0}, [r1, :128], r2 + vld1.8 {q1}, [r12, :128], r2 + vld1.8 {q2}, [r1, :128], r2 + vpaddl.u8 q0, q0 + vld1.8 {q3}, [r12, :128], r2 + vpaddl.u8 q1, q1 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + vshl.i16 q2, q2, #2 + vshl.i16 q3, q3, #2 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d1}, [r12, :64], r2 + vld1.8 {d2}, [r1, :64], r2 + vld1.8 {d3}, [r12, :64], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q1, q1 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + vdup.16 d7, d3[3] + vmov d6, d3 + vdup.16 d5, d2[3] + vmov d4, d2 + vdup.16 d3, d1[3] + vmov d2, d1 + vdup.16 d1, d0[3] + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + adr r7, L(ipred_cfl_ac_422_w16_tbl) + ldr r3, [r7, r3, lsl #2] + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_422_w16_tbl): + .word L(ipred_cfl_ac_422_w16_wpad0) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad1) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad2) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad3) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_422_w16_wpad0): +1: // Copy and subsample input, without padding + vld1.8 {q0, q1}, [r1, :128], r2 + vld1.8 {q2, q3}, [r12, :128], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q1, q1 + vpaddl.u8 q2, q2 + vpaddl.u8 q3, q3 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + vshl.i16 q2, q2, #2 + vshl.i16 q3, q3, #2 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): +1: // Copy and subsample input, padding 4 + vldr d2, [r1, #16] + vld1.8 {q0}, [r1, :128], r2 + vldr d6, [r12, #16] + vld1.8 {q2}, [r12, :128], r2 + vpaddl.u8 d2, d2 + vpaddl.u8 q0, q0 + vpaddl.u8 d6, d6 + vpaddl.u8 q2, q2 + vshl.i16 d2, d2, #2 + vshl.i16 q0, q0, #2 + vshl.i16 d6, d6, #2 + vshl.i16 q2, q2, #2 + vdup.16 d3, d2[3] + vdup.16 d7, d6[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): +1: // Copy and subsample input, padding 8 + vld1.8 {q0}, [r1, :128], r2 + vld1.8 {q2}, [r12, :128], r2 + vpaddl.u8 q0, q0 + vpaddl.u8 q2, q2 + vshl.i16 q0, q0, #2 + vshl.i16 q2, q2, #2 + vdup.16 q1, d1[3] + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): +1: // Copy and subsample input, padding 12 + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d1}, [r12, :64], r2 + vpaddl.u8 q0, q0 + vshl.i16 q0, q0, #2 + vdup.16 q3, d1[3] + vdup.16 q1, d0[3] + vdup.16 d5, d1[3] + vmov d4, d1 + vdup.16 d1, d0[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) +endfunc + +// void cfl_ac_444_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_8bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_444_tbl) + sub r8, r8, #26 + ldr r8, [r7, r8, lsl #2] + vmov.i16 q8, #0 + vmov.i16 q9, #0 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_444_tbl): + .word L(ipred_cfl_ac_444_w32) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w16) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w8) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w4) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_444_w4): +1: // Copy and expand input + vld1.32 {d0[]}, [r1, :32], r2 + vld1.32 {d0[1]}, [r12, :32], r2 + vld1.32 {d2[]}, [r1, :32], r2 + vld1.32 {d2[1]}, [r12, :32], r2 + vshll.u8 q0, d0, #3 + vshll.u8 q1, d2, #3 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + bgt 1b + cmp r4, #0 + vmov d0, d3 + vmov d1, d3 + vmov d2, d3 + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): +1: // Copy and expand input + vld1.16 {d0}, [r1, :64], r2 + vld1.16 {d2}, [r12, :64], r2 + vld1.16 {d4}, [r1, :64], r2 + vshll.u8 q0, d0, #3 + vld1.16 {d6}, [r12, :64], r2 + vshll.u8 q1, d2, #3 + vshll.u8 q2, d4, #3 + vshll.u8 q3, d6, #3 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + cmp r3, #0 + bne L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + vld1.8 {q1}, [r1, :128], r2 + vld1.8 {q3}, [r12, :128], r2 + vshll.u8 q0, d2, #3 + vshll.u8 q1, d3, #3 + vshll.u8 q2, d6, #3 + vshll.u8 q3, d7, #3 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d4}, [r12, :64], r2 + vshll.u8 q0, d0, #3 + vshll.u8 q2, d4, #3 + vdup.16 q1, d1[3] + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + adr r7, L(ipred_cfl_ac_444_w32_tbl) + ldr r3, [r7, r3, lsl #1] // (w3>>1) << 2 + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_444_w32_tbl): + .word L(ipred_cfl_ac_444_w32_wpad0) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad2) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad4) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad6) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_444_w32_wpad0): +1: // Copy and expand input, without padding + vld1.8 {q2, q3}, [r1, :128], r2 + vld1.8 {q13, q14}, [r12, :128], r2 + vshll.u8 q0, d4, #3 + vshll.u8 q1, d5, #3 + vshll.u8 q2, d6, #3 + vshll.u8 q3, d7, #3 + vshll.u8 q12, d26, #3 + vshll.u8 q13, d27, #3 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vshll.u8 q0, d28, #3 + vshll.u8 q1, d29, #3 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + vst1.16 {q12, q13}, [r0, :128]! + vadd.i16 q8, q8, q12 + vadd.i16 q9, q9, q13 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): +1: // Copy and expand input, padding 8 + vldr d4, [r1, #16] + vld1.8 {q1}, [r1, :128], r2 + vldr d28, [r12, #16] + vld1.8 {q13}, [r12, :128], r2 + vshll.u8 q2, d4, #3 + vshll.u8 q0, d2, #3 + vshll.u8 q1, d3, #3 + vshll.u8 q12, d26, #3 + vshll.u8 q13, d27, #3 + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vshll.u8 q0, d28, #3 + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + vdup.16 q1, d1[3] + vst1.16 {q12, q13}, [r0, :128]! + vadd.i16 q8, q8, q12 + vadd.i16 q9, q9, q13 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): +1: // Copy and expand input, padding 16 + vld1.8 {q1}, [r1, :128], r2 + vld1.8 {q13}, [r12, :128], r2 + vshll.u8 q0, d2, #3 + vshll.u8 q1, d3, #3 + vshll.u8 q12, d26, #3 + vshll.u8 q13, d27, #3 + vdup.16 q2, d3[3] + vdup.16 q3, d3[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vdup.16 q0, d27[3] + vdup.16 q1, d27[3] + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + vst1.16 {q12, q13}, [r0, :128]! + vadd.i16 q8, q8, q12 + vadd.i16 q9, q9, q13 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): +1: // Copy and expand input, padding 24 + vld1.8 {d0}, [r1, :64], r2 + vld1.8 {d24}, [r12, :64], r2 + vshll.u8 q0, d0, #3 + vshll.u8 q12, d24, #3 + subs r8, r8, #2 + vdup.16 q1, d1[3] + vdup.16 q2, d1[3] + vdup.16 q3, d1[3] + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q8, q8, q0 + vadd.i16 q9, q9, q1 + vdup.16 q13, d25[3] + vdup.16 q0, d25[3] + vdup.16 q1, d25[3] + vst1.16 {q2, q3}, [r0, :128]! + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q3 + vst1.16 {q12, q13}, [r0, :128]! + vadd.i16 q8, q8, q12 + vadd.i16 q9, q9, q13 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 1b + cmp r4, #0 + +L(ipred_cfl_ac_444_w32_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #1 + vst1.16 {q12, q13}, [r0, :128]! + vadd.i16 q8, q8, q12 + vadd.i16 q9, q9, q13 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q10, q10, q0 + vadd.i16 q11, q11, q1 + bgt 2b +3: + + // Multiply the height by eight and reuse the w4 subtracting + lsl r6, r6, #3 + // Aggregate the sums, with wider intermediates earlier than in + // ipred_cfl_ac_420_w8_calc_subtract_dc. + vpaddl.u16 q0, q8 + vpaddl.u16 q1, q9 + vpaddl.u16 q2, q10 + vpaddl.u16 q3, q11 + vadd.i32 q0, q0, q1 + vadd.i32 q2, q2, q3 + vadd.i32 q0, q0, q2 + vadd.i32 d0, d0, d1 + vpadd.i32 d0, d0, d0 // sum + sub r0, r0, r6, lsl #3 + vrshl.u32 d16, d0, d31 // (sum + (1 << (log2sz - 1))) >>= log2sz + vdup.16 q8, d16[0] + b L(ipred_cfl_ac_420_w4_subtract_dc) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/ipred16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3254 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, B Krishnan Iyer + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height, +// const int bitdepth_max); +function ipred_dc_128_16bpc_neon, export=1 + push {r4, lr} + ldr r4, [sp, #8] + ldr r12, [sp, #24] + clz r3, r3 + adr r2, L(ipred_dc_128_tbl) + sub r3, r3, #25 + vdup.16 q0, r12 + ldr r3, [r2, r3, lsl #2] + add r12, r0, r1 + vrshr.u16 q0, q0, #1 + add r2, r2, r3 + lsl r1, r1, #1 + bx r2 + + .align 2 +L(ipred_dc_128_tbl): + .word 640f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 320f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 160f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 8f - L(ipred_dc_128_tbl) + CONFIG_THUMB + .word 4f - L(ipred_dc_128_tbl) + CONFIG_THUMB +4: + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt 4b + pop {r4, pc} +8: + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + bgt 8b + pop {r4, pc} +160: + vmov q1, q0 +16: + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 16b + pop {r4, pc} +320: + vmov q1, q0 + sub r1, r1, #32 +32: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 32b + pop {r4, pc} +640: + vmov q1, q0 + sub r1, r1, #96 +64: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + subs r4, r4, #2 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 64b + pop {r4, pc} +endfunc + +// void ipred_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_16bpc_neon, export=1 + push {r4, lr} + ldr lr, [sp, #8] + clz r3, r3 + adr r4, L(ipred_v_tbl) + sub r3, r3, #25 + ldr r3, [r4, r3, lsl #2] + add r2, r2, #2 + add r4, r4, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r4 + + .align 2 +L(ipred_v_tbl): + .word 640f - L(ipred_v_tbl) + CONFIG_THUMB + .word 320f - L(ipred_v_tbl) + CONFIG_THUMB + .word 160f - L(ipred_v_tbl) + CONFIG_THUMB + .word 80f - L(ipred_v_tbl) + CONFIG_THUMB + .word 40f - L(ipred_v_tbl) + CONFIG_THUMB + +40: + vld1.16 {d0}, [r2] +4: + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + subs lr, lr, #4 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt 4b + pop {r4, pc} +80: + vld1.16 {q0}, [r2] +8: + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + subs lr, lr, #4 + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + bgt 8b + pop {r4, pc} +160: + vld1.16 {q0, q1}, [r2] +16: + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs lr, lr, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 16b + pop {r4, pc} +320: + vld1.16 {q0, q1}, [r2]! + sub r1, r1, #32 + vld1.16 {q2, q3}, [r2] +32: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d4, d5, d6, d7}, [r0, :128], r1 + vst1.16 {d4, d5, d6, d7}, [r12, :128], r1 + subs lr, lr, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d4, d5, d6, d7}, [r0, :128], r1 + vst1.16 {d4, d5, d6, d7}, [r12, :128], r1 + bgt 32b + pop {r4, pc} +640: + vld1.16 {q0, q1}, [r2]! + sub r1, r1, #96 + vld1.16 {q2, q3}, [r2]! + vld1.16 {q8, q9}, [r2]! + vld1.16 {q10, q11}, [r2]! +64: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d4, d5, d6, d7}, [r0, :128]! + vst1.16 {d4, d5, d6, d7}, [r12, :128]! + subs lr, lr, #2 + vst1.16 {d16, d17, d18, d19}, [r0, :128]! + vst1.16 {d16, d17, d18, d19}, [r12, :128]! + vst1.16 {d20, d21, d22, d23}, [r0, :128], r1 + vst1.16 {d20, d21, d22, d23}, [r12, :128], r1 + bgt 64b + pop {r4, pc} +endfunc + +// void ipred_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_16bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + clz r3, r3 + adr r5, L(ipred_h_tbl) + sub r3, r3, #25 + ldr r3, [r5, r3, lsl #2] + sub r2, r2, #2 + mov lr, #-2 + add r5, r5, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_h_tbl): + .word 640f - L(ipred_h_tbl) + CONFIG_THUMB + .word 320f - L(ipred_h_tbl) + CONFIG_THUMB + .word 160f - L(ipred_h_tbl) + CONFIG_THUMB + .word 8f - L(ipred_h_tbl) + CONFIG_THUMB + .word 40f - L(ipred_h_tbl) + CONFIG_THUMB +40: + sub r2, r2, #6 + mov lr, #-8 +4: + vld4.16 {d0[], d1[], d2[], d3[]}, [r2], lr + vst1.16 {d3}, [r0, :64], r1 + vst1.16 {d2}, [r12, :64], r1 + subs r4, r4, #4 + vst1.16 {d1}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt 4b + pop {r4-r5, pc} +8: + vld1.16 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.16 {d2[], d3[]}, [r2], lr + vst1.16 {q0}, [r0, :128], r1 + vld1.16 {d4[], d5[]}, [r2], lr + vst1.16 {q1}, [r12, :128], r1 + vld1.16 {d6[], d7[]}, [r2], lr + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r12, :128], r1 + bgt 8b + pop {r4-r5, pc} +160: + sub r1, r1, #16 +16: + vld1.16 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.16 {d2[], d3[]}, [r2], lr + vst1.16 {q0}, [r0, :128]! + vld1.16 {d4[], d5[]}, [r2], lr + vst1.16 {q1}, [r12, :128]! + vld1.16 {d6[], d7[]}, [r2], lr + vst1.16 {q0}, [r0, :128], r1 + vst1.16 {q1}, [r12, :128], r1 + vst1.16 {q2}, [r0, :128]! + vst1.16 {q3}, [r12, :128]! + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r12, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + sub r1, r1, #48 +32: + vld1.16 {d0[], d1[]}, [r2], lr + subs r4, r4, #4 + vld1.16 {d2[], d3[]}, [r2], lr + vst1.16 {q0}, [r0, :128]! + vld1.16 {d4[], d5[]}, [r2], lr + vst1.16 {q1}, [r12, :128]! + vld1.16 {d6[], d7[]}, [r2], lr + vst1.16 {q0}, [r0, :128]! + vst1.16 {q1}, [r12, :128]! + vst1.16 {q0}, [r0, :128]! + vst1.16 {q1}, [r12, :128]! + vst1.16 {q0}, [r0, :128], r1 + vst1.16 {q1}, [r12, :128], r1 + vst1.16 {q2}, [r0, :128]! + vst1.16 {q3}, [r12, :128]! + vst1.16 {q2}, [r0, :128]! + vst1.16 {q3}, [r12, :128]! + vst1.16 {q2}, [r0, :128]! + vst1.16 {q3}, [r12, :128]! + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r12, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + sub r1, r1, #96 +64: + vld1.16 {d0[], d1[]}, [r2], lr + subs r4, r4, #2 + vld1.16 {d4[], d5[]}, [r2], lr + vmov q1, q0 + vmov q3, q2 + vst1.16 {q0, q1}, [r0, :128]! + vst1.16 {q2, q3}, [r12, :128]! + vst1.16 {q0, q1}, [r0, :128]! + vst1.16 {q2, q3}, [r12, :128]! + vst1.16 {q0, q1}, [r0, :128]! + vst1.16 {q2, q3}, [r12, :128]! + vst1.16 {q0, q1}, [r0, :128], r1 + vst1.16 {q2, q3}, [r12, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_16bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + clz r3, r3 + adr r5, L(ipred_dc_top_tbl) + sub r3, r3, #25 + ldr r3, [r5, r3, lsl #2] + add r2, r2, #2 + add r5, r5, r3 + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_top_tbl): + .word 640f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 320f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 160f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 80f - L(ipred_dc_top_tbl) + CONFIG_THUMB + .word 40f - L(ipred_dc_top_tbl) + CONFIG_THUMB + +40: + vld1.16 {d0}, [r2] + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 d0, d0[0] +4: + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt 4b + pop {r4-r5, pc} +80: + vld1.16 {d0, d1}, [r2] + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] +8: + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + bgt 8b + pop {r4-r5, pc} +160: + vld1.16 {d0, d1, d2, d3}, [r2] + vadd.i16 q0, q0, q1 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d4, d0, #4 + vdup.16 q0, d4[0] + vdup.16 q1, d4[0] +16: + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + vld1.16 {d0, d1, d2, d3}, [r2]! + vld1.16 {d4, d5, d6, d7}, [r2] + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vadd.i16 q0, q0, q2 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpaddl.u16 d0, d0 + vrshrn.i32 d18, q0, #5 + vdup.16 q0, d18[0] + vdup.16 q1, d18[0] + sub r1, r1, #32 +32: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + vld1.16 {d0, d1, d2, d3}, [r2]! + vld1.16 {d4, d5, d6, d7}, [r2]! + vadd.i16 q0, q0, q1 + vld1.16 {d16, d17, d18, d19}, [r2]! + vadd.i16 q2, q2, q3 + vld1.16 {d20, d21, d22, d23}, [r2] + vadd.i16 q8, q8, q9 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q0, q2 + vadd.i16 q8, q8, q10 + vadd.i16 q0, q0, q8 + vadd.i16 d0, d0, d1 + vpaddl.u16 d0, d0 + vpadd.i32 d0, d0, d0 + vrshrn.i32 d18, q0, #6 + vdup.16 q0, d18[0] + vdup.16 q1, d18[0] + sub r1, r1, #96 +64: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + subs r4, r4, #2 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_16bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + sub r2, r2, r4, lsl #1 + clz r3, r3 + clz lr, r4 + sub lr, lr, #25 + adr r5, L(ipred_dc_left_tbl) + sub r3, r3, #20 + ldr r3, [r5, r3, lsl #2] + ldr lr, [r5, lr, lsl #2] + add r3, r5, r3 + add r5, r5, lr + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_left_tbl): + .word L(ipred_dc_left_h64) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h32) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h16) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h8) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_h4) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w64) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w32) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w16) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w8) - L(ipred_dc_left_tbl) + CONFIG_THUMB + .word L(ipred_dc_left_w4) - L(ipred_dc_left_tbl) + CONFIG_THUMB + +L(ipred_dc_left_h4): + vld1.16 {d0}, [r2, :64] + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 q0, d0[0] + bx r3 +L(ipred_dc_left_w4): + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt L(ipred_dc_left_w4) + pop {r4-r5, pc} +L(ipred_dc_left_h8): + vld1.16 {d0, d1}, [r2, :128] + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] + bx r3 +L(ipred_dc_left_w8): + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + bgt L(ipred_dc_left_w8) + pop {r4-r5, pc} +L(ipred_dc_left_h16): + vld1.16 {d0, d1, d2, d3}, [r2, :128] + vadd.i16 q0, q0, q1 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #4 + vdup.16 q0, d0[0] + bx r3 +L(ipred_dc_left_w16): + vmov q1, q0 +1: + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 1b + pop {r4-r5, pc} +L(ipred_dc_left_h32): + vld1.16 {d0, d1, d2, d3}, [r2, :128]! + vld1.16 {d4, d5, d6, d7}, [r2, :128] + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vadd.i16 q0, q0, q2 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpaddl.u16 d0, d0 + vrshrn.i32 d0, q0, #5 + vdup.16 q0, d0[0] + bx r3 +L(ipred_dc_left_w32): + sub r1, r1, #32 + vmov q1, q0 +1: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 1b + pop {r4-r5, pc} +L(ipred_dc_left_h64): + vld1.16 {d0, d1, d2, d3}, [r2, :128]! + vld1.16 {d4, d5, d6, d7}, [r2, :128]! + vadd.i16 q0, q0, q1 + vld1.16 {d16, d17, d18, d19}, [r2, :128]! + vadd.i16 q2, q2, q3 + vld1.16 {d20, d21, d22, d23}, [r2, :128] + vadd.i16 q8, q8, q9 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q0, q2 + vadd.i16 q8, q8, q10 + vadd.i16 q0, q0, q8 + vadd.i16 d0, d0, d1 + vpaddl.u16 d0, d0 + vpadd.i32 d0, d0, d0 + vrshrn.i32 d0, q0, #6 + vdup.16 q0, d0[0] + bx r3 +L(ipred_dc_left_w64): + sub r1, r1, #96 + vmov q1, q0 +1: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + subs r4, r4, #2 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 1b + pop {r4-r5, pc} +endfunc + +// void ipred_dc_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_16bpc_neon, export=1 + push {r4-r6, lr} + ldr r4, [sp, #16] + sub r2, r2, r4, lsl #1 + add lr, r3, r4 // width + height + clz r3, r3 + clz r12, r4 + vdup.32 q15, lr // width + height + adr r5, L(ipred_dc_tbl) + rbit lr, lr // rbit(width + height) + sub r3, r3, #20 // 25 leading bits, minus table offset 5 + sub r12, r12, #25 + clz lr, lr // ctz(width + height) + ldr r3, [r5, r3, lsl #2] + ldr r12, [r5, r12, lsl #2] + neg lr, lr // -ctz(width + height) + add r3, r5, r3 + add r5, r5, r12 + vshr.u32 q15, q15, #1 // (width + height) >> 1 + vdup.32 q14, lr // -ctz(width + height) + add r12, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_dc_tbl): + .word L(ipred_dc_h64) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h32) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h16) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h8) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_h4) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w64) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w32) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w16) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w8) - L(ipred_dc_tbl) + CONFIG_THUMB + .word L(ipred_dc_w4) - L(ipred_dc_tbl) + CONFIG_THUMB + +L(ipred_dc_h4): + vld1.16 {d0}, [r2, :64]! + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r3 +L(ipred_dc_w4): + vld1.16 {d2}, [r2] + vadd.i32 d0, d0, d30 + vpadd.i16 d2, d2, d2 + vpaddl.u16 d2, d2 + cmp r4, #4 + vadd.i32 d0, d0, d2 + vshl.u32 d0, d0, d28 + beq 1f + // h = 8/16 + cmp r4, #16 + movw lr, #0x6667 + movw r5, #0xAAAB + it ne + movne lr, r5 + vdup.32 d24, lr + vmul.i32 d0, d0, d24 + vshr.u32 d0, d0, #17 +1: + vdup.16 d0, d0[0] +2: + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + subs r4, r4, #4 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d0}, [r12, :64], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h8): + vld1.16 {d0, d1}, [r2, :128]! + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r3 +L(ipred_dc_w8): + vld1.16 {d2, d3}, [r2] + vadd.i32 d0, d0, d30 + vadd.i16 d2, d2, d3 + vpadd.i16 d2, d2, d2 + vpaddl.u16 d2, d2 + cmp r4, #8 + vadd.i32 d0, d0, d2 + vshl.u32 d0, d0, d28 + beq 1f + // h = 4/16/32 + cmp r4, #32 + movw lr, #0x6667 + movw r5, #0xAAAB + it ne + movne lr, r5 + vdup.32 d24, lr + vmul.i32 d0, d0, d24 + vshr.u32 d0, d0, #17 +1: + vdup.16 q0, d0[0] +2: + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1}, [r0, :128], r1 + vst1.16 {d0, d1}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h16): + vld1.16 {d0, d1, d2, d3}, [r2, :128]! + vadd.i16 q0, q0, q1 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r3 +L(ipred_dc_w16): + vld1.16 {d2, d3, d4, d5}, [r2] + vadd.i32 d0, d0, d30 + vadd.i16 q1, q1, q2 + vadd.i16 d2, d2, d3 + vpadd.i16 d2, d2, d1 + vpaddl.u16 d2, d2 + cmp r4, #16 + vadd.i32 d0, d0, d2 + vshl.u32 d4, d0, d28 + beq 1f + // h = 4/8/32/64 + tst r4, #(32+16+8) // 16 added to make a consecutive bitmask + movw lr, #0x6667 + movw r5, #0xAAAB + it ne + movne lr, r5 + vdup.32 d24, lr + vmul.i32 d4, d4, d24 + vshr.u32 d4, d4, #17 +1: + vdup.16 q0, d4[0] + vdup.16 q1, d4[0] +2: + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} + +L(ipred_dc_h32): + vld1.16 {d0, d1, d2, d3}, [r2, :128]! + vld1.16 {d4, d5, d6, d7}, [r2, :128]! + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vadd.i16 q0, q0, q2 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r3 +L(ipred_dc_w32): + vld1.16 {d2, d3, d4, d5}, [r2]! + vadd.i32 d0, d0, d30 + vld1.16 {d16, d17, d18, d19}, [r2] + vadd.i16 q1, q1, q2 + vadd.i16 q8, q8, q9 + vadd.i16 q1, q1, q8 + vadd.i16 d2, d2, d3 + vpadd.i16 d2, d2, d2 + vpaddl.u16 d2, d2 + cmp r4, #32 + vadd.i32 d0, d0, d2 + vshl.u32 d4, d0, d28 + beq 1f + // h = 8/16/64 + cmp r4, #8 + movw lr, #0x6667 + movw r5, #0xAAAB + it ne + movne lr, r5 + vdup.32 d24, lr + vmul.i32 d4, d4, d24 + vshr.u32 d4, d4, #17 +1: + sub r1, r1, #32 + vdup.16 q0, d4[0] + vdup.16 q1, d4[0] +2: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + subs r4, r4, #4 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} +L(ipred_dc_h64): + vld1.16 {d0, d1, d2, d3}, [r2, :128]! + vld1.16 {d4, d5, d6, d7}, [r2, :128]! + vadd.i16 q0, q0, q1 + vld1.16 {d16, d17, d18, d19}, [r2, :128]! + vadd.i16 q2, q2, q3 + vld1.16 {d20, d21, d22, d23}, [r2, :128]! + vadd.i16 q8, q8, q9 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q0, q2 + vadd.i16 q8, q8, q10 + vadd.i16 q0, q0, q8 + vadd.i16 d0, d0, d1 + vpaddl.u16 d0, d0 + add r2, r2, #2 + vpadd.i32 d0, d0, d0 + bx r3 +L(ipred_dc_w64): + vld1.16 {d2, d3, d4, d5}, [r2]! + vadd.i32 d0, d0, d30 + vld1.16 {d16, d17, d18, d19}, [r2]! + vadd.i16 q1, q1, q2 + vld1.16 {d20, d21, d22, d23}, [r2]! + vadd.i16 q8, q8, q9 + vld1.16 {d24, d25, d26, d27}, [r2]! + vadd.i16 q10, q10, q11 + vadd.i16 q12, q12, q13 + vadd.i16 q1, q1, q8 + vadd.i16 q10, q10, q12 + vadd.i16 q1, q1, q10 + vadd.i16 d2, d2, d3 + vpaddl.u16 d2, d2 + vpadd.i32 d2, d2, d2 + cmp r4, #64 + vadd.i32 d0, d0, d2 + vshl.u32 d4, d0, d28 + beq 1f + // h = 16/32 + cmp r4, #16 + movw lr, #0x6667 + movw r5, #0xAAAB + it ne + movne lr, r5 + vdup.32 d24, lr + vmul.i32 d4, d4, d24 + vshr.u32 d4, d4, #17 +1: + sub r1, r1, #96 + vdup.16 q0, d4[0] + vdup.16 q1, d4[0] +2: + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + subs r4, r4, #2 + vst1.16 {d0, d1, d2, d3}, [r0, :128]! + vst1.16 {d0, d1, d2, d3}, [r12, :128]! + vst1.16 {d0, d1, d2, d3}, [r0, :128], r1 + vst1.16 {d0, d1, d2, d3}, [r12, :128], r1 + bgt 2b + pop {r4-r6, pc} +endfunc + +// void ipred_paeth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_16bpc_neon, export=1 + push {r4-r6, lr} + vpush {q4} + ldr r4, [sp, #32] + clz lr, r3 + adr r12, L(ipred_paeth_tbl) + sub lr, lr, #25 + ldr lr, [r12, lr, lsl #2] + vld1.16 {d4[], d5[]}, [r2] + add r6, r2, #2 + sub r2, r2, #4 + add r12, r12, lr + mov r5, #-4 + add lr, r0, r1 + lsl r1, r1, #1 + bx r12 + + .align 2 +L(ipred_paeth_tbl): + .word 640f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 320f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 160f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 80f - L(ipred_paeth_tbl) + CONFIG_THUMB + .word 40f - L(ipred_paeth_tbl) + CONFIG_THUMB + +40: + sub r2, r2, #4 + mov r5, #-8 + vld1.16 {d6}, [r6] + vsub.i16 d16, d6, d4 // top - topleft + vmov d7, d6 + vmov d17, d16 +4: + vld4.16 {d0[], d1[], d2[], d3[]}, [r2, :64], r5 + vadd.i16 q9, q8, q0 // base + vadd.i16 q10, q8, q1 + vabd.s16 q11, q3, q9 // tdiff + vabd.s16 q12, q3, q10 + vabd.s16 q13, q2, q9 // tldiff + vabd.s16 q14, q2, q10 + vabd.s16 q9, q0, q9 // ldiff + vabd.s16 q10, q1, q10 + vmin.u16 q15, q11, q13 // min(tdiff, tldiff) + vmin.u16 q4, q12, q14 + vcge.u16 q11, q13, q11 // tldiff >= tdiff + vcge.u16 q12, q14, q12 + vcge.u16 q9, q15, q9 // min(tdiff, tldiff) >= ldiff + vcge.u16 q10, q4, q10 + vbsl q12, q3, q2 // tdiff <= tldiff ? top : topleft + vbsl q11, q3, q2 + vbit q12, q1, q10 // ldiff <= min ? left : ... + vbit q11, q0, q9 + vst1.16 {d25}, [r0, :64], r1 + vst1.16 {d24}, [lr, :64], r1 + subs r4, r4, #4 + vst1.16 {d23}, [r0, :64], r1 + vst1.16 {d22}, [lr, :64], r1 + bgt 4b + vpop {q4} + pop {r4-r6, pc} +80: +160: +320: +640: + vld1.16 {q3}, [r6]! + mov r12, r3 + sub r1, r1, r3, lsl #1 +1: + vld2.16 {d0[], d2[]}, [r2, :32], r5 + vmov d1, d0 + vmov d3, d2 +2: + vsub.i16 q8, q3, q2 // top - topleft + vadd.i16 q9, q8, q0 // base + vadd.i16 q10, q8, q1 + vabd.s16 q11, q3, q9 // tdiff + vabd.s16 q12, q3, q10 + vabd.s16 q13, q2, q9 // tldiff + vabd.s16 q14, q2, q10 + vabd.s16 q9, q0, q9 // ldiff + vabd.s16 q10, q1, q10 + vmin.u16 q15, q11, q13 // min(tdiff, tldiff) + vmin.u16 q4, q12, q14 + vcge.u16 q11, q13, q11 // tldiff >= tdiff + vcge.u16 q12, q14, q12 + vcge.u16 q9, q15, q9 // min(tdiff, tldiff) >= ldiff + vcge.u16 q10, q4, q10 + vbsl q12, q3, q2 // tdiff <= tldiff ? top : topleft + vbsl q11, q3, q2 + vbit q12, q1, q10 // ldiff <= min ? left : ... + vbit q11, q0, q9 + subs r3, r3, #8 + vst1.16 {q12}, [r0, :128]! + vst1.16 {q11}, [lr, :128]! + ble 8f + vld1.16 {q3}, [r6]! + b 2b +8: + subs r4, r4, #2 + ble 9f + // End of horizontal loop, move pointers to next two rows + sub r6, r6, r12, lsl #1 + add r0, r0, r1 + add lr, lr, r1 + vld1.16 {q3}, [r6]! + mov r3, r12 + b 1b +9: + vpop {q4} + pop {r4-r6, pc} +endfunc + +// void ipred_smooth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_16bpc_neon, export=1 + push {r4-r10, lr} + ldr r4, [sp, #32] + movrel r10, X(sm_weights) + add r12, r10, r4 + add r10, r10, r3 + clz r9, r3 + adr r5, L(ipred_smooth_tbl) + sub lr, r2, r4, lsl #1 + sub r9, r9, #25 + ldr r9, [r5, r9, lsl #2] + vld1.16 {d4[], d5[]}, [lr] // bottom + add r8, r2, #2 + add r5, r5, r9 + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_tbl): + .word 640f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_tbl) + CONFIG_THUMB + +40: + vld1.16 {d16}, [r8] // top + vld1.32 {d18[]}, [r10, :32] // weights_hor + sub r2, r2, #8 + mov r7, #-8 + vdup.16 q3, d16[3] // right + vsub.i16 q8, q8, q2 // top-bottom + vmovl.u8 q9, d18 // weights_hor + vadd.i16 d19, d4, d6 // bottom+right +4: + vld4.16 {d0[], d1[], d2[], d3[]}, [r2, :64], r7 // left + vld4.8 {d20[], d21[], d22[], d23[]}, [r12, :32]! // weights_ver + vshll.u16 q12, d19, #8 // (bottom+right)*256 + vshll.u16 q13, d19, #8 + vshll.u16 q14, d19, #8 + vshll.u16 q15, d19, #8 + vzip.32 d20, d21 // weights_ver + vzip.32 d22, d23 + vsub.i16 q1, q1, q3 // left-right + vsub.i16 q0, q0, q3 + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 + vmlal.s16 q12, d3, d18 // += (left-right)*weights_hor + vmlal.s16 q13, d2, d18 // (left flipped) + vmlal.s16 q14, d1, d18 + vmlal.s16 q15, d0, d18 + vmlal.s16 q12, d16, d20 // += (top-bottom)*weights_ver + vmlal.s16 q13, d16, d21 + vmlal.s16 q14, d16, d22 + vmlal.s16 q15, d16, d23 + vrshrn.i32 d24, q12, #9 + vrshrn.i32 d25, q13, #9 + vrshrn.i32 d26, q14, #9 + vrshrn.i32 d27, q15, #9 + vst1.16 {d24}, [r0, :64], r1 + vst1.16 {d25}, [r6, :64], r1 + subs r4, r4, #4 + vst1.16 {d26}, [r0, :64], r1 + vst1.16 {d27}, [r6, :64], r1 + bgt 4b + pop {r4-r10, pc} +80: + vld1.16 {q8}, [r8] // top + vld1.8 {d18}, [r10, :64] // weights_hor + sub r2, r2, #4 + mov r7, #-4 + vdup.16 q3, d17[3] // right + vsub.i16 q8, q8, q2 // top-bottom + vmovl.u8 q9, d18 // weights_hor + vadd.i16 d3, d4, d6 // bottom+right +8: + vld2.16 {d0[], d1[]}, [r2, :32], r7 // left + vld2.8 {d20[], d22[]}, [r12, :16]! // weights_ver + vshll.u16 q12, d3, #8 // (bottom+right)*256 + vshll.u16 q13, d3, #8 + vshll.u16 q14, d3, #8 + vshll.u16 q15, d3, #8 + vsub.i16 q0, q0, q3 // left-right + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 + vmlal.s16 q12, d1, d18 // += (left-right)*weights_hor + vmlal.s16 q13, d1, d19 // (left flipped) + vmlal.s16 q14, d0, d18 + vmlal.s16 q15, d0, d19 + vmlal.s16 q12, d16, d20 // += (top-bottom)*weights_ver + vmlal.s16 q13, d17, d20 + vmlal.s16 q14, d16, d22 + vmlal.s16 q15, d17, d22 + vrshrn.i32 d24, q12, #9 + vrshrn.i32 d25, q13, #9 + vrshrn.i32 d26, q14, #9 + vrshrn.i32 d27, q15, #9 + subs r4, r4, #2 + vst1.16 {q12}, [r0, :128], r1 + vst1.16 {q13}, [r6, :128], r1 + bgt 8b + pop {r4-r10, pc} +160: +320: +640: + add lr, r2, r3, lsl #1 + sub r2, r2, #4 + mov r7, #-4 + vld1.16 {d6[], d7[]}, [lr] // right + sub r1, r1, r3, lsl #1 + mov r9, r3 + vadd.i16 d3, d4, d6 // bottom+right + +1: + vld2.16 {d0[], d1[]}, [r2, :32], r7 // left + vld2.8 {d20[], d22[]}, [r12, :16]! // weights_ver + vsub.i16 q0, q0, q3 // left-right + vmovl.u8 q10, d20 // weights_ver + vmovl.u8 q11, d22 +2: + vld1.8 {d18}, [r10, :64]! // weights_hor + vld1.16 {q8}, [r8]! // top + vshll.u16 q12, d3, #8 // (bottom+right)*256 + vshll.u16 q13, d3, #8 + vmovl.u8 q9, d18 // weights_hor + vshll.u16 q14, d3, #8 + vshll.u16 q15, d3, #8 + vsub.i16 q8, q8, q2 // top-bottom + vmlal.s16 q12, d1, d18 // += (left-right)*weights_hor + vmlal.s16 q13, d1, d19 // (left flipped) + vmlal.s16 q14, d0, d18 + vmlal.s16 q15, d0, d19 + vmlal.s16 q12, d16, d20 // += (top-bottom)*weights_ver + vmlal.s16 q13, d17, d20 + vmlal.s16 q14, d16, d22 + vmlal.s16 q15, d17, d22 + vrshrn.i32 d24, q12, #9 + vrshrn.i32 d25, q13, #9 + vrshrn.i32 d26, q14, #9 + vrshrn.i32 d27, q15, #9 + subs r3, r3, #8 + vst1.16 {q12}, [r0, :128]! + vst1.16 {q13}, [r6, :128]! + bgt 2b + subs r4, r4, #2 + ble 9f + sub r8, r8, r9, lsl #1 + sub r10, r10, r9 + add r0, r0, r1 + add r6, r6, r1 + mov r3, r9 + b 1b +9: + pop {r4-r10, pc} +endfunc + +// void ipred_smooth_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_16bpc_neon, export=1 + push {r4-r7, lr} + ldr r4, [sp, #20] + movrel r7, X(sm_weights) + add r7, r7, r4 + clz lr, r3 + adr r5, L(ipred_smooth_v_tbl) + sub r12, r2, r4, lsl #1 + sub lr, lr, #25 + ldr lr, [r5, lr, lsl #2] + vld1.16 {d4[], d5[]}, [r12] // bottom + add r2, r2, #2 + add r5, r5, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_v_tbl): + .word 640f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_v_tbl) + CONFIG_THUMB + +40: + vld1.16 {d6}, [r2] // top + vsub.i16 d6, d6, d4 // top-bottom + vmov d7, d6 +4: + vld4.8 {d16[], d17[], d18[], d19[]}, [r7, :32]! // weights_ver + vzip.32 d16, d17 // weights_ver + vzip.32 d18, d19 + vshll.u8 q8, d16, #7 // weights_ver << 7 + vshll.u8 q9, d18, #7 + vqrdmulh.s16 q10, q3, q8 // ((top-bottom)*weights_ver + 128) >> 8 + vqrdmulh.s16 q11, q3, q9 + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q2 + vst1.16 {d20}, [r0, :64], r1 + vst1.16 {d21}, [r6, :64], r1 + subs r4, r4, #4 + vst1.16 {d22}, [r0, :64], r1 + vst1.16 {d23}, [r6, :64], r1 + bgt 4b + pop {r4-r7, pc} +80: + vld1.16 {q3}, [r2] // top + vsub.i16 q3, q3, q2 // top-bottom +8: + vld4.8 {d16[], d18[], d20[], d22[]}, [r7, :32]! // weights_ver + vshll.u8 q8, d16, #7 // weights_ver << 7 + vshll.u8 q9, d18, #7 + vshll.u8 q10, d20, #7 + vshll.u8 q11, d22, #7 + vqrdmulh.s16 q8, q3, q8 // ((top-bottom)*weights_ver + 128) >> 8 + vqrdmulh.s16 q9, q3, q9 + vqrdmulh.s16 q10, q3, q10 + vqrdmulh.s16 q11, q3, q11 + vadd.i16 q8, q8, q2 + vadd.i16 q9, q9, q2 + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q2 + vst1.16 {q8}, [r0, :128], r1 + vst1.16 {q9}, [r6, :128], r1 + subs r4, r4, #4 + vst1.16 {q10}, [r0, :128], r1 + vst1.16 {q11}, [r6, :128], r1 + bgt 8b + pop {r4-r7, pc} +160: +320: +640: + vpush {q4-q7} + // Set up pointers for four rows in parallel; r0, r6, r5, lr + add r5, r0, r1 + add lr, r6, r1 + lsl r1, r1, #1 + sub r1, r1, r3, lsl #1 + mov r12, r3 + +1: + vld4.8 {d8[], d10[], d12[], d14[]}, [r7, :32]! // weights_ver + vshll.u8 q4, d8, #7 // weights_ver << 7 + vshll.u8 q5, d10, #7 + vshll.u8 q6, d12, #7 + vshll.u8 q7, d14, #7 +2: + vld1.16 {q0, q1}, [r2]! // top + vsub.i16 q0, q0, q2 // top-bottom + vsub.i16 q1, q1, q2 + vqrdmulh.s16 q8, q0, q4 // ((top-bottom)*weights_ver + 128) >> 8 + vqrdmulh.s16 q9, q1, q4 + vqrdmulh.s16 q10, q0, q5 + vqrdmulh.s16 q11, q1, q5 + vqrdmulh.s16 q12, q0, q6 + vqrdmulh.s16 q13, q1, q6 + vqrdmulh.s16 q14, q0, q7 + vqrdmulh.s16 q15, q1, q7 + vadd.i16 q8, q8, q2 + vadd.i16 q9, q9, q2 + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q2 + vadd.i16 q12, q12, q2 + vadd.i16 q13, q13, q2 + vadd.i16 q14, q14, q2 + vadd.i16 q15, q15, q2 + subs r3, r3, #16 + vst1.16 {q8, q9}, [r0, :128]! + vst1.16 {q10, q11}, [r6, :128]! + vst1.16 {q12, q13}, [r5, :128]! + vst1.16 {q14, q15}, [lr, :128]! + bgt 2b + subs r4, r4, #4 + ble 9f + sub r2, r2, r12, lsl #1 + add r0, r0, r1 + add r6, r6, r1 + add r5, r5, r1 + add lr, lr, r1 + mov r3, r12 + b 1b +9: + vpop {q4-q7} + pop {r4-r7, pc} +endfunc + +// void ipred_smooth_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_16bpc_neon, export=1 + push {r4-r8, lr} + ldr r4, [sp, #24] + movrel r8, X(sm_weights) + add r8, r8, r3 + clz lr, r3 + adr r5, L(ipred_smooth_h_tbl) + add r12, r2, r3, lsl #1 + sub lr, lr, #25 + ldr lr, [r5, lr, lsl #2] + vld1.16 {d4[], d5[]}, [r12] // right + add r5, r5, lr + add r6, r0, r1 + lsl r1, r1, #1 + bx r5 + + .align 2 +L(ipred_smooth_h_tbl): + .word 640f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 320f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 160f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 80f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + .word 40f - L(ipred_smooth_h_tbl) + CONFIG_THUMB + +40: + vld1.32 {d6[]}, [r8, :32] // weights_hor + sub r2, r2, #8 + mov r7, #-8 + vshll.u8 q3, d6, #7 // weights_hor << 7 +4: + vld4.16 {d0[], d1[], d2[], d3[]}, [r2, :64], r7 // left + vsub.i16 q0, q0, q2 // left-right + vsub.i16 q1, q1, q2 + subs r4, r4, #4 + vqrdmulh.s16 q8, q1, q3 // ((left-right)*weights_hor + 128) >> 8 + vqrdmulh.s16 q9, q0, q3 // (left flipped) + vadd.i16 q8, q8, q2 + vadd.i16 q9, q9, q2 + vst1.16 {d17}, [r0, :64], r1 + vst1.16 {d16}, [r6, :64], r1 + vst1.16 {d19}, [r0, :64], r1 + vst1.16 {d18}, [r6, :64], r1 + bgt 4b + pop {r4-r8, pc} +80: + vld1.8 {d6}, [r8, :64] // weights_hor + sub r2, r2, #8 + mov r7, #-8 + vshll.u8 q3, d6, #7 // weights_hor << 7 +8: + vld1.16 {d23}, [r2, :64], r7 // left + subs r4, r4, #4 + vsub.i16 d23, d23, d4 // left-right + vdup.16 q8, d23[3] // flip left + vdup.16 q9, d23[2] + vdup.16 q10, d23[1] + vdup.16 q11, d23[0] + vqrdmulh.s16 q8, q8, q3 // ((left-right)*weights_hor + 128) >> 8 + vqrdmulh.s16 q9, q9, q3 + vqrdmulh.s16 q10, q10, q3 + vqrdmulh.s16 q11, q11, q3 + vadd.i16 q8, q8, q2 + vadd.i16 q9, q9, q2 + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q2 + vst1.16 {q8}, [r0, :128], r1 + vst1.16 {q9}, [r6, :128], r1 + vst1.16 {q10}, [r0, :128], r1 + vst1.16 {q11}, [r6, :128], r1 + bgt 8b + pop {r4-r8, pc} +160: +320: +640: + vpush {q4-q7} + sub r2, r2, #8 + mov r7, #-8 + // Set up pointers for four rows in parallel; r0, r6, r5, lr + add r5, r0, r1 + add lr, r6, r1 + lsl r1, r1, #1 + sub r1, r1, r3, lsl #1 + mov r12, r3 + +1: + vld1.16 {d15}, [r2, :64], r7 // left + vsub.i16 d15, d15, d4 // left-right + vdup.16 q4, d15[3] // flip left + vdup.16 q5, d15[2] + vdup.16 q6, d15[1] + vdup.16 q7, d15[0] +2: + vld1.8 {q1}, [r8, :128]! // weights_hor + subs r3, r3, #16 + vshll.u8 q0, d2, #7 // weights_hor << 7 + vshll.u8 q1, d3, #7 + vqrdmulh.s16 q8, q0, q4 // ((left-right)*weights_hor + 128) >> 8 + vqrdmulh.s16 q9, q1, q4 + vqrdmulh.s16 q10, q0, q5 + vqrdmulh.s16 q11, q1, q5 + vqrdmulh.s16 q12, q0, q6 + vqrdmulh.s16 q13, q1, q6 + vqrdmulh.s16 q14, q0, q7 + vqrdmulh.s16 q15, q1, q7 + vadd.i16 q8, q8, q2 + vadd.i16 q9, q9, q2 + vadd.i16 q10, q10, q2 + vadd.i16 q11, q11, q2 + vadd.i16 q12, q12, q2 + vadd.i16 q13, q13, q2 + vadd.i16 q14, q14, q2 + vadd.i16 q15, q15, q2 + vst1.16 {q8, q9}, [r0, :128]! + vst1.16 {q10, q11}, [r6, :128]! + vst1.16 {q12, q13}, [r5, :128]! + vst1.16 {q14, q15}, [lr, :128]! + bgt 2b + subs r4, r4, #4 + ble 9f + sub r8, r8, r12 + add r0, r0, r1 + add r6, r6, r1 + add r5, r5, r1 + add lr, lr, r1 + mov r3, r12 + b 1b +9: + vpop {q4-q7} + pop {r4-r8, pc} +endfunc + +// void ipred_filter_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height, +// const int bitdepth_max); +.macro filter_fn bpc +function ipred_filter_\bpc\()bpc_neon, export=1 + movw r12, #511 + ldrd r4, r5, [sp, #88] + and r5, r5, r12 // 511 + movrel r6, X(filter_intra_taps) + lsl r5, r5, #6 + add r6, r6, r5 + vld1.8 {d20, d21, d22, d23}, [r6, :128]! + clz lr, r3 + adr r5, L(ipred_filter\bpc\()_tbl) + vld1.8 {d27, d28, d29}, [r6, :64] + sub lr, lr, #26 + ldr lr, [r5, lr, lsl #2] + vmovl.s8 q8, d20 + vmovl.s8 q9, d21 + add r5, r5, lr + vmovl.s8 q10, d22 + vmovl.s8 q11, d23 + add r6, r0, r1 + lsl r1, r1, #1 + vmovl.s8 q12, d27 + vmovl.s8 q13, d28 + vmovl.s8 q14, d29 + mov r7, #-4 + vdup.16 q15, r8 + add r8, r2, #2 + sub r2, r2, #4 +.if \bpc == 10 + vmov.i16 q7, #0 +.endif + bx r5 + + .align 2 +L(ipred_filter\bpc\()_tbl): + .word 320f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB + .word 160f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB + .word 80f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB + .word 40f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB + +40: + vld1.16 {d0}, [r8] // top (0-3) +4: + vld1.16 {d2}, [r2], r7 // left (0-1) + topleft (2) +.if \bpc == 10 + vmul.i16 q2, q9, d0[0] // p1(top[0]) * filter(1) + vmla.i16 q2, q10, d0[1] // p2(top[1]) * filter(2) + vmla.i16 q2, q11, d0[2] // p3(top[2]) * filter(3) + vmla.i16 q2, q12, d0[3] // p4(top[3]) * filter(4) + vmla.i16 q2, q8, d2[2] // p0(topleft) * filter(0) + vmla.i16 q2, q13, d2[1] // p5(left[0]) * filter(5) + vmla.i16 q2, q14, d2[0] // p6(left[1]) * filter(6) + vrshr.s16 q2, q2, #4 + vmax.s16 q2, q2, q7 +.else + vmull.s16 q2, d18, d0[0] // p1(top[0]) * filter(1) + vmlal.s16 q2, d20, d0[1] // p2(top[1]) * filter(2) + vmlal.s16 q2, d22, d0[2] // p3(top[2]) * filter(3) + vmlal.s16 q2, d24, d0[3] // p4(top[3]) * filter(4) + vmlal.s16 q2, d16, d2[2] // p0(topleft) * filter(0) + vmlal.s16 q2, d26, d2[1] // p5(left[0]) * filter(5) + vmlal.s16 q2, d28, d2[0] // p6(left[1]) * filter(6) + vmull.s16 q3, d19, d0[0] // p1(top[0]) * filter(1) + vmlal.s16 q3, d21, d0[1] // p2(top[1]) * filter(2) + vmlal.s16 q3, d23, d0[2] // p3(top[2]) * filter(3) + vmlal.s16 q3, d25, d0[3] // p4(top[3]) * filter(4) + vmlal.s16 q3, d17, d2[2] // p0(topleft) * filter(0) + vmlal.s16 q3, d27, d2[1] // p5(left[0]) * filter(5) + vmlal.s16 q3, d29, d2[0] // p6(left[1]) * filter(6) + vqrshrun.s32 d4, q2, #4 + vqrshrun.s32 d5, q3, #4 +.endif + vmin.s16 q2, q2, q15 + subs r4, r4, #2 + vst1.16 {d4}, [r0, :64], r1 + vst1.16 {d5}, [r6, :64], r1 + vmov d0, d5 // move top from [4-7] to [0-3] + bgt 4b + vpop {q4-q7} + pop {r4-r8, pc} +80: + vld1.16 {q0}, [r8] // top (0-7) +8: + vld1.16 {d2}, [r2], r7 // left (0-1) + topleft (2) +.if \bpc == 10 + vmul.i16 q2, q9, d0[0] // p1(top[0]) * filter(1) + vmla.i16 q2, q10, d0[1] // p2(top[1]) * filter(2) + vmla.i16 q2, q11, d0[2] // p3(top[2]) * filter(3) + vmla.i16 q2, q12, d0[3] // p4(top[3]) * filter(4) + vmla.i16 q2, q8, d2[2] // p0(topleft) * filter(0) + vmla.i16 q2, q13, d2[1] // p5(left[0]) * filter(5) + vmla.i16 q2, q14, d2[0] // p6(left[1]) * filter(6) + vmul.i16 q3, q9, d1[0] // p1(top[0]) * filter(1) + vmla.i16 q3, q10, d1[1] // p2(top[1]) * filter(2) + vmla.i16 q3, q11, d1[2] // p3(top[2]) * filter(3) + vrshr.s16 q2, q2, #4 + vmax.s16 q2, q2, q7 + vmin.s16 q2, q2, q15 + vmla.i16 q3, q12, d1[3] // p4(top[3]) * filter(4) + vmla.i16 q3, q8, d0[3] // p0(topleft) * filter(0) + vmla.i16 q3, q13, d4[3] // p5(left[0]) * filter(5) + vmla.i16 q3, q14, d5[3] // p6(left[1]) * filter(6) + vrshr.s16 q3, q3, #4 + vmax.s16 q3, q3, q7 +.else + vmull.s16 q2, d18, d0[0] // p1(top[0]) * filter(1) + vmlal.s16 q2, d20, d0[1] // p2(top[1]) * filter(2) + vmlal.s16 q2, d22, d0[2] // p3(top[2]) * filter(3) + vmlal.s16 q2, d24, d0[3] // p4(top[3]) * filter(4) + vmlal.s16 q2, d16, d2[2] // p0(topleft) * filter(0) + vmlal.s16 q2, d26, d2[1] // p5(left[0]) * filter(5) + vmlal.s16 q2, d28, d2[0] // p6(left[1]) * filter(6) + vmull.s16 q3, d19, d0[0] // p1(top[0]) * filter(1) + vmlal.s16 q3, d21, d0[1] // p2(top[1]) * filter(2) + vmlal.s16 q3, d23, d0[2] // p3(top[2]) * filter(3) + vmlal.s16 q3, d25, d0[3] // p4(top[3]) * filter(4) + vmlal.s16 q3, d17, d2[2] // p0(topleft) * filter(0) + vmlal.s16 q3, d27, d2[1] // p5(left[0]) * filter(5) + vmlal.s16 q3, d29, d2[0] // p6(left[1]) * filter(6) + vqrshrun.s32 d4, q2, #4 + vmull.s16 q4, d18, d1[0] // p1(top[0]) * filter(1) + vmlal.s16 q4, d20, d1[1] // p2(top[1]) * filter(2) + vmlal.s16 q4, d22, d1[2] // p3(top[2]) * filter(3) + vqrshrun.s32 d5, q3, #4 + vmin.s16 q2, q2, q15 + vmlal.s16 q4, d24, d1[3] // p4(top[3]) * filter(4) + vmlal.s16 q4, d16, d0[3] // p0(topleft) * filter(0) + vmlal.s16 q4, d26, d4[3] // p5(left[0]) * filter(5) + vmlal.s16 q4, d28, d5[3] // p6(left[1]) * filter(6) + vmull.s16 q5, d19, d1[0] // p1(top[0]) * filter(1) + vmlal.s16 q5, d21, d1[1] // p2(top[1]) * filter(2) + vmlal.s16 q5, d23, d1[2] // p3(top[2]) * filter(3) + vmlal.s16 q5, d25, d1[3] // p4(top[3]) * filter(4) + vmlal.s16 q5, d17, d0[3] // p0(topleft) * filter(0) + vmlal.s16 q5, d27, d4[3] // p5(left[0]) * filter(5) + vmlal.s16 q5, d29, d5[3] // p6(left[1]) * filter(6) + vqrshrun.s32 d6, q4, #4 + vqrshrun.s32 d7, q5, #4 +.endif + vmin.s16 q3, q3, q15 + vswp d5, d6 + subs r4, r4, #2 + vst1.16 {q2}, [r0, :128], r1 + vmov q0, q3 + vst1.16 {q3}, [r6, :128], r1 + bgt 8b + vpop {q4-q7} + pop {r4-r8, pc} +160: +320: + sub r1, r1, r3, lsl #1 + mov lr, r3 + +1: + vld1.16 {d0}, [r2], r7 // left (0-1) + topleft (2) +2: + vld1.16 {q1, q2}, [r8]! // top(0-15) +.if \bpc == 10 + vmul.i16 q3, q8, d0[2] // p0(topleft) * filter(0) + vmla.i16 q3, q13, d0[1] // p5(left[0]) * filter(5) + vmla.i16 q3, q14, d0[0] // p6(left[1]) * filter(6) + vmla.i16 q3, q9, d2[0] // p1(top[0]) * filter(1) + vmla.i16 q3, q10, d2[1] // p2(top[1]) * filter(2) + vmla.i16 q3, q11, d2[2] // p3(top[2]) * filter(3) + vmla.i16 q3, q12, d2[3] // p4(top[3]) * filter(4) + + vmul.i16 q4, q9, d3[0] // p1(top[0]) * filter(1) + vmla.i16 q4, q10, d3[1] // p2(top[1]) * filter(2) + vmla.i16 q4, q11, d3[2] // p3(top[2]) * filter(3) + vrshr.s16 q3, q3, #4 + vmax.s16 q3, q3, q7 + vmin.s16 q3, q3, q15 + vmla.i16 q4, q12, d3[3] // p4(top[3]) * filter(4) + vmla.i16 q4, q8, d2[3] // p0(topleft) * filter(0) + vmla.i16 q4, q13, d6[3] // p5(left[0]) * filter(5) + vmla.i16 q4, q14, d7[3] // p6(left[1]) * filter(6) + + vmul.i16 q5, q9, d4[0] // p1(top[0]) * filter(1) + vmla.i16 q5, q10, d4[1] // p2(top[1]) * filter(2) + vmla.i16 q5, q11, d4[2] // p3(top[2]) * filter(3) + vrshr.s16 q4, q4, #4 + vmax.s16 q4, q4, q7 + vmin.s16 q4, q4, q15 + vmov q0, q4 + vmla.i16 q5, q12, d4[3] // p4(top[3]) * filter(4) + vmla.i16 q5, q8, d3[3] // p0(topleft) * filter(0) + vmla.i16 q5, q13, d0[3] // p5(left[0]) * filter(5) + vmla.i16 q5, q14, d1[3] // p6(left[1]) * filter(6) + + vmul.i16 q6, q9, d5[0] // p1(top[0]) * filter(1) + vmla.i16 q6, q10, d5[1] // p2(top[1]) * filter(2) + vmla.i16 q6, q11, d5[2] // p3(top[2]) * filter(3) + vrshr.s16 q5, q5, #4 + vmax.s16 q5, q5, q7 + vmin.s16 q5, q5, q15 + vmov q0, q5 + vmov.u16 r12, d5[3] + vmla.i16 q6, q12, d5[3] // p4(top[3]) * filter(4) + vmla.i16 q6, q8, d4[3] // p0(topleft) * filter(0) + vmla.i16 q6, q13, d0[3] // p5(left[0]) * filter(5) + vmla.i16 q6, q14, d1[3] // p6(left[1]) * filter(6) + vmov.16 d0[2], r12 + subs r3, r3, #16 + vrshr.s16 q6, q6, #4 +.else + vmull.s16 q3, d16, d0[2] // p0(topleft) * filter(0) + vmlal.s16 q3, d26, d0[1] // p5(left[0]) * filter(5) + vmlal.s16 q3, d28, d0[0] // p6(left[1]) * filter(6) + vmlal.s16 q3, d18, d2[0] // p1(top[0]) * filter(1) + vmlal.s16 q3, d20, d2[1] // p2(top[1]) * filter(2) + vmlal.s16 q3, d22, d2[2] // p3(top[2]) * filter(3) + vmlal.s16 q3, d24, d2[3] // p4(top[3]) * filter(4) + vmull.s16 q4, d17, d0[2] // p0(topleft) * filter(0) + vmlal.s16 q4, d27, d0[1] // p5(left[0]) * filter(5) + vmlal.s16 q4, d29, d0[0] // p6(left[1]) * filter(6) + vmlal.s16 q4, d19, d2[0] // p1(top[0]) * filter(1) + vmlal.s16 q4, d21, d2[1] // p2(top[1]) * filter(2) + vmlal.s16 q4, d23, d2[2] // p3(top[2]) * filter(3) + vmlal.s16 q4, d25, d2[3] // p4(top[3]) * filter(4) + vqrshrun.s32 d6, q3, #4 + vmull.s16 q5, d18, d3[0] // p1(top[0]) * filter(1) + vmlal.s16 q5, d20, d3[1] // p2(top[1]) * filter(2) + vqrshrun.s32 d7, q4, #4 + vmin.s16 q3, q3, q15 + vmlal.s16 q5, d22, d3[2] // p3(top[2]) * filter(3) + vmlal.s16 q5, d24, d3[3] // p4(top[3]) * filter(4) + vmlal.s16 q5, d16, d2[3] // p0(topleft) * filter(0) + vmlal.s16 q5, d26, d6[3] // p5(left[0]) * filter(5) + vmlal.s16 q5, d28, d7[3] // p6(left[1]) * filter(6) + vmull.s16 q6, d19, d3[0] // p1(top[0]) * filter(1) + vmlal.s16 q6, d21, d3[1] // p2(top[1]) * filter(2) + vmlal.s16 q6, d23, d3[2] // p3(top[2]) * filter(3) + vmlal.s16 q6, d25, d3[3] // p4(top[3]) * filter(4) + vmlal.s16 q6, d17, d2[3] // p0(topleft) * filter(0) + vmlal.s16 q6, d27, d6[3] // p5(left[0]) * filter(5) + vmlal.s16 q6, d29, d7[3] // p6(left[1]) * filter(6) + vqrshrun.s32 d8, q5, #4 + vmull.s16 q7, d18, d4[0] // p1(top[0]) * filter(1) + vmlal.s16 q7, d20, d4[1] // p2(top[1]) * filter(2) + vmlal.s16 q7, d22, d4[2] // p3(top[2]) * filter(3) + vqrshrun.s32 d9, q6, #4 + vmin.s16 q0, q4, q15 + vmlal.s16 q7, d24, d4[3] // p4(top[3]) * filter(4) + vmlal.s16 q7, d16, d3[3] // p0(topleft) * filter(0) + vmlal.s16 q7, d26, d0[3] // p5(left[0]) * filter(5) + vmlal.s16 q7, d28, d1[3] // p6(left[1]) * filter(6) + vmin.s16 q4, q4, q15 + vmull.s16 q6, d19, d4[0] // p1(top[0]) * filter(1) + vmlal.s16 q6, d21, d4[1] // p2(top[1]) * filter(2) + vmlal.s16 q6, d23, d4[2] // p3(top[2]) * filter(3) + vmlal.s16 q6, d25, d4[3] // p4(top[3]) * filter(4) + vmlal.s16 q6, d17, d3[3] // p0(topleft) * filter(0) + vmlal.s16 q6, d27, d0[3] // p5(left[0]) * filter(5) + vmlal.s16 q6, d29, d1[3] // p6(left[1]) * filter(6) + vqrshrun.s32 d10, q7, #4 + vmull.s16 q1, d18, d5[0] // p1(top[0]) * filter(1) + vmlal.s16 q1, d20, d5[1] // p2(top[1]) * filter(2) + vmlal.s16 q1, d22, d5[2] // p3(top[2]) * filter(3) + vqrshrun.s32 d11, q6, #4 + vmin.s16 q0, q5, q15 + vmlal.s16 q1, d24, d5[3] // p4(top[3]) * filter(4) + vmlal.s16 q1, d16, d4[3] // p0(topleft) * filter(0) + vmlal.s16 q1, d26, d0[3] // p5(left[0]) * filter(5) + vmlal.s16 q1, d28, d1[3] // p6(left[1]) * filter(6) + vmin.s16 q5, q5, q15 + vmov.u16 r12, d5[3] + vmull.s16 q7, d19, d5[0] // p1(top[0]) * filter(1) + vmlal.s16 q7, d21, d5[1] // p2(top[1]) * filter(2) + vmlal.s16 q7, d23, d5[2] // p3(top[2]) * filter(3) + vmlal.s16 q7, d25, d5[3] // p4(top[3]) * filter(4) + vmlal.s16 q7, d17, d4[3] // p0(topleft) * filter(0) + vmlal.s16 q7, d27, d0[3] // p5(left[0]) * filter(5) + vmlal.s16 q7, d29, d1[3] // p6(left[1]) * filter(6) + vmov.16 d0[2], r12 + vqrshrun.s32 d12, q1, #4 + subs r3, r3, #16 + vqrshrun.s32 d13, q7, #4 +.endif + vswp q4, q5 +.if \bpc == 10 + vmax.s16 q6, q6, q7 +.endif + vswp d7, d10 + vmin.s16 q6, q6, q15 + + vswp d9, d12 + + vst1.16 {q3, q4}, [r0, :128]! + vst1.16 {q5, q6}, [r6, :128]! + ble 8f + vmov.u16 r12, d13[3] + vmov.16 d0[0], r12 + vmov.u16 r12, d9[3] + vmov.16 d0[1], r12 + b 2b +8: + subs r4, r4, #2 + + ble 9f + sub r8, r6, lr, lsl #1 + add r0, r0, r1 + add r6, r6, r1 + mov r3, lr + b 1b +9: + vpop {q4-q7} + pop {r4-r8, pc} +endfunc +.endm + +filter_fn 10 +filter_fn 12 + +function ipred_filter_16bpc_neon, export=1 + push {r4-r8, lr} + vpush {q4-q7} + movw r12, 0x3ff + ldr r8, [sp, #104] + cmp r8, r12 + ble ipred_filter_10bpc_neon + b ipred_filter_12bpc_neon +endfunc + +// void pal_pred_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_16bpc_neon, export=1 + push {r4-r5, lr} + ldr r4, [sp, #12] + ldr r5, [sp, #16] + vld1.16 {q14}, [r2, :128] + clz lr, r4 + adr r12, L(pal_pred_tbl) + sub lr, lr, #25 + ldr lr, [r12, lr, lsl #2] + vmov.i16 q15, #0x100 + add r12, r12, lr + add r2, r0, r1 + bx r12 + + .align 2 +L(pal_pred_tbl): + .word 640f - L(pal_pred_tbl) + CONFIG_THUMB + .word 320f - L(pal_pred_tbl) + CONFIG_THUMB + .word 160f - L(pal_pred_tbl) + CONFIG_THUMB + .word 80f - L(pal_pred_tbl) + CONFIG_THUMB + .word 40f - L(pal_pred_tbl) + CONFIG_THUMB + +40: + lsl r1, r1, #1 +4: + vld1.8 {q1}, [r3, :128]! + subs r5, r5, #4 + // Restructure q1 from a, b, c, ... into 2*a, 2*a+1, 2*b, 2*b+1, 2*c, 2*c+1, ... + vadd.i8 q0, q1, q1 + vadd.i8 q1, q1, q1 + vzip.8 q0, q1 + vadd.i16 q0, q0, q15 + vadd.i16 q1, q1, q15 + vtbl.8 d0, {q14}, d0 + vtbl.8 d1, {q14}, d1 + vst1.16 {d0}, [r0, :64], r1 + vtbl.8 d2, {q14}, d2 + vst1.16 {d1}, [r2, :64], r1 + vtbl.8 d3, {q14}, d3 + vst1.16 {d2}, [r0, :64], r1 + vst1.16 {d3}, [r2, :64], r1 + bgt 4b + pop {r4-r5, pc} +80: + lsl r1, r1, #1 +8: + vld1.8 {q1, q2}, [r3, :128]! + subs r5, r5, #4 + // Prefer doing the adds twice, instead of chaining a vmov after + // the add. + vadd.i8 q0, q1, q1 + vadd.i8 q1, q1, q1 + vadd.i8 q3, q2, q2 + vadd.i8 q2, q2, q2 + vzip.8 q0, q1 + vzip.8 q2, q3 + vadd.i16 q0, q0, q15 + vadd.i16 q1, q1, q15 + vtbl.8 d0, {q14}, d0 + vadd.i16 q2, q2, q15 + vtbl.8 d1, {q14}, d1 + vadd.i16 q3, q3, q15 + vtbl.8 d2, {q14}, d2 + vtbl.8 d3, {q14}, d3 + vtbl.8 d4, {q14}, d4 + vtbl.8 d5, {q14}, d5 + vst1.16 {q0}, [r0, :128], r1 + vtbl.8 d6, {q14}, d6 + vst1.16 {q1}, [r2, :128], r1 + vtbl.8 d7, {q14}, d7 + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r2, :128], r1 + bgt 8b + pop {r4-r5, pc} +160: + lsl r1, r1, #1 +16: + vld1.8 {q2, q3}, [r3, :128]! + subs r5, r5, #4 + vld1.8 {q10, q11}, [r3, :128]! + vadd.i8 q0, q2, q2 + vadd.i8 q1, q2, q2 + vadd.i8 q2, q3, q3 + vadd.i8 q3, q3, q3 + vadd.i8 q8, q10, q10 + vadd.i8 q9, q10, q10 + vadd.i8 q10, q11, q11 + vzip.8 q0, q1 + vadd.i8 q11, q11, q11 + vzip.8 q2, q3 + vzip.8 q8, q9 + vadd.i16 q0, q0, q15 + vzip.8 q10, q11 + vadd.i16 q1, q1, q15 + vadd.i16 q2, q2, q15 + vadd.i16 q3, q3, q15 + vadd.i16 q8, q8, q15 + vadd.i16 q9, q9, q15 + vadd.i16 q10, q10, q15 + vtbl.8 d0, {q14}, d0 + vadd.i16 q11, q11, q15 + vtbl.8 d1, {q14}, d1 + vtbl.8 d2, {q14}, d2 + vtbl.8 d3, {q14}, d3 + vtbl.8 d4, {q14}, d4 + vtbl.8 d5, {q14}, d5 + vtbl.8 d6, {q14}, d6 + vtbl.8 d7, {q14}, d7 + vtbl.8 d16, {q14}, d16 + vtbl.8 d17, {q14}, d17 + vtbl.8 d18, {q14}, d18 + vst1.16 {q0, q1}, [r0, :128], r1 + vtbl.8 d19, {q14}, d19 + vtbl.8 d20, {q14}, d20 + vst1.16 {q2, q3}, [r2, :128], r1 + vtbl.8 d21, {q14}, d21 + vtbl.8 d22, {q14}, d22 + vst1.16 {q8, q9}, [r0, :128], r1 + vtbl.8 d23, {q14}, d23 + vst1.16 {q10, q11}, [r2, :128], r1 + bgt 16b + pop {r4-r5, pc} +320: + lsl r1, r1, #1 + sub r1, r1, #32 +32: + vld1.8 {q2, q3}, [r3, :128]! + subs r5, r5, #2 + vld1.8 {q10, q11}, [r3, :128]! + vadd.i8 q0, q2, q2 + vadd.i8 q1, q2, q2 + vadd.i8 q2, q3, q3 + vadd.i8 q3, q3, q3 + vadd.i8 q8, q10, q10 + vadd.i8 q9, q10, q10 + vadd.i8 q10, q11, q11 + vzip.8 q0, q1 + vadd.i8 q11, q11, q11 + vzip.8 q2, q3 + vzip.8 q8, q9 + vadd.i16 q0, q0, q15 + vzip.8 q10, q11 + vadd.i16 q1, q1, q15 + vadd.i16 q2, q2, q15 + vadd.i16 q3, q3, q15 + vadd.i16 q8, q8, q15 + vadd.i16 q9, q9, q15 + vadd.i16 q10, q10, q15 + vtbl.8 d0, {q14}, d0 + vadd.i16 q11, q11, q15 + vtbl.8 d1, {q14}, d1 + vtbl.8 d2, {q14}, d2 + vtbl.8 d3, {q14}, d3 + vtbl.8 d4, {q14}, d4 + vtbl.8 d5, {q14}, d5 + vtbl.8 d6, {q14}, d6 + vtbl.8 d7, {q14}, d7 + vtbl.8 d16, {q14}, d16 + vtbl.8 d17, {q14}, d17 + vtbl.8 d18, {q14}, d18 + vst1.16 {q0, q1}, [r0, :128]! + vtbl.8 d19, {q14}, d19 + vtbl.8 d20, {q14}, d20 + vst1.16 {q2, q3}, [r0, :128], r1 + vtbl.8 d21, {q14}, d21 + vtbl.8 d22, {q14}, d22 + vst1.16 {q8, q9}, [r2, :128]! + vtbl.8 d23, {q14}, d23 + vst1.16 {q10, q11}, [r2, :128], r1 + bgt 32b + pop {r4-r5, pc} +640: + sub r1, r1, #96 +64: + vld1.8 {q2, q3}, [r3, :128]! + subs r5, r5, #1 + vld1.8 {q10, q11}, [r3, :128]! + vadd.i8 q0, q2, q2 + vadd.i8 q1, q2, q2 + vadd.i8 q2, q3, q3 + vadd.i8 q3, q3, q3 + vadd.i8 q8, q10, q10 + vadd.i8 q9, q10, q10 + vadd.i8 q10, q11, q11 + vzip.8 q0, q1 + vadd.i8 q11, q11, q11 + vzip.8 q2, q3 + vzip.8 q8, q9 + vadd.i16 q0, q0, q15 + vzip.8 q10, q11 + vadd.i16 q1, q1, q15 + vadd.i16 q2, q2, q15 + vadd.i16 q3, q3, q15 + vadd.i16 q8, q8, q15 + vadd.i16 q9, q9, q15 + vadd.i16 q10, q10, q15 + vtbl.8 d0, {q14}, d0 + vadd.i16 q11, q11, q15 + vtbl.8 d1, {q14}, d1 + vtbl.8 d2, {q14}, d2 + vtbl.8 d3, {q14}, d3 + vtbl.8 d4, {q14}, d4 + vtbl.8 d5, {q14}, d5 + vtbl.8 d6, {q14}, d6 + vtbl.8 d7, {q14}, d7 + vtbl.8 d16, {q14}, d16 + vtbl.8 d17, {q14}, d17 + vtbl.8 d18, {q14}, d18 + vst1.16 {q0, q1}, [r0, :128]! + vtbl.8 d19, {q14}, d19 + vtbl.8 d20, {q14}, d20 + vst1.16 {q2, q3}, [r0, :128]! + vtbl.8 d21, {q14}, d21 + vtbl.8 d22, {q14}, d22 + vst1.16 {q8, q9}, [r0, :128]! + vtbl.8 d23, {q14}, d23 + vst1.16 {q10, q11}, [r0, :128], r1 + bgt 64b + pop {r4-r5, pc} +endfunc + +// void ipred_cfl_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_128_16bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + clz lr, r3 + vdup.16 q15, r7 // bitdepth_max + adr r12, L(ipred_cfl_128_tbl) + sub lr, lr, #26 + ldr lr, [r12, lr, lsl #2] + vrshr.u16 q0, q15, #1 + vdup.16 q1, r6 // alpha + add r12, r12, lr + add r6, r0, r1 + lsl r1, r1, #1 + vmov.i16 q14, #0 + bx r12 + + .align 2 +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w8) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + .word L(ipred_cfl_splat_w4) - L(ipred_cfl_128_tbl) + CONFIG_THUMB + +L(ipred_cfl_splat_w4): + vld1.16 {q8, q9}, [r5, :128]! + vmull.s16 q2, d16, d2 // diff = ac * alpha + vmull.s16 q3, d17, d3 + vmull.s16 q8, d18, d2 + vmull.s16 q9, d19, d3 + vshr.s32 q10, q2, #31 // sign = diff >> 15 + vshr.s32 q11, q3, #31 + vshr.s32 q12, q8, #31 + vshr.s32 q13, q9, #31 + vadd.i32 q2, q2, q10 // diff + sign + vadd.i32 q3, q3, q11 + vadd.i32 q8, q8, q12 + vadd.i32 q9, q9, q13 + vrshrn.i32 d4, q2, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshrn.i32 d5, q3, #6 + vrshrn.i32 d6, q8, #6 + vrshrn.i32 d7, q9, #6 + vadd.i16 q2, q2, q0 // dc + apply_sign() + vadd.i16 q3, q3, q0 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmin.s16 q2, q2, q15 + vmin.s16 q3, q3, q15 + vst1.16 {d4}, [r0, :64], r1 + vst1.16 {d5}, [r6, :64], r1 + subs r4, r4, #4 + vst1.16 {d6}, [r0, :64], r1 + vst1.16 {d7}, [r6, :64], r1 + bgt L(ipred_cfl_splat_w4) + pop {r4-r8, pc} +L(ipred_cfl_splat_w8): + vld1.16 {q8, q9}, [r5, :128]! + subs r4, r4, #2 + vmull.s16 q2, d16, d2 // diff = ac * alpha + vmull.s16 q3, d17, d3 + vmull.s16 q8, d18, d2 + vmull.s16 q9, d19, d3 + vshr.s32 q10, q2, #31 // sign = diff >> 15 + vshr.s32 q11, q3, #31 + vshr.s32 q12, q8, #31 + vshr.s32 q13, q9, #31 + vadd.i32 q2, q2, q10 // diff + sign + vadd.i32 q3, q3, q11 + vadd.i32 q8, q8, q12 + vadd.i32 q9, q9, q13 + vrshrn.i32 d4, q2, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshrn.i32 d5, q3, #6 + vrshrn.i32 d6, q8, #6 + vrshrn.i32 d7, q9, #6 + vadd.i16 q2, q2, q0 // dc + apply_sign() + vadd.i16 q3, q3, q0 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmin.s16 q2, q2, q15 + vmin.s16 q3, q3, q15 + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r6, :128], r1 + bgt L(ipred_cfl_splat_w8) + pop {r4-r8, pc} +L(ipred_cfl_splat_w16): + vpush {q4-q7} + add r12, r5, r3, lsl #1 + sub r1, r1, r3, lsl #1 + mov lr, r3 +1: + vld1.16 {q6, q7}, [r5, :128]! + vmull.s16 q2, d12, d2 // diff = ac * alpha + vld1.16 {q8, q9}, [r12, :128]! + vmull.s16 q3, d13, d3 + vmull.s16 q4, d14, d2 + vmull.s16 q5, d15, d3 + vmull.s16 q6, d16, d2 + vmull.s16 q7, d17, d3 + vmull.s16 q8, d18, d2 + vmull.s16 q9, d19, d3 + vshr.s32 q10, q2, #31 // sign = diff >> 15 + vshr.s32 q11, q3, #31 + vshr.s32 q12, q4, #31 + vshr.s32 q13, q5, #31 + vadd.i32 q2, q2, q10 // diff + sign + vshr.s32 q10, q6, #31 + vadd.i32 q3, q3, q11 + vshr.s32 q11, q7, #31 + vadd.i32 q4, q4, q12 + vshr.s32 q12, q8, #31 + vadd.i32 q5, q5, q13 + vshr.s32 q13, q9, #31 + vadd.i32 q6, q6, q10 + vadd.i32 q7, q7, q11 + vadd.i32 q8, q8, q12 + vadd.i32 q9, q9, q13 + vrshrn.i32 d4, q2, #6 // (diff + sign + 32) >> 6 = apply_sign() + vrshrn.i32 d5, q3, #6 + vrshrn.i32 d6, q4, #6 + vrshrn.i32 d7, q5, #6 + vadd.i16 q2, q2, q0 // dc + apply_sign() + vrshrn.i32 d8, q6, #6 + vrshrn.i32 d9, q7, #6 + vadd.i16 q3, q3, q0 + vrshrn.i32 d10, q8, #6 + vrshrn.i32 d11, q9, #6 + vadd.i16 q4, q4, q0 + vadd.i16 q5, q5, q0 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmax.s16 q4, q4, q14 + vmax.s16 q5, q5, q14 + vmin.s16 q2, q2, q15 + vmin.s16 q3, q3, q15 + vmin.s16 q4, q4, q15 + vmin.s16 q5, q5, q15 + subs r3, r3, #16 + vst1.16 {q2, q3}, [r0, :128]! + vst1.16 {q4, q5}, [r6, :128]! + bgt 1b + subs r4, r4, #2 + add r5, r5, lr, lsl #1 + add r12, r12, lr, lsl #1 + add r0, r0, r1 + add r6, r6, r1 + mov r3, lr + bgt 1b + vpop {q4-q7} + pop {r4-r8, pc} +endfunc + +// void ipred_cfl_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_top_16bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + clz lr, r3 + vdup.16 q15, r7 // bitdepth_max + adr r12, L(ipred_cfl_top_tbl) + sub lr, lr, #26 + ldr lr, [r12, lr, lsl #2] + vdup.16 q1, r6 // alpha + add r2, r2, #2 + add r12, r12, lr + add r6, r0, r1 + lsl r1, r1, #1 + vmov.i16 q14, #0 + bx r12 + + .align 2 +L(ipred_cfl_top_tbl): + .word 32f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 16f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 8f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + .word 4f - L(ipred_cfl_top_tbl) + CONFIG_THUMB + +4: + vld1.16 {d0}, [r2] + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w4) +8: + vld1.16 {q0}, [r2] + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w8) +16: + vld1.16 {q2, q3}, [r2] + vadd.i16 q0, q2, q3 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #4 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +32: + vld1.16 {q8, q9}, [r2]! + vld1.16 {q10, q11}, [r2] + vadd.i16 q8, q8, q9 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q8, q10 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpaddl.u16 d0, d0 + vrshrn.i32 d0, q0, #5 + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +endfunc + +// void ipred_cfl_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_left_16bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + sub r2, r2, r4, lsl #1 + clz lr, r3 + clz r8, r4 + vdup.16 q15, r7 // bitdepth_max + adr r12, L(ipred_cfl_splat_tbl) + adr r7, L(ipred_cfl_left_tbl) + sub lr, lr, #26 + sub r8, r8, #26 + ldr lr, [r12, lr, lsl #2] + ldr r8, [r7, r8, lsl #2] + vdup.16 q1, r6 // alpha + add r12, r12, lr + add r7, r7, r8 + add r6, r0, r1 + lsl r1, r1, #1 + vmov.i16 q14, #0 + bx r7 + + .align 2 +L(ipred_cfl_left_tbl): + .word L(ipred_cfl_left_h32) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h16) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h8) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + .word L(ipred_cfl_left_h4) - L(ipred_cfl_left_tbl) + CONFIG_THUMB + +L(ipred_cfl_left_h4): + vld1.16 {d0}, [r2, :64] + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #2 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h8): + vld1.16 {q0}, [r2, :128] + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #3 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h16): + vld1.16 {q2, q3}, [r2, :128] + vadd.i16 q0, q2, q3 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpadd.i16 d0, d0, d0 + vrshr.u16 d0, d0, #4 + vdup.16 q0, d0[0] + bx r12 + +L(ipred_cfl_left_h32): + vld1.16 {q8, q9}, [r2, :128]! + vld1.16 {q10, q11}, [r2, :128] + vadd.i16 q8, q8, q9 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q8, q10 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + vpaddl.u16 d0, d0 + vrshrn.i32 d0, q0, #5 + vdup.16 q0, d0[0] + bx r12 +endfunc + +// void ipred_cfl_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_16bpc_neon, export=1 + push {r4-r8, lr} + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #32] + sub r2, r2, r4, lsl #1 + add r8, r3, r4 // width + height + vdup.16 q1, r6 // alpha + clz lr, r3 + clz r6, r4 + vdup.32 d16, r8 // width + height + vdup.16 q15, r7 // bitdepth_max + adr r7, L(ipred_cfl_tbl) + rbit r8, r8 // rbit(width + height) + sub lr, lr, #22 // 26 leading bits, minus table offset 4 + sub r6, r6, #26 + clz r8, r8 // ctz(width + height) + ldr lr, [r7, lr, lsl #2] + ldr r6, [r7, r6, lsl #2] + neg r8, r8 // -ctz(width + height) + add r12, r7, lr + add r7, r7, r6 + vshr.u32 d16, d16, #1 // (width + height) >> 1 + vdup.32 d17, r8 // -ctz(width + height) + add r6, r0, r1 + lsl r1, r1, #1 + vmov.i16 q14, #0 + bx r7 + + .align 2 +L(ipred_cfl_tbl): + .word L(ipred_cfl_h32) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h16) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h8) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_h4) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w32) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w16) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w8) - L(ipred_cfl_tbl) + CONFIG_THUMB + .word L(ipred_cfl_w4) - L(ipred_cfl_tbl) + CONFIG_THUMB + +L(ipred_cfl_h4): + vld1.16 {d0}, [r2, :64]! + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r12 +L(ipred_cfl_w4): + vld1.16 {d1}, [r2] + vadd.i32 d0, d0, d16 + vpadd.i16 d1, d1, d1 + vpaddl.u16 d1, d1 + cmp r4, #4 + vadd.i32 d0, d0, d1 + vshl.u32 d0, d0, d17 + beq 1f + // h = 8/16 + cmp r4, #16 + movw lr, #0x6667 + movw r8, #0xAAAB + it ne + movne lr, r8 + vdup.32 d18, lr + vmul.i32 d0, d0, d18 + vshr.u32 d0, d0, #17 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + vld1.16 {q0}, [r2, :128]! + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r12 +L(ipred_cfl_w8): + vld1.16 {q2}, [r2] + vadd.i32 d0, d0, d16 + vadd.i16 d1, d4, d5 + vpadd.i16 d1, d1, d1 + vpaddl.u16 d1, d1 + cmp r4, #8 + vadd.i32 d0, d0, d1 + vshl.u32 d0, d0, d17 + beq 1f + // h = 4/16/32 + cmp r4, #32 + movw lr, #0x6667 + movw r8, #0xAAAB + it ne + movne lr, r8 + vdup.32 d18, lr + vmul.i32 d0, d0, d18 + vshr.u32 d0, d0, #17 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + vld1.16 {q2, q3}, [r2, :128]! + vadd.i16 q0, q2, q3 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r12 +L(ipred_cfl_w16): + vld1.16 {q2, q3}, [r2] + vadd.i32 d0, d0, d16 + vadd.i16 q2, q2, q3 + vadd.i16 d1, d4, d5 + vpadd.i16 d1, d1, d1 + vpaddl.u16 d1, d1 + cmp r4, #16 + vadd.i32 d0, d0, d1 + vshl.u32 d0, d0, d17 + beq 1f + // h = 4/8/32/64 + tst r4, #(32+16+8) // 16 added to make a consecutive bitmask + movw lr, #0x6667 + movw r8, #0xAAAB + it ne + movne lr, r8 + vdup.32 d18, lr + vmul.i32 d0, d0, d18 + vshr.u32 d0, d0, #17 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + vld1.16 {q2, q3}, [r2, :128]! + vld1.16 {q10, q11}, [r2, :128]! + vadd.i16 q2, q2, q3 + vadd.i16 q10, q10, q11 + vadd.i16 q0, q2, q10 + vadd.i16 d0, d0, d1 + vpadd.i16 d0, d0, d0 + add r2, r2, #2 + vpaddl.u16 d0, d0 + bx r12 +L(ipred_cfl_w32): + vld1.16 {q2, q3}, [r2]! + vadd.i32 d0, d0, d16 + vld1.16 {q10, q11}, [r2]! + vadd.i16 q2, q2, q3 + vadd.i16 q10, q10, q11 + vadd.i16 q2, q2, q10 + vadd.i16 d1, d4, d5 + vpadd.i16 d1, d1, d1 + vpaddl.u16 d1, d1 + cmp r4, #32 + vadd.i32 d0, d0, d1 + vshl.u32 d0, d0, d17 + beq 1f + // h = 8/16/64 + cmp r4, #8 + movw lr, #0x6667 + movw r8, #0xAAAB + it ne + movne lr, r8 + vdup.32 d18, lr + vmul.i32 d0, d0, d18 + vshr.u32 d0, d0, #17 +1: + vdup.16 q0, d0[0] + b L(ipred_cfl_splat_w16) +endfunc + +// void cfl_ac_420_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_16bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_420_tbl) + sub r8, r8, #27 + ldr r8, [r7, r8, lsl #2] + vmov.i32 q8, #0 + vmov.i32 q9, #0 + vmov.i32 q10, #0 + vmov.i32 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_420_tbl): + .word L(ipred_cfl_ac_420_w16) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w8) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w4) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_420_w4): +1: // Copy and subsample input + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q1}, [r12, :128], r2 + vld1.16 {q2}, [r1, :128], r2 + vld1.16 {q3}, [r12, :128], r2 + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d4, d5 + vshl.i16 q0, q0, #1 + subs r8, r8, #2 + vst1.16 {q0}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + bgt 1b + cmp r4, #0 + vmov d0, d1 + vmov d2, d1 + vmov d3, d1 +L(ipred_cfl_ac_420_w4_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 2b +3: +L(ipred_cfl_ac_420_w4_calc_subtract_dc): + // Aggregate the sums + vadd.i32 q8, q8, q9 + vadd.i32 q10, q10, q11 + vadd.i32 q0, q8, q10 + vadd.i32 d0, d0, d1 + vpadd.i32 d0, d0, d0 // sum + sub r0, r0, r6, lsl #3 + vrshl.u32 d16, d0, d31 // (sum + (1 << (log2sz - 1))) >>= log2sz + vdup.16 q8, d16[0] +6: // Subtract dc from ac + vld1.16 {q0, q1}, [r0, :128] + subs r6, r6, #4 + vsub.i16 q0, q0, q8 + vsub.i16 q1, q1, q8 + vst1.16 {q0, q1}, [r0, :128]! + bgt 6b + pop {r4-r8, pc} + +L(ipred_cfl_ac_420_w8): + cmp r3, #0 + bne L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + vld1.16 {q0, q1}, [r1, :128], r2 + vld1.16 {q2, q3}, [r12, :128], r2 + vld1.16 {q12, q13}, [r1, :128], r2 + vadd.i16 q0, q0, q2 + vadd.i16 q1, q1, q3 + vld1.16 {q2, q3}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vadd.i16 q12, q12, q2 + vadd.i16 q13, q13, q3 + vpadd.i16 d2, d24, d25 + vpadd.i16 d3, d26, d27 + vshl.i16 q0, q0, #1 + vshl.i16 q1, q1, #1 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + vmov q0, q1 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q1}, [r12, :128], r2 + vld1.16 {q2}, [r1, :128], r2 + vld1.16 {q3}, [r12, :128], r2 + vadd.i16 q0, q0, q1 + vadd.i16 q2, q2, q3 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d4, d5 + vshl.i16 q0, q0, #1 + vdup.16 d3, d1[3] + vmov d2, d1 + vdup.16 d1, d0[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + vmov q0, q1 + +L(ipred_cfl_ac_420_w8_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 2b +3: + + // Double the height and reuse the w4 summing/subtracting + lsl r6, r6, #1 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_w16): + adr r7, L(ipred_cfl_ac_420_w16_tbl) + ldr r3, [r7, r3, lsl #2] + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_420_w16_tbl): + .word L(ipred_cfl_ac_420_w16_wpad0) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad1) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad2) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_420_w16_wpad3) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_420_w16_wpad0): + sub r2, r2, #32 +1: // Copy and subsample input, without padding + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q12, q13}, [r12, :128]! + vld1.16 {q2, q3}, [r1, :128], r2 + vadd.i16 q0, q0, q12 + vadd.i16 q1, q1, q13 + vld1.16 {q12, q13}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vadd.i16 q2, q2, q12 + vadd.i16 q3, q3, q13 + vpadd.i16 d2, d4, d5 + vpadd.i16 d3, d6, d7 + vshl.i16 q0, q0, #1 + vshl.i16 q1, q1, #1 + subs r8, r8, #1 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): + sub r2, r2, #32 +1: // Copy and subsample input, padding 4 + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q12, q13}, [r12, :128]! + vld1.16 {q2}, [r1, :128], r2 + vadd.i16 q0, q0, q12 + vadd.i16 q1, q1, q13 + vld1.16 {q12}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vadd.i16 q2, q2, q12 + vpadd.i16 d1, d2, d3 + vpadd.i16 d2, d4, d5 + vshl.i16 q0, q0, #1 + vshl.i16 d2, d2, #1 + subs r8, r8, #1 + vdup.16 d3, d2[3] + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): +1: // Copy and subsample input, padding 8 + vld1.16 {q0, q1}, [r1, :128], r2 + vld1.16 {q12, q13}, [r12, :128], r2 + vadd.i16 q0, q0, q12 + vadd.i16 q1, q1, q13 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vshl.i16 q0, q0, #1 + subs r8, r8, #1 + vdup.16 q1, d1[3] + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): +1: // Copy and subsample input, padding 12 + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q12}, [r12, :128], r2 + vadd.i16 q0, q0, q12 + vpadd.i16 d0, d0, d1 + vshl.i16 d0, d0, #1 + subs r8, r8, #1 + vdup.16 q1, d0[3] + vdup.16 d1, d0[3] + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 2b +3: + + // Quadruple the height and reuse the w4 summing/subtracting + lsl r6, r6, #2 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) +endfunc + +// void cfl_ac_422_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_16bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_422_tbl) + sub r8, r8, #27 + ldr r8, [r7, r8, lsl #2] + vmov.i16 q8, #0 + vmov.i16 q9, #0 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_422_tbl): + .word L(ipred_cfl_ac_422_w16) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w8) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w4) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_422_w4): +1: // Copy and subsample input + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q1}, [r12, :128], r2 + vld1.16 {q2}, [r1, :128], r2 + vld1.16 {q3}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vpadd.i16 d2, d4, d5 + vpadd.i16 d3, d6, d7 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + vmov d0, d3 + vmov d1, d3 + vmov d2, d3 + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + cmp r3, #0 + bne L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + vld1.16 {q0, q1}, [r1, :128], r2 + vld1.16 {q2, q3}, [r12, :128], r2 + vld1.16 {q12, q13}, [r1, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vpadd.i16 d2, d4, d5 + vpadd.i16 d3, d6, d7 + vld1.16 {q2, q3}, [r12, :128], r2 + vpadd.i16 d24, d24, d25 + vpadd.i16 d25, d26, d27 + vpadd.i16 d26, d4, d5 + vpadd.i16 d27, d6, d7 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + vshl.i16 q2, q12, #2 + vshl.i16 q3, q13, #2 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q2}, [r12, :128], r2 + vld1.16 {q12}, [r1, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d4, d5 + vld1.16 {q2, q3}, [r12, :128], r2 + vpadd.i16 d24, d24, d25 + vpadd.i16 d25, d4, d5 + vshl.i16 q0, q0, #2 + vshl.i16 q12, q12, #2 + vdup.16 d7, d25[3] + vmov d6, d25 + vdup.16 d5, d24[3] + vmov d4, d24 + vdup.16 d3, d1[3] + vmov d2, d1 + vdup.16 d1, d0[3] + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + adr r7, L(ipred_cfl_ac_422_w16_tbl) + ldr r3, [r7, r3, lsl #2] + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_422_w16_tbl): + .word L(ipred_cfl_ac_422_w16_wpad0) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad1) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad2) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_422_w16_wpad3) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_422_w16_wpad0): + sub r2, r2, #32 +1: // Copy and subsample input, without padding + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q2, q3}, [r12, :128]! + vld1.16 {q12, q13}, [r1, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vpadd.i16 d2, d24, d25 + vpadd.i16 d3, d26, d27 + vld1.16 {q12, q13}, [r12, :128], r2 + vpadd.i16 d4, d4, d5 + vpadd.i16 d5, d6, d7 + vpadd.i16 d6, d24, d25 + vpadd.i16 d7, d26, d27 + vshl.i16 q0, q0, #2 + vshl.i16 q1, q1, #2 + vshl.i16 q2, q2, #2 + vshl.i16 q3, q3, #2 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): + sub r2, r2, #32 +1: // Copy and subsample input, padding 4 + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q2, q3}, [r12, :128]! + vld1.16 {q12}, [r1, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vpadd.i16 d2, d24, d25 + vld1.16 {q12}, [r12, :128], r2 + vpadd.i16 d4, d4, d5 + vpadd.i16 d5, d6, d7 + vpadd.i16 d6, d24, d25 + vshl.i16 q0, q0, #2 + vshl.i16 d2, d2, #2 + vshl.i16 q2, q2, #2 + vshl.i16 d6, d6, #2 + vdup.16 d3, d2[3] + vdup.16 d7, d6[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): +1: // Copy and subsample input, padding 8 + vld1.16 {q0, q1}, [r1, :128], r2 + vld1.16 {q2, q3}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d2, d3 + vpadd.i16 d4, d4, d5 + vpadd.i16 d5, d6, d7 + vshl.i16 q0, q0, #2 + vshl.i16 q2, q2, #2 + vdup.16 q1, d1[3] + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): +1: // Copy and subsample input, padding 12 + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q2}, [r12, :128], r2 + vpadd.i16 d0, d0, d1 + vpadd.i16 d1, d4, d5 + vshl.i16 q0, q0, #2 + vdup.16 q3, d1[3] + vdup.16 q1, d0[3] + vdup.16 d5, d1[3] + vmov d4, d1 + vdup.16 d1, d0[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) +endfunc + +// void cfl_ac_444_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_16bpc_neon, export=1 + push {r4-r8,lr} + ldrd r4, r5, [sp, #24] + ldr r6, [sp, #32] + clz r8, r5 + lsl r4, r4, #2 + adr r7, L(ipred_cfl_ac_444_tbl) + sub r8, r8, #26 + ldr r8, [r7, r8, lsl #2] + vmov.i16 q8, #0 + vmov.i16 q9, #0 + vmov.i16 q10, #0 + vmov.i16 q11, #0 + add r7, r7, r8 + sub r8, r6, r4 // height - h_pad + rbit lr, r5 // rbit(width) + rbit r12, r6 // rbit(height) + clz lr, lr // ctz(width) + clz r12, r12 // ctz(height) + add lr, lr, r12 // log2sz + add r12, r1, r2 + vdup.32 d31, lr + lsl r2, r2, #1 + vneg.s32 d31, d31 // -log2sz + bx r7 + + .align 2 +L(ipred_cfl_ac_444_tbl): + .word L(ipred_cfl_ac_444_w32) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w16) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w8) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w4) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_444_w4): +1: // Copy and expand input + vld1.16 {d0}, [r1, :64], r2 + vld1.16 {d1}, [r12, :64], r2 + vld1.16 {d2}, [r1, :64], r2 + vld1.16 {d3}, [r12, :64], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + bgt 1b + cmp r4, #0 + vmov d0, d3 + vmov d1, d3 + vmov d2, d3 + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): +1: // Copy and expand input + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q1}, [r12, :128], r2 + vld1.16 {q2}, [r1, :128], r2 + vld1.16 {q3}, [r12, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + vshl.i16 q2, q2, #3 + vshl.i16 q3, q3, #3 + subs r8, r8, #4 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q3 + vmov q1, q3 + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + cmp r3, #0 + bne L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + vld1.16 {q0, q1}, [r1, :128], r2 + vld1.16 {q2, q3}, [r12, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + vshl.i16 q2, q2, #3 + vshl.i16 q3, q3, #3 + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + vld1.16 {q0}, [r1, :128], r2 + vld1.16 {q2}, [r12, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q2, q2, #3 + vdup.16 q1, d1[3] + vdup.16 q3, d5[3] + subs r8, r8, #2 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + vmov q0, q2 + vmov q1, q3 + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + adr r7, L(ipred_cfl_ac_444_w32_tbl) + ldr r3, [r7, r3, lsl #1] // (w3>>1) << 2 + asr r2, r2, #1 + add r7, r7, r3 + bx r7 + + .align 2 +L(ipred_cfl_ac_444_w32_tbl): + .word L(ipred_cfl_ac_444_w32_wpad0) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad2) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad4) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + .word L(ipred_cfl_ac_444_w32_wpad6) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB + +L(ipred_cfl_ac_444_w32_wpad0): + sub r2, r2, #32 +1: // Copy and expand input, without padding + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q2, q3}, [r1, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + vshl.i16 q2, q2, #3 + vshl.i16 q3, q3, #3 + subs r8, r8, #1 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): + sub r2, r2, #32 +1: // Copy and expand input, padding 8 + vld1.16 {q0, q1}, [r1, :128]! + vld1.16 {q2}, [r1, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + vshl.i16 q2, q2, #3 + subs r8, r8, #1 + vst1.16 {q0, q1}, [r0, :128]! + vdup.16 q3, d5[3] + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): +1: // Copy and expand input, padding 16 + vld1.16 {q0, q1}, [r1, :128], r2 + vshl.i16 q0, q0, #3 + vshl.i16 q1, q1, #3 + subs r8, r8, #1 + vst1.16 {q0, q1}, [r0, :128]! + vdup.16 q2, d3[3] + vdup.16 q3, d3[3] + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): +1: // Copy and expand input, padding 24 + vld1.16 {q0}, [r1, :128], r2 + vshl.i16 q0, q0, #3 + subs r8, r8, #1 + vdup.16 q1, d1[3] + vst1.16 {q0, q1}, [r0, :128]! + vdup.16 q2, d1[3] + vdup.16 q3, d1[3] + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 1b + cmp r4, #0 + +L(ipred_cfl_ac_444_w32_hpad): + beq 3f // This assumes that all callers already did "cmp r4, #0" +2: // Vertical padding (h_pad > 0) + subs r4, r4, #1 + vst1.16 {q0, q1}, [r0, :128]! + vaddw.u16 q8, q8, d0 + vaddw.u16 q9, q9, d1 + vaddw.u16 q10, q10, d2 + vaddw.u16 q11, q11, d3 + vst1.16 {q2, q3}, [r0, :128]! + vaddw.u16 q8, q8, d4 + vaddw.u16 q9, q9, d5 + vaddw.u16 q10, q10, d6 + vaddw.u16 q11, q11, d7 + bgt 2b +3: + + // Multiply the height by eight and reuse the w4 subtracting + lsl r6, r6, #3 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/itx.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/itx.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3343 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "src/arm/asm.S" +#include "util.S" + +// The exported functions in this file have got the following signature: +// void itxfm_add(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob); + +// Most of the functions use the following register layout: +// r0-r3 external parameters +// r4 function pointer to first transform +// r5 function pointer to second transform +// r6 output parameter for helper function +// r7 input parameter for helper function +// r8 input stride for helper function +// r9 scratch variable for helper functions +// r10-r11 pointer to list of eob thresholds, eob threshold value, +// scratch variables within helper functions (backed up) + +// The SIMD registers most often use the following layout: +// d0-d3 multiplication coefficients +// d4-d7 scratch registers +// d8-d15 unused in some transforms, used for scratch registers in others +// d16-v31 inputs/outputs of transforms + +// Potential further optimizations, that are left unimplemented for now: +// - Trying to keep multiplication coefficients in registers across multiple +// transform functions. (The register layout is designed to potentially +// allow this.) +// - Use a simplified version of the transforms themselves for cases where +// we know a significant number of inputs are zero. E.g. if the eob value +// indicates only a quarter of input values are set, for idct16 and up, +// a significant amount of calculation can be skipped, at the cost of more +// code duplication and special casing. + +const idct_coeffs, align=4 + // idct4 + .short 2896, 2896*8, 1567, 3784 + // idct8 + .short 799, 4017, 3406, 2276 + // idct16 + .short 401, 4076, 3166, 2598 + .short 1931, 3612, 3920, 1189 + // idct32 + .short 201, 4091, 3035, 2751 + .short 1751, 3703, 3857, 1380 + .short 995, 3973, 3513, 2106 + .short 2440, 3290, 4052, 601 +endconst + +const idct64_coeffs, align=4 + .short 101*8, 4095*8, 2967*8, -2824*8 + .short 1660*8, 3745*8, 3822*8, -1474*8 + .short 4076, 401, 4017, 799 + + .short 4036*8, -700*8, 2359*8, 3349*8 + .short 3461*8, -2191*8, 897*8, 3996*8 + .short -3166, -2598, -799, -4017 + + .short 501*8, 4065*8, 3229*8, -2520*8 + .short 2019*8, 3564*8, 3948*8, -1092*8 + .short 3612, 1931, 2276, 3406 + + .short 4085*8, -301*8, 2675*8, 3102*8 + .short 3659*8, -1842*8, 1285*8, 3889*8 + .short -3920, -1189, -3406, -2276 +endconst + +const iadst4_coeffs, align=4 + // .h[4-5] can be interpreted as .s[2] + .short 1321, 3803, 2482, 3344, 3344, 0 +endconst + +const iadst8_coeffs, align=4 + .short 4076, 401, 3612, 1931 + .short 2598, 3166, 1189, 3920 + // idct_coeffs + .short 2896, 0, 1567, 3784, 0, 0, 0, 0 +endconst + +const iadst16_coeffs, align=4 + .short 4091, 201, 3973, 995 + .short 3703, 1751, 3290, 2440 + .short 2751, 3035, 2106, 3513 + .short 1380, 3857, 601, 4052 +endconst + +.macro vmull_vmlal d0, s0, s1, c0, c1 + vmull.s16 \d0, \s0, \c0 + vmlal.s16 \d0, \s1, \c1 +.endm + +.macro vmull_vmlal_8h d0, d1, s0, s1, s2, s3, c0, c1 + vmull.s16 \d0, \s0, \c0 + vmlal.s16 \d0, \s2, \c1 + vmull.s16 \d1, \s1, \c0 + vmlal.s16 \d1, \s3, \c1 +.endm + +.macro vmull_vmlsl d0, s0, s1, c0, c1 + vmull.s16 \d0, \s0, \c0 + vmlsl.s16 \d0, \s1, \c1 +.endm + +.macro vmull_vmlsl_8h d0, d1, s0, s1, s2, s3, c0, c1 + vmull.s16 \d0, \s0, \c0 + vmlsl.s16 \d0, \s2, \c1 + vmull.s16 \d1, \s1, \c0 + vmlsl.s16 \d1, \s3, \c1 +.endm + +.macro vqrshrn_8h d0, d1, s0, s1, shift + vqrshrn.s32 \d0, \s0, \shift + vqrshrn.s32 \d1, \s1, \shift +.endm + +.macro scale_input c, r0, r1, r2 r3, r4, r5, r6, r7 + vqrdmulh.s16 \r0, \r0, \c + vqrdmulh.s16 \r1, \r1, \c +.ifnb \r2 + vqrdmulh.s16 \r2, \r2, \c + vqrdmulh.s16 \r3, \r3, \c +.endif +.ifnb \r4 + vqrdmulh.s16 \r4, \r4, \c + vqrdmulh.s16 \r5, \r5, \c + vqrdmulh.s16 \r6, \r6, \c + vqrdmulh.s16 \r7, \r7, \c +.endif +.endm + +.macro load_add_store load, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src, shiftbits=4 +.ifnb \load + vld1.8 {\load}, [\src, :64], r1 +.endif +.ifnb \shift + vrshr.s16 \shift, \shift, #\shiftbits +.endif +.ifnb \addsrc + vaddw.u8 \adddst, \adddst, \addsrc +.endif +.ifnb \narrowsrc + vqmovun.s16 \narrowdst, \narrowsrc +.endif +.ifnb \store + vst1.8 {\store}, [\dst, :64], r1 +.endif +.endm +.macro load_add_store_8x8 dst, src, shiftbits=4 + mov \src, \dst + load_add_store d2, q8, , , , , , \dst, \src, \shiftbits + load_add_store d3, q9, , , , , , \dst, \src, \shiftbits + load_add_store d4, q10, d2, q8, , , , \dst, \src, \shiftbits + load_add_store d5, q11, d3, q9, q8, d2, , \dst, \src, \shiftbits + load_add_store d6, q12, d4, q10, q9, d3, d2, \dst, \src, \shiftbits + load_add_store d7, q13, d5, q11, q10, d4, d3, \dst, \src, \shiftbits + load_add_store d2, q14, d6, q12, q11, d5, d4, \dst, \src, \shiftbits + load_add_store d3, q15, d7, q13, q12, d6, d5, \dst, \src, \shiftbits + load_add_store , , d2, q14, q13, d7, d6, \dst, \src, \shiftbits + load_add_store , , d3, q15, q14, d2, d7, \dst, \src, \shiftbits + load_add_store , , , , q15, d3, d2, \dst, \src, \shiftbits + load_add_store , , , , , , d3, \dst, \src, \shiftbits +.endm +.macro load_add_store_8x4 dst, src + mov \src, \dst + load_add_store d2, q8, , , , , , \dst, \src + load_add_store d3, q9, , , , , , \dst, \src + load_add_store d4, q10, d2, q8, , , , \dst, \src + load_add_store d5, q11, d3, q9, q8, d2, , \dst, \src + load_add_store , , d4, q10, q9, d3, d2, \dst, \src + load_add_store , , d5, q11, q10, d4, d3, \dst, \src + load_add_store , , , , q11, d5, d4, \dst, \src + load_add_store , , , , , , d5, \dst, \src +.endm +.macro load_add_store4 load, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src +.ifnb \load + vld1.32 {\load[0]}, [\src, :32], r1 +.endif +.ifnb \shift + vrshr.s16 \shift, \shift, #4 +.endif +.ifnb \load + vld1.32 {\load[1]}, [\src, :32], r1 +.endif +.ifnb \addsrc + vaddw.u8 \adddst, \adddst, \addsrc +.endif +.ifnb \store + vst1.32 {\store[0]}, [\dst, :32], r1 +.endif +.ifnb \narrowsrc + vqmovun.s16 \narrowdst, \narrowsrc +.endif +.ifnb \store + vst1.32 {\store[1]}, [\dst, :32], r1 +.endif +.endm +.macro load_add_store_4x16 dst, src + mov \src, \dst + load_add_store4 d0, , , , , , , \dst, \src + load_add_store4 d1, q8, , , , , , \dst, \src + load_add_store4 d2, q9, d0, q8, , , , \dst, \src + load_add_store4 d3, q10, d1, q9, q8, d0, , \dst, \src + load_add_store4 d4, q11, d2, q10, q9, d1, d0, \dst, \src + load_add_store4 d5, q12, d3, q11, q10, d2, d1, \dst, \src + load_add_store4 d6, q13, d4, q12, q11, d3, d2, \dst, \src + load_add_store4 d7, q14, d5, q13, q12, d4, d3, \dst, \src + load_add_store4 , q15, d6, q14, q13, d5, d4, \dst, \src + load_add_store4 , , d7, q15, q14, d6, d5, \dst, \src + load_add_store4 , , , , q15, d7, d6, \dst, \src + load_add_store4 , , , , , , d7, \dst, \src +.endm +.macro load_add_store_4x8 dst, src + mov \src, \dst + load_add_store4 d0, , , , , , , \dst, \src + load_add_store4 d1, q8, , , , , , \dst, \src + load_add_store4 d2, q9, d0, q8, , , , \dst, \src + load_add_store4 d3, q10, d1, q9, q8, d0, , \dst, \src + load_add_store4 , q11, d2, q10, q9, d1, d0, \dst, \src + load_add_store4 , , d3, q11, q10, d2, d1, \dst, \src + load_add_store4 , , , , q11, d3, d2, \dst, \src + load_add_store4 , , , , , , d3, \dst, \src +.endm + +.macro idct_dc w, h, shift + cmp r3, #0 + bne 1f + vmov.i16 d30, #0 + movw r12, #2896*8 + vld1.16 {d16[]}, [r2, :16] + vdup.16 d0, r12 + vqrdmulh.s16 d16, d16, d0[0] + vst1.16 {d30[0]}, [r2, :16] +.if (\w == 2*\h) || (2*\w == \h) + vqrdmulh.s16 d16, d16, d0[0] +.endif +.if \shift > 0 + vrshr.s16 d16, d16, #\shift +.endif + vqrdmulh.s16 d20, d16, d0[0] + mov r3, #\h + vrshr.s16 d16, d20, #4 + vrshr.s16 d17, d20, #4 + b idct_dc_w\w\()_neon +1: +.endm + +function idct_dc_w4_neon +1: + vld1.32 {d0[0]}, [r0, :32], r1 + vld1.32 {d0[1]}, [r0, :32], r1 + vld1.32 {d1[0]}, [r0, :32], r1 + vld1.32 {d1[1]}, [r0, :32], r1 + subs r3, r3, #4 + sub r0, r0, r1, lsl #2 + vaddw.u8 q10, q8, d0 + vqmovun.s16 d0, q10 + vaddw.u8 q11, q8, d1 + vst1.32 {d0[0]}, [r0, :32], r1 + vqmovun.s16 d1, q11 + vst1.32 {d0[1]}, [r0, :32], r1 + vst1.32 {d1[0]}, [r0, :32], r1 + vst1.32 {d1[1]}, [r0, :32], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w8_neon +1: + vld1.8 {d0}, [r0, :64], r1 + vld1.8 {d1}, [r0, :64], r1 + vld1.8 {d2}, [r0, :64], r1 + vaddw.u8 q10, q8, d0 + vld1.8 {d3}, [r0, :64], r1 + sub r0, r0, r1, lsl #2 + subs r3, r3, #4 + vaddw.u8 q11, q8, d1 + vqmovun.s16 d0, q10 + vaddw.u8 q12, q8, d2 + vqmovun.s16 d1, q11 + vaddw.u8 q13, q8, d3 + vst1.8 {d0}, [r0, :64], r1 + vqmovun.s16 d2, q12 + vst1.8 {d1}, [r0, :64], r1 + vqmovun.s16 d3, q13 + vst1.8 {d2}, [r0, :64], r1 + vst1.8 {d3}, [r0, :64], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w16_neon +1: + vld1.8 {q0}, [r0, :128], r1 + vld1.8 {q1}, [r0, :128], r1 + vld1.8 {q2}, [r0, :128], r1 + subs r3, r3, #4 + vaddw.u8 q10, q8, d0 + vaddw.u8 q11, q8, d1 + vld1.8 {q3}, [r0, :128], r1 + vaddw.u8 q12, q8, d2 + vaddw.u8 q13, q8, d3 + sub r0, r0, r1, lsl #2 + vaddw.u8 q14, q8, d4 + vaddw.u8 q15, q8, d5 + vqmovun.s16 d0, q10 + vqmovun.s16 d1, q11 + vaddw.u8 q10, q8, d6 + vaddw.u8 q11, q8, d7 + vqmovun.s16 d2, q12 + vqmovun.s16 d3, q13 + vqmovun.s16 d4, q14 + vqmovun.s16 d5, q15 + vst1.8 {q0}, [r0, :128], r1 + vqmovun.s16 d6, q10 + vqmovun.s16 d7, q11 + vst1.8 {q1}, [r0, :128], r1 + vst1.8 {q2}, [r0, :128], r1 + vst1.8 {q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w32_neon +1: + vld1.8 {q0, q1}, [r0, :128], r1 + subs r3, r3, #2 + vld1.8 {q2, q3}, [r0, :128], r1 + vaddw.u8 q10, q8, d0 + vaddw.u8 q11, q8, d1 + vaddw.u8 q12, q8, d2 + vaddw.u8 q13, q8, d3 + sub r0, r0, r1, lsl #1 + vaddw.u8 q14, q8, d4 + vaddw.u8 q15, q8, d5 + vqmovun.s16 d0, q10 + vqmovun.s16 d1, q11 + vaddw.u8 q10, q8, d6 + vaddw.u8 q11, q8, d7 + vqmovun.s16 d2, q12 + vqmovun.s16 d3, q13 + vqmovun.s16 d4, q14 + vqmovun.s16 d5, q15 + vst1.8 {q0, q1}, [r0, :128], r1 + vqmovun.s16 d6, q10 + vqmovun.s16 d7, q11 + vst1.8 {q2, q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w64_neon + sub r1, r1, #32 +1: + vld1.8 {q0, q1}, [r0, :128]! + subs r3, r3, #1 + vld1.8 {q2, q3}, [r0, :128] + vaddw.u8 q10, q8, d0 + vaddw.u8 q11, q8, d1 + vaddw.u8 q12, q8, d2 + vaddw.u8 q13, q8, d3 + sub r0, r0, #32 + vaddw.u8 q14, q8, d4 + vaddw.u8 q15, q8, d5 + vqmovun.s16 d0, q10 + vqmovun.s16 d1, q11 + vaddw.u8 q10, q8, d6 + vaddw.u8 q11, q8, d7 + vqmovun.s16 d2, q12 + vqmovun.s16 d3, q13 + vqmovun.s16 d4, q14 + vqmovun.s16 d5, q15 + vst1.8 {q0, q1}, [r0, :128]! + vqmovun.s16 d6, q10 + vqmovun.s16 d7, q11 + vst1.8 {q2, q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +.macro iwht4 + vadd.i16 d16, d16, d17 + vsub.i16 d21, d18, d19 + vsub.i16 d20, d16, d21 + vshr.s16 d20, d20, #1 + vsub.i16 d18, d20, d17 + vsub.i16 d17, d20, d19 + vadd.i16 d19, d21, d18 + vsub.i16 d16, d16, d17 +.endm + +.macro idct_4h_x4 r0, r1, r2, r3 + vmull_vmlal q3, \r1, \r3, d0[3], d0[2] + vmull_vmlsl q2, \r1, \r3, d0[2], d0[3] + vmull_vmlal q1, \r0, \r2, d0[0], d0[0] + vqrshrn.s32 d6, q3, #12 + vqrshrn.s32 d7, q2, #12 + vmull_vmlsl q2, \r0, \r2, d0[0], d0[0] + vqrshrn.s32 d2, q1, #12 + vqrshrn.s32 d3, q2, #12 + vqadd.s16 \r0, d2, d6 + vqsub.s16 \r3, d2, d6 + vqadd.s16 \r1, d3, d7 + vqsub.s16 \r2, d3, d7 +.endm + +.macro idct_8h_x4 q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7 + vmull_vmlal_8h q6, q7, \r2, \r3, \r6, \r7, d0[3], d0[2] + vmull_vmlsl_8h q4, q5, \r2, \r3, \r6, \r7, d0[2], d0[3] + vmull_vmlal_8h q2, q3, \r0, \r1, \r4, \r5, d0[0], d0[0] + vqrshrn_8h d12, d13, q6, q7, #12 + vqrshrn_8h d14, d15, q4, q5, #12 + vmull_vmlsl_8h q4, q5, \r0, \r1, \r4, \r5, d0[0], d0[0] + vqrshrn_8h d4, d5, q2, q3, #12 + vqrshrn_8h d6, d7, q4, q5, #12 + vqadd.s16 \q0, q2, q6 + vqsub.s16 \q3, q2, q6 + vqadd.s16 \q1, q3, q7 + vqsub.s16 \q2, q3, q7 +.endm + +function inv_dct_4h_x4_neon, export=1 + movrel_local r12, idct_coeffs + vld1.16 {d0}, [r12, :64] + idct_4h_x4 d16, d17, d18, d19 + bx lr +endfunc + +function inv_dct_8h_x4_neon, export=1 + movrel_local r12, idct_coeffs + vld1.16 {d0}, [r12, :64] + idct_8h_x4 q8, q9, q10, q11, d16, d17, d18, d19, d20, d21, d22, d23 + bx lr +endfunc + +.macro iadst_4x4 o0, o1, o2, o3 + movrel_local r12, iadst4_coeffs + vld1.16 {d0, d1}, [r12, :128] + + vsubl.s16 q1, d16, d18 + vmull.s16 q2, d16, d0[0] + vmlal.s16 q2, d18, d0[1] + vmlal.s16 q2, d19, d0[2] + vmull.s16 q10, d17, d0[3] + vaddw.s16 q1, q1, d19 + vmull.s16 q3, d16, d0[2] + vmlsl.s16 q3, d18, d0[0] + vmlsl.s16 q3, d19, d0[1] + + vadd.s32 q11, q2, q3 + vmul.s32 q1, q1, d1[0] + vadd.s32 q2, q2, q10 + vadd.s32 q3, q3, q10 + vsub.s32 q11, q11, q10 + + vqrshrn.s32 \o0, q2, #12 + vqrshrn.s32 \o2, q1, #12 + vqrshrn.s32 \o1, q3, #12 + vqrshrn.s32 \o3, q11, #12 +.endm + +function inv_adst_4h_x4_neon, export=1 + iadst_4x4 d16, d17, d18, d19 + bx lr +endfunc + +function inv_flipadst_4h_x4_neon, export=1 + iadst_4x4 d19, d18, d17, d16 + bx lr +endfunc + +.macro iadst_8x4 o0, o1, o2, o3, o4, o5, o6, o7 + movrel_local r12, iadst4_coeffs + vld1.16 {d0, d1}, [r12, :128] + + vsubl.s16 q2, d16, d20 + vsubl.s16 q3, d17, d21 + vmull.s16 q4, d16, d0[0] + vmlal.s16 q4, d20, d0[1] + vmlal.s16 q4, d22, d0[2] + vmull.s16 q5, d17, d0[0] + vmlal.s16 q5, d21, d0[1] + vmlal.s16 q5, d23, d0[2] + vaddw.s16 q2, q2, d22 + vaddw.s16 q3, q3, d23 + vmull.s16 q6, d16, d0[2] + vmlsl.s16 q6, d20, d0[0] + vmlsl.s16 q6, d22, d0[1] + vmull.s16 q7, d17, d0[2] + vmlsl.s16 q7, d21, d0[0] + vmlsl.s16 q7, d23, d0[1] + + vmul.s32 q10, q2, d1[0] + vmul.s32 q11, q3, d1[0] + + vmull.s16 q2, d18, d0[3] + vmull.s16 q3, d19, d0[3] + + vadd.s32 q8, q4, q2 // out0 + vadd.s32 q9, q5, q3 + + vadd.s32 q4, q4, q6 // out3 + vadd.s32 q5, q5, q7 + + vadd.s32 q6, q6, q2 // out1 + vadd.s32 q7, q7, q3 + + vsub.s32 q4, q4, q2 // out3 + vsub.s32 q5, q5, q3 + + vqrshrn.s32 d20, q10, #12 + vqrshrn.s32 d21, q11, #12 + + vqrshrn.s32 \o0, q8, #12 + vqrshrn.s32 \o1, q9, #12 + +.ifc \o4, d18 + vmov q9, q10 +.endif + + vqrshrn.s32 \o2, q6, #12 + vqrshrn.s32 \o3, q7, #12 + + vqrshrn.s32 \o6, q4, #12 + vqrshrn.s32 \o7, q5, #12 +.endm + +function inv_adst_8h_x4_neon, export=1 + iadst_8x4 d16, d17, d18, d19, d20, d21, d22, d23 + bx lr +endfunc + +function inv_flipadst_8h_x4_neon, export=1 + iadst_8x4 d22, d23, d20, d21, d18, d19, d16, d17 + bx lr +endfunc + +function inv_identity_4h_x4_neon, export=1 + movw r12, #(5793-4096)*8 + vdup.16 d0, r12 + vqrdmulh.s16 q2, q8, d0[0] + vqrdmulh.s16 q3, q9, d0[0] + vqadd.s16 q8, q8, q2 + vqadd.s16 q9, q9, q3 + bx lr +endfunc + +function inv_identity_8h_x4_neon, export=1 + movw r12, #(5793-4096)*8 + vdup.16 d0, r12 + vqrdmulh.s16 q1, q8, d0[0] + vqrdmulh.s16 q2, q9, d0[0] + vqrdmulh.s16 q3, q10, d0[0] + vqadd.s16 q8, q8, q1 + vqrdmulh.s16 q1, q11, d0[0] + vqadd.s16 q9, q9, q2 + vqadd.s16 q10, q10, q3 + vqadd.s16 q11, q11, q1 + bx lr +endfunc + +.macro identity_8x4_shift1 r0, r1, r2, r3, c +.irp i, \r0, \r1, \r2, \r3 + vqrdmulh.s16 q1, \i, \c + vrhadd.s16 \i, \i, q1 +.endr +.endm + +function inv_txfm_add_wht_wht_4x4_8bpc_neon, export=1 + push {r4-r5,lr} + vmov.i16 q15, #0 + vld1.16 {d16, d17, d18, d19}, [r2, :128] + vst1.16 {q15}, [r2, :128]! + + vshr.s16 q8, q8, #2 + vshr.s16 q9, q9, #2 + + iwht4 + + vst1.16 {q15}, [r2, :128]! + transpose_4x4h q8, q9, d16, d17, d18, d19 + + iwht4 + + vld1.32 {d0[]}, [r0, :32], r1 + vld1.32 {d0[1]}, [r0, :32], r1 + vld1.32 {d1[]}, [r0, :32], r1 + vld1.32 {d1[1]}, [r0, :32], r1 + + b L(itx_4x4_end) +endfunc + +function inv_txfm_add_4x4_neon + vmov.i16 q15, #0 + vld1.16 {d16, d17, d18, d19}, [r2, :128] + vst1.16 {q15}, [r2, :128]! + + blx r4 + + vst1.16 {q15}, [r2, :128]! + transpose_4x4h q8, q9, d16, d17, d18, d19 + + blx r5 + + vld1.32 {d0[]}, [r0, :32], r1 + vld1.32 {d0[1]}, [r0, :32], r1 + vld1.32 {d1[]}, [r0, :32], r1 + vld1.32 {d1[1]}, [r0, :32], r1 + vrshr.s16 q8, q8, #4 + vrshr.s16 q9, q9, #4 + +L(itx_4x4_end): + sub r0, r0, r1, lsl #2 + vaddw.u8 q8, q8, d0 + vqmovun.s16 d0, q8 + vaddw.u8 q9, q9, d1 + vst1.32 {d0[0]}, [r0, :32], r1 + vqmovun.s16 d1, q9 + vst1.32 {d0[1]}, [r0, :32], r1 + vst1.32 {d1[0]}, [r0, :32], r1 + vst1.32 {d1[1]}, [r0, :32], r1 + + pop {r4-r5,pc} +endfunc + +.macro def_fn_4x4 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_4x4_8bpc_neon, export=1 + push {r4-r5,lr} + +.ifc \txfm1\()_\txfm2, dct_dct + cmp r3, #0 + bne 1f + vmov.i16 d30, #0 + movw r12, #2896*8 + vld1.16 {d16[]}, [r2, :16] + vdup.16 d4, r12 + vst1.16 {d30[0]}, [r2, :16] + vqrdmulh.s16 d16, d16, d4[0] + vld1.32 {d0[0]}, [r0, :32], r1 + vqrdmulh.s16 d20, d16, d4[0] + vld1.32 {d0[1]}, [r0, :32], r1 + vrshr.s16 d16, d20, #4 + vrshr.s16 d17, d20, #4 + vld1.32 {d1[0]}, [r0, :32], r1 + vmov q9, q8 + vld1.32 {d1[1]}, [r0, :32], r1 + b L(itx_4x4_end) +1: +.endif + movrel_local r4, inv_\txfm1\()_4h_x4_neon + movrel_local r5, inv_\txfm2\()_4h_x4_neon + b inv_txfm_add_4x4_neon +endfunc +.endm + +def_fn_4x4 dct, dct +def_fn_4x4 identity, identity +def_fn_4x4 dct, adst +def_fn_4x4 dct, flipadst +def_fn_4x4 dct, identity +def_fn_4x4 adst, dct +def_fn_4x4 adst, adst +def_fn_4x4 adst, flipadst +def_fn_4x4 flipadst, dct +def_fn_4x4 flipadst, adst +def_fn_4x4 flipadst, flipadst +def_fn_4x4 identity, dct + +def_fn_4x4 adst, identity +def_fn_4x4 flipadst, identity +def_fn_4x4 identity, adst +def_fn_4x4 identity, flipadst + +.macro idct_8h_x8 q0, q1, q2, q3, q4, q5, q6, q7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15 + idct_8h_x4 \q0, \q2, \q4, \q6, \r0, \r1, \r4, \r5, \r8, \r9, \r12, \r13 + + vmull_vmlsl_8h q2, q3, \r2, \r3, \r14, \r15, d1[0], d1[1] // -> t4a + vmull_vmlal_8h q4, q5, \r2, \r3, \r14, \r15, d1[1], d1[0] // -> t7a + vmull_vmlsl_8h q6, q7, \r10, \r11, \r6, \r7, d1[2], d1[3] // -> t5a + vqrshrn_8h \r2, \r3, q2, q3, #12 // t4a + vqrshrn_8h \r14, \r15, q4, q5, #12 // t7a + vmull_vmlal_8h q2, q3, \r10, \r11, \r6, \r7, d1[3], d1[2] // -> t6a + vqrshrn_8h \r6, \r7, q6, q7, #12 // t5a + vqrshrn_8h \r10, \r11, q2, q3, #12 // t6a + + vqadd.s16 q2, \q1, \q3 // t4 + vqsub.s16 \q1, \q1, \q3 // t5a + vqadd.s16 q3, \q7, \q5 // t7 + vqsub.s16 \q3, \q7, \q5 // t6a + + vmull_vmlsl_8h q4, q5, \r6, \r7, \r2, \r3, d0[0], d0[0] // -> t5 + vmull_vmlal_8h q6, q7, \r6, \r7, \r2, \r3, d0[0], d0[0] // -> t6 + vqrshrn_8h d8, d9, q4, q5, #12 // t5 + vqrshrn_8h d10, d11, q6, q7, #12 // t6 + + vqsub.s16 \q7, \q0, q3 // out7 + vqadd.s16 \q0, \q0, q3 // out0 + vqadd.s16 \q1, \q2, q5 // out1 + vqsub.s16 q6, \q2, q5 // out6 + vqadd.s16 \q2, \q4, q4 // out2 + vqsub.s16 \q5, \q4, q4 // out5 + vqadd.s16 \q3, \q6, q2 // out3 + vqsub.s16 \q4, \q6, q2 // out4 + vmov \q6, q6 // out6 +.endm + +.macro idct_4h_x8 r0, r1, r2, r3, r4, r5, r6, r7 + idct_4h_x4 \r0, \r2, \r4, \r6 + + vmull_vmlsl q1, \r1, \r7, d1[0], d1[1] // -> t4a + vmull_vmlal q2, \r1, \r7, d1[1], d1[0] // -> t7a + vmull_vmlsl q3, \r5, \r3, d1[2], d1[3] // -> t5a + vqrshrn.s32 \r1, q1, #12 // t4a + vmull_vmlal q1, \r5, \r3, d1[3], d1[2] // -> t6a + vqrshrn.s32 \r7, q2, #12 // t7a + vqrshrn.s32 \r3, q3, #12 // t5a + vqrshrn.s32 \r5, q1, #12 // taa + + vqadd.s16 d2, \r1, \r3 // t4 + vqsub.s16 \r1, \r1, \r3 // t5a + vqadd.s16 d3, \r7, \r5 // t7 + vqsub.s16 \r3, \r7, \r5 // t6a + + vmull_vmlsl q2, \r3, \r1, d0[0], d0[0] // -> t5 + vmull_vmlal q3, \r3, \r1, d0[0], d0[0] // -> t6 + vqrshrn.s32 d4, q2, #12 // t5 + vqrshrn.s32 d5, q3, #12 // t6 + + vqsub.s16 \r7, \r0, d3 // out7 + vqadd.s16 \r0, \r0, d3 // out0 + vqadd.s16 \r1, \r2, d5 // out1 + vqsub.s16 d6, \r2, d5 // out6 + vqadd.s16 \r2, \r4, d4 // out2 + vqsub.s16 \r5, \r4, d4 // out5 + vqadd.s16 \r3, \r6, d2 // out3 + vqsub.s16 \r4, \r6, d2 // out4 + vmov \r6, d6 // out6 +.endm + +function inv_dct_8h_x8_neon, export=1 + movrel_local r12, idct_coeffs + vld1.16 {q0}, [r12, :128] + idct_8h_x8 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + bx lr +endfunc + +function inv_dct_4h_x8_neon, export=1 + movrel_local r12, idct_coeffs + vld1.16 {q0}, [r12, :128] + idct_4h_x8 d16, d17, d18, d19, d20, d21, d22, d23 + bx lr +endfunc + +.macro iadst_8h_x8 q0, q1, q2, q3, q4, q5, q6, q7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15 + movrel_local r12, iadst8_coeffs + vld1.16 {d0, d1, d2}, [r12, :64] + + vmull_vmlal_8h q2, q3, d30, d31, d16, d17, d0[0], d0[1] + vmull_vmlsl_8h q4, q5, d30, d31, d16, d17, d0[1], d0[0] + vmull_vmlal_8h q6, q7, d26, d27, d20, d21, d0[2], d0[3] + vqrshrn_8h d16, d17, q2, q3, #12 // t0a + vqrshrn_8h d30, d31, q4, q5, #12 // t1a + vmull_vmlsl_8h q2, q3, d26, d27, d20, d21, d0[3], d0[2] + vmull_vmlal_8h q4, q5, d22, d23, d24, d25, d1[0], d1[1] + vqrshrn_8h d20, d21, q6, q7, #12 // t2a + vqrshrn_8h d26, d27, q2, q3, #12 // t3a + vmull_vmlsl_8h q6, q7, d22, d23, d24, d25, d1[1], d1[0] + vmull_vmlal_8h q2, q3, d18, d19, d28, d29, d1[2], d1[3] + vqrshrn_8h d24, d25, q4, q5, #12 // t4a + vqrshrn_8h d22, d23, q6, q7, #12 // t5a + vmull_vmlsl_8h q4, q5, d18, d19, d28, d29, d1[3], d1[2] + vqrshrn_8h d28, d29, q2, q3, #12 // t6a + vqrshrn_8h d18, d19, q4, q5, #12 // t7a + + vqadd.s16 q2, q8, q12 // t0 + vqsub.s16 q3, q8, q12 // t4 + vqadd.s16 q4, q15, q11 // t1 + vqsub.s16 q5, q15, q11 // t5 + vqadd.s16 q6, q10, q14 // t2 + vqsub.s16 q7, q10, q14 // t6 + vqadd.s16 q10, q13, q9 // t3 + vqsub.s16 q11, q13, q9 // t7 + + vmull_vmlal_8h q8, q9, d6, d7, d10, d11, d2[3], d2[2] + vmull_vmlsl_8h q12, q13, d6, d7, d10, d11, d2[2], d2[3] + vmull_vmlsl_8h q14, q15, d22, d23, d14, d15, d2[3], d2[2] + + vqrshrn_8h d6, d7, q8, q9, #12 // t4a + vqrshrn_8h d10, d11, q12, q13, #12 // t5a + + vmull_vmlal_8h q8, q9, d22, d23, d14, d15, d2[2], d2[3] + + vqrshrn_8h d14, d15, q14, q15, #12 // t6a + vqrshrn_8h d22, d23, q8, q9, #12 // t7a + + vqadd.s16 \q0, q2, q6 // out0 + vqsub.s16 q2, q2, q6 // t2 + vqadd.s16 \q7, q4, q10 // out7 + vqsub.s16 q4, q4, q10 // t3 + vqneg.s16 \q7, \q7 // out7 + + vqadd.s16 \q1, q3, q7 // out1 + vqsub.s16 q3, q3, q7 // t6 + vqadd.s16 \q6, q5, q11 // out6 + vqsub.s16 q5, q5, q11 // t7 + vqneg.s16 \q1, \q1 // out1 + + vmull_vmlal_8h q10, q11, d4, d5, d8, d9, d2[0], d2[0] // -> out3 (q11 or q12) + vmull_vmlsl_8h q6, q7, d4, d5, d8, d9, d2[0], d2[0] // -> out4 (q12 or q11) + vmull_vmlsl_8h q12, q13, d6, d7, d10, d11, d2[0], d2[0] // -> out5 (q13 or q10) + vqrshrn_8h d4, d5, q10, q11, #12 // out3 + vmull_vmlal_8h q10, q11, d6, d7, d10, d11, d2[0], d2[0] // -> out2 (q10 or q13) + vqrshrn_8h d6, d7, q12, q13, #12 // out5 + vqrshrn_8h \r4, \r5, q10, q11, #12 // out2 (q10 or q13) + vqrshrn_8h \r8, \r9, q6, q7, #12 // out4 (q12 or q11) + + vqneg.s16 \q3, q2 // out3 + vqneg.s16 \q5, q3 // out5 +.endm + +.macro iadst_4h_x8 r0, r1, r2, r3, r4, r5, r6, r7 + movrel_local r12, iadst8_coeffs + vld1.16 {d0, d1, d2}, [r12, :64] + + vmull_vmlal q2, d23, d16, d0[0], d0[1] + vmull_vmlsl q3, d23, d16, d0[1], d0[0] + vmull_vmlal q4, d21, d18, d0[2], d0[3] + vqrshrn.s32 d16, q2, #12 // t0a + vqrshrn.s32 d23, q3, #12 // t1a + vmull_vmlsl q5, d21, d18, d0[3], d0[2] + vmull_vmlal q6, d19, d20, d1[0], d1[1] + vqrshrn.s32 d18, q4, #12 // t2a + vqrshrn.s32 d21, q5, #12 // t3a + vmull_vmlsl q7, d19, d20, d1[1], d1[0] + vmull_vmlal q2, d17, d22, d1[2], d1[3] + vqrshrn.s32 d20, q6, #12 // t4a + vqrshrn.s32 d19, q7, #12 // t5a + vmull_vmlsl q3, d17, d22, d1[3], d1[2] + vqrshrn.s32 d22, q2, #12 // t6a + vqrshrn.s32 d17, q3, #12 // t7a + + vqadd.s16 d4, d16, d20 // t0 + vqsub.s16 d5, d16, d20 // t4 + vqadd.s16 d6, d23, d19 // t1 + vqsub.s16 d7, d23, d19 // t5 + vqadd.s16 d8, d18, d22 // t2 + vqsub.s16 d9, d18, d22 // t6 + vqadd.s16 d18, d21, d17 // t3 + vqsub.s16 d19, d21, d17 // t7 + + vmull_vmlal q8, d5, d7, d2[3], d2[2] + vmull_vmlsl q10, d5, d7, d2[2], d2[3] + vmull_vmlsl q11, d19, d9, d2[3], d2[2] + + vqrshrn.s32 d5, q8, #12 // t4a + vqrshrn.s32 d7, q10, #12 // t5a + + vmull_vmlal q8, d19, d9, d2[2], d2[3] + + vqrshrn.s32 d9, q11, #12 // t6a + vqrshrn.s32 d19, q8, #12 // t7a + + vqadd.s16 \r0, d4, d8 // out0 + vqsub.s16 d4, d4, d8 // t2 + vqadd.s16 \r7, d6, d18 // out7 + vqsub.s16 d6, d6, d18 // t3 + vqneg.s16 \r7, \r7 // out7 + + vqadd.s16 \r1, d5, d9 // out1 + vqsub.s16 d5, d5, d9 // t6 + vqadd.s16 \r6, d7, d19 // out6 + vqsub.s16 d7, d7, d19 // t7 + vqneg.s16 \r1, \r1 // out1 + + vmull_vmlal q9, d4, d6, d2[0], d2[0] // -> out3 (d19 or d20) + vmull_vmlsl q4, d4, d6, d2[0], d2[0] // -> out4 (d20 or d19) + vmull_vmlsl q10, d5, d7, d2[0], d2[0] // -> out5 (d21 or d18) + vqrshrn.s32 d4, q9, #12 // out3 + vmull_vmlal q9, d5, d7, d2[0], d2[0] // -> out2 (d18 or d21) + vqrshrn.s32 d5, q10, #12 // out5 + vqrshrn.s32 \r2, q9, #12 // out2 (d18 or d21) + vqrshrn.s32 \r4, q4, #12 // out4 (d20 or d19) + + vqneg.s16 \r3, d4 // out3 + vqneg.s16 \r5, d5 // out5 +.endm + +function inv_adst_8h_x8_neon, export=1 + iadst_8h_x8 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + bx lr +endfunc + +function inv_flipadst_8h_x8_neon, export=1 + iadst_8h_x8 q15, q14, q13, q12, q11, q10, q9, q8, d30, d31, d28, d29, d26, d27, d24, d25, d22, d23, d20, d21, d18, d19, d16, d17 + bx lr +endfunc + +function inv_adst_4h_x8_neon, export=1 + iadst_4h_x8 d16, d17, d18, d19, d20, d21, d22, d23 + bx lr +endfunc + +function inv_flipadst_4h_x8_neon, export=1 + iadst_4h_x8 d23, d22, d21, d20, d19, d18, d17, d16 + bx lr +endfunc + +function inv_identity_8h_x8_neon, export=1 + vqshl.s16 q8, q8, #1 + vqshl.s16 q9, q9, #1 + vqshl.s16 q10, q10, #1 + vqshl.s16 q11, q11, #1 + vqshl.s16 q12, q12, #1 + vqshl.s16 q13, q13, #1 + vqshl.s16 q14, q14, #1 + vqshl.s16 q15, q15, #1 + bx lr +endfunc + +function inv_identity_4h_x8_neon, export=1 + vqshl.s16 q8, q8, #1 + vqshl.s16 q9, q9, #1 + vqshl.s16 q10, q10, #1 + vqshl.s16 q11, q11, #1 + bx lr +endfunc + +.macro def_fn_8x8_base variant +function inv_txfm_\variant\()add_8x8_neon + vmov.i16 q0, #0 + vmov.i16 q1, #0 + vld1.16 {q8, q9}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vld1.16 {q10, q11}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vld1.16 {q12, q13}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vld1.16 {q14, q15}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128] + +.ifc \variant, identity_ + // The identity shl #1 and downshift srshr #1 cancel out +.else + blx r4 + + vrshr.s16 q8, q8, #1 + vrshr.s16 q9, q9, #1 + vrshr.s16 q10, q10, #1 + vrshr.s16 q11, q11, #1 + vrshr.s16 q12, q12, #1 + vrshr.s16 q13, q13, #1 + vrshr.s16 q14, q14, #1 + vrshr.s16 q15, q15, #1 +.endif + + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + + blx r5 + + load_add_store_8x8 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,pc} +endfunc +.endm + +def_fn_8x8_base +def_fn_8x8_base identity_ + +.macro def_fn_8x8 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_8x8_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 8, 8, 1 +.endif + push {r4-r5,r7,lr} + vpush {q4-q7} + movrel_local r5, inv_\txfm2\()_8h_x8_neon +.ifc \txfm1, identity + b inv_txfm_identity_add_8x8_neon +.else + movrel_local r4, inv_\txfm1\()_8h_x8_neon + b inv_txfm_add_8x8_neon +.endif +endfunc +.endm + +def_fn_8x8 dct, dct +def_fn_8x8 identity, identity +def_fn_8x8 dct, adst +def_fn_8x8 dct, flipadst +def_fn_8x8 dct, identity +def_fn_8x8 adst, dct +def_fn_8x8 adst, adst +def_fn_8x8 adst, flipadst +def_fn_8x8 flipadst, dct +def_fn_8x8 flipadst, adst +def_fn_8x8 flipadst, flipadst +def_fn_8x8 identity, dct +def_fn_8x8 adst, identity +def_fn_8x8 flipadst, identity +def_fn_8x8 identity, adst +def_fn_8x8 identity, flipadst + +function inv_txfm_add_8x4_neon + vmov.i16 q14, #0 + vmov.i16 q15, #0 + movw r12, #2896*8 + vdup.16 d0, r12 + vld1.16 {d16, d17, d18, d19}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128]! + vld1.16 {d20, d21, d22, d23}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128] + + scale_input d0[0], q8, q9, q10, q11 + + blx r4 + + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + vswp d17, d20 + vswp d19, d21 + vswp d18, d20 + vswp d21, d22 + + blx r5 + + load_add_store_8x4 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,pc} +endfunc + +function inv_txfm_add_4x8_neon + vmov.i16 q14, #0 + vmov.i16 q15, #0 + movw r12, #2896*8 + vdup.16 d0, r12 + vld1.16 {q8, q9}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128]! + vld1.16 {q10, q11}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128] + + scale_input d0[0], q8, q9, q10, q11 + + blx r4 + + transpose_4x8h q8, q9, q10, q11 + vswp d17, d20 + vswp d19, d21 + vswp d17, d18 + vswp d19, d22 + + blx r5 + + load_add_store_4x8 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,pc} +endfunc + +.macro def_fn_48 w, h, txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 0 +.endif + push {r4-r5,r7,lr} + vpush {q4-q7} + movrel_local r4, inv_\txfm1\()_\h\()h_x\w\()_neon + movrel_local r5, inv_\txfm2\()_\w\()h_x\h\()_neon + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_48 w, h +def_fn_48 \w, \h, dct, dct +def_fn_48 \w, \h, identity, identity +def_fn_48 \w, \h, dct, adst +def_fn_48 \w, \h, dct, flipadst +def_fn_48 \w, \h, dct, identity +def_fn_48 \w, \h, adst, dct +def_fn_48 \w, \h, adst, adst +def_fn_48 \w, \h, adst, flipadst +def_fn_48 \w, \h, flipadst, dct +def_fn_48 \w, \h, flipadst, adst +def_fn_48 \w, \h, flipadst, flipadst +def_fn_48 \w, \h, identity, dct +def_fn_48 \w, \h, adst, identity +def_fn_48 \w, \h, flipadst, identity +def_fn_48 \w, \h, identity, adst +def_fn_48 \w, \h, identity, flipadst +.endm + +def_fns_48 4, 8 +def_fns_48 8, 4 + +function inv_dct_4h_x16_neon, export=1 + movrel_local r12, idct_coeffs + vld1.16 {q0, q1}, [r12, :128] + + vmull_vmlsl q2, d17, d31, d2[0], d2[1] // -> t8a + vmull_vmlal q3, d17, d31, d2[1], d2[0] // -> t15a + vmull_vmlsl q4, d25, d23, d2[2], d2[3] // -> t9a + vqrshrn.s32 d17, q2, #12 // t8a + vqrshrn.s32 d31, q3, #12 // t15a + vmull_vmlal q2, d25, d23, d2[3], d2[2] // -> t14a + vmull_vmlsl q3, d21, d27, d3[0], d3[1] // -> t10a + vqrshrn.s32 d23, q4, #12 // t9a + vqrshrn.s32 d25, q2, #12 // t14a + vmull_vmlal q4, d21, d27, d3[1], d3[0] // -> t13a + vmull_vmlsl q2, d29, d19, d3[2], d3[3] // -> t11a + vqrshrn.s32 d21, q3, #12 // t10a + vqrshrn.s32 d27, q4, #12 // t13a + vmull_vmlal q3, d29, d19, d3[3], d3[2] // -> t12a + vqrshrn.s32 d19, q2, #12 // t11a + vqrshrn.s32 d29, q3, #12 // t12a + + idct_4h_x8 d16, d18, d20, d22, d24, d26, d28, d30 + + vqsub.s16 d4, d17, d23 // t9 + vqadd.s16 d17, d17, d23 // t8 + vqsub.s16 d5, d31, d25 // t14 + vqadd.s16 d31, d31, d25 // t15 + vqsub.s16 d23, d19, d21 // t10 + vqadd.s16 d19, d19, d21 // t11 + vqadd.s16 d25, d29, d27 // t12 + vqsub.s16 d29, d29, d27 // t13 + + vmull_vmlsl q3, d5, d4, d0[2], d0[3] // -> t9a + vmull_vmlal q4, d5, d4, d0[3], d0[2] // -> t14a + vqrshrn.s32 d21, q3, #12 // t9a + vqrshrn.s32 d27, q4, #12 // t14a + + vmull_vmlsl q3, d29, d23, d0[2], d0[3] // -> t13a + vmull_vmlal q4, d29, d23, d0[3], d0[2] // -> t10a + vqrshrn.s32 d29, q3, #12 // t13a + vneg.s32 q4, q4 + vqrshrn.s32 d23, q4, #12 // t10a + + vqsub.s16 d4, d17, d19 // t11a + vqadd.s16 d17, d17, d19 // t8a + vqsub.s16 d5, d31, d25 // t12a + vqadd.s16 d31, d31, d25 // t15a + vqadd.s16 d19, d21, d23 // t9 + vqsub.s16 d21, d21, d23 // t10 + vqsub.s16 d25, d27, d29 // t13 + vqadd.s16 d27, d27, d29 // t14 + + vmull_vmlsl q3, d5, d4, d0[0], d0[0] // -> t11 + vmull_vmlal q4, d5, d4, d0[0], d0[0] // -> t12 + vmull_vmlsl q2, d25, d21, d0[0], d0[0] // -> t10a + + vqrshrn.s32 d6, q3, #12 // t11 + vqrshrn.s32 d7, q4, #12 // t12 + vmull_vmlal q4, d25, d21, d0[0], d0[0] // -> t13a + vqrshrn.s32 d4, q2, #12 // t10a + vqrshrn.s32 d5, q4, #12 // t13a + + vqadd.s16 d8, d16, d31 // out0 + vqsub.s16 d31, d16, d31 // out15 + vmov d16, d8 + vqadd.s16 d23, d30, d17 // out7 + vqsub.s16 d9, d30, d17 // out8 + vqadd.s16 d17, d18, d27 // out1 + vqsub.s16 d30, d18, d27 // out14 + vqadd.s16 d18, d20, d5 // out2 + vqsub.s16 d29, d20, d5 // out13 + vqadd.s16 d5, d28, d19 // out6 + vqsub.s16 d25, d28, d19 // out9 + vqadd.s16 d19, d22, d7 // out3 + vqsub.s16 d28, d22, d7 // out12 + vqadd.s16 d20, d24, d6 // out4 + vqsub.s16 d27, d24, d6 // out11 + vqadd.s16 d21, d26, d4 // out5 + vqsub.s16 d26, d26, d4 // out10 + vmov d24, d9 + vmov d22, d5 + + bx lr +endfunc + +.macro iadst_16 o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15 + movrel_local r12, iadst16_coeffs + vld1.16 {q0, q1}, [r12, :128] + movrel_local r12, idct_coeffs + + vmull_vmlal q2, d31, d16, d0[0], d0[1] // -> t0 + vmull_vmlsl q3, d31, d16, d0[1], d0[0] // -> t1 + vmull_vmlal q4, d29, d18, d0[2], d0[3] // -> t2 + vqrshrn.s32 d16, q2, #12 // t0 + vqrshrn.s32 d31, q3, #12 // t1 + vmull_vmlsl q2, d29, d18, d0[3], d0[2] // -> t3 + vmull_vmlal q3, d27, d20, d1[0], d1[1] // -> t4 + vqrshrn.s32 d18, q4, #12 // t2 + vqrshrn.s32 d29, q2, #12 // t3 + vmull_vmlsl q4, d27, d20, d1[1], d1[0] // -> t5 + vmull_vmlal q2, d25, d22, d1[2], d1[3] // -> t6 + vqrshrn.s32 d20, q3, #12 // t4 + vqrshrn.s32 d27, q4, #12 // t5 + vmull_vmlsl q3, d25, d22, d1[3], d1[2] // -> t7 + vmull_vmlal q4, d23, d24, d2[0], d2[1] // -> t8 + vqrshrn.s32 d22, q2, #12 // t6 + vqrshrn.s32 d25, q3, #12 // t7 + vmull_vmlsl q2, d23, d24, d2[1], d2[0] // -> t9 + vmull_vmlal q3, d21, d26, d2[2], d2[3] // -> t10 + vqrshrn.s32 d23, q4, #12 // t8 + vqrshrn.s32 d24, q2, #12 // t9 + vmull_vmlsl q4, d21, d26, d2[3], d2[2] // -> t11 + vmull_vmlal q2, d19, d28, d3[0], d3[1] // -> t12 + vqrshrn.s32 d21, q3, #12 // t10 + vqrshrn.s32 d26, q4, #12 // t11 + vmull_vmlsl q3, d19, d28, d3[1], d3[0] // -> t13 + vmull_vmlal q4, d17, d30, d3[2], d3[3] // -> t14 + vqrshrn.s32 d19, q2, #12 // t12 + vqrshrn.s32 d28, q3, #12 // t13 + vmull_vmlsl q2, d17, d30, d3[3], d3[2] // -> t15 + vqrshrn.s32 d17, q4, #12 // t14 + vqrshrn.s32 d30, q2, #12 // t15 + + vld1.16 {q0}, [r12, :128] + + vqsub.s16 d2, d16, d23 // t8a + vqadd.s16 d16, d16, d23 // t0a + vqsub.s16 d3, d31, d24 // t9a + vqadd.s16 d31, d31, d24 // t1a + vqadd.s16 d23, d18, d21 // t2a + vqsub.s16 d18, d18, d21 // t10a + vqadd.s16 d24, d29, d26 // t3a + vqsub.s16 d29, d29, d26 // t11a + vqadd.s16 d21, d20, d19 // t4a + vqsub.s16 d20, d20, d19 // t12a + vqadd.s16 d26, d27, d28 // t5a + vqsub.s16 d27, d27, d28 // t13a + vqadd.s16 d19, d22, d17 // t6a + vqsub.s16 d22, d22, d17 // t14a + vqadd.s16 d28, d25, d30 // t7a + vqsub.s16 d25, d25, d30 // t15a + + vmull_vmlal q2, d2, d3, d1[1], d1[0] // -> t8 + vmull_vmlsl q3, d2, d3, d1[0], d1[1] // -> t9 + vmull_vmlal q4, d18, d29, d1[3], d1[2] // -> t10 + vqrshrn.s32 d17, q2, #12 // t8 + vqrshrn.s32 d30, q3, #12 // t9 + vmull_vmlsl q2, d18, d29, d1[2], d1[3] // -> t11 + vmull_vmlsl q3, d27, d20, d1[1], d1[0] // -> t12 + vqrshrn.s32 d18, q4, #12 // t10 + vqrshrn.s32 d29, q2, #12 // t11 + vmull_vmlal q4, d27, d20, d1[0], d1[1] // -> t13 + vmull_vmlsl q2, d25, d22, d1[3], d1[2] // -> t14 + vqrshrn.s32 d27, q3, #12 // t12 + vqrshrn.s32 d20, q4, #12 // t13 + vmull_vmlal q3, d25, d22, d1[2], d1[3] // -> t15 + vqrshrn.s32 d25, q2, #12 // t14 + vqrshrn.s32 d22, q3, #12 // t15 + + vqsub.s16 d2, d16, d21 // t4 + vqadd.s16 d16, d16, d21 // t0 + vqsub.s16 d3, d31, d26 // t5 + vqadd.s16 d31, d31, d26 // t1 + vqadd.s16 d21, d23, d19 // t2 + vqsub.s16 d23, d23, d19 // t6 + vqadd.s16 d26, d24, d28 // t3 + vqsub.s16 d24, d24, d28 // t7 + vqadd.s16 d19, d17, d27 // t8a + vqsub.s16 d17, d17, d27 // t12a + vqadd.s16 d28, d30, d20 // t9a + vqsub.s16 d30, d30, d20 // t13a + vqadd.s16 d27, d18, d25 // t10a + vqsub.s16 d18, d18, d25 // t14a + vqadd.s16 d20, d29, d22 // t11a + vqsub.s16 d29, d29, d22 // t15a + + vmull_vmlal q2, d2, d3, d0[3], d0[2] // -> t4a + vmull_vmlsl q3, d2, d3, d0[2], d0[3] // -> t5a + vmull_vmlsl q4, d24, d23, d0[3], d0[2] // -> t6a + vqrshrn.s32 d22, q2, #12 // t4a + vqrshrn.s32 d25, q3, #12 // t5a + vmull_vmlal q2, d24, d23, d0[2], d0[3] // -> t7a + vmull_vmlal q3, d17, d30, d0[3], d0[2] // -> t12 + vqrshrn.s32 d24, q4, #12 // t6a + vqrshrn.s32 d23, q2, #12 // t7a + vmull_vmlsl q4, d17, d30, d0[2], d0[3] // -> t13 + vmull_vmlsl q2, d29, d18, d0[3], d0[2] // -> t14 + vqrshrn.s32 d17, q3, #12 // t12 + vmull_vmlal q3, d29, d18, d0[2], d0[3] // -> t15 + vqrshrn.s32 d29, q4, #12 // t13 + vqrshrn.s32 d30, q2, #12 // t14 + vqrshrn.s32 d18, q3, #12 // t15 + + vqsub.s16 d2, d16, d21 // t2a +.ifc \o0, d16 + vqadd.s16 \o0, d16, d21 // out0 + vqsub.s16 d21, d31, d26 // t3a + vqadd.s16 \o15,d31, d26 // out15 +.else + vqadd.s16 d4, d16, d21 // out0 + vqsub.s16 d21, d31, d26 // t3a + vqadd.s16 \o15,d31, d26 // out15 + vmov \o0, d4 +.endif + vqneg.s16 \o15, \o15 // out15 + + vqsub.s16 d3, d29, d18 // t15a + vqadd.s16 \o13,d29, d18 // out13 + vqadd.s16 \o2, d17, d30 // out2 + vqsub.s16 d26, d17, d30 // t14a + vqneg.s16 \o13,\o13 // out13 + + vqadd.s16 \o1, d19, d27 // out1 + vqsub.s16 d27, d19, d27 // t10 + vqadd.s16 \o14,d28, d20 // out14 + vqsub.s16 d20, d28, d20 // t11 + vqneg.s16 \o1, \o1 // out1 + + vqadd.s16 \o3, d22, d24 // out3 + vqsub.s16 d22, d22, d24 // t6 + vqadd.s16 \o12,d25, d23 // out12 + vqsub.s16 d23, d25, d23 // t7 + vqneg.s16 \o3, \o3 // out3 + + vmull_vmlsl q12, d2, d21, d0[0], d0[0] // -> out8 (d24 or d23) + vmull_vmlal q2, d2, d21, d0[0], d0[0] // -> out7 (d23 or d24) + vmull_vmlal q3, d26, d3, d0[0], d0[0] // -> out5 (d21 or d26) + + vqrshrn.s32 d24, q12, #12 // out8 + vqrshrn.s32 d4, q2, #12 // out7 + vqrshrn.s32 d5, q3, #12 // out5 + vmull_vmlsl q4, d26, d3, d0[0], d0[0] // -> out10 (d26 or d21) + vmull_vmlal q1, d22, d23, d0[0], d0[0] // -> out4 (d20 or d27) + vqrshrn.s32 d26, q4, #12 // out10 + + vmull_vmlsl q4, d22, d23, d0[0], d0[0] // -> out11 (d27 or d20) + vmull_vmlal q11, d27, d20, d0[0], d0[0] // -> out6 (d22 or d25) + vmull_vmlsl q3, d27, d20, d0[0], d0[0] // -> out9 (d25 or d22) + + vqrshrn.s32 \o4, q1, #12 // out4 + vqrshrn.s32 d7, q3, #12 // out9 + vqrshrn.s32 d6, q4, #12 // out11 + vqrshrn.s32 \o6, q11, #12 // out6 + +.ifc \o8, d23 + vmov \o8, d24 + vmov \o10,d26 +.endif + + vqneg.s16 \o7, d4 // out7 + vqneg.s16 \o5, d5 // out5 + vqneg.s16 \o11,d6 // out11 + vqneg.s16 \o9, d7 // out9 +.endm + +function inv_adst_4h_x16_neon, export=1 + iadst_16 d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + bx lr +endfunc + +function inv_flipadst_4h_x16_neon, export=1 + iadst_16 d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16 + bx lr +endfunc + +function inv_identity_4h_x16_neon, export=1 + movw r12, #2*(5793-4096)*8 + vdup.16 d0, r12 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s16 q1, \i, d0[0] + vqadd.s16 \i, \i, \i + vqadd.s16 \i, \i, q1 +.endr + bx lr +endfunc + +.macro identity_4x16_shift2 c +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s16 q2, \i, \c + vshr.s16 q2, q2, #1 + vrhadd.s16 \i, \i, q2 +.endr +.endm + +.macro identity_4x16_shift1 c +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s16 q2, \i, \c + vrshr.s16 q2, q2, #1 + vqadd.s16 \i, \i, q2 +.endr +.endm + +.macro identity_8x8_shift1 c + identity_4x16_shift1 \c +.endm + +.macro identity_8x8 c +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s16 q2, \i, \c + vqadd.s16 \i, \i, \i + vqadd.s16 \i, \i, q2 +.endr +.endm + +.macro def_horz_16 scale=0, identity=0, shift=2, suffix +function inv_txfm_horz\suffix\()_16x4_neon + push {lr} + vmov.i16 d7, #0 +.if \identity + movw r12, #2*(5793-4096)*8 + vdup.16 d0, r12 +.endif +.if \scale + movw r12, #2896*8 + vdup.16 d1, r12 +.endif +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64] + vst1.16 {d7}, [r7, :64], r8 +.endr +.if \scale + scale_input d1[0], q8, q9, q10, q11, q12, q13, q14, q15 +.endif +.if \identity +.if \shift == -2 + identity_4x16_shift2 d0[0] +.else + identity_4x16_shift1 d0[0] +.endif +.else + blx r4 +.endif +.if \shift > 0 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vrshr.s16 \i, \i, #\shift +.endr +.endif + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + transpose_4x4h q14, q15, d28, d29, d30, d31 + +.irp i, d16, d20, d24, d28, d17, d21, d25, d29, d18, d22, d26, d30, d19, d23, d27, d31 + vst1.16 {\i}, [r6, :64]! +.endr + + pop {pc} +endfunc +.endm + +def_horz_16 scale=0, identity=0, shift=2 +def_horz_16 scale=1, identity=0, shift=1, suffix=_scale +def_horz_16 scale=0, identity=1, shift=-2, suffix=_identity +def_horz_16 scale=1, identity=1, shift=-1, suffix=_scale_identity + +function inv_txfm_add_vert_4x16_neon + push {lr} +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + blx r5 + load_add_store_4x16 r6, r7 + pop {pc} +endfunc + +function inv_txfm_add_16x16_neon + sub_sp_align 512 + ldrh r11, [r10], #2 +.irp i, 0, 4, 8, 12 + add r6, sp, #(\i*16*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.if \i < 12 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*2) + mov r8, #16*2 + blx r9 +.endr + b 3f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #4 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b +3: +.irp i, 0, 4, 8, 12 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #32 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 512 + vpop {q4} + pop {r4-r11,pc} +endfunc + +const eob_16x16 + .short 10, 36, 78, 256 +endconst + +const eob_16x16_identity + .short 4, 8, 12, 256 +endconst + +.macro def_fn_16x16 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_16x16_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 16, 16, 2 +.endif + push {r4-r11,lr} + vpush {q4} +.ifc \txfm1, identity + movrel_local r9, inv_txfm_horz_identity_16x4_neon +.else + movrel_local r9, inv_txfm_horz_16x4_neon + movrel_local r4, inv_\txfm1\()_4h_x16_neon +.endif + movrel_local r5, inv_\txfm2\()_4h_x16_neon +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel_local r10, eob_16x16 +.else + movrel_local r10, eob_16x16_identity +.endif +.else +.ifc \txfm2, identity + movrel_local r10, eob_16x16_identity +.else + movrel_local r10, eob_16x16 +.endif +.endif + b inv_txfm_add_16x16_neon +endfunc +.endm + +def_fn_16x16 dct, dct +def_fn_16x16 identity, identity +def_fn_16x16 dct, adst +def_fn_16x16 dct, flipadst +def_fn_16x16 dct, identity +def_fn_16x16 adst, dct +def_fn_16x16 adst, adst +def_fn_16x16 adst, flipadst +def_fn_16x16 flipadst, dct +def_fn_16x16 flipadst, adst +def_fn_16x16 flipadst, flipadst +def_fn_16x16 identity, dct + +.macro def_fn_416_base variant +function inv_txfm_\variant\()add_16x4_neon + +.ifc \variant, identity_ + vmov.i16 d4, #0 +.irp i, d16, d18, d20, d22 + vld1.16 {\i}, [r2, :64] + vst1.16 {d4}, [r2, :64]! +.endr +.irp i, d17, d19, d21, d23 + vld1.16 {\i}, [r2, :64] + vst1.16 {d4}, [r2, :64]! +.endr + movw r12, #2*(5793-4096)*8 + vdup.16 d0, r12 +.irp i, d24, d26, d28, d30 + vld1.16 {\i}, [r2, :64] + vst1.16 {d4}, [r2, :64]! +.endr +.irp i, d25, d27, d29, d31 + vld1.16 {\i}, [r2, :64] + vst1.16 {d4}, [r2, :64]! +.endr + + identity_4x16_shift1 d0[0] +.else + vmov.i16 q2, #0 + vmov.i16 q3, #0 + vld1.16 {d16, d17, d18, d19}, [r2, :128] + vst1.16 {q2, q3}, [r2, :128]! + vld1.16 {d20, d21, d22, d23}, [r2, :128] + vst1.16 {q2, q3}, [r2, :128]! + vld1.16 {d24, d25, d26, d27}, [r2, :128] + vst1.16 {q2, q3}, [r2, :128]! + vld1.16 {d28, d29, d30, d31}, [r2, :128] + vst1.16 {q2, q3}, [r2, :128]! + + blx r4 + + vswp d17, d20 + vswp d19, d22 + vswp d18, d20 + vswp d19, d21 +.irp i, q8, q9, q10, q11 + vrshr.s16 \i, \i, #1 +.endr +.endif + transpose_4x8h q8, q9, q10, q11 + blx r5 + mov r6, r0 + load_add_store_8x4 r6, r7 + +.ifc \variant, identity_ + vmov q8, q12 + vmov q9, q13 + vmov q10, q14 + vmov q11, q15 +.else + vswp d25, d28 + vswp d27, d30 + vswp d26, d28 + vswp d27, d29 + vrshr.s16 q8, q12, #1 + vrshr.s16 q9, q13, #1 + vrshr.s16 q10, q14, #1 + vrshr.s16 q11, q15, #1 +.endif + transpose_4x8h q8, q9, q10, q11 + blx r5 + add r6, r0, #8 + load_add_store_8x4 r6, r7 + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_\variant\()add_4x16_neon + vmov.i16 q2, #0 + + mov r11, #32 + cmp r3, r10 + blt 1f + + add r6, r2, #16 +.ifc \variant, identity_ +.irp i, q12, q13, q14, q15 + vld1.16 {\i}, [r6, :128] + vst1.16 {q2}, [r6, :128], r11 +.endr + movw r12, #(5793-4096)*8 + vdup.16 d0, r12 + identity_8x4_shift1 q12, q13, q14, q15, d0[0] +.else +.irp i, q8, q9, q10, q11 + vld1.16 {\i}, [r6, :128] + vst1.16 {q2}, [r6, :128], r11 +.endr + blx r4 + vrshr.s16 q12, q8, #1 + vrshr.s16 q13, q9, #1 + vrshr.s16 q14, q10, #1 + vrshr.s16 q15, q11, #1 +.endif + transpose_4x8h q12, q13, q14, q15 + vswp d27, d29 + vswp d26, d28 + vswp d27, d30 + vswp d25, d28 + + b 2f +1: +.irp i, q12, q13, q14, q15 + vmov.i16 \i, #0 +.endr +2: + vmov.i16 q2, #0 +.irp i, q8, q9, q10, q11 + vld1.16 {\i}, [r2, :128] + vst1.16 {q2}, [r2, :128], r11 +.endr +.ifc \variant, identity_ + movw r12, #(5793-4096)*8 + vdup.16 d0, r12 + identity_8x4_shift1 q8, q9, q10, q11, d0[0] +.else + blx r4 +.irp i, q8, q9, q10, q11 + vrshr.s16 \i, \i, #1 +.endr +.endif + transpose_4x8h q8, q9, q10, q11 + vswp d19, d21 + vswp d18, d20 + vswp d19, d22 + vswp d17, d20 + + blx r5 + + load_add_store_4x16 r0, r6 + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +def_fn_416_base +def_fn_416_base identity_ + +.macro def_fn_416 w, h, txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + push {r4-r11,lr} + vpush {q4-q7} +.if \w == 4 + movrel_local r4, inv_\txfm1\()_8h_x\w\()_neon + movrel_local r5, inv_\txfm2\()_4h_x\h\()_neon + mov r10, #\eob_half +.else + movrel_local r4, inv_\txfm1\()_4h_x\w\()_neon + movrel_local r5, inv_\txfm2\()_8h_x\h\()_neon +.endif +.ifc \txfm1, identity + b inv_txfm_identity_add_\w\()x\h\()_neon +.else + b inv_txfm_add_\w\()x\h\()_neon +.endif +endfunc +.endm + +.macro def_fns_416 w, h +def_fn_416 \w, \h, dct, dct, 29 +def_fn_416 \w, \h, identity, identity, 29 +def_fn_416 \w, \h, dct, adst, 29 +def_fn_416 \w, \h, dct, flipadst, 29 +def_fn_416 \w, \h, dct, identity, 8 +def_fn_416 \w, \h, adst, dct, 29 +def_fn_416 \w, \h, adst, adst, 29 +def_fn_416 \w, \h, adst, flipadst, 29 +def_fn_416 \w, \h, flipadst, dct, 29 +def_fn_416 \w, \h, flipadst, adst, 29 +def_fn_416 \w, \h, flipadst, flipadst, 29 +def_fn_416 \w, \h, identity, dct, 32 +def_fn_416 \w, \h, adst, identity, 8 +def_fn_416 \w, \h, flipadst, identity, 8 +def_fn_416 \w, \h, identity, adst, 32 +def_fn_416 \w, \h, identity, flipadst, 32 +.endm + +def_fns_416 4, 16 +def_fns_416 16, 4 + +.macro def_fn_816_base variant +function inv_txfm_\variant\()add_16x8_neon + sub_sp_align 256 + +.irp i, 0, 4 + add r6, sp, #(\i*16*2) +.if \i > 0 + cmp r3, r10 + blt 1f +.endif + add r7, r2, #(\i*2) + mov r8, #8*2 + blx r9 +.endr + b 2f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr +2: + +.irp i, 0, 8 + add r7, sp, #(\i*2) + mov r8, #32 +.irp j, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\j}, [r7, :128], r8 +.endr + blx r5 + + add r6, r0, #(\i) + load_add_store_8x8 r6, r7 +.endr + + add_sp_align 256 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_\variant\()add_8x16_neon + sub_sp_align 256 + +.irp i, 0, 8 + add r6, sp, #(\i*8*2) +.if \i > 0 + cmp r3, r10 + blt 1f +.endif + add r7, r2, #(\i*2) + mov r8, #16*2 + + vmov.i16 q2, #0 + movw r12, #2896*8 + vdup.16 d0, r12 + +.irp j, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\j}, [r7, :128] + vst1.16 {q2}, [r7, :128], r8 +.endr + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 +.ifc \variant, identity_ + // The identity shl #1 and downshift vrshr #1 cancel out +.else + blx r4 +.irp j, q8, q9, q10, q11, q12, q13, q14, q15 + vrshr.s16 \j, \j, #1 +.endr +.endif + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + vst1.16 {q8, q9}, [r6, :128]! + vst1.16 {q10, q11}, [r6, :128]! + vst1.16 {q12, q13}, [r6, :128]! + vst1.16 {q14, q15}, [r6, :128]! +.endr + b 2f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr +2: + +.irp i, 0, 4 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #16 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 256 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +def_fn_816_base +def_fn_816_base identity_ + +.macro def_fn_816 w, h, txfm1, txfm2, eob_8x8, eob_4x4 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + push {r4-r11,lr} + vpush {q4-q7} +.if \w == 8 + movrel_local r4, inv_\txfm1\()_8h_x8_neon + movrel_local r5, inv_\txfm2\()_4h_x16_neon +.else +.ifc \txfm1, identity + movrel_local r9, inv_txfm_horz_scale_identity_16x4_neon +.else + movrel_local r4, inv_\txfm1\()_4h_x16_neon + movrel_local r9, inv_txfm_horz_scale_16x4_neon +.endif + movrel_local r5, inv_\txfm2\()_8h_x8_neon +.endif +.if \w == 8 + mov r10, #\eob_8x8 +.else + mov r10, #\eob_4x4 +.endif +.ifc \txfm1, identity + b inv_txfm_identity_add_\w\()x\h\()_neon +.else + b inv_txfm_add_\w\()x\h\()_neon +.endif +endfunc +.endm + +.macro def_fns_816 w, h +def_fn_816 \w, \h, dct, dct, 43, 10 +def_fn_816 \w, \h, identity, identity, 43, 10 +def_fn_816 \w, \h, dct, adst, 43, 10 +def_fn_816 \w, \h, dct, flipadst, 43, 10 +def_fn_816 \w, \h, dct, identity, 8, 4 +def_fn_816 \w, \h, adst, dct, 43, 10 +def_fn_816 \w, \h, adst, adst, 43, 10 +def_fn_816 \w, \h, adst, flipadst, 43, 10 +def_fn_816 \w, \h, flipadst, dct, 43, 10 +def_fn_816 \w, \h, flipadst, adst, 43, 10 +def_fn_816 \w, \h, flipadst, flipadst, 43, 10 +def_fn_816 \w, \h, identity, dct, 64, 4 +def_fn_816 \w, \h, adst, identity, 8, 4 +def_fn_816 \w, \h, flipadst, identity, 8, 4 +def_fn_816 \w, \h, identity, adst, 64, 4 +def_fn_816 \w, \h, identity, flipadst, 64, 4 +.endm + +def_fns_816 8, 16 +def_fns_816 16, 8 + +function inv_dct32_odd_4h_x16_neon, export=1 + movrel_local r12, idct_coeffs, 2*16 + vld1.16 {q0, q1}, [r12, :128] + sub r12, r12, #2*16 + + vmull_vmlsl q2, d16, d31, d0[0], d0[1] // -> t16a + vmull_vmlal q3, d16, d31, d0[1], d0[0] // -> t31a + vmull_vmlsl q4, d24, d23, d0[2], d0[3] // -> t17a + vqrshrn.s32 d16, q2, #12 // t16a + vqrshrn.s32 d31, q3, #12 // t31a + vmull_vmlal q2, d24, d23, d0[3], d0[2] // -> t30a + vmull_vmlsl q3, d20, d27, d1[0], d1[1] // -> t18a + vqrshrn.s32 d24, q4, #12 // t17a + vqrshrn.s32 d23, q2, #12 // t30a + vmull_vmlal q4, d20, d27, d1[1], d1[0] // -> t29a + vmull_vmlsl q2, d28, d19, d1[2], d1[3] // -> t19a + vqrshrn.s32 d20, q3, #12 // t18a + vqrshrn.s32 d27, q4, #12 // t29a + vmull_vmlal q3, d28, d19, d1[3], d1[2] // -> t28a + vmull_vmlsl q4, d18, d29, d2[0], d2[1] // -> t20a + vqrshrn.s32 d28, q2, #12 // t19a + vqrshrn.s32 d19, q3, #12 // t28a + vmull_vmlal q2, d18, d29, d2[1], d2[0] // -> t27a + vmull_vmlsl q3, d26, d21, d2[2], d2[3] // -> t21a + vqrshrn.s32 d18, q4, #12 // t20a + vqrshrn.s32 d29, q2, #12 // t27a + vmull_vmlal q4, d26, d21, d2[3], d2[2] // -> t26a + vmull_vmlsl q2, d22, d25, d3[0], d3[1] // -> t22a + vqrshrn.s32 d26, q3, #12 // t21a + vqrshrn.s32 d21, q4, #12 // t26a + vmull_vmlal q3, d22, d25, d3[1], d3[0] // -> t25a + vmull_vmlsl q4, d30, d17, d3[2], d3[3] // -> t23a + vqrshrn.s32 d22, q2, #12 // t22a + vqrshrn.s32 d25, q3, #12 // t25a + vmull_vmlal q2, d30, d17, d3[3], d3[2] // -> t24a + vqrshrn.s32 d30, q4, #12 // t23a + vqrshrn.s32 d17, q2, #12 // t24a + + vld1.16 {q0}, [r12, :128] + + vqsub.s16 d2, d16, d24 // t17 + vqadd.s16 d16, d16, d24 // t16 + vqsub.s16 d3, d31, d23 // t30 + vqadd.s16 d31, d31, d23 // t31 + vqsub.s16 d24, d28, d20 // t18 + vqadd.s16 d28, d28, d20 // t19 + vqadd.s16 d23, d18, d26 // t20 + vqsub.s16 d18, d18, d26 // t21 + vqsub.s16 d20, d30, d22 // t22 + vqadd.s16 d30, d30, d22 // t23 + vqadd.s16 d26, d17, d25 // t24 + vqsub.s16 d17, d17, d25 // t25 + vqsub.s16 d22, d29, d21 // t26 + vqadd.s16 d29, d29, d21 // t27 + vqadd.s16 d25, d19, d27 // t28 + vqsub.s16 d19, d19, d27 // t29 + + vmull_vmlsl q2, d3, d2, d1[0], d1[1] // -> t17a + vmull_vmlal q3, d3, d2, d1[1], d1[0] // -> t30a + vmull_vmlal q4, d19, d24, d1[1], d1[0] // -> t18a + vqrshrn.s32 d21, q2, #12 // t17a + vqrshrn.s32 d27, q3, #12 // t30a + vneg.s32 q4, q4 // -> t18a + vmull_vmlsl q1, d19, d24, d1[0], d1[1] // -> t29a + vmull_vmlsl q2, d22, d18, d1[2], d1[3] // -> t21a + vqrshrn.s32 d19, q4, #12 // t18a + vqrshrn.s32 d24, q1, #12 // t29a + vmull_vmlal q3, d22, d18, d1[3], d1[2] // -> t26a + vmull_vmlal q4, d17, d20, d1[3], d1[2] // -> t22a + vqrshrn.s32 d22, q2, #12 // t21a + vqrshrn.s32 d18, q3, #12 // t26a + vneg.s32 q4, q4 // -> t22a + vmull_vmlsl q1, d17, d20, d1[2], d1[3] // -> t25a + vqrshrn.s32 d17, q4, #12 // t22a + vqrshrn.s32 d20, q1, #12 // t25a + + vqsub.s16 d2, d27, d24 // t29 + vqadd.s16 d27, d27, d24 // t30 + vqsub.s16 d3, d21, d19 // t18 + vqadd.s16 d21, d21, d19 // t17 + vqsub.s16 d24, d16, d28 // t19a + vqadd.s16 d16, d16, d28 // t16a + vqsub.s16 d19, d30, d23 // t20a + vqadd.s16 d30, d30, d23 // t23a + vqsub.s16 d28, d17, d22 // t21 + vqadd.s16 d17, d17, d22 // t22 + vqadd.s16 d23, d26, d29 // t24a + vqsub.s16 d26, d26, d29 // t27a + vqadd.s16 d22, d20, d18 // t25 + vqsub.s16 d20, d20, d18 // t26 + vqsub.s16 d29, d31, d25 // t28a + vqadd.s16 d31, d31, d25 // t31a + + vmull_vmlsl q2, d2, d3, d0[2], d0[3] // -> t18a + vmull_vmlal q3, d2, d3, d0[3], d0[2] // -> t29a + vmull_vmlsl q4, d29, d24, d0[2], d0[3] // -> t19 + vqrshrn.s32 d18, q2, #12 // t18a + vqrshrn.s32 d25, q3, #12 // t29a + vmull_vmlal q1, d29, d24, d0[3], d0[2] // -> t28 + vmull_vmlal q2, d26, d19, d0[3], d0[2] // -> t20 + vqrshrn.s32 d29, q4, #12 // t19 + vqrshrn.s32 d24, q1, #12 // t28 + vneg.s32 q2, q2 // -> t20 + vmull_vmlsl q3, d26, d19, d0[2], d0[3] // -> t27 + vmull_vmlal q4, d20, d28, d0[3], d0[2] // -> t21a + vqrshrn.s32 d26, q2, #12 // t20 + vqrshrn.s32 d19, q3, #12 // t27 + vneg.s32 q4, q4 // -> t21a + vmull_vmlsl q1, d20, d28, d0[2], d0[3] // -> t26a + vqrshrn.s32 d20, q4, #12 // t21a + vqrshrn.s32 d28, q1, #12 // t26a + + vqsub.s16 d2, d16, d30 // t23 + vqadd.s16 d16, d16, d30 // t16 = out16 + vqsub.s16 d3, d31, d23 // t24 + vqadd.s16 d31, d31, d23 // t31 = out31 + vqsub.s16 d23, d21, d17 // t22a + vqadd.s16 d17, d21, d17 // t17a = out17 + vqadd.s16 d30, d27, d22 // t30a = out30 + vqsub.s16 d21, d27, d22 // t25a + vqsub.s16 d27, d18, d20 // t21 + vqadd.s16 d18, d18, d20 // t18 = out18 + vqadd.s16 d4, d29, d26 // t19a = out19 + vqsub.s16 d26, d29, d26 // t20a + vqadd.s16 d29, d25, d28 // t29 = out29 + vqsub.s16 d25, d25, d28 // t26 + vqadd.s16 d28, d24, d19 // t28a = out28 + vqsub.s16 d24, d24, d19 // t27a + vmov d19, d4 // out19 + + vmull_vmlsl q2, d24, d26, d0[0], d0[0] // -> t20 + vmull_vmlal q3, d24, d26, d0[0], d0[0] // -> t27 + vqrshrn.s32 d20, q2, #12 // t20 + vqrshrn.s32 d22, q3, #12 // t27 + + vmull_vmlal q2, d25, d27, d0[0], d0[0] // -> t26a + vmull_vmlsl q3, d25, d27, d0[0], d0[0] // -> t21a + vmov d27, d22 // t27 + vqrshrn.s32 d26, q2, #12 // t26a + + vmull_vmlsl q12, d21, d23, d0[0], d0[0] // -> t22 + vmull_vmlal q2, d21, d23, d0[0], d0[0] // -> t25 + vqrshrn.s32 d21, q3, #12 // t21a + vqrshrn.s32 d22, q12, #12 // t22 + vqrshrn.s32 d25, q2, #12 // t25 + + vmull_vmlsl q2, d3, d2, d0[0], d0[0] // -> t23a + vmull_vmlal q3, d3, d2, d0[0], d0[0] // -> t24a + vqrshrn.s32 d23, q2, #12 // t23a + vqrshrn.s32 d24, q3, #12 // t24a + + bx lr +endfunc + +.macro def_horz_32 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_dct_32x4_neon + push {lr} + vmov.i16 d7, #0 + lsl r8, r8, #1 +.if \scale + movw r12, #2896*8 + vdup.16 d0, r12 +.endif + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64] + vst1.16 {d7}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + add r7, r7, r8, lsr #1 +.if \scale + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 +.endif + bl inv_dct_4h_x16_neon + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + transpose_4x4h q14, q15, d28, d29, d30, d31 + +.macro store1 r0, r1, r2, r3 + vst1.16 {\r0}, [r6, :64]! + vst1.16 {\r1}, [r6, :64]! + vst1.16 {\r2}, [r6, :64]! + vst1.16 {\r3}, [r6, :64]! + add r6, r6, #32 +.endm + store1 d16, d20, d24, d28 + store1 d17, d21, d25, d29 + store1 d18, d22, d26, d30 + store1 d19, d23, d27, d31 +.purgem store1 + sub r6, r6, #64*4 + + vmov.i16 d7, #0 +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64] + vst1.16 {d7}, [r7, :64], r8 +.endr +.if \scale + // This relies on the fact that the idct also leaves the right coeff in d0[1] + scale_input d0[1], q8, q9, q10, q11, q12, q13, q14, q15 +.endif + bl inv_dct32_odd_4h_x16_neon + transpose_4x4h q15, q14, d31, d30, d29, d28 + transpose_4x4h q13, q12, d27, d26, d25, d24 + transpose_4x4h q11, q10, d23, d22, d21, d20 + transpose_4x4h q9, q8, d19, d18, d17, d16 +.macro store2 r0, r1, r2, r3, shift + vld1.16 {q0, q1}, [r6, :128] + vqsub.s16 d7, d0, \r0 + vqadd.s16 d0, d0, \r0 + vqsub.s16 d6, d1, \r1 + vqadd.s16 d1, d1, \r1 + vqsub.s16 d5, d2, \r2 + vqadd.s16 d2, d2, \r2 + vqsub.s16 d4, d3, \r3 + vqadd.s16 d3, d3, \r3 + vrev64.16 q2, q2 + vrev64.16 q3, q3 + vrshr.s16 q0, q0, #\shift + vrshr.s16 q1, q1, #\shift + vrshr.s16 q2, q2, #\shift + vrshr.s16 q3, q3, #\shift + vst1.16 {q0, q1}, [r6, :128]! + vst1.16 {q2, q3}, [r6, :128]! +.endm + + store2 d31, d27, d23, d19, \shift + store2 d30, d26, d22, d18, \shift + store2 d29, d25, d21, d17, \shift + store2 d28, d24, d20, d16, \shift +.purgem store2 + pop {pc} +endfunc +.endm + +def_horz_32 scale=0, shift=2 +def_horz_32 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_dct_4x32_neon + push {r10-r11,lr} + lsl r8, r8, #1 + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + + bl inv_dct_4h_x16_neon + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vst1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + add r7, r7, r8, lsr #1 + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + sub r7, r7, r8, lsr #1 + bl inv_dct32_odd_4h_x16_neon + + neg r9, r8 + mov r10, r6 +.macro combine r0, r1, r2, r3, op, stride + vld1.16 {d4}, [r7, :64], \stride + vld1.32 {d2[0]}, [r10, :32], r1 + vld1.16 {d5}, [r7, :64], \stride + vld1.32 {d2[1]}, [r10, :32], r1 + \op\().s16 d4, d4, \r0 + vld1.16 {d6}, [r7, :64], \stride + vld1.32 {d3[0]}, [r10, :32], r1 + \op\().s16 d5, d5, \r1 + vld1.32 {d3[1]}, [r10, :32], r1 + vrshr.s16 q2, q2, #4 + \op\().s16 d6, d6, \r2 + vld1.16 {d7}, [r7, :64], \stride + vaddw.u8 q2, q2, d2 + \op\().s16 d7, d7, \r3 + vqmovun.s16 d2, q2 + vrshr.s16 q3, q3, #4 + vst1.32 {d2[0]}, [r6, :32], r1 + vaddw.u8 q3, q3, d3 + vst1.32 {d2[1]}, [r6, :32], r1 + vqmovun.s16 d3, q3 + vst1.32 {d3[0]}, [r6, :32], r1 + vst1.32 {d3[1]}, [r6, :32], r1 +.endm + combine d31, d30, d29, d28, vqadd, r8 + combine d27, d26, d25, d24, vqadd, r8 + combine d23, d22, d21, d20, vqadd, r8 + combine d19, d18, d17, d16, vqadd, r8 + sub r7, r7, r8 + combine d16, d17, d18, d19, vqsub, r9 + combine d20, d21, d22, d23, vqsub, r9 + combine d24, d25, d26, d27, vqsub, r9 + combine d28, d29, d30, d31, vqsub, r9 +.purgem combine + + pop {r10-r11,pc} +endfunc + +const eob_32x32 + .short 10, 36, 78, 136, 210, 300, 406, 1024 +endconst + +const eob_16x32 + .short 10, 36, 78, 151, 215, 279, 343, 512 +endconst + +const eob_16x32_shortside + .short 10, 36, 78, 512 +endconst + +const eob_8x32 + // Contrary to the others, this one is only ever used in increments of 8x8 + .short 43, 107, 171, 256 +endconst + +function inv_txfm_add_identity_identity_32x32_8bpc_neon, export=1 + push {r4-r7,lr} + vmov.i16 q0, #0 + movrel_local r5, eob_32x32, 2 + + mov r6, #2*32 +1: + mov r12, #0 + movrel_local r4, eob_32x32, 2 +2: + add r12, r12, #8 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r2, :128] + vst1.16 {q0}, [r2, :128], r6 +.endr + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + + load_add_store_8x8 r0, r7, shiftbits=2 + ldrh lr, [r4], #4 + sub r0, r0, r1, lsl #3 + cmp r3, lr + add r0, r0, #8 + bge 2b + + ldrh lr, [r5], #4 + cmp r3, lr + blt 9f + + sub r0, r0, r12 + add r0, r0, r1, lsl #3 + mls r2, r6, r12, r2 + add r2, r2, #2*8 + b 1b +9: + pop {r4-r7,pc} +endfunc + +.macro shift_8_regs op, shift +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + \op \i, \i, #\shift +.endr +.endm + +.macro def_identity_1632 w, h, wshort, hshort +function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1 + push {r4-r7,lr} + movw r6, #2896*8 + movw r7, #2*(5793-4096)*8 + vdup.i16 d0, r6 + movrel_local r5, eob_16x32\hshort, 2 + vmov.16 d0[1], r7 + + mov r6, #2*\h +1: + mov r12, #0 + movrel_local r4, eob_16x32\wshort, 2 +2: + vmov.i16 q1, #0 + add r12, r12, #8 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r2, :128] + vst1.16 {q1}, [r2, :128], r6 +.endr + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 + +.if \w == 16 + // 16x32 + identity_8x8_shift1 d0[1] +.else + // 32x16 + shift_8_regs vqshl.s16, 1 + identity_8x8 d0[1] +.endif + + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + +.if \w == 16 + load_add_store_8x8 r0, r7, shiftbits=2 +.else + load_add_store_8x8 r0, r7, shiftbits=4 +.endif + ldrh lr, [r4], #4 + sub r0, r0, r1, lsl #3 + cmp r3, lr + add r0, r0, #8 + bge 2b + + ldrh lr, [r5], #4 + cmp r3, lr + blt 9f + + sub r0, r0, r12 + add r0, r0, r1, lsl #3 + mls r2, r6, r12, r2 + add r2, r2, #2*8 + b 1b +9: + pop {r4-r7,pc} +endfunc +.endm + +def_identity_1632 16, 32, _shortside, +def_identity_1632 32, 16, , _shortside + +.macro def_identity_832 w, h +function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1 + push {r4-r5,lr} + vmov.i16 q0, #0 + movrel_local r4, eob_8x32 + + mov r12, #2*\h +1: + ldrh lr, [r4], #2 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r2, :128] + vst1.16 {q0}, [r2, :128], r12 +.endr + +.if \w == 8 + // 8x32 + shift_8_regs vrshr.s16, 1 +.endif + + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + + cmp r3, lr +.if \w == 8 + load_add_store_8x8 r0, r5, shiftbits=2 +.else + load_add_store_8x8 r0, r5, shiftbits=3 +.endif + + blt 9f +.if \w == 8 + sub r2, r2, r12, lsl #3 + add r2, r2, #2*8 +.else + sub r0, r0, r1, lsl #3 + add r0, r0, #8 +.endif + b 1b + +9: + pop {r4-r5,pc} +endfunc +.endm + +def_identity_832 8, 32 +def_identity_832 32, 8 + +function inv_txfm_add_dct_dct_32x32_8bpc_neon, export=1 + idct_dc 32, 32, 2 + + push {r4-r11,lr} + vpush {q4} + sub_sp_align 2048 + movrel_local r10, eob_32x32 + ldrh r11, [r10], #2 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, sp, #(\i*32*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*2) + mov r8, #32*2 + bl inv_txfm_horz_dct_32x4_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #32*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 2048 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_16x32_8bpc_neon, export=1 + idct_dc 16, 32, 1 + + push {r4-r11,lr} + vpush {q4} + sub_sp_align 1024 + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + movrel_local r4, inv_dct_4h_x16_neon + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, sp, #(\i*16*2) + add r7, r2, #(\i*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endif + mov r8, #2*32 + bl inv_txfm_horz_scale_16x4_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #4 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #16*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 1024 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x16_8bpc_neon, export=1 + idct_dc 32, 16, 1 + + push {r4-r11,lr} + vpush {q4} + sub_sp_align 1024 + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + movrel_local r5, inv_dct_4h_x16_neon + +.irp i, 0, 4, 8, 12 + add r6, sp, #(\i*32*2) + add r7, r2, #(\i*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.if \i < 12 + ldrh r11, [r10], #2 +.endif +.endif + mov r8, #2*16 + bl inv_txfm_horz_scale_dct_32x4_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #32*2 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 1024 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_8x32_8bpc_neon, export=1 + idct_dc 8, 32, 2 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 512 + + movrel_local r10, eob_8x32 + + mov r8, #2*32 + mov r9, #32 + mov r6, sp +1: + vmov.i16 q0, #0 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r2, :128] + vst1.16 {q0}, [r2, :128], r8 +.endr + ldrh r11, [r10], #2 + sub r2, r2, r8, lsl #3 + sub r9, r9, #8 + add r2, r2, #2*8 + + bl inv_dct_8h_x8_neon + +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vrshr.s16 \i, \i, #2 +.endr + + transpose_8x8h q8, q9, q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30 + + vst1.16 {q8, q9}, [r6, :128]! + cmp r3, r11 + vst1.16 {q10, q11}, [r6, :128]! + vst1.16 {q12, q13}, [r6, :128]! + vst1.16 {q14, q15}, [r6, :128]! + + bge 1b + cmp r9, #0 + beq 3f + + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r9, r9, #8 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4 + add r6, r0, #(\i) + add r7, sp, #(\i*2) + mov r8, #8*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 512 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x8_8bpc_neon, export=1 + idct_dc 32, 8, 2 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 512 + +.irp i, 0, 4 + add r6, sp, #(\i*32*2) + add r7, r2, #(\i*2) +.if \i > 0 + cmp r3, #10 + blt 1f +.endif + mov r8, #8*2 + bl inv_txfm_horz_dct_32x4_neon +.endr + b 2f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + +2: + mov r8, #2*32 + mov r9, #0 +1: + add r6, r0, r9 + add r7, sp, r9, lsl #1 // #(\i*2) + +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r7, :128], r8 +.endr + add r9, r9, #8 + + bl inv_dct_8h_x8_neon + + cmp r9, #32 + + load_add_store_8x8 r6, r7 + + blt 1b + + add_sp_align 512 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_dct64_step1_neon + // in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + // in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + // in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + // in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + + vld1.16 {d0, d1, d2}, [r12, :64]! + + vqrdmulh.s16 d23, d16, d0[1] // t63a + vqrdmulh.s16 d16, d16, d0[0] // t32a + vqrdmulh.s16 d22, d17, d0[2] // t62a + vqrdmulh.s16 d17, d17, d0[3] // t33a + vqrdmulh.s16 d21, d18, d1[1] // t61a + vqrdmulh.s16 d18, d18, d1[0] // t34a + vqrdmulh.s16 d20, d19, d1[2] // t60a + vqrdmulh.s16 d19, d19, d1[3] // t35a + + vqadd.s16 d24, d16, d17 // t32 + vqsub.s16 d25, d16, d17 // t33 + vqsub.s16 d26, d19, d18 // t34 + vqadd.s16 d27, d19, d18 // t35 + vqadd.s16 d28, d20, d21 // t60 + vqsub.s16 d29, d20, d21 // t61 + vqsub.s16 d30, d23, d22 // t62 + vqadd.s16 d31, d23, d22 // t63 + + vmull_vmlal q2, d29, d26, d2[0], d2[1] // -> t34a + vmull_vmlsl q3, d29, d26, d2[1], d2[0] // -> t61a + vneg.s32 q2, q2 // t34a + vmull_vmlsl q4, d30, d25, d2[1], d2[0] // -> t33a + vqrshrn.s32 d26, q2, #12 // t34a + vmull_vmlal q2, d30, d25, d2[0], d2[1] // -> t62a + vqrshrn.s32 d29, q3, #12 // t61a + vqrshrn.s32 d25, q4, #12 // t33a + vqrshrn.s32 d30, q2, #12 // t62a + + vqadd.s16 d16, d24, d27 // t32a + vqsub.s16 d19, d24, d27 // t35a + vqadd.s16 d17, d25, d26 // t33 + vqsub.s16 d18, d25, d26 // t34 + vqsub.s16 d20, d31, d28 // t60a + vqadd.s16 d23, d31, d28 // t63a + vqsub.s16 d21, d30, d29 // t61 + vqadd.s16 d22, d30, d29 // t62 + + vmull_vmlal q2, d21, d18, d2[2], d2[3] // -> t61a + vmull_vmlsl q3, d21, d18, d2[3], d2[2] // -> t34a + vmull_vmlal q4, d20, d19, d2[2], d2[3] // -> t60 + vqrshrn.s32 d21, q2, #12 // t61a + vqrshrn.s32 d18, q3, #12 // t34a + vmull_vmlsl q2, d20, d19, d2[3], d2[2] // -> t35 + vqrshrn.s32 d20, q4, #12 // t60 + vqrshrn.s32 d19, q2, #12 // t35 + + vst1.16 {d16, d17, d18, d19}, [r6, :128]! + vst1.16 {d20, d21, d22, d23}, [r6, :128]! + + bx lr +endfunc + +function inv_dct64_step2_neon + movrel_local r12, idct_coeffs + vld1.16 {d0}, [r12, :64] +1: + // t32a/33/34a/35/60/61a/62/63a + // t56a/57/58a/59/36/37a/38/39a + // t40a/41/42a/43/52/53a/54/55a + // t48a/49/50a/51/44/45a/46/47a + vldr d16, [r6, #2*4*0] // t32a + vldr d17, [r9, #2*4*8] // t39a + vldr d18, [r9, #2*4*0] // t63a + vldr d19, [r6, #2*4*8] // t56a + vldr d20, [r6, #2*4*16] // t40a + vldr d21, [r9, #2*4*24] // t47a + vldr d22, [r9, #2*4*16] // t55a + vldr d23, [r6, #2*4*24] // t48a + + vqadd.s16 d24, d16, d17 // t32 + vqsub.s16 d25, d16, d17 // t39 + vqadd.s16 d26, d18, d19 // t63 + vqsub.s16 d27, d18, d19 // t56 + vqsub.s16 d28, d21, d20 // t40 + vqadd.s16 d29, d21, d20 // t47 + vqadd.s16 d30, d23, d22 // t48 + vqsub.s16 d31, d23, d22 // t55 + + vmull_vmlal q2, d27, d25, d0[3], d0[2] // -> t56a + vmull_vmlsl q3, d27, d25, d0[2], d0[3] // -> t39a + vmull_vmlal q4, d31, d28, d0[3], d0[2] // -> t40a + vqrshrn.s32 d25, q2, #12 // t56a + vqrshrn.s32 d27, q3, #12 // t39a + vneg.s32 q4, q4 // t40a + vmull_vmlsl q2, d31, d28, d0[2], d0[3] // -> t55a + vqrshrn.s32 d31, q4, #12 // t40a + vqrshrn.s32 d28, q2, #12 // t55a + + vqadd.s16 d16, d24, d29 // t32a + vqsub.s16 d19, d24, d29 // t47a + vqadd.s16 d17, d27, d31 // t39 + vqsub.s16 d18, d27, d31 // t40 + vqsub.s16 d20, d26, d30 // t48a + vqadd.s16 d23, d26, d30 // t63a + vqsub.s16 d21, d25, d28 // t55 + vqadd.s16 d22, d25, d28 // t56 + + vmull_vmlsl q2, d21, d18, d0[0], d0[0] // -> t40a + vmull_vmlal q3, d21, d18, d0[0], d0[0] // -> t55a + vmull_vmlsl q4, d20, d19, d0[0], d0[0] // -> t47 + vqrshrn.s32 d18, q2, #12 // t40a + vqrshrn.s32 d21, q3, #12 // t55a + vmull_vmlal q2, d20, d19, d0[0], d0[0] // -> t48 + vqrshrn.s32 d19, q4, #12 // t47 + vqrshrn.s32 d20, q2, #12 // t48 + + vstr d16, [r6, #2*4*0] // t32a + vstr d17, [r9, #2*4*0] // t39 + vstr d18, [r6, #2*4*8] // t40a + vstr d19, [r9, #2*4*8] // t47 + vstr d20, [r6, #2*4*16] // t48 + vstr d21, [r9, #2*4*16] // t55a + vstr d22, [r6, #2*4*24] // t56 + vstr d23, [r9, #2*4*24] // t63a + + add r6, r6, #2*4 + sub r9, r9, #2*4 + cmp r6, r9 + blt 1b + bx lr +endfunc + +.macro load8 src, strd, zero, clear +.irp i, d16, d17, d18, d19, d20, d21, d22, d23 +.if \clear + vld1.16 {\i}, [\src, :64] + vst1.16 {\zero}, [\src, :64], \strd +.else + vld1.16 {\i}, [\src, :64], \strd +.endif +.endr +.endm + +.macro store16 dst + vst1.16 {q8, q9}, [\dst, :128]! + vst1.16 {q10, q11}, [\dst, :128]! + vst1.16 {q12, q13}, [\dst, :128]! + vst1.16 {q14, q15}, [\dst, :128]! +.endm + +.macro clear_upper8 +.irp i, q12, q13, q14, q15 + vmov.i16 \i, #0 +.endr +.endm + +.macro vmov_if reg, val, cond +.if \cond + vmov.i16 \reg, \val +.endif +.endm + +.macro movdup_if reg, gpr, val, cond +.if \cond + movw \gpr, \val + vdup.16 \reg, \gpr +.endif +.endm + +.macro vst1_if regs, dst, dstalign, cond +.if \cond + vst1.16 \regs, \dst, \dstalign +.endif +.endm + +.macro scale_if cond, c, r0, r1, r2, r3, r4, r5, r6, r7 +.if \cond + scale_input \c, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endif +.endm + +.macro def_dct64_func suffix, clear=0, scale=0 +function inv_txfm_dct\suffix\()_4h_x64_neon, export=1 + mov r6, sp + + push {r10-r11,lr} + + lsl r8, r8, #2 + + movdup_if d0, r12, #2896*8, \scale + vmov_if d7, #0, \clear + load8 r7, r8, d7, \clear + clear_upper8 + sub r7, r7, r8, lsl #3 + add r7, r7, r8, lsr #1 + scale_if \scale, d0[0], q8, q9, q10, q11 + + bl inv_dct_4h_x16_neon + + store16 r6 + + movdup_if d0, r12, #2896*8, \scale + vmov_if d7, #0, \clear + load8 r7, r8, d7, \clear + clear_upper8 + sub r7, r7, r8, lsl #3 + lsr r8, r8, #1 + sub r7, r7, r8, lsr #1 + scale_if \scale, d0[0], q8, q9, q10, q11 + + bl inv_dct32_odd_4h_x16_neon + + add r10, r6, #8*15 + sub r6, r6, #8*16 + + mov r9, #-8 + +.macro store_addsub r0, r1, r2, r3 + vld1.16 {d2}, [r6, :64]! + vld1.16 {d3}, [r6, :64]! + vqadd.s16 d6, d2, \r0 + vqsub.s16 \r0, d2, \r0 + vld1.16 {d4}, [r6, :64]! + vqadd.s16 d7, d3, \r1 + vqsub.s16 \r1, d3, \r1 + vld1.16 {d5}, [r6, :64]! + vqadd.s16 d2, d4, \r2 + sub r6, r6, #8*4 + vqsub.s16 \r2, d4, \r2 + vst1.16 {d6}, [r6, :64]! + vst1.16 {\r0}, [r10, :64], r9 + vqadd.s16 d3, d5, \r3 + vqsub.s16 \r3, d5, \r3 + vst1.16 {d7}, [r6, :64]! + vst1.16 {\r1}, [r10, :64], r9 + vst1.16 {d2}, [r6, :64]! + vst1.16 {\r2}, [r10, :64], r9 + vst1.16 {d3}, [r6, :64]! + vst1.16 {\r3}, [r10, :64], r9 +.endm + store_addsub d31, d30, d29, d28 + store_addsub d27, d26, d25, d24 + store_addsub d23, d22, d21, d20 + store_addsub d19, d18, d17, d16 +.purgem store_addsub + + add r6, r6, #2*4*16 + + movrel_local r12, idct64_coeffs + movdup_if d0, lr, #2896*8, \scale + vmov_if d7, #0, \clear + add r9, r7, r8, lsl #4 // offset 16 + add r10, r7, r8, lsl #3 // offset 8 + sub r9, r9, r8 // offset 15 + sub r11, r10, r8 // offset 7 + vld1.16 {d16}, [r7, :64] // in1 (offset 0) + vld1.16 {d17}, [r9, :64] // in31 (offset 15) + vld1.16 {d18}, [r10, :64] // in17 (offset 8) + vld1.16 {d19}, [r11, :64] // in15 (offset 7) + vst1_if {d7}, [r7, :64], \clear + vst1_if {d7}, [r9, :64], \clear + vst1_if {d7}, [r10, :64], \clear + vst1_if {d7}, [r11, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, #2896*8, \scale + vmov_if d7, #0, \clear + add r7, r7, r8, lsl #2 // offset 4 + sub r9, r9, r8, lsl #2 // offset 11 + sub r10, r7, r8 // offset 3 + add r11, r9, r8 // offset 12 + vld1.16 {d16}, [r10, :64] // in7 (offset 3) + vld1.16 {d17}, [r11, :64] // in25 (offset 12) + vld1.16 {d18}, [r9, :64] // in23 (offset 11) + vld1.16 {d19}, [r7, :64] // in9 (offset 4) + vst1_if {d7}, [r7, :64], \clear + vst1_if {d7}, [r9, :64], \clear + vst1_if {d7}, [r10, :64], \clear + vst1_if {d7}, [r11, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, #2896*8, \scale + vmov_if d7, #0, \clear + sub r10, r10, r8, lsl #1 // offset 1 + sub r9, r9, r8, lsl #1 // offset 9 + add r10, r10, r8 // offset 2 + add r9, r9, r8 // offset 10 + add r7, r7, r8 // offset 5 + add r11, r11, r8 // offset 13 + vld1.16 d16, [r10, :64] // in5 (offset 2) + vld1.16 d17, [r11, :64] // in27 (offset 13) + vld1.16 d18, [r9, :64] // in21 (offset 10) + vld1.16 d19, [r7, :64] // in11 (offset 5) + vst1_if d7, [r10, :64], \clear + vst1_if d7, [r11, :64], \clear + vst1_if d7, [r9, :64], \clear + vst1_if d7, [r7, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, #2896*8, \scale + vmov_if d7, #0, \clear + sub r10, r10, r8 // offset 1 + sub r9, r9, r8 // offset 9 + add r11, r11, r8 // offset 14 + add r7, r7, r8 // offset 6 + vld1.16 d16, [r10, :64] // in3 (offset 1) + vld1.16 d17, [r11, :64] // in29 (offset 14) + vld1.16 d18, [r9, :64] // in19 (offset 9) + vld1.16 d19, [r7, :64] // in13 (offset 6) + vst1_if d7, [r10, :64], \clear + vst1_if d7, [r11, :64], \clear + vst1_if d7, [r9, :64], \clear + vst1_if d7, [r7, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + + sub r6, r6, #2*4*32 + add r9, r6, #2*4*7 + + bl inv_dct64_step2_neon + + pop {r10-r11,pc} +endfunc +.endm + +def_dct64_func +def_dct64_func _clear, clear=1 +def_dct64_func _clear_scale, clear=1, scale=1 + +function inv_txfm_horz_dct_64x4_neon + vdup.16 q3, r9 + + mov r7, sp + add r8, sp, #2*4*(64 - 4) + add r9, r6, #2*56 + + push {r10-r11,lr} + + mov r10, #2*64 + mov r11, #-2*4*4 + +1: + vld1.16 {d16, d17, d18, d19}, [r7, :128]! + vld1.16 {d28, d29, d30, d31}, [r8, :128], r11 + vld1.16 {d20, d21, d22, d23}, [r7, :128]! + vld1.16 {d24, d25, d26, d27}, [r8, :128], r11 + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q15, q14, d31, d30, d29, d28 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q13, q12, d27, d26, d25, d24 + +.macro store_addsub src0, src1, src2, src3 + vqsub.s16 d3, \src0, \src1 + vqsub.s16 d2, \src2, \src3 + vqadd.s16 d0, \src0, \src1 + vqadd.s16 d1, \src2, \src3 + vrshl.s16 q1, q1, q3 + vrshl.s16 q0, q0, q3 + vrev64.16 q1, q1 + vst1.16 {q0}, [r6, :128], r10 + vst1.16 {q1}, [r9, :128], r10 +.endm + store_addsub d16, d31, d20, d27 + store_addsub d17, d30, d21, d26 + store_addsub d18, d29, d22, d25 + store_addsub d19, d28, d23, d24 +.purgem store_addsub + sub r6, r6, r10, lsl #2 + sub r9, r9, r10, lsl #2 + add r6, r6, #16 + sub r9, r9, #16 + + cmp r7, r8 + blt 1b + pop {r10-r11,pc} +endfunc + +function inv_txfm_add_vert_dct_4x64_neon + lsl r8, r8, #1 + + mov r7, sp + add r8, sp, #2*4*(64 - 4) + add r9, r6, r1, lsl #6 + sub r9, r9, r1 + + push {r10-r11,lr} + + neg r10, r1 + mov r11, #-2*4*4 + +1: + vld1.16 {d16, d17, d18, d19}, [r7, :128]! + vld1.16 {d28, d29, d30, d31}, [r8, :128], r11 + vld1.16 {d20, d21, d22, d23}, [r7, :128]! + vld1.16 {d24, d25, d26, d27}, [r8, :128], r11 + +.macro add_dest_addsub src0, src1, src2, src3 + vld1.32 {d0[0]}, [r6, :32], r1 + vld1.32 {d1[0]}, [r9, :32], r10 + vqadd.s16 d4, \src0, \src1 + vld1.32 {d0[1]}, [r6, :32] + vqadd.s16 d5, \src2, \src3 + vld1.32 {d1[1]}, [r9, :32] + vqsub.s16 d6, \src0, \src1 + vqsub.s16 d7, \src2, \src3 + sub r6, r6, r1 + sub r9, r9, r10 + vrshr.s16 q2, q2, #4 + vrshr.s16 q3, q3, #4 + vaddw.u8 q2, q2, d0 + vaddw.u8 q3, q3, d1 + vqmovun.s16 d0, q2 + vqmovun.s16 d1, q3 + vst1.32 {d0[0]}, [r6, :32], r1 + vst1.32 {d1[0]}, [r9, :32], r10 + vst1.32 {d0[1]}, [r6, :32], r1 + vst1.32 {d1[1]}, [r9, :32], r10 +.endm + add_dest_addsub d16, d31, d17, d30 + add_dest_addsub d18, d29, d19, d28 + add_dest_addsub d20, d27, d21, d26 + add_dest_addsub d22, d25, d23, d24 +.purgem add_dest_addsub + cmp r7, r8 + blt 1b + + pop {r10-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x64_8bpc_neon, export=1 + idct_dc 64, 64, 2 + + push {r4-r11,lr} + vpush {q4} + + sub_sp_align 64*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r5, #(\i*64*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*2) + mov r8, #32*2 + bl inv_txfm_dct_clear_4h_x64_neon + add r6, r5, #(\i*64*2) + mov r9, #-2 // shift + bl inv_txfm_horz_dct_64x4_neon +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r7, r5, #(\i*2) + mov r8, #64*2 + bl inv_txfm_dct_4h_x64_neon + add r6, r0, #(\i) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 64*32*2+64*4*2 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x32_8bpc_neon, export=1 + idct_dc 64, 32, 1 + + push {r4-r11,lr} + vpush {q4} + + sub_sp_align 64*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r5, #(\i*64*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*2) + mov r8, #32*2 + bl inv_txfm_dct_clear_scale_4h_x64_neon + add r6, r5, #(\i*64*2) + mov r9, #-1 // shift + bl inv_txfm_horz_dct_64x4_neon +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r6, r0, #(\i) + add r7, r5, #(\i*2) + mov r8, #64*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 64*32*2+64*4*2 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x64_8bpc_neon, export=1 + idct_dc 32, 64, 1 + + push {r4-r11,lr} + vpush {q4} + + sub_sp_align 32*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + ldrh r11, [r10], #2 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r5, #(\i*32*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*2) + mov r8, #32*2 + bl inv_txfm_horz_scale_dct_32x4_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r7, r5, #(\i*2) + mov r8, #32*2 + bl inv_txfm_dct_4h_x64_neon + add r6, r0, #(\i) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 32*32*2+64*4*2 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x16_8bpc_neon, export=1 + idct_dc 64, 16, 2 + + push {r4-r11,lr} + vpush {q4} + + sub_sp_align 64*16*2+64*4*2 + add r4, sp, #64*4*2 + + movrel_local r10, eob_16x32 + +.irp i, 0, 4, 8, 12 + add r6, r4, #(\i*64*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*2) + mov r8, #16*2 + bl inv_txfm_dct_clear_4h_x64_neon + add r6, r4, #(\i*64*2) + mov r9, #-2 // shift + bl inv_txfm_horz_dct_64x4_neon +.if \i < 12 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: + movrel_local r5, inv_dct_4h_x16_neon +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r6, r0, #(\i) + add r7, r4, #(\i*2) + mov r8, #64*2 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 64*16*2+64*4*2 + vpop {q4} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_16x64_8bpc_neon, export=1 + idct_dc 16, 64, 2 + + push {r4-r11,lr} + vpush {q4} + + sub_sp_align 16*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + + movrel_local r4, inv_dct_4h_x16_neon +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r5, #(\i*16*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 28 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*2) + mov r8, #32*2 + bl inv_txfm_horz_16x4_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #4 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12 + add r7, r5, #(\i*2) + mov r8, #16*2 + bl inv_txfm_dct_4h_x64_neon + add r6, r0, #(\i) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 16*32*2+64*4*2 + vpop {q4} + pop {r4-r11,pc} +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/itx16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/itx16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/itx16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3625 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "src/arm/asm.S" +#include "util.S" + +// The exported functions in this file have got the following signature: +// void itxfm_add(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob); + +// Most of the functions use the following register layout: +// r0-r3 external parameters +// r4 function pointer to first transform +// r5 function pointer to second transform +// r6 output parameter for helper function +// r7 input parameter for helper function +// r8 input stride for helper function +// r9 scratch variable for helper functions +// r10-r11 pointer to list of eob thresholds, eob threshold value, +// scratch variables within helper functions (backed up) + +// The SIMD registers most often use the following layout: +// d0-d3 multiplication coefficients +// d4-d7 scratch registers +// d8-d15 unused in some transforms, used for scratch registers in others +// d16-v31 inputs/outputs of transforms + +// Potential further optimizations, that are left unimplemented for now: +// - Trying to keep multiplication coefficients in registers across multiple +// transform functions. (The register layout is designed to potentially +// allow this.) +// - Use a simplified version of the transforms themselves for cases where +// we know a significant number of inputs are zero. E.g. if the eob value +// indicates only a quarter of input values are set, for idct16 and up, +// a significant amount of calculation can be skipped, at the cost of more +// code duplication and special casing. + +// A macro for cases where a thumb mov can express the constant in one +// instruction, while arm mode requires two separate movw+movt pairs. +.macro mov_const reg, val +#if CONFIG_THUMB + mov.w \reg, #\val +#else + movw \reg, #((\val) & 0xffff) + movt \reg, #(((\val) >> 16) & 0xffff) +#endif +.endm + +const idct_coeffs, align=4 + // idct4 + .int 2896, 2896*8*(1<<16), 1567, 3784 + // idct8 + .int 799, 4017, 3406, 2276 + // idct16 + .int 401, 4076, 3166, 2598 + .int 1931, 3612, 3920, 1189 + // idct32 + .int 201, 4091, 3035, 2751 + .int 1751, 3703, 3857, 1380 + .int 995, 3973, 3513, 2106 + .int 2440, 3290, 4052, 601 +endconst + +const idct64_coeffs, align=4 + .int 101*8*(1<<16), 4095*8*(1<<16), 2967*8*(1<<16), -2824*8*(1<<16) + .int 1660*8*(1<<16), 3745*8*(1<<16), 3822*8*(1<<16), -1474*8*(1<<16) + .int 4076, 401, 4017, 799 + + .int 4036*8*(1<<16), -700*8*(1<<16), 2359*8*(1<<16), 3349*8*(1<<16) + .int 3461*8*(1<<16), -2191*8*(1<<16), 897*8*(1<<16), 3996*8*(1<<16) + .int -3166, -2598, -799, -4017 + + .int 501*8*(1<<16), 4065*8*(1<<16), 3229*8*(1<<16), -2520*8*(1<<16) + .int 2019*8*(1<<16), 3564*8*(1<<16), 3948*8*(1<<16), -1092*8*(1<<16) + .int 3612, 1931, 2276, 3406 + + .int 4085*8*(1<<16), -301*8*(1<<16), 2675*8*(1<<16), 3102*8*(1<<16) + .int 3659*8*(1<<16), -1842*8*(1<<16), 1285*8*(1<<16), 3889*8*(1<<16) + .int -3920, -1189, -3406, -2276 +endconst + +const iadst4_coeffs, align=4 + .int 1321, 3803, 2482, 3344 +endconst + +const iadst8_coeffs, align=4 + .int 4076, 401, 3612, 1931 + .int 2598, 3166, 1189, 3920 + // idct_coeffs + .int 2896, 0, 1567, 3784 +endconst + +const iadst16_coeffs, align=4 + .int 4091, 201, 3973, 995 + .int 3703, 1751, 3290, 2440 + .int 2751, 3035, 2106, 3513 + .int 1380, 3857, 601, 4052 +endconst + +.macro vmul_vmla d0, s0, s1, c0, c1 + vmul.i32 \d0, \s0, \c0 + vmla.i32 \d0, \s1, \c1 +.endm + +.macro vmul_vmls d0, s0, s1, c0, c1 + vmul.i32 \d0, \s0, \c0 + vmls.i32 \d0, \s1, \c1 +.endm + +.macro scale_input c, r0, r1, r2 r3, r4, r5, r6, r7 + vqrdmulh.s32 \r0, \r0, \c + vqrdmulh.s32 \r1, \r1, \c +.ifnb \r2 + vqrdmulh.s32 \r2, \r2, \c + vqrdmulh.s32 \r3, \r3, \c +.endif +.ifnb \r4 + vqrdmulh.s32 \r4, \r4, \c + vqrdmulh.s32 \r5, \r5, \c + vqrdmulh.s32 \r6, \r6, \c + vqrdmulh.s32 \r7, \r7, \c +.endif +.endm + +.macro load_add_store load, shift, addsrc, adddst, max, min, store, dst, src, shiftbits=4 +.ifnb \load + vld1.16 {\load}, [\src, :128], r1 +.endif +.ifnb \shift + vrshr.s16 \shift, \shift, #\shiftbits +.endif +.ifnb \addsrc + vqadd.s16 \adddst, \adddst, \addsrc +.endif +.ifnb \max + vmax.s16 \max, \max, q6 +.endif +.ifnb \min + vmin.s16 \min, \min, q7 +.endif +.ifnb \store + vst1.16 {\store}, [\dst, :128], r1 +.endif +.endm +.macro load_add_store_8x8 dst, src, shiftbits=4 + mov \src, \dst + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff + load_add_store q0, q8, , , , , , \dst, \src, \shiftbits + load_add_store q1, q9, , , , , , \dst, \src, \shiftbits + load_add_store q2, q10, q0, q8, , , , \dst, \src, \shiftbits + load_add_store q3, q11, q1, q9, q8, , , \dst, \src, \shiftbits + load_add_store q4, q12, q2, q10, q9, q8, , \dst, \src, \shiftbits + load_add_store q5, q13, q3, q11, q10, q9, q8, \dst, \src, \shiftbits + load_add_store q0, q14, q4, q12, q11, q10, q9, \dst, \src, \shiftbits + load_add_store q1, q15, q5, q13, q12, q11, q10, \dst, \src, \shiftbits + load_add_store , , q0, q14, q13, q12, q11, \dst, \src, \shiftbits + load_add_store , , q1, q15, q14, q13, q12, \dst, \src, \shiftbits + load_add_store , , , , q15, q14, q13, \dst, \src, \shiftbits + load_add_store , , , , , q15, q14, \dst, \src, \shiftbits + load_add_store , , , , , , q15, \dst, \src, \shiftbits +.endm +.macro load_add_store_8x4 dst, src, shiftbits=4 + mov \src, \dst + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff + load_add_store q0, q8, , , , , , \dst, \src, \shiftbits + load_add_store q1, q9, , , , , , \dst, \src, \shiftbits + load_add_store q2, q10, q0, q8, , , , \dst, \src, \shiftbits + load_add_store q3, q11, q1, q9, q8, , , \dst, \src, \shiftbits + load_add_store , , q2, q10, q9, q8, , \dst, \src, \shiftbits + load_add_store , , q3, q11, q10, q9, q8, \dst, \src, \shiftbits + load_add_store , , , , q11, q10, q9, \dst, \src, \shiftbits + load_add_store , , , , , q11, q10, \dst, \src, \shiftbits + load_add_store , , , , , , q11, \dst, \src, \shiftbits +.endm +.macro load_add_store4 load1, load2, shift, addsrc, adddst, max, min, store1, store2, dst, src, shiftbits=4 +.ifnb \load1 + vld1.16 {\load1}, [\src, :64], r1 +.endif +.ifnb \shift + vrshr.s16 \shift, \shift, #\shiftbits +.endif +.ifnb \load2 + vld1.16 {\load2}, [\src, :64], r1 +.endif +.ifnb \addsrc + vqadd.s16 \adddst, \adddst, \addsrc +.endif +.ifnb \max + vmax.s16 \max, \max, q6 +.endif +.ifnb \store1 + vst1.16 {\store1}, [\dst, :64], r1 +.endif +.ifnb \min + vmin.s16 \min, \min, q7 +.endif +.ifnb \store2 + vst1.16 {\store2}, [\dst, :64], r1 +.endif +.endm +.macro load_add_store_4x16 dst, src + mov \src, \dst + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff + mov \src, \dst + load_add_store4 d0, d1, q8, , , , , , , \dst, \src + load_add_store4 d2, d3, q9, , , , , , , \dst, \src + load_add_store4 d4, d5, q10, q0, q8, , , , , \dst, \src + load_add_store4 d6, d7, q11, q1, q9, q8, , , , \dst, \src + load_add_store4 d8, d9, q12, q2, q10, q9, q8, , , \dst, \src + load_add_store4 d10, d11, q13, q3, q11, q10, q9, d16, d17, \dst, \src + load_add_store4 d0, d1, q14, q4, q12, q11, q10, d18, d19, \dst, \src + load_add_store4 d2, d3, q15, q5, q13, q12, q11, d20, d21, \dst, \src + load_add_store4 , , , q0, q14, q13, q12, d22, d23, \dst, \src + load_add_store4 , , , q1, q15, q14, q13, d24, d25, \dst, \src + load_add_store4 , , , , , q15, q14, d26, d27, \dst, \src + load_add_store4 , , , , , , q15, d28, d29, \dst, \src + load_add_store4 , , , , , , , d30, d31, \dst, \src +.endm +.macro load_add_store_4x8 dst, src, shiftbits=4 + mov \src, \dst + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff + mov \src, \dst + load_add_store4 d0, d1, q8, , , , , , , \dst, \src, \shiftbits + load_add_store4 d2, d3, q9, , , , , , , \dst, \src, \shiftbits + load_add_store4 d4, d5, q10, q0, q8, , , , , \dst, \src, \shiftbits + load_add_store4 d6, d7, q11, q1, q9, q8, , , , \dst, \src, \shiftbits + load_add_store4 , , , q2, q10, q9, q8, , , \dst, \src, \shiftbits + load_add_store4 , , , q3, q11, q10, q9, d16, d17, \dst, \src, \shiftbits + load_add_store4 , , , , , q11, q10, d18, d19, \dst, \src, \shiftbits + load_add_store4 , , , , , , q11, d20, d21, \dst, \src, \shiftbits + load_add_store4 , , , , , , , d22, d23, \dst, \src, \shiftbits +.endm +.macro load_add_store_4x4 dst, src, shiftbits=4 + mov \src, \dst + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff + mov \src, \dst + load_add_store4 d0, d1, q8, , , , , , , \dst, \src, \shiftbits + load_add_store4 d2, d3, q9, q0, q8, , , , , \dst, \src, \shiftbits + load_add_store4 , , , q1, q9, q8, , , , \dst, \src, \shiftbits + load_add_store4 , , , , , q9, q8, , , \dst, \src, \shiftbits + load_add_store4 , , , , , , q9, d16, d17, \dst, \src, \shiftbits + load_add_store4 , , , , , , , d18, d19, \dst, \src, \shiftbits +.endm + +.macro idct_dc w, h, shift + cmp r3, #0 + bne 1f + vmov.i16 q14, #0 + mov_const r12, 2896*8*(1<<16) + vld1.32 {d24[], d25[]}, [r2, :32] + vdup.32 d0, r12 + vqrdmulh.s32 q13, q12, d0[0] + vst1.32 {d28[0]}, [r2, :32] +.if (\w == 2*\h) || (2*\w == \h) + vqrdmulh.s32 q13, q13, d0[0] +.endif +.if \shift > 0 + vqrshrn.s32 d24, q13, #\shift + vqrshrn.s32 d25, q13, #\shift +.else + vqmovn.s32 d24, q13 + vqmovn.s32 d25, q13 +.endif + vqrdmulh.s16 q12, q12, d0[1] + mov r3, #\h + vrshr.s16 q12, q12, #4 + b idct_dc_w\w\()_neon +1: +.endm + +function idct_dc_w4_neon + vmvn.i16 q15, #0xfc00 // 0x3ff +1: + vld1.16 {d0}, [r0, :64], r1 + vld1.16 {d1}, [r0, :64], r1 + vld1.16 {d2}, [r0, :64], r1 + vld1.16 {d3}, [r0, :64], r1 + subs r3, r3, #4 + vqadd.s16 q0, q0, q12 + sub r0, r0, r1, lsl #2 + vqadd.s16 q1, q1, q12 + vmax.s16 q0, q0, q14 + vmax.s16 q1, q1, q14 + vmin.s16 q0, q0, q15 + vst1.16 {d0}, [r0, :64], r1 + vmin.s16 q1, q1, q15 + vst1.16 {d1}, [r0, :64], r1 + vst1.16 {d2}, [r0, :64], r1 + vst1.16 {d3}, [r0, :64], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w8_neon + vmvn.i16 q15, #0xfc00 // 0x3ff +1: + vld1.16 {q0}, [r0, :128], r1 + subs r3, r3, #4 + vld1.16 {q1}, [r0, :128], r1 + vqadd.s16 q0, q0, q12 + vld1.16 {q2}, [r0, :128], r1 + vqadd.s16 q1, q1, q12 + vld1.16 {q3}, [r0, :128], r1 + vqadd.s16 q2, q2, q12 + vqadd.s16 q3, q3, q12 + sub r0, r0, r1, lsl #2 + vmax.s16 q0, q0, q14 + vmax.s16 q1, q1, q14 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmin.s16 q0, q0, q15 + vmin.s16 q1, q1, q15 + vst1.16 {q0}, [r0, :128], r1 + vmin.s16 q2, q2, q15 + vst1.16 {q1}, [r0, :128], r1 + vmin.s16 q3, q3, q15 + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w16_neon + vmvn.i16 q15, #0xfc00 // 0x3ff +1: + vld1.16 {q0, q1}, [r0, :128], r1 + subs r3, r3, #2 + vld1.16 {q2, q3}, [r0, :128], r1 + vqadd.s16 q0, q0, q12 + vqadd.s16 q1, q1, q12 + vqadd.s16 q2, q2, q12 + vqadd.s16 q3, q3, q12 + sub r0, r0, r1, lsl #1 + vmax.s16 q0, q0, q14 + vmax.s16 q1, q1, q14 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmin.s16 q0, q0, q15 + vmin.s16 q1, q1, q15 + vmin.s16 q2, q2, q15 + vst1.16 {q0, q1}, [r0, :128], r1 + vmin.s16 q3, q3, q15 + vst1.16 {q2, q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w32_neon + sub r1, r1, #32 + vmvn.i16 q15, #0xfc00 // 0x3ff +1: + vld1.16 {q0, q1}, [r0, :128]! + subs r3, r3, #1 + vld1.16 {q2, q3}, [r0, :128] + vqadd.s16 q0, q0, q12 + vqadd.s16 q1, q1, q12 + vqadd.s16 q2, q2, q12 + vqadd.s16 q3, q3, q12 + sub r0, r0, #32 + vmax.s16 q0, q0, q14 + vmax.s16 q1, q1, q14 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmin.s16 q0, q0, q15 + vmin.s16 q1, q1, q15 + vmin.s16 q2, q2, q15 + vst1.16 {q0, q1}, [r0, :128]! + vmin.s16 q3, q3, q15 + vst1.16 {q2, q3}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +function idct_dc_w64_neon + sub r1, r1, #96 + vmvn.i16 q15, #0xfc00 // 0x3ff +1: + vld1.16 {q0, q1}, [r0, :128]! + subs r3, r3, #1 + vld1.16 {q2, q3}, [r0, :128]! + vqadd.s16 q0, q0, q12 + vld1.16 {q8, q9}, [r0, :128]! + vqadd.s16 q1, q1, q12 + vld1.16 {q10, q11}, [r0, :128] + vqadd.s16 q2, q2, q12 + vqadd.s16 q3, q3, q12 + vqadd.s16 q8, q8, q12 + vqadd.s16 q9, q9, q12 + vqadd.s16 q10, q10, q12 + vqadd.s16 q11, q11, q12 + sub r0, r0, #96 + vmax.s16 q0, q0, q14 + vmax.s16 q1, q1, q14 + vmax.s16 q2, q2, q14 + vmax.s16 q3, q3, q14 + vmax.s16 q8, q8, q14 + vmax.s16 q9, q9, q14 + vmax.s16 q10, q10, q14 + vmax.s16 q11, q11, q14 + vmin.s16 q0, q0, q15 + vmin.s16 q1, q1, q15 + vmin.s16 q2, q2, q15 + vmin.s16 q3, q3, q15 + vmin.s16 q8, q8, q15 + vst1.16 {q0, q1}, [r0, :128]! + vmin.s16 q9, q9, q15 + vst1.16 {q2, q3}, [r0, :128]! + vmin.s16 q10, q10, q15 + vst1.16 {q8, q9}, [r0, :128]! + vmin.s16 q11, q11, q15 + vst1.16 {q10, q11}, [r0, :128], r1 + bgt 1b + bx lr +endfunc + +.macro iwht4 + vadd.i32 q8, q8, q9 + vsub.i32 q13, q10, q11 + vsub.i32 q12, q8, q13 + vshr.s32 q12, q12, #1 + vsub.i32 q10, q12, q9 + vsub.i32 q9, q12, q11 + vadd.i32 q11, q13, q10 + vsub.i32 q8, q8, q9 +.endm + +.macro idct_4s_x4 r0, r1, r2, r3 + vmul_vmla q4, \r1, \r3, d1[1], d1[0] + vmul_vmla q2, \r0, \r2, d0[0], d0[0] + vmul_vmls q3, \r1, \r3, d1[0], d1[1] + vmul_vmls q5, \r0, \r2, d0[0], d0[0] + vrshr.s32 q4, q4, #12 + vrshr.s32 q2, q2, #12 + vrshr.s32 q3, q3, #12 + vrshr.s32 q5, q5, #12 + vqadd.s32 \r0, q2, q4 + vqsub.s32 \r3, q2, q4 + vqadd.s32 \r1, q5, q3 + vqsub.s32 \r2, q5, q3 +.endm + +.macro idct_2s_x4 r0, r1, r2, r3 + vmul_vmla d6, \r1, \r3, d1[1], d1[0] + vmul_vmla d4, \r0, \r2, d0[0], d0[0] + vmul_vmls d5, \r1, \r3, d1[0], d1[1] + vmul_vmls d7, \r0, \r2, d0[0], d0[0] + vrshr.s32 d6, d6, #12 + vrshr.s32 d4, d4, #12 + vrshr.s32 d5, d5, #12 + vrshr.s32 d7, d7, #12 + vqadd.s32 \r0, d4, d6 + vqsub.s32 \r3, d4, d6 + vqadd.s32 \r1, d7, d5 + vqsub.s32 \r2, d7, d5 +.endm + +function inv_dct_4s_x4_neon + movrel_local r12, idct_coeffs + vld1.32 {d0, d1}, [r12, :128] + idct_4s_x4 q8, q9, q10, q11 + bx lr +endfunc + +.macro iadst_4x4 o0, o1, o2, o3 + movrel_local r12, iadst4_coeffs + vld1.32 {d0, d1}, [r12, :128] + + vsub.i32 q1, q8, q10 + vmul.i32 q2, q8, d0[0] + vmla.i32 q2, q10, d0[1] + vmla.i32 q2, q11, d1[0] + vmul.i32 q4, q9, d1[1] + vadd.i32 q1, q1, q11 + vmul.i32 q3, q8, d1[0] + vmls.i32 q3, q10, d0[0] + vmls.i32 q3, q11, d0[1] + + vadd.i32 \o3, q2, q3 + vmul.i32 \o2, q1, d1[1] + vadd.i32 \o0, q2, q4 + vadd.i32 \o1, q3, q4 + vsub.i32 \o3, \o3, q4 + + vrshr.s32 \o0, \o0, #12 + vrshr.s32 \o2, \o2, #12 + vrshr.s32 \o1, \o1, #12 + vrshr.s32 \o3, \o3, #12 +.endm + +function inv_adst_4s_x4_neon + iadst_4x4 q8, q9, q10, q11 + bx lr +endfunc + +function inv_flipadst_4s_x4_neon + iadst_4x4 q11, q10, q9, q8 + bx lr +endfunc + +function inv_identity_4s_x4_neon + mov r12, #0 + movt r12, #(5793-4096)*8 + vdup.32 d0, r12 + vqrdmulh.s32 q1, q8, d0[0] + vqrdmulh.s32 q2, q9, d0[0] + vqrdmulh.s32 q3, q10, d0[0] + vqrdmulh.s32 q4, q11, d0[0] + vqadd.s32 q8, q8, q1 + vqadd.s32 q9, q9, q2 + vqadd.s32 q10, q10, q3 + vqadd.s32 q11, q11, q4 + bx lr +endfunc + +function inv_txfm_add_wht_wht_4x4_16bpc_neon, export=1 + push {r4-r5,lr} + vpush {q4-q5} + vmov.i16 q14, #0 + vmov.i16 q15, #0 + vld1.32 {q8, q9}, [r2, :128] + vst1.32 {q14, q15}, [r2, :128]! + vshr.s16 q8, q8, #2 + vld1.32 {q10, q11}, [r2, :128] + vshr.s16 q9, q9, #2 + vshr.s16 q10, q10, #2 + vshr.s16 q11, q11, #2 + + iwht4 + + vst1.32 {q14, q15}, [r2, :128] + transpose_4x4s q8, q9, q10, q11, d16, d17, d18, d19, d20, d21, d22, d23 + + iwht4 + + vld1.16 {d0}, [r0, :64], r1 + vqmovn.s32 d16, q8 + vld1.16 {d1}, [r0, :64], r1 + vqmovn.s32 d17, q9 + vld1.16 {d2}, [r0, :64], r1 + vqmovn.s32 d18, q10 + vld1.16 {d3}, [r0, :64], r1 + vqmovn.s32 d19, q11 + + b L(itx_4x4_end) +endfunc + +function inv_txfm_add_4x4_neon + vmov.i16 q14, #0 + vmov.i16 q15, #0 + vld1.32 {q8, q9}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128]! + vld1.32 {q10, q11}, [r2, :128] + vst1.16 {q14, q15}, [r2, :128] + + blx r4 + + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q9 + vqmovn.s32 d18, q10 + vqmovn.s32 d19, q11 + transpose_4x4h q8, q9, d16, d17, d18, d19 + + blx r5 + + vld1.16 {d0}, [r0, :64], r1 + vld1.16 {d1}, [r0, :64], r1 + vrshr.s16 q8, q8, #4 + vld1.16 {d2}, [r0, :64], r1 + vrshr.s16 q9, q9, #4 + vld1.16 {d3}, [r0, :64], r1 + +L(itx_4x4_end): + vmvn.i16 q15, #0xfc00 // 0x3ff + sub r0, r0, r1, lsl #2 + vqadd.s16 q8, q8, q0 + vqadd.s16 q9, q9, q1 + vmax.s16 q8, q8, q14 + vmax.s16 q9, q9, q14 + vmin.s16 q8, q8, q15 + vmin.s16 q9, q9, q15 + vst1.16 {d16}, [r0, :64], r1 + vst1.16 {d17}, [r0, :64], r1 + vst1.16 {d18}, [r0, :64], r1 + vst1.16 {d19}, [r0, :64], r1 + + vpop {q4-q5} + pop {r4-r5,pc} +endfunc + +.macro def_fn_4x4 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_4x4_16bpc_neon, export=1 + push {r4-r5,lr} + vpush {q4-q5} + +.ifc \txfm1\()_\txfm2, dct_dct + cmp r3, #0 + bne 1f + vmov.i16 q14, #0 + mov_const r12, 2896*8*(1<<16) + vld1.32 {d16[], d17[]}, [r2, :32] + vdup.32 d4, r12 + vst1.32 {d28[0]}, [r2, :32] + vqrdmulh.s32 q8, q8, d4[0] + vld1.16 {d0}, [r0, :64], r1 + vqmovn.s32 d20, q8 + vqmovn.s32 d21, q8 + vld1.16 {d1}, [r0, :64], r1 + vqrdmulh.s16 q10, q10, d4[1] + vld1.16 {d2}, [r0, :64], r1 + vrshr.s16 q8, q10, #4 + vld1.16 {d3}, [r0, :64], r1 + vrshr.s16 q9, q10, #4 + b L(itx_4x4_end) +1: +.endif + movrel_local r4, inv_\txfm1\()_4s_x4_neon + movrel r5, X(inv_\txfm2\()_4h_x4_neon) + b inv_txfm_add_4x4_neon +endfunc +.endm + +def_fn_4x4 dct, dct +def_fn_4x4 identity, identity +def_fn_4x4 dct, adst +def_fn_4x4 dct, flipadst +def_fn_4x4 dct, identity +def_fn_4x4 adst, dct +def_fn_4x4 adst, adst +def_fn_4x4 adst, flipadst +def_fn_4x4 flipadst, dct +def_fn_4x4 flipadst, adst +def_fn_4x4 flipadst, flipadst +def_fn_4x4 identity, dct + +def_fn_4x4 adst, identity +def_fn_4x4 flipadst, identity +def_fn_4x4 identity, adst +def_fn_4x4 identity, flipadst + +.macro idct_4s_x8 r0, r1, r2, r3, r4, r5, r6, r7 + idct_4s_x4 \r0, \r2, \r4, \r6 + + vmov.i32 q5, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 q4, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 +.irp r, \r0, \r2, \r4, \r6 + vmin.s32 \r, \r, q5 +.endr +.irp r, \r0, \r2, \r4, \r6 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmls q2, \r1, \r7, d2[0], d2[1] // -> t4a + vmul_vmla q3, \r1, \r7, d2[1], d2[0] // -> t7a + vmul_vmls q6, \r5, \r3, d3[0], d3[1] // -> t5a + vmul_vmla q7, \r5, \r3, d3[1], d3[0] // -> t6a + vrshr.s32 \r1, q2, #12 // t4a + vrshr.s32 \r7, q3, #12 // t7a + vrshr.s32 \r3, q6, #12 // t5a + vrshr.s32 \r5, q7, #12 // t6a + + vqadd.s32 q2, \r1, \r3 // t4 + vqsub.s32 \r1, \r1, \r3 // t5a + vqadd.s32 q3, \r7, \r5 // t7 + vqsub.s32 \r3, \r7, \r5 // t6a + +.irp r, q2, \r1, q3, \r3 + vmin.s32 \r, \r, q5 +.endr +.irp r, q2, \r1, q3, \r3 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmls q7, \r3, \r1, d0[0], d0[0] // -> t5 + vmul_vmla q6, \r3, \r1, d0[0], d0[0] // -> t6 + vrshr.s32 q7, q7, #12 // t5 + vrshr.s32 q5, q6, #12 // t6 + + vqsub.s32 \r7, \r0, q3 // out7 + vqadd.s32 \r0, \r0, q3 // out0 + vqadd.s32 \r1, \r2, q5 // out1 + vqsub.s32 q6, \r2, q5 // out6 + vqadd.s32 \r2, \r4, q7 // out2 + vqsub.s32 \r5, \r4, q7 // out5 + vqadd.s32 \r3, \r6, q2 // out3 + vqsub.s32 \r4, \r6, q2 // out4 + vmov \r6, q6 // out6 +.endm + +.macro idct_2s_x8 r0, r1, r2, r3, r4, r5, r6, r7 + idct_2s_x4 \r0, \r2, \r4, \r6 + + vmov.i32 d9, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 d8, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 +.irp r, \r0, \r2, \r4, \r6 + vmin.s32 \r, \r, d9 +.endr +.irp r, \r0, \r2, \r4, \r6 + vmax.s32 \r, \r, d8 +.endr + + vmul_vmls d4, \r1, \r7, d2[0], d2[1] // -> t4a + vmul_vmla d5, \r1, \r7, d2[1], d2[0] // -> t7a + vmul_vmls d6, \r5, \r3, d3[0], d3[1] // -> t5a + vmul_vmla d7, \r5, \r3, d3[1], d3[0] // -> t6a + vrshr.s32 \r1, d4, #12 // t4a + vrshr.s32 \r7, d5, #12 // t7a + vrshr.s32 \r3, d6, #12 // t5a + vrshr.s32 \r5, d7, #12 // t6a + + vqadd.s32 d4, \r1, \r3 // t4 + vqsub.s32 \r1, \r1, \r3 // t5a + vqadd.s32 d5, \r7, \r5 // t7 + vqsub.s32 \r3, \r7, \r5 // t6a + +.irp r, d4, \r1, d5, \r3 + vmin.s32 \r, \r, d9 +.endr +.irp r, d4, \r1, d5, \r3 + vmax.s32 \r, \r, d8 +.endr + + vmul_vmls d6, \r3, \r1, d0[0], d0[0] // -> t5 + vmul_vmla d7, \r3, \r1, d0[0], d0[0] // -> t6 + vrshr.s32 d6, d6, #12 // t5 + vrshr.s32 d7, d7, #12 // t6 + + vqsub.s32 \r7, \r0, d5 // out7 + vqadd.s32 \r0, \r0, d5 // out0 + vqadd.s32 \r1, \r2, d7 // out1 + vqsub.s32 d7, \r2, d7 // out6 + vqadd.s32 \r2, \r4, d6 // out2 + vqsub.s32 \r5, \r4, d6 // out5 + vqadd.s32 \r3, \r6, d4 // out3 + vqsub.s32 \r4, \r6, d4 // out4 + vmov \r6, d7 // out6 +.endm + +function inv_dct_4s_x8_neon + movrel_local r12, idct_coeffs + vld1.32 {q0, q1}, [r12, :128] + idct_4s_x8 q8, q9, q10, q11, q12, q13, q14, q15 + bx lr +endfunc + +.macro iadst_4s_x8 r0, r1, r2, r3, r4, r5, r6, r7 + movrel_local r12, iadst8_coeffs + vld1.32 {q0, q1}, [r12, :128]! + + vmul_vmla q2, q15, q8, d0[0], d0[1] + vmul_vmls q3, q15, q8, d0[1], d0[0] + vmul_vmla q4, q13, q10, d1[0], d1[1] + vrshr.s32 q8, q2, #12 // t0a + vrshr.s32 q15, q3, #12 // t1a + vmul_vmls q5, q13, q10, d1[1], d1[0] + vmul_vmla q6, q11, q12, d2[0], d2[1] + vrshr.s32 q10, q4, #12 // t2a + vrshr.s32 q13, q5, #12 // t3a + vmul_vmls q7, q11, q12, d2[1], d2[0] + vmul_vmla q2, q9, q14, d3[0], d3[1] + vrshr.s32 q12, q6, #12 // t4a + vrshr.s32 q11, q7, #12 // t5a + vmul_vmls q3, q9, q14, d3[1], d3[0] + vrshr.s32 q14, q2, #12 // t6a + vrshr.s32 q9, q3, #12 // t7a + + vld1.32 {q0}, [r12] + + vqadd.s32 q2, q8, q12 // t0 + vqsub.s32 q3, q8, q12 // t4 + vmov.i32 q12, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vqadd.s32 q4, q15, q11 // t1 + vqsub.s32 q5, q15, q11 // t5 + vqadd.s32 q6, q10, q14 // t2 + vqsub.s32 q7, q10, q14 // t6 + vmvn.i32 q14, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 + vqadd.s32 q10, q13, q9 // t3 + vqsub.s32 q11, q13, q9 // t7 + +.irp r, q2, q3, q4, q5, q6, q7, q10, q11 + vmin.s32 \r, \r, q12 +.endr +.irp r, q2, q3, q4, q5, q6, q7, q10, q11 + vmax.s32 \r, \r, q14 +.endr + + vmul_vmla q8, q3, q5, d1[1], d1[0] + vmul_vmls q13, q3, q5, d1[0], d1[1] + vmul_vmls q14, q11, q7, d1[1], d1[0] + + vrshr.s32 q3, q8, #12 // t4a + vrshr.s32 q5, q13, #12 // t5a + + vmul_vmla q8, q11, q7, d1[0], d1[1] + + vrshr.s32 q7, q14, #12 // t6a + vrshr.s32 q11, q8, #12 // t7a + + vqadd.s32 \r0, q2, q6 // out0 + vqsub.s32 q2, q2, q6 // t2 + vqadd.s32 \r7, q4, q10 // out7 + vqsub.s32 q4, q4, q10 // t3 + + vmvn.i32 q10, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 + + vqadd.s32 \r1, q3, q7 // out1 + vqsub.s32 q3, q3, q7 // t6 + vqadd.s32 \r6, q5, q11 // out6 + vqsub.s32 q5, q5, q11 // t7 + + // Not clipping the output registers, as they will be downshifted and + // narrowed afterwards anyway. +.irp r, q2, q4, q3, q5 + vmin.s32 \r, \r, q12 +.endr +.irp r, q2, q4, q3, q5 + vmax.s32 \r, \r, q10 +.endr + + vqneg.s32 \r7, \r7 // out7 + vqneg.s32 \r1, \r1 // out1 + + vmul_vmla q10, q2, q4, d0[0], d0[0] // -> out3 (q11 or q12) + vmul_vmls q6, q2, q4, d0[0], d0[0] // -> out4 (q12 or q11) + vmul_vmls q12, q3, q5, d0[0], d0[0] // -> out5 (q13 or q10) + vrshr.s32 q2, q10, #12 // out3 + vmul_vmla q10, q3, q5, d0[0], d0[0] // -> out2 (q10 or q13) + vrshr.s32 q3, q12, #12 // out5 + vrshr.s32 \r2, q10, #12 // out2 (q10 or q13) + vrshr.s32 \r4, q6, #12 // out4 (q12 or q11) + + vqneg.s32 \r3, q2 // out3 + vqneg.s32 \r5, q3 // out5 +.endm + +function inv_adst_4s_x8_neon + iadst_4s_x8 q8, q9, q10, q11, q12, q13, q14, q15 + bx lr +endfunc + +function inv_flipadst_4s_x8_neon + iadst_4s_x8 q15, q14, q13, q12, q11, q10, q9, q8 + bx lr +endfunc + +function inv_identity_4s_x8_neon + vqshl.s32 q8, q8, #1 + vqshl.s32 q9, q9, #1 + vqshl.s32 q10, q10, #1 + vqshl.s32 q11, q11, #1 + vqshl.s32 q12, q12, #1 + vqshl.s32 q13, q13, #1 + vqshl.s32 q14, q14, #1 + vqshl.s32 q15, q15, #1 + bx lr +endfunc + +function inv_txfm_add_8x8_neon + vmov.i32 q0, #0 + mov r7, #8*4 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r7 +.endr + + blx r4 + + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q12, #1 + vqrshrn.s32 d18, q9, #1 + vqrshrn.s32 d19, q13, #1 + vqrshrn.s32 d20, q10, #1 + vqrshrn.s32 d21, q14, #1 + vqrshrn.s32 d22, q11, #1 + vqrshrn.s32 d23, q15, #1 + + cmp r3, r10 + transpose_4x8h q8, q9, q10, q11 + + blt 1f + + sub r2, r2, r7, lsl #3 + vpush {q8-q11} + + add r2, r2, #16 + vmov.i32 q0, #0 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r7 +.endr + + blx r4 + + vqrshrn.s32 d31, q15, #1 + vqrshrn.s32 d30, q11, #1 + vqrshrn.s32 d29, q14, #1 + vqrshrn.s32 d28, q10, #1 + vqrshrn.s32 d27, q13, #1 + vqrshrn.s32 d26, q9, #1 + vqrshrn.s32 d25, q12, #1 + vqrshrn.s32 d24, q8, #1 + vpop {q8-q11} + + transpose_4x8h q12, q13, q14, q15 + + b 2f + +1: + vmov.i16 q12, #0 + vmov.i16 q13, #0 + vmov.i16 q14, #0 + vmov.i16 q15, #0 + +2: + blx r5 + + load_add_store_8x8 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,r10,pc} +endfunc + +.macro def_fn_8x8 txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_8x8_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 8, 8, 1 +.endif + push {r4-r5,r7,r10,lr} + vpush {q4-q7} + mov r10, #\eob_half + movrel_local r4, inv_\txfm1\()_4s_x8_neon + movrel r5, X(inv_\txfm2\()_8h_x8_neon) + b inv_txfm_add_8x8_neon +endfunc +.endm + +def_fn_8x8 dct, dct, 10 +def_fn_8x8 identity, identity, 10 +def_fn_8x8 dct, adst, 10 +def_fn_8x8 dct, flipadst, 10 +def_fn_8x8 dct, identity, 4 +def_fn_8x8 adst, dct, 10 +def_fn_8x8 adst, adst, 10 +def_fn_8x8 adst, flipadst, 10 +def_fn_8x8 flipadst, dct, 10 +def_fn_8x8 flipadst, adst, 10 +def_fn_8x8 flipadst, flipadst, 10 +def_fn_8x8 identity, dct, 4 +def_fn_8x8 adst, identity, 4 +def_fn_8x8 flipadst, identity, 4 +def_fn_8x8 identity, adst, 4 +def_fn_8x8 identity, flipadst, 4 + +function inv_txfm_add_8x4_neon + mov_const r12, 2896*8*(1<<16) + vmov.i32 q0, #0 + vmov.i32 q1, #0 + vld1.16 {q8, q9}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vdup.32 d4, r12 + vld1.16 {q10, q11}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vld1.16 {q12, q13}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + vld1.16 {q14, q15}, [r2, :128] + vst1.16 {q0, q1}, [r2, :128]! + + scale_input d4[0], q8, q9, q10, q11, q12, q13, q14, q15 + + blx r4 + + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q9 + vqmovn.s32 d18, q10 + vqmovn.s32 d19, q11 + vqmovn.s32 d20, q12 + vqmovn.s32 d21, q13 + vqmovn.s32 d22, q14 + vqmovn.s32 d23, q15 + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + vswp d17, d20 + vswp d19, d21 + vswp d18, d20 + vswp d21, d22 + + blx r5 + + load_add_store_8x4 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,r10,pc} +endfunc + +function inv_txfm_add_4x8_neon + mov_const r12, 2896*8*(1<<16) + vmov.i32 q0, #0 + cmp r3, r10 + mov r7, #32 + blt 1f + + add r2, r2, #16 + vdup.32 d2, r12 +.irp i, q8, q9, q10, q11 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r7 +.endr + + scale_input d2[0], q8, q9, q10, q11 + sub r2, r2, r7, lsl #2 + + blx r4 + + sub r2, r2, #16 + + vqmovn.s32 d24, q8 + vqmovn.s32 d25, q9 + vqmovn.s32 d26, q10 + vqmovn.s32 d27, q11 + transpose_4x4h q12, q13, d24, d25, d26, d27 + + b 2f + +1: + vmov.i16 q12, #0 + vmov.i16 q13, #0 + +2: + mov_const r12, 2896*8*(1<<16) + vmov.i32 q0, #0 + vdup.32 d2, r12 +.irp i, q8, q9, q10, q11 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r7 +.endr + scale_input d2[0], q8, q9, q10, q11 + blx r4 + + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q9 + vqmovn.s32 d18, q10 + vqmovn.s32 d19, q11 + transpose_4x4h q8, q9, d16, d17, d18, d19 + + vmov q10, q12 + vmov q11, q13 + + blx r5 + + load_add_store_4x8 r0, r7 + vpop {q4-q7} + pop {r4-r5,r7,r10,pc} +endfunc + +.macro def_fn_48 w, h, txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 0 +.endif + push {r4-r5,r7,r10,lr} + vpush {q4-q7} + movrel_local r4, inv_\txfm1\()_4s_x\w\()_neon +.if \w == 4 + mov r10, #\eob_half +.endif + movrel r5, X(inv_\txfm2\()_\w\()h_x\h\()_neon) + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_48 w, h +def_fn_48 \w, \h, dct, dct, 13 +def_fn_48 \w, \h, identity, identity, 13 +def_fn_48 \w, \h, dct, adst, 13 +def_fn_48 \w, \h, dct, flipadst, 13 +def_fn_48 \w, \h, dct, identity, 4 +def_fn_48 \w, \h, adst, dct, 13 +def_fn_48 \w, \h, adst, adst, 13 +def_fn_48 \w, \h, adst, flipadst, 13 +def_fn_48 \w, \h, flipadst, dct, 13 +def_fn_48 \w, \h, flipadst, adst, 13 +def_fn_48 \w, \h, flipadst, flipadst, 13 +def_fn_48 \w, \h, identity, dct, 16 +def_fn_48 \w, \h, adst, identity, 4 +def_fn_48 \w, \h, flipadst, identity, 4 +def_fn_48 \w, \h, identity, adst, 16 +def_fn_48 \w, \h, identity, flipadst, 16 +.endm + +def_fns_48 4, 8 +def_fns_48 8, 4 + +function inv_dct_2s_x16_neon + movrel_local r12, idct_coeffs + vld1.32 {q0, q1}, [r12, :128]! + + idct_2s_x8 d16, d18, d20, d22, d24, d26, d28, d30 + + // idct_8 leaves the row_clip_max/min constants in d9 and d8 +.irp r, d16, d18, d20, d22, d24, d26, d28, d30 + vmin.s32 \r, \r, d9 +.endr +.irp r, d16, d18, d20, d22, d24, d26, d28, d30 + vmax.s32 \r, \r, d8 +.endr + + vld1.32 {q0, q1}, [r12, :128] + sub r12, r12, #32 + + vmul_vmls d4, d17, d31, d0[0], d0[1] // -> t8a + vmul_vmla d5, d17, d31, d0[1], d0[0] // -> t15a + vmul_vmls d6, d25, d23, d1[0], d1[1] // -> t9a + vrshr.s32 d17, d4, #12 // t8a + vrshr.s32 d31, d5, #12 // t15a + vmul_vmla d4, d25, d23, d1[1], d1[0] // -> t14a + vmul_vmls d5, d21, d27, d2[0], d2[1] // -> t10a + vrshr.s32 d23, d6, #12 // t9a + vrshr.s32 d25, d4, #12 // t14a + vmul_vmla d6, d21, d27, d2[1], d2[0] // -> t13a + vmul_vmls d4, d29, d19, d3[0], d3[1] // -> t11a + vrshr.s32 d21, d5, #12 // t10a + vrshr.s32 d27, d6, #12 // t13a + vmul_vmla d5, d29, d19, d3[1], d3[0] // -> t12a + vrshr.s32 d19, d4, #12 // t11a + vrshr.s32 d29, d5, #12 // t12a + + vld1.32 {q0}, [r12, :128] + + vqsub.s32 d4, d17, d23 // t9 + vqadd.s32 d17, d17, d23 // t8 + vqsub.s32 d5, d31, d25 // t14 + vqadd.s32 d31, d31, d25 // t15 + vqsub.s32 d23, d19, d21 // t10 + vqadd.s32 d19, d19, d21 // t11 + vqadd.s32 d25, d29, d27 // t12 + vqsub.s32 d29, d29, d27 // t13 + +.irp r, d4, d17, d5, d31, d23, d19, d25, d29 + vmin.s32 \r, \r, d9 +.endr +.irp r, d4, d17, d5, d31, d23, d19, d25, d29 + vmax.s32 \r, \r, d8 +.endr + + vmul_vmls d6, d5, d4, d1[0], d1[1] // -> t9a + vmul_vmla d7, d5, d4, d1[1], d1[0] // -> t14a + vrshr.s32 d21, d6, #12 // t9a + vrshr.s32 d27, d7, #12 // t14a + + vmul_vmls d6, d29, d23, d1[0], d1[1] // -> t13a + vmul_vmla d7, d29, d23, d1[1], d1[0] // -> t10a + vrshr.s32 d29, d6, #12 // t13a + vneg.s32 d7, d7 + vrshr.s32 d23, d7, #12 // t10a + + vqsub.s32 d4, d17, d19 // t11a + vqadd.s32 d17, d17, d19 // t8a + vqsub.s32 d5, d31, d25 // t12a + vqadd.s32 d31, d31, d25 // t15a + vqadd.s32 d19, d21, d23 // t9 + vqsub.s32 d21, d21, d23 // t10 + vqsub.s32 d25, d27, d29 // t13 + vqadd.s32 d27, d27, d29 // t14 + +.irp r, d4, d17, d5, d31, d19, d21, d25, d27 + vmin.s32 \r, \r, d9 +.endr +.irp r, d4, d17, d5, d31, d19, d21, d25, d27 + vmax.s32 \r, \r, d8 +.endr + + vmul_vmls d6, d5, d4, d0[0], d0[0] // -> t11 + vmul_vmla d7, d5, d4, d0[0], d0[0] // -> t12 + vmul_vmls d4, d25, d21, d0[0], d0[0] // -> t10a + + vrshr.s32 d6, d6, #12 // t11 + vrshr.s32 d7, d7, #12 // t12 + vmul_vmla d5, d25, d21, d0[0], d0[0] // -> t13a + vrshr.s32 d4, d4, #12 // t10a + vrshr.s32 d5, d5, #12 // t13a + + vqadd.s32 d8, d16, d31 // out0 + vqsub.s32 d31, d16, d31 // out15 + vmov d16, d8 + vqadd.s32 d23, d30, d17 // out7 + vqsub.s32 d9, d30, d17 // out8 + vqadd.s32 d17, d18, d27 // out1 + vqsub.s32 d30, d18, d27 // out14 + vqadd.s32 d18, d20, d5 // out2 + vqsub.s32 d29, d20, d5 // out13 + vqadd.s32 d5, d28, d19 // out6 + vqsub.s32 d25, d28, d19 // out9 + vqadd.s32 d19, d22, d7 // out3 + vqsub.s32 d28, d22, d7 // out12 + vqadd.s32 d20, d24, d6 // out4 + vqsub.s32 d27, d24, d6 // out11 + vqadd.s32 d21, d26, d4 // out5 + vqsub.s32 d26, d26, d4 // out10 + vmov d24, d9 + vmov d22, d5 + + bx lr +endfunc + +.macro iadst_16 o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15 + movrel_local r12, iadst16_coeffs + vld1.32 {q0, q1}, [r12, :128]! + + vmul_vmla d4, d31, d16, d0[0], d0[1] // -> t0 + vmul_vmls d6, d31, d16, d0[1], d0[0] // -> t1 + vmul_vmla d8, d29, d18, d1[0], d1[1] // -> t2 + vrshr.s32 d16, d4, #12 // t0 + vrshr.s32 d31, d6, #12 // t1 + vmul_vmls d4, d29, d18, d1[1], d1[0] // -> t3 + vmul_vmla d6, d27, d20, d2[0], d2[1] // -> t4 + vrshr.s32 d18, d8, #12 // t2 + vrshr.s32 d29, d4, #12 // t3 + vmul_vmls d8, d27, d20, d2[1], d2[0] // -> t5 + vmul_vmla d4, d25, d22, d3[0], d3[1] // -> t6 + vrshr.s32 d20, d6, #12 // t4 + vrshr.s32 d27, d8, #12 // t5 + vmul_vmls d6, d25, d22, d3[1], d3[0] // -> t7 + vld1.32 {q0, q1}, [r12, :128] + movrel_local r12, idct_coeffs + vmul_vmla d8, d23, d24, d0[0], d0[1] // -> t8 + vrshr.s32 d22, d4, #12 // t6 + vrshr.s32 d25, d6, #12 // t7 + vmul_vmls d4, d23, d24, d0[1], d0[0] // -> t9 + vmul_vmla d6, d21, d26, d1[0], d1[1] // -> t10 + vrshr.s32 d23, d8, #12 // t8 + vrshr.s32 d24, d4, #12 // t9 + vmul_vmls d8, d21, d26, d1[1], d1[0] // -> t11 + vmul_vmla d4, d19, d28, d2[0], d2[1] // -> t12 + vrshr.s32 d21, d6, #12 // t10 + vrshr.s32 d26, d8, #12 // t11 + vmul_vmls d6, d19, d28, d2[1], d2[0] // -> t13 + vmul_vmla d8, d17, d30, d3[0], d3[1] // -> t14 + vrshr.s32 d19, d4, #12 // t12 + vrshr.s32 d28, d6, #12 // t13 + vmul_vmls d4, d17, d30, d3[1], d3[0] // -> t15 + vrshr.s32 d17, d8, #12 // t14 + vrshr.s32 d30, d4, #12 // t15 + + vld1.32 {q0, q1}, [r12, :128] + + vmov.i32 d11, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 d10, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 + + vqsub.s32 d5, d16, d23 // t8a + vqadd.s32 d16, d16, d23 // t0a + vqsub.s32 d7, d31, d24 // t9a + vqadd.s32 d31, d31, d24 // t1a + vqadd.s32 d23, d18, d21 // t2a + vqsub.s32 d18, d18, d21 // t10a + vqadd.s32 d24, d29, d26 // t3a + vqsub.s32 d29, d29, d26 // t11a + vqadd.s32 d21, d20, d19 // t4a + vqsub.s32 d20, d20, d19 // t12a + vqadd.s32 d26, d27, d28 // t5a + vqsub.s32 d27, d27, d28 // t13a + vqadd.s32 d19, d22, d17 // t6a + vqsub.s32 d22, d22, d17 // t14a + vqadd.s32 d28, d25, d30 // t7a + vqsub.s32 d25, d25, d30 // t15a + +.irp r, d5, d16, d7, d31, d23, d18, d24, d29, d21, d20, d26, d27, d19, d22, d28, d25 + vmin.s32 \r, \r, d11 +.endr +.irp r, d5, d16, d7, d31, d23, d18, d24, d29, d21, d20, d26, d27, d19, d22, d28, d25 + vmax.s32 \r, \r, d10 +.endr + + vmul_vmla d4, d5, d7, d2[1], d2[0] // -> t8 + vmul_vmls d6, d5, d7, d2[0], d2[1] // -> t9 + vmul_vmla d8, d18, d29, d3[1], d3[0] // -> t10 + vrshr.s32 d17, d4, #12 // t8 + vrshr.s32 d30, d6, #12 // t9 + vmul_vmls d4, d18, d29, d3[0], d3[1] // -> t11 + vmul_vmls d6, d27, d20, d2[1], d2[0] // -> t12 + vrshr.s32 d18, d8, #12 // t10 + vrshr.s32 d29, d4, #12 // t11 + vmul_vmla d8, d27, d20, d2[0], d2[1] // -> t13 + vmul_vmls d4, d25, d22, d3[1], d3[0] // -> t14 + vrshr.s32 d27, d6, #12 // t12 + vrshr.s32 d20, d8, #12 // t13 + vmul_vmla d6, d25, d22, d3[0], d3[1] // -> t15 + vrshr.s32 d25, d4, #12 // t14 + vrshr.s32 d22, d6, #12 // t15 + + vqsub.s32 d2, d16, d21 // t4 + vqadd.s32 d16, d16, d21 // t0 + vqsub.s32 d3, d31, d26 // t5 + vqadd.s32 d31, d31, d26 // t1 + vqadd.s32 d21, d23, d19 // t2 + vqsub.s32 d23, d23, d19 // t6 + vqadd.s32 d26, d24, d28 // t3 + vqsub.s32 d24, d24, d28 // t7 + vqadd.s32 d19, d17, d27 // t8a + vqsub.s32 d17, d17, d27 // t12a + vqadd.s32 d28, d30, d20 // t9a + vqsub.s32 d30, d30, d20 // t13a + vqadd.s32 d27, d18, d25 // t10a + vqsub.s32 d18, d18, d25 // t14a + vqadd.s32 d20, d29, d22 // t11a + vqsub.s32 d29, d29, d22 // t15a + +.irp r, d2, d16, d3, d31, d21, d23, d26, d24, d19, d17, d28, d30, d27, d18, d20, d29 + vmin.s32 \r, \r, d11 +.endr +.irp r, d2, d16, d3, d31, d21, d23, d26, d24, d19, d17, d28, d30, d27, d18, d20, d29 + vmax.s32 \r, \r, d10 +.endr + + vmul_vmla d4, d2, d3, d1[1], d1[0] // -> t4a + vmul_vmls d6, d2, d3, d1[0], d1[1] // -> t5a + vmul_vmls d8, d24, d23, d1[1], d1[0] // -> t6a + vrshr.s32 d22, d4, #12 // t4a + vrshr.s32 d25, d6, #12 // t5a + vmul_vmla d4, d24, d23, d1[0], d1[1] // -> t7a + vmul_vmla d6, d17, d30, d1[1], d1[0] // -> t12 + vrshr.s32 d24, d8, #12 // t6a + vrshr.s32 d23, d4, #12 // t7a + vmul_vmls d8, d17, d30, d1[0], d1[1] // -> t13 + vmul_vmls d4, d29, d18, d1[1], d1[0] // -> t14 + vrshr.s32 d17, d6, #12 // t12 + vmul_vmla d6, d29, d18, d1[0], d1[1] // -> t15 + vrshr.s32 d29, d8, #12 // t13 + vrshr.s32 d30, d4, #12 // t14 + vrshr.s32 d18, d6, #12 // t15 + + vqsub.s32 d2, d16, d21 // t2a +.ifc \o0, d16 + vqadd.s32 \o0, d16, d21 // out0 + vqsub.s32 d21, d31, d26 // t3a + vqadd.s32 \o15,d31, d26 // out15 +.else + vqadd.s32 d4, d16, d21 // out0 + vqsub.s32 d21, d31, d26 // t3a + vqadd.s32 \o15,d31, d26 // out15 + vmov \o0, d4 +.endif + + vqsub.s32 d3, d29, d18 // t15a + vqadd.s32 \o13,d29, d18 // out13 + vqadd.s32 \o2, d17, d30 // out2 + vqsub.s32 d26, d17, d30 // t14a + + vqadd.s32 \o1, d19, d27 // out1 + vqsub.s32 d27, d19, d27 // t10 + vqadd.s32 \o14,d28, d20 // out14 + vqsub.s32 d20, d28, d20 // t11 + + vqadd.s32 \o3, d22, d24 // out3 + vqsub.s32 d22, d22, d24 // t6 + vqadd.s32 \o12,d25, d23 // out12 + vqsub.s32 d23, d25, d23 // t7 + + // Not clipping the output registers, as they will be downshifted and + // narrowed afterwards anyway. +.irp r, d2, d21, d3, d26, d27, d20, d22, d23 + vmin.s32 \r, \r, d11 +.endr +.irp r, d2, d21, d3, d26, d27, d20, d22, d23 + vmax.s32 \r, \r, d10 +.endr + + vqneg.s32 \o15, \o15 // out15 + vqneg.s32 \o13,\o13 // out13 + vqneg.s32 \o1, \o1 // out1 + vqneg.s32 \o3, \o3 // out3 + + vmul_vmls d24, d2, d21, d0[0], d0[0] // -> out8 (d24 or d23) + vmul_vmla d4, d2, d21, d0[0], d0[0] // -> out7 (d23 or d24) + vmul_vmla d6, d26, d3, d0[0], d0[0] // -> out5 (d21 or d26) + + vrshr.s32 d24, d24, #12 // out8 + vrshr.s32 d4, d4, #12 // out7 + vrshr.s32 d5, d6, #12 // out5 + vmul_vmls d8, d26, d3, d0[0], d0[0] // -> out10 (d26 or d21) + vmul_vmla d2, d22, d23, d0[0], d0[0] // -> out4 (d20 or d27) + vrshr.s32 d26, d8, #12 // out10 + + vmul_vmls d8, d22, d23, d0[0], d0[0] // -> out11 (d27 or d20) + vmul_vmla d22, d27, d20, d0[0], d0[0] // -> out6 (d22 or d25) + vmul_vmls d6, d27, d20, d0[0], d0[0] // -> out9 (d25 or d22) + + vrshr.s32 \o4, d2, #12 // out4 + vrshr.s32 d7, d6, #12 // out9 + vrshr.s32 d6, d8, #12 // out11 + vrshr.s32 \o6, d22, #12 // out6 + +.ifc \o8, d23 + vmov \o8, d24 + vmov \o10,d26 +.endif + + vqneg.s32 \o7, d4 // out7 + vqneg.s32 \o5, d5 // out5 + vqneg.s32 \o11,d6 // out11 + vqneg.s32 \o9, d7 // out9 +.endm + +function inv_adst_2s_x16_neon + iadst_16 d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + bx lr +endfunc + +function inv_flipadst_2s_x16_neon + iadst_16 d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16 + bx lr +endfunc + +function inv_identity_2s_x16_neon + mov r12, #0 + movt r12, #2*(5793-4096)*8 + vdup.32 d0, r12 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s32 q1, \i, d0[0] + vqadd.s32 \i, \i, \i + vqadd.s32 \i, \i, q1 +.endr + bx lr +endfunc + +.macro identity_8x4_shift1 c +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s32 q2, \i, \c + vrshr.s32 q2, q2, #1 + vqadd.s32 \i, \i, q2 +.endr +.endm + +.macro identity_8x4 c +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vqrdmulh.s32 q2, \i, \c + vqadd.s32 \i, \i, \i + vqadd.s32 \i, \i, q2 +.endr +.endm + +.macro def_horz_16 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_16x2_neon + push {lr} + vmov.i32 d7, #0 +.if \scale + mov_const r12, 2896*8*(1<<16) + vdup.32 d1, r12 +.endif +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.32 {\i}, [r7, :64] + vst1.32 {d7}, [r7, :64], r8 +.endr +.if \scale + scale_input d1[0], q8, q9, q10, q11, q12, q13, q14, q15 +.endif + blx r4 + vqrshrn.s32 d16, q8, #\shift + vqrshrn.s32 d17, q9, #\shift + vqrshrn.s32 d18, q10, #\shift + vqrshrn.s32 d19, q11, #\shift + vqrshrn.s32 d20, q12, #\shift + vqrshrn.s32 d21, q13, #\shift + vqrshrn.s32 d22, q14, #\shift + vqrshrn.s32 d23, q15, #\shift + vuzp.16 q8, q9 + vuzp.16 q10, q11 + +.irp i, q8, q10, q9, q11 + vst1.16 {\i}, [r6, :128]! +.endr + + pop {pc} +endfunc +.endm + +def_horz_16 scale=0, shift=2 +def_horz_16 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_4x16_neon + push {lr} +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + blx r5 + load_add_store_4x16 r6, r7 + pop {pc} +endfunc + +function inv_txfm_add_16x16_neon + sub_sp_align 512 + ldrh r11, [r10], #2 +.irp i, 0, 2, 4, 6, 8, 10, 12, 14 + add r6, sp, #(\i*16*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.if \i < 14 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #16*4 + bl inv_txfm_horz_16x2_neon +.endr + b 3f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b +3: +.irp i, 0, 4, 8, 12 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #32 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 512 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +const eob_16x16 + .short 3, 10, 21, 36, 55, 78, 105, 256 +endconst + +const eob_16x16_identity + .short 2, 4, 6, 8, 10, 12, 14, 256 +endconst + +.macro def_fn_16x16 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_16x16_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 16, 16, 2 +.endif + push {r4-r11,lr} + vpush {q4-q7} + movrel_local r4, inv_\txfm1\()_2s_x16_neon + movrel r5, X(inv_\txfm2\()_4h_x16_neon) +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel_local r10, eob_16x16 +.else + movrel_local r10, eob_16x16_identity +.endif +.else +.ifc \txfm2, identity + movrel_local r10, eob_16x16_identity +.else + movrel_local r10, eob_16x16 +.endif +.endif + b inv_txfm_add_16x16_neon +endfunc +.endm + +def_fn_16x16 dct, dct +def_fn_16x16 identity, identity +def_fn_16x16 dct, adst +def_fn_16x16 dct, flipadst +def_fn_16x16 dct, identity +def_fn_16x16 adst, dct +def_fn_16x16 adst, adst +def_fn_16x16 adst, flipadst +def_fn_16x16 flipadst, dct +def_fn_16x16 flipadst, adst +def_fn_16x16 flipadst, flipadst +def_fn_16x16 identity, dct + +function inv_txfm_add_16x4_neon + cmp r3, r10 + mov r11, #16 + blt 1f + + add r6, r2, #8 + vmov.i32 d4, #0 +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.32 {\i}, [r6, :64] + vst1.32 {d4}, [r6, :64], r11 +.endr + blx r4 + + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q9, #1 + vqrshrn.s32 d18, q10, #1 + vqrshrn.s32 d19, q11, #1 + vqrshrn.s32 d20, q12, #1 + vqrshrn.s32 d21, q13, #1 + vqrshrn.s32 d22, q14, #1 + vqrshrn.s32 d23, q15, #1 + vuzp.16 q8, q9 + mov r6, sp + vuzp.16 q10, q11 + vpush {q8-q11} + + b 2f + +1: + vmov.i16 q8, #0 + vmov.i16 q9, #0 + mov r6, sp + vpush {q8-q9} + vpush {q8-q9} + +2: + vmov.i32 d4, #0 +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.32 {\i}, [r2, :64] + vst1.32 {d4}, [r2, :64], r11 +.endr + + blx r4 + + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q9, #1 + vqrshrn.s32 d18, q10, #1 + vqrshrn.s32 d19, q11, #1 + vqrshrn.s32 d20, q12, #1 + vqrshrn.s32 d21, q13, #1 + vqrshrn.s32 d22, q14, #1 + vqrshrn.s32 d23, q15, #1 + vuzp.16 q8, q9 + mov r6, sp + vuzp.16 q10, q11 + + vmov q12, q10 + vmov q13, q11 + + vpop {q10-q11} + blx r5 + mov r6, r0 + load_add_store_8x4 r6, r7 + + vpop {q10-q11} + vmov q8, q12 + vmov q9, q13 + blx r5 + add r6, r0, #16 + load_add_store_8x4 r6, r7 + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_4x16_neon + ldrh r9, [r10, #4] + + mov r11, #64 + cmp r3, r9 + ldrh r9, [r10, #2] + blt 1f + + add r6, r2, #48 + vmov.i32 q2, #0 +.irp i, q8, q9, q10, q11 + vld1.32 {\i}, [r6, :128] + vst1.32 {q2}, [r6, :128], r11 +.endr + blx r4 + vqrshrn.s32 d28, q8, #1 + vqrshrn.s32 d29, q9, #1 + vqrshrn.s32 d30, q10, #1 + vqrshrn.s32 d31, q11, #1 + transpose_4x4h q14, q15, d28, d29, d30, d31 + + b 2f +1: + vmov.i16 q14, #0 + vmov.i16 q15, #0 +2: + cmp r3, r9 + ldrh r9, [r10] + blt 1f + + add r6, r2, #32 + vmov.i32 q2, #0 +.irp i, q8, q9, q10, q11 + vld1.32 {\i}, [r6, :128] + vst1.32 {q2}, [r6, :128], r11 +.endr + blx r4 + vqrshrn.s32 d24, q8, #1 + vqrshrn.s32 d25, q9, #1 + vqrshrn.s32 d26, q10, #1 + vqrshrn.s32 d27, q11, #1 + transpose_4x4h q12, q13, d24, d25, d26, d27 + + b 2f +1: + vmov.i16 q12, #0 + vmov.i16 q13, #0 +2: + cmp r3, r9 + blt 1f + + add r6, r2, #16 + vmov.i32 q2, #0 +.irp i, q8, q9, q10, q11 + vld1.32 {\i}, [r6, :128] + vst1.32 {q2}, [r6, :128], r11 +.endr + blx r4 + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q9, #1 + vqrshrn.s32 d18, q10, #1 + vqrshrn.s32 d19, q11, #1 + transpose_4x4h q8, q9, d16, d17, d18, d19 + + b 2f +1: + vmov.i16 q8, #0 + vmov.i16 q9, #0 +2: + vmov.i16 q2, #0 + vpush {q8-q9} +.irp i, q8, q9, q10, q11 + vld1.16 {\i}, [r2, :128] + vst1.16 {q2}, [r2, :128], r11 +.endr + blx r4 + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q9, #1 + vqrshrn.s32 d18, q10, #1 + vqrshrn.s32 d19, q11, #1 + transpose_4x4h q8, q9, d16, d17, d18, d19 + vpop {q10-q11} + + blx r5 + + load_add_store_4x16 r0, r6 + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +const eob_4x16 + .short 13, 29, 45, 64 +endconst + +const eob_4x16_identity1 + .short 16, 32, 48, 64 +endconst + +const eob_4x16_identity2 + .short 4, 8, 12, 64 +endconst + +.macro def_fn_416 w, h, txfm1, txfm2, eob_16x4 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + push {r4-r11,lr} + vpush {q4-q7} +.if \w == 4 + movrel_local r4, inv_\txfm1\()_4s_x\w\()_neon + movrel r5, X(inv_\txfm2\()_4h_x\h\()_neon) +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel_local r10, eob_4x16 +.else + movrel_local r10, eob_4x16_identity1 +.endif +.else +.ifc \txfm2, identity + movrel_local r10, eob_4x16_identity2 +.else + movrel_local r10, eob_4x16 +.endif +.endif +.else + mov r10, #\eob_16x4 + movrel_local r4, inv_\txfm1\()_2s_x\w\()_neon + movrel r5, X(inv_\txfm2\()_8h_x\h\()_neon) +.endif + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_416 w, h +def_fn_416 \w, \h, dct, dct, 3 +def_fn_416 \w, \h, identity, identity, 3 +def_fn_416 \w, \h, dct, adst, 3 +def_fn_416 \w, \h, dct, flipadst, 3 +def_fn_416 \w, \h, dct, identity, 2 +def_fn_416 \w, \h, adst, dct, 3 +def_fn_416 \w, \h, adst, adst, 3 +def_fn_416 \w, \h, adst, flipadst, 3 +def_fn_416 \w, \h, flipadst, dct, 3 +def_fn_416 \w, \h, flipadst, adst, 3 +def_fn_416 \w, \h, flipadst, flipadst, 3 +def_fn_416 \w, \h, identity, dct, 2 +def_fn_416 \w, \h, adst, identity, 2 +def_fn_416 \w, \h, flipadst, identity, 2 +def_fn_416 \w, \h, identity, adst, 2 +def_fn_416 \w, \h, identity, flipadst, 2 +.endm + +def_fns_416 4, 16 +def_fns_416 16, 4 + +function inv_txfm_add_16x8_neon + sub_sp_align 256 + ldrh r11, [r10], #2 + +.irp i, 0, 2, 4, 6 + add r6, sp, #(\i*16*2) +.if \i > 0 + mov r8, #(8 - \i) + cmp r3, r11 + blt 1f +.if \i < 6 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #8*4 + bl inv_txfm_horz_scale_16x2_neon +.endr + b 3f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b +3: + +.irp i, 0, 8 + add r7, sp, #(\i*2) + mov r8, #32 +.irp j, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\j}, [r7, :128], r8 +.endr + blx r5 + + add r6, r0, #(\i*2) + load_add_store_8x8 r6, r7 +.endr + + add_sp_align 256 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_8x16_neon + add r10, r10, #2 + sub_sp_align 256 + ldrh r11, [r10], #4 + +.irp i, 0, 4, 8, 12 + add r6, sp, #(\i*8*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.if \i < 12 + ldrh r11, [r10], #4 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #16*4 + + mov_const r12, 2896*8*(1<<16) + vmov.i32 q2, #0 + vdup.32 d0, r12 + +.irp j, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\j}, [r7, :128] + vst1.32 {q2}, [r7, :128], r8 +.endr + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 + blx r4 + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q9, #1 + vqrshrn.s32 d18, q10, #1 + vqrshrn.s32 d19, q11, #1 + vqrshrn.s32 d20, q12, #1 + vqrshrn.s32 d21, q13, #1 + vqrshrn.s32 d22, q14, #1 + vqrshrn.s32 d23, q15, #1 + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 +.irp j, d16, d20, d17, d21, d18, d22, d19, d23 + vst1.16 {\j}, [r6, :64]! +.endr +.endr + b 3f +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #4 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b +3: + +.irp i, 0, 4 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #16 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 256 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +const eob_8x16 + .short 3, 10, 21, 43, 59, 75, 91, 128 +endconst + +const eob_8x16_identity1 + .short 2, 4, 6, 64, 80, 96, 112, 128 +endconst + +const eob_8x16_identity2 + .short 2, 4, 6, 8, 10, 12, 14, 128 +endconst + +.macro def_fn_816 w, h, txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + push {r4-r11,lr} + vpush {q4-q7} +.if \w == 8 + movrel_local r4, inv_\txfm1\()_4s_x8_neon + movrel r5, X(inv_\txfm2\()_4h_x16_neon) +.else + movrel_local r4, inv_\txfm1\()_2s_x16_neon + movrel r5, X(inv_\txfm2\()_8h_x8_neon) +.endif +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel_local r10, eob_8x16 +.else + movrel_local r10, eob_8x16_identity1 +.endif +.else +.ifc \txfm2, identity + movrel_local r10, eob_8x16_identity2 +.else + movrel_local r10, eob_8x16 +.endif +.endif + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_816 w, h +def_fn_816 \w, \h, dct, dct +def_fn_816 \w, \h, identity, identity +def_fn_816 \w, \h, dct, adst +def_fn_816 \w, \h, dct, flipadst +def_fn_816 \w, \h, dct, identity +def_fn_816 \w, \h, adst, dct +def_fn_816 \w, \h, adst, adst +def_fn_816 \w, \h, adst, flipadst +def_fn_816 \w, \h, flipadst, dct +def_fn_816 \w, \h, flipadst, adst +def_fn_816 \w, \h, flipadst, flipadst +def_fn_816 \w, \h, identity, dct +def_fn_816 \w, \h, adst, identity +def_fn_816 \w, \h, flipadst, identity +def_fn_816 \w, \h, identity, adst +def_fn_816 \w, \h, identity, flipadst +.endm + +def_fns_816 8, 16 +def_fns_816 16, 8 + +function inv_dct32_odd_2s_x16_neon + movrel_local r12, idct_coeffs, 4*16 + vld1.32 {q0, q1}, [r12, :128]! + + vmul_vmls d4, d16, d31, d0[0], d0[1] // -> t16a + vmul_vmla d6, d16, d31, d0[1], d0[0] // -> t31a + vmul_vmls d8, d24, d23, d1[0], d1[1] // -> t17a + vrshr.s32 d16, d4, #12 // t16a + vrshr.s32 d31, d6, #12 // t31a + vmul_vmla d4, d24, d23, d1[1], d1[0] // -> t30a + vmul_vmls d6, d20, d27, d2[0], d2[1] // -> t18a + vrshr.s32 d24, d8, #12 // t17a + vrshr.s32 d23, d4, #12 // t30a + vmul_vmla d8, d20, d27, d2[1], d2[0] // -> t29a + vmul_vmls d4, d28, d19, d3[0], d3[1] // -> t19a + vrshr.s32 d20, d6, #12 // t18a + vrshr.s32 d27, d8, #12 // t29a + vmul_vmla d6, d28, d19, d3[1], d3[0] // -> t28a + vld1.32 {q0, q1}, [r12, :128] + sub r12, r12, #4*24 + vmul_vmls d8, d18, d29, d0[0], d0[1] // -> t20a + vrshr.s32 d28, d4, #12 // t19a + vrshr.s32 d19, d6, #12 // t28a + vmul_vmla d4, d18, d29, d0[1], d0[0] // -> t27a + vmul_vmls d6, d26, d21, d1[0], d1[1] // -> t21a + vrshr.s32 d18, d8, #12 // t20a + vrshr.s32 d29, d4, #12 // t27a + vmul_vmla d8, d26, d21, d1[1], d1[0] // -> t26a + vmul_vmls d4, d22, d25, d2[0], d2[1] // -> t22a + vrshr.s32 d26, d6, #12 // t21a + vrshr.s32 d21, d8, #12 // t26a + vmul_vmla d6, d22, d25, d2[1], d2[0] // -> t25a + vmul_vmls d8, d30, d17, d3[0], d3[1] // -> t23a + vrshr.s32 d22, d4, #12 // t22a + vrshr.s32 d25, d6, #12 // t25a + vmul_vmla d4, d30, d17, d3[1], d3[0] // -> t24a + vrshr.s32 d30, d8, #12 // t23a + vrshr.s32 d17, d4, #12 // t24a + + vld1.32 {q0, q1}, [r12, :128] + + vmov.i32 d11, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 d10, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 + + vqsub.s32 d5, d16, d24 // t17 + vqadd.s32 d16, d16, d24 // t16 + vqsub.s32 d7, d31, d23 // t30 + vqadd.s32 d31, d31, d23 // t31 + vqsub.s32 d24, d28, d20 // t18 + vqadd.s32 d28, d28, d20 // t19 + vqadd.s32 d23, d18, d26 // t20 + vqsub.s32 d18, d18, d26 // t21 + vqsub.s32 d20, d30, d22 // t22 + vqadd.s32 d30, d30, d22 // t23 + vqadd.s32 d26, d17, d25 // t24 + vqsub.s32 d17, d17, d25 // t25 + vqsub.s32 d22, d29, d21 // t26 + vqadd.s32 d29, d29, d21 // t27 + vqadd.s32 d25, d19, d27 // t28 + vqsub.s32 d19, d19, d27 // t29 + +.irp r, d5, d16, d7, d31, d24, d28, d23, d18, d20, d30, d26, d17, d22, d29, d25, d19 + vmin.s32 \r, \r, d11 +.endr +.irp r, d5, d16, d7, d31, d24, d28, d23, d18, d20, d30, d26, d17, d22, d29, d25, d19 + vmax.s32 \r, \r, d10 +.endr + + vmul_vmls d4, d7, d5, d2[0], d2[1] // -> t17a + vmul_vmla d6, d7, d5, d2[1], d2[0] // -> t30a + vmul_vmla d8, d19, d24, d2[1], d2[0] // -> t18a + vrshr.s32 d21, d4, #12 // t17a + vrshr.s32 d27, d6, #12 // t30a + vneg.s32 d8, d8 // -> t18a + vmul_vmls d5, d19, d24, d2[0], d2[1] // -> t29a + vmul_vmls d4, d22, d18, d3[0], d3[1] // -> t21a + vrshr.s32 d19, d8, #12 // t18a + vrshr.s32 d24, d5, #12 // t29a + vmul_vmla d6, d22, d18, d3[1], d3[0] // -> t26a + vmul_vmla d8, d17, d20, d3[1], d3[0] // -> t22a + vrshr.s32 d22, d4, #12 // t21a + vrshr.s32 d18, d6, #12 // t26a + vneg.s32 d8, d8 // -> t22a + vmul_vmls d5, d17, d20, d3[0], d3[1] // -> t25a + vrshr.s32 d17, d8, #12 // t22a + vrshr.s32 d20, d5, #12 // t25a + + vqsub.s32 d2, d27, d24 // t29 + vqadd.s32 d27, d27, d24 // t30 + vqsub.s32 d3, d21, d19 // t18 + vqadd.s32 d21, d21, d19 // t17 + vqsub.s32 d24, d16, d28 // t19a + vqadd.s32 d16, d16, d28 // t16a + vqsub.s32 d19, d30, d23 // t20a + vqadd.s32 d30, d30, d23 // t23a + vqsub.s32 d28, d17, d22 // t21 + vqadd.s32 d17, d17, d22 // t22 + vqadd.s32 d23, d26, d29 // t24a + vqsub.s32 d26, d26, d29 // t27a + vqadd.s32 d22, d20, d18 // t25 + vqsub.s32 d20, d20, d18 // t26 + vqsub.s32 d29, d31, d25 // t28a + vqadd.s32 d31, d31, d25 // t31a + +.irp r, d2, d27, d3, d21, d24, d16, d19, d30, d28, d17, d23, d26, d22, d20, d29, d31 + vmin.s32 \r, \r, d11 +.endr +.irp r, d2, d27, d3, d21, d24, d16, d19, d30, d28, d17, d23, d26, d22, d20, d29, d31 + vmax.s32 \r, \r, d10 +.endr + + vmul_vmls d4, d2, d3, d1[0], d1[1] // -> t18a + vmul_vmla d6, d2, d3, d1[1], d1[0] // -> t29a + vmul_vmls d8, d29, d24, d1[0], d1[1] // -> t19 + vrshr.s32 d18, d4, #12 // t18a + vrshr.s32 d25, d6, #12 // t29a + vmul_vmla d5, d29, d24, d1[1], d1[0] // -> t28 + vmul_vmla d4, d26, d19, d1[1], d1[0] // -> t20 + vrshr.s32 d29, d8, #12 // t19 + vrshr.s32 d24, d5, #12 // t28 + vneg.s32 d4, d4 // -> t20 + vmul_vmls d6, d26, d19, d1[0], d1[1] // -> t27 + vmul_vmla d8, d20, d28, d1[1], d1[0] // -> t21a + vrshr.s32 d26, d4, #12 // t20 + vrshr.s32 d19, d6, #12 // t27 + vneg.s32 d8, d8 // -> t21a + vmul_vmls d5, d20, d28, d1[0], d1[1] // -> t26a + vrshr.s32 d20, d8, #12 // t21a + vrshr.s32 d28, d5, #12 // t26a + + vqsub.s32 d2, d16, d30 // t23 + vqadd.s32 d16, d16, d30 // t16 = out16 + vqsub.s32 d3, d31, d23 // t24 + vqadd.s32 d31, d31, d23 // t31 = out31 + vqsub.s32 d23, d21, d17 // t22a + vqadd.s32 d17, d21, d17 // t17a = out17 + vqadd.s32 d30, d27, d22 // t30a = out30 + vqsub.s32 d21, d27, d22 // t25a + vqsub.s32 d27, d18, d20 // t21 + vqadd.s32 d18, d18, d20 // t18 = out18 + vqadd.s32 d4, d29, d26 // t19a = out19 + vqsub.s32 d26, d29, d26 // t20a + vqadd.s32 d29, d25, d28 // t29 = out29 + vqsub.s32 d25, d25, d28 // t26 + vqadd.s32 d28, d24, d19 // t28a = out28 + vqsub.s32 d24, d24, d19 // t27a + vmov d19, d4 // out19 + +.irp r, d2, d16, d3, d31, d23, d17, d30, d21, d27, d18, d19, d26, d29, d25, d28, d24 + vmin.s32 \r, \r, d11 +.endr +.irp r, d2, d16, d3, d31, d23, d17, d30, d21, d27, d18, d19, d26, d29, d25, d28, d24 + vmax.s32 \r, \r, d10 +.endr + + vmul_vmls d4, d24, d26, d0[0], d0[0] // -> t20 + vmul_vmla d6, d24, d26, d0[0], d0[0] // -> t27 + vrshr.s32 d20, d4, #12 // t20 + vrshr.s32 d22, d6, #12 // t27 + + vmul_vmla d4, d25, d27, d0[0], d0[0] // -> t26a + vmul_vmls d6, d25, d27, d0[0], d0[0] // -> t21a + vmov d27, d22 // t27 + vrshr.s32 d26, d4, #12 // t26a + + vmul_vmls d24, d21, d23, d0[0], d0[0] // -> t22 + vmul_vmla d4, d21, d23, d0[0], d0[0] // -> t25 + vrshr.s32 d21, d6, #12 // t21a + vrshr.s32 d22, d24, #12 // t22 + vrshr.s32 d25, d4, #12 // t25 + + vmul_vmls d4, d3, d2, d0[0], d0[0] // -> t23a + vmul_vmla d6, d3, d2, d0[0], d0[0] // -> t24a + vrshr.s32 d23, d4, #12 // t23a + vrshr.s32 d24, d6, #12 // t24a + + bx lr +endfunc + +.macro def_horz_32 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_dct_32x2_neon + push {lr} + vmov.i32 d7, #0 + lsl r8, r8, #1 +.if \scale + mov_const r12, 2896*8*(1<<16) + vdup.32 d0, r12 +.endif + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.32 {\i}, [r7, :64] + vst1.32 {d7}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + add r7, r7, r8, lsr #1 +.if \scale + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 +.endif + bl inv_dct_2s_x16_neon + + // idct_16 leaves the row_clip_max/min constants in d9 and d8, + // but here we want to use full q registers for clipping. + vmov.i32 q3, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 q2, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 +.irp r, q8, q9, q10, q11, q12, q13, q14, q15 + vmin.s32 \r, \r, q3 +.endr +.irp r, q8, q9, q10, q11, q12, q13, q14, q15 + vmax.s32 \r, \r, q2 +.endr + + vtrn.32 d16, d17 + vtrn.32 d18, d19 + vtrn.32 d20, d21 + vtrn.32 d22, d23 + vtrn.32 d24, d25 + vtrn.32 d26, d27 + vtrn.32 d28, d29 + vtrn.32 d30, d31 + +.macro store1 r0, r1, r2, r3 + vst1.16 {\r0}, [r6, :64]! + vst1.16 {\r1}, [r6, :64]! + vst1.16 {\r2}, [r6, :64]! + vst1.16 {\r3}, [r6, :64]! +.endm + store1 d16, d18, d20, d22 + store1 d24, d26, d28, d30 + store1 d17, d19, d21, d23 + store1 d25, d27, d29, d31 +.purgem store1 + sub r6, r6, #64*2 + + vmov.i32 d7, #0 +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.32 {\i}, [r7, :64] + vst1.32 {d7}, [r7, :64], r8 +.endr +.if \scale + // This relies on the fact that the idct also leaves the right coeff in d0[1] + scale_input d0[1], q8, q9, q10, q11, q12, q13, q14, q15 +.endif + bl inv_dct32_odd_2s_x16_neon + vtrn.32 d31, d30 + vtrn.32 d29, d28 + vtrn.32 d27, d26 + vtrn.32 d25, d24 + vtrn.32 d23, d22 + vtrn.32 d21, d20 + vtrn.32 d19, d18 + vtrn.32 d17, d16 +.macro store2 r0, r1, r2, r3, r4, r5, r6, r7, shift + vld1.32 {q0, q1}, [r6, :128]! + vld1.32 {q2, q3}, [r6, :128] + sub r6, r6, #32 + vqsub.s32 d15, d0, \r0 + vqadd.s32 d0, d0, \r0 + vqsub.s32 d14, d1, \r1 + vqadd.s32 d1, d1, \r1 + vqsub.s32 d13, d2, \r2 + vqadd.s32 d2, d2, \r2 + vqsub.s32 d12, d3, \r3 + vqadd.s32 d3, d3, \r3 + vqsub.s32 d11, d4, \r4 + vqadd.s32 d4, d4, \r4 + vqsub.s32 d10, d5, \r5 + vqadd.s32 d5, d5, \r5 + vqsub.s32 d9, d6, \r6 + vqadd.s32 d6, d6, \r6 + vqsub.s32 d8, d7, \r7 + vqadd.s32 d7, d7, \r7 + vqrshrn.s32 d0, q0, #\shift + vqrshrn.s32 d1, q1, #\shift + vqrshrn.s32 d2, q2, #\shift + vqrshrn.s32 d3, q3, #\shift + vqrshrn.s32 d4, q4, #\shift + vqrshrn.s32 d5, q5, #\shift + vqrshrn.s32 d6, q6, #\shift + vqrshrn.s32 d7, q7, #\shift + vrev32.16 q2, q2 + vrev32.16 q3, q3 + vst1.16 {q0, q1}, [r6, :128]! + vst1.16 {q2, q3}, [r6, :128]! +.endm + + store2 d31, d29, d27, d25, d23, d21, d19, d17, \shift + store2 d30, d28, d26, d24, d22, d20, d18, d16, \shift +.purgem store2 + pop {pc} +endfunc +.endm + +def_horz_32 scale=0, shift=2 +def_horz_32 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_dct_4x32_neon + push {r10-r11,lr} + lsl r8, r8, #1 + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + + bl X(inv_dct_4h_x16_neon) + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vst1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + add r7, r7, r8, lsr #1 + +.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 + vld1.16 {\i}, [r7, :64], r8 +.endr + sub r7, r7, r8, lsl #4 + sub r7, r7, r8, lsr #1 + bl X(inv_dct32_odd_4h_x16_neon) + + neg r9, r8 + mov r10, r6 + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff +.macro combine r0, r1, r2, r3, op, stride + vld1.16 {d4}, [r7, :64], \stride + vld1.16 {d0}, [r10, :64], r1 + vld1.16 {d5}, [r7, :64], \stride + vld1.16 {d1}, [r10, :64], r1 + \op\().s16 d4, d4, \r0 + vld1.16 {d6}, [r7, :64], \stride + vld1.16 {d2}, [r10, :64], r1 + \op\().s16 d5, d5, \r1 + vld1.16 {d3}, [r10, :64], r1 + vrshr.s16 q2, q2, #4 + \op\().s16 d6, d6, \r2 + vld1.16 {d7}, [r7, :64], \stride + vqadd.s16 q0, q0, q2 + \op\().s16 d7, d7, \r3 + vmax.s16 q0, q0, q6 + vrshr.s16 q3, q3, #4 + vmin.s16 q0, q0, q7 + vqadd.s16 q1, q1, q3 + vst1.16 {d0}, [r6, :64], r1 + vmax.s16 q1, q1, q6 + vst1.16 {d1}, [r6, :64], r1 + vmin.s16 q1, q1, q7 + vst1.16 {d2}, [r6, :64], r1 + vst1.16 {d3}, [r6, :64], r1 +.endm + combine d31, d30, d29, d28, vqadd, r8 + combine d27, d26, d25, d24, vqadd, r8 + combine d23, d22, d21, d20, vqadd, r8 + combine d19, d18, d17, d16, vqadd, r8 + sub r7, r7, r8 + combine d16, d17, d18, d19, vqsub, r9 + combine d20, d21, d22, d23, vqsub, r9 + combine d24, d25, d26, d27, vqsub, r9 + combine d28, d29, d30, d31, vqsub, r9 +.purgem combine + + pop {r10-r11,pc} +endfunc + +const eob_32x32 + .short 3, 10, 21, 36, 55, 78, 105, 136, 171, 210, 253, 300, 351, 406, 465, 1024 +endconst + +const eob_16x32 + .short 3, 10, 21, 36, 55, 78, 105, 151, 183, 215, 247, 279, 311, 343, 375, 512 +endconst + +const eob_16x32_shortside + .short 3, 10, 21, 36, 55, 78, 105, 512 +endconst + +const eob_8x32 + .short 3, 10, 21, 43, 59, 75, 91, 107, 123, 139, 155, 171, 187, 203, 219, 256 +endconst + +function inv_txfm_add_identity_identity_32x32_16bpc_neon, export=1 + push {r4-r7,lr} + vpush {q6-q7} + movrel_local r5, eob_32x32, 2 + + mov r6, #4*32 +1: + mov r12, #0 + movrel_local r4, eob_32x32, 6 +2: + vmov.i32 q0, #0 + add r12, r12, #8 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r6 +.endr + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q12 + vqmovn.s32 d18, q9 + vqmovn.s32 d19, q13 + vqmovn.s32 d20, q10 + vqmovn.s32 d21, q14 + vqmovn.s32 d22, q11 + vqmovn.s32 d23, q15 + transpose_4x8h q8, q9, q10, q11 + + load_add_store_8x4 r0, r7, shiftbits=2 + ldrh lr, [r4], #8 + sub r0, r0, r1, lsl #2 + cmp r3, lr + add r0, r0, #2*8 + bge 2b + + ldrh lr, [r5], #4 + cmp r3, lr + blt 9f + + sub r0, r0, r12, lsl #1 + add r0, r0, r1, lsl #2 + mls r2, r6, r12, r2 + add r2, r2, #4*4 + b 1b +9: + vpop {q6-q7} + pop {r4-r7,pc} +endfunc + +.macro shift_8_regs op, shift +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + \op \i, \i, #\shift +.endr +.endm + +.macro def_identity_1632 w, h, wshort, hshort +function inv_txfm_add_identity_identity_\w\()x\h\()_16bpc_neon, export=1 + push {r4-r9,lr} + vpush {q6-q7} + mov r9, #0 + mov_const r8, 2896*8*(1<<16) + movt r9, #2*(5793-4096)*8 + movrel_local r5, eob_16x32\hshort, 2 + + mov r6, #4*\h +1: + mov r12, #0 + movrel_local r4, eob_16x32\wshort, 6 +2: + vdup.i32 d0, r8 + vmov.i32 q1, #0 + vmov.32 d0[1], r9 + add r12, r12, #8 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q1}, [r2, :128], r6 +.endr + scale_input d0[0], q8, q9, q10, q11, q12, q13, q14, q15 + +.if \w == 16 + // 16x32 + identity_8x4_shift1 d0[1] +.else + // 32x16 + shift_8_regs vqshl.s32, 1 + identity_8x4 d0[1] +.endif + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q12 + vqmovn.s32 d18, q9 + vqmovn.s32 d19, q13 + vqmovn.s32 d20, q10 + vqmovn.s32 d21, q14 + vqmovn.s32 d22, q11 + vqmovn.s32 d23, q15 + transpose_4x8h q8, q9, q10, q11 + +.if \w == 16 + load_add_store_8x4 r0, r7, shiftbits=2 +.else + load_add_store_8x4 r0, r7, shiftbits=4 +.endif + ldrh lr, [r4], #8 + sub r0, r0, r1, lsl #2 + cmp r3, lr + add r0, r0, #2*8 + bge 2b + + ldrh lr, [r5], #4 + cmp r3, lr + blt 9f + + sub r0, r0, r12, lsl #1 + add r0, r0, r1, lsl #2 + mls r2, r6, r12, r2 + add r2, r2, #4*4 + b 1b +9: + vpop {q6-q7} + pop {r4-r9,pc} +endfunc +.endm + +def_identity_1632 16, 32, _shortside, +def_identity_1632 32, 16, , _shortside + +.macro def_identity_832 w, h +function inv_txfm_add_identity_identity_\w\()x\h\()_16bpc_neon, export=1 + push {r4-r5,lr} + vpush {q6-q7} + movrel_local r4, eob_8x32, 2 + + mov r12, #4*\h +1: + ldrh lr, [r4], #4 +.if \w == 8 + vmov.i32 q0, #0 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r12 +.endr + + vqrshrn.s32 d16, q8, #1 + vqrshrn.s32 d17, q12, #1 + vqrshrn.s32 d18, q9, #1 + vqrshrn.s32 d19, q13, #1 + vqrshrn.s32 d20, q10, #1 + vqrshrn.s32 d21, q14, #1 + vqrshrn.s32 d22, q11, #1 + vqrshrn.s32 d23, q15, #1 + + transpose_4x8h q8, q9, q10, q11 + + cmp r3, lr + load_add_store_8x4 r0, r5, shiftbits=2 + blt 9f + sub r2, r2, r12, lsl #3 + add r2, r2, #4*4 +.else + vmov.i32 q0, #0 + vmov.i32 q1, #0 + vld1.32 {q8, q9}, [r2, :128] + vst1.32 {q0, q1}, [r2, :128], r12 + vld1.32 {q10, q11}, [r2, :128] + vst1.32 {q0, q1}, [r2, :128], r12 + vld1.32 {q12, q13}, [r2, :128] + vst1.32 {q0, q1}, [r2, :128], r12 + vld1.32 {q14, q15}, [r2, :128] + vst1.32 {q0, q1}, [r2, :128], r12 + vqmovn.s32 d16, q8 + vqmovn.s32 d17, q10 + vqmovn.s32 d20, q9 + vqmovn.s32 d21, q11 + vqmovn.s32 d18, q12 + vqmovn.s32 d19, q14 + vqmovn.s32 d22, q13 + vqmovn.s32 d23, q15 + + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + + cmp r3, lr + load_add_store_4x8 r0, r5, shiftbits=3 + blt 9f + sub r0, r0, r1, lsl #3 + add r0, r0, #2*4 +.endif + b 1b + +9: + vpop {q6-q7} + pop {r4-r5,pc} +endfunc +.endm + +def_identity_832 8, 32 +def_identity_832 32, 8 + +function inv_txfm_add_dct_dct_32x32_16bpc_neon, export=1 + idct_dc 32, 32, 2 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 2048 + movrel_local r10, eob_32x32 + ldrh r11, [r10], #2 + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, sp, #(\i*32*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #32*4 + bl inv_txfm_horz_dct_32x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #32*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 2048 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_16x32_16bpc_neon, export=1 + idct_dc 16, 32, 1 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 1024 + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + movrel_local r4, inv_dct_2s_x16_neon + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, sp, #(\i*16*2) + add r7, r2, #(\i*4) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endif + mov r8, #4*32 + bl inv_txfm_horz_scale_16x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #16*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 1024 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x16_16bpc_neon, export=1 + idct_dc 32, 16, 1 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 1024 + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + movrel r5, X(inv_dct_4h_x16_neon) + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14 + add r6, sp, #(\i*32*2) + add r7, r2, #(\i*4) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.if \i < 14 + ldrh r11, [r10], #2 +.endif +.endif + mov r8, #4*16 + bl inv_txfm_horz_scale_dct_32x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #32*2 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 1024 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_8x32_16bpc_neon, export=1 + idct_dc 8, 32, 2 + + push {r4-r11,lr} + vpush {q4-q7} + sub_sp_align 512 + + movrel_local r10, eob_8x32, 2 + + mov r8, #4*32 + mov r9, #32 + mov r6, sp +1: + vmov.i32 q0, #0 +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.32 {\i}, [r2, :128] + vst1.32 {q0}, [r2, :128], r8 +.endr + ldrh r11, [r10], #4 + sub r2, r2, r8, lsl #3 + sub r9, r9, #4 + add r2, r2, #4*4 + + bl inv_dct_4s_x8_neon + + vqrshrn.s32 d16, q8, #2 + vqrshrn.s32 d18, q9, #2 + vqrshrn.s32 d20, q10, #2 + vqrshrn.s32 d22, q11, #2 + vqrshrn.s32 d17, q12, #2 + vqrshrn.s32 d19, q13, #2 + vqrshrn.s32 d21, q14, #2 + vqrshrn.s32 d23, q15, #2 + + transpose_4x8h q8, q9, q10, q11 + + vst1.16 {q8, q9}, [r6, :128]! + cmp r3, r11 + vst1.16 {q10, q11}, [r6, :128]! + + bge 1b + cmp r9, #0 + beq 3f + + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r9, r9, #4 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4 + add r6, r0, #(\i*2) + add r7, sp, #(\i*2) + mov r8, #8*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 512 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x8_16bpc_neon, export=1 + idct_dc 32, 8, 2 + + push {r4-r11,lr} + vpush {q4-q7} + movrel_local r10, eob_8x32 + sub_sp_align 512 + ldrh r11, [r10], #2 + +.irp i, 0, 2, 4, 6 + add r6, sp, #(\i*32*2) + add r7, r2, #(\i*4) +.if \i > 0 + cmp r3, r11 + mov r8, #(8 - \i) + blt 1f +.if \i < 6 + ldrh r11, [r10], #2 +.endif +.endif + mov r8, #8*4 + bl inv_txfm_horz_dct_32x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: + mov r8, #2*32 + mov r9, #0 +1: + add r6, r0, r9, lsl #1 + add r7, sp, r9, lsl #1 // #(\i*2) + +.irp i, q8, q9, q10, q11, q12, q13, q14, q15 + vld1.16 {\i}, [r7, :128], r8 +.endr + add r9, r9, #8 + + bl X(inv_dct_8h_x8_neon) + + cmp r9, #32 + + load_add_store_8x8 r6, r7 + + blt 1b + + add_sp_align 512 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_dct64_step1_neon + // in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + // in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + // in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + // in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + + vld1.32 {q0, q1}, [r12, :128]! + + vqrdmulh.s32 d23, d16, d0[1] // t63a + vqrdmulh.s32 d16, d16, d0[0] // t32a + vqrdmulh.s32 d22, d17, d1[0] // t62a + vqrdmulh.s32 d17, d17, d1[1] // t33a + vqrdmulh.s32 d21, d18, d2[1] // t61a + vqrdmulh.s32 d18, d18, d2[0] // t34a + vqrdmulh.s32 d20, d19, d3[0] // t60a + vqrdmulh.s32 d19, d19, d3[1] // t35a + + vld1.32 {q0}, [r12, :128]! + + vqadd.s32 d24, d16, d17 // t32 + vqsub.s32 d25, d16, d17 // t33 + vqsub.s32 d26, d19, d18 // t34 + vqadd.s32 d27, d19, d18 // t35 + vqadd.s32 d28, d20, d21 // t60 + vqsub.s32 d29, d20, d21 // t61 + vqsub.s32 d30, d23, d22 // t62 + vqadd.s32 d31, d23, d22 // t63 + +.irp r, q12, q13, q14, q15 + vmin.s32 \r, \r, q5 +.endr +.irp r, q12, q13, q14, q15 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmla d4, d29, d26, d0[0], d0[1] // -> t34a + vmul_vmls d6, d29, d26, d0[1], d0[0] // -> t61a + vneg.s32 d4, d4 // t34a + vmul_vmls d7, d30, d25, d0[1], d0[0] // -> t33a + vrshr.s32 d26, d4, #12 // t34a + vmul_vmla d4, d30, d25, d0[0], d0[1] // -> t62a + vrshr.s32 d29, d6, #12 // t61a + vrshr.s32 d25, d7, #12 // t33a + vrshr.s32 d30, d4, #12 // t62a + + vqadd.s32 d16, d24, d27 // t32a + vqsub.s32 d19, d24, d27 // t35a + vqadd.s32 d17, d25, d26 // t33 + vqsub.s32 d18, d25, d26 // t34 + vqsub.s32 d20, d31, d28 // t60a + vqadd.s32 d23, d31, d28 // t63a + vqsub.s32 d21, d30, d29 // t61 + vqadd.s32 d22, d30, d29 // t62 + +.irp r, q8, q9, q10, q11 + vmin.s32 \r, \r, q5 +.endr +.irp r, q8, q9, q10, q11 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmla d4, d21, d18, d1[0], d1[1] // -> t61a + vmul_vmls d6, d21, d18, d1[1], d1[0] // -> t34a + vmul_vmla d7, d20, d19, d1[0], d1[1] // -> t60 + vrshr.s32 d21, d4, #12 // t61a + vrshr.s32 d18, d6, #12 // t34a + vmul_vmls d4, d20, d19, d1[1], d1[0] // -> t35 + vrshr.s32 d20, d7, #12 // t60 + vrshr.s32 d19, d4, #12 // t35 + + vst1.32 {d16, d17, d18, d19}, [r6, :128]! + vst1.32 {d20, d21, d22, d23}, [r6, :128]! + + bx lr +endfunc + +function inv_dct64_step2_neon + movrel_local r12, idct_coeffs + vld1.32 {q0}, [r12, :128] +1: + // t32a/33/34a/35/60/61a/62/63a + // t56a/57/58a/59/36/37a/38/39a + // t40a/41/42a/43/52/53a/54/55a + // t48a/49/50a/51/44/45a/46/47a + vldr d16, [r6, #4*2*0] // t32a + vldr d17, [r9, #4*2*8] // t39a + vldr d18, [r9, #4*2*0] // t63a + vldr d19, [r6, #4*2*8] // t56a + vldr d20, [r6, #4*2*16] // t40a + vldr d21, [r9, #4*2*24] // t47a + vldr d22, [r9, #4*2*16] // t55a + vldr d23, [r6, #4*2*24] // t48a + + vqadd.s32 d24, d16, d17 // t32 + vqsub.s32 d25, d16, d17 // t39 + vqadd.s32 d26, d18, d19 // t63 + vqsub.s32 d27, d18, d19 // t56 + vqsub.s32 d28, d21, d20 // t40 + vqadd.s32 d29, d21, d20 // t47 + vqadd.s32 d30, d23, d22 // t48 + vqsub.s32 d31, d23, d22 // t55 + +.irp r, q12, q13, q14, q15 + vmin.s32 \r, \r, q5 +.endr +.irp r, q12, q13, q14, q15 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmla d4, d27, d25, d1[1], d1[0] // -> t56a + vmul_vmls d6, d27, d25, d1[0], d1[1] // -> t39a + vmul_vmla d7, d31, d28, d1[1], d1[0] // -> t40a + vrshr.s32 d25, d4, #12 // t56a + vrshr.s32 d27, d6, #12 // t39a + vneg.s32 d7, d7 // t40a + vmul_vmls d4, d31, d28, d1[0], d1[1] // -> t55a + vrshr.s32 d31, d7, #12 // t40a + vrshr.s32 d28, d4, #12 // t55a + + vqadd.s32 d16, d24, d29 // t32a + vqsub.s32 d19, d24, d29 // t47a + vqadd.s32 d17, d27, d31 // t39 + vqsub.s32 d18, d27, d31 // t40 + vqsub.s32 d20, d26, d30 // t48a + vqadd.s32 d23, d26, d30 // t63a + vqsub.s32 d21, d25, d28 // t55 + vqadd.s32 d22, d25, d28 // t56 + +.irp r, q8, q9, q10, q11 + vmin.s32 \r, \r, q5 +.endr +.irp r, q8, q9, q10, q11 + vmax.s32 \r, \r, q4 +.endr + + vmul_vmls d4, d21, d18, d0[0], d0[0] // -> t40a + vmul_vmla d6, d21, d18, d0[0], d0[0] // -> t55a + vmul_vmls d7, d20, d19, d0[0], d0[0] // -> t47 + vrshr.s32 d18, d4, #12 // t40a + vrshr.s32 d21, d6, #12 // t55a + vmul_vmla d4, d20, d19, d0[0], d0[0] // -> t48 + vrshr.s32 d19, d7, #12 // t47 + vrshr.s32 d20, d4, #12 // t48 + + vstr d16, [r6, #4*2*0] // t32a + vstr d17, [r9, #4*2*0] // t39 + vstr d18, [r6, #4*2*8] // t40a + vstr d19, [r9, #4*2*8] // t47 + vstr d20, [r6, #4*2*16] // t48 + vstr d21, [r9, #4*2*16] // t55a + vstr d22, [r6, #4*2*24] // t56 + vstr d23, [r9, #4*2*24] // t63a + + add r6, r6, #4*2 + sub r9, r9, #4*2 + cmp r6, r9 + blt 1b + bx lr +endfunc + +.macro load8 src, strd, zero, clear +.irp i, d16, d17, d18, d19, d20, d21, d22, d23 +.if \clear + vld1.32 {\i}, [\src, :64] + vst1.32 {\zero}, [\src, :64], \strd +.else + vld1.32 {\i}, [\src, :64], \strd +.endif +.endr +.endm + +.macro store16 dst + vst1.32 {q8, q9}, [\dst, :128]! + vst1.32 {q10, q11}, [\dst, :128]! + vst1.32 {q12, q13}, [\dst, :128]! + vst1.32 {q14, q15}, [\dst, :128]! +.endm + +.macro clear_upper8 +.irp i, q12, q13, q14, q15 + vmov.i32 \i, #0 +.endr +.endm + +.macro vmov_if reg, val, cond +.if \cond + vmov.i32 \reg, \val +.endif +.endm + +.macro movdup_if reg, gpr, val, cond +.if \cond + mov_const \gpr, \val + vdup.32 \reg, \gpr +.endif +.endm + +.macro vst1_if regs, dst, dstalign, cond +.if \cond + vst1.32 \regs, \dst, \dstalign +.endif +.endm + +.macro scale_if cond, c, r0, r1, r2, r3, r4, r5, r6, r7 +.if \cond + scale_input \c, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endif +.endm + +.macro def_dct64_func suffix, clear=0, scale=0 +function inv_txfm_dct\suffix\()_2s_x64_neon + mov r6, sp + + push {r10-r11,lr} + + lsl r8, r8, #2 + + movdup_if d0, r12, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + load8 r7, r8, d7, \clear + clear_upper8 + sub r7, r7, r8, lsl #3 + add r7, r7, r8, lsr #1 + scale_if \scale, d0[0], q8, q9, q10, q11 + + bl inv_dct_2s_x16_neon + + // idct_16 leaves the row_clip_max/min constants in d9 and d8, + // but here we want to use full q registers for clipping. + vmov.i32 q3, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 q2, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 +.irp r, q8, q9, q10, q11, q12, q13, q14, q15 + vmin.s32 \r, \r, q3 +.endr +.irp r, q8, q9, q10, q11, q12, q13, q14, q15 + vmax.s32 \r, \r, q2 +.endr + + store16 r6 + + movdup_if d0, r12, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + load8 r7, r8, d7, \clear + clear_upper8 + sub r7, r7, r8, lsl #3 + lsr r8, r8, #1 + sub r7, r7, r8, lsr #1 + scale_if \scale, d0[0], q8, q9, q10, q11 + + bl inv_dct32_odd_2s_x16_neon + + add r10, r6, #8*15 + sub r6, r6, #8*16 + + mov r9, #-8 + + vmov.i32 d1, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 d0, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 +.macro store_addsub r0, r1, r2, r3 + vld1.32 {d2}, [r6, :64]! + vld1.32 {d3}, [r6, :64]! + vqadd.s32 d6, d2, \r0 + vqsub.s32 \r0, d2, \r0 + vld1.32 {d4}, [r6, :64]! + vqadd.s32 d7, d3, \r1 + vqsub.s32 \r1, d3, \r1 + vmin.s32 d6, d6, d1 + vmin.s32 \r0, \r0, d1 + vld1.32 {d5}, [r6, :64]! + vqadd.s32 d2, d4, \r2 + sub r6, r6, #8*4 + vmax.s32 d6, d6, d0 + vmax.s32 \r0, \r0, d0 + vqsub.s32 \r2, d4, \r2 + vmin.s32 d7, d7, d1 + vmin.s32 \r1, \r1, d1 + vst1.32 {d6}, [r6, :64]! + vst1.32 {\r0}, [r10, :64], r9 + vmin.s32 d2, d2, d1 + vmin.s32 \r2, \r2, d1 + vmax.s32 d7, d7, d0 + vmax.s32 \r1, \r1, d0 + vqadd.s32 d3, d5, \r3 + vqsub.s32 \r3, d5, \r3 + vmax.s32 d2, d2, d0 + vmax.s32 \r2, \r2, d0 + vmin.s32 d3, d3, d1 + vmin.s32 \r3, \r3, d1 + vst1.32 {d7}, [r6, :64]! + vst1.32 {\r1}, [r10, :64], r9 + vmax.s32 d3, d3, d0 + vmax.s32 \r3, \r3, d0 + vst1.32 {d2}, [r6, :64]! + vst1.32 {\r2}, [r10, :64], r9 + vst1.32 {d3}, [r6, :64]! + vst1.32 {\r3}, [r10, :64], r9 +.endm + store_addsub d31, d30, d29, d28 + store_addsub d27, d26, d25, d24 + store_addsub d23, d22, d21, d20 + store_addsub d19, d18, d17, d16 +.purgem store_addsub + + add r6, r6, #2*4*16 + + movrel_local r12, idct64_coeffs + vmov.i32 q5, #0x1ffff // row_clip_max = ~(~bdmax << 7), 0x1ffff + vmvn.i32 q4, #0x1ffff // row_clip_min = (~bdmax << 7), 0xfffe0000 + movdup_if d0, lr, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + add r9, r7, r8, lsl #4 // offset 16 + add r10, r7, r8, lsl #3 // offset 8 + sub r9, r9, r8 // offset 15 + sub r11, r10, r8 // offset 7 + vld1.32 {d16}, [r7, :64] // in1 (offset 0) + vld1.32 {d17}, [r9, :64] // in31 (offset 15) + vld1.32 {d18}, [r10, :64] // in17 (offset 8) + vld1.32 {d19}, [r11, :64] // in15 (offset 7) + vst1_if {d7}, [r7, :64], \clear + vst1_if {d7}, [r9, :64], \clear + vst1_if {d7}, [r10, :64], \clear + vst1_if {d7}, [r11, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + add r7, r7, r8, lsl #2 // offset 4 + sub r9, r9, r8, lsl #2 // offset 11 + sub r10, r7, r8 // offset 3 + add r11, r9, r8 // offset 12 + vld1.32 {d16}, [r10, :64] // in7 (offset 3) + vld1.32 {d17}, [r11, :64] // in25 (offset 12) + vld1.32 {d18}, [r9, :64] // in23 (offset 11) + vld1.32 {d19}, [r7, :64] // in9 (offset 4) + vst1_if {d7}, [r7, :64], \clear + vst1_if {d7}, [r9, :64], \clear + vst1_if {d7}, [r10, :64], \clear + vst1_if {d7}, [r11, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + sub r10, r10, r8, lsl #1 // offset 1 + sub r9, r9, r8, lsl #1 // offset 9 + add r10, r10, r8 // offset 2 + add r9, r9, r8 // offset 10 + add r7, r7, r8 // offset 5 + add r11, r11, r8 // offset 13 + vld1.32 d16, [r10, :64] // in5 (offset 2) + vld1.32 d17, [r11, :64] // in27 (offset 13) + vld1.32 d18, [r9, :64] // in21 (offset 10) + vld1.32 d19, [r7, :64] // in11 (offset 5) + vst1_if d7, [r10, :64], \clear + vst1_if d7, [r11, :64], \clear + vst1_if d7, [r9, :64], \clear + vst1_if d7, [r7, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + movdup_if d0, lr, 2896*8*(1<<16), \scale + vmov_if d7, #0, \clear + sub r10, r10, r8 // offset 1 + sub r9, r9, r8 // offset 9 + add r11, r11, r8 // offset 14 + add r7, r7, r8 // offset 6 + vld1.32 d16, [r10, :64] // in3 (offset 1) + vld1.32 d17, [r11, :64] // in29 (offset 14) + vld1.32 d18, [r9, :64] // in19 (offset 9) + vld1.32 d19, [r7, :64] // in13 (offset 6) + vst1_if d7, [r10, :64], \clear + vst1_if d7, [r11, :64], \clear + vst1_if d7, [r9, :64], \clear + vst1_if d7, [r7, :64], \clear + scale_if \scale, d0[0], q8, q9 + bl inv_dct64_step1_neon + + sub r6, r6, #2*4*32 + add r9, r6, #2*4*7 + + bl inv_dct64_step2_neon + + pop {r10-r11,pc} +endfunc +.endm + +def_dct64_func _clear, clear=1 +def_dct64_func _clear_scale, clear=1, scale=1 + +function inv_txfm_horz_dct_64x2_neon + vdup.32 q4, r9 + + mov r7, sp + add r8, sp, #2*4*(64 - 4) + add r9, r6, #2*56 + + push {r10-r11,lr} + + mov r10, #2*64 + mov r11, #-2*4*4 + +1: + vld1.32 {d16, d17, d18, d19}, [r7, :128]! + vld1.32 {d28, d29, d30, d31}, [r8, :128], r11 + vld1.32 {d20, d21, d22, d23}, [r7, :128]! + vld1.32 {d24, d25, d26, d27}, [r8, :128], r11 + vtrn.32 d16, d17 + vtrn.32 d18, d19 + vtrn.32 d20, d21 + vtrn.32 d22, d23 + vtrn.32 d31, d30 + vtrn.32 d29, d28 + vtrn.32 d27, d26 + vtrn.32 d25, d24 + +.macro store_addsub src0, src1, src2, src3, src4, src5, src6, src7 + vqsub.s32 d7, \src0, \src1 + vqsub.s32 d6, \src2, \src3 + vqsub.s32 d5, \src4, \src5 + vqsub.s32 d4, \src6, \src7 + vqadd.s32 d0, \src0, \src1 + vqadd.s32 d1, \src2, \src3 + vqadd.s32 d2, \src4, \src5 + vqadd.s32 d3, \src6, \src7 + vrshl.s32 q3, q3, q4 + vrshl.s32 q2, q2, q4 + vrshl.s32 q0, q0, q4 + vrshl.s32 q1, q1, q4 + vqmovn.s32 d7, q3 + vqmovn.s32 d6, q2 + vqmovn.s32 d0, q0 + vqmovn.s32 d1, q1 + vrev32.16 q3, q3 + vst1.16 {q0}, [r6, :128], r10 + vst1.16 {q3}, [r9, :128], r10 +.endm + store_addsub d16, d31, d18, d29, d20, d27, d22, d25 + store_addsub d17, d30, d19, d28, d21, d26, d23, d24 +.purgem store_addsub + sub r6, r6, r10, lsl #1 + sub r9, r9, r10, lsl #1 + add r6, r6, #16 + sub r9, r9, #16 + + cmp r7, r8 + blt 1b + pop {r10-r11,pc} +endfunc + +function inv_txfm_add_vert_dct_4x64_neon + lsl r8, r8, #1 + + mov r7, sp + add r8, sp, #2*4*(64 - 4) + add r9, r6, r1, lsl #6 + sub r9, r9, r1 + + push {r10-r11,lr} + + neg r10, r1 + mov r11, #-2*4*4 + +1: + vld1.16 {d16, d17, d18, d19}, [r7, :128]! + vld1.16 {d28, d29, d30, d31}, [r8, :128], r11 + vld1.16 {d20, d21, d22, d23}, [r7, :128]! + vld1.16 {d24, d25, d26, d27}, [r8, :128], r11 + + vmov.i16 q6, #0 + vmvn.i16 q7, #0xfc00 // 0x3ff +.macro add_dest_addsub src0, src1, src2, src3 + vld1.16 {d0}, [r6, :64], r1 + vld1.16 {d1}, [r9, :64], r10 + vqadd.s16 d4, \src0, \src1 + vld1.16 {d2}, [r6, :64] + vqsub.s16 d5, \src0, \src1 + vld1.16 {d3}, [r9, :64] + vqadd.s16 d6, \src2, \src3 + vqsub.s16 d7, \src2, \src3 + sub r6, r6, r1 + sub r9, r9, r10 + vrshr.s16 q2, q2, #4 + vrshr.s16 q3, q3, #4 + vqadd.s16 q2, q2, q0 + vqadd.s16 q3, q3, q1 + vmax.s16 q2, q2, q6 + vmax.s16 q3, q3, q6 + vmin.s16 q2, q2, q7 + vmin.s16 q3, q3, q7 + vst1.16 {d4}, [r6, :64], r1 + vst1.16 {d5}, [r9, :64], r10 + vst1.16 {d6}, [r6, :64], r1 + vst1.16 {d7}, [r9, :64], r10 +.endm + add_dest_addsub d16, d31, d17, d30 + add_dest_addsub d18, d29, d19, d28 + add_dest_addsub d20, d27, d21, d26 + add_dest_addsub d22, d25, d23, d24 +.purgem add_dest_addsub + cmp r7, r8 + blt 1b + + pop {r10-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x64_16bpc_neon, export=1 + idct_dc 64, 64, 2 + + push {r4-r11,lr} + vpush {q4-q7} + + sub_sp_align 64*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, r5, #(\i*64*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*4) + mov r8, #32*4 + bl inv_txfm_dct_clear_2s_x64_neon + add r6, r5, #(\i*64*2) + mov r9, #-2 // shift + bl inv_txfm_horz_dct_64x2_neon +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r7, r5, #(\i*2) + mov r8, #64*2 + bl X(inv_txfm_dct_4h_x64_neon) + add r6, r0, #(\i*2) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 64*32*2+64*4*2 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x32_16bpc_neon, export=1 + idct_dc 64, 32, 1 + + push {r4-r11,lr} + vpush {q4-q7} + + sub_sp_align 64*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, r5, #(\i*64*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*4) + mov r8, #32*4 + bl inv_txfm_dct_clear_scale_2s_x64_neon + add r6, r5, #(\i*64*2) + mov r9, #-1 // shift + bl inv_txfm_horz_dct_64x2_neon +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r6, r0, #(\i*2) + add r7, r5, #(\i*2) + mov r8, #64*2 + bl inv_txfm_add_vert_dct_4x32_neon +.endr + + add_sp_align 64*32*2+64*4*2 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_32x64_16bpc_neon, export=1 + idct_dc 32, 64, 1 + + push {r4-r11,lr} + vpush {q4-q7} + + sub_sp_align 32*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_32x32 + ldrh r11, [r10], #2 + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, r5, #(\i*32*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #32*4 + bl inv_txfm_horz_scale_dct_32x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 4 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add r7, r5, #(\i*2) + mov r8, #32*2 + bl X(inv_txfm_dct_4h_x64_neon) + add r6, r0, #(\i*2) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 32*32*2+64*4*2 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_64x16_16bpc_neon, export=1 + idct_dc 64, 16, 2 + + push {r4-r11,lr} + vpush {q4-q7} + + sub_sp_align 64*16*2+64*4*2 + add r4, sp, #64*4*2 + + movrel_local r10, eob_16x32 + +.irp i, 0, 2, 4, 6, 8, 10, 12, 14 + add r6, r4, #(\i*64*2) +.if \i > 0 + mov r8, #(16 - \i) + cmp r3, r11 + blt 1f +.endif + add r7, r2, #(\i*4) + mov r8, #16*4 + bl inv_txfm_dct_clear_2s_x64_neon + add r6, r4, #(\i*64*2) + mov r9, #-2 // shift + bl inv_txfm_horz_dct_64x2_neon +.if \i < 8 + ldrh r11, [r10], #2 +.endif +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 8 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: + movrel r5, X(inv_dct_4h_x16_neon) +.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 + add r6, r0, #(\i*2) + add r7, r4, #(\i*2) + mov r8, #64*2 + bl inv_txfm_add_vert_4x16_neon +.endr + + add_sp_align 64*16*2+64*4*2 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +function inv_txfm_add_dct_dct_16x64_16bpc_neon, export=1 + idct_dc 16, 64, 2 + + push {r4-r11,lr} + vpush {q4-q7} + + sub_sp_align 16*32*2+64*4*2 + add r5, sp, #64*4*2 + + movrel_local r10, eob_16x32 + ldrh r11, [r10], #2 + + movrel_local r4, inv_dct_2s_x16_neon +.irp i, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + add r6, r5, #(\i*16*2) +.if \i > 0 + mov r8, #(32 - \i) + cmp r3, r11 + blt 1f +.if \i < 30 + ldrh r11, [r10], #2 +.endif +.endif + add r7, r2, #(\i*4) + mov r8, #32*4 + bl inv_txfm_horz_16x2_neon +.endr + b 3f + +1: + vmov.i16 q2, #0 + vmov.i16 q3, #0 +2: + subs r8, r8, #2 +.rept 2 + vst1.16 {q2, q3}, [r6, :128]! +.endr + bgt 2b + +3: +.irp i, 0, 4, 8, 12 + add r7, r5, #(\i*2) + mov r8, #16*2 + bl X(inv_txfm_dct_4h_x64_neon) + add r6, r0, #(\i*2) + bl inv_txfm_add_vert_dct_4x64_neon +.endr + + add_sp_align 16*32*2+64*4*2 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,868 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro loop_filter wd +function lpf_8_wd\wd\()_neon + vabd.u8 d0, d22, d23 // abs(p1 - p0) + vabd.u8 d1, d25, d24 // abs(q1 - q0) + vabd.u8 d2, d23, d24 // abs(p0 - q0) + vabd.u8 d3, d22, d25 // abs(p1 - q1) +.if \wd >= 6 + vabd.u8 d4, d21, d22 // abs(p2 - p1) + vabd.u8 d5, d26, d25 // abs(q2 - q1) +.endif +.if \wd >= 8 + vabd.u8 d6, d20, d21 // abs(p3 - p2) + vabd.u8 d7, d27, d26 // abs(q3 - q3) +.endif +.if \wd >= 6 + vmax.u8 d4, d4, d5 +.endif + vqadd.u8 d2, d2, d2 // abs(p0 - q0) * 2 +.if \wd >= 8 + vmax.u8 d6, d6, d7 +.endif + vshr.u8 d3, d3, #1 +.if \wd >= 8 + vmax.u8 d4, d4, d6 +.endif +.if \wd >= 6 + vand d4, d4, d14 +.endif + vmax.u8 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0)) + vqadd.u8 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 +.if \wd >= 6 + vmax.u8 d4, d0, d4 + vcge.u8 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I +.else + vcge.u8 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I +.endif + vcge.u8 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E + vand d1, d1, d2 // fm + vand d1, d1, d13 // fm && wd >= 4 +.if \wd >= 6 + vand d14, d14, d1 // fm && wd > 4 +.endif +.if \wd >= 16 + vand d15, d15, d1 // fm && wd == 16 +.endif + + vmov r10, r11, d1 + orrs r10, r10, r11 + beq 9f // if (!fm || wd < 4) return; + +.if \wd >= 6 + vmov.i8 d10, #1 + vabd.u8 d2, d21, d23 // abs(p2 - p0) + vabd.u8 d3, d22, d23 // abs(p1 - p0) + vabd.u8 d4, d25, d24 // abs(q1 - q0) + vabd.u8 d5, d26, d24 // abs(q2 - q0) +.if \wd >= 8 + vabd.u8 d6, d20, d23 // abs(p3 - p0) + vabd.u8 d7, d27, d24 // abs(q3 - q0) +.endif + vmax.u8 d2, d2, d3 + vmax.u8 d4, d4, d5 +.if \wd >= 8 + vmax.u8 d6, d6, d7 +.endif + vmax.u8 d2, d2, d4 +.if \wd >= 8 + vmax.u8 d2, d2, d6 +.endif + +.if \wd == 16 + vabd.u8 d3, d17, d23 // abs(p6 - p0) + vabd.u8 d4, d18, d23 // abs(p5 - p0) + vabd.u8 d5, d19, d23 // abs(p4 - p0) +.endif + vcge.u8 d2, d10, d2 // flat8in +.if \wd == 16 + vabd.u8 d6, d28, d24 // abs(q4 - q0) + vabd.u8 d7, d29, d24 // abs(q5 - q0) + vabd.u8 d8, d30, d24 // abs(q6 - q0) +.endif + vand d14, d2, d14 // flat8in && fm && wd > 4 + vbic d1, d1, d14 // fm && wd >= 4 && !flat8in +.if \wd == 16 + vmax.u8 d3, d3, d4 + vmax.u8 d5, d5, d6 +.endif + vmov r10, r11, d1 +.if \wd == 16 + vmax.u8 d7, d7, d8 + vmax.u8 d3, d3, d5 + vmax.u8 d3, d3, d7 + vcge.u8 d3, d10, d3 // flat8out +.endif + orrs r10, r10, r11 +.if \wd == 16 + vand d15, d15, d3 // flat8out && fm && wd == 16 + vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16 + vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out +.endif + beq 1f // skip wd == 4 case +.endif + + vsubl.u8 q1, d22, d25 // p1 - q1 + vcgt.u8 d0, d0, d12 // hev + vqmovn.s16 d2, q1 + vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1) + vbic d0, d1, d0 // (fm && wd >= 4 && !hev) + vsubl.u8 q1, d24, d23 + vmov.i16 q3, #3 + vmul.i16 q1, q1, q3 + vmov.i8 d6, #4 + vaddw.s8 q1, q1, d4 + vmov.i8 d7, #3 + vqmovn.s16 d2, q1 // f + vqadd.s8 d4, d6, d2 // imin(f + 4, 127) + vqadd.s8 d5, d7, d2 // imin(f + 3, 127) + vshr.s8 d4, d4, #3 // f1 + vshr.s8 d5, d5, #3 // f2 + vmovl.u8 q1, d23 // p0 + vmovl.u8 q3, d24 // q0 + vaddw.s8 q1, q1, d5 + vsubw.s8 q3, q3, d4 + vrshr.s8 d4, d4, #1 // (f1 + 1) >> 1 + vqmovun.s16 d2, q1 // out p0 + vqmovun.s16 d6, q3 // out q0 + vbit d23, d2, d1 // if (fm && wd >= 4) + vmovl.u8 q1, d22 // p1 + vbit d24, d6, d1 // if (fm && wd >= 4) + vmovl.u8 q3, d25 // q1 + vaddw.s8 q1, q1, d4 + vsubw.s8 q3, q3, d4 + vqmovun.s16 d2, q1 // out p1 + vqmovun.s16 d6, q3 // out q1 + vbit d22, d2, d0 // if (fm && wd >= 4 && !hev) + vbit d25, d6, d0 // if (fm && wd >= 4 && !hev) +1: + +.if \wd == 6 + vmov r10, r11, d14 + orrs r10, r10, r11 + beq 2f // skip if there's no flat8in + + vaddl.u8 q0, d21, d21 // p2 * 2 + vaddl.u8 q1, d21, d22 // p2 + p1 + vaddl.u8 q2, d22, d23 // p1 + p0 + vaddl.u8 q3, d23, d24 // p0 + q0 + vadd.i16 q4, q0, q1 + vadd.i16 q5, q2, q3 + vaddl.u8 q6, d24, d25 // q0 + q1 + vadd.i16 q4, q4, q5 + vsub.i16 q6, q6, q0 + vaddl.u8 q5, d25, d26 // q1 + q2 + vrshrn.i16 d0, q4, #3 // out p1 + + vadd.i16 q4, q4, q6 + vsub.i16 q5, q5, q1 + vaddl.u8 q6, d26, d26 // q2 + q2 + vrshrn.i16 d1, q4, #3 // out p0 + + vadd.i16 q4, q4, q5 + vsub.i16 q6, q6, q2 + vrshrn.i16 d2, q4, #3 // out q0 + + vbit d22, d0, d14 // p1 if (flat8in) + vadd.i16 q4, q4, q6 + vbit d23, d1, d14 // p0 if (flat8in) + vrshrn.i16 d3, q4, #3 // out q1 + vbit d24, d2, d14 // q0 if (flat8in) + vbit d25, d3, d14 // q1 if (flat8in) +.elseif \wd >= 8 + vmov r10, r11, d14 + orrs r10, r10, r11 +.if \wd == 8 + beq 8f // skip if there's no flat8in +.else + beq 2f // skip if there's no flat8in +.endif + + vaddl.u8 q0, d20, d21 // p3 + p2 + vaddl.u8 q1, d22, d25 // p1 + q1 + vaddl.u8 q2, d20, d22 // p3 + p1 + vaddl.u8 q3, d23, d26 // p0 + q2 + vadd.i16 q4, q0, q0 // 2 * (p3 + p2) + vaddw.u8 q4, q4, d23 // + p0 + vaddw.u8 q4, q4, d24 // + q0 + vadd.i16 q4, q4, q2 // + p3 + p1 + vsub.i16 q1, q1, q0 // p1 + q1 - p3 - p2 + vsub.i16 q3, q3, q2 // p0 + q2 - p3 - p1 + vrshrn.i16 d10, q4, #3 // out p2 + + vadd.i16 q4, q4, q1 + vaddl.u8 q0, d20, d23 // p3 + p0 + vaddl.u8 q1, d24, d27 // q0 + q3 + vrshrn.i16 d11, q4, #3 // out p1 + + vadd.i16 q4, q4, q3 + vsub.i16 q1, q1, q0 // q0 + q3 - p3 - p0 + vaddl.u8 q2, d21, d24 // p2 + q0 + vaddl.u8 q3, d25, d27 // q1 + q3 + vrshrn.i16 d12, q4, #3 // out p0 + + vadd.i16 q4, q4, q1 + vsub.i16 q3, q3, q2 // q1 + q3 - p2 - q0 + vaddl.u8 q0, d22, d25 // p1 + q1 + vaddl.u8 q1, d26, d27 // q2 + q3 + vrshrn.i16 d13, q4, #3 // out q0 + + vadd.i16 q4, q4, q3 + vsub.i16 q1, q1, q0 // q2 + q3 - p1 - q1 + vrshrn.i16 d0, q4, #3 // out q1 + + vadd.i16 q4, q4, q1 + + vbit d21, d10, d14 + vbit d22, d11, d14 + vbit d23, d12, d14 + vrshrn.i16 d1, q4, #3 // out q2 + vbit d24, d13, d14 + vbit d25, d0, d14 + vbit d26, d1, d14 +.endif +2: +.if \wd == 16 + vmov r10, r11, d15 + orrs r10, r10, r11 + bne 1f // check if flat8out is needed + vmov r10, r11, d14 + orrs r10, r10, r11 + beq 8f // if there was no flat8in, just write the inner 4 pixels + b 7f // if flat8in was used, write the inner 6 pixels +1: + + vaddl.u8 q1, d17, d17 // p6 + p6 + vaddl.u8 q2, d17, d18 // p6 + p5 + vaddl.u8 q3, d17, d19 // p6 + p4 + vaddl.u8 q4, d17, d20 // p6 + p3 + vadd.i16 q6, q1, q2 + vadd.i16 q5, q3, q4 + vaddl.u8 q3, d17, d21 // p6 + p2 + vadd.i16 q6, q6, q5 + vaddl.u8 q4, d17, d22 // p6 + p1 + vaddl.u8 q5, d18, d23 // p5 + p0 + vadd.i16 q3, q3, q4 + vaddl.u8 q4, d19, d24 // p4 + q0 + vadd.i16 q6, q6, q3 + vadd.i16 q5, q5, q4 + vaddl.u8 q3, d20, d25 // p3 + q1 + vadd.i16 q6, q6, q5 + vsub.i16 q3, q3, q1 + vaddl.u8 q1, d21, d26 // p2 + q2 + vrshrn.i16 d0, q6, #4 // out p5 + vadd.i16 q6, q6, q3 // - (p6 + p6) + (p3 + q1) + vsub.i16 q1, q1, q2 + vaddl.u8 q2, d22, d27 // p1 + q3 + vaddl.u8 q3, d17, d19 // p6 + p4 + vrshrn.i16 d1, q6, #4 // out p4 + vadd.i16 q6, q6, q1 // - (p6 + p5) + (p2 + q2) + vsub.i16 q2, q2, q3 + vaddl.u8 q3, d23, d28 // p0 + q4 + vaddl.u8 q4, d17, d20 // p6 + p3 + vrshrn.i16 d2, q6, #4 // out p3 + vadd.i16 q6, q6, q2 // - (p6 + p4) + (p1 + q3) + vsub.i16 q3, q3, q4 + vaddl.u8 q4, d24, d29 // q0 + q5 + vaddl.u8 q2, d17, d21 // p6 + p2 + vrshrn.i16 d3, q6, #4 // out p2 + vadd.i16 q6, q6, q3 // - (p6 + p3) + (p0 + q4) + vsub.i16 q4, q4, q2 + vaddl.u8 q3, d25, d30 // q1 + q6 + vaddl.u8 q5, d17, d22 // p6 + p1 + vrshrn.i16 d4, q6, #4 // out p1 + vadd.i16 q6, q6, q4 // - (p6 + p2) + (q0 + q5) + vsub.i16 q3, q3, q5 + vaddl.u8 q4, d26, d30 // q2 + q6 + vbif d0, d18, d15 // out p5 + vaddl.u8 q5, d18, d23 // p5 + p0 + vrshrn.i16 d5, q6, #4 // out p0 + vadd.i16 q6, q6, q3 // - (p6 + p1) + (q1 + q6) + vsub.i16 q4, q4, q5 + vaddl.u8 q5, d27, d30 // q3 + q6 + vbif d1, d19, d15 // out p4 + vaddl.u8 q9, d19, d24 // p4 + q0 + vrshrn.i16 d6, q6, #4 // out q0 + vadd.i16 q6, q6, q4 // - (p5 + p0) + (q2 + q6) + vsub.i16 q5, q5, q9 + vaddl.u8 q4, d28, d30 // q4 + q6 + vbif d2, d20, d15 // out p3 + vaddl.u8 q9, d20, d25 // p3 + q1 + vrshrn.i16 d7, q6, #4 // out q1 + vadd.i16 q6, q6, q5 // - (p4 + q0) + (q3 + q6) + vsub.i16 q9, q4, q9 + vaddl.u8 q5, d29, d30 // q5 + q6 + vbif d3, d21, d15 // out p2 + vaddl.u8 q10, d21, d26 // p2 + q2 + vrshrn.i16 d8, q6, #4 // out q2 + vadd.i16 q6, q6, q9 // - (p3 + q1) + (q4 + q6) + vsub.i16 q5, q5, q10 + vaddl.u8 q9, d30, d30 // q6 + q6 + vbif d4, d22, d15 // out p1 + vaddl.u8 q10, d22, d27 // p1 + q3 + vrshrn.i16 d9, q6, #4 // out q3 + vadd.i16 q6, q6, q5 // - (p2 + q2) + (q5 + q6) + vsub.i16 q9, q9, q10 + vbif d5, d23, d15 // out p0 + vrshrn.i16 d10, q6, #4 // out q4 + vadd.i16 q6, q6, q9 // - (p1 + q3) + (q6 + q6) + vrshrn.i16 d11, q6, #4 // out q5 + vbif d6, d24, d15 // out q0 + vbif d7, d25, d15 // out q1 + vbif d8, d26, d15 // out q2 + vbif d9, d27, d15 // out q3 + vbif d10, d28, d15 // out q4 + vbif d11, d29, d15 // out q5 +.endif + + bx lr +.if \wd == 16 +7: + // Return to a shorter epilogue, writing only the inner 6 pixels + bx r8 +.endif +.if \wd >= 8 +8: + // Return to a shorter epilogue, writing only the inner 4 pixels + bx r9 +.endif +9: + // Return directly without writing back any pixels + bx r12 +endfunc +.endm + +loop_filter 16 +loop_filter 8 +loop_filter 6 +loop_filter 4 + +.macro lpf_8_wd16 + adr r8, 7f + CONFIG_THUMB + adr r9, 8f + CONFIG_THUMB + bl lpf_8_wd16_neon +.endm + +.macro lpf_8_wd8 + adr r9, 8f + CONFIG_THUMB + bl lpf_8_wd8_neon +.endm + +.macro lpf_8_wd6 + bl lpf_8_wd6_neon +.endm + +.macro lpf_8_wd4 + bl lpf_8_wd4_neon +.endm + +function lpf_v_4_8_neon + mov r12, lr + sub r10, r0, r1, lsl #1 + vld1.8 {d22}, [r10, :64], r1 // p1 + vld1.8 {d24}, [r0, :64], r1 // q0 + vld1.8 {d23}, [r10, :64], r1 // p0 + vld1.8 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + + lpf_8_wd4 + + sub r10, r0, r1, lsl #1 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_4_8_neon + mov r12, lr + sub r10, r0, #2 + add r0, r10, r1, lsl #2 + vld1.32 {d22[0]}, [r10], r1 + vld1.32 {d22[1]}, [r0], r1 + vld1.32 {d23[0]}, [r10], r1 + vld1.32 {d23[1]}, [r0], r1 + vld1.32 {d24[0]}, [r10], r1 + vld1.32 {d24[1]}, [r0], r1 + vld1.32 {d25[0]}, [r10], r1 + vld1.32 {d25[1]}, [r0], r1 + add r0, r0, #2 + + transpose_4x8b q11, q12, d22, d23, d24, d25 + + lpf_8_wd4 + + sub r10, r0, r1, lsl #3 + sub r10, r10, #2 + transpose_4x8b q11, q12, d22, d23, d24, d25 + add r0, r10, r1, lsl #2 + + vst1.32 {d22[0]}, [r10], r1 + vst1.32 {d22[1]}, [r0], r1 + vst1.32 {d23[0]}, [r10], r1 + vst1.32 {d23[1]}, [r0], r1 + vst1.32 {d24[0]}, [r10], r1 + vst1.32 {d24[1]}, [r0], r1 + vst1.32 {d25[0]}, [r10], r1 + vst1.32 {d25[1]}, [r0], r1 + add r0, r0, #2 + bx r12 +endfunc + +function lpf_v_6_8_neon + mov r12, lr + sub r10, r0, r1, lsl #1 + sub r10, r10, r1 + vld1.8 {d21}, [r10, :64], r1 // p2 + vld1.8 {d24}, [r0, :64], r1 // q0 + vld1.8 {d22}, [r10, :64], r1 // p1 + vld1.8 {d25}, [r0, :64], r1 // q1 + vld1.8 {d23}, [r10, :64], r1 // p0 + vld1.8 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + + lpf_8_wd6 + + sub r10, r0, r1, lsl #1 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_6_8_neon + mov r12, lr + sub r10, r0, #4 + add r0, r10, r1, lsl #2 + vld1.8 {d20}, [r10], r1 + vld1.8 {d24}, [r0], r1 + vld1.8 {d21}, [r10], r1 + vld1.8 {d25}, [r0], r1 + vld1.8 {d22}, [r10], r1 + vld1.8 {d26}, [r0], r1 + vld1.8 {d23}, [r10], r1 + vld1.8 {d27}, [r0], r1 + add r0, r0, #4 + + transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27 + + lpf_8_wd6 + + sub r10, r0, r1, lsl #3 + sub r10, r10, #2 + transpose_4x8b q11, q12, d22, d23, d24, d25 + add r0, r10, r1, lsl #2 + + vst1.32 {d22[0]}, [r10], r1 + vst1.32 {d22[1]}, [r0], r1 + vst1.32 {d23[0]}, [r10], r1 + vst1.32 {d23[1]}, [r0], r1 + vst1.32 {d24[0]}, [r10], r1 + vst1.32 {d24[1]}, [r0], r1 + vst1.32 {d25[0]}, [r10], r1 + vst1.32 {d25[1]}, [r0], r1 + add r0, r0, #2 + bx r12 +endfunc + +function lpf_v_8_8_neon + mov r12, lr + sub r10, r0, r1, lsl #2 + vld1.8 {d20}, [r10, :64], r1 // p3 + vld1.8 {d24}, [r0, :64], r1 // q0 + vld1.8 {d21}, [r10, :64], r1 // p2 + vld1.8 {d25}, [r0, :64], r1 // q1 + vld1.8 {d22}, [r10, :64], r1 // p1 + vld1.8 {d26}, [r0, :64], r1 // q2 + vld1.8 {d23}, [r10, :64], r1 // p0 + vld1.8 {d27}, [r0, :64], r1 // q3 + sub r0, r0, r1, lsl #2 + + lpf_8_wd8 + + sub r10, r0, r1, lsl #1 + sub r10, r10, r1 + vst1.8 {d21}, [r10, :64], r1 // p2 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d25}, [r0, :64], r1 // q1 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + bx r12 + +8: + sub r10, r0, r1, lsl #1 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_8_8_neon + mov r12, lr + sub r10, r0, #4 + add r0, r10, r1, lsl #2 + vld1.8 {d20}, [r10], r1 + vld1.8 {d24}, [r0], r1 + vld1.8 {d21}, [r10], r1 + vld1.8 {d25}, [r0], r1 + vld1.8 {d22}, [r10], r1 + vld1.8 {d26}, [r0], r1 + vld1.8 {d23}, [r10], r1 + vld1.8 {d27}, [r0], r1 + add r0, r0, #4 + + transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27 + + lpf_8_wd8 + + sub r10, r0, r1, lsl #3 + sub r10, r10, #4 + transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27 + add r0, r10, r1, lsl #2 + + vst1.8 {d20}, [r10], r1 + vst1.8 {d24}, [r0], r1 + vst1.8 {d21}, [r10], r1 + vst1.8 {d25}, [r0], r1 + vst1.8 {d22}, [r10], r1 + vst1.8 {d26}, [r0], r1 + vst1.8 {d23}, [r10], r1 + vst1.8 {d27}, [r0], r1 + add r0, r0, #4 + bx r12 +8: + sub r10, r0, r1, lsl #3 + sub r10, r10, #2 + transpose_4x8b q11, q12, d22, d23, d24, d25 + add r0, r10, r1, lsl #2 + + vst1.32 {d22[0]}, [r10], r1 + vst1.32 {d22[1]}, [r0], r1 + vst1.32 {d23[0]}, [r10], r1 + vst1.32 {d23[1]}, [r0], r1 + vst1.32 {d24[0]}, [r10], r1 + vst1.32 {d24[1]}, [r0], r1 + vst1.32 {d25[0]}, [r10], r1 + vst1.32 {d25[1]}, [r0], r1 + add r0, r0, #2 + bx r12 +endfunc + +function lpf_v_16_8_neon + mov r12, lr + + sub r10, r0, r1, lsl #3 + add r10, r10, r1 + vld1.8 {d17}, [r10, :64], r1 // p6 + vld1.8 {d24}, [r0, :64], r1 // q0 + vld1.8 {d18}, [r10, :64], r1 // p5 + vld1.8 {d25}, [r0, :64], r1 // q1 + vld1.8 {d19}, [r10, :64], r1 // p4 + vld1.8 {d26}, [r0, :64], r1 // q2 + vld1.8 {d20}, [r10, :64], r1 // p3 + vld1.8 {d27}, [r0, :64], r1 // q3 + vld1.8 {d21}, [r10, :64], r1 // p2 + vld1.8 {d28}, [r0, :64], r1 // q4 + vld1.8 {d22}, [r10, :64], r1 // p1 + vld1.8 {d29}, [r0, :64], r1 // q5 + vld1.8 {d23}, [r10, :64], r1 // p0 + vld1.8 {d30}, [r0, :64], r1 // q6 + sub r0, r0, r1, lsl #3 + add r0, r0, r1 + + lpf_8_wd16 + + sub r10, r0, r1, lsl #2 + sub r10, r10, r1, lsl #1 + vst1.8 {d0}, [r10, :64], r1 // p5 + vst1.8 {d6}, [r0, :64], r1 // q0 + vst1.8 {d1}, [r10, :64], r1 // p4 + vst1.8 {d7}, [r0, :64], r1 // q1 + vst1.8 {d2}, [r10, :64], r1 // p3 + vst1.8 {d8}, [r0, :64], r1 // q2 + vst1.8 {d3}, [r10, :64], r1 // p2 + vst1.8 {d9}, [r0, :64], r1 // q3 + vst1.8 {d4}, [r10, :64], r1 // p1 + vst1.8 {d10}, [r0, :64], r1 // q4 + vst1.8 {d5}, [r10, :64], r1 // p0 + vst1.8 {d11}, [r0, :64], r1 // q5 + sub r0, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + bx r12 +7: + sub r10, r0, r1 + sub r10, r10, r1, lsl #1 + vst1.8 {d21}, [r10, :64], r1 // p2 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d25}, [r0, :64], r1 // q1 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + bx r12 + +8: + sub r10, r0, r1, lsl #1 + vst1.8 {d22}, [r10, :64], r1 // p1 + vst1.8 {d24}, [r0, :64], r1 // q0 + vst1.8 {d23}, [r10, :64], r1 // p0 + vst1.8 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_16_8_neon + mov r12, lr + sub r10, r0, #8 + vld1.8 {d16}, [r10, :64], r1 + vld1.8 {d24}, [r0, :64], r1 + vld1.8 {d17}, [r10, :64], r1 + vld1.8 {d25}, [r0, :64], r1 + vld1.8 {d18}, [r10, :64], r1 + vld1.8 {d26}, [r0, :64], r1 + vld1.8 {d19}, [r10, :64], r1 + vld1.8 {d27}, [r0, :64], r1 + vld1.8 {d20}, [r10, :64], r1 + vld1.8 {d28}, [r0, :64], r1 + vld1.8 {d21}, [r10, :64], r1 + vld1.8 {d29}, [r0, :64], r1 + vld1.8 {d22}, [r10, :64], r1 + vld1.8 {d30}, [r0, :64], r1 + vld1.8 {d23}, [r10, :64], r1 + vld1.8 {d31}, [r0, :64], r1 + + transpose_8x8b q8, q9, q10, q11, d16, d17, d18, d19, d20, d21, d22, d23 + transpose_8x8b q12, q13, q14, q15, d24, d25, d26, d27, d28, d29, d30, d31 + + lpf_8_wd16 + + sub r0, r0, r1, lsl #3 + sub r10, r0, #8 + + transpose_8x8b q8, q0, q1, q2, d16, d17, d0, d1, d2, d3, d4, d5 + transpose_8x8b q3, q4, q5, q15, d6, d7, d8, d9, d10, d11, d30, d31 + + vst1.8 {d16}, [r10, :64], r1 + vst1.8 {d6}, [r0, :64], r1 + vst1.8 {d17}, [r10, :64], r1 + vst1.8 {d7}, [r0, :64], r1 + vst1.8 {d0}, [r10, :64], r1 + vst1.8 {d8}, [r0, :64], r1 + vst1.8 {d1}, [r10, :64], r1 + vst1.8 {d9}, [r0, :64], r1 + vst1.8 {d2}, [r10, :64], r1 + vst1.8 {d10}, [r0, :64], r1 + vst1.8 {d3}, [r10, :64], r1 + vst1.8 {d11}, [r0, :64], r1 + vst1.8 {d4}, [r10, :64], r1 + vst1.8 {d30}, [r0, :64], r1 + vst1.8 {d5}, [r10, :64], r1 + vst1.8 {d31}, [r0, :64], r1 + bx r12 + +7: + sub r10, r0, r1, lsl #3 + sub r10, r10, #4 + transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27 + add r0, r10, r1, lsl #2 + + vst1.8 {d20}, [r10], r1 + vst1.8 {d24}, [r0], r1 + vst1.8 {d21}, [r10], r1 + vst1.8 {d25}, [r0], r1 + vst1.8 {d22}, [r10], r1 + vst1.8 {d26}, [r0], r1 + vst1.8 {d23}, [r10], r1 + vst1.8 {d27}, [r0], r1 + add r0, r0, #4 + bx r12 +8: + sub r10, r0, r1, lsl #3 + sub r10, r10, #2 + transpose_4x8b q11, q12, d22, d23, d24, d25 + add r0, r10, r1, lsl #2 + + vst1.32 {d22[0]}, [r10], r1 + vst1.32 {d22[1]}, [r0], r1 + vst1.32 {d23[0]}, [r10], r1 + vst1.32 {d23[1]}, [r0], r1 + vst1.32 {d24[0]}, [r10], r1 + vst1.32 {d24[1]}, [r0], r1 + vst1.32 {d25[0]}, [r10], r1 + vst1.32 {d25[1]}, [r0], r1 + add r0, r0, #2 + bx r12 +endfunc + +// void dav1d_lpf_v_sb_y_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint32_t *const vmask, +// const uint8_t (*l)[4], ptrdiff_t b4_stride, +// const Av1FilterLUT *lut, const int w) + +.macro lpf_func dir, type +function lpf_\dir\()_sb_\type\()_8bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [r2] // vmask[0], vmask[1] +.ifc \type, y + ldr r2, [r2, #8] // vmask[2] +.endif + add r5, r5, #128 // Move to sharp part of lut +.ifc \type, y + orr r7, r7, r2 // vmask[1] |= vmask[2] +.endif +.ifc \dir, v + sub r4, r3, r4, lsl #2 +.else + sub r3, r3, #4 + lsl r4, r4, #2 +.endif + orr r6, r6, r7 // vmask[0] |= vmask[1] + +1: + tst r6, #0x03 +.ifc \dir, v + vld1.8 {d0}, [r4]! + vld1.8 {d1}, [r3]! +.else + vld2.32 {d0[0], d1[0]}, [r3], r4 + vld2.32 {d0[1], d1[1]}, [r3], r4 +.endif + beq 7f // if (!(vm & bits)) continue; + + vld1.8 {d5[]}, [r5] // sharp[0] + add r5, r5, #8 + vmov.i32 d2, #0xff + vdup.32 d13, r6 // vmask[0] + + vand d0, d0, d2 // Keep only lowest byte in each 32 bit word + vand d1, d1, d2 + vtst.8 d3, d1, d2 // Check for nonzero values in l[0][0] + vmov.i8 d4, #1 + vld1.8 {d6[]}, [r5] // sharp[1] + sub r5, r5, #8 + vbif d1, d0, d3 // if (!l[0][0]) L = l[offset][0] + vtst.32 d2, d1, d2 // L != 0 + vmul.i32 d1, d1, d4 // L +.ifc \type, y + vdup.32 d15, r2 // vmask[2] +.endif + vdup.32 d14, r7 // vmask[1] + vmov r10, r11, d2 + orrs r10, r10, r11 + beq 7f // if (!L) continue; + vneg.s8 d5, d5 // -sharp[0] + movrel_local r10, word_12 + vshr.u8 d12, d1, #4 // H + vld1.32 {d16}, [r10, :64] + vshl.s8 d3, d1, d5 // L >> sharp[0] +.ifc \type, y + vtst.32 d15, d15, d16 // if (vmask[2] & bits) +.endif + vmov.i8 d7, #2 + vmin.u8 d3, d3, d6 // imin(L >> sharp[0], sharp[1]) + vadd.i8 d0, d1, d7 // L + 2 + vmax.u8 d11, d3, d4 // imax(imin(), 1) = limit = I + vadd.u8 d0, d0, d0 // 2*(L + 2) + vtst.32 d14, d14, d16 // if (vmask[1] & bits) + vadd.i8 d10, d0, d11 // 2*(L + 2) + limit = E + vtst.32 d13, d13, d16 // if (vmask[0] & bits) + vand d13, d13, d2 // vmask[0] &= L != 0 + +.ifc \type, y + tst r2, #0x03 + beq 2f + // wd16 + bl lpf_\dir\()_16_8_neon + b 8f +2: +.endif + tst r7, #0x03 + beq 3f +.ifc \type, y + // wd8 + bl lpf_\dir\()_8_8_neon +.else + // wd6 + bl lpf_\dir\()_6_8_neon +.endif + b 8f +3: + // wd4 + bl lpf_\dir\()_4_8_neon +.ifc \dir, h + b 8f +7: + // For dir h, the functions above increment r0. + // If the whole function is skipped, increment it here instead. + add r0, r0, r1, lsl #3 +.else +7: +.endif +8: + lsrs r6, r6, #2 // vmask[0] >>= 2 + lsr r7, r7, #2 // vmask[1] >>= 2 +.ifc \type, y + lsr r2, r2, #2 // vmask[2] >>= 2 +.endif +.ifc \dir, v + add r0, r0, #8 +.else + // For dir h, r0 is returned incremented +.endif + bne 1b + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +lpf_func v, y +lpf_func h, y +lpf_func v, uv +lpf_func h, uv + +const word_12, align=4 + .word 1, 2 +endconst diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/loopfilter16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,859 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro loop_filter wd +function lpf_4_wd\wd\()_neon + vabd.u16 d0, d22, d23 // abs(p1 - p0) + vabd.u16 d1, d25, d24 // abs(q1 - q0) + vabd.u16 d2, d23, d24 // abs(p0 - q0) + vabd.u16 d3, d22, d25 // abs(p1 - q1) +.if \wd >= 6 + vabd.u16 d4, d21, d22 // abs(p2 - p1) + vabd.u16 d5, d26, d25 // abs(q2 - q1) +.endif +.if \wd >= 8 + vabd.u16 d6, d20, d21 // abs(p3 - p2) + vabd.u16 d7, d27, d26 // abs(q3 - q3) +.endif +.if \wd >= 6 + vmax.u16 d4, d4, d5 +.endif + vqadd.u16 d2, d2, d2 // abs(p0 - q0) * 2 +.if \wd >= 8 + vmax.u16 d6, d6, d7 +.endif + vshr.u16 d3, d3, #1 +.if \wd >= 8 + vmax.u16 d4, d4, d6 +.endif + vmax.u16 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0)) + vqadd.u16 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 +.if \wd >= 6 + vmax.u16 d4, d0, d4 + vcge.u16 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I +.else + vcge.u16 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I +.endif + vcge.u16 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E + vand d1, d1, d2 // fm && wd >= 4 (implicit) +.if \wd >= 6 + vmov d14, d1 // fm && wd > 4 (implicit) +.endif +.if \wd >= 16 + vmov d15, d1 // fm && wd == 16 (implicit) +.endif + + vmov r10, r11, d1 + orrs r10, r10, r11 + beq 9f // if (!fm || wd < 4) return; + +.if \wd >= 6 + vmov.i16 d10, #1 + vabd.u16 d2, d21, d23 // abs(p2 - p0) + vabd.u16 d3, d22, d23 // abs(p1 - p0) + vabd.u16 d4, d25, d24 // abs(q1 - q0) + vabd.u16 d5, d26, d24 // abs(q2 - q0) + vdup.16 d9, r9 // bitdepth_min_8 +.if \wd >= 8 + vabd.u16 d6, d20, d23 // abs(p3 - p0) + vabd.u16 d7, d27, d24 // abs(q3 - q0) +.endif + vmax.u16 d2, d2, d3 + vmax.u16 d4, d4, d5 +.if \wd >= 8 + vmax.u16 d6, d6, d7 +.endif + vmax.u16 d2, d2, d4 + vshl.u16 d10, d10, d9 // F = 1 << bitdepth_min_8 +.if \wd >= 8 + vmax.u16 d2, d2, d6 +.endif + +.if \wd == 16 + vabd.u16 d3, d17, d23 // abs(p6 - p0) + vabd.u16 d4, d18, d23 // abs(p5 - p0) + vabd.u16 d5, d19, d23 // abs(p4 - p0) +.endif + vcge.u16 d2, d10, d2 // flat8in +.if \wd == 16 + vabd.u16 d6, d28, d24 // abs(q4 - q0) + vabd.u16 d7, d29, d24 // abs(q5 - q0) + vabd.u16 d8, d30, d24 // abs(q6 - q0) +.endif + vand d14, d2, d14 // flat8in && fm && wd > 4 + vbic d1, d1, d14 // fm && wd >= 4 && !flat8in +.if \wd == 16 + vmax.u16 d3, d3, d4 + vmax.u16 d5, d5, d6 +.endif + vmov r10, r11, d1 +.if \wd == 16 + vmax.u16 d7, d7, d8 + vmax.u16 d3, d3, d5 + vmax.u16 d3, d3, d7 + vcge.u16 d3, d10, d3 // flat8out +.endif + orrs r10, r10, r11 +.if \wd == 16 + vand d15, d15, d3 // flat8out && fm && wd == 16 + vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16 + vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out +.endif + beq 1f // skip wd == 4 case +.endif + + vdup.16 d3, r8 // bitdepth_max + vsub.u16 d2, d22, d25 // p1 - q1 + vshr.u16 d3, d3, #1 // 128 << bitdepth_min_8 - 1 + vcgt.u16 d0, d0, d12 // hev + vmvn d9, d3 // - 128 * (1 << bitdepth_min_8) + vmin.s16 d2, d2, d3 // iclip_diff(p1 - q1) + vmax.s16 d2, d2, d9 // iclip_diff(p1 - q1) + vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1) + vsub.u16 d2, d24, d23 + vmov.i16 d6, #3 + vbic d0, d1, d0 // (fm && wd >= 4 && !hev) + vmul.i16 d2, d2, d6 + vmov.i16 d7, #4 + vadd.i16 d2, d2, d4 + vmin.s16 d2, d2, d3 // f = iclip_diff() + vmax.s16 d2, d2, d9 // f = iclip_diff() + vqadd.s16 d4, d7, d2 // f + 4 + vqadd.s16 d5, d6, d2 // f + 3 + vmin.s16 d4, d4, d3 // imin(f + 4, 128 << bitdepth_min_8 - 1) + vmin.s16 d5, d5, d3 // imin(f + 3, 128 << bitdepth_min_8 - 1) + vshr.s16 d4, d4, #3 // f1 + vshr.s16 d5, d5, #3 // f2 + vmov.i16 d9, #0 + vdup.16 d3, r8 // bitdepth_max + vqadd.s16 d2, d23, d5 // p0 + f2 + vqsub.s16 d6, d24, d4 // q0 - f1 + vrshr.s16 d4, d4, #1 // (f1 + 1) >> 1 + vmin.s16 d2, d2, d3 // out p0 = iclip_pixel() + vmin.s16 d6, d6, d3 // out q0 = iclip_pixel() + vmax.s16 d2, d2, d9 // out p0 = iclip_pixel() + vmax.s16 d6, d6, d9 // out q0 = iclip_pixel() + vbit d23, d2, d1 // if (fm && wd >= 4) + vbit d24, d6, d1 // if (fm && wd >= 4) + vqadd.s16 d2, d22, d4 // p1 + f + vqsub.s16 d6, d25, d4 // q1 - f + vmin.s16 d2, d2, d3 // out p1 = iclip_pixel() + vmin.s16 d6, d6, d3 // out q1 = iclip_pixel() + vmax.s16 d2, d2, d9 // out p1 = iclip_pixel() + vmax.s16 d6, d6, d9 // out q1 = iclip_pixel() + vbit d22, d2, d0 // if (fm && wd >= 4 && !hev) + vbit d25, d6, d0 // if (fm && wd >= 4 && !hev) +1: + +.if \wd == 6 + vmov r10, r11, d14 + orrs r10, r10, r11 + beq 2f // skip if there's no flat8in + + vadd.i16 d0, d21, d21 // p2 * 2 + vadd.i16 d2, d21, d22 // p2 + p1 + vadd.i16 d4, d22, d23 // p1 + p0 + vadd.i16 d6, d23, d24 // p0 + q0 + vadd.i16 d8, d0, d2 + vadd.i16 d10, d4, d6 + vadd.i16 d12, d24, d25 // q0 + q1 + vadd.i16 d8, d8, d10 + vsub.i16 d12, d12, d0 + vadd.i16 d10, d25, d26 // q1 + q2 + vrshr.u16 d0, d8, #3 // out p1 + + vadd.i16 d8, d8, d12 + vsub.i16 d10, d10, d2 + vadd.i16 d12, d26, d26 // q2 + q2 + vrshr.u16 d1, d8, #3 // out p0 + + vadd.i16 d8, d8, d10 + vsub.i16 d12, d12, d4 + vrshr.u16 d2, d8, #3 // out q0 + + vbit d22, d0, d14 // p1 if (flat8in) + vadd.i16 d8, d8, d12 + vbit d23, d1, d14 // p0 if (flat8in) + vrshr.u16 d3, d8, #3 // out q1 + vbit d24, d2, d14 // q0 if (flat8in) + vbit d25, d3, d14 // q1 if (flat8in) +.elseif \wd >= 8 + vmov r10, r11, d14 + orrs r10, r10, r11 +.if \wd == 8 + beq 8f // skip if there's no flat8in +.else + beq 2f // skip if there's no flat8in +.endif + + vadd.i16 d0, d20, d21 // p3 + p2 + vadd.i16 d2, d22, d25 // p1 + q1 + vadd.i16 d4, d20, d22 // p3 + p1 + vadd.i16 d6, d23, d26 // p0 + q2 + vadd.i16 d8, d0, d0 // 2 * (p3 + p2) + vadd.i16 d9, d23, d24 // p0 + q0 + vadd.i16 d8, d8, d4 // + p3 + p1 + vsub.i16 d2, d2, d0 // p1 + q1 - p3 - p2 + vadd.i16 d8, d8, d9 // + p0 + q0 + vsub.i16 d6, d6, d4 // p0 + q2 - p3 - p1 + vrshr.u16 d10, d8, #3 // out p2 + + vadd.i16 d8, d8, d2 + vadd.i16 d0, d20, d23 // p3 + p0 + vadd.i16 d2, d24, d27 // q0 + q3 + vrshr.u16 d11, d8, #3 // out p1 + + vadd.i16 d8, d8, d6 + vsub.i16 d2, d2, d0 // q0 + q3 - p3 - p0 + vadd.i16 d4, d21, d24 // p2 + q0 + vadd.i16 d6, d25, d27 // q1 + q3 + vrshr.u16 d12, d8, #3 // out p0 + + vadd.i16 d8, d8, d2 + vsub.i16 d6, d6, d4 // q1 + q3 - p2 - q0 + vadd.i16 d0, d22, d25 // p1 + q1 + vadd.i16 d2, d26, d27 // q2 + q3 + vrshr.u16 d13, d8, #3 // out q0 + + vadd.i16 d8, d8, d6 + vsub.i16 d2, d2, d0 // q2 + q3 - p1 - q1 + vrshr.u16 d0, d8, #3 // out q1 + + vadd.i16 d8, d8, d2 + + vbit d21, d10, d14 + vbit d22, d11, d14 + vbit d23, d12, d14 + vrshr.u16 d1, d8, #3 // out q2 + vbit d24, d13, d14 + vbit d25, d0, d14 + vbit d26, d1, d14 +.endif +2: +.if \wd == 16 + vmov r10, r11, d15 + orrs r10, r10, r11 + bne 1f // check if flat8out is needed + vmov r10, r11, d14 + orrs r10, r10, r11 + beq 8f // if there was no flat8in, just write the inner 4 pixels + b 7f // if flat8in was used, write the inner 6 pixels +1: + + vadd.i16 d2, d17, d17 // p6 + p6 + vadd.i16 d4, d17, d18 // p6 + p5 + vadd.i16 d6, d17, d19 // p6 + p4 + vadd.i16 d8, d17, d20 // p6 + p3 + vadd.i16 d12, d2, d4 + vadd.i16 d10, d6, d8 + vadd.i16 d6, d17, d21 // p6 + p2 + vadd.i16 d12, d12, d10 + vadd.i16 d8, d17, d22 // p6 + p1 + vadd.i16 d10, d18, d23 // p5 + p0 + vadd.i16 d6, d6, d8 + vadd.i16 d8, d19, d24 // p4 + q0 + vadd.i16 d12, d12, d6 + vadd.i16 d10, d10, d8 + vadd.i16 d6, d20, d25 // p3 + q1 + vadd.i16 d12, d12, d10 + vsub.i16 d6, d6, d2 + vadd.i16 d2, d21, d26 // p2 + q2 + vrshr.u16 d0, d12, #4 // out p5 + vadd.i16 d12, d12, d6 // - (p6 + p6) + (p3 + q1) + vsub.i16 d2, d2, d4 + vadd.i16 d4, d22, d27 // p1 + q3 + vadd.i16 d6, d17, d19 // p6 + p4 + vrshr.u16 d1, d12, #4 // out p4 + vadd.i16 d12, d12, d2 // - (p6 + p5) + (p2 + q2) + vsub.i16 d4, d4, d6 + vadd.i16 d6, d23, d28 // p0 + q4 + vadd.i16 d8, d17, d20 // p6 + p3 + vrshr.u16 d2, d12, #4 // out p3 + vadd.i16 d12, d12, d4 // - (p6 + p4) + (p1 + q3) + vsub.i16 d6, d6, d8 + vadd.i16 d8, d24, d29 // q0 + q5 + vadd.i16 d4, d17, d21 // p6 + p2 + vrshr.u16 d3, d12, #4 // out p2 + vadd.i16 d12, d12, d6 // - (p6 + p3) + (p0 + q4) + vsub.i16 d8, d8, d4 + vadd.i16 d6, d25, d30 // q1 + q6 + vadd.i16 d10, d17, d22 // p6 + p1 + vrshr.u16 d4, d12, #4 // out p1 + vadd.i16 d12, d12, d8 // - (p6 + p2) + (q0 + q5) + vsub.i16 d6, d6, d10 + vadd.i16 d8, d26, d30 // q2 + q6 + vbif d0, d18, d15 // out p5 + vadd.i16 d10, d18, d23 // p5 + p0 + vrshr.u16 d5, d12, #4 // out p0 + vadd.i16 d12, d12, d6 // - (p6 + p1) + (q1 + q6) + vsub.i16 d8, d8, d10 + vadd.i16 d10, d27, d30 // q3 + q6 + vbif d1, d19, d15 // out p4 + vadd.i16 d18, d19, d24 // p4 + q0 + vrshr.u16 d6, d12, #4 // out q0 + vadd.i16 d12, d12, d8 // - (p5 + p0) + (q2 + q6) + vsub.i16 d10, d10, d18 + vadd.i16 d8, d28, d30 // q4 + q6 + vbif d2, d20, d15 // out p3 + vadd.i16 d18, d20, d25 // p3 + q1 + vrshr.u16 d7, d12, #4 // out q1 + vadd.i16 d12, d12, d10 // - (p4 + q0) + (q3 + q6) + vsub.i16 d18, d8, d18 + vadd.i16 d10, d29, d30 // q5 + q6 + vbif d3, d21, d15 // out p2 + vadd.i16 d20, d21, d26 // p2 + q2 + vrshr.u16 d8, d12, #4 // out q2 + vadd.i16 d12, d12, d18 // - (p3 + q1) + (q4 + q6) + vsub.i16 d10, d10, d20 + vadd.i16 d18, d30, d30 // q6 + q6 + vbif d4, d22, d15 // out p1 + vadd.i16 d20, d22, d27 // p1 + q3 + vrshr.u16 d9, d12, #4 // out q3 + vadd.i16 d12, d12, d10 // - (p2 + q2) + (q5 + q6) + vsub.i16 d18, d18, d20 + vbif d5, d23, d15 // out p0 + vrshr.u16 d10, d12, #4 // out q4 + vadd.i16 d12, d12, d18 // - (p1 + q3) + (q6 + q6) + vrshr.u16 d11, d12, #4 // out q5 + vbif d6, d24, d15 // out q0 + vbif d7, d25, d15 // out q1 + vbif d8, d26, d15 // out q2 + vbif d9, d27, d15 // out q3 + vbif d10, d28, d15 // out q4 + vbif d11, d29, d15 // out q5 +.endif + + bx lr +.if \wd == 16 +7: + // Return to a shorter epilogue, writing only the inner 6 pixels + bx r6 +.endif +.if \wd >= 8 +8: + // Return to a shorter epilogue, writing only the inner 4 pixels + bx r7 +.endif +9: + // Return directly without writing back any pixels + bx r12 +endfunc +.endm + +loop_filter 16 +loop_filter 8 +loop_filter 6 +loop_filter 4 + +.macro lpf_4_wd16 + adr r6, 7f + CONFIG_THUMB + adr r7, 8f + CONFIG_THUMB + bl lpf_4_wd16_neon +.endm + +.macro lpf_4_wd8 + adr r7, 8f + CONFIG_THUMB + bl lpf_4_wd8_neon +.endm + +.macro lpf_4_wd6 + bl lpf_4_wd6_neon +.endm + +.macro lpf_4_wd4 + bl lpf_4_wd4_neon +.endm + +function lpf_v_4_4_neon + mov r12, lr + sub r10, r0, r1, lsl #1 + vld1.16 {d22}, [r10, :64], r1 // p1 + vld1.16 {d24}, [r0, :64], r1 // q0 + vld1.16 {d23}, [r10, :64], r1 // p0 + vld1.16 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + + lpf_4_wd4 + + sub r10, r0, r1, lsl #1 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_4_4_neon + mov r12, lr + sub r10, r0, #4 + add r0, r10, r1, lsl #1 + vld1.16 {d22}, [r10], r1 + vld1.16 {d24}, [r0], r1 + vld1.16 {d23}, [r10], r1 + vld1.16 {d25}, [r0], r1 + add r0, r0, #4 + + transpose_4x4h q11, q12, d22, d23, d24, d25 + + lpf_4_wd4 + + sub r10, r0, r1, lsl #2 + sub r10, r10, #4 + transpose_4x4h q11, q12, d22, d23, d24, d25 + add r0, r10, r1, lsl #1 + + vst1.16 {d22}, [r10], r1 + vst1.16 {d24}, [r0], r1 + vst1.16 {d23}, [r10], r1 + vst1.16 {d25}, [r0], r1 + add r0, r0, #4 + bx r12 +endfunc + +function lpf_v_6_4_neon + mov r12, lr + sub r10, r0, r1, lsl #1 + sub r10, r10, r1 + vld1.16 {d21}, [r10, :64], r1 // p2 + vld1.16 {d24}, [r0, :64], r1 // q0 + vld1.16 {d22}, [r10, :64], r1 // p1 + vld1.16 {d25}, [r0, :64], r1 // q1 + vld1.16 {d23}, [r10, :64], r1 // p0 + vld1.16 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + + lpf_4_wd6 + + sub r10, r0, r1, lsl #1 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_6_4_neon + mov r12, lr + sub r10, r0, #8 + vld1.16 {d20}, [r10, :64], r1 + vld1.16 {d24}, [r0, :64], r1 + vld1.16 {d21}, [r10, :64], r1 + vld1.16 {d25}, [r0, :64], r1 + vld1.16 {d22}, [r10, :64], r1 + vld1.16 {d26}, [r0, :64], r1 + vld1.16 {d23}, [r10, :64], r1 + vld1.16 {d27}, [r0, :64], r1 + + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + + lpf_4_wd6 + + sub r0, r0, #4 + transpose_4x4h q11, q12, d22, d23, d24, d25 + sub r10, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + + vst1.16 {d22}, [r10], r1 + vst1.16 {d24}, [r0], r1 + vst1.16 {d23}, [r10], r1 + vst1.16 {d25}, [r0], r1 + add r0, r0, #4 + bx r12 +endfunc + +function lpf_v_8_4_neon + mov r12, lr + sub r10, r0, r1, lsl #2 + vld1.16 {d20}, [r10, :64], r1 // p3 + vld1.16 {d24}, [r0, :64], r1 // q0 + vld1.16 {d21}, [r10, :64], r1 // p2 + vld1.16 {d25}, [r0, :64], r1 // q1 + vld1.16 {d22}, [r10, :64], r1 // p1 + vld1.16 {d26}, [r0, :64], r1 // q2 + vld1.16 {d23}, [r10, :64], r1 // p0 + vld1.16 {d27}, [r0, :64], r1 // q3 + sub r0, r0, r1, lsl #2 + + lpf_4_wd8 + + sub r10, r0, r1, lsl #1 + sub r10, r10, r1 + vst1.16 {d21}, [r10, :64], r1 // p2 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d25}, [r0, :64], r1 // q1 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + bx r12 + +8: + sub r10, r0, r1, lsl #1 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_8_4_neon + mov r12, lr + sub r10, r0, #8 + vld1.16 {d20}, [r10, :64], r1 + vld1.16 {d24}, [r0, :64], r1 + vld1.16 {d21}, [r10, :64], r1 + vld1.16 {d25}, [r0, :64], r1 + vld1.16 {d22}, [r10, :64], r1 + vld1.16 {d26}, [r0, :64], r1 + vld1.16 {d23}, [r10, :64], r1 + vld1.16 {d27}, [r0, :64], r1 + + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + + lpf_4_wd8 + + sub r0, r0, r1, lsl #2 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + sub r10, r0, #8 + + vst1.16 {d20}, [r10, :64], r1 + vst1.16 {d24}, [r0, :64], r1 + vst1.16 {d21}, [r10, :64], r1 + vst1.16 {d25}, [r0, :64], r1 + vst1.16 {d22}, [r10, :64], r1 + vst1.16 {d26}, [r0, :64], r1 + vst1.16 {d23}, [r10, :64], r1 + vst1.16 {d27}, [r0, :64], r1 + bx r12 +8: + sub r0, r0, #4 + transpose_4x4h q11, q12, d22, d23, d24, d25 + sub r10, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + + vst1.16 {d22}, [r10], r1 + vst1.16 {d24}, [r0], r1 + vst1.16 {d23}, [r10], r1 + vst1.16 {d25}, [r0], r1 + add r0, r0, #4 + bx r12 +endfunc + +function lpf_v_16_4_neon + mov r12, lr + + sub r10, r0, r1, lsl #3 + add r10, r10, r1 + vld1.16 {d17}, [r10, :64], r1 // p6 + vld1.16 {d24}, [r0, :64], r1 // q0 + vld1.16 {d18}, [r10, :64], r1 // p5 + vld1.16 {d25}, [r0, :64], r1 // q1 + vld1.16 {d19}, [r10, :64], r1 // p4 + vld1.16 {d26}, [r0, :64], r1 // q2 + vld1.16 {d20}, [r10, :64], r1 // p3 + vld1.16 {d27}, [r0, :64], r1 // q3 + vld1.16 {d21}, [r10, :64], r1 // p2 + vld1.16 {d28}, [r0, :64], r1 // q4 + vld1.16 {d22}, [r10, :64], r1 // p1 + vld1.16 {d29}, [r0, :64], r1 // q5 + vld1.16 {d23}, [r10, :64], r1 // p0 + vld1.16 {d30}, [r0, :64], r1 // q6 + sub r0, r0, r1, lsl #3 + add r0, r0, r1 + + lpf_4_wd16 + + sub r10, r0, r1, lsl #2 + sub r10, r10, r1, lsl #1 + vst1.16 {d0}, [r10, :64], r1 // p5 + vst1.16 {d6}, [r0, :64], r1 // q0 + vst1.16 {d1}, [r10, :64], r1 // p4 + vst1.16 {d7}, [r0, :64], r1 // q1 + vst1.16 {d2}, [r10, :64], r1 // p3 + vst1.16 {d8}, [r0, :64], r1 // q2 + vst1.16 {d3}, [r10, :64], r1 // p2 + vst1.16 {d9}, [r0, :64], r1 // q3 + vst1.16 {d4}, [r10, :64], r1 // p1 + vst1.16 {d10}, [r0, :64], r1 // q4 + vst1.16 {d5}, [r10, :64], r1 // p0 + vst1.16 {d11}, [r0, :64], r1 // q5 + sub r0, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + bx r12 +7: + sub r10, r0, r1 + sub r10, r10, r1, lsl #1 + vst1.16 {d21}, [r10, :64], r1 // p2 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d25}, [r0, :64], r1 // q1 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d26}, [r0, :64], r1 // q2 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + bx r12 + +8: + sub r10, r0, r1, lsl #1 + vst1.16 {d22}, [r10, :64], r1 // p1 + vst1.16 {d24}, [r0, :64], r1 // q0 + vst1.16 {d23}, [r10, :64], r1 // p0 + vst1.16 {d25}, [r0, :64], r1 // q1 + sub r0, r0, r1, lsl #1 + bx r12 +endfunc + +function lpf_h_16_4_neon + mov r12, lr + sub r10, r0, #16 + sub r0, r0, #8 + vld1.16 {d16}, [r10, :64], r1 + vld1.16 {d20}, [r0, :64], r1 + vld1.16 {d17}, [r10, :64], r1 + vld1.16 {d21}, [r0, :64], r1 + vld1.16 {d18}, [r10, :64], r1 + vld1.16 {d22}, [r0, :64], r1 + vld1.16 {d19}, [r10, :64], r1 + vld1.16 {d23}, [r0, :64], r1 + sub r10, r10, r1, lsl #2 + sub r0, r0, r1, lsl #2 + add r10, r10, #16 + add r0, r0, #16 + vld1.16 {d24}, [r10, :64], r1 + vld1.16 {d28}, [r0, :64], r1 + vld1.16 {d25}, [r10, :64], r1 + vld1.16 {d29}, [r0, :64], r1 + vld1.16 {d26}, [r10, :64], r1 + vld1.16 {d30}, [r0, :64], r1 + vld1.16 {d27}, [r10, :64], r1 + vld1.16 {d31}, [r0, :64], r1 + sub r0, r0, #8 + + transpose_4x4h q8, q9, d16, d17, d18, d19 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + transpose_4x4h q14, q15, d28, d29, d30, d31 + + lpf_4_wd16 + + sub r0, r0, r1, lsl #2 + transpose_4x4h q8, q0, d16, d17, d0, d1 + transpose_4x4h q1, q2, d2, d3, d4, d5 + transpose_4x4h q3, q4, d6, d7, d8, d9 + transpose_4x4h q5, q15, d10, d11, d30, d31 + sub r10, r0, #16 + sub r0, r0, #8 + + vst1.16 {d16}, [r10, :64], r1 + vst1.16 {d2}, [r0, :64], r1 + vst1.16 {d17}, [r10, :64], r1 + vst1.16 {d3}, [r0, :64], r1 + vst1.16 {d0}, [r10, :64], r1 + vst1.16 {d4}, [r0, :64], r1 + vst1.16 {d1}, [r10, :64], r1 + vst1.16 {d5}, [r0, :64], r1 + sub r10, r10, r1, lsl #2 + sub r0, r0, r1, lsl #2 + add r10, r10, #16 + add r0, r0, #16 + vst1.16 {d6}, [r10, :64], r1 + vst1.16 {d10}, [r0, :64], r1 + vst1.16 {d7}, [r10, :64], r1 + vst1.16 {d11}, [r0, :64], r1 + vst1.16 {d8}, [r10, :64], r1 + vst1.16 {d30}, [r0, :64], r1 + vst1.16 {d9}, [r10, :64], r1 + vst1.16 {d31}, [r0, :64], r1 + sub r0, r0, #8 + + bx r12 + +7: + sub r0, r0, r1, lsl #2 + transpose_4x4h q10, q11, d20, d21, d22, d23 + transpose_4x4h q12, q13, d24, d25, d26, d27 + sub r10, r0, #8 + + vst1.16 {d20}, [r10, :64], r1 + vst1.16 {d24}, [r0, :64], r1 + vst1.16 {d21}, [r10, :64], r1 + vst1.16 {d25}, [r0, :64], r1 + vst1.16 {d22}, [r10, :64], r1 + vst1.16 {d26}, [r0, :64], r1 + vst1.16 {d23}, [r10, :64], r1 + vst1.16 {d27}, [r0, :64], r1 + bx r12 +8: + sub r0, r0, #4 + transpose_4x4h q11, q12, d22, d23, d24, d25 + sub r10, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + + vst1.16 {d22}, [r10], r1 + vst1.16 {d24}, [r0], r1 + vst1.16 {d23}, [r10], r1 + vst1.16 {d25}, [r0], r1 + add r0, r0, #4 + bx r12 +endfunc + +// void dav1d_lpf_v_sb_y_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint32_t *const vmask, +// const uint8_t (*l)[4], ptrdiff_t b4_stride, +// const Av1FilterLUT *lut, const int w, +// const int bitdepth_max) + +.macro lpf_func dir, type +function lpf_\dir\()_sb_\type\()_16bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldr r8, [sp, #112] // bitdepth_max; the 'w' parameter isn't loaded + sub sp, sp, #8 + clz r9, r8 + rsb r9, r9, #24 // bitdepth_min_8 + ldrd r6, r7, [r2] // vmask[0], vmask[1] +.ifc \type, y + ldr r2, [r2, #8] // vmask[2] +.endif + add r5, r5, #128 // Move to sharp part of lut +.ifc \type, y + orr r7, r7, r2 // vmask[1] |= vmask[2] +.endif +.ifc \dir, v + sub r4, r3, r4, lsl #2 +.else + sub r3, r3, #4 + lsl r4, r4, #2 +.endif + orr r6, r6, r7 // vmask[0] |= vmask[1] + +1: + tst r6, #0x01 + strd r6, r7, [sp] +.ifc \dir, v + ldrb r10, [r4], #4 + ldrb r11, [r3], #4 +.else + ldrb r10, [r3] + ldrb r11, [r3, #4] + add r3, r3, r4 +.endif + beq 7f // if (!(vm & bits)) continue; + + orrs r12, r10, r11 + vdup.16 d31, r9 // bitdepth_min_8 + beq 7f // if (!(l[0][0] | l[offset][0])) continue; + cmp r11, #0 // Check for nonzero values in l[0][0] + ldrb r6, [r5], #8 // sharp[0] + it eq + moveq r11, r10 // if (!l[0][0]) L = l[offset][0] + ldrb r12, [r5] // sharp[1] + lsr r6, r11, r6 // L >> sharp[0] + sub r5, r5, #8 + cmp r12, r6 + lsr r10, r11, #4 // H + add r11, r11, #2 // L + 2 + it lt + movlt r6, r12 // imin(L >> sharp[0], sharp[1]) + add r11, r11, r11 // 2*(L + 2) + cmp r6, #1 + lsl r10, r10, r9 // H << bitdepth_min_8 + it lt + movlt r6, #1 // imax(imin(), 1) = limit = I + vdup.16 d12, r10 // H << bitdepth_min_8 + add r11, r11, r6 // 2*(L + 2) + limit = E + lsl r6, r6, r9 // I << bitdepth_min_8 + lsl r11, r11, r9 // E << bitdepth_min_8 + vdup.16 d11, r6 // I << bitdepth_min_8 + vdup.16 d10, r11 // E << bitdepth_min_8 + +.ifc \type, y + tst r2, #0x01 + beq 2f + // wd16 + bl lpf_\dir\()_16_4_neon + b 8f +2: +.endif + tst r7, #0x01 + beq 3f +.ifc \type, y + // wd8 + bl lpf_\dir\()_8_4_neon +.else + // wd6 + bl lpf_\dir\()_6_4_neon +.endif + b 8f +3: + // wd4 + bl lpf_\dir\()_4_4_neon +.ifc \dir, h + b 8f +7: + // For dir h, the functions above increment r0. + // If the whole function is skipped, increment it here instead. + add r0, r0, r1, lsl #2 +.else +7: +.endif +8: + ldrd r6, r7, [sp] +.ifc \type, y + lsr r2, r2, #1 // vmask[2] >>= 1 +.endif +.ifc \dir, v + add r0, r0, #8 +.else + // For dir h, r0 is returned incremented +.endif + lsrs r6, r6, #1 // vmask[0] >>= 1 + lsr r7, r7, #1 // vmask[1] >>= 1 + bne 1b + + add sp, sp, #8 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +lpf_func v, y +lpf_func h, y +lpf_func v, uv +lpf_func h, uv diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,791 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +const right_ext_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +right_ext_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void dav1d_wiener_filter_h_8bpc_neon(int16_t *dst, const pixel (*left)[4], +// const pixel *src, ptrdiff_t stride, +// const int16_t fh[8], intptr_t w, +// int h, enum LrEdgeFlags edges); +function wiener_filter_h_8bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + mov r8, r5 + vld1.16 {q0}, [r4, :128] + movw r9, #(1 << 14) - (1 << 2) + vdup.16 q14, r9 + vmov.s16 q15, #2048 + // Calculate mid_stride + add r10, r5, #7 + bic r10, r10, #7 + lsl r10, r10, #1 + + // Set up pointers for reading/writing alternate rows + add r12, r0, r10 + lsl r10, r10, #1 + add lr, r2, r3 + lsl r3, r3, #1 + + // Subtract the aligned width from mid_stride + add r11, r5, #7 + bic r11, r11, #7 + sub r10, r10, r11, lsl #1 + + // Subtract the number of pixels read from the source stride + add r11, r11, #8 + sub r3, r3, r11 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r1, #0 + bne 0f + // left == NULL + sub r2, r2, #3 + sub lr, lr, #3 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add r3, r3, #3 + + +1: // Loop vertically + vld1.8 {q2}, [r2]! + vld1.8 {q9}, [lr]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r1, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.32 {d3[1]}, [r1]! + // Move r2/lr back to account for the last 3 bytes we loaded earlier, + // which we'll shift out. + sub r2, r2, #3 + sub lr, lr, #3 + vld1.32 {d17[1]}, [r1]! + vext.8 q2, q1, q2, #13 + vext.8 q9, q8, q9, #13 + b 2f +0: + // !LR_HAVE_LEFT, fill q1 with the leftmost byte + // and shift q2 to have 3x the first byte at the front. + vdup.8 q1, d4[0] + vdup.8 q8, d18[0] + // Move r2 back to account for the last 3 bytes we loaded before, + // which we shifted out. + sub r2, r2, #3 + sub lr, lr, #3 + vext.8 q2, q1, q2, #13 + vext.8 q9, q8, q9, #13 + +2: + vmovl.u8 q1, d4 + vmovl.u8 q2, d5 + vmovl.u8 q8, d18 + vmovl.u8 q9, d19 + + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that byte to pad with + // here since we can find it pretty easily from here. + sub r9, r5, #14 + ldrb r11, [r2, r9] + ldrb r9, [lr, r9] + // Fill q12/q13 with the right padding pixel + vdup.16 q12, r11 + vdup.16 q13, r9 +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #11 + bge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+3 pixels valid in q1-q2. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in q1/2.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel_local r4, right_ext_mask, -6 + sub r4, r4, r5, lsl #1 + vld1.8 {q10, q11}, [r4] + + vbit q1, q12, q10 + vbit q2, q12, q11 + vbit q8, q13, q10 + vbit q9, q13, q11 + +4: // Loop horizontally + vext.8 q11, q1, q2, #4 + vext.8 q5, q1, q2, #8 + vext.8 q10, q1, q2, #2 + vext.8 q6, q1, q2, #10 + vext.8 q7, q1, q2, #12 + vext.8 q4, q1, q2, #6 + vadd.i16 q5, q5, q11 + vadd.i16 q6, q6, q10 + vadd.i16 q7, q7, q1 + vmul.s16 q3, q4, d0[3] + vmla.s16 q3, q5, d1[0] + vmla.s16 q3, q6, d1[1] + vmla.s16 q3, q7, d1[2] + + vext.8 q4, q8, q9, #4 + vext.8 q6, q8, q9, #8 + vext.8 q11, q8, q9, #2 + vext.8 q7, q8, q9, #10 + vadd.i16 q6, q6, q4 + vext.8 q4, q8, q9, #12 + vext.8 q5, q8, q9, #6 + vadd.i16 q7, q7, q11 + vadd.i16 q4, q4, q8 + vmul.s16 q10, q5, d0[3] + vmla.s16 q10, q6, d1[0] + vmla.s16 q10, q7, d1[1] + vmla.s16 q10, q4, d1[2] + + vext.8 q1, q1, q2, #6 + vext.8 q8, q8, q9, #6 + vshl.s16 q1, q1, #7 + vshl.s16 q8, q8, #7 + vsub.s16 q1, q1, q14 + vsub.s16 q8, q8, q14 + vqadd.s16 q3, q3, q1 + vqadd.s16 q10, q10, q8 + vshr.s16 q3, q3, #3 + vshr.s16 q10, q10, #3 + vadd.s16 q3, q3, q15 + vadd.s16 q10, q10, q15 + subs r5, r5, #8 + vst1.16 {q3}, [r0, :128]! + vst1.16 {q10}, [r12, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vmov q1, q2 + vmov q8, q9 + vld1.8 {d4}, [r2]! + vld1.8 {d18}, [lr]! + vmovl.u8 q2, d4 + vmovl.u8 q9, d18 + bne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r10 + add r12, r12, r10 + add r2, r2, r3 + add lr, lr, r3 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_wiener_filter_v_8bpc_neon(pixel *dst, ptrdiff_t stride, +// const int16_t *mid, int w, int h, +// const int16_t fv[8], enum LrEdgeFlags edges, +// ptrdiff_t mid_stride); +function wiener_filter_v_8bpc_neon, export=1 + push {r4-r7,lr} + vpush {q4-q6} + ldrd r4, r5, [sp, #68] + ldrd r6, r7, [sp, #76] + mov lr, r4 + vld1.16 {q0}, [r5, :128] + + // Calculate the number of rows to move back when looping vertically + mov r12, r4 + tst r6, #4 // LR_HAVE_TOP + beq 0f + sub r2, r2, r7, lsl #1 + add r12, r12, #2 +0: + tst r6, #8 // LR_HAVE_BOTTOM + beq 1f + add r12, r12, #2 + +1: // Start of horizontal loop; start one vertical filter slice. + // Load rows into q8-q11 and pad properly. + tst r6, #4 // LR_HAVE_TOP + vld1.16 {q8}, [r2, :128], r7 + beq 2f + // LR_HAVE_TOP + vld1.16 {q10}, [r2, :128], r7 + vmov q9, q8 + vld1.16 {q11}, [r2, :128], r7 + b 3f +2: // !LR_HAVE_TOP + vmov q9, q8 + vmov q10, q8 + vmov q11, q8 + +3: + cmp r4, #4 + blt 5f + // Start filtering normally; fill in q12-q14 with unique rows. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + vld1.16 {q14}, [r2, :128], r7 + +4: +.macro filter compare + subs r4, r4, #1 + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + vadd.i16 q4, q10, q12 + vadd.i16 q5, q9, q13 + vadd.i16 q6, q8, q14 + vmull.s16 q2, d22, d0[3] + vmlal.s16 q2, d8, d1[0] + vmlal.s16 q2, d10, d1[1] + vmlal.s16 q2, d12, d1[2] + vmull.s16 q3, d23, d0[3] + vmlal.s16 q3, d9, d1[0] + vmlal.s16 q3, d11, d1[1] + vmlal.s16 q3, d13, d1[2] + vqrshrun.s32 d4, q2, #11 + vqrshrun.s32 d5, q3, #11 + vqmovun.s16 d4, q2 + vst1.8 {d4}, [r0, :64], r1 +.if \compare + cmp r4, #4 +.else + ble 9f +.endif + vmov q8, q9 + vmov q9, q10 + vmov q10, q11 + vmov q11, q12 + vmov q12, q13 + vmov q13, q14 +.endm + filter 1 + blt 7f + vld1.16 {q14}, [r2, :128], r7 + b 4b + +5: // Less than 4 rows in total; not all of q12-q13 are filled yet. + tst r6, #8 // LR_HAVE_BOTTOM + beq 6f + // LR_HAVE_BOTTOM + cmp r4, #2 + // We load at least 2 rows in all cases. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + bgt 53f // 3 rows in total + beq 52f // 2 rows in total +51: // 1 row in total, q11 already loaded, load edge into q12-q14. + vmov q13, q12 + b 8f +52: // 2 rows in total, q11 already loaded, load q12 with content data + // and 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vmov q15, q14 + b 8f +53: + // 3 rows in total, q11 already loaded, load q12 and q13 with content + // and 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vld1.16 {q15}, [r2, :128], r7 + vmov q1, q15 + b 8f + +6: + // !LR_HAVE_BOTTOM + cmp r4, #2 + bgt 63f // 3 rows in total + beq 62f // 2 rows in total +61: // 1 row in total, q11 already loaded, pad that into q12-q14. + vmov q12, q11 + vmov q13, q11 + vmov q14, q11 + b 8f +62: // 2 rows in total, q11 already loaded, load q12 and pad that into q12-q15. + vld1.16 {q12}, [r2, :128], r7 + vmov q13, q12 + vmov q14, q12 + vmov q15, q12 + b 8f +63: + // 3 rows in total, q11 already loaded, load q12 and q13 and pad q13 into q14-q15,q1. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + vmov q14, q13 + vmov q15, q13 + vmov q1, q13 + b 8f + +7: + // All registers up to q13 are filled already, 3 valid rows left. + // < 4 valid rows left; fill in padding and filter the last + // few rows. + tst r6, #8 // LR_HAVE_BOTTOM + beq 71f + // LR_HAVE_BOTTOM; load 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vld1.16 {q15}, [r2, :128], r7 + vmov q1, q15 + b 8f +71: + // !LR_HAVE_BOTTOM, pad 3 rows + vmov q14, q13 + vmov q15, q13 + vmov q1, q13 + +8: // At this point, all registers up to q14-15,q1 are loaded with + // edge/padding (depending on how many rows are left). + filter 0 // This branches to 9f when done + vmov q14, q15 + vmov q15, q1 + b 8b + +9: // End of one vertical slice. + subs r3, r3, #8 + ble 0f + // Move pointers back up to the top and loop horizontally. + mls r0, r1, lr, r0 + mls r2, r7, r12, r2 + add r0, r0, #8 + add r2, r2, #16 + mov r4, lr + b 1b + +0: + vpop {q4-q6} + pop {r4-r7,pc} +.purgem filter +endfunc + +#define SUM_STRIDE (384+16) + +#include "looprestoration_tmpl.S" + +// void dav1d_sgr_box3_h_8bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_h_8bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + add r5, r5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add r10, r0, #(4*SUM_STRIDE) // sumsq + add r11, r1, #(2*SUM_STRIDE) // sum + add r12, r3, r4 // src + lsl r4, r4, #1 + mov r9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add lr, r5, #7 + bic lr, lr, #7 + sub r9, r9, lr, lsl #1 + + // Store the width for the vertical loop + mov r8, r5 + + // Subtract the number of pixels read from the input from the stride + add lr, lr, #8 + sub r4, r4, lr + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r2, #0 + bne 0f + // left == NULL + sub r3, r3, #2 + sub r12, r12, #2 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 2 pixels from the src pointer, + // but shift it as if we had done that. + add r4, r4, #2 + + +1: // Loop vertically + vld1.8 {q0}, [r3]! + vld1.8 {q4}, [r12]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r2, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.32 {d3[]}, [r2]! + // Move r3/r12 back to account for the last 2 bytes we loaded earlier, + // which we'll shift out. + sub r3, r3, #2 + sub r12, r12, #2 + vld1.32 {d11[]}, [r2]! + vext.8 q0, q1, q0, #14 + vext.8 q4, q5, q4, #14 + b 2f +0: + // !LR_HAVE_LEFT, fill q1 with the leftmost byte + // and shift q0 to have 2x the first byte at the front. + vdup.8 q1, d0[0] + vdup.8 q5, d8[0] + // Move r3 back to account for the last 2 bytes we loaded before, + // which we shifted out. + sub r3, r3, #2 + sub r12, r12, #2 + vext.8 q0, q1, q0, #14 + vext.8 q4, q5, q4, #14 + +2: + vmull.u8 q1, d0, d0 + vmull.u8 q2, d1, d1 + vmull.u8 q5, d8, d8 + vmull.u8 q6, d9, d9 + + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that byte to pad with + // here since we can find it pretty easily from here. + sub lr, r5, #(2 + 16 - 2 + 1) + ldrb r11, [r3, lr] + ldrb lr, [r12, lr] + // Fill q14/q15 with the right padding pixel + vdup.8 q14, r11 + vdup.8 q15, lr + // Restore r11 after using it for a temporary value + add r11, r1, #(2*SUM_STRIDE) +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #10 + bge 4f // If w >= 10, all used input pixels are valid + + // 1 <= w < 10, w pixels valid in q0. For w=9, this ends up called + // again; it's not strictly needed in those cases (we pad enough here), + // but keeping the code as simple as possible. + + // Insert padding in q0/4.b[w] onwards + movrel_local lr, right_ext_mask + sub lr, lr, r5 + vld1.8 {q13}, [lr] + + vbit q0, q14, q13 + vbit q4, q15, q13 + + // Update the precalculated squares + vmull.u8 q1, d0, d0 + vmull.u8 q2, d1, d1 + vmull.u8 q5, d8, d8 + vmull.u8 q6, d9, d9 + +4: // Loop horizontally + vext.8 d16, d0, d1, #1 + vext.8 d17, d0, d1, #2 + vext.8 d18, d8, d9, #1 + vext.8 d19, d8, d9, #2 + vaddl.u8 q3, d0, d16 + vaddw.u8 q3, q3, d17 + vaddl.u8 q7, d8, d18 + vaddw.u8 q7, q7, d19 + + vext.8 q8, q1, q2, #2 + vext.8 q9, q1, q2, #4 + vext.8 q10, q5, q6, #2 + vext.8 q11, q5, q6, #4 + + vaddl.u16 q12, d2, d16 + vaddl.u16 q13, d3, d17 + vaddw.u16 q12, q12, d18 + vaddw.u16 q13, q13, d19 + + vaddl.u16 q8, d10, d20 + vaddl.u16 q9, d11, d21 + vaddw.u16 q8, q8, d22 + vaddw.u16 q9, q9, d23 + + subs r5, r5, #8 + vst1.16 {q3}, [r1, :128]! + vst1.16 {q7}, [r11, :128]! + vst1.32 {q12, q13}, [r0, :128]! + vst1.32 {q8, q9}, [r10, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vld1.8 {d6}, [r3]! + vld1.8 {d14}, [r12]! + vmov q1, q2 + vmov q5, q6 + vext.8 q0, q0, q3, #8 + vext.8 q4, q4, q7, #8 + vmull.u8 q2, d6, d6 + vmull.u8 q6, d14, d14 + + bne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r9, lsl #1 + add r10, r10, r9, lsl #1 + add r1, r1, r9 + add r11, r11, r9 + add r3, r3, r4 + add r12, r12, r4 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_sgr_box5_h_8bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_h_8bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + add r5, r5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add r10, r0, #(4*SUM_STRIDE) // sumsq + add r11, r1, #(2*SUM_STRIDE) // sum + add r12, r3, r4 // src + lsl r4, r4, #1 + mov r9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add lr, r5, #7 + bic lr, lr, #7 + sub r9, r9, lr, lsl #1 + add lr, lr, #8 + sub r4, r4, lr + + // Store the width for the vertical loop + mov r8, r5 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r2, #0 + bne 0f + // left == NULL + sub r3, r3, #3 + sub r12, r12, #3 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add r4, r4, #3 + +1: // Loop vertically + vld1.8 {q0}, [r3]! + vld1.8 {q4}, [r12]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r2, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.32 {d3[]}, [r2]! + // Move r3/r12 back to account for the last 3 bytes we loaded earlier, + // which we'll shift out. + sub r3, r3, #3 + sub r12, r12, #3 + vld1.32 {d11[]}, [r2]! + vext.8 q0, q1, q0, #13 + vext.8 q4, q5, q4, #13 + b 2f +0: + // !LR_HAVE_LEFT, fill q1 with the leftmost byte + // and shift q0 to have 3x the first byte at the front. + vdup.8 q1, d0[0] + vdup.8 q5, d8[0] + // Move r3 back to account for the last 3 bytes we loaded before, + // which we shifted out. + sub r3, r3, #3 + sub r12, r12, #3 + vext.8 q0, q1, q0, #13 + vext.8 q4, q5, q4, #13 + +2: + vmull.u8 q1, d0, d0 + vmull.u8 q2, d1, d1 + vmull.u8 q5, d8, d8 + vmull.u8 q6, d9, d9 + + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that byte to pad with + // here since we can find it pretty easily from here. + sub lr, r5, #(2 + 16 - 3 + 1) + ldrb r11, [r3, lr] + ldrb lr, [r12, lr] + // Fill q14/q15 with the right padding pixel + vdup.8 q14, r11 + vdup.8 q15, lr + // Restore r11 after using it for a temporary value + add r11, r1, #(2*SUM_STRIDE) +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #11 + bge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+1 pixels valid in q0. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in q0/4.b[w+1] onwards; fuse the +1 into the + // buffer pointer. + movrel_local lr, right_ext_mask, -1 + sub lr, lr, r5 + vld1.8 {q13}, [lr] + + vbit q0, q14, q13 + vbit q4, q15, q13 + + // Update the precalculated squares + vmull.u8 q1, d0, d0 + vmull.u8 q2, d1, d1 + vmull.u8 q5, d8, d8 + vmull.u8 q6, d9, d9 + +4: // Loop horizontally + vext.8 d16, d0, d1, #1 + vext.8 d17, d0, d1, #2 + vext.8 d18, d0, d1, #3 + vext.8 d19, d0, d1, #4 + vext.8 d20, d8, d9, #1 + vext.8 d21, d8, d9, #2 + vext.8 d22, d8, d9, #3 + vext.8 d23, d8, d9, #4 + vaddl.u8 q3, d0, d16 + vaddl.u8 q12, d17, d18 + vaddl.u8 q7, d8, d20 + vaddl.u8 q13, d21, d22 + vaddw.u8 q3, q3, d19 + vaddw.u8 q7, q7, d23 + vadd.u16 q3, q3, q12 + vadd.u16 q7, q7, q13 + + vext.8 q8, q1, q2, #2 + vext.8 q9, q1, q2, #4 + vext.8 q10, q1, q2, #6 + vext.8 q11, q1, q2, #8 + vaddl.u16 q12, d2, d16 + vaddl.u16 q13, d3, d17 + vaddl.u16 q8, d18, d20 + vaddl.u16 q9, d19, d21 + vaddw.u16 q12, q12, d22 + vaddw.u16 q13, q13, d23 + vadd.i32 q12, q12, q8 + vadd.i32 q13, q13, q9 + vext.8 q8, q5, q6, #2 + vext.8 q9, q5, q6, #4 + vext.8 q10, q5, q6, #6 + vext.8 q11, q5, q6, #8 + vaddl.u16 q1, d10, d16 + vaddl.u16 q5, d11, d17 + vaddl.u16 q8, d18, d20 + vaddl.u16 q9, d19, d21 + vaddw.u16 q1, q1, d22 + vaddw.u16 q5, q5, d23 + vadd.i32 q10, q1, q8 + vadd.i32 q11, q5, q9 + + subs r5, r5, #8 + vst1.16 {q3}, [r1, :128]! + vst1.16 {q7}, [r11, :128]! + vst1.32 {q12, q13}, [r0, :128]! + vst1.32 {q10, q11}, [r10, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vld1.8 {d6}, [r3]! + vld1.8 {d14}, [r12]! + vmov q1, q2 + vmov q5, q6 + vext.8 q0, q0, q3, #8 + vext.8 q4, q4, q7, #8 + vmull.u8 q2, d6, d6 + vmull.u8 q6, d14, d14 + bne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r9, lsl #1 + add r10, r10, r9, lsl #1 + add r1, r1, r9 + add r11, r11, r9 + add r3, r3, r4 + add r12, r12, r4 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +sgr_funcs 8 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,801 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +const right_ext_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +right_ext_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void dav1d_wiener_filter_h_16bpc_neon(int16_t *dst, const pixel (*left)[4], +// const pixel *src, ptrdiff_t stride, +// const int16_t fh[7], const intptr_t w, +// int h, enum LrEdgeFlags edges, +// const int bitdepth_max); +function wiener_filter_h_16bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + ldr r8, [sp, #116] // bitdepth_max + vld1.16 {q0}, [r4, :128] + clz r8, r8 + vmov.i32 q14, #1 + sub r9, r8, #38 // -(bitdepth + 6) + sub r8, r8, #25 // -round_bits_h + neg r9, r9 // bitdepth + 6 + vdup.32 q1, r9 + vdup.32 q13, r8 // -round_bits_h + vmov.i16 q15, #8192 + vshl.u32 q14, q14, q1 // 1 << (bitdepth + 6) + mov r8, r5 + // Calculate mid_stride + add r10, r5, #7 + bic r10, r10, #7 + lsl r10, r10, #1 + + // Set up pointers for reading/writing alternate rows + add r12, r0, r10 + lsl r10, r10, #1 + add lr, r2, r3 + lsl r3, r3, #1 + + // Subtract the aligned width from mid_stride + add r11, r5, #7 + bic r11, r11, #7 + sub r10, r10, r11, lsl #1 + + // Subtract the number of pixels read from the source stride + add r11, r11, #8 + sub r3, r3, r11, lsl #1 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r1, #0 + bne 0f + // left == NULL + sub r2, r2, #6 + sub lr, lr, #6 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add r3, r3, #6 + + +1: // Loop vertically + vld1.16 {q2, q3}, [r2]! + vld1.16 {q4, q5}, [lr]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r1, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.16 {d3}, [r1]! + // Move r2/lr back to account for the last 3 pixels we loaded earlier, + // which we'll shift out. + sub r2, r2, #6 + sub lr, lr, #6 + vld1.16 {d13}, [r1]! + vext.8 q3, q2, q3, #10 + vext.8 q2, q1, q2, #10 + vext.8 q5, q4, q5, #10 + vext.8 q4, q6, q4, #10 + b 2f +0: + // !LR_HAVE_LEFT, fill q1 with the leftmost pixel + // and shift q2/q3 to have 3x the first pixel at the front. + vdup.16 q1, d4[0] + vdup.16 q6, d8[0] + // Move r2 back to account for the last 3 pixels we loaded before, + // which we shifted out. + sub r2, r2, #6 + sub lr, lr, #6 + vext.8 q3, q2, q3, #10 + vext.8 q2, q1, q2, #10 + vext.8 q5, q4, q5, #10 + vext.8 q4, q6, q4, #10 + +2: + + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that pixel to pad with + // here since we can find it pretty easily from here. + sub r9, r5, #14 + lsl r9, r9, #1 + ldrh r11, [r2, r9] + ldrh r9, [lr, r9] + // Fill q11/q12 with the right padding pixel + vdup.16 q11, r11 + vdup.16 q12, r9 +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #11 + bge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+3 pixels valid in q2-q3. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in q2/3.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel_local r4, right_ext_mask, -6 + sub r4, r4, r5, lsl #1 + vld1.8 {q9, q10}, [r4] + + vbit q2, q11, q9 + vbit q3, q11, q10 + vbit q4, q12, q9 + vbit q5, q12, q10 + +4: // Loop horizontally + vext.8 q7, q2, q3, #4 + vext.8 q8, q2, q3, #8 + vext.8 q6, q2, q3, #2 + vext.8 q9, q2, q3, #10 + vadd.i16 q8, q8, q7 + vadd.i16 q9, q9, q6 + vext.8 q6, q2, q3, #12 + vext.8 q7, q2, q3, #6 + vadd.i16 q2, q2, q6 + vmull.s16 q6, d14, d0[3] + vmlal.s16 q6, d16, d1[0] + vmlal.s16 q6, d18, d1[1] + vmlal.s16 q6, d4, d1[2] + vmull.s16 q7, d15, d0[3] + vmlal.s16 q7, d17, d1[0] + vmlal.s16 q7, d19, d1[1] + vmlal.s16 q7, d5, d1[2] + + vext.8 q8, q4, q5, #4 + vext.8 q10, q4, q5, #8 + vext.8 q9, q4, q5, #2 + vext.8 q2, q4, q5, #10 + vadd.i16 q10, q10, q8 + vadd.i16 q2, q2, q9 + vext.8 q8, q4, q5, #12 + vext.8 q9, q4, q5, #6 + vadd.i16 q4, q4, q8 + vmull.s16 q8, d18, d0[3] + vmlal.s16 q8, d20, d1[0] + vmlal.s16 q8, d4, d1[1] + vmlal.s16 q8, d8, d1[2] + vmull.s16 q9, d19, d0[3] + vmlal.s16 q9, d21, d1[0] + vmlal.s16 q9, d5, d1[1] + vmlal.s16 q9, d9, d1[2] + + vmvn.i16 q10, #0x8000 // 0x7fff = (1 << 15) - 1 + vadd.i32 q6, q6, q14 + vadd.i32 q7, q7, q14 + vadd.i32 q8, q8, q14 + vadd.i32 q9, q9, q14 + vrshl.s32 q6, q6, q13 + vrshl.s32 q7, q7, q13 + vrshl.s32 q8, q8, q13 + vrshl.s32 q9, q9, q13 + vqmovun.s32 d12, q6 + vqmovun.s32 d13, q7 + vqmovun.s32 d14, q8 + vqmovun.s32 d15, q9 + vmin.u16 q6, q6, q10 + vmin.u16 q7, q7, q10 + vsub.i16 q6, q6, q15 + vsub.i16 q7, q7, q15 + subs r5, r5, #8 + vst1.16 {q6}, [r0, :128]! + vst1.16 {q7}, [r12, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vmov q2, q3 + vmov q4, q5 + vld1.16 {q3}, [r2]! + vld1.16 {q5}, [lr]! + bne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r10 + add r12, r12, r10 + add r2, r2, r3 + add lr, lr, r3 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_wiener_filter_v_16bpc_neon(pixel *dst, ptrdiff_t stride, +// const int16_t *mid, int w, int h, +// const int16_t fv[7], enum LrEdgeFlags edges, +// ptrdiff_t mid_stride, const int bitdepth_max); +function wiener_filter_v_16bpc_neon, export=1 + push {r4-r7,lr} + vpush {q4-q5} + ldrd r4, r5, [sp, #52] + ldrd r6, r7, [sp, #60] + ldr lr, [sp, #68] // bitdepth_max + vld1.16 {q0}, [r5, :128] + vdup.16 q5, lr + clz lr, lr + sub lr, lr, #11 // round_bits_v + vdup.32 q4, lr + mov lr, r4 + vneg.s32 q4, q4 // -round_bits_v + + // Calculate the number of rows to move back when looping vertically + mov r12, r4 + tst r6, #4 // LR_HAVE_TOP + beq 0f + sub r2, r2, r7, lsl #1 + add r12, r12, #2 +0: + tst r6, #8 // LR_HAVE_BOTTOM + beq 1f + add r12, r12, #2 + +1: // Start of horizontal loop; start one vertical filter slice. + // Load rows into q8-q11 and pad properly. + tst r6, #4 // LR_HAVE_TOP + vld1.16 {q8}, [r2, :128], r7 + beq 2f + // LR_HAVE_TOP + vld1.16 {q10}, [r2, :128], r7 + vmov q9, q8 + vld1.16 {q11}, [r2, :128], r7 + b 3f +2: // !LR_HAVE_TOP + vmov q9, q8 + vmov q10, q8 + vmov q11, q8 + +3: + cmp r4, #4 + blt 5f + // Start filtering normally; fill in q12-q14 with unique rows. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + vld1.16 {q14}, [r2, :128], r7 + +4: +.macro filter compare + subs r4, r4, #1 + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + vmull.s16 q2, d16, d0[0] + vmlal.s16 q2, d18, d0[1] + vmlal.s16 q2, d20, d0[2] + vmlal.s16 q2, d22, d0[3] + vmlal.s16 q2, d24, d1[0] + vmlal.s16 q2, d26, d1[1] + vmlal.s16 q2, d28, d1[2] + vmull.s16 q3, d17, d0[0] + vmlal.s16 q3, d19, d0[1] + vmlal.s16 q3, d21, d0[2] + vmlal.s16 q3, d23, d0[3] + vmlal.s16 q3, d25, d1[0] + vmlal.s16 q3, d27, d1[1] + vmlal.s16 q3, d29, d1[2] + vrshl.s32 q2, q2, q4 // round_bits_v + vrshl.s32 q3, q3, q4 + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vmin.u16 q2, q2, q5 // bitdepth_max + vst1.16 {q2}, [r0, :128], r1 +.if \compare + cmp r4, #4 +.else + ble 9f +.endif + vmov q8, q9 + vmov q9, q10 + vmov q10, q11 + vmov q11, q12 + vmov q12, q13 + vmov q13, q14 +.endm + filter 1 + blt 7f + vld1.16 {q14}, [r2, :128], r7 + b 4b + +5: // Less than 4 rows in total; not all of q12-q13 are filled yet. + tst r6, #8 // LR_HAVE_BOTTOM + beq 6f + // LR_HAVE_BOTTOM + cmp r4, #2 + // We load at least 2 rows in all cases. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + bgt 53f // 3 rows in total + beq 52f // 2 rows in total +51: // 1 row in total, q11 already loaded, load edge into q12-q14. + vmov q13, q12 + b 8f +52: // 2 rows in total, q11 already loaded, load q12 with content data + // and 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vmov q15, q14 + b 8f +53: + // 3 rows in total, q11 already loaded, load q12 and q13 with content + // and 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vld1.16 {q15}, [r2, :128], r7 + vmov q1, q15 + b 8f + +6: + // !LR_HAVE_BOTTOM + cmp r4, #2 + bgt 63f // 3 rows in total + beq 62f // 2 rows in total +61: // 1 row in total, q11 already loaded, pad that into q12-q14. + vmov q12, q11 + vmov q13, q11 + vmov q14, q11 + b 8f +62: // 2 rows in total, q11 already loaded, load q12 and pad that into q12-q15. + vld1.16 {q12}, [r2, :128], r7 + vmov q13, q12 + vmov q14, q12 + vmov q15, q12 + b 8f +63: + // 3 rows in total, q11 already loaded, load q12 and q13 and pad q13 into q14-q15,q1. + vld1.16 {q12}, [r2, :128], r7 + vld1.16 {q13}, [r2, :128], r7 + vmov q14, q13 + vmov q15, q13 + vmov q1, q13 + b 8f + +7: + // All registers up to q13 are filled already, 3 valid rows left. + // < 4 valid rows left; fill in padding and filter the last + // few rows. + tst r6, #8 // LR_HAVE_BOTTOM + beq 71f + // LR_HAVE_BOTTOM; load 2 rows of edge. + vld1.16 {q14}, [r2, :128], r7 + vld1.16 {q15}, [r2, :128], r7 + vmov q1, q15 + b 8f +71: + // !LR_HAVE_BOTTOM, pad 3 rows + vmov q14, q13 + vmov q15, q13 + vmov q1, q13 + +8: // At this point, all registers up to q14-q15,q1 are loaded with + // edge/padding (depending on how many rows are left). + filter 0 // This branches to 9f when done + vmov q14, q15 + vmov q15, q1 + b 8b + +9: // End of one vertical slice. + subs r3, r3, #8 + ble 0f + // Move pointers back up to the top and loop horizontally. + mls r0, r1, lr, r0 + mls r2, r7, r12, r2 + add r0, r0, #16 + add r2, r2, #16 + mov r4, lr + b 1b + +0: + vpop {q4-q5} + pop {r4-r7,pc} +.purgem filter +endfunc + +#define SUM_STRIDE (384+16) + +#include "looprestoration_tmpl.S" + +// void dav1d_sgr_box3_h_16bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_h_16bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + add r5, r5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add r10, r0, #(4*SUM_STRIDE) // sumsq + add r11, r1, #(2*SUM_STRIDE) // sum + add r12, r3, r4 // src + lsl r4, r4, #1 + mov r9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add lr, r5, #7 + bic lr, lr, #7 + sub r9, r9, lr, lsl #1 + + // Store the width for the vertical loop + mov r8, r5 + + // Subtract the number of pixels read from the input from the stride + add lr, lr, #8 + sub r4, r4, lr, lsl #1 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r2, #0 + bne 0f + // left == NULL + sub r3, r3, #4 + sub r12, r12, #4 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 2 pixels from the src pointer, + // but shift it as if we had done that. + add r4, r4, #4 + + +1: // Loop vertically + vld1.16 {q0, q1}, [r3]! + vld1.16 {q4, q5}, [r12]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r2, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.16 {d5}, [r2]! + // Move r3/r12 back to account for the last 2 pixels we loaded earlier, + // which we'll shift out. + sub r3, r3, #4 + sub r12, r12, #4 + vld1.16 {d13}, [r2]! + vext.8 q1, q0, q1, #12 + vext.8 q0, q2, q0, #12 + vext.8 q5, q4, q5, #12 + vext.8 q4, q6, q4, #12 + b 2f +0: + // !LR_HAVE_LEFT, fill q2 with the leftmost pixel + // and shift q0 to have 2x the first byte at the front. + vdup.16 q2, d0[0] + vdup.16 q6, d8[0] + // Move r3 back to account for the last 2 pixels we loaded before, + // which we shifted out. + sub r3, r3, #4 + sub r12, r12, #4 + vext.8 q1, q0, q1, #12 + vext.8 q0, q2, q0, #12 + vext.8 q5, q4, q5, #12 + vext.8 q4, q6, q4, #12 + +2: + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that pixel to pad with + // here since we can find it pretty easily from here. + sub lr, r5, #(2 + 16 - 2 + 1) + lsl lr, lr, #1 + ldrh r11, [r3, lr] + ldrh lr, [r12, lr] + // Fill q14/q15 with the right padding pixel + vdup.16 q14, r11 + vdup.16 q15, lr + // Restore r11 after using it for a temporary value + add r11, r1, #(2*SUM_STRIDE) +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #10 + bge 4f // If w >= 10, all used input pixels are valid + + // 1 <= w < 10, w pixels valid in q0-q1. For w=9, this ends up called + // again; it's not strictly needed in those cases (we pad enough here), + // but keeping the code as simple as possible. + + // Insert padding in q0/1.h[w] onwards + movrel_local lr, right_ext_mask + sub lr, lr, r5, lsl #1 + vld1.8 {q12, q13}, [lr] + + vbit q0, q14, q12 + vbit q1, q14, q13 + vbit q4, q15, q12 + vbit q5, q15, q13 + +4: // Loop horizontally + vext.8 q8, q0, q1, #2 + vext.8 q10, q4, q5, #2 + vext.8 q9, q0, q1, #4 + vext.8 q11, q4, q5, #4 + vadd.i16 q2, q0, q8 + vadd.i16 q3, q4, q10 + vadd.i16 q2, q2, q9 + vadd.i16 q3, q3, q11 + + vmull.u16 q6, d0, d0 + vmlal.u16 q6, d16, d16 + vmlal.u16 q6, d18, d18 + vmull.u16 q12, d8, d8 + vmlal.u16 q12, d20, d20 + vmlal.u16 q12, d22, d22 + vmull.u16 q7, d1, d1 + vmlal.u16 q7, d17, d17 + vmlal.u16 q7, d19, d19 + vmull.u16 q13, d9, d9 + vmlal.u16 q13, d21, d21 + vmlal.u16 q13, d23, d23 + subs r5, r5, #8 + vst1.16 {q2}, [r1, :128]! + vst1.16 {q3}, [r11, :128]! + vst1.32 {q6, q7}, [r0, :128]! + vst1.32 {q12, q13}, [r10, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vmov q0, q1 + vmov q4, q5 + vld1.16 {q1}, [r3]! + vld1.16 {q5}, [r12]! + + bne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r9, lsl #1 + add r10, r10, r9, lsl #1 + add r1, r1, r9 + add r11, r11, r9 + add r3, r3, r4 + add r12, r12, r4 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_sgr_box5_h_16bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_h_16bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + add r5, r5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add r10, r0, #(4*SUM_STRIDE) // sumsq + add r11, r1, #(2*SUM_STRIDE) // sum + add r12, r3, r4 // src + lsl r4, r4, #1 + mov r9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add lr, r5, #7 + bic lr, lr, #7 + sub r9, r9, lr, lsl #1 + add lr, lr, #8 + sub r4, r4, lr, lsl #1 + + // Store the width for the vertical loop + mov r8, r5 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst r7, #1 // LR_HAVE_LEFT + beq 2f + // LR_HAVE_LEFT + cmp r2, #0 + bne 0f + // left == NULL + sub r3, r3, #6 + sub r12, r12, #6 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add r4, r4, #6 + +1: // Loop vertically + vld1.16 {q0, q1}, [r3]! + vld1.16 {q4, q5}, [r12]! + + tst r7, #1 // LR_HAVE_LEFT + beq 0f + cmp r2, #0 + beq 2f + // LR_HAVE_LEFT, left != NULL + vld1.16 {d5}, [r2]! + // Move r3/r12 back to account for the last 3 pixels we loaded earlier, + // which we'll shift out. + sub r3, r3, #6 + sub r12, r12, #6 + vld1.16 {d13}, [r2]! + vext.8 q1, q0, q1, #10 + vext.8 q0, q2, q0, #10 + vext.8 q5, q4, q5, #10 + vext.8 q4, q6, q4, #10 + b 2f +0: + // !LR_HAVE_LEFT, fill q2 with the leftmost pixel + // and shift q0 to have 3x the first pixel at the front. + vdup.16 q2, d0[0] + vdup.16 q6, d8[0] + // Move r3 back to account for the last 3 pixels we loaded before, + // which we shifted out. + sub r3, r3, #6 + sub r12, r12, #6 + vext.8 q1, q0, q1, #10 + vext.8 q0, q2, q0, #10 + vext.8 q5, q4, q5, #10 + vext.8 q4, q6, q4, #10 + +2: + tst r7, #2 // LR_HAVE_RIGHT + bne 4f + // If we'll need to pad the right edge, load that pixel to pad with + // here since we can find it pretty easily from here. + sub lr, r5, #(2 + 16 - 3 + 1) + lsl lr, lr, #1 + ldrh r11, [r3, lr] + ldrh lr, [r12, lr] + // Fill q14/q15 with the right padding pixel + vdup.16 q14, r11 + vdup.16 q15, lr + // Restore r11 after using it for a temporary value + add r11, r1, #(2*SUM_STRIDE) +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp r5, #11 + bge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+1 pixels valid in q0-q1. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in q0/1.h[w+1] onwards; fuse the +1 into the + // buffer pointer. + movrel_local lr, right_ext_mask, -2 + sub lr, lr, r5, lsl #1 + vld1.8 {q12, q13}, [lr] + + vbit q0, q14, q12 + vbit q1, q14, q13 + vbit q4, q15, q12 + vbit q5, q15, q13 + +4: // Loop horizontally + vext.8 q8, q0, q1, #2 + vext.8 q10, q4, q5, #2 + vext.8 q9, q0, q1, #4 + vext.8 q11, q4, q5, #4 + vadd.i16 q2, q0, q8 + vadd.i16 q3, q4, q10 + vadd.i16 q2, q2, q9 + vadd.i16 q3, q3, q11 + + vmull.u16 q6, d0, d0 + vmlal.u16 q6, d16, d16 + vmlal.u16 q6, d18, d18 + vmull.u16 q12, d8, d8 + vmlal.u16 q12, d20, d20 + vmlal.u16 q12, d22, d22 + vmull.u16 q7, d1, d1 + vmlal.u16 q7, d17, d17 + vmlal.u16 q7, d19, d19 + vmull.u16 q13, d9, d9 + vmlal.u16 q13, d21, d21 + vmlal.u16 q13, d23, d23 + + vext.8 q8, q0, q1, #6 + vext.8 q10, q4, q5, #6 + vext.8 q9, q0, q1, #8 + vext.8 q11, q4, q5, #8 + vadd.i16 q2, q2, q8 + vadd.i16 q3, q3, q10 + vadd.i16 q2, q2, q9 + vadd.i16 q3, q3, q11 + + vmlal.u16 q6, d16, d16 + vmlal.u16 q6, d1, d1 + vmlal.u16 q12, d20, d20 + vmlal.u16 q12, d9, d9 + vmlal.u16 q7, d17, d17 + vmlal.u16 q7, d19, d19 + vmlal.u16 q13, d21, d21 + vmlal.u16 q13, d23, d23 + + subs r5, r5, #8 + vst1.16 {q2}, [r1, :128]! + vst1.16 {q3}, [r11, :128]! + vst1.32 {q6, q7}, [r0, :128]! + vst1.32 {q12, q13}, [r10, :128]! + + ble 9f + tst r7, #2 // LR_HAVE_RIGHT + vmov q0, q1 + vmov q4, q5 + vld1.16 {q1}, [r3]! + vld1.16 {q5}, [r12]! + bne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs r6, r6, #2 + ble 0f + // Jump to the next row and loop horizontally + add r0, r0, r9, lsl #1 + add r10, r10, r9, lsl #1 + add r1, r1, r9 + add r11, r11, r9 + add r3, r3, r4 + add r12, r12, r4 + mov r5, r8 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +sgr_funcs 16 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_common.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_common.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_common.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_common.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,453 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define SUM_STRIDE (384+16) + +// void dav1d_sgr_box3_v_neon(int32_t *sumsq, int16_t *sum, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_v_neon, export=1 + push {r4-r9,lr} + ldr r4, [sp, #28] + add r12, r3, #2 // Number of output rows to move back + mov lr, r3 // Number of input rows to move back + add r2, r2, #2 // Actual summed width + mov r7, #(4*SUM_STRIDE) // sumsq stride + mov r8, #(2*SUM_STRIDE) // sum stride + sub r0, r0, #(4*SUM_STRIDE) // sumsq -= stride + sub r1, r1, #(2*SUM_STRIDE) // sum -= stride + + tst r4, #4 // LR_HAVE_TOP + beq 0f + // If have top, read from row -2. + sub r5, r0, #(4*SUM_STRIDE) + sub r6, r1, #(2*SUM_STRIDE) + add lr, lr, #2 + b 1f +0: + // !LR_HAVE_TOP + // If we don't have top, read from row 0 even if + // we start writing to row -1. + add r5, r0, #(4*SUM_STRIDE) + add r6, r1, #(2*SUM_STRIDE) +1: + + tst r4, #8 // LR_HAVE_BOTTOM + beq 1f + // LR_HAVE_BOTTOM + add r3, r3, #2 // Sum all h+2 lines with the main loop + add lr, lr, #2 +1: + mov r9, r3 // Backup of h for next loops + +1: + // Start of horizontal loop; start one vertical filter slice. + // Start loading rows into q8-q13 and q0-q2 taking top + // padding into consideration. + tst r4, #4 // LR_HAVE_TOP + vld1.32 {q8, q9}, [r5, :128], r7 + vld1.16 {q0}, [r6, :128], r8 + beq 2f + // LR_HAVE_TOP + vld1.32 {q10, q11}, [r5, :128], r7 + vld1.16 {q1}, [r6, :128], r8 + vld1.32 {q12, q13}, [r5, :128], r7 + vld1.16 {q2}, [r6, :128], r8 + b 3f +2: // !LR_HAVE_TOP + vmov q10, q8 + vmov q11, q9 + vmov q1, q0 + vmov q12, q8 + vmov q13, q9 + vmov q2, q0 + +3: + subs r3, r3, #1 +.macro add3 + vadd.i32 q8, q8, q10 + vadd.i32 q9, q9, q11 + vadd.i16 q0, q0, q1 + vadd.i32 q8, q8, q12 + vadd.i32 q9, q9, q13 + vadd.i16 q0, q0, q2 + vst1.32 {q8, q9}, [r0, :128], r7 + vst1.16 {q0}, [r1, :128], r8 +.endm + add3 + vmov q8, q10 + vmov q9, q11 + vmov q0, q1 + vmov q10, q12 + vmov q11, q13 + vmov q1, q2 + ble 4f + vld1.32 {q12, q13}, [r5, :128], r7 + vld1.16 {q2}, [r6, :128], r8 + b 3b + +4: + tst r4, #8 // LR_HAVE_BOTTOM + bne 5f + // !LR_HAVE_BOTTOM + // Produce two more rows, extending the already loaded rows. + add3 + vmov q8, q10 + vmov q9, q11 + vmov q0, q1 + add3 + +5: // End of one vertical slice. + subs r2, r2, #8 + ble 0f + // Move pointers back up to the top and loop horizontally. + // Input pointers + mls r5, r7, lr, r5 + mls r6, r8, lr, r6 + // Output pointers + mls r0, r7, r12, r0 + mls r1, r8, r12, r1 + add r0, r0, #32 + add r1, r1, #16 + add r5, r5, #32 + add r6, r6, #16 + mov r3, r9 + b 1b + +0: + pop {r4-r9,pc} +.purgem add3 +endfunc + +// void dav1d_sgr_box5_v_neon(int32_t *sumsq, int16_t *sum, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_v_neon, export=1 + push {r4-r9,lr} + vpush {q5-q7} + ldr r4, [sp, #76] + add r12, r3, #2 // Number of output rows to move back + mov lr, r3 // Number of input rows to move back + add r2, r2, #8 // Actual summed width + mov r7, #(4*SUM_STRIDE) // sumsq stride + mov r8, #(2*SUM_STRIDE) // sum stride + sub r0, r0, #(4*SUM_STRIDE) // sumsq -= stride + sub r1, r1, #(2*SUM_STRIDE) // sum -= stride + + tst r4, #4 // LR_HAVE_TOP + beq 0f + // If have top, read from row -2. + sub r5, r0, #(4*SUM_STRIDE) + sub r6, r1, #(2*SUM_STRIDE) + add lr, lr, #2 + b 1f +0: + // !LR_HAVE_TOP + // If we don't have top, read from row 0 even if + // we start writing to row -1. + add r5, r0, #(4*SUM_STRIDE) + add r6, r1, #(2*SUM_STRIDE) +1: + + tst r4, #8 // LR_HAVE_BOTTOM + beq 0f + // LR_HAVE_BOTTOM + add r3, r3, #2 // Handle h+2 lines with the main loop + add lr, lr, #2 + b 1f +0: + // !LR_HAVE_BOTTOM + sub r3, r3, #1 // Handle h-1 lines with the main loop +1: + mov r9, r3 // Backup of h for next loops + +1: + // Start of horizontal loop; start one vertical filter slice. + // Start loading rows into q6-q15 and q0-q3,q5 taking top + // padding into consideration. + tst r4, #4 // LR_HAVE_TOP + vld1.32 {q6, q7}, [r5, :128], r7 + vld1.16 {q0}, [r6, :128], r8 + beq 2f + // LR_HAVE_TOP + vld1.32 {q10, q11}, [r5, :128], r7 + vld1.16 {q2}, [r6, :128], r8 + vmov q8, q6 + vmov q9, q7 + vmov q1, q0 + vld1.32 {q12, q13}, [r5, :128], r7 + vld1.16 {q3}, [r6, :128], r8 + b 3f +2: // !LR_HAVE_TOP + vmov q8, q6 + vmov q9, q7 + vmov q1, q0 + vmov q10, q6 + vmov q11, q7 + vmov q2, q0 + vmov q12, q6 + vmov q13, q7 + vmov q3, q0 + +3: + cmp r3, #0 + beq 4f + vld1.32 {q14, q15}, [r5, :128], r7 + vld1.16 {q5}, [r6, :128], r8 + +3: + // Start of vertical loop + subs r3, r3, #2 +.macro add5 + vadd.i32 q6, q6, q8 + vadd.i32 q7, q7, q9 + vadd.i16 q0, q0, q1 + vadd.i32 q6, q6, q10 + vadd.i32 q7, q7, q11 + vadd.i16 q0, q0, q2 + vadd.i32 q6, q6, q12 + vadd.i32 q7, q7, q13 + vadd.i16 q0, q0, q3 + vadd.i32 q6, q6, q14 + vadd.i32 q7, q7, q15 + vadd.i16 q0, q0, q5 + vst1.32 {q6, q7}, [r0, :128], r7 + vst1.16 {q0}, [r1, :128], r8 +.endm + add5 +.macro shift2 + vmov q6, q10 + vmov q7, q11 + vmov q0, q2 + vmov q8, q12 + vmov q9, q13 + vmov q1, q3 + vmov q10, q14 + vmov q11, q15 + vmov q2, q5 +.endm + shift2 + add r0, r0, r7 + add r1, r1, r8 + ble 5f + vld1.32 {q12, q13}, [r5, :128], r7 + vld1.16 {q3}, [r6, :128], r8 + vld1.32 {q14, q15}, [r5, :128], r7 + vld1.16 {q5}, [r6, :128], r8 + b 3b + +4: + // h == 1, !LR_HAVE_BOTTOM. + // Pad the last row with the only content row, and add. + vmov q14, q12 + vmov q15, q13 + vmov q5, q3 + add5 + shift2 + add r0, r0, r7 + add r1, r1, r8 + add5 + b 6f + +5: + tst r4, #8 // LR_HAVE_BOTTOM + bne 6f + // !LR_HAVE_BOTTOM + cmp r3, #0 + bne 5f + // The intended three edge rows left; output the one at h-2 and + // the past edge one at h. + vld1.32 {q12, q13}, [r5, :128], r7 + vld1.16 {q3}, [r6, :128], r8 + // Pad the past-edge row from the last content row. + vmov q14, q12 + vmov q15, q13 + vmov q5, q3 + add5 + shift2 + add r0, r0, r7 + add r1, r1, r8 + // The last two rows are already padded properly here. + add5 + b 6f + +5: + // r3 == -1, two rows left, output one. + // Pad the last two rows from the mid one. + vmov q12, q10 + vmov q13, q11 + vmov q3, q2 + vmov q14, q10 + vmov q15, q11 + vmov q5, q2 + add5 + add r0, r0, r7 + add r1, r1, r8 + b 6f + +6: // End of one vertical slice. + subs r2, r2, #8 + ble 0f + // Move pointers back up to the top and loop horizontally. + // Input pointers + mls r5, r7, lr, r5 + mls r6, r8, lr, r6 + // Output pointers + mls r0, r7, r12, r0 + mls r1, r8, r12, r1 + add r0, r0, #32 + add r1, r1, #16 + add r5, r5, #32 + add r6, r6, #16 + mov r3, r9 + b 1b + +0: + vpop {q5-q7} + pop {r4-r9,pc} +.purgem add5 +endfunc + +// void dav1d_sgr_calc_ab1_neon(int32_t *a, int16_t *b, +// const int w, const int h, const int strength, +// const int bitdepth_max); +// void dav1d_sgr_calc_ab2_neon(int32_t *a, int16_t *b, +// const int w, const int h, const int strength, +// const int bitdepth_max); +function sgr_calc_ab1_neon, export=1 + push {r4-r7,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #84] + add r3, r3, #2 // h += 2 + clz r6, r5 + vmov.i32 q15, #9 // n + movw r5, #455 + mov lr, #SUM_STRIDE + b sgr_calc_ab_neon +endfunc + +function sgr_calc_ab2_neon, export=1 + push {r4-r7,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #84] + add r3, r3, #3 // h += 3 + clz r6, r5 + asr r3, r3, #1 // h /= 2 + vmov.i32 q15, #25 // n + mov r5, #164 + mov lr, #(2*SUM_STRIDE) +endfunc + +function sgr_calc_ab_neon + movrel r12, X(sgr_x_by_x) + sub r6, r6, #24 // -bitdepth_min_8 + vld1.8 {q8, q9}, [r12, :128]! + add r7, r6, r6 // -2*bitdepth_min_8 + vmov.i8 q11, #5 + vmov.i8 d10, #55 // idx of last 5 + vld1.8 {q10}, [r12, :128] + vmov.i8 d11, #72 // idx of last 4 + vmov.i8 d12, #101 // idx of last 3 + vmov.i8 d13, #169 // idx of last 2 + vmov.i8 d14, #254 // idx of last 1 + vmov.i8 d15, #32 // elements consumed in first vtbl + add r2, r2, #2 // w += 2 + add r12, r2, #7 + bic r12, r12, #7 // aligned w + sub r12, lr, r12 // increment between rows + vdup.32 q12, r4 + sub r0, r0, #(4*(SUM_STRIDE)) + sub r1, r1, #(2*(SUM_STRIDE)) + mov r4, r2 // backup of w + vsub.i8 q8, q8, q11 + vsub.i8 q9, q9, q11 + vsub.i8 q10, q10, q11 +1: + vld1.32 {q0, q1}, [r0, :128] // a + vld1.16 {q2}, [r1, :128] // b + vdup.32 q13, r7 // -2*bitdepth_min_8 + vdup.16 q14, r6 // -bitdepth_min_8 + subs r2, r2, #8 + vrshl.s32 q0, q0, q13 + vrshl.s32 q1, q1, q13 + vrshl.s16 q4, q2, q14 + vmul.i32 q0, q0, q15 // a * n + vmul.i32 q1, q1, q15 // a * n + vmull.u16 q3, d8, d8 // b * b + vmull.u16 q4, d9, d9 // b * b + vqsub.u32 q0, q0, q3 // imax(a * n - b * b, 0) + vqsub.u32 q1, q1, q4 // imax(a * n - b * b, 0) + vmul.i32 q0, q0, q12 // p * s + vmul.i32 q1, q1, q12 // p * s + vqshrn.u32 d0, q0, #16 + vqshrn.u32 d1, q1, #16 + vqrshrn.u16 d0, q0, #4 // imin(z, 255) + + vcgt.u8 d2, d0, d10 // = -1 if sgr_x_by_x[d0] < 5 + vcgt.u8 d3, d0, d11 // = -1 if sgr_x_by_x[d0] < 4 + vtbl.8 d1, {q8, q9}, d0 + vcgt.u8 d6, d0, d12 // = -1 if sgr_x_by_x[d0] < 3 + vsub.i8 d9, d0, d15 // indices for vtbx + vcgt.u8 d7, d0, d13 // = -1 if sgr_x_by_x[d0] < 2 + vadd.i8 d2, d2, d3 + vtbx.8 d1, {q10}, d9 + vcgt.u8 d8, d0, d14 // = -1 if sgr_x_by_x[d0] < 1 + vadd.i8 d6, d6, d7 + vadd.i8 d8, d8, d22 + vadd.i8 d2, d2, d6 + vadd.i8 d1, d1, d8 + vadd.i8 d1, d1, d2 + vmovl.u8 q0, d1 // x + + vmov.i16 q13, #256 + vdup.32 q14, r5 // one_by_x + + vmull.u16 q1, d0, d4 // x * BB[i] + vmull.u16 q2, d1, d5 // x * BB[i] + vmul.i32 q1, q1, q14 // x * BB[i] * sgr_one_by_x + vmul.i32 q2, q2, q14 // x * BB[i] * sgr_one_by_x + vrshr.s32 q1, q1, #12 // AA[i] + vrshr.s32 q2, q2, #12 // AA[i] + vsub.i16 q0, q13, q0 // 256 - x + + vst1.32 {q1, q2}, [r0, :128]! + vst1.16 {q0}, [r1, :128]! + bgt 1b + + subs r3, r3, #1 + ble 0f + add r0, r0, r12, lsl #2 + add r1, r1, r12, lsl #1 + mov r2, r4 + b 1b +0: + vpop {q4-q7} + pop {r4-r7,pc} +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_tmpl.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_tmpl.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_tmpl.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/looprestoration_tmpl.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,600 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" + +#define FILTER_OUT_STRIDE 384 + +.macro sgr_funcs bpc +// void dav1d_sgr_finish_filter1_Xbpc_neon(int16_t *tmp, +// const pixel *src, const ptrdiff_t stride, +// const int32_t *a, const int16_t *b, +// const int w, const int h); +function sgr_finish_filter1_\bpc\()bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldr r6, [sp, #108] + sub r7, r3, #(4*SUM_STRIDE) + add r8, r3, #(4*SUM_STRIDE) + sub r9, r4, #(2*SUM_STRIDE) + add r10, r4, #(2*SUM_STRIDE) + mov r11, #SUM_STRIDE + mov r12, #FILTER_OUT_STRIDE + add lr, r5, #3 + bic lr, lr, #3 // Aligned width +.if \bpc == 8 + sub r2, r2, lr +.else + sub r2, r2, lr, lsl #1 +.endif + sub r12, r12, lr + sub r11, r11, lr + sub r11, r11, #4 // We read 4 extra elements from both a and b + mov lr, r5 + vmov.i16 q14, #3 + vmov.i32 q15, #3 +1: + vld1.16 {q0}, [r9, :128]! + vld1.16 {q1}, [r4, :128]! + vld1.16 {q2}, [r10, :128]! + vld1.32 {q8, q9}, [r7, :128]! + vld1.32 {q10, q11}, [r3, :128]! + vld1.32 {q12, q13}, [r8, :128]! + +2: + subs r5, r5, #4 + vext.8 d6, d0, d1, #2 // -stride + vext.8 d7, d2, d3, #2 // 0 + vext.8 d8, d4, d5, #2 // +stride + vext.8 d9, d0, d1, #4 // +1-stride + vext.8 d10, d2, d3, #4 // +1 + vext.8 d11, d4, d5, #4 // +1+stride + vadd.i16 d2, d2, d6 // -1, -stride + vadd.i16 d7, d7, d8 // 0, +stride + vadd.i16 d0, d0, d9 // -1-stride, +1-stride + vadd.i16 d2, d2, d7 + vadd.i16 d4, d4, d11 // -1+stride, +1+stride + vadd.i16 d2, d2, d10 // +1 + vadd.i16 d0, d0, d4 + + vext.8 q3, q8, q9, #4 // -stride + vshl.i16 d2, d2, #2 + vext.8 q4, q8, q9, #8 // +1-stride + vext.8 q5, q10, q11, #4 // 0 + vext.8 q6, q10, q11, #8 // +1 + vmla.i16 d2, d0, d28 // * 3 -> a + vadd.i32 q3, q3, q10 // -stride, -1 + vadd.i32 q8, q8, q4 // -1-stride, +1-stride + vadd.i32 q5, q5, q6 // 0, +1 + vadd.i32 q8, q8, q12 // -1+stride + vadd.i32 q3, q3, q5 + vext.8 q7, q12, q13, #4 // +stride + vext.8 q10, q12, q13, #8 // +1+stride +.if \bpc == 8 + vld1.32 {d24[0]}, [r1, :32]! // src +.else + vld1.16 {d24}, [r1, :64]! // src +.endif + vadd.i32 q3, q3, q7 // +stride + vadd.i32 q8, q8, q10 // +1+stride + vshl.i32 q3, q3, #2 + vmla.i32 q3, q8, q15 // * 3 -> b +.if \bpc == 8 + vmovl.u8 q12, d24 // src +.endif + vmov d0, d1 + vmlal.u16 q3, d2, d24 // b + a * src + vmov d2, d3 + vrshrn.i32 d6, q3, #9 + vmov d4, d5 + vst1.16 {d6}, [r0]! + + ble 3f + vmov q8, q9 + vmov q10, q11 + vmov q12, q13 + vld1.16 {d1}, [r9, :64]! + vld1.16 {d3}, [r4, :64]! + vld1.16 {d5}, [r10, :64]! + vld1.32 {q9}, [r7, :128]! + vld1.32 {q11}, [r3, :128]! + vld1.32 {q13}, [r8, :128]! + b 2b + +3: + subs r6, r6, #1 + ble 0f + mov r5, lr + add r0, r0, r12, lsl #1 + add r1, r1, r2 + add r3, r3, r11, lsl #2 + add r7, r7, r11, lsl #2 + add r8, r8, r11, lsl #2 + add r4, r4, r11, lsl #1 + add r9, r9, r11, lsl #1 + add r10, r10, r11, lsl #1 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_sgr_finish_filter2_Xbpc_neon(int16_t *tmp, +// const pixel *src, const ptrdiff_t stride, +// const int32_t *a, const int16_t *b, +// const int w, const int h); +function sgr_finish_filter2_\bpc\()bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldr r6, [sp, #108] + add r7, r3, #(4*(SUM_STRIDE)) + sub r3, r3, #(4*(SUM_STRIDE)) + add r8, r4, #(2*(SUM_STRIDE)) + sub r4, r4, #(2*(SUM_STRIDE)) + mov r9, #(2*SUM_STRIDE) + mov r10, #FILTER_OUT_STRIDE + add r11, r5, #7 + bic r11, r11, #7 // Aligned width +.if \bpc == 8 + sub r2, r2, r11 +.else + sub r2, r2, r11, lsl #1 +.endif + sub r10, r10, r11 + sub r9, r9, r11 + sub r9, r9, #4 // We read 4 extra elements from a + sub r12, r9, #4 // We read 8 extra elements from b + mov lr, r5 + +1: + vld1.16 {q0, q1}, [r4, :128]! + vld1.16 {q2, q3}, [r8, :128]! + vld1.32 {q8, q9}, [r3, :128]! + vld1.32 {q11, q12}, [r7, :128]! + vld1.32 {q10}, [r3, :128]! + vld1.32 {q13}, [r7, :128]! + +2: + vmov.i16 q14, #5 + vmov.i16 q15, #6 + subs r5, r5, #8 + vext.8 q4, q0, q1, #4 // +1-stride + vext.8 q5, q2, q3, #4 // +1+stride + vext.8 q6, q0, q1, #2 // -stride + vext.8 q7, q2, q3, #2 // +stride + vadd.i16 q0, q0, q4 // -1-stride, +1-stride + vadd.i16 q5, q2, q5 // -1+stride, +1+stride + vadd.i16 q2, q6, q7 // -stride, +stride + vadd.i16 q0, q0, q5 + + vext.8 q4, q8, q9, #8 // +1-stride + vext.8 q5, q9, q10, #8 + vext.8 q6, q11, q12, #8 // +1+stride + vext.8 q7, q12, q13, #8 + vmul.i16 q0, q0, q14 // * 5 + vmla.i16 q0, q2, q15 // * 6 + vadd.i32 q4, q4, q8 // -1-stride, +1-stride + vadd.i32 q5, q5, q9 + vadd.i32 q6, q6, q11 // -1+stride, +1+stride + vadd.i32 q7, q7, q12 + vadd.i32 q4, q4, q6 + vadd.i32 q5, q5, q7 + vext.8 q6, q8, q9, #4 // -stride + vext.8 q7, q9, q10, #4 + vext.8 q8, q11, q12, #4 // +stride + vext.8 q11, q12, q13, #4 + +.if \bpc == 8 + vld1.8 {d4}, [r1, :64]! +.else + vld1.8 {q2}, [r1, :128]! +.endif + + vmov.i32 q14, #5 + vmov.i32 q15, #6 + + vadd.i32 q6, q6, q8 // -stride, +stride + vadd.i32 q7, q7, q11 + vmul.i32 q4, q4, q14 // * 5 + vmla.i32 q4, q6, q15 // * 6 + vmul.i32 q5, q5, q14 // * 5 + vmla.i32 q5, q7, q15 // * 6 + +.if \bpc == 8 + vmovl.u8 q2, d4 +.endif + vmlal.u16 q4, d0, d4 // b + a * src + vmlal.u16 q5, d1, d5 // b + a * src + vmov q0, q1 + vrshrn.i32 d8, q4, #9 + vrshrn.i32 d9, q5, #9 + vmov q2, q3 + vst1.16 {q4}, [r0, :128]! + + ble 3f + vmov q8, q10 + vmov q11, q13 + vld1.16 {q1}, [r4, :128]! + vld1.16 {q3}, [r8, :128]! + vld1.32 {q9, q10}, [r3, :128]! + vld1.32 {q12, q13}, [r7, :128]! + b 2b + +3: + subs r6, r6, #1 + ble 0f + mov r5, lr + add r0, r0, r10, lsl #1 + add r1, r1, r2 + add r3, r3, r9, lsl #2 + add r7, r7, r9, lsl #2 + add r4, r4, r12, lsl #1 + add r8, r8, r12, lsl #1 + + vld1.32 {q8, q9}, [r3, :128]! + vld1.16 {q0, q1}, [r4, :128]! + vld1.32 {q10}, [r3, :128]! + + vmov.i16 q12, #5 + vmov.i16 q13, #6 + +4: + subs r5, r5, #8 + vext.8 q3, q0, q1, #4 // +1 + vext.8 q2, q0, q1, #2 // 0 + vadd.i16 q0, q0, q3 // -1, +1 + + vext.8 q4, q8, q9, #4 // 0 + vext.8 q5, q9, q10, #4 + vext.8 q6, q8, q9, #8 // +1 + vext.8 q7, q9, q10, #8 + vmul.i16 q2, q2, q13 // * 6 + vmla.i16 q2, q0, q12 // * 5 -> a +.if \bpc == 8 + vld1.8 {d22}, [r1, :64]! +.else + vld1.16 {q11}, [r1, :128]! +.endif + vadd.i32 q8, q8, q6 // -1, +1 + vadd.i32 q9, q9, q7 +.if \bpc == 8 + vmovl.u8 q11, d22 +.endif + vmul.i32 q4, q4, q15 // * 6 + vmla.i32 q4, q8, q14 // * 5 -> b + vmul.i32 q5, q5, q15 // * 6 + vmla.i32 q5, q9, q14 // * 5 -> b + + vmlal.u16 q4, d4, d22 // b + a * src + vmlal.u16 q5, d5, d23 + vmov q0, q1 + vrshrn.i32 d8, q4, #8 + vrshrn.i32 d9, q5, #8 + vmov q8, q10 + vst1.16 {q4}, [r0, :128]! + + ble 5f + vld1.16 {q1}, [r4, :128]! + vld1.32 {q9, q10}, [r3, :128]! + b 4b + +5: + subs r6, r6, #1 + ble 0f + mov r5, lr + sub r3, r3, r11, lsl #2 // Rewind r3/r4 to where they started + sub r4, r4, r11, lsl #1 + add r0, r0, r10, lsl #1 + add r1, r1, r2 + sub r3, r3, #16 + sub r4, r4, #16 + b 1b +0: + vpop {q4-q7} + pop {r4-r11,pc} +endfunc + +// void dav1d_sgr_weighted1_Xbpc_neon(pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *t1, const int w, const int h, +// const int wt, const int bitdepth_max); +function sgr_weighted1_\bpc\()bpc_neon, export=1 + push {r4-r9,lr} + ldrd r4, r5, [sp, #28] + ldrd r6, r7, [sp, #36] +.if \bpc == 16 + ldr r8, [sp, #44] +.endif + vdup.16 d31, r7 + cmp r6, #2 +.if \bpc == 16 + vdup.16 q14, r8 +.endif + add r9, r0, r1 + add r12, r2, r3 + add lr, r4, #2*FILTER_OUT_STRIDE + mov r7, #(4*FILTER_OUT_STRIDE) + lsl r1, r1, #1 + lsl r3, r3, #1 + add r8, r5, #7 + bic r8, r8, #7 // Aligned width +.if \bpc == 8 + sub r1, r1, r8 + sub r3, r3, r8 +.else + sub r1, r1, r8, lsl #1 + sub r3, r3, r8, lsl #1 +.endif + sub r7, r7, r8, lsl #1 + mov r8, r5 + blt 2f +1: +.if \bpc == 8 + vld1.8 {d0}, [r2, :64]! + vld1.8 {d16}, [r12, :64]! +.else + vld1.16 {q0}, [r2, :128]! + vld1.16 {q8}, [r12, :128]! +.endif + vld1.16 {q1}, [r4, :128]! + vld1.16 {q9}, [lr, :128]! + subs r5, r5, #8 +.if \bpc == 8 + vshll.u8 q0, d0, #4 // u + vshll.u8 q8, d16, #4 // u +.else + vshl.i16 q0, q0, #4 // u + vshl.i16 q8, q8, #4 // u +.endif + vsub.i16 q1, q1, q0 // t1 - u + vsub.i16 q9, q9, q8 // t1 - u + vshll.u16 q2, d0, #7 // u << 7 + vshll.u16 q3, d1, #7 // u << 7 + vshll.u16 q10, d16, #7 // u << 7 + vshll.u16 q11, d17, #7 // u << 7 + vmlal.s16 q2, d2, d31 // v + vmlal.s16 q3, d3, d31 // v + vmlal.s16 q10, d18, d31 // v + vmlal.s16 q11, d19, d31 // v +.if \bpc == 8 + vrshrn.i32 d4, q2, #11 + vrshrn.i32 d5, q3, #11 + vrshrn.i32 d20, q10, #11 + vrshrn.i32 d21, q11, #11 + vqmovun.s16 d4, q2 + vqmovun.s16 d20, q10 + vst1.8 {d4}, [r0, :64]! + vst1.8 {d20}, [r9, :64]! +.else + vqrshrun.s32 d4, q2, #11 + vqrshrun.s32 d5, q3, #11 + vqrshrun.s32 d20, q10, #11 + vqrshrun.s32 d21, q11, #11 + vmin.u16 q2, q2, q14 + vmin.u16 q10, q10, q14 + vst1.16 {q2}, [r0, :128]! + vst1.16 {q10}, [r9, :128]! +.endif + bgt 1b + + sub r6, r6, #2 + cmp r6, #1 + blt 0f + mov r5, r8 + add r0, r0, r1 + add r9, r9, r1 + add r2, r2, r3 + add r12, r12, r3 + add r4, r4, r7 + add lr, lr, r7 + beq 2f + b 1b + +2: +.if \bpc == 8 + vld1.8 {d0}, [r2, :64]! +.else + vld1.16 {q0}, [r2, :128]! +.endif + vld1.16 {q1}, [r4, :128]! + subs r5, r5, #8 +.if \bpc == 8 + vshll.u8 q0, d0, #4 // u +.else + vshl.i16 q0, q0, #4 // u +.endif + vsub.i16 q1, q1, q0 // t1 - u + vshll.u16 q2, d0, #7 // u << 7 + vshll.u16 q3, d1, #7 // u << 7 + vmlal.s16 q2, d2, d31 // v + vmlal.s16 q3, d3, d31 // v +.if \bpc == 8 + vrshrn.i32 d4, q2, #11 + vrshrn.i32 d5, q3, #11 + vqmovun.s16 d2, q2 + vst1.8 {d2}, [r0, :64]! +.else + vqrshrun.s32 d4, q2, #11 + vqrshrun.s32 d5, q3, #11 + vmin.u16 q2, q2, q14 + vst1.16 {q2}, [r0, :128]! +.endif + bgt 2b +0: + pop {r4-r9,pc} +endfunc + +// void dav1d_sgr_weighted2_Xbpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *t1, const int16_t *t2, +// const int w, const int h, +// const int16_t wt[2], const int bitdepth_max); +function sgr_weighted2_\bpc\()bpc_neon, export=1 + push {r4-r11,lr} + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] +.if \bpc == 8 + ldr r8, [sp, #52] +.else + ldrd r8, r9, [sp, #52] +.endif + cmp r7, #2 + add r10, r0, r1 + add r11, r2, r3 + add r12, r4, #2*FILTER_OUT_STRIDE + add lr, r5, #2*FILTER_OUT_STRIDE + vld2.16 {d30[], d31[]}, [r8] // wt[0], wt[1] +.if \bpc == 16 + vdup.16 q14, r9 +.endif + mov r8, #4*FILTER_OUT_STRIDE + lsl r1, r1, #1 + lsl r3, r3, #1 + add r9, r6, #7 + bic r9, r9, #7 // Aligned width +.if \bpc == 8 + sub r1, r1, r9 + sub r3, r3, r9 +.else + sub r1, r1, r9, lsl #1 + sub r3, r3, r9, lsl #1 +.endif + sub r8, r8, r9, lsl #1 + mov r9, r6 + blt 2f +1: +.if \bpc == 8 + vld1.8 {d0}, [r2, :64]! + vld1.8 {d16}, [r11, :64]! +.else + vld1.16 {q0}, [r2, :128]! + vld1.16 {q8}, [r11, :128]! +.endif + vld1.16 {q1}, [r4, :128]! + vld1.16 {q9}, [r12, :128]! + vld1.16 {q2}, [r5, :128]! + vld1.16 {q10}, [lr, :128]! + subs r6, r6, #8 +.if \bpc == 8 + vshll.u8 q0, d0, #4 // u + vshll.u8 q8, d16, #4 // u +.else + vshl.i16 q0, q0, #4 // u + vshl.i16 q8, q8, #4 // u +.endif + vsub.i16 q1, q1, q0 // t1 - u + vsub.i16 q2, q2, q0 // t2 - u + vsub.i16 q9, q9, q8 // t1 - u + vsub.i16 q10, q10, q8 // t2 - u + vshll.u16 q3, d0, #7 // u << 7 + vshll.u16 q0, d1, #7 // u << 7 + vshll.u16 q11, d16, #7 // u << 7 + vshll.u16 q8, d17, #7 // u << 7 + vmlal.s16 q3, d2, d30 // wt[0] * (t1 - u) + vmlal.s16 q3, d4, d31 // wt[1] * (t2 - u) + vmlal.s16 q0, d3, d30 // wt[0] * (t1 - u) + vmlal.s16 q0, d5, d31 // wt[1] * (t2 - u) + vmlal.s16 q11, d18, d30 // wt[0] * (t1 - u) + vmlal.s16 q11, d20, d31 // wt[1] * (t2 - u) + vmlal.s16 q8, d19, d30 // wt[0] * (t1 - u) + vmlal.s16 q8, d21, d31 // wt[1] * (t2 - u) +.if \bpc == 8 + vrshrn.i32 d6, q3, #11 + vrshrn.i32 d7, q0, #11 + vrshrn.i32 d22, q11, #11 + vrshrn.i32 d23, q8, #11 + vqmovun.s16 d6, q3 + vqmovun.s16 d22, q11 + vst1.8 {d6}, [r0, :64]! + vst1.8 {d22}, [r10, :64]! +.else + vqrshrun.s32 d6, q3, #11 + vqrshrun.s32 d7, q0, #11 + vqrshrun.s32 d22, q11, #11 + vqrshrun.s32 d23, q8, #11 + vmin.u16 q3, q3, q14 + vmin.u16 q11, q11, q14 + vst1.16 {q3}, [r0, :128]! + vst1.16 {q11}, [r10, :128]! +.endif + bgt 1b + + subs r7, r7, #2 + cmp r7, #1 + blt 0f + mov r6, r9 + add r0, r0, r1 + add r10, r10, r1 + add r2, r2, r3 + add r11, r11, r3 + add r4, r4, r8 + add r12, r12, r8 + add r5, r5, r8 + add lr, lr, r8 + beq 2f + b 1b + +2: +.if \bpc == 8 + vld1.8 {d0}, [r2, :64]! +.else + vld1.16 {q0}, [r2, :128]! +.endif + vld1.16 {q1}, [r4, :128]! + vld1.16 {q2}, [r5, :128]! + subs r6, r6, #8 +.if \bpc == 8 + vshll.u8 q0, d0, #4 // u +.else + vshl.i16 q0, q0, #4 // u +.endif + vsub.i16 q1, q1, q0 // t1 - u + vsub.i16 q2, q2, q0 // t2 - u + vshll.u16 q3, d0, #7 // u << 7 + vshll.u16 q0, d1, #7 // u << 7 + vmlal.s16 q3, d2, d30 // wt[0] * (t1 - u) + vmlal.s16 q3, d4, d31 // wt[1] * (t2 - u) + vmlal.s16 q0, d3, d30 // wt[0] * (t1 - u) + vmlal.s16 q0, d5, d31 // wt[1] * (t2 - u) +.if \bpc == 8 + vrshrn.i32 d6, q3, #11 + vrshrn.i32 d7, q0, #11 + vqmovun.s16 d6, q3 + vst1.8 {d6}, [r0, :64]! +.else + vqrshrun.s32 d6, q3, #11 + vqrshrun.s32 d7, q0, #11 + vmin.u16 q3, q3, q14 + vst1.16 {q3}, [r0, :128]! +.endif + bgt 1b +0: + pop {r4-r11,pc} +endfunc +.endm diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/mc.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/mc.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3340 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro avg dst0, dst1, t0, t1, t2, t3 + vld1.16 {\t0,\t1}, [r2, :128]! + vld1.16 {\t2,\t3}, [r3, :128]! + vadd.i16 \t0, \t0, \t2 + vadd.i16 \t1, \t1, \t3 + vqrshrun.s16 \dst0, \t0, #5 + vqrshrun.s16 \dst1, \t1, #5 +.endm + +.macro w_avg dst0, dst1, t0, t1, t2, t3 + vld1.16 {\t0,\t1}, [r2, :128]! + vld1.16 {\t2,\t3}, [r3, :128]! + vsub.i16 \t0, \t2, \t0 + vsub.i16 \t1, \t3, \t1 + vqdmulh.s16 \t0, \t0, q15 + vqdmulh.s16 \t1, \t1, q15 + vadd.i16 \t0, \t2, \t0 + vadd.i16 \t1, \t3, \t1 + vqrshrun.s16 \dst0, \t0, #4 + vqrshrun.s16 \dst1, \t1, #4 +.endm + +.macro mask dst0, dst1, t0, t1, t2, t3 + vld1.8 {q14}, [lr, :128]! + vld1.16 {\t0,\t1}, [r2, :128]! + vmul.i8 q14, q14, q15 + vld1.16 {\t2,\t3}, [r3, :128]! + vshll.i8 q13, d28, #8 + vshll.i8 q14, d29, #8 + vsub.i16 \t0, \t2, \t0 + vsub.i16 \t1, \t3, \t1 + vqdmulh.s16 \t0, \t0, q13 + vqdmulh.s16 \t1, \t1, q14 + vadd.i16 \t0, \t2, \t0 + vadd.i16 \t1, \t3, \t1 + vqrshrun.s16 \dst0, \t0, #4 + vqrshrun.s16 \dst1, \t1, #4 +.endm + +.macro bidir_fn type +function \type\()_8bpc_neon, export=1 + push {r4-r6,lr} + ldrd r4, r5, [sp, #16] + clz r4, r4 +.ifnc \type, avg + ldr lr, [sp, #24] +.endif +.ifc \type, w_avg + vdup.s16 q15, lr + vneg.s16 q15, q15 + vshl.i16 q15, q15, #11 +.endif +.ifc \type, mask + vmov.i8 q15, #256-2 +.endif + adr r12, L(\type\()_tbl) + sub r4, r4, #24 + ldr r4, [r12, r4, lsl #2] + \type d16, d17, q0, q1, q2, q3 + add r12, r12, r4 + bx r12 + + .align 2 +L(\type\()_tbl): + .word 1280f - L(\type\()_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_tbl) + CONFIG_THUMB + .word 4f - L(\type\()_tbl) + CONFIG_THUMB + +4: + add r6, r0, r1 + lsl r1, r1, #1 + cmp r5, #4 + vst1.32 {d16[0]}, [r0, :32], r1 + vst1.32 {d16[1]}, [r6, :32], r1 + vst1.32 {d17[0]}, [r0, :32], r1 + vst1.32 {d17[1]}, [r6, :32], r1 + beq 0f + \type d18, d19, q0, q1, q2, q3 + cmp r5, #8 + vst1.32 {d18[0]}, [r0, :32], r1 + vst1.32 {d18[1]}, [r6, :32], r1 + vst1.32 {d19[0]}, [r0, :32], r1 + vst1.32 {d19[1]}, [r6, :32], r1 + beq 0f + \type d16, d17, q0, q1, q2, q3 + vst1.32 {d16[0]}, [r0, :32], r1 + vst1.32 {d16[1]}, [r6, :32], r1 + \type d18, d19, q0, q1, q2, q3 + vst1.32 {d17[0]}, [r0, :32], r1 + vst1.32 {d17[1]}, [r6, :32], r1 + vst1.32 {d18[0]}, [r0, :32], r1 + vst1.32 {d18[1]}, [r6, :32], r1 + vst1.32 {d19[0]}, [r0, :32], r1 + vst1.32 {d19[1]}, [r6, :32], r1 + pop {r4-r6,pc} +80: + add r6, r0, r1 + lsl r1, r1, #1 +8: + vst1.8 {d16}, [r0, :64], r1 + \type d18, d19, q0, q1, q2, q3 + vst1.8 {d17}, [r6, :64], r1 + vst1.8 {d18}, [r0, :64], r1 + subs r5, r5, #4 + vst1.8 {d19}, [r6, :64], r1 + ble 0f + \type d16, d17, q0, q1, q2, q3 + b 8b +160: + add r6, r0, r1 + lsl r1, r1, #1 +16: + \type d18, d19, q0, q1, q2, q3 + vst1.8 {q8}, [r0, :128], r1 + \type d20, d21, q0, q1, q2, q3 + vst1.8 {q9}, [r6, :128], r1 + \type d22, d23, q0, q1, q2, q3 + vst1.8 {q10}, [r0, :128], r1 + subs r5, r5, #4 + vst1.8 {q11}, [r6, :128], r1 + ble 0f + \type d16, d17, q0, q1, q2, q3 + b 16b +320: + add r6, r0, r1 + lsl r1, r1, #1 +32: + \type d18, d19, q0, q1, q2, q3 + \type d20, d21, q0, q1, q2, q3 + vst1.8 {q8, q9}, [r0, :128], r1 + \type d22, d23, q0, q1, q2, q3 + subs r5, r5, #2 + vst1.8 {q10, q11}, [r6, :128], r1 + ble 0f + \type d16, d17, q0, q1, q2, q3 + b 32b +640: + add r6, r0, #32 +64: + \type d18, d19, q0, q1, q2, q3 + \type d20, d21, q0, q1, q2, q3 + \type d22, d23, q0, q1, q2, q3 + vst1.8 {q8, q9}, [r0, :128], r1 + \type d16, d17, q0, q1, q2, q3 + vst1.8 {q10, q11}, [r6, :128], r1 + \type d18, d19, q0, q1, q2, q3 + \type d20, d21, q0, q1, q2, q3 + vst1.8 {q8, q9}, [r0, :128], r1 + \type d22, d23, q0, q1, q2, q3 + subs r5, r5, #2 + vst1.8 {q10, q11}, [r6, :128], r1 + ble 0f + \type d16, d17, q0, q1, q2, q3 + b 64b +1280: + sub r1, r1, #32 + add r6, r0, #64 +128: + \type d18, d19, q0, q1, q2, q3 + \type d20, d21, q0, q1, q2, q3 + \type d22, d23, q0, q1, q2, q3 + vst1.8 {q8, q9}, [r0, :128]! + \type d16, d17, q0, q1, q2, q3 + vst1.8 {q10, q11}, [r0, :128], r1 + \type d18, d19, q0, q1, q2, q3 + \type d20, d21, q0, q1, q2, q3 + vst1.8 {q8, q9}, [r6, :128]! + \type d22, d23, q0, q1, q2, q3 + subs r5, r5, #1 + vst1.8 {q10, q11}, [r6, :128], r1 + ble 0f + \type d16, d17, q0, q1, q2, q3 + b 128b + +0: + pop {r4-r6,pc} +endfunc +.endm + +bidir_fn avg +bidir_fn w_avg +bidir_fn mask + + +.macro w_mask_fn type +function w_mask_\type\()_8bpc_neon, export=1 + push {r4-r9,lr} + ldrd r4, r5, [sp, #28] + ldrd r6, r7, [sp, #36] + clz r8, r4 + adr r9, L(w_mask_\type\()_tbl) + sub r8, r8, #24 + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + movw r12, #6903 + vdup.16 q14, r12 +.if \type == 444 + vmov.i8 q15, #64 +.elseif \type == 422 + vdup.8 d0, r7 // d0[] <- sign + vmov.i8 d30, #129 + vsub.i8 d30, d30, d0 // 129 - sign +.elseif \type == 420 + vdup.16 q0, r7 // d0[] <- sign + vmov.i16 q15, #256 + vsub.i16 q15, q15, q0 // 256 - sign +.endif + add r12, r0, r1 + lsl r1, r1, #1 + bx r9 + + .align 2 +L(w_mask_\type\()_tbl): + .word 1280f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + .word 640f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + .word 320f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + .word 160f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + .word 8f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + .word 4f - L(w_mask_\type\()_tbl) + CONFIG_THUMB + +4: + vld1.16 {d0, d1, d2, d3}, [r2, :128]! // tmp1 (four rows at once) + vld1.16 {d4, d5, d6, d7}, [r3, :128]! // tmp2 (four rows at once) + subs r5, r5, #4 + vsub.i16 q8, q2, q0 // tmp2-tmp1 + vsub.i16 q9, q3, q1 + vabd.s16 q10, q0, q2 // (abs(tmp1[x] - tmp2[x])) + vabd.s16 q11, q1, q3 + vqsub.u16 q10, q14, q10 // 6903 - abs () + vqsub.u16 q11, q14, q11 + vshr.s16 q10, q10, #8 // 64-m = (6903 - abs()) >> 8 + vshr.s16 q11, q11, #8 + vshl.s16 q12, q10, #9 // (64-m)<<9 + vshl.s16 q13, q11, #9 + vqdmulh.s16 q12, q12, q8 // ((tmp2-tmp1)*(64-m)<<9)>>15 + vqdmulh.s16 q13, q13, q9 + vadd.i16 q12, q12, q0 // (((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1 + vadd.i16 q13, q13, q1 + vqrshrun.s16 d24, q12, #4 // (((((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1) + 8) >> 4 + vqrshrun.s16 d25, q13, #4 +.if \type == 444 + vmovn.u16 d20, q10 // 64 - m + vmovn.u16 d21, q11 + vsub.i8 q10, q15, q10 // m + vst1.8 {d20, d21}, [r6, :128]! +.elseif \type == 422 + vpadd.s16 d20, d20, d21 // (64 - m) + (64 - n) (column wise addition) + vpadd.s16 d21, d22, d23 + vmovn.s16 d6, q10 + vhsub.u8 d6, d30, d6 // ((129 - sign) - ((64 - m) + (64 - n))) >> 1 + vst1.8 {d6}, [r6, :64]! +.elseif \type == 420 + vadd.s16 d20, d20, d21 // (64 - my1) + (64 - my2) (row wise addition) + vadd.s16 d21, d22, d23 + vpadd.s16 d20, d20, d21 // (128 - m) + (128 - n) (column wise addition) + vsub.s16 d20, d30, d20 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.u16 d20, q10, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.32 {d20[0]}, [r6, :32]! +.endif + vst1.32 {d24[0]}, [r0, :32], r1 + vst1.32 {d24[1]}, [r12, :32], r1 + vst1.32 {d25[0]}, [r0, :32], r1 + vst1.32 {d25[1]}, [r12, :32], r1 + bgt 4b + pop {r4-r9,pc} +8: + vld1.16 {d0, d1, d2, d3}, [r2, :128]! // tmp1y1, tmp1y2 + vld1.16 {d4, d5, d6, d7}, [r3, :128]! // tmp2y1, tmp2y2 + subs r5, r5, #2 + vsub.i16 q8, q2, q0 // tmp2y1 - tmp1y1 + vsub.i16 q9, q3, q1 // tmp2y2 - tmp1y2 + vabd.s16 q10, q0, q2 // abs(tmp1y1 - tmp2y1) + vabd.s16 q11, q1, q3 // abs(tmp1y2 - tmp2y2) + vqsub.u16 q10, q14, q10 // 6903 - abs(tmp1y1 - tmp2y1) + vqsub.u16 q11, q14, q11 // 6903 - abs(tmp1y2 - tmp2y2) + vshr.s16 q10, q10, #8 // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8 + vshr.s16 q11, q11, #8 // 64 - my2 = 6903 - abs(tmp1y2 - tmp2y2) >> 8 + vshl.s16 q12, q10, #9 // (64 - my1) << 9 + vshl.s16 q13, q11, #9 // (64 - my2) << 9 + vqdmulh.s16 q12, q12, q8 // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15 + vqdmulh.s16 q13, q13, q9 // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15 + vadd.s16 q12, q12, q0 // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1 + vadd.s16 q13, q13, q1 // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2 + vqrshrun.s16 d24, q12, #4 // (((((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4 + vqrshrun.s16 d25, q13, #4 // (((((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4 +.if \type == 444 + vmovn.u16 d20, q10 // 64 - m + vmovn.u16 d21, q11 + vsub.i8 q10, q15, q10 // m + vst1.8 {d20, d21}, [r6, :128]! +.elseif \type == 422 + vpadd.s16 d20, d20, d21 // (64 - my1) + (64 - ny1) (column wise addition) + vpadd.s16 d21, d22, d23 // (64 - my2) + (64 - ny2) + vmovn.s16 d20, q10 + vhsub.u8 d20, d30, d20 // ((129 - sign) - ((64 - my1/y2) + (64 - ny1/y2))) >> 1 + vst1.8 {d20}, [r6, :64]! +.elseif \type == 420 + vadd.s16 q10, q10, q11 // (64 - my1) + (64 - my2) (row wise addition) + vpadd.s16 d20, d20, d21 // (128 - m) + (128 - n) (column wise addition) + vsub.s16 d20, d30, d20 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.u16 d20, q10, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.32 {d20[0]}, [r6, :32]! +.endif + vst1.16 {d24}, [r0, :64], r1 + vst1.16 {d25}, [r12, :64], r1 + bgt 8b + pop {r4-r9,pc} +1280: +640: +320: +160: + sub r1, r1, r4 +.if \type == 444 + add lr, r6, r4 +.elseif \type == 422 + add lr, r6, r4, lsr #1 +.endif + add r9, r3, r4, lsl #1 + add r7, r2, r4, lsl #1 +161: + mov r8, r4 +16: + vld1.16 {d0, d1, d2, d3}, [r2, :128]! // tmp1y1 + vld1.16 {d4, d5, d6, d7}, [r3, :128]! // tmp2y1 + vld1.16 {d16, d17, d18, d19}, [r7, :128]! // tmp1y2 + subs r8, r8, #16 + vsub.i16 q2, q2, q0 // tmp2y1 - tmp1y1 + vsub.i16 q3, q3, q1 + vabs.s16 q10, q2 // abs(tm2y1 - tmp1y1) + vabs.s16 q11, q3 + vqsub.u16 q10, q14, q10 // 6903 - abs(tmp1y1 - tmp2y1) + vqsub.u16 q11, q14, q11 + vshr.s16 q10, q10, #8 // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8 + vshr.s16 q11, q11, #8 + vshl.s16 q12, q10, #9 // (64 - my1) << 9 + vshl.s16 q13, q11, #9 + vqdmulh.s16 q12, q12, q2 // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15 + vqdmulh.s16 q13, q13, q3 + vadd.i16 q12, q12, q0 // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1 + vadd.i16 q13, q13, q1 + vld1.16 {d0, d1, d2, d3}, [r9, :128]! // tmp2h2 +.if \type == 444 + vmovn.u16 d20, q10 // 64 - my1 + vmovn.u16 d21, q11 + vsub.i8 q10, q15, q10 // my1 + vst1.8 {d20, d21}, [r6, :128]! +.elseif \type == 422 + vpadd.s16 d20, d20, d21 // (64 - my1) + (64 - ny1) (column wise addition) + vpadd.s16 d21, d22, d23 + vmovn.s16 d20, q10 + vhsub.u8 d20, d30, d20 // ((129 - sign) - ((64 - my1) + (64 - ny1))) >> 1 + vst1.8 {d20}, [r6, :64]! +.endif + vqrshrun.s16 d24, q12, #4 // (((((tmp2y1 - tmp1y1)*(64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4 + vqrshrun.s16 d25, q13, #4 + vsub.i16 q0, q0, q8 // tmp2y2 - tmp1y2 + vsub.i16 q1, q1, q9 + vst1.16 {d24, d25}, [r0, :128]! // store dsty1 + vabs.s16 q2, q0 // abs(tmp2y2 - tmp1y2) + vabs.s16 q3, q1 + vqsub.u16 q2, q14, q2 // 6903 - abs(tmp2y2 - tmp1y2) + vqsub.u16 q3, q14, q3 + vshr.s16 q2, q2, #8 // (6903 - abs(tmp2y2 - tmp1y2)) >> 8 + vshr.s16 q3, q3, #8 + vshl.s16 q12, q2, #9 // (64 - my2) << 9 + vshl.s16 q13, q3, #9 +.if \type == 444 + vmovn.u16 d4, q2 // 64 - my2 + vmovn.u16 d5, q3 + vsub.i8 q2, q15, q2 // my2 + vst1.8 {d4, d5}, [lr, :128]! +.elseif \type == 422 + vpadd.s16 d4, d4, d5 // (64 - my2) + (64 - ny2) (column wise addition) + vpadd.s16 d5, d6, d7 + vmovn.s16 d4, q2 + vhsub.u8 d4, d30, d4 // ((129 - sign) - ((64 - my2) + (64 - ny2))) >> 1 + vst1.8 {d4}, [lr, :64]! +.elseif \type == 420 + vadd.s16 q10, q10, q2 // (64 - my1) + (64 - my2) (row wise addition) + vadd.s16 q11, q11, q3 + vpadd.s16 d20, d20, d21 // (128 - m) + (128 - n) (column wise addition) + vpadd.s16 d21, d22, d23 + vsub.s16 q10, q15, q10 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.u16 d20, q10, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.8 {d20}, [r6, :64]! +.endif + vqdmulh.s16 q12, q12, q0 // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15 + vqdmulh.s16 q13, q13, q1 + vadd.i16 q12, q12, q8 // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2 + vadd.i16 q13, q13, q9 + vqrshrun.s16 d24, q12, #4 // (((((tmp2y2 - tmp1y2)*(64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4 + vqrshrun.s16 d25, q13, #4 + vst1.16 {d24, d25}, [r12, :128]! // store dsty2 + bgt 16b + subs r5, r5, #2 + add r2, r2, r4, lsl #1 + add r3, r3, r4, lsl #1 + add r7, r7, r4, lsl #1 + add r9, r9, r4, lsl #1 +.if \type == 444 + add r6, r6, r4 + add lr, lr, r4 +.elseif \type == 422 + add r6, r6, r4, lsr #1 + add lr, lr, r4, lsr #1 +.endif + add r0, r0, r1 + add r12, r12, r1 + bgt 161b + pop {r4-r9,pc} +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + + +function blend_8bpc_neon, export=1 + push {r4-r5,lr} + ldrd r4, r5, [sp, #12] + clz lr, r3 + adr r3, L(blend_tbl) + sub lr, lr, #26 + ldr lr, [r3, lr, lsl #2] + add r3, r3, lr + bx r3 + + .align 2 +L(blend_tbl): + .word 320f - L(blend_tbl) + CONFIG_THUMB + .word 160f - L(blend_tbl) + CONFIG_THUMB + .word 80f - L(blend_tbl) + CONFIG_THUMB + .word 40f - L(blend_tbl) + CONFIG_THUMB + +40: + vmov.i8 d22, #64 + add r12, r0, r1 + lsl r1, r1, #1 +4: + vld1.u8 {d2}, [r5, :64]! + vld1.u8 {d1}, [r2, :64]! + vld1.32 {d0[]}, [r0, :32] + subs r4, r4, #2 + vld1.32 {d0[1]}, [r12, :32] + vsub.i8 d3, d22, d2 + vmull.u8 q8, d1, d2 + vmlal.u8 q8, d0, d3 + vrshrn.i16 d20, q8, #6 + vst1.32 {d20[0]}, [r0, :32], r1 + vst1.32 {d20[1]}, [r12, :32], r1 + bgt 4b + pop {r4-r5,pc} +80: + vmov.i8 d16, #64 + add r12, r0, r1 + lsl r1, r1, #1 +8: + vld1.u8 {q1}, [r5, :128]! + vld1.u8 {q2}, [r2, :128]! + vld1.u8 {d0}, [r0, :64] + vsub.i8 d17, d16, d2 + vld1.u8 {d1}, [r12, :64] + subs r4, r4, #2 + vsub.i8 d18, d16, d3 + vmull.u8 q3, d2, d4 + vmlal.u8 q3, d0, d17 + vmull.u8 q10, d3, d5 + vmlal.u8 q10, d1, d18 + vrshrn.i16 d22, q3, #6 + vrshrn.i16 d23, q10, #6 + vst1.u8 {d22}, [r0, :64], r1 + vst1.u8 {d23}, [r12, :64], r1 + bgt 8b + pop {r4-r5,pc} +160: + vmov.i8 q12, #64 + add r12, r0, r1 + lsl r1, r1, #1 +16: + vld1.u8 {q1, q2}, [r5, :128]! + vld1.u8 {q8, q9}, [r2, :128]! + vld1.u8 {q0}, [r0, :128] + subs r4, r4, #2 + vsub.i8 q15, q12, q1 + vld1.u8 {q13}, [r12, :128] + vmull.u8 q3, d16, d2 + vmlal.u8 q3, d0, d30 + vmull.u8 q14, d17, d3 + vmlal.u8 q14, d1, d31 + vsub.i8 q15, q12, q2 + vrshrn.i16 d20, q3, #6 + vrshrn.i16 d21, q14, #6 + vmull.u8 q3, d18, d4 + vmlal.u8 q3, d26, d30 + vmull.u8 q14, d19, d5 + vmlal.u8 q14, d27, d31 + vrshrn.i16 d22, q3, #6 + vrshrn.i16 d23, q14, #6 + vst1.u8 {q10}, [r0, :128], r1 + vst1.u8 {q11}, [r12, :128], r1 + bgt 16b + pop {r4-r5,pc} +320: + vmov.i8 q10, #64 +32: + vld1.u8 {q2, q3}, [r5, :128]! + vld1.u8 {q8, q9}, [r2, :128]! + vld1.u8 {q0, q1}, [r0, :128] + subs r4, r4, #1 + vsub.i8 q11, q10, q2 + vmull.u8 q15, d16, d4 + vmlal.u8 q15, d0, d22 + vmull.u8 q14, d17, d5 + vmlal.u8 q14, d1, d23 + vsub.i8 q11, q10, q3 + vrshrn.i16 d24, q15, #6 + vrshrn.i16 d25, q14, #6 + vmull.u8 q15, d18, d6 + vmlal.u8 q15, d2, d22 + vmull.u8 q14, d19, d7 + vmlal.u8 q14, d3, d23 + vrshrn.i16 d26, q15, #6 + vrshrn.i16 d27, q14, #6 + vst1.u8 {q12, q13}, [r0, :128], r1 + bgt 32b + pop {r4-r5,pc} +endfunc + +function blend_h_8bpc_neon, export=1 + push {r4-r5,lr} + ldr r4, [sp, #12] + movrel r5, X(obmc_masks) + add r5, r5, r4 + sub r4, r4, r4, lsr #2 + clz lr, r3 + adr r12, L(blend_h_tbl) + sub lr, lr, #24 + ldr lr, [r12, lr, lsl #2] + add r12, r12, lr + bx r12 + + .align 2 +L(blend_h_tbl): + .word 1280f - L(blend_h_tbl) + CONFIG_THUMB + .word 640f - L(blend_h_tbl) + CONFIG_THUMB + .word 320f - L(blend_h_tbl) + CONFIG_THUMB + .word 160f - L(blend_h_tbl) + CONFIG_THUMB + .word 80f - L(blend_h_tbl) + CONFIG_THUMB + .word 40f - L(blend_h_tbl) + CONFIG_THUMB + .word 20f - L(blend_h_tbl) + CONFIG_THUMB + +20: + vmov.i8 d22, #64 + add r12, r0, r1 + lsl r1, r1, #1 +2: + vld1.16 {d2[], d3[]}, [r5, :16]! + vld1.32 {d1[]}, [r2, :32]! + subs r4, r4, #2 + vld1.16 {d0[]}, [r0, :16] + vzip.8 d2, d3 + vsub.i8 d4, d22, d2 + vld1.16 {d0[1]}, [r12, :16] + vmull.u8 q8, d1, d2 + vmlal.u8 q8, d0, d4 + vrshrn.i16 d20, q8, #6 + vst1.16 {d20[0]}, [r0, :16], r1 + vst1.16 {d20[1]}, [r12, :16], r1 + bgt 2b + pop {r4-r5,pc} +40: + vmov.i8 d22, #64 + add r12, r0, r1 + lsl r1, r1, #1 +4: + vld2.u8 {d2[], d3[]}, [r5, :16]! + vld1.u8 {d1}, [r2, :64]! + subs r4, r4, #2 + vext.u8 d2, d2, d3, #4 + vld1.32 {d0[]}, [r0, :32] + vsub.i8 d6, d22, d2 + vld1.32 {d0[1]}, [r12, :32] + vmull.u8 q8, d1, d2 + vmlal.u8 q8, d0, d6 + vrshrn.i16 d20, q8, #6 + vst1.32 {d20[0]}, [r0, :32], r1 + vst1.32 {d20[1]}, [r12, :32], r1 + bgt 4b + pop {r4-r5,pc} +80: + vmov.i8 q8, #64 + add r12, r0, r1 + lsl r1, r1, #1 +8: + vld2.u8 {d2[], d3[]}, [r5, :16]! + vld1.u8 {d4, d5}, [r2, :128]! + vld1.u8 {d0}, [r0, :64] + vsub.i8 q9, q8, q1 + vld1.u8 {d1}, [r12, :64] + subs r4, r4, #2 + vmull.u8 q3, d2, d4 + vmlal.u8 q3, d0, d18 + vmull.u8 q10, d3, d5 + vmlal.u8 q10, d1, d19 + vrshrn.i16 d22, q3, #6 + vrshrn.i16 d23, q10, #6 + vst1.u8 {d22}, [r0, :64], r1 + vst1.u8 {d23}, [r12, :64], r1 + bgt 8b + pop {r4-r5,pc} +160: + vmov.i8 q12, #64 + add r12, r0, r1 + lsl r1, r1, #1 +16: + vld2.u8 {d28[], d29[]}, [r5, :16]! + vld1.u8 {d2, d3, d4, d5}, [r2, :128]! + vsub.i8 q15, q12, q14 + vld1.u8 {q0}, [r0, :128] + subs r4, r4, #2 + vld1.u8 {q13}, [r12, :128] + vmull.u8 q3, d2, d28 + vmlal.u8 q3, d0, d30 + vmull.u8 q8, d3, d28 + vmlal.u8 q8, d1, d30 + vrshrn.i16 d18, q3, #6 + vrshrn.i16 d19, q8, #6 + vmull.u8 q3, d4, d29 + vmlal.u8 q3, d26, d31 + vmull.u8 q8, d5, d29 + vmlal.u8 q8, d27, d31 + vrshrn.i16 d20, q3, #6 + vrshrn.i16 d21, q8, #6 + vst1.u8 {q9}, [r0, :128], r1 + vst1.u8 {q10}, [r12, :128], r1 + bgt 16b + pop {r4-r5,pc} +320: +640: +1280: + vmov.i8 d20, #64 + sub r1, r1, r3 +321: + vld1.u8 {d6[]}, [r5]! + vsub.i8 d7, d20, d6 + mov r12, r3 +32: + vld1.u8 {q8, q9}, [r2, :128]! + vld1.u8 {q0, q1}, [r0, :128] + vmull.u8 q15, d16, d6 + vmlal.u8 q15, d0, d7 + vmull.u8 q14, d17, d6 + vmlal.u8 q14, d1, d7 + vrshrn.i16 d0, q15, #6 + vrshrn.i16 d1, q14, #6 + vmull.u8 q15, d18, d6 + vmlal.u8 q15, d2, d7 + vmull.u8 q14, d19, d6 + vmlal.u8 q14, d3, d7 + vrshrn.i16 d2, q15, #6 + vrshrn.i16 d3, q14, #6 + subs r12, r12, #32 + vst1.u8 {q0, q1}, [r0, :128]! + bgt 32b + add r0, r0, r1 + subs r4, r4, #1 + bgt 321b + pop {r4-r5,pc} +endfunc + +function blend_v_8bpc_neon, export=1 + push {r4,lr} + ldr r4, [sp, #8] + movrel lr, X(obmc_masks) + add lr, lr, r3 + clz r12, r3 + adr r3, L(blend_v_tbl) + sub r12, r12, #26 + ldr r12, [r3, r12, lsl #2] + add r3, r3, r12 + bx r3 + + .align 2 +L(blend_v_tbl): + .word 320f - L(blend_v_tbl) + CONFIG_THUMB + .word 160f - L(blend_v_tbl) + CONFIG_THUMB + .word 80f - L(blend_v_tbl) + CONFIG_THUMB + .word 40f - L(blend_v_tbl) + CONFIG_THUMB + .word 20f - L(blend_v_tbl) + CONFIG_THUMB + +20: + vmov.i8 d22, #64 + vld1.8 {d2[]}, [lr] + add r12, r0, r1 + lsl r1, r1, #1 + vsub.i8 d3, d22, d2 +2: + vld1.16 {d1[0]}, [r2, :16]! + vld1.8 {d0[]}, [r0] + subs r4, r4, #2 + vld1.8 {d1[1]}, [r2] + vld1.8 {d0[1]}, [r12] + vmull.u8 q2, d1, d2 + vmlal.u8 q2, d0, d3 + vrshrn.i16 d6, q2, #6 + add r2, r2, #2 + vst1.8 {d6[0]}, [r0], r1 + vst1.8 {d6[1]}, [r12], r1 + bgt 2b + pop {r4,pc} +40: + vmov.i8 d22, #64 + vld1.32 {d4[]}, [lr, :32] + add r12, r0, r1 + lsl r1, r1, #1 + vsub.i8 d5, d22, d4 + sub r1, r1, #2 +4: + vld1.u8 {d2}, [r2, :64]! + vld1.32 {d0[]}, [r0, :32] + vld1.32 {d0[1]}, [r12, :32] + subs r4, r4, #2 + vmull.u8 q3, d2, d4 + vmlal.u8 q3, d0, d5 + vrshrn.i16 d20, q3, #6 + vst1.16 {d20[0]}, [r0, :16]! + vst1.16 {d20[2]}, [r12, :16]! + vst1.8 {d20[2]}, [r0], r1 + vst1.8 {d20[6]}, [r12], r1 + bgt 4b + pop {r4,pc} +80: + vmov.i8 d16, #64 + vld1.u8 {d2}, [lr, :64] + add r12, r0, r1 + lsl r1, r1, #1 + vsub.i8 d17, d16, d2 + sub r1, r1, #4 +8: + vld1.u8 {d4, d5}, [r2, :128]! + vld1.u8 {d0}, [r0, :64] + vld1.u8 {d1}, [r12, :64] + subs r4, r4, #2 + vmull.u8 q3, d2, d4 + vmlal.u8 q3, d0, d17 + vmull.u8 q10, d2, d5 + vmlal.u8 q10, d1, d17 + vrshrn.i16 d22, q3, #6 + vrshrn.i16 d23, q10, #6 + vst1.32 {d22[0]}, [r0, :32]! + vst1.32 {d23[0]}, [r12, :32]! + vst1.16 {d22[2]}, [r0, :16], r1 + vst1.16 {d23[2]}, [r12, :16], r1 + bgt 8b + pop {r4,pc} +160: + vmov.i8 q12, #64 + vld1.u8 {q14}, [lr, :128] + add r12, r0, r1 + lsl r1, r1, #1 + vsub.i8 q11, q12, q14 + sub r1, r1, #8 +16: + vld1.u8 {q1, q2}, [r2, :128]! + vld1.u8 {q0}, [r0, :128] + subs r4, r4, #2 + vld1.u8 {q13}, [r12, :128] + vmull.u8 q3, d2, d28 + vmlal.u8 q3, d0, d22 + vmull.u8 q8, d3, d29 + vmlal.u8 q8, d1, d23 + vrshrn.i16 d18, q3, #6 + vrshrn.i16 d19, q8, #6 + vmull.u8 q3, d4, d28 + vmlal.u8 q3, d26, d22 + vmull.u8 q8, d5, d29 + vmlal.u8 q8, d27, d23 + vrshrn.i16 d20, q3, #6 + vrshrn.i16 d21, q8, #6 + vst1.u8 {d18}, [r0, :64]! + vst1.u8 {d20}, [r12, :64]! + vst1.32 {d19[0]}, [r0, :32], r1 + vst1.32 {d21[0]}, [r12, :32], r1 + bgt 16b + pop {r4,pc} +320: + vmov.i8 q10, #64 + vld1.u8 {q2, q3}, [lr, :128] + vsub.i8 q11, q10, q2 + vsub.i8 d24, d20, d6 +32: + vld1.u8 {q8, q9}, [r2, :128]! + vld1.u8 {d0, d1, d2}, [r0, :64] + subs r4, r4, #1 + vmull.u8 q15, d16, d4 + vmlal.u8 q15, d0, d22 + vmull.u8 q14, d17, d5 + vmlal.u8 q14, d1, d23 + vrshrn.i16 d0, q15, #6 + vrshrn.i16 d1, q14, #6 + vmull.u8 q15, d18, d6 + vmlal.u8 q15, d2, d24 + vrshrn.i16 d2, q15, #6 + vst1.u8 {d0, d1, d2}, [r0, :64], r1 + bgt 32b + pop {r4,pc} +endfunc + + +// This has got the same signature as the put_8tap functions, +// assumes that the caller has loaded the h argument into r5, +// and assumes that r8 is set to (clz(w)-24). +function put_neon + adr r9, L(put_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(put_tbl): + .word 1280f - L(put_tbl) + CONFIG_THUMB + .word 640f - L(put_tbl) + CONFIG_THUMB + .word 32f - L(put_tbl) + CONFIG_THUMB + .word 160f - L(put_tbl) + CONFIG_THUMB + .word 8f - L(put_tbl) + CONFIG_THUMB + .word 4f - L(put_tbl) + CONFIG_THUMB + .word 2f - L(put_tbl) + CONFIG_THUMB + +2: + vld1.16 {d0[]}, [r2], r3 + vld1.16 {d1[]}, [r2], r3 + subs r5, r5, #2 + vst1.16 {d0[0]}, [r0, :16], r1 + vst1.16 {d1[0]}, [r0, :16], r1 + bgt 2b + pop {r4-r11,pc} +4: + vld1.32 {d0[]}, [r2], r3 + vld1.32 {d1[]}, [r2], r3 + subs r5, r5, #2 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d1[0]}, [r0, :32], r1 + bgt 4b + pop {r4-r11,pc} +8: + vld1.8 {d0}, [r2], r3 + vld1.8 {d1}, [r2], r3 + subs r5, r5, #2 + vst1.8 {d0}, [r0, :64], r1 + vst1.8 {d1}, [r0, :64], r1 + bgt 8b + pop {r4-r11,pc} +160: + add r8, r0, r1 + lsl r1, r1, #1 + add r9, r2, r3 + lsl r3, r3, #1 +16: + vld1.8 {q0}, [r2], r3 + vld1.8 {q1}, [r9], r3 + subs r5, r5, #2 + vst1.8 {q0}, [r0, :128], r1 + vst1.8 {q1}, [r8, :128], r1 + bgt 16b + pop {r4-r11,pc} +32: + vld1.8 {q0, q1}, [r2], r3 + subs r5, r5, #1 + vst1.8 {q0, q1}, [r0, :128], r1 + bgt 32b + pop {r4-r11,pc} +640: + sub r1, r1, #32 + sub r3, r3, #32 +64: + vld1.8 {q0, q1}, [r2]! + vst1.8 {q0, q1}, [r0, :128]! + vld1.8 {q2, q3}, [r2], r3 + subs r5, r5, #1 + vst1.8 {q2, q3}, [r0, :128], r1 + bgt 64b + pop {r4-r11,pc} +1280: + sub r1, r1, #96 + sub r3, r3, #96 +128: + vld1.8 {q8, q9}, [r2]! + vst1.8 {q8, q9}, [r0, :128]! + vld1.8 {q10, q11}, [r2]! + vst1.8 {q10, q11}, [r0, :128]! + vld1.8 {q12, q13}, [r2]! + vst1.8 {q12, q13}, [r0, :128]! + vld1.8 {q14, q15}, [r2], r3 + subs r5, r5, #1 + vst1.8 {q14, q15}, [r0, :128], r1 + bgt 128b + pop {r4-r11,pc} +endfunc + + +// This has got the same signature as the put_8tap functions, +// assumes that the caller has loaded the h argument into r4, +// and assumes that r8 is set to (clz(w)-24), and r7 to w*2. +function prep_neon + adr r9, L(prep_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(prep_tbl): + .word 1280f - L(prep_tbl) + CONFIG_THUMB + .word 640f - L(prep_tbl) + CONFIG_THUMB + .word 320f - L(prep_tbl) + CONFIG_THUMB + .word 160f - L(prep_tbl) + CONFIG_THUMB + .word 8f - L(prep_tbl) + CONFIG_THUMB + .word 4f - L(prep_tbl) + CONFIG_THUMB + +4: + vld1.32 {d0[]}, [r1], r2 + vld1.32 {d2[]}, [r1], r2 + subs r4, r4, #2 + vshll.u8 q0, d0, #4 + vshll.u8 q1, d2, #4 + vst1.16 {d1, d2}, [r0, :64]! + bgt 4b + pop {r4-r11,pc} +8: + vld1.8 {d0}, [r1], r2 + vld1.8 {d2}, [r1], r2 + subs r4, r4, #2 + vshll.u8 q0, d0, #4 + vshll.u8 q1, d2, #4 + vst1.16 {q0, q1}, [r0, :128]! + bgt 8b + pop {r4-r11,pc} +160: + add r9, r1, r2 + lsl r2, r2, #1 + add r8, r0, r7 + lsl r7, r7, #1 +16: + vld1.8 {q2}, [r1], r2 + vld1.8 {q3}, [r9], r2 + subs r4, r4, #2 + vshll.u8 q0, d4, #4 + vshll.u8 q1, d5, #4 + vshll.u8 q2, d6, #4 + vshll.u8 q3, d7, #4 + vst1.16 {q0, q1}, [r0, :128], r7 + vst1.16 {q2, q3}, [r8, :128], r7 + bgt 16b + pop {r4-r11,pc} +320: + add r8, r0, r3 +32: + vld1.8 {q0, q1}, [r1], r2 + subs r4, r4, #2 + vshll.u8 q8, d0, #4 + vshll.u8 q9, d1, #4 + vld1.8 {q2, q3}, [r1], r2 + vshll.u8 q10, d2, #4 + vshll.u8 q11, d3, #4 + vshll.u8 q12, d4, #4 + vst1.16 {q8, q9}, [r0, :128], r7 + vshll.u8 q13, d5, #4 + vst1.16 {q10, q11}, [r8, :128], r7 + vshll.u8 q14, d6, #4 + vst1.16 {q12, q13}, [r0, :128], r7 + vshll.u8 q15, d7, #4 + vst1.16 {q14, q15}, [r8, :128], r7 + bgt 32b + pop {r4-r11,pc} +640: + sub r2, r2, #32 + add r8, r0, #32 + mov r6, #64 +64: + vld1.8 {q0, q1}, [r1]! + subs r4, r4, #1 + vshll.u8 q8, d0, #4 + vshll.u8 q9, d1, #4 + vld1.8 {q2, q3}, [r1], r2 + vshll.u8 q10, d2, #4 + vshll.u8 q11, d3, #4 + vshll.u8 q12, d4, #4 + vst1.16 {q8, q9}, [r0, :128], r6 + vshll.u8 q13, d5, #4 + vshll.u8 q14, d6, #4 + vst1.16 {q10, q11}, [r8, :128], r6 + vshll.u8 q15, d7, #4 + vst1.16 {q12, q13}, [r0, :128], r6 + vst1.16 {q14, q15}, [r8, :128], r6 + bgt 64b + pop {r4-r11,pc} +1280: + sub r2, r2, #96 + add r8, r0, #32 + mov r6, #64 +128: + vld1.8 {q0, q1}, [r1]! + vld1.8 {q2, q3}, [r1]! + vshll.u8 q10, d0, #4 + vshll.u8 q11, d1, #4 + vshll.u8 q12, d2, #4 + vshll.u8 q13, d3, #4 + vshll.u8 q14, d4, #4 + vshll.u8 q15, d5, #4 + vld1.8 {q8, q9}, [r1]! + vst1.16 {q10, q11}, [r0, :128], r6 + vst1.16 {q12, q13}, [r8, :128], r6 + vshll.u8 q0, d6, #4 + vshll.u8 q1, d7, #4 + vshll.u8 q2, d16, #4 + vshll.u8 q3, d17, #4 + vshll.u8 q8, d18, #4 + vshll.u8 q9, d19, #4 + vld1.8 {q10, q11}, [r1], r2 + vst1.16 {q14, q15}, [r0, :128], r6 + vst1.16 {q0, q1}, [r8, :128], r6 + vshll.u8 q12, d20, #4 + vshll.u8 q13, d21, #4 + vshll.u8 q14, d22, #4 + vshll.u8 q15, d23, #4 + subs r4, r4, #1 + vst1.16 {q2, q3}, [r0, :128], r6 + vst1.16 {q8, q9}, [r8, :128], r6 + vst1.16 {q12, q13}, [r0, :128], r6 + vst1.16 {q14, q15}, [r8, :128], r6 + bgt 128b + pop {r4-r11,pc} +endfunc + + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + vld1.\wd {\d0[]}, [\s0], \strd + vld1.\wd {\d1[]}, [\s1], \strd +.ifnb \d2 + vld1.\wd {\d2[]}, [\s0], \strd + vld1.\wd {\d3[]}, [\s1], \strd +.endif +.ifnb \d4 + vld1.\wd {\d4[]}, [\s0], \strd +.endif +.ifnb \d5 + vld1.\wd {\d5[]}, [\s1], \strd +.endif +.ifnb \d6 + vld1.\wd {\d6[]}, [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + vld1.8 {\d0}, [\s0], \strd + vld1.8 {\d1}, [\s1], \strd +.ifnb \d2 + vld1.8 {\d2}, [\s0], \strd + vld1.8 {\d3}, [\s1], \strd +.endif +.ifnb \d4 + vld1.8 {\d4}, [\s0], \strd +.endif +.ifnb \d5 + vld1.8 {\d5}, [\s1], \strd +.endif +.ifnb \d6 + vld1.8 {\d6}, [\s0], \strd +.endif +.endm +.macro load_16 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, 16, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro interleave_1_16 r0, r1, r2, r3, r4 + vext.8 \r0, \r0, \r1, #6 + vext.8 \r1, \r1, \r2, #6 +.ifnb \r3 + vext.8 \r2, \r2, \r3, #6 + vext.8 \r3, \r3, \r4, #6 +.endif +.endm +.macro interleave_1_32 r0, r1, r2, r3, r4 + vext.8 \r0, \r0, \r1, #4 + vext.8 \r1, \r1, \r2, #4 +.ifnb \r3 + vext.8 \r2, \r2, \r3, #4 + vext.8 \r3, \r3, \r4, #4 +.endif +.endm +.macro vmovl_u8 q0, d0, q1, d1, q2, d2, q3, d3, q4, d4, q5, d5, q6, d6 + vmovl.u8 \q0, \d0 + vmovl.u8 \q1, \d1 +.ifnb \q2 + vmovl.u8 \q2, \d2 + vmovl.u8 \q3, \d3 +.endif +.ifnb \q4 + vmovl.u8 \q4, \d4 +.endif +.ifnb \q5 + vmovl.u8 \q5, \d5 +.endif +.ifnb \q6 + vmovl.u8 \q6, \d6 +.endif +.endm +.macro mul_mla_4 d, s0, s1, s2, s3 + vmul.s16 \d, \s0, d0[0] + vmla.s16 \d, \s1, d0[1] + vmla.s16 \d, \s2, d0[2] + vmla.s16 \d, \s3, d0[3] +.endm +.macro mul_mla_8_0 d0, s0, s1, s2, s3, s4, s5, s6, s7 + vmul.s16 \d0, \s0, d0[0] + vmla.s16 \d0, \s1, d0[1] + vmla.s16 \d0, \s2, d0[2] + vmla.s16 \d0, \s3, d0[3] + vmla.s16 \d0, \s4, d1[0] + vmla.s16 \d0, \s5, d1[1] + vmla.s16 \d0, \s6, d1[2] + vmla.s16 \d0, \s7, d1[3] +.endm +.macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + vmul.s16 \d0, \s0, d0[0] + vmla.s16 \d0, \s1, d0[1] + vmla.s16 \d0, \s2, d0[2] + vmla.s16 \d0, \s3, d0[3] + vmla.s16 \d0, \s4, d1[0] + vmla.s16 \d0, \s5, d1[1] + vmla.s16 \d0, \s6, d1[2] + vmla.s16 \d0, \s7, d1[3] + vmul.s16 \d1, \s1, d0[0] + vmla.s16 \d1, \s2, d0[1] + vmla.s16 \d1, \s3, d0[2] + vmla.s16 \d1, \s4, d0[3] + vmla.s16 \d1, \s5, d1[0] + vmla.s16 \d1, \s6, d1[1] + vmla.s16 \d1, \s7, d1[2] + vmla.s16 \d1, \s8, d1[3] +.endm +.macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 + vmul.s16 \d0, \s0, d0[0] + vmla.s16 \d0, \s1, d0[1] + vmla.s16 \d0, \s2, d0[2] + vmla.s16 \d0, \s3, d0[3] + vmla.s16 \d0, \s4, d1[0] + vmla.s16 \d0, \s5, d1[1] + vmla.s16 \d0, \s6, d1[2] + vmla.s16 \d0, \s7, d1[3] + vmul.s16 \d1, \s2, d0[0] + vmla.s16 \d1, \s3, d0[1] + vmla.s16 \d1, \s4, d0[2] + vmla.s16 \d1, \s5, d0[3] + vmla.s16 \d1, \s6, d1[0] + vmla.s16 \d1, \s7, d1[1] + vmla.s16 \d1, \s8, d1[2] + vmla.s16 \d1, \s9, d1[3] +.endm +.macro vqrshrun_s16 shift, q0, d0, q1, d1, q2, d2, q3, d3 + vqrshrun.s16 \d0, \q0, #\shift +.ifnb \q1 + vqrshrun.s16 \d1, \q1, #\shift +.endif +.ifnb \q2 + vqrshrun.s16 \d2, \q2, #\shift + vqrshrun.s16 \d3, \q3, #\shift +.endif +.endm +.macro vrshr_s16 shift, r0, r1, r2, r3 + vrshr.s16 \r0, \r0, #\shift +.ifnb \r1 + vrshr.s16 \r1, \r1, #\shift +.endif +.ifnb \r2 + vrshr.s16 \r2, \r2, #\shift + vrshr.s16 \r3, \r3, #\shift +.endif +.endm +.macro st_16 strd, reg, lanes + vst1.16 {\reg[0]}, [r0, :16], \strd + vst1.16 {\reg[1]}, [r8, :16], \strd +.if \lanes > 2 + vst1.16 {\reg[2]}, [r0, :16], \strd + vst1.16 {\reg[3]}, [r8, :16], \strd +.endif +.endm +.macro st_32 strd, r0, r1 + vst1.32 {\r0[0]}, [r0, :32], \strd + vst1.32 {\r0[1]}, [r8, :32], \strd +.ifnb \r1 + vst1.32 {\r1[0]}, [r0, :32], \strd + vst1.32 {\r1[1]}, [r8, :32], \strd +.endif +.endm +.macro st_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7 + vst1.8 {\r0}, [r0, \align], \strd + vst1.8 {\r1}, [r8, \align], \strd +.ifnb \r2 + vst1.8 {\r2}, [r0, \align], \strd + vst1.8 {\r3}, [r8, \align], \strd +.endif +.ifnb \r4 + vst1.8 {\r4}, [r0, \align], \strd + vst1.8 {\r5}, [r8, \align], \strd + vst1.8 {\r6}, [r0, \align], \strd + vst1.8 {\r7}, [r8, \align], \strd +.endif +.endm +.macro shift_store_4 type, strd, q0, d0, d1, q1, d2, d3 +.ifc \type, put + vqrshrun_s16 6, \q0, \d0, \q1, \d2 + st_32 \strd, \d0, \d2 +.else + vrshr_s16 2, \q0, \q1 + st_reg \strd, :64, \d0, \d1, \d2, \d3 +.endif +.endm +.macro shift_store_8 type, strd, q0, d0, q1, d1, q2, d2, q3, d3 +.ifc \type, put + vqrshrun_s16 6, \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3 + st_reg \strd, :64, \d0, \d1, \d2, \d3 +.else + vrshr_s16 2, \q0, \q1, \q2, \q3 + st_reg \strd, :128,\q0, \q1, \q2, \q3 +.endif +.endm +.macro shift_store_16 type, strd, q0, d0, d1, q1, q2, d4, d5, q3 +.ifc \type, put + vqrshrun.s16 \d0, \q0, #6 + vqrshrun.s16 \d1, \q1, #6 + vqrshrun.s16 \d4, \q2, #6 + vqrshrun.s16 \d5, \q3, #6 + st_reg \strd, :128, \q0, \q2 +.else + vrshr_s16 2, \q0, \q1, \q2, \q3 + vst1.16 {\q0, \q1}, [r0, :128], \strd + vst1.16 {\q2, \q3}, [r8, :128], \strd +.endif +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_8bpc_neon, export=1 + push {r4-r11,lr} + movw r8, \type_h + movw r9, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, ds2, sr2, shift_hv +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] + movw r10, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, r10 + mul \my, \my, r10 + add \mx, \mx, r8 // mx, 8tap_h, 4tap_h + add \my, \my, r9 // my, 8tap_v, 4tap_v +.ifc \type, prep + lsl \d_strd, \w, #1 +.endif + + clz r8, \w + tst \mx, #(0x7f << 14) + sub r8, r8, #24 + movrel r10, X(mc_subpel_filters), -8 + bne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + bne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx r9, \mx, #7, #7 + and \mx, \mx, #0x7f + it gt + movgt \mx, r9 + tst \my, #(0x7f << 14) + add \mx, r10, \mx, lsl #3 + bne L(\type\()_8tap_hv) + + adr r9, L(\type\()_8tap_h_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_8tap_h_tbl): + .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + +20: // 2xN h +.ifc \type, put + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 +2: + vld1.8 {d4}, [\src], \s_strd + vld1.8 {d6}, [\sr2], \s_strd + vmovl.u8 q2, d4 + vmovl.u8 q3, d6 + vext.8 d5, d4, d5, #2 + vext.8 d7, d6, d7, #2 + subs \h, \h, #2 + vtrn.32 d4, d6 + vtrn.32 d5, d7 + vmul.s16 d2, d4, d0[0] + vmla.s16 d2, d5, d0[1] + vmla.s16 d2, d6, d0[2] + vmla.s16 d2, d7, d0[3] + vrshr.s16 d2, d2, #2 + vqrshrun.s16 d2, q1, #4 + vst1.16 {d2[0]}, [\dst, :16], \d_strd + vst1.16 {d2[1]}, [\ds2, :16], \d_strd + bgt 2b + pop {r4-r11,pc} +.endif + +40: // 4xN h + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 +4: + vld1.8 {d16}, [\src], \s_strd + vld1.8 {d24}, [\sr2], \s_strd + vmovl.u8 q8, d16 + vmovl.u8 q12, d24 + vext.8 d18, d16, d17, #2 + vext.8 d20, d16, d17, #4 + vext.8 d22, d16, d17, #6 + vext.8 d26, d24, d25, #2 + vext.8 d28, d24, d25, #4 + vext.8 d30, d24, d25, #6 + subs \h, \h, #2 + vmul.s16 d4, d16, d0[0] + vmla.s16 d4, d18, d0[1] + vmla.s16 d4, d20, d0[2] + vmla.s16 d4, d22, d0[3] + vmul.s16 d5, d24, d0[0] + vmla.s16 d5, d26, d0[1] + vmla.s16 d5, d28, d0[2] + vmla.s16 d5, d30, d0[3] + vrshr.s16 q2, q2, #2 +.ifc \type, put + vqrshrun.s16 d4, q2, #4 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d4[1]}, [\ds2, :32], \d_strd +.else + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d5}, [\ds2, :64], \d_strd +.endif + bgt 4b + pop {r4-r11,pc} + +80: // 8xN h + vld1.8 {d0}, [\mx, :64] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 +8: + vld1.8 {q8}, [\src], \s_strd + vld1.8 {q12}, [\sr2], \s_strd + vmovl.u8 q9, d17 + vmovl.u8 q8, d16 + vmovl.u8 q13, d25 + vmovl.u8 q12, d24 + + vmul.s16 q10, q8, d0[0] + vmul.s16 q14, q12, d0[0] +.irpc i, 1234567 + vext.8 q11, q8, q9, #(2*\i) + vext.8 q15, q12, q13, #(2*\i) +.if \i < 4 + vmla.s16 q10, q11, d0[\i] + vmla.s16 q14, q15, d0[\i] +.else + vmla.s16 q10, q11, d1[\i-4] + vmla.s16 q14, q15, d1[\i-4] +.endif +.endr + subs \h, \h, #2 + vrshr.s16 q10, q10, #2 + vrshr.s16 q14, q14, #2 +.ifc \type, put + vqrshrun.s16 d20, q10, #4 + vqrshrun.s16 d28, q14, #4 + vst1.8 {d20}, [\dst, :64], \d_strd + vst1.8 {d28}, [\ds2, :64], \d_strd +.else + vst1.16 {q10}, [\dst, :128], \d_strd + vst1.16 {q14}, [\ds2, :128], \d_strd +.endif + bgt 8b + pop {r4-r11,pc} + +160: +320: +640: +1280: // 16xN, 32xN, ... h + // This could be done without touching q4-q6, by using only + // one temporary for vext in the loop. That's slower on A7 and A53, + // (but surprisingly, marginally faster on A8 and A73). + vpush {q4-q6} + vld1.8 {d0}, [\mx, :64] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 + + sub \s_strd, \s_strd, \w + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w +.endif +161: + vld1.8 {d16, d17, d18}, [\src]! + vld1.8 {d24, d25, d26}, [\sr2]! + mov \mx, \w + vmovl.u8 q10, d18 + vmovl.u8 q9, d17 + vmovl.u8 q8, d16 + vmovl.u8 q14, d26 + vmovl.u8 q13, d25 + vmovl.u8 q12, d24 + +16: + vmul.s16 q1, q8, d0[0] + vmul.s16 q2, q9, d0[0] + vmul.s16 q3, q12, d0[0] + vmul.s16 q4, q13, d0[0] +.irpc i, 1234567 + vext.8 q5, q8, q9, #(2*\i) + vext.8 q6, q9, q10, #(2*\i) + vext.8 q11, q12, q13, #(2*\i) + vext.8 q15, q13, q14, #(2*\i) +.if \i < 4 + vmla.s16 q1, q5, d0[\i] + vmla.s16 q2, q6, d0[\i] + vmla.s16 q3, q11, d0[\i] + vmla.s16 q4, q15, d0[\i] +.else + vmla.s16 q1, q5, d1[\i-4] + vmla.s16 q2, q6, d1[\i-4] + vmla.s16 q3, q11, d1[\i-4] + vmla.s16 q4, q15, d1[\i-4] +.endif +.endr + vrshr.s16 q1, q1, #2 + vrshr.s16 q2, q2, #2 + vrshr.s16 q3, q3, #2 + vrshr.s16 q4, q4, #2 + subs \mx, \mx, #16 +.ifc \type, put + vqrshrun.s16 d2, q1, #4 + vqrshrun.s16 d3, q2, #4 + vqrshrun.s16 d4, q3, #4 + vqrshrun.s16 d5, q4, #4 + vst1.8 {q1}, [\dst, :128]! + vst1.8 {q2}, [\ds2, :128]! +.else + vst1.16 {q1, q2}, [\dst, :128]! + vst1.16 {q3, q4}, [\ds2, :128]! +.endif + ble 9f + + vmov q8, q10 + vmov q12, q14 + vld1.8 {d18, d19}, [\src]! + vld1.8 {d26, d27}, [\sr2]! + vmovl.u8 q10, d19 + vmovl.u8 q9, d18 + vmovl.u8 q14, d27 + vmovl.u8 q13, d26 + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + bgt 161b + vpop {q4-q6} + pop {r4-r11,pc} + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx r9, \my, #7, #7 + and \my, \my, #0x7f + it gt + movgt \my, r9 + add \my, r10, \my, lsl #3 + + adr r9, L(\type\()_8tap_v_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_8tap_v_tbl): + .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + +20: // 2xN v +.ifc \type, put + bgt 28f + + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + // 2x2 v + load_16 \src, \sr2, \s_strd, d1, d2, d3, d4, d5 + interleave_1_16 d1, d2, d3, d4, d5 + bgt 24f + vmovl_u8 q8, d1, q9, d2, q10, d3, q11, d4 + mul_mla_4 d6, d16, d18, d20, d22 + vqrshrun_s16 6, q3, d6 + st_16 \d_strd, d6, 2 + pop {r4-r11,pc} + +24: // 2x4 v + load_16 \sr2, \src, \s_strd, d6, d7 + interleave_1_16 d5, d6, d7 + vmovl_u8 q8, d1, q9, d2, q10, d3, q11, d4, q12, d5, q13, d6 + vmov d17, d20 + vmov d19, d22 + vmov d21, d24 + vmov d23, d26 + mul_mla_4 q3, q8, q9, q10, q11 + vqrshrun_s16 6, q3, d6 + st_16 \d_strd, d6, 4 + pop {r4-r11,pc} + +28: // 2x6, 2x8, 2x12, 2x16 v + vpush {q4-q7} + vld1.8 {d0}, [\my, :64] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 + + load_16 \src, \sr2, \s_strd, d2, d4, d6, d8, d10, d12, d14 + interleave_1_16 d2, d4, d6, d8, d10 + interleave_1_16 d10, d12, d14 + vmovl_u8 q1, d2, q2, d4, q3, d6, q4, d8, q5, d10, q6, d12 + vmov d3, d6 + vmov d5, d8 + vmov d7, d10 + vmov d9, d12 +216: + subs \h, \h, #4 + load_16 \sr2, \src, \s_strd, d16, d18, d20, d22 + interleave_1_16 d14, d16, d18, d20, d22 + vmovl_u8 q7, d14, q8, d16, q9, d18, q10, d20 + vmov d11, d14 + vmov d13, d16 + vmov d15, d18 + vmov d17, d20 + mul_mla_8_0 q1, q1, q2, q3, q4, q5, q6, q7, q8 + vqrshrun_s16 6, q1, d2 + st_16 \d_strd, d2, 4 + ble 0f + cmp \h, #2 + vmov q1, q5 + vmov q2, q6 + vmov q3, q7 + vmov q4, q8 + vmov q5, q9 + vmov q6, q10 + vmov d14, d22 + beq 26f + b 216b +26: + load_16 \sr2, \src, \s_strd, d16, d18 + interleave_1_16 d14, d16, d18 + vmovl_u8 q7, d14, q8, d16 + vmov d11, d14 + vmov d13, d16 + mul_mla_8_0 d2, d2, d4, d6, d8, d10, d12, d14, d16 + vqrshrun_s16 6, q1, d2 + st_16 \d_strd, d2, 2 +0: + vpop {q4-q7} + pop {r4-r11,pc} +.endif + +40: + bgt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_32 \src, \sr2, \s_strd, d1, d2, d3, d4, d5 + interleave_1_32 d1, d2, d3, d4, d5 + vmovl_u8 q8, d1, q9, d2, q10, d3, q11, d4 + mul_mla_4 q3, q8, q9, q10, q11 + shift_store_4 \type, \d_strd, q3, d6, d7 + ble 0f + load_32 \sr2, \src, \s_strd, d6, d7 + interleave_1_32 d5, d6, d7 + vmovl_u8 q12, d5, q13, d6 + mul_mla_4 q3, q10, q11, q12, q13 + shift_store_4 \type, \d_strd, q3, d6, d7 +0: + pop {r4-r11,pc} + +480: // 4x6, 4x8, 4x12, 4x16 v + vpush {q4} + vld1.8 {d0}, [\my, :64] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_32 \src, \sr2, \s_strd, d2, d4, d6, d8, d16, d18, d20 + interleave_1_32 d2, d4, d6 + interleave_1_32 d6, d8, d16, d18, d20 + vmovl_u8 q1, d2, q2, d4, q3, d6, q4, d8, q8, d16, q9, d18 + +48: + subs \h, \h, #4 + load_32 \sr2, \src, \s_strd, d22, d24, d26, d28 + interleave_1_32 d20, d22, d24, d26, d28 + vmovl_u8 q10, d20, q11, d22, q12, d24, q13, d26 + mul_mla_8_2 q1, q2, q1, q2, q3, q4, q8, q9, q10, q11, q12, q13 + shift_store_4 \type, \d_strd, q1, d2, d3, q2, d4, d5 + ble 0f + load_32 \sr2, \src, \s_strd, d30, d2 + subs \h, \h, #2 + interleave_1_32 d28, d30, d2 + vmovl_u8 q14, d28, q15, d30 + mul_mla_8_0 q8, q8, q9, q10, q11, q12, q13, q14, q15 + shift_store_4 \type, \d_strd, q8, d16, d17 + ble 0f + load_32 \sr2, \src, \s_strd, d4, d6 + subs \h, \h, #2 + interleave_1_32 d2, d4, d6 + vmovl_u8 q1, d2, q2, d4 + mul_mla_8_0 q9, q10, q11, q12, q13, q14, q15, q1, q2 + shift_store_4 \type, \d_strd, q9, d18, d19 + ble 0f + subs \h, \h, #4 + load_32 \sr2, \src, \s_strd, d8, d16, d18, d20 + interleave_1_32 d6, d8, d16, d18, d20 + vmovl_u8 q3, d6, q4, d8, q8, d16, q9, d18 + mul_mla_8_2 q12, q13, q12, q13, q14, q15, q1, q2, q3, q4, q8, q9 + shift_store_4 \type, \d_strd, q12, d24, d25, q13, d26, d27 + bgt 48b +0: + vpop {q4} + pop {r4-r11,pc} + +80: + bgt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_reg \src, \sr2, \s_strd, d1, d2, d3, d4, d5 + vmovl_u8 q8, d1, q9, d2, q10, d3, q11, d4, q12, d5 + mul_mla_4 q1, q8, q9, q10, q11 + mul_mla_4 q2, q9, q10, q11, q12 + shift_store_8 \type, \d_strd, q1, d2, q2, d4 + ble 0f + load_reg \sr2, \src, \s_strd, d6, d7 + vmovl_u8 q13, d6, q14, d7 + mul_mla_4 q1, q10, q11, q12, q13 + mul_mla_4 q2, q11, q12, q13, q14 + shift_store_8 \type, \d_strd, q1, d2, q2, d4 +0: + pop {r4-r11,pc} + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + vpush {q4} + vld1.8 {d0}, [\my, :64] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + vmovl.s8 q0, d0 + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_reg \src, \sr2, \s_strd, d2, d4, d6, d8, d16, d18, d20 + vmovl_u8 q1, d2, q2, d4, q3, d6, q4, d8, q8, d16, q9, d18, q10, d20 + +88: + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, d22, d24 + vmovl_u8 q11, d22, q12, d24 + mul_mla_8_1 q1, q2, q1, q2, q3, q4, q8, q9, q10, q11, q12 + shift_store_8 \type, \d_strd, q1, d2, q2, d4 + ble 9f + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, d26, d28 + vmovl_u8 q13, d26, q14, d28 + mul_mla_8_1 q3, q4, q3, q4, q8, q9, q10, q11, q12, q13, q14 + shift_store_8 \type, \d_strd, q3, d6, q4, d8 + ble 9f + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, d30, d2 + vmovl_u8 q15, d30, q1, d2 + mul_mla_8_1 q8, q9, q8, q9, q10, q11, q12, q13, q14, q15, q1 + shift_store_8 \type, \d_strd, q8, d16, q9, d18 + ble 9f + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, d4, d6 + vmovl_u8 q2, d4, q3, d6 + mul_mla_8_1 q10, q11, q10, q11, q12, q13, q14, q15, q1, q2, q3 + shift_store_8 \type, \d_strd, q10, d20, q11, d22 + ble 9f + subs \h, \h, #4 + load_reg \sr2, \src, \s_strd, d8, d16, d18, d20 + vmovl_u8 q4, d8, q8, d16, q9, d18, q10, d20 + mul_mla_8_1 q12, q13, q12, q13, q14, q15, q1, q2, q3, q4, q8 + mul_mla_8_1 q14, q15, q14, q15, q1, q2, q3, q4, q8, q9, q10 + shift_store_8 \type, \d_strd, q12, d24, q13, d26, q14, d28, q15, d30 + bgt 88b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + vpop {q4} + pop {r4-r11,pc} + +160: + bgt 1680b + + // 16x2, 16x4 v + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + cmp \h, #2 + load_reg \src, \sr2, \s_strd, q11, q12, q13, q14, q15 + vmovl.u8 q1, d22 + vmovl.u8 q2, d24 + vmovl.u8 q3, d26 + vmovl.u8 q8, d28 + vmovl.u8 q9, d30 + vmovl.u8 q11, d23 + vmovl.u8 q12, d25 + vmovl.u8 q13, d27 + vmovl.u8 q14, d29 + vmovl.u8 q15, d31 + mul_mla_4 q1, q1, q2, q3, q8 + mul_mla_4 q10, q2, q3, q8, q9 + mul_mla_4 q2, q11, q12, q13, q14 + mul_mla_4 q11, q12, q13, q14, q15 + shift_store_16 \type, \d_strd, q1, d2, d3, q2, q10, d20, d21, q11 + ble 0f + load_reg \sr2, \src, \s_strd, q10, q11 + vmovl.u8 q1, d20 + vmovl.u8 q10, d21 + vmovl.u8 q12, d22 + vmovl.u8 q11, d23 + mul_mla_4 q2, q3, q8, q9, q1 + mul_mla_4 q3, q13, q14, q15, q10 + mul_mla_4 q13, q8, q9, q1, q12 + mul_mla_4 q14, q14, q15, q10, q11 + shift_store_16 \type, \d_strd, q2, d4, d5, q3, q13, d26, d27, q14 +0: + pop {r4-r11,pc} + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx r9, \my, #7, #7 + and \my, \my, #0x7f + it gt + movgt \my, r9 + add \my, r10, \my, lsl #3 + + adr r9, L(\type\()_8tap_hv_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_8tap_hv_tbl): + .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + +20: +.ifc \type, put + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + bgt 280f + add \my, \my, #2 + vld1.32 {d2[]}, [\my] + + // 2x2, 2x4 hv + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + + vld1.8 {d26}, [\src], \s_strd + vmovl.u8 q13, d26 + vext.8 q14, q13, q13, #2 + vmul.s16 d26, d26, d0 + vmul.s16 d28, d28, d0 + vpadd.s16 d26, d26, d28 + vpadd.s16 d26, d26, d26 + vrshr.s16 d16, d26, #2 + bl L(\type\()_8tap_filter_2) + + vext.8 d16, d16, d16, #4 + vmov d17, d26 + vext.8 d16, d16, d26, #4 + +2: + bl L(\type\()_8tap_filter_2) + + vext.8 d18, d17, d26, #4 + vmull.s16 q2, d16, d2[0] + vmlal.s16 q2, d17, d2[1] + vmlal.s16 q2, d18, d2[2] + vmlal.s16 q2, d26, d2[3] + + vqrshrn.s32 d4, q2, #\shift_hv + vqmovun.s16 d4, q2 + subs \h, \h, #2 + vst1.16 {d4[0]}, [\dst, :16], \d_strd + vst1.16 {d4[1]}, [\ds2, :16], \d_strd + ble 0f + vmov d16, d18 + vmov d17, d26 + b 2b + +280: // 2x8, 2x16, 2x32 hv + vld1.8 {d2}, [\my, :64] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + vld1.8 {d26}, [\src], \s_strd + vmovl.u8 q13, d26 + vext.8 q14, q13, q13, #2 + vmul.s16 d26, d26, d0 + vmul.s16 d28, d28, d0 + vpadd.s16 d26, d26, d28 + vpadd.s16 d26, d26, d26 + vrshr.s16 d16, d26, #2 + + bl L(\type\()_8tap_filter_2) + vext.8 d16, d16, d16, #4 + vmov d17, d26 + vext.8 d16, d16, d26, #4 + bl L(\type\()_8tap_filter_2) + vext.8 d18, d17, d26, #4 + vmov d19, d26 + bl L(\type\()_8tap_filter_2) + vext.8 d20, d19, d26, #4 + vmov d21, d26 + +28: + bl L(\type\()_8tap_filter_2) + vext.8 d22, d21, d26, #4 + vmull.s16 q2, d16, d2[0] + vmlal.s16 q2, d17, d2[1] + vmlal.s16 q2, d18, d2[2] + vmlal.s16 q2, d19, d2[3] + vmlal.s16 q2, d20, d3[0] + vmlal.s16 q2, d21, d3[1] + vmlal.s16 q2, d22, d3[2] + vmlal.s16 q2, d26, d3[3] + + vqrshrn.s32 d4, q2, #\shift_hv + vqmovun.s16 d4, q2 + subs \h, \h, #2 + vst1.16 {d4[0]}, [\dst, :16], \d_strd + vst1.16 {d4[1]}, [\ds2, :16], \d_strd + ble 0f + vmov d16, d18 + vmov d17, d19 + vmov d18, d20 + vmov d19, d21 + vmov d20, d22 + vmov d21, d26 + b 28b + +0: + pop {r4-r11,pc} + +L(\type\()_8tap_filter_2): + vld1.8 {d28}, [\sr2], \s_strd + vld1.8 {d30}, [\src], \s_strd + vext.8 d29, d28, d28, #1 + vext.8 d31, d30, d30, #1 + vmovl.u8 q13, d28 + vmovl.u8 q14, d29 + vmov d27, d28 + vmovl.u8 q14, d30 + vmovl.u8 q15, d31 + vtrn.32 d26, d28 + vtrn.32 d27, d30 + vmul.s16 d26, d26, d0[0] + vmla.s16 d26, d27, d0[1] + vmla.s16 d26, d28, d0[2] + vmla.s16 d26, d30, d0[3] + vrshr.s16 d26, d26, #2 + vext.8 d27, d26, d26, #4 + bx lr +.endif + +40: + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + bgt 480f + add \my, \my, #2 + vld1.32 {d2[]}, [\my] + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + // 4x2, 4x4 hv + vld1.8 {d30}, [\src], \s_strd + vmovl.u8 q14, d30 + vext.8 d27, d28, d29, #2 + vext.8 d30, d28, d29, #4 + vext.8 d31, d28, d29, #6 + vmul.s16 d26, d28, d0[0] + vmla.s16 d26, d27, d0[1] + vmla.s16 d26, d30, d0[2] + vmla.s16 d26, d31, d0[3] + vrshr.s16 d16, d26, #2 + + bl L(\type\()_8tap_filter_4) + vmov d17, d26 + vmov d18, d27 + +4: + bl L(\type\()_8tap_filter_4) + vmull.s16 q2, d16, d2[0] + vmlal.s16 q2, d17, d2[1] + vmlal.s16 q2, d18, d2[2] + vmlal.s16 q2, d26, d2[3] + vmull.s16 q3, d17, d2[0] + vmlal.s16 q3, d18, d2[1] + vmlal.s16 q3, d26, d2[2] + vmlal.s16 q3, d27, d2[3] + vqrshrn.s32 d4, q2, #\shift_hv + vqrshrn.s32 d6, q3, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + vqmovun.s16 d4, q2 + vqmovun.s16 d6, q3 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d6[0]}, [\ds2, :32], \d_strd +.else + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d6}, [\ds2, :64], \d_strd +.endif + ble 0f + vmov d16, d18 + vmov d17, d26 + vmov d18, d27 + b 4b + +480: // 4x8, 4x16, 4x32 hv + vld1.8 {d2}, [\my, :64] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + vld1.8 {d30}, [\src], \s_strd + vmovl.u8 q14, d30 + vext.8 d27, d28, d29, #2 + vext.8 d30, d28, d29, #4 + vext.8 d31, d28, d29, #6 + vmul.s16 d26, d28, d0[0] + vmla.s16 d26, d27, d0[1] + vmla.s16 d26, d30, d0[2] + vmla.s16 d26, d31, d0[3] + vrshr.s16 d16, d26, #2 + + bl L(\type\()_8tap_filter_4) + vmov d17, d26 + vmov d18, d27 + bl L(\type\()_8tap_filter_4) + vmov d19, d26 + vmov d20, d27 + bl L(\type\()_8tap_filter_4) + vmov d21, d26 + vmov d22, d27 + +48: + bl L(\type\()_8tap_filter_4) + vmull.s16 q2, d16, d2[0] + vmlal.s16 q2, d17, d2[1] + vmlal.s16 q2, d18, d2[2] + vmlal.s16 q2, d19, d2[3] + vmlal.s16 q2, d20, d3[0] + vmlal.s16 q2, d21, d3[1] + vmlal.s16 q2, d22, d3[2] + vmlal.s16 q2, d26, d3[3] + vmull.s16 q3, d17, d2[0] + vmlal.s16 q3, d18, d2[1] + vmlal.s16 q3, d19, d2[2] + vmlal.s16 q3, d20, d2[3] + vmlal.s16 q3, d21, d3[0] + vmlal.s16 q3, d22, d3[1] + vmlal.s16 q3, d26, d3[2] + vmlal.s16 q3, d27, d3[3] + vqrshrn.s32 d4, q2, #\shift_hv + vqrshrn.s32 d6, q3, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + vqmovun.s16 d4, q2 + vqmovun.s16 d6, q3 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d6[0]}, [\ds2, :32], \d_strd +.else + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d6}, [\ds2, :64], \d_strd +.endif + ble 0f + vmov d16, d18 + vmov d17, d19 + vmov d18, d20 + vmov d19, d21 + vmov d20, d22 + vmov d21, d26 + vmov d22, d27 + b 48b +0: + pop {r4-r11,pc} + +L(\type\()_8tap_filter_4): + vld1.8 {d30}, [\sr2], \s_strd + vld1.8 {d31}, [\src], \s_strd + vmovl.u8 q14, d30 + vext.8 d27, d28, d29, #2 + vext.8 d30, d28, d29, #4 + vext.8 d1, d28, d29, #6 + vmul.s16 d26, d28, d0[0] + vmla.s16 d26, d27, d0[1] + vmla.s16 d26, d30, d0[2] + vmla.s16 d26, d1, d0[3] + + vmovl.u8 q14, d31 + vext.8 d30, d28, d29, #2 + vext.8 d31, d28, d29, #4 + vext.8 d1, d28, d29, #6 + vmul.s16 d27, d28, d0[0] + vmla.s16 d27, d30, d0[1] + vmla.s16 d27, d31, d0[2] + vmla.s16 d27, d1, d0[3] + vrshr.s16 d26, d26, #2 + vrshr.s16 d27, d27, #2 + bx lr + +80: +160: +320: + bgt 880f + vpush {q4-q7} + add \my, \my, #2 + vld1.8 {d0}, [\mx, :64] + vld1.32 {d2[]}, [\my] + sub \src, \src, #3 + sub \src, \src, \s_strd + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + vld1.8 {q14}, [\src], \s_strd + vmovl.u8 q12, d28 + vmovl.u8 q13, d29 + vmul.s16 q10, q12, d0[0] +.irpc i, 123 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d0[\i] +.endr +.irpc i, 4567 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d1[\i-4] +.endr + vrshr.s16 q3, q10, #2 + + bl L(\type\()_8tap_filter_8) + vmov q4, q10 + vmov q5, q11 + +8: + bl L(\type\()_8tap_filter_8) + vmull.s16 q12, d6, d2[0] + vmull.s16 q13, d7, d2[0] + vmull.s16 q14, d8, d2[0] + vmull.s16 q15, d9, d2[0] + vmlal.s16 q12, d8, d2[1] + vmlal.s16 q13, d9, d2[1] + vmlal.s16 q14, d10, d2[1] + vmlal.s16 q15, d11, d2[1] + vmlal.s16 q12, d10, d2[2] + vmlal.s16 q13, d11, d2[2] + vmlal.s16 q14, d20, d2[2] + vmlal.s16 q15, d21, d2[2] + vmlal.s16 q12, d20, d2[3] + vmlal.s16 q13, d21, d2[3] + vmlal.s16 q14, d22, d2[3] + vmlal.s16 q15, d23, d2[3] + vqrshrn.s32 d24, q12, #\shift_hv + vqrshrn.s32 d25, q13, #\shift_hv + vqrshrn.s32 d28, q14, #\shift_hv + vqrshrn.s32 d29, q15, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + vqmovun.s16 d24, q12 + vqmovun.s16 d28, q14 + vst1.8 {d24}, [\dst, :64], \d_strd + vst1.8 {d28}, [\ds2, :64], \d_strd +.else + vst1.16 {q12}, [\dst, :128], \d_strd + vst1.16 {q14}, [\ds2, :128], \d_strd +.endif + ble 9f + vmov q3, q5 + vmov q4, q10 + vmov q5, q11 + b 8b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 164b + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + vpush {q4-q7} + vld1.8 {d0}, [\mx, :64] + vld1.8 {d2}, [\my, :64] + sub \src, \src, #3 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + vld1.8 {q14}, [\src], \s_strd + vmovl.u8 q12, d28 + vmovl.u8 q13, d29 + vmul.s16 q10, q12, d0[0] +.irpc i, 123 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d0[\i] +.endr +.irpc i, 4567 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d1[\i-4] +.endr + vrshr.s16 q3, q10, #2 + + bl L(\type\()_8tap_filter_8) + vmov q4, q10 + vmov q5, q11 + bl L(\type\()_8tap_filter_8) + vmov q6, q10 + vmov q7, q11 + bl L(\type\()_8tap_filter_8) + vmov q8, q10 + vmov q9, q11 + +88: + bl L(\type\()_8tap_filter_8) + vmull.s16 q12, d6, d2[0] + vmull.s16 q13, d7, d2[0] + vmull.s16 q14, d8, d2[0] + vmull.s16 q15, d9, d2[0] + vmlal.s16 q12, d8, d2[1] + vmlal.s16 q13, d9, d2[1] + vmlal.s16 q14, d10, d2[1] + vmlal.s16 q15, d11, d2[1] + vmlal.s16 q12, d10, d2[2] + vmlal.s16 q13, d11, d2[2] + vmlal.s16 q14, d12, d2[2] + vmlal.s16 q15, d13, d2[2] + vmlal.s16 q12, d12, d2[3] + vmlal.s16 q13, d13, d2[3] + vmlal.s16 q14, d14, d2[3] + vmlal.s16 q15, d15, d2[3] + vmlal.s16 q12, d14, d3[0] + vmlal.s16 q13, d15, d3[0] + vmlal.s16 q14, d16, d3[0] + vmlal.s16 q15, d17, d3[0] + vmlal.s16 q12, d16, d3[1] + vmlal.s16 q13, d17, d3[1] + vmlal.s16 q14, d18, d3[1] + vmlal.s16 q15, d19, d3[1] + vmlal.s16 q12, d18, d3[2] + vmlal.s16 q13, d19, d3[2] + vmlal.s16 q14, d20, d3[2] + vmlal.s16 q15, d21, d3[2] + vmlal.s16 q12, d20, d3[3] + vmlal.s16 q13, d21, d3[3] + vmlal.s16 q14, d22, d3[3] + vmlal.s16 q15, d23, d3[3] + vqrshrn.s32 d24, q12, #\shift_hv + vqrshrn.s32 d25, q13, #\shift_hv + vqrshrn.s32 d28, q14, #\shift_hv + vqrshrn.s32 d29, q15, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + vqmovun.s16 d24, q12 + vqmovun.s16 d28, q14 + vst1.8 {d24}, [\dst, :64], \d_strd + vst1.8 {d28}, [\ds2, :64], \d_strd +.else + vst1.16 {q12}, [\dst, :128], \d_strd + vst1.16 {q14}, [\ds2, :128], \d_strd +.endif + ble 9f + vmov q3, q5 + vmov q4, q6 + vmov q5, q7 + vmov q6, q8 + vmov q7, q9 + vmov q8, q10 + vmov q9, q11 + b 88b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + vpop {q4-q7} + pop {r4-r11,pc} + +L(\type\()_8tap_filter_8): + vld1.8 {q14}, [\sr2], \s_strd + vld1.8 {q15}, [\src], \s_strd + vmovl.u8 q12, d28 + vmovl.u8 q13, d29 + vmul.s16 q10, q12, d0[0] +.irpc i, 123 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d0[\i] +.endr +.irpc i, 4567 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q10, q14, d1[\i-4] +.endr + vmovl.u8 q12, d30 + vmovl.u8 q13, d31 + vmul.s16 q11, q12, d0[0] +.irpc i, 123 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q11, q14, d0[\i] +.endr +.irpc i, 4567 + vext.8 q14, q12, q13, #(2*\i) + vmla.s16 q11, q14, d1[\i-4] +.endr + vrshr.s16 q10, q10, #2 + vrshr.s16 q11, q11, #2 + bx lr +endfunc + + +function \type\()_bilin_8bpc_neon, export=1 + push {r4-r11,lr} + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] + vdup.8 d1, \mx + vdup.8 d3, \my + rsb r8, \mx, #16 + rsb r9, \my, #16 + vdup.8 d0, r8 + vdup.8 d2, r9 +.ifc \type, prep + lsl \d_strd, \w, #1 +.endif + clz r8, \w + cmp \mx, #0 + sub r8, r8, #24 + bne L(\type\()_bilin_h) + cmp \my, #0 + bne L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cmp \my, #0 + bne L(\type\()_bilin_hv) + + adr r9, L(\type\()_bilin_h_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_bilin_h_tbl): + .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + +20: // 2xN h +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + vld1.32 {d4[]}, [\src], \s_strd + vld1.32 {d6[]}, [\sr2], \s_strd + vext.8 d5, d4, d4, #1 + vext.8 d7, d6, d6, #1 + vtrn.16 q2, q3 + subs \h, \h, #2 + vmull.u8 q3, d4, d0 + vmlal.u8 q3, d5, d1 + vqrshrn.u16 d4, q3, #4 + vst1.16 {d4[0]}, [\dst, :16], \d_strd + vst1.16 {d4[1]}, [\ds2, :16], \d_strd + bgt 2b + pop {r4-r11,pc} +.endif + +40: // 4xN h + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + vld1.8 {d4}, [\src], \s_strd + vld1.8 {d6}, [\sr2], \s_strd + vext.8 d5, d4, d4, #1 + vext.8 d7, d6, d6, #1 + vtrn.32 q2, q3 + subs \h, \h, #2 + vmull.u8 q3, d4, d0 + vmlal.u8 q3, d5, d1 +.ifc \type, put + vqrshrn.u16 d4, q3, #4 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d4[1]}, [\ds2, :32], \d_strd +.else + vst1.16 {d6}, [\dst, :64], \d_strd + vst1.16 {d7}, [\ds2, :64], \d_strd +.endif + bgt 4b + pop {r4-r11,pc} + +80: // 8xN h + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + vld1.8 {q8}, [\src], \s_strd + vld1.8 {q10}, [\sr2], \s_strd + vext.8 q9, q8, q8, #1 + vext.8 q11, q10, q10, #1 + subs \h, \h, #2 + vmull.u8 q8, d16, d0 + vmull.u8 q10, d20, d0 + vmlal.u8 q8, d18, d1 + vmlal.u8 q10, d22, d1 +.ifc \type, put + vqrshrn.u16 d16, q8, #4 + vqrshrn.u16 d18, q10, #4 + vst1.8 {d16}, [\dst, :64], \d_strd + vst1.8 {d18}, [\ds2, :64], \d_strd +.else + vst1.16 {q8}, [\dst, :128], \d_strd + vst1.16 {q10}, [\ds2, :128], \d_strd +.endif + bgt 8b + pop {r4-r11,pc} +160: +320: +640: +1280: // 16xN, 32xN, ... h + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w +.endif +161: + vld1.8 {d16}, [\src]! + vld1.8 {d22}, [\sr2]! + mov \mx, \w + +16: + vld1.8 {d17,d18}, [\src]! + vld1.8 {d23,d24}, [\sr2]! + vext.8 q10, q8, q9, #1 + vext.8 q13, q11, q12, #1 + vmull.u8 q2, d16, d0 + vmull.u8 q3, d17, d0 + vmull.u8 q14, d22, d0 + vmull.u8 q15, d23, d0 + vmlal.u8 q2, d20, d1 + vmlal.u8 q3, d21, d1 + vmlal.u8 q14, d26, d1 + vmlal.u8 q15, d27, d1 + subs \mx, \mx, #16 +.ifc \type, put + vqrshrn.u16 d4, q2, #4 + vqrshrn.u16 d5, q3, #4 + vqrshrn.u16 d28, q14, #4 + vqrshrn.u16 d29, q15, #4 + vst1.8 {q2}, [\dst, :128]! + vst1.8 {q14}, [\ds2, :128]! +.else + vst1.16 {q2, q3}, [\dst, :128]! + vst1.16 {q14, q15}, [\ds2, :128]! +.endif + ble 9f + + vmov d16, d18 + vmov d22, d24 + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + bgt 161b + pop {r4-r11,pc} + +L(\type\()_bilin_v): + cmp \h, #4 + adr r9, L(\type\()_bilin_v_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_bilin_v_tbl): + .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + +20: // 2xN v +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + vld1.16 {d16[]}, [\src], \s_strd + bgt 24f +22: + vld1.16 {d17[]}, [\sr2], \s_strd + vld1.16 {d18[]}, [\src], \s_strd + vext.8 d16, d16, d17, #6 + vext.8 d17, d17, d18, #6 + vmull.u8 q2, d16, d2 + vmlal.u8 q2, d17, d3 + vqrshrn.u16 d4, q2, #4 + vst1.16 {d4[0]}, [\dst, :16] + vst1.16 {d4[1]}, [\ds2, :16] + pop {r4-r11,pc} +24: // 2x4, 2x6, 2x8, ... v + vld1.16 {d17[]}, [\sr2], \s_strd + vld1.16 {d18[]}, [\src], \s_strd + vld1.16 {d19[]}, [\sr2], \s_strd + vld1.16 {d20[]}, [\src], \s_strd + sub \h, \h, #4 + vext.8 d16, d16, d17, #6 + vext.8 d17, d17, d18, #6 + vext.8 d18, d18, d19, #6 + vext.8 d19, d19, d20, #6 + vtrn.32 d16, d18 + vtrn.32 d17, d19 + vmull.u8 q2, d16, d2 + vmlal.u8 q2, d17, d3 + cmp \h, #2 + vqrshrn.u16 d4, q2, #4 + vst1.16 {d4[0]}, [\dst, :16], \d_strd + vst1.16 {d4[1]}, [\ds2, :16], \d_strd + vst1.16 {d4[2]}, [\dst, :16], \d_strd + vst1.16 {d4[3]}, [\ds2, :16], \d_strd + blt 0f + vmov d16, d20 + beq 22b + b 24b +0: + pop {r4-r11,pc} +.endif + +40: // 4xN v + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vld1.32 {d16[]}, [\src], \s_strd +4: + vld1.32 {d17[]}, [\sr2], \s_strd + vld1.32 {d18[]}, [\src], \s_strd + vext.8 d16, d16, d17, #4 + vext.8 d17, d17, d18, #4 + vmull.u8 q2, d16, d2 + vmlal.u8 q2, d17, d3 + subs \h, \h, #2 +.ifc \type, put + vqrshrn.u16 d4, q2, #4 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d4[1]}, [\ds2, :32], \d_strd +.else + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d5}, [\ds2, :64], \d_strd +.endif + ble 0f + vmov d16, d18 + b 4b +0: + pop {r4-r11,pc} + +80: // 8xN v + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vld1.8 {d16}, [\src], \s_strd +8: + vld1.8 {d17}, [\sr2], \s_strd + vld1.8 {d18}, [\src], \s_strd + vmull.u8 q2, d16, d2 + vmull.u8 q3, d17, d2 + vmlal.u8 q2, d17, d3 + vmlal.u8 q3, d18, d3 + subs \h, \h, #2 +.ifc \type, put + vqrshrn.u16 d4, q2, #4 + vqrshrn.u16 d6, q3, #4 + vst1.8 {d4}, [\dst, :64], \d_strd + vst1.8 {d6}, [\ds2, :64], \d_strd +.else + vst1.16 {q2}, [\dst, :128], \d_strd + vst1.16 {q3}, [\ds2, :128], \d_strd +.endif + ble 0f + vmov d16, d18 + b 8b +0: + pop {r4-r11,pc} + +160: // 16xN, 32xN, ... +320: +640: +1280: + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.8 {q8}, [\src], \s_strd +2: + vld1.8 {q9}, [\sr2], \s_strd + vld1.8 {q10}, [\src], \s_strd + vmull.u8 q12, d16, d2 + vmull.u8 q13, d17, d2 + vmull.u8 q14, d18, d2 + vmull.u8 q15, d19, d2 + vmlal.u8 q12, d18, d3 + vmlal.u8 q13, d19, d3 + vmlal.u8 q14, d20, d3 + vmlal.u8 q15, d21, d3 + subs \h, \h, #2 +.ifc \type, put + vqrshrn.u16 d24, q12, #4 + vqrshrn.u16 d25, q13, #4 + vqrshrn.u16 d28, q14, #4 + vqrshrn.u16 d29, q15, #4 + vst1.8 {q12}, [\dst, :128], \d_strd + vst1.8 {q14}, [\ds2, :128], \d_strd +.else + vst1.16 {q12, q13}, [\dst, :128], \d_strd + vst1.16 {q14, q15}, [\ds2, :128], \d_strd +.endif + ble 9f + vmov q8, q10 + b 2b +9: + subs \w, \w, #16 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 +.ifc \type, put + add \dst, \dst, #16 +.else + add \dst, \dst, #32 +.endif + b 1b +0: + pop {r4-r11,pc} + +L(\type\()_bilin_hv): + vmovl.u8 q2, d2 + vmovl.u8 q3, d3 + adr r9, L(\type\()_bilin_hv_tbl) + ldr r8, [r9, r8, lsl #2] + add r9, r9, r8 + bx r9 + + .align 2 +L(\type\()_bilin_hv_tbl): + .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + +20: // 2xN hv +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.32 {d28[]}, [\src], \s_strd + vext.8 d29, d28, d28, #1 + vmull.u8 q8, d28, d0 + vmlal.u8 q8, d29, d1 + +2: + vld1.32 {d28[]}, [\sr2], \s_strd + vld1.32 {d30[]}, [\src], \s_strd + vext.8 d29, d28, d28, #1 + vext.8 d31, d30, d30, #1 + vtrn.16 d28, d30 + vtrn.16 d29, d31 + vmull.u8 q9, d28, d0 + vmlal.u8 q9, d29, d1 + + vtrn.32 d16, d18 + + vmul.u16 d20, d16, d4 + vmla.u16 d20, d19, d6 + vqrshrn.u16 d20, q10, #8 + subs \h, \h, #2 + vst1.16 {d20[0]}, [\dst, :16], \d_strd + vst1.16 {d20[1]}, [\ds2, :16], \d_strd + ble 0f + vtrn.32 d19, d16 + b 2b +0: + pop {r4-r11,pc} +.endif + +40: // 4xN hv + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.8 {d28}, [\src], \s_strd + vext.8 d29, d28, d28, #1 + vmull.u8 q8, d28, d0 + vmlal.u8 q8, d29, d1 + +4: + vld1.8 {d28}, [\sr2], \s_strd + vld1.8 {d30}, [\src], \s_strd + vext.8 d29, d28, d28, #1 + vext.8 d31, d30, d30, #1 + vtrn.32 d28, d30 + vtrn.32 d29, d31 + vmull.u8 q9, d28, d0 + vmlal.u8 q9, d29, d1 + + vmov d17, d18 + + vmul.u16 q10, q8, q2 + vmla.u16 q10, q9, q3 + subs \h, \h, #2 +.ifc \type, put + vqrshrn.u16 d20, q10, #8 + vst1.32 {d20[0]}, [\dst, :32], \d_strd + vst1.32 {d20[1]}, [\ds2, :32], \d_strd +.else + vrshr.u16 q10, q10, #4 + vst1.16 {d20}, [\dst, :64], \d_strd + vst1.16 {d21}, [\ds2, :64], \d_strd +.endif + ble 0f + vmov d16, d19 + b 4b +0: + pop {r4-r11,pc} + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.8 {q12}, [\src], \s_strd + vext.8 q13, q12, q12, #1 + vmull.u8 q8, d24, d0 + vmlal.u8 q8, d26, d1 + +2: + vld1.8 {q12}, [\sr2], \s_strd + vld1.8 {q14}, [\src], \s_strd + vext.8 q13, q12, q12, #1 + vext.8 q15, q14, q14, #1 + vmull.u8 q9, d24, d0 + vmlal.u8 q9, d26, d1 + vmull.u8 q10, d28, d0 + vmlal.u8 q10, d30, d1 + + vmul.u16 q8, q8, q2 + vmla.u16 q8, q9, q3 + vmul.u16 q9, q9, q2 + vmla.u16 q9, q10, q3 + subs \h, \h, #2 +.ifc \type, put + vqrshrn.u16 d16, q8, #8 + vqrshrn.u16 d18, q9, #8 + vst1.8 {d16}, [\dst, :64], \d_strd + vst1.8 {d18}, [\ds2, :64], \d_strd +.else + vrshr.u16 q8, q8, #4 + vrshr.u16 q9, q9, #4 + vst1.16 {q8}, [\dst, :128], \d_strd + vst1.16 {q9}, [\ds2, :128], \d_strd +.endif + ble 9f + vmov q8, q10 + b 2b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 1b +0: + pop {r4-r11,pc} +endfunc +.endm + +filter_fn put, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, 10 +filter_fn prep, r0, r7, r1, r2, r3, r4, r5, r6, r8, r9, 6 + +.macro load_filter_ptr src + asr r12, \src, #10 + add r12, r11, r12, lsl #3 +.endm + +.macro load_filter_coef dst, src, inc + add \src, \src, \inc + vld1.8 {\dst}, [r12, :64] +.endm + +.macro load_filter_row dst, src, inc + load_filter_ptr \src + load_filter_coef \dst, \src, \inc +.endm + +function warp_filter_horz_neon + load_filter_ptr r5 // filter 0 + vld1.16 {q7}, [r2], r3 + vmov.i8 q6, #128 + + load_filter_coef d0, r5, r7 // filter 0 + load_filter_row d1, r5, r7 // filter 1 + load_filter_row d2, r5, r7 // filter 2 + load_filter_ptr r5 // filter 3 + veor q7, q7, q6 // subtract by 128 to allow using vmull + load_filter_coef d3, r5, r7 // filter 3 + vext.8 d12, d14, d15, #1 // filter 1 pixels + vext.8 d13, d14, d15, #2 // filter 2 pixels + load_filter_ptr r5 // filter 4 + vmull.s8 q2, d14, d0 // filter 0 output + vmull.s8 q3, d12, d1 // filter 1 output + load_filter_coef d0, r5, r7 // filter 4 + load_filter_ptr r5 // filter 5 + vext.8 d12, d14, d15, #3 // filter 3 pixels + vmull.s8 q4, d13, d2 // filter 2 output + vext.8 d13, d14, d15, #4 // filter 4 pixels + vpadd.i16 d4, d4, d5 // pixel 0 (4x16) + vpadd.i16 d5, d6, d7 // pixel 1 (4x16) + load_filter_coef d1, r5, r7 // filter 5 + load_filter_ptr r5 // filter 6 + vmull.s8 q5, d12, d3 // filter 3 output + vext.8 d12, d14, d15, #5 // filter 5 pixels + vmull.s8 q3, d13, d0 // filter 4 output + load_filter_coef d0, r5, r7 // filter 6 + vext.8 d13, d14, d15, #6 // filter 6 pixels + load_filter_ptr r5 // filter 7 + vpadd.i16 d8, d8, d9 // pixel 2 (4x16) + vpadd.i16 d9, d10, d11 // pixel 3 (4x16) + vmull.s8 q5, d12, d1 // filter 5 output + load_filter_coef d1, r5, r7 // filter 7 + vext.8 d14, d14, d15, #7 // filter 7 pixels + vpadd.i16 d6, d6, d7 // pixel 4 (4x16) + vpadd.i16 d10, d10, d11 // pixel 5 (4x16) + vmull.s8 q6, d13, d0 // filter 6 output + vmull.s8 q7, d14, d1 // filter 7 output + + sub r5, r5, r7, lsl #3 + + vpadd.i16 d4, d4, d5 // pixel 0,1 (2x16) + vpadd.i16 d5, d8, d9 // pixel 2,3 (2x16) + vpadd.i16 d12, d12, d13 // pixel 6 (4x16) + vpadd.i16 d14, d14, d15 // pixel 7 (4x16) + vpadd.i16 d6, d6, d10 // pixel 4,5 (2x16) + vpadd.i16 d10, d12, d14 // pixel 6,7 (2x16) + vpadd.i16 d4, d4, d5 // pixel 0-3 + vpadd.i16 d5, d6, d10 // pixel 4-7 + + add r5, r5, r8 + + bx lr +endfunc + +// void dav1d_warp_affine_8x8_8bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my) +.macro warp t, shift +function warp_affine_8x8\t\()_8bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldr r6, [sp, #108] + ldrd r8, r9, [r4] + sxth r7, r8 + asr r8, r8, #16 + asr r4, r9, #16 + sxth r9, r9 + mov r10, #8 + sub r2, r2, r3, lsl #1 + sub r2, r2, r3 + sub r2, r2, #3 + movrel r11, X(mc_warp_filter), 64*8 +.ifnb \t + lsl r1, r1, #1 +.endif + add r5, r5, #512 + add r6, r6, #512 + + bl warp_filter_horz_neon + vrshr.s16 q8, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q9, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q10, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q11, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q12, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q13, q2, #3 + bl warp_filter_horz_neon + vrshr.s16 q14, q2, #3 + +1: + bl warp_filter_horz_neon + vrshr.s16 q15, q2, #3 + + load_filter_row d8, r6, r9 + load_filter_row d9, r6, r9 + load_filter_row d10, r6, r9 + load_filter_row d11, r6, r9 + load_filter_row d12, r6, r9 + load_filter_row d13, r6, r9 + load_filter_row d14, r6, r9 + load_filter_row d15, r6, r9 + transpose_8x8b q4, q5, q6, q7, d8, d9, d10, d11, d12, d13, d14, d15 + vmovl.s8 q1, d8 + vmovl.s8 q2, d9 + vmovl.s8 q3, d10 + vmovl.s8 q4, d11 + vmovl.s8 q5, d12 + vmovl.s8 q6, d13 + + sub r6, r6, r9, lsl #3 + + // This ordering of vmull/vmlal is highly beneficial for + // Cortex A8/A9/A53 here, but harmful for Cortex A7. + vmull.s16 q0, d16, d2 + vmlal.s16 q0, d18, d4 + vmlal.s16 q0, d20, d6 + vmlal.s16 q0, d22, d8 + vmlal.s16 q0, d24, d10 + vmlal.s16 q0, d26, d12 + vmull.s16 q1, d17, d3 + vmlal.s16 q1, d19, d5 + vmlal.s16 q1, d21, d7 + vmlal.s16 q1, d23, d9 + vmlal.s16 q1, d25, d11 + vmlal.s16 q1, d27, d13 + + vmovl.s8 q2, d14 + vmovl.s8 q3, d15 + + vmlal.s16 q0, d28, d4 + vmlal.s16 q0, d30, d6 + vmlal.s16 q1, d29, d5 + vmlal.s16 q1, d31, d7 + +.ifb \t + vmov.i16 q7, #128 +.else + vmov.i16 q7, #0x800 +.endif + + vmov q8, q9 + vmov q9, q10 + vqrshrn.s32 d0, q0, #\shift + vmov q10, q11 + vqrshrn.s32 d1, q1, #\shift + vmov q11, q12 + vadd.i16 q0, q0, q7 + vmov q12, q13 +.ifb \t + vqmovun.s16 d0, q0 +.endif + vmov q13, q14 + vmov q14, q15 + subs r10, r10, #1 +.ifnb \t + vst1.16 {q0}, [r0, :128], r1 +.else + vst1.8 {d0}, [r0, :64], r1 +.endif + + add r6, r6, r4 + bgt 1b + + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +warp , 11 +warp t, 7 + +// void dav1d_emu_edge_8bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_8bpc_neon, export=1 + push {r4-r11,lr} + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] + ldrd r8, r9, [sp, #52] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub r12, r3, #1 // ih - 1 + cmp r5, r3 + sub lr, r2, #1 // iw - 1 + it lt + movlt r12, r5 // min(y, ih - 1) + cmp r4, r2 + bic r12, r12, r12, asr #31 // max(min(y, ih - 1), 0) + it lt + movlt lr, r4 // min(x, iw - 1) + bic lr, lr, lr, asr #31 // max(min(x, iw - 1), 0) + mla r8, r12, r9, r8 // ref += iclip() * stride + add r8, r8, lr // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add r10, r5, r1 // y + bh + neg r5, r5 // -y + sub r10, r10, r3 // y + bh - ih + sub r12, r1, #1 // bh - 1 + cmp r10, r1 + bic r5, r5, r5, asr #31 // max(-y, 0) + it ge + movge r10, r12 // min(y + bh - ih, bh-1) + cmp r5, r1 + bic r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0) + it ge + movge r5, r12 // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add r11, r4, r0 // x + bw + neg r4, r4 // -x + sub r11, r11, r2 // x + bw - iw + sub lr, r0, #1 // bw - 1 + cmp r11, r0 + bic r4, r4, r4, asr #31 // max(-x, 0) + it ge + movge r11, lr // min(x + bw - iw, bw-1) + cmp r4, r0 + bic r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0) + it ge + movge r4, lr // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub r1, r1, r5 // bh - top_ext + mla r6, r5, r7, r6 + sub r2, r0, r4 // bw - left_ext + sub r1, r1, r10 // center_h = bh - top_ext - bottom_ext + sub r2, r2, r11 // center_w = bw - left_ext - right_ext + + mov r0, r6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + vld1.8 {d0[], d1[]}, [r8] + mov r12, r6 // out = dst + mov r3, r4 +1: + subs r3, r3, #16 + vst1.8 {q0}, [r12, :128]! + bgt 1b +.endif + mov lr, r8 + add r12, r6, r4 // out = dst + left_ext + mov r3, r2 +1: + vld1.8 {q0, q1}, [lr]! + subs r3, r3, #32 +.if \need_left + vst1.8 {q0, q1}, [r12]! +.else + vst1.8 {q0, q1}, [r12, :128]! +.endif + bgt 1b +.if \need_right + add r3, r8, r2 // in + center_w + sub r3, r3, #1 // in + center_w - 1 + add r12, r6, r4 // dst + left_ext + vld1.8 {d0[], d1[]}, [r3] + add r12, r12, r2 // out = dst + left_ext + center_w + mov r3, r11 +1: + subs r3, r3, #16 + vst1.8 {q0}, [r12]! + bgt 1b +.endif + + subs r1, r1, #1 // center_h-- + add r6, r6, r7 + add r8, r8, r9 + bgt 0b +.endm + + cmp r4, #0 + beq 2f + // need_left + cmp r11, #0 + beq 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cmp r11, #0 + beq 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + cmp r10, #0 + // Storing the original dst in r0 overwrote bw, recalculate it here + add r2, r2, r4 // center_w + left_ext + add r2, r2, r11 // bw = center_w + left_ext + right_ext + + beq 3f + // need_bottom + sub r8, r6, r7 // ref = dst - stride + mov r4, r2 +1: + vld1.8 {q0, q1}, [r8, :128]! + mov r3, r10 +2: + subs r3, r3, #1 + vst1.8 {q0, q1}, [r6, :128], r7 + bgt 2b + mls r6, r7, r10, r6 // dst -= bottom_ext * stride + subs r4, r4, #32 // bw -= 32 + add r6, r6, #32 // dst += 32 + bgt 1b + +3: + cmp r5, #0 + beq 3f + // need_top + mls r6, r7, r5, r0 // dst = stored_dst - top_ext * stride +1: + vld1.8 {q0, q1}, [r0, :128]! + mov r3, r5 +2: + subs r3, r3, #1 + vst1.8 {q0, q1}, [r6, :128], r7 + bgt 2b + mls r6, r7, r5, r6 // dst -= top_ext * stride + subs r2, r2, #32 // bw -= 32 + add r6, r6, #32 // dst += 32 + bgt 1b + +3: + pop {r4-r11,pc} +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/mc16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/mc16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/mc16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3658 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define PREP_BIAS 8192 + +.macro avg d0, d00, d01, d1, d10, d11 + vld1.16 {q0, q1}, [r2, :128]! + vld1.16 {q2, q3}, [r3, :128]! + vqadd.s16 q0, q0, q2 + vqadd.s16 q1, q1, q3 + vmax.s16 q0, q0, q12 // -2*PREP_BIAS - 1 << intermediate_bits + vmax.s16 q1, q1, q12 // -2*PREP_BIAS - 1 << intermediate_bits + vqsub.s16 q0, q0, q12 // -2*PREP_BIAS - 1 << intermediate_bits + vqsub.s16 q1, q1, q12 // -2*PREP_BIAS - 1 << intermediate_bits + vshl.s16 \d0, q0, q13 // -(intermediate_bits+1) + vshl.s16 \d1, q1, q13 // -(intermediate_bits+1) +.endm + +.macro w_avg d0, d00, d01, d1, d10, d11 + vld1.16 {q0, q1}, [r2, :128]! + vld1.16 {q2, q3}, [r3, :128]! + // This difference requires a 17 bit range, and all bits are + // significant for the following multiplication. + vsubl.s16 \d0, d4, d0 + vsubl.s16 q0, d5, d1 + vsubl.s16 \d1, d6, d2 + vsubl.s16 q1, d7, d3 + vmul.s32 \d0, \d0, q4 + vmul.s32 q0, q0, q4 + vmul.s32 \d1, \d1, q4 + vmul.s32 q1, q1, q4 + vshr.s32 \d0, \d0, #4 + vshr.s32 q0, q0, #4 + vshr.s32 \d1, \d1, #4 + vshr.s32 q1, q1, #4 + vaddw.s16 \d0, \d0, d4 + vaddw.s16 q0, q0, d5 + vaddw.s16 \d1, \d1, d6 + vaddw.s16 q1, q1, d7 + vmovn.i32 \d00, \d0 + vmovn.i32 \d01, q0 + vmovn.i32 \d10, \d1 + vmovn.i32 \d11, q1 + vrshl.s16 \d0, \d0, q13 // -intermediate_bits + vrshl.s16 \d1, \d1, q13 // -intermediate_bits + vadd.s16 \d0, \d0, q12 // PREP_BIAS >> intermediate_bits + vadd.s16 \d1, \d1, q12 // PREP_BIAS >> intermediate_bits + vmin.s16 \d0, \d0, q15 // bitdepth_max + vmin.s16 \d1, \d1, q15 // bitdepth_max + vmax.s16 \d0, \d0, q14 // 0 + vmax.s16 \d1, \d1, q14 // 0 +.endm + +.macro mask d0, d00, d01, d1, d10, d11 + vld1.8 {q7}, [r6, :128]! + vld1.16 {q0, q1}, [r2, :128]! + vneg.s8 q7, q7 + vld1.16 {q2, q3}, [r3, :128]! + vmovl.s8 q6, d14 + vmovl.s8 q7, d15 + vmovl.s16 q4, d12 + vmovl.s16 q5, d13 + vmovl.s16 q6, d14 + vmovl.s16 q7, d15 + vsubl.s16 \d0, d4, d0 + vsubl.s16 q0, d5, d1 + vsubl.s16 \d1, d6, d2 + vsubl.s16 q1, d7, d3 + vmul.s32 \d0, \d0, q4 + vmul.s32 q0, q0, q5 + vmul.s32 \d1, \d1, q6 + vmul.s32 q1, q1, q7 + vshr.s32 \d0, \d0, #6 + vshr.s32 q0, q0, #6 + vshr.s32 \d1, \d1, #6 + vshr.s32 q1, q1, #6 + vaddw.s16 \d0, \d0, d4 + vaddw.s16 q0, q0, d5 + vaddw.s16 \d1, \d1, d6 + vaddw.s16 q1, q1, d7 + vmovn.i32 \d00, \d0 + vmovn.i32 \d01, q0 + vmovn.i32 \d10, \d1 + vmovn.i32 \d11, q1 + vrshl.s16 \d0, \d0, q13 // -intermediate_bits + vrshl.s16 \d1, \d1, q13 // -intermediate_bits + vadd.s16 \d0, \d0, q12 // PREP_BIAS >> intermediate_bits + vadd.s16 \d1, \d1, q12 // PREP_BIAS >> intermediate_bits + vmin.s16 \d0, \d0, q15 // bitdepth_max + vmin.s16 \d1, \d1, q15 // bitdepth_max + vmax.s16 \d0, \d0, q14 // 0 + vmax.s16 \d1, \d1, q14 // 0 +.endm + +.macro bidir_fn type, bdmax +function \type\()_16bpc_neon, export=1 + push {r4-r7,lr} + ldrd r4, r5, [sp, #20] + ldr r6, [sp, #28] + clz r4, r4 +.ifnc \type, avg + ldr r7, [sp, #32] + vmov.i16 q14, #0 + vdup.16 q15, r7 // bitdepth_max +.endif +.ifc \type, w_avg + vpush {q4} +.endif +.ifc \type, mask + vpush {q4-q7} +.endif + clz r7, \bdmax + sub r7, r7, #18 // intermediate_bits = clz(bitdepth_max) - 18 +.ifc \type, avg + mov lr, #1 + movw r12, #2*PREP_BIAS + lsl lr, lr, r7 // 1 << intermediate_bits + neg r12, r12 // -2*PREP_BIAS + add r7, r7, #1 + sub r12, r12, lr // -2*PREP_BIAS - 1 << intermediate_bits + neg r7, r7 // -(intermediate_bits+1) + vdup.16 q12, r12 // -2*PREP_BIAS - 1 << intermediate_bits + vdup.16 q13, r7 // -(intermediate_bits+1) +.else + mov r12, #PREP_BIAS + lsr r12, r12, r7 // PREP_BIAS >> intermediate_bits + neg r7, r7 // -intermediate_bits + vdup.16 q12, r12 // PREP_BIAS >> intermediate_bits + vdup.16 q13, r7 // -intermediate_bits +.endif +.ifc \type, w_avg + vdup.32 q4, r6 + vneg.s32 q4, q4 +.endif + adr r7, L(\type\()_tbl) + sub r4, r4, #24 + \type q8, d16, d17, q9, d18, d19 + ldr r4, [r7, r4, lsl #2] + add r7, r7, r4 + bx r7 + + .align 2 +L(\type\()_tbl): + .word 1280f - L(\type\()_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_tbl) + CONFIG_THUMB + +40: + add r7, r0, r1 + lsl r1, r1, #1 +4: + subs r5, r5, #4 + vst1.16 {d16}, [r0, :64], r1 + vst1.16 {d17}, [r7, :64], r1 + vst1.16 {d18}, [r0, :64], r1 + vst1.16 {d19}, [r7, :64], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 4b +80: + add r7, r0, r1 + lsl r1, r1, #1 +8: + vst1.16 {q8}, [r0, :128], r1 + subs r5, r5, #2 + vst1.16 {q9}, [r7, :128], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 8b +160: +16: + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r1 + subs r5, r5, #2 + vst1.16 {q10, q11}, [r0, :128], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 16b +320: + add r7, r0, #32 +32: + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r1 + subs r5, r5, #1 + vst1.16 {q10, q11}, [r7, :128], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 32b +640: + add r7, r0, #32 + mov r12, #64 + sub r1, r1, #64 +64: + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r12 + \type q8, d16, d17, q9, d18, d19 + vst1.16 {q10, q11}, [r7, :128], r12 + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r1 + subs r5, r5, #1 + vst1.16 {q10, q11}, [r7, :128], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 64b +1280: + add r7, r0, #32 + mov r12, #64 + sub r1, r1, #192 +128: + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r12 + \type q8, d16, d17, q9, d18, d19 + vst1.16 {q10, q11}, [r7, :128], r12 + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r12 + \type q8, d16, d17, q9, d18, d19 + vst1.16 {q10, q11}, [r7, :128], r12 + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r12 + \type q8, d16, d17, q9, d18, d19 + vst1.16 {q10, q11}, [r7, :128], r12 + \type q10, d20, d21, q11, d22, d23 + vst1.16 {q8, q9}, [r0, :128], r1 + subs r5, r5, #1 + vst1.16 {q10, q11}, [r7, :128], r1 + ble 0f + \type q8, d16, d17, q9, d18, d19 + b 128b +0: +.ifc \type, mask + vpop {q4-q7} +.endif +.ifc \type, w_avg + vpop {q4} +.endif + pop {r4-r7,pc} +endfunc +.endm + +bidir_fn avg, r6 +bidir_fn w_avg, r7 +bidir_fn mask, r7 + + +.macro w_mask_fn type +function w_mask_\type\()_16bpc_neon, export=1 + push {r4-r10,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #96] + ldrd r6, r7, [sp, #104] + ldr r8, [sp, #112] + clz r9, r4 + adr lr, L(w_mask_\type\()_tbl) + vdup.16 q15, r8 // bitdepth_max + sub r9, r9, #24 + clz r8, r8 // clz(bitdepth_max) + ldr r9, [lr, r9, lsl #2] + add r9, lr, r9 + sub r8, r8, #12 // sh = intermediate_bits + 6 = clz(bitdepth_max) - 12 + mov r10, #PREP_BIAS*64 + neg r8, r8 // -sh + movw r12, #27615 // (64 + 1 - 38)<> mask_sh + vshr.u16 q7, q7, #10 + vadd.i32 q2, q2, q13 // += PREP_BIAS*64 + vadd.i32 q3, q3, q13 + vadd.i32 q4, q4, q13 + vadd.i32 q5, q5, q13 + vmovl.u16 q12, d12 + vmovl.u16 q13, d13 + vmla.i32 q2, q8, q12 // (tmp2-tmp1)*(64-m) + vmovl.u16 q12, d14 + vmla.i32 q3, q9, q13 + vmovl.u16 q13, d15 + vmla.i32 q4, q10, q12 + vmla.i32 q5, q11, q13 + vrshl.s32 q2, q2, q14 // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + vrshl.s32 q3, q3, q14 + vrshl.s32 q4, q4, q14 + vrshl.s32 q5, q5, q14 + vqmovun.s32 d4, q2 // iclip_pixel + vqmovun.s32 d5, q3 + vqmovun.s32 d6, q4 + vqmovun.s32 d7, q5 + vmin.u16 q2, q2, q15 // iclip_pixel + vmin.u16 q3, q3, q15 // iclip_pixel +.if \type == 444 + vmovn.i16 d12, q6 // 64 - m + vmovn.i16 d13, q7 + vsub.i16 q6, q1, q6 // m + vst1.8 {q6}, [r6, :128]! +.elseif \type == 422 + vpadd.i16 d12, d12, d13 // (64 - m) + (64 - n) (column wise addition) + vpadd.i16 d13, d14, d15 + vmovn.i16 d12, q6 + vhsub.u8 d12, d2, d12 // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + vst1.8 {d12}, [r6, :64]! +.elseif \type == 420 + vadd.i16 d12, d12, d13 // (64 - my1) + (64 - my2) (row wise addition) + vadd.i16 d13, d14, d15 + vpadd.i16 d12, d12, d13 // (128 - m) + (128 - n) (column wise addition) + vsub.i16 d12, d2, d12 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.i16 d12, q6, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.32 {d12[0]}, [r6, :32]! +.endif + vst1.16 {d4}, [r0, :64], r1 + vst1.16 {d5}, [r12, :64], r1 + vst1.16 {d6}, [r0, :64], r1 + vst1.16 {d7}, [r12, :64], r1 + bgt 4b + vpop {q4-q7} + pop {r4-r10,pc} +8: + vld1.16 {q2, q3}, [r2, :128]! // tmp1 + vld1.16 {q4, q5}, [r3, :128]! // tmp2 + subs r5, r5, #2 + vdup.32 q13, r10 // PREP_BIAS*64 + vabd.s16 q6, q2, q4 // abs(tmp1 - tmp2) + vabd.s16 q7, q3, q5 + vsubl.s16 q8, d8, d4 // tmp2 - tmp1 (requires 17 bit) + vsubl.s16 q9, d9, d5 + vsubl.s16 q10, d10, d6 + vsubl.s16 q11, d11, d7 + vqsub.u16 q6, q0, q6 // 27615 - abs() + vqsub.u16 q7, q0, q7 + vshll.s16 q5, d7, #6 // tmp1 << 6 + vshll.s16 q4, d6, #6 + vshll.s16 q3, d5, #6 + vshll.s16 q2, d4, #6 + vshr.u16 q6, q6, #10 // 64-m = (27615 - abs()) >> mask_sh + vshr.u16 q7, q7, #10 + vadd.i32 q2, q2, q13 // += PREP_BIAS*64 + vadd.i32 q3, q3, q13 + vadd.i32 q4, q4, q13 + vadd.i32 q5, q5, q13 + vmovl.u16 q12, d12 + vmovl.u16 q13, d13 + vmla.i32 q2, q8, q12 // (tmp2-tmp1)*(64-m) + vmovl.u16 q12, d14 + vmla.i32 q3, q9, q13 + vmovl.u16 q13, d15 + vmla.i32 q4, q10, q12 + vmla.i32 q5, q11, q13 + vrshl.s32 q2, q2, q14 // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + vrshl.s32 q3, q3, q14 + vrshl.s32 q4, q4, q14 + vrshl.s32 q5, q5, q14 + vqmovun.s32 d4, q2 // iclip_pixel + vqmovun.s32 d5, q3 + vqmovun.s32 d6, q4 + vqmovun.s32 d7, q5 + vmin.u16 q2, q2, q15 // iclip_pixel + vmin.u16 q3, q3, q15 // iclip_pixel +.if \type == 444 + vmovn.i16 d12, q6 // 64 - m + vmovn.i16 d13, q7 + vsub.i16 q6, q1, q6 // m + vst1.8 {q6}, [r6, :128]! +.elseif \type == 422 + vpadd.i16 d12, d12, d13 // (64 - m) + (64 - n) (column wise addition) + vpadd.i16 d13, d14, d15 + vmovn.i16 d12, q6 + vhsub.u8 d12, d2, d12 // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + vst1.8 {d12}, [r6, :64]! +.elseif \type == 420 + vadd.i16 q6, q6, q7 // (64 - my1) + (64 - my2) (row wise addition) + vpadd.i16 d12, d12, d13 // (128 - m) + (128 - n) (column wise addition) + vsub.i16 d12, d2, d12 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.i16 d12, q6, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.32 {d12[0]}, [r6, :32]! +.endif + vst1.16 {q2}, [r0, :128], r1 + vst1.16 {q3}, [r12, :128], r1 + bgt 8b + vpop {q4-q7} + pop {r4-r10,pc} +1280: +640: +320: +160: + sub r1, r1, r4, lsl #1 +.if \type == 444 + add lr, r6, r4 +.elseif \type == 422 + add lr, r6, r4, lsr #1 +.endif + add r7, r2, r4, lsl #1 + add r9, r3, r4, lsl #1 +161: + mov r8, r4 +16: + vld1.16 {q2}, [r2, :128]! // tmp1 + vld1.16 {q4}, [r3, :128]! // tmp2 + vld1.16 {q3}, [r7, :128]! + vld1.16 {q5}, [r9, :128]! + subs r8, r8, #8 + vdup.32 q13, r10 // PREP_BIAS*64 + vabd.s16 q6, q2, q4 // abs(tmp1 - tmp2) + vabd.s16 q7, q3, q5 + vsubl.s16 q8, d8, d4 // tmp2 - tmp1 (requires 17 bit) + vsubl.s16 q9, d9, d5 + vsubl.s16 q10, d10, d6 + vsubl.s16 q11, d11, d7 + vqsub.u16 q6, q0, q6 // 27615 - abs() + vqsub.u16 q7, q0, q7 + vshll.s16 q5, d7, #6 // tmp1 << 6 + vshll.s16 q4, d6, #6 + vshll.s16 q3, d5, #6 + vshll.s16 q2, d4, #6 + vshr.u16 q6, q6, #10 // 64-m = (27615 - abs()) >> mask_sh + vshr.u16 q7, q7, #10 + vadd.i32 q2, q2, q13 // += PREP_BIAS*64 + vadd.i32 q3, q3, q13 + vadd.i32 q4, q4, q13 + vadd.i32 q5, q5, q13 + vmovl.u16 q12, d12 + vmovl.u16 q13, d13 + vmla.i32 q2, q8, q12 // (tmp2-tmp1)*(64-m) + vmovl.u16 q12, d14 + vmla.i32 q3, q9, q13 + vmovl.u16 q13, d15 + vmla.i32 q4, q10, q12 + vmla.i32 q5, q11, q13 + vrshl.s32 q2, q2, q14 // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + vrshl.s32 q3, q3, q14 + vrshl.s32 q4, q4, q14 + vrshl.s32 q5, q5, q14 + vqmovun.s32 d4, q2 // iclip_pixel + vqmovun.s32 d5, q3 + vqmovun.s32 d6, q4 + vqmovun.s32 d7, q5 + vmin.u16 q2, q2, q15 // iclip_pixel + vmin.u16 q3, q3, q15 // iclip_pixel +.if \type == 444 + vmovn.i16 d12, q6 // 64 - m + vmovn.i16 d13, q7 + vsub.i16 q6, q1, q6 // m + vst1.8 {d12}, [r6, :64]! + vst1.8 {d13}, [lr, :64]! +.elseif \type == 422 + vpadd.i16 d12, d12, d13 // (64 - m) + (64 - n) (column wise addition) + vpadd.i16 d13, d14, d15 + vmovn.i16 d12, q6 + vhsub.u8 d12, d2, d12 // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + vst1.32 {d12[0]}, [r6, :32]! + vst1.32 {d12[1]}, [lr, :32]! +.elseif \type == 420 + vadd.i16 q6, q6, q7 // (64 - my1) + (64 - my2) (row wise addition) + vpadd.i16 d12, d12, d13 // (128 - m) + (128 - n) (column wise addition) + vsub.i16 d12, d2, d12 // (256 - sign) - ((128 - m) + (128 - n)) + vrshrn.i16 d12, q6, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + vst1.32 {d12[0]}, [r6, :32]! +.endif + vst1.16 {q2}, [r0, :128]! + vst1.16 {q3}, [r12, :128]! + bgt 16b + subs r5, r5, #2 + add r2, r2, r4, lsl #1 + add r3, r3, r4, lsl #1 + add r7, r7, r4, lsl #1 + add r9, r9, r4, lsl #1 +.if \type == 444 + add r6, r6, r4 + add lr, lr, r4 +.elseif \type == 422 + add r6, r6, r4, lsr #1 + add lr, lr, r4, lsr #1 +.endif + add r0, r0, r1 + add r12, r12, r1 + bgt 161b + vpop {q4-q7} + pop {r4-r10,pc} +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + +function blend_16bpc_neon, export=1 + push {r4-r5,lr} + ldrd r4, r5, [sp, #12] + clz lr, r3 + adr r3, L(blend_tbl) + sub lr, lr, #26 + ldr lr, [r3, lr, lsl #2] + add r3, r3, lr + bx r3 + + .align 2 +L(blend_tbl): + .word 320f - L(blend_tbl) + CONFIG_THUMB + .word 160f - L(blend_tbl) + CONFIG_THUMB + .word 80f - L(blend_tbl) + CONFIG_THUMB + .word 40f - L(blend_tbl) + CONFIG_THUMB + +40: + add r12, r0, r1 + lsl r1, r1, #1 +4: + vld1.8 {d4}, [r5, :64]! + vld1.16 {q1}, [r2, :128]! + vld1.16 {d0}, [r0, :64] + vneg.s8 d4, d4 // -m + subs r4, r4, #2 + vld1.16 {d1}, [r12, :64] + vmovl.s8 q2, d4 + vshl.i16 q2, q2, #9 // -m << 9 + vsub.i16 q1, q0, q1 // a - b + vqrdmulh.s16 q1, q1, q2 // ((a-b)*-m + 32) >> 6 + vadd.i16 q0, q0, q1 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d1}, [r12, :64], r1 + bgt 4b + pop {r4-r5,pc} +80: + add r12, r0, r1 + lsl r1, r1, #1 +8: + vld1.8 {q8}, [r5, :128]! + vld1.16 {q2, q3}, [r2, :128]! + vneg.s8 q9, q8 // -m + vld1.16 {q0}, [r0, :128] + vld1.16 {q1}, [r12, :128] + vmovl.s8 q8, d18 + vmovl.s8 q9, d19 + vshl.i16 q8, q8, #9 // -m << 9 + vshl.i16 q9, q9, #9 + vsub.i16 q2, q0, q2 // a - b + vsub.i16 q3, q1, q3 + subs r4, r4, #2 + vqrdmulh.s16 q2, q2, q8 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q3, q3, q9 + vadd.i16 q0, q0, q2 + vadd.i16 q1, q1, q3 + vst1.16 {q0}, [r0, :128], r1 + vst1.16 {q1}, [r12, :128], r1 + bgt 8b + pop {r4-r5,pc} +160: + add r12, r0, r1 + lsl r1, r1, #1 +16: + vld1.8 {q12, q13}, [r5, :128]! + vld1.16 {q8, q9}, [r2, :128]! + subs r4, r4, #2 + vneg.s8 q14, q12 // -m + vld1.16 {q0, q1}, [r0, :128] + vneg.s8 q15, q13 + vld1.16 {q10, q11}, [r2, :128]! + vmovl.s8 q12, d28 + vmovl.s8 q13, d29 + vmovl.s8 q14, d30 + vmovl.s8 q15, d31 + vld1.16 {q2, q3}, [r12, :128] + vshl.i16 q12, q12, #9 // -m << 9 + vshl.i16 q13, q13, #9 + vshl.i16 q14, q14, #9 + vshl.i16 q15, q15, #9 + vsub.i16 q8, q0, q8 // a - b + vsub.i16 q9, q1, q9 + vsub.i16 q10, q2, q10 + vsub.i16 q11, q3, q11 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q9, q9, q13 + vqrdmulh.s16 q10, q10, q14 + vqrdmulh.s16 q11, q11, q15 + vadd.i16 q0, q0, q8 + vadd.i16 q1, q1, q9 + vadd.i16 q2, q2, q10 + vst1.16 {q0, q1}, [r0, :128], r1 + vadd.i16 q3, q3, q11 + vst1.16 {q2, q3}, [r12, :128], r1 + bgt 16b + pop {r4-r5,pc} +320: + add r12, r0, #32 +32: + vld1.8 {q12, q13}, [r5, :128]! + vld1.16 {q8, q9}, [r2, :128]! + subs r4, r4, #1 + vneg.s8 q14, q12 // -m + vld1.16 {q0, q1}, [r0, :128] + vneg.s8 q15, q13 + vld1.16 {q10, q11}, [r2, :128]! + vmovl.s8 q12, d28 + vmovl.s8 q13, d29 + vmovl.s8 q14, d30 + vmovl.s8 q15, d31 + vld1.16 {q2, q3}, [r12, :128] + vshl.i16 q12, q12, #9 // -m << 9 + vshl.i16 q13, q13, #9 + vshl.i16 q14, q14, #9 + vshl.i16 q15, q15, #9 + vsub.i16 q8, q0, q8 // a - b + vsub.i16 q9, q1, q9 + vsub.i16 q10, q2, q10 + vsub.i16 q11, q3, q11 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q9, q9, q13 + vqrdmulh.s16 q10, q10, q14 + vqrdmulh.s16 q11, q11, q15 + vadd.i16 q0, q0, q8 + vadd.i16 q1, q1, q9 + vadd.i16 q2, q2, q10 + vst1.16 {q0, q1}, [r0, :128], r1 + vadd.i16 q3, q3, q11 + vst1.16 {q2, q3}, [r12, :128], r1 + bgt 32b + pop {r4-r5,pc} +endfunc + +function blend_h_16bpc_neon, export=1 + push {r4-r5,lr} + ldr r4, [sp, #12] + movrel r5, X(obmc_masks) + add r5, r5, r4 + sub r4, r4, r4, lsr #2 + clz lr, r3 + adr r12, L(blend_h_tbl) + sub lr, lr, #24 + ldr lr, [r12, lr, lsl #2] + add r12, r12, lr + bx r12 + + .align 2 +L(blend_h_tbl): + .word 1280f - L(blend_h_tbl) + CONFIG_THUMB + .word 640f - L(blend_h_tbl) + CONFIG_THUMB + .word 320f - L(blend_h_tbl) + CONFIG_THUMB + .word 160f - L(blend_h_tbl) + CONFIG_THUMB + .word 80f - L(blend_h_tbl) + CONFIG_THUMB + .word 40f - L(blend_h_tbl) + CONFIG_THUMB + .word 20f - L(blend_h_tbl) + CONFIG_THUMB + +20: + add r12, r0, r1 + lsl r1, r1, #1 +2: + vld2.8 {d4[], d5[]}, [r5, :16]! + vld1.16 {d2}, [r2, :64]! + vext.8 d4, d4, d5, #6 + subs r4, r4, #2 + vneg.s8 d4, d4 // -m + vld1.32 {d0[]}, [r0, :32] + vld1.32 {d0[1]}, [r12, :32] + vmovl.s8 q2, d4 + vshl.i16 d4, d4, #9 // -m << 9 + vsub.i16 d2, d0, d2 // a - b + vqrdmulh.s16 d2, d2, d4 // ((a-b)*-m + 32) >> 6 + vadd.i16 d0, d0, d2 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d0[1]}, [r12, :32], r1 + bgt 2b + pop {r4-r5,pc} +40: + add r12, r0, r1 + lsl r1, r1, #1 +4: + vld2.8 {d4[], d5[]}, [r5, :16]! + vld1.16 {q1}, [r2, :128]! + vext.8 d4, d4, d5, #4 + subs r4, r4, #2 + vneg.s8 d4, d4 // -m + vld1.16 {d0}, [r0, :64] + vld1.16 {d1}, [r12, :64] + vmovl.s8 q2, d4 + vshl.i16 q2, q2, #9 // -m << 9 + vsub.i16 q1, q0, q1 // a - b + vqrdmulh.s16 q1, q1, q2 // ((a-b)*-m + 32) >> 6 + vadd.i16 q0, q0, q1 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d1}, [r12, :64], r1 + bgt 4b + pop {r4-r5,pc} +80: + add r12, r0, r1 + lsl r1, r1, #1 +8: + vld2.8 {d16[], d17[]}, [r5, :16]! + vld1.16 {q2, q3}, [r2, :128]! + vneg.s8 q9, q8 // -m + vld1.16 {q0}, [r0, :128] + subs r4, r4, #2 + vmovl.s8 q8, d18 + vmovl.s8 q9, d19 + vld1.16 {q1}, [r12, :128] + vshl.i16 q8, q8, #9 // -m << 9 + vshl.i16 q9, q9, #9 + vsub.i16 q2, q0, q2 // a - b + vsub.i16 q3, q1, q3 + vqrdmulh.s16 q2, q2, q8 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q3, q3, q9 + vadd.i16 q0, q0, q2 + vadd.i16 q1, q1, q3 + vst1.16 {q0}, [r0, :128], r1 + vst1.16 {q1}, [r12, :128], r1 + bgt 8b + pop {r4-r5,pc} +160: + add r12, r0, r1 + lsl r1, r1, #1 +16: + vld2.8 {d24[], d25[]}, [r5, :16]! + vld1.16 {q8, q9}, [r2, :128]! + subs r4, r4, #2 + vneg.s8 q13, q12 // -m + vld1.16 {q0, q1}, [r0, :128] + vmovl.s8 q12, d26 + vld1.16 {q10, q11}, [r2, :128]! + vmovl.s8 q13, d27 + vld1.16 {q2, q3}, [r12, :128] + vshl.i16 q12, q12, #9 // -m << 9 + vshl.i16 q13, q13, #9 + vsub.i16 q8, q0, q8 // a - b + vsub.i16 q9, q1, q9 + vsub.i16 q10, q2, q10 + vsub.i16 q11, q3, q11 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q9, q9, q12 + vqrdmulh.s16 q10, q10, q13 + vqrdmulh.s16 q11, q11, q13 + vadd.i16 q0, q0, q8 + vadd.i16 q1, q1, q9 + vadd.i16 q2, q2, q10 + vadd.i16 q3, q3, q11 + vst1.16 {q0, q1}, [r0, :128], r1 + vst1.16 {q2, q3}, [r12, :128], r1 + bgt 16b + pop {r4-r5,pc} +1280: +640: +320: + sub r1, r1, r3, lsl #1 +321: + vld1.8 {d24[]}, [r5]! + mov r12, r3 + vneg.s8 d24, d24 // -m + vmovl.s8 q12, d24 + vshl.i16 q12, q12, #9 // -m << 9 +32: + vld1.16 {q8, q9}, [r2, :128]! + vld1.16 {q0, q1}, [r0, :128]! + subs r12, r12, #32 + vld1.16 {q10, q11}, [r2, :128]! + vld1.16 {q2, q3}, [r0, :128] + vsub.i16 q8, q0, q8 // a - b + vsub.i16 q9, q1, q9 + vsub.i16 q10, q2, q10 + vsub.i16 q11, q3, q11 + sub r0, r0, #32 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q9, q9, q12 + vqrdmulh.s16 q10, q10, q12 + vqrdmulh.s16 q11, q11, q12 + vadd.i16 q0, q0, q8 + vadd.i16 q1, q1, q9 + vadd.i16 q2, q2, q10 + vst1.16 {q0, q1}, [r0, :128]! + vadd.i16 q3, q3, q11 + vst1.16 {q2, q3}, [r0, :128]! + bgt 32b + subs r4, r4, #1 + add r0, r0, r1 + bgt 321b + pop {r4-r5,pc} +endfunc + +function blend_v_16bpc_neon, export=1 + push {r4,lr} + ldr r4, [sp, #8] + movrel lr, X(obmc_masks) + add lr, lr, r3 + clz r12, r3 + adr r3, L(blend_v_tbl) + sub r12, r12, #26 + ldr r12, [r3, r12, lsl #2] + add r3, r3, r12 + bx r3 + + .align 2 +L(blend_v_tbl): + .word 320f - L(blend_v_tbl) + CONFIG_THUMB + .word 160f - L(blend_v_tbl) + CONFIG_THUMB + .word 80f - L(blend_v_tbl) + CONFIG_THUMB + .word 40f - L(blend_v_tbl) + CONFIG_THUMB + .word 20f - L(blend_v_tbl) + CONFIG_THUMB + +20: + add r12, r0, r1 + lsl r1, r1, #1 + vld1.8 {d4[]}, [lr] + vneg.s8 d4, d4 // -m + vmovl.s8 q2, d4 + vshl.i16 d4, d4, #9 // -m << 9 +2: + vld1.32 {d2[]}, [r2, :32]! + vld1.16 {d0[]}, [r0, :16] + subs r4, r4, #2 + vld1.16 {d2[1]}, [r2, :16] + vld1.16 {d0[1]}, [r12, :16] + add r2, r2, #4 + vsub.i16 d2, d0, d2 // a - b + vqrdmulh.s16 d2, d2, d4 // ((a-b)*-m + 32) >> 6 + vadd.i16 d0, d0, d2 + vst1.16 {d0[0]}, [r0, :16], r1 + vst1.16 {d0[1]}, [r12, :16], r1 + bgt 2b + pop {r4,pc} +40: + vld1.32 {d4[]}, [lr, :32] + add r12, r0, r1 + vneg.s8 d4, d4 // -m + lsl r1, r1, #1 + vmovl.s8 q2, d4 + sub r1, r1, #4 + vshl.i16 q2, q2, #9 // -m << 9 +4: + vld1.16 {q1}, [r2, :128]! + vld1.16 {d0}, [r0, :64] + vld1.16 {d1}, [r12, :64] + subs r4, r4, #2 + vsub.i16 q1, q0, q1 // a - b + vqrdmulh.s16 q1, q1, q2 // ((a-b)*-m + 32) >> 6 + vadd.i16 q0, q0, q1 + vst1.32 {d0[0]}, [r0, :32]! + vst1.32 {d1[0]}, [r12, :32]! + vst1.16 {d0[2]}, [r0, :16], r1 + vst1.16 {d1[2]}, [r12, :16], r1 + bgt 4b + pop {r4,pc} +80: + vld1.8 {d16}, [lr, :64] + add r12, r0, r1 + vneg.s8 d16, d16 // -m + lsl r1, r1, #1 + vmovl.s8 q8, d16 + sub r1, r1, #8 + vshl.i16 q8, q8, #9 // -m << 9 +8: + vld1.16 {q2, q3}, [r2, :128]! + vld1.16 {q0}, [r0, :128] + vld1.16 {q1}, [r12, :128] + subs r4, r4, #2 + vsub.i16 q2, q0, q2 // a - b + vsub.i16 q3, q1, q3 + vqrdmulh.s16 q2, q2, q8 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q3, q3, q8 + vadd.i16 q0, q0, q2 + vadd.i16 q1, q1, q3 + vst1.16 {d0}, [r0, :64]! + vst1.16 {d2}, [r12, :64]! + vst1.32 {d1[0]}, [r0, :32], r1 + vst1.32 {d3[0]}, [r12, :32], r1 + bgt 8b + pop {r4,pc} +160: + vld1.8 {q12}, [lr, :128] + add r12, r0, r1 + vneg.s8 q13, q12 // -m + lsl r1, r1, #1 + vmovl.s8 q12, d26 + vmovl.s8 q13, d27 + vshl.i16 q12, q12, #9 // -m << 9 + vshl.i16 d26, d26, #9 +16: + vld1.16 {q8, q9}, [r2, :128]! + vld1.16 {d0, d1, d2}, [r0, :64] + subs r4, r4, #2 + vld1.16 {q10, q11}, [r2, :128]! + vsub.i16 q8, q0, q8 // a - b + vld1.16 {d4, d5, d6}, [r12, :64] + vsub.i16 d18, d2, d18 + vsub.i16 q10, q2, q10 + vsub.i16 d22, d6, d22 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 d18, d18, d26 + vqrdmulh.s16 q10, q10, q12 + vqrdmulh.s16 d22, d22, d26 + vadd.i16 q0, q0, q8 + vadd.i16 d2, d2, d18 + vadd.i16 q2, q2, q10 + vst1.16 {d0, d1, d2}, [r0, :64], r1 + vadd.i16 d6, d6, d22 + vst1.16 {d4, d5, d6}, [r12, :64], r1 + bgt 16b + pop {r4,pc} +320: + vld1.8 {d24, d25, d26}, [lr, :64] + vneg.s8 q14, q12 // -m + vneg.s8 d30, d26 + vmovl.s8 q12, d28 + vmovl.s8 q13, d29 + vmovl.s8 q14, d30 + sub r1, r1, #32 + vshl.i16 q12, q12, #9 // -m << 9 + vshl.i16 q13, q13, #9 + vshl.i16 q14, q14, #9 +32: + vld1.16 {q8, q9}, [r2, :128]! + vld1.16 {q0, q1}, [r0, :128]! + subs r4, r4, #1 + vld1.16 {q10}, [r2, :128] + vsub.i16 q8, q0, q8 // a - b + vld1.16 {q2}, [r0, :128] + sub r0, r0, #32 + vsub.i16 q9, q1, q9 + vsub.i16 q10, q2, q10 + vqrdmulh.s16 q8, q8, q12 // ((a-b)*-m + 32) >> 6 + vqrdmulh.s16 q9, q9, q13 + vqrdmulh.s16 q10, q10, q14 + vadd.i16 q0, q0, q8 + vadd.i16 q1, q1, q9 + vadd.i16 q2, q2, q10 + vst1.16 {q0, q1}, [r0, :128]! + add r2, r2, #32 + vst1.16 {q2}, [r0, :128], r1 + bgt 32b + pop {r4,pc} +endfunc + +// This has got the same signature as the put_8tap functions, +// and assumes that r9 is set to (clz(w)-24). +function put_neon + adr r10, L(put_tbl) + ldr r9, [r10, r9, lsl #2] + add r10, r10, r9 + bx r10 + + .align 2 +L(put_tbl): + .word 1280f - L(put_tbl) + CONFIG_THUMB + .word 640f - L(put_tbl) + CONFIG_THUMB + .word 320f - L(put_tbl) + CONFIG_THUMB + .word 16f - L(put_tbl) + CONFIG_THUMB + .word 80f - L(put_tbl) + CONFIG_THUMB + .word 4f - L(put_tbl) + CONFIG_THUMB + .word 2f - L(put_tbl) + CONFIG_THUMB + +2: + vld1.32 {d0[]}, [r2], r3 + vld1.32 {d1[]}, [r2], r3 + subs r5, r5, #2 + vst1.32 {d0[0]}, [r0, :32], r1 + vst1.32 {d1[1]}, [r0, :32], r1 + bgt 2b + pop {r4-r11,pc} +4: + vld1.16 {d0}, [r2], r3 + vld1.16 {d1}, [r2], r3 + subs r5, r5, #2 + vst1.16 {d0}, [r0, :64], r1 + vst1.16 {d1}, [r0, :64], r1 + bgt 4b + pop {r4-r11,pc} +80: + add r8, r0, r1 + lsl r1, r1, #1 + add r9, r2, r3 + lsl r3, r3, #1 +8: + vld1.16 {q0}, [r2], r3 + vld1.16 {q1}, [r9], r3 + subs r5, r5, #2 + vst1.16 {q0}, [r0, :128], r1 + vst1.16 {q1}, [r8, :128], r1 + bgt 8b + pop {r4-r11,pc} +16: + vld1.16 {q0, q1}, [r2], r3 + subs r5, r5, #1 + vst1.16 {q0, q1}, [r0, :128], r1 + bgt 16b + pop {r4-r11,pc} +320: + sub r1, r1, #32 + sub r3, r3, #32 +32: + vld1.16 {q0, q1}, [r2]! + vst1.16 {q0, q1}, [r0, :128]! + vld1.16 {q2, q3}, [r2], r3 + subs r5, r5, #1 + vst1.16 {q2, q3}, [r0, :128], r1 + bgt 32b + pop {r4-r11,pc} +640: + sub r1, r1, #96 + sub r3, r3, #96 +64: + vld1.16 {q8, q9}, [r2]! + vst1.16 {q8, q9}, [r0, :128]! + vld1.16 {q10, q11}, [r2]! + vst1.16 {q10, q11}, [r0, :128]! + vld1.16 {q12, q13}, [r2]! + vst1.16 {q12, q13}, [r0, :128]! + vld1.16 {q14, q15}, [r2], r3 + subs r5, r5, #1 + vst1.16 {q14, q15}, [r0, :128], r1 + bgt 64b + pop {r4-r11,pc} +1280: + sub r1, r1, #224 + sub r3, r3, #224 +128: + vld1.16 {q8, q9}, [r2]! + vst1.16 {q8, q9}, [r0, :128]! + vld1.16 {q10, q11}, [r2]! + vst1.16 {q10, q11}, [r0, :128]! + vld1.16 {q12, q13}, [r2]! + vst1.16 {q12, q13}, [r0, :128]! + vld1.16 {q14, q15}, [r2]! + vst1.16 {q14, q15}, [r0, :128]! + vld1.16 {q8, q9}, [r2]! + vst1.16 {q8, q9}, [r0, :128]! + vld1.16 {q10, q11}, [r2]! + vst1.16 {q10, q11}, [r0, :128]! + vld1.16 {q12, q13}, [r2]! + vst1.16 {q12, q13}, [r0, :128]! + vld1.16 {q14, q15}, [r2], r3 + subs r5, r5, #1 + vst1.16 {q14, q15}, [r0, :128], r1 + bgt 128b + pop {r4-r11,pc} +endfunc + +// This has got the same signature as the prep_8tap functions, +// and assumes that r9 is set to (clz(w)-24), r7 to intermediate_bits and +// r8 to w*2. +function prep_neon + adr r10, L(prep_tbl) + ldr r9, [r10, r9, lsl #2] + vdup.16 q15, r7 // intermediate_bits + vmov.i16 q14, #PREP_BIAS + add r10, r10, r9 + bx r10 + + .align 2 +L(prep_tbl): + .word 1280f - L(prep_tbl) + CONFIG_THUMB + .word 640f - L(prep_tbl) + CONFIG_THUMB + .word 320f - L(prep_tbl) + CONFIG_THUMB + .word 16f - L(prep_tbl) + CONFIG_THUMB + .word 80f - L(prep_tbl) + CONFIG_THUMB + .word 40f - L(prep_tbl) + CONFIG_THUMB + +40: + add r9, r1, r2 + lsl r2, r2, #1 +4: + vld1.16 {d0}, [r1], r2 + vld1.16 {d1}, [r9], r2 + subs r4, r4, #2 + vshl.s16 q0, q0, q15 + vsub.i16 q0, q0, q14 + vst1.16 {q0}, [r0, :128]! + bgt 4b + pop {r4-r11,pc} +80: + add r9, r1, r2 + lsl r2, r2, #1 +8: + vld1.16 {q0}, [r1], r2 + vld1.16 {q1}, [r9], r2 + subs r4, r4, #2 + vshl.s16 q0, q0, q15 + vshl.s16 q1, q1, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vst1.16 {q0, q1}, [r0, :128]! + bgt 8b + pop {r4-r11,pc} +16: + vld1.16 {q0, q1}, [r1], r2 + vshl.s16 q0, q0, q15 + vld1.16 {q2, q3}, [r1], r2 + subs r4, r4, #2 + vshl.s16 q1, q1, q15 + vshl.s16 q2, q2, q15 + vshl.s16 q3, q3, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vsub.i16 q2, q2, q14 + vst1.16 {q0, q1}, [r0, :128]! + vsub.i16 q3, q3, q14 + vst1.16 {q2, q3}, [r0, :128]! + bgt 16b + pop {r4-r11,pc} +320: + sub r2, r2, #32 +32: + vld1.16 {q0, q1}, [r1]! + subs r4, r4, #1 + vshl.s16 q0, q0, q15 + vld1.16 {q2, q3}, [r1], r2 + vshl.s16 q1, q1, q15 + vshl.s16 q2, q2, q15 + vshl.s16 q3, q3, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vsub.i16 q2, q2, q14 + vst1.16 {q0, q1}, [r0, :128]! + vsub.i16 q3, q3, q14 + vst1.16 {q2, q3}, [r0, :128]! + bgt 32b + pop {r4-r11,pc} +640: + sub r2, r2, #96 +64: + vld1.16 {q0, q1}, [r1]! + subs r4, r4, #1 + vshl.s16 q0, q0, q15 + vld1.16 {q2, q3}, [r1]! + vshl.s16 q1, q1, q15 + vld1.16 {q8, q9}, [r1]! + vshl.s16 q2, q2, q15 + vld1.16 {q10, q11}, [r1], r2 + vshl.s16 q3, q3, q15 + vshl.s16 q8, q8, q15 + vshl.s16 q9, q9, q15 + vshl.s16 q10, q10, q15 + vshl.s16 q11, q11, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vsub.i16 q2, q2, q14 + vsub.i16 q3, q3, q14 + vsub.i16 q8, q8, q14 + vst1.16 {q0, q1}, [r0, :128]! + vsub.i16 q9, q9, q14 + vst1.16 {q2, q3}, [r0, :128]! + vsub.i16 q10, q10, q14 + vst1.16 {q8, q9}, [r0, :128]! + vsub.i16 q11, q11, q14 + vst1.16 {q10, q11}, [r0, :128]! + bgt 64b + pop {r4-r11,pc} +1280: + sub r2, r2, #224 +128: + vld1.16 {q0, q1}, [r1]! + subs r4, r4, #1 + vshl.s16 q0, q0, q15 + vld1.16 {q2, q3}, [r1]! + vshl.s16 q1, q1, q15 + vld1.16 {q8, q9}, [r1]! + vshl.s16 q2, q2, q15 + vld1.16 {q10, q11}, [r1]! + vshl.s16 q3, q3, q15 + vshl.s16 q8, q8, q15 + vshl.s16 q9, q9, q15 + vshl.s16 q10, q10, q15 + vshl.s16 q11, q11, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vsub.i16 q2, q2, q14 + vsub.i16 q3, q3, q14 + vsub.i16 q8, q8, q14 + vst1.16 {q0, q1}, [r0, :128]! + vld1.16 {q0, q1}, [r1]! + vsub.i16 q9, q9, q14 + vsub.i16 q10, q10, q14 + vst1.16 {q2, q3}, [r0, :128]! + vld1.16 {q2, q3}, [r1]! + vsub.i16 q11, q11, q14 + vshl.s16 q0, q0, q15 + vst1.16 {q8, q9}, [r0, :128]! + vld1.16 {q8, q9}, [r1]! + vshl.s16 q1, q1, q15 + vshl.s16 q2, q2, q15 + vst1.16 {q10, q11}, [r0, :128]! + vld1.16 {q10, q11}, [r1], r2 + vshl.s16 q3, q3, q15 + vshl.s16 q8, q8, q15 + vshl.s16 q9, q9, q15 + vshl.s16 q10, q10, q15 + vshl.s16 q11, q11, q15 + vsub.i16 q0, q0, q14 + vsub.i16 q1, q1, q14 + vsub.i16 q2, q2, q14 + vsub.i16 q3, q3, q14 + vsub.i16 q8, q8, q14 + vst1.16 {q0, q1}, [r0, :128]! + vsub.i16 q9, q9, q14 + vst1.16 {q2, q3}, [r0, :128]! + vsub.i16 q10, q10, q14 + vst1.16 {q8, q9}, [r0, :128]! + vsub.i16 q11, q11, q14 + vst1.16 {q10, q11}, [r0, :128]! + bgt 128b + pop {r4-r11,pc} +endfunc + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + vld1.\wd {\d0[]}, [\s0], \strd + vld1.\wd {\d1[]}, [\s1], \strd +.ifnb \d2 + vld1.\wd {\d2[]}, [\s0], \strd + vld1.\wd {\d3[]}, [\s1], \strd +.endif +.ifnb \d4 + vld1.\wd {\d4[]}, [\s0], \strd +.endif +.ifnb \d5 + vld1.\wd {\d5[]}, [\s1], \strd +.endif +.ifnb \d6 + vld1.\wd {\d6[]}, [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + vld1.16 {\d0}, [\s0], \strd + vld1.16 {\d1}, [\s1], \strd +.ifnb \d2 + vld1.16 {\d2}, [\s0], \strd + vld1.16 {\d3}, [\s1], \strd +.endif +.ifnb \d4 + vld1.16 {\d4}, [\s0], \strd +.endif +.ifnb \d5 + vld1.16 {\d5}, [\s1], \strd +.endif +.ifnb \d6 + vld1.16 {\d6}, [\s0], \strd +.endif +.endm +.macro load_regpair s0, s1, strd, d0, d1, d2, d3, d4, d5 + vld1.16 {\d0, \d1}, [\s0], \strd +.ifnb \d2 + vld1.16 {\d2, \d3}, [\s1], \strd +.endif +.ifnb \d4 + vld1.16 {\d4, \d5}, [\s0], \strd +.endif +.endm +.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_16s16 s0, s1, strd, d0, d1, d2, d3, d4, d5 + load_regpair \s0, \s1, \strd, \d0, \d1, \d2, \d3, \d4, \d5 +.endm +.macro interleave_1_32 r0, r1, r2, r3, r4 + vext.8 \r0, \r0, \r1, #4 + vext.8 \r1, \r1, \r2, #4 +.ifnb \r3 + vext.8 \r2, \r2, \r3, #4 + vext.8 \r3, \r3, \r4, #4 +.endif +.endm +.macro vmin_u16 c, r0, r1, r2, r3 + vmin.u16 \r0, \r0, \c +.ifnb \r1 + vmin.u16 \r1, \r1, \c +.endif +.ifnb \r2 + vmin.u16 \r2, \r2, \c + vmin.u16 \r3, \r3, \c +.endif +.endm +.macro vsub_i16 c, r0, r1, r2, r3 + vsub.i16 \r0, \r0, \c +.ifnb \r1 + vsub.i16 \r1, \r1, \c +.endif +.ifnb \r2 + vsub.i16 \r2, \r2, \c + vsub.i16 \r3, \r3, \c +.endif +.endm +.macro vmull_vmlal_4 d, s0, s1, s2, s3 + vmull.s16 \d, \s0, d0[0] + vmlal.s16 \d, \s1, d0[1] + vmlal.s16 \d, \s2, d0[2] + vmlal.s16 \d, \s3, d0[3] +.endm +.macro vmull_vmlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7 + vmull.s16 \d, \s0, d0[0] + vmlal.s16 \d, \s1, d0[1] + vmlal.s16 \d, \s2, d0[2] + vmlal.s16 \d, \s3, d0[3] + vmlal.s16 \d, \s4, d1[0] + vmlal.s16 \d, \s5, d1[1] + vmlal.s16 \d, \s6, d1[2] + vmlal.s16 \d, \s7, d1[3] +.endm +.macro vqrshrun_s32 shift, q0, d0, q1, d1, q2, d2, q3, d3 + vqrshrun.s32 \d0, \q0, #\shift +.ifnb \q1 + vqrshrun.s32 \d1, \q1, #\shift +.endif +.ifnb \q2 + vqrshrun.s32 \d2, \q2, #\shift + vqrshrun.s32 \d3, \q3, #\shift +.endif +.endm +.macro vmovn_i32 q0, d0, q1, d1, q2, d2, q3, d3 + vmovn.i32 \d0, \q0 +.ifnb \q1 + vmovn.i32 \d1, \q1 +.endif +.ifnb \q2 + vmovn.i32 \d2, \q2 + vmovn.i32 \d3, \q3 +.endif +.endm +.macro vrshl_s32 shift, r0, r1, r2, r3 + vrshl.s32 \r0, \r0, \shift + vrshl.s32 \r1, \r1, \shift +.ifnb \r2 + vrshl.s32 \r2, \r2, \shift + vrshl.s32 \r3, \r3, \shift +.endif +.endm +.macro vst1_32 strd, r0, r1 + vst1.32 {\r0[0]}, [r0, :32], \strd + vst1.32 {\r0[1]}, [r9, :32], \strd +.ifnb \r1 + vst1.32 {\r1[0]}, [r0, :32], \strd + vst1.32 {\r1[1]}, [r9, :32], \strd +.endif +.endm +.macro vst1_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7 + vst1.16 {\r0}, [r0, \align], \strd + vst1.16 {\r1}, [r9, \align], \strd +.ifnb \r2 + vst1.16 {\r2}, [r0, \align], \strd + vst1.16 {\r3}, [r9, \align], \strd +.endif +.ifnb \r4 + vst1.16 {\r4}, [r0, \align], \strd + vst1.16 {\r5}, [r9, \align], \strd + vst1.16 {\r6}, [r0, \align], \strd + vst1.16 {\r7}, [r9, \align], \strd +.endif +.endm +.macro finalize type, q0, q1, d0, d1, q2, q3, d2, d3 +.ifc \type, put + vqrshrun_s32 6, \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3 + vmin_u16 q15, \q0, \q1 +.else + vrshl_s32 q14, \q0, \q1, \q2, \q3 // -(6-intermediate_bits) + vmovn_i32 \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3 + vsub_i16 q15, \q0, \q1 // PREP_BIAS +.endif +.endm +.macro shift_store_4 type, strd, q0, q1, d0, d1, q2, q3, d2, d3 + finalize \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3 + vst1_reg \strd, :64, \d0, \d1, \d2, \d3 +.endm +.macro shift_store_8 type, strd, q0, q1, d0, d1, q2, q3, d2, d3 + finalize \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3 + vst1_reg \strd, :128, \q0, \q1 +.endm +.macro shift_store_16 type, strd, q0, q1, d0, d1, q2, q3, d2, d3 + finalize \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3 + vst1.16 {\q0, \q1}, [r0, :128], \strd +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_16bpc_neon, export=1 + push {r4-r11,lr} + movw r9, \type_h + movw r10, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, bdmax, ds2, sr2 +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] +.ifc \bdmax, r8 + ldr r8, [sp, #52] +.endif + movw r11, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, r11 + mul \my, \my, r11 + add \mx, \mx, r9 // mx, 8tap_h, 4tap_h + add \my, \my, r10 // my, 8tap_v, 4tap_v + +.ifc \type, prep + lsl \d_strd, \w, #1 +.endif + + vdup.16 q15, \bdmax // bitdepth_max + clz \bdmax, \bdmax + clz r9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + tst \mx, #(0x7f << 14) + sub r9, r9, #24 + add lr, \bdmax, #6 // 6 + intermediate_bits + rsb r12, \bdmax, #6 // 6 - intermediate_bits + movrel r11, X(mc_subpel_filters), -8 + bne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + bne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx r10, \mx, #7, #7 + and \mx, \mx, #0x7f + it gt + movgt \mx, r10 + tst \my, #(0x7f << 14) + add \mx, r11, \mx, lsl #3 + bne L(\type\()_8tap_hv) + + adr r10, L(\type\()_8tap_h_tbl) + vdup.32 q14, r12 // 6 - intermediate_bits + ldr r9, [r10, r9, lsl #2] + vneg.s32 q14, q14 // -(6-intermediate_bits) +.ifc \type, put + vdup.16 q13, \bdmax // intermediate_bits +.else + vmov.i16 q13, #PREP_BIAS +.endif + add r10, r10, r9 +.ifc \type, put + vneg.s16 q13, q13 // -intermediate_bits +.endif + bx r10 + + .align 2 +L(\type\()_8tap_h_tbl): + .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB + +20: // 2xN h +.ifc \type, put + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 +2: + vld1.16 {q2}, [\src], \s_strd + vld1.16 {q3}, [\sr2], \s_strd + vext.8 d5, d4, d5, #2 + vext.8 d7, d6, d7, #2 + subs \h, \h, #2 + vtrn.32 d4, d6 + vtrn.32 d5, d7 + vmull.s16 q1, d4, d0[0] + vmlal.s16 q1, d5, d0[1] + vmlal.s16 q1, d6, d0[2] + vmlal.s16 q1, d7, d0[3] + vrshl.s32 q1, q1, q14 // -(6-intermediate_bits) + vqmovun.s32 d2, q1 + vrshl.s16 d2, d2, d26 // -intermediate_bits + vmin.u16 d2, d2, d30 + vst1.32 {d2[0]}, [\dst, :32], \d_strd + vst1.32 {d2[1]}, [\ds2, :32], \d_strd + bgt 2b + pop {r4-r11,pc} +.endif + +40: // 4xN h + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 +4: + vld1.16 {q8}, [\src], \s_strd + vld1.16 {q11}, [\sr2], \s_strd + vext.8 d18, d16, d17, #2 + vext.8 d19, d16, d17, #4 + vext.8 d20, d16, d17, #6 + vext.8 d24, d22, d23, #2 + vext.8 d25, d22, d23, #4 + vext.8 d21, d22, d23, #6 + subs \h, \h, #2 + vmull.s16 q2, d16, d0[0] + vmlal.s16 q2, d18, d0[1] + vmlal.s16 q2, d19, d0[2] + vmlal.s16 q2, d20, d0[3] + vmull.s16 q3, d22, d0[0] + vmlal.s16 q3, d24, d0[1] + vmlal.s16 q3, d25, d0[2] + vmlal.s16 q3, d21, d0[3] + vrshl.s32 q2, q2, q14 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) +.ifc \type, put + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vrshl.s16 q2, q2, q13 // -intermediate_bits + vmin.u16 q2, q2, q15 +.else + vmovn.s32 d4, q2 + vmovn.s32 d5, q3 + vsub.i16 q2, q2, q13 // PREP_BIAS +.endif + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d5}, [\ds2, :64], \d_strd + bgt 4b + pop {r4-r11,pc} + +80: +160: +320: +640: +1280: // 8xN, 16xN, 32xN, ... h + vpush {q4-q5} + vld1.8 {d0}, [\mx, :64] + sub \src, \src, #6 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 + + sub \s_strd, \s_strd, \w, lsl #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, lsl #1 +.endif +81: + vld1.16 {q8, q9}, [\src]! + vld1.16 {q10, q11}, [\sr2]! + mov \mx, \w + +8: + vmull.s16 q1, d16, d0[0] + vmull.s16 q2, d17, d0[0] + vmull.s16 q3, d20, d0[0] + vmull.s16 q4, d21, d0[0] +.irpc i, 1234567 + vext.8 q12, q8, q9, #(2*\i) + vext.8 q5, q10, q11, #(2*\i) +.if \i < 4 + vmlal.s16 q1, d24, d0[\i] + vmlal.s16 q2, d25, d0[\i] + vmlal.s16 q3, d10, d0[\i] + vmlal.s16 q4, d11, d0[\i] +.else + vmlal.s16 q1, d24, d1[\i-4] + vmlal.s16 q2, d25, d1[\i-4] + vmlal.s16 q3, d10, d1[\i-4] + vmlal.s16 q4, d11, d1[\i-4] +.endif +.endr + subs \mx, \mx, #8 + vrshl.s32 q1, q1, q14 // -(6-intermediate_bits) + vrshl.s32 q2, q2, q14 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) + vrshl.s32 q4, q4, q14 // -(6-intermediate_bits) +.ifc \type, put + vqmovun.s32 d2, q1 + vqmovun.s32 d3, q2 + vqmovun.s32 d4, q3 + vqmovun.s32 d5, q4 + vrshl.s16 q1, q1, q13 // -intermediate_bits + vrshl.s16 q2, q2, q13 // -intermediate_bits + vmin.u16 q1, q1, q15 + vmin.u16 q2, q2, q15 +.else + vmovn.s32 d2, q1 + vmovn.s32 d3, q2 + vmovn.s32 d4, q3 + vmovn.s32 d5, q4 + vsub.i16 q1, q1, q13 // PREP_BIAS + vsub.i16 q2, q2, q13 // PREP_BIAS +.endif + vst1.16 {q1}, [\dst, :128]! + vst1.16 {q2}, [\ds2, :128]! + ble 9f + + vmov q8, q9 + vmov q10, q11 + vld1.16 {q9}, [\src]! + vld1.16 {q11}, [\sr2]! + b 8b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + bgt 81b + vpop {q4-q5} + pop {r4-r11,pc} + + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx r10, \my, #7, #7 + and \my, \my, #0x7f + it gt + movgt \my, r10 + add \my, r11, \my, lsl #3 + +.ifc \type, prep + vdup.32 q14, r12 // 6 - intermediate_bits + vmov.i16 q15, #PREP_BIAS +.endif + adr r10, L(\type\()_8tap_v_tbl) + ldr r9, [r10, r9, lsl #2] +.ifc \type, prep + vneg.s32 q14, q14 // -(6-intermediate_bits) +.endif + add r10, r10, r9 + bx r10 + + .align 2 +L(\type\()_8tap_v_tbl): + .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB + +20: // 2xN v +.ifc \type, put + bgt 28f + + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + // 2x2 v + load_32 \src, \sr2, \s_strd, d1, d2, d3, d4, d5 + interleave_1_32 d1, d2, d3, d4, d5 + bgt 24f + vmull_vmlal_4 q8, d1, d2, d3, d4 + vqrshrun_s32 6, q8, d16 + vmin_u16 d30, d16 + vst1_32 \d_strd, d16 + pop {r4-r11,pc} + +24: // 2x4 v + load_32 \sr2, \src, \s_strd, d6, d7 + interleave_1_32 d5, d6, d7 + vmull_vmlal_4 q8, d1, d2, d3, d4 + vmull_vmlal_4 q9, d3, d4, d5, d6 + vqrshrun_s32 6, q8, d16, q9, d17 + vmin_u16 q15, q8 + vst1_32 \d_strd, d16, d17 + pop {r4-r11,pc} + +28: // 2x6, 2x8, 2x12, 2x16 v + vld1.8 {d0}, [\my, :64] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + vmovl.s8 q0, d0 + + load_32 \src, \sr2, \s_strd, d2, d3, d4, d5, d6, d7, d16 + interleave_1_32 d2, d3, d4, d5, d6 + interleave_1_32 d6, d7, d16 +216: + subs \h, \h, #4 + load_32 \sr2, \src, \s_strd, d17, d18, d19, d20 + interleave_1_32 d16, d17, d18, d19, d20 + vmull_vmlal_8 q13, d2, d3, d4, d5, d6, d7, d16, d17 + vmull_vmlal_8 q1, d4, d5, d6, d7, d16, d17, d18, d19 + vqrshrun_s32 6, q13, d26, q1, d27 + vmin_u16 q15, q13 + vst1_32 \d_strd, d26, d27 + ble 0f + cmp \h, #2 + vmov q1, q3 + vmov q2, q8 + vmov q3, q9 + vmov d16, d20 + beq 26f + b 216b +26: + load_32 \sr2, \src, \s_strd, d17, d18 + interleave_1_32 d16, d17, d18 + vmull_vmlal_8 q13, d2, d3, d4, d5, d6, d7, d16, d17 + vqrshrun_s32 6, q13, d26 + vmin_u16 d30, d26 + vst1_32 \d_strd, d26 +0: + pop {r4-r11,pc} +.endif + +40: + bgt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_reg \src, \sr2, \s_strd, d1, d2, d3, d4, d5 + vmull_vmlal_4 q8, d1, d2, d3, d4 + vmull_vmlal_4 q9, d2, d3, d4, d5 + shift_store_4 \type, \d_strd, q8, q9, d16, d17 + ble 0f + load_reg \sr2, \src, \s_strd, d6, d7 + vmull_vmlal_4 q8, d3, d4, d5, d6 + vmull_vmlal_4 q9, d4, d5, d6, d7 + shift_store_4 \type, \d_strd, q8, q9, d16, d17 +0: + pop {r4-r11,pc} + +480: // 4x6, 4x8, 4x12, 4x16 v + vld1.8 {d0}, [\my, :64] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_reg \src, \sr2, \s_strd, d16, d17, d18, d19, d20, d21, d22 + +48: + subs \h, \h, #4 + load_reg \sr2, \src, \s_strd, d23, d24, d25, d26 + vmull_vmlal_8 q1, d16, d17, d18, d19, d20, d21, d22, d23 + vmull_vmlal_8 q2, d17, d18, d19, d20, d21, d22, d23, d24 + vmull_vmlal_8 q3, d18, d19, d20, d21, d22, d23, d24, d25 + vmull_vmlal_8 q8, d19, d20, d21, d22, d23, d24, d25, d26 + shift_store_4 \type, \d_strd, q1, q2, d2, d3, q3, q8, d4, d5 + ble 0f + cmp \h, #2 + vmov q8, q10 + vmov q9, q11 + vmov q10, q12 + vmov d22, d26 + beq 46f + b 48b +46: + load_reg \sr2, \src, \s_strd, d23, d24 + vmull_vmlal_8 q1, d16, d17, d18, d19, d20, d21, d22, d23 + vmull_vmlal_8 q2, d17, d18, d19, d20, d21, d22, d23, d24 + shift_store_4 \type, \d_strd, q1, q2, d2, d3 +0: + pop {r4-r11,pc} + +80: + bgt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + + load_reg \src, \sr2, \s_strd, q1, q2, q3, q8, q9 + vmull_vmlal_4 q10, d2, d4, d6, d16 + vmull_vmlal_4 q11, d3, d5, d7, d17 + vmull_vmlal_4 q12, d4, d6, d16, d18 + vmull_vmlal_4 q13, d5, d7, d17, d19 + shift_store_8 \type, \d_strd, q10, q11, d20, d21, q12, q13, d22, d23 + ble 0f + load_reg \sr2, \src, \s_strd, q10, q11 + vmull_vmlal_4 q1, d6, d16, d18, d20 + vmull_vmlal_4 q2, d7, d17, d19, d21 + vmull_vmlal_4 q12, d16, d18, d20, d22 + vmull_vmlal_4 q13, d17, d19, d21, d23 + shift_store_8 \type, \d_strd, q1, q2, d2, d3, q12, q13, d4, d5 +0: + pop {r4-r11,pc} + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + vpush {q4-q7} + vld1.8 {d0}, [\my, :64] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + vmovl.s8 q0, d0 + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_reg \src, \sr2, \s_strd, q5, q6, q7, q8, q9, q10, q11 + +88: + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, q12, q13 + vmull_vmlal_8 q1, d10, d12, d14, d16, d18, d20, d22, d24 + vmull_vmlal_8 q2, d11, d13, d15, d17, d19, d21, d23, d25 + vmull_vmlal_8 q3, d12, d14, d16, d18, d20, d22, d24, d26 + vmull_vmlal_8 q4, d13, d15, d17, d19, d21, d23, d25, d27 + shift_store_8 \type, \d_strd, q1, q2, d2, d3, q3, q4, d4, d5 + ble 9f + subs \h, \h, #2 + load_reg \sr2, \src, \s_strd, q1, q2 + vmull_vmlal_8 q3, d14, d16, d18, d20, d22, d24, d26, d2 + vmull_vmlal_8 q4, d15, d17, d19, d21, d23, d25, d27, d3 + vmull_vmlal_8 q5, d16, d18, d20, d22, d24, d26, d2, d4 + vmull_vmlal_8 q6, d17, d19, d21, d23, d25, d27, d3, d5 + shift_store_8 \type, \d_strd, q3, q4, d6, d7, q5, q6, d8, d9 + ble 9f + vmov q5, q9 + vmov q6, q10 + vmov q7, q11 + vmov q8, q12 + vmov q9, q13 + vmov q10, q1 + vmov q11, q2 + b 88b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + vpop {q4-q7} + pop {r4-r11,pc} + +160: + bgt 1680b + + // 16x2, 16x4 v + vpush {q6-q7} + add \my, \my, #2 + vld1.32 {d0[]}, [\my] + sub \src, \src, \s_strd + vmovl.s8 q0, d0 + + load_16s16 \src, \src, \s_strd, q6, q7, q8, q9, q10, q11 +16: + load_16s16 \src, \src, \s_strd, q12, q13 + subs \h, \h, #1 + vmull_vmlal_4 q1, d12, d16, d20, d24 + vmull_vmlal_4 q2, d13, d17, d21, d25 + vmull_vmlal_4 q3, d14, d18, d22, d26 + vmull_vmlal_4 q6, d15, d19, d23, d27 + shift_store_16 \type, \d_strd, q1, q2, d2, d3, q3, q6, d4, d5 + ble 0f + vmov q6, q8 + vmov q7, q9 + vmov q8, q10 + vmov q9, q11 + vmov q10, q12 + vmov q11, q13 + b 16b +0: + vpop {q6-q7} + pop {r4-r11,pc} + + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx r10, \my, #7, #7 + and \my, \my, #0x7f + it gt + movgt \my, r10 +4: + add \my, r11, \my, lsl #3 + + adr r10, L(\type\()_8tap_hv_tbl) + neg r12, r12 // -(6-intermediate_bits) + ldr r9, [r10, r9, lsl #2] + vdup.32 q14, r12 // -(6-intermediate_bits) +.ifc \type, put + neg r8, lr // -(6+intermeidate_bits) +.else + vmov.i16 q13, #PREP_BIAS +.endif + add r10, r10, r9 +.ifc \type, put + vdup.32 q13, r8 // -(6+intermediate_bits) +.endif + bx r10 + + .align 2 +L(\type\()_8tap_hv_tbl): + .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB + +20: +.ifc \type, put + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + bgt 280f + add \my, \my, #2 + vld1.32 {d2[]}, [\my] + + // 2x2, 2x4 hv + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + vld1.16 {q11}, [\src], \s_strd + vext.8 d24, d22, d23, #2 + vmull.s16 q11, d22, d0 + vmull.s16 q12, d24, d0 + vpadd.s32 d22, d22, d23 + vpadd.s32 d23, d24, d25 + vpadd.s32 d22, d22, d23 + vrshl.s32 d16, d22, d28 // -(6-intermediate_bits) + vmovn.i32 d16, q8 + bl L(\type\()_8tap_filter_2) + + vext.8 d16, d16, d16, #4 + vext.8 d16, d16, d24, #4 + vmov d17, d24 + +2: + bl L(\type\()_8tap_filter_2) + + vext.8 d18, d17, d24, #4 + vmull.s16 q2, d16, d2[0] + vmlal.s16 q2, d17, d2[1] + vmlal.s16 q2, d18, d2[2] + vmlal.s16 q2, d24, d2[3] + + vrshl.s32 q2, q2, q13 // -(6+intermediate_bits) + vqmovun.s32 d4, q2 + vmin.u16 d4, d4, d30 + subs \h, \h, #2 + vst1.32 {d4[0]}, [\dst, :32], \d_strd + vst1.32 {d4[1]}, [\ds2, :32], \d_strd + ble 0f + vmov d16, d18 + vmov d17, d24 + b 2b + +280: // 2x8, 2x16, 2x32 hv + vld1.8 {d2}, [\my, :64] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + vld1.16 {q11}, [\src], \s_strd + vext.8 d24, d22, d23, #2 + vmull.s16 q11, d22, d0 + vmull.s16 q12, d24, d0 + vpadd.s32 d22, d22, d23 + vpadd.s32 d23, d24, d25 + vpadd.s32 d22, d22, d23 + vrshl.s32 d16, d22, d28 // -(6-intermediate_bits) + vmovn.i32 d16, q8 + + bl L(\type\()_8tap_filter_2) + + vext.8 d16, d16, d16, #4 + vext.8 d16, d16, d24, #4 + vmov d17, d24 + bl L(\type\()_8tap_filter_2) + vext.8 d18, d17, d24, #4 + vmov d19, d24 + bl L(\type\()_8tap_filter_2) + vext.8 d20, d19, d24, #4 + vmov d21, d24 + +28: + bl L(\type\()_8tap_filter_2) + vext.8 d22, d21, d24, #4 + vmull.s16 q3, d16, d2[0] + vmlal.s16 q3, d17, d2[1] + vmlal.s16 q3, d18, d2[2] + vmlal.s16 q3, d19, d2[3] + vmlal.s16 q3, d20, d3[0] + vmlal.s16 q3, d21, d3[1] + vmlal.s16 q3, d22, d3[2] + vmlal.s16 q3, d24, d3[3] + + vrshl.s32 q3, q3, q13 // -(6+intermediate_bits) + vqmovun.s32 d6, q3 + vmin.u16 d6, d6, d30 + subs \h, \h, #2 + vst1.32 {d6[0]}, [\dst, :32], \d_strd + vst1.32 {d6[1]}, [\ds2, :32], \d_strd + ble 0f + vmov q8, q9 + vmov q9, q10 + vmov d20, d22 + vmov d21, d24 + b 28b +0: + pop {r4-r11,pc} + +L(\type\()_8tap_filter_2): + vld1.16 {q11}, [\sr2], \s_strd + vld1.16 {q12}, [\src], \s_strd + vext.8 d23, d22, d23, #2 + vext.8 d25, d24, d25, #2 + vtrn.32 q11, q12 + vmull.s16 q3, d22, d0[0] + vmlal.s16 q3, d23, d0[1] + vmlal.s16 q3, d24, d0[2] + vmlal.s16 q3, d25, d0[3] + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) + vmovn.i32 d24, q3 + bx lr +.endif + +40: + add \mx, \mx, #2 + vld1.32 {d0[]}, [\mx] + bgt 480f + add \my, \my, #2 + vld1.32 {d2[]}, [\my] + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + // 4x2, 4x4 hv + vld1.16 {q11}, [\src], \s_strd + vext.8 d24, d22, d23, #2 + vext.8 d25, d22, d23, #4 + vext.8 d23, d22, d23, #6 + vmull.s16 q10, d22, d0[0] + vmlal.s16 q10, d24, d0[1] + vmlal.s16 q10, d25, d0[2] + vmlal.s16 q10, d23, d0[3] + vrshl.s32 q10, q10, q14 // -(6-intermediate_bits) + vmovn.i32 d17, q10 + + bl L(\type\()_8tap_filter_4) + vmov q9, q12 + +4: + bl L(\type\()_8tap_filter_4) + vmull.s16 q2, d17, d2[0] + vmlal.s16 q2, d18, d2[1] + vmlal.s16 q2, d19, d2[2] + vmlal.s16 q2, d24, d2[3] + vmull.s16 q3, d18, d2[0] + vmlal.s16 q3, d19, d2[1] + vmlal.s16 q3, d24, d2[2] + vmlal.s16 q3, d25, d2[3] +.ifc \type, put + vrshl.s32 q2, q2, q13 // -(6+intermediate_bits) + vrshl.s32 q3, q3, q13 // -(6+intermediate_bits) + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vmin.u16 q2, q2, q15 +.else + vrshrn.i32 d4, q2, #6 + vrshrn.i32 d5, q3, #6 + vsub.i16 q2, q2, q13 // PREP_BIAS +.endif + subs \h, \h, #2 + + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d5}, [\ds2, :64], \d_strd + ble 0f + vmov d17, d19 + vmov q9, q12 + b 4b +0: + pop {r4-r11,pc} + +480: // 4x8, 4x16, 4x32 hv + vpush {d13-d15} + vld1.8 {d2}, [\my, :64] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + + vld1.16 {q11}, [\src], \s_strd + vext.8 d24, d22, d23, #2 + vext.8 d25, d22, d23, #4 + vext.8 d23, d22, d23, #6 + vmull.s16 q10, d22, d0[0] + vmlal.s16 q10, d24, d0[1] + vmlal.s16 q10, d25, d0[2] + vmlal.s16 q10, d23, d0[3] + vrshl.s32 q10, q10, q14 // -(6-intermediate_bits) + vmovn.i32 d13, q10 + + bl L(\type\()_8tap_filter_4) + vmov q7, q12 + bl L(\type\()_8tap_filter_4) + vmov q8, q12 + bl L(\type\()_8tap_filter_4) + vmov q9, q12 + +48: + bl L(\type\()_8tap_filter_4) + vmull.s16 q2, d13, d2[0] + vmlal.s16 q2, d14, d2[1] + vmlal.s16 q2, d15, d2[2] + vmlal.s16 q2, d16, d2[3] + vmlal.s16 q2, d17, d3[0] + vmlal.s16 q2, d18, d3[1] + vmlal.s16 q2, d19, d3[2] + vmlal.s16 q2, d24, d3[3] + vmull.s16 q3, d14, d2[0] + vmlal.s16 q3, d15, d2[1] + vmlal.s16 q3, d16, d2[2] + vmlal.s16 q3, d17, d2[3] + vmlal.s16 q3, d18, d3[0] + vmlal.s16 q3, d19, d3[1] + vmlal.s16 q3, d24, d3[2] + vmlal.s16 q3, d25, d3[3] +.ifc \type, put + vrshl.s32 q2, q2, q13 // -(6+intermediate_bits) + vrshl.s32 q3, q3, q13 // -(6+intermediate_bits) + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vmin.u16 q2, q2, q15 +.else + vrshrn.i32 d4, q2, #6 + vrshrn.i32 d5, q3, #6 + vsub.i16 q2, q2, q13 // PREP_BIAS +.endif + subs \h, \h, #2 + vst1.16 {d4}, [\dst, :64], \d_strd + vst1.16 {d5}, [\ds2, :64], \d_strd + ble 0f + vmov d13, d15 + vmov q7, q8 + vmov q8, q9 + vmov q9, q12 + b 48b +0: + vpop {d13-d15} + pop {r4-r11,pc} + +L(\type\()_8tap_filter_4): + vld1.16 {q10}, [\sr2], \s_strd + vld1.16 {q11}, [\src], \s_strd + vext.8 d24, d20, d21, #2 + vext.8 d25, d20, d21, #4 + vext.8 d21, d20, d21, #6 + vmull.s16 q3, d20, d0[0] + vmlal.s16 q3, d24, d0[1] + vmlal.s16 q3, d25, d0[2] + vmlal.s16 q3, d21, d0[3] + vext.8 d24, d22, d23, #2 + vext.8 d25, d22, d23, #4 + vext.8 d23, d22, d23, #6 + vmull.s16 q10, d22, d0[0] + vmlal.s16 q10, d24, d0[1] + vmlal.s16 q10, d25, d0[2] + vmlal.s16 q10, d23, d0[3] + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) + vrshl.s32 q10, q10, q14 // -(6-intermediate_bits) + vmovn.i32 d24, q3 + vmovn.i32 d25, q10 + bx lr + +80: +160: +320: + bgt 880f + add \my, \my, #2 + vld1.8 {d0}, [\mx, :64] + vld1.32 {d2[]}, [\my] + sub \src, \src, #6 + sub \src, \src, \s_strd + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + vld1.16 {q11, q12}, [\src], \s_strd + vmull.s16 q2, d22, d0[0] + vmull.s16 q3, d23, d0[0] + vdup.32 q14, r12 // -(6-intermediate_bits) +.irpc i, 1234567 + vext.8 q10, q11, q12, #(2*\i) +.if \i < 4 + vmlal.s16 q2, d20, d0[\i] + vmlal.s16 q3, d21, d0[\i] +.else + vmlal.s16 q2, d20, d1[\i - 4] + vmlal.s16 q3, d21, d1[\i - 4] +.endif +.endr + vrshl.s32 q2, q2, q14 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) + vmovn.i32 d16, q2 + vmovn.i32 d17, q3 + + bl L(\type\()_8tap_filter_8) + vmov q9, q11 + vmov q10, q12 + +8: + bl L(\type\()_8tap_filter_8) + vmull.s16 q2, d16, d2[0] + vmull.s16 q3, d17, d2[0] + vmull.s16 q13, d18, d2[0] + vmull.s16 q14, d19, d2[0] +.ifc \type, put + vdup.32 q8, r8 // -(6+intermediate_bits) +.endif + vmlal.s16 q2, d18, d2[1] + vmlal.s16 q3, d19, d2[1] + vmlal.s16 q13, d20, d2[1] + vmlal.s16 q14, d21, d2[1] + vmlal.s16 q2, d20, d2[2] + vmlal.s16 q3, d21, d2[2] + vmlal.s16 q13, d22, d2[2] + vmlal.s16 q14, d23, d2[2] + vmlal.s16 q2, d22, d2[3] + vmlal.s16 q3, d23, d2[3] + vmlal.s16 q13, d24, d2[3] + vmlal.s16 q14, d25, d2[3] +.ifc \type, put + vdup.16 q9, \bdmax // bitdepth_max + vrshl.s32 q2, q2, q8 // -(6+intermediate_bits) + vrshl.s32 q3, q3, q8 // -(6+intermediate_bits) + vrshl.s32 q13, q13, q8 // -(6+intermediate_bits) + vrshl.s32 q14, q14, q8 // -(6+intermediate_bits) + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vqmovun.s32 d6, q13 + vqmovun.s32 d7, q14 + vmin.u16 q2, q2, q15 + vmin.u16 q3, q3, q15 +.else + vmov.i16 q9, #PREP_BIAS + vrshrn.i32 d4, q2, #6 + vrshrn.i32 d5, q3, #6 + vrshrn.i32 d6, q13, #6 + vrshrn.i32 d7, q14, #6 + vsub.i16 q2, q2, q9 // PREP_BIAS + vsub.i16 q3, q3, q9 // PREP_BIAS +.endif + subs \h, \h, #2 + vst1.16 {q2}, [\dst, :128], \d_strd + vst1.16 {q3}, [\ds2, :128], \d_strd + ble 9f + vmov q8, q10 + vmov q9, q11 + vmov q10, q12 + b 8b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 164b +0: + pop {r4-r11,pc} + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + vpush {q4-q7} + vld1.8 {d0}, [\mx, :64] + vld1.8 {d2}, [\my, :64] + sub \src, \src, #6 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + vmovl.s8 q0, d0 + vmovl.s8 q1, d2 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + vld1.16 {q11, q12}, [\src], \s_strd + vmull.s16 q2, d22, d0[0] + vmull.s16 q3, d23, d0[0] + vdup.32 q14, r12 // -(6-intermediate_bits) +.irpc i, 1234567 + vext.8 q10, q11, q12, #(2*\i) +.if \i < 4 + vmlal.s16 q2, d20, d0[\i] + vmlal.s16 q3, d21, d0[\i] +.else + vmlal.s16 q2, d20, d1[\i - 4] + vmlal.s16 q3, d21, d1[\i - 4] +.endif +.endr + vrshl.s32 q2, q2, q14 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q14 // -(6-intermediate_bits) + vmovn.i32 d8, q2 + vmovn.i32 d9, q3 + + bl L(\type\()_8tap_filter_8) + vmov q5, q11 + vmov q6, q12 + bl L(\type\()_8tap_filter_8) + vmov q7, q11 + vmov q8, q12 + bl L(\type\()_8tap_filter_8) + vmov q9, q11 + vmov q10, q12 + +88: + bl L(\type\()_8tap_filter_8) + vmull.s16 q2, d8, d2[0] + vmull.s16 q3, d9, d2[0] + vmull.s16 q13, d10, d2[0] + vmull.s16 q14, d11, d2[0] +.ifc \type, put + vdup.32 q4, r8 // -(6+intermediate_bits) +.endif + vmlal.s16 q2, d10, d2[1] + vmlal.s16 q3, d11, d2[1] + vmlal.s16 q13, d12, d2[1] + vmlal.s16 q14, d13, d2[1] + vmlal.s16 q2, d12, d2[2] + vmlal.s16 q3, d13, d2[2] + vmlal.s16 q13, d14, d2[2] + vmlal.s16 q14, d15, d2[2] + vmlal.s16 q2, d14, d2[3] + vmlal.s16 q3, d15, d2[3] + vmlal.s16 q13, d16, d2[3] + vmlal.s16 q14, d17, d2[3] + vmlal.s16 q2, d16, d3[0] + vmlal.s16 q3, d17, d3[0] + vmlal.s16 q13, d18, d3[0] + vmlal.s16 q14, d19, d3[0] + vmlal.s16 q2, d18, d3[1] + vmlal.s16 q3, d19, d3[1] + vmlal.s16 q13, d20, d3[1] + vmlal.s16 q14, d21, d3[1] + vmlal.s16 q2, d20, d3[2] + vmlal.s16 q3, d21, d3[2] + vmlal.s16 q13, d22, d3[2] + vmlal.s16 q14, d23, d3[2] + vmlal.s16 q2, d22, d3[3] + vmlal.s16 q3, d23, d3[3] + vmlal.s16 q13, d24, d3[3] + vmlal.s16 q14, d25, d3[3] +.ifc \type, put + vrshl.s32 q2, q2, q4 // -(6+intermediate_bits) + vrshl.s32 q3, q3, q4 // -(6+intermediate_bits) + vrshl.s32 q13, q13, q4 // -(6+intermediate_bits) + vrshl.s32 q14, q14, q4 // -(6+intermediate_bits) + vqmovun.s32 d4, q2 + vqmovun.s32 d5, q3 + vqmovun.s32 d6, q13 + vqmovun.s32 d7, q14 + vmin.u16 q2, q2, q15 + vmin.u16 q3, q3, q15 +.else + vmov.i16 q5, #PREP_BIAS + vrshrn.i32 d4, q2, #6 + vrshrn.i32 d5, q3, #6 + vrshrn.i32 d6, q13, #6 + vrshrn.i32 d7, q14, #6 + vsub.i16 q2, q2, q5 // PREP_BIAS + vsub.i16 q3, q3, q5 // PREP_BIAS +.endif + subs \h, \h, #2 + vst1.16 {q2}, [\dst, :128], \d_strd + vst1.16 {q3}, [\ds2, :128], \d_strd + ble 9f + vmov q4, q6 + vmov q5, q7 + vmov q6, q8 + vmov q7, q9 + vmov q8, q10 + vmov q9, q11 + vmov q10, q12 + b 88b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + vpop {q4-q7} + pop {r4-r11,pc} + +L(\type\()_8tap_filter_8): + vld1.16 {q13, q14}, [\sr2], \s_strd + vmull.s16 q2, d26, d0[0] + vmull.s16 q3, d27, d0[0] +.irpc i, 1234567 + vext.8 q12, q13, q14, #(2*\i) +.if \i < 4 + vmlal.s16 q2, d24, d0[\i] + vmlal.s16 q3, d25, d0[\i] +.else + vmlal.s16 q2, d24, d1[\i - 4] + vmlal.s16 q3, d25, d1[\i - 4] +.endif +.endr + vdup.32 q12, r12 // -(6-intermediate_bits) + vld1.16 {q13, q14}, [\src], \s_strd + vrshl.s32 q2, q2, q12 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q12 // -(6-intermediate_bits) + vmovn.i32 d4, q2 + vmovn.i32 d5, q3 + + vmull.s16 q3, d26, d0[0] + vmull.s16 q11, d27, d0[0] +.irpc i, 1234567 + vext.8 q12, q13, q14, #(2*\i) +.if \i < 4 + vmlal.s16 q3, d24, d0[\i] + vmlal.s16 q11, d25, d0[\i] +.else + vmlal.s16 q3, d24, d1[\i - 4] + vmlal.s16 q11, d25, d1[\i - 4] +.endif +.endr + vdup.32 q13, r12 // -(6-intermediate_bits) + vrshl.s32 q3, q3, q13 // -(6-intermediate_bits) + vrshl.s32 q11, q11, q13 // -(6-intermediate_bits) + + vmovn.i32 d24, q3 + vmovn.i32 d25, q11 + vmov q11, q2 + bx lr +endfunc + +function \type\()_bilin_16bpc_neon, export=1 + push {r4-r11,lr} + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] +.ifc \bdmax, r8 + ldr r8, [sp, #52] +.endif + vdup.16 q1, \mx + vdup.16 q3, \my + rsb r9, \mx, #16 + rsb r10, \my, #16 + vdup.16 q0, r9 + vdup.16 q2, r10 +.ifc \type, prep + lsl \d_strd, \w, #1 +.endif + clz \bdmax, \bdmax // bitdepth_max + clz r9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + cmp \mx, #0 + sub r9, r9, #24 + rsb r11, \bdmax, #4 // 4 - intermediate_bits + add r12, \bdmax, #4 // 4 + intermediate_bits + bne L(\type\()_bilin_h) + cmp \my, #0 + bne L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cmp \my, #0 + bne L(\type\()_bilin_hv) + + adr r10, L(\type\()_bilin_h_tbl) + vdup.16 q15, r11 // 4 - intermediate_bits + ldr r9, [r10, r9, lsl #2] + vneg.s16 q15, q15 // -(4-intermediate_bits) +.ifc \type, put + vdup.16 q14, \bdmax // intermediate_bits +.else + vmov.i16 q14, #PREP_BIAS +.endif + add r10, r10, r9 +.ifc \type, put + vneg.s16 q14, q14 // -intermediate_bits +.endif + bx r10 + + .align 2 +L(\type\()_bilin_h_tbl): + .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB + +20: // 2xN h +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + vld1.16 {d16}, [\src], \s_strd + vld1.16 {d18}, [\sr2], \s_strd + vext.8 d17, d16, d16, #2 + vext.8 d19, d18, d18, #2 + vtrn.32 d16, d18 + vtrn.32 d17, d19 + subs \h, \h, #2 + vmul.i16 d16, d16, d0 + vmla.i16 d16, d17, d2 + vrshl.u16 d16, d16, d30 + vrshl.u16 d16, d16, d28 + vst1.32 {d16[0]}, [\dst, :32], \d_strd + vst1.32 {d16[1]}, [\ds2, :32], \d_strd + bgt 2b + pop {r4-r11,pc} +.endif + +40: // 4xN h + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + vld1.16 {q8}, [\src], \s_strd + vld1.16 {q10}, [\sr2], \s_strd + vext.8 q9, q8, q8, #2 + vext.8 q11, q10, q10, #2 + vmov d17, d20 + vmov d19, d22 + subs \h, \h, #2 + vmul.i16 q8, q8, q0 + vmla.i16 q8, q9, q1 + vrshl.u16 q8, q8, q15 +.ifc \type, put + vrshl.u16 q8, q8, q14 +.else + vsub.i16 q8, q8, q14 +.endif + vst1.16 {d16}, [\dst, :64], \d_strd + vst1.16 {d17}, [\ds2, :64], \d_strd + bgt 4b + pop {r4-r11,pc} + +80: // 8xN h + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + vld1.16 {d16, d17, d18}, [\src], \s_strd + vld1.16 {d20, d21, d22}, [\sr2], \s_strd + vext.8 q9, q8, q9, #2 + vext.8 q11, q10, q11, #2 + subs \h, \h, #2 + vmul.i16 q8, q8, q0 + vmla.i16 q8, q9, q1 + vmul.i16 q10, q10, q0 + vmla.i16 q10, q11, q1 + vrshl.u16 q8, q8, q15 + vrshl.u16 q10, q10, q15 +.ifc \type, put + vrshl.u16 q8, q8, q14 + vrshl.u16 q10, q10, q14 +.else + vsub.i16 q8, q8, q14 + vsub.i16 q10, q10, q14 +.endif + vst1.16 {q8}, [\dst, :128], \d_strd + vst1.16 {q10}, [\ds2, :128], \d_strd + bgt 8b + pop {r4-r11,pc} +160: +320: +640: +1280: // 16xN, 32xN, ... h + vpush {q4-q7} + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w, lsl #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, lsl #1 +.endif +161: + vld1.16 {q4}, [\src]! + vld1.16 {q9}, [\sr2]! + mov \mx, \w + +16: + vld1.16 {q5, q6}, [\src]! + vld1.16 {q10, q11}, [\sr2]! + vext.8 q7, q4, q5, #2 + vext.8 q8, q5, q6, #2 + vext.8 q12, q9, q10, #2 + vext.8 q13, q10, q11, #2 + vmul.i16 q4, q4, q0 + vmla.i16 q4, q7, q1 + vmul.i16 q5, q5, q0 + vmla.i16 q5, q8, q1 + vmul.i16 q9, q9, q0 + vmla.i16 q9, q12, q1 + vmul.i16 q10, q10, q0 + vmla.i16 q10, q13, q1 + vrshl.u16 q4, q4, q15 + vrshl.u16 q5, q5, q15 + vrshl.u16 q9, q9, q15 + vrshl.u16 q10, q10, q15 + subs \mx, \mx, #16 +.ifc \type, put + vrshl.u16 q4, q4, q14 + vrshl.u16 q5, q5, q14 + vrshl.u16 q9, q9, q14 + vrshl.u16 q10, q10, q14 +.else + vsub.i16 q4, q4, q14 + vsub.i16 q5, q5, q14 + vsub.i16 q9, q9, q14 + vsub.i16 q10, q10, q14 +.endif + vst1.16 {q4, q5}, [\dst, :128]! + vst1.16 {q9, q10}, [\ds2, :128]! + ble 9f + + vmov q4, q6 + vmov q9, q11 + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + bgt 161b + vpop {q4-q7} + pop {r4-r11,pc} + + +L(\type\()_bilin_v): + cmp \h, #4 + adr r10, L(\type\()_bilin_v_tbl) +.ifc \type, prep + vdup.16 q15, r11 // 4 - intermediate_bits +.endif + ldr r9, [r10, r9, lsl #2] +.ifc \type, prep + vmov.i16 q14, #PREP_BIAS + vneg.s16 q15, q15 // -(4-intermediate_bits) +.endif + add r10, r10, r9 + bx r10 + + .align 2 +L(\type\()_bilin_v_tbl): + .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB + +20: // 2xN v +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + vld1.32 {d16[]}, [\src], \s_strd + bgt 24f +22: + vld1.32 {d17[]}, [\sr2], \s_strd + vld1.32 {d18[]}, [\src], \s_strd + vext.8 d16, d16, d17, #4 + vext.8 d17, d17, d18, #4 + vmul.i16 d16, d16, d4 + vmla.i16 d16, d17, d6 + vrshr.u16 d16, d16, #4 + vst1.32 {d16[0]}, [\dst, :32] + vst1.32 {d16[1]}, [\ds2, :32] + pop {r4-r11,pc} +24: // 2x4, 2x6, 2x8, ... v + vld1.32 {d17[]}, [\sr2], \s_strd + vld1.32 {d18[]}, [\src], \s_strd + vld1.32 {d19[]}, [\sr2], \s_strd + vld1.32 {d20[]}, [\src], \s_strd + subs \h, \h, #4 + vext.8 d16, d16, d17, #4 + vext.8 d17, d17, d18, #4 + vext.8 d18, d18, d19, #4 + vext.8 d19, d19, d20, #4 + vswp d17, d18 + vmul.i16 q8, q8, q2 + vmla.i16 q8, q9, q3 + cmp \h, #2 + vrshr.u16 q8, q8, #4 + vst1.32 {d16[0]}, [\dst, :32], \d_strd + vst1.32 {d16[1]}, [\ds2, :32], \d_strd + vst1.32 {d17[0]}, [\dst, :32], \d_strd + vst1.32 {d17[1]}, [\ds2, :32], \d_strd + blt 0f + vmov d16, d20 + beq 22b + b 24b +0: + pop {r4-r11,pc} +.endif + +40: // 4xN v + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vld1.16 {d16}, [\src], \s_strd +4: + vld1.16 {d17}, [\sr2], \s_strd + vld1.16 {d19}, [\src], \s_strd + vmov d18, d17 + vmul.i16 q8, q8, q2 + vmla.i16 q8, q9, q3 + subs \h, \h, #2 +.ifc \type, put + vrshr.u16 q8, q8, #4 +.else + vrshl.u16 q8, q8, q15 + vsub.i16 q8, q8, q14 +.endif + vst1.16 {d16}, [\dst, :64], \d_strd + vst1.16 {d17}, [\ds2, :64], \d_strd + ble 0f + vmov d16, d19 + b 4b +0: + pop {r4-r11,pc} + +80: // 8xN v + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + vld1.16 {q8}, [\src], \s_strd +8: + vld1.16 {q9}, [\sr2], \s_strd + vld1.16 {q10}, [\src], \s_strd + vmul.i16 q8, q8, q2 + vmla.i16 q8, q9, q3 + vmul.i16 q9, q9, q2 + vmla.i16 q9, q10, q3 + subs \h, \h, #2 +.ifc \type, put + vrshr.u16 q8, q8, #4 + vrshr.u16 q9, q9, #4 +.else + vrshl.u16 q8, q8, q15 + vrshl.u16 q9, q9, q15 + vsub.i16 q8, q8, q14 + vsub.i16 q9, q9, q14 +.endif + vst1.16 {q8}, [\dst, :128], \d_strd + vst1.16 {q9}, [\ds2, :128], \d_strd + ble 0f + vmov q8, q10 + b 8b +0: + pop {r4-r11,pc} + +160: // 16xN, 32xN, ... +320: +640: +1280: + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.16 {q8, q9}, [\src], \s_strd +2: + vld1.16 {q10, q11}, [\sr2], \s_strd + vld1.16 {q12, q13}, [\src], \s_strd + vmul.i16 q8, q8, q2 + vmla.i16 q8, q10, q3 + vmul.i16 q9, q9, q2 + vmla.i16 q9, q11, q3 + vmul.i16 q10, q10, q2 + vmla.i16 q10, q12, q3 + vmul.i16 q11, q11, q2 + vmla.i16 q11, q13, q3 + subs \h, \h, #2 +.ifc \type, put + vrshr.u16 q8, q8, #4 + vrshr.u16 q9, q9, #4 + vrshr.u16 q10, q10, #4 + vrshr.u16 q11, q11, #4 +.else + vrshl.u16 q8, q8, q15 + vrshl.u16 q9, q9, q15 + vrshl.u16 q10, q10, q15 + vrshl.u16 q11, q11, q15 + vsub.i16 q8, q8, q14 + vsub.i16 q9, q9, q14 + vsub.i16 q10, q10, q14 + vsub.i16 q11, q11, q14 +.endif + vst1.16 {q8, q9}, [\dst, :128], \d_strd + vst1.16 {q10, q11}, [\ds2, :128], \d_strd + ble 9f + vmov q8, q12 + vmov q9, q13 + b 2b +9: + subs \w, \w, #16 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #32 + add \dst, \dst, #32 + b 1b +0: + pop {r4-r11,pc} + +L(\type\()_bilin_hv): + adr r10, L(\type\()_bilin_hv_tbl) + vdup.16 q15, r11 // 4 - intermediate_bits + ldr r9, [r10, r9, lsl #2] + vneg.s16 q15, q15 // -(4-intermediate_bits) +.ifc \type, put + vdup.32 q14, r12 // 4 + intermediate_bits +.else + vmov.i16 q14, #PREP_BIAS +.endif + add r10, r10, r9 +.ifc \type, put + vneg.s32 q14, q14 // -(4+intermediate_bits) +.endif + bx r10 + + .align 2 +L(\type\()_bilin_hv_tbl): + .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 640f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 320f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 160f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 80f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 40f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + .word 20f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB + +20: // 2xN hv +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.16 {d20}, [\src], \s_strd + vext.8 d21, d20, d20, #2 + vmul.i16 d16, d20, d0 + vmla.i16 d16, d21, d2 + vrshl.u16 d16, d16, d30 + vext.8 d16, d16, d16, #4 + +2: + vld1.16 {d20}, [\sr2], \s_strd + vld1.16 {d22}, [\src], \s_strd + vext.8 d21, d20, d20, #2 + vext.8 d23, d22, d22, #2 + vtrn.32 d20, d22 + vtrn.32 d21, d23 + vmul.i16 d18, d20, d0 + vmla.i16 d18, d21, d2 + vrshl.u16 d18, d18, d30 + + vext.8 d16, d16, d18, #4 + + vmull.u16 q8, d16, d4 + vmlal.u16 q8, d18, d6 + vrshl.u32 q8, q8, q14 + vmovn.i32 d16, q8 + subs \h, \h, #2 + vst1.32 {d16[0]}, [\dst, :32], \d_strd + vst1.32 {d16[1]}, [\ds2, :32], \d_strd + ble 0f + vmov d16, d18 + b 2b +0: + pop {r4-r11,pc} +.endif + +40: // 4xN hv + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.16 {q10}, [\src], \s_strd + vext.8 d21, d20, d21, #2 + vmul.i16 d16, d20, d0 + vmla.i16 d16, d21, d2 + vrshl.u16 d16, d16, d30 + +4: + vld1.16 {q10}, [\sr2], \s_strd + vld1.16 {q11}, [\src], \s_strd + vext.8 d21, d20, d21, #2 + vext.8 d23, d22, d23, #2 + vswp d21, d22 + vmul.i16 q9, q10, q0 + vmla.i16 q9, q11, q1 + vrshl.u16 q9, q9, q15 + + vmull.u16 q10, d16, d4 + vmlal.u16 q10, d18, d6 + vmull.u16 q11, d18, d4 + vmlal.u16 q11, d19, d6 +.ifc \type, put + vrshl.u32 q10, q10, q14 + vrshl.u32 q11, q11, q14 + vmovn.i32 d20, q10 + vmovn.i32 d21, q11 +.else + vrshrn.i32 d20, q10, #4 + vrshrn.i32 d21, q11, #4 + vsub.i16 q10, q10, q14 +.endif + subs \h, \h, #2 + vst1.16 {d20}, [\dst, :64], \d_strd + vst1.16 {d21}, [\ds2, :64], \d_strd + ble 0f + vmov d16, d19 + b 4b +0: + pop {r4-r11,pc} + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + vld1.16 {d20, d21, d22}, [\src], \s_strd + vext.8 q11, q10, q11, #2 + vmul.i16 q8, q10, q0 + vmla.i16 q8, q11, q1 + vrshl.u16 q8, q8, q15 + +2: + vld1.16 {d20, d21, d22}, [\sr2], \s_strd + vld1.16 {d24, d25, d26}, [\src], \s_strd + vext.8 q11, q10, q11, #2 + vext.8 q13, q12, q13, #2 + vmul.i16 q9, q10, q0 + vmla.i16 q9, q11, q1 + vmul.i16 q10, q12, q0 + vmla.i16 q10, q13, q1 + vrshl.u16 q9, q9, q15 + vrshl.u16 q10, q10, q15 + + vmull.u16 q11, d16, d4 + vmlal.u16 q11, d18, d6 + vmull.u16 q12, d17, d4 + vmlal.u16 q12, d19, d6 + vmull.u16 q8, d18, d4 + vmlal.u16 q8, d20, d6 + vmull.u16 q9, d19, d4 + vmlal.u16 q9, d21, d6 +.ifc \type, put + vrshl.u32 q11, q11, q14 + vrshl.u32 q12, q12, q14 + vrshl.u32 q8, q8, q14 + vrshl.u32 q9, q9, q14 + vmovn.i32 d22, q11 + vmovn.i32 d23, q12 + vmovn.i32 d16, q8 + vmovn.i32 d17, q9 +.else + vrshrn.i32 d22, q11, #4 + vrshrn.i32 d23, q12, #4 + vrshrn.i32 d16, q8, #4 + vrshrn.i32 d17, q9, #4 + vsub.i16 q11, q11, q14 + vsub.i16 q8, q8, q14 +.endif + subs \h, \h, #2 + vst1.16 {q11}, [\dst, :128], \d_strd + vst1.16 {q8}, [\ds2, :128], \d_strd + ble 9f + vmov q8, q10 + b 2b +9: + subs \w, \w, #8 + ble 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + mls \src, \s_strd, \my, \src + mls \dst, \d_strd, \my, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 1b +0: + pop {r4-r11,pc} +endfunc +.endm + +filter_fn put, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 +filter_fn prep, r0, r8, r1, r2, r3, r4, r5, r6, r7, r9, r10 + +.macro load_filter_ptr src + asr r12, \src, #10 + add r12, r11, r12, lsl #3 +.endm + +.macro load_filter_coef dst, src, inc + add \src, \src, \inc + vld1.8 {\dst}, [r12, :64] +.endm + +.macro load_filter_row dst, src, inc + load_filter_ptr \src + load_filter_coef \dst, \src, \inc +.endm + +function warp_filter_horz_neon + load_filter_ptr r5 // filter 0 + vld1.16 {q6,q7}, [r2], r3 + + load_filter_coef d0, r5, r7 // filter 0 + load_filter_row d2, r5, r7 // filter 1 + vmovl.s8 q0, d0 // filter 0 + vext.8 q3, q6, q7, #2*1 // filter 1 pixels + vmovl.s8 q1, d2 // filter 1 + + vmull.s16 q4, d12, d0 // filter 0 output (0-3) + vmull.s16 q5, d13, d1 // filter 0 output (4-7) + + load_filter_ptr r5 // filter 2 + + vmull.s16 q2, d6, d2 // filter 1 output (0-3) + vmull.s16 q3, d7, d3 // filter 1 output (4-7) + + load_filter_coef d0, r5, r7 // filter 2 + + vpadd.i32 d8, d8, d9 // half pixel 0 (2x32) + vpadd.i32 d9, d10, d11 // half pixel 0 (2x32) + + load_filter_ptr r5 // filter 3 + + vpadd.i32 d4, d4, d5 // half pixel 1 (2x32) + vpadd.i32 d5, d6, d7 // half pixel 1 (2x32) + + vmovl.s8 q0, d0 // filter 2 + vext.8 q3, q6, q7, #2*2 // filter 2 pixels + + vpadd.i32 d8, d8, d9 // pixel 0 (2x32) + vpadd.i32 d9, d4, d5 // pixel 1 (2x32) + + load_filter_coef d2, r5, r7 // filter 3 + + vmull.s16 q2, d6, d0 // filter 2 output (0-3) + vmull.s16 q3, d7, d1 // filter 2 output (4-7) + + load_filter_ptr r5 // filter 4 + + vpadd.i32 d8, d8, d9 // pixel 0,1 + + vpadd.i32 d9, d4, d5 // half pixel 2 (2x32) + vpadd.i32 d10, d6, d7 // half pixel 2 (2x32) + + vmovl.s8 q1, d2 // filter 3 + vext.8 q3, q6, q7, #2*3 // filter 3 pixels + + load_filter_coef d0, r5, r7 // filter 4 + + vpadd.i32 d9, d9, d10 // pixel 2 (2x32) + + vmull.s16 q2, d6, d2 // filter 3 output (0-3) + vmull.s16 q3, d7, d3 // filter 3 output (4-7) + + vmovl.s8 q0, d0 // filter 4 + load_filter_ptr r5 // filter 5 + + vpadd.i32 d10, d4, d5 // half pixel 3 (2x32) + vpadd.i32 d11, d6, d7 // half pixel 3 (2x32) + + vext.8 q3, q6, q7, #2*4 // filter 4 pixels + load_filter_coef d2, r5, r7 // filter 5 + + vpadd.i32 d10, d10, d11 // pixel 3 (2x32) + + vpadd.i32 d9, d9, d10 // pixel 2,3 + + vmull.s16 q2, d6, d0 // filter 4 output (0-3) + vmull.s16 q3, d7, d1 // filter 4 output (4-7) + + vmovl.s8 q1, d2 // filter 5 + load_filter_ptr r5 // filter 6 + + vpadd.i32 d10, d4, d5 // half pixel 4 (2x32) + vpadd.i32 d11, d6, d7 // half pixel 4 (2x32) + + vext.8 q3, q6, q7, #2*5 // filter 5 pixels + load_filter_coef d0, r5, r7 // filter 6 + + vpadd.i32 d10, d10, d11 // pixel 4 (2x32) + + vmull.s16 q2, d6, d2 // filter 5 output (0-3) + vmull.s16 q3, d7, d3 // filter 5 output (4-7) + + vmovl.s8 q0, d0 // filter 6 + load_filter_ptr r5 // filter 7 + + vpadd.i32 d4, d4, d5 // half pixel 5 (2x32) + vpadd.i32 d5, d6, d7 // half pixel 5 (2x32) + + vext.8 q3, q6, q7, #2*6 // filter 6 pixels + load_filter_coef d2, r5, r7 // filter 7 + + vpadd.i32 d11, d4, d5 // pixel 5 (2x32) + + vmull.s16 q2, d6, d0 // filter 6 output (0-3) + vmull.s16 q3, d7, d1 // filter 6 output (4-7) + + vmovl.s8 q1, d2 // filter 7 + + vpadd.i32 d10, d10, d11 // pixel 4,5 + + vpadd.i32 d4, d4, d5 // half pixel 6 (2x32) + vpadd.i32 d5, d6, d7 // half pixel 6 (2x32) + + vext.8 q3, q6, q7, #2*7 // filter 7 pixels + + vpadd.i32 d11, d4, d5 // pixel 6 (2x32) + + vmull.s16 q2, d6, d2 // filter 7 output (0-3) + vmull.s16 q3, d7, d3 // filter 7 output (4-7) + + vld1.32 {d14[],d15[]}, [sp] // -(7 - intermediate_bits) + + vpadd.i32 d4, d4, d5 // half pixel 7 (2x32) + vpadd.i32 d5, d6, d7 // half pixel 7 (2x32) + + sub r5, r5, r7, lsl #3 + + vpadd.i32 d4, d4, d5 // pixel 7 (2x32) + + add r5, r5, r8 + + vpadd.i32 d11, d11, d4 // pixel 6,7 + + vrshl.s32 q4, q4, q7 // -(7 - intermediate_bits) + vrshl.s32 q5, q5, q7 // -(7 - intermediate_bits) + + bx lr +endfunc + +// void dav1d_warp_affine_8x8_16bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my, +// const int bitdepth_max) +.macro warp t +function warp_affine_8x8\t\()_16bpc_neon, export=1 + push {r4-r11,lr} + vpush {q4-q7} + ldrd r4, r5, [sp, #100] + ldrd r6, r7, [sp, #108] + sub sp, sp, #8 + + clz r7, r7 + // intermediate_bits = clz(bitdepth_max) - 18 +.ifb \t + sub r8, r7, #11 // 7 + intermediate_bits = clz(bitdepth_max) - 18 + 7 +.endif + sub r7, r7, #25 // -(7 - intermediate_bits) +.ifb \t + neg r8, r8 // -(7 + intermediate_bits) +.endif + str r7, [sp] // spill -(7 - intermediate_bits) on stack +.ifb \t + str r8, [sp, #4] // spill -(7 + intermediate_bits) on stack +.endif + + ldrd r8, r9, [r4] + sxth r7, r8 + asr r8, r8, #16 + asr r4, r9, #16 + sxth r9, r9 + mov r10, #8 + sub r2, r2, r3, lsl #1 + sub r2, r2, r3 + sub r2, r2, #6 + movrel r11, X(mc_warp_filter), 64*8 +.ifnb \t + lsl r1, r1, #1 +.endif + add r5, r5, #512 + add r6, r6, #512 + + bl warp_filter_horz_neon + vmovn.i32 d16, q4 + vmovn.i32 d17, q5 + bl warp_filter_horz_neon + vmovn.i32 d18, q4 + vmovn.i32 d19, q5 + bl warp_filter_horz_neon + vmovn.i32 d20, q4 + vmovn.i32 d21, q5 + bl warp_filter_horz_neon + vmovn.i32 d22, q4 + vmovn.i32 d23, q5 + bl warp_filter_horz_neon + vmovn.i32 d24, q4 + vmovn.i32 d25, q5 + bl warp_filter_horz_neon + vmovn.i32 d26, q4 + vmovn.i32 d27, q5 + bl warp_filter_horz_neon + vmovn.i32 d28, q4 + vmovn.i32 d29, q5 + +1: + bl warp_filter_horz_neon + vmovn.i32 d30, q4 + vmovn.i32 d31, q5 + + load_filter_row d8, r6, r9 + load_filter_row d9, r6, r9 + load_filter_row d10, r6, r9 + load_filter_row d11, r6, r9 + load_filter_row d12, r6, r9 + load_filter_row d13, r6, r9 + load_filter_row d14, r6, r9 + load_filter_row d15, r6, r9 + transpose_8x8b q4, q5, q6, q7, d8, d9, d10, d11, d12, d13, d14, d15 + vmovl.s8 q1, d8 + vmovl.s8 q2, d9 + vmovl.s8 q3, d10 + vmovl.s8 q4, d11 + vmovl.s8 q5, d12 + vmovl.s8 q6, d13 + + sub r6, r6, r9, lsl #3 + + // This ordering of vmull/vmlal is highly beneficial for + // Cortex A8/A9/A53 here, but harmful for Cortex A7. + vmull.s16 q0, d16, d2 + vmlal.s16 q0, d18, d4 + vmlal.s16 q0, d20, d6 + vmlal.s16 q0, d22, d8 + vmlal.s16 q0, d24, d10 + vmlal.s16 q0, d26, d12 + vmull.s16 q1, d17, d3 + vmlal.s16 q1, d19, d5 + vmlal.s16 q1, d21, d7 + vmlal.s16 q1, d23, d9 + vmlal.s16 q1, d25, d11 + vmlal.s16 q1, d27, d13 + + vmovl.s8 q2, d14 + vmovl.s8 q3, d15 + + vmlal.s16 q0, d28, d4 + vmlal.s16 q0, d30, d6 + vmlal.s16 q1, d29, d5 + vmlal.s16 q1, d31, d7 + +.ifb \t + ldr lr, [sp, #4] // -(7 + intermediate_bits) + ldr r12, [sp, #120] // bitdepth_max + vdup.32 q2, lr // -(7 + intermediate_bits) + vdup.16 q3, r12 // bitdepth_max +.endif + + vmov q8, q9 + vmov q9, q10 +.ifb \t + vrshl.s32 q0, q0, q2 // -(7 + intermediate_bits) + vrshl.s32 q1, q1, q2 // -(7 + intermediate_bits) +.else + vrshrn.s32 d0, q0, #7 + vrshrn.s32 d1, q1, #7 + vmov.i16 q3, #PREP_BIAS +.endif + vmov q10, q11 +.ifb \t + vqmovun.s32 d0, q0 + vqmovun.s32 d1, q1 +.else + vsub.i16 q0, q0, q3 // PREP_BIAS +.endif + vmov q11, q12 + vmov q12, q13 +.ifb \t + vmin.u16 q0, q0, q3 // bitdepth_max +.endif + vmov q13, q14 + vmov q14, q15 + subs r10, r10, #1 + vst1.16 {q0}, [r0, :128], r1 + + add r6, r6, r4 + bgt 1b + + add sp, sp, #8 + vpop {q4-q7} + pop {r4-r11,pc} +endfunc +.endm + +warp +warp t + +// void dav1d_emu_edge_16bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_16bpc_neon, export=1 + push {r4-r11,lr} + ldrd r4, r5, [sp, #36] + ldrd r6, r7, [sp, #44] + ldrd r8, r9, [sp, #52] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub r12, r3, #1 // ih - 1 + cmp r5, r3 + sub lr, r2, #1 // iw - 1 + it lt + movlt r12, r5 // min(y, ih - 1) + cmp r4, r2 + bic r12, r12, r12, asr #31 // max(min(y, ih - 1), 0) + it lt + movlt lr, r4 // min(x, iw - 1) + bic lr, lr, lr, asr #31 // max(min(x, iw - 1), 0) + mla r8, r12, r9, r8 // ref += iclip() * stride + add r8, r8, lr, lsl #1 // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add r10, r5, r1 // y + bh + neg r5, r5 // -y + sub r10, r10, r3 // y + bh - ih + sub r12, r1, #1 // bh - 1 + cmp r10, r1 + bic r5, r5, r5, asr #31 // max(-y, 0) + it ge + movge r10, r12 // min(y + bh - ih, bh-1) + cmp r5, r1 + bic r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0) + it ge + movge r5, r12 // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add r11, r4, r0 // x + bw + neg r4, r4 // -x + sub r11, r11, r2 // x + bw - iw + sub lr, r0, #1 // bw - 1 + cmp r11, r0 + bic r4, r4, r4, asr #31 // max(-x, 0) + it ge + movge r11, lr // min(x + bw - iw, bw-1) + cmp r4, r0 + bic r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0) + it ge + movge r4, lr // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub r1, r1, r5 // bh - top_ext + mla r6, r5, r7, r6 + sub r2, r0, r4 // bw - left_ext + sub r1, r1, r10 // center_h = bh - top_ext - bottom_ext + sub r2, r2, r11 // center_w = bw - left_ext - right_ext + + mov r0, r6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + vld1.16 {d0[], d1[]}, [r8] + mov r12, r6 // out = dst + mov r3, r4 + vmov q1, q0 +1: + subs r3, r3, #16 + vst1.16 {q0, q1}, [r12, :128]! + bgt 1b +.endif + mov lr, r8 + add r12, r6, r4, lsl #1 // out = dst + left_ext + mov r3, r2 +1: + vld1.16 {q0, q1}, [lr]! + subs r3, r3, #32 + vld1.16 {q2, q3}, [lr]! +.if \need_left + vst1.16 {q0, q1}, [r12]! + vst1.16 {q2, q3}, [r12]! +.else + vst1.16 {q0, q1}, [r12, :128]! + vst1.16 {q2, q3}, [r12, :128]! +.endif + bgt 1b +.if \need_right + add r3, r8, r2, lsl #1 // in + center_w + sub r3, r3, #2 // in + center_w - 1 + add r12, r6, r4, lsl #1 // dst + left_ext + vld1.16 {d0[], d1[]}, [r3] + add r12, r12, r2, lsl #1 // out = dst + left_ext + center_w + mov r3, r11 + vmov q1, q0 +1: + subs r3, r3, #16 + vst1.16 {q0, q1}, [r12]! + bgt 1b +.endif + + subs r1, r1, #1 // center_h-- + add r6, r6, r7 + add r8, r8, r9 + bgt 0b +.endm + + cmp r4, #0 + beq 2f + // need_left + cmp r11, #0 + beq 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cmp r11, #0 + beq 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + cmp r10, #0 + // Storing the original dst in r0 overwrote bw, recalculate it here + add r2, r2, r4 // center_w + left_ext + add r2, r2, r11 // bw = center_w + left_ext + right_ext + + beq 3f + // need_bottom + sub r8, r6, r7 // ref = dst - stride + mov r4, r2 + sub r12, r7, #32 +1: + vld1.16 {q0, q1}, [r8, :128]! + mov r3, r10 + vld1.16 {q2, q3}, [r8, :128]! +2: + vst1.16 {q0, q1}, [r6, :128]! + subs r3, r3, #1 + vst1.16 {q2, q3}, [r6, :128], r12 + bgt 2b + mls r6, r7, r10, r6 // dst -= bottom_ext * stride + subs r4, r4, #32 // bw -= 32 + add r6, r6, #64 // dst += 32 + bgt 1b + +3: + cmp r5, #0 + beq 3f + // need_top + mls r6, r7, r5, r0 // dst = stored_dst - top_ext * stride + sub r12, r7, #32 +1: + vld1.16 {q0, q1}, [r0, :128]! + mov r3, r5 + vld1.16 {q2, q3}, [r0, :128]! +2: + vst1.16 {q0, q1}, [r6, :128]! + subs r3, r3, #1 + vst1.16 {q2, q3}, [r6, :128], r12 + bgt 2b + mls r6, r7, r5, r6 // dst -= top_ext * stride + subs r2, r2, #32 // bw -= 32 + add r6, r6, #64 // dst += 32 + bgt 1b + +3: + pop {r4-r11,pc} +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/msac.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/msac.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/msac.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/msac.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,575 @@ +/* + * Copyright © 2019, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define BUF_POS 0 +#define BUF_END 4 +#define DIF 8 +#define RNG 12 +#define CNT 16 +#define ALLOW_UPDATE_CDF 20 + +const coeffs + .short 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0 + .short 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +endconst + +const bits, align=4 + .short 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 + .short 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 +endconst + +.macro vld1_align_n d0, q0, q1, src, n +.if \n == 4 + vld1.16 {\d0}, [\src, :64] +.elseif \n == 8 + vld1.16 {\q0}, [\src, :128] +.else + vld1.16 {\q0, \q1}, [\src, :128] +.endif +.endm + +.macro vld1_n d0, q0, q1, src, n +.if \n == 4 + vld1.16 {\d0}, [\src] +.elseif \n == 8 + vld1.16 {\q0}, [\src] +.else + vld1.16 {\q0, \q1}, [\src] +.endif +.endm + +.macro vst1_align_n d0, q0, q1, src, n +.if \n == 4 + vst1.16 {\d0}, [\src, :64] +.elseif \n == 8 + vst1.16 {\q0}, [\src, :128] +.else + vst1.16 {\q0, \q1}, [\src, :128] +.endif +.endm + +.macro vst1_n d0, q0, q1, src, n +.if \n == 4 + vst1.16 {\d0}, [\src] +.elseif \n == 8 + vst1.16 {\q0}, [\src] +.else + vst1.16 {\q0, \q1}, [\src] +.endif +.endm + +.macro vshr_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vshr.u16 \d0, \s0, \s3 +.else + vshr.u16 \d1, \s1, \s4 +.if \n == 16 + vshr.u16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vadd_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vadd.i16 \d0, \s0, \s3 +.else + vadd.i16 \d1, \s1, \s4 +.if \n == 16 + vadd.i16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vsub_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vsub.i16 \d0, \s0, \s3 +.else + vsub.i16 \d1, \s1, \s4 +.if \n == 16 + vsub.i16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vand_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vand \d0, \s0, \s3 +.else + vand \d1, \s1, \s4 +.if \n == 16 + vand \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vcge_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vcge.u16 \d0, \s0, \s3 +.else + vcge.u16 \d1, \s1, \s4 +.if \n == 16 + vcge.u16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vrhadd_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vrhadd.u16 \d0, \s0, \s3 +.else + vrhadd.u16 \d1, \s1, \s4 +.if \n == 16 + vrhadd.u16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vshl_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vshl.s16 \d0, \s0, \s3 +.else + vshl.s16 \d1, \s1, \s4 +.if \n == 16 + vshl.s16 \d2, \s2, \s5 +.endif +.endif +.endm + +.macro vqdmulh_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n +.if \n == 4 + vqdmulh.s16 \d0, \s0, \s3 +.else + vqdmulh.s16 \d1, \s1, \s4 +.if \n == 16 + vqdmulh.s16 \d2, \s2, \s5 +.endif +.endif +.endm + +// unsigned dav1d_msac_decode_symbol_adapt4_neon(MsacContext *s, uint16_t *cdf, +// size_t n_symbols); + +function msac_decode_symbol_adapt4_neon, export=1 +.macro decode_update n + push {r4-r10,lr} + sub sp, sp, #48 + add r8, r0, #RNG + + vld1_align_n d0, q0, q1, r1, \n // cdf + vld1.16 {d16[]}, [r8, :16] // rng + movrel_local r9, coeffs, 30 + vmov.i16 d30, #0x7f00 // 0x7f00 + sub r9, r9, r2, lsl #1 + vmvn.i16 q14, #0x3f // 0xffc0 + add r8, sp, #14 + vand d22, d16, d30 // rng & 0x7f00 + vst1.16 {d16[0]}, [r8, :16] // store original u = s->rng + vand_n d4, q2, q3, d0, q0, q1, d28, q14, q14, \n // cdf & 0xffc0 +.if \n > 4 + vmov d23, d22 +.endif + + vld1_n d16, q8, q9, r9, \n // EC_MIN_PROB * (n_symbols - ret) + vqdmulh_n d20, q10, q11, d4, q2, q3, d22, q11, q11, \n // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1 + add r8, r0, #DIF + 2 + + vadd_n d16, q8, q9, d4, q2, q3, d16, q8, q9, \n // v = cdf + EC_MIN_PROB * (n_symbols - ret) +.if \n == 4 + vmov.i16 d17, #0 +.endif + vadd_n d16, q8, q9, d20, q10, q11, d16, q8, q9, \n // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret) + + add r9, sp, #16 + vld1.16 {d20[]}, [r8, :16] // dif >> (EC_WIN_SIZE - 16) + movrel_local r8, bits + vst1_n q8, q8, q9, r9, \n // store v values to allow indexed access + + vmov d21, d20 + vld1_align_n q12, q12, q13, r8, \n +.if \n == 16 + vmov q11, q10 +.endif + + vcge_n q2, q2, q3, q10, q10, q11, q8, q8, q9, \n // c >= v + + vand_n q10, q10, q11, q2, q2, q3, q12, q12, q13, \n // One bit per halfword set in the mask +.if \n == 16 + vadd.i16 q10, q10, q11 +.endif + vadd.i16 d20, d20, d21 // Aggregate mask bits + ldr r4, [r0, #ALLOW_UPDATE_CDF] + vpadd.i16 d20, d20, d20 + lsl r10, r2, #1 + vpadd.i16 d20, d20, d20 + vmov.u16 r3, d20[0] + cmp r4, #0 + rbit r3, r3 + clz lr, r3 // ret + + beq L(renorm) + // update_cdf + ldrh r3, [r1, r10] // count = cdf[n_symbols] + vmov.i8 q10, #0xff +.if \n == 16 + mov r4, #-5 +.else + mvn r12, r2 + mov r4, #-4 + cmn r12, #3 // set C if n_symbols <= 2 +.endif + vrhadd_n d16, q8, q9, d20, q10, q10, d4, q2, q3, \n // i >= val ? -1 : 32768 +.if \n == 16 + sub r4, r4, r3, lsr #4 // -((count >> 4) + 5) +.else + lsr r12, r3, #4 // count >> 4 + sbc r4, r4, r12 // -((count >> 4) + (n_symbols > 2) + 4) +.endif + vsub_n d16, q8, q9, d16, q8, q9, d0, q0, q1, \n // (32768 - cdf[i]) or (-1 - cdf[i]) +.if \n == 4 + vdup.16 d20, r4 // -rate +.else + vdup.16 q10, r4 // -rate +.endif + + sub r3, r3, r3, lsr #5 // count - (count == 32) + vsub_n d0, q0, q1, d0, q0, q1, d4, q2, q3, \n // cdf + (i >= val ? 1 : 0) + vshl_n d16, q8, q9, d16, q8, q9, d20, q10, q10, \n // ({32768,-1} - cdf[i]) >> rate + add r3, r3, #1 // count + (count < 32) + vadd_n d0, q0, q1, d0, q0, q1, d16, q8, q9, \n // cdf + (32768 - cdf[i]) >> rate + vst1_align_n d0, q0, q1, r1, \n + strh r3, [r1, r10] +.endm + + decode_update 4 + +L(renorm): + add r8, sp, #16 + add r8, r8, lr, lsl #1 + ldrh r3, [r8] // v + ldrh r4, [r8, #-2] // u + ldr r6, [r0, #CNT] + ldr r7, [r0, #DIF] + sub r4, r4, r3 // rng = u - v + clz r5, r4 // clz(rng) + eor r5, r5, #16 // d = clz(rng) ^ 16 + mvn r7, r7 // ~dif + add r7, r7, r3, lsl #16 // ~dif + (v << 16) +L(renorm2): + lsl r4, r4, r5 // rng << d + subs r6, r6, r5 // cnt -= d + lsl r7, r7, r5 // (~dif + (v << 16)) << d + str r4, [r0, #RNG] + mvn r7, r7 // ~dif + bhs 9f + + // refill + ldr r3, [r0, #BUF_POS] // BUF_POS + ldr r4, [r0, #BUF_END] // BUF_END + add r5, r3, #4 + cmp r5, r4 + bgt 2f + + ldr r3, [r3] // next_bits + add r8, r6, #23 // shift_bits = cnt + 23 + add r6, r6, #16 // cnt += 16 + rev r3, r3 // next_bits = bswap(next_bits) + sub r5, r5, r8, lsr #3 // buf_pos -= shift_bits >> 3 + and r8, r8, #24 // shift_bits &= 24 + lsr r3, r3, r8 // next_bits >>= shift_bits + sub r8, r8, r6 // shift_bits -= 16 + cnt + str r5, [r0, #BUF_POS] + lsl r3, r3, r8 // next_bits <<= shift_bits + rsb r6, r8, #16 // cnt = cnt + 32 - shift_bits + eor r7, r7, r3 // dif ^= next_bits + b 9f + +2: // refill_eob + rsb r5, r6, #8 // c = 8 - cnt +3: + cmp r3, r4 + bge 4f + ldrb r8, [r3], #1 + lsl r8, r8, r5 + eor r7, r7, r8 + subs r5, r5, #8 + bge 3b + +4: // refill_eob_end + str r3, [r0, #BUF_POS] + rsb r6, r5, #8 // cnt = 8 - c + +9: + str r6, [r0, #CNT] + str r7, [r0, #DIF] + + mov r0, lr + add sp, sp, #48 + + pop {r4-r10,pc} +endfunc + +function msac_decode_symbol_adapt8_neon, export=1 + decode_update 8 + b L(renorm) +endfunc + +function msac_decode_symbol_adapt16_neon, export=1 + decode_update 16 + b L(renorm) +endfunc + +function msac_decode_hi_tok_neon, export=1 + push {r4-r10,lr} + vld1.16 {d0}, [r1, :64] // cdf + add r4, r0, #RNG + vmov.i16 d31, #0x7f00 // 0x7f00 + movrel_local r5, coeffs, 30-2*3 + vmvn.i16 d30, #0x3f // 0xffc0 + ldrh r9, [r1, #6] // count = cdf[n_symbols] + vld1.16 {d1[]}, [r4, :16] // rng + movrel_local r4, bits + vld1.16 {d29}, [r5] // EC_MIN_PROB * (n_symbols - ret) + add r5, r0, #DIF + 2 + vld1.16 {q8}, [r4, :128] + mov r2, #-24 + vand d20, d0, d30 // cdf & 0xffc0 + ldr r10, [r0, #ALLOW_UPDATE_CDF] + vld1.16 {d2[]}, [r5, :16] // dif >> (EC_WIN_SIZE - 16) + sub sp, sp, #48 + ldr r6, [r0, #CNT] + ldr r7, [r0, #DIF] + vmov d3, d2 +1: + vand d23, d1, d31 // rng & 0x7f00 + vqdmulh.s16 d18, d20, d23 // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1 + add r12, sp, #14 + vadd.i16 d6, d20, d29 // v = cdf + EC_MIN_PROB * (n_symbols - ret) + vadd.i16 d6, d18, d6 // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret) + vmov.i16 d7, #0 + vst1.16 {d1[0]}, [r12, :16] // store original u = s->rng + add r12, sp, #16 + vcge.u16 q2, q1, q3 // c >= v + vst1.16 {q3}, [r12] // store v values to allow indexed access + vand q9, q2, q8 // One bit per halfword set in the mask + + vadd.i16 d18, d18, d19 // Aggregate mask bits + vpadd.i16 d18, d18, d18 + vpadd.i16 d18, d18, d18 + vmov.u16 r3, d18[0] + cmp r10, #0 + add r2, r2, #5 + rbit r3, r3 + add r8, sp, #16 + clz lr, r3 // ret + + beq 2f + // update_cdf + vmov.i8 d22, #0xff + mov r4, #-5 + vrhadd.u16 d6, d22, d4 // i >= val ? -1 : 32768 + sub r4, r4, r9, lsr #4 // -((count >> 4) + 5) + vsub.i16 d6, d6, d0 // (32768 - cdf[i]) or (-1 - cdf[i]) + vdup.16 d18, r4 // -rate + + sub r9, r9, r9, lsr #5 // count - (count == 32) + vsub.i16 d0, d0, d4 // cdf + (i >= val ? 1 : 0) + vshl.s16 d6, d6, d18 // ({32768,-1} - cdf[i]) >> rate + add r9, r9, #1 // count + (count < 32) + vadd.i16 d0, d0, d6 // cdf + (32768 - cdf[i]) >> rate + vst1.16 {d0}, [r1, :64] + vand d20, d0, d30 // cdf & 0xffc0 + strh r9, [r1, #6] + +2: + add r8, r8, lr, lsl #1 + ldrh r3, [r8] // v + ldrh r4, [r8, #-2] // u + sub r4, r4, r3 // rng = u - v + clz r5, r4 // clz(rng) + eor r5, r5, #16 // d = clz(rng) ^ 16 + mvn r7, r7 // ~dif + add r7, r7, r3, lsl #16 // ~dif + (v << 16) + lsl r4, r4, r5 // rng << d + subs r6, r6, r5 // cnt -= d + lsl r7, r7, r5 // (~dif + (v << 16)) << d + str r4, [r0, #RNG] + vdup.16 d1, r4 + mvn r7, r7 // ~dif + bhs 9f + + // refill + ldr r3, [r0, #BUF_POS] // BUF_POS + ldr r4, [r0, #BUF_END] // BUF_END + add r5, r3, #4 + cmp r5, r4 + bgt 2f + + ldr r3, [r3] // next_bits + add r8, r6, #23 // shift_bits = cnt + 23 + add r6, r6, #16 // cnt += 16 + rev r3, r3 // next_bits = bswap(next_bits) + sub r5, r5, r8, lsr #3 // buf_pos -= shift_bits >> 3 + and r8, r8, #24 // shift_bits &= 24 + lsr r3, r3, r8 // next_bits >>= shift_bits + sub r8, r8, r6 // shift_bits -= 16 + cnt + str r5, [r0, #BUF_POS] + lsl r3, r3, r8 // next_bits <<= shift_bits + rsb r6, r8, #16 // cnt = cnt + 32 - shift_bits + eor r7, r7, r3 // dif ^= next_bits + b 9f + +2: // refill_eob + rsb r5, r6, #8 // c = 40 - cnt +3: + cmp r3, r4 + bge 4f + ldrb r8, [r3], #1 + lsl r8, r8, r5 + eor r7, r7, r8 + subs r5, r5, #8 + bge 3b + +4: // refill_eob_end + str r3, [r0, #BUF_POS] + rsb r6, r5, #8 // cnt = 40 - c + +9: + lsl lr, lr, #1 + sub lr, lr, #5 + lsr r12, r7, #16 + adds r2, r2, lr // carry = tok_br < 3 || tok == 15 + vdup.16 q1, r12 + bcc 1b // loop if !carry + add r2, r2, #30 + str r6, [r0, #CNT] + add sp, sp, #48 + str r7, [r0, #DIF] + lsr r0, r2, #1 + pop {r4-r10,pc} +endfunc + +function msac_decode_bool_equi_neon, export=1 + push {r4-r10,lr} + ldr r5, [r0, #RNG] + ldr r6, [r0, #CNT] + sub sp, sp, #48 + ldr r7, [r0, #DIF] + bic r4, r5, #0xff // r &= 0xff00 + add r4, r4, #8 + mov r2, #0 + subs r8, r7, r4, lsl #15 // dif - vw + lsr r4, r4, #1 // v + sub r5, r5, r4 // r - v + itee lo + movlo r2, #1 + movhs r4, r5 // if (ret) v = r - v; + movhs r7, r8 // if (ret) dif = dif - vw; + + clz r5, r4 // clz(rng) + mvn r7, r7 // ~dif + eor r5, r5, #16 // d = clz(rng) ^ 16 + mov lr, r2 + b L(renorm2) +endfunc + +function msac_decode_bool_neon, export=1 + push {r4-r10,lr} + ldr r5, [r0, #RNG] + ldr r6, [r0, #CNT] + sub sp, sp, #48 + ldr r7, [r0, #DIF] + lsr r4, r5, #8 // r >> 8 + bic r1, r1, #0x3f // f &= ~63 + mul r4, r4, r1 + mov r2, #0 + lsr r4, r4, #7 + add r4, r4, #4 // v + subs r8, r7, r4, lsl #16 // dif - vw + sub r5, r5, r4 // r - v + itee lo + movlo r2, #1 + movhs r4, r5 // if (ret) v = r - v; + movhs r7, r8 // if (ret) dif = dif - vw; + + clz r5, r4 // clz(rng) + mvn r7, r7 // ~dif + eor r5, r5, #16 // d = clz(rng) ^ 16 + mov lr, r2 + b L(renorm2) +endfunc + +function msac_decode_bool_adapt_neon, export=1 + push {r4-r10,lr} + ldr r9, [r1] // cdf[0-1] + ldr r5, [r0, #RNG] + movw lr, #0xffc0 + ldr r6, [r0, #CNT] + sub sp, sp, #48 + ldr r7, [r0, #DIF] + lsr r4, r5, #8 // r >> 8 + and r2, r9, lr // f &= ~63 + mul r4, r4, r2 + mov r2, #0 + lsr r4, r4, #7 + add r4, r4, #4 // v + subs r8, r7, r4, lsl #16 // dif - vw + sub r5, r5, r4 // r - v + ldr r10, [r0, #ALLOW_UPDATE_CDF] + itee lo + movlo r2, #1 + movhs r4, r5 // if (ret) v = r - v; + movhs r7, r8 // if (ret) dif = dif - vw; + + cmp r10, #0 + clz r5, r4 // clz(rng) + mvn r7, r7 // ~dif + eor r5, r5, #16 // d = clz(rng) ^ 16 + mov lr, r2 + + beq L(renorm2) + + lsr r2, r9, #16 // count = cdf[1] + uxth r9, r9 // cdf[0] + + sub r3, r2, r2, lsr #5 // count - (count >= 32) + lsr r2, r2, #4 // count >> 4 + add r10, r3, #1 // count + (count < 32) + add r2, r2, #4 // rate = (count >> 4) | 4 + + sub r9, r9, lr // cdf[0] -= bit + sub r3, r9, lr, lsl #15 // {cdf[0], cdf[0] - 32769} + asr r3, r3, r2 // {cdf[0], cdf[0] - 32769} >> rate + sub r9, r9, r3 // cdf[0] + + strh r9, [r1] + strh r10, [r1, #2] + + b L(renorm2) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/util.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/util.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/32/util.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/32/util.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,184 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2015 Martin Storsjo + * Copyright © 2015 Janne Grunau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef DAV1D_SRC_ARM_32_UTIL_S +#define DAV1D_SRC_ARM_32_UTIL_S + +#include "config.h" +#include "src/arm/asm.S" + +.macro movrel_local rd, val, offset=0 +#if defined(PIC) + ldr \rd, 90001f + b 90002f +90001: + .word \val + \offset - (90002f + 8 - 4 * CONFIG_THUMB) +90002: + add \rd, \rd, pc +#else + movw \rd, #:lower16:\val+\offset + movt \rd, #:upper16:\val+\offset +#endif +.endm + +.macro movrel rd, val, offset=0 +#if defined(PIC) && defined(__APPLE__) + ldr \rd, 1f + b 2f +1: + .word 3f - (2f + 8 - 4 * CONFIG_THUMB) +2: + ldr \rd, [pc, \rd] +.if \offset < 0 + sub \rd, \rd, #-(\offset) +.elseif \offset > 0 + add \rd, \rd, #\offset +.endif + .non_lazy_symbol_pointer +3: + .indirect_symbol \val + .word 0 + .text +#else + movrel_local \rd, \val, \offset +#endif +.endm + +// This macro clobbers r7 (and r12 on windows) and stores data at the +// bottom of the stack; sp is the start of the space allocated that +// the caller can use. +.macro sub_sp_align space +#if CONFIG_THUMB + mov r7, sp + and r7, r7, #15 +#else + and r7, sp, #15 +#endif + sub sp, sp, r7 + // Now the stack is aligned, store the amount of adjustment back + // on the stack, as we don't want to waste a register as frame + // pointer. + str r7, [sp, #-16]! +#ifdef _WIN32 +.if \space > 8192 + // Here, we'd need to touch two (or more) pages while decrementing + // the stack pointer. + .error "sub_sp_align doesn't support values over 8K at the moment" +.elseif \space > 4096 + sub r7, sp, #4096 + ldr r12, [r7] + sub r7, r7, #(\space - 4096) + mov sp, r7 +.else + sub sp, sp, #\space +.endif +#else +.if \space >= 4096 + sub sp, sp, #(\space)/4096*4096 +.endif +.if (\space % 4096) != 0 + sub sp, sp, #(\space)%4096 +.endif +#endif +.endm + +.macro add_sp_align space +.if \space >= 4096 + add sp, sp, #(\space)/4096*4096 +.endif +.if (\space % 4096) != 0 + add sp, sp, #(\space)%4096 +.endif + ldr r7, [sp], #16 + // Add back the original stack adjustment + add sp, sp, r7 +.endm + +.macro transpose_8x8b q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7 + vtrn.32 \q0, \q2 + vtrn.32 \q1, \q3 + + vtrn.16 \r0, \r2 + vtrn.16 \r1, \r3 + vtrn.16 \r4, \r6 + vtrn.16 \r5, \r7 + + vtrn.8 \r0, \r1 + vtrn.8 \r2, \r3 + vtrn.8 \r4, \r5 + vtrn.8 \r6, \r7 +.endm + +.macro transpose_8x8h r0, r1, r2, r3, r4, r5, r6, r7, d0, d1, d2, d3, d4, d5, d6, d7 + vswp \d0, \d4 + vswp \d1, \d5 + vswp \d2, \d6 + vswp \d3, \d7 + + vtrn.32 \r0, \r2 + vtrn.32 \r1, \r3 + vtrn.32 \r4, \r6 + vtrn.32 \r5, \r7 + + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 + vtrn.16 \r4, \r5 + vtrn.16 \r6, \r7 +.endm + +.macro transpose_4x8b q0, q1, r0, r1, r2, r3 + vtrn.16 \q0, \q1 + + vtrn.8 \r0, \r1 + vtrn.8 \r2, \r3 +.endm + +.macro transpose_4x4s q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7 + vswp \r1, \r4 // vtrn.64 \q0, \q2 + vswp \r3, \r6 // vtrn.64 \q1, \q3 + + vtrn.32 \q0, \q1 + vtrn.32 \q2, \q3 +.endm + +.macro transpose_4x4h q0, q1, r0, r1, r2, r3 + vtrn.32 \q0, \q1 + + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 +.endm + +.macro transpose_4x8h r0, r1, r2, r3 + vtrn.32 \r0, \r2 + vtrn.32 \r1, \r3 + + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 +.endm + +#endif /* DAV1D_SRC_ARM_32_UTIL_S */ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,520 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" +#include "cdef_tmpl.S" + +.macro pad_top_bottom s1, s2, w, stride, rn, rw, ret + tst w7, #1 // CDEF_HAVE_LEFT + b.eq 2f + // CDEF_HAVE_LEFT + sub \s1, \s1, #2 + sub \s2, \s2, #2 + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + ldr \rn\()0, [\s1] + ldr s1, [\s1, #\w] + ldr \rn\()2, [\s2] + ldr s3, [\s2, #\w] + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + uxtl v2.8h, v2.8b + uxtl v3.8h, v3.8b + str \rw\()0, [x0] + str d1, [x0, #2*\w] + add x0, x0, #2*\stride + str \rw\()2, [x0] + str d3, [x0, #2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ldr \rn\()0, [\s1] + ldr h1, [\s1, #\w] + ldr \rn\()2, [\s2] + ldr h3, [\s2, #\w] + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + uxtl v2.8h, v2.8b + uxtl v3.8h, v3.8b + str \rw\()0, [x0] + str s1, [x0, #2*\w] + str s31, [x0, #2*\w+4] + add x0, x0, #2*\stride + str \rw\()2, [x0] + str s3, [x0, #2*\w] + str s31, [x0, #2*\w+4] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +2: + // !CDEF_HAVE_LEFT + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + ldr \rn\()0, [\s1] + ldr h1, [\s1, #\w] + ldr \rn\()2, [\s2] + ldr h3, [\s2, #\w] + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + uxtl v2.8h, v2.8b + uxtl v3.8h, v3.8b + str s31, [x0] + stur \rw\()0, [x0, #4] + str s1, [x0, #4+2*\w] + add x0, x0, #2*\stride + str s31, [x0] + stur \rw\()2, [x0, #4] + str s3, [x0, #4+2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ldr \rn\()0, [\s1] + ldr \rn\()1, [\s2] + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + str s31, [x0] + stur \rw\()0, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + str s31, [x0] + stur \rw\()1, [x0, #4] + str s31, [x0, #4+2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride +.endif +3: +.endm + +.macro load_n_incr dst, src, incr, w +.if \w == 4 + ld1 {\dst\().s}[0], [\src], \incr +.else + ld1 {\dst\().8b}, [\src], \incr +.endif +.endm + +// void dav1d_cdef_paddingX_8bpc_neon(uint16_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +.macro padding_func w, stride, rn, rw +function cdef_padding\w\()_8bpc_neon, export=1 + cmp w7, #0xf // fully edged + b.eq cdef_padding\w\()_edged_8bpc_neon + movi v30.8h, #0x80, lsl #8 + mov v31.16b, v30.16b + sub x0, x0, #2*(2*\stride+2) + tst w7, #4 // CDEF_HAVE_TOP + b.ne 1f + // !CDEF_HAVE_TOP + st1 {v30.8h, v31.8h}, [x0], #32 +.if \w == 8 + st1 {v30.8h, v31.8h}, [x0], #32 +.endif + b 3f +1: + // CDEF_HAVE_TOP + add x9, x4, x2 + pad_top_bottom x4, x9, \w, \stride, \rn, \rw, 0 + + // Middle section +3: + tst w7, #1 // CDEF_HAVE_LEFT + b.eq 2f + // CDEF_HAVE_LEFT + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + ld1 {v0.h}[0], [x3], #2 + ldr h2, [x1, #\w] + load_n_incr v1, x1, x2, \w + subs w6, w6, #1 + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + uxtl v2.8h, v2.8b + str s0, [x0] + stur \rw\()1, [x0, #4] + str s2, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 0b + b 3f +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ld1 {v0.h}[0], [x3], #2 + load_n_incr v1, x1, x2, \w + subs w6, w6, #1 + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + str s0, [x0] + stur \rw\()1, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 1b + b 3f +2: + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + ldr h1, [x1, #\w] + load_n_incr v0, x1, x2, \w + subs w6, w6, #1 + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + str s31, [x0] + stur \rw\()0, [x0, #4] + str s1, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 0b + b 3f +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + load_n_incr v0, x1, x2, \w + subs w6, w6, #1 + uxtl v0.8h, v0.8b + str s31, [x0] + stur \rw\()0, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 1b + +3: + tst w7, #8 // CDEF_HAVE_BOTTOM + b.ne 1f + // !CDEF_HAVE_BOTTOM + st1 {v30.8h, v31.8h}, [x0], #32 +.if \w == 8 + st1 {v30.8h, v31.8h}, [x0], #32 +.endif + ret +1: + // CDEF_HAVE_BOTTOM + add x9, x5, x2 + pad_top_bottom x5, x9, \w, \stride, \rn, \rw, 1 +endfunc +.endm + +padding_func 8, 16, d, q +padding_func 4, 8, s, d + +// void cdef_paddingX_edged_8bpc_neon(uint8_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +.macro padding_func_edged w, stride, reg +function cdef_padding\w\()_edged_8bpc_neon, export=1 + sub x4, x4, #2 + sub x5, x5, #2 + sub x0, x0, #(2*\stride+2) + +.if \w == 4 + ldr d0, [x4] + ldr d1, [x4, x2] + st1 {v0.8b, v1.8b}, [x0], #16 +.else + add x9, x4, x2 + ldr d0, [x4] + ldr s1, [x4, #8] + ldr d2, [x9] + ldr s3, [x9, #8] + str d0, [x0] + str s1, [x0, #8] + str d2, [x0, #\stride] + str s3, [x0, #\stride+8] + add x0, x0, #2*\stride +.endif + +0: + ld1 {v0.h}[0], [x3], #2 + ldr h2, [x1, #\w] + load_n_incr v1, x1, x2, \w + subs w6, w6, #1 + str h0, [x0] + stur \reg\()1, [x0, #2] + str h2, [x0, #2+\w] + add x0, x0, #\stride + b.gt 0b + +.if \w == 4 + ldr d0, [x5] + ldr d1, [x5, x2] + st1 {v0.8b, v1.8b}, [x0], #16 +.else + add x9, x5, x2 + ldr d0, [x5] + ldr s1, [x5, #8] + ldr d2, [x9] + ldr s3, [x9, #8] + str d0, [x0] + str s1, [x0, #8] + str d2, [x0, #\stride] + str s3, [x0, #\stride+8] +.endif + ret +endfunc +.endm + +padding_func_edged 8, 16, d +padding_func_edged 4, 8, s + +tables + +filter 8, 8 +filter 4, 8 + +find_dir 8 + +.macro load_px_8 d1, d2, w +.if \w == 8 + add x6, x2, w9, sxtb // x + off + sub x9, x2, w9, sxtb // x - off + ld1 {\d1\().d}[0], [x6] // p0 + add x6, x6, #16 // += stride + ld1 {\d2\().d}[0], [x9] // p1 + add x9, x9, #16 // += stride + ld1 {\d1\().d}[1], [x6] // p0 + ld1 {\d2\().d}[1], [x9] // p0 +.else + add x6, x2, w9, sxtb // x + off + sub x9, x2, w9, sxtb // x - off + ld1 {\d1\().s}[0], [x6] // p0 + add x6, x6, #8 // += stride + ld1 {\d2\().s}[0], [x9] // p1 + add x9, x9, #8 // += stride + ld1 {\d1\().s}[1], [x6] // p0 + add x6, x6, #8 // += stride + ld1 {\d2\().s}[1], [x9] // p1 + add x9, x9, #8 // += stride + ld1 {\d1\().s}[2], [x6] // p0 + add x6, x6, #8 // += stride + ld1 {\d2\().s}[2], [x9] // p1 + add x9, x9, #8 // += stride + ld1 {\d1\().s}[3], [x6] // p0 + ld1 {\d2\().s}[3], [x9] // p1 +.endif +.endm +.macro handle_pixel_8 s1, s2, thresh_vec, shift, tap, min +.if \min + umin v3.16b, v3.16b, \s1\().16b + umax v4.16b, v4.16b, \s1\().16b + umin v3.16b, v3.16b, \s2\().16b + umax v4.16b, v4.16b, \s2\().16b +.endif + uabd v16.16b, v0.16b, \s1\().16b // abs(diff) + uabd v20.16b, v0.16b, \s2\().16b // abs(diff) + ushl v17.16b, v16.16b, \shift // abs(diff) >> shift + ushl v21.16b, v20.16b, \shift // abs(diff) >> shift + uqsub v17.16b, \thresh_vec, v17.16b // clip = imax(0, threshold - (abs(diff) >> shift)) + uqsub v21.16b, \thresh_vec, v21.16b // clip = imax(0, threshold - (abs(diff) >> shift)) + cmhi v18.16b, v0.16b, \s1\().16b // px > p0 + cmhi v22.16b, v0.16b, \s2\().16b // px > p1 + umin v17.16b, v17.16b, v16.16b // imin(abs(diff), clip) + umin v21.16b, v21.16b, v20.16b // imin(abs(diff), clip) + dup v19.16b, \tap // taps[k] + neg v16.16b, v17.16b // -imin() + neg v20.16b, v21.16b // -imin() + bsl v18.16b, v16.16b, v17.16b // constrain() = apply_sign() + bsl v22.16b, v20.16b, v21.16b // constrain() = apply_sign() + mla v1.16b, v18.16b, v19.16b // sum += taps[k] * constrain() + mla v2.16b, v22.16b, v19.16b // sum += taps[k] * constrain() +.endm + +// void cdef_filterX_edged_8bpc_neon(pixel *dst, ptrdiff_t dst_stride, +// const uint8_t *tmp, int pri_strength, +// int sec_strength, int dir, int damping, +// int h); +.macro filter_func_8 w, pri, sec, min, suffix +function cdef_filter\w\suffix\()_edged_8bpc_neon +.if \pri + movrel x8, pri_taps + and w9, w3, #1 + add x8, x8, w9, uxtw #1 +.endif + movrel x9, directions\w + add x5, x9, w5, uxtw #1 + movi v30.8b, #7 + dup v28.8b, w6 // damping + +.if \pri + dup v25.16b, w3 // threshold +.endif +.if \sec + dup v27.16b, w4 // threshold +.endif + trn1 v24.8b, v25.8b, v27.8b + clz v24.8b, v24.8b // clz(threshold) + sub v24.8b, v30.8b, v24.8b // ulog2(threshold) + uqsub v24.8b, v28.8b, v24.8b // shift = imax(0, damping - ulog2(threshold)) + neg v24.8b, v24.8b // -shift +.if \sec + dup v26.16b, v24.b[1] +.endif +.if \pri + dup v24.16b, v24.b[0] +.endif + +1: +.if \w == 8 + add x12, x2, #16 + ld1 {v0.d}[0], [x2] // px + ld1 {v0.d}[1], [x12] // px +.else + add x12, x2, #1*8 + add x13, x2, #2*8 + add x14, x2, #3*8 + ld1 {v0.s}[0], [x2] // px + ld1 {v0.s}[1], [x12] // px + ld1 {v0.s}[2], [x13] // px + ld1 {v0.s}[3], [x14] // px +.endif + + // We need 9-bits or two 8-bit accululators to fit the sum. + // Max of |sum| > 15*2*6(pri) + 4*4*3(sec) = 228. + // Start sum at -1 instead of 0 to help handle rounding later. + movi v1.16b, #255 // sum + movi v2.16b, #0 // sum +.if \min + mov v3.16b, v0.16b // min + mov v4.16b, v0.16b // max +.endif + + // Instead of loading sec_taps 2, 1 from memory, just set it + // to 2 initially and decrease for the second round. + // This is also used as loop counter. + mov w11, #2 // sec_taps[0] + +2: +.if \pri + ldrb w9, [x5] // off1 + + load_px_8 v5, v6, \w +.endif + +.if \sec + add x5, x5, #4 // +2*2 + ldrb w9, [x5] // off2 + load_px_8 v28, v29, \w +.endif + +.if \pri + ldrb w10, [x8] // *pri_taps + + handle_pixel_8 v5, v6, v25.16b, v24.16b, w10, \min +.endif + +.if \sec + add x5, x5, #8 // +2*4 + ldrb w9, [x5] // off3 + load_px_8 v5, v6, \w + + handle_pixel_8 v28, v29, v27.16b, v26.16b, w11, \min + + handle_pixel_8 v5, v6, v27.16b, v26.16b, w11, \min + + sub x5, x5, #11 // x5 -= 2*(2+4); x5 += 1; +.else + add x5, x5, #1 // x5 += 1 +.endif + subs w11, w11, #1 // sec_tap-- (value) +.if \pri + add x8, x8, #1 // pri_taps++ (pointer) +.endif + b.ne 2b + + // Perform halving adds since the value won't fit otherwise. + // To handle the offset for negative values, use both halving w/ and w/o rounding. + srhadd v5.16b, v1.16b, v2.16b // sum >> 1 + shadd v6.16b, v1.16b, v2.16b // (sum - 1) >> 1 + cmlt v1.16b, v5.16b, #0 // sum < 0 + bsl v1.16b, v6.16b, v5.16b // (sum - (sum < 0)) >> 1 + + srshr v1.16b, v1.16b, #3 // (8 + sum - (sum < 0)) >> 4 + + usqadd v0.16b, v1.16b // px + (8 + sum ...) >> 4 +.if \min + umin v0.16b, v0.16b, v4.16b + umax v0.16b, v0.16b, v3.16b // iclip(px + .., min, max) +.endif +.if \w == 8 + st1 {v0.d}[0], [x0], x1 + add x2, x2, #2*16 // tmp += 2*tmp_stride + subs w7, w7, #2 // h -= 2 + st1 {v0.d}[1], [x0], x1 +.else + st1 {v0.s}[0], [x0], x1 + add x2, x2, #4*8 // tmp += 4*tmp_stride + st1 {v0.s}[1], [x0], x1 + subs w7, w7, #4 // h -= 4 + st1 {v0.s}[2], [x0], x1 + st1 {v0.s}[3], [x0], x1 +.endif + + // Reset pri_taps and directions back to the original point + sub x5, x5, #2 +.if \pri + sub x8, x8, #2 +.endif + + b.gt 1b + ret +endfunc +.endm + +.macro filter_8 w +filter_func_8 \w, pri=1, sec=0, min=0, suffix=_pri +filter_func_8 \w, pri=0, sec=1, min=0, suffix=_sec +filter_func_8 \w, pri=1, sec=1, min=1, suffix=_pri_sec +.endm + +filter_8 8 +filter_8 4 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" +#include "cdef_tmpl.S" + +.macro pad_top_bot_16 s1, s2, w, stride, reg, ret + tst w7, #1 // CDEF_HAVE_LEFT + b.eq 2f + // CDEF_HAVE_LEFT + sub \s1, \s1, #4 + sub \s2, \s2, #4 + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + ldr \reg\()0, [\s1] + ldr d1, [\s1, #2*\w] + ldr \reg\()2, [\s2] + ldr d3, [\s2, #2*\w] + str \reg\()0, [x0] + str d1, [x0, #2*\w] + add x0, x0, #2*\stride + str \reg\()2, [x0] + str d3, [x0, #2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ldr \reg\()0, [\s1] + ldr s1, [\s1, #2*\w] + ldr \reg\()2, [\s2] + ldr s3, [\s2, #2*\w] + str \reg\()0, [x0] + str s1, [x0, #2*\w] + str s31, [x0, #2*\w+4] + add x0, x0, #2*\stride + str \reg\()2, [x0] + str s3, [x0, #2*\w] + str s31, [x0, #2*\w+4] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +2: + // !CDEF_HAVE_LEFT + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT + ldr \reg\()0, [\s1] + ldr s1, [\s1, #2*\w] + ldr \reg\()2, [\s2] + ldr s3, [\s2, #2*\w] + str s31, [x0] + stur \reg\()0, [x0, #4] + str s1, [x0, #4+2*\w] + add x0, x0, #2*\stride + str s31, [x0] + stur \reg\()2, [x0, #4] + str s3, [x0, #4+2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride + b 3f +.endif + +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ldr \reg\()0, [\s1] + ldr \reg\()1, [\s2] + str s31, [x0] + stur \reg\()0, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + str s31, [x0] + stur \reg\()1, [x0, #4] + str s31, [x0, #4+2*\w] +.if \ret + ret +.else + add x0, x0, #2*\stride +.endif +3: +.endm + +.macro load_n_incr_16 dst, src, incr, w +.if \w == 4 + ld1 {\dst\().4h}, [\src], \incr +.else + ld1 {\dst\().8h}, [\src], \incr +.endif +.endm + +// void dav1d_cdef_paddingX_16bpc_neon(uint16_t *tmp, const pixel *src, +// ptrdiff_t src_stride, const pixel (*left)[2], +// const pixel *const top, +// const pixel *const bottom, int h, +// enum CdefEdgeFlags edges); + +.macro padding_func_16 w, stride, reg +function cdef_padding\w\()_16bpc_neon, export=1 + movi v30.8h, #0x80, lsl #8 + mov v31.16b, v30.16b + sub x0, x0, #2*(2*\stride+2) + tst w7, #4 // CDEF_HAVE_TOP + b.ne 1f + // !CDEF_HAVE_TOP + st1 {v30.8h, v31.8h}, [x0], #32 +.if \w == 8 + st1 {v30.8h, v31.8h}, [x0], #32 +.endif + b 3f +1: + // CDEF_HAVE_TOP + add x9, x4, x2 + pad_top_bot_16 x4, x9, \w, \stride, \reg, 0 + + // Middle section +3: + tst w7, #1 // CDEF_HAVE_LEFT + b.eq 2f + // CDEF_HAVE_LEFT + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + ld1 {v0.s}[0], [x3], #4 + ldr s2, [x1, #2*\w] + load_n_incr_16 v1, x1, x2, \w + subs w6, w6, #1 + str s0, [x0] + stur \reg\()1, [x0, #4] + str s2, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 0b + b 3f +1: + // CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + ld1 {v0.s}[0], [x3], #4 + load_n_incr_16 v1, x1, x2, \w + subs w6, w6, #1 + str s0, [x0] + stur \reg\()1, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 1b + b 3f +2: + tst w7, #2 // CDEF_HAVE_RIGHT + b.eq 1f + // !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT +0: + ldr s1, [x1, #2*\w] + load_n_incr_16 v0, x1, x2, \w + subs w6, w6, #1 + str s31, [x0] + stur \reg\()0, [x0, #4] + str s1, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 0b + b 3f +1: + // !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT + load_n_incr_16 v0, x1, x2, \w + subs w6, w6, #1 + str s31, [x0] + stur \reg\()0, [x0, #4] + str s31, [x0, #4+2*\w] + add x0, x0, #2*\stride + b.gt 1b + +3: + tst w7, #8 // CDEF_HAVE_BOTTOM + b.ne 1f + // !CDEF_HAVE_BOTTOM + st1 {v30.8h, v31.8h}, [x0], #32 +.if \w == 8 + st1 {v30.8h, v31.8h}, [x0], #32 +.endif + ret +1: + // CDEF_HAVE_BOTTOM + add x9, x5, x2 + pad_top_bot_16 x5, x9, \w, \stride, \reg, 1 +endfunc +.endm + +padding_func_16 8, 16, q +padding_func_16 4, 8, d + +tables + +filter 8, 16 +filter 4, 16 + +find_dir 16 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_dist.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_dist.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_dist.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_dist.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,250 @@ +/* Copyright (c) 2023, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// v0: tmp register +// v1: src input +// v2: dst input +// v3 = sum(src_{i,j}) +// v4 = sum(src_{i,j}^2) +// v5 = sum(dst_{i,j}) +// v6 = sum(dst_{i,j}^2) +// v7 = sum(src_{i,j} * dst_{i,j}) +// v16: zero register +.macro CDEF_DIST_W8 + uabal v3.8h, v1.8b, v16.8b // sum pixel values + umull v0.8h, v1.8b, v1.8b // square + uabal v4.4s, v0.4h, v16.4h // accumulate + uabal2 v4.4s, v0.8h, v16.8h + uabal v5.8h, v2.8b, v16.8b // same as above, but for dst + umull v0.8h, v2.8b, v2.8b + uabal v6.4s, v0.4h, v16.4h + uabal2 v6.4s, v0.8h, v16.8h + umull v0.8h, v1.8b, v2.8b // src_{i,j} * dst_{i,j} + uabal v7.4s, v0.4h, v16.4h + uabal2 v7.4s, v0.8h, v16.8h +.endm + +.macro CDEF_DIST_REFINE shift=0 + addv h3, v3.8h + umull v3.4s, v3.4h, v3.4h + urshr v3.4s, v3.4s, #(6-\shift) // s3: sum(src_{i,j})^2 / N + addv s4, v4.4s // s4: sum(src_{i,j}^2) + addv h5, v5.8h + umull v5.4s, v5.4h, v5.4h + urshr v5.4s, v5.4s, #(6-\shift) // s5: sum(dst_{i,j})^2 / N + addv s6, v6.4s // s6: sum(dst_{i,j}^2) + addv s7, v7.4s + add v0.4s, v4.4s, v6.4s + sub v0.4s, v0.4s, v7.4s + sub v0.4s, v0.4s, v7.4s // s0: sse + uqsub v4.4s, v4.4s, v3.4s // s4: svar + uqsub v6.4s, v6.4s, v5.4s // s6: dvar +.if \shift != 0 + shl v4.4s, v4.4s, #\shift + shl v6.4s, v6.4s, #\shift +.endif + str s4, [x4] + str s6, [x4, #4] + str s0, [x4, #8] +.endm + +.macro LOAD_ROW + ldr d1, [x0] + ldr d2, [x2] + add x0, x0, x1 + add x2, x2, x3 +.endm + +.macro LOAD_ROWS + ldr s1, [x0] + ldr s2, [x2] + ldr s0, [x0, x1] + ldr s17, [x2, x3] + add x0, x0, x1, lsl 1 + add x2, x2, x3, lsl 1 + zip1 v1.2s, v1.2s, v0.2s + zip1 v2.2s, v2.2s, v17.2s +.endm + +.macro CDEF_DIST_INIT width, height +.irp i, v3.8h, v4.8h, v5.8h, v6.8h, v7.8h, v16.8h + movi \i, #0 +.endr +.if \width == 4 + mov w5, #(\height / 2) +.else + mov w5, #\height +.endif +.endm + +// x0: src: *const u8, +// x1: src_stride: isize, +// x2: dst: *const u8, +// x3: dst_stride: isize, +// x4: ret_ptr: *mut u32, +function cdef_dist_kernel_4x4_neon, export=1 + CDEF_DIST_INIT 4, 4 +L(cdk_4x4): + LOAD_ROWS + CDEF_DIST_W8 + subs w5, w5, #1 + bne L(cdk_4x4) + CDEF_DIST_REFINE 2 + ret +endfunc + +function cdef_dist_kernel_4x8_neon, export=1 + CDEF_DIST_INIT 4, 8 +L(cdk_4x8): + LOAD_ROWS + CDEF_DIST_W8 + subs w5, w5, #1 + bne L(cdk_4x8) + CDEF_DIST_REFINE 1 + ret +endfunc + +function cdef_dist_kernel_8x4_neon, export=1 + CDEF_DIST_INIT 8, 4 +L(cdk_8x4): + LOAD_ROW + CDEF_DIST_W8 + subs w5, w5, #1 + bne L(cdk_8x4) + CDEF_DIST_REFINE 1 + ret +endfunc + +function cdef_dist_kernel_8x8_neon, export=1 + CDEF_DIST_INIT 8, 8 +L(cdk_8x8): + LOAD_ROW + CDEF_DIST_W8 + subs w5, w5, #1 + bne L(cdk_8x8) + CDEF_DIST_REFINE + ret +endfunc + +// v0: tmp register +// v1: src input +// v2: dst input +// v3 = sum(src_{i,j}) +// v4 = sum(src_{i,j}^2) +// v5 = sum(dst_{i,j}) +// v6 = sum(dst_{i,j}^2) +// v7 = sum(src_{i,j} * dst_{i,j}) +// v16: zero register +.macro CDEF_DIST_HBD_W8 + uabal v3.4s, v1.4h, v16.4h // sum pixel values + uabal2 v3.4s, v1.8h, v16.8h + umlal v4.4s, v1.4h, v1.4h // square and accumulate + umlal2 v4.4s, v1.8h, v1.8h + uabal v5.4s, v2.4h, v16.4h // same as above, but for dst + uabal2 v5.4s, v2.8h, v16.8h + umlal v6.4s, v2.4h, v2.4h + umlal2 v6.4s, v2.8h, v2.8h + umlal v7.4s, v1.4h, v2.4h // src_{i,j} * dst_{i,j} + umlal2 v7.4s, v1.8h, v2.8h +.endm + +.macro CDEF_DIST_HBD_REFINE shift=0 + addv s3, v3.4s + umull v3.2d, v3.2s, v3.2s + urshr d3, d3, #(6-\shift) // d3: sum(src_{i,j})^2 / N + uaddlv d4, v4.4s // d4: sum(src_{i,j}^2) + addv s5, v5.4s + umull v5.2d, v5.2s, v5.2s + urshr d5, d5, #(6-\shift) // d5: sum(dst_{i,j})^2 / N + uaddlv d6, v6.4s // d6: sum(dst_{i,j}^2) + uaddlv d7, v7.4s + add d0, d4, d6 + sub d0, d0, d7 + sub d0, d0, d7 // d0: sse + uqsub d4, d4, d3 // d4: svar + uqsub d6, d6, d5 // d6: dvar +.if \shift != 0 + shl d4, d4, #\shift + shl d6, d6, #\shift +.endif + str s4, [x4] + str s6, [x4, #4] + str s0, [x4, #8] +.endm + +.macro LOAD_ROW_HBD + ldr q1, [x0] + ldr q2, [x2] + add x0, x0, x1 + add x2, x2, x3 +.endm + +.macro LOAD_ROWS_HBD + ldr d1, [x0] + ldr d2, [x2] + ldr d0, [x0, x1] + ldr d17, [x2, x3] + add x0, x0, x1, lsl 1 + add x2, x2, x3, lsl 1 + mov v1.d[1], v0.d[0] + mov v2.d[1], v17.d[0] +.endm + +// x0: src: *const u16, +// x1: src_stride: isize, +// x2: dst: *const u16, +// x3: dst_stride: isize, +// x4: ret_ptr: *mut u32, +function cdef_dist_kernel_4x4_hbd_neon, export=1 + CDEF_DIST_INIT 4, 4 +L(cdk_hbd_4x4): + LOAD_ROWS_HBD + CDEF_DIST_HBD_W8 + subs w5, w5, #1 + bne L(cdk_hbd_4x4) + CDEF_DIST_HBD_REFINE 2 + ret +endfunc + +function cdef_dist_kernel_4x8_hbd_neon, export=1 + CDEF_DIST_INIT 4, 8 +L(cdk_hbd_4x8): + LOAD_ROWS_HBD + CDEF_DIST_HBD_W8 + subs w5, w5, #1 + bne L(cdk_hbd_4x8) + CDEF_DIST_HBD_REFINE 1 + ret +endfunc + +function cdef_dist_kernel_8x4_hbd_neon, export=1 + CDEF_DIST_INIT 8, 4 +L(cdk_hbd_8x4): + LOAD_ROW_HBD + CDEF_DIST_HBD_W8 + subs w5, w5, #1 + bne L(cdk_hbd_8x4) + CDEF_DIST_HBD_REFINE 1 + ret +endfunc + +function cdef_dist_kernel_8x8_hbd_neon, export=1 + CDEF_DIST_INIT 8, 8 +L(cdk_hbd_8x8): + LOAD_ROW_HBD + CDEF_DIST_HBD_W8 + subs w5, w5, #1 + bne L(cdk_hbd_8x8) + CDEF_DIST_HBD_REFINE + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_tmpl.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_tmpl.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_tmpl.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/cdef_tmpl.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,511 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro dir_table w, stride +const directions\w + .byte -1 * \stride + 1, -2 * \stride + 2 + .byte 0 * \stride + 1, -1 * \stride + 2 + .byte 0 * \stride + 1, 0 * \stride + 2 + .byte 0 * \stride + 1, 1 * \stride + 2 + .byte 1 * \stride + 1, 2 * \stride + 2 + .byte 1 * \stride + 0, 2 * \stride + 1 + .byte 1 * \stride + 0, 2 * \stride + 0 + .byte 1 * \stride + 0, 2 * \stride - 1 +// Repeated, to avoid & 7 + .byte -1 * \stride + 1, -2 * \stride + 2 + .byte 0 * \stride + 1, -1 * \stride + 2 + .byte 0 * \stride + 1, 0 * \stride + 2 + .byte 0 * \stride + 1, 1 * \stride + 2 + .byte 1 * \stride + 1, 2 * \stride + 2 + .byte 1 * \stride + 0, 2 * \stride + 1 +endconst +.endm + +.macro tables +dir_table 8, 16 +dir_table 4, 8 + +const pri_taps + .byte 4, 2, 3, 3 +endconst +.endm + +.macro load_px d1, d2, w +.if \w == 8 + add x6, x2, w9, sxtb #1 // x + off + sub x9, x2, w9, sxtb #1 // x - off + ld1 {\d1\().8h}, [x6] // p0 + ld1 {\d2\().8h}, [x9] // p1 +.else + add x6, x2, w9, sxtb #1 // x + off + sub x9, x2, w9, sxtb #1 // x - off + ld1 {\d1\().4h}, [x6] // p0 + add x6, x6, #2*8 // += stride + ld1 {\d2\().4h}, [x9] // p1 + add x9, x9, #2*8 // += stride + ld1 {\d1\().d}[1], [x6] // p0 + ld1 {\d2\().d}[1], [x9] // p1 +.endif +.endm +.macro handle_pixel s1, s2, thresh_vec, shift, tap, min +.if \min + umin v2.8h, v2.8h, \s1\().8h + smax v3.8h, v3.8h, \s1\().8h + umin v2.8h, v2.8h, \s2\().8h + smax v3.8h, v3.8h, \s2\().8h +.endif + uabd v16.8h, v0.8h, \s1\().8h // abs(diff) + uabd v20.8h, v0.8h, \s2\().8h // abs(diff) + ushl v17.8h, v16.8h, \shift // abs(diff) >> shift + ushl v21.8h, v20.8h, \shift // abs(diff) >> shift + uqsub v17.8h, \thresh_vec, v17.8h // clip = imax(0, threshold - (abs(diff) >> shift)) + uqsub v21.8h, \thresh_vec, v21.8h // clip = imax(0, threshold - (abs(diff) >> shift)) + sub v18.8h, \s1\().8h, v0.8h // diff = p0 - px + sub v22.8h, \s2\().8h, v0.8h // diff = p1 - px + neg v16.8h, v17.8h // -clip + neg v20.8h, v21.8h // -clip + smin v18.8h, v18.8h, v17.8h // imin(diff, clip) + smin v22.8h, v22.8h, v21.8h // imin(diff, clip) + dup v19.8h, \tap // taps[k] + smax v18.8h, v18.8h, v16.8h // constrain() = imax(imin(diff, clip), -clip) + smax v22.8h, v22.8h, v20.8h // constrain() = imax(imin(diff, clip), -clip) + mla v1.8h, v18.8h, v19.8h // sum += taps[k] * constrain() + mla v1.8h, v22.8h, v19.8h // sum += taps[k] * constrain() +.endm + +// void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride, +// const uint16_t *tmp, int pri_strength, +// int sec_strength, int dir, int damping, +// int h, size_t edges); +.macro filter_func w, bpc, pri, sec, min, suffix +function cdef_filter\w\suffix\()_\bpc\()bpc_neon +.if \bpc == 8 + ldr w8, [sp] // edges + cmp w8, #0xf + b.eq cdef_filter\w\suffix\()_edged_8bpc_neon +.endif +.if \pri +.if \bpc == 16 + ldr w9, [sp, #8] // bitdepth_max + clz w9, w9 + sub w9, w9, #24 // -bitdepth_min_8 + neg w9, w9 // bitdepth_min_8 +.endif + movrel x8, pri_taps +.if \bpc == 16 + lsr w9, w3, w9 // pri_strength >> bitdepth_min_8 + and w9, w9, #1 // (pri_strength >> bitdepth_min_8) & 1 +.else + and w9, w3, #1 +.endif + add x8, x8, w9, uxtw #1 +.endif + movrel x9, directions\w + add x5, x9, w5, uxtw #1 + movi v30.4h, #15 + dup v28.4h, w6 // damping + +.if \pri + dup v25.8h, w3 // threshold +.endif +.if \sec + dup v27.8h, w4 // threshold +.endif + trn1 v24.4h, v25.4h, v27.4h + clz v24.4h, v24.4h // clz(threshold) + sub v24.4h, v30.4h, v24.4h // ulog2(threshold) + uqsub v24.4h, v28.4h, v24.4h // shift = imax(0, damping - ulog2(threshold)) + neg v24.4h, v24.4h // -shift +.if \sec + dup v26.8h, v24.h[1] +.endif +.if \pri + dup v24.8h, v24.h[0] +.endif + +1: +.if \w == 8 + ld1 {v0.8h}, [x2] // px +.else + add x12, x2, #2*8 + ld1 {v0.4h}, [x2] // px + ld1 {v0.d}[1], [x12] // px +.endif + + movi v1.8h, #0 // sum +.if \min + mov v2.16b, v0.16b // min + mov v3.16b, v0.16b // max +.endif + + // Instead of loading sec_taps 2, 1 from memory, just set it + // to 2 initially and decrease for the second round. + // This is also used as loop counter. + mov w11, #2 // sec_taps[0] + +2: +.if \pri + ldrb w9, [x5] // off1 + + load_px v4, v5, \w +.endif + +.if \sec + add x5, x5, #4 // +2*2 + ldrb w9, [x5] // off2 + load_px v6, v7, \w +.endif + +.if \pri + ldrb w10, [x8] // *pri_taps + + handle_pixel v4, v5, v25.8h, v24.8h, w10, \min +.endif + +.if \sec + add x5, x5, #8 // +2*4 + ldrb w9, [x5] // off3 + load_px v4, v5, \w + + handle_pixel v6, v7, v27.8h, v26.8h, w11, \min + + handle_pixel v4, v5, v27.8h, v26.8h, w11, \min + + sub x5, x5, #11 // x5 -= 2*(2+4); x5 += 1; +.else + add x5, x5, #1 // x5 += 1 +.endif + subs w11, w11, #1 // sec_tap-- (value) +.if \pri + add x8, x8, #1 // pri_taps++ (pointer) +.endif + b.ne 2b + + cmlt v4.8h, v1.8h, #0 // -(sum < 0) + add v1.8h, v1.8h, v4.8h // sum - (sum < 0) + srshr v1.8h, v1.8h, #4 // (8 + sum - (sum < 0)) >> 4 + add v0.8h, v0.8h, v1.8h // px + (8 + sum ...) >> 4 +.if \min + smin v0.8h, v0.8h, v3.8h + smax v0.8h, v0.8h, v2.8h // iclip(px + .., min, max) +.endif +.if \bpc == 8 + xtn v0.8b, v0.8h +.endif +.if \w == 8 + add x2, x2, #2*16 // tmp += tmp_stride + subs w7, w7, #1 // h-- +.if \bpc == 8 + st1 {v0.8b}, [x0], x1 +.else + st1 {v0.8h}, [x0], x1 +.endif +.else +.if \bpc == 8 + st1 {v0.s}[0], [x0], x1 +.else + st1 {v0.d}[0], [x0], x1 +.endif + add x2, x2, #2*16 // tmp += 2*tmp_stride + subs w7, w7, #2 // h -= 2 +.if \bpc == 8 + st1 {v0.s}[1], [x0], x1 +.else + st1 {v0.d}[1], [x0], x1 +.endif +.endif + + // Reset pri_taps and directions back to the original point + sub x5, x5, #2 +.if \pri + sub x8, x8, #2 +.endif + + b.gt 1b + ret +endfunc +.endm + +.macro filter w, bpc +filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri +filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec +filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec + +function cdef_filter\w\()_\bpc\()bpc_neon, export=1 + cbnz w3, 1f // pri_strength + b cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec +1: + cbnz w4, 1f // sec_strength + b cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri +1: + b cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec +endfunc +.endm + +const div_table + .short 840, 420, 280, 210, 168, 140, 120, 105 +endconst + +const alt_fact + .short 420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0 +endconst + +.macro cost_alt d1, d2, s1, s2, s3, s4 + smull v22.4s, \s1\().4h, \s1\().4h // sum_alt[n]*sum_alt[n] + smull2 v23.4s, \s1\().8h, \s1\().8h + smull v24.4s, \s2\().4h, \s2\().4h + smull v25.4s, \s3\().4h, \s3\().4h // sum_alt[n]*sum_alt[n] + smull2 v26.4s, \s3\().8h, \s3\().8h + smull v27.4s, \s4\().4h, \s4\().4h + mul v22.4s, v22.4s, v29.4s // sum_alt[n]^2*fact + mla v22.4s, v23.4s, v30.4s + mla v22.4s, v24.4s, v31.4s + mul v25.4s, v25.4s, v29.4s // sum_alt[n]^2*fact + mla v25.4s, v26.4s, v30.4s + mla v25.4s, v27.4s, v31.4s + addv \d1, v22.4s // *cost_ptr + addv \d2, v25.4s // *cost_ptr +.endm + +.macro find_best s1, s2, s3 +.ifnb \s2 + mov w5, \s2\().s[0] +.endif + cmp w4, w1 // cost[n] > best_cost + csel w0, w3, w0, gt // best_dir = n + csel w1, w4, w1, gt // best_cost = cost[n] +.ifnb \s2 + add w3, w3, #1 // n++ + cmp w5, w1 // cost[n] > best_cost + mov w4, \s3\().s[0] + csel w0, w3, w0, gt // best_dir = n + csel w1, w5, w1, gt // best_cost = cost[n] + add w3, w3, #1 // n++ +.endif +.endm + +// Steps for loading and preparing each row +.macro dir_load_step1 s1, bpc +.if \bpc == 8 + ld1 {\s1\().8b}, [x0], x1 +.else + ld1 {\s1\().8h}, [x0], x1 +.endif +.endm + +.macro dir_load_step2 s1, bpc +.if \bpc == 8 + usubl \s1\().8h, \s1\().8b, v31.8b +.else + ushl \s1\().8h, \s1\().8h, v8.8h +.endif +.endm + +.macro dir_load_step3 s1, bpc +// Nothing for \bpc == 8 +.if \bpc != 8 + sub \s1\().8h, \s1\().8h, v31.8h +.endif +.endm + +// int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride, +// unsigned *const var) +.macro find_dir bpc +function cdef_find_dir_\bpc\()bpc_neon, export=1 +.if \bpc == 16 + str d8, [sp, #-0x10]! + clz w3, w3 // clz(bitdepth_max) + sub w3, w3, #24 // -bitdepth_min_8 + dup v8.8h, w3 +.endif + sub sp, sp, #32 // cost + mov w3, #8 +.if \bpc == 8 + movi v31.16b, #128 +.else + movi v31.8h, #128 +.endif + movi v30.16b, #0 + movi v1.8h, #0 // v0-v1 sum_diag[0] + movi v3.8h, #0 // v2-v3 sum_diag[1] + movi v5.8h, #0 // v4-v5 sum_hv[0-1] + movi v7.8h, #0 // v6-v7 sum_alt[0] + dir_load_step1 v26, \bpc // Setup first row early + movi v17.8h, #0 // v16-v17 sum_alt[1] + movi v18.8h, #0 // v18-v19 sum_alt[2] + dir_load_step2 v26, \bpc + movi v19.8h, #0 + dir_load_step3 v26, \bpc + movi v21.8h, #0 // v20-v21 sum_alt[3] + +.irpc i, 01234567 + addv h25, v26.8h // [y] + rev64 v27.8h, v26.8h + addp v28.8h, v26.8h, v30.8h // [(x >> 1)] + add v5.8h, v5.8h, v26.8h // sum_hv[1] + ext v27.16b, v27.16b, v27.16b, #8 // [-x] + rev64 v29.4h, v28.4h // [-(x >> 1)] + ins v4.h[\i], v25.h[0] // sum_hv[0] +.if \i < 6 + ext v22.16b, v30.16b, v26.16b, #(16-2*(3-(\i/2))) + ext v23.16b, v26.16b, v30.16b, #(16-2*(3-(\i/2))) + add v18.8h, v18.8h, v22.8h // sum_alt[2] + add v19.4h, v19.4h, v23.4h // sum_alt[2] +.else + add v18.8h, v18.8h, v26.8h // sum_alt[2] +.endif +.if \i == 0 + mov v20.16b, v26.16b // sum_alt[3] +.elseif \i == 1 + add v20.8h, v20.8h, v26.8h // sum_alt[3] +.else + ext v24.16b, v30.16b, v26.16b, #(16-2*(\i/2)) + ext v25.16b, v26.16b, v30.16b, #(16-2*(\i/2)) + add v20.8h, v20.8h, v24.8h // sum_alt[3] + add v21.4h, v21.4h, v25.4h // sum_alt[3] +.endif +.if \i == 0 + mov v0.16b, v26.16b // sum_diag[0] + dir_load_step1 v26, \bpc + mov v2.16b, v27.16b // sum_diag[1] + dir_load_step2 v26, \bpc + mov v6.16b, v28.16b // sum_alt[0] + dir_load_step3 v26, \bpc + mov v16.16b, v29.16b // sum_alt[1] +.else + ext v22.16b, v30.16b, v26.16b, #(16-2*\i) + ext v23.16b, v26.16b, v30.16b, #(16-2*\i) + ext v24.16b, v30.16b, v27.16b, #(16-2*\i) + ext v25.16b, v27.16b, v30.16b, #(16-2*\i) +.if \i != 7 // Nothing to load for the final row + dir_load_step1 v26, \bpc // Start setting up the next row early. +.endif + add v0.8h, v0.8h, v22.8h // sum_diag[0] + add v1.8h, v1.8h, v23.8h // sum_diag[0] + add v2.8h, v2.8h, v24.8h // sum_diag[1] + add v3.8h, v3.8h, v25.8h // sum_diag[1] +.if \i != 7 + dir_load_step2 v26, \bpc +.endif + ext v22.16b, v30.16b, v28.16b, #(16-2*\i) + ext v23.16b, v28.16b, v30.16b, #(16-2*\i) + ext v24.16b, v30.16b, v29.16b, #(16-2*\i) + ext v25.16b, v29.16b, v30.16b, #(16-2*\i) +.if \i != 7 + dir_load_step3 v26, \bpc +.endif + add v6.8h, v6.8h, v22.8h // sum_alt[0] + add v7.4h, v7.4h, v23.4h // sum_alt[0] + add v16.8h, v16.8h, v24.8h // sum_alt[1] + add v17.4h, v17.4h, v25.4h // sum_alt[1] +.endif +.endr + + movi v31.4s, #105 + + smull v26.4s, v4.4h, v4.4h // sum_hv[0]*sum_hv[0] + smlal2 v26.4s, v4.8h, v4.8h + smull v27.4s, v5.4h, v5.4h // sum_hv[1]*sum_hv[1] + smlal2 v27.4s, v5.8h, v5.8h + mul v26.4s, v26.4s, v31.4s // cost[2] *= 105 + mul v27.4s, v27.4s, v31.4s // cost[6] *= 105 + addv s4, v26.4s // cost[2] + addv s5, v27.4s // cost[6] + + rev64 v1.8h, v1.8h + rev64 v3.8h, v3.8h + ext v1.16b, v1.16b, v1.16b, #10 // sum_diag[0][14-n] + ext v3.16b, v3.16b, v3.16b, #10 // sum_diag[1][14-n] + + str s4, [sp, #2*4] // cost[2] + str s5, [sp, #6*4] // cost[6] + + movrel x4, div_table + ld1 {v31.8h}, [x4] + + smull v22.4s, v0.4h, v0.4h // sum_diag[0]*sum_diag[0] + smull2 v23.4s, v0.8h, v0.8h + smlal v22.4s, v1.4h, v1.4h + smlal2 v23.4s, v1.8h, v1.8h + smull v24.4s, v2.4h, v2.4h // sum_diag[1]*sum_diag[1] + smull2 v25.4s, v2.8h, v2.8h + smlal v24.4s, v3.4h, v3.4h + smlal2 v25.4s, v3.8h, v3.8h + uxtl v30.4s, v31.4h // div_table + uxtl2 v31.4s, v31.8h + mul v22.4s, v22.4s, v30.4s // cost[0] + mla v22.4s, v23.4s, v31.4s // cost[0] + mul v24.4s, v24.4s, v30.4s // cost[4] + mla v24.4s, v25.4s, v31.4s // cost[4] + addv s0, v22.4s // cost[0] + addv s2, v24.4s // cost[4] + + movrel x5, alt_fact + ld1 {v29.4h, v30.4h, v31.4h}, [x5]// div_table[2*m+1] + 105 + + str s0, [sp, #0*4] // cost[0] + str s2, [sp, #4*4] // cost[4] + + uxtl v29.4s, v29.4h // div_table[2*m+1] + 105 + uxtl v30.4s, v30.4h + uxtl v31.4s, v31.4h + + cost_alt s6, s16, v6, v7, v16, v17 // cost[1], cost[3] + cost_alt s18, s20, v18, v19, v20, v21 // cost[5], cost[7] + str s6, [sp, #1*4] // cost[1] + str s16, [sp, #3*4] // cost[3] + + mov w0, #0 // best_dir + mov w1, v0.s[0] // best_cost + mov w3, #1 // n + + str s18, [sp, #5*4] // cost[5] + str s20, [sp, #7*4] // cost[7] + + mov w4, v6.s[0] + + find_best v6, v4, v16 + find_best v16, v2, v18 + find_best v18, v5, v20 + find_best v20 + + eor w3, w0, #4 // best_dir ^4 + ldr w4, [sp, w3, uxtw #2] + sub w1, w1, w4 // best_cost - cost[best_dir ^ 4] + lsr w1, w1, #10 + str w1, [x2] // *var + + add sp, sp, #32 +.if \bpc == 16 + ldr d8, [sp], 0x10 +.endif + ret +endfunc +.endm diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5245 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_128_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_128_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + movi v0.16b, #128 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + movi v1.16b, #128 +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + movi v1.16b, #128 + movi v2.16b, #128 + movi v3.16b, #128 +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_128_tbl): + .hword L(ipred_dc_128_tbl) - 640b + .hword L(ipred_dc_128_tbl) - 320b + .hword L(ipred_dc_128_tbl) - 16b + .hword L(ipred_dc_128_tbl) - 8b + .hword L(ipred_dc_128_tbl) - 4b +endfunc + +// void ipred_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_v_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #1 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2] +4: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] +8: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] +16: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_v_tbl): + .hword L(ipred_v_tbl) - 640b + .hword L(ipred_v_tbl) - 320b + .hword L(ipred_v_tbl) - 160b + .hword L(ipred_v_tbl) - 80b + .hword L(ipred_v_tbl) - 40b +endfunc + +// void ipred_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_h_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + sub x2, x2, #4 + sub x5, x5, w3, uxtw + mov x7, #-4 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + st1 {v3.s}[0], [x0], x1 + st1 {v2.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v1.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + st1 {v3.8b}, [x0], x1 + st1 {v2.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v1.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + st1 {v3.16b}, [x0], x1 + st1 {v2.16b}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + st1 {v1.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_h_tbl): + .hword L(ipred_h_tbl) - 64b + .hword L(ipred_h_tbl) - 32b + .hword L(ipred_h_tbl) - 16b + .hword L(ipred_h_tbl) - 8b + .hword L(ipred_h_tbl) - 4b +endfunc + +// void ipred_dc_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_8bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_top_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #1 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.8b, v0.b[0] +4: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.8b, v0.b[0] +8: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] +16: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add v2.4h, v0.4h, v1.4h + rshrn v2.8b, v2.8h, #5 + dup v0.16b, v2.b[0] + dup v1.16b, v2.b[0] +32: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v4.4h, v0.4h, v1.4h + add v5.4h, v2.4h, v3.4h + add v4.4h, v4.4h, v5.4h + rshrn v4.8b, v4.8h, #6 + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] + dup v2.16b, v4.b[0] + dup v3.16b, v4.b[0] +64: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_top_tbl): + .hword L(ipred_dc_top_tbl) - 640b + .hword L(ipred_dc_top_tbl) - 320b + .hword L(ipred_dc_top_tbl) - 160b + .hword L(ipred_dc_top_tbl) - 80b + .hword L(ipred_dc_top_tbl) - 40b +endfunc + +// void ipred_dc_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + clz w3, w3 + clz w7, w4 + adr x5, L(ipred_dc_left_tbl) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w7, w7, #25 + ldrh w3, [x5, w3, uxtw #1] + ldrh w7, [x5, w7, uxtw #1] + sub x3, x5, w3, uxtw + sub x5, x5, w7, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w4): + AARCH64_VALID_JUMP_TARGET + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt L(ipred_dc_left_w4) + ret + +L(ipred_dc_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + rshrn v0.8b, v0.8h, #3 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w8): + AARCH64_VALID_JUMP_TARGET + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt L(ipred_dc_left_w8) + ret + +L(ipred_dc_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w16): + AARCH64_VALID_JUMP_TARGET + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt L(ipred_dc_left_w16) + ret + +L(ipred_dc_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add v0.4h, v0.4h, v1.4h + rshrn v0.8b, v0.8h, #5 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w32): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +1: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v0.4h, v0.4h, v1.4h + add v2.4h, v2.4h, v3.4h + add v0.4h, v0.4h, v2.4h + rshrn v0.8b, v0.8h, #6 + dup v0.16b, v0.b[0] + br x3 +L(ipred_dc_left_w64): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +1: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_tbl): + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h4) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w4) +endfunc + +// void ipred_dc_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + add w7, w3, w4 // width + height + clz w3, w3 + clz w6, w4 + dup v16.8h, w7 // width + height + adr x5, L(ipred_dc_tbl) + rbit w7, w7 // rbit(width + height) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w6, w6, #25 + clz w7, w7 // ctz(width + height) + ldrh w3, [x5, w3, uxtw #1] + ldrh w6, [x5, w6, uxtw #1] + neg w7, w7 // -ctz(width + height) + sub x3, x5, w3, uxtw + sub x5, x5, w6, uxtw + ushr v16.8h, v16.8h, #1 // (width + height) >> 1 + dup v17.8h, w7 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], #4 + ins v0.s[1], wzr + uaddlv h0, v0.8b + add x2, x2, #1 + br x3 +L(ipred_dc_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.s}[0], [x2] + ins v1.s[1], wzr + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.8b + cmp w4, #4 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x3334/2) + movk w16, #(0x5556/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8b, v0.b[0] +2: + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + subs w4, w4, #4 + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[0], [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], #8 + uaddlv h0, v0.8b + add x2, x2, #1 + br x3 +L(ipred_dc_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.8b + cmp w4, #8 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8b, v0.b[0] +2: + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2], #16 + uaddlv h0, v0.16b + add x2, x2, #1 + br x3 +L(ipred_dc_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + cmp w4, #16 + add v0.4h, v0.4h, v1.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/8/32/64 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.16b, v0.b[0] +2: + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x2], #32 + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add x2, x2, #1 + add v0.4h, v0.4h, v1.4h + br x3 +L(ipred_dc_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + uaddlv h2, v2.16b + cmp w4, #32 + add v0.4h, v0.4h, v1.4h + add v0.4h, v0.4h, v2.4h + ushl v4.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16/64 + cmp w4, #8 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v4.4h, v4.4h, v16.4h +1: + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] +2: + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b}, [x0], x1 + st1 {v0.16b, v1.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], #64 + uaddlv h0, v0.16b + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v0.4h, v0.4h, v1.4h + add v2.4h, v2.4h, v3.4h + add x2, x2, #1 + add v0.4h, v0.4h, v2.4h + br x3 +L(ipred_dc_w64): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b, v3.16b, v4.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h1, v1.16b + uaddlv h2, v2.16b + uaddlv h3, v3.16b + uaddlv h4, v4.16b + add v1.4h, v1.4h, v2.4h + add v3.4h, v3.4h, v4.4h + cmp w4, #64 + add v0.4h, v0.4h, v1.4h + add v0.4h, v0.4h, v3.4h + ushl v4.4h, v0.4h, v17.4h + b.eq 1f + // h = 16/32 + mov w16, #(0x5556/2) + movk w16, #(0x3334/2), lsl #16 + lsr w16, w16, w4 + dup v16.4h, w16 + sqdmulh v4.4h, v4.4h, v16.4h +1: + dup v0.16b, v4.b[0] + dup v1.16b, v4.b[0] + dup v2.16b, v4.b[0] + dup v3.16b, v4.b[0] +2: + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + subs w4, w4, #4 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_tbl): + .hword L(ipred_dc_tbl) - L(ipred_dc_h64) + .hword L(ipred_dc_tbl) - L(ipred_dc_h32) + .hword L(ipred_dc_tbl) - L(ipred_dc_h16) + .hword L(ipred_dc_tbl) - L(ipred_dc_h8) + .hword L(ipred_dc_tbl) - L(ipred_dc_h4) + .hword L(ipred_dc_tbl) - L(ipred_dc_w64) + .hword L(ipred_dc_tbl) - L(ipred_dc_w32) + .hword L(ipred_dc_tbl) - L(ipred_dc_w16) + .hword L(ipred_dc_tbl) - L(ipred_dc_w8) + .hword L(ipred_dc_tbl) - L(ipred_dc_w4) +endfunc + +// void ipred_paeth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_8bpc_neon, export=1 + clz w9, w3 + adr x5, L(ipred_paeth_tbl) + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x2] + add x8, x2, #1 + sub x2, x2, #4 + sub x5, x5, w9, uxtw + mov x7, #-4 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.4s}, [x8] + usubl v6.8h, v5.8b, v4.8b // top - topleft +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + zip1 v0.2s, v0.2s, v1.2s + zip1 v2.2s, v2.2s, v3.2s + uaddw v16.8h, v6.8h, v0.8b + uaddw v17.8h, v6.8h, v2.8b + sqxtun v16.8b, v16.8h // base + sqxtun2 v16.16b, v17.8h + zip1 v0.2d, v0.2d, v2.2d + uabd v20.16b, v5.16b, v16.16b // tdiff + uabd v22.16b, v4.16b, v16.16b // tldiff + uabd v16.16b, v0.16b, v16.16b // ldiff + umin v18.16b, v20.16b, v22.16b // min(tdiff, tldiff) + cmhs v20.16b, v22.16b, v20.16b // tldiff >= tdiff + cmhs v16.16b, v18.16b, v16.16b // min(tdiff, tldiff) >= ldiff + bsl v20.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bit v20.16b, v0.16b, v16.16b // ldiff <= min ? left : ... + st1 {v20.s}[3], [x0], x1 + st1 {v20.s}[2], [x6], x1 + subs w4, w4, #4 + st1 {v20.s}[1], [x0], x1 + st1 {v20.s}[0], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.2d}, [x8] + usubl v6.8h, v5.8b, v4.8b // top - topleft +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 + uaddw v16.8h, v6.8h, v0.8b + uaddw v17.8h, v6.8h, v1.8b + uaddw v18.8h, v6.8h, v2.8b + uaddw v19.8h, v6.8h, v3.8b + sqxtun v16.8b, v16.8h // base + sqxtun2 v16.16b, v17.8h + sqxtun v18.8b, v18.8h + sqxtun2 v18.16b, v19.8h + zip1 v2.2d, v2.2d, v3.2d + zip1 v0.2d, v0.2d, v1.2d + uabd v21.16b, v5.16b, v18.16b // tdiff + uabd v20.16b, v5.16b, v16.16b + uabd v23.16b, v4.16b, v18.16b // tldiff + uabd v22.16b, v4.16b, v16.16b + uabd v17.16b, v2.16b, v18.16b // ldiff + uabd v16.16b, v0.16b, v16.16b + umin v19.16b, v21.16b, v23.16b // min(tdiff, tldiff) + umin v18.16b, v20.16b, v22.16b + cmhs v21.16b, v23.16b, v21.16b // tldiff >= tdiff + cmhs v20.16b, v22.16b, v20.16b + cmhs v17.16b, v19.16b, v17.16b // min(tdiff, tldiff) >= ldiff + cmhs v16.16b, v18.16b, v16.16b + bsl v21.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v20.16b, v5.16b, v4.16b + bit v21.16b, v2.16b, v17.16b // ldiff <= min ? left : ... + bit v20.16b, v0.16b, v16.16b + st1 {v21.d}[1], [x0], x1 + st1 {v21.d}[0], [x6], x1 + subs w4, w4, #4 + st1 {v20.d}[1], [x0], x1 + st1 {v20.d}[0], [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v5.16b}, [x8], #16 + mov w9, w3 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw +1: + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x7 +2: + usubl v6.8h, v5.8b, v4.8b // top - topleft + usubl2 v7.8h, v5.16b, v4.16b + uaddw v24.8h, v6.8h, v0.8b + uaddw v25.8h, v7.8h, v0.8b + uaddw v26.8h, v6.8h, v1.8b + uaddw v27.8h, v7.8h, v1.8b + uaddw v28.8h, v6.8h, v2.8b + uaddw v29.8h, v7.8h, v2.8b + uaddw v30.8h, v6.8h, v3.8b + uaddw v31.8h, v7.8h, v3.8b + sqxtun v17.8b, v26.8h // base + sqxtun2 v17.16b, v27.8h + sqxtun v16.8b, v24.8h + sqxtun2 v16.16b, v25.8h + sqxtun v19.8b, v30.8h + sqxtun2 v19.16b, v31.8h + sqxtun v18.8b, v28.8h + sqxtun2 v18.16b, v29.8h + uabd v23.16b, v5.16b, v19.16b // tdiff + uabd v22.16b, v5.16b, v18.16b + uabd v21.16b, v5.16b, v17.16b + uabd v20.16b, v5.16b, v16.16b + uabd v27.16b, v4.16b, v19.16b // tldiff + uabd v26.16b, v4.16b, v18.16b + uabd v25.16b, v4.16b, v17.16b + uabd v24.16b, v4.16b, v16.16b + uabd v19.16b, v3.16b, v19.16b // ldiff + uabd v18.16b, v2.16b, v18.16b + uabd v17.16b, v1.16b, v17.16b + uabd v16.16b, v0.16b, v16.16b + umin v31.16b, v23.16b, v27.16b // min(tdiff, tldiff) + umin v30.16b, v22.16b, v26.16b + umin v29.16b, v21.16b, v25.16b + umin v28.16b, v20.16b, v24.16b + cmhs v23.16b, v27.16b, v23.16b // tldiff >= tdiff + cmhs v22.16b, v26.16b, v22.16b + cmhs v21.16b, v25.16b, v21.16b + cmhs v20.16b, v24.16b, v20.16b + cmhs v19.16b, v31.16b, v19.16b // min(tdiff, tldiff) >= ldiff + cmhs v18.16b, v30.16b, v18.16b + cmhs v17.16b, v29.16b, v17.16b + cmhs v16.16b, v28.16b, v16.16b + bsl v23.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v22.16b, v5.16b, v4.16b + bsl v21.16b, v5.16b, v4.16b + bsl v20.16b, v5.16b, v4.16b + bit v23.16b, v3.16b, v19.16b // ldiff <= min ? left : ... + bit v22.16b, v2.16b, v18.16b + bit v21.16b, v1.16b, v17.16b + bit v20.16b, v0.16b, v16.16b + subs w3, w3, #16 + st1 {v23.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v21.16b}, [x5], #16 + st1 {v20.16b}, [x10], #16 + b.le 8f + ld1 {v5.16b}, [x8], #16 + b 2b +8: + subs w4, w4, #4 + b.le 9f + // End of horizontal loop, move pointers to next four rows + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + // Load the top row as early as possible + ld1 {v5.16b}, [x8], #16 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_paeth_tbl): + .hword L(ipred_paeth_tbl) - 640b + .hword L(ipred_paeth_tbl) - 320b + .hword L(ipred_paeth_tbl) - 160b + .hword L(ipred_paeth_tbl) - 80b + .hword L(ipred_paeth_tbl) - 40b +endfunc + +// void ipred_smooth_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_8bpc_neon, export=1 + movrel x10, X(sm_weights) + add x11, x10, w4, uxtw + add x10, x10, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_tbl) + sub x12, x2, w4, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x12] // bottom + add x8, x2, #1 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2s}, [x8] // top + ld1r {v7.2s}, [x10] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + dup v5.16b, v6.b[3] // right + usubl v6.8h, v6.8b, v4.8b // top-bottom + uxtl v7.8h, v7.8b // weights_hor +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + zip1 v1.2s, v1.2s, v0.2s // left, flipped + zip1 v0.2s, v3.2s, v2.2s + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + shll v22.8h, v4.8b, #8 // bottom*256 + shll v23.8h, v4.8b, #8 + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + mla v20.8h, v0.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h + mla v22.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v23.8h, v6.8h, v18.8h + uhadd v20.8h, v20.8h, v22.8h + uhadd v21.8h, v21.8h, v23.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8b}, [x8] // top + ld1 {v7.8b}, [x10] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + dup v5.16b, v6.b[7] // right + usubl v6.8h, v6.8b, v4.8b // top-bottom + uxtl v7.8h, v7.8b // weights_hor +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + usubl v2.8h, v2.8b, v5.8b + usubl v3.8h, v3.8b, v5.8b + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + mla v20.8h, v3.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v2.8h, v7.8h // (left flipped) + mla v22.8h, v1.8h, v7.8h + mla v23.8h, v0.8h, v7.8h + mla v24.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v6.8h, v17.8h + mla v26.8h, v6.8h, v18.8h + mla v27.8h, v6.8h, v19.8h + uhadd v20.8h, v20.8h, v24.8h + uhadd v21.8h, v21.8h, v25.8h + uhadd v22.8h, v22.8h, v26.8h + uhadd v23.8h, v23.8h, v27.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v20.8b}, [x0], x1 + st1 {v21.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + add x12, x2, w3, uxtw + sub x2, x2, #2 + mov x7, #-2 + ld1r {v5.16b}, [x12] // right + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld2r {v0.8b, v1.8b}, [x2], x7 // left + ld2r {v16.8b, v17.8b}, [x11], #2 // weights_ver + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b +2: + ld1 {v7.16b}, [x10], #16 // weights_hor + ld1 {v3.16b}, [x8], #16 // top + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + usubl v2.8h, v3.8b, v4.8b // top-bottom + usubl2 v3.8h, v3.16b, v4.16b + mla v20.8h, v1.8h, v6.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h // (left flipped) + mla v22.8h, v0.8h, v6.8h + mla v23.8h, v0.8h, v7.8h + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + mla v24.8h, v2.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v3.8h, v16.8h + mla v26.8h, v2.8h, v17.8h + mla v27.8h, v3.8h, v17.8h + uhadd v20.8h, v20.8h, v24.8h + uhadd v21.8h, v21.8h, v25.8h + uhadd v22.8h, v22.8h, v26.8h + uhadd v23.8h, v23.8h, v27.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x8, w9, uxtw + sub x10, x10, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_tbl): + .hword L(ipred_smooth_tbl) - 640b + .hword L(ipred_smooth_tbl) - 320b + .hword L(ipred_smooth_tbl) - 160b + .hword L(ipred_smooth_tbl) - 80b + .hword L(ipred_smooth_tbl) - 40b +endfunc + +// void ipred_smooth_v_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_8bpc_neon, export=1 + movrel x7, X(sm_weights) + add x7, x7, w4, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_v_tbl) + sub x8, x2, w4, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.16b}, [x8] // bottom + add x2, x2, #1 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2s}, [x2] // top + usubl v6.8h, v6.8b, v4.8b // top-bottom +4: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + shll v22.8h, v4.8b, #8 // bottom*256 + shll v23.8h, v4.8b, #8 + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + mla v22.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v23.8h, v6.8h, v18.8h + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v22.s}[0], [x0], x1 + st1 {v22.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v23.s}[0], [x0], x1 + st1 {v23.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8b}, [x2] // top + usubl v6.8h, v6.8b, v4.8b // top-bottom +8: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + shll v24.8h, v4.8b, #8 // bottom*256 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + mla v24.8h, v6.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v25.8h, v6.8h, v17.8h + mla v26.8h, v6.8h, v18.8h + mla v27.8h, v6.8h, v19.8h + rshrn v24.8b, v24.8h, #8 + rshrn v25.8b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn v27.8b, v27.8h, #8 + st1 {v24.8b}, [x0], x1 + st1 {v25.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v26.8b}, [x0], x1 + st1 {v27.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + // Set up pointers for four rows in parallel; x0, x6, x5, x8 + add x5, x0, x1 + add x8, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b +2: + ld1 {v3.16b}, [x2], #16 // top + shll v20.8h, v4.8b, #8 // bottom*256 + shll v21.8h, v4.8b, #8 + shll v22.8h, v4.8b, #8 + shll v23.8h, v4.8b, #8 + shll v24.8h, v4.8b, #8 + shll v25.8h, v4.8b, #8 + shll v26.8h, v4.8b, #8 + shll v27.8h, v4.8b, #8 + usubl v2.8h, v3.8b, v4.8b // top-bottom + usubl2 v3.8h, v3.16b, v4.16b + mla v20.8h, v2.8h, v16.8h // bottom*256 + (top-bottom)*weights_ver + mla v21.8h, v3.8h, v16.8h + mla v22.8h, v2.8h, v17.8h + mla v23.8h, v3.8h, v17.8h + mla v24.8h, v2.8h, v18.8h + mla v25.8h, v3.8h, v18.8h + mla v26.8h, v2.8h, v19.8h + mla v27.8h, v3.8h, v19.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + rshrn v24.8b, v24.8h, #8 + rshrn2 v24.16b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn2 v26.16b, v27.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v24.16b}, [x5], #16 + st1 {v26.16b}, [x8], #16 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x2, x2, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x8, x8, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_v_tbl): + .hword L(ipred_smooth_v_tbl) - 640b + .hword L(ipred_smooth_v_tbl) - 320b + .hword L(ipred_smooth_v_tbl) - 160b + .hword L(ipred_smooth_v_tbl) - 80b + .hword L(ipred_smooth_v_tbl) - 40b +endfunc + +// void ipred_smooth_h_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_8bpc_neon, export=1 + movrel x8, X(sm_weights) + add x8, x8, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_h_tbl) + add x12, x2, w3, uxtw + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v5.16b}, [x12] // right + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v7.2s}, [x8] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + uxtl v7.8h, v7.8b // weights_hor +4: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + zip1 v1.2s, v1.2s, v0.2s // left, flipped + zip1 v0.2s, v3.2s, v2.2s + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + mla v20.8h, v0.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v1.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v7.8b}, [x8] // weights_hor + sub x2, x2, #4 + mov x7, #-4 + uxtl v7.8h, v7.8b // weights_hor +8: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + usubl v3.8h, v3.8b, v5.8b // left-right + usubl v2.8h, v2.8b, v5.8b + usubl v1.8h, v1.8b, v5.8b + usubl v0.8h, v0.8b, v5.8b + mla v20.8h, v3.8h, v7.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v2.8h, v7.8h // (left flipped) + mla v22.8h, v1.8h, v7.8h + mla v23.8h, v0.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn v21.8b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn v23.8b, v23.8h, #8 + st1 {v20.8b}, [x0], x1 + st1 {v21.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + sub x2, x2, #4 + mov x7, #-4 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x2], x7 // left + usubl v0.8h, v0.8b, v5.8b // left-right + usubl v1.8h, v1.8b, v5.8b + usubl v2.8h, v2.8b, v5.8b + usubl v3.8h, v3.8b, v5.8b +2: + ld1 {v7.16b}, [x8], #16 // weights_hor + shll v20.8h, v5.8b, #8 // right*256 + shll v21.8h, v5.8b, #8 + shll v22.8h, v5.8b, #8 + shll v23.8h, v5.8b, #8 + shll v24.8h, v5.8b, #8 + shll v25.8h, v5.8b, #8 + shll v26.8h, v5.8b, #8 + shll v27.8h, v5.8b, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + mla v20.8h, v3.8h, v6.8h // right*256 + (left-right)*weights_hor + mla v21.8h, v3.8h, v7.8h // (left flipped) + mla v22.8h, v2.8h, v6.8h + mla v23.8h, v2.8h, v7.8h + mla v24.8h, v1.8h, v6.8h + mla v25.8h, v1.8h, v7.8h + mla v26.8h, v0.8h, v6.8h + mla v27.8h, v0.8h, v7.8h + rshrn v20.8b, v20.8h, #8 + rshrn2 v20.16b, v21.8h, #8 + rshrn v22.8b, v22.8h, #8 + rshrn2 v22.16b, v23.8h, #8 + rshrn v24.8b, v24.8h, #8 + rshrn2 v24.16b, v25.8h, #8 + rshrn v26.8b, v26.8h, #8 + rshrn2 v26.16b, v27.8h, #8 + subs w3, w3, #16 + st1 {v20.16b}, [x0], #16 + st1 {v22.16b}, [x6], #16 + st1 {v24.16b}, [x5], #16 + st1 {v26.16b}, [x10], #16 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_h_tbl): + .hword L(ipred_smooth_h_tbl) - 640b + .hword L(ipred_smooth_h_tbl) - 320b + .hword L(ipred_smooth_h_tbl) - 160b + .hword L(ipred_smooth_h_tbl) - 80b + .hword L(ipred_smooth_h_tbl) - 40b +endfunc + +const padding_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +padding_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void ipred_z1_upsample_edge_8bpc_neon(pixel *out, const int hsz, +// const pixel *const in, const int end); +function ipred_z1_upsample_edge_8bpc_neon, export=1 + movrel x4, padding_mask + ld1 {v0.16b}, [x2] // in[] + add x5, x2, w3, uxtw // in[end] + sub x4, x4, w3, uxtw + + ld1r {v1.16b}, [x5] // padding + ld1 {v3.16b}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v1.16b, v3.16b // padded in[] + + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + + uaddl v16.8h, v4.8b, v5.8b // in[i+1] + in[i+2] + uaddl2 v17.8h, v4.16b, v5.16b + uaddl v18.8h, v0.8b, v6.8b // in[i+0] + in[i+3] + uaddl2 v19.8h, v0.16b, v6.16b + mul v16.8h, v16.8h, v31.8h // 9*(in[i+1] + in[i+2]) + mul v17.8h, v17.8h, v31.8h + sub v16.8h, v16.8h, v18.8h + sub v17.8h, v17.8h, v19.8h + + sqrshrun v16.8b, v16.8h, #4 + sqrshrun2 v16.16b, v17.8h, #4 + + zip1 v0.16b, v4.16b, v16.16b + zip2 v1.16b, v4.16b, v16.16b + + st1 {v0.16b, v1.16b}, [x0] + + ret +endfunc + +// void ipred_z2_upsample_edge_8bpc_neon(pixel *out, const int sz, +// const pixel *const in); +function ipred_z2_upsample_edge_8bpc_neon, export=1 + // Here, sz is 4 or 8, and we produce 2*sz+1 output elements. + movrel x4, padding_mask + ld1 {v0.16b}, [x2] // in[] + add x5, x2, w1, uxtw // in[sz] + sub x4, x4, w1, uxtw + + ld1r {v2.16b}, [x2] // in[0] for padding + ld1r {v1.16b}, [x5] // padding + ld1 {v3.16b}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v1.16b, v3.16b // padded in[] + + ext v4.16b, v2.16b, v0.16b, #15 + ext v5.16b, v0.16b, v1.16b, #1 + ext v6.16b, v0.16b, v1.16b, #2 + + uaddl v16.8h, v0.8b, v5.8b // in[i+0] + in[i+1] + uaddl v18.8h, v4.8b, v6.8b // in[i-1] + in[i+2] + mul v16.8h, v16.8h, v31.8h // 9*(in[i+1] + in[i+2]) + sub v16.8h, v16.8h, v18.8h + + sqrshrun v16.8b, v16.8h, #4 + + add x5, x0, #16 + + zip1 v2.16b, v0.16b, v16.16b + + st1 {v1.b}[0], [x5] + // In case sz=8, output one single pixel in out[16]. + st1 {v2.16b}, [x0] + + ret +endfunc + +const edge_filter + .byte 0, 4, 8, 0 + .byte 0, 5, 6, 0 +// Leaving out the coeffs for strength=3 +// .byte 2, 4, 4, 0 +endconst + +// void ipred_z1_filter_edge_8bpc_neon(pixel *out, const int sz, +// const pixel *const in, const int end, +// const int strength); +function ipred_z1_filter_edge_8bpc_neon, export=1 + cmp w4, #3 + b.eq L(fivetap) // if (strength == 3) goto fivetap + + movrel x5, edge_filter, -3 + add x5, x5, w4, uxtw #2 // edge_filter + (strength - 1)*4 + 1 + + ld1 {v31.h}[0], [x5] // kernel[1-2] + + ld1 {v0.16b}, [x2], #16 + + dup v30.16b, v31.b[0] + dup v31.16b, v31.b[1] +1: + // in[end], is the last valid pixel. We produce 16 pixels out by + // using 18 pixels in - the last pixel used is [17] of the ones + // read/buffered. + cmp w3, #17 + ld1 {v1.16b}, [x2], #16 + b.lt 2f + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + umull v4.8h, v0.8b, v30.8b + umlal v4.8h, v2.8b, v31.8b + umlal v4.8h, v3.8b, v30.8b + umull2 v5.8h, v0.16b, v30.16b + umlal2 v5.8h, v2.16b, v31.16b + umlal2 v5.8h, v3.16b, v30.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + rshrn v4.8b, v4.8h, #4 + rshrn2 v4.16b, v5.8h, #4 + sub w3, w3, #16 + st1 {v4.16b}, [x0], #16 + b.gt 1b + ret +2: + // Right padding + + // x2[w3-32] is the padding pixel (x2 points 32 bytes ahead) + movrel x5, padding_mask + sub w6, w3, #32 + sub x5, x5, w3, uxtw + add x6, x2, w6, sxtw + + ld1 {v2.16b}, [x5] // padding_mask + + ld1r {v1.16b}, [x6] + bit v0.16b, v1.16b, v2.16b // Pad v0-v1 + + // Filter one block + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + umull v4.8h, v0.8b, v30.8b + umlal v4.8h, v2.8b, v31.8b + umlal v4.8h, v3.8b, v30.8b + umull2 v5.8h, v0.16b, v30.16b + umlal2 v5.8h, v2.16b, v31.16b + umlal2 v5.8h, v3.16b, v30.16b + subs w1, w1, #16 + rshrn v4.8b, v4.8h, #4 + rshrn2 v4.16b, v5.8h, #4 + st1 {v4.16b}, [x0], #16 + b.le 9f +5: + // After one block, any remaining output would only be filtering + // padding - thus just store the padding. + subs w1, w1, #16 + st1 {v1.16b}, [x0], #16 + b.gt 5b +9: + ret + +L(fivetap): + sub x2, x2, #1 // topleft -= 1 + movi v29.16b, #2 + ld1 {v0.16b}, [x2], #16 + movi v30.16b, #4 + movi v31.16b, #4 + ins v0.b[0], v0.b[1] +1: + // in[end+1], is the last valid pixel. We produce 16 pixels out by + // using 20 pixels in - the last pixel used is [19] of the ones + // read/buffered. + cmp w3, #18 + ld1 {v1.16b}, [x2], #16 + b.lt 2f // if (end + 1 < 19) + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v0.16b, v1.16b, #3 + ext v5.16b, v0.16b, v1.16b, #4 + umull v6.8h, v0.8b, v29.8b + umlal v6.8h, v2.8b, v30.8b + umlal v6.8h, v3.8b, v31.8b + umlal v6.8h, v4.8b, v30.8b + umlal v6.8h, v5.8b, v29.8b + umull2 v7.8h, v0.16b, v29.16b + umlal2 v7.8h, v2.16b, v30.16b + umlal2 v7.8h, v3.16b, v31.16b + umlal2 v7.8h, v4.16b, v30.16b + umlal2 v7.8h, v5.16b, v29.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + rshrn v6.8b, v6.8h, #4 + rshrn2 v6.16b, v7.8h, #4 + sub w3, w3, #16 + st1 {v6.16b}, [x0], #16 + b.gt 1b + ret +2: + // Right padding + + // x2[w3+1-32] is the padding pixel (x2 points 32 bytes ahead) + movrel x5, padding_mask, -1 + sub w6, w3, #31 + sub x5, x5, w3, uxtw + add x6, x2, w6, sxtw + + ld1 {v2.16b, v3.16b}, [x5] // padding_mask + + ld1r {v28.16b}, [x6] + bit v0.16b, v28.16b, v2.16b // Pad v0-v1 + bit v1.16b, v28.16b, v3.16b +4: + // Filter one block + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v0.16b, v1.16b, #3 + ext v5.16b, v0.16b, v1.16b, #4 + umull v6.8h, v0.8b, v29.8b + umlal v6.8h, v2.8b, v30.8b + umlal v6.8h, v3.8b, v31.8b + umlal v6.8h, v4.8b, v30.8b + umlal v6.8h, v5.8b, v29.8b + umull2 v7.8h, v0.16b, v29.16b + umlal2 v7.8h, v2.16b, v30.16b + umlal2 v7.8h, v3.16b, v31.16b + umlal2 v7.8h, v4.16b, v30.16b + umlal2 v7.8h, v5.16b, v29.16b + subs w1, w1, #16 + mov v0.16b, v1.16b + mov v1.16b, v28.16b + rshrn v6.8b, v6.8h, #4 + rshrn2 v6.16b, v7.8h, #4 + sub w3, w3, #16 + st1 {v6.16b}, [x0], #16 + b.le 9f + // v0-v1[w3+1] is the last valid pixel; if (w3 + 1 > 0) we need to + // filter properly once more - aka (w3 >= 0). + cmp w3, #0 + b.ge 4b +5: + // When w3 <= 0, all remaining pixels in v0-v1 are equal to the + // last valid pixel - thus just output that without filtering. + subs w1, w1, #16 + st1 {v1.16b}, [x0], #16 + b.gt 5b +9: + ret +endfunc + +// void ipred_pixel_set_8bpc_neon(pixel *out, const pixel px, +// const int n); +function ipred_pixel_set_8bpc_neon, export=1 + dup v0.16b, w1 +1: + subs w2, w2, #16 + st1 {v0.16b}, [x0], #16 + b.gt 1b + ret +endfunc + +// void ipred_z1_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const int width, const int height, +// const int dx, const int max_base_x); +function ipred_z1_fill1_8bpc_neon, export=1 + clz w9, w3 + adr x8, L(ipred_z1_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw // top[max_base_x] + sub x8, x8, w9, uxtw + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + br x8 +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + ldr d0, [x2, w8, uxtw] // top[base] + ldr d2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + ext v1.8b, v0.8b, v0.8b, #1 // top[base+1] + ext v3.8b, v2.8b, v2.8b, #1 + usubl v6.8h, v1.8b, v0.8b // top[base+1]-top[base] + usubl v7.8h, v3.8b, v2.8b + ushll v16.8h, v0.8b, #6 // top[base]*64 + ushll v17.8h, v2.8b, #6 + mla v16.4h, v6.4h, v4.4h // + top[base+1]*frac + mla v17.4h, v7.4h, v5.4h + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.s}[0], [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.s}[0], [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v31.s}[0], [x0], x1 + b.gt 49b + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.8b, w9 // frac + dup v5.8b, w11 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8b, w9 // 64 - frac + dup v7.8b, w11 + ext v1.16b, v0.16b, v0.16b, #1 // top[base+1] + ext v3.16b, v2.16b, v2.16b, #1 + umull v16.8h, v0.8b, v6.8b // top[base]*(64-frac) + umlal v16.8h, v1.8b, v4.8b // + top[base+1]*frac + umull v17.8h, v2.8b, v7.8b + umlal v17.8h, v3.8b, v5.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8b}, [x0], x1 + b.gt 89b + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + mov w12, w3 + + add x13, x0, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 169f + add x8, x2, w8, uxtw + add x10, x2, w10, uxtw + dup v4.16b, w9 // frac + dup v5.16b, w11 + ld1 {v0.16b, v1.16b}, [x8], #32 // top[base] + ld1 {v2.16b, v3.16b}, [x10], #32 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.16b, w9 // 64 - frac + dup v7.16b, w11 + add w7, w7, w5 // xpos += dx +2: + ext v16.16b, v0.16b, v1.16b, #1 // top[base+1] + ext v17.16b, v2.16b, v3.16b, #1 + subs w3, w3, #16 + umull v18.8h, v0.8b, v6.8b // top[base]*(64-frac) + umlal v18.8h, v16.8b, v4.8b // + top[base+1]*frac + umull2 v19.8h, v0.16b, v6.16b + umlal2 v19.8h, v16.16b, v4.16b + umull v20.8h, v2.8b, v7.8b + umlal v20.8h, v17.8b, v5.8b + umull2 v21.8h, v2.16b, v7.16b + umlal2 v21.8h, v17.16b, v5.16b + rshrn v16.8b, v18.8h, #6 + rshrn2 v16.16b, v19.8h, #6 + rshrn v17.8b, v20.8h, #6 + rshrn2 v17.16b, v21.8h, #6 + st1 {v16.16b}, [x0], #16 + st1 {v17.16b}, [x13], #16 + b.le 3f + mov v0.16b, v1.16b + ld1 {v1.16b}, [x8], #16 // top[base] + mov v2.16b, v3.16b + ld1 {v3.16b}, [x10], #16 + b 2b + +3: + subs w4, w4, #2 + b.le 9f + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 1b +9: + ret + +169: + st1 {v31.16b}, [x0], #16 + subs w3, w3, #16 + st1 {v31.16b}, [x13], #16 + b.gt 169b + subs w4, w4, #2 + b.le 9b + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 169b + +L(ipred_z1_fill1_tbl): + .hword L(ipred_z1_fill1_tbl) - 640b + .hword L(ipred_z1_fill1_tbl) - 320b + .hword L(ipred_z1_fill1_tbl) - 160b + .hword L(ipred_z1_fill1_tbl) - 80b + .hword L(ipred_z1_fill1_tbl) - 40b +endfunc + +function ipred_z1_fill2_8bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // top[max_base_x] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + b.eq 8f + +4: // w == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + ldr d0, [x2, w8, uxtw] // top[base] + ldr d2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8b, v0.8b, v0.8b // top[base+1] + uzp1 v0.8b, v0.8b, v0.8b // top[base] + uzp2 v3.8b, v2.8b, v2.8b + uzp1 v2.8b, v2.8b, v2.8b + usubl v6.8h, v1.8b, v0.8b // top[base+1]-top[base] + usubl v7.8h, v3.8b, v2.8b + ushll v16.8h, v0.8b, #6 // top[base]*64 + ushll v17.8h, v2.8b, #6 + mla v16.4h, v6.4h, v4.4h // + top[base+1]*frac + mla v17.4h, v7.4h, v5.4h + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.s}[0], [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.s}[0], [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v31.s}[0], [x0], x1 + b.gt 49b + ret + +8: // w == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.8b, w9 // frac + dup v5.8b, w11 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8b, w9 // 64 - frac + dup v7.8b, w11 + uzp2 v1.16b, v0.16b, v0.16b // top[base+1] + uzp1 v0.16b, v0.16b, v0.16b // top[base] + uzp2 v3.16b, v2.16b, v2.16b + uzp1 v2.16b, v2.16b, v2.16b + umull v16.8h, v1.8b, v4.8b // top[base+1]*frac + umlal v16.8h, v0.8b, v6.8b // + top[base]*(64-frac) + umull v17.8h, v3.8b, v5.8b + umlal v17.8h, v2.8b, v7.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8b}, [x0], x1 + b.gt 89b + ret +endfunc + +// void ipred_reverse_8bpc_neon(pixel *dst, const pixel *const src, +// const int n); +function ipred_reverse_8bpc_neon, export=1 + sub x1, x1, #16 + add x3, x0, #8 + mov x4, #16 +1: + ld1 {v0.16b}, [x1] + subs w2, w2, #16 + rev64 v0.16b, v0.16b + sub x1, x1, #16 + st1 {v0.d}[1], [x0], x4 + st1 {v0.d}[0], [x3], x4 + b.gt 1b + ret +endfunc + +const increments + .short 0, 1, 2, 3, 4, 5, 6, 7 + .short 8, 9, 10, 11, 12, 13, 14, 15 +endconst + +// void ipred_z2_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const pixel *const left, +// const int width, const int height, +// const int dx, const int dy); +function ipred_z2_fill1_8bpc_neon, export=1 + clz w10, w4 + adr x9, L(ipred_z2_fill1_tbl) + sub w10, w10, #25 + ldrh w10, [x9, w10, uxtw #1] + mov w8, #(1 << 6) // xpos = 1 << 6 + sub x9, x9, w10, uxtw + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + + br x9 +40: + AARCH64_VALID_JUMP_TARGET + + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // Worst case height for w=4 is 16, but we need at least h+1 elements + ld1 {v0.16b, v1.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + tbl v16.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2s, v30.2s, v28.2s // base_y + 1, base_y + 2 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v29.8b, #2 +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + // Cut corners here; only doing tbl over v0 here; we only + // seem to need the last pixel, from v1, after skipping to the + // left-only codepath below. + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + ext v3.8b, v2.8b, v2.8b, #1 // top[base_x+1] + ext v5.8b, v4.8b, v4.8b, #1 + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + trn1 v2.2s, v2.2s, v4.2s // top[base_x] + trn1 v3.2s, v3.2s, v5.2s // top[base_x+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 4b + +49: + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+2] + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 49b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // Worst case height for w=8 is 32, but we need at least h+1 elements + ld1 {v0.16b, v1.16b, v2.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + add v30.8b, v29.8b, v19.8b // base_y + 2 + add v29.8b, v29.8b, v17.8b // base_y + 1 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + + movi v24.8b, #2 // 2 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + // Cut corners here; only doing tbl over v0-v1 here; we only + // seem to need the last pixel, from v2, after skipping to the + // left-only codepath below. + tbl v19.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+1] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + tbl v20.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+2] + + ext v5.16b, v4.16b, v4.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 8b + +89: + tbl v19.8b, {v0.16b, v1.16b, v2.16b}, v29.8b // left[base_y+1] + tbl v20.8b, {v0.16b, v1.16b, v2.16b}, v30.8b // left[base_y+2] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 89b + +9: + ret + +160: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + add x11, x11, #16 // increments + + dup v18.8h, w7 // -dy + movi v17.16b, #1 + add x3, x3, #1 // Skip past left[0] + + ld1 {v14.8h}, [x11] // {8,9,10,11,12,13,14,15} + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + mul v19.8h, v14.8h, v18.8h // {8,9,10,11,12,13,14,15}* -dy + movi v25.16b, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + add v18.8h, v19.8h, v18.8h + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + xtn2 v31.16b, v14.8h // {8,9,10,11,12,13,14,15} + + // Worst case height is 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x3] // left[] + ld1r {v15.16b}, [x2] // left[0] == top[0] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v16.8h // (uint8_t)ypos + xtn2 v27.16b, v18.8h + shrn v29.8b, v16.8h, #6 // ypos >> 6 + shrn2 v29.16b, v18.8h, #6 + mov v18.16b, v15.16b // left[0] + and v27.16b, v27.16b, v25.16b // frac_y + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbx v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 + add v29.16b, v29.16b, v17.16b // base_y + 1 + + sub v28.16b, v26.16b, v27.16b // 64 - frac_y + + movi v24.16b, #2 // 2 +16: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 169f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw + add x11, x2, w11, sxtw + + ld1 {v4.16b, v5.16b}, [x9] // top[base_x] + mov v19.16b, v15.16b // left[0] + ld1 {v6.16b, v7.16b}, [x11] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + mov v20.16b, v15.16b // left[0] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn v22.8b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn v17.8b, v17.8h + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + trn1 v21.2d, v21.2d, v21.2d // first base_x + trn1 v22.2d, v22.2d, v22.2d + trn1 v16.2d, v16.2d, v16.2d // (uint8_t)xpos + trn1 v17.2d, v17.2d, v17.2d + + ext v5.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + + sub v8.16b, v26.16b, v16.16b // 64 - frac_x + sub v9.16b, v26.16b, v17.16b + + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + + add v21.16b, v21.16b, v31.16b // actual base_x + add v22.16b, v22.16b, v31.16b + + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v5.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v7.8b, v17.8b + umull2 v18.8h, v6.16b, v9.16b + umlal2 v18.8h, v7.16b, v17.16b + + cmge v21.16b, v21.16b, #0 + cmge v22.16b, v22.16b, #0 + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v18.8h, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.16b}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.16b}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 + add v30.16b, v30.16b, v24.16b // base_y += 2 + b 16b + +169: + mov v19.16b, v15.16b + mov v20.16b, v15.16b + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + umull v4.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v4.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v5.8h, v18.16b, v28.16b + umlal2 v5.8h, v19.16b, v27.16b + umull v6.8h, v19.8b, v28.8b + umlal v6.8h, v20.8b, v27.8b + umull2 v7.8h, v19.16b, v28.16b + umlal2 v7.8h, v20.16b, v27.16b + + rshrn v4.8b, v4.8h, #6 + rshrn2 v4.16b, v5.8h, #6 + rshrn v5.8b, v6.8h, #6 + rshrn2 v5.16b, v7.8h, #6 + + st1 {v4.16b}, [x0], x1 + subs w5, w5, #2 + st1 {v5.16b}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 + add v30.16b, v30.16b, v24.16b // base_y += 2 + b 169b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +320: +640: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + add x11, x11, #16 // increments + + dup v25.8h, w7 // -dy + add x3, x3, #1 // Skip past left[0] + + ld1 {v14.8h}, [x11] // {8,9,10,11,12,13,14,15} + + add x13, x0, x1 // alternating row + lsl x1, x1, #1 // stride *= 2 + sub x1, x1, w4, uxtw // stride -= width + + movi v11.8h, #8 + mul v26.8h, v31.8h, v25.8h // {0,1,2,3,4,5,6,7}* -dy + add v26.8h, v26.8h, v25.8h // -= dy + mul v25.8h, v25.8h, v11.8h // -8*dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + xtn2 v31.16b, v14.8h // {8,9,10,11,12,13,14,15} + + // Worst case height is 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x3] // left[] + ld1r {v15.16b}, [x2] // left[0] == top[0] + + mov w12, w4 // orig w + neg w14, w4 // -w + +1: + mov v23.16b, v26.16b // reset ypos + + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, w14 // base_x <= -w + asr w11, w8, #6 // base_x + b.le 329f + + dup v17.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + + add x9, x2, w9, sxtw + add x11, x2, w11, sxtw + + sqshrn v21.8b, v16.8h, #6 // first base_x + sqshrn v22.8b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn v17.8b, v17.8h + + ld1 {v4.16b}, [x9], #16 // top[base_x] + ld1 {v6.16b}, [x11], #16 + + trn1 v21.2d, v21.2d, v21.2d // first base_x + trn1 v22.2d, v22.2d, v22.2d + trn1 v16.2d, v16.2d, v16.2d // (uint8_t)xpos + trn1 v17.2d, v17.2d, v17.2d + + movi v10.16b, #0x3e + movi v11.16b, #64 + + and v16.16b, v16.16b, v10.16b // frac_x + and v17.16b, v17.16b, v10.16b + + sub v8.16b, v11.16b, v16.16b // 64 - frac_x + sub v9.16b, v11.16b, v17.16b + + add v21.16b, v21.16b, v31.16b // actual base_x + add v22.16b, v22.16b, v31.16b + +2: + add v13.8h, v23.8h, v25.8h // ypos -= 8*dy + movi v12.16b, #64 + movi v20.16b, #2 + movi v10.16b, #0x3e + + smov w10, v22.b[0] + + xtn v27.8b, v23.8h // (uint8_t)ypos + xtn2 v27.16b, v13.8h + shrn v29.8b, v23.8h, #6 // ypos >> 6 + shrn2 v29.16b, v13.8h, #6 + cmp w10, #0 // base_x (bottom left) >= 0 + and v27.16b, v27.16b, v10.16b // frac_y + + mov v18.16b, v15.16b // left[0] + + b.ge 4f + + add v23.8h, v13.8h, v25.8h // ypos -= 8*dy + movi v13.16b, #1 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v13.16b // base_y + 1 + mov v19.16b, v15.16b // left[0] + + sub v28.16b, v12.16b, v27.16b // 64 - frac_y + + ld1 {v5.16b}, [x9], #16 // top[base_x] + ld1 {v7.16b}, [x11], #16 + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v13.16b // base_y + 2 + + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + ext v18.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #1 + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v18.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v18.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v19.8b, v17.8b + umull2 v20.8h, v6.16b, v9.16b + umlal2 v20.8h, v19.16b, v17.16b + + cmge v18.16b, v21.16b, #0 + cmge v19.16b, v22.16b, #0 + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v20.8h, #6 + + bit v10.16b, v12.16b, v18.16b + bit v11.16b, v13.16b, v19.16b + + st1 {v10.16b}, [x0], #16 + subs w4, w4, #16 + st1 {v11.16b}, [x13], #16 + b.le 3f + + movi v10.16b, #16 + mov v4.16b, v5.16b + mov v6.16b, v7.16b + add v21.16b, v21.16b, v10.16b // base_x += 16 + add v22.16b, v22.16b, v10.16b + b 2b + +3: + subs w5, w5, #2 + b.le 9f + movi v10.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + mov w4, w12 // reset w + add v26.8h, v26.8h, v10.8h // ypos += 2*(1<<6) + b 1b + +4: // The rest of the row only predicted from top[] + ld1 {v5.16b}, [x9], #16 // top[base_x] + ld1 {v7.16b}, [x11], #16 + + ext v18.16b, v4.16b, v5.16b, #1 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #1 + + umull v12.8h, v4.8b, v8.8b // top[base_x]-*(64-frac_x) + umlal v12.8h, v18.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v13.8h, v4.16b, v8.16b + umlal2 v13.8h, v18.16b, v16.16b + umull v14.8h, v6.8b, v9.8b + umlal v14.8h, v19.8b, v17.8b + umull2 v20.8h, v6.16b, v9.16b + umlal2 v20.8h, v19.16b, v17.16b + + rshrn v12.8b, v12.8h, #6 + rshrn2 v12.16b, v13.8h, #6 + rshrn v13.8b, v14.8h, #6 + rshrn2 v13.16b, v20.8h, #6 + + st1 {v12.16b}, [x0], #16 + subs w4, w4, #16 + st1 {v13.16b}, [x13], #16 + b.le 3b + + mov v4.16b, v5.16b + mov v6.16b, v7.16b + b 4b + +329: // The rest of the block only predicted from left[] + add x1, x1, w4, uxtw // restore stride + mov w12, w5 // orig remaining h +1: + add v13.8h, v23.8h, v25.8h // ypos -= 8*dy + movi v12.16b, #64 + movi v10.16b, #0x3e + + xtn v27.8b, v23.8h // (uint8_t)ypos + xtn2 v27.16b, v13.8h + shrn v29.8b, v23.8h, #6 // ypos >> 6 + shrn2 v29.16b, v13.8h, #6 + and v27.16b, v27.16b, v10.16b // frac_y + + mov v18.16b, v15.16b // left[0] + add v23.8h, v13.8h, v25.8h // ypos -= 8*dy + movi v21.16b, #1 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v21.16b // base_y + 1 + + sub v28.16b, v12.16b, v27.16b // 64 - frac_y +2: + mov v19.16b, v15.16b // left[0] + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v21.16b // base_y + 2 + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + add v29.16b, v29.16b, v21.16b // next base_y + + umull v10.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v10.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v11.8h, v18.16b, v28.16b + umlal2 v11.8h, v19.16b, v27.16b + umull v12.8h, v19.8b, v28.8b + umlal v12.8h, v20.8b, v27.8b + umull2 v13.8h, v19.16b, v28.16b + umlal2 v13.8h, v20.16b, v27.16b + + rshrn v10.8b, v10.8h, #6 + rshrn2 v10.16b, v11.8h, #6 + rshrn v11.8b, v12.8h, #6 + rshrn2 v11.16b, v13.8h, #6 + + st1 {v10.16b}, [x0], x1 + subs w5, w5, #2 + st1 {v11.16b}, [x13], x1 + b.le 3f + mov v18.16b, v20.16b + b 2b + +3: + subs w4, w4, #16 + b.le 9f + + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w5, w12 // reset h + b 1b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +L(ipred_z2_fill1_tbl): + .hword L(ipred_z2_fill1_tbl) - 640b + .hword L(ipred_z2_fill1_tbl) - 320b + .hword L(ipred_z2_fill1_tbl) - 160b + .hword L(ipred_z2_fill1_tbl) - 80b + .hword L(ipred_z2_fill1_tbl) - 40b +endfunc + +function ipred_z2_fill2_8bpc_neon, export=1 + cmp w4, #8 + mov w8, #(2 << 6) // xpos = 2 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + tbl v16.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2s, v30.2s, v28.2s // base_y + 1, base_y + 2 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v29.8b, #2 + add v31.8b, v31.8b, v31.8b // {0,2,4,6,0,2,4,6} +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + uzp2 v3.8b, v2.8b, v4.8b // top[base_x+1] + uzp1 v2.8b, v2.8b, v4.8b // top[base_x] + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 4b + +49: + tbl v17.8b, {v0.16b}, v30.8b // left[base_y+1], left[base_y+2] + + trn1 v16.2s, v16.2s, v17.2s // left[base_y], left[base_y+1] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + ext v16.8b, v17.8b, v17.8b, #4 + add v30.8b, v30.8b, v29.8b // base_y += 2 + b 49b + +9: + ret + +80: + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + add v30.8b, v29.8b, v19.8b // base_y + 2 + add v29.8b, v29.8b, v17.8b // base_y + 1 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + + movi v24.8b, #2 // 2 + add v31.16b, v31.16b, v31.16b // {0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14} +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + tbl v19.8b, {v0.16b}, v29.8b // left[base_y+1] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + tbl v20.8b, {v0.16b}, v30.8b // left[base_y+2] + + uzp2 v5.16b, v4.16b, v6.16b // top[base_x+1] + uzp1 v4.16b, v4.16b, v6.16b // top[base_x] + + and v16.16b, v16.16b, v25.16b // frac_x + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 8b + +89: + tbl v19.8b, {v0.16b}, v29.8b // left[base_y+1] + tbl v20.8b, {v0.16b}, v30.8b // left[base_y+2] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull v17.8h, v19.8b, v28.8b + umlal v17.8h, v20.8b, v27.8b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + mov v18.8b, v20.8b + add v29.8b, v29.8b, v24.8b // base_y += 2 + add v30.8b, v30.8b, v24.8b // base_y += 2 + b 89b + +9: + ret +endfunc + +function ipred_z2_fill3_8bpc_neon, export=1 + cmp w4, #8 + mov w8, #(1 << 6) // xpos = 1 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.16b, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3} + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.16b, v1.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + add v30.8b, v29.8b, v17.8b // base_y + 1 + add v28.8b, v29.8b, v19.8b // base_y + 2 + + trn1 v31.2s, v31.2s, v31.2s // {0,1,2,3,0,1,2,3} + + add v24.8b, v30.8b, v19.8b // base_y + 3 + + trn1 v29.2s, v29.2s, v28.2s // base_y + 0, base_y + 2 + trn1 v30.2s, v30.2s, v24.2s // base_y + 1, base_y + 3 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + trn1 v27.2s, v27.2s, v27.2s // frac_y + trn1 v28.2s, v28.2s, v28.2s // 64 - frac_y + + movi v24.8b, #4 +4: + asr w9, w8, #6 // base_x + dup v6.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + dup v7.4h, w8 // xpos + + ldr d2, [x2, w9, sxtw] // top[base_x] + ldr d4, [x2, w11, sxtw] + + trn1 v6.2d, v6.2d, v7.2d // xpos + + tbl v16.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+0], left[base_y+2] + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+3] + + shrn v20.8b, v6.8h, #6 // first base_x for each row + xtn v6.8b, v6.8h // (uint8_t)xpos + + ext v3.8b, v2.8b, v2.8b, #1 // top[base_x+1] + ext v5.8b, v4.8b, v4.8b, #1 + + and v6.8b, v6.8b, v25.8b // frac_x + + trn1 v2.2s, v2.2s, v4.2s // top[base_x] + trn1 v3.2s, v3.2s, v5.2s // top[base_x+1] + + sub v7.8b, v26.8b, v6.8b // 64 - frac_x + + add v20.8b, v20.8b, v31.8b // actual base_x + + umull v16.8h, v16.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v16.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + + umull v22.8h, v2.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v3.8b, v6.8b // + top[base_x+1]*frac_x + + cmge v20.8b, v20.8b, #0 + + rshrn v16.8b, v16.8h, #6 + rshrn v22.8b, v22.8h, #6 + + bit v16.8b, v22.8b, v20.8b + + st1 {v16.s}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + add v29.8b, v29.8b, v24.8b // base_y += 4 + add v30.8b, v30.8b, v24.8b // base_y += 4 + b 4b + +49: + tbl v16.8b, {v0.16b, v1.16b}, v29.8b // left[base_y+0], left[base_y+2] + tbl v17.8b, {v0.16b, v1.16b}, v30.8b // left[base_y+1], left[base_y+3] + + umull v18.8h, v16.8b, v28.8b // left[base_y]*(64-frac_t) + umlal v18.8h, v17.8b, v27.8b // + left[base_y+1]*frac_y + rshrn v18.8b, v18.8h, #6 + + st1 {v18.s}[0], [x0], x1 + subs w5, w5, #2 + st1 {v18.s}[1], [x0], x1 + b.le 9f + + add v29.8b, v29.8b, v24.8b // base_y += 4 + add v30.8b, v30.8b, v24.8b // base_y += 4 + b 49b + +9: + ret + +80: + dup v30.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v30.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.16b, #0x3e + add v30.8h, v16.8h, v30.8h // -= dy + + xtn v31.8b, v31.8h // {0,1,2,3,4,5,6,7} + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.16b, v1.16b, v2.16b}, [x3] // left[] + + movi v26.16b, #64 + movi v19.16b, #2 + + xtn v27.8b, v30.8h // (uint8_t)ypos + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v27.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + add v28.8b, v29.8b, v17.8b // base_y + 1 + add v30.8b, v29.8b, v19.8b // base_y + 2 + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7} + add v24.8b, v28.8b, v19.8b // base_y + 3 + + trn1 v29.2d, v29.2d, v30.2d // base_y + 0, base_y + 2 + trn1 v30.2d, v28.2d, v24.2d // base_y + 1, base_y + 3 + + sub v28.8b, v26.8b, v27.8b // 64 - frac_y + + movi v24.16b, #4 + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + shrn v21.8b, v16.8h, #6 // first base_x + shrn2 v21.16b, v17.8h, #6 + xtn v16.8b, v16.8h // (uint8_t)xpos + xtn2 v16.16b, v17.8h + + ext v5.16b, v4.16b, v4.16b, #1 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #1 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v7.16b, v26.16b, v16.16b // 64 - frac_x + + add v21.16b, v21.16b, v31.16b // actual base_x + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v17.8h, v18.16b, v28.16b + umlal2 v17.8h, v19.16b, v27.16b + + umull v22.8h, v4.8b, v7.8b // top[base_x]-*(64-frac_x) + umlal v22.8h, v5.8b, v16.8b // + top[base_x+1]*frac_x + umull2 v23.8h, v4.16b, v7.16b + umlal2 v23.8h, v5.16b, v16.16b + + cmge v21.16b, v21.16b, #0 + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + rshrn v22.8b, v22.8h, #6 + rshrn2 v22.16b, v23.8h, #6 + + bit v6.16b, v22.16b, v21.16b + + st1 {v6.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 + add v30.16b, v30.16b, v24.16b // base_y += 4 + b 8b + +89: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + umull v6.8h, v18.8b, v28.8b // left[base_y]*(64-frac_y) + umlal v6.8h, v19.8b, v27.8b // + left[base_y+1]*frac_y + umull2 v17.8h, v18.16b, v28.16b + umlal2 v17.8h, v19.16b, v27.16b + + rshrn v6.8b, v6.8h, #6 + rshrn2 v6.16b, v17.8h, #6 + + st1 {v6.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v6.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 + add v30.16b, v30.16b, v24.16b // base_y += 4 + b 89b + +9: + ret +endfunc + + +// void ipred_z3_fill1_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const left, +// const int width, const int height, +// const int dy, const int max_base_y); +function ipred_z3_fill1_8bpc_neon, export=1 + cmp w6, #64 + clz w9, w3 + adr x8, L(ipred_z3_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw // left[max_base_y] + sub x8, x8, w9, uxtw + movrel x11, increments + ld1r {v31.16b}, [x10] // padding + ld1 {v30.8h}, [x11] // increments + mov w7, w5 + b.gt L(ipred_z3_fill1_large_h16) + br x8 + +40: + AARCH64_VALID_JUMP_TARGET + dup v29.4h, w5 // dy + + mul v30.4h, v30.4h, v29.4h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is width+height-1, for w=4, h=16, <= 32 + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.4h, v29.4h, v30.4h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + mov v4.8b, v31.8b + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + + tbx v4.8b, {v0.16b, v1.16b}, v26.8b // left[base] + + trn1 v27.2s, v27.2s, v28.2s // base + 1, base + 2 + trn1 v24.2s, v24.2s, v24.2s // frac + trn1 v25.2s, v25.2s, v25.2s // 64 - frac +1: + mov v5.8b, v31.8b + tbx v5.8b, {v0.16b, v1.16b}, v27.8b // left[base+1], left[base+2] + + trn1 v4.2s, v4.2s, v5.2s // left[base], left[base+1] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + rshrn v16.8b, v16.8h, #6 + st1 {v16.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + ext v4.8b, v5.8b, v5.8b, #4 + uqadd v27.8b, v27.8b, v21.8b // base += 2 + b 1b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + dup v29.8h, w5 // dy + + mul v30.8h, v30.8h, v29.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is width+height-1, for w=8, h=32, <= 48 + ld1 {v0.16b, v1.16b, v2.16b}, [x2] // left[] + add v30.8h, v29.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + mov v4.8b, v31.8b + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + + tbx v4.8b, {v0.16b, v1.16b, v2.16b}, v26.8b // left[base] +1: + mov v5.8b, v31.8b + mov v6.8b, v31.8b + tbx v5.8b, {v0.16b, v1.16b, v2.16b}, v27.8b // left[base+1] + tbx v6.8b, {v0.16b, v1.16b, v2.16b}, v28.8b // left[base+2] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull v17.8h, v5.8b, v25.8b + umlal v17.8h, v6.8b, v24.8b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.le 9f + + mov v4.8b, v6.8b + uqadd v27.8b, v27.8b, v21.8b // base += 2 + uqadd v28.8b, v28.8b, v21.8b // base += 2 + b 1b + +9: + ret + +160: + AARCH64_VALID_JUMP_TARGET + dup v28.8h, w5 // dy + + shl v29.8h, v28.8h, #3 // 8*dy + mul v30.8h, v30.8h, v28.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // This is only executed if we've checked that max_base_y <= 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] // left[] + add v28.8h, v28.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + add v29.8h, v28.8h, v29.8h // ypos + 8*dy + + xtn v24.8b, v28.8h // (uint8_t)ypos + xtn2 v24.16b, v29.8h + uqshrn v26.8b, v28.8h, #6 // base + uqshrn2 v26.16b, v29.8h, #6 + and v24.16b, v24.16b, v23.16b // frac + + mov v4.16b, v31.16b + uqadd v27.16b, v26.16b, v20.16b // base + 1 + uqadd v28.16b, v26.16b, v21.16b // base + 2 + sub v25.16b, v22.16b, v24.16b // 64 - frac + + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v26.16b // left[base] +1: + mov v5.16b, v31.16b + mov v6.16b, v31.16b + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v27.16b // left[base+1] + tbx v6.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v28.16b // left[base+2] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + umull v18.8h, v5.8b, v25.8b + umlal v18.8h, v6.8b, v24.8b + umull2 v19.8h, v5.16b, v25.16b + umlal2 v19.8h, v6.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn2 v16.16b, v17.8h, #6 + rshrn v17.8b, v18.8h, #6 + rshrn2 v17.16b, v19.8h, #6 + st1 {v16.16b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.16b}, [x0], x1 + b.le 9f + + mov v4.16b, v6.16b + uqadd v27.16b, v27.16b, v21.16b // base += 2 + uqadd v28.16b, v28.16b, v21.16b // base += 2 + b 1b + +9: + ret +320: +640: + AARCH64_VALID_JUMP_TARGET + dup v28.8h, w5 // dy + mov w12, w3 + + add x13, x0, x1 + + shl v29.8h, v28.8h, #3 // 8*dy + mul v30.8h, v30.8h, v28.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + lsl x1, x1, #1 + sub x1, x1, w3, uxtw + add v30.8h, v28.8h, v30.8h // ypos + + // This is only executed if we've checked that max_base_y <= 64. + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2] // left[] + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + +1: + mov v26.16b, v30.16b // reset ypos + +2: + add v27.8h, v26.8h, v29.8h // ypos + 8*dy + uqshrn v16.8b, v26.8h, #6 // base + uqshrn2 v16.16b, v27.8h, #6 + xtn v24.8b, v26.8h // (uint8_t)ypos + xtn2 v24.16b, v27.8h + umov w14, v16.b[0] + and v24.16b, v24.16b, v23.16b // frac + + uqadd v17.16b, v16.16b, v20.16b // base + 1 + cmp w14, w6 // base >= max_base_y + uqadd v18.16b, v16.16b, v21.16b // base + 2 + sub v25.16b, v22.16b, v24.16b // 64 - frac + + b.ge 4f + + mov v4.16b, v31.16b + mov v5.16b, v31.16b + mov v6.16b, v31.16b + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v16.16b // left[base] + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v17.16b // left[base+1] + tbx v6.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v18.16b // left[base+2] + + subs w3, w3, #16 + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + umull v18.8h, v5.8b, v25.8b + umlal v18.8h, v6.8b, v24.8b + umull2 v19.8h, v5.16b, v25.16b + umlal2 v19.8h, v6.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn2 v16.16b, v17.8h, #6 + rshrn v17.8b, v18.8h, #6 + rshrn2 v17.16b, v19.8h, #6 + st1 {v16.16b}, [x0], #16 + st1 {v17.16b}, [x13], #16 + b.le 3f + add v26.8h, v27.8h, v29.8h // ypos += 16*dy + b 2b + +3: + subs w4, w4, #2 + b.le 9f + movi v16.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + add v30.8h, v30.8h, v16.8h // ypos = dy + y*(1<<6)*2 + mov w3, w12 + b 1b + +4: + subs w3, w3, #16 + st1 {v31.16b}, [x0], #16 + st1 {v31.16b}, [x13], #16 + b.gt 4b + b 3b + +9: + ret + +L(ipred_z3_fill1_large_h16): + // Fallback case for max_base_y > 64; similar to the z1 + // implementation. This does the filtering vertically, filling out + // a 2x pixel column at a time. + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + + mov w12, w4 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // ypos += dy + cmp w8, w6 // base >= max_base_y + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw + add x10, x2, w10, uxtw + dup v4.16b, w9 // frac + dup v5.16b, w11 + ld1 {v0.16b, v1.16b}, [x8], #32 // left[base] + ld1 {v2.16b, v3.16b}, [x10], #32 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.16b, w9 // 64 - frac + dup v7.16b, w11 + add w7, w7, w5 // ypos += dy +2: + ext v16.16b, v0.16b, v1.16b, #1 // left[base+1] + ext v17.16b, v2.16b, v3.16b, #1 + subs w4, w4, #16 + umull v18.8h, v16.8b, v4.8b // left[base+1]*frac + umlal v18.8h, v0.8b, v6.8b // + left[base]*(64-frac) + umull2 v19.8h, v16.16b, v4.16b + umlal2 v19.8h, v0.16b, v6.16b + umull v20.8h, v17.8b, v5.8b + umlal v20.8h, v2.8b, v7.8b + umull2 v21.8h, v17.16b, v5.16b + umlal2 v21.8h, v2.16b, v7.16b + rshrn v16.8b, v18.8h, #6 + rshrn2 v16.16b, v19.8h, #6 + rshrn v17.8b, v20.8h, #6 + rshrn2 v17.16b, v21.8h, #6 + zip1 v18.16b, v16.16b, v17.16b + zip2 v19.16b, v16.16b, v17.16b + st1 {v18.h}[0], [x0], x1 + st1 {v18.h}[1], [x13], x1 + st1 {v18.h}[2], [x0], x1 + st1 {v18.h}[3], [x13], x1 + st1 {v18.h}[4], [x0], x1 + st1 {v18.h}[5], [x13], x1 + st1 {v18.h}[6], [x0], x1 + st1 {v18.h}[7], [x13], x1 + st1 {v19.h}[0], [x0], x1 + st1 {v19.h}[1], [x13], x1 + st1 {v19.h}[2], [x0], x1 + st1 {v19.h}[3], [x13], x1 + st1 {v19.h}[4], [x0], x1 + st1 {v19.h}[5], [x13], x1 + st1 {v19.h}[6], [x0], x1 + st1 {v19.h}[7], [x13], x1 + b.le 3f + mov v0.16b, v1.16b + ld1 {v1.16b}, [x8], #16 // left[base] + mov v2.16b, v3.16b + ld1 {v3.16b}, [x10], #16 + b 2b + +3: + subs w3, w3, #2 + b.le 9f + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #2 + add x13, x13, #2 + mov w4, w12 + b 1b +9: + ret + +L(ipred_z3_fill1_tbl): + .hword L(ipred_z3_fill1_tbl) - 640b + .hword L(ipred_z3_fill1_tbl) - 320b + .hword L(ipred_z3_fill1_tbl) - 160b + .hword L(ipred_z3_fill1_tbl) - 80b + .hword L(ipred_z3_fill1_tbl) - 40b +endfunc + +function ipred_z3_fill_padding_neon, export=0 + cmp w3, #16 + adr x8, L(ipred_z3_fill_padding_tbl) + b.gt L(ipred_z3_fill_padding_wide) + // w3 = remaining width, w4 = constant height + mov w12, w4 + +1: + // Fill a WxH rectangle with padding. W can be any number; + // this fills the exact width by filling in the largest + // power of two in the remaining width, and repeating. + clz w9, w3 + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + sub x9, x8, w9, uxtw + br x9 + +2: + st1 {v31.h}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.h}[0], [x13], x1 + st1 {v31.h}[0], [x0], x1 + st1 {v31.h}[0], [x13], x1 + b.gt 2b + subs w3, w3, #2 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #2 + add x13, x13, #2 + mov w4, w12 + b 1b + +4: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.s}[0], [x13], x1 + st1 {v31.s}[0], [x0], x1 + st1 {v31.s}[0], [x13], x1 + b.gt 4b + subs w3, w3, #4 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b + +8: + st1 {v31.8b}, [x0], x1 + subs w4, w4, #4 + st1 {v31.8b}, [x13], x1 + st1 {v31.8b}, [x0], x1 + st1 {v31.8b}, [x13], x1 + b.gt 4b + subs w3, w3, #8 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #8 + add x13, x13, #8 + mov w4, w12 + b 1b + +16: +32: +64: + st1 {v31.16b}, [x0], x1 + subs w4, w4, #4 + st1 {v31.16b}, [x13], x1 + st1 {v31.16b}, [x0], x1 + st1 {v31.16b}, [x13], x1 + b.gt 4b + subs w3, w3, #16 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w4, w12 + b 1b + +9: + ret + +L(ipred_z3_fill_padding_tbl): + .hword L(ipred_z3_fill_padding_tbl) - 64b + .hword L(ipred_z3_fill_padding_tbl) - 32b + .hword L(ipred_z3_fill_padding_tbl) - 16b + .hword L(ipred_z3_fill_padding_tbl) - 8b + .hword L(ipred_z3_fill_padding_tbl) - 4b + .hword L(ipred_z3_fill_padding_tbl) - 2b + +L(ipred_z3_fill_padding_wide): + // Fill a WxH rectangle with padding, with W > 16. + lsr x1, x1, #1 + mov w12, w3 + sub x1, x1, w3, uxtw +1: + ands w5, w3, #15 + b.eq 2f + // If the width isn't aligned to 16, first do one 16 byte write + // and align the start pointer. + sub w3, w3, w5 + st1 {v31.16b}, [x0] + add x0, x0, w5, uxtw +2: + // Fill the rest of the line with aligned 16 byte writes. + subs w3, w3, #16 + st1 {v31.16b}, [x0], #16 + b.gt 2b + subs w4, w4, #1 + add x0, x0, x1 + b.le 9f + mov w3, w12 + b 1b +9: + ret +endfunc + +function ipred_z3_fill2_8bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // left[max_base_y] + movrel x11, increments + ld1r {v31.16b}, [x10] // padding + ld1 {v30.8h}, [x11] // increments + b.eq 80f + +40: // w == 4 + dup v29.4h, w5 // dy + + mul v30.4h, v30.4h, v29.4h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is 2*(width+height)-2, but width+height <= 16, + // so max_base_y <= 32. + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.4h, v29.4h, v30.4h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + uqadd v29.8b, v27.8b, v21.8b // base + 3 + + trn1 v24.2s, v24.2s, v24.2s // frac + trn1 v26.2s, v26.2s, v28.2s // base + 0, base + 2 + trn1 v27.2s, v27.2s, v29.2s // base + 1, base + 3 + trn1 v25.2s, v25.2s, v25.2s // 64 - frac + + movi v21.16b, #4 +1: + mov v4.8b, v31.8b + mov v5.8b, v31.8b + tbx v4.8b, {v0.16b, v1.16b}, v26.8b // left[base], left[base+2] + tbx v5.8b, {v0.16b, v1.16b}, v27.8b // left[base+1], left[base+3] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + rshrn v16.8b, v16.8h, #6 + st1 {v16.s}[0], [x0], x1 + subs w4, w4, #2 + st1 {v16.s}[1], [x0], x1 + b.le 9f + + uqadd v26.8b, v26.8b, v21.8b // base += 4 + uqadd v27.8b, v27.8b, v21.8b // base += 4 + b 1b + +9: + ret + +80: // w == 8 + dup v29.8h, w5 // dy + + mul v30.8h, v30.8h, v29.8h // {0,1,2,3,4,5,6,7}*dy + movi v23.16b, #0x3e + + // Worst case max_base_y is 2*(width+height)-2, but width+height <= 16, + // so max_base_y <= 32. + ld1 {v0.16b, v1.16b}, [x2] // left[] + add v30.8h, v29.8h, v30.8h // ypos + + movi v22.16b, #64 + movi v20.16b, #1 + movi v21.16b, #2 + + xtn v24.8b, v30.8h // (uint8_t)ypos + uqshrn v26.8b, v30.8h, #6 // base + and v24.8b, v24.8b, v23.8b // frac + + uqadd v27.8b, v26.8b, v20.8b // base + 1 + uqadd v28.8b, v26.8b, v21.8b // base + 2 + sub v25.8b, v22.8b, v24.8b // 64 - frac + uqadd v29.8b, v27.8b, v21.8b // base + 3 + + trn1 v24.2d, v24.2d, v24.2d // frac + trn1 v26.2d, v26.2d, v28.2d // base + 0, base + 2 + trn1 v27.2d, v27.2d, v29.2d // base + 1, base + 3 + trn1 v25.2d, v25.2d, v25.2d // 64 - frac + + movi v21.16b, #4 +1: + mov v4.16b, v31.16b + mov v5.16b, v31.16b + tbx v4.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v26.16b // left[base], left[base+2] + tbx v5.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v27.16b // left[base+1], left[base+3] + + umull v16.8h, v4.8b, v25.8b // left[base]*(64-frac) + umlal v16.8h, v5.8b, v24.8b // + left[base+1]*frac + umull2 v17.8h, v4.16b, v25.16b + umlal2 v17.8h, v5.16b, v24.16b + rshrn v16.8b, v16.8h, #6 + rshrn v17.8b, v17.8h, #6 + st1 {v16.8b}, [x0], x1 + subs w4, w4, #2 + st1 {v17.8b}, [x0], x1 + b.le 9f + + uqadd v26.16b, v26.16b, v21.16b // base += 4 + uqadd v27.16b, v27.16b, v21.16b // base += 4 + b 1b + +9: + ret +endfunc + + +// void ipred_filter_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height); +function ipred_filter_8bpc_neon, export=1 + and w5, w5, #511 + movrel x6, X(filter_intra_taps) + lsl w5, w5, #6 + add x6, x6, w5, uxtw + ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x6], #32 + clz w9, w3 + adr x5, L(ipred_filter_tbl) + ld1 {v20.8b, v21.8b, v22.8b}, [x6] + sub w9, w9, #26 + ldrh w9, [x5, w9, uxtw #1] + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + sub x5, x5, w9, uxtw + sxtl v18.8h, v18.8b + sxtl v19.8h, v19.8b + add x6, x0, x1 + lsl x1, x1, #1 + sxtl v20.8h, v20.8b + sxtl v21.8h, v21.8b + sxtl v22.8h, v22.8b + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ldur s0, [x2, #1] // top (0-3) + sub x2, x2, #2 + mov x7, #-2 + uxtl v0.8h, v0.8b // top (0-3) +4: + ld1 {v1.s}[0], [x2], x7 // left (0-1) + topleft (2) + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + uxtl v1.8h, v1.8b // left (0-1) + topleft (2) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + sqrshrun v2.8b, v2.8h, #4 + subs w4, w4, #2 + st1 {v2.s}[0], [x0], x1 + uxtl v0.8h, v2.8b + st1 {v2.s}[1], [x6], x1 + ext v0.16b, v0.16b, v0.16b, #8 // move top from [4-7] to [0-3] + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ldur d0, [x2, #1] // top (0-7) + sub x2, x2, #2 + mov x7, #-2 + uxtl v0.8h, v0.8b // top (0-7) +8: + ld1 {v1.s}[0], [x2], x7 // left (0-1) + topleft (2) + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + uxtl v1.8h, v1.8b // left (0-1) + topleft (2) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + mul v3.8h, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + sqrshrun v2.8b, v2.8h, #4 + uxtl v1.8h, v2.8b // first block, in 16 bit + mla v3.8h, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + mla v3.8h, v16.8h, v0.h[3] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v1.h[3] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v1.h[7] // p6(left[1]) * filter(6) + sqrshrun v3.8b, v3.8h, #4 + subs w4, w4, #2 + st2 {v2.s, v3.s}[0], [x0], x1 + zip2 v0.2s, v2.2s, v3.2s + st2 {v2.s, v3.s}[1], [x6], x1 + uxtl v0.8h, v0.8b + b.gt 8b + ret +160: +320: + AARCH64_VALID_JUMP_TARGET + add x8, x2, #1 + sub x2, x2, #2 + mov x7, #-2 + sub x1, x1, w3, uxtw + mov w9, w3 + +1: + ld1 {v0.s}[0], [x2], x7 // left (0-1) + topleft (2) + uxtl v0.8h, v0.8b // left (0-1) + topleft (2) +2: + ld1 {v2.16b}, [x8], #16 // top(0-15) + mul v3.8h, v16.8h, v0.h[2] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + uxtl v1.8h, v2.8b // top(0-7) + uxtl2 v2.8h, v2.16b // top(8-15) + mla v3.8h, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + mla v3.8h, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + mla v3.8h, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + mul v4.8h, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + mla v4.8h, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + mla v4.8h, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + sqrshrun v3.8b, v3.8h, #4 + uxtl v0.8h, v3.8b // first block, in 16 bit + mla v4.8h, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + mla v4.8h, v16.8h, v1.h[3] // p0(topleft) * filter(0) + mla v4.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v4.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + mul v5.8h, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + mla v5.8h, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + mla v5.8h, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + sqrshrun v4.8b, v4.8h, #4 + uxtl v0.8h, v4.8b // second block, in 16 bit + mla v5.8h, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + mla v5.8h, v16.8h, v1.h[7] // p0(topleft) * filter(0) + mla v5.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v5.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + mul v6.8h, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + mla v6.8h, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + mla v6.8h, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + sqrshrun v5.8b, v5.8h, #4 + uxtl v0.8h, v5.8b // third block, in 16 bit + mla v6.8h, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + mla v6.8h, v16.8h, v2.h[3] // p0(topleft) * filter(0) + mla v6.8h, v21.8h, v0.h[3] // p5(left[0]) * filter(5) + mla v6.8h, v22.8h, v0.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + sqrshrun v6.8b, v6.8h, #4 + + st4 {v3.s, v4.s, v5.s, v6.s}[0], [x0], #16 + st4 {v3.s, v4.s, v5.s, v6.s}[1], [x6], #16 + b.le 8f + ins v0.h[2], v2.h[7] + ins v0.b[0], v6.b[7] + ins v0.b[2], v6.b[3] + b 2b +8: + subs w4, w4, #2 + b.le 9f + sub x8, x6, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_filter_tbl): + .hword L(ipred_filter_tbl) - 320b + .hword L(ipred_filter_tbl) - 160b + .hword L(ipred_filter_tbl) - 80b + .hword L(ipred_filter_tbl) - 40b +endfunc + +// void pal_pred_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_8bpc_neon, export=1 + ld1 {v0.8h}, [x2] + clz w9, w4 + adr x6, L(pal_pred_tbl) + sub w9, w9, #25 + ldrh w9, [x6, w9, uxtw #1] + xtn v0.8b, v0.8h + sub x6, x6, w9, uxtw + add x2, x0, x1 + lsl x1, x1, #1 + br x6 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b}, [x3], #16 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + st1 {v1.s}[0], [x0], x1 + st1 {v1.s}[1], [x2], x1 + st1 {v1.s}[2], [x0], x1 + st1 {v1.s}[3], [x2], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x3], #32 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + st1 {v1.d}[0], [x0], x1 + tbl v2.16b, {v0.16b}, v2.16b + st1 {v1.d}[1], [x2], x1 + st1 {v2.d}[0], [x0], x1 + st1 {v2.d}[1], [x2], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b, v3.16b, v4.16b}, [x3], #64 + subs w5, w5, #4 + tbl v1.16b, {v0.16b}, v1.16b + tbl v2.16b, {v0.16b}, v2.16b + st1 {v1.16b}, [x0], x1 + tbl v3.16b, {v0.16b}, v3.16b + st1 {v2.16b}, [x2], x1 + tbl v4.16b, {v0.16b}, v4.16b + st1 {v3.16b}, [x0], x1 + st1 {v4.16b}, [x2], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x3], #64 + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x3], #64 + subs w5, w5, #4 + tbl v16.16b, {v0.16b}, v16.16b + tbl v17.16b, {v0.16b}, v17.16b + tbl v18.16b, {v0.16b}, v18.16b + tbl v19.16b, {v0.16b}, v19.16b + tbl v20.16b, {v0.16b}, v20.16b + st1 {v16.16b, v17.16b}, [x0], x1 + tbl v21.16b, {v0.16b}, v21.16b + st1 {v18.16b, v19.16b}, [x2], x1 + tbl v22.16b, {v0.16b}, v22.16b + st1 {v20.16b, v21.16b}, [x0], x1 + tbl v23.16b, {v0.16b}, v23.16b + st1 {v22.16b, v23.16b}, [x2], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x3], #64 + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x3], #64 + subs w5, w5, #2 + tbl v16.16b, {v0.16b}, v16.16b + tbl v17.16b, {v0.16b}, v17.16b + tbl v18.16b, {v0.16b}, v18.16b + tbl v19.16b, {v0.16b}, v19.16b + st1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0], x1 + tbl v20.16b, {v0.16b}, v20.16b + tbl v21.16b, {v0.16b}, v21.16b + tbl v22.16b, {v0.16b}, v22.16b + tbl v23.16b, {v0.16b}, v23.16b + st1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x2], x1 + b.gt 64b + ret + +L(pal_pred_tbl): + .hword L(pal_pred_tbl) - 64b + .hword L(pal_pred_tbl) - 32b + .hword L(pal_pred_tbl) - 16b + .hword L(pal_pred_tbl) - 8b + .hword L(pal_pred_tbl) - 4b +endfunc + +// void ipred_cfl_128_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_128_8bpc_neon, export=1 + clz w9, w3 + adr x7, L(ipred_cfl_128_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + movi v0.8h, #128 // dc + dup v1.8h, w6 // alpha + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 +L(ipred_cfl_splat_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x5], #32 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + cmlt v4.8h, v2.8h, #0 // sign + cmlt v5.8h, v3.8h, #0 + add v2.8h, v2.8h, v4.8h // diff + sign + add v3.8h, v3.8h, v5.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [x0], x1 + st1 {v2.s}[1], [x6], x1 + subs w4, w4, #4 + st1 {v3.s}[0], [x0], x1 + st1 {v3.s}[1], [x6], x1 + b.gt L(ipred_cfl_splat_w4) + ret +L(ipred_cfl_splat_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x5], #64 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + mul v4.8h, v4.8h, v1.8h + mul v5.8h, v5.8h, v1.8h + cmlt v16.8h, v2.8h, #0 // sign + cmlt v17.8h, v3.8h, #0 + cmlt v18.8h, v4.8h, #0 + cmlt v19.8h, v5.8h, #0 + add v2.8h, v2.8h, v16.8h // diff + sign + add v3.8h, v3.8h, v17.8h + add v4.8h, v4.8h, v18.8h + add v5.8h, v5.8h, v19.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + srshr v4.8h, v4.8h, #6 + srshr v5.8h, v5.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + add v4.8h, v4.8h, v0.8h + add v5.8h, v5.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + st1 {v2.8b}, [x0], x1 + st1 {v3.8b}, [x6], x1 + subs w4, w4, #4 + st1 {v4.8b}, [x0], x1 + st1 {v5.8b}, [x6], x1 + b.gt L(ipred_cfl_splat_w8) + ret +L(ipred_cfl_splat_w16): + AARCH64_VALID_JUMP_TARGET + add x7, x5, w3, uxtw #1 + sub x1, x1, w3, uxtw + mov w9, w3 +1: + ld1 {v2.8h, v3.8h}, [x5], #32 + ld1 {v4.8h, v5.8h}, [x7], #32 + mul v2.8h, v2.8h, v1.8h // diff = ac * alpha + mul v3.8h, v3.8h, v1.8h + mul v4.8h, v4.8h, v1.8h + mul v5.8h, v5.8h, v1.8h + cmlt v16.8h, v2.8h, #0 // sign + cmlt v17.8h, v3.8h, #0 + cmlt v18.8h, v4.8h, #0 + cmlt v19.8h, v5.8h, #0 + add v2.8h, v2.8h, v16.8h // diff + sign + add v3.8h, v3.8h, v17.8h + add v4.8h, v4.8h, v18.8h + add v5.8h, v5.8h, v19.8h + srshr v2.8h, v2.8h, #6 // (diff + sign + 32) >> 6 = apply_sign() + srshr v3.8h, v3.8h, #6 + srshr v4.8h, v4.8h, #6 + srshr v5.8h, v5.8h, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + add v4.8h, v4.8h, v0.8h + add v5.8h, v5.8h, v0.8h + sqxtun v2.8b, v2.8h // iclip_pixel(dc + apply_sign()) + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + subs w3, w3, #16 + st1 {v2.8b, v3.8b}, [x0], #16 + st1 {v4.8b, v5.8b}, [x6], #16 + b.gt 1b + subs w4, w4, #2 + add x5, x5, w9, uxtw #1 + add x7, x7, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b.gt 1b + ret + +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w8) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w4) +endfunc + +// void ipred_cfl_top_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_top_8bpc_neon, export=1 + clz w9, w3 + adr x7, L(ipred_cfl_top_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + dup v1.8h, w6 // alpha + add x2, x2, #1 + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 +4: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v2.4h, v2.4h, v3.4h + urshr v2.4h, v2.4h, #5 + dup v0.8h, v2.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_top_tbl): + .hword L(ipred_cfl_top_tbl) - 32b + .hword L(ipred_cfl_top_tbl) - 16b + .hword L(ipred_cfl_top_tbl) - 8b + .hword L(ipred_cfl_top_tbl) - 4b +endfunc + +// void ipred_cfl_left_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_left_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + clz w9, w3 + clz w8, w4 + adr x10, L(ipred_cfl_splat_tbl) + adr x7, L(ipred_cfl_left_tbl) + sub w9, w9, #26 + sub w8, w8, #26 + ldrh w9, [x10, w9, uxtw #1] + ldrh w8, [x7, w8, uxtw #1] + dup v1.8h, w6 // alpha + sub x9, x10, w9, uxtw + sub x7, x7, w8, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x7 + +L(ipred_cfl_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2] + uaddlv h0, v0.8b + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add v2.4h, v2.4h, v3.4h + urshr v2.4h, v2.4h, #5 + dup v0.8h, v2.h[0] + br x9 + +L(ipred_cfl_left_tbl): + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h32) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h16) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h8) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h4) +endfunc + +// void ipred_cfl_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha); +function ipred_cfl_8bpc_neon, export=1 + sub x2, x2, w4, uxtw + add w8, w3, w4 // width + height + dup v1.8h, w6 // alpha + clz w9, w3 + clz w6, w4 + dup v16.8h, w8 // width + height + adr x7, L(ipred_cfl_tbl) + rbit w8, w8 // rbit(width + height) + sub w9, w9, #22 // 26 leading bits, minus table offset 4 + sub w6, w6, #26 + clz w8, w8 // ctz(width + height) + ldrh w9, [x7, w9, uxtw #1] + ldrh w6, [x7, w6, uxtw #1] + neg w8, w8 // -ctz(width + height) + sub x9, x7, w9, uxtw + sub x7, x7, w6, uxtw + ushr v16.8h, v16.8h, #1 // (width + height) >> 1 + dup v17.8h, w8 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x7 + +L(ipred_cfl_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], #4 + ins v0.s[1], wzr + add x2, x2, #1 + uaddlv h0, v0.8b + br x9 +L(ipred_cfl_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.s}[0], [x2] + ins v2.s[1], wzr + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.8b + cmp w4, #4 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x3334/2) + movk w16, #(0x5556/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], #8 + uaddlv h0, v0.8b + add x2, x2, #1 + br x9 +L(ipred_cfl_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.8b + cmp w4, #8 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x2], #16 + uaddlv h0, v0.16b + add x2, x2, #1 + br x9 +L(ipred_cfl_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.16b + cmp w4, #16 + add v0.4h, v0.4h, v2.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 4/8/32 + cmp w4, #4 + mov w16, #(0x3334/2) + mov w17, #(0x5556/2) + csel w16, w16, w17, eq + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2], #32 + uaddlv h2, v2.16b + uaddlv h3, v3.16b + add x2, x2, #1 + add v0.4h, v2.4h, v3.4h + br x9 +L(ipred_cfl_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b, v3.16b}, [x2] + add v0.4h, v0.4h, v16.4h + uaddlv h2, v2.16b + uaddlv h3, v3.16b + cmp w4, #32 + add v0.4h, v0.4h, v2.4h + add v0.4h, v0.4h, v3.4h + ushl v0.4h, v0.4h, v17.4h + b.eq 1f + // h = 8/16 + mov w16, #(0x5556/2) + movk w16, #(0x3334/2), lsl #16 + add w17, w4, w4 // w17 = 2*h = 16 or 32 + lsr w16, w16, w17 + dup v16.4h, w16 + sqdmulh v0.4h, v0.4h, v16.4h +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_tbl): + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h4) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w4) +endfunc + +// void cfl_ac_420_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_420_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_420_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v0.d}[1], [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + subs w8, w8, #2 + st1 {v0.8h}, [x0], #16 + add v16.8h, v16.8h, v0.8h + b.gt 1b + trn2 v1.2d, v0.2d, v0.2d + trn2 v0.2d, v0.2d, v0.2d +L(ipred_cfl_ac_420_w4_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + b.gt 2b +3: + // Aggregate the sums + add v0.8h, v16.8h, v17.8h + uaddlv s0, v0.8h // sum + sub x0, x0, w6, uxtw #3 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x10], x2 + ld1 {v2.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v3.16b}, [x10], x2 + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + add v0.8h, v0.8h, v1.8h + add v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v2.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + b.gt 1b + mov v0.16b, v1.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v0.d}[1], [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + dup v1.4h, v0.h[3] + dup v3.4h, v0.h[7] + trn2 v2.2d, v0.2d, v0.2d + subs w8, w8, #2 + st1 {v0.4h, v1.4h, v2.4h, v3.4h}, [x0], #32 + add v16.4h, v16.4h, v0.4h + add v17.4h, v17.4h, v1.4h + add v18.4h, v18.4h, v2.4h + add v19.4h, v19.4h, v3.4h + b.gt 1b + trn1 v0.2d, v2.2d, v3.2d + trn1 v1.2d, v2.2d, v3.2d + +L(ipred_cfl_ac_420_w8_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + add v18.8h, v18.8h, v0.8h + add v19.8h, v19.8h, v1.8h + b.gt 2b +3: + +L(ipred_cfl_ac_420_w8_calc_subtract_dc): + // Aggregate the sums + add v0.8h, v16.8h, v17.8h + add v2.8h, v18.8h, v19.8h + uaddlp v0.4s, v0.8h + uaddlp v2.4s, v2.8h + add v0.4s, v0.4s, v2.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #4 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +L(ipred_cfl_ac_420_w8_subtract_dc): +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + sub v2.8h, v2.8h, v4.8h + sub v3.8h, v3.8h, v4.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_420_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_420_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.16b, v1.16b}, [x1], x2 + ld1 {v2.16b, v3.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + ld1 {v4.16b, v5.16b}, [x1], x2 + uaddlp v1.8h, v1.16b + ld1 {v6.16b, v7.16b}, [x10], x2 + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + uaddlp v4.8h, v4.16b + uaddlp v5.8h, v5.16b + uaddlp v6.8h, v6.16b + uaddlp v7.8h, v7.16b + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + add v4.8h, v4.8h, v6.8h + add v5.8h, v5.8h, v7.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v1.8h, #1 + shl v2.8h, v4.8h, #1 + shl v3.8h, v5.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr d1, [x1, #16] + ld1 {v0.16b}, [x1], x2 + ldr d3, [x10, #16] + ld1 {v2.16b}, [x10], x2 + uaddlp v1.4h, v1.8b + ldr d5, [x1, #16] + uaddlp v0.8h, v0.16b + ld1 {v4.16b}, [x1], x2 + uaddlp v3.4h, v3.8b + ldr d7, [x10, #16] + uaddlp v2.8h, v2.16b + ld1 {v6.16b}, [x10], x2 + uaddlp v5.4h, v5.8b + uaddlp v4.8h, v4.16b + uaddlp v7.4h, v7.8b + uaddlp v6.8h, v6.16b + add v1.4h, v1.4h, v3.4h + add v0.8h, v0.8h, v2.8h + add v5.4h, v5.4h, v7.4h + add v4.8h, v4.8h, v6.8h + shl v1.4h, v1.4h, #1 + shl v0.8h, v0.8h, #1 + shl v3.4h, v5.4h, #1 + shl v2.8h, v4.8h, #1 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + ld1 {v4.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v6.16b}, [x10], x2 + uaddlp v2.8h, v2.16b + uaddlp v4.8h, v4.16b + uaddlp v6.8h, v6.16b + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v2.8h, v4.8h, #1 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + ld1 {v4.8b}, [x1], x2 + uaddlp v0.4h, v0.8b + ld1 {v6.8b}, [x10], x2 + uaddlp v2.4h, v2.8b + uaddlp v4.4h, v4.8b + uaddlp v6.4h, v6.8b + add v0.4h, v0.4h, v2.4h + add v4.4h, v4.4h, v6.4h + shl v0.4h, v0.4h, #1 + shl v2.4h, v4.4h, #1 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + +L(ipred_cfl_ac_420_w16_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 2b +3: + + // Double the height and reuse the w8 summing/subtracting + lsl w6, w6, #1 + b L(ipred_cfl_ac_420_w8_calc_subtract_dc) + +L(ipred_cfl_ac_420_tbl): + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w16) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w8) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w4) + .hword 0 + +L(ipred_cfl_ac_420_w16_tbl): + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad0) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad1) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad2) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad3) +endfunc + +// void cfl_ac_422_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_422_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_422_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8b}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v1.8b}, [x1], x2 + ld1 {v1.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + subs w8, w8, #4 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x10], x2 + ld1 {v2.16b}, [x1], x2 + uaddlp v0.8h, v0.16b + ld1 {v3.16b}, [x10], x2 + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + shl v2.8h, v2.8h, #2 + shl v3.8h, v3.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8b}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v2.8b}, [x1], x2 + ld1 {v2.d}[1], [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v2.8h, v2.16b + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v0.h[3] + dup v5.8h, v0.h[7] + dup v6.4h, v2.h[3] + dup v7.8h, v2.h[7] + trn2 v1.2d, v0.2d, v5.2d + trn1 v0.2d, v0.2d, v4.2d + trn2 v3.2d, v2.2d, v7.2d + trn1 v2.2d, v2.2d, v6.2d + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_422_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_422_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.16b, v1.16b}, [x1], x2 + ld1 {v2.16b, v3.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v1.8h, v1.16b + uaddlp v2.8h, v2.16b + uaddlp v3.8h, v3.16b + shl v0.8h, v0.8h, #2 + shl v1.8h, v1.8h, #2 + shl v2.8h, v2.8h, #2 + shl v3.8h, v3.8h, #2 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr d1, [x1, #16] + ld1 {v0.16b}, [x1], x2 + ldr d3, [x10, #16] + ld1 {v2.16b}, [x10], x2 + uaddlp v1.4h, v1.8b + uaddlp v0.8h, v0.16b + uaddlp v3.4h, v3.8b + uaddlp v2.8h, v2.16b + shl v1.4h, v1.4h, #2 + shl v0.8h, v0.8h, #2 + shl v3.4h, v3.4h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + uaddlp v0.8h, v0.16b + uaddlp v2.8h, v2.16b + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + uaddlp v0.4h, v0.8b + uaddlp v2.4h, v2.8b + shl v0.4h, v0.4h, #2 + shl v2.4h, v2.4h, #2 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_tbl): + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w16) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w8) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w4) + .hword 0 + +L(ipred_cfl_ac_422_w16_tbl): + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad0) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad1) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad2) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad3) +endfunc + +// void cfl_ac_444_8bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_8bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_444_tbl) + sub w8, w8, #26 + ldrh w8, [x7, w8, uxtw #1] + movi v16.8h, #0 + movi v17.8h, #0 + movi v18.8h, #0 + movi v19.8h, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_444_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.s}[0], [x1], x2 + ld1 {v0.s}[1], [x10], x2 + ld1 {v1.s}[0], [x1], x2 + ld1 {v1.s}[1], [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v1.8h, v1.8b, #3 + subs w8, w8, #4 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x10], x2 + ld1 {v2.8b}, [x1], x2 + ushll v0.8h, v0.8b, #3 + ld1 {v3.8b}, [x10], x2 + ushll v1.8h, v1.8b, #3 + ushll v2.8h, v2.8b, #3 + ushll v3.8h, v3.8b, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + ld1 {v0.16b}, [x1], x2 + ld1 {v2.16b}, [x10], x2 + ld1 {v4.16b}, [x1], x2 + ushll2 v1.8h, v0.16b, #3 + ushll v0.8h, v0.8b, #3 + ld1 {v6.16b}, [x10], x2 + ushll2 v3.8h, v2.16b, #3 + ushll v2.8h, v2.8b, #3 + ushll2 v5.8h, v4.16b, #3 + ushll v4.8h, v4.8b, #3 + ushll2 v7.8h, v6.16b, #3 + ushll v6.8h, v6.8b, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + mov v0.16b, v6.16b + mov v1.16b, v7.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + ld1 {v0.8b}, [x1], x2 + ld1 {v2.8b}, [x10], x2 + ld1 {v4.8b}, [x1], x2 + ld1 {v6.8b}, [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v2.8h, v2.8b, #3 + ushll v4.8h, v4.8b, #3 + ushll v6.8h, v6.8b, #3 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + dup v5.8h, v4.h[7] + dup v7.8h, v6.h[7] + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + mov v0.16b, v6.16b + mov v1.16b, v7.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_444_w32_tbl) + ldrh w3, [x7, w3, uxtw] // (w3>>1) << 1 + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_444_w32_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, without padding + ld1 {v2.16b, v3.16b}, [x1], x2 + ld1 {v6.16b, v7.16b}, [x10], x2 + ushll v0.8h, v2.8b, #3 + ushll2 v1.8h, v2.16b, #3 + ushll v2.8h, v3.8b, #3 + ushll2 v3.8h, v3.16b, #3 + ushll v4.8h, v6.8b, #3 + ushll2 v5.8h, v6.16b, #3 + ushll v6.8h, v7.8b, #3 + ushll2 v7.8h, v7.16b, #3 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 8 + ldr d2, [x1, #16] + ld1 {v1.16b}, [x1], x2 + ldr d6, [x10, #16] + ld1 {v5.16b}, [x10], x2 + ushll v2.8h, v2.8b, #3 + ushll v0.8h, v1.8b, #3 + ushll2 v1.8h, v1.16b, #3 + ushll v6.8h, v6.8b, #3 + ushll v4.8h, v5.8b, #3 + ushll2 v5.8h, v5.16b, #3 + dup v3.8h, v2.h[7] + dup v7.8h, v6.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 16 + ld1 {v1.16b}, [x1], x2 + ld1 {v5.16b}, [x10], x2 + ushll v0.8h, v1.8b, #3 + ushll2 v1.8h, v1.16b, #3 + ushll v4.8h, v5.8b, #3 + ushll2 v5.8h, v5.16b, #3 + dup v2.8h, v1.h[7] + dup v3.8h, v1.h[7] + dup v6.8h, v5.h[7] + dup v7.8h, v5.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 24 + ld1 {v0.8b}, [x1], x2 + ld1 {v4.8b}, [x10], x2 + ushll v0.8h, v0.8b, #3 + ushll v4.8h, v4.8b, #3 + dup v1.8h, v0.h[7] + dup v2.8h, v0.h[7] + dup v3.8h, v0.h[7] + dup v5.8h, v4.h[7] + dup v6.8h, v4.h[7] + dup v7.8h, v4.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v16.8h, v16.8h, v0.8h + add v17.8h, v17.8h, v1.8h + add v18.8h, v18.8h, v2.8h + add v19.8h, v19.8h, v3.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 1b + +L(ipred_cfl_ac_444_w32_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #2 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + add v16.8h, v16.8h, v4.8h + add v17.8h, v17.8h, v5.8h + add v18.8h, v18.8h, v6.8h + add v19.8h, v19.8h, v7.8h + b.gt 2b +3: + + // Quadruple the height and reuse the w8 subtracting + lsl w6, w6, #2 + // Aggregate the sums, with wider intermediates earlier than in + // ipred_cfl_ac_420_w8_calc_subtract_dc. + uaddlp v0.4s, v16.8h + uaddlp v1.4s, v17.8h + uaddlp v2.4s, v18.8h + uaddlp v3.4s, v19.8h + add v0.4s, v0.4s, v1.4s + add v2.4s, v2.4s, v3.4s + add v0.4s, v0.4s, v2.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #4 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] + b L(ipred_cfl_ac_420_w8_subtract_dc) + +L(ipred_cfl_ac_444_tbl): + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w32) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w16) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w8) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w4) + +L(ipred_cfl_ac_444_w32_tbl): + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad0) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad2) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad4) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad6) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/ipred16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5639 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// void ipred_dc_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height, +// const int bitdepth_max); +function ipred_dc_128_16bpc_neon, export=1 + ldr w8, [sp] + clz w3, w3 + adr x5, L(ipred_dc_128_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + dup v0.8h, w8 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + urshr v0.8h, v0.8h, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b + sub x1, x1, #64 +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_128_tbl): + .hword L(ipred_dc_128_tbl) - 640b + .hword L(ipred_dc_128_tbl) - 320b + .hword L(ipred_dc_128_tbl) - 160b + .hword L(ipred_dc_128_tbl) - 8b + .hword L(ipred_dc_128_tbl) - 4b +endfunc + +// void ipred_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_v_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_v_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #2 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] +4: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] +8: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + sub x1, x1, #64 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_v_tbl): + .hword L(ipred_v_tbl) - 640b + .hword L(ipred_v_tbl) - 320b + .hword L(ipred_v_tbl) - 160b + .hword L(ipred_v_tbl) - 80b + .hword L(ipred_v_tbl) - 40b +endfunc + +// void ipred_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_h_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_h_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + sub x2, x2, #8 + sub x5, x5, w3, uxtw + mov x7, #-8 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +4: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + st1 {v3.4h}, [x0], x1 + st1 {v2.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v1.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 + str q3, [x0, #16] + str q2, [x6, #16] + stp q3, q3, [x0, #32] + stp q2, q2, [x6, #32] + stp q3, q3, [x0, #64] + stp q2, q2, [x6, #64] + stp q3, q3, [x0, #96] + stp q2, q2, [x6, #96] + st1 {v3.8h}, [x0], x1 + st1 {v2.8h}, [x6], x1 + subs w4, w4, #4 + str q1, [x0, #16] + str q0, [x6, #16] + stp q1, q1, [x0, #32] + stp q0, q0, [x6, #32] + stp q1, q1, [x0, #64] + stp q0, q0, [x6, #64] + stp q1, q1, [x0, #96] + stp q0, q0, [x6, #96] + st1 {v1.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_h_tbl): + .hword L(ipred_h_tbl) - 64b + .hword L(ipred_h_tbl) - 32b + .hword L(ipred_h_tbl) - 16b + .hword L(ipred_h_tbl) - 8b + .hword L(ipred_h_tbl) - 4b +endfunc + +// void ipred_dc_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_top_16bpc_neon, export=1 + clz w3, w3 + adr x5, L(ipred_dc_top_tbl) + sub w3, w3, #25 + ldrh w3, [x5, w3, uxtw #1] + add x2, x2, #2 + sub x5, x5, w3, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.4h, v0.h[0] +4: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] +8: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addv h0, v0.8h + urshr v2.4h, v0.4h, #4 + dup v0.8h, v2.h[0] + dup v1.8h, v2.h[0] +16: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #5 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +32: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #6 + sub x1, x1, #64 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +64: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 64b + ret + +L(ipred_dc_top_tbl): + .hword L(ipred_dc_top_tbl) - 640b + .hword L(ipred_dc_top_tbl) - 320b + .hword L(ipred_dc_top_tbl) - 160b + .hword L(ipred_dc_top_tbl) - 80b + .hword L(ipred_dc_top_tbl) - 40b +endfunc + +// void ipred_dc_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_left_16bpc_neon, export=1 + sub x2, x2, w4, uxtw #1 + clz w3, w3 + clz w7, w4 + adr x5, L(ipred_dc_left_tbl) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w7, w7, #25 + ldrh w3, [x5, w3, uxtw #1] + ldrh w7, [x5, w7, uxtw #1] + sub x3, x5, w3, uxtw + sub x5, x5, w7, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + br x3 +L(ipred_dc_left_w4): + AARCH64_VALID_JUMP_TARGET + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt L(ipred_dc_left_w4) + ret + +L(ipred_dc_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x3 +L(ipred_dc_left_w8): + AARCH64_VALID_JUMP_TARGET + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt L(ipred_dc_left_w8) + ret + +L(ipred_dc_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addv h0, v0.8h + urshr v2.4h, v0.4h, #4 + dup v0.8h, v2.h[0] + dup v1.8h, v2.h[0] + br x3 +L(ipred_dc_left_w16): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b +1: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2] + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + uaddlp v0.4s, v0.8h + addv s0, v0.4s + rshrn v4.4h, v0.4s, #5 + dup v0.8h, v4.h[0] + br x3 +L(ipred_dc_left_w32): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b +1: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + uaddlv s0, v0.8h + rshrn v4.4h, v0.4s, #6 + dup v0.8h, v4.h[0] + br x3 +L(ipred_dc_left_w64): + AARCH64_VALID_JUMP_TARGET + mov v1.16b, v0.16b + mov v2.16b, v0.16b + mov v3.16b, v0.16b + sub x1, x1, #64 +1: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 1b + ret + +L(ipred_dc_left_tbl): + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_h4) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w64) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w32) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w16) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w8) + .hword L(ipred_dc_left_tbl) - L(ipred_dc_left_w4) +endfunc + +// void ipred_dc_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_dc_16bpc_neon, export=1 + sub x2, x2, w4, uxtw #1 + add w7, w3, w4 // width + height + clz w3, w3 + clz w6, w4 + dup v16.4s, w7 // width + height + adr x5, L(ipred_dc_tbl) + rbit w7, w7 // rbit(width + height) + sub w3, w3, #20 // 25 leading bits, minus table offset 5 + sub w6, w6, #25 + clz w7, w7 // ctz(width + height) + ldrh w3, [x5, w3, uxtw #1] + ldrh w6, [x5, w6, uxtw #1] + neg w7, w7 // -ctz(width + height) + sub x3, x5, w3, uxtw + sub x5, x5, w6, uxtw + ushr v16.4s, v16.4s, #1 // (width + height) >> 1 + dup v17.4s, w7 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + br x5 + +L(ipred_dc_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], #8 + uaddlv s0, v0.4h + add x2, x2, #2 + br x3 +L(ipred_dc_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.4h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s1, v1.4h + cmp w4, #4 + add v0.2s, v0.2s, v1.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.4h, v0.h[0] +2: + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.4h}, [x0], x1 + st1 {v0.4h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2], #16 + uaddlv s0, v0.8h + add x2, x2, #2 + br x3 +L(ipred_dc_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s1, v1.8h + cmp w4, #8 + add v0.2s, v0.2s, v1.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] +2: + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h}, [x0], x1 + st1 {v0.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h}, [x2], #32 + addp v0.8h, v0.8h, v1.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + uaddlv s1, v1.8h + cmp w4, #16 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/8/32/64 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v0.8h, v1.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v0.8h, v0.8h, v2.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h, v3.8h, v4.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + addp v3.8h, v3.8h, v4.8h + addp v1.8h, v1.8h, v3.8h + uaddlv s1, v1.8h + cmp w4, #32 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16/64 + cmp w4, #8 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_h64): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], #64 + addp v0.8h, v0.8h, v1.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + addp v0.8h, v0.8h, v4.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x3 +L(ipred_dc_w64): + AARCH64_VALID_JUMP_TARGET + ld1 {v1.8h, v2.8h, v3.8h, v4.8h}, [x2], #64 + add v0.2s, v0.2s, v16.2s + addp v1.8h, v1.8h, v2.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x2] + addp v3.8h, v3.8h, v4.8h + addp v20.8h, v20.8h, v21.8h + addp v22.8h, v22.8h, v23.8h + addp v1.8h, v1.8h, v3.8h + addp v20.8h, v20.8h, v22.8h + addp v1.8h, v1.8h, v20.8h + uaddlv s1, v1.8h + cmp w4, #64 + add v0.2s, v0.2s, v1.2s + ushl v4.2s, v0.2s, v17.2s + b.eq 1f + // h = 16/32 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v4.2s, v4.2s, v16.2s + ushr v4.2s, v4.2s, #17 +1: + sub x1, x1, #64 + dup v0.8h, v4.h[0] + dup v1.8h, v4.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v4.h[0] +2: + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], #64 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x1 + b.gt 2b + ret + +L(ipred_dc_tbl): + .hword L(ipred_dc_tbl) - L(ipred_dc_h64) + .hword L(ipred_dc_tbl) - L(ipred_dc_h32) + .hword L(ipred_dc_tbl) - L(ipred_dc_h16) + .hword L(ipred_dc_tbl) - L(ipred_dc_h8) + .hword L(ipred_dc_tbl) - L(ipred_dc_h4) + .hword L(ipred_dc_tbl) - L(ipred_dc_w64) + .hword L(ipred_dc_tbl) - L(ipred_dc_w32) + .hword L(ipred_dc_tbl) - L(ipred_dc_w16) + .hword L(ipred_dc_tbl) - L(ipred_dc_w8) + .hword L(ipred_dc_tbl) - L(ipred_dc_w4) +endfunc + +// void ipred_paeth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_paeth_16bpc_neon, export=1 + clz w9, w3 + adr x5, L(ipred_paeth_tbl) + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x2] + add x8, x2, #2 + sub x2, x2, #8 + sub x5, x5, w9, uxtw + mov x7, #-8 + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v5.2d}, [x8] + sub v6.8h, v5.8h, v4.8h // top - topleft +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + add v16.8h, v6.8h, v0.8h // base + add v17.8h, v6.8h, v2.8h + sabd v20.8h, v5.8h, v16.8h // tdiff + sabd v21.8h, v5.8h, v17.8h + sabd v22.8h, v4.8h, v16.8h // tldiff + sabd v23.8h, v4.8h, v17.8h + sabd v16.8h, v0.8h, v16.8h // ldiff + sabd v17.8h, v2.8h, v17.8h + umin v18.8h, v20.8h, v22.8h // min(tdiff, tldiff) + umin v19.8h, v21.8h, v23.8h + cmge v20.8h, v22.8h, v20.8h // tldiff >= tdiff + cmge v21.8h, v23.8h, v21.8h + cmge v16.8h, v18.8h, v16.8h // min(tdiff, tldiff) >= ldiff + cmge v17.8h, v19.8h, v17.8h + bsl v21.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v20.16b, v5.16b, v4.16b + bit v21.16b, v2.16b, v17.16b // ldiff <= min ? left : ... + bit v20.16b, v0.16b, v16.16b + st1 {v21.d}[1], [x0], x1 + st1 {v21.d}[0], [x6], x1 + subs w4, w4, #4 + st1 {v20.d}[1], [x0], x1 + st1 {v20.d}[0], [x6], x1 + b.gt 4b + ret +80: +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + ld1 {v5.8h}, [x8], #16 + mov w9, w3 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 +1: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 +2: + sub v6.8h, v5.8h, v4.8h // top - topleft + add v16.8h, v6.8h, v0.8h // base + add v17.8h, v6.8h, v1.8h + add v18.8h, v6.8h, v2.8h + add v19.8h, v6.8h, v3.8h + sabd v20.8h, v5.8h, v16.8h // tdiff + sabd v21.8h, v5.8h, v17.8h + sabd v22.8h, v5.8h, v18.8h + sabd v23.8h, v5.8h, v19.8h + sabd v24.8h, v4.8h, v16.8h // tldiff + sabd v25.8h, v4.8h, v17.8h + sabd v26.8h, v4.8h, v18.8h + sabd v27.8h, v4.8h, v19.8h + sabd v16.8h, v0.8h, v16.8h // ldiff + sabd v17.8h, v1.8h, v17.8h + sabd v18.8h, v2.8h, v18.8h + sabd v19.8h, v3.8h, v19.8h + umin v28.8h, v20.8h, v24.8h // min(tdiff, tldiff) + umin v29.8h, v21.8h, v25.8h + umin v30.8h, v22.8h, v26.8h + umin v31.8h, v23.8h, v27.8h + cmge v20.8h, v24.8h, v20.8h // tldiff >= tdiff + cmge v21.8h, v25.8h, v21.8h + cmge v22.8h, v26.8h, v22.8h + cmge v23.8h, v27.8h, v23.8h + cmge v16.8h, v28.8h, v16.8h // min(tdiff, tldiff) >= ldiff + cmge v17.8h, v29.8h, v17.8h + cmge v18.8h, v30.8h, v18.8h + cmge v19.8h, v31.8h, v19.8h + bsl v23.16b, v5.16b, v4.16b // tdiff <= tldiff ? top : topleft + bsl v22.16b, v5.16b, v4.16b + bsl v21.16b, v5.16b, v4.16b + bsl v20.16b, v5.16b, v4.16b + bit v23.16b, v3.16b, v19.16b // ldiff <= min ? left : ... + bit v22.16b, v2.16b, v18.16b + bit v21.16b, v1.16b, v17.16b + bit v20.16b, v0.16b, v16.16b + st1 {v23.8h}, [x0], #16 + st1 {v22.8h}, [x6], #16 + subs w3, w3, #8 + st1 {v21.8h}, [x5], #16 + st1 {v20.8h}, [x10], #16 + b.le 8f + ld1 {v5.8h}, [x8], #16 + b 2b +8: + subs w4, w4, #4 + b.le 9f + // End of horizontal loop, move pointers to next four rows + sub x8, x8, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + // Load the top row as early as possible + ld1 {v5.8h}, [x8], #16 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_paeth_tbl): + .hword L(ipred_paeth_tbl) - 640b + .hword L(ipred_paeth_tbl) - 320b + .hword L(ipred_paeth_tbl) - 160b + .hword L(ipred_paeth_tbl) - 80b + .hword L(ipred_paeth_tbl) - 40b +endfunc + +// void ipred_smooth_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_16bpc_neon, export=1 + movrel x10, X(sm_weights) + add x11, x10, w4, uxtw + add x10, x10, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_tbl) + sub x12, x2, w4, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x12] // bottom + add x8, x2, #2 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2d}, [x8] // top + ld1r {v7.2s}, [x10] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + dup v5.8h, v6.h[3] // right + sub v6.8h, v6.8h, v4.8h // top-bottom + uxtl v7.8h, v7.8b // weights_hor + add v31.4h, v4.4h, v5.4h // bottom+right +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + zip1 v1.2d, v1.2d, v0.2d // left, flipped + zip1 v0.2d, v3.2d, v2.2d + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v18.8h, v18.8b + smlal v20.4s, v0.4h, v7.4h // += (left-right)*weights_hor + smlal2 v21.4s, v0.8h, v7.8h + smlal v22.4s, v1.4h, v7.4h + smlal2 v23.4s, v1.8h, v7.8h + smlal v20.4s, v6.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v6.8h, v16.8h + smlal v22.4s, v6.4h, v18.4h + smlal2 v23.4s, v6.8h, v18.8h + rshrn v20.4h, v20.4s, #9 + rshrn v21.4h, v21.4s, #9 + rshrn v22.4h, v22.4s, #9 + rshrn v23.4h, v23.4s, #9 + st1 {v20.4h}, [x0], x1 + st1 {v21.4h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.4h}, [x0], x1 + st1 {v23.4h}, [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8h}, [x8] // top + ld1 {v7.8b}, [x10] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + dup v5.8h, v6.h[7] // right + sub v6.8h, v6.8h, v4.8h // top-bottom + uxtl v7.8h, v7.8b // weights_hor + add v31.4h, v4.4h, v5.4h // bottom+right +8: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x11], #4 // weights_ver + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + ushll v24.4s, v31.4h, #8 + ushll v25.4s, v31.4h, #8 + ushll v26.4s, v31.4h, #8 + ushll v27.4s, v31.4h, #8 + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sub v2.8h, v2.8h, v5.8h + sub v3.8h, v3.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v19.8h, v19.8b + smlal v20.4s, v3.4h, v7.4h // += (left-right)*weights_hor + smlal2 v21.4s, v3.8h, v7.8h // (left flipped) + smlal v22.4s, v2.4h, v7.4h + smlal2 v23.4s, v2.8h, v7.8h + smlal v24.4s, v1.4h, v7.4h + smlal2 v25.4s, v1.8h, v7.8h + smlal v26.4s, v0.4h, v7.4h + smlal2 v27.4s, v0.8h, v7.8h + smlal v20.4s, v6.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v6.8h, v16.8h + smlal v22.4s, v6.4h, v17.4h + smlal2 v23.4s, v6.8h, v17.8h + smlal v24.4s, v6.4h, v18.4h + smlal2 v25.4s, v6.8h, v18.8h + smlal v26.4s, v6.4h, v19.4h + smlal2 v27.4s, v6.8h, v19.8h + rshrn v20.4h, v20.4s, #9 + rshrn2 v20.8h, v21.4s, #9 + rshrn v21.4h, v22.4s, #9 + rshrn2 v21.8h, v23.4s, #9 + rshrn v22.4h, v24.4s, #9 + rshrn2 v22.8h, v25.4s, #9 + rshrn v23.4h, v26.4s, #9 + rshrn2 v23.8h, v27.4s, #9 + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + add x12, x2, w3, uxtw #1 + sub x1, x1, w3, uxtw #1 + ld1r {v5.8h}, [x12] // right + sub x2, x2, #4 + mov x7, #-4 + mov w9, w3 + add v31.4h, v4.4h, v5.4h // bottom+right + +1: + ld2r {v0.8h, v1.8h}, [x2], x7 // left + ld2r {v16.8b, v17.8b}, [x11], #2 // weights_ver + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + uxtl v16.8h, v16.8b // weights_ver + uxtl v17.8h, v17.8b +2: + ld1 {v7.16b}, [x10], #16 // weights_hor + ld1 {v2.8h, v3.8h}, [x8], #32 // top + ushll v20.4s, v31.4h, #8 // (bottom+right)*256 + ushll v21.4s, v31.4h, #8 + ushll v22.4s, v31.4h, #8 + ushll v23.4s, v31.4h, #8 + ushll v24.4s, v31.4h, #8 + ushll v25.4s, v31.4h, #8 + ushll v26.4s, v31.4h, #8 + ushll v27.4s, v31.4h, #8 + uxtl v6.8h, v7.8b // weights_hor + uxtl2 v7.8h, v7.16b + sub v2.8h, v2.8h, v4.8h // top-bottom + sub v3.8h, v3.8h, v4.8h + smlal v20.4s, v1.4h, v6.4h // += (left-right)*weights_hor + smlal2 v21.4s, v1.8h, v6.8h // (left flipped) + smlal v22.4s, v1.4h, v7.4h + smlal2 v23.4s, v1.8h, v7.8h + smlal v24.4s, v0.4h, v6.4h + smlal2 v25.4s, v0.8h, v6.8h + smlal v26.4s, v0.4h, v7.4h + smlal2 v27.4s, v0.8h, v7.8h + smlal v20.4s, v2.4h, v16.4h // += (top-bottom)*weights_ver + smlal2 v21.4s, v2.8h, v16.8h + smlal v22.4s, v3.4h, v16.4h + smlal2 v23.4s, v3.8h, v16.8h + smlal v24.4s, v2.4h, v17.4h + smlal2 v25.4s, v2.8h, v17.8h + smlal v26.4s, v3.4h, v17.4h + smlal2 v27.4s, v3.8h, v17.8h + rshrn v20.4h, v20.4s, #9 + rshrn2 v20.8h, v21.4s, #9 + rshrn v21.4h, v22.4s, #9 + rshrn2 v21.8h, v23.4s, #9 + rshrn v22.4h, v24.4s, #9 + rshrn2 v22.8h, v25.4s, #9 + rshrn v23.4h, v26.4s, #9 + rshrn2 v23.8h, v27.4s, #9 + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x8, w9, uxtw #1 + sub x10, x10, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_tbl): + .hword L(ipred_smooth_tbl) - 640b + .hword L(ipred_smooth_tbl) - 320b + .hword L(ipred_smooth_tbl) - 160b + .hword L(ipred_smooth_tbl) - 80b + .hword L(ipred_smooth_tbl) - 40b +endfunc + +// void ipred_smooth_v_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_v_16bpc_neon, export=1 + movrel x7, X(sm_weights) + add x7, x7, w4, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_v_tbl) + sub x8, x2, w4, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v4.8h}, [x8] // bottom + add x2, x2, #2 + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v6.2d}, [x2] // top + sub v6.8h, v6.8h, v4.8h // top-bottom +4: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + zip1 v16.2s, v16.2s, v17.2s // weights_ver + zip1 v18.2s, v18.2s, v19.2s + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v18.8h, v18.8b, #7 + sqrdmulh v20.8h, v6.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v6.8h, v18.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + st1 {v20.d}[0], [x0], x1 + st1 {v20.d}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.d}[0], [x0], x1 + st1 {v21.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v6.8h}, [x2] // top + sub v6.8h, v6.8h, v4.8h // top-bottom +8: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v17.8h, v17.8b, #7 + ushll v18.8h, v18.8b, #7 + ushll v19.8h, v19.8b, #7 + sqrdmulh v20.8h, v6.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v6.8h, v17.8h + sqrdmulh v22.8h, v6.8h, v18.8h + sqrdmulh v23.8h, v6.8h, v19.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + add v22.8h, v22.8h, v4.8h + add v23.8h, v23.8h, v4.8h + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + // Set up pointers for four rows in parallel; x0, x6, x5, x8 + add x5, x0, x1 + add x8, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld4r {v16.8b, v17.8b, v18.8b, v19.8b}, [x7], #4 // weights_ver + ushll v16.8h, v16.8b, #7 // weights_ver << 7 + ushll v17.8h, v17.8b, #7 + ushll v18.8h, v18.8b, #7 + ushll v19.8h, v19.8b, #7 +2: + ld1 {v2.8h, v3.8h}, [x2], #32 // top + sub v2.8h, v2.8h, v4.8h // top-bottom + sub v3.8h, v3.8h, v4.8h + sqrdmulh v20.8h, v2.8h, v16.8h // ((top-bottom)*weights_ver + 128) >> 8 + sqrdmulh v21.8h, v3.8h, v16.8h + sqrdmulh v22.8h, v2.8h, v17.8h + sqrdmulh v23.8h, v3.8h, v17.8h + sqrdmulh v24.8h, v2.8h, v18.8h + sqrdmulh v25.8h, v3.8h, v18.8h + sqrdmulh v26.8h, v2.8h, v19.8h + sqrdmulh v27.8h, v3.8h, v19.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v4.8h + add v22.8h, v22.8h, v4.8h + add v23.8h, v23.8h, v4.8h + add v24.8h, v24.8h, v4.8h + add v25.8h, v25.8h, v4.8h + add v26.8h, v26.8h, v4.8h + add v27.8h, v27.8h, v4.8h + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + st1 {v24.8h, v25.8h}, [x5], #32 + st1 {v26.8h, v27.8h}, [x8], #32 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x2, x2, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x8, x8, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_v_tbl): + .hword L(ipred_smooth_v_tbl) - 640b + .hword L(ipred_smooth_v_tbl) - 320b + .hword L(ipred_smooth_v_tbl) - 160b + .hword L(ipred_smooth_v_tbl) - 80b + .hword L(ipred_smooth_v_tbl) - 40b +endfunc + +// void ipred_smooth_h_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int a, +// const int max_width, const int max_height); +function ipred_smooth_h_16bpc_neon, export=1 + movrel x8, X(sm_weights) + add x8, x8, w3, uxtw + clz w9, w3 + adr x5, L(ipred_smooth_h_tbl) + add x12, x2, w3, uxtw #1 + sub w9, w9, #25 + ldrh w9, [x5, w9, uxtw #1] + ld1r {v5.8h}, [x12] // right + sub x5, x5, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v7.2s}, [x8] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + ushll v7.8h, v7.8b, #7 // weights_hor << 7 +4: + ld4r {v0.4h, v1.4h, v2.4h, v3.4h}, [x2], x7 // left + zip1 v1.2d, v1.2d, v0.2d // left, flipped + zip1 v0.2d, v3.2d, v2.2d + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sqrdmulh v20.8h, v0.8h, v7.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v1.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + st1 {v20.d}[0], [x0], x1 + st1 {v20.d}[1], [x6], x1 + subs w4, w4, #4 + st1 {v21.d}[0], [x0], x1 + st1 {v21.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v7.8b}, [x8] // weights_hor + sub x2, x2, #8 + mov x7, #-8 + ushll v7.8h, v7.8b, #7 // weights_hor << 7 +8: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + sub v3.8h, v3.8h, v5.8h // left-right + sub v2.8h, v2.8h, v5.8h + sub v1.8h, v1.8h, v5.8h + sub v0.8h, v0.8h, v5.8h + sqrdmulh v20.8h, v3.8h, v7.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v2.8h, v7.8h // (left flipped) + sqrdmulh v22.8h, v1.8h, v7.8h + sqrdmulh v23.8h, v0.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + add v22.8h, v22.8h, v5.8h + add v23.8h, v23.8h, v5.8h + st1 {v20.8h}, [x0], x1 + st1 {v21.8h}, [x6], x1 + subs w4, w4, #4 + st1 {v22.8h}, [x0], x1 + st1 {v23.8h}, [x6], x1 + b.gt 8b + ret +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + sub x2, x2, #8 + mov x7, #-8 + // Set up pointers for four rows in parallel; x0, x6, x5, x10 + add x5, x0, x1 + add x10, x6, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld4r {v0.8h, v1.8h, v2.8h, v3.8h}, [x2], x7 // left + sub v0.8h, v0.8h, v5.8h // left-right + sub v1.8h, v1.8h, v5.8h + sub v2.8h, v2.8h, v5.8h + sub v3.8h, v3.8h, v5.8h +2: + ld1 {v7.16b}, [x8], #16 // weights_hor + ushll v6.8h, v7.8b, #7 // weights_hor << 7 + ushll2 v7.8h, v7.16b, #7 + sqrdmulh v20.8h, v3.8h, v6.8h // ((left-right)*weights_hor + 128) >> 8 + sqrdmulh v21.8h, v3.8h, v7.8h // (left flipped) + sqrdmulh v22.8h, v2.8h, v6.8h + sqrdmulh v23.8h, v2.8h, v7.8h + sqrdmulh v24.8h, v1.8h, v6.8h + sqrdmulh v25.8h, v1.8h, v7.8h + sqrdmulh v26.8h, v0.8h, v6.8h + sqrdmulh v27.8h, v0.8h, v7.8h + add v20.8h, v20.8h, v5.8h + add v21.8h, v21.8h, v5.8h + add v22.8h, v22.8h, v5.8h + add v23.8h, v23.8h, v5.8h + add v24.8h, v24.8h, v5.8h + add v25.8h, v25.8h, v5.8h + add v26.8h, v26.8h, v5.8h + add v27.8h, v27.8h, v5.8h + subs w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + st1 {v22.8h, v23.8h}, [x6], #32 + st1 {v24.8h, v25.8h}, [x5], #32 + st1 {v26.8h, v27.8h}, [x10], #32 + b.gt 2b + subs w4, w4, #4 + b.le 9f + sub x8, x8, w9, uxtw + add x0, x0, x1 + add x6, x6, x1 + add x5, x5, x1 + add x10, x10, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_smooth_h_tbl): + .hword L(ipred_smooth_h_tbl) - 640b + .hword L(ipred_smooth_h_tbl) - 320b + .hword L(ipred_smooth_h_tbl) - 160b + .hword L(ipred_smooth_h_tbl) - 80b + .hword L(ipred_smooth_h_tbl) - 40b +endfunc + +const padding_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +padding_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void ipred_z1_upsample_edge_16bpc_neon(pixel *out, const int hsz, +// const pixel *const in, const int end, +// const int bitdepth_max); +function ipred_z1_upsample_edge_16bpc_neon, export=1 + dup v30.8h, w4 // bitdepth_max + movrel x4, padding_mask + ld1 {v0.8h, v1.8h}, [x2] // in[] + add x5, x2, w3, uxtw #1 // in[end] + sub x4, x4, w3, uxtw #1 + + ld1r {v2.8h}, [x5] // padding + ld1 {v3.8h, v4.8h}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v2.16b, v3.16b // padded in[] + bit v1.16b, v2.16b, v4.16b + + ext v4.16b, v0.16b, v1.16b, #2 + ext v5.16b, v1.16b, v2.16b, #2 + ext v6.16b, v0.16b, v1.16b, #4 + ext v7.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + + add v18.8h, v4.8h, v6.8h // in[i+1] + in[i+2] + add v19.8h, v5.8h, v7.8h + add v20.8h, v0.8h, v16.8h + add v21.8h, v1.8h, v17.8h + umull v22.4s, v18.4h, v31.4h // 9*(in[i+1] + in[i+2]) + umull2 v23.4s, v18.8h, v31.8h + umull v24.4s, v19.4h, v31.4h + umull2 v25.4s, v19.8h, v31.8h + usubw v22.4s, v22.4s, v20.4h + usubw2 v23.4s, v23.4s, v20.8h + usubw v24.4s, v24.4s, v21.4h + usubw2 v25.4s, v25.4s, v21.8h + + sqrshrun v16.4h, v22.4s, #4 + sqrshrun2 v16.8h, v23.4s, #4 + sqrshrun v17.4h, v24.4s, #4 + sqrshrun2 v17.8h, v25.4s, #4 + + smin v16.8h, v16.8h, v30.8h + smin v17.8h, v17.8h, v30.8h + + zip1 v0.8h, v4.8h, v16.8h + zip2 v1.8h, v4.8h, v16.8h + zip1 v2.8h, v5.8h, v17.8h + zip2 v3.8h, v5.8h, v17.8h + + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + + ret +endfunc + +// void ipred_z2_upsample_edge_16bpc_neon(pixel *out, const int sz, +// const pixel *const in, +// const int bitdepth_max); +function ipred_z2_upsample_edge_16bpc_neon, export=1 + dup v30.8h, w3 // bitdepth_max + // Here, sz is 4 or 8, and we produce 2*sz+1 output elements. + movrel x4, padding_mask + ld1 {v0.8h, v1.8h}, [x2] // in[] + add x5, x2, w1, uxtw #1 // in[sz] + sub x4, x4, w1, uxtw #1 + + ld1r {v3.8h}, [x2] // in[0] for padding + ld1r {v2.8h}, [x5] // padding + ld1 {v4.8h, v5.8h}, [x4] // padding_mask + + movi v31.8h, #9 + + bit v0.16b, v2.16b, v4.16b // padded in[] + bit v1.16b, v2.16b, v5.16b + + ext v4.16b, v3.16b, v0.16b, #14 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #4 + + add v16.8h, v0.8h, v5.8h // in[i+0] + in[i+1] + add v17.8h, v4.8h, v6.8h // in[i-1] + in[i+2] + umull v18.4s, v16.4h, v31.4h // 9*(in[i+1] + in[i+2]) + umull2 v19.4s, v16.8h, v31.8h + usubw v18.4s, v18.4s, v17.4h + usubw2 v19.4s, v19.4s, v17.8h + + sqrshrun v16.4h, v18.4s, #4 + sqrshrun2 v16.8h, v19.4s, #4 + + add x5, x0, #2*16 + + smin v16.8h, v16.8h, v30.8h + + zip1 v4.8h, v0.8h, v16.8h + zip2 v5.8h, v0.8h, v16.8h + + st1 {v2.h}[0], [x5] + // In case sz=8, output one single pixel in out[16]. + st1 {v4.8h, v5.8h}, [x0] + + ret +endfunc + +const edge_filter + .short 0, 4, 8, 0 + .short 0, 5, 6, 0 +// Leaving out the coeffs for strength=3 +// .byte 2, 4, 4, 0 +endconst + +// void ipred_z1_filter_edge_16bpc_neon(pixel *out, const int sz, +// const pixel *const in, const int end, +// const int strength); +function ipred_z1_filter_edge_16bpc_neon, export=1 + cmp w4, #3 + b.eq L(fivetap) // if (strength == 3) goto fivetap + + movrel x5, edge_filter, -6 + add x5, x5, w4, uxtw #3 // edge_filter + 2*((strength - 1)*4 + 1) + + ld1 {v31.s}[0], [x5] // kernel[1-2] + + ld1 {v0.8h}, [x2], #16 + + dup v30.8h, v31.h[0] + dup v31.8h, v31.h[1] +1: + // in[end], is the last valid pixel. We produce 16 pixels out by + // using 18 pixels in - the last pixel used is [17] of the ones + // read/buffered. + cmp w3, #17 + ld1 {v1.8h, v2.8h}, [x2], #32 + b.lt 2f + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + mul v16.8h, v0.8h, v30.8h + mla v16.8h, v3.8h, v31.8h + mla v16.8h, v5.8h, v30.8h + mul v17.8h, v1.8h, v30.8h + mla v17.8h, v4.8h, v31.8h + mla v17.8h, v6.8h, v30.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + urshr v16.8h, v16.8h, #4 + urshr v17.8h, v17.8h, #4 + sub w3, w3, #16 + st1 {v16.8h, v17.8h}, [x0], #32 + b.gt 1b + ret +2: + // Right padding + + // x2[w3-24] is the padding pixel (x2 points 24 pixels ahead) + movrel x5, padding_mask + sub w6, w3, #24 + sub x5, x5, w3, uxtw #1 + add x6, x2, w6, sxtw #1 + + ld1 {v3.8h, v4.8h}, [x5] // padding_mask + + ld1r {v2.8h}, [x6] + bit v0.16b, v2.16b, v3.16b // Pad v0-v1 + bit v1.16b, v2.16b, v4.16b + + // Filter one block + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + mul v16.8h, v0.8h, v30.8h + mla v16.8h, v3.8h, v31.8h + mla v16.8h, v5.8h, v30.8h + mul v17.8h, v1.8h, v30.8h + mla v17.8h, v4.8h, v31.8h + mla v17.8h, v6.8h, v30.8h + subs w1, w1, #16 + urshr v16.8h, v16.8h, #4 + urshr v17.8h, v17.8h, #4 + st1 {v16.8h, v17.8h}, [x0], #32 + b.le 9f +5: + // After one block, any remaining output would only be filtering + // padding - thus just store the padding. + subs w1, w1, #16 + st1 {v2.16b}, [x0], #16 + b.gt 5b +9: + ret + +L(fivetap): + sub x2, x2, #2 // topleft -= 1 pixel + movi v29.8h, #2 + ld1 {v0.8h}, [x2], #16 + movi v30.8h, #4 + movi v31.8h, #4 + ins v0.h[0], v0.h[1] +1: + // in[end+1], is the last valid pixel. We produce 16 pixels out by + // using 20 pixels in - the last pixel used is [19] of the ones + // read/buffered. + cmp w3, #18 + ld1 {v1.8h, v2.8h}, [x2], #32 + b.lt 2f // if (end + 1 < 19) + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + ext v18.16b, v0.16b, v1.16b, #8 + ext v19.16b, v1.16b, v2.16b, #8 + mul v20.8h, v0.8h, v29.8h + mla v20.8h, v3.8h, v30.8h + mla v20.8h, v5.8h, v31.8h + mla v20.8h, v16.8h, v30.8h + mla v20.8h, v18.8h, v29.8h + mul v21.8h, v1.8h, v29.8h + mla v21.8h, v4.8h, v30.8h + mla v21.8h, v6.8h, v31.8h + mla v21.8h, v17.8h, v30.8h + mla v21.8h, v19.8h, v29.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + urshr v20.8h, v20.8h, #4 + urshr v21.8h, v21.8h, #4 + sub w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + b.gt 1b + ret +2: + // Right padding + + // x2[w3+1-24] is the padding pixel (x2 points 24 pixels ahead) + movrel x5, padding_mask, -2 + sub w6, w3, #23 + sub x5, x5, w3, uxtw #1 + add x6, x2, w6, sxtw #1 + + ld1 {v3.8h, v4.8h, v5.8h}, [x5] // padding_mask + + ld1r {v28.8h}, [x6] + bit v0.16b, v28.16b, v3.16b // Pad v0-v2 + bit v1.16b, v28.16b, v4.16b + bit v2.16b, v28.16b, v5.16b +4: + // Filter one block + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v1.16b, v2.16b, #2 + ext v5.16b, v0.16b, v1.16b, #4 + ext v6.16b, v1.16b, v2.16b, #4 + ext v16.16b, v0.16b, v1.16b, #6 + ext v17.16b, v1.16b, v2.16b, #6 + ext v18.16b, v0.16b, v1.16b, #8 + ext v19.16b, v1.16b, v2.16b, #8 + mul v20.8h, v0.8h, v29.8h + mla v20.8h, v3.8h, v30.8h + mla v20.8h, v5.8h, v31.8h + mla v20.8h, v16.8h, v30.8h + mla v20.8h, v18.8h, v29.8h + mul v21.8h, v1.8h, v29.8h + mla v21.8h, v4.8h, v30.8h + mla v21.8h, v6.8h, v31.8h + mla v21.8h, v17.8h, v30.8h + mla v21.8h, v19.8h, v29.8h + subs w1, w1, #16 + mov v0.16b, v2.16b + mov v1.16b, v28.16b + mov v2.16b, v28.16b + urshr v20.8h, v20.8h, #4 + urshr v21.8h, v21.8h, #4 + sub w3, w3, #16 + st1 {v20.8h, v21.8h}, [x0], #32 + b.le 9f + // v0-v1[w3+1] is the last valid pixel; if (w3 + 1 > 0) we need to + // filter properly once more - aka (w3 >= 0). + cmp w3, #0 + b.ge 4b +5: + // When w3 <= 0, all remaining pixels in v0-v1 are equal to the + // last valid pixel - thus just output that without filtering. + subs w1, w1, #8 + st1 {v28.8h}, [x0], #16 + b.gt 5b +9: + ret +endfunc + +// void ipred_pixel_set_16bpc_neon(pixel *out, const pixel px, +// const int n); +function ipred_pixel_set_16bpc_neon, export=1 + dup v0.8h, w1 +1: + subs w2, w2, #8 + st1 {v0.8h}, [x0], #16 + b.gt 1b + ret +endfunc + +// void ipred_z1_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const int width, const int height, +// const int dx, const int max_base_x); +function ipred_z1_fill1_16bpc_neon, export=1 + clz w9, w3 + adr x8, L(ipred_z1_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw #1 // top[max_base_x] + sub x8, x8, w9, uxtw + ld1r {v31.8h}, [x10] // padding + mov w7, w5 + mov w15, #64 + br x8 +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + ext v1.16b, v0.16b, v0.16b, #2 // top[base+1] + ext v3.16b, v2.16b, v2.16b, #2 + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + st1 {v16.4h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.4h}, [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.4h}, [x0], x1 + b.gt 49b + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h}, [x8] // top[base] + ld1 {v2.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + ldr h1, [x8, #16] + ldr h3, [x10, #16] + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + ext v1.16b, v0.16b, v1.16b, #2 // top[base+1] + ext v3.16b, v2.16b, v3.16b, #2 + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v1.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v1.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v3.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v3.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + st1 {v16.8h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8h}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8h}, [x0], x1 + b.gt 89b + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + mov w12, w3 + + add x13, x0, x1 + lsl x1, x1, #1 + sub x1, x1, w3, uxtw #1 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 169f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v6.8h, w9 // frac + dup v7.8h, w11 + ld1 {v0.8h, v1.8h, v2.8h}, [x8], #48 // top[base] + ld1 {v3.8h, v4.8h, v5.8h}, [x10], #48 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v16.8h, w9 // 64 - frac + dup v17.8h, w11 + add w7, w7, w5 // xpos += dx +2: + ext v18.16b, v0.16b, v1.16b, #2 // top[base+1] + ext v19.16b, v1.16b, v2.16b, #2 + ext v20.16b, v3.16b, v4.16b, #2 + ext v21.16b, v4.16b, v5.16b, #2 + subs w3, w3, #16 + umull v22.4s, v0.4h, v16.4h // top[base]*(64-frac) + umlal v22.4s, v18.4h, v6.4h // + top[base+1]*frac + umull2 v23.4s, v0.8h, v16.8h + umlal2 v23.4s, v18.8h, v6.8h + umull v24.4s, v1.4h, v16.4h + umlal v24.4s, v19.4h, v6.4h + umull2 v25.4s, v1.8h, v16.8h + umlal2 v25.4s, v19.8h, v6.8h + umull v26.4s, v3.4h, v17.4h + umlal v26.4s, v20.4h, v7.4h + umull2 v27.4s, v3.8h, v17.8h + umlal2 v27.4s, v20.8h, v7.8h + umull v28.4s, v4.4h, v17.4h + umlal v28.4s, v21.4h, v7.4h + umull2 v29.4s, v4.8h, v17.8h + umlal2 v29.4s, v21.8h, v7.8h + rshrn v22.4h, v22.4s, #6 + rshrn2 v22.8h, v23.4s, #6 + rshrn v23.4h, v24.4s, #6 + rshrn2 v23.8h, v25.4s, #6 + rshrn v24.4h, v26.4s, #6 + rshrn2 v24.8h, v27.4s, #6 + rshrn v25.4h, v28.4s, #6 + rshrn2 v25.8h, v29.4s, #6 + st1 {v22.8h, v23.8h}, [x0], #32 + st1 {v24.8h, v25.8h}, [x13], #32 + b.le 3f + mov v0.16b, v2.16b + ld1 {v1.8h, v2.8h}, [x8], #32 // top[base] + mov v3.16b, v5.16b + ld1 {v4.8h, v5.8h}, [x10], #32 + b 2b + +3: + subs w4, w4, #2 + b.le 9f + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 1b +9: + ret + +169: + st1 {v31.8h}, [x0], #16 + subs w3, w3, #8 + st1 {v31.8h}, [x13], #16 + b.gt 169b + subs w4, w4, #2 + b.le 9b + add x0, x0, x1 + add x13, x13, x1 + mov w3, w12 + b 169b + +L(ipred_z1_fill1_tbl): + .hword L(ipred_z1_fill1_tbl) - 640b + .hword L(ipred_z1_fill1_tbl) - 320b + .hword L(ipred_z1_fill1_tbl) - 160b + .hword L(ipred_z1_fill1_tbl) - 80b + .hword L(ipred_z1_fill1_tbl) - 40b +endfunc + +function ipred_z1_fill2_16bpc_neon, export=1 + cmp w3, #8 + add x10, x2, w6, uxtw // top[max_base_x] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + b.eq 8f + +4: // w == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 49f + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8h, v0.8h, v0.8h // top[base+1] + uzp1 v0.8h, v0.8h, v0.8h // top[base] + uzp2 v3.8h, v2.8h, v2.8h + uzp1 v2.8h, v2.8h, v2.8h + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + st1 {v16.4h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.4h}, [x0], x1 + b.gt 4b + ret + +49: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.4h}, [x0], x1 + b.gt 49b + ret + +8: // w == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge 89f + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h, v1.8h}, [x8] // top[base] + ld1 {v2.8h, v3.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + uzp2 v20.8h, v0.8h, v1.8h // top[base+1] + uzp1 v0.8h, v0.8h, v1.8h // top[base] + uzp2 v21.8h, v2.8h, v3.8h + uzp1 v2.8h, v2.8h, v3.8h + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v20.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v20.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v21.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v21.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + st1 {v16.8h}, [x0], x1 + add w7, w7, w5 // xpos += dx + subs w4, w4, #2 + st1 {v17.8h}, [x0], x1 + b.gt 8b + ret + +89: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #2 + st1 {v31.8h}, [x0], x1 + b.gt 89b + ret +endfunc + +// void ipred_reverse_16bpc_neon(pixel *dst, const pixel *const src, +// const int n); +function ipred_reverse_16bpc_neon, export=1 + sub x1, x1, #16 + add x3, x0, #8 + mov x4, #16 +1: + ld1 {v0.8h}, [x1] + subs w2, w2, #8 + rev64 v0.8h, v0.8h + sub x1, x1, #16 + st1 {v0.d}[1], [x0], x4 + st1 {v0.d}[0], [x3], x4 + b.gt 1b + ret +endfunc + +const increments + .short 0, 1, 2, 3, 4, 5, 6, 7 +endconst + +// void ipred_z2_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const top, +// const pixel *const left, +// const int width, const int height, +// const int dx, const int dy); +function ipred_z2_fill1_16bpc_neon, export=1 + clz w10, w4 + adr x9, L(ipred_z2_fill1_tbl) + sub w10, w10, #25 + ldrh w10, [x9, w10, uxtw #1] + mov w8, #(1 << 6) // xpos = 1 << 6 + sub x9, x9, w10, uxtw + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + + br x9 +40: + AARCH64_VALID_JUMP_TARGET + + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // Worst case height for w=4 is 16, but we need at least h+1 elements + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2d, v30.2d, v28.2d // base_y + 1, base_y + 2 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v29.16b, #4 +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + // Cut corners here; only doing tbl over v0-v1 here; we only + // seem to need the last pixel, from v2, after skipping to the + // left-only codepath below. + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + ext v5.16b, v4.16b, v4.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 4b + +49: + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+2] + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 49b + +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + add x3, x3, #2 // Skip past left[0] + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // Worst case height for w=8 is 32. + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x3] // left[] + ld1r {v15.8h}, [x2] // left[0] == top[0] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + mov v18.16b, v15.16b // left[0] + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + movi v17.16b, #2 + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbx v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 (*2) + add v29.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + mov v19.16b, v15.16b // left[0] + ld1 {v6.8h, v7.8h}, [x11] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + mov v20.16b, v15.16b // left[0] + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + ext v5.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v21.8h, v21.8h, #0 + cmge v22.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 8b + +89: + mov v19.16b, v15.16b + mov v20.16b, v15.16b + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b // left[base_y+2] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v19.4h, v28.4h + umlal v6.4s, v20.4h, v27.4h + umull2 v7.4s, v19.8h, v28.8h + umlal2 v7.4s, v20.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v25.8h, w7 // -dy + add x3, x3, #2 // Skip past left[0] + + add x13, x0, x1 // alternating row + lsl x1, x1, #1 // stride *= 2 + sub x1, x1, w4, uxtw #1 // stride -= width + + movi v11.8h, #8 + mul v26.8h, v31.8h, v25.8h // {0,1,2,3,4,5,6,7}* -dy + add v26.8h, v26.8h, v25.8h // -= dy + mul v25.8h, v25.8h, v11.8h // -8*dy + + // Worst case height is 64, but we can only fit 32 pixels into + // v0-v3 usable within one tbx instruction. As long as base_y is + // up to 32, we use tbx. + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x3] // left[] + ld1r {v15.8h}, [x2] // left[0] == top[0] + + mov w12, w4 // orig w + neg w14, w4 // -w + +1: + mov v23.16b, v26.16b // reset ypos + + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, w14 // base_x <= -2*w + asr w11, w8, #6 // base_x + b.le 169f + + dup v17.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + ld1 {v4.8h}, [x9], #16 // top[base_x] + ld1 {v6.8h}, [x11], #16 + + movi v10.8h, #0x3e + movi v11.8h, #64 + + and v16.16b, v16.16b, v10.16b // frac_x + and v17.16b, v17.16b, v10.16b + + sub v8.8h, v11.8h, v16.8h // 64 - frac_x + sub v9.8h, v11.8h, v17.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + +2: + smov w10, v22.h[0] + + shrn v29.8b, v23.8h, #6 // ypos >> 6 + movi v12.8h, #64 + cmp w10, #0 // base_x (bottom left) >= 0 + smov w10, v29.b[0] // base_y[0] + movi v10.8h, #0x3e + + b.ge 4f + and v27.16b, v23.16b, v10.16b // frac_y + cmp w10, #(32-3) + + mov v18.16b, v15.16b // left[0] + sub v28.8h, v12.8h, v27.8h // 64 - frac_y + b.gt 22f + +21: + // base_y < 32, using tbx + shl v29.8b, v29.8b, #1 // 2*base_y + movi v11.8h, #1, lsl #8 + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v29.16b, v29.16b, v11.16b // 2*base, 2*base+1, ... + + movi v13.16b, #2 + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + + add v29.16b, v29.16b, v13.16b // base_y + 1 (*2) + mov v19.16b, v15.16b // left[0] + + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + + add v29.16b, v29.16b, v13.16b // base_y + 2 (*2) + mov v20.16b, v15.16b // left[0] + + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + + b 23f + +22: + // base_y >= 32, using separate loads. + smov w15, v29.b[1] + smov w16, v29.b[2] + add x10, x3, w10, sxtw #1 + smov w17, v29.b[3] + add x15, x3, w15, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[0], [x10] + smov w10, v29.b[4] + add x16, x3, w16, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[1], [x15] + smov w15, v29.b[5] + add x17, x3, w17, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[2], [x16] + smov w16, v29.b[6] + add x10, x3, w10, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[3], [x17] + smov w17, v29.b[7] + add x15, x3, w15, sxtw #1 + add x16, x3, w16, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[4], [x10] + add x17, x3, w17, sxtw #1 + ld3 {v18.h, v19.h, v20.h}[5], [x15] + ld3 {v18.h, v19.h, v20.h}[6], [x16] + ld3 {v18.h, v19.h, v20.h}[7], [x17] + +23: + + ld1 {v5.8h}, [x9], #16 // top[base_x] + ld1 {v7.8h}, [x11], #16 + + add v23.8h, v23.8h, v25.8h // ypos -= 8*dy + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + ext v18.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #2 + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v18.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v18.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v19.4h, v17.4h + umull2 v20.4s, v6.8h, v9.8h + umlal2 v20.4s, v19.8h, v17.8h + + cmge v18.8h, v21.8h, #0 + cmge v19.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v20.4s, #6 + + bit v10.16b, v12.16b, v18.16b + bit v11.16b, v13.16b, v19.16b + + st1 {v10.8h}, [x0], #16 + subs w4, w4, #8 + st1 {v11.8h}, [x13], #16 + b.le 3f + + movi v10.8h, #8 + mov v4.16b, v5.16b + mov v6.16b, v7.16b + add v21.8h, v21.8h, v10.8h // base_x += 8 + add v22.8h, v22.8h, v10.8h + b 2b + +3: + subs w5, w5, #2 + b.le 9f + movi v10.8h, #128 + add x0, x0, x1 + add x13, x13, x1 + mov w4, w12 // reset w + add v26.8h, v26.8h, v10.8h // ypos += 2*(1<<6) + b 1b + +4: // The rest of the row only predicted from top[] + ld1 {v5.8h}, [x9], #16 // top[base_x] + ld1 {v7.8h}, [x11], #16 + + ext v18.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v19.16b, v6.16b, v7.16b, #2 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v18.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v18.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v19.4h, v17.4h + umull2 v20.4s, v6.8h, v9.8h + umlal2 v20.4s, v19.8h, v17.8h + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v20.4s, #6 + + st1 {v12.8h}, [x0], #16 + subs w4, w4, #8 + st1 {v13.8h}, [x13], #16 + b.le 3b + + mov v4.16b, v5.16b + mov v6.16b, v7.16b + b 4b + +169: // The rest of the block only predicted from left[] + add x1, x1, w4, uxtw #1 // restore stride + mov w12, w5 // orig remaining h +1: + movi v12.8h, #64 + movi v10.8h, #0x3e + + shrn v29.8b, v23.8h, #6 // ypos >> 6 + and v27.16b, v23.16b, v10.16b // frac_y + + smov w10, v29.b[0] // base_y[0] + + shl v29.8b, v29.8b, #1 // 2*base_y + movi v11.8h, #1, lsl #8 + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v23.8h, v23.8h, v25.8h // ypos -= 8*dy + add v29.16b, v29.16b, v11.16b // 2*base, 2*base+1, ... + + cmp w10, #(32-1) + + mov v18.16b, v15.16b // left[0] + movi v21.16b, #2 + + sub v28.8h, v12.8h, v27.8h // 64 - frac_y + + b.gt 31f + + tbx v18.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y] + add v29.16b, v29.16b, v21.16b // base_y + 1 (*2) + +2: + // base_y < 32, using tbx. + smov w10, v29.b[0] // base_y[0] + mov v19.16b, v15.16b // left[0] + cmp w10, #(64-4) + b.gt 32f + tbx v19.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+1] + add v29.16b, v29.16b, v21.16b // base_y + 2 (*2) + mov v20.16b, v15.16b // left[0] + tbx v20.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v29.16b // left[base_y+2] + add v29.16b, v29.16b, v21.16b // next base_y + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v11.8h}, [x13], x1 + b.le 4f + mov v18.16b, v20.16b + b 2b + +31: // base_y >= 32, using separate loads, loading v18 if we had to bail + // in the prologue. + smov w10, v29.b[0] + smov w15, v29.b[2] + movi v21.16b, #2 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld1 {v18.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld1 {v18.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld1 {v18.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld1 {v18.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld1 {v18.h}[4], [x10] + add x17, x3, w17, sxtw + ld1 {v18.h}[5], [x15] + add v29.16b, v29.16b, v21.16b // next base_y + ld1 {v18.h}[6], [x16] + ld1 {v18.h}[7], [x17] + +32: // base_y >= 32, using separate loads. + cmp w5, #4 + b.lt 34f +33: // h >= 4, preserving v18 from the previous round, loading v19-v22. + smov w10, v29.b[0] + subs w5, w5, #4 + smov w15, v29.b[2] + movi v10.16b, #8 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[4], [x10] + add x17, x3, w17, sxtw + ld4 {v19.h, v20.h, v21.h, v22.h}[5], [x15] + ld4 {v19.h, v20.h, v21.h, v22.h}[6], [x16] + add v29.16b, v29.16b, v10.16b // next base_y + ld4 {v19.h, v20.h, v21.h, v22.h}[7], [x17] + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v20.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v12.4s, v21.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v13.4s, v20.8h, v28.8h + umlal2 v13.4s, v21.8h, v27.8h + umull v14.4s, v21.4h, v28.4h + umlal v14.4s, v22.4h, v27.4h + umull2 v18.4s, v21.8h, v28.8h + umlal2 v18.4s, v22.8h, v27.8h + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + st1 {v10.8h}, [x0], x1 + cmp w5, #2 + st1 {v11.8h}, [x13], x1 + st1 {v12.8h}, [x0], x1 + st1 {v13.8h}, [x13], x1 + b.lt 4f + mov v18.16b, v22.16b + b.gt 33b + +34: // h == 2, preserving v18 from the previous round, loading v19-v20. + smov w10, v29.b[0] + smov w15, v29.b[2] + movi v21.16b, #4 + smov w16, v29.b[4] + add x10, x3, w10, sxtw + smov w17, v29.b[6] + add x15, x3, w15, sxtw + ld2 {v19.h, v20.h}[0], [x10] + smov w10, v29.b[8] + add x16, x3, w16, sxtw + ld2 {v19.h, v20.h}[1], [x15] + smov w15, v29.b[10] + add x17, x3, w17, sxtw + ld2 {v19.h, v20.h}[2], [x16] + smov w16, v29.b[12] + add x10, x3, w10, sxtw + ld2 {v19.h, v20.h}[3], [x17] + smov w17, v29.b[14] + add x15, x3, w15, sxtw + add x16, x3, w16, sxtw + ld2 {v19.h, v20.h}[4], [x10] + add x17, x3, w17, sxtw + ld2 {v19.h, v20.h}[5], [x15] + ld2 {v19.h, v20.h}[6], [x16] + add v29.16b, v29.16b, v21.16b // next base_y + ld2 {v19.h, v20.h}[7], [x17] + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + st1 {v10.8h}, [x0], x1 + st1 {v11.8h}, [x13], x1 + // The h==2 case only happens once at the end, if at all. + +4: + subs w4, w4, #8 + b.le 9f + + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w5, w12 // reset h + b 1b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret + +L(ipred_z2_fill1_tbl): + .hword L(ipred_z2_fill1_tbl) - 640b + .hword L(ipred_z2_fill1_tbl) - 320b + .hword L(ipred_z2_fill1_tbl) - 160b + .hword L(ipred_z2_fill1_tbl) - 80b + .hword L(ipred_z2_fill1_tbl) - 40b +endfunc + +function ipred_z2_fill2_16bpc_neon, export=1 + cmp w4, #8 + mov w8, #(2 << 6) // xpos = 2 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.8h, v1.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + tbl v18.8b, {v0.16b}, v29.8b // left[base_y] + + trn1 v30.2d, v30.2d, v28.2d // base_y + 1, base_y + 2 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v29.16b, #4 + add v31.8h, v31.8h, v31.8h // {0,2,4,6,0,2,4,6} +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-8 // base_x <= -8 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + uzp2 v5.8h, v4.8h, v6.8h // top[base_x+1] + uzp1 v4.8h, v4.8h, v6.8h // top[base_x] + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 4b + +49: + tbl v19.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+1], left[base_y+2] + + trn1 v18.2d, v18.2d, v19.2d // left[base_y], left[base_y+1] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + ext v18.16b, v19.16b, v19.16b, #8 + add v30.16b, v30.16b, v29.16b // base_y += 2 (*2) + b 49b + +9: + ret + +80: + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + movi v17.8b, #1 + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // For upsample_top, w <= 8 and h <= 8; we may need up to h+1 elements + // from left. + ld1 {v0.8h, v1.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 1 + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + movi v17.16b, #2 + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + // Cut corners here; for the first row we don't expect to need to + // read outside of v0. + tbl v18.16b, {v0.16b}, v29.16b // left[base_y] + + add v30.16b, v29.16b, v19.16b // base_y + 2 (*2) + add v29.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 + add v31.16b, v31.16b, v31.16b // {0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14} +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + ld1 {v6.8h, v7.8h}, [x11] + + tbl v19.16b, {v0.16b, v1.16b}, v29.16b // left[base_y+1] + + sshr v21.8h, v16.8h, #6 // first base_x + sshr v22.8h, v17.8h, #6 + + tbl v20.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+2] + + uzp2 v2.8h, v4.8h, v5.8h // top[base_x+1] + uzp1 v4.8h, v4.8h, v5.8h // top[base_x] + uzp2 v3.8h, v6.8h, v7.8h + uzp1 v6.8h, v6.8h, v7.8h + mov v5.16b, v2.16b + mov v7.16b, v3.16b + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v21.8h, v21.8h, v31.8h // actual base_x + add v22.8h, v22.8h, v31.8h + + umull v12.4s, v19.4h, v28.4h + umlal v12.4s, v20.4h, v27.4h + umull2 v13.4s, v19.8h, v28.8h + umlal2 v13.4s, v20.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v21.8h, v21.8h, #0 + cmge v22.8h, v22.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v21.16b + bit v11.16b, v13.16b, v22.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 8b + +89: + tbl v19.16b, {v0.16b, v1.16b}, v29.16b // left[base_y+1] + tbl v20.16b, {v0.16b, v1.16b}, v30.16b // left[base_y+2] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v19.4h, v28.4h + umlal v6.4s, v20.4h, v27.4h + umull2 v7.4s, v19.8h, v28.8h + umlal2 v7.4s, v20.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + mov v18.16b, v20.16b + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 2 (*2) + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret +endfunc + +function ipred_z2_fill3_16bpc_neon, export=1 + cmp w4, #8 + mov w8, #(1 << 6) // xpos = 1 << 6 + sub w8, w8, w6 // xpos -= dx + + movrel x11, increments + ld1 {v31.8h}, [x11] // increments + neg w7, w7 // -dy + b.eq 80f + +40: + dup v30.4h, w7 // -dy + movi v17.8b, #1 + + mul v16.4h, v31.4h, v30.4h // {0,1,2,3}* -dy + movi v25.8h, #0x3e + add v30.4h, v16.4h, v30.4h // -= dy + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #2 + + shrn v29.8b, v30.8h, #6 // ypos >> 6 + and v27.8b, v30.8b, v25.8b // frac_y + + add v29.8b, v29.8b, v19.8b // base_y = (ypos >> 6) + 2 + + movi v23.4h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + movi v19.16b, #4 + zip1 v29.8b, v29.8b, v29.8b // duplicate elements + movi v17.8b, #2 + add v29.8b, v29.8b, v23.8b // 2*base, 2*base+1, ... + + add v30.8b, v29.8b, v17.8b // base_y + 1 (*2) + add v28.8b, v29.8b, v19.8b // base_y + 2 (*2) + + trn1 v31.2d, v31.2d, v31.2d // {0,1,2,3,0,1,2,3} + + add v24.8b, v30.8b, v19.8b // base_y + 3 (*2) + + trn1 v29.2d, v29.2d, v28.2d // base_y + 0, base_y + 2 + trn1 v30.2d, v30.2d, v24.2d // base_y + 1, base_y + 3 + + sub v28.4h, v26.4h, v27.4h // 64 - frac_y + + trn1 v27.2d, v27.2d, v27.2d // frac_y + trn1 v28.2d, v28.2d, v28.2d // 64 - frac_y + + movi v24.16b, #8 +4: + asr w9, w8, #6 // base_x + dup v16.4h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-4 // base_x <= -4 + asr w11, w8, #6 // base_x + b.le 49f + + lsl w9, w9, #1 + lsl w11, w11, #1 + + dup v17.4h, w8 // xpos + + ldr q4, [x2, w9, sxtw] // top[base_x] + ldr q6, [x2, w11, sxtw] + + trn1 v16.2d, v16.2d, v17.2d // xpos + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + sshr v20.8h, v16.8h, #6 // first base_x for each row + + ext v5.16b, v4.16b, v4.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v6.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + + trn1 v4.2d, v4.2d, v6.2d // top[base_x] + trn1 v5.2d, v5.2d, v7.2d // top[base_x+1] + + sub v17.8h, v26.8h, v16.8h // 64 - frac_x + + add v20.8h, v20.8h, v31.8h // actual base_x + + umull v21.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v21.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v22.4s, v18.8h, v28.8h + umlal2 v22.4s, v19.8h, v27.8h + + umull v23.4s, v4.4h, v17.4h // top[base_x]-*(64-frac_x) + umlal v23.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v24.4s, v4.8h, v17.8h + umlal2 v24.4s, v5.8h, v16.8h + + cmge v20.8h, v20.8h, #0 + + rshrn v21.4h, v21.4s, #6 + rshrn2 v21.8h, v22.4s, #6 + rshrn v22.4h, v23.4s, #6 + rshrn2 v22.8h, v24.4s, #6 + + movi v24.16b, #8 + + bit v21.16b, v22.16b, v20.16b + + st1 {v21.d}[0], [x0], x1 + sub w8, w8, w6 // xpos -= dx + subs w5, w5, #2 + st1 {v21.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 4 (*2) + b 4b + +49: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0], left[base_y+2] + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1], left[base_y+3] + + umull v20.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v20.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v21.4s, v18.8h, v28.8h + umlal2 v21.4s, v19.8h, v27.8h + + rshrn v20.4h, v20.4s, #6 + rshrn2 v20.8h, v21.4s, #6 + + st1 {v20.d}[0], [x0], x1 + subs w5, w5, #2 + st1 {v20.d}[1], [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 4 (*2) + add v30.16b, v30.16b, v24.16b // base_y += 4 (*2) + b 49b + +9: + ret + +80: + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + dup v18.8h, w7 // -dy + movi v17.16b, #2 + + mul v16.8h, v31.8h, v18.8h // {0,1,2,3,4,5,6,7}* -dy + movi v25.8h, #0x3e + add v16.8h, v16.8h, v18.8h // -= dy + + // For upsample_left, w <= 8 and h <= 8; we may need up to 2*h+1 elements. + ld1 {v0.8h, v1.8h, v2.8h}, [x3] // left[] + + movi v26.8h, #64 + movi v19.16b, #4 + + shrn v29.8b, v16.8h, #6 // ypos >> 6 + and v27.16b, v16.16b, v25.16b // frac_y + + add v29.8b, v29.8b, v17.8b // base_y = (ypos >> 6) + 2 + + movi v23.8h, #1, lsl #8 + shl v29.8b, v29.8b, #1 // 2*base_y + mov v18.16b, v15.16b // left[0] + zip1 v29.16b, v29.16b, v29.16b // duplicate elements + add v29.16b, v29.16b, v23.16b // 2*base, 2*base+1, ... + + add v30.16b, v29.16b, v17.16b // base_y + 1 (*2) + + sub v28.8h, v26.8h, v27.8h // 64 - frac_y + + movi v24.16b, #4 +8: + asr w9, w8, #6 // base_x + dup v16.8h, w8 // xpos + sub w8, w8, w6 // xpos -= dx + cmp w9, #-16 // base_x <= -16 + asr w11, w8, #6 // base_x + b.le 89f + + dup v17.8h, w8 // xpos + + add x9, x2, w9, sxtw #1 + add x11, x2, w11, sxtw #1 + + ld1 {v4.8h, v5.8h}, [x9] // top[base_x] + ld1 {v6.8h, v7.8h}, [x11] + + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0] + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1] + add v30.16b, v30.16b, v24.16b + + sshr v22.8h, v16.8h, #6 // first base_x + tbl v20.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+2] + sshr v23.8h, v17.8h, #6 + tbl v21.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+3] + + ext v5.16b, v4.16b, v5.16b, #2 // top[base_x+1] + ext v7.16b, v6.16b, v7.16b, #2 + + and v16.16b, v16.16b, v25.16b // frac_x + and v17.16b, v17.16b, v25.16b + + umull v10.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v10.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + + sub v8.8h, v26.8h, v16.8h // 64 - frac_x + sub v9.8h, v26.8h, v17.8h + + umull2 v11.4s, v18.8h, v28.8h + umlal2 v11.4s, v19.8h, v27.8h + + add v22.8h, v22.8h, v31.8h // actual base_x + add v23.8h, v23.8h, v31.8h + + umull v12.4s, v20.4h, v28.4h + umlal v12.4s, v21.4h, v27.4h + umull2 v13.4s, v20.8h, v28.8h + umlal2 v13.4s, v21.8h, v27.8h + + rshrn v10.4h, v10.4s, #6 + rshrn2 v10.8h, v11.4s, #6 + rshrn v11.4h, v12.4s, #6 + rshrn2 v11.8h, v13.4s, #6 + + umull v12.4s, v4.4h, v8.4h // top[base_x]-*(64-frac_x) + umlal v12.4s, v5.4h, v16.4h // + top[base_x+1]*frac_x + umull2 v13.4s, v4.8h, v8.8h + umlal2 v13.4s, v5.8h, v16.8h + umull v14.4s, v6.4h, v9.4h + umlal v14.4s, v7.4h, v17.4h + umull2 v18.4s, v6.8h, v9.8h + umlal2 v18.4s, v7.8h, v17.8h + + cmge v22.8h, v22.8h, #0 + cmge v23.8h, v23.8h, #0 + + rshrn v12.4h, v12.4s, #6 + rshrn2 v12.8h, v13.4s, #6 + rshrn v13.4h, v14.4s, #6 + rshrn2 v13.8h, v18.4s, #6 + + bit v10.16b, v12.16b, v22.16b + bit v11.16b, v13.16b, v23.16b + + st1 {v10.8h}, [x0], x1 + subs w5, w5, #2 + sub w8, w8, w6 // xpos -= dx + st1 {v11.8h}, [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b + b 8b + +89: + tbl v18.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+0] + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + tbl v19.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+1] + add v30.16b, v30.16b, v24.16b + tbl v20.16b, {v0.16b, v1.16b, v2.16b}, v29.16b // left[base_y+2] + tbl v21.16b, {v0.16b, v1.16b, v2.16b}, v30.16b // left[base_y+3] + + umull v4.4s, v18.4h, v28.4h // left[base_y]*(64-frac_y) + umlal v4.4s, v19.4h, v27.4h // + left[base_y+1]*frac_y + umull2 v5.4s, v18.8h, v28.8h + umlal2 v5.4s, v19.8h, v27.8h + umull v6.4s, v20.4h, v28.4h + umlal v6.4s, v21.4h, v27.4h + umull2 v7.4s, v20.8h, v28.8h + umlal2 v7.4s, v21.8h, v27.8h + + rshrn v4.4h, v4.4s, #6 + rshrn2 v4.8h, v5.4s, #6 + rshrn v5.4h, v6.4s, #6 + rshrn2 v5.8h, v7.4s, #6 + + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x0], x1 + b.le 9f + + add v29.16b, v29.16b, v24.16b // base_y += 2 (*2) + add v30.16b, v30.16b, v24.16b + b 89b + +9: + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret +endfunc + +// void ipred_z3_fill1_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const left, +// const int width, const int height, +// const int dy, const int max_base_y); +function ipred_z3_fill1_16bpc_neon, export=1 + clz w9, w4 + adr x8, L(ipred_z3_fill1_tbl) + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + add x10, x2, w6, uxtw #1 // left[max_base_y] + sub x8, x8, w9, uxtw + ld1r {v31.8h}, [x10] // padding + mov w7, w5 + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + br x8 + +40: + AARCH64_VALID_JUMP_TARGET +4: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // left[base] + ldr q2, [x2, w10, uxtw] + dup v4.8h, w9 // frac + dup v5.8h, w11 + ext v1.16b, v0.16b, v0.16b, #2 // left[base+1] + ext v3.16b, v2.16b, v2.16b, #2 + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + add w7, w7, w5 // xpos += dx + st1 {v18.s}[2], [x0] + st1 {v18.s}[3], [x13] + b.le 9f + sub x0, x0, x1 // ptr -= 4 * (2*stride) + sub x13, x13, x1 + add x0, x0, #4 + add x13, x13, #4 + b 4b +9: + ret + +80: + AARCH64_VALID_JUMP_TARGET +8: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h}, [x8] // left[base] + ld1 {v2.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + ldr h1, [x8, #16] + ldr h3, [x10, #16] + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + ext v1.16b, v0.16b, v1.16b, #2 // left[base+1] + ext v3.16b, v2.16b, v3.16b, #2 + umull v16.4s, v0.4h, v6.4h // left[base]*(64-frac) + umlal v16.4s, v1.4h, v4.4h // + left[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v1.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v3.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v3.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + zip2 v19.8h, v16.8h, v17.8h + add w7, w7, w5 // xpos += dx + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + b.le 9f + sub x0, x0, x1, lsl #2 // ptr -= 4 * (2*stride) + sub x13, x13, x1, lsl #2 + add x0, x0, #4 + add x13, x13, #4 + b 8b +9: + ret + +160: +320: +640: + AARCH64_VALID_JUMP_TARGET + mov w12, w4 +1: + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // ypos += dy + cmp w8, w6 // base >= max_base_y + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v6.8h, w9 // frac + dup v7.8h, w11 + ld1 {v0.8h, v1.8h, v2.8h}, [x8], #48 // left[base] + ld1 {v3.8h, v4.8h, v5.8h}, [x10], #48 + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v16.8h, w9 // 64 - frac + dup v17.8h, w11 + add w7, w7, w5 // ypos += dy +2: + ext v18.16b, v0.16b, v1.16b, #2 // left[base+1] + ext v19.16b, v1.16b, v2.16b, #2 + ext v20.16b, v3.16b, v4.16b, #2 + ext v21.16b, v4.16b, v5.16b, #2 + subs w4, w4, #16 + umull v22.4s, v0.4h, v16.4h // left[base]*(64-frac) + umlal v22.4s, v18.4h, v6.4h // + left[base+1]*frac + umull2 v23.4s, v0.8h, v16.8h + umlal2 v23.4s, v18.8h, v6.8h + umull v24.4s, v1.4h, v16.4h + umlal v24.4s, v19.4h, v6.4h + umull2 v25.4s, v1.8h, v16.8h + umlal2 v25.4s, v19.8h, v6.8h + umull v26.4s, v3.4h, v17.4h + umlal v26.4s, v20.4h, v7.4h + umull2 v27.4s, v3.8h, v17.8h + umlal2 v27.4s, v20.8h, v7.8h + umull v28.4s, v4.4h, v17.4h + umlal v28.4s, v21.4h, v7.4h + umull2 v29.4s, v4.8h, v17.8h + umlal2 v29.4s, v21.8h, v7.8h + rshrn v22.4h, v22.4s, #6 + rshrn2 v22.8h, v23.4s, #6 + rshrn v23.4h, v24.4s, #6 + rshrn2 v23.8h, v25.4s, #6 + rshrn v24.4h, v26.4s, #6 + rshrn2 v24.8h, v27.4s, #6 + rshrn v25.4h, v28.4s, #6 + rshrn2 v25.8h, v29.4s, #6 + zip1 v18.8h, v22.8h, v24.8h + zip2 v19.8h, v22.8h, v24.8h + zip1 v20.8h, v23.8h, v25.8h + zip2 v21.8h, v23.8h, v25.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + st1 {v20.s}[0], [x0], x1 + st1 {v20.s}[1], [x13], x1 + st1 {v20.s}[2], [x0], x1 + st1 {v20.s}[3], [x13], x1 + st1 {v21.s}[0], [x0], x1 + st1 {v21.s}[1], [x13], x1 + st1 {v21.s}[2], [x0], x1 + st1 {v21.s}[3], [x13], x1 + b.le 3f + mov v0.16b, v2.16b + ld1 {v1.8h, v2.8h}, [x8], #32 // left[base] + mov v3.16b, v5.16b + ld1 {v4.8h, v5.8h}, [x10], #32 + b 2b + +3: + subs w3, w3, #2 + b.le 9f + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b +9: + ret + +L(ipred_z3_fill1_tbl): + .hword L(ipred_z3_fill1_tbl) - 640b + .hword L(ipred_z3_fill1_tbl) - 320b + .hword L(ipred_z3_fill1_tbl) - 160b + .hword L(ipred_z3_fill1_tbl) - 80b + .hword L(ipred_z3_fill1_tbl) - 40b +endfunc + +function ipred_z3_fill_padding_neon, export=0 + cmp w3, #8 + adr x8, L(ipred_z3_fill_padding_tbl) + b.gt L(ipred_z3_fill_padding_wide) + // w3 = remaining width, w4 = constant height + mov w12, w4 + +1: + // Fill a WxH rectangle with padding. W can be any number; + // this fills the exact width by filling in the largest + // power of two in the remaining width, and repeating. + clz w9, w3 + sub w9, w9, #25 + ldrh w9, [x8, w9, uxtw #1] + sub x9, x8, w9, uxtw + br x9 + +2: + st1 {v31.s}[0], [x0], x1 + subs w4, w4, #4 + st1 {v31.s}[0], [x13], x1 + st1 {v31.s}[0], [x0], x1 + st1 {v31.s}[0], [x13], x1 + b.gt 2b + subs w3, w3, #2 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #4 + add x13, x13, #4 + mov w4, w12 + b 1b + +4: + st1 {v31.4h}, [x0], x1 + subs w4, w4, #4 + st1 {v31.4h}, [x13], x1 + st1 {v31.4h}, [x0], x1 + st1 {v31.4h}, [x13], x1 + b.gt 4b + subs w3, w3, #4 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #8 + add x13, x13, #8 + mov w4, w12 + b 1b + +8: +16: +32: +64: + st1 {v31.8h}, [x0], x1 + subs w4, w4, #4 + st1 {v31.8h}, [x13], x1 + st1 {v31.8h}, [x0], x1 + st1 {v31.8h}, [x13], x1 + b.gt 4b + subs w3, w3, #8 + lsr x1, x1, #1 + msub x0, x1, x12, x0 // ptr -= h * stride + msub x13, x1, x12, x13 + b.le 9f + lsl x1, x1, #1 + add x0, x0, #16 + add x13, x13, #16 + mov w4, w12 + b 1b + +9: + ret + +L(ipred_z3_fill_padding_tbl): + .hword L(ipred_z3_fill_padding_tbl) - 64b + .hword L(ipred_z3_fill_padding_tbl) - 32b + .hword L(ipred_z3_fill_padding_tbl) - 16b + .hword L(ipred_z3_fill_padding_tbl) - 8b + .hword L(ipred_z3_fill_padding_tbl) - 4b + .hword L(ipred_z3_fill_padding_tbl) - 2b + +L(ipred_z3_fill_padding_wide): + // Fill a WxH rectangle with padding, with W > 8. + lsr x1, x1, #1 + mov w12, w3 + sub x1, x1, w3, uxtw #1 +1: + ands w5, w3, #7 + b.eq 2f + // If the width isn't aligned to 8, first do one 8 pixel write + // and align the start pointer. + sub w3, w3, w5 + st1 {v31.8h}, [x0] + add x0, x0, w5, uxtw #1 +2: + // Fill the rest of the line with aligned 8 pixel writes. + subs w3, w3, #8 + st1 {v31.8h}, [x0], #16 + b.gt 2b + subs w4, w4, #1 + add x0, x0, x1 + b.le 9f + mov w3, w12 + b 1b +9: + ret +endfunc + +function ipred_z3_fill2_16bpc_neon, export=1 + cmp w4, #8 + add x10, x2, w6, uxtw // left[max_base_y] + ld1r {v31.16b}, [x10] // padding + mov w7, w5 + mov w15, #64 + add x13, x0, x1 + lsl x1, x1, #1 + b.eq 8f + +4: // h == 4 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + lsl w8, w8, #1 + lsl w10, w10, #1 + ldr q0, [x2, w8, uxtw] // top[base] + ldr q2, [x2, w10, uxtw] + dup v4.4h, w9 // frac + dup v5.4h, w11 + uzp2 v1.8h, v0.8h, v0.8h // top[base+1] + uzp1 v0.8h, v0.8h, v0.8h // top[base] + uzp2 v3.8h, v2.8h, v2.8h + uzp1 v2.8h, v2.8h, v2.8h + sub v6.4h, v1.4h, v0.4h // top[base+1]-top[base] + sub v7.4h, v3.4h, v2.4h + ushll v16.4s, v0.4h, #6 // top[base]*64 + ushll v17.4s, v2.4h, #6 + smlal v16.4s, v6.4h, v4.4h // + top[base+1]*frac + smlal v17.4s, v7.4h, v5.4h + rshrn v16.4h, v16.4s, #6 + rshrn v17.4h, v17.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + add w7, w7, w5 // xpos += dx + st1 {v18.s}[2], [x0] + st1 {v18.s}[3], [x13] + b.le 9f + sub x0, x0, x1 // ptr -= 4 * (2*stride) + sub x13, x13, x1 + add x0, x0, #4 + add x13, x13, #4 + b 4b +9: + ret + +8: // h == 8 + lsr w8, w7, #6 // base + and w9, w7, #0x3e // frac + add w7, w7, w5 // xpos += dx + cmp w8, w6 // base >= max_base_x + lsr w10, w7, #6 // base + and w11, w7, #0x3e // frac + b.ge ipred_z3_fill_padding_neon + add x8, x2, w8, uxtw #1 + add x10, x2, w10, uxtw #1 + dup v4.8h, w9 // frac + dup v5.8h, w11 + ld1 {v0.8h, v1.8h}, [x8] // top[base] + ld1 {v2.8h, v3.8h}, [x10] + sub w9, w15, w9 // 64 - frac + sub w11, w15, w11 + dup v6.8h, w9 // 64 - frac + dup v7.8h, w11 + uzp2 v20.8h, v0.8h, v1.8h // top[base+1] + uzp1 v0.8h, v0.8h, v1.8h // top[base] + uzp2 v21.8h, v2.8h, v3.8h + uzp1 v2.8h, v2.8h, v3.8h + umull v16.4s, v0.4h, v6.4h // top[base]*(64-frac) + umlal v16.4s, v20.4h, v4.4h // + top[base+1]*frac + umull2 v17.4s, v0.8h, v6.8h + umlal2 v17.4s, v20.8h, v4.8h + umull v18.4s, v2.4h, v7.4h + umlal v18.4s, v21.4h, v5.4h + umull2 v19.4s, v2.8h, v7.8h + umlal2 v19.4s, v21.8h, v5.8h + rshrn v16.4h, v16.4s, #6 + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + subs w3, w3, #2 + zip1 v18.8h, v16.8h, v17.8h + zip2 v19.8h, v16.8h, v17.8h + add w7, w7, w5 // xpos += dx + st1 {v18.s}[0], [x0], x1 + st1 {v18.s}[1], [x13], x1 + st1 {v18.s}[2], [x0], x1 + st1 {v18.s}[3], [x13], x1 + st1 {v19.s}[0], [x0], x1 + st1 {v19.s}[1], [x13], x1 + st1 {v19.s}[2], [x0], x1 + st1 {v19.s}[3], [x13], x1 + b.le 9f + sub x0, x0, x1, lsl #2 // ptr -= 4 * (2*stride) + sub x13, x13, x1, lsl #2 + add x0, x0, #4 + add x13, x13, #4 + b 8b +9: + ret +endfunc + + +// void ipred_filter_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, const int filt_idx, +// const int max_width, const int max_height, +// const int bitdepth_max); +.macro filter_fn bpc +function ipred_filter_\bpc\()bpc_neon + and w5, w5, #511 + movrel x6, X(filter_intra_taps) + lsl w5, w5, #6 + add x6, x6, w5, uxtw + ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x6], #32 + clz w9, w3 + adr x5, L(ipred_filter\bpc\()_tbl) + ld1 {v20.8b, v21.8b, v22.8b}, [x6] + sub w9, w9, #26 + ldrh w9, [x5, w9, uxtw #1] + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + sub x5, x5, w9, uxtw + sxtl v18.8h, v18.8b + sxtl v19.8h, v19.8b + add x6, x0, x1 + lsl x1, x1, #1 + sxtl v20.8h, v20.8b + sxtl v21.8h, v21.8b + sxtl v22.8h, v22.8b + dup v31.8h, w8 +.if \bpc == 10 + movi v30.8h, #0 +.endif + br x5 +40: + AARCH64_VALID_JUMP_TARGET + ldur d0, [x2, #2] // top (0-3) + sub x2, x2, #4 + mov x7, #-4 +4: + ld1 {v1.4h}, [x2], x7 // left (0-1) + topleft (2) +.if \bpc == 10 + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + srshr v2.8h, v2.8h, #4 + smax v2.8h, v2.8h, v30.8h +.else + smull v2.4s, v17.4h, v0.h[0] // p1(top[0]) * filter(1) + smlal v2.4s, v18.4h, v0.h[1] // p2(top[1]) * filter(2) + smlal v2.4s, v19.4h, v0.h[2] // p3(top[2]) * filter(3) + smlal v2.4s, v20.4h, v0.h[3] // p4(top[3]) * filter(4) + smlal v2.4s, v16.4h, v1.h[2] // p0(topleft) * filter(0) + smlal v2.4s, v21.4h, v1.h[1] // p5(left[0]) * filter(5) + smlal v2.4s, v22.4h, v1.h[0] // p6(left[1]) * filter(6) + smull2 v3.4s, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + smlal2 v3.4s, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + smlal2 v3.4s, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + smlal2 v3.4s, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + smlal2 v3.4s, v16.8h, v1.h[2] // p0(topleft) * filter(0) + smlal2 v3.4s, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + smlal2 v3.4s, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + sqrshrun v2.4h, v2.4s, #4 + sqrshrun2 v2.8h, v3.4s, #4 +.endif + smin v2.8h, v2.8h, v31.8h + subs w4, w4, #2 + st1 {v2.d}[0], [x0], x1 + ext v0.16b, v2.16b, v2.16b, #8 // move top from [4-7] to [0-3] + st1 {v2.d}[1], [x6], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ldur q0, [x2, #2] // top (0-7) + sub x2, x2, #4 + mov x7, #-4 +8: + ld1 {v1.4h}, [x2], x7 // left (0-1) + topleft (2) +.if \bpc == 10 + mul v2.8h, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + mla v2.8h, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + mla v2.8h, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + mla v2.8h, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + mla v2.8h, v16.8h, v1.h[2] // p0(topleft) * filter(0) + mla v2.8h, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + mla v2.8h, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + mul v3.8h, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + srshr v2.8h, v2.8h, #4 + smax v2.8h, v2.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + mla v3.8h, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + mla v3.8h, v16.8h, v0.h[3] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v2.h[3] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v2.h[7] // p6(left[1]) * filter(6) + srshr v3.8h, v3.8h, #4 + smax v3.8h, v3.8h, v30.8h +.else + smull v2.4s, v17.4h, v0.h[0] // p1(top[0]) * filter(1) + smlal v2.4s, v18.4h, v0.h[1] // p2(top[1]) * filter(2) + smlal v2.4s, v19.4h, v0.h[2] // p3(top[2]) * filter(3) + smlal v2.4s, v20.4h, v0.h[3] // p4(top[3]) * filter(4) + smlal v2.4s, v16.4h, v1.h[2] // p0(topleft) * filter(0) + smlal v2.4s, v21.4h, v1.h[1] // p5(left[0]) * filter(5) + smlal v2.4s, v22.4h, v1.h[0] // p6(left[1]) * filter(6) + smull2 v3.4s, v17.8h, v0.h[0] // p1(top[0]) * filter(1) + smlal2 v3.4s, v18.8h, v0.h[1] // p2(top[1]) * filter(2) + smlal2 v3.4s, v19.8h, v0.h[2] // p3(top[2]) * filter(3) + smlal2 v3.4s, v20.8h, v0.h[3] // p4(top[3]) * filter(4) + smlal2 v3.4s, v16.8h, v1.h[2] // p0(topleft) * filter(0) + smlal2 v3.4s, v21.8h, v1.h[1] // p5(left[0]) * filter(5) + smlal2 v3.4s, v22.8h, v1.h[0] // p6(left[1]) * filter(6) + smull v4.4s, v17.4h, v0.h[4] // p1(top[0]) * filter(1) + smlal v4.4s, v18.4h, v0.h[5] // p2(top[1]) * filter(2) + smlal v4.4s, v19.4h, v0.h[6] // p3(top[2]) * filter(3) + sqrshrun v2.4h, v2.4s, #4 + sqrshrun2 v2.8h, v3.4s, #4 + smin v2.8h, v2.8h, v31.8h + smlal v4.4s, v20.4h, v0.h[7] // p4(top[3]) * filter(4) + smlal v4.4s, v16.4h, v0.h[3] // p0(topleft) * filter(0) + smlal v4.4s, v21.4h, v2.h[3] // p5(left[0]) * filter(5) + smlal v4.4s, v22.4h, v2.h[7] // p6(left[1]) * filter(6) + smull2 v5.4s, v17.8h, v0.h[4] // p1(top[0]) * filter(1) + smlal2 v5.4s, v18.8h, v0.h[5] // p2(top[1]) * filter(2) + smlal2 v5.4s, v19.8h, v0.h[6] // p3(top[2]) * filter(3) + smlal2 v5.4s, v20.8h, v0.h[7] // p4(top[3]) * filter(4) + smlal2 v5.4s, v16.8h, v0.h[3] // p0(topleft) * filter(0) + smlal2 v5.4s, v21.8h, v2.h[3] // p5(left[0]) * filter(5) + smlal2 v5.4s, v22.8h, v2.h[7] // p6(left[1]) * filter(6) + sqrshrun v3.4h, v4.4s, #4 + sqrshrun2 v3.8h, v5.4s, #4 +.endif + smin v3.8h, v3.8h, v31.8h + subs w4, w4, #2 + st2 {v2.d, v3.d}[0], [x0], x1 + zip2 v0.2d, v2.2d, v3.2d + st2 {v2.d, v3.d}[1], [x6], x1 + b.gt 8b + ret +160: +320: + AARCH64_VALID_JUMP_TARGET + add x8, x2, #2 + sub x2, x2, #4 + mov x7, #-4 + sub x1, x1, w3, uxtw #1 + mov w9, w3 + +1: + ld1 {v0.4h}, [x2], x7 // left (0-1) + topleft (2) +2: + ld1 {v1.8h, v2.8h}, [x8], #32 // top(0-15) +.if \bpc == 10 + mul v3.8h, v16.8h, v0.h[2] // p0(topleft) * filter(0) + mla v3.8h, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + mla v3.8h, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + mla v3.8h, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + mla v3.8h, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + mla v3.8h, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + mla v3.8h, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + mul v4.8h, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + mla v4.8h, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + mla v4.8h, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + srshr v3.8h, v3.8h, #4 + smax v3.8h, v3.8h, v30.8h + smin v3.8h, v3.8h, v31.8h + mla v4.8h, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + mla v4.8h, v16.8h, v1.h[3] // p0(topleft) * filter(0) + mla v4.8h, v21.8h, v3.h[3] // p5(left[0]) * filter(5) + mla v4.8h, v22.8h, v3.h[7] // p6(left[1]) * filter(6) + + mul v5.8h, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + mla v5.8h, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + mla v5.8h, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + srshr v4.8h, v4.8h, #4 + smax v4.8h, v4.8h, v30.8h + smin v4.8h, v4.8h, v31.8h + mla v5.8h, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + mla v5.8h, v16.8h, v1.h[7] // p0(topleft) * filter(0) + mla v5.8h, v21.8h, v4.h[3] // p5(left[0]) * filter(5) + mla v5.8h, v22.8h, v4.h[7] // p6(left[1]) * filter(6) + + mul v6.8h, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + mla v6.8h, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + mla v6.8h, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + srshr v5.8h, v5.8h, #4 + smax v5.8h, v5.8h, v30.8h + smin v5.8h, v5.8h, v31.8h + mla v6.8h, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + mla v6.8h, v16.8h, v2.h[3] // p0(topleft) * filter(0) + mla v6.8h, v21.8h, v5.h[3] // p5(left[0]) * filter(5) + mla v6.8h, v22.8h, v5.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + srshr v6.8h, v6.8h, #4 + smax v6.8h, v6.8h, v30.8h +.else + smull v3.4s, v16.4h, v0.h[2] // p0(topleft) * filter(0) + smlal v3.4s, v21.4h, v0.h[1] // p5(left[0]) * filter(5) + smlal v3.4s, v22.4h, v0.h[0] // p6(left[1]) * filter(6) + smlal v3.4s, v17.4h, v1.h[0] // p1(top[0]) * filter(1) + smlal v3.4s, v18.4h, v1.h[1] // p2(top[1]) * filter(2) + smlal v3.4s, v19.4h, v1.h[2] // p3(top[2]) * filter(3) + smlal v3.4s, v20.4h, v1.h[3] // p4(top[3]) * filter(4) + smull2 v4.4s, v16.8h, v0.h[2] // p0(topleft) * filter(0) + smlal2 v4.4s, v21.8h, v0.h[1] // p5(left[0]) * filter(5) + smlal2 v4.4s, v22.8h, v0.h[0] // p6(left[1]) * filter(6) + smlal2 v4.4s, v17.8h, v1.h[0] // p1(top[0]) * filter(1) + smlal2 v4.4s, v18.8h, v1.h[1] // p2(top[1]) * filter(2) + smlal2 v4.4s, v19.8h, v1.h[2] // p3(top[2]) * filter(3) + smlal2 v4.4s, v20.8h, v1.h[3] // p4(top[3]) * filter(4) + + smull v5.4s, v17.4h, v1.h[4] // p1(top[0]) * filter(1) + smlal v5.4s, v18.4h, v1.h[5] // p2(top[1]) * filter(2) + smlal v5.4s, v19.4h, v1.h[6] // p3(top[2]) * filter(3) + sqrshrun v3.4h, v3.4s, #4 + sqrshrun2 v3.8h, v4.4s, #4 + smin v3.8h, v3.8h, v31.8h + smlal v5.4s, v20.4h, v1.h[7] // p4(top[3]) * filter(4) + smlal v5.4s, v16.4h, v1.h[3] // p0(topleft) * filter(0) + smlal v5.4s, v21.4h, v3.h[3] // p5(left[0]) * filter(5) + smlal v5.4s, v22.4h, v3.h[7] // p6(left[1]) * filter(6) + smull2 v6.4s, v17.8h, v1.h[4] // p1(top[0]) * filter(1) + smlal2 v6.4s, v18.8h, v1.h[5] // p2(top[1]) * filter(2) + smlal2 v6.4s, v19.8h, v1.h[6] // p3(top[2]) * filter(3) + smlal2 v6.4s, v20.8h, v1.h[7] // p4(top[3]) * filter(4) + smlal2 v6.4s, v16.8h, v1.h[3] // p0(topleft) * filter(0) + smlal2 v6.4s, v21.8h, v3.h[3] // p5(left[0]) * filter(5) + smlal2 v6.4s, v22.8h, v3.h[7] // p6(left[1]) * filter(6) + + smull v24.4s, v17.4h, v2.h[0] // p1(top[0]) * filter(1) + smlal v24.4s, v18.4h, v2.h[1] // p2(top[1]) * filter(2) + smlal v24.4s, v19.4h, v2.h[2] // p3(top[2]) * filter(3) + sqrshrun v4.4h, v5.4s, #4 + sqrshrun2 v4.8h, v6.4s, #4 + smin v4.8h, v4.8h, v31.8h + smlal v24.4s, v20.4h, v2.h[3] // p4(top[3]) * filter(4) + smlal v24.4s, v16.4h, v1.h[7] // p0(topleft) * filter(0) + smlal v24.4s, v21.4h, v4.h[3] // p5(left[0]) * filter(5) + smlal v24.4s, v22.4h, v4.h[7] // p6(left[1]) * filter(6) + smull2 v25.4s, v17.8h, v2.h[0] // p1(top[0]) * filter(1) + smlal2 v25.4s, v18.8h, v2.h[1] // p2(top[1]) * filter(2) + smlal2 v25.4s, v19.8h, v2.h[2] // p3(top[2]) * filter(3) + smlal2 v25.4s, v20.8h, v2.h[3] // p4(top[3]) * filter(4) + smlal2 v25.4s, v16.8h, v1.h[7] // p0(topleft) * filter(0) + smlal2 v25.4s, v21.8h, v4.h[3] // p5(left[0]) * filter(5) + smlal2 v25.4s, v22.8h, v4.h[7] // p6(left[1]) * filter(6) + + smull v26.4s, v17.4h, v2.h[4] // p1(top[0]) * filter(1) + smlal v26.4s, v18.4h, v2.h[5] // p2(top[1]) * filter(2) + smlal v26.4s, v19.4h, v2.h[6] // p3(top[2]) * filter(3) + sqrshrun v5.4h, v24.4s, #4 + sqrshrun2 v5.8h, v25.4s, #4 + smin v5.8h, v5.8h, v31.8h + smlal v26.4s, v20.4h, v2.h[7] // p4(top[3]) * filter(4) + smlal v26.4s, v16.4h, v2.h[3] // p0(topleft) * filter(0) + smlal v26.4s, v21.4h, v5.h[3] // p5(left[0]) * filter(5) + smlal v26.4s, v22.4h, v5.h[7] // p6(left[1]) * filter(6) + smull2 v27.4s, v17.8h, v2.h[4] // p1(top[0]) * filter(1) + smlal2 v27.4s, v18.8h, v2.h[5] // p2(top[1]) * filter(2) + smlal2 v27.4s, v19.8h, v2.h[6] // p3(top[2]) * filter(3) + smlal2 v27.4s, v20.8h, v2.h[7] // p4(top[3]) * filter(4) + smlal2 v27.4s, v16.8h, v2.h[3] // p0(topleft) * filter(0) + smlal2 v27.4s, v21.8h, v5.h[3] // p5(left[0]) * filter(5) + smlal2 v27.4s, v22.8h, v5.h[7] // p6(left[1]) * filter(6) + + subs w3, w3, #16 + sqrshrun v6.4h, v26.4s, #4 + sqrshrun2 v6.8h, v27.4s, #4 +.endif + smin v6.8h, v6.8h, v31.8h + + ins v0.h[2], v2.h[7] + st4 {v3.d, v4.d, v5.d, v6.d}[0], [x0], #32 + ins v0.h[0], v6.h[7] + st4 {v3.d, v4.d, v5.d, v6.d}[1], [x6], #32 + ins v0.h[1], v6.h[3] + b.gt 2b + subs w4, w4, #2 + b.le 9f + sub x8, x6, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b 1b +9: + ret + +L(ipred_filter\bpc\()_tbl): + .hword L(ipred_filter\bpc\()_tbl) - 320b + .hword L(ipred_filter\bpc\()_tbl) - 160b + .hword L(ipred_filter\bpc\()_tbl) - 80b + .hword L(ipred_filter\bpc\()_tbl) - 40b +endfunc +.endm + +filter_fn 10 +filter_fn 12 + +function ipred_filter_16bpc_neon, export=1 + ldr w8, [sp] + cmp w8, 0x3ff + b.le ipred_filter_10bpc_neon + b ipred_filter_12bpc_neon +endfunc + +// void pal_pred_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint16_t *const pal, const uint8_t *idx, +// const int w, const int h); +function pal_pred_16bpc_neon, export=1 + ld1 {v30.8h}, [x2] + clz w9, w4 + adr x6, L(pal_pred_tbl) + sub w9, w9, #25 + ldrh w9, [x6, w9, uxtw #1] + movi v31.8h, #1, lsl #8 + sub x6, x6, w9, uxtw + br x6 +40: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +4: + ld1 {v1.16b}, [x3], #16 + subs w5, w5, #4 + // Restructure v1 from a, b, c, ... into 2*a, 2*a+1, 2*b, 2*b+1, 2*c, 2*c+1, ... + add v1.16b, v1.16b, v1.16b + zip1 v0.16b, v1.16b, v1.16b + zip2 v1.16b, v1.16b, v1.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + st1 {v0.d}[0], [x0], x1 + tbl v1.16b, {v30.16b}, v1.16b + st1 {v0.d}[1], [x2], x1 + st1 {v1.d}[0], [x0], x1 + st1 {v1.d}[1], [x2], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +8: + ld1 {v2.16b, v3.16b}, [x3], #32 + subs w5, w5, #4 + add v2.16b, v2.16b, v2.16b + add v3.16b, v3.16b, v3.16b + zip1 v0.16b, v2.16b, v2.16b + zip2 v1.16b, v2.16b, v2.16b + zip1 v2.16b, v3.16b, v3.16b + zip2 v3.16b, v3.16b, v3.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + tbl v1.16b, {v30.16b}, v1.16b + st1 {v0.8h}, [x0], x1 + tbl v2.16b, {v30.16b}, v2.16b + st1 {v1.8h}, [x2], x1 + tbl v3.16b, {v30.16b}, v3.16b + st1 {v2.8h}, [x0], x1 + st1 {v3.8h}, [x2], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +16: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #4 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + st1 {v2.8h, v3.8h}, [x2], x1 + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h}, [x0], x1 + st1 {v6.8h, v7.8h}, [x2], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + add x2, x0, x1 + lsl x1, x1, #1 +32: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #2 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], x1 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + add x2, x0, #64 +64: + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x3], #64 + subs w5, w5, #1 + add v4.16b, v4.16b, v4.16b + add v5.16b, v5.16b, v5.16b + add v6.16b, v6.16b, v6.16b + add v7.16b, v7.16b, v7.16b + zip1 v0.16b, v4.16b, v4.16b + zip2 v1.16b, v4.16b, v4.16b + zip1 v2.16b, v5.16b, v5.16b + zip2 v3.16b, v5.16b, v5.16b + zip1 v4.16b, v6.16b, v6.16b + zip2 v5.16b, v6.16b, v6.16b + zip1 v6.16b, v7.16b, v7.16b + zip2 v7.16b, v7.16b, v7.16b + add v0.8h, v0.8h, v31.8h + add v1.8h, v1.8h, v31.8h + add v2.8h, v2.8h, v31.8h + add v3.8h, v3.8h, v31.8h + add v4.8h, v4.8h, v31.8h + tbl v0.16b, {v30.16b}, v0.16b + add v5.8h, v5.8h, v31.8h + tbl v1.16b, {v30.16b}, v1.16b + add v6.8h, v6.8h, v31.8h + tbl v2.16b, {v30.16b}, v2.16b + add v7.8h, v7.8h, v31.8h + tbl v3.16b, {v30.16b}, v3.16b + tbl v4.16b, {v30.16b}, v4.16b + tbl v5.16b, {v30.16b}, v5.16b + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + tbl v6.16b, {v30.16b}, v6.16b + tbl v7.16b, {v30.16b}, v7.16b + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], x1 + b.gt 64b + ret + +L(pal_pred_tbl): + .hword L(pal_pred_tbl) - 640b + .hword L(pal_pred_tbl) - 320b + .hword L(pal_pred_tbl) - 160b + .hword L(pal_pred_tbl) - 80b + .hword L(pal_pred_tbl) - 40b +endfunc + +// void ipred_cfl_128_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_128_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + clz w9, w3 + adr x7, L(ipred_cfl_128_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + urshr v0.8h, v31.8h, #1 + dup v1.8h, w6 // alpha + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 +L(ipred_cfl_splat_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x5], #32 + subs w4, w4, #4 + smull v2.4s, v4.4h, v1.4h // diff = ac * alpha + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v16.4s, v2.4s, #0 // sign + cmlt v17.4s, v3.4s, #0 + cmlt v18.4s, v4.4s, #0 + cmlt v19.4s, v5.4s, #0 + add v2.4s, v2.4s, v16.4s // diff + sign + add v3.4s, v3.4s, v17.4s + add v4.4s, v4.4s, v18.4s + add v5.4s, v5.4s, v19.4s + rshrn v2.4h, v2.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + st1 {v2.d}[0], [x0], x1 + st1 {v2.d}[1], [x6], x1 + st1 {v3.d}[0], [x0], x1 + st1 {v3.d}[1], [x6], x1 + b.gt L(ipred_cfl_splat_w4) + ret +L(ipred_cfl_splat_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x5], #32 + subs w4, w4, #2 + smull v2.4s, v4.4h, v1.4h // diff = ac * alpha + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v16.4s, v2.4s, #0 // sign + cmlt v17.4s, v3.4s, #0 + cmlt v18.4s, v4.4s, #0 + cmlt v19.4s, v5.4s, #0 + add v2.4s, v2.4s, v16.4s // diff + sign + add v3.4s, v3.4s, v17.4s + add v4.4s, v4.4s, v18.4s + add v5.4s, v5.4s, v19.4s + rshrn v2.4h, v2.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + add v2.8h, v2.8h, v0.8h // dc + apply_sign() + add v3.8h, v3.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + st1 {v2.8h}, [x0], x1 + st1 {v3.8h}, [x6], x1 + b.gt L(ipred_cfl_splat_w8) + ret +L(ipred_cfl_splat_w16): + AARCH64_VALID_JUMP_TARGET + add x7, x5, w3, uxtw #1 + sub x1, x1, w3, uxtw #1 + mov w9, w3 +1: + ld1 {v2.8h, v3.8h}, [x5], #32 + ld1 {v4.8h, v5.8h}, [x7], #32 + subs w3, w3, #16 + smull v16.4s, v2.4h, v1.4h // diff = ac * alpha + smull2 v17.4s, v2.8h, v1.8h + smull v18.4s, v3.4h, v1.4h + smull2 v19.4s, v3.8h, v1.8h + smull v2.4s, v4.4h, v1.4h + smull2 v3.4s, v4.8h, v1.8h + smull v4.4s, v5.4h, v1.4h + smull2 v5.4s, v5.8h, v1.8h + cmlt v20.4s, v16.4s, #0 // sign + cmlt v21.4s, v17.4s, #0 + cmlt v22.4s, v18.4s, #0 + cmlt v23.4s, v19.4s, #0 + cmlt v24.4s, v2.4s, #0 + cmlt v25.4s, v3.4s, #0 + cmlt v26.4s, v4.4s, #0 + cmlt v27.4s, v5.4s, #0 + add v16.4s, v16.4s, v20.4s // diff + sign + add v17.4s, v17.4s, v21.4s + add v18.4s, v18.4s, v22.4s + add v19.4s, v19.4s, v23.4s + add v2.4s, v2.4s, v24.4s + add v3.4s, v3.4s, v25.4s + add v4.4s, v4.4s, v26.4s + add v5.4s, v5.4s, v27.4s + rshrn v16.4h, v16.4s, #6 // (diff + sign + 32) >> 6 = apply_sign() + rshrn2 v16.8h, v17.4s, #6 + rshrn v17.4h, v18.4s, #6 + rshrn2 v17.8h, v19.4s, #6 + rshrn v6.4h, v2.4s, #6 + rshrn2 v6.8h, v3.4s, #6 + rshrn v7.4h, v4.4s, #6 + rshrn2 v7.8h, v5.4s, #6 + add v2.8h, v16.8h, v0.8h // dc + apply_sign() + add v3.8h, v17.8h, v0.8h + add v4.8h, v6.8h, v0.8h + add v5.8h, v7.8h, v0.8h + smax v2.8h, v2.8h, v30.8h + smax v3.8h, v3.8h, v30.8h + smax v4.8h, v4.8h, v30.8h + smax v5.8h, v5.8h, v30.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + smin v4.8h, v4.8h, v31.8h + smin v5.8h, v5.8h, v31.8h + st1 {v2.8h, v3.8h}, [x0], #32 + st1 {v4.8h, v5.8h}, [x6], #32 + b.gt 1b + subs w4, w4, #2 + add x5, x5, w9, uxtw #1 + add x7, x7, w9, uxtw #1 + add x0, x0, x1 + add x6, x6, x1 + mov w3, w9 + b.gt 1b + ret + +L(ipred_cfl_128_tbl): +L(ipred_cfl_splat_tbl): + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w16) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w8) + .hword L(ipred_cfl_128_tbl) - L(ipred_cfl_splat_w4) +endfunc + +// void ipred_cfl_top_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_top_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + clz w9, w3 + adr x7, L(ipred_cfl_top_tbl) + sub w9, w9, #26 + ldrh w9, [x7, w9, uxtw #1] + dup v1.8h, w6 // alpha + add x2, x2, #2 + sub x7, x7, w9, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + addp v0.8h, v2.8h, v3.8h + addv h0, v0.8h + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + uaddlv s0, v0.8h + rshrn v0.4h, v0.4s, #5 + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_top_tbl): + .hword L(ipred_cfl_top_tbl) - 32b + .hword L(ipred_cfl_top_tbl) - 16b + .hword L(ipred_cfl_top_tbl) - 8b + .hword L(ipred_cfl_top_tbl) - 4b +endfunc + +// void ipred_cfl_left_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_left_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + sub x2, x2, w4, uxtw #1 + clz w9, w3 + clz w8, w4 + adr x10, L(ipred_cfl_splat_tbl) + adr x7, L(ipred_cfl_left_tbl) + sub w9, w9, #26 + sub w8, w8, #26 + ldrh w9, [x10, w9, uxtw #1] + ldrh w8, [x7, w8, uxtw #1] + dup v1.8h, w6 // alpha + sub x9, x10, w9, uxtw + sub x7, x7, w8, uxtw + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 + +L(ipred_cfl_left_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2] + addv h0, v0.4h + urshr v0.4h, v0.4h, #2 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2] + addv h0, v0.8h + urshr v0.4h, v0.4h, #3 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + addp v0.8h, v2.8h, v3.8h + addv h0, v0.8h + urshr v0.4h, v0.4h, #4 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + uaddlv s0, v0.8h + rshrn v0.4h, v0.4s, #5 + dup v0.8h, v0.h[0] + br x9 + +L(ipred_cfl_left_tbl): + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h32) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h16) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h8) + .hword L(ipred_cfl_left_tbl) - L(ipred_cfl_left_h4) +endfunc + +// void ipred_cfl_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *const topleft, +// const int width, const int height, +// const int16_t *ac, const int alpha, +// const int bitdepth_max); +function ipred_cfl_16bpc_neon, export=1 + dup v31.8h, w7 // bitdepth_max + sub x2, x2, w4, uxtw #1 + add w8, w3, w4 // width + height + dup v1.8h, w6 // alpha + clz w9, w3 + clz w6, w4 + dup v16.4s, w8 // width + height + adr x7, L(ipred_cfl_tbl) + rbit w8, w8 // rbit(width + height) + sub w9, w9, #22 // 26 leading bits, minus table offset 4 + sub w6, w6, #26 + clz w8, w8 // ctz(width + height) + ldrh w9, [x7, w9, uxtw #1] + ldrh w6, [x7, w6, uxtw #1] + neg w8, w8 // -ctz(width + height) + sub x9, x7, w9, uxtw + sub x7, x7, w6, uxtw + ushr v16.4s, v16.4s, #1 // (width + height) >> 1 + dup v17.4s, w8 // -ctz(width + height) + add x6, x0, x1 + lsl x1, x1, #1 + movi v30.8h, #0 + br x7 + +L(ipred_cfl_h4): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], #8 + uaddlv s0, v0.4h + add x2, x2, #2 + br x9 +L(ipred_cfl_w4): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.4h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s2, v2.4h + cmp w4, #4 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #16 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w4) + +L(ipred_cfl_h8): + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8h}, [x2], #16 + uaddlv s0, v0.8h + add x2, x2, #2 + br x9 +L(ipred_cfl_w8): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h}, [x2] + add v0.2s, v0.2s, v16.2s + uaddlv s2, v2.8h + cmp w4, #8 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/16/32 + cmp w4, #32 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w8) + +L(ipred_cfl_h16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2], #32 + addp v0.8h, v2.8h, v3.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x9 +L(ipred_cfl_w16): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h}, [x2] + add v0.2s, v0.2s, v16.2s + addp v2.8h, v2.8h, v3.8h + uaddlv s2, v2.8h + cmp w4, #16 + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 4/8/32 + tst w4, #(32+16+8) // 16 added to make a consecutive bitmask + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_h32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2], #64 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v0.8h, v2.8h, v4.8h + add x2, x2, #2 + uaddlv s0, v0.8h + br x9 +L(ipred_cfl_w32): + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8h, v3.8h, v4.8h, v5.8h}, [x2] + add v0.4s, v0.4s, v16.4s + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v2.8h, v2.8h, v4.8h + cmp w4, #32 + uaddlv s2, v2.8h + add v0.2s, v0.2s, v2.2s + ushl v0.2s, v0.2s, v17.2s + b.eq 1f + // h = 8/16 + cmp w4, #8 + mov w16, #0x6667 + mov w17, #0xAAAB + csel w16, w16, w17, eq + dup v16.2s, w16 + mul v0.2s, v0.2s, v16.2s + ushr v0.2s, v0.2s, #17 +1: + dup v0.8h, v0.h[0] + b L(ipred_cfl_splat_w16) + +L(ipred_cfl_tbl): + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_h4) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w32) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w16) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w8) + .hword L(ipred_cfl_tbl) - L(ipred_cfl_w4) +endfunc + +// void cfl_ac_420_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_420_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_420_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_420_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v2.8h + addp v1.8h, v1.8h, v3.8h + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + subs w8, w8, #2 + st1 {v0.8h}, [x0], #16 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + b.gt 1b + trn2 v1.2d, v0.2d, v0.2d + trn2 v0.2d, v0.2d, v0.2d +L(ipred_cfl_ac_420_w4_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 2b +3: +L(ipred_cfl_ac_420_w4_calc_subtract_dc): + // Aggregate the sums + add v24.4s, v24.4s, v25.4s + add v26.4s, v26.4s, v27.4s + add v0.4s, v24.4s, v26.4s + addv s0, v0.4s // sum + sub x0, x0, w6, uxtw #3 + urshl v4.2s, v0.2s, v31.2s // (sum + (1 << (log2sz - 1))) >>= log2sz + dup v4.8h, v4.h[0] +6: // Subtract dc from ac + ld1 {v0.8h, v1.8h}, [x0] + subs w6, w6, #4 + sub v0.8h, v0.8h, v4.8h + sub v1.8h, v1.8h, v4.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 6b + ret + +L(ipred_cfl_ac_420_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_420_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v4.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + mov v0.16b, v1.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_420_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v2.8h + addp v1.8h, v1.8h, v3.8h + add v0.8h, v0.8h, v1.8h + shl v0.8h, v0.8h, #1 + dup v1.4h, v0.h[3] + dup v3.4h, v0.h[7] + trn2 v2.2d, v0.2d, v0.2d + subs w8, w8, #2 + st1 {v0.4h, v1.4h, v2.4h, v3.4h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw v25.4s, v25.4s, v1.4h + uaddw v26.4s, v26.4s, v2.4h + uaddw v27.4s, v27.4s, v3.4h + b.gt 1b + trn1 v0.2d, v2.2d, v3.2d + trn1 v1.2d, v2.2d, v3.2d + +L(ipred_cfl_ac_420_w8_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 2b +3: + + // Double the height and reuse the w4 summing/subtracting + lsl w6, w6, #1 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_420_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_420_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x1], x2 + add v0.8h, v0.8h, v4.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x10], x2 + add v2.8h, v2.8h, v6.8h + addp v16.8h, v16.8h, v17.8h + addp v18.8h, v18.8h, v19.8h + addp v20.8h, v20.8h, v21.8h + addp v22.8h, v22.8h, v23.8h + add v16.8h, v16.8h, v20.8h + add v18.8h, v18.8h, v22.8h + shl v0.8h, v0.8h, #1 + shl v1.8h, v2.8h, #1 + shl v2.8h, v16.8h, #1 + shl v3.8h, v18.8h, #1 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr q2, [x1, #32] + ld1 {v0.8h, v1.8h}, [x1], x2 + ldr q5, [x10, #32] + ld1 {v3.8h, v4.8h}, [x10], x2 + addp v2.8h, v2.8h, v2.8h + addp v0.8h, v0.8h, v1.8h + addp v5.8h, v5.8h, v5.8h + addp v3.8h, v3.8h, v4.8h + ldr q18, [x1, #32] + add v2.4h, v2.4h, v5.4h + ld1 {v16.8h, v17.8h}, [x1], x2 + add v0.8h, v0.8h, v3.8h + ldr q21, [x10, #32] + ld1 {v19.8h, v20.8h}, [x10], x2 + addp v18.8h, v18.8h, v18.8h + addp v16.8h, v16.8h, v17.8h + addp v21.8h, v21.8h, v21.8h + addp v19.8h, v19.8h, v20.8h + add v18.4h, v18.4h, v21.4h + add v16.8h, v16.8h, v19.8h + shl v1.4h, v2.4h, #1 + shl v0.8h, v0.8h, #1 + shl v3.4h, v18.4h, #1 + shl v2.8h, v16.8h, #1 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v2.8h + add v4.8h, v4.8h, v6.8h + shl v0.8h, v0.8h, #1 + shl v2.8h, v4.8h, #1 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_420_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + ld1 {v4.8h}, [x1], x2 + ld1 {v6.8h}, [x10], x2 + addp v0.8h, v0.8h, v4.8h + addp v2.8h, v2.8h, v6.8h + add v0.8h, v0.8h, v2.8h + shl v0.8h, v0.8h, #1 + dup v1.8h, v0.h[3] + dup v3.8h, v0.h[7] + trn2 v2.2d, v0.2d, v3.2d + trn1 v0.2d, v0.2d, v1.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + +L(ipred_cfl_ac_420_w16_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 2b +3: + + // Quadruple the height and reuse the w4 summing/subtracting + lsl w6, w6, #2 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_420_tbl): + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w16) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w8) + .hword L(ipred_cfl_ac_420_tbl) - L(ipred_cfl_ac_420_w4) + .hword 0 + +L(ipred_cfl_ac_420_w16_tbl): + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad0) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad1) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad2) + .hword L(ipred_cfl_ac_420_w16_tbl) - L(ipred_cfl_ac_420_w16_wpad3) +endfunc + +// void cfl_ac_422_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_422_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_422_tbl) + sub w8, w8, #27 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_422_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_422_w8): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_422_w8_wpad) +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + ld1 {v4.8h, v5.8h}, [x1], x2 + addp v0.8h, v0.8h, v1.8h + ld1 {v6.8h, v7.8h}, [x10], x2 + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + shl v2.8h, v4.8h, #2 + shl v3.8h, v6.8h, #2 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w8_wpad): +1: // Copy and subsample input, padding 4 + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + ld1 {v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v4.4h, v0.h[3] + dup v5.8h, v0.h[7] + dup v6.4h, v2.h[3] + dup v7.8h, v2.h[7] + trn2 v1.2d, v0.2d, v5.2d + trn1 v0.2d, v0.2d, v4.2d + trn2 v3.2d, v2.2d, v7.2d + trn1 v2.2d, v2.2d, v6.2d + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_422_w16): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_422_w16_tbl) + ldrh w3, [x7, w3, uxtw #1] + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_422_w16_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + shl v0.8h, v0.8h, #2 + shl v1.8h, v2.8h, #2 + shl v2.8h, v4.8h, #2 + shl v3.8h, v6.8h, #2 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad1): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 4 + ldr q2, [x1, #32] + ld1 {v0.8h, v1.8h}, [x1], x2 + ldr q6, [x10, #32] + ld1 {v4.8h, v5.8h}, [x10], x2 + addp v2.8h, v2.8h, v2.8h + addp v0.8h, v0.8h, v1.8h + addp v6.8h, v6.8h, v6.8h + addp v4.8h, v4.8h, v5.8h + shl v1.4h, v2.4h, #2 + shl v0.8h, v0.8h, #2 + shl v3.4h, v6.4h, #2 + shl v2.8h, v4.8h, #2 + dup v4.4h, v1.h[3] + dup v5.4h, v3.h[3] + trn1 v1.2d, v1.2d, v4.2d + trn1 v3.2d, v3.2d, v5.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 8 + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + shl v0.8h, v0.8h, #2 + shl v2.8h, v2.8h, #2 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_w16_wpad3): + AARCH64_VALID_JUMP_TARGET +1: // Copy and subsample input, padding 12 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + addp v0.8h, v0.8h, v0.8h + addp v2.8h, v2.8h, v2.8h + shl v0.4h, v0.4h, #2 + shl v2.4h, v2.4h, #2 + dup v1.8h, v0.h[3] + dup v3.8h, v2.h[3] + trn1 v0.2d, v0.2d, v1.2d + trn1 v2.2d, v2.2d, v3.2d + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_422_tbl): + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w16) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w8) + .hword L(ipred_cfl_ac_422_tbl) - L(ipred_cfl_ac_422_w4) + .hword 0 + +L(ipred_cfl_ac_422_w16_tbl): + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad0) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad1) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad2) + .hword L(ipred_cfl_ac_422_w16_tbl) - L(ipred_cfl_ac_422_w16_wpad3) +endfunc + +// void cfl_ac_444_16bpc_neon(int16_t *const ac, const pixel *const ypx, +// const ptrdiff_t stride, const int w_pad, +// const int h_pad, const int cw, const int ch); +function ipred_cfl_ac_444_16bpc_neon, export=1 + clz w8, w5 + lsl w4, w4, #2 + adr x7, L(ipred_cfl_ac_444_tbl) + sub w8, w8, #26 + ldrh w8, [x7, w8, uxtw #1] + movi v24.4s, #0 + movi v25.4s, #0 + movi v26.4s, #0 + movi v27.4s, #0 + sub x7, x7, w8, uxtw + sub w8, w6, w4 // height - h_pad + rbit w9, w5 // rbit(width) + rbit w10, w6 // rbit(height) + clz w9, w9 // ctz(width) + clz w10, w10 // ctz(height) + add w9, w9, w10 // log2sz + add x10, x1, x2 + dup v31.4s, w9 + lsl x2, x2, #1 + neg v31.4s, v31.4s // -log2sz + br x7 + +L(ipred_cfl_ac_444_w4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.4h}, [x1], x2 + ld1 {v0.d}[1], [x10], x2 + ld1 {v1.4h}, [x1], x2 + ld1 {v1.d}[1], [x10], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + b.gt 1b + trn2 v0.2d, v1.2d, v1.2d + trn2 v1.2d, v1.2d, v1.2d + b L(ipred_cfl_ac_420_w4_hpad) + +L(ipred_cfl_ac_444_w8): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x10], x2 + ld1 {v2.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + ld1 {v3.8h}, [x10], x2 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #4 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v3.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w8_hpad) + +L(ipred_cfl_ac_444_w16): + AARCH64_VALID_JUMP_TARGET + cbnz w3, L(ipred_cfl_ac_444_w16_wpad) +1: // Copy and expand input, without padding + ld1 {v0.8h, v1.8h}, [x1], x2 + ld1 {v2.8h, v3.8h}, [x10], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w16_wpad): +1: // Copy and expand input, padding 8 + ld1 {v0.8h}, [x1], x2 + ld1 {v2.8h}, [x10], x2 + shl v0.8h, v0.8h, #3 + shl v2.8h, v2.8h, #3 + dup v1.8h, v0.h[7] + dup v3.8h, v2.h[7] + subs w8, w8, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + mov v0.16b, v2.16b + mov v1.16b, v3.16b + b L(ipred_cfl_ac_420_w16_hpad) + +L(ipred_cfl_ac_444_w32): + AARCH64_VALID_JUMP_TARGET + adr x7, L(ipred_cfl_ac_444_w32_tbl) + ldrh w3, [x7, w3, uxtw] // (w3>>1) << 1 + lsr x2, x2, #1 // Restore the stride to one line increments + sub x7, x7, w3, uxtw + br x7 + +L(ipred_cfl_ac_444_w32_wpad0): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, without padding + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + shl v2.8h, v2.8h, #3 + shl v3.8h, v3.8h, #3 + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad2): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 8 + ld1 {v0.8h, v1.8h, v2.8h}, [x1], x2 + shl v2.8h, v2.8h, #3 + shl v0.8h, v0.8h, #3 + shl v1.8h, v1.8h, #3 + dup v3.8h, v2.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad4): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 16 + ld1 {v0.8h, v1.8h}, [x1], x2 + shl v1.8h, v1.8h, #3 + shl v0.8h, v0.8h, #3 + dup v2.8h, v1.h[7] + dup v3.8h, v1.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + b L(ipred_cfl_ac_444_w32_hpad) + +L(ipred_cfl_ac_444_w32_wpad6): + AARCH64_VALID_JUMP_TARGET +1: // Copy and expand input, padding 24 + ld1 {v0.8h}, [x1], x2 + shl v0.8h, v0.8h, #3 + dup v1.8h, v0.h[7] + dup v2.8h, v0.h[7] + dup v3.8h, v0.h[7] + subs w8, w8, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 1b + +L(ipred_cfl_ac_444_w32_hpad): + cbz w4, 3f +2: // Vertical padding (h_pad > 0) + subs w4, w4, #2 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + uaddw v24.4s, v24.4s, v0.4h + uaddw2 v25.4s, v25.4s, v0.8h + uaddw v26.4s, v26.4s, v1.4h + uaddw2 v27.4s, v27.4s, v1.8h + uaddw v24.4s, v24.4s, v2.4h + uaddw2 v25.4s, v25.4s, v2.8h + uaddw v26.4s, v26.4s, v3.4h + uaddw2 v27.4s, v27.4s, v3.8h + b.gt 2b +3: + + // Multiply the height by eight and reuse the w4 subtracting + lsl w6, w6, #3 + b L(ipred_cfl_ac_420_w4_calc_subtract_dc) + +L(ipred_cfl_ac_444_tbl): + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w32) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w16) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w8) + .hword L(ipred_cfl_ac_444_tbl) - L(ipred_cfl_ac_444_w4) + +L(ipred_cfl_ac_444_w32_tbl): + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad0) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad2) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad4) + .hword L(ipred_cfl_ac_444_w32_tbl) - L(ipred_cfl_ac_444_w32_wpad6) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/itx.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/itx.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3270 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "src/arm/asm.S" +#include "util.S" + +// The exported functions in this file have got the following signature: +// void itxfm_add(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob); + +// Most of the functions use the following register layout: +// x0-x3 external parameters +// x4 function pointer to first transform +// x5 function pointer to second transform +// x6 output parameter for helper function +// x7 input parameter for helper function +// x8 input stride for helper function +// x9-x12 scratch variables for helper functions +// x13 pointer to list of eob thresholds +// x14 return pointer for helper function +// x15 return pointer for main function + +// The SIMD registers most often use the following layout: +// v0-v1 multiplication coefficients +// v2-v7 scratch registers +// v8-v15 unused +// v16-v31 inputs/outputs of transforms + +// Potential further optimizations, that are left unimplemented for now: +// - Trying to keep multiplication coefficients in registers across multiple +// transform functions. (The register layout is designed to potentially +// allow this.) +// - Use a simplified version of the transforms themselves for cases where +// we know a significant number of inputs are zero. E.g. if the eob value +// indicates only a quarter of input values are set, for idct16 and up, +// a significant amount of calculation can be skipped, at the cost of more +// code duplication and special casing. + +const idct_coeffs, align=4 + // idct4 + .short 2896, 2896*8, 1567, 3784 + // idct8 + .short 799, 4017, 3406, 2276 + // idct16 + .short 401, 4076, 3166, 2598 + .short 1931, 3612, 3920, 1189 + // idct32 + .short 201, 4091, 3035, 2751 + .short 1751, 3703, 3857, 1380 + .short 995, 3973, 3513, 2106 + .short 2440, 3290, 4052, 601 +endconst + +const idct64_coeffs, align=4 + .short 101*8, 4095*8, 2967*8, -2824*8 + .short 1660*8, 3745*8, 3822*8, -1474*8 + .short 4076, 401, 4017, 799 + .short 0, 0, 0, 0 + + .short 4036*8, -700*8, 2359*8, 3349*8 + .short 3461*8, -2191*8, 897*8, 3996*8 + .short -3166, -2598, -799, -4017 + .short 0, 0, 0, 0 + + .short 501*8, 4065*8, 3229*8, -2520*8 + .short 2019*8, 3564*8, 3948*8, -1092*8 + .short 3612, 1931, 2276, 3406 + .short 0, 0, 0, 0 + + .short 4085*8, -301*8, 2675*8, 3102*8 + .short 3659*8, -1842*8, 1285*8, 3889*8 + .short -3920, -1189, -3406, -2276 + .short 0, 0, 0, 0 +endconst + +const iadst4_coeffs, align=4 + // .h[4-5] can be interpreted as .s[2] + .short 1321, 3803, 2482, 3344, 3344, 0 +endconst + +const iadst8_coeffs, align=4 + .short 4076, 401, 3612, 1931 + .short 2598, 3166, 1189, 3920 + // idct_coeffs + .short 2896, 0, 1567, 3784, 0, 0, 0, 0 +endconst + +const iadst16_coeffs, align=4 + .short 4091, 201, 3973, 995 + .short 3703, 1751, 3290, 2440 + .short 2751, 3035, 2106, 3513 + .short 1380, 3857, 601, 4052 +endconst + +.macro smull_smlal d0, d1, s0, s1, c0, c1, sz + smull \d0\().4s, \s0\().4h, \c0 + smlal \d0\().4s, \s1\().4h, \c1 +.ifc \sz, .8h + smull2 \d1\().4s, \s0\().8h, \c0 + smlal2 \d1\().4s, \s1\().8h, \c1 +.endif +.endm + +.macro smull_smlsl d0, d1, s0, s1, c0, c1, sz + smull \d0\().4s, \s0\().4h, \c0 + smlsl \d0\().4s, \s1\().4h, \c1 +.ifc \sz, .8h + smull2 \d1\().4s, \s0\().8h, \c0 + smlsl2 \d1\().4s, \s1\().8h, \c1 +.endif +.endm + +.macro sqrshrn_sz d0, s0, s1, shift, sz + sqrshrn \d0\().4h, \s0\().4s, \shift +.ifc \sz, .8h + sqrshrn2 \d0\().8h, \s1\().4s, \shift +.endif +.endm + +.macro scale_input sz, c, r0, r1, r2 r3, r4, r5, r6, r7 + sqrdmulh \r0\sz, \r0\sz, \c + sqrdmulh \r1\sz, \r1\sz, \c + sqrdmulh \r2\sz, \r2\sz, \c + sqrdmulh \r3\sz, \r3\sz, \c +.ifnb \r4 + sqrdmulh \r4\sz, \r4\sz, \c + sqrdmulh \r5\sz, \r5\sz, \c + sqrdmulh \r6\sz, \r6\sz, \c + sqrdmulh \r7\sz, \r7\sz, \c +.endif +.endm + +.macro load_add_store load, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src, shiftbits=4 +.ifnb \load + ld1 {\load}, [\src], x1 +.endif +.ifnb \shift + srshr \shift, \shift, #\shiftbits +.endif +.ifnb \addsrc + uaddw \adddst, \adddst, \addsrc +.endif +.ifnb \narrowsrc + sqxtun \narrowdst, \narrowsrc +.endif +.ifnb \store + st1 {\store}, [\dst], x1 +.endif +.endm +.macro load_add_store_8x16 dst, src + mov \src, \dst + load_add_store v2.8b, v16.8h, , , , , , \dst, \src + load_add_store v3.8b, v17.8h, , , , , , \dst, \src + load_add_store v4.8b, v18.8h, v2.8b, v16.8h, , , , \dst, \src + load_add_store v5.8b, v19.8h, v3.8b, v17.8h, v16.8h, v2.8b, , \dst, \src + load_add_store v6.8b, v20.8h, v4.8b, v18.8h, v17.8h, v3.8b, v2.8b, \dst, \src + load_add_store v7.8b, v21.8h, v5.8b, v19.8h, v18.8h, v4.8b, v3.8b, \dst, \src + load_add_store v2.8b, v22.8h, v6.8b, v20.8h, v19.8h, v5.8b, v4.8b, \dst, \src + load_add_store v3.8b, v23.8h, v7.8b, v21.8h, v20.8h, v6.8b, v5.8b, \dst, \src + load_add_store v4.8b, v24.8h, v2.8b, v22.8h, v21.8h, v7.8b, v6.8b, \dst, \src + load_add_store v5.8b, v25.8h, v3.8b, v23.8h, v22.8h, v2.8b, v7.8b, \dst, \src + load_add_store v6.8b, v26.8h, v4.8b, v24.8h, v23.8h, v3.8b, v2.8b, \dst, \src + load_add_store v7.8b, v27.8h, v5.8b, v25.8h, v24.8h, v4.8b, v3.8b, \dst, \src + load_add_store v2.8b, v28.8h, v6.8b, v26.8h, v25.8h, v5.8b, v4.8b, \dst, \src + load_add_store v3.8b, v29.8h, v7.8b, v27.8h, v26.8h, v6.8b, v5.8b, \dst, \src + load_add_store v4.8b, v30.8h, v2.8b, v28.8h, v27.8h, v7.8b, v6.8b, \dst, \src + load_add_store v5.8b, v31.8h, v3.8b, v29.8h, v28.8h, v2.8b, v7.8b, \dst, \src + load_add_store , , v4.8b, v30.8h, v29.8h, v3.8b, v2.8b, \dst, \src + load_add_store , , v5.8b, v31.8h, v30.8h, v4.8b, v3.8b, \dst, \src + load_add_store , , , , v31.8h, v5.8b, v4.8b, \dst, \src + load_add_store , , , , , , v5.8b, \dst, \src +.endm +.macro load_add_store_8x8 dst, src, shiftbits=4 + mov \src, \dst + load_add_store v2.8b, v16.8h, , , , , , \dst, \src, \shiftbits + load_add_store v3.8b, v17.8h, , , , , , \dst, \src, \shiftbits + load_add_store v4.8b, v18.8h, v2.8b, v16.8h, , , , \dst, \src, \shiftbits + load_add_store v5.8b, v19.8h, v3.8b, v17.8h, v16.8h, v2.8b, , \dst, \src, \shiftbits + load_add_store v6.8b, v20.8h, v4.8b, v18.8h, v17.8h, v3.8b, v2.8b, \dst, \src, \shiftbits + load_add_store v7.8b, v21.8h, v5.8b, v19.8h, v18.8h, v4.8b, v3.8b, \dst, \src, \shiftbits + load_add_store v2.8b, v22.8h, v6.8b, v20.8h, v19.8h, v5.8b, v4.8b, \dst, \src, \shiftbits + load_add_store v3.8b, v23.8h, v7.8b, v21.8h, v20.8h, v6.8b, v5.8b, \dst, \src, \shiftbits + load_add_store , , v2.8b, v22.8h, v21.8h, v7.8b, v6.8b, \dst, \src, \shiftbits + load_add_store , , v3.8b, v23.8h, v22.8h, v2.8b, v7.8b, \dst, \src, \shiftbits + load_add_store , , , , v23.8h, v3.8b, v2.8b, \dst, \src, \shiftbits + load_add_store , , , , , , v3.8b, \dst, \src, \shiftbits +.endm +.macro load_add_store_8x4 dst, src + mov \src, \dst + load_add_store v2.8b, v16.8h, , , , , , \dst, \src + load_add_store v3.8b, v17.8h, , , , , , \dst, \src + load_add_store v4.8b, v18.8h, v2.8b, v16.8h, , , , \dst, \src + load_add_store v5.8b, v19.8h, v3.8b, v17.8h, v16.8h, v2.8b, , \dst, \src + load_add_store , , v4.8b, v18.8h, v17.8h, v3.8b, v2.8b, \dst, \src + load_add_store , , v5.8b, v19.8h, v18.8h, v4.8b, v3.8b, \dst, \src + load_add_store , , , , v19.8h, v5.8b, v4.8b, \dst, \src + load_add_store , , , , , , v5.8b, \dst, \src +.endm +.macro load_add_store4 load, inssrc, insdst, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src +.ifnb \load + ld1 {\load}[0], [\src], x1 +.endif +.ifnb \inssrc + ins \insdst\().d[1], \inssrc\().d[0] +.endif +.ifnb \shift + srshr \shift, \shift, #4 +.endif +.ifnb \load + ld1 {\load}[1], [\src], x1 +.endif +.ifnb \addsrc + uaddw \adddst, \adddst, \addsrc +.endif +.ifnb \store + st1 {\store}[0], [\dst], x1 +.endif +.ifnb \narrowsrc + sqxtun \narrowdst, \narrowsrc +.endif +.ifnb \store + st1 {\store}[1], [\dst], x1 +.endif +.endm +.macro load_add_store_4x16 dst, src + mov \src, \dst + load_add_store4 v0.s, v17, v16, , , , , , , \dst, \src + load_add_store4 v1.s, v19, v18, , , , , , , \dst, \src + load_add_store4 v2.s, v21, v20, v16.8h, , , , , , \dst, \src + load_add_store4 v3.s, v23, v22, v18.8h, v0.8b, v16.8h, , , , \dst, \src + load_add_store4 v4.s, v25, v24, v20.8h, v1.8b, v18.8h, v16.8h, v0.8b, , \dst, \src + load_add_store4 v5.s, v27, v26, v22.8h, v2.8b, v20.8h, v18.8h, v1.8b, v0.s, \dst, \src + load_add_store4 v6.s, v29, v28, v24.8h, v3.8b, v22.8h, v20.8h, v2.8b, v1.s, \dst, \src + load_add_store4 v7.s, v31, v30, v26.8h, v4.8b, v24.8h, v22.8h, v3.8b, v2.s, \dst, \src + load_add_store4 , , , v28.8h, v5.8b, v26.8h, v24.8h, v4.8b, v3.s, \dst, \src + load_add_store4 , , , v30.8h, v6.8b, v28.8h, v26.8h, v5.8b, v4.s, \dst, \src + load_add_store4 , , , , v7.8b, v30.8h, v28.8h, v6.8b, v5.s, \dst, \src + load_add_store4 , , , , , , v30.8h, v7.8b, v6.s, \dst, \src + load_add_store4 , , , , , , , , v7.s, \dst, \src +.endm +.macro load_add_store_4x8 dst, src + mov \src, \dst + load_add_store4 v0.s, v17, v16, , , , , , , \dst, \src + load_add_store4 v1.s, v19, v18, , , , , , , \dst, \src + load_add_store4 v2.s, v21, v20, v16.8h, , , , , , \dst, \src + load_add_store4 v3.s, v23, v22, v18.8h, v0.8b, v16.8h, , , , \dst, \src + load_add_store4 , , , v20.8h, v1.8b, v18.8h, v16.8h, v0.8b, , \dst, \src + load_add_store4 , , , v22.8h, v2.8b, v20.8h, v18.8h, v1.8b, v0.s, \dst, \src + load_add_store4 , , , , v3.8b, v22.8h, v20.8h, v2.8b, v1.s, \dst, \src + load_add_store4 , , , , , , v22.8h, v3.8b, v2.s, \dst, \src + load_add_store4 , , , , , , , , v3.s, \dst, \src +.endm + +.macro idct_dc w, h, shift + cbnz w3, 1f + mov w16, #2896*8 + ld1r {v16.8h}, [x2] + dup v0.4h, w16 + sqrdmulh v16.8h, v16.8h, v0.h[0] + strh wzr, [x2] +.if (\w == 2*\h) || (2*\w == \h) + sqrdmulh v16.8h, v16.8h, v0.h[0] +.endif +.if \shift > 0 + srshr v16.8h, v16.8h, #\shift +.endif + sqrdmulh v16.8h, v16.8h, v0.h[0] + srshr v16.8h, v16.8h, #4 + mov w4, #\h + b idct_dc_w\w\()_neon +1: +.endm + +function idct_dc_w4_neon +1: + ld1 {v0.s}[0], [x0], x1 + ld1 {v0.s}[1], [x0], x1 + ld1 {v1.s}[0], [x0], x1 + ld1 {v1.s}[1], [x0], x1 + subs w4, w4, #4 + sub x0, x0, x1, lsl #2 + uaddw v0.8h, v16.8h, v0.8b + sqxtun v0.8b, v0.8h + uaddw v1.8h, v16.8h, v1.8b + st1 {v0.s}[0], [x0], x1 + sqxtun v1.8b, v1.8h + st1 {v0.s}[1], [x0], x1 + st1 {v1.s}[0], [x0], x1 + st1 {v1.s}[1], [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w8_neon +1: + ld1 {v0.8b}, [x0], x1 + ld1 {v1.8b}, [x0], x1 + ld1 {v2.8b}, [x0], x1 + uaddw v20.8h, v16.8h, v0.8b + ld1 {v3.8b}, [x0], x1 + sub x0, x0, x1, lsl #2 + subs w4, w4, #4 + uaddw v21.8h, v16.8h, v1.8b + sqxtun v0.8b, v20.8h + uaddw v22.8h, v16.8h, v2.8b + sqxtun v1.8b, v21.8h + uaddw v23.8h, v16.8h, v3.8b + st1 {v0.8b}, [x0], x1 + sqxtun v2.8b, v22.8h + st1 {v1.8b}, [x0], x1 + sqxtun v3.8b, v23.8h + st1 {v2.8b}, [x0], x1 + st1 {v3.8b}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w16_neon +1: + ld1 {v0.16b}, [x0], x1 + ld1 {v1.16b}, [x0], x1 + ld1 {v2.16b}, [x0], x1 + subs w4, w4, #4 + uaddw v20.8h, v16.8h, v0.8b + uaddw2 v21.8h, v16.8h, v0.16b + ld1 {v3.16b}, [x0], x1 + uaddw v22.8h, v16.8h, v1.8b + uaddw2 v23.8h, v16.8h, v1.16b + sub x0, x0, x1, lsl #2 + uaddw v24.8h, v16.8h, v2.8b + uaddw2 v25.8h, v16.8h, v2.16b + sqxtun v0.8b, v20.8h + sqxtun2 v0.16b, v21.8h + uaddw v26.8h, v16.8h, v3.8b + uaddw2 v27.8h, v16.8h, v3.16b + sqxtun v1.8b, v22.8h + sqxtun2 v1.16b, v23.8h + sqxtun v2.8b, v24.8h + sqxtun2 v2.16b, v25.8h + st1 {v0.16b}, [x0], x1 + sqxtun v3.8b, v26.8h + sqxtun2 v3.16b, v27.8h + st1 {v1.16b}, [x0], x1 + st1 {v2.16b}, [x0], x1 + st1 {v3.16b}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w32_neon +1: + ld1 {v0.16b, v1.16b}, [x0], x1 + subs w4, w4, #2 + uaddw v20.8h, v16.8h, v0.8b + uaddw2 v21.8h, v16.8h, v0.16b + ld1 {v2.16b, v3.16b}, [x0] + uaddw v22.8h, v16.8h, v1.8b + uaddw2 v23.8h, v16.8h, v1.16b + sub x0, x0, x1 + uaddw v24.8h, v16.8h, v2.8b + uaddw2 v25.8h, v16.8h, v2.16b + sqxtun v0.8b, v20.8h + sqxtun2 v0.16b, v21.8h + uaddw v26.8h, v16.8h, v3.8b + uaddw2 v27.8h, v16.8h, v3.16b + sqxtun v1.8b, v22.8h + sqxtun2 v1.16b, v23.8h + sqxtun v2.8b, v24.8h + sqxtun2 v2.16b, v25.8h + st1 {v0.16b, v1.16b}, [x0], x1 + sqxtun v3.8b, v26.8h + sqxtun2 v3.16b, v27.8h + st1 {v2.16b, v3.16b}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w64_neon +1: + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0] + subs w4, w4, #1 + uaddw v20.8h, v16.8h, v0.8b + uaddw2 v21.8h, v16.8h, v0.16b + uaddw v22.8h, v16.8h, v1.8b + uaddw2 v23.8h, v16.8h, v1.16b + uaddw v24.8h, v16.8h, v2.8b + uaddw2 v25.8h, v16.8h, v2.16b + sqxtun v0.8b, v20.8h + sqxtun2 v0.16b, v21.8h + uaddw v26.8h, v16.8h, v3.8b + uaddw2 v27.8h, v16.8h, v3.16b + sqxtun v1.8b, v22.8h + sqxtun2 v1.16b, v23.8h + sqxtun v2.8b, v24.8h + sqxtun2 v2.16b, v25.8h + sqxtun v3.8b, v26.8h + sqxtun2 v3.16b, v27.8h + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + b.gt 1b + ret +endfunc + +.macro iwht4 + add v16.4h, v16.4h, v17.4h + sub v21.4h, v18.4h, v19.4h + sub v20.4h, v16.4h, v21.4h + sshr v20.4h, v20.4h, #1 + sub v18.4h, v20.4h, v17.4h + sub v17.4h, v20.4h, v19.4h + add v19.4h, v21.4h, v18.4h + sub v16.4h, v16.4h, v17.4h +.endm + +.macro idct_4 r0, r1, r2, r3, sz + smull_smlal v6, v7, \r1, \r3, v0.h[3], v0.h[2], \sz + smull_smlsl v4, v5, \r1, \r3, v0.h[2], v0.h[3], \sz + smull_smlal v2, v3, \r0, \r2, v0.h[0], v0.h[0], \sz + sqrshrn_sz v6, v6, v7, #12, \sz + sqrshrn_sz v7, v4, v5, #12, \sz + smull_smlsl v4, v5, \r0, \r2, v0.h[0], v0.h[0], \sz + sqrshrn_sz v2, v2, v3, #12, \sz + sqrshrn_sz v3, v4, v5, #12, \sz + sqadd \r0\sz, v2\sz, v6\sz + sqsub \r3\sz, v2\sz, v6\sz + sqadd \r1\sz, v3\sz, v7\sz + sqsub \r2\sz, v3\sz, v7\sz +.endm + +function inv_dct_4h_x4_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.4h}, [x16] + idct_4 v16, v17, v18, v19, .4h + ret +endfunc + +function inv_dct_8h_x4_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.4h}, [x16] + idct_4 v16, v17, v18, v19, .8h + ret +endfunc + +.macro iadst_4x4 o0, o1, o2, o3 + movrel x16, iadst4_coeffs + ld1 {v0.8h}, [x16] + + ssubl v3.4s, v16.4h, v18.4h + smull v4.4s, v16.4h, v0.h[0] + smlal v4.4s, v18.4h, v0.h[1] + smlal v4.4s, v19.4h, v0.h[2] + smull v7.4s, v17.4h, v0.h[3] + saddw v3.4s, v3.4s, v19.4h + smull v5.4s, v16.4h, v0.h[2] + smlsl v5.4s, v18.4h, v0.h[0] + smlsl v5.4s, v19.4h, v0.h[1] + + add \o3\().4s, v4.4s, v5.4s + mul \o2\().4s, v3.4s, v0.s[2] + add \o0\().4s, v4.4s, v7.4s + add \o1\().4s, v5.4s, v7.4s + sub \o3\().4s, \o3\().4s, v7.4s + + sqrshrn \o0\().4h, \o0\().4s, #12 + sqrshrn \o2\().4h, \o2\().4s, #12 + sqrshrn \o1\().4h, \o1\().4s, #12 + sqrshrn \o3\().4h, \o3\().4s, #12 +.endm + +function inv_adst_4h_x4_neon, export=1 + iadst_4x4 v16, v17, v18, v19 + ret +endfunc + +function inv_flipadst_4h_x4_neon, export=1 + iadst_4x4 v19, v18, v17, v16 + ret +endfunc + +.macro iadst_8x4 o0, o1, o2, o3 + movrel x16, iadst4_coeffs + ld1 {v0.8h}, [x16] + + ssubl v2.4s, v16.4h, v18.4h + ssubl2 v3.4s, v16.8h, v18.8h + smull v4.4s, v16.4h, v0.h[0] + smlal v4.4s, v18.4h, v0.h[1] + smlal v4.4s, v19.4h, v0.h[2] + smull2 v5.4s, v16.8h, v0.h[0] + smlal2 v5.4s, v18.8h, v0.h[1] + smlal2 v5.4s, v19.8h, v0.h[2] + saddw v2.4s, v2.4s, v19.4h + saddw2 v3.4s, v3.4s, v19.8h + smull v6.4s, v16.4h, v0.h[2] + smlsl v6.4s, v18.4h, v0.h[0] + smlsl v6.4s, v19.4h, v0.h[1] + smull2 v7.4s, v16.8h, v0.h[2] + smlsl2 v7.4s, v18.8h, v0.h[0] + smlsl2 v7.4s, v19.8h, v0.h[1] + + mul v18.4s, v2.4s, v0.s[2] + mul v19.4s, v3.4s, v0.s[2] + + smull v2.4s, v17.4h, v0.h[3] + smull2 v3.4s, v17.8h, v0.h[3] + + add v16.4s, v4.4s, v2.4s // out0 + add v17.4s, v5.4s, v3.4s + + add v4.4s, v4.4s, v6.4s // out3 + add v5.4s, v5.4s, v7.4s + + add v6.4s, v6.4s, v2.4s // out1 + add v7.4s, v7.4s, v3.4s + + sub v4.4s, v4.4s, v2.4s // out3 + sub v5.4s, v5.4s, v3.4s + + sqrshrn v18.4h, v18.4s, #12 + sqrshrn2 v18.8h, v19.4s, #12 + + sqrshrn \o0\().4h, v16.4s, #12 + sqrshrn2 \o0\().8h, v17.4s, #12 + +.ifc \o2, v17 + mov v17.16b, v18.16b +.endif + + sqrshrn \o1\().4h, v6.4s, #12 + sqrshrn2 \o1\().8h, v7.4s, #12 + + sqrshrn \o3\().4h, v4.4s, #12 + sqrshrn2 \o3\().8h, v5.4s, #12 +.endm + +function inv_adst_8h_x4_neon, export=1 + iadst_8x4 v16, v17, v18, v19 + ret +endfunc + +function inv_flipadst_8h_x4_neon, export=1 + iadst_8x4 v19, v18, v17, v16 + ret +endfunc + +function inv_identity_4h_x4_neon, export=1 + mov w16, #(5793-4096)*8 + dup v0.4h, w16 + sqrdmulh v4.4h, v16.4h, v0.h[0] + sqrdmulh v5.4h, v17.4h, v0.h[0] + sqrdmulh v6.4h, v18.4h, v0.h[0] + sqrdmulh v7.4h, v19.4h, v0.h[0] + sqadd v16.4h, v16.4h, v4.4h + sqadd v17.4h, v17.4h, v5.4h + sqadd v18.4h, v18.4h, v6.4h + sqadd v19.4h, v19.4h, v7.4h + ret +endfunc + +function inv_identity_8h_x4_neon, export=1 + mov w16, #(5793-4096)*8 + dup v0.4h, w16 + sqrdmulh v4.8h, v16.8h, v0.h[0] + sqrdmulh v5.8h, v17.8h, v0.h[0] + sqrdmulh v6.8h, v18.8h, v0.h[0] + sqrdmulh v7.8h, v19.8h, v0.h[0] + sqadd v16.8h, v16.8h, v4.8h + sqadd v17.8h, v17.8h, v5.8h + sqadd v18.8h, v18.8h, v6.8h + sqadd v19.8h, v19.8h, v7.8h + ret +endfunc + +.macro identity_8x4_shift1 r0, r1, r2, r3, c +.irp i, \r0\().8h, \r1\().8h, \r2\().8h, \r3\().8h + sqrdmulh v2.8h, \i, \c + srhadd \i, \i, v2.8h +.endr +.endm + +function inv_txfm_add_wht_wht_4x4_8bpc_neon, export=1 + mov x15, x30 + movi v31.8h, #0 + ld1 {v16.4h,v17.4h,v18.4h,v19.4h}, [x2] + st1 {v31.8h}, [x2], #16 + + sshr v16.4h, v16.4h, #2 + sshr v17.4h, v17.4h, #2 + sshr v18.4h, v18.4h, #2 + sshr v19.4h, v19.4h, #2 + + iwht4 + + st1 {v31.8h}, [x2], #16 + transpose_4x4h v16, v17, v18, v19, v20, v21, v22, v23 + + iwht4 + + ld1 {v0.s}[0], [x0], x1 + ld1 {v0.s}[1], [x0], x1 + ins v16.d[1], v17.d[0] + ins v18.d[1], v19.d[0] + ld1 {v1.s}[0], [x0], x1 + ld1 {v1.s}[1], [x0], x1 + + b L(itx_4x4_end) +endfunc + +function inv_txfm_add_4x4_neon + movi v31.8h, #0 + ld1 {v16.4h,v17.4h,v18.4h,v19.4h}, [x2] + st1 {v31.8h}, [x2], #16 + + blr x4 + + st1 {v31.8h}, [x2], #16 + transpose_4x4h v16, v17, v18, v19, v20, v21, v22, v23 + + blr x5 + + ld1 {v0.s}[0], [x0], x1 + ld1 {v0.s}[1], [x0], x1 + ins v16.d[1], v17.d[0] + ins v18.d[1], v19.d[0] + ld1 {v1.s}[0], [x0], x1 + ld1 {v1.s}[1], [x0], x1 + srshr v16.8h, v16.8h, #4 + srshr v18.8h, v18.8h, #4 + +L(itx_4x4_end): + sub x0, x0, x1, lsl #2 + uaddw v16.8h, v16.8h, v0.8b + sqxtun v0.8b, v16.8h + uaddw v18.8h, v18.8h, v1.8b + st1 {v0.s}[0], [x0], x1 + sqxtun v1.8b, v18.8h + st1 {v0.s}[1], [x0], x1 + st1 {v1.s}[0], [x0], x1 + st1 {v1.s}[1], [x0], x1 + + ret x15 +endfunc + +.macro def_fn_4x4 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_4x4_8bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + cbnz w3, 1f + mov w16, #2896*8 + ld1r {v16.8h}, [x2] + dup v4.8h, w16 + strh wzr, [x2] + sqrdmulh v16.8h, v16.8h, v4.h[0] + ld1 {v0.s}[0], [x0], x1 + sqrdmulh v20.8h, v16.8h, v4.h[0] + ld1 {v0.s}[1], [x0], x1 + srshr v16.8h, v20.8h, #4 + ld1 {v1.s}[0], [x0], x1 + srshr v18.8h, v20.8h, #4 + ld1 {v1.s}[1], [x0], x1 + b L(itx_4x4_end) +1: +.endif + adr x4, inv_\txfm1\()_4h_x4_neon + adr x5, inv_\txfm2\()_4h_x4_neon + b inv_txfm_add_4x4_neon +endfunc +.endm + +def_fn_4x4 dct, dct +def_fn_4x4 identity, identity +def_fn_4x4 dct, adst +def_fn_4x4 dct, flipadst +def_fn_4x4 dct, identity +def_fn_4x4 adst, dct +def_fn_4x4 adst, adst +def_fn_4x4 adst, flipadst +def_fn_4x4 flipadst, dct +def_fn_4x4 flipadst, adst +def_fn_4x4 flipadst, flipadst +def_fn_4x4 identity, dct + +def_fn_4x4 adst, identity +def_fn_4x4 flipadst, identity +def_fn_4x4 identity, adst +def_fn_4x4 identity, flipadst + +.macro idct_8 r0, r1, r2, r3, r4, r5, r6, r7, sz, szb + idct_4 \r0, \r2, \r4, \r6, \sz + + smull_smlsl v2, v3, \r1, \r7, v0.h[4], v0.h[5], \sz // -> t4a + smull_smlal v4, v5, \r1, \r7, v0.h[5], v0.h[4], \sz // -> t7a + smull_smlsl v6, v7, \r5, \r3, v0.h[6], v0.h[7], \sz // -> t5a + sqrshrn_sz \r1, v2, v3, #12, \sz // t4a + sqrshrn_sz \r7, v4, v5, #12, \sz // t7a + smull_smlal v2, v3, \r5, \r3, v0.h[7], v0.h[6], \sz // -> t6a + sqrshrn_sz \r3, v6, v7, #12, \sz // t5a + sqrshrn_sz \r5, v2, v3, #12, \sz // t6a + + sqadd v2\sz, \r1\sz, \r3\sz // t4 + sqsub \r1\sz, \r1\sz, \r3\sz // t5a + sqadd v3\sz, \r7\sz, \r5\sz // t7 + sqsub \r3\sz, \r7\sz, \r5\sz // t6a + + smull_smlsl v4, v5, \r3, \r1, v0.h[0], v0.h[0], \sz // -> t5 + smull_smlal v6, v7, \r3, \r1, v0.h[0], v0.h[0], \sz // -> t6 + sqrshrn_sz v4, v4, v5, #12, \sz // t5 + sqrshrn_sz v5, v6, v7, #12, \sz // t6 + + sqsub \r7\sz, \r0\sz, v3\sz // out7 + sqadd \r0\sz, \r0\sz, v3\sz // out0 + sqadd \r1\sz, \r2\sz, v5\sz // out1 + sqsub v6\sz, \r2\sz, v5\sz // out6 + sqadd \r2\sz, \r4\sz, v4\sz // out2 + sqsub \r5\sz, \r4\sz, v4\sz // out5 + sqadd \r3\sz, \r6\sz, v2\sz // out3 + sqsub \r4\sz, \r6\sz, v2\sz // out4 + mov \r6\szb, v6\szb // out6 +.endm + +function inv_dct_8h_x8_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.8h}, [x16] + idct_8 v16, v17, v18, v19, v20, v21, v22, v23, .8h, .16b + ret +endfunc + +function inv_dct_4h_x8_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.8h}, [x16] + idct_8 v16, v17, v18, v19, v20, v21, v22, v23, .4h, .8b + ret +endfunc + +.macro iadst_8 o0, o1, o2, o3, o4, o5, o6, o7, sz + movrel x16, iadst8_coeffs + ld1 {v0.8h, v1.8h}, [x16] + + smull_smlal v2, v3, v23, v16, v0.h[0], v0.h[1], \sz + smull_smlsl v4, v5, v23, v16, v0.h[1], v0.h[0], \sz + smull_smlal v6, v7, v21, v18, v0.h[2], v0.h[3], \sz + sqrshrn_sz v16, v2, v3, #12, \sz // t0a + sqrshrn_sz v23, v4, v5, #12, \sz // t1a + smull_smlsl v2, v3, v21, v18, v0.h[3], v0.h[2], \sz + smull_smlal v4, v5, v19, v20, v0.h[4], v0.h[5], \sz + sqrshrn_sz v18, v6, v7, #12, \sz // t2a + sqrshrn_sz v21, v2, v3, #12, \sz // t3a + smull_smlsl v6, v7, v19, v20, v0.h[5], v0.h[4], \sz + smull_smlal v2, v3, v17, v22, v0.h[6], v0.h[7], \sz + sqrshrn_sz v20, v4, v5, #12, \sz // t4a + sqrshrn_sz v19, v6, v7, #12, \sz // t5a + smull_smlsl v4, v5, v17, v22, v0.h[7], v0.h[6], \sz + sqrshrn_sz v22, v2, v3, #12, \sz // t6a + sqrshrn_sz v17, v4, v5, #12, \sz // t7a + + sqadd v2\sz, v16\sz, v20\sz // t0 + sqsub v3\sz, v16\sz, v20\sz // t4 + sqadd v4\sz, v23\sz, v19\sz // t1 + sqsub v5\sz, v23\sz, v19\sz // t5 + sqadd v6\sz, v18\sz, v22\sz // t2 + sqsub v7\sz, v18\sz, v22\sz // t6 + sqadd v18\sz, v21\sz, v17\sz // t3 + sqsub v19\sz, v21\sz, v17\sz // t7 + + smull_smlal v16, v17, v3, v5, v1.h[3], v1.h[2], \sz + smull_smlsl v20, v21, v3, v5, v1.h[2], v1.h[3], \sz + smull_smlsl v22, v23, v19, v7, v1.h[3], v1.h[2], \sz + + sqrshrn_sz v3, v16, v17, #12, \sz // t4a + sqrshrn_sz v5, v20, v21, #12, \sz // t5a + + smull_smlal v16, v17, v19, v7, v1.h[2], v1.h[3], \sz + + sqrshrn_sz v7, v22, v23, #12, \sz // t6a + sqrshrn_sz v19, v16, v17, #12, \sz // t7a + + sqadd \o0\()\sz, v2\sz, v6\sz // out0 + sqsub v2\sz, v2\sz, v6\sz // t2 + sqadd \o7\()\sz, v4\sz, v18\sz // out7 + sqsub v4\sz, v4\sz, v18\sz // t3 + sqneg \o7\()\sz, \o7\()\sz // out7 + + sqadd \o1\()\sz, v3\sz, v7\sz // out1 + sqsub v3\sz, v3\sz, v7\sz // t6 + sqadd \o6\()\sz, v5\sz, v19\sz // out6 + sqsub v5\sz, v5\sz, v19\sz // t7 + sqneg \o1\()\sz, \o1\()\sz // out1 + + smull_smlal v18, v19, v2, v4, v1.h[0], v1.h[0], \sz // -> out3 (v19 or v20) + smull_smlsl v6, v7, v2, v4, v1.h[0], v1.h[0], \sz // -> out4 (v20 or v19) + smull_smlsl v20, v21, v3, v5, v1.h[0], v1.h[0], \sz // -> out5 (v21 or v18) + sqrshrn_sz v2, v18, v19, #12, \sz // out3 + smull_smlal v18, v19, v3, v5, v1.h[0], v1.h[0], \sz // -> out2 (v18 or v21) + sqrshrn_sz v3, v20, v21, #12, \sz // out5 + sqrshrn_sz \o2, v18, v19, #12, \sz // out2 (v18 or v21) + sqrshrn_sz \o4, v6, v7, #12, \sz // out4 (v20 or v19) + + sqneg \o3\()\sz, v2\sz // out3 + sqneg \o5\()\sz, v3\sz // out5 +.endm + +function inv_adst_8h_x8_neon, export=1 + iadst_8 v16, v17, v18, v19, v20, v21, v22, v23, .8h + ret +endfunc + +function inv_flipadst_8h_x8_neon, export=1 + iadst_8 v23, v22, v21, v20, v19, v18, v17, v16, .8h + ret +endfunc + +function inv_adst_4h_x8_neon, export=1 + iadst_8 v16, v17, v18, v19, v20, v21, v22, v23, .4h + ret +endfunc + +function inv_flipadst_4h_x8_neon, export=1 + iadst_8 v23, v22, v21, v20, v19, v18, v17, v16, .4h + ret +endfunc + +function inv_identity_8h_x8_neon, export=1 + sqshl v16.8h, v16.8h, #1 + sqshl v17.8h, v17.8h, #1 + sqshl v18.8h, v18.8h, #1 + sqshl v19.8h, v19.8h, #1 + sqshl v20.8h, v20.8h, #1 + sqshl v21.8h, v21.8h, #1 + sqshl v22.8h, v22.8h, #1 + sqshl v23.8h, v23.8h, #1 + ret +endfunc + +function inv_identity_4h_x8_neon, export=1 + sqshl v16.4h, v16.4h, #1 + sqshl v17.4h, v17.4h, #1 + sqshl v18.4h, v18.4h, #1 + sqshl v19.4h, v19.4h, #1 + sqshl v20.4h, v20.4h, #1 + sqshl v21.4h, v21.4h, #1 + sqshl v22.4h, v22.4h, #1 + sqshl v23.4h, v23.4h, #1 + ret +endfunc + +.macro def_fn_8x8_base variant +function inv_txfm_\variant\()add_8x8_neon + movi v28.8h, #0 + movi v29.8h, #0 + movi v30.8h, #0 + movi v31.8h, #0 + ld1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x2] + st1 {v28.8h,v29.8h,v30.8h,v31.8h}, [x2], #64 + ld1 {v20.8h,v21.8h,v22.8h,v23.8h}, [x2] + st1 {v28.8h,v29.8h,v30.8h,v31.8h}, [x2] + +.ifc \variant, identity_ + // The identity shl #1 and downshift srshr #1 cancel out +.else + blr x4 + + srshr v16.8h, v16.8h, #1 + srshr v17.8h, v17.8h, #1 + srshr v18.8h, v18.8h, #1 + srshr v19.8h, v19.8h, #1 + srshr v20.8h, v20.8h, #1 + srshr v21.8h, v21.8h, #1 + srshr v22.8h, v22.8h, #1 + srshr v23.8h, v23.8h, #1 +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 + + blr x5 + + load_add_store_8x8 x0, x7 + ret x15 +endfunc +.endm + +def_fn_8x8_base +def_fn_8x8_base identity_ + +.macro def_fn_8x8 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_8x8_8bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 8, 8, 1 +.endif + adr x5, inv_\txfm2\()_8h_x8_neon +.ifc \txfm1, identity + b inv_txfm_identity_add_8x8_neon +.else + adr x4, inv_\txfm1\()_8h_x8_neon + b inv_txfm_add_8x8_neon +.endif +endfunc +.endm + +def_fn_8x8 dct, dct +def_fn_8x8 identity, identity +def_fn_8x8 dct, adst +def_fn_8x8 dct, flipadst +def_fn_8x8 dct, identity +def_fn_8x8 adst, dct +def_fn_8x8 adst, adst +def_fn_8x8 adst, flipadst +def_fn_8x8 flipadst, dct +def_fn_8x8 flipadst, adst +def_fn_8x8 flipadst, flipadst +def_fn_8x8 identity, dct +def_fn_8x8 adst, identity +def_fn_8x8 flipadst, identity +def_fn_8x8 identity, adst +def_fn_8x8 identity, flipadst + +function inv_txfm_add_8x4_neon + movi v30.8h, #0 + movi v31.8h, #0 + mov w16, #2896*8 + dup v0.4h, w16 + ld1 {v16.4h,v17.4h,v18.4h,v19.4h}, [x2] + st1 {v30.8h,v31.8h}, [x2], #32 + ld1 {v20.4h,v21.4h,v22.4h,v23.4h}, [x2] + st1 {v30.8h,v31.8h}, [x2] + + scale_input .4h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + + blr x4 + + transpose_4x4h v16, v17, v18, v19, v4, v5, v6, v7 + transpose_4x4h v20, v21, v22, v23, v4, v5, v6, v7 + ins v16.d[1], v20.d[0] + ins v17.d[1], v21.d[0] + ins v18.d[1], v22.d[0] + ins v19.d[1], v23.d[0] + + blr x5 + + load_add_store_8x4 x0, x7 + ret x15 +endfunc + +function inv_txfm_add_4x8_neon + movi v28.8h, #0 + movi v29.8h, #0 + movi v30.8h, #0 + movi v31.8h, #0 + mov w16, #2896*8 + dup v0.4h, w16 + ld1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x2] + st1 {v28.8h,v29.8h,v30.8h,v31.8h}, [x2] + + scale_input .8h, v0.h[0], v16, v17, v18, v19 + + blr x4 + + transpose_4x8h v16, v17, v18, v19, v4, v5, v6, v7 + ins v20.d[0], v16.d[1] + ins v21.d[0], v17.d[1] + ins v22.d[0], v18.d[1] + ins v23.d[0], v19.d[1] + + blr x5 + + load_add_store_4x8 x0, x7 + ret x15 +endfunc + +.macro def_fn_48 w, h, txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 0 +.endif + adr x4, inv_\txfm1\()_\h\()h_x\w\()_neon + adr x5, inv_\txfm2\()_\w\()h_x\h\()_neon + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_48 w, h +def_fn_48 \w, \h, dct, dct +def_fn_48 \w, \h, identity, identity +def_fn_48 \w, \h, dct, adst +def_fn_48 \w, \h, dct, flipadst +def_fn_48 \w, \h, dct, identity +def_fn_48 \w, \h, adst, dct +def_fn_48 \w, \h, adst, adst +def_fn_48 \w, \h, adst, flipadst +def_fn_48 \w, \h, flipadst, dct +def_fn_48 \w, \h, flipadst, adst +def_fn_48 \w, \h, flipadst, flipadst +def_fn_48 \w, \h, identity, dct +def_fn_48 \w, \h, adst, identity +def_fn_48 \w, \h, flipadst, identity +def_fn_48 \w, \h, identity, adst +def_fn_48 \w, \h, identity, flipadst +.endm + +def_fns_48 4, 8 +def_fns_48 8, 4 + + +.macro idct_16 sz, szb + idct_8 v16, v18, v20, v22, v24, v26, v28, v30, \sz, \szb + + smull_smlsl v2, v3, v17, v31, v1.h[0], v1.h[1], \sz // -> t8a + smull_smlal v4, v5, v17, v31, v1.h[1], v1.h[0], \sz // -> t15a + smull_smlsl v6, v7, v25, v23, v1.h[2], v1.h[3], \sz // -> t9a + sqrshrn_sz v17, v2, v3, #12, \sz // t8a + sqrshrn_sz v31, v4, v5, #12, \sz // t15a + smull_smlal v2, v3, v25, v23, v1.h[3], v1.h[2], \sz // -> t14a + smull_smlsl v4, v5, v21, v27, v1.h[4], v1.h[5], \sz // -> t10a + sqrshrn_sz v23, v6, v7, #12, \sz // t9a + sqrshrn_sz v25, v2, v3, #12, \sz // t14a + smull_smlal v6, v7, v21, v27, v1.h[5], v1.h[4], \sz // -> t13a + smull_smlsl v2, v3, v29, v19, v1.h[6], v1.h[7], \sz // -> t11a + sqrshrn_sz v21, v4, v5, #12, \sz // t10a + sqrshrn_sz v27, v6, v7, #12, \sz // t13a + smull_smlal v4, v5, v29, v19, v1.h[7], v1.h[6], \sz // -> t12a + sqrshrn_sz v19, v2, v3, #12, \sz // t11a + sqrshrn_sz v29, v4, v5, #12, \sz // t12a + + sqsub v2\sz, v17\sz, v23\sz // t9 + sqadd v17\sz, v17\sz, v23\sz // t8 + sqsub v3\sz, v31\sz, v25\sz // t14 + sqadd v31\sz, v31\sz, v25\sz // t15 + sqsub v23\sz, v19\sz, v21\sz // t10 + sqadd v19\sz, v19\sz, v21\sz // t11 + sqadd v25\sz, v29\sz, v27\sz // t12 + sqsub v29\sz, v29\sz, v27\sz // t13 + + smull_smlsl v4, v5, v3, v2, v0.h[2], v0.h[3], \sz // -> t9a + smull_smlal v6, v7, v3, v2, v0.h[3], v0.h[2], \sz // -> t14a + sqrshrn_sz v21, v4, v5, #12, \sz // t9a + sqrshrn_sz v27, v6, v7, #12, \sz // t14a + + smull_smlsl v4, v5, v29, v23, v0.h[2], v0.h[3], \sz // -> t13a + smull_smlal v6, v7, v29, v23, v0.h[3], v0.h[2], \sz // -> t10a + sqrshrn_sz v29, v4, v5, #12, \sz // t13a + neg v6.4s, v6.4s +.ifc \sz, .8h + neg v7.4s, v7.4s +.endif + sqrshrn_sz v23, v6, v7, #12, \sz // t10a + + sqsub v2\sz, v17\sz, v19\sz // t11a + sqadd v17\sz, v17\sz, v19\sz // t8a + sqsub v3\sz, v31\sz, v25\sz // t12a + sqadd v31\sz, v31\sz, v25\sz // t15a + sqadd v19\sz, v21\sz, v23\sz // t9 + sqsub v21\sz, v21\sz, v23\sz // t10 + sqsub v25\sz, v27\sz, v29\sz // t13 + sqadd v27\sz, v27\sz, v29\sz // t14 + + smull_smlsl v4, v5, v3, v2, v0.h[0], v0.h[0], \sz // -> t11 + smull_smlal v6, v7, v3, v2, v0.h[0], v0.h[0], \sz // -> t12 + smull_smlsl v2, v3, v25, v21, v0.h[0], v0.h[0], \sz // -> t10a + + sqrshrn_sz v4, v4, v5, #12, \sz // t11 + sqrshrn_sz v5, v6, v7, #12, \sz // t12 + smull_smlal v6, v7, v25, v21, v0.h[0], v0.h[0], \sz // -> t13a + sqrshrn_sz v2, v2, v3, #12, \sz // t10a + sqrshrn_sz v3, v6, v7, #12, \sz // t13a + + sqadd v6\sz, v16\sz, v31\sz // out0 + sqsub v31\sz, v16\sz, v31\sz // out15 + mov v16\szb, v6\szb + sqadd v23\sz, v30\sz, v17\sz // out7 + sqsub v7\sz, v30\sz, v17\sz // out8 + sqadd v17\sz, v18\sz, v27\sz // out1 + sqsub v30\sz, v18\sz, v27\sz // out14 + sqadd v18\sz, v20\sz, v3\sz // out2 + sqsub v29\sz, v20\sz, v3\sz // out13 + sqadd v3\sz, v28\sz, v19\sz // out6 + sqsub v25\sz, v28\sz, v19\sz // out9 + sqadd v19\sz, v22\sz, v5\sz // out3 + sqsub v28\sz, v22\sz, v5\sz // out12 + sqadd v20\sz, v24\sz, v4\sz // out4 + sqsub v27\sz, v24\sz, v4\sz // out11 + sqadd v21\sz, v26\sz, v2\sz // out5 + sqsub v26\sz, v26\sz, v2\sz // out10 + mov v24\szb, v7\szb + mov v22\szb, v3\szb +.endm + +function inv_dct_8h_x16_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.8h, v1.8h}, [x16] + idct_16 .8h, .16b + ret +endfunc + +function inv_dct_4h_x16_neon, export=1 + movrel x16, idct_coeffs + ld1 {v0.8h, v1.8h}, [x16] + idct_16 .4h, .8b + ret +endfunc + +.macro iadst_16 o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, sz, szb + movrel x16, iadst16_coeffs + ld1 {v0.8h, v1.8h}, [x16] + movrel x16, idct_coeffs + + smull_smlal v2, v3, v31, v16, v0.h[0], v0.h[1], \sz // -> t0 + smull_smlsl v4, v5, v31, v16, v0.h[1], v0.h[0], \sz // -> t1 + smull_smlal v6, v7, v29, v18, v0.h[2], v0.h[3], \sz // -> t2 + sqrshrn_sz v16, v2, v3, #12, \sz // t0 + sqrshrn_sz v31, v4, v5, #12, \sz // t1 + smull_smlsl v2, v3, v29, v18, v0.h[3], v0.h[2], \sz // -> t3 + smull_smlal v4, v5, v27, v20, v0.h[4], v0.h[5], \sz // -> t4 + sqrshrn_sz v18, v6, v7, #12, \sz // t2 + sqrshrn_sz v29, v2, v3, #12, \sz // t3 + smull_smlsl v6, v7, v27, v20, v0.h[5], v0.h[4], \sz // -> t5 + smull_smlal v2, v3, v25, v22, v0.h[6], v0.h[7], \sz // -> t6 + sqrshrn_sz v20, v4, v5, #12, \sz // t4 + sqrshrn_sz v27, v6, v7, #12, \sz // t5 + smull_smlsl v4, v5, v25, v22, v0.h[7], v0.h[6], \sz // -> t7 + smull_smlal v6, v7, v23, v24, v1.h[0], v1.h[1], \sz // -> t8 + sqrshrn_sz v22, v2, v3, #12, \sz // t6 + sqrshrn_sz v25, v4, v5, #12, \sz // t7 + smull_smlsl v2, v3, v23, v24, v1.h[1], v1.h[0], \sz // -> t9 + smull_smlal v4, v5, v21, v26, v1.h[2], v1.h[3], \sz // -> t10 + sqrshrn_sz v23, v6, v7, #12, \sz // t8 + sqrshrn_sz v24, v2, v3, #12, \sz // t9 + smull_smlsl v6, v7, v21, v26, v1.h[3], v1.h[2], \sz // -> t11 + smull_smlal v2, v3, v19, v28, v1.h[4], v1.h[5], \sz // -> t12 + sqrshrn_sz v21, v4, v5, #12, \sz // t10 + sqrshrn_sz v26, v6, v7, #12, \sz // t11 + smull_smlsl v4, v5, v19, v28, v1.h[5], v1.h[4], \sz // -> t13 + smull_smlal v6, v7, v17, v30, v1.h[6], v1.h[7], \sz // -> t14 + sqrshrn_sz v19, v2, v3, #12, \sz // t12 + sqrshrn_sz v28, v4, v5, #12, \sz // t13 + smull_smlsl v2, v3, v17, v30, v1.h[7], v1.h[6], \sz // -> t15 + sqrshrn_sz v17, v6, v7, #12, \sz // t14 + sqrshrn_sz v30, v2, v3, #12, \sz // t15 + + ld1 {v0.8h}, [x16] + + sqsub v2\sz, v16\sz, v23\sz // t8a + sqadd v16\sz, v16\sz, v23\sz // t0a + sqsub v3\sz, v31\sz, v24\sz // t9a + sqadd v31\sz, v31\sz, v24\sz // t1a + sqadd v23\sz, v18\sz, v21\sz // t2a + sqsub v18\sz, v18\sz, v21\sz // t10a + sqadd v24\sz, v29\sz, v26\sz // t3a + sqsub v29\sz, v29\sz, v26\sz // t11a + sqadd v21\sz, v20\sz, v19\sz // t4a + sqsub v20\sz, v20\sz, v19\sz // t12a + sqadd v26\sz, v27\sz, v28\sz // t5a + sqsub v27\sz, v27\sz, v28\sz // t13a + sqadd v19\sz, v22\sz, v17\sz // t6a + sqsub v22\sz, v22\sz, v17\sz // t14a + sqadd v28\sz, v25\sz, v30\sz // t7a + sqsub v25\sz, v25\sz, v30\sz // t15a + + smull_smlal v4, v5, v2, v3, v0.h[5], v0.h[4], \sz // -> t8 + smull_smlsl v6, v7, v2, v3, v0.h[4], v0.h[5], \sz // -> t9 + smull_smlal v2, v3, v18, v29, v0.h[7], v0.h[6], \sz // -> t10 + sqrshrn_sz v17, v4, v5, #12, \sz // t8 + sqrshrn_sz v30, v6, v7, #12, \sz // t9 + smull_smlsl v4, v5, v18, v29, v0.h[6], v0.h[7], \sz // -> t11 + smull_smlsl v6, v7, v27, v20, v0.h[5], v0.h[4], \sz // -> t12 + sqrshrn_sz v18, v2, v3, #12, \sz // t10 + sqrshrn_sz v29, v4, v5, #12, \sz // t11 + smull_smlal v2, v3, v27, v20, v0.h[4], v0.h[5], \sz // -> t13 + smull_smlsl v4, v5, v25, v22, v0.h[7], v0.h[6], \sz // -> t14 + sqrshrn_sz v27, v6, v7, #12, \sz // t12 + sqrshrn_sz v20, v2, v3, #12, \sz // t13 + smull_smlal v6, v7, v25, v22, v0.h[6], v0.h[7], \sz // -> t15 + sqrshrn_sz v25, v4, v5, #12, \sz // t14 + sqrshrn_sz v22, v6, v7, #12, \sz // t15 + + sqsub v2\sz, v16\sz, v21\sz // t4 + sqadd v16\sz, v16\sz, v21\sz // t0 + sqsub v3\sz, v31\sz, v26\sz // t5 + sqadd v31\sz, v31\sz, v26\sz // t1 + sqadd v21\sz, v23\sz, v19\sz // t2 + sqsub v23\sz, v23\sz, v19\sz // t6 + sqadd v26\sz, v24\sz, v28\sz // t3 + sqsub v24\sz, v24\sz, v28\sz // t7 + sqadd v19\sz, v17\sz, v27\sz // t8a + sqsub v17\sz, v17\sz, v27\sz // t12a + sqadd v28\sz, v30\sz, v20\sz // t9a + sqsub v30\sz, v30\sz, v20\sz // t13a + sqadd v27\sz, v18\sz, v25\sz // t10a + sqsub v18\sz, v18\sz, v25\sz // t14a + sqadd v20\sz, v29\sz, v22\sz // t11a + sqsub v29\sz, v29\sz, v22\sz // t15a + + smull_smlal v4, v5, v2, v3, v0.h[3], v0.h[2], \sz // -> t4a + smull_smlsl v6, v7, v2, v3, v0.h[2], v0.h[3], \sz // -> t5a + smull_smlsl v2, v3, v24, v23, v0.h[3], v0.h[2], \sz // -> t6a + sqrshrn_sz v22, v4, v5, #12, \sz // t4a + sqrshrn_sz v25, v6, v7, #12, \sz // t5a + smull_smlal v4, v5, v24, v23, v0.h[2], v0.h[3], \sz // -> t7a + smull_smlal v6, v7, v17, v30, v0.h[3], v0.h[2], \sz // -> t12 + sqrshrn_sz v24, v2, v3, #12, \sz // t6a + sqrshrn_sz v23, v4, v5, #12, \sz // t7a + smull_smlsl v2, v3, v17, v30, v0.h[2], v0.h[3], \sz // -> t13 + smull_smlsl v4, v5, v29, v18, v0.h[3], v0.h[2], \sz // -> t14 + sqrshrn_sz v17, v6, v7, #12, \sz // t12 + smull_smlal v6, v7, v29, v18, v0.h[2], v0.h[3], \sz // -> t15 + sqrshrn_sz v29, v2, v3, #12, \sz // t13 + sqrshrn_sz v30, v4, v5, #12, \sz // t14 + sqrshrn_sz v18, v6, v7, #12, \sz // t15 + + sqsub v2\sz, v16\sz, v21\sz // t2a +.ifc \o0, v16 + sqadd \o0\sz, v16\sz, v21\sz // out0 + sqsub v21\sz, v31\sz, v26\sz // t3a + sqadd \o15\sz, v31\sz, v26\sz // out15 +.else + sqadd v4\sz, v16\sz, v21\sz // out0 + sqsub v21\sz, v31\sz, v26\sz // t3a + sqadd \o15\sz, v31\sz, v26\sz // out15 + mov \o0\szb, v4\szb +.endif + sqneg \o15\sz, \o15\sz // out15 + + sqsub v3\sz, v29\sz, v18\sz // t15a + sqadd \o13\sz, v29\sz, v18\sz // out13 + sqadd \o2\sz, v17\sz, v30\sz // out2 + sqsub v26\sz, v17\sz, v30\sz // t14a + sqneg \o13\sz, \o13\sz // out13 + + sqadd \o1\sz, v19\sz, v27\sz // out1 + sqsub v27\sz, v19\sz, v27\sz // t10 + sqadd \o14\sz, v28\sz, v20\sz // out14 + sqsub v20\sz, v28\sz, v20\sz // t11 + sqneg \o1\sz, \o1\sz // out1 + + sqadd \o3\sz, v22\sz, v24\sz // out3 + sqsub v22\sz, v22\sz, v24\sz // t6 + sqadd \o12\sz, v25\sz, v23\sz // out12 + sqsub v23\sz, v25\sz, v23\sz // t7 + sqneg \o3\sz, \o3\sz // out3 + + smull_smlsl v24, v25, v2, v21, v0.h[0], v0.h[0], \sz // -> out8 (v24 or v23) + smull_smlal v4, v5, v2, v21, v0.h[0], v0.h[0], \sz // -> out7 (v23 or v24) + smull_smlal v6, v7, v26, v3, v0.h[0], v0.h[0], \sz // -> out5 (v21 or v26) + + sqrshrn_sz v24, v24, v25, #12, \sz // out8 + sqrshrn_sz v4, v4, v5, #12, \sz // out7 + sqrshrn_sz v5, v6, v7, #12, \sz // out5 + smull_smlsl v6, v7, v26, v3, v0.h[0], v0.h[0], \sz // -> out10 (v26 or v21) + smull_smlal v2, v3, v22, v23, v0.h[0], v0.h[0], \sz // -> out4 (v20 or v27) + sqrshrn_sz v26, v6, v7, #12, \sz // out10 + + smull_smlsl v6, v7, v22, v23, v0.h[0], v0.h[0], \sz // -> out11 (v27 or v20) + smull_smlal v22, v23, v27, v20, v0.h[0], v0.h[0], \sz // -> out6 (v22 or v25) + smull_smlsl v21, v25, v27, v20, v0.h[0], v0.h[0], \sz // -> out9 (v25 or v22) + + sqrshrn_sz \o4, v2, v3, #12, \sz // out4 + sqrshrn_sz v6, v6, v7, #12, \sz // out11 + sqrshrn_sz v7, v21, v25, #12, \sz // out9 + sqrshrn_sz \o6, v22, v23, #12, \sz // out6 + +.ifc \o8, v23 + mov \o8\szb, v24\szb + mov \o10\szb, v26\szb +.endif + + sqneg \o7\sz, v4\sz // out7 + sqneg \o5\sz, v5\sz // out5 + sqneg \o11\sz, v6\sz // out11 + sqneg \o9\sz, v7\sz // out9 +.endm + +function inv_adst_8h_x16_neon, export=1 + iadst_16 v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, .8h, .16b + ret +endfunc + +function inv_flipadst_8h_x16_neon, export=1 + iadst_16 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, .8h, .16b + ret +endfunc + +function inv_adst_4h_x16_neon, export=1 + iadst_16 v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, .4h, .8b + ret +endfunc + +function inv_flipadst_4h_x16_neon, export=1 + iadst_16 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, .4h, .8b + ret +endfunc + +function inv_identity_8h_x16_neon, export=1 + mov w16, #2*(5793-4096)*8 + dup v0.4h, w16 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + sqrdmulh v2.8h, v\i\().8h, v0.h[0] + sqadd v\i\().8h, v\i\().8h, v\i\().8h + sqadd v\i\().8h, v\i\().8h, v2.8h +.endr + ret +endfunc + +function inv_identity_4h_x16_neon, export=1 + mov w16, #2*(5793-4096)*8 + dup v0.4h, w16 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + sqrdmulh v2.4h, v\i\().4h, v0.h[0] + sqadd v\i\().4h, v\i\().4h, v\i\().4h + sqadd v\i\().4h, v\i\().4h, v2.4h +.endr + ret +endfunc + +.macro identity_8x16_shift2 c +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + sqrdmulh v2.8h, \i, \c + sshr v2.8h, v2.8h, #1 + srhadd \i, \i, v2.8h +.endr +.endm + +.macro identity_8x16_shift1 c +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + sqrdmulh v2.8h, \i, \c + srshr v2.8h, v2.8h, #1 + sqadd \i, \i, v2.8h +.endr +.endm + +.macro identity_8x8_shift1 c +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + sqrdmulh v2.8h, \i, \c + srshr v2.8h, v2.8h, #1 + sqadd \i, \i, v2.8h +.endr +.endm + +.macro identity_8x8 c +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + sqrdmulh v2.8h, \i, \c + sqadd \i, \i, \i + sqadd \i, \i, v2.8h +.endr +.endm + +.macro def_horz_16 scale=0, identity=0, shift=2, suffix +function inv_txfm_horz\suffix\()_16x8_neon + AARCH64_VALID_CALL_TARGET + mov x14, x30 + movi v7.8h, #0 +.if \identity + mov w16, #2*(5793-4096)*8 + dup v0.4h, w16 +.elseif \scale + mov w16, #2896*8 + dup v0.4h, w16 +.endif +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + ld1 {\i}, [x7] + st1 {v7.8h}, [x7], x8 +.endr +.if \scale + scale_input .8h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .8h, v0.h[0], v24, v25, v26, v27, v28, v29, v30, v31 +.endif +.if \identity + identity_8x16_shift2 v0.h[0] +.else + blr x4 +.endif +.if \shift > 0 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + srshr \i, \i, #\shift +.endr +.endif + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + transpose_8x8h v24, v25, v26, v27, v28, v29, v30, v31, v4, v5 + +.irp i, v16.8h, v24.8h, v17.8h, v25.8h, v18.8h, v26.8h, v19.8h, v27.8h, v20.8h, v28.8h, v21.8h, v29.8h, v22.8h, v30.8h, v23.8h, v31.8h + st1 {\i}, [x6], #16 +.endr + + ret x14 +endfunc +.endm + +def_horz_16 scale=0, identity=0, shift=2 +def_horz_16 scale=1, identity=0, shift=1, suffix=_scale +def_horz_16 scale=0, identity=1, shift=0, suffix=_identity + +function inv_txfm_add_vert_8x16_neon + mov x14, x30 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + blr x5 + load_add_store_8x16 x6, x7 + ret x14 +endfunc + +function inv_txfm_add_16x16_neon + mov x15, x30 + sub sp, sp, #512 +.irp i, 0, 8 + add x6, sp, #(\i*16*2) +.if \i == 8 + cmp w3, w13 + b.lt 1f +.endif + add x7, x2, #(\i*2) + mov x8, #16*2 + blr x9 +.endr + b 2f +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr +2: +.irp i, 0, 8 + add x6, x0, #(\i) + add x7, sp, #(\i*2) + mov x8, #32 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, sp, #512 + ret x15 +endfunc + +.macro def_fn_16x16 txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_16x16_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 16, 16, 2 +.endif +.ifc \txfm1, identity + adr x9, inv_txfm_horz_identity_16x8_neon +.else + adr x9, inv_txfm_horz_16x8_neon + adr x4, inv_\txfm1\()_8h_x16_neon +.endif + adr x5, inv_\txfm2\()_8h_x16_neon + mov x13, #\eob_half + b inv_txfm_add_16x16_neon +endfunc +.endm + +def_fn_16x16 dct, dct, 36 +def_fn_16x16 identity, identity, 36 +def_fn_16x16 dct, adst, 36 +def_fn_16x16 dct, flipadst, 36 +def_fn_16x16 dct, identity, 8 +def_fn_16x16 adst, dct, 36 +def_fn_16x16 adst, adst, 36 +def_fn_16x16 adst, flipadst, 36 +def_fn_16x16 flipadst, dct, 36 +def_fn_16x16 flipadst, adst, 36 +def_fn_16x16 flipadst, flipadst, 36 +def_fn_16x16 identity, dct, 8 + +.macro def_fn_416_base variant +function inv_txfm_\variant\()add_16x4_neon + mov x15, x30 + movi v4.8h, #0 + +.ifc \variant, identity_ +.irp i, v16.4h, v17.4h, v18.4h, v19.4h + ld1 {\i}, [x2] + st1 {v4.4h}, [x2], #8 +.endr +.irp i, v16.d, v17.d, v18.d, v19.d + ld1 {\i}[1], [x2] + st1 {v4.4h}, [x2], #8 +.endr + mov w16, #2*(5793-4096)*8 + dup v0.4h, w16 +.irp i, v20.4h, v21.4h, v22.4h, v23.4h + ld1 {\i}, [x2] + st1 {v4.4h}, [x2], #8 +.endr +.irp i, v20.d, v21.d, v22.d, v23.d + ld1 {\i}[1], [x2] + st1 {v4.4h}, [x2], #8 +.endr + + identity_8x16_shift1 v0.h[0] +.else +.irp i, v16.4h, v17.4h, v18.4h, v19.4h, v20.4h, v21.4h, v22.4h, v23.4h, v24.4h, v25.4h, v26.4h, v27.4h, v28.4h, v29.4h, v30.4h, v31.4h + ld1 {\i}, [x2] + st1 {v4.4h}, [x2], #8 +.endr + + blr x4 + + ins v16.d[1], v20.d[0] + ins v17.d[1], v21.d[0] + ins v18.d[1], v22.d[0] + ins v19.d[1], v23.d[0] +.irp i, v16.8h, v17.8h, v18.8h, v19.8h + srshr \i, \i, #1 +.endr +.endif + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + blr x5 + mov x6, x0 + load_add_store_8x4 x6, x7 + +.ifc \variant, identity_ + mov v16.16b, v20.16b + mov v17.16b, v21.16b + mov v18.16b, v22.16b + mov v19.16b, v23.16b +.else + ins v24.d[1], v28.d[0] + ins v25.d[1], v29.d[0] + ins v26.d[1], v30.d[0] + ins v27.d[1], v31.d[0] + srshr v16.8h, v24.8h, #1 + srshr v17.8h, v25.8h, #1 + srshr v18.8h, v26.8h, #1 + srshr v19.8h, v27.8h, #1 +.endif + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + blr x5 + add x6, x0, #8 + load_add_store_8x4 x6, x7 + + ret x15 +endfunc + +function inv_txfm_\variant\()add_4x16_neon + mov x15, x30 + movi v2.8h, #0 + + mov x11, #32 + cmp w3, w13 + b.lt 1f + + add x6, x2, #16 +.ifc \variant, identity_ +.irp i, v24.8h, v25.8h, v26.8h, v27.8h + ld1 {\i}, [x6] + st1 {v2.8h}, [x6], x11 +.endr + mov w16, #(5793-4096)*8 + dup v0.4h, w16 + identity_8x4_shift1 v24, v25, v26, v27, v0.h[0] +.else +.irp i, v16.8h, v17.8h, v18.8h, v19.8h + ld1 {\i}, [x6] + st1 {v2.8h}, [x6], x11 +.endr + blr x4 + srshr v24.8h, v16.8h, #1 + srshr v25.8h, v17.8h, #1 + srshr v26.8h, v18.8h, #1 + srshr v27.8h, v19.8h, #1 +.endif + transpose_4x8h v24, v25, v26, v27, v4, v5, v6, v7 + ins v28.d[0], v24.d[1] + ins v29.d[0], v25.d[1] + ins v30.d[0], v26.d[1] + ins v31.d[0], v27.d[1] + + b 2f +1: +.irp i, v24.4h, v25.4h, v26.4h, v27.4h, v28.4h, v29.4h, v30.4h, v31.4h + movi \i, #0 +.endr +2: + movi v2.8h, #0 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h + ld1 {\i}, [x2] + st1 {v2.8h}, [x2], x11 +.endr +.ifc \variant, identity_ + mov w16, #(5793-4096)*8 + dup v0.4h, w16 + identity_8x4_shift1 v16, v17, v18, v19, v0.h[0] +.else + blr x4 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h + srshr \i, \i, #1 +.endr +.endif + transpose_4x8h v16, v17, v18, v19, v4, v5, v6, v7 + ins v20.d[0], v16.d[1] + ins v21.d[0], v17.d[1] + ins v22.d[0], v18.d[1] + ins v23.d[0], v19.d[1] + + blr x5 + + load_add_store_4x16 x0, x6 + + ret x15 +endfunc +.endm + +def_fn_416_base +def_fn_416_base identity_ + +.macro def_fn_416 w, h, txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif +.if \w == 4 + adr x4, inv_\txfm1\()_8h_x\w\()_neon + adr x5, inv_\txfm2\()_4h_x\h\()_neon + mov w13, #\eob_half +.else + adr x4, inv_\txfm1\()_4h_x\w\()_neon + adr x5, inv_\txfm2\()_8h_x\h\()_neon +.endif +.ifc \txfm1, identity + b inv_txfm_identity_add_\w\()x\h\()_neon +.else + b inv_txfm_add_\w\()x\h\()_neon +.endif +endfunc +.endm + +.macro def_fns_416 w, h +def_fn_416 \w, \h, dct, dct, 29 +def_fn_416 \w, \h, identity, identity, 29 +def_fn_416 \w, \h, dct, adst, 29 +def_fn_416 \w, \h, dct, flipadst, 29 +def_fn_416 \w, \h, dct, identity, 8 +def_fn_416 \w, \h, adst, dct, 29 +def_fn_416 \w, \h, adst, adst, 29 +def_fn_416 \w, \h, adst, flipadst, 29 +def_fn_416 \w, \h, flipadst, dct, 29 +def_fn_416 \w, \h, flipadst, adst, 29 +def_fn_416 \w, \h, flipadst, flipadst, 29 +def_fn_416 \w, \h, identity, dct, 32 +def_fn_416 \w, \h, adst, identity, 8 +def_fn_416 \w, \h, flipadst, identity, 8 +def_fn_416 \w, \h, identity, adst, 32 +def_fn_416 \w, \h, identity, flipadst, 32 +.endm + +def_fns_416 4, 16 +def_fns_416 16, 4 + + +.macro def_fn_816_base variant +function inv_txfm_\variant\()add_16x8_neon + mov x15, x30 + movi v4.8h, #0 + mov w16, #2896*8 + dup v0.4h, w16 + +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + ld1 {\i}, [x2] + st1 {v4.8h}, [x2], #16 +.endr + + scale_input .8h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .8h, v0.h[0], v24, v25, v26, v27, v28, v29, v30, v31 +.ifc \variant, identity_ + mov w16, #2*(5793-4096)*8 + dup v0.4h, w16 + identity_8x16_shift1 v0.h[0] +.else + blr x4 + +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + srshr \i, \i, #1 +.endr +.endif + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v2, v3 + + blr x5 + + mov x6, x0 + load_add_store_8x8 x6, x7 + +.ifc \variant, identity_ + mov v16.16b, v24.16b + mov v17.16b, v25.16b + mov v18.16b, v26.16b + mov v19.16b, v27.16b + mov v20.16b, v28.16b + mov v21.16b, v29.16b + mov v22.16b, v30.16b + mov v23.16b, v31.16b +.else + srshr v16.8h, v24.8h, #1 + srshr v17.8h, v25.8h, #1 + srshr v18.8h, v26.8h, #1 + srshr v19.8h, v27.8h, #1 + srshr v20.8h, v28.8h, #1 + srshr v21.8h, v29.8h, #1 + srshr v22.8h, v30.8h, #1 + srshr v23.8h, v31.8h, #1 +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v2, v3 + + blr x5 + + add x0, x0, #8 + load_add_store_8x8 x0, x7 + + ret x15 +endfunc + +function inv_txfm_\variant\()add_8x16_neon + mov x15, x30 + movi v4.8h, #0 + mov w16, #2896*8 + dup v0.4h, w16 + mov x11, #32 + + cmp w3, w13 + b.lt 1f + + add x6, x2, #16 +.ifc \variant, identity_ +.irp i, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + ld1 {\i}, [x6] + st1 {v4.8h}, [x6], x11 +.endr + scale_input .8h, v0.h[0], v24, v25, v26, v27, v28, v29, v30, v31 + // The identity shl #1 and downshift srshr #1 cancel out +.else +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + ld1 {\i}, [x6] + st1 {v4.8h}, [x6], x11 +.endr + scale_input .8h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + blr x4 + + srshr v24.8h, v16.8h, #1 + srshr v25.8h, v17.8h, #1 + srshr v26.8h, v18.8h, #1 + srshr v27.8h, v19.8h, #1 + srshr v28.8h, v20.8h, #1 + srshr v29.8h, v21.8h, #1 + srshr v30.8h, v22.8h, #1 + srshr v31.8h, v23.8h, #1 +.endif + transpose_8x8h v24, v25, v26, v27, v28, v29, v30, v31, v2, v3 + + b 2f + +1: +.irp i, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + movi \i, #0 +.endr + +2: + movi v4.8h, #0 + mov w16, #2896*8 + dup v0.4h, w16 + +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + ld1 {\i}, [x2] + st1 {v4.8h}, [x2], x11 +.endr + scale_input .8h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 +.ifc \variant, identity_ + // The identity shl #1 and downshift srshr #1 cancel out +.else + blr x4 + +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + srshr \i, \i, #1 +.endr +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v2, v3 + + blr x5 + + load_add_store_8x16 x0, x6 + + ret x15 +endfunc +.endm + +def_fn_816_base +def_fn_816_base identity_ + +.macro def_fn_816 w, h, txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + adr x4, inv_\txfm1\()_8h_x\w\()_neon + adr x5, inv_\txfm2\()_8h_x\h\()_neon +.if \w == 8 + mov x13, #\eob_half +.endif +.ifc \txfm1, identity + b inv_txfm_identity_add_\w\()x\h\()_neon +.else + b inv_txfm_add_\w\()x\h\()_neon +.endif +endfunc +.endm + +.macro def_fns_816 w, h +def_fn_816 \w, \h, dct, dct, 43 +def_fn_816 \w, \h, identity, identity, 43 +def_fn_816 \w, \h, dct, adst, 43 +def_fn_816 \w, \h, dct, flipadst, 43 +def_fn_816 \w, \h, dct, identity, 8 +def_fn_816 \w, \h, adst, dct, 43 +def_fn_816 \w, \h, adst, adst, 43 +def_fn_816 \w, \h, adst, flipadst, 43 +def_fn_816 \w, \h, flipadst, dct, 43 +def_fn_816 \w, \h, flipadst, adst, 43 +def_fn_816 \w, \h, flipadst, flipadst, 43 +def_fn_816 \w, \h, identity, dct, 64 +def_fn_816 \w, \h, adst, identity, 8 +def_fn_816 \w, \h, flipadst, identity, 8 +def_fn_816 \w, \h, identity, adst, 64 +def_fn_816 \w, \h, identity, flipadst, 64 +.endm + +def_fns_816 8, 16 +def_fns_816 16, 8 + +function inv_dct32_odd_8h_x16_neon, export=1 + movrel x16, idct_coeffs, 2*16 + ld1 {v0.8h, v1.8h}, [x16] + sub x16, x16, #2*16 + + smull_smlsl v2, v3, v16, v31, v0.h[0], v0.h[1], .8h // -> t16a + smull_smlal v4, v5, v16, v31, v0.h[1], v0.h[0], .8h // -> t31a + smull_smlsl v6, v7, v24, v23, v0.h[2], v0.h[3], .8h // -> t17a + sqrshrn_sz v16, v2, v3, #12, .8h // t16a + sqrshrn_sz v31, v4, v5, #12, .8h // t31a + smull_smlal v2, v3, v24, v23, v0.h[3], v0.h[2], .8h // -> t30a + smull_smlsl v4, v5, v20, v27, v0.h[4], v0.h[5], .8h // -> t18a + sqrshrn_sz v24, v6, v7, #12, .8h // t17a + sqrshrn_sz v23, v2, v3, #12, .8h // t30a + smull_smlal v6, v7, v20, v27, v0.h[5], v0.h[4], .8h // -> t29a + smull_smlsl v2, v3, v28, v19, v0.h[6], v0.h[7], .8h // -> t19a + sqrshrn_sz v20, v4, v5, #12, .8h // t18a + sqrshrn_sz v27, v6, v7, #12, .8h // t29a + smull_smlal v4, v5, v28, v19, v0.h[7], v0.h[6], .8h // -> t28a + smull_smlsl v6, v7, v18, v29, v1.h[0], v1.h[1], .8h // -> t20a + sqrshrn_sz v28, v2, v3, #12, .8h // t19a + sqrshrn_sz v19, v4, v5, #12, .8h // t28a + smull_smlal v2, v3, v18, v29, v1.h[1], v1.h[0], .8h // -> t27a + smull_smlsl v4, v5, v26, v21, v1.h[2], v1.h[3], .8h // -> t21a + sqrshrn_sz v18, v6, v7, #12, .8h // t20a + sqrshrn_sz v29, v2, v3, #12, .8h // t27a + smull_smlal v6, v7, v26, v21, v1.h[3], v1.h[2], .8h // -> t26a + smull_smlsl v2, v3, v22, v25, v1.h[4], v1.h[5], .8h // -> t22a + sqrshrn_sz v26, v4, v5, #12, .8h // t21a + sqrshrn_sz v21, v6, v7, #12, .8h // t26a + smull_smlal v4, v5, v22, v25, v1.h[5], v1.h[4], .8h // -> t25a + smull_smlsl v6, v7, v30, v17, v1.h[6], v1.h[7], .8h // -> t23a + sqrshrn_sz v22, v2, v3, #12, .8h // t22a + sqrshrn_sz v25, v4, v5, #12, .8h // t25a + smull_smlal v2, v3, v30, v17, v1.h[7], v1.h[6], .8h // -> t24a + sqrshrn_sz v30, v6, v7, #12, .8h // t23a + sqrshrn_sz v17, v2, v3, #12, .8h // t24a + + ld1 {v0.8h}, [x16] + + sqsub v2.8h, v16.8h, v24.8h // t17 + sqadd v16.8h, v16.8h, v24.8h // t16 + sqsub v3.8h, v31.8h, v23.8h // t30 + sqadd v31.8h, v31.8h, v23.8h // t31 + sqsub v24.8h, v28.8h, v20.8h // t18 + sqadd v28.8h, v28.8h, v20.8h // t19 + sqadd v23.8h, v18.8h, v26.8h // t20 + sqsub v18.8h, v18.8h, v26.8h // t21 + sqsub v20.8h, v30.8h, v22.8h // t22 + sqadd v30.8h, v30.8h, v22.8h // t23 + sqadd v26.8h, v17.8h, v25.8h // t24 + sqsub v17.8h, v17.8h, v25.8h // t25 + sqsub v22.8h, v29.8h, v21.8h // t26 + sqadd v29.8h, v29.8h, v21.8h // t27 + sqadd v25.8h, v19.8h, v27.8h // t28 + sqsub v19.8h, v19.8h, v27.8h // t29 + + smull_smlsl v4, v5, v3, v2, v0.h[4], v0.h[5], .8h // -> t17a + smull_smlal v6, v7, v3, v2, v0.h[5], v0.h[4], .8h // -> t30a + smull_smlal v2, v3, v19, v24, v0.h[5], v0.h[4], .8h // -> t18a + sqrshrn_sz v21, v4, v5, #12, .8h // t17a + sqrshrn_sz v27, v6, v7, #12, .8h // t30a + neg v2.4s, v2.4s // -> t18a + neg v3.4s, v3.4s // -> t18a + smull_smlsl v4, v5, v19, v24, v0.h[4], v0.h[5], .8h // -> t29a + smull_smlsl v6, v7, v22, v18, v0.h[6], v0.h[7], .8h // -> t21a + sqrshrn_sz v19, v2, v3, #12, .8h // t18a + sqrshrn_sz v24, v4, v5, #12, .8h // t29a + smull_smlal v2, v3, v22, v18, v0.h[7], v0.h[6], .8h // -> t26a + smull_smlal v4, v5, v17, v20, v0.h[7], v0.h[6], .8h // -> t22a + sqrshrn_sz v22, v6, v7, #12, .8h // t21a + sqrshrn_sz v18, v2, v3, #12, .8h // t26a + neg v4.4s, v4.4s // -> t22a + neg v5.4s, v5.4s // -> t22a + smull_smlsl v6, v7, v17, v20, v0.h[6], v0.h[7], .8h // -> t25a + sqrshrn_sz v17, v4, v5, #12, .8h // t22a + sqrshrn_sz v20, v6, v7, #12, .8h // t25a + + sqsub v2.8h, v27.8h, v24.8h // t29 + sqadd v27.8h, v27.8h, v24.8h // t30 + sqsub v3.8h, v21.8h, v19.8h // t18 + sqadd v21.8h, v21.8h, v19.8h // t17 + sqsub v24.8h, v16.8h, v28.8h // t19a + sqadd v16.8h, v16.8h, v28.8h // t16a + sqsub v19.8h, v30.8h, v23.8h // t20a + sqadd v30.8h, v30.8h, v23.8h // t23a + sqsub v28.8h, v17.8h, v22.8h // t21 + sqadd v17.8h, v17.8h, v22.8h // t22 + sqadd v23.8h, v26.8h, v29.8h // t24a + sqsub v26.8h, v26.8h, v29.8h // t27a + sqadd v22.8h, v20.8h, v18.8h // t25 + sqsub v20.8h, v20.8h, v18.8h // t26 + sqsub v29.8h, v31.8h, v25.8h // t28a + sqadd v31.8h, v31.8h, v25.8h // t31a + + smull_smlsl v4, v5, v2, v3, v0.h[2], v0.h[3], .8h // -> t18a + smull_smlal v6, v7, v2, v3, v0.h[3], v0.h[2], .8h // -> t29a + smull_smlsl v2, v3, v29, v24, v0.h[2], v0.h[3], .8h // -> t19 + sqrshrn_sz v18, v4, v5, #12, .8h // t18a + sqrshrn_sz v25, v6, v7, #12, .8h // t29a + smull_smlal v4, v5, v29, v24, v0.h[3], v0.h[2], .8h // -> t28 + smull_smlal v6, v7, v26, v19, v0.h[3], v0.h[2], .8h // -> t20 + sqrshrn_sz v29, v2, v3, #12, .8h // t19 + sqrshrn_sz v24, v4, v5, #12, .8h // t28 + neg v6.4s, v6.4s // -> t20 + neg v7.4s, v7.4s // -> t20 + smull_smlsl v2, v3, v26, v19, v0.h[2], v0.h[3], .8h // -> t27 + smull_smlal v4, v5, v20, v28, v0.h[3], v0.h[2], .8h // -> t21a + sqrshrn_sz v26, v6, v7, #12, .8h // t20 + sqrshrn_sz v19, v2, v3, #12, .8h // t27 + neg v4.4s, v4.4s // -> t21a + neg v5.4s, v5.4s // -> t21a + smull_smlsl v6, v7, v20, v28, v0.h[2], v0.h[3], .8h // -> t26a + sqrshrn_sz v20, v4, v5, #12, .8h // t21a + sqrshrn_sz v28, v6, v7, #12, .8h // t26a + + sqsub v2.8h, v16.8h, v30.8h // t23 + sqadd v16.8h, v16.8h, v30.8h // t16 = out16 + sqsub v3.8h, v31.8h, v23.8h // t24 + sqadd v31.8h, v31.8h, v23.8h // t31 = out31 + sqsub v23.8h, v21.8h, v17.8h // t22a + sqadd v17.8h, v21.8h, v17.8h // t17a = out17 + sqadd v30.8h, v27.8h, v22.8h // t30a = out30 + sqsub v21.8h, v27.8h, v22.8h // t25a + sqsub v27.8h, v18.8h, v20.8h // t21 + sqadd v18.8h, v18.8h, v20.8h // t18 = out18 + sqadd v4.8h, v29.8h, v26.8h // t19a = out19 + sqsub v26.8h, v29.8h, v26.8h // t20a + sqadd v29.8h, v25.8h, v28.8h // t29 = out29 + sqsub v25.8h, v25.8h, v28.8h // t26 + sqadd v28.8h, v24.8h, v19.8h // t28a = out28 + sqsub v24.8h, v24.8h, v19.8h // t27a + mov v19.16b, v4.16b // out19 + + smull_smlsl v4, v5, v24, v26, v0.h[0], v0.h[0], .8h // -> t20 + smull_smlal v6, v7, v24, v26, v0.h[0], v0.h[0], .8h // -> t27 + sqrshrn_sz v20, v4, v5, #12, .8h // t20 + sqrshrn_sz v22, v6, v7, #12, .8h // t27 + + smull_smlal v4, v5, v25, v27, v0.h[0], v0.h[0], .8h // -> t26a + smull_smlsl v6, v7, v25, v27, v0.h[0], v0.h[0], .8h // -> t21a + mov v27.16b, v22.16b // t27 + sqrshrn_sz v26, v4, v5, #12, .8h // t26a + + smull_smlsl v24, v25, v21, v23, v0.h[0], v0.h[0], .8h // -> t22 + smull_smlal v4, v5, v21, v23, v0.h[0], v0.h[0], .8h // -> t25 + sqrshrn_sz v21, v6, v7, #12, .8h // t21a + sqrshrn_sz v22, v24, v25, #12, .8h // t22 + sqrshrn_sz v25, v4, v5, #12, .8h // t25 + + smull_smlsl v4, v5, v3, v2, v0.h[0], v0.h[0], .8h // -> t23a + smull_smlal v6, v7, v3, v2, v0.h[0], v0.h[0], .8h // -> t24a + sqrshrn_sz v23, v4, v5, #12, .8h // t23a + sqrshrn_sz v24, v6, v7, #12, .8h // t24a + + ret +endfunc + +.macro def_horz_32 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_dct_32x8_neon + mov x14, x30 + movi v7.8h, #0 + lsl x8, x8, #1 +.if \scale + mov w16, #2896*8 + dup v0.4h, w16 +.endif + +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + ld1 {\i}, [x7] + st1 {v7.8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + add x7, x7, x8, lsr #1 +.if \scale + scale_input .8h, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .8h, v0.h[0], v24, v25, v26, v27, v28, v29, v30, v31 +.endif + bl inv_dct_8h_x16_neon + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + transpose_8x8h v24, v25, v26, v27, v28, v29, v30, v31, v4, v5 + +.macro store1 r0, r1 + st1 {\r0}, [x6], #16 + st1 {\r1}, [x6], #16 + add x6, x6, #32 +.endm + store1 v16.8h, v24.8h + store1 v17.8h, v25.8h + store1 v18.8h, v26.8h + store1 v19.8h, v27.8h + store1 v20.8h, v28.8h + store1 v21.8h, v29.8h + store1 v22.8h, v30.8h + store1 v23.8h, v31.8h +.purgem store1 + sub x6, x6, #64*8 + + movi v7.8h, #0 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + ld1 {\i}, [x7] + st1 {v7.8h}, [x7], x8 +.endr +.if \scale + // This relies on the fact that the idct also leaves the right coeff in v0.h[1] + scale_input .8h, v0.h[1], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .8h, v0.h[1], v24, v25, v26, v27, v28, v29, v30, v31 +.endif + bl inv_dct32_odd_8h_x16_neon + transpose_8x8h v31, v30, v29, v28, v27, v26, v25, v24, v4, v5 + transpose_8x8h v23, v22, v21, v20, v19, v18, v17, v16, v4, v5 +.macro store2 r0, r1, shift + ld1 {v4.8h, v5.8h}, [x6] + sqsub v7.8h, v4.8h, \r0 + sqsub v6.8h, v5.8h, \r1 + sqadd v4.8h, v4.8h, \r0 + sqadd v5.8h, v5.8h, \r1 + rev64 v6.8h, v6.8h + rev64 v7.8h, v7.8h + srshr v4.8h, v4.8h, #\shift + srshr v5.8h, v5.8h, #\shift + srshr v6.8h, v6.8h, #\shift + srshr v7.8h, v7.8h, #\shift + ext v6.16b, v6.16b, v6.16b, #8 + st1 {v4.8h, v5.8h}, [x6], #32 + ext v7.16b, v7.16b, v7.16b, #8 + st1 {v6.8h, v7.8h}, [x6], #32 +.endm + + store2 v31.8h, v23.8h, \shift + store2 v30.8h, v22.8h, \shift + store2 v29.8h, v21.8h, \shift + store2 v28.8h, v20.8h, \shift + store2 v27.8h, v19.8h, \shift + store2 v26.8h, v18.8h, \shift + store2 v25.8h, v17.8h, \shift + store2 v24.8h, v16.8h, \shift +.purgem store2 + ret x14 +endfunc +.endm + +def_horz_32 scale=0, shift=2 +def_horz_32 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_dct_8x32_neon + mov x14, x30 + lsl x8, x8, #1 + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + + bl inv_dct_8h_x16_neon + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + st1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + add x7, x7, x8, lsr #1 + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + sub x7, x7, x8, lsr #1 + bl inv_dct32_odd_8h_x16_neon + + neg x9, x8 + mov x10, x6 +.macro combine r0, r1, r2, r3, op, stride + ld1 {v5.8h}, [x7], \stride + ld1 {v2.8b}, [x10], x1 + ld1 {v6.8h}, [x7], \stride + ld1 {v3.8b}, [x10], x1 + \op v5.8h, v5.8h, \r0 + ld1 {v7.8h}, [x7], \stride + ld1 {v4.8b}, [x10], x1 + srshr v5.8h, v5.8h, #4 + \op v6.8h, v6.8h, \r1 + uaddw v5.8h, v5.8h, v2.8b + srshr v6.8h, v6.8h, #4 + \op v7.8h, v7.8h, \r2 + sqxtun v2.8b, v5.8h + ld1 {v5.8h}, [x7], \stride + uaddw v6.8h, v6.8h, v3.8b + srshr v7.8h, v7.8h, #4 + \op v5.8h, v5.8h, \r3 + st1 {v2.8b}, [x6], x1 + ld1 {v2.8b}, [x10], x1 + sqxtun v3.8b, v6.8h + uaddw v7.8h, v7.8h, v4.8b + srshr v5.8h, v5.8h, #4 + st1 {v3.8b}, [x6], x1 + sqxtun v4.8b, v7.8h + uaddw v5.8h, v5.8h, v2.8b + st1 {v4.8b}, [x6], x1 + sqxtun v2.8b, v5.8h + st1 {v2.8b}, [x6], x1 +.endm + combine v31.8h, v30.8h, v29.8h, v28.8h, sqadd, x8 + combine v27.8h, v26.8h, v25.8h, v24.8h, sqadd, x8 + combine v23.8h, v22.8h, v21.8h, v20.8h, sqadd, x8 + combine v19.8h, v18.8h, v17.8h, v16.8h, sqadd, x8 + sub x7, x7, x8 + combine v16.8h, v17.8h, v18.8h, v19.8h, sqsub, x9 + combine v20.8h, v21.8h, v22.8h, v23.8h, sqsub, x9 + combine v24.8h, v25.8h, v26.8h, v27.8h, sqsub, x9 + combine v28.8h, v29.8h, v30.8h, v31.8h, sqsub, x9 +.purgem combine + + ret x14 +endfunc + +const eob_32x32 + .short 36, 136, 300, 1024 +endconst + +const eob_16x32 + .short 36, 151, 279, 512 +endconst + +const eob_16x32_shortside + .short 36, 512 +endconst + +const eob_8x32 + .short 43, 107, 171, 256 +endconst + +function inv_txfm_add_identity_identity_32x32_8bpc_neon, export=1 + movi v0.8h, #0 + movrel x13, eob_32x32 + + mov x8, #2*32 +1: + mov w9, #0 + movrel x12, eob_32x32 +2: + add w9, w9, #8 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + ld1 {v\i\().8h}, [x2] + st1 {v0.8h}, [x2], x8 +.endr + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + + load_add_store_8x8 x0, x7, shiftbits=2 + ldrh w11, [x12], #2 + sub x0, x0, x1, lsl #3 + add x0, x0, #8 + cmp w3, w11 + b.ge 2b + + ldrh w11, [x13], #2 + cmp w3, w11 + b.lt 9f + + sub x0, x0, w9, uxtw + add x0, x0, x1, lsl #3 + msub x2, x8, x9, x2 + add x2, x2, #2*8 + b 1b +9: + ret +endfunc + +.macro shift_8_regs op, shift +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + \op \i, \i, #\shift +.endr +.endm + +.macro def_identity_1632 w, h, wshort, hshort +function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1 + mov w16, #2896*8 + mov w17, #2*(5793-4096)*8 + dup v1.4h, w16 + movi v0.8h, #0 + mov v1.h[1], w17 + movrel x13, eob_16x32\hshort + + mov x8, #2*\h +1: + mov w9, #0 + movrel x12, eob_16x32\wshort +2: + add w9, w9, #8 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + ld1 {\i}, [x2] + st1 {v0.8h}, [x2], x8 +.endr + scale_input .8h, v1.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + +.if \w == 16 + // 16x32 + identity_8x8_shift1 v1.h[1] +.else + // 32x16 + shift_8_regs sqshl, 1 + identity_8x8 v1.h[1] +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + +.if \w == 16 + load_add_store_8x8 x0, x7, shiftbits=2 +.else + load_add_store_8x8 x0, x7, shiftbits=4 +.endif + ldrh w11, [x12], #2 + sub x0, x0, x1, lsl #3 + add x0, x0, #8 + cmp w3, w11 + b.ge 2b + + ldrh w11, [x13], #2 + cmp w3, w11 + b.lt 9f + + sub x0, x0, w9, uxtw + add x0, x0, x1, lsl #3 + msub x2, x8, x9, x2 + add x2, x2, #2*8 + b 1b +9: + ret +endfunc +.endm + +def_identity_1632 16, 32, _shortside, +def_identity_1632 32, 16, , _shortside + +.macro def_identity_832 w, h +function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1 + movi v0.8h, #0 + movrel x13, eob_8x32 + + mov w8, #2*\h +1: + ldrh w12, [x13], #2 +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h + ld1 {\i}, [x2] + st1 {v0.8h}, [x2], x8 +.endr + +.if \w == 8 + // 8x32 + shift_8_regs srshr, 1 +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + + cmp w3, w12 +.if \w == 8 + load_add_store_8x8 x0, x7, shiftbits=2 +.else + load_add_store_8x8 x0, x7, shiftbits=3 +.endif + + b.lt 9f +.if \w == 8 + sub x2, x2, x8, lsl #3 + add x2, x2, #2*8 +.else + sub x0, x0, x1, lsl #3 + add x0, x0, #8 +.endif + b 1b + +9: + ret +endfunc +.endm + +def_identity_832 8, 32 +def_identity_832 32, 8 + +function inv_txfm_add_dct_dct_32x32_8bpc_neon, export=1 + idct_dc 32, 32, 2 + + mov x15, x30 + sub sp, sp, #2048 + movrel x13, eob_32x32 + ldrh w12, [x13], #2 + +.irp i, 0, 8, 16, 24 + add x6, sp, #(\i*32*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*2) + mov x8, #32*2 + bl inv_txfm_horz_dct_32x8_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x6, x0, #(\i) + add x7, sp, #(\i*2) + mov x8, #32*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, sp, #2048 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_16x32_8bpc_neon, export=1 + idct_dc 16, 32, 1 + + mov x15, x30 + sub sp, sp, #1024 + movrel x13, eob_16x32 + ldrh w12, [x13], #2 + adr x4, inv_dct_8h_x16_neon + +.irp i, 0, 8, 16, 24 + add x6, sp, #(\i*16*2) + add x7, x2, #(\i*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endif + mov x8, #2*32 + bl inv_txfm_horz_scale_16x8_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #8 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8 + add x6, x0, #(\i) + add x7, sp, #(\i*2) + mov x8, #16*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, sp, #1024 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x16_8bpc_neon, export=1 + idct_dc 32, 16, 1 + + mov x15, x30 + sub sp, sp, #1024 + + adr x5, inv_dct_8h_x16_neon + +.irp i, 0, 8 + add x6, sp, #(\i*32*2) + add x7, x2, #(\i*2) +.if \i > 0 + mov w8, #(16 - \i) + cmp w3, #36 + b.lt 1f +.endif + mov x8, #2*16 + bl inv_txfm_horz_scale_dct_32x8_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x6, x0, #(\i) + add x7, sp, #(\i*2) + mov x8, #32*2 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, sp, #1024 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_8x32_8bpc_neon, export=1 + idct_dc 8, 32, 2 + + mov x15, x30 + sub sp, sp, #512 + + movrel x13, eob_8x32 + + movi v28.8h, #0 + mov x8, #2*32 + mov w9, #32 + mov x6, sp +1: +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + ld1 {v\i\().8h}, [x2] + st1 {v28.8h}, [x2], x8 +.endr + ldrh w12, [x13], #2 + sub x2, x2, x8, lsl #3 + sub w9, w9, #8 + add x2, x2, #2*8 + + bl inv_dct_8h_x8_neon + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + srshr v\i\().8h, v\i\().8h, #2 +.endr + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 + + st1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x6], #64 + cmp w3, w12 + st1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x6], #64 + + b.ge 1b + cbz w9, 3f + + movi v29.8h, #0 + movi v30.8h, #0 + movi v31.8h, #0 +2: + subs w9, w9, #8 +.rept 2 + st1 {v28.8h,v29.8h,v30.8h,v31.8h}, [x6], #64 +.endr + b.gt 2b + +3: + mov x6, x0 + mov x7, sp + mov x8, #8*2 + bl inv_txfm_add_vert_dct_8x32_neon + + add sp, sp, #512 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x8_8bpc_neon, export=1 + idct_dc 32, 8, 2 + + mov x15, x30 + sub sp, sp, #512 + + mov x6, sp + mov x7, x2 + mov x8, #8*2 + bl inv_txfm_horz_dct_32x8_neon + + mov x8, #2*32 + mov w9, #0 +1: + add x6, x0, x9 + add x7, sp, x9, lsl #1 // #(\i*2) + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + ld1 {v\i\().8h}, [x7], x8 +.endr + add w9, w9, #8 + + bl inv_dct_8h_x8_neon + + cmp w9, #32 + + load_add_store_8x8 x6, x7 + + b.lt 1b + + add sp, sp, #512 + ret x15 +endfunc + +function inv_dct64_step1_neon + // in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + // in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + // in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + // in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + + ld1 {v0.8h, v1.8h}, [x17], #32 + + sqrdmulh v23.8h, v16.8h, v0.h[1] // t63a + sqrdmulh v16.8h, v16.8h, v0.h[0] // t32a + sqrdmulh v22.8h, v17.8h, v0.h[2] // t62a + sqrdmulh v17.8h, v17.8h, v0.h[3] // t33a + sqrdmulh v21.8h, v18.8h, v0.h[5] // t61a + sqrdmulh v18.8h, v18.8h, v0.h[4] // t34a + sqrdmulh v20.8h, v19.8h, v0.h[6] // t60a + sqrdmulh v19.8h, v19.8h, v0.h[7] // t35a + + sqadd v24.8h, v16.8h, v17.8h // t32 + sqsub v25.8h, v16.8h, v17.8h // t33 + sqsub v26.8h, v19.8h, v18.8h // t34 + sqadd v27.8h, v19.8h, v18.8h // t35 + sqadd v28.8h, v20.8h, v21.8h // t60 + sqsub v29.8h, v20.8h, v21.8h // t61 + sqsub v30.8h, v23.8h, v22.8h // t62 + sqadd v31.8h, v23.8h, v22.8h // t63 + + smull_smlal v2, v3, v29, v26, v1.h[0], v1.h[1], .8h // -> t34a + smull_smlsl v4, v5, v29, v26, v1.h[1], v1.h[0], .8h // -> t61a + neg v2.4s, v2.4s // t34a + neg v3.4s, v3.4s // t34a + smull_smlsl v6, v7, v30, v25, v1.h[1], v1.h[0], .8h // -> t33a + sqrshrn_sz v26, v2, v3, #12, .8h // t34a + smull_smlal v2, v3, v30, v25, v1.h[0], v1.h[1], .8h // -> t62a + sqrshrn_sz v29, v4, v5, #12, .8h // t61a + sqrshrn_sz v25, v6, v7, #12, .8h // t33a + sqrshrn_sz v30, v2, v3, #12, .8h // t62a + + sqadd v16.8h, v24.8h, v27.8h // t32a + sqsub v19.8h, v24.8h, v27.8h // t35a + sqadd v17.8h, v25.8h, v26.8h // t33 + sqsub v18.8h, v25.8h, v26.8h // t34 + sqsub v20.8h, v31.8h, v28.8h // t60a + sqadd v23.8h, v31.8h, v28.8h // t63a + sqsub v21.8h, v30.8h, v29.8h // t61 + sqadd v22.8h, v30.8h, v29.8h // t62 + + smull_smlal v2, v3, v21, v18, v1.h[2], v1.h[3], .8h // -> t61a + smull_smlsl v4, v5, v21, v18, v1.h[3], v1.h[2], .8h // -> t34a + smull_smlal v6, v7, v20, v19, v1.h[2], v1.h[3], .8h // -> t60 + sqrshrn_sz v21, v2, v3, #12, .8h // t61a + sqrshrn_sz v18, v4, v5, #12, .8h // t34a + smull_smlsl v2, v3, v20, v19, v1.h[3], v1.h[2], .8h // -> t35 + sqrshrn_sz v20, v6, v7, #12, .8h // t60 + sqrshrn_sz v19, v2, v3, #12, .8h // t35 + + st1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x6], #64 + st1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x6], #64 + + ret +endfunc + +function inv_dct64_step2_neon + movrel x16, idct_coeffs + ld1 {v0.4h}, [x16] +1: + // t32a/33/34a/35/60/61a/62/63a + // t56a/57/58a/59/36/37a/38/39a + // t40a/41/42a/43/52/53a/54/55a + // t48a/49/50a/51/44/45a/46/47a + ldr q16, [x6, #2*8*0] // t32a + ldr q17, [x9, #2*8*8] // t39a + ldr q18, [x9, #2*8*0] // t63a + ldr q19, [x6, #2*8*8] // t56a + ldr q20, [x6, #2*8*16] // t40a + ldr q21, [x9, #2*8*24] // t47a + ldr q22, [x9, #2*8*16] // t55a + ldr q23, [x6, #2*8*24] // t48a + + sqadd v24.8h, v16.8h, v17.8h // t32 + sqsub v25.8h, v16.8h, v17.8h // t39 + sqadd v26.8h, v18.8h, v19.8h // t63 + sqsub v27.8h, v18.8h, v19.8h // t56 + sqsub v28.8h, v21.8h, v20.8h // t40 + sqadd v29.8h, v21.8h, v20.8h // t47 + sqadd v30.8h, v23.8h, v22.8h // t48 + sqsub v31.8h, v23.8h, v22.8h // t55 + + smull_smlal v2, v3, v27, v25, v0.h[3], v0.h[2], .8h // -> t56a + smull_smlsl v4, v5, v27, v25, v0.h[2], v0.h[3], .8h // -> t39a + smull_smlal v6, v7, v31, v28, v0.h[3], v0.h[2], .8h // -> t40a + sqrshrn_sz v25, v2, v3, #12, .8h // t56a + sqrshrn_sz v27, v4, v5, #12, .8h // t39a + neg v6.4s, v6.4s // t40a + neg v7.4s, v7.4s // t40a + smull_smlsl v2, v3, v31, v28, v0.h[2], v0.h[3], .8h // -> t55a + sqrshrn_sz v31, v6, v7, #12, .8h // t40a + sqrshrn_sz v28, v2, v3, #12, .8h // t55a + + sqadd v16.8h, v24.8h, v29.8h // t32a + sqsub v19.8h, v24.8h, v29.8h // t47a + sqadd v17.8h, v27.8h, v31.8h // t39 + sqsub v18.8h, v27.8h, v31.8h // t40 + sqsub v20.8h, v26.8h, v30.8h // t48a + sqadd v23.8h, v26.8h, v30.8h // t63a + sqsub v21.8h, v25.8h, v28.8h // t55 + sqadd v22.8h, v25.8h, v28.8h // t56 + + smull_smlsl v2, v3, v21, v18, v0.h[0], v0.h[0], .8h // -> t40a + smull_smlal v4, v5, v21, v18, v0.h[0], v0.h[0], .8h // -> t55a + smull_smlsl v6, v7, v20, v19, v0.h[0], v0.h[0], .8h // -> t47 + sqrshrn_sz v18, v2, v3, #12, .8h // t40a + sqrshrn_sz v21, v4, v5, #12, .8h // t55a + smull_smlal v2, v3, v20, v19, v0.h[0], v0.h[0], .8h // -> t48 + sqrshrn_sz v19, v6, v7, #12, .8h // t47 + sqrshrn_sz v20, v2, v3, #12, .8h // t48 + + str q16, [x6, #2*8*0] // t32a + str q17, [x9, #2*8*0] // t39 + str q18, [x6, #2*8*8] // t40a + str q19, [x9, #2*8*8] // t47 + str q20, [x6, #2*8*16] // t48 + str q21, [x9, #2*8*16] // t55a + str q22, [x6, #2*8*24] // t56 + str q23, [x9, #2*8*24] // t63a + + add x6, x6, #2*8 + sub x9, x9, #2*8 + cmp x6, x9 + b.lt 1b + ret +endfunc + +.macro load8 src, strd, zero, clear +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h +.if \clear + ld1 {\i}, [\src] + st1 {\zero}, [\src], \strd +.else + ld1 {\i}, [\src], \strd +.endif +.endr +.endm + +.macro store16 dst +.irp i, v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + st1 {\i}, [\dst], #16 +.endr +.endm + +.macro clear_upper8 +.irp i, v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h + movi \i, #0 +.endr +.endm + +.macro movi_if reg, val, cond +.if \cond + movi \reg, \val +.endif +.endm + +.macro movdup_if reg, gpr, val, cond +.if \cond + mov \gpr, \val + dup \reg, \gpr +.endif +.endm + +.macro st1_if regs, dst, cond +.if \cond + st1 \regs, \dst +.endif +.endm + +.macro str_if reg, dst, cond +.if \cond + str \reg, \dst +.endif +.endm + +.macro stroff_if reg, dst, dstoff, cond +.if \cond + str \reg, \dst, \dstoff +.endif +.endm + +.macro scale_if cond, c, r0, r1, r2, r3, r4, r5, r6, r7 +.if \cond + scale_input .8h, \c, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endif +.endm + +.macro def_dct64_func suffix, clear=0, scale=0 +function inv_txfm_dct\suffix\()_8h_x64_neon, export=1 + mov x14, x30 + mov x6, sp + lsl x8, x8, #2 + + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + load8 x7, x8, v7.8h, \clear + clear_upper8 + sub x7, x7, x8, lsl #3 + add x7, x7, x8, lsr #1 + scale_if \scale, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + + bl inv_dct_8h_x16_neon + + store16 x6 + + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + load8 x7, x8, v7.8h, \clear + clear_upper8 + sub x7, x7, x8, lsl #3 + lsr x8, x8, #1 + sub x7, x7, x8, lsr #1 + scale_if \scale, v0.h[0], v16, v17, v18, v19, v20, v21, v22, v23 + + bl inv_dct32_odd_8h_x16_neon + + add x10, x6, #16*15 + sub x6, x6, #16*16 + + mov x9, #-16 + +.macro store_addsub r0, r1, r2, r3 + ld1 {v2.8h}, [x6], #16 + ld1 {v3.8h}, [x6], #16 + sqadd v6.8h, v2.8h, \r0 + sqsub \r0, v2.8h, \r0 + ld1 {v4.8h}, [x6], #16 + sqadd v7.8h, v3.8h, \r1 + sqsub \r1, v3.8h, \r1 + ld1 {v5.8h}, [x6], #16 + sqadd v2.8h, v4.8h, \r2 + sub x6, x6, #16*4 + sqsub \r2, v4.8h, \r2 + st1 {v6.8h}, [x6], #16 + st1 {\r0}, [x10], x9 + sqadd v3.8h, v5.8h, \r3 + sqsub \r3, v5.8h, \r3 + st1 {v7.8h}, [x6], #16 + st1 {\r1}, [x10], x9 + st1 {v2.8h}, [x6], #16 + st1 {\r2}, [x10], x9 + st1 {v3.8h}, [x6], #16 + st1 {\r3}, [x10], x9 +.endm + store_addsub v31.8h, v30.8h, v29.8h, v28.8h + store_addsub v27.8h, v26.8h, v25.8h, v24.8h + store_addsub v23.8h, v22.8h, v21.8h, v20.8h + store_addsub v19.8h, v18.8h, v17.8h, v16.8h +.purgem store_addsub + + add x6, x6, #2*8*16 + + movrel x17, idct64_coeffs + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + add x9, x7, x8, lsl #4 // offset 16 + add x10, x7, x8, lsl #3 // offset 8 + sub x9, x9, x8 // offset 15 + sub x11, x10, x8 // offset 7 + ld1 {v16.8h}, [x7] // in1 (offset 0) + ld1 {v17.8h}, [x9] // in31 (offset 15) + ld1 {v18.8h}, [x10] // in17 (offset 8) + ld1 {v19.8h}, [x11] // in15 (offset 7) + st1_if {v7.8h}, [x7], \clear + st1_if {v7.8h}, [x9], \clear + st1_if {v7.8h}, [x10], \clear + st1_if {v7.8h}, [x11], \clear + scale_if \scale, v0.h[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + add x7, x7, x8, lsl #2 // offset 4 + sub x9, x9, x8, lsl #2 // offset 11 + sub x10, x7, x8 // offset 3 + add x11, x9, x8 // offset 12 + ld1 {v16.8h}, [x10] // in7 (offset 3) + ld1 {v17.8h}, [x11] // in25 (offset 12) + ld1 {v18.8h}, [x9] // in23 (offset 11) + ld1 {v19.8h}, [x7] // in9 (offset 4) + st1_if {v7.8h}, [x7], \clear + st1_if {v7.8h}, [x9], \clear + st1_if {v7.8h}, [x10], \clear + st1_if {v7.8h}, [x11], \clear + scale_if \scale, v0.h[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + sub x10, x10, x8, lsl #1 // offset 1 + sub x9, x9, x8, lsl #1 // offset 9 + add x7, x7, x8 // offset 5 + add x11, x11, x8 // offset 13 + ldr q16, [x10, x8] // in5 (offset 2) + ldr q17, [x11] // in27 (offset 13) + ldr q18, [x9, x8] // in21 (offset 10) + ldr q19, [x7] // in11 (offset 5) + stroff_if q7, [x10, x8], \clear + str_if q7, [x11], \clear + stroff_if q7, [x9, x8], \clear + str_if q7, [x7], \clear + scale_if \scale, v0.h[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movdup_if v0.4h, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + ldr q16, [x10] // in3 (offset 1) + ldr q17, [x11, x8] // in29 (offset 14) + ldr q18, [x9] // in19 (offset 9) + ldr q19, [x7, x8] // in13 (offset 6) + str_if q7, [x10], \clear + stroff_if q7, [x11, x8], \clear + str_if q7, [x9], \clear + stroff_if q7, [x7, x8], \clear + scale_if \scale, v0.h[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + + sub x6, x6, #2*8*32 + add x9, x6, #2*8*7 + + bl inv_dct64_step2_neon + + ret x14 +endfunc +.endm + +def_dct64_func +def_dct64_func _clear, clear=1 +def_dct64_func _clear_scale, clear=1, scale=1 + + +function inv_txfm_horz_dct_64x8_neon + mov x14, x30 + + mov x7, sp + add x8, sp, #2*8*(64 - 4) + add x9, x6, #2*56 + mov x10, #2*64 + mov x11, #-2*8*4 + + dup v7.8h, w12 +1: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x7], #64 + ld1 {v28.8h, v29.8h, v30.8h, v31.8h}, [x8], x11 + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x7], #64 + ld1 {v24.8h, v25.8h, v26.8h, v27.8h}, [x8], x11 + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + transpose_8x8h v31, v30, v29, v28, v27, v26, v25, v24, v4, v5 + +.macro store_addsub src0, src1, src2, src3 + sqsub v1.8h, \src0, \src1 + sqadd v0.8h, \src0, \src1 + sqsub v3.8h, \src2, \src3 + srshl v1.8h, v1.8h, v7.8h + sqadd v2.8h, \src2, \src3 + srshl v0.8h, v0.8h, v7.8h + srshl v3.8h, v3.8h, v7.8h + rev64 v1.8h, v1.8h + srshl v2.8h, v2.8h, v7.8h + rev64 v3.8h, v3.8h + ext v1.16b, v1.16b, v1.16b, #8 + st1 {v0.8h}, [x6], x10 + ext v3.16b, v3.16b, v3.16b, #8 + st1 {v1.8h}, [x9], x10 + st1 {v2.8h}, [x6], x10 + st1 {v3.8h}, [x9], x10 +.endm + store_addsub v16.8h, v31.8h, v17.8h, v30.8h + store_addsub v18.8h, v29.8h, v19.8h, v28.8h + store_addsub v20.8h, v27.8h, v21.8h, v26.8h + store_addsub v22.8h, v25.8h, v23.8h, v24.8h +.purgem store_addsub + sub x6, x6, x10, lsl #3 + sub x9, x9, x10, lsl #3 + add x6, x6, #16 + sub x9, x9, #16 + + cmp x7, x8 + b.lt 1b + ret x14 +endfunc + +function inv_txfm_add_vert_dct_8x64_neon + mov x14, x30 + lsl x8, x8, #1 + + mov x7, sp + add x8, sp, #2*8*(64 - 4) + add x9, x6, x1, lsl #6 + sub x9, x9, x1 + neg x10, x1 + mov x11, #-2*8*4 + +1: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x7], #64 + ld1 {v28.8h, v29.8h, v30.8h, v31.8h}, [x8], x11 + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x7], #64 + ld1 {v24.8h, v25.8h, v26.8h, v27.8h}, [x8], x11 + +.macro add_dest_addsub src0, src1, src2, src3 + ld1 {v0.8b}, [x6], x1 + ld1 {v1.8b}, [x9], x10 + sqadd v4.8h, \src0, \src1 + ld1 {v2.8b}, [x6] + sqsub v5.8h, \src0, \src1 + ld1 {v3.8b}, [x9] + sqadd v6.8h, \src2, \src3 + sqsub v7.8h, \src2, \src3 + sub x6, x6, x1 + sub x9, x9, x10 + srshr v4.8h, v4.8h, #4 + srshr v5.8h, v5.8h, #4 + srshr v6.8h, v6.8h, #4 + uaddw v4.8h, v4.8h, v0.8b + srshr v7.8h, v7.8h, #4 + uaddw v5.8h, v5.8h, v1.8b + uaddw v6.8h, v6.8h, v2.8b + sqxtun v0.8b, v4.8h + uaddw v7.8h, v7.8h, v3.8b + sqxtun v1.8b, v5.8h + st1 {v0.8b}, [x6], x1 + sqxtun v2.8b, v6.8h + st1 {v1.8b}, [x9], x10 + sqxtun v3.8b, v7.8h + st1 {v2.8b}, [x6], x1 + st1 {v3.8b}, [x9], x10 +.endm + add_dest_addsub v16.8h, v31.8h, v17.8h, v30.8h + add_dest_addsub v18.8h, v29.8h, v19.8h, v28.8h + add_dest_addsub v20.8h, v27.8h, v21.8h, v26.8h + add_dest_addsub v22.8h, v25.8h, v23.8h, v24.8h +.purgem add_dest_addsub + cmp x7, x8 + b.lt 1b + + ret x14 +endfunc + +function inv_txfm_add_dct_dct_64x64_8bpc_neon, export=1 + idct_dc 64, 64, 2 + + mov x15, x30 + + sub_sp 64*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_32x32 + +.irp i, 0, 8, 16, 24 + add x6, x5, #(\i*64*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*2) + mov x8, #32*2 + mov x12, #-2 // shift + bl inv_txfm_dct_clear_8h_x64_neon + add x6, x5, #(\i*64*2) + bl inv_txfm_horz_dct_64x8_neon +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x7, x5, #(\i*2) + mov x8, #64*2 + bl inv_txfm_dct_8h_x64_neon + add x6, x0, #(\i) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #64*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_64x32_8bpc_neon, export=1 + idct_dc 64, 32, 1 + + mov x15, x30 + + sub_sp 64*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_32x32 + +.irp i, 0, 8, 16, 24 + add x6, x5, #(\i*64*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*2) + mov x8, #32*2 + mov x12, #-1 // shift + bl inv_txfm_dct_clear_scale_8h_x64_neon + add x6, x5, #(\i*64*2) + bl inv_txfm_horz_dct_64x8_neon +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x6, x0, #(\i) + add x7, x5, #(\i*2) + mov x8, #64*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, x5, #64*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x64_8bpc_neon, export=1 + idct_dc 32, 64, 1 + + mov x15, x30 + + sub_sp 32*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_32x32 + ldrh w12, [x13], #2 + +.irp i, 0, 8, 16, 24 + add x6, x5, #(\i*32*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*2) + mov x8, #32*2 + bl inv_txfm_horz_scale_dct_32x8_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x7, x5, #(\i*2) + mov x8, #32*2 + bl inv_txfm_dct_8h_x64_neon + add x6, x0, #(\i) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #32*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_64x16_8bpc_neon, export=1 + idct_dc 64, 16, 2 + + mov x15, x30 + + sub_sp 64*16*2+64*8*2 + add x4, sp, #64*8*2 + + movrel x13, eob_16x32 + +.irp i, 0, 8 + add x6, x4, #(\i*64*2) +.if \i > 0 + mov w8, #(16 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*2) + mov x8, #16*2 + mov x12, #-2 // shift + bl inv_txfm_dct_clear_8h_x64_neon + add x6, x4, #(\i*64*2) + bl inv_txfm_horz_dct_64x8_neon +.if \i < 8 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: + adr x5, inv_dct_8h_x16_neon +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x6, x0, #(\i) + add x7, x4, #(\i*2) + mov x8, #64*2 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, x4, #64*16*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_16x64_8bpc_neon, export=1 + idct_dc 16, 64, 2 + + mov x15, x30 + + sub_sp 16*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_16x32 + ldrh w12, [x13], #2 + + adr x4, inv_dct_8h_x16_neon +.irp i, 0, 8, 16, 24 + add x6, x5, #(\i*16*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 24 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*2) + mov x8, #32*2 + bl inv_txfm_horz_16x8_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #8 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8 + add x7, x5, #(\i*2) + mov x8, #16*2 + bl inv_txfm_dct_8h_x64_neon + add x6, x0, #(\i) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #16*32*2 + ret x15 +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/itx16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/itx16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/itx16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3648 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "src/arm/asm.S" +#include "util.S" + +// The exported functions in this file have got the following signature: +// void itxfm_add(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob, +// int bitdepth_max); + +// Most of the functions use the following register layout: +// x0-x3 external parameters +// x4 function pointer to first transform +// x5 function pointer to second transform +// x6 output parameter for helper function +// x7 input parameter for helper function +// x8 input stride for helper function +// x9-x12 scratch variables for helper functions +// x13 pointer to list of eob thresholds +// x14 return pointer for helper function +// x15 return pointer for main function + +// The SIMD registers most often use the following layout: +// v0-v1 multiplication coefficients +// v2-v7 scratch registers +// v8-v15 unused +// v16-v31 inputs/outputs of transforms + +const idct_coeffs, align=4 + // idct4 + .int 2896, 2896*8*(1<<16), 1567, 3784 + // idct8 + .int 799, 4017, 3406, 2276 + // idct16 + .int 401, 4076, 3166, 2598 + .int 1931, 3612, 3920, 1189 + // idct32 + .int 201, 4091, 3035, 2751 + .int 1751, 3703, 3857, 1380 + .int 995, 3973, 3513, 2106 + .int 2440, 3290, 4052, 601 +endconst + +const idct64_coeffs, align=4 + .int 101*8*(1<<16), 4095*8*(1<<16), 2967*8*(1<<16), -2824*8*(1<<16) + .int 1660*8*(1<<16), 3745*8*(1<<16), 3822*8*(1<<16), -1474*8*(1<<16) + .int 4076, 401, 4017, 799 + + .int 4036*8*(1<<16), -700*8*(1<<16), 2359*8*(1<<16), 3349*8*(1<<16) + .int 3461*8*(1<<16), -2191*8*(1<<16), 897*8*(1<<16), 3996*8*(1<<16) + .int -3166, -2598, -799, -4017 + + .int 501*8*(1<<16), 4065*8*(1<<16), 3229*8*(1<<16), -2520*8*(1<<16) + .int 2019*8*(1<<16), 3564*8*(1<<16), 3948*8*(1<<16), -1092*8*(1<<16) + .int 3612, 1931, 2276, 3406 + + .int 4085*8*(1<<16), -301*8*(1<<16), 2675*8*(1<<16), 3102*8*(1<<16) + .int 3659*8*(1<<16), -1842*8*(1<<16), 1285*8*(1<<16), 3889*8*(1<<16) + .int -3920, -1189, -3406, -2276 +endconst + +const iadst4_coeffs, align=4 + .int 1321, 3803, 2482, 3344 +endconst + +const iadst8_coeffs, align=4 + .int 4076, 401, 3612, 1931 + .int 2598, 3166, 1189, 3920 + // idct_coeffs + .int 2896, 0, 1567, 3784 +endconst + +const iadst16_coeffs, align=4 + .int 4091, 201, 3973, 995 + .int 3703, 1751, 3290, 2440 + .int 2751, 3035, 2106, 3513 + .int 1380, 3857, 601, 4052 +endconst + +.macro mul_mla d, s0, s1, c0, c1 + mul \d\().4s, \s0\().4s, \c0 + mla \d\().4s, \s1\().4s, \c1 +.endm + +.macro mul_mls d, s0, s1, c0, c1 + mul \d\().4s, \s0\().4s, \c0 + mls \d\().4s, \s1\().4s, \c1 +.endm + +.macro scale_input sz, c, r0, r1, r2 r3, r4, r5, r6, r7 + sqrdmulh \r0\sz, \r0\sz, \c + sqrdmulh \r1\sz, \r1\sz, \c + sqrdmulh \r2\sz, \r2\sz, \c + sqrdmulh \r3\sz, \r3\sz, \c +.ifnb \r4 + sqrdmulh \r4\sz, \r4\sz, \c + sqrdmulh \r5\sz, \r5\sz, \c + sqrdmulh \r6\sz, \r6\sz, \c + sqrdmulh \r7\sz, \r7\sz, \c +.endif +.endm + +.macro smin_4s r0, r1, r2 + smin \r0\().4s, \r1\().4s, \r2\().4s +.endm +.macro smax_4s r0, r1, r2 + smax \r0\().4s, \r1\().4s, \r2\().4s +.endm + +.macro load_add_store load, shift, addsrc, adddst, min, store, dst, src, shiftbits=4 +.ifnb \load + ld1 {\load}, [\src], x1 +.endif +.ifnb \shift + srshr \shift, \shift, #\shiftbits +.endif +.ifnb \addsrc + usqadd \adddst, \addsrc +.endif +.ifnb \min + smin \min, \min, v7.8h +.endif +.ifnb \store + st1 {\store}, [\dst], x1 +.endif +.endm +.macro load_add_store_8x16 dst, src + mov \src, \dst + mvni v7.8h, #0xfc, lsl #8 // 0x3ff + load_add_store v2.8h, v16.8h, , , , , \dst, \src + load_add_store v3.8h, v17.8h, , , , , \dst, \src + load_add_store v4.8h, v18.8h, v16.8h, v2.8h, , , \dst, \src + load_add_store v5.8h, v19.8h, v17.8h, v3.8h, v2.8h, , \dst, \src + load_add_store v16.8h, v20.8h, v18.8h, v4.8h, v3.8h, v2.8h, \dst, \src + load_add_store v17.8h, v21.8h, v19.8h, v5.8h, v4.8h, v3.8h, \dst, \src + load_add_store v18.8h, v22.8h, v20.8h, v16.8h, v5.8h, v4.8h, \dst, \src + load_add_store v19.8h, v23.8h, v21.8h, v17.8h, v16.8h, v5.8h, \dst, \src + load_add_store v20.8h, v24.8h, v22.8h, v18.8h, v17.8h, v16.8h, \dst, \src + load_add_store v21.8h, v25.8h, v23.8h, v19.8h, v18.8h, v17.8h, \dst, \src + load_add_store v22.8h, v26.8h, v24.8h, v20.8h, v19.8h, v18.8h, \dst, \src + load_add_store v23.8h, v27.8h, v25.8h, v21.8h, v20.8h, v19.8h, \dst, \src + load_add_store v24.8h, v28.8h, v26.8h, v22.8h, v21.8h, v20.8h, \dst, \src + load_add_store v25.8h, v29.8h, v27.8h, v23.8h, v22.8h, v21.8h, \dst, \src + load_add_store v26.8h, v30.8h, v28.8h, v24.8h, v23.8h, v22.8h, \dst, \src + load_add_store v27.8h, v31.8h, v29.8h, v25.8h, v24.8h, v23.8h, \dst, \src + load_add_store , , v30.8h, v26.8h, v25.8h, v24.8h, \dst, \src + load_add_store , , v31.8h, v27.8h, v26.8h, v25.8h, \dst, \src + load_add_store , , , , v27.8h, v26.8h, \dst, \src + load_add_store , , , , , v27.8h, \dst, \src +.endm +.macro load_add_store_8x8 dst, src, shiftbits=4 + mov \src, \dst + mvni v7.8h, #0xfc, lsl #8 // 0x3ff + load_add_store v2.8h, v16.8h, , , , , \dst, \src, \shiftbits + load_add_store v3.8h, v17.8h, , , , , \dst, \src, \shiftbits + load_add_store v4.8h, v18.8h, v16.8h, v2.8h, , , \dst, \src, \shiftbits + load_add_store v5.8h, v19.8h, v17.8h, v3.8h, v2.8h, , \dst, \src, \shiftbits + load_add_store v16.8h, v20.8h, v18.8h, v4.8h, v3.8h, v2.8h, \dst, \src, \shiftbits + load_add_store v17.8h, v21.8h, v19.8h, v5.8h, v4.8h, v3.8h, \dst, \src, \shiftbits + load_add_store v18.8h, v22.8h, v20.8h, v16.8h, v5.8h, v4.8h, \dst, \src, \shiftbits + load_add_store v19.8h, v23.8h, v21.8h, v17.8h, v16.8h, v5.8h, \dst, \src, \shiftbits + load_add_store , , v22.8h, v18.8h, v17.8h, v16.8h, \dst, \src, \shiftbits + load_add_store , , v23.8h, v19.8h, v18.8h, v17.8h, \dst, \src, \shiftbits + load_add_store , , , , v19.8h, v18.8h, \dst, \src, \shiftbits + load_add_store , , , , , v19.8h, \dst, \src, \shiftbits +.endm +.macro load_add_store_8x4 dst, src, shiftbits=4 + mov \src, \dst + mvni v7.8h, #0xfc, lsl #8 // 0x3ff + load_add_store v2.8h, v16.8h, , , , , \dst, \src, \shiftbits + load_add_store v3.8h, v17.8h, , , , , \dst, \src, \shiftbits + load_add_store v4.8h, v18.8h, v16.8h, v2.8h, , , \dst, \src, \shiftbits + load_add_store v5.8h, v19.8h, v17.8h, v3.8h, v2.8h, , \dst, \src, \shiftbits + load_add_store , , v18.8h, v4.8h, v3.8h, v2.8h, \dst, \src, \shiftbits + load_add_store , , v19.8h, v5.8h, v4.8h, v3.8h, \dst, \src, \shiftbits + load_add_store , , , , v5.8h, v4.8h, \dst, \src, \shiftbits + load_add_store , , , , , v5.8h, \dst, \src, \shiftbits +.endm +.macro load_add_store4 load, inssrc, insdst, shift, addsrc, adddst, min, store, dst, src +.ifnb \load + ld1 {\load}[0], [\src], x1 +.endif +.ifnb \inssrc + ins \insdst\().d[1], \inssrc\().d[0] +.endif +.ifnb \shift + srshr \shift, \shift, #4 +.endif +.ifnb \load + ld1 {\load}[1], [\src], x1 +.endif +.ifnb \addsrc + usqadd \adddst, \addsrc +.endif +.ifnb \store + st1 {\store}[0], [\dst], x1 +.endif +.ifnb \min + smin \min, \min, v7.8h +.endif +.ifnb \store + st1 {\store}[1], [\dst], x1 +.endif +.endm +.macro load_add_store_4x16 dst, src + mov \src, \dst + mvni v7.8h, #0xfc, lsl #8 // 0x3ff + load_add_store4 v0.d, v17, v16, , , , , , \dst, \src + load_add_store4 v1.d, v19, v18, , , , , , \dst, \src + load_add_store4 v2.d, v21, v20, v16.8h, , , , , \dst, \src + load_add_store4 v3.d, v23, v22, v18.8h, v16.8h, v0.8h, , , \dst, \src + load_add_store4 v17.d, v25, v24, v20.8h, v18.8h, v1.8h, v0.8h, , \dst, \src + load_add_store4 v19.d, v27, v26, v22.8h, v20.8h, v2.8h, v1.8h, v0.d, \dst, \src + load_add_store4 v21.d, v29, v28, v24.8h, v22.8h, v3.8h, v2.8h, v1.d, \dst, \src + load_add_store4 v23.d, v31, v30, v26.8h, v24.8h, v17.8h, v3.8h, v2.d, \dst, \src + load_add_store4 , , , v28.8h, v26.8h, v19.8h, v17.8h, v3.d, \dst, \src + load_add_store4 , , , v30.8h, v28.8h, v21.8h, v19.8h, v17.d, \dst, \src + load_add_store4 , , , , v30.8h, v23.8h, v21.8h, v19.d, \dst, \src + load_add_store4 , , , , , , v23.8h, v21.d, \dst, \src + load_add_store4 , , , , , , , v23.d, \dst, \src +.endm +.macro load_add_store_4x8 dst, src + mov \src, \dst + mvni v7.8h, #0xfc, lsl #8 // 0x3ff + load_add_store4 v0.d, v17, v16, , , , , , \dst, \src + load_add_store4 v1.d, v19, v18, , , , , , \dst, \src + load_add_store4 v2.d, v21, v20, v16.8h, , , , , \dst, \src + load_add_store4 v3.d, v23, v22, v18.8h, v16.8h, v0.8h, , , \dst, \src + load_add_store4 , , , v20.8h, v18.8h, v1.8h, v0.8h, , \dst, \src + load_add_store4 , , , v22.8h, v20.8h, v2.8h, v1.8h, v0.d, \dst, \src + load_add_store4 , , , , v22.8h, v3.8h, v2.8h, v1.d, \dst, \src + load_add_store4 , , , , , , v3.8h, v2.d, \dst, \src + load_add_store4 , , , , , , , v3.d, \dst, \src +.endm + +.macro idct_dc w, h, shift + cbnz w3, 1f + movz w16, #2896*8, lsl #16 + ld1r {v16.4s}, [x2] + dup v0.2s, w16 + sqrdmulh v20.4s, v16.4s, v0.s[0] + str wzr, [x2] +.if (\w == 2*\h) || (2*\w == \h) + sqrdmulh v20.4s, v20.4s, v0.s[0] +.endif +.if \shift > 0 + sqrshrn v16.4h, v20.4s, #\shift + sqrshrn2 v16.8h, v20.4s, #\shift +.else + sqxtn v16.4h, v20.4s + sqxtn2 v16.8h, v20.4s +.endif + sqrdmulh v16.8h, v16.8h, v0.h[1] + srshr v16.8h, v16.8h, #4 + mov w4, #\h + b idct_dc_w\w\()_neon +1: +.endm + +function idct_dc_w4_neon + mvni v31.8h, #0xfc, lsl #8 // 0x3ff +1: + ld1 {v0.d}[0], [x0], x1 + ld1 {v0.d}[1], [x0], x1 + ld1 {v1.d}[0], [x0], x1 + subs w4, w4, #4 + ld1 {v1.d}[1], [x0], x1 + usqadd v0.8h, v16.8h + sub x0, x0, x1, lsl #2 + usqadd v1.8h, v16.8h + smin v0.8h, v0.8h, v31.8h + st1 {v0.d}[0], [x0], x1 + smin v1.8h, v1.8h, v31.8h + st1 {v0.d}[1], [x0], x1 + st1 {v1.d}[0], [x0], x1 + st1 {v1.d}[1], [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w8_neon + mvni v31.8h, #0xfc, lsl #8 // 0x3ff +1: + ld1 {v0.8h}, [x0], x1 + subs w4, w4, #4 + ld1 {v1.8h}, [x0], x1 + usqadd v0.8h, v16.8h + ld1 {v2.8h}, [x0], x1 + usqadd v1.8h, v16.8h + ld1 {v3.8h}, [x0], x1 + usqadd v2.8h, v16.8h + usqadd v3.8h, v16.8h + sub x0, x0, x1, lsl #2 + smin v0.8h, v0.8h, v31.8h + smin v1.8h, v1.8h, v31.8h + st1 {v0.8h}, [x0], x1 + smin v2.8h, v2.8h, v31.8h + st1 {v1.8h}, [x0], x1 + smin v3.8h, v3.8h, v31.8h + st1 {v2.8h}, [x0], x1 + st1 {v3.8h}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w16_neon + mvni v31.8h, #0xfc, lsl #8 // 0x3ff +1: + ld1 {v0.8h, v1.8h}, [x0], x1 + subs w4, w4, #2 + ld1 {v2.8h, v3.8h}, [x0], x1 + usqadd v0.8h, v16.8h + usqadd v1.8h, v16.8h + sub x0, x0, x1, lsl #1 + usqadd v2.8h, v16.8h + usqadd v3.8h, v16.8h + smin v0.8h, v0.8h, v31.8h + smin v1.8h, v1.8h, v31.8h + smin v2.8h, v2.8h, v31.8h + st1 {v0.8h, v1.8h}, [x0], x1 + smin v3.8h, v3.8h, v31.8h + st1 {v2.8h, v3.8h}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w32_neon + mvni v31.8h, #0xfc, lsl #8 // 0x3ff +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + subs w4, w4, #1 + usqadd v0.8h, v16.8h + usqadd v1.8h, v16.8h + usqadd v2.8h, v16.8h + usqadd v3.8h, v16.8h + smin v0.8h, v0.8h, v31.8h + smin v1.8h, v1.8h, v31.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + b.gt 1b + ret +endfunc + +function idct_dc_w64_neon + mvni v31.8h, #0xfc, lsl #8 // 0x3ff + sub x1, x1, #64 +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + subs w4, w4, #1 + usqadd v0.8h, v16.8h + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0] + usqadd v1.8h, v16.8h + sub x0, x0, #64 + usqadd v2.8h, v16.8h + usqadd v3.8h, v16.8h + usqadd v4.8h, v16.8h + usqadd v5.8h, v16.8h + usqadd v6.8h, v16.8h + usqadd v7.8h, v16.8h + smin v0.8h, v0.8h, v31.8h + smin v1.8h, v1.8h, v31.8h + smin v2.8h, v2.8h, v31.8h + smin v3.8h, v3.8h, v31.8h + smin v4.8h, v4.8h, v31.8h + smin v5.8h, v5.8h, v31.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + smin v6.8h, v6.8h, v31.8h + smin v7.8h, v7.8h, v31.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + b.gt 1b + ret +endfunc + +.macro iwht4 + add v16.4s, v16.4s, v17.4s + sub v21.4s, v18.4s, v19.4s + sub v20.4s, v16.4s, v21.4s + sshr v20.4s, v20.4s, #1 + sub v18.4s, v20.4s, v17.4s + sub v17.4s, v20.4s, v19.4s + add v19.4s, v21.4s, v18.4s + sub v16.4s, v16.4s, v17.4s +.endm + +.macro idct_4 r0, r1, r2, r3 + mul_mla v6, \r1, \r3, v0.s[3], v0.s[2] + mul_mla v2, \r0, \r2, v0.s[0], v0.s[0] + mul_mls v4, \r1, \r3, v0.s[2], v0.s[3] + mul_mls v3, \r0, \r2, v0.s[0], v0.s[0] + srshr v6.4s, v6.4s, #12 + srshr v2.4s, v2.4s, #12 + srshr v7.4s, v4.4s, #12 + srshr v3.4s, v3.4s, #12 + sqadd \r0\().4s, v2.4s, v6.4s + sqsub \r3\().4s, v2.4s, v6.4s + sqadd \r1\().4s, v3.4s, v7.4s + sqsub \r2\().4s, v3.4s, v7.4s +.endm + +function inv_dct_4s_x4_neon + AARCH64_VALID_CALL_TARGET + movrel x16, idct_coeffs + ld1 {v0.4s}, [x16] + idct_4 v16, v17, v18, v19 + ret +endfunc + +.macro iadst_4x4 o0, o1, o2, o3 + movrel x16, iadst4_coeffs + ld1 {v0.4s}, [x16] + + sub v3.4s, v16.4s, v18.4s + mul v4.4s, v16.4s, v0.s[0] + mla v4.4s, v18.4s, v0.s[1] + mla v4.4s, v19.4s, v0.s[2] + mul v7.4s, v17.4s, v0.s[3] + add v3.4s, v3.4s, v19.4s + mul v5.4s, v16.4s, v0.s[2] + mls v5.4s, v18.4s, v0.s[0] + mls v5.4s, v19.4s, v0.s[1] + + add \o3\().4s, v4.4s, v5.4s + mul \o2\().4s, v3.4s, v0.s[3] + add \o0\().4s, v4.4s, v7.4s + add \o1\().4s, v5.4s, v7.4s + sub \o3\().4s, \o3\().4s, v7.4s + + srshr \o0\().4s, \o0\().4s, #12 + srshr \o2\().4s, \o2\().4s, #12 + srshr \o1\().4s, \o1\().4s, #12 + srshr \o3\().4s, \o3\().4s, #12 +.endm + +function inv_adst_4s_x4_neon + AARCH64_VALID_CALL_TARGET + iadst_4x4 v16, v17, v18, v19 + ret +endfunc + +function inv_flipadst_4s_x4_neon + AARCH64_VALID_CALL_TARGET + iadst_4x4 v19, v18, v17, v16 + ret +endfunc + +function inv_identity_4s_x4_neon + AARCH64_VALID_CALL_TARGET + movz w16, #(5793-4096)*8, lsl #16 + dup v0.2s, w16 + sqrdmulh v4.4s, v16.4s, v0.s[0] + sqrdmulh v5.4s, v17.4s, v0.s[0] + sqrdmulh v6.4s, v18.4s, v0.s[0] + sqrdmulh v7.4s, v19.4s, v0.s[0] + sqadd v16.4s, v16.4s, v4.4s + sqadd v17.4s, v17.4s, v5.4s + sqadd v18.4s, v18.4s, v6.4s + sqadd v19.4s, v19.4s, v7.4s + ret +endfunc + +function inv_txfm_add_wht_wht_4x4_16bpc_neon, export=1 + mov x15, x30 + movi v30.4s, #0 + movi v31.4s, #0 + ld1 {v16.4s,v17.4s,v18.4s,v19.4s}, [x2] + st1 {v30.4s, v31.4s}, [x2], #32 + + sshr v16.4s, v16.4s, #2 + sshr v17.4s, v17.4s, #2 + sshr v18.4s, v18.4s, #2 + sshr v19.4s, v19.4s, #2 + + iwht4 + + st1 {v30.4s, v31.4s}, [x2], #32 + transpose_4x4s v16, v17, v18, v19, v20, v21, v22, v23 + + iwht4 + + ld1 {v0.d}[0], [x0], x1 + sqxtn v16.4h, v16.4s + ld1 {v0.d}[1], [x0], x1 + sqxtn2 v16.8h, v17.4s + ld1 {v1.d}[0], [x0], x1 + sqxtn v18.4h, v18.4s + ld1 {v1.d}[1], [x0], x1 + sqxtn2 v18.8h, v19.4s + + b L(itx_4x4_end) +endfunc + +function inv_txfm_add_4x4_neon + movi v30.4s, #0 + movi v31.4s, #0 + ld1 {v16.4s,v17.4s,v18.4s,v19.4s}, [x2] + st1 {v30.4s, v31.4s}, [x2], #32 + + blr x4 + + st1 {v30.4s, v31.4s}, [x2], #32 + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn v18.4h, v18.4s + sqxtn v19.4h, v19.4s + transpose_4x4h v16, v17, v18, v19, v20, v21, v22, v23 + + blr x5 + + ld1 {v0.d}[0], [x0], x1 + ld1 {v0.d}[1], [x0], x1 + ins v16.d[1], v17.d[0] + ins v18.d[1], v19.d[0] + ld1 {v1.d}[0], [x0], x1 + ld1 {v1.d}[1], [x0], x1 + srshr v16.8h, v16.8h, #4 + srshr v18.8h, v18.8h, #4 + +L(itx_4x4_end): + mvni v31.8h, #0xfc, lsl #8 // 0x3ff + sub x0, x0, x1, lsl #2 + usqadd v0.8h, v16.8h + usqadd v1.8h, v18.8h + smin v0.8h, v0.8h, v31.8h + st1 {v0.d}[0], [x0], x1 + smin v1.8h, v1.8h, v31.8h + st1 {v0.d}[1], [x0], x1 + st1 {v1.d}[0], [x0], x1 + st1 {v1.d}[1], [x0], x1 + + ret x15 +endfunc + +.macro def_fn_4x4 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_4x4_16bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + cbnz w3, 1f + movz w16, #2896*8, lsl #16 + ld1r {v16.4s}, [x2] + dup v4.2s, w16 + str wzr, [x2] + sqrdmulh v16.4s, v16.4s, v4.s[0] + ld1 {v0.d}[0], [x0], x1 + sqxtn v20.4h, v16.4s + sqxtn2 v20.8h, v16.4s + ld1 {v0.d}[1], [x0], x1 + sqrdmulh v20.8h, v20.8h, v4.h[1] + ld1 {v1.d}[0], [x0], x1 + srshr v16.8h, v20.8h, #4 + ld1 {v1.d}[1], [x0], x1 + srshr v18.8h, v20.8h, #4 + movi v30.8h, #0 + b L(itx_4x4_end) +1: +.endif + adr x4, inv_\txfm1\()_4s_x4_neon + movrel x5, X(inv_\txfm2\()_4h_x4_neon) + b inv_txfm_add_4x4_neon +endfunc +.endm + +def_fn_4x4 dct, dct +def_fn_4x4 identity, identity +def_fn_4x4 dct, adst +def_fn_4x4 dct, flipadst +def_fn_4x4 dct, identity +def_fn_4x4 adst, dct +def_fn_4x4 adst, adst +def_fn_4x4 adst, flipadst +def_fn_4x4 flipadst, dct +def_fn_4x4 flipadst, adst +def_fn_4x4 flipadst, flipadst +def_fn_4x4 identity, dct + +def_fn_4x4 adst, identity +def_fn_4x4 flipadst, identity +def_fn_4x4 identity, adst +def_fn_4x4 identity, flipadst + +.macro idct_8 r0, r1, r2, r3, r4, r5, r6, r7 + idct_4 \r0, \r2, \r4, \r6 + + movi v5.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + mvni v4.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 +.irp r, \r0, \r2, \r4, \r6 + smin_4s \r, \r, v5 +.endr +.irp r, \r0, \r2, \r4, \r6 + smax_4s \r, \r, v4 +.endr + + mul_mls v2, \r1, \r7, v1.s[0], v1.s[1] // -> t4a + mul_mla v3, \r1, \r7, v1.s[1], v1.s[0] // -> t7a + mul_mls v6, \r5, \r3, v1.s[2], v1.s[3] // -> t5a + mul_mla v7, \r5, \r3, v1.s[3], v1.s[2] // -> t6a + srshr \r1\().4s, v2.4s, #12 // t4a + srshr \r7\().4s, v3.4s, #12 // t7a + srshr \r3\().4s, v6.4s, #12 // t5a + srshr \r5\().4s, v7.4s, #12 // t6a + + sqadd v2.4s, \r1\().4s, \r3\().4s // t4 + sqsub \r1\().4s, \r1\().4s, \r3\().4s // t5a + sqadd v3.4s, \r7\().4s, \r5\().4s // t7 + sqsub \r3\().4s, \r7\().4s, \r5\().4s // t6a + +.irp r, v2, \r1, v3, \r3 + smin_4s \r, \r, v5 +.endr +.irp r, v2, \r1, v3, \r3 + smax_4s \r, \r, v4 +.endr + + mul_mls v7, \r3, \r1, v0.s[0], v0.s[0] // -> t5 + mul_mla v6, \r3, \r1, v0.s[0], v0.s[0] // -> t6 + srshr v7.4s, v7.4s, #12 // t5 + srshr v6.4s, v6.4s, #12 // t6 + + sqsub \r7\().4s, \r0\().4s, v3.4s // out7 + sqadd \r0\().4s, \r0\().4s, v3.4s // out0 + sqadd \r1\().4s, \r2\().4s, v6.4s // out1 + sqsub v6.4s, \r2\().4s, v6.4s // out6 + sqadd \r2\().4s, \r4\().4s, v7.4s // out2 + sqsub \r5\().4s, \r4\().4s, v7.4s // out5 + sqadd \r3\().4s, \r6\().4s, v2.4s // out3 + sqsub \r4\().4s, \r6\().4s, v2.4s // out4 + mov \r6\().16b, v6.16b // out6 +.endm + +function inv_dct_4s_x8_neon + AARCH64_VALID_CALL_TARGET + movrel x16, idct_coeffs + ld1 {v0.4s, v1.4s}, [x16] + idct_8 v16, v17, v18, v19, v20, v21, v22, v23 + ret +endfunc + +.macro iadst_8 o0, o1, o2, o3, o4, o5, o6, o7 + movrel x16, iadst8_coeffs + ld1 {v0.4s, v1.4s}, [x16], #32 + + mul_mla v2, v23, v16, v0.s[0], v0.s[1] + mul_mls v4, v23, v16, v0.s[1], v0.s[0] + mul_mla v6, v21, v18, v0.s[2], v0.s[3] + srshr v16.4s, v2.4s, #12 // t0a + srshr v23.4s, v4.4s, #12 // t1a + mul_mls v2, v21, v18, v0.s[3], v0.s[2] + mul_mla v4, v19, v20, v1.s[0], v1.s[1] + srshr v18.4s, v6.4s, #12 // t2a + srshr v21.4s, v2.4s, #12 // t3a + mul_mls v6, v19, v20, v1.s[1], v1.s[0] + mul_mla v2, v17, v22, v1.s[2], v1.s[3] + srshr v20.4s, v4.4s, #12 // t4a + srshr v19.4s, v6.4s, #12 // t5a + mul_mls v4, v17, v22, v1.s[3], v1.s[2] + srshr v22.4s, v2.4s, #12 // t6a + srshr v17.4s, v4.4s, #12 // t7a + + ld1 {v0.4s}, [x16] + + movi v1.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + + sqadd v2.4s, v16.4s, v20.4s // t0 + sqsub v3.4s, v16.4s, v20.4s // t4 + mvni v20.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + sqadd v4.4s, v23.4s, v19.4s // t1 + sqsub v5.4s, v23.4s, v19.4s // t5 + sqadd v6.4s, v18.4s, v22.4s // t2 + sqsub v7.4s, v18.4s, v22.4s // t6 + sqadd v18.4s, v21.4s, v17.4s // t3 + sqsub v19.4s, v21.4s, v17.4s // t7 + +.irp r, v2, v3, v4, v5, v6, v7, v18, v19 + smin_4s \r, \r, v1 +.endr +.irp r, v2, v3, v4, v5, v6, v7, v18, v19 + smax_4s \r, \r, v20 +.endr + + mul_mla v16, v3, v5, v0.s[3], v0.s[2] + mul_mls v20, v3, v5, v0.s[2], v0.s[3] + mul_mls v22, v19, v7, v0.s[3], v0.s[2] + + srshr v3.4s, v16.4s, #12 // t4a + srshr v5.4s, v20.4s, #12 // t5a + + mul_mla v16, v19, v7, v0.s[2], v0.s[3] + + srshr v7.4s, v22.4s, #12 // t6a + srshr v19.4s, v16.4s, #12 // t7a + + sqadd \o0\().4s, v2.4s, v6.4s // out0 + sqsub v2.4s, v2.4s, v6.4s // t2 + sqadd \o7\().4s, v4.4s, v18.4s // out7 + sqsub v4.4s, v4.4s, v18.4s // t3 + + mvni v18.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + + sqadd \o1\().4s, v3.4s, v7.4s // out1 + sqsub v3.4s, v3.4s, v7.4s // t6 + sqadd \o6\().4s, v5.4s, v19.4s // out6 + sqsub v5.4s, v5.4s, v19.4s // t7 + + // Not clipping the output registers, as they will be downshifted and + // narrowed afterwards anyway. +.irp r, v2, v4, v3, v5 + smin_4s \r, \r, v1 +.endr +.irp r, v2, v4, v3, v5 + smax_4s \r, \r, v18 +.endr + + sqneg \o7\().4s, \o7\().4s // out7 + sqneg \o1\().4s, \o1\().4s // out1 + + mul_mla v18, v2, v4, v0.s[0], v0.s[0] // -> out3 (v19 or v20) + mul_mls v6, v2, v4, v0.s[0], v0.s[0] // -> out4 (v20 or v19) + mul_mls v20, v3, v5, v0.s[0], v0.s[0] // -> out5 (v21 or v18) + srshr v2.4s, v18.4s, #12 // out3 + mul_mla v18, v3, v5, v0.s[0], v0.s[0] // -> out2 (v18 or v21) + srshr v3.4s, v20.4s, #12 // out5 + srshr \o2\().4s, v18.4s, #12 // out2 (v18 or v21) + srshr \o4\().4s, v6.4s, #12 // out4 (v20 or v19) + + sqneg \o3\().4s, v2.4s // out3 + sqneg \o5\().4s, v3.4s // out5 +.endm + +function inv_adst_4s_x8_neon + AARCH64_VALID_CALL_TARGET + iadst_8 v16, v17, v18, v19, v20, v21, v22, v23 + ret +endfunc + +function inv_flipadst_4s_x8_neon + AARCH64_VALID_CALL_TARGET + iadst_8 v23, v22, v21, v20, v19, v18, v17, v16 + ret +endfunc + +function inv_identity_4s_x8_neon + AARCH64_VALID_CALL_TARGET + sqshl v16.4s, v16.4s, #1 + sqshl v17.4s, v17.4s, #1 + sqshl v18.4s, v18.4s, #1 + sqshl v19.4s, v19.4s, #1 + sqshl v20.4s, v20.4s, #1 + sqshl v21.4s, v21.4s, #1 + sqshl v22.4s, v22.4s, #1 + sqshl v23.4s, v23.4s, #1 + ret +endfunc + +function inv_txfm_add_8x8_neon + movi v31.4s, #0 + + cmp w3, w13 + mov x11, #32 + b.lt 1f + + add x6, x2, #16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x6] + st1 {v31.4s}, [x6], x11 +.endr + + blr x4 + + sqrshrn v24.4h, v16.4s, #1 + sqrshrn v25.4h, v17.4s, #1 + sqrshrn v26.4h, v18.4s, #1 + sqrshrn v27.4h, v19.4s, #1 + sqrshrn2 v24.8h, v20.4s, #1 + sqrshrn2 v25.8h, v21.4s, #1 + sqrshrn2 v26.8h, v22.4s, #1 + sqrshrn2 v27.8h, v23.4s, #1 + + transpose_4x8h v24, v25, v26, v27, v2, v3, v4, v5 + + b 2f + +1: +.irp i, v24.8h, v25.8h, v26.8h, v27.8h + movi \i, #0 +.endr + +2: + +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x2] + st1 {v31.4s}, [x2], x11 +.endr + + blr x4 + + sqrshrn v16.4h, v16.4s, #1 + sqrshrn v17.4h, v17.4s, #1 + sqrshrn v18.4h, v18.4s, #1 + sqrshrn v19.4h, v19.4s, #1 + sqrshrn2 v16.8h, v20.4s, #1 + sqrshrn2 v17.8h, v21.4s, #1 + sqrshrn2 v18.8h, v22.4s, #1 + sqrshrn2 v19.8h, v23.4s, #1 + + transpose_4x8h v16, v17, v18, v19, v20, v21, v22, v23 + + mov v20.16b, v24.16b + mov v21.16b, v25.16b + mov v22.16b, v26.16b + mov v23.16b, v27.16b + + blr x5 + + load_add_store_8x8 x0, x7 + ret x15 +endfunc + +.macro def_fn_8x8 txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_8x8_16bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 8, 8, 1 +.endif + movrel x5, X(inv_\txfm2\()_8h_x8_neon) + mov w13, #\eob_half + adr x4, inv_\txfm1\()_4s_x8_neon + b inv_txfm_add_8x8_neon +endfunc +.endm + +def_fn_8x8 dct, dct, 10 +def_fn_8x8 identity, identity, 10 +def_fn_8x8 dct, adst, 10 +def_fn_8x8 dct, flipadst, 10 +def_fn_8x8 dct, identity, 4 +def_fn_8x8 adst, dct, 10 +def_fn_8x8 adst, adst, 10 +def_fn_8x8 adst, flipadst, 10 +def_fn_8x8 flipadst, dct, 10 +def_fn_8x8 flipadst, adst, 10 +def_fn_8x8 flipadst, flipadst, 10 +def_fn_8x8 identity, dct, 4 +def_fn_8x8 adst, identity, 4 +def_fn_8x8 flipadst, identity, 4 +def_fn_8x8 identity, adst, 4 +def_fn_8x8 identity, flipadst, 4 + +function inv_txfm_add_8x4_neon + movi v28.4s, #0 + movi v29.4s, #0 + movi v30.4s, #0 + movi v31.4s, #0 + ld1 {v16.4s,v17.4s,v18.4s,v19.4s}, [x2] + st1 {v28.4s,v29.4s,v30.4s,v31.4s}, [x2], #64 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 + ld1 {v20.4s,v21.4s,v22.4s,v23.4s}, [x2] + st1 {v28.4s,v29.4s,v30.4s,v31.4s}, [x2] + + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + + blr x4 + + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn v18.4h, v18.4s + sqxtn v19.4h, v19.4s + sqxtn v20.4h, v20.4s + sqxtn v21.4h, v21.4s + sqxtn v22.4h, v22.4s + sqxtn v23.4h, v23.4s + + transpose_4x4h v16, v17, v18, v19, v4, v5, v6, v7 + transpose_4x4h v20, v21, v22, v23, v4, v5, v6, v7 + ins v16.d[1], v20.d[0] + ins v17.d[1], v21.d[0] + ins v18.d[1], v22.d[0] + ins v19.d[1], v23.d[0] + + blr x5 + + load_add_store_8x4 x0, x7 + ret x15 +endfunc + +function inv_txfm_add_4x8_neon + movz w16, #2896*8, lsl #16 + movi v31.4s, #0 + dup v30.2s, w16 + + cmp w3, w13 + mov x11, #32 + b.lt 1f + + add x6, x2, #16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x6] + st1 {v31.4s}, [x6], x11 +.endr + scale_input .4s, v30.s[0], v16, v17, v18, v19 + blr x4 + sqxtn v20.4h, v16.4s + sqxtn v21.4h, v17.4s + sqxtn v22.4h, v18.4s + sqxtn v23.4h, v19.4s + transpose_4x4h v20, v21, v22, v23, v4, v5, v6, v7 + + b 2f + +1: +.irp i, v20, v21, v22, v23 + movi \i\().4h, #0 +.endr + +2: + +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x2] + st1 {v31.4s}, [x2], x11 +.endr + scale_input .4s, v30.s[0], v16, v17, v18, v19 + blr x4 + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn v18.4h, v18.4s + sqxtn v19.4h, v19.4s + transpose_4x4h v16, v17, v18, v19, v4, v5, v6, v7 + + blr x5 + + load_add_store_4x8 x0, x7 + ret x15 +endfunc + +.macro def_fn_48 w, h, txfm1, txfm2, eob_half +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 + mov x15, x30 + +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 0 +.endif + adr x4, inv_\txfm1\()_4s_x\w\()_neon +.if \w == 4 + mov w13, #\eob_half +.endif + movrel x5, X(inv_\txfm2\()_\w\()h_x\h\()_neon) + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_48 w, h +def_fn_48 \w, \h, dct, dct, 13 +def_fn_48 \w, \h, identity, identity, 13 +def_fn_48 \w, \h, dct, adst, 13 +def_fn_48 \w, \h, dct, flipadst, 13 +def_fn_48 \w, \h, dct, identity, 4 +def_fn_48 \w, \h, adst, dct, 13 +def_fn_48 \w, \h, adst, adst, 13 +def_fn_48 \w, \h, adst, flipadst, 13 +def_fn_48 \w, \h, flipadst, dct, 13 +def_fn_48 \w, \h, flipadst, adst, 13 +def_fn_48 \w, \h, flipadst, flipadst, 13 +def_fn_48 \w, \h, identity, dct, 16 +def_fn_48 \w, \h, adst, identity, 4 +def_fn_48 \w, \h, flipadst, identity, 4 +def_fn_48 \w, \h, identity, adst, 16 +def_fn_48 \w, \h, identity, flipadst, 16 +.endm + +def_fns_48 4, 8 +def_fns_48 8, 4 + + +function inv_dct_4s_x16_neon + AARCH64_VALID_CALL_TARGET + movrel x16, idct_coeffs + ld1 {v0.4s, v1.4s}, [x16], #32 + + idct_8 v16, v18, v20, v22, v24, v26, v28, v30 + + // idct_8 leaves the row_clip_max/min constants in v5 and v4 +.irp r, v16, v18, v20, v22, v24, v26, v28, v30 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v16, v18, v20, v22, v24, v26, v28, v30 + smax \r\().4s, \r\().4s, v4.4s +.endr + + ld1 {v0.4s, v1.4s}, [x16] + sub x16, x16, #32 + + mul_mls v2, v17, v31, v0.s[0], v0.s[1] // -> t8a + mul_mla v3, v17, v31, v0.s[1], v0.s[0] // -> t15a + mul_mls v6, v25, v23, v0.s[2], v0.s[3] // -> t9a + srshr v17.4s, v2.4s, #12 // t8a + srshr v31.4s, v3.4s, #12 // t15a + mul_mla v2, v25, v23, v0.s[3], v0.s[2] // -> t14a + mul_mls v3, v21, v27, v1.s[0], v1.s[1] // -> t10a + srshr v23.4s, v6.4s, #12 // t9a + srshr v25.4s, v2.4s, #12 // t14a + mul_mla v6, v21, v27, v1.s[1], v1.s[0] // -> t13a + mul_mls v2, v29, v19, v1.s[2], v1.s[3] // -> t11a + srshr v21.4s, v3.4s, #12 // t10a + srshr v27.4s, v6.4s, #12 // t13a + mul_mla v3, v29, v19, v1.s[3], v1.s[2] // -> t12a + srshr v19.4s, v2.4s, #12 // t11a + srshr v29.4s, v3.4s, #12 // t12a + + ld1 {v0.4s}, [x16] + + sqsub v2.4s, v17.4s, v23.4s // t9 + sqadd v17.4s, v17.4s, v23.4s // t8 + sqsub v3.4s, v31.4s, v25.4s // t14 + sqadd v31.4s, v31.4s, v25.4s // t15 + sqsub v23.4s, v19.4s, v21.4s // t10 + sqadd v19.4s, v19.4s, v21.4s // t11 + sqadd v25.4s, v29.4s, v27.4s // t12 + sqsub v29.4s, v29.4s, v27.4s // t13 + +.irp r, v2, v17, v3, v31, v23, v19, v25, v29 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v2, v17, v3, v31, v23, v19, v25, v29 + smax \r\().4s, \r\().4s, v4.4s +.endr + + mul_mls v7, v3, v2, v0.s[2], v0.s[3] // -> t9a + mul_mla v6, v3, v2, v0.s[3], v0.s[2] // -> t14a + srshr v21.4s, v7.4s, #12 // t9a + srshr v27.4s, v6.4s, #12 // t14a + + mul_mls v7, v29, v23, v0.s[2], v0.s[3] // -> t13a + mul_mla v6, v29, v23, v0.s[3], v0.s[2] // -> t10a + srshr v29.4s, v7.4s, #12 // t13a + neg v6.4s, v6.4s + srshr v23.4s, v6.4s, #12 // t10a + + sqsub v2.4s, v17.4s, v19.4s // t11a + sqadd v17.4s, v17.4s, v19.4s // t8a + sqsub v3.4s, v31.4s, v25.4s // t12a + sqadd v31.4s, v31.4s, v25.4s // t15a + sqadd v19.4s, v21.4s, v23.4s // t9 + sqsub v21.4s, v21.4s, v23.4s // t10 + sqsub v25.4s, v27.4s, v29.4s // t13 + sqadd v27.4s, v27.4s, v29.4s // t14 + +.irp r, v2, v17, v3, v31, v19, v21, v25, v27 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v2, v17, v3, v31, v19, v21, v25, v27 + smax \r\().4s, \r\().4s, v4.4s +.endr + + mul_mls v7, v3, v2, v0.s[0], v0.s[0] // -> t11 + mul_mla v6, v3, v2, v0.s[0], v0.s[0] // -> t12 + mul_mls v2, v25, v21, v0.s[0], v0.s[0] // -> t10a + + srshr v7.4s, v7.4s, #12 // t11 + srshr v6.4s, v6.4s, #12 // t12 + mul_mla v3, v25, v21, v0.s[0], v0.s[0] // -> t13a + srshr v2.4s, v2.4s, #12 // t10a + srshr v3.4s, v3.4s, #12 // t13a + + sqadd v1.4s, v16.4s, v31.4s // out0 + sqsub v31.4s, v16.4s, v31.4s // out15 + mov v16.16b, v1.16b + sqadd v23.4s, v30.4s, v17.4s // out7 + sqsub v1.4s, v30.4s, v17.4s // out8 + sqadd v17.4s, v18.4s, v27.4s // out1 + sqsub v30.4s, v18.4s, v27.4s // out14 + sqadd v18.4s, v20.4s, v3.4s // out2 + sqsub v29.4s, v20.4s, v3.4s // out13 + sqadd v3.4s, v28.4s, v19.4s // out6 + sqsub v25.4s, v28.4s, v19.4s // out9 + sqadd v19.4s, v22.4s, v6.4s // out3 + sqsub v28.4s, v22.4s, v6.4s // out12 + sqadd v20.4s, v24.4s, v7.4s // out4 + sqsub v27.4s, v24.4s, v7.4s // out11 + sqadd v21.4s, v26.4s, v2.4s // out5 + sqsub v26.4s, v26.4s, v2.4s // out10 + mov v24.16b, v1.16b + mov v22.16b, v3.16b + + ret +endfunc + +.macro iadst_16 o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15 + movrel x16, iadst16_coeffs + ld1 {v0.4s, v1.4s}, [x16], #32 + + mul_mla v2, v31, v16, v0.s[0], v0.s[1] // -> t0 + mul_mls v4, v31, v16, v0.s[1], v0.s[0] // -> t1 + mul_mla v6, v29, v18, v0.s[2], v0.s[3] // -> t2 + srshr v16.4s, v2.4s, #12 // t0 + srshr v31.4s, v4.4s, #12 // t1 + mul_mls v2, v29, v18, v0.s[3], v0.s[2] // -> t3 + mul_mla v4, v27, v20, v1.s[0], v1.s[1] // -> t4 + srshr v18.4s, v6.4s, #12 // t2 + srshr v29.4s, v2.4s, #12 // t3 + mul_mls v6, v27, v20, v1.s[1], v1.s[0] // -> t5 + mul_mla v2, v25, v22, v1.s[2], v1.s[3] // -> t6 + srshr v20.4s, v4.4s, #12 // t4 + srshr v27.4s, v6.4s, #12 // t5 + mul_mls v4, v25, v22, v1.s[3], v1.s[2] // -> t7 + ld1 {v0.4s, v1.4s}, [x16] + movrel x16, idct_coeffs + mul_mla v6, v23, v24, v0.s[0], v0.s[1] // -> t8 + srshr v22.4s, v2.4s, #12 // t6 + srshr v25.4s, v4.4s, #12 // t7 + mul_mls v2, v23, v24, v0.s[1], v0.s[0] // -> t9 + mul_mla v4, v21, v26, v0.s[2], v0.s[3] // -> t10 + srshr v23.4s, v6.4s, #12 // t8 + srshr v24.4s, v2.4s, #12 // t9 + mul_mls v6, v21, v26, v0.s[3], v0.s[2] // -> t11 + mul_mla v2, v19, v28, v1.s[0], v1.s[1] // -> t12 + srshr v21.4s, v4.4s, #12 // t10 + srshr v26.4s, v6.4s, #12 // t11 + mul_mls v4, v19, v28, v1.s[1], v1.s[0] // -> t13 + mul_mla v6, v17, v30, v1.s[2], v1.s[3] // -> t14 + srshr v19.4s, v2.4s, #12 // t12 + srshr v28.4s, v4.4s, #12 // t13 + mul_mls v2, v17, v30, v1.s[3], v1.s[2] // -> t15 + srshr v17.4s, v6.4s, #12 // t14 + srshr v30.4s, v2.4s, #12 // t15 + + ld1 {v0.4s, v1.4s}, [x16] + + movi v5.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + mvni v7.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + + sqsub v2.4s, v16.4s, v23.4s // t8a + sqadd v16.4s, v16.4s, v23.4s // t0a + sqsub v3.4s, v31.4s, v24.4s // t9a + sqadd v31.4s, v31.4s, v24.4s // t1a + sqadd v23.4s, v18.4s, v21.4s // t2a + sqsub v18.4s, v18.4s, v21.4s // t10a + sqadd v24.4s, v29.4s, v26.4s // t3a + sqsub v29.4s, v29.4s, v26.4s // t11a + sqadd v21.4s, v20.4s, v19.4s // t4a + sqsub v20.4s, v20.4s, v19.4s // t12a + sqadd v26.4s, v27.4s, v28.4s // t5a + sqsub v27.4s, v27.4s, v28.4s // t13a + sqadd v19.4s, v22.4s, v17.4s // t6a + sqsub v22.4s, v22.4s, v17.4s // t14a + sqadd v28.4s, v25.4s, v30.4s // t7a + sqsub v25.4s, v25.4s, v30.4s // t15a + +.irp r, v2, v16, v3, v31, v23, v18, v24, v29, v21, v20, v26, v27, v19, v22, v28, v25 + smin_4s \r, \r, v5 +.endr +.irp r, v2, v16, v3, v31, v23, v18, v24, v29, v21, v20, v26, v27, v19, v22, v28, v25 + smax_4s \r, \r, v7 +.endr + + mul_mla v4, v2, v3, v1.s[1], v1.s[0] // -> t8 + mul_mls v6, v2, v3, v1.s[0], v1.s[1] // -> t9 + mul_mla v2, v18, v29, v1.s[3], v1.s[2] // -> t10 + srshr v17.4s, v4.4s, #12 // t8 + srshr v30.4s, v6.4s, #12 // t9 + mul_mls v4, v18, v29, v1.s[2], v1.s[3] // -> t11 + mul_mls v6, v27, v20, v1.s[1], v1.s[0] // -> t12 + srshr v18.4s, v2.4s, #12 // t10 + srshr v29.4s, v4.4s, #12 // t11 + mul_mla v2, v27, v20, v1.s[0], v1.s[1] // -> t13 + mul_mls v4, v25, v22, v1.s[3], v1.s[2] // -> t14 + srshr v27.4s, v6.4s, #12 // t12 + srshr v20.4s, v2.4s, #12 // t13 + mul_mla v6, v25, v22, v1.s[2], v1.s[3] // -> t15 + srshr v25.4s, v4.4s, #12 // t14 + srshr v22.4s, v6.4s, #12 // t15 + + sqsub v2.4s, v16.4s, v21.4s // t4 + sqadd v16.4s, v16.4s, v21.4s // t0 + sqsub v3.4s, v31.4s, v26.4s // t5 + sqadd v31.4s, v31.4s, v26.4s // t1 + sqadd v21.4s, v23.4s, v19.4s // t2 + sqsub v23.4s, v23.4s, v19.4s // t6 + sqadd v26.4s, v24.4s, v28.4s // t3 + sqsub v24.4s, v24.4s, v28.4s // t7 + sqadd v19.4s, v17.4s, v27.4s // t8a + sqsub v17.4s, v17.4s, v27.4s // t12a + sqadd v28.4s, v30.4s, v20.4s // t9a + sqsub v30.4s, v30.4s, v20.4s // t13a + sqadd v27.4s, v18.4s, v25.4s // t10a + sqsub v18.4s, v18.4s, v25.4s // t14a + sqadd v20.4s, v29.4s, v22.4s // t11a + sqsub v29.4s, v29.4s, v22.4s // t15a + +.irp r, v2, v16, v3, v31, v21, v23, v26, v24, v19, v17, v28, v30, v27, v18, v20, v29 + smin_4s \r, \r, v5 +.endr +.irp r, v2, v16, v3, v31, v21, v23, v26, v24, v19, v17, v28, v30, v27, v18, v20, v29 + smax_4s \r, \r, v7 +.endr + + mul_mla v4, v2, v3, v0.s[3], v0.s[2] // -> t4a + mul_mls v6, v2, v3, v0.s[2], v0.s[3] // -> t5a + mul_mls v2, v24, v23, v0.s[3], v0.s[2] // -> t6a + srshr v22.4s, v4.4s, #12 // t4a + srshr v25.4s, v6.4s, #12 // t5a + mul_mla v4, v24, v23, v0.s[2], v0.s[3] // -> t7a + mul_mla v6, v17, v30, v0.s[3], v0.s[2] // -> t12 + srshr v24.4s, v2.4s, #12 // t6a + srshr v23.4s, v4.4s, #12 // t7a + mul_mls v2, v17, v30, v0.s[2], v0.s[3] // -> t13 + mul_mls v4, v29, v18, v0.s[3], v0.s[2] // -> t14 + srshr v17.4s, v6.4s, #12 // t12 + mul_mla v6, v29, v18, v0.s[2], v0.s[3] // -> t15 + srshr v29.4s, v2.4s, #12 // t13 + srshr v30.4s, v4.4s, #12 // t14 + srshr v18.4s, v6.4s, #12 // t15 + + sqsub v2.4s, v16.4s, v21.4s // t2a +.ifc \o0, v16 + sqadd \o0\().4s, v16.4s, v21.4s // out0 + sqsub v21.4s, v31.4s, v26.4s // t3a + sqadd \o15\().4s, v31.4s, v26.4s // out15 +.else + sqadd v4.4s, v16.4s, v21.4s // out0 + sqsub v21.4s, v31.4s, v26.4s // t3a + sqadd \o15\().4s, v31.4s, v26.4s // out15 + mov \o0\().16b, v4.16b +.endif + + sqsub v3.4s, v29.4s, v18.4s // t15a + sqadd \o13\().4s, v29.4s, v18.4s // out13 + sqadd \o2\().4s, v17.4s, v30.4s // out2 + sqsub v26.4s, v17.4s, v30.4s // t14a + + sqadd \o1\().4s, v19.4s, v27.4s // out1 + sqsub v27.4s, v19.4s, v27.4s // t10 + sqadd \o14\().4s, v28.4s, v20.4s // out14 + sqsub v20.4s, v28.4s, v20.4s // t11 + + sqadd \o3\().4s, v22.4s, v24.4s // out3 + sqsub v22.4s, v22.4s, v24.4s // t6 + sqadd \o12\().4s, v25.4s, v23.4s // out12 + sqsub v23.4s, v25.4s, v23.4s // t7 + + // Not clipping the output registers, as they will be downshifted and + // narrowed afterwards anyway. +.irp r, v2, v21, v3, v26, v27, v20, v22, v23 + smin_4s \r, \r, v5 +.endr +.irp r, v2, v21, v3, v26, v27, v20, v22, v23 + smax_4s \r, \r, v7 +.endr + + sqneg \o15\().4s, \o15\().4s // out15 + sqneg \o13\().4s, \o13\().4s // out13 + sqneg \o1\().4s, \o1\().4s // out1 + sqneg \o3\().4s, \o3\().4s // out3 + + mul_mls v24, v2, v21, v0.s[0], v0.s[0] // -> out8 (v24 or v23) + mul_mla v4, v2, v21, v0.s[0], v0.s[0] // -> out7 (v23 or v24) + mul_mla v6, v26, v3, v0.s[0], v0.s[0] // -> out5 (v21 or v26) + + srshr v24.4s, v24.4s, #12 // out8 + srshr v4.4s, v4.4s, #12 // out7 + srshr v5.4s, v6.4s, #12 // out5 + mul_mls v6, v26, v3, v0.s[0], v0.s[0] // -> out10 (v26 or v21) + mul_mla v2, v22, v23, v0.s[0], v0.s[0] // -> out4 (v20 or v27) + srshr v26.4s, v6.4s, #12 // out10 + + mul_mls v6, v22, v23, v0.s[0], v0.s[0] // -> out11 (v27 or v20) + mul_mla v22, v27, v20, v0.s[0], v0.s[0] // -> out6 (v22 or v25) + mul_mls v21, v27, v20, v0.s[0], v0.s[0] // -> out9 (v25 or v22) + + srshr \o4\().4s, v2.4s, #12 // out4 + srshr v6.4s, v6.4s, #12 // out11 + srshr v7.4s, v21.4s, #12 // out9 + srshr \o6\().4s, v22.4s, #12 // out6 + +.ifc \o8, v23 + mov \o8\().16b, v24.16b + mov \o10\().16b, v26.16b +.endif + + sqneg \o7\().4s, v4.4s // out7 + sqneg \o5\().4s, v5.4s // out5 + sqneg \o11\().4s, v6.4s // out11 + sqneg \o9\().4s, v7.4s // out9 +.endm + +function inv_adst_4s_x16_neon + AARCH64_VALID_CALL_TARGET + iadst_16 v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 + ret +endfunc + +function inv_flipadst_4s_x16_neon + AARCH64_VALID_CALL_TARGET + iadst_16 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16 + ret +endfunc + +function inv_identity_4s_x16_neon + AARCH64_VALID_CALL_TARGET + movz w16, #2*(5793-4096)*8, lsl #16 + dup v0.2s, w16 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + sqrdmulh v2.4s, v\i\().4s, v0.s[0] + sqadd v\i\().4s, v\i\().4s, v\i\().4s + sqadd v\i\().4s, v\i\().4s, v2.4s +.endr + ret +endfunc + +.macro identity_4x16_shift1 c +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + sqrdmulh v3.4s, \i, \c + srshr v3.4s, v3.4s, #1 + sqadd \i, \i, v3.4s +.endr +.endm + +.macro identity_4x16 c +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + sqrdmulh v3.4s, \i, \c + sqadd \i, \i, \i + sqadd \i, \i, v3.4s +.endr +.endm + +.macro def_horz_16 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_16x4_neon + mov x14, x30 + movi v7.4s, #0 +.if \scale + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.endif +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x7] + st1 {v7.4s}, [x7], x8 +.endr +.if \scale + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v0.s[0], v24, v25, v26, v27, v28, v29, v30, v31 +.endif + blr x4 + sqrshrn v16.4h, v16.4s, #\shift + sqrshrn v17.4h, v17.4s, #\shift + sqrshrn v18.4h, v18.4s, #\shift + sqrshrn v19.4h, v19.4s, #\shift + sqrshrn2 v16.8h, v20.4s, #\shift + sqrshrn2 v17.8h, v21.4s, #\shift + sqrshrn2 v18.8h, v22.4s, #\shift + sqrshrn2 v19.8h, v23.4s, #\shift + sqrshrn v20.4h, v24.4s, #\shift + sqrshrn v21.4h, v25.4s, #\shift + sqrshrn v22.4h, v26.4s, #\shift + sqrshrn v23.4h, v27.4s, #\shift + sqrshrn2 v20.8h, v28.4s, #\shift + sqrshrn2 v21.8h, v29.4s, #\shift + sqrshrn2 v22.8h, v30.4s, #\shift + sqrshrn2 v23.8h, v31.4s, #\shift + transpose_4x8h v16, v17, v18, v19, v4, v5, v6, v7 + transpose_4x8h v20, v21, v22, v23, v4, v5, v6, v7 + +.irp i, v16.8h, v20.8h, v17.8h, v21.8h, v18.8h, v22.8h, v19.8h, v23.8h + st1 {\i}, [x6], #16 +.endr + + ret x14 +endfunc +.endm + +def_horz_16 scale=0, shift=2 +def_horz_16 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_8x16_neon + mov x14, x30 +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + blr x5 + load_add_store_8x16 x6, x7 + ret x14 +endfunc + +function inv_txfm_add_16x16_neon + mov x15, x30 + sub sp, sp, #512 + ldrh w12, [x13], #2 +.irp i, 0, 4, 8, 12 + add x6, sp, #(\i*16*2) +.if \i > 0 + mov w8, #(16 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 12 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*4) + mov x8, #16*4 + bl inv_txfm_horz_16x4_neon +.endr + b 3f +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 2 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b +3: +.irp i, 0, 8 + add x6, x0, #(\i*2) + add x7, sp, #(\i*2) + mov x8, #32 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, sp, #512 + ret x15 +endfunc + +const eob_16x16 + .short 10, 36, 78, 256 +endconst + +const eob_16x16_identity + .short 4, 8, 12, 256 +endconst + +.macro def_fn_16x16 txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_16x16_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc 16, 16, 2 +.endif + adr x4, inv_\txfm1\()_4s_x16_neon + movrel x5, X(inv_\txfm2\()_8h_x16_neon) +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel x13, eob_16x16 +.else + movrel x13, eob_16x16_identity +.endif +.else +.ifc \txfm2, identity + movrel x13, eob_16x16_identity +.else + movrel x13, eob_16x16 +.endif +.endif + b inv_txfm_add_16x16_neon +endfunc +.endm + +def_fn_16x16 dct, dct +def_fn_16x16 identity, identity +def_fn_16x16 dct, adst +def_fn_16x16 dct, flipadst +def_fn_16x16 dct, identity +def_fn_16x16 adst, dct +def_fn_16x16 adst, adst +def_fn_16x16 adst, flipadst +def_fn_16x16 flipadst, dct +def_fn_16x16 flipadst, adst +def_fn_16x16 flipadst, flipadst +def_fn_16x16 identity, dct + +function inv_txfm_add_16x4_neon + mov x15, x30 + movi v4.4s, #0 + +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x2] + st1 {v4.4s}, [x2], #16 +.endr + + blr x4 + + sqrshrn v16.4h, v16.4s, #1 + sqrshrn v17.4h, v17.4s, #1 + sqrshrn v18.4h, v18.4s, #1 + sqrshrn v19.4h, v19.4s, #1 + sqrshrn2 v16.8h, v20.4s, #1 + sqrshrn2 v17.8h, v21.4s, #1 + sqrshrn2 v18.8h, v22.4s, #1 + sqrshrn2 v19.8h, v23.4s, #1 + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + blr x5 + mov x6, x0 + load_add_store_8x4 x6, x7 + + sqrshrn v16.4h, v24.4s, #1 + sqrshrn v17.4h, v25.4s, #1 + sqrshrn v18.4h, v26.4s, #1 + sqrshrn v19.4h, v27.4s, #1 + sqrshrn2 v16.8h, v28.4s, #1 + sqrshrn2 v17.8h, v29.4s, #1 + sqrshrn2 v18.8h, v30.4s, #1 + sqrshrn2 v19.8h, v31.4s, #1 + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + blr x5 + add x6, x0, #16 + load_add_store_8x4 x6, x7 + + ret x15 +endfunc + +function inv_txfm_add_4x16_neon + ldrh w12, [x13, #4] + mov x15, x30 + + mov x11, #64 + + cmp w3, w12 + ldrh w12, [x13, #2] + b.lt 1f + + add x6, x2, #48 + movi v2.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x6] + st1 {v2.4s}, [x6], x11 +.endr + blr x4 + sqrshrn v28.4h, v16.4s, #1 + sqrshrn v29.4h, v17.4s, #1 + sqrshrn v30.4h, v18.4s, #1 + sqrshrn v31.4h, v19.4s, #1 + transpose_4x4h v28, v29, v30, v31, v4, v5, v6, v7 + + b 2f +1: +.irp i, v28.4h, v29.4h, v30.4h, v31.4h + movi \i, #0 +.endr +2: + cmp w3, w12 + ldrh w12, [x13, #0] + b.lt 1f + + add x6, x2, #32 + movi v2.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x6] + st1 {v2.4s}, [x6], x11 +.endr + blr x4 + sqrshrn v24.4h, v16.4s, #1 + sqrshrn v25.4h, v17.4s, #1 + sqrshrn v26.4h, v18.4s, #1 + sqrshrn v27.4h, v19.4s, #1 + transpose_4x4h v24, v25, v26, v27, v4, v5, v6, v7 + + b 2f +1: +.irp i, v24.4h, v25.4h, v26.4h, v27.4h + movi \i, #0 +.endr +2: + cmp w3, w12 + b.lt 1f + + add x6, x2, #16 + movi v2.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x6] + st1 {v2.4s}, [x6], x11 +.endr + blr x4 + sqrshrn v20.4h, v16.4s, #1 + sqrshrn v21.4h, v17.4s, #1 + sqrshrn v22.4h, v18.4s, #1 + sqrshrn v23.4h, v19.4s, #1 + transpose_4x4h v20, v21, v22, v23, v4, v5, v6, v7 + + b 2f +1: +.irp i, v20.4h, v21.4h, v22.4h, v23.4h + movi \i, #0 +.endr +2: + + movi v2.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s + ld1 {\i}, [x2] + st1 {v2.4s}, [x2], x11 +.endr + blr x4 + sqrshrn v16.4h, v16.4s, #1 + sqrshrn v17.4h, v17.4s, #1 + sqrshrn v18.4h, v18.4s, #1 + sqrshrn v19.4h, v19.4s, #1 + transpose_4x8h v16, v17, v18, v19, v4, v5, v6, v7 + + blr x5 + + load_add_store_4x16 x0, x6 + + ret x15 +endfunc + +const eob_4x16 + .short 13, 29, 45, 64 +endconst + +const eob_4x16_identity1 + .short 16, 32, 48, 64 +endconst + +const eob_4x16_identity2 + .short 4, 8, 12, 64 +endconst + +.macro def_fn_416 w, h, txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif +.if \w == 4 + adr x4, inv_\txfm1\()_4s_x\w\()_neon + movrel x5, X(inv_\txfm2\()_4h_x\h\()_neon) +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel x13, eob_4x16 +.else + movrel x13, eob_4x16_identity1 +.endif +.else +.ifc \txfm2, identity + movrel x13, eob_4x16_identity2 +.else + movrel x13, eob_4x16 +.endif +.endif +.else + adr x4, inv_\txfm1\()_4s_x\w\()_neon + movrel x5, X(inv_\txfm2\()_8h_x\h\()_neon) +.endif + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_416 w, h +def_fn_416 \w, \h, dct, dct +def_fn_416 \w, \h, identity, identity +def_fn_416 \w, \h, dct, adst +def_fn_416 \w, \h, dct, flipadst +def_fn_416 \w, \h, dct, identity +def_fn_416 \w, \h, adst, dct +def_fn_416 \w, \h, adst, adst +def_fn_416 \w, \h, adst, flipadst +def_fn_416 \w, \h, flipadst, dct +def_fn_416 \w, \h, flipadst, adst +def_fn_416 \w, \h, flipadst, flipadst +def_fn_416 \w, \h, identity, dct +def_fn_416 \w, \h, adst, identity +def_fn_416 \w, \h, flipadst, identity +def_fn_416 \w, \h, identity, adst +def_fn_416 \w, \h, identity, flipadst +.endm + +def_fns_416 4, 16 +def_fns_416 16, 4 + + +function inv_txfm_add_16x8_neon + mov x15, x30 + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + cmp w3, w13 + mov x11, #32 + b.lt 1f + + movi v4.4s, #0 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 + + add x6, x2, #16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x6] + st1 {v4.4s}, [x6], x11 +.endr + + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v0.s[0], v24, v25, v26, v27, v28, v29, v30, v31 + blr x4 + + sqrshrn v8.4h, v16.4s, #1 + sqrshrn v9.4h, v17.4s, #1 + sqrshrn v10.4h, v18.4s, #1 + sqrshrn v11.4h, v19.4s, #1 + sqrshrn2 v8.8h, v20.4s, #1 + sqrshrn2 v9.8h, v21.4s, #1 + sqrshrn2 v10.8h, v22.4s, #1 + sqrshrn2 v11.8h, v23.4s, #1 + sqrshrn v12.4h, v24.4s, #1 + sqrshrn v13.4h, v25.4s, #1 + sqrshrn v14.4h, v26.4s, #1 + sqrshrn v15.4h, v27.4s, #1 + sqrshrn2 v12.8h, v28.4s, #1 + sqrshrn2 v13.8h, v29.4s, #1 + sqrshrn2 v14.8h, v30.4s, #1 + sqrshrn2 v15.8h, v31.4s, #1 + + transpose_4x8h v8, v9, v10, v11, v2, v3, v4, v5 + transpose_4x8h v12, v13, v14, v15, v2, v3, v4, v5 + + b 2f +1: +.irp i, v8.8h, v9.8h, v10.8h, v11.8h, v12.8h, v13.8h, v14.8h, v15.8h + movi \i, #0 +.endr +2: + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 + + movi v4.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x2] + st1 {v4.4s}, [x2], x11 +.endr + + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v0.s[0], v24, v25, v26, v27, v28, v29, v30, v31 + blr x4 + + sqrshrn v16.4h, v16.4s, #1 + sqrshrn v17.4h, v17.4s, #1 + sqrshrn v18.4h, v18.4s, #1 + sqrshrn v19.4h, v19.4s, #1 + sqrshrn2 v16.8h, v20.4s, #1 + sqrshrn2 v17.8h, v21.4s, #1 + sqrshrn2 v18.8h, v22.4s, #1 + sqrshrn2 v19.8h, v23.4s, #1 + + mov v20.16b, v8.16b + mov v21.16b, v9.16b + mov v22.16b, v10.16b + mov v23.16b, v11.16b + + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + + sqrshrn v8.4h, v24.4s, #1 + sqrshrn v9.4h, v25.4s, #1 + sqrshrn v10.4h, v26.4s, #1 + sqrshrn v11.4h, v27.4s, #1 + sqrshrn2 v8.8h, v28.4s, #1 + sqrshrn2 v9.8h, v29.4s, #1 + sqrshrn2 v10.8h, v30.4s, #1 + sqrshrn2 v11.8h, v31.4s, #1 + + transpose_4x8h v8, v9, v10, v11, v2, v3, v4, v5 + + blr x5 + + mov x6, x0 + load_add_store_8x8 x6, x7 + + mov v16.16b, v8.16b + mov v17.16b, v9.16b + mov v18.16b, v10.16b + mov v19.16b, v11.16b + mov v20.16b, v12.16b + mov v21.16b, v13.16b + mov v22.16b, v14.16b + mov v23.16b, v15.16b + + blr x5 + + add x0, x0, #16 + load_add_store_8x8 x0, x7 + + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret x15 +endfunc + +function inv_txfm_add_8x16_neon + mov x15, x30 + stp d8, d9, [sp, #-0x20]! + stp d10, d11, [sp, #0x10] + ldrh w12, [x13, #4] + + mov x11, #64 + + cmp w3, w12 + ldrh w12, [x13, #2] + b.lt 1f + + add x6, x2, #48 + movi v4.4s, #0 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x6] + st1 {v4.4s}, [x6], x11 +.endr + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + blr x4 + + sqrshrn v28.4h, v16.4s, #1 + sqrshrn v29.4h, v17.4s, #1 + sqrshrn v30.4h, v18.4s, #1 + sqrshrn v31.4h, v19.4s, #1 + sqrshrn2 v28.8h, v20.4s, #1 + sqrshrn2 v29.8h, v21.4s, #1 + sqrshrn2 v30.8h, v22.4s, #1 + sqrshrn2 v31.8h, v23.4s, #1 + transpose_4x8h v28, v29, v30, v31, v2, v3, v4, v5 + + b 2f + +1: +.irp i, v28.8h, v29.8h, v30.8h, v31.8h + movi \i, #0 +.endr + +2: + cmp w3, w12 + ldrh w12, [x13, #0] + b.lt 1f + + add x6, x2, #32 + movi v4.4s, #0 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x6] + st1 {v4.4s}, [x6], x11 +.endr + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + blr x4 + + sqrshrn v24.4h, v16.4s, #1 + sqrshrn v25.4h, v17.4s, #1 + sqrshrn v26.4h, v18.4s, #1 + sqrshrn v27.4h, v19.4s, #1 + sqrshrn2 v24.8h, v20.4s, #1 + sqrshrn2 v25.8h, v21.4s, #1 + sqrshrn2 v26.8h, v22.4s, #1 + sqrshrn2 v27.8h, v23.4s, #1 + transpose_4x8h v24, v25, v26, v27, v2, v3, v4, v5 + + b 2f + +1: +.irp i, v24.8h, v25.8h, v26.8h, v27.8h + movi \i, #0 +.endr + +2: + cmp w3, w12 + b.lt 1f + + add x6, x2, #16 + movi v4.4s, #0 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x6] + st1 {v4.4s}, [x6], x11 +.endr + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + blr x4 + + sqrshrn v8.4h, v16.4s, #1 + sqrshrn v9.4h, v17.4s, #1 + sqrshrn v10.4h, v18.4s, #1 + sqrshrn v11.4h, v19.4s, #1 + sqrshrn2 v8.8h, v20.4s, #1 + sqrshrn2 v9.8h, v21.4s, #1 + sqrshrn2 v10.8h, v22.4s, #1 + sqrshrn2 v11.8h, v23.4s, #1 + transpose_4x8h v8, v9, v10, v11, v2, v3, v4, v5 + + b 2f + +1: +.irp i, v8.8h, v9.8h, v10.8h, v11.8h + movi \i, #0 +.endr + +2: + movi v4.4s, #0 + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s + ld1 {\i}, [x2] + st1 {v4.4s}, [x2], x11 +.endr + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + blr x4 + + sqrshrn v16.4h, v16.4s, #1 + sqrshrn v17.4h, v17.4s, #1 + sqrshrn v18.4h, v18.4s, #1 + sqrshrn v19.4h, v19.4s, #1 + sqrshrn2 v16.8h, v20.4s, #1 + sqrshrn2 v17.8h, v21.4s, #1 + sqrshrn2 v18.8h, v22.4s, #1 + sqrshrn2 v19.8h, v23.4s, #1 + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + + mov v20.16b, v8.16b + mov v21.16b, v9.16b + mov v22.16b, v10.16b + mov v23.16b, v11.16b + + blr x5 + + load_add_store_8x16 x0, x6 + + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x20 + + ret x15 +endfunc + +const eob_8x16 + .short 10, 43, 75, 128 +endconst + +const eob_8x16_identity1 + .short 4, 64, 96, 128 +endconst + +const eob_8x16_identity2 + .short 4, 8, 12, 128 +endconst + +.macro def_fn_816 w, h, txfm1, txfm2 +function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_16bpc_neon, export=1 +.ifc \txfm1\()_\txfm2, dct_dct + idct_dc \w, \h, 1 +.endif + adr x4, inv_\txfm1\()_4s_x\w\()_neon + movrel x5, X(inv_\txfm2\()_8h_x\h\()_neon) +.ifc \txfm1, identity +.ifc \txfm2, identity + movrel x13, eob_8x16 +.else + movrel x13, eob_8x16_identity1 +.endif +.else +.ifc \txfm2, identity + movrel x13, eob_8x16_identity2 +.else + movrel x13, eob_8x16 +.endif +.endif +.if \h == 8 + ldrh w13, [x13] +.endif + b inv_txfm_add_\w\()x\h\()_neon +endfunc +.endm + +.macro def_fns_816 w, h +def_fn_816 \w, \h, dct, dct +def_fn_816 \w, \h, identity, identity +def_fn_816 \w, \h, dct, adst +def_fn_816 \w, \h, dct, flipadst +def_fn_816 \w, \h, dct, identity +def_fn_816 \w, \h, adst, dct +def_fn_816 \w, \h, adst, adst +def_fn_816 \w, \h, adst, flipadst +def_fn_816 \w, \h, flipadst, dct +def_fn_816 \w, \h, flipadst, adst +def_fn_816 \w, \h, flipadst, flipadst +def_fn_816 \w, \h, identity, dct +def_fn_816 \w, \h, adst, identity +def_fn_816 \w, \h, flipadst, identity +def_fn_816 \w, \h, identity, adst +def_fn_816 \w, \h, identity, flipadst +.endm + +def_fns_816 8, 16 +def_fns_816 16, 8 + +function inv_dct32_odd_4s_x16_neon + movrel x16, idct_coeffs, 4*16 + ld1 {v0.4s, v1.4s}, [x16], #32 + + mul_mls v2, v16, v31, v0.s[0], v0.s[1] // -> t16a + mul_mla v4, v16, v31, v0.s[1], v0.s[0] // -> t31a + mul_mls v6, v24, v23, v0.s[2], v0.s[3] // -> t17a + srshr v16.4s, v2.4s, #12 // t16a + srshr v31.4s, v4.4s, #12 // t31a + mul_mla v2, v24, v23, v0.s[3], v0.s[2] // -> t30a + mul_mls v4, v20, v27, v1.s[0], v1.s[1] // -> t18a + srshr v24.4s, v6.4s, #12 // t17a + srshr v23.4s, v2.4s, #12 // t30a + mul_mla v6, v20, v27, v1.s[1], v1.s[0] // -> t29a + mul_mls v2, v28, v19, v1.s[2], v1.s[3] // -> t19a + srshr v20.4s, v4.4s, #12 // t18a + srshr v27.4s, v6.4s, #12 // t29a + mul_mla v4, v28, v19, v1.s[3], v1.s[2] // -> t28a + ld1 {v0.4s, v1.4s}, [x16] + sub x16, x16, #4*24 + mul_mls v6, v18, v29, v0.s[0], v0.s[1] // -> t20a + srshr v28.4s, v2.4s, #12 // t19a + srshr v19.4s, v4.4s, #12 // t28a + mul_mla v2, v18, v29, v0.s[1], v0.s[0] // -> t27a + mul_mls v4, v26, v21, v0.s[2], v0.s[3] // -> t21a + srshr v18.4s, v6.4s, #12 // t20a + srshr v29.4s, v2.4s, #12 // t27a + mul_mla v6, v26, v21, v0.s[3], v0.s[2] // -> t26a + mul_mls v2, v22, v25, v1.s[0], v1.s[1] // -> t22a + srshr v26.4s, v4.4s, #12 // t21a + srshr v21.4s, v6.4s, #12 // t26a + mul_mla v4, v22, v25, v1.s[1], v1.s[0] // -> t25a + mul_mls v6, v30, v17, v1.s[2], v1.s[3] // -> t23a + srshr v22.4s, v2.4s, #12 // t22a + srshr v25.4s, v4.4s, #12 // t25a + mul_mla v2, v30, v17, v1.s[3], v1.s[2] // -> t24a + srshr v30.4s, v6.4s, #12 // t23a + srshr v17.4s, v2.4s, #12 // t24a + + ld1 {v0.4s, v1.4s}, [x16] + + movi v5.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + mvni v4.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + + sqsub v2.4s, v16.4s, v24.4s // t17 + sqadd v16.4s, v16.4s, v24.4s // t16 + sqsub v3.4s, v31.4s, v23.4s // t30 + sqadd v31.4s, v31.4s, v23.4s // t31 + sqsub v24.4s, v28.4s, v20.4s // t18 + sqadd v28.4s, v28.4s, v20.4s // t19 + sqadd v23.4s, v18.4s, v26.4s // t20 + sqsub v18.4s, v18.4s, v26.4s // t21 + sqsub v20.4s, v30.4s, v22.4s // t22 + sqadd v30.4s, v30.4s, v22.4s // t23 + sqadd v26.4s, v17.4s, v25.4s // t24 + sqsub v17.4s, v17.4s, v25.4s // t25 + sqsub v22.4s, v29.4s, v21.4s // t26 + sqadd v29.4s, v29.4s, v21.4s // t27 + sqadd v25.4s, v19.4s, v27.4s // t28 + sqsub v19.4s, v19.4s, v27.4s // t29 + +.irp r, v2, v16, v3, v31, v24, v28, v23, v18, v20, v30, v26, v17, v22, v29, v25, v19 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v2, v16, v3, v31, v24, v28, v23, v18, v20, v30, v26, v17, v22, v29, v25, v19 + smax \r\().4s, \r\().4s, v4.4s +.endr + + mul_mls v7, v3, v2, v1.s[0], v1.s[1] // -> t17a + mul_mla v6, v3, v2, v1.s[1], v1.s[0] // -> t30a + mul_mla v2, v19, v24, v1.s[1], v1.s[0] // -> t18a + srshr v21.4s, v7.4s, #12 // t17a + srshr v27.4s, v6.4s, #12 // t30a + neg v2.4s, v2.4s // -> t18a + mul_mls v7, v19, v24, v1.s[0], v1.s[1] // -> t29a + mul_mls v6, v22, v18, v1.s[2], v1.s[3] // -> t21a + srshr v19.4s, v2.4s, #12 // t18a + srshr v24.4s, v7.4s, #12 // t29a + mul_mla v2, v22, v18, v1.s[3], v1.s[2] // -> t26a + mul_mla v7, v17, v20, v1.s[3], v1.s[2] // -> t22a + srshr v22.4s, v6.4s, #12 // t21a + srshr v18.4s, v2.4s, #12 // t26a + neg v7.4s, v7.4s // -> t22a + mul_mls v6, v17, v20, v1.s[2], v1.s[3] // -> t25a + srshr v17.4s, v7.4s, #12 // t22a + srshr v20.4s, v6.4s, #12 // t25a + + sqsub v2.4s, v27.4s, v24.4s // t29 + sqadd v27.4s, v27.4s, v24.4s // t30 + sqsub v3.4s, v21.4s, v19.4s // t18 + sqadd v21.4s, v21.4s, v19.4s // t17 + sqsub v24.4s, v16.4s, v28.4s // t19a + sqadd v16.4s, v16.4s, v28.4s // t16a + sqsub v19.4s, v30.4s, v23.4s // t20a + sqadd v30.4s, v30.4s, v23.4s // t23a + sqsub v28.4s, v17.4s, v22.4s // t21 + sqadd v17.4s, v17.4s, v22.4s // t22 + sqadd v23.4s, v26.4s, v29.4s // t24a + sqsub v26.4s, v26.4s, v29.4s // t27a + sqadd v22.4s, v20.4s, v18.4s // t25 + sqsub v20.4s, v20.4s, v18.4s // t26 + sqsub v29.4s, v31.4s, v25.4s // t28a + sqadd v31.4s, v31.4s, v25.4s // t31a + +.irp r, v2, v27, v3, v21, v24, v16, v19, v30, v28, v17, v23, v26, v22, v20, v29, v31 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v2, v27, v3, v21, v24, v16, v19, v30, v28, v17, v23, v26, v22, v20, v29, v31 + smax \r\().4s, \r\().4s, v4.4s +.endr + + mul_mls v7, v2, v3, v0.s[2], v0.s[3] // -> t18a + mul_mla v6, v2, v3, v0.s[3], v0.s[2] // -> t29a + mul_mls v2, v29, v24, v0.s[2], v0.s[3] // -> t19 + srshr v18.4s, v7.4s, #12 // t18a + srshr v25.4s, v6.4s, #12 // t29a + mul_mla v7, v29, v24, v0.s[3], v0.s[2] // -> t28 + mul_mla v6, v26, v19, v0.s[3], v0.s[2] // -> t20 + srshr v29.4s, v2.4s, #12 // t19 + srshr v24.4s, v7.4s, #12 // t28 + neg v6.4s, v6.4s // -> t20 + mul_mls v2, v26, v19, v0.s[2], v0.s[3] // -> t27 + mul_mla v7, v20, v28, v0.s[3], v0.s[2] // -> t21a + srshr v26.4s, v6.4s, #12 // t20 + srshr v19.4s, v2.4s, #12 // t27 + neg v7.4s, v7.4s // -> t21a + mul_mls v6, v20, v28, v0.s[2], v0.s[3] // -> t26a + srshr v20.4s, v7.4s, #12 // t21a + srshr v28.4s, v6.4s, #12 // t26a + + sqsub v2.4s, v16.4s, v30.4s // t23 + sqadd v16.4s, v16.4s, v30.4s // t16 = out16 + sqsub v3.4s, v31.4s, v23.4s // t24 + sqadd v31.4s, v31.4s, v23.4s // t31 = out31 + sqsub v23.4s, v21.4s, v17.4s // t22a + sqadd v17.4s, v21.4s, v17.4s // t17a = out17 + sqadd v30.4s, v27.4s, v22.4s // t30a = out30 + sqsub v21.4s, v27.4s, v22.4s // t25a + sqsub v27.4s, v18.4s, v20.4s // t21 + sqadd v18.4s, v18.4s, v20.4s // t18 = out18 + sqadd v7.4s, v29.4s, v26.4s // t19a = out19 + sqsub v26.4s, v29.4s, v26.4s // t20a + sqadd v29.4s, v25.4s, v28.4s // t29 = out29 + sqsub v25.4s, v25.4s, v28.4s // t26 + sqadd v28.4s, v24.4s, v19.4s // t28a = out28 + sqsub v24.4s, v24.4s, v19.4s // t27a + mov v19.16b, v7.16b // out19 + +.irp r, v2, v16, v3, v31, v23, v17, v30, v21, v27, v18, v19, v26, v29, v25, v28, v24 + smin \r\().4s, \r\().4s, v5.4s +.endr +.irp r, v2, v16, v3, v31, v23, v17, v30, v21, v27, v18, v19, v26, v29, v25, v28, v24 + smax \r\().4s, \r\().4s, v4.4s +.endr + + mul_mls v7, v24, v26, v0.s[0], v0.s[0] // -> t20 + mul_mla v6, v24, v26, v0.s[0], v0.s[0] // -> t27 + srshr v20.4s, v7.4s, #12 // t20 + srshr v22.4s, v6.4s, #12 // t27 + + mul_mla v7, v25, v27, v0.s[0], v0.s[0] // -> t26a + mul_mls v6, v25, v27, v0.s[0], v0.s[0] // -> t21a + mov v27.16b, v22.16b // t27 + srshr v26.4s, v7.4s, #12 // t26a + + mul_mls v24, v21, v23, v0.s[0], v0.s[0] // -> t22 + mul_mla v7, v21, v23, v0.s[0], v0.s[0] // -> t25 + srshr v21.4s, v6.4s, #12 // t21a + srshr v22.4s, v24.4s, #12 // t22 + srshr v25.4s, v7.4s, #12 // t25 + + mul_mls v7, v3, v2, v0.s[0], v0.s[0] // -> t23a + mul_mla v6, v3, v2, v0.s[0], v0.s[0] // -> t24a + srshr v23.4s, v7.4s, #12 // t23a + srshr v24.4s, v6.4s, #12 // t24a + + ret +endfunc + +.macro def_horz_32 scale=0, shift=2, suffix +function inv_txfm_horz\suffix\()_dct_32x4_neon + mov x14, x30 + movi v7.4s, #0 + lsl x8, x8, #1 +.if \scale + movz w16, #2896*8, lsl #16 + dup v0.2s, w16 +.endif + +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x7] + st1 {v7.4s}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + add x7, x7, x8, lsr #1 +.if \scale + scale_input .4s, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v0.s[0], v24, v25, v26, v27, v28, v29, v30, v31 +.endif + bl inv_dct_4s_x16_neon + + // idct_16 leaves the row_clip_max/min constants in v5 and v4 +.irp r, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 + smin_4s \r, \r, v5 +.endr +.irp r, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 + smax_4s \r, \r, v4 +.endr + + transpose_4x4s v16, v17, v18, v19, v2, v3, v4, v5 + transpose_4x4s v20, v21, v22, v23, v2, v3, v4, v5 + transpose_4x4s v24, v25, v26, v27, v2, v3, v4, v5 + transpose_4x4s v28, v29, v30, v31, v2, v3, v4, v5 + +.macro store1 r0, r1, r2, r3 + st1 {\r0}, [x6], #16 + st1 {\r1}, [x6], #16 + st1 {\r2}, [x6], #16 + st1 {\r3}, [x6], #16 +.endm + store1 v16.4s, v20.4s, v24.4s, v28.4s + store1 v17.4s, v21.4s, v25.4s, v29.4s + store1 v18.4s, v22.4s, v26.4s, v30.4s + store1 v19.4s, v23.4s, v27.4s, v31.4s +.purgem store1 + sub x6, x6, #64*4 + + movi v7.4s, #0 +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + ld1 {\i}, [x7] + st1 {v7.4s}, [x7], x8 +.endr +.if \scale + // This relies on the fact that the idct also leaves the right coeff in v0.s[1] + scale_input .4s, v0.s[1], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v0.s[1], v24, v25, v26, v27, v28, v29, v30, v31 +.endif + bl inv_dct32_odd_4s_x16_neon + transpose_4x4s v31, v30, v29, v28, v2, v3, v4, v5 + transpose_4x4s v27, v26, v25, v24, v2, v3, v4, v5 + transpose_4x4s v23, v22, v21, v20, v2, v3, v4, v5 + transpose_4x4s v19, v18, v17, v16, v2, v3, v4, v5 +.macro store2 r0, r1, r2, r3, shift + ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [x6] + sqsub v4.4s, v0.4s, \r0 + sqadd v0.4s, v0.4s, \r0 + sqsub v5.4s, v1.4s, \r1 + sqadd v1.4s, v1.4s, \r1 + sqsub v6.4s, v2.4s, \r2 + sqadd v2.4s, v2.4s, \r2 + sqsub v7.4s, v3.4s, \r3 + sqadd v3.4s, v3.4s, \r3 + sqrshrn v0.4h, v0.4s, #\shift + sqrshrn2 v0.8h, v1.4s, #\shift + sqrshrn v1.4h, v2.4s, #\shift + sqrshrn2 v1.8h, v3.4s, #\shift + sqrshrn v2.4h, v7.4s, #\shift + sqrshrn2 v2.8h, v6.4s, #\shift + sqrshrn v3.4h, v5.4s, #\shift + sqrshrn2 v3.8h, v4.4s, #\shift + st1 {v0.8h, v1.8h}, [x6], #32 + rev64 v2.8h, v2.8h + rev64 v3.8h, v3.8h + st1 {v2.8h, v3.8h}, [x6], #32 +.endm + + store2 v31.4s, v27.4s, v23.4s, v19.4s, \shift + store2 v30.4s, v26.4s, v22.4s, v18.4s, \shift + store2 v29.4s, v25.4s, v21.4s, v17.4s, \shift + store2 v28.4s, v24.4s, v20.4s, v16.4s, \shift +.purgem store2 + ret x14 +endfunc +.endm + +def_horz_32 scale=0, shift=2 +def_horz_32 scale=1, shift=1, suffix=_scale + +function inv_txfm_add_vert_dct_8x32_neon + mov x14, x30 + lsl x8, x8, #1 + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + + bl X(inv_dct_8h_x16_neon) + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + st1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + add x7, x7, x8, lsr #1 + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ld1 {v\i\().8h}, [x7], x8 +.endr + sub x7, x7, x8, lsl #4 + sub x7, x7, x8, lsr #1 + bl X(inv_dct32_odd_8h_x16_neon) + + neg x9, x8 + mov x10, x6 + mvni v1.8h, #0xfc, lsl #8 // 0x3ff +.macro combine r0, r1, r2, r3, op, stride + ld1 {v5.8h}, [x7], \stride + ld1 {v2.8h}, [x10], x1 + ld1 {v6.8h}, [x7], \stride + ld1 {v3.8h}, [x10], x1 + \op v5.8h, v5.8h, \r0 + ld1 {v7.8h}, [x7], \stride + ld1 {v4.8h}, [x10], x1 + srshr v5.8h, v5.8h, #4 + \op v6.8h, v6.8h, \r1 + usqadd v2.8h, v5.8h + srshr v6.8h, v6.8h, #4 + \op v7.8h, v7.8h, \r2 + ld1 {v5.8h}, [x7], \stride + usqadd v3.8h, v6.8h + smin v2.8h, v2.8h, v1.8h + srshr v7.8h, v7.8h, #4 + \op v5.8h, v5.8h, \r3 + st1 {v2.8h}, [x6], x1 + ld1 {v2.8h}, [x10], x1 + usqadd v4.8h, v7.8h + smin v3.8h, v3.8h, v1.8h + srshr v5.8h, v5.8h, #4 + st1 {v3.8h}, [x6], x1 + usqadd v2.8h, v5.8h + smin v4.8h, v4.8h, v1.8h + st1 {v4.8h}, [x6], x1 + smin v2.8h, v2.8h, v1.8h + st1 {v2.8h}, [x6], x1 +.endm + combine v31.8h, v30.8h, v29.8h, v28.8h, sqadd, x8 + combine v27.8h, v26.8h, v25.8h, v24.8h, sqadd, x8 + combine v23.8h, v22.8h, v21.8h, v20.8h, sqadd, x8 + combine v19.8h, v18.8h, v17.8h, v16.8h, sqadd, x8 + sub x7, x7, x8 + combine v16.8h, v17.8h, v18.8h, v19.8h, sqsub, x9 + combine v20.8h, v21.8h, v22.8h, v23.8h, sqsub, x9 + combine v24.8h, v25.8h, v26.8h, v27.8h, sqsub, x9 + combine v28.8h, v29.8h, v30.8h, v31.8h, sqsub, x9 +.purgem combine + + ret x14 +endfunc + +const eob_32x32 + .short 10, 36, 78, 136, 210, 300, 406, 1024 +endconst + +const eob_16x32 + .short 10, 36, 78, 151, 215, 279, 343, 512 +endconst + +const eob_16x32_shortside + .short 10, 36, 78, 512 +endconst + +const eob_8x32 + .short 10, 43, 75, 107, 139, 171, 203, 256 +endconst + +function inv_txfm_add_identity_identity_32x32_16bpc_neon, export=1 + movi v0.8h, #0 + movi v1.8h, #0 + movrel x13, eob_32x32, 2 + + mov x8, #4*32 +1: + mov w9, #0 + movrel x12, eob_32x32, 2 +2: + add w9, w9, #8 + ld1 {v16.4s, v17.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v18.4s, v19.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v20.4s, v21.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v22.4s, v23.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v24.4s, v25.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v26.4s, v27.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v28.4s, v29.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v30.4s, v31.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v17.4s + sqxtn v17.4h, v18.4s + sqxtn2 v17.8h, v19.4s + sqxtn v18.4h, v20.4s + sqxtn2 v18.8h, v21.4s + sqxtn v19.4h, v22.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v24.4s + sqxtn2 v20.8h, v25.4s + sqxtn v21.4h, v26.4s + sqxtn2 v21.8h, v27.4s + sqxtn v22.4h, v28.4s + sqxtn2 v22.8h, v29.4s + sqxtn v23.4h, v30.4s + sqxtn2 v23.8h, v31.4s + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + + load_add_store_8x8 x0, x7, shiftbits=2 + ldrh w11, [x12], #4 + sub x0, x0, x1, lsl #3 + add x0, x0, #2*8 + cmp w3, w11 + b.ge 2b + + ldrh w11, [x13], #4 + cmp w3, w11 + b.lt 9f + + sub x0, x0, w9, uxtw #1 + add x0, x0, x1, lsl #3 + msub x2, x8, x9, x2 + add x2, x2, #4*8 + b 1b +9: + ret +endfunc + +.macro shift_16_regs op, shift +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + \op \i, \i, #\shift +.endr +.endm + +.macro def_identity_1632 w, h, wshort, hshort +function inv_txfm_add_identity_identity_\w\()x\h\()_16bpc_neon, export=1 + movz w16, #2896*8, lsl #16 + movz w17, #2*(5793-4096)*8, lsl #16 + movi v0.4s, #0 + movi v1.4s, #0 + movrel x13, eob_16x32\hshort, 2 + + mov x8, #4*\h +1: + mov w9, #0 + movrel x12, eob_16x32\wshort, 2 +2: + add w9, w9, #8 + ld1 {v16.4s, v17.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + dup v2.2s, w16 + ld1 {v18.4s, v19.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + mov v2.s[1], w17 + ld1 {v20.4s, v21.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v22.4s, v23.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v24.4s, v25.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v26.4s, v27.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v28.4s, v29.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v30.4s, v31.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + scale_input .4s, v2.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + scale_input .4s, v2.s[0], v24, v25, v26, v27, v28, v29, v30, v31 + +.if \w == 16 + // 16x32 + identity_4x16_shift1 v2.s[1] +.else + // 32x16 + shift_16_regs sqshl, 1 + identity_4x16 v2.s[1] +.endif + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v17.4s + sqxtn v17.4h, v18.4s + sqxtn2 v17.8h, v19.4s + sqxtn v18.4h, v20.4s + sqxtn2 v18.8h, v21.4s + sqxtn v19.4h, v22.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v24.4s + sqxtn2 v20.8h, v25.4s + sqxtn v21.4h, v26.4s + sqxtn2 v21.8h, v27.4s + sqxtn v22.4h, v28.4s + sqxtn2 v22.8h, v29.4s + sqxtn v23.4h, v30.4s + sqxtn2 v23.8h, v31.4s + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + +.if \w == 16 + load_add_store_8x8 x0, x7, shiftbits=2 +.else + load_add_store_8x8 x0, x7, shiftbits=4 +.endif + ldrh w11, [x12], #4 + sub x0, x0, x1, lsl #3 + add x0, x0, #16 + cmp w3, w11 + b.ge 2b + + ldrh w11, [x13], #4 + cmp w3, w11 + b.lt 9f + + sub x0, x0, w9, uxtw #1 + add x0, x0, x1, lsl #3 + msub x2, x8, x9, x2 + add x2, x2, #4*8 + b 1b +9: + ret +endfunc +.endm + +def_identity_1632 16, 32, _shortside, +def_identity_1632 32, 16, , _shortside + +.macro def_identity_832 w, h +function inv_txfm_add_identity_identity_\w\()x\h\()_16bpc_neon, export=1 + movi v0.4s, #0 + movi v1.4s, #0 + // Working on 8x8 blocks, read every other entry from eob_8x32 + movrel x13, eob_8x32, 2 + + mov w8, #4*\h +1: + // Working on 8x8 blocks, read every other entry from eob_8x32 + ldrh w12, [x13], #4 + ld1 {v16.4s, v17.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v18.4s, v19.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v20.4s, v21.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v22.4s, v23.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v24.4s, v25.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v26.4s, v27.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v28.4s, v29.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + ld1 {v30.4s, v31.4s}, [x2] + st1 {v0.4s, v1.4s}, [x2], x8 + +.if \w == 8 + sqrshrn v16.4h, v16.4s, #1 + sqrshrn2 v16.8h, v17.4s, #1 + sqrshrn v17.4h, v18.4s, #1 + sqrshrn2 v17.8h, v19.4s, #1 + sqrshrn v18.4h, v20.4s, #1 + sqrshrn2 v18.8h, v21.4s, #1 + sqrshrn v19.4h, v22.4s, #1 + sqrshrn2 v19.8h, v23.4s, #1 + sqrshrn v20.4h, v24.4s, #1 + sqrshrn2 v20.8h, v25.4s, #1 + sqrshrn v21.4h, v26.4s, #1 + sqrshrn2 v21.8h, v27.4s, #1 + sqrshrn v22.4h, v28.4s, #1 + sqrshrn2 v22.8h, v29.4s, #1 + sqrshrn v23.4h, v30.4s, #1 + sqrshrn2 v23.8h, v31.4s, #1 +.else + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v17.4s + sqxtn v17.4h, v18.4s + sqxtn2 v17.8h, v19.4s + sqxtn v18.4h, v20.4s + sqxtn2 v18.8h, v21.4s + sqxtn v19.4h, v22.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v24.4s + sqxtn2 v20.8h, v25.4s + sqxtn v21.4h, v26.4s + sqxtn2 v21.8h, v27.4s + sqxtn v22.4h, v28.4s + sqxtn2 v22.8h, v29.4s + sqxtn v23.4h, v30.4s + sqxtn2 v23.8h, v31.4s +.endif + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v4, v5 + + + cmp w3, w12 +.if \w == 8 + load_add_store_8x8 x0, x7, shiftbits=2 +.else + load_add_store_8x8 x0, x7, shiftbits=3 +.endif + + b.lt 9f +.if \w == 8 + sub x2, x2, x8, lsl #3 + add x2, x2, #4*8 +.else + sub x0, x0, x1, lsl #3 + add x0, x0, #2*8 +.endif + b 1b + +9: + ret +endfunc +.endm + +def_identity_832 8, 32 +def_identity_832 32, 8 + +function inv_txfm_add_dct_dct_32x32_16bpc_neon, export=1 + idct_dc 32, 32, 2 + + mov x15, x30 + sub sp, sp, #2048 + movrel x13, eob_32x32 + ldrh w12, [x13], #2 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, sp, #(\i*32*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 28 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*4) + mov x8, #32*4 + bl inv_txfm_horz_dct_32x4_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x6, x0, #(\i*2) + add x7, sp, #(\i*2) + mov x8, #32*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, sp, #2048 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_16x32_16bpc_neon, export=1 + idct_dc 16, 32, 1 + + mov x15, x30 + sub sp, sp, #1024 + movrel x13, eob_16x32 + ldrh w12, [x13], #2 + adr x4, inv_dct_4s_x16_neon + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, sp, #(\i*16*2) + add x7, x2, #(\i*4) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 28 + ldrh w12, [x13], #2 +.endif +.endif + mov x8, #4*32 + bl inv_txfm_horz_scale_16x4_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 2 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8 + add x6, x0, #(\i*2) + add x7, sp, #(\i*2) + mov x8, #16*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, sp, #1024 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x16_16bpc_neon, export=1 + idct_dc 32, 16, 1 + + mov x15, x30 + sub sp, sp, #1024 + + movrel x13, eob_16x32 + movrel x5, X(inv_dct_8h_x16_neon) + ldrh w12, [x13], #2 + +.irp i, 0, 4, 8, 12 + add x6, sp, #(\i*32*2) + add x7, x2, #(\i*4) +.if \i > 0 + mov w8, #(16 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 12 + ldrh w12, [x13], #2 +.endif +.endif + mov x8, #4*16 + bl inv_txfm_horz_scale_dct_32x4_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x6, x0, #(\i*2) + add x7, sp, #(\i*2) + mov x8, #32*2 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, sp, #1024 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_8x32_16bpc_neon, export=1 + idct_dc 8, 32, 2 + + mov x15, x30 + sub sp, sp, #512 + + movrel x13, eob_8x32 + + movi v28.4s, #0 + mov x8, #4*32 + mov w9, #32 + mov x6, sp + mov x7, x2 +1: +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + ld1 {v\i\().4s}, [x7] + st1 {v28.4s}, [x7], x8 +.endr + ldrh w12, [x13], #2 + sub w9, w9, #4 + sub x7, x7, x8, lsl #3 + add x7, x7, #4*4 + + bl inv_dct_4s_x8_neon + + sqrshrn v16.4h, v16.4s, #2 + sqrshrn v17.4h, v17.4s, #2 + sqrshrn v18.4h, v18.4s, #2 + sqrshrn v19.4h, v19.4s, #2 + sqrshrn2 v16.8h, v20.4s, #2 + sqrshrn2 v17.8h, v21.4s, #2 + sqrshrn2 v18.8h, v22.4s, #2 + sqrshrn2 v19.8h, v23.4s, #2 + + transpose_4x8h v16, v17, v18, v19, v2, v3, v4, v5 + + cmp w3, w12 + st1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x6], #64 + + b.ge 1b + cbz w9, 3f + + movi v29.8h, #0 + movi v30.8h, #0 + movi v31.8h, #0 +2: + subs w9, w9, #4 + st1 {v28.8h,v29.8h,v30.8h,v31.8h}, [x6], #64 + b.gt 2b + +3: + mov x6, x0 + mov x7, sp + mov x8, #8*2 + bl inv_txfm_add_vert_dct_8x32_neon + + add sp, sp, #512 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x8_16bpc_neon, export=1 + idct_dc 32, 8, 2 + + mov x15, x30 + sub sp, sp, #512 + +.irp i, 0, 4 + add x6, sp, #(\i*32*2) + add x7, x2, #(\i*4) +.if \i > 0 + cmp w3, #10 + b.lt 1f +.endif + mov x8, #8*4 + bl inv_txfm_horz_dct_32x4_neon +.endr + b 2f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + +2: + mov x8, #2*32 + mov w9, #0 +1: + add x6, x0, x9, lsl #1 + add x7, sp, x9, lsl #1 // #(\i*2) + +.irp i, 16, 17, 18, 19, 20, 21, 22, 23 + ld1 {v\i\().8h}, [x7], x8 +.endr + add w9, w9, #8 + + bl X(inv_dct_8h_x8_neon) + + cmp w9, #32 + + load_add_store_8x8 x6, x7 + + b.lt 1b + + add sp, sp, #512 + ret x15 +endfunc + +function inv_dct64_step1_neon + // in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + // in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + // in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + // in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + + ld1 {v0.4s, v1.4s}, [x17], #32 + + sqrdmulh v23.4s, v16.4s, v0.s[1] // t63a + sqrdmulh v16.4s, v16.4s, v0.s[0] // t32a + sqrdmulh v22.4s, v17.4s, v0.s[2] // t62a + sqrdmulh v17.4s, v17.4s, v0.s[3] // t33a + sqrdmulh v21.4s, v18.4s, v1.s[1] // t61a + sqrdmulh v18.4s, v18.4s, v1.s[0] // t34a + sqrdmulh v20.4s, v19.4s, v1.s[2] // t60a + sqrdmulh v19.4s, v19.4s, v1.s[3] // t35a + + ld1 {v0.4s}, [x17], #16 + + sqadd v24.4s, v16.4s, v17.4s // t32 + sqsub v25.4s, v16.4s, v17.4s // t33 + sqsub v26.4s, v19.4s, v18.4s // t34 + sqadd v27.4s, v19.4s, v18.4s // t35 + sqadd v28.4s, v20.4s, v21.4s // t60 + sqsub v29.4s, v20.4s, v21.4s // t61 + sqsub v30.4s, v23.4s, v22.4s // t62 + sqadd v31.4s, v23.4s, v22.4s // t63 + +.irp r, v24, v25, v26, v27, v28, v29, v30, v31 + smin_4s \r, \r, v5 +.endr +.irp r, v24, v25, v26, v27, v28, v29, v30, v31 + smax_4s \r, \r, v4 +.endr + + mul_mla v2, v29, v26, v0.s[0], v0.s[1] // -> t34a + mul_mls v7, v29, v26, v0.s[1], v0.s[0] // -> t61a + neg v2.4s, v2.4s // t34a + mul_mls v6, v30, v25, v0.s[1], v0.s[0] // -> t33a + srshr v26.4s, v2.4s, #12 // t34a + mul_mla v2, v30, v25, v0.s[0], v0.s[1] // -> t62a + srshr v29.4s, v7.4s, #12 // t61a + srshr v25.4s, v6.4s, #12 // t33a + srshr v30.4s, v2.4s, #12 // t62a + + sqadd v16.4s, v24.4s, v27.4s // t32a + sqsub v19.4s, v24.4s, v27.4s // t35a + sqadd v17.4s, v25.4s, v26.4s // t33 + sqsub v18.4s, v25.4s, v26.4s // t34 + sqsub v20.4s, v31.4s, v28.4s // t60a + sqadd v23.4s, v31.4s, v28.4s // t63a + sqsub v21.4s, v30.4s, v29.4s // t61 + sqadd v22.4s, v30.4s, v29.4s // t62 + +.irp r, v16, v19, v17, v18, v20, v23, v21, v22 + smin_4s \r, \r, v5 +.endr +.irp r, v16, v19, v17, v18, v20, v23, v21, v22 + smax_4s \r, \r, v4 +.endr + + mul_mla v2, v21, v18, v0.s[2], v0.s[3] // -> t61a + mul_mls v7, v21, v18, v0.s[3], v0.s[2] // -> t34a + mul_mla v6, v20, v19, v0.s[2], v0.s[3] // -> t60 + srshr v21.4s, v2.4s, #12 // t61a + srshr v18.4s, v7.4s, #12 // t34a + mul_mls v2, v20, v19, v0.s[3], v0.s[2] // -> t35 + srshr v20.4s, v6.4s, #12 // t60 + srshr v19.4s, v2.4s, #12 // t35 + + st1 {v16.4s, v17.4s, v18.4s, v19.4s}, [x6], #64 + st1 {v20.4s, v21.4s, v22.4s, v23.4s}, [x6], #64 + + ret +endfunc + +function inv_dct64_step2_neon + movrel x16, idct_coeffs + ld1 {v0.4s}, [x16] +1: + // t32a/33/34a/35/60/61a/62/63a + // t56a/57/58a/59/36/37a/38/39a + // t40a/41/42a/43/52/53a/54/55a + // t48a/49/50a/51/44/45a/46/47a + ldr q16, [x6, #4*4*0] // t32a + ldr q17, [x9, #4*4*8] // t39a + ldr q18, [x9, #4*4*0] // t63a + ldr q19, [x6, #4*4*8] // t56a + ldr q20, [x6, #4*4*16] // t40a + ldr q21, [x9, #4*4*24] // t47a + ldr q22, [x9, #4*4*16] // t55a + ldr q23, [x6, #4*4*24] // t48a + + sqadd v24.4s, v16.4s, v17.4s // t32 + sqsub v25.4s, v16.4s, v17.4s // t39 + sqadd v26.4s, v18.4s, v19.4s // t63 + sqsub v27.4s, v18.4s, v19.4s // t56 + sqsub v28.4s, v21.4s, v20.4s // t40 + sqadd v29.4s, v21.4s, v20.4s // t47 + sqadd v30.4s, v23.4s, v22.4s // t48 + sqsub v31.4s, v23.4s, v22.4s // t55 + +.irp r, v24, v25, v26, v27, v28, v29, v30, v31 + smin_4s \r, \r, v5 +.endr +.irp r, v24, v25, v26, v27, v28, v29, v30, v31 + smax_4s \r, \r, v4 +.endr + + mul_mla v2, v27, v25, v0.s[3], v0.s[2] // -> t56a + mul_mls v7, v27, v25, v0.s[2], v0.s[3] // -> t39a + mul_mla v6, v31, v28, v0.s[3], v0.s[2] // -> t40a + srshr v25.4s, v2.4s, #12 // t56a + srshr v27.4s, v7.4s, #12 // t39a + neg v6.4s, v6.4s // t40a + mul_mls v2, v31, v28, v0.s[2], v0.s[3] // -> t55a + srshr v31.4s, v6.4s, #12 // t40a + srshr v28.4s, v2.4s, #12 // t55a + + sqadd v16.4s, v24.4s, v29.4s // t32a + sqsub v19.4s, v24.4s, v29.4s // t47a + sqadd v17.4s, v27.4s, v31.4s // t39 + sqsub v18.4s, v27.4s, v31.4s // t40 + sqsub v20.4s, v26.4s, v30.4s // t48a + sqadd v23.4s, v26.4s, v30.4s // t63a + sqsub v21.4s, v25.4s, v28.4s // t55 + sqadd v22.4s, v25.4s, v28.4s // t56 + +.irp r, v16, v19, v17, v18, v20, v23, v21, v22 + smin_4s \r, \r, v5 +.endr +.irp r, v16, v19, v17, v18, v20, v23, v21, v22 + smax_4s \r, \r, v4 +.endr + + mul_mls v2, v21, v18, v0.s[0], v0.s[0] // -> t40a + mul_mla v7, v21, v18, v0.s[0], v0.s[0] // -> t55a + mul_mls v6, v20, v19, v0.s[0], v0.s[0] // -> t47 + srshr v18.4s, v2.4s, #12 // t40a + srshr v21.4s, v7.4s, #12 // t55a + mul_mla v2, v20, v19, v0.s[0], v0.s[0] // -> t48 + srshr v19.4s, v6.4s, #12 // t47 + srshr v20.4s, v2.4s, #12 // t48 + + str q16, [x6, #4*4*0] // t32a + str q17, [x9, #4*4*0] // t39 + str q18, [x6, #4*4*8] // t40a + str q19, [x9, #4*4*8] // t47 + str q20, [x6, #4*4*16] // t48 + str q21, [x9, #4*4*16] // t55a + str q22, [x6, #4*4*24] // t56 + str q23, [x9, #4*4*24] // t63a + + add x6, x6, #4*4 + sub x9, x9, #4*4 + cmp x6, x9 + b.lt 1b + ret +endfunc + +.macro load8 src, strd, zero, clear +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s +.if \clear + ld1 {\i}, [\src] + st1 {\zero}, [\src], \strd +.else + ld1 {\i}, [\src], \strd +.endif +.endr +.endm + +.macro store16 dst +.irp i, v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + st1 {\i}, [\dst], #16 +.endr +.endm + +.macro clear_upper8 +.irp i, v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s + movi \i, #0 +.endr +.endm + +.macro movi_if reg, val, cond +.if \cond + movi \reg, \val +.endif +.endm + +.macro movz16dup_if reg, gpr, val, cond +.if \cond + movz \gpr, \val, lsl #16 + dup \reg, \gpr +.endif +.endm + +.macro st1_if regs, dst, cond +.if \cond + st1 \regs, \dst +.endif +.endm + +.macro str_if reg, dst, cond +.if \cond + str \reg, \dst +.endif +.endm + +.macro stroff_if reg, dst, dstoff, cond +.if \cond + str \reg, \dst, \dstoff +.endif +.endm + +.macro scale_if cond, c, r0, r1, r2, r3, r4, r5, r6, r7 +.if \cond + scale_input .4s, \c, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endif +.endm + +.macro def_dct64_func suffix, clear=0, scale=0 +function inv_txfm_dct\suffix\()_4s_x64_neon + mov x14, x30 + mov x6, sp + lsl x8, x8, #2 + + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.4s, #0, \clear + load8 x7, x8, v7.4s, \clear + clear_upper8 + sub x7, x7, x8, lsl #3 + add x7, x7, x8, lsr #1 + scale_if \scale, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + + bl inv_dct_4s_x16_neon + + // idct_16 leaves the row_clip_max/min constants in v5 and v4 +.irp r, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 + smin_4s \r, \r, v5 +.endr +.irp r, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 + smax_4s \r, \r, v4 +.endr + + store16 x6 + + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.8h, #0, \clear + load8 x7, x8, v7.4s, \clear + clear_upper8 + sub x7, x7, x8, lsl #3 + lsr x8, x8, #1 + sub x7, x7, x8, lsr #1 + scale_if \scale, v0.s[0], v16, v17, v18, v19, v20, v21, v22, v23 + + bl inv_dct32_odd_4s_x16_neon + + add x10, x6, #16*15 + sub x6, x6, #16*16 + + mov x9, #-16 + + movi v1.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + mvni v0.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + +.macro store_addsub r0, r1, r2, r3 + ld1 {v2.4s}, [x6], #16 + ld1 {v3.4s}, [x6], #16 + sqadd v6.4s, v2.4s, \r0 + sqsub \r0, v2.4s, \r0 + ld1 {v4.4s}, [x6], #16 + sqadd v7.4s, v3.4s, \r1 + sqsub \r1, v3.4s, \r1 + smin v6.4s, v6.4s, v1.4s + smin \r0, \r0, v1.4s + ld1 {v5.4s}, [x6], #16 + sqadd v2.4s, v4.4s, \r2 + sub x6, x6, #16*4 + smax v6.4s, v6.4s, v0.4s + smax \r0, \r0, v0.4s + sqsub \r2, v4.4s, \r2 + smin v7.4s, v7.4s, v1.4s + smin \r1, \r1, v1.4s + st1 {v6.4s}, [x6], #16 + st1 {\r0}, [x10], x9 + smin v2.4s, v2.4s, v1.4s + smin \r2, \r2, v1.4s + smax v7.4s, v7.4s, v0.4s + smax \r1, \r1, v0.4s + sqadd v3.4s, v5.4s, \r3 + sqsub \r3, v5.4s, \r3 + smax v2.4s, v2.4s, v0.4s + smax \r2, \r2, v0.4s + smin v3.4s, v3.4s, v1.4s + smin \r3, \r3, v1.4s + st1 {v7.4s}, [x6], #16 + st1 {\r1}, [x10], x9 + smax v3.4s, v3.4s, v0.4s + smax \r3, \r3, v0.4s + st1 {v2.4s}, [x6], #16 + st1 {\r2}, [x10], x9 + st1 {v3.4s}, [x6], #16 + st1 {\r3}, [x10], x9 +.endm + store_addsub v31.4s, v30.4s, v29.4s, v28.4s + store_addsub v27.4s, v26.4s, v25.4s, v24.4s + store_addsub v23.4s, v22.4s, v21.4s, v20.4s + store_addsub v19.4s, v18.4s, v17.4s, v16.4s +.purgem store_addsub + + add x6, x6, #4*4*16 + + movrel x17, idct64_coeffs + movi v5.4s, #1, msl #16 // row_clip_max = ~(~bdmax << 7), 0x1ffff + mvni v4.4s, #1, msl #16 // row_clip_min = (~bdmax << 7), 0xfffe0000 + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.4s, #0, \clear + add x9, x7, x8, lsl #4 // offset 16 + add x10, x7, x8, lsl #3 // offset 8 + sub x9, x9, x8 // offset 15 + sub x11, x10, x8 // offset 7 + ld1 {v16.4s}, [x7] // in1 (offset 0) + ld1 {v17.4s}, [x9] // in31 (offset 15) + ld1 {v18.4s}, [x10] // in17 (offset 8) + ld1 {v19.4s}, [x11] // in15 (offset 7) + st1_if {v7.4s}, [x7], \clear + st1_if {v7.4s}, [x9], \clear + st1_if {v7.4s}, [x10], \clear + st1_if {v7.4s}, [x11], \clear + scale_if \scale, v0.s[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.4s, #0, \clear + add x7, x7, x8, lsl #2 // offset 4 + sub x9, x9, x8, lsl #2 // offset 11 + sub x10, x7, x8 // offset 3 + add x11, x9, x8 // offset 12 + ld1 {v16.4s}, [x10] // in7 (offset 3) + ld1 {v17.4s}, [x11] // in25 (offset 12) + ld1 {v18.4s}, [x9] // in23 (offset 11) + ld1 {v19.4s}, [x7] // in9 (offset 4) + st1_if {v7.4s}, [x7], \clear + st1_if {v7.4s}, [x9], \clear + st1_if {v7.4s}, [x10], \clear + st1_if {v7.4s}, [x11], \clear + scale_if \scale, v0.s[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.4s, #0, \clear + sub x10, x10, x8, lsl #1 // offset 1 + sub x9, x9, x8, lsl #1 // offset 9 + add x7, x7, x8 // offset 5 + add x11, x11, x8 // offset 13 + ldr q16, [x10, x8] // in5 (offset 2) + ldr q17, [x11] // in27 (offset 13) + ldr q18, [x9, x8] // in21 (offset 10) + ldr q19, [x7] // in11 (offset 5) + stroff_if q7, [x10, x8], \clear + str_if q7, [x11], \clear + stroff_if q7, [x9, x8], \clear + str_if q7, [x7], \clear + scale_if \scale, v0.s[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + movz16dup_if v0.2s, w16, #2896*8, \scale + movi_if v7.4s, #0, \clear + ldr q16, [x10] // in3 (offset 1) + ldr q17, [x11, x8] // in29 (offset 14) + ldr q18, [x9] // in19 (offset 9) + ldr q19, [x7, x8] // in13 (offset 6) + str_if q7, [x10], \clear + stroff_if q7, [x11, x8], \clear + str_if q7, [x9], \clear + stroff_if q7, [x7, x8], \clear + scale_if \scale, v0.s[0], v16, v17, v18, v19 + bl inv_dct64_step1_neon + + sub x6, x6, #4*4*32 + add x9, x6, #4*4*7 + + bl inv_dct64_step2_neon + + ret x14 +endfunc +.endm + +def_dct64_func _clear, clear=1 +def_dct64_func _clear_scale, clear=1, scale=1 + + +function inv_txfm_horz_dct_64x4_neon + mov x14, x30 + + mov x7, sp + add x8, sp, #4*4*(64 - 4) + add x9, x6, #2*56 + mov x10, #2*64 + mov x11, #-4*4*4 + + dup v7.4s, w12 +1: + ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [x7], #64 + ld1 {v28.4s, v29.4s, v30.4s, v31.4s}, [x8], x11 + ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [x7], #64 + ld1 {v24.4s, v25.4s, v26.4s, v27.4s}, [x8], x11 + transpose_4x4s v16, v17, v18, v19, v2, v3, v4, v5 + transpose_4x4s v20, v21, v22, v23, v2, v3, v4, v5 + transpose_4x4s v31, v30, v29, v28, v2, v3, v4, v5 + transpose_4x4s v27, v26, v25, v24, v2, v3, v4, v5 + +.macro store_addsub src0, src1, src2, src3 + sqsub v1.4s, \src0, \src1 + sqadd v0.4s, \src0, \src1 + sqsub v3.4s, \src2, \src3 + srshl v1.4s, v1.4s, v7.4s + sqadd v2.4s, \src2, \src3 + srshl v3.4s, v3.4s, v7.4s + srshl v0.4s, v0.4s, v7.4s + srshl v2.4s, v2.4s, v7.4s + sqxtn v3.4h, v3.4s + sqxtn2 v3.8h, v1.4s + sqxtn v0.4h, v0.4s + sqxtn2 v0.8h, v2.4s + rev64 v3.8h, v3.8h + st1 {v0.8h}, [x6], x10 + st1 {v3.8h}, [x9], x10 +.endm + store_addsub v16.4s, v31.4s, v20.4s, v27.4s + store_addsub v17.4s, v30.4s, v21.4s, v26.4s + store_addsub v18.4s, v29.4s, v22.4s, v25.4s + store_addsub v19.4s, v28.4s, v23.4s, v24.4s +.purgem store_addsub + sub x6, x6, x10, lsl #2 + sub x9, x9, x10, lsl #2 + add x6, x6, #16 + sub x9, x9, #16 + + cmp x7, x8 + b.lt 1b + ret x14 +endfunc + +function inv_txfm_add_vert_dct_8x64_neon + mov x14, x30 + lsl x8, x8, #1 + + mov x7, sp + add x8, sp, #2*8*(64 - 4) + add x9, x6, x1, lsl #6 + sub x9, x9, x1 + neg x10, x1 + mov x11, #-2*8*4 + +1: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x7], #64 + ld1 {v28.8h, v29.8h, v30.8h, v31.8h}, [x8], x11 + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x7], #64 + ld1 {v24.8h, v25.8h, v26.8h, v27.8h}, [x8], x11 + + mvni v7.8h, #0xfc, lsl #8 // 0x3ff +.macro add_dest_addsub src0, src1, src2, src3 + ld1 {v0.8h}, [x6], x1 + ld1 {v1.8h}, [x9], x10 + sqadd v4.8h, \src0, \src1 + ld1 {v2.8h}, [x6] + sqsub \src0, \src0, \src1 + ld1 {v3.8h}, [x9] + sqadd v5.8h, \src2, \src3 + sqsub \src2, \src2, \src3 + sub x6, x6, x1 + sub x9, x9, x10 + srshr v4.8h, v4.8h, #4 + srshr v5.8h, v5.8h, #4 + srshr \src0, \src0, #4 + usqadd v0.8h, v4.8h + srshr \src2, \src2, #4 + usqadd v1.8h, \src0 + usqadd v2.8h, v5.8h + smin v0.8h, v0.8h, v7.8h + usqadd v3.8h, \src2 + smin v1.8h, v1.8h, v7.8h + st1 {v0.8h}, [x6], x1 + smin v2.8h, v2.8h, v7.8h + st1 {v1.8h}, [x9], x10 + smin v3.8h, v3.8h, v7.8h + st1 {v2.8h}, [x6], x1 + st1 {v3.8h}, [x9], x10 +.endm + add_dest_addsub v16.8h, v31.8h, v17.8h, v30.8h + add_dest_addsub v18.8h, v29.8h, v19.8h, v28.8h + add_dest_addsub v20.8h, v27.8h, v21.8h, v26.8h + add_dest_addsub v22.8h, v25.8h, v23.8h, v24.8h +.purgem add_dest_addsub + cmp x7, x8 + b.lt 1b + + ret x14 +endfunc + +function inv_txfm_add_dct_dct_64x64_16bpc_neon, export=1 + idct_dc 64, 64, 2 + + mov x15, x30 + + sub_sp 64*32*2+64*4*4 + add x5, sp, #64*4*4 + + movrel x13, eob_32x32 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, x5, #(\i*64*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*4) + mov x8, #32*4 + mov x12, #-2 // shift + bl inv_txfm_dct_clear_4s_x64_neon + add x6, x5, #(\i*64*2) + bl inv_txfm_horz_dct_64x4_neon +.if \i < 28 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x7, x5, #(\i*2) + mov x8, #64*2 + bl X(inv_txfm_dct_8h_x64_neon) + add x6, x0, #(\i*2) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #64*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_64x32_16bpc_neon, export=1 + idct_dc 64, 32, 1 + + mov x15, x30 + + sub_sp 64*32*2+64*4*4 + add x5, sp, #64*4*4 + + movrel x13, eob_32x32 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, x5, #(\i*64*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*4) + mov x8, #32*4 + mov x12, #-1 // shift + bl inv_txfm_dct_clear_scale_4s_x64_neon + add x6, x5, #(\i*64*2) + bl inv_txfm_horz_dct_64x4_neon +.if \i < 28 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x6, x0, #(\i*2) + add x7, x5, #(\i*2) + mov x8, #64*2 + bl inv_txfm_add_vert_dct_8x32_neon +.endr + + add sp, x5, #64*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_32x64_16bpc_neon, export=1 + idct_dc 32, 64, 1 + + mov x15, x30 + + sub_sp 32*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_32x32 + ldrh w12, [x13], #2 + +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, x5, #(\i*32*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f + ldrh w12, [x13], #2 +.endif + add x7, x2, #(\i*4) + mov x8, #32*4 + bl inv_txfm_horz_scale_dct_32x4_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8, 16, 24 + add x7, x5, #(\i*2) + mov x8, #32*2 + bl X(inv_txfm_dct_8h_x64_neon) + add x6, x0, #(\i*2) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #32*32*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_64x16_16bpc_neon, export=1 + idct_dc 64, 16, 2 + + mov x15, x30 + + sub_sp 64*16*2+64*4*4 + add x4, sp, #64*4*4 + + movrel x13, eob_16x32 + +.irp i, 0, 4, 8, 12 + add x6, x4, #(\i*64*2) +.if \i > 0 + mov w8, #(16 - \i) + cmp w3, w12 + b.lt 1f +.endif + add x7, x2, #(\i*4) + mov x8, #16*4 + mov x12, #-2 // shift + bl inv_txfm_dct_clear_4s_x64_neon + add x6, x4, #(\i*64*2) + bl inv_txfm_horz_dct_64x4_neon +.if \i < 12 + ldrh w12, [x13], #2 +.endif +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #2 +.rept 4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: + movrel x5, X(inv_dct_8h_x16_neon) +.irp i, 0, 8, 16, 24, 32, 40, 48, 56 + add x6, x0, #(\i*2) + add x7, x4, #(\i*2) + mov x8, #64*2 + bl inv_txfm_add_vert_8x16_neon +.endr + + add sp, x4, #64*16*2 + ret x15 +endfunc + +function inv_txfm_add_dct_dct_16x64_16bpc_neon, export=1 + idct_dc 16, 64, 2 + + mov x15, x30 + + sub_sp 16*32*2+64*8*2 + add x5, sp, #64*8*2 + + movrel x13, eob_16x32 + ldrh w12, [x13], #2 + + adr x4, inv_dct_4s_x16_neon +.irp i, 0, 4, 8, 12, 16, 20, 24, 28 + add x6, x5, #(\i*16*2) +.if \i > 0 + mov w8, #(32 - \i) + cmp w3, w12 + b.lt 1f +.if \i < 28 + ldrh w12, [x13], #2 +.endif +.endif + add x7, x2, #(\i*4) + mov x8, #32*4 + bl inv_txfm_horz_16x4_neon +.endr + b 3f + +1: + movi v4.8h, #0 + movi v5.8h, #0 + movi v6.8h, #0 + movi v7.8h, #0 +2: + subs w8, w8, #4 +.rept 2 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x6], #64 +.endr + b.gt 2b + +3: +.irp i, 0, 8 + add x7, x5, #(\i*2) + mov x8, #16*2 + bl X(inv_txfm_dct_8h_x64_neon) + add x6, x0, #(\i*2) + bl inv_txfm_add_vert_dct_8x64_neon +.endr + + add sp, x5, #16*32*2 + ret x15 +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1129 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// depending on how many pixels need to be stored, returns: +// x14 = (1 << 0) : 0 pixels +// x14 = (1 << 4) : inner 4 pixels +// x14 = (1 << 6) : inner 6 pixels +// x14 = 0 : all pixels +.macro loop_filter wd +function lpf_16_wd\wd\()_neon + uabd v0.16b, v22.16b, v23.16b // abs(p1 - p0) + uabd v1.16b, v25.16b, v24.16b // abs(q1 - q0) + uabd v2.16b, v23.16b, v24.16b // abs(p0 - q0) + uabd v3.16b, v22.16b, v25.16b // abs(p1 - q1) +.if \wd >= 6 + uabd v4.16b, v21.16b, v22.16b // abs(p2 - p1) + uabd v5.16b, v26.16b, v25.16b // abs(q2 - q1) +.endif +.if \wd >= 8 + uabd v6.16b, v20.16b, v21.16b // abs(p3 - p2) + uabd v7.16b, v27.16b, v26.16b // abs(q3 - q3) +.endif +.if \wd >= 6 + umax v4.16b, v4.16b, v5.16b +.endif + uqadd v2.16b, v2.16b, v2.16b // abs(p0 - q0) * 2 +.if \wd >= 8 + umax v6.16b, v6.16b, v7.16b +.endif + ushr v3.16b, v3.16b, #1 +.if \wd >= 8 + umax v4.16b, v4.16b, v6.16b +.endif +.if \wd >= 6 + and v4.16b, v4.16b, v14.16b +.endif + umax v0.16b, v0.16b, v1.16b // max(abs(p1 - p0), abs(q1 - q0)) + uqadd v2.16b, v2.16b, v3.16b // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 +.if \wd >= 6 + umax v4.16b, v0.16b, v4.16b + cmhs v1.16b, v11.16b, v4.16b // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I +.else + cmhs v1.16b, v11.16b, v0.16b // max(abs(p1 - p0), abs(q1 - q0)) <= I +.endif + cmhs v2.16b, v10.16b, v2.16b // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E + and v1.16b, v1.16b, v2.16b // fm + and v1.16b, v1.16b, v13.16b // fm && wd >= 4 +.if \wd >= 6 + and v14.16b, v14.16b, v1.16b // fm && wd > 4 +.endif +.if \wd >= 16 + and v15.16b, v15.16b, v1.16b // fm && wd == 16 +.endif + + mov x16, v1.d[0] + mov x17, v1.d[1] + adds x16, x16, x17 + b.ne 9f // if (!fm || wd < 4) return; + mov x14, #(1 << 0) + ret +9: +.if \wd >= 6 + movi v10.16b, #1 + uabd v2.16b, v21.16b, v23.16b // abs(p2 - p0) + uabd v3.16b, v22.16b, v23.16b // abs(p1 - p0) + uabd v4.16b, v25.16b, v24.16b // abs(q1 - q0) + uabd v5.16b, v26.16b, v24.16b // abs(q2 - q0) +.if \wd >= 8 + uabd v6.16b, v20.16b, v23.16b // abs(p3 - p0) + uabd v7.16b, v27.16b, v24.16b // abs(q3 - q0) +.endif + umax v2.16b, v2.16b, v3.16b + umax v4.16b, v4.16b, v5.16b +.if \wd >= 8 + umax v6.16b, v6.16b, v7.16b +.endif + umax v2.16b, v2.16b, v4.16b +.if \wd >= 8 + umax v2.16b, v2.16b, v6.16b +.endif + +.if \wd == 16 + uabd v3.16b, v17.16b, v23.16b // abs(p6 - p0) + uabd v4.16b, v18.16b, v23.16b // abs(p5 - p0) + uabd v5.16b, v19.16b, v23.16b // abs(p4 - p0) +.endif + cmhs v2.16b, v10.16b, v2.16b // flat8in +.if \wd == 16 + uabd v6.16b, v28.16b, v24.16b // abs(q4 - q0) + uabd v7.16b, v29.16b, v24.16b // abs(q5 - q0) + uabd v8.16b, v30.16b, v24.16b // abs(q6 - q0) +.endif + and v14.16b, v2.16b, v14.16b // flat8in && fm && wd > 4 + bic v1.16b, v1.16b, v14.16b // fm && wd >= 4 && !flat8in +.if \wd == 16 + umax v3.16b, v3.16b, v4.16b + umax v5.16b, v5.16b, v6.16b +.endif + mov x16, v1.d[0] + mov x17, v1.d[1] +.if \wd == 16 + umax v7.16b, v7.16b, v8.16b + umax v3.16b, v3.16b, v5.16b + umax v3.16b, v3.16b, v7.16b + cmhs v3.16b, v10.16b, v3.16b // flat8out +.endif + adds x16, x16, x17 +.if \wd == 16 + and v15.16b, v15.16b, v3.16b // flat8out && fm && wd == 16 + and v15.16b, v15.16b, v14.16b // flat8out && flat8in && fm && wd == 16 + bic v14.16b, v14.16b, v15.16b // flat8in && fm && wd >= 4 && !flat8out +.endif + b.eq 1f // skip wd == 4 case +.endif + movi v3.16b, #128 + eor v2.16b, v22.16b, v3.16b // p1 - 128 + eor v3.16b, v25.16b, v3.16b // q1 - 128 + cmhi v0.16b, v0.16b, v12.16b // hev + sqsub v2.16b, v2.16b, v3.16b // iclip_diff(p1 - q1) + and v4.16b, v2.16b, v0.16b // if (hev) iclip_diff(p1 - q1) + bic v0.16b, v1.16b, v0.16b // (fm && wd >= 4 && !hev) + usubl v2.8h, v24.8b, v23.8b + movi v5.8h, #3 + usubl2 v3.8h, v24.16b, v23.16b + mul v2.8h, v2.8h, v5.8h + mul v3.8h, v3.8h, v5.8h + movi v6.16b, #4 + saddw v2.8h, v2.8h, v4.8b + saddw2 v3.8h, v3.8h, v4.16b + movi v7.16b, #3 + sqxtn v2.8b, v2.8h // f + sqxtn2 v2.16b, v3.8h + sqadd v4.16b, v6.16b, v2.16b // imin(f + 4, 127) + sqadd v5.16b, v7.16b, v2.16b // imin(f + 3, 127) + sshr v4.16b, v4.16b, #3 // f1 + sshr v5.16b, v5.16b, #3 // f2 + mov v2.16b, v23.16b // p0 + mov v3.16b, v24.16b // q0 + neg v6.16b, v4.16b // -f1 + srshr v4.16b, v4.16b, #1 // (f1 + 1) >> 1 + // p0 + f2, q0 - f1 + usqadd v2.16b, v5.16b // out p0 + usqadd v3.16b, v6.16b // out q0 + neg v6.16b, v4.16b // -((f1 + 1) >> 1) + bit v23.16b, v2.16b, v1.16b // if (fm && wd >= 4) + bit v24.16b, v3.16b, v1.16b // if (fm && wd >= 4) + mov v2.16b, v22.16b // p1 + mov v3.16b, v25.16b // q1 + // p1 + ((f1 + 1) >> 1), q1 - ((f1 + 1) >> 1) + usqadd v2.16b, v4.16b // out p1 + usqadd v3.16b, v6.16b // out q1 + bit v22.16b, v2.16b, v0.16b // if (fm && wd >= 4 && !hev) + bit v25.16b, v3.16b, v0.16b // if (fm && wd >= 4 && !hev) +1: + +.if \wd == 6 + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 + b.eq 2f // skip if there's no flat8in + + uaddl v0.8h, v21.8b, v21.8b // p2 * 2 + uaddl2 v1.8h, v21.16b, v21.16b + uaddl v2.8h, v21.8b, v22.8b // p2 + p1 + uaddl2 v3.8h, v21.16b, v22.16b + uaddl v4.8h, v22.8b, v23.8b // p1 + p0 + uaddl2 v5.8h, v22.16b, v23.16b + uaddl v6.8h, v23.8b, v24.8b // p0 + q0 + uaddl2 v7.8h, v23.16b, v24.16b + add v8.8h, v0.8h, v2.8h + add v9.8h, v1.8h, v3.8h + add v10.8h, v4.8h, v6.8h + add v11.8h, v5.8h, v7.8h + uaddl v12.8h, v24.8b, v25.8b // q0 + q1 + uaddl2 v13.8h, v24.16b, v25.16b + add v8.8h, v8.8h, v10.8h + add v9.8h, v9.8h, v11.8h + sub v12.8h, v12.8h, v0.8h + sub v13.8h, v13.8h, v1.8h + uaddl v10.8h, v25.8b, v26.8b // q1 + q2 + uaddl2 v11.8h, v25.16b, v26.16b + rshrn v0.8b, v8.8h, #3 // out p1 + rshrn2 v0.16b, v9.8h, #3 + + add v8.8h, v8.8h, v12.8h + add v9.8h, v9.8h, v13.8h + sub v10.8h, v10.8h, v2.8h + sub v11.8h, v11.8h, v3.8h + uaddl v12.8h, v26.8b, v26.8b // q2 + q2 + uaddl2 v13.8h, v26.16b, v26.16b + rshrn v1.8b, v8.8h, #3 // out p0 + rshrn2 v1.16b, v9.8h, #3 + + add v8.8h, v8.8h, v10.8h + add v9.8h, v9.8h, v11.8h + sub v12.8h, v12.8h, v4.8h + sub v13.8h, v13.8h, v5.8h + rshrn v2.8b, v8.8h, #3 // out q0 + rshrn2 v2.16b, v9.8h, #3 + + bit v22.16b, v0.16b, v14.16b // p1 if (flat8in) + add v8.8h, v8.8h, v12.8h + add v9.8h, v9.8h, v13.8h + bit v23.16b, v1.16b, v14.16b // p0 if (flat8in) + rshrn v3.8b, v8.8h, #3 // out q1 + rshrn2 v3.16b, v9.8h, #3 + bit v24.16b, v2.16b, v14.16b // q0 if (flat8in) + bit v25.16b, v3.16b, v14.16b // q1 if (flat8in) +.elseif \wd >= 8 + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 +.if \wd == 8 + b.eq 8f // skip if there's no flat8in +.else + b.eq 2f // skip if there's no flat8in +.endif + + uaddl v0.8h, v20.8b, v21.8b // p3 + p2 + uaddl2 v1.8h, v20.16b, v21.16b + uaddl v2.8h, v22.8b, v25.8b // p1 + q1 + uaddl2 v3.8h, v22.16b, v25.16b + uaddl v4.8h, v20.8b, v22.8b // p3 + p1 + uaddl2 v5.8h, v20.16b, v22.16b + uaddl v6.8h, v23.8b, v26.8b // p0 + q2 + uaddl2 v7.8h, v23.16b, v26.16b + add v8.8h, v0.8h, v0.8h // 2 * (p3 + p2) + add v9.8h, v1.8h, v1.8h + uaddw v8.8h, v8.8h, v23.8b // + p0 + uaddw2 v9.8h, v9.8h, v23.16b + uaddw v8.8h, v8.8h, v24.8b // + q0 + uaddw2 v9.8h, v9.8h, v24.16b + add v8.8h, v8.8h, v4.8h + add v9.8h, v9.8h, v5.8h // + p3 + p1 + sub v2.8h, v2.8h, v0.8h // p1 + q1 - p3 - p2 + sub v3.8h, v3.8h, v1.8h + sub v6.8h, v6.8h, v4.8h // p0 + q2 - p3 - p1 + sub v7.8h, v7.8h, v5.8h + rshrn v10.8b, v8.8h, #3 // out p2 + rshrn2 v10.16b, v9.8h, #3 + + add v8.8h, v8.8h, v2.8h + add v9.8h, v9.8h, v3.8h + uaddl v0.8h, v20.8b, v23.8b // p3 + p0 + uaddl2 v1.8h, v20.16b, v23.16b + uaddl v2.8h, v24.8b, v27.8b // q0 + q3 + uaddl2 v3.8h, v24.16b, v27.16b + rshrn v11.8b, v8.8h, #3 // out p1 + rshrn2 v11.16b, v9.8h, #3 + + add v8.8h, v8.8h, v6.8h + add v9.8h, v9.8h, v7.8h + sub v2.8h, v2.8h, v0.8h // q0 + q3 - p3 - p0 + sub v3.8h, v3.8h, v1.8h + uaddl v4.8h, v21.8b, v24.8b // p2 + q0 + uaddl2 v5.8h, v21.16b, v24.16b + uaddl v6.8h, v25.8b, v27.8b // q1 + q3 + uaddl2 v7.8h, v25.16b, v27.16b + rshrn v12.8b, v8.8h, #3 // out p0 + rshrn2 v12.16b, v9.8h, #3 + + add v8.8h, v8.8h, v2.8h + add v9.8h, v9.8h, v3.8h + sub v6.8h, v6.8h, v4.8h // q1 + q3 - p2 - q0 + sub v7.8h, v7.8h, v5.8h + uaddl v0.8h, v22.8b, v25.8b // p1 + q1 + uaddl2 v1.8h, v22.16b, v25.16b + uaddl v2.8h, v26.8b, v27.8b // q2 + q3 + uaddl2 v3.8h, v26.16b, v27.16b + rshrn v13.8b, v8.8h, #3 // out q0 + rshrn2 v13.16b, v9.8h, #3 + + add v8.8h, v8.8h, v6.8h + add v9.8h, v9.8h, v7.8h + sub v2.8h, v2.8h, v0.8h // q2 + q3 - p1 - q1 + sub v3.8h, v3.8h, v1.8h + rshrn v0.8b, v8.8h, #3 // out q1 + rshrn2 v0.16b, v9.8h, #3 + + add v8.8h, v8.8h, v2.8h + add v9.8h , v9.8h, v3.8h + + bit v21.16b, v10.16b, v14.16b + bit v22.16b, v11.16b, v14.16b + bit v23.16b, v12.16b, v14.16b + rshrn v1.8b, v8.8h, #3 // out q2 + rshrn2 v1.16b, v9.8h, #3 + bit v24.16b, v13.16b, v14.16b + bit v25.16b, v0.16b, v14.16b + bit v26.16b, v1.16b, v14.16b +.endif +2: +.if \wd == 16 + mov x16, v15.d[0] + mov x17, v15.d[1] + adds x16, x16, x17 + b.ne 1f // check if flat8out is needed + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 + b.eq 8f // if there was no flat8in, just write the inner 4 pixels + b 7f // if flat8in was used, write the inner 6 pixels +1: + + uaddl v2.8h, v17.8b, v17.8b // p6 + p6 + uaddl2 v3.8h, v17.16b, v17.16b + uaddl v4.8h, v17.8b, v18.8b // p6 + p5 + uaddl2 v5.8h, v17.16b, v18.16b + uaddl v6.8h, v17.8b, v19.8b // p6 + p4 + uaddl2 v7.8h, v17.16b, v19.16b + uaddl v8.8h, v17.8b, v20.8b // p6 + p3 + uaddl2 v9.8h, v17.16b, v20.16b + add v12.8h, v2.8h, v4.8h + add v13.8h, v3.8h, v5.8h + add v10.8h, v6.8h, v8.8h + add v11.8h, v7.8h, v9.8h + uaddl v6.8h, v17.8b, v21.8b // p6 + p2 + uaddl2 v7.8h, v17.16b, v21.16b + add v12.8h, v12.8h, v10.8h + add v13.8h, v13.8h, v11.8h + uaddl v8.8h, v17.8b, v22.8b // p6 + p1 + uaddl2 v9.8h, v17.16b, v22.16b + uaddl v10.8h, v18.8b, v23.8b // p5 + p0 + uaddl2 v11.8h, v18.16b, v23.16b + add v6.8h, v6.8h, v8.8h + add v7.8h, v7.8h, v9.8h + uaddl v8.8h, v19.8b, v24.8b // p4 + q0 + uaddl2 v9.8h, v19.16b, v24.16b + add v12.8h, v12.8h, v6.8h + add v13.8h, v13.8h, v7.8h + add v10.8h, v10.8h, v8.8h + add v11.8h, v11.8h, v9.8h + uaddl v6.8h, v20.8b, v25.8b // p3 + q1 + uaddl2 v7.8h, v20.16b, v25.16b + add v12.8h, v12.8h, v10.8h + add v13.8h, v13.8h, v11.8h + sub v6.8h, v6.8h, v2.8h + sub v7.8h, v7.8h, v3.8h + uaddl v2.8h, v21.8b, v26.8b // p2 + q2 + uaddl2 v3.8h, v21.16b, v26.16b + rshrn v0.8b, v12.8h, #4 // out p5 + rshrn2 v0.16b, v13.8h, #4 + add v12.8h, v12.8h, v6.8h // - (p6 + p6) + (p3 + q1) + add v13.8h, v13.8h, v7.8h + sub v2.8h, v2.8h, v4.8h + sub v3.8h, v3.8h, v5.8h + uaddl v4.8h, v22.8b, v27.8b // p1 + q3 + uaddl2 v5.8h, v22.16b, v27.16b + uaddl v6.8h, v17.8b, v19.8b // p6 + p4 + uaddl2 v7.8h, v17.16b, v19.16b + rshrn v1.8b, v12.8h, #4 // out p4 + rshrn2 v1.16b, v13.8h, #4 + add v12.8h, v12.8h, v2.8h // - (p6 + p5) + (p2 + q2) + add v13.8h, v13.8h, v3.8h + sub v4.8h, v4.8h, v6.8h + sub v5.8h, v5.8h, v7.8h + uaddl v6.8h, v23.8b, v28.8b // p0 + q4 + uaddl2 v7.8h, v23.16b, v28.16b + uaddl v8.8h, v17.8b, v20.8b // p6 + p3 + uaddl2 v9.8h, v17.16b, v20.16b + rshrn v2.8b, v12.8h, #4 // out p3 + rshrn2 v2.16b, v13.8h, #4 + add v12.8h, v12.8h, v4.8h // - (p6 + p4) + (p1 + q3) + add v13.8h, v13.8h, v5.8h + sub v6.8h, v6.8h, v8.8h + sub v7.8h, v7.8h, v9.8h + uaddl v8.8h, v24.8b, v29.8b // q0 + q5 + uaddl2 v9.8h, v24.16b, v29.16b + uaddl v4.8h, v17.8b, v21.8b // p6 + p2 + uaddl2 v5.8h, v17.16b, v21.16b + rshrn v3.8b, v12.8h, #4 // out p2 + rshrn2 v3.16b, v13.8h, #4 + add v12.8h, v12.8h, v6.8h // - (p6 + p3) + (p0 + q4) + add v13.8h, v13.8h, v7.8h + sub v8.8h, v8.8h, v4.8h + sub v9.8h, v9.8h, v5.8h + uaddl v6.8h, v25.8b, v30.8b // q1 + q6 + uaddl2 v7.8h, v25.16b, v30.16b + uaddl v10.8h, v17.8b, v22.8b // p6 + p1 + uaddl2 v11.8h, v17.16b, v22.16b + rshrn v4.8b, v12.8h, #4 // out p1 + rshrn2 v4.16b, v13.8h, #4 + add v12.8h, v12.8h, v8.8h // - (p6 + p2) + (q0 + q5) + add v13.8h, v13.8h, v9.8h + sub v6.8h, v6.8h, v10.8h + sub v7.8h, v7.8h, v11.8h + uaddl v8.8h, v26.8b, v30.8b // q2 + q6 + uaddl2 v9.8h, v26.16b, v30.16b + bif v0.16b, v18.16b, v15.16b // out p5 + uaddl v10.8h, v18.8b, v23.8b // p5 + p0 + uaddl2 v11.8h, v18.16b, v23.16b + rshrn v5.8b, v12.8h, #4 // out p0 + rshrn2 v5.16b, v13.8h, #4 + add v12.8h, v12.8h, v6.8h // - (p6 + p1) + (q1 + q6) + add v13.8h, v13.8h, v7.8h + sub v8.8h, v8.8h, v10.8h + sub v9.8h, v9.8h, v11.8h + uaddl v10.8h, v27.8b, v30.8b // q3 + q6 + uaddl2 v11.8h, v27.16b, v30.16b + bif v1.16b, v19.16b, v15.16b // out p4 + uaddl v18.8h, v19.8b, v24.8b // p4 + q0 + uaddl2 v19.8h, v19.16b, v24.16b + rshrn v6.8b, v12.8h, #4 // out q0 + rshrn2 v6.16b, v13.8h, #4 + add v12.8h, v12.8h, v8.8h // - (p5 + p0) + (q2 + q6) + add v13.8h, v13.8h, v9.8h + sub v10.8h, v10.8h, v18.8h + sub v11.8h, v11.8h, v19.8h + uaddl v8.8h, v28.8b, v30.8b // q4 + q6 + uaddl2 v9.8h, v28.16b, v30.16b + bif v2.16b, v20.16b, v15.16b // out p3 + uaddl v18.8h, v20.8b, v25.8b // p3 + q1 + uaddl2 v19.8h, v20.16b, v25.16b + rshrn v7.8b, v12.8h, #4 // out q1 + rshrn2 v7.16b, v13.8h, #4 + add v12.8h, v12.8h, v10.8h // - (p4 + q0) + (q3 + q6) + add v13.8h, v13.8h, v11.8h + sub v18.8h, v8.8h, v18.8h + sub v19.8h, v9.8h, v19.8h + uaddl v10.8h, v29.8b, v30.8b // q5 + q6 + uaddl2 v11.8h, v29.16b, v30.16b + bif v3.16b, v21.16b, v15.16b // out p2 + uaddl v20.8h, v21.8b, v26.8b // p2 + q2 + uaddl2 v21.8h, v21.16b, v26.16b + rshrn v8.8b, v12.8h, #4 // out q2 + rshrn2 v8.16b, v13.8h, #4 + add v12.8h, v12.8h, v18.8h // - (p3 + q1) + (q4 + q6) + add v13.8h, v13.8h, v19.8h + sub v10.8h, v10.8h, v20.8h + sub v11.8h, v11.8h, v21.8h + uaddl v18.8h, v30.8b, v30.8b // q6 + q6 + uaddl2 v19.8h, v30.16b, v30.16b + bif v4.16b, v22.16b, v15.16b // out p1 + uaddl v20.8h, v22.8b, v27.8b // p1 + q3 + uaddl2 v21.8h, v22.16b, v27.16b + rshrn v9.8b, v12.8h, #4 // out q3 + rshrn2 v9.16b, v13.8h, #4 + add v12.8h, v12.8h, v10.8h // - (p2 + q2) + (q5 + q6) + add v13.8h, v13.8h, v11.8h + sub v18.8h, v18.8h, v20.8h + sub v19.8h, v19.8h, v21.8h + bif v5.16b, v23.16b, v15.16b // out p0 + rshrn v10.8b, v12.8h, #4 // out q4 + rshrn2 v10.16b, v13.8h, #4 + add v12.8h, v12.8h, v18.8h // - (p1 + q3) + (q6 + q6) + add v13.8h, v13.8h, v19.8h + rshrn v11.8b, v12.8h, #4 // out q5 + rshrn2 v11.16b, v13.8h, #4 + bif v6.16b, v24.16b, v15.16b // out q0 + bif v7.16b, v25.16b, v15.16b // out q1 + bif v8.16b, v26.16b, v15.16b // out q2 + bif v9.16b, v27.16b, v15.16b // out q3 + bif v10.16b, v28.16b, v15.16b // out q4 + bif v11.16b, v29.16b, v15.16b // out q5 +.endif + + mov x14, #0 + ret +.if \wd == 16 +7: + // Return to a shorter epilogue, writing only the inner 6 pixels + mov x14, #(1 << 6) + ret +.endif +.if \wd >= 8 +8: + // Return to a shorter epilogue, writing only the inner 4 pixels + mov x14, #(1 << 4) + ret +.endif +endfunc +.endm + +loop_filter 16 +loop_filter 8 +loop_filter 6 +loop_filter 4 + +.macro lpf_16_wd16 + bl lpf_16_wd16_neon + cbz x14, 1f + tbnz x14, #6, 7f + tbnz x14, #4, 8f + ret x15 +1: +.endm + +.macro lpf_16_wd8 + bl lpf_16_wd8_neon + cbz x14, 1f + tbnz x14, #4, 8f + ret x15 +1: +.endm + +.macro lpf_16_wd6 + bl lpf_16_wd6_neon + cbz x14, 1f + ret x15 +1: +.endm + +.macro lpf_16_wd4 + bl lpf_16_wd4_neon + cbz x14, 1f + ret x15 +1: +.endm + +function lpf_v_4_16_neon + mov x15, x30 + sub x16, x0, x1, lsl #1 + ld1 {v22.16b}, [x16], x1 // p1 + ld1 {v24.16b}, [x0], x1 // q0 + ld1 {v23.16b}, [x16], x1 // p0 + ld1 {v25.16b}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + + lpf_16_wd4 + + sub x16, x0, x1, lsl #1 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v25.16b}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_4_16_neon + mov x15, x30 + sub x16, x0, #2 + add x0, x16, x1, lsl #3 + ld1 {v22.s}[0], [x16], x1 + ld1 {v22.s}[2], [x0], x1 + ld1 {v23.s}[0], [x16], x1 + ld1 {v23.s}[2], [x0], x1 + ld1 {v24.s}[0], [x16], x1 + ld1 {v24.s}[2], [x0], x1 + ld1 {v25.s}[0], [x16], x1 + ld1 {v25.s}[2], [x0], x1 + ld1 {v22.s}[1], [x16], x1 + ld1 {v22.s}[3], [x0], x1 + ld1 {v23.s}[1], [x16], x1 + ld1 {v23.s}[3], [x0], x1 + ld1 {v24.s}[1], [x16], x1 + ld1 {v24.s}[3], [x0], x1 + ld1 {v25.s}[1], [x16], x1 + ld1 {v25.s}[3], [x0], x1 + add x0, x0, #2 + + transpose_4x16b v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_16_wd4 + + sub x16, x0, x1, lsl #4 + sub x16, x16, #2 + transpose_4x16b v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v22.s}[0], [x16], x1 + st1 {v22.s}[2], [x0], x1 + st1 {v23.s}[0], [x16], x1 + st1 {v23.s}[2], [x0], x1 + st1 {v24.s}[0], [x16], x1 + st1 {v24.s}[2], [x0], x1 + st1 {v25.s}[0], [x16], x1 + st1 {v25.s}[2], [x0], x1 + st1 {v22.s}[1], [x16], x1 + st1 {v22.s}[3], [x0], x1 + st1 {v23.s}[1], [x16], x1 + st1 {v23.s}[3], [x0], x1 + st1 {v24.s}[1], [x16], x1 + st1 {v24.s}[3], [x0], x1 + st1 {v25.s}[1], [x16], x1 + st1 {v25.s}[3], [x0], x1 + add x0, x0, #2 + ret x15 +endfunc + +function lpf_v_6_16_neon + mov x15, x30 + sub x16, x0, x1, lsl #1 + sub x16, x16, x1 + ld1 {v21.16b}, [x16], x1 // p2 + ld1 {v24.16b}, [x0], x1 // q0 + ld1 {v22.16b}, [x16], x1 // p1 + ld1 {v25.16b}, [x0], x1 // q1 + ld1 {v23.16b}, [x16], x1 // p0 + ld1 {v26.16b}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + + lpf_16_wd6 + + sub x16, x0, x1, lsl #1 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v25.16b}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_6_16_neon + mov x15, x30 + sub x16, x0, #4 + add x0, x16, x1, lsl #3 + ld1 {v20.d}[0], [x16], x1 + ld1 {v20.d}[1], [x0], x1 + ld1 {v21.d}[0], [x16], x1 + ld1 {v21.d}[1], [x0], x1 + ld1 {v22.d}[0], [x16], x1 + ld1 {v22.d}[1], [x0], x1 + ld1 {v23.d}[0], [x16], x1 + ld1 {v23.d}[1], [x0], x1 + ld1 {v24.d}[0], [x16], x1 + ld1 {v24.d}[1], [x0], x1 + ld1 {v25.d}[0], [x16], x1 + ld1 {v25.d}[1], [x0], x1 + ld1 {v26.d}[0], [x16], x1 + ld1 {v26.d}[1], [x0], x1 + ld1 {v27.d}[0], [x16], x1 + ld1 {v27.d}[1], [x0], x1 + add x0, x0, #4 + + transpose_8x16b v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_16_wd6 + + sub x16, x0, x1, lsl #4 + sub x16, x16, #2 + transpose_4x16b v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v22.s}[0], [x16], x1 + st1 {v22.s}[2], [x0], x1 + st1 {v23.s}[0], [x16], x1 + st1 {v23.s}[2], [x0], x1 + st1 {v24.s}[0], [x16], x1 + st1 {v24.s}[2], [x0], x1 + st1 {v25.s}[0], [x16], x1 + st1 {v25.s}[2], [x0], x1 + st1 {v22.s}[1], [x16], x1 + st1 {v22.s}[3], [x0], x1 + st1 {v23.s}[1], [x16], x1 + st1 {v23.s}[3], [x0], x1 + st1 {v24.s}[1], [x16], x1 + st1 {v24.s}[3], [x0], x1 + st1 {v25.s}[1], [x16], x1 + st1 {v25.s}[3], [x0], x1 + add x0, x0, #2 + ret x15 +endfunc + +function lpf_v_8_16_neon + mov x15, x30 + sub x16, x0, x1, lsl #2 + ld1 {v20.16b}, [x16], x1 // p3 + ld1 {v24.16b}, [x0], x1 // q0 + ld1 {v21.16b}, [x16], x1 // p2 + ld1 {v25.16b}, [x0], x1 // q1 + ld1 {v22.16b}, [x16], x1 // p1 + ld1 {v26.16b}, [x0], x1 // q2 + ld1 {v23.16b}, [x16], x1 // p0 + ld1 {v27.16b}, [x0], x1 // q3 + sub x0, x0, x1, lsl #2 + + lpf_16_wd8 + + sub x16, x0, x1, lsl #1 + sub x16, x16, x1 + st1 {v21.16b}, [x16], x1 // p2 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v25.16b}, [x0], x1 // q1 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v26.16b}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + ret x15 + +8: + sub x16, x0, x1, lsl #1 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v25.16b}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_8_16_neon + mov x15, x30 + sub x16, x0, #4 + add x0, x16, x1, lsl #3 + ld1 {v20.d}[0], [x16], x1 + ld1 {v20.d}[1], [x0], x1 + ld1 {v21.d}[0], [x16], x1 + ld1 {v21.d}[1], [x0], x1 + ld1 {v22.d}[0], [x16], x1 + ld1 {v22.d}[1], [x0], x1 + ld1 {v23.d}[0], [x16], x1 + ld1 {v23.d}[1], [x0], x1 + ld1 {v24.d}[0], [x16], x1 + ld1 {v24.d}[1], [x0], x1 + ld1 {v25.d}[0], [x16], x1 + ld1 {v25.d}[1], [x0], x1 + ld1 {v26.d}[0], [x16], x1 + ld1 {v26.d}[1], [x0], x1 + ld1 {v27.d}[0], [x16], x1 + ld1 {v27.d}[1], [x0], x1 + add x0, x0, #4 + + transpose_8x16b v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_16_wd8 + + sub x16, x0, x1, lsl #4 + sub x16, x16, #4 + transpose_8x16b v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v20.d}[0], [x16], x1 + st1 {v20.d}[1], [x0], x1 + st1 {v21.d}[0], [x16], x1 + st1 {v21.d}[1], [x0], x1 + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + st1 {v26.d}[0], [x16], x1 + st1 {v26.d}[1], [x0], x1 + st1 {v27.d}[0], [x16], x1 + st1 {v27.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +8: + sub x16, x0, x1, lsl #4 + sub x16, x16, #2 + transpose_4x16b v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v22.s}[0], [x16], x1 + st1 {v22.s}[2], [x0], x1 + st1 {v23.s}[0], [x16], x1 + st1 {v23.s}[2], [x0], x1 + st1 {v24.s}[0], [x16], x1 + st1 {v24.s}[2], [x0], x1 + st1 {v25.s}[0], [x16], x1 + st1 {v25.s}[2], [x0], x1 + st1 {v22.s}[1], [x16], x1 + st1 {v22.s}[3], [x0], x1 + st1 {v23.s}[1], [x16], x1 + st1 {v23.s}[3], [x0], x1 + st1 {v24.s}[1], [x16], x1 + st1 {v24.s}[3], [x0], x1 + st1 {v25.s}[1], [x16], x1 + st1 {v25.s}[3], [x0], x1 + add x0, x0, #2 + ret x15 +endfunc + +function lpf_v_16_16_neon + mov x15, x30 + + sub x16, x0, x1, lsl #3 + add x16, x16, x1 + ld1 {v17.16b}, [x16], x1 // p6 + ld1 {v24.16b}, [x0], x1 // q0 + ld1 {v18.16b}, [x16], x1 // p5 + ld1 {v25.16b}, [x0], x1 // q1 + ld1 {v19.16b}, [x16], x1 // p4 + ld1 {v26.16b}, [x0], x1 // q2 + ld1 {v20.16b}, [x16], x1 // p3 + ld1 {v27.16b}, [x0], x1 // q3 + ld1 {v21.16b}, [x16], x1 // p2 + ld1 {v28.16b}, [x0], x1 // q4 + ld1 {v22.16b}, [x16], x1 // p1 + ld1 {v29.16b}, [x0], x1 // q5 + ld1 {v23.16b}, [x16], x1 // p0 + ld1 {v30.16b}, [x0], x1 // q6 + sub x0, x0, x1, lsl #3 + add x0, x0, x1 + + lpf_16_wd16 + + sub x16, x0, x1, lsl #2 + sub x16, x16, x1, lsl #1 + st1 {v0.16b}, [x16], x1 // p5 + st1 {v6.16b}, [x0], x1 // q0 + st1 {v1.16b}, [x16], x1 // p4 + st1 {v7.16b}, [x0], x1 // q1 + st1 {v2.16b}, [x16], x1 // p3 + st1 {v8.16b}, [x0], x1 // q2 + st1 {v3.16b}, [x16], x1 // p2 + st1 {v9.16b}, [x0], x1 // q3 + st1 {v4.16b}, [x16], x1 // p1 + st1 {v10.16b}, [x0], x1 // q4 + st1 {v5.16b}, [x16], x1 // p0 + st1 {v11.16b}, [x0], x1 // q5 + sub x0, x0, x1, lsl #2 + sub x0, x0, x1, lsl #1 + ret x15 +7: + sub x16, x0, x1 + sub x16, x16, x1, lsl #1 + st1 {v21.16b}, [x16], x1 // p2 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v25.16b}, [x0], x1 // q1 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v26.16b}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + ret x15 + +8: + sub x16, x0, x1, lsl #1 + st1 {v22.16b}, [x16], x1 // p1 + st1 {v24.16b}, [x0], x1 // q0 + st1 {v23.16b}, [x16], x1 // p0 + st1 {v25.16b}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_16_16_neon + mov x15, x30 + sub x16, x0, #8 + ld1 {v16.d}[0], [x16], x1 + ld1 {v24.d}[0], [x0], x1 + ld1 {v17.d}[0], [x16], x1 + ld1 {v25.d}[0], [x0], x1 + ld1 {v18.d}[0], [x16], x1 + ld1 {v26.d}[0], [x0], x1 + ld1 {v19.d}[0], [x16], x1 + ld1 {v27.d}[0], [x0], x1 + ld1 {v20.d}[0], [x16], x1 + ld1 {v28.d}[0], [x0], x1 + ld1 {v21.d}[0], [x16], x1 + ld1 {v29.d}[0], [x0], x1 + ld1 {v22.d}[0], [x16], x1 + ld1 {v30.d}[0], [x0], x1 + ld1 {v23.d}[0], [x16], x1 + ld1 {v31.d}[0], [x0], x1 + ld1 {v16.d}[1], [x16], x1 + ld1 {v24.d}[1], [x0], x1 + ld1 {v17.d}[1], [x16], x1 + ld1 {v25.d}[1], [x0], x1 + ld1 {v18.d}[1], [x16], x1 + ld1 {v26.d}[1], [x0], x1 + ld1 {v19.d}[1], [x16], x1 + ld1 {v27.d}[1], [x0], x1 + ld1 {v20.d}[1], [x16], x1 + ld1 {v28.d}[1], [x0], x1 + ld1 {v21.d}[1], [x16], x1 + ld1 {v29.d}[1], [x0], x1 + ld1 {v22.d}[1], [x16], x1 + ld1 {v30.d}[1], [x0], x1 + ld1 {v23.d}[1], [x16], x1 + ld1 {v31.d}[1], [x0], x1 + + transpose_8x16b v16, v17, v18, v19, v20, v21, v22, v23, v0, v1 + transpose_8x16b v24, v25, v26, v27, v28, v29, v30, v31, v0, v1 + + lpf_16_wd16 + + sub x0, x0, x1, lsl #4 + sub x16, x0, #8 + + transpose_8x16b v16, v17, v0, v1, v2, v3, v4, v5, v18, v19 + transpose_8x16b v6, v7, v8, v9, v10, v11, v30, v31, v18, v19 + + st1 {v16.d}[0], [x16], x1 + st1 {v6.d}[0], [x0], x1 + st1 {v17.d}[0], [x16], x1 + st1 {v7.d}[0], [x0], x1 + st1 {v0.d}[0], [x16], x1 + st1 {v8.d}[0], [x0], x1 + st1 {v1.d}[0], [x16], x1 + st1 {v9.d}[0], [x0], x1 + st1 {v2.d}[0], [x16], x1 + st1 {v10.d}[0], [x0], x1 + st1 {v3.d}[0], [x16], x1 + st1 {v11.d}[0], [x0], x1 + st1 {v4.d}[0], [x16], x1 + st1 {v30.d}[0], [x0], x1 + st1 {v5.d}[0], [x16], x1 + st1 {v31.d}[0], [x0], x1 + st1 {v16.d}[1], [x16], x1 + st1 {v6.d}[1], [x0], x1 + st1 {v17.d}[1], [x16], x1 + st1 {v7.d}[1], [x0], x1 + st1 {v0.d}[1], [x16], x1 + st1 {v8.d}[1], [x0], x1 + st1 {v1.d}[1], [x16], x1 + st1 {v9.d}[1], [x0], x1 + st1 {v2.d}[1], [x16], x1 + st1 {v10.d}[1], [x0], x1 + st1 {v3.d}[1], [x16], x1 + st1 {v11.d}[1], [x0], x1 + st1 {v4.d}[1], [x16], x1 + st1 {v30.d}[1], [x0], x1 + st1 {v5.d}[1], [x16], x1 + st1 {v31.d}[1], [x0], x1 + ret x15 + +7: + sub x16, x0, x1, lsl #4 + sub x16, x16, #4 + transpose_8x16b v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v20.d}[0], [x16], x1 + st1 {v20.d}[1], [x0], x1 + st1 {v21.d}[0], [x16], x1 + st1 {v21.d}[1], [x0], x1 + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + st1 {v26.d}[0], [x16], x1 + st1 {v26.d}[1], [x0], x1 + st1 {v27.d}[0], [x16], x1 + st1 {v27.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +8: + sub x16, x0, x1, lsl #4 + sub x16, x16, #2 + transpose_4x16b v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #3 + + st1 {v22.s}[0], [x16], x1 + st1 {v22.s}[2], [x0], x1 + st1 {v23.s}[0], [x16], x1 + st1 {v23.s}[2], [x0], x1 + st1 {v24.s}[0], [x16], x1 + st1 {v24.s}[2], [x0], x1 + st1 {v25.s}[0], [x16], x1 + st1 {v25.s}[2], [x0], x1 + st1 {v22.s}[1], [x16], x1 + st1 {v22.s}[3], [x0], x1 + st1 {v23.s}[1], [x16], x1 + st1 {v23.s}[3], [x0], x1 + st1 {v24.s}[1], [x16], x1 + st1 {v24.s}[3], [x0], x1 + st1 {v25.s}[1], [x16], x1 + st1 {v25.s}[3], [x0], x1 + add x0, x0, #2 + ret x15 +endfunc + +// void dav1d_lpf_v_sb_y_8bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint32_t *const vmask, +// const uint8_t (*l)[4], ptrdiff_t b4_stride, +// const Av1FilterLUT *lut, const int w) + +.macro lpf_func dir, type +function lpf_\dir\()_sb_\type\()_8bpc_neon, export=1 + mov x11, x30 + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + ldp w6, w7, [x2] // vmask[0], vmask[1] +.ifc \type, y + ldr w2, [x2, #8] // vmask[2] +.endif + add x5, x5, #128 // Move to sharp part of lut +.ifc \type, y + orr w7, w7, w2 // vmask[1] |= vmask[2] +.endif +.ifc \dir, v + sub x4, x3, x4, lsl #2 +.else + sub x3, x3, #4 + lsl x4, x4, #2 +.endif + orr w6, w6, w7 // vmask[0] |= vmask[1] + +1: + tst w6, #0x0f +.ifc \dir, v + ld1 {v0.16b}, [x4], #16 + ld1 {v1.16b}, [x3], #16 +.else + ld2 {v0.s,v1.s}[0], [x3], x4 + ld2 {v0.s,v1.s}[1], [x3], x4 + ld2 {v0.s,v1.s}[2], [x3], x4 + ld2 {v0.s,v1.s}[3], [x3], x4 +.endif + b.eq 7f // if (!(vm & bits)) continue; + + ld1r {v5.16b}, [x5] // sharp[0] + add x5, x5, #8 + movi v2.4s, #0xff + dup v13.4s, w6 // vmask[0] + + and v0.16b, v0.16b, v2.16b // Keep only lowest byte in each 32 bit word + and v1.16b, v1.16b, v2.16b + cmtst v3.16b, v1.16b, v2.16b // Check for nonzero values in l[0][0] + movi v4.16b, #1 + ld1r {v6.16b}, [x5] // sharp[1] + sub x5, x5, #8 + bif v1.16b, v0.16b, v3.16b // if (!l[0][0]) L = l[offset][0] + cmtst v2.4s, v1.4s, v2.4s // L != 0 + mul v1.4s, v1.4s, v4.4s // L +.ifc \type, y + dup v15.4s, w2 // vmask[2] +.endif + dup v14.4s, w7 // vmask[1] + mov x16, v2.d[0] + mov x17, v2.d[1] + adds x16, x16, x17 + b.eq 7f // if (!L) continue; + neg v5.16b, v5.16b // -sharp[0] + movrel x16, word_1248 + ushr v12.16b, v1.16b, #4 // H + ld1 {v16.4s}, [x16] + sshl v3.16b, v1.16b, v5.16b // L >> sharp[0] +.ifc \type, y + cmtst v15.4s, v15.4s, v16.4s // if (vmask[2] & bits) +.endif + movi v7.16b, #2 + umin v3.16b, v3.16b, v6.16b // imin(L >> sharp[0], sharp[1]) + add v0.16b, v1.16b, v7.16b // L + 2 + umax v11.16b, v3.16b, v4.16b // imax(imin(), 1) = limit = I + add v0.16b, v0.16b, v0.16b // 2*(L + 2) + cmtst v14.4s, v14.4s, v16.4s // if (vmask[1] & bits) + add v10.16b, v0.16b, v11.16b // 2*(L + 2) + limit = E + cmtst v13.4s, v13.4s, v16.4s // if (vmask[0] & bits) + and v13.16b, v13.16b, v2.16b // vmask[0] &= L != 0 + +.ifc \type, y + tst w2, #0x0f + b.eq 2f + // wd16 + bl lpf_\dir\()_16_16_neon + b 8f +2: +.endif + tst w7, #0x0f + b.eq 3f +.ifc \type, y + // wd8 + bl lpf_\dir\()_8_16_neon +.else + // wd6 + bl lpf_\dir\()_6_16_neon +.endif + b 8f +3: + // wd4 + bl lpf_\dir\()_4_16_neon +.ifc \dir, h + b 8f +7: + // For dir h, the functions above increment x0. + // If the whole function is skipped, increment it here instead. + add x0, x0, x1, lsl #4 +.else +7: +.endif +8: + lsr w6, w6, #4 // vmask[0] >>= 4 + lsr w7, w7, #4 // vmask[1] >>= 4 +.ifc \type, y + lsr w2, w2, #4 // vmask[2] >>= 4 +.endif +.ifc \dir, v + add x0, x0, #16 +.else + // For dir h, x0 is returned incremented +.endif + cbnz w6, 1b + + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret x11 +endfunc +.endm + +lpf_func v, y +lpf_func h, y +lpf_func v, uv +lpf_func h, uv + +const word_1248 + .word 1, 2, 4, 8 +endconst diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/loopfilter16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,925 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +// depending on how many pixels need to be stored, returns: +// x14 = (1 << 0) : 0 pixels +// x14 = (1 << 4) : inner 4 pixels +// x14 = (1 << 6) : inner 6 pixels +// x14 = 0 : all pixels +.macro loop_filter wd +function lpf_8_wd\wd\()_neon + uabd v0.8h, v22.8h, v23.8h // abs(p1 - p0) + uabd v1.8h, v25.8h, v24.8h // abs(q1 - q0) + uabd v2.8h, v23.8h, v24.8h // abs(p0 - q0) + uabd v3.8h, v22.8h, v25.8h // abs(p1 - q1) +.if \wd >= 6 + uabd v4.8h, v21.8h, v22.8h // abs(p2 - p1) + uabd v5.8h, v26.8h, v25.8h // abs(q2 - q1) +.endif +.if \wd >= 8 + uabd v6.8h, v20.8h, v21.8h // abs(p3 - p2) + uabd v7.8h, v27.8h, v26.8h // abs(q3 - q3) +.endif +.if \wd >= 6 + umax v4.8h, v4.8h, v5.8h +.endif + uqadd v2.8h, v2.8h, v2.8h // abs(p0 - q0) * 2 +.if \wd >= 8 + umax v6.8h, v6.8h, v7.8h +.endif + ushr v3.8h, v3.8h, #1 +.if \wd >= 8 + umax v4.8h, v4.8h, v6.8h +.endif +.if \wd >= 6 + and v4.16b, v4.16b, v14.16b +.endif + umax v0.8h, v0.8h, v1.8h // max(abs(p1 - p0), abs(q1 - q0)) + uqadd v2.8h, v2.8h, v3.8h // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 +.if \wd >= 6 + umax v4.8h, v0.8h, v4.8h + cmhs v1.8h, v11.8h, v4.8h // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I +.else + cmhs v1.8h, v11.8h, v0.8h // max(abs(p1 - p0), abs(q1 - q0)) <= I +.endif + cmhs v2.8h, v10.8h, v2.8h // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E + and v1.16b, v1.16b, v2.16b // fm + and v1.16b, v1.16b, v13.16b // fm && wd >= 4 +.if \wd >= 6 + and v14.16b, v14.16b, v1.16b // fm && wd > 4 +.endif +.if \wd >= 16 + and v15.16b, v15.16b, v1.16b // fm && wd == 16 +.endif + + mov x16, v1.d[0] + mov x17, v1.d[1] + adds x16, x16, x17 + b.ne 9f // if (!fm || wd < 4) return; + mov x14, #(1 << 0) + ret +9: +.if \wd >= 6 + movi v10.8h, #1 + uabd v2.8h, v21.8h, v23.8h // abs(p2 - p0) + uabd v3.8h, v22.8h, v23.8h // abs(p1 - p0) + uabd v4.8h, v25.8h, v24.8h // abs(q1 - q0) + uabd v5.8h, v26.8h, v24.8h // abs(q2 - q0) + dup v9.8h, w9 // bitdepth_min_8 +.if \wd >= 8 + uabd v6.8h, v20.8h, v23.8h // abs(p3 - p0) + uabd v7.8h, v27.8h, v24.8h // abs(q3 - q0) +.endif + umax v2.8h, v2.8h, v3.8h + umax v4.8h, v4.8h, v5.8h +.if \wd >= 8 + umax v6.8h, v6.8h, v7.8h +.endif + umax v2.8h, v2.8h, v4.8h + ushl v10.8h, v10.8h, v9.8h // F = 1 << bitdepth_min_8 +.if \wd >= 8 + umax v2.8h, v2.8h, v6.8h +.endif + +.if \wd == 16 + uabd v3.8h, v17.8h, v23.8h // abs(p6 - p0) + uabd v4.8h, v18.8h, v23.8h // abs(p5 - p0) + uabd v5.8h, v19.8h, v23.8h // abs(p4 - p0) +.endif + cmhs v2.8h, v10.8h, v2.8h // flat8in +.if \wd == 16 + uabd v6.8h, v28.8h, v24.8h // abs(q4 - q0) + uabd v7.8h, v29.8h, v24.8h // abs(q5 - q0) + uabd v8.8h, v30.8h, v24.8h // abs(q6 - q0) +.endif + and v14.16b, v2.16b, v14.16b // flat8in && fm && wd > 4 + bic v1.16b, v1.16b, v14.16b // fm && wd >= 4 && !flat8in +.if \wd == 16 + umax v3.8h, v3.8h, v4.8h + umax v5.8h, v5.8h, v6.8h +.endif + mov x16, v1.d[0] + mov x17, v1.d[1] +.if \wd == 16 + umax v7.8h, v7.8h, v8.8h + umax v3.8h, v3.8h, v5.8h + umax v3.8h, v3.8h, v7.8h + cmhs v3.8h, v10.8h, v3.8h // flat8out +.endif + adds x16, x16, x17 +.if \wd == 16 + and v15.16b, v15.16b, v3.16b // flat8out && fm && wd == 16 + and v15.16b, v15.16b, v14.16b // flat8out && flat8in && fm && wd == 16 + bic v14.16b, v14.16b, v15.16b // flat8in && fm && wd >= 4 && !flat8out +.endif + b.eq 1f // skip wd == 4 case +.endif + + dup v3.8h, w8 // bitdepth_max + sub v2.8h, v22.8h, v25.8h // p1 - q1 + ushr v3.8h, v3.8h, #1 // 128 << bitdepth_min_8 - 1 + cmhi v0.8h, v0.8h, v12.8h // hev + not v9.16b, v3.16b // - 128 * (1 << bitdepth_min_8) + smin v2.8h, v2.8h, v3.8h // iclip_diff(p1 - q1) + smax v2.8h, v2.8h, v9.8h // iclip_diff(p1 - q1) + and v4.16b, v2.16b, v0.16b // if (hev) iclip_diff(p1 - q1) + sub v2.8h, v24.8h, v23.8h + movi v5.8h, #3 + bic v0.16b, v1.16b, v0.16b // (fm && wd >= 4 && !hev) + mul v2.8h, v2.8h, v5.8h + movi v6.8h, #4 + add v2.8h, v2.8h, v4.8h + smin v2.8h, v2.8h, v3.8h // f = iclip_diff() + smax v2.8h, v2.8h, v9.8h // f = iclip_diff() + sqadd v4.8h, v6.8h, v2.8h // f + 4 + sqadd v5.8h, v5.8h, v2.8h // f + 3 + smin v4.8h, v4.8h, v3.8h // imin(f + 4, 128 << bitdepth_min_8 - 1) + smin v5.8h, v5.8h, v3.8h // imin(f + 3, 128 << bitdepth_min_8 - 1) + sshr v4.8h, v4.8h, #3 // f1 + sshr v5.8h, v5.8h, #3 // f2 + movi v9.8h, #0 + dup v3.8h, w8 // bitdepth_max + sqadd v2.8h, v23.8h, v5.8h // p0 + f2 + sqsub v6.8h, v24.8h, v4.8h // q0 - f1 + srshr v4.8h, v4.8h, #1 // (f1 + 1) >> 1 + smin v2.8h, v2.8h, v3.8h // out p0 = iclip_pixel() + smin v6.8h, v6.8h, v3.8h // out q0 = iclip_pixel() + smax v2.8h, v2.8h, v9.8h // out p0 = iclip_pixel() + smax v6.8h, v6.8h, v9.8h // out q0 = iclip_pixel() + bit v23.16b, v2.16b, v1.16b // if (fm && wd >= 4) + bit v24.16b, v6.16b, v1.16b // if (fm && wd >= 4) + sqadd v2.8h, v22.8h, v4.8h // p1 + f + sqsub v6.8h, v25.8h, v4.8h // q1 - f + smin v2.8h, v2.8h, v3.8h // out p1 = iclip_pixel() + smin v6.8h, v6.8h, v3.8h // out q1 = iclip_pixel() + smax v2.8h, v2.8h, v9.8h // out p1 = iclip_pixel() + smax v6.8h, v6.8h, v9.8h // out q1 = iclip_pixel() + bit v22.16b, v2.16b, v0.16b // if (fm && wd >= 4 && !hev) + bit v25.16b, v6.16b, v0.16b // if (fm && wd >= 4 && !hev) +1: + +.if \wd == 6 + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 + b.eq 2f // skip if there's no flat8in + + add v0.8h, v21.8h, v21.8h // p2 * 2 + add v2.8h, v21.8h, v22.8h // p2 + p1 + add v4.8h, v22.8h, v23.8h // p1 + p0 + add v6.8h, v23.8h, v24.8h // p0 + q0 + add v8.8h, v0.8h, v2.8h + add v10.8h, v4.8h, v6.8h + add v12.8h, v24.8h, v25.8h // q0 + q1 + add v8.8h, v8.8h, v10.8h + sub v12.8h, v12.8h, v0.8h + add v10.8h, v25.8h, v26.8h // q1 + q2 + urshr v0.8h, v8.8h, #3 // out p1 + + add v8.8h, v8.8h, v12.8h + sub v10.8h, v10.8h, v2.8h + add v12.8h, v26.8h, v26.8h // q2 + q2 + urshr v1.8h, v8.8h, #3 // out p0 + + add v8.8h, v8.8h, v10.8h + sub v12.8h, v12.8h, v4.8h + urshr v2.8h, v8.8h, #3 // out q0 + + bit v22.16b, v0.16b, v14.16b // p1 if (flat8in) + add v8.8h, v8.8h, v12.8h + bit v23.16b, v1.16b, v14.16b // p0 if (flat8in) + urshr v3.8h, v8.8h, #3 // out q1 + bit v24.16b, v2.16b, v14.16b // q0 if (flat8in) + bit v25.16b, v3.16b, v14.16b // q1 if (flat8in) +.elseif \wd >= 8 + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 +.if \wd == 8 + b.eq 8f // skip if there's no flat8in +.else + b.eq 2f // skip if there's no flat8in +.endif + + add v0.8h, v20.8h, v21.8h // p3 + p2 + add v2.8h, v22.8h, v25.8h // p1 + q1 + add v4.8h, v20.8h, v22.8h // p3 + p1 + add v6.8h, v23.8h, v26.8h // p0 + q2 + add v8.8h, v0.8h, v0.8h // 2 * (p3 + p2) + add v9.8h, v23.8h, v24.8h // p0 + q0 + add v8.8h, v8.8h, v4.8h // + p3 + p1 + sub v2.8h, v2.8h, v0.8h // p1 + q1 - p3 - p2 + add v8.8h, v8.8h, v9.8h // + p0 + q0 + sub v6.8h, v6.8h, v4.8h // p0 + q2 - p3 - p1 + urshr v10.8h, v8.8h, #3 // out p2 + + add v8.8h, v8.8h, v2.8h + add v0.8h, v20.8h, v23.8h // p3 + p0 + add v2.8h, v24.8h, v27.8h // q0 + q3 + urshr v11.8h, v8.8h, #3 // out p1 + + add v8.8h, v8.8h, v6.8h + sub v2.8h, v2.8h, v0.8h // q0 + q3 - p3 - p0 + add v4.8h, v21.8h, v24.8h // p2 + q0 + add v6.8h, v25.8h, v27.8h // q1 + q3 + urshr v12.8h, v8.8h, #3 // out p0 + + add v8.8h, v8.8h, v2.8h + sub v6.8h, v6.8h, v4.8h // q1 + q3 - p2 - q0 + add v0.8h, v22.8h, v25.8h // p1 + q1 + add v2.8h, v26.8h, v27.8h // q2 + q3 + urshr v13.8h, v8.8h, #3 // out q0 + + add v8.8h, v8.8h, v6.8h + sub v2.8h, v2.8h, v0.8h // q2 + q3 - p1 - q1 + urshr v0.8h, v8.8h, #3 // out q1 + + add v8.8h, v8.8h, v2.8h + + bit v21.16b, v10.16b, v14.16b + bit v22.16b, v11.16b, v14.16b + bit v23.16b, v12.16b, v14.16b + urshr v1.8h, v8.8h, #3 // out q2 + bit v24.16b, v13.16b, v14.16b + bit v25.16b, v0.16b, v14.16b + bit v26.16b, v1.16b, v14.16b +.endif +2: +.if \wd == 16 + mov x16, v15.d[0] + mov x17, v15.d[1] + adds x16, x16, x17 + b.ne 1f // check if flat8out is needed + mov x16, v14.d[0] + mov x17, v14.d[1] + adds x16, x16, x17 + b.eq 8f // if there was no flat8in, just write the inner 4 pixels + b 7f // if flat8in was used, write the inner 6 pixels +1: + + add v2.8h, v17.8h, v17.8h // p6 + p6 + add v4.8h, v17.8h, v18.8h // p6 + p5 + add v6.8h, v17.8h, v19.8h // p6 + p4 + add v8.8h, v17.8h, v20.8h // p6 + p3 + add v12.8h, v2.8h, v4.8h + add v10.8h, v6.8h, v8.8h + add v6.8h, v17.8h, v21.8h // p6 + p2 + add v12.8h, v12.8h, v10.8h + add v8.8h, v17.8h, v22.8h // p6 + p1 + add v10.8h, v18.8h, v23.8h // p5 + p0 + add v6.8h, v6.8h, v8.8h + add v8.8h, v19.8h, v24.8h // p4 + q0 + add v12.8h, v12.8h, v6.8h + add v10.8h, v10.8h, v8.8h + add v6.8h, v20.8h, v25.8h // p3 + q1 + add v12.8h, v12.8h, v10.8h + sub v6.8h, v6.8h, v2.8h + add v2.8h, v21.8h, v26.8h // p2 + q2 + urshr v0.8h, v12.8h, #4 // out p5 + add v12.8h, v12.8h, v6.8h // - (p6 + p6) + (p3 + q1) + sub v2.8h, v2.8h, v4.8h + add v4.8h, v22.8h, v27.8h // p1 + q3 + add v6.8h, v17.8h, v19.8h // p6 + p4 + urshr v1.8h, v12.8h, #4 // out p4 + add v12.8h, v12.8h, v2.8h // - (p6 + p5) + (p2 + q2) + sub v4.8h, v4.8h, v6.8h + add v6.8h, v23.8h, v28.8h // p0 + q4 + add v8.8h, v17.8h, v20.8h // p6 + p3 + urshr v2.8h, v12.8h, #4 // out p3 + add v12.8h, v12.8h, v4.8h // - (p6 + p4) + (p1 + q3) + sub v6.8h, v6.8h, v8.8h + add v8.8h, v24.8h, v29.8h // q0 + q5 + add v4.8h, v17.8h, v21.8h // p6 + p2 + urshr v3.8h, v12.8h, #4 // out p2 + add v12.8h, v12.8h, v6.8h // - (p6 + p3) + (p0 + q4) + sub v8.8h, v8.8h, v4.8h + add v6.8h, v25.8h, v30.8h // q1 + q6 + add v10.8h, v17.8h, v22.8h // p6 + p1 + urshr v4.8h, v12.8h, #4 // out p1 + add v12.8h, v12.8h, v8.8h // - (p6 + p2) + (q0 + q5) + sub v6.8h, v6.8h, v10.8h + add v8.8h, v26.8h, v30.8h // q2 + q6 + bif v0.16b, v18.16b, v15.16b // out p5 + add v10.8h, v18.8h, v23.8h // p5 + p0 + urshr v5.8h, v12.8h, #4 // out p0 + add v12.8h, v12.8h, v6.8h // - (p6 + p1) + (q1 + q6) + sub v8.8h, v8.8h, v10.8h + add v10.8h, v27.8h, v30.8h // q3 + q6 + bif v1.16b, v19.16b, v15.16b // out p4 + add v18.8h, v19.8h, v24.8h // p4 + q0 + urshr v6.8h, v12.8h, #4 // out q0 + add v12.8h, v12.8h, v8.8h // - (p5 + p0) + (q2 + q6) + sub v10.8h, v10.8h, v18.8h + add v8.8h, v28.8h, v30.8h // q4 + q6 + bif v2.16b, v20.16b, v15.16b // out p3 + add v18.8h, v20.8h, v25.8h // p3 + q1 + urshr v7.8h, v12.8h, #4 // out q1 + add v12.8h, v12.8h, v10.8h // - (p4 + q0) + (q3 + q6) + sub v18.8h, v8.8h, v18.8h + add v10.8h, v29.8h, v30.8h // q5 + q6 + bif v3.16b, v21.16b, v15.16b // out p2 + add v20.8h, v21.8h, v26.8h // p2 + q2 + urshr v8.8h, v12.8h, #4 // out q2 + add v12.8h, v12.8h, v18.8h // - (p3 + q1) + (q4 + q6) + sub v10.8h, v10.8h, v20.8h + add v18.8h, v30.8h, v30.8h // q6 + q6 + bif v4.16b, v22.16b, v15.16b // out p1 + add v20.8h, v22.8h, v27.8h // p1 + q3 + urshr v9.8h, v12.8h, #4 // out q3 + add v12.8h, v12.8h, v10.8h // - (p2 + q2) + (q5 + q6) + sub v18.8h, v18.8h, v20.8h + bif v5.16b, v23.16b, v15.16b // out p0 + urshr v10.8h, v12.8h, #4 // out q4 + add v12.8h, v12.8h, v18.8h // - (p1 + q3) + (q6 + q6) + urshr v11.8h, v12.8h, #4 // out q5 + bif v6.16b, v24.16b, v15.16b // out q0 + bif v7.16b, v25.16b, v15.16b // out q1 + bif v8.16b, v26.16b, v15.16b // out q2 + bif v9.16b, v27.16b, v15.16b // out q3 + bif v10.16b, v28.16b, v15.16b // out q4 + bif v11.16b, v29.16b, v15.16b // out q5 +.endif + + mov x14, #0 + ret +.if \wd == 16 +7: + // Return to a shorter epilogue, writing only the inner 6 pixels + mov x14, #(1 << 6) + ret +.endif +.if \wd >= 8 +8: + // Return to a shorter epilogue, writing only the inner 4 pixels + mov x14, #(1 << 4) + ret +.endif +endfunc +.endm + +loop_filter 16 +loop_filter 8 +loop_filter 6 +loop_filter 4 + +.macro lpf_8_wd16 + bl lpf_8_wd16_neon + cbz x14, 1f + tbnz x14, #6, 7f + tbnz x14, #4, 8f + ret x15 +1: +.endm + +.macro lpf_8_wd8 + bl lpf_8_wd8_neon + cbz x14, 1f + tbnz x14, #4, 8f + ret x15 +1: +.endm + +.macro lpf_8_wd6 + bl lpf_8_wd6_neon + cbz x14, 1f + ret x15 +1: +.endm + +.macro lpf_8_wd4 + bl lpf_8_wd4_neon + cbz x14, 1f + ret x15 +1: +.endm + +function lpf_v_4_8_neon + mov x15, x30 + sub x16, x0, x1, lsl #1 + ld1 {v22.8h}, [x16], x1 // p1 + ld1 {v24.8h}, [x0], x1 // q0 + ld1 {v23.8h}, [x16], x1 // p0 + ld1 {v25.8h}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + + lpf_8_wd4 + + sub x16, x0, x1, lsl #1 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v25.8h}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_4_8_neon + mov x15, x30 + sub x16, x0, #4 + add x0, x16, x1, lsl #2 + ld1 {v22.d}[0], [x16], x1 + ld1 {v22.d}[1], [x0], x1 + ld1 {v23.d}[0], [x16], x1 + ld1 {v23.d}[1], [x0], x1 + ld1 {v24.d}[0], [x16], x1 + ld1 {v24.d}[1], [x0], x1 + ld1 {v25.d}[0], [x16], x1 + ld1 {v25.d}[1], [x0], x1 + add x0, x0, #4 + + transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_8_wd4 + + sub x16, x0, x1, lsl #3 + sub x16, x16, #4 + transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +endfunc + +function lpf_v_6_8_neon + mov x15, x30 + sub x16, x0, x1, lsl #1 + sub x16, x16, x1 + ld1 {v21.8h}, [x16], x1 // p2 + ld1 {v24.8h}, [x0], x1 // q0 + ld1 {v22.8h}, [x16], x1 // p1 + ld1 {v25.8h}, [x0], x1 // q1 + ld1 {v23.8h}, [x16], x1 // p0 + ld1 {v26.8h}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + + lpf_8_wd6 + + sub x16, x0, x1, lsl #1 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v25.8h}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_6_8_neon + mov x15, x30 + sub x16, x0, #8 + add x0, x16, x1, lsl #2 + ld1 {v20.8h}, [x16], x1 + ld1 {v24.8h}, [x0], x1 + ld1 {v21.8h}, [x16], x1 + ld1 {v25.8h}, [x0], x1 + ld1 {v22.8h}, [x16], x1 + ld1 {v26.8h}, [x0], x1 + ld1 {v23.8h}, [x16], x1 + ld1 {v27.8h}, [x0], x1 + add x0, x0, #8 + + transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_8_wd6 + + sub x16, x0, x1, lsl #3 + sub x16, x16, #4 + transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +endfunc + +function lpf_v_8_8_neon + mov x15, x30 + sub x16, x0, x1, lsl #2 + ld1 {v20.8h}, [x16], x1 // p3 + ld1 {v24.8h}, [x0], x1 // q0 + ld1 {v21.8h}, [x16], x1 // p2 + ld1 {v25.8h}, [x0], x1 // q1 + ld1 {v22.8h}, [x16], x1 // p1 + ld1 {v26.8h}, [x0], x1 // q2 + ld1 {v23.8h}, [x16], x1 // p0 + ld1 {v27.8h}, [x0], x1 // q3 + sub x0, x0, x1, lsl #2 + + lpf_8_wd8 + + sub x16, x0, x1, lsl #1 + sub x16, x16, x1 + st1 {v21.8h}, [x16], x1 // p2 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v25.8h}, [x0], x1 // q1 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v26.8h}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + ret x15 + +8: + sub x16, x0, x1, lsl #1 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v25.8h}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_8_8_neon + mov x15, x30 + sub x16, x0, #8 + add x0, x16, x1, lsl #2 + ld1 {v20.8h}, [x16], x1 + ld1 {v24.8h}, [x0], x1 + ld1 {v21.8h}, [x16], x1 + ld1 {v25.8h}, [x0], x1 + ld1 {v22.8h}, [x16], x1 + ld1 {v26.8h}, [x0], x1 + ld1 {v23.8h}, [x16], x1 + ld1 {v27.8h}, [x0], x1 + add x0, x0, #8 + + transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + + lpf_8_wd8 + + sub x16, x0, x1, lsl #3 + sub x16, x16, #8 + transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v20.8h}, [x16], x1 + st1 {v24.8h}, [x0], x1 + st1 {v21.8h}, [x16], x1 + st1 {v25.8h}, [x0], x1 + st1 {v22.8h}, [x16], x1 + st1 {v26.8h}, [x0], x1 + st1 {v23.8h}, [x16], x1 + st1 {v27.8h}, [x0], x1 + add x0, x0, #8 + ret x15 +8: + sub x16, x0, x1, lsl #3 + sub x16, x16, #4 + transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +endfunc + +function lpf_v_16_8_neon + mov x15, x30 + + sub x16, x0, x1, lsl #3 + add x16, x16, x1 + ld1 {v17.8h}, [x16], x1 // p6 + ld1 {v24.8h}, [x0], x1 // q0 + ld1 {v18.8h}, [x16], x1 // p5 + ld1 {v25.8h}, [x0], x1 // q1 + ld1 {v19.8h}, [x16], x1 // p4 + ld1 {v26.8h}, [x0], x1 // q2 + ld1 {v20.8h}, [x16], x1 // p3 + ld1 {v27.8h}, [x0], x1 // q3 + ld1 {v21.8h}, [x16], x1 // p2 + ld1 {v28.8h}, [x0], x1 // q4 + ld1 {v22.8h}, [x16], x1 // p1 + ld1 {v29.8h}, [x0], x1 // q5 + ld1 {v23.8h}, [x16], x1 // p0 + ld1 {v30.8h}, [x0], x1 // q6 + sub x0, x0, x1, lsl #3 + add x0, x0, x1 + + lpf_8_wd16 + + sub x16, x0, x1, lsl #2 + sub x16, x16, x1, lsl #1 + st1 {v0.8h}, [x16], x1 // p5 + st1 {v6.8h}, [x0], x1 // q0 + st1 {v1.8h}, [x16], x1 // p4 + st1 {v7.8h}, [x0], x1 // q1 + st1 {v2.8h}, [x16], x1 // p3 + st1 {v8.8h}, [x0], x1 // q2 + st1 {v3.8h}, [x16], x1 // p2 + st1 {v9.8h}, [x0], x1 // q3 + st1 {v4.8h}, [x16], x1 // p1 + st1 {v10.8h}, [x0], x1 // q4 + st1 {v5.8h}, [x16], x1 // p0 + st1 {v11.8h}, [x0], x1 // q5 + sub x0, x0, x1, lsl #2 + sub x0, x0, x1, lsl #1 + ret x15 +7: + sub x16, x0, x1 + sub x16, x16, x1, lsl #1 + st1 {v21.8h}, [x16], x1 // p2 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v25.8h}, [x0], x1 // q1 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v26.8h}, [x0], x1 // q2 + sub x0, x0, x1, lsl #1 + sub x0, x0, x1 + ret x15 + +8: + sub x16, x0, x1, lsl #1 + st1 {v22.8h}, [x16], x1 // p1 + st1 {v24.8h}, [x0], x1 // q0 + st1 {v23.8h}, [x16], x1 // p0 + st1 {v25.8h}, [x0], x1 // q1 + sub x0, x0, x1, lsl #1 + ret x15 +endfunc + +function lpf_h_16_8_neon + mov x15, x30 + sub x16, x0, #16 + ld1 {v16.8h}, [x16], x1 + ld1 {v24.8h}, [x0], x1 + ld1 {v17.8h}, [x16], x1 + ld1 {v25.8h}, [x0], x1 + ld1 {v18.8h}, [x16], x1 + ld1 {v26.8h}, [x0], x1 + ld1 {v19.8h}, [x16], x1 + ld1 {v27.8h}, [x0], x1 + ld1 {v20.8h}, [x16], x1 + ld1 {v28.8h}, [x0], x1 + ld1 {v21.8h}, [x16], x1 + ld1 {v29.8h}, [x0], x1 + ld1 {v22.8h}, [x16], x1 + ld1 {v30.8h}, [x0], x1 + ld1 {v23.8h}, [x16], x1 + ld1 {v31.8h}, [x0], x1 + + transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v0, v1 + transpose_8x8h v24, v25, v26, v27, v28, v29, v30, v31, v0, v1 + + lpf_8_wd16 + + sub x0, x0, x1, lsl #3 + sub x16, x0, #16 + + transpose_8x8h v16, v17, v0, v1, v2, v3, v4, v5, v18, v19 + transpose_8x8h v6, v7, v8, v9, v10, v11, v30, v31, v18, v19 + + st1 {v16.8h}, [x16], x1 + st1 {v6.8h}, [x0], x1 + st1 {v17.8h}, [x16], x1 + st1 {v7.8h}, [x0], x1 + st1 {v0.8h}, [x16], x1 + st1 {v8.8h}, [x0], x1 + st1 {v1.8h}, [x16], x1 + st1 {v9.8h}, [x0], x1 + st1 {v2.8h}, [x16], x1 + st1 {v10.8h}, [x0], x1 + st1 {v3.8h}, [x16], x1 + st1 {v11.8h}, [x0], x1 + st1 {v4.8h}, [x16], x1 + st1 {v30.8h}, [x0], x1 + st1 {v5.8h}, [x16], x1 + st1 {v31.8h}, [x0], x1 + ret x15 + +7: + sub x16, x0, x1, lsl #3 + sub x16, x16, #8 + transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v20.8h}, [x16], x1 + st1 {v24.8h}, [x0], x1 + st1 {v21.8h}, [x16], x1 + st1 {v25.8h}, [x0], x1 + st1 {v22.8h}, [x16], x1 + st1 {v26.8h}, [x0], x1 + st1 {v23.8h}, [x16], x1 + st1 {v27.8h}, [x0], x1 + add x0, x0, #8 + ret x15 +8: + sub x16, x0, x1, lsl #3 + sub x16, x16, #4 + transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29 + add x0, x16, x1, lsl #2 + + st1 {v22.d}[0], [x16], x1 + st1 {v22.d}[1], [x0], x1 + st1 {v23.d}[0], [x16], x1 + st1 {v23.d}[1], [x0], x1 + st1 {v24.d}[0], [x16], x1 + st1 {v24.d}[1], [x0], x1 + st1 {v25.d}[0], [x16], x1 + st1 {v25.d}[1], [x0], x1 + add x0, x0, #4 + ret x15 +endfunc + +// void dav1d_lpf_v_sb_y_16bpc_neon(pixel *dst, const ptrdiff_t stride, +// const uint32_t *const vmask, +// const uint8_t (*l)[4], ptrdiff_t b4_stride, +// const Av1FilterLUT *lut, const int w, +// const int bitdepth_max) + +.macro lpf_func dir, type +function lpf_\dir\()_sb_\type\()_16bpc_neon, export=1 + mov x11, x30 + mov w8, w7 // bitdepth_max + clz w9, w8 + mov w10, #24 + sub w9, w10, w9 // bitdepth_min_8 + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + ldp w6, w7, [x2] // vmask[0], vmask[1] +.ifc \type, y + ldr w2, [x2, #8] // vmask[2] +.endif + add x5, x5, #128 // Move to sharp part of lut +.ifc \type, y + orr w7, w7, w2 // vmask[1] |= vmask[2] +.endif +.ifc \dir, v + sub x4, x3, x4, lsl #2 +.else + sub x3, x3, #4 + lsl x4, x4, #2 +.endif + orr w6, w6, w7 // vmask[0] |= vmask[1] + +1: + tst w6, #0x03 +.ifc \dir, v + ld1 {v0.8b}, [x4], #8 + ld1 {v1.8b}, [x3], #8 +.else + ld2 {v0.s,v1.s}[0], [x3], x4 + ld2 {v0.s,v1.s}[1], [x3], x4 +.endif + b.eq 7f // if (!(vm & bits)) continue; + + ld1r {v5.8b}, [x5] // sharp[0] + add x5, x5, #8 + movi v2.2s, #0xff + dup v13.2s, w6 // vmask[0] + dup v31.8h, w9 // bitdepth_min_8 + + and v0.8b, v0.8b, v2.8b // Keep only lowest byte in each 32 bit word + and v1.8b, v1.8b, v2.8b + cmtst v3.8b, v1.8b, v2.8b // Check for nonzero values in l[0][0] + movi v4.8b, #1 + ld1r {v6.8b}, [x5] // sharp[1] + sub x5, x5, #8 + bif v1.8b, v0.8b, v3.8b // if (!l[0][0]) L = l[offset][0] + cmtst v2.2s, v1.2s, v2.2s // L != 0 + mul v1.2s, v1.2s, v4.2s // L +.ifc \type, y + dup v15.2s, w2 // vmask[2] +.endif + dup v14.2s, w7 // vmask[1] + mov x16, v2.d[0] + cmp x16, #0 + b.eq 7f // if (!L) continue; + neg v5.8b, v5.8b // -sharp[0] + movrel x16, word_12 + ushr v12.8b, v1.8b, #4 // H + ld1 {v16.2s}, [x16] + sshl v3.8b, v1.8b, v5.8b // L >> sharp[0] +.ifc \type, y + cmtst v15.2s, v15.2s, v16.2s // if (vmask[2] & bits) +.endif + movi v7.8b, #2 + umin v3.8b, v3.8b, v6.8b // imin(L >> sharp[0], sharp[1]) + add v0.8b, v1.8b, v7.8b // L + 2 + umax v11.8b, v3.8b, v4.8b // imax(imin(), 1) = limit = I + add v0.8b, v0.8b, v0.8b // 2*(L + 2) + cmtst v14.2s, v14.2s, v16.2s // if (vmask[1] & bits) + uxtl v12.8h, v12.8b + add v10.8b, v0.8b, v11.8b // 2*(L + 2) + limit = E + cmtst v13.2s, v13.2s, v16.2s // if (vmask[0] & bits) + uxtl v11.8h, v11.8b + uxtl v10.8h, v10.8b + and v13.8b, v13.8b, v2.8b // vmask[0] &= L != 0 + sxtl v14.8h, v14.8b + sxtl v13.8h, v13.8b +.ifc \type, y + sxtl v15.8h, v15.8b +.endif + ushl v12.8h, v12.8h, v31.8h + ushl v11.8h, v11.8h, v31.8h + ushl v10.8h, v10.8h, v31.8h + +.ifc \type, y + tst w2, #0x03 + b.eq 2f + // wd16 + bl lpf_\dir\()_16_8_neon + b 8f +2: +.endif + tst w7, #0x03 + b.eq 3f +.ifc \type, y + // wd8 + bl lpf_\dir\()_8_8_neon +.else + // wd6 + bl lpf_\dir\()_6_8_neon +.endif + b 8f +3: + // wd4 + bl lpf_\dir\()_4_8_neon +.ifc \dir, h + b 8f +7: + // For dir h, the functions above increment x0. + // If the whole function is skipped, increment it here instead. + add x0, x0, x1, lsl #3 +.else +7: +.endif +8: + lsr w6, w6, #2 // vmask[0] >>= 2 + lsr w7, w7, #2 // vmask[1] >>= 2 +.ifc \type, y + lsr w2, w2, #2 // vmask[2] >>= 2 +.endif +.ifc \dir, v + add x0, x0, #16 +.else + // For dir h, x0 is returned incremented +.endif + cbnz w6, 1b + + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + ret x11 +endfunc +.endm + +lpf_func v, y +lpf_func h, y +lpf_func v, uv +lpf_func h, uv + +const word_12 + .word 1, 2 +endconst diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1336 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +const right_ext_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +right_ext_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void dav1d_wiener_filter7_8bpc_neon(pixel *p, const ptrdiff_t stride, +// const pixel (*left)[4], const pixel *lpf, +// const int w, int h, +// const int16_t filter[2][8], +// const enum LrEdgeFlags edges); +function wiener_filter7_8bpc_neon, export=1 + AARCH64_SIGN_LINK_REGISTER + stp x29, x30, [sp, #-16]! + mov x29, sp + ld1 {v0.8h, v1.8h}, [x6] + tst w7, #4 // LR_HAVE_TOP + sub_sp 384*2*6 + + mov w17, #(1 << 14) - (1 << 2) + dup v30.8h, w17 + movi v31.8h, #8, lsl #8 + + // x9 - t6 + // x10 - t5 + // x11 - t4 + // x12 - t3 + // x13 - t2 + // x14 - t1 + // x15 - t0 + mov x14, sp // t1 + b.eq L(no_top_7) + + mov x16, x2 // backup left + mov x2, #0 + bl wiener_filter7_h_8bpc_neon + add x3, x3, x1 // lpf += stride + mov x9, x14 // t6 + mov x10, x14 // t5 + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_8bpc_neon + add x3, x3, x1, lsl #2 + add x3, x3, x1 // lpf += stride*5 + mov x11, x14 // t4 + add x14, x14, #384*2 // t1 += 384*2 + mov x2, x16 // left + mov x16, x3 // backup lpf + mov x3, x0 // lpf = p + bl wiener_filter7_h_8bpc_neon + subs w5, w5, #1 // h-- + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_8bpc_neon + mov x13, x14 // t2 + subs w5, w5, #1 // h-- + b.eq L(v2_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x3, x3, x1 // src += stride + +L(main_7): + add x15, x14, #384*2 // t0 = t1 + 384*2 +L(main_loop_7): + bl wiener_filter7_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_loop_7) + tst w7, #8 // LR_HAVE_BOTTOM + b.eq L(v3_7) + + mov x3, x16 // restore lpf + mov x2, #0 // left = NULL + bl wiener_filter7_hv_8bpc_neon + bl wiener_filter7_hv_8bpc_neon +L(v1_7): + bl wiener_filter7_v_8bpc_neon + + mov sp, x29 + ldp x29, x30, [sp], #16 + AARCH64_VALIDATE_LINK_REGISTER + ret + +L(no_top_7): + add x3, x3, x1, lsl #2 + add x16, x3, x1, lsl #1 // lpf += stride*6, backup + mov x3, x0 // lpf = p + + bl wiener_filter7_h_8bpc_neon + subs w5, w5, #1 // h-- + mov x9, x14 // t6 + mov x10, x14 // t5 + mov x11, x14 // t4 + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_8bpc_neon + subs w5, w5, #1 // h-- + mov x13, x14 // t2 + b.eq L(v2_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x3, x3, x1 // src += stride + add x15, x14, #384*2 // t0 = t1 + 384*2 + bl wiener_filter7_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x15, x15, #384*2*4 // t0 += 384*2*4 + bl wiener_filter7_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_7) +L(v3_7): + bl wiener_filter7_v_8bpc_neon +L(v2_7): + bl wiener_filter7_v_8bpc_neon + b L(v1_7) +endfunc + + +function wiener_filter7_h_8bpc_neon + stp x3, x4, [sp, #-32]! + str x14, [sp, #16] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #3 + ld1 {v3.16b}, [x3], #16 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v3.16b}, [x3], #16 + ld1 {v2.s}[3], [x2], #4 + // Move x3 back to account for the last 3 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #3 + ext v3.16b, v2.16b, v3.16b, #13 + b 2f + +1: + ld1 {v3.16b}, [x3], #16 + // !LR_HAVE_LEFT, fill v2 with the leftmost byte + // and shift v3 to have 3x the first byte at the front. + dup v2.16b, v3.b[0] + // Move x3 back to account for the last 3 bytes we loaded before, + // which we shifted out. + sub x3, x3, #3 + ext v3.16b, v2.16b, v3.16b, #13 + +2: + ld1 {v4.8b}, [x3], #8 + uxtl v2.8h, v3.8b + uxtl2 v3.8h, v3.16b + uxtl v4.8h, v4.8b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #19 + b.ge 4f // If w >= 19, all used input pixels are valid + + // 1 <= w < 19, w+3 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-22] to find the padding pixel. + sub w17, w4, #22 + // Insert padding in v2/3/4.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -6 + ldr b28, [x3, w17, sxtw] + sub x6, x6, w4, uxtw #1 + dup v28.8h, v28.h[0] + ld1 {v25.16b, v26.16b, v27.16b}, [x6] + + bit v2.16b, v28.16b, v25.16b + bit v3.16b, v28.16b, v26.16b + bit v4.16b, v28.16b, v27.16b + +4: // Loop horizontally + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + ext v17.16b, v2.16b, v3.16b, #4 + ext v19.16b, v2.16b, v3.16b, #8 + ext v16.16b, v2.16b, v3.16b, #2 + ext v20.16b, v2.16b, v3.16b, #10 + ext v21.16b, v2.16b, v3.16b, #12 + ext v18.16b, v2.16b, v3.16b, #6 + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v2.8h + shl v22.8h, v18.8h, #7 + mul v6.8h, v18.8h, v0.h[3] + mla v6.8h, v19.8h, v0.h[4] + mla v6.8h, v20.8h, v0.h[5] + mla v6.8h, v21.8h, v0.h[6] + + ext v17.16b, v3.16b, v4.16b, #4 + ext v19.16b, v3.16b, v4.16b, #8 + ext v16.16b, v3.16b, v4.16b, #2 + ext v20.16b, v3.16b, v4.16b, #10 + ext v21.16b, v3.16b, v4.16b, #12 + ext v18.16b, v3.16b, v4.16b, #6 + + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v3.8h + shl v23.8h, v18.8h, #7 + mul v7.8h, v18.8h, v0.h[3] + mla v7.8h, v19.8h, v0.h[4] + mla v7.8h, v20.8h, v0.h[5] + mla v7.8h, v21.8h, v0.h[6] + + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + sqadd v6.8h, v6.8h, v22.8h + sqadd v7.8h, v7.8h, v23.8h + sshr v6.8h, v6.8h, #3 + sshr v7.8h, v7.8h, #3 + add v6.8h, v6.8h, v31.8h + add v7.8h, v7.8h, v31.8h + + subs w4, w4, #16 + + st1 {v6.8h, v7.8h}, [x14], #32 + + b.le 0f + mov v2.16b, v4.16b + ld1 {v4.16b}, [x3], #16 + tst w7, #2 // LR_HAVE_RIGHT + uxtl v3.8h, v4.8b + uxtl2 v4.8h, v4.16b + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldr x14, [sp, #16] + ldp x3, x4, [sp], #32 + ret +endfunc + +function wiener_filter7_v_8bpc_neon + // Backing up/restoring registers shifted, so that x9 gets the value + // of x10, etc, afterwards. + stp x10, x11, [sp, #-64]! + stp x12, x13, [sp, #16] + stp x14, x14, [sp, #32] + stp x0, x4, [sp, #48] +1: + ld1 {v20.8h, v21.8h}, [x11], #32 + ld1 {v24.8h, v25.8h}, [x13], #32 + + ld1 {v18.8h, v19.8h}, [x10], #32 + add v24.8h, v24.8h, v20.8h + ld1 {v26.8h, v27.8h}, [x14], #32 + + ld1 {v16.8h, v17.8h}, [x9], #32 + add v28.8h, v26.8h, v18.8h + ld1 {v22.8h, v23.8h}, [x12], #32 + + add v16.8h, v26.8h, v16.8h + add v25.8h, v25.8h, v21.8h + + smull v2.4s, v22.4h, v1.h[3] + smlal v2.4s, v24.4h, v1.h[4] + smlal v2.4s, v28.4h, v1.h[5] + smlal v2.4s, v16.4h, v1.h[6] + add v29.8h, v27.8h, v19.8h + smull2 v3.4s, v22.8h, v1.h[3] + smlal2 v3.4s, v24.8h, v1.h[4] + smlal2 v3.4s, v28.8h, v1.h[5] + smlal2 v3.4s, v16.8h, v1.h[6] + add v17.8h, v27.8h, v17.8h + smull v4.4s, v23.4h, v1.h[3] + smlal v4.4s, v25.4h, v1.h[4] + smlal v4.4s, v29.4h, v1.h[5] + smlal v4.4s, v17.4h, v1.h[6] + smull2 v5.4s, v23.8h, v1.h[3] + smlal2 v5.4s, v25.8h, v1.h[4] + smlal2 v5.4s, v29.8h, v1.h[5] + smlal2 v5.4s, v17.8h, v1.h[6] + sqrshrun v2.4h, v2.4s, #11 + sqrshrun2 v2.8h, v3.4s, #11 + sqrshrun v3.4h, v4.4s, #11 + sqrshrun2 v3.8h, v5.4s, #11 + sqxtun v2.8b, v2.8h + sqxtun2 v2.16b, v3.8h + subs w4, w4, #16 + st1 {v2.16b}, [x0], #16 + b.gt 1b + + ldp x0, x4, [sp, #48] + ldp x13, x14, [sp, #32] + ldp x11, x12, [sp, #16] + ldp x9, x10, [sp], #64 + + add x0, x0, x1 + ret +endfunc + +function wiener_filter7_hv_8bpc_neon + // Backing up/restoring registers shifted, so that x9 gets the value + // of x10, etc, and x15==x9, afterwards. + stp x10, x11, [sp, #-80]! + stp x12, x13, [sp, #16] + stp x14, x15, [sp, #32] + stp x10, x0, [sp, #48] + stp x3, x4, [sp, #64] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #3 + ld1 {v3.16b}, [x3], #16 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v3.16b}, [x3], #16 + ld1 {v2.s}[3], [x2], #4 + // Move x3 back to account for the last 3 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #3 + ext v3.16b, v2.16b, v3.16b, #13 + b 2f +1: + ld1 {v3.16b}, [x3], #16 + // !LR_HAVE_LEFT, fill v2 with the leftmost byte + // and shift v3 to have 3x the first byte at the front. + dup v2.16b, v3.b[0] + // Move x3 back to account for the last 3 bytes we loaded before, + // which we shifted out. + sub x3, x3, #3 + ext v3.16b, v2.16b, v3.16b, #13 + +2: + ld1 {v4.8b}, [x3], #8 + uxtl v2.8h, v3.8b + uxtl2 v3.8h, v3.16b + uxtl v4.8h, v4.8b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #19 + b.ge 4f // If w >= 19, all used input pixels are valid + + // 1 <= w < 19, w+3 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-22] to find the padding pixel. + sub w17, w4, #22 + // Insert padding in v2/3/4.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -6 + ldr b28, [x3, w17, sxtw] + sub x6, x6, w4, uxtw #1 + dup v28.8h, v28.h[0] + ld1 {v25.16b, v26.16b, v27.16b}, [x6] + + bit v2.16b, v28.16b, v25.16b + bit v3.16b, v28.16b, v26.16b + bit v4.16b, v28.16b, v27.16b + +4: // Loop horizontally + ext v17.16b, v2.16b, v3.16b, #4 + ext v19.16b, v2.16b, v3.16b, #8 + ext v16.16b, v2.16b, v3.16b, #2 + ext v20.16b, v2.16b, v3.16b, #10 + ext v21.16b, v2.16b, v3.16b, #12 + ext v18.16b, v2.16b, v3.16b, #6 + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v2.8h + shl v22.8h, v18.8h, #7 + mul v6.8h, v18.8h, v0.h[3] + mla v6.8h, v19.8h, v0.h[4] + mla v6.8h, v20.8h, v0.h[5] + mla v6.8h, v21.8h, v0.h[6] + + ext v17.16b, v3.16b, v4.16b, #4 + ext v19.16b, v3.16b, v4.16b, #8 + ext v16.16b, v3.16b, v4.16b, #2 + ext v20.16b, v3.16b, v4.16b, #10 + ext v21.16b, v3.16b, v4.16b, #12 + ext v18.16b, v3.16b, v4.16b, #6 + + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v3.8h + shl v23.8h, v18.8h, #7 + mul v7.8h, v18.8h, v0.h[3] + mla v7.8h, v19.8h, v0.h[4] + mla v7.8h, v20.8h, v0.h[5] + mla v7.8h, v21.8h, v0.h[6] + + ld1 {v20.8h, v21.8h}, [x11], #32 + + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + ld1 {v26.8h, v27.8h}, [x13], #32 + sqadd v6.8h, v6.8h, v22.8h + sqadd v7.8h, v7.8h, v23.8h + ld1 {v18.8h, v19.8h}, [x10], #32 + sshr v6.8h, v6.8h, #3 + sshr v7.8h, v7.8h, #3 + ld1 {v28.8h, v29.8h}, [x14], #32 + add v6.8h, v6.8h, v31.8h + add v7.8h, v7.8h, v31.8h + + ld1 {v16.8h, v17.8h}, [x9], #32 + add v26.8h, v20.8h, v26.8h + + ld1 {v24.8h, v25.8h}, [x12], #32 + add v28.8h, v18.8h, v28.8h + + add v16.8h, v16.8h, v6.8h + add v27.8h, v21.8h, v27.8h + + smull v18.4s, v24.4h, v1.h[3] + smlal v18.4s, v26.4h, v1.h[4] + smlal v18.4s, v28.4h, v1.h[5] + smlal v18.4s, v16.4h, v1.h[6] + add v29.8h, v19.8h, v29.8h + smull2 v19.4s, v24.8h, v1.h[3] + smlal2 v19.4s, v26.8h, v1.h[4] + smlal2 v19.4s, v28.8h, v1.h[5] + smlal2 v19.4s, v16.8h, v1.h[6] + add v17.8h, v17.8h, v7.8h + smull v20.4s, v25.4h, v1.h[3] + smlal v20.4s, v27.4h, v1.h[4] + smlal v20.4s, v29.4h, v1.h[5] + smlal v20.4s, v17.4h, v1.h[6] + smull2 v21.4s, v25.8h, v1.h[3] + smlal2 v21.4s, v27.8h, v1.h[4] + smlal2 v21.4s, v29.8h, v1.h[5] + smlal2 v21.4s, v17.8h, v1.h[6] + sqrshrun v18.4h, v18.4s, #11 + sqrshrun2 v18.8h, v19.4s, #11 + sqrshrun v19.4h, v20.4s, #11 + sqrshrun2 v19.8h, v21.4s, #11 + st1 {v6.8h, v7.8h}, [x15], #32 + sqxtun v18.8b, v18.8h + sqxtun2 v18.16b, v19.8h + subs w4, w4, #16 + + st1 {v18.16b}, [x0], #16 + + b.le 0f + mov v2.16b, v4.16b + ld1 {v4.16b}, [x3], #16 + tst w7, #2 // LR_HAVE_RIGHT + uxtl v3.8h, v4.8b + uxtl2 v4.8h, v4.16b + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldp x3, x4, [sp, #64] + ldp x15, x0, [sp, #48] + ldp x13, x14, [sp, #32] + ldp x11, x12, [sp, #16] + ldp x9, x10, [sp], #80 + + add x3, x3, x1 + add x0, x0, x1 + + ret +endfunc + +// void dav1d_wiener_filter5_8bpc_neon(pixel *p, const ptrdiff_t stride, +// const pixel (*left)[4], const pixel *lpf, +// const int w, int h, +// const int16_t filter[2][8], +// const enum LrEdgeFlags edges); +function wiener_filter5_8bpc_neon, export=1 + AARCH64_SIGN_LINK_REGISTER + stp x29, x30, [sp, #-16]! + mov x29, sp + ld1 {v0.8h, v1.8h}, [x6] + tst w7, #4 // LR_HAVE_TOP + sub_sp 384*2*4 + + mov w17, #(1 << 14) - (1 << 2) + dup v30.8h, w17 + movi v31.8h, #8, lsl #8 + + // x11 - t4 + // x12 - t3 + // x13 - t2 + // x14 - t1 + // x15 - t0 + mov x14, sp // t1 + b.eq L(no_top_5) + + mov x16, x2 // backup left + mov x2, #0 + bl wiener_filter5_h_8bpc_neon + add x3, x3, x1 // lpf += stride + mov x11, x14 // t4 + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_8bpc_neon + add x3, x3, x1, lsl #2 + add x3, x3, x1 // lpf += stride*5 + mov x12, x14 // t3 + add x14, x14, #384*2 // t1 += 384*2 + mov x2, x16 // left + mov x16, x3 // backup lpf + mov x3, x0 // lpf = p + bl wiener_filter5_h_8bpc_neon + subs w5, w5, #1 // h-- + mov x13, x14 // t2 + b.eq L(v1_5) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x3, x3, x1 // src += stride + +L(main_5): + mov x15, x11 // t0 = t4 +L(main_loop_5): + bl wiener_filter5_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_loop_5) + tst w7, #8 // LR_HAVE_BOTTOM + b.eq L(v2_5) + + mov x3, x16 // restore lpf + mov x2, #0 // left = NULL + bl wiener_filter5_hv_8bpc_neon + bl wiener_filter5_hv_8bpc_neon +L(end_5): + + mov sp, x29 + ldp x29, x30, [sp], #16 + AARCH64_VALIDATE_LINK_REGISTER + ret + +L(no_top_5): + add x3, x3, x1, lsl #2 + add x16, x3, x1, lsl #1 // lpf += stride*6, backup + mov x3, x0 // lpf = p + + bl wiener_filter5_h_8bpc_neon + subs w5, w5, #1 // h-- + mov x11, x14 // t4 + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_5) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x3, x3, x1 // src += stride + add x15, x14, #384*2 // t0 = t1 + 384*2 + bl wiener_filter5_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x15, x15, #384*2*3 // t0 += 384*2*3 + bl wiener_filter5_hv_8bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_5) +L(v2_5): + bl wiener_filter5_v_8bpc_neon + add x0, x0, x1 + mov x11, x12 + mov x12, x13 + mov x13, x14 +L(v1_5): + bl wiener_filter5_v_8bpc_neon + b L(end_5) +endfunc + + +function wiener_filter5_h_8bpc_neon + stp x3, x4, [sp, #-32]! + str x14, [sp, #16] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #2 + ld1 {v3.16b}, [x3], #16 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v3.16b}, [x3], #16 + ld1 {v2.s}[3], [x2], #4 + // Move x3 back to account for the last 2 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #2 + ext v3.16b, v2.16b, v3.16b, #14 + b 2f + +1: + ld1 {v3.16b}, [x3], #16 + // !LR_HAVE_LEFT, fill v2 with the leftmost byte + // and shift v3 to have 3x the first byte at the front. + dup v2.16b, v3.b[0] + // Move x3 back to account for the last 2 bytes we loaded before, + // which we shifted out. + sub x3, x3, #2 + ext v3.16b, v2.16b, v3.16b, #14 + +2: + ld1 {v4.8b}, [x3], #8 + uxtl v2.8h, v3.8b + uxtl2 v3.8h, v3.16b + uxtl v4.8h, v4.8b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #18 + b.ge 4f // If w >= 18, all used input pixels are valid + + // 1 <= w < 18, w+2 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-23] to find the padding pixel. + sub w17, w4, #23 + // Insert padding in v2/3/4.h[w+2] onwards; fuse the +2 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -4 + ldr b28, [x3, w17, sxtw] + sub x6, x6, w4, uxtw #1 + dup v28.8h, v28.h[0] + ld1 {v25.16b, v26.16b, v27.16b}, [x6] + + bit v2.16b, v28.16b, v25.16b + bit v3.16b, v28.16b, v26.16b + bit v4.16b, v28.16b, v27.16b + +4: // Loop horizontally + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + ext v16.16b, v2.16b, v3.16b, #2 + ext v18.16b, v2.16b, v3.16b, #6 + ext v19.16b, v2.16b, v3.16b, #8 + ext v17.16b, v2.16b, v3.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v2.8h + shl v22.8h, v17.8h, #7 + mul v6.8h, v17.8h, v0.h[3] + mla v6.8h, v18.8h, v0.h[4] + mla v6.8h, v19.8h, v0.h[5] + + ext v16.16b, v3.16b, v4.16b, #2 + ext v18.16b, v3.16b, v4.16b, #6 + ext v19.16b, v3.16b, v4.16b, #8 + ext v17.16b, v3.16b, v4.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v3.8h + shl v23.8h, v17.8h, #7 + mul v7.8h, v17.8h, v0.h[3] + mla v7.8h, v18.8h, v0.h[4] + mla v7.8h, v19.8h, v0.h[5] + + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + sqadd v6.8h, v6.8h, v22.8h + sqadd v7.8h, v7.8h, v23.8h + sshr v6.8h, v6.8h, #3 + sshr v7.8h, v7.8h, #3 + add v6.8h, v6.8h, v31.8h + add v7.8h, v7.8h, v31.8h + + subs w4, w4, #16 + + st1 {v6.8h, v7.8h}, [x14], #32 + + b.le 0f + mov v2.16b, v4.16b + ld1 {v4.16b}, [x3], #16 + tst w7, #2 // LR_HAVE_RIGHT + uxtl v3.8h, v4.8b + uxtl2 v4.8h, v4.16b + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldr x14, [sp, #16] + ldp x3, x4, [sp], #32 + ret +endfunc + +function wiener_filter5_v_8bpc_neon + stp x11, x12, [sp, #-48]! + stp x13, x14, [sp, #16] + stp x0, x4, [sp, #32] +1: + ld1 {v18.8h, v19.8h}, [x12], #32 + ld1 {v22.8h, v23.8h}, [x14], #32 + ld1 {v16.8h, v17.8h}, [x11], #32 + + add v24.8h, v22.8h, v18.8h + ld1 {v20.8h, v21.8h}, [x13], #32 + add v16.8h, v22.8h, v16.8h + add v25.8h, v23.8h, v19.8h + + smull v2.4s, v20.4h, v1.h[3] + smlal v2.4s, v24.4h, v1.h[4] + smlal v2.4s, v16.4h, v1.h[5] + add v17.8h, v23.8h, v17.8h + smull2 v3.4s, v20.8h, v1.h[3] + smlal2 v3.4s, v24.8h, v1.h[4] + smlal2 v3.4s, v16.8h, v1.h[5] + smull v4.4s, v21.4h, v1.h[3] + smlal v4.4s, v25.4h, v1.h[4] + smlal v4.4s, v17.4h, v1.h[5] + smull2 v5.4s, v21.8h, v1.h[3] + smlal2 v5.4s, v25.8h, v1.h[4] + smlal2 v5.4s, v17.8h, v1.h[5] + sqrshrun v2.4h, v2.4s, #11 + sqrshrun2 v2.8h, v3.4s, #11 + sqrshrun v3.4h, v4.4s, #11 + sqrshrun2 v3.8h, v5.4s, #11 + sqxtun v2.8b, v2.8h + sqxtun2 v2.16b, v3.8h + subs w4, w4, #16 + st1 {v2.16b}, [x0], #16 + b.gt 1b + + ldp x0, x4, [sp, #32] + ldp x13, x14, [sp, #16] + ldp x11, x12, [sp], #48 + + ret +endfunc + +function wiener_filter5_hv_8bpc_neon + // Backing up/restoring registers shifted, so that x11 gets the value + // of x12, etc, and x15==x11, afterwards. + stp x12, x13, [sp, #-64]! + stp x14, x15, [sp, #16] + stp x12, x0, [sp, #32] + stp x3, x4, [sp, #48] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #2 + ld1 {v3.16b}, [x3], #16 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v3.16b}, [x3], #16 + ld1 {v2.s}[3], [x2], #4 + // Move x3 back to account for the last 2 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #2 + ext v3.16b, v2.16b, v3.16b, #14 + b 2f +1: + ld1 {v3.16b}, [x3], #16 + // !LR_HAVE_LEFT, fill v2 with the leftmost byte + // and shift v3 to have 2x the first byte at the front. + dup v2.16b, v3.b[0] + // Move x3 back to account for the last 2 bytes we loaded before, + // which we shifted out. + sub x3, x3, #2 + ext v3.16b, v2.16b, v3.16b, #14 + +2: + ld1 {v4.8b}, [x3], #8 + uxtl v2.8h, v3.8b + uxtl2 v3.8h, v3.16b + uxtl v4.8h, v4.8b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #18 + b.ge 4f // If w >= 18, all used input pixels are valid + + // 1 <= w < 18, w+2 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+1]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-23] to find the padding pixel. + sub w17, w4, #23 + // Insert padding in v2/3/4.h[w+2] onwards; fuse the +2 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -4 + ldr b28, [x3, w17, sxtw] + sub x6, x6, w4, uxtw #1 + dup v28.8h, v28.h[0] + ld1 {v25.16b, v26.16b, v27.16b}, [x6] + + bit v2.16b, v28.16b, v25.16b + bit v3.16b, v28.16b, v26.16b + bit v4.16b, v28.16b, v27.16b + +4: // Loop horizontally + + ext v16.16b, v2.16b, v3.16b, #2 + ext v18.16b, v2.16b, v3.16b, #6 + ext v19.16b, v2.16b, v3.16b, #8 + ext v17.16b, v2.16b, v3.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v2.8h + shl v22.8h, v17.8h, #7 + mul v6.8h, v17.8h, v0.h[3] + mla v6.8h, v18.8h, v0.h[4] + mla v6.8h, v19.8h, v0.h[5] + + ext v16.16b, v3.16b, v4.16b, #2 + ext v18.16b, v3.16b, v4.16b, #6 + ext v19.16b, v3.16b, v4.16b, #8 + ext v17.16b, v3.16b, v4.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v3.8h + shl v23.8h, v17.8h, #7 + mul v7.8h, v17.8h, v0.h[3] + mla v7.8h, v18.8h, v0.h[4] + mla v7.8h, v19.8h, v0.h[5] + + ld1 {v18.8h, v19.8h}, [x12], #32 + + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + ld1 {v24.8h, v25.8h}, [x14], #32 + sqadd v6.8h, v6.8h, v22.8h + sqadd v7.8h, v7.8h, v23.8h + ld1 {v16.8h, v17.8h}, [x11], #32 + sshr v6.8h, v6.8h, #3 + sshr v7.8h, v7.8h, #3 + ld1 {v20.8h, v21.8h}, [x13], #32 + add v6.8h, v6.8h, v31.8h + add v7.8h, v7.8h, v31.8h + + add v24.8h, v24.8h, v18.8h + add v16.8h, v16.8h, v6.8h + + smull v18.4s, v20.4h, v1.h[3] + smlal v18.4s, v24.4h, v1.h[4] + smlal v18.4s, v16.4h, v1.h[5] + add v25.8h, v25.8h, v19.8h + smull2 v19.4s, v20.8h, v1.h[3] + smlal2 v19.4s, v24.8h, v1.h[4] + smlal2 v19.4s, v16.8h, v1.h[5] + add v17.8h, v17.8h, v7.8h + smull v20.4s, v21.4h, v1.h[3] + smlal v20.4s, v25.4h, v1.h[4] + smlal v20.4s, v17.4h, v1.h[5] + smull2 v21.4s, v21.8h, v1.h[3] + smlal2 v21.4s, v25.8h, v1.h[4] + smlal2 v21.4s, v17.8h, v1.h[5] + sqrshrun v18.4h, v18.4s, #11 + sqrshrun2 v18.8h, v19.4s, #11 + sqrshrun v19.4h, v20.4s, #11 + sqrshrun2 v19.8h, v21.4s, #11 + st1 {v6.8h, v7.8h}, [x15], #32 + sqxtun v18.8b, v18.8h + sqxtun2 v18.16b, v19.8h + subs w4, w4, #16 + + st1 {v18.16b}, [x0], #16 + + b.le 0f + mov v2.16b, v4.16b + ld1 {v4.16b}, [x3], #16 + tst w7, #2 // LR_HAVE_RIGHT + uxtl v3.8h, v4.8b + uxtl2 v4.8h, v4.16b + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldp x3, x4, [sp, #48] + ldp x15, x0, [sp, #32] + ldp x13, x14, [sp, #16] + ldp x11, x12, [sp], #64 + + add x3, x3, x1 + add x0, x0, x1 + + ret +endfunc + +#define SUM_STRIDE (384+16) + +#include "looprestoration_tmpl.S" + +// void dav1d_sgr_box3_h_8bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_h_8bpc_neon, export=1 + add w5, w5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add x10, x0, #(4*SUM_STRIDE) // sumsq + add x11, x1, #(2*SUM_STRIDE) // sum + add x12, x3, x4 // src + lsl x4, x4, #1 + mov x9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add w13, w5, #7 + bic w13, w13, #7 + sub x9, x9, w13, uxtw #1 + + // Store the width for the vertical loop + mov w8, w5 + + // Subtract the number of pixels read from the input from the stride + add w13, w13, #8 + sub x4, x4, w13, uxtw + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 2f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #2 + sub x12, x12, #2 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 2 pixels from the src pointer, + // but shift it as if we had done that. + add x4, x4, #2 + + +1: // Loop vertically + ld1 {v0.16b}, [x3], #16 + ld1 {v4.16b}, [x12], #16 + + tst w7, #1 // LR_HAVE_LEFT + b.eq 0f + cbz x2, 2f + // LR_HAVE_LEFT, left != NULL + ld1 {v1.s}[3], [x2], #4 + // Move x3/x12 back to account for the last 2 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #2 + sub x12, x12, #2 + ld1 {v5.s}[3], [x2], #4 + ext v0.16b, v1.16b, v0.16b, #14 + ext v4.16b, v5.16b, v4.16b, #14 + b 2f +0: + // !LR_HAVE_LEFT, fill v1 with the leftmost byte + // and shift v0 to have 2x the first byte at the front. + dup v1.16b, v0.b[0] + dup v5.16b, v4.b[0] + // Move x3 back to account for the last 2 bytes we loaded before, + // which we shifted out. + sub x3, x3, #2 + sub x12, x12, #2 + ext v0.16b, v1.16b, v0.16b, #14 + ext v4.16b, v5.16b, v4.16b, #14 + +2: + umull v1.8h, v0.8b, v0.8b + umull2 v2.8h, v0.16b, v0.16b + umull v5.8h, v4.8b, v4.8b + umull2 v6.8h, v4.16b, v4.16b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + // If we'll need to pad the right edge, load that byte to pad with + // here since we can find it pretty easily from here. + sub w13, w5, #(2 + 16 - 2 + 1) + ldr b30, [x3, w13, sxtw] + ldr b31, [x12, w13, sxtw] + // Fill v30/v31 with the right padding pixel + dup v30.16b, v30.b[0] + dup v31.16b, v31.b[0] +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w5, #10 + b.ge 4f // If w >= 10, all used input pixels are valid + + // 1 <= w < 10, w pixels valid in v0. For w=9, this ends up called + // again; it's not strictly needed in those cases (we pad enough here), + // but keeping the code as simple as possible. + + // Insert padding in v0/4.b[w] onwards + movrel x13, right_ext_mask + sub x13, x13, w5, uxtw + ld1 {v29.16b}, [x13] + + bit v0.16b, v30.16b, v29.16b + bit v4.16b, v31.16b, v29.16b + + // Update the precalculated squares + umull v1.8h, v0.8b, v0.8b + umull2 v2.8h, v0.16b, v0.16b + umull v5.8h, v4.8b, v4.8b + umull2 v6.8h, v4.16b, v4.16b + +4: // Loop horizontally + ext v16.16b, v0.16b, v0.16b, #1 + ext v17.16b, v0.16b, v0.16b, #2 + ext v18.16b, v4.16b, v4.16b, #1 + ext v19.16b, v4.16b, v4.16b, #2 + uaddl v3.8h, v0.8b, v16.8b + uaddw v3.8h, v3.8h, v17.8b + uaddl v7.8h, v4.8b, v18.8b + uaddw v7.8h, v7.8h, v19.8b + + ext v20.16b, v1.16b, v2.16b, #2 + ext v21.16b, v1.16b, v2.16b, #4 + ext v22.16b, v5.16b, v6.16b, #2 + ext v23.16b, v5.16b, v6.16b, #4 + + uaddl v26.4s, v1.4h, v20.4h + uaddl2 v27.4s, v1.8h, v20.8h + uaddw v26.4s, v26.4s, v21.4h + uaddw2 v27.4s, v27.4s, v21.8h + + uaddl v28.4s, v5.4h, v22.4h + uaddl2 v29.4s, v5.8h, v22.8h + uaddw v28.4s, v28.4s, v23.4h + uaddw2 v29.4s, v29.4s, v23.8h + + subs w5, w5, #8 + + st1 {v3.8h}, [x1], #16 + st1 {v7.8h}, [x11], #16 + st1 {v26.4s,v27.4s}, [x0], #32 + st1 {v28.4s,v29.4s}, [x10], #32 + + b.le 9f + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8b}, [x3], #8 + ld1 {v7.8b}, [x12], #8 + mov v1.16b, v2.16b + mov v5.16b, v6.16b + ext v0.16b, v0.16b, v3.16b, #8 + ext v4.16b, v4.16b, v7.16b, #8 + umull v2.8h, v3.8b, v3.8b + umull v6.8h, v7.8b, v7.8b + + b.ne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs w6, w6, #2 + b.le 0f + // Jump to the next row and loop horizontally + add x0, x0, x9, lsl #1 + add x10, x10, x9, lsl #1 + add x1, x1, x9 + add x11, x11, x9 + add x3, x3, x4 + add x12, x12, x4 + mov w5, w8 + b 1b +0: + ret +endfunc + +// void dav1d_sgr_box5_h_8bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_h_8bpc_neon, export=1 + add w5, w5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add x10, x0, #(4*SUM_STRIDE) // sumsq + add x11, x1, #(2*SUM_STRIDE) // sum + add x12, x3, x4 // src + lsl x4, x4, #1 + mov x9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add w13, w5, #7 + bic w13, w13, #7 + sub x9, x9, w13, uxtw #1 + add w13, w13, #8 + sub x4, x4, w13, uxtw + + // Store the width for the vertical loop + mov w8, w5 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 2f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #3 + sub x12, x12, #3 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add x4, x4, #3 + +1: // Loop vertically + ld1 {v0.16b}, [x3], #16 + ld1 {v4.16b}, [x12], #16 + + tst w7, #1 // LR_HAVE_LEFT + b.eq 0f + cbz x2, 2f + // LR_HAVE_LEFT, left != NULL + ld1 {v1.s}[3], [x2], #4 + // Move x3/x12 back to account for the last 3 bytes we loaded earlier, + // which we'll shift out. + sub x3, x3, #3 + sub x12, x12, #3 + ld1 {v5.s}[3], [x2], #4 + ext v0.16b, v1.16b, v0.16b, #13 + ext v4.16b, v5.16b, v4.16b, #13 + b 2f +0: + // !LR_HAVE_LEFT, fill v1 with the leftmost byte + // and shift v0 to have 3x the first byte at the front. + dup v1.16b, v0.b[0] + dup v5.16b, v4.b[0] + // Move x3 back to account for the last 3 bytes we loaded before, + // which we shifted out. + sub x3, x3, #3 + sub x12, x12, #3 + ext v0.16b, v1.16b, v0.16b, #13 + ext v4.16b, v5.16b, v4.16b, #13 + +2: + umull v1.8h, v0.8b, v0.8b + umull2 v2.8h, v0.16b, v0.16b + umull v5.8h, v4.8b, v4.8b + umull2 v6.8h, v4.16b, v4.16b + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + // If we'll need to pad the right edge, load that byte to pad with + // here since we can find it pretty easily from here. + sub w13, w5, #(2 + 16 - 3 + 1) + ldr b30, [x3, w13, sxtw] + ldr b31, [x12, w13, sxtw] + // Fill v30/v31 with the right padding pixel + dup v30.16b, v30.b[0] + dup v31.16b, v31.b[0] +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w5, #11 + b.ge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+1 pixels valid in v0. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in v0/4.b[w+1] onwards; fuse the +1 into the + // buffer pointer. + movrel x13, right_ext_mask, -1 + sub x13, x13, w5, uxtw + ld1 {v29.16b}, [x13] + + bit v0.16b, v30.16b, v29.16b + bit v4.16b, v31.16b, v29.16b + + // Update the precalculated squares + umull v1.8h, v0.8b, v0.8b + umull2 v2.8h, v0.16b, v0.16b + umull v5.8h, v4.8b, v4.8b + umull2 v6.8h, v4.16b, v4.16b + +4: // Loop horizontally + ext v16.16b, v0.16b, v0.16b, #1 + ext v17.16b, v0.16b, v0.16b, #2 + ext v18.16b, v0.16b, v0.16b, #3 + ext v19.16b, v0.16b, v0.16b, #4 + ext v20.16b, v4.16b, v4.16b, #1 + ext v21.16b, v4.16b, v4.16b, #2 + ext v22.16b, v4.16b, v4.16b, #3 + ext v23.16b, v4.16b, v4.16b, #4 + uaddl v3.8h, v0.8b, v16.8b + uaddl v24.8h, v17.8b, v18.8b + uaddl v7.8h, v4.8b, v20.8b + uaddw v3.8h, v3.8h, v19.8b + uaddl v25.8h, v21.8b, v22.8b + uaddw v7.8h, v7.8h, v23.8b + add v3.8h, v3.8h, v24.8h + add v7.8h, v7.8h, v25.8h + + ext v16.16b, v1.16b, v2.16b, #2 + ext v17.16b, v1.16b, v2.16b, #4 + ext v18.16b, v1.16b, v2.16b, #6 + ext v19.16b, v1.16b, v2.16b, #8 + ext v20.16b, v5.16b, v6.16b, #2 + ext v21.16b, v5.16b, v6.16b, #4 + ext v22.16b, v5.16b, v6.16b, #6 + ext v23.16b, v5.16b, v6.16b, #8 + + uaddl v26.4s, v1.4h, v16.4h + uaddl2 v27.4s, v1.8h, v16.8h + uaddl v16.4s, v17.4h, v18.4h + uaddl2 v17.4s, v17.8h, v18.8h + uaddl v28.4s, v5.4h, v20.4h + uaddl2 v29.4s, v5.8h, v20.8h + uaddw v26.4s, v26.4s, v19.4h + uaddw2 v27.4s, v27.4s, v19.8h + uaddl v20.4s, v21.4h, v22.4h + uaddl2 v21.4s, v21.8h, v22.8h + uaddw v28.4s, v28.4s, v23.4h + uaddw2 v29.4s, v29.4s, v23.8h + add v26.4s, v26.4s, v16.4s + add v27.4s, v27.4s, v17.4s + add v28.4s, v28.4s, v20.4s + add v29.4s, v29.4s, v21.4s + + subs w5, w5, #8 + + st1 {v3.8h}, [x1], #16 + st1 {v7.8h}, [x11], #16 + st1 {v26.4s,v27.4s}, [x0], #32 + st1 {v28.4s,v29.4s}, [x10], #32 + + b.le 9f + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8b}, [x3], #8 + ld1 {v7.8b}, [x12], #8 + mov v1.16b, v2.16b + mov v5.16b, v6.16b + ext v0.16b, v0.16b, v3.16b, #8 + ext v4.16b, v4.16b, v7.16b, #8 + umull v2.8h, v3.8b, v3.8b + umull v6.8h, v7.8b, v7.8b + b.ne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs w6, w6, #2 + b.le 0f + // Jump to the next row and loop horizontally + add x0, x0, x9, lsl #1 + add x10, x10, x9, lsl #1 + add x1, x1, x9 + add x11, x11, x9 + add x3, x3, x4 + add x12, x12, x4 + mov w5, w8 + b 1b +0: + ret +endfunc + +sgr_funcs 8 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1419 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +const right_ext_mask_buf + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +right_ext_mask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +endconst + +// void dav1d_wiener_filter7_16bpc_neon(pixel *p, const ptrdiff_t p_stride, +// const pixel (*left)[4], const pixel *lpf, +// const int w, int h, +// const int16_t filter[2][8], +// const enum LrEdgeFlags edges, +// const int bitdepth_max); +function wiener_filter7_16bpc_neon, export=1 + ldr w8, [sp] + AARCH64_SIGN_LINK_REGISTER + stp x29, x30, [sp, #-32]! + stp d8, d9, [sp, #16] + mov x29, sp + ld1 {v0.8h, v1.8h}, [x6] + tst w7, #4 // LR_HAVE_TOP + sub_sp 384*2*6 + + dup v28.8h, w8 // bitdepth_max + clz w8, w8 + movi v30.4s, #1 + sub w10, w8, #38 // -(bitdepth + 6) + sub w11, w8, #11 // round_bits_v + sub w8, w8, #25 // -round_bits_h + neg w10, w10 // bitdepth + 6 + neg w11, w11 // -round_bits_v + dup v2.4s, w10 + dup v29.4s, w8 // -round_bits_h + dup v27.4s, w11 // -round_bits_v + movi v31.8h, #0x20, lsl #8 // 1 << 13 = 8192 + ushl v30.4s, v30.4s, v2.4s // 1 << (bitdepth + 6) + + zip1 v0.2d, v0.2d, v1.2d // move vertical coeffs to v0.h[4-7], freeing up v1 + + // x9 - t6 + // x10 - t5 + // x11 - t4 + // x12 - t3 + // x13 - t2 + // x14 - t1 + // x15 - t0 + mov x14, sp // t1 + b.eq L(no_top_7) + + mov x16, x2 // backup left + mov x2, #0 + bl wiener_filter7_h_16bpc_neon + add x3, x3, x1 // lpf += stride + mov x9, x14 // t6 + mov x10, x14 // t5 + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_16bpc_neon + add x3, x3, x1, lsl #2 + add x3, x3, x1 // lpf += stride*5 + mov x11, x14 // t4 + add x14, x14, #384*2 // t1 += 384*2 + mov x2, x16 // left + mov x16, x3 // backup lpf + mov x3, x0 // lpf = p + bl wiener_filter7_h_16bpc_neon + subs w5, w5, #1 // h-- + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_16bpc_neon + mov x13, x14 // t2 + subs w5, w5, #1 // h-- + b.eq L(v2_7) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x3, x3, x1 // src += stride + +L(main_7): + add x15, x14, #384*2 // t0 = t1 + 384*2 +L(main_loop_7): + bl wiener_filter7_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_loop_7) + tst w7, #8 // LR_HAVE_BOTTOM + b.eq L(v3_7) + + mov x3, x16 // restore lpf + mov x2, #0 // left = NULL + bl wiener_filter7_hv_16bpc_neon + bl wiener_filter7_hv_16bpc_neon +L(v1_7): + bl wiener_filter7_v_16bpc_neon + + mov sp, x29 + ldp d8, d9, [sp, #16] + ldp x29, x30, [sp], #32 + AARCH64_VALIDATE_LINK_REGISTER + ret + +L(no_top_7): + add x3, x3, x1, lsl #2 + add x16, x3, x1, lsl #1 // lpf += stride*6, backup + mov x3, x0 // lpf = p + + bl wiener_filter7_h_16bpc_neon + subs w5, w5, #1 // h-- + mov x9, x14 // t6 + mov x10, x14 // t5 + mov x11, x14 // t4 + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_7) + add x3, x3, x1 // src += p_stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_16bpc_neon + subs w5, w5, #1 // h-- + mov x13, x14 // t2 + b.eq L(v2_7) + add x3, x3, x1 // src += p_stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter7_h_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x3, x3, x1 // src += p_stride + add x15, x14, #384*2 // t0 = t1 + 384*2 + bl wiener_filter7_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v3_7) + add x15, x15, #384*2*4 // t0 += 384*2*4 + bl wiener_filter7_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_7) +L(v3_7): + bl wiener_filter7_v_16bpc_neon +L(v2_7): + bl wiener_filter7_v_16bpc_neon + b L(v1_7) +endfunc + + +function wiener_filter7_h_16bpc_neon + stp x3, x4, [sp, #-32]! + str x14, [sp, #16] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #6 + ld1 {v2.8h, v3.8h}, [x3], #32 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v2.8h, v3.8h}, [x3], #32 + ld1 {v4.d}[1], [x2], #8 + // Move x3 back to account for the last 3 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #6 + ext v3.16b, v2.16b, v3.16b, #10 + ext v2.16b, v4.16b, v2.16b, #10 + b 2f + +1: + ld1 {v2.8h, v3.8h}, [x3], #32 + // !LR_HAVE_LEFT, fill v4 with the leftmost pixel + // and shift v3 to have 3x the first pixel at the front. + dup v4.8h, v2.h[0] + // Move x3 back to account for the last 3 pixels we loaded before, + // which we shifted out. + sub x3, x3, #6 + ext v3.16b, v2.16b, v3.16b, #10 + ext v2.16b, v4.16b, v2.16b, #10 + +2: + ld1 {v4.8h}, [x3], #16 + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #19 + b.ge 4f // If w >= 19, all used input pixels are valid + + // 1 <= w < 19, w+3 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-22] to find the padding pixel. + sub w17, w4, #22 + // Insert padding in v2/3/4.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -6 + ldr h26, [x3, w17, sxtw #1] + sub x6, x6, w4, uxtw #1 + dup v26.8h, v26.h[0] + ld1 {v23.16b, v24.16b, v25.16b}, [x6] + + bit v2.16b, v26.16b, v23.16b + bit v3.16b, v26.16b, v24.16b + bit v4.16b, v26.16b, v25.16b + +4: // Loop horizontally + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + ext v17.16b, v2.16b, v3.16b, #4 + ext v19.16b, v2.16b, v3.16b, #8 + ext v16.16b, v2.16b, v3.16b, #2 + ext v20.16b, v2.16b, v3.16b, #10 + ext v21.16b, v2.16b, v3.16b, #12 + ext v18.16b, v2.16b, v3.16b, #6 + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v2.8h + smull v6.4s, v18.4h, v0.h[3] + smlal v6.4s, v19.4h, v0.h[2] + smlal v6.4s, v20.4h, v0.h[1] + smlal v6.4s, v21.4h, v0.h[0] + smull2 v7.4s, v18.8h, v0.h[3] + smlal2 v7.4s, v19.8h, v0.h[2] + smlal2 v7.4s, v20.8h, v0.h[1] + smlal2 v7.4s, v21.8h, v0.h[0] + + ext v17.16b, v3.16b, v4.16b, #4 + ext v19.16b, v3.16b, v4.16b, #8 + ext v16.16b, v3.16b, v4.16b, #2 + ext v20.16b, v3.16b, v4.16b, #10 + ext v21.16b, v3.16b, v4.16b, #12 + ext v18.16b, v3.16b, v4.16b, #6 + + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v3.8h + smull v16.4s, v18.4h, v0.h[3] + smlal v16.4s, v19.4h, v0.h[2] + smlal v16.4s, v20.4h, v0.h[1] + smlal v16.4s, v21.4h, v0.h[0] + smull2 v17.4s, v18.8h, v0.h[3] + smlal2 v17.4s, v19.8h, v0.h[2] + smlal2 v17.4s, v20.8h, v0.h[1] + smlal2 v17.4s, v21.8h, v0.h[0] + + mvni v24.8h, #0x80, lsl #8 // 0x7fff = (1 << 15) - 1 + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + add v16.4s, v16.4s, v30.4s + add v17.4s, v17.4s, v30.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + srshl v16.4s, v16.4s, v29.4s + srshl v17.4s, v17.4s, v29.4s + sqxtun v6.4h, v6.4s + sqxtun2 v6.8h, v7.4s + sqxtun v7.4h, v16.4s + sqxtun2 v7.8h, v17.4s + umin v6.8h, v6.8h, v24.8h + umin v7.8h, v7.8h, v24.8h + sub v6.8h, v6.8h, v31.8h + sub v7.8h, v7.8h, v31.8h + + subs w4, w4, #16 + + st1 {v6.8h, v7.8h}, [x14], #32 + + b.le 0f + mov v2.16b, v4.16b + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8h, v4.8h}, [x3], #32 + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldr x14, [sp, #16] + ldp x3, x4, [sp], #32 + ret +endfunc + +function wiener_filter7_v_16bpc_neon + // Backing up/restoring registers shifted, so that x9 gets the value + // of x10, etc, afterwards. + stp x10, x11, [sp, #-64]! + stp x12, x13, [sp, #16] + stp x14, x14, [sp, #32] + stp x0, x4, [sp, #48] +1: + ld1 {v16.8h, v17.8h}, [x9], #32 + ld1 {v18.8h, v19.8h}, [x10], #32 + ld1 {v20.8h, v21.8h}, [x11], #32 + ld1 {v22.8h, v23.8h}, [x12], #32 + ld1 {v24.8h, v25.8h}, [x13], #32 + ld1 {v6.8h, v7.8h}, [x14], #32 + + smull v2.4s, v16.4h, v0.h[4] + smlal v2.4s, v18.4h, v0.h[5] + smlal v2.4s, v20.4h, v0.h[6] + smlal v2.4s, v22.4h, v0.h[7] + smlal v2.4s, v24.4h, v0.h[6] + smlal v2.4s, v6.4h, v0.h[5] + smlal v2.4s, v6.4h, v0.h[4] + smull2 v3.4s, v16.8h, v0.h[4] + smlal2 v3.4s, v18.8h, v0.h[5] + smlal2 v3.4s, v20.8h, v0.h[6] + smlal2 v3.4s, v22.8h, v0.h[7] + smlal2 v3.4s, v24.8h, v0.h[6] + smlal2 v3.4s, v6.8h, v0.h[5] + smlal2 v3.4s, v6.8h, v0.h[4] + smull v4.4s, v17.4h, v0.h[4] + smlal v4.4s, v19.4h, v0.h[5] + smlal v4.4s, v21.4h, v0.h[6] + smlal v4.4s, v23.4h, v0.h[7] + smlal v4.4s, v25.4h, v0.h[6] + smlal v4.4s, v7.4h, v0.h[5] + smlal v4.4s, v7.4h, v0.h[4] + smull2 v5.4s, v17.8h, v0.h[4] + smlal2 v5.4s, v19.8h, v0.h[5] + smlal2 v5.4s, v21.8h, v0.h[6] + smlal2 v5.4s, v23.8h, v0.h[7] + smlal2 v5.4s, v25.8h, v0.h[6] + smlal2 v5.4s, v7.8h, v0.h[5] + smlal2 v5.4s, v7.8h, v0.h[4] + srshl v2.4s, v2.4s, v27.4s // -round_bits_v + srshl v3.4s, v3.4s, v27.4s + srshl v4.4s, v4.4s, v27.4s + srshl v5.4s, v5.4s, v27.4s + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v28.8h // bitdepth_max + umin v3.8h, v3.8h, v28.8h + subs w4, w4, #16 + st1 {v2.8h, v3.8h}, [x0], #32 + b.gt 1b + + ldp x0, x4, [sp, #48] + ldp x13, x14, [sp, #32] + ldp x11, x12, [sp, #16] + ldp x9, x10, [sp], #64 + + add x0, x0, x1 + ret +endfunc + +function wiener_filter7_hv_16bpc_neon + // Backing up/restoring registers shifted, so that x9 gets the value + // of x10, etc, and x15==x9, afterwards. + stp x10, x11, [sp, #-80]! + stp x12, x13, [sp, #16] + stp x14, x15, [sp, #32] + stp x10, x0, [sp, #48] + stp x3, x4, [sp, #64] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #6 + ld1 {v2.8h, v3.8h}, [x3], #32 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v2.8h, v3.8h}, [x3], #32 + ld1 {v4.d}[1], [x2], #8 + // Move x3 back to account for the last 3 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #6 + ext v3.16b, v2.16b, v3.16b, #10 + ext v2.16b, v4.16b, v2.16b, #10 + b 2f +1: + ld1 {v2.8h, v3.8h}, [x3], #32 + // !LR_HAVE_LEFT, fill v4 with the leftmost pixel + // and shift v3 to have 3x the first pixel at the front. + dup v4.8h, v2.h[0] + // Move x3 back to account for the last 3 pixels we loaded before, + // which we shifted out. + sub x3, x3, #6 + ext v3.16b, v2.16b, v3.16b, #10 + ext v2.16b, v4.16b, v2.16b, #10 + +2: + ld1 {v4.8h}, [x3], #16 + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #19 + b.ge 4f // If w >= 19, all used input pixels are valid + + // 1 <= w < 19, w+3 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-22] to find the padding pixel. + sub w17, w4, #22 + // Insert padding in v2/3/4.h[w+3] onwards; fuse the +3 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -6 + ldr h26, [x3, w17, sxtw #1] + sub x6, x6, w4, uxtw #1 + dup v26.8h, v26.h[0] + ld1 {v23.16b, v24.16b, v25.16b}, [x6] + + bit v2.16b, v26.16b, v23.16b + bit v3.16b, v26.16b, v24.16b + bit v4.16b, v26.16b, v25.16b + +4: // Loop horizontally + ext v17.16b, v2.16b, v3.16b, #4 + ext v19.16b, v2.16b, v3.16b, #8 + ext v16.16b, v2.16b, v3.16b, #2 + ext v20.16b, v2.16b, v3.16b, #10 + ext v21.16b, v2.16b, v3.16b, #12 + ext v18.16b, v2.16b, v3.16b, #6 + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v2.8h + smull v6.4s, v18.4h, v0.h[3] + smlal v6.4s, v19.4h, v0.h[2] + smlal v6.4s, v20.4h, v0.h[1] + smlal v6.4s, v21.4h, v0.h[0] + smull2 v7.4s, v18.8h, v0.h[3] + smlal2 v7.4s, v19.8h, v0.h[2] + smlal2 v7.4s, v20.8h, v0.h[1] + smlal2 v7.4s, v21.8h, v0.h[0] + + ext v17.16b, v3.16b, v4.16b, #4 + ext v19.16b, v3.16b, v4.16b, #8 + ext v16.16b, v3.16b, v4.16b, #2 + ext v20.16b, v3.16b, v4.16b, #10 + ext v21.16b, v3.16b, v4.16b, #12 + ext v18.16b, v3.16b, v4.16b, #6 + + add v19.8h, v19.8h, v17.8h + add v20.8h, v20.8h, v16.8h + add v21.8h, v21.8h, v3.8h + smull v24.4s, v18.4h, v0.h[3] + smlal v24.4s, v19.4h, v0.h[2] + smlal v24.4s, v20.4h, v0.h[1] + smlal v24.4s, v21.4h, v0.h[0] + smull2 v25.4s, v18.8h, v0.h[3] + smlal2 v25.4s, v19.8h, v0.h[2] + smlal2 v25.4s, v20.8h, v0.h[1] + smlal2 v25.4s, v21.8h, v0.h[0] + + ld1 {v16.8h, v17.8h}, [x9], #32 + + mvni v26.8h, #0x80, lsl #8 // 0x7fff = (1 << 15) - 1 + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + add v24.4s, v24.4s, v30.4s + add v25.4s, v25.4s, v30.4s + ld1 {v18.8h, v19.8h}, [x10], #32 + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + srshl v24.4s, v24.4s, v29.4s + srshl v25.4s, v25.4s, v29.4s + ld1 {v20.8h, v21.8h}, [x11], #32 + sqxtun v6.4h, v6.4s + sqxtun2 v6.8h, v7.4s + sqxtun v7.4h, v24.4s + sqxtun2 v7.8h, v25.4s + ld1 {v22.8h, v23.8h}, [x12], #32 + umin v6.8h, v6.8h, v26.8h + umin v7.8h, v7.8h, v26.8h + ld1 {v24.8h, v25.8h}, [x13], #32 + sub v6.8h, v6.8h, v31.8h + sub v7.8h, v7.8h, v31.8h + + ld1 {v8.8h, v9.8h}, [x14], #32 + + smull v1.4s, v16.4h, v0.h[4] + smlal v1.4s, v18.4h, v0.h[5] + smlal v1.4s, v20.4h, v0.h[6] + smlal v1.4s, v22.4h, v0.h[7] + smlal v1.4s, v24.4h, v0.h[6] + smlal v1.4s, v8.4h, v0.h[5] + smlal v1.4s, v6.4h, v0.h[4] + smull2 v5.4s, v16.8h, v0.h[4] + smlal2 v5.4s, v18.8h, v0.h[5] + smlal2 v5.4s, v20.8h, v0.h[6] + smlal2 v5.4s, v22.8h, v0.h[7] + smlal2 v5.4s, v24.8h, v0.h[6] + smlal2 v5.4s, v8.8h, v0.h[5] + smlal2 v5.4s, v6.8h, v0.h[4] + smull v26.4s, v17.4h, v0.h[4] + smlal v26.4s, v19.4h, v0.h[5] + smlal v26.4s, v21.4h, v0.h[6] + smlal v26.4s, v23.4h, v0.h[7] + smlal v26.4s, v25.4h, v0.h[6] + smlal v26.4s, v9.4h, v0.h[5] + smlal v26.4s, v7.4h, v0.h[4] + smull2 v16.4s, v17.8h, v0.h[4] + smlal2 v16.4s, v19.8h, v0.h[5] + smlal2 v16.4s, v21.8h, v0.h[6] + smlal2 v16.4s, v23.8h, v0.h[7] + smlal2 v16.4s, v25.8h, v0.h[6] + smlal2 v16.4s, v9.8h, v0.h[5] + smlal2 v16.4s, v7.8h, v0.h[4] + srshl v1.4s, v1.4s, v27.4s // -round_bits_v + srshl v5.4s, v5.4s, v27.4s + srshl v26.4s, v26.4s, v27.4s + srshl v16.4s, v16.4s, v27.4s + sqxtun v18.4h, v1.4s + sqxtun2 v18.8h, v5.4s + sqxtun v19.4h, v26.4s + sqxtun2 v19.8h, v16.4s + st1 {v6.8h, v7.8h}, [x15], #32 + umin v18.8h, v18.8h, v28.8h // bitdepth_max + umin v19.8h, v19.8h, v28.8h + subs w4, w4, #16 + + st1 {v18.8h, v19.8h}, [x0], #32 + + b.le 0f + mov v2.16b, v4.16b + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8h, v4.8h}, [x3], #32 + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldp x3, x4, [sp, #64] + ldp x15, x0, [sp, #48] + ldp x13, x14, [sp, #32] + ldp x11, x12, [sp, #16] + ldp x9, x10, [sp], #80 + + add x3, x3, x1 + add x0, x0, x1 + + ret +endfunc + +// void dav1d_wiener_filter5_16bpc_neon(pixel *p, const ptrdiff_t p_stride, +// const pixel (*left)[4], const pixel *lpf, +// const int w, int h, +// const int16_t filter[2][8], +// const enum LrEdgeFlags edges, +// const int bitdepth_max); +function wiener_filter5_16bpc_neon, export=1 + ldr w8, [sp] + AARCH64_SIGN_LINK_REGISTER + stp x29, x30, [sp, #-32]! + stp d8, d9, [sp, #16] + mov x29, sp + ld1 {v0.8h, v1.8h}, [x6] + tst w7, #4 // LR_HAVE_TOP + sub_sp 384*2*4 + + dup v28.8h, w8 // bitdepth_max + clz w8, w8 + movi v30.4s, #1 + sub w10, w8, #38 // -(bitdepth + 6) + sub w11, w8, #11 // round_bits_v + sub w8, w8, #25 // -round_bits_h + neg w10, w10 // bitdepth + 6 + neg w11, w11 // -round_bits_v + dup v2.4s, w10 + dup v29.4s, w8 // -round_bits_h + dup v27.4s, w11 // -round_bits_v + movi v31.8h, #0x20, lsl #8 // 1 << 13 = 8192 + ushl v30.4s, v30.4s, v2.4s // 1 << (bitdepth + 6) + + zip1 v0.2d, v0.2d, v1.2d // move vertical coeffs to v0.h[4-7], freeing up v1 + + // x11 - t4 + // x12 - t3 + // x13 - t2 + // x14 - t1 + // x15 - t0 + mov x14, sp // t1 + b.eq L(no_top_5) + + mov x16, x2 // backup left + mov x2, #0 + bl wiener_filter5_h_16bpc_neon + add x3, x3, x1 // lpf += stride + mov x11, x14 // t4 + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_16bpc_neon + add x3, x3, x1, lsl #2 + add x3, x3, x1 // lpf += stride*5 + mov x12, x14 // t3 + add x14, x14, #384*2 // t1 += 384*2 + mov x2, x16 // left + mov x16, x3 // backup lpf + mov x3, x0 // lpf = p + bl wiener_filter5_h_16bpc_neon + subs w5, w5, #1 // h-- + mov x13, x14 // t2 + b.eq L(v1_5) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x3, x3, x1 // src += stride + +L(main_5): + mov x15, x11 // t0 = t4 +L(main_loop_5): + bl wiener_filter5_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_loop_5) + tst w7, #8 // LR_HAVE_BOTTOM + b.eq L(v2_5) + + mov x3, x16 // restore lpf + mov x2, #0 // left = NULL + bl wiener_filter5_hv_16bpc_neon + bl wiener_filter5_hv_16bpc_neon +L(end_5): + + mov sp, x29 + ldp d8, d9, [sp, #16] + ldp x29, x30, [sp], #32 + AARCH64_VALIDATE_LINK_REGISTER + ret + +L(no_top_5): + add x3, x3, x1, lsl #2 + add x16, x3, x1, lsl #1 // lpf += stride*6, backup + mov x3, x0 // lpf = p + + bl wiener_filter5_h_16bpc_neon + subs w5, w5, #1 // h-- + mov x11, x14 // t4 + mov x12, x14 // t3 + mov x13, x14 // t2 + b.eq L(v1_5) + add x3, x3, x1 // src += stride + add x14, x14, #384*2 // t1 += 384*2 + bl wiener_filter5_h_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x3, x3, x1 // src += stride + add x15, x14, #384*2 // t0 = t1 + 384*2 + bl wiener_filter5_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.eq L(v2_5) + add x15, x15, #384*2*3 // t0 += 384*2*3 + bl wiener_filter5_hv_16bpc_neon + subs w5, w5, #1 // h-- + b.ne L(main_5) +L(v2_5): + bl wiener_filter5_v_16bpc_neon + add x0, x0, x1 + mov x11, x12 + mov x12, x13 + mov x13, x14 +L(v1_5): + bl wiener_filter5_v_16bpc_neon + b L(end_5) +endfunc + + +function wiener_filter5_h_16bpc_neon + stp x3, x4, [sp, #-32]! + str x14, [sp, #16] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #4 + ld1 {v2.8h, v3.8h}, [x3], #32 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v2.8h, v3.8h}, [x3], #32 + ld1 {v4.d}[1], [x2], #8 + // Move x3 back to account for the last 2 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #4 + ext v3.16b, v2.16b, v3.16b, #12 + ext v2.16b, v4.16b, v2.16b, #12 + b 2f + +1: + ld1 {v2.8h, v3.8h}, [x3], #32 + // !LR_HAVE_LEFT, fill v2 with the leftmost pixel + // and shift v3 to have 3x the first pixel at the front. + dup v4.8h, v2.h[0] + // Move x3 back to account for the last 2 pixels we loaded before, + // which we shifted out. + sub x3, x3, #4 + ext v3.16b, v2.16b, v3.16b, #12 + ext v2.16b, v4.16b, v2.16b, #12 + +2: + ld1 {v4.8h}, [x3], #16 + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #18 + b.ge 4f // If w >= 18, all used input pixels are valid + + // 1 <= w < 18, w+2 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+2]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-23] to find the padding pixel. + sub w17, w4, #23 + // Insert padding in v2/3/4.h[w+2] onwards; fuse the +2 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -4 + ldr h26, [x3, w17, sxtw #1] + sub x6, x6, w4, uxtw #1 + dup v26.8h, v26.h[0] + ld1 {v23.16b, v24.16b, v25.16b}, [x6] + + bit v2.16b, v26.16b, v23.16b + bit v3.16b, v26.16b, v24.16b + bit v4.16b, v26.16b, v25.16b + +4: // Loop horizontally + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + ext v16.16b, v2.16b, v3.16b, #2 + ext v18.16b, v2.16b, v3.16b, #6 + ext v19.16b, v2.16b, v3.16b, #8 + ext v17.16b, v2.16b, v3.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v2.8h + smull v6.4s, v17.4h, v0.h[3] + smlal v6.4s, v18.4h, v0.h[2] + smlal v6.4s, v19.4h, v0.h[1] + smull2 v7.4s, v17.8h, v0.h[3] + smlal2 v7.4s, v18.8h, v0.h[2] + smlal2 v7.4s, v19.8h, v0.h[1] + + ext v16.16b, v3.16b, v4.16b, #2 + ext v18.16b, v3.16b, v4.16b, #6 + ext v19.16b, v3.16b, v4.16b, #8 + ext v17.16b, v3.16b, v4.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v3.8h + smull v16.4s, v17.4h, v0.h[3] + smlal v16.4s, v18.4h, v0.h[2] + smlal v16.4s, v19.4h, v0.h[1] + smull2 v17.4s, v17.8h, v0.h[3] + smlal2 v17.4s, v18.8h, v0.h[2] + smlal2 v17.4s, v19.8h, v0.h[1] + + mvni v24.8h, #0x80, lsl #8 // 0x7fff = (1 << 15) - 1 + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + add v16.4s, v16.4s, v30.4s + add v17.4s, v17.4s, v30.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + srshl v16.4s, v16.4s, v29.4s + srshl v17.4s, v17.4s, v29.4s + sqxtun v6.4h, v6.4s + sqxtun2 v6.8h, v7.4s + sqxtun v7.4h, v16.4s + sqxtun2 v7.8h, v17.4s + umin v6.8h, v6.8h, v24.8h + umin v7.8h, v7.8h, v24.8h + sub v6.8h, v6.8h, v31.8h + sub v7.8h, v7.8h, v31.8h + + subs w4, w4, #16 + + st1 {v6.8h, v7.8h}, [x14], #32 + + b.le 0f + mov v2.16b, v4.16b + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8h, v4.8h}, [x3], #32 + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldr x14, [sp, #16] + ldp x3, x4, [sp], #32 + ret +endfunc + +function wiener_filter5_v_16bpc_neon + stp x11, x12, [sp, #-48]! + stp x13, x14, [sp, #16] + stp x0, x4, [sp, #32] +1: + ld1 {v16.8h, v17.8h}, [x11], #32 + ld1 {v18.8h, v19.8h}, [x12], #32 + ld1 {v20.8h, v21.8h}, [x13], #32 + ld1 {v22.8h, v23.8h}, [x14], #32 + + smull v2.4s, v16.4h, v0.h[5] + smlal v2.4s, v18.4h, v0.h[6] + smlal v2.4s, v20.4h, v0.h[7] + smlal v2.4s, v22.4h, v0.h[6] + smlal v2.4s, v22.4h, v0.h[5] + smull2 v3.4s, v16.8h, v0.h[5] + smlal2 v3.4s, v18.8h, v0.h[6] + smlal2 v3.4s, v20.8h, v0.h[7] + smlal2 v3.4s, v22.8h, v0.h[6] + smlal2 v3.4s, v22.8h, v0.h[5] + smull v4.4s, v17.4h, v0.h[5] + smlal v4.4s, v19.4h, v0.h[6] + smlal v4.4s, v21.4h, v0.h[7] + smlal v4.4s, v23.4h, v0.h[6] + smlal v4.4s, v23.4h, v0.h[5] + smull2 v5.4s, v17.8h, v0.h[5] + smlal2 v5.4s, v19.8h, v0.h[6] + smlal2 v5.4s, v21.8h, v0.h[7] + smlal2 v5.4s, v23.8h, v0.h[6] + smlal2 v5.4s, v23.8h, v0.h[5] + srshl v2.4s, v2.4s, v27.4s // -round_bits_v + srshl v3.4s, v3.4s, v27.4s + srshl v4.4s, v4.4s, v27.4s + srshl v5.4s, v5.4s, v27.4s + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v28.8h // bitdepth_max + umin v3.8h, v3.8h, v28.8h + + subs w4, w4, #16 + st1 {v2.8h, v3.8h}, [x0], #32 + b.gt 1b + + ldp x0, x4, [sp, #32] + ldp x13, x14, [sp, #16] + ldp x11, x12, [sp], #48 + + ret +endfunc + +function wiener_filter5_hv_16bpc_neon + // Backing up/restoring registers shifted, so that x11 gets the value + // of x12, etc, and x15==x11, afterwards. + stp x12, x13, [sp, #-64]! + stp x14, x15, [sp, #16] + stp x12, x0, [sp, #32] + stp x3, x4, [sp, #48] + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 1f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #4 + ld1 {v2.8h, v3.8h}, [x3], #32 + b 2f + +0: + // LR_HAVE_LEFT, left != NULL + ld1 {v2.8h, v3.8h}, [x3], #32 + ld1 {v4.d}[1], [x2], #8 + // Move x3 back to account for the last 2 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #4 + ext v3.16b, v2.16b, v3.16b, #12 + ext v2.16b, v4.16b, v2.16b, #12 + b 2f +1: + ld1 {v2.8h, v3.8h}, [x3], #32 + // !LR_HAVE_LEFT, fill v2 with the leftmost pixel + // and shift v3 to have 2x the first pixel at the front. + dup v4.8h, v2.h[0] + // Move x3 back to account for the last 2 pixels we loaded before, + // which we shifted out. + sub x3, x3, #4 + ext v3.16b, v2.16b, v3.16b, #12 + ext v2.16b, v4.16b, v2.16b, #12 + +2: + ld1 {v4.8h}, [x3], #16 + + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w4, #18 + b.ge 4f // If w >= 18, all used input pixels are valid + + // 1 <= w < 18, w+2 pixels valid in v2-v4. For w>=9, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // The padding pixel is v2/3/4.h[w+1]. x3 points at the next input, ie + // v2/3/4.h[24]. Thus read from x3[w-23] to find the padding pixel. + sub w17, w4, #23 + // Insert padding in v2/3/4.h[w+2] onwards; fuse the +2 (*2) into the + // buffer pointer. + movrel x6, right_ext_mask, -4 + ldr h26, [x3, w17, sxtw #1] + sub x6, x6, w4, uxtw #1 + dup v26.8h, v26.h[0] + ld1 {v23.16b, v24.16b, v25.16b}, [x6] + + bit v2.16b, v26.16b, v23.16b + bit v3.16b, v26.16b, v24.16b + bit v4.16b, v26.16b, v25.16b + +4: // Loop horizontally + ext v16.16b, v2.16b, v3.16b, #2 + ext v18.16b, v2.16b, v3.16b, #6 + ext v19.16b, v2.16b, v3.16b, #8 + ext v17.16b, v2.16b, v3.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v2.8h + smull v6.4s, v17.4h, v0.h[3] + smlal v6.4s, v18.4h, v0.h[2] + smlal v6.4s, v19.4h, v0.h[1] + smull2 v7.4s, v17.8h, v0.h[3] + smlal2 v7.4s, v18.8h, v0.h[2] + smlal2 v7.4s, v19.8h, v0.h[1] + + ext v16.16b, v3.16b, v4.16b, #2 + ext v18.16b, v3.16b, v4.16b, #6 + ext v19.16b, v3.16b, v4.16b, #8 + ext v17.16b, v3.16b, v4.16b, #4 + add v18.8h, v18.8h, v16.8h + add v19.8h, v19.8h, v3.8h + smull v24.4s, v17.4h, v0.h[3] + smlal v24.4s, v18.4h, v0.h[2] + smlal v24.4s, v19.4h, v0.h[1] + smull2 v25.4s, v17.8h, v0.h[3] + smlal2 v25.4s, v18.8h, v0.h[2] + smlal2 v25.4s, v19.8h, v0.h[1] + + ld1 {v16.8h, v17.8h}, [x11], #32 + mvni v26.8h, #0x80, lsl #8 // 0x7fff = (1 << 15) - 1 + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + add v24.4s, v24.4s, v30.4s + add v25.4s, v25.4s, v30.4s + ld1 {v18.8h, v19.8h}, [x12], #32 + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + srshl v24.4s, v24.4s, v29.4s + srshl v25.4s, v25.4s, v29.4s + ld1 {v20.8h, v21.8h}, [x13], #32 + sqxtun v6.4h, v6.4s + sqxtun2 v6.8h, v7.4s + sqxtun v7.4h, v24.4s + sqxtun2 v7.8h, v25.4s + ld1 {v22.8h, v23.8h}, [x14], #32 + umin v6.8h, v6.8h, v26.8h + umin v7.8h, v7.8h, v26.8h + sub v6.8h, v6.8h, v31.8h + sub v7.8h, v7.8h, v31.8h + + smull v8.4s, v16.4h, v0.h[5] + smlal v8.4s, v18.4h, v0.h[6] + smlal v8.4s, v20.4h, v0.h[7] + smlal v8.4s, v22.4h, v0.h[6] + smlal v8.4s, v6.4h, v0.h[5] + smull2 v9.4s, v16.8h, v0.h[5] + smlal2 v9.4s, v18.8h, v0.h[6] + smlal2 v9.4s, v20.8h, v0.h[7] + smlal2 v9.4s, v22.8h, v0.h[6] + smlal2 v9.4s, v6.8h, v0.h[5] + smull v1.4s, v17.4h, v0.h[5] + smlal v1.4s, v19.4h, v0.h[6] + smlal v1.4s, v21.4h, v0.h[7] + smlal v1.4s, v23.4h, v0.h[6] + smlal v1.4s, v7.4h, v0.h[5] + smull2 v5.4s, v17.8h, v0.h[5] + smlal2 v5.4s, v19.8h, v0.h[6] + smlal2 v5.4s, v21.8h, v0.h[7] + smlal2 v5.4s, v23.8h, v0.h[6] + smlal2 v5.4s, v7.8h, v0.h[5] + srshl v8.4s, v8.4s, v27.4s // -round_bits_v + srshl v9.4s, v9.4s, v27.4s + srshl v1.4s, v1.4s, v27.4s + srshl v5.4s, v5.4s, v27.4s + sqxtun v8.4h, v8.4s + sqxtun2 v8.8h, v9.4s + sqxtun v9.4h, v1.4s + sqxtun2 v9.8h, v5.4s + st1 {v6.8h, v7.8h}, [x15], #32 + umin v8.8h, v8.8h, v28.8h // bitdepth_max + umin v9.8h, v9.8h, v28.8h + + subs w4, w4, #16 + + st1 {v8.8h, v9.8h}, [x0], #32 + + b.le 0f + mov v2.16b, v4.16b + tst w7, #2 // LR_HAVE_RIGHT + ld1 {v3.8h, v4.8h}, [x3], #32 + b.ne 4b // If we don't need to pad, just keep filtering. + b 3b // If we need to pad, check how many pixels we have left. + +0: + ldp x3, x4, [sp, #48] + ldp x15, x0, [sp, #32] + ldp x13, x14, [sp, #16] + ldp x11, x12, [sp], #64 + + add x3, x3, x1 + add x0, x0, x1 + + ret +endfunc + +#define SUM_STRIDE (384+16) + +#include "looprestoration_tmpl.S" + +// void dav1d_sgr_box3_h_16bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_h_16bpc_neon, export=1 + add w5, w5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add x10, x0, #(4*SUM_STRIDE) // sumsq + add x11, x1, #(2*SUM_STRIDE) // sum + add x12, x3, x4 // src + lsl x4, x4, #1 + mov x9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add w13, w5, #7 + bic w13, w13, #7 + sub x9, x9, w13, uxtw #1 + + // Store the width for the vertical loop + mov w8, w5 + + // Subtract the number of pixels read from the input from the stride + add w13, w13, #8 + sub x4, x4, w13, uxtw #1 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 2f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #4 + sub x12, x12, #4 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 2 pixels from the src pointer, + // but shift it as if we had done that. + add x4, x4, #4 + + +1: // Loop vertically + ld1 {v0.8h, v1.8h}, [x3], #32 + ld1 {v16.8h, v17.8h}, [x12], #32 + + tst w7, #1 // LR_HAVE_LEFT + b.eq 0f + cbz x2, 2f + // LR_HAVE_LEFT, left != NULL + ld1 {v2.d}[1], [x2], #8 + // Move x3/x12 back to account for the last 2 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #4 + sub x12, x12, #4 + ld1 {v18.d}[1], [x2], #8 + ext v1.16b, v0.16b, v1.16b, #12 + ext v0.16b, v2.16b, v0.16b, #12 + ext v17.16b, v16.16b, v17.16b, #12 + ext v16.16b, v18.16b, v16.16b, #12 + b 2f +0: + // !LR_HAVE_LEFT, fill v2 with the leftmost pixel + // and shift v0/v1 to have 2x the first pixel at the front. + dup v2.8h, v0.h[0] + dup v18.8h, v16.h[0] + // Move x3 back to account for the last 2 pixels we loaded before, + // which we shifted out. + sub x3, x3, #4 + sub x12, x12, #4 + ext v1.16b, v0.16b, v1.16b, #12 + ext v0.16b, v2.16b, v0.16b, #12 + ext v17.16b, v16.16b, v17.16b, #12 + ext v16.16b, v18.16b, v16.16b, #12 + +2: + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + // If we'll need to pad the right edge, load that pixel to pad with + // here since we can find it pretty easily from here. + sub w13, w5, #(2 + 16 - 2 + 1) + ldr h30, [x3, w13, sxtw #1] + ldr h31, [x12, w13, sxtw #1] + // Fill v30/v31 with the right padding pixel + dup v30.8h, v30.h[0] + dup v31.8h, v31.h[0] +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w5, #10 + b.ge 4f // If w >= 10, all used input pixels are valid + + // 1 <= w < 10, w pixels valid in v0-v1. For w=9, this ends up called + // again; it's not strictly needed in those cases (we pad enough here), + // but keeping the code as simple as possible. + + // Insert padding in v0/1.h[w] onwards + movrel x13, right_ext_mask + sub x13, x13, w5, uxtw #1 + ld1 {v28.16b, v29.16b}, [x13] + + bit v0.16b, v30.16b, v28.16b + bit v1.16b, v30.16b, v29.16b + bit v16.16b, v31.16b, v28.16b + bit v17.16b, v31.16b, v29.16b + +4: // Loop horizontally + ext v26.16b, v0.16b, v1.16b, #2 + ext v28.16b, v16.16b, v17.16b, #2 + ext v27.16b, v0.16b, v1.16b, #4 + ext v29.16b, v16.16b, v17.16b, #4 + + add v6.8h, v0.8h, v26.8h + umull v22.4s, v0.4h, v0.4h + umlal v22.4s, v26.4h, v26.4h + umlal v22.4s, v27.4h, v27.4h + add v7.8h, v16.8h, v28.8h + umull v24.4s, v16.4h, v16.4h + umlal v24.4s, v28.4h, v28.4h + umlal v24.4s, v29.4h, v29.4h + add v6.8h, v6.8h, v27.8h + umull2 v23.4s, v0.8h, v0.8h + umlal2 v23.4s, v26.8h, v26.8h + umlal2 v23.4s, v27.8h, v27.8h + add v7.8h, v7.8h, v29.8h + umull2 v25.4s, v16.8h, v16.8h + umlal2 v25.4s, v28.8h, v28.8h + umlal2 v25.4s, v29.8h, v29.8h + + subs w5, w5, #8 + + st1 {v6.8h}, [x1], #16 + st1 {v7.8h}, [x11], #16 + st1 {v22.4s,v23.4s}, [x0], #32 + st1 {v24.4s,v25.4s}, [x10], #32 + + b.le 9f + tst w7, #2 // LR_HAVE_RIGHT + mov v0.16b, v1.16b + mov v16.16b, v17.16b + ld1 {v1.8h}, [x3], #16 + ld1 {v17.8h}, [x12], #16 + + b.ne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs w6, w6, #2 + b.le 0f + // Jump to the next row and loop horizontally + add x0, x0, x9, lsl #1 + add x10, x10, x9, lsl #1 + add x1, x1, x9 + add x11, x11, x9 + add x3, x3, x4 + add x12, x12, x4 + mov w5, w8 + b 1b +0: + ret +endfunc + +// void dav1d_sgr_box5_h_16bpc_neon(int32_t *sumsq, int16_t *sum, +// const pixel (*left)[4], +// const pixel *src, const ptrdiff_t stride, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_h_16bpc_neon, export=1 + add w5, w5, #2 // w += 2 + + // Set up pointers for reading/writing alternate rows + add x10, x0, #(4*SUM_STRIDE) // sumsq + add x11, x1, #(2*SUM_STRIDE) // sum + add x12, x3, x4 // src + lsl x4, x4, #1 + mov x9, #(2*2*SUM_STRIDE) // double sum stride + + // Subtract the aligned width from the output stride. + add w13, w5, #7 + bic w13, w13, #7 + sub x9, x9, w13, uxtw #1 + add w13, w13, #8 + sub x4, x4, w13, uxtw #1 + + // Store the width for the vertical loop + mov w8, w5 + + // Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL + tst w7, #1 // LR_HAVE_LEFT + b.eq 2f + // LR_HAVE_LEFT + cbnz x2, 0f + // left == NULL + sub x3, x3, #6 + sub x12, x12, #6 + b 1f +0: // LR_HAVE_LEFT, left != NULL +2: // !LR_HAVE_LEFT, increase the stride. + // For this case we don't read the left 3 pixels from the src pointer, + // but shift it as if we had done that. + add x4, x4, #6 + +1: // Loop vertically + ld1 {v0.8h, v1.8h}, [x3], #32 + ld1 {v16.8h, v17.8h}, [x12], #32 + + tst w7, #1 // LR_HAVE_LEFT + b.eq 0f + cbz x2, 2f + // LR_HAVE_LEFT, left != NULL + ld1 {v2.d}[1], [x2], #8 + // Move x3/x12 back to account for the last 3 pixels we loaded earlier, + // which we'll shift out. + sub x3, x3, #6 + sub x12, x12, #6 + ld1 {v18.d}[1], [x2], #8 + ext v1.16b, v0.16b, v1.16b, #10 + ext v0.16b, v2.16b, v0.16b, #10 + ext v17.16b, v16.16b, v17.16b, #10 + ext v16.16b, v18.16b, v16.16b, #10 + b 2f +0: + // !LR_HAVE_LEFT, fill v2 with the leftmost pixel + // and shift v0/v1 to have 3x the first pixel at the front. + dup v2.8h, v0.h[0] + dup v18.8h, v16.h[0] + // Move x3 back to account for the last 3 pixels we loaded before, + // which we shifted out. + sub x3, x3, #6 + sub x12, x12, #6 + ext v1.16b, v0.16b, v1.16b, #10 + ext v0.16b, v2.16b, v0.16b, #10 + ext v17.16b, v16.16b, v17.16b, #10 + ext v16.16b, v18.16b, v16.16b, #10 + +2: + tst w7, #2 // LR_HAVE_RIGHT + b.ne 4f + // If we'll need to pad the right edge, load that pixel to pad with + // here since we can find it pretty easily from here. + sub w13, w5, #(2 + 16 - 3 + 1) + ldr h30, [x3, w13, sxtw #1] + ldr h31, [x12, w13, sxtw #1] + // Fill v30/v31 with the right padding pixel + dup v30.8h, v30.h[0] + dup v31.8h, v31.h[0] +3: // !LR_HAVE_RIGHT + + // Check whether we need to pad the right edge + cmp w5, #11 + b.ge 4f // If w >= 11, all used input pixels are valid + + // 1 <= w < 11, w+1 pixels valid in v0-v1. For w=9 or w=10, + // this ends up called again; it's not strictly needed in those + // cases (we pad enough here), but keeping the code as simple as possible. + + // Insert padding in v0/1.h[w+1] onwards; fuse the +1 into the + // buffer pointer. + movrel x13, right_ext_mask, -2 + sub x13, x13, w5, uxtw #1 + ld1 {v28.16b, v29.16b}, [x13] + + bit v0.16b, v30.16b, v28.16b + bit v1.16b, v30.16b, v29.16b + bit v16.16b, v31.16b, v28.16b + bit v17.16b, v31.16b, v29.16b + +4: // Loop horizontally + ext v26.16b, v0.16b, v1.16b, #2 + ext v28.16b, v16.16b, v17.16b, #2 + ext v27.16b, v0.16b, v1.16b, #4 + ext v29.16b, v16.16b, v17.16b, #4 + + add v6.8h, v0.8h, v26.8h + umull v22.4s, v0.4h, v0.4h + umlal v22.4s, v26.4h, v26.4h + umlal v22.4s, v27.4h, v27.4h + add v7.8h, v16.8h, v28.8h + umull v24.4s, v16.4h, v16.4h + umlal v24.4s, v28.4h, v28.4h + umlal v24.4s, v29.4h, v29.4h + add v6.8h, v6.8h, v27.8h + umull2 v23.4s, v0.8h, v0.8h + umlal2 v23.4s, v26.8h, v26.8h + umlal2 v23.4s, v27.8h, v27.8h + add v7.8h, v7.8h, v29.8h + umull2 v25.4s, v16.8h, v16.8h + umlal2 v25.4s, v28.8h, v28.8h + umlal2 v25.4s, v29.8h, v29.8h + + ext v26.16b, v0.16b, v1.16b, #6 + ext v28.16b, v16.16b, v17.16b, #6 + ext v27.16b, v0.16b, v1.16b, #8 + ext v29.16b, v16.16b, v17.16b, #8 + + add v6.8h, v6.8h, v26.8h + umlal v22.4s, v26.4h, v26.4h + umlal v22.4s, v27.4h, v27.4h + add v7.8h, v7.8h, v28.8h + umlal v24.4s, v28.4h, v28.4h + umlal v24.4s, v29.4h, v29.4h + add v6.8h, v6.8h, v27.8h + umlal2 v23.4s, v26.8h, v26.8h + umlal2 v23.4s, v27.8h, v27.8h + add v7.8h, v7.8h, v29.8h + umlal2 v25.4s, v28.8h, v28.8h + umlal2 v25.4s, v29.8h, v29.8h + + subs w5, w5, #8 + + st1 {v6.8h}, [x1], #16 + st1 {v7.8h}, [x11], #16 + st1 {v22.4s,v23.4s}, [x0], #32 + st1 {v24.4s,v25.4s}, [x10], #32 + + b.le 9f + tst w7, #2 // LR_HAVE_RIGHT + mov v0.16b, v1.16b + mov v16.16b, v17.16b + ld1 {v1.8h}, [x3], #16 + ld1 {v17.8h}, [x12], #16 + + b.ne 4b // If we don't need to pad, just keep summing. + b 3b // If we need to pad, check how many pixels we have left. + +9: + subs w6, w6, #2 + b.le 0f + // Jump to the next row and loop horizontally + add x0, x0, x9, lsl #1 + add x10, x10, x9, lsl #1 + add x1, x1, x9 + add x11, x11, x9 + add x3, x3, x4 + add x12, x12, x4 + mov w5, w8 + b 1b +0: + ret +endfunc + +sgr_funcs 16 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_common.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_common.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_common.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_common.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,432 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define SUM_STRIDE (384+16) + +// void dav1d_sgr_box3_v_neon(int32_t *sumsq, int16_t *sum, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box3_v_neon, export=1 + add w10, w3, #2 // Number of output rows to move back + mov w11, w3 // Number of input rows to move back + add w2, w2, #2 // Actual summed width + mov x7, #(4*SUM_STRIDE) // sumsq stride + mov x8, #(2*SUM_STRIDE) // sum stride + sub x0, x0, #(4*SUM_STRIDE) // sumsq -= stride + sub x1, x1, #(2*SUM_STRIDE) // sum -= stride + + tst w4, #4 // LR_HAVE_TOP + b.eq 0f + // If have top, read from row -2. + sub x5, x0, #(4*SUM_STRIDE) + sub x6, x1, #(2*SUM_STRIDE) + add w11, w11, #2 + b 1f +0: + // !LR_HAVE_TOP + // If we don't have top, read from row 0 even if + // we start writing to row -1. + add x5, x0, #(4*SUM_STRIDE) + add x6, x1, #(2*SUM_STRIDE) +1: + + tst w4, #8 // LR_HAVE_BOTTOM + b.eq 1f + // LR_HAVE_BOTTOM + add w3, w3, #2 // Sum all h+2 lines with the main loop + add w11, w11, #2 +1: + mov w9, w3 // Backup of h for next loops + +1: + // Start of horizontal loop; start one vertical filter slice. + // Start loading rows into v16-v21 and v24-v26 taking top + // padding into consideration. + tst w4, #4 // LR_HAVE_TOP + ld1 {v16.4s, v17.4s}, [x5], x7 + ld1 {v24.8h}, [x6], x8 + b.eq 2f + // LR_HAVE_TOP + ld1 {v18.4s, v19.4s}, [x5], x7 + ld1 {v25.8h}, [x6], x8 + ld1 {v20.4s, v21.4s}, [x5], x7 + ld1 {v26.8h}, [x6], x8 + b 3f +2: // !LR_HAVE_TOP + mov v18.16b, v16.16b + mov v19.16b, v17.16b + mov v25.16b, v24.16b + mov v20.16b, v16.16b + mov v21.16b, v17.16b + mov v26.16b, v24.16b + +3: + subs w3, w3, #1 +.macro add3 + add v16.4s, v16.4s, v18.4s + add v17.4s, v17.4s, v19.4s + add v24.8h, v24.8h, v25.8h + add v16.4s, v16.4s, v20.4s + add v17.4s, v17.4s, v21.4s + add v24.8h, v24.8h, v26.8h + st1 {v16.4s, v17.4s}, [x0], x7 + st1 {v24.8h}, [x1], x8 +.endm + add3 + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v24.16b, v25.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v25.16b, v26.16b + b.le 4f + ld1 {v20.4s, v21.4s}, [x5], x7 + ld1 {v26.8h}, [x6], x8 + b 3b + +4: + tst w4, #8 // LR_HAVE_BOTTOM + b.ne 5f + // !LR_HAVE_BOTTOM + // Produce two more rows, extending the already loaded rows. + add3 + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v24.16b, v25.16b + add3 + +5: // End of one vertical slice. + subs w2, w2, #8 + b.le 0f + // Move pointers back up to the top and loop horizontally. + // Input pointers + msub x5, x7, x11, x5 + msub x6, x8, x11, x6 + // Output pointers + msub x0, x7, x10, x0 + msub x1, x8, x10, x1 + add x0, x0, #32 + add x1, x1, #16 + add x5, x5, #32 + add x6, x6, #16 + mov w3, w9 + b 1b + +0: + ret +.purgem add3 +endfunc + +// void dav1d_sgr_box5_v_neon(int32_t *sumsq, int16_t *sum, +// const int w, const int h, +// const enum LrEdgeFlags edges); +function sgr_box5_v_neon, export=1 + add w10, w3, #2 // Number of output rows to move back + mov w11, w3 // Number of input rows to move back + add w2, w2, #8 // Actual summed width + mov x7, #(4*SUM_STRIDE) // sumsq stride + mov x8, #(2*SUM_STRIDE) // sum stride + sub x0, x0, #(4*SUM_STRIDE) // sumsq -= stride + sub x1, x1, #(2*SUM_STRIDE) // sum -= stride + + tst w4, #4 // LR_HAVE_TOP + b.eq 0f + // If have top, read from row -2. + sub x5, x0, #(4*SUM_STRIDE) + sub x6, x1, #(2*SUM_STRIDE) + add w11, w11, #2 + b 1f +0: + // !LR_HAVE_TOP + // If we don't have top, read from row 0 even if + // we start writing to row -1. + add x5, x0, #(4*SUM_STRIDE) + add x6, x1, #(2*SUM_STRIDE) +1: + + tst w4, #8 // LR_HAVE_BOTTOM + b.eq 0f + // LR_HAVE_BOTTOM + add w3, w3, #2 // Handle h+2 lines with the main loop + add w11, w11, #2 + b 1f +0: + // !LR_HAVE_BOTTOM + sub w3, w3, #1 // Handle h-1 lines with the main loop +1: + mov w9, w3 // Backup of h for next loops + +1: + // Start of horizontal loop; start one vertical filter slice. + // Start loading rows into v16-v25 and v26-v30 taking top + // padding into consideration. + tst w4, #4 // LR_HAVE_TOP + ld1 {v16.4s, v17.4s}, [x5], x7 + ld1 {v26.8h}, [x6], x8 + b.eq 2f + // LR_HAVE_TOP + ld1 {v20.4s, v21.4s}, [x5], x7 + ld1 {v28.8h}, [x6], x8 + mov v18.16b, v16.16b + mov v19.16b, v17.16b + mov v27.16b, v26.16b + ld1 {v22.4s, v23.4s}, [x5], x7 + ld1 {v29.8h}, [x6], x8 + b 3f +2: // !LR_HAVE_TOP + mov v18.16b, v16.16b + mov v19.16b, v17.16b + mov v27.16b, v26.16b + mov v20.16b, v16.16b + mov v21.16b, v17.16b + mov v28.16b, v26.16b + mov v22.16b, v16.16b + mov v23.16b, v17.16b + mov v29.16b, v26.16b + +3: + cbz w3, 4f + ld1 {v24.4s, v25.4s}, [x5], x7 + ld1 {v30.8h}, [x6], x8 + +3: + // Start of vertical loop + subs w3, w3, #2 +.macro add5 + add v16.4s, v16.4s, v18.4s + add v17.4s, v17.4s, v19.4s + add v26.8h, v26.8h, v27.8h + add v0.4s, v20.4s, v22.4s + add v1.4s, v21.4s, v23.4s + add v2.8h, v28.8h, v29.8h + add v16.4s, v16.4s, v24.4s + add v17.4s, v17.4s, v25.4s + add v26.8h, v26.8h, v30.8h + add v16.4s, v16.4s, v0.4s + add v17.4s, v17.4s, v1.4s + add v26.8h, v26.8h, v2.8h + st1 {v16.4s, v17.4s}, [x0], x7 + st1 {v26.8h}, [x1], x8 +.endm + add5 +.macro shift2 + mov v16.16b, v20.16b + mov v17.16b, v21.16b + mov v26.16b, v28.16b + mov v18.16b, v22.16b + mov v19.16b, v23.16b + mov v27.16b, v29.16b + mov v20.16b, v24.16b + mov v21.16b, v25.16b + mov v28.16b, v30.16b +.endm + shift2 + add x0, x0, x7 + add x1, x1, x8 + b.le 5f + ld1 {v22.4s, v23.4s}, [x5], x7 + ld1 {v29.8h}, [x6], x8 + ld1 {v24.4s, v25.4s}, [x5], x7 + ld1 {v30.8h}, [x6], x8 + b 3b + +4: + // h == 1, !LR_HAVE_BOTTOM. + // Pad the last row with the only content row, and add. + mov v24.16b, v22.16b + mov v25.16b, v23.16b + mov v30.16b, v29.16b + add5 + shift2 + add x0, x0, x7 + add x1, x1, x8 + add5 + b 6f + +5: + tst w4, #8 // LR_HAVE_BOTTOM + b.ne 6f + // !LR_HAVE_BOTTOM + cbnz w3, 5f + // The intended three edge rows left; output the one at h-2 and + // the past edge one at h. + ld1 {v22.4s, v23.4s}, [x5], x7 + ld1 {v29.8h}, [x6], x8 + // Pad the past-edge row from the last content row. + mov v24.16b, v22.16b + mov v25.16b, v23.16b + mov v30.16b, v29.16b + add5 + shift2 + add x0, x0, x7 + add x1, x1, x8 + // The last two rows are already padded properly here. + add5 + b 6f + +5: + // w3 == -1, two rows left, output one. + // Pad the last two rows from the mid one. + mov v22.16b, v20.16b + mov v23.16b, v21.16b + mov v29.16b, v28.16b + mov v24.16b, v20.16b + mov v25.16b, v21.16b + mov v30.16b, v28.16b + add5 + add x0, x0, x7 + add x1, x1, x8 + b 6f + +6: // End of one vertical slice. + subs w2, w2, #8 + b.le 0f + // Move pointers back up to the top and loop horizontally. + // Input pointers + msub x5, x7, x11, x5 + msub x6, x8, x11, x6 + // Output pointers + msub x0, x7, x10, x0 + msub x1, x8, x10, x1 + add x0, x0, #32 + add x1, x1, #16 + add x5, x5, #32 + add x6, x6, #16 + mov w3, w9 + b 1b + +0: + ret +.purgem add5 +endfunc + +// void dav1d_sgr_calc_ab1_neon(int32_t *a, int16_t *b, +// const int w, const int h, const int strength, +// const int bitdepth_max); +// void dav1d_sgr_calc_ab2_neon(int32_t *a, int16_t *b, +// const int w, const int h, const int strength, +// const int bitdepth_max); +function sgr_calc_ab1_neon, export=1 + clz w9, w5 + add x3, x3, #2 // h += 2 + movi v31.4s, #9 // n + mov x5, #455 + mov x8, #SUM_STRIDE + b sgr_calc_ab_neon +endfunc + +function sgr_calc_ab2_neon, export=1 + clz w9, w5 + add x3, x3, #3 // h += 3 + asr x3, x3, #1 // h /= 2 + movi v31.4s, #25 // n + mov x5, #164 + mov x8, #(2*SUM_STRIDE) +endfunc + +function sgr_calc_ab_neon + sub w9, w9, #24 // -bitdepth_min_8 + movrel x12, X(sgr_x_by_x) + ld1 {v16.16b, v17.16b, v18.16b}, [x12] + dup v6.8h, w9 // -bitdepth_min_8 + movi v19.16b, #5 + movi v20.8b, #55 // idx of last 5 + movi v21.8b, #72 // idx of last 4 + movi v22.8b, #101 // idx of last 3 + movi v23.8b, #169 // idx of last 2 + movi v24.8b, #254 // idx of last 1 + saddl v7.4s, v6.4h, v6.4h // -2*bitdepth_min_8 + add x2, x2, #2 // w += 2 + add x7, x2, #7 + bic x7, x7, #7 // aligned w + sub x7, x8, x7 // increment between rows + movi v29.8h, #1, lsl #8 + dup v28.4s, w4 + dup v30.4s, w5 // one_by_x + sub x0, x0, #(4*(SUM_STRIDE)) + sub x1, x1, #(2*(SUM_STRIDE)) + mov x6, x2 // backup of w + sub v16.16b, v16.16b, v19.16b + sub v17.16b, v17.16b, v19.16b + sub v18.16b, v18.16b, v19.16b +1: + subs x2, x2, #8 + ld1 {v0.4s, v1.4s}, [x0] // a + ld1 {v2.8h}, [x1] // b + srshl v0.4s, v0.4s, v7.4s + srshl v1.4s, v1.4s, v7.4s + srshl v4.8h, v2.8h, v6.8h + mul v0.4s, v0.4s, v31.4s // a * n + mul v1.4s, v1.4s, v31.4s // a * n + umull v3.4s, v4.4h, v4.4h // b * b + umull2 v4.4s, v4.8h, v4.8h // b * b + uqsub v0.4s, v0.4s, v3.4s // imax(a * n - b * b, 0) + uqsub v1.4s, v1.4s, v4.4s // imax(a * n - b * b, 0) + mul v0.4s, v0.4s, v28.4s // p * s + mul v1.4s, v1.4s, v28.4s // p * s + uqshrn v0.4h, v0.4s, #16 + uqshrn2 v0.8h, v1.4s, #16 + uqrshrn v0.8b, v0.8h, #4 // imin(z, 255) + + cmhi v25.8b, v0.8b, v20.8b // = -1 if sgr_x_by_x[v0] < 5 + cmhi v26.8b, v0.8b, v21.8b // = -1 if sgr_x_by_x[v0] < 4 + tbl v1.8b, {v16.16b, v17.16b, v18.16b}, v0.8b + cmhi v27.8b, v0.8b, v22.8b // = -1 if sgr_x_by_x[v0] < 3 + cmhi v4.8b, v0.8b, v23.8b // = -1 if sgr_x_by_x[v0] < 2 + add v25.8b, v25.8b, v26.8b + cmhi v5.8b, v0.8b, v24.8b // = -1 if sgr_x_by_x[v0] < 1 + add v27.8b, v27.8b, v4.8b + add v5.8b, v5.8b, v19.8b + add v25.8b, v25.8b, v27.8b + add v1.8b, v1.8b, v5.8b + add v1.8b, v1.8b, v25.8b + uxtl v1.8h, v1.8b // x + + umull v3.4s, v1.4h, v2.4h // x * BB[i] + umull2 v4.4s, v1.8h, v2.8h // x * BB[i] + mul v3.4s, v3.4s, v30.4s // x * BB[i] * sgr_one_by_x + mul v4.4s, v4.4s, v30.4s // x * BB[i] * sgr_one_by_x + srshr v3.4s, v3.4s, #12 // AA[i] + srshr v4.4s, v4.4s, #12 // AA[i] + sub v2.8h, v29.8h, v1.8h // 256 - x + + st1 {v3.4s, v4.4s}, [x0], #32 + st1 {v2.8h}, [x1], #16 + b.gt 1b + + subs x3, x3, #1 + b.le 0f + add x0, x0, x7, lsl #2 + add x1, x1, x7, lsl #1 + mov x2, x6 + b 1b +0: + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_tmpl.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_tmpl.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_tmpl.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/looprestoration_tmpl.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,597 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" + +#define FILTER_OUT_STRIDE 384 + +.macro sgr_funcs bpc +// void dav1d_sgr_finish_filter1_Xbpc_neon(int16_t *tmp, +// const pixel *src, const ptrdiff_t stride, +// const int32_t *a, const int16_t *b, +// const int w, const int h); +function sgr_finish_filter1_\bpc\()bpc_neon, export=1 + sub x7, x3, #(4*SUM_STRIDE) + add x8, x3, #(4*SUM_STRIDE) + sub x9, x4, #(2*SUM_STRIDE) + add x10, x4, #(2*SUM_STRIDE) + mov x11, #SUM_STRIDE + mov x12, #FILTER_OUT_STRIDE + add x13, x5, #7 + bic x13, x13, #7 // Aligned width +.if \bpc == 8 + sub x2, x2, x13 +.else + sub x2, x2, x13, lsl #1 +.endif + sub x12, x12, x13 + sub x11, x11, x13 + sub x11, x11, #4 // We read 4 extra elements from a + sub x14, x11, #4 // We read 8 extra elements from b + mov x13, x5 + movi v6.8h, #3 + movi v7.4s, #3 +1: + ld1 {v0.8h, v1.8h}, [x9], #32 + ld1 {v2.8h, v3.8h}, [x4], #32 + ld1 {v4.8h, v5.8h}, [x10], #32 + ld1 {v16.4s, v17.4s, v18.4s}, [x7], #48 + ld1 {v19.4s, v20.4s, v21.4s}, [x3], #48 + ld1 {v22.4s, v23.4s, v24.4s}, [x8], #48 + +2: + subs x5, x5, #8 + ext v25.16b, v0.16b, v1.16b, #2 // -stride + ext v26.16b, v2.16b, v3.16b, #2 // 0 + ext v27.16b, v4.16b, v5.16b, #2 // +stride + ext v28.16b, v0.16b, v1.16b, #4 // +1-stride + ext v29.16b, v2.16b, v3.16b, #4 // +1 + ext v30.16b, v4.16b, v5.16b, #4 // +1+stride + add v2.8h, v2.8h, v25.8h // -1, -stride + add v26.8h, v26.8h, v27.8h // 0, +stride + add v0.8h, v0.8h, v28.8h // -1-stride, +1-stride + add v2.8h, v2.8h, v26.8h + add v4.8h, v4.8h, v30.8h // -1+stride, +1+stride + add v2.8h, v2.8h, v29.8h // +1 + add v0.8h, v0.8h, v4.8h + + ext v25.16b, v16.16b, v17.16b, #4 // -stride + ext v26.16b, v17.16b, v18.16b, #4 + shl v2.8h, v2.8h, #2 + ext v27.16b, v16.16b, v17.16b, #8 // +1-stride + ext v28.16b, v17.16b, v18.16b, #8 + ext v29.16b, v19.16b, v20.16b, #4 // 0 + ext v30.16b, v20.16b, v21.16b, #4 + mla v2.8h, v0.8h, v6.8h // * 3 -> a + add v25.4s, v25.4s, v19.4s // -stride, -1 + add v26.4s, v26.4s, v20.4s + add v16.4s, v16.4s, v27.4s // -1-stride, +1-stride + add v17.4s, v17.4s, v28.4s + ext v27.16b, v19.16b, v20.16b, #8 // +1 + ext v28.16b, v20.16b, v21.16b, #8 + add v16.4s, v16.4s, v22.4s // -1+stride + add v17.4s, v17.4s, v23.4s + add v29.4s, v29.4s, v27.4s // 0, +1 + add v30.4s, v30.4s, v28.4s + add v25.4s, v25.4s, v29.4s + add v26.4s, v26.4s, v30.4s + ext v27.16b, v22.16b, v23.16b, #4 // +stride + ext v28.16b, v23.16b, v24.16b, #4 + ext v29.16b, v22.16b, v23.16b, #8 // +1+stride + ext v30.16b, v23.16b, v24.16b, #8 +.if \bpc == 8 + ld1 {v19.8b}, [x1], #8 // src +.else + ld1 {v19.8h}, [x1], #16 // src +.endif + add v25.4s, v25.4s, v27.4s // +stride + add v26.4s, v26.4s, v28.4s + add v16.4s, v16.4s, v29.4s // +1+stride + add v17.4s, v17.4s, v30.4s + shl v25.4s, v25.4s, #2 + shl v26.4s, v26.4s, #2 + mla v25.4s, v16.4s, v7.4s // * 3 -> b + mla v26.4s, v17.4s, v7.4s +.if \bpc == 8 + uxtl v19.8h, v19.8b // src +.endif + mov v0.16b, v1.16b + umlal v25.4s, v2.4h, v19.4h // b + a * src + umlal2 v26.4s, v2.8h, v19.8h + mov v2.16b, v3.16b + rshrn v25.4h, v25.4s, #9 + rshrn2 v25.8h, v26.4s, #9 + mov v4.16b, v5.16b + st1 {v25.8h}, [x0], #16 + + b.le 3f + mov v16.16b, v18.16b + mov v19.16b, v21.16b + mov v22.16b, v24.16b + ld1 {v1.8h}, [x9], #16 + ld1 {v3.8h}, [x4], #16 + ld1 {v5.8h}, [x10], #16 + ld1 {v17.4s, v18.4s}, [x7], #32 + ld1 {v20.4s, v21.4s}, [x3], #32 + ld1 {v23.4s, v24.4s}, [x8], #32 + b 2b + +3: + subs x6, x6, #1 + b.le 0f + mov x5, x13 + add x0, x0, x12, lsl #1 + add x1, x1, x2 + add x3, x3, x11, lsl #2 + add x7, x7, x11, lsl #2 + add x8, x8, x11, lsl #2 + add x4, x4, x14, lsl #1 + add x9, x9, x14, lsl #1 + add x10, x10, x14, lsl #1 + b 1b +0: + ret +endfunc + +// void dav1d_sgr_finish_filter2_Xbpc_neon(int16_t *tmp, +// const pixel *src, const ptrdiff_t stride, +// const int32_t *a, const int16_t *b, +// const int w, const int h); +function sgr_finish_filter2_\bpc\()bpc_neon, export=1 + add x7, x3, #(4*(SUM_STRIDE)) + sub x3, x3, #(4*(SUM_STRIDE)) + add x8, x4, #(2*(SUM_STRIDE)) + sub x4, x4, #(2*(SUM_STRIDE)) + mov x9, #(2*SUM_STRIDE) + mov x10, #FILTER_OUT_STRIDE + add x11, x5, #7 + bic x11, x11, #7 // Aligned width +.if \bpc == 8 + sub x2, x2, x11 +.else + sub x2, x2, x11, lsl #1 +.endif + sub x10, x10, x11 + sub x9, x9, x11 + sub x9, x9, #4 // We read 4 extra elements from a + sub x12, x9, #4 // We read 8 extra elements from b + mov x11, x5 + movi v4.8h, #5 + movi v5.4s, #5 + movi v6.8h, #6 + movi v7.4s, #6 +1: + ld1 {v0.8h, v1.8h}, [x4], #32 + ld1 {v2.8h, v3.8h}, [x8], #32 + ld1 {v16.4s, v17.4s, v18.4s}, [x3], #48 + ld1 {v19.4s, v20.4s, v21.4s}, [x7], #48 + +2: + subs x5, x5, #8 + ext v24.16b, v0.16b, v1.16b, #4 // +1-stride + ext v25.16b, v2.16b, v3.16b, #4 // +1+stride + ext v22.16b, v0.16b, v1.16b, #2 // -stride + ext v23.16b, v2.16b, v3.16b, #2 // +stride + add v0.8h, v0.8h, v24.8h // -1-stride, +1-stride + add v25.8h, v2.8h, v25.8h // -1+stride, +1+stride + add v2.8h, v22.8h, v23.8h // -stride, +stride + add v0.8h, v0.8h, v25.8h + + ext v22.16b, v16.16b, v17.16b, #4 // -stride + ext v23.16b, v17.16b, v18.16b, #4 + ext v24.16b, v19.16b, v20.16b, #4 // +stride + ext v25.16b, v20.16b, v21.16b, #4 + ext v26.16b, v16.16b, v17.16b, #8 // +1-stride + ext v27.16b, v17.16b, v18.16b, #8 + ext v28.16b, v19.16b, v20.16b, #8 // +1+stride + ext v29.16b, v20.16b, v21.16b, #8 + mul v0.8h, v0.8h, v4.8h // * 5 + mla v0.8h, v2.8h, v6.8h // * 6 +.if \bpc == 8 + ld1 {v31.8b}, [x1], #8 +.else + ld1 {v31.8h}, [x1], #16 +.endif + add v16.4s, v16.4s, v26.4s // -1-stride, +1-stride + add v17.4s, v17.4s, v27.4s + add v19.4s, v19.4s, v28.4s // -1+stride, +1+stride + add v20.4s, v20.4s, v29.4s + add v16.4s, v16.4s, v19.4s + add v17.4s, v17.4s, v20.4s + + add v22.4s, v22.4s, v24.4s // -stride, +stride + add v23.4s, v23.4s, v25.4s + // This is, surprisingly, faster than other variants where the + // mul+mla pairs are further apart, on Cortex A53. + mul v16.4s, v16.4s, v5.4s // * 5 + mla v16.4s, v22.4s, v7.4s // * 6 + mul v17.4s, v17.4s, v5.4s // * 5 + mla v17.4s, v23.4s, v7.4s // * 6 + +.if \bpc == 8 + uxtl v31.8h, v31.8b +.endif + umlal v16.4s, v0.4h, v31.4h // b + a * src + umlal2 v17.4s, v0.8h, v31.8h + mov v0.16b, v1.16b + rshrn v16.4h, v16.4s, #9 + rshrn2 v16.8h, v17.4s, #9 + mov v2.16b, v3.16b + st1 {v16.8h}, [x0], #16 + + b.le 3f + mov v16.16b, v18.16b + mov v19.16b, v21.16b + ld1 {v1.8h}, [x4], #16 + ld1 {v3.8h}, [x8], #16 + ld1 {v17.4s, v18.4s}, [x3], #32 + ld1 {v20.4s, v21.4s}, [x7], #32 + b 2b + +3: + subs x6, x6, #1 + b.le 0f + mov x5, x11 + add x0, x0, x10, lsl #1 + add x1, x1, x2 + add x3, x3, x9, lsl #2 + add x7, x7, x9, lsl #2 + add x4, x4, x12, lsl #1 + add x8, x8, x12, lsl #1 + mov x13, x3 + mov x14, x4 + + ld1 {v0.8h, v1.8h}, [x4], #32 + ld1 {v16.4s, v17.4s, v18.4s}, [x3], #48 + +4: + subs x5, x5, #8 + ext v23.16b, v0.16b, v1.16b, #4 // +1 + ext v22.16b, v0.16b, v1.16b, #2 // 0 + add v0.8h, v0.8h, v23.8h // -1, +1 + + ext v24.16b, v16.16b, v17.16b, #4 // 0 + ext v25.16b, v17.16b, v18.16b, #4 + ext v26.16b, v16.16b, v17.16b, #8 // +1 + ext v27.16b, v17.16b, v18.16b, #8 + mul v2.8h, v22.8h, v6.8h // * 6 + mla v2.8h, v0.8h, v4.8h // * 5 -> a +.if \bpc == 8 + ld1 {v31.8b}, [x1], #8 +.else + ld1 {v31.8h}, [x1], #16 +.endif + add v16.4s, v16.4s, v26.4s // -1, +1 + add v17.4s, v17.4s, v27.4s +.if \bpc == 8 + uxtl v31.8h, v31.8b +.endif + // This is, surprisingly, faster than other variants where the + // mul+mla pairs are further apart, on Cortex A53. + mul v24.4s, v24.4s, v7.4s // * 6 + mla v24.4s, v16.4s, v5.4s // * 5 -> b + mul v25.4s, v25.4s, v7.4s // * 6 + mla v25.4s, v17.4s, v5.4s // * 5 -> b + + umlal v24.4s, v2.4h, v31.4h // b + a * src + umlal2 v25.4s, v2.8h, v31.8h + mov v0.16b, v1.16b + rshrn v24.4h, v24.4s, #8 + rshrn2 v24.8h, v25.4s, #8 + mov v16.16b, v18.16b + st1 {v24.8h}, [x0], #16 + + b.le 5f + ld1 {v1.8h}, [x4], #16 + ld1 {v17.4s, v18.4s}, [x3], #32 + b 4b + +5: + subs x6, x6, #1 + b.le 0f + mov x5, x11 + add x0, x0, x10, lsl #1 + add x1, x1, x2 + mov x3, x13 // Rewind x3/x4 to where they started + mov x4, x14 + b 1b +0: + ret +endfunc + +// void dav1d_sgr_weighted1_Xbpc_neon(pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *t1, const int w, const int h, +// const int wt, const int bitdepth_max); +function sgr_weighted1_\bpc\()bpc_neon, export=1 +.if \bpc == 16 + ldr w8, [sp] +.endif + dup v31.8h, w7 + cmp x6, #2 +.if \bpc == 16 + dup v30.8h, w8 +.endif + add x9, x0, x1 + add x10, x2, x3 + add x11, x4, #2*FILTER_OUT_STRIDE + mov x7, #(4*FILTER_OUT_STRIDE) + lsl x1, x1, #1 + lsl x3, x3, #1 + add x8, x5, #7 + bic x8, x8, #7 // Aligned width +.if \bpc == 8 + sub x1, x1, x8 + sub x3, x3, x8 +.else + sub x1, x1, x8, lsl #1 + sub x3, x3, x8, lsl #1 +.endif + sub x7, x7, x8, lsl #1 + mov x8, x5 + b.lt 2f +1: +.if \bpc == 8 + ld1 {v0.8b}, [x2], #8 + ld1 {v4.8b}, [x10], #8 +.else + ld1 {v0.8h}, [x2], #16 + ld1 {v4.8h}, [x10], #16 +.endif + ld1 {v1.8h}, [x4], #16 + ld1 {v5.8h}, [x11], #16 + subs x5, x5, #8 +.if \bpc == 8 + ushll v0.8h, v0.8b, #4 // u + ushll v4.8h, v4.8b, #4 // u +.else + shl v0.8h, v0.8h, #4 // u + shl v4.8h, v4.8h, #4 // u +.endif + sub v1.8h, v1.8h, v0.8h // t1 - u + sub v5.8h, v5.8h, v4.8h // t1 - u + ushll v2.4s, v0.4h, #7 // u << 7 + ushll2 v3.4s, v0.8h, #7 // u << 7 + ushll v6.4s, v4.4h, #7 // u << 7 + ushll2 v7.4s, v4.8h, #7 // u << 7 + smlal v2.4s, v1.4h, v31.4h // v + smlal2 v3.4s, v1.8h, v31.8h // v + smlal v6.4s, v5.4h, v31.4h // v + smlal2 v7.4s, v5.8h, v31.8h // v +.if \bpc == 8 + rshrn v2.4h, v2.4s, #11 + rshrn2 v2.8h, v3.4s, #11 + rshrn v6.4h, v6.4s, #11 + rshrn2 v6.8h, v7.4s, #11 + sqxtun v2.8b, v2.8h + sqxtun v6.8b, v6.8h + st1 {v2.8b}, [x0], #8 + st1 {v6.8b}, [x9], #8 +.else + sqrshrun v2.4h, v2.4s, #11 + sqrshrun2 v2.8h, v3.4s, #11 + sqrshrun v6.4h, v6.4s, #11 + sqrshrun2 v6.8h, v7.4s, #11 + umin v2.8h, v2.8h, v30.8h + umin v6.8h, v6.8h, v30.8h + st1 {v2.8h}, [x0], #16 + st1 {v6.8h}, [x9], #16 +.endif + b.gt 1b + + sub x6, x6, #2 + cmp x6, #1 + b.lt 0f + mov x5, x8 + add x0, x0, x1 + add x9, x9, x1 + add x2, x2, x3 + add x10, x10, x3 + add x4, x4, x7 + add x11, x11, x7 + b.eq 2f + b 1b + +2: +.if \bpc == 8 + ld1 {v0.8b}, [x2], #8 +.else + ld1 {v0.8h}, [x2], #16 +.endif + ld1 {v1.8h}, [x4], #16 + subs x5, x5, #8 +.if \bpc == 8 + ushll v0.8h, v0.8b, #4 // u +.else + shl v0.8h, v0.8h, #4 // u +.endif + sub v1.8h, v1.8h, v0.8h // t1 - u + ushll v2.4s, v0.4h, #7 // u << 7 + ushll2 v3.4s, v0.8h, #7 // u << 7 + smlal v2.4s, v1.4h, v31.4h // v + smlal2 v3.4s, v1.8h, v31.8h // v +.if \bpc == 8 + rshrn v2.4h, v2.4s, #11 + rshrn2 v2.8h, v3.4s, #11 + sqxtun v2.8b, v2.8h + st1 {v2.8b}, [x0], #8 +.else + sqrshrun v2.4h, v2.4s, #11 + sqrshrun2 v2.8h, v3.4s, #11 + umin v2.8h, v2.8h, v30.8h + st1 {v2.8h}, [x0], #16 +.endif + b.gt 2b +0: + ret +endfunc + +// void dav1d_sgr_weighted2_Xbpc_neon(pixel *dst, const ptrdiff_t stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *t1, const int16_t *t2, +// const int w, const int h, +// const int16_t wt[2], const int bitdepth_max); +function sgr_weighted2_\bpc\()bpc_neon, export=1 +.if \bpc == 8 + ldr x8, [sp] +.else + ldp x8, x9, [sp] +.endif + cmp x7, #2 + add x10, x0, x1 + add x11, x2, x3 + add x12, x4, #2*FILTER_OUT_STRIDE + add x13, x5, #2*FILTER_OUT_STRIDE + ld2r {v30.8h, v31.8h}, [x8] // wt[0], wt[1] +.if \bpc == 16 + dup v29.8h, w9 +.endif + mov x8, #4*FILTER_OUT_STRIDE + lsl x1, x1, #1 + lsl x3, x3, #1 + add x9, x6, #7 + bic x9, x9, #7 // Aligned width +.if \bpc == 8 + sub x1, x1, x9 + sub x3, x3, x9 +.else + sub x1, x1, x9, lsl #1 + sub x3, x3, x9, lsl #1 +.endif + sub x8, x8, x9, lsl #1 + mov x9, x6 + b.lt 2f +1: +.if \bpc == 8 + ld1 {v0.8b}, [x2], #8 + ld1 {v16.8b}, [x11], #8 +.else + ld1 {v0.8h}, [x2], #16 + ld1 {v16.8h}, [x11], #16 +.endif + ld1 {v1.8h}, [x4], #16 + ld1 {v17.8h}, [x12], #16 + ld1 {v2.8h}, [x5], #16 + ld1 {v18.8h}, [x13], #16 + subs x6, x6, #8 +.if \bpc == 8 + ushll v0.8h, v0.8b, #4 // u + ushll v16.8h, v16.8b, #4 // u +.else + shl v0.8h, v0.8h, #4 // u + shl v16.8h, v16.8h, #4 // u +.endif + sub v1.8h, v1.8h, v0.8h // t1 - u + sub v2.8h, v2.8h, v0.8h // t2 - u + sub v17.8h, v17.8h, v16.8h // t1 - u + sub v18.8h, v18.8h, v16.8h // t2 - u + ushll v3.4s, v0.4h, #7 // u << 7 + ushll2 v4.4s, v0.8h, #7 // u << 7 + ushll v19.4s, v16.4h, #7 // u << 7 + ushll2 v20.4s, v16.8h, #7 // u << 7 + smlal v3.4s, v1.4h, v30.4h // wt[0] * (t1 - u) + smlal v3.4s, v2.4h, v31.4h // wt[1] * (t2 - u) + smlal2 v4.4s, v1.8h, v30.8h // wt[0] * (t1 - u) + smlal2 v4.4s, v2.8h, v31.8h // wt[1] * (t2 - u) + smlal v19.4s, v17.4h, v30.4h // wt[0] * (t1 - u) + smlal v19.4s, v18.4h, v31.4h // wt[1] * (t2 - u) + smlal2 v20.4s, v17.8h, v30.8h // wt[0] * (t1 - u) + smlal2 v20.4s, v18.8h, v31.8h // wt[1] * (t2 - u) +.if \bpc == 8 + rshrn v3.4h, v3.4s, #11 + rshrn2 v3.8h, v4.4s, #11 + rshrn v19.4h, v19.4s, #11 + rshrn2 v19.8h, v20.4s, #11 + sqxtun v3.8b, v3.8h + sqxtun v19.8b, v19.8h + st1 {v3.8b}, [x0], #8 + st1 {v19.8b}, [x10], #8 +.else + sqrshrun v3.4h, v3.4s, #11 + sqrshrun2 v3.8h, v4.4s, #11 + sqrshrun v19.4h, v19.4s, #11 + sqrshrun2 v19.8h, v20.4s, #11 + umin v3.8h, v3.8h, v29.8h + umin v19.8h, v19.8h, v29.8h + st1 {v3.8h}, [x0], #16 + st1 {v19.8h}, [x10], #16 +.endif + b.gt 1b + + subs x7, x7, #2 + cmp x7, #1 + b.lt 0f + mov x6, x9 + add x0, x0, x1 + add x10, x10, x1 + add x2, x2, x3 + add x11, x11, x3 + add x4, x4, x8 + add x12, x12, x8 + add x5, x5, x8 + add x13, x13, x8 + b.eq 2f + b 1b + +2: +.if \bpc == 8 + ld1 {v0.8b}, [x2], #8 +.else + ld1 {v0.8h}, [x2], #16 +.endif + ld1 {v1.8h}, [x4], #16 + ld1 {v2.8h}, [x5], #16 + subs x6, x6, #8 +.if \bpc == 8 + ushll v0.8h, v0.8b, #4 // u +.else + shl v0.8h, v0.8h, #4 // u +.endif + sub v1.8h, v1.8h, v0.8h // t1 - u + sub v2.8h, v2.8h, v0.8h // t2 - u + ushll v3.4s, v0.4h, #7 // u << 7 + ushll2 v4.4s, v0.8h, #7 // u << 7 + smlal v3.4s, v1.4h, v30.4h // wt[0] * (t1 - u) + smlal v3.4s, v2.4h, v31.4h // wt[1] * (t2 - u) + smlal2 v4.4s, v1.8h, v30.8h // wt[0] * (t1 - u) + smlal2 v4.4s, v2.8h, v31.8h // wt[1] * (t2 - u) +.if \bpc == 8 + rshrn v3.4h, v3.4s, #11 + rshrn2 v3.8h, v4.4s, #11 + sqxtun v3.8b, v3.8h + st1 {v3.8b}, [x0], #8 +.else + sqrshrun v3.4h, v3.4s, #11 + sqrshrun2 v3.8h, v4.4s, #11 + umin v3.8h, v3.8h, v29.8h + st1 {v3.8h}, [x0], #16 +.endif + b.gt 1b +0: + ret +endfunc +.endm diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/mc.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/mc.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3310 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2018, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro avg dst, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + add \t0\().8h, \t0\().8h, \t2\().8h + add \t1\().8h, \t1\().8h, \t3\().8h + sqrshrun \dst\().8b, \t0\().8h, #5 + sqrshrun2 \dst\().16b, \t1\().8h, #5 +.endm + +.macro w_avg dst, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sub \t0\().8h, \t2\().8h, \t0\().8h + sub \t1\().8h, \t3\().8h, \t1\().8h + sqdmulh \t0\().8h, \t0\().8h, v30.8h + sqdmulh \t1\().8h, \t1\().8h, v30.8h + add \t0\().8h, \t2\().8h, \t0\().8h + add \t1\().8h, \t3\().8h, \t1\().8h + sqrshrun \dst\().8b, \t0\().8h, #4 + sqrshrun2 \dst\().16b, \t1\().8h, #4 +.endm + +.macro mask dst, t0, t1, t2, t3 + ld1 {v30.16b}, [x6], 16 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + mul v30.16b, v30.16b, v31.16b + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + shll v28.8h, v30.8b, #8 + shll2 v29.8h, v30.16b, #8 + sub \t0\().8h, \t2\().8h, \t0\().8h + sub \t1\().8h, \t3\().8h, \t1\().8h + sqdmulh \t0\().8h, \t0\().8h, v28.8h + sqdmulh \t1\().8h, \t1\().8h, v29.8h + add \t0\().8h, \t2\().8h, \t0\().8h + add \t1\().8h, \t3\().8h, \t1\().8h + sqrshrun \dst\().8b, \t0\().8h, #4 + sqrshrun2 \dst\().16b, \t1\().8h, #4 +.endm + +.macro bidir_fn type +function \type\()_8bpc_neon, export=1 + clz w4, w4 +.ifc \type, w_avg + dup v30.8h, w6 + neg v30.8h, v30.8h + shl v30.8h, v30.8h, #11 +.endif +.ifc \type, mask + movi v31.16b, #256-2 +.endif + adr x7, L(\type\()_tbl) + sub w4, w4, #24 + ldrh w4, [x7, x4, lsl #1] + \type v4, v0, v1, v2, v3 + sub x7, x7, w4, uxtw + br x7 +40: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +4: + cmp w5, #4 + st1 {v4.s}[0], [x0], x1 + st1 {v4.s}[1], [x7], x1 + st1 {v4.s}[2], [x0], x1 + st1 {v4.s}[3], [x7], x1 + b.eq 0f + \type v5, v0, v1, v2, v3 + cmp w5, #8 + st1 {v5.s}[0], [x0], x1 + st1 {v5.s}[1], [x7], x1 + st1 {v5.s}[2], [x0], x1 + st1 {v5.s}[3], [x7], x1 + b.eq 0f + \type v4, v0, v1, v2, v3 + st1 {v4.s}[0], [x0], x1 + st1 {v4.s}[1], [x7], x1 + \type v5, v0, v1, v2, v3 + st1 {v4.s}[2], [x0], x1 + st1 {v4.s}[3], [x7], x1 + st1 {v5.s}[0], [x0], x1 + st1 {v5.s}[1], [x7], x1 + st1 {v5.s}[2], [x0], x1 + st1 {v5.s}[3], [x7], x1 + ret +80: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +8: + st1 {v4.d}[0], [x0], x1 + \type v5, v0, v1, v2, v3 + st1 {v4.d}[1], [x7], x1 + st1 {v5.d}[0], [x0], x1 + subs w5, w5, #4 + st1 {v5.d}[1], [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 8b +16: + AARCH64_VALID_JUMP_TARGET + \type v5, v0, v1, v2, v3 + st1 {v4.16b}, [x0], x1 + \type v6, v0, v1, v2, v3 + st1 {v5.16b}, [x0], x1 + \type v7, v0, v1, v2, v3 + st1 {v6.16b}, [x0], x1 + subs w5, w5, #4 + st1 {v7.16b}, [x0], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 16b +320: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +32: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + st1 {v4.16b,v5.16b}, [x0], x1 + \type v7, v0, v1, v2, v3 + subs w5, w5, #2 + st1 {v6.16b,v7.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 32b +640: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +64: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + \type v7, v0, v1, v2, v3 + \type v16, v0, v1, v2, v3 + \type v17, v0, v1, v2, v3 + st1 {v4.16b,v5.16b,v6.16b,v7.16b}, [x0], x1 + \type v18, v0, v1, v2, v3 + \type v19, v0, v1, v2, v3 + subs w5, w5, #2 + st1 {v16.16b,v17.16b,v18.16b,v19.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 64b +1280: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 +128: + \type v5, v0, v1, v2, v3 + \type v6, v0, v1, v2, v3 + \type v7, v0, v1, v2, v3 + \type v16, v0, v1, v2, v3 + \type v17, v0, v1, v2, v3 + st1 {v4.16b,v5.16b,v6.16b,v7.16b}, [x0], x1 + \type v18, v0, v1, v2, v3 + \type v19, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v16.16b,v17.16b,v18.16b,v19.16b}, [x7], x1 + b.le 0f + \type v4, v0, v1, v2, v3 + b 128b +0: + ret +L(\type\()_tbl): + .hword L(\type\()_tbl) - 1280b + .hword L(\type\()_tbl) - 640b + .hword L(\type\()_tbl) - 320b + .hword L(\type\()_tbl) - 16b + .hword L(\type\()_tbl) - 80b + .hword L(\type\()_tbl) - 40b +endfunc +.endm + +bidir_fn avg +bidir_fn w_avg +bidir_fn mask + + +.macro w_mask_fn type +function w_mask_\type\()_8bpc_neon, export=1 + clz w8, w4 + adr x9, L(w_mask_\type\()_tbl) + sub w8, w8, #24 + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + mov w10, #6903 + dup v0.8h, w10 +.if \type == 444 + movi v1.16b, #64 +.elseif \type == 422 + dup v2.8b, w7 + movi v3.8b, #129 + sub v3.8b, v3.8b, v2.8b +.elseif \type == 420 + dup v2.8h, w7 + movi v3.8h, #1, lsl #8 + sub v3.8h, v3.8h, v2.8h +.endif + add x12, x0, x1 + lsl x1, x1, #1 + br x9 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 (four rows at once) + ld1 {v6.8h, v7.8h}, [x3], #32 // tmp2 (four rows at once) + subs w5, w5, #4 + sub v16.8h, v6.8h, v4.8h + sub v17.8h, v7.8h, v5.8h + sabd v18.8h, v4.8h, v6.8h + sabd v19.8h, v5.8h, v7.8h + uqsub v18.8h, v0.8h, v18.8h + uqsub v19.8h, v0.8h, v19.8h + ushr v18.8h, v18.8h, #8 + ushr v19.8h, v19.8h, #8 + shl v20.8h, v18.8h, #9 + shl v21.8h, v19.8h, #9 + sqdmulh v20.8h, v20.8h, v16.8h + sqdmulh v21.8h, v21.8h, v17.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v5.8h + sqrshrun v22.8b, v20.8h, #4 + sqrshrun v23.8b, v21.8h, #4 +.if \type == 444 + uzp1 v18.16b, v18.16b, v19.16b // Same as xtn, xtn2 + sub v18.16b, v1.16b, v18.16b + st1 {v18.16b}, [x6], #16 +.elseif \type == 422 + addp v18.8h, v18.8h, v19.8h + xtn v18.8b, v18.8h + uhsub v18.8b, v3.8b, v18.8b + st1 {v18.8b}, [x6], #8 +.elseif \type == 420 + trn1 v24.2d, v18.2d, v19.2d + trn2 v25.2d, v18.2d, v19.2d + add v24.8h, v24.8h, v25.8h + addp v18.8h, v24.8h, v24.8h + sub v18.4h, v3.4h, v18.4h + rshrn v18.8b, v18.8h, #2 + st1 {v18.s}[0], [x6], #4 +.endif + st1 {v22.s}[0], [x0], x1 + st1 {v22.s}[1], [x12], x1 + st1 {v23.s}[0], [x0], x1 + st1 {v23.s}[1], [x12], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 + ld1 {v6.8h, v7.8h}, [x3], #32 + subs w5, w5, #2 + sub v16.8h, v6.8h, v4.8h + sub v17.8h, v7.8h, v5.8h + sabd v18.8h, v4.8h, v6.8h + sabd v19.8h, v5.8h, v7.8h + uqsub v18.8h, v0.8h, v18.8h + uqsub v19.8h, v0.8h, v19.8h + ushr v18.8h, v18.8h, #8 + ushr v19.8h, v19.8h, #8 + shl v20.8h, v18.8h, #9 + shl v21.8h, v19.8h, #9 + sqdmulh v20.8h, v20.8h, v16.8h + sqdmulh v21.8h, v21.8h, v17.8h + add v20.8h, v20.8h, v4.8h + add v21.8h, v21.8h, v5.8h + sqrshrun v22.8b, v20.8h, #4 + sqrshrun v23.8b, v21.8h, #4 +.if \type == 444 + uzp1 v18.16b, v18.16b, v19.16b // Same as xtn, xtn2 + sub v18.16b, v1.16b, v18.16b + st1 {v18.16b}, [x6], #16 +.elseif \type == 422 + addp v18.8h, v18.8h, v19.8h + xtn v18.8b, v18.8h + uhsub v18.8b, v3.8b, v18.8b + st1 {v18.8b}, [x6], #8 +.elseif \type == 420 + add v18.8h, v18.8h, v19.8h + addp v18.8h, v18.8h, v18.8h + sub v18.4h, v3.4h, v18.4h + rshrn v18.8b, v18.8h, #2 + st1 {v18.s}[0], [x6], #4 +.endif + st1 {v22.8b}, [x0], x1 + st1 {v23.8b}, [x12], x1 + b.gt 8b + ret +1280: +640: +320: +160: + AARCH64_VALID_JUMP_TARGET + mov w11, w4 + sub x1, x1, w4, uxtw +.if \type == 444 + add x10, x6, w4, uxtw +.elseif \type == 422 + add x10, x6, x11, lsr #1 +.endif + add x9, x3, w4, uxtw #1 + add x7, x2, w4, uxtw #1 +161: + mov w8, w4 +16: + ld1 {v4.8h, v5.8h}, [x2], #32 + ld1 {v6.8h, v7.8h}, [x3], #32 + ld1 {v16.8h, v17.8h}, [x7], #32 + ld1 {v18.8h, v19.8h}, [x9], #32 + subs w8, w8, #16 + sub v6.8h, v6.8h, v4.8h + sub v7.8h, v7.8h, v5.8h + sub v18.8h, v18.8h, v16.8h + sub v19.8h, v19.8h, v17.8h + abs v20.8h, v6.8h + abs v21.8h, v7.8h + abs v22.8h, v18.8h + abs v23.8h, v19.8h + uqsub v20.8h, v0.8h, v20.8h + uqsub v21.8h, v0.8h, v21.8h + uqsub v22.8h, v0.8h, v22.8h + uqsub v23.8h, v0.8h, v23.8h + ushr v20.8h, v20.8h, #8 + ushr v21.8h, v21.8h, #8 + ushr v22.8h, v22.8h, #8 + ushr v23.8h, v23.8h, #8 + shl v24.8h, v20.8h, #9 + shl v25.8h, v21.8h, #9 + shl v26.8h, v22.8h, #9 + shl v27.8h, v23.8h, #9 + sqdmulh v24.8h, v24.8h, v6.8h + sqdmulh v25.8h, v25.8h, v7.8h + sqdmulh v26.8h, v26.8h, v18.8h + sqdmulh v27.8h, v27.8h, v19.8h + add v24.8h, v24.8h, v4.8h + add v25.8h, v25.8h, v5.8h + add v26.8h, v26.8h, v16.8h + add v27.8h, v27.8h, v17.8h + sqrshrun v24.8b, v24.8h, #4 + sqrshrun v25.8b, v25.8h, #4 + sqrshrun v26.8b, v26.8h, #4 + sqrshrun v27.8b, v27.8h, #4 +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // Same as xtn, xtn2 + uzp1 v21.16b, v22.16b, v23.16b // Ditto + sub v20.16b, v1.16b, v20.16b + sub v21.16b, v1.16b, v21.16b + st1 {v20.16b}, [x6], #16 + st1 {v21.16b}, [x10], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h + addp v21.8h, v22.8h, v23.8h + xtn v20.8b, v20.8h + xtn v21.8b, v21.8h + uhsub v20.8b, v3.8b, v20.8b + uhsub v21.8b, v3.8b, v21.8b + st1 {v20.8b}, [x6], #8 + st1 {v21.8b}, [x10], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v22.8h + add v21.8h, v21.8h, v23.8h + addp v20.8h, v20.8h, v21.8h + sub v20.8h, v3.8h, v20.8h + rshrn v20.8b, v20.8h, #2 + st1 {v20.8b}, [x6], #8 +.endif + st1 {v24.8b, v25.8b}, [x0], #16 + st1 {v26.8b, v27.8b}, [x12], #16 + b.gt 16b + subs w5, w5, #2 + add x2, x2, w4, uxtw #1 + add x3, x3, w4, uxtw #1 + add x7, x7, w4, uxtw #1 + add x9, x9, w4, uxtw #1 +.if \type == 444 + add x6, x6, w4, uxtw + add x10, x10, w4, uxtw +.elseif \type == 422 + add x6, x6, x11, lsr #1 + add x10, x10, x11, lsr #1 +.endif + add x0, x0, x1 + add x12, x12, x1 + b.gt 161b + ret +L(w_mask_\type\()_tbl): + .hword L(w_mask_\type\()_tbl) - 1280b + .hword L(w_mask_\type\()_tbl) - 640b + .hword L(w_mask_\type\()_tbl) - 320b + .hword L(w_mask_\type\()_tbl) - 160b + .hword L(w_mask_\type\()_tbl) - 8b + .hword L(w_mask_\type\()_tbl) - 4b +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + + +function blend_8bpc_neon, export=1 + adr x6, L(blend_tbl) + clz w3, w3 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + br x6 +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.8b}, [x5], #8 + ld1 {v1.d}[0], [x2], #8 + ld1 {v0.s}[0], [x0] + subs w4, w4, #2 + ld1 {v0.s}[1], [x8] + sub v3.8b, v4.8b, v2.8b + umull v5.8h, v1.8b, v2.8b + umlal v5.8h, v0.8b, v3.8b + rshrn v6.8b, v5.8h, #6 + st1 {v6.s}[0], [x0], x1 + st1 {v6.s}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v2.16b}, [x5], #16 + ld1 {v1.16b}, [x2], #16 + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + sub v3.16b, v4.16b, v2.16b + subs w4, w4, #2 + umull v5.8h, v1.8b, v2.8b + umlal v5.8h, v0.8b, v3.8b + umull2 v6.8h, v1.16b, v2.16b + umlal2 v6.8h, v0.16b, v3.16b + rshrn v7.8b, v5.8h, #6 + rshrn2 v7.16b, v6.8h, #6 + st1 {v7.d}[0], [x0], x1 + st1 {v7.d}[1], [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld1 {v1.16b, v2.16b}, [x5], #32 + ld1 {v5.16b, v6.16b}, [x2], #32 + ld1 {v0.16b}, [x0] + subs w4, w4, #2 + sub v7.16b, v4.16b, v1.16b + sub v20.16b, v4.16b, v2.16b + ld1 {v3.16b}, [x8] + umull v16.8h, v5.8b, v1.8b + umlal v16.8h, v0.8b, v7.8b + umull2 v17.8h, v5.16b, v1.16b + umlal2 v17.8h, v0.16b, v7.16b + umull v21.8h, v6.8b, v2.8b + umlal v21.8h, v3.8b, v20.8b + umull2 v22.8h, v6.16b, v2.16b + umlal2 v22.8h, v3.16b, v20.16b + rshrn v18.8b, v16.8h, #6 + rshrn2 v18.16b, v17.8h, #6 + rshrn v19.8b, v21.8h, #6 + rshrn2 v19.16b, v22.8h, #6 + st1 {v18.16b}, [x0], x1 + st1 {v19.16b}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x5], #64 + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], #64 + ld1 {v20.16b, v21.16b}, [x0] + subs w4, w4, #2 + ld1 {v22.16b, v23.16b}, [x8] + sub v5.16b, v4.16b, v0.16b + sub v6.16b, v4.16b, v1.16b + sub v30.16b, v4.16b, v2.16b + sub v31.16b, v4.16b, v3.16b + umull v24.8h, v16.8b, v0.8b + umlal v24.8h, v20.8b, v5.8b + umull2 v26.8h, v16.16b, v0.16b + umlal2 v26.8h, v20.16b, v5.16b + umull v28.8h, v17.8b, v1.8b + umlal v28.8h, v21.8b, v6.8b + umull2 v7.8h, v17.16b, v1.16b + umlal2 v7.8h, v21.16b, v6.16b + umull v27.8h, v18.8b, v2.8b + umlal v27.8h, v22.8b, v30.8b + umull2 v1.8h, v18.16b, v2.16b + umlal2 v1.8h, v22.16b, v30.16b + umull v29.8h, v19.8b, v3.8b + umlal v29.8h, v23.8b, v31.8b + umull2 v21.8h, v19.16b, v3.16b + umlal2 v21.8h, v23.16b, v31.16b + rshrn v24.8b, v24.8h, #6 + rshrn2 v24.16b, v26.8h, #6 + rshrn v25.8b, v28.8h, #6 + rshrn2 v25.16b, v7.8h, #6 + rshrn v27.8b, v27.8h, #6 + rshrn2 v27.16b, v1.8h, #6 + rshrn v28.8b, v29.8h, #6 + rshrn2 v28.16b, v21.8h, #6 + st1 {v24.16b, v25.16b}, [x0], x1 + st1 {v27.16b, v28.16b}, [x8], x1 + b.gt 32b + ret +L(blend_tbl): + .hword L(blend_tbl) - 32b + .hword L(blend_tbl) - 16b + .hword L(blend_tbl) - 8b + .hword L(blend_tbl) - 4b +endfunc + +function blend_h_8bpc_neon, export=1 + adr x6, L(blend_h_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w4, uxtw + sub w4, w4, w4, lsr #2 + clz w7, w3 + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + sub w7, w7, #24 + ldrh w7, [x6, x7, lsl #1] + sub x6, x6, w7, uxtw + br x6 +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.h}[0], [x5], #2 + ld1 {v1.s}[0], [x2], #4 + subs w4, w4, #2 + ld1 {v2.h}[0], [x0] + zip1 v0.8b, v0.8b, v0.8b + sub v3.8b, v4.8b, v0.8b + ld1 {v2.h}[1], [x8] + umull v5.8h, v1.8b, v0.8b + umlal v5.8h, v2.8b, v3.8b + rshrn v5.8b, v5.8h, #6 + st1 {v5.h}[0], [x0], x1 + st1 {v5.h}[1], [x8], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.8b, v1.8b}, [x5], #2 + ld1 {v2.8b}, [x2], #8 + subs w4, w4, #2 + ext v0.8b, v0.8b, v1.8b, #4 + ld1 {v3.s}[0], [x0] + sub v5.8b, v4.8b, v0.8b + ld1 {v3.s}[1], [x8] + umull v6.8h, v2.8b, v0.8b + umlal v6.8h, v3.8b, v5.8b + rshrn v6.8b, v6.8h, #6 + st1 {v6.s}[0], [x0], x1 + st1 {v6.s}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.16b, v1.16b}, [x5], #2 + ld1 {v2.16b}, [x2], #16 + ld1 {v3.d}[0], [x0] + ext v0.16b, v0.16b, v1.16b, #8 + sub v5.16b, v4.16b, v0.16b + ld1 {v3.d}[1], [x8] + subs w4, w4, #2 + umull v6.8h, v0.8b, v2.8b + umlal v6.8h, v3.8b, v5.8b + umull2 v7.8h, v0.16b, v2.16b + umlal2 v7.8h, v3.16b, v5.16b + rshrn v16.8b, v6.8h, #6 + rshrn2 v16.16b, v7.8h, #6 + st1 {v16.d}[0], [x0], x1 + st1 {v16.d}[1], [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld2r {v0.16b, v1.16b}, [x5], #2 + ld1 {v2.16b, v3.16b}, [x2], #32 + ld1 {v5.16b}, [x0] + sub v7.16b, v4.16b, v0.16b + sub v16.16b, v4.16b, v1.16b + ld1 {v6.16b}, [x8] + subs w4, w4, #2 + umull v17.8h, v0.8b, v2.8b + umlal v17.8h, v5.8b, v7.8b + umull2 v18.8h, v0.16b, v2.16b + umlal2 v18.8h, v5.16b, v7.16b + umull v19.8h, v1.8b, v3.8b + umlal v19.8h, v6.8b, v16.8b + umull2 v20.8h, v1.16b, v3.16b + umlal2 v20.8h, v6.16b, v16.16b + rshrn v21.8b, v17.8h, #6 + rshrn2 v21.16b, v18.8h, #6 + rshrn v22.8b, v19.8h, #6 + rshrn2 v22.16b, v20.8h, #6 + st1 {v21.16b}, [x0], x1 + st1 {v22.16b}, [x8], x1 + b.gt 16b + ret +1280: +640: +320: + AARCH64_VALID_JUMP_TARGET + sub x1, x1, w3, uxtw + add x7, x2, w3, uxtw +321: + ld2r {v0.16b, v1.16b}, [x5], #2 + mov w6, w3 + sub v20.16b, v4.16b, v0.16b + sub v21.16b, v4.16b, v1.16b +32: + ld1 {v16.16b, v17.16b}, [x2], #32 + ld1 {v2.16b, v3.16b}, [x0] + subs w6, w6, #32 + umull v23.8h, v0.8b, v16.8b + umlal v23.8h, v2.8b, v20.8b + ld1 {v18.16b, v19.16b}, [x7], #32 + umull2 v27.8h, v0.16b, v16.16b + umlal2 v27.8h, v2.16b, v20.16b + ld1 {v6.16b, v7.16b}, [x8] + umull v24.8h, v0.8b, v17.8b + umlal v24.8h, v3.8b, v20.8b + umull2 v28.8h, v0.16b, v17.16b + umlal2 v28.8h, v3.16b, v20.16b + umull v25.8h, v1.8b, v18.8b + umlal v25.8h, v6.8b, v21.8b + umull2 v5.8h, v1.16b, v18.16b + umlal2 v5.8h, v6.16b, v21.16b + rshrn v29.8b, v23.8h, #6 + rshrn2 v29.16b, v27.8h, #6 + umull v26.8h, v1.8b, v19.8b + umlal v26.8h, v7.8b, v21.8b + umull2 v31.8h, v1.16b, v19.16b + umlal2 v31.8h, v7.16b, v21.16b + rshrn v30.8b, v24.8h, #6 + rshrn2 v30.16b, v28.8h, #6 + rshrn v23.8b, v25.8h, #6 + rshrn2 v23.16b, v5.8h, #6 + rshrn v24.8b, v26.8h, #6 + st1 {v29.16b, v30.16b}, [x0], #32 + rshrn2 v24.16b, v31.8h, #6 + st1 {v23.16b, v24.16b}, [x8], #32 + b.gt 32b + subs w4, w4, #2 + add x0, x0, x1 + add x8, x8, x1 + add x2, x2, w3, uxtw + add x7, x7, w3, uxtw + b.gt 321b + ret +L(blend_h_tbl): + .hword L(blend_h_tbl) - 1280b + .hword L(blend_h_tbl) - 640b + .hword L(blend_h_tbl) - 320b + .hword L(blend_h_tbl) - 16b + .hword L(blend_h_tbl) - 8b + .hword L(blend_h_tbl) - 4b + .hword L(blend_h_tbl) - 2b +endfunc + +function blend_v_8bpc_neon, export=1 + adr x6, L(blend_v_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w3, uxtw + clz w3, w3 + movi v4.16b, #64 + add x8, x0, x1 + lsl x1, x1, #1 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + br x6 +20: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.8b}, [x5] + sub v1.8b, v4.8b, v0.8b +2: + ld1 {v2.h}[0], [x2], #2 + ld1 {v3.b}[0], [x0] + subs w4, w4, #2 + ld1 {v2.b}[1], [x2] + ld1 {v3.b}[1], [x8] + umull v5.8h, v2.8b, v0.8b + umlal v5.8h, v3.8b, v1.8b + rshrn v5.8b, v5.8h, #6 + add x2, x2, #2 + st1 {v5.b}[0], [x0], x1 + st1 {v5.b}[1], [x8], x1 + b.gt 2b + ret +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2s}, [x5] + sub x1, x1, #2 + sub v1.8b, v4.8b, v0.8b +4: + ld1 {v2.8b}, [x2], #8 + ld1 {v3.s}[0], [x0] + ld1 {v3.s}[1], [x8] + subs w4, w4, #2 + umull v5.8h, v2.8b, v0.8b + umlal v5.8h, v3.8b, v1.8b + rshrn v5.8b, v5.8h, #6 + st1 {v5.h}[0], [x0], #2 + st1 {v5.h}[2], [x8], #2 + st1 {v5.b}[2], [x0], x1 + st1 {v5.b}[6], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1r {v0.2d}, [x5] + sub x1, x1, #4 + sub v1.16b, v4.16b, v0.16b +8: + ld1 {v2.16b}, [x2], #16 + ld1 {v3.d}[0], [x0] + ld1 {v3.d}[1], [x8] + subs w4, w4, #2 + umull v5.8h, v0.8b, v2.8b + umlal v5.8h, v3.8b, v1.8b + umull2 v6.8h, v0.16b, v2.16b + umlal2 v6.8h, v3.16b, v1.16b + rshrn v7.8b, v5.8h, #6 + rshrn2 v7.16b, v6.8h, #6 + st1 {v7.s}[0], [x0], #4 + st1 {v7.s}[2], [x8], #4 + st1 {v7.h}[2], [x0], x1 + st1 {v7.h}[6], [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b}, [x5] + sub x1, x1, #8 + sub v2.16b, v4.16b, v0.16b +16: + ld1 {v5.16b, v6.16b}, [x2], #32 + ld1 {v7.16b}, [x0] + subs w4, w4, #2 + ld1 {v16.16b}, [x8] + umull v17.8h, v5.8b, v0.8b + umlal v17.8h, v7.8b, v2.8b + umull2 v18.8h, v5.16b, v0.16b + umlal2 v18.8h, v7.16b, v2.16b + umull v20.8h, v6.8b, v0.8b + umlal v20.8h, v16.8b, v2.8b + umull2 v21.8h, v6.16b, v0.16b + umlal2 v21.8h, v16.16b, v2.16b + rshrn v19.8b, v17.8h, #6 + rshrn2 v19.16b, v18.8h, #6 + rshrn v22.8b, v20.8h, #6 + rshrn2 v22.16b, v21.8h, #6 + st1 {v19.8b}, [x0], #8 + st1 {v22.8b}, [x8], #8 + st1 {v19.s}[2], [x0], x1 + st1 {v22.s}[2], [x8], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.16b, v1.16b}, [x5] + sub x1, x1, #16 + sub v2.16b, v4.16b, v0.16b + sub v3.8b, v4.8b, v1.8b +32: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], #64 + ld1 {v5.16b, v6.16b}, [x0] + subs w4, w4, #2 + ld1 {v20.16b, v21.16b}, [x8] + umull v22.8h, v16.8b, v0.8b + umlal v22.8h, v5.8b, v2.8b + umull2 v23.8h, v16.16b, v0.16b + umlal2 v23.8h, v5.16b, v2.16b + umull v28.8h, v17.8b, v1.8b + umlal v28.8h, v6.8b, v3.8b + umull v30.8h, v18.8b, v0.8b + umlal v30.8h, v20.8b, v2.8b + umull2 v31.8h, v18.16b, v0.16b + umlal2 v31.8h, v20.16b, v2.16b + umull v25.8h, v19.8b, v1.8b + umlal v25.8h, v21.8b, v3.8b + rshrn v24.8b, v22.8h, #6 + rshrn2 v24.16b, v23.8h, #6 + rshrn v28.8b, v28.8h, #6 + rshrn v30.8b, v30.8h, #6 + rshrn2 v30.16b, v31.8h, #6 + rshrn v27.8b, v25.8h, #6 + st1 {v24.16b}, [x0], #16 + st1 {v30.16b}, [x8], #16 + st1 {v28.8b}, [x0], x1 + st1 {v27.8b}, [x8], x1 + b.gt 32b + ret +L(blend_v_tbl): + .hword L(blend_v_tbl) - 320b + .hword L(blend_v_tbl) - 160b + .hword L(blend_v_tbl) - 80b + .hword L(blend_v_tbl) - 40b + .hword L(blend_v_tbl) - 20b +endfunc + + +// This has got the same signature as the put_8tap functions, +// and assumes that x8 is set to (clz(w)-24). +function put_neon + adr x9, L(put_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.h}[0], [x2], x3 + ld1 {v1.h}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.h}[0], [x0], x1 + st1 {v1.h}[0], [x0], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], x3 + ld1 {v1.s}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.s}[0], [x0], x1 + st1 {v1.s}[0], [x0], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x2], x3 + ld1 {v1.8b}, [x2], x3 + subs w5, w5, #2 + st1 {v0.8b}, [x0], x1 + st1 {v1.8b}, [x0], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x8, x0, x1 + lsl x1, x1, #1 + add x9, x2, x3 + lsl x3, x3, #1 +16: + ld1 {v0.16b}, [x2], x3 + ld1 {v1.16b}, [x9], x3 + subs w5, w5, #2 + st1 {v0.16b}, [x0], x1 + st1 {v1.16b}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + subs w5, w5, #1 + stp x8, x9, [x0, #16] + add x2, x2, x3 + add x0, x0, x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + ldp x10, x11, [x2, #32] + stp x8, x9, [x0, #16] + subs w5, w5, #1 + ldp x12, x13, [x2, #48] + stp x10, x11, [x0, #32] + stp x12, x13, [x0, #48] + add x2, x2, x3 + add x0, x0, x1 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x2, x2, x3 + add x0, x0, x1 + b.gt 128b + ret + +L(put_tbl): + .hword L(put_tbl) - 128b + .hword L(put_tbl) - 64b + .hword L(put_tbl) - 32b + .hword L(put_tbl) - 160b + .hword L(put_tbl) - 8b + .hword L(put_tbl) - 4b + .hword L(put_tbl) - 2b +endfunc + + +// This has got the same signature as the prep_8tap functions, +// and assumes that x8 is set to (clz(w)-24), and x7 to w*2. +function prep_neon + adr x9, L(prep_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x1], x2 + ld1 {v1.s}[0], [x1], x2 + subs w4, w4, #2 + ushll v0.8h, v0.8b, #4 + ushll v1.8h, v1.8b, #4 + st1 {v0.4h, v1.4h}, [x0], #16 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [x1], x2 + ld1 {v1.8b}, [x1], x2 + subs w4, w4, #2 + ushll v0.8h, v0.8b, #4 + ushll v1.8h, v1.8b, #4 + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +16: + ld1 {v0.16b}, [x1], x2 + ld1 {v1.16b}, [x9], x2 + subs w4, w4, #2 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], #64 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + add x8, x0, w3, uxtw +32: + ld1 {v0.16b, v1.16b}, [x1], x2 + subs w4, w4, #2 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ld1 {v2.16b, v3.16b}, [x1], x2 + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + ushll v16.8h, v2.8b, #4 + st1 {v4.8h, v5.8h}, [x0], x7 + ushll2 v17.8h, v2.16b, #4 + st1 {v6.8h, v7.8h}, [x8], x7 + ushll v18.8h, v3.8b, #4 + st1 {v16.8h, v17.8h}, [x0], x7 + ushll2 v19.8h, v3.16b, #4 + st1 {v18.8h, v19.8h}, [x8], x7 + b.gt 32b + ret +640: + AARCH64_VALID_JUMP_TARGET + add x8, x0, #32 + mov x6, #64 +64: + ldp q0, q1, [x1] + subs w4, w4, #1 + ushll v4.8h, v0.8b, #4 + ushll2 v5.8h, v0.16b, #4 + ldp q2, q3, [x1, #32] + ushll v6.8h, v1.8b, #4 + ushll2 v7.8h, v1.16b, #4 + add x1, x1, x2 + ushll v16.8h, v2.8b, #4 + st1 {v4.8h, v5.8h}, [x0], x6 + ushll2 v17.8h, v2.16b, #4 + ushll v18.8h, v3.8b, #4 + st1 {v6.8h, v7.8h}, [x8], x6 + ushll2 v19.8h, v3.16b, #4 + st1 {v16.8h, v17.8h}, [x0], x6 + st1 {v18.8h, v19.8h}, [x8], x6 + b.gt 64b + ret +1280: + AARCH64_VALID_JUMP_TARGET + add x8, x0, #64 + mov x6, #128 +128: + ldp q0, q1, [x1] + ldp q2, q3, [x1, #32] + ushll v16.8h, v0.8b, #4 + ushll2 v17.8h, v0.16b, #4 + ushll v18.8h, v1.8b, #4 + ushll2 v19.8h, v1.16b, #4 + ushll v20.8h, v2.8b, #4 + ushll2 v21.8h, v2.16b, #4 + ldp q4, q5, [x1, #64] + st1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x0], x6 + ushll v22.8h, v3.8b, #4 + ushll2 v23.8h, v3.16b, #4 + ushll v24.8h, v4.8b, #4 + ushll2 v25.8h, v4.16b, #4 + ushll v26.8h, v5.8b, #4 + ushll2 v27.8h, v5.16b, #4 + ldp q6, q7, [x1, #96] + st1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x8], x6 + ushll v28.8h, v6.8b, #4 + ushll2 v29.8h, v6.16b, #4 + ushll v30.8h, v7.8b, #4 + ushll2 v31.8h, v7.16b, #4 + subs w4, w4, #1 + add x1, x1, x2 + st1 {v24.8h, v25.8h, v26.8h, v27.8h}, [x0], x6 + st1 {v28.8h, v29.8h, v30.8h, v31.8h}, [x8], x6 + b.gt 128b + ret + +L(prep_tbl): + .hword L(prep_tbl) - 1280b + .hword L(prep_tbl) - 640b + .hword L(prep_tbl) - 320b + .hword L(prep_tbl) - 160b + .hword L(prep_tbl) - 8b + .hword L(prep_tbl) - 4b +endfunc + + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}[0], [\s0], \strd + ld1 {\d1\wd}[0], [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}[0], [\s0], \strd + ld1 {\d3\wd}[0], [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}[0], [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}[0], [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}[0], [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}, [\s0], \strd + ld1 {\d1\wd}, [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}, [\s0], \strd + ld1 {\d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}, [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}, [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}, [\s0], \strd +.endif +.endm +.macro load_h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_s s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .s, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_8b s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .8b, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_16b s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .16b, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro interleave_1 wd, r0, r1, r2, r3, r4 + trn1 \r0\wd, \r0\wd, \r1\wd + trn1 \r1\wd, \r1\wd, \r2\wd +.ifnb \r3 + trn1 \r2\wd, \r2\wd, \r3\wd + trn1 \r3\wd, \r3\wd, \r4\wd +.endif +.endm +.macro interleave_1_h r0, r1, r2, r3, r4 + interleave_1 .4h, \r0, \r1, \r2, \r3, \r4 +.endm +.macro interleave_1_s r0, r1, r2, r3, r4 + interleave_1 .2s, \r0, \r1, \r2, \r3, \r4 +.endm +.macro interleave_2 wd, r0, r1, r2, r3, r4, r5 + trn1 \r0\wd, \r0\wd, \r2\wd + trn1 \r1\wd, \r1\wd, \r3\wd + trn1 \r2\wd, \r2\wd, \r4\wd + trn1 \r3\wd, \r3\wd, \r5\wd +.endm +.macro interleave_2_s r0, r1, r2, r3, r4, r5 + interleave_2 .2s, \r0, \r1, \r2, \r3, \r4, \r5 +.endm +.macro uxtl_b r0, r1, r2, r3, r4, r5, r6 + uxtl \r0\().8h, \r0\().8b + uxtl \r1\().8h, \r1\().8b +.ifnb \r2 + uxtl \r2\().8h, \r2\().8b + uxtl \r3\().8h, \r3\().8b +.endif +.ifnb \r4 + uxtl \r4\().8h, \r4\().8b +.endif +.ifnb \r5 + uxtl \r5\().8h, \r5\().8b +.endif +.ifnb \r6 + uxtl \r6\().8h, \r6\().8b +.endif +.endm +.macro mul_mla_4 d, s0, s1, s2, s3, wd + mul \d\wd, \s0\wd, v0.h[0] + mla \d\wd, \s1\wd, v0.h[1] + mla \d\wd, \s2\wd, v0.h[2] + mla \d\wd, \s3\wd, v0.h[3] +.endm +// Interleaving the mul/mla chains actually hurts performance +// significantly on Cortex A53, thus keeping mul/mla tightly +// chained like this. +.macro mul_mla_8_0_4h d0, s0, s1, s2, s3, s4, s5, s6, s7 + mul \d0\().4h, \s0\().4h, v0.h[0] + mla \d0\().4h, \s1\().4h, v0.h[1] + mla \d0\().4h, \s2\().4h, v0.h[2] + mla \d0\().4h, \s3\().4h, v0.h[3] + mla \d0\().4h, \s4\().4h, v0.h[4] + mla \d0\().4h, \s5\().4h, v0.h[5] + mla \d0\().4h, \s6\().4h, v0.h[6] + mla \d0\().4h, \s7\().4h, v0.h[7] +.endm +.macro mul_mla_8_0 d0, s0, s1, s2, s3, s4, s5, s6, s7 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] +.endm +.macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] + mul \d1\().8h, \s1\().8h, v0.h[0] + mla \d1\().8h, \s2\().8h, v0.h[1] + mla \d1\().8h, \s3\().8h, v0.h[2] + mla \d1\().8h, \s4\().8h, v0.h[3] + mla \d1\().8h, \s5\().8h, v0.h[4] + mla \d1\().8h, \s6\().8h, v0.h[5] + mla \d1\().8h, \s7\().8h, v0.h[6] + mla \d1\().8h, \s8\().8h, v0.h[7] +.endm +.macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 + mul \d0\().8h, \s0\().8h, v0.h[0] + mla \d0\().8h, \s1\().8h, v0.h[1] + mla \d0\().8h, \s2\().8h, v0.h[2] + mla \d0\().8h, \s3\().8h, v0.h[3] + mla \d0\().8h, \s4\().8h, v0.h[4] + mla \d0\().8h, \s5\().8h, v0.h[5] + mla \d0\().8h, \s6\().8h, v0.h[6] + mla \d0\().8h, \s7\().8h, v0.h[7] + mul \d1\().8h, \s2\().8h, v0.h[0] + mla \d1\().8h, \s3\().8h, v0.h[1] + mla \d1\().8h, \s4\().8h, v0.h[2] + mla \d1\().8h, \s5\().8h, v0.h[3] + mla \d1\().8h, \s6\().8h, v0.h[4] + mla \d1\().8h, \s7\().8h, v0.h[5] + mla \d1\().8h, \s8\().8h, v0.h[6] + mla \d1\().8h, \s9\().8h, v0.h[7] +.endm +.macro sqrshrun_b shift, r0, r1, r2, r3 + sqrshrun \r0\().8b, \r0\().8h, #\shift +.ifnb \r1 + sqrshrun \r1\().8b, \r1\().8h, #\shift +.endif +.ifnb \r2 + sqrshrun \r2\().8b, \r2\().8h, #\shift + sqrshrun \r3\().8b, \r3\().8h, #\shift +.endif +.endm +.macro srshr_h shift, r0, r1, r2, r3 + srshr \r0\().8h, \r0\().8h, #\shift +.ifnb \r1 + srshr \r1\().8h, \r1\().8h, #\shift +.endif +.ifnb \r2 + srshr \r2\().8h, \r2\().8h, #\shift + srshr \r3\().8h, \r3\().8h, #\shift +.endif +.endm +.macro st_h strd, reg, lanes + st1 {\reg\().h}[0], [x0], \strd + st1 {\reg\().h}[1], [x8], \strd +.if \lanes > 2 + st1 {\reg\().h}[2], [x0], \strd + st1 {\reg\().h}[3], [x8], \strd +.endif +.endm +.macro st_s strd, r0, r1 + st1 {\r0\().s}[0], [x0], \strd + st1 {\r0\().s}[1], [x8], \strd +.ifnb \r1 + st1 {\r1\().s}[0], [x0], \strd + st1 {\r1\().s}[1], [x8], \strd +.endif +.endm +.macro st_d strd, r0, r1 + st1 {\r0\().d}[0], [x0], \strd + st1 {\r0\().d}[1], [x8], \strd +.ifnb \r1 + st1 {\r1\().d}[0], [x0], \strd + st1 {\r1\().d}[1], [x8], \strd +.endif +.endm +.macro shift_store_4 type, strd, r0, r1 +.ifc \type, put + sqrshrun_b 6, \r0, \r1 + st_s \strd, \r0, \r1 +.else + srshr_h 2, \r0, \r1 + st_d \strd, \r0, \r1 +.endif +.endm +.macro st_reg strd, wd, r0, r1, r2, r3, r4, r5, r6, r7 + st1 {\r0\wd}, [x0], \strd + st1 {\r1\wd}, [x8], \strd +.ifnb \r2 + st1 {\r2\wd}, [x0], \strd + st1 {\r3\wd}, [x8], \strd +.endif +.ifnb \r4 + st1 {\r4\wd}, [x0], \strd + st1 {\r5\wd}, [x8], \strd + st1 {\r6\wd}, [x0], \strd + st1 {\r7\wd}, [x8], \strd +.endif +.endm +.macro st_8b strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .8b, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro st_16b strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .16b, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro shift_store_8 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_b 6, \r0, \r1, \r2, \r3 + st_8b \strd, \r0, \r1, \r2, \r3 +.else + srshr_h 2, \r0, \r1, \r2, \r3 + st_16b \strd, \r0, \r1, \r2, \r3 +.endif +.endm +.macro shift_store_16 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun \r0\().8b, \r0\().8h, #6 + sqrshrun2 \r0\().16b, \r1\().8h, #6 + sqrshrun \r2\().8b, \r2\().8h, #6 + sqrshrun2 \r2\().16b, \r3\().8h, #6 + st_16b \strd, \r0, \r2 +.else + srshr_h 2, \r0, \r1, \r2, \r3 + st1 {\r0\().8h, \r1\().8h}, [x0], \strd + st1 {\r2\().8h, \r3\().8h}, [x8], \strd +.endif +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_8bpc_neon, export=1 + mov x8, \type_h + mov x9, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, xmx, my, xmy, ds2, sr2, shift_hv +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon + mov w10, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, w10 + mul \my, \my, w10 + add \mx, \mx, w8 // mx, 8tap_h, 4tap_h + add \my, \my, w9 // my, 8tap_v, 4tap_v +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz w8, \w + tst \mx, #(0x7f << 14) + sub w8, w8, #24 + movrel x10, X(mc_subpel_filters), -8 + b.ne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + b.ne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx w9, \mx, #7, #7 + and \mx, \mx, #0x7f + b.le 4f + mov \mx, w9 +4: + tst \my, #(0x7f << 14) + add \xmx, x10, \mx, uxtw #3 + b.ne L(\type\()_8tap_hv) + + adr x9, L(\type\()_8tap_h_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +2: + ld1 {v4.8b}, [\src], \s_strd + ld1 {v6.8b}, [\sr2], \s_strd + uxtl v4.8h, v4.8b + uxtl v6.8h, v6.8b + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + subs \h, \h, #2 + trn1 v3.2s, v4.2s, v6.2s + trn2 v6.2s, v4.2s, v6.2s + trn1 v4.2s, v5.2s, v7.2s + trn2 v7.2s, v5.2s, v7.2s + mul v3.4h, v3.4h, v0.h[0] + mla v3.4h, v4.4h, v0.h[1] + mla v3.4h, v6.4h, v0.h[2] + mla v3.4h, v7.4h, v0.h[3] + srshr v3.4h, v3.4h, #2 + sqrshrun v3.8b, v3.8h, #4 + st1 {v3.h}[0], [\dst], \d_strd + st1 {v3.h}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #1 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +4: + ld1 {v16.8b}, [\src], \s_strd + ld1 {v20.8b}, [\sr2], \s_strd + uxtl v16.8h, v16.8b + uxtl v20.8h, v20.8b + ext v17.16b, v16.16b, v16.16b, #2 + ext v18.16b, v16.16b, v16.16b, #4 + ext v19.16b, v16.16b, v16.16b, #6 + ext v21.16b, v20.16b, v20.16b, #2 + ext v22.16b, v20.16b, v20.16b, #4 + ext v23.16b, v20.16b, v20.16b, #6 + subs \h, \h, #2 + mul v16.4h, v16.4h, v0.h[0] + mla v16.4h, v17.4h, v0.h[1] + mla v16.4h, v18.4h, v0.h[2] + mla v16.4h, v19.4h, v0.h[3] + mul v20.4h, v20.4h, v0.h[0] + mla v20.4h, v21.4h, v0.h[1] + mla v20.4h, v22.4h, v0.h[2] + mla v20.4h, v23.4h, v0.h[3] + srshr v16.4h, v16.4h, #2 + srshr v20.4h, v20.4h, #2 +.ifc \type, put + sqrshrun v16.8b, v16.8h, #4 + sqrshrun v20.8b, v20.8h, #4 + st1 {v16.s}[0], [\dst], \d_strd + st1 {v20.s}[0], [\ds2], \d_strd +.else + st1 {v16.4h}, [\dst], \d_strd + st1 {v20.4h}, [\ds2], \d_strd +.endif + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +8: + ld1 {v16.8b, v17.8b}, [\src], \s_strd + ld1 {v20.8b, v21.8b}, [\sr2], \s_strd + uxtl v16.8h, v16.8b + uxtl v17.8h, v17.8b + uxtl v20.8h, v20.8b + uxtl v21.8h, v21.8b + + mul v18.8h, v16.8h, v0.h[0] + mul v22.8h, v20.8h, v0.h[0] +.irpc i, 1234567 + ext v19.16b, v16.16b, v17.16b, #(2*\i) + ext v23.16b, v20.16b, v21.16b, #(2*\i) + mla v18.8h, v19.8h, v0.h[\i] + mla v22.8h, v23.8h, v0.h[\i] +.endr + subs \h, \h, #2 + srshr v18.8h, v18.8h, #2 + srshr v22.8h, v22.8h, #2 +.ifc \type, put + sqrshrun v18.8b, v18.8h, #4 + sqrshrun v22.8b, v22.8h, #4 + st1 {v18.8b}, [\dst], \d_strd + st1 {v22.8b}, [\ds2], \d_strd +.else + st1 {v18.8h}, [\dst], \d_strd + st1 {v22.8h}, [\ds2], \d_strd +.endif + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #3 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + sub \s_strd, \s_strd, \w, uxtw + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw +.endif +161: + ld1 {v16.8b, v17.8b, v18.8b}, [\src], #24 + ld1 {v20.8b, v21.8b, v22.8b}, [\sr2], #24 + mov \mx, \w + uxtl v16.8h, v16.8b + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v20.8h, v20.8b + uxtl v21.8h, v21.8b + uxtl v22.8h, v22.8b + +16: + mul v24.8h, v16.8h, v0.h[0] + mul v25.8h, v17.8h, v0.h[0] + mul v26.8h, v20.8h, v0.h[0] + mul v27.8h, v21.8h, v0.h[0] +.irpc i, 1234567 + ext v28.16b, v16.16b, v17.16b, #(2*\i) + ext v29.16b, v17.16b, v18.16b, #(2*\i) + ext v30.16b, v20.16b, v21.16b, #(2*\i) + ext v31.16b, v21.16b, v22.16b, #(2*\i) + mla v24.8h, v28.8h, v0.h[\i] + mla v25.8h, v29.8h, v0.h[\i] + mla v26.8h, v30.8h, v0.h[\i] + mla v27.8h, v31.8h, v0.h[\i] +.endr + srshr v24.8h, v24.8h, #2 + srshr v25.8h, v25.8h, #2 + srshr v26.8h, v26.8h, #2 + srshr v27.8h, v27.8h, #2 + subs \mx, \mx, #16 +.ifc \type, put + sqrshrun v24.8b, v24.8h, #4 + sqrshrun2 v24.16b, v25.8h, #4 + sqrshrun v26.8b, v26.8h, #4 + sqrshrun2 v26.16b, v27.8h, #4 + st1 {v24.16b}, [\dst], #16 + st1 {v26.16b}, [\ds2], #16 +.else + st1 {v24.8h, v25.8h}, [\dst], #32 + st1 {v26.8h, v27.8h}, [\ds2], #32 +.endif + b.le 9f + + mov v16.16b, v18.16b + mov v20.16b, v22.16b + ld1 {v17.8b, v18.8b}, [\src], #16 + ld1 {v21.8b, v22.8b}, [\sr2], #16 + uxtl v17.8h, v17.8b + uxtl v18.8h, v18.8b + uxtl v21.8h, v21.8b + uxtl v22.8h, v22.8b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_8tap_h_tbl): + .hword L(\type\()_8tap_h_tbl) - 1280b + .hword L(\type\()_8tap_h_tbl) - 640b + .hword L(\type\()_8tap_h_tbl) - 320b + .hword L(\type\()_8tap_h_tbl) - 160b + .hword L(\type\()_8tap_h_tbl) - 80b + .hword L(\type\()_8tap_h_tbl) - 40b + .hword L(\type\()_8tap_h_tbl) - 20b + .hword 0 + + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx w9, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w9 +4: + add \xmy, x10, \my, uxtw #3 + + adr x9, L(\type\()_8tap_v_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + b.gt 28f + + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + // 2x2 v + load_h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_h v1, v2, v3, v4, v5 + b.gt 24f + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .4h + sqrshrun_b 6, v6 + st_h \d_strd, v6, 2 + ret + +24: // 2x4 v + load_h \sr2, \src, \s_strd, v6, v7 + interleave_1_h v5, v6, v7 + interleave_2_s v1, v2, v3, v4, v5, v6 + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .8h + sqrshrun_b 6, v6 + st_h \d_strd, v6, 4 + ret + +28: // 2x6, 2x8, 2x12, 2x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + load_h \src, \sr2, \s_strd, v1, v2, v3, v4, v5, v6, v7 + interleave_1_h v1, v2, v3, v4, v5 + interleave_1_h v5, v6, v7 + interleave_2_s v1, v2, v3, v4, v5, v6 + uxtl_b v1, v2, v3, v4 +216: + subs \h, \h, #4 + load_h \sr2, \src, \s_strd, v16, v17, v18, v19 + interleave_1_h v7, v16, v17, v18, v19 + interleave_2_s v5, v6, v7, v16, v17, v18 + uxtl_b v5, v6, v7, v16 + mul_mla_8_0 v30, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_b 6, v30 + st_h \d_strd, v30, 4 + b.le 0f + cmp \h, #2 + mov v1.16b, v5.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + mov v4.16b, v16.16b + mov v5.16b, v17.16b + mov v6.16b, v18.16b + mov v7.16b, v19.16b + b.eq 26f + b 216b +26: + load_h \sr2, \src, \s_strd, v16, v17 + interleave_1_h v7, v16, v17 + uxtl_b v5, v6, v7, v16 + mul_mla_8_0_4h v30, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_b 6, v30 + st_h \d_strd, v30, 2 +0: + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + b.gt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_s v1, v2, v3, v4, v5 + uxtl_b v1, v2, v3, v4 + mul_mla_4 v6, v1, v2, v3, v4, .8h + shift_store_4 \type, \d_strd, v6 + b.le 0f + load_s \sr2, \src, \s_strd, v6, v7 + interleave_1_s v5, v6, v7 + uxtl_b v5, v6 + mul_mla_4 v7, v3, v4, v5, v6, .8h + shift_store_4 \type, \d_strd, v7 +0: + ret + +480: // 4x6, 4x8, 4x12, 4x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + interleave_1_s v16, v17, v18 + interleave_1_s v18, v19, v20, v21, v22 + uxtl_b v16, v17 + uxtl_b v18, v19, v20, v21 + +48: + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v23, v24, v25, v26 + interleave_1_s v22, v23, v24, v25, v26 + uxtl_b v22, v23, v24, v25 + mul_mla_8_2 v1, v2, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 + shift_store_4 \type, \d_strd, v1, v2 + b.le 0f + load_s \sr2, \src, \s_strd, v27, v16 + subs \h, \h, #2 + interleave_1_s v26, v27, v16 + uxtl_b v26, v27 + mul_mla_8_0 v1, v20, v21, v22, v23, v24, v25, v26, v27 + shift_store_4 \type, \d_strd, v1 + b.le 0f + load_s \sr2, \src, \s_strd, v17, v18 + subs \h, \h, #2 + interleave_1_s v16, v17, v18 + uxtl_b v16, v17 + mul_mla_8_0 v2, v22, v23, v24, v25, v26, v27, v16, v17 + shift_store_4 \type, \d_strd, v2 + b.le 0f + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v19, v20, v21, v22 + interleave_1_s v18, v19, v20, v21, v22 + uxtl_b v18, v19, v20, v21 + mul_mla_8_2 v1, v2, v24, v25, v26, v27, v16, v17, v18, v19, v20, v21 + shift_store_4 \type, \d_strd, v1, v2 + b.gt 48b +0: + ret + +80: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_8b \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + uxtl_b v1, v2, v3, v4, v5 + mul_mla_4 v6, v1, v2, v3, v4, .8h + mul_mla_4 v7, v2, v3, v4, v5, .8h + shift_store_8 \type, \d_strd, v6, v7 + b.le 0f + load_8b \sr2, \src, \s_strd, v6, v7 + uxtl_b v6, v7 + mul_mla_4 v1, v3, v4, v5, v6, .8h + mul_mla_4 v2, v4, v5, v6, v7, .8h + shift_store_8 \type, \d_strd, v1, v2 +0: + ret + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmy] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_8b \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + uxtl_b v16, v17, v18, v19, v20, v21, v22 + +88: + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v23, v24 + uxtl_b v23, v24 + mul_mla_8_1 v1, v2, v16, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_8 \type, \d_strd, v1, v2 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v25, v26 + uxtl_b v25, v26 + mul_mla_8_1 v3, v4, v18, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_8 \type, \d_strd, v3, v4 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v27, v16 + uxtl_b v27, v16 + mul_mla_8_1 v1, v2, v20, v21, v22, v23, v24, v25, v26, v27, v16 + shift_store_8 \type, \d_strd, v1, v2 + b.le 9f + subs \h, \h, #2 + load_8b \sr2, \src, \s_strd, v17, v18 + uxtl_b v17, v18 + mul_mla_8_1 v3, v4, v22, v23, v24, v25, v26, v27, v16, v17, v18 + shift_store_8 \type, \d_strd, v3, v4 + b.le 9f + subs \h, \h, #4 + load_8b \sr2, \src, \s_strd, v19, v20, v21, v22 + uxtl_b v19, v20, v21, v22 + mul_mla_8_1 v1, v2, v24, v25, v26, v27, v16, v17, v18, v19, v20 + mul_mla_8_1 v3, v4, v26, v27, v16, v17, v18, v19, v20, v21, v22 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.gt 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + ret + +160: + AARCH64_VALID_JUMP_TARGET + b.gt 1680b + + // 16x2, 16x4 v + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + cmp \h, #2 + load_16b \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + uxtl v16.8h, v1.8b + uxtl v17.8h, v2.8b + uxtl v18.8h, v3.8b + uxtl v19.8h, v4.8b + uxtl v20.8h, v5.8b + uxtl2 v23.8h, v1.16b + uxtl2 v24.8h, v2.16b + uxtl2 v25.8h, v3.16b + uxtl2 v26.8h, v4.16b + uxtl2 v27.8h, v5.16b + mul_mla_4 v1, v16, v17, v18, v19, .8h + mul_mla_4 v16, v17, v18, v19, v20, .8h + mul_mla_4 v2, v23, v24, v25, v26, .8h + mul_mla_4 v17, v24, v25, v26, v27, .8h + shift_store_16 \type, \d_strd, v1, v2, v16, v17 + b.le 0f + load_16b \sr2, \src, \s_strd, v6, v7 + uxtl v21.8h, v6.8b + uxtl v22.8h, v7.8b + uxtl2 v28.8h, v6.16b + uxtl2 v29.8h, v7.16b + mul_mla_4 v1, v18, v19, v20, v21, .8h + mul_mla_4 v3, v19, v20, v21, v22, .8h + mul_mla_4 v2, v25, v26, v27, v28, .8h + mul_mla_4 v4, v26, v27, v28, v29, .8h + shift_store_16 \type, \d_strd, v1, v2, v3, v4 +0: + ret + +L(\type\()_8tap_v_tbl): + .hword L(\type\()_8tap_v_tbl) - 1280b + .hword L(\type\()_8tap_v_tbl) - 640b + .hword L(\type\()_8tap_v_tbl) - 320b + .hword L(\type\()_8tap_v_tbl) - 160b + .hword L(\type\()_8tap_v_tbl) - 80b + .hword L(\type\()_8tap_v_tbl) - 40b + .hword L(\type\()_8tap_v_tbl) - 20b + .hword 0 + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx w9, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w9 +4: + add \xmy, x10, \my, uxtw #3 + + adr x9, L(\type\()_8tap_hv_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 280f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + + // 2x2, 2x4 hv + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v28.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + ext v29.16b, v28.16b, v28.16b, #2 + mul v28.4h, v28.4h, v0.4h + mul v29.4h, v29.4h, v0.4h + addp v28.4h, v28.4h, v29.4h + addp v16.4h, v28.4h, v28.4h + srshr v16.4h, v16.4h, #2 + bl L(\type\()_8tap_filter_2) + + trn1 v16.2s, v16.2s, v28.2s + mov v17.8b, v28.8b + +2: + bl L(\type\()_8tap_filter_2) + + ext v18.8b, v17.8b, v28.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v28.4h, v1.h[3] + + sqrshrn v2.4h, v2.4s, #\shift_hv + sqxtun v2.8b, v2.8h + subs \h, \h, #2 + st1 {v2.h}[0], [\dst], \d_strd + st1 {v2.h}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v28.8b + b 2b + +280: // 2x8, 2x16, 2x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v28.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + ext v29.16b, v28.16b, v28.16b, #2 + mul v28.4h, v28.4h, v0.4h + mul v29.4h, v29.4h, v0.4h + addp v28.4h, v28.4h, v29.4h + addp v16.4h, v28.4h, v28.4h + srshr v16.4h, v16.4h, #2 + + bl L(\type\()_8tap_filter_2) + trn1 v16.2s, v16.2s, v28.2s + mov v17.8b, v28.8b + bl L(\type\()_8tap_filter_2) + ext v18.8b, v17.8b, v28.8b, #4 + mov v19.8b, v28.8b + bl L(\type\()_8tap_filter_2) + ext v20.8b, v19.8b, v28.8b, #4 + mov v21.8b, v28.8b + +28: + bl L(\type\()_8tap_filter_2) + ext v22.8b, v21.8b, v28.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal v2.4s, v28.4h, v1.h[7] + + sqrshrn v2.4h, v2.4s, #\shift_hv + sqxtun v2.8b, v2.8h + subs \h, \h, #2 + st1 {v2.h}[0], [\dst], \d_strd + st1 {v2.h}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v28.8b + b 28b + +0: + ret x15 + +L(\type\()_8tap_filter_2): + ld1 {v28.8b}, [\sr2], \s_strd + ld1 {v30.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v30.8h, v30.8b + ext v29.16b, v28.16b, v28.16b, #2 + ext v31.16b, v30.16b, v30.16b, #2 + trn1 v27.2s, v28.2s, v30.2s + trn2 v30.2s, v28.2s, v30.2s + trn1 v28.2s, v29.2s, v31.2s + trn2 v31.2s, v29.2s, v31.2s + mul v27.4h, v27.4h, v0.h[0] + mla v27.4h, v28.4h, v0.h[1] + mla v27.4h, v30.4h, v0.h[2] + mla v27.4h, v31.4h, v0.h[3] + srshr v28.4h, v27.4h, #2 + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 480f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + sub \sr2, \src, #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + // 4x2, 4x4 hv + ld1 {v26.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + srshr v16.4h, v31.4h, #2 + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v28.8b + mov v18.8b, v29.8b + +4: + bl L(\type\()_8tap_filter_4) + // Interleaving the mul/mla chains actually hurts performance + // significantly on Cortex A53, thus keeping mul/mla tightly + // chained like this. + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v28.4h, v1.h[3] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v28.4h, v1.h[2] + smlal v3.4s, v29.4h, v1.h[3] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn v3.4h, v3.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [\dst], \d_strd + st1 {v3.s}[0], [\ds2], \d_strd +.else + st1 {v2.4h}, [\dst], \d_strd + st1 {v3.4h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v28.8b + mov v18.8b, v29.8b + b 4b + +480: // 4x8, 4x16, 4x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #1 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v26.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + srshr v16.4h, v31.4h, #2 + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v28.8b + mov v18.8b, v29.8b + bl L(\type\()_8tap_filter_4) + mov v19.8b, v28.8b + mov v20.8b, v29.8b + bl L(\type\()_8tap_filter_4) + mov v21.8b, v28.8b + mov v22.8b, v29.8b + +48: + bl L(\type\()_8tap_filter_4) + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal v2.4s, v28.4h, v1.h[7] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v19.4h, v1.h[2] + smlal v3.4s, v20.4h, v1.h[3] + smlal v3.4s, v21.4h, v1.h[4] + smlal v3.4s, v22.4h, v1.h[5] + smlal v3.4s, v28.4h, v1.h[6] + smlal v3.4s, v29.4h, v1.h[7] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn v3.4h, v3.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v2.s}[0], [\dst], \d_strd + st1 {v3.s}[0], [\ds2], \d_strd +.else + st1 {v2.4h}, [\dst], \d_strd + st1 {v3.4h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v28.8b + mov v22.8b, v29.8b + b 48b +0: + ret x15 + +L(\type\()_8tap_filter_4): + ld1 {v26.8b}, [\sr2], \s_strd + ld1 {v27.8b}, [\src], \s_strd + uxtl v26.8h, v26.8b + uxtl v27.8h, v27.8b + ext v28.16b, v26.16b, v26.16b, #2 + ext v29.16b, v26.16b, v26.16b, #4 + ext v30.16b, v26.16b, v26.16b, #6 + mul v31.4h, v26.4h, v0.h[0] + mla v31.4h, v28.4h, v0.h[1] + mla v31.4h, v29.4h, v0.h[2] + mla v31.4h, v30.4h, v0.h[3] + ext v28.16b, v27.16b, v27.16b, #2 + ext v29.16b, v27.16b, v27.16b, #4 + ext v30.16b, v27.16b, v27.16b, #6 + mul v27.4h, v27.4h, v0.h[0] + mla v27.4h, v28.4h, v0.h[1] + mla v27.4h, v29.4h, v0.h[2] + mla v27.4h, v30.4h, v0.h[3] + srshr v28.4h, v31.4h, #2 + srshr v29.4h, v27.4h, #2 + ret + +80: +160: +320: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + add \xmy, \xmy, #2 + ld1 {v0.8b}, [\xmx] + ld1 {v1.s}[0], [\xmy] + sub \src, \src, #3 + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + bl L(\type\()_8tap_filter_8_first) + bl L(\type\()_8tap_filter_8) + mov v17.16b, v24.16b + mov v18.16b, v25.16b + +8: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v24.4h, v1.h[2] + smlal2 v5.4s, v24.8h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + smlal2 v3.4s, v24.8h, v1.h[3] + smlal v4.4s, v25.4h, v1.h[3] + smlal2 v5.4s, v25.8h, v1.h[3] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn2 v2.8h, v3.4s, #\shift_hv + sqrshrn v4.4h, v4.4s, #\shift_hv + sqrshrn2 v4.8h, v5.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v4.8b, v4.8h + st1 {v2.8b}, [\dst], \d_strd + st1 {v4.8b}, [\ds2], \d_strd +.else + st1 {v2.8h}, [\dst], \d_strd + st1 {v4.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v24.16b + mov v18.16b, v25.16b + b 8b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 164b + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + ld1 {v1.8b}, [\xmy] + sub \src, \src, #3 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + bl L(\type\()_8tap_filter_8_first) + bl L(\type\()_8tap_filter_8) + mov v17.16b, v24.16b + mov v18.16b, v25.16b + bl L(\type\()_8tap_filter_8) + mov v19.16b, v24.16b + mov v20.16b, v25.16b + bl L(\type\()_8tap_filter_8) + mov v21.16b, v24.16b + mov v22.16b, v25.16b + +88: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v19.4h, v1.h[2] + smlal2 v5.4s, v19.8h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal2 v3.4s, v19.8h, v1.h[3] + smlal v4.4s, v20.4h, v1.h[3] + smlal2 v5.4s, v20.8h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal2 v3.4s, v20.8h, v1.h[4] + smlal v4.4s, v21.4h, v1.h[4] + smlal2 v5.4s, v21.8h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal2 v3.4s, v21.8h, v1.h[5] + smlal v4.4s, v22.4h, v1.h[5] + smlal2 v5.4s, v22.8h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal2 v3.4s, v22.8h, v1.h[6] + smlal v4.4s, v24.4h, v1.h[6] + smlal2 v5.4s, v24.8h, v1.h[6] + smlal v2.4s, v24.4h, v1.h[7] + smlal2 v3.4s, v24.8h, v1.h[7] + smlal v4.4s, v25.4h, v1.h[7] + smlal2 v5.4s, v25.8h, v1.h[7] + sqrshrn v2.4h, v2.4s, #\shift_hv + sqrshrn2 v2.8h, v3.4s, #\shift_hv + sqrshrn v4.4h, v4.4s, #\shift_hv + sqrshrn2 v4.8h, v5.4s, #\shift_hv + subs \h, \h, #2 +.ifc \type, put + sqxtun v2.8b, v2.8h + sqxtun v4.8b, v4.8h + st1 {v2.8b}, [\dst], \d_strd + st1 {v4.8b}, [\ds2], \d_strd +.else + st1 {v2.8h}, [\dst], \d_strd + st1 {v4.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v24.16b + mov v22.16b, v25.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 168b +0: + ret x15 + +L(\type\()_8tap_filter_8_first): + ld1 {v28.8b, v29.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v29.8h, v29.8b + mul v16.8h, v28.8h, v0.h[0] + ext v24.16b, v28.16b, v29.16b, #(2*1) + ext v25.16b, v28.16b, v29.16b, #(2*2) + ext v26.16b, v28.16b, v29.16b, #(2*3) + ext v27.16b, v28.16b, v29.16b, #(2*4) + mla v16.8h, v24.8h, v0.h[1] + mla v16.8h, v25.8h, v0.h[2] + mla v16.8h, v26.8h, v0.h[3] + mla v16.8h, v27.8h, v0.h[4] + ext v24.16b, v28.16b, v29.16b, #(2*5) + ext v25.16b, v28.16b, v29.16b, #(2*6) + ext v26.16b, v28.16b, v29.16b, #(2*7) + mla v16.8h, v24.8h, v0.h[5] + mla v16.8h, v25.8h, v0.h[6] + mla v16.8h, v26.8h, v0.h[7] + srshr v16.8h, v16.8h, #2 + ret + +L(\type\()_8tap_filter_8): + ld1 {v28.8b, v29.8b}, [\sr2], \s_strd + ld1 {v30.8b, v31.8b}, [\src], \s_strd + uxtl v28.8h, v28.8b + uxtl v29.8h, v29.8b + uxtl v30.8h, v30.8b + uxtl v31.8h, v31.8b + mul v24.8h, v28.8h, v0.h[0] + mul v25.8h, v30.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v28.16b, v29.16b, #(2*\i) + ext v27.16b, v30.16b, v31.16b, #(2*\i) + mla v24.8h, v26.8h, v0.h[\i] + mla v25.8h, v27.8h, v0.h[\i] +.endr + srshr v24.8h, v24.8h, #2 + srshr v25.8h, v25.8h, #2 + ret + +L(\type\()_8tap_hv_tbl): + .hword L(\type\()_8tap_hv_tbl) - 1280b + .hword L(\type\()_8tap_hv_tbl) - 640b + .hword L(\type\()_8tap_hv_tbl) - 320b + .hword L(\type\()_8tap_hv_tbl) - 160b + .hword L(\type\()_8tap_hv_tbl) - 80b + .hword L(\type\()_8tap_hv_tbl) - 40b + .hword L(\type\()_8tap_hv_tbl) - 20b + .hword 0 +endfunc + + +function \type\()_bilin_8bpc_neon, export=1 + dup v1.16b, \mx + dup v3.16b, \my + mov w9, #16 + sub w8, w9, \mx + sub w9, w9, \my + dup v0.16b, w8 + dup v2.16b, w9 +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz w8, \w + sub w8, w8, #24 + cbnz \mx, L(\type\()_bilin_h) + cbnz \my, L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cbnz \my, L(\type\()_bilin_hv) + + adr x9, L(\type\()_bilin_h_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + ld1 {v4.s}[0], [\src], \s_strd + ld1 {v6.s}[0], [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #1 + ext v7.8b, v6.8b, v6.8b, #1 + trn1 v4.4h, v4.4h, v6.4h + trn1 v5.4h, v5.4h, v7.4h + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + ld1 {v4.8b}, [\src], \s_strd + ld1 {v6.8b}, [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #1 + ext v7.8b, v6.8b, v6.8b, #1 + trn1 v4.2s, v4.2s, v6.2s + trn1 v5.2s, v5.2s, v7.2s + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + ld1 {v4.16b}, [\src], \s_strd + ld1 {v6.16b}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #1 + ext v7.16b, v6.16b, v6.16b, #1 + subs \h, \h, #2 + umull v4.8h, v4.8b, v0.8b + umull v6.8h, v6.8b, v0.8b + umlal v4.8h, v5.8b, v1.8b + umlal v6.8h, v7.8b, v1.8b +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn v6.8b, v6.8h, #4 + st1 {v4.8b}, [\dst], \d_strd + st1 {v6.8b}, [\ds2], \d_strd +.else + st1 {v4.8h}, [\dst], \d_strd + st1 {v6.8h}, [\ds2], \d_strd +.endif + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w, uxtw + sub \s_strd, \s_strd, #8 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw +.endif +161: + ld1 {v16.d}[1], [\src], #8 + ld1 {v20.d}[1], [\sr2], #8 + mov \mx, \w + +16: + ld1 {v18.16b}, [\src], #16 + ld1 {v22.16b}, [\sr2], #16 + ext v17.16b, v16.16b, v18.16b, #8 + ext v19.16b, v16.16b, v18.16b, #9 + ext v21.16b, v20.16b, v22.16b, #8 + ext v23.16b, v20.16b, v22.16b, #9 + umull v16.8h, v17.8b, v0.8b + umull2 v17.8h, v17.16b, v0.16b + umull v20.8h, v21.8b, v0.8b + umull2 v21.8h, v21.16b, v0.16b + umlal v16.8h, v19.8b, v1.8b + umlal2 v17.8h, v19.16b, v1.16b + umlal v20.8h, v23.8b, v1.8b + umlal2 v21.8h, v23.16b, v1.16b + subs \mx, \mx, #16 +.ifc \type, put + uqrshrn v16.8b, v16.8h, #4 + uqrshrn2 v16.16b, v17.8h, #4 + uqrshrn v20.8b, v20.8h, #4 + uqrshrn2 v20.16b, v21.8h, #4 + st1 {v16.16b}, [\dst], #16 + st1 {v20.16b}, [\ds2], #16 +.else + st1 {v16.8h, v17.8h}, [\dst], #32 + st1 {v20.8h, v21.8h}, [\ds2], #32 +.endif + b.le 9f + + mov v16.16b, v18.16b + mov v20.16b, v22.16b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_bilin_h_tbl): + .hword L(\type\()_bilin_h_tbl) - 1280b + .hword L(\type\()_bilin_h_tbl) - 640b + .hword L(\type\()_bilin_h_tbl) - 320b + .hword L(\type\()_bilin_h_tbl) - 160b + .hword L(\type\()_bilin_h_tbl) - 80b + .hword L(\type\()_bilin_h_tbl) - 40b + .hword L(\type\()_bilin_h_tbl) - 20b + .hword 0 + + +L(\type\()_bilin_v): + cmp \h, #4 + adr x9, L(\type\()_bilin_v_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + ld1 {v16.h}[0], [\src], \s_strd + b.gt 24f +22: + ld1 {v17.h}[0], [\sr2], \s_strd + ld1 {v18.h}[0], [\src], \s_strd + trn1 v16.4h, v16.4h, v17.4h + trn1 v17.4h, v17.4h, v18.4h + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst] + st1 {v4.h}[1], [\ds2] + ret +24: // 2x4, 2x6, 2x8, ... v + ld1 {v17.h}[0], [\sr2], \s_strd + ld1 {v18.h}[0], [\src], \s_strd + ld1 {v19.h}[0], [\sr2], \s_strd + ld1 {v20.h}[0], [\src], \s_strd + sub \h, \h, #4 + trn1 v16.4h, v16.4h, v17.4h + trn1 v17.4h, v17.4h, v18.4h + trn1 v18.4h, v18.4h, v19.4h + trn1 v19.4h, v19.4h, v20.4h + trn1 v16.2s, v16.2s, v18.2s + trn1 v17.2s, v17.2s, v19.2s + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + cmp \h, #2 + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + st1 {v4.h}[2], [\dst], \d_strd + st1 {v4.h}[3], [\ds2], \d_strd + b.lt 0f + mov v16.8b, v20.8b + b.eq 22b + b 24b +0: + ret +.endif + +40: // 4xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.s}[0], [\src], \s_strd +4: + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + umull v4.8h, v16.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + b 4b +0: + ret + +80: // 8xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.8b}, [\src], \s_strd +8: + ld1 {v17.8b}, [\sr2], \s_strd + ld1 {v18.8b}, [\src], \s_strd + umull v4.8h, v16.8b, v2.8b + umull v5.8h, v17.8b, v2.8b + umlal v4.8h, v17.8b, v3.8b + umlal v5.8h, v18.8b, v3.8b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn v5.8b, v5.8h, #4 + st1 {v4.8b}, [\dst], \d_strd + st1 {v5.8b}, [\ds2], \d_strd +.else + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd +.endif + b.le 0f + mov v16.8b, v18.8b + b 8b +0: + ret + +160: // 16xN, 32xN, ... +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v16.16b}, [\src], \s_strd +2: + ld1 {v17.16b}, [\sr2], \s_strd + ld1 {v18.16b}, [\src], \s_strd + umull v4.8h, v16.8b, v2.8b + umull2 v5.8h, v16.16b, v2.16b + umull v6.8h, v17.8b, v2.8b + umull2 v7.8h, v17.16b, v2.16b + umlal v4.8h, v17.8b, v3.8b + umlal2 v5.8h, v17.16b, v3.16b + umlal v6.8h, v18.8b, v3.8b + umlal2 v7.8h, v18.16b, v3.16b + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #4 + uqrshrn2 v4.16b, v5.8h, #4 + uqrshrn v6.8b, v6.8h, #4 + uqrshrn2 v6.16b, v7.8h, #4 + st1 {v4.16b}, [\dst], \d_strd + st1 {v6.16b}, [\ds2], \d_strd +.else + st1 {v4.8h, v5.8h}, [\dst], \d_strd + st1 {v6.8h, v7.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #16 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 +.ifc \type, put + add \dst, \dst, #16 +.else + add \dst, \dst, #32 +.endif + b 1b +0: + ret + +L(\type\()_bilin_v_tbl): + .hword L(\type\()_bilin_v_tbl) - 1280b + .hword L(\type\()_bilin_v_tbl) - 640b + .hword L(\type\()_bilin_v_tbl) - 320b + .hword L(\type\()_bilin_v_tbl) - 160b + .hword L(\type\()_bilin_v_tbl) - 80b + .hword L(\type\()_bilin_v_tbl) - 40b + .hword L(\type\()_bilin_v_tbl) - 20b + .hword 0 + +L(\type\()_bilin_hv): + uxtl v2.8h, v2.8b + uxtl v3.8h, v3.8b + adr x9, L(\type\()_bilin_hv_tbl) + ldrh w8, [x9, x8, lsl #1] + sub x9, x9, w8, uxtw + br x9 + +20: // 2xN hv + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.s}[0], [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +2: + ld1 {v28.s}[0], [\sr2], \s_strd + ld1 {v30.s}[0], [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + ext v31.8b, v30.8b, v30.8b, #1 + trn1 v28.4h, v28.4h, v30.4h + trn1 v29.4h, v29.4h, v31.4h + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + + trn1 v16.2s, v16.2s, v17.2s + + mul v4.4h, v16.4h, v2.4h + mla v4.4h, v17.4h, v3.4h + uqrshrn v4.8b, v4.8h, #8 + subs \h, \h, #2 + st1 {v4.h}[0], [\dst], \d_strd + st1 {v4.h}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2s, v17.2s, v17.2s + b 2b +0: + ret +.endif + +40: // 4xN hv + AARCH64_VALID_JUMP_TARGET + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.8b}, [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +4: + ld1 {v28.8b}, [\sr2], \s_strd + ld1 {v30.8b}, [\src], \s_strd + ext v29.8b, v28.8b, v28.8b, #1 + ext v31.8b, v30.8b, v30.8b, #1 + trn1 v28.2s, v28.2s, v30.2s + trn1 v29.2s, v29.2s, v31.2s + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + + trn1 v16.2d, v16.2d, v17.2d + + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #8 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd +.else + urshr v4.8h, v4.8h, #4 + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd +.endif + b.le 0f + trn2 v16.2d, v17.2d, v17.2d + b 4b +0: + ret + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v28.16b}, [\src], \s_strd + ext v29.16b, v28.16b, v28.16b, #1 + umull v16.8h, v28.8b, v0.8b + umlal v16.8h, v29.8b, v1.8b + +2: + ld1 {v28.16b}, [\sr2], \s_strd + ld1 {v30.16b}, [\src], \s_strd + ext v29.16b, v28.16b, v28.16b, #1 + ext v31.16b, v30.16b, v30.16b, #1 + umull v17.8h, v28.8b, v0.8b + umlal v17.8h, v29.8b, v1.8b + umull v18.8h, v30.8b, v0.8b + umlal v18.8h, v31.8b, v1.8b + + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v18.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + uqrshrn v4.8b, v4.8h, #8 + uqrshrn v5.8b, v5.8h, #8 + st1 {v4.8b}, [\dst], \d_strd + st1 {v5.8b}, [\ds2], \d_strd +.else + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd +.endif + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #8 +.ifc \type, put + add \dst, \dst, #8 +.else + add \dst, \dst, #16 +.endif + b 1b +0: + ret + +L(\type\()_bilin_hv_tbl): + .hword L(\type\()_bilin_hv_tbl) - 1280b + .hword L(\type\()_bilin_hv_tbl) - 640b + .hword L(\type\()_bilin_hv_tbl) - 320b + .hword L(\type\()_bilin_hv_tbl) - 160b + .hword L(\type\()_bilin_hv_tbl) - 80b + .hword L(\type\()_bilin_hv_tbl) - 40b + .hword L(\type\()_bilin_hv_tbl) - 20b + .hword 0 +endfunc +.endm + +filter_fn put, x0, x1, x2, x3, w4, w5, w6, x6, w7, x7, x8, x9, 10 +filter_fn prep, x0, x7, x1, x2, w3, w4, w5, x5, w6, x6, x8, x9, 6 + +.macro load_filter_row dst, src, inc + asr w13, \src, #10 + add \src, \src, \inc + ldr \dst, [x11, w13, sxtw #3] +.endm + +function warp_filter_horz_neon + add w12, w5, #512 + + ld1 {v16.8b, v17.8b}, [x2], x3 + + load_filter_row d0, w12, w7 + load_filter_row d1, w12, w7 + load_filter_row d2, w12, w7 + load_filter_row d3, w12, w7 + load_filter_row d4, w12, w7 + load_filter_row d5, w12, w7 + load_filter_row d6, w12, w7 + // subtract by 128 to allow using smull + eor v16.8b, v16.8b, v22.8b + eor v17.8b, v17.8b, v22.8b + load_filter_row d7, w12, w7 + + ext v18.8b, v16.8b, v17.8b, #1 + ext v19.8b, v16.8b, v17.8b, #2 + smull v0.8h, v0.8b, v16.8b + smull v1.8h, v1.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #3 + ext v20.8b, v16.8b, v17.8b, #4 + smull v2.8h, v2.8b, v19.8b + smull v3.8h, v3.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #5 + ext v19.8b, v16.8b, v17.8b, #6 + smull v4.8h, v4.8b, v20.8b + smull v5.8h, v5.8b, v18.8b + ext v18.8b, v16.8b, v17.8b, #7 + smull v6.8h, v6.8b, v19.8b + smull v7.8h, v7.8b, v18.8b + + addp v0.8h, v0.8h, v1.8h + addp v2.8h, v2.8h, v3.8h + addp v4.8h, v4.8h, v5.8h + addp v6.8h, v6.8h, v7.8h + + addp v0.8h, v0.8h, v2.8h + addp v4.8h, v4.8h, v6.8h + + addp v0.8h, v0.8h, v4.8h + + add w5, w5, w8 + + ret +endfunc + +// void dav1d_warp_affine_8x8_8bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my) +.macro warp t, shift +function warp_affine_8x8\t\()_8bpc_neon, export=1 + ldr x4, [x4] + sbfx x7, x4, #0, #16 + sbfx x8, x4, #16, #16 + sbfx x9, x4, #32, #16 + sbfx x4, x4, #48, #16 + mov w10, #8 + sub x2, x2, x3, lsl #1 + sub x2, x2, x3 + sub x2, x2, #3 + movrel x11, X(mc_warp_filter), 64*8 + mov x15, x30 +.ifnb \t + lsl x1, x1, #1 +.endif + + movi v22.8b, #128 +.ifb \t + movi v23.8h, #128 +.else + movi v23.8h, #8, lsl #8 +.endif + + bl warp_filter_horz_neon + srshr v24.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v25.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v26.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v27.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v28.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v29.8h, v0.8h, #3 + bl warp_filter_horz_neon + srshr v30.8h, v0.8h, #3 + +1: + add w14, w6, #512 + bl warp_filter_horz_neon + srshr v31.8h, v0.8h, #3 + + load_filter_row d0, w14, w9 + load_filter_row d1, w14, w9 + load_filter_row d2, w14, w9 + load_filter_row d3, w14, w9 + load_filter_row d4, w14, w9 + load_filter_row d5, w14, w9 + load_filter_row d6, w14, w9 + load_filter_row d7, w14, w9 + transpose_8x8b_xtl v0, v1, v2, v3, v4, v5, v6, v7, sxtl + + // This ordering of smull/smlal/smull2/smlal2 is highly + // beneficial for Cortex A53 here. + smull v16.4s, v24.4h, v0.4h + smlal v16.4s, v25.4h, v1.4h + smlal v16.4s, v26.4h, v2.4h + smlal v16.4s, v27.4h, v3.4h + smlal v16.4s, v28.4h, v4.4h + smlal v16.4s, v29.4h, v5.4h + smlal v16.4s, v30.4h, v6.4h + smlal v16.4s, v31.4h, v7.4h + smull2 v17.4s, v24.8h, v0.8h + smlal2 v17.4s, v25.8h, v1.8h + smlal2 v17.4s, v26.8h, v2.8h + smlal2 v17.4s, v27.8h, v3.8h + smlal2 v17.4s, v28.8h, v4.8h + smlal2 v17.4s, v29.8h, v5.8h + smlal2 v17.4s, v30.8h, v6.8h + smlal2 v17.4s, v31.8h, v7.8h + + mov v24.16b, v25.16b + mov v25.16b, v26.16b + sqrshrn v16.4h, v16.4s, #\shift + mov v26.16b, v27.16b + sqrshrn2 v16.8h, v17.4s, #\shift + mov v27.16b, v28.16b + mov v28.16b, v29.16b + add v16.8h, v16.8h, v23.8h +.ifb \t + sqxtun v16.8b, v16.8h +.endif + mov v29.16b, v30.16b + mov v30.16b, v31.16b + subs w10, w10, #1 +.ifnb \t + st1 {v16.8h}, [x0], x1 +.else + st1 {v16.8b}, [x0], x1 +.endif + + add w6, w6, w4 + b.gt 1b + + ret x15 +endfunc +.endm + +warp , 11 +warp t, 7 + +// void dav1d_emu_edge_8bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_8bpc_neon, export=1 + ldp x8, x9, [sp] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub x12, x3, #1 // ih - 1 + cmp x5, x3 + sub x13, x2, #1 // iw - 1 + csel x12, x12, x5, ge // min(y, ih - 1) + cmp x4, x2 + bic x12, x12, x12, asr #63 // max(min(y, ih - 1), 0) + csel x13, x13, x4, ge // min(x, iw - 1) + bic x13, x13, x13, asr #63 // max(min(x, iw - 1), 0) + madd x8, x12, x9, x8 // ref += iclip() * stride + add x8, x8, x13 // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add x10, x5, x1 // y + bh + neg x5, x5 // -y + sub x10, x10, x3 // y + bh - ih + sub x12, x1, #1 // bh - 1 + cmp x10, x1 + bic x5, x5, x5, asr #63 // max(-y, 0) + csel x10, x10, x12, lt // min(y + bh - ih, bh-1) + cmp x5, x1 + bic x10, x10, x10, asr #63 // max(min(y + bh - ih, bh-1), 0) + csel x5, x5, x12, lt // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add x11, x4, x0 // x + bw + neg x4, x4 // -x + sub x11, x11, x2 // x + bw - iw + sub x13, x0, #1 // bw - 1 + cmp x11, x0 + bic x4, x4, x4, asr #63 // max(-x, 0) + csel x11, x11, x13, lt // min(x + bw - iw, bw-1) + cmp x4, x0 + bic x11, x11, x11, asr #63 // max(min(x + bw - iw, bw-1), 0) + csel x4, x4, x13, lt // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub x1, x1, x5 // bh - top_ext + madd x6, x5, x7, x6 + sub x2, x0, x4 // bw - left_ext + sub x1, x1, x10 // center_h = bh - top_ext - bottom_ext + sub x2, x2, x11 // center_w = bw - left_ext - right_ext + + mov x14, x6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + ld1r {v0.16b}, [x8] + mov x12, x6 // out = dst + mov x3, x4 +1: + subs x3, x3, #16 + st1 {v0.16b}, [x12], #16 + b.gt 1b +.endif + mov x13, x8 + add x12, x6, x4 // out = dst + left_ext + mov x3, x2 +1: + ld1 {v0.16b, v1.16b}, [x13], #32 + subs x3, x3, #32 + st1 {v0.16b, v1.16b}, [x12], #32 + b.gt 1b +.if \need_right + add x3, x8, x2 // in + center_w + sub x3, x3, #1 // in + center_w - 1 + add x12, x6, x4 // dst + left_ext + ld1r {v0.16b}, [x3] + add x12, x12, x2 // out = dst + left_ext + center_w + mov x3, x11 +1: + subs x3, x3, #16 + st1 {v0.16b}, [x12], #16 + b.gt 1b +.endif + + subs x1, x1, #1 // center_h-- + add x6, x6, x7 + add x8, x8, x9 + b.gt 0b +.endm + + cbz x4, 2f + // need_left + cbz x11, 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cbz x11, 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + + cbz x10, 3f + // need_bottom + sub x8, x6, x7 // ref = dst - stride + mov x4, x0 +1: + ld1 {v0.16b, v1.16b}, [x8], #32 + mov x3, x10 +2: + subs x3, x3, #1 + st1 {v0.16b, v1.16b}, [x6], x7 + b.gt 2b + msub x6, x7, x10, x6 // dst -= bottom_ext * stride + subs x4, x4, #32 // bw -= 32 + add x6, x6, #32 // dst += 32 + b.gt 1b + +3: + cbz x5, 3f + // need_top + msub x6, x7, x5, x14 // dst = stored_dst - top_ext * stride +1: + ld1 {v0.16b, v1.16b}, [x14], #32 + mov x3, x5 +2: + subs x3, x3, #1 + st1 {v0.16b, v1.16b}, [x6], x7 + b.gt 2b + msub x6, x7, x5, x6 // dst -= top_ext * stride + subs x0, x0, #32 // bw -= 32 + add x6, x6, #32 // dst += 32 + b.gt 1b + +3: + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/mc16.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc16.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/mc16.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/mc16.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3611 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * Copyright © 2020, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define PREP_BIAS 8192 + +.macro avg d0, d1, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sqadd \t0\().8h, \t0\().8h, \t2\().8h + sqadd \t1\().8h, \t1\().8h, \t3\().8h + smax \t0\().8h, \t0\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + smax \t1\().8h, \t1\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sqsub \t0\().8h, \t0\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sqsub \t1\().8h, \t1\().8h, v28.8h // -2*PREP_BIAS - 1 << intermediate_bits + sshl \d0\().8h, \t0\().8h, v29.8h // -(intermediate_bits+1) + sshl \d1\().8h, \t1\().8h, v29.8h // -(intermediate_bits+1) +.endm + +.macro w_avg d0, d1, t0, t1, t2, t3 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + // This difference requires a 17 bit range, and all bits are + // significant for the following multiplication. + ssubl \d0\().4s, \t2\().4h, \t0\().4h + ssubl2 \t0\().4s, \t2\().8h, \t0\().8h + ssubl \d1\().4s, \t3\().4h, \t1\().4h + ssubl2 \t1\().4s, \t3\().8h, \t1\().8h + mul \d0\().4s, \d0\().4s, v27.4s + mul \t0\().4s, \t0\().4s, v27.4s + mul \d1\().4s, \d1\().4s, v27.4s + mul \t1\().4s, \t1\().4s, v27.4s + sshr \d0\().4s, \d0\().4s, #4 + sshr \t0\().4s, \t0\().4s, #4 + sshr \d1\().4s, \d1\().4s, #4 + sshr \t1\().4s, \t1\().4s, #4 + saddw \d0\().4s, \d0\().4s, \t2\().4h + saddw2 \t0\().4s, \t0\().4s, \t2\().8h + saddw \d1\().4s, \d1\().4s, \t3\().4h + saddw2 \t1\().4s, \t1\().4s, \t3\().8h + uzp1 \d0\().8h, \d0\().8h, \t0\().8h // Same as xtn, xtn2 + uzp1 \d1\().8h, \d1\().8h, \t1\().8h // Ditto + srshl \d0\().8h, \d0\().8h, v29.8h // -intermediate_bits + srshl \d1\().8h, \d1\().8h, v29.8h // -intermediate_bits + add \d0\().8h, \d0\().8h, v28.8h // PREP_BIAS >> intermediate_bits + add \d1\().8h, \d1\().8h, v28.8h // PREP_BIAS >> intermediate_bits + smin \d0\().8h, \d0\().8h, v31.8h // bitdepth_max + smin \d1\().8h, \d1\().8h, v31.8h // bitdepth_max + smax \d0\().8h, \d0\().8h, v30.8h // 0 + smax \d1\().8h, \d1\().8h, v30.8h // 0 +.endm + +.macro mask d0, d1, t0, t1, t2, t3 + ld1 {v27.16b}, [x6], 16 + ld1 {\t0\().8h,\t1\().8h}, [x2], 32 + neg v27.16b, v27.16b + ld1 {\t2\().8h,\t3\().8h}, [x3], 32 + sxtl v26.8h, v27.8b + sxtl2 v27.8h, v27.16b + sxtl v24.4s, v26.4h + sxtl2 v25.4s, v26.8h + sxtl v26.4s, v27.4h + sxtl2 v27.4s, v27.8h + ssubl \d0\().4s, \t2\().4h, \t0\().4h + ssubl2 \t0\().4s, \t2\().8h, \t0\().8h + ssubl \d1\().4s, \t3\().4h, \t1\().4h + ssubl2 \t1\().4s, \t3\().8h, \t1\().8h + mul \d0\().4s, \d0\().4s, v24.4s + mul \t0\().4s, \t0\().4s, v25.4s + mul \d1\().4s, \d1\().4s, v26.4s + mul \t1\().4s, \t1\().4s, v27.4s + sshr \d0\().4s, \d0\().4s, #6 + sshr \t0\().4s, \t0\().4s, #6 + sshr \d1\().4s, \d1\().4s, #6 + sshr \t1\().4s, \t1\().4s, #6 + saddw \d0\().4s, \d0\().4s, \t2\().4h + saddw2 \t0\().4s, \t0\().4s, \t2\().8h + saddw \d1\().4s, \d1\().4s, \t3\().4h + saddw2 \t1\().4s, \t1\().4s, \t3\().8h + uzp1 \d0\().8h, \d0\().8h, \t0\().8h // Same as xtn, xtn2 + uzp1 \d1\().8h, \d1\().8h, \t1\().8h // Ditto + srshl \d0\().8h, \d0\().8h, v29.8h // -intermediate_bits + srshl \d1\().8h, \d1\().8h, v29.8h // -intermediate_bits + add \d0\().8h, \d0\().8h, v28.8h // PREP_BIAS >> intermediate_bits + add \d1\().8h, \d1\().8h, v28.8h // PREP_BIAS >> intermediate_bits + smin \d0\().8h, \d0\().8h, v31.8h // bitdepth_max + smin \d1\().8h, \d1\().8h, v31.8h // bitdepth_max + smax \d0\().8h, \d0\().8h, v30.8h // 0 + smax \d1\().8h, \d1\().8h, v30.8h // 0 +.endm + +.macro bidir_fn type, bdmax +function \type\()_16bpc_neon, export=1 + clz w4, w4 +.ifnc \type, avg + dup v31.8h, \bdmax // bitdepth_max + movi v30.8h, #0 +.endif + clz w7, \bdmax + sub w7, w7, #18 // intermediate_bits = clz(bitdepth_max) - 18 +.ifc \type, avg + mov w9, #1 + mov w8, #-2*PREP_BIAS + lsl w9, w9, w7 // 1 << intermediate_bits + add w7, w7, #1 + sub w8, w8, w9 // -2*PREP_BIAS - 1 << intermediate_bits + neg w7, w7 // -(intermediate_bits+1) + dup v28.8h, w8 // -2*PREP_BIAS - 1 << intermediate_bits + dup v29.8h, w7 // -(intermediate_bits+1) +.else + mov w8, #PREP_BIAS + lsr w8, w8, w7 // PREP_BIAS >> intermediate_bits + neg w7, w7 // -intermediate_bits + dup v28.8h, w8 // PREP_BIAS >> intermediate_bits + dup v29.8h, w7 // -intermediate_bits +.endif +.ifc \type, w_avg + dup v27.4s, w6 + neg v27.4s, v27.4s +.endif + adr x7, L(\type\()_tbl) + sub w4, w4, #24 + \type v4, v5, v0, v1, v2, v3 + ldrh w4, [x7, x4, lsl #1] + sub x7, x7, w4, uxtw + br x7 +40: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +4: + subs w5, w5, #4 + st1 {v4.d}[0], [x0], x1 + st1 {v4.d}[1], [x7], x1 + st1 {v5.d}[0], [x0], x1 + st1 {v5.d}[1], [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 4b +80: + AARCH64_VALID_JUMP_TARGET + add x7, x0, x1 + lsl x1, x1, #1 +8: + st1 {v4.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v5.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 8b +16: + AARCH64_VALID_JUMP_TARGET + \type v6, v7, v0, v1, v2, v3 + st1 {v4.8h, v5.8h}, [x0], x1 + subs w5, w5, #2 + st1 {v6.8h, v7.8h}, [x0], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 16b +32: + AARCH64_VALID_JUMP_TARGET + \type v6, v7, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 32b +640: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 +64: + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + \type v18, v19, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 64b +1280: + AARCH64_VALID_JUMP_TARGET + add x7, x0, #64 + mov x8, #128 + sub x1, x1, #128 +128: + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x8 + \type v18, v19, v0, v1, v2, v3 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x8 + \type v4, v5, v0, v1, v2, v3 + \type v6, v7, v0, v1, v2, v3 + \type v16, v17, v0, v1, v2, v3 + subs w5, w5, #1 + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x0], x1 + \type v18, v19, v0, v1, v2, v3 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x7], x1 + b.le 0f + \type v4, v5, v0, v1, v2, v3 + b 128b +0: + ret +L(\type\()_tbl): + .hword L(\type\()_tbl) - 1280b + .hword L(\type\()_tbl) - 640b + .hword L(\type\()_tbl) - 32b + .hword L(\type\()_tbl) - 16b + .hword L(\type\()_tbl) - 80b + .hword L(\type\()_tbl) - 40b +endfunc +.endm + +bidir_fn avg, w6 +bidir_fn w_avg, w7 +bidir_fn mask, w7 + + +.macro w_mask_fn type +function w_mask_\type\()_16bpc_neon, export=1 + ldr w8, [sp] + clz w9, w4 + adr x10, L(w_mask_\type\()_tbl) + dup v31.8h, w8 // bitdepth_max + sub w9, w9, #24 + clz w8, w8 // clz(bitdepth_max) + ldrh w9, [x10, x9, lsl #1] + sub x10, x10, w9, uxtw + sub w8, w8, #12 // sh = intermediate_bits + 6 = clz(bitdepth_max) - 12 + mov w9, #PREP_BIAS*64 + neg w8, w8 // -sh + mov w11, #27615 // (64 + 1 - 38)<> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + uxtl v22.4s, v20.4h + uxtl2 v23.4s, v20.8h + uxtl v24.4s, v21.4h + uxtl2 v25.4s, v21.8h + mla v4.4s, v16.4s, v22.4s // (tmp2-tmp1)*(64-m) + mla v5.4s, v17.4s, v23.4s + mla v6.4s, v18.4s, v24.4s + mla v7.4s, v19.4s, v25.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v6.4s + sqxtun2 v5.8h, v7.4s + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + sub v20.16b, v1.16b, v20.16b // m + st1 {v20.16b}, [x6], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + xtn v20.8b, v20.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + st1 {v20.8b}, [x6], #8 +.elseif \type == 420 + trn1 v24.2d, v20.2d, v21.2d + trn2 v25.2d, v20.2d, v21.2d + add v24.8h, v24.8h, v25.8h // (64 - my1) + (64 - my2) (row wise addition) + addp v20.8h, v24.8h, v24.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.4h, v3.4h, v20.4h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.s}[0], [x6], #4 +.endif + st1 {v4.d}[0], [x0], x1 + st1 {v4.d}[1], [x12], x1 + st1 {v5.d}[0], [x0], x1 + st1 {v5.d}[1], [x12], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 + ld1 {v6.8h, v7.8h}, [x3], #32 // tmp2 + subs w5, w5, #2 + sabd v20.8h, v4.8h, v6.8h // abs(tmp1 - tmp2) + sabd v21.8h, v5.8h, v7.8h + ssubl v16.4s, v6.4h, v4.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v17.4s, v6.8h, v4.8h + ssubl v18.4s, v7.4h, v5.4h + ssubl2 v19.4s, v7.8h, v5.8h + uqsub v20.8h, v0.8h, v20.8h // 27615 - abs() + uqsub v21.8h, v0.8h, v21.8h + sshll2 v7.4s, v5.8h, #6 // tmp1 << 6 + sshll v6.4s, v5.4h, #6 + sshll2 v5.4s, v4.8h, #6 + sshll v4.4s, v4.4h, #6 + ushr v20.8h, v20.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v6.4s, v6.4s, v30.4s + add v7.4s, v7.4s, v30.4s + uxtl v22.4s, v20.4h + uxtl2 v23.4s, v20.8h + uxtl v24.4s, v21.4h + uxtl2 v25.4s, v21.8h + mla v4.4s, v16.4s, v22.4s // (tmp2-tmp1)*(64-m) + mla v5.4s, v17.4s, v23.4s + mla v6.4s, v18.4s, v24.4s + mla v7.4s, v19.4s, v25.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v6.4s, v6.4s, v29.4s + srshl v7.4s, v7.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v6.4s + sqxtun2 v5.8h, v7.4s + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + sub v20.16b, v1.16b, v20.16b // m + st1 {v20.16b}, [x6], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + xtn v20.8b, v20.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + st1 {v20.8b}, [x6], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v21.8h // (64 - my1) + (64 - my2) (row wise addition) + addp v20.8h, v20.8h, v20.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.4h, v3.4h, v20.4h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.s}[0], [x6], #4 +.endif + st1 {v4.8h}, [x0], x1 + st1 {v5.8h}, [x12], x1 + b.gt 8b + ret +1280: +640: +320: +160: + AARCH64_VALID_JUMP_TARGET + mov w11, w4 + sub x1, x1, w4, uxtw #1 +.if \type == 444 + add x10, x6, w4, uxtw +.elseif \type == 422 + add x10, x6, x11, lsr #1 +.endif + add x9, x3, w4, uxtw #1 + add x7, x2, w4, uxtw #1 +161: + mov w8, w4 +16: + ld1 {v4.8h, v5.8h}, [x2], #32 // tmp1 + ld1 {v16.8h, v17.8h}, [x3], #32 // tmp2 + ld1 {v6.8h, v7.8h}, [x7], #32 + ld1 {v18.8h, v19.8h}, [x9], #32 + subs w8, w8, #16 + sabd v20.8h, v4.8h, v16.8h // abs(tmp1 - tmp2) + sabd v21.8h, v5.8h, v17.8h + ssubl v22.4s, v16.4h, v4.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v23.4s, v16.8h, v4.8h + ssubl v24.4s, v17.4h, v5.4h + ssubl2 v25.4s, v17.8h, v5.8h + uqsub v20.8h, v0.8h, v20.8h // 27615 - abs() + uqsub v21.8h, v0.8h, v21.8h + sshll2 v27.4s, v5.8h, #6 // tmp1 << 6 + sshll v26.4s, v5.4h, #6 + sshll2 v5.4s, v4.8h, #6 + sshll v4.4s, v4.4h, #6 + ushr v20.8h, v20.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v21.8h, v21.8h, #10 + add v4.4s, v4.4s, v30.4s // += PREP_BIAS*64 + add v5.4s, v5.4s, v30.4s + add v26.4s, v26.4s, v30.4s + add v27.4s, v27.4s, v30.4s + uxtl v16.4s, v20.4h + uxtl2 v17.4s, v20.8h + uxtl v28.4s, v21.4h + mla v4.4s, v22.4s, v16.4s // (tmp2-tmp1)*(64-m) + uxtl2 v16.4s, v21.8h + mla v5.4s, v23.4s, v17.4s + mla v26.4s, v24.4s, v28.4s + mla v27.4s, v25.4s, v16.4s + srshl v4.4s, v4.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v5.4s, v5.4s, v29.4s + srshl v26.4s, v26.4s, v29.4s + srshl v27.4s, v27.4s, v29.4s + sqxtun v4.4h, v4.4s // iclip_pixel + sqxtun2 v4.8h, v5.4s + sqxtun v5.4h, v26.4s + sqxtun2 v5.8h, v27.4s + + // Start of other half + sabd v22.8h, v6.8h, v18.8h // abs(tmp1 - tmp2) + sabd v23.8h, v7.8h, v19.8h + + umin v4.8h, v4.8h, v31.8h // iclip_pixel + umin v5.8h, v5.8h, v31.8h + + ssubl v16.4s, v18.4h, v6.4h // tmp2 - tmp1 (requires 17 bit) + ssubl2 v17.4s, v18.8h, v6.8h + ssubl v18.4s, v19.4h, v7.4h + ssubl2 v19.4s, v19.8h, v7.8h + uqsub v22.8h, v0.8h, v22.8h // 27615 - abs() + uqsub v23.8h, v0.8h, v23.8h + sshll v24.4s, v6.4h, #6 // tmp1 << 6 + sshll2 v25.4s, v6.8h, #6 + sshll v26.4s, v7.4h, #6 + sshll2 v27.4s, v7.8h, #6 + ushr v22.8h, v22.8h, #10 // 64-m = (27615 - abs()) >> mask_sh + ushr v23.8h, v23.8h, #10 + add v24.4s, v24.4s, v30.4s // += PREP_BIAS*64 + add v25.4s, v25.4s, v30.4s + add v26.4s, v26.4s, v30.4s + add v27.4s, v27.4s, v30.4s + uxtl v6.4s, v22.4h + uxtl2 v7.4s, v22.8h + uxtl v28.4s, v23.4h + mla v24.4s, v16.4s, v6.4s // (tmp2-tmp1)*(64-m) + uxtl2 v6.4s, v23.8h + mla v25.4s, v17.4s, v7.4s + mla v26.4s, v18.4s, v28.4s + mla v27.4s, v19.4s, v6.4s + srshl v24.4s, v24.4s, v29.4s // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh + srshl v25.4s, v25.4s, v29.4s + srshl v26.4s, v26.4s, v29.4s + srshl v27.4s, v27.4s, v29.4s + sqxtun v6.4h, v24.4s // iclip_pixel + sqxtun2 v6.8h, v25.4s + sqxtun v7.4h, v26.4s + sqxtun2 v7.8h, v27.4s + umin v6.8h, v6.8h, v31.8h // iclip_pixel + umin v7.8h, v7.8h, v31.8h +.if \type == 444 + uzp1 v20.16b, v20.16b, v21.16b // 64 - m + uzp1 v21.16b, v22.16b, v23.16b + sub v20.16b, v1.16b, v20.16b // m + sub v21.16b, v1.16b, v21.16b + st1 {v20.16b}, [x6], #16 + st1 {v21.16b}, [x10], #16 +.elseif \type == 422 + addp v20.8h, v20.8h, v21.8h // (64 - m) + (64 - n) (column wise addition) + addp v21.8h, v22.8h, v23.8h + xtn v20.8b, v20.8h + xtn v21.8b, v21.8h + uhsub v20.8b, v3.8b, v20.8b // ((129 - sign) - ((64 - m) + (64 - n)) >> 1 + uhsub v21.8b, v3.8b, v21.8b + st1 {v20.8b}, [x6], #8 + st1 {v21.8b}, [x10], #8 +.elseif \type == 420 + add v20.8h, v20.8h, v22.8h // (64 - my1) + (64 - my2) (row wise addition) + add v21.8h, v21.8h, v23.8h + addp v20.8h, v20.8h, v21.8h // (128 - m) + (128 - n) (column wise addition) + sub v20.8h, v3.8h, v20.8h // (256 - sign) - ((128 - m) + (128 - n)) + rshrn v20.8b, v20.8h, #2 // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2 + st1 {v20.8b}, [x6], #8 +.endif + st1 {v4.8h, v5.8h}, [x0], #32 + st1 {v6.8h, v7.8h}, [x12], #32 + b.gt 16b + subs w5, w5, #2 + add x2, x2, w4, uxtw #1 + add x3, x3, w4, uxtw #1 + add x7, x7, w4, uxtw #1 + add x9, x9, w4, uxtw #1 +.if \type == 444 + add x6, x6, w4, uxtw + add x10, x10, w4, uxtw +.elseif \type == 422 + add x6, x6, x11, lsr #1 + add x10, x10, x11, lsr #1 +.endif + add x0, x0, x1 + add x12, x12, x1 + b.gt 161b + ret +L(w_mask_\type\()_tbl): + .hword L(w_mask_\type\()_tbl) - 1280b + .hword L(w_mask_\type\()_tbl) - 640b + .hword L(w_mask_\type\()_tbl) - 320b + .hword L(w_mask_\type\()_tbl) - 160b + .hword L(w_mask_\type\()_tbl) - 8b + .hword L(w_mask_\type\()_tbl) - 4b +endfunc +.endm + +w_mask_fn 444 +w_mask_fn 422 +w_mask_fn 420 + + +function blend_16bpc_neon, export=1 + adr x6, L(blend_tbl) + clz w3, w3 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + add x8, x0, x1 + br x6 +40: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +4: + ld1 {v2.8b}, [x5], #8 + ld1 {v1.8h}, [x2], #16 + ld1 {v0.d}[0], [x0] + neg v2.8b, v2.8b // -m + subs w4, w4, #2 + ld1 {v0.d}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.d}[0], [x0], x1 + st1 {v0.d}[1], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +8: + ld1 {v4.16b}, [x5], #16 + ld1 {v2.8h, v3.8h}, [x2], #32 + neg v5.16b, v4.16b // -m + ld1 {v0.8h}, [x0] + ld1 {v1.8h}, [x8] + sxtl v4.8h, v5.8b + sxtl2 v5.8h, v5.16b + shl v4.8h, v4.8h, #9 // -m << 9 + shl v5.8h, v5.8h, #9 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + subs w4, w4, #2 + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v5.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + lsl x1, x1, #1 +16: + ld1 {v16.16b, v17.16b}, [x5], #32 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + subs w4, w4, #2 + neg v18.16b, v16.16b // -m + neg v19.16b, v17.16b + ld1 {v0.8h, v1.8h}, [x0] + sxtl v16.8h, v18.8b + sxtl2 v17.8h, v18.16b + sxtl v18.8h, v19.8b + sxtl2 v19.8h, v19.16b + ld1 {v2.8h, v3.8h}, [x8] + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + shl v18.8h, v18.8h, #9 + shl v19.8h, v19.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v17.8h + sqrdmulh v6.8h, v6.8h, v18.8h + sqrdmulh v7.8h, v7.8h, v19.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v2.8h, v3.8h}, [x8], x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b, v17.16b}, [x5], #32 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + subs w4, w4, #1 + neg v18.16b, v16.16b // -m + neg v19.16b, v17.16b + sxtl v16.8h, v18.8b + sxtl2 v17.8h, v18.16b + sxtl v18.8h, v19.8b + sxtl2 v19.8h, v19.16b + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + shl v18.8h, v18.8h, #9 + shl v19.8h, v19.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v17.8h + sqrdmulh v6.8h, v6.8h, v18.8h + sqrdmulh v7.8h, v7.8h, v19.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], x1 + b.gt 32b + ret +L(blend_tbl): + .hword L(blend_tbl) - 32b + .hword L(blend_tbl) - 160b + .hword L(blend_tbl) - 80b + .hword L(blend_tbl) - 40b +endfunc + +function blend_h_16bpc_neon, export=1 + adr x6, L(blend_h_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w4, uxtw + sub w4, w4, w4, lsr #2 + clz w7, w3 + add x8, x0, x1 + lsl x1, x1, #1 + sub w7, w7, #24 + ldrh w7, [x6, x7, lsl #1] + sub x6, x6, w7, uxtw + br x6 +2: + AARCH64_VALID_JUMP_TARGET + ld2r {v2.8b, v3.8b}, [x5], #2 + ld1 {v1.4h}, [x2], #8 + ext v2.8b, v2.8b, v3.8b, #6 + subs w4, w4, #2 + neg v2.8b, v2.8b // -m + ld1 {v0.s}[0], [x0] + ld1 {v0.s}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.4h, v2.4h, #9 // -m << 9 + sub v1.4h, v0.4h, v1.4h // a - b + sqrdmulh v1.4h, v1.4h, v2.4h // ((a-b)*-m + 32) >> 6 + add v0.4h, v0.4h, v1.4h + st1 {v0.s}[0], [x0], x1 + st1 {v0.s}[1], [x8], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld2r {v2.8b, v3.8b}, [x5], #2 + ld1 {v1.8h}, [x2], #16 + ext v2.8b, v2.8b, v3.8b, #4 + subs w4, w4, #2 + neg v2.8b, v2.8b // -m + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.d}[0], [x0], x1 + st1 {v0.d}[1], [x8], x1 + b.gt 4b + ret +8: + AARCH64_VALID_JUMP_TARGET + ld2r {v4.8b, v5.8b}, [x5], #2 + ld1 {v2.8h, v3.8h}, [x2], #32 + neg v4.8b, v4.8b // -m + neg v5.8b, v5.8b + ld1 {v0.8h}, [x0] + subs w4, w4, #2 + sxtl v4.8h, v4.8b + sxtl v5.8h, v5.8b + ld1 {v1.8h}, [x8] + shl v4.8h, v4.8h, #9 // -m << 9 + shl v5.8h, v5.8h, #9 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v5.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ld2r {v16.8b, v17.8b}, [x5], #2 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + neg v16.8b, v16.8b // -m + neg v17.8b, v17.8b + ld1 {v0.8h, v1.8h}, [x0] + ld1 {v2.8h, v3.8h}, [x8] + subs w4, w4, #2 + sxtl v16.8h, v16.8b + sxtl v17.8h, v17.8b + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.8h, v17.8h, #9 + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.8h, v1.8h, v5.8h + sub v6.8h, v2.8h, v6.8h + sub v7.8h, v3.8h, v7.8h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.8h, v5.8h, v16.8h + sqrdmulh v6.8h, v6.8h, v17.8h + sqrdmulh v7.8h, v7.8h, v17.8h + add v0.8h, v0.8h, v4.8h + add v1.8h, v1.8h, v5.8h + add v2.8h, v2.8h, v6.8h + add v3.8h, v3.8h, v7.8h + st1 {v0.8h, v1.8h}, [x0], x1 + st1 {v2.8h, v3.8h}, [x8], x1 + b.gt 16b + ret +1280: +640: +320: + AARCH64_VALID_JUMP_TARGET + sub x1, x1, w3, uxtw #1 + add x7, x2, w3, uxtw #1 +321: + ld2r {v24.8b, v25.8b}, [x5], #2 + mov w6, w3 + neg v24.8b, v24.8b // -m + neg v25.8b, v25.8b + sxtl v24.8h, v24.8b + sxtl v25.8h, v25.8b + shl v24.8h, v24.8h, #9 // -m << 9 + shl v25.8h, v25.8h, #9 +32: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x2], #64 + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0] + subs w6, w6, #32 + sub v16.8h, v0.8h, v16.8h // a - b + sub v17.8h, v1.8h, v17.8h + sub v18.8h, v2.8h, v18.8h + sub v19.8h, v3.8h, v19.8h + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x7], #64 + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x8] + sqrdmulh v16.8h, v16.8h, v24.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v17.8h, v17.8h, v24.8h + sqrdmulh v18.8h, v18.8h, v24.8h + sqrdmulh v19.8h, v19.8h, v24.8h + sub v20.8h, v4.8h, v20.8h // a - b + sub v21.8h, v5.8h, v21.8h + sub v22.8h, v6.8h, v22.8h + sub v23.8h, v7.8h, v23.8h + add v0.8h, v0.8h, v16.8h + add v1.8h, v1.8h, v17.8h + add v2.8h, v2.8h, v18.8h + add v3.8h, v3.8h, v19.8h + sqrdmulh v20.8h, v20.8h, v25.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v21.8h, v21.8h, v25.8h + sqrdmulh v22.8h, v22.8h, v25.8h + sqrdmulh v23.8h, v23.8h, v25.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + add v4.8h, v4.8h, v20.8h + add v5.8h, v5.8h, v21.8h + add v6.8h, v6.8h, v22.8h + add v7.8h, v7.8h, v23.8h + st1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x8], #64 + b.gt 32b + subs w4, w4, #2 + add x0, x0, x1 + add x8, x8, x1 + add x2, x2, w3, uxtw #1 + add x7, x7, w3, uxtw #1 + b.gt 321b + ret +L(blend_h_tbl): + .hword L(blend_h_tbl) - 1280b + .hword L(blend_h_tbl) - 640b + .hword L(blend_h_tbl) - 320b + .hword L(blend_h_tbl) - 16b + .hword L(blend_h_tbl) - 8b + .hword L(blend_h_tbl) - 4b + .hword L(blend_h_tbl) - 2b +endfunc + +function blend_v_16bpc_neon, export=1 + adr x6, L(blend_v_tbl) + movrel x5, X(obmc_masks) + add x5, x5, w3, uxtw + clz w3, w3 + add x8, x0, x1 + lsl x1, x1, #1 + sub w3, w3, #26 + ldrh w3, [x6, x3, lsl #1] + sub x6, x6, w3, uxtw + br x6 +20: + AARCH64_VALID_JUMP_TARGET + ld1r {v2.8b}, [x5] + neg v2.8b, v2.8b // -m + sxtl v2.8h, v2.8b + shl v2.4h, v2.4h, #9 // -m << 9 +2: + ld1 {v1.s}[0], [x2], #4 + ld1 {v0.h}[0], [x0] + subs w4, w4, #2 + ld1 {v1.h}[1], [x2] + ld1 {v0.h}[1], [x8] + add x2, x2, #4 + sub v1.4h, v0.4h, v1.4h // a - b + sqrdmulh v1.4h, v1.4h, v2.4h // ((a-b)*-m + 32) >> 6 + add v0.4h, v0.4h, v1.4h + st1 {v0.h}[0], [x0], x1 + st1 {v0.h}[1], [x8], x1 + b.gt 2b + ret +40: + AARCH64_VALID_JUMP_TARGET + ld1r {v2.2s}, [x5] + sub x1, x1, #4 + neg v2.8b, v2.8b // -m + sxtl v2.8h, v2.8b + shl v2.8h, v2.8h, #9 // -m << 9 +4: + ld1 {v1.8h}, [x2], #16 + ld1 {v0.d}[0], [x0] + ld1 {v0.d}[1], [x8] + subs w4, w4, #2 + sub v1.8h, v0.8h, v1.8h // a - b + sqrdmulh v1.8h, v1.8h, v2.8h // ((a-b)*-m + 32) >> 6 + add v0.8h, v0.8h, v1.8h + st1 {v0.s}[0], [x0], #4 + st1 {v0.s}[2], [x8], #4 + st1 {v0.h}[2], [x0], x1 + st1 {v0.h}[6], [x8], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + ld1 {v4.8b}, [x5] + sub x1, x1, #8 + neg v4.8b, v4.8b // -m + sxtl v4.8h, v4.8b + shl v4.8h, v4.8h, #9 // -m << 9 +8: + ld1 {v2.8h, v3.8h}, [x2], #32 + ld1 {v0.8h}, [x0] + ld1 {v1.8h}, [x8] + subs w4, w4, #2 + sub v2.8h, v0.8h, v2.8h // a - b + sub v3.8h, v1.8h, v3.8h + sqrdmulh v2.8h, v2.8h, v4.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v3.8h, v3.8h, v4.8h + add v0.8h, v0.8h, v2.8h + add v1.8h, v1.8h, v3.8h + st1 {v0.d}[0], [x0], #8 + st1 {v1.d}[0], [x8], #8 + st1 {v0.s}[2], [x0], x1 + st1 {v1.s}[2], [x8], x1 + b.gt 8b + ret +160: + AARCH64_VALID_JUMP_TARGET + ld1 {v16.16b}, [x5] + sub x1, x1, #16 + neg v17.16b, v16.16b // -m + sxtl v16.8h, v17.8b + sxtl2 v17.8h, v17.16b + shl v16.8h, v16.8h, #9 // -m << 9 + shl v17.4h, v17.4h, #9 +16: + ld1 {v4.8h, v5.8h, v6.8h, v7.8h}, [x2], #64 + ld1 {v0.8h, v1.8h}, [x0] + subs w4, w4, #2 + ld1 {v2.8h, v3.8h}, [x8] + sub v4.8h, v0.8h, v4.8h // a - b + sub v5.4h, v1.4h, v5.4h + sub v6.8h, v2.8h, v6.8h + sub v7.4h, v3.4h, v7.4h + sqrdmulh v4.8h, v4.8h, v16.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v5.4h, v5.4h, v17.4h + sqrdmulh v6.8h, v6.8h, v16.8h + sqrdmulh v7.4h, v7.4h, v17.4h + add v0.8h, v0.8h, v4.8h + add v1.4h, v1.4h, v5.4h + add v2.8h, v2.8h, v6.8h + add v3.4h, v3.4h, v7.4h + st1 {v0.8h}, [x0], #16 + st1 {v2.8h}, [x8], #16 + st1 {v1.4h}, [x0], x1 + st1 {v3.4h}, [x8], x1 + b.gt 16b + ret +320: + AARCH64_VALID_JUMP_TARGET + ld1 {v24.16b, v25.16b}, [x5] + neg v26.16b, v24.16b // -m + neg v27.8b, v25.8b + sxtl v24.8h, v26.8b + sxtl2 v25.8h, v26.16b + sxtl v26.8h, v27.8b + shl v24.8h, v24.8h, #9 // -m << 9 + shl v25.8h, v25.8h, #9 + shl v26.8h, v26.8h, #9 +32: + ld1 {v16.8h, v17.8h, v18.8h, v19.8h}, [x2], #64 + ld1 {v0.8h, v1.8h, v2.8h}, [x0] + ld1 {v20.8h, v21.8h, v22.8h, v23.8h}, [x2], #64 + ld1 {v4.8h, v5.8h, v6.8h}, [x8] + subs w4, w4, #2 + sub v16.8h, v0.8h, v16.8h // a - b + sub v17.8h, v1.8h, v17.8h + sub v18.8h, v2.8h, v18.8h + sub v20.8h, v4.8h, v20.8h + sub v21.8h, v5.8h, v21.8h + sub v22.8h, v6.8h, v22.8h + sqrdmulh v16.8h, v16.8h, v24.8h // ((a-b)*-m + 32) >> 6 + sqrdmulh v17.8h, v17.8h, v25.8h + sqrdmulh v18.8h, v18.8h, v26.8h + sqrdmulh v20.8h, v20.8h, v24.8h + sqrdmulh v21.8h, v21.8h, v25.8h + sqrdmulh v22.8h, v22.8h, v26.8h + add v0.8h, v0.8h, v16.8h + add v1.8h, v1.8h, v17.8h + add v2.8h, v2.8h, v18.8h + add v4.8h, v4.8h, v20.8h + add v5.8h, v5.8h, v21.8h + add v6.8h, v6.8h, v22.8h + st1 {v0.8h, v1.8h, v2.8h}, [x0], x1 + st1 {v4.8h, v5.8h, v6.8h}, [x8], x1 + b.gt 32b + ret +L(blend_v_tbl): + .hword L(blend_v_tbl) - 320b + .hword L(blend_v_tbl) - 160b + .hword L(blend_v_tbl) - 80b + .hword L(blend_v_tbl) - 40b + .hword L(blend_v_tbl) - 20b +endfunc + + +// This has got the same signature as the put_8tap functions, +// and assumes that x9 is set to (clz(w)-24). +function put_neon + adr x10, L(put_tbl) + ldrh w9, [x10, x9, lsl #1] + sub x10, x10, w9, uxtw + br x10 + +2: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.s}[0], [x2], x3 + ld1 {v1.s}[0], [x2], x3 + subs w5, w5, #2 + st1 {v0.s}[0], [x0], x1 + st1 {v1.s}[0], [x0], x1 + b.gt 2b + ret +4: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.4h}, [x2], x3 + ld1 {v1.4h}, [x2], x3 + subs w5, w5, #2 + st1 {v0.4h}, [x0], x1 + st1 {v1.4h}, [x0], x1 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x8, x0, x1 + lsl x1, x1, #1 + add x9, x2, x3 + lsl x3, x3, #1 +8: + ld1 {v0.8h}, [x2], x3 + ld1 {v1.8h}, [x9], x3 + subs w5, w5, #2 + st1 {v0.8h}, [x0], x1 + st1 {v1.8h}, [x8], x1 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + subs w5, w5, #1 + stp x8, x9, [x0, #16] + add x2, x2, x3 + add x0, x0, x1 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x0] + ldp x10, x11, [x2, #32] + stp x8, x9, [x0, #16] + subs w5, w5, #1 + ldp x12, x13, [x2, #48] + stp x10, x11, [x0, #32] + stp x12, x13, [x0, #48] + add x2, x2, x3 + add x0, x0, x1 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x2, x2, x3 + add x0, x0, x1 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x2] + ldp q2, q3, [x2, #32] + stp q0, q1, [x0] + ldp q4, q5, [x2, #64] + stp q2, q3, [x0, #32] + ldp q6, q7, [x2, #96] + subs w5, w5, #1 + stp q4, q5, [x0, #64] + ldp q16, q17, [x2, #128] + stp q6, q7, [x0, #96] + ldp q18, q19, [x2, #160] + stp q16, q17, [x0, #128] + ldp q20, q21, [x2, #192] + stp q18, q19, [x0, #160] + ldp q22, q23, [x2, #224] + stp q20, q21, [x0, #192] + stp q22, q23, [x0, #224] + add x2, x2, x3 + add x0, x0, x1 + b.gt 128b + ret + +L(put_tbl): + .hword L(put_tbl) - 128b + .hword L(put_tbl) - 64b + .hword L(put_tbl) - 32b + .hword L(put_tbl) - 16b + .hword L(put_tbl) - 80b + .hword L(put_tbl) - 4b + .hword L(put_tbl) - 2b +endfunc + + +// This has got the same signature as the prep_8tap functions, +// and assumes that x9 is set to (clz(w)-24), w7 to intermediate_bits and +// x8 to w*2. +function prep_neon + adr x10, L(prep_tbl) + ldrh w9, [x10, x9, lsl #1] + dup v31.8h, w7 // intermediate_bits + movi v30.8h, #(PREP_BIAS >> 8), lsl #8 + sub x10, x10, w9, uxtw + br x10 + +40: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +4: + ld1 {v0.d}[0], [x1], x2 + ld1 {v0.d}[1], [x9], x2 + subs w4, w4, #2 + sshl v0.8h, v0.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + st1 {v0.8h}, [x0], #16 + b.gt 4b + ret +80: + AARCH64_VALID_JUMP_TARGET + add x9, x1, x2 + lsl x2, x2, #1 +8: + ld1 {v0.8h}, [x1], x2 + ld1 {v1.8h}, [x9], x2 + subs w4, w4, #2 + sshl v0.8h, v0.8h, v31.8h + sshl v1.8h, v1.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 8b + ret +16: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + add x1, x1, x2 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1] + add x1, x1, x2 + subs w4, w4, #2 + sshl v1.8h, v1.8h, v31.8h + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 16b + ret +32: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + add x1, x1, x2 + sshl v1.8h, v1.8h, v31.8h + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + subs w4, w4, #1 + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x0], #64 + b.gt 32b + ret +64: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + subs w4, w4, #1 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + sshl v1.8h, v1.8h, v31.8h + ldp q4, q5, [x1, #64] + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + ldp q6, q7, [x1, #96] + add x1, x1, x2 + sshl v4.8h, v4.8h, v31.8h + sshl v5.8h, v5.8h, v31.8h + sshl v6.8h, v6.8h, v31.8h + sshl v7.8h, v7.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + stp q0, q1, [x0] + sub v4.8h, v4.8h, v30.8h + sub v5.8h, v5.8h, v30.8h + stp q2, q3, [x0, #32] + sub v6.8h, v6.8h, v30.8h + sub v7.8h, v7.8h, v30.8h + stp q4, q5, [x0, #64] + stp q6, q7, [x0, #96] + add x0, x0, x8 + b.gt 64b + ret +128: + AARCH64_VALID_JUMP_TARGET + ldp q0, q1, [x1] + subs w4, w4, #1 + sshl v0.8h, v0.8h, v31.8h + ldp q2, q3, [x1, #32] + sshl v1.8h, v1.8h, v31.8h + ldp q4, q5, [x1, #64] + sshl v2.8h, v2.8h, v31.8h + sshl v3.8h, v3.8h, v31.8h + ldp q6, q7, [x1, #96] + sshl v4.8h, v4.8h, v31.8h + sshl v5.8h, v5.8h, v31.8h + ldp q16, q17, [x1, #128] + sshl v6.8h, v6.8h, v31.8h + sshl v7.8h, v7.8h, v31.8h + ldp q18, q19, [x1, #160] + sshl v16.8h, v16.8h, v31.8h + sshl v17.8h, v17.8h, v31.8h + ldp q20, q21, [x1, #192] + sshl v18.8h, v18.8h, v31.8h + sshl v19.8h, v19.8h, v31.8h + ldp q22, q23, [x1, #224] + add x1, x1, x2 + sshl v20.8h, v20.8h, v31.8h + sshl v21.8h, v21.8h, v31.8h + sshl v22.8h, v22.8h, v31.8h + sshl v23.8h, v23.8h, v31.8h + sub v0.8h, v0.8h, v30.8h + sub v1.8h, v1.8h, v30.8h + sub v2.8h, v2.8h, v30.8h + sub v3.8h, v3.8h, v30.8h + stp q0, q1, [x0] + sub v4.8h, v4.8h, v30.8h + sub v5.8h, v5.8h, v30.8h + stp q2, q3, [x0, #32] + sub v6.8h, v6.8h, v30.8h + sub v7.8h, v7.8h, v30.8h + stp q4, q5, [x0, #64] + sub v16.8h, v16.8h, v30.8h + sub v17.8h, v17.8h, v30.8h + stp q6, q7, [x0, #96] + sub v18.8h, v18.8h, v30.8h + sub v19.8h, v19.8h, v30.8h + stp q16, q17, [x0, #128] + sub v20.8h, v20.8h, v30.8h + sub v21.8h, v21.8h, v30.8h + stp q18, q19, [x0, #160] + sub v22.8h, v22.8h, v30.8h + sub v23.8h, v23.8h, v30.8h + stp q20, q21, [x0, #192] + stp q22, q23, [x0, #224] + add x0, x0, x8 + b.gt 128b + ret + +L(prep_tbl): + .hword L(prep_tbl) - 128b + .hword L(prep_tbl) - 64b + .hword L(prep_tbl) - 32b + .hword L(prep_tbl) - 16b + .hword L(prep_tbl) - 80b + .hword L(prep_tbl) - 40b +endfunc + + +.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}[0], [\s0], \strd + ld1 {\d1\wd}[0], [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}[0], [\s0], \strd + ld1 {\d3\wd}[0], [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}[0], [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}[0], [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}[0], [\s0], \strd +.endif +.endm +.macro load_reg s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6 + ld1 {\d0\wd}, [\s0], \strd + ld1 {\d1\wd}, [\s1], \strd +.ifnb \d2 + ld1 {\d2\wd}, [\s0], \strd + ld1 {\d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd}, [\s0], \strd +.endif +.ifnb \d5 + ld1 {\d5\wd}, [\s1], \strd +.endif +.ifnb \d6 + ld1 {\d6\wd}, [\s0], \strd +.endif +.endm +.macro load_regpair s0, s1, strd, wd, d0, d1, d2, d3, d4, d5 + ld1 {\d0\wd, \d1\wd}, [\s0], \strd +.ifnb \d2 + ld1 {\d2\wd, \d3\wd}, [\s1], \strd +.endif +.ifnb \d4 + ld1 {\d4\wd, \d5\wd}, [\s0], \strd +.endif +.endm +.macro load_s s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_slice \s0, \s1, \strd, .s, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_4h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .4h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_8h s0, s1, strd, d0, d1, d2, d3, d4, d5, d6 + load_reg \s0, \s1, \strd, .8h, \d0, \d1, \d2, \d3, \d4, \d5, \d6 +.endm +.macro load_16h s0, s1, strd, d0, d1, d2, d3, d4, d5 + load_regpair \s0, \s1, \strd, .8h, \d0, \d1, \d2, \d3, \d4, \d5 +.endm +.macro interleave_1 wd, r0, r1, r2, r3, r4 + trn1 \r0\wd, \r0\wd, \r1\wd + trn1 \r1\wd, \r1\wd, \r2\wd +.ifnb \r3 + trn1 \r2\wd, \r2\wd, \r3\wd + trn1 \r3\wd, \r3\wd, \r4\wd +.endif +.endm +.macro interleave_1_s r0, r1, r2, r3, r4 + interleave_1 .2s, \r0, \r1, \r2, \r3, \r4 +.endm +.macro umin_h c, wd, r0, r1, r2, r3 + umin \r0\wd, \r0\wd, \c\wd +.ifnb \r1 + umin \r1\wd, \r1\wd, \c\wd +.endif +.ifnb \r2 + umin \r2\wd, \r2\wd, \c\wd + umin \r3\wd, \r3\wd, \c\wd +.endif +.endm +.macro sub_h c, wd, r0, r1, r2, r3 + sub \r0\wd, \r0\wd, \c\wd +.ifnb \r1 + sub \r1\wd, \r1\wd, \c\wd +.endif +.ifnb \r2 + sub \r2\wd, \r2\wd, \c\wd + sub \r3\wd, \r3\wd, \c\wd +.endif +.endm +.macro smull_smlal_4 d, s0, s1, s2, s3 + smull \d\().4s, \s0\().4h, v0.h[0] + smlal \d\().4s, \s1\().4h, v0.h[1] + smlal \d\().4s, \s2\().4h, v0.h[2] + smlal \d\().4s, \s3\().4h, v0.h[3] +.endm +.macro smull2_smlal2_4 d, s0, s1, s2, s3 + smull2 \d\().4s, \s0\().8h, v0.h[0] + smlal2 \d\().4s, \s1\().8h, v0.h[1] + smlal2 \d\().4s, \s2\().8h, v0.h[2] + smlal2 \d\().4s, \s3\().8h, v0.h[3] +.endm +.macro smull_smlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7 + smull \d\().4s, \s0\().4h, v0.h[0] + smlal \d\().4s, \s1\().4h, v0.h[1] + smlal \d\().4s, \s2\().4h, v0.h[2] + smlal \d\().4s, \s3\().4h, v0.h[3] + smlal \d\().4s, \s4\().4h, v0.h[4] + smlal \d\().4s, \s5\().4h, v0.h[5] + smlal \d\().4s, \s6\().4h, v0.h[6] + smlal \d\().4s, \s7\().4h, v0.h[7] +.endm +.macro smull2_smlal2_8 d, s0, s1, s2, s3, s4, s5, s6, s7 + smull2 \d\().4s, \s0\().8h, v0.h[0] + smlal2 \d\().4s, \s1\().8h, v0.h[1] + smlal2 \d\().4s, \s2\().8h, v0.h[2] + smlal2 \d\().4s, \s3\().8h, v0.h[3] + smlal2 \d\().4s, \s4\().8h, v0.h[4] + smlal2 \d\().4s, \s5\().8h, v0.h[5] + smlal2 \d\().4s, \s6\().8h, v0.h[6] + smlal2 \d\().4s, \s7\().8h, v0.h[7] +.endm +.macro sqrshrun_h shift, r0, r1, r2, r3 + sqrshrun \r0\().4h, \r0\().4s, #\shift +.ifnb \r1 + sqrshrun2 \r0\().8h, \r1\().4s, #\shift +.endif +.ifnb \r2 + sqrshrun \r2\().4h, \r2\().4s, #\shift + sqrshrun2 \r2\().8h, \r3\().4s, #\shift +.endif +.endm +.macro xtn_h r0, r1, r2, r3 + uzp1 \r0\().8h, \r0\().8h, \r1\().8h // Same as xtn, xtn2 +.ifnb \r2 + uzp1 \r2\().8h, \r2\().8h, \r3\().8h // Ditto +.endif +.endm +.macro srshl_s shift, r0, r1, r2, r3 + srshl \r0\().4s, \r0\().4s, \shift\().4s + srshl \r1\().4s, \r1\().4s, \shift\().4s +.ifnb \r2 + srshl \r2\().4s, \r2\().4s, \shift\().4s + srshl \r3\().4s, \r3\().4s, \shift\().4s +.endif +.endm +.macro st_s strd, reg, lanes + st1 {\reg\().s}[0], [x0], \strd + st1 {\reg\().s}[1], [x9], \strd +.if \lanes > 2 + st1 {\reg\().s}[2], [x0], \strd + st1 {\reg\().s}[3], [x9], \strd +.endif +.endm +.macro st_d strd, r0, r1 + st1 {\r0\().d}[0], [x0], \strd + st1 {\r0\().d}[1], [x9], \strd +.ifnb \r1 + st1 {\r1\().d}[0], [x0], \strd + st1 {\r1\().d}[1], [x9], \strd +.endif +.endm +.macro shift_store_4 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin_h v31, .8h, \r0, \r2 +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub_h v29, .8h, \r0, \r2 // PREP_BIAS +.endif + st_d \strd, \r0, \r2 +.endm +.macro st_reg strd, wd, r0, r1, r2, r3, r4, r5, r6, r7 + st1 {\r0\wd}, [x0], \strd + st1 {\r1\wd}, [x9], \strd +.ifnb \r2 + st1 {\r2\wd}, [x0], \strd + st1 {\r3\wd}, [x9], \strd +.endif +.ifnb \r4 + st1 {\r4\wd}, [x0], \strd + st1 {\r5\wd}, [x9], \strd + st1 {\r6\wd}, [x0], \strd + st1 {\r7\wd}, [x9], \strd +.endif +.endm +.macro st_8h strd, r0, r1, r2, r3, r4, r5, r6, r7 + st_reg \strd, .8h, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7 +.endm +.macro shift_store_8 type, strd, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin_h v31, .8h, \r0, \r2 +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub_h v29, .8h, \r0, \r2 // PREP_BIAS +.endif + st_8h \strd, \r0, \r2 +.endm +.macro shift_store_16 type, strd, dst, r0, r1, r2, r3 +.ifc \type, put + sqrshrun_h 6, \r0, \r1, \r2, \r3 + umin \r0\().8h, \r0\().8h, v31.8h + umin \r1\().8h, \r2\().8h, v31.8h +.else + srshl_s v30, \r0, \r1, \r2, \r3 // -(6-intermediate_bits) + xtn_h \r0, \r1, \r2, \r3 + sub \r0\().8h, \r0\().8h, v29.8h + sub \r1\().8h, \r2\().8h, v29.8h +.endif + st1 {\r0\().8h, \r1\().8h}, [\dst], \strd +.endm + +.macro make_8tap_fn op, type, type_h, type_v +function \op\()_8tap_\type\()_16bpc_neon, export=1 + mov w9, \type_h + mov w10, \type_v + b \op\()_8tap_neon +endfunc +.endm + +// No spaces in these expressions, due to gas-preprocessor. +#define REGULAR ((0*15<<7)|3*15) +#define SMOOTH ((1*15<<7)|4*15) +#define SHARP ((2*15<<7)|3*15) + +.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, xmx, my, xmy, bdmax, ds2, sr2 +make_8tap_fn \type, regular, REGULAR, REGULAR +make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH +make_8tap_fn \type, regular_sharp, REGULAR, SHARP +make_8tap_fn \type, smooth, SMOOTH, SMOOTH +make_8tap_fn \type, smooth_regular, SMOOTH, REGULAR +make_8tap_fn \type, smooth_sharp, SMOOTH, SHARP +make_8tap_fn \type, sharp, SHARP, SHARP +make_8tap_fn \type, sharp_regular, SHARP, REGULAR +make_8tap_fn \type, sharp_smooth, SHARP, SMOOTH + +function \type\()_8tap_neon +.ifc \bdmax, w8 + ldr w8, [sp] +.endif + mov w11, #0x4081 // (1 << 14) | (1 << 7) | (1 << 0) + mul \mx, \mx, w11 + mul \my, \my, w11 + add \mx, \mx, w9 // mx, 8tap_h, 4tap_h + add \my, \my, w10 // my, 8tap_v, 4tap_v +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + dup v31.8h, \bdmax // bitdepth_max + clz \bdmax, \bdmax + clz w9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + mov w12, #6 + tst \mx, #(0x7f << 14) + sub w9, w9, #24 + add w13, w12, \bdmax // 6 + intermediate_bits + sub w12, w12, \bdmax // 6 - intermediate_bits + movrel x11, X(mc_subpel_filters), -8 + b.ne L(\type\()_8tap_h) + tst \my, #(0x7f << 14) + b.ne L(\type\()_8tap_v) + b \type\()_neon + +L(\type\()_8tap_h): + cmp \w, #4 + ubfx w10, \mx, #7, #7 + and \mx, \mx, #0x7f + b.le 4f + mov \mx, w10 +4: + tst \my, #(0x7f << 14) + add \xmx, x11, \mx, uxtw #3 + b.ne L(\type\()_8tap_hv) + + adr x10, L(\type\()_8tap_h_tbl) + dup v30.4s, w12 // 6 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v30.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + dup v29.8h, \bdmax // intermediate_bits +.else + movi v28.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v29.8h, v29.8h // -intermediate_bits +.endif + br x10 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +2: + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + subs \h, \h, #2 + trn1 v3.2s, v4.2s, v6.2s + trn2 v6.2s, v4.2s, v6.2s + trn1 v4.2s, v5.2s, v7.2s + trn2 v7.2s, v5.2s, v7.2s + smull v3.4s, v3.4h, v0.h[0] + smlal v3.4s, v4.4h, v0.h[1] + smlal v3.4s, v6.4h, v0.h[2] + smlal v3.4s, v7.4h, v0.h[3] + srshl v3.4s, v3.4s, v30.4s // -(6-intermediate_bits) + sqxtun v3.4h, v3.4s + srshl v3.4h, v3.4h, v29.4h // -intermediate_bits + umin v3.4h, v3.4h, v31.4h + st1 {v3.s}[0], [\dst], \d_strd + st1 {v3.s}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + sub \src, \src, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b +4: + ld1 {v16.8h}, [\src], \s_strd + ld1 {v20.8h}, [\sr2], \s_strd + ext v17.16b, v16.16b, v16.16b, #2 + ext v18.16b, v16.16b, v16.16b, #4 + ext v19.16b, v16.16b, v16.16b, #6 + ext v21.16b, v20.16b, v20.16b, #2 + ext v22.16b, v20.16b, v20.16b, #4 + ext v23.16b, v20.16b, v20.16b, #6 + subs \h, \h, #2 + smull v16.4s, v16.4h, v0.h[0] + smlal v16.4s, v17.4h, v0.h[1] + smlal v16.4s, v18.4h, v0.h[2] + smlal v16.4s, v19.4h, v0.h[3] + smull v20.4s, v20.4h, v0.h[0] + smlal v20.4s, v21.4h, v0.h[1] + smlal v20.4s, v22.4h, v0.h[2] + smlal v20.4s, v23.4h, v0.h[3] + srshl v16.4s, v16.4s, v30.4s // -(6-intermediate_bits) + srshl v20.4s, v20.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + sqxtun v16.4h, v16.4s + sqxtun2 v16.8h, v20.4s + srshl v16.8h, v16.8h, v29.8h // -intermediate_bits + umin v16.8h, v16.8h, v31.8h +.else + uzp1 v16.8h, v16.8h, v20.8h // Same as xtn, xtn2 + sub v16.8h, v16.8h, v28.8h // PREP_BIAS +.endif + st1 {v16.d}[0], [\dst], \d_strd + st1 {v16.d}[1], [\ds2], \d_strd + b.gt 4b + ret + +80: +160: +320: +640: +1280: // 8xN, 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + sub \src, \src, #6 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + sub \s_strd, \s_strd, \w, uxtw #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw #1 +.endif +81: + ld1 {v16.8h, v17.8h}, [\src], #32 + ld1 {v20.8h, v21.8h}, [\sr2], #32 + mov \mx, \w + +8: + smull v18.4s, v16.4h, v0.h[0] + smull2 v19.4s, v16.8h, v0.h[0] + smull v22.4s, v20.4h, v0.h[0] + smull2 v23.4s, v20.8h, v0.h[0] +.irpc i, 1234567 + ext v24.16b, v16.16b, v17.16b, #(2*\i) + ext v25.16b, v20.16b, v21.16b, #(2*\i) + smlal v18.4s, v24.4h, v0.h[\i] + smlal2 v19.4s, v24.8h, v0.h[\i] + smlal v22.4s, v25.4h, v0.h[\i] + smlal2 v23.4s, v25.8h, v0.h[\i] +.endr + subs \mx, \mx, #8 + srshl v18.4s, v18.4s, v30.4s // -(6-intermediate_bits) + srshl v19.4s, v19.4s, v30.4s // -(6-intermediate_bits) + srshl v22.4s, v22.4s, v30.4s // -(6-intermediate_bits) + srshl v23.4s, v23.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + sqxtun v18.4h, v18.4s + sqxtun2 v18.8h, v19.4s + sqxtun v22.4h, v22.4s + sqxtun2 v22.8h, v23.4s + srshl v18.8h, v18.8h, v29.8h // -intermediate_bits + srshl v22.8h, v22.8h, v29.8h // -intermediate_bits + umin v18.8h, v18.8h, v31.8h + umin v22.8h, v22.8h, v31.8h +.else + uzp1 v18.8h, v18.8h, v19.8h // Same as xtn, xtn2 + uzp1 v22.8h, v22.8h, v23.8h // Ditto + sub v18.8h, v18.8h, v28.8h // PREP_BIAS + sub v22.8h, v22.8h, v28.8h // PREP_BIAS +.endif + st1 {v18.8h}, [\dst], #16 + st1 {v22.8h}, [\ds2], #16 + b.le 9f + + mov v16.16b, v17.16b + mov v20.16b, v21.16b + ld1 {v17.8h}, [\src], #16 + ld1 {v21.8h}, [\sr2], #16 + b 8b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 81b + ret + +L(\type\()_8tap_h_tbl): + .hword L(\type\()_8tap_h_tbl) - 1280b + .hword L(\type\()_8tap_h_tbl) - 640b + .hword L(\type\()_8tap_h_tbl) - 320b + .hword L(\type\()_8tap_h_tbl) - 160b + .hword L(\type\()_8tap_h_tbl) - 80b + .hword L(\type\()_8tap_h_tbl) - 40b + .hword L(\type\()_8tap_h_tbl) - 20b + .hword 0 + + +L(\type\()_8tap_v): + cmp \h, #4 + ubfx w10, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w10 +4: + add \xmy, x11, \my, uxtw #3 + +.ifc \type, prep + dup v30.4s, w12 // 6 - intermediate_bits + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + adr x10, L(\type\()_8tap_v_tbl) + ldrh w9, [x10, x9, lsl #1] +.ifc \type, prep + neg v30.4s, v30.4s // -(6-intermediate_bits) +.endif + sub x10, x10, w9, uxtw + br x10 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + b.gt 28f + + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + // 2x2 v + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + interleave_1_s v1, v2, v3, v4, v5 + b.gt 24f + smull_smlal_4 v6, v1, v2, v3, v4 + sqrshrun_h 6, v6 + umin_h v31, .8h, v6 + st_s \d_strd, v6, 2 + ret + +24: // 2x4 v + load_s \sr2, \src, \s_strd, v6, v7 + interleave_1_s v5, v6, v7 + smull_smlal_4 v16, v1, v2, v3, v4 + smull_smlal_4 v17, v3, v4, v5, v6 + sqrshrun_h 6, v16, v17 + umin_h v31, .8h, v16 + st_s \d_strd, v16, 4 + ret + +28: // 2x6, 2x8, 2x12, 2x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + sxtl v0.8h, v0.8b + + load_s \src, \sr2, \s_strd, v1, v2, v3, v4, v5, v6, v7 + interleave_1_s v1, v2, v3, v4, v5 + interleave_1_s v5, v6, v7 +216: + subs \h, \h, #4 + load_s \sr2, \src, \s_strd, v16, v17, v18, v19 + interleave_1_s v7, v16, v17, v18, v19 + smull_smlal_8 v24, v1, v2, v3, v4, v5, v6, v7, v16 + smull_smlal_8 v25, v3, v4, v5, v6, v7, v16, v17, v18 + sqrshrun_h 6, v24, v25 + umin_h v31, .8h, v24 + st_s \d_strd, v24, 4 + b.le 0f + cmp \h, #2 + mov v1.16b, v5.16b + mov v2.16b, v6.16b + mov v3.16b, v7.16b + mov v4.16b, v16.16b + mov v5.16b, v17.16b + mov v6.16b, v18.16b + mov v7.16b, v19.16b + b.eq 26f + b 216b +26: + load_s \sr2, \src, \s_strd, v16, v17 + interleave_1_s v7, v16, v17 + smull_smlal_8 v24, v1, v2, v3, v4, v5, v6, v7, v16 + sqrshrun_h 6, v24 + umin_h v31, .4h, v24 + st_s \d_strd, v24, 2 +0: + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + b.gt 480f + + // 4x2, 4x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_4h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + smull_smlal_4 v6, v1, v2, v3, v4 + smull_smlal_4 v7, v2, v3, v4, v5 + shift_store_4 \type, \d_strd, v6, v7 + b.le 0f + load_4h \sr2, \src, \s_strd, v6, v7 + smull_smlal_4 v1, v3, v4, v5, v6 + smull_smlal_4 v2, v4, v5, v6, v7 + shift_store_4 \type, \d_strd, v1, v2 +0: + ret + +480: // 4x6, 4x8, 4x12, 4x16 v + ld1 {v0.8b}, [\xmy] + sub \sr2, \src, \s_strd, lsl #1 + add \ds2, \dst, \d_strd + sub \src, \sr2, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_4h \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + +48: + subs \h, \h, #4 + load_4h \sr2, \src, \s_strd, v23, v24, v25, v26 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v2, v17, v18, v19, v20, v21, v22, v23, v24 + smull_smlal_8 v3, v18, v19, v20, v21, v22, v23, v24, v25 + smull_smlal_8 v4, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_4 \type, \d_strd, v1, v2, v3, v4 + b.le 0f + cmp \h, #2 + mov v16.8b, v20.8b + mov v17.8b, v21.8b + mov v18.8b, v22.8b + mov v19.8b, v23.8b + mov v20.8b, v24.8b + mov v21.8b, v25.8b + mov v22.8b, v26.8b + b.eq 46f + b 48b +46: + load_4h \sr2, \src, \s_strd, v23, v24 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v2, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_4 \type, \d_strd, v1, v2 +0: + ret + +80: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + + // 8x2, 8x4 v + cmp \h, #2 + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + + load_8h \src, \sr2, \s_strd, v1, v2, v3, v4, v5 + smull_smlal_4 v16, v1, v2, v3, v4 + smull2_smlal2_4 v17, v1, v2, v3, v4 + smull_smlal_4 v18, v2, v3, v4, v5 + smull2_smlal2_4 v19, v2, v3, v4, v5 + shift_store_8 \type, \d_strd, v16, v17, v18, v19 + b.le 0f + load_8h \sr2, \src, \s_strd, v6, v7 + smull_smlal_4 v16, v3, v4, v5, v6 + smull2_smlal2_4 v17, v3, v4, v5, v6 + smull_smlal_4 v18, v4, v5, v6, v7 + smull2_smlal2_4 v19, v4, v5, v6, v7 + shift_store_8 \type, \d_strd, v16, v17, v18, v19 +0: + ret + +880: // 8x6, 8x8, 8x16, 8x32 v +1680: // 16x8, 16x16, ... +320: // 32x8, 32x16, ... +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmy] + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + mov \my, \h +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + load_8h \src, \sr2, \s_strd, v16, v17, v18, v19, v20, v21, v22 + +88: + subs \h, \h, #2 + load_8h \sr2, \src, \s_strd, v23, v24 + smull_smlal_8 v1, v16, v17, v18, v19, v20, v21, v22, v23 + smull2_smlal2_8 v2, v16, v17, v18, v19, v20, v21, v22, v23 + smull_smlal_8 v3, v17, v18, v19, v20, v21, v22, v23, v24 + smull2_smlal2_8 v4, v17, v18, v19, v20, v21, v22, v23, v24 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.le 9f + subs \h, \h, #2 + load_8h \sr2, \src, \s_strd, v25, v26 + smull_smlal_8 v1, v18, v19, v20, v21, v22, v23, v24, v25 + smull2_smlal2_8 v2, v18, v19, v20, v21, v22, v23, v24, v25 + smull_smlal_8 v3, v19, v20, v21, v22, v23, v24, v25, v26 + smull2_smlal2_8 v4, v19, v20, v21, v22, v23, v24, v25, v26 + shift_store_8 \type, \d_strd, v1, v2, v3, v4 + b.le 9f + mov v16.16b, v20.16b + mov v17.16b, v21.16b + mov v18.16b, v22.16b + mov v19.16b, v23.16b + mov v20.16b, v24.16b + mov v21.16b, v25.16b + mov v22.16b, v26.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + ret + +160: + AARCH64_VALID_JUMP_TARGET + b.gt 1680b + + // 16x2, 16x4 v + add \xmy, \xmy, #2 + ld1 {v0.s}[0], [\xmy] + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + + load_16h \src, \src, \s_strd, v16, v17, v18, v19, v20, v21 +16: + load_16h \src, \src, \s_strd, v22, v23 + subs \h, \h, #1 + smull_smlal_4 v1, v16, v18, v20, v22 + smull2_smlal2_4 v2, v16, v18, v20, v22 + smull_smlal_4 v3, v17, v19, v21, v23 + smull2_smlal2_4 v4, v17, v19, v21, v23 + shift_store_16 \type, \d_strd, x0, v1, v2, v3, v4 + b.le 0f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v23.16b + b 16b +0: + ret + +L(\type\()_8tap_v_tbl): + .hword L(\type\()_8tap_v_tbl) - 1280b + .hword L(\type\()_8tap_v_tbl) - 640b + .hword L(\type\()_8tap_v_tbl) - 320b + .hword L(\type\()_8tap_v_tbl) - 160b + .hword L(\type\()_8tap_v_tbl) - 80b + .hword L(\type\()_8tap_v_tbl) - 40b + .hword L(\type\()_8tap_v_tbl) - 20b + .hword 0 + +L(\type\()_8tap_hv): + cmp \h, #4 + ubfx w10, \my, #7, #7 + and \my, \my, #0x7f + b.le 4f + mov \my, w10 +4: + add \xmy, x11, \my, uxtw #3 + + adr x10, L(\type\()_8tap_hv_tbl) + dup v30.4s, w12 // 6 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v30.4s, v30.4s // -(6-intermediate_bits) +.ifc \type, put + dup v29.4s, w13 // 6 + intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v29.4s, v29.4s // -(6+intermediate_bits) +.endif + br x10 + +20: + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 280f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + + // 2x2, 2x4 hv + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v27.8h}, [\src], \s_strd + ext v28.16b, v27.16b, v27.16b, #2 + smull v27.4s, v27.4h, v0.4h + smull v28.4s, v28.4h, v0.4h + addp v27.4s, v27.4s, v28.4s + addp v16.4s, v27.4s, v27.4s + srshl v16.2s, v16.2s, v30.2s // -(6-intermediate_bits) + bl L(\type\()_8tap_filter_2) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + trn1 v16.2s, v16.2s, v24.2s + mov v17.8b, v24.8b + +2: + bl L(\type\()_8tap_filter_2) + + ext v18.8b, v17.8b, v24.8b, #4 + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + umin v2.4h, v2.4h, v31.4h + subs \h, \h, #2 + st1 {v2.s}[0], [\dst], \d_strd + st1 {v2.s}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v24.8b + b 2b + +280: // 2x8, 2x16, 2x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v27.8h}, [\src], \s_strd + ext v28.16b, v27.16b, v27.16b, #2 + smull v27.4s, v27.4h, v0.4h + smull v28.4s, v28.4h, v0.4h + addp v27.4s, v27.4s, v28.4s + addp v16.4s, v27.4s, v27.4s + srshl v16.2s, v16.2s, v30.2s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + + bl L(\type\()_8tap_filter_2) + xtn v16.4h, v16.4s + trn1 v16.2s, v16.2s, v24.2s + mov v17.8b, v24.8b + bl L(\type\()_8tap_filter_2) + ext v18.8b, v17.8b, v24.8b, #4 + mov v19.8b, v24.8b + bl L(\type\()_8tap_filter_2) + ext v20.8b, v19.8b, v24.8b, #4 + mov v21.8b, v24.8b + +28: + bl L(\type\()_8tap_filter_2) + ext v22.8b, v21.8b, v24.8b, #4 + smull v3.4s, v16.4h, v1.h[0] + smlal v3.4s, v17.4h, v1.h[1] + smlal v3.4s, v18.4h, v1.h[2] + smlal v3.4s, v19.4h, v1.h[3] + smlal v3.4s, v20.4h, v1.h[4] + smlal v3.4s, v21.4h, v1.h[5] + smlal v3.4s, v22.4h, v1.h[6] + smlal v3.4s, v24.4h, v1.h[7] + + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + sqxtun v3.4h, v3.4s + umin v3.4h, v3.4h, v31.4h + subs \h, \h, #2 + st1 {v3.s}[0], [\dst], \d_strd + st1 {v3.s}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v24.8b + b 28b + +0: + ret x15 + +L(\type\()_8tap_filter_2): + ld1 {v25.8h}, [\sr2], \s_strd + ld1 {v27.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v28.16b, v27.16b, v27.16b, #2 + trn1 v24.2s, v25.2s, v27.2s + trn2 v27.2s, v25.2s, v27.2s + trn1 v25.2s, v26.2s, v28.2s + trn2 v28.2s, v26.2s, v28.2s + smull v24.4s, v24.4h, v0.h[0] + smlal v24.4s, v25.4h, v0.h[1] + smlal v24.4s, v27.4h, v0.h[2] + smlal v24.4s, v28.4h, v0.h[3] + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + xtn v24.4h, v24.4s + ret +.endif + +40: + AARCH64_VALID_JUMP_TARGET + add \xmx, \xmx, #2 + ld1 {v0.s}[0], [\xmx] + b.gt 480f + add \xmy, \xmy, #2 + ld1 {v1.s}[0], [\xmy] + sub \sr2, \src, #2 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + // 4x2, 4x4 hv + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v16.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v24.8b + mov v18.8b, v25.8b + +4: + bl L(\type\()_8tap_filter_4) + smull v2.4s, v16.4h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal v2.4s, v24.4h, v1.h[3] + smull v3.4s, v17.4h, v1.h[0] + smlal v3.4s, v18.4h, v1.h[1] + smlal v3.4s, v24.4h, v1.h[2] + smlal v3.4s, v25.4h, v1.h[3] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + umin v2.8h, v2.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + + st1 {v2.d}[0], [\dst], \d_strd + st1 {v2.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v24.8b + mov v18.8b, v25.8b + b 4b + +480: // 4x8, 4x16, 4x32 hv + ld1 {v1.8b}, [\xmy] + sub \src, \src, #2 + sub \sr2, \src, \s_strd, lsl #1 + sub \src, \sr2, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v16.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53). + xtn v16.4h, v16.4s + + bl L(\type\()_8tap_filter_4) + mov v17.8b, v24.8b + mov v18.8b, v25.8b + bl L(\type\()_8tap_filter_4) + mov v19.8b, v24.8b + mov v20.8b, v25.8b + bl L(\type\()_8tap_filter_4) + mov v21.8b, v24.8b + mov v22.8b, v25.8b + +48: + bl L(\type\()_8tap_filter_4) + smull v3.4s, v16.4h, v1.h[0] + smlal v3.4s, v17.4h, v1.h[1] + smlal v3.4s, v18.4h, v1.h[2] + smlal v3.4s, v19.4h, v1.h[3] + smlal v3.4s, v20.4h, v1.h[4] + smlal v3.4s, v21.4h, v1.h[5] + smlal v3.4s, v22.4h, v1.h[6] + smlal v3.4s, v24.4h, v1.h[7] + smull v4.4s, v17.4h, v1.h[0] + smlal v4.4s, v18.4h, v1.h[1] + smlal v4.4s, v19.4h, v1.h[2] + smlal v4.4s, v20.4h, v1.h[3] + smlal v4.4s, v21.4h, v1.h[4] + smlal v4.4s, v22.4h, v1.h[5] + smlal v4.4s, v24.4h, v1.h[6] + smlal v4.4s, v25.4h, v1.h[7] +.ifc \type, put + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + sqxtun v3.4h, v3.4s + sqxtun2 v3.8h, v4.4s + umin v3.8h, v3.8h, v31.8h +.else + rshrn v3.4h, v3.4s, #6 + rshrn2 v3.8h, v4.4s, #6 + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v3.d}[0], [\dst], \d_strd + st1 {v3.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + mov v17.8b, v19.8b + mov v18.8b, v20.8b + mov v19.8b, v21.8b + mov v20.8b, v22.8b + mov v21.8b, v24.8b + mov v22.8b, v25.8b + b 48b +0: + ret x15 + +L(\type\()_8tap_filter_4): + ld1 {v24.8h}, [\sr2], \s_strd + ld1 {v25.8h}, [\src], \s_strd + ext v26.16b, v24.16b, v24.16b, #2 + ext v27.16b, v24.16b, v24.16b, #4 + ext v28.16b, v24.16b, v24.16b, #6 + smull v24.4s, v24.4h, v0.h[0] + smlal v24.4s, v26.4h, v0.h[1] + smlal v24.4s, v27.4h, v0.h[2] + smlal v24.4s, v28.4h, v0.h[3] + ext v26.16b, v25.16b, v25.16b, #2 + ext v27.16b, v25.16b, v25.16b, #4 + ext v28.16b, v25.16b, v25.16b, #6 + smull v25.4s, v25.4h, v0.h[0] + smlal v25.4s, v26.4h, v0.h[1] + smlal v25.4s, v27.4h, v0.h[2] + smlal v25.4s, v28.4h, v0.h[3] + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + xtn v24.4h, v24.4s + xtn v25.4h, v25.4s + ret + +80: +160: +320: + AARCH64_VALID_JUMP_TARGET + b.gt 880f + add \xmy, \xmy, #2 + ld1 {v0.8b}, [\xmx] + ld1 {v1.s}[0], [\xmy] + sub \src, \src, #6 + sub \src, \src, \s_strd + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +164: // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + ld1 {v27.8h, v28.8h}, [\src], \s_strd + smull v24.4s, v27.4h, v0.h[0] + smull2 v25.4s, v27.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v27.16b, v28.16b, #(2*\i) + smlal v24.4s, v26.4h, v0.h[\i] + smlal2 v25.4s, v26.8h, v0.h[\i] +.endr + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53), + // and conserves register space (no need to clobber v8-v15). + uzp1 v16.8h, v24.8h, v25.8h // Same as xtn, xtn2 + + bl L(\type\()_8tap_filter_8) + mov v17.16b, v23.16b + mov v18.16b, v24.16b + +8: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v23.4h, v1.h[2] + smlal2 v5.4s, v23.8h, v1.h[2] + smlal v2.4s, v23.4h, v1.h[3] + smlal2 v3.4s, v23.8h, v1.h[3] + smlal v4.4s, v24.4h, v1.h[3] + smlal2 v5.4s, v24.8h, v1.h[3] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + srshl v5.4s, v5.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v31.8h + umin v3.8h, v3.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v2.8h}, [\dst], \d_strd + st1 {v3.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v23.16b + mov v18.16b, v24.16b + b 8b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #2 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 164b + +880: // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv +640: +1280: + AARCH64_VALID_JUMP_TARGET + ld1 {v0.8b}, [\xmx] + ld1 {v1.8b}, [\xmy] + sub \src, \src, #6 + sub \src, \src, \s_strd + sub \src, \src, \s_strd, lsl #1 + sxtl v0.8h, v0.8b + sxtl v1.8h, v1.8b + mov x15, x30 + mov \my, \h + +168: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 + + ld1 {v27.8h, v28.8h}, [\src], \s_strd + smull v24.4s, v27.4h, v0.h[0] + smull2 v25.4s, v27.8h, v0.h[0] +.irpc i, 1234567 + ext v26.16b, v27.16b, v28.16b, #(2*\i) + smlal v24.4s, v26.4h, v0.h[\i] + smlal2 v25.4s, v26.8h, v0.h[\i] +.endr + srshl v24.4s, v24.4s, v30.4s // -(6-intermediate_bits) + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + // The intermediates from the horizontal pass fit in 16 bit without + // any bias; we could just as well keep them as .4s, but narrowing + // them to .4h gives a significant speedup on out of order cores + // (at the cost of a smaller slowdown on in-order cores such as A53), + // and conserves register space (no need to clobber v8-v15). + uzp1 v16.8h, v24.8h, v25.8h // Same as xtn, xtn2 + + bl L(\type\()_8tap_filter_8) + mov v17.16b, v23.16b + mov v18.16b, v24.16b + bl L(\type\()_8tap_filter_8) + mov v19.16b, v23.16b + mov v20.16b, v24.16b + bl L(\type\()_8tap_filter_8) + mov v21.16b, v23.16b + mov v22.16b, v24.16b + +88: + smull v2.4s, v16.4h, v1.h[0] + smull2 v3.4s, v16.8h, v1.h[0] + bl L(\type\()_8tap_filter_8) + smull v4.4s, v17.4h, v1.h[0] + smull2 v5.4s, v17.8h, v1.h[0] + smlal v2.4s, v17.4h, v1.h[1] + smlal2 v3.4s, v17.8h, v1.h[1] + smlal v4.4s, v18.4h, v1.h[1] + smlal2 v5.4s, v18.8h, v1.h[1] + smlal v2.4s, v18.4h, v1.h[2] + smlal2 v3.4s, v18.8h, v1.h[2] + smlal v4.4s, v19.4h, v1.h[2] + smlal2 v5.4s, v19.8h, v1.h[2] + smlal v2.4s, v19.4h, v1.h[3] + smlal2 v3.4s, v19.8h, v1.h[3] + smlal v4.4s, v20.4h, v1.h[3] + smlal2 v5.4s, v20.8h, v1.h[3] + smlal v2.4s, v20.4h, v1.h[4] + smlal2 v3.4s, v20.8h, v1.h[4] + smlal v4.4s, v21.4h, v1.h[4] + smlal2 v5.4s, v21.8h, v1.h[4] + smlal v2.4s, v21.4h, v1.h[5] + smlal2 v3.4s, v21.8h, v1.h[5] + smlal v4.4s, v22.4h, v1.h[5] + smlal2 v5.4s, v22.8h, v1.h[5] + smlal v2.4s, v22.4h, v1.h[6] + smlal2 v3.4s, v22.8h, v1.h[6] + smlal v4.4s, v23.4h, v1.h[6] + smlal2 v5.4s, v23.8h, v1.h[6] + smlal v2.4s, v23.4h, v1.h[7] + smlal2 v3.4s, v23.8h, v1.h[7] + smlal v4.4s, v24.4h, v1.h[7] + smlal2 v5.4s, v24.8h, v1.h[7] +.ifc \type, put + srshl v2.4s, v2.4s, v29.4s // -(6+intermediate_bits) + srshl v3.4s, v3.4s, v29.4s // -(6+intermediate_bits) + srshl v4.4s, v4.4s, v29.4s // -(6+intermediate_bits) + srshl v5.4s, v5.4s, v29.4s // -(6+intermediate_bits) + sqxtun v2.4h, v2.4s + sqxtun2 v2.8h, v3.4s + sqxtun v3.4h, v4.4s + sqxtun2 v3.8h, v5.4s + umin v2.8h, v2.8h, v31.8h + umin v3.8h, v3.8h, v31.8h +.else + rshrn v2.4h, v2.4s, #6 + rshrn2 v2.8h, v3.4s, #6 + rshrn v3.4h, v4.4s, #6 + rshrn2 v3.8h, v5.4s, #6 + sub v2.8h, v2.8h, v29.8h // PREP_BIAS + sub v3.8h, v3.8h, v29.8h // PREP_BIAS +.endif + subs \h, \h, #2 + st1 {v2.8h}, [\dst], \d_strd + st1 {v3.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + mov v17.16b, v19.16b + mov v18.16b, v20.16b + mov v19.16b, v21.16b + mov v20.16b, v22.16b + mov v21.16b, v23.16b + mov v22.16b, v24.16b + b 88b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #3 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 168b +0: + ret x15 + +L(\type\()_8tap_filter_8): + ld1 {v4.8h, v5.8h}, [\sr2], \s_strd + ld1 {v6.8h, v7.8h}, [\src], \s_strd + smull v25.4s, v4.4h, v0.h[0] + smull2 v26.4s, v4.8h, v0.h[0] + smull v27.4s, v6.4h, v0.h[0] + smull2 v28.4s, v6.8h, v0.h[0] +.irpc i, 1234567 + ext v23.16b, v4.16b, v5.16b, #(2*\i) + ext v24.16b, v6.16b, v7.16b, #(2*\i) + smlal v25.4s, v23.4h, v0.h[\i] + smlal2 v26.4s, v23.8h, v0.h[\i] + smlal v27.4s, v24.4h, v0.h[\i] + smlal2 v28.4s, v24.8h, v0.h[\i] +.endr + srshl v25.4s, v25.4s, v30.4s // -(6-intermediate_bits) + srshl v26.4s, v26.4s, v30.4s // -(6-intermediate_bits) + srshl v27.4s, v27.4s, v30.4s // -(6-intermediate_bits) + srshl v28.4s, v28.4s, v30.4s // -(6-intermediate_bits) + uzp1 v23.8h, v25.8h, v26.8h // Same as xtn, xtn2 + uzp1 v24.8h, v27.8h, v28.8h // Ditto + ret + +L(\type\()_8tap_hv_tbl): + .hword L(\type\()_8tap_hv_tbl) - 1280b + .hword L(\type\()_8tap_hv_tbl) - 640b + .hword L(\type\()_8tap_hv_tbl) - 320b + .hword L(\type\()_8tap_hv_tbl) - 160b + .hword L(\type\()_8tap_hv_tbl) - 80b + .hword L(\type\()_8tap_hv_tbl) - 40b + .hword L(\type\()_8tap_hv_tbl) - 20b + .hword 0 +endfunc + + +function \type\()_bilin_16bpc_neon, export=1 +.ifc \bdmax, w8 + ldr w8, [sp] +.endif + dup v1.8h, \mx + dup v3.8h, \my + mov w10, #16 + sub w9, w10, \mx + sub w10, w10, \my + dup v0.8h, w9 + dup v2.8h, w10 +.ifc \type, prep + uxtw \d_strd, \w + lsl \d_strd, \d_strd, #1 +.endif + + clz \bdmax, \bdmax // bitdepth_max + clz w9, \w + sub \bdmax, \bdmax, #18 // intermediate_bits = clz(bitdepth_max) - 18 + mov w11, #4 + sub w9, w9, #24 + sub w11, w11, \bdmax // 4 - intermediate_bits + add w12, \bdmax, #4 // 4 + intermediate_bits + cbnz \mx, L(\type\()_bilin_h) + cbnz \my, L(\type\()_bilin_v) + b \type\()_neon + +L(\type\()_bilin_h): + cbnz \my, L(\type\()_bilin_hv) + + adr x10, L(\type\()_bilin_h_tbl) + dup v31.8h, w11 // 4 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v31.8h, v31.8h // -(4-intermediate_bits) +.ifc \type, put + dup v30.8h, \bdmax // intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v30.8h, v30.8h // -intermediate_bits +.endif + br x10 + +20: // 2xN h + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +2: + ld1 {v4.4h}, [\src], \s_strd + ld1 {v6.4h}, [\sr2], \s_strd + ext v5.8b, v4.8b, v4.8b, #2 + ext v7.8b, v6.8b, v6.8b, #2 + trn1 v4.2s, v4.2s, v6.2s + trn1 v5.2s, v5.2s, v7.2s + subs \h, \h, #2 + mul v4.4h, v4.4h, v0.4h + mla v4.4h, v5.4h, v1.4h + urshl v4.4h, v4.4h, v31.4h + urshl v4.4h, v4.4h, v30.4h + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + b.gt 2b + ret +.endif + +40: // 4xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +4: + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v4.16b, #2 + ext v7.16b, v6.16b, v6.16b, #2 + trn1 v4.2d, v4.2d, v6.2d + trn1 v5.2d, v5.2d, v7.2d + subs \h, \h, #2 + mul v4.8h, v4.8h, v0.8h + mla v4.8h, v5.8h, v1.8h + urshl v4.8h, v4.8h, v31.8h +.ifc \type, put + urshl v4.8h, v4.8h, v30.8h +.else + sub v4.8h, v4.8h, v29.8h +.endif + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.gt 4b + ret + +80: // 8xN h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \d_strd, \d_strd, #1 + lsl \s_strd, \s_strd, #1 +8: + ldr h5, [\src, #16] + ldr h7, [\sr2, #16] + ld1 {v4.8h}, [\src], \s_strd + ld1 {v6.8h}, [\sr2], \s_strd + ext v5.16b, v4.16b, v5.16b, #2 + ext v7.16b, v6.16b, v7.16b, #2 + subs \h, \h, #2 + mul v4.8h, v4.8h, v0.8h + mla v4.8h, v5.8h, v1.8h + mul v6.8h, v6.8h, v0.8h + mla v6.8h, v7.8h, v1.8h + urshl v4.8h, v4.8h, v31.8h + urshl v6.8h, v6.8h, v31.8h +.ifc \type, put + urshl v4.8h, v4.8h, v30.8h + urshl v6.8h, v6.8h, v30.8h +.else + sub v4.8h, v4.8h, v29.8h + sub v6.8h, v6.8h, v29.8h +.endif + st1 {v4.8h}, [\dst], \d_strd + st1 {v6.8h}, [\ds2], \d_strd + b.gt 8b + ret +160: +320: +640: +1280: // 16xN, 32xN, ... h + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + + sub \s_strd, \s_strd, \w, uxtw #1 + sub \s_strd, \s_strd, #16 +.ifc \type, put + lsl \d_strd, \d_strd, #1 + sub \d_strd, \d_strd, \w, uxtw #1 +.endif +161: + ld1 {v16.8h}, [\src], #16 + ld1 {v21.8h}, [\sr2], #16 + mov \mx, \w + +16: + ld1 {v17.8h, v18.8h}, [\src], #32 + ld1 {v22.8h, v23.8h}, [\sr2], #32 + ext v19.16b, v16.16b, v17.16b, #2 + ext v20.16b, v17.16b, v18.16b, #2 + ext v24.16b, v21.16b, v22.16b, #2 + ext v25.16b, v22.16b, v23.16b, #2 + mul v16.8h, v16.8h, v0.8h + mla v16.8h, v19.8h, v1.8h + mul v17.8h, v17.8h, v0.8h + mla v17.8h, v20.8h, v1.8h + mul v21.8h, v21.8h, v0.8h + mla v21.8h, v24.8h, v1.8h + mul v22.8h, v22.8h, v0.8h + mla v22.8h, v25.8h, v1.8h + urshl v16.8h, v16.8h, v31.8h + urshl v17.8h, v17.8h, v31.8h + urshl v21.8h, v21.8h, v31.8h + urshl v22.8h, v22.8h, v31.8h + subs \mx, \mx, #16 +.ifc \type, put + urshl v16.8h, v16.8h, v30.8h + urshl v17.8h, v17.8h, v30.8h + urshl v21.8h, v21.8h, v30.8h + urshl v22.8h, v22.8h, v30.8h +.else + sub v16.8h, v16.8h, v29.8h + sub v17.8h, v17.8h, v29.8h + sub v21.8h, v21.8h, v29.8h + sub v22.8h, v22.8h, v29.8h +.endif + st1 {v16.8h, v17.8h}, [\dst], #32 + st1 {v21.8h, v22.8h}, [\ds2], #32 + b.le 9f + + mov v16.16b, v18.16b + mov v21.16b, v23.16b + b 16b + +9: + add \dst, \dst, \d_strd + add \ds2, \ds2, \d_strd + add \src, \src, \s_strd + add \sr2, \sr2, \s_strd + + subs \h, \h, #2 + b.gt 161b + ret + +L(\type\()_bilin_h_tbl): + .hword L(\type\()_bilin_h_tbl) - 1280b + .hword L(\type\()_bilin_h_tbl) - 640b + .hword L(\type\()_bilin_h_tbl) - 320b + .hword L(\type\()_bilin_h_tbl) - 160b + .hword L(\type\()_bilin_h_tbl) - 80b + .hword L(\type\()_bilin_h_tbl) - 40b + .hword L(\type\()_bilin_h_tbl) - 20b + .hword 0 + + +L(\type\()_bilin_v): + cmp \h, #4 + adr x10, L(\type\()_bilin_v_tbl) +.ifc \type, prep + dup v31.8h, w11 // 4 - intermediate_bits +.endif + ldrh w9, [x10, x9, lsl #1] +.ifc \type, prep + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 + neg v31.8h, v31.8h // -(4-intermediate_bits) +.endif + sub x10, x10, w9, uxtw + br x10 + +20: // 2xN v + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + cmp \h, #2 + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + // 2x2 v + ld1 {v16.s}[0], [\src], \s_strd + b.gt 24f +22: + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + mul v4.4h, v16.4h, v2.4h + mla v4.4h, v17.4h, v3.4h + urshr v4.8h, v4.8h, #4 + st1 {v4.s}[0], [\dst] + st1 {v4.s}[1], [\ds2] + ret +24: // 2x4, 2x6, 2x8, ... v + ld1 {v17.s}[0], [\sr2], \s_strd + ld1 {v18.s}[0], [\src], \s_strd + ld1 {v19.s}[0], [\sr2], \s_strd + ld1 {v20.s}[0], [\src], \s_strd + sub \h, \h, #4 + trn1 v16.2s, v16.2s, v17.2s + trn1 v17.2s, v17.2s, v18.2s + trn1 v18.2s, v18.2s, v19.2s + trn1 v19.2s, v19.2s, v20.2s + trn1 v16.2d, v16.2d, v18.2d + trn1 v17.2d, v17.2d, v19.2d + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + cmp \h, #2 + urshr v4.8h, v4.8h, #4 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + st1 {v4.s}[2], [\dst], \d_strd + st1 {v4.s}[3], [\ds2], \d_strd + b.lt 0f + mov v16.8b, v20.8b + b.eq 22b + b 24b +0: + ret +.endif + +40: // 4xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.4h}, [\src], \s_strd +4: + ld1 {v17.4h}, [\sr2], \s_strd + ld1 {v18.4h}, [\src], \s_strd + trn1 v16.2d, v16.2d, v17.2d + trn1 v17.2d, v17.2d, v18.2d + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + sub v4.8h, v4.8h, v29.8h +.endif + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.le 0f + mov v16.8b, v18.8b + b 4b +0: + ret + +80: // 8xN v + AARCH64_VALID_JUMP_TARGET + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + ld1 {v16.8h}, [\src], \s_strd +8: + ld1 {v17.8h}, [\sr2], \s_strd + ld1 {v18.8h}, [\src], \s_strd + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v17.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v18.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + urshl v5.8h, v5.8h, v31.8h + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h +.endif + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd + b.le 0f + mov v16.16b, v18.16b + b 8b +0: + ret + +160: // 16xN, 32xN, ... +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h +1: + add \ds2, \dst, \d_strd + add \sr2, \src, \s_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v16.8h, v17.8h}, [\src], \s_strd +2: + ld1 {v18.8h, v19.8h}, [\sr2], \s_strd + ld1 {v20.8h, v21.8h}, [\src], \s_strd + mul v4.8h, v16.8h, v2.8h + mla v4.8h, v18.8h, v3.8h + mul v5.8h, v17.8h, v2.8h + mla v5.8h, v19.8h, v3.8h + mul v6.8h, v18.8h, v2.8h + mla v6.8h, v20.8h, v3.8h + mul v7.8h, v19.8h, v2.8h + mla v7.8h, v21.8h, v3.8h + subs \h, \h, #2 +.ifc \type, put + urshr v4.8h, v4.8h, #4 + urshr v5.8h, v5.8h, #4 + urshr v6.8h, v6.8h, #4 + urshr v7.8h, v7.8h, #4 +.else + urshl v4.8h, v4.8h, v31.8h + urshl v5.8h, v5.8h, v31.8h + urshl v6.8h, v6.8h, v31.8h + urshl v7.8h, v7.8h, v31.8h + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h + sub v6.8h, v6.8h, v29.8h + sub v7.8h, v7.8h, v29.8h +.endif + st1 {v4.8h, v5.8h}, [\dst], \d_strd + st1 {v6.8h, v7.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v20.16b + mov v17.16b, v21.16b + b 2b +9: + subs \w, \w, #16 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #32 + add \dst, \dst, #32 + b 1b +0: + ret + +L(\type\()_bilin_v_tbl): + .hword L(\type\()_bilin_v_tbl) - 1280b + .hword L(\type\()_bilin_v_tbl) - 640b + .hword L(\type\()_bilin_v_tbl) - 320b + .hword L(\type\()_bilin_v_tbl) - 160b + .hword L(\type\()_bilin_v_tbl) - 80b + .hword L(\type\()_bilin_v_tbl) - 40b + .hword L(\type\()_bilin_v_tbl) - 20b + .hword 0 + +L(\type\()_bilin_hv): + adr x10, L(\type\()_bilin_hv_tbl) + dup v31.8h, w11 // 4 - intermediate_bits + ldrh w9, [x10, x9, lsl #1] + neg v31.8h, v31.8h // -(4-intermediate_bits) +.ifc \type, put + dup v30.4s, w12 // 4 + intermediate_bits +.else + movi v29.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + sub x10, x10, w9, uxtw +.ifc \type, put + neg v30.4s, v30.4s // -(4+intermediate_bits) +.endif + br x10 + +20: // 2xN hv + AARCH64_VALID_JUMP_TARGET +.ifc \type, put + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v20.4h}, [\src], \s_strd + ext v21.8b, v20.8b, v20.8b, #2 + mul v16.4h, v20.4h, v0.4h + mla v16.4h, v21.4h, v1.4h + urshl v16.4h, v16.4h, v31.4h + +2: + ld1 {v22.4h}, [\sr2], \s_strd + ld1 {v24.4h}, [\src], \s_strd + ext v23.8b, v22.8b, v22.8b, #2 + ext v25.8b, v24.8b, v24.8b, #2 + trn1 v22.2s, v22.2s, v24.2s + trn1 v23.2s, v23.2s, v25.2s + mul v17.4h, v22.4h, v0.4h + mla v17.4h, v23.4h, v1.4h + urshl v17.4h, v17.4h, v31.4h + + trn1 v16.2s, v16.2s, v17.2s + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + urshl v4.4s, v4.4s, v30.4s + xtn v4.4h, v4.4s + subs \h, \h, #2 + st1 {v4.s}[0], [\dst], \d_strd + st1 {v4.s}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2s, v17.2s, v17.2s + b 2b +0: + ret +.endif + +40: // 4xN hv + AARCH64_VALID_JUMP_TARGET + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ld1 {v20.8h}, [\src], \s_strd + ext v21.16b, v20.16b, v20.16b, #2 + mul v16.4h, v20.4h, v0.4h + mla v16.4h, v21.4h, v1.4h + urshl v16.4h, v16.4h, v31.4h + +4: + ld1 {v22.8h}, [\sr2], \s_strd + ld1 {v24.8h}, [\src], \s_strd + ext v23.16b, v22.16b, v22.16b, #2 + ext v25.16b, v24.16b, v24.16b, #2 + trn1 v22.2d, v22.2d, v24.2d + trn1 v23.2d, v23.2d, v25.2d + mul v17.8h, v22.8h, v0.8h + mla v17.8h, v23.8h, v1.8h + urshl v17.8h, v17.8h, v31.8h + + trn1 v16.2d, v16.2d, v17.2d + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + umull2 v5.4s, v16.8h, v2.8h + umlal2 v5.4s, v17.8h, v3.8h +.ifc \type, put + urshl v4.4s, v4.4s, v30.4s + urshl v5.4s, v5.4s, v30.4s + uzp1 v4.8h, v4.8h, v5.8h // Same as xtn, xtn2 +.else + rshrn v4.4h, v4.4s, #4 + rshrn2 v4.8h, v5.4s, #4 + sub v4.8h, v4.8h, v29.8h +.endif + subs \h, \h, #2 + st1 {v4.d}[0], [\dst], \d_strd + st1 {v4.d}[1], [\ds2], \d_strd + b.le 0f + trn2 v16.2d, v17.2d, v17.2d + b 4b +0: + ret + +80: // 8xN, 16xN, ... hv +160: +320: +640: +1280: + AARCH64_VALID_JUMP_TARGET + mov \my, \h + +1: + add \sr2, \src, \s_strd + add \ds2, \dst, \d_strd + lsl \s_strd, \s_strd, #1 + lsl \d_strd, \d_strd, #1 + + ldr h21, [\src, #16] + ld1 {v20.8h}, [\src], \s_strd + ext v21.16b, v20.16b, v21.16b, #2 + mul v16.8h, v20.8h, v0.8h + mla v16.8h, v21.8h, v1.8h + urshl v16.8h, v16.8h, v31.8h + +2: + ldr h23, [\sr2, #16] + ld1 {v22.8h}, [\sr2], \s_strd + ldr h25, [\src, #16] + ld1 {v24.8h}, [\src], \s_strd + ext v23.16b, v22.16b, v23.16b, #2 + ext v25.16b, v24.16b, v25.16b, #2 + mul v17.8h, v22.8h, v0.8h + mla v17.8h, v23.8h, v1.8h + mul v18.8h, v24.8h, v0.8h + mla v18.8h, v25.8h, v1.8h + urshl v17.8h, v17.8h, v31.8h + urshl v18.8h, v18.8h, v31.8h + + umull v4.4s, v16.4h, v2.4h + umlal v4.4s, v17.4h, v3.4h + umull2 v5.4s, v16.8h, v2.8h + umlal2 v5.4s, v17.8h, v3.8h + umull v6.4s, v17.4h, v2.4h + umlal v6.4s, v18.4h, v3.4h + umull2 v7.4s, v17.8h, v2.8h + umlal2 v7.4s, v18.8h, v3.8h +.ifc \type, put + urshl v4.4s, v4.4s, v30.4s + urshl v5.4s, v5.4s, v30.4s + urshl v6.4s, v6.4s, v30.4s + urshl v7.4s, v7.4s, v30.4s + uzp1 v4.8h, v4.8h, v5.8h // Same as xtn, xtn2 + uzp1 v5.8h, v6.8h, v7.8h // Ditto +.else + rshrn v4.4h, v4.4s, #4 + rshrn2 v4.8h, v5.4s, #4 + rshrn v5.4h, v6.4s, #4 + rshrn2 v5.8h, v7.4s, #4 + sub v4.8h, v4.8h, v29.8h + sub v5.8h, v5.8h, v29.8h +.endif + subs \h, \h, #2 + st1 {v4.8h}, [\dst], \d_strd + st1 {v5.8h}, [\ds2], \d_strd + b.le 9f + mov v16.16b, v18.16b + b 2b +9: + subs \w, \w, #8 + b.le 0f + asr \s_strd, \s_strd, #1 + asr \d_strd, \d_strd, #1 + msub \src, \s_strd, \xmy, \src + msub \dst, \d_strd, \xmy, \dst + sub \src, \src, \s_strd, lsl #1 + mov \h, \my + add \src, \src, #16 + add \dst, \dst, #16 + b 1b +0: + ret + +L(\type\()_bilin_hv_tbl): + .hword L(\type\()_bilin_hv_tbl) - 1280b + .hword L(\type\()_bilin_hv_tbl) - 640b + .hword L(\type\()_bilin_hv_tbl) - 320b + .hword L(\type\()_bilin_hv_tbl) - 160b + .hword L(\type\()_bilin_hv_tbl) - 80b + .hword L(\type\()_bilin_hv_tbl) - 40b + .hword L(\type\()_bilin_hv_tbl) - 20b + .hword 0 +endfunc +.endm + +filter_fn put, x0, x1, x2, x3, w4, w5, w6, x6, w7, x7, w8, x9, x10 +filter_fn prep, x0, x8, x1, x2, w3, w4, w5, x5, w6, x6, w7, x9, x10 + +.macro load_filter_row dst, src, inc + asr w13, \src, #10 + add \src, \src, \inc + ldr \dst, [x11, w13, sxtw #3] +.endm + +function warp_filter_horz_neon + add w12, w5, #512 + + ld1 {v16.8h, v17.8h}, [x2], x3 + + load_filter_row d0, w12, w7 + load_filter_row d1, w12, w7 + load_filter_row d2, w12, w7 + sxtl v0.8h, v0.8b + load_filter_row d3, w12, w7 + sxtl v1.8h, v1.8b + load_filter_row d4, w12, w7 + sxtl v2.8h, v2.8b + load_filter_row d5, w12, w7 + sxtl v3.8h, v3.8b + load_filter_row d6, w12, w7 + sxtl v4.8h, v4.8b + load_filter_row d7, w12, w7 + sxtl v5.8h, v5.8b + ext v18.16b, v16.16b, v17.16b, #2*1 + smull v8.4s, v16.4h, v0.4h + smull2 v9.4s, v16.8h, v0.8h + sxtl v6.8h, v6.8b + ext v19.16b, v16.16b, v17.16b, #2*2 + smull v10.4s, v18.4h, v1.4h + smull2 v11.4s, v18.8h, v1.8h + sxtl v7.8h, v7.8b + ext v20.16b, v16.16b, v17.16b, #2*3 + smull v0.4s, v19.4h, v2.4h + smull2 v1.4s, v19.8h, v2.8h + ext v21.16b, v16.16b, v17.16b, #2*4 + addp v8.4s, v8.4s, v9.4s + smull v2.4s, v20.4h, v3.4h + smull2 v3.4s, v20.8h, v3.8h + ext v22.16b, v16.16b, v17.16b, #2*5 + addp v9.4s, v10.4s, v11.4s + smull v10.4s, v21.4h, v4.4h + smull2 v11.4s, v21.8h, v4.8h + ext v23.16b, v16.16b, v17.16b, #2*6 + addp v0.4s, v0.4s, v1.4s + smull v18.4s, v22.4h, v5.4h + smull2 v19.4s, v22.8h, v5.8h + ext v16.16b, v16.16b, v17.16b, #2*7 + addp v1.4s, v2.4s, v3.4s + addp v2.4s, v10.4s, v11.4s + smull v20.4s, v23.4h, v6.4h + smull2 v21.4s, v23.8h, v6.8h + addp v3.4s, v18.4s, v19.4s + smull v22.4s, v16.4h, v7.4h + smull2 v23.4s, v16.8h, v7.8h + addp v4.4s, v20.4s, v21.4s + addp v5.4s, v22.4s, v23.4s + + addp v8.4s, v8.4s, v9.4s + addp v0.4s, v0.4s, v1.4s + addp v2.4s, v2.4s, v3.4s + addp v4.4s, v4.4s, v5.4s + + addp v16.4s, v8.4s, v0.4s + addp v17.4s, v2.4s, v4.4s + + add w5, w5, w8 + + srshl v16.4s, v16.4s, v14.4s // -(7 - intermediate_bits) + srshl v17.4s, v17.4s, v14.4s // -(7 - intermediate_bits) + + ret +endfunc + +// void dav1d_warp_affine_8x8_16bpc_neon( +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *src, const ptrdiff_t src_stride, +// const int16_t *const abcd, int mx, int my, +// const int bitdepth_max) +.macro warp t +function warp_affine_8x8\t\()_16bpc_neon, export=1 + stp d8, d9, [sp, #-0x40]! + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + +.ifb \t + dup v15.8h, w7 // bitdepth_max +.else + movi v15.8h, #(PREP_BIAS >> 8), lsl #8 +.endif + clz w7, w7 + // intermediate_bits = clz(bitdepth_max) - 18 +.ifb \t + sub w8, w7, #11 // 7 + intermediate_bits = clz(bitdepth_max) - 18 + 7 +.endif + sub w7, w7, #25 // -(7 - intermediate_bits) +.ifb \t + neg w8, w8 // -(7 + intermediate_bits) +.endif + dup v14.4s, w7 // -(7 - intermediate_bits) +.ifb \t + dup v13.4s, w8 // -(7 + intermediate_bits) +.endif + + ldr x4, [x4] + sbfx x7, x4, #0, #16 + sbfx x8, x4, #16, #16 + sbfx x9, x4, #32, #16 + sbfx x4, x4, #48, #16 + mov w10, #8 + sub x2, x2, x3, lsl #1 + sub x2, x2, x3 + sub x2, x2, #6 + movrel x11, X(mc_warp_filter), 64*8 + mov x15, x30 +.ifnb \t + lsl x1, x1, #1 +.endif + + bl warp_filter_horz_neon + uzp1 v24.8h, v16.8h, v17.8h // Same as xtn, xtn2 + bl warp_filter_horz_neon + uzp1 v25.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v26.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v27.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v28.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v29.8h, v16.8h, v17.8h // Ditto + bl warp_filter_horz_neon + uzp1 v30.8h, v16.8h, v17.8h // Ditto + +1: + add w14, w6, #512 + bl warp_filter_horz_neon + uzp1 v31.8h, v16.8h, v17.8h // Same as xtn, xtn2 + + load_filter_row d0, w14, w9 + load_filter_row d1, w14, w9 + load_filter_row d2, w14, w9 + load_filter_row d3, w14, w9 + load_filter_row d4, w14, w9 + load_filter_row d5, w14, w9 + load_filter_row d6, w14, w9 + load_filter_row d7, w14, w9 + transpose_8x8b_xtl v0, v1, v2, v3, v4, v5, v6, v7, sxtl + + // This ordering of smull/smlal/smull2/smlal2 is highly + // beneficial for Cortex A53 here. + smull v16.4s, v24.4h, v0.4h + smlal v16.4s, v25.4h, v1.4h + smlal v16.4s, v26.4h, v2.4h + smlal v16.4s, v27.4h, v3.4h + smlal v16.4s, v28.4h, v4.4h + smlal v16.4s, v29.4h, v5.4h + smlal v16.4s, v30.4h, v6.4h + smlal v16.4s, v31.4h, v7.4h + smull2 v17.4s, v24.8h, v0.8h + smlal2 v17.4s, v25.8h, v1.8h + smlal2 v17.4s, v26.8h, v2.8h + smlal2 v17.4s, v27.8h, v3.8h + smlal2 v17.4s, v28.8h, v4.8h + smlal2 v17.4s, v29.8h, v5.8h + smlal2 v17.4s, v30.8h, v6.8h + smlal2 v17.4s, v31.8h, v7.8h + + mov v24.16b, v25.16b + mov v25.16b, v26.16b +.ifb \t + srshl v16.4s, v16.4s, v13.4s // -(7 + intermediate_bits) + srshl v17.4s, v17.4s, v13.4s // -(7 + intermediate_bits) +.else + rshrn v16.4h, v16.4s, #7 + rshrn2 v16.8h, v17.4s, #7 +.endif + mov v26.16b, v27.16b +.ifb \t + sqxtun v16.4h, v16.4s + sqxtun2 v16.8h, v17.4s +.else + sub v16.8h, v16.8h, v15.8h // PREP_BIAS +.endif + mov v27.16b, v28.16b + mov v28.16b, v29.16b +.ifb \t + umin v16.8h, v16.8h, v15.8h // bitdepth_max +.endif + mov v29.16b, v30.16b + mov v30.16b, v31.16b + subs w10, w10, #1 + st1 {v16.8h}, [x0], x1 + + add w6, w6, w4 + b.gt 1b + + ldp d14, d15, [sp, #0x30] + ldp d12, d13, [sp, #0x20] + ldp d10, d11, [sp, #0x10] + ldp d8, d9, [sp], 0x40 + + ret x15 +endfunc +.endm + +warp +warp t + +// void dav1d_emu_edge_16bpc_neon( +// const intptr_t bw, const intptr_t bh, +// const intptr_t iw, const intptr_t ih, +// const intptr_t x, const intptr_t y, +// pixel *dst, const ptrdiff_t dst_stride, +// const pixel *ref, const ptrdiff_t ref_stride) +function emu_edge_16bpc_neon, export=1 + ldp x8, x9, [sp] + + // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + // ref += iclip(x, 0, iw - 1) + sub x12, x3, #1 // ih - 1 + cmp x5, x3 + sub x13, x2, #1 // iw - 1 + csel x12, x12, x5, ge // min(y, ih - 1) + cmp x4, x2 + bic x12, x12, x12, asr #63 // max(min(y, ih - 1), 0) + csel x13, x13, x4, ge // min(x, iw - 1) + bic x13, x13, x13, asr #63 // max(min(x, iw - 1), 0) + madd x8, x12, x9, x8 // ref += iclip() * stride + add x8, x8, x13, lsl #1 // ref += iclip() + + // bottom_ext = iclip(y + bh - ih, 0, bh - 1) + // top_ext = iclip(-y, 0, bh - 1) + add x10, x5, x1 // y + bh + neg x5, x5 // -y + sub x10, x10, x3 // y + bh - ih + sub x12, x1, #1 // bh - 1 + cmp x10, x1 + bic x5, x5, x5, asr #63 // max(-y, 0) + csel x10, x10, x12, lt // min(y + bh - ih, bh-1) + cmp x5, x1 + bic x10, x10, x10, asr #63 // max(min(y + bh - ih, bh-1), 0) + csel x5, x5, x12, lt // min(max(-y, 0), bh-1) + + // right_ext = iclip(x + bw - iw, 0, bw - 1) + // left_ext = iclip(-x, 0, bw - 1) + add x11, x4, x0 // x + bw + neg x4, x4 // -x + sub x11, x11, x2 // x + bw - iw + sub x13, x0, #1 // bw - 1 + cmp x11, x0 + bic x4, x4, x4, asr #63 // max(-x, 0) + csel x11, x11, x13, lt // min(x + bw - iw, bw-1) + cmp x4, x0 + bic x11, x11, x11, asr #63 // max(min(x + bw - iw, bw-1), 0) + csel x4, x4, x13, lt // min(max(-x, 0), bw - 1) + + // center_h = bh - top_ext - bottom_ext + // dst += top_ext * PXSTRIDE(dst_stride) + // center_w = bw - left_ext - right_ext + sub x1, x1, x5 // bh - top_ext + madd x6, x5, x7, x6 + sub x2, x0, x4 // bw - left_ext + sub x1, x1, x10 // center_h = bh - top_ext - bottom_ext + sub x2, x2, x11 // center_w = bw - left_ext - right_ext + + mov x14, x6 // backup of dst + +.macro v_loop need_left, need_right +0: +.if \need_left + ld1r {v0.8h}, [x8] + mov x12, x6 // out = dst + mov x3, x4 + mov v1.16b, v0.16b +1: + subs x3, x3, #16 + st1 {v0.8h, v1.8h}, [x12], #32 + b.gt 1b +.endif + mov x13, x8 + add x12, x6, x4, lsl #1 // out = dst + left_ext + mov x3, x2 +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x13], #64 + subs x3, x3, #32 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x12], #64 + b.gt 1b +.if \need_right + add x3, x8, x2, lsl #1 // in + center_w + sub x3, x3, #2 // in + center_w - 1 + add x12, x6, x4, lsl #1 // dst + left_ext + ld1r {v0.8h}, [x3] + add x12, x12, x2, lsl #1 // out = dst + left_ext + center_w + mov x3, x11 + mov v1.16b, v0.16b +1: + subs x3, x3, #16 + st1 {v0.8h, v1.8h}, [x12], #32 + b.gt 1b +.endif + + subs x1, x1, #1 // center_h-- + add x6, x6, x7 + add x8, x8, x9 + b.gt 0b +.endm + + cbz x4, 2f + // need_left + cbz x11, 3f + // need_left + need_right + v_loop 1, 1 + b 5f + +2: + // !need_left + cbz x11, 4f + // !need_left + need_right + v_loop 0, 1 + b 5f + +3: + // need_left + !need_right + v_loop 1, 0 + b 5f + +4: + // !need_left + !need_right + v_loop 0, 0 + +5: + + cbz x10, 3f + // need_bottom + sub x8, x6, x7 // ref = dst - stride + mov x4, x0 +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x8], #64 + mov x3, x10 +2: + subs x3, x3, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x7 + b.gt 2b + msub x6, x7, x10, x6 // dst -= bottom_ext * stride + subs x4, x4, #32 // bw -= 32 + add x6, x6, #64 // dst += 32 + b.gt 1b + +3: + cbz x5, 3f + // need_top + msub x6, x7, x5, x14 // dst = stored_dst - top_ext * stride +1: + ld1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x14], #64 + mov x3, x5 +2: + subs x3, x3, #1 + st1 {v0.8h, v1.8h, v2.8h, v3.8h}, [x6], x7 + b.gt 2b + msub x6, x7, x5, x6 // dst -= top_ext * stride + subs x0, x0, #32 // bw -= 32 + add x6, x6, #64 // dst += 32 + b.gt 1b + +3: + ret +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/msac.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/msac.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/msac.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/msac.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,480 @@ +/* + * Copyright © 2019, VideoLAN and dav1d authors + * Copyright © 2019, Martin Storsjo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" +#include "util.S" + +#define BUF_POS 0 +#define BUF_END 8 +#define DIF 16 +#define RNG 24 +#define CNT 28 +#define ALLOW_UPDATE_CDF 32 + +const coeffs + .short 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0 + .short 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +endconst + +const bits + .short 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 + .short 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 +endconst + +.macro ld1_n d0, d1, src, sz, n +.if \n <= 8 + ld1 {\d0\sz}, [\src] +.else + ld1 {\d0\sz, \d1\sz}, [\src] +.endif +.endm + +.macro st1_n s0, s1, dst, sz, n +.if \n <= 8 + st1 {\s0\sz}, [\dst] +.else + st1 {\s0\sz, \s1\sz}, [\dst] +.endif +.endm + +.macro ushr_n d0, d1, s0, s1, shift, sz, n + ushr \d0\sz, \s0\sz, \shift +.if \n == 16 + ushr \d1\sz, \s1\sz, \shift +.endif +.endm + +.macro add_n d0, d1, s0, s1, s2, s3, sz, n + add \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + add \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro sub_n d0, d1, s0, s1, s2, s3, sz, n + sub \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + sub \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro and_n d0, d1, s0, s1, s2, s3, sz, n + and \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + and \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro cmhs_n d0, d1, s0, s1, s2, s3, sz, n + cmhs \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + cmhs \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro urhadd_n d0, d1, s0, s1, s2, s3, sz, n + urhadd \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + urhadd \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro sshl_n d0, d1, s0, s1, s2, s3, sz, n + sshl \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + sshl \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro sqdmulh_n d0, d1, s0, s1, s2, s3, sz, n + sqdmulh \d0\sz, \s0\sz, \s2\sz +.if \n == 16 + sqdmulh \d1\sz, \s1\sz, \s3\sz +.endif +.endm + +.macro str_n idx0, idx1, dstreg, dstoff, n + str \idx0, [\dstreg, \dstoff] +.if \n == 16 + str \idx1, [\dstreg, \dstoff + 16] +.endif +.endm + +// unsigned dav1d_msac_decode_symbol_adapt4_neon(MsacContext *s, uint16_t *cdf, +// size_t n_symbols); + +function msac_decode_symbol_adapt4_neon, export=1 +.macro decode_update sz, szb, n + sub sp, sp, #48 + add x8, x0, #RNG + ld1_n v0, v1, x1, \sz, \n // cdf + ld1r {v4\sz}, [x8] // rng + movrel x9, coeffs, 30 + movi v31\sz, #0x7f, lsl #8 // 0x7f00 + sub x9, x9, x2, lsl #1 + mvni v30\sz, #0x3f // 0xffc0 + and v7\szb, v4\szb, v31\szb // rng & 0x7f00 + str h4, [sp, #14] // store original u = s->rng + and_n v2, v3, v0, v1, v30, v30, \szb, \n // cdf & 0xffc0 + + ld1_n v4, v5, x9, \sz, \n // EC_MIN_PROB * (n_symbols - ret) + sqdmulh_n v6, v7, v2, v3, v7, v7, \sz, \n // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1 + add x8, x0, #DIF + 6 + + add_n v4, v5, v2, v3, v4, v5, \sz, \n // v = cdf + EC_MIN_PROB * (n_symbols - ret) + add_n v4, v5, v6, v7, v4, v5, \sz, \n // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret) + + ld1r {v6.8h}, [x8] // dif >> (EC_WIN_SIZE - 16) + movrel x8, bits + str_n q4, q5, sp, #16, \n // store v values to allow indexed access + + ld1_n v16, v17, x8, .8h, \n + + cmhs_n v2, v3, v6, v6, v4, v5, .8h, \n // c >= v + + and_n v6, v7, v2, v3, v16, v17, .16b, \n // One bit per halfword set in the mask +.if \n == 16 + add v6.8h, v6.8h, v7.8h +.endif + addv h6, v6.8h // Aggregate mask bits + ldr w4, [x0, #ALLOW_UPDATE_CDF] + umov w3, v6.h[0] + rbit w3, w3 + clz w15, w3 // ret + + cbz w4, L(renorm) + // update_cdf + ldrh w3, [x1, x2, lsl #1] // count = cdf[n_symbols] + movi v5\szb, #0xff +.if \n == 16 + mov w4, #-5 +.else + mvn w14, w2 + mov w4, #-4 + cmn w14, #3 // set C if n_symbols <= 2 +.endif + urhadd_n v4, v5, v5, v5, v2, v3, \sz, \n // i >= val ? -1 : 32768 +.if \n == 16 + sub w4, w4, w3, lsr #4 // -((count >> 4) + 5) +.else + lsr w14, w3, #4 // count >> 4 + sbc w4, w4, w14 // -((count >> 4) + (n_symbols > 2) + 4) +.endif + sub_n v4, v5, v4, v5, v0, v1, \sz, \n // (32768 - cdf[i]) or (-1 - cdf[i]) + dup v6\sz, w4 // -rate + + sub w3, w3, w3, lsr #5 // count - (count == 32) + sub_n v0, v1, v0, v1, v2, v3, \sz, \n // cdf + (i >= val ? 1 : 0) + sshl_n v4, v5, v4, v5, v6, v6, \sz, \n // ({32768,-1} - cdf[i]) >> rate + add w3, w3, #1 // count + (count < 32) + add_n v0, v1, v0, v1, v4, v5, \sz, \n // cdf + (32768 - cdf[i]) >> rate + st1_n v0, v1, x1, \sz, \n + strh w3, [x1, x2, lsl #1] +.endm + + decode_update .4h, .8b, 4 + +L(renorm): + add x8, sp, #16 + add x8, x8, w15, uxtw #1 + ldrh w3, [x8] // v + ldurh w4, [x8, #-2] // u + ldr w6, [x0, #CNT] + ldr x7, [x0, #DIF] + sub w4, w4, w3 // rng = u - v + clz w5, w4 // clz(rng) + eor w5, w5, #16 // d = clz(rng) ^ 16 + mvn x7, x7 // ~dif + add x7, x7, x3, lsl #48 // ~dif + (v << 48) +L(renorm2): + lsl w4, w4, w5 // rng << d + subs w6, w6, w5 // cnt -= d + lsl x7, x7, x5 // (~dif + (v << 48)) << d + str w4, [x0, #RNG] + mvn x7, x7 // ~dif + b.hs 9f + + // refill + ldp x3, x4, [x0] // BUF_POS, BUF_END + add x5, x3, #8 + cmp x5, x4 + b.gt 2f + + ldr x3, [x3] // next_bits + add w8, w6, #23 // shift_bits = cnt + 23 + add w6, w6, #16 // cnt += 16 + rev x3, x3 // next_bits = bswap(next_bits) + sub x5, x5, x8, lsr #3 // buf_pos -= shift_bits >> 3 + and w8, w8, #24 // shift_bits &= 24 + lsr x3, x3, x8 // next_bits >>= shift_bits + sub w8, w8, w6 // shift_bits -= 16 + cnt + str x5, [x0, #BUF_POS] + lsl x3, x3, x8 // next_bits <<= shift_bits + mov w4, #48 + sub w6, w4, w8 // cnt = cnt + 64 - shift_bits + eor x7, x7, x3 // dif ^= next_bits + b 9f + +2: // refill_eob + mov w14, #40 + sub w5, w14, w6 // c = 40 - cnt +3: + cmp x3, x4 + b.ge 4f + ldrb w8, [x3], #1 + lsl x8, x8, x5 + eor x7, x7, x8 + subs w5, w5, #8 + b.ge 3b + +4: // refill_eob_end + str x3, [x0, #BUF_POS] + sub w6, w14, w5 // cnt = 40 - c + +9: + str w6, [x0, #CNT] + str x7, [x0, #DIF] + + mov w0, w15 + add sp, sp, #48 + ret +endfunc + +function msac_decode_symbol_adapt8_neon, export=1 + decode_update .8h, .16b, 8 + b L(renorm) +endfunc + +function msac_decode_symbol_adapt16_neon, export=1 + decode_update .8h, .16b, 16 + b L(renorm) +endfunc + +function msac_decode_hi_tok_neon, export=1 + ld1 {v0.4h}, [x1] // cdf + add x16, x0, #RNG + movi v31.4h, #0x7f, lsl #8 // 0x7f00 + movrel x17, coeffs, 30-2*3 + mvni v30.4h, #0x3f // 0xffc0 + ldrh w9, [x1, #6] // count = cdf[n_symbols] + ld1r {v3.4h}, [x16] // rng + movrel x16, bits + ld1 {v29.4h}, [x17] // EC_MIN_PROB * (n_symbols - ret) + add x17, x0, #DIF + 6 + ld1 {v16.8h}, [x16] + mov w13, #-24 + and v17.8b, v0.8b, v30.8b // cdf & 0xffc0 + ldr w10, [x0, #ALLOW_UPDATE_CDF] + ld1r {v1.8h}, [x17] // dif >> (EC_WIN_SIZE - 16) + sub sp, sp, #48 + ldr w6, [x0, #CNT] + ldr x7, [x0, #DIF] +1: + and v7.8b, v3.8b, v31.8b // rng & 0x7f00 + sqdmulh v6.4h, v17.4h, v7.4h // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1 + add v4.4h, v17.4h, v29.4h // v = cdf + EC_MIN_PROB * (n_symbols - ret) + add v4.4h, v6.4h, v4.4h // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret) + str h3, [sp, #14] // store original u = s->rng + cmhs v2.8h, v1.8h, v4.8h // c >= v + str q4, [sp, #16] // store v values to allow indexed access + and v6.16b, v2.16b, v16.16b // One bit per halfword set in the mask + addv h6, v6.8h // Aggregate mask bits + umov w3, v6.h[0] + add w13, w13, #5 + rbit w3, w3 + add x8, sp, #16 + clz w15, w3 // ret + + cbz w10, 2f + // update_cdf + movi v5.8b, #0xff + mov w4, #-5 + urhadd v4.4h, v5.4h, v2.4h // i >= val ? -1 : 32768 + sub w4, w4, w9, lsr #4 // -((count >> 4) + 5) + sub v4.4h, v4.4h, v0.4h // (32768 - cdf[i]) or (-1 - cdf[i]) + dup v6.4h, w4 // -rate + + sub w9, w9, w9, lsr #5 // count - (count == 32) + sub v0.4h, v0.4h, v2.4h // cdf + (i >= val ? 1 : 0) + sshl v4.4h, v4.4h, v6.4h // ({32768,-1} - cdf[i]) >> rate + add w9, w9, #1 // count + (count < 32) + add v0.4h, v0.4h, v4.4h // cdf + (32768 - cdf[i]) >> rate + st1 {v0.4h}, [x1] + and v17.8b, v0.8b, v30.8b // cdf & 0xffc0 + strh w9, [x1, #6] + +2: + add x8, x8, w15, uxtw #1 + ldrh w3, [x8] // v + ldurh w4, [x8, #-2] // u + sub w4, w4, w3 // rng = u - v + clz w5, w4 // clz(rng) + eor w5, w5, #16 // d = clz(rng) ^ 16 + mvn x7, x7 // ~dif + add x7, x7, x3, lsl #48 // ~dif + (v << 48) + lsl w4, w4, w5 // rng << d + subs w6, w6, w5 // cnt -= d + lsl x7, x7, x5 // (~dif + (v << 48)) << d + str w4, [x0, #RNG] + dup v3.4h, w4 + mvn x7, x7 // ~dif + b.hs 9f + + // refill + ldp x3, x4, [x0] // BUF_POS, BUF_END + add x5, x3, #8 + cmp x5, x4 + b.gt 2f + + ldr x3, [x3] // next_bits + add w8, w6, #23 // shift_bits = cnt + 23 + add w6, w6, #16 // cnt += 16 + rev x3, x3 // next_bits = bswap(next_bits) + sub x5, x5, x8, lsr #3 // buf_pos -= shift_bits >> 3 + and w8, w8, #24 // shift_bits &= 24 + lsr x3, x3, x8 // next_bits >>= shift_bits + sub w8, w8, w6 // shift_bits -= 16 + cnt + str x5, [x0, #BUF_POS] + lsl x3, x3, x8 // next_bits <<= shift_bits + mov w4, #48 + sub w6, w4, w8 // cnt = cnt + 64 - shift_bits + eor x7, x7, x3 // dif ^= next_bits + b 9f + +2: // refill_eob + mov w14, #40 + sub w5, w14, w6 // c = 40 - cnt +3: + cmp x3, x4 + b.ge 4f + ldrb w8, [x3], #1 + lsl x8, x8, x5 + eor x7, x7, x8 + subs w5, w5, #8 + b.ge 3b + +4: // refill_eob_end + str x3, [x0, #BUF_POS] + sub w6, w14, w5 // cnt = 40 - c + +9: + lsl w15, w15, #1 + sub w15, w15, #5 + lsr x12, x7, #48 + adds w13, w13, w15 // carry = tok_br < 3 || tok == 15 + dup v1.8h, w12 + b.cc 1b // loop if !carry + add w13, w13, #30 + str w6, [x0, #CNT] + add sp, sp, #48 + str x7, [x0, #DIF] + lsr w0, w13, #1 + ret +endfunc + +function msac_decode_bool_equi_neon, export=1 + ldp w5, w6, [x0, #RNG] // + CNT + sub sp, sp, #48 + ldr x7, [x0, #DIF] + bic w4, w5, #0xff // r &= 0xff00 + add w4, w4, #8 + subs x8, x7, x4, lsl #47 // dif - vw + lsr w4, w4, #1 // v + sub w5, w5, w4 // r - v + cset w15, lo + csel w4, w5, w4, hs // if (ret) v = r - v; + csel x7, x8, x7, hs // if (ret) dif = dif - vw; + + clz w5, w4 // clz(rng) + mvn x7, x7 // ~dif + eor w5, w5, #16 // d = clz(rng) ^ 16 + b L(renorm2) +endfunc + +function msac_decode_bool_neon, export=1 + ldp w5, w6, [x0, #RNG] // + CNT + sub sp, sp, #48 + ldr x7, [x0, #DIF] + lsr w4, w5, #8 // r >> 8 + bic w1, w1, #0x3f // f &= ~63 + mul w4, w4, w1 + lsr w4, w4, #7 + add w4, w4, #4 // v + subs x8, x7, x4, lsl #48 // dif - vw + sub w5, w5, w4 // r - v + cset w15, lo + csel w4, w5, w4, hs // if (ret) v = r - v; + csel x7, x8, x7, hs // if (ret) dif = dif - vw; + + clz w5, w4 // clz(rng) + mvn x7, x7 // ~dif + eor w5, w5, #16 // d = clz(rng) ^ 16 + b L(renorm2) +endfunc + +function msac_decode_bool_adapt_neon, export=1 + ldr w9, [x1] // cdf[0-1] + ldp w5, w6, [x0, #RNG] // + CNT + sub sp, sp, #48 + ldr x7, [x0, #DIF] + lsr w4, w5, #8 // r >> 8 + and w2, w9, #0xffc0 // f &= ~63 + mul w4, w4, w2 + lsr w4, w4, #7 + add w4, w4, #4 // v + subs x8, x7, x4, lsl #48 // dif - vw + sub w5, w5, w4 // r - v + cset w15, lo + csel w4, w5, w4, hs // if (ret) v = r - v; + csel x7, x8, x7, hs // if (ret) dif = dif - vw; + + ldr w10, [x0, #ALLOW_UPDATE_CDF] + + clz w5, w4 // clz(rng) + mvn x7, x7 // ~dif + eor w5, w5, #16 // d = clz(rng) ^ 16 + + cbz w10, L(renorm2) + + lsr w2, w9, #16 // count = cdf[1] + and w9, w9, #0xffff // cdf[0] + + sub w3, w2, w2, lsr #5 // count - (count >= 32) + lsr w2, w2, #4 // count >> 4 + add w10, w3, #1 // count + (count < 32) + add w2, w2, #4 // rate = (count >> 4) | 4 + + sub w9, w9, w15 // cdf[0] -= bit + sub w11, w9, w15, lsl #15 // {cdf[0], cdf[0] - 32769} + asr w11, w11, w2 // {cdf[0], cdf[0] - 32769} >> rate + sub w9, w9, w11 // cdf[0] + + strh w9, [x1] + strh w10, [x1, #2] + + b L(renorm2) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/sad.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sad.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/sad.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sad.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2016, Alliance for Open Media. All rights reserved + * Copyright (c) 2020-2023, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro sad_rect width, height +function sad\width\()x\height\()_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, \height +.if \width >= 16 + mov v1.16b, v0.16b +.endif + b L(sad_w\width\()) +endfunc +.endm + +function sad4x4_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #4 +L(sad_w4): + ldr s2, [x0] + ldr s3, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.8h, v2.8b, v3.8b + bne L(sad_w4) + uaddlp v0.2s, v0.4h + uaddlp v0.1d, v0.2s + fmov w0, s0 + ret +endfunc + +sad_rect 4, 8 +sad_rect 4, 16 + +.macro horizontal_long_add_16x8 + ushll v2.4s, v1.4h, #0 + uaddw2 v1.4s, v2.4s, v1.8h + uaddw v1.4s, v1.4s, v0.4h + uaddw2 v0.4s, v1.4s, v0.8h + uaddlp v0.2d, v0.4s + ext v1.16b, v0.16b, v0.16b, #8 + add v0.2s, v1.2s, v0.2s + fmov w0, s0 + ret +.endm + +.macro horizontal_add_16x8 + uaddlp v0.4s, v0.8h + uaddlp v0.2d, v0.4s + ext v1.16b, v0.16b, v0.16b, #8 + add v0.2s, v1.2s, v0.2s + fmov w0, s0 + ret +.endm + +function sad64x64_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #64 + mov v1.16b, v0.16b +L(sad_w64): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.8h, v2.8b, v3.8b + uabal2 v1.8h, v2.16b, v3.16b + uabal v0.8h, v4.8b, v5.8b + uabal2 v1.8h, v4.16b, v5.16b + uabal v0.8h, v6.8b, v7.8b + uabal2 v1.8h, v6.16b, v7.16b + uabal v0.8h, v16.8b, v17.8b + uabal2 v1.8h, v16.16b, v17.16b + bne L(sad_w64) + horizontal_long_add_16x8 +endfunc + +sad_rect 64, 16 +sad_rect 64, 32 +sad_rect 64, 128 + +function sad128x128_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #128 + mov v1.16b, v0.16b +L(sad_w128): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + ldp q18, q20, [x0, #64] + ldp q19, q21, [x2, #64] + ldp q22, q24, [x0, #96] + ldp q23, q25, [x2, #96] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabdl v26.8h, v2.8b, v3.8b + uabal2 v26.8h, v2.16b, v3.16b + uabal v26.8h, v4.8b, v5.8b + uabal2 v26.8h, v4.16b, v5.16b + uabal v26.8h, v6.8b, v7.8b + uabal2 v26.8h, v6.16b, v7.16b + uabal v26.8h, v16.8b, v17.8b + uabal2 v26.8h, v16.16b, v17.16b + uabal v26.8h, v18.8b, v19.8b + uabal2 v26.8h, v18.16b, v19.16b + uabal v26.8h, v20.8b, v21.8b + uabal2 v26.8h, v20.16b, v21.16b + uabal v26.8h, v22.8b, v23.8b + uabal2 v26.8h, v22.16b, v23.16b + uabal v26.8h, v24.8b, v25.8b + uabal2 v26.8h, v24.16b, v25.16b + uaddw v1.4s, v1.4s, v26.4h + uaddw2 v0.4s, v0.4s, v26.8h + bne L(sad_w128) + add v0.4s, v0.4s, v1.4s + uaddlp v0.2d, v0.4s + dup d3, v0.d[1] + add v0.2s, v0.2s, v3.2s + umov w0, v0.s[0] + ret +endfunc + +sad_rect 128, 64 + +function sad32x32_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #32 + mov v1.16b, v0.16b +L(sad_w32): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v1.8h, v2.8b, v3.8b + uabal2 v0.8h, v2.16b, v3.16b + uabal v1.8h, v4.8b, v5.8b + uabal2 v0.8h, v4.16b, v5.16b + bne L(sad_w32) + add v0.8h, v0.8h, v1.8h + horizontal_add_16x8 +endfunc + +sad_rect 32, 8 +sad_rect 32, 16 +sad_rect 32, 64 + +function sad16x16_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #16 + mov v1.16b, v0.16b +L(sad_w16): + ldr q2, [x0] + ldr q3, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.8h, v2.8b, v3.8b + uabal2 v1.8h, v2.16b, v3.16b + bne L(sad_w16) + add v0.8h, v0.8h, v1.8h + horizontal_add_16x8 +endfunc + +sad_rect 16, 4 +sad_rect 16, 8 +sad_rect 16, 32 +sad_rect 16, 64 + +function sad8x8_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #8 +L(sad_w8): + ldr d2, [x0] + ldr d3, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.8h, v2.8b, v3.8b + bne L(sad_w8) + horizontal_add_16x8 +endfunc + +sad_rect 8, 4 +sad_rect 8, 16 +sad_rect 8, 32 + +.macro sad_hbd_rect width, height +function sad\width\()x\height\()_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, \height +.if \width >= 8 + mov v1.16b, v0.16b +.endif +.if \width >= 64 && \height >= 64 + b L(sad_hbd_large_w\width\()) +.else + b L(sad_hbd_w\width\()) +.endif +endfunc +.endm + +function sad4x4_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #4 +L(sad_hbd_w4): + ldr d2, [x0] + ldr d3, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.4s, v2.4h, v3.4h + bne L(sad_hbd_w4) + addv s0, v0.4s + fmov w0, s0 + ret +endfunc + +sad_hbd_rect 4, 8 +sad_hbd_rect 4, 16 + +.macro horizontal_add_32x4 + uaddlp v0.2d, v0.4s + ext v1.16b, v0.16b, v0.16b, #8 + add v0.2s, v1.2s, v0.2s + fmov w0, s0 + ret +.endm + +function sad64x32_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #32 + mov v1.16b, v0.16b +L(sad_hbd_w64): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + ldp q18, q20, [x0, #64] + ldp q19, q21, [x2, #64] + ldp q22, q24, [x0, #96] + ldp q23, q25, [x2, #96] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.4s, v2.4h, v3.4h + uabal2 v1.4s, v2.8h, v3.8h + uabal v0.4s, v4.4h, v5.4h + uabal2 v1.4s, v4.8h, v5.8h + uabal v0.4s, v6.4h, v7.4h + uabal2 v1.4s, v6.8h, v7.8h + uabal v0.4s, v16.4h, v17.4h + uabal2 v1.4s, v16.8h, v17.8h + uabal v0.4s, v18.4h, v19.4h + uabal2 v1.4s, v18.8h, v19.8h + uabal v0.4s, v20.4h, v21.4h + uabal2 v1.4s, v20.8h, v21.8h + uabal v0.4s, v22.4h, v23.4h + uabal2 v1.4s, v22.8h, v23.8h + uabal v0.4s, v24.4h, v25.4h + uabal2 v1.4s, v24.8h, v25.8h + bne L(sad_hbd_w64) + horizontal_long_add_16x8 +endfunc + +function sad64x64_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #64 + mov v1.16b, v0.16b +L(sad_hbd_large_w64): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + ldp q18, q20, [x0, #64] + ldp q19, q21, [x2, #64] + ldp q22, q24, [x0, #96] + ldp q23, q25, [x2, #96] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabdl v26.4s, v2.4h, v3.4h + uabal2 v26.4s, v2.8h, v3.8h + uabal v26.4s, v4.4h, v5.4h + uabal2 v26.4s, v4.8h, v5.8h + uabal v26.4s, v6.4h, v7.4h + uabal2 v26.4s, v6.8h, v7.8h + uabal v26.4s, v16.4h, v17.4h + uabal2 v26.4s, v16.8h, v17.8h + uabal v26.4s, v18.4h, v19.4h + uabal2 v26.4s, v18.8h, v19.8h + uabal v26.4s, v20.4h, v21.4h + uabal2 v26.4s, v20.8h, v21.8h + uabal v26.4s, v22.4h, v23.4h + uabal2 v26.4s, v22.8h, v23.8h + uabal v26.4s, v24.4h, v25.4h + uabal2 v26.4s, v24.8h, v25.8h + uaddw v1.2d, v1.2d, v26.2s + uaddw2 v0.2d, v0.2d, v26.4s + bne L(sad_hbd_large_w64) + add v0.2d, v0.2d, v1.2d + dup d3, v0.d[1] + add v0.2d, v0.2d, v3.2d + umov x0, v0.d[0] + ret +endfunc + +sad_hbd_rect 64, 16 +sad_hbd_rect 64, 128 + +function sad128x128_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #128 + mov v1.16b, v0.16b +L(sad_hbd_large_w128): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + ldp q18, q20, [x0, #64] + ldp q19, q21, [x2, #64] + ldp q22, q24, [x0, #96] + ldp q23, q25, [x2, #96] + uabdl v26.4s, v2.4h, v3.4h + uabal2 v26.4s, v2.8h, v3.8h + uabal v26.4s, v4.4h, v5.4h + uabal2 v26.4s, v4.8h, v5.8h + uabal v26.4s, v6.4h, v7.4h + uabal2 v26.4s, v6.8h, v7.8h + uabal v26.4s, v16.4h, v17.4h + uabal2 v26.4s, v16.8h, v17.8h + uabal v26.4s, v18.4h, v19.4h + uabal2 v26.4s, v18.8h, v19.8h + uabal v26.4s, v20.4h, v21.4h + uabal2 v26.4s, v20.8h, v21.8h + uabal v26.4s, v22.4h, v23.4h + uabal2 v26.4s, v22.8h, v23.8h + uabal v26.4s, v24.4h, v25.4h + uabal2 v26.4s, v24.8h, v25.8h + uaddw v1.2d, v1.2d, v26.2s + uaddw2 v0.2d, v0.2d, v26.4s + ldp q2, q4, [x0, #128] + ldp q3, q5, [x2, #128] + ldp q6, q16, [x0, #160] + ldp q7, q17, [x2, #160] + ldp q18, q20, [x0, #192] + ldp q19, q21, [x2, #192] + ldp q22, q24, [x0, #224] + ldp q23, q25, [x2, #224] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabdl v26.4s, v2.4h, v3.4h + uabal2 v26.4s, v2.8h, v3.8h + uabal v26.4s, v4.4h, v5.4h + uabal2 v26.4s, v4.8h, v5.8h + uabal v26.4s, v6.4h, v7.4h + uabal2 v26.4s, v6.8h, v7.8h + uabal v26.4s, v16.4h, v17.4h + uabal2 v26.4s, v16.8h, v17.8h + uabal v26.4s, v18.4h, v19.4h + uabal2 v26.4s, v18.8h, v19.8h + uabal v26.4s, v20.4h, v21.4h + uabal2 v26.4s, v20.8h, v21.8h + uabal v26.4s, v22.4h, v23.4h + uabal2 v26.4s, v22.8h, v23.8h + uabal v26.4s, v24.4h, v25.4h + uabal2 v26.4s, v24.8h, v25.8h + uaddw v1.2d, v1.2d, v26.2s + uaddw2 v0.2d, v0.2d, v26.4s + bne L(sad_hbd_large_w128) + add v0.2d, v0.2d, v1.2d + dup d3, v0.d[1] + add v0.2d, v0.2d, v3.2d + umov x0, v0.d[0] + ret +endfunc + +sad_hbd_rect 128, 64 + +function sad32x32_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #32 + mov v1.16b, v0.16b +L(sad_hbd_w32): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + ldp q6, q16, [x0, #32] + ldp q7, q17, [x2, #32] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.4s, v2.4h, v3.4h + uabal2 v1.4s, v2.8h, v3.8h + uabal v0.4s, v4.4h, v5.4h + uabal2 v1.4s, v4.8h, v5.8h + uabal v0.4s, v6.4h, v7.4h + uabal2 v1.4s, v6.8h, v7.8h + uabal v0.4s, v16.4h, v17.4h + uabal2 v1.4s, v16.8h, v17.8h + bne L(sad_hbd_w32) + add v0.4s, v0.4s, v1.4s + horizontal_add_32x4 +endfunc + +sad_hbd_rect 32, 8 +sad_hbd_rect 32, 16 +sad_hbd_rect 32, 64 + +function sad16x16_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #16 + mov v1.16b, v0.16b +L(sad_hbd_w16): + ldp q2, q4, [x0] + ldp q3, q5, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.4s, v2.4h, v3.4h + uabal2 v1.4s, v2.8h, v3.8h + uabal v0.4s, v4.4h, v5.4h + uabal2 v1.4s, v4.8h, v5.8h + bne L(sad_hbd_w16) + add v0.4s, v0.4s, v1.4s + horizontal_add_32x4 +endfunc + +sad_hbd_rect 16, 4 +sad_hbd_rect 16, 8 +sad_hbd_rect 16, 32 +sad_hbd_rect 16, 64 + +function sad8x8_hbd_neon, export=1 + movi v0.4s, #0 + sxtw x1, w1 + sxtw x3, w3 + mov w4, #8 + mov v1.16b, v0.16b +L(sad_hbd_w8): + ldr q2, [x0] + ldr q3, [x2] + add x0, x0, x1 + add x2, x2, x3 + subs w4, w4, #1 + uabal v0.4s, v2.4h, v3.4h + uabal2 v1.4s, v2.8h, v3.8h + bne L(sad_hbd_w8) + add v0.4s, v0.4s, v1.4s + horizontal_add_32x4 +endfunc + +sad_hbd_rect 8, 4 +sad_hbd_rect 8, 16 +sad_hbd_rect 8, 32 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/satd.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/satd.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/satd.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/satd.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1473 @@ +/* Copyright (c) 2022-2023, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro butterfly r0, r1, r2, r3, t=8h + add \r0\().\t, \r2\().\t, \r3\().\t + sub \r1\().\t, \r2\().\t, \r3\().\t +.endm + +.macro butterflyw r0, r1, r2, r3, r4, r5 + sxtl \r0\().4s, \r4\().4h + sxtl2 \r2\().4s, \r4\().8h + ssubw \r1\().4s, \r0\().4s, \r5\().4h + ssubw2 \r3\().4s, \r2\().4s, \r5\().8h + saddw \r0\().4s, \r0\().4s, \r5\().4h + saddw2 \r2\().4s, \r2\().4s, \r5\().8h +.endm + +.macro interleave r0, r1, r2, r3 + zip1 \r0\().8h, \r2\().8h, \r3\().8h + zip2 \r1\().8h, \r2\().8h, \r3\().8h +.endm + +.macro interleave_pairs r0, r1, r2, r3 + zip1 \r0\().4s, \r2\().4s, \r3\().4s + zip2 \r1\().4s, \r2\().4s, \r3\().4s +.endm + +.macro interleave_quads r0, r1, r2, r3 + zip1 \r0\().2d, \r2\().2d, \r3\().2d + zip2 \r1\().2d, \r2\().2d, \r3\().2d +.endm + +.macro normalize_4 + add w0, w0, 2 + lsr w0, w0, 2 +.endm + +.macro normalize_8 + add w0, w0, 4 + lsr w0, w0, 3 +.endm + +// x0: src: *const u8, +// x1: src_stride: isize, +// x2: dst: *const u8, +// x3: dst_stride: isize, +function satd4x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + ldr s0, [src] + ldr s1, [dst] + + // subtract; cast to 16-bit + usubl v0.8h, v0.8b, v1.8b + + ldr s1, [src, src_stride] + ldr s2, [dst, dst_stride] + + usubl v1.8h, v1.8b, v2.8b + + // stride * 2 + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr s2, [src, x8] + ldr s3, [dst, x9] + + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr s3, [src, x8] + ldr s4, [dst, x9] + + usubl v3.8h, v3.8b, v4.8b + + // pack rows 0-2, 1-3 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // Horizontal transform + + // v0 0 1 2 3 8 9 10 11 + // v1 4 5 6 7 12 13 14 15 + + butterfly v2, v3, v0, v1 + + // v2 [0+4][1+5][2+6][3+7] [8+12][9+13][10+14][11+15] + // v3 [0-4][1-5][2-6][3-7] [8-12][9-13][10-14][11-15] + + interleave v0, v1, v2, v3 + + // v0 [ 0+4][ 0-4][ 1+5][ 1-5] [2 + 6][2 - 6][3 + 7][3 - 7] + // v1 [8+12][8-12][9+13][9-13] [10+14][10-14][11+15][11-15] + + butterfly v2, v3, v0, v1 + + // v2 [0+4+8+12][0-4+8-12][1+5+9+13][1-5+9-13] [2+6+10+14][2-6+10-14][3+7+11+15][3-7+11-15] + // v3 [0+4-8-12][0-4-8+12][1+5-9-13][1-5-9+13] [2+6-10-14][2-6-10+14][3+7-11-15][3-7-11+15] + + interleave_pairs v0, v1, v2, v3 + + // Vertical transform + + butterfly v2, v3, v0, v1 + + interleave v0, v1, v2, v3 + + butterfly v2, v3, v0, v1 + + // sum up transform + abs v2.8h, v2.8h + abs v3.8h, v3.8h + + add v0.8h, v2.8h, v3.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro DOUBLE_HADAMARD_4X4 hbd=0 + // Horizontal transform + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave_pairs v0, v1, v2, v3 + interleave_pairs v4, v5, v6, v7 + + // Vertical transform + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + +.if \hbd == 0 + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 +.else + butterflyw v2, v3, v16, v17, v0, v1 + butterflyw v6, v7, v18, v19, v4, v5 +.endif +.endm + +.macro SUM_DOUBLE_HADAMARD_4X4 + abs v2.8h, v2.8h + abs v3.8h, v3.8h + abs v6.8h, v6.8h + abs v7.8h, v7.8h + + add v0.8h, v2.8h, v3.8h + add v1.8h, v6.8h, v7.8h + add v0.8h, v0.8h, v1.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 +.endm + +function satd8x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + // load 8 pixel row + ldr d0, [src] + ldr d1, [dst] + + usubl v0.8h, v0.8b, v1.8b + + ldr d1, [src, src_stride] + ldr d2, [dst, dst_stride] + + usubl v1.8h, v1.8b, v2.8b + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr d2, [src, x8] + ldr d3, [dst, x9] + + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr d3, [src, x8] + ldr d4, [dst, x9] + + usubl v3.8h, v3.8b, v4.8b + + // extract top 64 bits out of register + // (4 x 16 bits = 64) + + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + + // pack rows 0-2, 1-3 (set 1) + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // pack rows 0-2, 1-3 (set 2) + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + + // v2-3 temp registers for first 4x4 block// + // 6-7 for second block + + DOUBLE_HADAMARD_4X4 + + SUM_DOUBLE_HADAMARD_4X4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro load_row n0, n1, src, dst, src_stride, dst_stride, should_add=1 + ldr s\n0, [\src] + ldr s\n1, [\dst] + + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b + +.if \should_add != 0 + add \src, \src, \src_stride + add \dst, \dst, \dst_stride +.endif +.endm + +.macro load_row2 n0, n1, src, dst, src_stride, dst_stride + ldr s\n0, [\src, \src_stride] + ldr s\n1, [\dst, \dst_stride] + + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b +.endm + +function satd4x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + // 0 * stride + load_row 0, 1, src, dst, src_stride, dst_stride, 0 + // 1 * stride + load_row2 1, 2, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + // pattern repeats + load_row 2, 3, src, dst, src_stride, dst_stride, 0 + load_row2 3, 4, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 4, 5, src, dst, src_stride, dst_stride, 0 + load_row2 5, 6, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 6, 7, src, dst, src_stride, dst_stride, 0 + load_row2 7, 8, src, dst, src_stride, dst_stride + + // pack rows + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + mov v4.d[1], v6.d[0] + mov v5.d[1], v7.d[0] + + DOUBLE_HADAMARD_4X4 + + SUM_DOUBLE_HADAMARD_4X4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +function satd16x4_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define ROW1 v0 + #define ROW2 v1 + #define TMP1 v2 + #define TMP2 v3 + + #define ROW3 v4 + #define ROW4 v5 + #define TMP3 v6 + #define TMP4 v7 + + #define ROW5 v16 + #define ROW6 v17 + #define TMP5 v20 + #define TMP6 v21 + + #define ROW7 v18 + #define ROW8 v19 + #define TMP7 v22 + #define TMP8 v23 + + // load 16 pixel row + ldr q0, [src] + ldr q1, [dst] + + usubl2 v16.8h, v0.16b, v1.16b + usubl v0.8h, v0.8b, v1.8b + + ldr q1, [src, src_stride] + ldr q2, [dst, dst_stride] + + usubl2 v17.8h, v1.16b, v2.16b + usubl v1.8h, v1.8b, v2.8b + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr q2, [src, x8] + ldr q3, [dst, x9] + + usubl2 v6.8h, v2.16b, v3.16b + usubl v2.8h, v2.8b, v3.8b + + // stride * 3 + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr q3, [src, x8] + ldr q4, [dst, x9] + + usubl2 v7.8h, v3.16b, v4.16b + usubl v3.8h, v3.8b, v4.8b + + // swap high/low 64 bits + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + ext v18.16b, v16.16b, v16.16b, 8 + ext v19.16b, v17.16b, v17.16b, 8 + + mov v16.d[1], v6.d[0] + mov v17.d[1], v7.d[0] + // 2-3 free + + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + // 6-7 free + mov v18.d[1], v6.d[1] + mov v19.d[1], v7.d[1] + + // 0,1 2,3 + // 4,5 6,7 + // 16,17 20,21 + // 18,19 22,23 + + // quadruple 4x4 hadamard + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave ROW1, ROW2, TMP1, TMP2 + interleave ROW3, ROW4, TMP3, TMP4 + interleave ROW5, ROW6, TMP5, TMP6 + interleave ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave_pairs ROW1, ROW2, TMP1, TMP2 + interleave_pairs ROW3, ROW4, TMP3, TMP4 + interleave_pairs ROW5, ROW6, TMP5, TMP6 + interleave_pairs ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + interleave ROW1, ROW2, TMP1, TMP2 + interleave ROW3, ROW4, TMP3, TMP4 + interleave ROW5, ROW6, TMP5, TMP6 + interleave ROW7, ROW8, TMP7, TMP8 + + butterfly TMP1, TMP2, ROW1, ROW2 + butterfly TMP3, TMP4, ROW3, ROW4 + butterfly TMP5, TMP6, ROW5, ROW6 + butterfly TMP7, TMP8, ROW7, ROW8 + + // absolute value of transform coefficients + abs TMP1.8h, TMP1.8h + abs TMP2.8h, TMP2.8h + abs TMP3.8h, TMP3.8h + abs TMP4.8h, TMP4.8h + abs TMP5.8h, TMP5.8h + abs TMP6.8h, TMP6.8h + abs TMP7.8h, TMP7.8h + abs TMP8.8h, TMP8.8h + + // stage 1 sum + add TMP1.8h, TMP1.8h, TMP5.8h + add TMP2.8h, TMP2.8h, TMP6.8h + add TMP3.8h, TMP3.8h, TMP7.8h + add TMP4.8h, TMP4.8h, TMP8.8h + + // stage 2 sum + add TMP1.8h, TMP1.8h, TMP3.8h + add TMP2.8h, TMP2.8h, TMP4.8h + add v0.8h, TMP1.8h, TMP2.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef ROW1 + #undef TMP1 + #undef ROW2 + #undef TMP2 + #undef ROW3 + #undef TMP3 + #undef ROW4 + #undef TMP4 + #undef ROW5 + #undef TMP5 + #undef ROW6 + #undef TMP6 + #undef ROW7 + #undef TMP7 + #undef ROW8 + #undef TMP8 +endfunc + +function satd4x16_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + load_row 0, 1, src, dst, src_stride, dst_stride, 0 + load_row2 1, 2, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 2, 3, src, dst, src_stride, dst_stride, 0 + load_row2 3, 4, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 4, 5, src, dst, src_stride, dst_stride, 0 + load_row2 5, 6, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 6, 7, src, dst, src_stride, dst_stride, 0 + load_row2 7, 16, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 16, 17, src, dst, src_stride, dst_stride, 0 + load_row2 17, 18, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 18, 19, src, dst, src_stride, dst_stride, 0 + load_row2 19, 20, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 20, 21, src, dst, src_stride, dst_stride, 0 + load_row2 21, 22, src, dst, src_stride, dst_stride + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + load_row 22, 23, src, dst, src_stride, dst_stride, 0 + load_row2 23, 24, src, dst, src_stride, dst_stride + + // pack rows + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + mov v4.d[1], v6.d[0] + mov v5.d[1], v7.d[0] + + mov v16.d[1], v18.d[0] + mov v17.d[1], v19.d[0] + + mov v20.d[1], v22.d[0] + mov v21.d[1], v23.d[0] + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + interleave v16, v17, v18, v19 + interleave v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave_pairs v0, v1, v2, v3 + interleave_pairs v4, v5, v6, v7 + interleave_pairs v16, v17, v18, v19 + interleave_pairs v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + interleave v0, v1, v2, v3 + interleave v4, v5, v6, v7 + interleave v16, v17, v18, v19 + interleave v20, v21, v22, v23 + + butterfly v2, v3, v0, v1 + butterfly v6, v7, v4, v5 + butterfly v18, v19, v16, v17 + butterfly v22, v23, v20, v21 + + abs v2.8h, v2.8h + abs v3.8h, v3.8h + abs v6.8h, v6.8h + abs v7.8h, v7.8h + abs v18.8h, v18.8h + abs v19.8h, v19.8h + abs v22.8h, v22.8h + abs v23.8h, v23.8h + + add v2.8h, v2.8h, v3.8h + add v6.8h, v6.8h, v7.8h + add v18.8h, v18.8h, v19.8h + add v22.8h, v22.8h, v23.8h + + add v2.8h, v2.8h, v6.8h + add v18.8h, v18.8h, v22.8h + add v0.8h, v2.8h, v18.8h + + addv h0, v0.8h + fmov w0, s0 + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride +endfunc + +.macro load_rows n0, n1, n2, src, dst, src_stride, dst_stride, n3=0, n4=0 +.if \n3 == 0 + ldr d\n0, [\src] + ldr d\n1, [\dst] +.else + ldr q\n0, [\src] + ldr q\n1, [\dst] + usubl2 v\n3\().8h, v\n0\().16b, v\n1\().16b +.endif + usubl v\n0\().8h, v\n0\().8b, v\n1\().8b + +.if \n4 == 0 + ldr d\n1, [\src, \src_stride] + ldr d\n2, [\dst, \dst_stride] +.else + ldr q\n1, [\src, \src_stride] + ldr q\n2, [\dst, \dst_stride] + usubl2 v\n4\().8h, v\n1\().16b, v\n2\().16b +.endif + usubl v\n1\().8h, v\n1\().8b, v\n2\().8b + + add \src, \src, \src_stride, lsl 1 + add \dst, \dst, \dst_stride, lsl 1 +.endm + +.macro HADAMARD_8X8_H \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // Horizontal transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + + interleave v\a0, v\a1, v\b0, v\b1 + interleave v\a2, v\a3, v\b2, v\b3 + interleave v\a4, v\a5, v\b4, v\b5 + interleave v\a6, v\a7, v\b6, v\b7 + + butterfly v\b0, v\b2, v\a0, v\a2 + butterfly v\b1, v\b3, v\a1, v\a3 + butterfly v\b4, v\b6, v\a4, v\a6 + butterfly v\b5, v\b7, v\a5, v\a7 + + interleave_pairs v\a0, v\a2, v\b0, v\b2 + interleave_pairs v\a1, v\a3, v\b1, v\b3 + interleave_pairs v\a4, v\a6, v\b4, v\b6 + interleave_pairs v\a5, v\a7, v\b5, v\b7 + + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 + + interleave_quads v\a0, v\a4, v\b0, v\b4 + interleave_quads v\a1, v\a5, v\b1, v\b5 + interleave_quads v\a2, v\a6, v\b2, v\b6 + interleave_quads v\a3, v\a7, v\b3, v\b7 +.endm + +.macro HADAMARD_8X8_V \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // Vertical transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\b0, v\b2 + butterfly v\a1, v\a3, v\b1, v\b3 + butterfly v\a4, v\a6, v\b4, v\b6 + butterfly v\a5, v\a7, v\b5, v\b7 + + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 +.endm + +.macro SUM_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + // absolute value of transform coefficients + abs v\b0\().8h, v\b0\().8h + abs v\b1\().8h, v\b1\().8h + abs v\b2\().8h, v\b2\().8h + abs v\b3\().8h, v\b3\().8h + abs v\b4\().8h, v\b4\().8h + abs v\b5\().8h, v\b5\().8h + abs v\b6\().8h, v\b6\().8h + abs v\b7\().8h, v\b7\().8h + + // stage 1 sum + sxtl v\a0\().4s, v\b0\().4h + sxtl v\a1\().4s, v\b1\().4h + sxtl v\a2\().4s, v\b2\().4h + sxtl v\a3\().4s, v\b3\().4h + saddw2 v\a0\().4s, v\a0\().4s, v\b0\().8h + saddw2 v\a1\().4s, v\a1\().4s, v\b1\().8h + saddw2 v\a2\().4s, v\a2\().4s, v\b2\().8h + saddw2 v\a3\().4s, v\a3\().4s, v\b3\().8h + saddw v\a0\().4s, v\a0\().4s, v\b4\().4h + saddw2 v\a1\().4s, v\a1\().4s, v\b4\().8h + saddw v\a2\().4s, v\a2\().4s, v\b5\().4h + saddw2 v\a3\().4s, v\a3\().4s, v\b5\().8h + saddw v\a0\().4s, v\a0\().4s, v\b6\().4h + saddw2 v\a1\().4s, v\a1\().4s, v\b6\().8h + saddw v\a2\().4s, v\a2\().4s, v\b7\().4h + saddw2 v\a3\().4s, v\a3\().4s, v\b7\().8h + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + + // stage 3 sum + add v0.4s, v\a0\().4s, v\a2\().4s + addv s0, v0.4s +.endm + +.macro SATD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 + + HADAMARD_8X8_H \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + HADAMARD_8X8_V \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + SUM_HADAMARD_8X8 \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 +.endm + + +function satd8x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define height w13 + + mov height, 8 + mov total, wzr + + // 0, 1; 2, 3 + // 4, 5; 6, 7 + // 16, 17; 20, 21 + // 18, 19; 22, 23 + +L(satd_w8): + load_rows 0, 1, 2, src, dst, src_stride, dst_stride + load_rows 4, 5, 6, src, dst, src_stride, dst_stride + load_rows 16, 17, 20, src, dst, src_stride, dst_stride + load_rows 18, 19, 22, src, dst, src_stride, dst_stride + + SATD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23 + + fmov subtotal, s0 + add total, subtotal, total + + subs height, height, #8 + bne L(satd_w8) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef height +endfunc + +.macro DOUBLE_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // Horizontal transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + butterfly v\a0, v\a1, v\c0, v\c1 + butterfly v\a2, v\a3, v\c2, v\c3 + butterfly v\a4, v\a5, v\c4, v\c5 + butterfly v\a6, v\a7, v\c6, v\c7 + + interleave v\c0, v\c1, v\b0, v\b1 + interleave v\c2, v\c3, v\b2, v\b3 + interleave v\c4, v\c5, v\b4, v\b5 + interleave v\c6, v\c7, v\b6, v\b7 + interleave v\b0, v\b1, v\a0, v\a1 + interleave v\b2, v\b3, v\a2, v\a3 + interleave v\b4, v\b5, v\a4, v\a5 + interleave v\b6, v\b7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\c0, v\c2 + butterfly v\a1, v\a3, v\c1, v\c3 + butterfly v\a4, v\a6, v\c4, v\c6 + butterfly v\a5, v\a7, v\c5, v\c7 + butterfly v\c0, v\c2, v\b0, v\b2 + butterfly v\c1, v\c3, v\b1, v\b3 + butterfly v\c4, v\c6, v\b4, v\b6 + butterfly v\c5, v\c7, v\b5, v\b7 + + interleave_pairs v\b0, v\b2, v\a0, v\a2 + interleave_pairs v\b1, v\b3, v\a1, v\a3 + interleave_pairs v\b4, v\b6, v\a4, v\a6 + interleave_pairs v\b5, v\b7, v\a5, v\a7 + interleave_pairs v\a0, v\a2, v\c0, v\c2 + interleave_pairs v\a1, v\a3, v\c1, v\c3 + interleave_pairs v\a4, v\a6, v\c4, v\c6 + interleave_pairs v\a5, v\a7, v\c5, v\c7 + + butterfly v\c0, v\c4, v\b0, v\b4 + butterfly v\c1, v\c5, v\b1, v\b5 + butterfly v\c2, v\c6, v\b2, v\b6 + butterfly v\c3, v\c7, v\b3, v\b7 + butterfly v\b0, v\b4, v\a0, v\a4 + butterfly v\b1, v\b5, v\a1, v\a5 + butterfly v\b2, v\b6, v\a2, v\a6 + butterfly v\b3, v\b7, v\a3, v\a7 + + interleave_quads v\a0, v\a4, v\c0, v\c4 + interleave_quads v\a1, v\a5, v\c1, v\c5 + interleave_quads v\a2, v\a6, v\c2, v\c6 + interleave_quads v\a3, v\a7, v\c3, v\c7 + interleave_quads v\c0, v\c4, v\b0, v\b4 + interleave_quads v\c1, v\c5, v\b1, v\b5 + interleave_quads v\c2, v\c6, v\b2, v\b6 + interleave_quads v\c3, v\c7, v\b3, v\b7 + + // Vertical transform + + butterfly v\b0, v\b1, v\a0, v\a1 + butterfly v\b2, v\b3, v\a2, v\a3 + butterfly v\b4, v\b5, v\a4, v\a5 + butterfly v\b6, v\b7, v\a6, v\a7 + butterfly v\a0, v\a1, v\c0, v\c1 + butterfly v\a2, v\a3, v\c2, v\c3 + butterfly v\a4, v\a5, v\c4, v\c5 + butterfly v\a6, v\a7, v\c6, v\c7 + + butterfly v\c0, v\c2, v\b0, v\b2 + butterfly v\c1, v\c3, v\b1, v\b3 + butterfly v\c4, v\c6, v\b4, v\b6 + butterfly v\c5, v\c7, v\b5, v\b7 + butterfly v\b0, v\b2, v\a0, v\a2 + butterfly v\b1, v\b3, v\a1, v\a3 + butterfly v\b4, v\b6, v\a4, v\a6 + butterfly v\b5, v\b7, v\a5, v\a7 + + butterfly v\a0, v\a4, v\c0, v\c4 + butterfly v\a1, v\a5, v\c1, v\c5 + butterfly v\a2, v\a6, v\c2, v\c6 + butterfly v\a3, v\a7, v\c3, v\c7 + butterfly v\c0, v\c4, v\b0, v\b4 + butterfly v\c1, v\c5, v\b1, v\b5 + butterfly v\c2, v\c6, v\b2, v\b6 + butterfly v\c3, v\c7, v\b3, v\b7 +.endm + +.macro SUM_DOUBLE_HADAMARD_8X8 \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // absolute value of transform coefficients + abs v\a0\().8h, v\a0\().8h + abs v\a1\().8h, v\a1\().8h + abs v\a2\().8h, v\a2\().8h + abs v\a3\().8h, v\a3\().8h + abs v\a4\().8h, v\a4\().8h + abs v\a5\().8h, v\a5\().8h + abs v\a6\().8h, v\a6\().8h + abs v\a7\().8h, v\a7\().8h + abs v\c0\().8h, v\c0\().8h + abs v\c1\().8h, v\c1\().8h + abs v\c2\().8h, v\c2\().8h + abs v\c3\().8h, v\c3\().8h + abs v\c4\().8h, v\c4\().8h + abs v\c5\().8h, v\c5\().8h + abs v\c6\().8h, v\c6\().8h + abs v\c7\().8h, v\c7\().8h + + // stage 1 sum + sxtl v\b0\().4s, v\a0\().4h + sxtl v\b1\().4s, v\a1\().4h + sxtl v\b2\().4s, v\a2\().4h + sxtl v\b3\().4s, v\a3\().4h + sxtl v\b4\().4s, v\a4\().4h + sxtl v\b5\().4s, v\a5\().4h + sxtl v\b6\().4s, v\a6\().4h + sxtl v\b7\().4s, v\a7\().4h + saddw2 v\b0\().4s, v\b0\().4s, v\a0\().8h + saddw2 v\b1\().4s, v\b1\().4s, v\a1\().8h + saddw2 v\b2\().4s, v\b2\().4s, v\a2\().8h + saddw2 v\b3\().4s, v\b3\().4s, v\a3\().8h + saddw2 v\b4\().4s, v\b4\().4s, v\a4\().8h + saddw2 v\b5\().4s, v\b5\().4s, v\a5\().8h + saddw2 v\b6\().4s, v\b6\().4s, v\a6\().8h + saddw2 v\b7\().4s, v\b7\().4s, v\a7\().8h + saddw v\b0\().4s, v\b0\().4s, v\c0\().4h + saddw2 v\b1\().4s, v\b1\().4s, v\c0\().8h + saddw v\b2\().4s, v\b2\().4s, v\c1\().4h + saddw2 v\b3\().4s, v\b3\().4s, v\c1\().8h + saddw v\b4\().4s, v\b4\().4s, v\c2\().4h + saddw2 v\b5\().4s, v\b5\().4s, v\c2\().8h + saddw v\b6\().4s, v\b6\().4s, v\c3\().4h + saddw2 v\b7\().4s, v\b7\().4s, v\c3\().8h + saddw v\b0\().4s, v\b0\().4s, v\c4\().4h + saddw2 v\b1\().4s, v\b1\().4s, v\c4\().8h + saddw v\b2\().4s, v\b2\().4s, v\c5\().4h + saddw2 v\b3\().4s, v\b3\().4s, v\c5\().8h + saddw v\b4\().4s, v\b4\().4s, v\c6\().4h + saddw2 v\b5\().4s, v\b5\().4s, v\c6\().8h + saddw v\b6\().4s, v\b6\().4s, v\c7\().4h + saddw2 v\b7\().4s, v\b7\().4s, v\c7\().8h + + // stage 2 sum + add v\b0\().4s, v\b0\().4s, v\b1\().4s + add v\b2\().4s, v\b2\().4s, v\b3\().4s + add v\b4\().4s, v\b4\().4s, v\b5\().4s + add v\b6\().4s, v\b6\().4s, v\b7\().4s + + // stage 3 sum + add v\b0\().4s, v\b0\().4s, v\b2\().4s + add v\b4\().4s, v\b4\().4s, v\b6\().4s + + // stage 4 sum + add v0.4s, v\b0\().4s, v\b4\().4s + addv s0, v0.4s +.endm + +function satd16x8_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define w_ext x11 + #define w_bak w11 + #define width w12 + #define height w13 + + mov height, 8 + mov width, 16 + sxtw w_ext, width + mov total, wzr + + // 0, 1; 2, 3; 24, 25 + // 4, 5; 6, 7; 26, 27 + // 16, 17; 20, 21; 28, 29 + // 18, 19; 22, 23; 30, 31 + +L(satd_w16up): + load_rows 0, 1, 2, src, dst, src_stride, dst_stride, 24, 25 + load_rows 4, 5, 6, src, dst, src_stride, dst_stride, 26, 27 + load_rows 16, 17, 20, src, dst, src_stride, dst_stride, 28, 29 + load_rows 18, 19, 22, src, dst, src_stride, dst_stride, 30, 31 + + DOUBLE_HADAMARD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + SUM_DOUBLE_HADAMARD_8X8 \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + fmov subtotal, s0 + add total, subtotal, total + + sub src, src, src_stride, lsl 3 + sub dst, dst, dst_stride, lsl 3 + add src, src, #16 + add dst, dst, #16 + subs width, width, #16 + bne L(satd_w16up) + + sub src, src, w_ext + sub dst, dst, w_ext + add src, src, src_stride, lsl 3 + add dst, dst, dst_stride, lsl 3 + subs height, height, #8 + mov width, w_bak + bne L(satd_w16up) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef w_ext + #undef w_bak + #undef subtotal + #undef total + #undef height + #undef width +endfunc + +.macro satd_x8up width, height +function satd\width\()x\height\()_neon, export=1 + mov w13, \height +.if \width == 8 + mov w10, wzr + b L(satd_w8) +.else + mov w12, \width + sxtw x11, w12 + mov w10, wzr + b L(satd_w16up) +.endif +endfunc +.endm + +satd_x8up 8, 16 +satd_x8up 8, 32 +satd_x8up 16, 16 +satd_x8up 16, 32 +satd_x8up 16, 64 +satd_x8up 32, 8 +satd_x8up 32, 16 +satd_x8up 32, 32 +satd_x8up 32, 64 +satd_x8up 64, 16 +satd_x8up 64, 32 +satd_x8up 64, 64 +satd_x8up 64, 128 +satd_x8up 128, 64 +satd_x8up 128, 128 + +.macro load_rows_hbd n0, n1, n2, src, dst, src_stride, dst_stride + ldr q\n0, [\src] + ldr q\n1, [\dst] + sub v\n0\().8h, v\n0\().8h, v\n1\().8h + + ldr q\n1, [\src, \src_stride] + ldr q\n2, [\dst, \dst_stride] + sub v\n1\().8h, v\n1\().8h, v\n2\().8h + + add \src, \src, \src_stride, lsl 1 + add \dst, \dst, \dst_stride, lsl 1 +.endm + +.macro HADAMARD_8X8_V_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // Vertical transform + + butterflyw v\b0, v\b1, v\c0, v\c1, v\a0, v\a1 + butterflyw v\b2, v\b3, v\c2, v\c3, v\a2, v\a3 + butterflyw v\b4, v\b5, v\c4, v\c5, v\a4, v\a5 + butterflyw v\b6, v\b7, v\c6, v\c7, v\a6, v\a7 + + butterfly v\a0, v\a2, v\b0, v\b2, 4s + butterfly v\a1, v\a3, v\b1, v\b3, 4s + butterfly v\a4, v\a6, v\b4, v\b6, 4s + butterfly v\a5, v\a7, v\b5, v\b7, 4s + butterfly v\b0, v\b2, v\c0, v\c2, 4s + butterfly v\b1, v\b3, v\c1, v\c3, 4s + butterfly v\b4, v\b6, v\c4, v\c6, 4s + butterfly v\b5, v\b7, v\c5, v\c7, 4s + + butterfly v\c0, v\c4, v\a0, v\a4, 4s + butterfly v\c1, v\c5, v\a1, v\a5, 4s + butterfly v\c2, v\c6, v\a2, v\a6, 4s + butterfly v\c3, v\c7, v\a3, v\a7, 4s + butterfly v\a0, v\a4, v\b0, v\b4, 4s + butterfly v\a1, v\a5, v\b1, v\b5, 4s + butterfly v\a2, v\a6, v\b2, v\b6, 4s + butterfly v\a3, v\a7, v\b3, v\b7, 4s +.endm + +.macro SUM_HADAMARD_8X8_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + // absolute value of transform coefficients + abs v\a0\().4s, v\a0\().4s + abs v\a1\().4s, v\a1\().4s + abs v\a2\().4s, v\a2\().4s + abs v\a3\().4s, v\a3\().4s + abs v\a4\().4s, v\a4\().4s + abs v\a5\().4s, v\a5\().4s + abs v\a6\().4s, v\a6\().4s + abs v\a7\().4s, v\a7\().4s + abs v\c0\().4s, v\c0\().4s + abs v\c1\().4s, v\c1\().4s + abs v\c2\().4s, v\c2\().4s + abs v\c3\().4s, v\c3\().4s + abs v\c4\().4s, v\c4\().4s + abs v\c5\().4s, v\c5\().4s + abs v\c6\().4s, v\c6\().4s + abs v\c7\().4s, v\c7\().4s + + // stage 1 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + add v\a4\().4s, v\a4\().4s, v\a5\().4s + add v\a6\().4s, v\a6\().4s, v\a7\().4s + add v\c0\().4s, v\c0\().4s, v\c1\().4s + add v\c2\().4s, v\c2\().4s, v\c3\().4s + add v\c4\().4s, v\c4\().4s, v\c5\().4s + add v\c6\().4s, v\c6\().4s, v\c7\().4s + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a2\().4s + add v\a4\().4s, v\a4\().4s, v\a6\().4s + add v\c0\().4s, v\c0\().4s, v\c2\().4s + add v\c4\().4s, v\c4\().4s, v\c6\().4s + + // stage 3 sum + add v\a0\().4s, v\a0\().4s, v\a4\().4s + add v\c0\().4s, v\c0\().4s, v\c4\().4s + + // stage 4 sum + add v0.4s, v\a0\().4s, v\c0\().4s + addv s0, v0.4s +.endm + + +.macro SATD_8X8_HBD \ + a0 a1 a2 a3 a4 a5 a6 a7 \ + b0 b1 b2 b3 b4 b5 b6 b7 \ + c0 c1 c2 c3 c4 c5 c6 c7 + + HADAMARD_8X8_H \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7 + + HADAMARD_8X8_V_HBD \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7, \ + \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 + + SUM_HADAMARD_8X8_HBD \ + \a0, \a1, \a2, \a3, \a4, \a5, \a6, \a7, \ + \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 +.endm + +function satd8x8_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define w_ext x11 + #define w_bak w11 + #define width w12 + #define height w13 + + mov height, 8 + mov width, 8 + sxtw w_ext, width + mov total, wzr + + // 0, 1; 2, 3; 24, 25 + // 4, 5; 6, 7; 26, 27 + // 16, 17; 20, 21; 28, 29 + // 18, 19; 22, 23; 30, 31 + +L(satd_w8up_hbd): + load_rows_hbd 0, 1, 2, src, dst, src_stride, dst_stride + load_rows_hbd 4, 5, 6, src, dst, src_stride, dst_stride + load_rows_hbd 16, 17, 20, src, dst, src_stride, dst_stride + load_rows_hbd 18, 19, 22, src, dst, src_stride, dst_stride + + SATD_8X8_HBD \ + 0, 1, 4, 5, 16, 17, 18, 19, \ + 2, 3, 6, 7, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + fmov subtotal, s0 + add total, subtotal, total + + sub src, src, src_stride, lsl 3 + sub dst, dst, dst_stride, lsl 3 + add src, src, #16 + add dst, dst, #16 + subs width, width, #8 + bne L(satd_w8up_hbd) + + sub src, src, w_ext, lsl 1 + sub dst, dst, w_ext, lsl 1 + add src, src, src_stride, lsl 3 + add dst, dst, dst_stride, lsl 3 + subs height, height, #8 + mov width, w_bak + bne L(satd_w8up_hbd) + + mov w0, total + normalize_8 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef w_ext + #undef w_bak + #undef subtotal + #undef total + #undef height + #undef width +endfunc + +.macro satd_x8up_hbd width, height +function satd\width\()x\height\()_hbd_neon, export=1 + mov w13, \height + mov w12, \width + sxtw x11, w12 + mov w10, wzr + b L(satd_w8up_hbd) +endfunc +.endm + +satd_x8up_hbd 8, 16 +satd_x8up_hbd 8, 32 +satd_x8up_hbd 16, 8 +satd_x8up_hbd 16, 16 +satd_x8up_hbd 16, 32 +satd_x8up_hbd 16, 64 +satd_x8up_hbd 32, 8 +satd_x8up_hbd 32, 16 +satd_x8up_hbd 32, 32 +satd_x8up_hbd 32, 64 +satd_x8up_hbd 64, 16 +satd_x8up_hbd 64, 32 +satd_x8up_hbd 64, 64 +satd_x8up_hbd 64, 128 +satd_x8up_hbd 128, 64 +satd_x8up_hbd 128, 128 + +// x0: src: *const u16, +// x1: src_stride: isize, +// x2: dst: *const u16, +// x3: dst_stride: isize, +function satd4x4_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define height w13 + + mov height, 4 + mov total, wzr + +L(satd_w4_hbd): + ldr d0, [src] + ldr d1, [dst] + sub v0.8h, v0.8h, v1.8h + + ldr d1, [src, src_stride] + ldr d2, [dst, dst_stride] + sub v1.8h, v1.8h, v2.8h + + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + ldr d2, [src] + ldr d3, [dst] + sub v2.8h, v2.8h, v3.8h + + ldr d3, [src, src_stride] + ldr d4, [dst, src_stride] + sub v3.8h, v3.8h, v4.8h + + add src, src, src_stride, lsl 1 + add dst, dst, dst_stride, lsl 1 + + // pack rows 0-2, 1-3 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + + // Horizontal transform + butterfly v2, v3, v0, v1 + interleave v0, v1, v2, v3 + butterfly v2, v3, v0, v1 + interleave_pairs v0, v1, v2, v3 + // Vertical transform + + butterfly v2, v3, v0, v1 + interleave v0, v1, v2, v3 + butterflyw v2, v3, v4, v5, v0, v1 + + // absolute value of transform coefficients + abs v2.4s, v2.4s + abs v3.4s, v3.4s + abs v4.4s, v4.4s + abs v5.4s, v5.4s + + // stage 1 sum + add v2.4s, v2.4s, v3.4s + add v4.4s, v4.4s, v5.4s + + // stage 2 sum + add v0.4s, v2.4s, v4.4s + addv s0, v0.4s + + fmov subtotal, s0 + add total, subtotal, total + + subs height, height, #4 + bne L(satd_w4_hbd) + + mov w0, total + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef height +endfunc + +function satd4x8_hbd_neon, export=1 + mov w13, 8 + mov w10, wzr + b L(satd_w4_hbd) +endfunc + +function satd4x16_hbd_neon, export=1 + mov w13, 16 + mov w10, wzr + b L(satd_w4_hbd) +endfunc + +.macro SUM_DOUBLE_HADAMARD_4X4_HBD \ + a0 a1 a2 a3 c0 c1 c2 c3 + + // absolute value of transform coefficients + abs v\a0\().4s, v\a0\().4s + abs v\a1\().4s, v\a1\().4s + abs v\a2\().4s, v\a2\().4s + abs v\a3\().4s, v\a3\().4s + abs v\c0\().4s, v\c0\().4s + abs v\c1\().4s, v\c1\().4s + abs v\c2\().4s, v\c2\().4s + abs v\c3\().4s, v\c3\().4s + + // stage 1 sum + add v\a0\().4s, v\a0\().4s, v\a1\().4s + add v\a2\().4s, v\a2\().4s, v\a3\().4s + add v\c0\().4s, v\c0\().4s, v\c1\().4s + add v\c2\().4s, v\c2\().4s, v\c3\().4s + + // stage 2 sum + add v\a0\().4s, v\a0\().4s, v\a2\().4s + add v\c0\().4s, v\c0\().4s, v\c2\().4s + + // stage 3 sum + add v0.4s, v\a0\().4s, v\c0\().4s + addv s0, v0.4s +.endm + +function satd8x4_hbd_neon, export=1 + #define src x0 + #define src_stride x1 + #define dst x2 + #define dst_stride x3 + + #define subtotal w9 + #define total w10 + #define width w12 + + mov width, 8 + mov total, wzr + +L(satd_h4_hbd): + ldr q0, [src] + ldr q1, [dst] + sub v0.8h, v0.8h, v1.8h + + ldr q1, [src, src_stride] + ldr q2, [dst, dst_stride] + sub v1.8h, v1.8h, v2.8h + + lsl x8, src_stride, 1 + lsl x9, dst_stride, 1 + + ldr q2, [src, x8] + ldr q3, [dst, x9] + sub v2.8h, v2.8h, v3.8h + + add x8, src_stride, src_stride, lsl 1 + add x9, dst_stride, dst_stride, lsl 1 + + ldr q3, [src, x8] + ldr q4, [dst, x9] + sub v3.8h, v3.8h, v4.8h + + ext v4.16b, v0.16b, v0.16b, 8 + ext v5.16b, v1.16b, v1.16b, 8 + mov v0.d[1], v2.d[0] + mov v1.d[1], v3.d[0] + mov v4.d[1], v2.d[1] + mov v5.d[1], v3.d[1] + + DOUBLE_HADAMARD_4X4 hbd=1 + SUM_DOUBLE_HADAMARD_4X4_HBD 2, 3, 16, 17, 6, 7, 18, 19 + + fmov subtotal, s0 + add total, subtotal, total + + add src, src, #16 + add dst, dst, #16 + subs width, width, #8 + bne L(satd_h4_hbd) + + mov w0, total + normalize_4 + ret + + #undef src + #undef src_stride + #undef dst + #undef dst_stride + + #undef subtotal + #undef total + #undef width +endfunc + +function satd16x4_hbd_neon, export=1 + mov w12, 16 + mov w10, wzr + b L(satd_h4_hbd) +endfunc diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/sse.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sse.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/sse.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/sse.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,522 @@ +/* Copyright (c) 2023, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "src/arm/asm.S" +#include "util.S" + +.macro LOAD_X4 t=q + ldr \t\()0, [x0] + ldr \t\()4, [x2] + ldr \t\()1, [x0, x1] + ldr \t\()5, [x2, x3] + ldr \t\()2, [x0, x11] + ldr \t\()6, [x2, x12] + ldr \t\()3, [x0, x8] + ldr \t\()7, [x2, x9] + ldr \t\()16, [x4] + add x0, x0, x1, lsl 2 + add x2, x2, x3, lsl 2 + add x4, x4, x5 + subs w10, w10, #4 +.ifc \t,q + mov v18.d[0], v16.d[1] +.else + mov v0.\t[1], v1.\t[0] + mov v4.\t[1], v5.\t[0] + mov v2.\t[1], v3.\t[0] + mov v6.\t[1], v7.\t[0] +.endif +.endm + +.macro INIT width, height +.if \width <= 16 + add x11, x1, x1 + add x12, x3, x3 + add x8, x1, x1, lsl 1 + add x9, x3, x3, lsl 1 +.elseif \width >= 64 + mov w8, #(\width) + sxtw x9, w8 +.endif + movi v17.4s, #0 + mov w10, #(\height) +.endm + +// x0: src: *const u8, +// x1: src_stride: isize, +// x2: dst: *const u8, +// x3: dst_stride: isize, +// x4: scale: *const u32, +// x5: scale_stride: isize, +function weighted_sse_4x4_neon, export=1 + INIT 4, 4 +L(wsse_w4): + LOAD_X4 t=s + uabd v0.8b, v0.8b, v4.8b // diff pixel values + uabd v1.8b, v2.8b, v6.8b + umull v0.8h, v0.8b, v0.8b // square + umull v1.8h, v1.8b, v1.8b + uaddl v2.4s, v0.4h, v1.4h // accumulate + uaddl2 v3.4s, v0.8h, v1.8h + add v0.4s, v2.4s, v3.4s + addv s0, v0.4s + umull v0.2d, v0.2s, v16.2s // apply scale + urshr d0, d0, #8 + add v17.2d, v17.2d, v0.2d + bne L(wsse_w4) + fmov x0, d17 + ret +endfunc + +.macro RET_SUM + mov v0.d[0], v17.d[1] + add d0, d0, d17 + fmov x0, d0 + ret +.endm + +function weighted_sse_8x8_neon, export=1 + INIT 8, 8 +L(wsse_w8): + LOAD_X4 t=d + uabd v0.16b, v0.16b, v4.16b // diff pixel values + uabd v1.16b, v2.16b, v6.16b + umull2 v2.8h, v0.16b, v0.16b // square + umull2 v3.8h, v1.16b, v1.16b + umull v0.8h, v0.8b, v0.8b + umull v1.8h, v1.8b, v1.8b + uaddlp v2.4s, v2.8h // accumulate + uaddlp v3.4s, v3.8h + uaddlp v0.4s, v0.8h + uaddlp v1.4s, v1.8h + uaddlp v2.2d, v2.4s + uadalp v2.2d, v3.4s + uadalp v2.2d, v0.4s + uadalp v2.2d, v1.4s + xtn v0.2s, v2.2d + umull v0.2d, v0.2s, v16.2s // apply scale + urshr v0.2d, v0.2d, #8 + add v17.2d, v17.2d, v0.2d + bne L(wsse_w8) + RET_SUM +endfunc + +function weighted_sse_16x16_neon, export=1 + INIT 16, 16 +L(wsse_w16): + LOAD_X4 + uabd v0.16b, v0.16b, v4.16b // diff pixel values + uabd v1.16b, v1.16b, v5.16b + uabd v2.16b, v2.16b, v6.16b + uabd v3.16b, v3.16b, v7.16b + umull2 v4.8h, v0.16b, v0.16b // square + umull2 v5.8h, v1.16b, v1.16b + umull2 v6.8h, v2.16b, v2.16b + umull2 v7.8h, v3.16b, v3.16b + umull v0.8h, v0.8b, v0.8b + umull v1.8h, v1.8b, v1.8b + umull v2.8h, v2.8b, v2.8b + umull v3.8h, v3.8b, v3.8b + uaddlp v4.4s, v4.8h // accumulate + uaddlp v5.4s, v5.8h + uaddlp v6.4s, v6.8h + uaddlp v7.4s, v7.8h + uaddlp v0.4s, v0.8h + uaddlp v1.4s, v1.8h + uaddlp v2.4s, v2.8h + uaddlp v3.4s, v3.8h + uaddlp v4.2d, v4.4s + uadalp v4.2d, v5.4s + uadalp v4.2d, v6.4s + uadalp v4.2d, v7.4s + xtn v4.2s, v4.2d + uaddlp v0.2d, v0.4s + uadalp v0.2d, v1.4s + uadalp v0.2d, v2.4s + uadalp v0.2d, v3.4s + xtn v0.2s, v0.2d + umull v4.2d, v4.2s, v18.2s // apply scale + umull v0.2d, v0.2s, v16.2s + urshr v4.2d, v4.2d, #8 + urshr v0.2d, v0.2d, #8 + add v17.2d, v17.2d, v4.2d + add v17.2d, v17.2d, v0.2d + bne L(wsse_w16) + RET_SUM +endfunc + +.macro LOAD_32X4 vert=1, hbd=0 + ldp q0, q22, [x0] + ldp q4, q26, [x2] + add x0, x0, x1 + add x2, x2, x3 + ldp q1, q23, [x0] + ldp q5, q27, [x2] + add x0, x0, x1 + add x2, x2, x3 + ldp q2, q24, [x0] + ldp q6, q28, [x2] + add x0, x0, x1 + add x2, x2, x3 + ldp q3, q25, [x0] + ldp q7, q29, [x2] + add x0, x0, x1 + add x2, x2, x3 +.if \vert == 1 +.if \hbd == 0 + ldp q16, q19, [x4] +.else + ldr q16, [x4] +.endif + add x4, x4, x5 + subs w10, w10, #4 +.else + sub x0, x0, x1, lsl 2 + sub x2, x2, x3, lsl 2 + add x0, x0, #32 + add x2, x2, #32 +.if \hbd == 0 + ldp q16, q19, [x4] + add x4, x4, #32 +.else + ldr q16, [x4] + add x4, x4, #16 +.endif +.endif + mov v18.d[0], v16.d[1] +.if \hbd == 0 + mov v20.d[0], v19.d[1] +.endif +.endm + +.macro WEIGHTED_SSE_32X4 + uabd v0.16b, v0.16b, v4.16b // diff pixel values + uabd v1.16b, v1.16b, v5.16b + uabd v2.16b, v2.16b, v6.16b + uabd v3.16b, v3.16b, v7.16b + uabd v22.16b, v22.16b, v26.16b + uabd v23.16b, v23.16b, v27.16b + uabd v24.16b, v24.16b, v28.16b + uabd v25.16b, v25.16b, v29.16b + umull2 v4.8h, v0.16b, v0.16b // square + umull2 v5.8h, v1.16b, v1.16b + umull2 v6.8h, v2.16b, v2.16b + umull2 v7.8h, v3.16b, v3.16b + umull2 v26.8h, v22.16b, v22.16b + umull2 v27.8h, v23.16b, v23.16b + umull2 v28.8h, v24.16b, v24.16b + umull2 v29.8h, v25.16b, v25.16b + umull v0.8h, v0.8b, v0.8b + umull v1.8h, v1.8b, v1.8b + umull v2.8h, v2.8b, v2.8b + umull v3.8h, v3.8b, v3.8b + umull v22.8h, v22.8b, v22.8b + umull v23.8h, v23.8b, v23.8b + umull v24.8h, v24.8b, v24.8b + umull v25.8h, v25.8b, v25.8b + uaddlp v4.4s, v4.8h // accumulate + uadalp v4.4s, v5.8h + uadalp v4.4s, v6.8h + uadalp v4.4s, v7.8h + uaddlp v26.4s, v26.8h + uadalp v26.4s, v27.8h + uadalp v26.4s, v28.8h + uadalp v26.4s, v29.8h + uaddlp v0.4s, v0.8h + uadalp v0.4s, v1.8h + uadalp v0.4s, v2.8h + uadalp v0.4s, v3.8h + uaddlp v22.4s, v22.8h + uadalp v22.4s, v23.8h + uadalp v22.4s, v24.8h + uadalp v22.4s, v25.8h + uaddlp v4.2d, v4.4s + uaddlp v26.2d, v26.4s + uaddlp v0.2d, v0.4s + uaddlp v22.2d, v22.4s + xtn v4.2s, v4.2d + xtn v26.2s, v26.2d + xtn v0.2s, v0.2d + xtn v22.2s, v22.2d + umull v4.2d, v4.2s, v18.2s // apply scale + umull v26.2d, v26.2s, v20.2s + umull v0.2d, v0.2s, v16.2s + umull v22.2d, v22.2s, v19.2s + urshr v4.2d, v4.2d, #8 + urshr v26.2d, v26.2d, #8 + urshr v0.2d, v0.2d, #8 + urshr v22.2d, v22.2d, #8 + add v4.2d, v4.2d, v26.2d + add v0.2d, v0.2d, v22.2d + add v17.2d, v17.2d, v4.2d + add v17.2d, v17.2d, v0.2d +.endm + +function weighted_sse_32x32_neon, export=1 + INIT 32, 32 +L(wsse_w32): + LOAD_32X4 + WEIGHTED_SSE_32X4 + bne L(wsse_w32) + RET_SUM +endfunc + +function weighted_sse_64x64_neon, export=1 + INIT 64, 64 +L(wsse_w32up): + LOAD_32X4 vert=0 + WEIGHTED_SSE_32X4 + subs w8, w8, #32 + bne L(wsse_w32up) + mov w8, w9 + sub x0, x0, x9 + sub x2, x2, x9 + add x0, x0, x1, lsl 2 + add x2, x2, x3, lsl 2 + sub x4, x4, x9 + add x4, x4, x5 + subs w10, w10, #4 + bne L(wsse_w32up) + RET_SUM +endfunc + +.macro weighted_sse width, height +function weighted_sse_\width\()x\height\()_neon, export=1 + INIT \width, \height +.if \width <= 32 + b L(wsse_w\width) +.else + b L(wsse_w32up) +.endif +endfunc +.endm + +weighted_sse 4, 8 +weighted_sse 4, 16 +weighted_sse 8, 4 +weighted_sse 8, 16 +weighted_sse 8, 32 +weighted_sse 16, 4 +weighted_sse 16, 8 +weighted_sse 16, 32 +weighted_sse 16, 64 +weighted_sse 32, 8 +weighted_sse 32, 16 +weighted_sse 32, 64 +weighted_sse 64, 16 +weighted_sse 64, 32 +weighted_sse 64, 128 +weighted_sse 128, 64 +weighted_sse 128, 128 + +.macro LOAD_X4_HBD t=q + ldr \t\()0, [x0] + ldr \t\()4, [x2] + ldr \t\()1, [x0, x1] + ldr \t\()5, [x2, x3] + ldr \t\()2, [x0, x11] + ldr \t\()6, [x2, x12] + ldr \t\()3, [x0, x8] + ldr \t\()7, [x2, x9] +.ifc \t,q + ldr d16, [x4] +.else + ldr s16, [x4] +.endif + add x0, x0, x1, lsl 2 + add x2, x2, x3, lsl 2 + add x4, x4, x5 + subs w10, w10, #4 +.endm + +.macro INIT_HBD width, height +.if \width <= 8 + add x11, x1, x1 + add x12, x3, x3 + add x8, x1, x1, lsl 1 + add x9, x3, x3, lsl 1 +.elseif \width >= 32 + mov w8, #(\width) + sxtw x9, w8 +.endif + movi v17.4s, #0 + mov w10, #(\height) +.endm + +// x0: src: *const u16, +// x1: src_stride: isize, +// x2: dst: *const u16, +// x3: dst_stride: isize, +// x4: scale: *const u32, +// x5: scale_stride: isize, +function weighted_sse_4x4_hbd_neon, export=1 + INIT_HBD 4, 4 +L(wsse_hbd_w4): + LOAD_X4_HBD t=d + uabd v0.8h, v0.8h, v4.8h // diff pixel values + uabd v1.8h, v1.8h, v5.8h + uabd v2.8h, v2.8h, v6.8h + uabd v3.8h, v3.8h, v7.8h + umull v0.4s, v0.4h, v0.4h // square + umull v1.4s, v1.4h, v1.4h + umull v2.4s, v2.4h, v2.4h + umull v3.4s, v3.4h, v3.4h + add v0.4s, v0.4s, v1.4s // accumulate + add v2.4s, v2.4s, v3.4s + add v0.4s, v0.4s, v2.4s + addv s0, v0.4s + umull v0.2d, v0.2s, v16.2s // apply scale + urshr d0, d0, #8 + add v17.2d, v17.2d, v0.2d + bne L(wsse_hbd_w4) + fmov x0, d17 + ret +endfunc + +function weighted_sse_8x8_hbd_neon, export=1 + INIT_HBD 8, 8 +L(wsse_hbd_w8): + LOAD_X4_HBD + uabd v4.8h, v0.8h, v4.8h // diff pixel values + uabd v5.8h, v1.8h, v5.8h + uabd v6.8h, v2.8h, v6.8h + uabd v7.8h, v3.8h, v7.8h + umull v0.4s, v4.4h, v4.4h // square + umull v1.4s, v5.4h, v5.4h + umull v2.4s, v6.4h, v6.4h + umull v3.4s, v7.4h, v7.4h + umull2 v4.4s, v4.8h, v4.8h + umull2 v5.4s, v5.8h, v5.8h + umull2 v6.4s, v6.8h, v6.8h + umull2 v7.4s, v7.8h, v7.8h + add v0.4s, v0.4s, v1.4s // accumulate + add v2.4s, v2.4s, v3.4s + add v4.4s, v4.4s, v5.4s + add v6.4s, v6.4s, v7.4s + add v0.4s, v0.4s, v2.4s + add v4.4s, v4.4s, v6.4s + addv s0, v0.4s + addv s4, v4.4s + mov v0.s[1], v4.s[0] + umull v0.2d, v0.2s, v16.2s // apply scale + urshr v0.2d, v0.2d, #8 + add v17.2d, v17.2d, v0.2d + bne L(wsse_hbd_w8) + RET_SUM +endfunc + +.macro WEIGHTED_SSE_16X4_HBD + uabd v0.8h, v0.8h, v4.8h // diff pixel values + uabd v1.8h, v1.8h, v5.8h + uabd v2.8h, v2.8h, v6.8h + uabd v3.8h, v3.8h, v7.8h + uabd v22.8h, v22.8h, v26.8h + uabd v23.8h, v23.8h, v27.8h + uabd v24.8h, v24.8h, v28.8h + uabd v25.8h, v25.8h, v29.8h + umull2 v4.4s, v0.8h, v0.8h // square + umull2 v5.4s, v1.8h, v1.8h + umull2 v6.4s, v2.8h, v2.8h + umull2 v7.4s, v3.8h, v3.8h + umull2 v26.4s, v22.8h, v22.8h + umull2 v27.4s, v23.8h, v23.8h + umull2 v28.4s, v24.8h, v24.8h + umull2 v29.4s, v25.8h, v25.8h + umull v0.4s, v0.4h, v0.4h + umull v1.4s, v1.4h, v1.4h + umull v2.4s, v2.4h, v2.4h + umull v3.4s, v3.4h, v3.4h + umull v22.4s, v22.4h, v22.4h + umull v23.4s, v23.4h, v23.4h + umull v24.4s, v24.4h, v24.4h + umull v25.4s, v25.4h, v25.4h + add v0.4s, v0.4s, v1.4s // accumulate + add v2.4s, v2.4s, v3.4s + add v4.4s, v4.4s, v5.4s + add v6.4s, v6.4s, v7.4s + add v22.4s, v22.4s, v23.4s + add v24.4s, v24.4s, v25.4s + add v26.4s, v26.4s, v27.4s + add v28.4s, v28.4s, v29.4s + add v0.4s, v0.4s, v2.4s + add v4.4s, v4.4s, v6.4s + add v22.4s, v22.4s, v24.4s + add v26.4s, v26.4s, v28.4s + addv s0, v0.4s + addv s4, v4.4s + addv s22, v22.4s + addv s26, v26.4s + mov v0.s[1], v4.s[0] + mov v22.s[1], v26.s[0] + umull v0.2d, v0.2s, v16.2s // apply scale + umull v22.2d, v22.2s, v18.2s + urshr v0.2d, v0.2d, #8 + urshr v22.2d, v22.2d, #8 + add v0.2d, v0.2d, v22.2d + add v17.2d, v17.2d, v0.2d +.endm + +function weighted_sse_16x16_hbd_neon, export=1 + INIT_HBD 16, 16 +L(wsse_hbd_w16): + LOAD_32X4 vert=1, hbd=1 + WEIGHTED_SSE_16X4_HBD + bne L(wsse_hbd_w16) + RET_SUM +endfunc + +function weighted_sse_32x32_hbd_neon, export=1 + INIT_HBD 32, 32 +L(wsse_hbd_w32up): + LOAD_32X4 vert=0, hbd=1 + WEIGHTED_SSE_16X4_HBD + subs w8, w8, #16 + bne L(wsse_hbd_w32up) + mov w8, w9 + sub x0, x0, x9, lsl 1 + sub x2, x2, x9, lsl 1 + add x0, x0, x1, lsl 2 + add x2, x2, x3, lsl 2 + sub x4, x4, x9 + add x4, x4, x5 + subs w10, w10, #4 + bne L(wsse_hbd_w32up) + RET_SUM +endfunc + +.macro weighted_sse_hbd width, height +function weighted_sse_\width\()x\height\()_hbd_neon, export=1 + INIT_HBD \width, \height +.if \width <= 16 + b L(wsse_hbd_w\width) +.else + b L(wsse_hbd_w32up) +.endif +endfunc +.endm + +weighted_sse_hbd 4, 8 +weighted_sse_hbd 4, 16 +weighted_sse_hbd 8, 4 +weighted_sse_hbd 8, 16 +weighted_sse_hbd 8, 32 +weighted_sse_hbd 16, 4 +weighted_sse_hbd 16, 8 +weighted_sse_hbd 16, 32 +weighted_sse_hbd 16, 64 +weighted_sse_hbd 32, 8 +weighted_sse_hbd 32, 16 +weighted_sse_hbd 32, 64 +weighted_sse_hbd 64, 16 +weighted_sse_hbd 64, 32 +weighted_sse_hbd 64, 64 +weighted_sse_hbd 64, 128 +weighted_sse_hbd 128, 64 +weighted_sse_hbd 128, 128 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/util.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/util.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/64/util.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/64/util.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,229 @@ +/****************************************************************************** + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2015 Martin Storsjo + * Copyright © 2015 Janne Grunau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef DAV1D_SRC_ARM_64_UTIL_S +#define DAV1D_SRC_ARM_64_UTIL_S + +#include "config.h" +#include "src/arm/asm.S" + +.macro movrel rd, val, offset=0 +#if defined(__APPLE__) + .if \offset < 0 + adrp \rd, \val@PAGE + add \rd, \rd, \val@PAGEOFF + sub \rd, \rd, -(\offset) + .else + adrp \rd, \val+(\offset)@PAGE + add \rd, \rd, \val+(\offset)@PAGEOFF + .endif +#elif defined(PIC) && defined(_WIN32) + .if \offset < 0 + adrp \rd, \val + add \rd, \rd, :lo12:\val + sub \rd, \rd, -(\offset) + .else + adrp \rd, \val+(\offset) + add \rd, \rd, :lo12:\val+(\offset) + .endif +#elif defined(PIC) + adrp \rd, \val+(\offset) + add \rd, \rd, :lo12:\val+(\offset) +#else + ldr \rd, =\val+\offset +#endif +.endm + +.macro sub_sp space +#ifdef _WIN32 +.if \space > 8192 + // Here, we'd need to touch two (or more) pages while decrementing + // the stack pointer. + .error "sub_sp_align doesn't support values over 8K at the moment" +.elseif \space > 4096 + sub x16, sp, #4096 + ldr xzr, [x16] + sub sp, x16, #(\space - 4096) +.else + sub sp, sp, #\space +.endif +#else +.if \space >= 4096 + sub sp, sp, #(\space)/4096*4096 +.endif +.if (\space % 4096) != 0 + sub sp, sp, #(\space)%4096 +.endif +#endif +.endm + +.macro transpose_8x8b_xtl r0, r1, r2, r3, r4, r5, r6, r7, xtl + // a0 b0 a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 a6 b6 a7 b7 + zip1 \r0\().16b, \r0\().16b, \r1\().16b + // c0 d0 c1 d1 c2 d2 d3 d3 c4 d4 c5 d5 c6 d6 d7 d7 + zip1 \r2\().16b, \r2\().16b, \r3\().16b + // e0 f0 e1 f1 e2 f2 e3 f3 e4 f4 e5 f5 e6 f6 e7 f7 + zip1 \r4\().16b, \r4\().16b, \r5\().16b + // g0 h0 g1 h1 g2 h2 h3 h3 g4 h4 g5 h5 g6 h6 h7 h7 + zip1 \r6\().16b, \r6\().16b, \r7\().16b + + // a0 b0 c0 d0 a2 b2 c2 d2 a4 b4 c4 d4 a6 b6 c6 d6 + trn1 \r1\().8h, \r0\().8h, \r2\().8h + // a1 b1 c1 d1 a3 b3 c3 d3 a5 b5 c5 d5 a7 b7 c7 d7 + trn2 \r3\().8h, \r0\().8h, \r2\().8h + // e0 f0 g0 h0 e2 f2 g2 h2 e4 f4 g4 h4 e6 f6 g6 h6 + trn1 \r5\().8h, \r4\().8h, \r6\().8h + // e1 f1 g1 h1 e3 f3 g3 h3 e5 f5 g5 h5 e7 f7 g7 h7 + trn2 \r7\().8h, \r4\().8h, \r6\().8h + + // a0 b0 c0 d0 e0 f0 g0 h0 a4 b4 c4 d4 e4 f4 g4 h4 + trn1 \r0\().4s, \r1\().4s, \r5\().4s + // a2 b2 c2 d2 e2 f2 g2 h2 a6 b6 c6 d6 e6 f6 g6 h6 + trn2 \r2\().4s, \r1\().4s, \r5\().4s + // a1 b1 c1 d1 e1 f1 g1 h1 a5 b5 c5 d5 e5 f5 g5 h5 + trn1 \r1\().4s, \r3\().4s, \r7\().4s + // a3 b3 c3 d3 e3 f3 g3 h3 a7 b7 c7 d7 e7 f7 g7 h7 + trn2 \r3\().4s, \r3\().4s, \r7\().4s + + \xtl\()2 \r4\().8h, \r0\().16b + \xtl \r0\().8h, \r0\().8b + \xtl\()2 \r6\().8h, \r2\().16b + \xtl \r2\().8h, \r2\().8b + \xtl\()2 \r5\().8h, \r1\().16b + \xtl \r1\().8h, \r1\().8b + \xtl\()2 \r7\().8h, \r3\().16b + \xtl \r3\().8h, \r3\().8b +.endm + +.macro transpose_8x8h r0, r1, r2, r3, r4, r5, r6, r7, t8, t9 + trn1 \t8\().8h, \r0\().8h, \r1\().8h + trn2 \t9\().8h, \r0\().8h, \r1\().8h + trn1 \r1\().8h, \r2\().8h, \r3\().8h + trn2 \r3\().8h, \r2\().8h, \r3\().8h + trn1 \r0\().8h, \r4\().8h, \r5\().8h + trn2 \r5\().8h, \r4\().8h, \r5\().8h + trn1 \r2\().8h, \r6\().8h, \r7\().8h + trn2 \r7\().8h, \r6\().8h, \r7\().8h + + trn1 \r4\().4s, \r0\().4s, \r2\().4s + trn2 \r2\().4s, \r0\().4s, \r2\().4s + trn1 \r6\().4s, \r5\().4s, \r7\().4s + trn2 \r7\().4s, \r5\().4s, \r7\().4s + trn1 \r5\().4s, \t9\().4s, \r3\().4s + trn2 \t9\().4s, \t9\().4s, \r3\().4s + trn1 \r3\().4s, \t8\().4s, \r1\().4s + trn2 \t8\().4s, \t8\().4s, \r1\().4s + + trn1 \r0\().2d, \r3\().2d, \r4\().2d + trn2 \r4\().2d, \r3\().2d, \r4\().2d + trn1 \r1\().2d, \r5\().2d, \r6\().2d + trn2 \r5\().2d, \r5\().2d, \r6\().2d + trn2 \r6\().2d, \t8\().2d, \r2\().2d + trn1 \r2\().2d, \t8\().2d, \r2\().2d + trn1 \r3\().2d, \t9\().2d, \r7\().2d + trn2 \r7\().2d, \t9\().2d, \r7\().2d +.endm + +.macro transpose_8x16b r0, r1, r2, r3, r4, r5, r6, r7, t8, t9 + trn1 \t8\().16b, \r0\().16b, \r1\().16b + trn2 \t9\().16b, \r0\().16b, \r1\().16b + trn1 \r1\().16b, \r2\().16b, \r3\().16b + trn2 \r3\().16b, \r2\().16b, \r3\().16b + trn1 \r0\().16b, \r4\().16b, \r5\().16b + trn2 \r5\().16b, \r4\().16b, \r5\().16b + trn1 \r2\().16b, \r6\().16b, \r7\().16b + trn2 \r7\().16b, \r6\().16b, \r7\().16b + + trn1 \r4\().8h, \r0\().8h, \r2\().8h + trn2 \r2\().8h, \r0\().8h, \r2\().8h + trn1 \r6\().8h, \r5\().8h, \r7\().8h + trn2 \r7\().8h, \r5\().8h, \r7\().8h + trn1 \r5\().8h, \t9\().8h, \r3\().8h + trn2 \t9\().8h, \t9\().8h, \r3\().8h + trn1 \r3\().8h, \t8\().8h, \r1\().8h + trn2 \t8\().8h, \t8\().8h, \r1\().8h + + trn1 \r0\().4s, \r3\().4s, \r4\().4s + trn2 \r4\().4s, \r3\().4s, \r4\().4s + trn1 \r1\().4s, \r5\().4s, \r6\().4s + trn2 \r5\().4s, \r5\().4s, \r6\().4s + trn2 \r6\().4s, \t8\().4s, \r2\().4s + trn1 \r2\().4s, \t8\().4s, \r2\().4s + trn1 \r3\().4s, \t9\().4s, \r7\().4s + trn2 \r7\().4s, \t9\().4s, \r7\().4s +.endm + +.macro transpose_4x16b r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().16b, \r0\().16b, \r1\().16b + trn2 \t5\().16b, \r0\().16b, \r1\().16b + trn1 \t6\().16b, \r2\().16b, \r3\().16b + trn2 \t7\().16b, \r2\().16b, \r3\().16b + + trn1 \r0\().8h, \t4\().8h, \t6\().8h + trn2 \r2\().8h, \t4\().8h, \t6\().8h + trn1 \r1\().8h, \t5\().8h, \t7\().8h + trn2 \r3\().8h, \t5\().8h, \t7\().8h +.endm + +.macro transpose_4x4h r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().4h, \r0\().4h, \r1\().4h + trn2 \t5\().4h, \r0\().4h, \r1\().4h + trn1 \t6\().4h, \r2\().4h, \r3\().4h + trn2 \t7\().4h, \r2\().4h, \r3\().4h + + trn1 \r0\().2s, \t4\().2s, \t6\().2s + trn2 \r2\().2s, \t4\().2s, \t6\().2s + trn1 \r1\().2s, \t5\().2s, \t7\().2s + trn2 \r3\().2s, \t5\().2s, \t7\().2s +.endm + +.macro transpose_4x4s r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().4s, \r0\().4s, \r1\().4s + trn2 \t5\().4s, \r0\().4s, \r1\().4s + trn1 \t6\().4s, \r2\().4s, \r3\().4s + trn2 \t7\().4s, \r2\().4s, \r3\().4s + + trn1 \r0\().2d, \t4\().2d, \t6\().2d + trn2 \r2\().2d, \t4\().2d, \t6\().2d + trn1 \r1\().2d, \t5\().2d, \t7\().2d + trn2 \r3\().2d, \t5\().2d, \t7\().2d +.endm + +.macro transpose_4x8h r0, r1, r2, r3, t4, t5, t6, t7 + trn1 \t4\().8h, \r0\().8h, \r1\().8h + trn2 \t5\().8h, \r0\().8h, \r1\().8h + trn1 \t6\().8h, \r2\().8h, \r3\().8h + trn2 \t7\().8h, \r2\().8h, \r3\().8h + + trn1 \r0\().4s, \t4\().4s, \t6\().4s + trn2 \r2\().4s, \t4\().4s, \t6\().4s + trn1 \r1\().4s, \t5\().4s, \t7\().4s + trn2 \r3\().4s, \t5\().4s, \t7\().4s +.endm + +#endif /* DAV1D_SRC_ARM_64_UTIL_S */ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/asm.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/asm.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/asm.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/asm.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,291 @@ +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Janne Grunau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV1D_SRC_ARM_ASM_S +#define DAV1D_SRC_ARM_ASM_S + +#include "config.h" + +#if ARCH_AARCH64 +#define x18 do_not_use_x18 +#define w18 do_not_use_w18 + +/* Support macros for + * - Armv8.3-A Pointer Authentication and + * - Armv8.5-A Branch Target Identification + * features which require emitting a .note.gnu.property section with the + * appropriate architecture-dependent feature bits set. + * + * |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to + * PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be + * used immediately before saving the LR register (x30) to the stack. + * |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring + * it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone + * with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also + * have the same value at the two points. For example: + * + * .global f + * f: + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or + * |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an + * indirect call target. In particular, all symbols exported from a file must + * begin with one of these macros. For example, a leaf function that does not + * save LR can instead use |AARCH64_VALID_CALL_TARGET|: + * + * .globl return_zero + * return_zero: + * AARCH64_VALID_CALL_TARGET + * mov x0, #0 + * ret + * + * A non-leaf function which does not immediately save LR may need both macros + * because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function + * may jump to an alternate implementation before setting up the stack: + * + * .globl with_early_jump + * with_early_jump: + * AARCH64_VALID_CALL_TARGET + * cmp x0, #128 + * b.lt .Lwith_early_jump_128 + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * .Lwith_early_jump_128: + * ... + * ret + * + * These annotations are only required with indirect calls. Private symbols that + * are only the target of direct calls do not require annotations. Also note + * that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not + * indirect jumps (BR). Indirect jumps in assembly are supported through + * |AARCH64_VALID_JUMP_TARGET|. Landing Pads which shall serve for jumps and + * calls can be created using |AARCH64_VALID_JUMP_CALL_TARGET|. + * + * Although not necessary, it is safe to use these macros in 32-bit ARM + * assembly. This may be used to simplify dual 32-bit and 64-bit files. + * + * References: + * - "ELF for the Arm® 64-bit Architecture" + * https: *github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst + * - "Providing protection for complex software" + * https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) +#define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has Branch Target Identification +#define AARCH64_VALID_JUMP_CALL_TARGET hint #38 // BTI 'jc' +#define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' +#define AARCH64_VALID_JUMP_TARGET hint #36 // BTI 'j' +#else +#define GNU_PROPERTY_AARCH64_BTI 0 // No Branch Target Identification +#define AARCH64_VALID_JUMP_CALL_TARGET +#define AARCH64_VALID_CALL_TARGET +#define AARCH64_VALID_JUMP_TARGET +#endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) + +#if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 0)) != 0) // authentication using key A +#define AARCH64_SIGN_LINK_REGISTER paciasp +#define AARCH64_VALIDATE_LINK_REGISTER autiasp +#elif ((__ARM_FEATURE_PAC_DEFAULT & (1 << 1)) != 0) // authentication using key B +#define AARCH64_SIGN_LINK_REGISTER pacibsp +#define AARCH64_VALIDATE_LINK_REGISTER autibsp +#else +#error Pointer authentication defines no valid key! +#endif +#if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 2)) != 0) // authentication of leaf functions +#error Authentication of leaf functions is enabled but not supported in dav1d! +#endif +#define GNU_PROPERTY_AARCH64_PAC (1 << 1) + +#elif defined(__APPLE__) && defined(__arm64e__) + +#define GNU_PROPERTY_AARCH64_PAC 0 +#define AARCH64_SIGN_LINK_REGISTER pacibsp +#define AARCH64_VALIDATE_LINK_REGISTER autibsp + +#else /* __ARM_FEATURE_PAC_DEFAULT */ + +#define GNU_PROPERTY_AARCH64_PAC 0 +#define AARCH64_SIGN_LINK_REGISTER +#define AARCH64_VALIDATE_LINK_REGISTER + +#endif /* !__ARM_FEATURE_PAC_DEFAULT */ + + +#if (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) + .pushsection .note.gnu.property, "a" + .balign 8 + .long 4 + .long 0x10 + .long 0x5 + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4 + .long (GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_PAC) + .long 0 + .popsection +#endif /* (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) */ +#endif /* ARCH_AARCH64 */ + +#if ARCH_ARM + .syntax unified +#ifdef __ELF__ + .arch armv7-a + .fpu neon + .eabi_attribute 10, 0 // suppress Tag_FP_arch + .eabi_attribute 12, 0 // suppress Tag_Advanced_SIMD_arch + .section .note.GNU-stack,"",%progbits // Mark stack as non-executable +#endif /* __ELF__ */ + +#ifdef _WIN32 +#define CONFIG_THUMB 1 +#else +#define CONFIG_THUMB 0 +#endif + +#if CONFIG_THUMB + .thumb +#define A @ +#define T +#else +#define A +#define T @ +#endif /* CONFIG_THUMB */ +#endif /* ARCH_ARM */ + +#if !defined(PIC) +#if defined(__PIC__) +#define PIC __PIC__ +#elif defined(__pic__) +#define PIC __pic__ +#endif +#endif + +#ifndef PRIVATE_PREFIX +#define PRIVATE_PREFIX dav1d_ +#endif + +#define PASTE(a,b) a ## b +#define CONCAT(a,b) PASTE(a,b) + +#ifdef PREFIX +#define EXTERN CONCAT(_,PRIVATE_PREFIX) +#else +#define EXTERN PRIVATE_PREFIX +#endif + +.macro function name, export=0, align=2 + .macro endfunc +#ifdef __ELF__ + .size \name, . - \name +#endif +#if HAVE_AS_FUNC + .endfunc +#endif + .purgem endfunc + .endm + .text + .align \align + .if \export + .global EXTERN\name +#ifdef __ELF__ + .type EXTERN\name, %function + .hidden EXTERN\name +#elif defined(__MACH__) + .private_extern EXTERN\name +#endif +#if HAVE_AS_FUNC + .func EXTERN\name +#endif +EXTERN\name: + .else +#ifdef __ELF__ + .type \name, %function +#endif +#if HAVE_AS_FUNC + .func \name +#endif + .endif +\name: +#if ARCH_AARCH64 + .if \export + AARCH64_VALID_CALL_TARGET + .endif +#endif +.endm + +.macro const name, export=0, align=2 + .macro endconst +#ifdef __ELF__ + .size \name, . - \name +#endif + .purgem endconst + .endm +#if defined(_WIN32) + .section .rdata +#elif !defined(__MACH__) + .section .rodata +#else + .const_data +#endif + .align \align + .if \export + .global EXTERN\name +#ifdef __ELF__ + .hidden EXTERN\name +#elif defined(__MACH__) + .private_extern EXTERN\name +#endif +EXTERN\name: + .endif +\name: +.endm + +#ifdef __APPLE__ +#define L(x) L ## x +#else +#define L(x) .L ## x +#endif + +#define X(x) CONCAT(EXTERN, x) + + +#endif /* DAV1D_SRC_ARM_ASM_S */ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/tables.S clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/tables.S --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/arm/tables.S 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/arm/tables.S 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2019-2022, The rav1e contributors. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +/* + * Copyright © 2018, VideoLAN and dav1d authors + * Copyright © 2018, Two Orioles, LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/arm/asm.S" + +const mc_subpel_filters, export=1, align=3 +.byte 0, 1, -3, 63, 4, -1, 0, 0 /* REGULAR */ +.byte 0, 1, -5, 61, 9, -2, 0, 0 +.byte 0, 1, -6, 58, 14, -4, 1, 0 +.byte 0, 1, -7, 55, 19, -5, 1, 0 +.byte 0, 1, -7, 51, 24, -6, 1, 0 +.byte 0, 1, -8, 47, 29, -6, 1, 0 +.byte 0, 1, -7, 42, 33, -6, 1, 0 +.byte 0, 1, -7, 38, 38, -7, 1, 0 +.byte 0, 1, -6, 33, 42, -7, 1, 0 +.byte 0, 1, -6, 29, 47, -8, 1, 0 +.byte 0, 1, -6, 24, 51, -7, 1, 0 +.byte 0, 1, -5, 19, 55, -7, 1, 0 +.byte 0, 1, -4, 14, 58, -6, 1, 0 +.byte 0, 0, -2, 9, 61, -5, 1, 0 +.byte 0, 0, -1, 4, 63, -3, 1, 0 +.byte 0, 1, 14, 31, 17, 1, 0, 0 /* SMOOTH */ +.byte 0, 0, 13, 31, 18, 2, 0, 0 +.byte 0, 0, 11, 31, 20, 2, 0, 0 +.byte 0, 0, 10, 30, 21, 3, 0, 0 +.byte 0, 0, 9, 29, 22, 4, 0, 0 +.byte 0, 0, 8, 28, 23, 5, 0, 0 +.byte 0, -1, 8, 27, 24, 6, 0, 0 +.byte 0, -1, 7, 26, 26, 7, -1, 0 +.byte 0, 0, 6, 24, 27, 8, -1, 0 +.byte 0, 0, 5, 23, 28, 8, 0, 0 +.byte 0, 0, 4, 22, 29, 9, 0, 0 +.byte 0, 0, 3, 21, 30, 10, 0, 0 +.byte 0, 0, 2, 20, 31, 11, 0, 0 +.byte 0, 0, 2, 18, 31, 13, 0, 0 +.byte 0, 0, 1, 17, 31, 14, 1, 0 +.byte -1, 1, -3, 63, 4, -1, 1, 0 /* SHARP */ +.byte -1, 3, -6, 62, 8, -3, 2, -1 +.byte -1, 4, -9, 60, 13, -5, 3, -1 +.byte -2, 5, -11, 58, 19, -7, 3, -1 +.byte -2, 5, -11, 54, 24, -9, 4, -1 +.byte -2, 5, -12, 50, 30, -10, 4, -1 +.byte -2, 5, -12, 45, 35, -11, 5, -1 +.byte -2, 6, -12, 40, 40, -12, 6, -2 +.byte -1, 5, -11, 35, 45, -12, 5, -2 +.byte -1, 4, -10, 30, 50, -12, 5, -2 +.byte -1, 4, -9, 24, 54, -11, 5, -2 +.byte -1, 3, -7, 19, 58, -11, 5, -2 +.byte -1, 3, -5, 13, 60, -9, 4, -1 +.byte -1, 2, -3, 8, 62, -6, 3, -1 +.byte 0, 1, -1, 4, 63, -3, 1, -1 +.byte 0, 0, -2, 63, 4, -1, 0, 0 /* REGULAR 4 */ +.byte 0, 0, -4, 61, 9, -2, 0, 0 +.byte 0, 0, -5, 58, 14, -3, 0, 0 +.byte 0, 0, -6, 55, 19, -4, 0, 0 +.byte 0, 0, -6, 51, 24, -5, 0, 0 +.byte 0, 0, -7, 47, 29, -5, 0, 0 +.byte 0, 0, -6, 42, 33, -5, 0, 0 +.byte 0, 0, -6, 38, 38, -6, 0, 0 +.byte 0, 0, -5, 33, 42, -6, 0, 0 +.byte 0, 0, -5, 29, 47, -7, 0, 0 +.byte 0, 0, -5, 24, 51, -6, 0, 0 +.byte 0, 0, -4, 19, 55, -6, 0, 0 +.byte 0, 0, -3, 14, 58, -5, 0, 0 +.byte 0, 0, -2, 9, 61, -4, 0, 0 +.byte 0, 0, -1, 4, 63, -2, 0, 0 +.byte 0, 0, 15, 31, 17, 1, 0, 0 /* SMOOTH 4 */ +.byte 0, 0, 13, 31, 18, 2, 0, 0 +.byte 0, 0, 11, 31, 20, 2, 0, 0 +.byte 0, 0, 10, 30, 21, 3, 0, 0 +.byte 0, 0, 9, 29, 22, 4, 0, 0 +.byte 0, 0, 8, 28, 23, 5, 0, 0 +.byte 0, 0, 7, 27, 24, 6, 0, 0 +.byte 0, 0, 6, 26, 26, 6, 0, 0 +.byte 0, 0, 6, 24, 27, 7, 0, 0 +.byte 0, 0, 5, 23, 28, 8, 0, 0 +.byte 0, 0, 4, 22, 29, 9, 0, 0 +.byte 0, 0, 3, 21, 30, 10, 0, 0 +.byte 0, 0, 2, 20, 31, 11, 0, 0 +.byte 0, 0, 2, 18, 31, 13, 0, 0 +.byte 0, 0, 1, 17, 31, 15, 0, 0 +/* Bilin scaled being very rarely used, add a new table entry + * and use the put/prep_8tap_scaled code, thus acting as a + * scaled bilinear filter. */ +.byte 0, 0, 0, 60, 4, 0, 0, 0 +.byte 0, 0, 0, 56, 8, 0, 0, 0 +.byte 0, 0, 0, 52, 12, 0, 0, 0 +.byte 0, 0, 0, 48, 16, 0, 0, 0 +.byte 0, 0, 0, 44, 20, 0, 0, 0 +.byte 0, 0, 0, 40, 24, 0, 0, 0 +.byte 0, 0, 0, 36, 28, 0, 0, 0 +.byte 0, 0, 0, 32, 32, 0, 0, 0 +.byte 0, 0, 0, 28, 36, 0, 0, 0 +.byte 0, 0, 0, 24, 40, 0, 0, 0 +.byte 0, 0, 0, 20, 44, 0, 0, 0 +.byte 0, 0, 0, 16, 48, 0, 0, 0 +.byte 0, 0, 0, 12, 52, 0, 0, 0 +.byte 0, 0, 0, 8, 56, 0, 0, 0 +.byte 0, 0, 0, 4, 60, 0, 0, 0 +endconst + +const filter_intra_taps, export=1, align=4 +.byte -6, 10, -5, 2, -3, 1, -3, 1 /* 0 */ +.byte -4, 6, -3, 2, -3, 2, -3, 1 +.byte 0, 0, 10, 0, 1, 10, 1, 2 +.byte 0, 0, 6, 0, 2, 6, 2, 2 +.byte 0, 12, 0, 9, 0, 7, 10, 5 +.byte 0, 2, 0, 2, 0, 2, 6, 3 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 12, 0, 9, 0, 7, 0, 5, 0 +.byte -10, 16, -6, 0, -4, 0, -2, 0 /* 1 */ +.byte -10, 16, -6, 0, -4, 0, -2, 0 +.byte 0, 0, 16, 0, 0, 16, 0, 0 +.byte 0, 0, 16, 0, 0, 16, 0, 0 +.byte 0, 10, 0, 6, 0, 4, 16, 2 +.byte 0, 0, 0, 0, 0, 0, 16, 0 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 10, 0, 6, 0, 4, 0, 2, 0 +.byte -8, 8, -8, 0, -8, 0, -8, 0 /* 2 */ +.byte -4, 4, -4, 0, -4, 0, -4, 0 +.byte 0, 0, 8, 0, 0, 8, 0, 0 +.byte 0, 0, 4, 0, 0, 4, 0, 0 +.byte 0, 16, 0, 16, 0, 16, 8, 16 +.byte 0, 0, 0, 0, 0, 0, 4, 0 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 16, 0, 16, 0, 16, 0, 16, 0 +.byte -2, 8, -1, 3, -1, 2, 0, 1 /* 3 */ +.byte -1, 4, -1, 3, -1, 2, -1, 2 +.byte 0, 0, 8, 0, 3, 8, 2, 3 +.byte 0, 0, 4, 0, 3, 4, 2, 3 +.byte 0, 10, 0, 6, 0, 4, 8, 2 +.byte 0, 3, 0, 4, 0, 4, 4, 3 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 10, 0, 6, 0, 4, 0, 3, 0 +.byte -12, 14, -10, 0, -9, 0, -8, 0 /* 4 */ +.byte -10, 12, -9, 1, -8, 0, -7, 0 +.byte 0, 0, 14, 0, 0, 14, 0, 0 +.byte 0, 0, 12, 0, 0, 12, 0, 1 +.byte 0, 14, 0, 12, 0, 11, 14, 10 +.byte 0, 0, 0, 0, 0, 1, 12, 1 +.byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 14, 0, 12, 0, 11, 0, 9, 0 +endconst + +const sgr_x_by_x, export=1, align=4 +.byte 255, 128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17 +.byte 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9 +.byte 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6 +.byte 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4 +.byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3 +.byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 +.byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +.byte 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +.byte 0 +endconst + +const mc_warp_filter, export=1, align=3 +/* [-1, 0) */ +.byte 0, 0, 127, 1, 0, 0, 0, 0, 0, - 1, 127, 2, 0, 0, 0, 0 +.byte 1, - 3, 127, 4, - 1, 0, 0, 0, 1, - 4, 126, 6, - 2, 1, 0, 0 +.byte 1, - 5, 126, 8, - 3, 1, 0, 0, 1, - 6, 125, 11, - 4, 1, 0, 0 +.byte 1, - 7, 124, 13, - 4, 1, 0, 0, 2, - 8, 123, 15, - 5, 1, 0, 0 +.byte 2, - 9, 122, 18, - 6, 1, 0, 0, 2, -10, 121, 20, - 6, 1, 0, 0 +.byte 2, -11, 120, 22, - 7, 2, 0, 0, 2, -12, 119, 25, - 8, 2, 0, 0 +.byte 3, -13, 117, 27, - 8, 2, 0, 0, 3, -13, 116, 29, - 9, 2, 0, 0 +.byte 3, -14, 114, 32, -10, 3, 0, 0, 3, -15, 113, 35, -10, 2, 0, 0 +.byte 3, -15, 111, 37, -11, 3, 0, 0, 3, -16, 109, 40, -11, 3, 0, 0 +.byte 3, -16, 108, 42, -12, 3, 0, 0, 4, -17, 106, 45, -13, 3, 0, 0 +.byte 4, -17, 104, 47, -13, 3, 0, 0, 4, -17, 102, 50, -14, 3, 0, 0 +.byte 4, -17, 100, 52, -14, 3, 0, 0, 4, -18, 98, 55, -15, 4, 0, 0 +.byte 4, -18, 96, 58, -15, 3, 0, 0, 4, -18, 94, 60, -16, 4, 0, 0 +.byte 4, -18, 91, 63, -16, 4, 0, 0, 4, -18, 89, 65, -16, 4, 0, 0 +.byte 4, -18, 87, 68, -17, 4, 0, 0, 4, -18, 85, 70, -17, 4, 0, 0 +.byte 4, -18, 82, 73, -17, 4, 0, 0, 4, -18, 80, 75, -17, 4, 0, 0 +.byte 4, -18, 78, 78, -18, 4, 0, 0, 4, -17, 75, 80, -18, 4, 0, 0 +.byte 4, -17, 73, 82, -18, 4, 0, 0, 4, -17, 70, 85, -18, 4, 0, 0 +.byte 4, -17, 68, 87, -18, 4, 0, 0, 4, -16, 65, 89, -18, 4, 0, 0 +.byte 4, -16, 63, 91, -18, 4, 0, 0, 4, -16, 60, 94, -18, 4, 0, 0 +.byte 3, -15, 58, 96, -18, 4, 0, 0, 4, -15, 55, 98, -18, 4, 0, 0 +.byte 3, -14, 52, 100, -17, 4, 0, 0, 3, -14, 50, 102, -17, 4, 0, 0 +.byte 3, -13, 47, 104, -17, 4, 0, 0, 3, -13, 45, 106, -17, 4, 0, 0 +.byte 3, -12, 42, 108, -16, 3, 0, 0, 3, -11, 40, 109, -16, 3, 0, 0 +.byte 3, -11, 37, 111, -15, 3, 0, 0, 2, -10, 35, 113, -15, 3, 0, 0 +.byte 3, -10, 32, 114, -14, 3, 0, 0, 2, - 9, 29, 116, -13, 3, 0, 0 +.byte 2, - 8, 27, 117, -13, 3, 0, 0, 2, - 8, 25, 119, -12, 2, 0, 0 +.byte 2, - 7, 22, 120, -11, 2, 0, 0, 1, - 6, 20, 121, -10, 2, 0, 0 +.byte 1, - 6, 18, 122, - 9, 2, 0, 0, 1, - 5, 15, 123, - 8, 2, 0, 0 +.byte 1, - 4, 13, 124, - 7, 1, 0, 0, 1, - 4, 11, 125, - 6, 1, 0, 0 +.byte 1, - 3, 8, 126, - 5, 1, 0, 0, 1, - 2, 6, 126, - 4, 1, 0, 0 +.byte 0, - 1, 4, 127, - 3, 1, 0, 0, 0, 0, 2, 127, - 1, 0, 0, 0 +/* [0, 1) */ +.byte 0, 0, 0, 127, 1, 0, 0, 0, 0, 0, -1, 127, 2, 0, 0, 0 +.byte 0, 1, -3, 127, 4, -2, 1, 0, 0, 1, -5, 127, 6, -2, 1, 0 +.byte 0, 2, -6, 126, 8, -3, 1, 0, -1, 2, -7, 126, 11, -4, 2, -1 +.byte -1, 3, -8, 125, 13, -5, 2, -1, -1, 3, -10, 124, 16, -6, 3, -1 +.byte -1, 4, -11, 123, 18, -7, 3, -1, -1, 4, -12, 122, 20, -7, 3, -1 +.byte -1, 4, -13, 121, 23, -8, 3, -1, -2, 5, -14, 120, 25, -9, 4, -1 +.byte -1, 5, -15, 119, 27, -10, 4, -1, -1, 5, -16, 118, 30, -11, 4, -1 +.byte -2, 6, -17, 116, 33, -12, 5, -1, -2, 6, -17, 114, 35, -12, 5, -1 +.byte -2, 6, -18, 113, 38, -13, 5, -1, -2, 7, -19, 111, 41, -14, 6, -2 +.byte -2, 7, -19, 110, 43, -15, 6, -2, -2, 7, -20, 108, 46, -15, 6, -2 +.byte -2, 7, -20, 106, 49, -16, 6, -2, -2, 7, -21, 104, 51, -16, 7, -2 +.byte -2, 7, -21, 102, 54, -17, 7, -2, -2, 8, -21, 100, 56, -18, 7, -2 +.byte -2, 8, -22, 98, 59, -18, 7, -2, -2, 8, -22, 96, 62, -19, 7, -2 +.byte -2, 8, -22, 94, 64, -19, 7, -2, -2, 8, -22, 91, 67, -20, 8, -2 +.byte -2, 8, -22, 89, 69, -20, 8, -2, -2, 8, -22, 87, 72, -21, 8, -2 +.byte -2, 8, -21, 84, 74, -21, 8, -2, -2, 8, -22, 82, 77, -21, 8, -2 +.byte -2, 8, -21, 79, 79, -21, 8, -2, -2, 8, -21, 77, 82, -22, 8, -2 +.byte -2, 8, -21, 74, 84, -21, 8, -2, -2, 8, -21, 72, 87, -22, 8, -2 +.byte -2, 8, -20, 69, 89, -22, 8, -2, -2, 8, -20, 67, 91, -22, 8, -2 +.byte -2, 7, -19, 64, 94, -22, 8, -2, -2, 7, -19, 62, 96, -22, 8, -2 +.byte -2, 7, -18, 59, 98, -22, 8, -2, -2, 7, -18, 56, 100, -21, 8, -2 +.byte -2, 7, -17, 54, 102, -21, 7, -2, -2, 7, -16, 51, 104, -21, 7, -2 +.byte -2, 6, -16, 49, 106, -20, 7, -2, -2, 6, -15, 46, 108, -20, 7, -2 +.byte -2, 6, -15, 43, 110, -19, 7, -2, -2, 6, -14, 41, 111, -19, 7, -2 +.byte -1, 5, -13, 38, 113, -18, 6, -2, -1, 5, -12, 35, 114, -17, 6, -2 +.byte -1, 5, -12, 33, 116, -17, 6, -2, -1, 4, -11, 30, 118, -16, 5, -1 +.byte -1, 4, -10, 27, 119, -15, 5, -1, -1, 4, -9, 25, 120, -14, 5, -2 +.byte -1, 3, -8, 23, 121, -13, 4, -1, -1, 3, -7, 20, 122, -12, 4, -1 +.byte -1, 3, -7, 18, 123, -11, 4, -1, -1, 3, -6, 16, 124, -10, 3, -1 +.byte -1, 2, -5, 13, 125, -8, 3, -1, -1, 2, -4, 11, 126, -7, 2, -1 +.byte 0, 1, -3, 8, 126, -6, 2, 0, 0, 1, -2, 6, 127, -5, 1, 0 +.byte 0, 1, -2, 4, 127, -3, 1, 0, 0, 0, 0, 2, 127, -1, 0, 0 +/* [1, 2) */ +.byte 0, 0, 0, 1, 127, 0, 0, 0, 0, 0, 0, - 1, 127, 2, 0, 0 +.byte 0, 0, 1, - 3, 127, 4, - 1, 0, 0, 0, 1, - 4, 126, 6, - 2, 1 +.byte 0, 0, 1, - 5, 126, 8, - 3, 1, 0, 0, 1, - 6, 125, 11, - 4, 1 +.byte 0, 0, 1, - 7, 124, 13, - 4, 1, 0, 0, 2, - 8, 123, 15, - 5, 1 +.byte 0, 0, 2, - 9, 122, 18, - 6, 1, 0, 0, 2, -10, 121, 20, - 6, 1 +.byte 0, 0, 2, -11, 120, 22, - 7, 2, 0, 0, 2, -12, 119, 25, - 8, 2 +.byte 0, 0, 3, -13, 117, 27, - 8, 2, 0, 0, 3, -13, 116, 29, - 9, 2 +.byte 0, 0, 3, -14, 114, 32, -10, 3, 0, 0, 3, -15, 113, 35, -10, 2 +.byte 0, 0, 3, -15, 111, 37, -11, 3, 0, 0, 3, -16, 109, 40, -11, 3 +.byte 0, 0, 3, -16, 108, 42, -12, 3, 0, 0, 4, -17, 106, 45, -13, 3 +.byte 0, 0, 4, -17, 104, 47, -13, 3, 0, 0, 4, -17, 102, 50, -14, 3 +.byte 0, 0, 4, -17, 100, 52, -14, 3, 0, 0, 4, -18, 98, 55, -15, 4 +.byte 0, 0, 4, -18, 96, 58, -15, 3, 0, 0, 4, -18, 94, 60, -16, 4 +.byte 0, 0, 4, -18, 91, 63, -16, 4, 0, 0, 4, -18, 89, 65, -16, 4 +.byte 0, 0, 4, -18, 87, 68, -17, 4, 0, 0, 4, -18, 85, 70, -17, 4 +.byte 0, 0, 4, -18, 82, 73, -17, 4, 0, 0, 4, -18, 80, 75, -17, 4 +.byte 0, 0, 4, -18, 78, 78, -18, 4, 0, 0, 4, -17, 75, 80, -18, 4 +.byte 0, 0, 4, -17, 73, 82, -18, 4, 0, 0, 4, -17, 70, 85, -18, 4 +.byte 0, 0, 4, -17, 68, 87, -18, 4, 0, 0, 4, -16, 65, 89, -18, 4 +.byte 0, 0, 4, -16, 63, 91, -18, 4, 0, 0, 4, -16, 60, 94, -18, 4 +.byte 0, 0, 3, -15, 58, 96, -18, 4, 0, 0, 4, -15, 55, 98, -18, 4 +.byte 0, 0, 3, -14, 52, 100, -17, 4, 0, 0, 3, -14, 50, 102, -17, 4 +.byte 0, 0, 3, -13, 47, 104, -17, 4, 0, 0, 3, -13, 45, 106, -17, 4 +.byte 0, 0, 3, -12, 42, 108, -16, 3, 0, 0, 3, -11, 40, 109, -16, 3 +.byte 0, 0, 3, -11, 37, 111, -15, 3, 0, 0, 2, -10, 35, 113, -15, 3 +.byte 0, 0, 3, -10, 32, 114, -14, 3, 0, 0, 2, - 9, 29, 116, -13, 3 +.byte 0, 0, 2, - 8, 27, 117, -13, 3, 0, 0, 2, - 8, 25, 119, -12, 2 +.byte 0, 0, 2, - 7, 22, 120, -11, 2, 0, 0, 1, - 6, 20, 121, -10, 2 +.byte 0, 0, 1, - 6, 18, 122, - 9, 2, 0, 0, 1, - 5, 15, 123, - 8, 2 +.byte 0, 0, 1, - 4, 13, 124, - 7, 1, 0, 0, 1, - 4, 11, 125, - 6, 1 +.byte 0, 0, 1, - 3, 8, 126, - 5, 1, 0, 0, 1, - 2, 6, 126, - 4, 1 +.byte 0, 0, 0, - 1, 4, 127, - 3, 1, 0, 0, 0, 0, 2, 127, - 1, 0 +/* dummy (replicate row index 191) */ +.byte 0, 0, 0, 0, 2, 127, - 1, 0 +endconst + +const sm_weights, export=1 +.byte 0, 0 /* Unused, because we always offset by bs, which is at least 2. */ +.byte 255, 128 /* bs = 2 */ +.byte 255, 149, 85, 64 /* bs = 4 */ +.byte 255, 197, 146, 105, 73, 50, 37, 32 /* bs = 8 */ +.byte 255, 225, 196, 170, 145, 123, 102, 84 /* bs = 16 */ +.byte 68, 54, 43, 33, 26, 20, 17, 16 +.byte 255, 240, 225, 210, 196, 182, 169, 157 /* bs =32 */ +.byte 145, 133, 122, 111, 101, 92, 83, 74 +.byte 66, 59, 52, 45, 39, 34, 29, 25 +.byte 21, 17, 14, 12, 10, 9, 8, 8 +.byte 255, 248, 240, 233, 225, 218, 210, 203 /* bs = 64 */ +.byte 196, 189, 182, 176, 169, 163, 156, 150 +.byte 144, 138, 133, 127, 121, 116, 111, 106 +.byte 101, 96, 91, 86, 82, 77, 73, 69 +.byte 65, 61, 57, 54, 50, 47, 44, 41 +.byte 38, 35, 32, 29, 27, 25, 22, 20 +.byte 18, 16, 15, 13, 12, 10, 9, 8 +.byte 7, 6, 6, 5, 5, 4, 4, 4 +endconst + +const obmc_masks, export=1, align=4 +.byte 0, 0 /* Unused */ +.byte 19, 0 /* 2 */ +.byte 25, 14, 5, 0 /* 4 */ +.byte 28, 22, 16, 11, 7, 3, 0, 0 /* 8 */ +.byte 30, 27, 24, 21, 18, 15, 12, 10 +.byte 8, 6, 4, 3, 0, 0, 0, 0 /* 16 */ +.byte 31, 29, 28, 26, 24, 23, 21, 20 +.byte 19, 17, 16, 14, 13, 12, 11, 9 +.byte 8, 7, 6, 5, 4, 4, 3, 2 +.byte 0, 0, 0, 0, 0, 0, 0, 0 /* 32 */ +endconst diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/cdef.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/cdef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/cdef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/cdef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,414 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cdef::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::*; +use crate::tiling::PlaneRegionMut; +use crate::util::*; + +type CdefPaddingFn = unsafe extern fn( + tmp: *mut u16, + src: *const u8, + src_stride: isize, + left: *const [u8; 2], + top: *const u8, + bottom: *const u8, + h: i32, + edges: isize, +); + +type CdefPaddingHBDFn = unsafe extern fn( + tmp: *mut u16, + src: *const u16, + src_stride: isize, + left: *const [u16; 2], + top: *const u16, + bottom: *const u16, + h: i32, + edges: isize, +); + +type CdefFilterFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + tmp: *const u16, + pri_strength: i32, + sec_strength: i32, + dir: i32, + damping: i32, + h: i32, + edges: isize, +); + +type CdefFilterHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + tmp: *const u16, + pri_strength: i32, + sec_strength: i32, + dir: i32, + damping: i32, + h: i32, + edges: isize, + bitdepth_max: i32, +); + +#[inline(always)] +const fn decimate_index(xdec: usize, ydec: usize) -> usize { + ((ydec << 1) | xdec) & 3 +} + +pub(crate) unsafe fn cdef_filter_block( + dst: &mut PlaneRegionMut<'_, T>, src: *const T, src_stride: isize, + pri_strength: i32, sec_strength: i32, dir: usize, damping: i32, + bit_depth: usize, xdec: usize, ydec: usize, edges: u8, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut| { + rust::cdef_filter_block( + dst, + src, + src_stride, + pri_strength, + sec_strength, + dir, + damping, + bit_depth, + xdec, + ydec, + edges, + cpu, + ); + }; + + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + match T::type_enum() { + PixelType::U8 => { + match ( + CDEF_PAD_FNS[cpu.as_index()][decimate_index(xdec, ydec)], + CDEF_FILTER_FNS[cpu.as_index()][decimate_index(xdec, ydec)], + ) { + (Some(pad), Some(func)) => { + let h = if ydec == 1 { 4 } else { 8 }; + let tmpstride = if xdec == 1 { 8 } else { 16 } as isize; + const MAXTMPSTRIDE: isize = 16; + const TMPSIZE: usize = (12 * MAXTMPSTRIDE + 8) as usize; + let mut tmp: Aligned<[u16; TMPSIZE]> = + Aligned::new([CDEF_VERY_LARGE; TMPSIZE]); + let top = src.offset(-2 * src_stride); + let bottom = src.offset(h as isize * src_stride); + let mut left: Aligned<[[u8; 2]; 8]> = Aligned::new([[0; 2]; 8]); + + // Rather than modify the dav1d assembly, just swallow our + // pride and copy relevant portions of src into a left + // array. The array is a monolithic, packed [x=2][y=8], + // though it is aligned to start on a 16-byte boundary. + if edges & CDEF_HAVE_LEFT != 0 { + let mut wptr = src.offset(-2) as *const u8; + for i in 0..h { + left.data[i as usize][0] = *wptr; + left.data[i as usize][1] = *wptr.add(1); + wptr = wptr.offset(src_stride); + } + } + + // dav1d's implicit indexing as of this version: tmp array + // working pointer points to the upper-left of the current + // coded block, not the upper-left of the tmp array storage, + // with an adjustment to ensure UL of the block is 16-byte + // aligned. src, similarly, points to upper left of src + // block being coded. top points to coded block minus two + // rows (that is, src.x, src.y-2). It does _not_ point to + // src.x-2, src.y-2. + (pad)( + tmp.data.as_mut_ptr().offset(2 * tmpstride + 8), + src as *const u8, + T::to_asm_stride(src_stride as usize), + left.data.as_ptr(), + top as *const u8, + bottom as *const u8, + 8 >> ydec, + edges.into(), + ); + + (func)( + dst.data_ptr_mut() as *mut u8, + T::to_asm_stride(dst.plane_cfg.stride), + tmp.data.as_ptr().offset(2 * tmpstride + 8), + pri_strength, + sec_strength, + dir as i32, + damping, + 8 >> ydec, + edges.into(), + ); + } + _ => call_rust(dst), + } + } + PixelType::U16 => { + match ( + CDEF_PAD_HBD_FNS[cpu.as_index()][decimate_index(xdec, ydec)], + CDEF_FILTER_HBD_FNS[cpu.as_index()][decimate_index(xdec, ydec)], + ) { + // almost exactly as above, but the call convention isn't + // quite what we'd need to roll 8 bit and HBD together in one + // clause using Rust macros. See comments above for + // indexing/addressing notes. + (Some(pad), Some(func)) => { + let h = if ydec == 1 { 4 } else { 8 }; + let tmpstride = if xdec == 1 { 8 } else { 16 } as isize; + const MAXTMPSTRIDE: isize = 16; + const TMPSIZE: usize = (12 * MAXTMPSTRIDE + 8) as usize; + let mut tmp: Aligned<[u16; TMPSIZE]> = + Aligned::new([CDEF_VERY_LARGE; TMPSIZE]); + let top = src.offset(-2 * src_stride); + let bottom = src.offset(h as isize * src_stride); + let mut left: Aligned<[[u16; 2]; 8]> = Aligned::new([[0; 2]; 8]); + + if edges & CDEF_HAVE_LEFT != 0 { + let mut wptr = src.offset(-2) as *const u16; + for i in 0..h { + left.data[i as usize][0] = *wptr; + left.data[i as usize][1] = *wptr.add(1); + wptr = wptr.offset(src_stride); + } + } + + (pad)( + tmp.data.as_mut_ptr().offset(2 * tmpstride + 8), + src as *const u16, + T::to_asm_stride(src_stride as usize), + left.data.as_ptr(), + top as *const u16, + bottom as *const u16, + 8 >> ydec, + edges.into(), + ); + + (func)( + dst.data_ptr_mut() as *mut u16, + T::to_asm_stride(dst.plane_cfg.stride), + tmp.data.as_ptr().offset(2 * tmpstride + 8), + pri_strength, + sec_strength, + dir as i32, + damping, + 8 >> ydec, + edges.into(), + (1 << bit_depth) - 1, + ); + } + _ => call_rust(dst), + } + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } +} + +extern { + fn rav1e_cdef_filter4_8bpc_neon( + dst: *mut u8, dst_stride: isize, tmp: *const u16, pri_strength: i32, + sec_strength: i32, dir: i32, damping: i32, h: i32, edges: isize, + ); + + fn rav1e_cdef_padding4_8bpc_neon( + tmp: *mut u16, src: *const u8, src_stride: isize, left: *const [u8; 2], + top: *const u8, bottom: *const u8, h: i32, edges: isize, + ); + + fn rav1e_cdef_filter8_8bpc_neon( + dst: *mut u8, dst_stride: isize, tmp: *const u16, pri_strength: i32, + sec_strength: i32, dir: i32, damping: i32, h: i32, edges: isize, + ); + + fn rav1e_cdef_padding8_8bpc_neon( + tmp: *mut u16, src: *const u8, src_stride: isize, left: *const [u8; 2], + top: *const u8, bottom: *const u8, h: i32, edges: isize, + ); + + fn rav1e_cdef_filter4_16bpc_neon( + dst: *mut u16, dst_stride: isize, tmp: *const u16, pri_strength: i32, + sec_strength: i32, dir: i32, damping: i32, h: i32, edges: isize, bd: i32, + ); + + fn rav1e_cdef_padding4_16bpc_neon( + tmp: *mut u16, src: *const u16, src_stride: isize, left: *const [u16; 2], + top: *const u16, bottom: *const u16, h: i32, edges: isize, + ); + + fn rav1e_cdef_filter8_16bpc_neon( + dst: *mut u16, dst_stride: isize, tmp: *const u16, pri_strength: i32, + sec_strength: i32, dir: i32, damping: i32, h: i32, edges: isize, bd: i32, + ); + + fn rav1e_cdef_padding8_16bpc_neon( + tmp: *mut u16, src: *const u16, src_stride: isize, left: *const [u16; 2], + top: *const u16, bottom: *const u16, h: i32, edges: isize, + ); +} + +static CDEF_PAD_FNS_NEON: [Option; 4] = { + let mut out: [Option; 4] = [None; 4]; + out[decimate_index(1, 1)] = Some(rav1e_cdef_padding4_8bpc_neon); + out[decimate_index(1, 0)] = Some(rav1e_cdef_padding4_8bpc_neon); + out[decimate_index(0, 0)] = Some(rav1e_cdef_padding8_8bpc_neon); + out +}; + +static CDEF_FILTER_FNS_NEON: [Option; 4] = { + let mut out: [Option; 4] = [None; 4]; + out[decimate_index(1, 1)] = Some(rav1e_cdef_filter4_8bpc_neon); + out[decimate_index(1, 0)] = Some(rav1e_cdef_filter4_8bpc_neon); + out[decimate_index(0, 0)] = Some(rav1e_cdef_filter8_8bpc_neon); + out +}; + +static CDEF_PAD_HBD_FNS_NEON: [Option; 4] = { + let mut out: [Option; 4] = [None; 4]; + out[decimate_index(1, 1)] = Some(rav1e_cdef_padding4_16bpc_neon); + out[decimate_index(1, 0)] = Some(rav1e_cdef_padding4_16bpc_neon); + out[decimate_index(0, 0)] = Some(rav1e_cdef_padding8_16bpc_neon); + out +}; + +static CDEF_FILTER_HBD_FNS_NEON: [Option; 4] = { + let mut out: [Option; 4] = [None; 4]; + out[decimate_index(1, 1)] = Some(rav1e_cdef_filter4_16bpc_neon); + out[decimate_index(1, 0)] = Some(rav1e_cdef_filter4_16bpc_neon); + out[decimate_index(0, 0)] = Some(rav1e_cdef_filter8_16bpc_neon); + out +}; + +cpu_function_lookup_table!( + CDEF_PAD_FNS: [[Option; 4]], + default: [None; 4], + [NEON] +); + +cpu_function_lookup_table!( + CDEF_FILTER_FNS: [[Option; 4]], + default: [None; 4], + [NEON] +); + +cpu_function_lookup_table!( + CDEF_PAD_HBD_FNS: [[Option; 4]], + default: [None; 4], + [NEON] +); + +cpu_function_lookup_table!( + CDEF_FILTER_HBD_FNS: [[Option; 4]], + default: [None; 4], + [NEON] +); + +type CdefDirLBDFn = + unsafe extern fn(tmp: *const u8, tmp_stride: isize, var: *mut u32) -> i32; +type CdefDirHBDFn = unsafe extern fn( + tmp: *const u16, + tmp_stride: isize, + var: *mut u32, + bitdepth_max: i32, +) -> i32; + +#[inline(always)] +#[allow(clippy::let_and_return)] +pub(crate) fn cdef_find_dir( + img: &PlaneSlice<'_, T>, var: &mut u32, coeff_shift: usize, + cpu: CpuFeatureLevel, +) -> i32 { + let call_rust = + |var: &mut u32| rust::cdef_find_dir::(img, var, coeff_shift, cpu); + + #[cfg(feature = "check_asm")] + let (ref_dir, ref_var) = { + let mut var: u32 = 0; + let dir = call_rust(&mut var); + (dir, var) + }; + + let dir = match T::type_enum() { + PixelType::U8 => { + if let Some(func) = CDEF_DIR_LBD_FNS[cpu.as_index()] { + unsafe { + (func)( + img.as_ptr() as *const _, + T::to_asm_stride(img.plane.cfg.stride), + var as *mut u32, + ) + } + } else { + call_rust(var) + } + } + PixelType::U16 if coeff_shift > 0 => { + if let Some(func) = CDEF_DIR_HBD_FNS[cpu.as_index()] { + unsafe { + (func)( + img.as_ptr() as *const _, + T::to_asm_stride(img.plane.cfg.stride), + var as *mut u32, + (1 << (coeff_shift + 8)) - 1, + ) + } + } else { + call_rust(var) + } + } + _ => call_rust(var), + }; + + #[cfg(feature = "check_asm")] + { + assert_eq!(dir, ref_dir); + assert_eq!(*var, ref_var); + } + + dir +} + +extern { + fn rav1e_cdef_find_dir_8bpc_neon( + tmp: *const u8, tmp_stride: isize, var: *mut u32, + ) -> i32; +} + +extern { + fn rav1e_cdef_find_dir_16bpc_neon( + tmp: *const u16, tmp_stride: isize, var: *mut u32, max_bitdepth: i32, + ) -> i32; +} + +cpu_function_lookup_table!( + CDEF_DIR_LBD_FNS: [Option], + default: None, + [(NEON, Some(rav1e_cdef_find_dir_8bpc_neon))] +); + +cpu_function_lookup_table!( + CDEF_DIR_HBD_FNS: [Option], + default: None, + [(NEON, Some(rav1e_cdef_find_dir_16bpc_neon))] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/cdef_dist.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/cdef_dist.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/cdef_dist.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/cdef_dist.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,191 @@ +// Copyright (c) 2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::activity::apply_ssim_boost; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::tiling::PlaneRegion; +use crate::util::Pixel; +use crate::util::PixelType; + +type CdefDistKernelFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, + ret_ptr: *mut u32, +); + +type CdefDistKernelHBDFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, + ret_ptr: *mut u32, +); + +extern { + fn rav1e_cdef_dist_kernel_4x4_neon( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_4x8_neon( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x4_neon( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x8_neon( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_4x4_hbd_neon( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_4x8_hbd_neon( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x4_hbd_neon( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x8_hbd_neon( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ret_ptr: *mut u32, + ); +} + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[allow(clippy::let_and_return)] +pub fn cdef_dist_kernel( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + debug_assert!(src.plane_cfg.xdec == 0); + debug_assert!(src.plane_cfg.ydec == 0); + debug_assert!(dst.plane_cfg.xdec == 0); + debug_assert!(dst.plane_cfg.ydec == 0); + + // Limit kernel to 8x8 + debug_assert!(w <= 8); + debug_assert!(h <= 8); + + let call_rust = + || -> u32 { rust::cdef_dist_kernel(dst, src, w, h, bit_depth, cpu) }; + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let (svar, dvar, sse) = match T::type_enum() { + PixelType::U8 => { + if let Some(func) = + CDEF_DIST_KERNEL_FNS[cpu.as_index()][kernel_fn_index(w, h)] + { + let mut ret_buf = [0u32; 3]; + // SAFETY: Calls Assembly code. + unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ret_buf.as_mut_ptr(), + ) + } + + (ret_buf[0], ret_buf[1], ret_buf[2]) + } else { + return call_rust(); + } + } + PixelType::U16 => { + if let Some(func) = + CDEF_DIST_KERNEL_HBD_FNS[cpu.as_index()][kernel_fn_index(w, h)] + { + let mut ret_buf = [0u32; 3]; + // SAFETY: Calls Assembly code. + unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ret_buf.as_mut_ptr(), + ) + } + + (ret_buf[0], ret_buf[1], ret_buf[2]) + } else { + return call_rust(); + } + } + }; + + let dist = apply_ssim_boost(sse, svar, dvar, bit_depth); + #[cfg(feature = "check_asm")] + assert_eq!( + dist, ref_dist, + "CDEF Distortion {}x{}: Assembly doesn't match reference code.", + w, h + ); + + dist +} + +/// Store functions in a 8x8 grid. Most will be empty. +const CDEF_DIST_KERNEL_FNS_LENGTH: usize = 8 * 8; + +const fn kernel_fn_index(w: usize, h: usize) -> usize { + ((w - 1) << 3) | (h - 1) +} + +static CDEF_DIST_KERNEL_FNS_NEON: [Option; + CDEF_DIST_KERNEL_FNS_LENGTH] = { + let mut out: [Option; CDEF_DIST_KERNEL_FNS_LENGTH] = + [None; CDEF_DIST_KERNEL_FNS_LENGTH]; + + out[kernel_fn_index(4, 4)] = Some(rav1e_cdef_dist_kernel_4x4_neon); + out[kernel_fn_index(4, 8)] = Some(rav1e_cdef_dist_kernel_4x8_neon); + out[kernel_fn_index(8, 4)] = Some(rav1e_cdef_dist_kernel_8x4_neon); + out[kernel_fn_index(8, 8)] = Some(rav1e_cdef_dist_kernel_8x8_neon); + + out +}; + +cpu_function_lookup_table!( + CDEF_DIST_KERNEL_FNS: + [[Option; CDEF_DIST_KERNEL_FNS_LENGTH]], + default: [None; CDEF_DIST_KERNEL_FNS_LENGTH], + [NEON] +); + +static CDEF_DIST_KERNEL_HBD_FNS_NEON: [Option; + CDEF_DIST_KERNEL_FNS_LENGTH] = { + let mut out: [Option; CDEF_DIST_KERNEL_FNS_LENGTH] = + [None; CDEF_DIST_KERNEL_FNS_LENGTH]; + + out[kernel_fn_index(4, 4)] = Some(rav1e_cdef_dist_kernel_4x4_hbd_neon); + out[kernel_fn_index(4, 8)] = Some(rav1e_cdef_dist_kernel_4x8_hbd_neon); + out[kernel_fn_index(8, 4)] = Some(rav1e_cdef_dist_kernel_8x4_hbd_neon); + out[kernel_fn_index(8, 8)] = Some(rav1e_cdef_dist_kernel_8x8_hbd_neon); + + out +}; + +cpu_function_lookup_table!( + CDEF_DIST_KERNEL_HBD_FNS: + [[Option; CDEF_DIST_KERNEL_FNS_LENGTH]], + default: [None; CDEF_DIST_KERNEL_FNS_LENGTH], + [NEON] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,629 @@ +// Copyright (c) 2020-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub use self::cdef_dist::*; +pub use self::sse::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::partition::BlockSize; +use crate::tiling::*; +use crate::util::*; + +mod cdef_dist; +mod sse; + +type SadFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, +) -> u32; + +type SadHbdFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, +) -> u32; + +type SatdFn = SadFn; +type SatdHbdFn = SadHbdFn; + +macro_rules! declare_asm_dist_fn { + ($(($name: ident, $T: ident)),+) => ( + $( + extern { fn $name ( + src: *const $T, src_stride: isize, dst: *const $T, dst_stride: isize + ) -> u32; } + )+ + ) +} + +declare_asm_dist_fn![ + (rav1e_sad4x4_neon, u8), + (rav1e_sad4x8_neon, u8), + (rav1e_sad4x16_neon, u8), + (rav1e_sad8x4_neon, u8), + (rav1e_sad8x8_neon, u8), + (rav1e_sad8x16_neon, u8), + (rav1e_sad8x32_neon, u8), + (rav1e_sad16x4_neon, u8), + (rav1e_sad16x8_neon, u8), + (rav1e_sad16x16_neon, u8), + (rav1e_sad16x32_neon, u8), + (rav1e_sad16x64_neon, u8), + (rav1e_sad32x8_neon, u8), + (rav1e_sad32x16_neon, u8), + (rav1e_sad32x32_neon, u8), + (rav1e_sad32x64_neon, u8), + (rav1e_sad64x16_neon, u8), + (rav1e_sad64x32_neon, u8), + (rav1e_sad64x64_neon, u8), + (rav1e_sad64x128_neon, u8), + (rav1e_sad128x64_neon, u8), + (rav1e_sad128x128_neon, u8), + /* SAD HBD */ + (rav1e_sad4x4_hbd_neon, u16), + (rav1e_sad4x8_hbd_neon, u16), + (rav1e_sad4x16_hbd_neon, u16), + (rav1e_sad8x4_hbd_neon, u16), + (rav1e_sad8x8_hbd_neon, u16), + (rav1e_sad8x16_hbd_neon, u16), + (rav1e_sad8x32_hbd_neon, u16), + (rav1e_sad16x4_hbd_neon, u16), + (rav1e_sad16x8_hbd_neon, u16), + (rav1e_sad16x16_hbd_neon, u16), + (rav1e_sad16x32_hbd_neon, u16), + (rav1e_sad16x64_hbd_neon, u16), + (rav1e_sad32x8_hbd_neon, u16), + (rav1e_sad32x16_hbd_neon, u16), + (rav1e_sad32x32_hbd_neon, u16), + (rav1e_sad32x64_hbd_neon, u16), + (rav1e_sad64x16_hbd_neon, u16), + (rav1e_sad64x32_hbd_neon, u16), + (rav1e_sad64x64_hbd_neon, u16), + (rav1e_sad64x128_hbd_neon, u16), + (rav1e_sad128x64_hbd_neon, u16), + (rav1e_sad128x128_hbd_neon, u16), + /* SATD */ + (rav1e_satd4x4_neon, u8), + (rav1e_satd4x8_neon, u8), + (rav1e_satd4x16_neon, u8), + (rav1e_satd8x4_neon, u8), + (rav1e_satd8x8_neon, u8), + (rav1e_satd8x16_neon, u8), + (rav1e_satd8x32_neon, u8), + (rav1e_satd16x4_neon, u8), + (rav1e_satd16x8_neon, u8), + (rav1e_satd16x16_neon, u8), + (rav1e_satd16x32_neon, u8), + (rav1e_satd16x64_neon, u8), + (rav1e_satd32x8_neon, u8), + (rav1e_satd32x16_neon, u8), + (rav1e_satd32x32_neon, u8), + (rav1e_satd32x64_neon, u8), + (rav1e_satd64x16_neon, u8), + (rav1e_satd64x32_neon, u8), + (rav1e_satd64x64_neon, u8), + (rav1e_satd64x128_neon, u8), + (rav1e_satd128x64_neon, u8), + (rav1e_satd128x128_neon, u8), + /* SATD HBD */ + (rav1e_satd4x4_hbd_neon, u16), + (rav1e_satd4x8_hbd_neon, u16), + (rav1e_satd4x16_hbd_neon, u16), + (rav1e_satd8x4_hbd_neon, u16), + (rav1e_satd8x8_hbd_neon, u16), + (rav1e_satd8x16_hbd_neon, u16), + (rav1e_satd8x32_hbd_neon, u16), + (rav1e_satd16x4_hbd_neon, u16), + (rav1e_satd16x8_hbd_neon, u16), + (rav1e_satd16x16_hbd_neon, u16), + (rav1e_satd16x32_hbd_neon, u16), + (rav1e_satd16x64_hbd_neon, u16), + (rav1e_satd32x8_hbd_neon, u16), + (rav1e_satd32x16_hbd_neon, u16), + (rav1e_satd32x32_hbd_neon, u16), + (rav1e_satd32x64_hbd_neon, u16), + (rav1e_satd64x16_hbd_neon, u16), + (rav1e_satd64x32_hbd_neon, u16), + (rav1e_satd64x64_hbd_neon, u16), + (rav1e_satd64x128_hbd_neon, u16), + (rav1e_satd128x64_hbd_neon, u16), + (rav1e_satd128x128_hbd_neon, u16) +]; + +// BlockSize::BLOCK_SIZES.next_power_of_two(); +const DIST_FNS_LENGTH: usize = 32; + +#[inline] +const fn to_index(bsize: BlockSize) -> usize { + bsize as usize & (DIST_FNS_LENGTH - 1) +} + +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_sad( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { rust::get_sad(src, dst, w, h, bit_depth, cpu) }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SAD_FNS[cpu.as_index()][to_index(bsize)] { + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SAD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!(dist, ref_dist); + + dist +} + +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_satd( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { rust::get_satd(src, dst, w, h, bit_depth, cpu) }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SATD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SATD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!(dist, ref_dist); + + dist +} + +static SAD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad4x4_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_sad4x8_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_sad4x16_neon); + + out[BLOCK_8X4 as usize] = Some(rav1e_sad8x4_neon); + out[BLOCK_8X8 as usize] = Some(rav1e_sad8x8_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_sad8x16_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_sad8x32_neon); + + out[BLOCK_16X4 as usize] = Some(rav1e_sad16x4_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_sad16x8_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_sad16x16_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_sad16x32_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_sad16x64_neon); + + out[BLOCK_32X8 as usize] = Some(rav1e_sad32x8_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_sad32x16_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_sad32x32_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_sad32x64_neon); + + out[BLOCK_64X16 as usize] = Some(rav1e_sad64x16_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_sad64x32_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_sad64x64_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_sad64x128_neon); + + out[BLOCK_128X64 as usize] = Some(rav1e_sad128x64_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_sad128x128_neon); + + out +}; + +static SAD_HBD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad4x4_hbd_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_sad4x8_hbd_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_sad4x16_hbd_neon); + + out[BLOCK_8X4 as usize] = Some(rav1e_sad8x4_hbd_neon); + out[BLOCK_8X8 as usize] = Some(rav1e_sad8x8_hbd_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_sad8x16_hbd_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_sad8x32_hbd_neon); + + out[BLOCK_16X4 as usize] = Some(rav1e_sad16x4_hbd_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_sad16x8_hbd_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_sad16x16_hbd_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_sad16x32_hbd_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_sad16x64_hbd_neon); + + out[BLOCK_32X8 as usize] = Some(rav1e_sad32x8_hbd_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_sad32x16_hbd_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_sad32x32_hbd_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_sad32x64_hbd_neon); + + out[BLOCK_64X16 as usize] = Some(rav1e_sad64x16_hbd_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_sad64x32_hbd_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_sad64x64_hbd_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_sad64x128_hbd_neon); + + out[BLOCK_128X64 as usize] = Some(rav1e_sad128x64_hbd_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_sad128x128_hbd_neon); + + out +}; + +static SATD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_satd4x4_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_satd4x8_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_satd4x16_neon); + out[BLOCK_8X4 as usize] = Some(rav1e_satd8x4_neon); + out[BLOCK_16X4 as usize] = Some(rav1e_satd16x4_neon); + + out[BLOCK_8X8 as usize] = Some(rav1e_satd8x8_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_satd8x16_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_satd8x32_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_satd16x8_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_satd16x16_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_satd16x32_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_satd16x64_neon); + out[BLOCK_32X8 as usize] = Some(rav1e_satd32x8_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_satd32x16_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_satd32x32_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_satd32x64_neon); + out[BLOCK_64X16 as usize] = Some(rav1e_satd64x16_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_satd64x32_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_satd64x64_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_satd64x128_neon); + out[BLOCK_128X64 as usize] = Some(rav1e_satd128x64_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_satd128x128_neon); + + out +}; + +static SATD_HBD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_satd4x4_hbd_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_satd4x8_hbd_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_satd4x16_hbd_neon); + out[BLOCK_8X4 as usize] = Some(rav1e_satd8x4_hbd_neon); + out[BLOCK_16X4 as usize] = Some(rav1e_satd16x4_hbd_neon); + + out[BLOCK_8X8 as usize] = Some(rav1e_satd8x8_hbd_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_satd8x16_hbd_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_satd8x32_hbd_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_satd16x8_hbd_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_satd16x16_hbd_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_satd16x32_hbd_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_satd16x64_hbd_neon); + out[BLOCK_32X8 as usize] = Some(rav1e_satd32x8_hbd_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_satd32x16_hbd_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_satd32x32_hbd_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_satd32x64_hbd_neon); + out[BLOCK_64X16 as usize] = Some(rav1e_satd64x16_hbd_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_satd64x32_hbd_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_satd64x64_hbd_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_satd64x128_hbd_neon); + out[BLOCK_128X64 as usize] = Some(rav1e_satd128x64_hbd_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_satd128x128_hbd_neon); + + out +}; + +cpu_function_lookup_table!( + SAD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +cpu_function_lookup_table!( + SAD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +cpu_function_lookup_table!( + SATD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +cpu_function_lookup_table!( + SATD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +#[cfg(test)] +mod test { + use super::*; + use crate::frame::{AsRegion, Plane}; + use rand::random; + use std::str::FromStr; + + macro_rules! test_dist_fns { + ($(($W:expr, $H:expr)),*, $DIST_TY:ident, $BD:expr, $OPT:ident, $OPTLIT:tt) => { + $( + paste::item! { + #[test] + fn []() { + if $BD > 8 { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u16; $W * $H], $W); + // dynamic allocation: test + let mut dst = Plane::from_slice(&vec![0u16; $W * $H], $W); + for (s, d) in src.data.iter_mut().zip(dst.data.iter_mut()) { + *s = random::() as u16 * $BD / 8; + *d = random::() as u16 * $BD / 8; + } + let result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + let rust_result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::RUST); + + assert_eq!(rust_result, result); + } else { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u8; $W * $H], $W); + // dynamic allocation: test + let mut dst = Plane::from_slice(&vec![0u8; $W * $H], $W); + for (s, d) in src.data.iter_mut().zip(dst.data.iter_mut()) { + *s = random::(); + *d = random::(); + } + let result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + let rust_result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::RUST); + + assert_eq!(rust_result, result); + } + } + } + )* + } + } + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + sad, + 8, + neon, + "neon" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + sad, + 10, + neon, + "neon" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + sad, + 12, + neon, + "neon" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + satd, + 8, + neon, + "neon" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + satd, + 10, + neon, + "neon" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + satd, + 12, + neon, + "neon" + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/sse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/sse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/sse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/dist/sse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,252 @@ +// Copyright (c) 2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::asm::aarch64::dist::to_index; +use crate::asm::aarch64::dist::DIST_FNS_LENGTH; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::encoder::IMPORTANCE_BLOCK_SIZE; +use crate::partition::BlockSize; +use crate::rdo::DistortionScale; +use crate::tiling::PlaneRegion; +use crate::util::*; + +type WeightedSseFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, + scale: *const u32, + scale_stride: isize, +) -> u64; + +type WeightedSseHBDFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, + scale: *const u32, + scale_stride: isize, +) -> u64; + +macro_rules! declare_asm_sse_fn { + ($($name: ident),+) => ( + $( + extern { fn $name ( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, scale: *const u32, scale_stride: isize + ) -> u64; } + )+ + ) +} + +macro_rules! declare_asm_hbd_sse_fn { + ($($name: ident),+) => ( + $( + extern { fn $name ( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, scale: *const u32, scale_stride: isize + ) -> u64; } + )+ + ) +} + +declare_asm_sse_fn![ + rav1e_weighted_sse_4x4_neon, + rav1e_weighted_sse_4x8_neon, + rav1e_weighted_sse_4x16_neon, + rav1e_weighted_sse_8x4_neon, + rav1e_weighted_sse_8x8_neon, + rav1e_weighted_sse_8x16_neon, + rav1e_weighted_sse_8x32_neon, + rav1e_weighted_sse_16x4_neon, + rav1e_weighted_sse_16x8_neon, + rav1e_weighted_sse_16x16_neon, + rav1e_weighted_sse_16x32_neon, + rav1e_weighted_sse_16x64_neon, + rav1e_weighted_sse_32x8_neon, + rav1e_weighted_sse_32x16_neon, + rav1e_weighted_sse_32x32_neon, + rav1e_weighted_sse_32x64_neon, + rav1e_weighted_sse_64x16_neon, + rav1e_weighted_sse_64x32_neon, + rav1e_weighted_sse_64x64_neon, + rav1e_weighted_sse_64x128_neon, + rav1e_weighted_sse_128x64_neon, + rav1e_weighted_sse_128x128_neon +]; + +declare_asm_hbd_sse_fn![ + rav1e_weighted_sse_4x4_hbd_neon, + rav1e_weighted_sse_4x8_hbd_neon, + rav1e_weighted_sse_4x16_hbd_neon, + rav1e_weighted_sse_8x4_hbd_neon, + rav1e_weighted_sse_8x8_hbd_neon, + rav1e_weighted_sse_8x16_hbd_neon, + rav1e_weighted_sse_8x32_hbd_neon, + rav1e_weighted_sse_16x4_hbd_neon, + rav1e_weighted_sse_16x8_hbd_neon, + rav1e_weighted_sse_16x16_hbd_neon, + rav1e_weighted_sse_16x32_hbd_neon, + rav1e_weighted_sse_16x64_hbd_neon, + rav1e_weighted_sse_32x8_hbd_neon, + rav1e_weighted_sse_32x16_hbd_neon, + rav1e_weighted_sse_32x32_hbd_neon, + rav1e_weighted_sse_32x64_hbd_neon, + rav1e_weighted_sse_64x16_hbd_neon, + rav1e_weighted_sse_64x32_hbd_neon, + rav1e_weighted_sse_64x64_hbd_neon, + rav1e_weighted_sse_64x128_hbd_neon, + rav1e_weighted_sse_128x64_hbd_neon, + rav1e_weighted_sse_128x128_hbd_neon +]; + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_weighted_sse( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, scale: &[u32], + scale_stride: usize, w: usize, h: usize, bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u64 { + // Assembly breaks if imp block size changes. + assert_eq!(IMPORTANCE_BLOCK_SIZE >> 1, 4); + + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u64 { + rust::get_weighted_sse(dst, src, scale, scale_stride, w, h, bit_depth, cpu) + }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let den = + DistortionScale::new(1, 1 << rust::GET_WEIGHTED_SSE_SHIFT).0 as u64; + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SSE_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + ((func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + scale.as_ptr(), + (scale_stride * std::mem::size_of::()) as isize, + ) + (den >> 1)) + / den + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SSE_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + ((func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + scale.as_ptr(), + (scale_stride * std::mem::size_of::()) as isize, + ) + (den >> 1)) + / den + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!( + dist, ref_dist, + "Weighted SSE {:?}: Assembly doesn't match reference code.", + bsize_opt + ); + + dist +} + +static SSE_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = + [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + out[BLOCK_4X4 as usize] = Some(rav1e_weighted_sse_4x4_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_weighted_sse_4x8_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_weighted_sse_4x16_neon); + out[BLOCK_8X4 as usize] = Some(rav1e_weighted_sse_8x4_neon); + out[BLOCK_8X8 as usize] = Some(rav1e_weighted_sse_8x8_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_weighted_sse_8x16_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_weighted_sse_8x32_neon); + out[BLOCK_16X4 as usize] = Some(rav1e_weighted_sse_16x4_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_weighted_sse_16x8_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_weighted_sse_16x16_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_weighted_sse_16x32_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_weighted_sse_16x64_neon); + out[BLOCK_32X8 as usize] = Some(rav1e_weighted_sse_32x8_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_weighted_sse_32x16_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_weighted_sse_32x32_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_weighted_sse_32x64_neon); + out[BLOCK_64X16 as usize] = Some(rav1e_weighted_sse_64x16_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_weighted_sse_64x32_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_weighted_sse_64x64_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_weighted_sse_64x128_neon); + out[BLOCK_128X64 as usize] = Some(rav1e_weighted_sse_128x64_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_weighted_sse_128x128_neon); + + out +}; + +static SSE_HBD_FNS_NEON: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = + [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + out[BLOCK_4X4 as usize] = Some(rav1e_weighted_sse_4x4_hbd_neon); + out[BLOCK_4X8 as usize] = Some(rav1e_weighted_sse_4x8_hbd_neon); + out[BLOCK_4X16 as usize] = Some(rav1e_weighted_sse_4x16_hbd_neon); + out[BLOCK_8X4 as usize] = Some(rav1e_weighted_sse_8x4_hbd_neon); + out[BLOCK_8X8 as usize] = Some(rav1e_weighted_sse_8x8_hbd_neon); + out[BLOCK_8X16 as usize] = Some(rav1e_weighted_sse_8x16_hbd_neon); + out[BLOCK_8X32 as usize] = Some(rav1e_weighted_sse_8x32_hbd_neon); + out[BLOCK_16X4 as usize] = Some(rav1e_weighted_sse_16x4_hbd_neon); + out[BLOCK_16X8 as usize] = Some(rav1e_weighted_sse_16x8_hbd_neon); + out[BLOCK_16X16 as usize] = Some(rav1e_weighted_sse_16x16_hbd_neon); + out[BLOCK_16X32 as usize] = Some(rav1e_weighted_sse_16x32_hbd_neon); + out[BLOCK_16X64 as usize] = Some(rav1e_weighted_sse_16x64_hbd_neon); + out[BLOCK_32X8 as usize] = Some(rav1e_weighted_sse_32x8_hbd_neon); + out[BLOCK_32X16 as usize] = Some(rav1e_weighted_sse_32x16_hbd_neon); + out[BLOCK_32X32 as usize] = Some(rav1e_weighted_sse_32x32_hbd_neon); + out[BLOCK_32X64 as usize] = Some(rav1e_weighted_sse_32x64_hbd_neon); + out[BLOCK_64X16 as usize] = Some(rav1e_weighted_sse_64x16_hbd_neon); + out[BLOCK_64X32 as usize] = Some(rav1e_weighted_sse_64x32_hbd_neon); + out[BLOCK_64X64 as usize] = Some(rav1e_weighted_sse_64x64_hbd_neon); + out[BLOCK_64X128 as usize] = Some(rav1e_weighted_sse_64x128_hbd_neon); + out[BLOCK_128X64 as usize] = Some(rav1e_weighted_sse_128x64_hbd_neon); + out[BLOCK_128X128 as usize] = Some(rav1e_weighted_sse_128x128_hbd_neon); + + out +}; + +cpu_function_lookup_table!( + SSE_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); + +cpu_function_lookup_table!( + SSE_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [NEON] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mc.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,490 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::*; +use crate::mc::FilterMode::*; +use crate::mc::*; +use crate::tiling::*; +use crate::util::*; + +type PutFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PutHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +type PrepFn = unsafe extern fn( + tmp: *mut i16, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PrepHBDFn = unsafe extern fn( + tmp: *mut i16, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +type AvgFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + tmp1: *const i16, + tmp2: *const i16, + width: i32, + height: i32, +); + +type AvgHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + tmp1: *const i16, + tmp2: *const i16, + width: i32, + height: i32, + bitdepth_max: i32, +); + +// gets an index that can be mapped to a function for a pair of filter modes +#[inline] +const fn get_2d_mode_idx(mode_x: FilterMode, mode_y: FilterMode) -> usize { + (mode_x as usize + 4 * (mode_y as usize)) & 15 +} + +#[inline(always)] +pub fn put_8tap( + dst: &mut PlaneRegionMut<'_, T>, src: PlaneSlice<'_, T>, width: usize, + height: usize, col_frac: i32, row_frac: i32, mode_x: FilterMode, + mode_y: FilterMode, bit_depth: usize, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::put_8tap( + dst, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth, + cpu, + ); + }; + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + unsafe { + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + + match T::type_enum() { + PixelType::U8 => { + match PUT_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(dst), + } + } + PixelType::U16 if bit_depth > 8 => { + match PUT_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + } + } + _ => call_rust(dst), + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } +} + +#[inline(always)] +pub fn prep_8tap( + tmp: &mut [i16], src: PlaneSlice<'_, T>, width: usize, height: usize, + col_frac: i32, row_frac: i32, mode_x: FilterMode, mode_y: FilterMode, + bit_depth: usize, cpu: CpuFeatureLevel, +) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2 <= width || width <= 128)); + + let call_rust = |tmp: &mut [i16]| { + rust::prep_8tap( + tmp, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth, + cpu, + ); + }; + #[cfg(feature = "check_asm")] + let ref_tmp = { + let mut copy = vec![0; width * height]; + copy[..].copy_from_slice(&tmp[..width * height]); + call_rust(&mut copy); + copy + }; + unsafe { + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check length of tmp + assert!(tmp.len() >= width * height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + match T::type_enum() { + PixelType::U8 => { + match PREP_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + tmp.as_mut_ptr(), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(tmp), + } + } + PixelType::U16 if bit_depth > 8 => { + match PREP_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + tmp.as_mut_ptr() as *mut _, + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(tmp), + } + } + _ => call_rust(tmp), + } + } + #[cfg(feature = "check_asm")] + { + assert_eq!(&tmp[..width * height], &ref_tmp[..]); + } +} + +pub fn mc_avg( + dst: &mut PlaneRegionMut<'_, T>, tmp1: &[i16], tmp2: &[i16], width: usize, + height: usize, bit_depth: usize, cpu: CpuFeatureLevel, +) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2 <= width || width <= 128)); + + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::mc_avg(dst, tmp1, tmp2, width, height, bit_depth, cpu); + }; + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + unsafe { + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check length of tmp1 & tmp2 + assert!(tmp1.len() >= width * height); + assert!(tmp2.len() >= width * height); + match T::type_enum() { + PixelType::U8 => match AVG_FNS[cpu.as_index()] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + tmp1.as_ptr(), + tmp2.as_ptr(), + width as i32, + height as i32, + ), + None => call_rust(dst), + }, + PixelType::U16 if bit_depth > 8 => match AVG_HBD_FNS[cpu.as_index()] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + tmp1.as_ptr(), + tmp2.as_ptr(), + width as i32, + height as i32, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + }, + _ => call_rust(dst), + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } +} + +macro_rules! decl_mc_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern { + $( + fn $func_name( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, + ); + )* + } + + static PUT_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } +} + +decl_mc_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular_8bpc_neon), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_8bpc_neon), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_8bpc_neon), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_8bpc_neon), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_8bpc_neon), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_8bpc_neon), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_8bpc_neon), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_8bpc_neon), + (SHARP, SHARP, rav1e_put_8tap_sharp_8bpc_neon), + (BILINEAR, BILINEAR, rav1e_put_bilin_8bpc_neon) +); + +cpu_function_lookup_table!( + PUT_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); + +macro_rules! decl_mc_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern { + $( + fn $func_name( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PUT_HBD_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } +} + +decl_mc_hbd_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular_16bpc_neon), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_16bpc_neon), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_16bpc_neon), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_16bpc_neon), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_16bpc_neon), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_16bpc_neon), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_16bpc_neon), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_16bpc_neon), + (SHARP, SHARP, rav1e_put_8tap_sharp_16bpc_neon), + (BILINEAR, BILINEAR, rav1e_put_bilin_16bpc_neon) +); + +cpu_function_lookup_table!( + PUT_HBD_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); + +macro_rules! decl_mct_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern { + $( + fn $func_name( + tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32, + ); + )* + } + + static PREP_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } +} + +decl_mct_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular_8bpc_neon), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_8bpc_neon), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_8bpc_neon), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_8bpc_neon), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_8bpc_neon), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_8bpc_neon), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_8bpc_neon), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_8bpc_neon), + (SHARP, SHARP, rav1e_prep_8tap_sharp_8bpc_neon), + (BILINEAR, BILINEAR, rav1e_prep_bilin_8bpc_neon) +); + +cpu_function_lookup_table!( + PREP_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); + +macro_rules! decl_mct_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + extern { + $( + fn $func_name( + tmp: *mut i16, src: *const u16, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PREP_HBD_FNS_NEON: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name); + )* + out + }; + } +} + +decl_mct_hbd_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular_16bpc_neon), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_16bpc_neon), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_16bpc_neon), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_16bpc_neon), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_16bpc_neon), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_16bpc_neon), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_16bpc_neon), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_16bpc_neon), + (SHARP, SHARP, rav1e_prep_8tap_sharp_16bpc_neon), + (BILINEAR, BILINEAR, rav1e_prep_bilin_16bpc_neon) +); + +cpu_function_lookup_table!( + PREP_HBD_FNS: [[Option; 16]], + default: [None; 16], + [NEON] +); + +extern { + fn rav1e_avg_8bpc_neon( + dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, + ); +} + +cpu_function_lookup_table!( + AVG_FNS: [Option], + default: None, + [(NEON, Some(rav1e_avg_8bpc_neon))] +); + +extern { + fn rav1e_avg_16bpc_neon( + dst: *mut u16, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, bitdepth_max: i32, + ); +} + +cpu_function_lookup_table!( + AVG_HBD_FNS: [Option], + default: None, + [(NEON, Some(rav1e_avg_16bpc_neon))] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +// Copyright (c) 2019-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod cdef; +pub mod dist; +pub mod mc; +pub mod predict; +pub mod transform; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/predict.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/predict.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/predict.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/predict.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,701 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::context::MAX_TX_SIZE; +use crate::cpu_features::CpuFeatureLevel; +use crate::partition::{BlockSize, IntraEdge}; +use crate::predict::rust::{ + dr_intra_derivative, select_ief_strength, select_ief_upsample, +}; +use crate::predict::{ + rust, IntraEdgeFilterParameters, PredictionMode, PredictionVariant, +}; +use crate::tiling::{PlaneRegion, PlaneRegionMut}; +use crate::transform::TxSize; +use crate::{Pixel, PixelType}; +use libc; +use libc::{c_int, ptrdiff_t}; +use std::mem::MaybeUninit; +use PixelType::{U16, U8}; + +macro_rules! decl_cfl_ac_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + ac: *mut MaybeUninit, src: *const u8, stride: libc::ptrdiff_t, + w_pad: libc::c_int, h_pad: libc::c_int, + width: libc::c_int, height: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_ac_fn! { + rav1e_ipred_cfl_ac_420_8bpc_neon, + rav1e_ipred_cfl_ac_422_8bpc_neon, + rav1e_ipred_cfl_ac_444_8bpc_neon +} + +macro_rules! decl_cfl_ac_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + ac: *mut MaybeUninit, src: *const u16, stride: libc::ptrdiff_t, + w_pad: libc::c_int, h_pad: libc::c_int, + width: libc::c_int, height: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_ac_hbd_fn! { + rav1e_ipred_cfl_ac_420_16bpc_neon, + rav1e_ipred_cfl_ac_422_16bpc_neon, + rav1e_ipred_cfl_ac_444_16bpc_neon +} + +macro_rules! decl_angular_ipred_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + ); + )* + } + }; +} + +decl_angular_ipred_fn! { + rav1e_ipred_dc_8bpc_neon, + rav1e_ipred_dc_128_8bpc_neon, + rav1e_ipred_dc_left_8bpc_neon, + rav1e_ipred_dc_top_8bpc_neon, + rav1e_ipred_v_8bpc_neon, + rav1e_ipred_h_8bpc_neon, + rav1e_ipred_smooth_8bpc_neon, + rav1e_ipred_smooth_v_8bpc_neon, + rav1e_ipred_smooth_h_8bpc_neon, + rav1e_ipred_paeth_8bpc_neon +} + +macro_rules! decl_angular_ipred_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + max_width: libc::c_int, max_height: libc::c_int, + bit_depth_max: libc::c_int, + ); + )* + } + }; +} + +decl_angular_ipred_hbd_fn! { + rav1e_ipred_dc_16bpc_neon, + rav1e_ipred_dc_128_16bpc_neon, + rav1e_ipred_dc_left_16bpc_neon, + rav1e_ipred_dc_top_16bpc_neon, + rav1e_ipred_v_16bpc_neon, + rav1e_ipred_h_16bpc_neon, + rav1e_ipred_smooth_16bpc_neon, + rav1e_ipred_smooth_v_16bpc_neon, + rav1e_ipred_smooth_h_16bpc_neon, + rav1e_ipred_paeth_16bpc_neon +} + +macro_rules! decl_cfl_pred_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, ac: *const i16, + alpha: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_pred_fn! { + rav1e_ipred_cfl_8bpc_neon, + rav1e_ipred_cfl_128_8bpc_neon, + rav1e_ipred_cfl_left_8bpc_neon, + rav1e_ipred_cfl_top_8bpc_neon +} + +macro_rules! decl_cfl_pred_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, ac: *const i16, + alpha: libc::c_int, bit_depth_max: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_pred_hbd_fn! { + rav1e_ipred_cfl_16bpc_neon, + rav1e_ipred_cfl_128_16bpc_neon, + rav1e_ipred_cfl_left_16bpc_neon, + rav1e_ipred_cfl_top_16bpc_neon +} + +extern { + fn rav1e_ipred_z1_upsample_edge_8bpc_neon( + out: *mut u8, hsz: c_int, _in: *const u8, end: c_int, + ); + fn rav1e_ipred_z1_upsample_edge_16bpc_neon( + out: *mut u16, hsz: c_int, _in: *const u16, end: c_int, + bit_depth_max: c_int, + ); + fn rav1e_ipred_z1_filter_edge_8bpc_neon( + out: *mut u8, sz: c_int, _in: *const u8, end: c_int, strength: c_int, + ); + fn rav1e_ipred_z1_filter_edge_16bpc_neon( + out: *mut u16, sz: c_int, _in: *const u16, end: c_int, strength: c_int, + ); + fn rav1e_ipred_z1_fill1_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, top: *const u8, width: c_int, + height: c_int, dx: c_int, max_base_x: c_int, + ); + fn rav1e_ipred_z1_fill1_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, top: *const u16, width: c_int, + height: c_int, dx: c_int, max_base_x: c_int, + ); + fn rav1e_ipred_z1_fill2_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, top: *const u8, width: c_int, + height: c_int, dx: c_int, max_base_x: c_int, + ); + fn rav1e_ipred_z1_fill2_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, top: *const u16, width: c_int, + height: c_int, dx: c_int, max_base_x: c_int, + ); + fn rav1e_ipred_z2_upsample_edge_8bpc_neon( + out: *mut u8, sz: c_int, _in: *const u8, + ); + fn rav1e_ipred_z2_upsample_edge_16bpc_neon( + out: *mut u16, sz: c_int, _in: *const u16, bit_depth_max: c_int, + ); + fn rav1e_ipred_z2_fill1_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, top: *const u8, left: *const u8, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z2_fill1_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, top: *const u16, left: *const u16, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z2_fill2_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, top: *const u8, left: *const u8, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z2_fill2_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, top: *const u16, left: *const u16, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z2_fill3_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, top: *const u8, left: *const u8, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z2_fill3_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, top: *const u16, left: *const u16, + width: c_int, height: c_int, dx: c_int, dy: c_int, + ); + fn rav1e_ipred_z3_fill1_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, left: *const u8, width: c_int, + height: c_int, dy: c_int, max_base_y: c_int, + ); + fn rav1e_ipred_z3_fill1_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, left: *const u16, width: c_int, + height: c_int, dy: c_int, max_base_y: c_int, + ); + fn rav1e_ipred_z3_fill2_8bpc_neon( + dst: *mut u8, stride: ptrdiff_t, left: *const u8, width: c_int, + height: c_int, dy: c_int, max_base_y: c_int, + ); + fn rav1e_ipred_z3_fill2_16bpc_neon( + dst: *mut u16, stride: ptrdiff_t, left: *const u16, width: c_int, + height: c_int, dy: c_int, max_base_y: c_int, + ); + fn rav1e_ipred_reverse_8bpc_neon(dst: *mut u8, src: *const u8, n: c_int); + fn rav1e_ipred_reverse_16bpc_neon(dst: *mut u16, src: *const u16, n: c_int); +} +#[inline] +unsafe fn ipred_z1_upsample_edge( + o: *mut T, sz: c_int, i: *const T, n: c_int, m: c_int, +) { + match T::type_enum() { + U8 => rav1e_ipred_z1_upsample_edge_8bpc_neon(o as _, sz, i as _, n), + U16 => rav1e_ipred_z1_upsample_edge_16bpc_neon(o as _, sz, i as _, n, m), + } +} +#[inline] +unsafe fn ipred_z2_upsample_edge( + o: *mut T, sz: c_int, i: *const T, m: c_int, +) { + match T::type_enum() { + U8 => rav1e_ipred_z2_upsample_edge_8bpc_neon(o as _, sz, i as _), + U16 => rav1e_ipred_z2_upsample_edge_16bpc_neon(o as _, sz, i as _, m), + } +} +#[inline] +unsafe fn ipred_z1_filter_edge( + o: *mut T, sz: c_int, i: *const T, n: c_int, s: c_int, +) { + match T::type_enum() { + U8 => rav1e_ipred_z1_filter_edge_8bpc_neon(o as _, sz, i as _, n, s), + U16 => rav1e_ipred_z1_filter_edge_16bpc_neon(o as _, sz, i as _, n, s), + } +} +#[inline] +unsafe fn ipred_reverse(o: *mut T, i: *const T, n: c_int) { + match T::type_enum() { + U8 => rav1e_ipred_reverse_8bpc_neon(o as _, i as _, n), + U16 => rav1e_ipred_reverse_16bpc_neon(o as _, i as _, n), + } +} + +#[rustfmt::skip] +struct Fill( + [unsafe extern fn(*mut u8, ptrdiff_t, *const u8, c_int, c_int, c_int, c_int); 2], + [unsafe extern fn(*mut u16, ptrdiff_t, *const u16, c_int, c_int, c_int, c_int); 2], +); +impl Fill { + unsafe fn ipred_fill( + self, dst: *mut T, stride: ptrdiff_t, src: *const T, w: c_int, h: c_int, + d: c_int, max_base: c_int, upsample: bool, + ) { + let u = upsample as usize; + match T::type_enum() { + U8 => self.0[u](dst as _, stride, src as _, w, h, d, max_base), + U16 => self.1[u](dst as _, stride, src as _, w, h, d, max_base), + } + } +} +const Z1: Fill = Fill( + [rav1e_ipred_z1_fill1_8bpc_neon, rav1e_ipred_z1_fill2_8bpc_neon], + [rav1e_ipred_z1_fill1_16bpc_neon, rav1e_ipred_z1_fill2_16bpc_neon], +); +const Z3: Fill = Fill( + [rav1e_ipred_z3_fill1_8bpc_neon, rav1e_ipred_z3_fill2_8bpc_neon], + [rav1e_ipred_z3_fill1_16bpc_neon, rav1e_ipred_z3_fill2_16bpc_neon], +); + +#[rustfmt::skip] +struct Fill2( + [unsafe extern fn(*mut u8, ptrdiff_t, *const u8, *const u8, c_int, c_int, c_int, c_int); 3], + [unsafe extern fn(*mut u16, ptrdiff_t, *const u16, *const u16, c_int, c_int, c_int, c_int); 3], +); +impl Fill2 { + unsafe fn ipred_fill( + self, dst: *mut T, stride: ptrdiff_t, top: *const T, left: *const T, + w: c_int, h: c_int, dx: c_int, dy: c_int, upsample_above: bool, + upsample_left: bool, + ) { + let u = if upsample_left { 2 } else { upsample_above as usize }; + match T::type_enum() { + U8 => self.0[u](dst as _, stride, top as _, left as _, w, h, dx, dy), + U16 => self.1[u](dst as _, stride, top as _, left as _, w, h, dx, dy), + } + } +} +const Z2: Fill2 = Fill2( + [ + rav1e_ipred_z2_fill1_8bpc_neon, + rav1e_ipred_z2_fill2_8bpc_neon, + rav1e_ipred_z2_fill3_8bpc_neon, + ], + [ + rav1e_ipred_z2_fill1_16bpc_neon, + rav1e_ipred_z2_fill2_16bpc_neon, + rav1e_ipred_z2_fill3_16bpc_neon, + ], +); + +unsafe fn ipred_z1( + dst: *mut T, stride: ptrdiff_t, src: *const T, angle: isize, w: c_int, + h: c_int, bd_max: c_int, edge_filter: bool, smooth_filter: bool, +) { + let mut dx = dr_intra_derivative(angle as _) as c_int; + let mut out = [MaybeUninit::::uninit(); MAX_TX_SIZE * 4 + 15 * 2 + 16]; + let out = out.as_mut_ptr() as *mut T; + + let upsample_above = edge_filter + && select_ief_upsample(w as _, h as _, smooth_filter, 90 - angle); + let max_base_x = if upsample_above { + ipred_z1_upsample_edge(out, w + h, src, w + w.min(h), bd_max); + dx <<= 1; + 2 * (w + h) - 2 + } else { + let strength = + select_ief_strength(w as _, h as _, smooth_filter, 90 - angle) as c_int; + if strength != 0 { + ipred_z1_filter_edge(out, w + h, src, w + w.min(h), strength); + w + h - 1 + } else { + let n = w + w.min(h); + out.copy_from_nonoverlapping(src.add(1), n as usize); + n - 1 + } + }; + + let base_inc = 1 + upsample_above as c_int; + let pad_pixels = w + 15; + let fill_pixel = out.add(max_base_x as usize).read(); + let base = out.add(max_base_x as usize + 1); + for i in 0..(pad_pixels * base_inc) as usize { + base.add(i).write(fill_pixel); + } + + Z1.ipred_fill(dst, stride, out, w, h, dx, max_base_x, upsample_above); +} + +unsafe fn ipred_z2( + dst: *mut T, stride: ptrdiff_t, src: *const T, angle: isize, w: c_int, + h: c_int, max_w: c_int, max_h: c_int, bd_max: c_int, edge_filter: bool, + smooth_filter: bool, +) { + assert!(angle > 90 && angle < 180); + let mut dx = dr_intra_derivative((180 - angle) as _) as c_int; + let mut dy = dr_intra_derivative((angle - 90) as _) as c_int; + let us_left = edge_filter + && select_ief_upsample(w as _, h as _, smooth_filter, 180 - angle); + let us_above = edge_filter + && select_ief_upsample(w as _, h as _, smooth_filter, angle - 90); + let mut out = [MaybeUninit::::uninit(); 3 * (MAX_TX_SIZE * 4 + 1)]; + let out = out.as_mut_ptr() as *mut T; + let left = out.add(2 * (64 + 1)); + let top = out.add(64 + 1); + let flipped = out; + if us_above { + ipred_z2_upsample_edge(top, w, src, bd_max); + dx <<= 1; + } else { + let strength = + select_ief_strength(w as _, h as _, smooth_filter, angle - 90) as c_int; + + if edge_filter && strength != 0 { + ipred_z1_filter_edge(top.add(1), max_w.min(w), src, w, strength); + if max_w < w { + top.add((1 + max_w) as _).copy_from_nonoverlapping( + src.add((1 + max_w) as _), + (w - max_w) as _, + ); + } + } else { + top.add(1).copy_from_nonoverlapping(src.add(1), w as _); + } + } + if us_left { + flipped.write(src.read()); + ipred_reverse(flipped.add(1), src, h); + ipred_z2_upsample_edge(left, h, flipped, bd_max); + dy <<= 1; + } else { + let strength = + select_ief_strength(w as _, h as _, smooth_filter, 180 - angle) as c_int; + + if edge_filter && strength != 0 { + flipped.write(src.read()); + ipred_reverse(flipped.add(1), src, h); + ipred_z1_filter_edge(left.add(1), max_h.min(h), flipped, h, strength); + if max_h < h { + left.add((1 + max_h) as _).copy_from_nonoverlapping( + flipped.add((1 + max_h) as _), + (h - max_h) as _, + ); + } + } else { + ipred_reverse(left.add(1), src, h); + } + } + let top_left = src.read(); + top.write(top_left); + left.write(top_left); + + assert!(!(us_above && us_left)); + Z2.ipred_fill(dst, stride, top, left, w, h, dx, dy, us_above, us_left); +} + +unsafe fn ipred_z3( + dst: *mut T, stride: ptrdiff_t, src: *const T, angle: isize, w: c_int, + h: c_int, bd_max: c_int, edge_filter: bool, smooth_filter: bool, +) { + assert!(angle > 180); + let mut dy = dr_intra_derivative(270 - angle as usize) as c_int; + let mut tmp = [MaybeUninit::::uninit(); MAX_TX_SIZE * 4 + 16]; + let mut out = [MaybeUninit::::uninit(); MAX_TX_SIZE * 8 + 15 * 2]; + let out = out.as_mut_ptr() as *mut T; + let tmp = tmp.as_mut_ptr() as *mut T; + + let upsample_left = edge_filter + && select_ief_upsample(w as _, h as _, smooth_filter, angle - 180); + let max_base_y = if upsample_left { + tmp.write(src.read()); + ipred_reverse(tmp.add(1), src, h + w.max(h)); + ipred_z1_upsample_edge(out, w + h, tmp, h + w.min(h), bd_max); + dy <<= 1; + 2 * (w + h) - 2 + } else { + let strength = + select_ief_strength(w as _, h as _, smooth_filter, angle - 180) as c_int; + if strength != 0 { + tmp.write(src.read()); + ipred_reverse(tmp.add(1), src, h + w.max(h)); + ipred_z1_filter_edge(out, w + h, tmp, h + w.min(h), strength); + w + h - 1 + } else { + let n = w + w.min(h); + ipred_reverse(out, src, n); + n - 1 + } + }; + + let base_inc = 1 + upsample_left as c_int; + let pad_pixels = (h + 15).max(64 - max_base_y - 1); + let fill_pixel = out.add(max_base_y as usize).read(); + let base = out.add(max_base_y as usize + 1); + for i in 0..(pad_pixels * base_inc) as usize { + base.add(i).write(fill_pixel); + } + + Z3.ipred_fill(dst, stride, out, w, h, dy, max_base_y, upsample_left); +} + +#[inline(always)] +pub fn dispatch_predict_intra( + mode: PredictionMode, variant: PredictionVariant, + dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize, + ac: &[i16], angle: isize, ief_params: Option, + edge_buf: &IntraEdge, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::dispatch_predict_intra( + mode, variant, dst, tx_size, bit_depth, ac, angle, ief_params, edge_buf, + cpu, + ); + }; + + if cpu < CpuFeatureLevel::NEON { + return call_rust(dst); + } + + unsafe { + let dst_ptr = dst.data_ptr_mut() as *mut _; + let dst_u16 = dst.data_ptr_mut() as *mut u16; + let stride = T::to_asm_stride(dst.plane_cfg.stride) as libc::ptrdiff_t; + let edge_ptr = edge_buf.top_left_ptr() as *const _; + let edge_u16 = edge_buf.top_left_ptr() as *const u16; + let w = tx_size.width() as libc::c_int; + let h = tx_size.height() as libc::c_int; + let angle = angle as libc::c_int; + let bd_max = (1 << bit_depth) - 1; + match T::type_enum() { + PixelType::U8 => match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_8bpc_neon, + PredictionVariant::LEFT => rav1e_ipred_dc_left_8bpc_neon, + PredictionVariant::TOP => rav1e_ipred_dc_top_8bpc_neon, + PredictionVariant::BOTH => rav1e_ipred_dc_8bpc_neon, + })(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_8bpc_neon(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_8bpc_neon(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_8bpc_neon(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_8bpc_neon( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_8bpc_neon( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_8bpc_neon(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_8bpc_neon, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_8bpc_neon, + PredictionVariant::TOP => rav1e_ipred_cfl_top_8bpc_neon, + PredictionVariant::BOTH => rav1e_ipred_cfl_8bpc_neon, + })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle); + } + _ => call_rust(dst), + }, + PixelType::U16 if bit_depth > 8 => match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_16bpc_neon, + PredictionVariant::LEFT => rav1e_ipred_dc_left_16bpc_neon, + PredictionVariant::TOP => rav1e_ipred_dc_top_16bpc_neon, + PredictionVariant::BOTH => rav1e_ipred_dc_16bpc_neon, + })(dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::H_PRED + | PredictionMode::V_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let edge_filter = ief_params.is_some(); + let smooth_filter = ief_params + .map(IntraEdgeFilterParameters::use_smooth_filter) + .unwrap_or_default(); + if (90..=180).contains(&angle) { + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + return ipred_z2( + dst.data_ptr_mut(), + stride, + edge_buf.top_left_ptr(), + angle as isize, + w, + h, + dx, + dy, + bd_max, + edge_filter, + smooth_filter, + ); + } + (if angle < 90 { ipred_z1 } else { ipred_z3 })( + dst.data_ptr_mut(), + stride, + edge_buf.top_left_ptr(), + angle as isize, + w, + h, + bd_max, + edge_filter, + smooth_filter, + ); + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_16bpc_neon( + dst_u16, stride, edge_u16, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_16bpc_neon, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_16bpc_neon, + PredictionVariant::TOP => rav1e_ipred_cfl_top_16bpc_neon, + PredictionVariant::BOTH => rav1e_ipred_cfl_16bpc_neon, + })(dst_u16, stride, edge_u16, w, h, ac_ptr, angle, bd_max); + } + _ => call_rust(dst), + }, + _ => call_rust(dst), + } + } +} + +/// It MUST initialize all `ac` elements. +#[inline(always)] +pub(crate) fn pred_cfl_ac( + ac: &mut [MaybeUninit], luma: &PlaneRegion<'_, T>, bsize: BlockSize, + w_pad: usize, h_pad: usize, cpu: CpuFeatureLevel, +) { + debug_assert_eq!(ac.len(), bsize.area()); + + if cpu < CpuFeatureLevel::NEON { + return rust::pred_cfl_ac::( + ac, luma, bsize, w_pad, h_pad, cpu, + ); + } + + let stride = T::to_asm_stride(luma.plane_cfg.stride) as libc::ptrdiff_t; + let w = bsize.width() as libc::c_int; + let h = bsize.height() as libc::c_int; + let w_pad = w_pad as libc::c_int; + let h_pad = h_pad as libc::c_int; + + // SAFETY: Calls Assembly code. + unsafe { + let ac_ptr = ac.as_mut_ptr(); + match T::type_enum() { + PixelType::U8 => { + let luma_ptr = luma.data_ptr() as *const u8; + (match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_8bpc_neon, + (1, 0) => rav1e_ipred_cfl_ac_422_8bpc_neon, + _ => rav1e_ipred_cfl_ac_420_8bpc_neon, + })(ac_ptr, luma_ptr, stride, w_pad, h_pad, w, h) + } + PixelType::U16 => { + let luma_ptr = luma.data_ptr() as *const u16; + (match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_16bpc_neon, + (1, 0) => rav1e_ipred_cfl_ac_422_16bpc_neon, + _ => rav1e_ipred_cfl_ac_420_16bpc_neon, + })(ac_ptr, luma_ptr, stride, w_pad, h_pad, w, h) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/forward.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/forward.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/forward.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/forward.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,461 @@ +// Copyright (c) 2019-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::asm::shared::transform::forward::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::transform::forward::rust; +use crate::transform::forward_shared::*; +use crate::transform::*; +use crate::util::*; +use std::mem::MaybeUninit; + +use debug_unreachable::debug_unreachable; + +use core::arch::aarch64::*; + +#[derive(Clone, Copy)] +#[repr(transparent)] +struct I32X8(int32x4x2_t); + +impl I32X8 { + #[inline] + const unsafe fn vec(self) -> int32x4x2_t { + self.0 + } + + #[inline] + const unsafe fn raw(a: int32x4x2_t) -> I32X8 { + Self(a) + } + + #[inline] + const unsafe fn new(a: int32x4_t, b: int32x4_t) -> I32X8 { + Self(int32x4x2_t(a, b)) + } +} + +type TxfmFunc = unsafe fn(&mut [I32X8]); + +impl_1d_tx!(allow(unused_attributes), unsafe); + +impl TxOperations for I32X8 { + #[inline] + unsafe fn zero() -> Self { + let zero = vdupq_n_s32(0); + I32X8::new(zero, zero) + } + + #[inline] + unsafe fn tx_mul(self, mul: i32) -> Self { + I32X8::new( + vrshrq_n_s32(vmulq_n_s32(self.vec().0, mul), SHIFT), + vrshrq_n_s32(vmulq_n_s32(self.vec().1, mul), SHIFT), + ) + } + + #[inline] + unsafe fn rshift1(self) -> Self { + I32X8::new( + vhsubq_s32( + self.vec().0, + vreinterpretq_s32_u32(vcltzq_s32(self.vec().0)), + ), + vhsubq_s32( + self.vec().1, + vreinterpretq_s32_u32(vcltzq_s32(self.vec().1)), + ), + ) + } + + #[inline] + unsafe fn add(self, b: Self) -> Self { + I32X8::new( + vaddq_s32(self.vec().0, b.vec().0), + vaddq_s32(self.vec().1, b.vec().1), + ) + } + + #[inline] + unsafe fn sub(self, b: Self) -> Self { + I32X8::new( + vsubq_s32(self.vec().0, b.vec().0), + vsubq_s32(self.vec().1, b.vec().1), + ) + } + + #[inline] + unsafe fn add_avg(self, b: Self) -> Self { + I32X8::new( + vhaddq_s32(self.vec().0, b.vec().0), + vhaddq_s32(self.vec().1, b.vec().1), + ) + } + + #[inline] + unsafe fn sub_avg(self, b: Self) -> Self { + I32X8::new( + vhsubq_s32(self.vec().0, b.vec().0), + vhsubq_s32(self.vec().1, b.vec().1), + ) + } +} + +#[inline] +unsafe fn vreinterpretq_u32_s32_x2(a: int32x4x2_t) -> uint32x4x2_t { + uint32x4x2_t(vreinterpretq_u32_s32(a.0), vreinterpretq_u32_s32(a.1)) +} + +#[inline] +unsafe fn vtrnq_s64_to_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { + let a = vreinterpretq_s64_s32(a); + let b = vreinterpretq_s64_s32(b); + int32x4x2_t( + vreinterpretq_s32_s64(vtrn1q_s64(a, b)), + vreinterpretq_s32_s64(vtrn2q_s64(a, b)), + ) +} + +#[inline] +unsafe fn transpose_8x8_neon( + input: &[I32X8; 8], into: &mut [MaybeUninit; 8], +) { + let stage1 = ( + vtrnq_s32(input[0].vec().0, input[1].vec().0), + vtrnq_s32(input[2].vec().0, input[3].vec().0), + vtrnq_s32(input[4].vec().0, input[5].vec().0), + vtrnq_s32(input[6].vec().0, input[7].vec().0), + vtrnq_s32(input[0].vec().1, input[1].vec().1), + vtrnq_s32(input[2].vec().1, input[3].vec().1), + vtrnq_s32(input[4].vec().1, input[5].vec().1), + vtrnq_s32(input[6].vec().1, input[7].vec().1), + ); + let stage2 = ( + vtrnq_s64_to_s32(stage1.0 .0, stage1.1 .0), + vtrnq_s64_to_s32(stage1.0 .1, stage1.1 .1), + vtrnq_s64_to_s32(stage1.2 .0, stage1.3 .0), + vtrnq_s64_to_s32(stage1.2 .1, stage1.3 .1), + vtrnq_s64_to_s32(stage1.4 .0, stage1.5 .0), + vtrnq_s64_to_s32(stage1.4 .1, stage1.5 .1), + vtrnq_s64_to_s32(stage1.6 .0, stage1.7 .0), + vtrnq_s64_to_s32(stage1.6 .1, stage1.7 .1), + ); + into[0].write(I32X8::new(stage2.0 .0, stage2.2 .0)); + into[1].write(I32X8::new(stage2.1 .0, stage2.3 .0)); + into[2].write(I32X8::new(stage2.0 .1, stage2.2 .1)); + into[3].write(I32X8::new(stage2.1 .1, stage2.3 .1)); + into[4].write(I32X8::new(stage2.4 .0, stage2.6 .0)); + into[5].write(I32X8::new(stage2.5 .0, stage2.7 .0)); + into[6].write(I32X8::new(stage2.4 .1, stage2.6 .1)); + into[7].write(I32X8::new(stage2.5 .1, stage2.7 .1)); +} + +#[inline] +unsafe fn transpose_8x4_neon( + input: &[I32X8; 8], into: &mut [MaybeUninit; 4], +) { + let stage1 = ( + vtrnq_s32(input[0].vec().0, input[1].vec().0), + vtrnq_s32(input[2].vec().0, input[3].vec().0), + vtrnq_s32(input[4].vec().0, input[5].vec().0), + vtrnq_s32(input[6].vec().0, input[7].vec().0), + ); + let stage2 = ( + vtrnq_s64_to_s32(stage1.0 .0, stage1.1 .0), + vtrnq_s64_to_s32(stage1.0 .1, stage1.1 .1), + vtrnq_s64_to_s32(stage1.2 .0, stage1.3 .0), + vtrnq_s64_to_s32(stage1.2 .1, stage1.3 .1), + ); + into[0].write(I32X8::new(stage2.0 .0, stage2.2 .0)); + into[1].write(I32X8::new(stage2.1 .0, stage2.3 .0)); + into[2].write(I32X8::new(stage2.0 .1, stage2.2 .1)); + into[3].write(I32X8::new(stage2.1 .1, stage2.3 .1)); +} + +#[inline] +unsafe fn transpose_4x8_neon( + input: &[I32X8; 4], into: &mut [MaybeUninit; 8], +) { + let stage1 = ( + vtrnq_s32(input[0].vec().0, input[1].vec().0), + vtrnq_s32(input[2].vec().0, input[3].vec().0), + vtrnq_s32(input[0].vec().1, input[1].vec().1), + vtrnq_s32(input[2].vec().1, input[3].vec().1), + ); + let stage2 = ( + vtrnq_s64_to_s32(stage1.0 .0, stage1.1 .0), + vtrnq_s64_to_s32(stage1.0 .1, stage1.1 .1), + vtrnq_s64_to_s32(stage1.2 .0, stage1.3 .0), + vtrnq_s64_to_s32(stage1.2 .1, stage1.3 .1), + ); + into[0].write(I32X8::raw(stage2.0)); + into[1].write(I32X8::raw(stage2.1)); + into[2].write(I32X8::new(stage2.0 .1, stage2.0 .0)); + into[3].write(I32X8::new(stage2.1 .1, stage2.1 .0)); + into[4].write(I32X8::raw(stage2.2)); + into[5].write(I32X8::raw(stage2.3)); + into[6].write(I32X8::new(stage2.2 .1, stage2.2 .0)); + into[7].write(I32X8::new(stage2.3 .1, stage2.3 .0)); +} + +#[inline] +unsafe fn transpose_4x4_neon( + input: &[I32X8; 4], into: &mut [MaybeUninit; 4], +) { + let stage1 = ( + vtrnq_s32(input[0].vec().0, input[1].vec().0), + vtrnq_s32(input[2].vec().0, input[3].vec().0), + ); + let stage2 = ( + vtrnq_s64_to_s32(stage1.0 .0, stage1.1 .0), + vtrnq_s64_to_s32(stage1.0 .1, stage1.1 .1), + ); + into[0].write(I32X8::raw(stage2.0)); + into[1].write(I32X8::raw(stage2.1)); + into[2].write(I32X8::new(stage2.0 .1, stage2.0 .0)); + into[3].write(I32X8::new(stage2.1 .1, stage2.1 .0)); +} + +#[inline] +unsafe fn shift_left_neon(a: I32X8, shift: u8) -> I32X8 { + let shift = vdupq_n_s32(shift.into()); + I32X8::new(vrshlq_s32(a.vec().0, shift), vrshlq_s32(a.vec().1, shift)) +} + +#[inline] +unsafe fn shift_right_neon(a: I32X8) -> I32X8 { + I32X8::new(vrshrq_n_s32(a.vec().0, SHIFT), vrshrq_n_s32(a.vec().1, SHIFT)) +} + +#[inline] +unsafe fn round_shift_array_neon(arr: &mut [I32X8], bit: i8) { + if arr.len() % 4 != 0 { + debug_unreachable!(); + } + + if bit == 0 { + return; + } + if bit > 0 { + if bit == 1 { + for s in arr.chunks_exact_mut(4) { + for chunk in s { + *chunk = shift_right_neon::<1>(*chunk) + } + } + } else if bit == 2 { + for s in arr.chunks_exact_mut(4) { + for chunk in s { + *chunk = shift_right_neon::<2>(*chunk) + } + } + } else { + debug_unreachable!(); + } + } else { + let shift = (-bit) as u8; + for s in arr.chunks_exact_mut(4) { + for chunk in s { + *chunk = shift_left_neon(*chunk, shift); + } + } + } +} + +#[allow(clippy::identity_op, clippy::erasing_op)] +unsafe fn forward_transform_neon( + input: &[i16], output: &mut [MaybeUninit], stride: usize, + tx_size: TxSize, tx_type: TxType, bd: usize, +) { + // Note when assigning txfm_size_col, we use the txfm_size from the + // row configuration and vice versa. This is intentionally done to + // accurately perform rectangular transforms. When the transform is + // rectangular, the number of columns will be the same as the + // txfm_size stored in the row cfg struct. It will make no difference + // for square transforms. + let txfm_size_col = tx_size.width(); + let txfm_size_row = tx_size.height(); + + let col_class = SizeClass1D::from_length(txfm_size_col); + let row_class = SizeClass1D::from_length(txfm_size_row); + + let mut buf = Aligned::new([MaybeUninit::::uninit(); 64 * 64 / 8]); + let buf = &mut buf.data[..txfm_size_col * (txfm_size_row / 8).max(1)]; + let cfg = Txfm2DFlipCfg::fwd(tx_type, tx_size, bd); + + let txfm_func_col = get_func(cfg.txfm_type_col); + let txfm_func_row = get_func(cfg.txfm_type_row); + + // Columns + for cg in (0..txfm_size_col).step_by(8) { + let shift = cfg.shift[0] as u8; + #[inline] + unsafe fn load_columns(input_ptr: *const i16, shift: u8) -> I32X8 { + // TODO: load 64-bits for x4 wide columns + let a = vld1q_s16(input_ptr); + shift_left_neon( + I32X8::new(vmovl_s16(vget_low_s16(a)), vmovl_high_s16(a)), + shift, + ) + } + + // Avoid zero initialization + let col_coeffs = + &mut [MaybeUninit::::uninit(); 64][..txfm_size_row]; + + if cfg.ud_flip { + // flip upside down + for (in_slice, out_reg) in + input[cg..].chunks(stride).zip(col_coeffs.iter_mut().rev()) + { + *out_reg = MaybeUninit::new(load_columns(in_slice.as_ptr(), shift)); + } + } else { + for (in_slice, out_reg) in + input[cg..].chunks(stride).zip(col_coeffs.iter_mut()) + { + *out_reg = MaybeUninit::new(load_columns(in_slice.as_ptr(), shift)); + } + } + + let col_coeffs = slice_assume_init_mut(col_coeffs); + + txfm_func_col(col_coeffs); + round_shift_array_neon(col_coeffs, -cfg.shift[1]); + + // Transpose the array. Select the appropriate method to do so. + match (row_class, col_class) { + (SizeClass1D::X8UP, SizeClass1D::X8UP) => { + for rg in (0..txfm_size_row).step_by(8) { + let buf = &mut buf[(rg / 8 * txfm_size_col) + cg..]; + let buf = cast_mut::<8, _>(buf); + let input = &col_coeffs[rg..]; + let input = cast::<8, _>(input); + transpose_8x8_neon(input, buf); + } + } + (SizeClass1D::X8UP, SizeClass1D::X4) => { + for rg in (0..txfm_size_row).step_by(8) { + let buf = &mut buf[(rg / 8 * txfm_size_col) + cg..]; + let buf = cast_mut::<4, _>(buf); + let input = &col_coeffs[rg..]; + let input = cast::<8, _>(input); + transpose_8x4_neon(input, buf); + } + } + (SizeClass1D::X4, SizeClass1D::X8UP) => { + // Don't need to loop over rows + let buf = &mut buf[cg..]; + let buf = cast_mut::<8, _>(buf); + let input = cast::<4, _>(col_coeffs); + transpose_4x8_neon(input, buf); + } + (SizeClass1D::X4, SizeClass1D::X4) => { + // Don't need to loop over rows + let buf = cast_mut::<4, _>(buf); + let input = cast::<4, _>(col_coeffs); + transpose_4x4_neon(input, buf); + } + } + } + + let buf = slice_assume_init_mut(buf); + + // Rows + for rg in (0..txfm_size_row).step_by(8) { + let row_coeffs = &mut buf[rg / 8 * txfm_size_col..][..txfm_size_col]; + + if cfg.lr_flip { + row_coeffs.reverse(); + } + + txfm_func_row(row_coeffs); + round_shift_array_neon(row_coeffs, -cfg.shift[2]); + + // Write out the coefficients using the correct method for transforms of + // this size. + match row_class { + SizeClass1D::X8UP => { + // Store output in at most 32x32 chunks. See rust code for details. + + // Output is grouped into 32x32 chunks so a stride of at most 32 is + // used for each chunk + let output_stride = txfm_size_row.min(32); + + // Split the first 32 rows from the last 32 rows and offset by rg % 32 + let output = &mut output[(rg & 31) + + (rg >= 32) as usize * output_stride * txfm_size_col.min(32)..]; + + for cg in (0..txfm_size_col).step_by(32) { + // Offset by zero or half of output + let output = &mut output[txfm_size_row * cg..]; + + for c in 0..txfm_size_col.min(32) { + match T::Pixel::type_enum() { + PixelType::U8 => { + let vec = row_coeffs[c + cg].vec(); + vst1_u16_x2( + output[c * output_stride..].as_mut_ptr() as *mut _, + uint16x4x2_t( + vreinterpret_u16_s16(vmovn_s32(vec.0)), + vreinterpret_u16_s16(vmovn_s32(vec.1)), + ), + ); + } + PixelType::U16 => { + vst1q_u32_x2( + output[c * output_stride..].as_mut_ptr() as *mut _, + vreinterpretq_u32_s32_x2(row_coeffs[c + cg].vec()), + ); + } + } + } + } + } + SizeClass1D::X4 => { + // Write out coefficients in normal order - it isn't possible to have + // more than 32 rows. + for c in 0..txfm_size_col { + match T::Pixel::type_enum() { + PixelType::U8 => { + vst1_s16( + output[c * txfm_size_row + rg..].as_mut_ptr() as *mut _, + vmovn_s32(row_coeffs[c].vec().0), + ); + } + PixelType::U16 => { + vst1q_s32( + output[c * txfm_size_row + rg..].as_mut_ptr() as *mut _, + row_coeffs[c].vec().0, + ); + } + } + } + } + } + } +} + +/// # Panics +/// +/// - If called with an invalid combination of `tx_size` and `tx_type` +#[inline] +pub fn forward_transform( + input: &[i16], output: &mut [MaybeUninit], stride: usize, + tx_size: TxSize, tx_type: TxType, bd: usize, cpu: CpuFeatureLevel, +) { + assert!(valid_av1_transform(tx_size, tx_type)); + if cpu >= CpuFeatureLevel::NEON { + // SAFETY: Calls Assembly code. + unsafe { + forward_transform_neon(input, output, stride, tx_size, tx_type, bd); + } + } else { + rust::forward_transform(input, output, stride, tx_size, tx_type, bd, cpu); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/inverse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/inverse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/inverse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/inverse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,322 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::tiling::PlaneRegionMut; +use crate::transform::inverse::*; +use crate::transform::*; +use crate::{Pixel, PixelType}; + +use crate::asm::shared::transform::inverse::*; + +pub fn inverse_transform_add( + input: &[T::Coeff], output: &mut PlaneRegionMut<'_, T>, eob: u16, + tx_size: TxSize, tx_type: TxType, bd: usize, cpu: CpuFeatureLevel, +) { + match T::type_enum() { + PixelType::U8 => { + if let Some(func) = INV_TXFM_FNS[cpu.as_index()][tx_size][tx_type] { + return call_inverse_func( + func, + input, + output, + eob, + tx_size.width(), + tx_size.height(), + bd, + ); + } + } + PixelType::U16 if bd == 10 => { + if let Some(func) = INV_TXFM_HBD_FNS[cpu.as_index()][tx_size][tx_type] { + return call_inverse_hbd_func( + func, + input, + output, + eob, + tx_size.width(), + tx_size.height(), + bd, + ); + } + } + PixelType::U16 => {} + }; + + rust::inverse_transform_add(input, output, eob, tx_size, tx_type, bd, cpu); +} + +macro_rules! decl_itx_fns { + // Takes a 2d list of tx types for W and H + ([$([$(($ENUM:expr, $TYPE1:ident, $TYPE2:ident)),*]),*], $W:expr, $H:expr, + $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + // For each tx type, declare an function for the current WxH + $( + $( + extern { + // Note: type1 and type2 are flipped + fn []( + dst: *mut u8, dst_stride: libc::ptrdiff_t, coeff: *mut i16, + eob: i32 + ); + } + )* + )* + // Create a lookup table for the tx types declared above + const []: [Option; TX_TYPES_PLUS_LL] = { + let mut out: [Option; TX_TYPES_PLUS_LL] = [None; TX_TYPES_PLUS_LL]; + $( + $( + out[$ENUM as usize] = Some([]); + )* + )* + out + }; + } + }; +} + +macro_rules! decl_itx_hbd_fns { + // Takes a 2d list of tx types for W and H + ([$([$(($ENUM:expr, $TYPE1:ident, $TYPE2:ident)),*]),*], $W:expr, $H:expr, + $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + // For each tx type, declare an function for the current WxH + $( + $( + extern { + // Note: type1 and type2 are flipped + fn []( + dst: *mut u16, dst_stride: libc::ptrdiff_t, coeff: *mut i16, + eob: i32, bitdepth_max: i32, + ); + } + )* + )* + // Create a lookup table for the tx types declared above + const []: [Option; TX_TYPES_PLUS_LL] = { + let mut out: [Option; TX_TYPES_PLUS_LL] = [None; TX_TYPES_PLUS_LL]; + $( + $( + out[$ENUM as usize] = Some([]); + )* + )* + out + }; + } + }; +} + +macro_rules! create_wxh_tables { + // Create a lookup table for each cpu feature + ([$([$(($W:expr, $H:expr)),*]),*], $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + const []: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = { + let mut out: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = + [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]; + // For each dimension, add an entry to the table + $( + $( + out[TxSize::[] as usize] = []; + )* + )* + out + }; + } + }; + + // Loop through cpu features + ($DIMS:tt, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + create_wxh_tables!($DIMS, $OPT_LOWER, $OPT_UPPER); + )* + }; +} + +macro_rules! create_wxh_hbd_tables { + // Create a lookup table for each cpu feature + ([$([$(($W:expr, $H:expr)),*]),*], $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + const []: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = { + let mut out: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = + [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]; + // For each dimension, add an entry to the table + $( + $( + out[TxSize::[] as usize] = []; + )* + )* + out + }; + } + }; + + // Loop through cpu features + ($DIMS:tt, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + create_wxh_hbd_tables!($DIMS, $OPT_LOWER, $OPT_UPPER); + )* + }; +} + +macro_rules! impl_itx_fns { + ($TYPES:tt, $W:expr, $H:expr, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + decl_itx_fns!($TYPES, $W, $H, $OPT_LOWER, $OPT_UPPER); + )* + }; + + // Loop over a list of dimensions + ($TYPES_VALID:tt, [$(($W:expr, $H:expr)),*], $OPT:tt) => { + $( + impl_itx_fns!($TYPES_VALID, $W, $H, $OPT); + )* + }; + + ($TYPES64:tt, $DIMS64:tt, $TYPES32:tt, $DIMS32:tt, $TYPES16:tt, $DIMS16:tt, + $TYPES84:tt, $DIMS84:tt, $TYPES4:tt, $DIMS4:tt, $OPT:tt) => { + // Make 2d list of tx types for each set of dimensions. Each set of + // dimensions uses a superset of the previous set of tx types. + impl_itx_fns!([$TYPES64], $DIMS64, $OPT); + impl_itx_fns!([$TYPES64, $TYPES32], $DIMS32, $OPT); + impl_itx_fns!([$TYPES64, $TYPES32, $TYPES16], $DIMS16, $OPT); + impl_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84], $DIMS84, $OPT + ); + impl_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84, $TYPES4], $DIMS4, $OPT + ); + + // Pool all of the dimensions together to create a table for each cpu + // feature level. + create_wxh_tables!( + [$DIMS64, $DIMS32, $DIMS16, $DIMS84, $DIMS4], $OPT + ); + }; +} + +impl_itx_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8)], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)], + [(neon, NEON)] +); + +cpu_function_lookup_table!( + INV_TXFM_FNS: [[[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]], + default: [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + [NEON] +); + +macro_rules! impl_itx_hbd_fns { + + ($TYPES:tt, $W:expr, $H:expr, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + decl_itx_hbd_fns!($TYPES, $W, $H, $OPT_LOWER, $OPT_UPPER); + )* + }; + + // Loop over a list of dimensions + ($TYPES_VALID:tt, [$(($W:expr, $H:expr)),*], $OPT:tt) => { + $( + impl_itx_hbd_fns!($TYPES_VALID, $W, $H, $OPT); + )* + }; + + ($TYPES64:tt, $DIMS64:tt, $TYPES32:tt, $DIMS32:tt, $TYPES16:tt, $DIMS16:tt, + $TYPES84:tt, $DIMS84:tt, $TYPES4:tt, $DIMS4:tt, $OPT:tt) => { + // Make 2d list of tx types for each set of dimensions. Each set of + // dimensions uses a superset of the previous set of tx types. + impl_itx_hbd_fns!([$TYPES64], $DIMS64, $OPT); + impl_itx_hbd_fns!([$TYPES64, $TYPES32], $DIMS32, $OPT); + impl_itx_hbd_fns!([$TYPES64, $TYPES32, $TYPES16], $DIMS16, $OPT); + impl_itx_hbd_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84], $DIMS84, $OPT + ); + impl_itx_hbd_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84, $TYPES4], $DIMS4, $OPT + ); + + // Pool all of the dimensions together to create a table for each cpu + // feature level. + create_wxh_hbd_tables!( + [$DIMS64, $DIMS32, $DIMS16, $DIMS84, $DIMS4], $OPT + ); + }; +} + +impl_itx_hbd_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8)], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)], + [(neon, NEON)] +); + +cpu_function_lookup_table!( + INV_TXFM_HBD_FNS: [[[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]], + default: [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + [NEON] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/aarch64/transform/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2019-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod forward; +pub mod inverse; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright (c) 2019, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(nasm_x86_64)] +pub mod x86; + +#[cfg(asm_neon)] +pub mod aarch64; + +#[cfg(any(nasm_x86_64, asm_neon))] +pub mod shared; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/cdef_dist.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/cdef_dist.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/cdef_dist.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/cdef_dist.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,164 @@ +// Copyright (c) 2022-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(test)] +pub mod test { + use crate::cpu_features::CpuFeatureLevel; + use crate::dist::*; + use crate::frame::*; + use crate::tiling::Area; + use crate::util::Pixel; + use rand::{rng, Rng}; + + fn random_planes(bd: usize) -> (Plane, Plane) { + let mut rng = rng(); + + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + for rows in input_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(rng.random_range(0u16..(1 << bd))); + } + } + + for rows in rec_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(rng.random_range(0u16..(1 << bd))); + } + } + + (input_plane, rec_plane) + } + + /// Create planes with the max values for pixels. + fn max_planes(bd: usize) -> (Plane, Plane) { + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + for rows in input_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from((1 << bd) - 1); + } + } + + for rows in rec_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from((1 << bd) - 1); + } + } + + (input_plane, rec_plane) + } + + /// Create planes with the max difference between the two values. + fn max_diff_planes(bd: usize) -> (Plane, Plane) { + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + for rows in input_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(0); + } + } + + for rows in rec_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from((1 << bd) - 1); + } + } + + (input_plane, rec_plane) + } + + #[test] + fn cdef_dist_simd_random() { + cdef_diff_tester(8, random_planes::); + } + + #[test] + fn cdef_dist_simd_random_hbd() { + cdef_diff_tester(10, random_planes::); + cdef_diff_tester(12, random_planes::); + } + + #[test] + fn cdef_dist_simd_large() { + cdef_diff_tester(8, max_planes::); + } + + #[test] + fn cdef_dist_simd_large_hbd() { + cdef_diff_tester(10, max_planes::); + cdef_diff_tester(12, max_planes::); + } + + #[test] + fn cdef_dist_simd_large_diff() { + cdef_diff_tester(8, max_diff_planes::); + } + + #[test] + fn cdef_dist_simd_large_diff_hbd() { + cdef_diff_tester(10, max_diff_planes::); + cdef_diff_tester(12, max_diff_planes::); + } + + fn cdef_diff_tester( + bd: usize, gen_planes: fn(bd: usize) -> (Plane, Plane), + ) { + let (src_plane, dst_plane) = gen_planes(bd); + + let mut fail = false; + + for w in 1..=8 { + for h in 1..=8 { + // Test alignment by choosing starting location based on width. + let area = Area::StartingAt { x: if w <= 4 { 4 } else { 8 }, y: 40 }; + + let src_region = src_plane.region(area); + let dst_region = dst_plane.region(area); + + let rust = rust::cdef_dist_kernel( + &src_region, + &dst_region, + w, + h, + bd, + CpuFeatureLevel::default(), + ); + + let simd = cdef_dist_kernel( + &src_region, + &dst_region, + w, + h, + bd, + CpuFeatureLevel::default(), + ); + + if simd != rust { + eprintln!( + "CDEF Distortion {}x{}: Assembly doesn't match reference code \ + \t {} (asm) != {} (ref)", + w, h, simd, rust + ); + fail = true; + } + } + + if fail { + panic!(); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod cdef_dist; +pub mod sse; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/sse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/sse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/sse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/dist/sse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,194 @@ +// Copyright (c) 2020-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(test)] +pub mod test { + use crate::config::CpuFeatureLevel; + use crate::dist::*; + use crate::frame::*; + use crate::partition::BlockSize; + use crate::rdo::DistortionScale; + use crate::tiling::Area; + use crate::util::*; + use rand::{rng, Rng}; + + fn random_planes(bd: usize) -> (Plane, Plane) { + let mut rng = rng(); + + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + for rows in input_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(rng.random_range(0u16..(1 << bd))); + } + } + + for rows in rec_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(rng.random_range(0u16..(1 << bd))); + } + } + + (input_plane, rec_plane) + } + + // Create planes with the max difference between the two values. + fn max_diff_planes(bd: usize) -> (Plane, Plane) { + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + for rows in input_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from(0); + } + } + + for rows in rec_plane.as_region_mut().rows_iter_mut() { + for c in rows { + *c = T::cast_from((1 << bd) - 1); + } + } + + (input_plane, rec_plane) + } + + /// Fill data for scaling of one (i.e. no scaling between blocks) + fn scaling_one(scales: &mut [u32]) { + for a in scales.iter_mut() { + *a = DistortionScale::default().0; + } + } + + /// Fill data for scaling of one + fn scaling_random(scales: &mut [u32]) { + let mut rng = rng(); + for a in scales.iter_mut() { + *a = rng.random_range( + DistortionScale::from(0.5).0..DistortionScale::from(1.5).0, + ); + } + } + + /// Fill the max value for scaling + /// TODO: Pair with max difference test + fn scaling_large(scales: &mut [u32]) { + for a in scales.iter_mut() { + *a = DistortionScale::from(f64::MAX).0; + } + } + + #[test] + fn weighted_sse_simd_no_scaling() { + weighted_sse_simd_tester(8, scaling_one, random_planes::); + } + + #[test] + fn weighted_sse_simd_random() { + weighted_sse_simd_tester(8, scaling_random, random_planes::); + } + + #[test] + fn weighted_sse_simd_large() { + weighted_sse_simd_tester(8, scaling_large, max_diff_planes::); + } + + #[test] + fn weighted_sse_hbd_simd_no_scaling() { + weighted_sse_simd_tester(12, scaling_one, random_planes::); + } + + #[test] + fn weighted_sse_hbd_simd_random() { + weighted_sse_simd_tester(12, scaling_random, random_planes::); + } + + #[test] + fn weighted_sse_hbd_simd_large() { + weighted_sse_simd_tester(12, scaling_large, max_diff_planes::); + } + + fn weighted_sse_simd_tester( + bd: usize, fill_scales: fn(scales: &mut [u32]), + gen_planes: fn(bd: usize) -> (Plane, Plane), + ) { + use BlockSize::*; + let blocks = vec![ + BLOCK_4X4, + BLOCK_4X8, + BLOCK_8X4, + BLOCK_8X8, + BLOCK_8X16, + BLOCK_16X8, + BLOCK_16X16, + BLOCK_16X32, + BLOCK_32X16, + BLOCK_32X32, + BLOCK_32X64, + BLOCK_64X32, + BLOCK_64X64, + BLOCK_64X128, + BLOCK_128X64, + BLOCK_128X128, + BLOCK_4X16, + BLOCK_16X4, + BLOCK_8X32, + BLOCK_32X8, + BLOCK_16X64, + BLOCK_64X16, + ]; + + const SCALE_STRIDE: usize = 256; + let mut scaling_storage = Aligned::new([0u32; 256 * SCALE_STRIDE]); + let scaling = &mut scaling_storage.data; + fill_scales(scaling); + + let (input_plane, rec_plane) = gen_planes(bd); + + for block in blocks { + // Start at block width to test alignment. + let area = Area::StartingAt { x: block.width() as isize, y: 40 }; + + let input_region = input_plane.region(area); + let rec_region = rec_plane.region(area); + + let rust = rust::get_weighted_sse( + &input_region, + &rec_region, + scaling, + SCALE_STRIDE, + block.width(), + block.height(), + bd, + CpuFeatureLevel::default(), + ); + + let simd = get_weighted_sse( + &input_region, + &rec_region, + scaling, + SCALE_STRIDE, + block.width(), + block.height(), + bd, + CpuFeatureLevel::default(), + ); + + assert!( + simd == rust, + "Weighted SSE {}: Assembly doesn't match reference code. {} (asm) != {} (ref)", + block, + simd, + rust, + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod dist; +pub mod predict; +pub mod transform; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/predict.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/predict.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/predict.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/predict.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(test)] +mod test { + use interpolate_name::interpolate_test; + use rand::random; + use std::mem::MaybeUninit; + + use crate::context::MAX_TX_SIZE; + use crate::cpu_features::CpuFeatureLevel; + use crate::frame::{AsRegion, Plane}; + use crate::partition::{BlockSize, IntraEdge}; + use crate::predict::dispatch_predict_intra; + use crate::predict::pred_cfl_ac; + use crate::predict::rust; + use crate::predict::{ + IntraEdgeFilterParameters, PredictionMode, PredictionVariant, + }; + use crate::transform::TxSize; + use crate::util::{slice_assume_init_mut, Aligned}; + use crate::Pixel; + + #[test] + fn pred_matches() { + for cpu in + &CpuFeatureLevel::all()[..=CpuFeatureLevel::default().as_index()] + { + pred_matches_inner::(*cpu, 8); + pred_matches_inner::(*cpu, 10); + pred_matches_inner::(*cpu, 12); + } + } + + fn pred_matches_inner(cpu: CpuFeatureLevel, bit_depth: usize) { + let tx_size = TxSize::TX_4X4; + let ac: Aligned<[i16; 32 * 32]> = Aligned::from_fn(|i| i as i16 - 16 * 32); + let edge_buf = Aligned::from_fn(|i| { + T::cast_from(((i ^ 1) + 32).saturating_sub(2 * MAX_TX_SIZE)) + }); + let edge_buf = IntraEdge::mock(&edge_buf); + + let ief_params_all = [ + None, + Some(IntraEdgeFilterParameters::default()), + Some(IntraEdgeFilterParameters { + above_mode: Some(PredictionMode::SMOOTH_PRED), + left_mode: Some(PredictionMode::SMOOTH_PRED), + ..Default::default() + }), + ]; + + for (mode, variant) in [ + (PredictionMode::DC_PRED, PredictionVariant::BOTH), + (PredictionMode::DC_PRED, PredictionVariant::TOP), + (PredictionMode::DC_PRED, PredictionVariant::LEFT), + (PredictionMode::DC_PRED, PredictionVariant::NONE), + (PredictionMode::V_PRED, PredictionVariant::BOTH), + (PredictionMode::H_PRED, PredictionVariant::BOTH), + (PredictionMode::D45_PRED, PredictionVariant::BOTH), + (PredictionMode::D135_PRED, PredictionVariant::BOTH), + (PredictionMode::D113_PRED, PredictionVariant::BOTH), + (PredictionMode::D157_PRED, PredictionVariant::BOTH), + (PredictionMode::D203_PRED, PredictionVariant::BOTH), + (PredictionMode::D67_PRED, PredictionVariant::BOTH), + (PredictionMode::SMOOTH_PRED, PredictionVariant::BOTH), + (PredictionMode::SMOOTH_V_PRED, PredictionVariant::BOTH), + (PredictionMode::SMOOTH_H_PRED, PredictionVariant::BOTH), + (PredictionMode::PAETH_PRED, PredictionVariant::BOTH), + (PredictionMode::UV_CFL_PRED, PredictionVariant::BOTH), + (PredictionMode::UV_CFL_PRED, PredictionVariant::TOP), + (PredictionMode::UV_CFL_PRED, PredictionVariant::LEFT), + (PredictionMode::UV_CFL_PRED, PredictionVariant::NONE), + ] + .iter() + { + let angles = match mode { + PredictionMode::V_PRED => [81, 84, 87, 90, 93, 96, 99].iter(), + PredictionMode::H_PRED => [171, 174, 177, 180, 183, 186, 189].iter(), + PredictionMode::D45_PRED => [36, 39, 42, 45, 48, 51, 54].iter(), + PredictionMode::D135_PRED => { + [126, 129, 132, 135, 138, 141, 144].iter() + } + PredictionMode::D113_PRED => { + [104, 107, 110, 113, 116, 119, 122].iter() + } + PredictionMode::D157_PRED => { + [148, 151, 154, 157, 160, 163, 166].iter() + } + PredictionMode::D203_PRED => { + [194, 197, 200, 203, 206, 209, 212].iter() + } + PredictionMode::D67_PRED => [58, 61, 64, 67, 70, 73, 76].iter(), + PredictionMode::UV_CFL_PRED => [ + -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + ] + .iter(), + _ => [0].iter(), + }; + for angle in angles { + for ief_params in match mode { + PredictionMode::V_PRED if *angle == 90 => [None].iter(), + PredictionMode::H_PRED if *angle == 180 => [None].iter(), + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => ief_params_all.iter(), + _ => [None].iter(), + } { + let expected = { + let mut plane = Plane::from_slice(&[T::zero(); 4 * 4], 4); + rust::dispatch_predict_intra( + *mode, + *variant, + &mut plane.as_region_mut(), + tx_size, + bit_depth, + &ac.data, + *angle, + *ief_params, + &edge_buf, + cpu, + ); + let mut data = [T::zero(); 4 * 4]; + for (v, d) in data.iter_mut().zip(plane.data[..].iter()) { + *v = *d; + } + data + }; + + let mut output = Plane::from_slice(&[T::zero(); 4 * 4], 4); + dispatch_predict_intra( + *mode, + *variant, + &mut output.as_region_mut(), + tx_size, + bit_depth, + &ac.data, + *angle, + *ief_params, + &edge_buf, + cpu, + ); + assert_eq!( + expected, + &output.data[..], + "mode={:?} variant={:?} angle={} ief_params.use_smooth_filter={:?} bit_depth={} cpu={:?}", + *mode, + *variant, + *angle, + ief_params.map(|p| p.use_smooth_filter()), + bit_depth, + cpu + ); + } + } + } + } + + #[interpolate_test(444, 0, 0)] + #[interpolate_test(422, 1, 0)] + #[interpolate_test(420, 1, 1)] + fn pred_cfl_ac_matches(xdec: usize, ydec: usize) { + pred_cfl_ac_matches_inner::(xdec, ydec, 8); + pred_cfl_ac_matches_inner::(xdec, ydec, 10); + pred_cfl_ac_matches_inner::(xdec, ydec, 12); + } + + fn pred_cfl_ac_matches_inner( + xdec: usize, ydec: usize, bit_depth: usize, + ) { + let h_pad = 0; + let w_pad = 0; + let plane_bsize = BlockSize::BLOCK_16X16; + + let mut plane = Plane::from_slice(&[T::zero(); 32 * 32], 32); + for p in plane.data_origin_mut() { + *p = T::cast_from(random::() >> (16 - bit_depth)); + } + let luma = &plane.as_region(); + + let mut ac_ref = Aligned::new([MaybeUninit::new(0x3333i16); 32 * 32]); + let ac_ref = &mut ac_ref.data[..plane_bsize.area()]; + + let cpu = CpuFeatureLevel::RUST; + (match (xdec, ydec) { + (0, 0) => rust::pred_cfl_ac::, + (1, 0) => rust::pred_cfl_ac::, + (_, _) => rust::pred_cfl_ac::, + })(ac_ref, luma, plane_bsize, w_pad, h_pad, cpu); + + for &cpu in + &CpuFeatureLevel::all()[..=CpuFeatureLevel::default().as_index()] + { + let mut ac = Aligned::new([MaybeUninit::new(0x7FFFi16); 32 * 32]); + let ac = &mut ac.data[..plane_bsize.area()]; + + (match (xdec, ydec) { + (0, 0) => pred_cfl_ac::, + (1, 0) => pred_cfl_ac::, + (_, _) => pred_cfl_ac::, + })(ac, luma, plane_bsize, w_pad, h_pad, cpu); + + unsafe { + let ac_ref = slice_assume_init_mut(ac_ref); + let ac = slice_assume_init_mut(ac); + + assert_eq!(&ac_ref, &ac); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/forward.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/forward.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/forward.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/forward.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,111 @@ +// Copyright (c) 2019-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +/// For classifying the number of rows and columns in a transform. Used to +/// select the operations to perform for different vector lengths. +#[derive(Debug, Clone, Copy)] +pub enum SizeClass1D { + X4, + X8UP, +} + +impl SizeClass1D { + #[inline] + pub fn from_length(len: usize) -> Self { + assert!(len.is_power_of_two()); + use SizeClass1D::*; + match len { + 4 => X4, + _ => X8UP, + } + } +} + +pub fn cast(x: &[T]) -> &[T; N] { + // SAFETY: we perform a bounds check with [..N], + // so casting to *const [T; N] is valid because the bounds + // check guarantees that x has N elements + unsafe { &*(&x[..N] as *const [T] as *const [T; N]) } +} + +pub fn cast_mut(x: &mut [T]) -> &mut [T; N] { + // SAFETY: we perform a bounds check with [..N], + // so casting to *mut [T; N] is valid because the bounds + // check guarantees that x has N elements + unsafe { &mut *(&mut x[..N] as *mut [T] as *mut [T; N]) } +} + +#[cfg(test)] +mod test { + use crate::cpu_features::*; + use crate::transform::{forward_transform, get_valid_txfm_types, TxSize}; + use crate::util::slice_assume_init_mut; + use rand::Rng; + use std::mem::MaybeUninit; + + // Ensure that the simd results match the rust code + #[test] + fn test_forward_transform() { + for &cpu in + &CpuFeatureLevel::all()[1..=CpuFeatureLevel::default().as_index()] + { + println!("Testing {:?}", cpu); + test_forward_transform_simd(cpu); + } + } + + fn test_forward_transform_simd(cpu: CpuFeatureLevel) { + let mut rng = rand::rng(); + + let tx_sizes = { + use TxSize::*; + [ + TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_64X64, TX_4X8, TX_8X4, TX_8X16, + TX_16X8, TX_16X32, TX_32X16, TX_32X64, TX_64X32, TX_4X16, TX_16X4, + TX_8X32, TX_32X8, TX_16X64, TX_64X16, + ] + }; + + for &tx_size in &tx_sizes { + let area = tx_size.area(); + + let input: Vec = + (0..area).map(|_| rng.random_range(-255..256)).collect(); + + for &tx_type in get_valid_txfm_types(tx_size) { + let mut output_ref = vec![MaybeUninit::new(0i16); area]; + let mut output_simd = vec![MaybeUninit::new(0i16); area]; + + println!("Testing combination {:?}, {:?}", tx_size, tx_type); + forward_transform( + &input[..], + &mut output_ref[..], + tx_size.width(), + tx_size, + tx_type, + 8, + CpuFeatureLevel::RUST, + ); + let output_ref = unsafe { slice_assume_init_mut(&mut output_ref[..]) }; + forward_transform( + &input[..], + &mut output_simd[..], + tx_size.width(), + tx_size, + tx_type, + 8, + cpu, + ); + let output_simd = + unsafe { slice_assume_init_mut(&mut output_simd[..]) }; + assert_eq!(output_ref, output_simd) + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/inverse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/inverse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/inverse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/inverse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,274 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::tiling::PlaneRegionMut; +use crate::util::*; +use std::mem::MaybeUninit; + +// Note: Input coeffs are mutable since the assembly uses them as a scratchpad +pub type InvTxfmFunc = + unsafe extern fn(*mut u8, libc::ptrdiff_t, *mut i16, i32); + +pub type InvTxfmHBDFunc = + unsafe extern fn(*mut u16, libc::ptrdiff_t, *mut i16, i32, i32); + +pub fn call_inverse_func( + func: InvTxfmFunc, input: &[T::Coeff], output: &mut PlaneRegionMut<'_, T>, + eob: u16, width: usize, height: usize, bd: usize, +) { + debug_assert!(bd == 8); + + // Only use at most 32 columns and 32 rows of input coefficients. + let input: &[T::Coeff] = &input[..width.min(32) * height.min(32)]; + + let mut copied = Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + + // Convert input to 16-bits. + // TODO: Remove by changing inverse assembly to not overwrite its input + for (a, b) in copied.data.iter_mut().zip(input) { + a.write(*b); + } + + // perform the inverse transform + // SAFETY: Calls Assembly code. + unsafe { + func( + output.data_ptr_mut() as *mut _, + output.plane_cfg.stride as isize, + copied.data.as_mut_ptr() as *mut _, + eob as i32 - 1, + ); + } +} + +pub fn call_inverse_hbd_func( + func: InvTxfmHBDFunc, input: &[T::Coeff], + output: &mut PlaneRegionMut<'_, T>, eob: u16, width: usize, height: usize, + bd: usize, +) { + // Only use at most 32 columns and 32 rows of input coefficients. + let input: &[T::Coeff] = &input[..width.min(32) * height.min(32)]; + + let mut copied = Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + + // Convert input to 16-bits. + // TODO: Remove by changing inverse assembly to not overwrite its input + for (a, b) in copied.data.iter_mut().zip(input) { + a.write(*b); + } + + // perform the inverse transform + // SAFETY: Calls Assembly code. + unsafe { + func( + output.data_ptr_mut() as *mut _, + T::to_asm_stride(output.plane_cfg.stride), + copied.data.as_mut_ptr() as *mut _, + eob as i32 - 1, + (1 << bd) - 1, + ); + } +} + +#[cfg(test)] +pub mod test { + use super::*; + use crate::context::av1_get_coded_tx_size; + use crate::cpu_features::CpuFeatureLevel; + use crate::frame::{AsRegion, Plane}; + use crate::scan_order::av1_scan_orders; + use crate::transform::TxSize::*; + use crate::transform::*; + use rand::{random, rng, Rng}; + + pub fn pick_eob( + coeffs: &mut [T], tx_size: TxSize, tx_type: TxType, sub_h: usize, + ) -> u16 { + /* From dav1d + * copy the topleft coefficients such that the return value (being the + * coefficient scantable index for the eob token) guarantees that only + * the topleft $sub out of $sz (where $sz >= $sub) coefficients in both + * dimensions are non-zero. This leads to braching to specific optimized + * simd versions (e.g. dc-only) so that we get full asm coverage in this + * test */ + let coeff_h = av1_get_coded_tx_size(tx_size).height(); + let sub_high: usize = if sub_h > 0 { sub_h * 8 - 1 } else { 0 }; + let sub_low: usize = if sub_h > 1 { sub_high - 8 } else { 0 }; + let mut eob = 0u16; + let mut exit = 0; + + let scan = av1_scan_orders[tx_size][tx_type].scan; + + for (i, &pos) in scan.iter().enumerate() { + exit = i as u16; + + let rc = pos as usize; + let rcx = rc % coeff_h; + let rcy = rc / coeff_h; + + if rcx > sub_high || rcy > sub_high { + break; + } else if eob == 0 && (rcx > sub_low || rcy > sub_low) { + eob = i as u16; + } + } + + if eob != 0 { + eob += rng().random_range(0..(exit - eob).min(1)); + } + for &pos in scan.iter().skip(usize::from(eob)) { + coeffs[pos as usize] = T::cast_from(0); + } + + eob + 1 + } + + pub fn test_transform( + tx_size: TxSize, tx_type: TxType, bit_depth: usize, cpu: CpuFeatureLevel, + ) { + let sub_h_iterations: usize = match tx_size.height().max(tx_size.width()) { + 4 => 2, + 8 => 2, + 16 => 3, + 32 | 64 => 4, + _ => unreachable!(), + }; + + for sub_h in 0..sub_h_iterations { + let mut src_storage = [T::zero(); 64 * 64]; + let src = &mut src_storage[..tx_size.area()]; + let mut dst = Plane::from_slice( + &[T::zero(); 64 * 64][..tx_size.area()], + tx_size.width(), + ); + let mut res = Aligned::<[MaybeUninit; 64 * 64]>::uninit_array(); + let res = &mut res.data[..tx_size.area()]; + let mut freq = + Aligned::<[MaybeUninit; 64 * 64]>::uninit_array(); + let freq = &mut freq.data[..tx_size.area()]; + for ((r, s), d) in + res.iter_mut().zip(src.iter_mut()).zip(dst.data.iter_mut()) + { + *s = T::cast_from(random::() >> (16 - bit_depth)); + *d = T::cast_from(random::() >> (16 - bit_depth)); + r.write(i16::cast_from(*s) - i16::cast_from(*d)); + } + // SAFETY: The loop just initialized res, and all three slices have the same length + let res = unsafe { slice_assume_init_mut(res) }; + forward_transform( + res, + freq, + tx_size.width(), + tx_size, + tx_type, + bit_depth, + CpuFeatureLevel::RUST, + ); + // SAFETY: forward_transform initialized freq + let freq = unsafe { slice_assume_init_mut(freq) }; + + let eob: u16 = pick_eob(freq, tx_size, tx_type, sub_h); + let mut rust_dst = dst.clone(); + + inverse_transform_add( + freq, + &mut dst.as_region_mut(), + eob, + tx_size, + tx_type, + bit_depth, + cpu, + ); + inverse_transform_add( + freq, + &mut rust_dst.as_region_mut(), + eob, + tx_size, + tx_type, + bit_depth, + CpuFeatureLevel::RUST, + ); + assert_eq!(rust_dst.data_origin(), dst.data_origin()); + } + } + + macro_rules! test_itx_fns { + ([$([$(($ENUM:expr, $TYPE1:ident, $TYPE2:ident)),*]),*], $W:expr, $H:expr) => { + paste::item! { + $( + $( + #[test] + fn []() { + for &cpu in + &CpuFeatureLevel::all()[..=CpuFeatureLevel::default().as_index()] + { + test_transform::([], $ENUM, 8, cpu); + test_transform::([], $ENUM, 10, cpu); + test_transform::([], $ENUM, 12, cpu); + } + } + )* + )* + } + }; + + ($TYPES_VALID:tt, [$(($W:expr, $H:expr)),*]) => { + $( + test_itx_fns!($TYPES_VALID, $W, $H); + )* + }; + + ($TYPES64:tt, $DIMS64:tt, $TYPES32:tt, $DIMS32:tt, $TYPES16:tt, $DIMS16:tt, + $TYPES84:tt, $DIMS84:tt, $TYPES4:tt, $DIMS4:tt) => { + test_itx_fns!([$TYPES64], $DIMS64); + test_itx_fns!([$TYPES64, $TYPES32], $DIMS32); + test_itx_fns!([$TYPES64, $TYPES32, $TYPES16], $DIMS16); + test_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84], $DIMS84 + ); + test_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84, $TYPES4], $DIMS4 + ); + }; + } + + test_itx_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8)], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)] + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/shared/transform/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod forward; +pub mod inverse; + +use crate::transform::*; +use std::ops::Index; + +impl Index for [T; TxSize::TX_SIZES_ALL] { + type Output = T; + #[inline] + fn index(&self, tx_size: TxSize) -> &Self::Output { + // SAFETY: values of TxSize are < TX_SIZES_ALL + unsafe { self.get_unchecked(tx_size as usize) } + } +} + +impl Index for [T; TX_TYPES] { + type Output = T; + #[inline] + fn index(&self, tx_type: TxType) -> &Self::Output { + // SAFETY: Wraps WHT_WHT to DCT_DCT + unsafe { self.get_unchecked((tx_type as usize) & 15) } + } +} + +impl Index for [T; TX_TYPES_PLUS_LL] { + type Output = T; + #[inline] + fn index(&self, tx_type: TxType) -> &Self::Output { + // SAFETY: values of TxType are < TX_TYPES_PLUS_LL + unsafe { self.get_unchecked(tx_type as usize) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/cdef.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/cdef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/cdef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/cdef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,501 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cdef::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::*; +use crate::tiling::PlaneRegionMut; +use crate::util::*; + +type CdefFilterFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + tmp: *const u16, + tmp_stride: isize, + pri_strength: i32, + sec_strength: i32, + dir: i32, + damping: i32, +); + +type CdefFilterHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + tmp: *const u16, + tmp_stride: isize, + pri_strength: i32, + sec_strength: i32, + dir: i32, + damping: i32, + bitdepth_max: i32, +); + +#[inline(always)] +const fn decimate_index(xdec: usize, ydec: usize) -> usize { + ((ydec << 1) | xdec) & 3 +} + +pub(crate) unsafe fn cdef_filter_block( + dst: &mut PlaneRegionMut<'_, T>, src: *const T, src_stride: isize, + pri_strength: i32, sec_strength: i32, dir: usize, damping: i32, + bit_depth: usize, xdec: usize, ydec: usize, edges: u8, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut| { + rust::cdef_filter_block( + dst, + src, + src_stride, + pri_strength, + sec_strength, + dir, + damping, + bit_depth, + xdec, + ydec, + edges, + cpu, + ); + }; + + // TODO: handle padding in the fast path + if edges != CDEF_HAVE_ALL && matches!(T::type_enum(), PixelType::U16) { + call_rust(dst); + } else { + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + match T::type_enum() { + PixelType::U8 => { + match CDEF_FILTER_FNS[cpu.as_index()][decimate_index(xdec, ydec)] { + Some(func) => { + // current cdef_filter_block asm does 16->8 for historical + // reasons. Copy into tmp space for now (also handling + // padding) until asm is updated + const TMPSTRIDE: isize = + std::mem::align_of::>() as isize; + /* 256 or 512-bit alignment, greater than 2 * (8>>xdec) + 2 */ + const TMPSIZE: usize = + ((2 + 8 + 2) * TMPSTRIDE + TMPSTRIDE) as usize; + let mut tmp: Aligned<[u16; TMPSIZE]> = + Aligned::new([CDEF_VERY_LARGE; TMPSIZE]); + rust::pad_into_tmp16( + tmp.data.as_mut_ptr().offset(TMPSTRIDE - 2), // points to + // *padding* upper left; the -2 is to make sure the + // block area is SIMD-aligned, not the padding + TMPSTRIDE, + src, // points to *block* upper left + src_stride, + 8 >> xdec, + 8 >> ydec, + edges, + ); + (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + tmp.data.as_ptr().offset(3 * TMPSTRIDE), + TMPSTRIDE, + pri_strength, + sec_strength, + dir as i32, + damping, + ); + } + None => call_rust(dst), + } + } + PixelType::U16 => { + match CDEF_FILTER_HBD_FNS[cpu.as_index()][decimate_index(xdec, ydec)] { + Some(func) => { + (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src as *const _, + src_stride, + pri_strength, + sec_strength, + dir as i32, + damping, + (1 << bit_depth) - 1, + ); + } + None => call_rust(dst), + } + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } + } +} + +extern { + fn rav1e_cdef_filter_4x4_avx2( + dst: *mut u8, dst_stride: isize, tmp: *const u16, tmp_stride: isize, + pri_strength: i32, sec_strength: i32, dir: i32, damping: i32, + ); + + fn rav1e_cdef_filter_4x8_avx2( + dst: *mut u8, dst_stride: isize, tmp: *const u16, tmp_stride: isize, + pri_strength: i32, sec_strength: i32, dir: i32, damping: i32, + ); + + fn rav1e_cdef_filter_8x8_avx2( + dst: *mut u8, dst_stride: isize, tmp: *const u16, tmp_stride: isize, + pri_strength: i32, sec_strength: i32, dir: i32, damping: i32, + ); +} + +static CDEF_FILTER_FNS_AVX2: [Option; 4] = { + let mut out: [Option; 4] = [None; 4]; + out[decimate_index(1, 1)] = Some(rav1e_cdef_filter_4x4_avx2); + out[decimate_index(1, 0)] = Some(rav1e_cdef_filter_4x8_avx2); + out[decimate_index(0, 0)] = Some(rav1e_cdef_filter_8x8_avx2); + out +}; + +cpu_function_lookup_table!( + CDEF_FILTER_FNS: [[Option; 4]], + default: [None; 4], + [AVX2] +); + +cpu_function_lookup_table!( + CDEF_FILTER_HBD_FNS: [[Option; 4]], + default: [None; 4], + [] +); + +type CdefDirLBDFn = + unsafe extern fn(tmp: *const u8, tmp_stride: isize, var: *mut u32) -> i32; +type CdefDirHBDFn = unsafe extern fn( + tmp: *const u16, + tmp_stride: isize, + var: *mut u32, + bitdepth_max: i32, +) -> i32; + +#[inline(always)] +#[allow(clippy::let_and_return)] +pub(crate) fn cdef_find_dir( + img: &PlaneSlice<'_, T>, var: &mut u32, coeff_shift: usize, + cpu: CpuFeatureLevel, +) -> i32 { + let call_rust = + |var: &mut u32| rust::cdef_find_dir::(img, var, coeff_shift, cpu); + + #[cfg(feature = "check_asm")] + let (ref_dir, ref_var) = { + let mut var: u32 = 0; + let dir = call_rust(&mut var); + (dir, var) + }; + + let dir = match T::type_enum() { + PixelType::U8 => { + if let Some(func) = CDEF_DIR_LBD_FNS[cpu.as_index()] { + // SAFETY: Calls Assembly code. + unsafe { + (func)( + img.as_ptr() as *const _, + T::to_asm_stride(img.plane.cfg.stride), + var as *mut u32, + ) + } + } else { + call_rust(var) + } + } + PixelType::U16 if coeff_shift > 0 => { + if let Some(func) = CDEF_DIR_HBD_FNS[cpu.as_index()] { + // SAFETY: Calls Assembly code. + unsafe { + (func)( + img.as_ptr() as *const _, + T::to_asm_stride(img.plane.cfg.stride), + var as *mut u32, + (1 << (coeff_shift + 8)) - 1, + ) + } + } else { + call_rust(var) + } + } + _ => call_rust(var), + }; + + #[cfg(feature = "check_asm")] + { + assert_eq!(dir, ref_dir); + assert_eq!(*var, ref_var); + } + + dir +} + +extern { + fn rav1e_cdef_dir_8bpc_ssse3( + tmp: *const u8, tmp_stride: isize, var: *mut u32, + ) -> i32; + + fn rav1e_cdef_dir_8bpc_avx2( + tmp: *const u8, tmp_stride: isize, var: *mut u32, + ) -> i32; + + fn rav1e_cdef_dir_16bpc_ssse3( + tmp: *const u16, tmp_stride: isize, var: *mut u32, bitdepth_max: i32, + ) -> i32; + + fn rav1e_cdef_dir_16bpc_sse4( + tmp: *const u16, tmp_stride: isize, var: *mut u32, bitdepth_max: i32, + ) -> i32; + + fn rav1e_cdef_dir_16bpc_avx2( + tmp: *const u16, tmp_stride: isize, var: *mut u32, bitdepth_max: i32, + ) -> i32; +} + +cpu_function_lookup_table!( + CDEF_DIR_LBD_FNS: [Option], + default: None, + [ + (SSSE3, Some(rav1e_cdef_dir_8bpc_ssse3)), + (AVX2, Some(rav1e_cdef_dir_8bpc_avx2)) + ] +); + +cpu_function_lookup_table!( + CDEF_DIR_HBD_FNS: [Option], + default: None, + [ + (SSSE3, Some(rav1e_cdef_dir_16bpc_ssse3)), + (SSE4_1, Some(rav1e_cdef_dir_16bpc_sse4)), + (AVX2, Some(rav1e_cdef_dir_16bpc_avx2)) + ] +); + +#[cfg(test)] +mod test { + pub const CDEF_HAVE_NONE: u8 = 0; + use super::*; + use interpolate_name::interpolate_test; + use rand::random; + use std::str::FromStr; + + macro_rules! test_cdef_filter_block { + ($(($XDEC:expr, $YDEC:expr)),*, $OPT:ident, $OPTLIT:literal) => { + $( + paste::item! { + #[interpolate_test(dir_0, 0)] + #[interpolate_test(dir_1, 1)] + #[interpolate_test(dir_2, 2)] + #[interpolate_test(dir_3, 3)] + #[interpolate_test(dir_4, 4)] + #[interpolate_test(dir_5, 5)] + #[interpolate_test(dir_6, 6)] + #[interpolate_test(dir_7, 7)] + fn [](dir: usize) { + if CpuFeatureLevel::default() < CpuFeatureLevel::from_str($OPTLIT).unwrap() { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + let width = 8 >> $XDEC; + let height = 8 >> $YDEC; + let area = width * height; + // dynamic allocation: test + let mut src = vec![0u8; area]; + // dynamic allocation: test + let mut dst = Plane::from_slice(&vec![0u8; area], width); + for (s, d) in src.iter_mut().zip(dst.data.iter_mut()) { + *s = random::(); + *d = random::(); + } + let mut rust_dst = dst.clone(); + + let src_stride = width as isize; + let pri_strength = 1; + let sec_strength = 0; + let damping = 2; + let bit_depth = 8; + + // SAFETY: Calling functions with raw pointers--we created the + // planes above and only read from the start. + unsafe { + cdef_filter_block(&mut dst.as_region_mut(), src.as_ptr(), src_stride, pri_strength, sec_strength, dir, damping, bit_depth, $XDEC, $YDEC, CDEF_HAVE_NONE, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + cdef_filter_block(&mut rust_dst.as_region_mut(), src.as_ptr(), src_stride, pri_strength, sec_strength, dir, damping, bit_depth, $XDEC, $YDEC, CDEF_HAVE_NONE, CpuFeatureLevel::RUST); + assert_eq!(rust_dst.data_origin(), dst.data_origin()); + } + } + } + )* + } + } + + macro_rules! test_cdef_filter_block_hbd { + ($(($XDEC:expr, $YDEC:expr)),*, $OPT:ident, $OPTLIT:literal) => { + $( + paste::item! { + #[interpolate_test(dir_0, 0)] + #[interpolate_test(dir_1, 1)] + #[interpolate_test(dir_2, 2)] + #[interpolate_test(dir_3, 3)] + #[interpolate_test(dir_4, 4)] + #[interpolate_test(dir_5, 5)] + #[interpolate_test(dir_6, 6)] + #[interpolate_test(dir_7, 7)] + fn [](dir: usize) { + if !is_x86_feature_detected!($OPTLIT) { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + let width = 8 >> $XDEC; + let height = 8 >> $YDEC; + let area = width * height; + // dynamic allocation: test + let mut src = vec![0u16; area]; + // dynamic allocation: test + let mut dst = Plane::from_slice(&vec![0u16; area], width); + for (s, d) in src.iter_mut().zip(dst.data.iter_mut()) { + *s = (random::() as u16) << 2; + *d = (random::() as u16) << 2; + } + let mut rust_dst = dst.clone(); + + let src_stride = width as isize; + let pri_strength = 1; + let sec_strength = 0; + let damping = 2; + let bit_depth = 10; + + // SAFETY: Calling functions with raw pointers--we created the + // planes above and only read from the start. + unsafe { + cdef_filter_block(&mut dst.as_region_mut(), src.as_ptr(), src_stride, pri_strength, sec_strength, dir, damping, bit_depth, $XDEC, $YDEC, CDEF_HAVE_NONE, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + cdef_filter_block(&mut rust_dst.as_region_mut(), src.as_ptr(), src_stride, pri_strength, sec_strength, dir, damping, bit_depth, $XDEC, $YDEC, CDEF_HAVE_NONE, CpuFeatureLevel::RUST); + assert_eq!(rust_dst.data_origin(), dst.data_origin()); + } + } + } + )* + } + } + + macro_rules! test_cdef_dir { + ($OPT:ident, $OPTLIT:literal) => { + paste::item! { + #[test] + fn []() { + use crate::context::{TileSuperBlockOffset, SuperBlockOffset}; + + if !is_x86_feature_detected!($OPTLIT) { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + let width = 8; + let height = 8; + let area = width * height; + // dynamic allocation: test + let mut src = vec![0u8; area]; + for s in src.iter_mut() { + *s = random::(); + } + let src = Plane::from_slice(&src, width); + let bit_depth = 8; + let coeff_shift = bit_depth - 8; + let sbo = TileSuperBlockOffset(SuperBlockOffset{ x:0, y:0 }); + + let mut var_asm: u32 = 0; + let mut var_rust: u32 = 0; + let in_po = sbo.plane_offset(&src.cfg); + let dir_asm = cdef_find_dir::( + &src.slice(in_po), + &mut var_asm, + coeff_shift, + CpuFeatureLevel::from_str($OPTLIT).unwrap(), + ); + let dir_rust = cdef_find_dir::( + &src.slice(in_po), + &mut var_rust, + coeff_shift, + CpuFeatureLevel::RUST, + ); + assert_eq!(var_asm, var_rust); + assert_eq!(dir_asm, dir_rust); + } + } + } + } + + macro_rules! test_cdef_dir_hbd { + ($OPT:ident, $OPTLIT:literal) => { + paste::item! { + #[test] + fn []() { + use crate::context::{TileSuperBlockOffset, SuperBlockOffset}; + + if !is_x86_feature_detected!($OPTLIT) { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + let width = 8; + let height = 8; + let area = width * height; + // dynamic allocation: test + let mut src = vec![0u16; area]; + for s in src.iter_mut() { + *s = (random::() as u16) << 2; + } + let src = Plane::from_slice(&src, width); + let bit_depth = 10; + let coeff_shift = bit_depth - 8; + let sbo = TileSuperBlockOffset(SuperBlockOffset{ x:0, y:0 }); + + let mut var_asm: u32 = 0; + let mut var_rust: u32 = 0; + let in_po = sbo.plane_offset(&src.cfg); + let dir_asm = cdef_find_dir::( + &src.slice(in_po), + &mut var_asm, + coeff_shift, + CpuFeatureLevel::from_str($OPTLIT).unwrap(), + ); + let dir_rust = cdef_find_dir::( + &src.slice(in_po), + &mut var_rust, + coeff_shift, + CpuFeatureLevel::RUST, + ); + assert_eq!(var_asm, var_rust); + assert_eq!(dir_asm, dir_rust); + } + } + } + } + + test_cdef_filter_block!((1, 1), (1, 0), (0, 0), avx2, "avx2"); + test_cdef_filter_block_hbd!((1, 1), (1, 0), (0, 0), avx2, "avx2"); + test_cdef_dir!(ssse3, "ssse3"); + test_cdef_dir!(avx2, "avx2"); + test_cdef_dir_hbd!(ssse3, "ssse3"); + test_cdef_dir_hbd!(sse4, "sse4.1"); + test_cdef_dir_hbd!(avx2, "avx2"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/cdef_dist.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/cdef_dist.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/cdef_dist.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/cdef_dist.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,243 @@ +// Copyright (c) 2022-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::activity::apply_ssim_boost; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::tiling::PlaneRegion; +use crate::util::Pixel; +use crate::util::PixelType; +use std::arch::x86_64::*; + +type CdefDistKernelFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, + ret_ptr: *mut u32, +); + +type CdefDistKernelHBDFn = unsafe fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, +) -> (u32, u32, u32); + +extern { + fn rav1e_cdef_dist_kernel_4x4_sse2( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_4x8_sse2( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x4_sse2( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); + fn rav1e_cdef_dist_kernel_8x8_sse2( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ret_ptr: *mut u32, + ); +} + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[allow(clippy::let_and_return)] +pub fn cdef_dist_kernel( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + debug_assert!(src.plane_cfg.xdec == 0); + debug_assert!(src.plane_cfg.ydec == 0); + debug_assert!(dst.plane_cfg.xdec == 0); + debug_assert!(dst.plane_cfg.ydec == 0); + + // Limit kernel to 8x8 + debug_assert!(w <= 8); + debug_assert!(h <= 8); + + let call_rust = + || -> u32 { rust::cdef_dist_kernel(dst, src, w, h, bit_depth, cpu) }; + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let (svar, dvar, sse) = match T::type_enum() { + PixelType::U8 => { + if let Some(func) = + CDEF_DIST_KERNEL_FNS[cpu.as_index()][kernel_fn_index(w, h)] + { + let mut ret_buf = [0u32; 3]; + // SAFETY: Calls Assembly code. + unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ret_buf.as_mut_ptr(), + ) + } + + (ret_buf[0], ret_buf[1], ret_buf[2]) + } else { + return call_rust(); + } + } + PixelType::U16 => { + if let Some(func) = + CDEF_DIST_KERNEL_HBD_FNS[cpu.as_index()][kernel_fn_index(w, h)] + { + // SAFETY: Calls Assembly code. + unsafe { + func( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + } + } else { + return call_rust(); + } + } + }; + + let dist = apply_ssim_boost(sse, svar, dvar, bit_depth); + #[cfg(feature = "check_asm")] + assert_eq!( + dist, ref_dist, + "CDEF Distortion {}x{}: Assembly doesn't match reference code.", + w, h + ); + + dist +} + +/// Store functions in a 8x8 grid. Most will be empty. +const CDEF_DIST_KERNEL_FNS_LENGTH: usize = 8 * 8; + +const fn kernel_fn_index(w: usize, h: usize) -> usize { + ((w - 1) << 3) | (h - 1) +} + +static CDEF_DIST_KERNEL_FNS_SSE2: [Option; + CDEF_DIST_KERNEL_FNS_LENGTH] = { + let mut out: [Option; CDEF_DIST_KERNEL_FNS_LENGTH] = + [None; CDEF_DIST_KERNEL_FNS_LENGTH]; + + out[kernel_fn_index(4, 4)] = Some(rav1e_cdef_dist_kernel_4x4_sse2); + out[kernel_fn_index(4, 8)] = Some(rav1e_cdef_dist_kernel_4x8_sse2); + out[kernel_fn_index(8, 4)] = Some(rav1e_cdef_dist_kernel_8x4_sse2); + out[kernel_fn_index(8, 8)] = Some(rav1e_cdef_dist_kernel_8x8_sse2); + + out +}; + +cpu_function_lookup_table!( + CDEF_DIST_KERNEL_FNS: + [[Option; CDEF_DIST_KERNEL_FNS_LENGTH]], + default: [None; CDEF_DIST_KERNEL_FNS_LENGTH], + [SSE2] +); + +#[target_feature(enable = "avx2")] +#[inline] +unsafe fn mm256_sum_i32(ymm: __m256i) -> i32 { + // We split the vector in half and then add the two halves and sum. + let m1 = _mm256_extracti128_si256(ymm, 1); + let m2 = _mm256_castsi256_si128(ymm); + let m2 = _mm_add_epi32(m2, m1); + let m1 = _mm_shuffle_epi32(m2, 0b11_10_11_10); + let m2 = _mm_add_epi32(m2, m1); + let m1 = _mm_shuffle_epi32(m2, 0b01_01_01_01); + let m2 = _mm_add_epi32(m2, m1); + _mm_cvtsi128_si32(m2) +} + +#[target_feature(enable = "avx2")] +#[inline] +unsafe fn rav1e_cdef_dist_kernel_8x8_hbd_avx2( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, +) -> (u32, u32, u32) { + let src = src as *const u8; + let dst = dst as *const u8; + + unsafe fn sum16(src: *const u8, src_stride: isize) -> u32 { + let h = 8; + let res = (0..h) + .map(|row| _mm_load_si128(src.offset(row * src_stride) as *const _)) + .reduce(|a, b| _mm_add_epi16(a, b)) + .unwrap(); + + let m32 = _mm256_cvtepi16_epi32(res); + mm256_sum_i32(m32) as u32 + } + unsafe fn mpadd32( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + ) -> u32 { + let h = 8; + let res = (0..h / 2) + .map(|row| { + let s = _mm256_loadu2_m128i( + src.offset(2 * row * src_stride) as *const _, + src.offset((2 * row + 1) * src_stride) as *const _, + ); + + let d = _mm256_loadu2_m128i( + dst.offset(2 * row * dst_stride) as *const _, + dst.offset((2 * row + 1) * dst_stride) as *const _, + ); + + _mm256_madd_epi16(s, d) + }) + .reduce(|a, b| _mm256_add_epi32(a, b)) + .unwrap(); + mm256_sum_i32(res) as u32 + } + + let sum_s = sum16(src, src_stride); + let sum_d = sum16(dst, dst_stride); + let sum_s2 = mpadd32(src, src_stride, src, src_stride); + let sum_d2 = mpadd32(dst, dst_stride, dst, dst_stride); + let sum_sd = mpadd32(src, src_stride, dst, dst_stride); + + // To get the distortion, compute sum of squared error and apply a weight + // based on the variance of the two planes. + let sse = sum_d2 + sum_s2 - 2 * sum_sd; + + // Convert to 64-bits to avoid overflow when squaring + let sum_s = sum_s as u64; + let sum_d = sum_d as u64; + + let svar = (sum_s2 as u64 - (sum_s * sum_s + 32) / 64) as u32; + let dvar = (sum_d2 as u64 - (sum_d * sum_d + 32) / 64) as u32; + + (svar, dvar, sse) +} + +static CDEF_DIST_KERNEL_HBD_FNS_AVX2: [Option; + CDEF_DIST_KERNEL_FNS_LENGTH] = { + let mut out: [Option; CDEF_DIST_KERNEL_FNS_LENGTH] = + [None; CDEF_DIST_KERNEL_FNS_LENGTH]; + + out[kernel_fn_index(8, 8)] = Some(rav1e_cdef_dist_kernel_8x8_hbd_avx2); + + out +}; + +cpu_function_lookup_table!( + CDEF_DIST_KERNEL_HBD_FNS: + [[Option; CDEF_DIST_KERNEL_FNS_LENGTH]], + default: [None; CDEF_DIST_KERNEL_FNS_LENGTH], + [AVX2] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,970 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub use self::cdef_dist::*; +pub use self::sse::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::partition::BlockSize; +use crate::tiling::*; +use crate::util::*; + +mod cdef_dist; +mod sse; + +type SadFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, +) -> u32; + +type SatdFn = SadFn; + +type SadHBDFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, +) -> u32; + +type SatdHBDFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, + bdmax: u32, +) -> u32; + +macro_rules! declare_asm_dist_fn { + ($(($name: ident, $T: ident)),+) => ( + $( + extern { fn $name ( + src: *const $T, src_stride: isize, dst: *const $T, dst_stride: isize + ) -> u32; } + )+ + ) +} + +macro_rules! declare_asm_satd_hbd_fn { + ($($name: ident),+) => ( + $( + extern { pub(crate) fn $name ( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, bdmax: u32 + ) -> u32; } + )+ + ) +} + +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +/// Horizontally sum 8 32-bit values in a YMM register +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn mm256_sum_i32(ymm: __m256i) -> i32 { + // We split the vector in half and then add (2, 3) + (0, 1), and finally 0 + 1. + let m1 = _mm256_extracti128_si256(ymm, 1); + let m2 = _mm256_castsi256_si128(ymm); + let m2 = _mm_add_epi32(m2, m1); + let m1 = _mm_shuffle_epi32(m2, 0b11_10_11_10); + let m2 = _mm_add_epi32(m2, m1); + let m1 = _mm_shuffle_epi32(m2, 0b01_01_01_01); + let m2 = _mm_add_epi32(m2, m1); + _mm_cvtsi128_si32(m2) +} + +/// Perform SAD over at most 256 (10 or 12-bit) values +/// +/// Returns a YMM register of 8 32-bit sums, which can +/// be used as an intermediate result for larger summations +/// +/// Limited to 256 values as any more 12-bit SADs may overflow +/// a 16-bit value. +/// +/// # Panics +/// - If `W` * `n_rows` > 256 +/// - If `W` is not a multiple of 16 +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn rav1e_sad_wxh_hbd_avx2_inner( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, + n_rows: usize, +) -> __m256i { + const LOADS_PER_REGISTER: usize = 32 / core::mem::size_of::(); // 16 + + // Check we can't overflow a 16-bit register + assert!(W * n_rows <= 256); + // Check we load the right number of values + assert_eq!(W % LOADS_PER_REGISTER, 0); + + let mut sum16 = _mm256_setzero_si256(); + (0..n_rows as isize).for_each(|n| { + (0..(W / LOADS_PER_REGISTER) as isize).for_each(|x| { + let res = _mm256_abs_epi16(_mm256_sub_epi16( + _mm256_loadu_si256( + src.offset(n * src_stride + x * LOADS_PER_REGISTER as isize * 2) + as *const _, + ), + _mm256_loadu_si256( + dst.offset(n * dst_stride + x * LOADS_PER_REGISTER as isize * 2) + as *const _, + ), + )); + sum16 = _mm256_add_epi16(sum16, res); + }) + }); + + let b = _mm256_unpackhi_epi16(sum16, _mm256_setzero_si256()); + let c = _mm256_unpacklo_epi16(sum16, _mm256_setzero_si256()); + + _mm256_add_epi32(b, c) +} + +/// Sum of Absolute Differences +/// +/// By convention, `src_stride` and `dst_stride` are measured in bytes, not u16's +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn rav1e_sad_wxh_hbd_avx2( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + n_rows: usize, +) -> u32 { + const MAX_INNER_SIZE: usize = 256; + let src = src as *const u8; + let dst = dst as *const u8; + + // Can we sum at least 1 entire row at once? + if W <= MAX_INNER_SIZE { + // If we can fit the entire area in one inner iteration, do it + if W * n_rows <= MAX_INNER_SIZE { + return mm256_sum_i32(rav1e_sad_wxh_hbd_avx2_inner::( + src, src_stride, dst, dst_stride, n_rows, + )) as u32; + } + // Otherwise, sum rows in sets of 256 + assert_eq!(MAX_INNER_SIZE % W, 0); + let row_step = (MAX_INNER_SIZE / W).min(n_rows); + assert_eq!(n_rows % row_step, 0); + let mut sum = _mm256_setzero_si256(); + (0..(n_rows / row_step) as isize).for_each(|w| { + let src = src.offset(w * row_step as isize * src_stride); + let dst = dst.offset(w * row_step as isize * dst_stride); + let res = rav1e_sad_wxh_hbd_avx2_inner::( + src, src_stride, dst, dst_stride, row_step, + ); + sum = _mm256_add_epi32(sum, res) + }); + mm256_sum_i32(sum) as u32 + } else { + // If we can't sum an entire row in one shot, split each row up + assert_eq!(W % MAX_INNER_SIZE, 0); + let sum = (0..n_rows) + .flat_map(|_| { + (0..(W / MAX_INNER_SIZE)).map(move |h| { + let src = src.offset(src_stride + (h * MAX_INNER_SIZE * 2) as isize); + let dst = dst.offset(dst_stride + (h * MAX_INNER_SIZE * 2) as isize); + rav1e_sad_wxh_hbd_avx2_inner::( + src, src_stride, dst, dst_stride, 1, + ) + }) + }) + .reduce(|a, b| unsafe { _mm256_add_epi32(a, b) }) + .unwrap(); + mm256_sum_i32(sum) as u32 + } +} + +declare_asm_dist_fn![ + // SSSE3 + (rav1e_sad_4x4_hbd_ssse3, u16), + (rav1e_sad_16x16_hbd_ssse3, u16), + (rav1e_satd_8x8_ssse3, u8), + // SSE2 + (rav1e_sad4x4_sse2, u8), + (rav1e_sad4x8_sse2, u8), + (rav1e_sad4x16_sse2, u8), + (rav1e_sad8x4_sse2, u8), + (rav1e_sad8x8_sse2, u8), + (rav1e_sad8x16_sse2, u8), + (rav1e_sad8x32_sse2, u8), + (rav1e_sad16x4_sse2, u8), + (rav1e_sad16x8_sse2, u8), + (rav1e_sad16x16_sse2, u8), + (rav1e_sad16x32_sse2, u8), + (rav1e_sad16x64_sse2, u8), + (rav1e_sad32x8_sse2, u8), + (rav1e_sad32x16_sse2, u8), + (rav1e_sad32x32_sse2, u8), + (rav1e_sad32x64_sse2, u8), + (rav1e_sad64x16_sse2, u8), + (rav1e_sad64x32_sse2, u8), + (rav1e_sad64x64_sse2, u8), + (rav1e_sad64x128_sse2, u8), + (rav1e_sad128x64_sse2, u8), + (rav1e_sad128x128_sse2, u8), + // SSE4 + (rav1e_satd_4x4_sse4, u8), + // AVX + (rav1e_sad32x8_avx2, u8), + (rav1e_sad32x16_avx2, u8), + (rav1e_sad32x32_avx2, u8), + (rav1e_sad32x64_avx2, u8), + (rav1e_sad64x16_avx2, u8), + (rav1e_sad64x32_avx2, u8), + (rav1e_sad64x64_avx2, u8), + (rav1e_sad64x128_avx2, u8), + (rav1e_sad128x64_avx2, u8), + (rav1e_sad128x128_avx2, u8), + (rav1e_satd_4x4_avx2, u8), + (rav1e_satd_8x8_avx2, u8), + (rav1e_satd_16x16_avx2, u8), + (rav1e_satd_32x32_avx2, u8), + (rav1e_satd_64x64_avx2, u8), + (rav1e_satd_128x128_avx2, u8), + (rav1e_satd_4x8_avx2, u8), + (rav1e_satd_8x4_avx2, u8), + (rav1e_satd_8x16_avx2, u8), + (rav1e_satd_16x8_avx2, u8), + (rav1e_satd_16x32_avx2, u8), + (rav1e_satd_32x16_avx2, u8), + (rav1e_satd_32x64_avx2, u8), + (rav1e_satd_64x32_avx2, u8), + (rav1e_satd_64x128_avx2, u8), + (rav1e_satd_128x64_avx2, u8), + (rav1e_satd_4x16_avx2, u8), + (rav1e_satd_16x4_avx2, u8), + (rav1e_satd_8x32_avx2, u8), + (rav1e_satd_32x8_avx2, u8), + (rav1e_satd_16x64_avx2, u8), + (rav1e_satd_64x16_avx2, u8) +]; + +declare_asm_satd_hbd_fn![ + rav1e_satd_4x4_hbd_avx2, + rav1e_satd_8x4_hbd_avx2, + rav1e_satd_4x8_hbd_avx2, + rav1e_satd_8x8_hbd_avx2, + rav1e_satd_16x8_hbd_avx2, + rav1e_satd_16x16_hbd_avx2, + rav1e_satd_32x32_hbd_avx2, + rav1e_satd_64x64_hbd_avx2, + rav1e_satd_128x128_hbd_avx2, + rav1e_satd_16x32_hbd_avx2, + rav1e_satd_16x64_hbd_avx2, + rav1e_satd_32x16_hbd_avx2, + rav1e_satd_32x64_hbd_avx2, + rav1e_satd_64x16_hbd_avx2, + rav1e_satd_64x32_hbd_avx2, + rav1e_satd_64x128_hbd_avx2, + rav1e_satd_128x64_hbd_avx2, + rav1e_satd_32x8_hbd_avx2, + rav1e_satd_8x16_hbd_avx2, + rav1e_satd_8x32_hbd_avx2, + rav1e_satd_16x4_hbd_avx2, + rav1e_satd_4x16_hbd_avx2 +]; + +// BlockSize::BLOCK_SIZES.next_power_of_two(); +pub(crate) const DIST_FNS_LENGTH: usize = 32; + +#[inline] +pub(crate) const fn to_index(bsize: BlockSize) -> usize { + bsize as usize & (DIST_FNS_LENGTH - 1) +} + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_sad( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { rust::get_sad(dst, src, w, h, bit_depth, cpu) }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SAD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SAD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!(dist, ref_dist); + + dist +} + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_satd( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, cpu: CpuFeatureLevel, +) -> u32 { + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u32 { rust::get_satd(dst, src, w, h, bit_depth, cpu) }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SATD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + ) + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SATD_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + (func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + (1 << bit_depth) - 1, + ) + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!(dist, ref_dist); + + dist +} + +// We have hand-written ASM for 4x4 and 16x16 HBD blocks, +// so we can use those for other block sizes as well. +macro_rules! get_sad_hbd_ssse3 { + ($(($W:expr, $H:expr, $BS:expr)),*) => { + $( + paste::item! { + #[target_feature(enable = "ssse3")] + unsafe extern fn []( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ) -> u32 { + let mut sum = 0; + for w in (0..$W).step_by($BS) { + for h in (0..$H).step_by($BS) { + sum += []( + src.offset(w + h * src_stride / 2), + src_stride, + dst.offset(w + h * dst_stride / 2), + dst_stride + ); + } + } + sum + } + } + )* + } +} + +get_sad_hbd_ssse3!( + // 4x4 base + (8, 8, 4), + (4, 8, 4), + (8, 4, 4), + (8, 16, 4), + (16, 8, 4), + (4, 16, 4), + (16, 4, 4), + (8, 32, 4), + (32, 8, 4), + (32, 32, 16), + (64, 64, 16), + (128, 128, 16), + (16, 32, 16), + (32, 16, 16), + (32, 64, 16), + (64, 32, 16), + (64, 128, 16), + (128, 64, 16), + (16, 64, 16), + (64, 16, 16) +); + +macro_rules! get_sad_hbd_avx2_WxH { + ($(($W:expr, $H:expr)),*) => { + $( + paste::item! { + #[target_feature(enable = "avx2")] + unsafe extern fn []( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, + ) -> u32 { + rav1e_sad_wxh_hbd_avx2::<$W>( + src, + src_stride, + dst, + dst_stride, + $H, + ) + } + } + )* + } +} + +get_sad_hbd_avx2_WxH!( + // No advantage to AVX below 16 width + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128) +); + +static SAD_FNS_SSE2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad4x4_sse2); + out[BLOCK_4X8 as usize] = Some(rav1e_sad4x8_sse2); + out[BLOCK_4X16 as usize] = Some(rav1e_sad4x16_sse2); + + out[BLOCK_8X4 as usize] = Some(rav1e_sad8x4_sse2); + out[BLOCK_8X8 as usize] = Some(rav1e_sad8x8_sse2); + out[BLOCK_8X16 as usize] = Some(rav1e_sad8x16_sse2); + out[BLOCK_8X32 as usize] = Some(rav1e_sad8x32_sse2); + + out[BLOCK_16X4 as usize] = Some(rav1e_sad16x4_sse2); + out[BLOCK_16X8 as usize] = Some(rav1e_sad16x8_sse2); + out[BLOCK_16X16 as usize] = Some(rav1e_sad16x16_sse2); + out[BLOCK_16X32 as usize] = Some(rav1e_sad16x32_sse2); + out[BLOCK_16X64 as usize] = Some(rav1e_sad16x64_sse2); + + out[BLOCK_32X8 as usize] = Some(rav1e_sad32x8_sse2); + out[BLOCK_32X16 as usize] = Some(rav1e_sad32x16_sse2); + out[BLOCK_32X32 as usize] = Some(rav1e_sad32x32_sse2); + out[BLOCK_32X64 as usize] = Some(rav1e_sad32x64_sse2); + + out[BLOCK_64X16 as usize] = Some(rav1e_sad64x16_sse2); + out[BLOCK_64X32 as usize] = Some(rav1e_sad64x32_sse2); + out[BLOCK_64X64 as usize] = Some(rav1e_sad64x64_sse2); + out[BLOCK_64X128 as usize] = Some(rav1e_sad64x128_sse2); + + out[BLOCK_128X64 as usize] = Some(rav1e_sad128x64_sse2); + out[BLOCK_128X128 as usize] = Some(rav1e_sad128x128_sse2); + + out +}; + +static SAD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad4x4_sse2); + out[BLOCK_4X8 as usize] = Some(rav1e_sad4x8_sse2); + out[BLOCK_4X16 as usize] = Some(rav1e_sad4x16_sse2); + + out[BLOCK_8X4 as usize] = Some(rav1e_sad8x4_sse2); + out[BLOCK_8X8 as usize] = Some(rav1e_sad8x8_sse2); + out[BLOCK_8X16 as usize] = Some(rav1e_sad8x16_sse2); + out[BLOCK_8X32 as usize] = Some(rav1e_sad8x32_sse2); + + out[BLOCK_16X4 as usize] = Some(rav1e_sad16x4_sse2); + out[BLOCK_16X8 as usize] = Some(rav1e_sad16x8_sse2); + out[BLOCK_16X16 as usize] = Some(rav1e_sad16x16_sse2); + out[BLOCK_16X32 as usize] = Some(rav1e_sad16x32_sse2); + out[BLOCK_16X64 as usize] = Some(rav1e_sad16x64_sse2); + + out[BLOCK_32X8 as usize] = Some(rav1e_sad32x8_avx2); + out[BLOCK_32X16 as usize] = Some(rav1e_sad32x16_avx2); + out[BLOCK_32X32 as usize] = Some(rav1e_sad32x32_avx2); + out[BLOCK_32X64 as usize] = Some(rav1e_sad32x64_avx2); + + out[BLOCK_64X16 as usize] = Some(rav1e_sad64x16_avx2); + out[BLOCK_64X32 as usize] = Some(rav1e_sad64x32_avx2); + out[BLOCK_64X64 as usize] = Some(rav1e_sad64x64_avx2); + out[BLOCK_64X128 as usize] = Some(rav1e_sad64x128_avx2); + + out[BLOCK_128X64 as usize] = Some(rav1e_sad128x64_avx2); + out[BLOCK_128X128 as usize] = Some(rav1e_sad128x128_avx2); + + out +}; + +cpu_function_lookup_table!( + SAD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSE2, AVX2] +); + +static SAD_HBD_FNS_SSSE3: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad_4x4_hbd_ssse3); + out[BLOCK_8X8 as usize] = Some(rav1e_sad_8x8_hbd_ssse3); + out[BLOCK_16X16 as usize] = Some(rav1e_sad_16x16_hbd_ssse3); + out[BLOCK_32X32 as usize] = Some(rav1e_sad_32x32_hbd_ssse3); + out[BLOCK_64X64 as usize] = Some(rav1e_sad_64x64_hbd_ssse3); + out[BLOCK_128X128 as usize] = Some(rav1e_sad_128x128_hbd_ssse3); + + out[BLOCK_4X8 as usize] = Some(rav1e_sad_4x8_hbd_ssse3); + out[BLOCK_8X4 as usize] = Some(rav1e_sad_8x4_hbd_ssse3); + out[BLOCK_8X16 as usize] = Some(rav1e_sad_8x16_hbd_ssse3); + out[BLOCK_16X8 as usize] = Some(rav1e_sad_16x8_hbd_ssse3); + out[BLOCK_16X32 as usize] = Some(rav1e_sad_16x32_hbd_ssse3); + out[BLOCK_32X16 as usize] = Some(rav1e_sad_32x16_hbd_ssse3); + out[BLOCK_32X64 as usize] = Some(rav1e_sad_32x64_hbd_ssse3); + out[BLOCK_64X32 as usize] = Some(rav1e_sad_64x32_hbd_ssse3); + out[BLOCK_64X128 as usize] = Some(rav1e_sad_64x128_hbd_ssse3); + out[BLOCK_128X64 as usize] = Some(rav1e_sad_128x64_hbd_ssse3); + + out[BLOCK_4X16 as usize] = Some(rav1e_sad_4x16_hbd_ssse3); + out[BLOCK_16X4 as usize] = Some(rav1e_sad_16x4_hbd_ssse3); + out[BLOCK_8X32 as usize] = Some(rav1e_sad_8x32_hbd_ssse3); + out[BLOCK_32X8 as usize] = Some(rav1e_sad_32x8_hbd_ssse3); + out[BLOCK_16X64 as usize] = Some(rav1e_sad_16x64_hbd_ssse3); + out[BLOCK_64X16 as usize] = Some(rav1e_sad_64x16_hbd_ssse3); + + out +}; + +static SAD_HBD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_sad_4x4_hbd_ssse3); + out[BLOCK_8X8 as usize] = Some(rav1e_sad_8x8_hbd_ssse3); + out[BLOCK_16X16 as usize] = Some(rav1e_sad_16x16_hbd_avx2); + out[BLOCK_32X32 as usize] = Some(rav1e_sad_32x32_hbd_avx2); + out[BLOCK_64X64 as usize] = Some(rav1e_sad_64x64_hbd_avx2); + out[BLOCK_128X128 as usize] = Some(rav1e_sad_128x128_hbd_avx2); + + out[BLOCK_4X8 as usize] = Some(rav1e_sad_4x8_hbd_ssse3); + out[BLOCK_8X4 as usize] = Some(rav1e_sad_8x4_hbd_ssse3); + out[BLOCK_8X16 as usize] = Some(rav1e_sad_8x16_hbd_ssse3); + out[BLOCK_16X8 as usize] = Some(rav1e_sad_16x8_hbd_avx2); + out[BLOCK_16X32 as usize] = Some(rav1e_sad_16x32_hbd_avx2); + out[BLOCK_32X16 as usize] = Some(rav1e_sad_32x16_hbd_avx2); + out[BLOCK_32X64 as usize] = Some(rav1e_sad_32x64_hbd_avx2); + out[BLOCK_64X32 as usize] = Some(rav1e_sad_64x32_hbd_avx2); + out[BLOCK_64X128 as usize] = Some(rav1e_sad_64x128_hbd_avx2); + out[BLOCK_128X64 as usize] = Some(rav1e_sad_128x64_hbd_avx2); + + out[BLOCK_4X16 as usize] = Some(rav1e_sad_4x16_hbd_ssse3); + out[BLOCK_16X4 as usize] = Some(rav1e_sad_16x4_hbd_avx2); + out[BLOCK_32X8 as usize] = Some(rav1e_sad_32x8_hbd_avx2); + out[BLOCK_16X64 as usize] = Some(rav1e_sad_16x64_hbd_avx2); + out[BLOCK_64X16 as usize] = Some(rav1e_sad_64x16_hbd_avx2); + + out +}; + +cpu_function_lookup_table!( + SAD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSSE3, AVX2] +); + +static SATD_FNS_SSSE3: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_8X8 as usize] = Some(rav1e_satd_8x8_ssse3); + + out +}; + +static SATD_FNS_SSE4_1: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_satd_4x4_sse4); + out[BLOCK_8X8 as usize] = Some(rav1e_satd_8x8_ssse3); + + out +}; + +static SATD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_satd_4x4_avx2); + out[BLOCK_8X8 as usize] = Some(rav1e_satd_8x8_avx2); + out[BLOCK_16X16 as usize] = Some(rav1e_satd_16x16_avx2); + out[BLOCK_32X32 as usize] = Some(rav1e_satd_32x32_avx2); + out[BLOCK_64X64 as usize] = Some(rav1e_satd_64x64_avx2); + out[BLOCK_128X128 as usize] = Some(rav1e_satd_128x128_avx2); + + out[BLOCK_4X8 as usize] = Some(rav1e_satd_4x8_avx2); + out[BLOCK_8X4 as usize] = Some(rav1e_satd_8x4_avx2); + out[BLOCK_8X16 as usize] = Some(rav1e_satd_8x16_avx2); + out[BLOCK_16X8 as usize] = Some(rav1e_satd_16x8_avx2); + out[BLOCK_16X32 as usize] = Some(rav1e_satd_16x32_avx2); + out[BLOCK_32X16 as usize] = Some(rav1e_satd_32x16_avx2); + out[BLOCK_32X64 as usize] = Some(rav1e_satd_32x64_avx2); + out[BLOCK_64X32 as usize] = Some(rav1e_satd_64x32_avx2); + out[BLOCK_64X128 as usize] = Some(rav1e_satd_64x128_avx2); + out[BLOCK_128X64 as usize] = Some(rav1e_satd_128x64_avx2); + + out[BLOCK_4X16 as usize] = Some(rav1e_satd_4x16_avx2); + out[BLOCK_16X4 as usize] = Some(rav1e_satd_16x4_avx2); + out[BLOCK_8X32 as usize] = Some(rav1e_satd_8x32_avx2); + out[BLOCK_32X8 as usize] = Some(rav1e_satd_32x8_avx2); + out[BLOCK_16X64 as usize] = Some(rav1e_satd_16x64_avx2); + out[BLOCK_64X16 as usize] = Some(rav1e_satd_64x16_avx2); + + out +}; + +cpu_function_lookup_table!( + SATD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSSE3, SSE4_1, AVX2] +); + +static SATD_HBD_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + + out[BLOCK_4X4 as usize] = Some(rav1e_satd_4x4_hbd_avx2); + out[BLOCK_8X8 as usize] = Some(rav1e_satd_8x8_hbd_avx2); + out[BLOCK_16X16 as usize] = Some(rav1e_satd_16x16_hbd_avx2); + out[BLOCK_32X32 as usize] = Some(rav1e_satd_32x32_hbd_avx2); + out[BLOCK_64X64 as usize] = Some(rav1e_satd_64x64_hbd_avx2); + out[BLOCK_128X128 as usize] = Some(rav1e_satd_128x128_hbd_avx2); + + out[BLOCK_4X8 as usize] = Some(rav1e_satd_4x8_hbd_avx2); + out[BLOCK_8X4 as usize] = Some(rav1e_satd_8x4_hbd_avx2); + out[BLOCK_8X16 as usize] = Some(rav1e_satd_8x16_hbd_avx2); + out[BLOCK_16X8 as usize] = Some(rav1e_satd_16x8_hbd_avx2); + out[BLOCK_16X32 as usize] = Some(rav1e_satd_16x32_hbd_avx2); + out[BLOCK_32X16 as usize] = Some(rav1e_satd_32x16_hbd_avx2); + out[BLOCK_32X64 as usize] = Some(rav1e_satd_32x64_hbd_avx2); + out[BLOCK_64X32 as usize] = Some(rav1e_satd_64x32_hbd_avx2); + out[BLOCK_64X128 as usize] = Some(rav1e_satd_64x128_hbd_avx2); + out[BLOCK_128X64 as usize] = Some(rav1e_satd_128x64_hbd_avx2); + + out[BLOCK_4X16 as usize] = Some(rav1e_satd_4x16_hbd_avx2); + out[BLOCK_16X4 as usize] = Some(rav1e_satd_16x4_hbd_avx2); + out[BLOCK_8X32 as usize] = Some(rav1e_satd_8x32_hbd_avx2); + out[BLOCK_32X8 as usize] = Some(rav1e_satd_32x8_hbd_avx2); + out[BLOCK_16X64 as usize] = Some(rav1e_satd_16x64_hbd_avx2); + out[BLOCK_64X16 as usize] = Some(rav1e_satd_64x16_hbd_avx2); + + out +}; + +cpu_function_lookup_table!( + SATD_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [AVX2] +); + +#[cfg(test)] +mod test { + use super::*; + use crate::frame::{AsRegion, Plane}; + use rand::random; + use std::str::FromStr; + + macro_rules! test_dist_fns { + ($(($W:expr, $H:expr)),*, $DIST_TY:ident, $BD:expr, $OPT:ident, $OPTLIT:tt) => { + $( + paste::item! { + #[test] + fn []() { + if CpuFeatureLevel::default() < CpuFeatureLevel::from_str($OPTLIT).unwrap() { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + if $BD > 8 { + // dynamic allocation: test + let mut src = Plane::from_slice(&[0u16; $W * $H], $W); + // dynamic allocation: test + let mut dst = Plane::from_slice(&[0u16; $W * $H], $W); + for (s, d) in src.data.iter_mut().zip(dst.data.iter_mut()) { + *s = random::() as u16 * $BD / 8; + *d = random::() as u16 * $BD / 8; + } + let result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + let rust_result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::RUST); + + assert_eq!(rust_result, result); + } else { + // dynamic allocation: test + let mut src = Plane::from_slice(&[0u8; $W * $H], $W); + // dynamic allocation: test + let mut dst = Plane::from_slice(&[0u8; $W * $H], $W); + for (s, d) in src.data.iter_mut().zip(dst.data.iter_mut()) { + *s = random::(); + *d = random::(); + } + let result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + let rust_result = [](&src.as_region(), &dst.as_region(), $W, $H, $BD, CpuFeatureLevel::RUST); + + assert_eq!(rust_result, result); + } + } + } + )* + } + } + + test_dist_fns!( + (4, 4), + (16, 16), + (8, 8), + (4, 8), + (8, 4), + (8, 16), + (16, 8), + (4, 16), + (16, 4), + (8, 32), + (32, 8), + (32, 32), + (64, 64), + (128, 128), + (16, 32), + (32, 16), + (32, 64), + (64, 32), + (64, 128), + (128, 64), + (16, 64), + (64, 16), + sad, + 10, + ssse3, + "ssse3" + ); + + test_dist_fns!( + (4, 4), + (16, 16), + (8, 8), + (4, 8), + (8, 4), + (8, 16), + (16, 8), + (4, 16), + (16, 4), + (8, 32), + (32, 8), + (32, 32), + (64, 64), + (128, 128), + (16, 32), + (32, 16), + (32, 64), + (64, 32), + (64, 128), + (128, 64), + (16, 64), + (64, 16), + sad, + 10, + avx2, + "avx2" + ); + + test_dist_fns!( + (4, 4), + (4, 8), + (4, 16), + (8, 4), + (8, 8), + (8, 16), + (8, 32), + (16, 16), + (32, 32), + (64, 64), + (128, 128), + sad, + 8, + sse2, + "sse2" + ); + + test_dist_fns!( + (16, 4), + (16, 8), + (16, 16), + (16, 32), + (16, 64), + (32, 8), + (32, 16), + (32, 32), + (32, 64), + (64, 16), + (64, 32), + (64, 64), + (64, 128), + (128, 64), + (128, 128), + sad, + 8, + avx2, + "avx2" + ); + + test_dist_fns!((8, 8), satd, 8, ssse3, "ssse3"); + + test_dist_fns!((4, 4), satd, 8, sse4, "sse4.1"); + + test_dist_fns!( + (4, 4), + (8, 8), + (16, 16), + (32, 32), + (64, 64), + (128, 128), + (4, 8), + (8, 4), + (8, 16), + (16, 8), + (16, 32), + (32, 16), + (32, 64), + (64, 32), + (64, 128), + (128, 64), + (4, 16), + (16, 4), + (8, 32), + (32, 8), + (16, 64), + (64, 16), + satd, + 8, + avx2, + "avx2" + ); + + test_dist_fns!( + (4, 4), + (8, 8), + (16, 16), + (32, 32), + (64, 64), + (128, 128), + (4, 8), + (8, 4), + (8, 16), + (16, 8), + (16, 32), + (32, 16), + (32, 64), + (64, 32), + (64, 128), + (128, 64), + (4, 16), + (16, 4), + (8, 32), + (32, 8), + (16, 64), + (64, 16), + satd, + 10, + avx2, + "avx2" + ); + + test_dist_fns!( + (4, 4), + (8, 8), + (16, 16), + (32, 32), + (64, 64), + (128, 128), + (4, 8), + (8, 4), + (8, 16), + (16, 8), + (16, 32), + (32, 16), + (32, 64), + (64, 32), + (64, 128), + (128, 64), + (4, 16), + (16, 4), + (8, 32), + (32, 8), + (16, 64), + (64, 16), + satd, + 12, + avx2, + "avx2" + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/sse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/sse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/sse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/dist/sse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,224 @@ +// Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::dist::*; +use crate::encoder::IMPORTANCE_BLOCK_SIZE; +use crate::partition::BlockSize; +use crate::rdo::DistortionScale; +use crate::tiling::PlaneRegion; +use crate::util::*; + +type WeightedSseFn = unsafe extern fn( + src: *const u8, + src_stride: isize, + dst: *const u8, + dst_stride: isize, + scale: *const u32, + scale_stride: isize, +) -> u64; + +type WeightedSseHBDFn = unsafe extern fn( + src: *const u16, + src_stride: isize, + dst: *const u16, + dst_stride: isize, + scale: *const u32, + scale_stride: isize, +) -> u64; + +macro_rules! declare_asm_sse_fn { + ($($name: ident),+) => ( + $( + extern { fn $name ( + src: *const u8, src_stride: isize, dst: *const u8, dst_stride: isize, scale: *const u32, scale_stride: isize + ) -> u64; } + )+ + ) +} + +macro_rules! declare_asm_hbd_sse_fn { + ($($name: ident),+) => ( + $( + extern { fn $name ( + src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize, scale: *const u32, scale_stride: isize + ) -> u64; } + )+ + ) +} + +declare_asm_sse_fn![ + // SSSE3 + rav1e_weighted_sse_4x4_ssse3, + rav1e_weighted_sse_4x8_ssse3, + rav1e_weighted_sse_4x16_ssse3, + rav1e_weighted_sse_8x4_ssse3, + rav1e_weighted_sse_8x8_ssse3, + rav1e_weighted_sse_8x16_ssse3, + rav1e_weighted_sse_8x32_ssse3, + // AVX2 + rav1e_weighted_sse_16x4_avx2, + rav1e_weighted_sse_16x8_avx2, + rav1e_weighted_sse_16x16_avx2, + rav1e_weighted_sse_16x32_avx2, + rav1e_weighted_sse_16x64_avx2, + rav1e_weighted_sse_32x8_avx2, + rav1e_weighted_sse_32x16_avx2, + rav1e_weighted_sse_32x32_avx2, + rav1e_weighted_sse_32x64_avx2, + rav1e_weighted_sse_64x16_avx2, + rav1e_weighted_sse_64x32_avx2, + rav1e_weighted_sse_64x64_avx2, + rav1e_weighted_sse_64x128_avx2, + rav1e_weighted_sse_128x64_avx2, + rav1e_weighted_sse_128x128_avx2 +]; + +declare_asm_hbd_sse_fn![ + // SSE2 + rav1e_weighted_sse_4x4_hbd_sse2 +]; + +/// # Panics +/// +/// - If in `check_asm` mode, panics on mismatch between native and ASM results. +#[inline(always)] +#[allow(clippy::let_and_return)] +pub fn get_weighted_sse( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, scale: &[u32], + scale_stride: usize, w: usize, h: usize, bit_depth: usize, + cpu: CpuFeatureLevel, +) -> u64 { + // Assembly breaks if imp block size changes. + assert_eq!(IMPORTANCE_BLOCK_SIZE >> 1, 4); + + let bsize_opt = BlockSize::from_width_and_height_opt(w, h); + + let call_rust = || -> u64 { + rust::get_weighted_sse(dst, src, scale, scale_stride, w, h, bit_depth, cpu) + }; + + #[cfg(feature = "check_asm")] + let ref_dist = call_rust(); + + #[inline] + const fn size_of_element(_: &[T]) -> usize { + std::mem::size_of::() + } + + let den = + DistortionScale::new(1, 1 << rust::GET_WEIGHTED_SSE_SHIFT).0 as u64; + let dist = match (bsize_opt, T::type_enum()) { + (Err(_), _) => call_rust(), + (Ok(bsize), PixelType::U8) => { + match SSE_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + ((func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + scale.as_ptr(), + (scale_stride * size_of_element(scale)) as isize, + ) + (den >> 1)) + / den + }, + None => call_rust(), + } + } + (Ok(bsize), PixelType::U16) => { + match SSE_HBD_FNS[cpu.as_index()][to_index(bsize)] { + // SAFETY: Calls Assembly code. + Some(func) => unsafe { + ((func)( + src.data_ptr() as *const _, + T::to_asm_stride(src.plane_cfg.stride), + dst.data_ptr() as *const _, + T::to_asm_stride(dst.plane_cfg.stride), + scale.as_ptr(), + (scale_stride * size_of_element(scale)) as isize, + ) + (den >> 1)) + / den + }, + None => call_rust(), + } + } + }; + + #[cfg(feature = "check_asm")] + assert_eq!( + dist, ref_dist, + "Weighted SSE {:?}: Assembly doesn't match reference code.", + bsize_opt + ); + + dist +} + +static SSE_FNS_SSSE3: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = + [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + out[BLOCK_4X4 as usize] = Some(rav1e_weighted_sse_4x4_ssse3); + out[BLOCK_4X8 as usize] = Some(rav1e_weighted_sse_4x8_ssse3); + out[BLOCK_4X16 as usize] = Some(rav1e_weighted_sse_4x16_ssse3); + out[BLOCK_8X4 as usize] = Some(rav1e_weighted_sse_8x4_ssse3); + out[BLOCK_8X8 as usize] = Some(rav1e_weighted_sse_8x8_ssse3); + out[BLOCK_8X16 as usize] = Some(rav1e_weighted_sse_8x16_ssse3); + out[BLOCK_8X32 as usize] = Some(rav1e_weighted_sse_8x32_ssse3); + + out +}; + +static SSE_FNS_AVX2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = SSE_FNS_SSSE3; + + use BlockSize::*; + out[BLOCK_16X4 as usize] = Some(rav1e_weighted_sse_16x4_avx2); + out[BLOCK_16X8 as usize] = Some(rav1e_weighted_sse_16x8_avx2); + out[BLOCK_16X16 as usize] = Some(rav1e_weighted_sse_16x16_avx2); + out[BLOCK_16X32 as usize] = Some(rav1e_weighted_sse_16x32_avx2); + out[BLOCK_16X64 as usize] = Some(rav1e_weighted_sse_16x64_avx2); + out[BLOCK_32X8 as usize] = Some(rav1e_weighted_sse_32x8_avx2); + out[BLOCK_32X16 as usize] = Some(rav1e_weighted_sse_32x16_avx2); + out[BLOCK_32X32 as usize] = Some(rav1e_weighted_sse_32x32_avx2); + out[BLOCK_32X64 as usize] = Some(rav1e_weighted_sse_32x64_avx2); + out[BLOCK_64X16 as usize] = Some(rav1e_weighted_sse_64x16_avx2); + out[BLOCK_64X32 as usize] = Some(rav1e_weighted_sse_64x32_avx2); + out[BLOCK_64X64 as usize] = Some(rav1e_weighted_sse_64x64_avx2); + out[BLOCK_64X128 as usize] = Some(rav1e_weighted_sse_64x128_avx2); + out[BLOCK_128X64 as usize] = Some(rav1e_weighted_sse_128x64_avx2); + out[BLOCK_128X128 as usize] = Some(rav1e_weighted_sse_128x128_avx2); + + out +}; + +static SSE_HBD_FNS_SSE2: [Option; DIST_FNS_LENGTH] = { + let mut out: [Option; DIST_FNS_LENGTH] = + [None; DIST_FNS_LENGTH]; + + use BlockSize::*; + out[BLOCK_4X4 as usize] = Some(rav1e_weighted_sse_4x4_hbd_sse2); + + out +}; + +cpu_function_lookup_table!( + SSE_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSSE3, AVX2] +); + +cpu_function_lookup_table!( + SSE_HBD_FNS: [[Option; DIST_FNS_LENGTH]], + default: [None; DIST_FNS_LENGTH], + [SSE2] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/ec.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/ec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/ec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/ec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,122 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::ec::rust; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +#[inline(always)] +pub fn update_cdf(cdf: &mut [u16; N], val: u32) { + if cdf.len() == 4 { + // SAFETY: Calls Assembly code, which is only valid when the length of + // `cdf` is 4. + return unsafe { + update_cdf_4_sse2(cdf, val); + }; + } + + rust::update_cdf(cdf, val); +} + +#[target_feature(enable = "sse2")] +#[inline] +unsafe fn update_cdf_4_sse2(cdf: &mut [u16], val: u32) { + let nsymbs = 4; + let rate = 5 + (cdf[nsymbs - 1] >> 4) as usize; + let count = cdf[nsymbs - 1] + (cdf[nsymbs - 1] < 32) as u16; + + // A bit of explanation of what is happening down here. First of all, let's look at the simple + // implementation: + // + // ``` + // if i as u32 >= val { + // *v -= *v >> rate; + // } else { + // *v += (32768 - *v) >> rate; + // } + // ``` + // + // We want to perform the same arithmetic operation in the two branches, therefore we can + // transform in something like: + // + // ``` + // if i as u32 >= val { + // *v -= *v >> rate; + // } else { + // *v -= -((32768 - *v) >> rate); + // } + // ``` + // + // It is possible to bring the "minus" for the second branch logically before the right shift + // using the following rule: + // -(x >> y) = (-1 - x) >> y + 1 + // So we obtain + // + // ``` + // if i as u32 >= val { + // *v -= *v >> rate; + // } else { + // *v -= (-1 - (32768 - *v)) >> rate + 1; + // } + // ``` + // + // Good. A range `0..4` can be compared against `val` in order to have a starting point to work + // in different ways on the two branches. `cmplt` returns `-1` if `lhs < rhs`, 0 otherwise. + // It is possible to use the `avg` SIMD operator, which performs `(lhs + rhs + 1) >> 1`. This is + // useful because `avg` treats numbers as unsigned, `-1 = 0xFFFF`, therefore `(0xFFFF + 0 + 1) >> + // 1 = 0x8000 = 32768`. Obviously `(0 + 0 + 1) >> 1 = 0`. + // + // Now the result of `cmplt` can be used along with the result from `avg` and the data in `cdf` + // in order to obtain the right hand side of the subtraction from `cdf`. + + let val_splat = _mm_set1_epi16(val as i16); + let indices = _mm_set_epi16(0, 0, 0, 0, 3, 2, 1, 0); + let index_lt_val = _mm_cmplt_epi16(indices, val_splat); + let k = _mm_avg_epu16(index_lt_val, _mm_setzero_si128()); + let cdf_simd = _mm_loadl_epi64(cdf.as_mut_ptr() as *const __m128i); + let k_minus_v = _mm_sub_epi16(k, cdf_simd); + let negated_if_lt_val = _mm_sub_epi16(index_lt_val, k_minus_v); + let shifted = + _mm_sra_epi16(negated_if_lt_val, _mm_set_epi32(0, 0, 0, rate as i32)); + let fixed_if_lt_val = _mm_sub_epi16(shifted, index_lt_val); + let result = _mm_sub_epi16(cdf_simd, fixed_if_lt_val); + + _mm_storel_epi64(cdf.as_mut_ptr() as *mut __m128i, result); + cdf[nsymbs - 1] = count; +} + +#[cfg(test)] +mod test { + use crate::ec::rust; + + #[test] + fn update_cdf_4_sse2() { + let mut cdf = [7296, 3819, 1616, 0]; + let mut cdf2 = [7296, 3819, 1616, 0]; + for i in 0..4 { + rust::update_cdf(&mut cdf, i); + // SAFETY: We are only testing on cdfs of size 4 + unsafe { + super::update_cdf_4_sse2(&mut cdf2, i); + } + assert_eq!(cdf, cdf2); + } + + let mut cdf = [7297, 3820, 1617, 0]; + let mut cdf2 = cdf; + for i in 0..4 { + rust::update_cdf(&mut cdf, i); + // SAFETY: We are only testing on cdfs of size 4 + unsafe { + super::update_cdf_4_sse2(&mut cdf2, i); + } + assert_eq!(cdf, cdf2); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/lrf.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/lrf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/lrf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/lrf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,646 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::PlaneSlice; +use crate::lrf::*; +use crate::util::Pixel; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::mem; + +// computes an intermediate (ab) row for stripe_w + 2 columns at row y +#[inline] +pub fn sgrproj_box_ab_r1( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, cpu: CpuFeatureLevel, +) { + // only use 8-bit AVX2 assembly when bitdepth equals 8 + if cpu >= CpuFeatureLevel::AVX2 && BD == 8 { + // SAFETY: Calls Assembly code. + return unsafe { + sgrproj_box_ab_r1_avx2::( + af, + bf, + iimg, + iimg_sq, + iimg_stride, + y, + stripe_w, + s, + ); + }; + } + + rust::sgrproj_box_ab_r1::( + af, + bf, + iimg, + iimg_sq, + iimg_stride, + y, + stripe_w, + s, + cpu, + ); +} + +// computes an intermediate (ab) row for stripe_w + 2 columns at row y +#[inline] +pub fn sgrproj_box_ab_r2( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, cpu: CpuFeatureLevel, +) { + // only use 8-bit AVX2 assembly when bitdepth equals 8 + if cpu >= CpuFeatureLevel::AVX2 && BD == 8 { + // SAFETY: Calls Assembly code. + return unsafe { + sgrproj_box_ab_r2_avx2::( + af, + bf, + iimg, + iimg_sq, + iimg_stride, + y, + stripe_w, + s, + ); + }; + } + + rust::sgrproj_box_ab_r2::( + af, + bf, + iimg, + iimg_sq, + iimg_stride, + y, + stripe_w, + s, + cpu, + ); +} + +#[inline] +pub fn sgrproj_box_f_r0( + f: &mut [u32], y: usize, w: usize, cdeffed: &PlaneSlice, + cpu: CpuFeatureLevel, +) { + if cpu >= CpuFeatureLevel::AVX2 { + // SAFETY: Calls Assembly code. + return unsafe { + sgrproj_box_f_r0_avx2(f, y, w, cdeffed); + }; + } + + rust::sgrproj_box_f_r0(f, y, w, cdeffed, cpu); +} + +#[inline] +pub fn sgrproj_box_f_r1( + af: &[&[u32]; 3], bf: &[&[u32]; 3], f: &mut [u32], y: usize, w: usize, + cdeffed: &PlaneSlice, cpu: CpuFeatureLevel, +) { + if cpu >= CpuFeatureLevel::AVX2 { + // SAFETY: Calls Assembly code. + return unsafe { + sgrproj_box_f_r1_avx2(af, bf, f, y, w, cdeffed); + }; + } + + rust::sgrproj_box_f_r1(af, bf, f, y, w, cdeffed, cpu); +} + +#[inline] +pub fn sgrproj_box_f_r2( + af: &[&[u32]; 2], bf: &[&[u32]; 2], f0: &mut [u32], f1: &mut [u32], + y: usize, w: usize, cdeffed: &PlaneSlice, cpu: CpuFeatureLevel, +) { + if cpu >= CpuFeatureLevel::AVX2 { + // SAFETY: Calls Assembly code. + return unsafe { + sgrproj_box_f_r2_avx2(af, bf, f0, f1, y, w, cdeffed); + }; + } + + rust::sgrproj_box_f_r2(af, bf, f0, f1, y, w, cdeffed, cpu); +} + +static X_BY_XPLUS1: [u32; 256] = [ + // Special case: Map 0 -> 1 (corresponding to a value of 1/256) + // instead of 0. See comments in selfguided_restoration_internal() for why + 1, 128, 171, 192, 205, 213, 219, 224, 228, 230, 233, 235, 236, 238, 239, 240, + 241, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 247, 247, 248, + 248, 248, 248, 249, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 256, +]; + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn sgrproj_box_ab_8_avx2( + r: usize, af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, x: usize, y: usize, s: u32, +) { + let bdm8 = BD - 8; + let d: usize = r * 2 + 1; + let n: i32 = (d * d) as i32; + let one_over_n = if r == 1 { 455 } else { 164 }; + + // Using an integral image, compute the sum of a square region + #[inline] + #[target_feature(enable = "avx2")] + unsafe fn get_integral_square_avx2( + iimg: &[u32], stride: usize, x: usize, y: usize, size: usize, + ) -> __m256i { + let iimg = iimg.as_ptr().add(y * stride + x); + // Cancel out overflow in iimg by using wrapping arithmetic + _mm256_sub_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(iimg as *const _), + _mm256_loadu_si256(iimg.add(size * stride + size) as *const _), + ), + _mm256_add_epi32( + _mm256_loadu_si256(iimg.add(size * stride) as *const _), + _mm256_loadu_si256(iimg.add(size) as *const _), + ), + ) + } + + let sum = get_integral_square_avx2(iimg, iimg_stride, x, y, d); + let ssq = get_integral_square_avx2(iimg_sq, iimg_stride, x, y, d); + let scaled_sum = _mm256_srlv_epi32( + _mm256_add_epi32(sum, _mm256_set1_epi32(1 << bdm8 as i32 >> 1)), + _mm256_set1_epi32(bdm8 as i32), + ); + let scaled_ssq = _mm256_srlv_epi32( + _mm256_add_epi32(ssq, _mm256_set1_epi32(1 << (2 * bdm8) as i32 >> 1)), + _mm256_set1_epi32(2 * bdm8 as i32), + ); + let p = _mm256_max_epi32( + _mm256_setzero_si256(), + _mm256_sub_epi32( + _mm256_mullo_epi32(scaled_ssq, _mm256_set1_epi32(n)), + _mm256_madd_epi16(scaled_sum, scaled_sum), + ), + ); + let z = _mm256_srli_epi32( + _mm256_add_epi32( + _mm256_mullo_epi32(p, _mm256_set1_epi32(s as i32)), + _mm256_set1_epi32(1 << SGRPROJ_MTABLE_BITS as i32 >> 1), + ), + SGRPROJ_MTABLE_BITS as i32, + ); + let a = _mm256_i32gather_epi32( + X_BY_XPLUS1.as_ptr() as *const _, + _mm256_min_epi32(z, _mm256_set1_epi32(255)), + 4, + ); + let b = _mm256_mullo_epi32( + _mm256_madd_epi16( + _mm256_sub_epi32(_mm256_set1_epi32(1 << SGRPROJ_SGR_BITS as i32), a), + sum, + ), + _mm256_set1_epi32(one_over_n), + ); + let b = _mm256_srlv_epi32( + _mm256_add_epi32( + b, + _mm256_set1_epi32(1 << SGRPROJ_RECIP_BITS as i32 >> 1), + ), + _mm256_set1_epi32(SGRPROJ_RECIP_BITS as i32), + ); + _mm256_storeu_si256(af.as_mut_ptr().add(x) as *mut _, a); + _mm256_storeu_si256(bf.as_mut_ptr().add(x) as *mut _, b); +} + +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sgrproj_box_ab_r1_avx2( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, +) { + for x in (0..stripe_w + 2).step_by(8) { + if x + 8 <= stripe_w + 2 { + sgrproj_box_ab_8_avx2::( + 1, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + x, + y, + s, + ); + } else { + // finish using scalar + rust::sgrproj_box_ab_internal::( + 1, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + x, + y, + stripe_w, + s, + ); + } + } + + #[cfg(feature = "check_asm")] + { + let mut af_ref: Vec = vec![0; stripe_w + 2]; + let mut bf_ref: Vec = vec![0; stripe_w + 2]; + rust::sgrproj_box_ab_internal::( + 1, + &mut af_ref, + &mut bf_ref, + iimg, + iimg_sq, + iimg_stride, + 0, + y, + stripe_w, + s, + ); + assert_eq!(&af[..stripe_w + 2], &af_ref[..]); + assert_eq!(&bf[..stripe_w + 2], &bf_ref[..]); + } +} + +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sgrproj_box_ab_r2_avx2( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, +) { + for x in (0..stripe_w + 2).step_by(8) { + if x + 8 <= stripe_w + 2 { + sgrproj_box_ab_8_avx2::( + 2, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + x, + y, + s, + ); + } else { + // finish using scalar + rust::sgrproj_box_ab_internal::( + 2, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + x, + y, + stripe_w, + s, + ); + } + } + + #[cfg(feature = "check_asm")] + { + let mut af_ref: Vec = vec![0; stripe_w + 2]; + let mut bf_ref: Vec = vec![0; stripe_w + 2]; + rust::sgrproj_box_ab_internal::( + 2, + &mut af_ref, + &mut bf_ref, + iimg, + iimg_sq, + iimg_stride, + 0, + y, + stripe_w, + s, + ); + assert_eq!(&af[..stripe_w + 2], &af_ref[..]); + assert_eq!(&bf[..stripe_w + 2], &bf_ref[..]); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn sgrproj_box_f_r0_8_avx2( + f: &mut [u32], x: usize, y: usize, cdeffed: &PlaneSlice, +) { + _mm256_storeu_si256( + f.as_mut_ptr().add(x) as *mut _, + _mm256_slli_epi32( + if mem::size_of::() == 1 { + _mm256_cvtepu8_epi32(_mm_loadl_epi64( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + } else { + _mm256_cvtepu16_epi32(_mm_loadu_si128( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + }, + SGRPROJ_RST_BITS as i32, + ), + ); +} + +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sgrproj_box_f_r0_avx2( + f: &mut [u32], y: usize, w: usize, cdeffed: &PlaneSlice, +) { + for x in (0..w).step_by(8) { + if x + 8 <= w { + sgrproj_box_f_r0_8_avx2(f, x, y, cdeffed); + } else { + // finish using scalar + rust::sgrproj_box_f_r0_internal(f, x, y, w, cdeffed); + } + } + + #[cfg(feature = "check_asm")] + { + let mut f_ref: Vec = vec![0; w]; + rust::sgrproj_box_f_r0_internal(&mut f_ref, 0, y, w, cdeffed); + assert_eq!(&f[..w], &f_ref[..]); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn sgrproj_box_f_r1_8_avx2( + af: &[&[u32]; 3], bf: &[&[u32]; 3], f: &mut [u32], x: usize, y: usize, + cdeffed: &PlaneSlice, +) { + let three = _mm256_set1_epi32(3); + let four = _mm256_set1_epi32(4); + let a0 = af[0].as_ptr(); + let a1 = af[1].as_ptr(); + let a2 = af[2].as_ptr(); + let b0 = bf[0].as_ptr(); + let b1 = bf[1].as_ptr(); + let b2 = bf[2].as_ptr(); + let a = _mm256_add_epi32( + _mm256_madd_epi16( + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(a0.add(x) as *const _), + _mm256_loadu_si256(a0.add(x + 2) as *const _), + ), + _mm256_add_epi32( + _mm256_loadu_si256(a2.add(x) as *const _), + _mm256_loadu_si256(a2.add(x + 2) as *const _), + ), + ), + three, + ), + _mm256_madd_epi16( + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(a1.add(x) as *const _), + _mm256_loadu_si256(a0.add(x + 1) as *const _), + ), + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(a1.add(x + 1) as *const _), + _mm256_loadu_si256(a2.add(x + 1) as *const _), + ), + _mm256_loadu_si256(a1.add(x + 2) as *const _), + ), + ), + four, + ), + ); + let b = _mm256_add_epi32( + _mm256_mullo_epi32( + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(b0.add(x) as *const _), + _mm256_loadu_si256(b0.add(x + 2) as *const _), + ), + _mm256_add_epi32( + _mm256_loadu_si256(b2.add(x) as *const _), + _mm256_loadu_si256(b2.add(x + 2) as *const _), + ), + ), + three, + ), + _mm256_mullo_epi32( + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(b1.add(x) as *const _), + _mm256_loadu_si256(b0.add(x + 1) as *const _), + ), + _mm256_add_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(b1.add(x + 1) as *const _), + _mm256_loadu_si256(b2.add(x + 1) as *const _), + ), + _mm256_loadu_si256(b1.add(x + 2) as *const _), + ), + ), + four, + ), + ); + let v = _mm256_add_epi32( + _mm256_madd_epi16( + a, + if mem::size_of::() == 1 { + _mm256_cvtepu8_epi32(_mm_loadl_epi64( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + } else { + _mm256_cvtepu16_epi32(_mm_loadu_si128( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + }, + ), + b, + ); + const SHIFT: i32 = (5 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS) as i32; + _mm256_storeu_si256( + f.as_mut_ptr().add(x) as *mut _, + _mm256_srli_epi32( + _mm256_add_epi32(v, _mm256_set1_epi32(1 << SHIFT >> 1)), + SHIFT, + ), + ); +} + +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sgrproj_box_f_r1_avx2( + af: &[&[u32]; 3], bf: &[&[u32]; 3], f: &mut [u32], y: usize, w: usize, + cdeffed: &PlaneSlice, +) { + for x in (0..w).step_by(8) { + if x + 8 <= w { + sgrproj_box_f_r1_8_avx2(af, bf, f, x, y, cdeffed); + } else { + // finish using scalar + rust::sgrproj_box_f_r1_internal(af, bf, f, x, y, w, cdeffed); + } + } + + #[cfg(feature = "check_asm")] + { + let mut f_ref: Vec = vec![0; w]; + rust::sgrproj_box_f_r1_internal(af, bf, &mut f_ref, 0, y, w, cdeffed); + assert_eq!(&f[..w], &f_ref[..]); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn sgrproj_box_f_r2_8_avx2( + af: &[&[u32]; 2], bf: &[&[u32]; 2], f0: &mut [u32], f1: &mut [u32], + x: usize, y: usize, cdeffed: &PlaneSlice, +) { + let five = _mm256_set1_epi32(5); + let six = _mm256_set1_epi32(6); + let a0 = af[0].as_ptr(); + let a2 = af[1].as_ptr(); + let b0 = bf[0].as_ptr(); + let b2 = bf[1].as_ptr(); + let a = _mm256_add_epi32( + _mm256_madd_epi16( + _mm256_add_epi32( + _mm256_loadu_si256(a0.add(x) as *const _), + _mm256_loadu_si256(a0.add(x + 2) as *const _), + ), + five, + ), + _mm256_madd_epi16(_mm256_loadu_si256(a0.add(x + 1) as *const _), six), + ); + let b = _mm256_add_epi32( + _mm256_mullo_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(b0.add(x) as *const _), + _mm256_loadu_si256(b0.add(x + 2) as *const _), + ), + five, + ), + _mm256_mullo_epi32(_mm256_loadu_si256(b0.add(x + 1) as *const _), six), + ); + let ao = _mm256_add_epi32( + _mm256_madd_epi16( + _mm256_add_epi32( + _mm256_loadu_si256(a2.add(x) as *const _), + _mm256_loadu_si256(a2.add(x + 2) as *const _), + ), + five, + ), + _mm256_madd_epi16(_mm256_loadu_si256(a2.add(x + 1) as *const _), six), + ); + let bo = _mm256_add_epi32( + _mm256_mullo_epi32( + _mm256_add_epi32( + _mm256_loadu_si256(b2.add(x) as *const _), + _mm256_loadu_si256(b2.add(x + 2) as *const _), + ), + five, + ), + _mm256_mullo_epi32(_mm256_loadu_si256(b2.add(x + 1) as *const _), six), + ); + let v = _mm256_add_epi32( + _mm256_madd_epi16( + _mm256_add_epi32(a, ao), + if mem::size_of::() == 1 { + _mm256_cvtepu8_epi32(_mm_loadl_epi64( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + } else { + _mm256_cvtepu16_epi32(_mm_loadu_si128( + cdeffed.subslice(x, y).as_ptr() as *const _ + )) + }, + ), + _mm256_add_epi32(b, bo), + ); + let vo = _mm256_add_epi32( + _mm256_madd_epi16( + ao, + if mem::size_of::() == 1 { + _mm256_cvtepu8_epi32(_mm_loadl_epi64( + cdeffed.subslice(x, y + 1).as_ptr() as *const _, + )) + } else { + _mm256_cvtepu16_epi32(_mm_loadu_si128( + cdeffed.subslice(x, y + 1).as_ptr() as *const _, + )) + }, + ), + bo, + ); + const SHIFT: i32 = (5 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS) as i32; + _mm256_storeu_si256( + f0.as_mut_ptr().add(x) as *mut _, + _mm256_srli_epi32( + _mm256_add_epi32(v, _mm256_set1_epi32(1 << SHIFT >> 1)), + SHIFT, + ), + ); + const SHIFTO: i32 = (4 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS) as i32; + _mm256_storeu_si256( + f1.as_mut_ptr().add(x) as *mut _, + _mm256_srli_epi32( + _mm256_add_epi32(vo, _mm256_set1_epi32(1 << SHIFTO >> 1)), + SHIFTO, + ), + ); +} + +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sgrproj_box_f_r2_avx2( + af: &[&[u32]; 2], bf: &[&[u32]; 2], f0: &mut [u32], f1: &mut [u32], + y: usize, w: usize, cdeffed: &PlaneSlice, +) { + for x in (0..w).step_by(8) { + if x + 8 <= w { + sgrproj_box_f_r2_8_avx2(af, bf, f0, f1, x, y, cdeffed); + } else { + // finish using scalar + rust::sgrproj_box_f_r2_internal(af, bf, f0, f1, x, y, w, cdeffed); + } + } + + #[cfg(feature = "check_asm")] + { + let mut f0_ref: Vec = vec![0; w]; + let mut f1_ref: Vec = vec![0; w]; + rust::sgrproj_box_f_r2_internal( + af, + bf, + &mut f0_ref, + &mut f1_ref, + 0, + y, + w, + cdeffed, + ); + assert_eq!(&f0[..w], &f0_ref[..]); + assert_eq!(&f1[..w], &f1_ref[..]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/mc.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/mc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,833 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::*; +use crate::mc::FilterMode::*; +use crate::mc::*; +use crate::tiling::*; +use crate::util::*; + +type PutFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PutHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +type PrepFn = unsafe extern fn( + tmp: *mut i16, + src: *const u8, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, +); + +type PrepHBDFn = unsafe extern fn( + tmp: *mut i16, + src: *const u16, + src_stride: isize, + width: i32, + height: i32, + col_frac: i32, + row_frac: i32, + bitdepth_max: i32, +); + +type AvgFn = unsafe extern fn( + dst: *mut u8, + dst_stride: isize, + tmp1: *const i16, + tmp2: *const i16, + width: i32, + height: i32, +); + +type AvgHBDFn = unsafe extern fn( + dst: *mut u16, + dst_stride: isize, + tmp1: *const i16, + tmp2: *const i16, + width: i32, + height: i32, + bitdepth_max: i32, +); + +// gets an index that can be mapped to a function for a pair of filter modes +#[inline] +const fn get_2d_mode_idx(mode_x: FilterMode, mode_y: FilterMode) -> usize { + (mode_x as usize + 4 * (mode_y as usize)) & 15 +} + +/// # Panics +/// +/// - If `width` is not a power of 2 +/// - If `width` is not between 2 and 128 +/// - If `height` is odd +/// - If `width * height` is greater than the length of `tmp1` or `tmp2` +/// - If `width` and `height` do not fit within the bounds of `src` +#[inline(always)] +pub fn put_8tap( + dst: &mut PlaneRegionMut<'_, T>, src: PlaneSlice<'_, T>, width: usize, + height: usize, col_frac: i32, row_frac: i32, mode_x: FilterMode, + mode_y: FilterMode, bit_depth: usize, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::put_8tap( + dst, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth, + cpu, + ); + }; + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + unsafe { + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + + match T::type_enum() { + PixelType::U8 => { + match PUT_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(dst), + } + } + PixelType::U16 => { + match PUT_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + } + } + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } +} + +/// # Panics +/// +/// - If `width` is not a power of 2 +/// - If `width` is not between 2 and 128 +/// - If `height` is odd +/// - If `width * height` is greater than the length of `tmp1` or `tmp2` +/// - If `width` and `height` do not fit within the bounds of `src` +#[inline(always)] +pub fn prep_8tap( + tmp: &mut [i16], src: PlaneSlice<'_, T>, width: usize, height: usize, + col_frac: i32, row_frac: i32, mode_x: FilterMode, mode_y: FilterMode, + bit_depth: usize, cpu: CpuFeatureLevel, +) { + let call_rust = |tmp: &mut [i16]| { + rust::prep_8tap( + tmp, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth, + cpu, + ); + }; + #[cfg(feature = "check_asm")] + let ref_tmp = { + let mut copy = vec![0; width * height]; + copy[..].copy_from_slice(&tmp[..width * height]); + call_rust(&mut copy); + copy + }; + + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + unsafe { + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check length of tmp + assert!(tmp.len() >= width * height); + + // SAFETY: Check bounds of src + assert!(src.accessible(width + 4, height + 4)); + assert!(src.accessible_neg(3, 3)); + + match T::type_enum() { + PixelType::U8 => { + match PREP_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + tmp.as_mut_ptr(), + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + ), + None => call_rust(tmp), + } + } + PixelType::U16 if bit_depth > 8 => { + match PREP_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] { + Some(func) => (func)( + tmp.as_mut_ptr() as *mut _, + src.as_ptr() as *const _, + T::to_asm_stride(src.plane.cfg.stride), + width as i32, + height as i32, + col_frac, + row_frac, + (1 << bit_depth) - 1, + ), + None => call_rust(tmp), + } + } + _ => call_rust(tmp), + } + } + #[cfg(feature = "check_asm")] + { + assert_eq!(&tmp[..width * height], &ref_tmp[..]); + } +} + +/// # Panics +/// +/// - If `width` is not a power of 2 +/// - If `width` is not between 2 and 128 +/// - If `width * height` is greater than the length of `tmp1` or `tmp2` +/// - If `width` and `height` do not fit within the bounds of `dst` +pub fn mc_avg( + dst: &mut PlaneRegionMut<'_, T>, tmp1: &[i16], tmp2: &[i16], width: usize, + height: usize, bit_depth: usize, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::mc_avg(dst, tmp1, tmp2, width, height, bit_depth, cpu); + }; + #[cfg(feature = "check_asm")] + let ref_dst = { + let mut copy = dst.scratch_copy(); + call_rust(&mut copy.as_region_mut()); + copy + }; + + // SAFETY: The assembly only supports even heights and valid uncropped + // widths + unsafe { + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + // SAFETY: Check bounds of dst + assert!(dst.rect().width >= width && dst.rect().height >= height); + + // SAFETY: Check length of tmp1 & tmp2 + assert!(tmp1.len() >= width * height); + assert!(tmp2.len() >= width * height); + + match T::type_enum() { + PixelType::U8 => match AVG_FNS[cpu.as_index()] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + tmp1.as_ptr(), + tmp2.as_ptr(), + width as i32, + height as i32, + ), + None => call_rust(dst), + }, + PixelType::U16 if bit_depth > 8 => match AVG_HBD_FNS[cpu.as_index()] { + Some(func) => (func)( + dst.data_ptr_mut() as *mut _, + T::to_asm_stride(dst.plane_cfg.stride), + tmp1.as_ptr(), + tmp2.as_ptr(), + width as i32, + height as i32, + (1 << bit_depth) - 1, + ), + None => call_rust(dst), + }, + _ => call_rust(dst), + } + } + #[cfg(feature = "check_asm")] + { + for (dst_row, ref_row) in + dst.rows_iter().zip(ref_dst.as_region().rows_iter()) + { + for (dst, reference) in dst_row.iter().zip(ref_row) { + assert_eq!(*dst, *reference); + } + } + } +} + +macro_rules! decl_mc_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + paste::item! { + extern { + $( + fn [<$func_name _ssse3>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx2>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx512icl>]( + dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32 + ); + )* + } + + static PUT_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PUT_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + + static PUT_FNS_AVX512ICL: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx512icl>]); + )* + out + }; + } + } +} + +decl_mc_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular_8bpc), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_8bpc), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_8bpc), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_8bpc), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_8bpc), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_8bpc), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_8bpc), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_8bpc), + (SHARP, SHARP, rav1e_put_8tap_sharp_8bpc), + (BILINEAR, BILINEAR, rav1e_put_bilin_8bpc) +); + +cpu_function_lookup_table!( + PUT_FNS: [[Option; 16]], + default: [None; 16], + [SSSE3, AVX2, AVX512ICL] +); + +macro_rules! decl_mc_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + paste::item! { + extern { + $( + fn [<$func_name _ssse3>]( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + + fn [<$func_name _avx2>]( + dst: *mut u16, dst_stride: isize, src: *const u16, src_stride: isize, + w: i32, h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PUT_HBD_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PUT_HBD_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + } + } +} + +decl_mc_hbd_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular_16bpc), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_16bpc), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_16bpc), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_16bpc), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_16bpc), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_16bpc), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_16bpc), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_16bpc), + (SHARP, SHARP, rav1e_put_8tap_sharp_16bpc), + (BILINEAR, BILINEAR, rav1e_put_bilin_16bpc) +); + +cpu_function_lookup_table!( + PUT_HBD_FNS: [[Option; 16]], + default: [None; 16], + [SSSE3, AVX2] +); + +macro_rules! decl_mct_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + paste::item! { + extern { + $( + fn [<$func_name _sse2>]( + tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _ssse3>]( + tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx2>]( + tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32 + ); + + fn [<$func_name _avx512icl>]( + tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32 + ); + )* + } + + static PREP_FNS_SSE2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _sse2>]); + )* + out + }; + + static PREP_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PREP_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + + static PREP_FNS_AVX512ICL: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx512icl>]); + )* + out + }; + } + } +} + +decl_mct_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular_8bpc), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_8bpc), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_8bpc), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_8bpc), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_8bpc), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_8bpc), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_8bpc), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_8bpc), + (SHARP, SHARP, rav1e_prep_8tap_sharp_8bpc), + (BILINEAR, BILINEAR, rav1e_prep_bilin_8bpc) +); + +cpu_function_lookup_table!( + PREP_FNS: [[Option; 16]], + default: [None; 16], + [SSE2, SSSE3, AVX2, AVX512ICL] +); + +macro_rules! decl_mct_hbd_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => { + paste::item! { + extern { + $( + fn [<$func_name _ssse3>]( + tmp: *mut i16, src: *const u16, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + + fn [<$func_name _avx2>]( + tmp: *mut i16, src: *const u16, src_stride: libc::ptrdiff_t, w: i32, + h: i32, mx: i32, my: i32, bitdepth_max: i32, + ); + )* + } + + static PREP_HBD_FNS_SSSE3: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _ssse3>]); + )* + out + }; + + static PREP_HBD_FNS_AVX2: [Option; 16] = { + let mut out: [Option; 16] = [None; 16]; + $( + out[get_2d_mode_idx($mode_x, $mode_y)] = Some([<$func_name _avx2>]); + )* + out + }; + } + } +} + +decl_mct_hbd_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular_16bpc), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_16bpc), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_16bpc), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_16bpc), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_16bpc), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_16bpc), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_16bpc), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_16bpc), + (SHARP, SHARP, rav1e_prep_8tap_sharp_16bpc), + (BILINEAR, BILINEAR, rav1e_prep_bilin_16bpc) +); + +cpu_function_lookup_table!( + PREP_HBD_FNS: [[Option; 16]], + default: [None; 16], + [SSSE3, AVX2] +); + +extern { + fn rav1e_avg_8bpc_ssse3( + dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, + ); + + fn rav1e_avg_8bpc_avx2( + dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, + ); + + fn rav1e_avg_8bpc_avx512icl( + dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, + ); + + fn rav1e_avg_16bpc_ssse3( + dst: *mut u16, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, bitdepth_max: i32, + ); + + fn rav1e_avg_16bpc_avx2( + dst: *mut u16, dst_stride: libc::ptrdiff_t, tmp1: *const i16, + tmp2: *const i16, w: i32, h: i32, bitdepth_max: i32, + ); +} + +cpu_function_lookup_table!( + AVG_FNS: [Option], + default: None, + [ + (SSSE3, Some(rav1e_avg_8bpc_ssse3)), + (AVX2, Some(rav1e_avg_8bpc_avx2)), + (AVX512ICL, Some(rav1e_avg_8bpc_avx512icl)) + ] +); + +cpu_function_lookup_table!( + AVG_HBD_FNS: [Option], + default: None, + [(SSSE3, Some(rav1e_avg_16bpc_ssse3)), (AVX2, Some(rav1e_avg_16bpc_avx2))] +); + +#[cfg(test)] +mod test { + use super::*; + use rand::random; + use std::str::FromStr; + + macro_rules! test_put_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),*, $OPT:ident, $OPTLIT:tt, $BD:expr) => { + $( + paste::item! { + #[test] + fn []() { + if CpuFeatureLevel::default() < CpuFeatureLevel::from_str($OPTLIT).unwrap() { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + let test_mvs = [MotionVector { row: 0, col: 0 }, MotionVector { row: 4, col: 0 }, MotionVector { row: 0, col: 4 }, MotionVector { row: 4, col: 4 }]; + if $BD > 8 { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u16; 64 * 64], 64); + for s in src.data.iter_mut() { + *s = random::() as u16 * $BD / 8; + } + // dynamic allocation: test + let mut dst1 = Plane::from_slice(&vec![0u16; 64 * 64], 64); + // dynamic allocation: test + let mut dst2 = Plane::from_slice(&vec![0u16; 64 * 64], 64); + + for mv in &test_mvs { + let (row_frac, col_frac, src) = get_params(&src, PlaneOffset { x: 0, y: 0 }, *mv); + super::put_8tap(&mut dst1.as_region_mut(), src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + super::put_8tap(&mut dst2.as_region_mut(), src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::RUST); + + assert_eq!(&*dst1.data, &*dst2.data); + } + } else { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u8; 64 * 64], 64); + for s in src.data.iter_mut() { + *s = random::(); + } + // dynamic allocation: test + let mut dst1 = Plane::from_slice(&vec![0u8; 64 * 64], 64); + // dynamic allocation: test + let mut dst2 = Plane::from_slice(&vec![0u8; 64 * 64], 64); + + for mv in &test_mvs { + let (row_frac, col_frac, src) = get_params(&src, PlaneOffset { x: 0, y: 0 }, *mv); + super::put_8tap(&mut dst1.as_region_mut(), src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + super::put_8tap(&mut dst2.as_region_mut(), src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::RUST); + + assert_eq!(&*dst1.data, &*dst2.data); + } + }; + } + } + )* + } + } + + test_put_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth), + (SHARP, SHARP, rav1e_put_8tap_sharp), + (BILINEAR, BILINEAR, rav1e_put_bilin), + ssse3, + "ssse3", + 8 + ); + + test_put_fns!( + (REGULAR, REGULAR, rav1e_put_8tap_regular), + (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth), + (REGULAR, SHARP, rav1e_put_8tap_regular_sharp), + (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular), + (SMOOTH, SMOOTH, rav1e_put_8tap_smooth), + (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp), + (SHARP, REGULAR, rav1e_put_8tap_sharp_regular), + (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth), + (SHARP, SHARP, rav1e_put_8tap_sharp), + (BILINEAR, BILINEAR, rav1e_put_bilin), + avx2, + "avx2", + 8 + ); + + macro_rules! test_prep_fns { + ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),*, $OPT:ident, $OPTLIT:tt, $BD:expr) => { + $( + paste::item! { + #[test] + fn []() { + if CpuFeatureLevel::default() < CpuFeatureLevel::from_str($OPTLIT).unwrap() { + eprintln!("Ignoring {} test, not supported on this machine!", $OPTLIT); + return; + } + + // dynamic allocation: test + let mut dst1 = Aligned::new([0i16; 128 * 128]); + // dynamic allocation: test + let mut dst2 = Aligned::new([0i16; 128 * 128]); + let test_mvs = [MotionVector { row: 0, col: 0 }, MotionVector { row: 4, col: 0 }, MotionVector { row: 0, col: 4 }, MotionVector { row: 4, col: 4 }]; + + if $BD > 8 { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u16; 64 * 64], 64); + for s in src.data.iter_mut() { + *s = random::() as u16 * $BD / 8; + } + + for mv in &test_mvs { + let (row_frac, col_frac, src) = get_params(&src, PlaneOffset { x: 0, y: 0 }, *mv); + super::prep_8tap(&mut dst1.data, src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + super::prep_8tap(&mut dst2.data, src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::RUST); + } + } else { + // dynamic allocation: test + let mut src = Plane::from_slice(&vec![0u8; 64 * 64], 64); + for s in src.data.iter_mut() { + *s = random::(); + } + + for mv in &test_mvs { + let (row_frac, col_frac, src) = get_params(&src, PlaneOffset { x: 0, y: 0 }, *mv); + super::prep_8tap(&mut dst1.data, src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::from_str($OPTLIT).unwrap()); + super::prep_8tap(&mut dst2.data, src, 8, 8, col_frac, row_frac, $mode_x, $mode_y, 8, CpuFeatureLevel::RUST); + } + }; + + assert_eq!(&dst1.data.to_vec(), &dst2.data.to_vec()); + } + } + )* + } + } + + test_prep_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth), + (SHARP, SHARP, rav1e_prep_8tap_sharp), + (BILINEAR, BILINEAR, rav1e_prep_bilin), + ssse3, + "ssse3", + 8 + ); + + test_prep_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth), + (SHARP, SHARP, rav1e_prep_8tap_sharp), + (BILINEAR, BILINEAR, rav1e_prep_bilin), + avx2, + "avx2", + 8 + ); + + test_prep_fns!( + (REGULAR, REGULAR, rav1e_prep_8tap_regular), + (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth), + (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp), + (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular), + (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth), + (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp), + (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular), + (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth), + (SHARP, SHARP, rav1e_prep_8tap_sharp), + (BILINEAR, BILINEAR, rav1e_prep_bilin), + avx512icl, + "avx512vpclmulqdq", + 8 + ); + + fn get_params( + rec_plane: &Plane, po: PlaneOffset, mv: MotionVector, + ) -> (i32, i32, PlaneSlice) { + let rec_cfg = &rec_plane.cfg; + let shift_row = 3 + rec_cfg.ydec; + let shift_col = 3 + rec_cfg.xdec; + let row_offset = mv.row as i32 >> shift_row; + let col_offset = mv.col as i32 >> shift_col; + let row_frac = + (mv.row as i32 - (row_offset << shift_row)) << (4 - shift_row); + let col_frac = + (mv.col as i32 - (col_offset << shift_col)) << (4 - shift_col); + let qo = PlaneOffset { + x: po.x + col_offset as isize - 3, + y: po.y + row_offset as isize - 3, + }; + (row_frac, col_frac, rec_plane.slice(qo).clamp().subslice(3, 3)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod cdef; +pub mod dist; +pub mod ec; +pub mod lrf; +pub mod mc; +pub mod predict; +pub mod quantize; +pub mod transform; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/predict.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/predict.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/predict.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/predict.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,928 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::partition::{BlockSize, IntraEdge}; +use crate::predict::{ + rust, IntraEdgeFilterParameters, PredictionMode, PredictionVariant, +}; +use crate::tiling::{PlaneRegion, PlaneRegionMut}; +use crate::transform::TxSize; +use crate::Pixel; +use std::mem::MaybeUninit; +use v_frame::pixel::PixelType; + +macro_rules! decl_angular_ipred_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + ); + )* + } + }; +} + +decl_angular_ipred_fn! { + rav1e_ipred_h_8bpc_ssse3, + rav1e_ipred_h_8bpc_avx2, + rav1e_ipred_h_8bpc_avx512icl, + rav1e_ipred_v_8bpc_ssse3, + rav1e_ipred_v_8bpc_avx2, + rav1e_ipred_v_8bpc_avx512icl, + rav1e_ipred_dc_8bpc_ssse3, + rav1e_ipred_dc_8bpc_avx2, + rav1e_ipred_dc_8bpc_avx512icl, + rav1e_ipred_dc_left_8bpc_ssse3, + rav1e_ipred_dc_left_8bpc_avx2, + rav1e_ipred_dc_left_8bpc_avx512icl, + rav1e_ipred_dc_128_8bpc_ssse3, + rav1e_ipred_dc_128_8bpc_avx2, + rav1e_ipred_dc_128_8bpc_avx512icl, + rav1e_ipred_dc_top_8bpc_ssse3, + rav1e_ipred_dc_top_8bpc_avx2, + rav1e_ipred_dc_top_8bpc_avx512icl, + rav1e_ipred_smooth_v_8bpc_ssse3, + rav1e_ipred_smooth_v_8bpc_avx2, + rav1e_ipred_smooth_v_8bpc_avx512icl, + rav1e_ipred_smooth_h_8bpc_ssse3, + rav1e_ipred_smooth_h_8bpc_avx2, + rav1e_ipred_smooth_h_8bpc_avx512icl, + rav1e_ipred_smooth_8bpc_ssse3, + rav1e_ipred_smooth_8bpc_avx2, + rav1e_ipred_smooth_8bpc_avx512icl, + rav1e_ipred_z1_8bpc_ssse3, + rav1e_ipred_z1_8bpc_avx2, + rav1e_ipred_z3_8bpc_ssse3, + rav1e_ipred_z3_8bpc_avx2, + rav1e_ipred_paeth_8bpc_ssse3, + rav1e_ipred_paeth_8bpc_avx2, + rav1e_ipred_paeth_8bpc_avx512icl +} + +macro_rules! decl_angular_ipred_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + max_width: libc::c_int, max_height: libc::c_int, + bit_depth_max: libc::c_int, + ); + )* + } + }; +} + +decl_angular_ipred_hbd_fn! { + rav1e_ipred_h_16bpc_ssse3, + rav1e_ipred_h_16bpc_avx2, + rav1e_ipred_v_16bpc_ssse3, + rav1e_ipred_v_16bpc_avx2, + rav1e_ipred_dc_16bpc_ssse3, + rav1e_ipred_dc_16bpc_avx2, + rav1e_ipred_dc_left_16bpc_ssse3, + rav1e_ipred_dc_left_16bpc_avx2, + rav1e_ipred_dc_128_16bpc_ssse3, + rav1e_ipred_dc_128_16bpc_avx2, + rav1e_ipred_dc_top_16bpc_ssse3, + rav1e_ipred_dc_top_16bpc_avx2, + rav1e_ipred_smooth_v_16bpc_ssse3, + rav1e_ipred_smooth_v_16bpc_avx2, + rav1e_ipred_smooth_v_16bpc_avx512icl, + rav1e_ipred_smooth_h_16bpc_ssse3, + rav1e_ipred_smooth_h_16bpc_avx2, + rav1e_ipred_smooth_h_16bpc_avx512icl, + rav1e_ipred_smooth_16bpc_ssse3, + rav1e_ipred_smooth_16bpc_avx2, + rav1e_ipred_smooth_16bpc_avx512icl, + rav1e_ipred_z1_16bpc_ssse3, + rav1e_ipred_z1_16bpc_avx2, + rav1e_ipred_z2_16bpc_ssse3, + rav1e_ipred_z3_16bpc_ssse3, + rav1e_ipred_z3_16bpc_avx2, + rav1e_ipred_paeth_16bpc_ssse3, + rav1e_ipred_paeth_16bpc_avx2, + rav1e_ipred_paeth_16bpc_avx512icl +} + +// For z2 prediction, we need to provide extra parameters, dx and dy, which indicate +// the distance between the predicted block's top-left pixel and the frame's edge. +// It is required for the intra edge filtering process. +extern { + + fn rav1e_ipred_z2_8bpc_ssse3( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + dx: libc::c_int, dy: libc::c_int, + ); + + fn rav1e_ipred_z2_8bpc_avx2( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + dx: libc::c_int, dy: libc::c_int, + ); + + fn rav1e_ipred_z2_16bpc_avx2( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, angle: libc::c_int, + dx: libc::c_int, dy: libc::c_int, bit_depth_max: libc::c_int, + ); +} + +macro_rules! decl_cfl_ac_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + ac: *mut MaybeUninit, src: *const u8, stride: libc::ptrdiff_t, + w_pad: libc::c_int, h_pad: libc::c_int, + width: libc::c_int, height: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_ac_fn! { + rav1e_ipred_cfl_ac_420_8bpc_avx2, + rav1e_ipred_cfl_ac_420_8bpc_ssse3, + rav1e_ipred_cfl_ac_422_8bpc_avx2, + rav1e_ipred_cfl_ac_422_8bpc_ssse3, + rav1e_ipred_cfl_ac_444_8bpc_avx2, + rav1e_ipred_cfl_ac_444_8bpc_ssse3 +} + +macro_rules! decl_cfl_ac_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + ac: *mut MaybeUninit, src: *const u16, stride: libc::ptrdiff_t, + w_pad: libc::c_int, h_pad: libc::c_int, + width: libc::c_int, height: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_ac_hbd_fn! { + rav1e_ipred_cfl_ac_420_16bpc_ssse3, + rav1e_ipred_cfl_ac_420_16bpc_avx2, + rav1e_ipred_cfl_ac_422_16bpc_ssse3, + rav1e_ipred_cfl_ac_422_16bpc_avx2, + rav1e_ipred_cfl_ac_444_16bpc_ssse3, + rav1e_ipred_cfl_ac_444_16bpc_avx2 +} + +macro_rules! decl_cfl_pred_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8, + width: libc::c_int, height: libc::c_int, ac: *const i16, + alpha: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_pred_fn! { + rav1e_ipred_cfl_8bpc_ssse3, + rav1e_ipred_cfl_8bpc_avx2, + rav1e_ipred_cfl_left_8bpc_ssse3, + rav1e_ipred_cfl_left_8bpc_avx2, + rav1e_ipred_cfl_top_8bpc_ssse3, + rav1e_ipred_cfl_top_8bpc_avx2, + rav1e_ipred_cfl_128_8bpc_ssse3, + rav1e_ipred_cfl_128_8bpc_avx2 +} + +macro_rules! decl_cfl_pred_hbd_fn { + ($($f:ident),+) => { + extern { + $( + fn $f( + dst: *mut u16, stride: libc::ptrdiff_t, topleft: *const u16, + width: libc::c_int, height: libc::c_int, ac: *const i16, + alpha: libc::c_int, bit_depth_max: libc::c_int, + ); + )* + } + }; +} + +decl_cfl_pred_hbd_fn! { + rav1e_ipred_cfl_16bpc_ssse3, + rav1e_ipred_cfl_16bpc_avx2, + rav1e_ipred_cfl_128_16bpc_ssse3, + rav1e_ipred_cfl_128_16bpc_avx2, + rav1e_ipred_cfl_left_16bpc_ssse3, + rav1e_ipred_cfl_left_16bpc_avx2, + rav1e_ipred_cfl_top_16bpc_ssse3, + rav1e_ipred_cfl_top_16bpc_avx2 +} + +#[inline(always)] +pub fn dispatch_predict_intra( + mode: PredictionMode, variant: PredictionVariant, + dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize, + ac: &[i16], angle: isize, ief_params: Option, + edge_buf: &IntraEdge, cpu: CpuFeatureLevel, +) { + let call_rust = |dst: &mut PlaneRegionMut<'_, T>| { + rust::dispatch_predict_intra( + mode, variant, dst, tx_size, bit_depth, ac, angle, ief_params, edge_buf, + cpu, + ); + }; + + // SAFETY: Calls Assembly code. + unsafe { + let stride = T::to_asm_stride(dst.plane_cfg.stride) as libc::ptrdiff_t; + let w = tx_size.width() as libc::c_int; + let h = tx_size.height() as libc::c_int; + let angle = angle as libc::c_int; + + match T::type_enum() { + PixelType::U8 => { + let dst_ptr = dst.data_ptr_mut() as *mut _; + let edge_ptr = edge_buf.top_left_ptr() as *const _; + if cpu >= CpuFeatureLevel::AVX512ICL { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_8bpc_avx512icl, + PredictionVariant::LEFT => rav1e_ipred_dc_left_8bpc_avx512icl, + PredictionVariant::TOP => rav1e_ipred_dc_top_8bpc_avx512icl, + PredictionVariant::BOTH => rav1e_ipred_dc_8bpc_avx512icl, + })(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } else if angle < 180 { + rav1e_ipred_z2_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, + ); + } else { + rav1e_ipred_z3_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_8bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_8bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_8bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_cfl_top_8bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_cfl_8bpc_avx2, + })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle); + } + _ => call_rust(dst), + } + } else if cpu >= CpuFeatureLevel::AVX2 { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_8bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_dc_left_8bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_dc_top_8bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_dc_8bpc_avx2, + })(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_8bpc_avx2(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_8bpc_avx2(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } else if angle < 180 { + rav1e_ipred_z2_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, + ); + } else { + rav1e_ipred_z3_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_8bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_8bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_8bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_cfl_top_8bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_cfl_8bpc_avx2, + })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle); + } + _ => call_rust(dst), + } + } else if cpu >= CpuFeatureLevel::SSSE3 { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_8bpc_ssse3, + PredictionVariant::LEFT => rav1e_ipred_dc_left_8bpc_ssse3, + PredictionVariant::TOP => rav1e_ipred_dc_top_8bpc_ssse3, + PredictionVariant::BOTH => rav1e_ipred_dc_8bpc_ssse3, + })(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_8bpc_ssse3(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_8bpc_ssse3(dst_ptr, stride, edge_ptr, w, h, angle); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } else if angle < 180 { + rav1e_ipred_z2_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, + ); + } else { + rav1e_ipred_z3_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_8bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_8bpc_ssse3, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_8bpc_ssse3, + PredictionVariant::TOP => rav1e_ipred_cfl_top_8bpc_ssse3, + PredictionVariant::BOTH => rav1e_ipred_cfl_8bpc_ssse3, + })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle); + } + _ => call_rust(dst), + } + } else { + call_rust(dst) + } + } + PixelType::U16 => { + let dst_ptr = dst.data_ptr_mut() as *mut _; + let edge_ptr = edge_buf.top_left_ptr() as *const _; + let bd_max = (1 << bit_depth) - 1; + if cpu >= CpuFeatureLevel::AVX512ICL { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_16bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_dc_left_16bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_dc_top_16bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_dc_16bpc_avx2, + })( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max + ); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } else if angle < 180 { + rav1e_ipred_z2_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, bd_max, + ); + } else { + rav1e_ipred_z3_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_16bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_16bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_16bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_16bpc_avx512icl( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_16bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_16bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_cfl_top_16bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_cfl_16bpc_avx2, + })( + dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle, bd_max + ); + } + _ => call_rust(dst), + } + } else if cpu >= CpuFeatureLevel::AVX2 { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_16bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_dc_left_16bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_dc_top_16bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_dc_16bpc_avx2, + })( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max + ); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } else if angle < 180 { + rav1e_ipred_z2_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, bd_max, + ); + } else { + rav1e_ipred_z3_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_16bpc_avx2( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_16bpc_avx2, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_16bpc_avx2, + PredictionVariant::TOP => rav1e_ipred_cfl_top_16bpc_avx2, + PredictionVariant::BOTH => rav1e_ipred_cfl_16bpc_avx2, + })( + dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle, bd_max + ); + } + _ => call_rust(dst), + } + } else if cpu >= CpuFeatureLevel::SSSE3 { + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => rav1e_ipred_dc_128_16bpc_ssse3, + PredictionVariant::LEFT => rav1e_ipred_dc_left_16bpc_ssse3, + PredictionVariant::TOP => rav1e_ipred_dc_top_16bpc_ssse3, + PredictionVariant::BOTH => rav1e_ipred_dc_16bpc_ssse3, + })( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max + ); + } + PredictionMode::V_PRED if angle == 90 => { + rav1e_ipred_v_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::H_PRED if angle == 180 => { + rav1e_ipred_h_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => { + let (enable_ief, ief_smooth_filter) = + if let Some(params) = ief_params { + ( + true as libc::c_int, + params.use_smooth_filter() as libc::c_int, + ) + } else { + (false as libc::c_int, false as libc::c_int) + }; + + // dav1d assembly uses the unused integer bits to hold IEF parameters + let angle_arg = + angle | (enable_ief << 10) | (ief_smooth_filter << 9); + + // From dav1d, bw and bh are the frame width and height rounded to 8px units + let (bw, bh) = ( + ((dst.plane_cfg.width + 7) >> 3) << 3, + ((dst.plane_cfg.height + 7) >> 3) << 3, + ); + // From dav1d, dx and dy are the distance from the predicted block to the frame edge + let (dx, dy) = ( + (bw as isize - dst.rect().x) as libc::c_int, + (bh as isize - dst.rect().y) as libc::c_int, + ); + + if angle <= 90 { + rav1e_ipred_z1_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } else if angle < 180 { + rav1e_ipred_z2_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, dx, dy, bd_max, + ); + } else { + rav1e_ipred_z3_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle_arg, 0, 0, bd_max, + ); + } + } + PredictionMode::SMOOTH_PRED => { + rav1e_ipred_smooth_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_V_PRED => { + rav1e_ipred_smooth_v_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::SMOOTH_H_PRED => { + rav1e_ipred_smooth_h_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::PAETH_PRED => { + rav1e_ipred_paeth_16bpc_ssse3( + dst_ptr, stride, edge_ptr, w, h, angle, 0, 0, bd_max, + ); + } + PredictionMode::UV_CFL_PRED => { + let ac_ptr = ac.as_ptr() as *const _; + (match variant { + PredictionVariant::NONE => rav1e_ipred_cfl_128_16bpc_ssse3, + PredictionVariant::LEFT => rav1e_ipred_cfl_left_16bpc_ssse3, + PredictionVariant::TOP => rav1e_ipred_cfl_top_16bpc_ssse3, + PredictionVariant::BOTH => rav1e_ipred_cfl_16bpc_ssse3, + })( + dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle, bd_max + ); + } + _ => call_rust(dst), + } + } else { + call_rust(dst) + } + } + } + } +} + +// The implementation MUST inititialize all `ac` elements +#[inline(always)] +pub(crate) fn pred_cfl_ac( + ac: &mut [MaybeUninit], luma: &PlaneRegion<'_, T>, bsize: BlockSize, + w_pad: usize, h_pad: usize, cpu: CpuFeatureLevel, +) { + debug_assert_eq!(ac.len(), bsize.area()); + + let call_rust = |ac: &mut [MaybeUninit]| { + rust::pred_cfl_ac::(ac, luma, bsize, w_pad, h_pad, cpu); + }; + + let stride = T::to_asm_stride(luma.plane_cfg.stride) as libc::ptrdiff_t; + let w = bsize.width() as libc::c_int; + let h = bsize.height() as libc::c_int; + let w_pad = w_pad as libc::c_int; + let h_pad = h_pad as libc::c_int; + + // SAFETY: Calls Assembly code. + unsafe { + let ac_ptr = ac.as_mut_ptr(); + match T::type_enum() { + PixelType::U8 if cpu >= CpuFeatureLevel::SSSE3 => { + let luma_ptr = luma.data_ptr() as *const u8; + (if cpu >= CpuFeatureLevel::AVX2 { + match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_8bpc_avx2, + (1, 0) => rav1e_ipred_cfl_ac_422_8bpc_avx2, + _ => rav1e_ipred_cfl_ac_420_8bpc_avx2, + } + } else { + match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_8bpc_ssse3, + (1, 0) => rav1e_ipred_cfl_ac_422_8bpc_ssse3, + _ => rav1e_ipred_cfl_ac_420_8bpc_ssse3, + } + })(ac_ptr, luma_ptr, stride, w_pad, h_pad, w, h) + } + PixelType::U16 if cpu >= CpuFeatureLevel::SSSE3 => { + let luma_ptr = luma.data_ptr() as *const u16; + (if cpu >= CpuFeatureLevel::AVX2 { + match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_16bpc_avx2, + (1, 0) => rav1e_ipred_cfl_ac_422_16bpc_avx2, + _ => rav1e_ipred_cfl_ac_420_16bpc_avx2, + } + } else { + match (XDEC, YDEC) { + (0, 0) => rav1e_ipred_cfl_ac_444_16bpc_ssse3, + (1, 0) => rav1e_ipred_cfl_ac_422_16bpc_ssse3, + _ => rav1e_ipred_cfl_ac_420_16bpc_ssse3, + } + })(ac_ptr, luma_ptr, stride, w_pad, h_pad, w, h) + } + _ => call_rust(ac), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/quantize.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/quantize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/quantize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/quantize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +use crate::context::av1_get_coded_tx_size; +use crate::cpu_features::CpuFeatureLevel; +use crate::quantize::*; +use crate::transform::TxSize; +use crate::util::*; +use std::mem::MaybeUninit; + +type DequantizeFn = unsafe fn( + qindex: u8, + coeffs_ptr: *const i16, + _eob: u16, + rcoeffs_ptr: *mut i16, + tx_size: TxSize, + bit_depth: usize, + dc_delta_q: i8, + ac_delta_q: i8, +); + +cpu_function_lookup_table!( + DEQUANTIZE_FNS: [Option], + default: None, + [(AVX2, Some(dequantize_avx2))] +); + +#[inline(always)] +pub fn dequantize( + qindex: u8, coeffs: &[T], eob: u16, rcoeffs: &mut [MaybeUninit], + tx_size: TxSize, bit_depth: usize, dc_delta_q: i8, ac_delta_q: i8, + cpu: CpuFeatureLevel, +) { + let call_rust = |rcoeffs: &mut [MaybeUninit]| { + crate::quantize::rust::dequantize( + qindex, coeffs, eob, rcoeffs, tx_size, bit_depth, dc_delta_q, + ac_delta_q, cpu, + ); + }; + + #[cfg(any(feature = "check_asm", test))] + let mut ref_rcoeffs = { + let area = av1_get_coded_tx_size(tx_size).area(); + let mut copy = vec![MaybeUninit::new(T::cast_from(0)); area]; + call_rust(&mut copy); + copy + }; + + match T::Pixel::type_enum() { + PixelType::U8 => { + if let Some(func) = DEQUANTIZE_FNS[cpu.as_index()] { + // SAFETY: Calls Assembly code. + unsafe { + (func)( + qindex, + coeffs.as_ptr() as *const _, + eob, + rcoeffs.as_mut_ptr() as *mut _, + tx_size, + bit_depth, + dc_delta_q, + ac_delta_q, + ) + } + } else { + call_rust(rcoeffs) + } + } + PixelType::U16 => call_rust(rcoeffs), + } + + #[cfg(any(feature = "check_asm", test))] + { + let area = av1_get_coded_tx_size(tx_size).area(); + let rcoeffs = unsafe { slice_assume_init_mut(&mut rcoeffs[..area]) }; + let ref_rcoeffs = unsafe { slice_assume_init_mut(&mut ref_rcoeffs[..]) }; + assert_eq!(rcoeffs, ref_rcoeffs); + } +} + +#[target_feature(enable = "avx2")] +unsafe fn dequantize_avx2( + qindex: u8, coeffs_ptr: *const i16, _eob: u16, rcoeffs_ptr: *mut i16, + tx_size: TxSize, bit_depth: usize, dc_delta_q: i8, ac_delta_q: i8, +) { + let log_tx_scale = _mm256_set1_epi32(get_log_tx_scale(tx_size) as i32); + + let quants_ac = + _mm256_set1_epi32(ac_q(qindex, ac_delta_q, bit_depth).get() as i32); + // Use the dc quantize as first vector element for the first iteration + let mut quants = _mm256_insert_epi32( + quants_ac, + dc_q(qindex, dc_delta_q, bit_depth).get() as i32, + 0, + ); + + let area: usize = av1_get_coded_tx_size(tx_size).area(); + // Step by 16 (256/16) coefficients for each iteration + let step: usize = 16; + assert!(area >= step); + + // Increase the pointers as we iterate + let mut coeffs_ptr: *const i16 = coeffs_ptr; + let mut rcoeffs_ptr: *mut i16 = rcoeffs_ptr; + for _i in (0..area).step_by(step) { + let coeffs = _mm256_load_si256(coeffs_ptr as *const _); + let coeffs_abs = _mm256_abs_epi16(coeffs); + + // TODO: Since log_tx_scale is at most 2 and we gain an extra bit by taking + // the abs value (unless the range is [-(2^15), 2^15 + 1]), it might be + // possible to perform a 16-bit multiply and get the highest bit by + // comparing coeffs to (1<<16) / quant. The would cost 1 compare, 1 blend, + // and 1 add, but would get rid of 1 pack, 2 unpacks, 1 shift, and 1 + // multiply. + + let rcoeffs = _mm256_sign_epi16( + _mm256_packs_epi32( + // (abs_coeff * quant) >> log_tx_scale + _mm256_srlv_epi32( + _mm256_madd_epi16( + quants, + // Convert the first half of each lane to 32-bits + _mm256_unpacklo_epi16(coeffs_abs, _mm256_setzero_si256()), + ), + log_tx_scale, + ), + // Second half + _mm256_srlv_epi32( + _mm256_madd_epi16( + quants_ac, + _mm256_unpackhi_epi16(coeffs_abs, _mm256_setzero_si256()), + ), + log_tx_scale, + ), + ), + coeffs, + ); + _mm256_store_si256(rcoeffs_ptr as *mut _, rcoeffs); + + // Only use a dc quantizer for the first iteration + quants = quants_ac; + coeffs_ptr = coeffs_ptr.add(step); + rcoeffs_ptr = rcoeffs_ptr.add(step); + } +} + +#[cfg(test)] +mod test { + use super::*; + use rand::distr::{Distribution, Uniform}; + use rand::{rng, Rng}; + + #[test] + fn dequantize_test() { + let mut rng = rng(); + + use TxSize::*; + let tx_sizes = [ + TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_64X64, TX_4X8, TX_8X4, TX_8X16, + TX_16X8, TX_16X32, TX_32X16, TX_32X64, TX_64X32, TX_4X16, TX_16X4, + TX_8X32, TX_32X8, TX_16X64, TX_64X16, + ]; + + let bd: usize = 8; + + for &tx_size in &tx_sizes { + let qindex: u8 = rng.random_range((MINQ as u8)..(MAXQ as u8)); + let dc_quant = dc_q(qindex, 0, bd).get() as i16; + let ac_quant = ac_q(qindex, 0, bd).get() as i16; + + // Test the min, max, and random eobs + let eobs = { + let mut out = [0u16; 16]; + let area: usize = av1_get_coded_tx_size(tx_size).area(); + out[0] = 0; + out[1] = area as u16; + for eob in out.iter_mut().skip(2) { + *eob = rng.random_range(0..area as u16); + } + out + }; + + for &eob in &eobs { + let mut qcoeffs = Aligned::new([0i16; 32 * 32]); + let mut rcoeffs = Aligned::new([MaybeUninit::new(0i16); 32 * 32]); + + // Generate quantized coefficients up to the eob + // SAFETY: always correct + let between = Uniform::new_inclusive(-i16::MAX, i16::MAX).unwrap(); + for (i, qcoeff) in + qcoeffs.data.iter_mut().enumerate().take(eob as usize) + { + *qcoeff = between.sample(&mut rng) + / if i == 0 { dc_quant } else { ac_quant }; + } + + // Rely on quantize's internal tests + dequantize( + qindex, + &qcoeffs.data, + eob, + &mut rcoeffs.data, + tx_size, + bd, + 0, + 0, + CpuFeatureLevel::default(), + ); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/forward.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/forward.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/forward.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/forward.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,457 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::asm::shared::transform::forward::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::transform::forward::rust; +use crate::transform::forward_shared::*; +use crate::transform::*; +use crate::util::*; +use std::mem::MaybeUninit; + +use debug_unreachable::debug_unreachable; + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[derive(Copy, Clone)] +struct I32X8 { + data: __m256i, +} + +impl I32X8 { + #[target_feature(enable = "avx2")] + #[inline] + const unsafe fn vec(self) -> __m256i { + self.data + } + + #[target_feature(enable = "avx2")] + #[inline] + const unsafe fn new(a: __m256i) -> I32X8 { + I32X8 { data: a } + } +} + +type TxfmFunc = unsafe fn(&mut [I32X8]); + +impl_1d_tx!(target_feature(enable = "avx2"), unsafe); + +impl TxOperations for I32X8 { + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn zero() -> Self { + I32X8::new(_mm256_setzero_si256()) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn tx_mul(self, mul: i32) -> Self { + I32X8::new(_mm256_srav_epi32( + _mm256_add_epi32( + _mm256_mullo_epi32(self.vec(), _mm256_set1_epi32(mul)), + _mm256_set1_epi32(1 << SHIFT >> 1), + ), + _mm256_set1_epi32(SHIFT), + )) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn rshift1(self) -> Self { + I32X8::new(_mm256_srai_epi32( + _mm256_sub_epi32( + self.vec(), + _mm256_cmpgt_epi32(_mm256_setzero_si256(), self.vec()), + ), + 1, + )) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn add(self, b: Self) -> Self { + I32X8::new(_mm256_add_epi32(self.vec(), b.vec())) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn sub(self, b: Self) -> Self { + I32X8::new(_mm256_sub_epi32(self.vec(), b.vec())) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn add_avg(self, b: Self) -> Self { + I32X8::new(_mm256_srai_epi32(_mm256_add_epi32(self.vec(), b.vec()), 1)) + } + + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn sub_avg(self, b: Self) -> Self { + I32X8::new(_mm256_srai_epi32(_mm256_sub_epi32(self.vec(), b.vec()), 1)) + } +} + +#[target_feature(enable = "avx2")] +unsafe fn transpose_8x8_avx2(input: &[I32X8; 8], into: &mut [I32X8; 8]) { + let stage1 = ( + _mm256_unpacklo_epi32(input[0].vec(), input[1].vec()), + _mm256_unpackhi_epi32(input[0].vec(), input[1].vec()), + _mm256_unpacklo_epi32(input[2].vec(), input[3].vec()), + _mm256_unpackhi_epi32(input[2].vec(), input[3].vec()), + _mm256_unpacklo_epi32(input[4].vec(), input[5].vec()), + _mm256_unpackhi_epi32(input[4].vec(), input[5].vec()), + _mm256_unpacklo_epi32(input[6].vec(), input[7].vec()), + _mm256_unpackhi_epi32(input[6].vec(), input[7].vec()), + ); + + let stage2 = ( + _mm256_unpacklo_epi64(stage1.0, stage1.2), + _mm256_unpackhi_epi64(stage1.0, stage1.2), + _mm256_unpacklo_epi64(stage1.1, stage1.3), + _mm256_unpackhi_epi64(stage1.1, stage1.3), + _mm256_unpacklo_epi64(stage1.4, stage1.6), + _mm256_unpackhi_epi64(stage1.4, stage1.6), + _mm256_unpacklo_epi64(stage1.5, stage1.7), + _mm256_unpackhi_epi64(stage1.5, stage1.7), + ); + + #[allow(clippy::identity_op)] + const LO: i32 = (2 << 4) | 0; + const HI: i32 = (3 << 4) | 1; + into[0] = I32X8::new(_mm256_permute2x128_si256(stage2.0, stage2.4, LO)); + into[1] = I32X8::new(_mm256_permute2x128_si256(stage2.1, stage2.5, LO)); + into[2] = I32X8::new(_mm256_permute2x128_si256(stage2.2, stage2.6, LO)); + into[3] = I32X8::new(_mm256_permute2x128_si256(stage2.3, stage2.7, LO)); + into[4] = I32X8::new(_mm256_permute2x128_si256(stage2.0, stage2.4, HI)); + into[5] = I32X8::new(_mm256_permute2x128_si256(stage2.1, stage2.5, HI)); + into[6] = I32X8::new(_mm256_permute2x128_si256(stage2.2, stage2.6, HI)); + into[7] = I32X8::new(_mm256_permute2x128_si256(stage2.3, stage2.7, HI)); +} + +#[target_feature(enable = "avx2")] +unsafe fn transpose_8x4_avx2(input: &[I32X8; 8], into: &mut [I32X8; 4]) { + // Last 8 are empty + let stage1 = ( + //0101 + _mm256_unpacklo_epi32(input[0].vec(), input[1].vec()), + _mm256_unpackhi_epi32(input[0].vec(), input[1].vec()), + _mm256_unpacklo_epi32(input[2].vec(), input[3].vec()), + _mm256_unpackhi_epi32(input[2].vec(), input[3].vec()), + _mm256_unpacklo_epi32(input[4].vec(), input[5].vec()), + _mm256_unpackhi_epi32(input[4].vec(), input[5].vec()), + _mm256_unpacklo_epi32(input[6].vec(), input[7].vec()), + _mm256_unpackhi_epi32(input[6].vec(), input[7].vec()), + ); + + let stage2 = ( + _mm256_unpacklo_epi64(stage1.0, stage1.2), + _mm256_unpackhi_epi64(stage1.0, stage1.2), + _mm256_unpacklo_epi64(stage1.1, stage1.3), + _mm256_unpackhi_epi64(stage1.1, stage1.3), + _mm256_unpacklo_epi64(stage1.4, stage1.6), + _mm256_unpackhi_epi64(stage1.4, stage1.6), + _mm256_unpacklo_epi64(stage1.5, stage1.7), + _mm256_unpackhi_epi64(stage1.5, stage1.7), + ); + + #[allow(clippy::identity_op)] + const LO: i32 = (2 << 4) | 0; + into[0] = I32X8::new(_mm256_permute2x128_si256(stage2.0, stage2.4, LO)); + into[1] = I32X8::new(_mm256_permute2x128_si256(stage2.1, stage2.5, LO)); + into[2] = I32X8::new(_mm256_permute2x128_si256(stage2.2, stage2.6, LO)); + into[3] = I32X8::new(_mm256_permute2x128_si256(stage2.3, stage2.7, LO)); +} + +#[target_feature(enable = "avx2")] +unsafe fn transpose_4x8_avx2(input: &[I32X8; 4], into: &mut [I32X8; 8]) { + let stage1 = ( + // 0101 + _mm256_unpacklo_epi32(input[0].vec(), input[1].vec()), + _mm256_unpackhi_epi32(input[0].vec(), input[1].vec()), + // 2323 + _mm256_unpacklo_epi32(input[2].vec(), input[3].vec()), + _mm256_unpackhi_epi32(input[2].vec(), input[3].vec()), + ); + + let stage2 = ( + // 01234567 + _mm256_unpacklo_epi64(stage1.0, stage1.2), + _mm256_unpackhi_epi64(stage1.0, stage1.2), + _mm256_unpacklo_epi64(stage1.1, stage1.3), + _mm256_unpackhi_epi64(stage1.1, stage1.3), + ); + + into[0] = I32X8::new(stage2.0); + into[1] = I32X8::new(stage2.1); + into[2] = I32X8::new(stage2.2); + into[3] = I32X8::new(stage2.3); + into[4] = + I32X8::new(_mm256_castsi128_si256(_mm256_extractf128_si256(stage2.0, 1))); + into[5] = + I32X8::new(_mm256_castsi128_si256(_mm256_extractf128_si256(stage2.1, 1))); + into[6] = + I32X8::new(_mm256_castsi128_si256(_mm256_extractf128_si256(stage2.2, 1))); + into[7] = + I32X8::new(_mm256_castsi128_si256(_mm256_extractf128_si256(stage2.3, 1))); +} + +#[target_feature(enable = "avx2")] +unsafe fn transpose_4x4_avx2(input: &[I32X8; 4], into: &mut [I32X8; 4]) { + let stage1 = ( + _mm256_unpacklo_epi32(input[0].vec(), input[1].vec()), + _mm256_unpackhi_epi32(input[0].vec(), input[1].vec()), + _mm256_unpacklo_epi32(input[2].vec(), input[3].vec()), + _mm256_unpackhi_epi32(input[2].vec(), input[3].vec()), + ); + + into[0] = I32X8::new(_mm256_unpacklo_epi64(stage1.0, stage1.2)); + into[1] = I32X8::new(_mm256_unpackhi_epi64(stage1.0, stage1.2)); + into[2] = I32X8::new(_mm256_unpacklo_epi64(stage1.1, stage1.3)); + into[3] = I32X8::new(_mm256_unpackhi_epi64(stage1.1, stage1.3)); +} + +#[target_feature(enable = "avx2")] +#[inline] +unsafe fn shift_left(a: I32X8, shift: u8) -> I32X8 { + I32X8::new(_mm256_sllv_epi32(a.vec(), _mm256_set1_epi32(shift as i32))) +} + +#[target_feature(enable = "avx2")] +#[inline] +unsafe fn shift_right(a: I32X8, shift: u8) -> I32X8 { + I32X8::new(_mm256_srav_epi32( + _mm256_add_epi32(a.vec(), _mm256_set1_epi32(1 << (shift as i32) >> 1)), + _mm256_set1_epi32(shift as i32), + )) +} + +#[target_feature(enable = "avx2")] +#[inline] +unsafe fn round_shift_array_avx2(arr: &mut [I32X8], bit: i8) { + if arr.len() % 4 != 0 { + debug_unreachable!(); + } + + if bit == 0 { + return; + } + if bit > 0 { + let shift = bit as u8; + for s in arr.chunks_exact_mut(4) { + for chunk in s { + *chunk = shift_right(*chunk, shift); + } + } + } else { + let shift = (-bit) as u8; + for s in arr.chunks_exact_mut(4) { + for chunk in s { + *chunk = shift_left(*chunk, shift); + } + } + } +} + +#[allow(clippy::identity_op, clippy::erasing_op)] +#[target_feature(enable = "avx2")] +unsafe fn forward_transform_avx2( + input: &[i16], output: &mut [MaybeUninit], stride: usize, + tx_size: TxSize, tx_type: TxType, bd: usize, +) { + // Note when assigning txfm_size_col, we use the txfm_size from the + // row configuration and vice versa. This is intentionally done to + // accurately perform rectangular transforms. When the transform is + // rectangular, the number of columns will be the same as the + // txfm_size stored in the row cfg struct. It will make no difference + // for square transforms. + let txfm_size_col = tx_size.width(); + let txfm_size_row = tx_size.height(); + + let col_class = SizeClass1D::from_length(txfm_size_col); + let row_class = SizeClass1D::from_length(txfm_size_row); + + let mut tmp: Aligned<[I32X8; 64 * 64 / 8]> = Aligned::uninitialized(); + let buf = &mut tmp.data[..txfm_size_col * (txfm_size_row / 8).max(1)]; + let cfg = Txfm2DFlipCfg::fwd(tx_type, tx_size, bd); + + let txfm_func_col = get_func(cfg.txfm_type_col); + let txfm_func_row = get_func(cfg.txfm_type_row); + + // Columns + for cg in (0..txfm_size_col).step_by(8) { + let shift = cfg.shift[0] as u8; + #[target_feature(enable = "avx2")] + #[inline] + unsafe fn load_columns(input_ptr: *const i16, shift: u8) -> I32X8 { + // TODO: load 64-bits for x4 wide columns + shift_left( + I32X8::new(_mm256_cvtepi16_epi32(_mm_loadu_si128( + input_ptr as *const _, + ))), + shift, + ) + } + + // Avoid zero initialization + let tx_in = &mut [MaybeUninit::::uninit(); 64][..txfm_size_row]; + + if cfg.ud_flip { + // flip upside down + for (in_slice, out_reg) in + input[cg..].chunks(stride).zip(tx_in.iter_mut().rev()) + { + *out_reg = MaybeUninit::new(load_columns(in_slice.as_ptr(), shift)); + } + } else { + for (in_slice, out_reg) in + input[cg..].chunks(stride).zip(tx_in.iter_mut()) + { + *out_reg = MaybeUninit::new(load_columns(in_slice.as_ptr(), shift)); + } + } + + let col_coeffs = slice_assume_init_mut(tx_in); + + txfm_func_col(col_coeffs); + round_shift_array_avx2(col_coeffs, -cfg.shift[1]); + + // Transpose the array. Select the appropriate method to do so. + match (row_class, col_class) { + (SizeClass1D::X8UP, SizeClass1D::X8UP) => { + for rg in (0..txfm_size_row).step_by(8) { + let buf = &mut buf[(rg / 8 * txfm_size_col) + cg..]; + let buf = cast_mut::<8, _>(buf); + let input = &col_coeffs[rg..]; + let input = cast::<8, _>(input); + transpose_8x8_avx2(input, buf); + } + } + (SizeClass1D::X8UP, SizeClass1D::X4) => { + for rg in (0..txfm_size_row).step_by(8) { + let buf = &mut buf[(rg / 8 * txfm_size_col) + cg..]; + let buf = cast_mut::<4, _>(buf); + let input = &col_coeffs[rg..]; + let input = cast::<8, _>(input); + transpose_8x4_avx2(input, buf); + } + } + (SizeClass1D::X4, SizeClass1D::X8UP) => { + // Don't need to loop over rows + let buf = &mut buf[cg..]; + let buf = cast_mut::<8, _>(buf); + let input = cast::<4, _>(col_coeffs); + transpose_4x8_avx2(input, buf); + } + (SizeClass1D::X4, SizeClass1D::X4) => { + // Don't need to loop over rows + let buf = cast_mut::<4, _>(buf); + let input = cast::<4, _>(col_coeffs); + transpose_4x4_avx2(input, buf); + } + } + } + + // Rows + for rg in (0..txfm_size_row).step_by(8) { + let row_coeffs = &mut buf[rg / 8 * txfm_size_col..][..txfm_size_col]; + + if cfg.lr_flip { + row_coeffs.reverse(); + } + + txfm_func_row(row_coeffs); + round_shift_array_avx2(row_coeffs, -cfg.shift[2]); + + // Write out the coefficients using the correct method for transforms of + // this size. + match row_class { + SizeClass1D::X8UP => { + // Store output in at most 32x32 chunks. See rust code for details. + + // Output is grouped into 32x32 chunks so a stride of at most 32 is + // used for each chunk + let output_stride = txfm_size_row.min(32); + + // Split the first 32 rows from the last 32 rows and offset by rg % 32 + let output = &mut output[(rg & 31) + + (rg >= 32) as usize * output_stride * txfm_size_col.min(32)..]; + + for cg in (0..txfm_size_col).step_by(32) { + // Offset by zero or half of output + let output = &mut output[txfm_size_row * cg..]; + + for c in 0..txfm_size_col.min(32) { + match T::Pixel::type_enum() { + PixelType::U8 => { + let vec = row_coeffs[c + cg].vec(); + let lo = _mm256_castsi256_si128(vec); + let hi = _mm256_extracti128_si256(vec, 1); + _mm_storeu_si128( + output[c * output_stride..].as_mut_ptr() as *mut _, + _mm_packs_epi32(lo, hi), + ); + } + PixelType::U16 => { + _mm256_storeu_si256( + output[c * output_stride..].as_mut_ptr() as *mut _, + row_coeffs[c + cg].vec(), + ); + } + } + } + } + } + SizeClass1D::X4 => { + // Write out coefficients in normal order - it isn't possible to have + // more than 32 rows. + for c in 0..txfm_size_col { + match T::Pixel::type_enum() { + PixelType::U8 => { + let lo = _mm256_castsi256_si128(row_coeffs[c].vec()); + _mm_storel_epi64( + output[c * txfm_size_row + rg..].as_mut_ptr() as *mut _, + _mm_packs_epi32(lo, lo), + ); + } + PixelType::U16 => { + _mm256_storeu_si256( + output[c * txfm_size_row + rg..].as_mut_ptr() as *mut _, + row_coeffs[c].vec(), + ); + } + } + } + } + } + } +} + +/// # Panics +/// +/// - If called with an invalid combination of `tx_size` and `tx_type` +#[inline] +pub fn forward_transform( + input: &[i16], output: &mut [MaybeUninit], stride: usize, + tx_size: TxSize, tx_type: TxType, bd: usize, cpu: CpuFeatureLevel, +) { + assert!(valid_av1_transform(tx_size, tx_type)); + if cpu >= CpuFeatureLevel::AVX2 { + // SAFETY: Calls Assembly code. + unsafe { + forward_transform_avx2(input, output, stride, tx_size, tx_type, bd); + } + } else { + rust::forward_transform(input, output, stride, tx_size, tx_type, bd, cpu); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/inverse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/inverse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/inverse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/inverse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,563 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::tiling::PlaneRegionMut; +use crate::transform::inverse::*; +use crate::transform::*; +use crate::{Pixel, PixelType}; + +use crate::asm::shared::transform::inverse::*; + +pub fn inverse_transform_add( + input: &[T::Coeff], output: &mut PlaneRegionMut<'_, T>, eob: u16, + tx_size: TxSize, tx_type: TxType, bd: usize, cpu: CpuFeatureLevel, +) { + match T::type_enum() { + PixelType::U8 => { + if let Some(func) = INV_TXFM_FNS[cpu.as_index()][tx_size][tx_type] { + return call_inverse_func( + func, + input, + output, + eob, + tx_size.width(), + tx_size.height(), + bd, + ); + } + } + PixelType::U16 if bd == 10 => { + if let Some(func) = INV_TXFM_HBD_FNS_10[cpu.as_index()][tx_size][tx_type] + { + return call_inverse_hbd_func( + func, + input, + output, + eob, + tx_size.width(), + tx_size.height(), + bd, + ); + } + } + PixelType::U16 => { + if let Some(func) = INV_TXFM_HBD_FNS_12[cpu.as_index()][tx_size][tx_type] + { + return call_inverse_hbd_func( + func, + input, + output, + eob, + tx_size.width(), + tx_size.height(), + bd, + ); + } + } + }; + + rust::inverse_transform_add(input, output, eob, tx_size, tx_type, bd, cpu); +} + +macro_rules! decl_itx_fns { + // Takes a 2d list of tx types for W and H + ([$([$(($ENUM:expr, $TYPE1:ident, $TYPE2:ident)),*]),*], $W:expr, $H:expr, + $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + // For each tx type, declare an function for the current WxH + $( + $( + extern { + // Note: type1 and type2 are flipped + fn []( + dst: *mut u8, dst_stride: libc::ptrdiff_t, coeff: *mut i16, + eob: i32 + ); + } + )* + )* + // Create a lookup table for the tx types declared above + const []: [Option; TX_TYPES_PLUS_LL] = { + let mut out: [Option; TX_TYPES_PLUS_LL] = [None; TX_TYPES_PLUS_LL]; + $( + $( + out[$ENUM as usize] = Some([]); + )* + )* + out + }; + } + }; +} + +macro_rules! decl_itx_hbd_fns { + // Takes a 2d list of tx types for W and H + ([$([$(($ENUM:expr, $TYPE1:ident, $TYPE2:ident)),*]),*], $W:expr, $H:expr, $BPC:expr, + $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + // For each tx type, declare an function for the current WxH + $( + $( + extern { + // Note: type1 and type2 are flipped + fn []( + dst: *mut u16, dst_stride: libc::ptrdiff_t, coeff: *mut i16, + eob: i32, bitdepth_max: i32, + ); + } + )* + )* + // Create a lookup table for the tx types declared above + const []: [Option; TX_TYPES_PLUS_LL] = { + #[allow(unused_mut)] + let mut out: [Option; TX_TYPES_PLUS_LL] = [None; TX_TYPES_PLUS_LL]; + $( + $( + out[$ENUM as usize] = Some([]); + )* + )* + out + }; + } + }; +} + +macro_rules! create_wxh_tables { + // Create a lookup table for each cpu feature + ([$([$(($W:expr, $H:expr)),*]),*], $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + const []: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = { + let mut out: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = + [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]; + // For each dimension, add an entry to the table + $( + $( + out[TxSize::[] as usize] = []; + )* + )* + out + }; + } + }; + + // Loop through cpu features + ($DIMS:tt, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + create_wxh_tables!($DIMS, $OPT_LOWER, $OPT_UPPER); + )* + }; +} + +macro_rules! create_wxh_hbd_tables { + // Create a lookup table for each cpu feature + ([$([$(($W:expr, $H:expr)),*]),*], $EXT:ident, $BPC:expr, $OPT_LOWER:ident, $OPT_UPPER:ident) => { + paste::item! { + const []: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = { + let mut out: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] = + [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]; + // For each dimension, add an entry to the table + $( + $( + out[TxSize::[] as usize] = []; + )* + )* + out + }; + } + }; + + // Loop through cpu features + ($DIMS:tt, $EXT:ident, [$(($BPC:expr, $OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + create_wxh_hbd_tables!($DIMS, $EXT, $BPC, $OPT_LOWER, $OPT_UPPER); + )* + }; +} + +macro_rules! impl_itx_fns { + ($TYPES:tt, $W:expr, $H:expr, [$(($OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + decl_itx_fns!($TYPES, $W, $H, $OPT_LOWER, $OPT_UPPER); + )* + }; + + // Loop over a list of dimensions + ($TYPES_VALID:tt, [$(($W:expr, $H:expr)),*], $OPT:tt) => { + $( + impl_itx_fns!($TYPES_VALID, $W, $H, $OPT); + )* + }; + + ($TYPES64:tt, $DIMS64:tt, $TYPES32:tt, $DIMS32:tt, $TYPES16:tt, $DIMS16:tt, + $TYPES84:tt, $DIMS84:tt, $TYPES4:tt, $DIMS4:tt, $OPT:tt) => { + // Make 2d list of tx types for each set of dimensions. Each set of + // dimensions uses a superset of the previous set of tx types. + impl_itx_fns!([$TYPES64], $DIMS64, $OPT); + impl_itx_fns!([$TYPES64, $TYPES32], $DIMS32, $OPT); + impl_itx_fns!([$TYPES64, $TYPES32, $TYPES16], $DIMS16, $OPT); + impl_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84], $DIMS84, $OPT + ); + impl_itx_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84, $TYPES4], $DIMS4, $OPT + ); + + // Pool all of the dimensions together to create a table for each cpu + // feature level. + create_wxh_tables!( + [$DIMS64, $DIMS32, $DIMS16, $DIMS84, $DIMS4], $OPT + ); + }; +} + +impl_itx_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8)], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)], + [(avx2, AVX2)] +); + +impl_itx_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8), (4, 4)], + // 4x4 + [], + [], + [(avx512icl, AVX512ICL), (ssse3, SSSE3)] +); + +impl_itx_fns!( + // 64x + [], + [], + // 32x + [], + [], + // 16x16 + [], + [], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [], + [], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)], + [(sse2, SSE2)] +); + +cpu_function_lookup_table!( + INV_TXFM_FNS: [[[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]], + default: [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + [SSE2, SSSE3, AVX2, AVX512ICL] +); + +macro_rules! impl_itx_hbd_fns { + + ($TYPES:tt, $W:expr, $H:expr, [$(($BPC:expr, $OPT_LOWER:ident, $OPT_UPPER:ident)),+]) => { + $( + decl_itx_hbd_fns!($TYPES, $W, $H, $BPC, $OPT_LOWER, $OPT_UPPER); + )* + }; + + // Loop over a list of dimensions + ($TYPES_VALID:tt, [$(($W:expr, $H:expr)),*], $OPT:tt) => { + $( + impl_itx_hbd_fns!($TYPES_VALID, $W, $H, $OPT); + )* + }; + + ($TYPES64:tt, $DIMS64:tt, $TYPES32:tt, $DIMS32:tt, $TYPES16:tt, $DIMS16:tt, + $TYPES84:tt, $DIMS84:tt, $TYPES4:tt, $DIMS4:tt, $EXT:ident, $OPT:tt) => { + // Make 2d list of tx types for each set of dimensions. Each set of + // dimensions uses a superset of the previous set of tx types. + impl_itx_hbd_fns!([$TYPES64], $DIMS64, $OPT); + impl_itx_hbd_fns!([$TYPES64, $TYPES32], $DIMS32, $OPT); + impl_itx_hbd_fns!([$TYPES64, $TYPES32, $TYPES16], $DIMS16, $OPT); + impl_itx_hbd_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84], $DIMS84, $OPT + ); + impl_itx_hbd_fns!( + [$TYPES64, $TYPES32, $TYPES16, $TYPES84, $TYPES4], $DIMS4, $OPT + ); + + // Pool all of the dimensions together to create a table for each cpu + // feature level. + create_wxh_hbd_tables!( + [$DIMS64, $DIMS32, $DIMS16, $DIMS84, $DIMS4], $EXT, $OPT + ); + }; +} + +impl_itx_hbd_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (64, 16), (16, 64)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (8, 8)], + // 4x4 + [], + [], + _10, + [(10, avx512icl, AVX512ICL)] +); + +impl_itx_hbd_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8), (4, 4)], + // 4x4 + [], + [], + _10_, + [(10, avx2, AVX2)] +); + +impl_itx_hbd_fns!( + // 64x + [(TxType::DCT_DCT, dct, dct)], + [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)], + // 32x + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32), (32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8), (4, 4)], + // 4x4 + [], + [], + _10, + [(16, sse4, SSE4_1)] +); + +impl_itx_hbd_fns!( + // 64x + [], + [], + // 32x + [], + [], + // 16x16 + [], + [], + // 8x, 4x and 16x (minus 16x16 and 4x4) + [], + [], + // 4x4 + [(TxType::WHT_WHT, wht, wht)], + [(4, 4)], + _16, + [(16, sse2, SSE2), (16, avx2, AVX2)] +); + +const INV_TXFM_HBD_FNS_10_SSE2: [[Option; TX_TYPES_PLUS_LL]; + TxSize::TX_SIZES_ALL] = INV_TXFM_HBD_FNS_16_SSE2; +const INV_TXFM_HBD_FNS_12_SSE2: [[Option; TX_TYPES_PLUS_LL]; + TxSize::TX_SIZES_ALL] = INV_TXFM_HBD_FNS_16_SSE2; + +const fn merge_hbd_fns( + a: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + b: [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], +) -> [[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL] { + let mut out = b; + let mut tx_size = 0; + loop { + let mut tx_type = 0; + loop { + if a[tx_size][tx_type].is_some() { + out[tx_size][tx_type] = a[tx_size][tx_type]; + } + tx_type += 1; + if tx_type == TX_TYPES_PLUS_LL { + break; + } + } + tx_size += 1; + if tx_size == TxSize::TX_SIZES_ALL { + break; + } + } + out +} + +const INV_TXFM_HBD_FNS_10_AVX2: [[Option; TX_TYPES_PLUS_LL]; + TxSize::TX_SIZES_ALL] = + merge_hbd_fns(INV_TXFM_HBD_FNS_10__AVX2, INV_TXFM_HBD_FNS_16_AVX2); + +cpu_function_lookup_table!( + INV_TXFM_HBD_FNS_10: [[[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]], + default: [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + [SSE2, SSE4_1, AVX2, AVX512ICL] +); + +impl_itx_hbd_fns!( + // 32x (DCT and IDTX swapped due to incomplete DCT implementation) + [(TxType::IDTX, identity, identity)], + [(32, 32), (32, 16), (16, 32)], + [(TxType::DCT_DCT, dct, dct)], + [(32, 8), (8, 32)], + // 16x16 + [ + (TxType::DCT_ADST, dct, adst), + (TxType::ADST_DCT, adst, dct), + (TxType::DCT_FLIPADST, dct, flipadst), + (TxType::FLIPADST_DCT, flipadst, dct), + (TxType::V_DCT, dct, identity), + (TxType::H_DCT, identity, dct), + (TxType::ADST_ADST, adst, adst), + (TxType::ADST_FLIPADST, adst, flipadst), + (TxType::FLIPADST_ADST, flipadst, adst), + (TxType::FLIPADST_FLIPADST, flipadst, flipadst) + ], + [(16, 16)], + // 8x, 4x and 16x (minus 16x16) + [ + (TxType::V_ADST, adst, identity), + (TxType::H_ADST, identity, adst), + (TxType::V_FLIPADST, flipadst, identity), + (TxType::H_FLIPADST, identity, flipadst) + ], + [(16, 8), (8, 16), (16, 4), (4, 16), (8, 8), (8, 4), (4, 8), (4, 4)], + // 4x4 + [], + [], + _12_, + [(12, avx2, AVX2)] +); + +const INV_TXFM_HBD_FNS_12_AVX2: [[Option; TX_TYPES_PLUS_LL]; + TxSize::TX_SIZES_ALL] = + merge_hbd_fns(INV_TXFM_HBD_FNS_12__AVX2, INV_TXFM_HBD_FNS_16_AVX2); + +cpu_function_lookup_table!( + INV_TXFM_HBD_FNS_12: [[[Option; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL]], + default: [[None; TX_TYPES_PLUS_LL]; TxSize::TX_SIZES_ALL], + [SSE2, AVX2] +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/asm/x86/transform/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2019, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub mod forward; +pub mod inverse; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/common.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/common.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/common.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/common.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,721 @@ +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::error::*; +use crate::muxer::{create_muxer, Muxer}; +use crate::stats::MetricsEnabled; +use clap::builder::styling::AnsiColor; +use clap::builder::Styles; +use clap::{CommandFactory, Parser as Clap, Subcommand}; +use clap_complete::{generate, Shell}; +use rav1e::prelude::*; +use scan_fmt::scan_fmt; + +use rav1e::config::CpuFeatureLevel; +use std::fs::File; +use std::io; +use std::io::prelude::*; +use std::path::PathBuf; +use std::sync::OnceLock; + +pub mod built_info { + // The file has been placed there by the build script. + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +#[derive(Clap)] +#[clap( + name = "rav1e", + styles = get_styles(), + version = get_version(), + long_version = get_long_version(), + about = "AV1 video encoder", + long_about = None +)] +pub struct CliOptions { + /// Uncompressed YUV4MPEG2 video input + #[clap(value_parser, help_heading = "INPUT/OUTPUT")] + pub input: PathBuf, + /// Compressed AV1 in IVF video output + #[clap(long, short, value_parser, help_heading = "INPUT/OUTPUT")] + pub output: PathBuf, + /// Overwrite output file. + #[clap(short = 'y', help_heading = "INPUT/OUTPUT")] + pub overwrite: bool, + + /// Set the threadpool size. If 0, will use the number of logical CPUs. + /// rav1e will use up to this many threads. Additional tiles may be needed to + /// increase thread utilization. + #[clap(long, value_parser, default_value_t = 0, help_heading = "THREADING")] + pub threads: usize, + /// Number of tile rows. Must be a power of 2. rav1e may override this based on video resolution. + #[clap(long, value_parser, default_value_t = 0, help_heading = "THREADING")] + pub tile_rows: usize, + /// Number of tile columns. Must be a power of 2. rav1e may override this based on video resolution. + #[clap(long, value_parser, default_value_t = 0, help_heading = "THREADING")] + pub tile_cols: usize, + /// Number of tiles. Tile-cols and tile-rows are overridden + /// so that the video has at least this many tiles. + #[clap( + long, + value_parser, + conflicts_with = "tile_rows", + conflicts_with = "tile_cols", + help_heading = "THREADING" + )] + pub tiles: Option, + /// Maximum number of GOPs that can be encoded in parallel + #[cfg(feature = "unstable")] + #[clap(long, value_parser, default_value_t = 0, help_heading = "THREADING")] + pub slots: usize, + + /// Perform the first pass of a two-pass encode, + /// saving the pass data to the specified file for future passes + #[clap( + long, + value_parser, + value_name = "STATS_FILE", + help_heading = "ENCODE SETTINGS" + )] + pub first_pass: Option, + /// Perform the second pass of a two-pass encode, + /// reading the pass data saved from a previous pass from the specified file + #[clap( + long, + value_parser, + value_name = "STATS_FILE", + help_heading = "ENCODE SETTINGS" + )] + pub second_pass: Option, + /// Maximum number of frames to encode + #[clap( + long, + short, + value_parser, + default_value_t = 0, + help_heading = "ENCODE SETTINGS" + )] + pub limit: usize, + /// Skip n number of frames and encode + #[clap( + long, + value_parser, + default_value_t = 0, + help_heading = "ENCODE SETTINGS" + )] + pub skip: usize, + /// Quantizer (0-255), smaller values are higher quality [default: 100] + #[clap(long, value_parser, help_heading = "ENCODE SETTINGS")] + pub quantizer: Option, + /// Minimum quantizer (0-255) to use in bitrate mode [default: 0] + #[clap(long, value_parser, help_heading = "ENCODE SETTINGS")] + pub min_quantizer: Option, + /// Bitrate (kbps) + #[clap(long, short, value_parser, help_heading = "ENCODE SETTINGS")] + pub bitrate: Option, + /// Speed level (0 is best quality, 10 is fastest). + /// Speeds 10 and 0 are extremes and are generally not recommended. + #[clap(long, short, value_parser = clap::value_parser!(u8).range(0..=10), default_value_t = 6, help_heading = "ENCODE SETTINGS", long_help = build_speed_long_help())] + pub speed: u8, + /// Speed level for scene-change detection, 0: best quality, 1: fastest mode. + /// [default: 0 for s0-s9, 1 for s10] + #[clap(long, value_parser = clap::value_parser!(u8).range(0..=1), help_heading = "ENCODE SETTINGS")] + pub scd_speed: Option, + /// Minimum interval between keyframes + #[clap( + long, + short = 'i', + value_parser, + default_value_t = 12, + help_heading = "ENCODE SETTINGS" + )] + pub min_keyint: u64, + /// Maximum interval between keyframes. When set to 0, disables fixed-interval keyframes. + #[clap( + long, + short = 'I', + value_parser, + default_value_t = 240, + help_heading = "ENCODE SETTINGS" + )] + pub keyint: u64, + /// Maximum interval between switch frames. When set to 0, disables switch frames. + #[clap( + long, + short = 'S', + value_parser, + default_value_t = 0, + help_heading = "ENCODE SETTINGS" + )] + pub switch_frame_interval: u64, + /// "Number of frames over which rate control should distribute the reservoir + /// [default: min(240, 1.5x keyint)] + /// A minimum value of 12 is enforced. + #[clap(long, value_parser = clap::value_parser!(i32).range(12..), help_heading = "ENCODE SETTINGS")] + pub reservoir_frame_delay: Option, + /// Low latency mode; disables frame reordering. + /// Has a significant speed-to-quality trade-off + #[clap(long, help_heading = "ENCODE SETTINGS")] + pub low_latency: bool, + /// Disables scene detection entirely. + /// Has a significant speed-to-quality trade-off in full encodes. + /// Useful for chunked encoding. + #[clap(long, help_heading = "ENCODE SETTINGS")] + pub no_scene_detection: bool, + /// Number of frames encoder should lookahead for RDO purposes\n\ + /// [default value for speed levels: 10,9 - 10; 8,7,6 - 20; 5,4,3 - 30; 2,1,0 - 40] + #[clap(long, value_parser, help_heading = "ENCODE SETTINGS")] + pub rdo_lookahead_frames: Option, + /// Quality tuning + #[clap(long, value_parser, default_value_t = Tune::Psychovisual, help_heading = "ENCODE SETTINGS")] + pub tune: Tune, + /// Still picture mode + #[clap(long, help_heading = "ENCODE SETTINGS")] + pub still_picture: bool, + /// Uses grain synthesis to add photon noise to the resulting encode. + /// Takes a strength value 0-64. + #[clap( + long, + conflicts_with = "film_grain_table", + value_parser = clap::value_parser!(u8).range(0..=64), + default_value_t = 0, + help_heading = "ENCODE SETTINGS" + )] + pub photon_noise: u8, + /// Uses a film grain table file to apply grain synthesis to the encode. + /// Uses the same table file format as aomenc and svt-av1. + #[clap( + long, + alias = "photon-noise-table", + value_parser, + help_heading = "ENCODE SETTINGS" + )] + pub film_grain_table: Option, + /// Force the high bitdepth codepath even for 8bit content. + /// Mainly for debugging purposes. + #[clap(long, help_heading = "ENCODE SETTINGS")] + pub high_bitdepth: bool, + + /// Pixel range + #[clap(long, value_parser, help_heading = "VIDEO METADATA")] + pub range: Option, + /// Color primaries used to describe color parameters + #[clap(long, value_parser, help_heading = "VIDEO METADATA")] + pub primaries: Option, + /// Transfer characteristics used to describe color parameters + #[clap(long, value_parser, help_heading = "VIDEO METADATA")] + pub transfer: Option, + /// Matrix coefficients used to describe color parameters + #[clap(long, value_parser, help_heading = "VIDEO METADATA")] + pub matrix: Option, + /// Mastering display primaries in the form of G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min) + #[clap(long, help_heading = "VIDEO METADATA")] + pub mastering_display: Option, + /// Content light level used to describe content luminosity (cll,fall) + #[clap(long, help_heading = "VIDEO METADATA")] + pub content_light: Option, + /// AV1 level to target in the form ., e.g. 3.1. + /// Specify "unconstrained" for no level constraints or "auto" to let + /// the encoder choose (default) + #[clap(long, help_heading = "LEVEL")] + pub level: Option, + /// Constant frame rate to set at the output (inferred from input when omitted) + #[clap(long, value_parser, help_heading = "VIDEO METADATA")] + pub frame_rate: Option, + /// The time scale associated with the frame rate if provided (ignored otherwise) + #[clap( + long, + value_parser, + default_value_t = 0, + help_heading = "VIDEO METADATA" + )] + pub time_scale: u64, + + /// Provide a benchmark report at the end of the encoding + #[clap(long, help_heading = "DEBUGGING")] + pub benchmark: bool, + /// Verbose logging; outputs info for every frame + #[clap(long, short, help_heading = "DEBUGGING")] + pub verbose: bool, + /// Do not output any status message + #[clap(long, short, conflicts_with = "verbose", help_heading = "DEBUGGING")] + pub quiet: bool, + /// Calculate and display PSNR metrics + #[clap(long, help_heading = "DEBUGGING")] + pub psnr: bool, + /// Calculate and display several metrics including PSNR, SSIM, CIEDE2000 etc + #[clap(long, conflicts_with = "psnr", help_heading = "DEBUGGING")] + pub metrics: bool, + /// Outputs a Y4M file containing the output from the decoder + #[clap(long, short, value_parser, help_heading = "DEBUGGING")] + pub reconstruction: Option, + + #[clap(subcommand)] + pub command: Option, +} + +static VERSION_STR: OnceLock = OnceLock::new(); +static LONG_VERSION_STR: OnceLock = OnceLock::new(); + +fn get_styles() -> Styles { + Styles::styled() + .header(AnsiColor::Yellow.on_default()) + .usage(AnsiColor::Green.on_default()) + .literal(AnsiColor::Green.on_default()) + .placeholder(AnsiColor::Green.on_default()) +} + +fn get_version() -> &'static str { + VERSION_STR.get_or_init(|| { + format!( + "{} ({})", + rav1e::version::full(), + // We cannot use `built_info::DEBUG` because that tells us if there are debug symbols, + // not if there are optimizations. + if cfg!(debug_assertions) { "debug" } else { "release" } + ) + }) +} + +fn get_long_version() -> &'static str { + LONG_VERSION_STR.get_or_init(|| { + let rustflags = env!("CARGO_ENCODED_RUSTFLAGS"); + let rustflags = if rustflags.trim().is_empty() { + "(None)".to_string() + } else { + // Replace non-printable ASCII Unit Separator with whitespace + rustflags.replace(0x1F as char, " ") + }; + format!( + "{}\n{} {}\nCompiled CPU Features: {}\nRuntime Assembly Support: {}{}\nThreading: {}\nUnstable Features: {}\nCompiler Flags: {}", + get_version(), + built_info::RUSTC_VERSION, + built_info::TARGET, + option_env!("CARGO_CFG_TARGET_FEATURE").unwrap_or("(None)"), + if cfg!(feature = "asm") { "Enabled" } else { "Disabled" }, + if cfg!(feature = "asm") { + format!("\nRuntime Assembly Level: {}", CpuFeatureLevel::default()) + } else { + String::new() + }, + if cfg!(feature = "threading") { "Enabled" } else { "Disabled" }, + if cfg!(feature = "unstable") { "Enabled" } else { "Disabled" }, + rustflags + ) + }) +} + +#[derive(Subcommand)] +pub enum Commands { + /// Advanced features + Advanced { + /// Output to stdout the completion definition for the shell + #[clap(long, short, value_parser)] + completion: Option, + /// Save the current configuration in a toml file + #[clap(long, short, value_parser)] + save_config: Option, + /// Load the encoder configuration from a toml file + #[clap(long, short, value_parser, conflicts_with = "save-config")] + load_config: Option, + }, +} + +pub struct EncoderIO { + pub input: Box, + pub output: Box, + pub rec: Option>, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum Verboseness { + Quiet, + Normal, + Verbose, +} + +pub struct ParsedCliOptions { + pub io: EncoderIO, + pub enc: EncoderConfig, + pub limit: usize, + pub color_range_specified: bool, + pub override_time_base: bool, + pub skip: usize, + pub verbose: Verboseness, + pub benchmark: bool, + pub threads: usize, + pub metrics_enabled: MetricsEnabled, + pub pass1file_name: Option, + pub pass2file_name: Option, + #[cfg(feature = "serialize")] + pub save_config: Option, + pub photon_noise: u8, + #[cfg(feature = "unstable")] + #[allow(unused)] + pub slots: usize, + pub force_highbitdepth: bool, +} + +#[cfg(feature = "serialize")] +static HELP_TEXT: OnceLock = OnceLock::new(); + +#[cfg(feature = "serialize")] +fn build_speed_long_help() -> Option<&'static str> { + let help = HELP_TEXT.get_or_init(|| { + let levels = (0..=10) + .map(|speed| { + let s = SpeedSettings::from_preset(speed); + let o = crate::kv::to_string(&s).unwrap().replace(", ", "\n "); + format!("{:2} :\n {}", speed, o) + }) + .collect::>() + .join("\n"); + + format!( + "Speed level (0 is best quality, 10 is fastest)\n\ + Speeds 10 and 0 are extremes and are generally not recommended\n\ + {}", + levels + ) + }); + + Some(&help) +} + +#[cfg(not(feature = "serialize"))] +#[allow(clippy::missing_const_for_fn)] +fn build_speed_long_help() -> Option<&'static str> { + Some( + "Speed level (0 is best quality, 10 is fastest)\n\ + Speeds 10 and 0 are extremes and are generally not recommended", + ) +} + +#[allow(unused_mut)] +/// Only call this once at the start of the app, +/// otherwise bad things will happen. +pub fn parse_cli() -> Result { + let matches = CliOptions::parse(); + + #[cfg(feature = "serialize")] + let mut save_config_path = None; + let mut enc = None; + + if let Some(command) = matches.command.as_ref() { + match command { + Commands::Advanced { completion, save_config, load_config } => { + if let Some(shell) = completion { + let mut app = CliOptions::command(); + let app_name = app.get_name().to_string(); + generate(*shell, &mut app, app_name, &mut std::io::stdout()); + std::process::exit(0); + } + + #[cfg(feature = "serialize")] + { + save_config_path = save_config.clone(); + if let Some(load_config) = load_config { + let mut config = String::new(); + File::open(load_config) + .and_then(|mut f| f.read_to_string(&mut config)) + .map_err(|e| e.context("Cannot open the configuration file"))?; + + enc = Some(toml::from_str(&config).unwrap()); + } + } + #[cfg(not(feature = "serialize"))] + { + if save_config.is_some() || load_config.is_some() { + let e: io::Error = io::ErrorKind::InvalidInput.into(); + return Err(e.context( + "The load/save config advanced option requires the + `serialize` feature, rebuild adding it.", + )); + } + } + } + } + } + + let rec = match matches.reconstruction.as_ref() { + Some(f) => Some(Box::new( + File::create(f) + .map_err(|e| e.context("Cannot create reconstruction file"))?, + ) as Box), + None => None, + }; + + let os_input = &matches.input; + let io = EncoderIO { + input: match os_input.to_str() { + Some("-") => Box::new(io::stdin()) as Box, + _ => Box::new( + File::open(os_input) + .map_err(|e| e.context("Cannot open input file"))?, + ) as Box, + }, + output: create_muxer(&matches.output, matches.overwrite)?, + rec, + }; + + let enc = enc.map_or_else(|| parse_config(&matches), Ok)?; + + let verbose = if matches.quiet { + Verboseness::Quiet + } else if matches.verbose { + Verboseness::Verbose + } else { + Verboseness::Normal + }; + + let metrics_enabled = if matches.metrics { + MetricsEnabled::All + } else if matches.psnr { + MetricsEnabled::Psnr + } else { + MetricsEnabled::None + }; + + let limit = matches.limit; + if enc.still_picture && limit > 1 { + panic!("A limit cannot be set above 1 in still picture mode"); + } + + #[cfg(feature = "unstable")] + let slots = matches.slots; + + Ok(ParsedCliOptions { + io, + enc, + limit, + color_range_specified: matches.range.is_some(), + override_time_base: matches.frame_rate.is_some(), + metrics_enabled, + skip: matches.skip, + benchmark: matches.benchmark, + verbose, + threads: matches.threads, + pass1file_name: matches.first_pass.clone(), + pass2file_name: matches.second_pass.clone(), + #[cfg(feature = "serialize")] + save_config: save_config_path, + photon_noise: matches.photon_noise, + force_highbitdepth: matches.high_bitdepth, + #[cfg(feature = "unstable")] + slots, + }) +} + +fn parse_config(matches: &CliOptions) -> Result { + let maybe_quantizer = matches.quantizer; + let maybe_bitrate = matches.bitrate; + let quantizer = maybe_quantizer.unwrap_or_else(|| { + if maybe_bitrate.is_some() { + // If a bitrate is specified, the quantizer is the maximum allowed (e.g., + // the minimum quality allowed), which by default should be + // unconstrained. + 255 + } else { + 100 + } + }) as usize; + let bitrate: i32 = maybe_bitrate.unwrap_or(0); + if bitrate <= 0 + && (matches.first_pass.is_some() || matches.second_pass.is_some()) + { + panic!("A target bitrate must be specified when using passes"); + } + + if quantizer == 0 { + unimplemented!("Lossless encoding not yet implemented"); + } else if quantizer > 255 { + panic!("Quantizer must be between 0-255"); + } + + let speed = matches.speed; + let scene_detection_speed = matches.scd_speed; + let max_interval = matches.keyint; + let min_interval = matches.min_keyint.min(max_interval); + + if speed > 10 { + panic!("Speed must be between 0-10"); + } else if min_interval > max_interval { + panic!("Maximum keyframe interval must be greater than or equal to minimum keyframe interval"); + } + + let color_primaries = matches.primaries.unwrap_or_default(); + let transfer_characteristics = matches.transfer.unwrap_or_default(); + let matrix_coefficients = matches.matrix.unwrap_or_default(); + + let mut cfg = EncoderConfig::with_speed_preset(speed); + + if let Some(level_str) = &matches.level { + cfg.level_idx = match level_str.as_str() { + "auto" => None, + "unconstrained" => Some(31), + _ => { + let (major, minor) = scan_fmt!(level_str, "{}.{}", u8, u8) + .expect("Could not parse AV1 level"); + if major > 7 || minor > 3 { + panic!("Invalid AV1 level") + } + Some(((major - 2) << 2) + minor) + } + }; + }; + + if let Some(scd_speed) = scene_detection_speed { + cfg.speed_settings.scene_detection_mode = if scd_speed == 0 { + SceneDetectionSpeed::Standard + } else { + SceneDetectionSpeed::Fast + }; + } + + cfg.set_key_frame_interval(min_interval, max_interval); + cfg.switch_frame_interval = matches.switch_frame_interval; + + cfg.pixel_range = matches.range.unwrap_or_default(); + cfg.color_description = if color_primaries == ColorPrimaries::Unspecified + && transfer_characteristics == TransferCharacteristics::Unspecified + && matrix_coefficients == MatrixCoefficients::Unspecified + { + // No need to set a color description with all parameters unspecified. + None + } else { + Some(ColorDescription { + color_primaries, + transfer_characteristics, + matrix_coefficients, + }) + }; + + cfg.mastering_display = matches.mastering_display.as_ref().map(|mastering_display| { + let (g_x, g_y, b_x, b_y, r_x, r_y, wp_x, wp_y, max_lum, min_lum) = + scan_fmt!( + mastering_display, + "G({},{})B({},{})R({},{})WP({},{})L({},{})", + f64, + f64, + f64, + f64, + f64, + f64, + f64, + f64, + f64, + f64 + ) + .expect("Cannot parse the mastering display option"); + + /* AV1 spec sec. 6.7.4 "Metadata high dynamic range mastering display color volume semantics" + * specifies chromaticity coords as 0.16 fixed-point numbers, which have a max float value + * of 0.9999847412109375 (rounding to 1). + */ + let chromaticity_range = 0.0..=1.0; + if !chromaticity_range.contains(&g_x) + || !chromaticity_range.contains(&g_y) + || !chromaticity_range.contains(&b_x) + || !chromaticity_range.contains(&b_y) + || !chromaticity_range.contains(&r_x) + || !chromaticity_range.contains(&r_y) + || !chromaticity_range.contains(&wp_x) + || !chromaticity_range.contains(&wp_y) + { + warn!( + "Chromaticity coordinates will be trimmed to the range 0.0 to 1.0 (see AV1 spec sec. 6.7.4)." + ); + } + + MasteringDisplay { + primaries: [ + ChromaticityPoint { + x: (r_x * ((1 << 16) as f64)).round() as u16, + y: (r_y * ((1 << 16) as f64)).round() as u16, + }, + ChromaticityPoint { + x: (g_x * ((1 << 16) as f64)).round() as u16, + y: (g_y * ((1 << 16) as f64)).round() as u16, + }, + ChromaticityPoint { + x: (b_x * ((1 << 16) as f64)).round() as u16, + y: (b_y * ((1 << 16) as f64)).round() as u16, + }, + ], + white_point: ChromaticityPoint { + x: (wp_x * ((1 << 16) as f64)).round() as u16, + y: (wp_y * ((1 << 16) as f64)).round() as u16, + }, + max_luminance: (max_lum * ((1 << 8) as f64)).round() as u32, + min_luminance: (min_lum * ((1 << 14) as f64)).round() as u32, + } + }); + + cfg.content_light = + matches.content_light.as_ref().and_then(|content_light| { + let (cll, fall) = scan_fmt!(content_light, "{},{}", u16, u16) + .expect("Cannot parse the content light option"); + if cll == 0 && fall == 0 { + None + } else { + Some(ContentLight { + max_content_light_level: cll, + max_frame_average_light_level: fall, + }) + } + }); + + cfg.still_picture = matches.still_picture; + + cfg.quantizer = quantizer; + cfg.min_quantizer = matches.min_quantizer.unwrap_or(0); + cfg.bitrate = bitrate.checked_mul(1000).expect("Bitrate too high"); + cfg.reservoir_frame_delay = matches.reservoir_frame_delay; + + if let Some(rdo_frames) = matches.rdo_lookahead_frames { + cfg.speed_settings.rdo_lookahead_frames = rdo_frames; + } + + cfg.tune = matches.tune; + + if cfg.tune == Tune::Psychovisual { + cfg.speed_settings.transform.tx_domain_distortion = false; + } + + cfg.tile_cols = matches.tile_cols; + cfg.tile_rows = matches.tile_rows; + + cfg.tiles = matches.tiles.unwrap_or(0); + + if cfg.tile_cols > 64 || cfg.tile_rows > 64 { + panic!("Tile columns and rows may not be greater than 64"); + } + + if let Some(table_file) = matches.film_grain_table.as_ref() { + let contents = std::fs::read_to_string(table_file) + .expect("Failed to read film grain table file"); + let table = av1_grain::parse_grain_table(&contents) + .expect("Failed to parse film grain table"); + if !table.is_empty() { + cfg.film_grain_params = Some(table); + } + } + + if let Some(frame_rate) = matches.frame_rate { + cfg.time_base = Rational::new(matches.time_scale, frame_rate); + } + + cfg.low_latency = matches.low_latency; + // Disables scene_detection + if matches.no_scene_detection { + cfg.speed_settings.scene_detection_mode = SceneDetectionSpeed::None; + } + + Ok(cfg) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/decoder/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/decoder/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2021, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use rav1e::prelude::*; + +pub mod y4m; + +pub trait FrameBuilder { + fn new_frame(&self) -> Frame; +} + +pub trait Decoder: Send { + fn get_video_details(&self) -> VideoDetails; + fn read_frame>( + &mut self, ctx: &F, cfg: &VideoDetails, + ) -> Result, DecodeError>; +} + +#[derive(Debug)] +pub enum DecodeError { + EOF, + BadInput, + UnknownColorspace, + ParseError, + IoError, + MemoryLimitExceeded, +} + +#[derive(Debug, Clone, Copy)] +pub struct VideoDetails { + pub width: usize, + pub height: usize, + pub sample_aspect_ratio: Rational, + pub bit_depth: usize, + pub chroma_sampling: ChromaSampling, + pub chroma_sample_position: ChromaSamplePosition, + pub time_base: Rational, +} + +impl Default for VideoDetails { + fn default() -> Self { + VideoDetails { + width: 640, + height: 480, + sample_aspect_ratio: Rational { num: 1, den: 1 }, + bit_depth: 8, + chroma_sampling: ChromaSampling::Cs420, + chroma_sample_position: ChromaSamplePosition::Unknown, + time_base: Rational { num: 30, den: 1 }, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/decoder/y4m.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/y4m.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/decoder/y4m.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/decoder/y4m.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::io::Read; + +use crate::color::ChromaSampling::Cs400; +use crate::decoder::{DecodeError, Decoder, FrameBuilder, VideoDetails}; +use rav1e::prelude::*; + +impl Decoder for y4m::Decoder> { + fn get_video_details(&self) -> VideoDetails { + let width = self.get_width(); + let height = self.get_height(); + let aspect_ratio = self.get_pixel_aspect(); + let color_space = self.get_colorspace(); + let bit_depth = color_space.get_bit_depth(); + let (chroma_sampling, chroma_sample_position) = + map_y4m_color_space(color_space); + let framerate = self.get_framerate(); + let time_base = Rational::new(framerate.den as u64, framerate.num as u64); + + VideoDetails { + width, + height, + sample_aspect_ratio: if aspect_ratio.num == 0 && aspect_ratio.den == 0 { + Rational::new(1, 1) + } else { + Rational::new(aspect_ratio.num as u64, aspect_ratio.den as u64) + }, + bit_depth, + chroma_sampling, + chroma_sample_position, + time_base, + } + } + + fn read_frame>( + &mut self, ctx: &F, cfg: &VideoDetails, + ) -> Result, DecodeError> { + let bytes = self.get_bytes_per_sample(); + self + .read_frame() + .map(|frame| { + let mut f = ctx.new_frame(); + + let (chroma_width, _) = + cfg.chroma_sampling.get_chroma_dimensions(cfg.width, cfg.height); + + f.planes[0].copy_from_raw_u8( + frame.get_y_plane(), + cfg.width * bytes, + bytes, + ); + if cfg.chroma_sampling != Cs400 { + f.planes[1].copy_from_raw_u8( + frame.get_u_plane(), + chroma_width * bytes, + bytes, + ); + f.planes[2].copy_from_raw_u8( + frame.get_v_plane(), + chroma_width * bytes, + bytes, + ); + } + f + }) + .map_err(Into::into) + } +} + +impl From for DecodeError { + fn from(e: y4m::Error) -> DecodeError { + match e { + y4m::Error::EOF => DecodeError::EOF, + y4m::Error::BadInput => DecodeError::BadInput, + y4m::Error::UnknownColorspace => DecodeError::UnknownColorspace, + y4m::Error::ParseError(_) => DecodeError::ParseError, + y4m::Error::IoError(_) => DecodeError::IoError, + // Note that this error code has nothing to do with the system running out of memory, + // it means the y4m decoder has exceeded its memory allocation limit. + y4m::Error::OutOfMemory => DecodeError::MemoryLimitExceeded, + } + } +} + +pub const fn map_y4m_color_space( + color_space: y4m::Colorspace, +) -> (ChromaSampling, ChromaSamplePosition) { + use crate::ChromaSamplePosition::*; + use crate::ChromaSampling::*; + use y4m::Colorspace::*; + match color_space { + Cmono | Cmono12 => (Cs400, Unknown), + C420jpeg | C420paldv => (Cs420, Unknown), + C420mpeg2 => (Cs420, Vertical), + C420 | C420p10 | C420p12 => (Cs420, Colocated), + C422 | C422p10 | C422p12 => (Cs422, Colocated), + C444 | C444p10 | C444p12 => (Cs444, Colocated), + _ => unimplemented!(), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/error.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[derive(Debug, thiserror::Error)] +pub enum CliError { + #[error("Cannot parse option `{opt}`: {err}")] + ParseInt { opt: String, err: std::num::ParseIntError }, + #[error("{msg}")] + Message { msg: String }, + #[error("{msg}: {e}")] + Generic { msg: String, e: String }, +} + +impl CliError { + pub fn new(msg: &str) -> CliError { + CliError::Message { msg: msg.to_owned() } + } +} + +pub trait ToError: std::error::Error + Sized { + fn context(self, msg: &str) -> CliError { + CliError::Generic { msg: msg.to_owned(), e: self.to_string() } + } +} + +impl ToError for std::num::ParseIntError { + fn context(self, opt: &str) -> CliError { + CliError::ParseInt { opt: opt.to_lowercase(), err: self } + } +} + +impl ToError for std::io::Error {} +impl ToError for rav1e::InvalidConfig {} +impl ToError for rav1e::EncoderStatus {} +impl ToError for rav1e::config::RateControlError {} + +pub fn print_error(e: &dyn std::error::Error) { + error!("{}", e); + let mut cause = e.source(); + while let Some(e) = cause { + error!("Caused by: {}", e); + cause = e.source(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/kv.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/kv.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/kv.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/kv.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +#![allow(unused_variables)] +use serde::{ser, Serialize, Serializer}; +use thiserror::*; + +use std::fmt; + +struct KVString { + output: String, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)] +enum Error { + #[error("unsupported")] + Unsupported, +} + +impl ser::Error for Error { + #[cold] + fn custom(msg: T) -> Error { + Error::Unsupported + } +} + +/// Serialize a configuration as a Key-Value string. +pub fn to_string(value: &T) -> Result +where + T: Serialize, +{ + let mut serializer = KVString { output: String::new() }; + value.serialize(&mut serializer).map_err(|_| ())?; + Ok(serializer.output) +} + +impl Serializer for &mut KVString { + type Ok = (); + type Error = Error; + type SerializeSeq = ser::Impossible<(), Self::Error>; + type SerializeTuple = ser::Impossible<(), Self::Error>; + type SerializeTupleStruct = ser::Impossible<(), Self::Error>; + type SerializeTupleVariant = ser::Impossible<(), Self::Error>; + type SerializeMap = ser::Impossible<(), Self::Error>; + type SerializeStruct = Self; + type SerializeStructVariant = ser::Impossible<(), Self::Error>; + + fn serialize_bool(self, v: bool) -> Result { + self.output += if v { "true" } else { "false" }; + Ok(()) + } + fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { + self.output += &v.to_string(); + Ok(()) + } + + fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { + self.output += &v.to_string(); + Ok(()) + } + fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { + self.serialize_f64(f64::from(v)) + } + + fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { + self.output += &v.to_string(); + Ok(()) + } + fn serialize_char(self, v: char) -> Result { + unimplemented!() + } + fn serialize_str(self, v: &str) -> Result { + self.output += v; + Ok(()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + unimplemented!() + } + fn serialize_none(self) -> Result { + self.output += "None"; + Ok(()) + } + fn serialize_some( + self, value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + fn serialize_unit(self) -> Result { + self.output += ""; + Ok(()) + } + fn serialize_unit_struct( + self, name: &'static str, + ) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, name: &'static str, variant_index: u32, variant: &'static str, + ) -> Result { + self.serialize_str(variant) + } + + fn serialize_newtype_struct( + self, name: &'static str, value: &T, + ) -> Result + where + T: Serialize, + { + unimplemented!() + } + + fn serialize_newtype_variant( + self, name: &'static str, variant_index: u32, variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + unimplemented!() + } + + fn serialize_seq( + self, len: Option, + ) -> Result { + unimplemented!() + } + fn serialize_tuple( + self, len: usize, + ) -> Result { + unimplemented!() + } + fn serialize_tuple_struct( + self, name: &'static str, len: usize, + ) -> Result { + unimplemented!() + } + fn serialize_tuple_variant( + self, name: &'static str, variant_index: u32, variant: &'static str, + len: usize, + ) -> Result { + unimplemented!() + } + fn serialize_map( + self, len: Option, + ) -> Result { + unimplemented!() + } + fn serialize_struct( + self, name: &'static str, len: usize, + ) -> Result { + Ok(self) + } + fn serialize_struct_variant( + self, name: &'static str, variant_index: u32, variant: &'static str, + len: usize, + ) -> Result { + unimplemented!() + } +} + +impl<'a> ser::SerializeStruct for &mut KVString { + type Ok = (); + type Error = Error; + + // Assume a single flat struct for now + fn serialize_field( + &mut self, key: &'static str, value: &T, + ) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + if !self.output.is_empty() { + self.output += ", " + } + self.output += key; + self.output += " = "; + value.serialize(&mut **self) + } + + fn end(self) -> Result<(), Self::Error> { + Ok(()) + } +} + +#[cfg(test)] +mod test { + use rav1e::prelude::SpeedSettings; + + #[test] + fn serialize_speed_settings() { + for preset in 0..=10 { + let s = SpeedSettings::from_preset(preset); + let out = super::to_string(&s).unwrap(); + println!("preset {}: {}", preset, out); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/ivf.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/ivf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/ivf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/ivf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::Muxer; +use crate::error::*; +use ivf::*; +use rav1e::prelude::*; +use std::fs; +use std::fs::File; +use std::io; +use std::io::Write; +use std::path::Path; + +pub struct IvfMuxer { + output: Box, +} + +impl Muxer for IvfMuxer { + fn write_header( + &mut self, width: usize, height: usize, framerate_num: usize, + framerate_den: usize, + ) { + write_ivf_header( + &mut self.output, + width, + height, + framerate_num, + framerate_den, + ); + } + + #[profiling::function] + fn write_frame(&mut self, pts: u64, data: &[u8], _frame_type: FrameType) { + write_ivf_frame(&mut self.output, pts, data); + } + + fn flush(&mut self) -> io::Result<()> { + self.output.flush() + } +} + +cfg_if::cfg_if! { + if #[cfg(unix)] { + use std::os::unix::fs::*; + fn is_file>(path: P) -> bool { + fs::metadata(path).map(|meta| { + !meta.file_type().is_char_device() && !meta.file_type().is_socket() + }).unwrap_or(false) + } + } else { + fn is_file>(path: P) -> bool { + fs::metadata(path).is_ok() + } + } +} + +impl IvfMuxer { + pub fn check_file>(path: P) -> Result<(), CliError> { + if is_file(path.as_ref()) { + eprint!( + "File '{}' already exists. Overwrite ? [y/N] ", + path.as_ref().display() + ); + io::stdout().flush().unwrap(); + + let mut option_input = String::new(); + io::stdin() + .read_line(&mut option_input) + .expect("Failed to read option."); + + match option_input.as_str().trim() { + "y" | "Y" => return Ok(()), + _ => return Err(CliError::new("Not overwriting, exiting.")), + }; + } + Ok(()) + } + + pub fn open>( + path: P, + ) -> Result, CliError> { + let ivf = IvfMuxer { + output: match path.as_ref().to_str() { + Some("-") => Box::new(std::io::stdout()), + _ => Box::new( + File::create(path) + .map_err(|e| e.context("Cannot open output file"))?, + ), + }, + }; + Ok(Box::new(ivf)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +mod ivf; +use self::ivf::IvfMuxer; + +mod y4m; +pub use self::y4m::write_y4m_frame; + +use rav1e::prelude::*; + +use std::ffi::OsStr; +use std::io; +use std::path::Path; + +use crate::error::*; + +pub trait Muxer: Send { + fn write_header( + &mut self, width: usize, height: usize, framerate_num: usize, + framerate_den: usize, + ); + + fn write_frame(&mut self, pts: u64, data: &[u8], frame_type: FrameType); + + fn flush(&mut self) -> io::Result<()>; +} + +pub fn create_muxer>( + path: P, overwrite: bool, +) -> Result, CliError> { + if !overwrite { + IvfMuxer::check_file(path.as_ref())?; + } + + if let Some(path) = path.as_ref().to_str() { + if path == "-" { + return IvfMuxer::open(path); + } + } + + let ext = path + .as_ref() + .extension() + .and_then(OsStr::to_str) + .map(str::to_lowercase) + .unwrap_or_else(|| "ivf".into()); + + match &ext[..] { + "ivf" => IvfMuxer::open(path), + _e => { + panic!("{ext} is not a supported extension, please change to .ivf"); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/y4m.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/y4m.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/muxer/y4m.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/muxer/y4m.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,105 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::decoder::VideoDetails; +use rav1e::prelude::*; +use std::io::Write; +use std::slice; + +#[profiling::function] +pub fn write_y4m_frame( + y4m_enc: &mut y4m::Encoder>, rec: &Frame, + y4m_details: VideoDetails, +) { + let planes = + if y4m_details.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + let bytes_per_sample = if y4m_details.bit_depth > 8 { 2 } else { 1 }; + let (chroma_width, chroma_height) = y4m_details + .chroma_sampling + .get_chroma_dimensions(y4m_details.width, y4m_details.height); + let pitch_y = y4m_details.width * bytes_per_sample; + let pitch_uv = chroma_width * bytes_per_sample; + + let (mut rec_y, mut rec_u, mut rec_v) = ( + vec![128u8; pitch_y * y4m_details.height], + vec![128u8; pitch_uv * chroma_height], + vec![128u8; pitch_uv * chroma_height], + ); + + let (stride_y, stride_u, stride_v) = ( + rec.planes[0].cfg.stride, + rec.planes[1].cfg.stride, + rec.planes[2].cfg.stride, + ); + + for (line, line_out) in + rec.planes[0].data_origin().chunks(stride_y).zip(rec_y.chunks_mut(pitch_y)) + { + if y4m_details.bit_depth > 8 { + // SAFETY: This is essentially doing a transmute to u16, but safer. + unsafe { + line_out.copy_from_slice(slice::from_raw_parts::( + line.as_ptr() as *const u8, + pitch_y, + )); + } + } else { + line_out.copy_from_slice( + &line.iter().map(|&v| u8::cast_from(v)).collect::>() + [..pitch_y], + ); + } + } + + if planes > 1 { + for (line, line_out) in rec.planes[1] + .data_origin() + .chunks(stride_u) + .zip(rec_u.chunks_mut(pitch_uv)) + { + if y4m_details.bit_depth > 8 { + // SAFETY: This is essentially doing a transmute to u16, but safer. + unsafe { + line_out.copy_from_slice(slice::from_raw_parts::( + line.as_ptr() as *const u8, + pitch_uv, + )); + } + } else { + line_out.copy_from_slice( + &line.iter().map(|&v| u8::cast_from(v)).collect::>() + [..pitch_uv], + ); + } + } + for (line, line_out) in rec.planes[2] + .data_origin() + .chunks(stride_v) + .zip(rec_v.chunks_mut(pitch_uv)) + { + if y4m_details.bit_depth > 8 { + // SAFETY: This is essentially doing a transmute to u16, but safer. + unsafe { + line_out.copy_from_slice(slice::from_raw_parts::( + line.as_ptr() as *const u8, + pitch_uv, + )); + } + } else { + line_out.copy_from_slice( + &line.iter().map(|&v| u8::cast_from(v)).collect::>() + [..pitch_uv], + ); + } + } + } + + let rec_frame = y4m::Frame::new([&rec_y, &rec_u, &rec_v], None); + y4m_enc.write_frame(&rec_frame).unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/rav1e-ch.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e-ch.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/rav1e-ch.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e-ch.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,600 @@ +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[macro_use] +extern crate log; + +mod common; +mod decoder; +mod error; +#[cfg(feature = "serialize")] +mod kv; +mod muxer; +mod stats; + +use crate::common::*; +use crate::error::*; +use crate::stats::*; +use rav1e::config::CpuFeatureLevel; +use rav1e::prelude::*; + +use crate::decoder::{Decoder, FrameBuilder, VideoDetails}; +use crate::muxer::*; +use std::fs::File; +use std::io::{Read, Seek, Write}; +use std::sync::Arc; + +impl FrameBuilder for FrameSender { + fn new_frame(&self) -> Frame { + FrameSender::new_frame(self) + } +} + +struct Source { + limit: usize, + count: usize, + input: D, + #[cfg(all(unix, feature = "signal-hook"))] + exit_requested: Arc, +} + +impl Source { + cfg_if::cfg_if! { + if #[cfg(all(unix, feature = "signal-hook"))] { + fn new(limit: usize, input: D) -> Self { + use signal_hook::{flag, consts}; + + // Make sure double CTRL+C and similar kills + let exit_requested = Arc::new(std::sync::atomic::AtomicBool::new(false)); + for sig in consts::TERM_SIGNALS { + // When terminated by a second term signal, exit with exit code 1. + // This will do nothing the first time (because term_now is false). + flag::register_conditional_shutdown(*sig, 1, Arc::clone(&exit_requested)).unwrap(); + // But this will "arm" the above for the second time, by setting it to true. + // The order of registering these is important, if you put this one first, it will + // first arm and then terminate ‒ all in the first round. + flag::register(*sig, Arc::clone(&exit_requested)).unwrap(); + } + Self { limit, input, count: 0, exit_requested, } + } + } else { + fn new(limit: usize, input: D) -> Self { + Self { limit, input, count: 0, } + } + } + } + + fn read_frame( + &mut self, send_frame: &mut FrameSender, video_info: VideoDetails, + ) -> bool { + if self.limit != 0 && self.count == self.limit { + return false; + } + + #[cfg(all(unix, feature = "signal-hook"))] + { + if self.exit_requested.load(std::sync::atomic::Ordering::SeqCst) { + return false; + } + } + match self.input.read_frame(send_frame, &video_info) { + Ok(frame) => { + self.count += 1; + let _ = send_frame.send(frame); + true + } + _ => false, + } + } +} + +fn do_encode( + cfg: Config, verbose: Verboseness, mut progress: ProgressInfo, + output: &mut dyn Muxer, mut source: Source, pass1file: Option, + pass2file: Option, + mut y4m_enc: Option>>, + metrics_enabled: MetricsEnabled, +) -> Result<(), CliError> { + let ((mut send_frame, receive_packet), (send_rc, receive_rc)) = + match (pass1file.is_some(), pass2file.is_some()) { + (true, true) => { + let (channel, (send_rc, receive_rc)) = cfg + .new_multipass_channel::() + .map_err(|e| e.context("Invalid setup"))?; + (channel, (Some(send_rc), Some(receive_rc))) + } + (true, false) => { + let (channel, receive_rc) = cfg + .new_firstpass_channel() + .map_err(|e| e.context("Invalid setup"))?; + (channel, (None, Some(receive_rc))) + } + (false, true) => { + let (channel, send_rc) = cfg + .new_secondpass_channel() + .map_err(|e| e.context("Invalid setup"))?; + (channel, (Some(send_rc), None)) + } + (false, false) => { + let channel = + cfg.new_channel().map_err(|e| e.context("Invalid setup"))?; + (channel, (None, None)) + } + }; + + let y4m_details = source.input.get_video_details(); + + crossbeam::thread::scope(move |s| -> Result<(), CliError> { + // Receive pass data + let receive_pass_data = s.spawn(move |_| -> Result<(), CliError> { + if let (Some(mut passfile), Some(receive_rc)) = (pass1file, receive_rc) { + let len = receive_rc.summary_size(); + let buf = vec![0u8; len]; + + passfile + .write_all(&(len as u64).to_be_bytes()) + .map_err(|e| e.context("Unable to write to two-pass data file."))?; + + passfile + .write_all(&buf) + .map_err(|e| e.context("Unable to write to two-pass data file."))?; + for data in receive_rc.iter() { + match data { + RcData::Frame(outbuf) => { + let len = outbuf.len() as u64; + passfile.write_all(&len.to_be_bytes()).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + + passfile.write_all(&outbuf).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + } + RcData::Summary(outbuf) => { + // Write an end marker + passfile.write_all(&0u64.to_be_bytes()).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + + // The last packet of rate control data we get is the summary data. + // Let's put it at the start of the file. + passfile.seek(std::io::SeekFrom::Start(0)).map_err(|e| { + e.context("Unable to seek in the two-pass data file.") + })?; + let len = outbuf.len() as u64; + + passfile.write_all(&len.to_be_bytes()).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + + passfile.write_all(&outbuf).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + } + } + } + } + Ok(()) + }); + + // Send frames + let send_frames = s.spawn(move |_| -> Result<(), CliError> { + while source.read_frame(&mut send_frame, y4m_details) {} + + // send_frame.result() + Ok(()) + }); + + // Send pass data + let send_pass_data = s.spawn(move |_| -> Result<(), CliError> { + if let (Some(mut passfile), Some(mut send_rc)) = (pass2file, send_rc) { + let mut buflen = [0u8; 8]; + + passfile + .read_exact(&mut buflen) + .map_err(|e| e.context("Unable to read the two-pass data file."))?; + + let mut data = vec![0u8; u64::from_be_bytes(buflen) as usize]; + + passfile + .read_exact(&mut data) + .map_err(|e| e.context("Unable to read the two-pass data file."))?; + + while send_rc.send(RcData::Frame(data.into_boxed_slice())).is_ok() { + passfile.read_exact(&mut buflen).map_err(|e| { + e.context("Unable to read the two-pass data file.") + })?; + + if u64::from_be_bytes(buflen) == 0 { + break; + } + + data = vec![0u8; u64::from_be_bytes(buflen) as usize]; + + passfile.read_exact(&mut data).map_err(|e| { + e.context("Unable to read the two-pass data file.") + })?; + } + } + + Ok(()) + }); + + // Receive Packets + let receive_packets = s.spawn(move |_| -> Result<(), CliError> { + for pkt in receive_packet.iter() { + output.write_frame( + pkt.input_frameno as u64, + pkt.data.as_ref(), + pkt.frame_type, + ); + output.flush().unwrap(); + if let (Some(ref mut y4m_enc_uw), Some(ref rec)) = + (y4m_enc.as_mut(), &pkt.rec) + { + write_y4m_frame(y4m_enc_uw, rec, y4m_details); + } + let summary = build_frame_summary( + pkt, + y4m_details.bit_depth, + y4m_details.chroma_sampling, + metrics_enabled, + ); + + if verbose != Verboseness::Quiet { + progress.add_frame(summary.clone()); + if verbose == Verboseness::Verbose { + info!("{} - {}", summary, progress); + } else { + // Print a one-line progress indicator that overrides itself with every update + eprint!("\r{} ", progress); + }; + } + } + + if verbose != Verboseness::Quiet { + if verbose == Verboseness::Verbose { + // Clear out the temporary progress indicator + eprint!("\r"); + } + progress.print_summary(verbose == Verboseness::Verbose); + } + + // receive_packet.result() + Ok(()) + }); + + send_pass_data.join().expect("The send pass data thread panicked ")?; + receive_pass_data + .join() + .expect("The receive pass data thread panicked")?; + send_frames.join().expect("The send frames thread panicked")?; + receive_packets.join().expect("The receive packets thread panicked")?; + + Ok(()) + }) + .unwrap() +} + +fn main() -> Result<(), Box> { + init_logger(); + + #[cfg(feature = "tracing")] + let (chrome_layer, _guard) = + tracing_chrome::ChromeLayerBuilder::new().build(); + + #[cfg(feature = "tracing")] + { + use tracing_subscriber::layer::SubscriberExt; + tracing::subscriber::set_global_default( + tracing_subscriber::registry().with(chrome_layer), + ) + .unwrap(); + } + + run().map_err(|e| { + error::print_error(&e); + Box::new(e) as Box + }) +} + +fn init_logger() { + use std::str::FromStr; + fn level_colored(l: log::Level) -> console::StyledObject<&'static str> { + use console::style; + use log::Level; + match l { + Level::Trace => style("??").dim(), + Level::Debug => style("? ").dim(), + Level::Info => style("> ").green(), + Level::Warn => style("! ").yellow(), + Level::Error => style("!!").red(), + } + } + + let level = std::env::var("RAV1E_LOG") + .ok() + .and_then(|l| log::LevelFilter::from_str(&l).ok()) + .unwrap_or(log::LevelFilter::Info); + + fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "{level} {message}", + level = level_colored(record.level()), + message = message, + )); + }) + // set the default log level. to filter out verbose log messages from dependencies, set + // this to Warn and overwrite the log level for your crate. + .level(log::LevelFilter::Warn) + // change log levels for individual modules. Note: This looks for the record's target + // field which defaults to the module path but can be overwritten with the `target` + // parameter: + // `info!(target="special_target", "This log message is about special_target");` + .level_for("rav1e", level) + .level_for("rav1e_ch", level) + // output to stdout + .chain(std::io::stderr()) + .apply() + .unwrap(); +} + +cfg_if::cfg_if! { + if #[cfg(any(target_os = "windows", target_arch = "wasm32"))] { + fn print_rusage() { + eprintln!("Resource usage reporting is not currently supported on this platform"); + } + } else { + fn print_rusage() { + // SAFETY: This uses an FFI, it is safe because we call it correctly. + let (utime, stime, maxrss) = unsafe { + let mut usage = std::mem::zeroed(); + let _ = libc::getrusage(libc::RUSAGE_SELF, &mut usage); + (usage.ru_utime, usage.ru_stime, usage.ru_maxrss) + }; + eprintln!( + "user time: {} s", + utime.tv_sec as f64 + utime.tv_usec as f64 / 1_000_000f64 + ); + eprintln!( + "system time: {} s", + stime.tv_sec as f64 + stime.tv_usec as f64 / 1_000_000f64 + ); + eprintln!("maximum rss: {} KB", maxrss); + } + } +} + +fn run() -> Result<(), error::CliError> { + let mut cli = parse_cli()?; + // Maximum frame size by specification + maximum y4m header + let limit = y4m::Limits { + // Use saturating operations to gracefully handle 32-bit architectures + bytes: 64usize + .saturating_mul(64) + .saturating_mul(4096) + .saturating_mul(2304) + .saturating_add(1024), + }; + let mut y4m_dec = match y4m::Decoder::new_with_limits(cli.io.input, limit) { + Err(e) => { + return Err(CliError::new(match e { + y4m::Error::ParseError(_) => { + "Could not parse input video. Is it a y4m file?" + } + y4m::Error::IoError(_) => { + "Could not read input file. Check that the path is correct and you have read permissions." + } + y4m::Error::UnknownColorspace => { + "Unknown colorspace or unsupported bit depth." + } + y4m::Error::OutOfMemory => "The video's frame size exceeds the limit.", + y4m::Error::EOF => "Unexpected end of input.", + y4m::Error::BadInput => "Bad y4m input parameters provided.", + })) + } + Ok(d) => d, + }; + let video_info = y4m_dec.get_video_details(); + let y4m_enc = cli.io.rec.map(|rec| { + y4m::encode( + video_info.width, + video_info.height, + y4m::Ratio::new( + video_info.time_base.den as usize, + video_info.time_base.num as usize, + ), + ) + .with_colorspace(y4m_dec.get_colorspace()) + .with_pixel_aspect(y4m::Ratio { + num: video_info.sample_aspect_ratio.num as usize, + den: video_info.sample_aspect_ratio.den as usize, + }) + .write_header(rec) + .unwrap() + }); + + match video_info.bit_depth { + 8 | 10 | 12 => {} + _ => return Err(CliError::new("Unsupported bit depth")), + } + + cli.enc.width = video_info.width; + cli.enc.height = video_info.height; + cli.enc.bit_depth = video_info.bit_depth; + cli.enc.sample_aspect_ratio = video_info.sample_aspect_ratio; + cli.enc.chroma_sampling = video_info.chroma_sampling; + cli.enc.chroma_sample_position = video_info.chroma_sample_position; + + // If no pixel range is specified via CLI, assume limited, + // as it is the default for the Y4M format. + if !cli.color_range_specified { + cli.enc.pixel_range = PixelRange::Limited; + } + + if !cli.override_time_base { + cli.enc.time_base = video_info.time_base; + } + + if cli.photon_noise > 0 && cli.enc.film_grain_params.is_none() { + cli.enc.film_grain_params = Some(vec![generate_photon_noise_params( + 0, + u64::MAX, + NoiseGenArgs { + iso_setting: cli.photon_noise as u32 * 100, + width: video_info.width as u32, + height: video_info.height as u32, + transfer_function: if cli.enc.is_hdr() { + TransferFunction::SMPTE2084 + } else { + TransferFunction::BT1886 + }, + chroma_grain: false, + random_seed: None, + }, + )]); + } + + let mut rc = RateControlConfig::new(); + + let pass2file = match cli.pass2file_name { + Some(f) => { + let mut f = File::open(f).map_err(|e| { + e.context("Unable to open file for reading two-pass data") + })?; + let mut buflen = [0u8; 8]; + f.read_exact(&mut buflen) + .map_err(|e| e.context("Summary data too short"))?; + let len = i64::from_be_bytes(buflen); + let mut buf = vec![0u8; len as usize]; + + f.read_exact(&mut buf) + .map_err(|e| e.context("Summary data too short"))?; + + rc = RateControlConfig::from_summary_slice(&buf) + .map_err(|e| e.context("Invalid summary"))?; + + Some(f) + } + None => None, + }; + + let pass1file = match cli.pass1file_name { + Some(f) => { + let f = File::create(f).map_err(|e| { + e.context("Unable to open file for writing two-pass data") + })?; + rc = rc.with_emit_data(true); + Some(f) + } + None => None, + }; + + let cfg = Config::new() + .with_encoder_config(cli.enc.clone()) + .with_threads(cli.threads) + .with_rate_control(rc) + .with_parallel_gops(cli.slots); + + #[cfg(feature = "serialize")] + { + if let Some(save_config) = cli.save_config { + let mut out = File::create(save_config) + .map_err(|e| e.context("Cannot create configuration file"))?; + let s = toml::to_string(&cli.enc).unwrap(); + out + .write_all(s.as_bytes()) + .map_err(|e| e.context("Cannot write the configuration file"))? + } + } + + cli.io.output.write_header( + video_info.width, + video_info.height, + cli.enc.time_base.den as usize, + cli.enc.time_base.num as usize, + ); + + let tiling = + cfg.tiling_info().map_err(|e| e.context("Invalid configuration"))?; + if cli.verbose != Verboseness::Quiet { + info!("CPU Feature Level: {}", CpuFeatureLevel::default()); + + info!( + "Using y4m decoder: {}x{}p @ {}/{} fps, {}, {}-bit", + video_info.width, + video_info.height, + video_info.time_base.den, + video_info.time_base.num, + video_info.chroma_sampling, + video_info.bit_depth + ); + info!("Encoding settings: {}", cli.enc); + + if tiling.tile_count() == 1 { + info!("Using 1 tile"); + } else { + info!( + "Using {} tiles ({}x{})", + tiling.tile_count(), + tiling.cols, + tiling.rows + ); + } + } + + let progress = ProgressInfo::new( + Rational { num: video_info.time_base.den, den: video_info.time_base.num }, + if cli.limit == 0 { None } else { Some(cli.limit) }, + cli.metrics_enabled, + ); + + for _ in 0..cli.skip { + match y4m_dec.read_frame() { + Ok(f) => f, + Err(_) => { + return Err(CliError::new("Skipped more frames than in the input")) + } + }; + } + + let source = Source::new(cli.limit, y4m_dec); + + if video_info.bit_depth == 8 && !cli.force_highbitdepth { + do_encode::>>( + cfg, + cli.verbose, + progress, + &mut *cli.io.output, + source, + pass1file, + pass2file, + y4m_enc, + cli.metrics_enabled, + )? + } else { + do_encode::>>( + cfg, + cli.verbose, + progress, + &mut *cli.io.output, + source, + pass1file, + pass2file, + y4m_enc, + cli.metrics_enabled, + )? + } + if cli.benchmark { + print_rusage(); + } + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/rav1e.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/rav1e.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/rav1e.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,584 @@ +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[macro_use] +extern crate log; + +mod common; +mod decoder; +mod error; +#[cfg(feature = "serialize")] +mod kv; +mod muxer; +mod stats; + +use crate::common::*; +use crate::error::*; +use crate::stats::*; +use rav1e::config::CpuFeatureLevel; +use rav1e::prelude::*; + +use crate::decoder::{Decoder, FrameBuilder, VideoDetails}; +use crate::muxer::*; +use std::fs::File; +use std::io::{Read, Seek, Write}; +use std::process::exit; +use std::sync::Arc; + +impl FrameBuilder for Context { + fn new_frame(&self) -> Frame { + Context::new_frame(self) + } +} + +struct Source { + limit: usize, + count: usize, + input: D, + #[cfg(all(unix, feature = "signal-hook"))] + exit_requested: Arc, +} + +impl Source { + cfg_if::cfg_if! { + if #[cfg(all(unix, feature = "signal-hook"))] { + fn new(limit: usize, input: D) -> Self { + use signal_hook::{flag, consts}; + + // Make sure double CTRL+C and similar kills + let exit_requested = Arc::new(std::sync::atomic::AtomicBool::new(false)); + for sig in consts::TERM_SIGNALS { + // When terminated by a second term signal, exit with exit code 1. + // This will do nothing the first time (because term_now is false). + flag::register_conditional_shutdown(*sig, 1, Arc::clone(&exit_requested)).unwrap(); + // But this will "arm" the above for the second time, by setting it to true. + // The order of registering these is important, if you put this one first, it will + // first arm and then terminate ‒ all in the first round. + flag::register(*sig, Arc::clone(&exit_requested)).unwrap(); + } + + Self { limit, input, count: 0, exit_requested, } + } + } else { + #[allow(clippy::missing_const_for_fn)] + fn new(limit: usize, input: D) -> Self { + Self { limit, input, count: 0, } + } + } + } + + #[profiling::function] + fn read_frame( + &mut self, ctx: &mut Context, video_info: VideoDetails, + ) -> Result<(), CliError> { + if self.limit != 0 && self.count == self.limit { + ctx.flush(); + return Ok(()); + } + + #[cfg(all(unix, feature = "signal-hook"))] + { + if self.exit_requested.load(std::sync::atomic::Ordering::SeqCst) { + ctx.flush(); + return Ok(()); + } + } + + match self.input.read_frame(ctx, &video_info) { + Ok(frame) => { + match video_info.bit_depth { + 8 | 10 | 12 => {} + _ => return Err(CliError::new("Unsupported bit depth")), + } + self.count += 1; + let _ = ctx.send_frame(Some(Arc::new(frame))); + } + _ => { + ctx.flush(); + } + }; + Ok(()) + } +} + +// Encode and write a frame. +// Returns frame information in a `Result`. +#[profiling::function] +fn process_frame( + ctx: &mut Context, output_file: &mut dyn Muxer, source: &mut Source, + pass1file: Option<&mut File>, pass2file: Option<&mut File>, + mut y4m_enc: Option<&mut y4m::Encoder>>, + metrics_cli: MetricsEnabled, +) -> Result>, CliError> { + let y4m_details = source.input.get_video_details(); + let mut frame_summaries = Vec::new(); + let mut pass1file = pass1file; + let mut pass2file = pass2file; + + // Submit first pass data to pass 2. + if let Some(passfile) = pass2file.as_mut() { + while ctx.rc_second_pass_data_required() > 0 { + let mut buflen = [0u8; 8]; + passfile + .read_exact(&mut buflen) + .map_err(|e| e.context("Unable to read the two-pass data file."))?; + let mut data = vec![0u8; u64::from_be_bytes(buflen) as usize]; + + passfile + .read_exact(&mut data) + .map_err(|e| e.context("Unable to read the two-pass data file."))?; + + ctx + .rc_send_pass_data(&data) + .map_err(|e| e.context("Corrupted first pass data"))?; + } + } + + let pkt_wrapped = ctx.receive_packet(); + let (ret, emit_pass_data) = match pkt_wrapped { + Ok(pkt) => { + output_file.write_frame( + pkt.input_frameno, + pkt.data.as_ref(), + pkt.frame_type, + ); + if let (Some(ref mut y4m_enc_uw), Some(ref rec)) = + (y4m_enc.as_mut(), &pkt.rec) + { + write_y4m_frame(y4m_enc_uw, rec, y4m_details); + } + frame_summaries.push(build_frame_summary( + pkt, + y4m_details.bit_depth, + y4m_details.chroma_sampling, + metrics_cli, + )); + Ok((Some(frame_summaries), true)) + } + Err(EncoderStatus::NeedMoreData) => { + source.read_frame(ctx, y4m_details)?; + Ok((Some(frame_summaries), false)) + } + Err(EncoderStatus::EnoughData) => { + unreachable!() + } + Err(EncoderStatus::LimitReached) => Ok((None, true)), + Err(e @ EncoderStatus::Failure) => { + Err(e.context("Failed to encode video")) + } + Err(e @ EncoderStatus::NotReady) => { + Err(e.context("Mismanaged handling of two-pass stats data")) + } + Err(EncoderStatus::Encoded) => Ok((Some(frame_summaries), true)), + }?; + + // Save first pass data from pass 1. + if let Some(passfile) = pass1file.as_mut() { + if emit_pass_data { + match ctx.rc_receive_pass_data() { + Some(RcData::Frame(outbuf)) => { + let len = outbuf.len() as u64; + passfile.write_all(&len.to_be_bytes()).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + + passfile.write_all(&outbuf).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + } + Some(RcData::Summary(outbuf)) => { + // The last packet of rate control data we get is the summary data. + // Let's put it at the start of the file. + passfile.rewind().map_err(|e| { + e.context("Unable to seek in the two-pass data file.") + })?; + let len = outbuf.len() as u64; + + passfile.write_all(&len.to_be_bytes()).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + + passfile.write_all(&outbuf).map_err(|e| { + e.context("Unable to write to two-pass data file.") + })?; + } + None => {} + } + } + } + + Ok(ret) +} + +fn do_encode( + cfg: Config, verbose: Verboseness, mut progress: ProgressInfo, + output: &mut dyn Muxer, mut source: Source, mut pass1file: Option, + mut pass2file: Option, + mut y4m_enc: Option>>, + metrics_enabled: MetricsEnabled, +) -> Result<(), CliError> { + let mut ctx: Context = + cfg.new_context().map_err(|e| e.context("Invalid encoder settings"))?; + + // Let's write down a placeholder. + if let Some(passfile) = pass1file.as_mut() { + let len = ctx.rc_summary_size(); + let buf = vec![0u8; len]; + + passfile + .write_all(&(len as u64).to_be_bytes()) + .map_err(|e| e.context("Unable to write to two-pass data file."))?; + + passfile + .write_all(&buf) + .map_err(|e| e.context("Unable to write to two-pass data file."))?; + } + + while let Some(frame_info) = process_frame( + &mut ctx, + &mut *output, + &mut source, + pass1file.as_mut(), + pass2file.as_mut(), + y4m_enc.as_mut(), + metrics_enabled, + )? { + if verbose != Verboseness::Quiet { + for frame in frame_info { + progress.add_frame(frame.clone()); + if verbose == Verboseness::Verbose { + info!("{} - {}", frame, progress); + } else { + // Print a one-line progress indicator that overrides itself with every update + eprint!("\r{progress} "); + }; + } + + output.flush().unwrap(); + } + } + if verbose != Verboseness::Quiet { + if verbose == Verboseness::Verbose { + // Clear out the temporary progress indicator + eprint!("\r"); + } + progress.print_summary(verbose == Verboseness::Verbose); + } + Ok(()) +} + +fn main() { + init_logger(); + + #[cfg(feature = "tracing")] + let (chrome_layer, _guard) = + tracing_chrome::ChromeLayerBuilder::new().build(); + + #[cfg(feature = "tracing")] + { + use tracing_subscriber::layer::SubscriberExt; + tracing::subscriber::set_global_default( + tracing_subscriber::registry().with(chrome_layer), + ) + .unwrap(); + } + + run().unwrap_or_else(|e| { + error::print_error(&e); + exit(1); + }); +} + +fn init_logger() { + use std::str::FromStr; + fn level_colored(l: log::Level) -> console::StyledObject<&'static str> { + use console::style; + use log::Level; + match l { + Level::Trace => style("??").dim(), + Level::Debug => style("? ").dim(), + Level::Info => style("> ").green(), + Level::Warn => style("! ").yellow(), + Level::Error => style("!!").red(), + } + } + + let level = std::env::var("RAV1E_LOG") + .ok() + .and_then(|l| log::LevelFilter::from_str(&l).ok()) + .unwrap_or(log::LevelFilter::Info); + + fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "{level} {message}", + level = level_colored(record.level()), + message = message, + )); + }) + // set the default log level. to filter out verbose log messages from dependencies, set + // this to Warn and overwrite the log level for your crate. + .level(log::LevelFilter::Warn) + // change log levels for individual modules. Note: This looks for the record's target + // field which defaults to the module path but can be overwritten with the `target` + // parameter: + // `info!(target="special_target", "This log message is about special_target");` + .level_for("rav1e", level) + // output to stdout + .chain(std::io::stderr()) + .apply() + .unwrap(); +} + +cfg_if::cfg_if! { + if #[cfg(any(target_os = "windows", target_arch = "wasm32"))] { + fn print_rusage() { + eprintln!("Resource usage reporting is not currently supported on this platform"); + } + } else { + fn print_rusage() { + // SAFETY: This uses an FFI, it is safe because we call it correctly. + let (utime, stime, maxrss) = unsafe { + let mut usage = std::mem::zeroed(); + let _ = libc::getrusage(libc::RUSAGE_SELF, &mut usage); + (usage.ru_utime, usage.ru_stime, usage.ru_maxrss) + }; + eprintln!( + "user time: {} s", + utime.tv_sec as f64 + utime.tv_usec as f64 / 1_000_000f64 + ); + eprintln!( + "system time: {} s", + stime.tv_sec as f64 + stime.tv_usec as f64 / 1_000_000f64 + ); + eprintln!("maximum rss: {maxrss} KB"); + } + } +} + +fn run() -> Result<(), error::CliError> { + let mut cli = parse_cli()?; + // Maximum frame size by specification + maximum y4m header + let limit = y4m::Limits { + // Use saturating operations to gracefully handle 32-bit architectures + bytes: 64usize + .saturating_mul(64) + .saturating_mul(4096) + .saturating_mul(2304) + .saturating_add(1024), + }; + let mut y4m_dec = match y4m::Decoder::new_with_limits(cli.io.input, limit) { + Err(e) => { + return Err(CliError::new(match e { + y4m::Error::ParseError(_) => { + "Could not parse input video. Is it a y4m file?" + } + y4m::Error::IoError(_) => { + "Could not read input file. Check that the path is correct and you have read permissions." + } + y4m::Error::UnknownColorspace => { + "Unknown colorspace or unsupported bit depth." + } + y4m::Error::OutOfMemory => "The video's frame size exceeds the limit.", + y4m::Error::EOF => "Unexpected end of input.", + y4m::Error::BadInput => "Bad y4m input parameters provided.", + })) + } + Ok(d) => d, + }; + let video_info = y4m_dec.get_video_details(); + let y4m_enc = cli.io.rec.map(|rec| { + y4m::encode( + video_info.width, + video_info.height, + y4m::Ratio::new( + video_info.time_base.den as usize, + video_info.time_base.num as usize, + ), + ) + .with_colorspace(y4m_dec.get_colorspace()) + .with_pixel_aspect(y4m::Ratio { + num: video_info.sample_aspect_ratio.num as usize, + den: video_info.sample_aspect_ratio.den as usize, + }) + .write_header(rec) + .unwrap() + }); + + cli.enc.width = video_info.width; + cli.enc.height = video_info.height; + cli.enc.sample_aspect_ratio = video_info.sample_aspect_ratio; + cli.enc.bit_depth = video_info.bit_depth; + cli.enc.chroma_sampling = video_info.chroma_sampling; + cli.enc.chroma_sample_position = video_info.chroma_sample_position; + + // If no pixel range is specified via CLI, assume limited, + // as it is the default for the Y4M format. + if !cli.color_range_specified { + cli.enc.pixel_range = PixelRange::Limited; + } + + if !cli.override_time_base { + cli.enc.time_base = video_info.time_base; + } + + if cli.photon_noise > 0 && cli.enc.film_grain_params.is_none() { + cli.enc.film_grain_params = Some(vec![generate_photon_noise_params( + 0, + u64::MAX, + NoiseGenArgs { + iso_setting: cli.photon_noise as u32 * 100, + width: video_info.width as u32, + height: video_info.height as u32, + transfer_function: if cli.enc.is_hdr() { + TransferFunction::SMPTE2084 + } else { + TransferFunction::BT1886 + }, + chroma_grain: false, + random_seed: None, + }, + )]); + } + + let mut rc = RateControlConfig::new(); + + let pass2file = match cli.pass2file_name { + Some(f) => { + let mut f = File::open(f).map_err(|e| { + e.context("Unable to open file for reading two-pass data") + })?; + let mut buflen = [0u8; 8]; + f.read_exact(&mut buflen) + .map_err(|e| e.context("Summary data too short"))?; + let len = i64::from_be_bytes(buflen); + let mut buf = vec![0u8; len as usize]; + + f.read_exact(&mut buf) + .map_err(|e| e.context("Summary data too short"))?; + + rc = RateControlConfig::from_summary_slice(&buf) + .map_err(|e| e.context("Invalid summary"))?; + + Some(f) + } + None => None, + }; + + let pass1file = match cli.pass1file_name { + Some(f) => { + let f = File::create(f).map_err(|e| { + e.context("Unable to open file for writing two-pass data") + })?; + rc = rc.with_emit_data(true); + Some(f) + } + None => None, + }; + + let cfg = Config::new() + .with_encoder_config(cli.enc.clone()) + .with_threads(cli.threads) + .with_rate_control(rc); + + #[cfg(feature = "serialize")] + { + if let Some(save_config) = cli.save_config { + let mut out = File::create(save_config) + .map_err(|e| e.context("Cannot create configuration file"))?; + let s = toml::to_string(&cli.enc).unwrap(); + out + .write_all(s.as_bytes()) + .map_err(|e| e.context("Cannot write the configuration file"))? + } + } + + cli.io.output.write_header( + video_info.width, + video_info.height, + cli.enc.time_base.den as usize, + cli.enc.time_base.num as usize, + ); + + let tiling = + cfg.tiling_info().map_err(|e| e.context("Invalid configuration"))?; + if cli.verbose != Verboseness::Quiet { + info!("CPU Feature Level: {}", CpuFeatureLevel::default()); + + info!( + "Using y4m decoder: {}x{}p @ {}/{} fps, {}, {}-bit", + video_info.width, + video_info.height, + video_info.time_base.den, + video_info.time_base.num, + video_info.chroma_sampling, + video_info.bit_depth + ); + info!("Encoding settings: {}", cli.enc); + + if tiling.tile_count() == 1 { + info!("Using 1 tile"); + } else { + info!( + "Using {} tiles ({}x{})", + tiling.tile_count(), + tiling.cols, + tiling.rows + ); + } + } + + let progress = ProgressInfo::new( + Rational { num: video_info.time_base.den, den: video_info.time_base.num }, + if cli.limit == 0 { None } else { Some(cli.limit) }, + cli.metrics_enabled, + ); + + for _ in 0..cli.skip { + match y4m_dec.read_frame() { + Ok(f) => f, + Err(_) => { + return Err(CliError::new("Skipped more frames than in the input")) + } + }; + } + + let source = Source::new(cli.limit, y4m_dec); + + if video_info.bit_depth == 8 && !cli.force_highbitdepth { + do_encode::>>( + cfg, + cli.verbose, + progress, + &mut *cli.io.output, + source, + pass1file, + pass2file, + y4m_enc, + cli.metrics_enabled, + )? + } else { + do_encode::>>( + cfg, + cli.verbose, + progress, + &mut *cli.io.output, + source, + pass1file, + pass2file, + y4m_enc, + cli.metrics_enabled, + )? + } + if cli.benchmark { + print_rusage(); + } + + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/stats.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/stats.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/bin/stats.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/bin/stats.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,777 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use av_metrics::video::*; +use rav1e::data::EncoderStats; +use rav1e::prelude::*; +use std::fmt; +use std::time::Instant; + +#[derive(Debug, Clone)] +pub struct FrameSummary { + /// Frame size in bytes + pub size: usize, + pub input_frameno: u64, + pub frame_type: FrameType, + /// Contains metrics such as PSNR, SSIM, etc. + pub metrics: QualityMetrics, + /// QP selected for the frame. + pub qp: u8, + /// Block-level encoding stats for the frame + pub enc_stats: EncoderStats, +} + +#[profiling::function] +pub fn build_frame_summary( + packets: Packet, bit_depth: usize, chroma_sampling: ChromaSampling, + metrics_cli: MetricsEnabled, +) -> FrameSummary { + let metrics_input_frame: &Frame = packets.source.as_ref().unwrap(); + let metrics_output_frame: &Frame = packets.rec.as_ref().unwrap(); + let encode_metrics: QualityMetrics = calculate_frame_metrics( + metrics_input_frame, + metrics_output_frame, + bit_depth, + chroma_sampling, + metrics_cli, + ); + FrameSummary { + size: packets.data.len(), + input_frameno: packets.input_frameno, + frame_type: packets.frame_type, + metrics: encode_metrics, + qp: packets.qp, + enc_stats: packets.enc_stats, + } +} + +impl fmt::Display for FrameSummary { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Input Frame {} - {} - {} bytes{}", + self.input_frameno, + self.frame_type, + self.size, + if let Some(psnr) = self.metrics.psnr { + format!( + " - PSNR: Y: {:.4} Cb: {:.4} Cr: {:.4}", + psnr.y, psnr.u, psnr.v + ) + } else { + String::new() + } + ) + } +} + +#[derive(Debug, Clone)] +pub struct ProgressInfo { + // Frame rate of the video + frame_rate: Rational, + // The length of the whole video, in frames, if known + total_frames: Option, + // The time the encode was started + time_started: Instant, + // List of frames encoded so far + frame_info: Vec, + // Video size so far in bytes. + // + // This value will be updated in the CLI very frequently, so we cache the previous value + // to reduce the overall complexity. + encoded_size: usize, + // Which Metrics to display during and at end of encode + metrics_enabled: MetricsEnabled, +} + +impl ProgressInfo { + pub fn new( + frame_rate: Rational, total_frames: Option, + metrics_enabled: MetricsEnabled, + ) -> Self { + Self { + frame_rate, + total_frames, + time_started: Instant::now(), + frame_info: Vec::with_capacity(total_frames.unwrap_or_default()), + encoded_size: 0, + metrics_enabled, + } + } + + pub fn add_frame(&mut self, frame: FrameSummary) { + self.encoded_size += frame.size; + self.frame_info.push(frame); + } + + pub fn frames_encoded(&self) -> usize { + self.frame_info.len() + } + + pub fn encoding_fps(&self) -> f64 { + let duration = Instant::now().duration_since(self.time_started); + self.frame_info.len() as f64 + / (duration.as_secs() as f64 + duration.subsec_millis() as f64 / 1000f64) + } + + pub fn video_fps(&self) -> f64 { + self.frame_rate.num as f64 / self.frame_rate.den as f64 + } + + // Returns the bitrate of the frames so far, in bits/second + pub fn bitrate(&self) -> usize { + let bits = self.encoded_size * 8; + let seconds = self.frame_info.len() as f64 / self.video_fps(); + (bits as f64 / seconds) as usize + } + + // Estimates the final filesize in bytes, if the number of frames is known + pub fn estimated_size(&self) -> usize { + self + .total_frames + .map(|frames| self.encoded_size * frames / self.frames_encoded()) + .unwrap_or_default() + } + + // Estimates the remaining encoding time in seconds, if the number of frames is known + pub fn estimated_time(&self) -> u64 { + self + .total_frames + .map(|frames| { + (frames - self.frames_encoded()) as f64 / self.encoding_fps() + }) + .unwrap_or_default() as u64 + } + + // Elapsed time in seconds + pub fn elapsed_time(&self) -> u64 { + Instant::now().duration_since(self.time_started).as_secs() + } + + // Number of frames of given type which appear in the video + fn get_frame_type_count(&self, frame_type: FrameType) -> usize { + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .count() + } + + fn get_frame_type_avg_size(&self, frame_type: FrameType) -> usize { + let count = self.get_frame_type_count(frame_type); + if count == 0 { + return 0; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.size) + .sum::() + / count + } + + fn get_frame_type_avg_qp(&self, frame_type: FrameType) -> f32 { + let count = self.get_frame_type_count(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.qp as f32) + .sum::() + / count as f32 + } + + fn get_block_count_by_frame_type(&self, frame_type: FrameType) -> usize { + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.block_size_counts.iter().sum::()) + .sum() + } + + fn get_tx_count_by_frame_type(&self, frame_type: FrameType) -> usize { + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.tx_type_counts.iter().sum::()) + .sum() + } + + fn get_bsize_pct_by_frame_type( + &self, bsize: BlockSize, frame_type: FrameType, + ) -> f32 { + let count = self.get_block_count_by_frame_type(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.block_size_counts[bsize as usize]) + .sum::() as f32 + / count as f32 + * 100. + } + + fn get_skip_pct_by_frame_type(&self, frame_type: FrameType) -> f32 { + let count = self.get_block_count_by_frame_type(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.skip_block_count) + .sum::() as f32 + / count as f32 + * 100. + } + + fn get_txtype_pct_by_frame_type( + &self, txtype: TxType, frame_type: FrameType, + ) -> f32 { + let count = self.get_tx_count_by_frame_type(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.tx_type_counts[txtype as usize]) + .sum::() as f32 + / count as f32 + * 100. + } + + fn get_luma_pred_count_by_frame_type(&self, frame_type: FrameType) -> usize { + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.luma_pred_mode_counts.iter().sum::()) + .sum() + } + + fn get_chroma_pred_count_by_frame_type( + &self, frame_type: FrameType, + ) -> usize { + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| { + frame.enc_stats.chroma_pred_mode_counts.iter().sum::() + }) + .sum() + } + + fn get_luma_pred_mode_pct_by_frame_type( + &self, pred_mode: PredictionMode, frame_type: FrameType, + ) -> f32 { + let count = self.get_luma_pred_count_by_frame_type(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.luma_pred_mode_counts[pred_mode as usize]) + .sum::() as f32 + / count as f32 + * 100. + } + + fn get_chroma_pred_mode_pct_by_frame_type( + &self, pred_mode: PredictionMode, frame_type: FrameType, + ) -> f32 { + let count = self.get_chroma_pred_count_by_frame_type(frame_type); + if count == 0 { + return 0.; + } + self + .frame_info + .iter() + .filter(|frame| frame.frame_type == frame_type) + .map(|frame| frame.enc_stats.chroma_pred_mode_counts[pred_mode as usize]) + .sum::() as f32 + / count as f32 + * 100. + } + + pub fn print_summary(&self, verbose: bool) { + eprint!("\r"); + info!("{}", self); + info!("----------"); + self.print_frame_type_summary(FrameType::KEY); + self.print_frame_type_summary(FrameType::INTER); + self.print_frame_type_summary(FrameType::INTRA_ONLY); + self.print_frame_type_summary(FrameType::SWITCH); + if verbose { + self.print_block_type_summary(); + self.print_transform_type_summary(); + self.print_prediction_modes_summary(); + } + match self.metrics_enabled { + MetricsEnabled::None => info!("----"), + MetricsEnabled::Psnr => self.print_video_psnr(), + MetricsEnabled::All => { + self.print_video_psnr(); + self.print_video_all(); + } + } + } + + fn print_frame_type_summary(&self, frame_type: FrameType) { + let count = self.get_frame_type_count(frame_type); + let size = self.get_frame_type_avg_size(frame_type); + let avg_qp = self.get_frame_type_avg_qp(frame_type); + info!( + "{:17} {:>6} | avg QP: {:6.2} | avg size: {:>7} B", + format!("{frame_type}:"), + count, + avg_qp, + size + ); + } + + fn print_video_psnr(&self) { + info!("----------"); + let psnr_y = sum_metric(&self.frame_info, |fi| fi.metrics.psnr.unwrap().y); + let psnr_u = sum_metric(&self.frame_info, |fi| fi.metrics.psnr.unwrap().u); + let psnr_v = sum_metric(&self.frame_info, |fi| fi.metrics.psnr.unwrap().v); + let psnr_avg = + sum_metric(&self.frame_info, |fi| fi.metrics.psnr.unwrap().avg); + info!( + "Mean PSNR: Avg: {:.4} Y: {:.4} Cb: {:.4} Cr: {:.4}", + psnr_avg, psnr_y, psnr_u, psnr_v + ); + } + fn print_video_all(&self) { + info!("----------"); + let psnr_hvs = + sum_metric(&self.frame_info, |fi| fi.metrics.psnr_hvs.unwrap().avg); + let ssim = sum_metric(&self.frame_info, |fi| fi.metrics.ssim.unwrap().avg); + let ms_ssim = + sum_metric(&self.frame_info, |fi| fi.metrics.ms_ssim.unwrap().avg); + let ciede = sum_metric(&self.frame_info, |fi| fi.metrics.ciede.unwrap()); + info!("PSNR HVS: {:.4}", psnr_hvs); + info!("SSIM: {:.4} MS SSIM: {:.4}", ssim, ms_ssim); + info!("CIEDE2000: {:.4}", ciede); + info!("----------"); + } + + fn print_block_type_summary(&self) { + self.print_block_type_summary_for_frame_type(FrameType::KEY, 'I'); + self.print_block_type_summary_for_frame_type(FrameType::INTER, 'P'); + } + + fn print_block_type_summary_for_frame_type( + &self, frame_type: FrameType, type_label: char, + ) { + info!("----------"); + info!( + "bsize {}: {:>6} {:>6} {:>6} {:>6} {:>6} {:>6}", + type_label, "x128", "x64", "x32", "x16", "x8", "x4" + ); + info!( + " 128x: {:>5.1}% {:>5.1}% {}", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_128X128, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_128X64, frame_type), + if frame_type == FrameType::INTER { + format!("skip: {:>5.1}%", self.get_skip_pct_by_frame_type(frame_type)) + } else { + String::new() + } + ); + info!( + " 64x: {:>5.1}% {:>5.1}% {:>5.1}% {:>5.1}%", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_64X128, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_64X64, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_64X32, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_64X16, frame_type), + ); + info!( + " 32x: {:>5.1}% {:>5.1}% {:>5.1}% {:>5.1}%", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_32X64, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_32X32, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_32X16, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_32X8, frame_type), + ); + info!( + " 16x: {:>5.1}% {:>5.1}% {:>5.1}% {:>5.1}% {:>5.1}%", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_16X64, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_16X32, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_16X16, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_16X8, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_16X4, frame_type), + ); + info!( + " 8x: {:>5.1}% {:>5.1}% {:>5.1}% {:>5.1}%", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_8X32, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_8X16, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_8X8, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_8X4, frame_type), + ); + info!( + " 4x: {:>5.1}% {:>5.1}% {:>5.1}%", + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_4X16, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_4X8, frame_type), + self.get_bsize_pct_by_frame_type(BlockSize::BLOCK_4X4, frame_type), + ); + } + + fn print_transform_type_summary(&self) { + info!("----------"); + self.print_transform_type_summary_by_frame_type(FrameType::KEY, 'I'); + self.print_transform_type_summary_by_frame_type(FrameType::INTER, 'P'); + } + + fn print_transform_type_summary_by_frame_type( + &self, frame_type: FrameType, type_label: char, + ) { + info!( + "txtypes {}: DCT_DCT: {:.1}% | ADST_DCT: {:.1}% | DCT_ADST: {:.1}% | ADST_ADST: {:.1}%", + type_label, + self.get_txtype_pct_by_frame_type(TxType::DCT_DCT, frame_type), + self.get_txtype_pct_by_frame_type(TxType::ADST_DCT, frame_type), + self.get_txtype_pct_by_frame_type(TxType::DCT_ADST, frame_type), + self.get_txtype_pct_by_frame_type(TxType::ADST_ADST, frame_type) + ); + info!( + " IDTX: {:.1}% | V_DCT: {:.1}% | H_DCT: {:.1}%", + self.get_txtype_pct_by_frame_type(TxType::IDTX, frame_type), + self.get_txtype_pct_by_frame_type(TxType::V_DCT, frame_type), + self.get_txtype_pct_by_frame_type(TxType::H_DCT, frame_type), + ) + } + + fn print_prediction_modes_summary(&self) { + info!("----------"); + self.print_luma_prediction_mode_summary_by_frame_type(FrameType::KEY, 'I'); + self + .print_chroma_prediction_mode_summary_by_frame_type(FrameType::KEY, 'I'); + info!("----------"); + self + .print_luma_prediction_mode_summary_by_frame_type(FrameType::INTER, 'P'); + self.print_chroma_prediction_mode_summary_by_frame_type( + FrameType::INTER, + 'P', + ); + } + + fn print_luma_prediction_mode_summary_by_frame_type( + &self, frame_type: FrameType, type_label: char, + ) { + if frame_type == FrameType::KEY { + info!( + "y modes {}: DC: {:.1}% | V: {:.1}% | H: {:.1}% | Paeth: {:.1}%", + type_label, + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::DC_PRED, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::V_PRED, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::H_PRED, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::PAETH_PRED, + frame_type + ), + ); + info!( + " Smooth: {:.1}% | Smooth V: {:.1}% | Smooth H: {:.1}%", + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::SMOOTH_PRED, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::SMOOTH_V_PRED, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::SMOOTH_H_PRED, + frame_type + ), + ); + // Keep angular order for presentation here, rather than enum order. + info!( + " D: 45: {:.1}% | 67: {:.1}% | 113: {:.1}% | 135: {:.1}% | 157: {:.1}% | 203: {:.1}%", + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D45_PRED, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D67_PRED, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D113_PRED, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D135_PRED, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D157_PRED, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::D203_PRED, frame_type), + ); + } else if frame_type == FrameType::INTER { + info!( + "y modes {}: Nearest: {:.1}% | Near0: {:.1}% | Near1: {:.1}% | NearNear0: {:.1}% | NearNear1: {:.1}% | NearNear2: {:.1}%", + type_label, + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEARESTMV, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEAR0MV, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEAR1MV, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR0MV, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR1MV, frame_type), + self.get_luma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR2MV, frame_type), + ); + info!( + "y modes {}: NearNew0: {:.1}% | NearNew1: {:.1}% | NearNew2: {:.1}%", + type_label, + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW0MV, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW1MV, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW2MV, + frame_type + ), + ); + info!( + "y modes {}: NewNear0: {:.1}% | NewNear1: {:.1}% | NewNear2: {:.1}%", + type_label, + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR0MV, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR1MV, + frame_type + ), + self.get_luma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR2MV, + frame_type + ), + ); + } + } + + fn print_chroma_prediction_mode_summary_by_frame_type( + &self, frame_type: FrameType, type_label: char, + ) { + if frame_type == FrameType::KEY { + info!( + "uv modes {}: DC: {:.1}% | V: {:.1}% | H: {:.1}% | Paeth: {:.1}%", + type_label, + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::DC_PRED, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::V_PRED, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::H_PRED, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::PAETH_PRED, + frame_type + ), + ); + info!( + " Smooth: {:.1}% | Smooth V: {:.1}% | Smooth H: {:.1}% | UV CFL: {:.1}%", + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::SMOOTH_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::SMOOTH_V_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::SMOOTH_H_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::UV_CFL_PRED, frame_type), + ); + // Keep angular order for presentation here, rather than enum order. + info!( + " D: 45: {:.1}% | 67: {:.1}% | 113: {:.1}% | 135: {:.1}% | 157: {:.1}% | 203: {:.1}%", + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D45_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D67_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D113_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D135_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D157_PRED, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::D203_PRED, frame_type), + ); + } else if frame_type == FrameType::INTER { + info!( + "uv modes {}: Nearest: {:.1}% | Near0: {:.1}% | Near1: {:.1}% | NearNear0: {:.1}% | NearNear1: {:.1}% | NearNear2: {:.1}%", + type_label, + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEARESTMV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAR0MV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAR1MV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR0MV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR1MV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAR_NEAR2MV, frame_type), + ); + info!( + "uv modes {}: NearNew0: {:.1}% | NearNew1: {:.1}% | NearNew2: {:.1}%", + type_label, + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW0MV, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW1MV, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEAR_NEW2MV, + frame_type + ), + ); + info!( + "uv modes {}: NewNear0: {:.1}% | NewNear1: {:.1}% | NewNear2: {:.1}%", + type_label, + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR0MV, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR1MV, + frame_type + ), + self.get_chroma_pred_mode_pct_by_frame_type( + PredictionMode::NEW_NEAR2MV, + frame_type + ), + ); + info!(" New: {:.1}% | NewNew: {:.1}% | NearestNearest: {:.1}% | GlobalGlobal: {:.1}%", + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEWMV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEW_NEWMV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::NEAREST_NEARESTMV, frame_type), + self.get_chroma_pred_mode_pct_by_frame_type(PredictionMode::GLOBAL_GLOBALMV, frame_type),); + } + } +} + +fn sum_metric f64>( + frame_info: &[FrameSummary], map_fn: F, +) -> f64 { + frame_info.iter().map(map_fn).sum::() / frame_info.len() as f64 +} + +impl fmt::Display for ProgressInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(total_frames) = self.total_frames { + write!( + f, + "encoded {}/{} frames, {:.3} fps, {:.2} Kb/s, est: {}, {:.2} MB, elapsed: {}", + self.frames_encoded(), + total_frames, + self.encoding_fps(), + self.bitrate() as f64 / 1000f64, + secs_to_human_time(self.estimated_time()), + self.estimated_size() as f64 / (1024 * 1024) as f64, + secs_to_human_time(self.elapsed_time()) + ) + } else { + write!( + f, + "encoded {} frames, {:.3} fps, {:.2} Kb/s, elapsed: {}", + self.frames_encoded(), + self.encoding_fps(), + self.bitrate() as f64 / 1000f64, + secs_to_human_time(self.elapsed_time()) + ) + } + } +} + +fn secs_to_human_time(mut secs: u64) -> String { + let mut mins = secs / 60; + secs %= 60; + let hours = mins / 60; + mins %= 60; + if hours > 0 { + format!("{hours}h {mins}m {secs}s") + } else if mins > 0 { + format!("{mins}m {secs}s") + } else { + format!("{secs}s") + } +} + +#[derive(Debug, Clone, Copy, Default, PartialEq)] +pub struct QualityMetrics { + /// Peak Signal-to-Noise Ratio for Y, U, and V planes + pub psnr: Option, + /// Peak Signal-to-Noise Ratio as perceived by the Human Visual System-- + /// taking into account Contrast Sensitivity Function (CSF) + pub psnr_hvs: Option, + /// Structural Similarity + pub ssim: Option, + /// Multi-Scale Structural Similarity + pub ms_ssim: Option, + /// CIEDE 2000 [color difference algorithm](https://en.wikipedia.org/wiki/Color_difference#CIEDE2000) + pub ciede: Option, + /// Aligned Peak Signal-to-Noise Ratio for Y, U, and V planes + pub apsnr: Option, + /// Netflix's Video Multimethod Assessment Fusion + pub vmaf: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MetricsEnabled { + /// Don't calculate any metrics. + None, + /// Calculate the PSNR of each plane, but no other metrics. + Psnr, + /// Calculate all implemented metrics. Currently implemented metrics match what is available via AWCY. + All, +} + +pub fn calculate_frame_metrics( + frame1: &Frame, frame2: &Frame, bit_depth: usize, cs: ChromaSampling, + metrics: MetricsEnabled, +) -> QualityMetrics { + match metrics { + MetricsEnabled::None => QualityMetrics::default(), + MetricsEnabled::Psnr => QualityMetrics { + psnr: Some( + psnr::calculate_frame_psnr(frame1, frame2, bit_depth, cs).unwrap(), + ), + ..Default::default() + }, + MetricsEnabled::All => { + let mut metrics = QualityMetrics { + psnr: Some( + psnr::calculate_frame_psnr(frame1, frame2, bit_depth, cs).unwrap(), + ), + psnr_hvs: Some( + psnr_hvs::calculate_frame_psnr_hvs(frame1, frame2, bit_depth, cs) + .unwrap(), + ), + ..Default::default() + }; + let ssim = ssim::calculate_frame_ssim(frame1, frame2, bit_depth, cs); + metrics.ssim = Some(ssim.unwrap()); + let ms_ssim = + ssim::calculate_frame_msssim(frame1, frame2, bit_depth, cs); + metrics.ms_ssim = Some(ms_ssim.unwrap()); + let ciede = ciede::calculate_frame_ciede(frame1, frame2, bit_depth, cs); + metrics.ciede = Some(ciede.unwrap()); + // TODO APSNR + // TODO VMAF + metrics + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/capi.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/capi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/capi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/capi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1529 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +//! # C API for rav1e +//! +//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/) +//! encoder written in [Rust](https://rust-lang.org) +//! +//! This is the C-compatible API +#![deny(missing_docs)] +// Basically everything will be unsafe since this is a FFI +#![allow(clippy::undocumented_unsafe_blocks)] +// const extern fns are unstable +#![allow(clippy::missing_const_for_fn)] + +use std::slice; +use std::sync::Arc; + +use std::ffi::CStr; +use std::ffi::CString; +use std::mem; +use std::os::raw::c_char; +use std::os::raw::c_int; +use std::os::raw::c_void; + +use libc::ptrdiff_t; +use libc::size_t; + +use num_derive::*; +use num_traits::cast::FromPrimitive; + +use scan_fmt::scan_fmt; + +use crate::api::SceneDetectionSpeed; +use crate::prelude as rav1e; + +type PixelRange = rav1e::PixelRange; +type ChromaSamplePosition = rav1e::ChromaSamplePosition; +type ChromaSampling = rav1e::ChromaSampling; +type MatrixCoefficients = rav1e::MatrixCoefficients; +type ColorPrimaries = rav1e::ColorPrimaries; +type TransferCharacteristics = rav1e::TransferCharacteristics; +type Rational = rav1e::Rational; +type FrameTypeOverride = rav1e::FrameTypeOverride; +type FrameOpaqueCb = Option; +type T35 = rav1e::T35; + +#[derive(Clone)] +enum FrameInternal { + U8(Arc>), + U16(Arc>), +} + +impl From> for FrameInternal { + fn from(f: rav1e::Frame) -> FrameInternal { + FrameInternal::U8(Arc::new(f)) + } +} + +impl From> for FrameInternal { + fn from(f: rav1e::Frame) -> FrameInternal { + FrameInternal::U16(Arc::new(f)) + } +} + +impl From>> for FrameInternal { + fn from(f: Arc>) -> FrameInternal { + FrameInternal::U8(f) + } +} + +impl From>> for FrameInternal { + fn from(f: Arc>) -> FrameInternal { + FrameInternal::U16(f) + } +} + +struct FrameOpaque { + opaque: *mut c_void, + cb: FrameOpaqueCb, +} + +unsafe impl Send for FrameOpaque {} +unsafe impl Sync for FrameOpaque {} + +impl Default for FrameOpaque { + fn default() -> Self { + FrameOpaque { opaque: std::ptr::null_mut(), cb: None } + } +} + +impl Drop for FrameOpaque { + fn drop(&mut self) { + let FrameOpaque { opaque, cb } = self; + if let Some(cb) = cb { + cb(*opaque); + } + } +} + +/// Raw video Frame +/// +/// It can be allocated through `rav1e_frame_new()`, +/// populated using `rav1e_frame_fill_plane()`, +/// and freed using `rav1e_frame_unref()`. +pub struct Frame { + fi: FrameInternal, + frame_type: FrameTypeOverride, + opaque: Option, + t35_metadata: Vec, +} + +/// Status that can be returned by encoder functions. +#[repr(C)] +#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)] +pub enum EncoderStatus { + /// Normal operation. + Success = 0, + /// The encoder needs more data to produce an output packet. + /// + /// May be emitted by `rav1e_receive_packet` when frame reordering is + /// enabled. + NeedMoreData, + /// There are enough frames in the queue. + /// + /// May be emitted by `rav1e_send_frame` when trying to send a frame after + /// the encoder has been flushed or the internal queue is full. + EnoughData, + /// The encoder has already produced the number of frames requested. + /// + /// May be emitted by `rav1e_receive_packet` after a flush request had been + /// processed or the frame limit had been reached. + LimitReached, + /// A Frame had been encoded but not emitted yet. + Encoded, + /// Generic fatal error. + Failure = -1, + /// A frame was encoded in the first pass of a 2-pass encode, but its stats + /// data was not retrieved with `rav1e_twopass_out`, or not enough stats data + /// was provided in the second pass of a 2-pass encode to encode the next + /// frame. + NotReady = -2, +} + +impl EncoderStatus { + const fn to_c(&self) -> *const u8 { + use self::EncoderStatus::*; + match self { + Success => "Normal operation\0".as_ptr(), + NeedMoreData => "The encoder needs more data to produce an output packet\0".as_ptr(), + EnoughData => "There are enough frames in the queue\0".as_ptr(), + LimitReached => "The encoder has already produced the number of frames requested\0".as_ptr(), + Encoded => "A Frame had been encoded but not emitted yet\0".as_ptr(), + Failure => "Generic fatal error\0".as_ptr(), + NotReady => "First-pass stats data not retrieved or not enough second-pass data provided\0".as_ptr(), + } + } +} + +impl From> for EncoderStatus { + fn from(status: Option) -> Self { + match status { + None => EncoderStatus::Success, + Some(s) => match s { + rav1e::EncoderStatus::NeedMoreData => EncoderStatus::NeedMoreData, + rav1e::EncoderStatus::EnoughData => EncoderStatus::EnoughData, + rav1e::EncoderStatus::LimitReached => EncoderStatus::LimitReached, + rav1e::EncoderStatus::Encoded => EncoderStatus::Encoded, + rav1e::EncoderStatus::Failure => EncoderStatus::Failure, + rav1e::EncoderStatus::NotReady => EncoderStatus::NotReady, + }, + } + } +} + +/// Encoder configuration +/// +/// Instantiate it using `rav1e_config_default()` and fine-tune it using +/// `rav1e_config_parse()`. +/// +/// Use `rav1e_config_unref()` to free its memory. +pub struct Config { + cfg: rav1e::Config, +} + +enum EncContext { + U8(rav1e::Context), + U16(rav1e::Context), +} + +impl EncContext { + fn new_frame(&self) -> FrameInternal { + match self { + EncContext::U8(ctx) => ctx.new_frame().into(), + EncContext::U16(ctx) => ctx.new_frame().into(), + } + } + fn send_frame( + &mut self, frame: Option, frame_type: FrameTypeOverride, + opaque: Option, t35_metadata: Box<[T35]>, + ) -> Result<(), rav1e::EncoderStatus> { + let info = rav1e::FrameParameters { + frame_type_override: frame_type, + opaque, + t35_metadata, + }; + if let Some(frame) = frame { + match (self, frame) { + (EncContext::U8(ctx), FrameInternal::U8(ref f)) => { + ctx.send_frame((f.clone(), info)) + } + (EncContext::U16(ctx), FrameInternal::U16(ref f)) => { + ctx.send_frame((f.clone(), info)) + } + _ => Err(rav1e::EncoderStatus::Failure), + } + } else { + match self { + EncContext::U8(ctx) => ctx.send_frame(None), + EncContext::U16(ctx) => ctx.send_frame(None), + } + } + } + + fn receive_packet(&mut self) -> Result { + fn receive_packet( + ctx: &mut rav1e::Context, + ) -> Result + where + FrameInternal: From>>, + { + ctx.receive_packet().map(|p| { + let mut p = std::mem::ManuallyDrop::new(p); + let opaque = p.opaque.take().map_or_else(std::ptr::null_mut, |o| { + let mut opaque = o.downcast::().unwrap(); + opaque.cb = None; + opaque.opaque + }); + let p = std::mem::ManuallyDrop::into_inner(p); + let rav1e::Packet { + data, rec, source, input_frameno, frame_type, .. + } = p; + let len = data.len(); + let data = Box::into_raw(data.into_boxed_slice()) as *const u8; + let rec = if let Some(rec) = rec { + let rec = FrameInternal::from(rec); + Box::into_raw(Box::new(Frame { + fi: rec, + frame_type: FrameTypeOverride::No, + opaque: None, + t35_metadata: Vec::new(), + })) + } else { + std::ptr::null_mut() + }; + let source = if let Some(source) = source { + let source = FrameInternal::from(source); + Box::into_raw(Box::new(Frame { + fi: source, + frame_type: FrameTypeOverride::No, + opaque: None, + t35_metadata: Vec::new(), + })) + } else { + std::ptr::null_mut() + }; + Packet { data, rec, source, len, input_frameno, frame_type, opaque } + }) + } + match self { + EncContext::U8(ctx) => receive_packet(ctx), + EncContext::U16(ctx) => receive_packet(ctx), + } + } + + fn container_sequence_header(&self) -> Vec { + match self { + EncContext::U8(ctx) => ctx.container_sequence_header(), + EncContext::U16(ctx) => ctx.container_sequence_header(), + } + } + + fn twopass_bytes_needed(&mut self) -> usize { + match self { + EncContext::U8(ctx) => ctx.twopass_bytes_needed(), + EncContext::U16(ctx) => ctx.twopass_bytes_needed(), + } + } + + fn twopass_in(&mut self, buf: &[u8]) -> Result { + match self { + EncContext::U8(ctx) => ctx.twopass_in(buf), + EncContext::U16(ctx) => ctx.twopass_in(buf), + } + } + + fn twopass_out(&mut self) -> Option<&[u8]> { + match self { + EncContext::U8(ctx) => ctx.twopass_out(), + EncContext::U16(ctx) => ctx.twopass_out(), + } + } + + fn rc_summary_size(&self) -> usize { + match self { + EncContext::U8(ctx) => ctx.rc_summary_size(), + EncContext::U16(ctx) => ctx.rc_summary_size(), + } + } + + fn rc_receive_pass_data(&mut self) -> Option { + match self { + EncContext::U8(ctx) => ctx.rc_receive_pass_data(), + EncContext::U16(ctx) => ctx.rc_receive_pass_data(), + } + } + + fn rc_second_pass_data_required(&self) -> usize { + match self { + EncContext::U8(ctx) => ctx.rc_second_pass_data_required(), + EncContext::U16(ctx) => ctx.rc_second_pass_data_required(), + } + } + + fn rc_send_pass_data( + &mut self, data: &[u8], + ) -> Result<(), rav1e::EncoderStatus> { + match self { + EncContext::U8(ctx) => ctx.rc_send_pass_data(data), + EncContext::U16(ctx) => ctx.rc_send_pass_data(data), + } + } + + fn config(&self) -> rav1e::EncoderConfig { + // Ideally this would return a reference instead of cloning, + // but that would require a breaking change in the CAPI. + match self { + EncContext::U8(ctx) => ctx.config.clone(), + EncContext::U16(ctx) => ctx.config.clone(), + } + } +} + +/// Encoder context +/// +/// Contains the encoding state, it is created by `rav1e_context_new()` using an +/// Encoder configuration. +/// +/// Use `rav1e_context_unref()` to free its memory. +pub struct Context { + ctx: EncContext, + last_err: Option, +} + +type FrameType = rav1e::FrameType; + +/// Encoded Packet +/// +/// The encoded packets are retrieved using `rav1e_receive_packet()`. +/// +/// Use `rav1e_packet_unref()` to free its memory. +#[repr(C)] +pub struct Packet { + /// Encoded data buffer + pub data: *const u8, + /// Encoded data buffer size + pub len: size_t, + /// Frame sequence number + pub input_frameno: u64, + /// Frame type + pub frame_type: FrameType, + /// User provided opaque data + pub opaque: *mut c_void, + /// The reconstruction of the shown frame. + /// This is freed automatically by `rav1e_packet_unref()`. + pub rec: *mut Frame, + /// The Reference Frame + /// This is freed automatically by `rav1e_packet_unref()`. + pub source: *mut Frame, +} + +/// Version information as presented in `[package]` `version`. +/// +/// e.g. `0.1.0` +/// +/// Can be parsed by [semver](https://crates.io/crates/semver). +/// This returns the version of the loaded library, regardless +/// of which version the library user was built against. +#[no_mangle] +pub unsafe extern fn rav1e_version_short() -> *const c_char { + concat!(env!("CARGO_PKG_VERSION"), "\0").as_ptr() as *const c_char +} + +static FULL_VERSION_C: std::sync::OnceLock = + std::sync::OnceLock::new(); + +/// Version information with the information +/// provided by `git describe --tags`. +/// +/// e.g. `0.1.0 (v0.1.0-1-g743d464)` +/// +/// This returns the version of the loaded library, regardless +/// of which version the library user was built against. +#[no_mangle] +pub unsafe extern fn rav1e_version_full() -> *const c_char { + FULL_VERSION_C + .get_or_init(|| { + CString::new(crate::version::full()).expect("Bogus version data") + }) + .as_ptr() as *const c_char +} + +/// Simple Data +/// +/// Use `rav1e_data_unref()` to free its memory. +#[repr(C)] +pub struct Data { + /// Pointer to the data buffer + pub data: *const u8, + /// Data buffer size + pub len: size_t, +} + +/// Free a `RaData` buffer +#[no_mangle] +pub unsafe extern fn rav1e_data_unref(data: *mut Data) { + if !data.is_null() { + let data = Box::from_raw(data); + let _ = Vec::from_raw_parts( + data.data as *mut u8, + data.len as usize, + data.len as usize, + ); + } +} + +/// Create a `RaConfig` filled with default parameters. +#[no_mangle] +pub unsafe extern fn rav1e_config_default() -> *mut Config { + let cfg = rav1e::Config::default(); + + let c = Box::new(Config { cfg }); + + Box::into_raw(c) +} + +unsafe fn decode_slice<'a>( + data: *mut *const u8, len: *mut size_t, +) -> (c_int, Option<&'a [u8]>) { + if *len < 8 { + return (8, None); + } + + let buf = slice::from_raw_parts(*data, *len as usize); + let (len_bytes, rest) = buf.split_at(std::mem::size_of::()); + let buf_len = u64::from_be_bytes(len_bytes.try_into().unwrap()) as usize; + let full_len = buf_len + 8; + if buf_len > rest.len() { + return (full_len as c_int, None); + } + + *len -= full_len; + *data = (*data).offset(full_len.try_into().unwrap()); + + (0, Some(&rest[..buf_len])) +} + +/// Setup a second pass rate control using the provided summary +/// +/// Passing `NULL` data resets the rate control settings. +/// +/// If additional data is required, pointer and len stay unchanged, otherwise +/// they are updated. +/// +/// Return: +/// `0` on success +/// `> 0` if the buffer has to be larger +/// `< 0` on failure +#[no_mangle] +// Panic can never occur here +#[allow(clippy::missing_panics_doc)] +pub unsafe extern fn rav1e_config_set_rc_summary( + cfg: *mut Config, data: *mut *const u8, len: *mut size_t, +) -> c_int { + if data.is_null() { + (*cfg).cfg.rate_control.summary = None; + + return 0; + } + + let (needed, maybe_buf) = decode_slice(data, len); + + if maybe_buf.is_none() { + return needed; + } + + let summary = rav1e::RateControlSummary::from_slice(maybe_buf.unwrap()).ok(); + if summary.is_none() { + -1 + } else { + (*cfg).cfg.rate_control.summary = summary; + + 0 + } +} + +/// Request to emit pass data +/// +/// Set emit to 0 to not emit pass data, non-zero to emit pass data. +/// +#[no_mangle] +pub unsafe extern fn rav1e_config_set_emit_data( + cfg: *mut Config, emit: c_int, +) { + (*cfg).cfg.rate_control.emit_pass_data = emit != 0; +} + +/// Set the display aspect ratio of the stream +/// +/// Needed for anamorphic video. +#[no_mangle] +pub unsafe extern fn rav1e_config_set_sample_aspect_ratio( + cfg: *mut Config, sample_aspect_ratio: Rational, +) { + (*cfg).cfg.enc.sample_aspect_ratio = sample_aspect_ratio +} + +/// Set the time base of the stream +/// +/// Needed for rate control. +#[no_mangle] +pub unsafe extern fn rav1e_config_set_time_base( + cfg: *mut Config, time_base: Rational, +) { + (*cfg).cfg.enc.time_base = time_base +} + +/// Set pixel format of the stream. +/// +/// Supported values for `subsampling` and `chroma_pos` are defined by the +/// enum types `RaChromaSampling` and `RaChromaSamplePosition` respectively. +/// Valid values for `pixel_range` are 0 and 1. +/// +/// Returns a negative value on error or 0. +#[no_mangle] +pub unsafe extern fn rav1e_config_set_pixel_format( + cfg: *mut Config, bit_depth: u8, subsampling: ChromaSampling, + chroma_pos: ChromaSamplePosition, pixel_range: PixelRange, +) -> c_int { + if bit_depth != 8 && bit_depth != 10 && bit_depth != 12 { + return -1; + } + (*cfg).cfg.enc.bit_depth = bit_depth as usize; + + let subsampling_val = + std::mem::transmute::(subsampling); + if ChromaSampling::from_i32(subsampling_val).is_none() { + return -1; + } + (*cfg).cfg.enc.chroma_sampling = subsampling; + + let chroma_pos_val = + std::mem::transmute::(chroma_pos); + if ChromaSamplePosition::from_i32(chroma_pos_val).is_none() { + return -1; + } + (*cfg).cfg.enc.chroma_sample_position = chroma_pos; + + let pixel_range_val = std::mem::transmute::(pixel_range); + if PixelRange::from_i32(pixel_range_val).is_none() { + return -1; + } + (*cfg).cfg.enc.pixel_range = pixel_range; + + 0 +} + +/// Set color properties of the stream. +/// +/// Supported values are defined by the enum types +/// `RaMatrixCoefficients`, `RaColorPrimaries`, and `RaTransferCharacteristics` +/// respectively. +/// +/// Return a negative value on error or 0. +#[no_mangle] +pub unsafe extern fn rav1e_config_set_color_description( + cfg: *mut Config, matrix: MatrixCoefficients, primaries: ColorPrimaries, + transfer: TransferCharacteristics, +) -> c_int { + (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription { + matrix_coefficients: matrix, + color_primaries: primaries, + transfer_characteristics: transfer, + }); + + if (*cfg).cfg.enc.color_description.is_some() { + 0 + } else { + -1 + } +} + +/// Set the content light level information for HDR10 streams. +/// +/// Return a negative value on error or 0. +#[no_mangle] +pub unsafe extern fn rav1e_config_set_content_light( + cfg: *mut Config, max_content_light_level: u16, + max_frame_average_light_level: u16, +) -> c_int { + (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight { + max_content_light_level, + max_frame_average_light_level, + }); + + if (*cfg).cfg.enc.content_light.is_some() { + 0 + } else { + -1 + } +} + +/// Set the mastering display information for HDR10 streams. +/// +/// `primaries` and `white_point` arguments are `RaChromaticityPoint`, +/// containing 0.16 fixed point values. +/// `max_luminance` is a 24.8 fixed point value. +/// `min_luminance` is a 18.14 fixed point value. +/// +/// Returns a negative value on error or 0. +/// cbindgen:ptrs-as-arrays=[[primaries;3]] +#[no_mangle] +pub unsafe extern fn rav1e_config_set_mastering_display( + cfg: *mut Config, primaries: *const rav1e::ChromaticityPoint, + white_point: rav1e::ChromaticityPoint, max_luminance: u32, + min_luminance: u32, +) -> c_int { + let primaries = *(primaries as *const [rav1e::ChromaticityPoint; 3]); + + (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay { + primaries, + white_point, + max_luminance, + min_luminance, + }); + + if (*cfg).cfg.enc.mastering_display.is_some() { + 0 + } else { + -1 + } +} + +/// Free the `RaConfig`. +#[no_mangle] +pub unsafe extern fn rav1e_config_unref(cfg: *mut Config) { + if !cfg.is_null() { + let _ = Box::from_raw(cfg); + } +} + +unsafe fn option_match( + cfg: *mut Config, key: *const c_char, value: *const c_char, +) -> Result<(), ()> { + let key = CStr::from_ptr(key).to_str().map_err(|_| ())?; + let value = CStr::from_ptr(value).to_str().map_err(|_| ())?; + let enc = &mut (*cfg).cfg.enc; + + match key { + "width" => enc.width = value.parse().map_err(|_| ())?, + "height" => enc.height = value.parse().map_err(|_| ())?, + "speed" => { + enc.speed_settings = + rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?) + } + + "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?, + + "tiles" => enc.tiles = value.parse().map_err(|_| ())?, + "tile_rows" => enc.tile_rows = value.parse().map_err(|_| ())?, + "tile_cols" => enc.tile_cols = value.parse().map_err(|_| ())?, + + "tune" => enc.tune = value.parse().map_err(|_| ())?, + "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?, + "min_quantizer" => enc.min_quantizer = value.parse().map_err(|_| ())?, + "bitrate" => enc.bitrate = value.parse().map_err(|_| ())?, + + "key_frame_interval" => { + enc.set_key_frame_interval( + enc.min_key_frame_interval, + value.parse().map_err(|_| ())?, + ); + } + "min_key_frame_interval" => { + enc.set_key_frame_interval( + value.parse().map_err(|_| ())?, + enc.max_key_frame_interval, + ); + } + "switch_frame_interval" => { + enc.switch_frame_interval = value.parse().map_err(|_| ())? + } + "reservoir_frame_delay" => { + enc.reservoir_frame_delay = Some(value.parse().map_err(|_| ())?) + } + "rdo_lookahead_frames" => { + enc.speed_settings.rdo_lookahead_frames = + value.parse().map_err(|_| ())? + } + "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?, + "enable_timing_info" => { + enc.enable_timing_info = value.parse().map_err(|_| ())? + } + "still_picture" => enc.still_picture = value.parse().map_err(|_| ())?, + "no_scene_detection" => { + if value.parse::().map_err(|_| ())? { + enc.speed_settings.scene_detection_mode = SceneDetectionSpeed::None; + } + } + + "level" => { + enc.level_idx = match value { + "auto" => None, + "unconstrained" => Some(31), + _ => { + let (major, minor) = + scan_fmt!(value, "{}.{}", u8, u8).map_err(|_| ())?; + if major > 7 || minor > 3 { + return Err(()); + } + Some(((major - 2) << 2) + minor) + } + }; + } + + _ => return Err(()), + } + + Ok(()) +} + +/// Set a configuration parameter using its key and value as string. +/// +/// Available keys and values +/// - `"width"`: width of the frame, default `640` +/// - `"height"`: height of the frame, default `480` +/// - `"speed"`: 0-10, default `6` +/// - `"threads"`: maximum number of threads to be used, default auto +/// - `"tune"`: `"psnr"` or `"psychovisual"`, default `"psychovisual"` +/// - `"quantizer"`: 0-255, default `100` +/// - `"tiles"`: total number of tiles desired (0 denotes auto), default `0` +/// - `"tile_rows"`: number of tiles horizontally (must be a power of two, overridden by tiles if present), default `0` +/// - `"tile_cols"`: number of tiles vertically (must be a power of two, overridden by tiles if present), default `0` +/// - `"min_quantizer"`: minimum allowed base quantizer to use in bitrate mode, default `0` +/// - `"bitrate"`: target bitrate for the bitrate mode (required for two pass mode), default `0` +/// - `"key_frame_interval"`: maximum interval between two keyframes, default `240` +/// - `"min_key_frame_interval"`: minimum interval between two keyframes, default `12` +/// - `"switch_frame_interval"`: interval between switch frames, default `0` +/// - `"reservoir_frame_delay"`: number of temporal units over which to distribute the reservoir usage, default `None` +/// - `"rdo_lookahead_frames"`: number of frames to read ahead for the RDO lookahead computation, default `40` +/// - `"low_latency"`: flag to enable low latency mode, default `false` +/// - `"enable_timing_info"`: flag to enable signaling timing info in the bitstream, default `false` +/// - `"still_picture"`: flag for still picture mode, default `false` +/// - `"no_scene_detection"`: flag to disable scene detection, default `false` +/// +/// Return a negative value on error or 0. +#[no_mangle] +pub unsafe extern fn rav1e_config_parse( + cfg: *mut Config, key: *const c_char, value: *const c_char, +) -> c_int { + if option_match(cfg, key, value) == Ok(()) { + 0 + } else { + -1 + } +} + +/// Set a configuration parameter using its key and value as integer. +/// +/// Available keys and values are the same as `rav1e_config_parse()` +/// +/// Return a negative value on error or 0. +#[no_mangle] +// Panic can never occur here +#[allow(clippy::missing_panics_doc)] +pub unsafe extern fn rav1e_config_parse_int( + cfg: *mut Config, key: *const c_char, value: c_int, +) -> c_int { + let val = CString::new(value.to_string()).unwrap(); + if option_match(cfg, key, val.as_ptr()) == Ok(()) { + 0 + } else { + config_parse_bool(cfg, key, value) + } +} + +unsafe fn config_parse_bool( + cfg: *mut Config, key: *const c_char, value: c_int, +) -> c_int { + let val = CString::new(if value != 0 { "true" } else { "false" }).unwrap(); + if option_match(cfg, key, val.as_ptr()) == Ok(()) { + 0 + } else { + -1 + } +} + +/// Generate a new encoding context from a populated encoder configuration +/// +/// Multiple contexts can be generated through it. +/// Returns `Null` if context creation failed, e.g. by passing +/// an invalid `Config`. +#[no_mangle] +pub unsafe extern fn rav1e_context_new(cfg: *const Config) -> *mut Context { + let cfg = &(*cfg).cfg; + let enc = &cfg.enc; + + let ctx = match enc.bit_depth { + 8 => cfg.new_context().map(EncContext::U8), + _ => cfg.new_context().map(EncContext::U16), + }; + + if let Ok(ctx) = ctx { + Box::into_raw(Box::new(Context { ctx, last_err: None })) + } else { + std::ptr::null_mut() + } +} + +/// Free the `RaContext`. +#[no_mangle] +pub unsafe extern fn rav1e_context_unref(ctx: *mut Context) { + if !ctx.is_null() { + let _ = Box::from_raw(ctx); + } +} + +/// Produce a new frame from the encoding context +/// +/// It must be populated using `rav1e_frame_fill_plane()`. +/// +/// The frame is reference counted and must be released passing it to `rav1e_frame_unref()`, +/// see `rav1e_send_frame()`. +#[no_mangle] +pub unsafe extern fn rav1e_frame_new(ctx: *const Context) -> *mut Frame { + let fi = (*ctx).ctx.new_frame(); + let frame_type = rav1e::FrameTypeOverride::No; + let f = Frame { fi, frame_type, opaque: None, t35_metadata: Vec::new() }; + let frame = Box::new(f); + + Box::into_raw(frame) +} + +/// Free the `RaFrame`. +#[no_mangle] +pub unsafe extern fn rav1e_frame_unref(frame: *mut Frame) { + if !frame.is_null() { + let _ = Box::from_raw(frame); + } +} + +/// Overrides the encoders frame type decision for a frame +/// +/// Must be called before `rav1e_send_frame()` if used. +#[no_mangle] +pub unsafe extern fn rav1e_frame_set_type( + frame: *mut Frame, frame_type: FrameTypeOverride, +) -> c_int { + let frame_type_val = + std::mem::transmute::(frame_type); + if FrameTypeOverride::from_i32(frame_type_val).is_none() { + return -1; + } + (*frame).frame_type = frame_type; + + 0 +} + +/// Register an opaque data and a destructor to the frame +/// +/// It takes the ownership of its memory: +/// - it will relinquish the ownership to the context if +/// `rav1e_send_frame` is called. +/// - it will call the destructor if `rav1e_frame_unref` is called +/// otherwise. +#[no_mangle] +pub unsafe extern fn rav1e_frame_set_opaque( + frame: *mut Frame, opaque: *mut c_void, cb: FrameOpaqueCb, +) { + if opaque.is_null() { + (*frame).opaque = None; + } else { + (*frame).opaque = Some(FrameOpaque { opaque, cb }); + } +} + +/// Add generic T35 metadata to a frame +/// +/// The buffer will be copied into the frame and can be freed +/// immediately after this call. +/// +/// Can be called multiple times to add multiple T35 metadata +/// blocks. +#[no_mangle] +pub unsafe extern fn rav1e_frame_add_t35_metadata( + frame: *mut Frame, country_code: u8, country_code_extension_byte: u8, + data: *const u8, data_len: size_t, +) { + (*frame).t35_metadata.push(T35 { + country_code, + country_code_extension_byte, + data: slice::from_raw_parts(data, data_len).into(), + }); +} + +/// Retrieve the first-pass data of a two-pass encode for the frame that was +/// just encoded. This should be called BEFORE every call to `rav1e_receive_packet()` +/// (including the very first one), even if no packet was produced by the +/// last call to `rav1e_receive_packet`, if any (i.e., `RA_ENCODER_STATUS_ENCODED` +/// was returned). It needs to be called once more after +/// `RA_ENCODER_STATUS_LIMIT_REACHED` is returned, to retrieve the header that +/// should be written to the front of the stats file (overwriting the +/// placeholder header that was emitted at the start of encoding). +/// +/// It is still safe to call this function when `rav1e_receive_packet()` returns any +/// other error. It will return `NULL` instead of returning a duplicate copy +/// of the previous frame's data. +/// +/// Must be freed with `rav1e_data_unref()`. +#[no_mangle] +// Panic can never occur here +#[allow(clippy::missing_panics_doc)] +pub unsafe extern fn rav1e_twopass_out(ctx: *mut Context) -> *mut Data { + let buf = (*ctx).ctx.twopass_out(); + + if buf.is_none() { + return std::ptr::null_mut(); + } + + let v = buf.unwrap().to_vec(); + Box::into_raw(Box::new(Data { + len: v.len(), + data: Box::into_raw(v.into_boxed_slice()) as *mut u8, + })) +} + +/// Rate Control Data +#[derive(Debug, PartialEq)] +#[repr(C)] +pub enum RcDataKind { + /// A Rate Control Summary Packet + /// + /// It is emitted once, after the encoder is flushed. + /// + /// It contains a summary of the rate control information for the + /// encoding process that just terminated. + Summary, + /// A Rate Control Frame-specific Packet + /// + /// It is emitted every time a frame is processed. + /// + /// The information contained is required to encode its matching + /// frame in a second pass encoding. + Frame, + /// There is no pass data available for now + /// + /// This is emitted if `rav1e_rc_receive_pass_data` is called more + /// often than it should. + Empty, +} + +/// Return the Rate Control Summary Packet size +/// +/// It is useful mainly to preserve space when saving +/// both Rate Control Summary and Frame Packets in a single file +#[no_mangle] +pub unsafe extern fn rav1e_rc_summary_size(ctx: *const Context) -> size_t { + (*ctx).ctx.rc_summary_size() as size_t + 8 +} + +/// Return the first pass data +/// +/// Call it after `rav1e_receive_packet()` returns a normal condition status: +/// - `EncoderStatus::Encoded`, +/// - `EncoderStatus::Success`, +/// - `EncoderStatus::LimitReached`. +/// +/// use `rav1e_data_unref()` to free the data. +/// +/// It will return a `RcDataKind::Summary` once the encoder is flushed. +#[no_mangle] +pub unsafe extern fn rav1e_rc_receive_pass_data( + ctx: *mut Context, data: *mut *mut Data, +) -> RcDataKind { + use crate::api::RcData::*; + let (buf, kind) = match (*ctx).ctx.rc_receive_pass_data() { + Some(Summary(data)) => (data, RcDataKind::Summary), + Some(Frame(data)) => (data, RcDataKind::Frame), + None => return RcDataKind::Empty, + }; + + let mut full_buf = Vec::with_capacity(buf.len() + 8); + + full_buf.extend_from_slice(&(buf.len() as u64).to_be_bytes()); + full_buf.extend_from_slice(&buf); + + let full_buf = full_buf.into_boxed_slice(); + + *data = Box::into_raw(Box::new(Data { + len: full_buf.len(), + data: Box::into_raw(full_buf) as *mut u8, + })); + + kind +} + +/// Number of pass data packets required to progress the encoding process. +/// +/// At least that number of packets must be passed before the encoder can +/// progress. +/// +/// Stop feeding-in pass data packets once the function returns 0. +/// +/// ``` c +/// while (rav1e_rc_second_pass_data_required(ctx) > 0) { +/// int more = rav1e_rc_send_pass_data(ctx, &data, &len); +/// if (more > 0) { +/// refill(&data, &len); +/// } else if (more < 0) { +/// goto fail; +/// } +/// } +/// ``` +/// +#[no_mangle] +pub unsafe extern fn rav1e_rc_second_pass_data_required( + ctx: *const Context, +) -> i32 { + (*ctx).ctx.rc_second_pass_data_required() as i32 +} + +/// Feed the first pass Rate Control data to the encoder, +/// Frame-specific Packets only. +/// +/// Call it before `receive_packet()` +/// +/// If additional data is required, pointer and len stay unchanged, otherwise +/// they are updated. +/// +/// Returns: +/// - `0` on success, +/// - `> 0` the amount of bytes needed +/// - `< 0` on unrecoverable failure +#[no_mangle] +// Panic can never occur here +#[allow(clippy::missing_panics_doc)] +pub unsafe extern fn rav1e_rc_send_pass_data( + ctx: *mut Context, data: *mut *const u8, len: *mut size_t, +) -> c_int { + let (need, maybe_buf) = decode_slice(data, len); + + if maybe_buf.is_none() { + return need; + } + + let ret = (*ctx) + .ctx + .rc_send_pass_data(maybe_buf.unwrap()) + .map(|_v| None) + .unwrap_or_else(Some); + + (*ctx).last_err = ret; + + if ret.is_some() { + -1 + } else { + 0 + } +} + +/// Ask how many bytes of the stats file are needed before the next frame +/// of the second pass in a two-pass encode can be encoded. This is a lower +/// bound (more might be required), but if 0 is returned, then encoding can +/// proceed. This is just a hint to the application, and does not need to +/// be called for encoding the second pass to work, so long as the +/// application continues to provide more data to `rav1e_twopass_in()` in a loop +/// until `rav1e_twopass_in()` returns 0. +#[no_mangle] +pub unsafe extern fn rav1e_twopass_bytes_needed(ctx: *mut Context) -> size_t { + (*ctx).ctx.twopass_bytes_needed() as size_t +} + +/// Provide stats data produced in the first pass of a two-pass encode to the +/// second pass. On success this returns the number of bytes of that data +/// which were consumed. When encoding the second pass of a two-pass encode, +/// this should be called repeatedly in a loop before every call to +/// `rav1e_receive_packet()` (including the very first one) until no bytes are +/// consumed, or until `twopass_bytes_needed()` returns 0. Returns -1 on failure. +#[no_mangle] +pub unsafe extern fn rav1e_twopass_in( + ctx: *mut Context, buf: *mut u8, buf_size: size_t, +) -> c_int { + let buf_slice = slice::from_raw_parts(buf, buf_size as usize); + let r = (*ctx).ctx.twopass_in(buf_slice); + match r { + Ok(v) => v as c_int, + Err(v) => { + (*ctx).last_err = Some(v); + -1 + } + } +} + +/// Send the frame for encoding +/// +/// The function increases the frame internal reference count and it can be passed multiple +/// times to different `rav1e_send_frame()` with a caveat: +/// +/// The opaque data, if present, will be moved from the `Frame` to the `Context` +/// and returned by `rav1e_receive_packet` in the `Packet` `opaque` field or +/// the destructor will be called on `rav1e_context_unref` if the frame is +/// still pending in the encoder. +/// +/// Returns: +/// - `0` on success, +/// - `> 0` if the input queue is full +/// - `< 0` on unrecoverable failure +#[no_mangle] +pub unsafe extern fn rav1e_send_frame( + ctx: *mut Context, frame: *mut Frame, +) -> EncoderStatus { + if !frame.is_null() { + let rav1e::EncoderConfig { width, height, chroma_sampling, .. } = + (*ctx).ctx.config(); + let planes = if chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + match (*frame).fi { + FrameInternal::U8(ref mut f) => { + rav1e_frame_pad_internal(f, planes, width, height) + } + FrameInternal::U16(ref mut f) => { + rav1e_frame_pad_internal(f, planes, width, height) + } + } + } + + let frame_internal = + if frame.is_null() { None } else { Some((*frame).fi.clone()) }; + let frame_type = if frame.is_null() { + rav1e::FrameTypeOverride::No + } else { + (*frame).frame_type + }; + + let maybe_opaque = if frame.is_null() { + None + } else { + (*frame).opaque.take().map(rav1e::Opaque::new) + }; + + let t35_metadata = if frame.is_null() { + Box::new([]) + } else { + mem::take(&mut (*frame).t35_metadata).into_boxed_slice() + }; + + let ret = (*ctx) + .ctx + .send_frame(frame_internal, frame_type, maybe_opaque, t35_metadata) + .map(|_v| None) + .unwrap_or_else(Some); + + (*ctx).last_err = ret; + + ret.into() +} + +/// Return the last encoder status +#[no_mangle] +pub unsafe extern fn rav1e_last_status(ctx: *const Context) -> EncoderStatus { + (*ctx).last_err.into() +} + +/// Return a static string matching the `EncoderStatus` variant. +/// +#[no_mangle] +pub unsafe extern fn rav1e_status_to_str( + status: EncoderStatus, +) -> *const c_char { + if EncoderStatus::from_i32(std::mem::transmute(status)).is_none() { + return std::ptr::null(); + } + + status.to_c() as *const c_char +} + +/// Receive encoded data +/// +/// Returns: +/// - `0` on success +/// - `> 0` if additional frame data is required +/// - `< 0` on unrecoverable failure +#[no_mangle] +pub unsafe extern fn rav1e_receive_packet( + ctx: *mut Context, pkt: *mut *mut Packet, +) -> EncoderStatus { + let ret = (*ctx) + .ctx + .receive_packet() + .map(|packet| { + *pkt = Box::into_raw(Box::new(packet)); + None + }) + .unwrap_or_else(Some); + + (*ctx).last_err = ret; + + ret.into() +} + +/// Free the `RaPacket`. +#[no_mangle] +pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) { + if !pkt.is_null() { + let pkt = Box::from_raw(pkt); + let _ = Vec::from_raw_parts( + pkt.data as *mut u8, + pkt.len as usize, + pkt.len as usize, + ); + rav1e_frame_unref(pkt.rec); + rav1e_frame_unref(pkt.source); + } +} + +/// Produce a sequence header matching the current encoding context +/// +/// Its format is compatible with the AV1 Matroska and ISOBMFF specification. +/// +/// Use `rav1e_data_unref()` to free it. +#[no_mangle] +pub unsafe extern fn rav1e_container_sequence_header( + ctx: *const Context, +) -> *mut Data { + let buf = (*ctx).ctx.container_sequence_header(); + + Box::into_raw(Box::new(Data { + len: buf.len(), + data: Box::into_raw(buf.into_boxed_slice()) as *mut u8, + })) +} + +fn rav1e_frame_fill_plane_internal( + f: &mut Arc>, plane: c_int, data_slice: &[u8], + stride: ptrdiff_t, bytewidth: c_int, +) { + let input = Arc::get_mut(f).unwrap(); + input.planes[plane as usize].copy_from_raw_u8( + data_slice, + stride as usize, + bytewidth as usize, + ); +} + +fn rav1e_frame_pad_internal( + f: &mut Arc>, planes: usize, width: usize, height: usize, +) { + if let Some(ref mut input) = Arc::get_mut(f) { + for plane in input.planes[..planes].iter_mut() { + plane.pad(width, height); + } + } +} + +fn rav1e_frame_extract_plane_internal( + f: &Arc>, plane: c_int, data_slice: &mut [u8], + stride: ptrdiff_t, bytewidth: c_int, +) { + f.planes[plane as usize].copy_to_raw_u8( + data_slice, + stride as usize, + bytewidth as usize, + ); +} + +/// Fill a frame plane +/// +/// Currently the frame contains 3 planes, the first is luminance followed by +/// chrominance. +/// +/// The data is copied and this function has to be called for each plane. +/// +/// `frame`: A frame provided by `rav1e_frame_new()` +/// `plane`: The index of the plane starting from 0 +/// `data`: The data to be copied +/// `data_len`: Length of the buffer +/// `stride`: Plane line in bytes, including padding +/// `bytewidth`: Number of bytes per component, either 1 or 2 +#[no_mangle] +pub unsafe extern fn rav1e_frame_fill_plane( + frame: *mut Frame, plane: c_int, data: *const u8, data_len: size_t, + stride: ptrdiff_t, bytewidth: c_int, +) { + let data_slice = slice::from_raw_parts(data, data_len as usize); + + match (*frame).fi { + FrameInternal::U8(ref mut f) => { + rav1e_frame_fill_plane_internal(f, plane, data_slice, stride, bytewidth) + } + FrameInternal::U16(ref mut f) => { + rav1e_frame_fill_plane_internal(f, plane, data_slice, stride, bytewidth) + } + } +} + +/// Extract a frame plane +/// +/// This is the reverse of `rav1e_frame_fill_plane()`, primarily used for +/// extracting the source and reconstruction data from a `RaPacket`. +/// +/// Currently the frame contains 3 planes, the first is luminance followed by +/// chrominance. +/// +/// The data is copied out of the frame for a single plane. +/// +/// `frame`: A frame provided inside a packet returned by `rav1e_receive_packet()` +/// `plane`: The index of the plane starting from 0 +/// `data`: The destination for the data +/// `data_len`: Length of the buffer +/// `stride`: Plane line in bytes, including padding +/// `bytewidth`: Number of bytes per component, either 1 or 2 +#[no_mangle] +pub unsafe extern fn rav1e_frame_extract_plane( + frame: *const Frame, plane: c_int, data: *mut u8, data_len: size_t, + stride: ptrdiff_t, bytewidth: c_int, +) { + let data_slice = slice::from_raw_parts_mut(data, data_len as usize); + + match (*frame).fi { + FrameInternal::U8(ref f) => rav1e_frame_extract_plane_internal( + f, plane, data_slice, stride, bytewidth, + ), + FrameInternal::U16(ref f) => rav1e_frame_extract_plane_internal( + f, plane, data_slice, stride, bytewidth, + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::ffi::CString; + + #[test] + fn forward_opaque() { + unsafe { + let rac = rav1e_config_default(); + let w = CString::new("width").unwrap(); + rav1e_config_parse_int(rac, w.as_ptr(), 64); + let h = CString::new("height").unwrap(); + rav1e_config_parse_int(rac, h.as_ptr(), 64); + let s = CString::new("speed").unwrap(); + rav1e_config_parse_int(rac, s.as_ptr(), 10); + let l = CString::new("level").unwrap(); + let lo = CString::new("6.2").unwrap(); + rav1e_config_parse(rac, l.as_ptr(), lo.as_ptr()); + + let rax = rav1e_context_new(rac); + + let f = rav1e_frame_new(rax); + + let pixels = [42; 64 * 64]; + rav1e_frame_fill_plane(f, 0, pixels.as_ptr(), pixels.len(), 64, 1); + + for i in 0..30 { + let v = Box::new(i as u8); + extern fn cb(o: *mut c_void) { + let v = unsafe { Box::from_raw(o as *mut u8) }; + eprintln!("Would free {}", v); + } + rav1e_frame_set_opaque(f, Box::into_raw(v) as *mut c_void, Some(cb)); + rav1e_send_frame(rax, f); + } + + rav1e_send_frame(rax, std::ptr::null_mut()); + + for _ in 0..15 { + let mut p: *mut Packet = std::ptr::null_mut(); + let ret = rav1e_receive_packet(rax, &mut p); + + if ret == EncoderStatus::Success { + let mut source = vec![1; 64 * 64]; + rav1e_frame_extract_plane( + (*p).source, + 0, + source.as_mut_ptr(), + 64 * 64, + 64, + 1, + ); + assert_eq!(source, vec![42; 64 * 64]); + let v = Box::from_raw((*p).opaque as *mut u8); + eprintln!("Opaque {}", v); + } + + if ret == EncoderStatus::LimitReached { + break; + } + } + + let v = Box::new(42u64); + extern fn cb(o: *mut c_void) { + let v = unsafe { Box::from_raw(o as *mut u64) }; + eprintln!("Would free {}", v); + } + rav1e_frame_set_opaque(f, Box::into_raw(v) as *mut c_void, Some(cb)); + + // 42 would be freed after this + rav1e_frame_unref(f); + // 15 - reorder delay .. 29 would be freed after this + rav1e_context_unref(rax); + rav1e_config_unref(rac); + } + } + + #[test] + fn two_pass_encoding() { + unsafe { + let rac = rav1e_config_default(); + let w = CString::new("width").unwrap(); + rav1e_config_parse_int(rac, w.as_ptr(), 64); + let h = CString::new("height").unwrap(); + rav1e_config_parse_int(rac, h.as_ptr(), 64); + let s = CString::new("speed").unwrap(); + rav1e_config_parse_int(rac, s.as_ptr(), 10); + let s = CString::new("bitrate").unwrap(); + rav1e_config_parse_int(rac, s.as_ptr(), 1000); + rav1e_config_set_emit_data(rac, 1); + + let rax = rav1e_context_new(rac); + let f = rav1e_frame_new(rax); + + let pixels = [42; 64 * 64]; + rav1e_frame_fill_plane(f, 0, pixels.as_ptr(), pixels.len(), 64, 1); + + for _ in 0..10 { + rav1e_send_frame(rax, f); + } + + rav1e_send_frame(rax, std::ptr::null_mut()); + + let mut frame_data = std::collections::VecDeque::new(); + let mut summary: *mut Data = std::ptr::null_mut(); + + loop { + let mut p: *mut Packet = std::ptr::null_mut(); + let ret = rav1e_receive_packet(rax, &mut p); + rav1e_packet_unref(p); + if ret == EncoderStatus::LimitReached { + let kind = rav1e_rc_receive_pass_data(rax, &mut summary); + assert_eq!(kind, RcDataKind::Summary); + eprintln!("Got rc summary {} bytes", (*summary).len); + break; + } else if ret == EncoderStatus::Encoded + || ret == EncoderStatus::Success + { + let mut p: *mut Data = std::ptr::null_mut(); + let kind = rav1e_rc_receive_pass_data(rax, &mut p); + assert_eq!(kind, RcDataKind::Frame); + eprintln!("Got rc frame data {} bytes", (*p).len); + frame_data.push_back(p); + } + } + + rav1e_config_set_emit_data(rac, 0); + let mut data = (*summary).data; + let mut len = (*summary).len; + let ret = rav1e_config_set_rc_summary(rac, &mut data, &mut len); + assert_eq!(ret, 0); + + rav1e_data_unref(summary); + + for _ in 0..10 { + rav1e_send_frame(rax, f); + } + + rav1e_send_frame(rax, std::ptr::null_mut()); + + loop { + let mut p: *mut Packet = std::ptr::null_mut(); + while rav1e_rc_second_pass_data_required(rax) > 0 { + let d = frame_data.pop_front().unwrap(); + let mut data = (*d).data; + let mut len = (*d).len; + rav1e_rc_send_pass_data(rax, &mut data, &mut len); + rav1e_data_unref(d); + } + + let ret = rav1e_receive_packet(rax, &mut p); + rav1e_packet_unref(p); + if ret == EncoderStatus::LimitReached { + break; + } + } + + rav1e_frame_unref(f); + rav1e_context_unref(rax); + rav1e_config_unref(rac); + } + } + + #[test] + fn invalid_level() { + unsafe { + let rac = rav1e_config_default(); + let l = CString::new("level").unwrap(); + let lo = CString::new("8.3").unwrap(); + assert_eq!(rav1e_config_parse(rac, l.as_ptr(), lo.as_ptr()), -1); + rav1e_config_unref(rac); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cdef.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cdef.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cdef.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cdef.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,625 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::color::ChromaSampling::Cs400; +use crate::context::*; +use crate::encoder::FrameInvariants; +use crate::frame::*; +use crate::tiling::*; +use crate::util::{clamp, msb, CastFromPrimitive, Pixel}; + +use crate::cpu_features::CpuFeatureLevel; +use std::cmp; + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub(crate) use crate::asm::x86::cdef::*; + } else if #[cfg(asm_neon)] { + pub(crate) use crate::asm::aarch64::cdef::*; + } else { + pub(crate) use self::rust::*; + } +} + +pub const CDEF_VERY_LARGE: u16 = 0x8000; +// These values match dav1d; flags indicating where padding exists +pub const CDEF_HAVE_LEFT: u8 = 1 << 0; +pub const CDEF_HAVE_RIGHT: u8 = 1 << 1; +pub const CDEF_HAVE_TOP: u8 = 1 << 2; +pub const CDEF_HAVE_BOTTOM: u8 = 1 << 3; +pub const CDEF_HAVE_ALL: u8 = + CDEF_HAVE_LEFT | CDEF_HAVE_RIGHT | CDEF_HAVE_TOP | CDEF_HAVE_BOTTOM; + +pub(crate) const CDEF_SEC_STRENGTHS: u8 = 4; + +pub struct CdefDirections { + dir: [[u8; 8]; 8], + var: [[i32; 8]; 8], +} + +pub(crate) mod rust { + use super::*; + + use simd_helpers::cold_for_target_arch; + + // Instead of dividing by n between 2 and 8, we multiply by 3*5*7*8/n. + // The output is then 840 times larger, but we don't care for finding + // the max. + const CDEF_DIV_TABLE: [i32; 9] = [0, 840, 420, 280, 210, 168, 140, 120, 105]; + + /// Returns the position and value of the first instance of the max element in + /// a slice as a tuple. + /// + /// # Arguments + /// + /// * `elems` - A non-empty slice of integers + /// + /// # Panics + /// + /// Panics if `elems` is empty + #[inline] + fn first_max_element(elems: &[i32]) -> (usize, i32) { + // In case of a tie, the first element must be selected. + let (max_idx, max_value) = elems + .iter() + .enumerate() + .max_by_key(|&(i, v)| (v, -(i as isize))) + .unwrap(); + (max_idx, *max_value) + } + + // Detect direction. 0 means 45-degree up-right, 2 is horizontal, and so on. + // The search minimizes the weighted variance along all the lines in a + // particular direction, i.e. the squared error between the input and a + // "predicted" block where each pixel is replaced by the average along a line + // in a particular direction. Since each direction have the same sum(x^2) term, + // that term is never computed. See Section 2, step 2, of: + // http://jmvalin.ca/notes/intra_paint.pdf + pub fn cdef_find_dir( + img: &PlaneSlice<'_, T>, var: &mut u32, coeff_shift: usize, + _cpu: CpuFeatureLevel, + ) -> i32 { + let mut cost: [i32; 8] = [0; 8]; + let mut partial: [[i32; 15]; 8] = [[0; 15]; 8]; + for i in 0..8 { + for j in 0..8 { + let p: i32 = i32::cast_from(img[i][j]); + // We subtract 128 here to reduce the maximum range of the squared + // partial sums. + debug_assert!(p >> coeff_shift <= 255); + let x = (p >> coeff_shift) - 128; + partial[0][i + j] += x; + partial[1][i + j / 2] += x; + partial[2][i] += x; + partial[3][3 + i - j / 2] += x; + partial[4][7 + i - j] += x; + partial[5][3 - i / 2 + j] += x; + partial[6][j] += x; + partial[7][i / 2 + j] += x; + } + } + for i in 0..8 { + cost[2] += partial[2][i] * partial[2][i]; + cost[6] += partial[6][i] * partial[6][i]; + } + cost[2] *= CDEF_DIV_TABLE[8]; + cost[6] *= CDEF_DIV_TABLE[8]; + for i in 0..7 { + cost[0] += (partial[0][i] * partial[0][i] + + partial[0][14 - i] * partial[0][14 - i]) + * CDEF_DIV_TABLE[i + 1]; + cost[4] += (partial[4][i] * partial[4][i] + + partial[4][14 - i] * partial[4][14 - i]) + * CDEF_DIV_TABLE[i + 1]; + } + cost[0] += partial[0][7] * partial[0][7] * CDEF_DIV_TABLE[8]; + cost[4] += partial[4][7] * partial[4][7] * CDEF_DIV_TABLE[8]; + for i in (1..8).step_by(2) { + for j in 0..5 { + cost[i] += partial[i][3 + j] * partial[i][3 + j]; + } + cost[i] *= CDEF_DIV_TABLE[8]; + for j in 0..3 { + cost[i] += (partial[i][j] * partial[i][j] + + partial[i][10 - j] * partial[i][10 - j]) + * CDEF_DIV_TABLE[2 * j + 2]; + } + } + + let (best_dir, best_cost) = first_max_element(&cost); + // Difference between the optimal variance and the variance along the + // orthogonal direction. Again, the sum(x^2) terms cancel out. + // We'd normally divide by 840, but dividing by 1024 is close enough + // for what we're going to do with this. */ + *var = ((best_cost - cost[(best_dir + 4) & 7]) >> 10) as u32; + + best_dir as i32 + } + + #[inline(always)] + fn constrain(diff: i32, threshold: i32, damping: i32) -> i32 { + if threshold != 0 { + let shift = cmp::max(0, damping - msb(threshold)); + let magnitude = (threshold - (diff.abs() >> shift)).clamp(0, diff.abs()); + + if diff < 0 { + -magnitude + } else { + magnitude + } + } else { + 0 + } + } + + pub unsafe fn pad_into_tmp16( + dst: *mut u16, dst_stride: isize, src: *const T, src_stride: isize, + block_width: usize, block_height: usize, edges: u8, + ) { + let mut w = block_width; + let mut h = block_height; + let (dst_col, src_col) = if (edges & CDEF_HAVE_LEFT) != 0 { + w += 2; + (dst, src.offset(-2)) + } else { + (dst.offset(2), src) + }; + if (edges & CDEF_HAVE_RIGHT) != 0 { + w += 2; + }; + + let (mut dst_ptr, mut src_ptr) = if (edges & CDEF_HAVE_TOP) != 0 { + h += 2; + (dst_col, src_col.offset(-2 * src_stride)) + } else { + (dst_col.offset(2 * dst_stride), src_col) + }; + if (edges & CDEF_HAVE_BOTTOM) != 0 { + h += 2; + }; + + for _y in 0..h { + for x in 0..w { + *dst_ptr.add(x) = u16::cast_from(*src_ptr.add(x)); + } + src_ptr = src_ptr.offset(src_stride); + dst_ptr = dst_ptr.offset(dst_stride); + } + } + + #[cold_for_target_arch("x86_64")] + #[allow(clippy::erasing_op, clippy::identity_op, clippy::neg_multiply)] + pub(crate) unsafe fn cdef_filter_block( + dst: &mut PlaneRegionMut<'_, T>, input: *const U, istride: isize, + pri_strength: i32, sec_strength: i32, dir: usize, damping: i32, + bit_depth: usize, xdec: usize, ydec: usize, edges: u8, + _cpu: CpuFeatureLevel, + ) { + if edges != CDEF_HAVE_ALL { + // slowpath for unpadded border[s] + let tmpstride = 2 + (8 >> xdec) + 2; + let mut tmp = [CDEF_VERY_LARGE; (2 + 8 + 2) * (2 + 8 + 2)]; + // copy in what pixels we have/are allowed to use + pad_into_tmp16( + tmp.as_mut_ptr(), // points to *padding* upper left + tmpstride, + input, // points to *block* upper left + istride, + 8 >> xdec, + 8 >> ydec, + edges, + ); + cdef_filter_block( + dst, + tmp.as_ptr().offset(2 * tmpstride + 2), + tmpstride, + pri_strength, + sec_strength, + dir, + damping, + bit_depth, + xdec, + ydec, + CDEF_HAVE_ALL, + _cpu, + ); + } else { + let xsize = (8 >> xdec) as isize; + let ysize = (8 >> ydec) as isize; + let coeff_shift = bit_depth - 8; + let cdef_pri_taps = [[4, 2], [3, 3]]; + let cdef_sec_taps = [[2, 1], [2, 1]]; + let pri_taps = + cdef_pri_taps[((pri_strength >> coeff_shift) & 1) as usize]; + let sec_taps = + cdef_sec_taps[((pri_strength >> coeff_shift) & 1) as usize]; + let cdef_directions = [ + [-1 * istride + 1, -2 * istride + 2], + [0 * istride + 1, -1 * istride + 2], + [0 * istride + 1, 0 * istride + 2], + [0 * istride + 1, 1 * istride + 2], + [1 * istride + 1, 2 * istride + 2], + [1 * istride + 0, 2 * istride + 1], + [1 * istride + 0, 2 * istride + 0], + [1 * istride + 0, 2 * istride - 1], + ]; + for i in 0..ysize { + for j in 0..xsize { + let ptr_in = input.offset(i * istride + j); + let x = i32::cast_from(*ptr_in); + let mut sum: i32 = 0; + let mut max = x; + let mut min = x; + for k in 0..2usize { + let cdef_dirs = [ + cdef_directions[dir][k], + cdef_directions[(dir + 2) & 7][k], + cdef_directions[(dir + 6) & 7][k], + ]; + let pri_tap = pri_taps[k]; + let p = [ + i32::cast_from(*ptr_in.offset(cdef_dirs[0])), + i32::cast_from(*ptr_in.offset(-cdef_dirs[0])), + ]; + for p_elem in p.iter() { + sum += pri_tap * constrain(*p_elem - x, pri_strength, damping); + if *p_elem != CDEF_VERY_LARGE as i32 { + max = cmp::max(*p_elem, max); + } + min = cmp::min(*p_elem, min); + } + + let s = [ + i32::cast_from(*ptr_in.offset(cdef_dirs[1])), + i32::cast_from(*ptr_in.offset(-cdef_dirs[1])), + i32::cast_from(*ptr_in.offset(cdef_dirs[2])), + i32::cast_from(*ptr_in.offset(-cdef_dirs[2])), + ]; + let sec_tap = sec_taps[k]; + for s_elem in s.iter() { + if *s_elem != CDEF_VERY_LARGE as i32 { + max = cmp::max(*s_elem, max); + } + min = cmp::min(*s_elem, min); + sum += sec_tap * constrain(*s_elem - x, sec_strength, damping); + } + } + let v = x + ((8 + sum - (sum < 0) as i32) >> 4); + dst[i as usize][j as usize] = T::cast_from(clamp(v, min, max)); + } + } + } + } + + #[cfg(test)] + mod test { + use super::*; + + #[test] + fn check_max_element() { + assert_eq!(first_max_element(&[-1, -1, 1, 2, 3, 4, 6, 6]), (6, 6)); + assert_eq!(first_max_element(&[-1, -1, 1, 2, 3, 4, 7, 6]), (6, 7)); + assert_eq!(first_max_element(&[0, 0]), (0, 0)); + } + } +} + +// We use the variance of an 8x8 block to adjust the effective filter strength. +#[inline] +fn adjust_strength(strength: i32, var: i32) -> i32 { + let i = if (var >> 6) != 0 { cmp::min(msb(var >> 6), 12) } else { 0 }; + if var != 0 { + (strength * (4 + i) + 8) >> 4 + } else { + 0 + } +} + +#[profiling::function] +pub fn cdef_analyze_superblock_range( + fi: &FrameInvariants, in_frame: &Frame, blocks: &TileBlocks<'_>, + sb_w: usize, sb_h: usize, +) -> Vec { + let mut ret = Vec::::with_capacity(sb_h * sb_w); + for sby in 0..sb_h { + for sbx in 0..sb_w { + let sbo = TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby }); + ret.push(cdef_analyze_superblock(fi, in_frame, blocks, sbo)); + } + } + ret +} + +#[profiling::function] +pub fn cdef_analyze_superblock( + fi: &FrameInvariants, in_frame: &Frame, blocks: &TileBlocks<'_>, + sbo: TileSuperBlockOffset, +) -> CdefDirections { + let coeff_shift = fi.sequence.bit_depth - 8; + let mut dir: CdefDirections = + CdefDirections { dir: [[0; 8]; 8], var: [[0; 8]; 8] }; + // Each direction block is 8x8 in y, and direction computation only looks at y + for by in 0..8 { + for bx in 0..8 { + let block_offset = sbo.block_offset(bx << 1, by << 1); + if block_offset.0.x < blocks.cols() && block_offset.0.y < blocks.rows() { + let skip = blocks[block_offset].skip + & blocks[sbo.block_offset(2 * bx + 1, 2 * by)].skip + & blocks[sbo.block_offset(2 * bx, 2 * by + 1)].skip + & blocks[sbo.block_offset(2 * bx + 1, 2 * by + 1)].skip; + + if !skip { + let mut var: u32 = 0; + let in_plane = &in_frame.planes[0]; + let in_po = sbo.plane_offset(&in_plane.cfg); + let in_slice = in_plane.slice(in_po); + dir.dir[bx][by] = cdef_find_dir::( + &in_slice.reslice(8 * bx as isize, 8 * by as isize), + &mut var, + coeff_shift, + fi.cpu_feature_level, + ) as u8; + dir.var[bx][by] = var as i32; + } + } + } + } + dir +} + +// input: A Frame of reconstructed/deblocked pixels prepared to +// undergo CDEF. Note that the input is a Frame and not a Tile due to +// Tiles not allowing [supervised] out-of-rect access for padding +// pixels. This will be corrected at some point in the future. + +// tile_sbo: specifies an offset into the output Tile, not an +// absolute offset in the visible frame. The Tile's own offset is +// added to this in order to address into the input Frame. + +// tb: the TileBlocks associated with the filtered region; the +// provided blocks co-locate with the output region. The TileBlocks +// provide by-[super]qblock CDEF parameters. + +// output: TileMut destination for filtered pixels. The output's +// rect specifies the region of the input to be processed (x and y +// are relative to the input Frame's origin). Note that an +// additional area of 2 pixels of padding is used for CDEF. When +// these pixels are unavailable (beyond the visible frame or at a +// tile boundary), the filtering process ignores input pixels that +// don't exist. + +/// # Panics +/// +/// - If called with invalid parameters +#[profiling::function] +pub fn cdef_filter_superblock( + fi: &FrameInvariants, input: &Frame, output: &mut TileMut<'_, T>, + blocks: &TileBlocks<'_>, tile_sbo: TileSuperBlockOffset, cdef_index: u8, + cdef_dirs: &CdefDirections, +) { + let bit_depth = fi.sequence.bit_depth; + let coeff_shift = fi.sequence.bit_depth as i32 - 8; + let cdef_damping = fi.cdef_damping as i32; + let cdef_y_strength = fi.cdef_y_strengths[cdef_index as usize]; + let cdef_uv_strength = fi.cdef_uv_strengths[cdef_index as usize]; + let cdef_pri_y_strength = (cdef_y_strength / CDEF_SEC_STRENGTHS) as i32; + let mut cdef_sec_y_strength = (cdef_y_strength % CDEF_SEC_STRENGTHS) as i32; + let cdef_pri_uv_strength = (cdef_uv_strength / CDEF_SEC_STRENGTHS) as i32; + let planes = if fi.sequence.chroma_sampling == Cs400 { 1 } else { 3 }; + let mut cdef_sec_uv_strength = + (cdef_uv_strength % CDEF_SEC_STRENGTHS) as i32; + if cdef_sec_y_strength == 3 { + cdef_sec_y_strength += 1; + } + if cdef_sec_uv_strength == 3 { + cdef_sec_uv_strength += 1; + } + + let tile_rect = *output.planes[0].rect(); + let input_xoffset = + tile_rect.x + tile_sbo.plane_offset(&input.planes[0].cfg).x; + let input_yoffset = + tile_rect.y + tile_sbo.plane_offset(&input.planes[0].cfg).y; + let input_xavail = input.planes[0].cfg.width as isize - input_xoffset; + let input_yavail = input.planes[0].cfg.height as isize - input_yoffset; + + /* determine what edge padding we have, and what padding we don't. + * We don't pad here, but rather tell the filter_block call what it + * needs to do, then let it handle the specifics (following dav1d's + * lead). We make one assumption that's not obvious: Because the + * cdef clipping area is rounded up to an even 8x8 luma block, we + * don't need to guard against having only one (as opposed to two) + * pixels of padding past the current block boundary. The padding + * is all-or-nothing. */ + + // Slightly harder than in dav1d; we're not always doing full-frame. + let have_top_p = + if tile_sbo.0.y as isize + tile_rect.y > 0 { CDEF_HAVE_TOP } else { 0 }; + let have_left_p = + if tile_sbo.0.x as isize + tile_rect.x > 0 { CDEF_HAVE_LEFT } else { 0 }; + let mut edges = have_top_p | CDEF_HAVE_BOTTOM; + + // Each direction block is 8x8 in y, potentially smaller if subsampled in chroma + for by in 0..8usize { + if by + 1 >= (input_yavail as usize >> 3) { + edges &= !CDEF_HAVE_BOTTOM + }; + edges &= !CDEF_HAVE_LEFT; + edges |= have_left_p; + edges |= CDEF_HAVE_RIGHT; + for bx in 0..8usize { + if bx + 1 >= (input_xavail as usize >> 3) { + edges &= !CDEF_HAVE_RIGHT + }; + let block_offset = tile_sbo.block_offset(bx << 1, by << 1); + if block_offset.0.x < blocks.cols() && block_offset.0.y < blocks.rows() { + let skip = blocks[block_offset].skip + & blocks[tile_sbo.block_offset(2 * bx + 1, 2 * by)].skip + & blocks[tile_sbo.block_offset(2 * bx, 2 * by + 1)].skip + & blocks[tile_sbo.block_offset(2 * bx + 1, 2 * by + 1)].skip; + let dir = cdef_dirs.dir[bx][by]; + let var = cdef_dirs.var[bx][by]; + for p in 0..planes { + let out_plane = &mut output.planes[p]; + let in_plane = &input.planes[p]; + let xdec = in_plane.cfg.xdec; + let ydec = in_plane.cfg.ydec; + let xsize = 8 >> xdec; + let ysize = 8 >> ydec; + let in_po = PlaneOffset { + x: (input_xoffset >> xdec) + (bx * xsize) as isize, + y: (input_yoffset >> ydec) + (by * ysize) as isize, + }; + let in_stride = in_plane.cfg.stride; + let in_slice = &in_plane.slice(in_po); + + let out_block = &mut out_plane.subregion_mut(Area::BlockRect { + bo: tile_sbo.block_offset(2 * bx, 2 * by).0, + width: xsize, + height: ysize, + }); + + if !skip { + let local_pri_strength; + let local_sec_strength; + let mut local_damping: i32 = cdef_damping + coeff_shift; + // See `Cdef_Uv_Dir` constant lookup table in Section 7.15.1 + // + let local_dir = if p == 0 { + local_pri_strength = + adjust_strength(cdef_pri_y_strength << coeff_shift, var); + local_sec_strength = cdef_sec_y_strength << coeff_shift; + if cdef_pri_y_strength != 0 { + dir as usize + } else { + 0 + } + } else { + local_pri_strength = cdef_pri_uv_strength << coeff_shift; + local_sec_strength = cdef_sec_uv_strength << coeff_shift; + local_damping -= 1; + if cdef_pri_uv_strength != 0 { + if xdec != ydec { + [7, 0, 2, 4, 5, 6, 6, 6][dir as usize] + } else { + dir as usize + } + } else { + 0 + } + }; + + // SAFETY: `cdef_filter_block` may call Assembly code. + // The asserts here verify that we are not calling it + // with invalid parameters. + unsafe { + assert!( + input.planes[p].cfg.width as isize + >= in_po.x + + xsize as isize + + if edges & CDEF_HAVE_RIGHT > 0 { 2 } else { 0 } + ); + assert!( + 0 <= in_po.x - if edges & CDEF_HAVE_LEFT > 0 { 2 } else { 0 } + ); + assert!( + input.planes[p].cfg.height as isize + >= in_po.y + + ysize as isize + + if edges & CDEF_HAVE_BOTTOM > 0 { 2 } else { 0 } + ); + assert!( + 0 <= in_po.y - if edges & CDEF_HAVE_TOP > 0 { 2 } else { 0 } + ); + + cdef_filter_block( + out_block, + in_slice.as_ptr(), + in_stride as isize, + local_pri_strength, + local_sec_strength, + local_dir, + local_damping, + bit_depth, + xdec, + ydec, + edges, + fi.cpu_feature_level, + ); + } + } else { + // no filtering, but we need to copy input to output + for i in 0..ysize { + for j in 0..xsize { + out_block[i][j] = in_slice[i][j]; + } + } + } + } + } + edges |= CDEF_HAVE_LEFT; + } + edges |= CDEF_HAVE_TOP; + } +} + +// The purpose of CDEF is to perform deringing based on the detected +// direction of blocks. CDEF parameters are stored for each 64 by 64 +// block of pixels. The CDEF filter is applied on each 8 by 8 block +// of pixels. Reference: +// http://av1-spec.argondesign.com/av1-spec/av1-spec.html#cdef-process + +// input: A Frame of reconstructed/deblocked pixels prepared to +// undergo CDEF. cdef_filter_tile acts on a subset of these input +// pixels, as specified by the PlaneRegion rect of the output. Note +// that the input is a Frame and not a Tile due to Tiles not +// allowing [supervised] out-of-rect access for padding pixels. +// This will be corrected at some point in the future. + +// tb: the TileBlocks associated with the filtered region; the +// provided blocks co-locate with the output region. + +// output: TileMut destination for filtered pixels. The output's +// rect specifies the region of the input to be processed (x and y +// are relative to the input Frame's origin). Note that an +// additional area of 2 pixels of padding is used for CDEF. When +// these pixels are unavailable (beyond the visible frame or at a +// tile boundary), the filtering process ignores input pixels that +// don't exist. + +#[profiling::function] +pub fn cdef_filter_tile( + fi: &FrameInvariants, input: &Frame, tb: &TileBlocks, + output: &mut TileMut<'_, T>, +) { + // Each filter block is 64x64, except right and/or bottom for non-multiple-of-64 sizes. + // FIXME: 128x128 SB support will break this, we need FilterBlockOffset etc. + + // No need to guard against having fewer actual coded blocks than + // the output.rect() area. Inner code already guards this case. + let fb_width = output.planes[0].rect().width.div_ceil(64); + let fb_height = output.planes[0].rect().height.div_ceil(64); + + // should parallelize this + for fby in 0..fb_height { + for fbx in 0..fb_width { + // tile_sbo is treated as an offset into the Tiles' plane + // regions, not as an absolute offset in the visible frame. The + // Tile's own offset is added to this in order to address into + // the input Frame. + let tile_sbo = TileSuperBlockOffset(SuperBlockOffset { x: fbx, y: fby }); + let cdef_index = tb.get_cdef(tile_sbo); + let cdef_dirs = cdef_analyze_superblock(fi, input, tb, tile_sbo); + + cdef_filter_superblock( + fi, input, output, tb, tile_sbo, cdef_index, &cdef_dirs, + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/block_unit.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/block_unit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/block_unit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/block_unit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2017 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::mem::MaybeUninit; + +use super::*; + +use crate::predict::PredictionMode; + +pub const MAX_PLANES: usize = 3; + +pub const BLOCK_SIZE_GROUPS: usize = 4; +pub const MAX_ANGLE_DELTA: usize = 3; +pub const DIRECTIONAL_MODES: usize = 8; +pub const KF_MODE_CONTEXTS: usize = 5; + +pub const INTRA_INTER_CONTEXTS: usize = 4; +pub const INTER_MODE_CONTEXTS: usize = 8; +pub const DRL_MODE_CONTEXTS: usize = 3; +pub const COMP_INTER_CONTEXTS: usize = 5; +pub const COMP_REF_TYPE_CONTEXTS: usize = 5; +pub const UNI_COMP_REF_CONTEXTS: usize = 3; + +pub const PLANE_TYPES: usize = 2; +const REF_TYPES: usize = 2; + +pub const COMP_INDEX_CONTEXTS: usize = 6; +pub const COMP_GROUP_IDX_CONTEXTS: usize = 6; + +pub const COEFF_CONTEXT_MAX_WIDTH: usize = MAX_TILE_WIDTH / MI_SIZE; + +/// Absolute offset in blocks, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct BlockOffset { + pub x: usize, + pub y: usize, +} + +/// Absolute offset in blocks inside a plane, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PlaneBlockOffset(pub BlockOffset); + +/// Absolute offset in blocks inside a tile, where a block is defined +/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct TileBlockOffset(pub BlockOffset); + +impl BlockOffset { + /// Offset of the superblock in which this block is located. + #[inline] + const fn sb_offset(self) -> SuperBlockOffset { + SuperBlockOffset { + x: self.x >> SUPERBLOCK_TO_BLOCK_SHIFT, + y: self.y >> SUPERBLOCK_TO_BLOCK_SHIFT, + } + } + + /// Offset of the top-left pixel of this block. + #[inline] + const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + PlaneOffset { + x: (self.x >> plane.xdec << BLOCK_TO_PLANE_SHIFT) as isize, + y: (self.y >> plane.ydec << BLOCK_TO_PLANE_SHIFT) as isize, + } + } + + /// Convert to plane offset without decimation. + #[inline] + const fn to_luma_plane_offset(self) -> PlaneOffset { + PlaneOffset { + x: (self.x as isize) << BLOCK_TO_PLANE_SHIFT, + y: (self.y as isize) << BLOCK_TO_PLANE_SHIFT, + } + } + + #[inline] + const fn y_in_sb(self) -> usize { + self.y % MIB_SIZE + } + + #[inline] + fn with_offset(self, col_offset: isize, row_offset: isize) -> BlockOffset { + let x = self.x as isize + col_offset; + let y = self.y as isize + row_offset; + debug_assert!(x >= 0); + debug_assert!(y >= 0); + + BlockOffset { x: x as usize, y: y as usize } + } +} + +impl PlaneBlockOffset { + /// Offset of the superblock in which this block is located. + #[inline] + pub const fn sb_offset(self) -> PlaneSuperBlockOffset { + PlaneSuperBlockOffset(self.0.sb_offset()) + } + + /// Offset of the top-left pixel of this block. + #[inline] + pub const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + self.0.plane_offset(plane) + } + + /// Convert to plane offset without decimation. + #[inline] + pub const fn to_luma_plane_offset(self) -> PlaneOffset { + self.0.to_luma_plane_offset() + } + + #[inline] + pub const fn y_in_sb(self) -> usize { + self.0.y_in_sb() + } + + #[inline] + pub fn with_offset( + self, col_offset: isize, row_offset: isize, + ) -> PlaneBlockOffset { + Self(self.0.with_offset(col_offset, row_offset)) + } +} + +impl TileBlockOffset { + /// Offset of the superblock in which this block is located. + #[inline] + pub const fn sb_offset(self) -> TileSuperBlockOffset { + TileSuperBlockOffset(self.0.sb_offset()) + } + + /// Offset of the top-left pixel of this block. + #[inline] + pub const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + self.0.plane_offset(plane) + } + + /// Convert to plane offset without decimation. + #[inline] + pub const fn to_luma_plane_offset(self) -> PlaneOffset { + self.0.to_luma_plane_offset() + } + + #[inline] + pub const fn y_in_sb(self) -> usize { + self.0.y_in_sb() + } + + #[inline] + pub fn with_offset( + self, col_offset: isize, row_offset: isize, + ) -> TileBlockOffset { + Self(self.0.with_offset(col_offset, row_offset)) + } +} + +#[derive(Copy, Clone)] +pub struct Block { + pub mode: PredictionMode, + pub partition: PartitionType, + pub skip: bool, + pub ref_frames: [RefType; 2], + pub mv: [MotionVector; 2], + // note: indexes are reflist index, NOT the same as libaom + pub neighbors_ref_counts: [u8; INTER_REFS_PER_FRAME], + pub cdef_index: u8, + pub bsize: BlockSize, + pub n4_w: u8, /* block width in the unit of mode_info */ + pub n4_h: u8, /* block height in the unit of mode_info */ + pub txsize: TxSize, + // The block-level deblock_deltas are left-shifted by + // fi.deblock.block_delta_shift and added to the frame-configured + // deltas + pub deblock_deltas: [i8; FRAME_LF_COUNT], + pub segmentation_idx: u8, +} + +impl Block { + pub fn is_inter(&self) -> bool { + self.mode >= PredictionMode::NEARESTMV + } + pub fn has_second_ref(&self) -> bool { + self.ref_frames[1] != INTRA_FRAME && self.ref_frames[1] != NONE_FRAME + } +} + +impl Default for Block { + fn default() -> Block { + Block { + mode: PredictionMode::DC_PRED, + partition: PartitionType::PARTITION_NONE, + skip: false, + ref_frames: [INTRA_FRAME; 2], + mv: [MotionVector::default(); 2], + neighbors_ref_counts: [0; INTER_REFS_PER_FRAME], + cdef_index: 0, + bsize: BLOCK_64X64, + n4_w: BLOCK_64X64.width_mi() as u8, + n4_h: BLOCK_64X64.height_mi() as u8, + txsize: TX_64X64, + deblock_deltas: [0, 0, 0, 0], + segmentation_idx: 0, + } + } +} + +#[derive(Clone)] +pub struct BlockContextCheckpoint { + x: usize, + chroma_sampling: ChromaSampling, + cdef_coded: bool, + above_partition_context: [u8; MIB_SIZE >> 1], + // left context is also at 8x8 granularity + left_partition_context: [u8; MIB_SIZE >> 1], + above_tx_context: [u8; MIB_SIZE], + left_tx_context: [u8; MIB_SIZE], + above_coeff_context: [[u8; MIB_SIZE]; MAX_PLANES], + left_coeff_context: [[u8; MIB_SIZE]; MAX_PLANES], +} + +pub struct BlockContext<'a> { + pub cdef_coded: bool, + pub code_deltas: bool, + pub update_seg: bool, + pub preskip_segid: bool, + pub above_partition_context: [u8; PARTITION_CONTEXT_MAX_WIDTH], + pub left_partition_context: [u8; MIB_SIZE >> 1], + pub above_tx_context: [u8; COEFF_CONTEXT_MAX_WIDTH], + pub left_tx_context: [u8; MIB_SIZE], + pub above_coeff_context: [[u8; COEFF_CONTEXT_MAX_WIDTH]; MAX_PLANES], + pub left_coeff_context: [[u8; MIB_SIZE]; MAX_PLANES], + pub blocks: &'a mut TileBlocksMut<'a>, +} + +impl<'a> BlockContext<'a> { + pub fn new(blocks: &'a mut TileBlocksMut<'a>) -> Self { + BlockContext { + cdef_coded: false, + code_deltas: false, + update_seg: false, + preskip_segid: false, + above_partition_context: [0; PARTITION_CONTEXT_MAX_WIDTH], + left_partition_context: [0; MIB_SIZE >> 1], + above_tx_context: [0; COEFF_CONTEXT_MAX_WIDTH], + left_tx_context: [0; MIB_SIZE], + above_coeff_context: [ + [0; COEFF_CONTEXT_MAX_WIDTH], + [0; COEFF_CONTEXT_MAX_WIDTH], + [0; COEFF_CONTEXT_MAX_WIDTH], + ], + left_coeff_context: [[0; MIB_SIZE]; MAX_PLANES], + blocks, + } + } + + pub fn checkpoint( + &self, tile_bo: &TileBlockOffset, chroma_sampling: ChromaSampling, + ) -> BlockContextCheckpoint { + let x = tile_bo.0.x & (COEFF_CONTEXT_MAX_WIDTH - MIB_SIZE); + let mut checkpoint = BlockContextCheckpoint { + x, + chroma_sampling, + cdef_coded: self.cdef_coded, + above_partition_context: [0; MIB_SIZE >> 1], + left_partition_context: self.left_partition_context, + above_tx_context: [0; MIB_SIZE], + left_tx_context: self.left_tx_context, + above_coeff_context: [[0; MIB_SIZE]; MAX_PLANES], + left_coeff_context: self.left_coeff_context, + }; + checkpoint.above_partition_context.copy_from_slice( + &self.above_partition_context[(x >> 1)..][..(MIB_SIZE >> 1)], + ); + checkpoint + .above_tx_context + .copy_from_slice(&self.above_tx_context[x..][..MIB_SIZE]); + let num_planes = + if chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + for (p, (dst, src)) in checkpoint + .above_coeff_context + .iter_mut() + .zip(self.above_coeff_context.iter()) + .enumerate() + .take(num_planes) + { + let xdec = (p > 0 && chroma_sampling != ChromaSampling::Cs444) as usize; + dst.copy_from_slice(&src[(x >> xdec)..][..MIB_SIZE]); + } + checkpoint + } + + pub fn rollback(&mut self, checkpoint: &BlockContextCheckpoint) { + let x = checkpoint.x & (COEFF_CONTEXT_MAX_WIDTH - MIB_SIZE); + self.cdef_coded = checkpoint.cdef_coded; + self.above_partition_context[(x >> 1)..][..(MIB_SIZE >> 1)] + .copy_from_slice(&checkpoint.above_partition_context); + self.left_partition_context = checkpoint.left_partition_context; + self.above_tx_context[x..][..MIB_SIZE] + .copy_from_slice(&checkpoint.above_tx_context); + self.left_tx_context = checkpoint.left_tx_context; + let num_planes = + if checkpoint.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + for (p, (dst, src)) in self + .above_coeff_context + .iter_mut() + .zip(checkpoint.above_coeff_context.iter()) + .enumerate() + .take(num_planes) + { + let xdec = (p > 0 && checkpoint.chroma_sampling != ChromaSampling::Cs444) + as usize; + dst[(x >> xdec)..][..MIB_SIZE].copy_from_slice(src); + } + self.left_coeff_context = checkpoint.left_coeff_context; + } + + #[inline] + pub fn set_dc_sign(cul_level: &mut u32, dc_val: i32) { + if dc_val < 0 { + *cul_level |= 1 << COEFF_CONTEXT_BITS; + } else if dc_val > 0 { + *cul_level += 2 << COEFF_CONTEXT_BITS; + } + } + + pub fn set_coeff_context( + &mut self, plane: usize, bo: TileBlockOffset, tx_size: TxSize, + xdec: usize, ydec: usize, value: u8, + ) { + for above in &mut self.above_coeff_context[plane][(bo.0.x >> xdec)..] + [..tx_size.width_mi()] + { + *above = value; + } + let bo_y = bo.y_in_sb(); + for left in &mut self.left_coeff_context[plane][(bo_y >> ydec)..] + [..tx_size.height_mi()] + { + *left = value; + } + } + + fn reset_left_coeff_context(&mut self, plane: usize) { + for c in &mut self.left_coeff_context[plane] { + *c = 0; + } + } + + fn reset_left_partition_context(&mut self) { + for c in &mut self.left_partition_context { + *c = 0; + } + } + + pub fn update_tx_size_context( + &mut self, bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize, + skip: bool, + ) { + let n4_w = bsize.width_mi(); + let n4_h = bsize.height_mi(); + + let (tx_w, tx_h) = if skip { + ((n4_w * MI_SIZE) as u8, (n4_h * MI_SIZE) as u8) + } else { + (tx_size.width() as u8, tx_size.height() as u8) + }; + + let above_ctx = &mut self.above_tx_context[bo.0.x..bo.0.x + n4_w]; + let left_ctx = + &mut self.left_tx_context[bo.y_in_sb()..bo.y_in_sb() + n4_h]; + + for v in above_ctx[0..n4_w].iter_mut() { + *v = tx_w; + } + + for v in left_ctx[0..n4_h].iter_mut() { + *v = tx_h; + } + } + + fn reset_left_tx_context(&mut self) { + for c in &mut self.left_tx_context { + *c = 0; + } + } + + pub fn reset_left_contexts(&mut self, planes: usize) { + for p in 0..planes { + BlockContext::reset_left_coeff_context(self, p); + } + BlockContext::reset_left_partition_context(self); + + BlockContext::reset_left_tx_context(self); + } + + // The mode info data structure has a one element border above and to the + // left of the entries corresponding to real macroblocks. + // The prediction flags in these dummy entries are initialized to 0. + // 0 - inter/inter, inter/--, --/inter, --/-- + // 1 - intra/inter, inter/intra + // 2 - intra/--, --/intra + // 3 - intra/intra + pub fn intra_inter_context(&self, bo: TileBlockOffset) -> usize { + let has_above = bo.0.y > 0; + let has_left = bo.0.x > 0; + + match (has_above, has_left) { + (true, true) => { + let above_intra = !self.blocks.above_of(bo).is_inter(); + let left_intra = !self.blocks.left_of(bo).is_inter(); + if above_intra && left_intra { + 3 + } else { + (above_intra || left_intra) as usize + } + } + (true, false) => { + if self.blocks.above_of(bo).is_inter() { + 0 + } else { + 2 + } + } + (false, true) => { + if self.blocks.left_of(bo).is_inter() { + 0 + } else { + 2 + } + } + _ => 0, + } + } + + pub fn get_txb_ctx( + &self, plane_bsize: BlockSize, tx_size: TxSize, plane: usize, + bo: TileBlockOffset, xdec: usize, ydec: usize, frame_clipped_txw: usize, + frame_clipped_txh: usize, + ) -> TXB_CTX { + let mut txb_ctx = TXB_CTX { txb_skip_ctx: 0, dc_sign_ctx: 0 }; + const MAX_TX_SIZE_UNIT: usize = 16; + const signs: [i8; 3] = [0, -1, 1]; + const dc_sign_contexts: [usize; 4 * MAX_TX_SIZE_UNIT + 1] = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + ]; + let mut dc_sign: i16 = 0; + + let above_ctxs = &self.above_coeff_context[plane][(bo.0.x >> xdec)..] + [..frame_clipped_txw >> 2]; + let left_ctxs = &self.left_coeff_context[plane][(bo.y_in_sb() >> ydec)..] + [..frame_clipped_txh >> 2]; + + // Decide txb_ctx.dc_sign_ctx + for &ctx in above_ctxs { + let sign = ctx >> COEFF_CONTEXT_BITS; + dc_sign += signs[sign as usize] as i16; + } + + for &ctx in left_ctxs { + let sign = ctx >> COEFF_CONTEXT_BITS; + dc_sign += signs[sign as usize] as i16; + } + + txb_ctx.dc_sign_ctx = + dc_sign_contexts[(dc_sign + 2 * MAX_TX_SIZE_UNIT as i16) as usize]; + + // Decide txb_ctx.txb_skip_ctx + if plane == 0 { + if plane_bsize == tx_size.block_size() { + txb_ctx.txb_skip_ctx = 0; + } else { + // This is the algorithm to generate table skip_contexts[min][max]. + // if (!max) + // txb_skip_ctx = 1; + // else if (!min) + // txb_skip_ctx = 2 + (max > 3); + // else if (max <= 3) + // txb_skip_ctx = 4; + // else if (min <= 3) + // txb_skip_ctx = 5; + // else + // txb_skip_ctx = 6; + const skip_contexts: [[u8; 5]; 5] = [ + [1, 2, 2, 2, 3], + [1, 4, 4, 4, 5], + [1, 4, 4, 4, 5], + [1, 4, 4, 4, 5], + [1, 4, 4, 4, 6], + ]; + + let top: u8 = above_ctxs.iter().fold(0, |acc, ctx| acc | *ctx) + & COEFF_CONTEXT_MASK as u8; + + let left: u8 = left_ctxs.iter().fold(0, |acc, ctx| acc | *ctx) + & COEFF_CONTEXT_MASK as u8; + + let max = cmp::min(top | left, 4); + let min = cmp::min(cmp::min(top, left), 4); + txb_ctx.txb_skip_ctx = + skip_contexts[min as usize][max as usize] as usize; + } + } else { + let top: u8 = above_ctxs.iter().fold(0, |acc, ctx| acc | *ctx); + let left: u8 = left_ctxs.iter().fold(0, |acc, ctx| acc | *ctx); + let ctx_base = (top != 0) as usize + (left != 0) as usize; + let ctx_offset = if num_pels_log2_lookup[plane_bsize as usize] + > num_pels_log2_lookup[tx_size.block_size() as usize] + { + 10 + } else { + 7 + }; + txb_ctx.txb_skip_ctx = ctx_base + ctx_offset; + } + + txb_ctx + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct NMVComponent { + pub sign_cdf: [u16; 2], + pub class0_hp_cdf: [u16; 2], + pub hp_cdf: [u16; 2], + pub class0_cdf: [u16; CLASS0_SIZE], + pub bits_cdf: [[u16; 2]; MV_OFFSET_BITS], + + pub class0_fp_cdf: [[u16; MV_FP_SIZE]; CLASS0_SIZE], + pub fp_cdf: [u16; MV_FP_SIZE], + + pub classes_cdf: [u16; MV_CLASSES], + // MV_CLASSES + 5 == 16; pad the last CDF for rollback. + padding: [u16; 5], +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct NMVContext { + pub joints_cdf: [u16; MV_JOINTS], + // MV_JOINTS + 12 == 16; pad the last CDF for rollback. + padding: [u16; 12], + pub comps: [NMVComponent; 2], +} + +// lv_map +pub static default_nmv_context: NMVContext = { + NMVContext { + joints_cdf: cdf([4096, 11264, 19328]), + padding: [0; 12], + comps: [ + NMVComponent { + classes_cdf: cdf([ + 28672, 30976, 31858, 32320, 32551, 32656, 32740, 32757, 32762, 32767, + ]), + class0_fp_cdf: cdf_2d([[16384, 24576, 26624], [12288, 21248, 24128]]), + fp_cdf: cdf([8192, 17408, 21248]), + sign_cdf: cdf([128 * 128]), + class0_hp_cdf: cdf([160 * 128]), + hp_cdf: cdf([128 * 128]), + class0_cdf: cdf([216 * 128]), + bits_cdf: cdf_2d([ + [128 * 136], + [128 * 140], + [128 * 148], + [128 * 160], + [128 * 176], + [128 * 192], + [128 * 224], + [128 * 234], + [128 * 234], + [128 * 240], + ]), + padding: [0; 5], + }, + NMVComponent { + classes_cdf: cdf([ + 28672, 30976, 31858, 32320, 32551, 32656, 32740, 32757, 32762, 32767, + ]), + class0_fp_cdf: cdf_2d([[16384, 24576, 26624], [12288, 21248, 24128]]), + fp_cdf: cdf([8192, 17408, 21248]), + sign_cdf: cdf([128 * 128]), + class0_hp_cdf: cdf([160 * 128]), + hp_cdf: cdf([128 * 128]), + class0_cdf: cdf([216 * 128]), + bits_cdf: cdf_2d([ + [128 * 136], + [128 * 140], + [128 * 148], + [128 * 160], + [128 * 176], + [128 * 192], + [128 * 224], + [128 * 234], + [128 * 234], + [128 * 240], + ]), + padding: [0; 5], + }, + ], + } +}; + +#[derive(Clone)] +pub struct CandidateMV { + pub this_mv: MotionVector, + pub comp_mv: MotionVector, + pub weight: u32, +} + +#[derive(Clone)] +pub struct FrameBlocks { + blocks: Box<[Block]>, + pub cols: usize, + pub rows: usize, +} + +impl FrameBlocks { + pub fn new(cols: usize, rows: usize) -> Self { + Self { + blocks: vec![Block::default(); cols * rows].into_boxed_slice(), + cols, + rows, + } + } + + #[inline(always)] + pub fn as_tile_blocks(&self) -> TileBlocks<'_> { + TileBlocks::new(self, 0, 0, self.cols, self.rows) + } + + #[inline(always)] + pub fn as_tile_blocks_mut(&mut self) -> TileBlocksMut<'_> { + TileBlocksMut::new(self, 0, 0, self.cols, self.rows) + } +} + +impl Index for FrameBlocks { + type Output = [Block]; + #[inline] + fn index(&self, index: usize) -> &Self::Output { + &self.blocks[index * self.cols..(index + 1) * self.cols] + } +} + +impl IndexMut for FrameBlocks { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.blocks[index * self.cols..(index + 1) * self.cols] + } +} + +// for convenience, also index by BlockOffset + +impl Index for FrameBlocks { + type Output = Block; + #[inline] + fn index(&self, bo: PlaneBlockOffset) -> &Self::Output { + &self[bo.0.y][bo.0.x] + } +} + +impl IndexMut for FrameBlocks { + #[inline] + fn index_mut(&mut self, bo: PlaneBlockOffset) -> &mut Self::Output { + &mut self[bo.0.y][bo.0.x] + } +} + +impl ContextWriter<'_> { + pub fn get_cdf_intra_mode_kf( + &self, bo: TileBlockOffset, + ) -> &[u16; INTRA_MODES] { + static intra_mode_context: [usize; INTRA_MODES] = + [0, 1, 2, 3, 4, 4, 4, 4, 3, 0, 1, 2, 0]; + let above_mode = if bo.0.y > 0 { + self.bc.blocks.above_of(bo).mode + } else { + PredictionMode::DC_PRED + }; + let left_mode = if bo.0.x > 0 { + self.bc.blocks.left_of(bo).mode + } else { + PredictionMode::DC_PRED + }; + let above_ctx = intra_mode_context[above_mode as usize]; + let left_ctx = intra_mode_context[left_mode as usize]; + &self.fc.kf_y_cdf[above_ctx][left_ctx] + } + + pub fn write_intra_mode_kf( + &mut self, w: &mut W, bo: TileBlockOffset, mode: PredictionMode, + ) { + static intra_mode_context: [usize; INTRA_MODES] = + [0, 1, 2, 3, 4, 4, 4, 4, 3, 0, 1, 2, 0]; + let above_mode = if bo.0.y > 0 { + self.bc.blocks.above_of(bo).mode + } else { + PredictionMode::DC_PRED + }; + let left_mode = if bo.0.x > 0 { + self.bc.blocks.left_of(bo).mode + } else { + PredictionMode::DC_PRED + }; + let above_ctx = intra_mode_context[above_mode as usize]; + let left_ctx = intra_mode_context[left_mode as usize]; + let cdf = &self.fc.kf_y_cdf[above_ctx][left_ctx]; + symbol_with_update!(self, w, mode as u32, cdf); + } + + pub fn get_cdf_intra_mode(&self, bsize: BlockSize) -> &[u16; INTRA_MODES] { + &self.fc.y_mode_cdf[size_group_lookup[bsize as usize] as usize] + } + + #[inline] + pub fn write_intra_mode( + &mut self, w: &mut W, bsize: BlockSize, mode: PredictionMode, + ) { + let cdf = &self.fc.y_mode_cdf[size_group_lookup[bsize as usize] as usize]; + symbol_with_update!(self, w, mode as u32, cdf); + } + + #[inline] + pub fn write_intra_uv_mode( + &mut self, w: &mut W, uv_mode: PredictionMode, y_mode: PredictionMode, + bs: BlockSize, + ) { + if bs.cfl_allowed() { + let cdf = &self.fc.uv_mode_cfl_cdf[y_mode as usize]; + symbol_with_update!(self, w, uv_mode as u32, cdf); + } else { + let cdf = &self.fc.uv_mode_cdf[y_mode as usize]; + symbol_with_update!(self, w, uv_mode as u32, cdf); + } + } + + #[inline] + pub fn write_angle_delta( + &mut self, w: &mut W, angle: i8, mode: PredictionMode, + ) { + symbol_with_update!( + self, + w, + (angle + MAX_ANGLE_DELTA as i8) as u32, + &self.fc.angle_delta_cdf + [mode as usize - PredictionMode::V_PRED as usize] + ); + } + + pub fn write_use_filter_intra( + &mut self, w: &mut W, enable: bool, block_size: BlockSize, + ) { + let cdf = &self.fc.filter_intra_cdfs[block_size as usize]; + symbol_with_update!(self, w, enable as u32, cdf); + } + + /// # Panics + /// + /// - If called with `enable: true` (not yet implemented + pub fn write_use_palette_mode( + &mut self, w: &mut W, enable: bool, bsize: BlockSize, bo: TileBlockOffset, + luma_mode: PredictionMode, chroma_mode: PredictionMode, xdec: usize, + ydec: usize, cs: ChromaSampling, + ) { + if enable { + unimplemented!(); // TODO + } + + let (ctx_luma, ctx_chroma) = (0, 0); // TODO: increase based on surrounding block info + + if luma_mode == PredictionMode::DC_PRED { + let bsize_ctx = bsize.width_mi_log2() + bsize.height_mi_log2() - 2; + let cdf = &self.fc.palette_y_mode_cdfs[bsize_ctx][ctx_luma]; + symbol_with_update!(self, w, enable as u32, cdf); + } + + if has_chroma(bo, bsize, xdec, ydec, cs) + && chroma_mode == PredictionMode::DC_PRED + { + let cdf = &self.fc.palette_uv_mode_cdfs[ctx_chroma]; + symbol_with_update!(self, w, enable as u32, cdf); + } + } + + fn find_valid_row_offs( + row_offset: isize, mi_row: usize, mi_rows: usize, + ) -> isize { + cmp::min( + cmp::max(row_offset, -(mi_row as isize)), + (mi_rows - mi_row - 1) as isize, + ) + } + + fn find_valid_col_offs( + col_offset: isize, mi_col: usize, mi_cols: usize, + ) -> isize { + cmp::min( + cmp::max(col_offset, -(mi_col as isize)), + (mi_cols - mi_col - 1) as isize, + ) + } + + fn find_matching_mv( + mv: MotionVector, mv_stack: &mut ArrayVec, + ) -> bool { + for mv_cand in mv_stack { + if mv.row == mv_cand.this_mv.row && mv.col == mv_cand.this_mv.col { + return true; + } + } + false + } + + fn find_matching_mv_and_update_weight( + mv: MotionVector, mv_stack: &mut ArrayVec, weight: u32, + ) -> bool { + for mv_cand in mv_stack { + if mv.row == mv_cand.this_mv.row && mv.col == mv_cand.this_mv.col { + mv_cand.weight += weight; + return true; + } + } + false + } + + fn find_matching_comp_mv_and_update_weight( + mvs: [MotionVector; 2], mv_stack: &mut ArrayVec, + weight: u32, + ) -> bool { + for mv_cand in mv_stack { + if mvs[0].row == mv_cand.this_mv.row + && mvs[0].col == mv_cand.this_mv.col + && mvs[1].row == mv_cand.comp_mv.row + && mvs[1].col == mv_cand.comp_mv.col + { + mv_cand.weight += weight; + return true; + } + } + false + } + + fn add_ref_mv_candidate( + ref_frames: [RefType; 2], blk: &Block, + mv_stack: &mut ArrayVec, weight: u32, + newmv_count: &mut usize, is_compound: bool, + ) -> bool { + if !blk.is_inter() { + /* For intrabc */ + false + } else if is_compound { + if blk.ref_frames[0] == ref_frames[0] + && blk.ref_frames[1] == ref_frames[1] + { + let found_match = Self::find_matching_comp_mv_and_update_weight( + blk.mv, mv_stack, weight, + ); + + if !found_match && mv_stack.len() < MAX_REF_MV_STACK_SIZE { + let mv_cand = + CandidateMV { this_mv: blk.mv[0], comp_mv: blk.mv[1], weight }; + + mv_stack.push(mv_cand); + } + + if blk.mode.has_newmv() { + *newmv_count += 1; + } + + true + } else { + false + } + } else { + let mut found = false; + for i in 0..2 { + if blk.ref_frames[i] == ref_frames[0] { + let found_match = Self::find_matching_mv_and_update_weight( + blk.mv[i], mv_stack, weight, + ); + + if !found_match && mv_stack.len() < MAX_REF_MV_STACK_SIZE { + let mv_cand = CandidateMV { + this_mv: blk.mv[i], + comp_mv: MotionVector::default(), + weight, + }; + + mv_stack.push(mv_cand); + } + + if blk.mode.has_newmv() { + *newmv_count += 1; + } + + found = true; + } + } + found + } + } + + fn add_extra_mv_candidate( + blk: &Block, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, fi: &FrameInvariants, + is_compound: bool, ref_id_count: &mut [usize; 2], + ref_id_mvs: &mut [[MotionVector; 2]; 2], ref_diff_count: &mut [usize; 2], + ref_diff_mvs: &mut [[MotionVector; 2]; 2], + ) { + if is_compound { + for cand_list in 0..2 { + let cand_ref = blk.ref_frames[cand_list]; + if cand_ref != INTRA_FRAME && cand_ref != NONE_FRAME { + for list in 0..2 { + let mut cand_mv = blk.mv[cand_list]; + if cand_ref == ref_frames[list] && ref_id_count[list] < 2 { + ref_id_mvs[list][ref_id_count[list]] = cand_mv; + ref_id_count[list] += 1; + } else if ref_diff_count[list] < 2 { + if fi.ref_frame_sign_bias[cand_ref.to_index()] + != fi.ref_frame_sign_bias[ref_frames[list].to_index()] + { + cand_mv.row = -cand_mv.row; + cand_mv.col = -cand_mv.col; + } + ref_diff_mvs[list][ref_diff_count[list]] = cand_mv; + ref_diff_count[list] += 1; + } + } + } + } + } else { + for cand_list in 0..2 { + let cand_ref = blk.ref_frames[cand_list]; + if cand_ref != INTRA_FRAME && cand_ref != NONE_FRAME { + let mut mv = blk.mv[cand_list]; + if fi.ref_frame_sign_bias[cand_ref.to_index()] + != fi.ref_frame_sign_bias[ref_frames[0].to_index()] + { + mv.row = -mv.row; + mv.col = -mv.col; + } + + if !Self::find_matching_mv(mv, mv_stack) { + let mv_cand = CandidateMV { + this_mv: mv, + comp_mv: MotionVector::default(), + weight: 2, + }; + mv_stack.push(mv_cand); + } + } + } + } + } + + fn scan_row_mbmi( + &self, bo: TileBlockOffset, row_offset: isize, max_row_offs: isize, + processed_rows: &mut isize, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, newmv_count: &mut usize, + bsize: BlockSize, is_compound: bool, + ) -> bool { + let bc = &self.bc; + let target_n4_w = bsize.width_mi(); + + let end_mi = cmp::min( + cmp::min(target_n4_w, bc.blocks.cols() - bo.0.x), + BLOCK_64X64.width_mi(), + ); + let n4_w_8 = BLOCK_8X8.width_mi(); + let n4_w_16 = BLOCK_16X16.width_mi(); + let mut col_offset = 0; + + if row_offset.abs() > 1 { + col_offset = 1; + if ((bo.0.x & 0x01) != 0) && (target_n4_w < n4_w_8) { + col_offset -= 1; + } + } + + let use_step_16 = target_n4_w >= 16; + + let mut found_match = false; + + let mut i = 0; + while i < end_mi { + let cand = + &bc.blocks[bo.with_offset(col_offset + i as isize, row_offset)]; + + let n4_w = cand.n4_w as usize; + let mut len = cmp::min(target_n4_w, n4_w); + if use_step_16 { + len = cmp::max(n4_w_16, len); + } else if row_offset.abs() > 1 { + len = cmp::max(len, n4_w_8); + } + + let mut weight: u32 = 2; + if target_n4_w >= n4_w_8 && target_n4_w <= n4_w { + let inc = cmp::min(-max_row_offs + row_offset + 1, cand.n4_h as isize); + assert!(inc >= 0); + weight = cmp::max(weight, inc as u32); + *processed_rows = inc - row_offset - 1; + } + + if Self::add_ref_mv_candidate( + ref_frames, + cand, + mv_stack, + len as u32 * weight, + newmv_count, + is_compound, + ) { + found_match = true; + } + + i += len; + } + + found_match + } + + fn scan_col_mbmi( + &self, bo: TileBlockOffset, col_offset: isize, max_col_offs: isize, + processed_cols: &mut isize, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, newmv_count: &mut usize, + bsize: BlockSize, is_compound: bool, + ) -> bool { + let bc = &self.bc; + + let target_n4_h = bsize.height_mi(); + + let end_mi = cmp::min( + cmp::min(target_n4_h, bc.blocks.rows() - bo.0.y), + BLOCK_64X64.height_mi(), + ); + let n4_h_8 = BLOCK_8X8.height_mi(); + let n4_h_16 = BLOCK_16X16.height_mi(); + let mut row_offset = 0; + + if col_offset.abs() > 1 { + row_offset = 1; + if ((bo.0.y & 0x01) != 0) && (target_n4_h < n4_h_8) { + row_offset -= 1; + } + } + + let use_step_16 = target_n4_h >= 16; + + let mut found_match = false; + + let mut i = 0; + while i < end_mi { + let cand = + &bc.blocks[bo.with_offset(col_offset, row_offset + i as isize)]; + let n4_h = cand.n4_h as usize; + let mut len = cmp::min(target_n4_h, n4_h); + if use_step_16 { + len = cmp::max(n4_h_16, len); + } else if col_offset.abs() > 1 { + len = cmp::max(len, n4_h_8); + } + + let mut weight: u32 = 2; + if target_n4_h >= n4_h_8 && target_n4_h <= n4_h { + let inc = cmp::min(-max_col_offs + col_offset + 1, cand.n4_w as isize); + assert!(inc >= 0); + weight = cmp::max(weight, inc as u32); + *processed_cols = inc - col_offset - 1; + } + + if Self::add_ref_mv_candidate( + ref_frames, + cand, + mv_stack, + len as u32 * weight, + newmv_count, + is_compound, + ) { + found_match = true; + } + + i += len; + } + + found_match + } + + fn scan_blk_mbmi( + &self, bo: TileBlockOffset, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, newmv_count: &mut usize, + is_compound: bool, + ) -> bool { + if bo.0.x >= self.bc.blocks.cols() || bo.0.y >= self.bc.blocks.rows() { + return false; + } + + let weight = 2 * BLOCK_8X8.width_mi() as u32; + /* Always assume its within a tile, probably wrong */ + Self::add_ref_mv_candidate( + ref_frames, + &self.bc.blocks[bo], + mv_stack, + weight, + newmv_count, + is_compound, + ) + } + + fn add_offset(mv_stack: &mut ArrayVec) { + for cand_mv in mv_stack { + cand_mv.weight += REF_CAT_LEVEL; + } + } + + #[profiling::function] + fn setup_mvref_list( + &self, bo: TileBlockOffset, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, bsize: BlockSize, + fi: &FrameInvariants, is_compound: bool, + ) -> usize { + let (_rf, _rf_num) = (INTRA_FRAME, 1); + + let target_n4_h = bsize.height_mi(); + let target_n4_w = bsize.width_mi(); + + let mut max_row_offs: isize = 0; + let row_adj = + (target_n4_h < BLOCK_8X8.height_mi()) && (bo.0.y & 0x01) != 0x0; + + let mut max_col_offs: isize = 0; + let col_adj = + (target_n4_w < BLOCK_8X8.width_mi()) && (bo.0.x & 0x01) != 0x0; + + let mut processed_rows: isize = 0; + let mut processed_cols: isize = 0; + + let up_avail = bo.0.y > 0; + let left_avail = bo.0.x > 0; + + if up_avail { + max_row_offs = -2 * MVREF_ROW_COLS as isize + row_adj as isize; + + // limit max offset for small blocks + if target_n4_h < BLOCK_8X8.height_mi() { + max_row_offs = -2 * 2 + row_adj as isize; + } + + let rows = self.bc.blocks.rows(); + max_row_offs = Self::find_valid_row_offs(max_row_offs, bo.0.y, rows); + } + + if left_avail { + max_col_offs = -2 * MVREF_ROW_COLS as isize + col_adj as isize; + + // limit max offset for small blocks + if target_n4_w < BLOCK_8X8.width_mi() { + max_col_offs = -2 * 2 + col_adj as isize; + } + + let cols = self.bc.blocks.cols(); + max_col_offs = Self::find_valid_col_offs(max_col_offs, bo.0.x, cols); + } + + let mut row_match = false; + let mut col_match = false; + let mut newmv_count: usize = 0; + + if max_row_offs.abs() >= 1 { + let found_match = self.scan_row_mbmi( + bo, + -1, + max_row_offs, + &mut processed_rows, + ref_frames, + mv_stack, + &mut newmv_count, + bsize, + is_compound, + ); + row_match |= found_match; + } + if max_col_offs.abs() >= 1 { + let found_match = self.scan_col_mbmi( + bo, + -1, + max_col_offs, + &mut processed_cols, + ref_frames, + mv_stack, + &mut newmv_count, + bsize, + is_compound, + ); + col_match |= found_match; + } + if has_tr(bo, bsize) && bo.0.y > 0 { + let found_match = self.scan_blk_mbmi( + bo.with_offset(target_n4_w as isize, -1), + ref_frames, + mv_stack, + &mut newmv_count, + is_compound, + ); + row_match |= found_match; + } + + let nearest_match = usize::from(row_match) + usize::from(col_match); + + Self::add_offset(mv_stack); + + /* Scan the second outer area. */ + let mut far_newmv_count: usize = 0; // won't be used + + let found_match = bo.0.x > 0 + && bo.0.y > 0 + && self.scan_blk_mbmi( + bo.with_offset(-1, -1), + ref_frames, + mv_stack, + &mut far_newmv_count, + is_compound, + ); + row_match |= found_match; + + for idx in 2..=MVREF_ROW_COLS { + let row_offset = -2 * idx as isize + 1 + row_adj as isize; + let col_offset = -2 * idx as isize + 1 + col_adj as isize; + + if row_offset.abs() <= max_row_offs.abs() + && row_offset.abs() > processed_rows + { + let found_match = self.scan_row_mbmi( + bo, + row_offset, + max_row_offs, + &mut processed_rows, + ref_frames, + mv_stack, + &mut far_newmv_count, + bsize, + is_compound, + ); + row_match |= found_match; + } + + if col_offset.abs() <= max_col_offs.abs() + && col_offset.abs() > processed_cols + { + let found_match = self.scan_col_mbmi( + bo, + col_offset, + max_col_offs, + &mut processed_cols, + ref_frames, + mv_stack, + &mut far_newmv_count, + bsize, + is_compound, + ); + col_match |= found_match; + } + } + + let total_match = usize::from(row_match) + usize::from(col_match); + + assert!(total_match >= nearest_match); + + // mode_context contains both newmv_context and refmv_context, where newmv_context + // lies in the REF_MVOFFSET least significant bits + let mode_context = match nearest_match { + 0 => cmp::min(total_match, 1) + (total_match << REFMV_OFFSET), + 1 => 3 - cmp::min(newmv_count, 1) + ((2 + total_match) << REFMV_OFFSET), + _ => 5 - cmp::min(newmv_count, 1) + (5 << REFMV_OFFSET), + }; + + /* TODO: Find nearest match and assign nearest and near mvs */ + + // 7.10.2.11 Sort MV stack according to weight + mv_stack.sort_by(|a, b| b.weight.cmp(&a.weight)); + + if mv_stack.len() < 2 { + // 7.10.2.12 Extra search process + + let w4 = bsize.width_mi().min(16).min(self.bc.blocks.cols() - bo.0.x); + let h4 = bsize.height_mi().min(16).min(self.bc.blocks.rows() - bo.0.y); + let num4x4 = w4.min(h4); + + let passes = i32::from(!up_avail)..=i32::from(left_avail); + + let mut ref_id_count: [usize; 2] = [0; 2]; + let mut ref_diff_count: [usize; 2] = [0; 2]; + let mut ref_id_mvs = [[MotionVector::default(); 2]; 2]; + let mut ref_diff_mvs = [[MotionVector::default(); 2]; 2]; + + for pass in passes { + let mut idx = 0; + while idx < num4x4 && mv_stack.len() < 2 { + let rbo = if pass == 0 { + bo.with_offset(idx as isize, -1) + } else { + bo.with_offset(-1, idx as isize) + }; + + let blk = &self.bc.blocks[rbo]; + Self::add_extra_mv_candidate( + blk, + ref_frames, + mv_stack, + fi, + is_compound, + &mut ref_id_count, + &mut ref_id_mvs, + &mut ref_diff_count, + &mut ref_diff_mvs, + ); + + idx += if pass == 0 { blk.n4_w } else { blk.n4_h } as usize; + } + } + + if is_compound { + let mut combined_mvs = [[MotionVector::default(); 2]; 2]; + + for list in 0..2 { + let mut comp_count = 0; + for idx in 0..ref_id_count[list] { + combined_mvs[comp_count][list] = ref_id_mvs[list][idx]; + comp_count += 1; + } + for idx in 0..ref_diff_count[list] { + if comp_count < 2 { + combined_mvs[comp_count][list] = ref_diff_mvs[list][idx]; + comp_count += 1; + } + } + } + + if mv_stack.len() == 1 { + let mv_cand = if combined_mvs[0][0].row == mv_stack[0].this_mv.row + && combined_mvs[0][0].col == mv_stack[0].this_mv.col + && combined_mvs[0][1].row == mv_stack[0].comp_mv.row + && combined_mvs[0][1].col == mv_stack[0].comp_mv.col + { + CandidateMV { + this_mv: combined_mvs[1][0], + comp_mv: combined_mvs[1][1], + weight: 2, + } + } else { + CandidateMV { + this_mv: combined_mvs[0][0], + comp_mv: combined_mvs[0][1], + weight: 2, + } + }; + mv_stack.push(mv_cand); + } else { + for idx in 0..2 { + let mv_cand = CandidateMV { + this_mv: combined_mvs[idx][0], + comp_mv: combined_mvs[idx][1], + weight: 2, + }; + mv_stack.push(mv_cand); + } + } + + assert!(mv_stack.len() == 2); + } + } + + /* TODO: Handle single reference frame extension */ + + let frame_bo = PlaneBlockOffset(BlockOffset { + x: self.bc.blocks.x() + bo.0.x, + y: self.bc.blocks.y() + bo.0.y, + }); + // clamp mvs + for mv in mv_stack { + let blk_w = bsize.width(); + let blk_h = bsize.height(); + let border_w = 128 + blk_w as isize * 8; + let border_h = 128 + blk_h as isize * 8; + let mvx_min = + -(frame_bo.0.x as isize) * (8 * MI_SIZE) as isize - border_w; + let mvx_max = ((self.bc.blocks.frame_cols() - frame_bo.0.x) as isize + - (blk_w / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_w; + let mvy_min = + -(frame_bo.0.y as isize) * (8 * MI_SIZE) as isize - border_h; + let mvy_max = ((self.bc.blocks.frame_rows() - frame_bo.0.y) as isize + - (blk_h / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_h; + mv.this_mv.row = + (mv.this_mv.row as isize).clamp(mvy_min, mvy_max) as i16; + mv.this_mv.col = + (mv.this_mv.col as isize).clamp(mvx_min, mvx_max) as i16; + mv.comp_mv.row = + (mv.comp_mv.row as isize).clamp(mvy_min, mvy_max) as i16; + mv.comp_mv.col = + (mv.comp_mv.col as isize).clamp(mvx_min, mvx_max) as i16; + } + + mode_context + } + + /// # Panics + /// + /// - If the first ref frame is not set (`NONE_FRAME`) + pub fn find_mvrefs( + &self, bo: TileBlockOffset, ref_frames: [RefType; 2], + mv_stack: &mut ArrayVec, bsize: BlockSize, + fi: &FrameInvariants, is_compound: bool, + ) -> usize { + assert!(ref_frames[0] != NONE_FRAME); + if ref_frames[0] != NONE_FRAME { + // TODO: If ref_frames[0] != INTRA_FRAME, convert global mv to an mv; + // otherwise, set the global mv ref to invalid. + } + + if ref_frames[0] != INTRA_FRAME { + /* TODO: Set zeromv ref to the converted global motion vector */ + } else { + /* TODO: Set the zeromv ref to 0 */ + return 0; + } + + self.setup_mvref_list(bo, ref_frames, mv_stack, bsize, fi, is_compound) + } + + pub fn fill_neighbours_ref_counts(&mut self, bo: TileBlockOffset) { + let mut ref_counts = [0; INTER_REFS_PER_FRAME]; + + if bo.0.y > 0 { + let above_b = self.bc.blocks.above_of(bo); + if above_b.is_inter() { + ref_counts[above_b.ref_frames[0].to_index()] += 1; + if above_b.has_second_ref() { + ref_counts[above_b.ref_frames[1].to_index()] += 1; + } + } + } + + if bo.0.x > 0 { + let left_b = self.bc.blocks.left_of(bo); + if left_b.is_inter() { + ref_counts[left_b.ref_frames[0].to_index()] += 1; + if left_b.has_second_ref() { + ref_counts[left_b.ref_frames[1].to_index()] += 1; + } + } + } + self.bc.blocks[bo].neighbors_ref_counts = ref_counts; + } + + #[inline] + pub const fn ref_count_ctx(counts0: u8, counts1: u8) -> usize { + if counts0 < counts1 { + 0 + } else if counts0 == counts1 { + 1 + } else { + 2 + } + } + + #[inline] + pub fn get_pred_ctx_brfarf2_or_arf(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let brfarf2_count = ref_counts[BWDREF_FRAME.to_index()] + + ref_counts[ALTREF2_FRAME.to_index()]; + let arf_count = ref_counts[ALTREF_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(brfarf2_count, arf_count) + } + + #[inline] + pub fn get_pred_ctx_ll2_or_l3gld(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let l_l2_count = + ref_counts[LAST_FRAME.to_index()] + ref_counts[LAST2_FRAME.to_index()]; + let l3_gold_count = + ref_counts[LAST3_FRAME.to_index()] + ref_counts[GOLDEN_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(l_l2_count, l3_gold_count) + } + + #[inline] + pub fn get_pred_ctx_last_or_last2(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let l_count = ref_counts[LAST_FRAME.to_index()]; + let l2_count = ref_counts[LAST2_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(l_count, l2_count) + } + + #[inline] + pub fn get_pred_ctx_last3_or_gold(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let l3_count = ref_counts[LAST3_FRAME.to_index()]; + let gold_count = ref_counts[GOLDEN_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(l3_count, gold_count) + } + + #[inline] + pub fn get_pred_ctx_brf_or_arf2(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let brf_count = ref_counts[BWDREF_FRAME.to_index()]; + let arf2_count = ref_counts[ALTREF2_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(brf_count, arf2_count) + } + + pub fn get_comp_mode_ctx(&self, bo: TileBlockOffset) -> usize { + let avail_left = bo.0.x > 0; + let avail_up = bo.0.y > 0; + let (left0, left1) = if avail_left { + let bo_left = bo.with_offset(-1, 0); + let ref_frames = &self.bc.blocks[bo_left].ref_frames; + (ref_frames[0], ref_frames[1]) + } else { + (INTRA_FRAME, NONE_FRAME) + }; + let (above0, above1) = if avail_up { + let bo_up = bo.with_offset(0, -1); + let ref_frames = &self.bc.blocks[bo_up].ref_frames; + (ref_frames[0], ref_frames[1]) + } else { + (INTRA_FRAME, NONE_FRAME) + }; + let left_single = left1 == NONE_FRAME; + let above_single = above1 == NONE_FRAME; + let left_intra = left0 == INTRA_FRAME; + let above_intra = above0 == INTRA_FRAME; + let left_backward = left0.is_bwd_ref(); + let above_backward = above0.is_bwd_ref(); + + if avail_left && avail_up { + if above_single && left_single { + (above_backward ^ left_backward) as usize + } else if above_single { + 2 + (above_backward || above_intra) as usize + } else if left_single { + 2 + (left_backward || left_intra) as usize + } else { + 4 + } + } else if avail_up { + if above_single { + above_backward as usize + } else { + 3 + } + } else if avail_left { + if left_single { + left_backward as usize + } else { + 3 + } + } else { + 1 + } + } + + pub fn get_comp_ref_type_ctx(&self, bo: TileBlockOffset) -> usize { + fn is_samedir_ref_pair(ref0: RefType, ref1: RefType) -> bool { + (ref0.is_bwd_ref() && ref0 != NONE_FRAME) + == (ref1.is_bwd_ref() && ref1 != NONE_FRAME) + } + + let avail_left = bo.0.x > 0; + let avail_up = bo.0.y > 0; + let (left0, left1) = if avail_left { + let bo_left = bo.with_offset(-1, 0); + let ref_frames = &self.bc.blocks[bo_left].ref_frames; + (ref_frames[0], ref_frames[1]) + } else { + (INTRA_FRAME, NONE_FRAME) + }; + let (above0, above1) = if avail_up { + let bo_up = bo.with_offset(0, -1); + let ref_frames = &self.bc.blocks[bo_up].ref_frames; + (ref_frames[0], ref_frames[1]) + } else { + (INTRA_FRAME, NONE_FRAME) + }; + let left_single = left1 == NONE_FRAME; + let above_single = above1 == NONE_FRAME; + let left_intra = left0 == INTRA_FRAME; + let above_intra = above0 == INTRA_FRAME; + let above_comp_inter = avail_up && !above_intra && !above_single; + let left_comp_inter = avail_left && !left_intra && !left_single; + let above_uni_comp = + above_comp_inter && is_samedir_ref_pair(above0, above1); + let left_uni_comp = left_comp_inter && is_samedir_ref_pair(left0, left1); + + if avail_up && !above_intra && avail_left && !left_intra { + let samedir = is_samedir_ref_pair(above0, left0) as usize; + + if !above_comp_inter && !left_comp_inter { + 1 + 2 * samedir + } else if !above_comp_inter { + if !left_uni_comp { + 1 + } else { + 3 + samedir + } + } else if !left_comp_inter { + if !above_uni_comp { + 1 + } else { + 3 + samedir + } + } else if !above_uni_comp && !left_uni_comp { + 0 + } else if !above_uni_comp || !left_uni_comp { + 2 + } else { + 3 + ((above0 == BWDREF_FRAME) == (left0 == BWDREF_FRAME)) as usize + } + } else if avail_up && avail_left { + if above_comp_inter { + 1 + 2 * above_uni_comp as usize + } else if left_comp_inter { + 1 + 2 * left_uni_comp as usize + } else { + 2 + } + } else if above_comp_inter { + 4 * above_uni_comp as usize + } else if left_comp_inter { + 4 * left_uni_comp as usize + } else { + 2 + } + } + + /// # Panics + /// + /// - If `mode` is not an inter mode + pub fn write_compound_mode( + &mut self, w: &mut W, mode: PredictionMode, ctx: usize, + ) { + let newmv_ctx = ctx & NEWMV_CTX_MASK; + let refmv_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; + + let ctx = if refmv_ctx < 2 { + newmv_ctx.min(1) + } else if refmv_ctx < 4 { + (newmv_ctx + 1).min(4) + } else { + (newmv_ctx.max(1) + 3).min(7) + }; + + assert!(mode >= PredictionMode::NEAREST_NEARESTMV); + let val = match mode { + PredictionMode::NEAREST_NEARESTMV => 0, + PredictionMode::NEAR_NEAR0MV + | PredictionMode::NEAR_NEAR1MV + | PredictionMode::NEAR_NEAR2MV => 1, + PredictionMode::NEAREST_NEWMV => 2, + PredictionMode::NEW_NEARESTMV => 3, + PredictionMode::NEAR_NEW0MV + | PredictionMode::NEAR_NEW1MV + | PredictionMode::NEAR_NEW2MV => 4, + PredictionMode::NEW_NEAR0MV + | PredictionMode::NEW_NEAR1MV + | PredictionMode::NEW_NEAR2MV => 5, + PredictionMode::GLOBAL_GLOBALMV => 6, + PredictionMode::NEW_NEWMV => 7, + _ => unreachable!(), + }; + symbol_with_update!(self, w, val, &self.fc.compound_mode_cdf[ctx]); + } + + pub fn write_inter_mode( + &mut self, w: &mut W, mode: PredictionMode, ctx: usize, + ) { + use PredictionMode::{GLOBALMV, NEARESTMV, NEWMV}; + let newmv_ctx = ctx & NEWMV_CTX_MASK; + let cdf = &self.fc.newmv_cdf[newmv_ctx]; + symbol_with_update!(self, w, (mode != NEWMV) as u32, cdf); + if mode != NEWMV { + let zeromv_ctx = (ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK; + let cdf = &self.fc.zeromv_cdf[zeromv_ctx]; + symbol_with_update!(self, w, (mode != GLOBALMV) as u32, cdf); + if mode != GLOBALMV { + let refmv_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; + let cdf = &self.fc.refmv_cdf[refmv_ctx]; + symbol_with_update!(self, w, (mode != NEARESTMV) as u32, cdf); + } + } + } + + #[inline] + pub fn write_drl_mode( + &mut self, w: &mut W, drl_mode: bool, ctx: usize, + ) { + let cdf = &self.fc.drl_cdfs[ctx]; + symbol_with_update!(self, w, drl_mode as u32, cdf); + } + + /// # Panics + /// + /// - If the MV is invalid + pub fn write_mv( + &mut self, w: &mut W, mv: MotionVector, ref_mv: MotionVector, + mv_precision: MvSubpelPrecision, + ) { + // + assert!(mv.is_valid()); + + let diff = + MotionVector { row: mv.row - ref_mv.row, col: mv.col - ref_mv.col }; + let j: MvJointType = av1_get_mv_joint(diff); + + let cdf = &self.fc.nmv_context.joints_cdf; + symbol_with_update!(self, w, j as u32, cdf); + + if mv_joint_vertical(j) { + self.encode_mv_component(w, diff.row as i32, 0, mv_precision); + } + if mv_joint_horizontal(j) { + self.encode_mv_component(w, diff.col as i32, 1, mv_precision); + } + } + + pub fn write_block_deblock_deltas( + &mut self, w: &mut W, bo: TileBlockOffset, multi: bool, planes: usize, + ) { + let block = &self.bc.blocks[bo]; + let deltas_count = if multi { FRAME_LF_COUNT + planes - 3 } else { 1 }; + let deltas = &block.deblock_deltas[..deltas_count]; + + for (i, &delta) in deltas.iter().enumerate() { + let abs = delta.unsigned_abs() as u32; + let cdf = if multi { + &self.fc.deblock_delta_multi_cdf[i] + } else { + &self.fc.deblock_delta_cdf + }; + + symbol_with_update!(self, w, cmp::min(abs, DELTA_LF_SMALL), cdf); + + if abs >= DELTA_LF_SMALL { + let bits = msb(abs as i32 - 1) as u32; + w.literal(3, bits - 1); + w.literal(bits as u8, abs - (1 << bits) - 1); + } + if abs > 0 { + w.bool(delta < 0, 16384); + } + } + } + + pub fn write_is_inter( + &mut self, w: &mut W, bo: TileBlockOffset, is_inter: bool, + ) { + let ctx = self.bc.intra_inter_context(bo); + let cdf = &self.fc.intra_inter_cdfs[ctx]; + symbol_with_update!(self, w, is_inter as u32, cdf); + } + + pub fn write_coeffs_lv_map( + &mut self, w: &mut W, plane: usize, bo: TileBlockOffset, coeffs_in: &[T], + eob: u16, pred_mode: PredictionMode, tx_size: TxSize, tx_type: TxType, + plane_bsize: BlockSize, xdec: usize, ydec: usize, + use_reduced_tx_set: bool, frame_clipped_txw: usize, + frame_clipped_txh: usize, + ) -> bool { + debug_assert!(frame_clipped_txw != 0); + debug_assert!(frame_clipped_txh != 0); + + let is_inter = pred_mode >= PredictionMode::NEARESTMV; + + // Note: Both intra and inter mode uses inter scan order. Surprised? + let scan: &[u16] = &av1_scan_orders[tx_size as usize][tx_type as usize] + .scan[..usize::from(eob)]; + let height = av1_get_coded_tx_size(tx_size).height(); + + // Create a slice with coeffs in scan order + let mut coeffs_storage: Aligned> = + Aligned::new(ArrayVec::new()); + let coeffs = &mut coeffs_storage.data; + coeffs.extend(scan.iter().map(|&scan_idx| coeffs_in[scan_idx as usize])); + + let cul_level: u32 = coeffs.iter().map(|c| u32::cast_from(c.abs())).sum(); + + let txs_ctx = Self::get_txsize_entropy_ctx(tx_size); + let txb_ctx = self.bc.get_txb_ctx( + plane_bsize, + tx_size, + plane, + bo, + xdec, + ydec, + frame_clipped_txw, + frame_clipped_txh, + ); + + { + let cdf = &self.fc.txb_skip_cdf[txs_ctx][txb_ctx.txb_skip_ctx]; + symbol_with_update!(self, w, (eob == 0) as u32, cdf); + } + + if eob == 0 { + self.bc.set_coeff_context(plane, bo, tx_size, xdec, ydec, 0); + return false; + } + + let mut levels_buf = [0u8; TX_PAD_2D]; + let levels: &mut [u8] = + &mut levels_buf[TX_PAD_TOP * (height + TX_PAD_HOR)..]; + + self.txb_init_levels(coeffs_in, height, levels, height + TX_PAD_HOR); + + let tx_class = tx_type_to_class[tx_type as usize]; + let plane_type = usize::from(plane != 0); + + // Signal tx_type for luma plane only + if plane == 0 { + self.write_tx_type( + w, + tx_size, + tx_type, + pred_mode, + is_inter, + use_reduced_tx_set, + ); + } + + self.encode_eob(eob, tx_size, tx_class, txs_ctx, plane_type, w); + self.encode_coeffs( + coeffs, levels, scan, eob, tx_size, tx_class, txs_ctx, plane_type, w, + ); + let cul_level = + self.encode_coeff_signs(coeffs, w, plane_type, txb_ctx, cul_level); + self.bc.set_coeff_context(plane, bo, tx_size, xdec, ydec, cul_level as u8); + true + } + + fn encode_eob( + &mut self, eob: u16, tx_size: TxSize, tx_class: TxClass, txs_ctx: usize, + plane_type: usize, w: &mut W, + ) { + let (eob_pt, eob_extra) = Self::get_eob_pos_token(eob); + let eob_multi_size: usize = tx_size.area_log2() - 4; + let eob_multi_ctx: usize = usize::from(tx_class != TX_CLASS_2D); + + match eob_multi_size { + 0 => { + let cdf = &self.fc.eob_flag_cdf16[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + 1 => { + let cdf = &self.fc.eob_flag_cdf32[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + 2 => { + let cdf = &self.fc.eob_flag_cdf64[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + 3 => { + let cdf = &self.fc.eob_flag_cdf128[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + 4 => { + let cdf = &self.fc.eob_flag_cdf256[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + 5 => { + let cdf = &self.fc.eob_flag_cdf512[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + _ => { + let cdf = &self.fc.eob_flag_cdf1024[plane_type][eob_multi_ctx]; + symbol_with_update!(self, w, eob_pt - 1, cdf); + } + } + + let eob_offset_bits = k_eob_offset_bits[eob_pt as usize]; + + if eob_offset_bits > 0 { + let mut eob_shift = eob_offset_bits - 1; + let mut bit: u32 = u32::from((eob_extra & (1 << eob_shift)) != 0); + let cdf = + &self.fc.eob_extra_cdf[txs_ctx][plane_type][(eob_pt - 3) as usize]; + symbol_with_update!(self, w, bit, cdf); + for i in 1..eob_offset_bits { + eob_shift = eob_offset_bits - 1 - i; + bit = u32::from((eob_extra & (1 << eob_shift)) != 0); + w.bit(bit as u16); + } + } + } + + fn encode_coeffs( + &mut self, coeffs: &[T], levels: &mut [u8], scan: &[u16], eob: u16, + tx_size: TxSize, tx_class: TxClass, txs_ctx: usize, plane_type: usize, + w: &mut W, + ) { + let mut coeff_contexts = + Aligned::<[MaybeUninit; MAX_CODED_TX_SQUARE]>::uninit_array(); + + // get_nz_map_contexts sets coeff_contexts contiguously as a parallel array for scan, not in scan order + let coeff_contexts = self.get_nz_map_contexts( + levels, + scan, + eob, + tx_size, + tx_class, + &mut coeff_contexts.data, + ); + + let bhl = Self::get_txb_bhl(tx_size); + + let scan_with_ctx = + scan.iter().copied().zip(coeff_contexts.iter().copied()); + for (c, ((pos, coeff_ctx), v)) in + scan_with_ctx.zip(coeffs.iter().copied()).enumerate().rev() + { + let pos = pos as usize; + let coeff_ctx = coeff_ctx as usize; + let level = v.abs(); + + if c == usize::from(eob) - 1 { + symbol_with_update!( + self, + w, + cmp::min(u32::cast_from(level), 3) - 1, + &self.fc.coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx] + ); + } else { + symbol_with_update!( + self, + w, + cmp::min(u32::cast_from(level), 3), + &self.fc.coeff_base_cdf[txs_ctx][plane_type][coeff_ctx] + ); + } + + if level > T::cast_from(NUM_BASE_LEVELS) { + let base_range = level - T::cast_from(1 + NUM_BASE_LEVELS); + let br_ctx = Self::get_br_ctx(levels, pos, bhl, tx_class); + let mut idx: T = T::cast_from(0); + + loop { + if idx >= T::cast_from(COEFF_BASE_RANGE) { + break; + } + let k = cmp::min(base_range - idx, T::cast_from(BR_CDF_SIZE - 1)); + let cdf = &self.fc.coeff_br_cdf + [txs_ctx.min(TxSize::TX_32X32 as usize)][plane_type][br_ctx]; + symbol_with_update!(self, w, u32::cast_from(k), cdf); + if k < T::cast_from(BR_CDF_SIZE - 1) { + break; + } + idx += T::cast_from(BR_CDF_SIZE - 1); + } + } + } + } + + fn encode_coeff_signs( + &mut self, coeffs: &[T], w: &mut W, plane_type: usize, txb_ctx: TXB_CTX, + orig_cul_level: u32, + ) -> u32 { + // Loop to code all signs in the transform block, + // starting with the sign of DC (if applicable) + for (c, &v) in coeffs.iter().enumerate() { + if v == T::cast_from(0) { + continue; + } + + let level = v.abs(); + let sign = u32::from(v < T::cast_from(0)); + if c == 0 { + let cdf = &self.fc.dc_sign_cdf[plane_type][txb_ctx.dc_sign_ctx]; + symbol_with_update!(self, w, sign, cdf); + } else { + w.bit(sign as u16); + } + // save extra golomb codes for separate loop + if level > T::cast_from(COEFF_BASE_RANGE + NUM_BASE_LEVELS) { + w.write_golomb(u32::cast_from( + level - T::cast_from(COEFF_BASE_RANGE + NUM_BASE_LEVELS + 1), + )); + } + } + + let mut new_cul_level = + cmp::min(COEFF_CONTEXT_MASK as u32, orig_cul_level); + + BlockContext::set_dc_sign(&mut new_cul_level, i32::cast_from(coeffs[0])); + + new_cul_level + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/cdf_context.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/cdf_context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/cdf_context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/cdf_context.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,745 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; +use std::marker::PhantomData; + +pub const CDF_LEN_MAX: usize = 16; + +#[derive(Clone)] +pub struct CDFContextCheckpoint { + small: usize, + large: usize, +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct CDFContext { + pub comp_bwd_ref_cdf: [[[u16; 2]; BWD_REFS - 1]; REF_CONTEXTS], + pub comp_mode_cdf: [[u16; 2]; COMP_INTER_CONTEXTS], + pub comp_ref_cdf: [[[u16; 2]; FWD_REFS - 1]; REF_CONTEXTS], + pub comp_ref_type_cdf: [[u16; 2]; COMP_REF_TYPE_CONTEXTS], + pub dc_sign_cdf: [[[u16; 2]; DC_SIGN_CONTEXTS]; PLANE_TYPES], + pub drl_cdfs: [[u16; 2]; DRL_MODE_CONTEXTS], + pub eob_extra_cdf: + [[[[u16; 2]; EOB_COEF_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], + pub filter_intra_cdfs: [[u16; 2]; BlockSize::BLOCK_SIZES_ALL], + pub intra_inter_cdfs: [[u16; 2]; INTRA_INTER_CONTEXTS], + pub lrf_sgrproj_cdf: [u16; 2], + pub lrf_wiener_cdf: [u16; 2], + pub newmv_cdf: [[u16; 2]; NEWMV_MODE_CONTEXTS], + pub palette_uv_mode_cdfs: [[u16; 2]; PALETTE_UV_MODE_CONTEXTS], + pub palette_y_mode_cdfs: + [[[u16; 2]; PALETTE_Y_MODE_CONTEXTS]; PALETTE_BSIZE_CTXS], + pub refmv_cdf: [[u16; 2]; REFMV_MODE_CONTEXTS], + pub single_ref_cdfs: [[[u16; 2]; SINGLE_REFS - 1]; REF_CONTEXTS], + pub skip_cdfs: [[u16; 2]; SKIP_CONTEXTS], + pub txb_skip_cdf: [[[u16; 2]; TXB_SKIP_CONTEXTS]; TxSize::TX_SIZES], + pub txfm_partition_cdf: [[u16; 2]; TXFM_PARTITION_CONTEXTS], + pub zeromv_cdf: [[u16; 2]; GLOBALMV_MODE_CONTEXTS], + pub tx_size_8x8_cdf: [[u16; MAX_TX_DEPTH]; TX_SIZE_CONTEXTS], + pub inter_tx_3_cdf: [[u16; 2]; TX_SIZE_SQR_CONTEXTS], + + pub coeff_base_eob_cdf: + [[[[u16; 3]; SIG_COEF_CONTEXTS_EOB]; PLANE_TYPES]; TxSize::TX_SIZES], + pub lrf_switchable_cdf: [u16; 3], + pub tx_size_cdf: [[[u16; MAX_TX_DEPTH + 1]; TX_SIZE_CONTEXTS]; BIG_TX_CATS], + + pub coeff_base_cdf: + [[[[u16; 4]; SIG_COEF_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], + pub coeff_br_cdf: + [[[[u16; BR_CDF_SIZE]; LEVEL_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], + pub deblock_delta_cdf: [u16; DELTA_LF_PROBS + 1], + pub deblock_delta_multi_cdf: [[u16; DELTA_LF_PROBS + 1]; FRAME_LF_COUNT], + pub partition_w8_cdf: [[u16; 4]; PARTITION_TYPES], + + pub eob_flag_cdf16: [[[u16; 5]; 2]; PLANE_TYPES], + pub intra_tx_2_cdf: [[[u16; 5]; INTRA_MODES]; TX_SIZE_SQR_CONTEXTS], + + pub eob_flag_cdf32: [[[u16; 6]; 2]; PLANE_TYPES], + + pub angle_delta_cdf: [[u16; 2 * MAX_ANGLE_DELTA + 1]; DIRECTIONAL_MODES], + pub eob_flag_cdf64: [[[u16; 7]; 2]; PLANE_TYPES], + pub intra_tx_1_cdf: [[[u16; 7]; INTRA_MODES]; TX_SIZE_SQR_CONTEXTS], + + pub cfl_sign_cdf: [u16; CFL_JOINT_SIGNS], + pub compound_mode_cdf: [[u16; INTER_COMPOUND_MODES]; INTER_MODE_CONTEXTS], + pub eob_flag_cdf128: [[[u16; 8]; 2]; PLANE_TYPES], + pub spatial_segmentation_cdfs: [[u16; 8]; 3], + pub partition_w128_cdf: [[u16; 8]; PARTITION_TYPES], + + pub eob_flag_cdf256: [[[u16; 9]; 2]; PLANE_TYPES], + + pub eob_flag_cdf512: [[[u16; 10]; 2]; PLANE_TYPES], + pub partition_cdf: [[u16; EXT_PARTITION_TYPES]; 3 * PARTITION_TYPES], + + pub eob_flag_cdf1024: [[[u16; 11]; 2]; PLANE_TYPES], + + pub inter_tx_2_cdf: [[u16; 12]; TX_SIZE_SQR_CONTEXTS], + + pub kf_y_cdf: [[[u16; INTRA_MODES]; KF_MODE_CONTEXTS]; KF_MODE_CONTEXTS], + pub y_mode_cdf: [[u16; INTRA_MODES]; BLOCK_SIZE_GROUPS], + pub uv_mode_cdf: [[u16; INTRA_MODES]; INTRA_MODES], + + pub uv_mode_cfl_cdf: [[u16; UV_INTRA_MODES]; INTRA_MODES], + + pub cfl_alpha_cdf: [[u16; CFL_ALPHABET_SIZE]; CFL_ALPHA_CONTEXTS], + pub inter_tx_1_cdf: [[u16; TX_TYPES]; TX_SIZE_SQR_CONTEXTS], + + pub nmv_context: NMVContext, +} + +pub struct CDFOffset { + offset: usize, + phantom: PhantomData<[u16; CDF_LEN]>, +} + +impl CDFContext { + pub fn new(quantizer: u8) -> CDFContext { + let qctx = match quantizer { + 0..=20 => 0, + 21..=60 => 1, + 61..=120 => 2, + _ => 3, + }; + CDFContext { + partition_w8_cdf: default_partition_w8_cdf, + partition_w128_cdf: default_partition_w128_cdf, + partition_cdf: default_partition_cdf, + kf_y_cdf: default_kf_y_mode_cdf, + y_mode_cdf: default_if_y_mode_cdf, + uv_mode_cdf: default_uv_mode_cdf, + uv_mode_cfl_cdf: default_uv_mode_cfl_cdf, + cfl_sign_cdf: default_cfl_sign_cdf, + cfl_alpha_cdf: default_cfl_alpha_cdf, + newmv_cdf: default_newmv_cdf, + zeromv_cdf: default_zeromv_cdf, + refmv_cdf: default_refmv_cdf, + intra_tx_2_cdf: default_intra_tx_2_cdf, + intra_tx_1_cdf: default_intra_tx_1_cdf, + inter_tx_3_cdf: default_inter_tx_3_cdf, + inter_tx_2_cdf: default_inter_tx_2_cdf, + inter_tx_1_cdf: default_inter_tx_1_cdf, + tx_size_8x8_cdf: default_tx_size_8x8_cdf, + tx_size_cdf: default_tx_size_cdf, + txfm_partition_cdf: default_txfm_partition_cdf, + skip_cdfs: default_skip_cdfs, + intra_inter_cdfs: default_intra_inter_cdf, + angle_delta_cdf: default_angle_delta_cdf, + filter_intra_cdfs: default_filter_intra_cdfs, + palette_y_mode_cdfs: default_palette_y_mode_cdfs, + palette_uv_mode_cdfs: default_palette_uv_mode_cdfs, + comp_mode_cdf: default_comp_mode_cdf, + comp_ref_type_cdf: default_comp_ref_type_cdf, + comp_ref_cdf: default_comp_ref_cdf, + comp_bwd_ref_cdf: default_comp_bwdref_cdf, + single_ref_cdfs: default_single_ref_cdf, + drl_cdfs: default_drl_cdf, + compound_mode_cdf: default_compound_mode_cdf, + nmv_context: default_nmv_context, + deblock_delta_multi_cdf: default_delta_lf_multi_cdf, + deblock_delta_cdf: default_delta_lf_cdf, + spatial_segmentation_cdfs: default_spatial_pred_seg_tree_cdf, + lrf_switchable_cdf: default_switchable_restore_cdf, + lrf_sgrproj_cdf: default_sgrproj_restore_cdf, + lrf_wiener_cdf: default_wiener_restore_cdf, + + // lv_map + txb_skip_cdf: av1_default_txb_skip_cdfs[qctx], + dc_sign_cdf: av1_default_dc_sign_cdfs[qctx], + eob_extra_cdf: av1_default_eob_extra_cdfs[qctx], + + eob_flag_cdf16: av1_default_eob_multi16_cdfs[qctx], + eob_flag_cdf32: av1_default_eob_multi32_cdfs[qctx], + eob_flag_cdf64: av1_default_eob_multi64_cdfs[qctx], + eob_flag_cdf128: av1_default_eob_multi128_cdfs[qctx], + eob_flag_cdf256: av1_default_eob_multi256_cdfs[qctx], + eob_flag_cdf512: av1_default_eob_multi512_cdfs[qctx], + eob_flag_cdf1024: av1_default_eob_multi1024_cdfs[qctx], + + coeff_base_eob_cdf: av1_default_coeff_base_eob_multi_cdfs[qctx], + coeff_base_cdf: av1_default_coeff_base_multi_cdfs[qctx], + coeff_br_cdf: av1_default_coeff_lps_multi_cdfs[qctx], + } + } + + pub fn reset_counts(&mut self) { + macro_rules! reset_1d { + ($field:expr) => { + let r = $field.last_mut().unwrap(); + *r = 0; + }; + } + macro_rules! reset_2d { + ($field:expr) => { + for x in $field.iter_mut() { + reset_1d!(x); + } + }; + } + macro_rules! reset_3d { + ($field:expr) => { + for x in $field.iter_mut() { + reset_2d!(x); + } + }; + } + macro_rules! reset_4d { + ($field:expr) => { + for x in $field.iter_mut() { + reset_3d!(x); + } + }; + } + + reset_2d!(self.partition_w8_cdf); + reset_2d!(self.partition_w128_cdf); + reset_2d!(self.partition_cdf); + + reset_3d!(self.kf_y_cdf); + reset_2d!(self.y_mode_cdf); + + reset_2d!(self.uv_mode_cdf); + reset_2d!(self.uv_mode_cfl_cdf); + reset_1d!(self.cfl_sign_cdf); + reset_2d!(self.cfl_alpha_cdf); + reset_2d!(self.newmv_cdf); + reset_2d!(self.zeromv_cdf); + reset_2d!(self.refmv_cdf); + + reset_3d!(self.intra_tx_2_cdf); + reset_3d!(self.intra_tx_1_cdf); + + reset_2d!(self.inter_tx_3_cdf); + reset_2d!(self.inter_tx_2_cdf); + reset_2d!(self.inter_tx_1_cdf); + + reset_2d!(self.tx_size_8x8_cdf); + reset_3d!(self.tx_size_cdf); + + reset_2d!(self.txfm_partition_cdf); + + reset_2d!(self.skip_cdfs); + reset_2d!(self.intra_inter_cdfs); + reset_2d!(self.angle_delta_cdf); + reset_2d!(self.filter_intra_cdfs); + reset_3d!(self.palette_y_mode_cdfs); + reset_2d!(self.palette_uv_mode_cdfs); + reset_2d!(self.comp_mode_cdf); + reset_2d!(self.comp_ref_type_cdf); + reset_3d!(self.comp_ref_cdf); + reset_3d!(self.comp_bwd_ref_cdf); + reset_3d!(self.single_ref_cdfs); + reset_2d!(self.drl_cdfs); + reset_2d!(self.compound_mode_cdf); + reset_2d!(self.deblock_delta_multi_cdf); + reset_1d!(self.deblock_delta_cdf); + reset_2d!(self.spatial_segmentation_cdfs); + reset_1d!(self.lrf_switchable_cdf); + reset_1d!(self.lrf_sgrproj_cdf); + reset_1d!(self.lrf_wiener_cdf); + + reset_1d!(self.nmv_context.joints_cdf); + for i in 0..2 { + reset_1d!(self.nmv_context.comps[i].classes_cdf); + reset_2d!(self.nmv_context.comps[i].class0_fp_cdf); + reset_1d!(self.nmv_context.comps[i].fp_cdf); + reset_1d!(self.nmv_context.comps[i].sign_cdf); + reset_1d!(self.nmv_context.comps[i].class0_hp_cdf); + reset_1d!(self.nmv_context.comps[i].hp_cdf); + reset_1d!(self.nmv_context.comps[i].class0_cdf); + reset_2d!(self.nmv_context.comps[i].bits_cdf); + } + + // lv_map + reset_3d!(self.txb_skip_cdf); + reset_3d!(self.dc_sign_cdf); + reset_4d!(self.eob_extra_cdf); + + reset_3d!(self.eob_flag_cdf16); + reset_3d!(self.eob_flag_cdf32); + reset_3d!(self.eob_flag_cdf64); + reset_3d!(self.eob_flag_cdf128); + reset_3d!(self.eob_flag_cdf256); + reset_3d!(self.eob_flag_cdf512); + reset_3d!(self.eob_flag_cdf1024); + + reset_4d!(self.coeff_base_eob_cdf); + reset_4d!(self.coeff_base_cdf); + reset_4d!(self.coeff_br_cdf); + } + + /// # Panics + /// + /// - If any of the CDF arrays are uninitialized. + /// This should never happen and indicates a development error. + pub fn build_map(&self) -> Vec<(&'static str, usize, usize)> { + use std::mem::size_of_val; + + let partition_w8_cdf_start = + self.partition_w8_cdf.first().unwrap().as_ptr() as usize; + let partition_w8_cdf_end = + partition_w8_cdf_start + size_of_val(&self.partition_w8_cdf); + let partition_w128_cdf_start = + self.partition_w128_cdf.first().unwrap().as_ptr() as usize; + let partition_w128_cdf_end = + partition_w128_cdf_start + size_of_val(&self.partition_w128_cdf); + let partition_cdf_start = + self.partition_cdf.first().unwrap().as_ptr() as usize; + let partition_cdf_end = + partition_cdf_start + size_of_val(&self.partition_cdf); + let kf_y_cdf_start = self.kf_y_cdf.first().unwrap().as_ptr() as usize; + let kf_y_cdf_end = kf_y_cdf_start + size_of_val(&self.kf_y_cdf); + let y_mode_cdf_start = self.y_mode_cdf.first().unwrap().as_ptr() as usize; + let y_mode_cdf_end = y_mode_cdf_start + size_of_val(&self.y_mode_cdf); + let uv_mode_cdf_start = + self.uv_mode_cdf.first().unwrap().as_ptr() as usize; + let uv_mode_cdf_end = uv_mode_cdf_start + size_of_val(&self.uv_mode_cdf); + let uv_mode_cfl_cdf_start = + self.uv_mode_cfl_cdf.first().unwrap().as_ptr() as usize; + let uv_mode_cfl_cdf_end = + uv_mode_cfl_cdf_start + size_of_val(&self.uv_mode_cfl_cdf); + let cfl_sign_cdf_start = self.cfl_sign_cdf.as_ptr() as usize; + let cfl_sign_cdf_end = + cfl_sign_cdf_start + size_of_val(&self.cfl_sign_cdf); + let cfl_alpha_cdf_start = + self.cfl_alpha_cdf.first().unwrap().as_ptr() as usize; + let cfl_alpha_cdf_end = + cfl_alpha_cdf_start + size_of_val(&self.cfl_alpha_cdf); + let newmv_cdf_start = self.newmv_cdf.first().unwrap().as_ptr() as usize; + let newmv_cdf_end = newmv_cdf_start + size_of_val(&self.newmv_cdf); + let zeromv_cdf_start = self.zeromv_cdf.first().unwrap().as_ptr() as usize; + let zeromv_cdf_end = zeromv_cdf_start + size_of_val(&self.zeromv_cdf); + let refmv_cdf_start = self.refmv_cdf.first().unwrap().as_ptr() as usize; + let refmv_cdf_end = refmv_cdf_start + size_of_val(&self.refmv_cdf); + let intra_tx_2_cdf_start = + self.intra_tx_2_cdf.first().unwrap().as_ptr() as usize; + let intra_tx_2_cdf_end = + intra_tx_2_cdf_start + size_of_val(&self.intra_tx_2_cdf); + let intra_tx_1_cdf_start = + self.intra_tx_1_cdf.first().unwrap().as_ptr() as usize; + let intra_tx_1_cdf_end = + intra_tx_1_cdf_start + size_of_val(&self.intra_tx_1_cdf); + let inter_tx_3_cdf_start = + self.inter_tx_3_cdf.first().unwrap().as_ptr() as usize; + let inter_tx_3_cdf_end = + inter_tx_3_cdf_start + size_of_val(&self.inter_tx_3_cdf); + let inter_tx_2_cdf_start = + self.inter_tx_2_cdf.first().unwrap().as_ptr() as usize; + let inter_tx_2_cdf_end = + inter_tx_2_cdf_start + size_of_val(&self.inter_tx_2_cdf); + let inter_tx_1_cdf_start = + self.inter_tx_1_cdf.first().unwrap().as_ptr() as usize; + let inter_tx_1_cdf_end = + inter_tx_1_cdf_start + size_of_val(&self.inter_tx_1_cdf); + let tx_size_8x8_cdf_start = + self.tx_size_8x8_cdf.first().unwrap().as_ptr() as usize; + let tx_size_8x8_cdf_end = + tx_size_8x8_cdf_start + size_of_val(&self.tx_size_8x8_cdf); + let tx_size_cdf_start = + self.tx_size_cdf.first().unwrap().as_ptr() as usize; + let tx_size_cdf_end = tx_size_cdf_start + size_of_val(&self.tx_size_cdf); + let txfm_partition_cdf_start = + self.txfm_partition_cdf.first().unwrap().as_ptr() as usize; + let txfm_partition_cdf_end = + txfm_partition_cdf_start + size_of_val(&self.txfm_partition_cdf); + let skip_cdfs_start = self.skip_cdfs.first().unwrap().as_ptr() as usize; + let skip_cdfs_end = skip_cdfs_start + size_of_val(&self.skip_cdfs); + let intra_inter_cdfs_start = + self.intra_inter_cdfs.first().unwrap().as_ptr() as usize; + let intra_inter_cdfs_end = + intra_inter_cdfs_start + size_of_val(&self.intra_inter_cdfs); + let angle_delta_cdf_start = + self.angle_delta_cdf.first().unwrap().as_ptr() as usize; + let angle_delta_cdf_end = + angle_delta_cdf_start + size_of_val(&self.angle_delta_cdf); + let filter_intra_cdfs_start = + self.filter_intra_cdfs.first().unwrap().as_ptr() as usize; + let filter_intra_cdfs_end = + filter_intra_cdfs_start + size_of_val(&self.filter_intra_cdfs); + let palette_y_mode_cdfs_start = + self.palette_y_mode_cdfs.first().unwrap().as_ptr() as usize; + let palette_y_mode_cdfs_end = + palette_y_mode_cdfs_start + size_of_val(&self.palette_y_mode_cdfs); + let palette_uv_mode_cdfs_start = + self.palette_uv_mode_cdfs.first().unwrap().as_ptr() as usize; + let palette_uv_mode_cdfs_end = + palette_uv_mode_cdfs_start + size_of_val(&self.palette_uv_mode_cdfs); + let comp_mode_cdf_start = + self.comp_mode_cdf.first().unwrap().as_ptr() as usize; + let comp_mode_cdf_end = + comp_mode_cdf_start + size_of_val(&self.comp_mode_cdf); + let comp_ref_type_cdf_start = + self.comp_ref_type_cdf.first().unwrap().as_ptr() as usize; + let comp_ref_type_cdf_end = + comp_ref_type_cdf_start + size_of_val(&self.comp_ref_type_cdf); + let comp_ref_cdf_start = + self.comp_ref_cdf.first().unwrap().as_ptr() as usize; + let comp_ref_cdf_end = + comp_ref_cdf_start + size_of_val(&self.comp_ref_cdf); + let comp_bwd_ref_cdf_start = + self.comp_bwd_ref_cdf.first().unwrap().as_ptr() as usize; + let comp_bwd_ref_cdf_end = + comp_bwd_ref_cdf_start + size_of_val(&self.comp_bwd_ref_cdf); + let single_ref_cdfs_start = + self.single_ref_cdfs.first().unwrap().as_ptr() as usize; + let single_ref_cdfs_end = + single_ref_cdfs_start + size_of_val(&self.single_ref_cdfs); + let drl_cdfs_start = self.drl_cdfs.first().unwrap().as_ptr() as usize; + let drl_cdfs_end = drl_cdfs_start + size_of_val(&self.drl_cdfs); + let compound_mode_cdf_start = + self.compound_mode_cdf.first().unwrap().as_ptr() as usize; + let compound_mode_cdf_end = + compound_mode_cdf_start + size_of_val(&self.compound_mode_cdf); + let nmv_context_start = &self.nmv_context as *const NMVContext as usize; + let nmv_context_end = nmv_context_start + size_of_val(&self.nmv_context); + let deblock_delta_multi_cdf_start = + self.deblock_delta_multi_cdf.first().unwrap().as_ptr() as usize; + let deblock_delta_multi_cdf_end = deblock_delta_multi_cdf_start + + size_of_val(&self.deblock_delta_multi_cdf); + let deblock_delta_cdf_start = self.deblock_delta_cdf.as_ptr() as usize; + let deblock_delta_cdf_end = + deblock_delta_cdf_start + size_of_val(&self.deblock_delta_cdf); + let spatial_segmentation_cdfs_start = + self.spatial_segmentation_cdfs.first().unwrap().as_ptr() as usize; + let spatial_segmentation_cdfs_end = spatial_segmentation_cdfs_start + + size_of_val(&self.spatial_segmentation_cdfs); + let lrf_switchable_cdf_start = self.lrf_switchable_cdf.as_ptr() as usize; + let lrf_switchable_cdf_end = + lrf_switchable_cdf_start + size_of_val(&self.lrf_switchable_cdf); + let lrf_sgrproj_cdf_start = self.lrf_sgrproj_cdf.as_ptr() as usize; + let lrf_sgrproj_cdf_end = + lrf_sgrproj_cdf_start + size_of_val(&self.lrf_sgrproj_cdf); + let lrf_wiener_cdf_start = self.lrf_wiener_cdf.as_ptr() as usize; + let lrf_wiener_cdf_end = + lrf_wiener_cdf_start + size_of_val(&self.lrf_wiener_cdf); + + let txb_skip_cdf_start = + self.txb_skip_cdf.first().unwrap().as_ptr() as usize; + let txb_skip_cdf_end = + txb_skip_cdf_start + size_of_val(&self.txb_skip_cdf); + let dc_sign_cdf_start = + self.dc_sign_cdf.first().unwrap().as_ptr() as usize; + let dc_sign_cdf_end = dc_sign_cdf_start + size_of_val(&self.dc_sign_cdf); + let eob_extra_cdf_start = + self.eob_extra_cdf.first().unwrap().as_ptr() as usize; + let eob_extra_cdf_end = + eob_extra_cdf_start + size_of_val(&self.eob_extra_cdf); + let eob_flag_cdf16_start = + self.eob_flag_cdf16.first().unwrap().as_ptr() as usize; + let eob_flag_cdf16_end = + eob_flag_cdf16_start + size_of_val(&self.eob_flag_cdf16); + let eob_flag_cdf32_start = + self.eob_flag_cdf32.first().unwrap().as_ptr() as usize; + let eob_flag_cdf32_end = + eob_flag_cdf32_start + size_of_val(&self.eob_flag_cdf32); + let eob_flag_cdf64_start = + self.eob_flag_cdf64.first().unwrap().as_ptr() as usize; + let eob_flag_cdf64_end = + eob_flag_cdf64_start + size_of_val(&self.eob_flag_cdf64); + let eob_flag_cdf128_start = + self.eob_flag_cdf128.first().unwrap().as_ptr() as usize; + let eob_flag_cdf128_end = + eob_flag_cdf128_start + size_of_val(&self.eob_flag_cdf128); + let eob_flag_cdf256_start = + self.eob_flag_cdf256.first().unwrap().as_ptr() as usize; + let eob_flag_cdf256_end = + eob_flag_cdf256_start + size_of_val(&self.eob_flag_cdf256); + let eob_flag_cdf512_start = + self.eob_flag_cdf512.first().unwrap().as_ptr() as usize; + let eob_flag_cdf512_end = + eob_flag_cdf512_start + size_of_val(&self.eob_flag_cdf512); + let eob_flag_cdf1024_start = + self.eob_flag_cdf1024.first().unwrap().as_ptr() as usize; + let eob_flag_cdf1024_end = + eob_flag_cdf1024_start + size_of_val(&self.eob_flag_cdf1024); + let coeff_base_eob_cdf_start = + self.coeff_base_eob_cdf.first().unwrap().as_ptr() as usize; + let coeff_base_eob_cdf_end = + coeff_base_eob_cdf_start + size_of_val(&self.coeff_base_eob_cdf); + let coeff_base_cdf_start = + self.coeff_base_cdf.first().unwrap().as_ptr() as usize; + let coeff_base_cdf_end = + coeff_base_cdf_start + size_of_val(&self.coeff_base_cdf); + let coeff_br_cdf_start = + self.coeff_br_cdf.first().unwrap().as_ptr() as usize; + let coeff_br_cdf_end = + coeff_br_cdf_start + size_of_val(&self.coeff_br_cdf); + + vec![ + ("partition_w8_cdf", partition_w8_cdf_start, partition_w8_cdf_end), + ("partition_w128_cdf", partition_w128_cdf_start, partition_w128_cdf_end), + ("partition_cdf", partition_cdf_start, partition_cdf_end), + ("kf_y_cdf", kf_y_cdf_start, kf_y_cdf_end), + ("y_mode_cdf", y_mode_cdf_start, y_mode_cdf_end), + ("uv_mode_cdf", uv_mode_cdf_start, uv_mode_cdf_end), + ("uv_mode_cfl_cdf", uv_mode_cfl_cdf_start, uv_mode_cfl_cdf_end), + ("cfl_sign_cdf", cfl_sign_cdf_start, cfl_sign_cdf_end), + ("cfl_alpha_cdf", cfl_alpha_cdf_start, cfl_alpha_cdf_end), + ("newmv_cdf", newmv_cdf_start, newmv_cdf_end), + ("zeromv_cdf", zeromv_cdf_start, zeromv_cdf_end), + ("refmv_cdf", refmv_cdf_start, refmv_cdf_end), + ("intra_tx_2_cdf", intra_tx_2_cdf_start, intra_tx_2_cdf_end), + ("intra_tx_1_cdf", intra_tx_1_cdf_start, intra_tx_1_cdf_end), + ("inter_tx_3_cdf", inter_tx_3_cdf_start, inter_tx_3_cdf_end), + ("inter_tx_2_cdf", inter_tx_2_cdf_start, inter_tx_2_cdf_end), + ("inter_tx_1_cdf", inter_tx_1_cdf_start, inter_tx_1_cdf_end), + ("tx_size_8x8_cdf", tx_size_8x8_cdf_start, tx_size_8x8_cdf_end), + ("tx_size_cdf", tx_size_cdf_start, tx_size_cdf_end), + ("txfm_partition_cdf", txfm_partition_cdf_start, txfm_partition_cdf_end), + ("skip_cdfs", skip_cdfs_start, skip_cdfs_end), + ("intra_inter_cdfs", intra_inter_cdfs_start, intra_inter_cdfs_end), + ("angle_delta_cdf", angle_delta_cdf_start, angle_delta_cdf_end), + ("filter_intra_cdfs", filter_intra_cdfs_start, filter_intra_cdfs_end), + ( + "palette_y_mode_cdfs", + palette_y_mode_cdfs_start, + palette_y_mode_cdfs_end, + ), + ( + "palette_uv_mode_cdfs", + palette_uv_mode_cdfs_start, + palette_uv_mode_cdfs_end, + ), + ("comp_mode_cdf", comp_mode_cdf_start, comp_mode_cdf_end), + ("comp_ref_type_cdf", comp_ref_type_cdf_start, comp_ref_type_cdf_end), + ("comp_ref_cdf", comp_ref_cdf_start, comp_ref_cdf_end), + ("comp_bwd_ref_cdf", comp_bwd_ref_cdf_start, comp_bwd_ref_cdf_end), + ("single_ref_cdfs", single_ref_cdfs_start, single_ref_cdfs_end), + ("drl_cdfs", drl_cdfs_start, drl_cdfs_end), + ("compound_mode_cdf", compound_mode_cdf_start, compound_mode_cdf_end), + ("nmv_context", nmv_context_start, nmv_context_end), + ( + "deblock_delta_multi_cdf", + deblock_delta_multi_cdf_start, + deblock_delta_multi_cdf_end, + ), + ("deblock_delta_cdf", deblock_delta_cdf_start, deblock_delta_cdf_end), + ( + "spatial_segmentation_cdfs", + spatial_segmentation_cdfs_start, + spatial_segmentation_cdfs_end, + ), + ("lrf_switchable_cdf", lrf_switchable_cdf_start, lrf_switchable_cdf_end), + ("lrf_sgrproj_cdf", lrf_sgrproj_cdf_start, lrf_sgrproj_cdf_end), + ("lrf_wiener_cdf", lrf_wiener_cdf_start, lrf_wiener_cdf_end), + ("txb_skip_cdf", txb_skip_cdf_start, txb_skip_cdf_end), + ("dc_sign_cdf", dc_sign_cdf_start, dc_sign_cdf_end), + ("eob_extra_cdf", eob_extra_cdf_start, eob_extra_cdf_end), + ("eob_flag_cdf16", eob_flag_cdf16_start, eob_flag_cdf16_end), + ("eob_flag_cdf32", eob_flag_cdf32_start, eob_flag_cdf32_end), + ("eob_flag_cdf64", eob_flag_cdf64_start, eob_flag_cdf64_end), + ("eob_flag_cdf128", eob_flag_cdf128_start, eob_flag_cdf128_end), + ("eob_flag_cdf256", eob_flag_cdf256_start, eob_flag_cdf256_end), + ("eob_flag_cdf512", eob_flag_cdf512_start, eob_flag_cdf512_end), + ("eob_flag_cdf1024", eob_flag_cdf1024_start, eob_flag_cdf1024_end), + ("coeff_base_eob_cdf", coeff_base_eob_cdf_start, coeff_base_eob_cdf_end), + ("coeff_base_cdf", coeff_base_cdf_start, coeff_base_cdf_end), + ("coeff_br_cdf", coeff_br_cdf_start, coeff_br_cdf_end), + ] + } + + pub fn offset( + &self, cdf: *const [u16; CDF_LEN], + ) -> CDFOffset { + CDFOffset { + offset: cdf as usize - self as *const _ as usize, + phantom: PhantomData, + } + } +} + +impl fmt::Debug for CDFContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "CDFContext contains too many numbers to print :-(") + } +} + +macro_rules! symbol_with_update { + ($self:ident, $w:ident, $s:expr, $cdf:expr) => { + let cdf = $self.fc.offset($cdf); + $w.symbol_with_update($s, cdf, &mut $self.fc_log, &mut $self.fc); + symbol_with_update!($self, $cdf); + }; + ($self:ident, $cdf:expr) => { + #[cfg(feature = "desync_finder")] + { + let cdf: &[_] = $cdf; + if let Some(map) = $self.fc_map.as_ref() { + map.lookup(cdf.as_ptr() as usize); + } + } + }; +} + +#[derive(Clone)] +pub struct ContextWriterCheckpoint { + pub fc: CDFContextCheckpoint, + pub bc: BlockContextCheckpoint, +} + +struct CDFContextLogPartition { + pub data: Vec<[u16; CDF_LEN_MAX_PLUS_1]>, +} + +impl + CDFContextLogPartition +{ + fn new(capacity: usize) -> Self { + Self { data: Vec::with_capacity(capacity) } + } + #[inline(always)] + fn push( + &mut self, fc: &mut CDFContext, cdf: CDFOffset, + ) -> &mut [u16; CDF_LEN] { + debug_assert!(CDF_LEN < CDF_LEN_MAX_PLUS_1); + debug_assert!(cdf.offset <= u16::MAX.into()); + // SAFETY: Maintain an invariant of non-zero spare capacity, so that + // branching may be deferred until writes are issued. Benchmarks indicate + // this is faster than first testing capacity and possibly reallocating. + unsafe { + let len = self.data.len(); + let new_len = len + 1; + let capacity = self.data.capacity(); + debug_assert!(new_len <= capacity); + let dst = self.data.as_mut_ptr().add(len) as *mut u16; + let base = fc as *mut _ as *mut u8; + let src = base.add(cdf.offset) as *const u16; + dst.copy_from_nonoverlapping(src, CDF_LEN_MAX_PLUS_1 - 1); + *dst.add(CDF_LEN_MAX_PLUS_1 - 1) = cdf.offset as u16; + self.data.set_len(new_len); + if CDF_LEN_MAX_PLUS_1 > capacity.wrapping_sub(new_len) { + self.data.reserve(CDF_LEN_MAX_PLUS_1); + } + let cdf = base.add(cdf.offset) as *mut [u16; CDF_LEN]; + &mut *cdf + } + } + #[inline(always)] + fn rollback(&mut self, fc: &mut CDFContext, checkpoint: usize) { + let base = fc as *mut _ as *mut u8; + let mut len = self.data.len(); + // SAFETY: We use unchecked pointers here for performance. + // Since we know the length, we can ensure not to go OOB. + unsafe { + let mut src = self.data.as_mut_ptr().add(len); + while len > checkpoint { + len -= 1; + src = src.sub(1); + let src = src as *mut u16; + let offset = *src.add(CDF_LEN_MAX_PLUS_1 - 1) as usize; + let dst = base.add(offset) as *mut u16; + dst.copy_from_nonoverlapping(src, CDF_LEN_MAX_PLUS_1 - 1); + } + self.data.set_len(len); + } + } +} + +const CDF_LEN_SMALL: usize = 4; + +pub struct CDFContextLog { + small: CDFContextLogPartition<{ CDF_LEN_SMALL + 1 }>, + large: CDFContextLogPartition<{ CDF_LEN_MAX + 1 }>, +} + +impl Default for CDFContextLog { + fn default() -> Self { + Self { + small: CDFContextLogPartition::new(1 << 16), + large: CDFContextLogPartition::new(1 << 9), + } + } +} + +impl CDFContextLog { + fn checkpoint(&self) -> CDFContextCheckpoint { + CDFContextCheckpoint { + small: self.small.data.len(), + large: self.large.data.len(), + } + } + #[inline(always)] + pub fn push( + &mut self, fc: &mut CDFContext, cdf: CDFOffset, + ) -> &mut [u16; CDF_LEN] { + if CDF_LEN <= CDF_LEN_SMALL { + self.small.push(fc, cdf) + } else { + self.large.push(fc, cdf) + } + } + #[inline(always)] + pub fn rollback( + &mut self, fc: &mut CDFContext, checkpoint: &CDFContextCheckpoint, + ) { + self.small.rollback(fc, checkpoint.small); + self.large.rollback(fc, checkpoint.large); + } + pub fn clear(&mut self) { + self.small.data.clear(); + self.large.data.clear(); + } +} + +pub struct ContextWriter<'a> { + pub bc: BlockContext<'a>, + pub fc: &'a mut CDFContext, + pub fc_log: CDFContextLog, + #[cfg(feature = "desync_finder")] + pub fc_map: Option, // For debugging purposes +} + +impl<'a> ContextWriter<'a> { + #[allow(clippy::let_and_return)] + pub fn new(fc: &'a mut CDFContext, bc: BlockContext<'a>) -> Self { + let fc_log = CDFContextLog::default(); + #[allow(unused_mut)] + let mut cw = ContextWriter { + bc, + fc, + fc_log, + #[cfg(feature = "desync_finder")] + fc_map: Default::default(), + }; + #[cfg(feature = "desync_finder")] + { + if std::env::var_os("RAV1E_DEBUG").is_some() { + cw.fc_map = Some(FieldMap { map: cw.fc.build_map() }); + } + } + + cw + } + + pub const fn cdf_element_prob(cdf: &[u16], element: usize) -> u16 { + (if element > 0 { cdf[element - 1] } else { 32768 }) + - (if element + 1 < cdf.len() { cdf[element] } else { 0 }) + } + + pub fn checkpoint( + &self, tile_bo: &TileBlockOffset, chroma_sampling: ChromaSampling, + ) -> ContextWriterCheckpoint { + ContextWriterCheckpoint { + fc: self.fc_log.checkpoint(), + bc: self.bc.checkpoint(tile_bo, chroma_sampling), + } + } + + pub fn rollback(&mut self, checkpoint: &ContextWriterCheckpoint) { + self.fc_log.rollback(self.fc, &checkpoint.fc); + self.bc.rollback(&checkpoint.bc); + #[cfg(feature = "desync_finder")] + { + if self.fc_map.is_some() { + self.fc_map = Some(FieldMap { map: self.fc.build_map() }); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/frame_header.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/frame_header.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/frame_header.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/frame_header.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,275 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +impl CDFContext { + // rather than test writing and rolling back the cdf, we just count Q8 bits using the current cdf + pub fn count_lrf_switchable( + &self, w: &W, rs: &TileRestorationState, filter: RestorationFilter, + pli: usize, + ) -> u32 { + match filter { + RestorationFilter::None => w.symbol_bits(0, &self.lrf_switchable_cdf), + RestorationFilter::Wiener { .. } => { + unreachable!() // for now, not permanently + } + RestorationFilter::Sgrproj { set, xqd } => { + // Does *not* use 'RESTORE_SGRPROJ' but rather just '2' + let rp = &rs.planes[pli]; + let mut bits = w.symbol_bits(2, &self.lrf_switchable_cdf) + + ((SGRPROJ_PARAMS_BITS as u32) << OD_BITRES); + for i in 0..2 { + let s = SGRPROJ_PARAMS_S[set as usize][i]; + let min = SGRPROJ_XQD_MIN[i] as i32; + let max = SGRPROJ_XQD_MAX[i] as i32; + if s > 0 { + bits += w.count_signed_subexp_with_ref( + xqd[i] as i32, + min, + max + 1, + SGRPROJ_PRJ_SUBEXP_K, + rp.sgrproj_ref[i] as i32, + ); + } + } + bits + } + } + } +} + +impl ContextWriter<'_> { + fn get_ref_frame_ctx_b0(&self, bo: TileBlockOffset) -> usize { + let ref_counts = self.bc.blocks[bo].neighbors_ref_counts; + + let fwd_cnt = ref_counts[LAST_FRAME.to_index()] + + ref_counts[LAST2_FRAME.to_index()] + + ref_counts[LAST3_FRAME.to_index()] + + ref_counts[GOLDEN_FRAME.to_index()]; + + let bwd_cnt = ref_counts[BWDREF_FRAME.to_index()] + + ref_counts[ALTREF2_FRAME.to_index()] + + ref_counts[ALTREF_FRAME.to_index()]; + + ContextWriter::ref_count_ctx(fwd_cnt, bwd_cnt) + } + + /// # Panics + /// + /// - If the `comp_mode` setting does not match the reference mode and size. + pub fn write_ref_frames( + &mut self, w: &mut W, fi: &FrameInvariants, bo: TileBlockOffset, + ) { + let rf = self.bc.blocks[bo].ref_frames; + let sz = self.bc.blocks[bo].n4_w.min(self.bc.blocks[bo].n4_h); + + /* TODO: Handle multiple references */ + let comp_mode = self.bc.blocks[bo].has_second_ref(); + + if fi.reference_mode != ReferenceMode::SINGLE && sz >= 2 { + let ctx = self.get_comp_mode_ctx(bo); + let cdf = &self.fc.comp_mode_cdf[ctx]; + symbol_with_update!(self, w, comp_mode as u32, cdf); + } else { + assert!(!comp_mode); + } + + if comp_mode { + let comp_ref_type: u32 = 1; // bidir + let ctx = self.get_comp_ref_type_ctx(bo); + let cdf = &self.fc.comp_ref_type_cdf[ctx]; + symbol_with_update!(self, w, comp_ref_type, cdf); + + if comp_ref_type == 0 { + unimplemented!(); + } else { + let compref = rf[0] == GOLDEN_FRAME || rf[0] == LAST3_FRAME; + let ctx = self.get_pred_ctx_ll2_or_l3gld(bo); + let cdf = &self.fc.comp_ref_cdf[ctx][0]; + symbol_with_update!(self, w, compref as u32, cdf); + if !compref { + let compref_p1 = rf[0] == LAST2_FRAME; + let ctx = self.get_pred_ctx_last_or_last2(bo); + let cdf = &self.fc.comp_ref_cdf[ctx][1]; + symbol_with_update!(self, w, compref_p1 as u32, cdf); + } else { + let compref_p2 = rf[0] == GOLDEN_FRAME; + let ctx = self.get_pred_ctx_last3_or_gold(bo); + let cdf = &self.fc.comp_ref_cdf[ctx][2]; + symbol_with_update!(self, w, compref_p2 as u32, cdf); + } + let comp_bwdref = rf[1] == ALTREF_FRAME; + let ctx = self.get_pred_ctx_brfarf2_or_arf(bo); + let cdf = &self.fc.comp_bwd_ref_cdf[ctx][0]; + symbol_with_update!(self, w, comp_bwdref as u32, cdf); + if !comp_bwdref { + let comp_bwdref_p1 = rf[1] == ALTREF2_FRAME; + let ctx = self.get_pred_ctx_brf_or_arf2(bo); + let cdf = &self.fc.comp_bwd_ref_cdf[ctx][1]; + symbol_with_update!(self, w, comp_bwdref_p1 as u32, cdf); + } + } + } else { + let b0_ctx = self.get_ref_frame_ctx_b0(bo); + let b0 = rf[0] != NONE_FRAME && rf[0].is_bwd_ref(); + + let cdf = &self.fc.single_ref_cdfs[b0_ctx][0]; + symbol_with_update!(self, w, b0 as u32, cdf); + if b0 { + let b1_ctx = self.get_pred_ctx_brfarf2_or_arf(bo); + let b1 = rf[0] == ALTREF_FRAME; + + let cdf = &self.fc.single_ref_cdfs[b1_ctx][1]; + symbol_with_update!(self, w, b1 as u32, cdf); + if !b1 { + let b5_ctx = self.get_pred_ctx_brf_or_arf2(bo); + let b5 = rf[0] == ALTREF2_FRAME; + + let cdf = &self.fc.single_ref_cdfs[b5_ctx][5]; + symbol_with_update!(self, w, b5 as u32, cdf); + } + } else { + let b2_ctx = self.get_pred_ctx_ll2_or_l3gld(bo); + let b2 = rf[0] == LAST3_FRAME || rf[0] == GOLDEN_FRAME; + + let cdf = &self.fc.single_ref_cdfs[b2_ctx][2]; + symbol_with_update!(self, w, b2 as u32, cdf); + if !b2 { + let b3_ctx = self.get_pred_ctx_last_or_last2(bo); + let b3 = rf[0] != LAST_FRAME; + + let cdf = &self.fc.single_ref_cdfs[b3_ctx][3]; + symbol_with_update!(self, w, b3 as u32, cdf); + } else { + let b4_ctx = self.get_pred_ctx_last3_or_gold(bo); + let b4 = rf[0] != LAST3_FRAME; + + let cdf = &self.fc.single_ref_cdfs[b4_ctx][4]; + symbol_with_update!(self, w, b4 as u32, cdf); + } + } + } + } + + pub fn count_lrf_switchable( + &self, w: &W, rs: &TileRestorationState, filter: RestorationFilter, + pli: usize, + ) -> u32 { + self.fc.count_lrf_switchable(w, rs, filter, pli) + } + + /// # Panics + /// + /// - If the LRF has already been written for this superblock + pub fn write_lrf( + &mut self, w: &mut W, rs: &mut TileRestorationStateMut, + sbo: TileSuperBlockOffset, pli: usize, + ) { + let rp = &mut rs.planes[pli]; + if let Some(filter) = rp.restoration_unit(sbo, true).map(|ru| ru.filter) { + match filter { + RestorationFilter::None => match rp.rp_cfg.lrf_type { + RESTORE_WIENER => { + let cdf = &self.fc.lrf_wiener_cdf; + symbol_with_update!(self, w, 0, cdf); + } + RESTORE_SGRPROJ => { + let cdf = &self.fc.lrf_sgrproj_cdf; + symbol_with_update!(self, w, 0, cdf); + } + RESTORE_SWITCHABLE => { + let cdf = &self.fc.lrf_switchable_cdf; + symbol_with_update!(self, w, 0, cdf); + } + RESTORE_NONE => {} + _ => unreachable!(), + }, + RestorationFilter::Sgrproj { set, xqd } => { + match rp.rp_cfg.lrf_type { + RESTORE_SGRPROJ => { + let cdf = &self.fc.lrf_sgrproj_cdf; + symbol_with_update!(self, w, 1, cdf); + } + RESTORE_SWITCHABLE => { + // Does *not* write 'RESTORE_SGRPROJ' + let cdf = &self.fc.lrf_switchable_cdf; + symbol_with_update!(self, w, 2, cdf); + } + _ => unreachable!(), + } + w.literal(SGRPROJ_PARAMS_BITS, set as u32); + for i in 0..2 { + let s = SGRPROJ_PARAMS_S[set as usize][i]; + let min = SGRPROJ_XQD_MIN[i] as i32; + let max = SGRPROJ_XQD_MAX[i] as i32; + if s > 0 { + w.write_signed_subexp_with_ref( + xqd[i] as i32, + min, + max + 1, + SGRPROJ_PRJ_SUBEXP_K, + rp.sgrproj_ref[i] as i32, + ); + rp.sgrproj_ref[i] = xqd[i]; + } else { + // Nothing written, just update the reference + if i == 0 { + assert!(xqd[i] == 0); + rp.sgrproj_ref[0] = 0; + } else { + rp.sgrproj_ref[1] = 95; // LOL at spec. The result is always 95. + } + } + } + } + RestorationFilter::Wiener { coeffs } => { + match rp.rp_cfg.lrf_type { + RESTORE_WIENER => { + let cdf = &self.fc.lrf_wiener_cdf; + symbol_with_update!(self, w, 1, cdf); + } + RESTORE_SWITCHABLE => { + // Does *not* write 'RESTORE_WIENER' + let cdf = &self.fc.lrf_switchable_cdf; + symbol_with_update!(self, w, 1, cdf); + } + _ => unreachable!(), + } + for pass in 0..2 { + let first_coeff = if pli == 0 { + 0 + } else { + assert!(coeffs[pass][0] == 0); + 1 + }; + for i in first_coeff..3 { + let min = WIENER_TAPS_MIN[i] as i32; + let max = WIENER_TAPS_MAX[i] as i32; + w.write_signed_subexp_with_ref( + coeffs[pass][i] as i32, + min, + max + 1, + (i + 1) as u8, + rp.wiener_ref[pass][i] as i32, + ); + rp.wiener_ref[pass][i] = coeffs[pass][i]; + } + } + } + } + } + } + + pub fn write_cdef( + &mut self, w: &mut W, strength_index: u8, bits: u8, + ) { + w.literal(bits, strength_index as u32); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,246 @@ +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +use crate::color::ChromaSampling; +use crate::ec::{Writer, OD_BITRES}; +use crate::encoder::FrameInvariants; +use crate::entropymode::*; +use crate::frame::*; +use crate::header::ReferenceMode; +use crate::lrf::*; +use crate::mc::MotionVector; +use crate::partition::BlockSize::*; +use crate::partition::RefType::*; +use crate::partition::*; +use crate::scan_order::*; +use crate::tiling::*; +use crate::token_cdfs::*; +use crate::transform::TxSize::*; + +use crate::transform::*; +use crate::util::*; + +use arrayvec::*; +use std::default::Default; +use std::ops::{Add, Index, IndexMut}; +use std::*; + +const MAX_REF_MV_STACK_SIZE: usize = 8; +pub const REF_CAT_LEVEL: u32 = 640; + +pub const FRAME_LF_COUNT: usize = 4; +pub const MAX_LOOP_FILTER: usize = 63; +const DELTA_LF_SMALL: u32 = 3; +pub const DELTA_LF_PROBS: usize = DELTA_LF_SMALL as usize; + +const DELTA_Q_SMALL: u32 = 3; +pub const DELTA_Q_PROBS: usize = DELTA_Q_SMALL as usize; + +static size_group_lookup: [u8; BlockSize::BLOCK_SIZES_ALL] = + [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 0, 0, 1, 1, 2, 2]; + +static num_pels_log2_lookup: [u8; BlockSize::BLOCK_SIZES_ALL] = + [4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 14, 6, 6, 8, 8, 10, 10]; + +#[macro_use] +mod cdf_context; +pub use cdf_context::*; + +mod partition_unit; +pub use partition_unit::*; + +mod superblock_unit; +pub use superblock_unit::*; + +mod transform_unit; +pub use transform_unit::TxClass::*; +pub use transform_unit::*; + +mod block_unit; +pub use block_unit::*; + +mod frame_header; + +#[derive(Debug, Default)] +pub struct FieldMap { + map: Vec<(&'static str, usize, usize)>, +} + +impl FieldMap { + /// Print the field the address belong to + fn lookup(&self, addr: usize) { + for (name, start, end) in &self.map { + if addr >= *start && addr < *end { + println!(" CDF {name}"); + println!(); + return; + } + } + + println!(" CDF address not found: {addr}"); + } +} + +#[inline] +pub const fn av1_get_coded_tx_size(tx_size: TxSize) -> TxSize { + match tx_size { + TX_64X64 | TX_64X32 | TX_32X64 => TX_32X32, + TX_16X64 => TX_16X32, + TX_64X16 => TX_32X16, + _ => tx_size, + } +} + +/* Symbols for coding magnitude class of nonzero components */ +const MV_CLASSES: usize = 11; + +// MV Class Types +const MV_CLASS_0: usize = 0; /* (0, 2] integer pel */ +const MV_CLASS_1: usize = 1; /* (2, 4] integer pel */ +const MV_CLASS_2: usize = 2; /* (4, 8] integer pel */ +const MV_CLASS_3: usize = 3; /* (8, 16] integer pel */ +const MV_CLASS_4: usize = 4; /* (16, 32] integer pel */ +const MV_CLASS_5: usize = 5; /* (32, 64] integer pel */ +const MV_CLASS_6: usize = 6; /* (64, 128] integer pel */ +const MV_CLASS_7: usize = 7; /* (128, 256] integer pel */ +const MV_CLASS_8: usize = 8; /* (256, 512] integer pel */ +const MV_CLASS_9: usize = 9; /* (512, 1024] integer pel */ +const MV_CLASS_10: usize = 10; /* (1024,2048] integer pel */ + +const CLASS0_BITS: usize = 1; /* bits at integer precision for class 0 */ +const CLASS0_SIZE: usize = 1 << CLASS0_BITS; +const MV_OFFSET_BITS: usize = MV_CLASSES + CLASS0_BITS - 2; +const MV_BITS_CONTEXTS: usize = 6; +const MV_FP_SIZE: usize = 4; + +const MV_MAX_BITS: usize = MV_CLASSES + CLASS0_BITS + 2; +const MV_MAX: usize = (1 << MV_MAX_BITS) - 1; +const MV_VALS: usize = (MV_MAX << 1) + 1; + +const MV_IN_USE_BITS: usize = 14; +pub const MV_UPP: i32 = 1 << MV_IN_USE_BITS; +pub const MV_LOW: i32 = -(1 << MV_IN_USE_BITS); + +#[inline(always)] +pub const fn av1_get_mv_joint(mv: MotionVector) -> MvJointType { + match (mv.row, mv.col) { + (0, 0) => MvJointType::MV_JOINT_ZERO, + (0, _) => MvJointType::MV_JOINT_HNZVZ, + (_, 0) => MvJointType::MV_JOINT_HZVNZ, + (_, _) => MvJointType::MV_JOINT_HNZVNZ, + } +} +#[inline(always)] +pub fn mv_joint_vertical(joint_type: MvJointType) -> bool { + joint_type == MvJointType::MV_JOINT_HZVNZ + || joint_type == MvJointType::MV_JOINT_HNZVNZ +} +#[inline(always)] +pub fn mv_joint_horizontal(joint_type: MvJointType) -> bool { + joint_type == MvJointType::MV_JOINT_HNZVZ + || joint_type == MvJointType::MV_JOINT_HNZVNZ +} +#[inline(always)] +pub const fn mv_class_base(mv_class: usize) -> u32 { + if mv_class != MV_CLASS_0 { + (CLASS0_SIZE << (mv_class + 2)) as u32 + } else { + 0 + } +} +#[inline(always)] +// If n != 0, returns the floor of log base 2 of n. If n == 0, returns 0. +pub fn log_in_base_2(n: u32) -> u8 { + 31 - cmp::min(31, n.leading_zeros() as u8) +} + +/// Returns `(mv_class, offset)` +#[inline(always)] +pub fn get_mv_class(z: u32) -> (usize, u32) { + let c = if z >= CLASS0_SIZE as u32 * 4096 { + MV_CLASS_10 + } else { + log_in_base_2(z >> 3) as usize + }; + + let offset = z - mv_class_base(c); + (c, offset) +} + +impl ContextWriter<'_> { + /// # Panics + /// + /// - If the `comp` is 0 + /// - If the `comp` is outside the bounds of `MV_LOW` and `MV_UPP` + pub fn encode_mv_component( + &mut self, w: &mut W, comp: i32, axis: usize, precision: MvSubpelPrecision, + ) { + assert!(comp != 0); + assert!((MV_LOW..=MV_UPP).contains(&comp)); + let sign: u32 = u32::from(comp < 0); + let mag: u32 = if sign == 1 { -comp as u32 } else { comp as u32 }; + let (mv_class, offset) = get_mv_class(mag - 1); + let d = offset >> 3; // int mv data + let fr = (offset >> 1) & 3; // fractional mv data + let hp = offset & 1; // high precision mv data + + // Sign + { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = &mvcomp.sign_cdf; + symbol_with_update!(self, w, sign, cdf); + } + + // Class + { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = &mvcomp.classes_cdf; + symbol_with_update!(self, w, mv_class as u32, cdf); + } + + // Integer bits + if mv_class == MV_CLASS_0 { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = &mvcomp.class0_cdf; + symbol_with_update!(self, w, d, cdf); + } else { + let n = mv_class + CLASS0_BITS - 1; // number of bits + for i in 0..n { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = &mvcomp.bits_cdf[i]; + symbol_with_update!(self, w, (d >> i) & 1, cdf); + } + } + // Fractional bits + if precision > MvSubpelPrecision::MV_SUBPEL_NONE { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = if mv_class == MV_CLASS_0 { + &mvcomp.class0_fp_cdf[d as usize] + } else { + &mvcomp.fp_cdf + }; + symbol_with_update!(self, w, fr, cdf); + } + + // High precision bit + if precision > MvSubpelPrecision::MV_SUBPEL_LOW_PRECISION { + let mvcomp = &self.fc.nmv_context.comps[axis]; + let cdf = if mv_class == MV_CLASS_0 { + &mvcomp.class0_hp_cdf + } else { + &mvcomp.hp_cdf + }; + symbol_with_update!(self, w, hp, cdf); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/partition_unit.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/partition_unit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/partition_unit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/partition_unit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,550 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +// Generates 4 bit field in which each bit set to 1 represents +// a blocksize partition 1111 means we split 64x64, 32x32, 16x16 +// and 8x8. 1000 means we just split the 64x64 to 32x32 +pub static partition_context_lookup: [[u8; 2]; BlockSize::BLOCK_SIZES_ALL] = [ + [31, 31], // 4X4 - {0b11111, 0b11111} + [31, 30], // 4X8 - {0b11111, 0b11110} + [30, 31], // 8X4 - {0b11110, 0b11111} + [30, 30], // 8X8 - {0b11110, 0b11110} + [30, 28], // 8X16 - {0b11110, 0b11100} + [28, 30], // 16X8 - {0b11100, 0b11110} + [28, 28], // 16X16 - {0b11100, 0b11100} + [28, 24], // 16X32 - {0b11100, 0b11000} + [24, 28], // 32X16 - {0b11000, 0b11100} + [24, 24], // 32X32 - {0b11000, 0b11000} + [24, 16], // 32X64 - {0b11000, 0b10000} + [16, 24], // 64X32 - {0b10000, 0b11000} + [16, 16], // 64X64 - {0b10000, 0b10000} + [16, 0], // 64X128- {0b10000, 0b00000} + [0, 16], // 128X64- {0b00000, 0b10000} + [0, 0], // 128X128-{0b00000, 0b00000} + [31, 28], // 4X16 - {0b11111, 0b11100} + [28, 31], // 16X4 - {0b11100, 0b11111} + [30, 24], // 8X32 - {0b11110, 0b11000} + [24, 30], // 32X8 - {0b11000, 0b11110} + [28, 16], // 16X64 - {0b11100, 0b10000} + [16, 28], // 64X16 - {0b10000, 0b11100} +]; + +pub const CFL_JOINT_SIGNS: usize = 8; +pub const CFL_ALPHA_CONTEXTS: usize = 6; +pub const CFL_ALPHABET_SIZE: usize = 16; + +pub const PARTITION_PLOFFSET: usize = 4; +pub const PARTITION_BLOCK_SIZES: usize = 4 + 1; +const PARTITION_CONTEXTS_PRIMARY: usize = + PARTITION_BLOCK_SIZES * PARTITION_PLOFFSET; +pub const PARTITION_CONTEXTS: usize = PARTITION_CONTEXTS_PRIMARY; +pub const PARTITION_TYPES: usize = 4; +pub const EXT_PARTITION_TYPES: usize = 10; + +pub const SKIP_CONTEXTS: usize = 3; +pub const SKIP_MODE_CONTEXTS: usize = 3; + +// partition contexts are at 8x8 granularity, as it is not possible to +// split 4x4 blocks any further than that +pub const PARTITION_CONTEXT_GRANULARITY: usize = 8; +pub const PARTITION_CONTEXT_MAX_WIDTH: usize = + MAX_TILE_WIDTH / PARTITION_CONTEXT_GRANULARITY; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum CFLSign { + CFL_SIGN_ZERO = 0, + CFL_SIGN_NEG = 1, + CFL_SIGN_POS = 2, +} + +impl CFLSign { + pub const fn from_alpha(a: i16) -> CFLSign { + [CFL_SIGN_NEG, CFL_SIGN_ZERO, CFL_SIGN_POS][(a.signum() + 1) as usize] + } +} + +use crate::context::CFLSign::*; + +const CFL_SIGNS: usize = 3; +static cfl_sign_value: [i16; CFL_SIGNS] = [0, -1, 1]; + +#[derive(Copy, Clone, Debug)] +pub struct CFLParams { + pub sign: [CFLSign; 2], + pub scale: [u8; 2], +} + +impl Default for CFLParams { + #[inline] + fn default() -> Self { + Self { sign: [CFL_SIGN_NEG, CFL_SIGN_ZERO], scale: [1, 0] } + } +} + +impl CFLParams { + /// # Panics + /// + /// - If either current sign is zero + #[inline] + pub fn joint_sign(self) -> u32 { + assert!(self.sign[0] != CFL_SIGN_ZERO || self.sign[1] != CFL_SIGN_ZERO); + (self.sign[0] as u32) * (CFL_SIGNS as u32) + (self.sign[1] as u32) - 1 + } + /// # Panics + /// + /// - If the sign at index `uv` is zero + #[inline] + pub fn context(self, uv: usize) -> usize { + assert!(self.sign[uv] != CFL_SIGN_ZERO); + (self.sign[uv] as usize - 1) * CFL_SIGNS + (self.sign[1 - uv] as usize) + } + /// # Panics + /// + /// - If the sign at index `uv` is zero + #[inline] + pub fn index(self, uv: usize) -> u32 { + assert!(self.sign[uv] != CFL_SIGN_ZERO && self.scale[uv] != 0); + (self.scale[uv] - 1) as u32 + } + #[inline] + pub fn alpha(self, uv: usize) -> i16 { + cfl_sign_value[self.sign[uv] as usize] * (self.scale[uv] as i16) + } + #[inline] + pub const fn from_alpha(u: i16, v: i16) -> CFLParams { + CFLParams { + sign: [CFLSign::from_alpha(u), CFLSign::from_alpha(v)], + scale: [u.unsigned_abs() as u8, v.unsigned_abs() as u8], + } + } +} + +impl ContextWriter<'_> { + fn partition_gather_horz_alike( + out: &mut [u16; 2], cdf_in: &[u16], _bsize: BlockSize, + ) { + out[0] = 32768; + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_HORZ as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_SPLIT as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_HORZ_A as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_HORZ_B as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_VERT_A as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_HORZ_4 as usize, + ); + out[0] = 32768 - out[0]; + out[1] = 0; + } + + fn partition_gather_vert_alike( + out: &mut [u16; 2], cdf_in: &[u16], _bsize: BlockSize, + ) { + out[0] = 32768; + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_VERT as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_SPLIT as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_HORZ_A as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_VERT_A as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_VERT_B as usize, + ); + out[0] -= ContextWriter::cdf_element_prob( + cdf_in, + PartitionType::PARTITION_VERT_4 as usize, + ); + out[0] = 32768 - out[0]; + out[1] = 0; + } + + #[inline] + pub fn write_skip( + &mut self, w: &mut W, bo: TileBlockOffset, skip: bool, + ) { + let ctx = self.bc.skip_context(bo); + let cdf = &self.fc.skip_cdfs[ctx]; + symbol_with_update!(self, w, skip as u32, cdf); + } + + pub fn get_segment_pred( + &self, bo: TileBlockOffset, last_active_segid: u8, + ) -> (u8, u8) { + let mut prev_ul = -1; + let mut prev_u = -1; + let mut prev_l = -1; + if bo.0.x > 0 && bo.0.y > 0 { + prev_ul = self.bc.blocks.above_left_of(bo).segmentation_idx as i8; + } + if bo.0.y > 0 { + prev_u = self.bc.blocks.above_of(bo).segmentation_idx as i8; + } + if bo.0.x > 0 { + prev_l = self.bc.blocks.left_of(bo).segmentation_idx as i8; + } + + /* Pick CDF index based on number of matching/out-of-bounds segment IDs. */ + let cdf_index: u8; + if prev_ul < 0 || prev_u < 0 || prev_l < 0 { + /* Edge case */ + cdf_index = 0; + } else if (prev_ul == prev_u) && (prev_ul == prev_l) { + cdf_index = 2; + } else if (prev_ul == prev_u) || (prev_ul == prev_l) || (prev_u == prev_l) + { + cdf_index = 1; + } else { + cdf_index = 0; + } + + /* If 2 or more are identical returns that as predictor, otherwise prev_l. */ + let r: i8; + if prev_u == -1 { + /* edge case */ + r = if prev_l == -1 { 0 } else { prev_l }; + } else if prev_l == -1 { + /* edge case */ + r = prev_u; + } else { + r = if prev_ul == prev_u { prev_u } else { prev_l }; + } + + ((r as u8).min(last_active_segid), cdf_index) + } + + pub fn write_cfl_alphas(&mut self, w: &mut W, cfl: CFLParams) { + symbol_with_update!(self, w, cfl.joint_sign(), &self.fc.cfl_sign_cdf); + for uv in 0..2 { + if cfl.sign[uv] != CFL_SIGN_ZERO { + symbol_with_update!( + self, + w, + cfl.index(uv), + &self.fc.cfl_alpha_cdf[cfl.context(uv)] + ); + } + } + } + + /// # Panics + /// + /// - If called with an 8x8 or larger `bsize` + /// - If called with a `PartitionType` incompatible with the current block. + pub fn write_partition( + &mut self, w: &mut impl Writer, bo: TileBlockOffset, p: PartitionType, + bsize: BlockSize, + ) { + debug_assert!(bsize.is_sqr()); + assert!(bsize >= BlockSize::BLOCK_8X8); + let hbs = bsize.width_mi() / 2; + let has_cols = (bo.0.x + hbs) < self.bc.blocks.cols(); + let has_rows = (bo.0.y + hbs) < self.bc.blocks.rows(); + let ctx = self.bc.partition_plane_context(bo, bsize); + assert!(ctx < PARTITION_CONTEXTS); + + if !has_rows && !has_cols { + return; + } + + if has_rows && has_cols { + if ctx < PARTITION_TYPES { + let cdf = &self.fc.partition_w8_cdf[ctx]; + symbol_with_update!(self, w, p as u32, cdf); + } else if ctx < 4 * PARTITION_TYPES { + let cdf = &self.fc.partition_cdf[ctx - PARTITION_TYPES]; + symbol_with_update!(self, w, p as u32, cdf); + } else { + let cdf = &self.fc.partition_w128_cdf[ctx - 4 * PARTITION_TYPES]; + symbol_with_update!(self, w, p as u32, cdf); + } + } else if !has_rows && has_cols { + assert!( + p == PartitionType::PARTITION_SPLIT + || p == PartitionType::PARTITION_HORZ + ); + assert!(bsize > BlockSize::BLOCK_8X8); + let mut cdf = [0u16; 2]; + if ctx < PARTITION_TYPES { + let partition_cdf = &self.fc.partition_w8_cdf[ctx]; + ContextWriter::partition_gather_vert_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } else if ctx < 4 * PARTITION_TYPES { + let partition_cdf = &self.fc.partition_cdf[ctx - PARTITION_TYPES]; + ContextWriter::partition_gather_vert_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } else { + let partition_cdf = + &self.fc.partition_w128_cdf[ctx - 4 * PARTITION_TYPES]; + ContextWriter::partition_gather_vert_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } + w.symbol((p == PartitionType::PARTITION_SPLIT) as u32, &cdf); + } else { + assert!( + p == PartitionType::PARTITION_SPLIT + || p == PartitionType::PARTITION_VERT + ); + assert!(bsize > BlockSize::BLOCK_8X8); + let mut cdf = [0u16; 2]; + if ctx < PARTITION_TYPES { + let partition_cdf = &self.fc.partition_w8_cdf[ctx]; + ContextWriter::partition_gather_horz_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } else if ctx < 4 * PARTITION_TYPES { + let partition_cdf = &self.fc.partition_cdf[ctx - PARTITION_TYPES]; + ContextWriter::partition_gather_horz_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } else { + let partition_cdf = + &self.fc.partition_w128_cdf[ctx - 4 * PARTITION_TYPES]; + ContextWriter::partition_gather_horz_alike( + &mut cdf, + partition_cdf, + bsize, + ); + } + w.symbol((p == PartitionType::PARTITION_SPLIT) as u32, &cdf); + } + } + + fn neg_interleave(x: i32, r: i32, max: i32) -> i32 { + assert!(x < max); + if r == 0 { + return x; + } else if r >= (max - 1) { + return -x + max - 1; + } + let diff = x - r; + if 2 * r < max { + if diff.abs() <= r { + if diff > 0 { + return (diff << 1) - 1; + } else { + return (-diff) << 1; + } + } + x + } else { + if diff.abs() < (max - r) { + if diff > 0 { + return (diff << 1) - 1; + } else { + return (-diff) << 1; + } + } + (max - x) - 1 + } + } + + pub fn write_segmentation( + &mut self, w: &mut W, bo: TileBlockOffset, bsize: BlockSize, skip: bool, + last_active_segid: u8, + ) { + let (pred, cdf_index) = self.get_segment_pred(bo, last_active_segid); + if skip { + self.bc.blocks.set_segmentation_idx(bo, bsize, pred); + return; + } + let seg_idx = self.bc.blocks[bo].segmentation_idx; + let coded_id = Self::neg_interleave( + seg_idx as i32, + pred as i32, + (last_active_segid + 1) as i32, + ); + symbol_with_update!( + self, + w, + coded_id as u32, + &self.fc.spatial_segmentation_cdfs[cdf_index as usize] + ); + } +} + +impl BlockContext<'_> { + /// # Panics + /// + /// - If called with a non-square `bsize` + pub fn partition_plane_context( + &self, bo: TileBlockOffset, bsize: BlockSize, + ) -> usize { + // TODO: this should be way simpler without sub8x8 + let above_ctx = self.above_partition_context[bo.0.x >> 1]; + let left_ctx = self.left_partition_context[bo.y_in_sb() >> 1]; + let bsl = bsize.width_log2() - BLOCK_8X8.width_log2(); + let above = (above_ctx >> bsl) & 1; + let left = (left_ctx >> bsl) & 1; + + assert!(bsize.is_sqr()); + + (left * 2 + above) as usize + bsl * PARTITION_PLOFFSET + } + + /// # Panics + /// + /// - If the block size is invalid for subsampling + pub fn reset_skip_context( + &mut self, bo: TileBlockOffset, bsize: BlockSize, xdec: usize, + ydec: usize, cs: ChromaSampling, + ) { + let num_planes = if cs == ChromaSampling::Cs400 { 1 } else { 3 }; + let nplanes = if bsize >= BLOCK_8X8 { + num_planes + } else { + 1 + (num_planes - 1) * has_chroma(bo, bsize, xdec, ydec, cs) as usize + }; + + for plane in 0..nplanes { + let xdec2 = if plane == 0 { 0 } else { xdec }; + let ydec2 = if plane == 0 { 0 } else { ydec }; + + let plane_bsize = if plane == 0 { + bsize + } else { + bsize.subsampled_size(xdec2, ydec2).unwrap() + }; + let bw = plane_bsize.width_mi(); + let bh = plane_bsize.height_mi(); + + for above in + &mut self.above_coeff_context[plane][(bo.0.x >> xdec2)..][..bw] + { + *above = 0; + } + + let bo_y = bo.y_in_sb(); + for left in &mut self.left_coeff_context[plane][(bo_y >> ydec2)..][..bh] + { + *left = 0; + } + } + } + + pub fn skip_context(&self, bo: TileBlockOffset) -> usize { + let above_skip = bo.0.y > 0 && self.blocks.above_of(bo).skip; + let left_skip = bo.0.x > 0 && self.blocks.left_of(bo).skip; + above_skip as usize + left_skip as usize + } + + /// # Panics + /// + /// - If called with a non-square `bsize` + pub fn update_partition_context( + &mut self, bo: TileBlockOffset, subsize: BlockSize, bsize: BlockSize, + ) { + assert!(bsize.is_sqr()); + + let bw = bsize.width_mi(); + let bh = bsize.height_mi(); + + let above_ctx = + &mut self.above_partition_context[bo.0.x >> 1..(bo.0.x + bw) >> 1]; + let left_ctx = &mut self.left_partition_context + [bo.y_in_sb() >> 1..(bo.y_in_sb() + bh) >> 1]; + + // update the partition context at the end notes. set partition bits + // of block sizes larger than the current one to be one, and partition + // bits of smaller block sizes to be zero. + for above in &mut above_ctx[..bw >> 1] { + *above = partition_context_lookup[subsize as usize][0]; + } + + for left in &mut left_ctx[..bh >> 1] { + *left = partition_context_lookup[subsize as usize][1]; + } + } +} + +#[cfg(test)] +mod test { + #[test] + fn cdf_map() { + use super::*; + + let cdf = CDFContext::new(8); + let cdf_map = FieldMap { map: cdf.build_map() }; + let f = &cdf.partition_cdf[2]; + cdf_map.lookup(f.as_ptr() as usize); + } + + use super::CFLSign; + use super::CFLSign::*; + + static cfl_alpha_signs: [[CFLSign; 2]; 8] = [ + [CFL_SIGN_ZERO, CFL_SIGN_NEG], + [CFL_SIGN_ZERO, CFL_SIGN_POS], + [CFL_SIGN_NEG, CFL_SIGN_ZERO], + [CFL_SIGN_NEG, CFL_SIGN_NEG], + [CFL_SIGN_NEG, CFL_SIGN_POS], + [CFL_SIGN_POS, CFL_SIGN_ZERO], + [CFL_SIGN_POS, CFL_SIGN_NEG], + [CFL_SIGN_POS, CFL_SIGN_POS], + ]; + + static cfl_context: [[usize; 8]; 2] = + [[0, 0, 0, 1, 2, 3, 4, 5], [0, 3, 0, 1, 4, 0, 2, 5]]; + + #[test] + fn cfl_joint_sign() { + use super::*; + + let mut cfl = CFLParams::default(); + for (joint_sign, &signs) in cfl_alpha_signs.iter().enumerate() { + cfl.sign = signs; + assert!(cfl.joint_sign() as usize == joint_sign); + for uv in 0..2 { + if signs[uv] != CFL_SIGN_ZERO { + assert!(cfl.context(uv) == cfl_context[uv][joint_sign]); + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/superblock_unit.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/superblock_unit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/superblock_unit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/superblock_unit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,127 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +pub const MAX_SB_SIZE_LOG2: usize = 7; +const SB_SIZE_LOG2: usize = 6; +pub const SB_SIZE: usize = 1 << SB_SIZE_LOG2; +const SB_SQUARE: usize = SB_SIZE * SB_SIZE; + +pub const MI_SIZE_LOG2: usize = 2; +pub const MI_SIZE: usize = 1 << MI_SIZE_LOG2; +pub const MAX_MIB_SIZE_LOG2: usize = MAX_SB_SIZE_LOG2 - MI_SIZE_LOG2; +pub const MIB_SIZE_LOG2: usize = SB_SIZE_LOG2 - MI_SIZE_LOG2; +pub const MIB_SIZE: usize = 1 << MIB_SIZE_LOG2; +pub const MIB_MASK: usize = MIB_SIZE - 1; + +pub const SUPERBLOCK_TO_PLANE_SHIFT: usize = SB_SIZE_LOG2; +pub const SUPERBLOCK_TO_BLOCK_SHIFT: usize = MIB_SIZE_LOG2; +pub const BLOCK_TO_PLANE_SHIFT: usize = MI_SIZE_LOG2; +pub const IMPORTANCE_BLOCK_TO_BLOCK_SHIFT: usize = 1; +pub const LOCAL_BLOCK_MASK: usize = (1 << SUPERBLOCK_TO_BLOCK_SHIFT) - 1; + +pub const MAX_SB_IN_IMP_B: usize = 1 + << (MAX_SB_SIZE_LOG2 + - IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + - BLOCK_TO_PLANE_SHIFT); + +/// Absolute offset in superblocks, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SuperBlockOffset { + pub x: usize, + pub y: usize, +} + +/// Absolute offset in superblocks inside a plane, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PlaneSuperBlockOffset(pub SuperBlockOffset); + +/// Absolute offset in superblocks inside a tile, where a superblock is defined +/// to be an `N*N` square where `N == (1 << SUPERBLOCK_TO_PLANE_SHIFT)`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TileSuperBlockOffset(pub SuperBlockOffset); + +impl SuperBlockOffset { + /// Offset of a block inside the current superblock. + #[inline] + const fn block_offset(self, block_x: usize, block_y: usize) -> BlockOffset { + BlockOffset { + x: (self.x << SUPERBLOCK_TO_BLOCK_SHIFT) + block_x, + y: (self.y << SUPERBLOCK_TO_BLOCK_SHIFT) + block_y, + } + } + + /// Offset of the top-left pixel of this block. + #[inline] + const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + PlaneOffset { + x: (self.x as isize) << (SUPERBLOCK_TO_PLANE_SHIFT - plane.xdec), + y: (self.y as isize) << (SUPERBLOCK_TO_PLANE_SHIFT - plane.ydec), + } + } +} + +impl Add for SuperBlockOffset { + type Output = Self; + #[inline] + fn add(self, rhs: Self) -> Self::Output { + Self { x: self.x + rhs.x, y: self.y + rhs.y } + } +} + +impl PlaneSuperBlockOffset { + /// Offset of a block inside the current superblock. + #[inline] + pub const fn block_offset( + self, block_x: usize, block_y: usize, + ) -> PlaneBlockOffset { + PlaneBlockOffset(self.0.block_offset(block_x, block_y)) + } + + /// Offset of the top-left pixel of this block. + #[inline] + pub const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + self.0.plane_offset(plane) + } +} + +impl Add for PlaneSuperBlockOffset { + type Output = Self; + #[inline] + fn add(self, rhs: Self) -> Self::Output { + PlaneSuperBlockOffset(self.0 + rhs.0) + } +} + +impl TileSuperBlockOffset { + /// Offset of a block inside the current superblock. + #[inline] + pub const fn block_offset( + self, block_x: usize, block_y: usize, + ) -> TileBlockOffset { + TileBlockOffset(self.0.block_offset(block_x, block_y)) + } + + /// Offset of the top-left pixel of this block. + #[inline] + pub const fn plane_offset(self, plane: &PlaneConfig) -> PlaneOffset { + self.0.plane_offset(plane) + } +} + +impl Add for TileSuperBlockOffset { + type Output = Self; + #[inline] + fn add(self, rhs: Self) -> Self::Output { + TileSuperBlockOffset(self.0 + rhs.0) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/transform_unit.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/transform_unit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/context/transform_unit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/context/transform_unit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,986 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; +use crate::predict::PredictionMode; +use crate::predict::PredictionMode::*; +use crate::transform::TxType::*; +use std::mem::MaybeUninit; + +pub const MAX_TX_SIZE: usize = 64; + +pub const MAX_CODED_TX_SIZE: usize = 32; +pub const MAX_CODED_TX_SQUARE: usize = MAX_CODED_TX_SIZE * MAX_CODED_TX_SIZE; + +pub const TX_SIZE_SQR_CONTEXTS: usize = 4; // Coded tx_size <= 32x32, so is the # of CDF contexts from tx sizes + +pub const TX_SETS: usize = 6; +pub const TX_SETS_INTRA: usize = 3; +pub const TX_SETS_INTER: usize = 4; + +pub const INTRA_MODES: usize = 13; +pub const UV_INTRA_MODES: usize = 14; + +const MAX_VARTX_DEPTH: usize = 2; + +pub const TXFM_PARTITION_CONTEXTS: usize = + (TxSize::TX_SIZES - TxSize::TX_8X8 as usize) * 6 - 3; + +// Number of transform types in each set type +pub static num_tx_set: [usize; TX_SETS] = [1, 2, 5, 7, 12, 16]; +pub static av1_tx_used: [[usize; TX_TYPES]; TX_SETS] = [ + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], +]; + +// Maps set types above to the indices used for intra +static tx_set_index_intra: [i8; TX_SETS] = [0, -1, 2, 1, -1, -1]; +// Maps set types above to the indices used for inter +static tx_set_index_inter: [i8; TX_SETS] = [0, 3, -1, -1, 2, 1]; + +pub static av1_tx_ind: [[usize; TX_TYPES]; TX_SETS] = [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 3, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 5, 6, 4, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0], + [3, 4, 5, 8, 6, 7, 9, 10, 11, 0, 1, 2, 0, 0, 0, 0], + [7, 8, 9, 12, 10, 11, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6], +]; + +pub static max_txsize_rect_lookup: [TxSize; BlockSize::BLOCK_SIZES_ALL] = [ + TX_4X4, // 4x4 + TX_4X8, // 4x8 + TX_8X4, // 8x4 + TX_8X8, // 8x8 + TX_8X16, // 8x16 + TX_16X8, // 16x8 + TX_16X16, // 16x16 + TX_16X32, // 16x32 + TX_32X16, // 32x16 + TX_32X32, // 32x32 + TX_32X64, // 32x64 + TX_64X32, // 64x32 + TX_64X64, // 64x64 + TX_64X64, // 64x128 + TX_64X64, // 128x64 + TX_64X64, // 128x128 + TX_4X16, // 4x16 + TX_16X4, // 16x4 + TX_8X32, // 8x32 + TX_32X8, // 32x8 + TX_16X64, // 16x64 + TX_64X16, // 64x16 +]; + +pub static sub_tx_size_map: [TxSize; TxSize::TX_SIZES_ALL] = [ + TX_4X4, // TX_4X4 + TX_4X4, // TX_8X8 + TX_8X8, // TX_16X16 + TX_16X16, // TX_32X32 + TX_32X32, // TX_64X64 + TX_4X4, // TX_4X8 + TX_4X4, // TX_8X4 + TX_8X8, // TX_8X16 + TX_8X8, // TX_16X8 + TX_16X16, // TX_16X32 + TX_16X16, // TX_32X16 + TX_32X32, // TX_32X64 + TX_32X32, // TX_64X32 + TX_4X8, // TX_4X16 + TX_8X4, // TX_16X4 + TX_8X16, // TX_8X32 + TX_16X8, // TX_32X8 + TX_16X32, // TX_16X64 + TX_32X16, // TX_64X16 +]; + +#[inline] +pub fn has_chroma( + bo: TileBlockOffset, bsize: BlockSize, subsampling_x: usize, + subsampling_y: usize, chroma_sampling: ChromaSampling, +) -> bool { + if chroma_sampling == ChromaSampling::Cs400 { + return false; + }; + + let bw = bsize.width_mi(); + let bh = bsize.height_mi(); + + ((bo.0.x & 0x01) == 1 || (bw & 0x01) == 0 || subsampling_x == 0) + && ((bo.0.y & 0x01) == 1 || (bh & 0x01) == 0 || subsampling_y == 0) +} + +pub fn get_tx_set( + tx_size: TxSize, is_inter: bool, use_reduced_set: bool, +) -> TxSet { + let tx_size_sqr_up = tx_size.sqr_up(); + let tx_size_sqr = tx_size.sqr(); + + if tx_size_sqr_up.block_size() > BlockSize::BLOCK_32X32 { + return TxSet::TX_SET_DCTONLY; + } + + if is_inter { + if use_reduced_set || tx_size_sqr_up == TxSize::TX_32X32 { + TxSet::TX_SET_INTER_3 + } else if tx_size_sqr == TxSize::TX_16X16 { + TxSet::TX_SET_INTER_2 + } else { + TxSet::TX_SET_INTER_1 + } + } else if tx_size_sqr_up == TxSize::TX_32X32 { + TxSet::TX_SET_DCTONLY + } else if use_reduced_set || tx_size_sqr == TxSize::TX_16X16 { + TxSet::TX_SET_INTRA_2 + } else { + TxSet::TX_SET_INTRA_1 + } +} + +pub fn get_tx_set_index( + tx_size: TxSize, is_inter: bool, use_reduced_set: bool, +) -> i8 { + let set_type = get_tx_set(tx_size, is_inter, use_reduced_set); + + if is_inter { + tx_set_index_inter[set_type as usize] + } else { + tx_set_index_intra[set_type as usize] + } +} + +static intra_mode_to_tx_type_context: [TxType; INTRA_MODES] = [ + DCT_DCT, // DC + ADST_DCT, // V + DCT_ADST, // H + DCT_DCT, // D45 + ADST_ADST, // D135 + ADST_DCT, // D113 + DCT_ADST, // D157 + DCT_ADST, // D203 + ADST_DCT, // D67 + ADST_ADST, // SMOOTH + ADST_DCT, // SMOOTH_V + DCT_ADST, // SMOOTH_H + ADST_ADST, // PAETH +]; + +static uv2y: [PredictionMode; UV_INTRA_MODES] = [ + DC_PRED, // UV_DC_PRED + V_PRED, // UV_V_PRED + H_PRED, // UV_H_PRED + D45_PRED, // UV_D45_PRED + D135_PRED, // UV_D135_PRED + D113_PRED, // UV_D113_PRED + D157_PRED, // UV_D157_PRED + D203_PRED, // UV_D203_PRED + D67_PRED, // UV_D67_PRED + SMOOTH_PRED, // UV_SMOOTH_PRED + SMOOTH_V_PRED, // UV_SMOOTH_V_PRED + SMOOTH_H_PRED, // UV_SMOOTH_H_PRED + PAETH_PRED, // UV_PAETH_PRED + DC_PRED, // CFL_PRED +]; + +pub fn uv_intra_mode_to_tx_type_context(pred: PredictionMode) -> TxType { + intra_mode_to_tx_type_context[uv2y[pred as usize] as usize] +} + +// Level Map +pub const TXB_SKIP_CONTEXTS: usize = 13; + +pub const EOB_COEF_CONTEXTS: usize = 9; + +const SIG_COEF_CONTEXTS_2D: usize = 26; +const SIG_COEF_CONTEXTS_1D: usize = 16; +pub const SIG_COEF_CONTEXTS_EOB: usize = 4; +pub const SIG_COEF_CONTEXTS: usize = + SIG_COEF_CONTEXTS_2D + SIG_COEF_CONTEXTS_1D; + +const COEFF_BASE_CONTEXTS: usize = SIG_COEF_CONTEXTS; +pub const DC_SIGN_CONTEXTS: usize = 3; + +const BR_TMP_OFFSET: usize = 12; +const BR_REF_CAT: usize = 4; +pub const LEVEL_CONTEXTS: usize = 21; + +pub const NUM_BASE_LEVELS: usize = 2; + +pub const BR_CDF_SIZE: usize = 4; +pub const COEFF_BASE_RANGE: usize = 4 * (BR_CDF_SIZE - 1); + +pub const COEFF_CONTEXT_BITS: usize = 6; +pub const COEFF_CONTEXT_MASK: usize = (1 << COEFF_CONTEXT_BITS) - 1; +const MAX_BASE_BR_RANGE: usize = COEFF_BASE_RANGE + NUM_BASE_LEVELS + 1; + +const BASE_CONTEXT_POSITION_NUM: usize = 12; + +// Pad 4 extra columns to remove horizontal availability check. +pub const TX_PAD_HOR_LOG2: usize = 2; +pub const TX_PAD_HOR: usize = 4; +// Pad 6 extra rows (2 on top and 4 on bottom) to remove vertical availability +// check. +pub const TX_PAD_TOP: usize = 2; +pub const TX_PAD_BOTTOM: usize = 4; +pub const TX_PAD_VER: usize = TX_PAD_TOP + TX_PAD_BOTTOM; +// Pad 16 extra bytes to avoid reading overflow in SIMD optimization. +const TX_PAD_END: usize = 16; +pub const TX_PAD_2D: usize = (MAX_CODED_TX_SIZE + TX_PAD_HOR) + * (MAX_CODED_TX_SIZE + TX_PAD_VER) + + TX_PAD_END; + +const TX_CLASSES: usize = 3; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum TxClass { + TX_CLASS_2D = 0, + TX_CLASS_HORIZ = 1, + TX_CLASS_VERT = 2, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum SegLvl { + SEG_LVL_ALT_Q = 0, /* Use alternate Quantizer .... */ + SEG_LVL_ALT_LF_Y_V = 1, /* Use alternate loop filter value on y plane vertical */ + SEG_LVL_ALT_LF_Y_H = 2, /* Use alternate loop filter value on y plane horizontal */ + SEG_LVL_ALT_LF_U = 3, /* Use alternate loop filter value on u plane */ + SEG_LVL_ALT_LF_V = 4, /* Use alternate loop filter value on v plane */ + SEG_LVL_REF_FRAME = 5, /* Optional Segment reference frame */ + SEG_LVL_SKIP = 6, /* Optional Segment (0,0) + skip mode */ + SEG_LVL_GLOBALMV = 7, + SEG_LVL_MAX = 8, +} + +pub const seg_feature_bits: [u32; SegLvl::SEG_LVL_MAX as usize] = + [8, 6, 6, 6, 6, 3, 0, 0]; + +pub const seg_feature_is_signed: [bool; SegLvl::SEG_LVL_MAX as usize] = + [true, true, true, true, true, false, false, false]; + +use crate::context::TxClass::*; + +pub static tx_type_to_class: [TxClass; TX_TYPES] = [ + TX_CLASS_2D, // DCT_DCT + TX_CLASS_2D, // ADST_DCT + TX_CLASS_2D, // DCT_ADST + TX_CLASS_2D, // ADST_ADST + TX_CLASS_2D, // FLIPADST_DCT + TX_CLASS_2D, // DCT_FLIPADST + TX_CLASS_2D, // FLIPADST_FLIPADST + TX_CLASS_2D, // ADST_FLIPADST + TX_CLASS_2D, // FLIPADST_ADST + TX_CLASS_2D, // IDTX + TX_CLASS_VERT, // V_DCT + TX_CLASS_HORIZ, // H_DCT + TX_CLASS_VERT, // V_ADST + TX_CLASS_HORIZ, // H_ADST + TX_CLASS_VERT, // V_FLIPADST + TX_CLASS_HORIZ, // H_FLIPADST +]; + +pub static eob_to_pos_small: [u8; 33] = [ + 0, 1, 2, // 0-2 + 3, 3, // 3-4 + 4, 4, 4, 4, // 5-8 + 5, 5, 5, 5, 5, 5, 5, 5, // 9-16 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 17-32 +]; + +pub static eob_to_pos_large: [u8; 17] = [ + 6, // place holder + 7, // 33-64 + 8, 8, // 65-128 + 9, 9, 9, 9, // 129-256 + 10, 10, 10, 10, 10, 10, 10, 10, // 257-512 + 11, // 513- +]; + +pub static k_eob_group_start: [u16; 12] = + [0, 1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513]; +pub static k_eob_offset_bits: [u16; 12] = [0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + +// The ctx offset table when TX is TX_CLASS_2D. +// TX col and row indices are clamped to 4 + +#[rustfmt::skip] +pub static av1_nz_map_ctx_offset: [[[i8; 5]; 5]; TxSize::TX_SIZES_ALL] = [ + // TX_4X4 + [ + [ 0, 1, 6, 6, 0], + [ 1, 6, 6, 21, 0], + [ 6, 6, 21, 21, 0], + [ 6, 21, 21, 21, 0], + [ 0, 0, 0, 0, 0] + ], + // TX_8X8 + [ + [ 0, 1, 6, 6, 21], + [ 1, 6, 6, 21, 21], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_16X16 + [ + [ 0, 1, 6, 6, 21], + [ 1, 6, 6, 21, 21], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_32X32 + [ + [ 0, 1, 6, 6, 21], + [ 1, 6, 6, 21, 21], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_64X64 + [ + [ 0, 1, 6, 6, 21], + [ 1, 6, 6, 21, 21], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_4X8 + [ + [ 0, 11, 11, 11, 0], + [11, 11, 11, 11, 0], + [ 6, 6, 21, 21, 0], + [ 6, 21, 21, 21, 0], + [21, 21, 21, 21, 0] + ], + // TX_8X4 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [ 0, 0, 0, 0, 0] + ], + // TX_8X16 + [ + [ 0, 11, 11, 11, 11], + [11, 11, 11, 11, 11], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_16X8 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21] + ], + // TX_16X32 + [ + [ 0, 11, 11, 11, 11], + [11, 11, 11, 11, 11], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_32X16 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21] + ], + // TX_32X64 + [ + [ 0, 11, 11, 11, 11], + [11, 11, 11, 11, 11], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_64X32 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21] + ], + // TX_4X16 + [ + [ 0, 11, 11, 11, 0], + [11, 11, 11, 11, 0], + [ 6, 6, 21, 21, 0], + [ 6, 21, 21, 21, 0], + [21, 21, 21, 21, 0] + ], + // TX_16X4 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [ 0, 0, 0, 0, 0] + ], + // TX_8X32 + [ + [ 0, 11, 11, 11, 11], + [11, 11, 11, 11, 11], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_32X8 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21] + ], + // TX_16X64 + [ + [ 0, 11, 11, 11, 11], + [11, 11, 11, 11, 11], + [ 6, 6, 21, 21, 21], + [ 6, 21, 21, 21, 21], + [21, 21, 21, 21, 21] + ], + // TX_64X16 + [ + [ 0, 16, 6, 6, 21], + [16, 16, 6, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21], + [16, 16, 21, 21, 21] + ] +]; + +const NZ_MAP_CTX_0: usize = SIG_COEF_CONTEXTS_2D; +const NZ_MAP_CTX_5: usize = NZ_MAP_CTX_0 + 5; +const NZ_MAP_CTX_10: usize = NZ_MAP_CTX_0 + 10; + +pub static nz_map_ctx_offset_1d: [usize; 32] = [ + NZ_MAP_CTX_0, + NZ_MAP_CTX_5, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, + NZ_MAP_CTX_10, +]; + +const CONTEXT_MAG_POSITION_NUM: usize = 3; + +static mag_ref_offset_with_txclass: [[[usize; 2]; CONTEXT_MAG_POSITION_NUM]; + 3] = [ + [[0, 1], [1, 0], [1, 1]], + [[0, 1], [1, 0], [0, 2]], + [[0, 1], [1, 0], [2, 0]], +]; + +// End of Level Map + +pub struct TXB_CTX { + pub txb_skip_ctx: usize, + pub dc_sign_ctx: usize, +} + +impl ContextWriter<'_> { + /// # Panics + /// + /// - If an invalid combination of `tx_type` and `tx_size` is passed + pub fn write_tx_type( + &mut self, w: &mut W, tx_size: TxSize, tx_type: TxType, + y_mode: PredictionMode, is_inter: bool, use_reduced_tx_set: bool, + ) { + let square_tx_size = tx_size.sqr(); + let tx_set = get_tx_set(tx_size, is_inter, use_reduced_tx_set); + let num_tx_types = num_tx_set[tx_set as usize]; + + if num_tx_types > 1 { + let tx_set_index = + get_tx_set_index(tx_size, is_inter, use_reduced_tx_set); + assert!(tx_set_index > 0); + assert!(av1_tx_used[tx_set as usize][tx_type as usize] != 0); + + if is_inter { + let s = av1_tx_ind[tx_set as usize][tx_type as usize] as u32; + if tx_set_index == 1 { + let cdf = &self.fc.inter_tx_1_cdf[square_tx_size as usize]; + symbol_with_update!(self, w, s, cdf); + } else if tx_set_index == 2 { + let cdf = &self.fc.inter_tx_2_cdf[square_tx_size as usize]; + symbol_with_update!(self, w, s, cdf); + } else { + let cdf = &self.fc.inter_tx_3_cdf[square_tx_size as usize]; + symbol_with_update!(self, w, s, cdf); + } + } else { + let intra_dir = y_mode; + // TODO: Once use_filter_intra is enabled, + // intra_dir = + // fimode_to_intradir[mbmi->filter_intra_mode_info.filter_intra_mode]; + + let s = av1_tx_ind[tx_set as usize][tx_type as usize] as u32; + if tx_set_index == 1 { + let cdf = &self.fc.intra_tx_1_cdf[square_tx_size as usize] + [intra_dir as usize]; + symbol_with_update!(self, w, s, cdf); + } else { + let cdf = &self.fc.intra_tx_2_cdf[square_tx_size as usize] + [intra_dir as usize]; + symbol_with_update!(self, w, s, cdf); + } + } + } + } + + fn get_tx_size_context( + &self, bo: TileBlockOffset, bsize: BlockSize, + ) -> usize { + let max_tx_size = max_txsize_rect_lookup[bsize as usize]; + let max_tx_wide = max_tx_size.width() as u8; + let max_tx_high = max_tx_size.height() as u8; + let has_above = bo.0.y > 0; + let has_left = bo.0.x > 0; + let mut above = self.bc.above_tx_context[bo.0.x] >= max_tx_wide; + let mut left = self.bc.left_tx_context[bo.y_in_sb()] >= max_tx_high; + + if has_above { + let above_blk = self.bc.blocks.above_of(bo); + if above_blk.is_inter() { + above = (above_blk.n4_w << MI_SIZE_LOG2) >= max_tx_wide; + }; + } + if has_left { + let left_blk = self.bc.blocks.left_of(bo); + if left_blk.is_inter() { + left = (left_blk.n4_h << MI_SIZE_LOG2) >= max_tx_high; + }; + } + if has_above && has_left { + return above as usize + left as usize; + }; + if has_above { + return above as usize; + }; + if has_left { + return left as usize; + }; + 0 + } + + pub fn write_tx_size_intra( + &mut self, w: &mut W, bo: TileBlockOffset, bsize: BlockSize, + tx_size: TxSize, + ) { + fn tx_size_to_depth(tx_size: TxSize, bsize: BlockSize) -> usize { + let mut ctx_size = max_txsize_rect_lookup[bsize as usize]; + let mut depth: usize = 0; + while tx_size != ctx_size { + depth += 1; + ctx_size = sub_tx_size_map[ctx_size as usize]; + debug_assert!(depth <= MAX_TX_DEPTH); + } + depth + } + fn bsize_to_max_depth(bsize: BlockSize) -> usize { + let mut tx_size: TxSize = max_txsize_rect_lookup[bsize as usize]; + let mut depth = 0; + while depth < MAX_TX_DEPTH && tx_size != TX_4X4 { + depth += 1; + tx_size = sub_tx_size_map[tx_size as usize]; + debug_assert!(depth <= MAX_TX_DEPTH); + } + depth + } + fn bsize_to_tx_size_cat(bsize: BlockSize) -> usize { + let mut tx_size: TxSize = max_txsize_rect_lookup[bsize as usize]; + debug_assert!(tx_size != TX_4X4); + let mut depth = 0; + while tx_size != TX_4X4 { + depth += 1; + tx_size = sub_tx_size_map[tx_size as usize]; + } + debug_assert!(depth <= MAX_TX_CATS); + + depth - 1 + } + + debug_assert!(!self.bc.blocks[bo].is_inter()); + debug_assert!(bsize > BlockSize::BLOCK_4X4); + + let tx_size_ctx = self.get_tx_size_context(bo, bsize); + let depth = tx_size_to_depth(tx_size, bsize); + + let max_depths = bsize_to_max_depth(bsize); + let tx_size_cat = bsize_to_tx_size_cat(bsize); + + debug_assert!(depth <= max_depths); + debug_assert!(!tx_size.is_rect() || bsize.is_rect_tx_allowed()); + + if tx_size_cat > 0 { + let cdf = &self.fc.tx_size_cdf[tx_size_cat - 1][tx_size_ctx]; + symbol_with_update!(self, w, depth as u32, cdf); + } else { + let cdf = &self.fc.tx_size_8x8_cdf[tx_size_ctx]; + symbol_with_update!(self, w, depth as u32, cdf); + } + } + + // Based on https://aomediacodec.github.io/av1-spec/#cdf-selection-process + // Used to decide the cdf (context) for txfm_split + fn get_above_tx_width( + &self, bo: TileBlockOffset, _bsize: BlockSize, _tx_size: TxSize, + first_tx: bool, + ) -> usize { + let has_above = bo.0.y > 0; + if first_tx { + if !has_above { + return 64; + } + let above_blk = self.bc.blocks.above_of(bo); + if above_blk.skip && above_blk.is_inter() { + return above_blk.bsize.width(); + } + } + self.bc.above_tx_context[bo.0.x] as usize + } + + fn get_left_tx_height( + &self, bo: TileBlockOffset, _bsize: BlockSize, _tx_size: TxSize, + first_tx: bool, + ) -> usize { + let has_left = bo.0.x > 0; + if first_tx { + if !has_left { + return 64; + } + let left_blk = self.bc.blocks.left_of(bo); + if left_blk.skip && left_blk.is_inter() { + return left_blk.bsize.height(); + } + } + self.bc.left_tx_context[bo.y_in_sb()] as usize + } + + fn txfm_partition_context( + &self, bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize, tbx: usize, + tby: usize, + ) -> usize { + debug_assert!(tx_size > TX_4X4); + debug_assert!(bsize > BlockSize::BLOCK_4X4); + + // TODO: from 2nd level partition, must know whether the tx block is the topmost(or leftmost) within a partition + let above = (self.get_above_tx_width(bo, bsize, tx_size, tby == 0) + < tx_size.width()) as usize; + let left = (self.get_left_tx_height(bo, bsize, tx_size, tbx == 0) + < tx_size.height()) as usize; + + let max_tx_size: TxSize = bsize.tx_size().sqr_up(); + let category: usize = (tx_size.sqr_up() != max_tx_size) as usize + + (TxSize::TX_SIZES - 1 - max_tx_size as usize) * 2; + + debug_assert!(category < TXFM_PARTITION_CONTEXTS); + + category * 3 + above + left + } + + pub fn write_tx_size_inter( + &mut self, w: &mut W, bo: TileBlockOffset, bsize: BlockSize, + tx_size: TxSize, txfm_split: bool, tbx: usize, tby: usize, depth: usize, + ) { + if bo.0.x >= self.bc.blocks.cols() || bo.0.y >= self.bc.blocks.rows() { + return; + } + debug_assert!(self.bc.blocks[bo].is_inter()); + debug_assert!(bsize > BlockSize::BLOCK_4X4); + debug_assert!(!tx_size.is_rect() || bsize.is_rect_tx_allowed()); + + if tx_size != TX_4X4 && depth < MAX_VARTX_DEPTH { + let ctx = self.txfm_partition_context(bo, bsize, tx_size, tbx, tby); + let cdf = &self.fc.txfm_partition_cdf[ctx]; + symbol_with_update!(self, w, txfm_split as u32, cdf); + } else { + debug_assert!(!txfm_split); + } + + if !txfm_split { + self.bc.update_tx_size_context(bo, tx_size.block_size(), tx_size, false); + } else { + // if txfm_split == true, split one level only + let split_tx_size = sub_tx_size_map[tx_size as usize]; + let bw = bsize.width_mi() / split_tx_size.width_mi(); + let bh = bsize.height_mi() / split_tx_size.height_mi(); + + for by in 0..bh { + for bx in 0..bw { + let tx_bo = TileBlockOffset(BlockOffset { + x: bo.0.x + bx * split_tx_size.width_mi(), + y: bo.0.y + by * split_tx_size.height_mi(), + }); + self.write_tx_size_inter( + w, + tx_bo, + bsize, + split_tx_size, + false, + bx, + by, + depth + 1, + ); + } + } + } + } + + #[inline] + pub const fn get_txsize_entropy_ctx(tx_size: TxSize) -> usize { + (tx_size.sqr() as usize + tx_size.sqr_up() as usize + 1) >> 1 + } + + pub fn txb_init_levels( + &self, coeffs: &[T], height: usize, levels: &mut [u8], + levels_stride: usize, + ) { + // Coefficients and levels are transposed from how they work in the spec + for (coeffs_col, levels_col) in + coeffs.chunks_exact(height).zip(levels.chunks_exact_mut(levels_stride)) + { + for (coeff, level) in coeffs_col.iter().zip(levels_col) { + *level = coeff.abs().min(T::cast_from(127)).as_(); + } + } + } + + // Since the coefficients and levels are transposed in relation to how they + // work in the spec, use the log of block height in our calculations instead + // of block width. + #[inline] + pub const fn get_txb_bhl(tx_size: TxSize) -> usize { + av1_get_coded_tx_size(tx_size).height_log2() + } + + /// Returns `(eob_pt, eob_extra)` + /// + /// # Panics + /// + /// - If `eob` is prior to the start of the group + #[inline] + pub fn get_eob_pos_token(eob: u16) -> (u32, u32) { + let t = if eob < 33 { + eob_to_pos_small[usize::from(eob)] as u32 + } else { + let e = usize::from(cmp::min((eob - 1) >> 5, 16)); + eob_to_pos_large[e] as u32 + }; + assert!(eob as i32 >= k_eob_group_start[t as usize] as i32); + let extra = eob as u32 - k_eob_group_start[t as usize] as u32; + + (t, extra) + } + + pub fn get_nz_mag(levels: &[u8], bhl: usize, tx_class: TxClass) -> usize { + // Levels are transposed from how they work in the spec + + // May version. + // Note: AOMMIN(level, 3) is useless for decoder since level < 3. + let mut mag = cmp::min(3, levels[1]); // { 1, 0 } + mag += cmp::min(3, levels[(1 << bhl) + TX_PAD_HOR]); // { 0, 1 } + + if tx_class == TX_CLASS_2D { + mag += cmp::min(3, levels[(1 << bhl) + TX_PAD_HOR + 1]); // { 1, 1 } + mag += cmp::min(3, levels[2]); // { 2, 0 } + mag += cmp::min(3, levels[(2 << bhl) + (2 << TX_PAD_HOR_LOG2)]); // { 0, 2 } + } else if tx_class == TX_CLASS_VERT { + mag += cmp::min(3, levels[2]); // { 2, 0 } + mag += cmp::min(3, levels[3]); // { 3, 0 } + mag += cmp::min(3, levels[4]); // { 4, 0 } + } else { + mag += cmp::min(3, levels[(2 << bhl) + (2 << TX_PAD_HOR_LOG2)]); // { 0, 2 } + mag += cmp::min(3, levels[(3 << bhl) + (3 << TX_PAD_HOR_LOG2)]); // { 0, 3 } + mag += cmp::min(3, levels[(4 << bhl) + (4 << TX_PAD_HOR_LOG2)]); // { 0, 4 } + } + + mag as usize + } + + fn get_nz_map_ctx_from_stats( + stats: usize, + coeff_idx: usize, // raster order + bhl: usize, + tx_size: TxSize, + tx_class: TxClass, + ) -> usize { + if (tx_class as u32 | coeff_idx as u32) == 0 { + return 0; + }; + + // Coefficients are transposed from how they work in the spec + let col: usize = coeff_idx >> bhl; + let row: usize = coeff_idx - (col << bhl); + + let ctx = ((stats + 1) >> 1).min(4); + + ctx + + match tx_class { + TX_CLASS_2D => { + // This is the algorithm to generate table av1_nz_map_ctx_offset[]. + // const int width = tx_size_wide[tx_size]; + // const int height = tx_size_high[tx_size]; + // if (width < height) { + // if (row < 2) return 11 + ctx; + // } else if (width > height) { + // if (col < 2) return 16 + ctx; + // } + // if (row + col < 2) return ctx + 1; + // if (row + col < 4) return 5 + ctx + 1; + // return 21 + ctx; + av1_nz_map_ctx_offset[tx_size as usize][cmp::min(row, 4)] + [cmp::min(col, 4)] as usize + } + TX_CLASS_HORIZ => nz_map_ctx_offset_1d[col], + TX_CLASS_VERT => nz_map_ctx_offset_1d[row], + } + } + + fn get_nz_map_ctx( + levels: &[u8], coeff_idx: usize, bhl: usize, area: usize, scan_idx: usize, + is_eob: bool, tx_size: TxSize, tx_class: TxClass, + ) -> usize { + if is_eob { + if scan_idx == 0 { + return 0; + } + if scan_idx <= area / 8 { + return 1; + } + if scan_idx <= area / 4 { + return 2; + } + return 3; + } + + // Levels are transposed from how they work in the spec + let padded_idx = coeff_idx + ((coeff_idx >> bhl) << TX_PAD_HOR_LOG2); + let stats = Self::get_nz_mag(&levels[padded_idx..], bhl, tx_class); + + Self::get_nz_map_ctx_from_stats(stats, coeff_idx, bhl, tx_size, tx_class) + } + + /// `coeff_contexts_no_scan` is not in the scan order. + /// Value for `pos = scan[i]` is at `coeff[i]`, not at `coeff[pos]`. + pub fn get_nz_map_contexts<'c>( + &self, levels: &mut [u8], scan: &[u16], eob: u16, tx_size: TxSize, + tx_class: TxClass, coeff_contexts_no_scan: &'c mut [MaybeUninit], + ) -> &'c mut [i8] { + let bhl = Self::get_txb_bhl(tx_size); + let area = av1_get_coded_tx_size(tx_size).area(); + + let scan = &scan[..usize::from(eob)]; + let coeffs = &mut coeff_contexts_no_scan[..usize::from(eob)]; + for (i, (coeff, pos)) in + coeffs.iter_mut().zip(scan.iter().copied()).enumerate() + { + coeff.write(Self::get_nz_map_ctx( + levels, + pos as usize, + bhl, + area, + i, + i == usize::from(eob) - 1, + tx_size, + tx_class, + ) as i8); + } + // SAFETY: every element has been initialized + unsafe { slice_assume_init_mut(coeffs) } + } + + pub fn get_br_ctx( + levels: &[u8], + coeff_idx: usize, // raster order + bhl: usize, + tx_class: TxClass, + ) -> usize { + // Coefficients and levels are transposed from how they work in the spec + let col: usize = coeff_idx >> bhl; + let row: usize = coeff_idx - (col << bhl); + let stride: usize = (1 << bhl) + TX_PAD_HOR; + let pos: usize = col * stride + row; + let mut mag: usize = (levels[pos + 1] + levels[pos + stride]) as usize; + + match tx_class { + TX_CLASS_2D => { + mag += levels[pos + stride + 1] as usize; + mag = cmp::min((mag + 1) >> 1, 6); + if coeff_idx == 0 { + return mag; + } + if (row < 2) && (col < 2) { + return mag + 7; + } + } + TX_CLASS_HORIZ => { + mag += levels[pos + (stride << 1)] as usize; + mag = cmp::min((mag + 1) >> 1, 6); + if coeff_idx == 0 { + return mag; + } + if col == 0 { + return mag + 7; + } + } + TX_CLASS_VERT => { + mag += levels[pos + 2] as usize; + mag = cmp::min((mag + 1) >> 1, 6); + if coeff_idx == 0 { + return mag; + } + if row == 0 { + return mag + 7; + } + } + } + + mag + 14 + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/aarch64.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/aarch64.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/aarch64.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/aarch64.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,116 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use arg_enum_proc_macro::ArgEnum; +use std::env; +use std::str::FromStr; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum)] +pub enum CpuFeatureLevel { + RUST, + NEON, +} + +impl CpuFeatureLevel { + #[cfg(test)] + pub(crate) const fn all() -> &'static [Self] { + use CpuFeatureLevel::*; + &[RUST, NEON] + } + + pub const fn len() -> usize { + CpuFeatureLevel::NEON as usize + 1 + } + + #[inline(always)] + pub fn as_index(self) -> usize { + self as usize + } +} + +impl Default for CpuFeatureLevel { + fn default() -> CpuFeatureLevel { + let detected = CpuFeatureLevel::NEON; + let manual: CpuFeatureLevel = match env::var("RAV1E_CPU_TARGET") { + Ok(feature) => CpuFeatureLevel::from_str(&feature).unwrap_or(detected), + Err(_e) => detected, + }; + if manual > detected { + detected + } else { + manual + } + } +} + +// Create a static lookup table for CPUFeatureLevel enums +// Note: keys are CpuFeatureLevels without any prefix (no CpuFeatureLevel::) +macro_rules! cpu_function_lookup_table { + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + static $name: [$type; crate::cpu_features::CpuFeatureLevel::len()] = { + use crate::cpu_features::CpuFeatureLevel; + #[allow(unused_mut)] + let mut out: [$type; CpuFeatureLevel::len()] = [$empty; CpuFeatureLevel::len()]; + + // Can't use out[0][.] == $empty in static as of rust 1.40 + #[allow(unused_mut)] + let mut set: [bool; CpuFeatureLevel::len()] = [false; CpuFeatureLevel::len()]; + + #[allow(unused_imports)] + use CpuFeatureLevel::*; + $( + out[$key as usize] = $value; + set[$key as usize] = true; + )* + cpu_function_lookup_table!(waterfall_cpu_features(out, set, [NEON])); + out + }; + }; + + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + $pub cpu_function_lookup_table!($name: [$type], default: $empty, [$(($key, $value)),*]); + }; + // Fill empty output functions with the existent functions they support. + // cpus should be in order of lowest cpu level to highest + // Used like an internal function + // Put in here to avoid adding more public macros + (waterfall_cpu_features($out:ident, $set:ident, [$($cpu:ident),*])) => { + // Use an array to emulate if statements (not supported in static as of + // rust 1.40). Setting best[0] (false) and best[1] (true) is equivalent to + // doing nothing and overriding our value respectively. + #[allow(unused_assignments)] + let mut best = [$out[0], $out[0]]; + $( + // If the current entry has a function, update out best function. + best[$set[$cpu as usize] as usize] = $out[$cpu as usize]; + // Update our current entry. Does nothing if it already had a function. + $out[$cpu as usize] = best[1]; + )* + }; + + + // use $name_$key as our values + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + paste::item!{ + cpu_function_lookup_table!( + $pub, $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + paste::item!{ + cpu_function_lookup_table!( + $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright (c) 2019-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + #[macro_use] + mod x86; + pub use x86::*; + } else if #[cfg(asm_neon)] { + #[macro_use] + mod aarch64; + pub use aarch64::*; + } else { + mod rust; + pub use rust::*; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/rust.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/rust.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/rust.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/rust.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use arg_enum_proc_macro::ArgEnum; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum, Default)] +pub enum CpuFeatureLevel { + #[default] + RUST, +} + +impl CpuFeatureLevel { + #[cfg(test)] + #[allow(unused)] + pub(crate) const fn all() -> &'static [Self] { + use CpuFeatureLevel::*; + &[RUST] + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/x86.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/x86.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/cpu_features/x86.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/cpu_features/x86.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,158 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use arg_enum_proc_macro::ArgEnum; +use std::env; +use std::str::FromStr; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, ArgEnum)] +pub enum CpuFeatureLevel { + RUST, + SSE2, + SSSE3, + #[arg_enum(alias = "sse4.1")] + SSE4_1, + AVX2, + AVX512, + #[arg_enum(alias = "avx512vpclmulqdq")] + AVX512ICL, +} + +impl CpuFeatureLevel { + #[cfg(test)] + pub(crate) const fn all() -> &'static [Self] { + use CpuFeatureLevel::*; + &[RUST, SSE2, SSSE3, SSE4_1, AVX2, AVX512, AVX512ICL] + } + + pub const fn len() -> usize { + CpuFeatureLevel::AVX512ICL as usize + 1 + } + + #[inline(always)] + pub const fn as_index(self) -> usize { + self as usize + } +} + +impl Default for CpuFeatureLevel { + fn default() -> CpuFeatureLevel { + fn avx512_detected() -> bool { + is_x86_feature_detected!("avx512bw") + && is_x86_feature_detected!("avx512cd") + && is_x86_feature_detected!("avx512dq") + && is_x86_feature_detected!("avx512f") + && is_x86_feature_detected!("avx512vl") + } + #[allow(deprecated)] // Until MSRV >= 1.69.0 + fn avx512icl_detected() -> bool { + // Per dav1d, these are the flags needed. + avx512_detected() + && is_x86_feature_detected!("avx512vnni") + && is_x86_feature_detected!("avx512ifma") + && is_x86_feature_detected!("avx512vbmi") + && is_x86_feature_detected!("avx512vbmi2") + && is_x86_feature_detected!("avx512vpopcntdq") + && is_x86_feature_detected!("avx512bitalg") + && is_x86_feature_detected!("avx512gfni") + && is_x86_feature_detected!("avx512vaes") + && is_x86_feature_detected!("avx512vpclmulqdq") + } + + let detected: CpuFeatureLevel = if avx512icl_detected() { + CpuFeatureLevel::AVX512ICL + } else if avx512_detected() { + CpuFeatureLevel::AVX512 + } else if is_x86_feature_detected!("avx2") { + CpuFeatureLevel::AVX2 + } else if is_x86_feature_detected!("sse4.1") { + CpuFeatureLevel::SSE4_1 + } else if is_x86_feature_detected!("ssse3") { + CpuFeatureLevel::SSSE3 + } else if is_x86_feature_detected!("sse2") { + CpuFeatureLevel::SSE2 + } else { + CpuFeatureLevel::RUST + }; + let manual: CpuFeatureLevel = match env::var("RAV1E_CPU_TARGET") { + Ok(feature) => CpuFeatureLevel::from_str(&feature).unwrap_or(detected), + Err(_e) => detected, + }; + if manual > detected { + detected + } else { + manual + } + } +} + +// Create a static lookup table for CPUFeatureLevel enums +// Note: keys are CpuFeatureLevels without any prefix (no CpuFeatureLevel::) +macro_rules! cpu_function_lookup_table { + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + static $name: [$type; crate::cpu_features::CpuFeatureLevel::len()] = { + use crate::cpu_features::CpuFeatureLevel; + #[allow(unused_mut)] + let mut out: [$type; CpuFeatureLevel::len()] = [$empty; CpuFeatureLevel::len()]; + + // Can't use out[0][.] == $empty in static as of rust 1.40 + #[allow(unused_mut)] + let mut set: [bool; CpuFeatureLevel::len()] = [false; CpuFeatureLevel::len()]; + + #[allow(unused_imports)] + use CpuFeatureLevel::*; + $( + out[$key as usize] = $value; + set[$key as usize] = true; + )* + cpu_function_lookup_table!(waterfall_cpu_features(out, set, [SSE2, SSSE3, SSE4_1, AVX2, AVX512, AVX512ICL])); + out + }; + }; + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$(($key:ident, $value:expr)),*]) => { + $pub cpu_function_lookup_table!($name: [$type], default: $empty, [$(($key, $value)),*]); + }; + + // Fill empty output functions with the existent functions they support. + // cpus should be in order of lowest cpu level to highest + // Used like an internal function + // Put in here to avoid adding more public macros + (waterfall_cpu_features($out:ident, $set:ident, [$($cpu:ident),*])) => { + // Use an array to emulate if statements (not supported in static as of + // rust 1.40). Setting best[0] (false) and best[1] (true) is equivalent to + // doing nothing and overriding our value respectively. + #[allow(unused_assignments)] + let mut best = [$out[0], $out[0]]; + $( + // If the current entry has a function, update out best function. + best[$set[$cpu as usize] as usize] = $out[$cpu as usize]; + // Update our current entry. Does nothing if it already had a function. + $out[$cpu as usize] = best[1]; + )* + }; + + // use $name_$key as our values + ($pub:vis, $name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + paste::item!{ + cpu_function_lookup_table!( + $pub, $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; + + // version for default visibility + ($name:ident: [$type:ty], default: $empty:expr, [$($key:ident),*]) => { + paste::item!{ + cpu_function_lookup_table!( + $name: [$type], default: $empty, [$(($key, [<$name _$key>])),*] + ); + } + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/deblock.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/deblock.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/deblock.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/deblock.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1668 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::api::FrameType; +use crate::color::ChromaSampling::Cs400; +use crate::context::*; +use crate::encoder::FrameInvariants; +use crate::partition::RefType::*; +use crate::predict::PredictionMode::*; +use crate::quantize::*; +use crate::tiling::*; +use crate::util::{clamp, ILog, Pixel}; +use crate::DeblockState; +use rayon::iter::*; +use std::cmp; + +fn deblock_adjusted_level( + deblock: &DeblockState, block: &Block, pli: usize, vertical: bool, +) -> usize { + let idx = if pli == 0 { usize::from(!vertical) } else { pli + 1 }; + + let level = if deblock.block_deltas_enabled { + // By-block filter strength delta, if the feature is active. + let block_delta = if deblock.block_delta_multi { + block.deblock_deltas[idx] << deblock.block_delta_shift + } else { + block.deblock_deltas[0] << deblock.block_delta_shift + }; + + // Add to frame-specified filter strength (Y-vertical, Y-horizontal, U, V) + clamp(block_delta + deblock.levels[idx] as i8, 0, MAX_LOOP_FILTER as i8) + as u8 + } else { + deblock.levels[idx] + }; + + // if fi.seg_feaure_active { + // rav1e does not yet support segments or segment features + // } + + // Are delta modifiers for specific references and modes active? If so, add them too. + if deblock.deltas_enabled { + let mode = block.mode; + let reference = block.ref_frames[0]; + let mode_type = usize::from( + mode >= NEARESTMV && mode != GLOBALMV && mode != GLOBAL_GLOBALMV, + ); + let l5 = level >> 5; + clamp( + level as i32 + + ((deblock.ref_deltas[reference.to_index()] as i32) << l5) + + if reference == INTRA_FRAME { + 0 + } else { + (deblock.mode_deltas[mode_type] as i32) << l5 + }, + 0, + MAX_LOOP_FILTER as i32, + ) as usize + } else { + level as usize + } +} + +#[inline] +fn deblock_left<'a, T: Pixel>( + blocks: &'a TileBlocks, in_bo: TileBlockOffset, p: &PlaneRegion, +) -> &'a Block { + let xdec = p.plane_cfg.xdec; + let ydec = p.plane_cfg.ydec; + + // subsampled chroma uses odd mi row/col + // We already know we're not at the upper/left corner, so prev_block is in frame + &blocks[in_bo.0.y | ydec][(in_bo.0.x | xdec) - (1 << xdec)] +} + +#[inline] +fn deblock_up<'a, T: Pixel>( + blocks: &'a TileBlocks, in_bo: TileBlockOffset, p: &PlaneRegion, +) -> &'a Block { + let xdec = p.plane_cfg.xdec; + let ydec = p.plane_cfg.ydec; + + // subsampled chroma uses odd mi row/col + &blocks[(in_bo.0.y | ydec) - (1 << ydec)][in_bo.0.x | xdec] +} + +// Must be called on a tx edge, and not on a frame edge. This is enforced above the call. +fn deblock_size( + block: &Block, prev_block: &Block, p: &PlaneRegion, pli: usize, + vertical: bool, block_edge: bool, +) -> usize { + let xdec = p.plane_cfg.xdec; + let ydec = p.plane_cfg.ydec; + + // filter application is conditional on skip and block edge + if !(block_edge + || !block.skip + || !prev_block.skip + || block.ref_frames[0] == INTRA_FRAME + || prev_block.ref_frames[0] == INTRA_FRAME) + { + 0 + } else { + let (txsize, prev_txsize) = if pli == 0 { + (block.txsize, prev_block.txsize) + } else { + ( + block.bsize.largest_chroma_tx_size(xdec, ydec), + prev_block.bsize.largest_chroma_tx_size(xdec, ydec), + ) + }; + let (tx_n, prev_tx_n) = if vertical { + (cmp::max(txsize.width_mi(), 1), cmp::max(prev_txsize.width_mi(), 1)) + } else { + (cmp::max(txsize.height_mi(), 1), cmp::max(prev_txsize.height_mi(), 1)) + }; + cmp::min( + if pli == 0 { 14 } else { 6 }, + cmp::min(tx_n, prev_tx_n) << MI_SIZE_LOG2, + ) + } +} + +// Must be called on a tx edge +#[inline] +fn deblock_level( + deblock: &DeblockState, block: &Block, prev_block: &Block, pli: usize, + vertical: bool, +) -> usize { + let level = deblock_adjusted_level(deblock, block, pli, vertical); + if level == 0 { + deblock_adjusted_level(deblock, prev_block, pli, vertical) + } else { + level + } +} + +// four taps, 4 outputs (two are trivial) +#[inline] +fn filter_narrow2_4( + p1: i32, p0: i32, q0: i32, q1: i32, shift: usize, +) -> [i32; 4] { + let filter0 = clamp(p1 - q1, -128 << shift, (128 << shift) - 1); + let filter1 = + clamp(filter0 + 3 * (q0 - p0) + 4, -128 << shift, (128 << shift) - 1) >> 3; + // be certain our optimization removing a clamp is sound + debug_assert!({ + let base = + clamp(filter0 + 3 * (q0 - p0), -128 << shift, (128 << shift) - 1); + let test = clamp(base + 4, -128 << shift, (128 << shift) - 1) >> 3; + filter1 == test + }); + let filter2 = + clamp(filter0 + 3 * (q0 - p0) + 3, -128 << shift, (128 << shift) - 1) >> 3; + // be certain our optimization removing a clamp is sound + debug_assert!({ + let base = + clamp(filter0 + 3 * (q0 - p0), -128 << shift, (128 << shift) - 1); + let test = clamp(base + 3, -128 << shift, (128 << shift) - 1) >> 3; + filter2 == test + }); + [ + p1, + clamp(p0 + filter2, 0, (256 << shift) - 1), + clamp(q0 - filter1, 0, (256 << shift) - 1), + q1, + ] +} + +// six taps, 6 outputs (four are trivial) +#[inline] +fn filter_narrow2_6( + p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, shift: usize, +) -> [i32; 6] { + let x = filter_narrow2_4(p1, p0, q0, q1, shift); + [p2, x[0], x[1], x[2], x[3], q2] +} + +// 12 taps, 12 outputs (ten are trivial) +#[inline] +fn filter_narrow2_12( + p5: i32, p4: i32, p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, + q2: i32, q3: i32, q4: i32, q5: i32, shift: usize, +) -> [i32; 12] { + let x = filter_narrow2_4(p1, p0, q0, q1, shift); + [p5, p4, p3, p2, x[0], x[1], x[2], x[3], q2, q3, q4, q5] +} + +// four taps, 4 outputs +#[inline] +fn filter_narrow4_4( + p1: i32, p0: i32, q0: i32, q1: i32, shift: usize, +) -> [i32; 4] { + let filter1 = + clamp(3 * (q0 - p0) + 4, -128 << shift, (128 << shift) - 1) >> 3; + // be certain our optimization removing a clamp is sound + debug_assert!({ + let base = clamp(3 * (q0 - p0), -128 << shift, (128 << shift) - 1); + let test = clamp(base + 4, -128 << shift, (128 << shift) - 1) >> 3; + filter1 == test + }); + let filter2 = + clamp(3 * (q0 - p0) + 3, -128 << shift, (128 << shift) - 1) >> 3; + // be certain our optimization removing a clamp is sound + debug_assert!({ + let base = clamp(3 * (q0 - p0), -128 << shift, (128 << shift) - 1); + let test = clamp(base + 3, -128 << shift, (128 << shift) - 1) >> 3; + filter2 == test + }); + let filter3 = (filter1 + 1) >> 1; + [ + clamp(p1 + filter3, 0, (256 << shift) - 1), + clamp(p0 + filter2, 0, (256 << shift) - 1), + clamp(q0 - filter1, 0, (256 << shift) - 1), + clamp(q1 - filter3, 0, (256 << shift) - 1), + ] +} + +// six taps, 6 outputs (two are trivial) +#[inline] +fn filter_narrow4_6( + p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, shift: usize, +) -> [i32; 6] { + let x = filter_narrow4_4(p1, p0, q0, q1, shift); + [p2, x[0], x[1], x[2], x[3], q2] +} + +// 12 taps, 12 outputs (eight are trivial) +#[inline] +fn filter_narrow4_12( + p5: i32, p4: i32, p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, + q2: i32, q3: i32, q4: i32, q5: i32, shift: usize, +) -> [i32; 12] { + let x = filter_narrow4_4(p1, p0, q0, q1, shift); + [p5, p4, p3, p2, x[0], x[1], x[2], x[3], q2, q3, q4, q5] +} + +// six taps, 4 outputs +#[rustfmt::skip] +#[inline] +const fn filter_wide6_4( + p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32 +) -> [i32; 4] { + [ + (p2*3 + p1*2 + p0*2 + q0 + (1<<2)) >> 3, + (p2 + p1*2 + p0*2 + q0*2 + q1 + (1<<2)) >> 3, + (p1 + p0*2 + q0*2 + q1*2 + q2 + (1<<2)) >> 3, + (p0 + q0*2 + q1*2 + q2*3 + (1<<2)) >> 3 + ] +} + +// eight taps, 6 outputs +#[rustfmt::skip] +#[inline] +const fn filter_wide8_6( + p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, q3: i32 +) -> [i32; 6] { + [ + (p3*3 + p2*2 + p1 + p0 + q0 + (1<<2)) >> 3, + (p3*2 + p2 + p1*2 + p0 + q0 + q1 + (1<<2)) >> 3, + (p3 + p2 + p1 + p0*2 + q0 + q1 + q2 +(1<<2)) >> 3, + (p2 + p1 + p0 + q0*2 + q1 + q2 + q3 + (1<<2)) >> 3, + (p1 + p0 + q0 + q1*2 + q2 + q3*2 + (1<<2)) >> 3, + (p0 + q0 + q1 + q2*2 + q3*3 + (1<<2)) >> 3 + ] +} + +// 12 taps, 12 outputs (six are trivial) +#[inline] +const fn filter_wide8_12( + p5: i32, p4: i32, p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, + q2: i32, q3: i32, q4: i32, q5: i32, +) -> [i32; 12] { + let x = filter_wide8_6(p3, p2, p1, p0, q0, q1, q2, q3); + [p5, p4, p3, x[0], x[1], x[2], x[3], x[4], x[5], q3, q4, q5] +} + +// fourteen taps, 12 outputs +#[rustfmt::skip] +#[inline] +const fn filter_wide14_12( + p6: i32, p5: i32, p4: i32, p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, + q1: i32, q2: i32, q3: i32, q4: i32, q5: i32, q6: i32 +) -> [i32; 12] { + [ + (p6*7 + p5*2 + p4*2 + p3 + p2 + p1 + p0 + q0 + (1<<3)) >> 4, + (p6*5 + p5*2 + p4*2 + p3*2 + p2 + p1 + p0 + q0 + q1 + (1<<3)) >> 4, + (p6*4 + p5 + p4*2 + p3*2 + p2*2 + p1 + p0 + q0 + q1 + q2 + (1<<3)) >> 4, + (p6*3 + p5 + p4 + p3*2 + p2*2 + p1*2 + p0 + q0 + q1 + q2 + q3 + (1<<3)) >> 4, + (p6*2 + p5 + p4 + p3 + p2*2 + p1*2 + p0*2 + q0 + q1 + q2 + q3 + q4 + (1<<3)) >> 4, + (p6 + p5 + p4 + p3 + p2 + p1*2 + p0*2 + q0*2 + q1 + q2 + q3 + q4 + q5 + (1<<3)) >> 4, + (p5 + p4 + p3 + p2 + p1 + p0*2 + q0*2 + q1*2 + q2 + q3 + q4 + q5 + q6 + (1<<3)) >> 4, + (p4 + p3 + p2 + p1 + p0 + q0*2 + q1*2 + q2*2 + q3 + q4 + q5 + q6*2 + (1<<3)) >> 4, + (p3 + p2 + p1 + p0 + q0 + q1*2 + q2*2 + q3*2 + q4 + q5 + q6*3 + (1<<3)) >> 4, + (p2 + p1 + p0 + q0 + q1 + q2*2 + q3*2 + q4*2 + q5 + q6*4 + (1<<3)) >> 4, + (p1 + p0 + q0 + q1 + q2 + q3*2 + q4*2 + q5*2 + q6*5 + (1<<3)) >> 4, + (p0 + q0 + q1 + q2 + q3 + q4*2 + q5*2 + q6*7 + (1<<3)) >> 4 + ] +} + +#[inline] +fn copy_horizontal( + dst: &mut PlaneRegionMut<'_, T>, x: usize, y: usize, src: &[i32], +) { + let row = &mut dst[y][x..]; + for (dst, src) in row.iter_mut().take(src.len()).zip(src) { + *dst = T::cast_from(*src); + } +} + +#[inline] +fn copy_vertical( + dst: &mut PlaneRegionMut<'_, T>, x: usize, y: usize, src: &[i32], +) { + for (i, v) in src.iter().enumerate() { + let p = &mut dst[y + i][x]; + *p = T::cast_from(*v); + } +} + +#[inline] +fn stride_sse(a: &[i32; LEN], b: &[i32; LEN]) -> i64 { + a.iter().zip(b).map(|(a, b)| (a - b) * (a - b)).sum::() as i64 +} + +#[inline] +const fn _level_to_limit(level: i32, shift: usize) -> i32 { + level << shift +} + +#[inline] +const fn limit_to_level(limit: i32, shift: usize) -> i32 { + (limit + (1 << shift) - 1) >> shift +} + +#[inline] +const fn _level_to_blimit(level: i32, shift: usize) -> i32 { + (3 * level + 4) << shift +} + +#[inline] +const fn blimit_to_level(blimit: i32, shift: usize) -> i32 { + (((blimit + (1 << shift) - 1) >> shift) - 2) / 3 +} + +#[inline] +const fn _level_to_thresh(level: i32, shift: usize) -> i32 { + level >> 4 << shift +} + +#[inline] +const fn thresh_to_level(thresh: i32, shift: usize) -> i32 { + (thresh + (1 << shift) - 1) >> shift << 4 +} + +#[inline] +fn nhev4(p1: i32, p0: i32, q0: i32, q1: i32, shift: usize) -> usize { + thresh_to_level(cmp::max((p1 - p0).abs(), (q1 - q0).abs()), shift) as usize +} + +#[inline] +fn mask4(p1: i32, p0: i32, q0: i32, q1: i32, shift: usize) -> usize { + cmp::max( + limit_to_level(cmp::max((p1 - p0).abs(), (q1 - q0).abs()), shift), + blimit_to_level((p0 - q0).abs() * 2 + (p1 - q1).abs() / 2, shift), + ) as usize +} + +#[inline] +fn deblock_size4_inner( + [p1, p0, q0, q1]: [i32; 4], level: usize, bd: usize, +) -> Option<[i32; 4]> { + if mask4(p1, p0, q0, q1, bd - 8) <= level { + let x = if nhev4(p1, p0, q0, q1, bd - 8) <= level { + filter_narrow4_4(p1, p0, q0, q1, bd - 8) + } else { + filter_narrow2_4(p1, p0, q0, q1, bd - 8) + }; + Some(x) + } else { + None + } +} + +// Assumes rec[0] is set 2 taps back from the edge +fn deblock_v_size4( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for y in 0..4 { + let p = &rec[y]; + let vals = [p[0].as_(), p[1].as_(), p[2].as_(), p[3].as_()]; + if let Some(data) = deblock_size4_inner(vals, level, bd) { + copy_horizontal(rec, 0, y, &data); + } + } +} + +// Assumes rec[0] is set 2 taps back from the edge +fn deblock_h_size4( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for x in 0..4 { + let vals = + [rec[0][x].as_(), rec[1][x].as_(), rec[2][x].as_(), rec[3][x].as_()]; + if let Some(data) = deblock_size4_inner(vals, level, bd) { + copy_vertical(rec, x, 0, &data); + } + } +} + +// Assumes rec[0] and src[0] are set 2 taps back from the edge. +// Accesses four taps, accumulates four pixels into the tally +fn sse_size4( + rec: &PlaneRegion<'_, T>, src: &PlaneRegion<'_, T>, + tally: &mut [i64; MAX_LOOP_FILTER + 2], horizontal_p: bool, bd: usize, +) { + for i in 0..4 { + let (p1, p0, q0, q1, a) = if horizontal_p { + ( + rec[0][i].as_(), + rec[1][i].as_(), + rec[2][i].as_(), + rec[3][i].as_(), + [src[0][i].as_(), src[1][i].as_(), src[2][i].as_(), src[3][i].as_()], + ) + } else { + ( + rec[i][0].as_(), + rec[i][1].as_(), + rec[i][2].as_(), + rec[i][3].as_(), + [src[i][0].as_(), src[i][1].as_(), src[i][2].as_(), src[i][3].as_()], + ) + }; + + // three possibilities: no filter, narrow2 and narrow4 + // All possibilities produce four outputs + let none: [_; 4] = [p1, p0, q0, q1]; + let narrow2 = filter_narrow2_4(p1, p0, q0, q1, bd - 8); + let narrow4 = filter_narrow4_4(p1, p0, q0, q1, bd - 8); + + // mask4 sets the dividing line for filter vs no filter + // nhev4 sets the dividing line between narrow2 and narrow4 + let mask = clamp(mask4(p1, p0, q0, q1, bd - 8), 1, MAX_LOOP_FILTER + 1); + let nhev = clamp(nhev4(p1, p0, q0, q1, bd - 8), mask, MAX_LOOP_FILTER + 1); + + // sse for each; short-circuit the 'special' no-op cases. + let sse_none = stride_sse(&a, &none); + let sse_narrow2 = + if nhev != mask { stride_sse(&a, &narrow2) } else { sse_none }; + let sse_narrow4 = if nhev <= MAX_LOOP_FILTER { + stride_sse(&a, &narrow4) + } else { + sse_none + }; + + // accumulate possible filter values into the tally + // level 0 is a special case + tally[0] += sse_none; + tally[mask] -= sse_none; + tally[mask] += sse_narrow2; + tally[nhev] -= sse_narrow2; + tally[nhev] += sse_narrow4; + } +} + +#[inline] +fn mask6( + p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, shift: usize, +) -> usize { + cmp::max( + limit_to_level( + cmp::max( + (p2 - p1).abs(), + cmp::max((p1 - p0).abs(), cmp::max((q2 - q1).abs(), (q1 - q0).abs())), + ), + shift, + ), + blimit_to_level((p0 - q0).abs() * 2 + (p1 - q1).abs() / 2, shift), + ) as usize +} + +#[inline] +fn flat6(p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32) -> usize { + cmp::max( + (p1 - p0).abs(), + cmp::max((q1 - q0).abs(), cmp::max((p2 - p0).abs(), (q2 - q0).abs())), + ) as usize +} + +#[inline] +fn deblock_size6_inner( + [p2, p1, p0, q0, q1, q2]: [i32; 6], level: usize, bd: usize, +) -> Option<[i32; 4]> { + if mask6(p2, p1, p0, q0, q1, q2, bd - 8) <= level { + let flat = 1 << (bd - 8); + let x = if flat6(p2, p1, p0, q0, q1, q2) <= flat { + filter_wide6_4(p2, p1, p0, q0, q1, q2) + } else if nhev4(p1, p0, q0, q1, bd - 8) <= level { + filter_narrow4_4(p1, p0, q0, q1, bd - 8) + } else { + filter_narrow2_4(p1, p0, q0, q1, bd - 8) + }; + Some(x) + } else { + None + } +} + +// Assumes slice[0] is set 3 taps back from the edge +fn deblock_v_size6( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for y in 0..4 { + let p = &rec[y]; + let vals = + [p[0].as_(), p[1].as_(), p[2].as_(), p[3].as_(), p[4].as_(), p[5].as_()]; + if let Some(data) = deblock_size6_inner(vals, level, bd) { + copy_horizontal(rec, 1, y, &data); + } + } +} + +// Assumes slice[0] is set 3 taps back from the edge +fn deblock_h_size6( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for x in 0..4 { + let vals = [ + rec[0][x].as_(), + rec[1][x].as_(), + rec[2][x].as_(), + rec[3][x].as_(), + rec[4][x].as_(), + rec[5][x].as_(), + ]; + if let Some(data) = deblock_size6_inner(vals, level, bd) { + copy_vertical(rec, x, 1, &data); + } + } +} + +// Assumes rec[0] and src[0] are set 3 taps back from the edge. +// Accesses six taps, accumulates four pixels into the tally +fn sse_size6( + rec: &PlaneRegion<'_, T>, src: &PlaneRegion<'_, T>, + tally: &mut [i64; MAX_LOOP_FILTER + 2], horizontal_p: bool, bd: usize, +) { + let flat = 1 << (bd - 8); + for i in 0..4 { + let (p2, p1, p0, q0, q1, q2, a) = if horizontal_p { + // six taps + ( + rec[0][i].as_(), + rec[1][i].as_(), + rec[2][i].as_(), + rec[3][i].as_(), + rec[4][i].as_(), + rec[5][i].as_(), + // four pixels to compare so offset one forward + [src[1][i].as_(), src[2][i].as_(), src[3][i].as_(), src[4][i].as_()], + ) + } else { + // six taps + ( + rec[i][0].as_(), + rec[i][1].as_(), + rec[i][2].as_(), + rec[i][3].as_(), + rec[i][4].as_(), + rec[i][5].as_(), + // four pixels to compare so offset one forward + [src[i][1].as_(), src[i][2].as_(), src[i][3].as_(), src[i][4].as_()], + ) + }; + + // Four possibilities: no filter, wide6, narrow2 and narrow4 + // All possibilities produce four outputs + let none: [_; 4] = [p1, p0, q0, q1]; + let wide6 = filter_wide6_4(p2, p1, p0, q0, q1, q2); + let narrow2 = filter_narrow2_4(p1, p0, q0, q1, bd - 8); + let narrow4 = filter_narrow4_4(p1, p0, q0, q1, bd - 8); + + // mask6 sets the dividing line for filter vs no filter + // flat6 decides between wide and narrow filters (unrelated to level) + // nhev4 sets the dividing line between narrow2 and narrow4 + let mask = + clamp(mask6(p2, p1, p0, q0, q1, q2, bd - 8), 1, MAX_LOOP_FILTER + 1); + let flatp = flat6(p2, p1, p0, q0, q1, q2) <= flat; + let nhev = clamp(nhev4(p1, p0, q0, q1, bd - 8), mask, MAX_LOOP_FILTER + 1); + + // sse for each; short-circuit the 'special' no-op cases. + let sse_none = stride_sse(&a, &none); + let sse_wide6 = if flatp && mask <= MAX_LOOP_FILTER { + stride_sse(&a, &wide6) + } else { + sse_none + }; + let sse_narrow2 = + if !flatp && nhev != mask { stride_sse(&a, &narrow2) } else { sse_none }; + let sse_narrow4 = if !flatp && nhev <= MAX_LOOP_FILTER { + stride_sse(&a, &narrow4) + } else { + sse_none + }; + + // accumulate possible filter values into the tally + tally[0] += sse_none; + tally[mask] -= sse_none; + if flatp { + tally[mask] += sse_wide6; + } else { + tally[mask] += sse_narrow2; + tally[nhev] -= sse_narrow2; + tally[nhev] += sse_narrow4; + } + } +} + +#[inline] +fn mask8( + p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, q3: i32, + shift: usize, +) -> usize { + cmp::max( + limit_to_level( + cmp::max( + (p3 - p2).abs(), + cmp::max( + (p2 - p1).abs(), + cmp::max( + (p1 - p0).abs(), + cmp::max( + (q3 - q2).abs(), + cmp::max((q2 - q1).abs(), (q1 - q0).abs()), + ), + ), + ), + ), + shift, + ), + blimit_to_level((p0 - q0).abs() * 2 + (p1 - q1).abs() / 2, shift), + ) as usize +} + +#[inline] +fn flat8( + p3: i32, p2: i32, p1: i32, p0: i32, q0: i32, q1: i32, q2: i32, q3: i32, +) -> usize { + cmp::max( + (p1 - p0).abs(), + cmp::max( + (q1 - q0).abs(), + cmp::max( + (p2 - p0).abs(), + cmp::max((q2 - q0).abs(), cmp::max((p3 - p0).abs(), (q3 - q0).abs())), + ), + ), + ) as usize +} + +#[inline] +fn deblock_size8_inner( + [p3, p2, p1, p0, q0, q1, q2, q3]: [i32; 8], level: usize, bd: usize, +) -> Option<[i32; 6]> { + if mask8(p3, p2, p1, p0, q0, q1, q2, q3, bd - 8) <= level { + let flat = 1 << (bd - 8); + let x = if flat8(p3, p2, p1, p0, q0, q1, q2, q3) <= flat { + filter_wide8_6(p3, p2, p1, p0, q0, q1, q2, q3) + } else if nhev4(p1, p0, q0, q1, bd - 8) <= level { + filter_narrow4_6(p2, p1, p0, q0, q1, q2, bd - 8) + } else { + filter_narrow2_6(p2, p1, p0, q0, q1, q2, bd - 8) + }; + Some(x) + } else { + None + } +} + +// Assumes rec[0] is set 4 taps back from the edge +fn deblock_v_size8( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for y in 0..4 { + let p = &rec[y]; + let vals = [ + p[0].as_(), + p[1].as_(), + p[2].as_(), + p[3].as_(), + p[4].as_(), + p[5].as_(), + p[6].as_(), + p[7].as_(), + ]; + if let Some(data) = deblock_size8_inner(vals, level, bd) { + copy_horizontal(rec, 1, y, &data); + } + } +} + +// Assumes rec[0] is set 4 taps back from the edge +fn deblock_h_size8( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for x in 0..4 { + let vals = [ + rec[0][x].as_(), + rec[1][x].as_(), + rec[2][x].as_(), + rec[3][x].as_(), + rec[4][x].as_(), + rec[5][x].as_(), + rec[6][x].as_(), + rec[7][x].as_(), + ]; + if let Some(data) = deblock_size8_inner(vals, level, bd) { + copy_vertical(rec, x, 1, &data); + } + } +} + +// Assumes rec[0] and src[0] are set 4 taps back from the edge. +// Accesses eight taps, accumulates six pixels into the tally +fn sse_size8( + rec: &PlaneRegion<'_, T>, src: &PlaneRegion<'_, T>, + tally: &mut [i64; MAX_LOOP_FILTER + 2], horizontal_p: bool, bd: usize, +) { + let flat = 1 << (bd - 8); + + for i in 0..4 { + let (p3, p2, p1, p0, q0, q1, q2, q3, a) = if horizontal_p { + // eight taps + ( + rec[0][i].as_(), + rec[1][i].as_(), + rec[2][i].as_(), + rec[3][i].as_(), + rec[4][i].as_(), + rec[5][i].as_(), + rec[6][i].as_(), + rec[7][i].as_(), + // six pixels to compare so offset one forward + [ + src[1][i].as_(), + src[2][i].as_(), + src[3][i].as_(), + src[4][i].as_(), + src[5][i].as_(), + src[6][i].as_(), + ], + ) + } else { + // eight taps + ( + rec[i][0].as_(), + rec[i][1].as_(), + rec[i][2].as_(), + rec[i][3].as_(), + rec[i][4].as_(), + rec[i][5].as_(), + rec[i][6].as_(), + rec[i][7].as_(), + // six pixels to compare so offset one forward + [ + src[i][1].as_(), + src[i][2].as_(), + src[i][3].as_(), + src[i][4].as_(), + src[i][5].as_(), + src[i][6].as_(), + ], + ) + }; + + // Four possibilities: no filter, wide8, narrow2 and narrow4 + let none: [_; 6] = [p2, p1, p0, q0, q1, q2]; + let wide8: [_; 6] = filter_wide8_6(p3, p2, p1, p0, q0, q1, q2, q3); + let narrow2: [_; 6] = filter_narrow2_6(p2, p1, p0, q0, q1, q2, bd - 8); + let narrow4: [_; 6] = filter_narrow4_6(p2, p1, p0, q0, q1, q2, bd - 8); + + // mask8 sets the dividing line for filter vs no filter + // flat8 decides between wide and narrow filters (unrelated to level) + // nhev4 sets the dividing line between narrow2 and narrow4 + let mask = clamp( + mask8(p3, p2, p1, p0, q0, q1, q2, q3, bd - 8), + 1, + MAX_LOOP_FILTER + 1, + ); + let flatp = flat8(p3, p2, p1, p0, q0, q1, q2, q3) <= flat; + let nhev = clamp(nhev4(p1, p0, q0, q1, bd - 8), mask, MAX_LOOP_FILTER + 1); + + // sse for each; short-circuit the 'special' no-op cases. + let sse_none = stride_sse(&a, &none); + let sse_wide8 = if flatp && mask <= MAX_LOOP_FILTER { + stride_sse(&a, &wide8) + } else { + sse_none + }; + let sse_narrow2 = + if !flatp && nhev != mask { stride_sse(&a, &narrow2) } else { sse_none }; + let sse_narrow4 = if !flatp && nhev <= MAX_LOOP_FILTER { + stride_sse(&a, &narrow4) + } else { + sse_none + }; + + // accumulate possible filter values into the tally + tally[0] += sse_none; + tally[mask] -= sse_none; + if flatp { + tally[mask] += sse_wide8; + } else { + tally[mask] += sse_narrow2; + tally[nhev] -= sse_narrow2; + tally[nhev] += sse_narrow4; + } + } +} + +#[inline] +fn flat14_outer( + p6: i32, p5: i32, p4: i32, p0: i32, q0: i32, q4: i32, q5: i32, q6: i32, +) -> usize { + cmp::max( + (p4 - p0).abs(), + cmp::max( + (q4 - q0).abs(), + cmp::max( + (p5 - p0).abs(), + cmp::max((q5 - q0).abs(), cmp::max((p6 - p0).abs(), (q6 - q0).abs())), + ), + ), + ) as usize +} + +#[inline] +fn deblock_size14_inner( + [p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6]: [i32; 14], + level: usize, bd: usize, +) -> Option<[i32; 12]> { + // 'mask' test + if mask8(p3, p2, p1, p0, q0, q1, q2, q3, bd - 8) <= level { + let flat = 1 << (bd - 8); + // inner flatness test + let x = if flat8(p3, p2, p1, p0, q0, q1, q2, q3) <= flat { + // outer flatness test + if flat14_outer(p6, p5, p4, p0, q0, q4, q5, q6) <= flat { + // sufficient flatness across 14 pixel width; run full-width filter + filter_wide14_12( + p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, + ) + } else { + // only flat in inner area, run 8-tap + filter_wide8_12(p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5) + } + } else if nhev4(p1, p0, q0, q1, bd - 8) <= level { + // not flat, run narrow filter + filter_narrow4_12(p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, bd - 8) + } else { + filter_narrow2_12(p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, bd - 8) + }; + Some(x) + } else { + None + } +} + +// Assumes rec[0] is set 7 taps back from the edge +fn deblock_v_size14( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for y in 0..4 { + let p = &rec[y]; + let vals = [ + p[0].as_(), + p[1].as_(), + p[2].as_(), + p[3].as_(), + p[4].as_(), + p[5].as_(), + p[6].as_(), + p[7].as_(), + p[8].as_(), + p[9].as_(), + p[10].as_(), + p[11].as_(), + p[12].as_(), + p[13].as_(), + ]; + if let Some(data) = deblock_size14_inner(vals, level, bd) { + copy_horizontal(rec, 1, y, &data); + } + } +} + +// Assumes rec[0] is set 7 taps back from the edge +fn deblock_h_size14( + rec: &mut PlaneRegionMut<'_, T>, level: usize, bd: usize, +) { + for x in 0..4 { + let vals = [ + rec[0][x].as_(), + rec[1][x].as_(), + rec[2][x].as_(), + rec[3][x].as_(), + rec[4][x].as_(), + rec[5][x].as_(), + rec[6][x].as_(), + rec[7][x].as_(), + rec[8][x].as_(), + rec[9][x].as_(), + rec[10][x].as_(), + rec[11][x].as_(), + rec[12][x].as_(), + rec[13][x].as_(), + ]; + if let Some(data) = deblock_size14_inner(vals, level, bd) { + copy_vertical(rec, x, 1, &data); + } + } +} + +// Assumes rec[0] and src[0] are set 7 taps back from the edge. +// Accesses fourteen taps, accumulates twelve pixels into the tally +fn sse_size14( + rec: &PlaneRegion<'_, T>, src: &PlaneRegion<'_, T>, + tally: &mut [i64; MAX_LOOP_FILTER + 2], horizontal_p: bool, bd: usize, +) { + let flat = 1 << (bd - 8); + for i in 0..4 { + let (p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, a) = + if horizontal_p { + // 14 taps + ( + rec[0][i].as_(), + rec[1][i].as_(), + rec[2][i].as_(), + rec[3][i].as_(), + rec[4][i].as_(), + rec[5][i].as_(), + rec[6][i].as_(), + rec[7][i].as_(), + rec[8][i].as_(), + rec[9][i].as_(), + rec[10][i].as_(), + rec[11][i].as_(), + rec[12][i].as_(), + rec[13][i].as_(), + // 12 pixels to compare so offset one forward + [ + src[1][i].as_(), + src[2][i].as_(), + src[3][i].as_(), + src[4][i].as_(), + src[5][i].as_(), + src[6][i].as_(), + src[7][i].as_(), + src[8][i].as_(), + src[9][i].as_(), + src[10][i].as_(), + src[11][i].as_(), + src[12][i].as_(), + ], + ) + } else { + // 14 taps + ( + rec[i][0].as_(), + rec[i][1].as_(), + rec[i][2].as_(), + rec[i][3].as_(), + rec[i][4].as_(), + rec[i][5].as_(), + rec[i][6].as_(), + rec[i][7].as_(), + rec[i][8].as_(), + rec[i][9].as_(), + rec[i][10].as_(), + rec[i][11].as_(), + rec[i][12].as_(), + rec[i][13].as_(), + // 12 pixels to compare so offset one forward + [ + src[i][1].as_(), + src[i][2].as_(), + src[i][3].as_(), + src[i][4].as_(), + src[i][5].as_(), + src[i][6].as_(), + src[i][7].as_(), + src[i][8].as_(), + src[i][9].as_(), + src[i][10].as_(), + src[i][11].as_(), + src[i][12].as_(), + ], + ) + }; + + // Five possibilities: no filter, wide14, wide8, narrow2 and narrow4 + let none: [i32; 12] = [p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5]; + let wide14 = + filter_wide14_12(p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6); + let wide8 = + filter_wide8_12(p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5); + let narrow2 = filter_narrow2_12( + p5, + p4, + p3, + p2, + p1, + p0, + q0, + q1, + q2, + q3, + q4, + q5, + bd - 8, + ); + let narrow4 = filter_narrow4_12( + p5, + p4, + p3, + p2, + p1, + p0, + q0, + q1, + q2, + q3, + q4, + q5, + bd - 8, + ); + + // mask8 sets the dividing line for filter vs no filter + // flat8 decides between wide and narrow filters (unrelated to level) + // flat14 decides between wide14 and wide8 filters + // nhev4 sets the dividing line between narrow2 and narrow4 + let mask = clamp( + mask8(p3, p2, p1, p0, q0, q1, q2, q3, bd - 8), + 1, + MAX_LOOP_FILTER + 1, + ); + let flat8p = flat8(p3, p2, p1, p0, q0, q1, q2, q3) <= flat; + let flat14p = flat14_outer(p6, p5, p4, p0, q0, q4, q5, q6) <= flat; + let nhev = clamp(nhev4(p1, p0, q0, q1, bd - 8), mask, MAX_LOOP_FILTER + 1); + + // sse for each; short-circuit the 'special' no-op cases. + let sse_none = stride_sse(&a, &none); + let sse_wide8 = if flat8p && !flat14p && mask <= MAX_LOOP_FILTER { + stride_sse(&a, &wide8) + } else { + sse_none + }; + let sse_wide14 = if flat8p && flat14p && mask <= MAX_LOOP_FILTER { + stride_sse(&a, &wide14) + } else { + sse_none + }; + let sse_narrow2 = if !flat8p && nhev != mask { + stride_sse(&a, &narrow2) + } else { + sse_none + }; + let sse_narrow4 = if !flat8p && nhev <= MAX_LOOP_FILTER { + stride_sse(&a, &narrow4) + } else { + sse_none + }; + + // accumulate possible filter values into the tally + tally[0] += sse_none; + tally[mask] -= sse_none; + if flat8p { + if flat14p { + tally[mask] += sse_wide14; + } else { + tally[mask] += sse_wide8; + } + } else { + tally[mask] += sse_narrow2; + tally[nhev] -= sse_narrow2; + tally[nhev] += sse_narrow4; + } + } +} + +fn filter_v_edge( + deblock: &DeblockState, blocks: &TileBlocks, bo: TileBlockOffset, + p: &mut PlaneRegionMut, pli: usize, bd: usize, xdec: usize, ydec: usize, +) { + let block = &blocks[bo]; + let txsize = if pli == 0 { + block.txsize + } else { + block.bsize.largest_chroma_tx_size(xdec, ydec) + }; + let tx_edge = (bo.0.x >> xdec) & (txsize.width_mi() - 1) == 0; + if tx_edge { + let prev_block = deblock_left(blocks, bo, &p.as_const()); + let block_edge = bo.0.x & (block.n4_w as usize - 1) == 0; + let filter_size = + deblock_size(block, prev_block, &p.as_const(), pli, true, block_edge); + if filter_size > 0 { + let level = deblock_level(deblock, block, prev_block, pli, true); + if level > 0 { + let po = bo.plane_offset(p.plane_cfg); + let mut plane_region = p.subregion_mut(Area::Rect { + x: po.x - (filter_size >> 1) as isize, + y: po.y, + width: filter_size, + height: 4, + }); + match filter_size { + 4 => { + deblock_v_size4(&mut plane_region, level, bd); + } + 6 => { + deblock_v_size6(&mut plane_region, level, bd); + } + 8 => { + deblock_v_size8(&mut plane_region, level, bd); + } + 14 => { + deblock_v_size14(&mut plane_region, level, bd); + } + _ => unreachable!(), + } + } + } + } +} + +fn sse_v_edge( + blocks: &TileBlocks, bo: TileBlockOffset, rec_plane: &PlaneRegion, + src_plane: &PlaneRegion, tally: &mut [i64; MAX_LOOP_FILTER + 2], + pli: usize, bd: usize, xdec: usize, ydec: usize, +) { + let block = &blocks[bo]; + let txsize = if pli == 0 { + block.txsize + } else { + block.bsize.largest_chroma_tx_size(xdec, ydec) + }; + let tx_edge = (bo.0.x >> xdec) & (txsize.width_mi() - 1) == 0; + if tx_edge { + let prev_block = deblock_left(blocks, bo, rec_plane); + let block_edge = bo.0.x & (block.n4_w as usize - 1) == 0; + let filter_size = + deblock_size(block, prev_block, rec_plane, pli, true, block_edge); + if filter_size > 0 { + let po = bo.plane_offset(rec_plane.plane_cfg); // rec and src have identical subsampling + let rec_region = rec_plane.subregion(Area::Rect { + x: po.x - (filter_size >> 1) as isize, + y: po.y, + width: filter_size, + height: 4, + }); + let src_region = src_plane.subregion(Area::Rect { + x: po.x - (filter_size >> 1) as isize, + y: po.y, + width: filter_size, + height: 4, + }); + match filter_size { + 4 => { + sse_size4(&rec_region, &src_region, tally, false, bd); + } + 6 => { + sse_size6(&rec_region, &src_region, tally, false, bd); + } + 8 => { + sse_size8(&rec_region, &src_region, tally, false, bd); + } + 14 => { + sse_size14(&rec_region, &src_region, tally, false, bd); + } + _ => unreachable!(), + } + } + } +} + +fn filter_h_edge( + deblock: &DeblockState, blocks: &TileBlocks, bo: TileBlockOffset, + p: &mut PlaneRegionMut, pli: usize, bd: usize, xdec: usize, ydec: usize, +) { + let block = &blocks[bo]; + let txsize = if pli == 0 { + block.txsize + } else { + block.bsize.largest_chroma_tx_size(xdec, ydec) + }; + let tx_edge = (bo.0.y >> ydec) & (txsize.height_mi() - 1) == 0; + if tx_edge { + let prev_block = deblock_up(blocks, bo, &p.as_const()); + let block_edge = bo.0.y & (block.n4_h as usize - 1) == 0; + let filter_size = + deblock_size(block, prev_block, &p.as_const(), pli, false, block_edge); + if filter_size > 0 { + let level = deblock_level(deblock, block, prev_block, pli, false); + if level > 0 { + let po = bo.plane_offset(p.plane_cfg); + let mut plane_region = p.subregion_mut(Area::Rect { + x: po.x, + y: po.y - (filter_size >> 1) as isize, + width: 4, + height: filter_size, + }); + match filter_size { + 4 => { + deblock_h_size4(&mut plane_region, level, bd); + } + 6 => { + deblock_h_size6(&mut plane_region, level, bd); + } + 8 => { + deblock_h_size8(&mut plane_region, level, bd); + } + 14 => { + deblock_h_size14(&mut plane_region, level, bd); + } + _ => unreachable!(), + } + } + } + } +} + +fn sse_h_edge( + blocks: &TileBlocks, bo: TileBlockOffset, rec_plane: &PlaneRegion, + src_plane: &PlaneRegion, tally: &mut [i64; MAX_LOOP_FILTER + 2], + pli: usize, bd: usize, xdec: usize, ydec: usize, +) { + let block = &blocks[bo]; + let txsize = if pli == 0 { + block.txsize + } else { + block.bsize.largest_chroma_tx_size(xdec, ydec) + }; + let tx_edge = (bo.0.y >> ydec) & (txsize.height_mi() - 1) == 0; + if tx_edge { + let prev_block = deblock_up(blocks, bo, rec_plane); + let block_edge = bo.0.y & (block.n4_h as usize - 1) == 0; + let filter_size = + deblock_size(block, prev_block, rec_plane, pli, true, block_edge); + if filter_size > 0 { + let po = bo.plane_offset(rec_plane.plane_cfg); // rec and src have identical subsampling + let rec_region = rec_plane.subregion(Area::Rect { + x: po.x, + y: po.y - (filter_size >> 1) as isize, + width: 4, + height: filter_size, + }); + let src_region = src_plane.subregion(Area::Rect { + x: po.x, + y: po.y - (filter_size >> 1) as isize, + width: 4, + height: filter_size, + }); + + match filter_size { + 4 => { + sse_size4(&rec_region, &src_region, tally, true, bd); + } + 6 => { + sse_size6(&rec_region, &src_region, tally, true, bd); + } + 8 => { + sse_size8(&rec_region, &src_region, tally, true, bd); + } + 14 => { + sse_size14(&rec_region, &src_region, tally, true, bd); + } + _ => unreachable!(), + } + } + } +} + +// Deblocks all edges, vertical and horizontal, in a single plane +#[profiling::function] +pub fn deblock_plane( + deblock: &DeblockState, p: &mut PlaneRegionMut, pli: usize, + blocks: &TileBlocks, crop_w: usize, crop_h: usize, bd: usize, +) { + let xdec = p.plane_cfg.xdec; + let ydec = p.plane_cfg.ydec; + assert!(xdec <= 1 && ydec <= 1); + + match pli { + 0 => { + if deblock.levels[0] == 0 && deblock.levels[1] == 0 { + return; + } + } + 1 => { + if deblock.levels[2] == 0 { + return; + } + } + 2 => { + if deblock.levels[3] == 0 { + return; + } + } + _ => return, + } + + let rect = p.rect(); + let cols = (cmp::min( + blocks.cols(), + ((crop_w - rect.x as usize) + MI_SIZE - 1) >> MI_SIZE_LOG2, + ) + (1 << xdec >> 1)) + >> xdec + << xdec; // Clippy can go suck an egg + let rows = (cmp::min( + blocks.rows(), + ((crop_h - rect.y as usize) + MI_SIZE - 1) >> MI_SIZE_LOG2, + ) + (1 << ydec >> 1)) + >> ydec + << ydec; // Clippy can go suck an egg + + // vertical edge filtering leads horizontal by one full MI-sized + // row (and horizontal filtering doesn't happen along the upper + // edge). Unroll to avoid corner-cases. + if rows > 0 { + for x in (1 << xdec..cols).step_by(1 << xdec) { + filter_v_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { x, y: 0 }), + p, + pli, + bd, + xdec, + ydec, + ); + } + if rows > 1 << ydec { + for x in (1 << xdec..cols).step_by(1 << xdec) { + filter_v_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { x, y: 1 << ydec }), + p, + pli, + bd, + xdec, + ydec, + ); + } + } + } + + // filter rows where vertical and horizontal edge filtering both + // happen (horizontal edge filtering lags vertical by one row). + for y in ((2 << ydec)..rows).step_by(1 << ydec) { + // Check for vertical edge at first MI block boundary on this row + if cols > 1 << xdec { + filter_v_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { x: 1 << xdec, y }), + p, + pli, + bd, + xdec, + ydec, + ); + } + // run the rest of the row with both vertical and horizontal edge filtering. + // Horizontal lags vertical edge by one row and two columns. + for x in (2 << xdec..cols).step_by(1 << xdec) { + filter_v_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { x, y }), + p, + pli, + bd, + xdec, + ydec, + ); + filter_h_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { + x: x - (2 << xdec), + y: y - (1 << ydec), + }), + p, + pli, + bd, + xdec, + ydec, + ); + } + // ..and the last two horizontal edges for the row + if cols >= 2 << xdec { + filter_h_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { + x: cols - (2 << xdec), + y: y - (1 << ydec), + }), + p, + pli, + bd, + xdec, + ydec, + ); + } + if cols >= 1 << xdec { + filter_h_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { + x: cols - (1 << xdec), + y: y - (1 << ydec), + }), + p, + pli, + bd, + xdec, + ydec, + ); + } + } + + // Last horizontal row, vertical is already complete + if rows > 1 << ydec { + for x in (0..cols).step_by(1 << xdec) { + filter_h_edge( + deblock, + blocks, + TileBlockOffset(BlockOffset { x, y: rows - (1 << ydec) }), + p, + pli, + bd, + xdec, + ydec, + ); + } + } +} + +// sse count of all edges in a single plane, accumulates into vertical and horizontal counts +fn sse_plane( + rec: &PlaneRegion, src: &PlaneRegion, + v_sse: &mut [i64; MAX_LOOP_FILTER + 2], + h_sse: &mut [i64; MAX_LOOP_FILTER + 2], pli: usize, blocks: &TileBlocks, + crop_w: usize, crop_h: usize, bd: usize, +) { + let xdec = rec.plane_cfg.xdec; + let ydec = rec.plane_cfg.ydec; + assert!(xdec <= 1 && ydec <= 1); + let rect = rec.rect(); + let cols = (cmp::min( + blocks.cols(), + (crop_w - rect.x as usize + MI_SIZE - 1) >> MI_SIZE_LOG2, + ) + (1 << xdec >> 1)) + >> xdec + << xdec; // Clippy can go suck an egg + let rows = (cmp::min( + blocks.rows(), + (crop_h - rect.y as usize + MI_SIZE - 1) >> MI_SIZE_LOG2, + ) + (1 << ydec >> 1)) + >> ydec + << ydec; // Clippy can go suck an egg + + // No horizontal edge filtering along top of frame + for x in (1 << xdec..cols).step_by(1 << xdec) { + sse_v_edge( + blocks, + TileBlockOffset(BlockOffset { x, y: 0 }), + rec, + src, + v_sse, + pli, + bd, + xdec, + ydec, + ); + } + + // Unlike actual filtering, we're counting horizontal and vertical + // as separable cases. No need to lag the horizontal processing + // behind vertical. + for y in (1 << ydec..rows).step_by(1 << ydec) { + // No vertical filtering along left edge of frame + sse_h_edge( + blocks, + TileBlockOffset(BlockOffset { x: 0, y }), + rec, + src, + h_sse, + pli, + bd, + xdec, + ydec, + ); + for x in (1 << xdec..cols).step_by(1 << xdec) { + sse_v_edge( + blocks, + TileBlockOffset(BlockOffset { x, y }), + rec, + src, + v_sse, + pli, + bd, + xdec, + ydec, + ); + sse_h_edge( + blocks, + TileBlockOffset(BlockOffset { x, y }), + rec, + src, + h_sse, + pli, + bd, + xdec, + ydec, + ); + } + } +} + +// Deblocks all edges in all planes of a frame +#[profiling::function] +pub fn deblock_filter_frame( + deblock: &DeblockState, tile: &mut TileMut, blocks: &TileBlocks, + crop_w: usize, crop_h: usize, bd: usize, planes: usize, +) { + tile.planes[..planes].par_iter_mut().enumerate().for_each(|(pli, plane)| { + deblock_plane(deblock, plane, pli, blocks, crop_w, crop_h, bd); + }); +} + +fn sse_optimize( + rec: &Tile, input: &Tile, blocks: &TileBlocks, crop_w: usize, + crop_h: usize, bd: usize, monochrome: bool, +) -> [u8; 4] { + // i64 allows us to accumulate a total of ~ 35 bits worth of pixels + assert!( + ILog::ilog(input.planes[0].plane_cfg.width) + + ILog::ilog(input.planes[0].plane_cfg.height) + < 35 + ); + let mut level = [0; 4]; + let planes = if monochrome { 1 } else { MAX_PLANES }; + + for pli in 0..planes { + let mut v_tally: [i64; MAX_LOOP_FILTER + 2] = [0; MAX_LOOP_FILTER + 2]; + let mut h_tally: [i64; MAX_LOOP_FILTER + 2] = [0; MAX_LOOP_FILTER + 2]; + + sse_plane( + &rec.planes[pli], + &input.planes[pli], + &mut v_tally, + &mut h_tally, + pli, + blocks, + crop_w, + crop_h, + bd, + ); + + for i in 1..=MAX_LOOP_FILTER { + v_tally[i] += v_tally[i - 1]; + h_tally[i] += h_tally[i - 1]; + } + + match pli { + 0 => { + let mut best_v = 999; + let mut best_h = 999; + for i in 0..=MAX_LOOP_FILTER { + if best_v == 999 || v_tally[best_v] > v_tally[i] { + best_v = i; + }; + if best_h == 999 || h_tally[best_h] > h_tally[i] { + best_h = i; + }; + } + level[0] = best_v as u8; + level[1] = best_h as u8; + } + 1 | 2 => { + let mut best = 999; + for i in 0..=MAX_LOOP_FILTER { + if best == 999 + || v_tally[best] + h_tally[best] > v_tally[i] + h_tally[i] + { + best = i; + }; + } + level[pli + 1] = best as u8; + } + _ => unreachable!(), + } + } + level +} + +#[profiling::function] +pub fn deblock_filter_optimize( + fi: &FrameInvariants, rec: &Tile, input: &Tile, + blocks: &TileBlocks, crop_w: usize, crop_h: usize, +) -> [u8; 4] { + if fi.config.speed_settings.fast_deblock { + let q = ac_q(fi.base_q_idx, 0, fi.sequence.bit_depth).get() as i32; + let level = clamp( + match fi.sequence.bit_depth { + 8 => { + if fi.frame_type == FrameType::KEY { + (q * 17563 - 421_574 + (1 << 18 >> 1)) >> 18 + } else { + (q * 6017 + 650_707 + (1 << 18 >> 1)) >> 18 + } + } + 10 => { + if fi.frame_type == FrameType::KEY { + ((q * 20723 + 4_060_632 + (1 << 20 >> 1)) >> 20) - 4 + } else { + (q * 20723 + 4_060_632 + (1 << 20 >> 1)) >> 20 + } + } + 12 => { + if fi.frame_type == FrameType::KEY { + ((q * 20723 + 16_242_526 + (1 << 22 >> 1)) >> 22) - 4 + } else { + (q * 20723 + 16_242_526 + (1 << 22 >> 1)) >> 22 + } + } + _ => unreachable!(), + }, + 0, + MAX_LOOP_FILTER as i32, + ) as u8; + [level; 4] + } else { + // Deblocking happens in 4x4 (luma) units; luma x,y are clipped to + // the *crop frame* of the entire frame by 4x4 block. + sse_optimize( + rec, + input, + blocks, + crop_w, + crop_h, + fi.sequence.bit_depth, + fi.sequence.chroma_sampling == Cs400, + ) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/dist.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/dist.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/dist.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/dist.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,534 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::dist::*; + } else if #[cfg(asm_neon)] { + pub use crate::asm::aarch64::dist::*; + } else { + pub use self::rust::*; + } +} + +pub(crate) mod rust { + use crate::activity::apply_ssim_boost; + use crate::cpu_features::CpuFeatureLevel; + use crate::tiling::*; + use crate::util::*; + + use crate::encoder::IMPORTANCE_BLOCK_SIZE; + use crate::rdo::DistortionScale; + + /// Compute the sum of absolute differences over a block. + /// w and h can be at most 128, the size of the largest block. + pub fn get_sad( + plane_org: &PlaneRegion<'_, T>, plane_ref: &PlaneRegion<'_, T>, w: usize, + h: usize, _bit_depth: usize, _cpu: CpuFeatureLevel, + ) -> u32 { + debug_assert!(w <= 128 && h <= 128); + let plane_org = + plane_org.subregion(Area::Rect { x: 0, y: 0, width: w, height: h }); + let plane_ref = + plane_ref.subregion(Area::Rect { x: 0, y: 0, width: w, height: h }); + + plane_org + .rows_iter() + .zip(plane_ref.rows_iter()) + .map(|(src, dst)| { + src + .iter() + .zip(dst) + .map(|(&p1, &p2)| i32::cast_from(p1).abs_diff(i32::cast_from(p2))) + .sum::() + }) + .sum() + } + + #[inline(always)] + const fn butterfly(a: i32, b: i32) -> (i32, i32) { + ((a + b), (a - b)) + } + + #[inline(always)] + #[allow(clippy::identity_op, clippy::erasing_op)] + fn hadamard4_1d< + const LEN: usize, + const N: usize, + const STRIDE0: usize, + const STRIDE1: usize, + >( + data: &mut [i32; LEN], + ) { + for i in 0..N { + let sub: &mut [i32] = &mut data[i * STRIDE0..]; + let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]); + let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]); + let (b0, b2) = butterfly(a0, a2); + let (b1, b3) = butterfly(a1, a3); + sub[0 * STRIDE1] = b0; + sub[1 * STRIDE1] = b1; + sub[2 * STRIDE1] = b2; + sub[3 * STRIDE1] = b3; + } + } + + #[inline(always)] + #[allow(clippy::identity_op, clippy::erasing_op)] + fn hadamard8_1d< + const LEN: usize, + const N: usize, + const STRIDE0: usize, + const STRIDE1: usize, + >( + data: &mut [i32; LEN], + ) { + for i in 0..N { + let sub: &mut [i32] = &mut data[i * STRIDE0..]; + + let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]); + let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]); + let (a4, a5) = butterfly(sub[4 * STRIDE1], sub[5 * STRIDE1]); + let (a6, a7) = butterfly(sub[6 * STRIDE1], sub[7 * STRIDE1]); + + let (b0, b2) = butterfly(a0, a2); + let (b1, b3) = butterfly(a1, a3); + let (b4, b6) = butterfly(a4, a6); + let (b5, b7) = butterfly(a5, a7); + + let (c0, c4) = butterfly(b0, b4); + let (c1, c5) = butterfly(b1, b5); + let (c2, c6) = butterfly(b2, b6); + let (c3, c7) = butterfly(b3, b7); + + sub[0 * STRIDE1] = c0; + sub[1 * STRIDE1] = c1; + sub[2 * STRIDE1] = c2; + sub[3 * STRIDE1] = c3; + sub[4 * STRIDE1] = c4; + sub[5 * STRIDE1] = c5; + sub[6 * STRIDE1] = c6; + sub[7 * STRIDE1] = c7; + } + } + + #[inline(always)] + fn hadamard2d( + data: &mut [i32; LEN], + ) { + /*Vertical transform.*/ + let vert_func = if H == 4 { + hadamard4_1d:: + } else { + hadamard8_1d:: + }; + vert_func(data); + /*Horizontal transform.*/ + let horz_func = if W == 4 { + hadamard4_1d:: + } else { + hadamard8_1d:: + }; + horz_func(data); + } + + // SAFETY: The length of data must be 16. + unsafe fn hadamard4x4(data: &mut [i32]) { + hadamard2d::<{ 4 * 4 }, 4, 4>(&mut *(data.as_mut_ptr() as *mut [i32; 16])); + } + + // SAFETY: The length of data must be 64. + unsafe fn hadamard8x8(data: &mut [i32]) { + hadamard2d::<{ 8 * 8 }, 8, 8>(&mut *(data.as_mut_ptr() as *mut [i32; 64])); + } + + /// Sum of absolute transformed differences over a block. + /// w and h can be at most 128, the size of the largest block. + /// Use the sum of 4x4 and 8x8 hadamard transforms for the transform, but + /// revert to sad on edges when these transforms do not fit into w and h. + /// 4x4 transforms instead of 8x8 transforms when width or height < 8. + pub fn get_satd( + plane_org: &PlaneRegion<'_, T>, plane_ref: &PlaneRegion<'_, T>, w: usize, + h: usize, _bit_depth: usize, _cpu: CpuFeatureLevel, + ) -> u32 { + assert!(w <= 128 && h <= 128); + assert!(plane_org.rect().width >= w && plane_org.rect().height >= h); + assert!(plane_ref.rect().width >= w && plane_ref.rect().height >= h); + + // Size of hadamard transform should be 4x4 or 8x8 + // 4x* and *x4 use 4x4 and all other use 8x8 + let size: usize = w.min(h).min(8); + let tx2d = if size == 4 { hadamard4x4 } else { hadamard8x8 }; + + let mut sum: u64 = 0; + + // Loop over chunks the size of the chosen transform + for chunk_y in (0..h).step_by(size) { + let chunk_h = (h - chunk_y).min(size); + for chunk_x in (0..w).step_by(size) { + let chunk_w = (w - chunk_x).min(size); + let chunk_area: Area = Area::Rect { + x: chunk_x as isize, + y: chunk_y as isize, + width: chunk_w, + height: chunk_h, + }; + let chunk_org = plane_org.subregion(chunk_area); + let chunk_ref = plane_ref.subregion(chunk_area); + + // Revert to sad on edge blocks (frame edges) + if chunk_w != size || chunk_h != size { + sum += get_sad( + &chunk_org, &chunk_ref, chunk_w, chunk_h, _bit_depth, _cpu, + ) as u64; + continue; + } + + let buf: &mut [i32] = &mut [0; 8 * 8][..size * size]; + + // Move the difference of the transforms to a buffer + for (row_diff, (row_org, row_ref)) in buf + .chunks_mut(size) + .zip(chunk_org.rows_iter().zip(chunk_ref.rows_iter())) + { + for (diff, (a, b)) in + row_diff.iter_mut().zip(row_org.iter().zip(row_ref.iter())) + { + *diff = i32::cast_from(*a) - i32::cast_from(*b); + } + } + + // Perform the hadamard transform on the differences + // SAFETY: A sufficient number elements exist for the size of the transform. + unsafe { + tx2d(buf); + } + + // Sum the absolute values of the transformed differences + sum += buf.iter().map(|a| a.unsigned_abs() as u64).sum::(); + } + } + + // Normalize the results + let ln = msb(size as i32) as u64; + ((sum + (1 << ln >> 1)) >> ln) as u32 + } + + /// Number of bits rounded off before summing in `get_weighted_sse` + pub const GET_WEIGHTED_SSE_SHIFT: u8 = 8; + + /// Computes weighted sum of squared error. + /// + /// Each scale is applied to a 4x4 region in the provided inputs. Each scale + /// value is a fixed point number, currently [`DistortionScale`]. + /// + /// Implementations can require alignment (`bw` (block width) for [`src1`] and + /// [`src2`] and `bw/4` for `scale`). + #[inline(never)] + pub fn get_weighted_sse( + src1: &PlaneRegion<'_, T>, src2: &PlaneRegion<'_, T>, scale: &[u32], + scale_stride: usize, w: usize, h: usize, _bit_depth: usize, + _cpu: CpuFeatureLevel, + ) -> u64 { + let src1 = src1.subregion(Area::Rect { x: 0, y: 0, width: w, height: h }); + // Always chunk and apply scaling on the sse of squares the size of + // decimated/sub-sampled importance block sizes. + // Warning: Changing this will require changing/disabling assembly. + let chunk_size: usize = IMPORTANCE_BLOCK_SIZE >> 1; + + // Iterator of a row of scales, stretched out to be per row + let scales = scale.chunks_exact(scale_stride); + + let sse = src1 + .vert_windows(chunk_size) + .step_by(chunk_size) + .zip(src2.vert_windows(chunk_size).step_by(chunk_size)) + .zip(scales) + .map(|((row1, row2), scales)| { + row1 + .horz_windows(chunk_size) + .step_by(chunk_size) + .zip(row2.horz_windows(chunk_size).step_by(chunk_size)) + .zip(scales) + .map(|((chunk1, chunk2), &scale)| { + let sum = chunk1 + .rows_iter() + .zip(chunk2.rows_iter()) + .map(|(chunk_row1, chunk_row2)| { + chunk_row1 + .iter() + .zip(chunk_row2) + .map(|(&a, &b)| { + let c = i32::cast_from(a) - i32::cast_from(b); + (c * c) as u32 + }) + .sum::() + }) + .sum::(); + (sum as u64 * scale as u64 + (1 << GET_WEIGHTED_SSE_SHIFT >> 1)) + >> GET_WEIGHTED_SSE_SHIFT + }) + .sum::() + }) + .sum::(); + + let den = DistortionScale::new(1, 1 << GET_WEIGHTED_SSE_SHIFT).0 as u64; + (sse + (den >> 1)) / den + } + + /// Number of bits of precision used in `AREA_DIVISORS` + const AREA_DIVISOR_BITS: u8 = 14; + + /// Lookup table for 2^`AREA_DIVISOR_BITS` / (1 + x) + #[rustfmt::skip] + const AREA_DIVISORS: [u16; 64] = [ + 16384, 8192, 5461, 4096, 3277, 2731, 2341, 2048, 1820, 1638, 1489, 1365, + 1260, 1170, 1092, 1024, 964, 910, 862, 819, 780, 745, 712, 683, + 655, 630, 607, 585, 565, 546, 529, 512, 496, 482, 468, 455, + 443, 431, 420, 410, 400, 390, 381, 372, 364, 356, 349, 341, + 334, 328, 321, 315, 309, 303, 298, 293, 287, 282, 278, 273, + 269, 264, 260, 256, + ]; + + /// Computes a distortion metric of the sum of squares weighted by activity. + /// w and h should be <= 8. + #[inline(never)] + pub fn cdef_dist_kernel( + src: &PlaneRegion<'_, T>, dst: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, _cpu: CpuFeatureLevel, + ) -> u32 { + // TODO: Investigate using different constants in ssim boost for block sizes + // smaller than 8x8. + + debug_assert!(src.plane_cfg.xdec == 0); + debug_assert!(src.plane_cfg.ydec == 0); + debug_assert!(dst.plane_cfg.xdec == 0); + debug_assert!(dst.plane_cfg.ydec == 0); + + // Limit kernel to 8x8 + debug_assert!(w <= 8); + debug_assert!(h <= 8); + + // Compute the following summations. + let mut sum_s: u32 = 0; // sum(src_{i,j}) + let mut sum_d: u32 = 0; // sum(dst_{i,j}) + let mut sum_s2: u32 = 0; // sum(src_{i,j}^2) + let mut sum_d2: u32 = 0; // sum(dst_{i,j}^2) + let mut sum_sd: u32 = 0; // sum(src_{i,j} * dst_{i,j}) + for (row1, row2) in src.rows_iter().take(h).zip(dst.rows_iter()) { + for (s, d) in row1[..w].iter().zip(row2) { + let s: u32 = u32::cast_from(*s); + let d: u32 = u32::cast_from(*d); + sum_s += s; + sum_d += d; + + sum_s2 += s * s; + sum_d2 += d * d; + sum_sd += s * d; + } + } + + // To get the distortion, compute sum of squared error and apply a weight + // based on the variance of the two planes. + let sse = sum_d2 + sum_s2 - 2 * sum_sd; + + // Convert to 64-bits to avoid overflow when squaring + let sum_s = sum_s as u64; + let sum_d = sum_d as u64; + + // Calculate the variance (more accurately variance*area) of each plane. + // var[iance] = avg(X^2) - avg(X)^2 = sum(X^2) / n - sum(X)^2 / n^2 + // (n = # samples i.e. area) + // var * n = sum(X^2) - sum(X)^2 / n + // When w and h are powers of two, this can be done via shifting. + let div = AREA_DIVISORS[w * h - 1] as u64; + let div_shift = AREA_DIVISOR_BITS; + // Due to rounding, negative values can occur when w or h aren't powers of + // two. Saturate to avoid underflow. + let mut svar = sum_s2.saturating_sub( + ((sum_s * sum_s * div + (1 << div_shift >> 1)) >> div_shift) as u32, + ); + let mut dvar = sum_d2.saturating_sub( + ((sum_d * sum_d * div + (1 << div_shift >> 1)) >> div_shift) as u32, + ); + + // Scale variances up to 8x8 size. + // scaled variance = var * (8x8) / wxh + // For 8x8, this is a nop. For powers of 2, this is doable with shifting. + // TODO: It should be possible and faster to do this adjustment in ssim boost + let scale_shift = AREA_DIVISOR_BITS - 6; + svar = + ((svar as u64 * div + (1 << scale_shift >> 1)) >> scale_shift) as u32; + dvar = + ((dvar as u64 * div + (1 << scale_shift >> 1)) >> scale_shift) as u32; + + apply_ssim_boost(sse, svar, dvar, bit_depth) + } +} + +#[cfg(test)] +pub mod test { + use super::*; + use crate::cpu_features::CpuFeatureLevel; + use crate::frame::*; + use crate::tiling::Area; + use crate::util::Pixel; + + // Generate plane data for get_sad_same() + fn setup_planes() -> (Plane, Plane) { + // Two planes with different strides + let mut input_plane = Plane::new(640, 480, 0, 0, 128 + 8, 128 + 8); + let mut rec_plane = Plane::new(640, 480, 0, 0, 2 * 128 + 8, 2 * 128 + 8); + + // Make the test pattern robust to data alignment + let xpad_off = + (input_plane.cfg.xorigin - input_plane.cfg.xpad) as i32 - 8i32; + + for (i, row) in + input_plane.data.chunks_mut(input_plane.cfg.stride).enumerate() + { + for (j, pixel) in row.iter_mut().enumerate() { + let val = ((j + i) as i32 - xpad_off) & 255i32; + assert!(val >= u8::MIN.into() && val <= u8::MAX.into()); + *pixel = T::cast_from(val); + } + } + + for (i, row) in rec_plane.data.chunks_mut(rec_plane.cfg.stride).enumerate() + { + for (j, pixel) in row.iter_mut().enumerate() { + let val = (j as i32 - i as i32 - xpad_off) & 255i32; + assert!(val >= u8::MIN.into() && val <= u8::MAX.into()); + *pixel = T::cast_from(val); + } + } + + (input_plane, rec_plane) + } + + // Regression and validation test for SAD computation + fn get_sad_same_inner() { + // dynamic allocation: test + let blocks: Vec<(usize, usize, u32)> = vec![ + (4, 4, 1912), + (4, 8, 4296), + (8, 4, 3496), + (8, 8, 7824), + (8, 16, 16592), + (16, 8, 14416), + (16, 16, 31136), + (16, 32, 60064), + (32, 16, 59552), + (32, 32, 120128), + (32, 64, 186688), + (64, 32, 250176), + (64, 64, 438912), + (64, 128, 654272), + (128, 64, 1016768), + (128, 128, 1689792), + (4, 16, 8680), + (16, 4, 6664), + (8, 32, 31056), + (32, 8, 27600), + (16, 64, 93344), + (64, 16, 116384), + ]; + + let bit_depth: usize = 8; + let (input_plane, rec_plane) = setup_planes::(); + + for (w, h, distortion) in blocks { + let area = Area::StartingAt { x: 32, y: 40 }; + + let input_region = input_plane.region(area); + let rec_region = rec_plane.region(area); + + assert_eq!( + distortion, + get_sad( + &input_region, + &rec_region, + w, + h, + bit_depth, + CpuFeatureLevel::default() + ) + ); + } + } + + #[test] + fn get_sad_same_u8() { + get_sad_same_inner::(); + } + + #[test] + fn get_sad_same_u16() { + get_sad_same_inner::(); + } + + fn get_satd_same_inner() { + let blocks: Vec<(usize, usize, u32)> = vec![ + (4, 4, 1408), + (4, 8, 2016), + (8, 4, 1816), + (8, 8, 3984), + (8, 16, 5136), + (16, 8, 4864), + (16, 16, 9984), + (16, 32, 13824), + (32, 16, 13760), + (32, 32, 27952), + (32, 64, 37168), + (64, 32, 45104), + (64, 64, 84176), + (64, 128, 127920), + (128, 64, 173680), + (128, 128, 321456), + (4, 16, 3136), + (16, 4, 2632), + (8, 32, 7056), + (32, 8, 6624), + (16, 64, 18432), + (64, 16, 21312), + ]; + + let bit_depth: usize = 8; + let (input_plane, rec_plane) = setup_planes::(); + + for (w, h, distortion) in blocks { + let area = Area::StartingAt { x: 32, y: 40 }; + + let input_region = input_plane.region(area); + let rec_region = rec_plane.region(area); + + assert_eq!( + distortion, + get_satd( + &input_region, + &rec_region, + w, + h, + bit_depth, + CpuFeatureLevel::default() + ) + ); + } + } + + #[test] + fn get_satd_same_u8() { + get_satd_same_inner::(); + } + + #[test] + fn get_satd_same_u16() { + get_satd_same_inner::(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/ec.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/ec.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1152 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_camel_case_types)] + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::ec::*; + } else { + pub use self::rust::*; + } +} + +use crate::context::{CDFContext, CDFContextLog, CDFOffset}; +use bitstream_io::{BigEndian, BitWrite, BitWriter}; +use std::io; + +pub const OD_BITRES: u8 = 3; +const EC_PROB_SHIFT: u32 = 6; +const EC_MIN_PROB: u32 = 4; +type ec_window = u32; + +/// Public trait interface to a bitstream `Writer`: a `Counter` can be +/// used to count bits for cost analysis without actually storing +/// anything (using a new `WriterCounter` as a `Writer`), to record +/// tokens for later writing (using a new `WriterRecorder` as a +/// `Writer`) to write actual final bits out using a range encoder +/// (using a new `WriterEncoder` as a `Writer`). A `WriterRecorder`'s +/// contents can be replayed into a `WriterEncoder`. +pub trait Writer { + /// Write a symbol `s`, using the passed in cdf reference; leaves `cdf` unchanged + fn symbol(&mut self, s: u32, cdf: &[u16; CDF_LEN]); + /// return approximate number of fractional bits in `OD_BITRES` + /// precision to write a symbol `s` using the passed in cdf reference; + /// leaves `cdf` unchanged + fn symbol_bits(&self, s: u32, cdf: &[u16]) -> u32; + /// Write a symbol `s`, using the passed in cdf reference; updates the referenced cdf. + fn symbol_with_update( + &mut self, s: u32, cdf: CDFOffset, log: &mut CDFContextLog, + fc: &mut CDFContext, + ); + /// Write a bool using passed in probability + fn bool(&mut self, val: bool, f: u16); + /// Write a single bit with flat probability + fn bit(&mut self, bit: u16); + /// Write literal `bits` with flat probability + fn literal(&mut self, bits: u8, s: u32); + /// Write passed `level` as a golomb code + fn write_golomb(&mut self, level: u32); + /// Write a value `v` in `[0, n-1]` quasi-uniformly + fn write_quniform(&mut self, n: u32, v: u32); + /// Return fractional bits needed to write a value `v` in `[0, n-1]` + /// quasi-uniformly + fn count_quniform(&self, n: u32, v: u32) -> u32; + /// Write symbol `v` in `[0, n-1]` with parameter `k` as finite subexponential + fn write_subexp(&mut self, n: u32, k: u8, v: u32); + /// Return fractional bits needed to write symbol v in `[0, n-1]` with + /// parameter k as finite subexponential + fn count_subexp(&self, n: u32, k: u8, v: u32) -> u32; + /// Write symbol `v` in `[0, n-1]` with parameter `k` as finite + /// subexponential based on a reference `r` also in `[0, n-1]`. + fn write_unsigned_subexp_with_ref(&mut self, v: u32, mx: u32, k: u8, r: u32); + /// Return fractional bits needed to write symbol `v` in `[0, n-1]` with + /// parameter `k` as finite subexponential based on a reference `r` + /// also in `[0, n-1]`. + fn count_unsigned_subexp_with_ref( + &self, v: u32, mx: u32, k: u8, r: u32, + ) -> u32; + /// Write symbol v in `[-(n-1), n-1]` with parameter k as finite + /// subexponential based on a reference ref also in `[-(n-1), n-1]`. + fn write_signed_subexp_with_ref( + &mut self, v: i32, low: i32, high: i32, k: u8, r: i32, + ); + /// Return fractional bits needed to write symbol `v` in `[-(n-1), n-1]` + /// with parameter `k` as finite subexponential based on a reference + /// `r` also in `[-(n-1), n-1]`. + fn count_signed_subexp_with_ref( + &self, v: i32, low: i32, high: i32, k: u8, r: i32, + ) -> u32; + /// Return current length of range-coded bitstream in integer bits + fn tell(&mut self) -> u32; + /// Return current length of range-coded bitstream in fractional + /// bits with `OD_BITRES` decimal precision + fn tell_frac(&mut self) -> u32; + /// Save current point in coding/recording to a checkpoint + fn checkpoint(&mut self) -> WriterCheckpoint; + /// Restore saved position in coding/recording from a checkpoint + fn rollback(&mut self, _: &WriterCheckpoint); + /// Add additional bits from rate estimators without coding a real symbol + fn add_bits_frac(&mut self, bits_frac: u32); +} + +/// `StorageBackend` is an internal trait used to tie a specific `Writer` +/// implementation's storage to the generic `Writer`. It would be +/// private, but Rust is deprecating 'private trait in a public +/// interface' support. +pub trait StorageBackend { + /// Store partially-computed range code into given storage backend + fn store(&mut self, fl: u16, fh: u16, nms: u16); + /// Return bit-length of encoded stream to date + fn stream_bits(&mut self) -> usize; + /// Backend implementation of checkpoint to pass through Writer interface + fn checkpoint(&mut self) -> WriterCheckpoint; + /// Backend implementation of rollback to pass through Writer interface + fn rollback(&mut self, _: &WriterCheckpoint); +} + +#[derive(Debug, Clone)] +pub struct WriterBase { + /// The number of values in the current range. + rng: u16, + /// The number of bits of data in the current value. + cnt: i16, + #[cfg(feature = "desync_finder")] + /// Debug enable flag + debug: bool, + /// Extra offset added to `tell()` and `tell_frac()` to approximate costs + /// of actually coding a symbol + fake_bits_frac: u32, + /// Use-specific storage + s: S, +} + +#[derive(Debug, Clone)] +pub struct WriterCounter { + /// Bits that would be shifted out to date + bits: usize, +} + +#[derive(Debug, Clone)] +pub struct WriterRecorder { + /// Storage for tokens + storage: Vec<(u16, u16, u16)>, + /// Bits that would be shifted out to date + bits: usize, +} + +#[derive(Debug, Clone)] +pub struct WriterEncoder { + /// A buffer for output bytes with their associated carry flags. + precarry: Vec, + /// The low end of the current range. + low: ec_window, +} + +#[derive(Clone)] +pub struct WriterCheckpoint { + /// Stream length coded/recorded to date, in the unit used by the Writer, + /// which may be bytes or bits. This depends on the assumption + /// that a Writer will only ever restore its own Checkpoint. + stream_size: usize, + /// To be defined by backend + backend_var: usize, + /// Saved number of values in the current range. + rng: u16, + /// Saved number of bits of data in the current value. + cnt: i16, +} + +/// Constructor for a counting Writer +impl WriterCounter { + #[inline] + pub const fn new() -> WriterBase { + WriterBase::new(WriterCounter { bits: 0 }) + } +} + +/// Constructor for a recording Writer +impl WriterRecorder { + #[inline] + pub const fn new() -> WriterBase { + WriterBase::new(WriterRecorder { storage: Vec::new(), bits: 0 }) + } +} + +/// Constructor for a encoding Writer +impl WriterEncoder { + #[inline] + pub const fn new() -> WriterBase { + WriterBase::new(WriterEncoder { precarry: Vec::new(), low: 0 }) + } +} + +/// The Counter stores nothing we write to it, it merely counts the +/// bit usage like in an Encoder for cost analysis. +impl StorageBackend for WriterBase { + #[inline] + fn store(&mut self, fl: u16, fh: u16, nms: u16) { + let (_l, r) = self.lr_compute(fl, fh, nms); + let d = r.leading_zeros() as usize; + + self.s.bits += d; + self.rng = r << d; + } + #[inline] + fn stream_bits(&mut self) -> usize { + self.s.bits + } + #[inline] + fn checkpoint(&mut self) -> WriterCheckpoint { + WriterCheckpoint { + stream_size: self.s.bits, + backend_var: 0, + rng: self.rng, + // We do not use `cnt` within Counter, but setting it here allows the compiler + // to do a 32-bit merged load/store. + cnt: self.cnt, + } + } + #[inline] + fn rollback(&mut self, checkpoint: &WriterCheckpoint) { + self.rng = checkpoint.rng; + self.s.bits = checkpoint.stream_size; + } +} + +/// The Recorder does not produce a range-coded bitstream, but it +/// still tracks the range coding progress like in an Encoder, as it +/// neds to be able to report bit costs for RDO decisions. It stores a +/// pair of mostly-computed range coding values per token recorded. +impl StorageBackend for WriterBase { + #[inline] + fn store(&mut self, fl: u16, fh: u16, nms: u16) { + let (_l, r) = self.lr_compute(fl, fh, nms); + let d = r.leading_zeros() as usize; + + self.s.bits += d; + self.rng = r << d; + self.s.storage.push((fl, fh, nms)); + } + #[inline] + fn stream_bits(&mut self) -> usize { + self.s.bits + } + #[inline] + fn checkpoint(&mut self) -> WriterCheckpoint { + WriterCheckpoint { + stream_size: self.s.bits, + backend_var: self.s.storage.len(), + rng: self.rng, + cnt: self.cnt, + } + } + #[inline] + fn rollback(&mut self, checkpoint: &WriterCheckpoint) { + self.rng = checkpoint.rng; + self.cnt = checkpoint.cnt; + self.s.bits = checkpoint.stream_size; + self.s.storage.truncate(checkpoint.backend_var); + } +} + +/// An Encoder produces an actual range-coded bitstream from passed in +/// tokens. It does not retain any information about the coded +/// tokens, only the resulting bitstream, and so it cannot be replayed +/// (only checkpointed and rolled back). +impl StorageBackend for WriterBase { + fn store(&mut self, fl: u16, fh: u16, nms: u16) { + let (l, r) = self.lr_compute(fl, fh, nms); + let mut low = l + self.s.low; + let mut c = self.cnt; + let d = r.leading_zeros() as usize; + let mut s = c + (d as i16); + + if s >= 0 { + c += 16; + let mut m = (1 << c) - 1; + if s >= 8 { + self.s.precarry.push((low >> c) as u16); + low &= m; + c -= 8; + m >>= 8; + } + self.s.precarry.push((low >> c) as u16); + s = c + (d as i16) - 24; + low &= m; + } + self.s.low = low << d; + self.rng = r << d; + self.cnt = s; + } + #[inline] + fn stream_bits(&mut self) -> usize { + self.s.precarry.len() * 8 + } + #[inline] + fn checkpoint(&mut self) -> WriterCheckpoint { + WriterCheckpoint { + stream_size: self.s.precarry.len(), + backend_var: self.s.low as usize, + rng: self.rng, + cnt: self.cnt, + } + } + fn rollback(&mut self, checkpoint: &WriterCheckpoint) { + self.rng = checkpoint.rng; + self.cnt = checkpoint.cnt; + self.s.low = checkpoint.backend_var as ec_window; + self.s.precarry.truncate(checkpoint.stream_size); + } +} + +/// A few local helper functions needed by the Writer that are not +/// part of the public interface. +impl WriterBase { + /// Internal constructor called by the subtypes that implement the + /// actual encoder and Recorder. + #[inline] + #[cfg(not(feature = "desync_finder"))] + const fn new(storage: S) -> Self { + WriterBase { rng: 0x8000, cnt: -9, fake_bits_frac: 0, s: storage } + } + + #[inline] + #[cfg(feature = "desync_finder")] + fn new(storage: S) -> Self { + WriterBase { + rng: 0x8000, + cnt: -9, + debug: std::env::var_os("RAV1E_DEBUG").is_some(), + fake_bits_frac: 0, + s: storage, + } + } + + /// Compute low and range values from token cdf values and local state + const fn lr_compute(&self, fl: u16, fh: u16, nms: u16) -> (ec_window, u16) { + let r = self.rng as u32; + debug_assert!(32768 <= r); + let mut u = (((r >> 8) * (fl as u32 >> EC_PROB_SHIFT)) + >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB * nms as u32; + if fl >= 32768 { + u = r; + } + let v = (((r >> 8) * (fh as u32 >> EC_PROB_SHIFT)) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB * (nms - 1) as u32; + (r - u, (u - v) as u16) + } + + /// Given the current total integer number of bits used and the current value of + /// rng, computes the fraction number of bits used to `OD_BITRES` precision. + /// This is used by `od_ec_enc_tell_frac()` and `od_ec_dec_tell_frac()`. + /// `nbits_total`: The number of whole bits currently used, i.e., the value + /// returned by `od_ec_enc_tell()` or `od_ec_dec_tell()`. + /// `rng`: The current value of rng from either the encoder or decoder state. + /// Return: The number of bits scaled by `2**OD_BITRES`. + /// This will always be slightly larger than the exact value (e.g., all + /// rounding error is in the positive direction). + fn frac_compute(nbits_total: u32, mut rng: u32) -> u32 { + // To handle the non-integral number of bits still left in the encoder/decoder + // state, we compute the worst-case number of bits of val that must be + // encoded to ensure that the value is inside the range for any possible + // subsequent bits. + // The computation here is independent of val itself (the decoder does not + // even track that value), even though the real number of bits used after + // od_ec_enc_done() may be 1 smaller if rng is a power of two and the + // corresponding trailing bits of val are all zeros. + // If we did try to track that special case, then coding a value with a + // probability of 1/(1 << n) might sometimes appear to use more than n bits. + // This may help explain the surprising result that a newly initialized + // encoder or decoder claims to have used 1 bit. + let nbits = nbits_total << OD_BITRES; + let mut l = 0; + for _ in 0..OD_BITRES { + rng = (rng * rng) >> 15; + let b = rng >> 16; + l = (l << 1) | b; + rng >>= b; + } + nbits - l + } + + const fn recenter(r: u32, v: u32) -> u32 { + if v > (r << 1) { + v + } else if v >= r { + (v - r) << 1 + } else { + ((r - v) << 1) - 1 + } + } + + #[cfg(feature = "desync_finder")] + fn print_backtrace(&self, s: u32) { + let mut depth = 3; + backtrace::trace(|frame| { + let ip = frame.ip(); + + depth -= 1; + + if depth == 0 { + backtrace::resolve(ip, |symbol| { + if let Some(name) = symbol.name() { + println!("Writing symbol {} from {}", s, name); + } + }); + false + } else { + true + } + }); + } +} + +/// Replay implementation specific to the Recorder +impl WriterBase { + /// Replays the partially-computed range tokens out of the Recorder's + /// storage and into the passed in Writer, which may be an Encoder + /// or another Recorder. Clears the Recorder after replay. + pub fn replay(&mut self, dest: &mut dyn StorageBackend) { + for &(fl, fh, nms) in &self.s.storage { + dest.store(fl, fh, nms); + } + self.rng = 0x8000; + self.cnt = -9; + self.s.storage.truncate(0); + self.s.bits = 0; + } +} + +/// Done implementation specific to the Encoder +impl WriterBase { + /// Indicates that there are no more symbols to encode. Flushes + /// remaining state into coding and returns a vector containing the + /// final bitstream. + pub fn done(&mut self) -> Vec { + // We output the minimum number of bits that ensures that the symbols encoded + // thus far will be decoded correctly regardless of the bits that follow. + let l = self.s.low; + let mut c = self.cnt; + let mut s = 10; + let m = 0x3FFF; + let mut e = ((l + m) & !m) | (m + 1); + + s += c; + + if s > 0 { + let mut n = (1 << (c + 16)) - 1; + + loop { + self.s.precarry.push((e >> (c + 16)) as u16); + e &= n; + s -= 8; + c -= 8; + n >>= 8; + + if s <= 0 { + break; + } + } + } + + let mut c = 0; + let mut offs = self.s.precarry.len(); + // dynamic allocation: grows during encode + let mut out = vec![0_u8; offs]; + while offs > 0 { + offs -= 1; + c += self.s.precarry[offs]; + out[offs] = c as u8; + c >>= 8; + } + + out + } +} + +/// Generic/shared implementation for `Writer`s with `StorageBackend`s +/// (ie, `Encoder`s and `Recorder`s) +impl Writer for WriterBase +where + WriterBase: StorageBackend, +{ + /// Encode a single binary value. + /// `val`: The value to encode (0 or 1). + /// `f`: The probability that the val is one, scaled by 32768. + fn bool(&mut self, val: bool, f: u16) { + debug_assert!(0 < f); + debug_assert!(f < 32768); + self.symbol(u32::from(val), &[f, 0]); + } + /// Encode a single boolean value. + /// + /// - `val`: The value to encode (`false` or `true`). + /// - `f`: The probability that the `val` is `true`, scaled by `32768`. + fn bit(&mut self, bit: u16) { + self.bool(bit == 1, 16384); + } + // fake add bits + fn add_bits_frac(&mut self, bits_frac: u32) { + self.fake_bits_frac += bits_frac + } + /// Encode a literal bitstring, bit by bit in MSB order, with flat + /// probability. + /// + /// - 'bits': Length of bitstring + /// - 's': Bit string to encode + fn literal(&mut self, bits: u8, s: u32) { + for bit in (0..bits).rev() { + self.bit((1 & (s >> bit)) as u16); + } + } + /// Encodes a symbol given a cumulative distribution function (CDF) table in Q15. + /// + /// - `s`: The index of the symbol to encode. + /// - `cdf`: The CDF, such that symbol s falls in the range + /// `[s > 0 ? cdf[s - 1] : 0, cdf[s])`. + /// The values must be monotonically non-decreasing, and the last value + /// must be greater than 32704. There should be at most 16 values. + /// The lower 6 bits of the last value hold the count. + #[inline(always)] + fn symbol(&mut self, s: u32, cdf: &[u16; CDF_LEN]) { + debug_assert!(cdf[cdf.len() - 1] < (1 << EC_PROB_SHIFT)); + let s = s as usize; + debug_assert!(s < cdf.len()); + // The above is stricter than the following overflow check: s <= cdf.len() + let nms = cdf.len() - s; + let fl = if s > 0 { + // SAFETY: We asserted that s is less than the length of the cdf + unsafe { *cdf.get_unchecked(s - 1) } + } else { + 32768 + }; + // SAFETY: We asserted that s is less than the length of the cdf + let fh = unsafe { *cdf.get_unchecked(s) }; + debug_assert!((fh >> EC_PROB_SHIFT) <= (fl >> EC_PROB_SHIFT)); + debug_assert!(fl <= 32768); + self.store(fl, fh, nms as u16); + } + /// Encodes a symbol given a cumulative distribution function (CDF) + /// table in Q15, then updates the CDF probabilities to reflect we've + /// written one more symbol 's'. + /// + /// - `s`: The index of the symbol to encode. + /// - `cdf`: The CDF, such that symbol s falls in the range + /// `[s > 0 ? cdf[s - 1] : 0, cdf[s])`. + /// The values must be monotonically non-decreasing, and the last value + /// must be greater 32704. There should be at most 16 values. + /// The lower 6 bits of the last value hold the count. + fn symbol_with_update( + &mut self, s: u32, cdf: CDFOffset, log: &mut CDFContextLog, + fc: &mut CDFContext, + ) { + #[cfg(feature = "desync_finder")] + { + if self.debug { + self.print_backtrace(s); + } + } + let cdf = log.push(fc, cdf); + self.symbol(s, cdf); + + update_cdf(cdf, s); + } + /// Returns approximate cost for a symbol given a cumulative + /// distribution function (CDF) table and current write state. + /// + /// - `s`: The index of the symbol to encode. + /// - `cdf`: The CDF, such that symbol s falls in the range + /// `[s > 0 ? cdf[s - 1] : 0, cdf[s])`. + /// The values must be monotonically non-decreasing, and the last value + /// must be greater than 32704. There should be at most 16 values. + /// The lower 6 bits of the last value hold the count. + fn symbol_bits(&self, s: u32, cdf: &[u16]) -> u32 { + let mut bits = 0; + debug_assert!(cdf[cdf.len() - 1] < (1 << EC_PROB_SHIFT)); + debug_assert!(32768 <= self.rng); + let rng = (self.rng >> 8) as u32; + let fh = cdf[s as usize] as u32 >> EC_PROB_SHIFT; + let r: u32 = if s > 0 { + let fl = cdf[s as usize - 1] as u32 >> EC_PROB_SHIFT; + ((rng * fl) >> (7 - EC_PROB_SHIFT)) - ((rng * fh) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB + } else { + let nms1 = cdf.len() as u32 - s - 1; + self.rng as u32 + - ((rng * fh) >> (7 - EC_PROB_SHIFT)) + - nms1 * EC_MIN_PROB + }; + + // The 9 here counteracts the offset of -9 baked into cnt. Don't include a termination bit. + let pre = Self::frac_compute((self.cnt + 9) as u32, self.rng as u32); + let d = r.leading_zeros() - 16; + let mut c = self.cnt; + let mut sh = c + (d as i16); + if sh >= 0 { + c += 16; + if sh >= 8 { + bits += 8; + c -= 8; + } + bits += 8; + sh = c + (d as i16) - 24; + } + // The 9 here counteracts the offset of -9 baked into cnt. Don't include a termination bit. + Self::frac_compute((bits + sh + 9) as u32, r << d) - pre + } + /// Encode a golomb to the bitstream. + /// + /// - 'level': passed in value to encode + fn write_golomb(&mut self, level: u32) { + let x = level + 1; + let length = 32 - x.leading_zeros(); + + for _ in 0..length - 1 { + self.bit(0); + } + + for i in (0..length).rev() { + self.bit(((x >> i) & 0x01) as u16); + } + } + /// Write a value `v` in `[0, n-1]` quasi-uniformly + /// - `n`: size of interval + /// - `v`: value to encode + fn write_quniform(&mut self, n: u32, v: u32) { + if n > 1 { + let l = 32 - n.leading_zeros() as u8; + let m = (1 << l) - n; + if v < m { + self.literal(l - 1, v); + } else { + self.literal(l - 1, m + ((v - m) >> 1)); + self.literal(1, (v - m) & 1); + } + } + } + /// Returns `QOD_BITRES` bits for a value `v` in `[0, n-1]` quasi-uniformly + /// - `n`: size of interval + /// - `v`: value to encode + fn count_quniform(&self, n: u32, v: u32) -> u32 { + let mut bits = 0; + if n > 1 { + let l = 32 - n.leading_zeros(); + let m = (1 << l) - n; + bits += (l - 1) << OD_BITRES; + if v >= m { + bits += 1 << OD_BITRES; + } + } + bits + } + /// Write symbol `v` in `[0, n-1]` with parameter `k` as finite subexponential + /// + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `v`: value to encode + fn write_subexp(&mut self, n: u32, k: u8, v: u32) { + let mut i = 0; + let mut mk = 0; + loop { + let b = if i != 0 { k + i - 1 } else { k }; + let a = 1 << b; + if n <= mk + 3 * a { + self.write_quniform(n - mk, v - mk); + break; + } else { + let t = v >= mk + a; + self.bool(t, 16384); + if t { + i += 1; + mk += a; + } else { + self.literal(b, v - mk); + break; + } + } + } + } + /// Returns `QOD_BITRES` bits for symbol `v` in `[0, n-1]` with parameter `k` + /// as finite subexponential + /// + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `v`: value to encode + fn count_subexp(&self, n: u32, k: u8, v: u32) -> u32 { + let mut i = 0; + let mut mk = 0; + let mut bits = 0; + loop { + let b = if i != 0 { k + i - 1 } else { k }; + let a = 1 << b; + if n <= mk + 3 * a { + bits += self.count_quniform(n - mk, v - mk); + break; + } else { + let t = v >= mk + a; + bits += 1 << OD_BITRES; + if t { + i += 1; + mk += a; + } else { + bits += (b as u32) << OD_BITRES; + break; + } + } + } + bits + } + /// Write symbol `v` in `[0, n-1]` with parameter `k` as finite + /// subexponential based on a reference `r` also in `[0, n-1]`. + /// + /// - `v`: value to encode + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `r`: reference + fn write_unsigned_subexp_with_ref(&mut self, v: u32, n: u32, k: u8, r: u32) { + if (r << 1) <= n { + self.write_subexp(n, k, Self::recenter(r, v)); + } else { + self.write_subexp(n, k, Self::recenter(n - 1 - r, n - 1 - v)); + } + } + /// Returns `QOD_BITRES` bits for symbol `v` in `[0, n-1]` + /// with parameter `k` as finite subexponential based on a + /// reference `r` also in `[0, n-1]`. + /// + /// - `v`: value to encode + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `r`: reference + fn count_unsigned_subexp_with_ref( + &self, v: u32, n: u32, k: u8, r: u32, + ) -> u32 { + if (r << 1) <= n { + self.count_subexp(n, k, Self::recenter(r, v)) + } else { + self.count_subexp(n, k, Self::recenter(n - 1 - r, n - 1 - v)) + } + } + /// Write symbol `v` in `[-(n-1), n-1]` with parameter `k` as finite + /// subexponential based on a reference `r` also in `[-(n-1), n-1]`. + /// + /// - `v`: value to encode + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `r`: reference + fn write_signed_subexp_with_ref( + &mut self, v: i32, low: i32, high: i32, k: u8, r: i32, + ) { + self.write_unsigned_subexp_with_ref( + (v - low) as u32, + (high - low) as u32, + k, + (r - low) as u32, + ); + } + /// Returns `QOD_BITRES` bits for symbol `v` in `[-(n-1), n-1]` + /// with parameter `k` as finite subexponential based on a + /// reference `r` also in `[-(n-1), n-1]`. + /// + /// - `v`: value to encode + /// - `n`: size of interval + /// - `k`: "parameter" + /// - `r`: reference + fn count_signed_subexp_with_ref( + &self, v: i32, low: i32, high: i32, k: u8, r: i32, + ) -> u32 { + self.count_unsigned_subexp_with_ref( + (v - low) as u32, + (high - low) as u32, + k, + (r - low) as u32, + ) + } + /// Returns the number of bits "used" by the encoded symbols so far. + /// This same number can be computed in either the encoder or the + /// decoder, and is suitable for making coding decisions. The value + /// will be the same whether using an `Encoder` or `Recorder`. + /// + /// Return: The integer number of bits. + /// This will always be slightly larger than the exact value (e.g., all + /// rounding error is in the positive direction). + fn tell(&mut self) -> u32 { + // The 10 here counteracts the offset of -9 baked into cnt, and adds 1 extra + // bit, which we reserve for terminating the stream. + (((self.stream_bits()) as i32) + (self.cnt as i32) + 10) as u32 + + (self.fake_bits_frac >> 8) + } + /// Returns the number of bits "used" by the encoded symbols so far. + /// This same number can be computed in either the encoder or the + /// decoder, and is suitable for making coding decisions. The value + /// will be the same whether using an `Encoder` or `Recorder`. + /// + /// Return: The number of bits scaled by `2**OD_BITRES`. + /// This will always be slightly larger than the exact value (e.g., all + /// rounding error is in the positive direction). + fn tell_frac(&mut self) -> u32 { + Self::frac_compute(self.tell(), self.rng as u32) + self.fake_bits_frac + } + /// Save current point in coding/recording to a checkpoint that can + /// be restored later. A `WriterCheckpoint` can be generated for an + /// `Encoder` or `Recorder`, but can only be used to rollback the `Writer` + /// instance from which it was generated. + fn checkpoint(&mut self) -> WriterCheckpoint { + StorageBackend::checkpoint(self) + } + /// Roll back a given `Writer` to the state saved in the `WriterCheckpoint` + /// + /// - 'wc': Saved `Writer` state/posiiton to restore + fn rollback(&mut self, wc: &WriterCheckpoint) { + StorageBackend::rollback(self, wc) + } +} + +pub trait BCodeWriter { + fn recenter_nonneg(&mut self, r: u16, v: u16) -> u16; + fn recenter_finite_nonneg(&mut self, n: u16, r: u16, v: u16) -> u16; + /// # Errors + /// + /// - Returns `std::io::Error` if the writer cannot be written to. + fn write_quniform(&mut self, n: u16, v: u16) -> Result<(), std::io::Error>; + /// # Errors + /// + /// - Returns `std::io::Error` if the writer cannot be written to. + fn write_subexpfin( + &mut self, n: u16, k: u16, v: u16, + ) -> Result<(), std::io::Error>; + /// # Errors + /// + /// - Returns `std::io::Error` if the writer cannot be written to. + fn write_refsubexpfin( + &mut self, n: u16, k: u16, r: i16, v: i16, + ) -> Result<(), std::io::Error>; + /// # Errors + /// + /// - Returns `std::io::Error` if the writer cannot be written to. + fn write_s_refsubexpfin( + &mut self, n: u16, k: u16, r: i16, v: i16, + ) -> Result<(), std::io::Error>; +} + +impl BCodeWriter for BitWriter { + fn recenter_nonneg(&mut self, r: u16, v: u16) -> u16 { + /* Recenters a non-negative literal v around a reference r */ + if v > (r << 1) { + v + } else if v >= r { + (v - r) << 1 + } else { + ((r - v) << 1) - 1 + } + } + fn recenter_finite_nonneg(&mut self, n: u16, r: u16, v: u16) -> u16 { + /* Recenters a non-negative literal v in [0, n-1] around a + reference r also in [0, n-1] */ + if (r << 1) <= n { + self.recenter_nonneg(r, v) + } else { + self.recenter_nonneg(n - 1 - r, n - 1 - v) + } + } + fn write_quniform(&mut self, n: u16, v: u16) -> Result<(), std::io::Error> { + if n > 1 { + let l = 16 - n.leading_zeros() as u8; + let m = (1 << l) - n; + if v < m { + self.write_var(l as u32 - 1, v) + } else { + self.write_var(l as u32 - 1, m + ((v - m) >> 1))?; + self.write::<1, u16>((v - m) & 1) + } + } else { + Ok(()) + } + } + fn write_subexpfin( + &mut self, n: u16, k: u16, v: u16, + ) -> Result<(), std::io::Error> { + /* Finite subexponential code that codes a symbol v in [0, n-1] with parameter k */ + let mut i = 0; + let mut mk = 0; + loop { + let b = if i > 0 { k + i - 1 } else { k }; + let a = 1 << b; + if n <= mk + 3 * a { + return self.write_quniform(n - mk, v - mk); + } else { + let t = v >= mk + a; + self.write_bit(t)?; + if t { + i += 1; + mk += a; + } else { + return self.write_var(b as u32, v - mk); + } + } + } + } + fn write_refsubexpfin( + &mut self, n: u16, k: u16, r: i16, v: i16, + ) -> Result<(), std::io::Error> { + /* Finite subexponential code that codes a symbol v in [0, n-1] with + parameter k based on a reference ref also in [0, n-1]. + Recenters symbol around r first and then uses a finite subexponential code. */ + let recentered_v = self.recenter_finite_nonneg(n, r as u16, v as u16); + self.write_subexpfin(n, k, recentered_v) + } + fn write_s_refsubexpfin( + &mut self, n: u16, k: u16, r: i16, v: i16, + ) -> Result<(), std::io::Error> { + /* Signed version of the above function */ + self.write_refsubexpfin( + (n << 1) - 1, + k, + r + (n - 1) as i16, + v + (n - 1) as i16, + ) + } +} + +pub(crate) fn cdf_to_pdf( + cdf: &[u16; CDF_LEN], +) -> [u16; CDF_LEN] { + let mut pdf = [0; CDF_LEN]; + let mut z = 32768u16 >> EC_PROB_SHIFT; + for (d, &a) in pdf.iter_mut().zip(cdf.iter()) { + *d = z - (a >> EC_PROB_SHIFT); + z = a >> EC_PROB_SHIFT; + } + pdf +} + +pub(crate) mod rust { + // Function to update the CDF for Writer calls that do so. + #[inline] + pub fn update_cdf(cdf: &mut [u16; N], val: u32) { + use crate::context::CDF_LEN_MAX; + let nsymbs = cdf.len(); + let mut rate = 3 + (nsymbs >> 1).min(2); + if let Some(count) = cdf.last_mut() { + rate += (*count >> 4) as usize; + *count += 1 - (*count >> 5); + } else { + return; + } + // Single loop (faster) + for (i, v) in + cdf[..nsymbs - 1].iter_mut().enumerate().take(CDF_LEN_MAX - 1) + { + if i as u32 >= val { + *v -= *v >> rate; + } else { + *v += (32768 - *v) >> rate; + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + const WINDOW_SIZE: i16 = 32; + const LOTS_OF_BITS: i16 = 0x4000; + + #[derive(Debug)] + struct Reader<'a> { + buf: &'a [u8], + bptr: usize, + dif: ec_window, + rng: u16, + cnt: i16, + } + + impl<'a> Reader<'a> { + fn new(buf: &'a [u8]) -> Self { + let mut r = Reader { + buf, + bptr: 0, + dif: (1 << (WINDOW_SIZE - 1)) - 1, + rng: 0x8000, + cnt: -15, + }; + r.refill(); + r + } + + fn refill(&mut self) { + let mut s = WINDOW_SIZE - 9 - (self.cnt + 15); + while s >= 0 && self.bptr < self.buf.len() { + assert!(s <= WINDOW_SIZE - 8); + self.dif ^= (self.buf[self.bptr] as ec_window) << s; + self.cnt += 8; + s -= 8; + self.bptr += 1; + } + if self.bptr >= self.buf.len() { + self.cnt = LOTS_OF_BITS; + } + } + + fn normalize(&mut self, dif: ec_window, rng: u32) { + assert!(rng <= 65536); + let d = rng.leading_zeros() - 16; + //let d = 16 - (32-rng.leading_zeros()); + self.cnt -= d as i16; + /*This is equivalent to shifting in 1's instead of 0's.*/ + self.dif = ((dif + 1) << d) - 1; + self.rng = (rng << d) as u16; + if self.cnt < 0 { + self.refill() + } + } + + fn bool(&mut self, f: u32) -> bool { + assert!(f < 32768); + let r = self.rng as u32; + assert!(self.dif >> (WINDOW_SIZE - 16) < r); + assert!(32768 <= r); + let v = (((r >> 8) * (f >> EC_PROB_SHIFT)) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB; + let vw = v << (WINDOW_SIZE - 16); + let (dif, rng, ret) = if self.dif >= vw { + (self.dif - vw, r - v, false) + } else { + (self.dif, v, true) + }; + self.normalize(dif, rng); + ret + } + + fn symbol(&mut self, icdf: &[u16]) -> i32 { + let r = self.rng as u32; + assert!(self.dif >> (WINDOW_SIZE - 16) < r); + assert!(32768 <= r); + let n = icdf.len() as u32 - 1; + let c = self.dif >> (WINDOW_SIZE - 16); + let mut v = self.rng as u32; + let mut ret = 0i32; + let mut u = v; + v = ((r >> 8) * (icdf[ret as usize] as u32 >> EC_PROB_SHIFT)) + >> (7 - EC_PROB_SHIFT); + v += EC_MIN_PROB * (n - ret as u32); + while c < v { + u = v; + ret += 1; + v = ((r >> 8) * (icdf[ret as usize] as u32 >> EC_PROB_SHIFT)) + >> (7 - EC_PROB_SHIFT); + v += EC_MIN_PROB * (n - ret as u32); + } + assert!(v < u); + assert!(u <= r); + let new_dif = self.dif - (v << (WINDOW_SIZE - 16)); + self.normalize(new_dif, u - v); + ret + } + } + + #[test] + fn booleans() { + let mut w = WriterEncoder::new(); + + w.bool(false, 1); + w.bool(true, 2); + w.bool(false, 3); + w.bool(true, 1); + w.bool(true, 2); + w.bool(false, 3); + + let b = w.done(); + + let mut r = Reader::new(&b); + + assert!(!r.bool(1)); + assert!(r.bool(2)); + assert!(!r.bool(3)); + assert!(r.bool(1)); + assert!(r.bool(2)); + assert!(!r.bool(3)); + } + + #[test] + fn cdf() { + let cdf = [7296, 3819, 1716, 0]; + + let mut w = WriterEncoder::new(); + + w.symbol(0, &cdf); + w.symbol(0, &cdf); + w.symbol(0, &cdf); + w.symbol(1, &cdf); + w.symbol(1, &cdf); + w.symbol(1, &cdf); + w.symbol(2, &cdf); + w.symbol(2, &cdf); + w.symbol(2, &cdf); + + let b = w.done(); + + let mut r = Reader::new(&b); + + assert_eq!(r.symbol(&cdf), 0); + assert_eq!(r.symbol(&cdf), 0); + assert_eq!(r.symbol(&cdf), 0); + assert_eq!(r.symbol(&cdf), 1); + assert_eq!(r.symbol(&cdf), 1); + assert_eq!(r.symbol(&cdf), 1); + assert_eq!(r.symbol(&cdf), 2); + assert_eq!(r.symbol(&cdf), 2); + assert_eq!(r.symbol(&cdf), 2); + } + + #[test] + fn mixed() { + let cdf = [7296, 3819, 1716, 0]; + + let mut w = WriterEncoder::new(); + + w.symbol(0, &cdf); + w.bool(true, 2); + w.symbol(0, &cdf); + w.bool(true, 2); + w.symbol(0, &cdf); + w.bool(true, 2); + w.symbol(1, &cdf); + w.bool(true, 1); + w.symbol(1, &cdf); + w.bool(false, 2); + w.symbol(1, &cdf); + w.symbol(2, &cdf); + w.symbol(2, &cdf); + w.symbol(2, &cdf); + + let b = w.done(); + + let mut r = Reader::new(&b); + + assert_eq!(r.symbol(&cdf), 0); + assert!(r.bool(2)); + assert_eq!(r.symbol(&cdf), 0); + assert!(r.bool(2)); + assert_eq!(r.symbol(&cdf), 0); + assert!(r.bool(2)); + assert_eq!(r.symbol(&cdf), 1); + assert!(r.bool(1)); + assert_eq!(r.symbol(&cdf), 1); + assert!(!r.bool(2)); + assert_eq!(r.symbol(&cdf), 1); + assert_eq!(r.symbol(&cdf), 2); + assert_eq!(r.symbol(&cdf), 2); + assert_eq!(r.symbol(&cdf), 2); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3858 @@ +// Copyright (c) 2018-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::collections::VecDeque; +use std::io::Write; +use std::mem::MaybeUninit; +use std::sync::Arc; +use std::{fmt, io, mem}; + +use arg_enum_proc_macro::ArgEnum; +use arrayvec::*; +use bitstream_io::{BigEndian, BitWrite, BitWriter}; +use rayon::iter::*; + +use crate::activity::*; +use crate::api::*; +use crate::cdef::*; +use crate::context::*; +use crate::deblock::*; +use crate::ec::*; +use crate::frame::*; +use crate::header::*; +use crate::lrf::*; +use crate::mc::{FilterMode, MotionVector}; +use crate::me::*; +use crate::partition::PartitionType::*; +use crate::partition::RefType::*; +use crate::partition::*; +use crate::predict::{ + luma_ac, AngleDelta, IntraEdgeFilterParameters, IntraParam, PredictionMode, +}; +use crate::quantize::*; +use crate::rate::{ + QuantizerParameters, FRAME_SUBTYPE_I, FRAME_SUBTYPE_P, QSCALE, +}; +use crate::rdo::*; +use crate::segmentation::*; +use crate::serialize::{Deserialize, Serialize}; +use crate::stats::EncoderStats; +use crate::tiling::*; +use crate::transform::*; +use crate::util::*; +use crate::wasm_bindgen::*; + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum CDEFSearchMethod { + PickFromQ, + FastSearch, + FullSearch, +} + +#[inline(always)] +fn poly2(q: f32, a: f32, b: f32, c: f32, max: i32) -> i32 { + clamp((q * q).mul_add(a, q.mul_add(b, c)).round() as i32, 0, max) +} + +pub static TEMPORAL_DELIMITER: [u8; 2] = [0x12, 0x00]; + +const MAX_NUM_TEMPORAL_LAYERS: usize = 8; +const MAX_NUM_SPATIAL_LAYERS: usize = 4; +const MAX_NUM_OPERATING_POINTS: usize = + MAX_NUM_TEMPORAL_LAYERS * MAX_NUM_SPATIAL_LAYERS; + +/// Size of blocks for the importance computation, in pixels. +pub const IMPORTANCE_BLOCK_SIZE: usize = + 1 << (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT); + +#[derive(Debug, Clone)] +pub struct ReferenceFrame { + pub order_hint: u32, + pub width: u32, + pub height: u32, + pub render_width: u32, + pub render_height: u32, + pub frame: Arc>, + pub input_hres: Arc>, + pub input_qres: Arc>, + pub cdfs: CDFContext, + pub frame_me_stats: RefMEStats, + pub output_frameno: u64, + pub segmentation: SegmentationState, +} + +#[derive(Debug, Clone, Default)] +pub struct ReferenceFramesSet { + pub frames: [Option>>; REF_FRAMES], + pub deblock: [DeblockState; REF_FRAMES], +} + +impl ReferenceFramesSet { + pub fn new() -> Self { + Self { frames: Default::default(), deblock: Default::default() } + } +} + +#[wasm_bindgen] +#[derive( + ArgEnum, Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, +)] +#[repr(C)] +pub enum Tune { + Psnr, + #[default] + Psychovisual, +} + +const FRAME_ID_LENGTH: u32 = 15; +const DELTA_FRAME_ID_LENGTH: u32 = 14; + +#[derive(Copy, Clone, Debug)] +pub struct Sequence { + /// OBU Sequence header of AV1 + pub profile: u8, + pub num_bits_width: u32, + pub num_bits_height: u32, + pub bit_depth: usize, + pub chroma_sampling: ChromaSampling, + pub chroma_sample_position: ChromaSamplePosition, + pub pixel_range: PixelRange, + pub color_description: Option, + pub mastering_display: Option, + pub content_light: Option, + pub max_frame_width: u32, + pub max_frame_height: u32, + pub frame_id_numbers_present_flag: bool, + pub frame_id_length: u32, + pub delta_frame_id_length: u32, + pub use_128x128_superblock: bool, + pub order_hint_bits_minus_1: u32, + /// 0 - force off + /// 1 - force on + /// 2 - adaptive + pub force_screen_content_tools: u32, + /// 0 - Not to force. MV can be in 1/4 or 1/8 + /// 1 - force to integer + /// 2 - adaptive + pub force_integer_mv: u32, + /// Video is a single frame still picture + pub still_picture: bool, + /// Use reduced header for still picture + pub reduced_still_picture_hdr: bool, + /// enables/disables `filter_intra` + pub enable_filter_intra: bool, + /// enables/disables corner/edge filtering and upsampling + pub enable_intra_edge_filter: bool, + /// enables/disables `interintra_compound` + pub enable_interintra_compound: bool, + /// enables/disables masked compound + pub enable_masked_compound: bool, + /// 0 - disable dual interpolation filter + /// 1 - enable vert/horiz filter selection + pub enable_dual_filter: bool, + /// 0 - disable order hint, and related tools + /// `jnt_comp`, `ref_frame_mvs`, `frame_sign_bias` + /// if 0, `enable_jnt_comp` and + /// `enable_ref_frame_mvs` must be set zs 0. + pub enable_order_hint: bool, + /// 0 - disable joint compound modes + /// 1 - enable it + pub enable_jnt_comp: bool, + /// 0 - disable ref frame mvs + /// 1 - enable it + pub enable_ref_frame_mvs: bool, + /// 0 - disable warped motion for sequence + /// 1 - enable it for the sequence + pub enable_warped_motion: bool, + /// 0 - Disable superres for the sequence, and disable + /// transmitting per-frame superres enabled flag. + /// 1 - Enable superres for the sequence, and also + /// enable per-frame flag to denote if superres is + /// enabled for that frame. + pub enable_superres: bool, + /// To turn on/off CDEF + pub enable_cdef: bool, + /// To turn on/off loop restoration + pub enable_restoration: bool, + /// To turn on/off larger-than-superblock loop restoration units + pub enable_large_lru: bool, + /// allow encoder to delay loop filter RDO/coding until after frame reconstruciton is complete + pub enable_delayed_loopfilter_rdo: bool, + pub operating_points_cnt_minus_1: usize, + pub operating_point_idc: [u16; MAX_NUM_OPERATING_POINTS], + pub display_model_info_present_flag: bool, + pub decoder_model_info_present_flag: bool, + pub level_idx: [u8; MAX_NUM_OPERATING_POINTS], + /// `seq_tier` in the spec. One bit: 0 or 1. + pub tier: [usize; MAX_NUM_OPERATING_POINTS], + pub film_grain_params_present: bool, + pub timing_info_present: bool, + pub tiling: TilingInfo, + pub time_base: Rational, +} + +impl Sequence { + /// # Panics + /// + /// Panics if the resulting tile sizes would be too large. + pub fn new(config: &EncoderConfig) -> Sequence { + let width_bits = 32 - (config.width as u32).leading_zeros(); + let height_bits = 32 - (config.height as u32).leading_zeros(); + assert!(width_bits <= 16); + assert!(height_bits <= 16); + + let profile = if config.bit_depth == 12 + || config.chroma_sampling == ChromaSampling::Cs422 + { + 2 + } else { + u8::from(config.chroma_sampling == ChromaSampling::Cs444) + }; + + let operating_point_idc: [u16; MAX_NUM_OPERATING_POINTS] = + [0; MAX_NUM_OPERATING_POINTS]; + let level_idx: [u8; MAX_NUM_OPERATING_POINTS] = + if let Some(level_idx) = config.level_idx { + [level_idx; MAX_NUM_OPERATING_POINTS] + } else { + [31; MAX_NUM_OPERATING_POINTS] + }; + let tier: [usize; MAX_NUM_OPERATING_POINTS] = + [0; MAX_NUM_OPERATING_POINTS]; + + // Restoration filters are not useful for very small frame sizes, + // so disable them in that case. + let enable_restoration_filters = config.width >= 32 && config.height >= 32; + let use_128x128_superblock = false; + + let frame_rate = config.frame_rate(); + let sb_size_log2 = Self::sb_size_log2(use_128x128_superblock); + + let mut tiling = TilingInfo::from_target_tiles( + sb_size_log2, + config.width, + config.height, + frame_rate, + TilingInfo::tile_log2(1, config.tile_cols).unwrap(), + TilingInfo::tile_log2(1, config.tile_rows).unwrap(), + config.chroma_sampling == ChromaSampling::Cs422, + ); + + if config.tiles > 0 { + let mut tile_rows_log2 = 0; + let mut tile_cols_log2 = 0; + while (tile_rows_log2 < tiling.max_tile_rows_log2) + || (tile_cols_log2 < tiling.max_tile_cols_log2) + { + tiling = TilingInfo::from_target_tiles( + sb_size_log2, + config.width, + config.height, + frame_rate, + tile_cols_log2, + tile_rows_log2, + config.chroma_sampling == ChromaSampling::Cs422, + ); + + if tiling.rows * tiling.cols >= config.tiles { + break; + }; + + if ((tiling.tile_height_sb >= tiling.tile_width_sb) + && (tiling.tile_rows_log2 < tiling.max_tile_rows_log2)) + || (tile_cols_log2 >= tiling.max_tile_cols_log2) + { + tile_rows_log2 += 1; + } else { + tile_cols_log2 += 1; + } + } + } + + Sequence { + tiling, + profile, + num_bits_width: width_bits, + num_bits_height: height_bits, + bit_depth: config.bit_depth, + chroma_sampling: config.chroma_sampling, + chroma_sample_position: config.chroma_sample_position, + pixel_range: config.pixel_range, + color_description: config.color_description, + mastering_display: config.mastering_display, + content_light: config.content_light, + max_frame_width: config.width as u32, + max_frame_height: config.height as u32, + frame_id_numbers_present_flag: false, + frame_id_length: FRAME_ID_LENGTH, + delta_frame_id_length: DELTA_FRAME_ID_LENGTH, + use_128x128_superblock, + order_hint_bits_minus_1: 5, + force_screen_content_tools: if config.still_picture { 2 } else { 0 }, + force_integer_mv: 2, + still_picture: config.still_picture, + reduced_still_picture_hdr: config.still_picture, + enable_filter_intra: false, + enable_intra_edge_filter: true, + enable_interintra_compound: false, + enable_masked_compound: false, + enable_dual_filter: false, + enable_order_hint: !config.still_picture, + enable_jnt_comp: false, + enable_ref_frame_mvs: false, + enable_warped_motion: false, + enable_superres: false, + enable_cdef: config.speed_settings.cdef && enable_restoration_filters, + enable_restoration: config.speed_settings.lrf + && enable_restoration_filters, + enable_large_lru: true, + enable_delayed_loopfilter_rdo: true, + operating_points_cnt_minus_1: 0, + operating_point_idc, + display_model_info_present_flag: false, + decoder_model_info_present_flag: false, + level_idx, + tier, + film_grain_params_present: config + .film_grain_params + .as_ref() + .map(|entries| !entries.is_empty()) + .unwrap_or(false), + timing_info_present: config.enable_timing_info, + time_base: config.time_base, + } + } + + pub const fn get_relative_dist(&self, a: u32, b: u32) -> i32 { + let diff = a as i32 - b as i32; + let m = 1 << self.order_hint_bits_minus_1; + (diff & (m - 1)) - (diff & m) + } + + pub fn get_skip_mode_allowed( + &self, fi: &FrameInvariants, inter_cfg: &InterConfig, + reference_select: bool, + ) -> bool { + if fi.intra_only || !reference_select || !self.enable_order_hint { + return false; + } + + let mut forward_idx: isize = -1; + let mut backward_idx: isize = -1; + let mut forward_hint = 0; + let mut backward_hint = 0; + + for i in inter_cfg.allowed_ref_frames().iter().map(|rf| rf.to_index()) { + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] { + let ref_hint = rec.order_hint; + + if self.get_relative_dist(ref_hint, fi.order_hint) < 0 { + if forward_idx < 0 + || self.get_relative_dist(ref_hint, forward_hint) > 0 + { + forward_idx = i as isize; + forward_hint = ref_hint; + } + } else if self.get_relative_dist(ref_hint, fi.order_hint) > 0 + && (backward_idx < 0 + || self.get_relative_dist(ref_hint, backward_hint) > 0) + { + backward_idx = i as isize; + backward_hint = ref_hint; + } + } + } + + if forward_idx < 0 { + false + } else if backward_idx >= 0 { + // set skip_mode_frame + true + } else { + let mut second_forward_idx: isize = -1; + let mut second_forward_hint = 0; + + for i in inter_cfg.allowed_ref_frames().iter().map(|rf| rf.to_index()) { + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] + { + let ref_hint = rec.order_hint; + + if self.get_relative_dist(ref_hint, forward_hint) < 0 + && (second_forward_idx < 0 + || self.get_relative_dist(ref_hint, second_forward_hint) > 0) + { + second_forward_idx = i as isize; + second_forward_hint = ref_hint; + } + } + } + + // TODO: Set skip_mode_frame, when second_forward_idx is not less than 0. + second_forward_idx >= 0 + } + } + + #[inline(always)] + const fn sb_size_log2(use_128x128_superblock: bool) -> usize { + 6 + (use_128x128_superblock as usize) + } +} + +#[derive(Debug, Clone)] +pub struct FrameState { + pub sb_size_log2: usize, + pub input: Arc>, + pub input_hres: Arc>, // half-resolution version of input luma + pub input_qres: Arc>, // quarter-resolution version of input luma + pub rec: Arc>, + pub cdfs: CDFContext, + pub context_update_tile_id: usize, // tile id used for the CDFontext + pub max_tile_size_bytes: u32, + pub deblock: DeblockState, + pub segmentation: SegmentationState, + pub restoration: RestorationState, + // Because we only reference these within a tile context, + // these are stored per-tile for easier access. + pub frame_me_stats: RefMEStats, + pub enc_stats: EncoderStats, +} + +impl FrameState { + pub fn new(fi: &FrameInvariants) -> Self { + // TODO(negge): Use fi.cfg.chroma_sampling when we store VideoDetails in FrameInvariants + FrameState::new_with_frame( + fi, + Arc::new(Frame::new(fi.width, fi.height, fi.sequence.chroma_sampling)), + ) + } + + /// Similar to [`FrameState::new_with_frame`], but takes an `me_stats` + /// and `rec` to enable reusing the same underlying allocations to create + /// a `FrameState` + /// + /// This function primarily exists for [`estimate_inter_costs`], and so + /// it does not create hres or qres versions of `frame` as downscaling is + /// somewhat expensive and are not needed for [`estimate_inter_costs`]. + pub fn new_with_frame_and_me_stats_and_rec( + fi: &FrameInvariants, frame: Arc>, me_stats: RefMEStats, + rec: Arc>, + ) -> Self { + let rs = RestorationState::new(fi, &frame); + + let hres = Plane::new(0, 0, 0, 0, 0, 0); + let qres = Plane::new(0, 0, 0, 0, 0, 0); + + Self { + sb_size_log2: fi.sb_size_log2(), + input: frame, + input_hres: Arc::new(hres), + input_qres: Arc::new(qres), + rec, + cdfs: CDFContext::new(0), + context_update_tile_id: 0, + max_tile_size_bytes: 0, + deblock: Default::default(), + segmentation: Default::default(), + restoration: rs, + frame_me_stats: me_stats, + enc_stats: Default::default(), + } + } + + pub fn new_with_frame( + fi: &FrameInvariants, frame: Arc>, + ) -> Self { + let rs = RestorationState::new(fi, &frame); + let luma_width = frame.planes[0].cfg.width; + let luma_height = frame.planes[0].cfg.height; + + let hres = frame.planes[0].downsampled(fi.width, fi.height); + let qres = hres.downsampled(fi.width, fi.height); + + Self { + sb_size_log2: fi.sb_size_log2(), + input: frame, + input_hres: Arc::new(hres), + input_qres: Arc::new(qres), + rec: Arc::new(Frame::new( + luma_width, + luma_height, + fi.sequence.chroma_sampling, + )), + cdfs: CDFContext::new(0), + context_update_tile_id: 0, + max_tile_size_bytes: 0, + deblock: Default::default(), + segmentation: Default::default(), + restoration: rs, + frame_me_stats: FrameMEStats::new_arc_array(fi.w_in_b, fi.h_in_b), + enc_stats: Default::default(), + } + } + + pub fn apply_tile_state_mut(&mut self, f: F) -> R + where + F: FnOnce(&mut TileStateMut<'_, T>) -> R, + { + let PlaneConfig { width, height, .. } = self.rec.planes[0].cfg; + let sbo_0 = PlaneSuperBlockOffset(SuperBlockOffset { x: 0, y: 0 }); + let frame_me_stats = self.frame_me_stats.clone(); + let frame_me_stats = &mut *frame_me_stats.write().expect("poisoned lock"); + let ts = &mut TileStateMut::new( + self, + sbo_0, + self.sb_size_log2, + width, + height, + frame_me_stats, + ); + + f(ts) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct DeblockState { + pub levels: [u8; MAX_PLANES + 1], // Y vertical edges, Y horizontal, U, V + pub sharpness: u8, + pub deltas_enabled: bool, + pub delta_updates_enabled: bool, + pub ref_deltas: [i8; REF_FRAMES], + pub mode_deltas: [i8; 2], + pub block_deltas_enabled: bool, + pub block_delta_shift: u8, + pub block_delta_multi: bool, +} + +impl Default for DeblockState { + fn default() -> Self { + DeblockState { + levels: [8, 8, 4, 4], + sharpness: 0, + deltas_enabled: false, // requires delta_q_enabled + delta_updates_enabled: false, + ref_deltas: [1, 0, 0, 0, 0, -1, -1, -1], + mode_deltas: [0, 0], + block_deltas_enabled: false, + block_delta_shift: 0, + block_delta_multi: false, + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +pub struct SegmentationState { + pub enabled: bool, + pub update_data: bool, + pub update_map: bool, + pub preskip: bool, + pub last_active_segid: u8, + pub features: [[bool; SegLvl::SEG_LVL_MAX as usize]; 8], + pub data: [[i16; SegLvl::SEG_LVL_MAX as usize]; 8], + pub threshold: [DistortionScale; 7], + pub min_segment: u8, + pub max_segment: u8, +} + +impl SegmentationState { + #[profiling::function] + pub fn update_threshold(&mut self, base_q_idx: u8, bd: usize) { + let base_ac_q = ac_q(base_q_idx, 0, bd).get() as u64; + let real_ac_q = ArrayVec::<_, MAX_SEGMENTS>::from_iter( + self.data[..=self.max_segment as usize].iter().map(|data| { + ac_q(base_q_idx, data[SegLvl::SEG_LVL_ALT_Q as usize] as i8, bd).get() + as u64 + }), + ); + self.threshold.fill(DistortionScale(0)); + for ((q1, q2), threshold) in + real_ac_q.iter().skip(1).zip(&real_ac_q).zip(&mut self.threshold) + { + *threshold = DistortionScale::new(base_ac_q.pow(2), q1 * q2); + } + } + + #[cfg(feature = "dump_lookahead_data")] + pub fn dump_threshold( + &self, data_location: std::path::PathBuf, input_frameno: u64, + ) { + use byteorder::{NativeEndian, WriteBytesExt}; + let file_name = format!("{:010}-thresholds", input_frameno); + let max_segment = self.max_segment; + // dynamic allocation: debugging only + let mut buf = vec![]; + buf.write_u64::(max_segment as u64).unwrap(); + for &v in &self.threshold[..max_segment as usize] { + buf.write_u32::(v.0).unwrap(); + } + ::std::fs::write(data_location.join(file_name).with_extension("bin"), buf) + .unwrap(); + } +} + +// Frame Invariants are invariant inside a frame +#[allow(dead_code)] +#[derive(Debug, Clone)] +pub struct FrameInvariants { + pub sequence: Arc, + pub config: Arc, + pub width: usize, + pub height: usize, + pub render_width: u32, + pub render_height: u32, + pub frame_size_override_flag: bool, + pub render_and_frame_size_different: bool, + pub sb_width: usize, + pub sb_height: usize, + pub w_in_b: usize, + pub h_in_b: usize, + pub input_frameno: u64, + pub order_hint: u32, + pub show_frame: bool, + pub showable_frame: bool, + pub error_resilient: bool, + pub intra_only: bool, + pub allow_high_precision_mv: bool, + pub frame_type: FrameType, + pub frame_to_show_map_idx: u32, + pub use_reduced_tx_set: bool, + pub reference_mode: ReferenceMode, + pub use_prev_frame_mvs: bool, + pub partition_range: PartitionRange, + pub globalmv_transformation_type: [GlobalMVMode; INTER_REFS_PER_FRAME], + pub num_tg: usize, + pub large_scale_tile: bool, + pub disable_cdf_update: bool, + pub allow_screen_content_tools: u32, + pub force_integer_mv: u32, + pub primary_ref_frame: u32, + pub refresh_frame_flags: u32, // a bitmask that specifies which + // reference frame slots will be updated with the current frame + // after it is decoded. + pub allow_intrabc: bool, + pub use_ref_frame_mvs: bool, + pub is_filter_switchable: bool, + pub is_motion_mode_switchable: bool, + pub disable_frame_end_update_cdf: bool, + pub allow_warped_motion: bool, + pub cdef_search_method: CDEFSearchMethod, + pub cdef_damping: u8, + pub cdef_bits: u8, + pub cdef_y_strengths: [u8; 8], + pub cdef_uv_strengths: [u8; 8], + pub delta_q_present: bool, + pub ref_frames: [u8; INTER_REFS_PER_FRAME], + pub ref_frame_sign_bias: [bool; INTER_REFS_PER_FRAME], + pub rec_buffer: ReferenceFramesSet, + pub base_q_idx: u8, + pub dc_delta_q: [i8; 3], + pub ac_delta_q: [i8; 3], + pub lambda: f64, + pub me_lambda: f64, + pub dist_scale: [DistortionScale; 3], + pub me_range_scale: u8, + pub use_tx_domain_distortion: bool, + pub use_tx_domain_rate: bool, + pub idx_in_group_output: u64, + pub pyramid_level: u64, + pub enable_early_exit: bool, + pub tx_mode_select: bool, + pub enable_inter_txfm_split: bool, + pub default_filter: FilterMode, + pub enable_segmentation: bool, + pub t35_metadata: Box<[T35]>, + /// Target CPU feature level. + pub cpu_feature_level: crate::cpu_features::CpuFeatureLevel, + + // These will be set if this is a coded (non-SEF) frame. + // We do not need them for SEFs. + pub coded_frame_data: Option>, +} + +/// These frame invariants are only used on coded frames, i.e. non-SEFs. +/// They are stored separately to avoid useless allocations +/// when we do not need them. +/// +/// Currently this consists only of lookahaed data. +/// This may change in the future. +#[derive(Debug, Clone)] +pub struct CodedFrameData { + /// The lookahead version of `rec_buffer`, used for storing and propagating + /// the original reference frames (rather than reconstructed ones). The + /// lookahead uses both `rec_buffer` and `lookahead_rec_buffer`, where + /// `rec_buffer` contains the current frame's reference frames and + /// `lookahead_rec_buffer` contains the next frame's reference frames. + pub lookahead_rec_buffer: ReferenceFramesSet, + /// Frame width in importance blocks. + pub w_in_imp_b: usize, + /// Frame height in importance blocks. + pub h_in_imp_b: usize, + /// Intra prediction cost estimations for each importance block. + pub lookahead_intra_costs: Box<[u32]>, + /// Future importance values for each importance block. That is, a value + /// indicating how much future frames depend on the block (for example, via + /// inter-prediction). + pub block_importances: Box<[f32]>, + /// Pre-computed `distortion_scale`. + pub distortion_scales: Box<[DistortionScale]>, + /// Pre-computed `activity_scale`. + pub activity_scales: Box<[DistortionScale]>, + pub activity_mask: ActivityMask, + /// Combined metric of activity and distortion + pub spatiotemporal_scores: Box<[DistortionScale]>, +} + +impl CodedFrameData { + pub fn new(fi: &FrameInvariants) -> CodedFrameData { + // Width and height are padded to 8×8 block size. + let w_in_imp_b = fi.w_in_b / 2; + let h_in_imp_b = fi.h_in_b / 2; + + CodedFrameData { + lookahead_rec_buffer: ReferenceFramesSet::new(), + w_in_imp_b, + h_in_imp_b, + // This is never used before it is assigned + lookahead_intra_costs: Box::new([]), + // dynamic allocation: once per frame + block_importances: vec![0.; w_in_imp_b * h_in_imp_b].into_boxed_slice(), + distortion_scales: vec![ + DistortionScale::default(); + w_in_imp_b * h_in_imp_b + ] + .into_boxed_slice(), + activity_scales: vec![ + DistortionScale::default(); + w_in_imp_b * h_in_imp_b + ] + .into_boxed_slice(), + activity_mask: Default::default(), + spatiotemporal_scores: Default::default(), + } + } + + // Assumes that we have already computed activity scales and distortion scales + // Returns -0.5 log2(mean(scale)) + #[profiling::function] + pub fn compute_spatiotemporal_scores(&mut self) -> i64 { + let mut scores = self + .distortion_scales + .iter() + .zip(self.activity_scales.iter()) + .map(|(&d, &a)| d * a) + .collect::>(); + + let inv_mean = DistortionScale::inv_mean(&scores); + + for score in scores.iter_mut() { + *score *= inv_mean; + } + + for scale in self.distortion_scales.iter_mut() { + *scale *= inv_mean; + } + + self.spatiotemporal_scores = scores; + + inv_mean.blog64() >> 1 + } + + // Assumes that we have already computed distortion_scales + // Returns -0.5 log2(mean(scale)) + #[profiling::function] + pub fn compute_temporal_scores(&mut self) -> i64 { + let inv_mean = DistortionScale::inv_mean(&self.distortion_scales); + for scale in self.distortion_scales.iter_mut() { + *scale *= inv_mean; + } + self.spatiotemporal_scores.clone_from(&self.distortion_scales); + inv_mean.blog64() >> 1 + } + + #[cfg(feature = "dump_lookahead_data")] + pub fn dump_scales( + &self, data_location: std::path::PathBuf, scales: Scales, + input_frameno: u64, + ) { + use byteorder::{NativeEndian, WriteBytesExt}; + let file_name = format!( + "{:010}-{}", + input_frameno, + match scales { + Scales::ActivityScales => "activity_scales", + Scales::DistortionScales => "distortion_scales", + Scales::SpatiotemporalScales => "spatiotemporal_scales", + } + ); + // dynamic allocation: debugging only + let mut buf = vec![]; + buf.write_u64::(self.w_in_imp_b as u64).unwrap(); + buf.write_u64::(self.h_in_imp_b as u64).unwrap(); + for &v in match scales { + Scales::ActivityScales => &self.activity_scales[..], + Scales::DistortionScales => &self.distortion_scales[..], + Scales::SpatiotemporalScales => &self.spatiotemporal_scores[..], + } { + buf.write_u32::(v.0).unwrap(); + } + ::std::fs::write(data_location.join(file_name).with_extension("bin"), buf) + .unwrap(); + } +} + +#[cfg(feature = "dump_lookahead_data")] +pub enum Scales { + ActivityScales, + DistortionScales, + SpatiotemporalScales, +} + +pub(crate) const fn pos_to_lvl(pos: u64, pyramid_depth: u64) -> u64 { + // Derive level within pyramid for a frame with a given coding order position + // For example, with a pyramid of depth 2, the 2 least significant bits of the + // position determine the level: + // 00 -> 0 + // 01 -> 2 + // 10 -> 1 + // 11 -> 2 + pyramid_depth - (pos | (1 << pyramid_depth)).trailing_zeros() as u64 +} + +impl FrameInvariants { + #[allow(clippy::erasing_op, clippy::identity_op)] + /// # Panics + /// + /// - If the size of `T` does not match the sequence's bit depth + pub fn new(config: Arc, sequence: Arc) -> Self { + assert!( + sequence.bit_depth <= mem::size_of::() * 8, + "bit depth cannot fit into u8" + ); + + let (width, height) = (config.width, config.height); + let frame_size_override_flag = width as u32 != sequence.max_frame_width + || height as u32 != sequence.max_frame_height; + + let (render_width, render_height) = config.render_size(); + let render_and_frame_size_different = + render_width != width || render_height != height; + + let use_reduced_tx_set = config.speed_settings.transform.reduced_tx_set; + let use_tx_domain_distortion = config.tune == Tune::Psnr + && config.speed_settings.transform.tx_domain_distortion; + let use_tx_domain_rate = config.speed_settings.transform.tx_domain_rate; + + let w_in_b = 2 * config.width.align_power_of_two_and_shift(3); // MiCols, ((width+7)/8)<<3 >> MI_SIZE_LOG2 + let h_in_b = 2 * config.height.align_power_of_two_and_shift(3); // MiRows, ((height+7)/8)<<3 >> MI_SIZE_LOG2 + + Self { + width, + height, + render_width: render_width as u32, + render_height: render_height as u32, + frame_size_override_flag, + render_and_frame_size_different, + sb_width: width.align_power_of_two_and_shift(6), + sb_height: height.align_power_of_two_and_shift(6), + w_in_b, + h_in_b, + input_frameno: 0, + order_hint: 0, + show_frame: true, + showable_frame: !sequence.reduced_still_picture_hdr, + error_resilient: false, + intra_only: true, + allow_high_precision_mv: false, + frame_type: FrameType::KEY, + frame_to_show_map_idx: 0, + use_reduced_tx_set, + reference_mode: ReferenceMode::SINGLE, + use_prev_frame_mvs: false, + partition_range: config.speed_settings.partition.partition_range, + globalmv_transformation_type: [GlobalMVMode::IDENTITY; + INTER_REFS_PER_FRAME], + num_tg: 1, + large_scale_tile: false, + disable_cdf_update: false, + allow_screen_content_tools: sequence.force_screen_content_tools, + force_integer_mv: 1, + primary_ref_frame: PRIMARY_REF_NONE, + refresh_frame_flags: ALL_REF_FRAMES_MASK, + allow_intrabc: false, + use_ref_frame_mvs: false, + is_filter_switchable: false, + is_motion_mode_switchable: false, // 0: only the SIMPLE motion mode will be used. + disable_frame_end_update_cdf: sequence.reduced_still_picture_hdr, + allow_warped_motion: false, + cdef_search_method: CDEFSearchMethod::PickFromQ, + cdef_damping: 3, + cdef_bits: 0, + cdef_y_strengths: [ + 0 * 4 + 0, + 1 * 4 + 0, + 2 * 4 + 1, + 3 * 4 + 1, + 5 * 4 + 2, + 7 * 4 + 3, + 10 * 4 + 3, + 13 * 4 + 3, + ], + cdef_uv_strengths: [ + 0 * 4 + 0, + 1 * 4 + 0, + 2 * 4 + 1, + 3 * 4 + 1, + 5 * 4 + 2, + 7 * 4 + 3, + 10 * 4 + 3, + 13 * 4 + 3, + ], + delta_q_present: false, + ref_frames: [0; INTER_REFS_PER_FRAME], + ref_frame_sign_bias: [false; INTER_REFS_PER_FRAME], + rec_buffer: ReferenceFramesSet::new(), + base_q_idx: config.quantizer as u8, + dc_delta_q: [0; 3], + ac_delta_q: [0; 3], + lambda: 0.0, + dist_scale: Default::default(), + me_lambda: 0.0, + me_range_scale: 1, + use_tx_domain_distortion, + use_tx_domain_rate, + idx_in_group_output: 0, + pyramid_level: 0, + enable_early_exit: true, + tx_mode_select: false, + default_filter: FilterMode::REGULAR, + cpu_feature_level: Default::default(), + enable_segmentation: config.speed_settings.segmentation + != SegmentationLevel::Disabled, + enable_inter_txfm_split: config + .speed_settings + .transform + .enable_inter_tx_split, + t35_metadata: Box::new([]), + sequence, + config, + coded_frame_data: None, + } + } + + pub fn new_key_frame( + config: Arc, sequence: Arc, + gop_input_frameno_start: u64, t35_metadata: Box<[T35]>, + ) -> Self { + let tx_mode_select = config.speed_settings.transform.rdo_tx_decision; + let mut fi = Self::new(config, sequence); + fi.input_frameno = gop_input_frameno_start; + fi.tx_mode_select = tx_mode_select; + fi.coded_frame_data = Some(CodedFrameData::new(&fi)); + fi.t35_metadata = t35_metadata; + fi + } + + /// Returns the created `FrameInvariants`, or `None` if this should be + /// a placeholder frame. + pub(crate) fn new_inter_frame( + previous_coded_fi: &Self, inter_cfg: &InterConfig, + gop_input_frameno_start: u64, output_frameno_in_gop: u64, + next_keyframe_input_frameno: u64, error_resilient: bool, + t35_metadata: Box<[T35]>, + ) -> Option { + let input_frameno = inter_cfg + .get_input_frameno(output_frameno_in_gop, gop_input_frameno_start); + if input_frameno >= next_keyframe_input_frameno { + // This is an invalid frame. We set it as a placeholder in the FI list. + return None; + } + + // We have this special thin clone method to avoid cloning the + // quite large lookahead data for SEFs, when it is not needed. + let mut fi = previous_coded_fi.clone_without_coded_data(); + fi.intra_only = false; + fi.force_integer_mv = 0; // note: should be 1 if fi.intra_only is true + fi.idx_in_group_output = + inter_cfg.get_idx_in_group_output(output_frameno_in_gop); + fi.tx_mode_select = fi.enable_inter_txfm_split; + + let show_existing_frame = + inter_cfg.get_show_existing_frame(fi.idx_in_group_output); + if !show_existing_frame { + fi.coded_frame_data.clone_from(&previous_coded_fi.coded_frame_data); + } + + fi.order_hint = + inter_cfg.get_order_hint(output_frameno_in_gop, fi.idx_in_group_output); + + fi.pyramid_level = inter_cfg.get_level(fi.idx_in_group_output); + + fi.frame_type = if (inter_cfg.switch_frame_interval > 0) + && (output_frameno_in_gop % inter_cfg.switch_frame_interval == 0) + && (fi.pyramid_level == 0) + { + FrameType::SWITCH + } else { + FrameType::INTER + }; + fi.error_resilient = + if fi.frame_type == FrameType::SWITCH { true } else { error_resilient }; + + fi.frame_size_override_flag = if fi.frame_type == FrameType::SWITCH { + true + } else if fi.sequence.reduced_still_picture_hdr { + false + } else if fi.frame_type == FrameType::INTER + && !fi.error_resilient + && fi.render_and_frame_size_different + { + // force frame_size_with_refs() code path if render size != frame size + true + } else { + fi.width as u32 != fi.sequence.max_frame_width + || fi.height as u32 != fi.sequence.max_frame_height + }; + + // this is the slot that the current frame is going to be saved into + let slot_idx = inter_cfg.get_slot_idx(fi.pyramid_level, fi.order_hint); + fi.show_frame = inter_cfg.get_show_frame(fi.idx_in_group_output); + fi.t35_metadata = if fi.show_frame { t35_metadata } else { Box::new([]) }; + fi.frame_to_show_map_idx = slot_idx; + fi.refresh_frame_flags = if fi.frame_type == FrameType::SWITCH { + ALL_REF_FRAMES_MASK + } else if fi.is_show_existing_frame() { + 0 + } else { + 1 << slot_idx + }; + + let second_ref_frame = + if fi.idx_in_group_output == 0 { LAST2_FRAME } else { ALTREF_FRAME }; + let ref_in_previous_group = LAST3_FRAME; + + // reuse probability estimates from previous frames only in top level frames + fi.primary_ref_frame = if fi.error_resilient || (fi.pyramid_level > 2) { + PRIMARY_REF_NONE + } else { + (ref_in_previous_group.to_index()) as u32 + }; + + if fi.pyramid_level == 0 { + // level 0 has no forward references + // default to last P frame + fi.ref_frames = [ + // calculations done relative to the slot_idx for this frame. + // the last four frames can be found by subtracting from the current slot_idx + // add 4 to prevent underflow + // TODO: maybe use order_hint here like in get_slot_idx? + // this is the previous P frame + (slot_idx + 4 - 1) as u8 % 4 + ; INTER_REFS_PER_FRAME]; + if inter_cfg.multiref { + // use the second-previous p frame as a second reference frame + fi.ref_frames[second_ref_frame.to_index()] = + (slot_idx + 4 - 2) as u8 % 4; + } + } else { + debug_assert!(inter_cfg.multiref); + + // fill in defaults + // default to backwards reference in lower level + fi.ref_frames = [{ + let oh = fi.order_hint + - (inter_cfg.group_input_len as u32 >> fi.pyramid_level); + let lvl1 = pos_to_lvl(oh as u64, inter_cfg.pyramid_depth); + if lvl1 == 0 { + ((oh >> inter_cfg.pyramid_depth) % 4) as u8 + } else { + 3 + lvl1 as u8 + } + }; INTER_REFS_PER_FRAME]; + // use forward reference in lower level as a second reference frame + fi.ref_frames[second_ref_frame.to_index()] = { + let oh = fi.order_hint + + (inter_cfg.group_input_len as u32 >> fi.pyramid_level); + let lvl2 = pos_to_lvl(oh as u64, inter_cfg.pyramid_depth); + if lvl2 == 0 { + ((oh >> inter_cfg.pyramid_depth) % 4) as u8 + } else { + 3 + lvl2 as u8 + } + }; + // use a reference to the previous frame in the same level + // (horizontally) as a third reference + fi.ref_frames[ref_in_previous_group.to_index()] = slot_idx as u8; + } + + fi.set_ref_frame_sign_bias(); + + fi.reference_mode = if inter_cfg.multiref && fi.idx_in_group_output != 0 { + ReferenceMode::SELECT + } else { + ReferenceMode::SINGLE + }; + fi.input_frameno = input_frameno; + fi.me_range_scale = (inter_cfg.group_input_len >> fi.pyramid_level) as u8; + + if fi.show_frame || fi.showable_frame { + let cur_frame_time = fi.frame_timestamp(); + // Increment the film grain seed for the next frame + if let Some(params) = + Arc::make_mut(&mut fi.config).get_film_grain_mut_at(cur_frame_time) + { + params.random_seed = params.random_seed.wrapping_add(3248); + if params.random_seed == 0 { + params.random_seed = DEFAULT_GRAIN_SEED; + } + } + } + + Some(fi) + } + + pub fn is_show_existing_frame(&self) -> bool { + self.coded_frame_data.is_none() + } + + pub fn clone_without_coded_data(&self) -> Self { + Self { + coded_frame_data: None, + + sequence: self.sequence.clone(), + config: self.config.clone(), + width: self.width, + height: self.height, + render_width: self.render_width, + render_height: self.render_height, + frame_size_override_flag: self.frame_size_override_flag, + render_and_frame_size_different: self.render_and_frame_size_different, + sb_width: self.sb_width, + sb_height: self.sb_height, + w_in_b: self.w_in_b, + h_in_b: self.h_in_b, + input_frameno: self.input_frameno, + order_hint: self.order_hint, + show_frame: self.show_frame, + showable_frame: self.showable_frame, + error_resilient: self.error_resilient, + intra_only: self.intra_only, + allow_high_precision_mv: self.allow_high_precision_mv, + frame_type: self.frame_type, + frame_to_show_map_idx: self.frame_to_show_map_idx, + use_reduced_tx_set: self.use_reduced_tx_set, + reference_mode: self.reference_mode, + use_prev_frame_mvs: self.use_prev_frame_mvs, + partition_range: self.partition_range, + globalmv_transformation_type: self.globalmv_transformation_type, + num_tg: self.num_tg, + large_scale_tile: self.large_scale_tile, + disable_cdf_update: self.disable_cdf_update, + allow_screen_content_tools: self.allow_screen_content_tools, + force_integer_mv: self.force_integer_mv, + primary_ref_frame: self.primary_ref_frame, + refresh_frame_flags: self.refresh_frame_flags, + allow_intrabc: self.allow_intrabc, + use_ref_frame_mvs: self.use_ref_frame_mvs, + is_filter_switchable: self.is_filter_switchable, + is_motion_mode_switchable: self.is_motion_mode_switchable, + disable_frame_end_update_cdf: self.disable_frame_end_update_cdf, + allow_warped_motion: self.allow_warped_motion, + cdef_search_method: self.cdef_search_method, + cdef_damping: self.cdef_damping, + cdef_bits: self.cdef_bits, + cdef_y_strengths: self.cdef_y_strengths, + cdef_uv_strengths: self.cdef_uv_strengths, + delta_q_present: self.delta_q_present, + ref_frames: self.ref_frames, + ref_frame_sign_bias: self.ref_frame_sign_bias, + rec_buffer: self.rec_buffer.clone(), + base_q_idx: self.base_q_idx, + dc_delta_q: self.dc_delta_q, + ac_delta_q: self.ac_delta_q, + lambda: self.lambda, + me_lambda: self.me_lambda, + dist_scale: self.dist_scale, + me_range_scale: self.me_range_scale, + use_tx_domain_distortion: self.use_tx_domain_distortion, + use_tx_domain_rate: self.use_tx_domain_rate, + idx_in_group_output: self.idx_in_group_output, + pyramid_level: self.pyramid_level, + enable_early_exit: self.enable_early_exit, + tx_mode_select: self.tx_mode_select, + enable_inter_txfm_split: self.enable_inter_txfm_split, + default_filter: self.default_filter, + enable_segmentation: self.enable_segmentation, + t35_metadata: self.t35_metadata.clone(), + cpu_feature_level: self.cpu_feature_level, + } + } + + pub fn set_ref_frame_sign_bias(&mut self) { + for i in 0..INTER_REFS_PER_FRAME { + self.ref_frame_sign_bias[i] = if !self.sequence.enable_order_hint { + false + } else if let Some(ref rec) = + self.rec_buffer.frames[self.ref_frames[i] as usize] + { + let hint = rec.order_hint; + self.sequence.get_relative_dist(hint, self.order_hint) > 0 + } else { + false + }; + } + } + + pub fn get_frame_subtype(&self) -> usize { + if self.frame_type == FrameType::KEY { + FRAME_SUBTYPE_I + } else { + FRAME_SUBTYPE_P + (self.pyramid_level as usize) + } + } + + fn pick_strength_from_q(&mut self, qps: &QuantizerParameters) { + self.cdef_damping = 3 + (self.base_q_idx >> 6); + let q = bexp64(qps.log_target_q + q57(QSCALE)) as f32; + /* These coefficients were trained on libaom. */ + let (y_f1, y_f2, uv_f1, uv_f2) = if !self.intra_only { + ( + poly2(q, -0.0000023593946_f32, 0.0068615186_f32, 0.02709886_f32, 15), + poly2(q, -0.00000057629734_f32, 0.0013993345_f32, 0.03831067_f32, 3), + poly2(q, -0.0000007095069_f32, 0.0034628846_f32, 0.00887099_f32, 15), + poly2(q, 0.00000023874085_f32, 0.00028223585_f32, 0.05576307_f32, 3), + ) + } else { + ( + poly2(q, 0.0000033731974_f32, 0.008070594_f32, 0.0187634_f32, 15), + poly2(q, 0.0000029167343_f32, 0.0027798624_f32, 0.0079405_f32, 3), + poly2(q, -0.0000130790995_f32, 0.012892405_f32, -0.00748388_f32, 15), + poly2(q, 0.0000032651783_f32, 0.00035520183_f32, 0.00228092_f32, 3), + ) + }; + self.cdef_y_strengths[0] = (y_f1 * CDEF_SEC_STRENGTHS as i32 + y_f2) as u8; + self.cdef_uv_strengths[0] = + (uv_f1 * CDEF_SEC_STRENGTHS as i32 + uv_f2) as u8; + } + + pub fn set_quantizers(&mut self, qps: &QuantizerParameters) { + self.base_q_idx = qps.ac_qi[0]; + let base_q_idx = self.base_q_idx as i32; + for pi in 0..3 { + self.dc_delta_q[pi] = (qps.dc_qi[pi] as i32 - base_q_idx) as i8; + self.ac_delta_q[pi] = (qps.ac_qi[pi] as i32 - base_q_idx) as i8; + } + self.lambda = + qps.lambda * ((1 << (2 * (self.sequence.bit_depth - 8))) as f64); + self.me_lambda = self.lambda.sqrt(); + self.dist_scale = qps.dist_scale.map(DistortionScale::from); + + match self.cdef_search_method { + CDEFSearchMethod::PickFromQ => { + self.pick_strength_from_q(qps); + } + // TODO: implement FastSearch and FullSearch + _ => unreachable!(), + } + } + + #[inline(always)] + pub fn sb_size_log2(&self) -> usize { + self.sequence.tiling.sb_size_log2 + } + + pub fn film_grain_params(&self) -> Option<&GrainTableSegment> { + if !(self.show_frame || self.showable_frame) { + return None; + } + let cur_frame_time = self.frame_timestamp(); + self.config.get_film_grain_at(cur_frame_time) + } + + pub fn frame_timestamp(&self) -> u64 { + // I don't know why this is the base unit for a timestamp but it is. 1/10000000 of a second. + const TIMESTAMP_BASE_UNIT: u64 = 10_000_000; + + self.input_frameno * TIMESTAMP_BASE_UNIT * self.sequence.time_base.num + / self.sequence.time_base.den + } +} + +impl fmt::Display for FrameInvariants { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Input Frame {} - {}", self.input_frameno, self.frame_type) + } +} + +/// # Errors +/// +/// - If the frame packet cannot be written to +pub fn write_temporal_delimiter(packet: &mut dyn io::Write) -> io::Result<()> { + packet.write_all(&TEMPORAL_DELIMITER)?; + Ok(()) +} + +fn write_key_frame_obus( + packet: &mut dyn io::Write, fi: &FrameInvariants, obu_extension: u32, +) -> io::Result<()> { + let mut buf1 = Vec::new(); + let mut buf2 = Vec::new(); + { + let mut bw2 = BitWriter::endian(&mut buf2, BigEndian); + bw2.write_sequence_header_obu(fi)?; + bw2.write_bit(true)?; // trailing bit + bw2.byte_align()?; + } + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_obu_header(ObuType::OBU_SEQUENCE_HEADER, obu_extension)?; + } + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_uleb128(buf2.len() as u64)?; + } + + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + packet.write_all(&buf2).unwrap(); + buf2.clear(); + + if fi.sequence.content_light.is_some() { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_sequence_metadata_obu( + ObuMetaType::OBU_META_HDR_CLL, + &fi.sequence, + )?; + packet.write_all(&buf1).unwrap(); + buf1.clear(); + } + + if fi.sequence.mastering_display.is_some() { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_sequence_metadata_obu( + ObuMetaType::OBU_META_HDR_MDCV, + &fi.sequence, + )?; + packet.write_all(&buf1).unwrap(); + buf1.clear(); + } + + Ok(()) +} + +/// Write into `dst` the difference between the blocks at `src1` and `src2` +fn diff( + dst: &mut [MaybeUninit], src1: &PlaneRegion<'_, T>, + src2: &PlaneRegion<'_, T>, +) { + debug_assert!(dst.len() % src1.rect().width == 0); + debug_assert_eq!(src1.rows_iter().count(), src1.rect().height); + + let width = src1.rect().width; + let height = src1.rect().height; + + if width == 0 + || width != src2.rect().width + || height == 0 + || src1.rows_iter().len() != src2.rows_iter().len() + { + debug_assert!(false); + return; + } + + for ((l, s1), s2) in + dst.chunks_exact_mut(width).zip(src1.rows_iter()).zip(src2.rows_iter()) + { + for ((r, v1), v2) in l.iter_mut().zip(s1).zip(s2) { + r.write(i16::cast_from(*v1) - i16::cast_from(*v2)); + } + } +} + +fn get_qidx( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, cw: &ContextWriter, + tile_bo: TileBlockOffset, +) -> u8 { + let mut qidx = fi.base_q_idx; + let sidx = cw.bc.blocks[tile_bo].segmentation_idx as usize; + if ts.segmentation.features[sidx][SegLvl::SEG_LVL_ALT_Q as usize] { + let delta = ts.segmentation.data[sidx][SegLvl::SEG_LVL_ALT_Q as usize]; + qidx = clamp((qidx as i16) + delta, 0, 255) as u8; + } + qidx +} + +/// For a transform block, +/// predict, transform, quantize, write coefficients to a bitstream, +/// dequantize, inverse-transform. +/// +/// # Panics +/// +/// - If the block size is invalid for subsampling +/// - If a tx type other than DCT is used for 64x64 blocks +pub fn encode_tx_block( + fi: &FrameInvariants, + ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, + w: &mut W, + p: usize, + // Offset in the luma plane of the partition enclosing this block. + tile_partition_bo: TileBlockOffset, + // tx block position within a partition, unit: tx block number + bx: usize, + by: usize, + // Offset in the luma plane where this tx block is colocated. Note that for + // a chroma block, this offset might be outside of the current partition. + // For example in 4:2:0, four 4x4 luma partitions share one 4x4 chroma block, + // this block is part of the last 4x4 partition, but its `tx_bo` offset + // matches the offset of the first 4x4 partition. + tx_bo: TileBlockOffset, + mode: PredictionMode, + tx_size: TxSize, + tx_type: TxType, + bsize: BlockSize, + po: PlaneOffset, + skip: bool, + qidx: u8, + ac: &[i16], + pred_intra_param: IntraParam, + rdo_type: RDOType, + need_recon_pixel: bool, +) -> (bool, ScaledDistortion) { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[p].cfg; + let tile_rect = ts.tile_rect().decimated(xdec, ydec); + let area = Area::BlockRect { + bo: tx_bo.0, + width: tx_size.width(), + height: tx_size.height(), + }; + + if tx_bo.0.x >= ts.mi_width || tx_bo.0.y >= ts.mi_height { + return (false, ScaledDistortion::zero()); + } + + debug_assert!(tx_bo.0.x < ts.mi_width); + debug_assert!(tx_bo.0.y < ts.mi_height); + + debug_assert!( + tx_size.sqr() <= TxSize::TX_32X32 || tx_type == TxType::DCT_DCT + ); + + let plane_bsize = bsize.subsampled_size(xdec, ydec).unwrap(); + + debug_assert!(p != 0 || !mode.is_intra() || tx_size.block_size() == plane_bsize || need_recon_pixel, + "mode.is_intra()={:#?}, plane={:#?}, tx_size.block_size()={:#?}, plane_bsize={:#?}, need_recon_pixel={:#?}", + mode.is_intra(), p, tx_size.block_size(), plane_bsize, need_recon_pixel); + + let ief_params = if mode.is_directional() + && fi.sequence.enable_intra_edge_filter + { + let (plane_xdec, plane_ydec) = if p == 0 { (0, 0) } else { (xdec, ydec) }; + let above_block_info = + ts.above_block_info(tile_partition_bo, plane_xdec, plane_ydec); + let left_block_info = + ts.left_block_info(tile_partition_bo, plane_xdec, plane_ydec); + Some(IntraEdgeFilterParameters::new(p, above_block_info, left_block_info)) + } else { + None + }; + + let frame_bo = ts.to_frame_block_offset(tx_bo); + let rec = &mut ts.rec.planes[p]; + + if mode.is_intra() { + let bit_depth = fi.sequence.bit_depth; + let mut edge_buf = Aligned::uninit_array(); + let edge_buf = get_intra_edges( + &mut edge_buf, + &rec.as_const(), + tile_partition_bo, + bx, + by, + bsize, + po, + tx_size, + bit_depth, + Some(mode), + fi.sequence.enable_intra_edge_filter, + pred_intra_param, + ); + + mode.predict_intra( + tile_rect, + &mut rec.subregion_mut(area), + tx_size, + bit_depth, + ac, + pred_intra_param, + ief_params, + &edge_buf, + fi.cpu_feature_level, + ); + } + + if skip { + return (false, ScaledDistortion::zero()); + } + + let coded_tx_area = av1_get_coded_tx_size(tx_size).area(); + let mut residual = Aligned::<[MaybeUninit; 64 * 64]>::uninit_array(); + let mut coeffs = Aligned::<[MaybeUninit; 64 * 64]>::uninit_array(); + let mut qcoeffs = + Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + let mut rcoeffs = + Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + let residual = &mut residual.data[..tx_size.area()]; + let coeffs = &mut coeffs.data[..tx_size.area()]; + let qcoeffs = init_slice_repeat_mut( + &mut qcoeffs.data[..coded_tx_area], + T::Coeff::cast_from(0), + ); + let rcoeffs = &mut rcoeffs.data[..coded_tx_area]; + + let (visible_tx_w, visible_tx_h) = clip_visible_bsize( + (fi.width + xdec) >> xdec, + (fi.height + ydec) >> ydec, + tx_size.block_size(), + (frame_bo.0.x << MI_SIZE_LOG2) >> xdec, + (frame_bo.0.y << MI_SIZE_LOG2) >> ydec, + ); + + if visible_tx_w != 0 && visible_tx_h != 0 { + diff( + residual, + &ts.input_tile.planes[p].subregion(area), + &rec.subregion(area), + ); + } else { + residual.fill(MaybeUninit::new(0)); + } + // SAFETY: `diff()` inits `tx_size.area()` elements when it matches size of `subregion(area)` + let residual = unsafe { slice_assume_init_mut(residual) }; + + forward_transform( + residual, + coeffs, + tx_size.width(), + tx_size, + tx_type, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + // SAFETY: forward_transform initialized coeffs + let coeffs = unsafe { slice_assume_init_mut(coeffs) }; + + let eob = ts.qc.quantize(coeffs, qcoeffs, tx_size, tx_type); + + let has_coeff = if need_recon_pixel || rdo_type.needs_coeff_rate() { + debug_assert!((((fi.w_in_b - frame_bo.0.x) << MI_SIZE_LOG2) >> xdec) >= 4); + debug_assert!((((fi.h_in_b - frame_bo.0.y) << MI_SIZE_LOG2) >> ydec) >= 4); + let frame_clipped_txw: usize = + (((fi.w_in_b - frame_bo.0.x) << MI_SIZE_LOG2) >> xdec) + .min(tx_size.width()); + let frame_clipped_txh: usize = + (((fi.h_in_b - frame_bo.0.y) << MI_SIZE_LOG2) >> ydec) + .min(tx_size.height()); + + cw.write_coeffs_lv_map( + w, + p, + tx_bo, + qcoeffs, + eob, + mode, + tx_size, + tx_type, + plane_bsize, + xdec, + ydec, + fi.use_reduced_tx_set, + frame_clipped_txw, + frame_clipped_txh, + ) + } else { + true + }; + + // Reconstruct + dequantize( + qidx, + qcoeffs, + eob, + rcoeffs, + tx_size, + fi.sequence.bit_depth, + fi.dc_delta_q[p], + fi.ac_delta_q[p], + fi.cpu_feature_level, + ); + // SAFETY: dequantize initialized rcoeffs + let rcoeffs = unsafe { slice_assume_init_mut(rcoeffs) }; + + if eob == 0 { + // All zero coefficients is a no-op + } else if !fi.use_tx_domain_distortion || need_recon_pixel { + inverse_transform_add( + rcoeffs, + &mut rec.subregion_mut(area), + eob, + tx_size, + tx_type, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + } + + let tx_dist = + if rdo_type.needs_tx_dist() && visible_tx_w != 0 && visible_tx_h != 0 { + // Store tx-domain distortion of this block + // rcoeffs above 32 rows/cols aren't held in the array, because they are + // always 0. The first 32x32 is stored first in coeffs so we can iterate + // over coeffs and rcoeffs for the first 32 rows/cols. For the + // coefficients above 32 rows/cols, we iterate over the rest of coeffs + // with the assumption that rcoeff coefficients are zero. + let mut raw_tx_dist = coeffs + .iter() + .zip(rcoeffs.iter()) + .map(|(&a, &b)| { + let c = i32::cast_from(a) - i32::cast_from(b); + (c * c) as u64 + }) + .sum::() + + coeffs[rcoeffs.len()..] + .iter() + .map(|&a| { + let c = i32::cast_from(a); + (c * c) as u64 + }) + .sum::(); + + let tx_dist_scale_bits = 2 * (3 - get_log_tx_scale(tx_size)); + let tx_dist_scale_rounding_offset = 1 << (tx_dist_scale_bits - 1); + + raw_tx_dist = + (raw_tx_dist + tx_dist_scale_rounding_offset) >> tx_dist_scale_bits; + + if rdo_type == RDOType::TxDistEstRate { + // look up rate and distortion in table + let estimated_rate = + estimate_rate(fi.base_q_idx, tx_size, raw_tx_dist); + w.add_bits_frac(estimated_rate as u32); + } + + let bias = distortion_scale(fi, ts.to_frame_block_offset(tx_bo), bsize); + RawDistortion::new(raw_tx_dist) * bias * fi.dist_scale[p] + } else { + ScaledDistortion::zero() + }; + + (has_coeff, tx_dist) +} + +/// # Panics +/// +/// - If the block size is invalid for subsampling +#[profiling::function] +pub fn motion_compensate( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, luma_mode: PredictionMode, ref_frames: [RefType; 2], + mvs: [MotionVector; 2], bsize: BlockSize, tile_bo: TileBlockOffset, + luma_only: bool, +) { + debug_assert!(!luma_mode.is_intra()); + + let PlaneConfig { xdec: u_xdec, ydec: u_ydec, .. } = ts.input.planes[1].cfg; + + // Inter mode prediction can take place once for a whole partition, + // instead of each tx-block. + let num_planes = 1 + + if !luma_only + && has_chroma( + tile_bo, + bsize, + u_xdec, + u_ydec, + fi.sequence.chroma_sampling, + ) { + 2 + } else { + 0 + }; + + let luma_tile_rect = ts.tile_rect(); + let compound_buffer = &mut ts.inter_compound_buffers; + for p in 0..num_planes { + let plane_bsize = if p == 0 { + bsize + } else { + bsize.subsampled_size(u_xdec, u_ydec).unwrap() + }; + + let rec = &mut ts.rec.planes[p]; + let po = tile_bo.plane_offset(rec.plane_cfg); + let &PlaneConfig { xdec, ydec, .. } = rec.plane_cfg; + let tile_rect = luma_tile_rect.decimated(xdec, ydec); + + let area = Area::BlockStartingAt { bo: tile_bo.0 }; + if p > 0 && bsize < BlockSize::BLOCK_8X8 { + let mut some_use_intra = false; + if bsize == BlockSize::BLOCK_4X4 || bsize == BlockSize::BLOCK_4X8 { + some_use_intra |= + cw.bc.blocks[tile_bo.with_offset(-1, 0)].mode.is_intra(); + }; + if !some_use_intra && bsize == BlockSize::BLOCK_4X4 + || bsize == BlockSize::BLOCK_8X4 + { + some_use_intra |= + cw.bc.blocks[tile_bo.with_offset(0, -1)].mode.is_intra(); + }; + if !some_use_intra && bsize == BlockSize::BLOCK_4X4 { + some_use_intra |= + cw.bc.blocks[tile_bo.with_offset(-1, -1)].mode.is_intra(); + }; + + if some_use_intra { + luma_mode.predict_inter( + fi, + tile_rect, + p, + po, + &mut rec.subregion_mut(area), + plane_bsize.width(), + plane_bsize.height(), + ref_frames, + mvs, + compound_buffer, + ); + } else { + assert!(u_xdec == 1 && u_ydec == 1); + // TODO: these are absolutely only valid for 4:2:0 + if bsize == BlockSize::BLOCK_4X4 { + let mv0 = cw.bc.blocks[tile_bo.with_offset(-1, -1)].mv; + let rf0 = cw.bc.blocks[tile_bo.with_offset(-1, -1)].ref_frames; + let mv1 = cw.bc.blocks[tile_bo.with_offset(0, -1)].mv; + let rf1 = cw.bc.blocks[tile_bo.with_offset(0, -1)].ref_frames; + let po1 = PlaneOffset { x: po.x + 2, y: po.y }; + let area1 = Area::StartingAt { x: po1.x, y: po1.y }; + let mv2 = cw.bc.blocks[tile_bo.with_offset(-1, 0)].mv; + let rf2 = cw.bc.blocks[tile_bo.with_offset(-1, 0)].ref_frames; + let po2 = PlaneOffset { x: po.x, y: po.y + 2 }; + let area2 = Area::StartingAt { x: po2.x, y: po2.y }; + let po3 = PlaneOffset { x: po.x + 2, y: po.y + 2 }; + let area3 = Area::StartingAt { x: po3.x, y: po3.y }; + luma_mode.predict_inter( + fi, + tile_rect, + p, + po, + &mut rec.subregion_mut(area), + 2, + 2, + rf0, + mv0, + compound_buffer, + ); + luma_mode.predict_inter( + fi, + tile_rect, + p, + po1, + &mut rec.subregion_mut(area1), + 2, + 2, + rf1, + mv1, + compound_buffer, + ); + luma_mode.predict_inter( + fi, + tile_rect, + p, + po2, + &mut rec.subregion_mut(area2), + 2, + 2, + rf2, + mv2, + compound_buffer, + ); + luma_mode.predict_inter( + fi, + tile_rect, + p, + po3, + &mut rec.subregion_mut(area3), + 2, + 2, + ref_frames, + mvs, + compound_buffer, + ); + } + if bsize == BlockSize::BLOCK_8X4 { + let mv1 = cw.bc.blocks[tile_bo.with_offset(0, -1)].mv; + let rf1 = cw.bc.blocks[tile_bo.with_offset(0, -1)].ref_frames; + luma_mode.predict_inter( + fi, + tile_rect, + p, + po, + &mut rec.subregion_mut(area), + 4, + 2, + rf1, + mv1, + compound_buffer, + ); + let po3 = PlaneOffset { x: po.x, y: po.y + 2 }; + let area3 = Area::StartingAt { x: po3.x, y: po3.y }; + luma_mode.predict_inter( + fi, + tile_rect, + p, + po3, + &mut rec.subregion_mut(area3), + 4, + 2, + ref_frames, + mvs, + compound_buffer, + ); + } + if bsize == BlockSize::BLOCK_4X8 { + let mv2 = cw.bc.blocks[tile_bo.with_offset(-1, 0)].mv; + let rf2 = cw.bc.blocks[tile_bo.with_offset(-1, 0)].ref_frames; + luma_mode.predict_inter( + fi, + tile_rect, + p, + po, + &mut rec.subregion_mut(area), + 2, + 4, + rf2, + mv2, + compound_buffer, + ); + let po3 = PlaneOffset { x: po.x + 2, y: po.y }; + let area3 = Area::StartingAt { x: po3.x, y: po3.y }; + luma_mode.predict_inter( + fi, + tile_rect, + p, + po3, + &mut rec.subregion_mut(area3), + 2, + 4, + ref_frames, + mvs, + compound_buffer, + ); + } + } + } else { + luma_mode.predict_inter( + fi, + tile_rect, + p, + po, + &mut rec.subregion_mut(area), + plane_bsize.width(), + plane_bsize.height(), + ref_frames, + mvs, + compound_buffer, + ); + } + } +} + +pub fn save_block_motion( + ts: &mut TileStateMut<'_, T>, bsize: BlockSize, tile_bo: TileBlockOffset, + ref_frame: usize, mv: MotionVector, +) { + let tile_me_stats = &mut ts.me_stats[ref_frame]; + let tile_bo_x_end = (tile_bo.0.x + bsize.width_mi()).min(ts.mi_width); + let tile_bo_y_end = (tile_bo.0.y + bsize.height_mi()).min(ts.mi_height); + for mi_y in tile_bo.0.y..tile_bo_y_end { + for mi_x in tile_bo.0.x..tile_bo_x_end { + tile_me_stats[mi_y][mi_x].mv = mv; + } + } +} + +#[profiling::function] +pub fn encode_block_pre_cdef( + seq: &Sequence, ts: &TileStateMut<'_, T>, cw: &mut ContextWriter, w: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, skip: bool, +) -> bool { + cw.bc.blocks.set_skip(tile_bo, bsize, skip); + if ts.segmentation.enabled + && ts.segmentation.update_map + && ts.segmentation.preskip + { + cw.write_segmentation( + w, + tile_bo, + bsize, + false, + ts.segmentation.last_active_segid, + ); + } + cw.write_skip(w, tile_bo, skip); + if ts.segmentation.enabled + && ts.segmentation.update_map + && !ts.segmentation.preskip + { + cw.write_segmentation( + w, + tile_bo, + bsize, + skip, + ts.segmentation.last_active_segid, + ); + } + if !skip && seq.enable_cdef { + cw.bc.cdef_coded = true; + } + cw.bc.cdef_coded +} + +/// # Panics +/// +/// - If chroma and luma do not match for inter modes +/// - If an invalid motion vector is found +#[profiling::function] +pub fn encode_block_post_cdef( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w: &mut W, luma_mode: PredictionMode, + chroma_mode: PredictionMode, angle_delta: AngleDelta, + ref_frames: [RefType; 2], mvs: [MotionVector; 2], bsize: BlockSize, + tile_bo: TileBlockOffset, skip: bool, cfl: CFLParams, tx_size: TxSize, + tx_type: TxType, mode_context: usize, mv_stack: &[CandidateMV], + rdo_type: RDOType, need_recon_pixel: bool, + enc_stats: Option<&mut EncoderStats>, +) -> (bool, ScaledDistortion) { + let planes = + if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + let is_inter = !luma_mode.is_intra(); + if is_inter { + assert!(luma_mode == chroma_mode); + }; + let sb_size = if fi.sequence.use_128x128_superblock { + BlockSize::BLOCK_128X128 + } else { + BlockSize::BLOCK_64X64 + }; + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + if skip { + cw.bc.reset_skip_context( + tile_bo, + bsize, + xdec, + ydec, + fi.sequence.chroma_sampling, + ); + } + cw.bc.blocks.set_block_size(tile_bo, bsize); + cw.bc.blocks.set_mode(tile_bo, bsize, luma_mode); + cw.bc.blocks.set_tx_size(tile_bo, bsize, tx_size); + cw.bc.blocks.set_ref_frames(tile_bo, bsize, ref_frames); + cw.bc.blocks.set_motion_vectors(tile_bo, bsize, mvs); + + //write_q_deltas(); + if cw.bc.code_deltas + && ts.deblock.block_deltas_enabled + && (bsize < sb_size || !skip) + { + cw.write_block_deblock_deltas( + w, + tile_bo, + ts.deblock.block_delta_multi, + planes, + ); + } + cw.bc.code_deltas = false; + + if fi.frame_type.has_inter() { + cw.write_is_inter(w, tile_bo, is_inter); + if is_inter { + cw.fill_neighbours_ref_counts(tile_bo); + cw.write_ref_frames(w, fi, tile_bo); + + if luma_mode.is_compound() { + cw.write_compound_mode(w, luma_mode, mode_context); + } else { + cw.write_inter_mode(w, luma_mode, mode_context); + } + + let ref_mv_idx = 0; + let num_mv_found = mv_stack.len(); + + if luma_mode == PredictionMode::NEWMV + || luma_mode == PredictionMode::NEW_NEWMV + { + if luma_mode == PredictionMode::NEW_NEWMV { + assert!(num_mv_found >= 2); + } + for idx in 0..2 { + if num_mv_found > idx + 1 { + let drl_mode = ref_mv_idx > idx; + let ctx: usize = (mv_stack[idx].weight < REF_CAT_LEVEL) as usize + + (mv_stack[idx + 1].weight < REF_CAT_LEVEL) as usize; + cw.write_drl_mode(w, drl_mode, ctx); + if !drl_mode { + break; + } + } + } + } + + let ref_mvs = if num_mv_found > 0 { + [mv_stack[ref_mv_idx].this_mv, mv_stack[ref_mv_idx].comp_mv] + } else { + [MotionVector::default(); 2] + }; + + let mv_precision = if fi.force_integer_mv != 0 { + MvSubpelPrecision::MV_SUBPEL_NONE + } else if fi.allow_high_precision_mv { + MvSubpelPrecision::MV_SUBPEL_HIGH_PRECISION + } else { + MvSubpelPrecision::MV_SUBPEL_LOW_PRECISION + }; + + if luma_mode == PredictionMode::NEWMV + || luma_mode == PredictionMode::NEW_NEWMV + || luma_mode == PredictionMode::NEW_NEARESTMV + { + cw.write_mv(w, mvs[0], ref_mvs[0], mv_precision); + } + if luma_mode == PredictionMode::NEW_NEWMV + || luma_mode == PredictionMode::NEAREST_NEWMV + { + cw.write_mv(w, mvs[1], ref_mvs[1], mv_precision); + } + + if luma_mode.has_nearmv() { + let ref_mv_idx = luma_mode.ref_mv_idx(); + if luma_mode != PredictionMode::NEAR0MV { + assert!(num_mv_found > ref_mv_idx); + } + + for idx in 1..3 { + if num_mv_found > idx + 1 { + let drl_mode = ref_mv_idx > idx; + let ctx: usize = (mv_stack[idx].weight < REF_CAT_LEVEL) as usize + + (mv_stack[idx + 1].weight < REF_CAT_LEVEL) as usize; + + cw.write_drl_mode(w, drl_mode, ctx); + if !drl_mode { + break; + } + } + } + if mv_stack.len() > 1 { + assert!(mv_stack[ref_mv_idx].this_mv.row == mvs[0].row); + assert!(mv_stack[ref_mv_idx].this_mv.col == mvs[0].col); + } else { + assert!(0 == mvs[0].row); + assert!(0 == mvs[0].col); + } + } else if luma_mode == PredictionMode::NEARESTMV { + if mv_stack.is_empty() { + assert_eq!(mvs[0].row, 0); + assert_eq!(mvs[0].col, 0); + } else { + assert_eq!(mvs[0].row, mv_stack[0].this_mv.row); + assert_eq!(mvs[0].col, mv_stack[0].this_mv.col); + } + } + } else { + cw.write_intra_mode(w, bsize, luma_mode); + } + } else { + cw.write_intra_mode_kf(w, tile_bo, luma_mode); + } + + if !is_inter { + if luma_mode.is_directional() && bsize >= BlockSize::BLOCK_8X8 { + cw.write_angle_delta(w, angle_delta.y, luma_mode); + } + if has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling) { + cw.write_intra_uv_mode(w, chroma_mode, luma_mode, bsize); + if chroma_mode.is_cfl() { + assert!(bsize.cfl_allowed()); + cw.write_cfl_alphas(w, cfl); + } + if chroma_mode.is_directional() && bsize >= BlockSize::BLOCK_8X8 { + cw.write_angle_delta(w, angle_delta.uv, chroma_mode); + } + } + + if fi.allow_screen_content_tools > 0 + && bsize >= BlockSize::BLOCK_8X8 + && bsize.width() <= 64 + && bsize.height() <= 64 + { + cw.write_use_palette_mode( + w, + false, + bsize, + tile_bo, + luma_mode, + chroma_mode, + xdec, + ydec, + fi.sequence.chroma_sampling, + ); + } + + if fi.sequence.enable_filter_intra + && luma_mode == PredictionMode::DC_PRED + && bsize.width() <= 32 + && bsize.height() <= 32 + { + cw.write_use_filter_intra(w, false, bsize); // turn off FILTER_INTRA + } + } + + // write tx_size here + if fi.tx_mode_select { + if bsize > BlockSize::BLOCK_4X4 && (!is_inter || !skip) { + if !is_inter { + cw.write_tx_size_intra(w, tile_bo, bsize, tx_size); + cw.bc.update_tx_size_context(tile_bo, bsize, tx_size, false); + } else { + // write var_tx_size + // if here, bsize > BLOCK_4X4 && is_inter && !skip && !Lossless + debug_assert!(fi.tx_mode_select); + debug_assert!(bsize > BlockSize::BLOCK_4X4); + debug_assert!(is_inter); + debug_assert!(!skip); + let max_tx_size = max_txsize_rect_lookup[bsize as usize]; + debug_assert!(max_tx_size.block_size() <= BlockSize::BLOCK_64X64); + + //TODO: "&& tx_size.block_size() < bsize" will be replaced with tx-split info for a partition + // once it is available. + let txfm_split = + fi.enable_inter_txfm_split && tx_size.block_size() < bsize; + + // TODO: Revise write_tx_size_inter() for txfm_split = true + cw.write_tx_size_inter( + w, + tile_bo, + bsize, + max_tx_size, + txfm_split, + 0, + 0, + 0, + ); + } + } else { + debug_assert!(bsize == BlockSize::BLOCK_4X4 || (is_inter && skip)); + cw.bc.update_tx_size_context(tile_bo, bsize, tx_size, is_inter && skip); + } + } + + if let Some(enc_stats) = enc_stats { + let pixels = tx_size.area(); + enc_stats.block_size_counts[bsize as usize] += pixels; + enc_stats.tx_type_counts[tx_type as usize] += pixels; + enc_stats.luma_pred_mode_counts[luma_mode as usize] += pixels; + enc_stats.chroma_pred_mode_counts[chroma_mode as usize] += pixels; + if skip { + enc_stats.skip_block_count += pixels; + } + } + + if fi.sequence.enable_intra_edge_filter { + for y in 0..bsize.height_mi() { + if tile_bo.0.y + y >= ts.mi_height { + continue; + } + for x in 0..bsize.width_mi() { + if tile_bo.0.x + x >= ts.mi_width { + continue; + } + let bi = &mut ts.coded_block_info[tile_bo.0.y + y][tile_bo.0.x + x]; + bi.luma_mode = luma_mode; + bi.chroma_mode = chroma_mode; + bi.reference_types = ref_frames; + } + } + } + + if is_inter { + motion_compensate( + fi, ts, cw, luma_mode, ref_frames, mvs, bsize, tile_bo, false, + ); + write_tx_tree( + fi, + ts, + cw, + w, + luma_mode, + angle_delta.y, + tile_bo, + bsize, + tx_size, + tx_type, + skip, + false, + rdo_type, + need_recon_pixel, + ) + } else { + write_tx_blocks( + fi, + ts, + cw, + w, + luma_mode, + chroma_mode, + angle_delta, + tile_bo, + bsize, + tx_size, + tx_type, + skip, + cfl, + false, + rdo_type, + need_recon_pixel, + ) + } +} + +/// # Panics +/// +/// - If attempting to encode a lossless block (not yet supported) +pub fn write_tx_blocks( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w: &mut W, luma_mode: PredictionMode, + chroma_mode: PredictionMode, angle_delta: AngleDelta, + tile_bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize, + tx_type: TxType, skip: bool, cfl: CFLParams, luma_only: bool, + rdo_type: RDOType, need_recon_pixel: bool, +) -> (bool, ScaledDistortion) { + let bw = bsize.width_mi() / tx_size.width_mi(); + let bh = bsize.height_mi() / tx_size.height_mi(); + let qidx = get_qidx(fi, ts, cw, tile_bo); + + // TODO: Lossless is not yet supported. + if !skip { + assert_ne!(qidx, 0); + } + + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let mut ac = Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + let mut partition_has_coeff: bool = false; + let mut tx_dist = ScaledDistortion::zero(); + let do_chroma = + has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling); + + ts.qc.update( + qidx, + tx_size, + luma_mode.is_intra(), + fi.sequence.bit_depth, + fi.dc_delta_q[0], + 0, + ); + + for by in 0..bh { + for bx in 0..bw { + let tx_bo = TileBlockOffset(BlockOffset { + x: tile_bo.0.x + bx * tx_size.width_mi(), + y: tile_bo.0.y + by * tx_size.height_mi(), + }); + if tx_bo.0.x >= ts.mi_width || tx_bo.0.y >= ts.mi_height { + continue; + } + let po = tx_bo.plane_offset(&ts.input.planes[0].cfg); + let (has_coeff, dist) = encode_tx_block( + fi, + ts, + cw, + w, + 0, + tile_bo, + bx, + by, + tx_bo, + luma_mode, + tx_size, + tx_type, + bsize, + po, + skip, + qidx, + &[], + IntraParam::AngleDelta(angle_delta.y), + rdo_type, + need_recon_pixel, + ); + partition_has_coeff |= has_coeff; + tx_dist += dist; + } + } + + if !do_chroma + || luma_only + || fi.sequence.chroma_sampling == ChromaSampling::Cs400 + { + return (partition_has_coeff, tx_dist); + }; + debug_assert!(has_chroma( + tile_bo, + bsize, + xdec, + ydec, + fi.sequence.chroma_sampling + )); + + let uv_tx_size = bsize.largest_chroma_tx_size(xdec, ydec); + + let mut bw_uv = (bw * tx_size.width_mi()) >> xdec; + let mut bh_uv = (bh * tx_size.height_mi()) >> ydec; + + if bw_uv == 0 || bh_uv == 0 { + bw_uv = 1; + bh_uv = 1; + } + + bw_uv /= uv_tx_size.width_mi(); + bh_uv /= uv_tx_size.height_mi(); + + let ac_data = if chroma_mode.is_cfl() { + luma_ac(&mut ac.data, ts, tile_bo, bsize, tx_size, fi) + } else { + [].as_slice() + }; + + let uv_tx_type = if uv_tx_size.width() >= 32 || uv_tx_size.height() >= 32 { + TxType::DCT_DCT + } else { + uv_intra_mode_to_tx_type_context(chroma_mode) + }; + + for p in 1..3 { + ts.qc.update( + qidx, + uv_tx_size, + true, + fi.sequence.bit_depth, + fi.dc_delta_q[p], + fi.ac_delta_q[p], + ); + let alpha = cfl.alpha(p - 1); + for by in 0..bh_uv { + for bx in 0..bw_uv { + let tx_bo = TileBlockOffset(BlockOffset { + x: tile_bo.0.x + ((bx * uv_tx_size.width_mi()) << xdec) + - ((bw * tx_size.width_mi() == 1) as usize) * xdec, + y: tile_bo.0.y + ((by * uv_tx_size.height_mi()) << ydec) + - ((bh * tx_size.height_mi() == 1) as usize) * ydec, + }); + + let mut po = tile_bo.plane_offset(&ts.input.planes[p].cfg); + po.x += (bx * uv_tx_size.width()) as isize; + po.y += (by * uv_tx_size.height()) as isize; + let (has_coeff, dist) = encode_tx_block( + fi, + ts, + cw, + w, + p, + tile_bo, + bx, + by, + tx_bo, + chroma_mode, + uv_tx_size, + uv_tx_type, + bsize, + po, + skip, + qidx, + ac_data, + if chroma_mode.is_cfl() { + IntraParam::Alpha(alpha) + } else { + IntraParam::AngleDelta(angle_delta.uv) + }, + rdo_type, + need_recon_pixel, + ); + partition_has_coeff |= has_coeff; + tx_dist += dist; + } + } + } + + (partition_has_coeff, tx_dist) +} + +pub fn write_tx_tree( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w: &mut W, luma_mode: PredictionMode, + angle_delta_y: i8, tile_bo: TileBlockOffset, bsize: BlockSize, + tx_size: TxSize, tx_type: TxType, skip: bool, luma_only: bool, + rdo_type: RDOType, need_recon_pixel: bool, +) -> (bool, ScaledDistortion) { + if skip { + return (false, ScaledDistortion::zero()); + } + let bw = bsize.width_mi() / tx_size.width_mi(); + let bh = bsize.height_mi() / tx_size.height_mi(); + let qidx = get_qidx(fi, ts, cw, tile_bo); + + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let ac = &[0i16; 0]; + let mut partition_has_coeff: bool = false; + let mut tx_dist = ScaledDistortion::zero(); + + ts.qc.update( + qidx, + tx_size, + luma_mode.is_intra(), + fi.sequence.bit_depth, + fi.dc_delta_q[0], + 0, + ); + + // TODO: If tx-parition more than only 1-level, this code does not work. + // It should recursively traverse the tx block that are split recursivelty by calling write_tx_tree(), + // as defined in https://aomediacodec.github.io/av1-spec/#transform-tree-syntax + for by in 0..bh { + for bx in 0..bw { + let tx_bo = TileBlockOffset(BlockOffset { + x: tile_bo.0.x + bx * tx_size.width_mi(), + y: tile_bo.0.y + by * tx_size.height_mi(), + }); + if tx_bo.0.x >= ts.mi_width || tx_bo.0.y >= ts.mi_height { + continue; + } + + let po = tx_bo.plane_offset(&ts.input.planes[0].cfg); + let (has_coeff, dist) = encode_tx_block( + fi, + ts, + cw, + w, + 0, + tile_bo, + 0, + 0, + tx_bo, + luma_mode, + tx_size, + tx_type, + bsize, + po, + skip, + qidx, + ac, + IntraParam::AngleDelta(angle_delta_y), + rdo_type, + need_recon_pixel, + ); + partition_has_coeff |= has_coeff; + tx_dist += dist; + } + } + + if !has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling) + || luma_only + || fi.sequence.chroma_sampling == ChromaSampling::Cs400 + { + return (partition_has_coeff, tx_dist); + }; + debug_assert!(has_chroma( + tile_bo, + bsize, + xdec, + ydec, + fi.sequence.chroma_sampling + )); + + let max_tx_size = max_txsize_rect_lookup[bsize as usize]; + debug_assert!(max_tx_size.block_size() <= BlockSize::BLOCK_64X64); + let uv_tx_size = bsize.largest_chroma_tx_size(xdec, ydec); + + let mut bw_uv = max_tx_size.width_mi() >> xdec; + let mut bh_uv = max_tx_size.height_mi() >> ydec; + + if bw_uv == 0 || bh_uv == 0 { + bw_uv = 1; + bh_uv = 1; + } + + bw_uv /= uv_tx_size.width_mi(); + bh_uv /= uv_tx_size.height_mi(); + + let uv_tx_type = if partition_has_coeff { + tx_type.uv_inter(uv_tx_size) + } else { + TxType::DCT_DCT + }; + + for p in 1..3 { + ts.qc.update( + qidx, + uv_tx_size, + false, + fi.sequence.bit_depth, + fi.dc_delta_q[p], + fi.ac_delta_q[p], + ); + + for by in 0..bh_uv { + for bx in 0..bw_uv { + let tx_bo = TileBlockOffset(BlockOffset { + x: tile_bo.0.x + ((bx * uv_tx_size.width_mi()) << xdec) + - (max_tx_size.width_mi() == 1) as usize * xdec, + y: tile_bo.0.y + ((by * uv_tx_size.height_mi()) << ydec) + - (max_tx_size.height_mi() == 1) as usize * ydec, + }); + + let mut po = tile_bo.plane_offset(&ts.input.planes[p].cfg); + po.x += (bx * uv_tx_size.width()) as isize; + po.y += (by * uv_tx_size.height()) as isize; + let (has_coeff, dist) = encode_tx_block( + fi, + ts, + cw, + w, + p, + tile_bo, + bx, + by, + tx_bo, + luma_mode, + uv_tx_size, + uv_tx_type, + bsize, + po, + skip, + qidx, + ac, + IntraParam::AngleDelta(angle_delta_y), + rdo_type, + need_recon_pixel, + ); + partition_has_coeff |= has_coeff; + tx_dist += dist; + } + } + } + + (partition_has_coeff, tx_dist) +} + +#[profiling::function] +pub fn encode_block_with_modes( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w_pre_cdef: &mut W, w_post_cdef: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, + mode_decision: &PartitionParameters, rdo_type: RDOType, + enc_stats: Option<&mut EncoderStats>, +) { + let (mode_luma, mode_chroma) = + (mode_decision.pred_mode_luma, mode_decision.pred_mode_chroma); + let cfl = mode_decision.pred_cfl_params; + let ref_frames = mode_decision.ref_frames; + let mvs = mode_decision.mvs; + let mut skip = mode_decision.skip; + let mut cdef_coded = cw.bc.cdef_coded; + + // Set correct segmentation ID before encoding and before + // rdo_tx_size_type(). + cw.bc.blocks.set_segmentation_idx(tile_bo, bsize, mode_decision.sidx); + + let mut mv_stack = ArrayVec::::new(); + let is_compound = ref_frames[1] != NONE_FRAME; + let mode_context = + cw.find_mvrefs(tile_bo, ref_frames, &mut mv_stack, bsize, fi, is_compound); + + let (tx_size, tx_type) = if !mode_decision.skip && !mode_decision.has_coeff { + skip = true; + rdo_tx_size_type( + fi, ts, cw, bsize, tile_bo, mode_luma, ref_frames, mvs, skip, + ) + } else { + (mode_decision.tx_size, mode_decision.tx_type) + }; + + cdef_coded = encode_block_pre_cdef( + &fi.sequence, + ts, + cw, + if cdef_coded { w_post_cdef } else { w_pre_cdef }, + bsize, + tile_bo, + skip, + ); + encode_block_post_cdef( + fi, + ts, + cw, + if cdef_coded { w_post_cdef } else { w_pre_cdef }, + mode_luma, + mode_chroma, + mode_decision.angle_delta, + ref_frames, + mvs, + bsize, + tile_bo, + skip, + cfl, + tx_size, + tx_type, + mode_context, + &mv_stack, + rdo_type, + true, + enc_stats, + ); +} + +#[profiling::function] +fn encode_partition_bottomup( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w_pre_cdef: &mut W, w_post_cdef: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, ref_rd_cost: f64, + inter_cfg: &InterConfig, enc_stats: &mut EncoderStats, +) -> PartitionGroupParameters { + let rdo_type = RDOType::PixelDistRealRate; + let mut rd_cost = f64::MAX; + let mut best_rd = f64::MAX; + let mut rdo_output = PartitionGroupParameters { + rd_cost, + part_type: PartitionType::PARTITION_INVALID, + part_modes: ArrayVec::new(), + }; + + if tile_bo.0.x >= ts.mi_width || tile_bo.0.y >= ts.mi_height { + return rdo_output; + } + + let is_square = bsize.is_sqr(); + let hbs = bsize.width_mi() / 2; + let has_cols = tile_bo.0.x + hbs < ts.mi_width; + let has_rows = tile_bo.0.y + hbs < ts.mi_height; + let is_straddle_x = tile_bo.0.x + bsize.width_mi() > ts.mi_width; + let is_straddle_y = tile_bo.0.y + bsize.height_mi() > ts.mi_height; + + // TODO: Update for 128x128 superblocks + assert!(fi.partition_range.max <= BlockSize::BLOCK_64X64); + + let must_split = + is_square && (bsize > fi.partition_range.max || !has_cols || !has_rows); + + let can_split = // FIXME: sub-8x8 inter blocks not supported for non-4:2:0 sampling + if fi.frame_type.has_inter() && + fi.sequence.chroma_sampling != ChromaSampling::Cs420 && + bsize <= BlockSize::BLOCK_8X8 { + false + } else { + (bsize > fi.partition_range.min && is_square) || must_split + }; + + assert!(bsize >= BlockSize::BLOCK_8X8 || !can_split); + + let mut best_partition = PartitionType::PARTITION_INVALID; + + let cw_checkpoint = cw.checkpoint(&tile_bo, fi.sequence.chroma_sampling); + let w_pre_checkpoint = w_pre_cdef.checkpoint(); + let w_post_checkpoint = w_post_cdef.checkpoint(); + + // Code the whole block + if !must_split { + let cost = if bsize >= BlockSize::BLOCK_8X8 && is_square { + let w: &mut W = if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + let tell = w.tell_frac(); + cw.write_partition(w, tile_bo, PartitionType::PARTITION_NONE, bsize); + compute_rd_cost(fi, w.tell_frac() - tell, ScaledDistortion::zero()) + } else { + 0.0 + }; + + let mode_decision = + rdo_mode_decision(fi, ts, cw, bsize, tile_bo, inter_cfg); + + if !mode_decision.pred_mode_luma.is_intra() { + // Fill the saved motion structure + save_block_motion( + ts, + mode_decision.bsize, + mode_decision.bo, + mode_decision.ref_frames[0].to_index(), + mode_decision.mvs[0], + ); + } + + rd_cost = mode_decision.rd_cost + cost; + + best_partition = PartitionType::PARTITION_NONE; + best_rd = rd_cost; + rdo_output.part_modes.push(mode_decision.clone()); + + if !can_split { + encode_block_with_modes( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + bsize, + tile_bo, + &mode_decision, + rdo_type, + Some(enc_stats), + ); + } + } // if !must_split + + let mut early_exit = false; + + // Test all partition types other than PARTITION_NONE by comparing their RD costs + if can_split { + debug_assert!(is_square); + + let mut partition_types = ArrayVec::::new(); + if bsize + <= fi.config.speed_settings.partition.non_square_partition_max_threshold + || is_straddle_x + || is_straddle_y + { + if has_cols { + partition_types.push(PartitionType::PARTITION_HORZ); + } + if !(fi.sequence.chroma_sampling == ChromaSampling::Cs422) && has_rows { + partition_types.push(PartitionType::PARTITION_VERT); + } + } + partition_types.push(PartitionType::PARTITION_SPLIT); + + for partition in partition_types { + // (!has_rows || !has_cols) --> must_split + debug_assert!((has_rows && has_cols) || must_split); + // (!has_rows && has_cols) --> partition != PartitionType::PARTITION_VERT + debug_assert!( + has_rows || !has_cols || (partition != PartitionType::PARTITION_VERT) + ); + // (has_rows && !has_cols) --> partition != PartitionType::PARTITION_HORZ + debug_assert!( + !has_rows || has_cols || (partition != PartitionType::PARTITION_HORZ) + ); + // (!has_rows && !has_cols) --> partition == PartitionType::PARTITION_SPLIT + debug_assert!( + has_rows || has_cols || (partition == PartitionType::PARTITION_SPLIT) + ); + + cw.rollback(&cw_checkpoint); + w_pre_cdef.rollback(&w_pre_checkpoint); + w_post_cdef.rollback(&w_post_checkpoint); + + let subsize = bsize.subsize(partition).unwrap(); + let hbsw = subsize.width_mi(); // Half the block size width in blocks + let hbsh = subsize.height_mi(); // Half the block size height in blocks + let mut child_modes = ArrayVec::::new(); + rd_cost = 0.0; + + if bsize >= BlockSize::BLOCK_8X8 { + let w: &mut W = + if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + let tell = w.tell_frac(); + cw.write_partition(w, tile_bo, partition, bsize); + rd_cost = + compute_rd_cost(fi, w.tell_frac() - tell, ScaledDistortion::zero()); + } + + let four_partitions = [ + tile_bo, + TileBlockOffset(BlockOffset { x: tile_bo.0.x + hbsw, y: tile_bo.0.y }), + TileBlockOffset(BlockOffset { x: tile_bo.0.x, y: tile_bo.0.y + hbsh }), + TileBlockOffset(BlockOffset { + x: tile_bo.0.x + hbsw, + y: tile_bo.0.y + hbsh, + }), + ]; + let partitions = get_sub_partitions(&four_partitions, partition); + + early_exit = false; + // If either of horz or vert partition types is being tested, + // two partitioned rectangles, defined in 'partitions', of the current block + // is passed to encode_partition_bottomup() + for offset in partitions { + if offset.0.x >= ts.mi_width || offset.0.y >= ts.mi_height { + continue; + } + let child_rdo_output = encode_partition_bottomup( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + subsize, + offset, + best_rd, + inter_cfg, + enc_stats, + ); + let cost = child_rdo_output.rd_cost; + assert!(cost >= 0.0); + + if cost != f64::MAX { + rd_cost += cost; + if !must_split + && fi.enable_early_exit + && (rd_cost >= best_rd || rd_cost >= ref_rd_cost) + { + assert!(cost != f64::MAX); + early_exit = true; + break; + } else if partition != PartitionType::PARTITION_SPLIT { + child_modes.push(child_rdo_output.part_modes[0].clone()); + } + } + } + + if !early_exit && rd_cost < best_rd { + best_rd = rd_cost; + best_partition = partition; + if partition != PartitionType::PARTITION_SPLIT { + assert!(!child_modes.is_empty()); + rdo_output.part_modes = child_modes; + } + } + } + + debug_assert!( + early_exit || best_partition != PartitionType::PARTITION_INVALID + ); + + // If the best partition is not PARTITION_SPLIT, recode it + if best_partition != PartitionType::PARTITION_SPLIT { + assert!(!rdo_output.part_modes.is_empty()); + cw.rollback(&cw_checkpoint); + w_pre_cdef.rollback(&w_pre_checkpoint); + w_post_cdef.rollback(&w_post_checkpoint); + + assert!(best_partition != PartitionType::PARTITION_NONE || !must_split); + let subsize = bsize.subsize(best_partition).unwrap(); + + if bsize >= BlockSize::BLOCK_8X8 { + let w: &mut W = + if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + cw.write_partition(w, tile_bo, best_partition, bsize); + } + for mode in rdo_output.part_modes.clone() { + assert!(subsize == mode.bsize); + + if !mode.pred_mode_luma.is_intra() { + save_block_motion( + ts, + mode.bsize, + mode.bo, + mode.ref_frames[0].to_index(), + mode.mvs[0], + ); + } + + // FIXME: redundant block re-encode + encode_block_with_modes( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + mode.bsize, + mode.bo, + &mode, + rdo_type, + Some(enc_stats), + ); + } + } + } // if can_split { + + assert!(best_partition != PartitionType::PARTITION_INVALID); + + if is_square + && bsize >= BlockSize::BLOCK_8X8 + && (bsize == BlockSize::BLOCK_8X8 + || best_partition != PartitionType::PARTITION_SPLIT) + { + cw.bc.update_partition_context( + tile_bo, + bsize.subsize(best_partition).unwrap(), + bsize, + ); + } + + rdo_output.rd_cost = best_rd; + rdo_output.part_type = best_partition; + + if best_partition != PartitionType::PARTITION_NONE { + rdo_output.part_modes.clear(); + } + rdo_output +} + +fn encode_partition_topdown( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w_pre_cdef: &mut W, w_post_cdef: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, + block_output: &Option, inter_cfg: &InterConfig, + enc_stats: &mut EncoderStats, +) { + if tile_bo.0.x >= ts.mi_width || tile_bo.0.y >= ts.mi_height { + return; + } + let is_square = bsize.is_sqr(); + let rdo_type = RDOType::PixelDistRealRate; + let hbs = bsize.width_mi() / 2; + let has_cols = tile_bo.0.x + hbs < ts.mi_width; + let has_rows = tile_bo.0.y + hbs < ts.mi_height; + + // TODO: Update for 128x128 superblocks + debug_assert!(fi.partition_range.max <= BlockSize::BLOCK_64X64); + + let must_split = + is_square && (bsize > fi.partition_range.max || !has_cols || !has_rows); + + let can_split = // FIXME: sub-8x8 inter blocks not supported for non-4:2:0 sampling + if fi.frame_type.has_inter() && + fi.sequence.chroma_sampling != ChromaSampling::Cs420 && + bsize <= BlockSize::BLOCK_8X8 { + false + } else { + (bsize > fi.partition_range.min && is_square) || must_split + }; + + let mut rdo_output = + block_output.clone().unwrap_or_else(|| PartitionGroupParameters { + part_type: PartitionType::PARTITION_INVALID, + rd_cost: f64::MAX, + part_modes: ArrayVec::new(), + }); + + let partition = if must_split { + PartitionType::PARTITION_SPLIT + } else if can_split { + debug_assert!(bsize.is_sqr()); + + // Blocks of sizes within the supported range are subjected to a partitioning decision + rdo_output = rdo_partition_decision( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + bsize, + tile_bo, + &rdo_output, + &[PartitionType::PARTITION_SPLIT, PartitionType::PARTITION_NONE], + rdo_type, + inter_cfg, + ); + rdo_output.part_type + } else { + // Blocks of sizes below the supported range are encoded directly + PartitionType::PARTITION_NONE + }; + + debug_assert!(partition != PartitionType::PARTITION_INVALID); + + let subsize = bsize.subsize(partition).unwrap(); + + if bsize >= BlockSize::BLOCK_8X8 && is_square { + let w: &mut W = if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + cw.write_partition(w, tile_bo, partition, bsize); + } + + match partition { + PartitionType::PARTITION_NONE => { + let rdo_decision; + let part_decision = + if let Some(part_mode) = rdo_output.part_modes.first() { + // The optimal prediction mode is known from a previous iteration + part_mode + } else { + // Make a prediction mode decision for blocks encoded with no rdo_partition_decision call (e.g. edges) + rdo_decision = + rdo_mode_decision(fi, ts, cw, bsize, tile_bo, inter_cfg); + &rdo_decision + }; + + let mut mode_luma = part_decision.pred_mode_luma; + let mut mode_chroma = part_decision.pred_mode_chroma; + + let cfl = part_decision.pred_cfl_params; + let skip = part_decision.skip; + let ref_frames = part_decision.ref_frames; + let mvs = part_decision.mvs; + let mut cdef_coded = cw.bc.cdef_coded; + + // Set correct segmentation ID before encoding and before + // rdo_tx_size_type(). + cw.bc.blocks.set_segmentation_idx(tile_bo, bsize, part_decision.sidx); + + // NOTE: Cannot avoid calling rdo_tx_size_type() here again, + // because, with top-down partition RDO, the neighboring contexts + // of current partition can change, i.e. neighboring partitions can split down more. + let (tx_size, tx_type) = rdo_tx_size_type( + fi, ts, cw, bsize, tile_bo, mode_luma, ref_frames, mvs, skip, + ); + + let mut mv_stack = ArrayVec::::new(); + let is_compound = ref_frames[1] != NONE_FRAME; + let mode_context = cw.find_mvrefs( + tile_bo, + ref_frames, + &mut mv_stack, + bsize, + fi, + is_compound, + ); + + // TODO: proper remap when is_compound is true + if !mode_luma.is_intra() { + if is_compound && mode_luma != PredictionMode::GLOBAL_GLOBALMV { + let match0 = mv_stack[0].this_mv.row == mvs[0].row + && mv_stack[0].this_mv.col == mvs[0].col; + let match1 = mv_stack[0].comp_mv.row == mvs[1].row + && mv_stack[0].comp_mv.col == mvs[1].col; + + let match2 = mv_stack[1].this_mv.row == mvs[0].row + && mv_stack[1].this_mv.col == mvs[0].col; + let match3 = mv_stack[1].comp_mv.row == mvs[1].row + && mv_stack[1].comp_mv.col == mvs[1].col; + + let match4 = mv_stack.len() > 2 && mv_stack[2].this_mv == mvs[0]; + let match5 = mv_stack.len() > 2 && mv_stack[2].comp_mv == mvs[1]; + + let match6 = mv_stack.len() > 3 && mv_stack[3].this_mv == mvs[0]; + let match7 = mv_stack.len() > 3 && mv_stack[3].comp_mv == mvs[1]; + + mode_luma = if match0 && match1 { + PredictionMode::NEAREST_NEARESTMV + } else if match2 && match3 { + PredictionMode::NEAR_NEAR0MV + } else if match4 && match5 { + PredictionMode::NEAR_NEAR1MV + } else if match6 && match7 { + PredictionMode::NEAR_NEAR2MV + } else if match0 { + PredictionMode::NEAREST_NEWMV + } else if match1 { + PredictionMode::NEW_NEARESTMV + } else { + PredictionMode::NEW_NEWMV + }; + + if mode_luma != PredictionMode::NEAREST_NEARESTMV + && mvs[0].row == 0 + && mvs[0].col == 0 + && mvs[1].row == 0 + && mvs[1].col == 0 + { + mode_luma = PredictionMode::GLOBAL_GLOBALMV; + } + mode_chroma = mode_luma; + } else if !is_compound && mode_luma != PredictionMode::GLOBALMV { + mode_luma = PredictionMode::NEWMV; + for (c, m) in mv_stack.iter().take(4).zip( + [ + PredictionMode::NEARESTMV, + PredictionMode::NEAR0MV, + PredictionMode::NEAR1MV, + PredictionMode::NEAR2MV, + ] + .iter(), + ) { + if c.this_mv.row == mvs[0].row && c.this_mv.col == mvs[0].col { + mode_luma = *m; + } + } + if mode_luma == PredictionMode::NEWMV + && mvs[0].row == 0 + && mvs[0].col == 0 + { + mode_luma = if mv_stack.is_empty() { + PredictionMode::NEARESTMV + } else if mv_stack.len() == 1 { + PredictionMode::NEAR0MV + } else { + PredictionMode::GLOBALMV + }; + } + mode_chroma = mode_luma; + } + + save_block_motion( + ts, + part_decision.bsize, + part_decision.bo, + part_decision.ref_frames[0].to_index(), + part_decision.mvs[0], + ); + } + + // FIXME: every final block that has gone through the RDO decision process is encoded twice + cdef_coded = encode_block_pre_cdef( + &fi.sequence, + ts, + cw, + if cdef_coded { w_post_cdef } else { w_pre_cdef }, + bsize, + tile_bo, + skip, + ); + encode_block_post_cdef( + fi, + ts, + cw, + if cdef_coded { w_post_cdef } else { w_pre_cdef }, + mode_luma, + mode_chroma, + part_decision.angle_delta, + ref_frames, + mvs, + bsize, + tile_bo, + skip, + cfl, + tx_size, + tx_type, + mode_context, + &mv_stack, + RDOType::PixelDistRealRate, + true, + Some(enc_stats), + ); + } + PARTITION_SPLIT | PARTITION_HORZ | PARTITION_VERT => { + if !rdo_output.part_modes.is_empty() { + debug_assert!(can_split && !must_split); + + // The optimal prediction modes for each split block is known from an rdo_partition_decision() call + for mode in rdo_output.part_modes { + // Each block is subjected to a new splitting decision + encode_partition_topdown( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + subsize, + mode.bo, + &Some(PartitionGroupParameters { + rd_cost: mode.rd_cost, + part_type: PartitionType::PARTITION_NONE, + part_modes: [mode][..].try_into().unwrap(), + }), + inter_cfg, + enc_stats, + ); + } + } else { + debug_assert!(must_split); + let hbsw = subsize.width_mi(); // Half the block size width in blocks + let hbsh = subsize.height_mi(); // Half the block size height in blocks + let four_partitions = [ + tile_bo, + TileBlockOffset(BlockOffset { + x: tile_bo.0.x + hbsw, + y: tile_bo.0.y, + }), + TileBlockOffset(BlockOffset { + x: tile_bo.0.x, + y: tile_bo.0.y + hbsh, + }), + TileBlockOffset(BlockOffset { + x: tile_bo.0.x + hbsw, + y: tile_bo.0.y + hbsh, + }), + ]; + let partitions = get_sub_partitions(&four_partitions, partition); + + partitions.iter().for_each(|&offset| { + encode_partition_topdown( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + subsize, + offset, + &None, + inter_cfg, + enc_stats, + ); + }); + } + } + _ => unreachable!(), + } + + if is_square + && bsize >= BlockSize::BLOCK_8X8 + && (bsize == BlockSize::BLOCK_8X8 + || partition != PartitionType::PARTITION_SPLIT) + { + cw.bc.update_partition_context(tile_bo, subsize, bsize); + } +} + +fn get_initial_cdfcontext(fi: &FrameInvariants) -> CDFContext { + let cdf = if fi.primary_ref_frame == PRIMARY_REF_NONE { + None + } else { + let ref_frame_idx = fi.ref_frames[fi.primary_ref_frame as usize] as usize; + let ref_frame = fi.rec_buffer.frames[ref_frame_idx].as_ref(); + ref_frame.map(|rec| rec.cdfs) + }; + + // return the retrieved instance if any, a new one otherwise + cdf.unwrap_or_else(|| CDFContext::new(fi.base_q_idx)) +} + +#[profiling::function] +fn encode_tile_group( + fi: &FrameInvariants, fs: &mut FrameState, inter_cfg: &InterConfig, +) -> Vec { + let planes = + if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + let mut blocks = FrameBlocks::new(fi.w_in_b, fi.h_in_b); + let ti = &fi.sequence.tiling; + + let initial_cdf = get_initial_cdfcontext(fi); + // dynamic allocation: once per frame + let mut cdfs = vec![initial_cdf; ti.tile_count()]; + + let (raw_tiles, stats): (Vec<_>, Vec<_>) = ti + .tile_iter_mut(fs, &mut blocks) + .zip(cdfs.iter_mut()) + .collect::>() + .into_par_iter() + .map(|(mut ctx, cdf)| { + encode_tile(fi, &mut ctx.ts, cdf, &mut ctx.tb, inter_cfg) + }) + .unzip(); + + for tile_stats in stats { + fs.enc_stats += &tile_stats; + } + + /* Frame deblocking operates over a single large tile wrapping the + * frame rather than the frame itself so that deblocking is + * available inside RDO when needed */ + /* TODO: Don't apply if lossless */ + let levels = fs.apply_tile_state_mut(|ts| { + let rec = &mut ts.rec; + deblock_filter_optimize( + fi, + &rec.as_const(), + &ts.input.as_tile(), + &blocks.as_tile_blocks(), + fi.width, + fi.height, + ) + }); + fs.deblock.levels = levels; + + if fs.deblock.levels[0] != 0 || fs.deblock.levels[1] != 0 { + fs.apply_tile_state_mut(|ts| { + let rec = &mut ts.rec; + deblock_filter_frame( + ts.deblock, + rec, + &blocks.as_tile_blocks(), + fi.width, + fi.height, + fi.sequence.bit_depth, + planes, + ); + }); + } + + if fi.sequence.enable_restoration { + // Until the loop filters are better pipelined, we'll need to keep + // around a copy of both the deblocked and cdeffed frame. + let deblocked_frame = (*fs.rec).clone(); + + /* TODO: Don't apply if lossless */ + if fi.sequence.enable_cdef { + fs.apply_tile_state_mut(|ts| { + let rec = &mut ts.rec; + cdef_filter_tile(fi, &deblocked_frame, &blocks.as_tile_blocks(), rec); + }); + } + /* TODO: Don't apply if lossless */ + fs.restoration.lrf_filter_frame( + Arc::get_mut(&mut fs.rec).unwrap(), + &deblocked_frame, + fi, + ); + } else { + /* TODO: Don't apply if lossless */ + if fi.sequence.enable_cdef { + let deblocked_frame = (*fs.rec).clone(); + fs.apply_tile_state_mut(|ts| { + let rec = &mut ts.rec; + cdef_filter_tile(fi, &deblocked_frame, &blocks.as_tile_blocks(), rec); + }); + } + } + + let (idx_max, max_len) = raw_tiles + .iter() + .map(Vec::len) + .enumerate() + .max_by_key(|&(_, len)| len) + .unwrap(); + + if !fi.disable_frame_end_update_cdf { + // use the biggest tile (in bytes) for CDF update + fs.context_update_tile_id = idx_max; + fs.cdfs = cdfs[idx_max]; + fs.cdfs.reset_counts(); + } + + let max_tile_size_bytes = ILog::ilog(max_len).div_ceil(8) as u32; + debug_assert!(max_tile_size_bytes > 0 && max_tile_size_bytes <= 4); + fs.max_tile_size_bytes = max_tile_size_bytes; + + build_raw_tile_group(ti, &raw_tiles, max_tile_size_bytes) +} + +fn build_raw_tile_group( + ti: &TilingInfo, raw_tiles: &[Vec], max_tile_size_bytes: u32, +) -> Vec { + // + let mut raw = Vec::new(); + let mut bw = BitWriter::endian(&mut raw, BigEndian); + if ti.cols * ti.rows > 1 { + // tile_start_and_end_present_flag + bw.write_bit(false).unwrap(); + } + bw.byte_align().unwrap(); + for (i, raw_tile) in raw_tiles.iter().enumerate() { + let last = raw_tiles.len() - 1; + if i != last { + let tile_size_minus_1 = raw_tile.len() - 1; + bw.write_le(max_tile_size_bytes, tile_size_minus_1 as u64).unwrap(); + } + bw.write_bytes(raw_tile).unwrap(); + } + raw +} + +pub struct SBSQueueEntry { + pub sbo: TileSuperBlockOffset, + pub lru_index: [i32; MAX_PLANES], + pub cdef_coded: bool, + pub w_pre_cdef: WriterBase, + pub w_post_cdef: WriterBase, +} + +#[profiling::function] +fn check_lf_queue( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w: &mut WriterBase, + sbs_q: &mut VecDeque, last_lru_ready: &mut [i32; 3], + last_lru_rdoed: &mut [i32; 3], last_lru_coded: &mut [i32; 3], + deblock_p: bool, +) { + let mut check_queue = true; + let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { + 1 + } else { + MAX_PLANES + }; + + // Walk queue from the head, see if anything is ready for RDO and flush + while check_queue { + if let Some(qe) = sbs_q.front_mut() { + for pli in 0..planes { + if qe.lru_index[pli] > last_lru_ready[pli] { + check_queue = false; + break; + } + } + if check_queue { + // yes, this entry is ready + if qe.cdef_coded || fi.sequence.enable_restoration { + // only RDO once for a given LRU. + + // One quirk worth noting: LRUs in different planes + // may be different sizes; eg, one chroma LRU may + // cover four luma LRUs. However, we won't get here + // until all are ready for RDO because the smaller + // ones all fit inside the biggest, and the biggest + // doesn't trigger until everything is done. + + // RDO happens on all LRUs within the confines of the + // biggest, all together. If any of this SB's planes' + // LRUs are RDOed, in actuality they all are. + + // SBs tagged with a lru index of -1 are ignored in + // LRU coding/rdoing decisions (but still need to rdo + // for cdef). + let mut already_rdoed = false; + for pli in 0..planes { + if qe.lru_index[pli] != -1 + && qe.lru_index[pli] <= last_lru_rdoed[pli] + { + already_rdoed = true; + break; + } + } + if !already_rdoed { + rdo_loop_decision(qe.sbo, fi, ts, cw, w, deblock_p); + for pli in 0..planes { + if qe.lru_index[pli] != -1 + && last_lru_rdoed[pli] < qe.lru_index[pli] + { + last_lru_rdoed[pli] = qe.lru_index[pli]; + } + } + } + } + // write LRF information + if !fi.allow_intrabc && fi.sequence.enable_restoration { + // TODO: also disallow if lossless + for pli in 0..planes { + if qe.lru_index[pli] != -1 + && last_lru_coded[pli] < qe.lru_index[pli] + { + last_lru_coded[pli] = qe.lru_index[pli]; + cw.write_lrf(w, &mut ts.restoration, qe.sbo, pli); + } + } + } + // Now that loop restoration is coded, we can replay the initial block bits + qe.w_pre_cdef.replay(w); + // Now code CDEF into the middle of the block + if qe.cdef_coded { + let cdef_index = cw.bc.blocks.get_cdef(qe.sbo); + cw.write_cdef(w, cdef_index, fi.cdef_bits); + // Code queued symbols that come after the CDEF index + qe.w_post_cdef.replay(w); + } + sbs_q.pop_front(); + } + } else { + check_queue = false; + } + } +} + +#[profiling::function] +fn encode_tile<'a, T: Pixel>( + fi: &FrameInvariants, ts: &'a mut TileStateMut<'_, T>, + fc: &'a mut CDFContext, blocks: &'a mut TileBlocksMut<'a>, + inter_cfg: &InterConfig, +) -> (Vec, EncoderStats) { + let mut enc_stats = EncoderStats::default(); + let mut w = WriterEncoder::new(); + let planes = + if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + + let bc = BlockContext::new(blocks); + let mut cw = ContextWriter::new(fc, bc); + let mut sbs_q: VecDeque = VecDeque::new(); + let mut last_lru_ready = [-1; 3]; + let mut last_lru_rdoed = [-1; 3]; + let mut last_lru_coded = [-1; 3]; + + // main loop + for sby in 0..ts.sb_height { + cw.bc.reset_left_contexts(planes); + + for sbx in 0..ts.sb_width { + cw.fc_log.clear(); + + let tile_sbo = TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby }); + let mut sbs_qe = SBSQueueEntry { + sbo: tile_sbo, + lru_index: [-1; MAX_PLANES], + cdef_coded: false, + w_pre_cdef: WriterRecorder::new(), + w_post_cdef: WriterRecorder::new(), + }; + + let tile_bo = tile_sbo.block_offset(0, 0); + cw.bc.cdef_coded = false; + cw.bc.code_deltas = fi.delta_q_present; + + let is_straddle_sbx = + tile_bo.0.x + BlockSize::BLOCK_64X64.width_mi() > ts.mi_width; + let is_straddle_sby = + tile_bo.0.y + BlockSize::BLOCK_64X64.height_mi() > ts.mi_height; + + // Encode SuperBlock + if fi.config.speed_settings.partition.encode_bottomup + || is_straddle_sbx + || is_straddle_sby + { + encode_partition_bottomup( + fi, + ts, + &mut cw, + &mut sbs_qe.w_pre_cdef, + &mut sbs_qe.w_post_cdef, + BlockSize::BLOCK_64X64, + tile_bo, + f64::MAX, + inter_cfg, + &mut enc_stats, + ); + } else { + encode_partition_topdown( + fi, + ts, + &mut cw, + &mut sbs_qe.w_pre_cdef, + &mut sbs_qe.w_post_cdef, + BlockSize::BLOCK_64X64, + tile_bo, + &None, + inter_cfg, + &mut enc_stats, + ); + } + + { + let mut check_queue = false; + // queue our superblock for when the LRU is complete + sbs_qe.cdef_coded = cw.bc.cdef_coded; + for pli in 0..planes { + if let Some((lru_x, lru_y)) = + ts.restoration.planes[pli].restoration_unit_index(tile_sbo, false) + { + let lru_index = ts.restoration.planes[pli] + .restoration_unit_countable(lru_x, lru_y) + as i32; + sbs_qe.lru_index[pli] = lru_index; + if ts.restoration.planes[pli] + .restoration_unit_last_sb_for_rdo(fi, ts.sbo, tile_sbo) + { + last_lru_ready[pli] = lru_index; + check_queue = true; + } + } else { + // we're likely in an area stretched into a new tile + // tag this SB to be ignored in LRU decisions + sbs_qe.lru_index[pli] = -1; + check_queue = true; + } + } + sbs_q.push_back(sbs_qe); + + if check_queue && !fi.sequence.enable_delayed_loopfilter_rdo { + check_lf_queue( + fi, + ts, + &mut cw, + &mut w, + &mut sbs_q, + &mut last_lru_ready, + &mut last_lru_rdoed, + &mut last_lru_coded, + true, + ); + } + } + } + } + + if fi.sequence.enable_delayed_loopfilter_rdo { + // Solve deblocking for just this tile + /* TODO: Don't apply if lossless */ + let deblock_levels = deblock_filter_optimize( + fi, + &ts.rec.as_const(), + &ts.input_tile, + &cw.bc.blocks.as_const(), + fi.width, + fi.height, + ); + + if deblock_levels[0] != 0 || deblock_levels[1] != 0 { + // copy reconstruction to a temp frame to restore it later + let rec_copy = if planes == 3 { + vec![ + ts.rec.planes[0].scratch_copy(), + ts.rec.planes[1].scratch_copy(), + ts.rec.planes[2].scratch_copy(), + ] + } else { + vec![ts.rec.planes[0].scratch_copy()] + }; + + // copy ts.deblock because we need to set some of our own values here + let mut deblock_copy = *ts.deblock; + deblock_copy.levels = deblock_levels; + + // temporarily deblock the reference + deblock_filter_frame( + &deblock_copy, + &mut ts.rec, + &cw.bc.blocks.as_const(), + fi.width, + fi.height, + fi.sequence.bit_depth, + planes, + ); + + // rdo lf and write + check_lf_queue( + fi, + ts, + &mut cw, + &mut w, + &mut sbs_q, + &mut last_lru_ready, + &mut last_lru_rdoed, + &mut last_lru_coded, + false, + ); + + // copy original reference back in + for pli in 0..planes { + let dst = &mut ts.rec.planes[pli]; + let src = &rec_copy[pli]; + for (dst_row, src_row) in dst.rows_iter_mut().zip(src.rows_iter()) { + for (out, input) in dst_row.iter_mut().zip(src_row) { + *out = *input; + } + } + } + } else { + // rdo lf and write + check_lf_queue( + fi, + ts, + &mut cw, + &mut w, + &mut sbs_q, + &mut last_lru_ready, + &mut last_lru_rdoed, + &mut last_lru_coded, + false, + ); + } + } + + assert!( + sbs_q.is_empty(), + "Superblock queue not empty in tile at offset {}:{}", + ts.sbo.0.x, + ts.sbo.0.y + ); + (w.done(), enc_stats) +} + +#[allow(unused)] +fn write_tile_group_header(tile_start_and_end_present_flag: bool) -> Vec { + let mut buf = Vec::new(); + { + let mut bw = BitWriter::endian(&mut buf, BigEndian); + bw.write_bit(tile_start_and_end_present_flag).unwrap(); + bw.byte_align().unwrap(); + } + buf +} + +/// Write a packet containing only the placeholder that tells the decoder +/// to present the already decoded frame present at `frame_to_show_map_idx` +/// +/// See `av1-spec` Section 6.8.2 and 7.18. +/// +/// # Panics +/// +/// - If the frame packets cannot be written +#[profiling::function] +pub fn encode_show_existing_frame( + fi: &FrameInvariants, fs: &mut FrameState, inter_cfg: &InterConfig, +) -> Vec { + debug_assert!(fi.is_show_existing_frame()); + let obu_extension = 0; + + let mut packet = Vec::new(); + + if fi.frame_type == FrameType::KEY { + write_key_frame_obus(&mut packet, fi, obu_extension).unwrap(); + } + + for t35 in fi.t35_metadata.iter() { + let mut t35_buf = Vec::new(); + let mut t35_bw = BitWriter::endian(&mut t35_buf, BigEndian); + t35_bw.write_t35_metadata_obu(t35).unwrap(); + packet.write_all(&t35_buf).unwrap(); + t35_buf.clear(); + } + + let mut buf1 = Vec::new(); + let mut buf2 = Vec::new(); + { + let mut bw2 = BitWriter::endian(&mut buf2, BigEndian); + bw2.write_frame_header_obu(fi, fs, inter_cfg).unwrap(); + } + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_obu_header(ObuType::OBU_FRAME_HEADER, obu_extension).unwrap(); + } + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_uleb128(buf2.len() as u64).unwrap(); + } + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + packet.write_all(&buf2).unwrap(); + buf2.clear(); + + let map_idx = fi.frame_to_show_map_idx as usize; + if let Some(ref rec) = fi.rec_buffer.frames[map_idx] { + let fs_rec = Arc::get_mut(&mut fs.rec).unwrap(); + let planes = + if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + for p in 0..planes { + fs_rec.planes[p].data.copy_from_slice(&rec.frame.planes[p].data); + } + } + packet +} + +fn get_initial_segmentation( + fi: &FrameInvariants, +) -> SegmentationState { + let segmentation = if fi.primary_ref_frame == PRIMARY_REF_NONE { + None + } else { + let ref_frame_idx = fi.ref_frames[fi.primary_ref_frame as usize] as usize; + let ref_frame = fi.rec_buffer.frames[ref_frame_idx].as_ref(); + ref_frame.map(|rec| rec.segmentation) + }; + + // return the retrieved instance if any, a new one otherwise + segmentation.unwrap_or_default() +} + +/// # Panics +/// +/// - If the frame packets cannot be written +#[profiling::function] +pub fn encode_frame( + fi: &FrameInvariants, fs: &mut FrameState, inter_cfg: &InterConfig, +) -> Vec { + debug_assert!(!fi.is_show_existing_frame()); + let obu_extension = 0; + + let mut packet = Vec::new(); + + if fi.enable_segmentation { + fs.segmentation = get_initial_segmentation(fi); + segmentation_optimize(fi, fs); + } + let tile_group = encode_tile_group(fi, fs, inter_cfg); + + if fi.frame_type == FrameType::KEY { + write_key_frame_obus(&mut packet, fi, obu_extension).unwrap(); + } + + for t35 in fi.t35_metadata.iter() { + let mut t35_buf = Vec::new(); + let mut t35_bw = BitWriter::endian(&mut t35_buf, BigEndian); + t35_bw.write_t35_metadata_obu(t35).unwrap(); + packet.write_all(&t35_buf).unwrap(); + t35_buf.clear(); + } + + let mut buf1 = Vec::new(); + let mut buf2 = Vec::new(); + { + let mut bw2 = BitWriter::endian(&mut buf2, BigEndian); + bw2.write_frame_header_obu(fi, fs, inter_cfg).unwrap(); + } + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_obu_header(ObuType::OBU_FRAME, obu_extension).unwrap(); + } + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + { + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_uleb128((buf2.len() + tile_group.len()) as u64).unwrap(); + } + packet.write_all(&buf1).unwrap(); + buf1.clear(); + + packet.write_all(&buf2).unwrap(); + buf2.clear(); + + packet.write_all(&tile_group).unwrap(); + packet +} + +pub fn update_rec_buffer( + output_frameno: u64, fi: &mut FrameInvariants, fs: &FrameState, +) { + let rfs = Arc::new(ReferenceFrame { + order_hint: fi.order_hint, + width: fi.width as u32, + height: fi.height as u32, + render_width: fi.render_width, + render_height: fi.render_height, + frame: fs.rec.clone(), + input_hres: fs.input_hres.clone(), + input_qres: fs.input_qres.clone(), + cdfs: fs.cdfs, + frame_me_stats: fs.frame_me_stats.clone(), + output_frameno, + segmentation: fs.segmentation, + }); + for i in 0..REF_FRAMES { + if (fi.refresh_frame_flags & (1 << i)) != 0 { + fi.rec_buffer.frames[i] = Some(Arc::clone(&rfs)); + fi.rec_buffer.deblock[i] = fs.deblock; + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn check_partition_types_order() { + assert_eq!( + RAV1E_PARTITION_TYPES[RAV1E_PARTITION_TYPES.len() - 1], + PartitionType::PARTITION_SPLIT + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/entropymode.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/entropymode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/entropymode.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/entropymode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1083 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] + +use crate::context::*; +use crate::partition::*; +use crate::predict::*; +use crate::transform::*; +use crate::util::*; + +pub const PALETTE_BSIZE_CTXS: usize = 7; +pub const PALETTE_Y_MODE_CONTEXTS: usize = 3; +pub const PALETTE_UV_MODE_CONTEXTS: usize = 2; +const PALETTE_COLOR_INDEX_CONTEXTS: usize = 5; +const RESTORE_SWITCHABLE_TYPES: usize = 3; +pub const TX_SIZE_CONTEXTS: usize = 3; + +// from seg_common.h +const MAX_SEGMENTS: usize = 8; +const SPATIAL_PREDICTION_PROBS: usize = 3; +const SEG_TEMPORAL_PRED_CTXS: usize = 3; + +// enums.h +const TX_SIZE_LUMA_MIN: usize = TxSize::TX_4X4 as usize; +const TX_SIZE_CTX_MIN: usize = TX_SIZE_LUMA_MIN + 1; +pub const MAX_TX_CATS: usize = TxSize::TX_SIZES - TX_SIZE_CTX_MIN; +pub const BIG_TX_CATS: usize = MAX_TX_CATS - 1; // All except 8x8, which has lower max depth. +pub const MAX_TX_DEPTH: usize = 2; + +// LUTS --------------------- + +pub static default_kf_y_mode_cdf: [[[u16; INTRA_MODES]; KF_MODE_CONTEXTS]; + KF_MODE_CONTEXTS] = cdf_3d([ + [ + [ + 15588, 17027, 19338, 20218, 20682, 21110, 21825, 23244, 24189, 28165, + 29093, 30466, + ], + [ + 12016, 18066, 19516, 20303, 20719, 21444, 21888, 23032, 24434, 28658, + 30172, 31409, + ], + [ + 10052, 10771, 22296, 22788, 23055, 23239, 24133, 25620, 26160, 29336, + 29929, 31567, + ], + [ + 14091, 15406, 16442, 18808, 19136, 19546, 19998, 22096, 24746, 29585, + 30958, 32462, + ], + [ + 12122, 13265, 15603, 16501, 18609, 20033, 22391, 25583, 26437, 30261, + 31073, 32475, + ], + ], + [ + [ + 10023, 19585, 20848, 21440, 21832, 22760, 23089, 24023, 25381, 29014, + 30482, 31436, + ], + [ + 5983, 24099, 24560, 24886, 25066, 25795, 25913, 26423, 27610, 29905, + 31276, 31794, + ], + [ + 7444, 12781, 20177, 20728, 21077, 21607, 22170, 23405, 24469, 27915, + 29090, 30492, + ], + [ + 8537, 14689, 15432, 17087, 17408, 18172, 18408, 19825, 24649, 29153, + 31096, 32210, + ], + [ + 7543, 14231, 15496, 16195, 17905, 20717, 21984, 24516, 26001, 29675, + 30981, 31994, + ], + ], + [ + [ + 12613, 13591, 21383, 22004, 22312, 22577, 23401, 25055, 25729, 29538, + 30305, 32077, + ], + [ + 9687, 13470, 18506, 19230, 19604, 20147, 20695, 22062, 23219, 27743, + 29211, 30907, + ], + [ + 6183, 6505, 26024, 26252, 26366, 26434, 27082, 28354, 28555, 30467, + 30794, 32086, + ], + [ + 10718, 11734, 14954, 17224, 17565, 17924, 18561, 21523, 23878, 28975, + 30287, 32252, + ], + [ + 9194, 9858, 16501, 17263, 18424, 19171, 21563, 25961, 26561, 30072, + 30737, 32463, + ], + ], + [ + [ + 12602, 14399, 15488, 18381, 18778, 19315, 19724, 21419, 25060, 29696, + 30917, 32409, + ], + [ + 8203, 13821, 14524, 17105, 17439, 18131, 18404, 19468, 25225, 29485, + 31158, 32342, + ], + [ + 8451, 9731, 15004, 17643, 18012, 18425, 19070, 21538, 24605, 29118, + 30078, 32018, + ], + [ + 7714, 9048, 9516, 16667, 16817, 16994, 17153, 18767, 26743, 30389, + 31536, 32528, + ], + [ + 8843, 10280, 11496, 15317, 16652, 17943, 19108, 22718, 25769, 29953, + 30983, 32485, + ], + ], + [ + [ + 12578, 13671, 15979, 16834, 19075, 20913, 22989, 25449, 26219, 30214, + 31150, 32477, + ], + [ + 9563, 13626, 15080, 15892, 17756, 20863, 22207, 24236, 25380, 29653, + 31143, 32277, + ], + [ + 8356, 8901, 17616, 18256, 19350, 20106, 22598, 25947, 26466, 29900, + 30523, 32261, + ], + [ + 10835, 11815, 13124, 16042, 17018, 18039, 18947, 22753, 24615, 29489, + 30883, 32482, + ], + [ + 7618, 8288, 9859, 10509, 15386, 18657, 22903, 28776, 29180, 31355, + 31802, 32593, + ], + ], +]); + +pub static default_angle_delta_cdf: [[u16; 2 * MAX_ANGLE_DELTA + 1]; + DIRECTIONAL_MODES] = cdf_2d([ + [2180, 5032, 7567, 22776, 26989, 30217], + [2301, 5608, 8801, 23487, 26974, 30330], + [3780, 11018, 13699, 19354, 23083, 31286], + [4581, 11226, 15147, 17138, 21834, 28397], + [1737, 10927, 14509, 19588, 22745, 28823], + [2664, 10176, 12485, 17650, 21600, 30495], + [2240, 11096, 15453, 20341, 22561, 28917], + [3605, 10428, 12459, 17676, 21244, 30655], +]); + +pub static default_if_y_mode_cdf: [[u16; INTRA_MODES]; BLOCK_SIZE_GROUPS] = + cdf_2d([ + [ + 22801, 23489, 24293, 24756, 25601, 26123, 26606, 27418, 27945, 29228, + 29685, 30349, + ], + [ + 18673, 19845, 22631, 23318, 23950, 24649, 25527, 27364, 28152, 29701, + 29984, 30852, + ], + [ + 19770, 20979, 23396, 23939, 24241, 24654, 25136, 27073, 27830, 29360, + 29730, 30659, + ], + [ + 20155, 21301, 22838, 23178, 23261, 23533, 23703, 24804, 25352, 26575, + 27016, 28049, + ], + ]); + +pub static default_uv_mode_cdf: [[u16; INTRA_MODES]; INTRA_MODES] = cdf_2d([ + [ + 22631, 24152, 25378, 25661, 25986, 26520, 27055, 27923, 28244, 30059, + 30941, 31961, + ], + [ + 9513, 26881, 26973, 27046, 27118, 27664, 27739, 27824, 28359, 29505, + 29800, 31796, + ], + [ + 9845, 9915, 28663, 28704, 28757, 28780, 29198, 29822, 29854, 30764, 31777, + 32029, + ], + [ + 13639, 13897, 14171, 25331, 25606, 25727, 25953, 27148, 28577, 30612, + 31355, 32493, + ], + [ + 9764, 9835, 9930, 9954, 25386, 27053, 27958, 28148, 28243, 31101, 31744, + 32363, + ], + [ + 11825, 13589, 13677, 13720, 15048, 29213, 29301, 29458, 29711, 31161, + 31441, 32550, + ], + [ + 14175, 14399, 16608, 16821, 17718, 17775, 28551, 30200, 30245, 31837, + 32342, 32667, + ], + [ + 12885, 13038, 14978, 15590, 15673, 15748, 16176, 29128, 29267, 30643, + 31961, 32461, + ], + [ + 12026, 13661, 13874, 15305, 15490, 15726, 15995, 16273, 28443, 30388, + 30767, 32416, + ], + [ + 19052, 19840, 20579, 20916, 21150, 21467, 21885, 22719, 23174, 28861, + 30379, 32175, + ], + [ + 18627, 19649, 20974, 21219, 21492, 21816, 22199, 23119, 23527, 27053, + 31397, 32148, + ], + [ + 17026, 19004, 19997, 20339, 20586, 21103, 21349, 21907, 22482, 25896, + 26541, 31819, + ], + [ + 12124, 13759, 14959, 14992, 15007, 15051, 15078, 15166, 15255, 15753, + 16039, 16606, + ], +]); + +pub static default_uv_mode_cfl_cdf: [[u16; UV_INTRA_MODES]; INTRA_MODES] = + cdf_2d([ + [ + 10407, 11208, 12900, 13181, 13823, 14175, 14899, 15656, 15986, 20086, + 20995, 22455, 24212, + ], + [ + 4532, 19780, 20057, 20215, 20428, 21071, 21199, 21451, 22099, 24228, + 24693, 27032, 29472, + ], + [ + 5273, 5379, 20177, 20270, 20385, 20439, 20949, 21695, 21774, 23138, + 24256, 24703, 26679, + ], + [ + 6740, 7167, 7662, 14152, 14536, 14785, 15034, 16741, 18371, 21520, + 22206, 23389, 24182, + ], + [ + 4987, 5368, 5928, 6068, 19114, 20315, 21857, 22253, 22411, 24911, 25380, + 26027, 26376, + ], + [ + 5370, 6889, 7247, 7393, 9498, 21114, 21402, 21753, 21981, 24780, 25386, + 26517, 27176, + ], + [ + 4816, 4961, 7204, 7326, 8765, 8930, 20169, 20682, 20803, 23188, 23763, + 24455, 24940, + ], + [ + 6608, 6740, 8529, 9049, 9257, 9356, 9735, 18827, 19059, 22336, 23204, + 23964, 24793, + ], + [ + 5998, 7419, 7781, 8933, 9255, 9549, 9753, 10417, 18898, 22494, 23139, + 24764, 25989, + ], + [ + 10660, 11298, 12550, 12957, 13322, 13624, 14040, 15004, 15534, 20714, + 21789, 23443, 24861, + ], + [ + 10522, 11530, 12552, 12963, 13378, 13779, 14245, 15235, 15902, 20102, + 22696, 23774, 25838, + ], + [ + 10099, 10691, 12639, 13049, 13386, 13665, 14125, 15163, 15636, 19676, + 20474, 23519, 25208, + ], + [ + 3144, 5087, 7382, 7504, 7593, 7690, 7801, 8064, 8232, 9248, 9875, 10521, + 29048, + ], + ]); + +pub const default_partition_w8_cdf: [[u16; 4]; PARTITION_TYPES] = cdf_2d([ + [19132, 25510, 30392], + [13928, 19855, 28540], + [12522, 23679, 28629], + [9896, 18783, 25853], +]); + +pub const default_partition_cdf: [[u16; EXT_PARTITION_TYPES]; + 3 * PARTITION_TYPES] = cdf_2d([ + [15597, 20929, 24571, 26706, 27664, 28821, 29601, 30571, 31902], + [7925, 11043, 16785, 22470, 23971, 25043, 26651, 28701, 29834], + [5414, 13269, 15111, 20488, 22360, 24500, 25537, 26336, 32117], + [2662, 6362, 8614, 20860, 23053, 24778, 26436, 27829, 31171], + [18462, 20920, 23124, 27647, 28227, 29049, 29519, 30178, 31544], + [7689, 9060, 12056, 24992, 25660, 26182, 26951, 28041, 29052], + [6015, 9009, 10062, 24544, 25409, 26545, 27071, 27526, 32047], + [1394, 2208, 2796, 28614, 29061, 29466, 29840, 30185, 31899], + [20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724], + [6732, 7490, 9497, 27944, 28250, 28515, 28969, 29630, 30104], + [5945, 7663, 8348, 28683, 29117, 29749, 30064, 30298, 32238], + [870, 1212, 1487, 31198, 31394, 31574, 31743, 31881, 32332], +]); + +pub const default_partition_w128_cdf: [[u16; 8]; PARTITION_TYPES] = cdf_2d([ + [27899, 28219, 28529, 32484, 32539, 32619, 32639], + [6607, 6990, 8268, 32060, 32219, 32338, 32371], + [5429, 6676, 7122, 32027, 32227, 32531, 32582], + [711, 966, 1172, 32448, 32538, 32617, 32664], +]); + +pub static default_intra_tx_1_cdf: [[[u16; 7]; INTRA_MODES]; + TX_SIZE_SQR_CONTEXTS] = cdf_3d([ + [ + [1535, 8035, 9461, 12751, 23467, 27825], + [564, 3335, 9709, 10870, 18143, 28094], + [672, 3247, 3676, 11982, 19415, 23127], + [5279, 13885, 15487, 18044, 23527, 30252], + [4423, 6074, 7985, 10416, 25693, 29298], + [1486, 4241, 9460, 10662, 16456, 27694], + [439, 2838, 3522, 6737, 18058, 23754], + [1190, 4233, 4855, 11670, 20281, 24377], + [1045, 4312, 8647, 10159, 18644, 29335], + [202, 3734, 4747, 7298, 17127, 24016], + [447, 4312, 6819, 8884, 16010, 23858], + [277, 4369, 5255, 8905, 16465, 22271], + [3409, 5436, 10599, 15599, 19687, 24040], + ], + [ + [1870, 13742, 14530, 16498, 23770, 27698], + [326, 8796, 14632, 15079, 19272, 27486], + [484, 7576, 7712, 14443, 19159, 22591], + [1126, 15340, 15895, 17023, 20896, 30279], + [655, 4854, 5249, 5913, 22099, 27138], + [1299, 6458, 8885, 9290, 14851, 25497], + [311, 5295, 5552, 6885, 16107, 22672], + [883, 8059, 8270, 11258, 17289, 21549], + [741, 7580, 9318, 10345, 16688, 29046], + [110, 7406, 7915, 9195, 16041, 23329], + [363, 7974, 9357, 10673, 15629, 24474], + [153, 7647, 8112, 9936, 15307, 19996], + [3511, 6332, 11165, 15335, 19323, 23594], + ], + [ + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + ], + [ + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + [4681, 9362, 14043, 18725, 23406, 28087], + ], +]); + +pub static default_intra_tx_2_cdf: [[[u16; 5]; INTRA_MODES]; + TX_SIZE_SQR_CONTEXTS] = cdf_3d([ + [ + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + ], + [ + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + ], + [ + [1127, 12814, 22772, 27483], + [145, 6761, 11980, 26667], + [362, 5887, 11678, 16725], + [385, 15213, 18587, 30693], + [25, 2914, 23134, 27903], + [60, 4470, 11749, 23991], + [37, 3332, 14511, 21448], + [157, 6320, 13036, 17439], + [119, 6719, 12906, 29396], + [47, 5537, 12576, 21499], + [269, 6076, 11258, 23115], + [83, 5615, 12001, 17228], + [1968, 5556, 12023, 18547], + ], + [ + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + [6554, 13107, 19661, 26214], + ], +]); + +pub static default_inter_tx_1_cdf: [[u16; TX_TYPES]; TX_SIZE_SQR_CONTEXTS] = + cdf_2d([ + [ + 4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266, 21504, 22848, 23934, + 25474, 27727, 28915, 30631, + ], + [ + 1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357, 17674, 20408, 22517, + 25010, 27116, 28856, 30749, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + ]); + +pub static default_inter_tx_2_cdf: [[u16; 12]; TX_SIZE_SQR_CONTEXTS] = + cdf_2d([ + [2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, 24576, 27307, 30037], + [2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, 24576, 27307, 30037], + [770, 2421, 5225, 12907, 15819, 18927, 21561, 24089, 26595, 28526, 30529], + [2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, 24576, 27307, 30037], + ]); + +pub static default_inter_tx_3_cdf: [[u16; 2]; TX_SIZE_SQR_CONTEXTS] = + cdf_2d([[16384], [4167], [1998], [748]]); + +pub static default_cfl_sign_cdf: [u16; CFL_JOINT_SIGNS] = + cdf([1418, 2123, 13340, 18405, 26972, 28343, 32294]); + +pub static default_cfl_alpha_cdf: [[u16; CFL_ALPHABET_SIZE]; + CFL_ALPHA_CONTEXTS] = cdf_2d([ + [ + 7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696, 32700, 32704, + 32708, 32712, 32716, 32720, 32724, + ], + [ + 14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573, 32620, 32647, + 32668, 32672, 32676, 32680, 32684, + ], + [ + 11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649, 32673, 32677, + 32681, 32685, 32689, 32693, 32697, + ], + [ + 26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704, 32708, 32712, + 32716, 32720, 32724, 32728, 32732, + ], + [ + 17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321, 32394, 32464, + 32516, 32560, 32576, 32593, 32622, + ], + [ + 14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843, 32144, 32413, + 32520, 32594, 32622, 32656, 32660, + ], +]); + +// This does not appear to be used in the rust project currently +const SWITCHABLE_FILTERS: usize = 3; +const SWITCHABLE_FILTER_CONTEXTS: usize = (SWITCHABLE_FILTERS + 1) * 4; + +#[allow(unused)] +pub static default_switchable_interp_cdf: [[u16; SWITCHABLE_FILTERS]; + SWITCHABLE_FILTER_CONTEXTS] = cdf_2d([ + [31935, 32720], + [5568, 32719], + [422, 2938], + [28244, 32608], + [31206, 31953], + [4862, 32121], + [770, 1152], + [20889, 25637], + [31910, 32724], + [4120, 32712], + [305, 2247], + [27403, 32636], + [31022, 32009], + [2963, 32093], + [601, 943], + [14969, 21398], +]); + +pub static default_newmv_cdf: [[u16; 2]; NEWMV_MODE_CONTEXTS] = [ + cdf([24035]), + cdf([16630]), + cdf([15339]), + cdf([8386]), + cdf([12222]), + cdf([4676]), + [0; 2], +]; + +pub static default_zeromv_cdf: [[u16; 2]; GLOBALMV_MODE_CONTEXTS] = + cdf_2d([[2175], [1054]]); + +pub static default_refmv_cdf: [[u16; 2]; REFMV_MODE_CONTEXTS] = + cdf_2d([[23974], [24188], [17848], [28622], [24312], [19923]]); + +pub static default_drl_cdf: [[u16; 2]; DRL_MODE_CONTEXTS] = + cdf_2d([[13104], [24560], [18945]]); + +pub static default_compound_mode_cdf: [[u16; INTER_COMPOUND_MODES]; + INTER_MODE_CONTEXTS] = cdf_2d([ + [7760, 13823, 15808, 17641, 19156, 20666, 26891], + [10730, 19452, 21145, 22749, 24039, 25131, 28724], + [10664, 20221, 21588, 22906, 24295, 25387, 28436], + [13298, 16984, 20471, 24182, 25067, 25736, 26422], + [18904, 23325, 25242, 27432, 27898, 28258, 30758], + [10725, 17454, 20124, 22820, 24195, 25168, 26046], + [17125, 24273, 25814, 27492, 28214, 28704, 30592], + [13046, 23214, 24505, 25942, 27435, 28442, 29330], +]); + +#[allow(unused)] +pub static default_interintra_cdf: [[u16; 2]; BLOCK_SIZE_GROUPS] = + cdf_2d([[16384], [26887], [27597], [30237]]); + +#[allow(unused)] +pub static default_interintra_mode_cdf: [[u16; + InterIntraMode::INTERINTRA_MODES as usize]; + BLOCK_SIZE_GROUPS] = cdf_2d([ + [8192, 16384, 24576], + [1875, 11082, 27332], + [2473, 9996, 26388], + [4238, 11537, 25926], +]); + +#[allow(unused)] +pub static default_wedge_interintra_cdf: [[u16; 2]; + BlockSize::BLOCK_SIZES_ALL] = cdf_2d([ + [16384], + [16384], + [16384], + [20036], + [24957], + [26704], + [27530], + [29564], + [29444], + [26872], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], +]); + +#[allow(unused)] +pub static default_compound_type_cdf: [[u16; + CompoundType::COMPOUND_TYPES as usize - 1]; + BlockSize::BLOCK_SIZES_ALL] = cdf_2d([ + [16384], + [16384], + [16384], + [23431], + [13171], + [11470], + [9770], + [9100], + [8233], + [6172], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [11820], + [7701], + [16384], + [16384], +]); + +#[allow(unused)] +pub static default_wedge_idx_cdf: [[u16; 16]; BlockSize::BLOCK_SIZES_ALL] = + cdf_2d([ + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094, 20359, 22362, 24127, + 25702, 27752, 29450, 31171, + ], + [ + 806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323, 17367, 18452, + 19422, 22839, 26127, 29629, + ], + [ + 2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939, 21332, 24520, + 27470, 29456, 30529, 31656, + ], + [ + 1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163, 20961, 22884, + 24471, 26719, 28714, 30877, + ], + [ + 1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369, 16730, 18114, + 19313, 22521, 26012, 29550, + ], + [ + 2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270, 20533, 23434, + 25972, 27944, 29570, 31416, + ], + [ + 1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638, 22038, 23963, + 25311, 26988, 28766, 31012, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284, 24985, + 25684, 27259, 28883, 30911, + ], + [ + 1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935, 25057, 27251, + 29173, 30089, 30960, 31933, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + [ + 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + ], + ]); + +#[allow(unused)] +pub static default_motion_mode_cdf: [[u16; + MotionMode::MOTION_MODES as usize]; + BlockSize::BLOCK_SIZES_ALL] = cdf_2d([ + [10923, 21845], + [10923, 21845], + [10923, 21845], + [7651, 24760], + [4738, 24765], + [5391, 25528], + [19419, 26810], + [5123, 23606], + [11606, 24308], + [26260, 29116], + [20360, 28062], + [21679, 26830], + [29516, 30701], + [28898, 30397], + [30878, 31335], + [32507, 32558], + [10923, 21845], + [10923, 21845], + [28799, 31390], + [26431, 30774], + [28973, 31594], + [29742, 31203], +]); + +#[allow(unused)] +pub static default_obmc_cdf: [[u16; 2]; BlockSize::BLOCK_SIZES_ALL] = + cdf_2d([ + [16384], + [16384], + [16384], + [10437], + [9371], + [9301], + [17432], + [14423], + [15142], + [25817], + [22823], + [22083], + [30128], + [31014], + [31560], + [32638], + [16384], + [16384], + [23664], + [20901], + [24008], + [26879], + ]); + +pub static default_intra_inter_cdf: [[u16; 2]; INTRA_INTER_CONTEXTS] = + cdf_2d([[806], [16662], [20186], [26538]]); + +pub static default_comp_mode_cdf: [[u16; 2]; COMP_INTER_CONTEXTS] = + cdf_2d([[26828], [24035], [12031], [10640], [2901]]); + +pub static default_comp_ref_type_cdf: [[u16; 2]; COMP_REF_TYPE_CONTEXTS] = + cdf_2d([[1198], [2070], [9166], [7499], [22475]]); + +#[allow(unused)] +pub static default_uni_comp_ref_cdf: [[[u16; 2]; UNIDIR_COMP_REFS - 1]; + UNI_COMP_REF_CONTEXTS] = cdf_3d([ + [[5284], [3865], [3128]], + [[23152], [14173], [15270]], + [[31774], [25120], [26710]], +]); + +pub static default_single_ref_cdf: [[[u16; 2]; SINGLE_REFS - 1]; + REF_CONTEXTS] = cdf_3d([ + [[4897], [1555], [4236], [8650], [904], [1444]], + [[16973], [16751], [19647], [24773], [11014], [15087]], + [[29744], [30279], [31194], [31895], [26875], [30304]], +]); + +pub static default_comp_ref_cdf: [[[u16; 2]; FWD_REFS - 1]; REF_CONTEXTS] = + cdf_3d([ + [[4946], [9468], [1503]], + [[19891], [22441], [15160]], + [[30731], [31059], [27544]], + ]); + +pub static default_comp_bwdref_cdf: [[[u16; 2]; BWD_REFS - 1]; REF_CONTEXTS] = + cdf_3d([[[2235], [1423]], [[17182], [15175]], [[30606], [30489]]]); + +#[allow(unused)] +pub static default_palette_y_size_cdf: [[u16; + PaletteSize::PALETTE_SIZES as usize]; + PALETTE_BSIZE_CTXS] = cdf_2d([ + [7952, 13000, 18149, 21478, 25527, 29241], + [7139, 11421, 16195, 19544, 23666, 28073], + [7788, 12741, 17325, 20500, 24315, 28530], + [8271, 14064, 18246, 21564, 25071, 28533], + [12725, 19180, 21863, 24839, 27535, 30120], + [9711, 14888, 16923, 21052, 25661, 27875], + [14940, 20797, 21678, 24186, 27033, 28999], +]); + +#[allow(unused)] +pub static default_palette_uv_size_cdf: [[u16; + PaletteSize::PALETTE_SIZES as usize]; + PALETTE_BSIZE_CTXS] = cdf_2d([ + [8713, 19979, 27128, 29609, 31331, 32272], + [5839, 15573, 23581, 26947, 29848, 31700], + [4426, 11260, 17999, 21483, 25863, 29430], + [3228, 9464, 14993, 18089, 22523, 27420], + [3768, 8886, 13091, 17852, 22495, 27207], + [2464, 8451, 12861, 21632, 25525, 28555], + [1269, 5435, 10433, 18963, 21700, 25865], +]); + +pub static default_palette_y_mode_cdfs: [[[u16; 2]; PALETTE_Y_MODE_CONTEXTS]; + PALETTE_BSIZE_CTXS] = cdf_3d([ + [[31676], [3419], [1261]], + [[31912], [2859], [980]], + [[31823], [3400], [781]], + [[32030], [3561], [904]], + [[32309], [7337], [1462]], + [[32265], [4015], [1521]], + [[32450], [7946], [129]], +]); + +pub static default_palette_uv_mode_cdfs: [[u16; 2]; PALETTE_UV_MODE_CONTEXTS] = + cdf_2d([[32461], [21488]]); + +#[allow(unused)] +pub static default_palette_y_color_index_cdf: [[[u16; + PaletteColor::PALETTE_COLORS as usize]; + PALETTE_COLOR_INDEX_CONTEXTS]; + PaletteSize::PALETTE_SIZES as usize] = [ + cdf_2d([[28710], [16384], [10553], [27036], [31603]]), + cdf_2d([ + [27877, 30490], + [11532, 25697], + [6544, 30234], + [23018, 28072], + [31915, 32385], + ]), + cdf_2d([ + [25572, 28046, 30045], + [9478, 21590, 27256], + [7248, 26837, 29824], + [19167, 24486, 28349], + [31400, 31825, 32250], + ]), + cdf_2d([ + [24779, 26955, 28576, 30282], + [8669, 20364, 24073, 28093], + [4255, 27565, 29377, 31067], + [19864, 23674, 26716, 29530], + [31646, 31893, 32147, 32426], + ]), + cdf_2d([ + [23132, 25407, 26970, 28435, 30073], + [7443, 17242, 20717, 24762, 27982], + [6300, 24862, 26944, 28784, 30671], + [18916, 22895, 25267, 27435, 29652], + [31270, 31550, 31808, 32059, 32353], + ]), + cdf_2d([ + [23105, 25199, 26464, 27684, 28931, 30318], + [6950, 15447, 18952, 22681, 25567, 28563], + [7560, 23474, 25490, 27203, 28921, 30708], + [18544, 22373, 24457, 26195, 28119, 30045], + [31198, 31451, 31670, 31882, 32123, 32391], + ]), + cdf_2d([ + [21689, 23883, 25163, 26352, 27506, 28827, 30195], + [6892, 15385, 17840, 21606, 24287, 26753, 29204], + [5651, 23182, 25042, 26518, 27982, 29392, 30900], + [19349, 22578, 24418, 25994, 27524, 29031, 30448], + [31028, 31270, 31504, 31705, 31927, 32153, 32392], + ]), +]; + +#[allow(unused)] +pub static default_palette_uv_color_index_cdf: [[[u16; + PaletteColor::PALETTE_COLORS as usize]; + PALETTE_COLOR_INDEX_CONTEXTS]; + PaletteSize::PALETTE_SIZES as usize] = [ + cdf_2d([[29089], [16384], [8713], [29257], [31610]]), + cdf_2d([ + [25257, 29145], + [12287, 27293], + [7033, 27960], + [20145, 25405], + [30608, 31639], + ]), + cdf_2d([ + [24210, 27175, 29903], + [9888, 22386, 27214], + [5901, 26053, 29293], + [18318, 22152, 28333], + [30459, 31136, 31926], + ]), + cdf_2d([ + [22980, 25479, 27781, 29986], + [8413, 21408, 24859, 28874], + [2257, 29449, 30594, 31598], + [19189, 21202, 25915, 28620], + [31844, 32044, 32281, 32518], + ]), + cdf_2d([ + [22217, 24567, 26637, 28683, 30548], + [7307, 16406, 19636, 24632, 28424], + [4441, 25064, 26879, 28942, 30919], + [17210, 20528, 23319, 26750, 29582], + [30674, 30953, 31396, 31735, 32207], + ]), + cdf_2d([ + [21239, 23168, 25044, 26962, 28705, 30506], + [6545, 15012, 18004, 21817, 25503, 28701], + [3448, 26295, 27437, 28704, 30126, 31442], + [15889, 18323, 21704, 24698, 26976, 29690], + [30988, 31204, 31479, 31734, 31983, 32325], + ]), + cdf_2d([ + [21442, 23288, 24758, 26246, 27649, 28980, 30563], + [5863, 14933, 17552, 20668, 23683, 26411, 29273], + [3415, 25810, 26877, 27990, 29223, 30394, 31618], + [17965, 20084, 22232, 23974, 26274, 28402, 30390], + [31190, 31329, 31516, 31679, 31825, 32026, 32322], + ]), +]; + +pub static default_txfm_partition_cdf: [[u16; 2]; TXFM_PARTITION_CONTEXTS] = + cdf_2d([ + [28581], + [23846], + [20847], + [24315], + [18196], + [12133], + [18791], + [10887], + [11005], + [27179], + [20004], + [11281], + [26549], + [19308], + [14224], + [28015], + [21546], + [14400], + [28165], + [22401], + [16088], + ]); + +pub static default_skip_cdfs: [[u16; 2]; SKIP_CONTEXTS] = + cdf_2d([[31671], [16515], [4576]]); + +#[allow(unused)] +pub static default_skip_mode_cdfs: [[u16; 2]; SKIP_MODE_CONTEXTS] = + cdf_2d([[32621], [20708], [8127]]); + +#[allow(unused)] +pub static default_compound_idx_cdfs: [[u16; 2]; COMP_INDEX_CONTEXTS] = + cdf_2d([[18244], [12865], [7053], [13259], [9334], [4644]]); + +#[allow(unused)] +pub static default_comp_group_idx_cdfs: [[u16; 2]; COMP_GROUP_IDX_CONTEXTS] = + cdf_2d([[26607], [22891], [18840], [24594], [19934], [22674]]); + +#[allow(unused)] +pub static default_intrabc_cdf: [u16; 2] = cdf([30531]); + +#[allow(unused)] +pub static default_filter_intra_mode_cdf: [u16; + FilterIntraMode::FILTER_INTRA_MODES as usize] = + cdf([8949, 12776, 17211, 29558]); + +pub static default_filter_intra_cdfs: [[u16; 2]; BlockSize::BLOCK_SIZES_ALL] = + cdf_2d([ + [4621], + [6743], + [5893], + [7866], + [12551], + [9394], + [12408], + [14301], + [12756], + [22343], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [12770], + [10368], + [20229], + [18101], + [16384], + [16384], + ]); + +pub static default_switchable_restore_cdf: [u16; RESTORE_SWITCHABLE_TYPES] = + cdf([9413, 22581]); + +pub static default_wiener_restore_cdf: [u16; 2] = cdf([11570]); + +pub static default_sgrproj_restore_cdf: [u16; 2] = cdf([16855]); + +#[allow(unused)] +pub static default_delta_q_cdf: [u16; DELTA_Q_PROBS + 1] = + cdf([28160, 32120, 32677]); + +pub static default_delta_lf_multi_cdf: [[u16; DELTA_LF_PROBS + 1]; + FRAME_LF_COUNT] = cdf_2d([ + [28160, 32120, 32677], + [28160, 32120, 32677], + [28160, 32120, 32677], + [28160, 32120, 32677], +]); + +pub static default_delta_lf_cdf: [u16; DELTA_LF_PROBS + 1] = + cdf([28160, 32120, 32677]); + +// FIXME(someone) need real defaults here +#[allow(unused)] +pub static default_seg_tree_cdf: [u16; MAX_SEGMENTS] = + cdf([4096, 8192, 12288, 16384, 20480, 24576, 28672]); + +#[allow(unused)] +pub static default_segment_pred_cdf: [[u16; 2]; SEG_TEMPORAL_PRED_CTXS] = + cdf_2d([[128 * 128], [128 * 128], [128 * 128]]); + +pub static default_spatial_pred_seg_tree_cdf: [[u16; MAX_SEGMENTS]; + SPATIAL_PREDICTION_PROBS] = cdf_2d([ + [5622, 7893, 16093, 18233, 27809, 28373, 32533], + [14274, 18230, 22557, 24935, 29980, 30851, 32344], + [27527, 28487, 28723, 28890, 32397, 32647, 32679], +]); + +pub static default_tx_size_8x8_cdf: [[u16; MAX_TX_DEPTH]; TX_SIZE_CONTEXTS] = + cdf_2d([[19968], [19968], [24320]]); + +pub static default_tx_size_cdf: [[[u16; MAX_TX_DEPTH + 1]; TX_SIZE_CONTEXTS]; + BIG_TX_CATS] = cdf_3d([ + [[12272, 30172], [12272, 30172], [18677, 30848]], + [[12986, 15180], [12986, 15180], [24302, 25602]], + [[5782, 11475], [5782, 11475], [16803, 22759]], +]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/ext/x86/x86inc.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ext/x86/x86inc.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/ext/x86/x86inc.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/ext/x86/x86inc.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1902 @@ +;***************************************************************************** +;* x86inc.asm: x86 abstraction layer +;***************************************************************************** +;* Copyright (C) 2005-2022 x264 project +;* +;* Authors: Loren Merritt +;* Henrik Gramner +;* Anton Mitrofanov +;* Fiona Glaser +;* +;* Permission to use, copy, modify, and/or distribute this software for any +;* purpose with or without fee is hereby granted, provided that the above +;* copyright notice and this permission notice appear in all copies. +;* +;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +;***************************************************************************** + +; This is a header file for the x86inc.asm assembly language, which uses +; NASM/YASM syntax combined with a large number of macros to provide easy +; abstraction between different calling conventions (x86_32, win64, linux64). +; It also has various other useful features to simplify writing the kind of +; DSP functions that are most often used. + +%ifndef private_prefix + %error private_prefix not defined +%endif + +%ifndef public_prefix + %define public_prefix private_prefix +%endif + +%ifndef STACK_ALIGNMENT + %if ARCH_X86_64 + %define STACK_ALIGNMENT 16 + %else + %define STACK_ALIGNMENT 4 + %endif +%endif + +%define WIN64 0 +%define UNIX64 0 +%if ARCH_X86_64 + %ifidn __OUTPUT_FORMAT__,win32 + %define WIN64 1 + %elifidn __OUTPUT_FORMAT__,win64 + %define WIN64 1 + %elifidn __OUTPUT_FORMAT__,x64 + %define WIN64 1 + %else + %define UNIX64 1 + %endif +%endif + +%define FORMAT_ELF 0 +%define FORMAT_MACHO 0 +%ifidn __OUTPUT_FORMAT__,elf + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf32 + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf64 + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,macho + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho32 + %define FORMAT_MACHO 1 +%elifidn __OUTPUT_FORMAT__,macho64 + %define FORMAT_MACHO 1 +%endif + +%ifdef PREFIX + %define mangle(x) _ %+ x +%else + %define mangle(x) x +%endif + +; Use VEX-encoding even in non-AVX functions +%ifndef FORCE_VEX_ENCODING + %define FORCE_VEX_ENCODING 0 +%endif + +%macro SECTION_RODATA 0-1 16 + %ifidn __OUTPUT_FORMAT__,win32 + SECTION .rdata align=%1 + %elif WIN64 + SECTION .rdata align=%1 + %else + SECTION .rodata align=%1 + %endif +%endmacro + +%if ARCH_X86_64 + %define PIC 1 ; always use PIC on x86-64 + default rel +%elifidn __OUTPUT_FORMAT__,win32 + %define PIC 0 ; PIC isn't used on 32-bit Windows +%elifndef PIC + %define PIC 0 +%endif + +%define HAVE_PRIVATE_EXTERN 1 +%ifdef __NASM_VER__ + %use smartalign + %if __NASM_VERSION_ID__ < 0x020e0000 ; 2.14 + %define HAVE_PRIVATE_EXTERN 0 + %endif +%endif + +; Macros to eliminate most code duplication between x86_32 and x86_64: +; Currently this works only for leaf functions which load all their arguments +; into registers at the start, and make no other use of the stack. Luckily that +; covers most use cases. + +; PROLOGUE: +; %1 = number of arguments. loads them from stack if needed. +; %2 = number of registers used. pushes callee-saved regs if needed. +; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed. +; %4 = (optional) stack size to be allocated. The stack will be aligned before +; allocating the specified stack size. If the required stack alignment is +; larger than the known stack alignment the stack will be manually aligned +; and an extra register will be allocated to hold the original stack +; pointer (to not invalidate r0m etc.). To prevent the use of an extra +; register as stack pointer, request a negative stack size. +; %4+/%5+ = list of names to define to registers +; PROLOGUE can also be invoked by adding the same options to cglobal + +; e.g. +; cglobal foo, 2,3,7,0x40, dst, src, tmp +; declares a function (foo) that automatically loads two arguments (dst and +; src) into registers, uses one additional register (tmp) plus 7 vector +; registers (m0-m6) and allocates 0x40 bytes of stack space. + +; TODO Some functions can use some args directly from the stack. If they're the +; last args then you can just not declare them, but if they're in the middle +; we need more flexible macro. + +; RET: +; Pops anything that was pushed by PROLOGUE, and returns. + +; REP_RET: +; Use this instead of RET if it's a branch target. + +; registers: +; rN and rNq are the native-size register holding function argument N +; rNd, rNw, rNb are dword, word, and byte size +; rNh is the high 8 bits of the word size +; rNm is the original location of arg N (a register or on the stack), dword +; rNmp is native size + +%macro DECLARE_REG 2-3 + %define r%1q %2 + %define r%1d %2d + %define r%1w %2w + %define r%1b %2b + %define r%1h %2h + %define %2q %2 + %if %0 == 2 + %define r%1m %2d + %define r%1mp %2 + %elif ARCH_X86_64 ; memory + %define r%1m [rstk + stack_offset + %3] + %define r%1mp qword r %+ %1 %+ m + %else + %define r%1m [rstk + stack_offset + %3] + %define r%1mp dword r %+ %1 %+ m + %endif + %define r%1 %2 +%endmacro + +%macro DECLARE_REG_SIZE 3 + %define r%1q r%1 + %define e%1q r%1 + %define r%1d e%1 + %define e%1d e%1 + %define r%1w %1 + %define e%1w %1 + %define r%1h %3 + %define e%1h %3 + %define r%1b %2 + %define e%1b %2 + %if ARCH_X86_64 == 0 + %define r%1 e%1 + %endif +%endmacro + +DECLARE_REG_SIZE ax, al, ah +DECLARE_REG_SIZE bx, bl, bh +DECLARE_REG_SIZE cx, cl, ch +DECLARE_REG_SIZE dx, dl, dh +DECLARE_REG_SIZE si, sil, null +DECLARE_REG_SIZE di, dil, null +DECLARE_REG_SIZE bp, bpl, null + +; t# defines for when per-arch register allocation is more complex than just function arguments + +%macro DECLARE_REG_TMP 1-* + %assign %%i 0 + %rep %0 + CAT_XDEFINE t, %%i, r%1 + %assign %%i %%i+1 + %rotate 1 + %endrep +%endmacro + +%macro DECLARE_REG_TMP_SIZE 0-* + %rep %0 + %define t%1q t%1 %+ q + %define t%1d t%1 %+ d + %define t%1w t%1 %+ w + %define t%1h t%1 %+ h + %define t%1b t%1 %+ b + %rotate 1 + %endrep +%endmacro + +DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 + +%if ARCH_X86_64 + %define gprsize 8 +%else + %define gprsize 4 +%endif + +%macro LEA 2 +%if ARCH_X86_64 + lea %1, [%2] +%elif PIC + call $+5 ; special-cased to not affect the RSB on most CPU:s + pop %1 + add %1, (%2)-$+1 +%else + mov %1, %2 +%endif +%endmacro + +; Repeats an instruction/operation for multiple arguments. +; Example usage: "REPX {psrlw x, 8}, m0, m1, m2, m3" +%macro REPX 2-* ; operation, args + %xdefine %%f(x) %1 + %rep %0 - 1 + %rotate 1 + %%f(%1) + %endrep +%endmacro + +%macro PUSH 1 + push %1 + %ifidn rstk, rsp + %assign stack_offset stack_offset+gprsize + %endif +%endmacro + +%macro POP 1 + pop %1 + %ifidn rstk, rsp + %assign stack_offset stack_offset-gprsize + %endif +%endmacro + +%macro PUSH_IF_USED 1-* + %rep %0 + %if %1 < regs_used + PUSH r%1 + %endif + %rotate 1 + %endrep +%endmacro + +%macro POP_IF_USED 1-* + %rep %0 + %if %1 < regs_used + pop r%1 + %endif + %rotate 1 + %endrep +%endmacro + +%macro LOAD_IF_USED 1-* + %rep %0 + %if %1 < num_args + mov r%1, r %+ %1 %+ mp + %endif + %rotate 1 + %endrep +%endmacro + +%macro SUB 2 + sub %1, %2 + %ifidn %1, rstk + %assign stack_offset stack_offset+(%2) + %endif +%endmacro + +%macro ADD 2 + add %1, %2 + %ifidn %1, rstk + %assign stack_offset stack_offset-(%2) + %endif +%endmacro + +%macro movifnidn 2 + %ifnidn %1, %2 + mov %1, %2 + %endif +%endmacro + +%if ARCH_X86_64 == 0 + %define movsxd movifnidn +%endif + +%macro movsxdifnidn 2 + %ifnidn %1, %2 + movsxd %1, %2 + %endif +%endmacro + +%macro ASSERT 1 + %if (%1) == 0 + %error assertion ``%1'' failed + %endif +%endmacro + +%macro DEFINE_ARGS 0-* + %ifdef n_arg_names + %assign %%i 0 + %rep n_arg_names + CAT_UNDEF arg_name %+ %%i, q + CAT_UNDEF arg_name %+ %%i, d + CAT_UNDEF arg_name %+ %%i, w + CAT_UNDEF arg_name %+ %%i, h + CAT_UNDEF arg_name %+ %%i, b + CAT_UNDEF arg_name %+ %%i, m + CAT_UNDEF arg_name %+ %%i, mp + CAT_UNDEF arg_name, %%i + %assign %%i %%i+1 + %endrep + %endif + + %xdefine %%stack_offset stack_offset + %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine + %assign %%i 0 + %rep %0 + %xdefine %1q r %+ %%i %+ q + %xdefine %1d r %+ %%i %+ d + %xdefine %1w r %+ %%i %+ w + %xdefine %1h r %+ %%i %+ h + %xdefine %1b r %+ %%i %+ b + %xdefine %1m r %+ %%i %+ m + %xdefine %1mp r %+ %%i %+ mp + CAT_XDEFINE arg_name, %%i, %1 + %assign %%i %%i+1 + %rotate 1 + %endrep + %xdefine stack_offset %%stack_offset + %assign n_arg_names %0 +%endmacro + +%define required_stack_alignment ((mmsize + 15) & ~15) +%define vzeroupper_required (mmsize > 16 && (ARCH_X86_64 == 0 || xmm_regs_used > 16 || notcpuflag(avx512))) +%define high_mm_regs (16*cpuflag(avx512)) + +; Large stack allocations on Windows need to use stack probing in order +; to guarantee that all stack memory is committed before accessing it. +; This is done by ensuring that the guard page(s) at the end of the +; currently committed pages are touched prior to any pages beyond that. +%if WIN64 + %assign STACK_PROBE_SIZE 8192 +%elifidn __OUTPUT_FORMAT__, win32 + %assign STACK_PROBE_SIZE 4096 +%else + %assign STACK_PROBE_SIZE 0 +%endif + +%macro PROBE_STACK 1 ; stack_size + %if STACK_PROBE_SIZE + %assign %%i STACK_PROBE_SIZE + %rep %1 / STACK_PROBE_SIZE + mov eax, [rsp-%%i] + %assign %%i %%i+STACK_PROBE_SIZE + %endrep + %endif +%endmacro + +%macro ALLOC_STACK 0-2 0, 0 ; stack_size, n_xmm_regs (for win64 only) + %ifnum %1 + %if %1 != 0 + %assign %%pad 0 + %assign stack_size %1 + %if stack_size < 0 + %assign stack_size -stack_size + %endif + %if WIN64 + %assign %%pad %%pad + 32 ; shadow space + %if mmsize != 8 + %assign xmm_regs_used %2 + %if xmm_regs_used > 8 + %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers + %endif + %endif + %endif + %if required_stack_alignment <= STACK_ALIGNMENT + ; maintain the current stack alignment + %assign stack_size_padded stack_size + %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + PROBE_STACK stack_size_padded + SUB rsp, stack_size_padded + %else + %assign %%reg_num (regs_used - 1) + %xdefine rstk r %+ %%reg_num + ; align stack, and save original stack location directly above + ; it, i.e. in [rsp+stack_size_padded], so we can restore the + ; stack in a single instruction (i.e. mov rsp, rstk or mov + ; rsp, [rsp+stack_size_padded]) + %if %1 < 0 ; need to store rsp on stack + %xdefine rstkm [rsp + stack_size + %%pad] + %assign %%pad %%pad + gprsize + %else ; can keep rsp in rstk during whole function + %xdefine rstkm rstk + %endif + %assign stack_size_padded stack_size + ((%%pad + required_stack_alignment-1) & ~(required_stack_alignment-1)) + PROBE_STACK stack_size_padded + mov rstk, rsp + and rsp, ~(required_stack_alignment-1) + sub rsp, stack_size_padded + movifnidn rstkm, rstk + %endif + WIN64_PUSH_XMM + %endif + %endif +%endmacro + +%macro SETUP_STACK_POINTER 0-1 0 + %ifnum %1 + %if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT + %if %1 > 0 + ; Reserve an additional register for storing the original stack pointer, but avoid using + ; eax/rax for this purpose since it can potentially get overwritten as a return value. + %assign regs_used (regs_used + 1) + %if ARCH_X86_64 && regs_used == 7 + %assign regs_used 8 + %elif ARCH_X86_64 == 0 && regs_used == 1 + %assign regs_used 2 + %endif + %endif + %if ARCH_X86_64 && regs_used < 5 + UNIX64 * 3 + ; Ensure that we don't clobber any registers containing arguments. For UNIX64 we also preserve r6 (rax) + ; since it's used as a hidden argument in vararg functions to specify the number of vector registers used. + %assign regs_used 5 + UNIX64 * 3 + %endif + %endif + %endif +%endmacro + +%if WIN64 ; Windows x64 ;================================================= + +DECLARE_REG 0, rcx +DECLARE_REG 1, rdx +DECLARE_REG 2, R8 +DECLARE_REG 3, R9 +DECLARE_REG 4, R10, 40 +DECLARE_REG 5, R11, 48 +DECLARE_REG 6, rax, 56 +DECLARE_REG 7, rdi, 64 +DECLARE_REG 8, rsi, 72 +DECLARE_REG 9, rbx, 80 +DECLARE_REG 10, rbp, 88 +DECLARE_REG 11, R14, 96 +DECLARE_REG 12, R15, 104 +DECLARE_REG 13, R12, 112 +DECLARE_REG 14, R13, 120 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + ASSERT regs_used >= num_args + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 15 + PUSH_IF_USED 7, 8, 9, 10, 11, 12, 13, 14 + ALLOC_STACK %4, %3 + %if mmsize != 8 && stack_size == 0 + WIN64_SPILL_XMM %3 + %endif + LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%macro WIN64_PUSH_XMM 0 + ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated. + %if xmm_regs_used > 6 + high_mm_regs + movaps [rstk + stack_offset + 8], xmm6 + %endif + %if xmm_regs_used > 7 + high_mm_regs + movaps [rstk + stack_offset + 24], xmm7 + %endif + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + %assign %%i 8 + %rep %%xmm_regs_on_stack + movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i + %assign %%i %%i+1 + %endrep + %endif +%endmacro + +%macro WIN64_SPILL_XMM 1 + %assign xmm_regs_used %1 + ASSERT xmm_regs_used <= 16 + high_mm_regs + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. + %assign %%pad %%xmm_regs_on_stack*16 + 32 + %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) + SUB rsp, stack_size_padded + %endif + WIN64_PUSH_XMM +%endmacro + +%macro WIN64_RESTORE_XMM_INTERNAL 0 + %assign %%pad_size 0 + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + %assign %%i xmm_regs_used - high_mm_regs + %rep %%xmm_regs_on_stack + %assign %%i %%i-1 + movaps xmm %+ %%i, [rsp + (%%i-8)*16 + stack_size + 32] + %endrep + %endif + %if stack_size_padded > 0 + %if stack_size > 0 && required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %assign %%pad_size stack_size_padded + %endif + %endif + %if xmm_regs_used > 7 + high_mm_regs + movaps xmm7, [rsp + stack_offset - %%pad_size + 24] + %endif + %if xmm_regs_used > 6 + high_mm_regs + movaps xmm6, [rsp + stack_offset - %%pad_size + 8] + %endif +%endmacro + +%macro WIN64_RESTORE_XMM 0 + WIN64_RESTORE_XMM_INTERNAL + %assign stack_offset (stack_offset-stack_size_padded) + %assign stack_size_padded 0 + %assign xmm_regs_used 0 +%endmacro + +%define has_epilogue regs_used > 7 || stack_size > 0 || vzeroupper_required || xmm_regs_used > 6+high_mm_regs + +%macro RET 0 + WIN64_RESTORE_XMM_INTERNAL + POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%elif ARCH_X86_64 ; *nix x64 ;============================================= + +DECLARE_REG 0, rdi +DECLARE_REG 1, rsi +DECLARE_REG 2, rdx +DECLARE_REG 3, rcx +DECLARE_REG 4, R8 +DECLARE_REG 5, R9 +DECLARE_REG 6, rax, 8 +DECLARE_REG 7, R10, 16 +DECLARE_REG 8, R11, 24 +DECLARE_REG 9, rbx, 32 +DECLARE_REG 10, rbp, 40 +DECLARE_REG 11, R14, 48 +DECLARE_REG 12, R15, 56 +DECLARE_REG 13, R12, 64 +DECLARE_REG 14, R13, 72 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + %assign xmm_regs_used %3 + ASSERT regs_used >= num_args + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 15 + PUSH_IF_USED 9, 10, 11, 12, 13, 14 + ALLOC_STACK %4 + LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%define has_epilogue regs_used > 9 || stack_size > 0 || vzeroupper_required + +%macro RET 0 + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif + POP_IF_USED 14, 13, 12, 11, 10, 9 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%else ; X86_32 ;============================================================== + +DECLARE_REG 0, eax, 4 +DECLARE_REG 1, ecx, 8 +DECLARE_REG 2, edx, 12 +DECLARE_REG 3, ebx, 16 +DECLARE_REG 4, esi, 20 +DECLARE_REG 5, edi, 24 +DECLARE_REG 6, ebp, 28 +%define rsp esp + +%macro DECLARE_ARG 1-* + %rep %0 + %define r%1m [rstk + stack_offset + 4*%1 + 4] + %define r%1mp dword r%1m + %rotate 1 + %endrep +%endmacro + +DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 + +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... + %assign num_args %1 + %assign regs_used %2 + ASSERT regs_used >= num_args + %if num_args > 7 + %assign num_args 7 + %endif + %if regs_used > 7 + %assign regs_used 7 + %endif + SETUP_STACK_POINTER %4 + ASSERT regs_used <= 7 + PUSH_IF_USED 3, 4, 5, 6 + ALLOC_STACK %4 + LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif +%endmacro + +%define has_epilogue regs_used > 3 || stack_size > 0 || vzeroupper_required + +%macro RET 0 + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif + POP_IF_USED 6, 5, 4, 3 + %if vzeroupper_required + vzeroupper + %endif + AUTO_REP_RET +%endmacro + +%endif ;====================================================================== + +%if WIN64 == 0 + %macro WIN64_SPILL_XMM 1 + %assign xmm_regs_used %1 + %endmacro + %macro WIN64_RESTORE_XMM 0 + %assign xmm_regs_used 0 + %endmacro + %macro WIN64_PUSH_XMM 0 + %endmacro +%endif + +; On AMD cpus <=K10, an ordinary ret is slow if it immediately follows either +; a branch or a branch target. So switch to a 2-byte form of ret in that case. +; We can automatically detect "follows a branch", but not a branch target. +; (SSSE3 is a sufficient condition to know that your cpu doesn't have this problem.) +%macro REP_RET 0 + %if has_epilogue || cpuflag(ssse3) + RET + %else + rep ret + %endif + annotate_function_size +%endmacro + +%define last_branch_adr $$ +%macro AUTO_REP_RET 0 + %if notcpuflag(ssse3) + times ((last_branch_adr-$)>>31)+1 rep ; times 1 iff $ == last_branch_adr. + %endif + ret + annotate_function_size +%endmacro + +%macro BRANCH_INSTR 0-* + %rep %0 + %macro %1 1-2 %1 + %2 %1 + %if notcpuflag(ssse3) + %%branch_instr equ $ + %xdefine last_branch_adr %%branch_instr + %endif + %endmacro + %rotate 1 + %endrep +%endmacro + +BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, jna, jnae, jb, jbe, jnb, jnbe, jc, jnc, js, jns, jo, jno, jp, jnp + +%macro TAIL_CALL 1-2 1 ; callee, is_nonadjacent + %if has_epilogue + call %1 + RET + %elif %2 + jmp %1 + %endif + annotate_function_size +%endmacro + +;============================================================================= +; arch-independent part +;============================================================================= + +%assign function_align 16 + +; Begin a function. +; Applies any symbol mangling needed for C linkage, and sets up a define such that +; subsequent uses of the function name automatically refer to the mangled version. +; Appends cpuflags to the function name if cpuflags has been specified. +; The "" empty default parameter is a workaround for nasm, which fails if SUFFIX +; is empty and we call cglobal_internal with just %1 %+ SUFFIX (without %2). +%macro cglobal 1-2+ "" ; name, [PROLOGUE args] + cglobal_internal 1, %1 %+ SUFFIX, %2 +%endmacro +%macro cvisible 1-2+ "" ; name, [PROLOGUE args] + cglobal_internal 0, %1 %+ SUFFIX, %2 +%endmacro +%macro cglobal_internal 2-3+ + annotate_function_size + %ifndef cglobaled_%2 + %if %1 + %xdefine %2 mangle(private_prefix %+ _ %+ %2) + %else + %xdefine %2 mangle(public_prefix %+ _ %+ %2) + %endif + %xdefine %2.skip_prologue %2 %+ .skip_prologue + CAT_XDEFINE cglobaled_, %2, 1 + %endif + %xdefine current_function %2 + %xdefine current_function_section __SECT__ + %if FORMAT_ELF + %if %1 + global %2:function hidden + %else + global %2:function + %endif + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN && %1 + global %2:private_extern + %else + global %2 + %endif + align function_align + %2: + RESET_MM_PERMUTATION ; needed for x86-64, also makes disassembly somewhat nicer + %xdefine rstk rsp ; copy of the original stack pointer, used when greater alignment than the known stack alignment is required + %assign stack_offset 0 ; stack pointer offset relative to the return address + %assign stack_size 0 ; amount of stack space that can be freely used inside a function + %assign stack_size_padded 0 ; total amount of allocated stack space, including space for callee-saved xmm registers on WIN64 and alignment padding + %assign xmm_regs_used 0 ; number of XMM registers requested, used for dealing with callee-saved registers on WIN64 and vzeroupper + %ifnidn %3, "" + PROLOGUE %3 + %endif +%endmacro + +; Create a global symbol from a local label with the correct name mangling and type +%macro cglobal_label 1 + %if FORMAT_ELF + global current_function %+ %1:function hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global current_function %+ %1:private_extern + %else + global current_function %+ %1 + %endif + %1: +%endmacro + +%macro cextern 1 + %xdefine %1 mangle(private_prefix %+ _ %+ %1) + CAT_XDEFINE cglobaled_, %1, 1 + extern %1 +%endmacro + +; like cextern, but without the prefix +%macro cextern_naked 1 + %ifdef PREFIX + %xdefine %1 mangle(%1) + %endif + CAT_XDEFINE cglobaled_, %1, 1 + extern %1 +%endmacro + +%macro const 1-2+ + %xdefine %1 mangle(private_prefix %+ _ %+ %1) + %if FORMAT_ELF + global %1:data hidden + %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN + global %1:private_extern + %else + global %1 + %endif + %1: %2 +%endmacro + +; This is needed for ELF, otherwise the GNU linker assumes the stack is executable by default. +%if FORMAT_ELF + [SECTION .note.GNU-stack noalloc noexec nowrite progbits] +%endif + +; Tell debuggers how large the function was. +; This may be invoked multiple times per function; we rely on later instances overriding earlier ones. +; This is invoked by RET and similar macros, and also cglobal does it for the previous function, +; but if the last function in a source file doesn't use any of the standard macros for its epilogue, +; then its size might be unspecified. +%macro annotate_function_size 0 + %ifdef __YASM_VER__ + %ifdef current_function + %if FORMAT_ELF + current_function_section + %%ecf equ $ + size current_function %%ecf - current_function + __SECT__ + %endif + %endif + %endif +%endmacro + +; cpuflags + +%assign cpuflags_mmx (1<<0) +%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx +%assign cpuflags_3dnow (1<<2) | cpuflags_mmx +%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow +%assign cpuflags_sse (1<<4) | cpuflags_mmx2 +%assign cpuflags_sse2 (1<<5) | cpuflags_sse +%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 +%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 +%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 +%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 +%assign cpuflags_sse4 (1<<10) | cpuflags_ssse3 +%assign cpuflags_sse42 (1<<11) | cpuflags_sse4 +%assign cpuflags_aesni (1<<12) | cpuflags_sse42 +%assign cpuflags_gfni (1<<13) | cpuflags_sse42 +%assign cpuflags_avx (1<<14) | cpuflags_sse42 +%assign cpuflags_xop (1<<15) | cpuflags_avx +%assign cpuflags_fma4 (1<<16) | cpuflags_avx +%assign cpuflags_fma3 (1<<17) | cpuflags_avx +%assign cpuflags_bmi1 (1<<18) | cpuflags_avx|cpuflags_lzcnt +%assign cpuflags_bmi2 (1<<19) | cpuflags_bmi1 +%assign cpuflags_avx2 (1<<20) | cpuflags_fma3|cpuflags_bmi2 +%assign cpuflags_avx512 (1<<21) | cpuflags_avx2 ; F, CD, BW, DQ, VL +%assign cpuflags_avx512icl (1<<22) | cpuflags_avx512|cpuflags_gfni ; VNNI, IFMA, VBMI, VBMI2, VPOPCNTDQ, BITALG, VAES, VPCLMULQDQ + +%assign cpuflags_cache32 (1<<23) +%assign cpuflags_cache64 (1<<24) +%assign cpuflags_aligned (1<<25) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<26) + +; Returns a boolean value expressing whether or not the specified cpuflag is enabled. +%define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) +%define notcpuflag(x) (cpuflag(x) ^ 1) + +; Takes an arbitrary number of cpuflags from the above list. +; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu. +; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co. +%macro INIT_CPUFLAGS 0-* + %xdefine SUFFIX + %undef cpuname + %assign cpuflags 0 + + %if %0 >= 1 + %rep %0 + %ifdef cpuname + %xdefine cpuname cpuname %+ _%1 + %else + %xdefine cpuname %1 + %endif + %assign cpuflags cpuflags | cpuflags_%1 + %rotate 1 + %endrep + %xdefine SUFFIX _ %+ cpuname + + %if cpuflag(avx) + %assign avx_enabled 1 + %endif + %if (mmsize == 16 && notcpuflag(sse2)) || (mmsize == 32 && notcpuflag(avx2)) + %define mova movaps + %define movu movups + %define movnta movntps + %endif + %if cpuflag(aligned) + %define movu mova + %elif cpuflag(sse3) && notcpuflag(ssse3) + %define movu lddqu + %endif + %endif + + %if ARCH_X86_64 || cpuflag(sse2) + %ifdef __NASM_VER__ + ALIGNMODE p6 + %else + CPU amdnop + %endif + %else + %ifdef __NASM_VER__ + ALIGNMODE nop + %else + CPU basicnop + %endif + %endif +%endmacro + +; Merge mmx, sse*, and avx* +; m# is a simd register of the currently selected size +; xm# is the corresponding xmm register if mmsize >= 16, otherwise the same as m# +; ym# is the corresponding ymm register if mmsize >= 32, otherwise the same as m# +; zm# is the corresponding zmm register if mmsize >= 64, otherwise the same as m# +; (All 4 remain in sync through SWAP.) + +%macro CAT_XDEFINE 3 + %xdefine %1%2 %3 +%endmacro + +%macro CAT_UNDEF 2 + %undef %1%2 +%endmacro + +%macro DEFINE_MMREGS 1 ; mmtype + %assign %%prev_mmregs 0 + %ifdef num_mmregs + %assign %%prev_mmregs num_mmregs + %endif + + %assign num_mmregs 8 + %if ARCH_X86_64 && mmsize >= 16 + %assign num_mmregs 16 + %if cpuflag(avx512) || mmsize == 64 + %assign num_mmregs 32 + %endif + %endif + + %assign %%i 0 + %rep num_mmregs + CAT_XDEFINE m, %%i, %1 %+ %%i + CAT_XDEFINE nn%1, %%i, %%i + %assign %%i %%i+1 + %endrep + %if %%prev_mmregs > num_mmregs + %rep %%prev_mmregs - num_mmregs + CAT_UNDEF m, %%i + CAT_UNDEF nn %+ mmtype, %%i + %assign %%i %%i+1 + %endrep + %endif + %xdefine mmtype %1 +%endmacro + +; Prefer registers 16-31 over 0-15 to avoid having to use vzeroupper +%macro AVX512_MM_PERMUTATION 0-1 0 ; start_reg + %if ARCH_X86_64 && cpuflag(avx512) + %assign %%i %1 + %rep 16-%1 + %assign %%i_high %%i+16 + SWAP %%i, %%i_high + %assign %%i %%i+1 + %endrep + %endif +%endmacro + +%macro INIT_MMX 0-1+ + %assign avx_enabled 0 + %define RESET_MM_PERMUTATION INIT_MMX %1 + %define mmsize 8 + %define mova movq + %define movu movq + %define movh movd + %define movnta movntq + INIT_CPUFLAGS %1 + DEFINE_MMREGS mm +%endmacro + +%macro INIT_XMM 0-1+ + %assign avx_enabled FORCE_VEX_ENCODING + %define RESET_MM_PERMUTATION INIT_XMM %1 + %define mmsize 16 + %define mova movdqa + %define movu movdqu + %define movh movq + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS xmm + %if WIN64 + AVX512_MM_PERMUTATION 6 ; Swap callee-saved registers with volatile registers + %endif + %xdefine bcstd 1to4 + %xdefine bcstq 1to2 +%endmacro + +%macro INIT_YMM 0-1+ + %assign avx_enabled 1 + %define RESET_MM_PERMUTATION INIT_YMM %1 + %define mmsize 32 + %define mova movdqa + %define movu movdqu + %undef movh + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS ymm + AVX512_MM_PERMUTATION + %xdefine bcstd 1to8 + %xdefine bcstq 1to4 +%endmacro + +%macro INIT_ZMM 0-1+ + %assign avx_enabled 1 + %define RESET_MM_PERMUTATION INIT_ZMM %1 + %define mmsize 64 + %define mova movdqa + %define movu movdqu + %undef movh + %define movnta movntdq + INIT_CPUFLAGS %1 + DEFINE_MMREGS zmm + AVX512_MM_PERMUTATION + %xdefine bcstd 1to16 + %xdefine bcstq 1to8 +%endmacro + +INIT_XMM + +%macro DECLARE_MMCAST 1 + %define mmmm%1 mm%1 + %define mmxmm%1 mm%1 + %define mmymm%1 mm%1 + %define mmzmm%1 mm%1 + %define xmmmm%1 mm%1 + %define xmmxmm%1 xmm%1 + %define xmmymm%1 xmm%1 + %define xmmzmm%1 xmm%1 + %define ymmmm%1 mm%1 + %define ymmxmm%1 xmm%1 + %define ymmymm%1 ymm%1 + %define ymmzmm%1 ymm%1 + %define zmmmm%1 mm%1 + %define zmmxmm%1 xmm%1 + %define zmmymm%1 ymm%1 + %define zmmzmm%1 zmm%1 + %define xm%1 xmm %+ m%1 + %define ym%1 ymm %+ m%1 + %define zm%1 zmm %+ m%1 +%endmacro + +%assign i 0 +%rep 32 + DECLARE_MMCAST i + %assign i i+1 +%endrep + +; I often want to use macros that permute their arguments. e.g. there's no +; efficient way to implement butterfly or transpose or dct without swapping some +; arguments. +; +; I would like to not have to manually keep track of the permutations: +; If I insert a permutation in the middle of a function, it should automatically +; change everything that follows. For more complex macros I may also have multiple +; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations. +; +; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that +; permutes its arguments. It's equivalent to exchanging the contents of the +; registers, except that this way you exchange the register names instead, so it +; doesn't cost any cycles. + +%macro PERMUTE 2-* ; takes a list of pairs to swap + %rep %0/2 + %xdefine %%tmp%2 m%2 + %rotate 2 + %endrep + %rep %0/2 + %xdefine m%1 %%tmp%2 + CAT_XDEFINE nn, m%1, %1 + %rotate 2 + %endrep +%endmacro + +%macro SWAP 2+ ; swaps a single chain (sometimes more concise than pairs) + %ifnum %1 ; SWAP 0, 1, ... + SWAP_INTERNAL_NUM %1, %2 + %else ; SWAP m0, m1, ... + SWAP_INTERNAL_NAME %1, %2 + %endif +%endmacro + +%macro SWAP_INTERNAL_NUM 2-* + %rep %0-1 + %xdefine %%tmp m%1 + %xdefine m%1 m%2 + %xdefine m%2 %%tmp + CAT_XDEFINE nn, m%1, %1 + CAT_XDEFINE nn, m%2, %2 + %rotate 1 + %endrep +%endmacro + +%macro SWAP_INTERNAL_NAME 2-* + %xdefine %%args nn %+ %1 + %rep %0-1 + %xdefine %%args %%args, nn %+ %2 + %rotate 1 + %endrep + SWAP_INTERNAL_NUM %%args +%endmacro + +; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later +; calls to that function will automatically load the permutation, so values can +; be returned in mmregs. +%macro SAVE_MM_PERMUTATION 0-1 + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif + %assign %%i 0 + %rep num_mmregs + %xdefine %%tmp m %+ %%i + CAT_XDEFINE %%f, %%i, regnumof %+ %%tmp + %assign %%i %%i+1 + %endrep +%endmacro + +%macro LOAD_MM_PERMUTATION 0-1 ; name to load from + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif + %xdefine %%tmp %%f %+ 0 + %ifnum %%tmp + DEFINE_MMREGS mmtype + %assign %%i 0 + %rep num_mmregs + %xdefine %%tmp %%f %+ %%i + CAT_XDEFINE %%m, %%i, m %+ %%tmp + %assign %%i %%i+1 + %endrep + %rep num_mmregs + %assign %%i %%i-1 + CAT_XDEFINE m, %%i, %%m %+ %%i + CAT_XDEFINE nn, m %+ %%i, %%i + %endrep + %endif +%endmacro + +; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't +%macro call 1 + %ifid %1 + call_internal %1 %+ SUFFIX, %1 + %else + call %1 + %endif +%endmacro +%macro call_internal 2 + %xdefine %%i %2 + %ifndef cglobaled_%2 + %ifdef cglobaled_%1 + %xdefine %%i %1 + %endif + %endif + call %%i + LOAD_MM_PERMUTATION %%i +%endmacro + +; Substitutions that reduce instruction size but are functionally equivalent +%macro add 2 + %ifnum %2 + %if %2==128 + sub %1, -128 + %else + add %1, %2 + %endif + %else + add %1, %2 + %endif +%endmacro + +%macro sub 2 + %ifnum %2 + %if %2==128 + add %1, -128 + %else + sub %1, %2 + %endif + %else + sub %1, %2 + %endif +%endmacro + +;============================================================================= +; AVX abstraction layer +;============================================================================= + +%assign i 0 +%rep 32 + %if i < 8 + CAT_XDEFINE sizeofmm, i, 8 + CAT_XDEFINE regnumofmm, i, i + %endif + CAT_XDEFINE sizeofxmm, i, 16 + CAT_XDEFINE sizeofymm, i, 32 + CAT_XDEFINE sizeofzmm, i, 64 + CAT_XDEFINE regnumofxmm, i, i + CAT_XDEFINE regnumofymm, i, i + CAT_XDEFINE regnumofzmm, i, i + %assign i i+1 +%endrep +%undef i + +%macro CHECK_AVX_INSTR_EMU 3-* + %xdefine %%opcode %1 + %xdefine %%dst %2 + %rep %0-2 + %ifidn %%dst, %3 + %error non-avx emulation of ``%%opcode'' is not supported + %endif + %rotate 1 + %endrep +%endmacro + +;%1 == instruction +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +;%6+: operands +%macro RUN_AVX_INSTR 6-9+ + %ifnum sizeof%7 + %assign __sizeofreg sizeof%7 + %elifnum sizeof%6 + %assign __sizeofreg sizeof%6 + %else + %assign __sizeofreg mmsize + %endif + %assign __emulate_avx 0 + %if avx_enabled && __sizeofreg >= 16 + %xdefine __instr v%1 + %else + %xdefine __instr %1 + %if %0 >= 8+%4 + %assign __emulate_avx 1 + %endif + %endif + %ifnidn %2, fnord + %ifdef cpuname + %if notcpuflag(%2) + %error use of ``%1'' %2 instruction in cpuname function: current_function + %elif %3 == 0 && __sizeofreg == 16 && notcpuflag(sse2) + %error use of ``%1'' sse2 instruction in cpuname function: current_function + %elif %3 == 0 && __sizeofreg == 32 && notcpuflag(avx2) + %error use of ``%1'' avx2 instruction in cpuname function: current_function + %elif __sizeofreg == 16 && notcpuflag(sse) + %error use of ``%1'' sse instruction in cpuname function: current_function + %elif __sizeofreg == 32 && notcpuflag(avx) + %error use of ``%1'' avx instruction in cpuname function: current_function + %elif __sizeofreg == 64 && notcpuflag(avx512) + %error use of ``%1'' avx512 instruction in cpuname function: current_function + %elifidn %1, pextrw ; special case because the base instruction is mmx2, + %ifnid %6 ; but sse4 is required for memory operands + %if notcpuflag(sse4) + %error use of ``%1'' sse4 instruction in cpuname function: current_function + %endif + %endif + %endif + %endif + %endif + + %if __emulate_avx + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 && %4 == 0 + %ifnidn %6, %7 + %ifidn %6, %8 + %xdefine __src1 %8 + %xdefine __src2 %7 + %elifnnum sizeof%8 + ; 3-operand AVX instructions with a memory arg can only have it in src2, + ; whereas SSE emulation prefers to have it in src1 (i.e. the mov). + ; So, if the instruction is commutative with a memory arg, swap them. + %xdefine __src1 %8 + %xdefine __src2 %7 + %endif + %endif + %endif + %ifnidn %6, __src1 + %if %0 >= 9 + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, __src2, %9 + %else + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, __src2 + %endif + %if __sizeofreg == 8 + MOVQ %6, __src1 + %elif %3 + MOVAPS %6, __src1 + %else + MOVDQA %6, __src1 + %endif + %endif + %if %0 >= 9 + %1 %6, __src2, %9 + %else + %1 %6, __src2 + %endif + %elif %0 >= 9 + %if avx_enabled && __sizeofreg >= 16 && %4 == 1 + %ifnnum regnumof%7 + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8, %9 + %else + __instr %6, %7, %8, %9 + %endif + %else + __instr %6, %7, %8, %9 + %endif + %elif %0 == 8 + %if avx_enabled && __sizeofreg >= 16 && %4 == 0 + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 + %ifnum regnumof%7 + %ifnum regnumof%8 + %if regnumof%7 < 8 && regnumof%8 >= 8 && regnumof%8 < 16 && sizeof%8 <= 32 + ; Most VEX-encoded instructions require an additional byte to encode when + ; src2 is a high register (e.g. m8..15). If the instruction is commutative + ; we can swap src1 and src2 when doing so reduces the instruction length. + %xdefine __src1 %8 + %xdefine __src2 %7 + %endif + %endif + %elifnum regnumof%8 ; put memory operands in src2 when possible + %xdefine __src1 %8 + %xdefine __src2 %7 + %else + %assign __emulate_avx 1 + %endif + %elifnnum regnumof%7 + ; EVEX allows imm8 shift instructions to be used with memory operands, + ; but VEX does not. This handles those special cases. + %ifnnum %8 + %assign __emulate_avx 1 + %elif notcpuflag(avx512) + %assign __emulate_avx 1 + %endif + %endif + %if __emulate_avx ; a separate load is required + %if %3 + vmovaps %6, %7 + %else + vmovdqa %6, %7 + %endif + __instr %6, %6, %8 + %else + __instr %6, __src1, __src2 + %endif + %else + __instr %6, %7, %8 + %endif + %elif %0 == 7 + %if avx_enabled && __sizeofreg >= 16 && %5 + %xdefine __src1 %6 + %xdefine __src2 %7 + %ifnum regnumof%6 + %ifnum regnumof%7 + %if regnumof%6 < 8 && regnumof%7 >= 8 && regnumof%7 < 16 && sizeof%7 <= 32 + %xdefine __src1 %7 + %xdefine __src2 %6 + %endif + %endif + %endif + __instr %6, __src1, __src2 + %else + __instr %6, %7 + %endif + %else + __instr %6 + %endif +%endmacro + +;%1 == instruction +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +%macro AVX_INSTR 1-5 fnord, 0, 255, 0 + %macro %1 1-10 fnord, fnord, fnord, fnord, %1, %2, %3, %4, %5 + %ifidn %2, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1 + %elifidn %3, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2 + %elifidn %4, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3 + %elifidn %5, fnord + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4 + %else + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4, %5 + %endif + %endmacro +%endmacro + +; Instructions with both VEX/EVEX and legacy encodings +; Non-destructive instructions are written without parameters +AVX_INSTR addpd, sse2, 1, 0, 1 +AVX_INSTR addps, sse, 1, 0, 1 +AVX_INSTR addsd, sse2, 1, 0, 0 +AVX_INSTR addss, sse, 1, 0, 0 +AVX_INSTR addsubpd, sse3, 1, 0, 0 +AVX_INSTR addsubps, sse3, 1, 0, 0 +AVX_INSTR aesdec, aesni, 0, 0, 0 +AVX_INSTR aesdeclast, aesni, 0, 0, 0 +AVX_INSTR aesenc, aesni, 0, 0, 0 +AVX_INSTR aesenclast, aesni, 0, 0, 0 +AVX_INSTR aesimc, aesni +AVX_INSTR aeskeygenassist, aesni +AVX_INSTR andnpd, sse2, 1, 0, 0 +AVX_INSTR andnps, sse, 1, 0, 0 +AVX_INSTR andpd, sse2, 1, 0, 1 +AVX_INSTR andps, sse, 1, 0, 1 +AVX_INSTR blendpd, sse4, 1, 1, 0 +AVX_INSTR blendps, sse4, 1, 1, 0 +AVX_INSTR blendvpd, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR blendvps, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR cmpeqpd, sse2, 1, 0, 1 +AVX_INSTR cmpeqps, sse, 1, 0, 1 +AVX_INSTR cmpeqsd, sse2, 1, 0, 0 +AVX_INSTR cmpeqss, sse, 1, 0, 0 +AVX_INSTR cmplepd, sse2, 1, 0, 0 +AVX_INSTR cmpleps, sse, 1, 0, 0 +AVX_INSTR cmplesd, sse2, 1, 0, 0 +AVX_INSTR cmpless, sse, 1, 0, 0 +AVX_INSTR cmpltpd, sse2, 1, 0, 0 +AVX_INSTR cmpltps, sse, 1, 0, 0 +AVX_INSTR cmpltsd, sse2, 1, 0, 0 +AVX_INSTR cmpltss, sse, 1, 0, 0 +AVX_INSTR cmpneqpd, sse2, 1, 0, 1 +AVX_INSTR cmpneqps, sse, 1, 0, 1 +AVX_INSTR cmpneqsd, sse2, 1, 0, 0 +AVX_INSTR cmpneqss, sse, 1, 0, 0 +AVX_INSTR cmpnlepd, sse2, 1, 0, 0 +AVX_INSTR cmpnleps, sse, 1, 0, 0 +AVX_INSTR cmpnlesd, sse2, 1, 0, 0 +AVX_INSTR cmpnless, sse, 1, 0, 0 +AVX_INSTR cmpnltpd, sse2, 1, 0, 0 +AVX_INSTR cmpnltps, sse, 1, 0, 0 +AVX_INSTR cmpnltsd, sse2, 1, 0, 0 +AVX_INSTR cmpnltss, sse, 1, 0, 0 +AVX_INSTR cmpordpd, sse2 1, 0, 1 +AVX_INSTR cmpordps, sse 1, 0, 1 +AVX_INSTR cmpordsd, sse2 1, 0, 0 +AVX_INSTR cmpordss, sse 1, 0, 0 +AVX_INSTR cmppd, sse2, 1, 1, 0 +AVX_INSTR cmpps, sse, 1, 1, 0 +AVX_INSTR cmpsd, sse2, 1, 1, 0 +AVX_INSTR cmpss, sse, 1, 1, 0 +AVX_INSTR cmpunordpd, sse2, 1, 0, 1 +AVX_INSTR cmpunordps, sse, 1, 0, 1 +AVX_INSTR cmpunordsd, sse2, 1, 0, 0 +AVX_INSTR cmpunordss, sse, 1, 0, 0 +AVX_INSTR comisd, sse2, 1 +AVX_INSTR comiss, sse, 1 +AVX_INSTR cvtdq2pd, sse2, 1 +AVX_INSTR cvtdq2ps, sse2, 1 +AVX_INSTR cvtpd2dq, sse2, 1 +AVX_INSTR cvtpd2ps, sse2, 1 +AVX_INSTR cvtps2dq, sse2, 1 +AVX_INSTR cvtps2pd, sse2, 1 +AVX_INSTR cvtsd2si, sse2, 1 +AVX_INSTR cvtsd2ss, sse2, 1, 0, 0 +AVX_INSTR cvtsi2sd, sse2, 1, 0, 0 +AVX_INSTR cvtsi2ss, sse, 1, 0, 0 +AVX_INSTR cvtss2sd, sse2, 1, 0, 0 +AVX_INSTR cvtss2si, sse, 1 +AVX_INSTR cvttpd2dq, sse2, 1 +AVX_INSTR cvttps2dq, sse2, 1 +AVX_INSTR cvttsd2si, sse2, 1 +AVX_INSTR cvttss2si, sse, 1 +AVX_INSTR divpd, sse2, 1, 0, 0 +AVX_INSTR divps, sse, 1, 0, 0 +AVX_INSTR divsd, sse2, 1, 0, 0 +AVX_INSTR divss, sse, 1, 0, 0 +AVX_INSTR dppd, sse4, 1, 1, 0 +AVX_INSTR dpps, sse4, 1, 1, 0 +AVX_INSTR extractps, sse4, 1 +AVX_INSTR gf2p8affineinvqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8affineqb, gfni, 0, 1, 0 +AVX_INSTR gf2p8mulb, gfni, 0, 0, 0 +AVX_INSTR haddpd, sse3, 1, 0, 0 +AVX_INSTR haddps, sse3, 1, 0, 0 +AVX_INSTR hsubpd, sse3, 1, 0, 0 +AVX_INSTR hsubps, sse3, 1, 0, 0 +AVX_INSTR insertps, sse4, 1, 1, 0 +AVX_INSTR lddqu, sse3 +AVX_INSTR ldmxcsr, sse, 1 +AVX_INSTR maskmovdqu, sse2 +AVX_INSTR maxpd, sse2, 1, 0, 1 +AVX_INSTR maxps, sse, 1, 0, 1 +AVX_INSTR maxsd, sse2, 1, 0, 0 +AVX_INSTR maxss, sse, 1, 0, 0 +AVX_INSTR minpd, sse2, 1, 0, 1 +AVX_INSTR minps, sse, 1, 0, 1 +AVX_INSTR minsd, sse2, 1, 0, 0 +AVX_INSTR minss, sse, 1, 0, 0 +AVX_INSTR movapd, sse2, 1 +AVX_INSTR movaps, sse, 1 +AVX_INSTR movd, mmx +AVX_INSTR movddup, sse3, 1 +AVX_INSTR movdqa, sse2 +AVX_INSTR movdqu, sse2 +AVX_INSTR movhlps, sse, 1, 0, 0 +AVX_INSTR movhpd, sse2, 1, 0, 0 +AVX_INSTR movhps, sse, 1, 0, 0 +AVX_INSTR movlhps, sse, 1, 0, 0 +AVX_INSTR movlpd, sse2, 1, 0, 0 +AVX_INSTR movlps, sse, 1, 0, 0 +AVX_INSTR movmskpd, sse2, 1 +AVX_INSTR movmskps, sse, 1 +AVX_INSTR movntdq, sse2 +AVX_INSTR movntdqa, sse4 +AVX_INSTR movntpd, sse2, 1 +AVX_INSTR movntps, sse, 1 +AVX_INSTR movq, mmx +AVX_INSTR movsd, sse2, 1, 0, 0 +AVX_INSTR movshdup, sse3, 1 +AVX_INSTR movsldup, sse3, 1 +AVX_INSTR movss, sse, 1, 0, 0 +AVX_INSTR movupd, sse2, 1 +AVX_INSTR movups, sse, 1 +AVX_INSTR mpsadbw, sse4, 0, 1, 0 +AVX_INSTR mulpd, sse2, 1, 0, 1 +AVX_INSTR mulps, sse, 1, 0, 1 +AVX_INSTR mulsd, sse2, 1, 0, 0 +AVX_INSTR mulss, sse, 1, 0, 0 +AVX_INSTR orpd, sse2, 1, 0, 1 +AVX_INSTR orps, sse, 1, 0, 1 +AVX_INSTR pabsb, ssse3 +AVX_INSTR pabsd, ssse3 +AVX_INSTR pabsw, ssse3 +AVX_INSTR packssdw, mmx, 0, 0, 0 +AVX_INSTR packsswb, mmx, 0, 0, 0 +AVX_INSTR packusdw, sse4, 0, 0, 0 +AVX_INSTR packuswb, mmx, 0, 0, 0 +AVX_INSTR paddb, mmx, 0, 0, 1 +AVX_INSTR paddd, mmx, 0, 0, 1 +AVX_INSTR paddq, sse2, 0, 0, 1 +AVX_INSTR paddsb, mmx, 0, 0, 1 +AVX_INSTR paddsw, mmx, 0, 0, 1 +AVX_INSTR paddusb, mmx, 0, 0, 1 +AVX_INSTR paddusw, mmx, 0, 0, 1 +AVX_INSTR paddw, mmx, 0, 0, 1 +AVX_INSTR palignr, ssse3, 0, 1, 0 +AVX_INSTR pand, mmx, 0, 0, 1 +AVX_INSTR pandn, mmx, 0, 0, 0 +AVX_INSTR pavgb, mmx2, 0, 0, 1 +AVX_INSTR pavgw, mmx2, 0, 0, 1 +AVX_INSTR pblendvb, sse4, 0, 1, 0 ; last operand must be xmm0 with legacy encoding +AVX_INSTR pblendw, sse4, 0, 1, 0 +AVX_INSTR pclmulhqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmulhqlqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqlqdq, fnord, 0, 0, 0 +AVX_INSTR pclmulqdq, fnord, 0, 1, 0 +AVX_INSTR pcmpeqb, mmx, 0, 0, 1 +AVX_INSTR pcmpeqd, mmx, 0, 0, 1 +AVX_INSTR pcmpeqq, sse4, 0, 0, 1 +AVX_INSTR pcmpeqw, mmx, 0, 0, 1 +AVX_INSTR pcmpestri, sse42 +AVX_INSTR pcmpestrm, sse42 +AVX_INSTR pcmpgtb, mmx, 0, 0, 0 +AVX_INSTR pcmpgtd, mmx, 0, 0, 0 +AVX_INSTR pcmpgtq, sse42, 0, 0, 0 +AVX_INSTR pcmpgtw, mmx, 0, 0, 0 +AVX_INSTR pcmpistri, sse42 +AVX_INSTR pcmpistrm, sse42 +AVX_INSTR pextrb, sse4 +AVX_INSTR pextrd, sse4 +AVX_INSTR pextrq, sse4 +AVX_INSTR pextrw, mmx2 +AVX_INSTR phaddd, ssse3, 0, 0, 0 +AVX_INSTR phaddsw, ssse3, 0, 0, 0 +AVX_INSTR phaddw, ssse3, 0, 0, 0 +AVX_INSTR phminposuw, sse4 +AVX_INSTR phsubd, ssse3, 0, 0, 0 +AVX_INSTR phsubsw, ssse3, 0, 0, 0 +AVX_INSTR phsubw, ssse3, 0, 0, 0 +AVX_INSTR pinsrb, sse4, 0, 1, 0 +AVX_INSTR pinsrd, sse4, 0, 1, 0 +AVX_INSTR pinsrq, sse4, 0, 1, 0 +AVX_INSTR pinsrw, mmx2, 0, 1, 0 +AVX_INSTR pmaddubsw, ssse3, 0, 0, 0 +AVX_INSTR pmaddwd, mmx, 0, 0, 1 +AVX_INSTR pmaxsb, sse4, 0, 0, 1 +AVX_INSTR pmaxsd, sse4, 0, 0, 1 +AVX_INSTR pmaxsw, mmx2, 0, 0, 1 +AVX_INSTR pmaxub, mmx2, 0, 0, 1 +AVX_INSTR pmaxud, sse4, 0, 0, 1 +AVX_INSTR pmaxuw, sse4, 0, 0, 1 +AVX_INSTR pminsb, sse4, 0, 0, 1 +AVX_INSTR pminsd, sse4, 0, 0, 1 +AVX_INSTR pminsw, mmx2, 0, 0, 1 +AVX_INSTR pminub, mmx2, 0, 0, 1 +AVX_INSTR pminud, sse4, 0, 0, 1 +AVX_INSTR pminuw, sse4, 0, 0, 1 +AVX_INSTR pmovmskb, mmx2 +AVX_INSTR pmovsxbd, sse4 +AVX_INSTR pmovsxbq, sse4 +AVX_INSTR pmovsxbw, sse4 +AVX_INSTR pmovsxdq, sse4 +AVX_INSTR pmovsxwd, sse4 +AVX_INSTR pmovsxwq, sse4 +AVX_INSTR pmovzxbd, sse4 +AVX_INSTR pmovzxbq, sse4 +AVX_INSTR pmovzxbw, sse4 +AVX_INSTR pmovzxdq, sse4 +AVX_INSTR pmovzxwd, sse4 +AVX_INSTR pmovzxwq, sse4 +AVX_INSTR pmuldq, sse4, 0, 0, 1 +AVX_INSTR pmulhrsw, ssse3, 0, 0, 1 +AVX_INSTR pmulhuw, mmx2, 0, 0, 1 +AVX_INSTR pmulhw, mmx, 0, 0, 1 +AVX_INSTR pmulld, sse4, 0, 0, 1 +AVX_INSTR pmullw, mmx, 0, 0, 1 +AVX_INSTR pmuludq, sse2, 0, 0, 1 +AVX_INSTR por, mmx, 0, 0, 1 +AVX_INSTR psadbw, mmx2, 0, 0, 1 +AVX_INSTR pshufb, ssse3, 0, 0, 0 +AVX_INSTR pshufd, sse2 +AVX_INSTR pshufhw, sse2 +AVX_INSTR pshuflw, sse2 +AVX_INSTR psignb, ssse3, 0, 0, 0 +AVX_INSTR psignd, ssse3, 0, 0, 0 +AVX_INSTR psignw, ssse3, 0, 0, 0 +AVX_INSTR pslld, mmx, 0, 0, 0 +AVX_INSTR pslldq, sse2, 0, 0, 0 +AVX_INSTR psllq, mmx, 0, 0, 0 +AVX_INSTR psllw, mmx, 0, 0, 0 +AVX_INSTR psrad, mmx, 0, 0, 0 +AVX_INSTR psraw, mmx, 0, 0, 0 +AVX_INSTR psrld, mmx, 0, 0, 0 +AVX_INSTR psrldq, sse2, 0, 0, 0 +AVX_INSTR psrlq, mmx, 0, 0, 0 +AVX_INSTR psrlw, mmx, 0, 0, 0 +AVX_INSTR psubb, mmx, 0, 0, 0 +AVX_INSTR psubd, mmx, 0, 0, 0 +AVX_INSTR psubq, sse2, 0, 0, 0 +AVX_INSTR psubsb, mmx, 0, 0, 0 +AVX_INSTR psubsw, mmx, 0, 0, 0 +AVX_INSTR psubusb, mmx, 0, 0, 0 +AVX_INSTR psubusw, mmx, 0, 0, 0 +AVX_INSTR psubw, mmx, 0, 0, 0 +AVX_INSTR ptest, sse4 +AVX_INSTR punpckhbw, mmx, 0, 0, 0 +AVX_INSTR punpckhdq, mmx, 0, 0, 0 +AVX_INSTR punpckhqdq, sse2, 0, 0, 0 +AVX_INSTR punpckhwd, mmx, 0, 0, 0 +AVX_INSTR punpcklbw, mmx, 0, 0, 0 +AVX_INSTR punpckldq, mmx, 0, 0, 0 +AVX_INSTR punpcklqdq, sse2, 0, 0, 0 +AVX_INSTR punpcklwd, mmx, 0, 0, 0 +AVX_INSTR pxor, mmx, 0, 0, 1 +AVX_INSTR rcpps, sse, 1 +AVX_INSTR rcpss, sse, 1, 0, 0 +AVX_INSTR roundpd, sse4, 1 +AVX_INSTR roundps, sse4, 1 +AVX_INSTR roundsd, sse4, 1, 1, 0 +AVX_INSTR roundss, sse4, 1, 1, 0 +AVX_INSTR rsqrtps, sse, 1 +AVX_INSTR rsqrtss, sse, 1, 0, 0 +AVX_INSTR shufpd, sse2, 1, 1, 0 +AVX_INSTR shufps, sse, 1, 1, 0 +AVX_INSTR sqrtpd, sse2, 1 +AVX_INSTR sqrtps, sse, 1 +AVX_INSTR sqrtsd, sse2, 1, 0, 0 +AVX_INSTR sqrtss, sse, 1, 0, 0 +AVX_INSTR stmxcsr, sse, 1 +AVX_INSTR subpd, sse2, 1, 0, 0 +AVX_INSTR subps, sse, 1, 0, 0 +AVX_INSTR subsd, sse2, 1, 0, 0 +AVX_INSTR subss, sse, 1, 0, 0 +AVX_INSTR ucomisd, sse2, 1 +AVX_INSTR ucomiss, sse, 1 +AVX_INSTR unpckhpd, sse2, 1, 0, 0 +AVX_INSTR unpckhps, sse, 1, 0, 0 +AVX_INSTR unpcklpd, sse2, 1, 0, 0 +AVX_INSTR unpcklps, sse, 1, 0, 0 +AVX_INSTR xorpd, sse2, 1, 0, 1 +AVX_INSTR xorps, sse, 1, 0, 1 + +; 3DNow instructions, for sharing code between AVX, SSE and 3DN +AVX_INSTR pfadd, 3dnow, 1, 0, 1 +AVX_INSTR pfmul, 3dnow, 1, 0, 1 +AVX_INSTR pfsub, 3dnow, 1, 0, 0 + +;%1 == instruction +;%2 == minimal instruction set +%macro GPR_INSTR 2 + %macro %1 2-5 fnord, %1, %2 + %ifdef cpuname + %if notcpuflag(%5) + %error use of ``%4'' %5 instruction in cpuname function: current_function + %endif + %endif + %ifidn %3, fnord + %4 %1, %2 + %else + %4 %1, %2, %3 + %endif + %endmacro +%endmacro + +GPR_INSTR andn, bmi1 +GPR_INSTR bextr, bmi1 +GPR_INSTR blsi, bmi1 +GPR_INSTR blsmsk, bmi1 +GPR_INSTR blsr, bmi1 +GPR_INSTR bzhi, bmi2 +GPR_INSTR mulx, bmi2 +GPR_INSTR pdep, bmi2 +GPR_INSTR pext, bmi2 +GPR_INSTR popcnt, sse42 +GPR_INSTR rorx, bmi2 +GPR_INSTR sarx, bmi2 +GPR_INSTR shlx, bmi2 +GPR_INSTR shrx, bmi2 + +; base-4 constants for shuffles +%assign i 0 +%rep 256 + %assign j ((i>>6)&3)*1000 + ((i>>4)&3)*100 + ((i>>2)&3)*10 + (i&3) + %if j < 10 + CAT_XDEFINE q000, j, i + %elif j < 100 + CAT_XDEFINE q00, j, i + %elif j < 1000 + CAT_XDEFINE q0, j, i + %else + CAT_XDEFINE q, j, i + %endif + %assign i i+1 +%endrep +%undef i +%undef j + +%macro FMA_INSTR 3 + %macro %1 4-7 %1, %2, %3 + %if cpuflag(xop) + v%5 %1, %2, %3, %4 + %elifnidn %1, %4 + %6 %1, %2, %3 + %7 %1, %4 + %else + %error non-xop emulation of ``%5 %1, %2, %3, %4'' is not supported + %endif + %endmacro +%endmacro + +FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation +FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation +FMA_INSTR pmacsww, pmullw, paddw +FMA_INSTR pmadcswd, pmaddwd, paddd + +; Macros for consolidating FMA3 and FMA4 using 4-operand (dst, src1, src2, src3) syntax. +; FMA3 is only possible if dst is the same as one of the src registers. +; Either src2 or src3 can be a memory operand. +%macro FMA4_INSTR 2-* + %push fma4_instr + %xdefine %$prefix %1 + %rep %0 - 1 + %macro %$prefix%2 4-6 %$prefix, %2 + %if notcpuflag(fma3) && notcpuflag(fma4) + %error use of ``%5%6'' fma instruction in cpuname function: current_function + %elif cpuflag(fma4) + v%5%6 %1, %2, %3, %4 + %elifidn %1, %2 + ; If %3 or %4 is a memory operand it needs to be encoded as the last operand. + %ifnum sizeof%3 + v%{5}213%6 %2, %3, %4 + %else + v%{5}132%6 %2, %4, %3 + %endif + %elifidn %1, %3 + v%{5}213%6 %3, %2, %4 + %elifidn %1, %4 + v%{5}231%6 %4, %2, %3 + %else + %error fma3 emulation of ``%5%6 %1, %2, %3, %4'' is not supported + %endif + %endmacro + %rotate 1 + %endrep + %pop +%endmacro + +FMA4_INSTR fmadd, pd, ps, sd, ss +FMA4_INSTR fmaddsub, pd, ps +FMA4_INSTR fmsub, pd, ps, sd, ss +FMA4_INSTR fmsubadd, pd, ps +FMA4_INSTR fnmadd, pd, ps, sd, ss +FMA4_INSTR fnmsub, pd, ps, sd, ss + +; Macros for converting VEX instructions to equivalent EVEX ones. +%macro EVEX_INSTR 2-3 0 ; vex, evex, prefer_evex + %macro %1 2-7 fnord, fnord, %1, %2, %3 + %ifidn %3, fnord + %define %%args %1, %2 + %elifidn %4, fnord + %define %%args %1, %2, %3 + %else + %define %%args %1, %2, %3, %4 + %endif + %assign %%evex_required cpuflag(avx512) & %7 + %ifnum regnumof%1 + %if regnumof%1 >= 16 || sizeof%1 > 32 + %assign %%evex_required 1 + %endif + %endif + %ifnum regnumof%2 + %if regnumof%2 >= 16 || sizeof%2 > 32 + %assign %%evex_required 1 + %endif + %endif + %ifnum regnumof%3 + %if regnumof%3 >= 16 || sizeof%3 > 32 + %assign %%evex_required 1 + %endif + %endif + %if %%evex_required + %6 %%args + %else + %5 %%args ; Prefer VEX over EVEX due to shorter instruction length + %endif + %endmacro +%endmacro + +EVEX_INSTR vbroadcastf128, vbroadcastf32x4 +EVEX_INSTR vbroadcasti128, vbroadcasti32x4 +EVEX_INSTR vextractf128, vextractf32x4 +EVEX_INSTR vextracti128, vextracti32x4 +EVEX_INSTR vinsertf128, vinsertf32x4 +EVEX_INSTR vinserti128, vinserti32x4 +EVEX_INSTR vmovdqa, vmovdqa32 +EVEX_INSTR vmovdqu, vmovdqu32 +EVEX_INSTR vpand, vpandd +EVEX_INSTR vpandn, vpandnd +EVEX_INSTR vpor, vpord +EVEX_INSTR vpxor, vpxord +EVEX_INSTR vrcpps, vrcp14ps, 1 ; EVEX versions have higher precision +EVEX_INSTR vrcpss, vrcp14ss, 1 +EVEX_INSTR vrsqrtps, vrsqrt14ps, 1 +EVEX_INSTR vrsqrtss, vrsqrt14ss, 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/frame/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/frame/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,104 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use num_derive::FromPrimitive; + +use crate::api::{Opaque, T35}; +use crate::context::SB_SIZE; +use crate::mc::SUBPEL_FILTER_SIZE; +use crate::util::*; + +use crate::tiling::*; + +mod plane; +pub use plane::*; + +const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE; +const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN; + +/// Override the frame type decision +/// +/// Only certain frame types can be selected. +#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, Default)] +#[repr(C)] +pub enum FrameTypeOverride { + /// Do not force any decision. + #[default] + No, + /// Force the frame to be a Keyframe. + Key, +} + +/// Optional per-frame encoder parameters +#[derive(Debug, Default)] +pub struct FrameParameters { + /// Force emitted frame to be of the type selected + pub frame_type_override: FrameTypeOverride, + /// Output the provided data in the matching encoded Packet + pub opaque: Option, + /// List of t35 metadata associated with this frame + pub t35_metadata: Box<[T35]>, +} + +pub use v_frame::frame::Frame; + +/// Public Trait Interface for Frame Allocation +pub(crate) trait FrameAlloc { + /// Initialise new frame default type + fn new(width: usize, height: usize, chroma_sampling: ChromaSampling) + -> Self; +} + +impl FrameAlloc for Frame { + /// Creates a new frame with the given parameters. + /// new function calls `new_with_padding` function which takes `luma_padding` + /// as parameter + fn new( + width: usize, height: usize, chroma_sampling: ChromaSampling, + ) -> Self { + v_frame::frame::Frame::new_with_padding( + width, + height, + chroma_sampling, + LUMA_PADDING, + ) + } +} + +/// Public Trait for calculating Padding +pub(crate) trait FramePad { + fn pad(&mut self, w: usize, h: usize, planes: usize); +} + +impl FramePad for Frame { + fn pad(&mut self, w: usize, h: usize, planes: usize) { + for pli in 0..planes { + self.planes[pli].pad(w, h); + } + } +} + +/// Public Trait for new Tile of a frame +pub(crate) trait AsTile { + fn as_tile(&self) -> Tile<'_, T>; + fn as_tile_mut(&mut self) -> TileMut<'_, T>; +} + +impl AsTile for Frame { + #[inline(always)] + fn as_tile(&self) -> Tile<'_, T> { + let PlaneConfig { width, height, .. } = self.planes[0].cfg; + Tile::new(self, TileRect { x: 0, y: 0, width, height }) + } + #[inline(always)] + fn as_tile_mut(&mut self) -> TileMut<'_, T> { + let PlaneConfig { width, height, .. } = self.planes[0].cfg; + TileMut::new(self, TileRect { x: 0, y: 0, width, height }) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/frame/plane.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/plane.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/frame/plane.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/frame/plane.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,54 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::tiling::*; +use crate::util::*; + +pub use v_frame::plane::*; + +pub trait AsRegion { + fn as_region(&self) -> PlaneRegion<'_, T>; + fn as_region_mut(&mut self) -> PlaneRegionMut<'_, T>; + fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T>; + fn region(&self, area: Area) -> PlaneRegion<'_, T>; +} + +impl AsRegion for Plane { + #[inline(always)] + fn region(&self, area: Area) -> PlaneRegion<'_, T> { + let rect = area.to_rect( + self.cfg.xdec, + self.cfg.ydec, + self.cfg.stride - self.cfg.xorigin, + self.cfg.alloc_height - self.cfg.yorigin, + ); + PlaneRegion::new(self, rect) + } + + #[inline(always)] + fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T> { + let rect = area.to_rect( + self.cfg.xdec, + self.cfg.ydec, + self.cfg.stride - self.cfg.xorigin, + self.cfg.alloc_height - self.cfg.yorigin, + ); + PlaneRegionMut::new(self, rect) + } + + #[inline(always)] + fn as_region(&self) -> PlaneRegion<'_, T> { + PlaneRegion::new_from_plane(self) + } + + #[inline(always)] + fn as_region_mut(&mut self) -> PlaneRegionMut<'_, T> { + PlaneRegionMut::new_from_plane(self) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/fuzzing.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/fuzzing.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/fuzzing.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/fuzzing.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,384 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::marker::PhantomData; +use std::sync::Arc; + +use libfuzzer_sys::arbitrary::{Arbitrary, Error, Unstructured}; + +use crate::prelude::*; + +// Adding new fuzz targets +// +// 1. Add a function to this file which looks like this: +// +// pub fn fuzz_something(data: Data) { +// // Invoke everything you need. +// // +// // Your function may accept a value of any type that implements +// // Arbitrary [1]. This is how fuzzer affects the execution—by +// // feeding in different bytes, which result in different +// // arbitrary values being generated. +// // [1]: https://docs.rs/arbitrary/0.3.3/arbitrary/trait.Arbitrary.html +// // +// // Derive Debug for the structures you create with arbitrary data. +// } +// +// 2. cargo fuzz add something +// 3. Copy the contents of any other .rs file from fuzz/fuzz_targets/ into the +// newly created fuzz/fuzz_targets/something.rs and change the function +// being called to fuzz_something. +// +// Now you can fuzz the new target with cargo fuzz. + +#[derive(Debug)] +pub struct ArbitraryConfig { + config: Config, +} + +#[inline] +fn arbitrary_rational(u: &mut Unstructured<'_>) -> Result { + Ok(Rational::new(Arbitrary::arbitrary(u)?, Arbitrary::arbitrary(u)?)) +} + +#[inline] +fn arbitrary_color_description( + u: &mut Unstructured<'_>, +) -> Result, Error> { + if Arbitrary::arbitrary(u)? { + return Ok(None); + } + Ok(Some(ColorDescription { + color_primaries: *u.choose(&[ + ColorPrimaries::BT709, + ColorPrimaries::Unspecified, + ColorPrimaries::BT470M, + ColorPrimaries::BT470BG, + ColorPrimaries::BT601, + ColorPrimaries::SMPTE240, + ColorPrimaries::GenericFilm, + ColorPrimaries::BT2020, + ColorPrimaries::XYZ, + ColorPrimaries::SMPTE431, + ColorPrimaries::SMPTE432, + ColorPrimaries::EBU3213, + ])?, + transfer_characteristics: *u.choose(&[ + TransferCharacteristics::BT709, + TransferCharacteristics::Unspecified, + TransferCharacteristics::BT470M, + TransferCharacteristics::BT470BG, + TransferCharacteristics::BT601, + TransferCharacteristics::SMPTE240, + TransferCharacteristics::Linear, + TransferCharacteristics::Log100, + TransferCharacteristics::Log100Sqrt10, + TransferCharacteristics::IEC61966, + TransferCharacteristics::BT1361, + TransferCharacteristics::SRGB, + TransferCharacteristics::BT2020_10Bit, + TransferCharacteristics::BT2020_12Bit, + TransferCharacteristics::SMPTE2084, + TransferCharacteristics::SMPTE428, + TransferCharacteristics::HLG, + ])?, + matrix_coefficients: *u.choose(&[ + MatrixCoefficients::Identity, + MatrixCoefficients::BT709, + MatrixCoefficients::Unspecified, + MatrixCoefficients::FCC, + MatrixCoefficients::BT470BG, + MatrixCoefficients::BT601, + MatrixCoefficients::SMPTE240, + MatrixCoefficients::YCgCo, + MatrixCoefficients::BT2020NCL, + MatrixCoefficients::BT2020CL, + MatrixCoefficients::SMPTE2085, + MatrixCoefficients::ChromatNCL, + MatrixCoefficients::ChromatCL, + MatrixCoefficients::ICtCp, + ])?, + })) +} + +#[inline] +fn arbitrary_chromacity_point( + u: &mut Unstructured<'_>, +) -> Result { + Ok(ChromaticityPoint { + x: Arbitrary::arbitrary(u)?, + y: Arbitrary::arbitrary(u)?, + }) +} + +#[inline] +fn arbitrary_mastering_display( + u: &mut Unstructured<'_>, +) -> Result, Error> { + if Arbitrary::arbitrary(u)? { + return Ok(None); + } + Ok(Some(MasteringDisplay { + primaries: [ + arbitrary_chromacity_point(u)?, + arbitrary_chromacity_point(u)?, + arbitrary_chromacity_point(u)?, + ], + white_point: arbitrary_chromacity_point(u)?, + max_luminance: Arbitrary::arbitrary(u)?, + min_luminance: Arbitrary::arbitrary(u)?, + })) +} + +#[inline] +fn arbitrary_content_light( + u: &mut Unstructured<'_>, +) -> Result, Error> { + if Arbitrary::arbitrary(u)? { + return Ok(None); + } + Ok(Some(ContentLight { + max_content_light_level: Arbitrary::arbitrary(u)?, + max_frame_average_light_level: Arbitrary::arbitrary(u)?, + })) +} + +impl Arbitrary<'_> for ArbitraryConfig { + fn arbitrary(u: &mut Unstructured<'_>) -> Result { + let mut enc = EncoderConfig::with_speed_preset(Arbitrary::arbitrary(u)?); + enc.width = Arbitrary::arbitrary(u)?; + enc.height = Arbitrary::arbitrary(u)?; + enc.bit_depth = u.int_in_range(0..=16)?; + enc.still_picture = Arbitrary::arbitrary(u)?; + enc.time_base = arbitrary_rational(u)?; + enc.min_key_frame_interval = Arbitrary::arbitrary(u)?; + enc.max_key_frame_interval = Arbitrary::arbitrary(u)?; + enc.reservoir_frame_delay = Arbitrary::arbitrary(u)?; + enc.low_latency = Arbitrary::arbitrary(u)?; + enc.quantizer = Arbitrary::arbitrary(u)?; + enc.min_quantizer = Arbitrary::arbitrary(u)?; + enc.bitrate = Arbitrary::arbitrary(u)?; + enc.tile_cols = Arbitrary::arbitrary(u)?; + enc.tile_rows = Arbitrary::arbitrary(u)?; + enc.tiles = Arbitrary::arbitrary(u)?; + enc.speed_settings.rdo_lookahead_frames = Arbitrary::arbitrary(u)?; + let config = Config::new().with_encoder_config(enc).with_threads(1); + Ok(Self { config }) + } +} + +pub fn fuzz_construct_context(arbitrary: ArbitraryConfig) { + let _: Result, _> = arbitrary.config.new_context(); +} + +fn encode_frames( + ctx: &mut Context, mut frames: impl Iterator>, +) -> Result<(), EncoderStatus> { + loop { + let rv = ctx.receive_packet(); + log::debug!("ctx.receive_packet() = {:#?}", rv); + + match rv { + Ok(_packet) => {} + Err(EncoderStatus::Encoded) => {} + Err(EncoderStatus::LimitReached) => { + break; + } + Err(EncoderStatus::NeedMoreData) => { + ctx.send_frame(frames.next().map(Arc::new))?; + } + Err(EncoderStatus::EnoughData) => { + unreachable!(); + } + Err(EncoderStatus::NotReady) => { + unreachable!(); + } + Err(EncoderStatus::Failure) => { + return Err(EncoderStatus::Failure); + } + } + } + + Ok(()) +} + +#[derive(Debug)] +pub struct ArbitraryEncoder { + config: Config, + frame_count: u8, + pixels: Box<[u8]>, +} + +impl Arbitrary<'_> for ArbitraryEncoder { + fn arbitrary(u: &mut Unstructured<'_>) -> Result { + let enc = EncoderConfig { + speed_settings: SpeedSettings::from_preset(u.int_in_range(0..=10)?), + width: u.int_in_range(1..=256)?, + height: u.int_in_range(1..=256)?, + still_picture: Arbitrary::arbitrary(u)?, + time_base: arbitrary_rational(u)?, + min_key_frame_interval: u.int_in_range(0..=3)?, + max_key_frame_interval: u.int_in_range(1..=4)?, + low_latency: Arbitrary::arbitrary(u)?, + quantizer: Arbitrary::arbitrary(u)?, + min_quantizer: Arbitrary::arbitrary(u)?, + bitrate: Arbitrary::arbitrary(u)?, + tile_cols: u.int_in_range(0..=2)?, + tile_rows: u.int_in_range(0..=2)?, + tiles: u.int_in_range(0..=16)?, + + chroma_sampling: *u.choose(&[ + ChromaSampling::Cs420, + ChromaSampling::Cs422, + ChromaSampling::Cs444, + ChromaSampling::Cs400, + ])?, + chroma_sample_position: *u.choose(&[ + ChromaSamplePosition::Unknown, + ChromaSamplePosition::Vertical, + ChromaSamplePosition::Colocated, + ])?, + pixel_range: *u.choose(&[PixelRange::Limited, PixelRange::Full])?, + error_resilient: Arbitrary::arbitrary(u)?, + reservoir_frame_delay: Arbitrary::arbitrary(u)?, + + sample_aspect_ratio: arbitrary_rational(u)?, + bit_depth: 8, + color_description: arbitrary_color_description(u)?, + mastering_display: arbitrary_mastering_display(u)?, + content_light: arbitrary_content_light(u)?, + level_idx: Some(31), + enable_timing_info: Arbitrary::arbitrary(u)?, + switch_frame_interval: u.int_in_range(0..=3)?, + tune: *u.choose(&[Tune::Psnr, Tune::Psychovisual])?, + film_grain_params: None, + }; + + let frame_count = + if enc.still_picture { 1 } else { u.int_in_range(1..=3)? }; + if u.is_empty() { + return Err(Error::NotEnoughData); + } + let pixels = u.bytes(u.len())?.to_vec().into_boxed_slice(); + let config = Config::new().with_encoder_config(enc).with_threads(1); + Ok(Self { config, frame_count, pixels }) + } +} + +pub fn fuzz_encode(arbitrary: ArbitraryEncoder) { + let res = arbitrary.config.new_context(); + if res.is_err() { + return; + } + let mut context: Context = res.unwrap(); + + let mut pixels = arbitrary.pixels.iter().cycle(); + let mut frame = context.new_frame(); + let frames = (0..arbitrary.frame_count).map(|_| { + for plane in &mut frame.planes { + let stride = plane.cfg.stride; + for row in plane.data_origin_mut().chunks_mut(stride) { + for pixel in row { + *pixel = *pixels.next().unwrap(); + } + } + } + + frame.clone() + }); + + let _ = encode_frames(&mut context, frames); +} + +#[derive(Debug)] +pub struct DecodeTestParameters { + w: usize, + h: usize, + speed: u8, + q: usize, + limit: usize, + bit_depth: usize, + chroma_sampling: ChromaSampling, + min_keyint: u64, + max_keyint: u64, + switch_frame_interval: u64, + low_latency: bool, + error_resilient: bool, + bitrate: i32, + tile_cols_log2: usize, + tile_rows_log2: usize, + still_picture: bool, + pixel: PhantomData, +} + +impl Arbitrary<'_> for DecodeTestParameters { + fn arbitrary(u: &mut Unstructured<'_>) -> Result { + let mut p = Self { + w: u.int_in_range(16..=16 + 255)?, + h: u.int_in_range(16..=16 + 255)?, + speed: u.int_in_range(0..=10)?, + q: u8::arbitrary(u)?.into(), + limit: u.int_in_range(1..=3)?, + bit_depth: 8, + chroma_sampling: *u.choose(&[ + ChromaSampling::Cs420, + ChromaSampling::Cs422, + ChromaSampling::Cs444, + ChromaSampling::Cs400, + ])?, + min_keyint: u.int_in_range(0..=3)?, + max_keyint: u.int_in_range(1..=4)?, + switch_frame_interval: u.int_in_range(0..=3)?, + low_latency: bool::arbitrary(u)?, + error_resilient: bool::arbitrary(u)?, + bitrate: u16::arbitrary(u)?.into(), + tile_cols_log2: u.int_in_range(0..=2)?, + tile_rows_log2: u.int_in_range(0..=2)?, + still_picture: bool::arbitrary(u)?, + pixel: PhantomData, + }; + if matches!(T::type_enum(), PixelType::U16) { + p.bit_depth = *u.choose(&[8, 10, 12])?; + } + if !p.low_latency { + p.switch_frame_interval = 0; + } + if p.still_picture { + p.limit = 1 + } + Ok(p) + } +} + +#[cfg(feature = "decode_test_dav1d")] +pub fn fuzz_encode_decode(p: DecodeTestParameters) { + use crate::test_encode_decode::*; + + let mut dec = get_decoder::("dav1d", p.w, p.h); + dec.encode_decode( + true, + p.w, + p.h, + p.speed, + p.q, + p.limit, + p.bit_depth, + p.chroma_sampling, + p.min_keyint, + p.max_keyint, + p.switch_frame_interval, + p.low_latency, + p.error_resilient, + p.bitrate, + p.tile_cols_log2, + p.tile_rows_log2, + p.still_picture, + None, + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/header.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/header.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/header.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/header.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1244 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::api::*; +use crate::context::*; +use crate::ec::*; +use crate::lrf::*; +use crate::partition::*; +use crate::tiling::MAX_TILE_WIDTH; +use crate::util::Fixed; +use crate::util::Pixel; + +use crate::DeblockState; +use crate::FrameInvariants; +use crate::FrameState; +use crate::SegmentationState; +use crate::Sequence; + +use arrayvec::ArrayVec; +use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; + +use std::io; + +pub const PRIMARY_REF_NONE: u32 = 7; +pub const ALL_REF_FRAMES_MASK: u32 = (1 << REF_FRAMES) - 1; + +const PRIMARY_REF_BITS: u32 = 3; + +#[allow(unused)] +const OP_POINTS_IDC_BITS: usize = 12; +#[allow(unused)] +const LEVEL_MAJOR_MIN: usize = 2; +#[allow(unused)] +const LEVEL_MAJOR_BITS: usize = 3; +#[allow(unused)] +const LEVEL_MINOR_BITS: usize = 2; +#[allow(unused)] +const LEVEL_BITS: usize = LEVEL_MAJOR_BITS + LEVEL_MINOR_BITS; + +#[allow(dead_code, non_camel_case_types)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ReferenceMode { + SINGLE = 0, + COMPOUND = 1, + SELECT = 2, +} + +#[allow(non_camel_case_types)] +#[allow(unused)] +pub enum ObuType { + OBU_SEQUENCE_HEADER = 1, + OBU_TEMPORAL_DELIMITER = 2, + OBU_FRAME_HEADER = 3, + OBU_TILE_GROUP = 4, + OBU_METADATA = 5, + OBU_FRAME = 6, + OBU_REDUNDANT_FRAME_HEADER = 7, + OBU_TILE_LIST = 8, + OBU_PADDING = 15, +} + +#[derive(Clone, Copy)] +#[allow(non_camel_case_types)] +#[allow(unused)] +pub enum ObuMetaType { + OBU_META_HDR_CLL = 1, + OBU_META_HDR_MDCV = 2, + OBU_META_SCALABILITY = 3, + OBU_META_ITUT_T35 = 4, + OBU_META_TIMECODE = 5, +} + +impl ObuMetaType { + const fn size(self) -> u64 { + use self::ObuMetaType::*; + match self { + OBU_META_HDR_CLL => 4, + OBU_META_HDR_MDCV => 24, + _ => 0, + } + } +} + +pub trait ULEB128Writer { + fn write_uleb128(&mut self, payload: u64) -> io::Result<()>; +} + +impl ULEB128Writer for BitWriter { + fn write_uleb128(&mut self, payload: u64) -> io::Result<()> { + // NOTE from libaom: + // Disallow values larger than 32-bits to ensure consistent behavior on 32 and + // 64 bit targets: value is typically used to determine buffer allocation size + // when decoded. + let mut coded_value: ArrayVec = ArrayVec::new(); + + let mut value = payload as u32; + loop { + let mut byte = (value & 0x7f) as u8; + value >>= 7u8; + if value != 0 { + // Signal that more bytes follow. + byte |= 0x80; + } + coded_value.push(byte); + + if value == 0 { + // We have to break at the end of the loop + // because there must be at least one byte written. + break; + } + } + + self.write_bytes(&coded_value)?; + + Ok(()) + } +} + +pub trait LEWriter { + fn write_le(&mut self, bytes: u32, payload: u64) -> io::Result<()>; +} + +// to write little endian values in a globally big-endian BitWriter +impl LEWriter for BitWriter { + fn write_le(&mut self, bytes: u32, value: u64) -> io::Result<()> { + let mut data = Vec::new(); + let mut bwle = BitWriter::endian(&mut data, LittleEndian); + bwle.write_var(bytes * 8, value)?; + self.write_bytes(&data) + } +} + +pub trait UncompressedHeader { + // Start of OBU Headers + fn write_obu_header( + &mut self, obu_type: ObuType, obu_extension: u32, + ) -> io::Result<()>; + fn write_sequence_metadata_obu( + &mut self, obu_meta_type: ObuMetaType, seq: &Sequence, + ) -> io::Result<()>; + fn write_sequence_header_obu( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_frame_header_obu( + &mut self, fi: &FrameInvariants, fs: &FrameState, + inter_cfg: &InterConfig, + ) -> io::Result<()>; + fn write_sequence_header( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()>; + fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()>; + // End of OBU Headers + + fn write_max_frame_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_frame_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_render_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_frame_size_with_refs( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_deblock_filter_a( + &mut self, fi: &FrameInvariants, deblock: &DeblockState, + ) -> io::Result<()>; + fn write_deblock_filter_b( + &mut self, fi: &FrameInvariants, deblock: &DeblockState, + ) -> io::Result<()>; + fn write_frame_cdef( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()>; + fn write_frame_lrf( + &mut self, fi: &FrameInvariants, rs: &RestorationState, + ) -> io::Result<()>; + fn write_segment_data( + &mut self, fi: &FrameInvariants, segmentation: &SegmentationState, + ) -> io::Result<()>; + fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()>; +} + +impl UncompressedHeader for BitWriter { + // Start of OBU Headers + // Write OBU Header syntax + fn write_obu_header( + &mut self, obu_type: ObuType, obu_extension: u32, + ) -> io::Result<()> { + self.write_bit(false)?; // forbidden bit. + self.write::<4, u8>(obu_type as u8)?; + self.write_bit(obu_extension != 0)?; + self.write_bit(true)?; // obu_has_payload_length_field + self.write_bit(false)?; // reserved + + if obu_extension != 0 { + unimplemented!(); + //self.write(8, obu_extension & 0xFF)?; size += 8; + } + + Ok(()) + } + + fn write_sequence_metadata_obu( + &mut self, obu_meta_type: ObuMetaType, seq: &Sequence, + ) -> io::Result<()> { + // header + self.write_obu_header(ObuType::OBU_METADATA, 0)?; + + // uleb128() - length + // we use a constant value to avoid computing the OBU size every time + // since it is fixed (depending on the metadata) + // +2 is for the metadata_type field and the trailing bits byte + self.write_uleb128(obu_meta_type.size() + 2)?; + + // uleb128() - metadata_type (1 byte) + self.write_uleb128(obu_meta_type as u64)?; + + match obu_meta_type { + ObuMetaType::OBU_META_HDR_CLL => { + let cll = seq.content_light.unwrap(); + self.write::<16, u16>(cll.max_content_light_level)?; + self.write::<16, u16>(cll.max_frame_average_light_level)?; + } + ObuMetaType::OBU_META_HDR_MDCV => { + let mdcv = seq.mastering_display.unwrap(); + for i in 0..3 { + self.write::<16, u16>(mdcv.primaries[i].x)?; + self.write::<16, u16>(mdcv.primaries[i].y)?; + } + + self.write::<16, u16>(mdcv.white_point.x)?; + self.write::<16, u16>(mdcv.white_point.y)?; + + self.write::<32, u32>(mdcv.max_luminance)?; + self.write::<32, u32>(mdcv.min_luminance)?; + } + _ => {} + } + + // trailing bits (1 byte) + self.write_bit(true)?; + self.byte_align()?; + + Ok(()) + } + + fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()> { + self.write_obu_header(ObuType::OBU_METADATA, 0)?; + + // metadata type + country code + optional extension + trailing bits + self.write_uleb128( + t35.data.len() as u64 + if t35.country_code == 0xFF { 4 } else { 3 }, + )?; + + self.write_uleb128(ObuMetaType::OBU_META_ITUT_T35 as u64)?; + + self.write::<8, u8>(t35.country_code)?; + if t35.country_code == 0xFF { + self.write::<8, u8>(t35.country_code_extension_byte)?; + } + self.write_bytes(&t35.data)?; + + // trailing bits (1 byte) + self.write_bit(true)?; + self.byte_align()?; + + Ok(()) + } + + fn write_sequence_header_obu( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + assert!( + !fi.sequence.reduced_still_picture_hdr || fi.sequence.still_picture + ); + + self.write::<3, u8>(fi.sequence.profile)?; // profile + self.write_bit(fi.sequence.still_picture)?; // still_picture + self.write_bit(fi.sequence.reduced_still_picture_hdr)?; // reduced_still_picture_header + + assert!(fi.sequence.level_idx[0] <= 31); + if fi.sequence.reduced_still_picture_hdr { + assert!(!fi.sequence.timing_info_present); + assert!(!fi.sequence.decoder_model_info_present_flag); + assert_eq!(fi.sequence.operating_points_cnt_minus_1, 0); + assert_eq!(fi.sequence.operating_point_idc[0], 0); + self.write::<5, u8>(fi.sequence.level_idx[0])?; // level + assert_eq!(fi.sequence.tier[0], 0); + } else { + self.write_bit(fi.sequence.timing_info_present)?; // timing info present + + if fi.sequence.timing_info_present { + self.write::<32, u64>(fi.sequence.time_base.num)?; + self.write::<32, u64>(fi.sequence.time_base.den)?; + + self.write_bit(true)?; // equal picture interval + self.write_bit(true)?; // zero interval + self.write_bit(false)?; // decoder model info present flag + } + + self.write_bit(false)?; // initial display delay present flag + self.write::<5, u8>(0)?; // one operating point + self.write::<12, u16>(0)?; // idc + self.write::<5, u8>(fi.sequence.level_idx[0])?; // level + if fi.sequence.level_idx[0] > 7 { + self.write::<1, u8>(0)?; // tier + } + } + + self.write_sequence_header(fi)?; + + self.write_color_config(&fi.sequence)?; + + self.write_bit(fi.sequence.film_grain_params_present)?; + + Ok(()) + } + + fn write_sequence_header( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + self.write_max_frame_size(fi)?; + + let seq = &fi.sequence; + + if seq.reduced_still_picture_hdr { + assert!(!seq.frame_id_numbers_present_flag); + } else { + self.write_bit(seq.frame_id_numbers_present_flag)?; + } + + if seq.frame_id_numbers_present_flag { + // We must always have delta_frame_id_length < frame_id_length, + // in order for a frame to be referenced with a unique delta. + // Avoid wasting bits by using a coding that enforces this restriction. + self.write::<4, u32>(seq.delta_frame_id_length - 2)?; + self.write::<3, u32>( + seq.frame_id_length - seq.delta_frame_id_length - 1, + )?; + } + + self.write_bit(seq.use_128x128_superblock)?; + self.write_bit(seq.enable_filter_intra)?; + self.write_bit(seq.enable_intra_edge_filter)?; + + if seq.reduced_still_picture_hdr { + assert!(!seq.enable_interintra_compound); + assert!(!seq.enable_masked_compound); + assert!(!seq.enable_warped_motion); + assert!(!seq.enable_dual_filter); + assert!(!seq.enable_order_hint); + assert!(!seq.enable_jnt_comp); + assert!(!seq.enable_ref_frame_mvs); + assert!(seq.force_screen_content_tools == 2); + assert!(seq.force_integer_mv == 2); + } else { + self.write_bit(seq.enable_interintra_compound)?; + self.write_bit(seq.enable_masked_compound)?; + self.write_bit(seq.enable_warped_motion)?; + self.write_bit(seq.enable_dual_filter)?; + self.write_bit(seq.enable_order_hint)?; + + if seq.enable_order_hint { + self.write_bit(seq.enable_jnt_comp)?; + self.write_bit(seq.enable_ref_frame_mvs)?; + } + + if seq.force_screen_content_tools == 2 { + self.write_bit(true)?; + } else { + self.write_bit(false)?; + self.write_bit(seq.force_screen_content_tools != 0)?; + } + if seq.force_screen_content_tools > 0 { + if seq.force_integer_mv == 2 { + self.write_bit(true)?; + } else { + self.write_bit(false)?; + self.write_bit(seq.force_integer_mv != 0)?; + } + } else { + assert!(seq.force_integer_mv == 2); + } + if seq.enable_order_hint { + self.write::<3, u32>(seq.order_hint_bits_minus_1)?; + } + } + + self.write_bit(seq.enable_superres)?; + self.write_bit(seq.enable_cdef)?; + self.write_bit(seq.enable_restoration)?; + + Ok(()) + } + + // + fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()> { + let high_bitdepth = seq.bit_depth > 8; + self.write_bit(high_bitdepth)?; + if seq.profile == 2 && high_bitdepth { + self.write_bit(seq.bit_depth == 12)?; // twelve_bit + } + + let monochrome = seq.chroma_sampling == ChromaSampling::Cs400; + if seq.profile == 1 { + assert!(!monochrome); + } else { + self.write_bit(monochrome)?; // mono_chrome + } + + // color_description_present_flag + self.write_bit(seq.color_description.is_some())?; + let mut srgb_triple = false; + if let Some(color_description) = seq.color_description { + self.write::<8, _>(color_description.color_primaries as u8)?; + self.write::<8, _>(color_description.transfer_characteristics as u8)?; + self.write::<8, _>(color_description.matrix_coefficients as u8)?; + srgb_triple = color_description.is_srgb_triple(); + } + + if monochrome || !srgb_triple { + self.write_bit(seq.pixel_range == PixelRange::Full)?; // color_range + } + if monochrome { + return Ok(()); + } else if srgb_triple { + assert!(seq.pixel_range == PixelRange::Full); + assert!(seq.chroma_sampling == ChromaSampling::Cs444); + } else { + if seq.profile == 0 { + assert!(seq.chroma_sampling == ChromaSampling::Cs420); + } else if seq.profile == 1 { + assert!(seq.chroma_sampling == ChromaSampling::Cs444); + } else if seq.bit_depth == 12 { + let subsampling_x = seq.chroma_sampling != ChromaSampling::Cs444; + let subsampling_y = seq.chroma_sampling == ChromaSampling::Cs420; + self.write_bit(subsampling_x)?; + if subsampling_x { + self.write_bit(subsampling_y)?; + } + } else { + assert!(seq.chroma_sampling == ChromaSampling::Cs422); + } + if seq.chroma_sampling == ChromaSampling::Cs420 { + self.write::<2, u8>(seq.chroma_sample_position as u8)?; + } + } + self.write_bit(true)?; // separate_uv_delta_q + + Ok(()) + } + + #[allow(unused)] + fn write_frame_header_obu( + &mut self, fi: &FrameInvariants, fs: &FrameState, + inter_cfg: &InterConfig, + ) -> io::Result<()> { + if fi.sequence.reduced_still_picture_hdr { + assert!(!fi.is_show_existing_frame()); + assert!(fi.frame_type == FrameType::KEY); + assert!(fi.show_frame); + assert!(!fi.showable_frame); + } else { + self.write_bit(fi.is_show_existing_frame())?; + + if fi.is_show_existing_frame() { + self.write::<3, u32>(fi.frame_to_show_map_idx)?; + + //TODO: + /* temporal_point_info(); + if fi.sequence.decoder_model_info_present_flag && + timing_info.equal_picture_interval == 0 { + // write frame_presentation_delay; + } + if fi.sequence.frame_id_numbers_present_flag { + // write display_frame_id; + }*/ + + self.write_bit(true)?; // trailing bit + self.byte_align()?; + return Ok(()); + } + + self.write::<2, u8>(fi.frame_type as u8)?; + self.write_bit(fi.show_frame)?; // show frame + + if fi.show_frame { + //TODO: + /* temporal_point_info(); + if fi.sequence.decoder_model_info_present_flag && + timing_info.equal_picture_interval == 0 { + // write frame_presentation_delay; + }*/ + } else { + self.write_bit(fi.showable_frame)?; + } + + if fi.error_resilient { + assert!(fi.primary_ref_frame == PRIMARY_REF_NONE); + } + if fi.frame_type == FrameType::SWITCH { + assert!(fi.error_resilient); + } else if !(fi.frame_type == FrameType::KEY && fi.show_frame) { + self.write_bit(fi.error_resilient)?; // error resilient + } + } + + self.write_bit(fi.disable_cdf_update)?; + + if fi.sequence.force_screen_content_tools == 2 { + self.write_bit(fi.allow_screen_content_tools != 0)?; + } else { + assert!( + fi.allow_screen_content_tools + == fi.sequence.force_screen_content_tools + ); + } + + if fi.allow_screen_content_tools > 0 { + if fi.sequence.force_integer_mv == 2 { + self.write_bit(fi.force_integer_mv != 0)?; + } else { + assert!(fi.force_integer_mv == fi.sequence.force_integer_mv); + } + } + + assert!( + fi.force_integer_mv + == u32::from(fi.frame_type == FrameType::KEY || fi.intra_only) + ); + + if fi.sequence.frame_id_numbers_present_flag { + unimplemented!(); + + //TODO: + //let frame_id_len = fi.sequence.frame_id_length; + //self.write(frame_id_len, fi.current_frame_id); + } + + if fi.frame_type != FrameType::SWITCH + && !fi.sequence.reduced_still_picture_hdr + { + self.write_bit(fi.frame_size_override_flag)?; // frame size overhead flag + } + + if fi.sequence.enable_order_hint { + let n = fi.sequence.order_hint_bits_minus_1 + 1; + let mask = (1 << n) - 1; + self.write_var(n, fi.order_hint & mask)?; + } + + if !fi.error_resilient && !fi.intra_only { + self.write::(fi.primary_ref_frame)?; + } + + if fi.sequence.decoder_model_info_present_flag { + unimplemented!(); + } + + if fi.frame_type == FrameType::KEY { + if !fi.show_frame { + // unshown keyframe (forward keyframe) + unimplemented!(); + self.write_var(REF_FRAMES as u32, fi.refresh_frame_flags)?; + } else { + assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK); + } + } else if fi.frame_type == FrameType::SWITCH { + assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK); + } else { + // Inter frame info goes here + if fi.intra_only { + assert!(fi.refresh_frame_flags != ALL_REF_FRAMES_MASK); + } else { + // TODO: This should be set once inter mode is used + } + self.write_var(REF_FRAMES as u32, fi.refresh_frame_flags)?; + }; + + if (!fi.intra_only || fi.refresh_frame_flags != ALL_REF_FRAMES_MASK) { + // Write all ref frame order hints if error_resilient_mode == 1 + if (fi.error_resilient && fi.sequence.enable_order_hint) { + for i in 0..REF_FRAMES { + let n = fi.sequence.order_hint_bits_minus_1 + 1; + let mask = (1 << n) - 1; + if let Some(ref rec) = fi.rec_buffer.frames[i] { + let ref_hint = rec.order_hint; + self.write_var(n, ref_hint & mask)?; + } else { + self.write_var(n, 0)?; + } + } + } + } + + // if KEY or INTRA_ONLY frame + if fi.intra_only { + self.write_frame_size(fi)?; + self.write_render_size(fi)?; + if fi.allow_screen_content_tools != 0 { + // TODO: && UpscaledWidth == FrameWidth. + self.write_bit(fi.allow_intrabc)?; + } + } + + let frame_refs_short_signaling = false; + if fi.frame_type == FrameType::KEY || fi.intra_only { + // Done by above + } else { + if fi.sequence.enable_order_hint { + self.write_bit(frame_refs_short_signaling)?; + if frame_refs_short_signaling { + unimplemented!(); + } + } + + for i in 0..INTER_REFS_PER_FRAME { + if !frame_refs_short_signaling { + self.write_var(REF_FRAMES_LOG2 as u32, fi.ref_frames[i])?; + } + if fi.sequence.frame_id_numbers_present_flag { + unimplemented!(); + } + } + + if !fi.error_resilient && fi.frame_size_override_flag { + self.write_frame_size_with_refs(fi)?; + } else { + self.write_frame_size(fi)?; + self.write_render_size(fi)?; + } + + if fi.force_integer_mv == 0 { + self.write_bit(fi.allow_high_precision_mv); + } + + self.write_bit(fi.is_filter_switchable)?; + if !fi.is_filter_switchable { + self.write::<2, u8>(fi.default_filter as u8)?; + } + self.write_bit(fi.is_motion_mode_switchable)?; + + if (!fi.error_resilient && fi.sequence.enable_ref_frame_mvs) { + self.write_bit(fi.use_ref_frame_mvs)?; + } + } + + if fi.sequence.reduced_still_picture_hdr || fi.disable_cdf_update { + assert!(fi.disable_frame_end_update_cdf); + } else { + self.write_bit(fi.disable_frame_end_update_cdf)?; + } + + // tile + // + + // Can we use the uniform spacing tile syntax? 'Uniform spacing' + // is a slight misnomer; it's more constrained than just a uniform + // spacing. + let ti = &fi.sequence.tiling; + + if fi.sb_width.align_power_of_two_and_shift(ti.tile_cols_log2) + == ti.tile_width_sb + && fi.sb_height.align_power_of_two_and_shift(ti.tile_rows_log2) + == ti.tile_height_sb + { + // yes; our actual tile width/height setting (which is always + // currently uniform) also matches the constrained width/height + // calculation implicit in the uniform spacing flag. + + self.write_bit(true)?; // uniform_tile_spacing_flag + + let cols_ones = ti.tile_cols_log2 - ti.min_tile_cols_log2; + for _ in 0..cols_ones { + self.write_bit(true); + } + if ti.tile_cols_log2 < ti.max_tile_cols_log2 { + self.write_bit(false); + } + + let rows_ones = ti.tile_rows_log2 - ti.min_tile_rows_log2; + for _ in 0..rows_ones { + self.write_bit(true); + } + if ti.tile_rows_log2 < ti.max_tile_rows_log2 { + self.write_bit(false); + } + } else { + self.write_bit(false)?; // uniform_tile_spacing_flag + let mut sofar = 0; + let mut widest_tile_sb = 0; + for _ in 0..ti.cols { + let max = (MAX_TILE_WIDTH + >> if fi.sequence.use_128x128_superblock { 7 } else { 6 }) + .min(fi.sb_width - sofar) as u16; + let this_sb_width = ti.tile_width_sb.min(fi.sb_width - sofar); + self.write_quniform(max, (this_sb_width - 1) as u16); + sofar += this_sb_width; + widest_tile_sb = widest_tile_sb.max(this_sb_width); + } + + let max_tile_area_sb = if ti.min_tiles_log2 > 0 { + (fi.sb_height * fi.sb_width) >> (ti.min_tiles_log2 + 1) + } else { + fi.sb_height * fi.sb_width + }; + + let max_tile_height_sb = (max_tile_area_sb / widest_tile_sb).max(1); + + sofar = 0; + for i in 0..ti.rows { + let max = max_tile_height_sb.min(fi.sb_height - sofar) as u16; + let this_sb_height = ti.tile_height_sb.min(fi.sb_height - sofar); + + self.write_quniform(max, (this_sb_height - 1) as u16); + sofar += this_sb_height; + } + } + + let tiles_log2 = ti.tile_cols_log2 + ti.tile_rows_log2; + if tiles_log2 > 0 { + // context_update_tile_id + // for now, always use the first tile CDF + self.write_var(tiles_log2 as u32, fs.context_update_tile_id as u32)?; + + // tile_size_bytes_minus_1 + self.write::<2, u32>(fs.max_tile_size_bytes - 1)?; + } + + // quantization + assert!(fi.base_q_idx > 0); + self.write::<8, u8>(fi.base_q_idx)?; // base_q_idx + self.write_delta_q(fi.dc_delta_q[0])?; + if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { + assert!(fi.ac_delta_q[0] == 0); + let diff_uv_delta = fi.dc_delta_q[1] != fi.dc_delta_q[2] + || fi.ac_delta_q[1] != fi.ac_delta_q[2]; + self.write_bit(diff_uv_delta)?; + self.write_delta_q(fi.dc_delta_q[1])?; + self.write_delta_q(fi.ac_delta_q[1])?; + if diff_uv_delta { + self.write_delta_q(fi.dc_delta_q[2])?; + self.write_delta_q(fi.ac_delta_q[2])?; + } + } + self.write_bit(false)?; // no qm + + // segmentation + self.write_segment_data(fi, &fs.segmentation)?; + + // delta_q + self.write_bit(false)?; // delta_q_present_flag: no delta q + + // delta_lf_params in the spec + self.write_deblock_filter_a(fi, &fs.deblock)?; + + // code for features not yet implemented.... + + // loop_filter_params in the spec + self.write_deblock_filter_b(fi, &fs.deblock)?; + + // cdef + self.write_frame_cdef(fi)?; + + // loop restoration + self.write_frame_lrf(fi, &fs.restoration)?; + + self.write_bit(fi.tx_mode_select)?; // tx mode + + let mut reference_select = false; + if !fi.intra_only { + reference_select = fi.reference_mode != ReferenceMode::SINGLE; + self.write_bit(reference_select)?; + } + + let skip_mode_allowed = + fi.sequence.get_skip_mode_allowed(fi, inter_cfg, reference_select); + if skip_mode_allowed { + self.write_bit(false)?; // skip_mode_present + } + + if fi.intra_only || fi.error_resilient || !fi.sequence.enable_warped_motion + { + } else { + self.write_bit(fi.allow_warped_motion)?; // allow_warped_motion + } + + self.write_bit(fi.use_reduced_tx_set)?; // reduced tx + + // global motion + if !fi.intra_only { + for i in 0..7 { + let mode = fi.globalmv_transformation_type[i]; + self.write_bit(mode != GlobalMVMode::IDENTITY)?; + if mode != GlobalMVMode::IDENTITY { + self.write_bit(mode == GlobalMVMode::ROTZOOM)?; + if mode != GlobalMVMode::ROTZOOM { + self.write_bit(mode == GlobalMVMode::TRANSLATION)?; + } + } + match mode { + GlobalMVMode::IDENTITY => { /* Nothing to do */ } + GlobalMVMode::TRANSLATION => { + let mv_x = 0; + let mv_x_ref = 0; + let mv_y = 0; + let mv_y_ref = 0; + let bits = 12 - 6 + 3 - !fi.allow_high_precision_mv as u8; + let bits_diff = 12 - 3 + fi.allow_high_precision_mv as u8; + BCodeWriter::write_s_refsubexpfin( + self, + (1 << bits) + 1, + 3, + mv_x_ref >> bits_diff, + mv_x >> bits_diff, + )?; + BCodeWriter::write_s_refsubexpfin( + self, + (1 << bits) + 1, + 3, + mv_y_ref >> bits_diff, + mv_y >> bits_diff, + )?; + } + GlobalMVMode::ROTZOOM => unimplemented!(), + GlobalMVMode::AFFINE => unimplemented!(), + }; + } + } + + if fi.sequence.film_grain_params_present { + if let Some(grain_params) = fi.film_grain_params() { + // Apply grain + self.write_bit(true)?; + self.write::<16, u16>(grain_params.random_seed)?; + if fi.frame_type == FrameType::INTER { + // For the purposes of photon noise, + // it's simpler to always update the params, + // and the output will be the same. + self.write_bit(true)?; + } + + self.write::<4, u8>(grain_params.scaling_points_y.len() as u8)?; + for point in &grain_params.scaling_points_y { + self.write::<8, u8>(point[0])?; + self.write::<8, u8>(point[1])?; + } + + let chroma_scaling_from_luma = + if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { + self.write_bit(grain_params.chroma_scaling_from_luma)?; + grain_params.chroma_scaling_from_luma + } else { + false + }; + if !(fi.sequence.chroma_sampling == ChromaSampling::Cs400 + || chroma_scaling_from_luma + || (fi.sequence.chroma_sampling == ChromaSampling::Cs420 + && grain_params.scaling_points_y.is_empty())) + { + self.write::<4, u8>(grain_params.scaling_points_cb.len() as u8)?; + for point in &grain_params.scaling_points_cb { + self.write::<8, u8>(point[0])?; + self.write::<8, u8>(point[1])?; + } + self.write::<4, u8>(grain_params.scaling_points_cr.len() as u8)?; + for point in &grain_params.scaling_points_cr { + self.write::<8, u8>(point[0])?; + self.write::<8, u8>(point[1])?; + } + } + + self.write::<2, u8>(grain_params.scaling_shift - 8)?; + self.write::<2, u8>(grain_params.ar_coeff_lag)?; + + let mut num_pos_luma = + (2 * grain_params.ar_coeff_lag * (grain_params.ar_coeff_lag + 1)) + as usize; + let mut num_pos_chroma; + if !grain_params.scaling_points_y.is_empty() { + num_pos_chroma = num_pos_luma + 1; + for i in 0..num_pos_luma { + self.write::<8, u8>( + (grain_params.ar_coeffs_y[i] as i16 + 128) as u8, + )?; + } + } else { + num_pos_chroma = num_pos_luma; + } + + if chroma_scaling_from_luma + || !grain_params.scaling_points_cb.is_empty() + { + for i in 0..num_pos_chroma { + self.write::<8, u8>( + (grain_params.ar_coeffs_cb[i] as i16 + 128) as u8, + )?; + } + } + if chroma_scaling_from_luma + || !grain_params.scaling_points_cr.is_empty() + { + for i in 0..num_pos_chroma { + self.write::<8, u8>( + (grain_params.ar_coeffs_cr[i] as i16 + 128) as u8, + )?; + } + } + + self.write::<2, u8>(grain_params.ar_coeff_shift - 6)?; + self.write::<2, u8>(grain_params.grain_scale_shift)?; + if !grain_params.scaling_points_cb.is_empty() { + self.write::<8, u8>(grain_params.cb_mult)?; + self.write::<8, u8>(grain_params.cb_luma_mult)?; + self.write::<9, u16>(grain_params.cb_offset)?; + } + if !grain_params.scaling_points_cr.is_empty() { + self.write::<8, u8>(grain_params.cr_mult)?; + self.write::<8, u8>(grain_params.cr_luma_mult)?; + self.write::<9, u16>(grain_params.cr_offset)?; + } + self.write_bit(grain_params.overlap_flag)?; + self.write_bit(fi.sequence.pixel_range == PixelRange::Limited)?; + } else { + // No film grain for this frame + self.write_bit(false)?; + } + } + + if fi.large_scale_tile { + unimplemented!(); + } + self.byte_align()?; + + Ok(()) + } + // End of OBU Headers + + fn write_max_frame_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + // width_bits and height_bits will have to be moved to the sequence header OBU + // when we add support for it. + let width = fi.width - 1; + let height = fi.height - 1; + let width_bits = log_in_base_2(width as u32) as u32 + 1; + let height_bits = log_in_base_2(height as u32) as u32 + 1; + assert!(width_bits <= 16); + assert!(height_bits <= 16); + self.write::<4, u32>(width_bits - 1)?; + self.write::<4, u32>(height_bits - 1)?; + self.write_var(width_bits, width as u16)?; + self.write_var(height_bits, height as u16)?; + Ok(()) + } + + fn write_frame_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + // width_bits and height_bits will have to be moved to the sequence header OBU + // when we add support for it. + if fi.frame_size_override_flag { + let width = fi.width - 1; + let height = fi.height - 1; + let width_bits = log_in_base_2(width as u32) as u32 + 1; + let height_bits = log_in_base_2(height as u32) as u32 + 1; + assert!(width_bits <= 16); + assert!(height_bits <= 16); + self.write_var(width_bits, width as u16)?; + self.write_var(height_bits, height as u16)?; + } + if fi.sequence.enable_superres { + unimplemented!(); + } + Ok(()) + } + + fn write_render_size( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + self.write_bit(fi.render_and_frame_size_different)?; + if fi.render_and_frame_size_different { + self.write::<16, u32>(fi.render_width - 1)?; + self.write::<16, u32>(fi.render_height - 1)?; + } + Ok(()) + } + + fn write_frame_size_with_refs( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + let mut found_ref = false; + for i in 0..INTER_REFS_PER_FRAME { + if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] { + if rec.width == fi.width as u32 + && rec.height == fi.height as u32 + && rec.render_width == fi.render_width + && rec.render_height == fi.render_height + { + self.write_bit(true)?; + found_ref = true; + break; + } else { + self.write_bit(false)?; + } + } else { + self.write_bit(false)?; + } + } + if !found_ref { + self.write_frame_size(fi)?; + self.write_render_size(fi)?; + } else if fi.sequence.enable_superres { + unimplemented!(); + } + Ok(()) + } + + fn write_deblock_filter_a( + &mut self, fi: &FrameInvariants, deblock: &DeblockState, + ) -> io::Result<()> { + if fi.delta_q_present { + if !fi.allow_intrabc { + self.write_bit(deblock.block_deltas_enabled)?; + } + if deblock.block_deltas_enabled { + self.write::<2, u8>(deblock.block_delta_shift)?; + self.write_bit(deblock.block_delta_multi)?; + } + } + Ok(()) + } + + fn write_deblock_filter_b( + &mut self, fi: &FrameInvariants, deblock: &DeblockState, + ) -> io::Result<()> { + let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { + 1 + } else { + MAX_PLANES + }; + assert!(deblock.levels[0] < 64); + self.write::<6, u8>(deblock.levels[0])?; // loop deblocking filter level 0 + assert!(deblock.levels[1] < 64); + self.write::<6, u8>(deblock.levels[1])?; // loop deblocking filter level 1 + if planes > 1 && (deblock.levels[0] > 0 || deblock.levels[1] > 0) { + assert!(deblock.levels[2] < 64); + self.write::<6, u8>(deblock.levels[2])?; // loop deblocking filter level 2 + assert!(deblock.levels[3] < 64); + self.write::<6, u8>(deblock.levels[3])?; // loop deblocking filter level 3 + } + self.write::<3, u8>(deblock.sharpness)?; // deblocking filter sharpness + self.write_bit(deblock.deltas_enabled)?; // loop deblocking filter deltas enabled + if deblock.deltas_enabled { + self.write_bit(deblock.delta_updates_enabled)?; // deltas updates enabled + if deblock.delta_updates_enabled { + // conditionally write ref delta updates + let prev_ref_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE { + [1, 0, 0, 0, 0, -1, -1, -1] + } else { + fi.rec_buffer.deblock + [fi.ref_frames[fi.primary_ref_frame as usize] as usize] + .ref_deltas + }; + for i in 0..REF_FRAMES { + let update = deblock.ref_deltas[i] != prev_ref_deltas[i]; + self.write_bit(update)?; + if update { + self.write_signed::<7, i8>(deblock.ref_deltas[i])?; + } + } + // conditionally write mode delta updates + let prev_mode_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE { + [0, 0] + } else { + fi.rec_buffer.deblock + [fi.ref_frames[fi.primary_ref_frame as usize] as usize] + .mode_deltas + }; + for i in 0..2 { + let update = deblock.mode_deltas[i] != prev_mode_deltas[i]; + self.write_bit(update)?; + if update { + self.write_signed::<7, i8>(deblock.mode_deltas[i])?; + } + } + } + } + Ok(()) + } + + fn write_frame_cdef( + &mut self, fi: &FrameInvariants, + ) -> io::Result<()> { + if fi.sequence.enable_cdef && !fi.allow_intrabc { + assert!(fi.cdef_damping >= 3); + assert!(fi.cdef_damping <= 6); + self.write::<2, u8>(fi.cdef_damping - 3)?; + assert!(fi.cdef_bits < 4); + self.write::<2, u8>(fi.cdef_bits)?; // cdef bits + for i in 0..(1 << fi.cdef_bits) { + assert!(fi.cdef_y_strengths[i] < 64); + assert!(fi.cdef_uv_strengths[i] < 64); + self.write::<6, u8>(fi.cdef_y_strengths[i])?; // cdef y strength + if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { + self.write::<6, u8>(fi.cdef_uv_strengths[i])?; // cdef uv strength + } + } + } + Ok(()) + } + + fn write_frame_lrf( + &mut self, fi: &FrameInvariants, rs: &RestorationState, + ) -> io::Result<()> { + if fi.sequence.enable_restoration && !fi.allow_intrabc { + // && !self.lossless + let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { + 1 + } else { + MAX_PLANES + }; + let mut use_lrf = false; + let mut use_chroma_lrf = false; + for i in 0..planes { + self.write::<2, u8>(rs.planes[i].cfg.lrf_type)?; // filter type by plane + if rs.planes[i].cfg.lrf_type != RESTORE_NONE { + use_lrf = true; + if i > 0 { + use_chroma_lrf = true; + } + } + } + if use_lrf { + // The Y shift value written here indicates shift up from superblock size + if !fi.sequence.use_128x128_superblock { + self.write::<1, u8>(u8::from(rs.planes[0].cfg.unit_size > 64))?; + } + + if rs.planes[0].cfg.unit_size > 64 { + self.write::<1, u8>(u8::from(rs.planes[0].cfg.unit_size > 128))?; + } + + if use_chroma_lrf + && fi.sequence.chroma_sampling == ChromaSampling::Cs420 + { + self.write::<1, u8>(u8::from( + rs.planes[0].cfg.unit_size > rs.planes[1].cfg.unit_size, + ))?; + } + } + } + Ok(()) + } + + fn write_segment_data( + &mut self, fi: &FrameInvariants, segmentation: &SegmentationState, + ) -> io::Result<()> { + assert_eq!(fi.enable_segmentation, segmentation.enabled); + self.write_bit(fi.enable_segmentation)?; + + if segmentation.enabled { + if fi.primary_ref_frame == PRIMARY_REF_NONE { + assert!(segmentation.update_map); + assert!(segmentation.update_data); + } else { + self.write_bit(segmentation.update_map)?; + if segmentation.update_map { + self.write_bit(false)?; /* Without using temporal prediction */ + } + self.write_bit(segmentation.update_data)?; + } + if segmentation.update_data { + for i in 0..8 { + for j in 0..SegLvl::SEG_LVL_MAX as usize { + self.write_bit(segmentation.features[i][j])?; + if segmentation.features[i][j] { + let bits = seg_feature_bits[j]; + let data = segmentation.data[i][j]; + if seg_feature_is_signed[j] { + self.write_signed_var(bits + 1, data)?; + } else { + self.write_var(bits, data)?; + } + } + } + } + } + } + Ok(()) + } + + fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()> { + self.write_bit(delta_q != 0)?; + if delta_q != 0 { + assert!((-63..=63).contains(&delta_q)); + self.write_signed::<7, i8>(delta_q)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::ULEB128Writer; + use bitstream_io::{BigEndian, BitWriter}; + use nom::error::Error; + use nom::IResult; + use quickcheck::quickcheck; + + fn leb128(mut input: &[u8]) -> IResult<&[u8], u64, Error<&[u8]>> { + use nom::bytes::complete::take; + + let mut value = 0u64; + for i in 0..8u8 { + let result = take(1usize)(input)?; + input = result.0; + let leb128_byte = result.1[0]; + value |= u64::from(leb128_byte & 0x7f) << (i * 7); + if (leb128_byte & 0x80) == 0 { + break; + } + } + Ok((input, value)) + } + + quickcheck! { + fn validate_leb128_write(val: u32) -> bool { + let mut buf1 = Vec::new(); + let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); + bw1.write_uleb128(val as u64).unwrap(); + let result = leb128(&buf1).unwrap(); + u64::from(val) == result.1 && result.0.is_empty() + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/levels.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/levels.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/levels.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/levels.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,116 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub static AV1_LEVEL_DEFINED: [bool; 32] = [ + true, // 2.0 + true, // 2.1 + false, false, true, // 3.0 + true, // 3.1 + false, false, true, // 4.0 + true, // 4.1 + false, false, true, // 5.0 + true, // 5.1 + true, // 5.2 + true, // 5.3 + true, // 6.0 + true, // 6.1 + true, // 6.2 + true, // 6.3 + false, false, false, false, false, false, false, false, false, false, false, + false, +]; + +pub static AV1_LEVEL_MAX_PIC_SIZE: [usize; 32] = [ + 147456, // 2.0 + 278784, // 2.1 + 0, 0, 665856, // 3.0 + 1065024, // 3.1 + 0, 0, 2359296, // 4.0 + 23592960, // 4.1 + 0, 0, 8912896, // 5.0 + 8912896, // 5.1 + 8912896, // 5.2 + 8912896, // 5.3 + 35651584, // 6.0 + 35651584, // 6.1 + 35651584, // 6.2 + 35651584, // 6.3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub static AV1_LEVEL_MAX_H_SIZE: [usize; 32] = [ + 2048, // 2.0 + 2816, // 2.1 + 0, 0, 4352, // 3.0 + 5504, // 3.1 + 0, 0, 6144, // 4.0 + 6144, // 4.1 + 0, 0, 8192, // 5.0 + 8192, // 5.1 + 8192, // 5.2 + 8192, // 5.3 + 16384, // 6.0 + 16384, // 6.1 + 16384, // 6.2 + 16384, // 6.3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub static AV1_LEVEL_MAX_V_SIZE: [usize; 32] = [ + 1152, // 2.0 + 1584, // 2.1 + 0, 0, 2448, // 3.0 + 3096, // 3.1 + 0, 0, 3456, // 4.0 + 3456, // 4.1 + 0, 0, 4352, // 5.0 + 4352, // 5.1 + 4352, // 5.2 + 4352, // 5.3 + 8704, // 6.0 + 8704, // 6.1 + 8704, // 6.2 + 8704, // 6.3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub static AV1_LEVEL_MAX_DISPLAY_RATE: [usize; 32] = [ + 4_423_680, // 2.0 + 8_363_520, // 2.1 + 0, + 0, + 19_975_680, // 3.0 + 31_950_720, // 3.1 + 0, + 0, + 70_778_880, // 4.0 + 141_557_760, // 4.1 + 0, + 0, + 267_386_880, // 5.0 + 534_773_760, // 5.1 + 1_069_547_520, // 5.2 + 1_069_547_520, // 5.3 + 1_069_547_520, // 6.0 + 2_139_095_040, // 6.1 + 4_278_190_080, // 6.2 + 4_278_190_080, // 6.3 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,329 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +//! rav1e is an [AV1] video encoder. It is designed to eventually cover all use +//! cases, though in its current form it is most suitable for cases where +//! libaom (the reference encoder) is too slow. +//! +//! ## Features +//! +//! * Intra and inter frames +//! * 64x64 superblocks +//! * 4x4 to 64x64 RDO-selected square and 2:1/1:2 rectangular blocks +//! * DC, H, V, Paeth, smooth, and a subset of directional prediction modes +//! * DCT, (FLIP-)ADST and identity transforms (up to 64x64, 16x16 and 32x32 +//! respectively) +//! * 8-, 10- and 12-bit depth color +//! * 4:2:0 (full support), 4:2:2 and 4:4:4 (limited) chroma sampling +//! * Variable speed settings +//! * Near real-time encoding at high speed levels +//! +//! ## Usage +//! +//! Encoding is done through the [`Context`] struct. Examples on +//! [`Context::receive_packet`] show how to create a [`Context`], send frames +//! into it and receive packets of encoded data. +//! +//! [AV1]: https://aomediacodec.github.io/av1-spec/av1-spec.pdf +//! [`Context`]: struct.Context.html +//! [`Context::receive_packet`]: struct.Context.html#method.receive_packet + +#![allow(missing_abi)] +#![allow(unused_unsafe)] + +#[cfg(test)] +#[macro_use] +extern crate pretty_assertions; + +pub use crate::api::color; +pub use crate::api::{ + Config, Context, EncoderConfig, EncoderStatus, InvalidConfig, Packet, +}; +use crate::encoder::*; +pub use crate::frame::Frame; +pub use crate::util::{CastFromPrimitive, Pixel, PixelType}; + +pub(crate) mod built_info { + // The file has been placed there by the build script. + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +mod serialize { + cfg_if::cfg_if! { + if #[cfg(feature="serialize")] { + pub use serde::*; + } else { + pub use noop_proc_macro::{Deserialize, Serialize}; + } + } +} + +mod wasm_bindgen { + cfg_if::cfg_if! { + if #[cfg(feature="wasm")] { + pub use wasm_bindgen::prelude::*; + } else { + pub use noop_proc_macro::wasm_bindgen; + } + } +} + +#[cfg(any(cargo_c, feature = "capi"))] +pub mod capi; + +#[macro_use] +mod transform; +#[macro_use] +mod cpu_features; + +mod activity; +pub(crate) mod asm; +mod dist; +mod ec; +mod partition; +mod predict; +mod quantize; +mod rdo; +mod rdo_tables; +#[macro_use] +mod util; +mod cdef; +#[doc(hidden)] +pub mod context; +mod deblock; +mod encoder; +mod entropymode; +mod levels; +mod lrf; +mod mc; +mod me; +mod rate; +mod recon_intra; +mod scan_order; +mod segmentation; +mod stats; +#[doc(hidden)] +pub mod tiling; +mod token_cdfs; + +mod api; +mod frame; +mod header; + +/// Commonly used types and traits. +pub mod prelude { + pub use crate::api::*; + pub use crate::encoder::{Sequence, Tune}; + pub use crate::frame::{ + Frame, FrameParameters, FrameTypeOverride, Plane, PlaneConfig, + }; + pub use crate::partition::BlockSize; + pub use crate::predict::PredictionMode; + pub use crate::transform::TxType; + pub use crate::util::{CastFromPrimitive, Pixel, PixelType}; +} + +/// Basic data structures +pub mod data { + pub use crate::api::{ + ChromaticityPoint, EncoderStatus, FrameType, Packet, Rational, + }; + pub use crate::frame::{Frame, FrameParameters}; + pub use crate::stats::EncoderStats; + pub use crate::util::{CastFromPrimitive, Pixel, PixelType}; +} + +/// Encoder configuration and settings +pub mod config { + pub use crate::api::config::{ + GrainTableSegment, NoiseGenArgs, TransferFunction, NUM_UV_COEFFS, + NUM_UV_POINTS, NUM_Y_COEFFS, NUM_Y_POINTS, + }; + pub use crate::api::{ + Config, EncoderConfig, InvalidConfig, PredictionModesSetting, + RateControlConfig, RateControlError, RateControlSummary, SpeedSettings, + }; + pub use crate::cpu_features::CpuFeatureLevel; +} + +/// Version information +/// +/// The information is recovered from `Cargo.toml` and `git describe`, when available. +/// +/// ``` +/// use rav1e::version; +/// use semver::Version; +/// +/// let major = version::major(); +/// let minor = version::minor(); +/// let patch = version::patch(); +/// +/// let short = version::short(); +/// +/// let v1 = Version::new(major, minor, patch); +/// let v2 = Version::parse(&short).unwrap(); +/// +/// assert_eq!(v1.major, v2.major); +/// ``` +pub mod version { + /// Major version component + /// + /// It is increased every time a release presents a incompatible API change. + /// + /// # Panics + /// + /// Will panic if package is not built with Cargo, + /// or if the package version is not a valid triplet of integers. + pub fn major() -> u64 { + env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap() + } + /// Minor version component + /// + /// It is increased every time a release presents new functionalities are added + /// in a backwards-compatible manner. + /// + /// # Panics + /// + /// Will panic if package is not built with Cargo, + /// or if the package version is not a valid triplet of integers. + pub fn minor() -> u64 { + env!("CARGO_PKG_VERSION_MINOR").parse().unwrap() + } + /// Patch version component + /// + /// It is increased every time a release provides only backwards-compatible bugfixes. + /// + /// # Panics + /// + /// Will panic if package is not built with Cargo, + /// or if the package version is not a valid triplet of integers. + pub fn patch() -> u64 { + env!("CARGO_PKG_VERSION_PATCH").parse().unwrap() + } + + /// Version information as presented in `[package]` `version`. + /// + /// e.g. `0.1.0` + /// + /// Can be parsed by [semver](https://crates.io/crates/semver). + pub fn short() -> String { + env!("CARGO_PKG_VERSION").to_string() + } + + /// Version information as presented in `[package] version` followed by the + /// short commit hash if present. + /// + /// e.g. `0.1.0 - g743d464` + /// + pub fn long() -> String { + let s = short(); + let hash = hash(); + + if hash.is_empty() { + s + } else { + format!("{s} - {hash}") + } + } + + cfg_if::cfg_if! { + if #[cfg(feature="git_version")] { + fn git_version() -> &'static str { + crate::built_info::GIT_VERSION.unwrap_or_default() + } + + fn git_hash() -> &'static str { + crate::built_info::GIT_COMMIT_HASH.unwrap_or_default() + } + } else { + fn git_version() -> &'static str { + "UNKNOWN" + } + + fn git_hash() -> &'static str { + "UNKNOWN" + } + } + } + /// Commit hash (short) + /// + /// Short hash of the git commit used by this build + /// + /// e.g. `g743d464` + /// + pub fn hash() -> String { + git_hash().to_string() + } + + /// Version information with the information + /// provided by `git describe --tags`. + /// + /// e.g. `0.1.0 (v0.1.0-1-g743d464)` + /// + pub fn full() -> String { + format!("{} ({})", short(), git_version(),) + } +} +#[cfg(all( + any(test, fuzzing), + any(feature = "decode_test", feature = "decode_test_dav1d") +))] +mod test_encode_decode; + +#[cfg(feature = "bench")] +pub mod bench { + pub mod api { + pub use crate::api::*; + } + pub mod cdef { + pub use crate::cdef::*; + } + pub mod context { + pub use crate::context::*; + } + pub mod dist { + pub use crate::dist::*; + } + pub mod ec { + pub use crate::ec::*; + } + pub mod encoder { + pub use crate::encoder::*; + } + pub mod mc { + pub use crate::mc::*; + } + pub mod partition { + pub use crate::partition::*; + } + pub mod frame { + pub use crate::frame::*; + } + pub mod predict { + pub use crate::predict::*; + } + pub mod rdo { + pub use crate::rdo::*; + } + pub mod tiling { + pub use crate::tiling::*; + } + pub mod transform { + pub use crate::transform::*; + } + pub mod util { + pub use crate::util::*; + } + pub mod cpu_features { + pub use crate::cpu_features::*; + } +} + +#[cfg(fuzzing)] +pub mod fuzzing; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/lrf.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lrf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/lrf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/lrf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1586 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::cmp; +use std::iter::FusedIterator; +use std::ops::{Index, IndexMut}; + +use crate::api::SGRComplexityLevel; +use crate::color::ChromaSampling::Cs400; +use crate::context::{MAX_PLANES, SB_SIZE}; +use crate::encoder::FrameInvariants; +use crate::frame::{ + AsRegion, Frame, Plane, PlaneConfig, PlaneOffset, PlaneSlice, +}; +use crate::tiling::{Area, PlaneRegion, PlaneRegionMut, Rect}; +use crate::util::{clamp, CastFromPrimitive, ILog, Pixel}; + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + use crate::asm::x86::lrf::*; + } else { + use self::rust::*; + } +} + +pub const RESTORATION_TILESIZE_MAX_LOG2: usize = 8; + +pub const RESTORE_NONE: u8 = 0; +pub const RESTORE_SWITCHABLE: u8 = 1; +pub const RESTORE_WIENER: u8 = 2; +pub const RESTORE_SGRPROJ: u8 = 3; + +pub const WIENER_TAPS_MIN: [i8; 3] = [-5, -23, -17]; +pub const WIENER_TAPS_MID: [i8; 3] = [3, -7, 15]; +pub const WIENER_TAPS_MAX: [i8; 3] = [10, 8, 46]; +#[allow(unused)] +pub const WIENER_TAPS_K: [i8; 3] = [1, 2, 3]; +pub const WIENER_BITS: usize = 7; + +pub const SGRPROJ_XQD_MIN: [i8; 2] = [-96, -32]; +pub const SGRPROJ_XQD_MID: [i8; 2] = [-32, 31]; +pub const SGRPROJ_XQD_MAX: [i8; 2] = [31, 95]; +pub const SGRPROJ_PRJ_SUBEXP_K: u8 = 4; +pub const SGRPROJ_PRJ_BITS: u8 = 7; +pub const SGRPROJ_PARAMS_BITS: u8 = 4; +pub const SGRPROJ_MTABLE_BITS: u8 = 20; +pub const SGRPROJ_SGR_BITS: u8 = 8; +pub const SGRPROJ_RECIP_BITS: u8 = 12; +pub const SGRPROJ_RST_BITS: u8 = 4; +pub const SGRPROJ_PARAMS_S: [[u32; 2]; 1 << SGRPROJ_PARAMS_BITS] = [ + [140, 3236], + [112, 2158], + [93, 1618], + [80, 1438], + [70, 1295], + [58, 1177], + [47, 1079], + [37, 996], + [30, 925], + [25, 863], + [0, 2589], + [0, 1618], + [0, 1177], + [0, 925], + [56, 0], + [22, 0], +]; + +// List of indices to SGRPROJ_PARAMS_S values that at a given complexity level. +// SGRPROJ_ALL_SETS contains every possible index +const SGRPROJ_ALL_SETS: &[u8] = + &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; +// SGRPROJ_REDUCED_SETS has half of the values. Using only these values gives +// most of the gains from sgr. The decision of which values to use is somewhat +// arbitrary. The sgr parameters has 3 discontinuous groups. The first has both +// parameters as non-zero. The other two are distinguishable by which of the +// two parameters is zero. There are an even number of each of these groups and +// the non-zero parameters grow as the indices increase. This array uses the +// 1st, 3rd, ... smallest params of each group. +const SGRPROJ_REDUCED_SETS: &[u8] = &[1, 3, 5, 7, 9, 11, 13, 15]; + +pub const fn get_sgr_sets(complexity: SGRComplexityLevel) -> &'static [u8] { + match complexity { + SGRComplexityLevel::Full => SGRPROJ_ALL_SETS, + SGRComplexityLevel::Reduced => SGRPROJ_REDUCED_SETS, + } +} + +pub const SOLVE_IMAGE_MAX: usize = 1 << RESTORATION_TILESIZE_MAX_LOG2; +pub const SOLVE_IMAGE_STRIDE: usize = SOLVE_IMAGE_MAX + 6 + 2; +pub const SOLVE_IMAGE_HEIGHT: usize = SOLVE_IMAGE_STRIDE; +pub const SOLVE_IMAGE_SIZE: usize = SOLVE_IMAGE_STRIDE * SOLVE_IMAGE_HEIGHT; + +pub const STRIPE_IMAGE_MAX: usize = (1 << RESTORATION_TILESIZE_MAX_LOG2) + + (1 << (RESTORATION_TILESIZE_MAX_LOG2 - 1)); +pub const STRIPE_IMAGE_STRIDE: usize = STRIPE_IMAGE_MAX + 6 + 2; +pub const STRIPE_IMAGE_HEIGHT: usize = 64 + 6 + 2; +pub const STRIPE_IMAGE_SIZE: usize = STRIPE_IMAGE_STRIDE * STRIPE_IMAGE_HEIGHT; + +pub const IMAGE_WIDTH_MAX: usize = [STRIPE_IMAGE_MAX, SOLVE_IMAGE_MAX] + [(STRIPE_IMAGE_MAX < SOLVE_IMAGE_MAX) as usize]; + +/// The buffer used in `sgrproj_stripe_filter()` and `sgrproj_solve()`. +#[derive(Debug)] +pub struct IntegralImageBuffer { + pub integral_image: Vec, + pub sq_integral_image: Vec, +} + +impl IntegralImageBuffer { + /// Creates a new buffer with the given size, filled with zeros. + #[inline] + pub fn zeroed(size: usize) -> Self { + Self { integral_image: vec![0; size], sq_integral_image: vec![0; size] } + } +} + +#[allow(unused)] // Wiener coming soon! +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +pub enum RestorationFilter { + #[default] + None, + Wiener { + coeffs: [[i8; 3]; 2], + }, + Sgrproj { + set: u8, + xqd: [i8; 2], + }, +} + +impl RestorationFilter { + pub const fn notequal(self, cmp: RestorationFilter) -> bool { + match self { + RestorationFilter::None => !matches!(cmp, RestorationFilter::None), + RestorationFilter::Sgrproj { set, xqd } => { + if let RestorationFilter::Sgrproj { set: set2, xqd: xqd2 } = cmp { + !(set == set2 && xqd[0] == xqd2[0] && xqd[1] == xqd2[1]) + } else { + true + } + } + RestorationFilter::Wiener { coeffs } => { + if let RestorationFilter::Wiener { coeffs: coeffs2 } = cmp { + !(coeffs[0][0] == coeffs2[0][0] + && coeffs[0][1] == coeffs2[0][1] + && coeffs[0][2] == coeffs2[0][2] + && coeffs[1][0] == coeffs2[1][0] + && coeffs[1][1] == coeffs2[1][1] + && coeffs[1][2] == coeffs2[1][2]) + } else { + true + } + } + } + } +} + +pub(crate) mod rust { + use crate::cpu_features::CpuFeatureLevel; + use crate::frame::PlaneSlice; + use crate::lrf::{ + get_integral_square, sgrproj_sum_finish, SGRPROJ_RST_BITS, + SGRPROJ_SGR_BITS, + }; + use crate::util::CastFromPrimitive; + use crate::Pixel; + + #[inline(always)] + pub(crate) fn sgrproj_box_ab_internal( + r: usize, af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, start_x: usize, y: usize, stripe_w: usize, s: u32, + ) { + let d: usize = r * 2 + 1; + let n: usize = d * d; + let one_over_n = if r == 1 { 455 } else { 164 }; + + assert!(iimg.len() > (y + d) * iimg_stride + stripe_w + 1 + d); + assert!(iimg_sq.len() > (y + d) * iimg_stride + stripe_w + 1 + d); + assert!(af.len() > stripe_w + 1); + assert!(bf.len() > stripe_w + 1); + + for x in start_x..stripe_w + 2 { + // SAFETY: We perform the bounds checks above, once for the whole loop + unsafe { + let sum = get_integral_square(iimg, iimg_stride, x, y, d); + let ssq = get_integral_square(iimg_sq, iimg_stride, x, y, d); + let (reta, retb) = + sgrproj_sum_finish::(ssq, sum, n as u32, one_over_n, s); + *af.get_unchecked_mut(x) = reta; + *bf.get_unchecked_mut(x) = retb; + } + } + } + + // computes an intermediate (ab) row for stripe_w + 2 columns at row y + pub(crate) fn sgrproj_box_ab_r1( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, + _cpu: CpuFeatureLevel, + ) { + sgrproj_box_ab_internal::( + 1, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + 0, + y, + stripe_w, + s, + ); + } + + // computes an intermediate (ab) row for stripe_w + 2 columns at row y + pub(crate) fn sgrproj_box_ab_r2( + af: &mut [u32], bf: &mut [u32], iimg: &[u32], iimg_sq: &[u32], + iimg_stride: usize, y: usize, stripe_w: usize, s: u32, + _cpu: CpuFeatureLevel, + ) { + sgrproj_box_ab_internal::( + 2, + af, + bf, + iimg, + iimg_sq, + iimg_stride, + 0, + y, + stripe_w, + s, + ); + } + + pub(crate) fn sgrproj_box_f_r0( + f: &mut [u32], y: usize, w: usize, cdeffed: &PlaneSlice, + _cpu: CpuFeatureLevel, + ) { + sgrproj_box_f_r0_internal(f, 0, y, w, cdeffed); + } + + #[inline(always)] + pub(crate) fn sgrproj_box_f_r0_internal( + f: &mut [u32], start_x: usize, y: usize, w: usize, cdeffed: &PlaneSlice, + ) { + let line = cdeffed.row(y); + for (fp, &v) in f[start_x..w].iter_mut().zip(line[start_x..w].iter()) { + *fp = u32::cast_from(v) << SGRPROJ_RST_BITS; + } + } + + pub(crate) fn sgrproj_box_f_r1( + af: &[&[u32]; 3], bf: &[&[u32]; 3], f: &mut [u32], y: usize, w: usize, + cdeffed: &PlaneSlice, _cpu: CpuFeatureLevel, + ) { + sgrproj_box_f_r1_internal(af, bf, f, 0, y, w, cdeffed); + } + + #[inline(always)] + pub(crate) fn sgrproj_box_f_r1_internal( + af: &[&[u32]; 3], bf: &[&[u32]; 3], f: &mut [u32], start_x: usize, + y: usize, w: usize, cdeffed: &PlaneSlice, + ) { + let shift = 5 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS; + let line = cdeffed.row(y); + for x in start_x..w { + let a = 3 * (af[0][x] + af[2][x] + af[0][x + 2] + af[2][x + 2]) + + 4 + * (af[1][x] + + af[0][x + 1] + + af[1][x + 1] + + af[2][x + 1] + + af[1][x + 2]); + let b = 3 * (bf[0][x] + bf[2][x] + bf[0][x + 2] + bf[2][x + 2]) + + 4 + * (bf[1][x] + + bf[0][x + 1] + + bf[1][x + 1] + + bf[2][x + 1] + + bf[1][x + 2]); + let v = a * u32::cast_from(line[x]) + b; + f[x] = (v + (1 << shift >> 1)) >> shift; + } + } + + pub(crate) fn sgrproj_box_f_r2( + af: &[&[u32]; 2], bf: &[&[u32]; 2], f0: &mut [u32], f1: &mut [u32], + y: usize, w: usize, cdeffed: &PlaneSlice, _cpu: CpuFeatureLevel, + ) { + sgrproj_box_f_r2_internal(af, bf, f0, f1, 0, y, w, cdeffed); + } + + #[inline(always)] + pub(crate) fn sgrproj_box_f_r2_internal( + af: &[&[u32]; 2], bf: &[&[u32]; 2], f0: &mut [u32], f1: &mut [u32], + start_x: usize, y: usize, w: usize, cdeffed: &PlaneSlice, + ) { + let shift = 5 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS; + let shifto = 4 + SGRPROJ_SGR_BITS - SGRPROJ_RST_BITS; + let line = cdeffed.row(y); + let line1 = cdeffed.row(y + 1); + + let af0 = af[0][start_x..w + 3].windows(3); + let af1 = af[1][start_x..w + 3].windows(3); + let bf0 = bf[0][start_x..w + 3].windows(3); + let bf1 = bf[1][start_x..w + 3].windows(3); + + let af_it = af0.zip(af1); + let bf_it = bf0.zip(bf1); + + let in0 = line[start_x..w].iter(); + let in1 = line1[start_x..w].iter(); + + let o0 = f0[start_x..w].iter_mut(); + let o1 = f1[start_x..w].iter_mut(); + + let in_iter = in0.zip(in1); + let out_iter = o0.zip(o1); + + let io_iter = out_iter.zip(in_iter); + + for (((o0, o1), (&p0, &p1)), ((af_0, af_1), (bf_0, bf_1))) in + io_iter.zip(af_it.zip(bf_it)) + { + let a = 5 * (af_0[0] + af_0[2]) + 6 * af_0[1]; + let b = 5 * (bf_0[0] + bf_0[2]) + 6 * bf_0[1]; + let ao = 5 * (af_1[0] + af_1[2]) + 6 * af_1[1]; + let bo = 5 * (bf_1[0] + bf_1[2]) + 6 * bf_1[1]; + let v = (a + ao) * u32::cast_from(p0) + b + bo; + *o0 = (v + (1 << shift >> 1)) >> shift; + let vo = ao * u32::cast_from(p1) + bo; + *o1 = (vo + (1 << shifto >> 1)) >> shifto; + } + } +} + +#[inline(always)] +fn sgrproj_sum_finish( + ssq: u32, sum: u32, n: u32, one_over_n: u32, s: u32, +) -> (u32, u32) { + let bdm8 = BD - 8; + let scaled_ssq = (ssq + (1 << (2 * bdm8) >> 1)) >> (2 * bdm8); + let scaled_sum = (sum + (1 << bdm8 >> 1)) >> bdm8; + let p = (scaled_ssq * n).saturating_sub(scaled_sum * scaled_sum); + let z = (p * s + (1 << SGRPROJ_MTABLE_BITS >> 1)) >> SGRPROJ_MTABLE_BITS; + let a = if z >= 255 { + 256 + } else if z == 0 { + 1 + } else { + ((z << SGRPROJ_SGR_BITS) + z / 2) / (z + 1) + }; + let b = ((1 << SGRPROJ_SGR_BITS) - a) * sum * one_over_n; + (a, (b + (1 << SGRPROJ_RECIP_BITS >> 1)) >> SGRPROJ_RECIP_BITS) +} + +// Using an integral image, compute the sum of a square region +// SAFETY: The size of `iimg` must be at least `(y + size) * stride + x + size` +#[inline(always)] +unsafe fn get_integral_square( + iimg: &[u32], stride: usize, x: usize, y: usize, size: usize, +) -> u32 { + // Cancel out overflow in iimg by using wrapping arithmetic + let top_left = *iimg.get_unchecked(y * stride + x); + let top_right = *iimg.get_unchecked(y * stride + x + size); + let bottom_left = *iimg.get_unchecked((y + size) * stride + x); + let bottom_right = *iimg.get_unchecked((y + size) * stride + x + size); + top_left + .wrapping_add(bottom_right) + .wrapping_sub(bottom_left) + .wrapping_sub(top_right) +} + +struct VertPaddedIter<'a, T: Pixel> { + // The two sources that can be selected when clipping + deblocked: &'a Plane, + cdeffed: &'a Plane, + // x index to choice where on the row to start + x: isize, + // y index that will be mutated + y: isize, + // The index at which to terminate. Can be larger than the slice length. + end: isize, + // Used for source buffer choice/clipping. May (and regularly will) + // be negative. + stripe_begin: isize, + // Also used for source buffer choice/clipping. May specify a stripe boundary + // less than, equal to, or larger than the buffers we're accessing. + stripe_end: isize, + // Active area cropping is done by specifying a value smaller than the height + // of the plane. + crop: isize, +} + +impl<'a, T: Pixel> VertPaddedIter<'a, T> { + fn new( + cdeffed: &PlaneSlice<'a, T>, deblocked: &PlaneSlice<'a, T>, + stripe_h: usize, crop: usize, + ) -> VertPaddedIter<'a, T> { + // cdeffed and deblocked must start at the same coordinates from their + // underlying planes. Since cropping is provided via a separate params, the + // height of the underlying planes do not need to match. + assert_eq!(cdeffed.x, deblocked.x); + assert_eq!(cdeffed.y, deblocked.y); + + // To share integral images, always use the max box filter radius of 2 + let r = 2; + + // The number of rows outside the stripe are needed + let rows_above = r + 2; + let rows_below = 2; + + // Offset crop and stripe_h so they are relative to the underlying plane + // and not the plane slice. + let crop = crop as isize + deblocked.y; + let stripe_end = stripe_h as isize + deblocked.y; + + // Move y up the number rows above. + // If y is negative we repeat the first row + let y = deblocked.y - rows_above as isize; + + VertPaddedIter { + deblocked: deblocked.plane, + cdeffed: cdeffed.plane, + x: deblocked.x, + y, + end: (rows_above + stripe_h + rows_below) as isize + y, + stripe_begin: deblocked.y, + stripe_end, + crop, + } + } +} + +impl<'a, T: Pixel> Iterator for VertPaddedIter<'a, T> { + type Item = &'a [T]; + + #[inline(always)] + fn next(&mut self) -> Option { + if self.end > self.y { + // clamp before deciding the source + // clamp vertically to storage at top and passed-in height at bottom + let cropped_y = clamp(self.y, 0, self.crop - 1); + // clamp vertically to stripe limits + let ly = clamp(cropped_y, self.stripe_begin - 2, self.stripe_end + 1); + + // decide if we're vertically inside or outside the strip + let src_plane = if ly >= self.stripe_begin && ly < self.stripe_end { + self.cdeffed + } else { + self.deblocked + }; + // cannot directly return self.ps.row(row) due to lifetime issue + let range = src_plane.row_range(self.x, ly); + self.y += 1; + Some(&src_plane.data[range]) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.end - self.y; + debug_assert!(remaining >= 0); + let remaining = remaining as usize; + + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for VertPaddedIter<'_, T> {} +impl FusedIterator for VertPaddedIter<'_, T> {} + +struct HorzPaddedIter<'a, T: Pixel> { + // Active area cropping is done using the length of the slice + slice: &'a [T], + // x index of the iterator + // When less than 0, repeat the first element. When greater than end, repeat + // the last element + index: isize, + // The index at which to terminate. Can be larger than the slice length. + end: usize, +} + +impl<'a, T: Pixel> HorzPaddedIter<'a, T> { + fn new( + slice: &'a [T], start_index: isize, width: usize, + ) -> HorzPaddedIter<'a, T> { + HorzPaddedIter { + slice, + index: start_index, + end: (width as isize + start_index) as usize, + } + } +} + +impl<'a, T: Pixel> Iterator for HorzPaddedIter<'a, T> { + type Item = &'a T; + + #[inline(always)] + fn next(&mut self) -> Option { + if self.index < self.end as isize { + // clamp to the edges of the frame + let x = clamp(self.index, 0, self.slice.len() as isize - 1) as usize; + self.index += 1; + Some(&self.slice[x]) + } else { + None + } + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + let size: usize = (self.end as isize - self.index) as usize; + (size, Some(size)) + } +} + +impl ExactSizeIterator for HorzPaddedIter<'_, T> {} +impl FusedIterator for HorzPaddedIter<'_, T> {} + +#[profiling::function] +pub fn setup_integral_image( + integral_image_buffer: &mut IntegralImageBuffer, + integral_image_stride: usize, crop_w: usize, crop_h: usize, stripe_w: usize, + stripe_h: usize, cdeffed: &PlaneSlice, deblocked: &PlaneSlice, +) { + let integral_image = &mut integral_image_buffer.integral_image; + let sq_integral_image = &mut integral_image_buffer.sq_integral_image; + + // Number of elements outside the stripe + let left_w = 4; // max radius of 2 + 2 padding + let right_w = 3; // max radius of 2 + 1 padding + + assert_eq!(cdeffed.x, deblocked.x); + + // Find how many unique elements to use to the left and right + let left_uniques = if cdeffed.x == 0 { 0 } else { left_w }; + let right_uniques = right_w.min(crop_w - stripe_w); + + // Find the total number of unique elements used + let row_uniques = left_uniques + stripe_w + right_uniques; + + // Negative start indices result in repeating the first element of the row + let start_index_x = if cdeffed.x == 0 { -(left_w as isize) } else { 0 }; + + let mut rows_iter = VertPaddedIter::new( + // Move left to encompass all the used data + &cdeffed.go_left(left_uniques), + &deblocked.go_left(left_uniques), + // since r2 uses every other row, we need an extra row if stripe_h is odd + stripe_h + (stripe_h & 1), + crop_h, + ) + .map(|row: &[T]| { + HorzPaddedIter::new( + // Limit how many unique elements we use + &row[..row_uniques], + start_index_x, + left_w + stripe_w + right_w, + ) + }); + + // Setup the first row + { + let mut sum: u32 = 0; + let mut sq_sum: u32 = 0; + // Remove the first row and use it outside of the main loop + let row = rows_iter.next().unwrap(); + for (src, (integral, sq_integral)) in + row.zip(integral_image.iter_mut().zip(sq_integral_image.iter_mut())) + { + let current = u32::cast_from(*src); + + // Wrap adds to prevent undefined behaviour on overflow. Overflow is + // cancelled out when calculating the sum of a region. + sum = sum.wrapping_add(current); + *integral = sum; + sq_sum = sq_sum.wrapping_add(current * current); + *sq_integral = sq_sum; + } + } + // Calculate all other rows + let mut integral_slice = &mut integral_image[..]; + let mut sq_integral_slice = &mut sq_integral_image[..]; + for row in rows_iter { + let mut sum: u32 = 0; + let mut sq_sum: u32 = 0; + + // Split the data between the previous row and future rows. + // This allows us to mutate the current row while accessing the + // previous row. + let (integral_row_prev, integral_row) = + integral_slice.split_at_mut(integral_image_stride); + let (sq_integral_row_prev, sq_integral_row) = + sq_integral_slice.split_at_mut(integral_image_stride); + for ( + src, + ((integral_above, sq_integral_above), (integral, sq_integral)), + ) in row.zip( + integral_row_prev + .iter() + .zip(sq_integral_row_prev.iter()) + .zip(integral_row.iter_mut().zip(sq_integral_row.iter_mut())), + ) { + let current = u32::cast_from(*src); + // Wrap adds to prevent undefined behaviour on overflow. Overflow is + // cancelled out when calculating the sum of a region. + sum = sum.wrapping_add(current); + *integral = sum.wrapping_add(*integral_above); + sq_sum = sq_sum.wrapping_add(current * current); + *sq_integral = sq_sum.wrapping_add(*sq_integral_above); + } + + // The current row also contains all future rows. Replacing the slice with + // it moves down a row. + integral_slice = integral_row; + sq_integral_slice = sq_integral_row; + } +} + +#[profiling::function] +pub fn sgrproj_stripe_filter( + set: u8, xqd: [i8; 2], fi: &FrameInvariants, + integral_image_buffer: &IntegralImageBuffer, integral_image_stride: usize, + cdeffed: &PlaneSlice, out: &mut PlaneRegionMut, +) { + let &Rect { width: stripe_w, height: stripe_h, .. } = out.rect(); + let mut a_r2: [[u32; IMAGE_WIDTH_MAX + 2]; 2] = + [[0; IMAGE_WIDTH_MAX + 2]; 2]; + let mut b_r2: [[u32; IMAGE_WIDTH_MAX + 2]; 2] = + [[0; IMAGE_WIDTH_MAX + 2]; 2]; + let mut f_r2_0: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + let mut f_r2_1: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + let mut a_r1: [[u32; IMAGE_WIDTH_MAX + 2]; 3] = + [[0; IMAGE_WIDTH_MAX + 2]; 3]; + let mut b_r1: [[u32; IMAGE_WIDTH_MAX + 2]; 3] = + [[0; IMAGE_WIDTH_MAX + 2]; 3]; + let mut f_r1: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + + let s_r2: u32 = SGRPROJ_PARAMS_S[set as usize][0]; + let s_r1: u32 = SGRPROJ_PARAMS_S[set as usize][1]; + + let fn_ab_r1 = match fi.sequence.bit_depth { + 8 => sgrproj_box_ab_r1::<8>, + 10 => sgrproj_box_ab_r1::<10>, + 12 => sgrproj_box_ab_r1::<12>, + _ => unimplemented!(), + }; + let fn_ab_r2 = match fi.sequence.bit_depth { + 8 => sgrproj_box_ab_r2::<8>, + 10 => sgrproj_box_ab_r2::<10>, + 12 => sgrproj_box_ab_r2::<12>, + _ => unimplemented!(), + }; + + /* prime the intermediate arrays */ + // One oddness about the radius=2 intermediate array computations that + // the spec doesn't make clear: Although the spec defines computation + // of every row (of a, b and f), only half of the rows (every-other + // row) are actually used. + let integral_image = &integral_image_buffer.integral_image; + let sq_integral_image = &integral_image_buffer.sq_integral_image; + if s_r2 > 0 { + fn_ab_r2( + &mut a_r2[0], + &mut b_r2[0], + integral_image, + sq_integral_image, + integral_image_stride, + 0, + stripe_w, + s_r2, + fi.cpu_feature_level, + ); + } + if s_r1 > 0 { + let integral_image_offset = integral_image_stride + 1; + fn_ab_r1( + &mut a_r1[0], + &mut b_r1[0], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + integral_image_stride, + 0, + stripe_w, + s_r1, + fi.cpu_feature_level, + ); + fn_ab_r1( + &mut a_r1[1], + &mut b_r1[1], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + integral_image_stride, + 1, + stripe_w, + s_r1, + fi.cpu_feature_level, + ); + } + + /* iterate by row */ + // Increment by two to handle the use of even rows by r=2 and run a nested + // loop to handle increments of one. + for y in (0..stripe_h).step_by(2) { + // get results to use y and y+1 + let f_r2_ab: [&[u32]; 2] = if s_r2 > 0 { + fn_ab_r2( + &mut a_r2[(y / 2 + 1) % 2], + &mut b_r2[(y / 2 + 1) % 2], + integral_image, + sq_integral_image, + integral_image_stride, + y + 2, + stripe_w, + s_r2, + fi.cpu_feature_level, + ); + let ap0: [&[u32]; 2] = [&a_r2[(y / 2) % 2], &a_r2[(y / 2 + 1) % 2]]; + let bp0: [&[u32]; 2] = [&b_r2[(y / 2) % 2], &b_r2[(y / 2 + 1) % 2]]; + sgrproj_box_f_r2( + &ap0, + &bp0, + &mut f_r2_0, + &mut f_r2_1, + y, + stripe_w, + cdeffed, + fi.cpu_feature_level, + ); + [&f_r2_0, &f_r2_1] + } else { + sgrproj_box_f_r0( + &mut f_r2_0, + y, + stripe_w, + cdeffed, + fi.cpu_feature_level, + ); + // share results for both rows + [&f_r2_0, &f_r2_0] + }; + for dy in 0..(2.min(stripe_h - y)) { + let y = y + dy; + if s_r1 > 0 { + let integral_image_offset = integral_image_stride + 1; + fn_ab_r1( + &mut a_r1[(y + 2) % 3], + &mut b_r1[(y + 2) % 3], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + integral_image_stride, + y + 2, + stripe_w, + s_r1, + fi.cpu_feature_level, + ); + let ap1: [&[u32]; 3] = + [&a_r1[y % 3], &a_r1[(y + 1) % 3], &a_r1[(y + 2) % 3]]; + let bp1: [&[u32]; 3] = + [&b_r1[y % 3], &b_r1[(y + 1) % 3], &b_r1[(y + 2) % 3]]; + sgrproj_box_f_r1( + &ap1, + &bp1, + &mut f_r1, + y, + stripe_w, + cdeffed, + fi.cpu_feature_level, + ); + } else { + sgrproj_box_f_r0( + &mut f_r1, + y, + stripe_w, + cdeffed, + fi.cpu_feature_level, + ); + } + + /* apply filter */ + let w0 = xqd[0] as i32; + let w1 = xqd[1] as i32; + let w2 = (1 << SGRPROJ_PRJ_BITS) - w0 - w1; + + let line = &cdeffed[y]; + + #[inline(always)] + fn apply_filter( + out: &mut [U], line: &[U], f_r1: &[u32], f_r2_ab: &[u32], + stripe_w: usize, bit_depth: usize, w0: i32, w1: i32, w2: i32, + ) { + let line_it = line[..stripe_w].iter(); + let f_r2_ab_it = f_r2_ab[..stripe_w].iter(); + let f_r1_it = f_r1[..stripe_w].iter(); + let out_it = out[..stripe_w].iter_mut(); + + for ((o, &u), (&f_r2_ab, &f_r1)) in + out_it.zip(line_it).zip(f_r2_ab_it.zip(f_r1_it)) + { + let u = i32::cast_from(u) << SGRPROJ_RST_BITS; + let v = w0 * f_r2_ab as i32 + w1 * u + w2 * f_r1 as i32; + let s = (v + (1 << (SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) >> 1)) + >> (SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS); + *o = U::cast_from(clamp(s, 0, (1 << bit_depth) - 1)); + } + } + + apply_filter( + &mut out[y], + line, + &f_r1, + f_r2_ab[dy], + stripe_w, + fi.sequence.bit_depth, + w0, + w1, + w2, + ); + } + } +} + +// Frame inputs below aren't all equal, and will change as work +// continues. There's no deblocked reconstruction available at this +// point of RDO, so we use the non-deblocked reconstruction, cdef and +// input. The input can be a full-sized frame. Cdef input is a partial +// frame constructed specifically for RDO. + +// For simplicity, this ignores stripe segmentation (it's possible the +// extra complexity isn't worth it and we'll ignore stripes +// permanently during RDO, but that's not been tested yet). Data +// access inside the cdef frame is monolithic and clipped to the cdef +// borders. + +// Input params follow the same rules as sgrproj_stripe_filter. +// Inputs are relative to the colocated slice views. +#[profiling::function] +pub fn sgrproj_solve( + set: u8, fi: &FrameInvariants, + integral_image_buffer: &IntegralImageBuffer, input: &PlaneRegion<'_, T>, + cdeffed: &PlaneSlice, cdef_w: usize, cdef_h: usize, +) -> (i8, i8) { + let mut a_r2: [[u32; IMAGE_WIDTH_MAX + 2]; 2] = + [[0; IMAGE_WIDTH_MAX + 2]; 2]; + let mut b_r2: [[u32; IMAGE_WIDTH_MAX + 2]; 2] = + [[0; IMAGE_WIDTH_MAX + 2]; 2]; + let mut f_r2_0: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + let mut f_r2_1: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + let mut a_r1: [[u32; IMAGE_WIDTH_MAX + 2]; 3] = + [[0; IMAGE_WIDTH_MAX + 2]; 3]; + let mut b_r1: [[u32; IMAGE_WIDTH_MAX + 2]; 3] = + [[0; IMAGE_WIDTH_MAX + 2]; 3]; + let mut f_r1: [u32; IMAGE_WIDTH_MAX] = [0; IMAGE_WIDTH_MAX]; + + let s_r2: u32 = SGRPROJ_PARAMS_S[set as usize][0]; + let s_r1: u32 = SGRPROJ_PARAMS_S[set as usize][1]; + + let mut h: [[f64; 2]; 2] = [[0., 0.], [0., 0.]]; + let mut c: [f64; 2] = [0., 0.]; + + let fn_ab_r1 = match fi.sequence.bit_depth { + 8 => sgrproj_box_ab_r1::<8>, + 10 => sgrproj_box_ab_r1::<10>, + 12 => sgrproj_box_ab_r1::<12>, + _ => unimplemented!(), + }; + let fn_ab_r2 = match fi.sequence.bit_depth { + 8 => sgrproj_box_ab_r2::<8>, + 10 => sgrproj_box_ab_r2::<10>, + 12 => sgrproj_box_ab_r2::<12>, + _ => unimplemented!(), + }; + + /* prime the intermediate arrays */ + // One oddness about the radius=2 intermediate array computations that + // the spec doesn't make clear: Although the spec defines computation + // of every row (of a, b and f), only half of the rows (every-other + // row) are actually used. + let integral_image = &integral_image_buffer.integral_image; + let sq_integral_image = &integral_image_buffer.sq_integral_image; + if s_r2 > 0 { + fn_ab_r2( + &mut a_r2[0], + &mut b_r2[0], + integral_image, + sq_integral_image, + SOLVE_IMAGE_STRIDE, + 0, + cdef_w, + s_r2, + fi.cpu_feature_level, + ); + } + if s_r1 > 0 { + let integral_image_offset = SOLVE_IMAGE_STRIDE + 1; + fn_ab_r1( + &mut a_r1[0], + &mut b_r1[0], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + SOLVE_IMAGE_STRIDE, + 0, + cdef_w, + s_r1, + fi.cpu_feature_level, + ); + fn_ab_r1( + &mut a_r1[1], + &mut b_r1[1], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + SOLVE_IMAGE_STRIDE, + 1, + cdef_w, + s_r1, + fi.cpu_feature_level, + ); + } + + /* iterate by row */ + // Increment by two to handle the use of even rows by r=2 and run a nested + // loop to handle increments of one. + for y in (0..cdef_h).step_by(2) { + // get results to use y and y+1 + let f_r2_01: [&[u32]; 2] = if s_r2 > 0 { + fn_ab_r2( + &mut a_r2[(y / 2 + 1) % 2], + &mut b_r2[(y / 2 + 1) % 2], + integral_image, + sq_integral_image, + SOLVE_IMAGE_STRIDE, + y + 2, + cdef_w, + s_r2, + fi.cpu_feature_level, + ); + let ap0: [&[u32]; 2] = [&a_r2[(y / 2) % 2], &a_r2[(y / 2 + 1) % 2]]; + let bp0: [&[u32]; 2] = [&b_r2[(y / 2) % 2], &b_r2[(y / 2 + 1) % 2]]; + sgrproj_box_f_r2( + &ap0, + &bp0, + &mut f_r2_0, + &mut f_r2_1, + y, + cdef_w, + cdeffed, + fi.cpu_feature_level, + ); + [&f_r2_0, &f_r2_1] + } else { + sgrproj_box_f_r0(&mut f_r2_0, y, cdef_w, cdeffed, fi.cpu_feature_level); + // share results for both rows + [&f_r2_0, &f_r2_0] + }; + for dy in 0..(2.min(cdef_h - y)) { + let y = y + dy; + if s_r1 > 0 { + let integral_image_offset = SOLVE_IMAGE_STRIDE + 1; + fn_ab_r1( + &mut a_r1[(y + 2) % 3], + &mut b_r1[(y + 2) % 3], + &integral_image[integral_image_offset..], + &sq_integral_image[integral_image_offset..], + SOLVE_IMAGE_STRIDE, + y + 2, + cdef_w, + s_r1, + fi.cpu_feature_level, + ); + let ap1: [&[u32]; 3] = + [&a_r1[y % 3], &a_r1[(y + 1) % 3], &a_r1[(y + 2) % 3]]; + let bp1: [&[u32]; 3] = + [&b_r1[y % 3], &b_r1[(y + 1) % 3], &b_r1[(y + 2) % 3]]; + sgrproj_box_f_r1( + &ap1, + &bp1, + &mut f_r1, + y, + cdef_w, + cdeffed, + fi.cpu_feature_level, + ); + } else { + sgrproj_box_f_r0(&mut f_r1, y, cdef_w, cdeffed, fi.cpu_feature_level); + } + + #[inline(always)] + fn process_line( + h: &mut [[f64; 2]; 2], c: &mut [f64; 2], cdeffed: &[T], input: &[T], + f_r1: &[u32], f_r2_ab: &[u32], cdef_w: usize, + ) { + let cdeffed_it = cdeffed[..cdef_w].iter(); + let input_it = input[..cdef_w].iter(); + let f_r2_ab_it = f_r2_ab[..cdef_w].iter(); + let f_r1_it = f_r1[..cdef_w].iter(); + + #[derive(Debug, Copy, Clone)] + struct Sums { + h: [[i64; 2]; 2], + c: [i64; 2], + } + + let sums: Sums = cdeffed_it + .zip(input_it) + .zip(f_r2_ab_it.zip(f_r1_it)) + .map(|((&u, &i), (&f2, &f1))| { + let u = i32::cast_from(u) << SGRPROJ_RST_BITS; + let s = (i32::cast_from(i) << SGRPROJ_RST_BITS) - u; + let f2 = f2 as i32 - u; + let f1 = f1 as i32 - u; + (s as i64, f1 as i64, f2 as i64) + }) + .fold(Sums { h: [[0; 2]; 2], c: [0; 2] }, |sums, (s, f1, f2)| { + let mut ret: Sums = sums; + ret.h[0][0] += f2 * f2; + ret.h[1][1] += f1 * f1; + ret.h[0][1] += f1 * f2; + ret.c[0] += f2 * s; + ret.c[1] += f1 * s; + ret + }); + + h[0][0] += sums.h[0][0] as f64; + h[1][1] += sums.h[1][1] as f64; + h[0][1] += sums.h[0][1] as f64; + c[0] += sums.c[0] as f64; + c[1] += sums.c[1] as f64; + } + + process_line( + &mut h, + &mut c, + &cdeffed[y], + &input[y], + &f_r1, + f_r2_01[dy], + cdef_w, + ); + } + } + + // this is lifted almost in-tact from libaom + let n = cdef_w as f64 * cdef_h as f64; + h[0][0] /= n; + h[0][1] /= n; + h[1][1] /= n; + h[1][0] = h[0][1]; + c[0] *= (1 << SGRPROJ_PRJ_BITS) as f64 / n; + c[1] *= (1 << SGRPROJ_PRJ_BITS) as f64 / n; + let (xq0, xq1) = if s_r2 == 0 { + // H matrix is now only the scalar h[1][1] + // C vector is now only the scalar c[1] + if h[1][1] == 0. { + (0, 0) + } else { + (0, (c[1] / h[1][1]).round() as i32) + } + } else if s_r1 == 0 { + // H matrix is now only the scalar h[0][0] + // C vector is now only the scalar c[0] + if h[0][0] == 0. { + (0, 0) + } else { + ((c[0] / h[0][0]).round() as i32, 0) + } + } else { + let det = h[0][0].mul_add(h[1][1], -h[0][1] * h[1][0]); + if det == 0. { + (0, 0) + } else { + // If scaling up dividend would overflow, instead scale down the divisor + let div1 = h[1][1].mul_add(c[0], -h[0][1] * c[1]); + let div2 = h[0][0].mul_add(c[1], -h[1][0] * c[0]); + ((div1 / det).round() as i32, (div2 / det).round() as i32) + } + }; + { + let xqd0 = + clamp(xq0, SGRPROJ_XQD_MIN[0] as i32, SGRPROJ_XQD_MAX[0] as i32); + let xqd1 = clamp( + (1 << SGRPROJ_PRJ_BITS) - xqd0 - xq1, + SGRPROJ_XQD_MIN[1] as i32, + SGRPROJ_XQD_MAX[1] as i32, + ); + (xqd0 as i8, xqd1 as i8) + } +} + +#[profiling::function] +fn wiener_stripe_filter( + coeffs: [[i8; 3]; 2], fi: &FrameInvariants, crop_w: usize, crop_h: usize, + stripe_w: usize, stripe_h: usize, stripe_x: usize, stripe_y: isize, + cdeffed: &Plane, deblocked: &Plane, out: &mut Plane, +) { + let bit_depth = fi.sequence.bit_depth; + let round_h = if bit_depth == 12 { 5 } else { 3 }; + let round_v = if bit_depth == 12 { 9 } else { 11 }; + let offset = 1 << (bit_depth + WIENER_BITS - round_h - 1); + let limit = (1 << (bit_depth + 1 + WIENER_BITS - round_h)) - 1; + + let mut coeffs_ = [[0; 3]; 2]; + for i in 0..2 { + for j in 0..3 { + coeffs_[i][j] = i32::from(coeffs[i][j]); + } + } + + let mut work: [i32; SB_SIZE + 7] = [0; SB_SIZE + 7]; + let vfilter: [i32; 7] = [ + coeffs_[0][0], + coeffs_[0][1], + coeffs_[0][2], + 128 - 2 * (coeffs_[0][0] + coeffs_[0][1] + coeffs_[0][2]), + coeffs_[0][2], + coeffs_[0][1], + coeffs_[0][0], + ]; + let hfilter: [i32; 7] = [ + coeffs_[1][0], + coeffs_[1][1], + coeffs_[1][2], + 128 - 2 * (coeffs_[1][0] + coeffs_[1][1] + coeffs_[1][2]), + coeffs_[1][2], + coeffs_[1][1], + coeffs_[1][0], + ]; + + // unlike x, our y can be negative to start as the first stripe + // starts off the top of the frame by 8 pixels, and can also run off the end of the frame + let start_wi = if stripe_y < 0 { -stripe_y } else { 0 } as usize; + let start_yi = if stripe_y < 0 { 0 } else { stripe_y } as usize; + let end_i = cmp::max( + 0, + if stripe_h as isize + stripe_y > crop_h as isize { + crop_h as isize - stripe_y - start_wi as isize + } else { + stripe_h as isize - start_wi as isize + }, + ) as usize; + + let mut out_slice = + out.mut_slice(PlaneOffset { x: 0, y: start_yi as isize }); + + for xi in stripe_x..stripe_x + stripe_w { + let n = cmp::min(7, crop_w as isize + 3 - xi as isize); + for yi in stripe_y - 3..stripe_y + stripe_h as isize + 4 { + let mut acc = 0; + let src = if yi < stripe_y { + let ly = cmp::max(clamp(yi, 0, crop_h as isize - 1), stripe_y - 2); + deblocked.row(ly) + } else if yi < stripe_y + stripe_h as isize { + let ly = clamp(yi, 0, crop_h as isize - 1); + cdeffed.row(ly) + } else { + let ly = cmp::min( + clamp(yi, 0, crop_h as isize - 1), + stripe_y + stripe_h as isize + 1, + ); + deblocked.row(ly) + }; + let start = i32::cast_from(src[0]); + let end = i32::cast_from(src[crop_w - 1]); + for i in 0..3 - xi as isize { + acc += hfilter[i as usize] * start; + } + + let off = 3 - (xi as isize); + let s = cmp::max(0, off) as usize; + let s1 = (s as isize - off) as usize; + let n1 = (n - off) as usize; + + for (hf, &v) in hfilter[s..n as usize].iter().zip(src[s1..n1].iter()) { + acc += hf * i32::cast_from(v); + } + + for i in n..7 { + acc += hfilter[i as usize] * end; + } + + acc = (acc + (1 << round_h >> 1)) >> round_h; + work[(yi - stripe_y + 3) as usize] = clamp(acc, -offset, limit - offset); + } + + for (wi, dst) in (start_wi..start_wi + end_i) + .zip(out_slice.rows_iter_mut().map(|row| &mut row[xi]).take(end_i)) + { + let mut acc = 0; + for (i, src) in (0..7).zip(work[wi..wi + 7].iter_mut()) { + acc += vfilter[i] * *src; + } + *dst = T::cast_from(clamp( + (acc + (1 << round_v >> 1)) >> round_v, + 0, + (1 << bit_depth) - 1, + )); + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +pub struct RestorationUnit { + pub filter: RestorationFilter, +} + +#[derive(Clone, Debug)] +pub struct FrameRestorationUnits { + units: Box<[RestorationUnit]>, + pub cols: usize, + pub rows: usize, +} + +impl FrameRestorationUnits { + pub fn new(cols: usize, rows: usize) -> Self { + Self { + units: vec![RestorationUnit::default(); cols * rows].into_boxed_slice(), + cols, + rows, + } + } +} + +impl Index for FrameRestorationUnits { + type Output = [RestorationUnit]; + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + &self.units[index * self.cols..(index + 1) * self.cols] + } +} + +impl IndexMut for FrameRestorationUnits { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.units[index * self.cols..(index + 1) * self.cols] + } +} + +#[derive(Clone, Debug)] +pub struct RestorationPlaneConfig { + pub lrf_type: u8, + pub unit_size: usize, + // (1 << sb_x_shift) gives the number of superblocks horizontally or + // vertically in a restoration unit, not accounting for RU stretching + pub sb_h_shift: usize, + pub sb_v_shift: usize, + pub sb_cols: usize, // actual number of SB cols in this LRU (accounting for stretch and crop) + pub sb_rows: usize, // actual number of SB rows in this LRU (accounting for stretch and crop) + // stripe height is 64 in all cases except 4:2:0 chroma planes where + // it is 32. This is independent of all other setup parameters + pub stripe_height: usize, + pub cols: usize, + pub rows: usize, +} + +#[derive(Clone, Debug)] +pub struct RestorationPlane { + pub cfg: RestorationPlaneConfig, + pub units: FrameRestorationUnits, +} + +impl RestorationPlane { + pub fn new( + lrf_type: u8, unit_size: usize, sb_h_shift: usize, sb_v_shift: usize, + sb_cols: usize, sb_rows: usize, stripe_decimate: usize, cols: usize, + rows: usize, + ) -> RestorationPlane { + let stripe_height = if stripe_decimate != 0 { 32 } else { 64 }; + RestorationPlane { + cfg: RestorationPlaneConfig { + lrf_type, + unit_size, + sb_h_shift, + sb_v_shift, + sb_cols, + sb_rows, + stripe_height, + cols, + rows, + }, + units: FrameRestorationUnits::new(cols, rows), + } + } + + // Stripes are always 64 pixels high in a non-subsampled + // frame, and decimated from 64 pixels in chroma. When + // filtering, they are not co-located on Y with superblocks. + fn restoration_unit_index_by_stripe( + &self, stripenum: usize, rux: usize, + ) -> (usize, usize) { + ( + cmp::min(rux, self.cfg.cols - 1), + cmp::min( + stripenum * self.cfg.stripe_height / self.cfg.unit_size, + self.cfg.rows - 1, + ), + ) + } + + pub fn restoration_unit_by_stripe( + &self, stripenum: usize, rux: usize, + ) -> &RestorationUnit { + let (x, y) = self.restoration_unit_index_by_stripe(stripenum, rux); + &self.units[y][x] + } +} + +#[derive(Clone, Debug)] +pub struct RestorationState { + pub planes: [RestorationPlane; MAX_PLANES], +} + +impl RestorationState { + pub fn new(fi: &FrameInvariants, input: &Frame) -> Self { + let PlaneConfig { xdec, ydec, .. } = input.planes[1].cfg; + // stripe size is decimated in 4:2:0 (and only 4:2:0) + let stripe_uv_decimate = usize::from(xdec > 0 && ydec > 0); + let y_sb_log2 = if fi.sequence.use_128x128_superblock { 7 } else { 6 }; + let uv_sb_h_log2 = y_sb_log2 - xdec; + let uv_sb_v_log2 = y_sb_log2 - ydec; + + let (lrf_y_shift, lrf_uv_shift) = if fi.sequence.enable_large_lru + && fi.sequence.enable_restoration + { + assert!( + fi.width > 1 && fi.height > 1, + "Width and height must be higher than 1 for LRF setup" + ); + + // Specific content does affect optimal LRU size choice, but the + // quantizer in use is a surprisingly strong selector. + let lrf_base_shift = if fi.base_q_idx > 200 { + 0 // big + } else if fi.base_q_idx > 160 { + 1 + } else { + 2 // small + }; + let lrf_chroma_shift = if stripe_uv_decimate > 0 { + // 4:2:0 only + if lrf_base_shift == 2 { + 1 // smallest chroma LRU is a win at low quant + } else { + // Will a down-shifted chroma LRU eliminate stretch in chroma? + // If so, that's generally a win. + let lrf_unit_size = + 1 << (RESTORATION_TILESIZE_MAX_LOG2 - lrf_base_shift); + let unshifted_stretch = ((fi.width >> xdec) - 1) % lrf_unit_size + <= lrf_unit_size / 2 + || ((fi.height >> ydec) - 1) % lrf_unit_size <= lrf_unit_size / 2; + let shifted_stretch = ((fi.width >> xdec) - 1) + % (lrf_unit_size >> 1) + <= lrf_unit_size / 4 + || ((fi.height >> ydec) - 1) % (lrf_unit_size >> 1) + <= lrf_unit_size / 4; + // shift to eliminate stretch if needed, + // otherwise do not shift and save the signaling bits + usize::from(unshifted_stretch && !shifted_stretch) + } + } else { + 0 + }; + (lrf_base_shift, lrf_base_shift + lrf_chroma_shift) + } else { + // Explicit request to tie LRU size to superblock size == + // smallest possible LRU size + let lrf_y_shift = if fi.sequence.use_128x128_superblock { 1 } else { 2 }; + (lrf_y_shift, lrf_y_shift + stripe_uv_decimate) + }; + + let mut y_unit_size = 1 << (RESTORATION_TILESIZE_MAX_LOG2 - lrf_y_shift); + let mut uv_unit_size = 1 << (RESTORATION_TILESIZE_MAX_LOG2 - lrf_uv_shift); + + let tiling = fi.sequence.tiling; + // Right now we defer to tiling setup: don't choose an LRU size + // large enough that a tile is not an integer number of LRUs + // wide/high. + if tiling.cols > 1 || tiling.rows > 1 { + // despite suggestions to the contrary, tiles can be + // non-powers-of-2. + let trailing_h_zeros = tiling.tile_width_sb.trailing_zeros() as usize; + let trailing_v_zeros = tiling.tile_height_sb.trailing_zeros() as usize; + let tile_aligned_y_unit_size = + 1 << (y_sb_log2 + trailing_h_zeros.min(trailing_v_zeros)); + let tile_aligned_uv_h_unit_size = 1 << (uv_sb_h_log2 + trailing_h_zeros); + let tile_aligned_uv_v_unit_size = 1 << (uv_sb_v_log2 + trailing_v_zeros); + y_unit_size = y_unit_size.min(tile_aligned_y_unit_size); + uv_unit_size = uv_unit_size + .min(tile_aligned_uv_h_unit_size.min(tile_aligned_uv_v_unit_size)); + + // But it's actually worse: LRUs can't span tiles (in our + // one-pass design that is, spec allows it). However, the spec + // mandates the last LRU stretches forward into any + // less-than-half-LRU span of superblocks at the right and + // bottom of a frame. These superblocks may well be in a + // different tile! Even if LRUs are minimum size (one + // superblock), when the right or bottom edge of the frame is a + // superblock that's less than half the width/height of a normal + // superblock, the LRU is forced by the spec to span into it + // (and thus a different tile). Tiling is under no such + // restriction; it could decide the right/left sliver will be in + // its own tile row/column. We can't disallow the combination + // here. The tiling code will have to either prevent it or + // tolerate it. (prayer mechanic == Issue #1629). + } + + // When coding 4:2:2 and 4:4:4, spec requires Y and UV LRU sizes + // to be the same*. If they differ at this + // point, it's due to a tiling restriction enforcing a maximum + // size, so force both to the smaller value. + // + // *see sec 5.9.20, "Loop restoration params syntax". The + // bitstream provides means of coding a different UV LRU size only + // when chroma is in use and both x and y are subsampled in the + // chroma planes. + if ydec == 0 && y_unit_size != uv_unit_size { + y_unit_size = uv_unit_size.min(y_unit_size); + uv_unit_size = y_unit_size; + } + + // derive the rest + let y_unit_log2 = y_unit_size.ilog() - 1; + let uv_unit_log2 = uv_unit_size.ilog() - 1; + let y_cols = ((fi.width + (y_unit_size >> 1)) / y_unit_size).max(1); + let y_rows = ((fi.height + (y_unit_size >> 1)) / y_unit_size).max(1); + let uv_cols = ((((fi.width + (1 << xdec >> 1)) >> xdec) + + (uv_unit_size >> 1)) + / uv_unit_size) + .max(1); + let uv_rows = ((((fi.height + (1 << ydec >> 1)) >> ydec) + + (uv_unit_size >> 1)) + / uv_unit_size) + .max(1); + + RestorationState { + planes: [ + RestorationPlane::new( + RESTORE_SWITCHABLE, + y_unit_size, + y_unit_log2 - y_sb_log2, + y_unit_log2 - y_sb_log2, + fi.sb_width, + fi.sb_height, + 0, + y_cols, + y_rows, + ), + RestorationPlane::new( + RESTORE_SWITCHABLE, + uv_unit_size, + uv_unit_log2 - uv_sb_h_log2, + uv_unit_log2 - uv_sb_v_log2, + fi.sb_width, + fi.sb_height, + stripe_uv_decimate, + uv_cols, + uv_rows, + ), + RestorationPlane::new( + RESTORE_SWITCHABLE, + uv_unit_size, + uv_unit_log2 - uv_sb_h_log2, + uv_unit_log2 - uv_sb_v_log2, + fi.sb_width, + fi.sb_height, + stripe_uv_decimate, + uv_cols, + uv_rows, + ), + ], + } + } + + #[profiling::function] + pub fn lrf_filter_frame( + &mut self, out: &mut Frame, pre_cdef: &Frame, + fi: &FrameInvariants, + ) { + let cdeffed = out.clone(); + let planes = + if fi.sequence.chroma_sampling == Cs400 { 1 } else { MAX_PLANES }; + + // unlike the other loop filters that operate over the padded + // frame dimensions, restoration filtering and source pixel + // accesses are clipped to the original frame dimensions + // that's why we use fi.width and fi.height instead of PlaneConfig fields + + // number of stripes (counted according to colocated Y luma position) + let stripe_n = (fi.height + 7) / 64 + 1; + + // Buffers for the stripe filter. + let mut stripe_filter_buffer = + IntegralImageBuffer::zeroed(STRIPE_IMAGE_SIZE); + + for pli in 0..planes { + let rp = &self.planes[pli]; + let xdec = out.planes[pli].cfg.xdec; + let ydec = out.planes[pli].cfg.ydec; + let crop_w = (fi.width + (1 << xdec >> 1)) >> xdec; + let crop_h = (fi.height + (1 << ydec >> 1)) >> ydec; + + for si in 0..stripe_n { + let (stripe_start_y, stripe_size) = if si == 0 { + (0, (64 - 8) >> ydec) + } else { + let start = (si * 64 - 8) >> ydec; + ( + start as isize, + // one past, unlike spec + (64 >> ydec).min(crop_h - start), + ) + }; + + // horizontally, go rdu-by-rdu + for rux in 0..rp.cfg.cols { + // stripe x pixel locations must be clipped to frame, last may need to stretch + let x = rux * rp.cfg.unit_size; + let size = + if rux == rp.cfg.cols - 1 { crop_w - x } else { rp.cfg.unit_size }; + let ru = rp.restoration_unit_by_stripe(si, rux); + match ru.filter { + RestorationFilter::Wiener { coeffs } => { + wiener_stripe_filter( + coeffs, + fi, + crop_w, + crop_h, + size, + stripe_size, + x, + stripe_start_y, + &cdeffed.planes[pli], + &pre_cdef.planes[pli], + &mut out.planes[pli], + ); + } + RestorationFilter::Sgrproj { set, xqd } => { + if !fi.sequence.enable_cdef { + continue; + } + + setup_integral_image( + &mut stripe_filter_buffer, + STRIPE_IMAGE_STRIDE, + crop_w - x, + (crop_h as isize - stripe_start_y) as usize, + size, + stripe_size, + &cdeffed.planes[pli] + .slice(PlaneOffset { x: x as isize, y: stripe_start_y }), + &pre_cdef.planes[pli] + .slice(PlaneOffset { x: x as isize, y: stripe_start_y }), + ); + + sgrproj_stripe_filter( + set, + xqd, + fi, + &stripe_filter_buffer, + STRIPE_IMAGE_STRIDE, + &cdeffed.planes[pli] + .slice(PlaneOffset { x: x as isize, y: stripe_start_y }), + &mut out.planes[pli].region_mut(Area::Rect { + x: x as isize, + y: stripe_start_y, + width: size, + height: stripe_size, + }), + ); + } + RestorationFilter::None => { + // do nothing + } + } + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/mc.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/mc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/mc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/mc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,480 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::mc::*; + } else if #[cfg(asm_neon)] { + pub use crate::asm::aarch64::mc::*; + } else { + pub use self::rust::*; + } +} + +use crate::cpu_features::CpuFeatureLevel; +use crate::frame::*; +use crate::tiling::*; +use crate::util::*; + +use simd_helpers::cold_for_target_arch; +use std::ops; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct MotionVector { + pub row: i16, + pub col: i16, +} + +impl MotionVector { + #[inline] + pub const fn quantize_to_fullpel(self) -> Self { + Self { row: (self.row / 8) * 8, col: (self.col / 8) * 8 } + } + + #[inline] + pub const fn is_zero(self) -> bool { + self.row == 0 && self.col == 0 + } + + #[inline] + pub const fn is_valid(self) -> bool { + use crate::context::{MV_LOW, MV_UPP}; + ((MV_LOW as i16) < self.row && self.row < (MV_UPP as i16)) + && ((MV_LOW as i16) < self.col && self.col < (MV_UPP as i16)) + } +} + +impl ops::Mul for MotionVector { + type Output = MotionVector; + + #[inline] + fn mul(self, rhs: i16) -> MotionVector { + MotionVector { row: self.row * rhs, col: self.col * rhs } + } +} + +impl ops::Mul for MotionVector { + type Output = MotionVector; + + #[inline] + fn mul(self, rhs: u16) -> MotionVector { + MotionVector { row: self.row * rhs as i16, col: self.col * rhs as i16 } + } +} + +impl ops::Shr for MotionVector { + type Output = MotionVector; + + #[inline] + fn shr(self, rhs: u8) -> MotionVector { + MotionVector { row: self.row >> rhs, col: self.col >> rhs } + } +} + +impl ops::Shl for MotionVector { + type Output = MotionVector; + + #[inline] + fn shl(self, rhs: u8) -> MotionVector { + MotionVector { row: self.row << rhs, col: self.col << rhs } + } +} + +impl ops::Add for MotionVector { + type Output = MotionVector; + + #[inline] + fn add(self, rhs: MotionVector) -> MotionVector { + MotionVector { row: self.row + rhs.row, col: self.col + rhs.col } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +#[allow(unused)] +pub enum FilterMode { + REGULAR = 0, + SMOOTH = 1, + SHARP = 2, + BILINEAR = 3, + SWITCHABLE = 4, +} + +pub const SUBPEL_FILTER_SIZE: usize = 8; + +const SUBPEL_FILTERS: [[[i32; SUBPEL_FILTER_SIZE]; 16]; 6] = [ + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 2, -6, 126, 8, -2, 0, 0], + [0, 2, -10, 122, 18, -4, 0, 0], + [0, 2, -12, 116, 28, -8, 2, 0], + [0, 2, -14, 110, 38, -10, 2, 0], + [0, 2, -14, 102, 48, -12, 2, 0], + [0, 2, -16, 94, 58, -12, 2, 0], + [0, 2, -14, 84, 66, -12, 2, 0], + [0, 2, -14, 76, 76, -14, 2, 0], + [0, 2, -12, 66, 84, -14, 2, 0], + [0, 2, -12, 58, 94, -16, 2, 0], + [0, 2, -12, 48, 102, -14, 2, 0], + [0, 2, -10, 38, 110, -14, 2, 0], + [0, 2, -8, 28, 116, -12, 2, 0], + [0, 0, -4, 18, 122, -10, 2, 0], + [0, 0, -2, 8, 126, -6, 2, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 2, 28, 62, 34, 2, 0, 0], + [0, 0, 26, 62, 36, 4, 0, 0], + [0, 0, 22, 62, 40, 4, 0, 0], + [0, 0, 20, 60, 42, 6, 0, 0], + [0, 0, 18, 58, 44, 8, 0, 0], + [0, 0, 16, 56, 46, 10, 0, 0], + [0, -2, 16, 54, 48, 12, 0, 0], + [0, -2, 14, 52, 52, 14, -2, 0], + [0, 0, 12, 48, 54, 16, -2, 0], + [0, 0, 10, 46, 56, 16, 0, 0], + [0, 0, 8, 44, 58, 18, 0, 0], + [0, 0, 6, 42, 60, 20, 0, 0], + [0, 0, 4, 40, 62, 22, 0, 0], + [0, 0, 4, 36, 62, 26, 0, 0], + [0, 0, 2, 34, 62, 28, 2, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [-2, 2, -6, 126, 8, -2, 2, 0], + [-2, 6, -12, 124, 16, -6, 4, -2], + [-2, 8, -18, 120, 26, -10, 6, -2], + [-4, 10, -22, 116, 38, -14, 6, -2], + [-4, 10, -22, 108, 48, -18, 8, -2], + [-4, 10, -24, 100, 60, -20, 8, -2], + [-4, 10, -24, 90, 70, -22, 10, -2], + [-4, 12, -24, 80, 80, -24, 12, -4], + [-2, 10, -22, 70, 90, -24, 10, -4], + [-2, 8, -20, 60, 100, -24, 10, -4], + [-2, 8, -18, 48, 108, -22, 10, -4], + [-2, 6, -14, 38, 116, -22, 10, -4], + [-2, 6, -10, 26, 120, -18, 8, -2], + [-2, 4, -6, 16, 124, -12, 6, -2], + [0, 2, -2, 8, 126, -6, 2, -2], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, 0, 120, 8, 0, 0, 0], + [0, 0, 0, 112, 16, 0, 0, 0], + [0, 0, 0, 104, 24, 0, 0, 0], + [0, 0, 0, 96, 32, 0, 0, 0], + [0, 0, 0, 88, 40, 0, 0, 0], + [0, 0, 0, 80, 48, 0, 0, 0], + [0, 0, 0, 72, 56, 0, 0, 0], + [0, 0, 0, 64, 64, 0, 0, 0], + [0, 0, 0, 56, 72, 0, 0, 0], + [0, 0, 0, 48, 80, 0, 0, 0], + [0, 0, 0, 40, 88, 0, 0, 0], + [0, 0, 0, 32, 96, 0, 0, 0], + [0, 0, 0, 24, 104, 0, 0, 0], + [0, 0, 0, 16, 112, 0, 0, 0], + [0, 0, 0, 8, 120, 0, 0, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, -4, 126, 8, -2, 0, 0], + [0, 0, -8, 122, 18, -4, 0, 0], + [0, 0, -10, 116, 28, -6, 0, 0], + [0, 0, -12, 110, 38, -8, 0, 0], + [0, 0, -12, 102, 48, -10, 0, 0], + [0, 0, -14, 94, 58, -10, 0, 0], + [0, 0, -12, 84, 66, -10, 0, 0], + [0, 0, -12, 76, 76, -12, 0, 0], + [0, 0, -10, 66, 84, -12, 0, 0], + [0, 0, -10, 58, 94, -14, 0, 0], + [0, 0, -10, 48, 102, -12, 0, 0], + [0, 0, -8, 38, 110, -12, 0, 0], + [0, 0, -6, 28, 116, -10, 0, 0], + [0, 0, -4, 18, 122, -8, 0, 0], + [0, 0, -2, 8, 126, -4, 0, 0], + ], + [ + [0, 0, 0, 128, 0, 0, 0, 0], + [0, 0, 30, 62, 34, 2, 0, 0], + [0, 0, 26, 62, 36, 4, 0, 0], + [0, 0, 22, 62, 40, 4, 0, 0], + [0, 0, 20, 60, 42, 6, 0, 0], + [0, 0, 18, 58, 44, 8, 0, 0], + [0, 0, 16, 56, 46, 10, 0, 0], + [0, 0, 14, 54, 48, 12, 0, 0], + [0, 0, 12, 52, 52, 12, 0, 0], + [0, 0, 12, 48, 54, 14, 0, 0], + [0, 0, 10, 46, 56, 16, 0, 0], + [0, 0, 8, 44, 58, 18, 0, 0], + [0, 0, 6, 42, 60, 20, 0, 0], + [0, 0, 4, 40, 62, 22, 0, 0], + [0, 0, 4, 36, 62, 26, 0, 0], + [0, 0, 2, 34, 62, 30, 0, 0], + ], +]; + +pub(crate) mod rust { + use super::*; + use num_traits::*; + + unsafe fn run_filter>( + src: *const T, stride: usize, filter: [i32; 8], + ) -> i32 { + filter + .iter() + .enumerate() + .map(|(i, f)| { + let p = src.add(i * stride); + f * (*p).as_() + }) + .sum::() + } + + fn get_filter( + mode: FilterMode, frac: i32, length: usize, + ) -> [i32; SUBPEL_FILTER_SIZE] { + let filter_idx = if mode == FilterMode::BILINEAR || length > 4 { + mode as usize + } else { + (mode as usize).min(1) + 4 + }; + SUBPEL_FILTERS[filter_idx][frac as usize] + } + + #[cold_for_target_arch("x86_64")] + pub fn put_8tap( + dst: &mut PlaneRegionMut<'_, T>, src: PlaneSlice<'_, T>, width: usize, + height: usize, col_frac: i32, row_frac: i32, mode_x: FilterMode, + mode_y: FilterMode, bit_depth: usize, _cpu: CpuFeatureLevel, + ) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + let ref_stride = src.plane.cfg.stride; + let y_filter = get_filter(mode_y, row_frac, height); + let x_filter = get_filter(mode_x, col_frac, width); + let max_sample_val = (1 << bit_depth) - 1; + let intermediate_bits = 4 - if bit_depth == 12 { 2 } else { 0 }; + match (col_frac, row_frac) { + (0, 0) => { + for r in 0..height { + let src_slice = &src[r]; + let dst_slice = &mut dst[r]; + dst_slice[..width].copy_from_slice(&src_slice[..width]); + } + } + (0, _) => { + let offset_slice = src.go_up(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + let dst_slice = &mut dst[r]; + for c in 0..width { + dst_slice[c] = T::cast_from( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter(src_slice[c..].as_ptr(), ref_stride, y_filter) + }, + 7, + ) + .clamp(0, max_sample_val), + ); + } + } + } + (_, 0) => { + let offset_slice = src.go_left(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + let dst_slice = &mut dst[r]; + for c in 0..width { + dst_slice[c] = T::cast_from( + round_shift( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ), + intermediate_bits, + ) + .clamp(0, max_sample_val), + ); + } + } + } + (_, _) => { + let mut intermediate: [i16; 8 * (128 + 7)] = [0; 8 * (128 + 7)]; + + let offset_slice = src.go_left(3).go_up(3); + for cg in (0..width).step_by(8) { + for r in 0..height + 7 { + let src_slice = &offset_slice[r]; + for c in cg..(cg + 8).min(width) { + intermediate[8 * r + (c - cg)] = round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ) as i16; + } + } + + for r in 0..height { + let dst_slice = &mut dst[r]; + for c in cg..(cg + 8).min(width) { + dst_slice[c] = T::cast_from( + round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter( + intermediate[8 * r + c - cg..].as_ptr(), + 8, + y_filter, + ) + }, + 7 + intermediate_bits, + ) + .clamp(0, max_sample_val), + ); + } + } + } + } + } + } + + // HBD output interval is [-20588, 36956] (10-bit), [-20602, 36983] (12-bit) + // Subtract PREP_BIAS to ensure result fits in i16 and matches dav1d assembly + const PREP_BIAS: i32 = 8192; + + #[cold_for_target_arch("x86_64")] + pub fn prep_8tap( + tmp: &mut [i16], src: PlaneSlice<'_, T>, width: usize, height: usize, + col_frac: i32, row_frac: i32, mode_x: FilterMode, mode_y: FilterMode, + bit_depth: usize, _cpu: CpuFeatureLevel, + ) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + let ref_stride = src.plane.cfg.stride; + let y_filter = get_filter(mode_y, row_frac, height); + let x_filter = get_filter(mode_x, col_frac, width); + let intermediate_bits = 4 - if bit_depth == 12 { 2 } else { 0 }; + let prep_bias = if bit_depth == 8 { 0 } else { PREP_BIAS }; + match (col_frac, row_frac) { + (0, 0) => { + for r in 0..height { + let src_slice = &src[r]; + for c in 0..width { + tmp[r * width + c] = (i16::cast_from(src_slice[c]) + << intermediate_bits) + - prep_bias as i16; + } + } + } + (0, _) => { + let offset_slice = src.go_up(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + for c in 0..width { + tmp[r * width + c] = (round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter(src_slice[c..].as_ptr(), ref_stride, y_filter) + }, + 7 - intermediate_bits, + ) - prep_bias) as i16; + } + } + } + (_, 0) => { + let offset_slice = src.go_left(3); + for r in 0..height { + let src_slice = &offset_slice[r]; + for c in 0..width { + tmp[r * width + c] = (round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ) - prep_bias) as i16; + } + } + } + (_, _) => { + let mut intermediate: [i16; 8 * (128 + 7)] = [0; 8 * (128 + 7)]; + + let offset_slice = src.go_left(3).go_up(3); + for cg in (0..width).step_by(8) { + for r in 0..height + 7 { + let src_slice = &offset_slice[r]; + for c in cg..(cg + 8).min(width) { + intermediate[8 * r + (c - cg)] = round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { run_filter(src_slice[c..].as_ptr(), 1, x_filter) }, + 7 - intermediate_bits, + ) as i16; + } + } + + for r in 0..height { + for c in cg..(cg + 8).min(width) { + tmp[r * width + c] = (round_shift( + // SAFETY: We pass this a raw pointer, but it's created from a + // checked slice, so we are safe. + unsafe { + run_filter( + intermediate[8 * r + c - cg..].as_ptr(), + 8, + y_filter, + ) + }, + 7, + ) - prep_bias) as i16; + } + } + } + } + } + } + + #[cold_for_target_arch("x86_64")] + pub fn mc_avg( + dst: &mut PlaneRegionMut<'_, T>, tmp1: &[i16], tmp2: &[i16], width: usize, + height: usize, bit_depth: usize, _cpu: CpuFeatureLevel, + ) { + // The assembly only supports even heights and valid uncropped widths + assert_eq!(height & 1, 0); + assert!(width.is_power_of_two() && (2..=128).contains(&width)); + + let max_sample_val = (1 << bit_depth) - 1; + let intermediate_bits = 4 - if bit_depth == 12 { 2 } else { 0 }; + let prep_bias = if bit_depth == 8 { 0 } else { PREP_BIAS * 2 }; + for r in 0..height { + let dst_slice = &mut dst[r]; + for c in 0..width { + dst_slice[c] = T::cast_from( + round_shift( + tmp1[r * width + c] as i32 + + tmp2[r * width + c] as i32 + + prep_bias, + intermediate_bits + 1, + ) + .clamp(0, max_sample_val), + ); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/me.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/me.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/me.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/me.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1523 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::api::InterConfig; +use crate::context::{ + BlockOffset, PlaneBlockOffset, SuperBlockOffset, TileBlockOffset, + TileSuperBlockOffset, MAX_SB_SIZE_LOG2, MIB_SIZE_LOG2, MI_SIZE, + MI_SIZE_LOG2, SB_SIZE, +}; +use crate::dist::*; +use crate::frame::*; +use crate::mc::MotionVector; +use crate::partition::*; +use crate::predict::PredictionMode; +use crate::tiling::*; +use crate::util::ILog; +use crate::util::{clamp, Pixel}; +use crate::FrameInvariants; + +use arrayvec::*; +use std::ops::{Index, IndexMut}; +use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; + +#[derive(Debug, Copy, Clone, Default)] +pub struct MEStats { + pub mv: MotionVector, + /// sad value, on the scale of a 128x128 block + pub normalized_sad: u32, +} + +#[derive(Debug, Clone)] +pub struct FrameMEStats { + stats: Box<[MEStats]>, + pub cols: usize, + pub rows: usize, +} + +/// cbindgen:ignore +pub type RefMEStats = Arc>; +/// cbindgen:ignore +pub type ReadGuardMEStats<'a> = + RwLockReadGuard<'a, [FrameMEStats; REF_FRAMES]>; +/// cbindgen:ignore +pub type WriteGuardMEStats<'a> = + RwLockWriteGuard<'a, [FrameMEStats; REF_FRAMES]>; + +impl FrameMEStats { + #[inline] + pub fn rows_iter(&self) -> std::slice::ChunksExact<'_, MEStats> { + self.stats.chunks_exact(self.cols) + } + + pub fn new(cols: usize, rows: usize) -> Self { + Self { + // dynamic allocation: once per frame + stats: vec![MEStats::default(); cols * rows].into_boxed_slice(), + cols, + rows, + } + } + pub fn new_arc_array(cols: usize, rows: usize) -> RefMEStats { + Arc::new(RwLock::new([ + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + FrameMEStats::new(cols, rows), + ])) + } +} + +impl Index for FrameMEStats { + type Output = [MEStats]; + #[inline] + fn index(&self, index: usize) -> &Self::Output { + &self.stats[index * self.cols..(index + 1) * self.cols] + } +} + +impl IndexMut for FrameMEStats { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.stats[index * self.cols..(index + 1) * self.cols] + } +} + +/// Result of motion search. +#[derive(Debug, Copy, Clone)] +pub struct MotionSearchResult { + /// Motion vector chosen by the motion search. + pub mv: MotionVector, + /// Rate distortion data associated with `mv`. + pub rd: MVCandidateRD, +} + +impl MotionSearchResult { + /// Creates an 'empty' value. + /// + /// To be considered empty, cost is set higher than any naturally occurring + /// cost value. The idea is that comparing to any valid rd output, the search + /// result will always be replaced. + #[inline(always)] + pub fn empty() -> MotionSearchResult { + MotionSearchResult { + mv: MotionVector::default(), + rd: MVCandidateRD::empty(), + } + } + + /// Check if the value should be considered to be empty. + #[inline(always)] + const fn is_empty(&self) -> bool { + self.rd.cost == u64::MAX + } +} + +/// Holds data from computing rate distortion of a motion vector. +#[derive(Debug, Copy, Clone)] +pub struct MVCandidateRD { + /// Rate distortion cost of the motion vector. + pub cost: u64, + /// Distortion metric value for the motion vector. + pub sad: u32, +} + +impl MVCandidateRD { + /// Creates an 'empty' value. + /// + /// To be considered empty, cost is set higher than any naturally occurring + /// cost value. The idea is that comparing to any valid rd output, the search + /// result will always be replaced. + #[inline(always)] + const fn empty() -> MVCandidateRD { + MVCandidateRD { sad: u32::MAX, cost: u64::MAX } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum MVSamplingMode { + INIT, + CORNER { right: bool, bottom: bool }, +} + +pub fn estimate_tile_motion( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + inter_cfg: &InterConfig, +) { + let init_size = MIB_SIZE_LOG2; + + let mut prev_ssdec: Option = None; + for mv_size_in_b_log2 in (2..=init_size).rev() { + let init = mv_size_in_b_log2 == init_size; + + // Choose subsampling. Pass one is quarter res and pass two is at half res. + let ssdec = match init_size - mv_size_in_b_log2 { + 0 => 2, + 1 => 1, + _ => 0, + }; + + let new_subsampling = + if let Some(prev) = prev_ssdec { prev != ssdec } else { false }; + prev_ssdec = Some(ssdec); + + // 0.5 and 0.125 are a fudge factors + let lambda = (fi.me_lambda * 256.0 / (1 << (2 * ssdec)) as f64 + * if ssdec == 0 { 0.5 } else { 0.125 }) as u32; + + for sby in 0..ts.sb_height { + for sbx in 0..ts.sb_width { + let mut tested_frames_flags = 0; + for &ref_frame in inter_cfg.allowed_ref_frames() { + let frame_flag = 1 << fi.ref_frames[ref_frame.to_index()]; + if tested_frames_flags & frame_flag == frame_flag { + continue; + } + tested_frames_flags |= frame_flag; + + let tile_bo = + TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby }) + .block_offset(0, 0); + + if new_subsampling { + refine_subsampled_sb_motion( + fi, + ts, + ref_frame, + mv_size_in_b_log2 + 1, + tile_bo, + ssdec, + lambda, + ); + } + + estimate_sb_motion( + fi, + ts, + ref_frame, + mv_size_in_b_log2, + tile_bo, + init, + ssdec, + lambda, + ); + } + } + } + } +} + +fn estimate_sb_motion( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, ref_frame: RefType, + mv_size_in_b_log2: usize, tile_bo: TileBlockOffset, init: bool, ssdec: u8, + lambda: u32, +) { + let pix_offset = tile_bo.to_luma_plane_offset(); + let sb_h: usize = SB_SIZE.min(ts.height - pix_offset.y as usize); + let sb_w: usize = SB_SIZE.min(ts.width - pix_offset.x as usize); + + let mv_size = MI_SIZE << mv_size_in_b_log2; + + // Process in blocks, cropping at edges. + for y in (0..sb_h).step_by(mv_size) { + for x in (0..sb_w).step_by(mv_size) { + let corner: MVSamplingMode = if init { + MVSamplingMode::INIT + } else { + // Processing the block a size up produces data that can be used by + // the right and bottom corners. + MVSamplingMode::CORNER { + right: x & mv_size == mv_size, + bottom: y & mv_size == mv_size, + } + }; + + let sub_bo = tile_bo + .with_offset(x as isize >> MI_SIZE_LOG2, y as isize >> MI_SIZE_LOG2); + + // Clamp to frame edge, rounding up in the case of subsampling. + // The rounding makes some assumptions about how subsampling is done. + let w = mv_size.min(sb_w - x + (1 << ssdec) - 1) >> ssdec; + let h = mv_size.min(sb_h - y + (1 << ssdec) - 1) >> ssdec; + + // Run motion estimation. + // Note that the initial search (init) instructs the called function to + // perform a more extensive search. + if let Some(results) = estimate_motion( + fi, + ts, + w, + h, + sub_bo, + ref_frame, + None, + corner, + init, + ssdec, + Some(lambda), + ) { + // normalize sad to 128x128 block + let sad = (((results.rd.sad as u64) << (MAX_SB_SIZE_LOG2 * 2)) + / (w * h) as u64) as u32; + save_me_stats( + ts, + mv_size_in_b_log2, + sub_bo, + ref_frame, + MEStats { mv: results.mv, normalized_sad: sad }, + ); + } + } + } +} + +fn refine_subsampled_sb_motion( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, ref_frame: RefType, + mv_size_in_b_log2: usize, tile_bo: TileBlockOffset, ssdec: u8, lambda: u32, +) { + let pix_offset = tile_bo.to_luma_plane_offset(); + let sb_h: usize = SB_SIZE.min(ts.height - pix_offset.y as usize); + let sb_w: usize = SB_SIZE.min(ts.width - pix_offset.x as usize); + + let mv_size = MI_SIZE << mv_size_in_b_log2; + + // Process in blocks, cropping at edges. + for y in (0..sb_h).step_by(mv_size) { + for x in (0..sb_w).step_by(mv_size) { + let sub_bo = tile_bo + .with_offset(x as isize >> MI_SIZE_LOG2, y as isize >> MI_SIZE_LOG2); + + // Clamp to frame edge, rounding up in the case of subsampling. + // The rounding makes some assumptions about how subsampling is done. + let w = mv_size.min(sb_w - x + (1 << ssdec) - 1) >> ssdec; + let h = mv_size.min(sb_h - y + (1 << ssdec) - 1) >> ssdec; + + // Refine the existing motion estimate + if let Some(results) = refine_subsampled_motion_estimate( + fi, ts, w, h, sub_bo, ref_frame, ssdec, lambda, + ) { + // normalize sad to 128x128 block + let sad = (((results.rd.sad as u64) << (MAX_SB_SIZE_LOG2 * 2)) + / (w * h) as u64) as u32; + save_me_stats( + ts, + mv_size_in_b_log2, + sub_bo, + ref_frame, + MEStats { mv: results.mv, normalized_sad: sad }, + ); + } + } + } +} + +fn save_me_stats( + ts: &mut TileStateMut<'_, T>, mv_size_in_b_log2: usize, + tile_bo: TileBlockOffset, ref_frame: RefType, stats: MEStats, +) { + let size_in_b = 1 << mv_size_in_b_log2; + let tile_me_stats = &mut ts.me_stats[ref_frame.to_index()]; + let tile_bo_x_end = (tile_bo.0.x + size_in_b).min(ts.mi_width); + let tile_bo_y_end = (tile_bo.0.y + size_in_b).min(ts.mi_height); + for mi_y in tile_bo.0.y..tile_bo_y_end { + for a in tile_me_stats[mi_y][tile_bo.0.x..tile_bo_x_end].iter_mut() { + *a = stats; + } + } +} + +fn get_mv_range( + w_in_b: usize, h_in_b: usize, bo: PlaneBlockOffset, blk_w: usize, + blk_h: usize, +) -> (isize, isize, isize, isize) { + let border_w = 128 + blk_w as isize * 8; + let border_h = 128 + blk_h as isize * 8; + let mvx_min = -(bo.0.x as isize) * (8 * MI_SIZE) as isize - border_w; + let mvx_max = ((w_in_b - bo.0.x) as isize - (blk_w / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_w; + let mvy_min = -(bo.0.y as isize) * (8 * MI_SIZE) as isize - border_h; + let mvy_max = ((h_in_b - bo.0.y) as isize - (blk_h / MI_SIZE) as isize) + * (8 * MI_SIZE) as isize + + border_h; + + // + use crate::context::{MV_LOW, MV_UPP}; + ( + mvx_min.max(MV_LOW as isize + 1), + mvx_max.min(MV_UPP as isize - 1), + mvy_min.max(MV_LOW as isize + 1), + mvy_max.min(MV_UPP as isize - 1), + ) +} + +struct MotionEstimationSubsets { + min_sad: u32, + median: Option, + subset_b: ArrayVec, + subset_c: ArrayVec, +} + +impl MotionEstimationSubsets { + fn all_mvs(&self) -> ArrayVec { + let mut all = ArrayVec::new(); + if let Some(median) = self.median { + all.push(median); + } + + all.extend(self.subset_b.iter().copied()); + all.extend(self.subset_c.iter().copied()); + + all + } +} + +#[profiling::function] +fn get_subset_predictors( + tile_bo: TileBlockOffset, tile_me_stats: &TileMEStats<'_>, + frame_ref_opt: Option>, ref_frame_id: usize, + pix_w: usize, pix_h: usize, mvx_min: isize, mvx_max: isize, mvy_min: isize, + mvy_max: isize, corner: MVSamplingMode, ssdec: u8, +) -> MotionEstimationSubsets { + let mut min_sad: u32 = u32::MAX; + let mut subset_b = ArrayVec::::new(); + let mut subset_c = ArrayVec::::new(); + + // rounded up width in blocks + let w = ((pix_w << ssdec) + MI_SIZE - 1) >> MI_SIZE_LOG2; + let h = ((pix_h << ssdec) + MI_SIZE - 1) >> MI_SIZE_LOG2; + + // Get predictors from the same frame. + + let clipped_half_w = (w >> 1).min(tile_me_stats.cols() - 1 - tile_bo.0.x); + let clipped_half_h = (h >> 1).min(tile_me_stats.rows() - 1 - tile_bo.0.y); + + let mut process_cand = |stats: MEStats| -> MotionVector { + min_sad = min_sad.min(stats.normalized_sad); + let mv = stats.mv.quantize_to_fullpel(); + MotionVector { + col: clamp(mv.col as isize, mvx_min, mvx_max) as i16, + row: clamp(mv.row as isize, mvy_min, mvy_max) as i16, + } + }; + + // Sample the middle of all block edges bordering this one. + // Note: If motion vectors haven't been precomputed to a given blocksize, then + // the right and bottom edges will be duplicates of the center predictor when + // processing in raster order. + + // left + if tile_bo.0.x > 0 { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h][tile_bo.0.x - 1], + )); + } + // top + if tile_bo.0.y > 0 { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y - 1][tile_bo.0.x + clipped_half_w], + )); + } + + // Sampling far right and far bottom edges was tested, but had worse results + // without an extensive threshold test (with threshold being applied after + // checking median and the best of each subset). + + // right + if let MVSamplingMode::CORNER { right: true, bottom: _ } = corner { + if tile_bo.0.x + w < tile_me_stats.cols() { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h][tile_bo.0.x + w], + )); + } + } + // bottom + if let MVSamplingMode::CORNER { right: _, bottom: true } = corner { + if tile_bo.0.y + h < tile_me_stats.rows() { + subset_b.push(process_cand( + tile_me_stats[tile_bo.0.y + h][tile_bo.0.x + clipped_half_w], + )); + } + } + + let median = if corner != MVSamplingMode::INIT { + // Sample the center of the current block. + Some(process_cand( + tile_me_stats[tile_bo.0.y + clipped_half_h] + [tile_bo.0.x + clipped_half_w], + )) + } else if subset_b.len() != 3 { + None + } else { + let mut rows: ArrayVec = subset_b.iter().map(|&a| a.row).collect(); + let mut cols: ArrayVec = subset_b.iter().map(|&a| a.col).collect(); + rows.as_mut_slice().sort_unstable(); + cols.as_mut_slice().sort_unstable(); + Some(MotionVector { row: rows[1], col: cols[1] }) + }; + + // Zero motion vector, don't use add_cand since it skips zero vectors. + subset_b.push(MotionVector::default()); + + // EPZS subset C predictors. + // Sample the middle of bordering side of the left, right, top and bottom + // blocks of the previous frame. + // Sample the middle of this block in the previous frame. + + if let Some(frame_me_stats) = frame_ref_opt { + let prev_frame = &frame_me_stats[ref_frame_id]; + + let frame_bo = PlaneBlockOffset(BlockOffset { + x: tile_me_stats.x() + tile_bo.0.x, + y: tile_me_stats.y() + tile_bo.0.y, + }); + let clipped_half_w = (w >> 1).min(prev_frame.cols - 1 - frame_bo.0.x); + let clipped_half_h = (h >> 1).min(prev_frame.rows - 1 - frame_bo.0.y); + + // left + if frame_bo.0.x > 0 { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x - 1], + )); + } + // top + if frame_bo.0.y > 0 { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y - 1][frame_bo.0.x + clipped_half_w], + )); + } + // right + if frame_bo.0.x + w < prev_frame.cols { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x + w], + )); + } + // bottom + if frame_bo.0.y + h < prev_frame.rows { + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + h][frame_bo.0.x + clipped_half_w], + )); + } + + subset_c.push(process_cand( + prev_frame[frame_bo.0.y + clipped_half_h][frame_bo.0.x + clipped_half_w], + )); + } + + // Undo normalization to 128x128 block size + let min_sad = ((min_sad as u64 * (pix_w * pix_h) as u64) + >> (MAX_SB_SIZE_LOG2 * 2)) as u32; + + let dec_mv = |mv: MotionVector| MotionVector { + col: mv.col >> ssdec, + row: mv.row >> ssdec, + }; + let median = median.map(dec_mv); + for mv in subset_b.iter_mut() { + *mv = dec_mv(*mv); + } + for mv in subset_c.iter_mut() { + *mv = dec_mv(*mv); + } + + MotionEstimationSubsets { min_sad, median, subset_b, subset_c } +} + +pub fn estimate_motion( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, w: usize, h: usize, + tile_bo: TileBlockOffset, ref_frame: RefType, + pmv: Option<[MotionVector; 2]>, corner: MVSamplingMode, + extensive_search: bool, ssdec: u8, lambda: Option, +) -> Option { + if let Some(ref rec) = + fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] + { + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + get_mv_range(fi.w_in_b, fi.h_in_b, frame_bo, w << ssdec, h << ssdec); + + let lambda = lambda.unwrap_or({ + // 0.5 is a fudge factor + (fi.me_lambda * 256.0 * 0.5) as u32 + }); + + let global_mv = [MotionVector { row: 0, col: 0 }; 2]; + + let po = frame_bo.to_luma_plane_offset(); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + (mvx_min >> ssdec, mvx_max >> ssdec, mvy_min >> ssdec, mvy_max >> ssdec); + let po = PlaneOffset { x: po.x >> ssdec, y: po.y >> ssdec }; + let p_ref = match ssdec { + 0 => &rec.frame.planes[0], + 1 => &rec.input_hres, + 2 => &rec.input_qres, + _ => unimplemented!(), + }; + + let org_region = &match ssdec { + 0 => ts.input_tile.planes[0] + .subregion(Area::BlockStartingAt { bo: tile_bo.0 }), + 1 => ts.input_hres.region(Area::StartingAt { x: po.x, y: po.y }), + 2 => ts.input_qres.region(Area::StartingAt { x: po.x, y: po.y }), + _ => unimplemented!(), + }; + + let mut best: MotionSearchResult = full_pixel_me( + fi, + ts, + org_region, + p_ref, + tile_bo, + po, + lambda, + pmv.unwrap_or(global_mv), + w, + h, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + ref_frame, + corner, + extensive_search, + ssdec, + ); + + if let Some(pmv) = pmv { + let use_satd: bool = fi.config.speed_settings.motion.use_satd_subpel; + if use_satd { + best.rd = get_fullpel_mv_rd( + fi, + po, + org_region, + p_ref, + fi.sequence.bit_depth, + pmv, + lambda, + use_satd, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + best.mv, + ); + } + + sub_pixel_me( + fi, po, org_region, p_ref, lambda, pmv, mvx_min, mvx_max, mvy_min, + mvy_max, w, h, use_satd, &mut best, ref_frame, + ); + } + + // Scale motion vectors to full res size + best.mv = best.mv << ssdec; + + Some(best) + } else { + None + } +} + +/// Refine motion estimation that was computed one level of subsampling up. +fn refine_subsampled_motion_estimate( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, w: usize, h: usize, + tile_bo: TileBlockOffset, ref_frame: RefType, ssdec: u8, lambda: u32, +) -> Option { + if let Some(ref rec) = + fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] + { + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + get_mv_range(fi.w_in_b, fi.h_in_b, frame_bo, w << ssdec, h << ssdec); + + let pmv = [MotionVector { row: 0, col: 0 }; 2]; + + let po = frame_bo.to_luma_plane_offset(); + let (mvx_min, mvx_max, mvy_min, mvy_max) = + (mvx_min >> ssdec, mvx_max >> ssdec, mvy_min >> ssdec, mvy_max >> ssdec); + let po = PlaneOffset { x: po.x >> ssdec, y: po.y >> ssdec }; + let p_ref = match ssdec { + 0 => &rec.frame.planes[0], + 1 => &rec.input_hres, + 2 => &rec.input_qres, + _ => unimplemented!(), + }; + + let org_region = &match ssdec { + 0 => ts.input_tile.planes[0] + .subregion(Area::BlockStartingAt { bo: tile_bo.0 }), + 1 => ts.input_hres.region(Area::StartingAt { x: po.x, y: po.y }), + 2 => ts.input_qres.region(Area::StartingAt { x: po.x, y: po.y }), + _ => unimplemented!(), + }; + + let mv = + ts.me_stats[ref_frame.to_index()][tile_bo.0.y][tile_bo.0.x].mv >> ssdec; + + // Given a motion vector at 0 at higher subsampling: + // | -1 | 0 | 1 | + // then the vectors at -1 to 2 should be tested at the current subsampling. + // |-------------| + // | -2 -1 | 0 1 | 2 3 | + // This corresponds to a 4x4 full search. + let x_lo = po.x + (mv.col as isize / 8 - 1).max(mvx_min / 8); + let x_hi = po.x + (mv.col as isize / 8 + 2).min(mvx_max / 8); + let y_lo = po.y + (mv.row as isize / 8 - 1).max(mvy_min / 8); + let y_hi = po.y + (mv.row as isize / 8 + 2).min(mvy_max / 8); + let mut results = full_search( + fi, x_lo, x_hi, y_lo, y_hi, w, h, org_region, p_ref, po, 1, lambda, pmv, + ); + + // Scale motion vectors to full res size + results.mv = results.mv << ssdec; + + Some(results) + } else { + None + } +} + +#[profiling::function] +fn full_pixel_me( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, + org_region: &PlaneRegion, p_ref: &Plane, tile_bo: TileBlockOffset, + po: PlaneOffset, lambda: u32, pmv: [MotionVector; 2], w: usize, h: usize, + mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, + ref_frame: RefType, corner: MVSamplingMode, extensive_search: bool, + ssdec: u8, +) -> MotionSearchResult { + let ref_frame_id = ref_frame.to_index(); + let tile_me_stats = &ts.me_stats[ref_frame_id].as_const(); + let frame_ref = fi.rec_buffer.frames[fi.ref_frames[0] as usize] + .as_ref() + .map(|frame_ref| frame_ref.frame_me_stats.read().expect("poisoned lock")); + let subsets = get_subset_predictors( + tile_bo, + tile_me_stats, + frame_ref, + ref_frame_id, + w, + h, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + corner, + ssdec, + ); + + let try_cands = |predictors: &[MotionVector], + best: &mut MotionSearchResult| { + let mut results = get_best_predictor( + fi, + po, + org_region, + p_ref, + predictors, + fi.sequence.bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + ); + fullpel_diamond_search( + fi, + po, + org_region, + p_ref, + &mut results, + fi.sequence.bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + ); + + if results.rd.cost < best.rd.cost { + *best = results; + } + }; + + let mut best: MotionSearchResult = MotionSearchResult::empty(); + if !extensive_search { + try_cands(&subsets.all_mvs(), &mut best); + best + } else { + // Perform a more thorough search before resorting to full search. + // Search the median, the best mvs of neighboring blocks, and motion vectors + // from the previous frame. Stop once a candidate with a sad less than a + // threshold is found. + + let thresh = (subsets.min_sad as f32 * 1.2) as u32 + + (((w * h) as u32) << (fi.sequence.bit_depth - 8)); + + if let Some(median) = subsets.median { + try_cands(&[median], &mut best); + + if best.rd.sad < thresh { + return best; + } + } + + try_cands(&subsets.subset_b, &mut best); + + if best.rd.sad < thresh { + return best; + } + + try_cands(&subsets.subset_c, &mut best); + + if best.rd.sad < thresh { + return best; + } + + // Preform UMH search, either as the last possible search when full search + // is disabled, or as the last search before resorting to full search. + uneven_multi_hex_search( + fi, + po, + org_region, + p_ref, + &mut best, + fi.sequence.bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + // Use 24, since it is the largest range that x264 uses. + 24, + ); + + if !fi.config.speed_settings.motion.me_allow_full_search + || best.rd.sad < thresh + { + return best; + } + + { + let range_x = (192 * fi.me_range_scale as isize) >> ssdec; + let range_y = (64 * fi.me_range_scale as isize) >> ssdec; + let x_lo = po.x + (-range_x).max(mvx_min / 8); + let x_hi = po.x + (range_x).min(mvx_max / 8); + let y_lo = po.y + (-range_y).max(mvy_min / 8); + let y_hi = po.y + (range_y).min(mvy_max / 8); + + let results = full_search( + fi, + x_lo, + x_hi, + y_lo, + y_hi, + w, + h, + org_region, + p_ref, + po, + // Full search is run at quarter resolution, except for short edges. + // When subsampling is lower than usual, the step size is raised so that + // the number of search locations stays the same. + 4 >> ssdec, + lambda, + [MotionVector::default(); 2], + ); + + if results.rd.cost < best.rd.cost { + results + } else { + best + } + } + } +} + +fn sub_pixel_me( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, lambda: u32, pmv: [MotionVector; 2], mvx_min: isize, + mvx_max: isize, mvy_min: isize, mvy_max: isize, w: usize, h: usize, + use_satd: bool, best: &mut MotionSearchResult, ref_frame: RefType, +) { + subpel_diamond_search( + fi, + po, + org_region, + p_ref, + fi.sequence.bit_depth, + pmv, + lambda, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + use_satd, + best, + ref_frame, + ); +} + +#[profiling::function] +fn get_best_predictor( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, predictors: &[MotionVector], bit_depth: usize, + pmv: [MotionVector; 2], lambda: u32, mvx_min: isize, mvx_max: isize, + mvy_min: isize, mvy_max: isize, w: usize, h: usize, +) -> MotionSearchResult { + let mut best: MotionSearchResult = MotionSearchResult::empty(); + + for &init_mv in predictors.iter() { + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, init_mv, + ); + + if rd.cost < best.rd.cost { + best.mv = init_mv; + best.rd = rd; + } + } + + best +} + +/// Declares an array of motion vectors in structure of arrays syntax. +/// Compared to [`search_pattern_subpel`], this version creates motion vectors +/// in fullpel resolution (x8). +macro_rules! search_pattern { + ($field_a:ident: [$($ll_a:expr),*], $field_b:ident: [$($ll_b:expr),*]) => { + [ $(MotionVector { $field_a: $ll_a << 3, $field_b: $ll_b << 3 } ),*] + }; +} + +/// Declares an array of motion vectors in structure of arrays syntax. +macro_rules! search_pattern_subpel { + ($field_a:ident: [$($ll_a:expr),*], $field_b:ident: [$($ll_b:expr),*]) => { + [ $(MotionVector { $field_a: $ll_a, $field_b: $ll_b } ),*] + }; +} + +/// Diamond pattern of radius 1 as shown below. For fullpel search, use +/// `DIAMOND_R1_PATTERN_FULLPEL` since it has been scaled for fullpel search. +/// ```text +/// X +/// XoX +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +/// +const DIAMOND_R1_PATTERN_SUBPEL: [MotionVector; 4] = search_pattern_subpel!( + col: [ 0, 1, 0, -1], + row: [ 1, 0, -1, 0] +); +/// Diamond pattern of radius 1 as shown below. Unlike `DIAMOND_R1_PATTERN`, the +/// vectors have been shifted fullpel scale. +/// ```text +/// X +/// XoX +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const DIAMOND_R1_PATTERN: [MotionVector; 4] = search_pattern!( + col: [ 0, 1, 0, -1], + row: [ 1, 0, -1, 0] +); + +/// Run a full pixel diamond search. The search is run on multiple step sizes. +/// +/// For each step size, candidate motion vectors are examined for improvement +/// to the current search location. The search location is moved to the best +/// candidate (if any). This is repeated until the search location stops moving. +#[profiling::function] +fn fullpel_diamond_search( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, current: &mut MotionSearchResult, bit_depth: usize, + pmv: [MotionVector; 2], lambda: u32, mvx_min: isize, mvx_max: isize, + mvy_min: isize, mvy_max: isize, w: usize, h: usize, +) { + // Define the initial and the final scale (log2) of the diamond. + let (mut diamond_radius_log2, diamond_radius_end_log2) = (1u8, 0u8); + + loop { + // Find the best candidate from the diamond pattern. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &DIAMOND_R1_PATTERN { + let cand_mv = current.mv + (offset << diamond_radius_log2); + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Continue the search at this scale until the can't find a better candidate + // to use. + if current.rd.cost <= best_cand.rd.cost { + if diamond_radius_log2 == diamond_radius_end_log2 { + break; + } else { + diamond_radius_log2 -= 1; + } + } else { + *current = best_cand; + } + } + + assert!(!current.is_empty()); +} + +/// A hexagon pattern around a center point. The pattern is ordered so that the +/// offsets circle around the center. This is done to allow pruning locations +/// covered by the last iteration. +/// ```text +/// 21012 +/// 2 X X +/// 1 +/// 0 X o X +/// 1 +/// 2 X X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +/// +/// The illustration below shows the process of a hexagon search. +/// ```text +/// Step 1 Step 2 +/// 1 1 1 1 2 +/// +/// 1(0)1 => 1 0(1)2 +/// +/// 1 1 1 1 2 +/// ``` +/// The search above has gone through the following steps. +/// 1. Search '1' elements for better candidates than the center '0'. +/// 2. Recenter around the best candidate ('(1)') and hexagon candidates that +/// don't overlap with the previous search step (labeled '2'). +const HEXAGON_PATTERN: [MotionVector; 6] = search_pattern!( + col: [ 0, 2, 2, 0, -2, -2], + row: [ -2, -1, 1, 2, 1, -1] +); + +/// A small square pattern around a center point. +/// ```text +/// 101 +/// 1 XXX +/// 0 XoX +/// 1 XXX +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const SQUARE_REFINE_PATTERN: [MotionVector; 8] = search_pattern!( + col: [ -1, 0, 1, -1, 1, -1, 0, 1], + row: [ 1, 1, 1, 0, 0, -1, -1, -1] +); + +/// Perform hexagon search and refine afterwards. +/// +/// In the hexagon search stage, candidate motion vectors are examined for +/// improvement to the current search location. The search location is moved to +/// the best candidate (if any). This is repeated until the search location +/// stops moving. +/// +/// Refinement uses a square pattern that fits between the hexagon candidates. +/// +/// The hexagon pattern is defined by [`HEXAGON_PATTERN`] and the refinement +/// is defined by [`SQUARE_REFINE_PATTERN`]. +/// +/// `current` provides the initial search location and serves as +/// the output for the final search results. +#[profiling::function] +fn hexagon_search( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, current: &mut MotionSearchResult, bit_depth: usize, + pmv: [MotionVector; 2], lambda: u32, mvx_min: isize, mvx_max: isize, + mvy_min: isize, mvy_max: isize, w: usize, h: usize, +) { + // The first iteration of hexagon search is implemented separate from + // subsequent iterations, which overlap with previous iterations. + + // Holds what candidate is used (if any). This is used to determine which + // candidates have already been tested in a previous iteration and can be + // skipped. + let mut best_cand_idx: usize = 0; + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + + // First iteration of hexagon search. There are six candidates to consider. + for i in 0..6 { + let cand_mv = current.mv + HEXAGON_PATTERN[i]; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < best_cand.rd.cost { + best_cand_idx = i; + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Run additional iterations of hexagon search until the search location + // doesn't update. + while best_cand.rd.cost < current.rd.cost { + // Update the search location. + *current = best_cand; + best_cand = MotionSearchResult::empty(); + + // Save the index/direction taken in the previous iteration to the current + // search location. + let center_cand_idx = best_cand_idx; + + // Look only at candidates that don't overlap with previous iterations. This + // corresponds with the three offsets (2D) with the closest direction to + // that traveled by the previous iteration. HEXAGON_PATTERN has clockwise + // order, so the last direction -1, +0, and +1 (mod 6) give the indices for + // these offsets. + for idx_offset_mod6 in 5..=7 { + let i = (center_cand_idx + idx_offset_mod6) % 6; + let cand_mv = current.mv + HEXAGON_PATTERN[i]; + + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < best_cand.rd.cost { + best_cand_idx = i; + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + } + + // Refine the motion after completing hexagon search. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &SQUARE_REFINE_PATTERN { + let cand_mv = current.mv + offset; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + if best_cand.rd.cost < current.rd.cost { + *current = best_cand; + } + + assert!(!current.is_empty()); +} + +/// Uneven multi-hexagon search pattern around a center point. Used for locating +/// irregular movement. +/// ```text +/// X +/// X X +/// X X +/// X X +/// X o X +/// X X +/// X X +/// X X +/// X +/// ``` +/// 'X's are motion candidates and the 'o' is the center. +const UMH_PATTERN: [MotionVector; 16] = search_pattern!( + col: [ -2, -1, 0, 1, 2, 3, 4, 3, 2, 1, 0, -1, -2, 3, -4, -3], + row: [ 4, 4, 4, 4, 4, 2, 0, -2, -4, -4, -4, -4, -4, -2, 0, 2] +); + +/// Perform an uneven multi-hexagon search. There are 4 stages: +/// 1. Unsymmetrical-cross search: Search the horizontal and vertical directions +/// for the general direction of the motion. +/// 2. A 5x5 full search is done to refine the current candidate. +/// 3. Uneven multi-hexagon search. See [`UMH_PATTERN`]. +/// 4. Refinement using standard hexagon search. +/// +/// `current` provides the initial search location and serves as +/// the output for the final search results. +/// +/// `me_range` parameter determines how far these stages can search. +#[profiling::function] +fn uneven_multi_hex_search( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, current: &mut MotionSearchResult, bit_depth: usize, + pmv: [MotionVector; 2], lambda: u32, mvx_min: isize, mvx_max: isize, + mvy_min: isize, mvy_max: isize, w: usize, h: usize, me_range: i16, +) { + assert!(!current.is_empty()); + + // Search in a cross pattern to obtain a rough approximate of motion. + // The cross is split into a horizontal and vertical component. Video content + // tends to have more horizontal motion, so the horizontal part of the cross + // is twice as large as the vertical half. + // X - + // | <- me_range/2 + // X | + // X X X XoX X X X - + // X + // + // X + // |------| + // \ + // me_range + let center = current.mv; + + // The larger, horizontal, part of the cross search. + for i in (1..=me_range).step_by(2) { + const HORIZONTAL_LINE: [MotionVector; 2] = search_pattern!( + col: [ 0, 0], + row: [-1, 1] + ); + + for &offset in &HORIZONTAL_LINE { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // The smaller, vertical, part of the cross search + for i in (1..=me_range >> 1).step_by(2) { + const VERTICAL_LINE: [MotionVector; 2] = search_pattern!( + col: [-1, 1], + row: [ 0, 0] + ); + + for &offset in &VERTICAL_LINE { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // 5x5 full search. Search a 5x5 square region around the current best mv. + let center = current.mv; + for row in -2..=2 { + for col in -2..=2 { + if row == 0 && col == 0 { + continue; + } + let cand_mv = center + MotionVector { row, col }; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // Run the hexagons in uneven multi-hexagon. The hexagonal pattern is tested + // around the best vector at multiple scales. + // Example of the UMH pattern run on a scale of 1 and 2: + // 2 - + // | <- me_range + // 2 2 | + // | + // 2 1 2 | + // 1 1 | + // 2 1 1 2 | + // 1 1 | + // 2 1 o 1 2 | + // 1 1 | + // 2 1 1 2 | + // 1 1 | + // 2 1 2 | + // | + // 2 2 | + // | + // 2 - + // |---------------| + // \ + // me_range + let center = current.mv; + + // Divide by 4, the radius of the UMH's hexagon. + let iterations = me_range >> 2; + for i in 1..=iterations { + for &offset in &UMH_PATTERN { + let cand_mv = center + offset * i; + let rd = get_fullpel_mv_rd( + fi, po, org_region, p_ref, bit_depth, pmv, lambda, false, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, cand_mv, + ); + + if rd.cost < current.rd.cost { + current.mv = cand_mv; + current.rd = rd; + } + } + } + + // Refine the search results using a 'normal' hexagon search. + hexagon_search( + fi, po, org_region, p_ref, current, bit_depth, pmv, lambda, mvx_min, + mvx_max, mvy_min, mvy_max, w, h, + ); +} + +/// Run a subpixel diamond search. The search is run on multiple step sizes. +/// +/// For each step size, candidate motion vectors are examined for improvement +/// to the current search location. The search location is moved to the best +/// candidate (if any). This is repeated until the search location stops moving. +#[profiling::function] +fn subpel_diamond_search( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + _p_ref: &Plane, bit_depth: usize, pmv: [MotionVector; 2], lambda: u32, + mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, w: usize, + h: usize, use_satd: bool, current: &mut MotionSearchResult, + ref_frame: RefType, +) { + use crate::util::Aligned; + + // Motion compensation assembly has special requirements for edges + let mc_w = w.next_power_of_two(); + let mc_h = (h + 1) & !1; + + // Metadata for subpel scratch pad. + let cfg = PlaneConfig::new(mc_w, mc_h, 0, 0, 0, 0, std::mem::size_of::()); + // Stack allocation for subpel scratch pad. + // SAFETY: We write to the array below before reading from it. + let mut buf: Aligned<[T; 128 * 128]> = unsafe { Aligned::uninitialized() }; + let mut tmp_region = PlaneRegionMut::from_slice( + &mut buf.data, + &cfg, + Rect { x: 0, y: 0, width: cfg.width, height: cfg.height }, + ); + + // start at 1/2 pel and end at 1/4 or 1/8 pel + let (mut diamond_radius_log2, diamond_radius_end_log2) = + (2u8, u8::from(!fi.allow_high_precision_mv)); + + loop { + // Find the best candidate from the diamond pattern. + let mut best_cand: MotionSearchResult = MotionSearchResult::empty(); + for &offset in &DIAMOND_R1_PATTERN_SUBPEL { + let cand_mv = current.mv + (offset << diamond_radius_log2); + + let rd = get_subpel_mv_rd( + fi, + po, + org_region, + bit_depth, + pmv, + lambda, + use_satd, + mvx_min, + mvx_max, + mvy_min, + mvy_max, + w, + h, + cand_mv, + &mut tmp_region, + ref_frame, + ); + + if rd.cost < best_cand.rd.cost { + best_cand.mv = cand_mv; + best_cand.rd = rd; + } + } + + // Continue the search at this scale until a better candidate isn't found. + if current.rd.cost <= best_cand.rd.cost { + if diamond_radius_log2 == diamond_radius_end_log2 { + break; + } else { + diamond_radius_log2 -= 1; + } + } else { + *current = best_cand; + } + } + + assert!(!current.is_empty()); +} + +#[inline] +fn get_fullpel_mv_rd( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + p_ref: &Plane, bit_depth: usize, pmv: [MotionVector; 2], lambda: u32, + use_satd: bool, mvx_min: isize, mvx_max: isize, mvy_min: isize, + mvy_max: isize, w: usize, h: usize, cand_mv: MotionVector, +) -> MVCandidateRD { + if (cand_mv.col as isize) < mvx_min + || (cand_mv.col as isize) > mvx_max + || (cand_mv.row as isize) < mvy_min + || (cand_mv.row as isize) > mvy_max + { + return MVCandidateRD::empty(); + } + + // Convert the motion vector into an full pixel offset. + let plane_ref = p_ref.region(Area::StartingAt { + x: po.x + (cand_mv.col / 8) as isize, + y: po.y + (cand_mv.row / 8) as isize, + }); + compute_mv_rd( + fi, pmv, lambda, use_satd, bit_depth, w, h, cand_mv, org_region, + &plane_ref, + ) +} + +fn get_subpel_mv_rd( + fi: &FrameInvariants, po: PlaneOffset, org_region: &PlaneRegion, + bit_depth: usize, pmv: [MotionVector; 2], lambda: u32, use_satd: bool, + mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, w: usize, + h: usize, cand_mv: MotionVector, tmp_region: &mut PlaneRegionMut, + ref_frame: RefType, +) -> MVCandidateRD { + if (cand_mv.col as isize) < mvx_min + || (cand_mv.col as isize) > mvx_max + || (cand_mv.row as isize) < mvy_min + || (cand_mv.row as isize) > mvy_max + { + return MVCandidateRD::empty(); + } + + let tmp_width = tmp_region.rect().width; + let tmp_height = tmp_region.rect().height; + let tile_rect = + TileRect { x: 0, y: 0, width: tmp_width, height: tmp_height }; + + PredictionMode::NEWMV.predict_inter_single( + fi, tile_rect, 0, po, tmp_region, + // motion comp's w & h on edges can be different than distortion's + tmp_width, tmp_height, ref_frame, cand_mv, + ); + let plane_ref = tmp_region.as_const(); + compute_mv_rd( + fi, pmv, lambda, use_satd, bit_depth, w, h, cand_mv, org_region, + &plane_ref, + ) +} + +/// Compute the rate distortion stats for a motion vector. +#[inline(always)] +fn compute_mv_rd( + fi: &FrameInvariants, pmv: [MotionVector; 2], lambda: u32, + use_satd: bool, bit_depth: usize, w: usize, h: usize, cand_mv: MotionVector, + plane_org: &PlaneRegion<'_, T>, plane_ref: &PlaneRegion<'_, T>, +) -> MVCandidateRD { + let sad = if use_satd { + get_satd(plane_org, plane_ref, w, h, bit_depth, fi.cpu_feature_level) + } else { + get_sad(plane_org, plane_ref, w, h, bit_depth, fi.cpu_feature_level) + }; + + let rate1 = get_mv_rate(cand_mv, pmv[0], fi.allow_high_precision_mv); + let rate2 = get_mv_rate(cand_mv, pmv[1], fi.allow_high_precision_mv); + let rate = rate1.min(rate2 + 1); + + MVCandidateRD { cost: 256 * sad as u64 + rate as u64 * lambda as u64, sad } +} + +#[profiling::function] +fn full_search( + fi: &FrameInvariants, x_lo: isize, x_hi: isize, y_lo: isize, y_hi: isize, + w: usize, h: usize, org_region: &PlaneRegion, p_ref: &Plane, + po: PlaneOffset, step: usize, lambda: u32, pmv: [MotionVector; 2], +) -> MotionSearchResult { + let search_region = p_ref.region(Area::Rect { + x: x_lo, + y: y_lo, + width: (x_hi - x_lo) as usize + w, + height: (y_hi - y_lo) as usize + h, + }); + + let mut best: MotionSearchResult = MotionSearchResult::empty(); + + // Select rectangular regions within search region with vert+horz windows + for vert_window in search_region.vert_windows(h).step_by(step) { + for ref_window in vert_window.horz_windows(w).step_by(step) { + let &Rect { x, y, .. } = ref_window.rect(); + + let mv = MotionVector { + row: 8 * (y as i16 - po.y as i16), + col: 8 * (x as i16 - po.x as i16), + }; + + let rd = compute_mv_rd( + fi, + pmv, + lambda, + false, + fi.sequence.bit_depth, + w, + h, + mv, + org_region, + &ref_window, + ); + + if rd.cost < best.rd.cost { + best.rd = rd; + best.mv = mv; + } + } + } + + best +} + +#[inline(always)] +fn get_mv_rate( + a: MotionVector, b: MotionVector, allow_high_precision_mv: bool, +) -> u32 { + #[inline(always)] + fn diff_to_rate(diff: i16, allow_high_precision_mv: bool) -> u32 { + let d = if allow_high_precision_mv { diff } else { diff >> 1 }; + 2 * ILog::ilog(d.abs()) as u32 + } + + diff_to_rate(a.row - b.row, allow_high_precision_mv) + + diff_to_rate(a.col - b.col, allow_high_precision_mv) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/partition.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/partition.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/partition.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/partition.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1061 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use self::BlockSize::*; +use self::TxSize::*; +use crate::context::*; +use crate::frame::*; +use crate::predict::*; +use crate::recon_intra::*; +use crate::serialize::{Deserialize, Serialize}; +use crate::tiling::*; +use crate::transform::TxSize; +use crate::util::*; +use thiserror::Error; + +use std::mem::transmute; +use std::mem::MaybeUninit; + +// LAST_FRAME through ALTREF_FRAME correspond to slots 0-6. +#[derive(PartialEq, Eq, PartialOrd, Copy, Clone, Debug)] +pub enum RefType { + INTRA_FRAME = 0, + LAST_FRAME = 1, + LAST2_FRAME = 2, + LAST3_FRAME = 3, + GOLDEN_FRAME = 4, + BWDREF_FRAME = 5, + ALTREF2_FRAME = 6, + ALTREF_FRAME = 7, + NONE_FRAME = 8, +} + +impl RefType { + /// convert to a ref list index, 0-6 (`INTER_REFS_PER_FRAME`) + /// + /// # Panics + /// + /// - If the ref type is a None or Intra frame + #[inline] + pub fn to_index(self) -> usize { + match self { + NONE_FRAME => { + panic!("Tried to get slot of NONE_FRAME"); + } + INTRA_FRAME => { + panic!("Tried to get slot of INTRA_FRAME"); + } + _ => (self as usize) - 1, + } + } + #[inline] + pub const fn is_fwd_ref(self) -> bool { + (self as usize) < 5 + } + #[inline] + pub const fn is_bwd_ref(self) -> bool { + (self as usize) >= 5 + } +} + +use self::RefType::*; +use std::fmt; +use std::fmt::Display; + +pub const ALL_INTER_REFS: [RefType; 7] = [ + LAST_FRAME, + LAST2_FRAME, + LAST3_FRAME, + GOLDEN_FRAME, + BWDREF_FRAME, + ALTREF2_FRAME, + ALTREF_FRAME, +]; + +pub const LAST_LAST2_FRAMES: usize = 0; // { LAST_FRAME, LAST2_FRAME } +pub const LAST_LAST3_FRAMES: usize = 1; // { LAST_FRAME, LAST3_FRAME } +pub const LAST_GOLDEN_FRAMES: usize = 2; // { LAST_FRAME, GOLDEN_FRAME } +pub const BWDREF_ALTREF_FRAMES: usize = 3; // { BWDREF_FRAME, ALTREF_FRAME } +pub const LAST2_LAST3_FRAMES: usize = 4; // { LAST2_FRAME, LAST3_FRAME } +pub const LAST2_GOLDEN_FRAMES: usize = 5; // { LAST2_FRAME, GOLDEN_FRAME } +pub const LAST3_GOLDEN_FRAMES: usize = 6; // { LAST3_FRAME, GOLDEN_FRAME } +pub const BWDREF_ALTREF2_FRAMES: usize = 7; // { BWDREF_FRAME, ALTREF2_FRAME } +pub const ALTREF2_ALTREF_FRAMES: usize = 8; // { ALTREF2_FRAME, ALTREF_FRAME } +pub const TOTAL_UNIDIR_COMP_REFS: usize = 9; + +// NOTE: UNIDIR_COMP_REFS is the number of uni-directional reference pairs +// that are explicitly signaled. +pub const UNIDIR_COMP_REFS: usize = BWDREF_ALTREF_FRAMES + 1; + +pub const FWD_REFS: usize = 4; +pub const BWD_REFS: usize = 3; +pub const SINGLE_REFS: usize = 7; +pub const TOTAL_REFS_PER_FRAME: usize = 8; +pub const INTER_REFS_PER_FRAME: usize = 7; +pub const TOTAL_COMP_REFS: usize = + FWD_REFS * BWD_REFS + TOTAL_UNIDIR_COMP_REFS; + +pub const REF_FRAMES_LOG2: usize = 3; +pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2; + +pub const REF_CONTEXTS: usize = 3; +pub const MVREF_ROW_COLS: usize = 3; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)] +pub enum PartitionType { + PARTITION_NONE, + PARTITION_HORZ, + PARTITION_VERT, + PARTITION_SPLIT, + PARTITION_HORZ_A, // HORZ split and the top partition is split again + PARTITION_HORZ_B, // HORZ split and the bottom partition is split again + PARTITION_VERT_A, // VERT split and the left partition is split again + PARTITION_VERT_B, // VERT split and the right partition is split again + PARTITION_HORZ_4, // 4:1 horizontal partition + PARTITION_VERT_4, // 4:1 vertical partition + PARTITION_INVALID, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(Default))] +pub enum BlockSize { + BLOCK_4X4, + BLOCK_4X8, + BLOCK_8X4, + BLOCK_8X8, + BLOCK_8X16, + BLOCK_16X8, + BLOCK_16X16, + BLOCK_16X32, + BLOCK_32X16, + BLOCK_32X32, + BLOCK_32X64, + BLOCK_64X32, + #[cfg_attr(test, default)] + BLOCK_64X64, + BLOCK_64X128, + BLOCK_128X64, + BLOCK_128X128, + BLOCK_4X16, + BLOCK_16X4, + BLOCK_8X32, + BLOCK_32X8, + BLOCK_16X64, + BLOCK_64X16, +} + +#[derive(Debug, Error, Copy, Clone, Eq, PartialEq)] +pub struct InvalidBlockSize; + +impl Display for InvalidBlockSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid block size") + } +} + +impl PartialOrd for BlockSize { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { + use std::cmp::Ordering::{Equal, Greater, Less}; + match ( + self.width().cmp(&other.width()), + self.height().cmp(&other.height()), + ) { + (Greater, Less) | (Less, Greater) => None, + (Equal, Equal) => Some(Equal), + (Greater, _) | (_, Greater) => Some(Greater), + (Less, _) | (_, Less) => Some(Less), + } + } +} + +impl BlockSize { + pub const BLOCK_SIZES_ALL: usize = 22; + pub const BLOCK_SIZES: usize = BlockSize::BLOCK_SIZES_ALL - 6; // BLOCK_SIZES_ALL minus 4:1 non-squares, six of them + + #[inline] + /// # Errors + /// + /// - Returns `InvalidBlockSize` if the given `w` and `h` do not produce + /// a valid block size. + pub fn from_width_and_height_opt( + w: usize, h: usize, + ) -> Result { + match (w, h) { + (4, 4) => Ok(BLOCK_4X4), + (4, 8) => Ok(BLOCK_4X8), + (4, 16) => Ok(BLOCK_4X16), + (8, 4) => Ok(BLOCK_8X4), + (8, 8) => Ok(BLOCK_8X8), + (8, 16) => Ok(BLOCK_8X16), + (8, 32) => Ok(BLOCK_8X32), + (16, 4) => Ok(BLOCK_16X4), + (16, 8) => Ok(BLOCK_16X8), + (16, 16) => Ok(BLOCK_16X16), + (16, 32) => Ok(BLOCK_16X32), + (16, 64) => Ok(BLOCK_16X64), + (32, 8) => Ok(BLOCK_32X8), + (32, 16) => Ok(BLOCK_32X16), + (32, 32) => Ok(BLOCK_32X32), + (32, 64) => Ok(BLOCK_32X64), + (64, 16) => Ok(BLOCK_64X16), + (64, 32) => Ok(BLOCK_64X32), + (64, 64) => Ok(BLOCK_64X64), + (64, 128) => Ok(BLOCK_64X128), + (128, 64) => Ok(BLOCK_128X64), + (128, 128) => Ok(BLOCK_128X128), + _ => Err(InvalidBlockSize), + } + } + + /// # Panics + /// + /// - If the given `w` and `h` do not produce a valid block size. + pub fn from_width_and_height(w: usize, h: usize) -> BlockSize { + Self::from_width_and_height_opt(w, h).unwrap() + } + + #[inline] + pub fn cfl_allowed(self) -> bool { + // TODO: fix me when enabling EXT_PARTITION_TYPES + self <= BlockSize::BLOCK_32X32 + } + + #[inline] + pub const fn width(self) -> usize { + 1 << self.width_log2() + } + + /// width * height + #[inline] + pub const fn area(self) -> usize { + self.width() * self.height() + } + + #[inline] + pub const fn width_log2(self) -> usize { + match self { + BLOCK_4X4 | BLOCK_4X8 | BLOCK_4X16 => 2, + BLOCK_8X4 | BLOCK_8X8 | BLOCK_8X16 | BLOCK_8X32 => 3, + BLOCK_16X4 | BLOCK_16X8 | BLOCK_16X16 | BLOCK_16X32 | BLOCK_16X64 => 4, + BLOCK_32X8 | BLOCK_32X16 | BLOCK_32X32 | BLOCK_32X64 => 5, + BLOCK_64X16 | BLOCK_64X32 | BLOCK_64X64 | BLOCK_64X128 => 6, + BLOCK_128X64 | BLOCK_128X128 => 7, + } + } + + #[inline] + pub const fn width_mi_log2(self) -> usize { + self.width_log2() - 2 + } + + #[inline] + pub const fn width_mi(self) -> usize { + self.width() >> MI_SIZE_LOG2 + } + + #[inline] + pub fn width_imp_b(self) -> usize { + (self.width() >> (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT)) + .max(1) + } + + #[inline] + pub const fn height(self) -> usize { + 1 << self.height_log2() + } + + #[inline] + pub const fn height_log2(self) -> usize { + match self { + BLOCK_4X4 | BLOCK_8X4 | BLOCK_16X4 => 2, + BLOCK_4X8 | BLOCK_8X8 | BLOCK_16X8 | BLOCK_32X8 => 3, + BLOCK_4X16 | BLOCK_8X16 | BLOCK_16X16 | BLOCK_32X16 | BLOCK_64X16 => 4, + BLOCK_8X32 | BLOCK_16X32 | BLOCK_32X32 | BLOCK_64X32 => 5, + BLOCK_16X64 | BLOCK_32X64 | BLOCK_64X64 | BLOCK_128X64 => 6, + BLOCK_64X128 | BLOCK_128X128 => 7, + } + } + + #[inline] + pub const fn height_mi_log2(self) -> usize { + self.height_log2() - 2 + } + + #[inline] + pub const fn height_mi(self) -> usize { + self.height() >> MI_SIZE_LOG2 + } + + #[inline] + pub fn height_imp_b(self) -> usize { + (self.height() >> (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT)) + .max(1) + } + + #[inline] + pub const fn tx_size(self) -> TxSize { + match self { + BLOCK_4X4 => TX_4X4, + BLOCK_4X8 => TX_4X8, + BLOCK_8X4 => TX_8X4, + BLOCK_8X8 => TX_8X8, + BLOCK_8X16 => TX_8X16, + BLOCK_16X8 => TX_16X8, + BLOCK_16X16 => TX_16X16, + BLOCK_16X32 => TX_16X32, + BLOCK_32X16 => TX_32X16, + BLOCK_32X32 => TX_32X32, + BLOCK_32X64 => TX_32X64, + BLOCK_64X32 => TX_64X32, + BLOCK_4X16 => TX_4X16, + BLOCK_16X4 => TX_16X4, + BLOCK_8X32 => TX_8X32, + BLOCK_32X8 => TX_32X8, + BLOCK_16X64 => TX_16X64, + BLOCK_64X16 => TX_64X16, + _ => TX_64X64, + } + } + + /// Source: `Subsampled_Size` (AV1 specification section 5.11.38) + /// + /// # Errors + /// + /// - Returns `InvalidBlockSize` if the given block size cannot + /// be subsampled in the requested way. + #[inline] + pub const fn subsampled_size( + self, xdec: usize, ydec: usize, + ) -> Result { + Ok(match (xdec, ydec) { + (0, 0) /* 4:4:4 */ => self, + (1, 0) /* 4:2:2 */ => match self { + BLOCK_4X4 | BLOCK_8X4 => BLOCK_4X4, + BLOCK_8X8 => BLOCK_4X8, + BLOCK_16X4 => BLOCK_8X4, + BLOCK_16X8 => BLOCK_8X8, + BLOCK_16X16 => BLOCK_8X16, + BLOCK_32X8 => BLOCK_16X8, + BLOCK_32X16 => BLOCK_16X16, + BLOCK_32X32 => BLOCK_16X32, + BLOCK_64X16 => BLOCK_32X16, + BLOCK_64X32 => BLOCK_32X32, + BLOCK_64X64 => BLOCK_32X64, + BLOCK_128X64 => BLOCK_64X64, + BLOCK_128X128 => BLOCK_64X128, + _ => return Err(InvalidBlockSize), + }, + (1, 1) /* 4:2:0 */ => match self { + BLOCK_4X4 | BLOCK_4X8 | BLOCK_8X4 | BLOCK_8X8 => BLOCK_4X4, + BLOCK_4X16 | BLOCK_8X16 => BLOCK_4X8, + BLOCK_8X32 => BLOCK_4X16, + BLOCK_16X4 | BLOCK_16X8 => BLOCK_8X4, + BLOCK_16X16 => BLOCK_8X8, + BLOCK_16X32 => BLOCK_8X16, + BLOCK_16X64 => BLOCK_8X32, + BLOCK_32X8 => BLOCK_16X4, + BLOCK_32X16 => BLOCK_16X8, + BLOCK_32X32 => BLOCK_16X16, + BLOCK_32X64 => BLOCK_16X32, + BLOCK_64X16 => BLOCK_32X8, + BLOCK_64X32 => BLOCK_32X16, + BLOCK_64X64 => BLOCK_32X32, + BLOCK_64X128 => BLOCK_32X64, + BLOCK_128X64 => BLOCK_64X32, + BLOCK_128X128 => BLOCK_64X64, + }, + _ => return Err(InvalidBlockSize), + }) + } + + /// # Panics + /// + /// Will panic if the subsampling is not possible + #[inline] + pub fn largest_chroma_tx_size(self, xdec: usize, ydec: usize) -> TxSize { + let plane_bsize = self + .subsampled_size(xdec, ydec) + .expect("invalid block size for this subsampling mode"); + + let chroma_tx_size = max_txsize_rect_lookup[plane_bsize as usize]; + + av1_get_coded_tx_size(chroma_tx_size) + } + + #[inline] + pub const fn is_sqr(self) -> bool { + self.width_log2() == self.height_log2() + } + + #[inline] + pub const fn is_sub8x8(self, xdec: usize, ydec: usize) -> bool { + xdec != 0 && self.width_log2() == 2 || ydec != 0 && self.height_log2() == 2 + } + + #[inline] + pub const fn sub8x8_offset( + self, xdec: usize, ydec: usize, + ) -> (isize, isize) { + let offset_x = if xdec != 0 && self.width_log2() == 2 { -1 } else { 0 }; + let offset_y = if ydec != 0 && self.height_log2() == 2 { -1 } else { 0 }; + + (offset_x, offset_y) + } + + /// # Errors + /// + /// - Returns `InvalidBlockSize` if the block size cannot be split + /// in the requested way. + pub const fn subsize( + self, partition: PartitionType, + ) -> Result { + use PartitionType::*; + + Ok(match partition { + PARTITION_NONE => self, + PARTITION_SPLIT => match self { + BLOCK_8X8 => BLOCK_4X4, + BLOCK_16X16 => BLOCK_8X8, + BLOCK_32X32 => BLOCK_16X16, + BLOCK_64X64 => BLOCK_32X32, + BLOCK_128X128 => BLOCK_64X64, + _ => return Err(InvalidBlockSize), + }, + PARTITION_HORZ | PARTITION_HORZ_A | PARTITION_HORZ_B => match self { + BLOCK_8X8 => BLOCK_8X4, + BLOCK_16X16 => BLOCK_16X8, + BLOCK_32X32 => BLOCK_32X16, + BLOCK_64X64 => BLOCK_64X32, + BLOCK_128X128 => BLOCK_128X64, + _ => return Err(InvalidBlockSize), + }, + PARTITION_VERT | PARTITION_VERT_A | PARTITION_VERT_B => match self { + BLOCK_8X8 => BLOCK_4X8, + BLOCK_16X16 => BLOCK_8X16, + BLOCK_32X32 => BLOCK_16X32, + BLOCK_64X64 => BLOCK_32X64, + BLOCK_128X128 => BLOCK_64X128, + _ => return Err(InvalidBlockSize), + }, + PARTITION_HORZ_4 => match self { + BLOCK_16X16 => BLOCK_16X4, + BLOCK_32X32 => BLOCK_32X8, + BLOCK_64X64 => BLOCK_64X16, + _ => return Err(InvalidBlockSize), + }, + PARTITION_VERT_4 => match self { + BLOCK_16X16 => BLOCK_4X16, + BLOCK_32X32 => BLOCK_8X32, + BLOCK_64X64 => BLOCK_16X64, + _ => return Err(InvalidBlockSize), + }, + _ => return Err(InvalidBlockSize), + }) + } + + pub const fn is_rect_tx_allowed(self) -> bool { + !matches!( + self, + BLOCK_4X4 + | BLOCK_8X8 + | BLOCK_16X16 + | BLOCK_32X32 + | BLOCK_64X64 + | BLOCK_64X128 + | BLOCK_128X64 + | BLOCK_128X128 + ) + } +} + +impl fmt::Display for BlockSize { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + BlockSize::BLOCK_4X4 => "4x4", + BlockSize::BLOCK_4X8 => "4x8", + BlockSize::BLOCK_8X4 => "8x4", + BlockSize::BLOCK_8X8 => "8x8", + BlockSize::BLOCK_8X16 => "8x16", + BlockSize::BLOCK_16X8 => "16x8", + BlockSize::BLOCK_16X16 => "16x16", + BlockSize::BLOCK_16X32 => "16x32", + BlockSize::BLOCK_32X16 => "32x16", + BlockSize::BLOCK_32X32 => "32x32", + BlockSize::BLOCK_32X64 => "32x64", + BlockSize::BLOCK_64X32 => "64x32", + BlockSize::BLOCK_64X64 => "64x64", + BlockSize::BLOCK_64X128 => "64x128", + BlockSize::BLOCK_128X64 => "128x64", + BlockSize::BLOCK_128X128 => "128x128", + BlockSize::BLOCK_4X16 => "4x16", + BlockSize::BLOCK_16X4 => "16x4", + BlockSize::BLOCK_8X32 => "8x32", + BlockSize::BLOCK_32X8 => "32x8", + BlockSize::BLOCK_16X64 => "16x64", + BlockSize::BLOCK_64X16 => "64x16", + } + ) + } +} + +pub const NEWMV_MODE_CONTEXTS: usize = 7; +pub const GLOBALMV_MODE_CONTEXTS: usize = 2; +pub const REFMV_MODE_CONTEXTS: usize = 6; +pub const INTER_COMPOUND_MODES: usize = 8; + +pub const REFMV_OFFSET: usize = 4; +pub const GLOBALMV_OFFSET: usize = 3; +pub const NEWMV_CTX_MASK: usize = (1 << GLOBALMV_OFFSET) - 1; +pub const GLOBALMV_CTX_MASK: usize = + (1 << (REFMV_OFFSET - GLOBALMV_OFFSET)) - 1; +pub const REFMV_CTX_MASK: usize = (1 << (8 - REFMV_OFFSET)) - 1; + +pub static RAV1E_PARTITION_TYPES: &[PartitionType] = &[ + PartitionType::PARTITION_NONE, + PartitionType::PARTITION_HORZ, + PartitionType::PARTITION_VERT, + PartitionType::PARTITION_SPLIT, +]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum GlobalMVMode { + IDENTITY = 0, // identity transformation, 0-parameter + TRANSLATION = 1, // translational motion 2-parameter + ROTZOOM = 2, // simplified affine with rotation + zoom only, 4-parameter + AFFINE = 3, // affine, 6-parameter +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum MvSubpelPrecision { + MV_SUBPEL_NONE = -1, + MV_SUBPEL_LOW_PRECISION = 0, + MV_SUBPEL_HIGH_PRECISION, +} + +/* Symbols for coding which components are zero jointly */ +pub const MV_JOINTS: usize = 4; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum MvJointType { + MV_JOINT_ZERO = 0, /* Zero vector */ + MV_JOINT_HNZVZ = 1, /* Vert zero, hor nonzero */ + MV_JOINT_HZVNZ = 2, /* Hor zero, vert nonzero */ + MV_JOINT_HNZVNZ = 3, /* Both components nonzero */ +} + +fn supersample_chroma_bsize( + bsize: BlockSize, ss_x: usize, ss_y: usize, +) -> BlockSize { + debug_assert!(ss_x < 2); + debug_assert!(ss_y < 2); + + match bsize { + BLOCK_4X4 => match (ss_x, ss_y) { + (1, 1) => BLOCK_8X8, + (1, 0) => BLOCK_8X4, + (0, 1) => BLOCK_4X8, + _ => bsize, + }, + BLOCK_4X8 => match (ss_x, ss_y) { + (1, 1) => BLOCK_8X8, + (1, 0) => BLOCK_8X8, + (0, 1) => BLOCK_4X8, + _ => bsize, + }, + BLOCK_8X4 => match (ss_x, ss_y) { + (1, 1) => BLOCK_8X8, + (1, 0) => BLOCK_8X4, + (0, 1) => BLOCK_8X8, + _ => bsize, + }, + BLOCK_4X16 => match (ss_x, ss_y) { + (1, 1) => BLOCK_8X16, + (1, 0) => BLOCK_8X16, + (0, 1) => BLOCK_4X16, + _ => bsize, + }, + BLOCK_16X4 => match (ss_x, ss_y) { + (1, 1) => BLOCK_16X8, + (1, 0) => BLOCK_16X4, + (0, 1) => BLOCK_16X8, + _ => bsize, + }, + _ => bsize, + } +} + +type IntraEdgeBuffer = Aligned<[MaybeUninit; 4 * MAX_TX_SIZE + 1]>; + +#[cfg(any(test, feature = "bench"))] +type IntraEdgeMock = Aligned<[T; 4 * MAX_TX_SIZE + 1]>; + +pub struct IntraEdge<'a, T: Pixel>(&'a [T], &'a [T], &'a [T]); + +impl<'a, T: Pixel> IntraEdge<'a, T> { + fn new( + edge_buf: &'a mut IntraEdgeBuffer, init_left: usize, init_above: usize, + ) -> Self { + // SAFETY: Initialized in `get_intra_edges`. + let left = unsafe { + let begin_left = 2 * MAX_TX_SIZE - init_left; + let end_above = 2 * MAX_TX_SIZE + 1 + init_above; + slice_assume_init_mut(&mut edge_buf.data[begin_left..end_above]) + }; + let (left, top_left) = left.split_at(init_left); + let (top_left, above) = top_left.split_at(1); + Self(left, top_left, above) + } + + pub const fn as_slices(&self) -> (&'a [T], &'a [T], &'a [T]) { + (self.0, self.1, self.2) + } + + pub const fn top_left_ptr(&self) -> *const T { + self.1.as_ptr() + } + + #[cfg(any(test, feature = "bench"))] + pub fn mock(edge_buf: &'a IntraEdgeMock) -> Self { + let left = &edge_buf.data[..]; + let (left, top_left) = left.split_at(2 * MAX_TX_SIZE); + let (top_left, above) = top_left.split_at(1); + Self(left, top_left, above) + } +} + +pub fn get_intra_edges<'a, T: Pixel>( + edge_buf: &'a mut IntraEdgeBuffer, + dst: &PlaneRegion<'_, T>, + partition_bo: TileBlockOffset, // partition bo, BlockOffset + bx: usize, + by: usize, + partition_size: BlockSize, // partition size, BlockSize + po: PlaneOffset, + tx_size: TxSize, + bit_depth: usize, + opt_mode: Option, + enable_intra_edge_filter: bool, + intra_param: IntraParam, +) -> IntraEdge<'a, T> { + let mut init_left: usize = 0; + let mut init_above: usize = 0; + + let plane_cfg = &dst.plane_cfg; + + let base = 128u16 << (bit_depth - 8); + + { + // left pixels are ordered from bottom to top and right-aligned + let (left, not_left) = edge_buf.data.split_at_mut(2 * MAX_TX_SIZE); + let (top_left, above) = not_left.split_at_mut(1); + + let x = po.x as usize; + let y = po.y as usize; + + let mut needs_left = true; + let mut needs_topleft = true; + let mut needs_top = true; + let mut needs_topright = true; + let mut needs_bottomleft = true; + let mut needs_topleft_filter = false; + + if let Some(mut mode) = opt_mode { + mode = match mode { + PredictionMode::PAETH_PRED => match (x, y) { + (0, 0) => PredictionMode::DC_PRED, + (0, _) => PredictionMode::V_PRED, + (_, 0) => PredictionMode::H_PRED, + _ => PredictionMode::PAETH_PRED, + }, + _ => mode, + }; + + let p_angle = intra_mode_to_angle(mode) + + match intra_param { + IntraParam::AngleDelta(val) => (val * ANGLE_STEP) as isize, + _ => 0, + }; + + let dc_or_cfl = + mode == PredictionMode::DC_PRED || mode == PredictionMode::UV_CFL_PRED; + + needs_left = (!dc_or_cfl || x != 0) || (p_angle > 90 && p_angle != 180); + needs_topleft = mode == PredictionMode::PAETH_PRED + || (mode.is_directional() && p_angle != 90 && p_angle != 180); + needs_top = (!dc_or_cfl || y != 0) || (p_angle != 90 && p_angle < 180); + needs_topright = mode.is_directional() && p_angle < 90; + needs_bottomleft = mode.is_directional() && p_angle > 180; + needs_topleft_filter = + enable_intra_edge_filter && p_angle > 90 && p_angle < 180; + } + + let rect_w = + dst.rect().width.min(dst.plane_cfg.width - dst.rect().x as usize); + let rect_h = + dst.rect().height.min(dst.plane_cfg.height - dst.rect().y as usize); + + // Needs left + if needs_left { + let txh = if y + tx_size.height() > rect_h { + rect_h - y + } else { + tx_size.height() + }; + if x != 0 { + for i in 0..txh { + debug_assert!(y + i < rect_h); + left[2 * MAX_TX_SIZE - 1 - i].write(dst[y + i][x - 1]); + } + if txh < tx_size.height() { + let val = dst[y + txh - 1][x - 1]; + for i in txh..tx_size.height() { + left[2 * MAX_TX_SIZE - 1 - i].write(val); + } + } + } else { + let val = if y != 0 { dst[y - 1][0] } else { T::cast_from(base + 1) }; + for v in left[2 * MAX_TX_SIZE - tx_size.height()..].iter_mut() { + v.write(val); + } + } + init_left += tx_size.height(); + } + + // Needs top + if needs_top { + let txw = if x + tx_size.width() > rect_w { + rect_w - x + } else { + tx_size.width() + }; + if y != 0 { + above[..txw].copy_from_slice( + // SAFETY: &[T] and &[MaybeUninit] have the same layout + unsafe { + transmute::<&[T], &[MaybeUninit]>(&dst[y - 1][x..x + txw]) + }, + ); + if txw < tx_size.width() { + let val = dst[y - 1][x + txw - 1]; + for i in txw..tx_size.width() { + above[i].write(val); + } + } + } else { + let val = if x != 0 { dst[0][x - 1] } else { T::cast_from(base - 1) }; + for v in above[..tx_size.width()].iter_mut() { + v.write(val); + } + } + init_above += tx_size.width(); + } + + let bx4 = bx * (tx_size.width() >> MI_SIZE_LOG2); // bx,by are in tx block indices + let by4 = by * (tx_size.height() >> MI_SIZE_LOG2); + + let have_top = by4 != 0 + || if plane_cfg.ydec != 0 { + partition_bo.0.y > 1 + } else { + partition_bo.0.y > 0 + }; + let have_left = bx4 != 0 + || if plane_cfg.xdec != 0 { + partition_bo.0.x > 1 + } else { + partition_bo.0.x > 0 + }; + + let right_available = x + tx_size.width() < rect_w; + let bottom_available = y + tx_size.height() < rect_h; + + let scaled_partition_size = + supersample_chroma_bsize(partition_size, plane_cfg.xdec, plane_cfg.ydec); + + // Needs top right + if needs_topright { + debug_assert!(plane_cfg.xdec <= 1 && plane_cfg.ydec <= 1); + + let num_avail = if y != 0 + && has_top_right( + scaled_partition_size, + partition_bo, + have_top, + right_available, + tx_size, + by4, + bx4, + plane_cfg.xdec, + plane_cfg.ydec, + ) { + tx_size.width().min(rect_w - x - tx_size.width()) + } else { + 0 + }; + if num_avail > 0 { + above[tx_size.width()..][..num_avail].copy_from_slice( + // SAFETY: &[T] and &[MaybeUninit] have the same layout + unsafe { + transmute::<&[T], &[MaybeUninit]>( + &dst[y - 1][x + tx_size.width()..][..num_avail], + ) + }, + ); + } + if num_avail < tx_size.height() { + let val = above[tx_size.width() + num_avail - 1]; + for v in above + [tx_size.width() + num_avail..tx_size.width() + tx_size.height()] + .iter_mut() + { + *v = val; + } + } + init_above += tx_size.height(); + } + + // SAFETY: The blocks above have initialized the first `init_above` items. + let above = unsafe { slice_assume_init_mut(&mut above[..init_above]) }; + + // Needs bottom left + if needs_bottomleft { + debug_assert!(plane_cfg.xdec <= 1 && plane_cfg.ydec <= 1); + + let num_avail = if x != 0 + && has_bottom_left( + scaled_partition_size, + partition_bo, + bottom_available, + have_left, + tx_size, + by4, + bx4, + plane_cfg.xdec, + plane_cfg.ydec, + ) { + tx_size.height().min(rect_h - y - tx_size.height()) + } else { + 0 + }; + if num_avail > 0 { + for i in 0..num_avail { + left[2 * MAX_TX_SIZE - tx_size.height() - 1 - i] + .write(dst[y + tx_size.height() + i][x - 1]); + } + } + if num_avail < tx_size.width() { + let val = left[2 * MAX_TX_SIZE - tx_size.height() - num_avail]; + for v in left[(2 * MAX_TX_SIZE - tx_size.height() - tx_size.width()) + ..(2 * MAX_TX_SIZE - tx_size.height() - num_avail)] + .iter_mut() + { + *v = val; + } + } + init_left += tx_size.width(); + } + + // SAFETY: The blocks above have initialized last `init_left` items. + let left = unsafe { + slice_assume_init_mut(&mut left[2 * MAX_TX_SIZE - init_left..]) + }; + + // Needs top-left + if needs_topleft { + let top_left = top_left[0].write(match (x, y) { + (0, 0) => T::cast_from(base), + (_, 0) => dst[0][x - 1], + (0, _) => dst[y - 1][0], + _ => dst[y - 1][x - 1], + }); + + let (w, h) = (tx_size.width(), tx_size.height()); + if needs_topleft_filter && w + h >= 24 { + let (l, a, tl): (u32, u32, u32) = + (left[left.len() - 1].into(), above[0].into(), (*top_left).into()); + let s = l * 5 + tl * 6 + a * 5; + + *top_left = T::cast_from((s + (1 << 3)) >> 4); + } + } else { + top_left[0].write(T::cast_from(base)); + } + } + IntraEdge::new(edge_buf, init_left, init_above) +} + +pub fn has_tr(bo: TileBlockOffset, bsize: BlockSize) -> bool { + let sb_mi_size = BLOCK_64X64.width_mi(); /* Assume 64x64 for now */ + let mask_row = bo.0.y & LOCAL_BLOCK_MASK; + let mask_col = bo.0.x & LOCAL_BLOCK_MASK; + let target_n4_w = bsize.width_mi(); + let target_n4_h = bsize.height_mi(); + + let mut bs = target_n4_w.max(target_n4_h); + + if bs > BLOCK_64X64.width_mi() { + return false; + } + + let mut has_tr = !((mask_row & bs) != 0 && (mask_col & bs) != 0); + + /* TODO: assert its a power of two */ + + while bs < sb_mi_size { + if (mask_col & bs) != 0 { + if (mask_col & (2 * bs) != 0) && (mask_row & (2 * bs) != 0) { + has_tr = false; + break; + } + } else { + break; + } + bs <<= 1; + } + + /* The left hand of two vertical rectangles always has a top right (as the + * block above will have been decoded) */ + if (target_n4_w < target_n4_h) && (bo.0.x & target_n4_w) == 0 { + has_tr = true; + } + + /* The bottom of two horizontal rectangles never has a top right (as the block + * to the right won't have been decoded) */ + if (target_n4_w > target_n4_h) && (bo.0.y & target_n4_h) != 0 { + has_tr = false; + } + + /* The bottom left square of a Vertical A (in the old format) does + * not have a top right as it is decoded before the right hand + * rectangle of the partition */ + /* + if blk.partition == PartitionType::PARTITION_VERT_A { + if blk.n4_w == blk.n4_h { + if (mask_row & bs) != 0 { + has_tr = false; + } + } + } + */ + + has_tr +} + +pub fn has_bl(bo: TileBlockOffset, bsize: BlockSize) -> bool { + let sb_mi_size = BLOCK_64X64.width_mi(); /* Assume 64x64 for now */ + let mask_row = bo.0.y & LOCAL_BLOCK_MASK; + let mask_col = bo.0.x & LOCAL_BLOCK_MASK; + let target_n4_w = bsize.width_mi(); + let target_n4_h = bsize.height_mi(); + + let mut bs = target_n4_w.max(target_n4_h); + + if bs > BLOCK_64X64.width_mi() { + return false; + } + + let mut has_bl = + (mask_row & bs) == 0 && (mask_col & bs) == 0 && bs < sb_mi_size; + + /* TODO: assert its a power of two */ + + while 2 * bs < sb_mi_size { + if (mask_col & bs) == 0 { + if (mask_col & (2 * bs) == 0) && (mask_row & (2 * bs) == 0) { + has_bl = true; + break; + } + } else { + break; + } + bs <<= 1; + } + + /* The right hand of two vertical rectangles never has a bottom left (as the + * block below won't have been decoded) */ + if (target_n4_w < target_n4_h) && (bo.0.x & target_n4_w) != 0 { + has_bl = false; + } + + /* The top of two horizontal rectangles always has a bottom left (as the block + * to the left will have been decoded) */ + if (target_n4_w > target_n4_h) && (bo.0.y & target_n4_h) == 0 { + has_bl = true; + } + + /* The bottom left square of a Vertical A (in the old format) does + * not have a top right as it is decoded before the right hand + * rectangle of the partition */ + /* + if blk.partition == PartitionType::PARTITION_VERT_A { + if blk.n4_w == blk.n4_h { + if (mask_row & bs) != 0 { + has_tr = false; + } + } + } + */ + + has_bl +} + +#[cfg(test)] +mod tests { + use crate::partition::BlockSize::*; + use crate::partition::{BlockSize, InvalidBlockSize}; + + #[test] + fn from_wh_matches_naive() { + fn from_wh_opt_naive( + w: usize, h: usize, + ) -> Result { + match (w, h) { + (4, 4) => Ok(BLOCK_4X4), + (4, 8) => Ok(BLOCK_4X8), + (8, 4) => Ok(BLOCK_8X4), + (8, 8) => Ok(BLOCK_8X8), + (8, 16) => Ok(BLOCK_8X16), + (16, 8) => Ok(BLOCK_16X8), + (16, 16) => Ok(BLOCK_16X16), + (16, 32) => Ok(BLOCK_16X32), + (32, 16) => Ok(BLOCK_32X16), + (32, 32) => Ok(BLOCK_32X32), + (32, 64) => Ok(BLOCK_32X64), + (64, 32) => Ok(BLOCK_64X32), + (64, 64) => Ok(BLOCK_64X64), + (64, 128) => Ok(BLOCK_64X128), + (128, 64) => Ok(BLOCK_128X64), + (128, 128) => Ok(BLOCK_128X128), + (4, 16) => Ok(BLOCK_4X16), + (16, 4) => Ok(BLOCK_16X4), + (8, 32) => Ok(BLOCK_8X32), + (32, 8) => Ok(BLOCK_32X8), + (16, 64) => Ok(BLOCK_16X64), + (64, 16) => Ok(BLOCK_64X16), + _ => Err(InvalidBlockSize), + } + } + + for w in 0..256 { + for h in 0..256 { + let a = BlockSize::from_width_and_height_opt(w, h); + let b = from_wh_opt_naive(w, h); + + assert_eq!(a, b); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/predict.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/predict.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/predict.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/predict.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1694 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use std::mem::MaybeUninit; + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::predict::*; + } else if #[cfg(asm_neon)] { + pub use crate::asm::aarch64::predict::*; + } else { + pub use self::rust::*; + } +} + +use aligned_vec::{avec, ABox}; + +use crate::context::{TileBlockOffset, MAX_SB_SIZE_LOG2, MAX_TX_SIZE}; +use crate::cpu_features::CpuFeatureLevel; +use crate::encoder::FrameInvariants; +use crate::frame::*; +use crate::mc::*; +use crate::partition::*; +use crate::tiling::*; +use crate::transform::*; +use crate::util::*; + +pub const ANGLE_STEP: i8 = 3; + +// TODO: Review the order of this list. +// The order impacts compression efficiency. +pub static RAV1E_INTRA_MODES: &[PredictionMode] = &[ + PredictionMode::DC_PRED, + PredictionMode::H_PRED, + PredictionMode::V_PRED, + PredictionMode::SMOOTH_PRED, + PredictionMode::SMOOTH_H_PRED, + PredictionMode::SMOOTH_V_PRED, + PredictionMode::PAETH_PRED, + PredictionMode::D45_PRED, + PredictionMode::D135_PRED, + PredictionMode::D113_PRED, + PredictionMode::D157_PRED, + PredictionMode::D203_PRED, + PredictionMode::D67_PRED, +]; + +pub static RAV1E_INTER_MODES_MINIMAL: &[PredictionMode] = + &[PredictionMode::NEARESTMV]; + +pub static RAV1E_INTER_COMPOUND_MODES: &[PredictionMode] = &[ + PredictionMode::GLOBAL_GLOBALMV, + PredictionMode::NEAREST_NEARESTMV, + PredictionMode::NEW_NEWMV, + PredictionMode::NEAREST_NEWMV, + PredictionMode::NEW_NEARESTMV, + PredictionMode::NEAR_NEAR0MV, + PredictionMode::NEAR_NEAR1MV, + PredictionMode::NEAR_NEAR2MV, +]; + +// There are more modes than in the spec because every allowed +// drl index for NEAR modes is considered its own mode. +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default)] +pub enum PredictionMode { + #[default] + DC_PRED, // Average of above and left pixels + V_PRED, // Vertical + H_PRED, // Horizontal + D45_PRED, // Directional 45 degree + D135_PRED, // Directional 135 degree + D113_PRED, // Directional 113 degree + D157_PRED, // Directional 157 degree + D203_PRED, // Directional 203 degree + D67_PRED, // Directional 67 degree + SMOOTH_PRED, // Combination of horizontal and vertical interpolation + SMOOTH_V_PRED, + SMOOTH_H_PRED, + PAETH_PRED, + UV_CFL_PRED, + NEARESTMV, + NEAR0MV, + NEAR1MV, + NEAR2MV, + GLOBALMV, + NEWMV, + // Compound ref compound modes + NEAREST_NEARESTMV, + NEAR_NEAR0MV, + NEAR_NEAR1MV, + NEAR_NEAR2MV, + NEAREST_NEWMV, + NEW_NEARESTMV, + NEAR_NEW0MV, + NEAR_NEW1MV, + NEAR_NEW2MV, + NEW_NEAR0MV, + NEW_NEAR1MV, + NEW_NEAR2MV, + GLOBAL_GLOBALMV, + NEW_NEWMV, +} + +// This is a higher number than in the spec and cannot be used +// for bitstream writing purposes. +pub const PREDICTION_MODES: usize = 34; + +#[derive(Copy, Clone, Debug)] +pub enum PredictionVariant { + NONE, + LEFT, + TOP, + BOTH, +} + +impl PredictionVariant { + #[inline] + const fn new(x: usize, y: usize) -> Self { + match (x, y) { + (0, 0) => PredictionVariant::NONE, + (_, 0) => PredictionVariant::LEFT, + (0, _) => PredictionVariant::TOP, + _ => PredictionVariant::BOTH, + } + } +} + +pub const fn intra_mode_to_angle(mode: PredictionMode) -> isize { + match mode { + PredictionMode::V_PRED => 90, + PredictionMode::H_PRED => 180, + PredictionMode::D45_PRED => 45, + PredictionMode::D135_PRED => 135, + PredictionMode::D113_PRED => 113, + PredictionMode::D157_PRED => 157, + PredictionMode::D203_PRED => 203, + PredictionMode::D67_PRED => 67, + _ => 0, + } +} + +impl PredictionMode { + #[inline] + pub fn is_compound(self) -> bool { + self >= PredictionMode::NEAREST_NEARESTMV + } + #[inline] + pub fn has_nearmv(self) -> bool { + self == PredictionMode::NEAR0MV + || self == PredictionMode::NEAR1MV + || self == PredictionMode::NEAR2MV + || self == PredictionMode::NEAR_NEAR0MV + || self == PredictionMode::NEAR_NEAR1MV + || self == PredictionMode::NEAR_NEAR2MV + || self == PredictionMode::NEAR_NEW0MV + || self == PredictionMode::NEAR_NEW1MV + || self == PredictionMode::NEAR_NEW2MV + || self == PredictionMode::NEW_NEAR0MV + || self == PredictionMode::NEW_NEAR1MV + || self == PredictionMode::NEW_NEAR2MV + } + #[inline] + pub fn has_newmv(self) -> bool { + self == PredictionMode::NEWMV + || self == PredictionMode::NEW_NEWMV + || self == PredictionMode::NEAREST_NEWMV + || self == PredictionMode::NEW_NEARESTMV + || self == PredictionMode::NEAR_NEW0MV + || self == PredictionMode::NEAR_NEW1MV + || self == PredictionMode::NEAR_NEW2MV + || self == PredictionMode::NEW_NEAR0MV + || self == PredictionMode::NEW_NEAR1MV + || self == PredictionMode::NEW_NEAR2MV + } + #[inline] + pub fn ref_mv_idx(self) -> usize { + if self == PredictionMode::NEAR0MV + || self == PredictionMode::NEAR1MV + || self == PredictionMode::NEAR2MV + { + self as usize - PredictionMode::NEAR0MV as usize + 1 + } else if self == PredictionMode::NEAR_NEAR0MV + || self == PredictionMode::NEAR_NEAR1MV + || self == PredictionMode::NEAR_NEAR2MV + { + self as usize - PredictionMode::NEAR_NEAR0MV as usize + 1 + } else { + 1 + } + } + + /// # Panics + /// + /// - If called on an inter `PredictionMode` + pub fn predict_intra( + self, tile_rect: TileRect, dst: &mut PlaneRegionMut<'_, T>, + tx_size: TxSize, bit_depth: usize, ac: &[i16], intra_param: IntraParam, + ief_params: Option, edge_buf: &IntraEdge, + cpu: CpuFeatureLevel, + ) { + assert!(self.is_intra()); + let &Rect { x: frame_x, y: frame_y, .. } = dst.rect(); + debug_assert!(frame_x >= 0 && frame_y >= 0); + // x and y are expressed relative to the tile + let x = frame_x as usize - tile_rect.x; + let y = frame_y as usize - tile_rect.y; + + let variant = PredictionVariant::new(x, y); + + let alpha = match intra_param { + IntraParam::Alpha(val) => val, + _ => 0, + }; + let angle_delta = match intra_param { + IntraParam::AngleDelta(val) => val, + _ => 0, + }; + + let mode = match self { + PredictionMode::PAETH_PRED => match variant { + PredictionVariant::NONE => PredictionMode::DC_PRED, + PredictionVariant::TOP => PredictionMode::V_PRED, + PredictionVariant::LEFT => PredictionMode::H_PRED, + PredictionVariant::BOTH => PredictionMode::PAETH_PRED, + }, + PredictionMode::UV_CFL_PRED if alpha == 0 => PredictionMode::DC_PRED, + _ => self, + }; + + let angle = match mode { + PredictionMode::UV_CFL_PRED => alpha as isize, + _ => intra_mode_to_angle(mode) + (angle_delta * ANGLE_STEP) as isize, + }; + + dispatch_predict_intra::( + mode, variant, dst, tx_size, bit_depth, ac, angle, ief_params, edge_buf, + cpu, + ); + } + + #[inline] + pub fn is_intra(self) -> bool { + self < PredictionMode::NEARESTMV + } + + #[inline] + pub fn is_cfl(self) -> bool { + self == PredictionMode::UV_CFL_PRED + } + + #[inline] + pub fn is_directional(self) -> bool { + self >= PredictionMode::V_PRED && self <= PredictionMode::D67_PRED + } + + #[inline(always)] + pub const fn angle_delta_count(self) -> i8 { + match self { + PredictionMode::V_PRED + | PredictionMode::H_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => 7, + _ => 1, + } + } + + // Used by inter prediction to extract the fractional component of a mv and + // obtain the correct PlaneSlice to operate on. + #[inline] + fn get_mv_params( + rec_plane: &Plane, po: PlaneOffset, mv: MotionVector, + ) -> (i32, i32, PlaneSlice) { + let &PlaneConfig { xdec, ydec, .. } = &rec_plane.cfg; + let row_offset = mv.row as i32 >> (3 + ydec); + let col_offset = mv.col as i32 >> (3 + xdec); + let row_frac = ((mv.row as i32) << (1 - ydec)) & 0xf; + let col_frac = ((mv.col as i32) << (1 - xdec)) & 0xf; + let qo = PlaneOffset { + x: po.x + col_offset as isize - 3, + y: po.y + row_offset as isize - 3, + }; + (row_frac, col_frac, rec_plane.slice(qo).clamp().subslice(3, 3)) + } + + /// Inter prediction with a single reference (i.e. not compound mode) + /// + /// # Panics + /// + /// - If called on an intra `PredictionMode` + pub fn predict_inter_single( + self, fi: &FrameInvariants, tile_rect: TileRect, p: usize, + po: PlaneOffset, dst: &mut PlaneRegionMut<'_, T>, width: usize, + height: usize, ref_frame: RefType, mv: MotionVector, + ) { + assert!(!self.is_intra()); + let frame_po = tile_rect.to_frame_plane_offset(po); + + let mode = fi.default_filter; + + if let Some(ref rec) = + fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] + { + let (row_frac, col_frac, src) = + PredictionMode::get_mv_params(&rec.frame.planes[p], frame_po, mv); + put_8tap( + dst, + src, + width, + height, + col_frac, + row_frac, + mode, + mode, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + } + } + + /// Inter prediction with two references. + /// + /// # Panics + /// + /// - If called on an intra `PredictionMode` + pub fn predict_inter_compound( + self, fi: &FrameInvariants, tile_rect: TileRect, p: usize, + po: PlaneOffset, dst: &mut PlaneRegionMut<'_, T>, width: usize, + height: usize, ref_frames: [RefType; 2], mvs: [MotionVector; 2], + buffer: &mut InterCompoundBuffers, + ) { + assert!(!self.is_intra()); + let frame_po = tile_rect.to_frame_plane_offset(po); + + let mode = fi.default_filter; + + for i in 0..2 { + if let Some(ref rec) = + fi.rec_buffer.frames[fi.ref_frames[ref_frames[i].to_index()] as usize] + { + let (row_frac, col_frac, src) = PredictionMode::get_mv_params( + &rec.frame.planes[p], + frame_po, + mvs[i], + ); + prep_8tap( + buffer.get_buffer_mut(i), + src, + width, + height, + col_frac, + row_frac, + mode, + mode, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + } + } + mc_avg( + dst, + buffer.get_buffer(0), + buffer.get_buffer(1), + width, + height, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + } + + /// Inter prediction that determines whether compound mode is being used based + /// on the second [`RefType`] in [`ref_frames`]. + pub fn predict_inter( + self, fi: &FrameInvariants, tile_rect: TileRect, p: usize, + po: PlaneOffset, dst: &mut PlaneRegionMut<'_, T>, width: usize, + height: usize, ref_frames: [RefType; 2], mvs: [MotionVector; 2], + compound_buffer: &mut InterCompoundBuffers, + ) { + let is_compound = ref_frames[1] != RefType::INTRA_FRAME + && ref_frames[1] != RefType::NONE_FRAME; + + if !is_compound { + self.predict_inter_single( + fi, + tile_rect, + p, + po, + dst, + width, + height, + ref_frames[0], + mvs[0], + ) + } else { + self.predict_inter_compound( + fi, + tile_rect, + p, + po, + dst, + width, + height, + ref_frames, + mvs, + compound_buffer, + ); + } + } +} + +/// A pair of buffers holding the interpolation of two references. Use for +/// compound inter prediction. +#[derive(Debug)] +pub struct InterCompoundBuffers { + data: ABox<[i16]>, +} + +impl InterCompoundBuffers { + // Size of one of the two buffers used. + const BUFFER_SIZE: usize = 1 << (2 * MAX_SB_SIZE_LOG2); + + /// Get the buffer for eith + #[inline] + fn get_buffer_mut(&mut self, i: usize) -> &mut [i16] { + match i { + 0 => &mut self.data[0..Self::BUFFER_SIZE], + 1 => &mut self.data[Self::BUFFER_SIZE..2 * Self::BUFFER_SIZE], + _ => panic!(), + } + } + + #[inline] + fn get_buffer(&self, i: usize) -> &[i16] { + match i { + 0 => &self.data[0..Self::BUFFER_SIZE], + 1 => &self.data[Self::BUFFER_SIZE..2 * Self::BUFFER_SIZE], + _ => panic!(), + } + } +} + +impl Default for InterCompoundBuffers { + fn default() -> Self { + Self { data: avec![0; 2 * Self::BUFFER_SIZE].into_boxed_slice() } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum InterIntraMode { + II_DC_PRED, + II_V_PRED, + II_H_PRED, + II_SMOOTH_PRED, + INTERINTRA_MODES, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum CompoundType { + COMPOUND_AVERAGE, + COMPOUND_WEDGE, + COMPOUND_DIFFWTD, + COMPOUND_TYPES, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum MotionMode { + SIMPLE_TRANSLATION, + OBMC_CAUSAL, // 2-sided OBMC + WARPED_CAUSAL, // 2-sided WARPED + MOTION_MODES, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum PaletteSize { + TWO_COLORS, + THREE_COLORS, + FOUR_COLORS, + FIVE_COLORS, + SIX_COLORS, + SEVEN_COLORS, + EIGHT_COLORS, + PALETTE_SIZES, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum PaletteColor { + PALETTE_COLOR_ONE, + PALETTE_COLOR_TWO, + PALETTE_COLOR_THREE, + PALETTE_COLOR_FOUR, + PALETTE_COLOR_FIVE, + PALETTE_COLOR_SIX, + PALETTE_COLOR_SEVEN, + PALETTE_COLOR_EIGHT, + PALETTE_COLORS, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] +pub enum FilterIntraMode { + FILTER_DC_PRED, + FILTER_V_PRED, + FILTER_H_PRED, + FILTER_D157_PRED, + FILTER_PAETH_PRED, + FILTER_INTRA_MODES, +} + +#[derive(Copy, Clone, Debug)] +pub enum IntraParam { + AngleDelta(i8), + Alpha(i16), + None, +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct AngleDelta { + pub y: i8, + pub uv: i8, +} + +#[derive(Copy, Clone, Default)] +pub struct IntraEdgeFilterParameters { + pub plane: usize, + pub above_ref_frame_types: Option<[RefType; 2]>, + pub left_ref_frame_types: Option<[RefType; 2]>, + pub above_mode: Option, + pub left_mode: Option, +} + +impl IntraEdgeFilterParameters { + pub fn new( + plane: usize, above_ctx: Option, + left_ctx: Option, + ) -> Self { + IntraEdgeFilterParameters { + plane, + above_mode: match above_ctx { + Some(bi) => match plane { + 0 => bi.luma_mode, + _ => bi.chroma_mode, + } + .into(), + None => None, + }, + left_mode: match left_ctx { + Some(bi) => match plane { + 0 => bi.luma_mode, + _ => bi.chroma_mode, + } + .into(), + None => None, + }, + above_ref_frame_types: above_ctx.map(|bi| bi.reference_types), + left_ref_frame_types: left_ctx.map(|bi| bi.reference_types), + } + } + + /// # Panics + /// + /// - If the appropriate ref frame types are not set on `self` + pub fn use_smooth_filter(self) -> bool { + let above_smooth = match self.above_mode { + Some(PredictionMode::SMOOTH_PRED) + | Some(PredictionMode::SMOOTH_V_PRED) + | Some(PredictionMode::SMOOTH_H_PRED) => { + self.plane == 0 + || self.above_ref_frame_types.unwrap()[0] == RefType::INTRA_FRAME + } + _ => false, + }; + + let left_smooth = match self.left_mode { + Some(PredictionMode::SMOOTH_PRED) + | Some(PredictionMode::SMOOTH_V_PRED) + | Some(PredictionMode::SMOOTH_H_PRED) => { + self.plane == 0 + || self.left_ref_frame_types.unwrap()[0] == RefType::INTRA_FRAME + } + _ => false, + }; + + above_smooth || left_smooth + } +} + +// Weights are quadratic from '1' to '1 / block_size', scaled by 2^sm_weight_log2_scale. +const sm_weight_log2_scale: u8 = 8; + +// Smooth predictor weights +#[rustfmt::skip] +static sm_weight_arrays: [u8; 2 * MAX_TX_SIZE] = [ + // Unused, because we always offset by bs, which is at least 2. + 0, 0, + // bs = 2 + 255, 128, + // bs = 4 + 255, 149, 85, 64, + // bs = 8 + 255, 197, 146, 105, 73, 50, 37, 32, + // bs = 16 + 255, 225, 196, 170, 145, 123, 102, 84, 68, 54, 43, 33, 26, 20, 17, 16, + // bs = 32 + 255, 240, 225, 210, 196, 182, 169, 157, 145, 133, 122, 111, 101, 92, 83, 74, + 66, 59, 52, 45, 39, 34, 29, 25, 21, 17, 14, 12, 10, 9, 8, 8, + // bs = 64 + 255, 248, 240, 233, 225, 218, 210, 203, 196, 189, 182, 176, 169, 163, 156, + 150, 144, 138, 133, 127, 121, 116, 111, 106, 101, 96, 91, 86, 82, 77, 73, 69, + 65, 61, 57, 54, 50, 47, 44, 41, 38, 35, 32, 29, 27, 25, 22, 20, 18, 16, 15, + 13, 12, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, 4, +]; + +#[inline(always)] +const fn get_scaled_luma_q0(alpha_q3: i16, ac_pred_q3: i16) -> i32 { + let scaled_luma_q6 = (alpha_q3 as i32) * (ac_pred_q3 as i32); + let abs_scaled_luma_q0 = (scaled_luma_q6.abs() + 32) >> 6; + if scaled_luma_q6 < 0 { + -abs_scaled_luma_q0 + } else { + abs_scaled_luma_q0 + } +} + +/// # Returns +/// +/// Initialized luma AC coefficients +/// +/// # Panics +/// +/// - If the block size is invalid for subsampling +/// +pub fn luma_ac<'ac, T: Pixel>( + ac: &'ac mut [MaybeUninit], ts: &mut TileStateMut<'_, T>, + tile_bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize, + fi: &FrameInvariants, +) -> &'ac mut [i16] { + use crate::context::MI_SIZE_LOG2; + + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let plane_bsize = bsize.subsampled_size(xdec, ydec).unwrap(); + + // ensure ac has the right length, so there aren't any uninitialized elements at the end + let ac = &mut ac[..plane_bsize.area()]; + + let bo = if bsize.is_sub8x8(xdec, ydec) { + let offset = bsize.sub8x8_offset(xdec, ydec); + tile_bo.with_offset(offset.0, offset.1) + } else { + tile_bo + }; + let rec = &ts.rec.planes[0]; + let luma = &rec.subregion(Area::BlockStartingAt { bo: bo.0 }); + let frame_bo = ts.to_frame_block_offset(bo); + + let frame_clipped_bw: usize = + ((fi.w_in_b - frame_bo.0.x) << MI_SIZE_LOG2).min(bsize.width()); + let frame_clipped_bh: usize = + ((fi.h_in_b - frame_bo.0.y) << MI_SIZE_LOG2).min(bsize.height()); + + // Similar to 'MaxLumaW' and 'MaxLumaH' stated in https://aomediacodec.github.io/av1-spec/#transform-block-semantics + let max_luma_w = if bsize.width() > BlockSize::BLOCK_8X8.width() { + let txw_log2 = tx_size.width_log2(); + ((frame_clipped_bw + (1 << txw_log2) - 1) >> txw_log2) << txw_log2 + } else { + bsize.width() + }; + let max_luma_h = if bsize.height() > BlockSize::BLOCK_8X8.height() { + let txh_log2 = tx_size.height_log2(); + ((frame_clipped_bh + (1 << txh_log2) - 1) >> txh_log2) << txh_log2 + } else { + bsize.height() + }; + + let w_pad = (bsize.width() - max_luma_w) >> (2 + xdec); + let h_pad = (bsize.height() - max_luma_h) >> (2 + ydec); + let cpu = fi.cpu_feature_level; + + (match (xdec, ydec) { + (0, 0) => pred_cfl_ac::, + (1, 0) => pred_cfl_ac::, + (_, _) => pred_cfl_ac::, + })(ac, luma, plane_bsize, w_pad, h_pad, cpu); + + // SAFETY: it relies on individual pred_cfl_ac implementations to initialize the ac + unsafe { slice_assume_init_mut(ac) } +} + +pub(crate) mod rust { + use super::*; + use std::mem::size_of; + + #[inline(always)] + pub fn dispatch_predict_intra( + mode: PredictionMode, variant: PredictionVariant, + dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize, + ac: &[i16], angle: isize, ief_params: Option, + edge_buf: &IntraEdge, _cpu: CpuFeatureLevel, + ) { + let width = tx_size.width(); + let height = tx_size.height(); + + // left pixels are ordered from bottom to top and right-aligned + let (left, top_left, above) = edge_buf.as_slices(); + + let above_slice = above; + let left_slice = &left[left.len().saturating_sub(height)..]; + let left_and_left_below_slice = + &left[left.len().saturating_sub(width + height)..]; + + match mode { + PredictionMode::DC_PRED => { + (match variant { + PredictionVariant::NONE => pred_dc_128, + PredictionVariant::LEFT => pred_dc_left, + PredictionVariant::TOP => pred_dc_top, + PredictionVariant::BOTH => pred_dc, + })(dst, above_slice, left_slice, width, height, bit_depth) + } + PredictionMode::V_PRED if angle == 90 => { + pred_v(dst, above_slice, width, height) + } + PredictionMode::H_PRED if angle == 180 => { + pred_h(dst, left_slice, width, height) + } + PredictionMode::H_PRED + | PredictionMode::V_PRED + | PredictionMode::D45_PRED + | PredictionMode::D135_PRED + | PredictionMode::D113_PRED + | PredictionMode::D157_PRED + | PredictionMode::D203_PRED + | PredictionMode::D67_PRED => pred_directional( + dst, + above_slice, + left_and_left_below_slice, + top_left, + angle as usize, + width, + height, + bit_depth, + ief_params, + ), + PredictionMode::SMOOTH_PRED => { + pred_smooth(dst, above_slice, left_slice, width, height) + } + PredictionMode::SMOOTH_V_PRED => { + pred_smooth_v(dst, above_slice, left_slice, width, height) + } + PredictionMode::SMOOTH_H_PRED => { + pred_smooth_h(dst, above_slice, left_slice, width, height) + } + PredictionMode::PAETH_PRED => { + pred_paeth(dst, above_slice, left_slice, top_left[0], width, height) + } + PredictionMode::UV_CFL_PRED => (match variant { + PredictionVariant::NONE => pred_cfl_128, + PredictionVariant::LEFT => pred_cfl_left, + PredictionVariant::TOP => pred_cfl_top, + PredictionVariant::BOTH => pred_cfl, + })( + dst, + ac, + angle as i16, + above_slice, + left_slice, + width, + height, + bit_depth, + ), + _ => unimplemented!(), + } + } + + pub(crate) fn pred_dc( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], width: usize, + height: usize, _bit_depth: usize, + ) { + let edges = left[..height].iter().chain(above[..width].iter()); + let len = (width + height) as u32; + let avg = (edges.fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }) + (len >> 1)) + / len; + let avg = T::cast_from(avg); + + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } + + pub(crate) fn pred_dc_128( + output: &mut PlaneRegionMut<'_, T>, _above: &[T], _left: &[T], + width: usize, height: usize, bit_depth: usize, + ) { + let v = T::cast_from(128u32 << (bit_depth - 8)); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(v); + } + } + + pub(crate) fn pred_dc_left( + output: &mut PlaneRegionMut<'_, T>, _above: &[T], left: &[T], + width: usize, height: usize, _bit_depth: usize, + ) { + let sum = left[..].iter().fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }); + let avg = T::cast_from((sum + (height >> 1) as u32) / height as u32); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } + + pub(crate) fn pred_dc_top( + output: &mut PlaneRegionMut<'_, T>, above: &[T], _left: &[T], + width: usize, height: usize, _bit_depth: usize, + ) { + let sum = above[..width].iter().fold(0u32, |acc, &v| { + let v: u32 = v.into(); + v + acc + }); + let avg = T::cast_from((sum + (width >> 1) as u32) / width as u32); + for line in output.rows_iter_mut().take(height) { + line[..width].fill(avg); + } + } + + pub(crate) fn pred_h( + output: &mut PlaneRegionMut<'_, T>, left: &[T], width: usize, + height: usize, + ) { + for (line, l) in output.rows_iter_mut().zip(left[..height].iter().rev()) { + line[..width].fill(*l); + } + } + + pub(crate) fn pred_v( + output: &mut PlaneRegionMut<'_, T>, above: &[T], width: usize, + height: usize, + ) { + for line in output.rows_iter_mut().take(height) { + line[..width].copy_from_slice(&above[..width]) + } + } + + pub(crate) fn pred_paeth( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], + above_left: T, width: usize, height: usize, + ) { + for r in 0..height { + let row = &mut output[r]; + for c in 0..width { + // Top-left pixel is fixed in libaom + let raw_top_left: i32 = above_left.into(); + let raw_left: i32 = left[height - 1 - r].into(); + let raw_top: i32 = above[c].into(); + + let p_base = raw_top + raw_left - raw_top_left; + let p_left = (p_base - raw_left).abs(); + let p_top = (p_base - raw_top).abs(); + let p_top_left = (p_base - raw_top_left).abs(); + + // Return nearest to base of left, top and top_left + if p_left <= p_top && p_left <= p_top_left { + row[c] = T::cast_from(raw_left); + } else if p_top <= p_top_left { + row[c] = T::cast_from(raw_top); + } else { + row[c] = T::cast_from(raw_top_left); + } + } + } + } + + pub(crate) fn pred_smooth( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], width: usize, + height: usize, + ) { + let below_pred = left[0]; // estimated by bottom-left pixel + let right_pred = above[width - 1]; // estimated by top-right pixel + let sm_weights_w = &sm_weight_arrays[width..]; + let sm_weights_h = &sm_weight_arrays[height..]; + + let log2_scale = 1 + sm_weight_log2_scale; + let scale = 1_u16 << sm_weight_log2_scale; + + // Weights sanity checks + assert!((sm_weights_w[0] as u16) < scale); + assert!((sm_weights_h[0] as u16) < scale); + assert!((scale - sm_weights_w[width - 1] as u16) < scale); + assert!((scale - sm_weights_h[height - 1] as u16) < scale); + // ensures no overflow when calculating predictor + assert!(log2_scale as usize + size_of::() < 31); + + for r in 0..height { + let row = &mut output[r]; + for c in 0..width { + let pixels = [above[c], below_pred, left[height - 1 - r], right_pred]; + + let weights = [ + sm_weights_h[r] as u16, + scale - sm_weights_h[r] as u16, + sm_weights_w[c] as u16, + scale - sm_weights_w[c] as u16, + ]; + + assert!( + scale >= (sm_weights_h[r] as u16) + && scale >= (sm_weights_w[c] as u16) + ); + + // Sum up weighted pixels + let mut this_pred: u32 = weights + .iter() + .zip(pixels.iter()) + .map(|(w, p)| { + let p: u32 = (*p).into(); + (*w as u32) * p + }) + .sum(); + this_pred = (this_pred + (1 << (log2_scale - 1))) >> log2_scale; + + row[c] = T::cast_from(this_pred); + } + } + } + + pub(crate) fn pred_smooth_h( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], width: usize, + height: usize, + ) { + let right_pred = above[width - 1]; // estimated by top-right pixel + let sm_weights = &sm_weight_arrays[width..]; + + let log2_scale = sm_weight_log2_scale; + let scale = 1_u16 << sm_weight_log2_scale; + + // Weights sanity checks + assert!((sm_weights[0] as u16) < scale); + assert!((scale - sm_weights[width - 1] as u16) < scale); + // ensures no overflow when calculating predictor + assert!(log2_scale as usize + size_of::() < 31); + + for r in 0..height { + let row = &mut output[r]; + for c in 0..width { + let pixels = [left[height - 1 - r], right_pred]; + let weights = [sm_weights[c] as u16, scale - sm_weights[c] as u16]; + + assert!(scale >= sm_weights[c] as u16); + + let mut this_pred: u32 = weights + .iter() + .zip(pixels.iter()) + .map(|(w, p)| { + let p: u32 = (*p).into(); + (*w as u32) * p + }) + .sum(); + this_pred = (this_pred + (1 << (log2_scale - 1))) >> log2_scale; + + row[c] = T::cast_from(this_pred); + } + } + } + + pub(crate) fn pred_smooth_v( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], width: usize, + height: usize, + ) { + let below_pred = left[0]; // estimated by bottom-left pixel + let sm_weights = &sm_weight_arrays[height..]; + + let log2_scale = sm_weight_log2_scale; + let scale = 1_u16 << sm_weight_log2_scale; + + // Weights sanity checks + assert!((sm_weights[0] as u16) < scale); + assert!((scale - sm_weights[height - 1] as u16) < scale); + // ensures no overflow when calculating predictor + assert!(log2_scale as usize + size_of::() < 31); + + for r in 0..height { + let row = &mut output[r]; + for c in 0..width { + let pixels = [above[c], below_pred]; + let weights = [sm_weights[r] as u16, scale - sm_weights[r] as u16]; + + assert!(scale >= sm_weights[r] as u16); + + let mut this_pred: u32 = weights + .iter() + .zip(pixels.iter()) + .map(|(w, p)| { + let p: u32 = (*p).into(); + (*w as u32) * p + }) + .sum(); + this_pred = (this_pred + (1 << (log2_scale - 1))) >> log2_scale; + + row[c] = T::cast_from(this_pred); + } + } + } + + pub(crate) fn pred_cfl_ac( + ac: &mut [MaybeUninit], luma: &PlaneRegion<'_, T>, + plane_bsize: BlockSize, w_pad: usize, h_pad: usize, _cpu: CpuFeatureLevel, + ) { + let max_luma_w = (plane_bsize.width() - w_pad * 4) << XDEC; + let max_luma_h = (plane_bsize.height() - h_pad * 4) << YDEC; + let max_luma_x: usize = max_luma_w.max(8) - (1 << XDEC); + let max_luma_y: usize = max_luma_h.max(8) - (1 << YDEC); + let mut sum: i32 = 0; + + let ac = &mut ac[..plane_bsize.area()]; + + for (sub_y, ac_rows) in + ac.chunks_exact_mut(plane_bsize.width()).enumerate() + { + for (sub_x, ac_item) in ac_rows.iter_mut().enumerate() { + // Refer to https://aomediacodec.github.io/av1-spec/#predict-chroma-from-luma-process + let luma_y = sub_y << YDEC; + let luma_x = sub_x << XDEC; + let y = luma_y.min(max_luma_y); + let x = luma_x.min(max_luma_x); + let mut sample: i16 = i16::cast_from(luma[y][x]); + if XDEC != 0 { + sample += i16::cast_from(luma[y][x + 1]); + } + if YDEC != 0 { + debug_assert!(XDEC != 0); + sample += i16::cast_from(luma[y + 1][x]) + + i16::cast_from(luma[y + 1][x + 1]); + } + sample <<= 3 - XDEC - YDEC; + ac_item.write(sample); + sum += sample as i32; + } + } + // SAFETY: the loop above has initialized all items + let ac = unsafe { slice_assume_init_mut(ac) }; + let shift = plane_bsize.width_log2() + plane_bsize.height_log2(); + let average = ((sum + (1 << (shift - 1))) >> shift) as i16; + + for val in ac { + *val -= average; + } + } + + pub(crate) fn pred_cfl_inner( + output: &mut PlaneRegionMut<'_, T>, ac: &[i16], alpha: i16, width: usize, + height: usize, bit_depth: usize, + ) { + if alpha == 0 { + return; + } + debug_assert!(ac.len() >= width * height); + assert!(output.plane_cfg.stride >= width); + assert!(output.rows_iter().len() >= height); + + let sample_max = (1 << bit_depth) - 1; + let avg: i32 = output[0][0].into(); + + for (line, luma) in + output.rows_iter_mut().zip(ac.chunks_exact(width)).take(height) + { + for (v, &l) in line[..width].iter_mut().zip(luma[..width].iter()) { + *v = T::cast_from( + (avg + get_scaled_luma_q0(alpha, l)).clamp(0, sample_max), + ); + } + } + } + + pub(crate) fn pred_cfl( + output: &mut PlaneRegionMut<'_, T>, ac: &[i16], alpha: i16, above: &[T], + left: &[T], width: usize, height: usize, bit_depth: usize, + ) { + pred_dc(output, above, left, width, height, bit_depth); + pred_cfl_inner(output, ac, alpha, width, height, bit_depth); + } + + pub(crate) fn pred_cfl_128( + output: &mut PlaneRegionMut<'_, T>, ac: &[i16], alpha: i16, above: &[T], + left: &[T], width: usize, height: usize, bit_depth: usize, + ) { + pred_dc_128(output, above, left, width, height, bit_depth); + pred_cfl_inner(output, ac, alpha, width, height, bit_depth); + } + + pub(crate) fn pred_cfl_left( + output: &mut PlaneRegionMut<'_, T>, ac: &[i16], alpha: i16, above: &[T], + left: &[T], width: usize, height: usize, bit_depth: usize, + ) { + pred_dc_left(output, above, left, width, height, bit_depth); + pred_cfl_inner(output, ac, alpha, width, height, bit_depth); + } + + pub(crate) fn pred_cfl_top( + output: &mut PlaneRegionMut<'_, T>, ac: &[i16], alpha: i16, above: &[T], + left: &[T], width: usize, height: usize, bit_depth: usize, + ) { + pred_dc_top(output, above, left, width, height, bit_depth); + pred_cfl_inner(output, ac, alpha, width, height, bit_depth); + } + + #[allow(clippy::collapsible_if)] + #[allow(clippy::collapsible_else_if)] + #[allow(clippy::needless_return)] + pub(crate) const fn select_ief_strength( + width: usize, height: usize, smooth_filter: bool, angle_delta: isize, + ) -> u8 { + let block_wh = width + height; + let abs_delta = angle_delta.unsigned_abs(); + + if smooth_filter { + if block_wh <= 8 { + if abs_delta >= 64 { + return 2; + } + if abs_delta >= 40 { + return 1; + } + } else if block_wh <= 16 { + if abs_delta >= 48 { + return 2; + } + if abs_delta >= 20 { + return 1; + } + } else if block_wh <= 24 { + if abs_delta >= 4 { + return 3; + } + } else { + return 3; + } + } else { + if block_wh <= 8 { + if abs_delta >= 56 { + return 1; + } + } else if block_wh <= 16 { + if abs_delta >= 40 { + return 1; + } + } else if block_wh <= 24 { + if abs_delta >= 32 { + return 3; + } + if abs_delta >= 16 { + return 2; + } + if abs_delta >= 8 { + return 1; + } + } else if block_wh <= 32 { + if abs_delta >= 32 { + return 3; + } + if abs_delta >= 4 { + return 2; + } + return 1; + } else { + return 3; + } + } + + return 0; + } + + pub(crate) const fn select_ief_upsample( + width: usize, height: usize, smooth_filter: bool, angle_delta: isize, + ) -> bool { + let block_wh = width + height; + let abs_delta = angle_delta.unsigned_abs(); + + if abs_delta == 0 || abs_delta >= 40 { + false + } else if smooth_filter { + block_wh <= 8 + } else { + block_wh <= 16 + } + } + + pub(crate) fn filter_edge( + size: usize, strength: u8, edge: &mut [T], + ) { + const INTRA_EDGE_KERNEL: [[u32; 5]; 3] = + [[0, 4, 8, 4, 0], [0, 5, 6, 5, 0], [2, 4, 4, 4, 2]]; + + if strength == 0 { + return; + } + + // Copy the edge buffer to avoid predicting from + // just-filtered samples. + let mut edge_filtered = [MaybeUninit::::uninit(); MAX_TX_SIZE * 4 + 1]; + let edge_filtered = + init_slice_repeat_mut(&mut edge_filtered[..edge.len()], T::zero()); + edge_filtered.copy_from_slice(&edge[..edge.len()]); + + for i in 1..size { + let mut s = 0; + + for j in 0..INTRA_EDGE_KERNEL[0].len() { + let k = (i + j).saturating_sub(2).min(size - 1); + s += INTRA_EDGE_KERNEL[(strength - 1) as usize][j] + * edge[k].to_u32().unwrap(); + } + + edge_filtered[i] = T::cast_from((s + 8) >> 4); + } + edge.copy_from_slice(edge_filtered); + } + + pub(crate) fn upsample_edge( + size: usize, edge: &mut [T], bit_depth: usize, + ) { + // The input edge should be valid in the -1..size range, + // where the -1 index is the top-left edge pixel. Since + // negative indices are unsafe in Rust, the caller is + // expected to globally offset it by 1, which makes the + // input range 0..=size. + let mut dup = [MaybeUninit::::uninit(); MAX_TX_SIZE]; + let dup = init_slice_repeat_mut(&mut dup[..size + 3], T::zero()); + dup[0] = edge[0]; + dup[1..=size + 1].copy_from_slice(&edge[0..=size]); + dup[size + 2] = edge[size]; + + // Past here the edge is being filtered, and its + // effective range is shifted from -1..size to + // -2..2*size-1. Again, because this is safe Rust, + // we cannot use negative indices, and the actual range + // will be 0..=2*size. The caller is expected to adjust + // its indices on receipt of the filtered edge. + edge[0] = dup[0]; + + for i in 0..size { + let mut s = -dup[i].to_i32().unwrap() + + (9 * dup[i + 1].to_i32().unwrap()) + + (9 * dup[i + 2].to_i32().unwrap()) + - dup[i + 3].to_i32().unwrap(); + s = ((s + 8) / 16).clamp(0, (1 << bit_depth) - 1); + + edge[2 * i + 1] = T::cast_from(s); + edge[2 * i + 2] = dup[i + 2]; + } + } + + pub(crate) const fn dr_intra_derivative(p_angle: usize) -> usize { + match p_angle { + 3 => 1023, + 6 => 547, + 9 => 372, + 14 => 273, + 17 => 215, + 20 => 178, + 23 => 151, + 26 => 132, + 29 => 116, + 32 => 102, + 36 => 90, + 39 => 80, + 42 => 71, + 45 => 64, + 48 => 57, + 51 => 51, + 54 => 45, + 58 => 40, + 61 => 35, + 64 => 31, + 67 => 27, + 70 => 23, + 73 => 19, + 76 => 15, + 81 => 11, + 84 => 7, + 87 => 3, + _ => 0, + } + } + + pub(crate) fn pred_directional( + output: &mut PlaneRegionMut<'_, T>, above: &[T], left: &[T], + top_left: &[T], p_angle: usize, width: usize, height: usize, + bit_depth: usize, ief_params: Option, + ) { + let sample_max = (1 << bit_depth) - 1; + + let max_x = output.plane_cfg.width as isize - 1; + let max_y = output.plane_cfg.height as isize - 1; + + let mut upsample_above = false; + let mut upsample_left = false; + + let mut above_edge: &[T] = above; + let mut left_edge: &[T] = left; + let top_left_edge: T = top_left[0]; + + let enable_edge_filter = ief_params.is_some(); + + // Initialize above and left edge buffers of the largest possible needed size if upsampled + // The first value is the top left pixel, also mutable and indexed at -1 in the spec + let mut above_filtered = [MaybeUninit::::uninit(); MAX_TX_SIZE * 4 + 1]; + let above_filtered = init_slice_repeat_mut( + &mut above_filtered[..=(width + height) * 2], + T::zero(), + ); + let mut left_filtered = [MaybeUninit::::uninit(); MAX_TX_SIZE * 4 + 1]; + let left_filtered = init_slice_repeat_mut( + &mut left_filtered[..=(width + height) * 2], + T::zero(), + ); + + if enable_edge_filter { + let above_len = above.len().min(above_filtered.len() - 1); + let left_len = left.len().min(left_filtered.len() - 1); + above_filtered[1..=above_len].clone_from_slice(&above[..above_len]); + for i in 1..=left_len { + left_filtered[i] = left[left.len() - i]; + } + + let smooth_filter = ief_params.unwrap().use_smooth_filter(); + + if p_angle != 90 && p_angle != 180 { + above_filtered[0] = top_left_edge; + left_filtered[0] = top_left_edge; + + let num_px = ( + width.min((max_x - output.rect().x + 1).try_into().unwrap()) + + if p_angle < 90 { height } else { 0 } + + 1, // above + height.min((max_y - output.rect().y + 1).try_into().unwrap()) + + if p_angle > 180 { width } else { 0 } + + 1, // left + ); + + let filter_strength = select_ief_strength( + width, + height, + smooth_filter, + p_angle as isize - 90, + ); + filter_edge(num_px.0, filter_strength, above_filtered); + let filter_strength = select_ief_strength( + width, + height, + smooth_filter, + p_angle as isize - 180, + ); + filter_edge(num_px.1, filter_strength, left_filtered); + } + + let num_px = ( + width + if p_angle < 90 { height } else { 0 }, // above + height + if p_angle > 180 { width } else { 0 }, // left + ); + + upsample_above = select_ief_upsample( + width, + height, + smooth_filter, + p_angle as isize - 90, + ); + if upsample_above { + upsample_edge(num_px.0, above_filtered, bit_depth); + } + upsample_left = select_ief_upsample( + width, + height, + smooth_filter, + p_angle as isize - 180, + ); + if upsample_left { + upsample_edge(num_px.1, left_filtered, bit_depth); + } + + left_filtered.reverse(); + above_edge = above_filtered; + left_edge = left_filtered; + } + + let dx = if p_angle < 90 { + dr_intra_derivative(p_angle) + } else if p_angle > 90 && p_angle < 180 { + dr_intra_derivative(180 - p_angle) + } else { + 0 // undefined + }; + + let dy = if p_angle > 90 && p_angle < 180 { + dr_intra_derivative(p_angle - 90) + } else if p_angle > 180 { + dr_intra_derivative(270 - p_angle) + } else { + 0 // undefined + }; + + // edge buffer index offsets applied due to the fact + // that we cannot safely use negative indices in Rust + let upsample_above = upsample_above as usize; + let upsample_left = upsample_left as usize; + let offset_above = (enable_edge_filter as usize) << upsample_above; + let offset_left = (enable_edge_filter as usize) << upsample_left; + + if p_angle < 90 { + for i in 0..height { + let row = &mut output[i]; + for j in 0..width { + let idx = (i + 1) * dx; + let base = (idx >> (6 - upsample_above)) + (j << upsample_above); + let shift = (((idx << upsample_above) >> 1) & 31) as i32; + let max_base_x = (height + width - 1) << upsample_above; + let v = (if base < max_base_x { + let a: i32 = above_edge[base + offset_above].into(); + let b: i32 = above_edge[base + 1 + offset_above].into(); + round_shift(a * (32 - shift) + b * shift, 5) + } else { + let c: i32 = above_edge[max_base_x + offset_above].into(); + c + }) + .clamp(0, sample_max); + row[j] = T::cast_from(v); + } + } + } else if p_angle > 90 && p_angle < 180 { + for i in 0..height { + let row = &mut output[i]; + for j in 0..width { + let idx = (j << 6) as isize - ((i + 1) * dx) as isize; + let base = idx >> (6 - upsample_above); + if base >= -(1 << upsample_above) { + let shift = (((idx << upsample_above) >> 1) & 31) as i32; + let a: i32 = if !enable_edge_filter && base < 0 { + top_left_edge + } else { + above_edge[(base + offset_above as isize) as usize] + } + .into(); + let b: i32 = + above_edge[(base + 1 + offset_above as isize) as usize].into(); + let v = round_shift(a * (32 - shift) + b * shift, 5) + .clamp(0, sample_max); + row[j] = T::cast_from(v); + } else { + let idx = (i << 6) as isize - ((j + 1) * dy) as isize; + let base = idx >> (6 - upsample_left); + let shift = (((idx << upsample_left) >> 1) & 31) as i32; + let l = left_edge.len() - 1; + let a: i32 = if !enable_edge_filter && base < 0 { + top_left_edge + } else if (base + offset_left as isize) == -2 { + left_edge[0] + } else { + left_edge[l - (base + offset_left as isize) as usize] + } + .into(); + let b: i32 = if (base + offset_left as isize) == -2 { + left_edge[1] + } else { + left_edge[l - (base + offset_left as isize + 1) as usize] + } + .into(); + let v = round_shift(a * (32 - shift) + b * shift, 5) + .clamp(0, sample_max); + row[j] = T::cast_from(v); + } + } + } + } else if p_angle > 180 { + for i in 0..height { + let row = &mut output[i]; + for j in 0..width { + let idx = (j + 1) * dy; + let base = (idx >> (6 - upsample_left)) + (i << upsample_left); + let shift = (((idx << upsample_left) >> 1) & 31) as i32; + let l = left_edge.len() - 1; + let a: i32 = left_edge[l.saturating_sub(base + offset_left)].into(); + let b: i32 = + left_edge[l.saturating_sub(base + offset_left + 1)].into(); + let v = + round_shift(a * (32 - shift) + b * shift, 5).clamp(0, sample_max); + row[j] = T::cast_from(v); + } + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::predict::rust::*; + use num_traits::*; + + #[test] + fn pred_matches_u8() { + let edge_buf = + Aligned::from_fn(|i| (i + 32).saturating_sub(MAX_TX_SIZE * 2).as_()); + let (all_left, top_left, above) = IntraEdge::mock(&edge_buf).as_slices(); + let left = &all_left[all_left.len() - 4..]; + + let mut output = Plane::from_slice(&[0u8; 4 * 4], 4); + + pred_dc(&mut output.as_region_mut(), above, left, 4, 4, 8); + assert_eq!(&output.data[..], [32u8; 16]); + + pred_dc_top(&mut output.as_region_mut(), above, left, 4, 4, 8); + assert_eq!(&output.data[..], [35u8; 16]); + + pred_dc_left(&mut output.as_region_mut(), above, left, 4, 4, 8); + assert_eq!(&output.data[..], [30u8; 16]); + + pred_dc_128(&mut output.as_region_mut(), above, left, 4, 4, 8); + assert_eq!(&output.data[..], [128u8; 16]); + + pred_v(&mut output.as_region_mut(), above, 4, 4); + assert_eq!( + &output.data[..], + [33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36] + ); + + pred_h(&mut output.as_region_mut(), left, 4, 4); + assert_eq!( + &output.data[..], + [31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28] + ); + + pred_paeth(&mut output.as_region_mut(), above, left, top_left[0], 4, 4); + assert_eq!( + &output.data[..], + [32, 34, 35, 36, 30, 32, 32, 36, 29, 32, 32, 32, 28, 28, 32, 32] + ); + + pred_smooth(&mut output.as_region_mut(), above, left, 4, 4); + assert_eq!( + &output.data[..], + [32, 34, 35, 35, 30, 32, 33, 34, 29, 31, 32, 32, 29, 30, 32, 32] + ); + + pred_smooth_h(&mut output.as_region_mut(), above, left, 4, 4); + assert_eq!( + &output.data[..], + [31, 33, 34, 35, 30, 33, 34, 35, 29, 32, 34, 34, 28, 31, 33, 34] + ); + + pred_smooth_v(&mut output.as_region_mut(), above, left, 4, 4); + assert_eq!( + &output.data[..], + [33, 34, 35, 36, 31, 31, 32, 33, 30, 30, 30, 31, 29, 30, 30, 30] + ); + + let left = &all_left[all_left.len() - 8..]; + let angles = [ + 3, 6, 9, 14, 17, 20, 23, 26, 29, 32, 36, 39, 42, 45, 48, 51, 54, 58, 61, + 64, 67, 70, 73, 76, 81, 84, 87, + ]; + let expected = [ + [40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [36, 37, 38, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [35, 36, 37, 38, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40], + [35, 36, 37, 38, 37, 38, 39, 40, 39, 40, 40, 40, 40, 40, 40, 40], + [35, 36, 37, 38, 37, 38, 39, 40, 38, 39, 40, 40, 40, 40, 40, 40], + [35, 36, 37, 38, 36, 37, 38, 39, 38, 39, 40, 40, 39, 40, 40, 40], + [34, 35, 36, 37, 36, 37, 38, 39, 37, 38, 39, 40, 39, 40, 40, 40], + [34, 35, 36, 37, 36, 37, 38, 39, 37, 38, 39, 40, 38, 39, 40, 40], + [34, 35, 36, 37, 35, 36, 37, 38, 36, 37, 38, 39, 37, 38, 39, 40], + [34, 35, 36, 37, 35, 36, 37, 38, 36, 37, 38, 39, 37, 38, 39, 40], + [34, 35, 36, 37, 35, 36, 37, 38, 36, 37, 38, 39, 37, 38, 39, 40], + [34, 35, 36, 37, 35, 36, 37, 38, 35, 36, 37, 38, 36, 37, 38, 39], + [34, 35, 36, 37, 34, 35, 36, 37, 35, 36, 37, 38, 36, 37, 38, 39], + [34, 35, 36, 37, 34, 35, 36, 37, 35, 36, 37, 38, 36, 37, 38, 39], + [34, 35, 36, 37, 34, 35, 36, 37, 35, 36, 37, 38, 35, 36, 37, 38], + [33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37, 35, 36, 37, 38], + [33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37, 35, 36, 37, 38], + [33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37, 34, 35, 36, 37], + [33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37, 34, 35, 36, 37], + [33, 34, 35, 36, 33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37], + [33, 34, 35, 36, 33, 34, 35, 36, 34, 35, 36, 37, 34, 35, 36, 37], + [33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36], + [33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36, 33, 34, 35, 36], + ]; + for (&angle, expected) in angles.iter().zip(expected.iter()) { + pred_directional( + &mut output.as_region_mut(), + above, + left, + top_left, + angle, + 4, + 4, + 8, + None, + ); + assert_eq!(&output.data[..], expected); + } + } + + #[test] + fn pred_max() { + let max12bit = 4096 - 1; + let above = [max12bit; 32]; + let left = [max12bit; 32]; + + let mut o = Plane::from_slice(&vec![0u16; 32 * 32], 32); + + pred_dc(&mut o.as_region_mut(), &above[..4], &left[..4], 4, 4, 16); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + pred_h(&mut o.as_region_mut(), &left[..4], 4, 4); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + pred_v(&mut o.as_region_mut(), &above[..4], 4, 4); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + let above_left = max12bit; + + pred_paeth( + &mut o.as_region_mut(), + &above[..4], + &left[..4], + above_left, + 4, + 4, + ); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + pred_smooth(&mut o.as_region_mut(), &above[..4], &left[..4], 4, 4); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + pred_smooth_h(&mut o.as_region_mut(), &above[..4], &left[..4], 4, 4); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + + pred_smooth_v(&mut o.as_region_mut(), &above[..4], &left[..4], 4, 4); + + for l in o.data.chunks(32).take(4) { + for v in l[..4].iter() { + assert_eq!(*v, max12bit); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/quantize/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/quantize/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,385 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] + +mod tables; + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::quantize::*; + } else { + pub use self::rust::*; + } +} + +pub use tables::*; + +use crate::scan_order::av1_scan_orders; +use crate::transform::{TxSize, TxType}; +use crate::util::*; +use std::mem; +use std::num::{NonZeroU16, NonZeroU32, NonZeroU64}; + +pub fn get_log_tx_scale(tx_size: TxSize) -> usize { + let num_pixels = tx_size.area(); + + Into::::into(num_pixels > 256) + + Into::::into(num_pixels > 1024) +} + +pub fn dc_q(qindex: u8, delta_q: i8, bit_depth: usize) -> NonZeroU16 { + let dc_q: [&[NonZeroU16; 256]; 3] = + [&dc_qlookup_Q3, &dc_qlookup_10_Q3, &dc_qlookup_12_Q3]; + let bd = ((bit_depth ^ 8) >> 1).min(2); + dc_q[bd][((qindex as isize + delta_q as isize).max(0) as usize).min(255)] +} + +pub fn ac_q(qindex: u8, delta_q: i8, bit_depth: usize) -> NonZeroU16 { + let ac_q: [&[NonZeroU16; 256]; 3] = + [&ac_qlookup_Q3, &ac_qlookup_10_Q3, &ac_qlookup_12_Q3]; + let bd = ((bit_depth ^ 8) >> 1).min(2); + ac_q[bd][((qindex as isize + delta_q as isize).max(0) as usize).min(255)] +} + +// TODO: Handle lossless properly. +fn select_qi(quantizer: i64, qlookup: &[NonZeroU16; QINDEX_RANGE]) -> u8 { + if quantizer < qlookup[MINQ].get() as i64 { + MINQ as u8 + } else if quantizer >= qlookup[MAXQ].get() as i64 { + MAXQ as u8 + } else { + match qlookup + .binary_search(&NonZeroU16::new(quantizer as u16).expect("Not zero")) + { + Ok(qi) => qi as u8, + Err(qi) => { + debug_assert!(qi > MINQ); + debug_assert!(qi <= MAXQ); + // Pick the closest quantizer in the log domain. + let qthresh = + (qlookup[qi - 1].get() as i32) * (qlookup[qi].get() as i32); + let q2_i32 = (quantizer as i32) * (quantizer as i32); + if q2_i32 < qthresh { + (qi - 1) as u8 + } else { + qi as u8 + } + } + } + } +} + +pub fn select_dc_qi(quantizer: i64, bit_depth: usize) -> u8 { + let qlookup = match bit_depth { + 8 => &dc_qlookup_Q3, + 10 => &dc_qlookup_10_Q3, + 12 => &dc_qlookup_12_Q3, + _ => unimplemented!(), + }; + select_qi(quantizer, qlookup) +} + +pub fn select_ac_qi(quantizer: i64, bit_depth: usize) -> u8 { + let qlookup = match bit_depth { + 8 => &ac_qlookup_Q3, + 10 => &ac_qlookup_10_Q3, + 12 => &ac_qlookup_12_Q3, + _ => unimplemented!(), + }; + select_qi(quantizer, qlookup) +} + +#[derive(Debug, Clone, Copy)] +pub struct QuantizationContext { + log_tx_scale: usize, + dc_quant: NonZeroU16, + dc_offset: u32, + dc_mul_add: (u32, u32, u32), + + ac_quant: NonZeroU16, + ac_offset_eob: u32, + ac_offset0: u32, + ac_offset1: u32, + ac_mul_add: (u32, u32, u32), +} + +impl Default for QuantizationContext { + fn default() -> Self { + QuantizationContext { + dc_quant: NonZeroU16::new(1).expect("Not zero"), + ac_quant: NonZeroU16::new(1).expect("Not zero"), + log_tx_scale: Default::default(), + dc_offset: Default::default(), + dc_mul_add: Default::default(), + ac_offset_eob: Default::default(), + ac_offset0: Default::default(), + ac_offset1: Default::default(), + ac_mul_add: Default::default(), + } + } +} + +fn divu_gen(d: NonZeroU32) -> (u32, u32, u32) { + let nbits = (mem::size_of_val(&d) as u64) * 8; + let m = nbits - d.leading_zeros() as u64 - 1; + if d.is_power_of_two() { + (0xFFFF_FFFF, 0xFFFF_FFFF, m as u32) + } else { + let d = NonZeroU64::from(d); + let t = (1u64 << (m + nbits)) / d; + + let d = d.get(); + let r = (t * d + d) & ((1 << nbits) - 1); + if r <= 1u64 << m { + (t as u32 + 1, 0u32, m as u32) + } else { + (t as u32, t as u32, m as u32) + } + } +} + +#[inline] +const fn divu_pair(x: u32, d: (u32, u32, u32)) -> u32 { + let x = x as u64; + let (a, b, shift) = d; + let shift = shift as u64; + let a = a as u64; + let b = b as u64; + + (((a * x + b) >> 32) >> shift) as u32 +} + +#[inline] +const fn copysign(value: u32, signed: i32) -> i32 { + if signed < 0 { + -(value as i32) + } else { + value as i32 + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::transform::TxSize::*; + + #[test] + fn test_divu_pair() { + for d in 1..1024 { + for x in 0..1000 { + let ab = divu_gen(NonZeroU32::new(d).unwrap()); + assert_eq!(x / d, divu_pair(x, ab)); + } + } + } + #[test] + fn gen_divu_table() { + let b: Vec<(u32, u32, u32)> = + dc_qlookup_Q3.iter().map(|&v| divu_gen(v.into())).collect(); + + println!("{:?}", b); + } + #[test] + fn test_tx_log_scale() { + let tx_sizes = [ + (TX_4X4, 0), + (TX_8X8, 0), + (TX_16X16, 0), + (TX_32X32, 1), + (TX_64X64, 2), + (TX_4X8, 0), + (TX_8X4, 0), + (TX_8X16, 0), + (TX_16X8, 0), + (TX_16X32, 1), + (TX_32X16, 1), + (TX_32X64, 2), + (TX_64X32, 2), + (TX_4X16, 0), + (TX_16X4, 0), + (TX_8X32, 0), + (TX_32X8, 0), + (TX_16X64, 1), + (TX_64X16, 1), + ]; + for &tx_size in tx_sizes.iter() { + assert!(tx_size.1 == get_log_tx_scale(tx_size.0)); + } + } +} + +impl QuantizationContext { + pub fn update( + &mut self, qindex: u8, tx_size: TxSize, is_intra: bool, bit_depth: usize, + dc_delta_q: i8, ac_delta_q: i8, + ) { + self.log_tx_scale = get_log_tx_scale(tx_size); + + self.dc_quant = dc_q(qindex, dc_delta_q, bit_depth); + self.dc_mul_add = divu_gen(self.dc_quant.into()); + + self.ac_quant = ac_q(qindex, ac_delta_q, bit_depth); + self.ac_mul_add = divu_gen(self.ac_quant.into()); + + // All of these biases were derived by measuring the cost of coding + // a zero vs coding a one on any given coefficient position, or, in + // the case of the EOB bias, the cost of coding the block with + // the chosen EOB (rounding to one) vs rounding to zero and continuing + // to choose a new EOB. This was done over several clips, with the + // average of the bit costs taken over all blocks in the set, and a new + // bias derived via the method outlined in Jean-Marc Valin's + // Journal of Dubious Theoretical Results[1], aka: + // + // lambda = ln(2) / 6.0 + // threshold = 0.5 + (lambda * avg_rate_diff) / 2.0 + // bias = 1 - threshold + // + // lambda is a constant since our offsets are already adjusted for the + // quantizer. + // + // Biases were then updated, and cost collection was re-run, until + // the calculated biases started to converge after 2-4 iterations. + // + // In theory, the rounding biases for inter should be somewhat smaller + // than the biases for intra, but this turns out to only be the case + // for EOB optimization, or at least, is covered by EOB optimization. + // The RD-optimal rounding biases for the actual coefficients seem + // to be quite close (+/- 1/256), for both inter and intra, + // post-deadzoning. + // + // [1] https://jmvalin.ca/notes/theoretical_results.pdf + self.dc_offset = + self.dc_quant.get() as u32 * (if is_intra { 109 } else { 108 }) / 256; + self.ac_offset0 = + self.ac_quant.get() as u32 * (if is_intra { 98 } else { 97 }) / 256; + self.ac_offset1 = + self.ac_quant.get() as u32 * (if is_intra { 109 } else { 108 }) / 256; + self.ac_offset_eob = + self.ac_quant.get() as u32 * (if is_intra { 88 } else { 44 }) / 256; + } + + #[inline] + pub fn quantize( + &self, coeffs: &[T], qcoeffs: &mut [T], tx_size: TxSize, tx_type: TxType, + ) -> u16 { + let scan = av1_scan_orders[tx_size as usize][tx_type as usize].scan; + let iscan = av1_scan_orders[tx_size as usize][tx_type as usize].iscan; + + qcoeffs[0] = { + let coeff: i32 = i32::cast_from(coeffs[0]) << self.log_tx_scale; + let abs_coeff = coeff.unsigned_abs(); + T::cast_from(copysign( + divu_pair(abs_coeff + self.dc_offset, self.dc_mul_add), + coeff, + )) + }; + + // Find the last non-zero coefficient using our smaller biases and + // zero everything else. + // This threshold is such that `abs(coeff) < deadzone` implies: + // (abs(coeff << log_tx_scale) + ac_offset_eob) / ac_quant == 0 + let deadzone = T::cast_from( + (self.ac_quant.get() as usize - self.ac_offset_eob as usize) + .align_power_of_two_and_shift(self.log_tx_scale), + ); + let eob = { + let eob_minus_one = iscan + .iter() + .zip(coeffs) + .map(|(&i, &c)| if c.abs() >= deadzone { i } else { 0 }) + .max() + .unwrap_or(0); + // We skip the DC coefficient since it has its own quantizer index. + if eob_minus_one > 0 { + eob_minus_one + 1 + } else { + u16::from(qcoeffs[0] != T::cast_from(0)) + } + }; + + // Here we use different rounding biases depending on whether we've + // had recent coefficients that are larger than one, or less than + // one. The reason for this is that a block usually has a chunk of + // large coefficients and a tail of zeroes and ones, and the tradeoffs + // for coding these two are different. In the tail of zeroes and ones, + // you'll likely end up spending most bits just saying where that + // coefficient is in the block, whereas in the chunk of larger + // coefficients, most bits will be spent on coding its magnitude. + // To that end, we want to bias more toward rounding to zero for + // that tail of zeroes and ones than we do for the larger coefficients. + let mut level_mode = 1; + let ac_quant = self.ac_quant.get() as u32; + for &pos in scan.iter().take(usize::from(eob)).skip(1) { + let coeff = i32::cast_from(coeffs[pos as usize]) << self.log_tx_scale; + let abs_coeff = coeff.unsigned_abs(); + + let level0 = divu_pair(abs_coeff, self.ac_mul_add); + let offset = if level0 > 1 - level_mode { + self.ac_offset1 + } else { + self.ac_offset0 + }; + + let abs_qcoeff: u32 = + level0 + (abs_coeff + offset >= (level0 + 1) * ac_quant) as u32; + if level_mode != 0 && abs_qcoeff == 0 { + level_mode = 0; + } else if abs_qcoeff > 1 { + level_mode = 1; + } + + qcoeffs[pos as usize] = T::cast_from(copysign(abs_qcoeff, coeff)); + } + + // Rather than zeroing the tail in scan order, assume that qcoeffs is + // pre-filled with zeros. + + // Check the eob is correct + debug_assert_eq!( + usize::from(eob), + scan + .iter() + .rposition(|&i| qcoeffs[i as usize] != T::cast_from(0)) + .map(|n| n + 1) + .unwrap_or(0) + ); + + eob + } +} + +pub mod rust { + use super::*; + use crate::cpu_features::CpuFeatureLevel; + use std::mem::MaybeUninit; + + pub fn dequantize( + qindex: u8, coeffs: &[T], _eob: u16, rcoeffs: &mut [MaybeUninit], + tx_size: TxSize, bit_depth: usize, dc_delta_q: i8, ac_delta_q: i8, + _cpu: CpuFeatureLevel, + ) { + let log_tx_scale = get_log_tx_scale(tx_size) as i32; + let offset = (1 << log_tx_scale) - 1; + + let dc_quant = dc_q(qindex, dc_delta_q, bit_depth).get() as i32; + let ac_quant = ac_q(qindex, ac_delta_q, bit_depth).get() as i32; + + for (i, (r, c)) in rcoeffs + .iter_mut() + .zip(coeffs.iter().map(|&c| i32::cast_from(c))) + .enumerate() + { + let quant = if i == 0 { dc_quant } else { ac_quant }; + r.write(T::cast_from( + (c * quant + ((c >> 31) & offset)) >> log_tx_scale, + )); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/quantize/tables.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/quantize/tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/quantize/tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,207 @@ +// Copyright (c) 2017-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::{ + mem::{transmute, MaybeUninit}, + num::NonZeroU16, +}; + +pub const MINQ: usize = 0; +pub const MAXQ: usize = 255; +pub(super) const QINDEX_RANGE: usize = MAXQ - MINQ + 1; + +pub(super) static dc_qlookup_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(dc_qlookup_Q3_raw); + +pub(super) static dc_qlookup_10_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(dc_qlookup_10_Q3_raw); + +pub(super) static dc_qlookup_12_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(dc_qlookup_12_Q3_raw); + +pub(super) static ac_qlookup_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(ac_qlookup_Q3_raw); + +pub(super) static ac_qlookup_10_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(ac_qlookup_10_Q3_raw); + +pub(super) static ac_qlookup_12_Q3: [NonZeroU16; QINDEX_RANGE] = + nonzero_checked(ac_qlookup_12_Q3_raw); + +#[rustfmt::skip] +const dc_qlookup_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, + 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, + 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, + 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, + 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, + 66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76, + 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, + 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, + 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134, + 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, + 166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, + 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247, + 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, + 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, + 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441, + 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, + 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, + 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, + 1184, 1232, 1282, 1336, +]; + +#[rustfmt::skip] +const dc_qlookup_10_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, + 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82, + 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, + 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, + 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, + 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, + 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, + 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, + 394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, + 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, + 576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, + 698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831, + 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, + 1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, + 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436, + 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, + 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, + 2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, + 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823, + 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347, +]; + +#[rustfmt::skip] +const dc_qlookup_12_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, + 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, + 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, + 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, + 596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, + 768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919, + 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, + 1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, + 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, + 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, + 1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, + 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, + 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, + 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, + 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, + 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, + 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, + 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, + 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966, + 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, + 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, + 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118, + 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, + 19718, 20521, 21387, +]; + +#[rustfmt::skip] +const ac_qlookup_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, + 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, + 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, + 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, + 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, + 456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571, + 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, + 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, + 951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196, + 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537, + 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, +]; + +#[rustfmt::skip] +const ac_qlookup_10_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, + 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92, + 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, + 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, + 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, + 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, + 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, + 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, + 474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571, + 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, + 725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, + 905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118, + 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, + 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, + 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, + 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, + 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, + 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, + 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, + 6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312, +]; + +#[rustfmt::skip] +const ac_qlookup_12_Q3_raw: [u16; QINDEX_RANGE] = [ + 4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, + 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, + 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, + 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, + 679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, + 884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067, + 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, + 1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, + 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693, + 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, + 2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, + 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943, + 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, + 3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, + 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, + 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, + 6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, + 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, + 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, + 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, + 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062, + 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, + 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, + 28143, 28687, 29247, +]; + +/// # Panics +/// +/// - If any value is zero +#[allow(clippy::let_unit_value)] +#[allow(clippy::unused_unit)] +const fn nonzero_checked( + raw: [u16; QINDEX_RANGE], +) -> [NonZeroU16; QINDEX_RANGE] { + // SAFETY: We initialize everything before exiting this function + unsafe { + let mut nonzero = [MaybeUninit::uninit(); QINDEX_RANGE]; + let mut i = 0; + while i < QINDEX_RANGE { + let _ = if raw[i] == 0 { [(); 0][i] } else { () }; + nonzero[i] = MaybeUninit::new(NonZeroU16::new_unchecked(raw[i])); + i += 1; + } + transmute(nonzero) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rate.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rate.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rate.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1647 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::cmp; + +use crate::api::color::ChromaSampling; +use crate::api::ContextInner; +use crate::encoder::TEMPORAL_DELIMITER; +use crate::quantize::{ac_q, dc_q, select_ac_qi, select_dc_qi}; +use crate::util::{ + bexp64, bexp_q24, blog64, clamp, q24_to_q57, q57, q57_to_q24, Pixel, +}; + +// The number of frame sub-types for which we track distinct parameters. +// This does not include FRAME_SUBTYPE_SEF, because we don't need to do any +// parameter tracking for Show Existing Frame frames. +pub const FRAME_NSUBTYPES: usize = 4; + +pub const FRAME_SUBTYPE_I: usize = 0; +pub const FRAME_SUBTYPE_P: usize = 1; +#[allow(unused)] +pub const FRAME_SUBTYPE_B0: usize = 2; +#[allow(unused)] +pub const FRAME_SUBTYPE_B1: usize = 3; +pub const FRAME_SUBTYPE_SEF: usize = 4; + +const PASS_SINGLE: i32 = 0; +const PASS_1: i32 = 1; +const PASS_2: i32 = 2; +const PASS_2_PLUS_1: i32 = 3; + +// Magic value at the start of the 2-pass stats file +const TWOPASS_MAGIC: i32 = 0x50324156; +// Version number for the 2-pass stats file +const TWOPASS_VERSION: i32 = 1; +// 4 byte magic + 4 byte version + 4 byte TU count + 4 byte SEF frame count +// + FRAME_NSUBTYPES*(4 byte frame count + 1 byte exp + 8 byte scale_sum) +pub(crate) const TWOPASS_HEADER_SZ: usize = 16 + FRAME_NSUBTYPES * (4 + 1 + 8); +// 4 byte frame type (show_frame and fti jointly coded) + 4 byte log_scale_q24 +const TWOPASS_PACKET_SZ: usize = 8; + +const SEF_BITS: i64 = 24; + +// The scale of AV1 quantizer tables (relative to the pixel domain), i.e., Q3. +pub(crate) const QSCALE: i32 = 3; + +// We clamp the actual I and B frame delays to a minimum of 10 to work +// within the range of values where later incrementing the delay works as +// designed. +// 10 is not an exact choice, but rather a good working trade-off. +const INTER_DELAY_TARGET_MIN: i32 = 10; + +// The base quantizer for a frame is adjusted based on the frame type using the +// formula (log_qp*mqp + dqp), where log_qp is the base-2 logarithm of the +// "linear" quantizer (the actual factor by which coefficients are divided). +// Because log_qp has an implicit offset built in based on the scale of the +// coefficients (which depends on the pixel bit depth and the transform +// scale), we normalize the quantizer to the equivalent for 8-bit pixels with +// orthonormal transforms for the purposes of rate modeling. +const MQP_Q12: &[i32; FRAME_NSUBTYPES] = &[ + // TODO: Use a const function once f64 operations in const functions are + // stable. + (1.0 * (1 << 12) as f64) as i32, + (1.0 * (1 << 12) as f64) as i32, + (1.0 * (1 << 12) as f64) as i32, + (1.0 * (1 << 12) as f64) as i32, +]; + +// The ratio 33_810_170.0 / 86_043_287.0 was derived by approximating the median +// of a change of 15 quantizer steps in the quantizer tables. +const DQP_Q57: &[i64; FRAME_NSUBTYPES] = &[ + (-(33_810_170.0 / 86_043_287.0) * (1i64 << 57) as f64) as i64, + (0.0 * (1i64 << 57) as f64) as i64, + ((33_810_170.0 / 86_043_287.0) * (1i64 << 57) as f64) as i64, + (2.0 * (33_810_170.0 / 86_043_287.0) * (1i64 << 57) as f64) as i64, +]; + +// For 8-bit-depth inter frames, log_q_y is derived from log_target_q with a +// linear model: +// log_q_y = log_target_q + (log_target_q >> 32) * Q_MODEL_MUL + Q_MODEL_ADD +// Derivation of the linear models: +// https://github.com/xiph/rav1e/blob/d02bdbd3b0b7b2cb9fc301031cc6a4e67a567a5c/doc/quantizer-weight-analysis.ipynb +#[rustfmt::skip] +const Q_MODEL_ADD: [i64; 4] = [ + // 4:2:0 + -0x24_4FE7_ECB3_DD90, + // 4:2:2 + -0x37_41DA_38AD_0924, + // 4:4:4 + -0x70_83BD_A626_311C, + // 4:0:0 + 0, +]; +#[rustfmt::skip] +const Q_MODEL_MUL: [i64; 4] = [ + // 4:2:0 + 0x8A0_50DD, + // 4:2:2 + 0x887_7666, + // 4:4:4 + 0x8D4_A712, + // 4:0:0 + 0, +]; + +#[rustfmt::skip] +const ROUGH_TAN_LOOKUP: &[u16; 18] = &[ + 0, 358, 722, 1098, 1491, 1910, + 2365, 2868, 3437, 4096, 4881, 5850, + 7094, 8784, 11254, 15286, 23230, 46817 +]; + +// A digital approximation of a 2nd-order low-pass Bessel follower. +// We use this for rate control because it has fast reaction time, but is +// critically damped. +pub struct IIRBessel2 { + c: [i32; 2], + g: i32, + x: [i32; 2], + y: [i32; 2], +} + +// alpha is Q24 in the range [0,0.5). +// The return value is 5.12. +fn warp_alpha(alpha: i32) -> i32 { + let i = ((alpha * 36) >> 24).min(16); + let t0 = ROUGH_TAN_LOOKUP[i as usize]; + let t1 = ROUGH_TAN_LOOKUP[i as usize + 1]; + let d = alpha * 36 - (i << 24); + ((((t0 as i64) << 32) + (((t1 - t0) << 8) as i64) * (d as i64)) >> 32) as i32 +} + +// Compute Bessel filter coefficients with the specified delay. +// Return: Filter parameters (c[0], c[1], g). +fn iir_bessel2_get_parameters(delay: i32) -> (i32, i32, i32) { + // This borrows some code from an unreleased version of Postfish. + // See the recipe at http://unicorn.us.com/alex/2polefilters.html for details + // on deriving the filter coefficients. + // alpha is Q24 + let alpha = (1 << 24) / delay; + // warp is 7.12 (5.12? the max value is 70386 in Q12). + let warp = warp_alpha(alpha).max(1) as i64; + // k1 is 9.12 (6.12?) + let k1 = 3 * warp; + // k2 is 16.24 (11.24?) + let k2 = k1 * warp; + // d is 16.15 (10.15?) + let d = ((((1 << 12) + k1) << 12) + k2 + 256) >> 9; + // a is 0.32, since d is larger than both 1.0 and k2 + let a = (k2 << 23) / d; + // ik2 is 25.24 + let ik2 = (1i64 << 48) / k2; + // b1 is Q56; in practice, the integer ranges between -2 and 2. + let b1 = 2 * a * (ik2 - (1i64 << 24)); + // b2 is Q56; in practice, the integer ranges between -2 and 2. + let b2 = (1i64 << 56) - ((4 * a) << 24) - b1; + // All of the filter parameters are Q24. + ( + ((b1 + (1i64 << 31)) >> 32) as i32, + ((b2 + (1i64 << 31)) >> 32) as i32, + ((a + 128) >> 8) as i32, + ) +} + +impl IIRBessel2 { + pub fn new(delay: i32, value: i32) -> IIRBessel2 { + let (c0, c1, g) = iir_bessel2_get_parameters(delay); + IIRBessel2 { c: [c0, c1], g, x: [value, value], y: [value, value] } + } + + // Re-initialize Bessel filter coefficients with the specified delay. + // This does not alter the x/y state, but changes the reaction time of the + // filter. + // Altering the time constant of a reactive filter without altering internal + // state is something that has to be done carefully, but our design operates + // at high enough delays and with small enough time constant changes to make + // it safe. + pub fn reinit(&mut self, delay: i32) { + let (c0, c1, g) = iir_bessel2_get_parameters(delay); + self.c[0] = c0; + self.c[1] = c1; + self.g = g; + } + + pub fn update(&mut self, x: i32) -> i32 { + let c0 = self.c[0] as i64; + let c1 = self.c[1] as i64; + let g = self.g as i64; + let x0 = self.x[0] as i64; + let x1 = self.x[1] as i64; + let y0 = self.y[0] as i64; + let y1 = self.y[1] as i64; + let ya = + ((((x as i64) + x0 * 2 + x1) * g + y0 * c0 + y1 * c1 + (1i64 << 23)) + >> 24) as i32; + self.x[1] = self.x[0]; + self.x[0] = x; + self.y[1] = self.y[0]; + self.y[0] = ya; + ya + } +} + +#[derive(Copy, Clone)] +struct RCFrameMetrics { + // The log base 2 of the scale factor for this frame in Q24 format. + log_scale_q24: i32, + // The frame type from pass 1 + fti: usize, + // Whether or not the frame was hidden in pass 1 + show_frame: bool, + // TODO: The input frame number corresponding to this frame in the input. + // input_frameno: u32 + // TODO vfr: PTS +} + +impl RCFrameMetrics { + const fn new() -> RCFrameMetrics { + RCFrameMetrics { log_scale_q24: 0, fti: 0, show_frame: false } + } +} + +/// Rate control pass summary +/// +/// It contains encoding information related to the whole previous +/// encoding pass. +#[derive(Debug, Default, Clone)] +pub struct RCSummary { + pub(crate) ntus: i32, + nframes: [i32; FRAME_NSUBTYPES + 1], + exp: [u8; FRAME_NSUBTYPES], + scale_sum: [i64; FRAME_NSUBTYPES], + pub(crate) total: i32, +} + +// Backing storage to deserialize Summary and Per-Frame pass data +// +// Can store up to a full header size since it is the largest of the two +// packet kinds. +pub(crate) struct RCDeserialize { + // The current byte position in the frame metrics buffer. + pass2_buffer_pos: usize, + // In pass 2, this represents the number of bytes that are available in the + // input buffer. + pass2_buffer_fill: usize, + // Buffer for current frame metrics in pass 2. + pass2_buffer: [u8; TWOPASS_HEADER_SZ], +} + +impl Default for RCDeserialize { + fn default() -> Self { + RCDeserialize { + pass2_buffer: [0; TWOPASS_HEADER_SZ], + pass2_buffer_pos: 0, + pass2_buffer_fill: 0, + } + } +} + +impl RCDeserialize { + // Fill the backing storage by reading enough bytes from the + // buf slice until goal bytes are available for parsing. + // + // goal must be at most TWOPASS_HEADER_SZ. + pub(crate) fn buffer_fill( + &mut self, buf: &[u8], consumed: usize, goal: usize, + ) -> usize { + let mut consumed = consumed; + while self.pass2_buffer_fill < goal && consumed < buf.len() { + self.pass2_buffer[self.pass2_buffer_fill] = buf[consumed]; + self.pass2_buffer_fill += 1; + consumed += 1; + } + consumed + } + + // Read the next n bytes as i64. + // n must be within 1 and 8 + fn unbuffer_val(&mut self, n: usize) -> i64 { + let mut bytes = n; + let mut ret = 0; + let mut shift = 0; + while bytes > 0 { + bytes -= 1; + ret |= (self.pass2_buffer[self.pass2_buffer_pos] as i64) << shift; + self.pass2_buffer_pos += 1; + shift += 8; + } + ret + } + + // Read metrics for the next frame. + fn parse_metrics(&mut self) -> Result { + debug_assert!(self.pass2_buffer_fill >= TWOPASS_PACKET_SZ); + let ft_val = self.unbuffer_val(4); + let show_frame = (ft_val >> 31) != 0; + let fti = (ft_val & 0x7FFFFFFF) as usize; + // Make sure the frame type is valid. + if fti > FRAME_NSUBTYPES { + return Err("Invalid frame type".to_string()); + } + let log_scale_q24 = self.unbuffer_val(4) as i32; + Ok(RCFrameMetrics { log_scale_q24, fti, show_frame }) + } + + // Read the summary header data. + pub(crate) fn parse_summary(&mut self) -> Result { + // check the magic value and version number. + if self.unbuffer_val(4) != TWOPASS_MAGIC as i64 { + return Err("Magic value mismatch".to_string()); + } + if self.unbuffer_val(4) != TWOPASS_VERSION as i64 { + return Err("Version number mismatch".to_string()); + } + let mut s = + RCSummary { ntus: self.unbuffer_val(4) as i32, ..Default::default() }; + + // Make sure the file claims to have at least one TU. + // Otherwise we probably got the placeholder data from an aborted + // pass 1. + if s.ntus < 1 { + return Err("No TUs found in first pass summary".to_string()); + } + let mut total: i32 = 0; + for nframes in s.nframes.iter_mut() { + let n = self.unbuffer_val(4) as i32; + if n < 0 { + return Err("Got negative frame count".to_string()); + } + total = total + .checked_add(n) + .ok_or_else(|| "Frame count too large".to_string())?; + + *nframes = n; + } + + // We can't have more TUs than frames. + if s.ntus > total { + return Err("More TUs than frames".to_string()); + } + + s.total = total; + + for exp in s.exp.iter_mut() { + *exp = self.unbuffer_val(1) as u8; + } + + for scale_sum in s.scale_sum.iter_mut() { + *scale_sum = self.unbuffer_val(8); + if *scale_sum < 0 { + return Err("Got negative scale sum".to_string()); + } + } + Ok(s) + } +} + +pub struct RCState { + // The target bit-rate in bits per second. + target_bitrate: i32, + // The number of TUs over which to distribute the reservoir usage. + // We use TUs because in our leaky bucket model, we only add bits to the + // reservoir on TU boundaries. + reservoir_frame_delay: i32, + // Whether or not the reservoir_frame_delay was explicitly specified by the + // user, or is the default value. + reservoir_frame_delay_is_set: bool, + // The maximum quantizer index to allow (for the luma AC coefficients, other + // quantizers will still be adjusted to match). + maybe_ac_qi_max: Option, + // The minimum quantizer index to allow (for the luma AC coefficients). + ac_qi_min: u8, + // Will we drop frames to meet bitrate requirements? + drop_frames: bool, + // Do we respect the maximum reservoir fullness? + cap_overflow: bool, + // Can the reservoir go negative? + cap_underflow: bool, + // The log of the first-pass base quantizer. + pass1_log_base_q: i64, + // Two-pass mode state. + // PASS_SINGLE => 1-pass encoding. + // PASS_1 => 1st pass of 2-pass encoding. + // PASS_2 => 2nd pass of 2-pass encoding. + // PASS_2_PLUS_1 => 2nd pass of 2-pass encoding, but also emitting pass 1 + // data again. + twopass_state: i32, + // The log of the number of pixels in a frame in Q57 format. + log_npixels: i64, + // The target average bits per Temporal Unit (input frame). + bits_per_tu: i64, + // The current bit reservoir fullness (bits available to be used). + reservoir_fullness: i64, + // The target buffer fullness. + // This is where we'd like to be by the last keyframe that appears in the + // next reservoir_frame_delay frames. + reservoir_target: i64, + // The maximum buffer fullness (total size of the buffer). + reservoir_max: i64, + // The log of estimated scale factor for the rate model in Q57 format. + // + // TODO: Convert to Q23 or figure out a better way to avoid overflow + // once 2-pass mode is introduced, if required. + log_scale: [i64; FRAME_NSUBTYPES], + // The exponent used in the rate model in Q6 format. + exp: [u8; FRAME_NSUBTYPES], + // The log of an estimated scale factor used to obtain the real framerate, + // for VFR sources or, e.g., 12 fps content doubled to 24 fps, etc. + // TODO vfr: log_vfr_scale: i64, + // Second-order lowpass filters to track scale and VFR. + scalefilter: [IIRBessel2; FRAME_NSUBTYPES], + // TODO vfr: vfrfilter: IIRBessel2, + // The number of frames of each type we have seen, for filter adaptation + // purposes. + // These are only 32 bits to guarantee that we can sum the scales over the + // whole file without overflow in a 64-bit int. + // That limits us to 2.268 years at 60 fps (minus 33% with re-ordering). + nframes: [i32; FRAME_NSUBTYPES + 1], + inter_delay: [i32; FRAME_NSUBTYPES - 1], + inter_delay_target: i32, + // The total accumulated estimation bias. + rate_bias: i64, + // The number of (non-Show Existing Frame) frames that have been encoded. + nencoded_frames: i64, + // The number of Show Existing Frames that have been emitted. + nsef_frames: i64, + // Buffer for current frame metrics in pass 1. + pass1_buffer: [u8; TWOPASS_HEADER_SZ], + // Whether or not the user has retrieved the pass 1 data for the last frame. + // For PASS_1 or PASS_2_PLUS_1 encoding, this is set to false after each + // frame is encoded, and must be set to true by calling twopass_out() before + // the next frame can be encoded. + pub pass1_data_retrieved: bool, + // Marks whether or not the user has retrieved the summary data at the end of + // the encode. + pass1_summary_retrieved: bool, + // Whether or not the user has provided enough data to encode in the second + // pass. + // For PASS_2 or PASS_2_PLUS_1 encoding, this is set to false after each + // frame, and must be set to true by calling twopass_in() before the next + // frame can be encoded. + pass2_data_ready: bool, + // TODO: Add a way to force the next frame to be a keyframe in 2-pass mode. + // Right now we are relying on keyframe detection to detect the same + // keyframes. + // The metrics for the previous frame. + prev_metrics: RCFrameMetrics, + // The metrics for the current frame. + cur_metrics: RCFrameMetrics, + // The buffered metrics for future frames. + frame_metrics: Vec, + // The total number of frames still in use in the circular metric buffer. + nframe_metrics: usize, + // The index of the current frame in the circular metric buffer. + frame_metrics_head: usize, + // Data deserialization + des: RCDeserialize, + // The TU count encoded so far. + ntus: i32, + // The TU count for the whole file. + ntus_total: i32, + // The remaining TU count. + ntus_left: i32, + // The frame count of each frame subtype in the whole file. + nframes_total: [i32; FRAME_NSUBTYPES + 1], + // The sum of those counts. + nframes_total_total: i32, + // The number of frames of each subtype yet to be processed. + nframes_left: [i32; FRAME_NSUBTYPES + 1], + // The sum of the scale values for each frame subtype. + scale_sum: [i64; FRAME_NSUBTYPES], + // The number of TUs represented by the current scale sums. + scale_window_ntus: i32, + // The frame count of each frame subtype in the current scale window. + scale_window_nframes: [i32; FRAME_NSUBTYPES + 1], + // The sum of the scale values for each frame subtype in the current window. + scale_window_sum: [i64; FRAME_NSUBTYPES], +} + +// TODO: Separate qi values for each color plane. +pub struct QuantizerParameters { + // The full-precision, unmodulated log quantizer upon which our modulated + // quantizer indices are based. + // This is only used to limit sudden quality changes from frame to frame, and + // as such is not adjusted when we encounter buffer overrun or underrun. + pub log_base_q: i64, + // The full-precision log quantizer modulated by the current frame type upon + // which our quantizer indices are based (including any adjustments to + // prevent buffer overrun or underrun). + // This is used when estimating the scale parameter once we know the actual + // bit usage of a frame. + pub log_target_q: i64, + pub dc_qi: [u8; 3], + pub ac_qi: [u8; 3], + pub lambda: f64, + pub dist_scale: [f64; 3], +} + +const Q57_SQUARE_EXP_SCALE: f64 = + (2.0 * ::std::f64::consts::LN_2) / ((1i64 << 57) as f64); + +// Daala style log-offset for chroma quantizers +// TODO: Optimal offsets for more configurations than just BT.709 +fn chroma_offset( + log_target_q: i64, chroma_sampling: ChromaSampling, +) -> (i64, i64) { + let x = log_target_q.max(0); + // Gradient optimized for CIEDE2000+PSNR on subset3 + let y = match chroma_sampling { + ChromaSampling::Cs400 => 0, + ChromaSampling::Cs420 => (x >> 2) + (x >> 6), // 0.266 + ChromaSampling::Cs422 => (x >> 3) + (x >> 4) - (x >> 7), // 0.180 + ChromaSampling::Cs444 => (x >> 4) + (x >> 5) + (x >> 8), // 0.098 + }; + // blog64(7) - blog64(4); blog64(5) - blog64(4) + (0x19D_5D9F_D501_0B37 - y, 0xA4_D3C2_5E68_DC58 - y) +} + +impl QuantizerParameters { + fn new_from_log_q( + log_base_q: i64, log_target_q: i64, bit_depth: usize, + chroma_sampling: ChromaSampling, is_intra: bool, + log_isqrt_mean_scale: i64, + ) -> QuantizerParameters { + let scale = log_isqrt_mean_scale + q57(QSCALE + bit_depth as i32 - 8); + + let mut log_q_y = log_target_q; + if !is_intra && bit_depth == 8 { + log_q_y = log_target_q + + (log_target_q >> 32) * Q_MODEL_MUL[chroma_sampling as usize] + + Q_MODEL_ADD[chroma_sampling as usize]; + } + + let quantizer = bexp64(log_q_y + scale); + let (offset_u, offset_v) = + chroma_offset(log_q_y + log_isqrt_mean_scale, chroma_sampling); + let mono = chroma_sampling == ChromaSampling::Cs400; + let log_q_u = log_q_y + offset_u; + let log_q_v = log_q_y + offset_v; + let quantizer_u = bexp64(log_q_u + scale); + let quantizer_v = bexp64(log_q_v + scale); + let lambda = (::std::f64::consts::LN_2 / 6.0) + * (((log_target_q + log_isqrt_mean_scale) as f64) + * Q57_SQUARE_EXP_SCALE) + .exp(); + + let scale = |q| bexp64((log_target_q - q) * 2 + q57(16)) as f64 / 65536.; + let dist_scale = [scale(log_q_y), scale(log_q_u), scale(log_q_v)]; + + let base_q_idx = select_ac_qi(quantizer, bit_depth).max(1); + + // delta_q only gets 6 bits + a sign bit, so it can differ by 63 at most. + let min_qi = base_q_idx.saturating_sub(63).max(1); + let max_qi = base_q_idx.saturating_add(63); + let clamp_qi = |qi: u8| qi.clamp(min_qi, max_qi); + + QuantizerParameters { + log_base_q, + log_target_q, + // TODO: Allow lossless mode; i.e. qi == 0. + dc_qi: [ + clamp_qi(select_dc_qi(quantizer, bit_depth)), + if mono { 0 } else { clamp_qi(select_dc_qi(quantizer_u, bit_depth)) }, + if mono { 0 } else { clamp_qi(select_dc_qi(quantizer_v, bit_depth)) }, + ], + ac_qi: [ + base_q_idx, + if mono { 0 } else { clamp_qi(select_ac_qi(quantizer_u, bit_depth)) }, + if mono { 0 } else { clamp_qi(select_ac_qi(quantizer_v, bit_depth)) }, + ], + lambda, + dist_scale, + } + } +} + +impl RCState { + pub fn new( + frame_width: i32, frame_height: i32, framerate_num: i64, + framerate_den: i64, target_bitrate: i32, maybe_ac_qi_max: Option, + ac_qi_min: u8, max_key_frame_interval: i32, + maybe_reservoir_frame_delay: Option, + ) -> RCState { + // The default buffer size is set equal to 1.5x the keyframe interval, or 240 + // frames; whichever is smaller, with a minimum of 12. + // For user set values, we enforce a minimum of 12. + // The interval is short enough to allow reaction, but long enough to allow + // looking into the next GOP (avoiding the case where the last frames + // before an I-frame get starved), in most cases. + // The 12 frame minimum gives us some chance to distribute bit estimation + // errors in the worst case. + let reservoir_frame_delay = maybe_reservoir_frame_delay + .unwrap_or_else(|| ((max_key_frame_interval * 3) >> 1).min(240)) + .max(12); + // TODO: What are the limits on these? + let npixels = (frame_width as i64) * (frame_height as i64); + // Insane framerates or frame sizes mean insane bitrates. + // Let's not get carried away. + // We also subtract 16 bits from each temporal unit to account for the + // temporal delimiter, whose bits are not included in the frame sizes + // reported to update_state(). + // TODO: Support constraints imposed by levels. + let bits_per_tu = clamp( + (target_bitrate as i64) * framerate_den / framerate_num, + 40, + 0x4000_0000_0000, + ) - (TEMPORAL_DELIMITER.len() * 8) as i64; + let reservoir_max = bits_per_tu * (reservoir_frame_delay as i64); + // Start with a buffer fullness and fullness target of 50%. + let reservoir_target = (reservoir_max + 1) >> 1; + // Pick exponents and initial scales for quantizer selection. + let ibpp = npixels / bits_per_tu; + // These have been derived by encoding many clips at every quantizer + // and running a piecewise-linear regression in binary log space. + let (i_exp, i_log_scale) = if ibpp < 1 { + (48u8, blog64(36) - q57(QSCALE)) + } else if ibpp < 4 { + (61u8, blog64(55) - q57(QSCALE)) + } else { + (77u8, blog64(129) - q57(QSCALE)) + }; + let (p_exp, p_log_scale) = if ibpp < 2 { + (69u8, blog64(32) - q57(QSCALE)) + } else if ibpp < 139 { + (104u8, blog64(84) - q57(QSCALE)) + } else { + (83u8, blog64(19) - q57(QSCALE)) + }; + let (b0_exp, b0_log_scale) = if ibpp < 2 { + (84u8, blog64(30) - q57(QSCALE)) + } else if ibpp < 92 { + (120u8, blog64(68) - q57(QSCALE)) + } else { + (68u8, blog64(4) - q57(QSCALE)) + }; + let (b1_exp, b1_log_scale) = if ibpp < 2 { + (87u8, blog64(27) - q57(QSCALE)) + } else if ibpp < 126 { + (139u8, blog64(84) - q57(QSCALE)) + } else { + (61u8, blog64(1) - q57(QSCALE)) + }; + + // TODO: Add support for "golden" P frames. + RCState { + target_bitrate, + reservoir_frame_delay, + reservoir_frame_delay_is_set: maybe_reservoir_frame_delay.is_some(), + maybe_ac_qi_max, + ac_qi_min, + drop_frames: false, + cap_overflow: true, + cap_underflow: false, + pass1_log_base_q: 0, + twopass_state: PASS_SINGLE, + log_npixels: blog64(npixels), + bits_per_tu, + reservoir_fullness: reservoir_target, + reservoir_target, + reservoir_max, + log_scale: [i_log_scale, p_log_scale, b0_log_scale, b1_log_scale], + exp: [i_exp, p_exp, b0_exp, b1_exp], + scalefilter: [ + IIRBessel2::new(4, q57_to_q24(i_log_scale)), + IIRBessel2::new(INTER_DELAY_TARGET_MIN, q57_to_q24(p_log_scale)), + IIRBessel2::new(INTER_DELAY_TARGET_MIN, q57_to_q24(b0_log_scale)), + IIRBessel2::new(INTER_DELAY_TARGET_MIN, q57_to_q24(b1_log_scale)), + ], + // TODO VFR + nframes: [0; FRAME_NSUBTYPES + 1], + inter_delay: [INTER_DELAY_TARGET_MIN; FRAME_NSUBTYPES - 1], + inter_delay_target: reservoir_frame_delay >> 1, + rate_bias: 0, + nencoded_frames: 0, + nsef_frames: 0, + pass1_buffer: [0; TWOPASS_HEADER_SZ], + pass1_data_retrieved: true, + pass1_summary_retrieved: false, + pass2_data_ready: false, + prev_metrics: RCFrameMetrics::new(), + cur_metrics: RCFrameMetrics::new(), + frame_metrics: Vec::new(), + nframe_metrics: 0, + frame_metrics_head: 0, + ntus: 0, + ntus_total: 0, + ntus_left: 0, + nframes_total: [0; FRAME_NSUBTYPES + 1], + nframes_total_total: 0, + nframes_left: [0; FRAME_NSUBTYPES + 1], + scale_sum: [0; FRAME_NSUBTYPES], + scale_window_ntus: 0, + scale_window_nframes: [0; FRAME_NSUBTYPES + 1], + scale_window_sum: [0; FRAME_NSUBTYPES], + des: RCDeserialize::default(), + } + } + + pub(crate) fn select_first_pass_qi( + &self, bit_depth: usize, fti: usize, chroma_sampling: ChromaSampling, + ) -> QuantizerParameters { + // Adjust the quantizer for the frame type, result is Q57: + let log_q = ((self.pass1_log_base_q + (1i64 << 11)) >> 12) + * (MQP_Q12[fti] as i64) + + DQP_Q57[fti]; + QuantizerParameters::new_from_log_q( + self.pass1_log_base_q, + log_q, + bit_depth, + chroma_sampling, + fti == 0, + 0, + ) + } + + // TODO: Separate quantizers for Cb and Cr. + #[profiling::function] + pub(crate) fn select_qi( + &self, ctx: &ContextInner, output_frameno: u64, fti: usize, + maybe_prev_log_base_q: Option, log_isqrt_mean_scale: i64, + ) -> QuantizerParameters { + // Is rate control active? + if self.target_bitrate <= 0 { + // Rate control is not active. + // Derive quantizer directly from frame type. + let bit_depth = ctx.config.bit_depth; + let chroma_sampling = ctx.config.chroma_sampling; + let (log_base_q, log_q) = + Self::calc_flat_quantizer(ctx.config.quantizer as u8, bit_depth, fti); + QuantizerParameters::new_from_log_q( + log_base_q, + log_q, + bit_depth, + chroma_sampling, + fti == 0, + log_isqrt_mean_scale, + ) + } else { + let mut nframes: [i32; FRAME_NSUBTYPES + 1] = [0; FRAME_NSUBTYPES + 1]; + let mut log_scale: [i64; FRAME_NSUBTYPES] = self.log_scale; + let mut reservoir_tus = self.reservoir_frame_delay.min(self.ntus_left); + let mut reservoir_frames = 0; + let mut log_cur_scale = (self.scalefilter[fti].y[0] as i64) << 33; + match self.twopass_state { + // First pass of 2-pass mode: use a fixed base quantizer. + PASS_1 => { + return self.select_first_pass_qi( + ctx.config.bit_depth, + fti, + ctx.config.chroma_sampling, + ); + } + // Second pass of 2-pass mode: we know exactly how much of each frame + // type there is in the current buffer window, and have estimates for + // the scales. + PASS_2 | PASS_2_PLUS_1 => { + let mut scale_window_sum: [i64; FRAME_NSUBTYPES] = + self.scale_window_sum; + let mut scale_window_nframes: [i32; FRAME_NSUBTYPES + 1] = + self.scale_window_nframes; + // Intentionally exclude Show Existing Frame frames from this. + for ftj in 0..FRAME_NSUBTYPES { + reservoir_frames += scale_window_nframes[ftj]; + } + // If we're approaching the end of the file, add some slack to keep + // us from slamming into a rail. + // Our rate accuracy goes down, but it keeps the result sensible. + // We position the target where the first forced keyframe beyond the + // end of the file would be (for consistency with 1-pass mode). + // TODO: let mut buf_pad = self.reservoir_frame_delay.min(...); + // if buf_delay < buf_pad { + // buf_pad -= buf_delay; + // } + // else ... + // Otherwise, search for the last keyframe in the buffer window and + // target that. + // Currently we only do this when using a finite buffer. + // We could save the position of the last keyframe in the stream in + // the summary data and do it with a whole-file buffer as well, but + // it isn't likely to make a difference. + if !self.frame_metrics.is_empty() { + let mut fm_tail = self.frame_metrics_head + self.nframe_metrics; + if fm_tail >= self.frame_metrics.len() { + fm_tail -= self.frame_metrics.len(); + } + let mut fmi = fm_tail; + loop { + if fmi == 0 { + fmi += self.frame_metrics.len(); + } + fmi -= 1; + // Stop before we remove the first frame. + if fmi == self.frame_metrics_head { + break; + } + // If we find a keyframe, remove it and everything past it. + if self.frame_metrics[fmi].fti == FRAME_SUBTYPE_I { + while fmi != fm_tail { + let m = &self.frame_metrics[fmi]; + let ftj = m.fti; + scale_window_nframes[ftj] -= 1; + if ftj < FRAME_NSUBTYPES { + scale_window_sum[ftj] -= bexp_q24(m.log_scale_q24); + reservoir_frames -= 1; + } + if m.show_frame { + reservoir_tus -= 1; + } + fmi += 1; + if fmi >= self.frame_metrics.len() { + fmi = 0; + } + } + // And stop scanning backwards. + break; + } + } + } + nframes = scale_window_nframes; + // If we're not using the same frame type as in pass 1 (because + // someone changed some encoding parameters), remove that scale + // estimate. + // We'll add a replacement for the correct frame type below. + if self.cur_metrics.fti != fti { + scale_window_nframes[self.cur_metrics.fti] -= 1; + if self.cur_metrics.fti != FRAME_SUBTYPE_SEF { + scale_window_sum[self.cur_metrics.fti] -= + bexp_q24(self.cur_metrics.log_scale_q24); + } + } else { + log_cur_scale = (self.cur_metrics.log_scale_q24 as i64) << 33; + } + // If we're approaching the end of the file, add some slack to keep + // us from slamming into a rail. + // Our rate accuracy goes down, but it keeps the result sensible. + // We position the target where the first forced keyframe beyond the + // end of the file would be (for consistency with 1-pass mode). + if reservoir_tus >= self.ntus_left + && self.ntus_total as u64 + > ctx.gop_input_frameno_start[&output_frameno] + { + let nfinal_gop_tus = self.ntus_total + - (ctx.gop_input_frameno_start[&output_frameno] as i32); + if ctx.config.max_key_frame_interval as i32 > nfinal_gop_tus { + let reservoir_pad = (ctx.config.max_key_frame_interval as i32 + - nfinal_gop_tus) + .min(self.reservoir_frame_delay - reservoir_tus); + let (guessed_reservoir_frames, guessed_reservoir_tus) = ctx + .guess_frame_subtypes( + &mut nframes, + reservoir_tus + reservoir_pad, + ); + reservoir_frames = guessed_reservoir_frames; + reservoir_tus = guessed_reservoir_tus; + } + } + // Blend in the low-pass filtered scale according to how many + // frames of each type we need to add compared to the actual sums in + // our window. + for ftj in 0..FRAME_NSUBTYPES { + let scale = scale_window_sum[ftj] + + bexp_q24(self.scalefilter[ftj].y[0]) + * (nframes[ftj] - scale_window_nframes[ftj]) as i64; + log_scale[ftj] = if nframes[ftj] > 0 { + blog64(scale) - blog64(nframes[ftj] as i64) - q57(24) + } else { + -self.log_npixels + }; + } + } + // Single pass. + _ => { + // Figure out how to re-distribute bits so that we hit our fullness + // target before the last keyframe in our current buffer window + // (after the current frame), or the end of the buffer window, + // whichever comes first. + // Count the various types and classes of frames. + let (guessed_reservoir_frames, guessed_reservoir_tus) = + ctx.guess_frame_subtypes(&mut nframes, self.reservoir_frame_delay); + reservoir_frames = guessed_reservoir_frames; + reservoir_tus = guessed_reservoir_tus; + // TODO: Scale for VFR. + } + } + // If we've been missing our target, add a penalty term. + let rate_bias = (self.rate_bias / (self.nencoded_frames + 100)) + * (reservoir_frames as i64); + // rate_total is the total bits available over the next + // reservoir_tus TUs. + let rate_total = self.reservoir_fullness - self.reservoir_target + + rate_bias + + (reservoir_tus as i64) * self.bits_per_tu; + // Find a target quantizer that meets our rate target for the + // specific mix of frame types we'll have over the next + // reservoir_frame frames. + // We model the rate<->quantizer relationship as + // rate = scale*(quantizer**-exp) + // In this case, we have our desired rate, an exponent selected in + // setup, and a scale that's been measured over our frame history, + // so we're solving for the quantizer. + // Exponentiation with arbitrary exponents is expensive, so we work + // in the binary log domain (binary exp and log aren't too bad): + // rate = exp2(log2(scale) - log2(quantizer)*exp) + // There's no easy closed form solution, so we bisection searh for it. + let bit_depth = ctx.config.bit_depth; + let chroma_sampling = ctx.config.chroma_sampling; + // TODO: Proper handling of lossless. + let mut log_qlo = blog64(ac_q(self.ac_qi_min, 0, bit_depth).get() as i64) + - q57(QSCALE + bit_depth as i32 - 8); + // The AC quantizer tables map to values larger than the DC quantizer + // tables, so we use that as the upper bound to make sure we can use + // the full table if needed. + let mut log_qhi = blog64( + ac_q(self.maybe_ac_qi_max.unwrap_or(255), 0, bit_depth).get() as i64, + ) - q57(QSCALE + bit_depth as i32 - 8); + let mut log_base_q = (log_qlo + log_qhi) >> 1; + while log_qlo < log_qhi { + // Count bits contributed by each frame type using the model. + let mut bits = 0i64; + for ftj in 0..FRAME_NSUBTYPES { + // Modulate base quantizer by frame type. + let log_q = ((log_base_q + (1i64 << 11)) >> 12) + * (MQP_Q12[ftj] as i64) + + DQP_Q57[ftj]; + // All the fields here are Q57 except for the exponent, which is + // Q6. + bits += (nframes[ftj] as i64) + * bexp64( + log_scale[ftj] + self.log_npixels + - ((log_q + 32) >> 6) * (self.exp[ftj] as i64), + ); + } + // The number of bits for Show Existing Frame frames is constant. + bits += (nframes[FRAME_SUBTYPE_SEF] as i64) * SEF_BITS; + let diff = bits - rate_total; + if diff > 0 { + log_qlo = log_base_q + 1; + } else if diff < 0 { + log_qhi = log_base_q - 1; + } else { + break; + } + log_base_q = (log_qlo + log_qhi) >> 1; + } + // If this was not one of the initial frames, limit the change in + // base quantizer to within [0.8*Q, 1.2*Q] where Q is the previous + // frame's base quantizer. + if let Some(prev_log_base_q) = maybe_prev_log_base_q { + log_base_q = clamp( + log_base_q, + prev_log_base_q - 0xA4_D3C2_5E68_DC58, + prev_log_base_q + 0xA4_D3C2_5E68_DC58, + ); + } + // Modulate base quantizer by frame type. + let mut log_q = ((log_base_q + (1i64 << 11)) >> 12) + * (MQP_Q12[fti] as i64) + + DQP_Q57[fti]; + // The above allocation looks only at the total rate we'll accumulate + // in the next reservoir_frame_delay frames. + // However, we could overflow the bit reservoir on the very next + // frame. + // Check for that here if we're not using a soft target. + if self.cap_overflow { + // Allow 3% of the buffer for prediction error. + // This should be plenty, and we don't mind if we go a bit over. + // We only want to keep these bits from being completely wasted. + let margin = (self.reservoir_max + 31) >> 5; + // We want to use at least this many bits next frame. + let soft_limit = self.reservoir_fullness + self.bits_per_tu + - (self.reservoir_max - margin); + if soft_limit > 0 { + let log_soft_limit = blog64(soft_limit); + // If we're predicting we won't use that many bits... + // TODO: When using frame re-ordering, we should include the rate + // for all of the frames in the current TU. + // When there is more than one frame, there will be no direct + // solution for the required adjustment, however. + let log_scale_pixels = log_cur_scale + self.log_npixels; + let exp = self.exp[fti] as i64; + let mut log_q_exp = ((log_q + 32) >> 6) * exp; + if log_scale_pixels - log_q_exp < log_soft_limit { + // Scale the adjustment based on how far into the margin we are. + log_q_exp += ((log_scale_pixels - log_soft_limit - log_q_exp) + >> 32) + * ((margin.min(soft_limit) << 32) / margin); + log_q = ((log_q_exp + (exp >> 1)) / exp) << 6; + } + } + } + // We just checked we don't overflow the reservoir next frame, now + // check we don't underflow and bust the budget (when not using a + // soft target). + if self.maybe_ac_qi_max.is_none() { + // Compute the maximum number of bits we can use in the next frame. + // Allow 50% of the rate for a single frame for prediction error. + // This may not be enough for keyframes or sudden changes in + // complexity. + let log_hard_limit = + blog64(self.reservoir_fullness + (self.bits_per_tu >> 1)); + // If we're predicting we'll use more than this... + // TODO: When using frame re-ordering, we should include the rate + // for all of the frames in the current TU. + // When there is more than one frame, there will be no direct + // solution for the required adjustment, however. + let log_scale_pixels = log_cur_scale + self.log_npixels; + let exp = self.exp[fti] as i64; + let mut log_q_exp = ((log_q + 32) >> 6) * exp; + if log_scale_pixels - log_q_exp > log_hard_limit { + // Force the target to hit our limit exactly. + log_q_exp = log_scale_pixels - log_hard_limit; + log_q = ((log_q_exp + (exp >> 1)) / exp) << 6; + // If that target is unreasonable, oh well; we'll have to drop. + } + } + + if let Some(qi_max) = self.maybe_ac_qi_max { + let (max_log_base_q, max_log_q) = + Self::calc_flat_quantizer(qi_max, ctx.config.bit_depth, fti); + log_base_q = cmp::min(log_base_q, max_log_base_q); + log_q = cmp::min(log_q, max_log_q); + } + if self.ac_qi_min > 0 { + let (min_log_base_q, min_log_q) = + Self::calc_flat_quantizer(self.ac_qi_min, ctx.config.bit_depth, fti); + log_base_q = cmp::max(log_base_q, min_log_base_q); + log_q = cmp::max(log_q, min_log_q); + } + QuantizerParameters::new_from_log_q( + log_base_q, + log_q, + bit_depth, + chroma_sampling, + fti == 0, + log_isqrt_mean_scale, + ) + } + } + + // Computes a quantizer directly from the frame type and base quantizer index, + // without consideration for rate control. + fn calc_flat_quantizer( + base_qi: u8, bit_depth: usize, fti: usize, + ) -> (i64, i64) { + // TODO: Rename "quantizer" something that indicates it is a quantizer + // index, and move it somewhere more sensible (or choose a better way to + // parameterize a "quality" configuration parameter). + + // We use the AC quantizer as the source quantizer since its quantizer + // tables have unique entries, while the DC tables do not. + let ac_quantizer = ac_q(base_qi, 0, bit_depth).get() as i64; + // Pick the nearest DC entry since an exact match may be unavailable. + let dc_qi = select_dc_qi(ac_quantizer, bit_depth); + let dc_quantizer = dc_q(dc_qi, 0, bit_depth).get() as i64; + // Get the log quantizers as Q57. + let log_ac_q = blog64(ac_quantizer) - q57(QSCALE + bit_depth as i32 - 8); + let log_dc_q = blog64(dc_quantizer) - q57(QSCALE + bit_depth as i32 - 8); + // Target the midpoint of the chosen entries. + let log_base_q = (log_ac_q + log_dc_q + 1) >> 1; + // Adjust the quantizer for the frame type, result is Q57: + let log_q = ((log_base_q + (1i64 << 11)) >> 12) * (MQP_Q12[fti] as i64) + + DQP_Q57[fti]; + (log_base_q, log_q) + } + + #[profiling::function] + pub fn update_state( + &mut self, bits: i64, fti: usize, show_frame: bool, log_target_q: i64, + trial: bool, droppable: bool, + ) -> bool { + if trial { + assert!(self.needs_trial_encode(fti)); + assert!(bits > 0); + } + let mut dropped = false; + // Update rate control only if rate control is active. + if self.target_bitrate > 0 { + let mut estimated_bits = 0; + let mut bits = bits; + let mut droppable = droppable; + let mut log_scale = q57(-64); + // Drop frames is also disabled for now in the case of infinite-buffer + // two-pass mode. + if !self.drop_frames + || fti == FRAME_SUBTYPE_SEF + || (self.twopass_state == PASS_2 + || self.twopass_state == PASS_2_PLUS_1) + && !self.frame_metrics.is_empty() + { + droppable = false; + } + if fti == FRAME_SUBTYPE_SEF { + debug_assert!(bits == SEF_BITS); + debug_assert!(show_frame); + // Please don't make trial encodes of a SEF. + debug_assert!(!trial); + estimated_bits = SEF_BITS; + self.nsef_frames += 1; + } else { + let log_q_exp = ((log_target_q + 32) >> 6) * (self.exp[fti] as i64); + let prev_log_scale = self.log_scale[fti]; + if bits <= 0 { + // We didn't code any blocks in this frame. + bits = 0; + dropped = true; + // TODO: Adjust VFR rate based on drop count. + } else { + // Compute the estimated scale factor for this frame type. + let log_bits = blog64(bits); + log_scale = (log_bits - self.log_npixels + log_q_exp).min(q57(16)); + estimated_bits = + bexp64(prev_log_scale + self.log_npixels - log_q_exp); + if !trial { + self.nencoded_frames += 1; + } + } + } + let log_scale_q24 = q57_to_q24(log_scale); + // Special two-pass processing. + if self.twopass_state == PASS_2 || self.twopass_state == PASS_2_PLUS_1 { + // Pass 2 mode: + if !trial { + // Move the current metrics back one frame. + self.prev_metrics = self.cur_metrics; + // Back out the last frame's statistics from the sliding window. + let ftj = self.prev_metrics.fti; + self.nframes_left[ftj] -= 1; + self.scale_window_nframes[ftj] -= 1; + if ftj < FRAME_NSUBTYPES { + self.scale_window_sum[ftj] -= + bexp_q24(self.prev_metrics.log_scale_q24); + } + if self.prev_metrics.show_frame { + self.ntus_left -= 1; + self.scale_window_ntus -= 1; + } + // Free the corresponding entry in the circular buffer. + if !self.frame_metrics.is_empty() { + self.nframe_metrics -= 1; + self.frame_metrics_head += 1; + if self.frame_metrics_head >= self.frame_metrics.len() { + self.frame_metrics_head = 0; + } + } + // Mark us ready for the next 2-pass packet. + self.pass2_data_ready = false; + // Update state, so the user doesn't have to keep calling + // twopass_in() after they've fed in all the data when we're using + // a finite buffer. + self.twopass_in(None).unwrap_or(0); + } + } + if self.twopass_state == PASS_1 || self.twopass_state == PASS_2_PLUS_1 { + // Pass 1 mode: save the metrics for this frame. + self.prev_metrics.log_scale_q24 = log_scale_q24; + self.prev_metrics.fti = fti; + self.prev_metrics.show_frame = show_frame; + self.pass1_data_retrieved = false; + } + // Common to all passes: + if fti != FRAME_SUBTYPE_SEF && bits > 0 { + // If this is the first example of the given frame type we've seen, + // we immediately replace the default scale factor guess with the + // estimate we just computed using the first frame. + if trial || self.nframes[fti] <= 0 { + let f = &mut self.scalefilter[fti]; + let x = log_scale_q24; + f.x[0] = x; + f.x[1] = x; + f.y[0] = x; + f.y[1] = x; + self.log_scale[fti] = log_scale; + // TODO: Duplicate regular P frame state for first golden P frame. + } else { + // Lengthen the time constant for the inter filters as we collect + // more frame statistics, until we reach our target. + if fti > 0 + && self.inter_delay[fti - 1] < self.inter_delay_target + && self.nframes[fti] >= self.inter_delay[fti - 1] + { + self.inter_delay[fti - 1] += 1; + self.scalefilter[fti].reinit(self.inter_delay[fti - 1]); + } + // Update the low-pass scale filter for this frame type regardless + // of whether or not we will ultimately drop this frame. + self.log_scale[fti] = + q24_to_q57(self.scalefilter[fti].update(log_scale_q24)); + } + // If this frame busts our budget, it must be dropped. + if droppable && self.reservoir_fullness + self.bits_per_tu < bits { + // TODO: Adjust VFR rate based on drop count. + bits = 0; + dropped = true; + } else { + // TODO: Update a low-pass filter to estimate the "real" frame rate + // taking timestamps and drops into account. + // This is only done if the frame is coded, as it needs the final + // count of dropped frames. + } + } + if !trial { + // Increment the frame count for filter adaptation purposes. + if !trial && self.nframes[fti] < i32::MAX { + self.nframes[fti] += 1; + } + self.reservoir_fullness -= bits; + if show_frame { + self.reservoir_fullness += self.bits_per_tu; + // TODO: Properly account for temporal delimiter bits. + } + // If we're too quick filling the buffer and overflow is capped, that + // rate is lost forever. + if self.cap_overflow { + self.reservoir_fullness = + self.reservoir_fullness.min(self.reservoir_max); + } + // If we're too quick draining the buffer and underflow is capped, + // don't try to make up that rate later. + if self.cap_underflow { + self.reservoir_fullness = self.reservoir_fullness.max(0); + } + // Adjust the bias for the real bits we've used. + self.rate_bias += estimated_bits - bits; + } + } + dropped + } + + pub const fn needs_trial_encode(&self, fti: usize) -> bool { + self.target_bitrate > 0 && self.nframes[fti] == 0 + } + + pub(crate) const fn ready(&self) -> bool { + match self.twopass_state { + PASS_SINGLE => true, + PASS_1 => self.pass1_data_retrieved, + PASS_2 => self.pass2_data_ready, + _ => self.pass1_data_retrieved && self.pass2_data_ready, + } + } + + fn buffer_val(&mut self, val: i64, bytes: usize, cur_pos: usize) -> usize { + let mut val = val; + let mut bytes = bytes; + let mut cur_pos = cur_pos; + while bytes > 0 { + bytes -= 1; + self.pass1_buffer[cur_pos] = val as u8; + cur_pos += 1; + val >>= 8; + } + cur_pos + } + + pub(crate) fn select_pass1_log_base_q( + &self, ctx: &ContextInner, output_frameno: u64, + ) -> i64 { + assert_eq!(self.twopass_state, PASS_SINGLE); + self.select_qi(ctx, output_frameno, FRAME_SUBTYPE_I, None, 0).log_base_q + } + + // Initialize the first pass and emit a placeholder summary + pub(crate) fn init_first_pass( + &mut self, maybe_pass1_log_base_q: Option, + ) { + if let Some(pass1_log_base_q) = maybe_pass1_log_base_q { + assert_eq!(self.twopass_state, PASS_SINGLE); + // Pick first-pass qi for scale calculations. + self.pass1_log_base_q = pass1_log_base_q; + } else { + debug_assert!(self.twopass_state == PASS_2); + } + self.twopass_state += PASS_1; + } + + // Prepare a placeholder summary + fn emit_placeholder_summary(&mut self) -> &[u8] { + // Fill in dummy summary values. + let mut cur_pos = 0; + cur_pos = self.buffer_val(TWOPASS_MAGIC as i64, 4, cur_pos); + cur_pos = self.buffer_val(TWOPASS_VERSION as i64, 4, cur_pos); + cur_pos = self.buffer_val(0, TWOPASS_HEADER_SZ - 8, cur_pos); + debug_assert!(cur_pos == TWOPASS_HEADER_SZ); + self.pass1_data_retrieved = true; + &self.pass1_buffer[..cur_pos] + } + + // Frame-specific pass data + pub(crate) fn emit_frame_data(&mut self) -> Option<&[u8]> { + let mut cur_pos = 0; + let fti = self.prev_metrics.fti; + if fti < FRAME_NSUBTYPES { + self.scale_sum[fti] += bexp_q24(self.prev_metrics.log_scale_q24); + } + if self.prev_metrics.show_frame { + self.ntus += 1; + } + // If we have encoded too many frames, prevent us from reaching the + // ready state required to encode more. + if self.nencoded_frames + self.nsef_frames >= i32::MAX as i64 { + None? + } + cur_pos = self.buffer_val( + ((self.prev_metrics.show_frame as i64) << 31) + | self.prev_metrics.fti as i64, + 4, + cur_pos, + ); + cur_pos = + self.buffer_val(self.prev_metrics.log_scale_q24 as i64, 4, cur_pos); + debug_assert!(cur_pos == TWOPASS_PACKET_SZ); + self.pass1_data_retrieved = true; + Some(&self.pass1_buffer[..cur_pos]) + } + + // Summary of the whole encoding process. + pub(crate) fn emit_summary(&mut self) -> &[u8] { + let mut cur_pos = 0; + cur_pos = self.buffer_val(TWOPASS_MAGIC as i64, 4, cur_pos); + cur_pos = self.buffer_val(TWOPASS_VERSION as i64, 4, cur_pos); + cur_pos = self.buffer_val(self.ntus as i64, 4, cur_pos); + for fti in 0..=FRAME_NSUBTYPES { + cur_pos = self.buffer_val(self.nframes[fti] as i64, 4, cur_pos); + } + for fti in 0..FRAME_NSUBTYPES { + cur_pos = self.buffer_val(self.exp[fti] as i64, 1, cur_pos); + } + for fti in 0..FRAME_NSUBTYPES { + cur_pos = self.buffer_val(self.scale_sum[fti], 8, cur_pos); + } + debug_assert!(cur_pos == TWOPASS_HEADER_SZ); + self.pass1_summary_retrieved = true; + &self.pass1_buffer[..cur_pos] + } + + // Emit either summary or frame-specific data depending on the previous call + pub(crate) fn twopass_out( + &mut self, done_processing: bool, + ) -> Option<&[u8]> { + if !self.pass1_data_retrieved { + if self.twopass_state != PASS_1 && self.twopass_state != PASS_2_PLUS_1 { + Some(self.emit_placeholder_summary()) + } else { + self.emit_frame_data() + } + } else if done_processing && !self.pass1_summary_retrieved { + Some(self.emit_summary()) + } else { + // The data for this frame has already been retrieved. + None + } + } + + // Initialize the rate control for second pass encoding + pub(crate) fn init_second_pass(&mut self) { + if self.twopass_state == PASS_SINGLE || self.twopass_state == PASS_1 { + // Initialize the second pass. + self.twopass_state += PASS_2; + // If the user requested a finite buffer, reserve the space required for + // it. + if self.reservoir_frame_delay_is_set { + debug_assert!(self.reservoir_frame_delay > 0); + // reservoir_frame_delay counts in TUs, but RCFrameMetrics are stored + // per frame (including Show Existing Frame frames). + // When re-ordering, we will have more frames than TUs. + // How many more? + // That depends on the re-ordering scheme used. + // Doubling the number of TUs and adding a fixed latency equal to the + // maximum number of reference frames we can store should be + // sufficient for any reasonable scheme, and keeps this code from + // depending too closely on the details of the scheme currently used + // by rav1e. + let nmetrics = (self.reservoir_frame_delay as usize) * 2 + 8; + self.frame_metrics.reserve_exact(nmetrics); + self.frame_metrics.resize(nmetrics, RCFrameMetrics::new()); + } + } + } + + pub(crate) fn setup_second_pass(&mut self, s: &RCSummary) { + self.ntus_total = s.ntus; + self.ntus_left = s.ntus; + self.nframes_total = s.nframes; + self.nframes_left = s.nframes; + self.nframes_total_total = s.nframes.iter().sum(); + if self.frame_metrics.is_empty() { + self.reservoir_frame_delay = s.ntus; + self.scale_window_nframes = self.nframes_total; + self.scale_window_sum = s.scale_sum; + self.reservoir_max = + self.bits_per_tu * (self.reservoir_frame_delay as i64); + self.reservoir_target = (self.reservoir_max + 1) >> 1; + self.reservoir_fullness = self.reservoir_target; + } else { + self.reservoir_frame_delay = self.reservoir_frame_delay.min(s.ntus); + } + self.exp = s.exp; + } + + // Parse the rate control summary + // + // It returns the amount of data consumed in the process or + // an empty error on parsing failure. + fn twopass_parse_summary(&mut self, buf: &[u8]) -> Result { + let consumed = self.des.buffer_fill(buf, 0, TWOPASS_HEADER_SZ); + if self.des.pass2_buffer_fill >= TWOPASS_HEADER_SZ { + self.des.pass2_buffer_pos = 0; + + let s = self.des.parse_summary()?; + + self.setup_second_pass(&s); + + // Got a valid header. + // Set up pass 2. + // Clear the header data from the buffer to make room for the + // packet data. + self.des.pass2_buffer_fill = 0; + } + + Ok(consumed) + } + + // Return the size of the first buffer twopass_in expects + // + // It is the summary size (constant) + the number of frame data packets + // (variable depending on the configuration) it needs to starts encoding. + pub(crate) fn twopass_first_packet_size(&self) -> usize { + let frames_needed = if !self.frame_metrics.is_empty() { + // If we're not using whole-file buffering, we need at least one + // frame per buffer slot. + self.reservoir_frame_delay as usize + } else { + // Otherwise we need just one. + 1 + }; + + TWOPASS_HEADER_SZ + frames_needed * TWOPASS_PACKET_SZ + } + + // Return the number of frame data packets to be parsed before + // the encoding process can continue. + pub(crate) fn twopass_in_frames_needed(&self) -> i32 { + if self.target_bitrate <= 0 { + return 0; + } + if self.frame_metrics.is_empty() { + return i32::from(!self.pass2_data_ready); + } + let mut cur_scale_window_nframes = 0; + let mut cur_nframes_left = 0; + for fti in 0..=FRAME_NSUBTYPES { + cur_scale_window_nframes += self.scale_window_nframes[fti]; + cur_nframes_left += self.nframes_left[fti]; + } + + (self.reservoir_frame_delay - self.scale_window_ntus) + .clamp(0, cur_nframes_left - cur_scale_window_nframes) + } + + pub(crate) fn parse_frame_data_packet( + &mut self, buf: &[u8], + ) -> Result<(), String> { + if buf.len() != TWOPASS_PACKET_SZ { + return Err("Incorrect buffer size".to_string()); + } + + self.des.buffer_fill(buf, 0, TWOPASS_PACKET_SZ); + self.des.pass2_buffer_pos = 0; + let m = self.des.parse_metrics()?; + self.des.pass2_buffer_fill = 0; + + if self.frame_metrics.is_empty() { + // We're using a whole-file buffer. + self.cur_metrics = m; + self.pass2_data_ready = true; + } else { + // Safety check + let frames_needed = self.twopass_in_frames_needed(); + + if frames_needed > 0 { + if self.nframe_metrics >= self.frame_metrics.len() { + return Err( + "Read too many frames without finding enough TUs".to_string(), + ); + } + + let mut fmi = self.frame_metrics_head + self.nframe_metrics; + if fmi >= self.frame_metrics.len() { + fmi -= self.frame_metrics.len(); + } + self.nframe_metrics += 1; + self.frame_metrics[fmi] = m; + // And accumulate the statistics over the window. + self.scale_window_nframes[m.fti] += 1; + if m.fti < FRAME_NSUBTYPES { + self.scale_window_sum[m.fti] += bexp_q24(m.log_scale_q24); + } + if m.show_frame { + self.scale_window_ntus += 1; + } + if frames_needed == 1 { + self.pass2_data_ready = true; + self.cur_metrics = self.frame_metrics[self.frame_metrics_head]; + } + } else { + return Err("No frames needed".to_string()); + } + } + + Ok(()) + } + + // Parse the rate control per-frame data + // + // If no buffer is passed return the amount of data it expects + // to consume next. + // + // If a properly sized buffer is passed it returns the amount of data + // consumed in the process or an empty error on parsing failure. + fn twopass_parse_frame_data( + &mut self, maybe_buf: Option<&[u8]>, mut consumed: usize, + ) -> Result { + { + if self.frame_metrics.is_empty() { + // We're using a whole-file buffer. + if let Some(buf) = maybe_buf { + consumed = self.des.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ); + if self.des.pass2_buffer_fill >= TWOPASS_PACKET_SZ { + self.des.pass2_buffer_pos = 0; + // Read metrics for the next frame. + self.cur_metrics = self.des.parse_metrics()?; + // Clear the buffer for the next frame. + self.des.pass2_buffer_fill = 0; + self.pass2_data_ready = true; + } + } else { + return Ok(TWOPASS_PACKET_SZ - self.des.pass2_buffer_fill); + } + } else { + // We're using a finite buffer. + let mut cur_scale_window_nframes = 0; + let mut cur_nframes_left = 0; + + for fti in 0..=FRAME_NSUBTYPES { + cur_scale_window_nframes += self.scale_window_nframes[fti]; + cur_nframes_left += self.nframes_left[fti]; + } + + let mut frames_needed = self.twopass_in_frames_needed(); + while frames_needed > 0 { + if let Some(buf) = maybe_buf { + consumed = self.des.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ); + if self.des.pass2_buffer_fill >= TWOPASS_PACKET_SZ { + self.des.pass2_buffer_pos = 0; + // Read the metrics for the next frame. + let m = self.des.parse_metrics()?; + // Add them to the circular buffer. + if self.nframe_metrics >= self.frame_metrics.len() { + return Err( + "Read too many frames without finding enough TUs" + .to_string(), + ); + } + let mut fmi = self.frame_metrics_head + self.nframe_metrics; + if fmi >= self.frame_metrics.len() { + fmi -= self.frame_metrics.len(); + } + self.nframe_metrics += 1; + self.frame_metrics[fmi] = m; + // And accumulate the statistics over the window. + self.scale_window_nframes[m.fti] += 1; + cur_scale_window_nframes += 1; + if m.fti < FRAME_NSUBTYPES { + self.scale_window_sum[m.fti] += bexp_q24(m.log_scale_q24); + } + if m.show_frame { + self.scale_window_ntus += 1; + } + frames_needed = (self.reservoir_frame_delay + - self.scale_window_ntus) + .clamp(0, cur_nframes_left - cur_scale_window_nframes); + // Clear the buffer for the next frame. + self.des.pass2_buffer_fill = 0; + } else { + // Go back for more data. + break; + } + } else { + return Ok( + TWOPASS_PACKET_SZ * (frames_needed as usize) + - self.des.pass2_buffer_fill, + ); + } + } + // If we've got all the frames we need, fill in the current metrics. + // We're ready to go. + if frames_needed <= 0 { + self.cur_metrics = self.frame_metrics[self.frame_metrics_head]; + // Mark us ready for the next frame. + self.pass2_data_ready = true; + } + } + } + + Ok(consumed) + } + + // If called without a buffer it will return the size of the next + // buffer it expects. + // + // If called with a buffer it will consume it fully. + // It returns Ok(0) if the buffer had been parsed or Err(()) + // if the buffer hadn't been enough or other errors happened. + pub(crate) fn twopass_in( + &mut self, maybe_buf: Option<&[u8]>, + ) -> Result { + let mut consumed = 0; + self.init_second_pass(); + // If we haven't got a valid summary header yet, try to parse one. + if self.nframes_total[FRAME_SUBTYPE_I] == 0 { + self.pass2_data_ready = false; + if let Some(buf) = maybe_buf { + consumed = self.twopass_parse_summary(buf)? + } else { + return Ok(self.twopass_first_packet_size()); + } + } + if self.nframes_total[FRAME_SUBTYPE_I] > 0 { + if self.nencoded_frames + self.nsef_frames + >= self.nframes_total_total as i64 + { + // We don't want any more data after the last frame, and we don't want + // to allow any more frames to be encoded. + self.pass2_data_ready = false; + } else if !self.pass2_data_ready { + return self.twopass_parse_frame_data(maybe_buf, consumed); + } + } + Ok(consumed) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rdo.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rdo.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2752 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_camel_case_types)] + +use std::fmt; +use std::mem::MaybeUninit; + +use arrayvec::*; +use itertools::izip; + +use crate::api::*; +use crate::cdef::*; +use crate::context::*; +use crate::cpu_features::CpuFeatureLevel; +use crate::deblock::*; +use crate::dist::*; +use crate::ec::{Writer, WriterCounter, OD_BITRES}; +use crate::encode_block_with_modes; +use crate::encoder::{FrameInvariants, IMPORTANCE_BLOCK_SIZE}; +use crate::frame::*; +use crate::header::ReferenceMode; +use crate::lrf::*; +use crate::mc::MotionVector; +use crate::me::estimate_motion; +use crate::me::MVSamplingMode; +use crate::me::MotionSearchResult; +use crate::motion_compensate; +use crate::partition::PartitionType::*; +use crate::partition::RefType::*; +use crate::partition::*; +use crate::predict::{ + luma_ac, AngleDelta, IntraEdgeFilterParameters, IntraParam, PredictionMode, + RAV1E_INTER_COMPOUND_MODES, RAV1E_INTER_MODES_MINIMAL, RAV1E_INTRA_MODES, +}; +use crate::rdo_tables::*; +use crate::tiling::*; +use crate::transform::{TxSet, TxSize, TxType, RAV1E_TX_TYPES}; +use crate::util::{init_slice_repeat_mut, Aligned, Pixel}; +use crate::write_tx_blocks; +use crate::write_tx_tree; +use crate::Tune; +use crate::{encode_block_post_cdef, encode_block_pre_cdef}; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum RDOType { + PixelDistRealRate, + TxDistRealRate, + TxDistEstRate, +} + +impl RDOType { + #[inline] + pub const fn needs_tx_dist(self) -> bool { + match self { + // Pixel-domain distortion and exact ec rate + RDOType::PixelDistRealRate => false, + // Tx-domain distortion and exact ec rate + RDOType::TxDistRealRate => true, + // Tx-domain distortion and txdist-based rate + RDOType::TxDistEstRate => true, + } + } + #[inline] + pub const fn needs_coeff_rate(self) -> bool { + match self { + RDOType::PixelDistRealRate => true, + RDOType::TxDistRealRate => true, + RDOType::TxDistEstRate => false, + } + } +} + +#[derive(Clone)] +pub struct PartitionGroupParameters { + pub rd_cost: f64, + pub part_type: PartitionType, + pub part_modes: ArrayVec, +} + +#[derive(Clone, Debug)] +pub struct PartitionParameters { + pub rd_cost: f64, + pub bo: TileBlockOffset, + pub bsize: BlockSize, + pub pred_mode_luma: PredictionMode, + pub pred_mode_chroma: PredictionMode, + pub pred_cfl_params: CFLParams, + pub angle_delta: AngleDelta, + pub ref_frames: [RefType; 2], + pub mvs: [MotionVector; 2], + pub skip: bool, + pub has_coeff: bool, + pub tx_size: TxSize, + pub tx_type: TxType, + pub sidx: u8, +} + +impl Default for PartitionParameters { + fn default() -> Self { + PartitionParameters { + rd_cost: f64::MAX, + bo: TileBlockOffset::default(), + bsize: BlockSize::BLOCK_32X32, + pred_mode_luma: PredictionMode::default(), + pred_mode_chroma: PredictionMode::default(), + pred_cfl_params: CFLParams::default(), + angle_delta: AngleDelta::default(), + ref_frames: [RefType::INTRA_FRAME, RefType::NONE_FRAME], + mvs: [MotionVector::default(); 2], + skip: false, + has_coeff: true, + tx_size: TxSize::TX_4X4, + tx_type: TxType::DCT_DCT, + sidx: 0, + } + } +} + +pub fn estimate_rate(qindex: u8, ts: TxSize, fast_distortion: u64) -> u64 { + let bs_index = ts as usize; + let q_bin_idx = (qindex as usize) / RDO_QUANT_DIV; + let bin_idx_down = + ((fast_distortion) / RATE_EST_BIN_SIZE).min((RDO_NUM_BINS - 2) as u64); + let bin_idx_up = (bin_idx_down + 1).min((RDO_NUM_BINS - 1) as u64); + let x0 = (bin_idx_down * RATE_EST_BIN_SIZE) as i64; + let x1 = (bin_idx_up * RATE_EST_BIN_SIZE) as i64; + let y0 = RDO_RATE_TABLE[q_bin_idx][bs_index][bin_idx_down as usize] as i64; + let y1 = RDO_RATE_TABLE[q_bin_idx][bs_index][bin_idx_up as usize] as i64; + let slope = ((y1 - y0) << 8) / (x1 - x0); + (y0 + (((fast_distortion as i64 - x0) * slope) >> 8)).max(0) as u64 +} + +#[allow(unused)] +pub fn cdef_dist_wxh DistortionScale>( + src1: &PlaneRegion<'_, T>, src2: &PlaneRegion<'_, T>, w: usize, h: usize, + bit_depth: usize, compute_bias: F, cpu: CpuFeatureLevel, +) -> Distortion { + debug_assert!(src1.plane_cfg.xdec == 0); + debug_assert!(src1.plane_cfg.ydec == 0); + debug_assert!(src2.plane_cfg.xdec == 0); + debug_assert!(src2.plane_cfg.ydec == 0); + + let mut sum = Distortion::zero(); + for y in (0..h).step_by(8) { + for x in (0..w).step_by(8) { + let kernel_h = (h - y).min(8); + let kernel_w = (w - x).min(8); + let area = Area::StartingAt { x: x as isize, y: y as isize }; + + let value = RawDistortion(cdef_dist_kernel( + &src1.subregion(area), + &src2.subregion(area), + kernel_w, + kernel_h, + bit_depth, + cpu, + ) as u64); + + // cdef is always called on non-subsampled planes, so BLOCK_8X8 is + // correct here. + sum += value * compute_bias(area, BlockSize::BLOCK_8X8); + } + } + sum +} + +/// Sum of Squared Error for a wxh block +/// Currently limited to w and h of valid blocks +pub fn sse_wxh DistortionScale>( + src1: &PlaneRegion<'_, T>, src2: &PlaneRegion<'_, T>, w: usize, h: usize, + compute_bias: F, bit_depth: usize, cpu: CpuFeatureLevel, +) -> Distortion { + // See get_weighted_sse in src/dist.rs. + // Provide a scale to get_weighted_sse for each square region of this size. + const CHUNK_SIZE: usize = IMPORTANCE_BLOCK_SIZE >> 1; + + // To bias the distortion correctly, compute it in blocks up to the size + // importance block size in a non-subsampled plane. + let imp_block_w = CHUNK_SIZE << src1.plane_cfg.xdec; + let imp_block_h = CHUNK_SIZE << src1.plane_cfg.ydec; + + let imp_bsize = BlockSize::from_width_and_height(imp_block_w, imp_block_h); + + let n_imp_blocks_w = w.div_ceil(CHUNK_SIZE); + let n_imp_blocks_h = h.div_ceil(CHUNK_SIZE); + + // TODO: Copying biases into a buffer is slow. It would be best if biases were + // passed directly. To do this, we would need different versions of the + // weighted sse function for decimated/subsampled data. Also requires + // eliminating use of unbiased sse. + // It should also be noted that the current copy code does not auto-vectorize. + + // Copy biases into a buffer. + let mut buf_storage = Aligned::new( + [MaybeUninit::::uninit(); 128 / CHUNK_SIZE * 128 / CHUNK_SIZE], + ); + let buf_stride = n_imp_blocks_w.next_power_of_two(); + let buf = init_slice_repeat_mut( + &mut buf_storage.data[..buf_stride * n_imp_blocks_h], + 0, + ); + + for block_y in 0..n_imp_blocks_h { + for block_x in 0..n_imp_blocks_w { + let block = Area::StartingAt { + x: (block_x * CHUNK_SIZE) as isize, + y: (block_y * CHUNK_SIZE) as isize, + }; + buf[block_y * buf_stride + block_x] = compute_bias(block, imp_bsize).0; + } + } + + Distortion(get_weighted_sse( + src1, src2, buf, buf_stride, w, h, bit_depth, cpu, + )) +} + +// TODO consider saturating_sub later +#[allow(clippy::implicit_saturating_sub)] +pub const fn clip_visible_bsize( + frame_w: usize, frame_h: usize, bsize: BlockSize, x: usize, y: usize, +) -> (usize, usize) { + let blk_w = bsize.width(); + let blk_h = bsize.height(); + + let visible_w: usize = if x + blk_w <= frame_w { + blk_w + } else if x >= frame_w { + 0 + } else { + frame_w - x + }; + + let visible_h: usize = if y + blk_h <= frame_h { + blk_h + } else if y >= frame_h { + 0 + } else { + frame_h - y + }; + + (visible_w, visible_h) +} + +// Compute the pixel-domain distortion for an encode +fn compute_distortion( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, bsize: BlockSize, + is_chroma_block: bool, tile_bo: TileBlockOffset, luma_only: bool, +) -> ScaledDistortion { + let area = Area::BlockStartingAt { bo: tile_bo.0 }; + let input_region = ts.input_tile.planes[0].subregion(area); + let rec_region = ts.rec.planes[0].subregion(area); + + // clip a block to have visible pixles only + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (visible_w, visible_h) = clip_visible_bsize( + fi.width, + fi.height, + bsize, + frame_bo.0.x << MI_SIZE_LOG2, + frame_bo.0.y << MI_SIZE_LOG2, + ); + + if visible_w == 0 || visible_h == 0 { + return ScaledDistortion::zero(); + } + + let mut distortion = match fi.config.tune { + Tune::Psychovisual => cdef_dist_wxh( + &input_region, + &rec_region, + visible_w, + visible_h, + fi.sequence.bit_depth, + |bias_area, bsize| { + distortion_scale( + fi, + input_region.subregion(bias_area).frame_block_offset(), + bsize, + ) + }, + fi.cpu_feature_level, + ), + Tune::Psnr => sse_wxh( + &input_region, + &rec_region, + visible_w, + visible_h, + |bias_area, bsize| { + distortion_scale( + fi, + input_region.subregion(bias_area).frame_block_offset(), + bsize, + ) + }, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ), + } * fi.dist_scale[0]; + + if is_chroma_block + && !luma_only + && fi.sequence.chroma_sampling != ChromaSampling::Cs400 + { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let chroma_w = if bsize.width() >= 8 || xdec == 0 { + (visible_w + xdec) >> xdec + } else { + (4 + visible_w + xdec) >> xdec + }; + let chroma_h = if bsize.height() >= 8 || ydec == 0 { + (visible_h + ydec) >> ydec + } else { + (4 + visible_h + ydec) >> ydec + }; + + for p in 1..3 { + let input_region = ts.input_tile.planes[p].subregion(area); + let rec_region = ts.rec.planes[p].subregion(area); + distortion += sse_wxh( + &input_region, + &rec_region, + chroma_w, + chroma_h, + |bias_area, bsize| { + distortion_scale( + fi, + input_region.subregion(bias_area).frame_block_offset(), + bsize, + ) + }, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) * fi.dist_scale[p]; + } + } + distortion +} + +// Compute the transform-domain distortion for an encode +fn compute_tx_distortion( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, bsize: BlockSize, + is_chroma_block: bool, tile_bo: TileBlockOffset, tx_dist: ScaledDistortion, + skip: bool, luma_only: bool, +) -> ScaledDistortion { + assert!(fi.config.tune == Tune::Psnr); + let area = Area::BlockStartingAt { bo: tile_bo.0 }; + let input_region = ts.input_tile.planes[0].subregion(area); + let rec_region = ts.rec.planes[0].subregion(area); + + let (visible_w, visible_h) = if !skip { + (bsize.width(), bsize.height()) + } else { + let frame_bo = ts.to_frame_block_offset(tile_bo); + clip_visible_bsize( + fi.width, + fi.height, + bsize, + frame_bo.0.x << MI_SIZE_LOG2, + frame_bo.0.y << MI_SIZE_LOG2, + ) + }; + + if visible_w == 0 || visible_h == 0 { + return ScaledDistortion::zero(); + } + + let mut distortion = if skip { + sse_wxh( + &input_region, + &rec_region, + visible_w, + visible_h, + |bias_area, bsize| { + distortion_scale( + fi, + input_region.subregion(bias_area).frame_block_offset(), + bsize, + ) + }, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) * fi.dist_scale[0] + } else { + tx_dist + }; + + if is_chroma_block + && !luma_only + && skip + && fi.sequence.chroma_sampling != ChromaSampling::Cs400 + { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let chroma_w = if bsize.width() >= 8 || xdec == 0 { + (visible_w + xdec) >> xdec + } else { + (4 + visible_w + xdec) >> xdec + }; + let chroma_h = if bsize.height() >= 8 || ydec == 0 { + (visible_h + ydec) >> ydec + } else { + (4 + visible_h + ydec) >> ydec + }; + + for p in 1..3 { + let input_region = ts.input_tile.planes[p].subregion(area); + let rec_region = ts.rec.planes[p].subregion(area); + distortion += sse_wxh( + &input_region, + &rec_region, + chroma_w, + chroma_h, + |bias_area, bsize| { + distortion_scale( + fi, + input_region.subregion(bias_area).frame_block_offset(), + bsize, + ) + }, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) * fi.dist_scale[p]; + } + } + distortion +} + +/// Compute a scaling factor to multiply the distortion of a block by, +/// this factor is determined using temporal RDO. +/// +/// # Panics +/// +/// - If called with `bsize` of 8x8 or smaller +/// - If the coded frame data doesn't exist on the `FrameInvariants` +pub fn distortion_scale( + fi: &FrameInvariants, frame_bo: PlaneBlockOffset, bsize: BlockSize, +) -> DistortionScale { + if !fi.config.temporal_rdo() { + return DistortionScale::default(); + } + // EncoderConfig::temporal_rdo() should always return false in situations + // where distortion is computed on > 8x8 blocks, so we should never hit this + // assert. + assert!(bsize <= BlockSize::BLOCK_8X8); + + let x = frame_bo.0.x >> IMPORTANCE_BLOCK_TO_BLOCK_SHIFT; + let y = frame_bo.0.y >> IMPORTANCE_BLOCK_TO_BLOCK_SHIFT; + + let coded_data = fi.coded_frame_data.as_ref().unwrap(); + coded_data.distortion_scales[y * coded_data.w_in_imp_b + x] +} + +/// # Panics +/// +/// - If the coded frame data doesn't exist on the `FrameInvariants` +pub fn spatiotemporal_scale( + fi: &FrameInvariants, frame_bo: PlaneBlockOffset, bsize: BlockSize, +) -> DistortionScale { + if !fi.config.temporal_rdo() && fi.config.tune != Tune::Psychovisual { + return DistortionScale::default(); + } + + let coded_data = fi.coded_frame_data.as_ref().unwrap(); + + let x0 = frame_bo.0.x >> IMPORTANCE_BLOCK_TO_BLOCK_SHIFT; + let y0 = frame_bo.0.y >> IMPORTANCE_BLOCK_TO_BLOCK_SHIFT; + let x1 = (x0 + bsize.width_imp_b()).min(coded_data.w_in_imp_b); + let y1 = (y0 + bsize.height_imp_b()).min(coded_data.h_in_imp_b); + let den = (((x1 - x0) * (y1 - y0)) as u64) << DistortionScale::SHIFT; + + // calling this on each slice individually improves autovectorization + // compared to using `Iterator::take` + #[inline(always)] + fn take_slice(slice: &[T], n: usize) -> &[T] { + slice.get(..n).unwrap_or(slice) + } + + let mut sum = 0; + for y in y0..y1 { + sum += take_slice( + &coded_data.distortion_scales[y * coded_data.w_in_imp_b..][x0..x1], + MAX_SB_IN_IMP_B, + ) + .iter() + .zip( + take_slice( + &coded_data.activity_scales[y * coded_data.w_in_imp_b..][x0..x1], + MAX_SB_IN_IMP_B, + ) + .iter(), + ) + .map(|(d, a)| d.0 as u64 * a.0 as u64) + .sum::(); + } + DistortionScale(((sum + (den >> 1)) / den) as u32) +} + +pub fn distortion_scale_for( + propagate_cost: f64, intra_cost: f64, +) -> DistortionScale { + // The mbtree paper \cite{mbtree} uses the following formula: + // + // QP_delta = -strength * log2(1 + (propagate_cost / intra_cost)) + // + // Since this is H.264, this corresponds to the following quantizer: + // + // Q' = Q * 2^(QP_delta/6) + // + // Since lambda is proportial to Q^2, this means we want to minimize: + // + // D + lambda' * R + // = D + 2^(QP_delta / 3) * lambda * R + // + // If we want to keep lambda fixed, we can instead scale distortion and + // minimize: + // + // D * scale + lambda * R + // + // where: + // + // scale = 2^(QP_delta / -3) + // = (1 + (propagate_cost / intra_cost))^(strength / 3) + // + // The original paper empirically chooses strength = 2.0, but strength = 1.0 + // seems to work best in rav1e currently, this may have something to do with + // the fact that they use 16x16 blocks whereas our "importance blocks" are + // 8x8, but everything should be scale invariant here so that's weird. + // + // @article{mbtree, + // title={A novel macroblock-tree algorithm for high-performance + // optimization of dependent video coding in H.264/AVC}, + // author={Garrett-Glaser, Jason}, + // journal={Tech. Rep.}, + // year={2009}, + // url={https://pdfs.semanticscholar.org/032f/1ab7d9db385780a02eb2d579af8303b266d2.pdf} + // } + + if intra_cost == 0. { + return DistortionScale::default(); // no scaling + } + + let strength = 1.0; // empirical, see comment above + let frac = (intra_cost + propagate_cost) / intra_cost; + frac.powf(strength / 3.0).into() +} + +/// Fixed point arithmetic version of distortion scale +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct DistortionScale(pub u32); + +#[repr(transparent)] +pub struct RawDistortion(u64); + +#[repr(transparent)] +pub struct Distortion(pub u64); + +#[repr(transparent)] +pub struct ScaledDistortion(u64); + +impl DistortionScale { + /// Bits past the radix point + const SHIFT: u32 = 14; + /// Number of bits used. Determines the max value. + /// 28 bits is quite excessive. + const BITS: u32 = 28; + /// Maximum internal value + const MAX: u64 = (1 << Self::BITS) - 1; + + #[inline] + pub const fn new(num: u64, den: u64) -> Self { + let raw = (num << Self::SHIFT).saturating_add(den / 2) / den; + let mask = (raw <= Self::MAX) as u64; + Self((mask * raw + (1 - mask) * Self::MAX) as u32) + } + + pub fn inv_mean(slice: &[Self]) -> Self { + use crate::util::{bexp64, blog32_q11}; + let sum = slice.iter().map(|&s| blog32_q11(s.0) as i64).sum::(); + let log_inv_mean_q11 = + (Self::SHIFT << 11) as i64 - sum / slice.len() as i64; + Self( + bexp64((log_inv_mean_q11 + (Self::SHIFT << 11) as i64) << (57 - 11)) + .clamp(1, (1 << Self::BITS) - 1) as u32, + ) + } + + /// Binary logarithm in Q11 + #[inline] + pub const fn blog16(self) -> i16 { + use crate::util::blog32_q11; + (blog32_q11(self.0) - ((Self::SHIFT as i32) << 11)) as i16 + } + + /// Binary logarithm in Q57 + #[inline] + pub const fn blog64(self) -> i64 { + use crate::util::{blog64, q57}; + blog64(self.0 as i64) - q57(Self::SHIFT as i32) + } + + /// Multiply, round and shift + /// Internal implementation, so don't use multiply trait. + #[inline] + pub const fn mul_u64(self, dist: u64) -> u64 { + (self.0 as u64 * dist + (1 << Self::SHIFT >> 1)) >> Self::SHIFT + } +} + +impl std::ops::Mul for DistortionScale { + type Output = Self; + + /// Multiply, round and shift + #[inline] + fn mul(self, rhs: Self) -> Self { + Self( + (((self.0 as u64 * rhs.0 as u64) + (1 << (Self::SHIFT - 1))) + >> Self::SHIFT) + .clamp(1, (1 << Self::BITS) - 1) as u32, + ) + } +} + +impl std::ops::MulAssign for DistortionScale { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; + } +} + +// Default value for DistortionScale is a fixed point 1 +impl Default for DistortionScale { + #[inline] + fn default() -> Self { + Self(1 << Self::SHIFT) + } +} + +impl fmt::Debug for DistortionScale { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", f64::from(*self)) + } +} + +impl From for DistortionScale { + #[inline] + fn from(scale: f64) -> Self { + let den = 1 << (Self::SHIFT + 1); + Self::new((scale * den as f64) as u64, den) + } +} + +impl From for f64 { + #[inline] + fn from(scale: DistortionScale) -> Self { + scale.0 as f64 / (1 << DistortionScale::SHIFT) as f64 + } +} + +impl RawDistortion { + #[inline] + pub const fn new(dist: u64) -> Self { + Self(dist) + } +} + +impl std::ops::Mul for RawDistortion { + type Output = Distortion; + #[inline] + fn mul(self, rhs: DistortionScale) -> Distortion { + Distortion(rhs.mul_u64(self.0)) + } +} + +impl Distortion { + #[inline] + pub const fn zero() -> Self { + Self(0) + } +} + +impl std::ops::Mul for Distortion { + type Output = ScaledDistortion; + #[inline] + fn mul(self, rhs: DistortionScale) -> ScaledDistortion { + ScaledDistortion(rhs.mul_u64(self.0)) + } +} + +impl std::ops::AddAssign for Distortion { + #[inline] + fn add_assign(&mut self, other: Self) { + self.0 += other.0; + } +} + +impl ScaledDistortion { + #[inline] + pub const fn zero() -> Self { + Self(0) + } +} + +impl std::ops::AddAssign for ScaledDistortion { + #[inline] + fn add_assign(&mut self, other: Self) { + self.0 += other.0; + } +} + +pub fn compute_rd_cost( + fi: &FrameInvariants, rate: u32, distortion: ScaledDistortion, +) -> f64 { + let rate_in_bits = (rate as f64) / ((1 << OD_BITRES) as f64); + fi.lambda.mul_add(rate_in_bits, distortion.0 as f64) +} + +pub fn rdo_tx_size_type( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, bsize: BlockSize, tile_bo: TileBlockOffset, + luma_mode: PredictionMode, ref_frames: [RefType; 2], mvs: [MotionVector; 2], + skip: bool, +) -> (TxSize, TxType) { + let is_inter = !luma_mode.is_intra(); + let mut tx_size = max_txsize_rect_lookup[bsize as usize]; + + if fi.enable_inter_txfm_split && is_inter && !skip { + tx_size = sub_tx_size_map[tx_size as usize]; // Always choose one level split size + } + + let mut best_tx_type = TxType::DCT_DCT; + let mut best_tx_size = tx_size; + let mut best_rd = f64::MAX; + + let do_rdo_tx_size = fi.tx_mode_select + && fi.config.speed_settings.transform.rdo_tx_decision + && !is_inter; + let rdo_tx_depth = if do_rdo_tx_size { 2 } else { 0 }; + let mut cw_checkpoint: Option = None; + + for _ in 0..=rdo_tx_depth { + let tx_set = get_tx_set(tx_size, is_inter, fi.use_reduced_tx_set); + + let do_rdo_tx_type = tx_set > TxSet::TX_SET_DCTONLY + && fi.config.speed_settings.transform.rdo_tx_decision + && !is_inter + && !skip; + + if !do_rdo_tx_size && !do_rdo_tx_type { + return (best_tx_size, best_tx_type); + }; + + let tx_types = + if do_rdo_tx_type { RAV1E_TX_TYPES } else { &[TxType::DCT_DCT] }; + + // Luma plane transform type decision + let (tx_type, rd_cost) = rdo_tx_type_decision( + fi, + ts, + cw, + &mut cw_checkpoint, + luma_mode, + ref_frames, + mvs, + bsize, + tile_bo, + tx_size, + tx_set, + tx_types, + best_rd, + ); + + if rd_cost < best_rd { + best_tx_size = tx_size; + best_tx_type = tx_type; + best_rd = rd_cost; + } + + debug_assert!(tx_size.width_log2() <= bsize.width_log2()); + debug_assert!(tx_size.height_log2() <= bsize.height_log2()); + debug_assert!( + tx_size.sqr() <= TxSize::TX_32X32 || tx_type == TxType::DCT_DCT + ); + + let next_tx_size = sub_tx_size_map[tx_size as usize]; + + if next_tx_size == tx_size { + break; + } else { + tx_size = next_tx_size; + }; + } + + (best_tx_size, best_tx_type) +} + +#[inline] +const fn dmv_in_range(mv: MotionVector, ref_mv: MotionVector) -> bool { + let diff_row = mv.row as i32 - ref_mv.row as i32; + let diff_col = mv.col as i32 - ref_mv.col as i32; + diff_row >= MV_LOW + && diff_row <= MV_UPP + && diff_col >= MV_LOW + && diff_col <= MV_UPP +} + +#[inline] +#[profiling::function] +fn luma_chroma_mode_rdo( + luma_mode: PredictionMode, fi: &FrameInvariants, bsize: BlockSize, + tile_bo: TileBlockOffset, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, rdo_type: RDOType, + cw_checkpoint: &ContextWriterCheckpoint, best: &mut PartitionParameters, + mvs: [MotionVector; 2], ref_frames: [RefType; 2], + mode_set_chroma: &[PredictionMode], luma_mode_is_intra: bool, + mode_context: usize, mv_stack: &ArrayVec, + angle_delta: AngleDelta, +) { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + + let is_chroma_block = + has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling); + + if !luma_mode_is_intra { + let ref_mvs = if mv_stack.is_empty() { + [MotionVector::default(); 2] + } else { + [mv_stack[0].this_mv, mv_stack[0].comp_mv] + }; + + if (luma_mode == PredictionMode::NEWMV + || luma_mode == PredictionMode::NEW_NEWMV + || luma_mode == PredictionMode::NEW_NEARESTMV) + && !dmv_in_range(mvs[0], ref_mvs[0]) + { + return; + } + + if (luma_mode == PredictionMode::NEW_NEWMV + || luma_mode == PredictionMode::NEAREST_NEWMV) + && !dmv_in_range(mvs[1], ref_mvs[1]) + { + return; + } + } + + // Find the best chroma prediction mode for the current luma prediction mode + let mut chroma_rdo = |skip: bool| -> bool { + use crate::segmentation::select_segment; + + let mut zero_distortion = false; + + for sidx in select_segment(fi, ts, tile_bo, bsize, skip) { + cw.bc.blocks.set_segmentation_idx(tile_bo, bsize, sidx); + + let (tx_size, tx_type) = rdo_tx_size_type( + fi, ts, cw, bsize, tile_bo, luma_mode, ref_frames, mvs, skip, + ); + for &chroma_mode in mode_set_chroma.iter() { + let wr = &mut WriterCounter::new(); + let tell = wr.tell_frac(); + + if bsize >= BlockSize::BLOCK_8X8 && bsize.is_sqr() { + cw.write_partition( + wr, + tile_bo, + PartitionType::PARTITION_NONE, + bsize, + ); + } + + // TODO(yushin): luma and chroma would have different decision based on chroma format + let need_recon_pixel = + luma_mode_is_intra && tx_size.block_size() != bsize; + + encode_block_pre_cdef(&fi.sequence, ts, cw, wr, bsize, tile_bo, skip); + let (has_coeff, tx_dist) = encode_block_post_cdef( + fi, + ts, + cw, + wr, + luma_mode, + chroma_mode, + angle_delta, + ref_frames, + mvs, + bsize, + tile_bo, + skip, + CFLParams::default(), + tx_size, + tx_type, + mode_context, + mv_stack, + rdo_type, + need_recon_pixel, + None, + ); + + let rate = wr.tell_frac() - tell; + let distortion = if fi.use_tx_domain_distortion && !need_recon_pixel { + compute_tx_distortion( + fi, + ts, + bsize, + is_chroma_block, + tile_bo, + tx_dist, + skip, + false, + ) + } else { + compute_distortion(fi, ts, bsize, is_chroma_block, tile_bo, false) + }; + let is_zero_dist = distortion.0 == 0; + let rd = compute_rd_cost(fi, rate, distortion); + if rd < best.rd_cost { + //if rd < best.rd_cost || luma_mode == PredictionMode::NEW_NEWMV { + best.rd_cost = rd; + best.pred_mode_luma = luma_mode; + best.pred_mode_chroma = chroma_mode; + best.angle_delta = angle_delta; + best.ref_frames = ref_frames; + best.mvs = mvs; + best.skip = skip; + best.has_coeff = has_coeff; + best.tx_size = tx_size; + best.tx_type = tx_type; + best.sidx = sidx; + zero_distortion = is_zero_dist; + } + + cw.rollback(cw_checkpoint); + } + } + + zero_distortion + }; + + // Don't skip when using intra modes + let zero_distortion = + if !luma_mode_is_intra { chroma_rdo(true) } else { false }; + // early skip + if !zero_distortion { + chroma_rdo(false); + } +} + +/// RDO-based mode decision +/// +/// # Panics +/// +/// - If the best RD found is negative. +/// This should never happen and indicates a development error. +#[profiling::function] +pub fn rdo_mode_decision( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, bsize: BlockSize, tile_bo: TileBlockOffset, + inter_cfg: &InterConfig, +) -> PartitionParameters { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let cw_checkpoint = cw.checkpoint(&tile_bo, fi.sequence.chroma_sampling); + + let rdo_type = if fi.use_tx_domain_rate { + RDOType::TxDistEstRate + } else if fi.use_tx_domain_distortion { + RDOType::TxDistRealRate + } else { + RDOType::PixelDistRealRate + }; + + let mut best = if fi.frame_type.has_inter() { + assert!(fi.frame_type != FrameType::KEY); + + inter_frame_rdo_mode_decision( + fi, + ts, + cw, + bsize, + tile_bo, + inter_cfg, + &cw_checkpoint, + rdo_type, + ) + } else { + PartitionParameters::default() + }; + + let is_chroma_block = + has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling); + + if !best.skip { + best = intra_frame_rdo_mode_decision( + fi, + ts, + cw, + bsize, + tile_bo, + &cw_checkpoint, + rdo_type, + best, + is_chroma_block, + ); + } + + if best.pred_mode_luma.is_intra() && is_chroma_block && bsize.cfl_allowed() { + cw.bc.blocks.set_segmentation_idx(tile_bo, bsize, best.sidx); + + let chroma_mode = PredictionMode::UV_CFL_PRED; + let cw_checkpoint = cw.checkpoint(&tile_bo, fi.sequence.chroma_sampling); + let mut wr = WriterCounter::new(); + let angle_delta = AngleDelta { y: best.angle_delta.y, uv: 0 }; + + write_tx_blocks( + fi, + ts, + cw, + &mut wr, + best.pred_mode_luma, + best.pred_mode_luma, + angle_delta, + tile_bo, + bsize, + best.tx_size, + best.tx_type, + false, + CFLParams::default(), + true, + rdo_type, + true, + ); + cw.rollback(&cw_checkpoint); + if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { + if let Some(cfl) = rdo_cfl_alpha(ts, tile_bo, bsize, best.tx_size, fi) { + let mut wr = WriterCounter::new(); + let tell = wr.tell_frac(); + + encode_block_pre_cdef( + &fi.sequence, + ts, + cw, + &mut wr, + bsize, + tile_bo, + best.skip, + ); + let (has_coeff, _) = encode_block_post_cdef( + fi, + ts, + cw, + &mut wr, + best.pred_mode_luma, + chroma_mode, + angle_delta, + best.ref_frames, + best.mvs, + bsize, + tile_bo, + best.skip, + cfl, + best.tx_size, + best.tx_type, + 0, + &[], + rdo_type, + true, // For CFL, luma should be always reconstructed. + None, + ); + + let rate = wr.tell_frac() - tell; + + // For CFL, tx-domain distortion is not an option. + let distortion = + compute_distortion(fi, ts, bsize, is_chroma_block, tile_bo, false); + let rd = compute_rd_cost(fi, rate, distortion); + if rd < best.rd_cost { + best.rd_cost = rd; + best.pred_mode_chroma = chroma_mode; + best.angle_delta = angle_delta; + best.has_coeff = has_coeff; + best.pred_cfl_params = cfl; + } + + cw.rollback(&cw_checkpoint); + } + } + } + + cw.bc.blocks.set_mode(tile_bo, bsize, best.pred_mode_luma); + cw.bc.blocks.set_ref_frames(tile_bo, bsize, best.ref_frames); + cw.bc.blocks.set_motion_vectors(tile_bo, bsize, best.mvs); + + assert!(best.rd_cost >= 0_f64); + + PartitionParameters { + bo: tile_bo, + bsize, + pred_mode_luma: best.pred_mode_luma, + pred_mode_chroma: best.pred_mode_chroma, + pred_cfl_params: best.pred_cfl_params, + angle_delta: best.angle_delta, + ref_frames: best.ref_frames, + mvs: best.mvs, + rd_cost: best.rd_cost, + skip: best.skip, + has_coeff: best.has_coeff, + tx_size: best.tx_size, + tx_type: best.tx_type, + sidx: best.sidx, + } +} + +#[profiling::function] +fn inter_frame_rdo_mode_decision( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, bsize: BlockSize, tile_bo: TileBlockOffset, + inter_cfg: &InterConfig, cw_checkpoint: &ContextWriterCheckpoint, + rdo_type: RDOType, +) -> PartitionParameters { + let mut best = PartitionParameters::default(); + + // we can never have more than 7 reference frame sets + let mut ref_frames_set = ArrayVec::<_, 7>::new(); + // again, max of 7 ref slots + let mut ref_slot_set = ArrayVec::<_, 7>::new(); + // our implementation never returns more than 3 at the moment + let mut mvs_from_me = ArrayVec::<_, 3>::new(); + let mut fwdref = None; + let mut bwdref = None; + + for i in inter_cfg.allowed_ref_frames().iter().copied() { + // Don't search LAST3 since it's used only for probs + if i == LAST3_FRAME { + continue; + } + + if !ref_slot_set.contains(&fi.ref_frames[i.to_index()]) { + if fwdref.is_none() && i.is_fwd_ref() { + fwdref = Some(ref_frames_set.len()); + } + if bwdref.is_none() && i.is_bwd_ref() { + bwdref = Some(ref_frames_set.len()); + } + ref_frames_set.push([i, NONE_FRAME]); + let slot_idx = fi.ref_frames[i.to_index()]; + ref_slot_set.push(slot_idx); + } + } + assert!(!ref_frames_set.is_empty()); + + let mut inter_mode_set = ArrayVec::<(PredictionMode, usize), 20>::new(); + let mut mvs_set = ArrayVec::<[MotionVector; 2], 20>::new(); + let mut satds = ArrayVec::::new(); + let mut mv_stacks = ArrayVec::<_, 20>::new(); + let mut mode_contexts = ArrayVec::<_, 7>::new(); + + for (i, &ref_frames) in ref_frames_set.iter().enumerate() { + let mut mv_stack = ArrayVec::::new(); + mode_contexts.push(cw.find_mvrefs( + tile_bo, + ref_frames, + &mut mv_stack, + bsize, + fi, + false, + )); + + let mut pmv = [MotionVector::default(); 2]; + if !mv_stack.is_empty() { + pmv[0] = mv_stack[0].this_mv; + } + if mv_stack.len() > 1 { + pmv[1] = mv_stack[1].this_mv; + } + + let res = estimate_motion( + fi, + ts, + bsize.width(), + bsize.height(), + tile_bo, + ref_frames[0], + Some(pmv), + MVSamplingMode::CORNER { right: true, bottom: true }, + false, + 0, + None, + ) + .unwrap_or_else(MotionSearchResult::empty); + let b_me = res.mv; + + mvs_from_me.push([b_me, MotionVector::default()]); + + for &x in RAV1E_INTER_MODES_MINIMAL { + inter_mode_set.push((x, i)); + } + if !mv_stack.is_empty() { + inter_mode_set.push((PredictionMode::NEAR0MV, i)); + } + if mv_stack.len() >= 2 { + inter_mode_set.push((PredictionMode::GLOBALMV, i)); + } + let include_near_mvs = fi.config.speed_settings.motion.include_near_mvs; + if include_near_mvs { + if mv_stack.len() >= 3 { + inter_mode_set.push((PredictionMode::NEAR1MV, i)); + } + if mv_stack.len() >= 4 { + inter_mode_set.push((PredictionMode::NEAR2MV, i)); + } + } + let same_row_col = |x: &CandidateMV| { + x.this_mv.row == mvs_from_me[i][0].row + && x.this_mv.col == mvs_from_me[i][0].col + }; + if !mv_stack + .iter() + .take(if include_near_mvs { 4 } else { 2 }) + .any(same_row_col) + && (mvs_from_me[i][0].row != 0 || mvs_from_me[i][0].col != 0) + { + inter_mode_set.push((PredictionMode::NEWMV, i)); + } + + mv_stacks.push(mv_stack); + } + + let sz = bsize.width_mi().min(bsize.height_mi()); + + // To use non single reference modes, block width and height must be greater than 4. + if fi.reference_mode != ReferenceMode::SINGLE && sz >= 2 { + // Adding compound candidate + if let Some(r0) = fwdref { + if let Some(r1) = bwdref { + let ref_frames = [ref_frames_set[r0][0], ref_frames_set[r1][0]]; + ref_frames_set.push(ref_frames); + let mv0 = mvs_from_me[r0][0]; + let mv1 = mvs_from_me[r1][0]; + mvs_from_me.push([mv0, mv1]); + let mut mv_stack = ArrayVec::::new(); + mode_contexts.push(cw.find_mvrefs( + tile_bo, + ref_frames, + &mut mv_stack, + bsize, + fi, + true, + )); + for &x in RAV1E_INTER_COMPOUND_MODES { + // exclude any NEAR mode based on speed setting + if fi.config.speed_settings.motion.include_near_mvs + || !x.has_nearmv() + { + let mv_stack_idx = ref_frames_set.len() - 1; + // exclude NEAR modes if the mv_stack is too short + if !(x.has_nearmv() && x.ref_mv_idx() >= mv_stack.len()) { + inter_mode_set.push((x, mv_stack_idx)); + } + } + } + mv_stacks.push(mv_stack); + } + } + } + + let num_modes_rdo = if fi.config.speed_settings.prediction.prediction_modes + >= PredictionModesSetting::ComplexAll + { + inter_mode_set.len() + } else { + 9 // This number is determined by AWCY test + }; + + inter_mode_set.iter().for_each(|&(luma_mode, i)| { + let mvs = match luma_mode { + PredictionMode::NEWMV | PredictionMode::NEW_NEWMV => mvs_from_me[i], + PredictionMode::NEARESTMV | PredictionMode::NEAREST_NEARESTMV => { + if !mv_stacks[i].is_empty() { + [mv_stacks[i][0].this_mv, mv_stacks[i][0].comp_mv] + } else { + [MotionVector::default(); 2] + } + } + PredictionMode::NEAR0MV | PredictionMode::NEAR_NEAR0MV => { + if mv_stacks[i].len() > 1 { + [mv_stacks[i][1].this_mv, mv_stacks[i][1].comp_mv] + } else { + [MotionVector::default(); 2] + } + } + PredictionMode::NEAR1MV + | PredictionMode::NEAR2MV + | PredictionMode::NEAR_NEAR1MV + | PredictionMode::NEAR_NEAR2MV => [ + mv_stacks[i][luma_mode.ref_mv_idx()].this_mv, + mv_stacks[i][luma_mode.ref_mv_idx()].comp_mv, + ], + PredictionMode::NEAREST_NEWMV => { + [mv_stacks[i][0].this_mv, mvs_from_me[i][1]] + } + PredictionMode::NEW_NEARESTMV => { + [mvs_from_me[i][0], mv_stacks[i][0].comp_mv] + } + PredictionMode::GLOBALMV | PredictionMode::GLOBAL_GLOBALMV => { + [MotionVector::default(); 2] + } + _ => { + unimplemented!(); + } + }; + mvs_set.push(mvs); + + // Calculate SATD for each mode + if num_modes_rdo != inter_mode_set.len() { + let tile_rect = ts.tile_rect(); + let rec = &mut ts.rec.planes[0]; + let po = tile_bo.plane_offset(rec.plane_cfg); + let mut rec_region = + rec.subregion_mut(Area::BlockStartingAt { bo: tile_bo.0 }); + + luma_mode.predict_inter( + fi, + tile_rect, + 0, + po, + &mut rec_region, + bsize.width(), + bsize.height(), + ref_frames_set[i], + mvs, + &mut ts.inter_compound_buffers, + ); + + let plane_org = ts.input_tile.planes[0] + .subregion(Area::BlockStartingAt { bo: tile_bo.0 }); + let plane_ref = rec_region.as_const(); + + let satd = get_satd( + &plane_org, + &plane_ref, + bsize.width(), + bsize.height(), + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + satds.push(satd); + } else { + satds.push(0); + } + }); + + let mut sorted = + izip!(inter_mode_set, mvs_set, satds).collect::>(); + if num_modes_rdo != sorted.len() { + sorted.sort_by_key(|((_mode, _i), _mvs, satd)| *satd); + } + + sorted.iter().take(num_modes_rdo).for_each( + |&((luma_mode, i), mvs, _satd)| { + let mode_set_chroma = ArrayVec::from([luma_mode]); + + luma_chroma_mode_rdo( + luma_mode, + fi, + bsize, + tile_bo, + ts, + cw, + rdo_type, + cw_checkpoint, + &mut best, + mvs, + ref_frames_set[i], + &mode_set_chroma, + false, + mode_contexts[i], + &mv_stacks[i], + AngleDelta::default(), + ); + }, + ); + + best +} + +#[profiling::function] +fn intra_frame_rdo_mode_decision( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, bsize: BlockSize, tile_bo: TileBlockOffset, + cw_checkpoint: &ContextWriterCheckpoint, rdo_type: RDOType, + mut best: PartitionParameters, is_chroma_block: bool, +) -> PartitionParameters { + let mut modes = ArrayVec::<_, INTRA_MODES>::new(); + + // Reduce number of prediction modes at higher speed levels + let num_modes_rdo = if (fi.frame_type == FrameType::KEY + && fi.config.speed_settings.prediction.prediction_modes + >= PredictionModesSetting::ComplexKeyframes) + || (fi.frame_type.has_inter() + && fi.config.speed_settings.prediction.prediction_modes + >= PredictionModesSetting::ComplexAll) + { + 7 + } else { + 3 + }; + + let intra_mode_set = RAV1E_INTRA_MODES; + + // Find mode with lowest rate cost + { + use crate::ec::cdf_to_pdf; + + let probs_all = cdf_to_pdf(if fi.frame_type.has_inter() { + cw.get_cdf_intra_mode(bsize) + } else { + cw.get_cdf_intra_mode_kf(tile_bo) + }); + + modes.try_extend_from_slice(intra_mode_set).unwrap(); + modes.sort_by_key(|&a| !probs_all[a as usize]); + } + + // If tx partition (i.e. fi.tx_mode_select) is enabled, the below intra prediction screening + // may be improved by emulating prediction for each tx block. + { + let satds = { + // FIXME: If tx partition is used, this whole sads block should be fixed + let tx_size = bsize.tx_size(); + let mut edge_buf = Aligned::uninit_array(); + let edge_buf = { + let rec = &ts.rec.planes[0].as_const(); + let po = tile_bo.plane_offset(rec.plane_cfg); + // FIXME: If tx partition is used, get_intra_edges() should be called for each tx block + get_intra_edges( + &mut edge_buf, + rec, + tile_bo, + 0, + 0, + bsize, + po, + tx_size, + fi.sequence.bit_depth, + None, + fi.sequence.enable_intra_edge_filter, + IntraParam::None, + ) + }; + + let ief_params = if fi.sequence.enable_intra_edge_filter { + let above_block_info = ts.above_block_info(tile_bo, 0, 0); + let left_block_info = ts.left_block_info(tile_bo, 0, 0); + Some(IntraEdgeFilterParameters::new( + 0, + above_block_info, + left_block_info, + )) + } else { + None + }; + + let mut satds_all = [0; INTRA_MODES]; + for &luma_mode in modes.iter().skip(num_modes_rdo / 2) { + let tile_rect = ts.tile_rect(); + let rec = &mut ts.rec.planes[0]; + let mut rec_region = + rec.subregion_mut(Area::BlockStartingAt { bo: tile_bo.0 }); + // FIXME: If tx partition is used, luma_mode.predict_intra() should be called for each tx block + luma_mode.predict_intra( + tile_rect, + &mut rec_region, + tx_size, + fi.sequence.bit_depth, + &[0i16; 2], + IntraParam::None, + if luma_mode.is_directional() { ief_params } else { None }, + &edge_buf, + fi.cpu_feature_level, + ); + + let plane_org = ts.input_tile.planes[0] + .subregion(Area::BlockStartingAt { bo: tile_bo.0 }); + let plane_ref = rec_region.as_const(); + + satds_all[luma_mode as usize] = get_satd( + &plane_org, + &plane_ref, + tx_size.width(), + tx_size.height(), + fi.sequence.bit_depth, + fi.cpu_feature_level, + ); + } + satds_all + }; + + modes[num_modes_rdo / 2..].sort_by_key(|&a| satds[a as usize]); + } + + debug_assert!(num_modes_rdo >= 1); + + modes.iter().take(num_modes_rdo).for_each(|&luma_mode| { + let mvs = [MotionVector::default(); 2]; + let ref_frames = [INTRA_FRAME, NONE_FRAME]; + let mut mode_set_chroma = ArrayVec::<_, 2>::new(); + mode_set_chroma.push(luma_mode); + if is_chroma_block && luma_mode != PredictionMode::DC_PRED { + mode_set_chroma.push(PredictionMode::DC_PRED); + } + luma_chroma_mode_rdo( + luma_mode, + fi, + bsize, + tile_bo, + ts, + cw, + rdo_type, + cw_checkpoint, + &mut best, + mvs, + ref_frames, + &mode_set_chroma, + true, + 0, + &ArrayVec::::new(), + AngleDelta::default(), + ); + }); + + if fi.config.speed_settings.prediction.fine_directional_intra + && bsize >= BlockSize::BLOCK_8X8 + { + // Find the best angle delta for the current best prediction mode + let luma_deltas = best.pred_mode_luma.angle_delta_count(); + let chroma_deltas = best.pred_mode_chroma.angle_delta_count(); + + let mvs = [MotionVector::default(); 2]; + let ref_frames = [INTRA_FRAME, NONE_FRAME]; + let mode_set_chroma = [best.pred_mode_chroma]; + let mv_stack = ArrayVec::<_, 9>::new(); + let mut best_angle_delta = best.angle_delta; + let mut angle_delta_rdo = |y, uv| -> AngleDelta { + if best.angle_delta.y != y || best.angle_delta.uv != uv { + luma_chroma_mode_rdo( + best.pred_mode_luma, + fi, + bsize, + tile_bo, + ts, + cw, + rdo_type, + cw_checkpoint, + &mut best, + mvs, + ref_frames, + &mode_set_chroma, + true, + 0, + &mv_stack, + AngleDelta { y, uv }, + ); + } + best.angle_delta + }; + + for i in 0..luma_deltas { + let angle_delta_y = + if luma_deltas == 1 { 0 } else { i - MAX_ANGLE_DELTA as i8 }; + best_angle_delta = angle_delta_rdo(angle_delta_y, best_angle_delta.uv); + } + for j in 0..chroma_deltas { + let angle_delta_uv = + if chroma_deltas == 1 { 0 } else { j - MAX_ANGLE_DELTA as i8 }; + best_angle_delta = angle_delta_rdo(best_angle_delta.y, angle_delta_uv); + } + } + + best +} + +/// # Panics +/// +/// - If the block size is invalid for subsampling. +#[profiling::function] +pub fn rdo_cfl_alpha( + ts: &mut TileStateMut<'_, T>, tile_bo: TileBlockOffset, bsize: BlockSize, + luma_tx_size: TxSize, fi: &FrameInvariants, +) -> Option { + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let uv_tx_size = bsize.largest_chroma_tx_size(xdec, ydec); + debug_assert!( + bsize.subsampled_size(xdec, ydec).unwrap() == uv_tx_size.block_size() + ); + + let frame_bo = ts.to_frame_block_offset(tile_bo); + let (visible_tx_w, visible_tx_h) = clip_visible_bsize( + (fi.width + xdec) >> xdec, + (fi.height + ydec) >> ydec, + uv_tx_size.block_size(), + (frame_bo.0.x << MI_SIZE_LOG2) >> xdec, + (frame_bo.0.y << MI_SIZE_LOG2) >> ydec, + ); + + if visible_tx_w == 0 || visible_tx_h == 0 { + return None; + }; + let mut ac = Aligned::<[MaybeUninit; 32 * 32]>::uninit_array(); + let ac = luma_ac(&mut ac.data, ts, tile_bo, bsize, luma_tx_size, fi); + let best_alpha: ArrayVec = (1..3) + .map(|p| { + let &PlaneConfig { xdec, ydec, .. } = ts.rec.planes[p].plane_cfg; + let tile_rect = ts.tile_rect().decimated(xdec, ydec); + let rec = &mut ts.rec.planes[p]; + let input = &ts.input_tile.planes[p]; + let po = tile_bo.plane_offset(rec.plane_cfg); + let mut edge_buf = Aligned::uninit_array(); + let edge_buf = get_intra_edges( + &mut edge_buf, + &rec.as_const(), + tile_bo, + 0, + 0, + bsize, + po, + uv_tx_size, + fi.sequence.bit_depth, + Some(PredictionMode::UV_CFL_PRED), + fi.sequence.enable_intra_edge_filter, + IntraParam::None, + ); + let mut alpha_cost = |alpha: i16| -> u64 { + let mut rec_region = + rec.subregion_mut(Area::BlockStartingAt { bo: tile_bo.0 }); + PredictionMode::UV_CFL_PRED.predict_intra( + tile_rect, + &mut rec_region, + uv_tx_size, + fi.sequence.bit_depth, + ac, + IntraParam::Alpha(alpha), + None, + &edge_buf, + fi.cpu_feature_level, + ); + sse_wxh( + &input.subregion(Area::BlockStartingAt { bo: tile_bo.0 }), + &rec_region.as_const(), + visible_tx_w, + visible_tx_h, + |_, _| DistortionScale::default(), // We're not doing RDO here. + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) + .0 + }; + let mut best = (alpha_cost(0), 0); + let mut count = 2; + for alpha in 1i16..=16i16 { + let cost = (alpha_cost(alpha), alpha_cost(-alpha)); + if cost.0 < best.0 { + best = (cost.0, alpha); + count += 2; + } + if cost.1 < best.0 { + best = (cost.1, -alpha); + count += 2; + } + if count < alpha { + break; + } + } + best.1 + }) + .collect(); + + if best_alpha[0] == 0 && best_alpha[1] == 0 { + None + } else { + Some(CFLParams::from_alpha(best_alpha[0], best_alpha[1])) + } +} + +/// RDO-based transform type decision +/// If `cw_checkpoint` is `None`, a checkpoint for cw's (`ContextWriter`) current +/// state is created and stored for later use. +/// +/// # Panics +/// +/// - If a writer checkpoint is never created before or within the function. +/// This should never happen and indicates a development error. +/// - If the best RD found is negative. +/// This should never happen and indicates a development error. +pub fn rdo_tx_type_decision( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, cw_checkpoint: &mut Option, + mode: PredictionMode, ref_frames: [RefType; 2], mvs: [MotionVector; 2], + bsize: BlockSize, tile_bo: TileBlockOffset, tx_size: TxSize, tx_set: TxSet, + tx_types: &[TxType], cur_best_rd: f64, +) -> (TxType, f64) { + let mut best_type = TxType::DCT_DCT; + let mut best_rd = f64::MAX; + + let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg; + let is_chroma_block = + has_chroma(tile_bo, bsize, xdec, ydec, fi.sequence.chroma_sampling); + + let is_inter = !mode.is_intra(); + + if cw_checkpoint.is_none() { + // Only run the first call + // Prevents creating multiple checkpoints for own version of cw + *cw_checkpoint = + Some(cw.checkpoint(&tile_bo, fi.sequence.chroma_sampling)); + } + + let rdo_type = if fi.use_tx_domain_distortion { + RDOType::TxDistRealRate + } else { + RDOType::PixelDistRealRate + }; + let need_recon_pixel = tx_size.block_size() != bsize && !is_inter; + + let mut first_iteration = true; + for &tx_type in tx_types { + // Skip unsupported transform types + if av1_tx_used[tx_set as usize][tx_type as usize] == 0 { + continue; + } + + if is_inter { + motion_compensate( + fi, ts, cw, mode, ref_frames, mvs, bsize, tile_bo, true, + ); + } + + let mut wr = WriterCounter::new(); + let tell = wr.tell_frac(); + let (_, tx_dist) = if is_inter { + write_tx_tree( + fi, + ts, + cw, + &mut wr, + mode, + 0, + tile_bo, + bsize, + tx_size, + tx_type, + false, + true, + rdo_type, + need_recon_pixel, + ) + } else { + write_tx_blocks( + fi, + ts, + cw, + &mut wr, + mode, + mode, + AngleDelta::default(), + tile_bo, + bsize, + tx_size, + tx_type, + false, + CFLParams::default(), // Unused. + true, + rdo_type, + need_recon_pixel, + ) + }; + + let rate = wr.tell_frac() - tell; + let distortion = if fi.use_tx_domain_distortion { + compute_tx_distortion( + fi, + ts, + bsize, + is_chroma_block, + tile_bo, + tx_dist, + false, + true, + ) + } else { + compute_distortion(fi, ts, bsize, is_chroma_block, tile_bo, true) + }; + cw.rollback(cw_checkpoint.as_ref().unwrap()); + + let rd = compute_rd_cost(fi, rate, distortion); + + if first_iteration { + // We use an optimization to early exit after testing the first + // transform type if the cost is higher than the existing best. + // The idea is that if this transform size is not better than he + // previous size, it is not worth testing remaining modes for this size. + if rd > cur_best_rd { + break; + } + first_iteration = false; + } + + if rd < best_rd { + best_rd = rd; + best_type = tx_type; + } + } + + assert!(best_rd >= 0_f64); + + (best_type, best_rd) +} + +pub fn get_sub_partitions( + four_partitions: &[TileBlockOffset; 4], partition: PartitionType, +) -> ArrayVec { + let mut partition_offsets = ArrayVec::::new(); + + partition_offsets.push(four_partitions[0]); + + if partition == PARTITION_NONE { + return partition_offsets; + } + if partition == PARTITION_VERT || partition == PARTITION_SPLIT { + partition_offsets.push(four_partitions[1]); + }; + if partition == PARTITION_HORZ || partition == PARTITION_SPLIT { + partition_offsets.push(four_partitions[2]); + }; + if partition == PARTITION_SPLIT { + partition_offsets.push(four_partitions[3]); + }; + + partition_offsets +} + +#[inline(always)] +fn rdo_partition_none( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, bsize: BlockSize, tile_bo: TileBlockOffset, + inter_cfg: &InterConfig, child_modes: &mut ArrayVec, +) -> f64 { + debug_assert!(tile_bo.0.x < ts.mi_width && tile_bo.0.y < ts.mi_height); + + let mode = rdo_mode_decision(fi, ts, cw, bsize, tile_bo, inter_cfg); + let cost = mode.rd_cost; + + child_modes.push(mode); + + cost +} + +// VERTICAL, HORIZONTAL or simple SPLIT +#[inline(always)] +fn rdo_partition_simple( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w_pre_cdef: &mut W, w_post_cdef: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, inter_cfg: &InterConfig, + partition: PartitionType, rdo_type: RDOType, best_rd: f64, + child_modes: &mut ArrayVec, +) -> Option { + debug_assert!(tile_bo.0.x < ts.mi_width && tile_bo.0.y < ts.mi_height); + let subsize = bsize.subsize(partition).unwrap(); + + let cost = if bsize >= BlockSize::BLOCK_8X8 { + let w: &mut W = if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + let tell = w.tell_frac(); + cw.write_partition(w, tile_bo, partition, bsize); + compute_rd_cost(fi, w.tell_frac() - tell, ScaledDistortion::zero()) + } else { + 0.0 + }; + + let hbsw = subsize.width_mi(); // Half the block size width in blocks + let hbsh = subsize.height_mi(); // Half the block size height in blocks + let four_partitions = [ + tile_bo, + TileBlockOffset(BlockOffset { x: tile_bo.0.x + hbsw, y: tile_bo.0.y }), + TileBlockOffset(BlockOffset { x: tile_bo.0.x, y: tile_bo.0.y + hbsh }), + TileBlockOffset(BlockOffset { + x: tile_bo.0.x + hbsw, + y: tile_bo.0.y + hbsh, + }), + ]; + + let partitions = get_sub_partitions(&four_partitions, partition); + + let mut rd_cost_sum = 0.0; + + for offset in partitions { + let hbs = subsize.width_mi() >> 1; + let has_cols = offset.0.x + hbs < ts.mi_width; + let has_rows = offset.0.y + hbs < ts.mi_height; + + if has_cols && has_rows { + let mode_decision = + rdo_mode_decision(fi, ts, cw, subsize, offset, inter_cfg); + + rd_cost_sum += mode_decision.rd_cost; + + if fi.enable_early_exit && rd_cost_sum > best_rd { + return None; + } + if subsize >= BlockSize::BLOCK_8X8 && subsize.is_sqr() { + let w: &mut W = + if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef }; + cw.write_partition(w, offset, PartitionType::PARTITION_NONE, subsize); + } + encode_block_with_modes( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + subsize, + offset, + &mode_decision, + rdo_type, + None, + ); + child_modes.push(mode_decision); + } else { + //rd_cost_sum += f64::MAX; + return None; + } + } + + Some(cost + rd_cost_sum) +} + +/// RDO-based single level partitioning decision +/// +/// # Panics +/// +/// - If the best RD found is negative. +/// This should never happen, and indicates a development error. +#[profiling::function] +pub fn rdo_partition_decision( + fi: &FrameInvariants, ts: &mut TileStateMut<'_, T>, + cw: &mut ContextWriter, w_pre_cdef: &mut W, w_post_cdef: &mut W, + bsize: BlockSize, tile_bo: TileBlockOffset, + cached_block: &PartitionGroupParameters, partition_types: &[PartitionType], + rdo_type: RDOType, inter_cfg: &InterConfig, +) -> PartitionGroupParameters { + let mut best_partition = cached_block.part_type; + let mut best_rd = cached_block.rd_cost; + let mut best_pred_modes = cached_block.part_modes.clone(); + + let cw_checkpoint = cw.checkpoint(&tile_bo, fi.sequence.chroma_sampling); + let w_pre_checkpoint = w_pre_cdef.checkpoint(); + let w_post_checkpoint = w_post_cdef.checkpoint(); + + for &partition in partition_types { + // Do not re-encode results we already have + if partition == cached_block.part_type { + continue; + } + + let mut child_modes = ArrayVec::<_, 4>::new(); + + let cost = match partition { + PARTITION_NONE if bsize <= BlockSize::BLOCK_64X64 => { + Some(rdo_partition_none( + fi, + ts, + cw, + bsize, + tile_bo, + inter_cfg, + &mut child_modes, + )) + } + PARTITION_SPLIT | PARTITION_HORZ | PARTITION_VERT => { + rdo_partition_simple( + fi, + ts, + cw, + w_pre_cdef, + w_post_cdef, + bsize, + tile_bo, + inter_cfg, + partition, + rdo_type, + best_rd, + &mut child_modes, + ) + } + _ => { + unreachable!(); + } + }; + + if let Some(rd) = cost { + if rd < best_rd { + best_rd = rd; + best_partition = partition; + best_pred_modes.clone_from(&child_modes); + } + } + cw.rollback(&cw_checkpoint); + w_pre_cdef.rollback(&w_pre_checkpoint); + w_post_cdef.rollback(&w_post_checkpoint); + } + + assert!(best_rd >= 0_f64); + + PartitionGroupParameters { + rd_cost: best_rd, + part_type: best_partition, + part_modes: best_pred_modes, + } +} + +#[profiling::function] +fn rdo_loop_plane_error( + base_sbo: TileSuperBlockOffset, offset_sbo: TileSuperBlockOffset, + sb_w: usize, sb_h: usize, fi: &FrameInvariants, ts: &TileStateMut<'_, T>, + blocks: &TileBlocks<'_>, test: &Frame, src: &Tile<'_, T>, pli: usize, +) -> ScaledDistortion { + let sb_w_blocks = + if fi.sequence.use_128x128_superblock { 16 } else { 8 } * sb_w; + let sb_h_blocks = + if fi.sequence.use_128x128_superblock { 16 } else { 8 } * sb_h; + // Each direction block is 8x8 in y, potentially smaller if subsampled in chroma + // accumulating in-frame and unpadded + let mut err = Distortion::zero(); + for by in 0..sb_h_blocks { + for bx in 0..sb_w_blocks { + let loop_bo = offset_sbo.block_offset(bx << 1, by << 1); + if loop_bo.0.x < blocks.cols() && loop_bo.0.y < blocks.rows() { + let src_plane = &src.planes[pli]; + let test_plane = &test.planes[pli]; + let PlaneConfig { xdec, ydec, .. } = *src_plane.plane_cfg; + debug_assert_eq!(xdec, test_plane.cfg.xdec); + debug_assert_eq!(ydec, test_plane.cfg.ydec); + + // Unfortunately, our distortion biases are only available via + // Frame-absolute addressing, so we need a block offset + // relative to the full frame origin (not the tile or analysis + // area) + let frame_bo = (base_sbo + offset_sbo).block_offset(bx << 1, by << 1); + let bias = distortion_scale( + fi, + ts.to_frame_block_offset(frame_bo), + BlockSize::BLOCK_8X8, + ); + + let src_region = + src_plane.subregion(Area::BlockStartingAt { bo: loop_bo.0 }); + let test_region = + test_plane.region(Area::BlockStartingAt { bo: loop_bo.0 }); + + err += if pli == 0 { + // For loop filters, We intentionally use cdef_dist even with + // `--tune Psnr`. Using SSE instead gives no PSNR gain but has a + // significant negative impact on other metrics and visual quality. + RawDistortion(cdef_dist_kernel( + &src_region, + &test_region, + 8, + 8, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) as u64) + * bias + } else { + sse_wxh( + &src_region, + &test_region, + 8 >> xdec, + 8 >> ydec, + |_, _| bias, + fi.sequence.bit_depth, + fi.cpu_feature_level, + ) + }; + } + } + } + err * fi.dist_scale[pli] +} + +/// Passed in a superblock offset representing the upper left corner of +/// the LRU area we're optimizing. This area covers the largest LRU in +/// any of the present planes, but may consist of a number of +/// superblocks and full, smaller LRUs in the other planes +/// +/// # Panics +/// +/// - If both CDEF and LRF are disabled. +#[profiling::function] +pub fn rdo_loop_decision( + base_sbo: TileSuperBlockOffset, fi: &FrameInvariants, + ts: &mut TileStateMut<'_, T>, cw: &mut ContextWriter, w: &mut W, + deblock_p: bool, +) { + let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { + 1 + } else { + MAX_PLANES + }; + assert!(fi.sequence.enable_cdef || fi.sequence.enable_restoration); + // Determine area of optimization: Which plane has the largest LRUs? + // How many LRUs for each? + let mut sb_w = 1; // how many superblocks wide the largest LRU + // is/how many SBs we're processing (same thing) + let mut sb_h = 1; // how many superblocks wide the largest LRU + // is/how many SBs we're processing (same thing) + let mut lru_w = [0; MAX_PLANES]; // how many LRUs we're processing + let mut lru_h = [0; MAX_PLANES]; // how many LRUs we're processing + for pli in 0..planes { + let sb_h_shift = ts.restoration.planes[pli].rp_cfg.sb_h_shift; + let sb_v_shift = ts.restoration.planes[pli].rp_cfg.sb_v_shift; + if sb_w < (1 << sb_h_shift) { + sb_w = 1 << sb_h_shift; + } + if sb_h < (1 << sb_v_shift) { + sb_h = 1 << sb_v_shift; + } + } + for pli in 0..planes { + let sb_h_shift = ts.restoration.planes[pli].rp_cfg.sb_h_shift; + let sb_v_shift = ts.restoration.planes[pli].rp_cfg.sb_v_shift; + lru_w[pli] = sb_w / (1 << sb_h_shift); + lru_h[pli] = sb_h / (1 << sb_v_shift); + } + + // The superblock width/height determinations may be calling for us + // to compute over superblocks that do not actually exist in the + // frame (off the right or lower edge). Trim sb width/height down + // to actual superblocks. Note that these last superblocks on the + // right/bottom may themselves still span the edge of the frame, but + // they do hold at least some visible pixels. + sb_w = sb_w.min(ts.sb_width - base_sbo.0.x); + sb_h = sb_h.min(ts.sb_height - base_sbo.0.y); + + // We have need to know the Y visible pixel limits as well (the + // sb_w/sb_h figures above can be used to determine how many + // allocated pixels, possibly beyond the visible frame, exist). + let crop_w = + fi.width - ((ts.sbo.0.x + base_sbo.0.x) << SUPERBLOCK_TO_PLANE_SHIFT); + let crop_h = + fi.height - ((ts.sbo.0.y + base_sbo.0.y) << SUPERBLOCK_TO_PLANE_SHIFT); + let pixel_w = crop_w.min(sb_w << SUPERBLOCK_TO_PLANE_SHIFT); + let pixel_h = crop_h.min(sb_h << SUPERBLOCK_TO_PLANE_SHIFT); + + // Based on `RestorationState::new` + const MAX_SB_SHIFT: usize = 4; + const MAX_SB_SIZE: usize = 1 << MAX_SB_SHIFT; + const MAX_LRU_SIZE: usize = MAX_SB_SIZE; + + // Static allocation relies on the "minimal LRU area for all N planes" invariant. + let mut best_index = [-1; MAX_SB_SIZE * MAX_SB_SIZE]; + let mut best_lrf = + [[RestorationFilter::None; MAX_PLANES]; MAX_LRU_SIZE * MAX_LRU_SIZE]; + + // due to imprecision in the reconstruction parameter solver, we + // need to make sure we don't fall into a limit cycle. Track our + // best cost at LRF so that we can break if we get a solution that doesn't + // improve at the reconstruction stage. + let mut best_lrf_cost = [[-1.0; MAX_PLANES]; MAX_LRU_SIZE * MAX_LRU_SIZE]; + + // sub-setted region of the TileBlocks for our working frame area. + // Note that the size of this subset is what signals CDEF as to the + // actual coded size. + let mut tileblocks_subset = cw.bc.blocks.subregion_mut( + base_sbo.block_offset(0, 0).0.x, + base_sbo.block_offset(0, 0).0.y, + sb_w << SUPERBLOCK_TO_BLOCK_SHIFT, + sb_h << SUPERBLOCK_TO_BLOCK_SHIFT, + ); + + // cdef doesn't run on superblocks that are completely skipped. + // Determine which super blocks are marked as skipped so we can avoid running + // them. If all blocks are skipped, we can avoid some of the overhead related + // to setting up for cdef. + let mut cdef_skip = [true; MAX_SB_SIZE * MAX_SB_SIZE]; + let mut cdef_skip_all = true; + if fi.sequence.enable_cdef { + for sby in 0..sb_h { + for sbx in 0..sb_w { + let blocks = tileblocks_subset.subregion(16 * sbx, 16 * sby, 16, 16); + let mut skip = true; + for y in 0..blocks.rows() { + for block in blocks[y].iter() { + skip &= block.skip; + } + } + cdef_skip[sby * MAX_SB_SIZE + sbx] = skip; + cdef_skip_all &= skip; + } + } + } + + // Unlike cdef, loop restoration will run regardless of whether blocks are + // skipped or not. At the same time, the most significant improvement will + // generally be from un-skipped blocks, so lru is only performed if there are + // un-skipped blocks. + // This should be the same as `cdef_skip_all`, except when cdef is disabled. + let mut lru_skip_all = true; + let mut lru_skip = [[true; MAX_PLANES]; MAX_LRU_SIZE * MAX_LRU_SIZE]; + if fi.sequence.enable_restoration { + if fi.config.speed_settings.lru_on_skip { + lru_skip_all = false; + lru_skip = [[false; MAX_PLANES]; MAX_LRU_SIZE * MAX_LRU_SIZE]; + } else { + for pli in 0..planes { + // width, in sb, of an LRU in this plane + let lru_sb_w = 1 << ts.restoration.planes[pli].rp_cfg.sb_h_shift; + // height, in sb, of an LRU in this plane + let lru_sb_h = 1 << ts.restoration.planes[pli].rp_cfg.sb_v_shift; + for lru_y in 0..lru_h[pli] { + // number of LRUs vertically + for lru_x in 0..lru_w[pli] { + // number of LRUs horizontally + + let loop_sbo = TileSuperBlockOffset(SuperBlockOffset { + x: lru_x * lru_sb_w, + y: lru_y * lru_sb_h, + }); + + if !ts.restoration.has_restoration_unit( + base_sbo + loop_sbo, + pli, + false, + ) { + continue; + } + + let start = loop_sbo.block_offset(0, 0).0; + let size = TileSuperBlockOffset(SuperBlockOffset { + x: lru_sb_w, + y: lru_sb_h, + }) + .block_offset(0, 0) + .0; + + let blocks = + tileblocks_subset.subregion(start.x, start.y, size.x, size.y); + let mut skip = true; + for y in 0..blocks.rows() { + for block in blocks[y].iter() { + skip &= block.skip; + } + } + lru_skip[lru_y * MAX_LRU_SIZE + lru_x][pli] = skip; + lru_skip_all &= skip; + } + } + } + } + } + + // Return early if all blocks are skipped for lru and cdef. + if lru_skip_all && cdef_skip_all { + return; + } + + // Loop filter RDO is an iterative process and we need temporary + // scratch data to hold the results of deblocking, cdef, and the + // loop reconstruction filter so that each can be partially updated + // without recomputing the entire stack. Construct + // largest-LRU-sized frames for each, accounting for padding + // required by deblocking, cdef and [optionally] LR. + let mut rec_subset = ts + .rec + .subregion(Area::BlockRect { + bo: base_sbo.block_offset(0, 0).0, + width: (pixel_w + 7) >> 3 << 3, + height: (pixel_h + 7) >> 3 << 3, + }) + .scratch_copy(); + + // const, no need to copy, just need the subregion (but do zero the + // origin to match the other copies/new backing frames). + let src_subset = ts + .input_tile + .subregion(Area::BlockRect { + bo: base_sbo.block_offset(0, 0).0, + width: (pixel_w + 7) >> 3 << 3, + height: (pixel_h + 7) >> 3 << 3, + }) + .home(); + + if deblock_p { + // Find a good deblocking filter solution for the passed in area. + // This is not RDO of deblocking itself, merely a solution to get + // better results from CDEF/LRF RDO. + let deblock_levels = deblock_filter_optimize( + fi, + &rec_subset.as_tile(), + &src_subset, + &tileblocks_subset.as_const(), + crop_w, + crop_h, + ); + + // Deblock the contents of our reconstruction copy. + if deblock_levels[0] != 0 || deblock_levels[1] != 0 { + // copy ts.deblock because we need to set some of our own values here + let mut deblock_copy = *ts.deblock; + deblock_copy.levels = deblock_levels; + + // finally, deblock the temp frame + deblock_filter_frame( + &deblock_copy, + &mut rec_subset.as_tile_mut(), + &tileblocks_subset.as_const(), + crop_w, + crop_h, + fi.sequence.bit_depth, + planes, + ); + } + } + + let mut cdef_work = + if !cdef_skip_all { Some(rec_subset.clone()) } else { None }; + let mut lrf_work = if !lru_skip_all { + Some(Frame { + planes: { + let new_plane = |pli: usize| { + let PlaneConfig { xdec, ydec, width, height, .. } = + rec_subset.planes[pli].cfg; + Plane::new(width, height, xdec, ydec, 0, 0) + }; + [new_plane(0), new_plane(1), new_plane(2)] + }, + }) + } else { + None + }; + + // Precompute directional analysis for CDEF + let cdef_data = { + if cdef_work.is_some() { + Some(( + &rec_subset, + cdef_analyze_superblock_range( + fi, + &rec_subset, + &tileblocks_subset.as_const(), + sb_w, + sb_h, + ), + )) + } else { + None + } + }; + + // CDEF/LRF decision iteration + // Start with a default of CDEF 0 and RestorationFilter::None + // Try all CDEF options for each sb with current LRF; if new CDEF+LRF choice is better, select it. + // Then try all LRF options with current CDEFs; if new CDEFs+LRF choice is better, select it. + // If LRF choice changed for any plane, repeat until no changes + // Limit iterations and where we break based on speed setting (in the TODO list ;-) + let mut cdef_change = true; + let mut lrf_change = true; + while cdef_change || lrf_change { + // search for improved cdef indices, superblock by superblock, if cdef is enabled. + if let (Some((rec_copy, cdef_dirs)), Some(cdef_ref)) = + (&cdef_data, &mut cdef_work.as_mut()) + { + for sby in 0..sb_h { + for sbx in 0..sb_w { + // determine whether this superblock can be skipped + if cdef_skip[sby * MAX_SB_SIZE + sbx] { + continue; + } + + let prev_best_index = best_index[sby * sb_w + sbx]; + let mut best_cost = -1.; + let mut best_new_index = -1i8; + + /* offset of the superblock we're currently testing within the larger + analysis area */ + let loop_sbo = + TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby }); + + /* cdef index testing loop */ + for cdef_index in 0..(1 << fi.cdef_bits) { + let mut err = ScaledDistortion::zero(); + let mut rate = 0; + + cdef_filter_superblock( + fi, + &rec_subset, + &mut cdef_ref.as_tile_mut(), + &tileblocks_subset.as_const(), + loop_sbo, + cdef_index, + &cdef_dirs[sby * sb_w + sbx], + ); + // apply LRF if any + for pli in 0..planes { + // We need the cropped-to-visible-frame area of this SB + let wh = + if fi.sequence.use_128x128_superblock { 128 } else { 64 }; + let PlaneConfig { xdec, ydec, .. } = cdef_ref.planes[pli].cfg; + let vis_width = (wh >> xdec).min( + (crop_w >> xdec) + - loop_sbo.plane_offset(&cdef_ref.planes[pli].cfg).x + as usize, + ); + let vis_height = (wh >> ydec).min( + (crop_h >> ydec) + - loop_sbo.plane_offset(&cdef_ref.planes[pli].cfg).y + as usize, + ); + // which LRU are we currently testing against? + if let (Some((lru_x, lru_y)), Some(lrf_ref)) = { + let rp = &ts.restoration.planes[pli]; + ( + rp.restoration_unit_offset(base_sbo, loop_sbo, false), + &mut lrf_work, + ) + } { + // We have a valid LRU, apply LRF, compute error + match best_lrf[lru_y * lru_w[pli] + lru_x][pli] { + RestorationFilter::None => { + err += rdo_loop_plane_error( + base_sbo, + loop_sbo, + 1, + 1, + fi, + ts, + &tileblocks_subset.as_const(), + cdef_ref, + &src_subset, + pli, + ); + rate += if fi.sequence.enable_restoration { + cw.fc.count_lrf_switchable( + w, + &ts.restoration.as_const(), + best_lrf[lru_y * lru_w[pli] + lru_x][pli], + pli, + ) + } else { + 0 // no relative cost differeneces to different + // CDEF params. If cdef is on, it's a wash. + }; + } + RestorationFilter::Sgrproj { set, xqd } => { + // only run on this single superblock + let loop_po = + loop_sbo.plane_offset(&cdef_ref.planes[pli].cfg); + // todo: experiment with borrowing border pixels + // rather than edge-extending. Right now this is + // hard-clipping to the superblock boundary. + setup_integral_image( + &mut ts.integral_buffer, + SOLVE_IMAGE_STRIDE, + vis_width, + vis_height, + vis_width, + vis_height, + &cdef_ref.planes[pli].slice(loop_po), + &cdef_ref.planes[pli].slice(loop_po), + ); + sgrproj_stripe_filter( + set, + xqd, + fi, + &ts.integral_buffer, + SOLVE_IMAGE_STRIDE, + &cdef_ref.planes[pli].slice(loop_po), + &mut lrf_ref.planes[pli].region_mut(Area::Rect { + x: loop_po.x, + y: loop_po.y, + width: vis_width, + height: vis_height, + }), + ); + err += rdo_loop_plane_error( + base_sbo, + loop_sbo, + 1, + 1, + fi, + ts, + &tileblocks_subset.as_const(), + lrf_ref, + &src_subset, + pli, + ); + rate += cw.fc.count_lrf_switchable( + w, + &ts.restoration.as_const(), + best_lrf[lru_y * lru_w[pli] + lru_x][pli], + pli, + ); + } + RestorationFilter::Wiener { .. } => unreachable!(), // coming soon + } + } else { + // No actual LRU here, compute error directly from CDEF output. + err += rdo_loop_plane_error( + base_sbo, + loop_sbo, + 1, + 1, + fi, + ts, + &tileblocks_subset.as_const(), + cdef_ref, + &src_subset, + pli, + ); + // no relative cost differeneces to different + // CDEF params. If cdef is on, it's a wash. + // rate += 0; + } + } + + let cost = compute_rd_cost(fi, rate, err); + if best_cost < 0. || cost < best_cost { + best_cost = cost; + best_new_index = cdef_index as i8; + } + } + + // Did we change any preexisting choices? + if best_new_index != prev_best_index { + cdef_change = true; + best_index[sby * sb_w + sbx] = best_new_index; + tileblocks_subset.set_cdef(loop_sbo, best_new_index as u8); + } + + let mut cdef_ref_tm = TileMut::new( + cdef_ref, + TileRect { + x: 0, + y: 0, + width: cdef_ref.planes[0].cfg.width, + height: cdef_ref.planes[0].cfg.height, + }, + ); + + // Keep cdef output up to date; we need it for restoration + // both below and above (padding) + cdef_filter_superblock( + fi, + rec_copy, + &mut cdef_ref_tm, + &tileblocks_subset.as_const(), + loop_sbo, + best_index[sby * sb_w + sbx] as u8, + &cdef_dirs[sby * sb_w + sbx], + ); + } + } + } + + if !cdef_change { + break; + } + cdef_change = false; + lrf_change = false; + + // search for improved restoration filter parameters if restoration is enabled + if let Some(lrf_ref) = &mut lrf_work.as_mut() { + let lrf_input = if cdef_work.is_some() { + // When CDEF is enabled, we pull from the CDEF output + cdef_work.as_ref().unwrap() + } else { + // When CDEF is disabled, we pull from the [optionally + // deblocked] reconstruction + &rec_subset + }; + for pli in 0..planes { + // Nominal size of LRU in pixels before clipping to visible frame + let unit_size = ts.restoration.planes[pli].rp_cfg.unit_size; + // width, in sb, of an LRU in this plane + let lru_sb_w = 1 << ts.restoration.planes[pli].rp_cfg.sb_h_shift; + // height, in sb, of an LRU in this plane + let lru_sb_h = 1 << ts.restoration.planes[pli].rp_cfg.sb_v_shift; + let PlaneConfig { xdec, ydec, .. } = lrf_ref.planes[pli].cfg; + for lru_y in 0..lru_h[pli] { + // number of LRUs vertically + for lru_x in 0..lru_w[pli] { + // number of LRUs horizontally + + // determine whether this lru should be skipped + if lru_skip[lru_y * MAX_LRU_SIZE + lru_x][pli] { + continue; + } + + let loop_sbo = TileSuperBlockOffset(SuperBlockOffset { + x: lru_x * lru_sb_w, + y: lru_y * lru_sb_h, + }); + if ts.restoration.has_restoration_unit( + base_sbo + loop_sbo, + pli, + false, + ) { + let src_plane = &src_subset.planes[pli]; // uncompressed input for reference + let lrf_in_plane = &lrf_input.planes[pli]; + let lrf_po = loop_sbo.plane_offset(src_plane.plane_cfg); + let mut best_new_lrf = best_lrf[lru_y * lru_w[pli] + lru_x][pli]; + let mut best_cost = + best_lrf_cost[lru_y * lru_w[pli] + lru_x][pli]; + + // Check the no filter option + { + let err = rdo_loop_plane_error( + base_sbo, + loop_sbo, + lru_sb_w, + lru_sb_h, + fi, + ts, + &tileblocks_subset.as_const(), + lrf_input, + &src_subset, + pli, + ); + let rate = cw.fc.count_lrf_switchable( + w, + &ts.restoration.as_const(), + best_new_lrf, + pli, + ); + + let cost = compute_rd_cost(fi, rate, err); + // Was this choice actually an improvement? + if best_cost < 0. || cost < best_cost { + best_cost = cost; + best_lrf_cost[lru_y * lru_w[pli] + lru_x][pli] = cost; + best_new_lrf = RestorationFilter::None; + } + } + + // Look for a self guided filter + // We need the cropped-to-visible-frame computation area of this LRU + let vis_width = unit_size.min( + (crop_w >> xdec) + - loop_sbo.plane_offset(&lrf_ref.planes[pli].cfg).x as usize, + ); + let vis_height = unit_size.min( + (crop_h >> ydec) + - loop_sbo.plane_offset(&lrf_ref.planes[pli].cfg).y as usize, + ); + + // todo: experiment with borrowing border pixels + // rather than edge-extending. Right now this is + // hard-clipping to the superblock boundary. + setup_integral_image( + &mut ts.integral_buffer, + SOLVE_IMAGE_STRIDE, + vis_width, + vis_height, + vis_width, + vis_height, + &lrf_in_plane.slice(lrf_po), + &lrf_in_plane.slice(lrf_po), + ); + + for &set in get_sgr_sets(fi.config.speed_settings.sgr_complexity) + { + let (xqd0, xqd1) = sgrproj_solve( + set, + fi, + &ts.integral_buffer, + &src_plane + .subregion(Area::StartingAt { x: lrf_po.x, y: lrf_po.y }), + &lrf_in_plane.slice(lrf_po), + vis_width, + vis_height, + ); + let current_lrf = + RestorationFilter::Sgrproj { set, xqd: [xqd0, xqd1] }; + if let RestorationFilter::Sgrproj { set, xqd } = current_lrf { + sgrproj_stripe_filter( + set, + xqd, + fi, + &ts.integral_buffer, + SOLVE_IMAGE_STRIDE, + &lrf_in_plane.slice(lrf_po), + &mut lrf_ref.planes[pli].region_mut(Area::Rect { + x: lrf_po.x, + y: lrf_po.y, + width: vis_width, + height: vis_height, + }), + ); + } + let err = rdo_loop_plane_error( + base_sbo, + loop_sbo, + lru_sb_w, + lru_sb_h, + fi, + ts, + &tileblocks_subset.as_const(), + lrf_ref, + &src_subset, + pli, + ); + let rate = cw.fc.count_lrf_switchable( + w, + &ts.restoration.as_const(), + current_lrf, + pli, + ); + let cost = compute_rd_cost(fi, rate, err); + if cost < best_cost { + best_cost = cost; + best_lrf_cost[lru_y * lru_w[pli] + lru_x][pli] = cost; + best_new_lrf = current_lrf; + } + } + + if best_lrf[lru_y * lru_w[pli] + lru_x][pli] + .notequal(best_new_lrf) + { + best_lrf[lru_y * lru_w[pli] + lru_x][pli] = best_new_lrf; + lrf_change = true; + if let Some(ru) = ts.restoration.planes[pli] + .restoration_unit_mut(base_sbo + loop_sbo) + { + ru.filter = best_new_lrf; + } + } + } + } + } + } + } + } +} + +#[test] +fn estimate_rate_test() { + assert_eq!(estimate_rate(0, TxSize::TX_4X4, 0), RDO_RATE_TABLE[0][0][0]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rdo_tables.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo_tables.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/rdo_tables.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/rdo_tables.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1083 @@ +// Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved +// Copyright (c) 2017-2019, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub const RDO_NUM_BINS: usize = 50; +#[allow(unused)] +pub const RDO_MAX_BIN: usize = 10000; +pub const RATE_EST_MAX_BIN: usize = 100_000; +pub const RDO_QUANT_BINS: usize = 8; +pub const RDO_QUANT_DIV: usize = 256 / RDO_QUANT_BINS; +#[allow(unused)] +pub const RDO_BIN_SIZE: u64 = (RDO_MAX_BIN / RDO_NUM_BINS) as u64; +pub const RATE_EST_BIN_SIZE: u64 = (RATE_EST_MAX_BIN / RDO_NUM_BINS) as u64; + +use crate::transform::TxSize; + +pub static RDO_RATE_TABLE: [[[u64; RDO_NUM_BINS]; TxSize::TX_SIZES_ALL]; + RDO_QUANT_BINS] = [ + [ + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 104, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 707, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 2756, + ], + [ + 13934, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 7628, + ], + [ + 3155, 8704, 12726, 17300, 19395, 20872, 22052, 23156, 24014, 25176, + 26269, 27336, 28359, 28967, 29713, 30205, 30847, 31286, 31776, 32355, + 32826, 33232, 33367, 33741, 34095, 34472, 34726, 35087, 35195, 35531, + 35614, 35728, 35934, 35973, 36165, 36360, 36281, 36651, 36759, 36921, + 37014, 37095, 37188, 37012, 37310, 37255, 37157, 37399, 37753, 41014, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 146, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 1159, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 7612, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 4525, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 56, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 446, + ], + [ + 3456, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 1438, + ], + [ + 5300, 12376, 13413, 21251, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 1449, + ], + [ + 468, 2455, 5285, 8433, 10917, 12155, 13651, 14712, 15475, 16484, 17678, + 18613, 19609, 20313, 20833, 21383, 21834, 22277, 22758, 23300, 23686, + 24012, 24419, 24739, 25112, 25439, 25602, 26011, 26256, 26389, 26539, + 26662, 26827, 26946, 27059, 27145, 27358, 27485, 27510, 27509, 27594, + 27720, 27792, 28033, 28029, 28087, 28285, 28548, 28657, 31616, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 69, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 2627, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 668, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 3957, 6158, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 955, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 26, + ], + [ + 814, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 217, + ], + [ + 1127, 2725, 4344, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 154, + ], + [ + 345, 1365, 2879, 4614, 6905, 9707, 9334, 9812, 11542, 14962, 22525, + 28756, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 717, + ], + [ + 116, 270, 689, 1041, 1618, 2298, 3748, 5051, 5800, 6310, 6909, 7391, + 7745, 8030, 8482, 8996, 9557, 10112, 10633, 11148, 11623, 12152, 12614, + 13089, 13592, 14000, 14425, 14886, 15182, 15630, 15871, 16282, 16506, + 16780, 17018, 17139, 17228, 17411, 17463, 17587, 17723, 17634, 17696, + 17944, 18012, 17950, 18006, 18005, 18182, 22725, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 23, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 873, 2245, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 182, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 519, 1820, 3040, 5457, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 154, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 169, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 15, + ], + [ + 463, 859, 1141, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 76, + ], + [ + 295, 923, 1607, 2072, 2388, 3105, 4419, 5573, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 65, + ], + [ + 112, 343, 674, 1102, 1578, 2089, 2648, 3376, 4342, 4869, 5708, 5918, + 5901, 6998, 8658, 8258, 7166, 7837, 9781, 10973, 10590, 11659, 11882, + 12548, 15440, 19254, 22300, 24169, 25287, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 413, + ], + [ + 60, 105, 217, 365, 586, 798, 1010, 1287, 1563, 1952, 2385, 2825, 3135, + 3158, 3796, 4070, 4377, 4574, 4794, 5032, 5350, 5507, 5762, 5986, 6267, + 6519, 6741, 7016, 7346, 7645, 8040, 8413, 8750, 9012, 9362, 9687, 9982, + 10270, 10558, 10725, 11056, 11204, 11387, 11663, 11752, 11877, 12042, + 12104, 12188, 16345, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 154, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 9, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 327, 950, 1500, 1781, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 78, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 125, 384, 795, 1244, 2031, 2451, 3184, 3711, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 75, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 83, 148, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 7, + ], + [ + 170, 381, 574, 822, 1042, 1186, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 28, + ], + [ + 89, 233, 449, 680, 867, 1082, 1319, 1445, 1725, 1907, 2163, 2432, 2636, + 3171, 3869, 4433, 4818, 5081, 5327, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 29, + ], + [ + 43, 112, 190, 282, 370, 477, 587, 725, 913, 1105, 1315, 1542, 1773, + 1992, 2173, 2337, 2526, 2703, 2884, 3072, 3276, 3472, 3668, 3886, 4168, + 4521, 4923, 5082, 4981, 5031, 5290, 5598, 6069, 6710, 7558, 8505, 9363, + 9523, 8687, 7810, 7479, 7697, 8214, 8970, 9562, 9978, 10067, 9798, 9430, + 843, + ], + [ + 46, 58, 75, 129, 207, 265, 340, 426, 505, 554, 662, 771, 873, 1023, + 1097, 1183, 1270, 1342, 1445, 1561, 1642, 1741, 1852, 1992, 2037, 2170, + 2236, 2339, 2387, 2507, 2713, 2837, 2893, 3108, 3262, 3364, 3466, 3592, + 3758, 3811, 4050, 4191, 4326, 4493, 4607, 4773, 4846, 5055, 5247, 9882, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 81, 155, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 3, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 120, 275, 521, 750, 987, 1167, 1264, 1373, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 55, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 57, 85, 114, 227, 424, 686, 890, 1071, 1436, 1495, 1521, 1956, 2182, + 2247, 2349, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 58, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 22, 47, 62, 81, 106, 116, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 2, + ], + [ + 46, 108, 158, 203, 253, 296, 333, 371, 429, 500, 558, 587, 580, 542, + 505, 502, 529, 554, 590, 612, 632, 645, 678, 684, 687, 735, 716, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 12, + ], + [ + 24, 56, 96, 144, 195, 247, 297, 343, 387, 427, 463, 499, 533, 568, 605, + 642, 685, 739, 806, 872, 904, 929, 982, 1068, 1168, 1238, 1254, 1246, + 1201, 1202, 1257, 1346, 1445, 1572, 1661, 1755, 1851, 1966, 2062, 2201, + 2290, 2405, 2448, 2482, 2488, 2474, 2367, 2270, 2085, 17, + ], + [ + 22, 34, 52, 72, 93, 112, 130, 149, 170, 198, 226, 261, 292, 326, 359, + 395, 427, 464, 507, 553, 605, 655, 716, 757, 804, 856, 902, 944, 987, + 1030, 1064, 1114, 1159, 1192, 1226, 1262, 1308, 1339, 1367, 1395, 1440, + 1470, 1504, 1548, 1568, 1604, 1647, 1680, 1715, 1461, + ], + [ + 40, 42, 47, 54, 72, 98, 111, 130, 148, 159, 182, 200, 231, 246, 285, + 298, 312, 324, 357, 375, 394, 418, 439, 467, 472, 501, 518, 536, 564, + 562, 604, 620, 632, 644, 674, 691, 735, 770, 786, 781, 827, 856, 947, + 939, 993, 1008, 1030, 1092, 1120, 3819, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 11, 38, 44, 35, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 1, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 70, 90, 117, 151, 195, 243, 297, 339, 386, 425, 475, 508, 517, 492, 487, + 494, 510, 499, 524, 617, 599, 652, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 46, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 43, 47, 47, 51, 65, 97, 120, 149, 181, 229, 277, 314, 371, 449, 480, + 499, 435, 616, 671, 604, 596, 586, 679, 832, 927, 876, 960, 923, 1070, + 1101, 1148, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 53, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 4, 11, 16, 18, 24, 30, 39, 46, 56, 58, 51, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 0, + ], + [ + 14, 30, 46, 60, 73, 84, 94, 105, 115, 126, 137, 150, 162, 175, 188, 199, + 207, 213, 217, 226, 235, 251, 263, 284, 301, 319, 336, 351, 363, 373, + 384, 393, 392, 391, 397, 390, 387, 376, 370, 357, 348, 338, 335, 328, + 321, 318, 318, 331, 320, 6, + ], + [ + 6, 13, 21, 31, 43, 55, 67, 79, 91, 103, 114, 125, 135, 145, 156, 164, + 174, 184, 193, 202, 212, 221, 229, 238, 245, 255, 263, 270, 281, 289, + 299, 308, 317, 326, 332, 343, 349, 357, 368, 374, 385, 399, 405, 417, + 425, 439, 452, 469, 480, 30, + ], + [ + 16, 17, 20, 23, 27, 31, 35, 39, 43, 48, 52, 57, 62, 68, 73, 78, 84, 90, + 96, 102, 108, 113, 120, 124, 129, 137, 143, 150, 157, 162, 170, 177, + 186, 195, 201, 207, 221, 225, 233, 244, 248, 259, 270, 274, 283, 292, + 302, 311, 320, 624, + ], + [ + 37, 37, 37, 38, 40, 42, 46, 48, 51, 55, 58, 60, 66, 69, 72, 77, 82, 81, + 86, 89, 93, 97, 98, 102, 107, 114, 116, 119, 128, 132, 130, 135, 137, + 138, 138, 139, 151, 156, 153, 153, 153, 154, 168, 172, 171, 170, 178, + 182, 191, 1284, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 1, 3, 7, 14, 17, 19, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 0, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 47, 52, 58, 63, 69, 73, 79, 84, 88, 94, 101, 106, 114, 124, 136, 141, + 146, 166, 193, 202, 223, 211, 243, 263, 279, 301, 264, 299, 308, 321, + 327, 337, 328, 346, 319, 321, 307, 329, 323, 304, 328, 315, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 33, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 38, 39, 41, 42, 41, 43, 42, 42, 45, 46, 53, 56, 60, 68, 70, 77, 84, 84, + 88, 75, 86, 121, 135, 137, 144, 154, 161, 162, 178, 183, 189, 196, 202, + 245, 286, 295, 251, 270, 265, 242, 242, 233, 182, 326, 183, 447, 294, + 330, 318, 108, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], + [ + [ + 1, 2, 2, 3, 3, 3, 3, 4, 5, 6, 8, 15, 17, 24, 25, 23, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 0, + ], + [ + 9, 16, 22, 26, 30, 34, 38, 42, 46, 49, 53, 55, 58, 61, 64, 66, 69, 71, + 74, 75, 78, 78, 83, 85, 87, 88, 88, 92, 94, 97, 97, 101, 102, 105, 107, + 106, 110, 113, 115, 119, 118, 117, 122, 126, 129, 129, 126, 131, 134, 6, + ], + [ + 3, 5, 6, 9, 11, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 44, 47, 51, 54, + 58, 62, 65, 68, 72, 75, 78, 79, 84, 88, 91, 95, 96, 100, 103, 106, 107, + 110, 111, 117, 119, 119, 122, 125, 127, 130, 132, 134, 138, 140, 21, + ], + [ + 11, 13, 13, 15, 16, 17, 18, 18, 19, 21, 22, 24, 25, 27, 28, 29, 31, 32, + 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 48, 49, 51, 52, + 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 66, 67, 69, 181, + ], + [ + 33, 32, 34, 34, 34, 35, 35, 36, 37, 37, 38, 38, 39, 39, 39, 40, 41, 41, + 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 50, 50, 51, 52, 53, 52, 52, 53, + 55, 55, 56, 56, 58, 58, 58, 59, 60, 60, 58, 59, 61, 393, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 0, 1, 1, 1, 2, 1, 2, 1, 2, 1, 0, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 0, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 40, 44, 47, 49, 50, 51, 52, 52, 51, 52, 53, 55, 55, 57, 57, 57, 59, 60, + 62, 63, 64, 65, 66, 67, 67, 69, 68, 72, 76, 77, 80, 76, 76, 85, 85, 90, + 92, 98, 87, 87, 88, 98, 94, 103, 107, 98, 107, 109, 109, 31, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 36, 37, 38, 38, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 38, 37, 38, 38, + 40, 40, 41, 40, 38, 44, 47, 44, 43, 44, 45, 50, 44, 44, 46, 49, 49, 54, + 58, 56, 64, 63, 62, 60, 54, 54, 59, 59, 65, 57, 60, 78, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + [ + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999, + ], + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/recon_intra.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/recon_intra.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/recon_intra.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/recon_intra.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,450 @@ +// Copyright (c) 2017-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use crate::context::*; +use crate::partition::BlockSize::*; +use crate::partition::*; +use crate::transform::*; + +static has_null: &[u8] = &[]; + +// Tables to store if the top-right reference pixels are available. The flags +// are represented with bits, packed into 8-bit integers. E.g., for the 32x32 +// blocks in a 128x128 superblock, the index of the "o" block is 10 (in raster +// order), so its flag is stored at the 3rd bit of the 2nd entry in the table, +// i.e. (table[10 / 8] >> (10 % 8)) & 1. +// . . . . +// . . . . +// . . o . +// . . . . +#[rustfmt::skip] +static has_tr_4x4: &[u8] = &[ + 255, 255, 255, 255, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 255, 255, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, + 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, +]; + +static has_tr_4x8: &[u8] = &[ + 255, 255, 255, 255, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, + 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, + 119, 119, 255, 255, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, + 119, 119, 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, + 119, 119, 119, 119, +]; + +#[rustfmt::skip] +static has_tr_8x4: &[u8] = &[ + 255, 255, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, + 127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, + 255, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, + 127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, +]; + +#[rustfmt::skip] +static has_tr_8x8: &[u8] = &[ + 255, 255, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85, + 255, 127, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85, +]; +static has_tr_8x16: &[u8] = &[ + 255, 255, 119, 119, 127, 127, 119, 119, 255, 127, 119, 119, 127, 127, 119, + 119, +]; +static has_tr_16x8: &[u8] = + &[255, 0, 85, 0, 119, 0, 85, 0, 127, 0, 85, 0, 119, 0, 85, 0]; +static has_tr_16x16: &[u8] = &[255, 85, 119, 85, 127, 85, 119, 85]; +static has_tr_16x32: &[u8] = &[255, 119, 127, 119]; +static has_tr_32x16: &[u8] = &[15, 5, 7, 5]; +static has_tr_32x32: &[u8] = &[95, 87]; +static has_tr_32x64: &[u8] = &[127]; +static has_tr_64x32: &[u8] = &[19]; +static has_tr_64x64: &[u8] = &[7]; +static has_tr_64x128: &[u8] = &[3]; +static has_tr_128x64: &[u8] = &[1]; +static has_tr_128x128: &[u8] = &[1]; +static has_tr_4x16: &[u8] = &[ + 255, 255, 255, 255, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127, 127, + 127, 255, 255, 255, 127, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127, + 127, 127, +]; +static has_tr_16x4: &[u8] = &[ + 255, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0, 127, 0, 0, 0, 85, 0, + 0, 0, 119, 0, 0, 0, 85, 0, 0, 0, +]; +static has_tr_8x32: &[u8] = &[255, 255, 127, 127, 255, 127, 127, 127]; +static has_tr_32x8: &[u8] = &[15, 0, 5, 0, 7, 0, 5, 0]; +static has_tr_16x64: &[u8] = &[255, 127]; +static has_tr_64x16: &[u8] = &[3, 1]; + +static has_tr_tables: &[&[u8]] = &[ + has_tr_4x4, // 4x4 + has_tr_4x8, // 4x8 + has_tr_8x4, // 8x4 + has_tr_8x8, // 8x8 + has_tr_8x16, // 8x16 + has_tr_16x8, // 16x8 + has_tr_16x16, // 16x16 + has_tr_16x32, // 16x32 + has_tr_32x16, // 32x16 + has_tr_32x32, // 32x32 + has_tr_32x64, // 32x64 + has_tr_64x32, // 64x32 + has_tr_64x64, // 64x64 + has_tr_64x128, // 64x128 + has_tr_128x64, // 128x64 + has_tr_128x128, // 128x128 + has_tr_4x16, // 4x16 + has_tr_16x4, // 16x4 + has_tr_8x32, // 8x32 + has_tr_32x8, // 32x8 + has_tr_16x64, // 16x64 + has_tr_64x16, // 64x16 +]; + +#[rustfmt::skip] +static has_tr_vert_8x8: &[u8] = &[ + 255, 255, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0, + 255, 127, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0, +]; +static has_tr_vert_16x16: &[u8] = &[255, 0, 119, 0, 127, 0, 119, 0]; +static has_tr_vert_32x32: &[u8] = &[15, 7]; +static has_tr_vert_64x64: &[u8] = &[3]; + +// The _vert_* tables are like the ordinary tables above, but describe the +// order we visit square blocks when doing a PARTITION_VERT_A or +// PARTITION_VERT_B. This is the same order as normal except for on the last +// split where we go vertically (TL, BL, TR, BR). We treat the rectangular block +// as a pair of squares, which means that these tables work correctly for both +// mixed vertical partition types. +// +// There are tables for each of the square sizes. Vertical rectangles (like +// BLOCK_16X32) use their respective "non-vert" table +static has_tr_vert_tables: &[&[u8]] = &[ + has_null, // 4X4 + has_tr_4x8, // 4X8 + has_null, // 8X4 + has_tr_vert_8x8, // 8X8 + has_tr_8x16, // 8X16 + has_null, // 16X8 + has_tr_vert_16x16, // 16X16 + has_tr_16x32, // 16X32 + has_null, // 32X16 + has_tr_vert_32x32, // 32X32 + has_tr_32x64, // 32X64 + has_null, // 64X32 + has_tr_vert_64x64, // 64X64 + has_tr_64x128, // 64x128 + has_null, // 128x64 + has_tr_128x128, // 128x128 +]; + +// TODO: Enable the case for PARTITION_VERT_A/B once they can be encoded by rav1e. +pub fn get_has_tr_table( + /*partition: PartitionType, */ bsize: BlockSize, +) -> &'static [u8] { + let ret: &[u8]; + // If this is a mixed vertical partition, look up bsize in orders_vert. + /*if partition == PartitionType::PARTITION_VERT_A || partition == PartitionType::PARTITION_VERT_B { + debug_assert!(bsize < BlockSize::BLOCK_SIZES); + ret = has_tr_vert_tables[bsize as usize]; + } else */ + { + ret = has_tr_tables[bsize as usize]; + } + + //debug_assert!(ret != ptr::has_null()); + + ret +} + +pub fn has_top_right( + bsize: BlockSize, partition_bo: TileBlockOffset, top_available: bool, + right_available: bool, tx_size: TxSize, row_off: usize, col_off: usize, + ss_x: usize, _ss_y: usize, +) -> bool { + if !top_available || !right_available { + return false; + }; + + let bw_unit = bsize.width_mi(); + let plane_bw_unit = (bw_unit >> ss_x).max(1); + let top_right_count_unit = tx_size.width_mi(); + + let mi_col = partition_bo.0.x; + let mi_row = partition_bo.0.y; + + if row_off > 0 { + // Just need to check if enough pixels on the right. + // 128x128 SB is not supported yet by rav1e + if bsize.width() > BLOCK_64X64.width() { + // Special case: For 128x128 blocks, the transform unit whose + // top-right corner is at the center of the block does in fact have + // pixels available at its top-right corner. + if row_off == BLOCK_64X64.height_mi() >> _ss_y + && col_off + top_right_count_unit == BLOCK_64X64.width_mi() >> ss_x + { + return false; + } + let plane_bw_unit_64 = BLOCK_64X64.width_mi() >> ss_x; + let col_off_64 = col_off % plane_bw_unit_64; + return col_off_64 + top_right_count_unit < plane_bw_unit_64; + } + col_off + top_right_count_unit < plane_bw_unit + } else { + // All top-right pixels are in the block above, which is already available. + if col_off + top_right_count_unit < plane_bw_unit { + return true; + }; + + let bw_in_mi_log2 = bsize.width_log2() - MI_SIZE_LOG2; + let bh_in_mi_log2 = bsize.height_log2() - MI_SIZE_LOG2; + let sb_mi_size: usize = 16; // 64x64 + let blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2; + let blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2; + + // Top row of superblock: so top-right pixels are in the top and/or + // top-right superblocks, both of which are already available. + if blk_row_in_sb == 0 { + return true; + }; + + // Rightmost column of superblock (and not the top row): so top-right pixels + // fall in the right superblock, which is not available yet. + if ((blk_col_in_sb + 1) << bw_in_mi_log2) >= sb_mi_size { + return false; + }; + + // General case (neither top row nor rightmost column): check if the + // top-right block is coded before the current block. + let this_blk_index = + (blk_row_in_sb << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) + blk_col_in_sb; + let idx1 = this_blk_index / 8; + let idx2 = this_blk_index % 8; + let has_tr_table: &[u8] = get_has_tr_table(/*partition,*/ bsize); + + ((has_tr_table[idx1] >> idx2) & 1) != 0 + } +} + +// Similar to the has_tr_* tables, but store if the bottom-left reference +// pixels are available. +static has_bl_4x4: &[u8] = &[ + 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, + 16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 1, 0, 84, 85, 85, 85, 16, 17, 17, 17, + 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, + 0, 0, 0, 0, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, + 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 1, 0, 84, 85, 85, 85, 16, + 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84, + 85, 85, 85, 0, 0, 0, 0, +]; +static has_bl_4x8: &[u8] = &[ + 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0, 16, 17, 17, 17, 0, + 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, + 17, 0, 0, 1, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0, +]; +static has_bl_8x4: &[u8] = &[ + 254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254, + 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0, 254, 255, + 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254, 255, 84, + 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0, +]; +static has_bl_8x8: &[u8] = &[ + 84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0, 84, 85, 16, 17, + 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0, +]; +static has_bl_8x16: &[u8] = + &[16, 17, 0, 1, 16, 17, 0, 0, 16, 17, 0, 1, 16, 17, 0, 0]; +static has_bl_16x8: &[u8] = + &[254, 84, 254, 16, 254, 84, 254, 0, 254, 84, 254, 16, 254, 84, 254, 0]; +static has_bl_16x16: &[u8] = &[84, 16, 84, 0, 84, 16, 84, 0]; +static has_bl_16x32: &[u8] = &[16, 0, 16, 0]; +static has_bl_32x16: &[u8] = &[78, 14, 78, 14]; +static has_bl_32x32: &[u8] = &[4, 4]; +static has_bl_32x64: &[u8] = &[0]; +static has_bl_64x32: &[u8] = &[34]; +static has_bl_64x64: &[u8] = &[0]; +static has_bl_64x128: &[u8] = &[0]; +static has_bl_128x64: &[u8] = &[0]; +static has_bl_128x128: &[u8] = &[0]; +static has_bl_4x16: &[u8] = &[ + 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 0, 0, +]; +static has_bl_16x4: &[u8] = &[ + 254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0, + 254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0, +]; +static has_bl_8x32: &[u8] = &[0, 1, 0, 0, 0, 1, 0, 0]; +static has_bl_32x8: &[u8] = &[238, 78, 238, 14, 238, 78, 238, 14]; +static has_bl_16x64: &[u8] = &[0, 0]; +static has_bl_64x16: &[u8] = &[42, 42]; + +static has_bl_tables: &[&[u8]] = &[ + has_bl_4x4, // 4x4 + has_bl_4x8, // 4x8 + has_bl_8x4, // 8x4 + has_bl_8x8, // 8x8 + has_bl_8x16, // 8x16 + has_bl_16x8, // 16x8 + has_bl_16x16, // 16x16 + has_bl_16x32, // 16x32 + has_bl_32x16, // 32x16 + has_bl_32x32, // 32x32 + has_bl_32x64, // 32x64 + has_bl_64x32, // 64x32 + has_bl_64x64, // 64x64 + has_bl_64x128, // 64x128 + has_bl_128x64, // 128x64 + has_bl_128x128, // 128x128 + has_bl_4x16, // 4x16 + has_bl_16x4, // 16x4 + has_bl_8x32, // 8x32 + has_bl_32x8, // 32x8 + has_bl_16x64, // 16x64 + has_bl_64x16, // 64x16 +]; + +#[rustfmt::skip] +static has_bl_vert_8x8: &[u8] = &[ + 254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0, + 254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0, +]; +static has_bl_vert_16x16: &[u8] = &[254, 16, 254, 0, 254, 16, 254, 0]; +static has_bl_vert_32x32: &[u8] = &[14, 14]; +static has_bl_vert_64x64: &[u8] = &[2]; + +// The _vert_* tables are like the ordinary tables above, but describe the +// order we visit square blocks when doing a PARTITION_VERT_A or +// PARTITION_VERT_B. This is the same order as normal except for on the last +// split where we go vertically (TL, BL, TR, BR). We treat the rectangular block +// as a pair of squares, which means that these tables work correctly for both +// mixed vertical partition types. +// +// There are tables for each of the square sizes. Vertical rectangles (like +// BLOCK_16X32) use their respective "non-vert" table +static has_bl_vert_tables: &[&[u8]] = &[ + has_null, // 4x4 + has_bl_4x8, // 4x8 + has_null, // 8x4 + has_bl_vert_8x8, // 8x8 + has_bl_8x16, // 8x16 + has_null, // 16x8 + has_bl_vert_16x16, // 16x16 + has_bl_16x32, // 16x32 + has_null, // 32x16 + has_bl_vert_32x32, // 32x32 + has_bl_32x64, // 32x64 + has_null, // 64x32 + has_bl_vert_64x64, // 64x64 + has_bl_64x128, // 64x128 + has_null, // 128x64 + has_bl_128x128, // 128x128 +]; + +pub fn get_has_bl_table( + /*partition: PartitionType, */ bsize: BlockSize, +) -> &'static [u8] { + let ret: &[u8]; + // If this is a mixed vertical partition, look up bsize in orders_vert. + /*if (partition == PARTITION_VERT_A || partition == PARTITION_VERT_B) { + //assert(bsize < BLOCK_SIZES); + ret = has_bl_vert_tables[bsize as usize]; + } else*/ + { + ret = has_bl_tables[bsize as usize]; + } + //debug_assert!(ret != ptr::has_null()); + ret +} + +pub fn has_bottom_left( + bsize: BlockSize, partition_bo: TileBlockOffset, bottom_available: bool, + left_available: bool, tx_size: TxSize, row_off: usize, col_off: usize, + _ss_x: usize, ss_y: usize, +) -> bool { + if !bottom_available || !left_available { + return false; + }; + + // Special case for 128x* blocks, when col_off is half the block width. + // This is needed because 128x* superblocks are divided into 64x* blocks in + // raster order + // 128x128 SB is not supported yet by rav1e + if bsize.width() > BLOCK_64X64.width() && col_off > 0 { + let plane_bw_unit_64 = BLOCK_64X64.width_mi() >> _ss_x; + let col_off_64 = col_off % plane_bw_unit_64; + if col_off_64 == 0 { + // We are at the left edge of top-right or bottom-right 64x* block. + let plane_bh_unit_64 = BLOCK_64X64.height_mi() >> ss_y; + let row_off_64 = row_off % plane_bh_unit_64; + let plane_bh_unit = (bsize.height_mi() >> ss_y).min(plane_bh_unit_64); + // Check if all bottom-left pixels are in the left 64x* block (which is + // already coded). + return row_off_64 + tx_size.height_mi() < plane_bh_unit; + } + } + + if col_off > 0 { + // Bottom-left pixels are in the bottom-left block, which is not available. + false + } else { + let bh_unit = bsize.height_mi(); + let plane_bh_unit = (bh_unit >> ss_y).max(1); + let bottom_left_count_unit = tx_size.height_mi(); + + let mi_col = partition_bo.0.x; + let mi_row = partition_bo.0.y; + + // All bottom-left pixels are in the left block, which is already available. + if row_off + bottom_left_count_unit < plane_bh_unit { + return true; + }; + + let bw_in_mi_log2 = bsize.width_log2() - MI_SIZE_LOG2; + let bh_in_mi_log2 = bsize.height_log2() - MI_SIZE_LOG2; + let sb_mi_size: usize = 16; // 64x64 + let blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2; + let blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2; + + // Leftmost column of superblock: so bottom-left pixels maybe in the left + // and/or bottom-left superblocks. But only the left superblock is + // available, so check if all required pixels fall in that superblock. + if blk_col_in_sb == 0 { + let blk_start_row_off = blk_row_in_sb << bh_in_mi_log2 >> ss_y; + let row_off_in_sb = blk_start_row_off + row_off; + let sb_height_unit = sb_mi_size >> ss_y; + return row_off_in_sb + bottom_left_count_unit < sb_height_unit; + //return row_off_in_sb + (bottom_left_count_unit << 1) < sb_height_unit; // Don't it need tx height? again? + } + + // Bottom row of superblock (and not the leftmost column): so bottom-left + // pixels fall in the bottom superblock, which is not available yet. + if ((blk_row_in_sb + 1) << bh_in_mi_log2) >= sb_mi_size { + return false; + }; + + // General case (neither leftmost column nor bottom row): check if the + // bottom-left block is coded before the current block. + let this_blk_index = + (blk_row_in_sb << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) + blk_col_in_sb; + let idx1 = this_blk_index / 8; + let idx2 = this_blk_index % 8; + let has_bl_table: &[u8] = get_has_bl_table(/*partition,*/ bsize); + + ((has_bl_table[idx1] >> idx2) & 1) != 0 + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/scan_order.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/scan_order.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/scan_order.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/scan_order.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1321 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +const MAX_NEIGHBORS: usize = 2; + +use crate::transform::*; + +pub struct SCAN_ORDER { + pub scan: &'static [u16], + pub iscan: &'static [u16], +} + +// To stop from having to perform an unnecessary transpose in the forward and +// inverse transforms, the output of the forward transform is transposed in +// relation to how is in the spec. This means that all of our scan orders are +// different from what is found the spec. + +#[rustfmt::skip] +static default_scan_4x4 : [u16; 16] = [ + 0, 4, 1, 2, 5, 8, 12, 9, 6, 3, 7, 10, 13, 14, 11, 15, +]; + +#[rustfmt::skip] +static mrow_scan_4x4 : [u16; 16] = [ + 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, +]; + +#[rustfmt::skip] +static mcol_scan_4x4 : [u16; 16] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +]; + +#[rustfmt::skip] +static default_scan_8x4 : [u16; 32] = [ + 0, 1, 4, 2, 5, 8, 3, 6, 9, 12, 7, 10, 13, 16, 11, 14, + 17, 20, 15, 18, 21, 24, 19, 22, 25, 28, 23, 26, 29, 27, 30, 31, +]; + +#[rustfmt::skip] +static mrow_scan_8x4 : [u16; 32] = [ + 0, 4, 8, 12, 16, 20, 24, 28, 1, 5, 9, 13, 17, 21, 25, 29, + 2, 6, 10, 14, 18, 22, 26, 30, 3, 7, 11, 15, 19, 23, 27, 31, +]; + +#[rustfmt::skip] +static mcol_scan_8x4 : [u16; 32] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +]; + +#[rustfmt::skip] +static default_scan_4x8 : [u16; 32] = [ + 0, 8, 1, 16, 9, 2, 24, 17, 10, 3, 25, 18, 11, 4, 26, 19, + 12, 5, 27, 20, 13, 6, 28, 21, 14, 7, 29, 22, 15, 30, 23, 31, +]; + +#[rustfmt::skip] +static mrow_scan_4x8 : [u16; 32] = [ + 0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27, + 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31, +]; + +#[rustfmt::skip] +static mcol_scan_4x8 : [u16; 32] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +]; + +#[rustfmt::skip] +static default_scan_16x4 : [u16; 64] = [ + 0, 1, 4, 2, 5, 8, 3, 6, 9, 12, 7, 10, 13, 16, 11, 14, + 17, 20, 15, 18, 21, 24, 19, 22, 25, 28, 23, 26, 29, 32, 27, 30, + 33, 36, 31, 34, 37, 40, 35, 38, 41, 44, 39, 42, 45, 48, 43, 46, + 49, 52, 47, 50, 53, 56, 51, 54, 57, 60, 55, 58, 61, 59, 62, 63, +]; + +#[rustfmt::skip] +static default_scan_4x16 : [u16; 64] = [ + 0, 16, 1, 32, 17, 2, 48, 33, 18, 3, 49, 34, 19, 4, 50, 35, + 20, 5, 51, 36, 21, 6, 52, 37, 22, 7, 53, 38, 23, 8, 54, 39, + 24, 9, 55, 40, 25, 10, 56, 41, 26, 11, 57, 42, 27, 12, 58, 43, + 28, 13, 59, 44, 29, 14, 60, 45, 30, 15, 61, 46, 31, 62, 47, 63, +]; + +#[rustfmt::skip] +static mcol_scan_16x4 : [u16; 64] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +]; + +#[rustfmt::skip] +static mcol_scan_4x16 : [u16; 64] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +]; + +#[rustfmt::skip] +static mrow_scan_16x4 : [u16; 64] = [ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, + 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, + 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, + 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, +]; + +#[rustfmt::skip] +static mrow_scan_4x16 : [u16; 64] = [ + 0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, + 4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, + 8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, + 12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63, +]; + +#[rustfmt::skip] +static default_scan_32x8 : [u16; 256] = [ + 0, 1, 8, 2, 9, 16, 3, 10, 17, 24, 4, 11, 18, 25, 32, + 5, 12, 19, 26, 33, 40, 6, 13, 20, 27, 34, 41, 48, 7, 14, + 21, 28, 35, 42, 49, 56, 15, 22, 29, 36, 43, 50, 57, 64, 23, + 30, 37, 44, 51, 58, 65, 72, 31, 38, 45, 52, 59, 66, 73, 80, + 39, 46, 53, 60, 67, 74, 81, 88, 47, 54, 61, 68, 75, 82, 89, + 96, 55, 62, 69, 76, 83, 90, 97, 104, 63, 70, 77, 84, 91, 98, + 105, 112, 71, 78, 85, 92, 99, 106, 113, 120, 79, 86, 93, 100, 107, + 114, 121, 128, 87, 94, 101, 108, 115, 122, 129, 136, 95, 102, 109, 116, + 123, 130, 137, 144, 103, 110, 117, 124, 131, 138, 145, 152, 111, 118, 125, + 132, 139, 146, 153, 160, 119, 126, 133, 140, 147, 154, 161, 168, 127, 134, + 141, 148, 155, 162, 169, 176, 135, 142, 149, 156, 163, 170, 177, 184, 143, + 150, 157, 164, 171, 178, 185, 192, 151, 158, 165, 172, 179, 186, 193, 200, + 159, 166, 173, 180, 187, 194, 201, 208, 167, 174, 181, 188, 195, 202, 209, + 216, 175, 182, 189, 196, 203, 210, 217, 224, 183, 190, 197, 204, 211, 218, + 225, 232, 191, 198, 205, 212, 219, 226, 233, 240, 199, 206, 213, 220, 227, + 234, 241, 248, 207, 214, 221, 228, 235, 242, 249, 215, 222, 229, 236, 243, + 250, 223, 230, 237, 244, 251, 231, 238, 245, 252, 239, 246, 253, 247, 254, + 255, +]; + +#[rustfmt::skip] +static default_scan_8x32 : [u16; 256] = [ + 0, 32, 1, 64, 33, 2, 96, 65, 34, 3, 128, 97, 66, 35, 4, + 160, 129, 98, 67, 36, 5, 192, 161, 130, 99, 68, 37, 6, 224, 193, + 162, 131, 100, 69, 38, 7, 225, 194, 163, 132, 101, 70, 39, 8, 226, + 195, 164, 133, 102, 71, 40, 9, 227, 196, 165, 134, 103, 72, 41, 10, + 228, 197, 166, 135, 104, 73, 42, 11, 229, 198, 167, 136, 105, 74, 43, + 12, 230, 199, 168, 137, 106, 75, 44, 13, 231, 200, 169, 138, 107, 76, + 45, 14, 232, 201, 170, 139, 108, 77, 46, 15, 233, 202, 171, 140, 109, + 78, 47, 16, 234, 203, 172, 141, 110, 79, 48, 17, 235, 204, 173, 142, + 111, 80, 49, 18, 236, 205, 174, 143, 112, 81, 50, 19, 237, 206, 175, + 144, 113, 82, 51, 20, 238, 207, 176, 145, 114, 83, 52, 21, 239, 208, + 177, 146, 115, 84, 53, 22, 240, 209, 178, 147, 116, 85, 54, 23, 241, + 210, 179, 148, 117, 86, 55, 24, 242, 211, 180, 149, 118, 87, 56, 25, + 243, 212, 181, 150, 119, 88, 57, 26, 244, 213, 182, 151, 120, 89, 58, + 27, 245, 214, 183, 152, 121, 90, 59, 28, 246, 215, 184, 153, 122, 91, + 60, 29, 247, 216, 185, 154, 123, 92, 61, 30, 248, 217, 186, 155, 124, + 93, 62, 31, 249, 218, 187, 156, 125, 94, 63, 250, 219, 188, 157, 126, + 95, 251, 220, 189, 158, 127, 252, 221, 190, 159, 253, 222, 191, 254, 223, + 255, +]; + +#[rustfmt::skip] +static mcol_scan_32x8 : [u16; 256] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, +]; + +#[rustfmt::skip] +static mcol_scan_8x32 : [u16; 256] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, +]; + +#[rustfmt::skip] +static mrow_scan_32x8 : [u16; 256] = [ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, + 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, + 240, 248, 1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, + 105, 113, 121, 129, 137, 145, 153, 161, 169, 177, 185, 193, 201, 209, 217, + 225, 233, 241, 249, 2, 10, 18, 26, 34, 42, 50, 58, 66, 74, 82, + 90, 98, 106, 114, 122, 130, 138, 146, 154, 162, 170, 178, 186, 194, 202, + 210, 218, 226, 234, 242, 250, 3, 11, 19, 27, 35, 43, 51, 59, 67, + 75, 83, 91, 99, 107, 115, 123, 131, 139, 147, 155, 163, 171, 179, 187, + 195, 203, 211, 219, 227, 235, 243, 251, 4, 12, 20, 28, 36, 44, 52, + 60, 68, 76, 84, 92, 100, 108, 116, 124, 132, 140, 148, 156, 164, 172, + 180, 188, 196, 204, 212, 220, 228, 236, 244, 252, 5, 13, 21, 29, 37, + 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 149, 157, + 165, 173, 181, 189, 197, 205, 213, 221, 229, 237, 245, 253, 6, 14, 22, + 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 142, + 150, 158, 166, 174, 182, 190, 198, 206, 214, 222, 230, 238, 246, 254, 7, + 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127, + 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247, + 255, +]; + +#[rustfmt::skip] +static mrow_scan_8x32 : [u16; 256] = [ + 0, 32, 64, 96, 128, 160, 192, 224, 1, 33, 65, 97, 129, 161, 193, 225, + 2, 34, 66, 98, 130, 162, 194, 226, 3, 35, 67, 99, 131, 163, 195, 227, + 4, 36, 68, 100, 132, 164, 196, 228, 5, 37, 69, 101, 133, 165, 197, 229, + 6, 38, 70, 102, 134, 166, 198, 230, 7, 39, 71, 103, 135, 167, 199, 231, + 8, 40, 72, 104, 136, 168, 200, 232, 9, 41, 73, 105, 137, 169, 201, 233, + 10, 42, 74, 106, 138, 170, 202, 234, 11, 43, 75, 107, 139, 171, 203, 235, + 12, 44, 76, 108, 140, 172, 204, 236, 13, 45, 77, 109, 141, 173, 205, 237, + 14, 46, 78, 110, 142, 174, 206, 238, 15, 47, 79, 111, 143, 175, 207, 239, + 16, 48, 80, 112, 144, 176, 208, 240, 17, 49, 81, 113, 145, 177, 209, 241, + 18, 50, 82, 114, 146, 178, 210, 242, 19, 51, 83, 115, 147, 179, 211, 243, + 20, 52, 84, 116, 148, 180, 212, 244, 21, 53, 85, 117, 149, 181, 213, 245, + 22, 54, 86, 118, 150, 182, 214, 246, 23, 55, 87, 119, 151, 183, 215, 247, + 24, 56, 88, 120, 152, 184, 216, 248, 25, 57, 89, 121, 153, 185, 217, 249, + 26, 58, 90, 122, 154, 186, 218, 250, 27, 59, 91, 123, 155, 187, 219, 251, + 28, 60, 92, 124, 156, 188, 220, 252, 29, 61, 93, 125, 157, 189, 221, 253, + 30, 62, 94, 126, 158, 190, 222, 254, 31, 63, 95, 127, 159, 191, 223, 255, +]; + +#[rustfmt::skip] +static default_scan_8x8 : [u16; 64] = [ + 0, 8, 1, 2, 9, 16, 24, 17, 10, 3, 4, 11, 18, 25, 32, 40, + 33, 26, 19, 12, 5, 6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35, + 28, 21, 14, 7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30, + 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63, +]; + +#[rustfmt::skip] +static mrow_scan_8x8 : [u16; 64] = [ + 0, 8, 16, 24, 32, 40, 48, 56, 1, 9, 17, 25, 33, 41, 49, 57, + 2, 10, 18, 26, 34, 42, 50, 58, 3, 11, 19, 27, 35, 43, 51, 59, + 4, 12, 20, 28, 36, 44, 52, 60, 5, 13, 21, 29, 37, 45, 53, 61, + 6, 14, 22, 30, 38, 46, 54, 62, 7, 15, 23, 31, 39, 47, 55, 63, +]; + +#[rustfmt::skip] +static mcol_scan_8x8 : [u16; 64] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +]; + +#[rustfmt::skip] +static default_scan_16x8 : [u16; 128] = [ + 0, 1, 8, 2, 9, 16, 3, 10, 17, 24, 4, 11, 18, 25, 32, + 5, 12, 19, 26, 33, 40, 6, 13, 20, 27, 34, 41, 48, 7, 14, + 21, 28, 35, 42, 49, 56, 15, 22, 29, 36, 43, 50, 57, 64, 23, + 30, 37, 44, 51, 58, 65, 72, 31, 38, 45, 52, 59, 66, 73, 80, + 39, 46, 53, 60, 67, 74, 81, 88, 47, 54, 61, 68, 75, 82, 89, + 96, 55, 62, 69, 76, 83, 90, 97, 104, 63, 70, 77, 84, 91, 98, + 105, 112, 71, 78, 85, 92, 99, 106, 113, 120, 79, 86, 93, 100, 107, + 114, 121, 87, 94, 101, 108, 115, 122, 95, 102, 109, 116, 123, 103, 110, + 117, 124, 111, 118, 125, 119, 126, 127, +]; + +#[rustfmt::skip] +static default_scan_8x16 : [u16; 128] = [ + 0, 16, 1, 32, 17, 2, 48, 33, 18, 3, 64, 49, 34, 19, 4, 80, + 65, 50, 35, 20, 5, 96, 81, 66, 51, 36, 21, 6, 112, 97, 82, 67, + 52, 37, 22, 7, 113, 98, 83, 68, 53, 38, 23, 8, 114, 99, 84, 69, + 54, 39, 24, 9, 115, 100, 85, 70, 55, 40, 25, 10, 116, 101, 86, 71, + 56, 41, 26, 11, 117, 102, 87, 72, 57, 42, 27, 12, 118, 103, 88, 73, + 58, 43, 28, 13, 119, 104, 89, 74, 59, 44, 29, 14, 120, 105, 90, 75, + 60, 45, 30, 15, 121, 106, 91, 76, 61, 46, 31, 122, 107, 92, 77, 62, + 47, 123, 108, 93, 78, 63, 124, 109, 94, 79, 125, 110, 95, 126, 111, 127, +]; + +#[rustfmt::skip] +static mrow_scan_16x8 : [u16; 128] = [ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, + 1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121, + 2, 10, 18, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, 122, + 3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123, + 4, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, + 5, 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, + 6, 14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, + 7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127, +]; + +#[rustfmt::skip] +static mrow_scan_8x16 : [u16; 128] = [ + 0, 16, 32, 48, 64, 80, 96, 112, 1, 17, 33, 49, 65, 81, 97, 113, + 2, 18, 34, 50, 66, 82, 98, 114, 3, 19, 35, 51, 67, 83, 99, 115, + 4, 20, 36, 52, 68, 84, 100, 116, 5, 21, 37, 53, 69, 85, 101, 117, + 6, 22, 38, 54, 70, 86, 102, 118, 7, 23, 39, 55, 71, 87, 103, 119, + 8, 24, 40, 56, 72, 88, 104, 120, 9, 25, 41, 57, 73, 89, 105, 121, + 10, 26, 42, 58, 74, 90, 106, 122, 11, 27, 43, 59, 75, 91, 107, 123, + 12, 28, 44, 60, 76, 92, 108, 124, 13, 29, 45, 61, 77, 93, 109, 125, + 14, 30, 46, 62, 78, 94, 110, 126, 15, 31, 47, 63, 79, 95, 111, 127, +]; + +#[rustfmt::skip] +static mcol_scan_16x8 : [u16; 128] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, +]; + +#[rustfmt::skip] +static mcol_scan_8x16 : [u16; 128] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, +]; + +#[rustfmt::skip] +static default_scan_32x16 : [u16; 512] = [ + 0, 1, 16, 2, 17, 32, 3, 18, 33, 48, 4, 19, 34, 49, 64, + 5, 20, 35, 50, 65, 80, 6, 21, 36, 51, 66, 81, 96, 7, 22, + 37, 52, 67, 82, 97, 112, 8, 23, 38, 53, 68, 83, 98, 113, 128, + 9, 24, 39, 54, 69, 84, 99, 114, 129, 144, 10, 25, 40, 55, 70, + 85, 100, 115, 130, 145, 160, 11, 26, 41, 56, 71, 86, 101, 116, 131, + 146, 161, 176, 12, 27, 42, 57, 72, 87, 102, 117, 132, 147, 162, 177, + 192, 13, 28, 43, 58, 73, 88, 103, 118, 133, 148, 163, 178, 193, 208, + 14, 29, 44, 59, 74, 89, 104, 119, 134, 149, 164, 179, 194, 209, 224, + 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, + 240, 31, 46, 61, 76, 91, 106, 121, 136, 151, 166, 181, 196, 211, 226, + 241, 256, 47, 62, 77, 92, 107, 122, 137, 152, 167, 182, 197, 212, 227, + 242, 257, 272, 63, 78, 93, 108, 123, 138, 153, 168, 183, 198, 213, 228, + 243, 258, 273, 288, 79, 94, 109, 124, 139, 154, 169, 184, 199, 214, 229, + 244, 259, 274, 289, 304, 95, 110, 125, 140, 155, 170, 185, 200, 215, 230, + 245, 260, 275, 290, 305, 320, 111, 126, 141, 156, 171, 186, 201, 216, 231, + 246, 261, 276, 291, 306, 321, 336, 127, 142, 157, 172, 187, 202, 217, 232, + 247, 262, 277, 292, 307, 322, 337, 352, 143, 158, 173, 188, 203, 218, 233, + 248, 263, 278, 293, 308, 323, 338, 353, 368, 159, 174, 189, 204, 219, 234, + 249, 264, 279, 294, 309, 324, 339, 354, 369, 384, 175, 190, 205, 220, 235, + 250, 265, 280, 295, 310, 325, 340, 355, 370, 385, 400, 191, 206, 221, 236, + 251, 266, 281, 296, 311, 326, 341, 356, 371, 386, 401, 416, 207, 222, 237, + 252, 267, 282, 297, 312, 327, 342, 357, 372, 387, 402, 417, 432, 223, 238, + 253, 268, 283, 298, 313, 328, 343, 358, 373, 388, 403, 418, 433, 448, 239, + 254, 269, 284, 299, 314, 329, 344, 359, 374, 389, 404, 419, 434, 449, 464, + 255, 270, 285, 300, 315, 330, 345, 360, 375, 390, 405, 420, 435, 450, 465, + 480, 271, 286, 301, 316, 331, 346, 361, 376, 391, 406, 421, 436, 451, 466, + 481, 496, 287, 302, 317, 332, 347, 362, 377, 392, 407, 422, 437, 452, 467, + 482, 497, 303, 318, 333, 348, 363, 378, 393, 408, 423, 438, 453, 468, 483, + 498, 319, 334, 349, 364, 379, 394, 409, 424, 439, 454, 469, 484, 499, 335, + 350, 365, 380, 395, 410, 425, 440, 455, 470, 485, 500, 351, 366, 381, 396, + 411, 426, 441, 456, 471, 486, 501, 367, 382, 397, 412, 427, 442, 457, 472, + 487, 502, 383, 398, 413, 428, 443, 458, 473, 488, 503, 399, 414, 429, 444, + 459, 474, 489, 504, 415, 430, 445, 460, 475, 490, 505, 431, 446, 461, 476, + 491, 506, 447, 462, 477, 492, 507, 463, 478, 493, 508, 479, 494, 509, 495, + 510, 511, +]; + +#[rustfmt::skip] +static default_scan_16x32 : [u16; 512] = [ + 0, 32, 1, 64, 33, 2, 96, 65, 34, 3, 128, 97, 66, 35, 4, + 160, 129, 98, 67, 36, 5, 192, 161, 130, 99, 68, 37, 6, 224, 193, + 162, 131, 100, 69, 38, 7, 256, 225, 194, 163, 132, 101, 70, 39, 8, + 288, 257, 226, 195, 164, 133, 102, 71, 40, 9, 320, 289, 258, 227, 196, + 165, 134, 103, 72, 41, 10, 352, 321, 290, 259, 228, 197, 166, 135, 104, + 73, 42, 11, 384, 353, 322, 291, 260, 229, 198, 167, 136, 105, 74, 43, + 12, 416, 385, 354, 323, 292, 261, 230, 199, 168, 137, 106, 75, 44, 13, + 448, 417, 386, 355, 324, 293, 262, 231, 200, 169, 138, 107, 76, 45, 14, + 480, 449, 418, 387, 356, 325, 294, 263, 232, 201, 170, 139, 108, 77, 46, + 15, 481, 450, 419, 388, 357, 326, 295, 264, 233, 202, 171, 140, 109, 78, + 47, 16, 482, 451, 420, 389, 358, 327, 296, 265, 234, 203, 172, 141, 110, + 79, 48, 17, 483, 452, 421, 390, 359, 328, 297, 266, 235, 204, 173, 142, + 111, 80, 49, 18, 484, 453, 422, 391, 360, 329, 298, 267, 236, 205, 174, + 143, 112, 81, 50, 19, 485, 454, 423, 392, 361, 330, 299, 268, 237, 206, + 175, 144, 113, 82, 51, 20, 486, 455, 424, 393, 362, 331, 300, 269, 238, + 207, 176, 145, 114, 83, 52, 21, 487, 456, 425, 394, 363, 332, 301, 270, + 239, 208, 177, 146, 115, 84, 53, 22, 488, 457, 426, 395, 364, 333, 302, + 271, 240, 209, 178, 147, 116, 85, 54, 23, 489, 458, 427, 396, 365, 334, + 303, 272, 241, 210, 179, 148, 117, 86, 55, 24, 490, 459, 428, 397, 366, + 335, 304, 273, 242, 211, 180, 149, 118, 87, 56, 25, 491, 460, 429, 398, + 367, 336, 305, 274, 243, 212, 181, 150, 119, 88, 57, 26, 492, 461, 430, + 399, 368, 337, 306, 275, 244, 213, 182, 151, 120, 89, 58, 27, 493, 462, + 431, 400, 369, 338, 307, 276, 245, 214, 183, 152, 121, 90, 59, 28, 494, + 463, 432, 401, 370, 339, 308, 277, 246, 215, 184, 153, 122, 91, 60, 29, + 495, 464, 433, 402, 371, 340, 309, 278, 247, 216, 185, 154, 123, 92, 61, + 30, 496, 465, 434, 403, 372, 341, 310, 279, 248, 217, 186, 155, 124, 93, + 62, 31, 497, 466, 435, 404, 373, 342, 311, 280, 249, 218, 187, 156, 125, + 94, 63, 498, 467, 436, 405, 374, 343, 312, 281, 250, 219, 188, 157, 126, + 95, 499, 468, 437, 406, 375, 344, 313, 282, 251, 220, 189, 158, 127, 500, + 469, 438, 407, 376, 345, 314, 283, 252, 221, 190, 159, 501, 470, 439, 408, + 377, 346, 315, 284, 253, 222, 191, 502, 471, 440, 409, 378, 347, 316, 285, + 254, 223, 503, 472, 441, 410, 379, 348, 317, 286, 255, 504, 473, 442, 411, + 380, 349, 318, 287, 505, 474, 443, 412, 381, 350, 319, 506, 475, 444, 413, + 382, 351, 507, 476, 445, 414, 383, 508, 477, 446, 415, 509, 478, 447, 510, + 479, 511, +]; + +#[rustfmt::skip] +static mrow_scan_32x16 : [u16; 512] = [ + 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, + 240, 256, 272, 288, 304, 320, 336, 352, 368, 384, 400, 416, 432, 448, 464, + 480, 496, 1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177, 193, + 209, 225, 241, 257, 273, 289, 305, 321, 337, 353, 369, 385, 401, 417, 433, + 449, 465, 481, 497, 2, 18, 34, 50, 66, 82, 98, 114, 130, 146, 162, + 178, 194, 210, 226, 242, 258, 274, 290, 306, 322, 338, 354, 370, 386, 402, + 418, 434, 450, 466, 482, 498, 3, 19, 35, 51, 67, 83, 99, 115, 131, + 147, 163, 179, 195, 211, 227, 243, 259, 275, 291, 307, 323, 339, 355, 371, + 387, 403, 419, 435, 451, 467, 483, 499, 4, 20, 36, 52, 68, 84, 100, + 116, 132, 148, 164, 180, 196, 212, 228, 244, 260, 276, 292, 308, 324, 340, + 356, 372, 388, 404, 420, 436, 452, 468, 484, 500, 5, 21, 37, 53, 69, + 85, 101, 117, 133, 149, 165, 181, 197, 213, 229, 245, 261, 277, 293, 309, + 325, 341, 357, 373, 389, 405, 421, 437, 453, 469, 485, 501, 6, 22, 38, + 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 246, 262, 278, + 294, 310, 326, 342, 358, 374, 390, 406, 422, 438, 454, 470, 486, 502, 7, + 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183, 199, 215, 231, 247, + 263, 279, 295, 311, 327, 343, 359, 375, 391, 407, 423, 439, 455, 471, 487, + 503, 8, 24, 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, + 232, 248, 264, 280, 296, 312, 328, 344, 360, 376, 392, 408, 424, 440, 456, + 472, 488, 504, 9, 25, 41, 57, 73, 89, 105, 121, 137, 153, 169, 185, + 201, 217, 233, 249, 265, 281, 297, 313, 329, 345, 361, 377, 393, 409, 425, + 441, 457, 473, 489, 505, 10, 26, 42, 58, 74, 90, 106, 122, 138, 154, + 170, 186, 202, 218, 234, 250, 266, 282, 298, 314, 330, 346, 362, 378, 394, + 410, 426, 442, 458, 474, 490, 506, 11, 27, 43, 59, 75, 91, 107, 123, + 139, 155, 171, 187, 203, 219, 235, 251, 267, 283, 299, 315, 331, 347, 363, + 379, 395, 411, 427, 443, 459, 475, 491, 507, 12, 28, 44, 60, 76, 92, + 108, 124, 140, 156, 172, 188, 204, 220, 236, 252, 268, 284, 300, 316, 332, + 348, 364, 380, 396, 412, 428, 444, 460, 476, 492, 508, 13, 29, 45, 61, + 77, 93, 109, 125, 141, 157, 173, 189, 205, 221, 237, 253, 269, 285, 301, + 317, 333, 349, 365, 381, 397, 413, 429, 445, 461, 477, 493, 509, 14, 30, + 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254, 270, + 286, 302, 318, 334, 350, 366, 382, 398, 414, 430, 446, 462, 478, 494, 510, + 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, + 255, 271, 287, 303, 319, 335, 351, 367, 383, 399, 415, 431, 447, 463, 479, + 495, 511, +]; + +#[rustfmt::skip] +static mrow_scan_16x32 : [u16; 512] = [ + 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480, + 1, 33, 65, 97, 129, 161, 193, 225, 257, 289, 321, 353, 385, 417, 449, 481, + 2, 34, 66, 98, 130, 162, 194, 226, 258, 290, 322, 354, 386, 418, 450, 482, + 3, 35, 67, 99, 131, 163, 195, 227, 259, 291, 323, 355, 387, 419, 451, 483, + 4, 36, 68, 100, 132, 164, 196, 228, 260, 292, 324, 356, 388, 420, 452, 484, + 5, 37, 69, 101, 133, 165, 197, 229, 261, 293, 325, 357, 389, 421, 453, 485, + 6, 38, 70, 102, 134, 166, 198, 230, 262, 294, 326, 358, 390, 422, 454, 486, + 7, 39, 71, 103, 135, 167, 199, 231, 263, 295, 327, 359, 391, 423, 455, 487, + 8, 40, 72, 104, 136, 168, 200, 232, 264, 296, 328, 360, 392, 424, 456, 488, + 9, 41, 73, 105, 137, 169, 201, 233, 265, 297, 329, 361, 393, 425, 457, 489, + 10, 42, 74, 106, 138, 170, 202, 234, 266, 298, 330, 362, 394, 426, 458, 490, + 11, 43, 75, 107, 139, 171, 203, 235, 267, 299, 331, 363, 395, 427, 459, 491, + 12, 44, 76, 108, 140, 172, 204, 236, 268, 300, 332, 364, 396, 428, 460, 492, + 13, 45, 77, 109, 141, 173, 205, 237, 269, 301, 333, 365, 397, 429, 461, 493, + 14, 46, 78, 110, 142, 174, 206, 238, 270, 302, 334, 366, 398, 430, 462, 494, + 15, 47, 79, 111, 143, 175, 207, 239, 271, 303, 335, 367, 399, 431, 463, 495, + 16, 48, 80, 112, 144, 176, 208, 240, 272, 304, 336, 368, 400, 432, 464, 496, + 17, 49, 81, 113, 145, 177, 209, 241, 273, 305, 337, 369, 401, 433, 465, 497, + 18, 50, 82, 114, 146, 178, 210, 242, 274, 306, 338, 370, 402, 434, 466, 498, + 19, 51, 83, 115, 147, 179, 211, 243, 275, 307, 339, 371, 403, 435, 467, 499, + 20, 52, 84, 116, 148, 180, 212, 244, 276, 308, 340, 372, 404, 436, 468, 500, + 21, 53, 85, 117, 149, 181, 213, 245, 277, 309, 341, 373, 405, 437, 469, 501, + 22, 54, 86, 118, 150, 182, 214, 246, 278, 310, 342, 374, 406, 438, 470, 502, + 23, 55, 87, 119, 151, 183, 215, 247, 279, 311, 343, 375, 407, 439, 471, 503, + 24, 56, 88, 120, 152, 184, 216, 248, 280, 312, 344, 376, 408, 440, 472, 504, + 25, 57, 89, 121, 153, 185, 217, 249, 281, 313, 345, 377, 409, 441, 473, 505, + 26, 58, 90, 122, 154, 186, 218, 250, 282, 314, 346, 378, 410, 442, 474, 506, + 27, 59, 91, 123, 155, 187, 219, 251, 283, 315, 347, 379, 411, 443, 475, 507, + 28, 60, 92, 124, 156, 188, 220, 252, 284, 316, 348, 380, 412, 444, 476, 508, + 29, 61, 93, 125, 157, 189, 221, 253, 285, 317, 349, 381, 413, 445, 477, 509, + 30, 62, 94, 126, 158, 190, 222, 254, 286, 318, 350, 382, 414, 446, 478, 510, + 31, 63, 95, 127, 159, 191, 223, 255, 287, 319, 351, 383, 415, 447, 479, 511, +]; + +#[rustfmt::skip] +static mcol_scan_32x16 : [u16; 512] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, +]; + +#[rustfmt::skip] +static mcol_scan_16x32 : [u16; 512] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, +]; + +#[rustfmt::skip] +static default_scan_16x16 : [u16; 256] = [ + 0, 16, 1, 2, 17, 32, 48, 33, 18, 3, 4, 19, 34, 49, 64, + 80, 65, 50, 35, 20, 5, 6, 21, 36, 51, 66, 81, 96, 112, 97, + 82, 67, 52, 37, 22, 7, 8, 23, 38, 53, 68, 83, 98, 113, 128, + 144, 129, 114, 99, 84, 69, 54, 39, 24, 9, 10, 25, 40, 55, 70, + 85, 100, 115, 130, 145, 160, 176, 161, 146, 131, 116, 101, 86, 71, 56, + 41, 26, 11, 12, 27, 42, 57, 72, 87, 102, 117, 132, 147, 162, 177, + 192, 208, 193, 178, 163, 148, 133, 118, 103, 88, 73, 58, 43, 28, 13, + 14, 29, 44, 59, 74, 89, 104, 119, 134, 149, 164, 179, 194, 209, 224, + 240, 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, + 15, 31, 46, 61, 76, 91, 106, 121, 136, 151, 166, 181, 196, 211, 226, + 241, 242, 227, 212, 197, 182, 167, 152, 137, 122, 107, 92, 77, 62, 47, + 63, 78, 93, 108, 123, 138, 153, 168, 183, 198, 213, 228, 243, 244, 229, + 214, 199, 184, 169, 154, 139, 124, 109, 94, 79, 95, 110, 125, 140, 155, + 170, 185, 200, 215, 230, 245, 246, 231, 216, 201, 186, 171, 156, 141, 126, + 111, 127, 142, 157, 172, 187, 202, 217, 232, 247, 248, 233, 218, 203, 188, + 173, 158, 143, 159, 174, 189, 204, 219, 234, 249, 250, 235, 220, 205, 190, + 175, 191, 206, 221, 236, 251, 252, 237, 222, 207, 223, 238, 253, 254, 239, + 255, +]; + +#[rustfmt::skip] +static mrow_scan_16x16 : [u16; 256] = [ + 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, + 1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177, 193, 209, 225, 241, + 2, 18, 34, 50, 66, 82, 98, 114, 130, 146, 162, 178, 194, 210, 226, 242, + 3, 19, 35, 51, 67, 83, 99, 115, 131, 147, 163, 179, 195, 211, 227, 243, + 4, 20, 36, 52, 68, 84, 100, 116, 132, 148, 164, 180, 196, 212, 228, 244, + 5, 21, 37, 53, 69, 85, 101, 117, 133, 149, 165, 181, 197, 213, 229, 245, + 6, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 246, + 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183, 199, 215, 231, 247, + 8, 24, 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, 232, 248, + 9, 25, 41, 57, 73, 89, 105, 121, 137, 153, 169, 185, 201, 217, 233, 249, + 10, 26, 42, 58, 74, 90, 106, 122, 138, 154, 170, 186, 202, 218, 234, 250, + 11, 27, 43, 59, 75, 91, 107, 123, 139, 155, 171, 187, 203, 219, 235, 251, + 12, 28, 44, 60, 76, 92, 108, 124, 140, 156, 172, 188, 204, 220, 236, 252, + 13, 29, 45, 61, 77, 93, 109, 125, 141, 157, 173, 189, 205, 221, 237, 253, + 14, 30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254, + 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, +]; + +#[rustfmt::skip] +static mcol_scan_16x16 : [u16; 256] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, +]; + +#[rustfmt::skip] +static mrow_scan_32x32 : [u16; 1024] = [ + 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, + 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, + 896, 928, 960, 992, 1, 33, 65, 97, 129, 161, 193, 225, 257, 289, + 321, 353, 385, 417, 449, 481, 513, 545, 577, 609, 641, 673, 705, 737, + 769, 801, 833, 865, 897, 929, 961, 993, 2, 34, 66, 98, 130, 162, + 194, 226, 258, 290, 322, 354, 386, 418, 450, 482, 514, 546, 578, 610, + 642, 674, 706, 738, 770, 802, 834, 866, 898, 930, 962, 994, 3, 35, + 67, 99, 131, 163, 195, 227, 259, 291, 323, 355, 387, 419, 451, 483, + 515, 547, 579, 611, 643, 675, 707, 739, 771, 803, 835, 867, 899, 931, + 963, 995, 4, 36, 68, 100, 132, 164, 196, 228, 260, 292, 324, 356, + 388, 420, 452, 484, 516, 548, 580, 612, 644, 676, 708, 740, 772, 804, + 836, 868, 900, 932, 964, 996, 5, 37, 69, 101, 133, 165, 197, 229, + 261, 293, 325, 357, 389, 421, 453, 485, 517, 549, 581, 613, 645, 677, + 709, 741, 773, 805, 837, 869, 901, 933, 965, 997, 6, 38, 70, 102, + 134, 166, 198, 230, 262, 294, 326, 358, 390, 422, 454, 486, 518, 550, + 582, 614, 646, 678, 710, 742, 774, 806, 838, 870, 902, 934, 966, 998, + 7, 39, 71, 103, 135, 167, 199, 231, 263, 295, 327, 359, 391, 423, + 455, 487, 519, 551, 583, 615, 647, 679, 711, 743, 775, 807, 839, 871, + 903, 935, 967, 999, 8, 40, 72, 104, 136, 168, 200, 232, 264, 296, + 328, 360, 392, 424, 456, 488, 520, 552, 584, 616, 648, 680, 712, 744, + 776, 808, 840, 872, 904, 936, 968, 1000, 9, 41, 73, 105, 137, 169, + 201, 233, 265, 297, 329, 361, 393, 425, 457, 489, 521, 553, 585, 617, + 649, 681, 713, 745, 777, 809, 841, 873, 905, 937, 969, 1001, 10, 42, + 74, 106, 138, 170, 202, 234, 266, 298, 330, 362, 394, 426, 458, 490, + 522, 554, 586, 618, 650, 682, 714, 746, 778, 810, 842, 874, 906, 938, + 970, 1002, 11, 43, 75, 107, 139, 171, 203, 235, 267, 299, 331, 363, + 395, 427, 459, 491, 523, 555, 587, 619, 651, 683, 715, 747, 779, 811, + 843, 875, 907, 939, 971, 1003, 12, 44, 76, 108, 140, 172, 204, 236, + 268, 300, 332, 364, 396, 428, 460, 492, 524, 556, 588, 620, 652, 684, + 716, 748, 780, 812, 844, 876, 908, 940, 972, 1004, 13, 45, 77, 109, + 141, 173, 205, 237, 269, 301, 333, 365, 397, 429, 461, 493, 525, 557, + 589, 621, 653, 685, 717, 749, 781, 813, 845, 877, 909, 941, 973, 1005, + 14, 46, 78, 110, 142, 174, 206, 238, 270, 302, 334, 366, 398, 430, + 462, 494, 526, 558, 590, 622, 654, 686, 718, 750, 782, 814, 846, 878, + 910, 942, 974, 1006, 15, 47, 79, 111, 143, 175, 207, 239, 271, 303, + 335, 367, 399, 431, 463, 495, 527, 559, 591, 623, 655, 687, 719, 751, + 783, 815, 847, 879, 911, 943, 975, 1007, 16, 48, 80, 112, 144, 176, + 208, 240, 272, 304, 336, 368, 400, 432, 464, 496, 528, 560, 592, 624, + 656, 688, 720, 752, 784, 816, 848, 880, 912, 944, 976, 1008, 17, 49, + 81, 113, 145, 177, 209, 241, 273, 305, 337, 369, 401, 433, 465, 497, + 529, 561, 593, 625, 657, 689, 721, 753, 785, 817, 849, 881, 913, 945, + 977, 1009, 18, 50, 82, 114, 146, 178, 210, 242, 274, 306, 338, 370, + 402, 434, 466, 498, 530, 562, 594, 626, 658, 690, 722, 754, 786, 818, + 850, 882, 914, 946, 978, 1010, 19, 51, 83, 115, 147, 179, 211, 243, + 275, 307, 339, 371, 403, 435, 467, 499, 531, 563, 595, 627, 659, 691, + 723, 755, 787, 819, 851, 883, 915, 947, 979, 1011, 20, 52, 84, 116, + 148, 180, 212, 244, 276, 308, 340, 372, 404, 436, 468, 500, 532, 564, + 596, 628, 660, 692, 724, 756, 788, 820, 852, 884, 916, 948, 980, 1012, + 21, 53, 85, 117, 149, 181, 213, 245, 277, 309, 341, 373, 405, 437, + 469, 501, 533, 565, 597, 629, 661, 693, 725, 757, 789, 821, 853, 885, + 917, 949, 981, 1013, 22, 54, 86, 118, 150, 182, 214, 246, 278, 310, + 342, 374, 406, 438, 470, 502, 534, 566, 598, 630, 662, 694, 726, 758, + 790, 822, 854, 886, 918, 950, 982, 1014, 23, 55, 87, 119, 151, 183, + 215, 247, 279, 311, 343, 375, 407, 439, 471, 503, 535, 567, 599, 631, + 663, 695, 727, 759, 791, 823, 855, 887, 919, 951, 983, 1015, 24, 56, + 88, 120, 152, 184, 216, 248, 280, 312, 344, 376, 408, 440, 472, 504, + 536, 568, 600, 632, 664, 696, 728, 760, 792, 824, 856, 888, 920, 952, + 984, 1016, 25, 57, 89, 121, 153, 185, 217, 249, 281, 313, 345, 377, + 409, 441, 473, 505, 537, 569, 601, 633, 665, 697, 729, 761, 793, 825, + 857, 889, 921, 953, 985, 1017, 26, 58, 90, 122, 154, 186, 218, 250, + 282, 314, 346, 378, 410, 442, 474, 506, 538, 570, 602, 634, 666, 698, + 730, 762, 794, 826, 858, 890, 922, 954, 986, 1018, 27, 59, 91, 123, + 155, 187, 219, 251, 283, 315, 347, 379, 411, 443, 475, 507, 539, 571, + 603, 635, 667, 699, 731, 763, 795, 827, 859, 891, 923, 955, 987, 1019, + 28, 60, 92, 124, 156, 188, 220, 252, 284, 316, 348, 380, 412, 444, + 476, 508, 540, 572, 604, 636, 668, 700, 732, 764, 796, 828, 860, 892, + 924, 956, 988, 1020, 29, 61, 93, 125, 157, 189, 221, 253, 285, 317, + 349, 381, 413, 445, 477, 509, 541, 573, 605, 637, 669, 701, 733, 765, + 797, 829, 861, 893, 925, 957, 989, 1021, 30, 62, 94, 126, 158, 190, + 222, 254, 286, 318, 350, 382, 414, 446, 478, 510, 542, 574, 606, 638, + 670, 702, 734, 766, 798, 830, 862, 894, 926, 958, 990, 1022, 31, 63, + 95, 127, 159, 191, 223, 255, 287, 319, 351, 383, 415, 447, 479, 511, + 543, 575, 607, 639, 671, 703, 735, 767, 799, 831, 863, 895, 927, 959, + 991, 1023, +]; + +#[rustfmt::skip] +static mcol_scan_32x32 : [u16; 1024] = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, + 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, + 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, + 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, + 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, + 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, + 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, + 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, + 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, + 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, + 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, + 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, + 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, + 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, + 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, + 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, + 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, + 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, + 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, + 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, + 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, + 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, + 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, + 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, + 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, + 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, + 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, + 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, + 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, + 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, + 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, + 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, + 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, + 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, +]; + +#[rustfmt::skip] +static default_scan_32x32 : [u16; 1024] = [ + 0, 32, 1, 2, 33, 64, 96, 65, 34, 3, 4, 35, 66, + 97, 128, 160, 129, 98, 67, 36, 5, 6, 37, 68, 99, 130, + 161, 192, 224, 193, 162, 131, 100, 69, 38, 7, 8, 39, 70, + 101, 132, 163, 194, 225, 256, 288, 257, 226, 195, 164, 133, 102, + 71, 40, 9, 10, 41, 72, 103, 134, 165, 196, 227, 258, 289, + 320, 352, 321, 290, 259, 228, 197, 166, 135, 104, 73, 42, 11, + 12, 43, 74, 105, 136, 167, 198, 229, 260, 291, 322, 353, 384, + 416, 385, 354, 323, 292, 261, 230, 199, 168, 137, 106, 75, 44, + 13, 14, 45, 76, 107, 138, 169, 200, 231, 262, 293, 324, 355, + 386, 417, 448, 480, 449, 418, 387, 356, 325, 294, 263, 232, 201, + 170, 139, 108, 77, 46, 15, 16, 47, 78, 109, 140, 171, 202, + 233, 264, 295, 326, 357, 388, 419, 450, 481, 512, 544, 513, 482, + 451, 420, 389, 358, 327, 296, 265, 234, 203, 172, 141, 110, 79, + 48, 17, 18, 49, 80, 111, 142, 173, 204, 235, 266, 297, 328, + 359, 390, 421, 452, 483, 514, 545, 576, 608, 577, 546, 515, 484, + 453, 422, 391, 360, 329, 298, 267, 236, 205, 174, 143, 112, 81, + 50, 19, 20, 51, 82, 113, 144, 175, 206, 237, 268, 299, 330, + 361, 392, 423, 454, 485, 516, 547, 578, 609, 640, 672, 641, 610, + 579, 548, 517, 486, 455, 424, 393, 362, 331, 300, 269, 238, 207, + 176, 145, 114, 83, 52, 21, 22, 53, 84, 115, 146, 177, 208, + 239, 270, 301, 332, 363, 394, 425, 456, 487, 518, 549, 580, 611, + 642, 673, 704, 736, 705, 674, 643, 612, 581, 550, 519, 488, 457, + 426, 395, 364, 333, 302, 271, 240, 209, 178, 147, 116, 85, 54, + 23, 24, 55, 86, 117, 148, 179, 210, 241, 272, 303, 334, 365, + 396, 427, 458, 489, 520, 551, 582, 613, 644, 675, 706, 737, 768, + 800, 769, 738, 707, 676, 645, 614, 583, 552, 521, 490, 459, 428, + 397, 366, 335, 304, 273, 242, 211, 180, 149, 118, 87, 56, 25, + 26, 57, 88, 119, 150, 181, 212, 243, 274, 305, 336, 367, 398, + 429, 460, 491, 522, 553, 584, 615, 646, 677, 708, 739, 770, 801, + 832, 864, 833, 802, 771, 740, 709, 678, 647, 616, 585, 554, 523, + 492, 461, 430, 399, 368, 337, 306, 275, 244, 213, 182, 151, 120, + 89, 58, 27, 28, 59, 90, 121, 152, 183, 214, 245, 276, 307, + 338, 369, 400, 431, 462, 493, 524, 555, 586, 617, 648, 679, 710, + 741, 772, 803, 834, 865, 896, 928, 897, 866, 835, 804, 773, 742, + 711, 680, 649, 618, 587, 556, 525, 494, 463, 432, 401, 370, 339, + 308, 277, 246, 215, 184, 153, 122, 91, 60, 29, 30, 61, 92, + 123, 154, 185, 216, 247, 278, 309, 340, 371, 402, 433, 464, 495, + 526, 557, 588, 619, 650, 681, 712, 743, 774, 805, 836, 867, 898, + 929, 960, 992, 961, 930, 899, 868, 837, 806, 775, 744, 713, 682, + 651, 620, 589, 558, 527, 496, 465, 434, 403, 372, 341, 310, 279, + 248, 217, 186, 155, 124, 93, 62, 31, 63, 94, 125, 156, 187, + 218, 249, 280, 311, 342, 373, 404, 435, 466, 497, 528, 559, 590, + 621, 652, 683, 714, 745, 776, 807, 838, 869, 900, 931, 962, 993, + 994, 963, 932, 901, 870, 839, 808, 777, 746, 715, 684, 653, 622, + 591, 560, 529, 498, 467, 436, 405, 374, 343, 312, 281, 250, 219, + 188, 157, 126, 95, 127, 158, 189, 220, 251, 282, 313, 344, 375, + 406, 437, 468, 499, 530, 561, 592, 623, 654, 685, 716, 747, 778, + 809, 840, 871, 902, 933, 964, 995, 996, 965, 934, 903, 872, 841, + 810, 779, 748, 717, 686, 655, 624, 593, 562, 531, 500, 469, 438, + 407, 376, 345, 314, 283, 252, 221, 190, 159, 191, 222, 253, 284, + 315, 346, 377, 408, 439, 470, 501, 532, 563, 594, 625, 656, 687, + 718, 749, 780, 811, 842, 873, 904, 935, 966, 997, 998, 967, 936, + 905, 874, 843, 812, 781, 750, 719, 688, 657, 626, 595, 564, 533, + 502, 471, 440, 409, 378, 347, 316, 285, 254, 223, 255, 286, 317, + 348, 379, 410, 441, 472, 503, 534, 565, 596, 627, 658, 689, 720, + 751, 782, 813, 844, 875, 906, 937, 968, 999, 1000, 969, 938, 907, + 876, 845, 814, 783, 752, 721, 690, 659, 628, 597, 566, 535, 504, + 473, 442, 411, 380, 349, 318, 287, 319, 350, 381, 412, 443, 474, + 505, 536, 567, 598, 629, 660, 691, 722, 753, 784, 815, 846, 877, + 908, 939, 970, 1001, 1002, 971, 940, 909, 878, 847, 816, 785, 754, + 723, 692, 661, 630, 599, 568, 537, 506, 475, 444, 413, 382, 351, + 383, 414, 445, 476, 507, 538, 569, 600, 631, 662, 693, 724, 755, + 786, 817, 848, 879, 910, 941, 972, 1003, 1004, 973, 942, 911, 880, + 849, 818, 787, 756, 725, 694, 663, 632, 601, 570, 539, 508, 477, + 446, 415, 447, 478, 509, 540, 571, 602, 633, 664, 695, 726, 757, + 788, 819, 850, 881, 912, 943, 974, 1005, 1006, 975, 944, 913, 882, + 851, 820, 789, 758, 727, 696, 665, 634, 603, 572, 541, 510, 479, + 511, 542, 573, 604, 635, 666, 697, 728, 759, 790, 821, 852, 883, + 914, 945, 976, 1007, 1008, 977, 946, 915, 884, 853, 822, 791, 760, + 729, 698, 667, 636, 605, 574, 543, 575, 606, 637, 668, 699, 730, + 761, 792, 823, 854, 885, 916, 947, 978, 1009, 1010, 979, 948, 917, + 886, 855, 824, 793, 762, 731, 700, 669, 638, 607, 639, 670, 701, + 732, 763, 794, 825, 856, 887, 918, 949, 980, 1011, 1012, 981, 950, + 919, 888, 857, 826, 795, 764, 733, 702, 671, 703, 734, 765, 796, + 827, 858, 889, 920, 951, 982, 1013, 1014, 983, 952, 921, 890, 859, + 828, 797, 766, 735, 767, 798, 829, 860, 891, 922, 953, 984, 1015, + 1016, 985, 954, 923, 892, 861, 830, 799, 831, 862, 893, 924, 955, + 986, 1017, 1018, 987, 956, 925, 894, 863, 895, 926, 957, 988, 1019, + 1020, 989, 958, 927, 959, 990, 1021, 1022, 991, 1023, +]; + +const fn invert(scan: [u16; N]) -> [u16; N] { + let mut iscan = scan; + let mut i = 0; + while i < N { + iscan[scan[i] as usize] = i as u16; + i += 1; + } + iscan +} + +static default_iscan_4x4: [u16; 16] = invert(default_scan_4x4); +static mrow_iscan_4x4: [u16; 16] = invert(mrow_scan_4x4); +static mcol_iscan_4x4: [u16; 16] = invert(mcol_scan_4x4); +static default_iscan_8x4: [u16; 32] = invert(default_scan_8x4); +static mrow_iscan_8x4: [u16; 32] = invert(mrow_scan_8x4); +static mcol_iscan_8x4: [u16; 32] = invert(mcol_scan_8x4); +static default_iscan_4x8: [u16; 32] = invert(default_scan_4x8); +static mrow_iscan_4x8: [u16; 32] = invert(mrow_scan_4x8); +static mcol_iscan_4x8: [u16; 32] = invert(mcol_scan_4x8); +static default_iscan_16x4: [u16; 64] = invert(default_scan_16x4); +static default_iscan_4x16: [u16; 64] = invert(default_scan_4x16); +static mcol_iscan_16x4: [u16; 64] = invert(mcol_scan_16x4); +static mcol_iscan_4x16: [u16; 64] = invert(mcol_scan_4x16); +static mrow_iscan_16x4: [u16; 64] = invert(mrow_scan_16x4); +static mrow_iscan_4x16: [u16; 64] = invert(mrow_scan_4x16); +static default_iscan_32x8: [u16; 256] = invert(default_scan_32x8); +static default_iscan_8x32: [u16; 256] = invert(default_scan_8x32); +static mcol_iscan_32x8: [u16; 256] = invert(mcol_scan_32x8); +static mcol_iscan_8x32: [u16; 256] = invert(mcol_scan_8x32); +static mrow_iscan_32x8: [u16; 256] = invert(mrow_scan_32x8); +static mrow_iscan_8x32: [u16; 256] = invert(mrow_scan_8x32); +static default_iscan_8x8: [u16; 64] = invert(default_scan_8x8); +static mrow_iscan_8x8: [u16; 64] = invert(mrow_scan_8x8); +static mcol_iscan_8x8: [u16; 64] = invert(mcol_scan_8x8); +static default_iscan_16x8: [u16; 128] = invert(default_scan_16x8); +static default_iscan_8x16: [u16; 128] = invert(default_scan_8x16); +static mrow_iscan_16x8: [u16; 128] = invert(mrow_scan_16x8); +static mrow_iscan_8x16: [u16; 128] = invert(mrow_scan_8x16); +static mcol_iscan_16x8: [u16; 128] = invert(mcol_scan_16x8); +static mcol_iscan_8x16: [u16; 128] = invert(mcol_scan_8x16); +static default_iscan_32x16: [u16; 512] = invert(default_scan_32x16); +static default_iscan_16x32: [u16; 512] = invert(default_scan_16x32); +static mrow_iscan_32x16: [u16; 512] = invert(mrow_scan_32x16); +static mrow_iscan_16x32: [u16; 512] = invert(mrow_scan_16x32); +static mcol_iscan_32x16: [u16; 512] = invert(mcol_scan_32x16); +static mcol_iscan_16x32: [u16; 512] = invert(mcol_scan_16x32); +static default_iscan_16x16: [u16; 256] = invert(default_scan_16x16); +static mrow_iscan_16x16: [u16; 256] = invert(mrow_scan_16x16); +static mcol_iscan_16x16: [u16; 256] = invert(mcol_scan_16x16); +static mrow_iscan_32x32: [u16; 1024] = invert(mrow_scan_32x32); +static mcol_iscan_32x32: [u16; 1024] = invert(mcol_scan_32x32); +static default_iscan_32x32: [u16; 1024] = invert(default_scan_32x32); + +#[rustfmt::skip] +pub static av1_scan_orders: [[SCAN_ORDER; TX_TYPES]; TxSize::TX_SIZES_ALL] = [ + [ + // TX_4X4 + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &default_scan_4x4, iscan: &default_iscan_4x4 }, + SCAN_ORDER { scan: &mrow_scan_4x4, iscan: &mrow_iscan_4x4 }, + SCAN_ORDER { scan: &mcol_scan_4x4, iscan: &mcol_iscan_4x4 }, + SCAN_ORDER { scan: &mrow_scan_4x4, iscan: &mrow_iscan_4x4 }, + SCAN_ORDER { scan: &mcol_scan_4x4, iscan: &mcol_iscan_4x4 }, + SCAN_ORDER { scan: &mrow_scan_4x4, iscan: &mrow_iscan_4x4 }, + SCAN_ORDER { scan: &mcol_scan_4x4, iscan: &mcol_iscan_4x4 }, + ], + [ + // TX_8X8 + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &default_scan_8x8, iscan: &default_iscan_8x8 }, + SCAN_ORDER { scan: &mrow_scan_8x8, iscan: &mrow_iscan_8x8 }, + SCAN_ORDER { scan: &mcol_scan_8x8, iscan: &mcol_iscan_8x8 }, + SCAN_ORDER { scan: &mrow_scan_8x8, iscan: &mrow_iscan_8x8 }, + SCAN_ORDER { scan: &mcol_scan_8x8, iscan: &mcol_iscan_8x8 }, + SCAN_ORDER { scan: &mrow_scan_8x8, iscan: &mrow_iscan_8x8 }, + SCAN_ORDER { scan: &mcol_scan_8x8, iscan: &mcol_iscan_8x8 }, + ], + [ + // TX_16X16 + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &default_scan_16x16, iscan: &default_iscan_16x16 }, + SCAN_ORDER { scan: &mrow_scan_16x16, iscan: &mrow_iscan_16x16 }, + SCAN_ORDER { scan: &mcol_scan_16x16, iscan: &mcol_iscan_16x16 }, + SCAN_ORDER { scan: &mrow_scan_16x16, iscan: &mrow_iscan_16x16 }, + SCAN_ORDER { scan: &mcol_scan_16x16, iscan: &mcol_iscan_16x16 }, + SCAN_ORDER { scan: &mrow_scan_16x16, iscan: &mrow_iscan_16x16 }, + SCAN_ORDER { scan: &mcol_scan_16x16, iscan: &mcol_iscan_16x16 }, + ], + [ + // TX_32X32 + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + ], + [ + // TX_64X64 + // Half of the coefficients of tx64 at higher frequencies are set to + // zeros. So tx32's scan order is used. + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + ], + [ + // TX_4X8 + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &default_scan_4x8, iscan: &default_iscan_4x8 }, + SCAN_ORDER { scan: &mrow_scan_4x8, iscan: &mrow_iscan_4x8 }, + SCAN_ORDER { scan: &mcol_scan_4x8, iscan: &mcol_iscan_4x8 }, + SCAN_ORDER { scan: &mrow_scan_4x8, iscan: &mrow_iscan_4x8 }, + SCAN_ORDER { scan: &mcol_scan_4x8, iscan: &mcol_iscan_4x8 }, + SCAN_ORDER { scan: &mrow_scan_4x8, iscan: &mrow_iscan_4x8 }, + SCAN_ORDER { scan: &mcol_scan_4x8, iscan: &mcol_iscan_4x8 }, + ], + [ + // TX_8X4 + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &default_scan_8x4, iscan: &default_iscan_8x4 }, + SCAN_ORDER { scan: &mrow_scan_8x4, iscan: &mrow_iscan_8x4 }, + SCAN_ORDER { scan: &mcol_scan_8x4, iscan: &mcol_iscan_8x4 }, + SCAN_ORDER { scan: &mrow_scan_8x4, iscan: &mrow_iscan_8x4 }, + SCAN_ORDER { scan: &mcol_scan_8x4, iscan: &mcol_iscan_8x4 }, + SCAN_ORDER { scan: &mrow_scan_8x4, iscan: &mrow_iscan_8x4 }, + SCAN_ORDER { scan: &mcol_scan_8x4, iscan: &mcol_iscan_8x4 }, + ], + [ + // TX_8X16 + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &default_scan_8x16, iscan: &default_iscan_8x16 }, + SCAN_ORDER { scan: &mrow_scan_8x16, iscan: &mrow_iscan_8x16 }, + SCAN_ORDER { scan: &mcol_scan_8x16, iscan: &mcol_iscan_8x16 }, + SCAN_ORDER { scan: &mrow_scan_8x16, iscan: &mrow_iscan_8x16 }, + SCAN_ORDER { scan: &mcol_scan_8x16, iscan: &mcol_iscan_8x16 }, + SCAN_ORDER { scan: &mrow_scan_8x16, iscan: &mrow_iscan_8x16 }, + SCAN_ORDER { scan: &mcol_scan_8x16, iscan: &mcol_iscan_8x16 }, + ], + [ + // TX_16X8 + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &default_scan_16x8, iscan: &default_iscan_16x8 }, + SCAN_ORDER { scan: &mrow_scan_16x8, iscan: &mrow_iscan_16x8 }, + SCAN_ORDER { scan: &mcol_scan_16x8, iscan: &mcol_iscan_16x8 }, + SCAN_ORDER { scan: &mrow_scan_16x8, iscan: &mrow_iscan_16x8 }, + SCAN_ORDER { scan: &mcol_scan_16x8, iscan: &mcol_iscan_16x8 }, + SCAN_ORDER { scan: &mrow_scan_16x8, iscan: &mrow_iscan_16x8 }, + SCAN_ORDER { scan: &mcol_scan_16x8, iscan: &mcol_iscan_16x8 }, + ], + [ + // TX_16X32 + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + ], + [ + // TX_32X16 + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + ], + [ + // TX_32X64 + // Half of the coefficients of tx64 at higher frequencies are set to + // zeros. So tx32's scan order is used. + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + ], + [ + // TX_64X32 + // Half of the coefficients of tx64 at higher frequencies are set to + // zeros. So tx32's scan order is used. + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &default_scan_32x32, iscan: &default_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + SCAN_ORDER { scan: &mrow_scan_32x32, iscan: &mrow_iscan_32x32 }, + SCAN_ORDER { scan: &mcol_scan_32x32, iscan: &mcol_iscan_32x32 }, + ], + [ + // TX_4X16 + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &default_scan_4x16, iscan: &default_iscan_4x16 }, + SCAN_ORDER { scan: &mrow_scan_4x16, iscan: &mrow_iscan_4x16 }, + SCAN_ORDER { scan: &mcol_scan_4x16, iscan: &mcol_iscan_4x16 }, + SCAN_ORDER { scan: &mrow_scan_4x16, iscan: &mrow_iscan_4x16 }, + SCAN_ORDER { scan: &mcol_scan_4x16, iscan: &mcol_iscan_4x16 }, + SCAN_ORDER { scan: &mrow_scan_4x16, iscan: &mrow_iscan_4x16 }, + SCAN_ORDER { scan: &mcol_scan_4x16, iscan: &mcol_iscan_4x16 }, + ], + [ + // TX_16X4 + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &default_scan_16x4, iscan: &default_iscan_16x4 }, + SCAN_ORDER { scan: &mrow_scan_16x4, iscan: &mrow_iscan_16x4 }, + SCAN_ORDER { scan: &mcol_scan_16x4, iscan: &mcol_iscan_16x4 }, + SCAN_ORDER { scan: &mrow_scan_16x4, iscan: &mrow_iscan_16x4 }, + SCAN_ORDER { scan: &mcol_scan_16x4, iscan: &mcol_iscan_16x4 }, + SCAN_ORDER { scan: &mrow_scan_16x4, iscan: &mrow_iscan_16x4 }, + SCAN_ORDER { scan: &mcol_scan_16x4, iscan: &mcol_iscan_16x4 }, + ], + [ + // TX_8X32 + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &default_scan_8x32, iscan: &default_iscan_8x32 }, + SCAN_ORDER { scan: &mrow_scan_8x32, iscan: &mrow_iscan_8x32 }, + SCAN_ORDER { scan: &mcol_scan_8x32, iscan: &mcol_iscan_8x32 }, + SCAN_ORDER { scan: &mrow_scan_8x32, iscan: &mrow_iscan_8x32 }, + SCAN_ORDER { scan: &mcol_scan_8x32, iscan: &mcol_iscan_8x32 }, + SCAN_ORDER { scan: &mrow_scan_8x32, iscan: &mrow_iscan_8x32 }, + SCAN_ORDER { scan: &mcol_scan_8x32, iscan: &mcol_iscan_8x32 }, + ], + [ + // TX_32X8 + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &default_scan_32x8, iscan: &default_iscan_32x8 }, + SCAN_ORDER { scan: &mrow_scan_32x8, iscan: &mrow_iscan_32x8 }, + SCAN_ORDER { scan: &mcol_scan_32x8, iscan: &mcol_iscan_32x8 }, + SCAN_ORDER { scan: &mrow_scan_32x8, iscan: &mrow_iscan_32x8 }, + SCAN_ORDER { scan: &mcol_scan_32x8, iscan: &mcol_iscan_32x8 }, + SCAN_ORDER { scan: &mrow_scan_32x8, iscan: &mrow_iscan_32x8 }, + SCAN_ORDER { scan: &mcol_scan_32x8, iscan: &mcol_iscan_32x8 }, + ], + [ + // TX_16X64 + // Half of the coefficients of tx64 at higher frequencies are set to + // zeros. So tx32's scan order is used. + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &default_scan_16x32, iscan: &default_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + SCAN_ORDER { scan: &mrow_scan_16x32, iscan: &mrow_iscan_16x32 }, + SCAN_ORDER { scan: &mcol_scan_16x32, iscan: &mcol_iscan_16x32 }, + ], + [ + // TX_64X16 + // Half of the coefficients of tx64 at higher frequencies are set to + // zeros. So tx32's scan order is used. + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &default_scan_32x16, iscan: &default_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + SCAN_ORDER { scan: &mrow_scan_32x16, iscan: &mrow_iscan_32x16 }, + SCAN_ORDER { scan: &mcol_scan_32x16, iscan: &mcol_iscan_32x16 }, + ], +]; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/segmentation.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/segmentation.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/segmentation.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/segmentation.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,196 @@ +// Copyright (c) 2018-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::context::*; +use crate::header::PRIMARY_REF_NONE; +use crate::partition::BlockSize; +use crate::rdo::spatiotemporal_scale; +use crate::rdo::DistortionScale; +use crate::tiling::TileStateMut; +use crate::util::Pixel; +use crate::FrameInvariants; +use crate::FrameState; + +pub const MAX_SEGMENTS: usize = 8; + +#[profiling::function] +pub fn segmentation_optimize( + fi: &FrameInvariants, fs: &mut FrameState, +) { + assert!(fi.enable_segmentation); + fs.segmentation.enabled = true; + + if fs.segmentation.enabled { + fs.segmentation.update_map = true; + + // We don't change the values between frames. + fs.segmentation.update_data = fi.primary_ref_frame == PRIMARY_REF_NONE; + + // Avoid going into lossless mode by never bringing qidx below 1. + // Because base_q_idx changes more frequently than the segmentation + // data, it is still possible for a segment to enter lossless, so + // enforcement elsewhere is needed. + let offset_lower_limit = 1 - fi.base_q_idx as i16; + + if !fs.segmentation.update_data { + let mut min_segment = MAX_SEGMENTS; + for i in 0..MAX_SEGMENTS { + if fs.segmentation.features[i][SegLvl::SEG_LVL_ALT_Q as usize] + && fs.segmentation.data[i][SegLvl::SEG_LVL_ALT_Q as usize] + >= offset_lower_limit + { + min_segment = i; + break; + } + } + assert_ne!(min_segment, MAX_SEGMENTS); + fs.segmentation.min_segment = min_segment as u8; + fs.segmentation.update_threshold(fi.base_q_idx, fi.config.bit_depth); + return; + } + + segmentation_optimize_inner(fi, fs, offset_lower_limit); + + /* Figure out parameters */ + fs.segmentation.preskip = false; + fs.segmentation.last_active_segid = 0; + for i in 0..MAX_SEGMENTS { + for j in 0..SegLvl::SEG_LVL_MAX as usize { + if fs.segmentation.features[i][j] { + fs.segmentation.last_active_segid = i as u8; + if j >= SegLvl::SEG_LVL_REF_FRAME as usize { + fs.segmentation.preskip = true; + } + } + } + } + } +} + +// Select target quantizers for each segment by fitting to log(scale). +fn segmentation_optimize_inner( + fi: &FrameInvariants, fs: &mut FrameState, offset_lower_limit: i16, +) { + use crate::quantize::{ac_q, select_ac_qi}; + use crate::util::kmeans; + use arrayvec::ArrayVec; + + // Minimize the total distance from a small set of values to all scales. + // Find k-means of log(spatiotemporal scale), k in 3..=8 + let c: ([_; 8], [_; 7], [_; 6], [_; 5], [_; 4], [_; 3]) = { + let spatiotemporal_scores = + &fi.coded_frame_data.as_ref().unwrap().spatiotemporal_scores; + let mut log2_scale_q11 = Vec::with_capacity(spatiotemporal_scores.len()); + log2_scale_q11.extend(spatiotemporal_scores.iter().map(|&s| s.blog16())); + log2_scale_q11.sort_unstable(); + let l = &log2_scale_q11; + (kmeans(l), kmeans(l), kmeans(l), kmeans(l), kmeans(l), kmeans(l)) + }; + + // Find variance in spacing between successive log(scale) + let var = |c: &[i16]| { + let delta = ArrayVec::<_, MAX_SEGMENTS>::from_iter( + c.iter().skip(1).zip(c).map(|(&a, &b)| b as i64 - a as i64), + ); + let mean = delta.iter().sum::() / delta.len() as i64; + delta.iter().map(|&d| (d - mean).pow(2)).sum::() as u64 + }; + let variance = + [var(&c.0), var(&c.1), var(&c.2), var(&c.3), var(&c.4), var(&c.5)]; + + // Choose the k value with minimal variance in spacing + let min_variance = *variance.iter().min().unwrap(); + let position = variance.iter().rposition(|&v| v == min_variance).unwrap(); + + // For the selected centroids, derive a target quantizer: + // scale Q'^2 = Q^2 + // See `distortion_scale_for` for more information. + let compute_delta = |centroids: &[i16]| { + use crate::util::{bexp64, blog64}; + let log2_base_ac_q_q57 = + blog64(ac_q(fi.base_q_idx, 0, fi.config.bit_depth).get().into()); + centroids + .iter() + .rev() + // Rewrite in log form and exponentiate: + // scale Q'^2 = Q^2 + // Q' = Q / sqrt(scale) + // log(Q') = log(Q) - 0.5 log(scale) + .map(|&log2_scale_q11| { + bexp64(log2_base_ac_q_q57 - ((log2_scale_q11 as i64) << (57 - 11 - 1))) + }) + // Find the index of the nearest quantizer to the target, + // and take the delta from the base quantizer index. + .map(|q| { + // Avoid going into lossless mode by never bringing qidx below 1. + select_ac_qi(q, fi.config.bit_depth).max(1) as i16 + - fi.base_q_idx as i16 + }) + .collect::>() + }; + + // Compute segment deltas for best value of k + let seg_delta = match position { + 0 => compute_delta(&c.0), + 1 => compute_delta(&c.1), + 2 => compute_delta(&c.2), + 3 => compute_delta(&c.3), + 4 => compute_delta(&c.4), + _ => compute_delta(&c.5), + }; + + // Update the segmentation data + fs.segmentation.min_segment = 0; + fs.segmentation.max_segment = seg_delta.len() as u8 - 1; + for (&delta, (features, data)) in seg_delta + .iter() + .zip(fs.segmentation.features.iter_mut().zip(&mut fs.segmentation.data)) + { + features[SegLvl::SEG_LVL_ALT_Q as usize] = true; + data[SegLvl::SEG_LVL_ALT_Q as usize] = delta.max(offset_lower_limit); + } + + fs.segmentation.update_threshold(fi.base_q_idx, fi.config.bit_depth); +} + +#[profiling::function] +pub fn select_segment( + fi: &FrameInvariants, ts: &TileStateMut<'_, T>, tile_bo: TileBlockOffset, + bsize: BlockSize, skip: bool, +) -> std::ops::RangeInclusive { + // If skip is true or segmentation is turned off, sidx is not coded. + if skip || !fi.enable_segmentation { + return 0..=0; + } + + use crate::api::SegmentationLevel; + if fi.config.speed_settings.segmentation == SegmentationLevel::Full { + return ts.segmentation.min_segment..=ts.segmentation.max_segment; + } + + let frame_bo = ts.to_frame_block_offset(tile_bo); + let scale = spatiotemporal_scale(fi, frame_bo, bsize); + + let sidx = segment_idx_from_distortion(&ts.segmentation.threshold, scale); + + // Avoid going into lossless mode by never bringing qidx below 1. + let sidx = sidx.max(ts.segmentation.min_segment); + + if fi.config.speed_settings.segmentation == SegmentationLevel::Complex { + return sidx..=ts.segmentation.max_segment.min(sidx.saturating_add(1)); + } + + sidx..=sidx +} + +fn segment_idx_from_distortion( + threshold: &[DistortionScale; MAX_SEGMENTS - 1], s: DistortionScale, +) -> u8 { + threshold.partition_point(|&t| s.0 < t.0) as u8 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/stats.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/stats.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/stats.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/stats.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,87 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::partition::BlockSize; +use crate::predict::PREDICTION_MODES; +use crate::serialize::{Deserialize, Serialize}; +use crate::transform::TX_TYPES; + +#[cfg(feature = "serialize")] +use serde_big_array::BigArray; + +use std::ops::{Add, AddAssign}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct EncoderStats { + /// Stores count of pixels belonging to each block size in this frame + pub block_size_counts: [usize; BlockSize::BLOCK_SIZES_ALL], + /// Stores count of pixels belonging to skip blocks in this frame + pub skip_block_count: usize, + /// Stores count of pixels belonging to each transform type in this frame + pub tx_type_counts: [usize; TX_TYPES], + /// Stores count of pixels belonging to each luma prediction mode in this frame + #[serde(with = "BigArray")] + pub luma_pred_mode_counts: [usize; PREDICTION_MODES], + /// Stores count of pixels belonging to each chroma prediction mode in this frame + #[serde(with = "BigArray")] + pub chroma_pred_mode_counts: [usize; PREDICTION_MODES], +} + +impl Default for EncoderStats { + fn default() -> Self { + let luma_pred_mode_counts = [0; PREDICTION_MODES]; + let chroma_pred_mode_counts = [0; PREDICTION_MODES]; + EncoderStats { + block_size_counts: [0; BlockSize::BLOCK_SIZES_ALL], + skip_block_count: 0, + tx_type_counts: [0; TX_TYPES], + luma_pred_mode_counts, + chroma_pred_mode_counts, + } + } +} + +impl Add<&Self> for EncoderStats { + type Output = Self; + + fn add(self, rhs: &EncoderStats) -> Self::Output { + let mut lhs = self; + lhs += rhs; + lhs + } +} + +impl AddAssign<&Self> for EncoderStats { + fn add_assign(&mut self, rhs: &EncoderStats) { + for (s, v) in + self.block_size_counts.iter_mut().zip(rhs.block_size_counts.iter()) + { + *s += v; + } + for (s, v) in self + .chroma_pred_mode_counts + .iter_mut() + .zip(rhs.chroma_pred_mode_counts.iter()) + { + *s += v; + } + for (s, v) in self + .luma_pred_mode_counts + .iter_mut() + .zip(rhs.luma_pred_mode_counts.iter()) + { + *s += v; + } + for (s, v) in self.tx_type_counts.iter_mut().zip(rhs.tx_type_counts.iter()) + { + *s += v; + } + self.skip_block_count += rhs.skip_block_count; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/aom.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/aom.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/aom.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/aom.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,174 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; +use crate::test_encode_decode::{compare_plane, DecodeResult, TestDecoder}; +use crate::util::Pixel; +use aom_sys::*; +use log::debug; +use std::collections::VecDeque; +use std::ffi::CStr; +use std::marker::PhantomData; +use std::{mem::MaybeUninit, ptr, slice}; + +pub(crate) struct AomDecoder { + dec: aom_codec_ctx, + iter: aom_codec_iter_t, + pixel: PhantomData, +} + +impl TestDecoder for AomDecoder { + fn setup_decoder(w: usize, h: usize) -> Self { + unsafe { + let interface = aom_codec_av1_dx(); + let cfg = aom_codec_dec_cfg_t { + threads: 1, + w: w as u32, + h: h as u32, + allow_lowbitdepth: 1, + }; + + let mut dec = MaybeUninit::uninit(); + let ret = aom_codec_dec_init_ver( + dec.as_mut_ptr(), + interface, + &cfg, + 0, + AOM_DECODER_ABI_VERSION as i32, + ); + if ret != 0 { + panic!("Cannot instantiate the decoder {}", ret); + } + + // Was initialized by aom_codec_dec_init_ver(). + let dec = dec.assume_init(); + AomDecoder { dec, iter: ptr::null_mut(), pixel: PhantomData } + } + } + + fn decode_packet( + &mut self, packet: &[u8], rec_fifo: &mut VecDeque>, w: usize, + h: usize, chroma_sampling: ChromaSampling, bit_depth: usize, verify: bool, + ) -> DecodeResult { + let mut corrupted_count = 0; + unsafe { + let ret = aom_codec_decode( + &mut self.dec, + packet.as_ptr(), + packet.len(), + ptr::null_mut(), + ); + debug!("Decoded. -> {}", ret); + if ret != 0 { + let error_msg = aom_codec_error(&mut self.dec); + debug!( + " Decode codec_decode failed: {}", + CStr::from_ptr(error_msg).to_string_lossy() + ); + let detail = aom_codec_error_detail(&mut self.dec); + if !detail.is_null() { + debug!( + " Decode codec_decode failed {}", + CStr::from_ptr(detail).to_string_lossy() + ); + } + + corrupted_count += 1; + } + + if ret == 0 { + loop { + debug!("Retrieving frame"); + let img = aom_codec_get_frame(&mut self.dec, &mut self.iter); + debug!("Retrieved."); + if img.is_null() { + return DecodeResult::Done; + } + let mut corrupted = 0; + let ret = aom_codec_control( + &mut self.dec, + aom_dec_control_id::AOMD_GET_FRAME_CORRUPTED as i32, + &mut corrupted, + ); + if ret != 0 { + let detail = aom_codec_error_detail(&mut self.dec); + panic!( + "Decode codec_control failed {}", + CStr::from_ptr(detail).to_string_lossy() + ); + } + corrupted_count += corrupted; + + if verify { + let rec = rec_fifo.pop_front().unwrap(); + compare_img(img, &rec, bit_depth, w, h, chroma_sampling); + } + } + } + } + if corrupted_count > 0 { + DecodeResult::Corrupted(corrupted_count) + } else { + DecodeResult::NotDone + } + } +} + +impl Drop for AomDecoder { + fn drop(&mut self) { + unsafe { aom_codec_destroy(&mut self.dec) }; + } +} + +fn compare_img( + img: *const aom_image_t, frame: &Frame, bit_depth: usize, width: usize, + height: usize, chroma_sampling: ChromaSampling, +) { + let img = unsafe { *img }; + let img_iter = img.planes.iter().zip(img.stride.iter()); + let planes = if chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; + + for (pli, (img_plane, frame_plane)) in + img_iter.zip(frame.planes.iter()).enumerate().take(planes) + { + let w = width >> frame_plane.cfg.xdec; + let h = height >> frame_plane.cfg.ydec; + let rec_stride = frame_plane.cfg.stride; + + if bit_depth > 8 { + let dec_stride = *img_plane.1 as usize / 2; + + let dec = unsafe { + let data = *img_plane.0 as *const u16; + let size = dec_stride * h; + + slice::from_raw_parts(data, size) + }; + + let rec: Vec = + frame_plane.data_origin().iter().map(|&v| u16::cast_from(v)).collect(); + + compare_plane::(&rec[..], rec_stride, dec, dec_stride, w, h, pli); + } else { + let dec_stride = *img_plane.1 as usize; + + let dec = unsafe { + let data = *img_plane.0 as *const u8; + let size = dec_stride * h; + + slice::from_raw_parts(data, size) + }; + + let rec: Vec = + frame_plane.data_origin().iter().map(|&v| u8::cast_from(v)).collect(); + + compare_plane::(&rec[..], rec_stride, dec, dec_stride, w, h, pli); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/dav1d.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/dav1d.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/dav1d.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/dav1d.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,185 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; +use crate::test_encode_decode::{compare_plane, DecodeResult, TestDecoder}; +use crate::util::{CastFromPrimitive, Pixel}; +use log::debug; +use std::collections::VecDeque; +use std::marker::PhantomData; +use std::os::raw::c_int; +use std::{ + mem::{self, MaybeUninit}, + ptr, slice, +}; + +use dav1d_sys::*; + +pub(crate) struct Dav1dDecoder { + dec: *mut Dav1dContext, + pixel: PhantomData, +} + +impl TestDecoder for Dav1dDecoder { + fn setup_decoder(_w: usize, _h: usize) -> Self { + unsafe { + let mut settings = MaybeUninit::uninit(); + dav1d_default_settings(settings.as_mut_ptr()); + + // Was initialized by dav1d_default_settings(). + let settings = settings.assume_init(); + + let mut dec: Dav1dDecoder = + Dav1dDecoder { dec: ptr::null_mut(), pixel: PhantomData }; + let ret = dav1d_open(&mut dec.dec, &settings); + + if ret != 0 { + panic!("Cannot instantiate the decoder {}", ret); + } + + dec + } + } + + fn decode_packet( + &mut self, packet: &[u8], rec_fifo: &mut VecDeque>, w: usize, + h: usize, chroma_sampling: ChromaSampling, bit_depth: usize, verify: bool, + ) -> DecodeResult { + let mut corrupted_count = 0; + let mut data = SafeDav1dData::new(packet); + let ret = data.send(self.dec); + debug!("Decoded. -> {}", ret); + if ret != 0 { + corrupted_count += 1; + } + + if ret == 0 { + loop { + let mut pic = SafeDav1dPicture::default(); + debug!("Retrieving frame"); + let ret = pic.get(self.dec); + debug!("Retrieved."); + if ret == DAV1D_ERR_AGAIN { + return DecodeResult::Done; + } + if ret != 0 { + panic!("Decode fail"); + } + + if verify { + let rec = rec_fifo.pop_front().unwrap(); + compare_pic(&pic.0, &rec, bit_depth, w, h, chroma_sampling); + } + } + } + if corrupted_count > 0 { + DecodeResult::Corrupted(corrupted_count) + } else { + DecodeResult::NotDone + } + } +} + +impl Drop for Dav1dDecoder { + fn drop(&mut self) { + unsafe { dav1d_close(&mut self.dec) }; + } +} + +struct SafeDav1dData(Dav1dData); + +impl SafeDav1dData { + fn new(packet: &[u8]) -> Self { + unsafe { + let mut data = Self { 0: mem::zeroed() }; + let ptr = dav1d_data_create(&mut data.0, packet.len()); + ptr::copy_nonoverlapping(packet.as_ptr(), ptr, packet.len()); + data + } + } + + fn send(&mut self, context: *mut Dav1dContext) -> c_int { + unsafe { dav1d_send_data(context, &mut self.0) } + } +} + +impl Drop for SafeDav1dData { + fn drop(&mut self) { + unsafe { dav1d_data_unref(&mut self.0) }; + } +} + +struct SafeDav1dPicture(Dav1dPicture); + +impl Default for SafeDav1dPicture { + fn default() -> Self { + Self { 0: unsafe { mem::zeroed() } } + } +} + +impl SafeDav1dPicture { + fn get(&mut self, context: *mut Dav1dContext) -> c_int { + unsafe { dav1d_get_picture(context, &mut self.0) } + } +} + +impl Drop for SafeDav1dPicture { + fn drop(&mut self) { + unsafe { dav1d_picture_unref(&mut self.0) } + } +} + +fn compare_pic( + pic: &Dav1dPicture, frame: &Frame, bit_depth: usize, width: usize, + height: usize, chroma_sampling: ChromaSampling, +) { + use crate::frame::Plane; + + let cmp_plane = |data, stride, frame_plane: &Plane, pli| { + let w = width >> frame_plane.cfg.xdec; + let h = height >> frame_plane.cfg.ydec; + let rec_stride = frame_plane.cfg.stride; + + if bit_depth > 8 { + let stride = stride / 2; + let dec = unsafe { + let data = data as *const u16; + let size = stride * h; + + slice::from_raw_parts(data, size) + }; + + let rec: Vec = + frame_plane.data_origin().iter().map(|&v| u16::cast_from(v)).collect(); + + compare_plane::(&rec[..], rec_stride, dec, stride, w, h, pli); + } else { + let dec = unsafe { + let data = data as *const u8; + let size = stride * h; + + slice::from_raw_parts(data, size) + }; + + let rec: Vec = + frame_plane.data_origin().iter().map(|&v| u8::cast_from(v)).collect(); + + compare_plane::(&rec[..], rec_stride, dec, stride, w, h, pli); + } + }; + + let lstride = pic.stride[0] as usize; + cmp_plane(pic.data[0], lstride, &frame.planes[0], 0); + + if chroma_sampling != ChromaSampling::Cs400 { + let cstride = pic.stride[1] as usize; + cmp_plane(pic.data[1], cstride, &frame.planes[1], 1); + cmp_plane(pic.data[2], cstride, &frame.planes[2], 2); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/test_encode_decode/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1073 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +// Fuzzing only uses a subset of these. +#![cfg_attr(fuzzing, allow(unused))] + +use crate::color::ChromaSampling; + +use crate::api::config::GrainTableSegment; +use crate::util::Pixel; +use crate::*; + +use arrayvec::ArrayVec; +use interpolate_name::interpolate_test; +use log::debug; +use rand::{Rng, SeedableRng}; +use rand_chacha::ChaChaRng; +use std::collections::VecDeque; + +#[cfg(feature = "decode_test")] +mod aom; +#[cfg(feature = "decode_test_dav1d")] +mod dav1d; + +#[cfg(feature = "decode_test")] +use aom::AomDecoder; +#[cfg(feature = "decode_test_dav1d")] +use dav1d::Dav1dDecoder; + +fn fill_frame(ra: &mut ChaChaRng, frame: &mut Frame) { + for plane in frame.planes.iter_mut() { + let stride = plane.cfg.stride; + for row in plane.data.chunks_mut(stride) { + for pixel in row { + let v: u8 = ra.random(); + *pixel = T::cast_from(v); + } + } + } +} + +fn read_frame_batch( + ctx: &mut Context, ra: &mut ChaChaRng, limit: usize, +) { + for _ in 0..limit { + let mut input = ctx.new_frame(); + fill_frame(ra, &mut input); + + let _ = ctx.send_frame(input); + } + + ctx.flush(); +} + +pub(crate) enum DecodeResult { + Done, + NotDone, + Corrupted(usize), +} + +pub(crate) trait TestDecoder { + fn setup_decoder(w: usize, h: usize) -> Self + where + Self: Sized; + fn encode_decode( + &mut self, verify: bool, w: usize, h: usize, speed: u8, quantizer: usize, + limit: usize, bit_depth: usize, chroma_sampling: ChromaSampling, + min_keyint: u64, max_keyint: u64, switch_frame_interval: u64, + low_latency: bool, error_resilient: bool, bitrate: i32, + tile_cols_log2: usize, tile_rows_log2: usize, still_picture: bool, + grain_table: Option>, + ) { + let mut ra = ChaChaRng::from_seed([0; 32]); + + let mut ctx: Context = setup_encoder( + w, + h, + speed, + quantizer, + bit_depth, + chroma_sampling, + min_keyint, + max_keyint, + switch_frame_interval, + low_latency, + error_resilient, + bitrate, + tile_cols_log2, + tile_rows_log2, + still_picture, + grain_table, + ); + + debug!( + "Encoding {}x{} speed {} quantizer {} bit-depth {} bitrate {}", + w, h, speed, quantizer, bit_depth, bitrate + ); + #[cfg(feature = "dump_ivf")] + let mut out = std::fs::File::create(&format!( + "out-{}x{}-s{}-q{}-r{}-{:?}.ivf", + w, h, speed, quantizer, bitrate, chroma_sampling + )) + .unwrap(); + #[cfg(feature = "dump_ivf")] + ivf::write_ivf_header(&mut out, w, h, 30, 1); + + let mut rec_fifo = VecDeque::new(); + read_frame_batch(&mut ctx, &mut ra, limit); + + for _ in 0..limit { + let mut corrupted_count = 0; + loop { + let res = ctx.receive_packet(); + if let Ok(pkt) = res { + debug!("Encoded packet {}", pkt.input_frameno); + + #[cfg(feature = "dump_ivf")] + ivf::write_ivf_frame(&mut out, pkt.input_frameno, &pkt.data); + + if let Some(pkt_rec) = pkt.rec { + rec_fifo.push_back((*pkt_rec).clone()); + } + let packet = pkt.data; + debug!("Decoding frame {}", pkt.input_frameno); + match self.decode_packet( + &packet, + &mut rec_fifo, + w, + h, + chroma_sampling, + bit_depth, + verify, + ) { + DecodeResult::Done => { + break; + } + DecodeResult::NotDone => {} + DecodeResult::Corrupted(corrupted) => { + corrupted_count += corrupted; + } + } + } else { + break; + } + } + assert_eq!(corrupted_count, 0); + } + } + fn decode_packet( + &mut self, packet: &[u8], rec_fifo: &mut VecDeque>, w: usize, + h: usize, chroma_sampling: ChromaSampling, bit_depth: usize, verify: bool, + ) -> DecodeResult; +} + +pub fn compare_plane( + rec: &[T], rec_stride: usize, dec: &[T], dec_stride: usize, width: usize, + height: usize, pli: usize, +) { + for (row, line) in + rec.chunks(rec_stride).zip(dec.chunks(dec_stride)).take(height).enumerate() + { + assert_eq!( + &line.0[..width], + &line.1[..width], + "at row {} of plane {}", + row, + pli + ); + } +} + +fn setup_encoder( + w: usize, h: usize, speed: u8, quantizer: usize, bit_depth: usize, + chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64, + switch_frame_interval: u64, low_latency: bool, error_resilient: bool, + bitrate: i32, tile_cols_log2: usize, tile_rows_log2: usize, + still_picture: bool, grain_table: Option>, +) -> Context { + assert!(bit_depth == 8 || std::mem::size_of::() > 1); + let mut enc = EncoderConfig::with_speed_preset(speed); + enc.quantizer = quantizer; + enc.min_key_frame_interval = min_keyint; + enc.max_key_frame_interval = max_keyint; + enc.switch_frame_interval = switch_frame_interval; + enc.low_latency = low_latency; + enc.error_resilient = error_resilient; + enc.width = w; + enc.height = h; + enc.bit_depth = bit_depth; + enc.chroma_sampling = chroma_sampling; + enc.bitrate = bitrate; + enc.tile_cols = 1 << tile_cols_log2; + enc.tile_rows = 1 << tile_rows_log2; + enc.still_picture = still_picture; + enc.film_grain_params = grain_table; + + let threads = if cfg!(fuzzing) { 1 } else { 2 }; + + let cfg = Config::new().with_encoder_config(enc).with_threads(threads); + + cfg.new_context().unwrap() +} + +// TODO: support non-multiple-of-16 dimensions +static DIMENSION_OFFSETS: &[(usize, usize)] = + &[(0, 0), (4, 4), (8, 8), (16, 16)]; + +fn speed(s: u8, decoder: &str) { + let quantizer = 100; + let limit = 5; + let w = 64; + let h = 80; + + for b in DIMENSION_OFFSETS.iter() { + let w = w + b.0; + let h = h + b.1; + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + s, + quantizer, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); + } +} + +macro_rules! test_speeds { + ($($S:expr),+) => { + $( + paste::item!{ + #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] + #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] + #[ignore] + fn [](decoder: &str) { + speed($S, decoder) + } + } + )* + } +} + +test_speeds! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } + +macro_rules! test_dimensions { + ($(($W:expr, $H:expr)),+) => { + $( + paste::item!{ + #[cfg_attr(feature = "decode_test", interpolate_name::interpolate_test(aom, "aom"))] + #[cfg_attr(feature = "decode_test_dav1d", interpolate_name::interpolate_test(dav1d, "dav1d"))] + fn [](decoder: &str) { + super::dimension($W, $H, decoder) + } + } + )* + } +} + +#[cfg(not(feature = "quick_test"))] +mod large_dimension { + test_dimensions! { + (512, 512), + (1024, 1024), + (2048, 2048) + } +} + +mod small_dimension { + test_dimensions! { + (256, 256), + (258, 258), + (260, 260), + (262, 262), + (264, 264), + (265, 265) + } +} + +mod tiny_dimension { + test_dimensions! { + (1, 1), + (2, 2), + (4, 4), + (8, 8), + (16, 16), + (32, 32), + (64, 64), + (128, 128) + } +} + +fn dimension(w: usize, h: usize, decoder: &str) { + let quantizer = 100; + let limit = 1; + let speed = 10; + let still_picture = w < 16 || h < 16; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + quantizer, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + still_picture, + None, + ); +} + +fn quantizer(decoder: &str, q: usize) { + let limit = 5; + let w = 64; + let h = 80; + let speed = 10; + + for b in DIMENSION_OFFSETS.iter() { + let mut dec = get_decoder::(decoder, b.0, b.1); + dec.encode_decode( + true, + w + b.0, + h + b.1, + speed, + q, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); + } +} + +macro_rules! test_quantizer { + ($($Q:expr),+) => { + $( + paste::item!{ + #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] + #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] + fn [](decoder: &str) { + quantizer(decoder, $Q); + } + } + )* + } +} + +test_quantizer! {60, 80, 100, 120} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn bitrate(decoder: &str) { + let limit = 5; + let w = 64; + let h = 80; + let speed = 10; + + for &q in [172, 220, 252, 255].iter() { + for &r in [100, 1000, 10_000].iter() { + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + r, + 0, + 0, + false, + None, + ); + } + } +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn keyframes(decoder: &str) { + let limit = 12; + let w = 64; + let h = 80; + let speed = 9; + let q = 100; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + 6, + 6, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn reordering(decoder: &str) { + let limit = 12; + let w = 64; + let h = 80; + let speed = 10; + let q = 100; + + for keyint in &[4, 5, 6] { + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + *keyint, + *keyint, + 0, + false, + false, + 0, + 0, + 0, + false, + None, + ); + } +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn reordering_short_video(decoder: &str) { + // Regression test for https://github.com/xiph/rav1e/issues/890 + let limit = 2; + let w = 64; + let h = 80; + let speed = 10; + let q = 100; + let keyint = 12; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + keyint, + keyint, + 0, + false, + false, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn error_resilient(decoder: &str) { + let limit = 2; + let w = 64; + let h = 80; + let speed = 10; + let q = 100; + let keyint = 12; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + keyint, + keyint, + 0, + true, + true, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn error_resilient_reordering(decoder: &str) { + let limit = 6; + let w = 64; + let h = 80; + let speed = 10; + let q = 100; + + for keyint in &[4, 5, 6] { + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + *keyint, + *keyint, + 0, + false, + true, + 0, + 0, + 0, + false, + None, + ); + } +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn switch_frame(decoder: &str) { + let limit = 3; + let w = 64; + let h = 80; + let speed = 10; + let q = 100; + let keyint = 12; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + keyint, + keyint, + 1, + true, + true, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn odd_size_frame_with_full_rdo(decoder: &str) { + let limit = 3; + let w = 64 + 1; + let h = 128 - 1; + let speed = 0; + let qindex = 100; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + qindex, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn low_bit_depth(decoder: &str) { + let quantizer = 100; + let limit = 3; // Include inter frames + let speed = 0; // Test as many tools as possible + let w = 64; + let h = 80; + + // 8-bit + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + quantizer, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +fn high_bit_depth(decoder: &str, depth: usize) { + let quantizer = 100; + let limit = 3; // Include inter frames + let speed = 0; // Test as many tools as possible + let w = 64; + let h = 80; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + quantizer, + limit, + depth, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +macro_rules! test_high_bit_depth { + ($($B:expr),+) => { + $( + paste::item!{ + #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] + #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] + #[ignore] + fn [](decoder: &str) { + high_bit_depth(decoder, $B); + } + } + )* + } +} + +test_high_bit_depth! {10, 12} + +fn chroma_sampling(decoder: &str, cs: ChromaSampling) { + let quantizer = 100; + let limit = 3; // Include inter frames + let speed = 0; // Test as many tools as possible + let w = 64; + let h = 80; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, w, h, speed, quantizer, limit, 8, cs, 15, 15, 0, true, false, 0, 0, + 0, false, None, + ); +} + +macro_rules! test_chroma_sampling { + ($(($S:expr, $I:expr)),+) => { + $( + paste::item!{ + #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] + #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] + #[ignore] + fn [](decoder: &str) { + chroma_sampling(decoder, $I); + } + } + )* + } +} + +test_chroma_sampling! {(400, ChromaSampling::Cs400), (420, ChromaSampling::Cs420), +(422, ChromaSampling::Cs422), (444, ChromaSampling::Cs444)} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn tile_encoding_with_stretched_restoration_units(decoder: &str) { + let limit = 5; + let w = 256; + // the bottom tiles are small (their height is 140-128=12), so they will use stretched + // restoration units from their above neighbours + let h = 140; + let speed = 10; + let q = 100; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 2, + 2, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +fn still_picture_mode(decoder: &str) { + let limit = 1; + let w = 480; + let h = 304; + let speed = 6; + let qindex = 100; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + qindex, + limit, + 8, + Default::default(), + 0, + 0, + 0, + false, + false, + 0, + 0, + 0, + true, + None, + ); +} + +pub(crate) fn get_decoder( + decoder: &str, w: usize, h: usize, +) -> Box> { + match decoder { + #[cfg(feature = "decode_test")] + "aom" => Box::new(AomDecoder::::setup_decoder(w, h)), + #[cfg(feature = "decode_test_dav1d")] + "dav1d" => Box::new(Dav1dDecoder::::setup_decoder(w, h)), + _ => unimplemented!(), + } +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn rdo_loop_decision_lrf_sanity(decoder: &str) { + let limit = 2; + let w = 936; + let h = 1404; + let speed = 9; + let q = 240; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + 6, + 6, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn rdo_loop_decision_cdef_sanity(decoder: &str) { + let limit = 2; + let w = 1404; + let h = 936; + let speed = 9; + let q = 240; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + true, + w, + h, + speed, + q, + limit, + 8, + Default::default(), + 6, + 6, + 0, + true, + false, + 0, + 0, + 0, + false, + None, + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn film_grain_table_luma_only(decoder: &str) { + let quantizer = 100; + let limit = 5; // Include inter frames + let speed = 10; + let w = 64; + let h = 80; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + false, + w, + h, + speed, + quantizer, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + Some(vec![GrainTableSegment { + start_time: 0, + end_time: 9223372036854775807, + scaling_points_y: ArrayVec::from([ + [0, 20], + [20, 5], + [39, 4], + [59, 3], + [78, 3], + [98, 3], + [118, 3], + [137, 3], + [157, 3], + [177, 3], + [196, 3], + [216, 4], + [235, 4], + [255, 4], + ]), + scaling_points_cb: ArrayVec::new(), + scaling_points_cr: ArrayVec::new(), + scaling_shift: 8, + ar_coeff_lag: 0, + ar_coeffs_y: ArrayVec::new(), + ar_coeffs_cb: ArrayVec::try_from([0].as_slice()).unwrap(), + ar_coeffs_cr: ArrayVec::try_from([0].as_slice()).unwrap(), + ar_coeff_shift: 6, + cb_mult: 0, + cb_luma_mult: 0, + cb_offset: 0, + cr_mult: 0, + cr_luma_mult: 0, + cr_offset: 0, + overlap_flag: true, + chroma_scaling_from_luma: false, + grain_scale_shift: 0, + random_seed: 7391, + }]), + ); +} + +#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))] +#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))] +#[ignore] +fn film_grain_table_chroma(decoder: &str) { + let quantizer = 100; + let limit = 5; // Include inter frames + let speed = 10; + let w = 64; + let h = 80; + + let mut dec = get_decoder::(decoder, w as usize, h as usize); + dec.encode_decode( + false, + w, + h, + speed, + quantizer, + limit, + 8, + Default::default(), + 15, + 15, + 0, + true, + false, + 0, + 0, + 0, + false, + Some(vec![GrainTableSegment { + start_time: 0, + end_time: 9223372036854775807, + scaling_points_y: ArrayVec::from([ + [0, 0], + [20, 4], + [39, 3], + [59, 3], + [78, 3], + [98, 3], + [118, 4], + [137, 4], + [157, 4], + [177, 4], + [196, 4], + [216, 5], + [235, 5], + [255, 5], + ]), + scaling_points_cb: ArrayVec::from([ + [0, 0], + [28, 0], + [57, 0], + [85, 0], + [113, 0], + [142, 0], + [170, 0], + [198, 0], + [227, 0], + [255, 1], + ]), + scaling_points_cr: ArrayVec::from([ + [0, 0], + [28, 0], + [57, 0], + [85, 0], + [113, 0], + [142, 0], + [170, 0], + [198, 0], + [227, 0], + [255, 1], + ]), + scaling_shift: 8, + ar_coeff_lag: 0, + ar_coeffs_y: ArrayVec::new(), + ar_coeffs_cb: ArrayVec::try_from([0].as_slice()).unwrap(), + ar_coeffs_cr: ArrayVec::try_from([0].as_slice()).unwrap(), + ar_coeff_shift: 6, + cb_mult: 128, + cb_luma_mult: 192, + cb_offset: 256, + cr_mult: 128, + cr_luma_mult: 192, + cr_offset: 256, + overlap_flag: true, + chroma_scaling_from_luma: false, + grain_scale_shift: 0, + random_seed: 7391, + }]), + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +// Copyright (c) 2019-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(unused)] + +mod plane_region; +mod tile; +mod tile_blocks; +mod tile_motion_stats; +mod tile_restoration_state; +mod tile_state; +mod tiler; + +pub use self::plane_region::*; +pub use self::tile::*; +pub use self::tile_blocks::*; +pub use self::tile_motion_stats::*; +pub use self::tile_restoration_state::*; +pub use self::tile_state::*; +pub use self::tiler::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/plane_region.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/plane_region.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/plane_region.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/plane_region.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,787 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(clippy::iter_nth_zero)] + +use crate::context::*; +use crate::frame::*; +use crate::util::*; + +use std::iter::FusedIterator; +use std::marker::PhantomData; +use std::ops::{Index, IndexMut}; +use std::slice; + +/// Rectangle of a plane region, in pixels +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub struct Rect { + // coordinates relative to the plane origin (xorigin, yorigin) + pub x: isize, + pub y: isize, + pub width: usize, + pub height: usize, +} + +impl Rect { + #[inline(always)] + pub const fn decimated(&self, xdec: usize, ydec: usize) -> Self { + Self { + x: self.x >> xdec, + y: self.y >> ydec, + width: self.width >> xdec, + height: self.height >> ydec, + } + } + pub const fn to_area(&self) -> Area { + Area::Rect { x: self.x, y: self.y, width: self.width, height: self.height } + } +} + +// Structure to describe a rectangle area in several ways +// +// To retrieve a subregion from a region, we need to provide the subregion +// bounds, relative to its parent region. The subregion must always be included +// in its parent region. +// +// For that purpose, we could just use a rectangle (x, y, width, height), but +// this would be too cumbersome to use in practice. For example, we often need +// to pass a subregion from an offset, using the same bottom-right corner as +// its parent, or to pass a subregion expressed in block offset instead of +// pixel offset. +// +// Area provides a flexible way to describe a subregion. +#[derive(Debug, Clone, Copy)] +pub enum Area { + /// A well-defined rectangle + Rect { x: isize, y: isize, width: usize, height: usize }, + /// A rectangle starting at offset (x, y) and ending at the bottom-right + /// corner of the parent + StartingAt { x: isize, y: isize }, + /// A well-defined rectangle with offset expressed in blocks + BlockRect { bo: BlockOffset, width: usize, height: usize }, + /// a rectangle starting at given block offset until the bottom-right corner + /// of the parent + BlockStartingAt { bo: BlockOffset }, +} + +impl Area { + #[inline(always)] + /// Convert to a rectangle of pixels. + /// For a `BlockRect` and `BlockStartingAt`, for subsampled chroma planes, + /// the returned rect will be aligned to a 4x4 chroma block. + /// This is necessary for `compute_distortion` and `rdo_cfl_alpha` as + /// the subsampled chroma block covers multiple luma blocks. + pub const fn to_rect( + &self, xdec: usize, ydec: usize, parent_width: usize, parent_height: usize, + ) -> Rect { + match *self { + Area::Rect { x, y, width, height } => Rect { x, y, width, height }, + Area::StartingAt { x, y } => Rect { + x, + y, + width: (parent_width as isize - x) as usize, + height: (parent_height as isize - y) as usize, + }, + Area::BlockRect { bo, width, height } => Rect { + x: (bo.x >> xdec << BLOCK_TO_PLANE_SHIFT) as isize, + y: (bo.y >> ydec << BLOCK_TO_PLANE_SHIFT) as isize, + width, + height, + }, + Area::BlockStartingAt { bo } => { + let x = (bo.x >> xdec << BLOCK_TO_PLANE_SHIFT) as isize; + let y = (bo.y >> ydec << BLOCK_TO_PLANE_SHIFT) as isize; + Rect { + x, + y, + width: (parent_width as isize - x) as usize, + height: (parent_height as isize - y) as usize, + } + } + } + } +} + +/// Bounded region of a plane +/// +/// This allows to give access to a rectangular area of a plane without +/// giving access to the whole plane. +#[derive(Debug)] +pub struct PlaneRegion<'a, T: Pixel> { + data: *const T, // points to (plane_cfg.x, plane_cfg.y) + pub plane_cfg: &'a PlaneConfig, + // private to guarantee borrowing rules + rect: Rect, + phantom: PhantomData<&'a T>, +} + +/// Mutable bounded region of a plane +/// +/// This allows to give mutable access to a rectangular area of the plane +/// without giving access to the whole plane. +#[derive(Debug)] +pub struct PlaneRegionMut<'a, T: Pixel> { + data: *mut T, // points to (plane_cfg.x, plane_cfg.y) + pub plane_cfg: &'a PlaneConfig, + rect: Rect, + phantom: PhantomData<&'a mut T>, +} + +// common impl for PlaneRegion and PlaneRegionMut +macro_rules! plane_region_common { + // $name: PlaneRegion or PlaneRegionMut + // $as_ptr: as_ptr or as_mut_ptr + // $opt_mut: nothing or mut + ($name:ident, $as_ptr:ident $(,$opt_mut:tt)?) => { + impl<'a, T: Pixel> $name<'a, T> { + #[inline(always)] + pub fn is_null(&self) -> bool { + self.data.is_null() + } + + #[cold] + pub fn empty(plane_cfg : &'a PlaneConfig) -> Self { + return Self { + // SAFETY: This is actually pretty unsafe. + // This means we need to ensure that no other method on this struct + // can access data if the dimensions are 0. + data: unsafe { std::ptr::null_mut::() }, + plane_cfg, + rect: Rect::default(), + phantom: PhantomData, + } + } + + /// # Panics + /// + /// - If the configured dimensions are invalid + #[inline(always)] + pub fn from_slice(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { + if cfg.width == 0 || cfg.height == 0 { + return Self::empty(&cfg); + } + assert!(rect.x >= -(cfg.xorigin as isize)); + assert!(rect.y >= -(cfg.yorigin as isize)); + assert!(cfg.xorigin as isize + rect.x + rect.width as isize <= cfg.stride as isize); + assert!(cfg.yorigin as isize + rect.y + rect.height as isize <= cfg.alloc_height as isize); + + // SAFETY: The above asserts ensure we do not go OOB. + unsafe { Self::from_slice_unsafe(data, cfg, rect)} + } + + #[inline(always)] + pub unsafe fn from_slice_unsafe(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { + debug_assert!(rect.x >= -(cfg.xorigin as isize)); + debug_assert!(rect.y >= -(cfg.yorigin as isize)); + debug_assert!(cfg.xorigin as isize + rect.x + rect.width as isize <= cfg.stride as isize); + debug_assert!(cfg.yorigin as isize + rect.y + rect.height as isize <= cfg.alloc_height as isize); + + let origin = (cfg.yorigin as isize + rect.y) * cfg.stride as isize + cfg.xorigin as isize + rect.x; + Self { + data: data.$as_ptr().offset(origin), + plane_cfg: cfg, + rect, + phantom: PhantomData, + } + } + + #[inline(always)] + pub fn new(plane: &'a $($opt_mut)? Plane, rect: Rect) -> Self { + Self::from_slice(& $($opt_mut)? plane.data, &plane.cfg, rect) + } + + #[inline(always)] + pub fn new_from_plane(plane: &'a $($opt_mut)? Plane) -> Self { + let rect = Area::StartingAt { x: 0, y: 0 }.to_rect( + plane.cfg.xdec, + plane.cfg.ydec, + plane.cfg.stride - plane.cfg.xorigin, + plane.cfg.alloc_height - plane.cfg.yorigin, + ); + + // SAFETY: Area::StartingAt{}.to_rect is guaranteed to be the entire plane + unsafe { Self::from_slice_unsafe(& $($opt_mut)? plane.data, &plane.cfg, rect) } + } + + #[inline(always)] + pub fn data_ptr(&self) -> *const T { + self.data + } + + #[inline(always)] + pub fn rect(&self) -> &Rect { + &self.rect + } + + #[inline(always)] + pub fn rows_iter(&self) -> RowsIter<'_, T> { + RowsIter { + data: self.data, + stride: self.plane_cfg.stride, + width: self.rect.width, + remaining: self.rect.height, + phantom: PhantomData, + } + } + + pub fn vert_windows(&self, h: usize) -> VertWindows<'_, T> { + VertWindows { + data: self.data, + plane_cfg: self.plane_cfg, + remaining: (self.rect.height as isize - h as isize + 1).max(0) as usize, + output_rect: Rect { + x: self.rect.x, + y: self.rect.y, + width: self.rect.width, + height: h + } + } + } + + pub fn horz_windows(&self, w: usize) -> HorzWindows<'_, T> { + HorzWindows { + data: self.data, + plane_cfg: self.plane_cfg, + remaining: (self.rect.width as isize - w as isize + 1).max(0) as usize, + output_rect: Rect { + x: self.rect.x, + y: self.rect.y, + width: w, + height: self.rect.height + } + } + } + + /// Return a view to a subregion of the plane + /// + /// The subregion must be included in (i.e. must not exceed) this region. + /// + /// It is described by an `Area`, relative to this region. + /// + /// # Panics + /// + /// - If the requested dimensions are larger than the plane region size + /// + /// # Example + /// + /// ``` ignore + /// # use rav1e::tiling::*; + /// # fn f(region: &PlaneRegion<'_, u16>) { + /// // a subregion from (10, 8) to the end of the region + /// let subregion = region.subregion(Area::StartingAt { x: 10, y: 8 }); + /// # } + /// ``` + /// + /// ``` ignore + /// # use rav1e::context::*; + /// # use rav1e::tiling::*; + /// # fn f(region: &PlaneRegion<'_, u16>) { + /// // a subregion from the top-left of block (2, 3) having size (64, 64) + /// let bo = BlockOffset { x: 2, y: 3 }; + /// let subregion = region.subregion(Area::BlockRect { bo, width: 64, height: 64 }); + /// # } + /// ``` + #[inline(always)] + pub fn subregion(&self, area: Area) -> PlaneRegion<'_, T> { + if self.data.is_null() { + return PlaneRegion::empty(&self.plane_cfg); + } + let rect = area.to_rect( + self.plane_cfg.xdec, + self.plane_cfg.ydec, + self.rect.width, + self.rect.height, + ); + assert!(rect.x >= 0 && rect.x as usize <= self.rect.width); + assert!(rect.y >= 0 && rect.y as usize <= self.rect.height); + // SAFETY: The above asserts ensure we do not go outside the original rectangle. + let data = unsafe { + self.data.add(rect.y as usize * self.plane_cfg.stride + rect.x as usize) + }; + let absolute_rect = Rect { + x: self.rect.x + rect.x, + y: self.rect.y + rect.y, + width: rect.width, + height: rect.height, + }; + PlaneRegion { + data, + plane_cfg: &self.plane_cfg, + rect: absolute_rect, + phantom: PhantomData, + } + } + + // Return an equivalent PlaneRegion with origin homed to 0,0. Data + // pointer is not moved (0,0 points to the same pixel previously + // pointed to by old x,y). + #[inline(always)] + pub fn home(&self) -> Self { + let home_rect = Rect { + x: 0, + y: 0, + width: self.rect.width, + height: self.rect.height, + }; + + Self { + data: self.data, + plane_cfg: &self.plane_cfg, + rect: home_rect, + phantom: PhantomData, + } + } + + #[inline(always)] + pub fn to_frame_plane_offset(&self, tile_po: PlaneOffset) -> PlaneOffset { + PlaneOffset { + x: self.rect.x + tile_po.x, + y: self.rect.y + tile_po.y, + } + } + + #[inline(always)] + pub fn to_frame_block_offset(&self, tile_bo: TileBlockOffset) -> PlaneBlockOffset { + debug_assert!(self.rect.x >= 0); + debug_assert!(self.rect.y >= 0); + let PlaneConfig { xdec, ydec, .. } = self.plane_cfg; + debug_assert!(self.rect.x as usize % (MI_SIZE >> xdec) == 0); + debug_assert!(self.rect.y as usize % (MI_SIZE >> ydec) == 0); + let bx = self.rect.x as usize >> MI_SIZE_LOG2 - xdec; + let by = self.rect.y as usize >> MI_SIZE_LOG2 - ydec; + PlaneBlockOffset(BlockOffset { + x: bx + tile_bo.0.x, + y: by + tile_bo.0.y, + }) + } + + #[inline(always)] + pub fn to_frame_super_block_offset( + &self, + tile_sbo: TileSuperBlockOffset, + sb_size_log2: usize + ) -> PlaneSuperBlockOffset { + debug_assert!(sb_size_log2 == 6 || sb_size_log2 == 7); + debug_assert!(self.rect.x >= 0); + debug_assert!(self.rect.y >= 0); + let PlaneConfig { xdec, ydec, .. } = self.plane_cfg; + debug_assert!(self.rect.x as usize % (1 << sb_size_log2 - xdec) == 0); + debug_assert!(self.rect.y as usize % (1 << sb_size_log2 - ydec) == 0); + let sbx = self.rect.x as usize >> sb_size_log2 - xdec; + let sby = self.rect.y as usize >> sb_size_log2 - ydec; + PlaneSuperBlockOffset(SuperBlockOffset { + x: sbx + tile_sbo.0.x, + y: sby + tile_sbo.0.y, + }) + } + + /// Returns the frame block offset of the subregion. + #[inline(always)] + pub fn frame_block_offset(&self) -> PlaneBlockOffset { + self.to_frame_block_offset(TileBlockOffset(BlockOffset { x: 0, y: 0 })) + } + + pub(crate) fn scratch_copy(&self) -> Plane { + let &Rect { width, height, .. } = self.rect(); + let &PlaneConfig { xdec, ydec, .. } = self.plane_cfg; + let mut ret: Plane = Plane::new(width, height, xdec, ydec, 0, 0); + let mut dst: PlaneRegionMut = ret.as_region_mut(); + for (dst_row, src_row) in dst.rows_iter_mut().zip(self.rows_iter()) { + for (out, input) in dst_row.iter_mut().zip(src_row) { + *out = *input; + } + } + ret + } + } + + unsafe impl Send for $name<'_, T> {} + unsafe impl Sync for $name<'_, T> {} + + impl Index for $name<'_, T> { + type Output = [T]; + + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rect.height); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.plane_cfg.stride); + slice::from_raw_parts(ptr, self.rect.width) + } + } + } + } +} + +plane_region_common!(PlaneRegion, as_ptr); +plane_region_common!(PlaneRegionMut, as_mut_ptr, mut); + +impl PlaneRegionMut<'_, T> { + #[inline(always)] + pub fn data_ptr_mut(&mut self) -> *mut T { + self.data + } + + #[inline(always)] + pub fn rows_iter_mut(&mut self) -> RowsIterMut<'_, T> { + RowsIterMut { + data: self.data, + stride: self.plane_cfg.stride, + width: self.rect.width, + remaining: self.rect.height, + phantom: PhantomData, + } + } + + /// Return a mutable view to a subregion of the plane + /// + /// The subregion must be included in (i.e. must not exceed) this region. + /// + /// It is described by an `Area`, relative to this region. + /// + /// # Panics + /// + /// - If the targeted `area` is outside of the bounds of this plane region. + /// + /// # Example + /// + /// ``` ignore + /// # use rav1e::tiling::*; + /// # fn f(region: &mut PlaneRegionMut<'_, u16>) { + /// // a mutable subregion from (10, 8) having size (32, 32) + /// let subregion = region.subregion_mut(Area::Rect { x: 10, y: 8, width: 32, height: 32 }); + /// # } + /// ``` + /// + /// ``` ignore + /// # use rav1e::context::*; + /// # use rav1e::tiling::*; + /// # fn f(region: &mut PlaneRegionMut<'_, u16>) { + /// // a mutable subregion from the top-left of block (2, 3) to the end of the region + /// let bo = BlockOffset { x: 2, y: 3 }; + /// let subregion = region.subregion_mut(Area::BlockStartingAt { bo }); + /// # } + /// ``` + #[inline(always)] + pub fn subregion_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T> { + let rect = area.to_rect( + self.plane_cfg.xdec, + self.plane_cfg.ydec, + self.rect.width, + self.rect.height, + ); + assert!(rect.x >= 0 && rect.x as usize <= self.rect.width); + assert!(rect.y >= 0 && rect.y as usize <= self.rect.height); + // SAFETY: The above asserts ensure we do not go outside the original rectangle. + let data = unsafe { + self.data.add(rect.y as usize * self.plane_cfg.stride + rect.x as usize) + }; + let absolute_rect = Rect { + x: self.rect.x + rect.x, + y: self.rect.y + rect.y, + width: rect.width, + height: rect.height, + }; + PlaneRegionMut { + data, + plane_cfg: self.plane_cfg, + rect: absolute_rect, + phantom: PhantomData, + } + } + + #[inline(always)] + pub fn as_const(&self) -> PlaneRegion<'_, T> { + PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.rect, + phantom: PhantomData, + } + } +} + +impl IndexMut for PlaneRegionMut<'_, T> { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rect.height); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.plane_cfg.stride); + slice::from_raw_parts_mut(ptr, self.rect.width) + } + } +} + +/// Iterator over plane region rows +pub struct RowsIter<'a, T: Pixel> { + data: *const T, + stride: usize, + width: usize, + remaining: usize, + phantom: PhantomData<&'a T>, +} + +/// Mutable iterator over plane region rows +pub struct RowsIterMut<'a, T: Pixel> { + data: *mut T, + stride: usize, + width: usize, + remaining: usize, + phantom: PhantomData<&'a mut T>, +} + +impl<'a, T: Pixel> Iterator for RowsIter<'a, T> { + type Item = &'a [T]; + + #[inline(always)] + fn next(&mut self) -> Option { + if self.remaining > 0 { + // SAFETY: We verified that we have enough data left to not go OOB, + // assuming that `self.stride` and `self.width` are set correctly. + let row = unsafe { + let ptr = self.data; + self.data = self.data.add(self.stride); + slice::from_raw_parts(ptr, self.width) + }; + self.remaining -= 1; + Some(row) + } else { + None + } + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } +} + +impl<'a, T: Pixel> Iterator for RowsIterMut<'a, T> { + type Item = &'a mut [T]; + + #[inline(always)] + fn next(&mut self) -> Option { + if self.remaining > 0 { + // SAFETY: We verified that we have enough data left to not go OOB, + // assuming that `self.stride` and `self.width` are set correctly. + let row = unsafe { + let ptr = self.data; + self.data = self.data.add(self.stride); + slice::from_raw_parts_mut(ptr, self.width) + }; + self.remaining -= 1; + Some(row) + } else { + None + } + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } +} + +impl ExactSizeIterator for RowsIter<'_, T> {} +impl FusedIterator for RowsIter<'_, T> {} +impl ExactSizeIterator for RowsIterMut<'_, T> {} +impl FusedIterator for RowsIterMut<'_, T> {} + +pub struct VertWindows<'a, T: Pixel> { + data: *const T, + plane_cfg: &'a PlaneConfig, + remaining: usize, + output_rect: Rect, +} + +pub struct HorzWindows<'a, T: Pixel> { + data: *const T, + plane_cfg: &'a PlaneConfig, + remaining: usize, + output_rect: Rect, +} + +impl<'a, T: Pixel> Iterator for VertWindows<'a, T> { + type Item = PlaneRegion<'a, T>; + + #[inline(always)] + fn next(&mut self) -> Option { + self.nth(0) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } + + #[inline(always)] + fn nth(&mut self, n: usize) -> Option { + if self.remaining > n { + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(self.plane_cfg.stride * n) }; + self.output_rect.y += n as isize; + let output = PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.output_rect, + phantom: PhantomData, + }; + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(self.plane_cfg.stride) }; + self.output_rect.y += 1; + self.remaining -= (n + 1); + Some(output) + } else { + None + } + } +} + +impl<'a, T: Pixel> Iterator for HorzWindows<'a, T> { + type Item = PlaneRegion<'a, T>; + + #[inline(always)] + fn next(&mut self) -> Option { + self.nth(0) + } + + #[inline(always)] + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } + + #[inline(always)] + fn nth(&mut self, n: usize) -> Option { + if self.remaining > n { + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(n) }; + self.output_rect.x += n as isize; + let output = PlaneRegion { + data: self.data, + plane_cfg: self.plane_cfg, + rect: self.output_rect, + phantom: PhantomData, + }; + // SAFETY: We verified that we have enough data left to not go OOB. + self.data = unsafe { self.data.add(1) }; + self.output_rect.x += 1; + self.remaining -= (n + 1); + Some(output) + } else { + None + } + } +} + +impl ExactSizeIterator for VertWindows<'_, T> {} +impl FusedIterator for VertWindows<'_, T> {} +impl ExactSizeIterator for HorzWindows<'_, T> {} +impl FusedIterator for HorzWindows<'_, T> {} + +#[test] +fn area_test() { + assert_eq!( + (Area::BlockStartingAt { bo: BlockOffset { x: 0, y: 0 } }) + .to_rect(0, 0, 100, 100), + Rect { x: 0, y: 0, width: 100, height: 100 } + ); + assert_eq!( + (Area::BlockStartingAt { bo: BlockOffset { x: 1, y: 1 } }) + .to_rect(0, 0, 100, 100), + Rect { x: 4, y: 4, width: 96, height: 96 } + ); + assert_eq!( + (Area::BlockStartingAt { bo: BlockOffset { x: 1, y: 1 } }) + .to_rect(1, 1, 50, 50), + Rect { x: 0, y: 0, width: 50, height: 50 } + ); + assert_eq!( + (Area::BlockStartingAt { bo: BlockOffset { x: 2, y: 2 } }) + .to_rect(1, 1, 50, 50), + Rect { x: 4, y: 4, width: 46, height: 46 } + ); + assert_eq!( + (Area::BlockRect { bo: BlockOffset { x: 0, y: 0 }, width: 1, height: 1 }) + .to_rect(0, 0, 100, 100), + Rect { x: 0, y: 0, width: 1, height: 1 } + ); + assert_eq!( + (Area::BlockRect { bo: BlockOffset { x: 1, y: 1 }, width: 1, height: 1 }) + .to_rect(0, 0, 100, 100), + Rect { x: 4, y: 4, width: 1, height: 1 } + ); + assert_eq!( + (Area::BlockRect { bo: BlockOffset { x: 1, y: 1 }, width: 1, height: 1 }) + .to_rect(1, 1, 50, 50), + Rect { x: 0, y: 0, width: 1, height: 1 } + ); + assert_eq!( + (Area::BlockRect { bo: BlockOffset { x: 2, y: 2 }, width: 1, height: 1 }) + .to_rect(1, 1, 50, 50), + Rect { x: 4, y: 4, width: 1, height: 1 } + ); +} + +#[test] +fn frame_block_offset() { + { + let p = Plane::::new(100, 100, 0, 0, 0, 0); + let pr = + PlaneRegion::new(&p, Rect { x: 0, y: 0, width: 100, height: 100 }); + let bo = BlockOffset { x: 0, y: 0 }; + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + PlaneBlockOffset(bo) + ); + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + pr.subregion(Area::BlockStartingAt { bo }).frame_block_offset() + ); + } + { + let p = Plane::::new(100, 100, 0, 0, 0, 0); + let pr = + PlaneRegion::new(&p, Rect { x: 0, y: 0, width: 100, height: 100 }); + let bo = BlockOffset { x: 1, y: 1 }; + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + PlaneBlockOffset(bo) + ); + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + pr.subregion(Area::BlockStartingAt { bo }).frame_block_offset() + ); + } + { + let p = Plane::::new(100, 100, 1, 1, 0, 0); + let pr = + PlaneRegion::new(&p, Rect { x: 0, y: 0, width: 100, height: 100 }); + let bo = BlockOffset { x: 1, y: 1 }; + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + PlaneBlockOffset(bo) + ); + } + { + let p = Plane::::new(100, 100, 1, 1, 0, 0); + let pr = + PlaneRegion::new(&p, Rect { x: 0, y: 0, width: 100, height: 100 }); + let bo = BlockOffset { x: 2, y: 2 }; + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + PlaneBlockOffset(bo) + ); + assert_eq!( + pr.to_frame_block_offset(TileBlockOffset(bo)), + pr.subregion(Area::BlockStartingAt { bo }).frame_block_offset() + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +use crate::context::*; +use crate::frame::*; +use crate::util::*; + +/// Rectangle of a tile, in pixels +/// +/// This is similar to Rect, but with unsigned (x, y) for convenience. +#[derive(Debug, Clone, Copy)] +pub struct TileRect { + pub x: usize, + pub y: usize, + pub width: usize, + pub height: usize, +} + +impl TileRect { + #[inline(always)] + pub const fn decimated(&self, xdec: usize, ydec: usize) -> Self { + Self { + x: self.x >> xdec, + y: self.y >> ydec, + width: self.width >> xdec, + height: self.height >> ydec, + } + } + + #[inline(always)] + pub const fn to_frame_plane_offset( + &self, tile_po: PlaneOffset, + ) -> PlaneOffset { + PlaneOffset { + x: self.x as isize + tile_po.x, + y: self.y as isize + tile_po.y, + } + } + + #[inline(always)] + pub fn to_frame_block_offset( + &self, tile_bo: TileBlockOffset, xdec: usize, ydec: usize, + ) -> PlaneBlockOffset { + debug_assert!(self.x % (MI_SIZE >> xdec) == 0); + debug_assert!(self.y % (MI_SIZE >> ydec) == 0); + let bx = self.x >> (MI_SIZE_LOG2 - xdec); + let by = self.y >> (MI_SIZE_LOG2 - ydec); + PlaneBlockOffset(BlockOffset { x: bx + tile_bo.0.x, y: by + tile_bo.0.y }) + } + + #[inline(always)] + pub fn to_frame_super_block_offset( + &self, tile_sbo: TileSuperBlockOffset, sb_size_log2: usize, xdec: usize, + ydec: usize, + ) -> PlaneSuperBlockOffset { + debug_assert!(sb_size_log2 == 6 || sb_size_log2 == 7); + debug_assert!(self.x % (1 << (sb_size_log2 - xdec)) == 0); + debug_assert!(self.y % (1 << (sb_size_log2 - ydec)) == 0); + let sbx = self.x >> (sb_size_log2 - xdec); + let sby = self.y >> (sb_size_log2 - ydec); + PlaneSuperBlockOffset(SuperBlockOffset { + x: sbx + tile_sbo.0.x, + y: sby + tile_sbo.0.y, + }) + } +} + +impl From for Rect { + #[inline(always)] + fn from(tile_rect: TileRect) -> Rect { + Rect { + x: tile_rect.x as isize, + y: tile_rect.y as isize, + width: tile_rect.width, + height: tile_rect.height, + } + } +} + +/// Tiled view of a frame +#[derive(Debug)] +pub struct Tile<'a, T: Pixel> { + pub planes: [PlaneRegion<'a, T>; MAX_PLANES], +} + +/// Mutable tiled view of a frame +#[derive(Debug)] +pub struct TileMut<'a, T: Pixel> { + pub planes: [PlaneRegionMut<'a, T>; MAX_PLANES], +} + +// common impl for Tile and TileMut +macro_rules! tile_common { + // $name: Tile or TileMut + // $pr_type: PlaneRegion or PlaneRegionMut + // $iter: iter or iter_mut + //opt_mut: nothing or mut + ($name:ident, $pr_type:ident, $iter:ident $(,$opt_mut:tt)?) => { + impl<'a, T: Pixel> $name<'a, T> { + + #[inline(always)] + pub fn new( + frame: &'a $($opt_mut)? Frame, + luma_rect: TileRect, + ) -> Self { + let mut planes_iter = frame.planes.$iter(); + Self { + planes: [ + { + let plane = planes_iter.next().unwrap(); + $pr_type::new(plane, luma_rect.into()) + }, + { + let plane = planes_iter.next().unwrap(); + let rect = luma_rect.decimated(plane.cfg.xdec, plane.cfg.ydec); + $pr_type::new(plane, rect.into()) + }, + { + let plane = planes_iter.next().unwrap(); + let rect = luma_rect.decimated(plane.cfg.xdec, plane.cfg.ydec); + $pr_type::new(plane, rect.into()) + }, + ], + } + } + + /// Return a view to a subregion of a Tile + /// + /// The subregion must be included in (i.e. must not exceed) this Tile. + /// + /// It is described by an `Area`, relative to the luma plane of + /// this region. + /// + /// # Panics + /// + /// - If the requested dimensions are larger than the plane size + #[inline(always)] + pub fn subregion(&self, area: Area) -> Tile<'_, T> { + let tile_rect = area.to_rect( + 0, + 0, + self.planes[0].rect().width, + self.planes[0].rect().height, + ); + Tile { + planes: { + let sub_plane = |pli: usize| { + let plane = &self.planes[pli]; + let &PlaneConfig { xdec, ydec, .. } = plane.plane_cfg; + let rect = tile_rect.decimated(xdec, ydec); + if !plane.is_null() { + assert!(rect.x >= 0 && rect.x as usize <= plane.rect().width); + assert!(rect.y >= 0 && rect.y as usize <= plane.rect().height); + assert!(rect.x as usize + rect.width <= + plane.rect().x as usize + plane.rect().width); + assert!(rect.y as usize + rect.height <= + plane.rect().y as usize + plane.rect().height); + } + plane.subregion(rect.to_area()) + }; + [sub_plane(0), sub_plane(1), sub_plane(2)] + }, + } + } + + // Return an equivalent Tile with origin homed to 0,0. Data + // pointer is not moved (0,0 points to the same pixel previously + // pointed to by old x,y). + #[inline(always)] + pub fn home(&self) -> Self { + Self { + planes: [ + self.planes[0].home(), + self.planes[1].home(), + self.planes[2].home(), + ], + } + } + + // Return a copy of this tile's contents in a new backing frame. + #[inline(always)] + pub(crate) fn scratch_copy(&self) -> Frame { + Frame { + planes: [ + self.planes[0].scratch_copy(), + self.planes[1].scratch_copy(), + self.planes[2].scratch_copy(), + ], + } + } + } + } +} + +tile_common!(Tile, PlaneRegion, iter); +tile_common!(TileMut, PlaneRegionMut, iter_mut, mut); + +impl TileMut<'_, T> { + #[inline(always)] + pub fn as_const(&self) -> Tile<'_, T> { + Tile { + planes: [ + self.planes[0].as_const(), + self.planes[1].as_const(), + self.planes[2].as_const(), + ], + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_blocks.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_blocks.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_blocks.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_blocks.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,310 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::context::*; +use crate::mc::MotionVector; +use crate::partition::*; +use crate::predict::PredictionMode; +use crate::transform::*; + +use std::cmp; +use std::marker::PhantomData; +use std::ops::{Index, IndexMut}; +use std::slice; + +/// Tiled view of `FrameBlocks` +#[derive(Debug)] +pub struct TileBlocks<'a> { + data: *const Block, + x: usize, + y: usize, + cols: usize, + rows: usize, + frame_cols: usize, + frame_rows: usize, + phantom: PhantomData<&'a Block>, +} + +/// Mutable tiled view of `FrameBlocks` +#[derive(Debug)] +pub struct TileBlocksMut<'a> { + data: *mut Block, + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + frame_cols: usize, + frame_rows: usize, + phantom: PhantomData<&'a mut Block>, +} + +// common impl for TileBlocks and TileBlocksMut +macro_rules! tile_blocks_common { + // $name: TileBlocks or TileBlocksMut + // $opt_mut: nothing or mut + ($name:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + #[inline(always)] + pub fn new( + frame_blocks: &'a $($opt_mut)? FrameBlocks, + x: usize, + y: usize, + cols: usize, + rows: usize, + ) -> Self { + Self { + data: & $($opt_mut)? frame_blocks[y][x], + x, + y, + cols, + rows, + frame_cols: frame_blocks.cols, + frame_rows: frame_blocks.rows, + phantom: PhantomData, + } + } + + pub fn subregion( + &mut self, + x: usize, + y: usize, + cols: usize, + rows: usize, + ) -> TileBlocks<'_> { + TileBlocks { + data: &self[y][x], + x: self.x+x, + y: self.y+y, + cols: cmp::min(cols, self.cols - x), + rows: cmp::min(rows, self.rows - y), + frame_cols: self.frame_cols, + frame_rows: self.frame_rows, + phantom: PhantomData, + } + } + + #[inline(always)] + pub const fn x(&self) -> usize { + self.x + } + + #[inline(always)] + pub const fn y(&self) -> usize { + self.y + } + + #[inline(always)] + pub const fn cols(&self) -> usize { + self.cols + } + + #[inline(always)] + pub const fn rows(&self) -> usize { + self.rows + } + + #[inline(always)] + pub const fn frame_cols(&self) -> usize { + self.frame_cols + } + + #[inline(always)] + pub const fn frame_rows(&self) -> usize { + self.frame_rows + } + + #[inline(always)] + pub fn above_of(&self, bo: TileBlockOffset) -> &Block { + &self[bo.0.y - 1][bo.0.x] + } + + #[inline(always)] + pub fn left_of(&self, bo: TileBlockOffset) -> &Block { + &self[bo.0.y][bo.0.x - 1] + } + + #[inline(always)] + pub fn above_left_of(&self, bo: TileBlockOffset) -> &Block { + &self[bo.0.y - 1][bo.0.x - 1] + } + + pub fn get_cdef(&self, sbo: TileSuperBlockOffset) -> u8 { + let bo = sbo.block_offset(0, 0).0; + self[bo.y][bo.x].cdef_index + } + } + + unsafe impl Send for $name<'_> {} + unsafe impl Sync for $name<'_> {} + + impl Index for $name<'_> { + type Output = [Block]; + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.frame_cols); + slice::from_raw_parts(ptr, self.cols) + } + } + } + + // for convenience, also index by TileBlockOffset + impl Index for $name<'_> { + type Output = Block; + #[inline(always)] + fn index(&self, bo: TileBlockOffset) -> &Self::Output { + &self[bo.0.y][bo.0.x] + } + } + } +} + +tile_blocks_common!(TileBlocks); +tile_blocks_common!(TileBlocksMut, mut); + +impl TileBlocksMut<'_> { + #[inline(always)] + pub const fn as_const(&self) -> TileBlocks<'_> { + TileBlocks { + data: self.data, + x: self.x, + y: self.y, + cols: self.cols, + rows: self.rows, + frame_cols: self.frame_cols, + frame_rows: self.frame_rows, + phantom: PhantomData, + } + } + + pub fn subregion_mut( + &mut self, x: usize, y: usize, cols: usize, rows: usize, + ) -> TileBlocksMut<'_> { + TileBlocksMut { + data: &mut self[y][x], + x: self.x + x, + y: self.y + y, + cols: cmp::min(cols, self.cols - x), + rows: cmp::min(rows, self.rows - y), + frame_cols: self.frame_cols, + frame_rows: self.frame_rows, + phantom: PhantomData, + } + } + + #[inline(always)] + pub fn for_each(&mut self, bo: TileBlockOffset, bsize: BlockSize, f: F) + where + F: Fn(&mut Block), + { + let mut bw = bsize.width_mi(); + let bh = bsize.height_mi(); + + if bo.0.x + bw >= self.cols { + bw = self.cols - bo.0.x; + } + for y in 0..bh { + if bo.0.y + y >= self.rows { + continue; + } + for block in self[bo.0.y + y][bo.0.x..bo.0.x + bw].iter_mut() { + f(block); + } + } + } + + #[inline(always)] + pub fn set_mode( + &mut self, bo: TileBlockOffset, bsize: BlockSize, mode: PredictionMode, + ) { + self.for_each(bo, bsize, |block| block.mode = mode); + } + + #[inline(always)] + pub fn set_block_size(&mut self, bo: TileBlockOffset, bsize: BlockSize) { + let n4_w = bsize.width_mi() as u8; + let n4_h = bsize.height_mi() as u8; + self.for_each(bo, bsize, |block| { + block.bsize = bsize; + block.n4_w = n4_w; + block.n4_h = n4_h; + }); + } + + #[inline(always)] + pub fn set_tx_size( + &mut self, bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize, + ) { + self.for_each(bo, bsize, |block| block.txsize = tx_size); + } + + #[inline(always)] + pub fn set_skip( + &mut self, bo: TileBlockOffset, bsize: BlockSize, skip: bool, + ) { + self.for_each(bo, bsize, |block| block.skip = skip); + } + + #[inline(always)] + pub fn set_segmentation_idx( + &mut self, bo: TileBlockOffset, bsize: BlockSize, idx: u8, + ) { + self.for_each(bo, bsize, |block| block.segmentation_idx = idx); + } + + #[inline(always)] + pub fn set_ref_frames( + &mut self, bo: TileBlockOffset, bsize: BlockSize, r: [RefType; 2], + ) { + self.for_each(bo, bsize, |block| block.ref_frames = r); + } + + #[inline(always)] + pub fn set_motion_vectors( + &mut self, bo: TileBlockOffset, bsize: BlockSize, mvs: [MotionVector; 2], + ) { + self.for_each(bo, bsize, |block| block.mv = mvs); + } + + #[inline(always)] + pub fn set_cdef(&mut self, sbo: TileSuperBlockOffset, cdef_index: u8) { + let bo = sbo.block_offset(0, 0).0; + // Checkme: Is 16 still the right block unit for 128x128 superblocks? + let bw = cmp::min(bo.x + MIB_SIZE, self.cols); + let bh = cmp::min(bo.y + MIB_SIZE, self.rows); + for y in bo.y..bh { + for x in bo.x..bw { + self[y][x].cdef_index = cdef_index; + } + } + } +} + +impl IndexMut for TileBlocksMut<'_> { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.frame_cols); + slice::from_raw_parts_mut(ptr, self.cols) + } + } +} + +impl IndexMut for TileBlocksMut<'_> { + #[inline(always)] + fn index_mut(&mut self, bo: TileBlockOffset) -> &mut Self::Output { + &mut self[bo.0.y][bo.0.x] + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_motion_stats.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_motion_stats.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_motion_stats.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_motion_stats.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,146 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::mc::MotionVector; +use crate::me::*; + +use std::marker::PhantomData; +use std::ops::{Index, IndexMut}; +use std::slice; + +/// Tiled view of `FrameMEStats` +#[derive(Debug)] +pub struct TileMEStats<'a> { + data: *const MEStats, + // expressed in mi blocks + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameMEStats` + stride: usize, + phantom: PhantomData<&'a MotionVector>, +} + +/// Mutable tiled view of `FrameMEStats` +#[derive(Debug)] +pub struct TileMEStatsMut<'a> { + data: *mut MEStats, + // expressed in mi blocks + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameMEStats` + stride: usize, + phantom: PhantomData<&'a mut MotionVector>, +} + +// common impl for TileMotionVectors and TileMotionVectorsMut +macro_rules! tile_me_stats_common { + // $name: TileMEStats or TileMEStatsMut + // $opt_mut: nothing or mut + ($name:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + /// # Panics + /// + /// - If the requested dimensions are larger than the frame MV size + #[inline(always)] + pub fn new( + frame_mvs: &'a $($opt_mut)? FrameMEStats, + x: usize, + y: usize, + cols: usize, + rows: usize, + ) -> Self { + assert!(x + cols <= frame_mvs.cols); + assert!(y + rows <= frame_mvs.rows); + Self { + data: & $($opt_mut)? frame_mvs[y][x], + x, + y, + cols, + rows, + stride: frame_mvs.cols, + phantom: PhantomData, + } + } + + #[inline(always)] + pub const fn x(&self) -> usize { + self.x + } + + #[inline(always)] + pub const fn y(&self) -> usize { + self.y + } + + #[inline(always)] + pub const fn cols(&self) -> usize { + self.cols + } + + #[inline(always)] + pub const fn rows(&self) -> usize { + self.rows + } + } + + unsafe impl Send for $name<'_> {} + unsafe impl Sync for $name<'_> {} + + impl Index for $name<'_> { + type Output = [MEStats]; + + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts(ptr, self.cols) + } + } + } + } +} + +tile_me_stats_common!(TileMEStats); +tile_me_stats_common!(TileMEStatsMut, mut); + +impl TileMEStatsMut<'_> { + #[inline(always)] + pub const fn as_const(&self) -> TileMEStats<'_> { + TileMEStats { + data: self.data, + x: self.x, + y: self.y, + cols: self.cols, + rows: self.rows, + stride: self.stride, + phantom: PhantomData, + } + } +} + +impl IndexMut for TileMEStatsMut<'_> { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts_mut(ptr, self.cols) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_restoration_state.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_restoration_state.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_restoration_state.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_restoration_state.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,426 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::context::*; +use crate::encoder::FrameInvariants; +use crate::lrf::*; +use crate::util::Pixel; + +use std::marker::PhantomData; +use std::ops::{Index, IndexMut}; +use std::ptr; +use std::slice; + +/// Tiled view of `RestorationUnits` +#[derive(Debug)] +pub struct TileRestorationUnits<'a> { + data: *const RestorationUnit, + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameRestorationUnits` + stride: usize, + phantom: PhantomData<&'a RestorationUnit>, +} + +/// Mutable tiled view of `RestorationUnits` +#[derive(Debug)] +pub struct TileRestorationUnitsMut<'a> { + data: *mut RestorationUnit, + // private to guarantee borrowing rules + x: usize, + y: usize, + cols: usize, + rows: usize, + /// number of cols in the underlying `FrameRestorationUnits` + stride: usize, + phantom: PhantomData<&'a mut RestorationUnit>, +} + +// common impl for TileRestorationUnits and TileRestorationUnitsMut +macro_rules! tile_restoration_units_common { + // $name: TileRestorationUnits or TileRestorationUnitsMut + // $null: null or null_mut + // $opt_mut: nothing or mut + ($name:ident, $null:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + #[inline(always)] + pub fn new( + frame_units: &'a $($opt_mut)? FrameRestorationUnits, + x: usize, + y: usize, + cols: usize, + rows: usize, + ) -> Self { + Self { + data: if x < frame_units.cols && y < frame_units.rows { + & $($opt_mut)? frame_units[y][x] + } else { + // on edges, a tile may contain no restoration units + ptr::$null() + }, + x, + y, + cols, + rows, + stride: frame_units.cols, + phantom: PhantomData, + } + } + + #[inline(always)] + pub const fn x(&self) -> usize { + self.x + } + + #[inline(always)] + pub const fn y(&self) -> usize { + self.y + } + + #[inline(always)] + pub const fn cols(&self) -> usize { + self.cols + } + + #[inline(always)] + pub const fn rows(&self) -> usize { + self.rows + } + } + + unsafe impl Send for $name<'_> {} + unsafe impl Sync for $name<'_> {} + + impl Index for $name<'_> { + type Output = [RestorationUnit]; + + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts(ptr, self.cols) + } + } + } + } +} + +tile_restoration_units_common!(TileRestorationUnits, null); +tile_restoration_units_common!(TileRestorationUnitsMut, null_mut, mut); + +impl TileRestorationUnitsMut<'_> { + #[inline(always)] + pub const fn as_const(&self) -> TileRestorationUnits<'_> { + TileRestorationUnits { + data: self.data, + x: self.x, + y: self.y, + cols: self.cols, + rows: self.rows, + stride: self.stride, + phantom: PhantomData, + } + } +} + +impl IndexMut for TileRestorationUnitsMut<'_> { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + assert!(index < self.rows); + // SAFETY: The above assert ensures we do not access OOB data. + unsafe { + let ptr = self.data.add(index * self.stride); + slice::from_raw_parts_mut(ptr, self.cols) + } + } +} + +/// Tiled view of `RestorationPlane` +#[derive(Debug)] +pub struct TileRestorationPlane<'a> { + pub rp_cfg: &'a RestorationPlaneConfig, + pub wiener_ref: [[i8; 3]; 2], + pub sgrproj_ref: [i8; 2], + pub units: TileRestorationUnits<'a>, +} + +/// Mutable tiled view of `RestorationPlane` +#[derive(Debug)] +pub struct TileRestorationPlaneMut<'a> { + pub rp_cfg: &'a RestorationPlaneConfig, + pub wiener_ref: [[i8; 3]; 2], + pub sgrproj_ref: [i8; 2], + pub units: TileRestorationUnitsMut<'a>, +} + +// common impl for TileRestorationPlane and TileRestorationPlaneMut +macro_rules! tile_restoration_plane_common { + // $name: TileRestorationPlane or TileRestorationPlaneMut + // $tru_type: TileRestorationUnits or TileRestorationUnitsMut + // $opt_mut: nothing or mut + ($name:ident, $tru_type:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + #[inline(always)] + pub fn new( + rp: &'a $($opt_mut)? RestorationPlane, + units_x: usize, + units_y: usize, + units_cols: usize, + units_rows: usize, + ) -> Self { + Self { + rp_cfg: &rp.cfg, + wiener_ref: [WIENER_TAPS_MID; 2], + sgrproj_ref: SGRPROJ_XQD_MID, + units: $tru_type::new(& $($opt_mut)? rp.units, units_x, units_y, units_cols, units_rows), + } + } + + // determines the loop restoration unit row and column a + // superblock belongs to. The stretch boolean indicates if a + // superblock that belongs to a stretched LRU should return an + // index (stretch == true) or None (stretch == false). + pub const fn restoration_unit_index(&self, sbo: TileSuperBlockOffset, stretch: bool) + -> Option<(usize, usize)> { + if self.units.rows > 0 && self.units.cols > 0 { + // is this a stretch block? + let x_stretch = sbo.0.x < self.rp_cfg.sb_cols && + sbo.0.x >> self.rp_cfg.sb_h_shift >= self.units.cols; + let y_stretch = sbo.0.y < self.rp_cfg.sb_rows && + sbo.0.y >> self.rp_cfg.sb_v_shift >= self.units.rows; + if (x_stretch || y_stretch) && !stretch { + None + } else { + let x = (sbo.0.x >> self.rp_cfg.sb_h_shift) - if x_stretch { 1 } else { 0 }; + let y = (sbo.0.y >> self.rp_cfg.sb_v_shift) - if y_stretch { 1 } else { 0 }; + if x < self.units.cols && y < self.units.rows { + Some((x, y)) + } else { + None + } + } + } else { + None + } + } + + pub fn restoration_unit_offset(&self, base: TileSuperBlockOffset, + offset: TileSuperBlockOffset, stretch: bool) + -> Option<(usize, usize)> { + let base_option = self.restoration_unit_index(base, stretch); + let delta_option = self.restoration_unit_index(base + offset, stretch); + if let (Some((base_x, base_y)), Some((delta_x, delta_y))) = + (base_option, delta_option) + { + Some ((delta_x - base_x, delta_y - base_y)) + } else { + None + } + } + + pub const fn restoration_unit_countable(&self, x: usize, y: usize) -> usize { + y * self.units.cols + x + } + + // Is this the last sb (in scan order) in the restoration unit + // that we will be considering for RDO? This would be a + // straightforward calculation but for stretch; if the LRU + // stretches into a different tile, we don't consider those SBs + // in the other tile to be part of the LRU for RDO purposes. + pub fn restoration_unit_last_sb_for_rdo( + &self, + fi: &FrameInvariants, + global_sbo: PlaneSuperBlockOffset, + tile_sbo: TileSuperBlockOffset, + ) -> bool { + // there is 1 restoration unit for (1 << sb_shift) super-blocks + let h_mask = (1 << self.rp_cfg.sb_h_shift) - 1; + let v_mask = (1 << self.rp_cfg.sb_v_shift) - 1; + // is this a stretch block? + let x_stretch = tile_sbo.0.x >> self.rp_cfg.sb_h_shift >= self.units.cols; + let y_stretch = tile_sbo.0.y >> self.rp_cfg.sb_v_shift >= self.units.rows; + // Need absolute superblock offsets for edge check, not local to the tile. + let sbx = global_sbo.0.x + tile_sbo.0.x; + let sby = global_sbo.0.y + tile_sbo.0.y; + // edge-of-tile check + edge-of-frame check + let last_x = (tile_sbo.0.x & h_mask == h_mask && !x_stretch) || sbx == fi.sb_width-1; + let last_y = (tile_sbo.0.y & v_mask == v_mask && !y_stretch) || sby == fi.sb_height-1; + last_x && last_y + } + + #[inline(always)] + pub fn restoration_unit(&self, sbo: TileSuperBlockOffset, stretch: bool) + -> Option<&RestorationUnit> { + self.restoration_unit_index(sbo, stretch).map(|(x, y)| &self.units[y][x]) + } + } + } +} + +tile_restoration_plane_common!(TileRestorationPlane, TileRestorationUnits); +tile_restoration_plane_common!( + TileRestorationPlaneMut, + TileRestorationUnitsMut, + mut +); + +impl TileRestorationPlaneMut<'_> { + #[inline(always)] + pub fn restoration_unit_mut( + &mut self, sbo: TileSuperBlockOffset, + ) -> Option<&mut RestorationUnit> { + // cannot use map() due to lifetime constraints + if let Some((x, y)) = self.restoration_unit_index(sbo, true) { + Some(&mut self.units[y][x]) + } else { + None + } + } + + #[inline(always)] + pub const fn as_const(&self) -> TileRestorationPlane<'_> { + TileRestorationPlane { + rp_cfg: self.rp_cfg, + wiener_ref: self.wiener_ref, + sgrproj_ref: self.sgrproj_ref, + units: self.units.as_const(), + } + } +} + +/// Tiled view of `RestorationState` +#[derive(Debug)] +pub struct TileRestorationState<'a> { + pub planes: [TileRestorationPlane<'a>; MAX_PLANES], +} + +/// Mutable tiled view of `RestorationState` +#[derive(Debug)] +pub struct TileRestorationStateMut<'a> { + pub planes: [TileRestorationPlaneMut<'a>; MAX_PLANES], +} + +// common impl for TileRestorationState and TileRestorationStateMut +macro_rules! tile_restoration_state_common { + // $name: TileRestorationState or TileRestorationStateMut + // $trp_type: TileRestorationPlane or TileRestorationPlaneMut + // $iter: iter or iter_mut + // $opt_mut: nothing or mut + ($name:ident, $trp_type:ident, $iter:ident $(,$opt_mut:tt)?) => { + impl<'a> $name<'a> { + + #[inline(always)] + pub fn new( + rs: &'a $($opt_mut)? RestorationState, + sbo: PlaneSuperBlockOffset, + sb_width: usize, + sb_height: usize, + ) -> Self { + let (units_x0, units_y0, units_cols0, units_rows0) = + Self::get_units_region(rs, sbo, sb_width, sb_height, 0); + let (units_x1, units_y1, units_cols1, units_rows1) = + Self::get_units_region(rs, sbo, sb_width, sb_height, 1); + let (units_x2, units_y2, units_cols2, units_rows2) = + Self::get_units_region(rs, sbo, sb_width, sb_height, 2); + // we cannot retrieve &mut of slice items directly and safely + let mut planes_iter = rs.planes.$iter(); + Self { + planes: [ + { + let plane = planes_iter.next().unwrap(); + $trp_type::new(plane, units_x0, units_y0, units_cols0, units_rows0) + }, + { + let plane = planes_iter.next().unwrap(); + $trp_type::new(plane, units_x1, units_y1, units_cols1, units_rows1) + }, + { + let plane = planes_iter.next().unwrap(); + $trp_type::new(plane, units_x2, units_y2, units_cols2, units_rows2) + }, + ], + } + } + + #[inline(always)] + fn get_units_region( + rs: &RestorationState, + sbo: PlaneSuperBlockOffset, + sb_width: usize, + sb_height: usize, + pli: usize, + ) -> (usize, usize, usize, usize) { + let sb_h_shift = rs.planes[pli].cfg.sb_h_shift; + let sb_v_shift = rs.planes[pli].cfg.sb_v_shift; + // there may be several super-blocks per restoration unit + // the given super-block offset must match the start of a restoration unit + debug_assert!(sbo.0.x % (1 << sb_h_shift) == 0); + debug_assert!(sbo.0.y % (1 << sb_v_shift) == 0); + + let units_x = sbo.0.x >> sb_h_shift; + let units_y = sbo.0.y >> sb_v_shift; + let units_cols = sb_width + (1 << sb_h_shift) - 1 >> sb_h_shift; + let units_rows = sb_height + (1 << sb_v_shift) - 1 >> sb_v_shift; + + let FrameRestorationUnits { cols: rs_cols, rows: rs_rows, .. } = rs.planes[pli].units; + // +1 because the last super-block may use the "stretched" restoration unit + // from its neighbours + // + debug_assert!(units_x < rs_cols + 1); + debug_assert!(units_y < rs_rows + 1); + debug_assert!(units_x + units_cols <= rs_cols + 1); + debug_assert!(units_y + units_rows <= rs_rows + 1); + + let units_x = units_x.min(rs_cols); + let units_y = units_y.min(rs_rows); + let units_cols = units_cols.min(rs_cols - units_x); + let units_rows = units_rows.min(rs_rows - units_y); + (units_x, units_y, units_cols, units_rows) + } + + #[inline(always)] + pub fn has_restoration_unit(&self, sbo: TileSuperBlockOffset, pli: usize, stretch: bool) + -> bool { + self.planes[pli].restoration_unit(sbo, stretch).is_some() + } + } + } +} + +tile_restoration_state_common!( + TileRestorationState, + TileRestorationPlane, + iter +); +tile_restoration_state_common!( + TileRestorationStateMut, + TileRestorationPlaneMut, + iter_mut, + mut +); + +impl TileRestorationStateMut<'_> { + #[inline(always)] + pub const fn as_const(&self) -> TileRestorationState { + TileRestorationState { + planes: [ + self.planes[0].as_const(), + self.planes[1].as_const(), + self.planes[2].as_const(), + ], + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_state.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_state.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tile_state.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tile_state.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,265 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +use crate::context::*; +use crate::encoder::*; +use crate::frame::*; +use crate::lrf::{IntegralImageBuffer, SOLVE_IMAGE_SIZE}; +use crate::mc::MotionVector; +use crate::me::FrameMEStats; +use crate::me::WriteGuardMEStats; +use crate::partition::{RefType, REF_FRAMES}; +use crate::predict::{InterCompoundBuffers, PredictionMode}; +use crate::quantize::*; +use crate::rdo::*; +use crate::stats::EncoderStats; +use crate::util::*; +use std::ops::{Index, IndexMut}; +use std::sync::Arc; + +/// Tiled view of `FrameState` +/// +/// Contrary to `PlaneRegionMut` and `TileMut`, there is no const version: +/// - in practice, we don't need it; +/// - it would require to instantiate a const version of every of its inner +/// tiled views recursively. +/// +/// # `TileState` fields +/// +/// The way the `FrameState` fields are mapped depend on how they are accessed +/// tile-wise and frame-wise. +/// +/// Some fields (like `qc`) are only used during tile-encoding, so they are only +/// stored in `TileState`. +/// +/// Some other fields (like `input` or `segmentation`) are not written +/// tile-wise, so they just reference the matching field in `FrameState`. +/// +/// Some others (like `rec`) are written tile-wise, but must be accessible +/// frame-wise once the tile views vanish (e.g. for deblocking). +#[derive(Debug)] +pub struct TileStateMut<'a, T: Pixel> { + pub sbo: PlaneSuperBlockOffset, + pub sb_size_log2: usize, + pub sb_width: usize, + pub sb_height: usize, + pub mi_width: usize, + pub mi_height: usize, + pub width: usize, + pub height: usize, + pub input: &'a Frame, // the whole frame + pub input_tile: Tile<'a, T>, // the current tile + pub input_hres: &'a Plane, + pub input_qres: &'a Plane, + pub deblock: &'a DeblockState, + pub rec: TileMut<'a, T>, + pub qc: QuantizationContext, + pub segmentation: &'a SegmentationState, + pub restoration: TileRestorationStateMut<'a>, + pub me_stats: Vec>, + pub coded_block_info: MiTileState, + pub integral_buffer: IntegralImageBuffer, + pub inter_compound_buffers: InterCompoundBuffers, +} + +/// Contains information for a coded block that is +/// useful to persist. For example, the intra edge +/// filter requires surrounding coded block information. +#[derive(Debug, Clone, Copy)] +pub struct CodedBlockInfo { + pub luma_mode: PredictionMode, + pub chroma_mode: PredictionMode, + pub reference_types: [RefType; 2], +} + +impl Default for CodedBlockInfo { + fn default() -> Self { + CodedBlockInfo { + luma_mode: PredictionMode::DC_PRED, + chroma_mode: PredictionMode::DC_PRED, + reference_types: [RefType::INTRA_FRAME, RefType::NONE_FRAME], + } + } +} + +#[derive(Debug, Clone)] +pub struct MiTileState { + mi_width: usize, + mi_height: usize, + mi_block_info: Vec, +} + +impl MiTileState { + pub fn new(mi_width: usize, mi_height: usize) -> Self { + MiTileState { + mi_width, + mi_height, + mi_block_info: vec![CodedBlockInfo::default(); mi_width * mi_height], + } + } +} + +impl Index for MiTileState { + type Output = [CodedBlockInfo]; + + #[inline(always)] + fn index(&self, index: usize) -> &Self::Output { + &self.mi_block_info[index * self.mi_width..(index + 1) * self.mi_width] + } +} + +impl IndexMut for MiTileState { + #[inline(always)] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.mi_block_info[index * self.mi_width..(index + 1) * self.mi_width] + } +} + +impl<'a, T: Pixel> TileStateMut<'a, T> { + pub fn new( + fs: &'a mut FrameState, sbo: PlaneSuperBlockOffset, + sb_size_log2: usize, width: usize, height: usize, + frame_me_stats: &'a mut [FrameMEStats], + ) -> Self { + debug_assert!( + width % MI_SIZE == 0, + "Tile width must be a multiple of MI_SIZE" + ); + debug_assert!( + height % MI_SIZE == 0, + "Tile width must be a multiple of MI_SIZE" + ); + + let sb_rounded_width = width.align_power_of_two(sb_size_log2); + let sb_rounded_height = height.align_power_of_two(sb_size_log2); + + let luma_rect = TileRect { + x: sbo.0.x << sb_size_log2, + y: sbo.0.y << sb_size_log2, + width: sb_rounded_width, + height: sb_rounded_height, + }; + let sb_width = width.align_power_of_two_and_shift(sb_size_log2); + let sb_height = height.align_power_of_two_and_shift(sb_size_log2); + + Self { + sbo, + sb_size_log2, + sb_width, + sb_height, + mi_width: width >> MI_SIZE_LOG2, + mi_height: height >> MI_SIZE_LOG2, + width, + height, + input: &fs.input, + input_tile: Tile::new(&fs.input, luma_rect), + input_hres: &fs.input_hres, + input_qres: &fs.input_qres, + deblock: &fs.deblock, + rec: TileMut::new(Arc::make_mut(&mut fs.rec), luma_rect), + qc: Default::default(), + segmentation: &fs.segmentation, + restoration: TileRestorationStateMut::new( + &mut fs.restoration, + sbo, + sb_width, + sb_height, + ), + me_stats: frame_me_stats + .iter_mut() + .map(|fmvs| { + TileMEStatsMut::new( + fmvs, + sbo.0.x << (sb_size_log2 - MI_SIZE_LOG2), + sbo.0.y << (sb_size_log2 - MI_SIZE_LOG2), + width >> MI_SIZE_LOG2, + height >> MI_SIZE_LOG2, + ) + }) + .collect(), + coded_block_info: MiTileState::new( + width >> MI_SIZE_LOG2, + height >> MI_SIZE_LOG2, + ), + integral_buffer: IntegralImageBuffer::zeroed(SOLVE_IMAGE_SIZE), + inter_compound_buffers: InterCompoundBuffers::default(), + } + } + + #[inline(always)] + pub fn tile_rect(&self) -> TileRect { + TileRect { + x: self.sbo.0.x << self.sb_size_log2, + y: self.sbo.0.y << self.sb_size_log2, + width: self.width, + height: self.height, + } + } + + #[inline(always)] + pub fn to_frame_block_offset( + &self, tile_bo: TileBlockOffset, + ) -> PlaneBlockOffset { + let bx = self.sbo.0.x << (self.sb_size_log2 - MI_SIZE_LOG2); + let by = self.sbo.0.y << (self.sb_size_log2 - MI_SIZE_LOG2); + PlaneBlockOffset(BlockOffset { x: bx + tile_bo.0.x, y: by + tile_bo.0.y }) + } + + #[inline(always)] + pub fn to_frame_super_block_offset( + &self, tile_sbo: TileSuperBlockOffset, + ) -> PlaneSuperBlockOffset { + PlaneSuperBlockOffset(SuperBlockOffset { + x: self.sbo.0.x + tile_sbo.0.x, + y: self.sbo.0.y + tile_sbo.0.y, + }) + } + + /// Returns above block information for context during prediction. + /// If there is no above block, returns `None`. + /// `xdec` and `ydec` are the decimation factors of the targeted plane. + pub fn above_block_info( + &self, bo: TileBlockOffset, xdec: usize, ydec: usize, + ) -> Option { + let (mut bo_x, mut bo_y) = (bo.0.x, bo.0.y); + if bo_x & 1 == 0 { + bo_x += xdec + }; + if bo_y & 1 == 1 { + bo_y -= ydec + }; + if bo_y == 0 { + None + } else { + Some(self.coded_block_info[bo_y - 1][bo_x]) + } + } + + /// Returns left block information for context during prediction. + /// If there is no left block, returns `None`. + /// `xdec` and `ydec` are the decimation factors of the targeted plane. + pub fn left_block_info( + &self, bo: TileBlockOffset, xdec: usize, ydec: usize, + ) -> Option { + let (mut bo_x, mut bo_y) = (bo.0.x, bo.0.y); + if bo_x & 1 == 1 { + bo_x -= xdec + }; + if bo_y & 1 == 0 { + bo_y += ydec + }; + if bo_x == 0 { + None + } else { + Some(self.coded_block_info[bo_y][bo_x - 1]) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tiler.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tiler.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/tiling/tiler.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/tiling/tiler.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,874 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::*; + +use crate::context::*; +use crate::encoder::*; +use crate::me::WriteGuardMEStats; +use crate::util::*; + +use std::iter::FusedIterator; +use std::marker::PhantomData; +use std::ops::DerefMut; + +pub const MAX_TILE_WIDTH: usize = 4096; +pub const MAX_TILE_AREA: usize = 4096 * 2304; +pub const MAX_TILE_COLS: usize = 64; +pub const MAX_TILE_ROWS: usize = 64; +pub const MAX_TILE_RATE: f64 = 4096f64 * 2176f64 * 60f64 * 1.1; + +/// Tiling information +/// +/// This stores everything necessary to split a frame into tiles, and write +/// headers fields into the bitstream. +/// +/// The method `tile_iter_mut()` actually provides tiled views of `FrameState` +/// and `FrameBlocks`. +#[derive(Debug, Clone, Copy)] +pub struct TilingInfo { + pub frame_width: usize, + pub frame_height: usize, + pub tile_width_sb: usize, + pub tile_height_sb: usize, + pub cols: usize, // number of columns of tiles within the whole frame + pub rows: usize, // number of rows of tiles within the whole frame + pub tile_cols_log2: usize, + pub tile_rows_log2: usize, + pub min_tile_cols_log2: usize, + pub max_tile_cols_log2: usize, + pub min_tile_rows_log2: usize, + pub max_tile_rows_log2: usize, + pub sb_size_log2: usize, + pub min_tiles_log2: usize, +} + +impl TilingInfo { + /// # Panics + /// + /// Panics if the resulting tile sizes would be too large. + pub fn from_target_tiles( + sb_size_log2: usize, frame_width: usize, frame_height: usize, + frame_rate: f64, tile_cols_log2: usize, tile_rows_log2: usize, + is_422_p: bool, + ) -> Self { + // + + // Frame::new() aligns to the next multiple of 8 + let frame_width = frame_width.align_power_of_two(3); + let frame_height = frame_height.align_power_of_two(3); + let frame_width_sb = + frame_width.align_power_of_two_and_shift(sb_size_log2); + let frame_height_sb = + frame_height.align_power_of_two_and_shift(sb_size_log2); + let sb_cols = frame_width.align_power_of_two_and_shift(sb_size_log2); + let sb_rows = frame_height.align_power_of_two_and_shift(sb_size_log2); + + // these are bitstream-defined values and must not be changed + let max_tile_width_sb = MAX_TILE_WIDTH >> sb_size_log2; + let max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size_log2); + let min_tile_cols_log2 = + Self::tile_log2(max_tile_width_sb, sb_cols).unwrap(); + let max_tile_cols_log2 = + Self::tile_log2(1, sb_cols.min(MAX_TILE_COLS)).unwrap(); + let max_tile_rows_log2 = + Self::tile_log2(1, sb_rows.min(MAX_TILE_ROWS)).unwrap(); + let min_tiles_log2 = min_tile_cols_log2 + .max(Self::tile_log2(max_tile_area_sb, sb_cols * sb_rows).unwrap()); + + // Implements restriction in Annex A of the spec. + // Unlike the other restrictions, this one does not change + // the header coding of the tile rows/cols. + let min_tiles_ratelimit_log2 = min_tiles_log2.max( + ((frame_width * frame_height) as f64 * frame_rate / MAX_TILE_RATE) + .ceil() + .log2() + .ceil() as usize, + ); + + let tile_cols_log2 = + tile_cols_log2.clamp(min_tile_cols_log2, max_tile_cols_log2); + let tile_width_sb_pre = + sb_cols.align_power_of_two_and_shift(tile_cols_log2); + + // If this is 4:2:2, our UV horizontal is subsampled but not our + // vertical. Loop Restoration Units must be square, so they + // will always have an even number of horizontal superblocks. For + // tiles and LRUs to align, tile_width_sb must be even in 4:2:2 + // video. + + // This is only relevant when doing loop restoration RDO inline + // with block/superblock encoding, that is, where tiles are + // relevant. If (when) we introduce optionally delaying loop-filter + // encode to after the partitioning loop, we won't need to make + // any 4:2:2 adjustment. + + let tile_width_sb = if is_422_p { + (tile_width_sb_pre + 1) >> 1 << 1 + } else { + tile_width_sb_pre + }; + + let cols = frame_width_sb.div_ceil(tile_width_sb); + + // Adjust tile_cols_log2 in case of rounding tile_width_sb to even. + let tile_cols_log2 = Self::tile_log2(1, cols).unwrap(); + assert!(tile_cols_log2 >= min_tile_cols_log2); + + let min_tile_rows_log2 = min_tiles_log2.saturating_sub(tile_cols_log2); + let min_tile_rows_ratelimit_log2 = + min_tiles_ratelimit_log2.saturating_sub(tile_cols_log2); + let tile_rows_log2 = tile_rows_log2 + .max(min_tile_rows_log2) + .clamp(min_tile_rows_ratelimit_log2, max_tile_rows_log2); + let tile_height_sb = sb_rows.align_power_of_two_and_shift(tile_rows_log2); + + let rows = frame_height_sb.div_ceil(tile_height_sb); + + Self { + frame_width, + frame_height, + tile_width_sb, + tile_height_sb, + cols, + rows, + tile_cols_log2, + tile_rows_log2, + min_tile_cols_log2, + max_tile_cols_log2, + min_tile_rows_log2, + max_tile_rows_log2, + sb_size_log2, + min_tiles_log2, + } + } + + /// Return the smallest value for `k` such that `blkSize << k` is greater than + /// or equal to `target`. + /// + /// + pub fn tile_log2(blk_size: usize, target: usize) -> Option { + let mut k = 0; + while (blk_size.checked_shl(k)?) < target { + k += 1; + } + Some(k as usize) + } + + #[inline(always)] + pub const fn tile_count(&self) -> usize { + self.cols * self.rows + } + + /// Split frame-level structures into tiles + /// + /// Provide mutable tiled views of frame-level structures. + pub fn tile_iter_mut<'a, T: Pixel>( + &self, fs: &'a mut FrameState, fb: &'a mut FrameBlocks, + ) -> TileContextIterMut<'a, T> { + let afs = fs as *mut _; + let afb = fb as *mut _; + let frame_me_stats = fs.frame_me_stats.write().expect("poisoned lock"); + TileContextIterMut { ti: *self, fs: afs, fb: afb, next: 0, frame_me_stats } + } +} + +/// Container for all tiled views +pub struct TileContextMut<'a, T: Pixel> { + pub ts: TileStateMut<'a, T>, + pub tb: TileBlocksMut<'a>, +} + +/// Iterator over tiled views +pub struct TileContextIterMut<'a, T: Pixel> { + ti: TilingInfo, + fs: *mut FrameState, + fb: *mut FrameBlocks, + frame_me_stats: WriteGuardMEStats<'a>, + next: usize, +} + +impl<'a, T: Pixel> Iterator for TileContextIterMut<'a, T> { + type Item = TileContextMut<'a, T>; + + fn next(&mut self) -> Option { + if self.next < self.ti.rows * self.ti.cols { + let tile_col = self.next % self.ti.cols; + let tile_row = self.next / self.ti.cols; + let ctx = TileContextMut { + ts: { + // SAFETY: Multiple tiles mutably access this struct. + // The dimensions must be configured correctly to ensure + // the tiles do not overlap. + let fs = unsafe { &mut *self.fs }; + // SAFETY: ditto + let frame_me_stats = unsafe { + let len = self.frame_me_stats.len(); + let ptr = self.frame_me_stats.as_mut_ptr(); + std::slice::from_raw_parts_mut(ptr, len) + }; + let sbo = PlaneSuperBlockOffset(SuperBlockOffset { + x: tile_col * self.ti.tile_width_sb, + y: tile_row * self.ti.tile_height_sb, + }); + let x = sbo.0.x << self.ti.sb_size_log2; + let y = sbo.0.y << self.ti.sb_size_log2; + let tile_width = self.ti.tile_width_sb << self.ti.sb_size_log2; + let tile_height = self.ti.tile_height_sb << self.ti.sb_size_log2; + let width = tile_width.min(self.ti.frame_width - x); + let height = tile_height.min(self.ti.frame_height - y); + TileStateMut::new( + fs, + sbo, + self.ti.sb_size_log2, + width, + height, + frame_me_stats, + ) + }, + tb: { + // SAFETY: Multiple tiles mutably access this struct. + // The dimensions must be configured correctly to ensure + // the tiles do not overlap. + let fb = unsafe { &mut *self.fb }; + let tile_width_mi = + self.ti.tile_width_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2); + let tile_height_mi = + self.ti.tile_height_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2); + let x = tile_col * tile_width_mi; + let y = tile_row * tile_height_mi; + let cols = tile_width_mi.min(fb.cols - x); + let rows = tile_height_mi.min(fb.rows - y); + TileBlocksMut::new(fb, x, y, cols, rows) + }, + }; + self.next += 1; + Some(ctx) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.ti.cols * self.ti.rows - self.next; + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for TileContextIterMut<'_, T> {} +impl FusedIterator for TileContextIterMut<'_, T> {} + +#[cfg(test)] +pub mod test { + use super::*; + use crate::api::*; + use crate::lrf::*; + use crate::mc::MotionVector; + use crate::predict::PredictionMode; + use std::sync::Arc; + + #[test] + fn test_tiling_info_from_tile_count() { + let sb_size_log2 = 6; + let (width, height) = (160, 144); + let frame_rate = 25f64; + + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + width, + height, + frame_rate, + 0, + 0, + false, + ); + assert_eq!(1, ti.cols); + assert_eq!(1, ti.rows); + assert_eq!(3, ti.tile_width_sb); + assert_eq!(3, ti.tile_height_sb); + + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + width, + height, + frame_rate, + 1, + 1, + false, + ); + assert_eq!(2, ti.cols); + assert_eq!(2, ti.rows); + assert_eq!(2, ti.tile_width_sb); + assert_eq!(2, ti.tile_height_sb); + + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + width, + height, + frame_rate, + 2, + 2, + false, + ); + assert_eq!(3, ti.cols); + assert_eq!(3, ti.rows); + assert_eq!(1, ti.tile_width_sb); + assert_eq!(1, ti.tile_height_sb); + + // cannot split more than superblocks + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + width, + height, + frame_rate, + 10, + 8, + false, + ); + assert_eq!(3, ti.cols); + assert_eq!(3, ti.rows); + assert_eq!(1, ti.tile_width_sb); + assert_eq!(1, ti.tile_height_sb); + + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + 1024, + 1024, + frame_rate, + 0, + 0, + false, + ); + assert_eq!(1, ti.cols); + assert_eq!(1, ti.rows); + assert_eq!(16, ti.tile_width_sb); + assert_eq!(16, ti.tile_height_sb); + } + + fn setup( + width: usize, height: usize, + ) -> (FrameInvariants, FrameState, FrameBlocks, f64) { + // FrameInvariants aligns to the next multiple of 8, so using other values could make tests confusing + assert!(width.trailing_zeros() >= 3); + assert!(height.trailing_zeros() >= 3); + // We test only for 420 for now + let chroma_sampling = ChromaSampling::Cs420; + let config = Arc::new(EncoderConfig { + width, + height, + bit_depth: 8, + chroma_sampling, + ..Default::default() + }); + let mut sequence = Sequence::new(&config); + // These tests are all assuming SB-sized LRUs, so set that. + sequence.enable_large_lru = false; + let frame_rate = config.frame_rate(); + let fi = FrameInvariants::new(config, Arc::new(sequence)); + let fs = FrameState::new(&fi); + let fb = FrameBlocks::new(fi.w_in_b, fi.h_in_b); + + (fi, fs, fb, frame_rate) + } + + #[test] + fn test_tile_iter_len() { + // frame size 160x144, 40x36 in 4x4-blocks + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + { + // 2x2 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 1, + 1, + false, + ); + let mut iter = ti.tile_iter_mut(&mut fs, &mut fb); + assert_eq!(4, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(3, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(2, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(1, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(0, iter.len()); + assert!(iter.next().is_none()); + } + + { + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let mut iter = ti.tile_iter_mut(&mut fs, &mut fb); + assert_eq!(9, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(8, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(7, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(6, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(5, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(4, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(3, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(2, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(1, iter.len()); + assert!(iter.next().is_some()); + assert_eq!(0, iter.len()); + assert!(iter.next().is_none()); + } + } + + #[inline] + fn rect( + region: &PlaneRegionMut<'_, T>, + ) -> (isize, isize, usize, usize) { + let &Rect { x, y, width, height } = region.rect(); + (x, y, width, height) + } + + #[test] + fn test_tile_area() { + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let tile_states = iter.map(|ctx| ctx.ts).collect::>(); + + // the frame must be split into 9 tiles: + // + // luma (Y) chroma (U) chroma (V) + // 64x64 64x64 32x64 32x32 32x32 16x32 32x32 32x32 16x32 + // 64x64 64x64 32x64 32x32 32x32 16x32 32x32 32x32 16x32 + // 64x16 64x16 32x16 32x 8 32x 8 16x 8 32x 8 32x 8 16x 8 + + assert_eq!(9, tile_states.len()); + + let tile = &tile_states[0].rec; // the top-left tile + assert_eq!((0, 0, 64, 64), rect(&tile.planes[0])); + assert_eq!((0, 0, 32, 32), rect(&tile.planes[1])); + assert_eq!((0, 0, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[1].rec; // the top-middle tile + assert_eq!((64, 0, 64, 64), rect(&tile.planes[0])); + assert_eq!((32, 0, 32, 32), rect(&tile.planes[1])); + assert_eq!((32, 0, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[2].rec; // the top-right tile + assert_eq!((128, 0, 64, 64), rect(&tile.planes[0])); + assert_eq!((64, 0, 32, 32), rect(&tile.planes[1])); + assert_eq!((64, 0, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[3].rec; // the middle-left tile + assert_eq!((0, 64, 64, 64), rect(&tile.planes[0])); + assert_eq!((0, 32, 32, 32), rect(&tile.planes[1])); + assert_eq!((0, 32, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[4].rec; // the center tile + assert_eq!((64, 64, 64, 64), rect(&tile.planes[0])); + assert_eq!((32, 32, 32, 32), rect(&tile.planes[1])); + assert_eq!((32, 32, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[5].rec; // the middle-right tile + assert_eq!((128, 64, 64, 64), rect(&tile.planes[0])); + assert_eq!((64, 32, 32, 32), rect(&tile.planes[1])); + assert_eq!((64, 32, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[6].rec; // the bottom-left tile + assert_eq!((0, 128, 64, 64), rect(&tile.planes[0])); + assert_eq!((0, 64, 32, 32), rect(&tile.planes[1])); + assert_eq!((0, 64, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[7].rec; // the bottom-middle tile + assert_eq!((64, 128, 64, 64), rect(&tile.planes[0])); + assert_eq!((32, 64, 32, 32), rect(&tile.planes[1])); + assert_eq!((32, 64, 32, 32), rect(&tile.planes[2])); + + let tile = &tile_states[8].rec; // the bottom-right tile + assert_eq!((128, 128, 64, 64), rect(&tile.planes[0])); + assert_eq!((64, 64, 32, 32), rect(&tile.planes[1])); + assert_eq!((64, 64, 32, 32), rect(&tile.planes[2])); + } + + #[inline] + const fn b_area(region: &TileBlocksMut<'_>) -> (usize, usize, usize, usize) { + (region.x(), region.y(), region.cols(), region.rows()) + } + + #[test] + fn test_tile_blocks_area() { + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let tbs = iter.map(|ctx| ctx.tb).collect::>(); + + // the FrameBlocks must be split into 9 TileBlocks: + // + // 16x16 16x16 8x16 + // 16x16 16x16 8x16 + // 16x 4 16x4 8x 4 + + assert_eq!(9, tbs.len()); + + assert_eq!((0, 0, 16, 16), b_area(&tbs[0])); + assert_eq!((16, 0, 16, 16), b_area(&tbs[1])); + assert_eq!((32, 0, 8, 16), b_area(&tbs[2])); + + assert_eq!((0, 16, 16, 16), b_area(&tbs[3])); + assert_eq!((16, 16, 16, 16), b_area(&tbs[4])); + assert_eq!((32, 16, 8, 16), b_area(&tbs[5])); + + assert_eq!((0, 32, 16, 4), b_area(&tbs[6])); + assert_eq!((16, 32, 16, 4), b_area(&tbs[7])); + assert_eq!((32, 32, 8, 4), b_area(&tbs[8])); + } + + #[test] + fn test_tile_write() { + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + { + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let mut tile_states = iter.map(|ctx| ctx.ts).collect::>(); + + { + // row 12 of Y-plane of the top-left tile + let tile_plane = &mut tile_states[0].rec.planes[0]; + let row = &mut tile_plane[12]; + assert_eq!(64, row.len()); + row[35..41].copy_from_slice(&[4, 42, 12, 18, 15, 31]); + } + + { + // row 8 of U-plane of the middle-right tile + let tile_plane = &mut tile_states[5].rec.planes[1]; + let row = &mut tile_plane[8]; + assert_eq!(32, row.len()); + row[..4].copy_from_slice(&[14, 121, 1, 3]); + } + + { + // row 1 of V-plane of the bottom-middle tile + let tile_plane = &mut tile_states[7].rec.planes[2]; + let row = &mut tile_plane[1]; + assert_eq!(32, row.len()); + row[11..16].copy_from_slice(&[6, 5, 2, 11, 8]); + } + } + + // check that writes on tiles correctly affected the underlying frame + + let plane = &fs.rec.planes[0]; + let y = plane.cfg.yorigin + 12; + let x = plane.cfg.xorigin + 35; + let idx = y * plane.cfg.stride + x; + assert_eq!(&[4, 42, 12, 18, 15, 31], &plane.data[idx..idx + 6]); + + let plane = &fs.rec.planes[1]; + let offset = (64, 32); // middle-right tile, chroma plane + let y = plane.cfg.yorigin + offset.1 + 8; + let x = plane.cfg.xorigin + offset.0; + let idx = y * plane.cfg.stride + x; + assert_eq!(&[14, 121, 1, 3], &plane.data[idx..idx + 4]); + + let plane = &fs.rec.planes[2]; + let offset = (32, 64); // bottom-middle tile, chroma plane + let y = plane.cfg.yorigin + offset.1 + 1; + let x = plane.cfg.xorigin + offset.0 + 11; + let idx = y * plane.cfg.stride + x; + assert_eq!(&[6, 5, 2, 11, 8], &plane.data[idx..idx + 5]); + } + + #[test] + fn test_tile_restoration_edges() { + let (fi, mut fs, mut fb, frame_rate) = setup(64, 80); + + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let mut tile_states = iter.map(|ctx| ctx.ts).collect::>(); + + assert_eq!(tile_states.len(), 2); + + { + let trs = &mut tile_states[0].restoration; + let units = &trs.planes[0].units; + assert_eq!(units.x(), 0); + assert_eq!(units.y(), 0); + assert_eq!(units.cols(), 1); + assert_eq!(units.rows(), 1); + } + + { + let trs = &mut tile_states[1].restoration; + let units = &trs.planes[0].units; + assert_eq!(units.x(), 0); + assert_eq!(units.y(), 1); + // no units, the tile is too small (less than 1/2 super-block) + assert_eq!(units.cols() * units.rows(), 0); + } + } + + #[test] + fn test_tile_restoration_write() { + let (fi, mut fs, mut fb, frame_rate) = setup(256, 256); + + { + // 2x2 tiles, each one containing 2×2 restoration units (1 super-block per restoration unit) + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 1, + 1, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let mut tile_states = iter.map(|ctx| ctx.ts).collect::>(); + + { + // unit (1, 0) of Y-plane of the top-left tile + let units = &mut tile_states[0].restoration.planes[0].units; + units[0][1].filter = + RestorationFilter::Wiener { coeffs: [[1, 2, 3], [4, 5, 6]] }; + } + + { + // unit (0, 1) of U-plane of the bottom-right tile + let units = &mut tile_states[3].restoration.planes[1].units; + units[1][0].filter = + RestorationFilter::Sgrproj { set: 42, xqd: [10, 20] }; + } + + { + // unit (1, 1) of V-plane of the bottom-left tile + let units = &mut tile_states[2].restoration.planes[2].units; + units[1][1].filter = + RestorationFilter::Sgrproj { set: 5, xqd: [1, 2] }; + } + } + + // check that writes on tiles correctly affected the underlying restoration units + + let units = &mut fs.restoration.planes[0].units; + assert_eq!( + units[0][1].filter, + RestorationFilter::Wiener { coeffs: [[1, 2, 3], [4, 5, 6]] } + ); + + let units = &mut fs.restoration.planes[1].units; + assert_eq!( + units[3][2].filter, + RestorationFilter::Sgrproj { set: 42, xqd: [10, 20] } + ); + + let units = &mut fs.restoration.planes[2].units; + assert_eq!( + units[3][1].filter, + RestorationFilter::Sgrproj { set: 5, xqd: [1, 2] } + ); + } + + #[test] + fn test_tile_motion_vectors_write() { + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + { + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let mut tile_states = iter.map(|ctx| ctx.ts).collect::>(); + + { + // block (8, 5) of the top-left tile (of the first ref frame) + let me_stats = &mut tile_states[0].me_stats[0]; + me_stats[5][8].mv = MotionVector { col: 42, row: 38 }; + println!("{:?}", me_stats[5][8].mv); + } + + { + // block (4, 2) of the middle-right tile (of ref frame 2) + let me_stats = &mut tile_states[5].me_stats[2]; + me_stats[2][3].mv = MotionVector { col: 2, row: 14 }; + } + } + + // check that writes on tiled views affected the underlying motion vectors + + let me_stats = &fs.frame_me_stats.read().unwrap()[0]; + assert_eq!(MotionVector { col: 42, row: 38 }, me_stats[5][8].mv); + + let me_stats = &fs.frame_me_stats.read().unwrap()[2]; + let mix = (128 >> MI_SIZE_LOG2) + 3; + let miy = (64 >> MI_SIZE_LOG2) + 2; + assert_eq!(MotionVector { col: 2, row: 14 }, me_stats[miy][mix].mv); + } + + #[test] + fn test_tile_blocks_write() { + let (fi, mut fs, mut fb, frame_rate) = setup(160, 144); + + { + // 4x4 tiles requested, will actually get 3x3 tiles + let ti = TilingInfo::from_target_tiles( + fi.sb_size_log2(), + fi.width, + fi.height, + frame_rate, + 2, + 2, + false, + ); + let iter = ti.tile_iter_mut(&mut fs, &mut fb); + let mut tbs = iter.map(|ctx| ctx.tb).collect::>(); + + { + // top-left tile + let tb = &mut tbs[0]; + // block (4, 3) + tb[3][4].n4_w = 42; + // block (8, 5) + tb[5][8].segmentation_idx = 14; + } + + { + // middle-right tile + let tb = &mut tbs[5]; + // block (0, 1) + tb[1][0].n4_h = 11; + // block (7, 5) + tb[5][7].cdef_index = 3; + } + + { + // bottom-middle tile + let tb = &mut tbs[7]; + // block (3, 2) + tb[2][3].mode = PredictionMode::PAETH_PRED; + // block (1, 1) + tb[1][1].n4_w = 8; + } + } + + // check that writes on tiles correctly affected the underlying blocks + + assert_eq!(42, fb[3][4].n4_w); + assert_eq!(14, fb[5][8].segmentation_idx); + + assert_eq!(11, fb[17][32].n4_h); + assert_eq!(3, fb[21][39].cdef_index); + + assert_eq!(PredictionMode::PAETH_PRED, fb[34][19].mode); + assert_eq!(8, fb[33][17].n4_w); + } + + #[test] + fn tile_log2_overflow() { + assert_eq!(TilingInfo::tile_log2(1, usize::MAX), None); + } + + #[test] + fn from_target_tiles_422() { + let sb_size_log2 = 6; + let is_422_p = true; + let frame_rate = 60.; + let sb_size = 1 << sb_size_log2; + + for frame_height in (sb_size..4352).step_by(sb_size) { + for tile_rows_log2 in + 0..=TilingInfo::tile_log2(1, frame_height >> sb_size_log2).unwrap() + { + for frame_width in (sb_size..7680).step_by(sb_size) { + for tile_cols_log2 in + 0..=TilingInfo::tile_log2(1, frame_width >> sb_size_log2).unwrap() + { + let ti = TilingInfo::from_target_tiles( + sb_size_log2, + frame_width, + frame_height, + frame_rate, + tile_cols_log2, + tile_rows_log2, + is_422_p, + ); + assert_eq!( + ti.tile_cols_log2, + TilingInfo::tile_log2(1, ti.cols).unwrap() + ); + assert_eq!( + ti.tile_rows_log2, + TilingInfo::tile_log2(1, ti.rows).unwrap() + ); + } + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/token_cdfs.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/token_cdfs.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/token_cdfs.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/token_cdfs.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3984 @@ +// Copyright (c) 2018-2021, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_upper_case_globals)] + +use crate::context::*; +use crate::transform::*; +use crate::util::*; + +const TOKEN_CDF_Q_CTXS: usize = 4; + +pub static av1_default_dc_sign_cdfs: [[[[u16; 2]; DC_SIGN_CONTEXTS]; + PLANE_TYPES]; TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [[128 * 125], [128 * 102], [128 * 147]], + [[128 * 119], [128 * 101], [128 * 135]], + ], + [ + [[128 * 125], [128 * 102], [128 * 147]], + [[128 * 119], [128 * 101], [128 * 135]], + ], + [ + [[128 * 125], [128 * 102], [128 * 147]], + [[128 * 119], [128 * 101], [128 * 135]], + ], + [ + [[128 * 125], [128 * 102], [128 * 147]], + [[128 * 119], [128 * 101], [128 * 135]], + ], +]); + +pub static av1_default_txb_skip_cdfs: [[[[u16; 2]; TXB_SKIP_CONTEXTS]; + TxSize::TX_SIZES]; TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [ + [31849], + [5892], + [12112], + [21935], + [20289], + [27473], + [32487], + [7654], + [19473], + [29984], + [9961], + [30242], + [32117], + ], + [ + [31548], + [1549], + [10130], + [16656], + [18591], + [26308], + [32537], + [5403], + [18096], + [30003], + [16384], + [16384], + [16384], + ], + [ + [29957], + [5391], + [18039], + [23566], + [22431], + [25822], + [32197], + [3778], + [15336], + [28981], + [16384], + [16384], + [16384], + ], + [ + [17920], + [1818], + [7282], + [25273], + [10923], + [31554], + [32624], + [1366], + [15628], + [30462], + [146], + [5132], + [31657], + ], + [ + [6308], + [117], + [1638], + [2161], + [16384], + [10923], + [30247], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [30371], + [7570], + [13155], + [20751], + [20969], + [27067], + [32013], + [5495], + [17942], + [28280], + [16384], + [16384], + [16384], + ], + [ + [31782], + [1836], + [10689], + [17604], + [21622], + [27518], + [32399], + [4419], + [16294], + [28345], + [16384], + [16384], + [16384], + ], + [ + [31901], + [10311], + [18047], + [24806], + [23288], + [27914], + [32296], + [4215], + [15756], + [28341], + [16384], + [16384], + [16384], + ], + [ + [26726], + [1045], + [11703], + [20590], + [18554], + [25970], + [31938], + [5583], + [21313], + [29390], + [641], + [22265], + [31452], + ], + [ + [26584], + [188], + [8847], + [24519], + [22938], + [30583], + [32608], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [29614], + [9068], + [12924], + [19538], + [17737], + [24619], + [30642], + [4119], + [16026], + [25657], + [16384], + [16384], + [16384], + ], + [ + [31957], + [3230], + [11153], + [18123], + [20143], + [26536], + [31986], + [3050], + [14603], + [25155], + [16384], + [16384], + [16384], + ], + [ + [32363], + [10692], + [19090], + [24357], + [24442], + [28312], + [32169], + [3648], + [15690], + [26815], + [16384], + [16384], + [16384], + ], + [ + [30669], + [3832], + [11663], + [18889], + [19782], + [23313], + [31330], + [5124], + [18719], + [28468], + [3082], + [20982], + [29443], + ], + [ + [28573], + [3183], + [17802], + [25977], + [26677], + [27832], + [32387], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [26887], + [6729], + [10361], + [17442], + [15045], + [22478], + [29072], + [2713], + [11861], + [20773], + [16384], + [16384], + [16384], + ], + [ + [31903], + [2044], + [7528], + [14618], + [16182], + [24168], + [31037], + [2786], + [11194], + [20155], + [16384], + [16384], + [16384], + ], + [ + [32510], + [8430], + [17318], + [24154], + [23674], + [28789], + [32139], + [3440], + [13117], + [22702], + [16384], + [16384], + [16384], + ], + [ + [31671], + [2056], + [11746], + [16852], + [18635], + [24715], + [31484], + [4656], + [16074], + [24704], + [1806], + [14645], + [25336], + ], + [ + [31539], + [8433], + [20576], + [27904], + [27852], + [30026], + [32441], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], +]); + +pub static av1_default_eob_extra_cdfs: [[[[[u16; 2]; EOB_COEF_CONTEXTS]; + PLANE_TYPES]; TxSize::TX_SIZES]; + TOKEN_CDF_Q_CTXS] = cdf_5d([ + [ + [ + [ + [16961], + [17223], + [7621], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + [ + [19069], + [22525], + [13377], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [20401], + [17025], + [12845], + [12873], + [14094], + [16384], + [16384], + [16384], + [16384], + ], + [ + [20681], + [20701], + [15250], + [15017], + [14928], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [23905], + [17194], + [16170], + [17695], + [13826], + [15810], + [12036], + [16384], + [16384], + ], + [ + [23959], + [20799], + [19021], + [16203], + [17886], + [14144], + [12010], + [16384], + [16384], + ], + ], + [ + [ + [27399], + [16327], + [18071], + [19584], + [20721], + [18432], + [19560], + [10150], + [8805], + ], + [ + [24932], + [20833], + [12027], + [16670], + [19914], + [15106], + [17662], + [13783], + [28756], + ], + ], + [ + [ + [23406], + [21845], + [18432], + [16384], + [17096], + [12561], + [17320], + [22395], + [21370], + ], + [ + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + ], + [ + [ + [ + [17471], + [20223], + [11357], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + [ + [20335], + [21667], + [14818], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [20430], + [20662], + [15367], + [16970], + [14657], + [16384], + [16384], + [16384], + [16384], + ], + [ + [22117], + [22028], + [18650], + [16042], + [15885], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [22409], + [21012], + [15650], + [17395], + [15469], + [20205], + [19511], + [16384], + [16384], + ], + [ + [24220], + [22480], + [17737], + [18916], + [19268], + [18412], + [18844], + [16384], + [16384], + ], + ], + [ + [ + [25991], + [20314], + [17731], + [19678], + [18649], + [17307], + [21798], + [17549], + [15630], + ], + [ + [26585], + [21469], + [20432], + [17735], + [19280], + [15235], + [20297], + [22471], + [28997], + ], + ], + [ + [ + [26605], + [11304], + [16726], + [16560], + [20866], + [23524], + [19878], + [13469], + [23084], + ], + [ + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + ], + [ + [ + [ + [18983], + [20512], + [14885], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + [ + [20090], + [19444], + [17286], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [19139], + [21487], + [18959], + [20910], + [19089], + [16384], + [16384], + [16384], + [16384], + ], + [ + [20536], + [20664], + [20625], + [19123], + [14862], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [19833], + [21502], + [17485], + [20267], + [18353], + [23329], + [21478], + [16384], + [16384], + ], + [ + [22041], + [23434], + [20001], + [20554], + [20951], + [20145], + [15562], + [16384], + [16384], + ], + ], + [ + [ + [23312], + [21607], + [16526], + [18957], + [18034], + [18934], + [24247], + [16921], + [17080], + ], + [ + [26579], + [24910], + [18637], + [19800], + [20388], + [9887], + [15642], + [30198], + [24721], + ], + ], + [ + [ + [26998], + [16737], + [17838], + [18922], + [19515], + [18636], + [17333], + [15776], + [22658], + ], + [ + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + ], + [ + [ + [ + [20177], + [20789], + [20262], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + [ + [21416], + [20855], + [23410], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [20238], + [21057], + [19159], + [22337], + [20159], + [16384], + [16384], + [16384], + [16384], + ], + [ + [20125], + [20559], + [21707], + [22296], + [17333], + [16384], + [16384], + [16384], + [16384], + ], + ], + [ + [ + [19941], + [20527], + [21470], + [22487], + [19558], + [22354], + [20331], + [16384], + [16384], + ], + [ + [22752], + [25006], + [22075], + [21576], + [17740], + [21690], + [19211], + [16384], + [16384], + ], + ], + [ + [ + [21442], + [22358], + [18503], + [20291], + [19945], + [21294], + [21178], + [19400], + [10556], + ], + [ + [24648], + [24949], + [20708], + [23905], + [20501], + [9558], + [9423], + [30365], + [19253], + ], + ], + [ + [ + [26064], + [22098], + [19613], + [20525], + [17595], + [16618], + [20497], + [18989], + [15513], + ], + [ + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + [16384], + ], + ], + ], +]); + +pub static av1_default_eob_multi16_cdfs: [[[[u16; 5]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [[840, 1039, 1980, 4895], [370, 671, 1883, 4471]], + [[3247, 4950, 9688, 14563], [1904, 3354, 7763, 14647]], + ], + [ + [[2125, 2551, 5165, 8946], [513, 765, 1859, 6339]], + [[7637, 9498, 14259, 19108], [2497, 4096, 8866, 16993]], + ], + [ + [[4016, 4897, 8881, 14968], [716, 1105, 2646, 10056]], + [[11139, 13270, 18241, 23566], [3192, 5032, 10297, 19755]], + ], + [ + [[6708, 8958, 14746, 22133], [1222, 2074, 4783, 15410]], + [[19575, 21766, 26044, 29709], [7297, 10767, 19273, 28194]], + ], +]); + +pub static av1_default_eob_multi32_cdfs: [[[[u16; 6]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [[400, 520, 977, 2102, 6542], [210, 405, 1315, 3326, 7537]], + [[2636, 4273, 7588, 11794, 20401], [1786, 3179, 6902, 11357, 19054]], + ], + [ + [[989, 1249, 2019, 4151, 10785], [313, 441, 1099, 2917, 8562]], + [[8394, 10352, 13932, 18855, 26014], [2578, 4124, 8181, 13670, 24234]], + ], + [ + [[2515, 3003, 4452, 8162, 16041], [574, 821, 1836, 5089, 13128]], + [[13468, 16303, 20361, 25105, 29281], [3542, 5502, 10415, 16760, 25644]], + ], + [ + [[4617, 5709, 8446, 13584, 23135], [1156, 1702, 3675, 9274, 20539]], + [[22086, 24282, 27010, 29770, 31743], [7699, 10897, 20891, 26926, 31628]], + ], +]); + +pub static av1_default_eob_multi64_cdfs: [[[[u16; 7]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [[329, 498, 1101, 1784, 3265, 7758], [335, 730, 1459, 5494, 8755, 12997]], + [ + [3505, 5304, 10086, 13814, 17684, 23370], + [1563, 2700, 4876, 10911, 14706, 22480], + ], + ], + [ + [ + [1260, 1446, 2253, 3712, 6652, 13369], + [401, 605, 1029, 2563, 5845, 12626], + ], + [ + [8609, 10612, 14624, 18714, 22614, 29024], + [1923, 3127, 5867, 9703, 14277, 27100], + ], + ], + [ + [ + [2374, 2772, 4583, 7276, 12288, 19706], + [497, 810, 1315, 3000, 7004, 15641], + ], + [ + [15050, 17126, 21410, 24886, 28156, 30726], + [4034, 6290, 10235, 14982, 21214, 28491], + ], + ], + [ + [ + [6307, 7541, 12060, 16358, 22553, 27865], + [1289, 2320, 3971, 7926, 14153, 24291], + ], + [ + [24212, 25708, 28268, 30035, 31307, 32049], + [8726, 12378, 19409, 26450, 30038, 32462], + ], + ], +]); + +pub static av1_default_eob_multi128_cdfs: [[[[u16; 8]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [ + [219, 482, 1140, 2091, 3680, 6028, 12586], + [371, 699, 1254, 4830, 9479, 12562, 17497], + ], + [ + [5245, 7456, 12880, 15852, 20033, 23932, 27608], + [2054, 3472, 5869, 14232, 18242, 20590, 26752], + ], + ], + [ + [ + [685, 933, 1488, 2714, 4766, 8562, 19254], + [217, 352, 618, 2303, 5261, 9969, 17472], + ], + [ + [8045, 11200, 15497, 19595, 23948, 27408, 30938], + [2310, 4160, 7471, 14997, 17931, 20768, 30240], + ], + ], + [ + [ + [1366, 1738, 2527, 5016, 9355, 15797, 24643], + [354, 558, 944, 2760, 7287, 14037, 21779], + ], + [ + [13627, 16246, 20173, 24429, 27948, 30415, 31863], + [6275, 9889, 14769, 23164, 27988, 30493, 32272], + ], + ], + [ + [ + [3472, 4885, 7489, 12481, 18517, 24536, 29635], + [886, 1731, 3271, 8469, 15569, 22126, 28383], + ], + [ + [24313, 26062, 28385, 30107, 31217, 31898, 32345], + [9165, 13282, 21150, 30286, 31894, 32571, 32712], + ], + ], +]); + +pub static av1_default_eob_multi256_cdfs: [[[[u16; 9]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [ + [310, 584, 1887, 3589, 6168, 8611, 11352, 15652], + [998, 1850, 2998, 5604, 17341, 19888, 22899, 25583], + ], + [ + [2520, 3240, 5952, 8870, 12577, 17558, 19954, 24168], + [2203, 4130, 7435, 10739, 20652, 23681, 25609, 27261], + ], + ], + [ + [ + [1448, 2109, 4151, 6263, 9329, 13260, 17944, 23300], + [399, 1019, 1749, 3038, 10444, 15546, 22739, 27294], + ], + [ + [6402, 8148, 12623, 15072, 18728, 22847, 26447, 29377], + [1674, 3252, 5734, 10159, 22397, 23802, 24821, 30940], + ], + ], + [ + [ + [3089, 3920, 6038, 9460, 14266, 19881, 25766, 29176], + [1084, 2358, 3488, 5122, 11483, 18103, 26023, 29799], + ], + [ + [11514, 13794, 17480, 20754, 24361, 27378, 29492, 31277], + [6571, 9610, 15516, 21826, 29092, 30829, 31842, 32708], + ], + ], + [ + [ + [5348, 7113, 11820, 15924, 22106, 26777, 30334, 31757], + [2453, 4474, 6307, 8777, 16474, 22975, 29000, 31547], + ], + [ + [23110, 24597, 27140, 28894, 30167, 30927, 31392, 32094], + [9998, 17661, 25178, 28097, 31308, 32038, 32403, 32695], + ], + ], +]); + +pub static av1_default_eob_multi512_cdfs: [[[[u16; 10]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [ + [641, 983, 3707, 5430, 10234, 14958, 18788, 23412, 26061], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + [ + [5095, 6446, 9996, 13354, 16017, 17986, 20919, 26129, 29140], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + ], + [ + [ + [1230, 2278, 5035, 7776, 11871, 15346, 19590, 24584, 28749], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + [ + [7265, 9979, 15819, 19250, 21780, 23846, 26478, 28396, 31811], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + ], + [ + [ + [2624, 3936, 6480, 9686, 13979, 17726, 23267, 28410, 31078], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + [ + [12015, 14769, 19588, 22052, 24222, 25812, 27300, 29219, 32114], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + ], + [ + [ + [5927, 7809, 10923, 14597, 19439, 24135, 28456, 31142, 32060], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + [ + [21093, 23043, 25742, 27658, 29097, 29716, 30073, 30820, 31956], + [3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491], + ], + ], +]); + +pub static av1_default_eob_multi1024_cdfs: [[[[u16; 11]; 2]; PLANE_TYPES]; + TOKEN_CDF_Q_CTXS] = cdf_4d([ + [ + [ + [393, 421, 751, 1623, 3160, 6352, 13345, 18047, 22571, 25830], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + [ + [1865, 1988, 2930, 4242, 10533, 16538, 21354, 27255, 28546, 31784], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + ], + [ + [ + [696, 948, 3145, 5702, 9706, 13217, 17851, 21856, 25692, 28034], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + [ + [2672, 3591, 9330, 17084, 22725, 24284, 26527, 28027, 28377, 30876], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + ], + [ + [ + [2784, 3831, 7041, 10521, 14847, 18844, 23155, 26682, 29229, 31045], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + [ + [9577, 12466, 17739, 20750, 22061, 23215, 24601, 25483, 25843, 32056], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + ], + [ + [ + [6698, 8334, 11961, 15762, 20186, 23862, 27434, 29326, 31082, 32050], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + [ + [20569, 22426, 25569, 26859, 28053, 28913, 29486, 29724, 29807, 32570], + [2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789], + ], + ], +]); + +pub static av1_default_coeff_lps_multi_cdfs: [[[[[u16; BR_CDF_SIZE]; + LEVEL_CONTEXTS]; + PLANE_TYPES]; + TxSize::TX_SIZES]; + TOKEN_CDF_Q_CTXS] = cdf_5d([ + [ + [ + [ + [14298, 20718, 24174], + [12536, 19601, 23789], + [8712, 15051, 19503], + [6170, 11327, 15434], + [4742, 8926, 12538], + [3803, 7317, 10546], + [1696, 3317, 4871], + [14392, 19951, 22756], + [15978, 23218, 26818], + [12187, 19474, 23889], + [9176, 15640, 20259], + [7068, 12655, 17028], + [5656, 10442, 14472], + [2580, 4992, 7244], + [12136, 18049, 21426], + [13784, 20721, 24481], + [10836, 17621, 21900], + [8372, 14444, 18847], + [6523, 11779, 16000], + [5337, 9898, 13760], + [3034, 5860, 8462], + ], + [ + [15967, 22905, 26286], + [13534, 20654, 24579], + [9504, 16092, 20535], + [6975, 12568, 16903], + [5364, 10091, 14020], + [4357, 8370, 11857], + [2506, 4934, 7218], + [23032, 28815, 30936], + [19540, 26704, 29719], + [15158, 22969, 27097], + [11408, 18865, 23650], + [8885, 15448, 20250], + [7108, 12853, 17416], + [4231, 8041, 11480], + [19823, 26490, 29156], + [18890, 25929, 28932], + [15660, 23491, 27433], + [12147, 19776, 24488], + [9728, 16774, 21649], + [7919, 14277, 19066], + [5440, 10170, 14185], + ], + ], + [ + [ + [14406, 20862, 24414], + [11824, 18907, 23109], + [8257, 14393, 18803], + [5860, 10747, 14778], + [4475, 8486, 11984], + [3606, 6954, 10043], + [1736, 3410, 5048], + [14430, 20046, 22882], + [15593, 22899, 26709], + [12102, 19368, 23811], + [9059, 15584, 20262], + [6999, 12603, 17048], + [5684, 10497, 14553], + [2822, 5438, 7862], + [15785, 21585, 24359], + [18347, 25229, 28266], + [14974, 22487, 26389], + [11423, 18681, 23271], + [8863, 15350, 20008], + [7153, 12852, 17278], + [3707, 7036, 9982], + ], + [ + [15460, 21696, 25469], + [12170, 19249, 23191], + [8723, 15027, 19332], + [6428, 11704, 15874], + [4922, 9292, 13052], + [4139, 7695, 11010], + [2291, 4508, 6598], + [19856, 26920, 29828], + [17923, 25289, 28792], + [14278, 21968, 26297], + [10910, 18136, 22950], + [8423, 14815, 19627], + [6771, 12283, 16774], + [4074, 7750, 11081], + [19852, 26074, 28672], + [19371, 26110, 28989], + [16265, 23873, 27663], + [12758, 20378, 24952], + [10095, 17098, 21961], + [8250, 14628, 19451], + [5205, 9745, 13622], + ], + ], + [ + [ + [10563, 16233, 19763], + [9794, 16022, 19804], + [6750, 11945, 15759], + [4963, 9186, 12752], + [3845, 7435, 10627], + [3051, 6085, 8834], + [1311, 2596, 3830], + [11246, 16404, 19689], + [12315, 18911, 22731], + [10557, 17095, 21289], + [8136, 14006, 18249], + [6348, 11474, 15565], + [5196, 9655, 13400], + [2349, 4526, 6587], + [13337, 18730, 21569], + [19306, 26071, 28882], + [15952, 23540, 27254], + [12409, 19934, 24430], + [9760, 16706, 21389], + [8004, 14220, 18818], + [4138, 7794, 10961], + ], + [ + [10870, 16684, 20949], + [9664, 15230, 18680], + [6886, 12109, 15408], + [4825, 8900, 12305], + [3630, 7162, 10314], + [3036, 6429, 9387], + [1671, 3296, 4940], + [13819, 19159, 23026], + [11984, 19108, 23120], + [10690, 17210, 21663], + [7984, 14154, 18333], + [6868, 12294, 16124], + [5274, 8994, 12868], + [2988, 5771, 8424], + [19736, 26647, 29141], + [18933, 26070, 28984], + [15779, 23048, 27200], + [12638, 20061, 24532], + [10692, 17545, 22220], + [9217, 15251, 20054], + [5078, 9284, 12594], + ], + ], + [ + [ + [2331, 3662, 5244], + [2891, 4771, 6145], + [4598, 7623, 9729], + [3520, 6845, 9199], + [3417, 6119, 9324], + [2601, 5412, 7385], + [600, 1173, 1744], + [7672, 13286, 17469], + [4232, 7792, 10793], + [2915, 5317, 7397], + [2318, 4356, 6152], + [2127, 4000, 5554], + [1850, 3478, 5275], + [977, 1933, 2843], + [18280, 24387, 27989], + [15852, 22671, 26185], + [13845, 20951, 24789], + [11055, 17966, 22129], + [9138, 15422, 19801], + [7454, 13145, 17456], + [3370, 6393, 9013], + ], + [ + [5842, 9229, 10838], + [2313, 3491, 4276], + [2998, 6104, 7496], + [2420, 7447, 9868], + [3034, 8495, 10923], + [4076, 8937, 10975], + [1086, 2370, 3299], + [9714, 17254, 20444], + [8543, 13698, 17123], + [4918, 9007, 11910], + [4129, 7532, 10553], + [2364, 5533, 8058], + [1834, 3546, 5563], + [1473, 2908, 4133], + [15405, 21193, 25619], + [15691, 21952, 26561], + [12962, 19194, 24165], + [10272, 17855, 22129], + [8588, 15270, 20718], + [8682, 14669, 19500], + [4870, 9636, 13205], + ], + ], + [ + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [14995, 21341, 24749], + [13158, 20289, 24601], + [8941, 15326, 19876], + [6297, 11541, 15807], + [4817, 9029, 12776], + [3731, 7273, 10627], + [1847, 3617, 5354], + [14472, 19659, 22343], + [16806, 24162, 27533], + [12900, 20404, 24713], + [9411, 16112, 20797], + [7056, 12697, 17148], + [5544, 10339, 14460], + [2954, 5704, 8319], + [12464, 18071, 21354], + [15482, 22528, 26034], + [12070, 19269, 23624], + [8953, 15406, 20106], + [7027, 12730, 17220], + [5887, 10913, 15140], + [3793, 7278, 10447], + ], + [ + [15571, 22232, 25749], + [14506, 21575, 25374], + [10189, 17089, 21569], + [7316, 13301, 17915], + [5783, 10912, 15190], + [4760, 9155, 13088], + [2993, 5966, 8774], + [23424, 28903, 30778], + [20775, 27666, 30290], + [16474, 24410, 28299], + [12471, 20180, 24987], + [9410, 16487, 21439], + [7536, 13614, 18529], + [5048, 9586, 13549], + [21090, 27290, 29756], + [20796, 27402, 30026], + [17819, 25485, 28969], + [13860, 21909, 26462], + [11002, 18494, 23529], + [8953, 15929, 20897], + [6448, 11918, 16454], + ], + ], + [ + [ + [15999, 22208, 25449], + [13050, 19988, 24122], + [8594, 14864, 19378], + [6033, 11079, 15238], + [4554, 8683, 12347], + [3672, 7139, 10337], + [1900, 3771, 5576], + [15788, 21340, 23949], + [16825, 24235, 27758], + [12873, 20402, 24810], + [9590, 16363, 21094], + [7352, 13209, 17733], + [5960, 10989, 15184], + [3232, 6234, 9007], + [15761, 20716, 23224], + [19318, 25989, 28759], + [15529, 23094, 26929], + [11662, 18989, 23641], + [8955, 15568, 20366], + [7281, 13106, 17708], + [4248, 8059, 11440], + ], + [ + [14899, 21217, 24503], + [13519, 20283, 24047], + [9429, 15966, 20365], + [6700, 12355, 16652], + [5088, 9704, 13716], + [4243, 8154, 11731], + [2702, 5364, 7861], + [22745, 28388, 30454], + [20235, 27146, 29922], + [15896, 23715, 27637], + [11840, 19350, 24131], + [9122, 15932, 20880], + [7488, 13581, 18362], + [5114, 9568, 13370], + [20845, 26553, 28932], + [20981, 27372, 29884], + [17781, 25335, 28785], + [13760, 21708, 26297], + [10975, 18415, 23365], + [9045, 15789, 20686], + [6130, 11199, 15423], + ], + ], + [ + [ + [13549, 19724, 23158], + [11844, 18382, 22246], + [7919, 13619, 17773], + [5486, 10143, 13946], + [4166, 7983, 11324], + [3364, 6506, 9427], + [1598, 3160, 4674], + [15281, 20979, 23781], + [14939, 22119, 25952], + [11363, 18407, 22812], + [8609, 14857, 19370], + [6737, 12184, 16480], + [5506, 10263, 14262], + [2990, 5786, 8380], + [20249, 25253, 27417], + [21070, 27518, 30001], + [16854, 24469, 28074], + [12864, 20486, 25000], + [9962, 16978, 21778], + [8074, 14338, 19048], + [4494, 8479, 11906], + ], + [ + [13960, 19617, 22829], + [11150, 17341, 21228], + [7150, 12964, 17190], + [5331, 10002, 13867], + [4167, 7744, 11057], + [3480, 6629, 9646], + [1883, 3784, 5686], + [18752, 25660, 28912], + [16968, 24586, 28030], + [13520, 21055, 25313], + [10453, 17626, 22280], + [8386, 14505, 19116], + [6742, 12595, 17008], + [4273, 8140, 11499], + [22120, 27827, 30233], + [20563, 27358, 29895], + [17076, 24644, 28153], + [13362, 20942, 25309], + [10794, 17965, 22695], + [9014, 15652, 20319], + [5708, 10512, 14497], + ], + ], + [ + [ + [5705, 10930, 15725], + [7946, 12765, 16115], + [6801, 12123, 16226], + [5462, 10135, 14200], + [4189, 8011, 11507], + [3191, 6229, 9408], + [1057, 2137, 3212], + [10018, 17067, 21491], + [7380, 12582, 16453], + [6068, 10845, 14339], + [5098, 9198, 12555], + [4312, 8010, 11119], + [3700, 6966, 9781], + [1693, 3326, 4887], + [18757, 24930, 27774], + [17648, 24596, 27817], + [14707, 22052, 26026], + [11720, 18852, 23292], + [9357, 15952, 20525], + [7810, 13753, 18210], + [3879, 7333, 10328], + ], + [ + [8278, 13242, 15922], + [10547, 15867, 18919], + [9106, 15842, 20609], + [6833, 13007, 17218], + [4811, 9712, 13923], + [3985, 7352, 11128], + [1688, 3458, 5262], + [12951, 21861, 26510], + [9788, 16044, 20276], + [6309, 11244, 14870], + [5183, 9349, 12566], + [4389, 8229, 11492], + [3633, 6945, 10620], + [3600, 6847, 9907], + [21748, 28137, 30255], + [19436, 26581, 29560], + [16359, 24201, 27953], + [13961, 21693, 25871], + [11544, 18686, 23322], + [9372, 16462, 20952], + [6138, 11210, 15390], + ], + ], + [ + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [16138, 22223, 25509], + [15347, 22430, 26332], + [9614, 16736, 21332], + [6600, 12275, 16907], + [4811, 9424, 13547], + [3748, 7809, 11420], + [2254, 4587, 6890], + [15196, 20284, 23177], + [18317, 25469, 28451], + [13918, 21651, 25842], + [10052, 17150, 21995], + [7499, 13630, 18587], + [6158, 11417, 16003], + [4014, 7785, 11252], + [15048, 21067, 24384], + [18202, 25346, 28553], + [14302, 22019, 26356], + [10839, 18139, 23166], + [8715, 15744, 20806], + [7536, 13576, 18544], + [5413, 10335, 14498], + ], + [ + [17394, 24501, 27895], + [15889, 23420, 27185], + [11561, 19133, 23870], + [8285, 14812, 19844], + [6496, 12043, 16550], + [4771, 9574, 13677], + [3603, 6830, 10144], + [21656, 27704, 30200], + [21324, 27915, 30511], + [17327, 25336, 28997], + [13417, 21381, 26033], + [10132, 17425, 22338], + [8580, 15016, 19633], + [5694, 11477, 16411], + [24116, 29780, 31450], + [23853, 29695, 31591], + [20085, 27614, 30428], + [15326, 24335, 28575], + [11814, 19472, 24810], + [10221, 18611, 24767], + [7689, 14558, 20321], + ], + ], + [ + [ + [16214, 22380, 25770], + [14213, 21304, 25295], + [9213, 15823, 20455], + [6395, 11758, 16139], + [4779, 9187, 13066], + [3821, 7501, 10953], + [2293, 4567, 6795], + [15859, 21283, 23820], + [18404, 25602, 28726], + [14325, 21980, 26206], + [10669, 17937, 22720], + [8297, 14642, 19447], + [6746, 12389, 16893], + [4324, 8251, 11770], + [16532, 21631, 24475], + [20667, 27150, 29668], + [16728, 24510, 28175], + [12861, 20645, 25332], + [10076, 17361, 22417], + [8395, 14940, 19963], + [5731, 10683, 14912], + ], + [ + [14433, 21155, 24938], + [14658, 21716, 25545], + [9923, 16824, 21557], + [6982, 13052, 17721], + [5419, 10503, 15050], + [4852, 9162, 13014], + [3271, 6395, 9630], + [22210, 27833, 30109], + [20750, 27368, 29821], + [16894, 24828, 28573], + [13247, 21276, 25757], + [10038, 17265, 22563], + [8587, 14947, 20327], + [5645, 11371, 15252], + [22027, 27526, 29714], + [23098, 29146, 31221], + [19886, 27341, 30272], + [15609, 23747, 28046], + [11993, 20065, 24939], + [9637, 18267, 23671], + [7625, 13801, 19144], + ], + ], + [ + [ + [14438, 20798, 24089], + [12621, 19203, 23097], + [8177, 14125, 18402], + [5674, 10501, 14456], + [4236, 8239, 11733], + [3447, 6750, 9806], + [1986, 3950, 5864], + [16208, 22099, 24930], + [16537, 24025, 27585], + [12780, 20381, 24867], + [9767, 16612, 21416], + [7686, 13738, 18398], + [6333, 11614, 15964], + [3941, 7571, 10836], + [22819, 27422, 29202], + [22224, 28514, 30721], + [17660, 25433, 28913], + [13574, 21482, 26002], + [10629, 17977, 22938], + [8612, 15298, 20265], + [5607, 10491, 14596], + ], + [ + [13569, 19800, 23206], + [13128, 19924, 23869], + [8329, 14841, 19403], + [6130, 10976, 15057], + [4682, 8839, 12518], + [3656, 7409, 10588], + [2577, 5099, 7412], + [22427, 28684, 30585], + [20913, 27750, 30139], + [15840, 24109, 27834], + [12308, 20029, 24569], + [10216, 16785, 21458], + [8309, 14203, 19113], + [6043, 11168, 15307], + [23166, 28901, 30998], + [21899, 28405, 30751], + [18413, 26091, 29443], + [15233, 23114, 27352], + [12683, 20472, 25288], + [10702, 18259, 23409], + [8125, 14464, 19226], + ], + ], + [ + [ + [9040, 14786, 18360], + [9979, 15718, 19415], + [7913, 13918, 18311], + [5859, 10889, 15184], + [4593, 8677, 12510], + [3820, 7396, 10791], + [1730, 3471, 5192], + [11803, 18365, 22709], + [11419, 18058, 22225], + [9418, 15774, 20243], + [7539, 13325, 17657], + [6233, 11317, 15384], + [5137, 9656, 13545], + [2977, 5774, 8349], + [21207, 27246, 29640], + [19547, 26578, 29497], + [16169, 23871, 27690], + [12820, 20458, 25018], + [10224, 17332, 22214], + [8526, 15048, 19884], + [5037, 9410, 13118], + ], + [ + [12339, 17329, 20140], + [13505, 19895, 23225], + [9847, 16944, 21564], + [7280, 13256, 18348], + [4712, 10009, 14454], + [4361, 7914, 12477], + [2870, 5628, 7995], + [20061, 25504, 28526], + [15235, 22878, 26145], + [12985, 19958, 24155], + [9782, 16641, 21403], + [9456, 16360, 20760], + [6855, 12940, 18557], + [5661, 10564, 15002], + [25656, 30602, 31894], + [22570, 29107, 31092], + [18917, 26423, 29541], + [15940, 23649, 27754], + [12803, 20581, 25219], + [11082, 18695, 23376], + [7939, 14373, 19005], + ], + ], + [ + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [18315, 24289, 27551], + [16854, 24068, 27835], + [10140, 17927, 23173], + [6722, 12982, 18267], + [4661, 9826, 14706], + [3832, 8165, 12294], + [2795, 6098, 9245], + [17145, 23326, 26672], + [20733, 27680, 30308], + [16032, 24461, 28546], + [11653, 20093, 25081], + [9290, 16429, 22086], + [7796, 14598, 19982], + [6502, 12378, 17441], + [21681, 27732, 30320], + [22389, 29044, 31261], + [19027, 26731, 30087], + [14739, 23755, 28624], + [11358, 20778, 25511], + [10995, 18073, 24190], + [9162, 14990, 20617], + ], + [ + [21425, 27952, 30388], + [18062, 25838, 29034], + [11956, 19881, 24808], + [7718, 15000, 20980], + [5702, 11254, 16143], + [4898, 9088, 16864], + [3679, 6776, 11907], + [23294, 30160, 31663], + [24397, 29896, 31836], + [19245, 27128, 30593], + [13202, 19825, 26404], + [11578, 19297, 23957], + [8073, 13297, 21370], + [5461, 10923, 19745], + [27367, 30521, 31934], + [24904, 30671, 31940], + [23075, 28460, 31299], + [14400, 23658, 30417], + [13885, 23882, 28325], + [14746, 22938, 27853], + [5461, 16384, 27307], + ], + ], + [ + [ + [18274, 24813, 27890], + [15537, 23149, 27003], + [9449, 16740, 21827], + [6700, 12498, 17261], + [4988, 9866, 14198], + [4236, 8147, 11902], + [2867, 5860, 8654], + [17124, 23171, 26101], + [20396, 27477, 30148], + [16573, 24629, 28492], + [12749, 20846, 25674], + [10233, 17878, 22818], + [8525, 15332, 20363], + [6283, 11632, 16255], + [20466, 26511, 29286], + [23059, 29174, 31191], + [19481, 27263, 30241], + [15458, 23631, 28137], + [12416, 20608, 25693], + [10261, 18011, 23261], + [8016, 14655, 19666], + ], + [ + [17616, 24586, 28112], + [15809, 23299, 27155], + [10767, 18890, 23793], + [7727, 14255, 18865], + [6129, 11926, 16882], + [4482, 9704, 14861], + [3277, 7452, 11522], + [22956, 28551, 30730], + [22724, 28937, 30961], + [18467, 26324, 29580], + [13234, 20713, 25649], + [11181, 17592, 22481], + [8291, 18358, 24576], + [7568, 11881, 14984], + [24948, 29001, 31147], + [25674, 30619, 32151], + [20841, 26793, 29603], + [14669, 24356, 28666], + [11334, 23593, 28219], + [8922, 14762, 22873], + [8301, 13544, 20535], + ], + ], + [ + [ + [17113, 23733, 27081], + [14139, 21406, 25452], + [8552, 15002, 19776], + [5871, 11120, 15378], + [4455, 8616, 12253], + [3469, 6910, 10386], + [2255, 4553, 6782], + [18224, 24376, 27053], + [19290, 26710, 29614], + [14936, 22991, 27184], + [11238, 18951, 23762], + [8786, 15617, 20588], + [7317, 13228, 18003], + [5101, 9512, 13493], + [22639, 28222, 30210], + [23216, 29331, 31307], + [19075, 26762, 29895], + [15014, 23113, 27457], + [11938, 19857, 24752], + [9942, 17280, 22282], + [7167, 13144, 17752], + ], + [ + [15820, 22738, 26488], + [13530, 20885, 25216], + [8395, 15530, 20452], + [6574, 12321, 16380], + [5353, 10419, 14568], + [4613, 8446, 12381], + [3440, 7158, 9903], + [24247, 29051, 31224], + [22118, 28058, 30369], + [16498, 24768, 28389], + [12920, 21175, 26137], + [10730, 18619, 25352], + [10187, 16279, 22791], + [9310, 14631, 22127], + [24970, 30558, 32057], + [24801, 29942, 31698], + [22432, 28453, 30855], + [19054, 25680, 29580], + [14392, 23036, 28109], + [12495, 20947, 26650], + [12442, 20326, 26214], + ], + ], + [ + [ + [12162, 18785, 22648], + [12749, 19697, 23806], + [8580, 15297, 20346], + [6169, 11749, 16543], + [4836, 9391, 13448], + [3821, 7711, 11613], + [2228, 4601, 7070], + [16319, 24725, 28280], + [15698, 23277, 27168], + [12726, 20368, 25047], + [9912, 17015, 21976], + [7888, 14220, 19179], + [6777, 12284, 17018], + [4492, 8590, 12252], + [23249, 28904, 30947], + [21050, 27908, 30512], + [17440, 25340, 28949], + [14059, 22018, 26541], + [11288, 18903, 23898], + [9411, 16342, 21428], + [6278, 11588, 15944], + ], + [ + [13981, 20067, 23226], + [16922, 23580, 26783], + [11005, 19039, 24487], + [7389, 14218, 19798], + [5598, 11505, 17206], + [6090, 11213, 15659], + [3820, 7371, 10119], + [21082, 26925, 29675], + [21262, 28627, 31128], + [18392, 26454, 30437], + [14870, 22910, 27096], + [12620, 19484, 24908], + [9290, 16553, 22802], + [6668, 14288, 20004], + [27704, 31055, 31949], + [24709, 29978, 31788], + [21668, 29264, 31657], + [18295, 26968, 30074], + [16399, 24422, 29313], + [14347, 23026, 28104], + [12370, 19806, 24477], + ], + ], + [ + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], +]); + +pub static av1_default_coeff_base_multi_cdfs: [[[[[u16; NUM_BASE_LEVELS + 2]; + SIG_COEF_CONTEXTS]; + PLANE_TYPES]; + TxSize::TX_SIZES]; + TOKEN_CDF_Q_CTXS] = cdf_5d([ + [ + [ + [ + [4034, 8930, 12727], + [18082, 29741, 31877], + [12596, 26124, 30493], + [9446, 21118, 27005], + [6308, 15141, 21279], + [2463, 6357, 9783], + [20667, 30546, 31929], + [13043, 26123, 30134], + [8151, 18757, 24778], + [5255, 12839, 18632], + [2820, 7206, 11161], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [15736, 27553, 30604], + [11210, 23794, 28787], + [5947, 13874, 19701], + [4215, 9323, 13891], + [2833, 6462, 10059], + [19605, 30393, 31582], + [13523, 26252, 30248], + [8446, 18622, 24512], + [3818, 10343, 15974], + [1481, 4117, 6796], + [22649, 31302, 32190], + [14829, 27127, 30449], + [8313, 17702, 23304], + [3022, 8301, 12786], + [1536, 4412, 7184], + [22354, 29774, 31372], + [14723, 25472, 29214], + [6673, 13745, 18662], + [2068, 5766, 9322], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [6302, 16444, 21761], + [23040, 31538, 32475], + [15196, 28452, 31496], + [10020, 22946, 28514], + [6533, 16862, 23501], + [3538, 9816, 15076], + [24444, 31875, 32525], + [15881, 28924, 31635], + [9922, 22873, 28466], + [6527, 16966, 23691], + [4114, 11303, 17220], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [20201, 30770, 32209], + [14754, 28071, 31258], + [8378, 20186, 26517], + [5916, 15299, 21978], + [4268, 11583, 17901], + [24361, 32025, 32581], + [18673, 30105, 31943], + [10196, 22244, 27576], + [5495, 14349, 20417], + [2676, 7415, 11498], + [24678, 31958, 32585], + [18629, 29906, 31831], + [9364, 20724, 26315], + [4641, 12318, 18094], + [2758, 7387, 11579], + [25433, 31842, 32469], + [18795, 29289, 31411], + [7644, 17584, 23592], + [3408, 9014, 15047], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [4536, 10072, 14001], + [25459, 31416, 32206], + [16605, 28048, 30818], + [11008, 22857, 27719], + [6915, 16268, 22315], + [2625, 6812, 10537], + [24257, 31788, 32499], + [16880, 29454, 31879], + [11958, 25054, 29778], + [7916, 18718, 25084], + [3383, 8777, 13446], + [22720, 31603, 32393], + [14960, 28125, 31335], + [9731, 22210, 27928], + [6304, 15832, 22277], + [2910, 7818, 12166], + [20375, 30627, 32131], + [13904, 27284, 30887], + [9368, 21558, 27144], + [5937, 14966, 21119], + [2667, 7225, 11319], + [23970, 31470, 32378], + [17173, 29734, 32018], + [12795, 25441, 29965], + [8981, 19680, 25893], + [4728, 11372, 16902], + [24287, 31797, 32439], + [16703, 29145, 31696], + [10833, 23554, 28725], + [6468, 16566, 23057], + [2415, 6562, 10278], + [26610, 32395, 32659], + [18590, 30498, 32117], + [12420, 25756, 29950], + [7639, 18746, 24710], + [3001, 8086, 12347], + [25076, 32064, 32580], + [17946, 30128, 32028], + [12024, 24985, 29378], + [7517, 18390, 24304], + [3243, 8781, 13331], + [8192, 16384, 24576], + ], + [ + [6037, 16771, 21957], + [24774, 31704, 32426], + [16830, 28589, 31056], + [10602, 22828, 27760], + [6733, 16829, 23071], + [3250, 8914, 13556], + [25582, 32220, 32668], + [18659, 30342, 32223], + [12546, 26149, 30515], + [8420, 20451, 26801], + [4636, 12420, 18344], + [27581, 32362, 32639], + [18987, 30083, 31978], + [11327, 24248, 29084], + [7264, 17719, 24120], + [3995, 10768, 16169], + [25893, 31831, 32487], + [16577, 28587, 31379], + [10189, 22748, 28182], + [6832, 17094, 23556], + [3708, 10110, 15334], + [25904, 32282, 32656], + [19721, 30792, 32276], + [12819, 26243, 30411], + [8572, 20614, 26891], + [5364, 14059, 20467], + [26580, 32438, 32677], + [20852, 31225, 32340], + [12435, 25700, 29967], + [8691, 20825, 26976], + [4446, 12209, 17269], + [27350, 32429, 32696], + [21372, 30977, 32272], + [12673, 25270, 29853], + [9208, 20925, 26640], + [5018, 13351, 18732], + [27351, 32479, 32713], + [21398, 31209, 32387], + [12162, 25047, 29842], + [7896, 18691, 25319], + [4670, 12882, 18881], + [8192, 16384, 24576], + ], + ], + [ + [ + [5487, 10460, 13708], + [21597, 28303, 30674], + [11037, 21953, 26476], + [8147, 17962, 22952], + [5242, 13061, 18532], + [1889, 5208, 8182], + [26774, 32133, 32590], + [17844, 29564, 31767], + [11690, 24438, 29171], + [7542, 18215, 24459], + [2993, 8050, 12319], + [28023, 32328, 32591], + [18651, 30126, 31954], + [12164, 25146, 29589], + [7762, 18530, 24771], + [3492, 9183, 13920], + [27591, 32008, 32491], + [17149, 28853, 31510], + [11485, 24003, 28860], + [7697, 18086, 24210], + [3075, 7999, 12218], + [28268, 32482, 32654], + [19631, 31051, 32404], + [13860, 27260, 31020], + [9605, 21613, 27594], + [4876, 12162, 17908], + [27248, 32316, 32576], + [18955, 30457, 32075], + [11824, 23997, 28795], + [7346, 18196, 24647], + [3403, 9247, 14111], + [29711, 32655, 32735], + [21169, 31394, 32417], + [13487, 27198, 30957], + [8828, 21683, 27614], + [4270, 11451, 17038], + [28708, 32578, 32731], + [20120, 31241, 32482], + [13692, 27550, 31321], + [9418, 22514, 28439], + [4999, 13283, 19462], + [8192, 16384, 24576], + ], + [ + [5673, 14302, 19711], + [26251, 30701, 31834], + [12782, 23783, 27803], + [9127, 20657, 25808], + [6368, 16208, 21462], + [2465, 7177, 10822], + [29961, 32563, 32719], + [18318, 29891, 31949], + [11361, 24514, 29357], + [7900, 19603, 25607], + [4002, 10590, 15546], + [29637, 32310, 32595], + [18296, 29913, 31809], + [10144, 21515, 26871], + [5358, 14322, 20394], + [3067, 8362, 13346], + [28652, 32470, 32676], + [17538, 30771, 32209], + [13924, 26882, 30494], + [10496, 22837, 27869], + [7236, 16396, 21621], + [30743, 32687, 32746], + [23006, 31676, 32489], + [14494, 27828, 31120], + [10174, 22801, 28352], + [6242, 15281, 21043], + [25817, 32243, 32720], + [18618, 31367, 32325], + [13997, 28318, 31878], + [12255, 26534, 31383], + [9561, 21588, 28450], + [28188, 32635, 32724], + [22060, 32365, 32728], + [18102, 30690, 32528], + [14196, 28864, 31999], + [12262, 25792, 30865], + [24176, 32109, 32628], + [18280, 29681, 31963], + [10205, 23703, 29664], + [7889, 20025, 27676], + [6060, 16743, 23970], + [8192, 16384, 24576], + ], + ], + [ + [ + [5141, 7096, 8260], + [27186, 29022, 29789], + [6668, 12568, 15682], + [2172, 6181, 8638], + [1126, 3379, 4531], + [443, 1361, 2254], + [26083, 31153, 32436], + [13486, 24603, 28483], + [6508, 14840, 19910], + [3386, 8800, 13286], + [1530, 4322, 7054], + [29639, 32080, 32548], + [15897, 27552, 30290], + [8588, 20047, 25383], + [4889, 13339, 19269], + [2240, 6871, 10498], + [28165, 32197, 32517], + [20735, 30427, 31568], + [14325, 24671, 27692], + [5119, 12554, 17805], + [1810, 5441, 8261], + [31212, 32724, 32748], + [23352, 31766, 32545], + [14669, 27570, 31059], + [8492, 20894, 27272], + [3644, 10194, 15204], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [2461, 7013, 9371], + [24749, 29600, 30986], + [9466, 19037, 22417], + [3584, 9280, 14400], + [1505, 3929, 5433], + [677, 1500, 2736], + [23987, 30702, 32117], + [13554, 24571, 29263], + [6211, 14556, 21155], + [3135, 10972, 15625], + [2435, 7127, 11427], + [31300, 32532, 32550], + [14757, 30365, 31954], + [4405, 11612, 18553], + [580, 4132, 7322], + [1695, 10169, 14124], + [30008, 32282, 32591], + [19244, 30108, 31748], + [11180, 24158, 29555], + [5650, 14972, 19209], + [2114, 5109, 8456], + [31856, 32716, 32748], + [23012, 31664, 32572], + [13694, 26656, 30636], + [8142, 19508, 26093], + [4253, 10955, 16724], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [601, 983, 1311], + [18725, 23406, 28087], + [5461, 8192, 10923], + [3781, 15124, 21425], + [2587, 7761, 12072], + [106, 458, 810], + [22282, 29710, 31894], + [8508, 20926, 25984], + [3726, 12713, 18083], + [1620, 7112, 10893], + [729, 2236, 3495], + [30163, 32474, 32684], + [18304, 30464, 32000], + [11443, 26526, 29647], + [6007, 15292, 21299], + [2234, 6703, 8937], + [30954, 32177, 32571], + [17363, 29562, 31076], + [9686, 22464, 27410], + [8192, 16384, 21390], + [1755, 8046, 11264], + [31168, 32734, 32748], + [22486, 31441, 32471], + [12833, 25627, 29738], + [6980, 17379, 23122], + [3111, 8887, 13479], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [6041, 11854, 15927], + [20326, 30905, 32251], + [14164, 26831, 30725], + [9760, 20647, 26585], + [6416, 14953, 21219], + [2966, 7151, 10891], + [23567, 31374, 32254], + [14978, 27416, 30946], + [9434, 20225, 26254], + [6658, 14558, 20535], + [3916, 8677, 12989], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [18088, 29545, 31587], + [13062, 25843, 30073], + [8940, 16827, 22251], + [7654, 13220, 17973], + [5733, 10316, 14456], + [22879, 31388, 32114], + [15215, 27993, 30955], + [9397, 19445, 24978], + [3442, 9813, 15344], + [1368, 3936, 6532], + [25494, 32033, 32406], + [16772, 27963, 30718], + [9419, 18165, 23260], + [2677, 7501, 11797], + [1516, 4344, 7170], + [26556, 31454, 32101], + [17128, 27035, 30108], + [8324, 15344, 20249], + [1903, 5696, 9469], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8455, 19003, 24368], + [23563, 32021, 32604], + [16237, 29446, 31935], + [10724, 23999, 29358], + [6725, 17528, 24416], + [3927, 10927, 16825], + [26313, 32288, 32634], + [17430, 30095, 32095], + [11116, 24606, 29679], + [7195, 18384, 25269], + [4726, 12852, 19315], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [22822, 31648, 32483], + [16724, 29633, 31929], + [10261, 23033, 28725], + [7029, 17840, 24528], + [4867, 13886, 21502], + [25298, 31892, 32491], + [17809, 29330, 31512], + [9668, 21329, 26579], + [4774, 12956, 18976], + [2322, 7030, 11540], + [25472, 31920, 32543], + [17957, 29387, 31632], + [9196, 20593, 26400], + [4680, 12705, 19202], + [2917, 8456, 13436], + [26471, 32059, 32574], + [18458, 29783, 31909], + [8400, 19464, 25956], + [3812, 10973, 17206], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [6779, 13743, 17678], + [24806, 31797, 32457], + [17616, 29047, 31372], + [11063, 23175, 28003], + [6521, 16110, 22324], + [2764, 7504, 11654], + [25266, 32367, 32637], + [19054, 30553, 32175], + [12139, 25212, 29807], + [7311, 18162, 24704], + [3397, 9164, 14074], + [25988, 32208, 32522], + [16253, 28912, 31526], + [9151, 21387, 27372], + [5688, 14915, 21496], + [2717, 7627, 12004], + [23144, 31855, 32443], + [16070, 28491, 31325], + [8702, 20467, 26517], + [5243, 13956, 20367], + [2621, 7335, 11567], + [26636, 32340, 32630], + [19990, 31050, 32341], + [13243, 26105, 30315], + [8588, 19521, 25918], + [4717, 11585, 17304], + [25844, 32292, 32582], + [19090, 30635, 32097], + [11963, 24546, 28939], + [6218, 16087, 22354], + [2340, 6608, 10426], + [28046, 32576, 32694], + [21178, 31313, 32296], + [13486, 26184, 29870], + [7149, 17871, 23723], + [2833, 7958, 12259], + [27710, 32528, 32686], + [20674, 31076, 32268], + [12413, 24955, 29243], + [6676, 16927, 23097], + [2966, 8333, 12919], + [8192, 16384, 24576], + ], + [ + [8639, 19339, 24429], + [24404, 31837, 32525], + [16997, 29425, 31784], + [11253, 24234, 29149], + [6751, 17394, 24028], + [3490, 9830, 15191], + [26283, 32471, 32714], + [19599, 31168, 32442], + [13146, 26954, 30893], + [8214, 20588, 26890], + [4699, 13081, 19300], + [28212, 32458, 32669], + [18594, 30316, 32100], + [11219, 24408, 29234], + [6865, 17656, 24149], + [3678, 10362, 16006], + [25825, 32136, 32616], + [17313, 29853, 32021], + [11197, 24471, 29472], + [6947, 17781, 24405], + [3768, 10660, 16261], + [27352, 32500, 32706], + [20850, 31468, 32469], + [14021, 27707, 31133], + [8964, 21748, 27838], + [5437, 14665, 21187], + [26304, 32492, 32698], + [20409, 31380, 32385], + [13682, 27222, 30632], + [8974, 21236, 26685], + [4234, 11665, 16934], + [26273, 32357, 32711], + [20672, 31242, 32441], + [14172, 27254, 30902], + [9870, 21898, 27275], + [5164, 13506, 19270], + [26725, 32459, 32728], + [20991, 31442, 32527], + [13071, 26434, 30811], + [8184, 20090, 26742], + [4803, 13255, 19895], + [8192, 16384, 24576], + ], + ], + [ + [ + [7555, 14942, 18501], + [24410, 31178, 32287], + [14394, 26738, 30253], + [8413, 19554, 25195], + [4766, 12924, 18785], + [2029, 5806, 9207], + [26776, 32364, 32663], + [18732, 29967, 31931], + [11005, 23786, 28852], + [6466, 16909, 23510], + [3044, 8638, 13419], + [29208, 32582, 32704], + [20068, 30857, 32208], + [12003, 25085, 29595], + [6947, 17750, 24189], + [3245, 9103, 14007], + [27359, 32465, 32669], + [19421, 30614, 32174], + [11915, 25010, 29579], + [6950, 17676, 24074], + [3007, 8473, 13096], + [29002, 32676, 32735], + [22102, 31849, 32576], + [14408, 28009, 31405], + [9027, 21679, 27931], + [4694, 12678, 18748], + [28216, 32528, 32682], + [20849, 31264, 32318], + [12756, 25815, 29751], + [7565, 18801, 24923], + [3509, 9533, 14477], + [30133, 32687, 32739], + [23063, 31910, 32515], + [14588, 28051, 31132], + [9085, 21649, 27457], + [4261, 11654, 17264], + [29518, 32691, 32748], + [22451, 31959, 32613], + [14864, 28722, 31700], + [9695, 22964, 28716], + [4932, 13358, 19502], + [8192, 16384, 24576], + ], + [ + [6465, 16958, 21688], + [25199, 31514, 32360], + [14774, 27149, 30607], + [9257, 21438, 26972], + [5723, 15183, 21882], + [3150, 8879, 13731], + [26989, 32262, 32682], + [17396, 29937, 32085], + [11387, 24901, 29784], + [7289, 18821, 25548], + [3734, 10577, 16086], + [29728, 32501, 32695], + [17431, 29701, 31903], + [9921, 22826, 28300], + [5896, 15434, 22068], + [3430, 9646, 14757], + [28614, 32511, 32705], + [19364, 30638, 32263], + [13129, 26254, 30402], + [8754, 20484, 26440], + [4378, 11607, 17110], + [30292, 32671, 32744], + [21780, 31603, 32501], + [14314, 27829, 31291], + [9611, 22327, 28263], + [4890, 13087, 19065], + [25862, 32567, 32733], + [20794, 32050, 32567], + [17243, 30625, 32254], + [13283, 27628, 31474], + [9669, 22532, 28918], + [27435, 32697, 32748], + [24922, 32390, 32714], + [21449, 31504, 32536], + [16392, 29729, 31832], + [11692, 24884, 29076], + [24193, 32290, 32735], + [18909, 31104, 32563], + [12236, 26841, 31403], + [8171, 21840, 29082], + [7224, 17280, 25275], + [8192, 16384, 24576], + ], + ], + [ + [ + [3078, 6839, 9890], + [13837, 20450, 24479], + [5914, 14222, 19328], + [3866, 10267, 14762], + [2612, 7208, 11042], + [1067, 2991, 4776], + [25817, 31646, 32529], + [13708, 26338, 30385], + [7328, 18585, 24870], + [4691, 13080, 19276], + [1825, 5253, 8352], + [29386, 32315, 32624], + [17160, 29001, 31360], + [9602, 21862, 27396], + [5915, 15772, 22148], + [2786, 7779, 12047], + [29246, 32450, 32663], + [18696, 29929, 31818], + [10510, 23369, 28560], + [6229, 16499, 23125], + [2608, 7448, 11705], + [30753, 32710, 32748], + [21638, 31487, 32503], + [12937, 26854, 30870], + [8182, 20596, 26970], + [3637, 10269, 15497], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [5244, 12150, 16906], + [20486, 26858, 29701], + [7756, 18317, 23735], + [3452, 9256, 13146], + [2020, 5206, 8229], + [1801, 4993, 7903], + [27051, 31858, 32531], + [15988, 27531, 30619], + [9188, 21484, 26719], + [6273, 17186, 23800], + [3108, 9355, 14764], + [31076, 32520, 32680], + [18119, 30037, 31850], + [10244, 22969, 27472], + [4692, 14077, 19273], + [3694, 11677, 17556], + [30060, 32581, 32720], + [21011, 30775, 32120], + [11931, 24820, 29289], + [7119, 17662, 24356], + [3833, 10706, 16304], + [31954, 32731, 32748], + [23913, 31724, 32489], + [15520, 28060, 31286], + [11517, 23008, 28571], + [6193, 14508, 20629], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [1035, 2807, 4156], + [13162, 18138, 20939], + [2696, 6633, 8755], + [1373, 4161, 6853], + [1099, 2746, 4716], + [340, 1021, 1599], + [22826, 30419, 32135], + [10395, 21762, 26942], + [4726, 12407, 17361], + [2447, 7080, 10593], + [1227, 3717, 6011], + [28156, 31424, 31934], + [16915, 27754, 30373], + [9148, 20990, 26431], + [5950, 15515, 21148], + [2492, 7327, 11526], + [30602, 32477, 32670], + [20026, 29955, 31568], + [11220, 23628, 28105], + [6652, 17019, 22973], + [3064, 8536, 13043], + [31769, 32724, 32748], + [22230, 30887, 32373], + [12234, 25079, 29731], + [7326, 18816, 25353], + [3933, 10907, 16616], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [8896, 16227, 20630], + [23629, 31782, 32527], + [15173, 27755, 31321], + [10158, 21233, 27382], + [6420, 14857, 21558], + [3269, 8155, 12646], + [24835, 32009, 32496], + [16509, 28421, 31579], + [10957, 21514, 27418], + [7881, 15930, 22096], + [5388, 10960, 15918], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [20745, 30773, 32093], + [15200, 27221, 30861], + [13032, 20873, 25667], + [12285, 18663, 23494], + [11563, 17481, 21489], + [26260, 31982, 32320], + [15397, 28083, 31100], + [9742, 19217, 24824], + [3261, 9629, 15362], + [1480, 4322, 7499], + [27599, 32256, 32460], + [16857, 27659, 30774], + [9551, 18290, 23748], + [3052, 8933, 14103], + [2021, 5910, 9787], + [29005, 32015, 32392], + [17677, 27694, 30863], + [9204, 17356, 23219], + [2403, 7516, 12814], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [10808, 22056, 26896], + [25739, 32313, 32676], + [17288, 30203, 32221], + [11359, 24878, 29896], + [6949, 17767, 24893], + [4287, 11796, 18071], + [27880, 32521, 32705], + [19038, 31004, 32414], + [12564, 26345, 30768], + [8269, 19947, 26779], + [5674, 14657, 21674], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [25742, 32319, 32671], + [19557, 31164, 32454], + [13381, 26381, 30755], + [10101, 21466, 26722], + [9209, 19650, 26825], + [27107, 31917, 32432], + [18056, 28893, 31203], + [10200, 21434, 26764], + [4660, 12913, 19502], + [2368, 6930, 12504], + [26960, 32158, 32613], + [18628, 30005, 32031], + [10233, 22442, 28232], + [5471, 14630, 21516], + [3235, 10767, 17109], + [27696, 32440, 32692], + [20032, 31167, 32438], + [8700, 21341, 28442], + [5662, 14831, 21795], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [9704, 17294, 21132], + [26762, 32278, 32633], + [18382, 29620, 31819], + [10891, 23475, 28723], + [6358, 16583, 23309], + [3248, 9118, 14141], + [27204, 32573, 32699], + [19818, 30824, 32329], + [11772, 25120, 30041], + [6995, 18033, 25039], + [3752, 10442, 16098], + [27222, 32256, 32559], + [15356, 28399, 31475], + [8821, 20635, 27057], + [5511, 14404, 21239], + [2935, 8222, 13051], + [24875, 32120, 32529], + [15233, 28265, 31445], + [8605, 20570, 26932], + [5431, 14413, 21196], + [2994, 8341, 13223], + [28201, 32604, 32700], + [21041, 31446, 32456], + [13221, 26213, 30475], + [8255, 19385, 26037], + [4930, 12585, 18830], + [28768, 32448, 32627], + [19705, 30561, 32021], + [11572, 23589, 28220], + [5532, 15034, 21446], + [2460, 7150, 11456], + [29874, 32619, 32699], + [21621, 31071, 32201], + [12511, 24747, 28992], + [6281, 16395, 22748], + [3246, 9278, 14497], + [29715, 32625, 32712], + [20958, 31011, 32283], + [11233, 23671, 28806], + [6012, 16128, 22868], + [3427, 9851, 15414], + [8192, 16384, 24576], + ], + [ + [11016, 22111, 26794], + [25946, 32357, 32677], + [17890, 30452, 32252], + [11678, 25142, 29816], + [6720, 17534, 24584], + [4230, 11665, 17820], + [28400, 32623, 32747], + [21164, 31668, 32575], + [13572, 27388, 31182], + [8234, 20750, 27358], + [5065, 14055, 20897], + [28981, 32547, 32705], + [18681, 30543, 32239], + [10919, 24075, 29286], + [6431, 17199, 24077], + [3819, 10464, 16618], + [26870, 32467, 32693], + [19041, 30831, 32347], + [11794, 25211, 30016], + [6888, 18019, 24970], + [4370, 12363, 18992], + [29578, 32670, 32744], + [23159, 32007, 32613], + [15315, 28669, 31676], + [9298, 22607, 28782], + [6144, 15913, 22968], + [28110, 32499, 32669], + [21574, 30937, 32015], + [12759, 24818, 28727], + [6545, 16761, 23042], + [3649, 10597, 16833], + [28163, 32552, 32728], + [22101, 31469, 32464], + [13160, 25472, 30143], + [7303, 18684, 25468], + [5241, 13975, 20955], + [28400, 32631, 32744], + [22104, 31793, 32603], + [13557, 26571, 30846], + [7749, 19861, 26675], + [4873, 14030, 21234], + [8192, 16384, 24576], + ], + ], + [ + [ + [9800, 17635, 21073], + [26153, 31885, 32527], + [15038, 27852, 31006], + [8718, 20564, 26486], + [5128, 14076, 20514], + [2636, 7566, 11925], + [27551, 32504, 32701], + [18310, 30054, 32100], + [10211, 23420, 29082], + [6222, 16876, 23916], + [3462, 9954, 15498], + [29991, 32633, 32721], + [19883, 30751, 32201], + [11141, 24184, 29285], + [6420, 16940, 23774], + [3392, 9753, 15118], + [28465, 32616, 32712], + [19850, 30702, 32244], + [10983, 24024, 29223], + [6294, 16770, 23582], + [3244, 9283, 14509], + [30023, 32717, 32748], + [22940, 32032, 32626], + [14282, 27928, 31473], + [8562, 21327, 27914], + [4846, 13393, 19919], + [29981, 32590, 32695], + [20465, 30963, 32166], + [11479, 23579, 28195], + [5916, 15648, 22073], + [3031, 8605, 13398], + [31146, 32691, 32739], + [23106, 31724, 32444], + [13783, 26738, 30439], + [7852, 19468, 25807], + [3860, 11124, 16853], + [31014, 32724, 32748], + [23629, 32109, 32628], + [14747, 28115, 31403], + [8545, 21242, 27478], + [4574, 12781, 19067], + [8192, 16384, 24576], + ], + [ + [9185, 19694, 24688], + [26081, 31985, 32621], + [16015, 29000, 31787], + [10542, 23690, 29206], + [6732, 17945, 24677], + [3916, 11039, 16722], + [28224, 32566, 32744], + [19100, 31138, 32485], + [12528, 26620, 30879], + [7741, 20277, 26885], + [4566, 12845, 18990], + [29933, 32593, 32718], + [17670, 30333, 32155], + [10385, 23600, 28909], + [6243, 16236, 22407], + [3976, 10389, 16017], + [28377, 32561, 32738], + [19366, 31175, 32482], + [13327, 27175, 31094], + [8258, 20769, 27143], + [4703, 13198, 19527], + [31086, 32706, 32748], + [22853, 31902, 32583], + [14759, 28186, 31419], + [9284, 22382, 28348], + [5585, 15192, 21868], + [28291, 32652, 32746], + [19849, 32107, 32571], + [14834, 26818, 29214], + [10306, 22594, 28672], + [6615, 17384, 23384], + [28947, 32604, 32745], + [25625, 32289, 32646], + [18758, 28672, 31403], + [10017, 23430, 28523], + [6862, 15269, 22131], + [23933, 32509, 32739], + [19927, 31495, 32631], + [11903, 26023, 30621], + [7026, 20094, 27252], + [5998, 18106, 24437], + [8192, 16384, 24576], + ], + ], + [ + [ + [4456, 11274, 15533], + [21219, 29079, 31616], + [11173, 23774, 28567], + [7282, 18293, 24263], + [4890, 13286, 19115], + [1890, 5508, 8659], + [26651, 32136, 32647], + [14630, 28254, 31455], + [8716, 21287, 27395], + [5615, 15331, 22008], + [2675, 7700, 12150], + [29954, 32526, 32690], + [16126, 28982, 31633], + [9030, 21361, 27352], + [5411, 14793, 21271], + [2943, 8422, 13163], + [29539, 32601, 32730], + [18125, 30385, 32201], + [10422, 24090, 29468], + [6468, 17487, 24438], + [2970, 8653, 13531], + [30912, 32715, 32748], + [20666, 31373, 32497], + [12509, 26640, 30917], + [8058, 20629, 27290], + [4231, 12006, 18052], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [10202, 20633, 25484], + [27336, 31445, 32352], + [12420, 24384, 28552], + [7648, 18115, 23856], + [5662, 14341, 19902], + [3611, 10328, 15390], + [30945, 32616, 32736], + [18682, 30505, 32253], + [11513, 25336, 30203], + [7449, 19452, 26148], + [4482, 13051, 18886], + [32022, 32690, 32747], + [18578, 30501, 32146], + [11249, 23368, 28631], + [5645, 16958, 22158], + [5009, 11444, 16637], + [31357, 32710, 32748], + [21552, 31494, 32504], + [13891, 27677, 31340], + [9051, 22098, 28172], + [5190, 13377, 19486], + [32364, 32740, 32748], + [24839, 31907, 32551], + [17160, 28779, 31696], + [12452, 24137, 29602], + [6165, 15389, 22477], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [2575, 7281, 11077], + [14002, 20866, 25402], + [6343, 15056, 19658], + [4474, 11858, 17041], + [2865, 8299, 12534], + [1344, 3949, 6391], + [24720, 31239, 32459], + [12585, 25356, 29968], + [7181, 18246, 24444], + [5025, 13667, 19885], + [2521, 7304, 11605], + [29908, 32252, 32584], + [17421, 29156, 31575], + [9889, 22188, 27782], + [5878, 15647, 22123], + [2814, 8665, 13323], + [30183, 32568, 32713], + [18528, 30195, 32049], + [10982, 24606, 29657], + [6957, 18165, 25231], + [3508, 10118, 15468], + [31761, 32736, 32748], + [21041, 31328, 32546], + [12568, 26732, 31166], + [8052, 20720, 27733], + [4336, 12192, 18396], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], + [ + [ + [ + [7062, 16472, 22319], + [24538, 32261, 32674], + [13675, 28041, 31779], + [8590, 20674, 27631], + [5685, 14675, 22013], + [3655, 9898, 15731], + [26493, 32418, 32658], + [16376, 29342, 32090], + [10594, 22649, 28970], + [8176, 17170, 24303], + [5605, 12694, 19139], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [23888, 31902, 32542], + [18612, 29687, 31987], + [16245, 24852, 29249], + [15765, 22608, 27559], + [19895, 24699, 27510], + [28401, 32212, 32457], + [15274, 27825, 30980], + [9364, 18128, 24332], + [2283, 8193, 15082], + [1228, 3972, 7881], + [29455, 32469, 32620], + [17981, 28245, 31388], + [10921, 20098, 26240], + [3743, 11829, 18657], + [2374, 9593, 15715], + [31068, 32466, 32635], + [20321, 29572, 31971], + [10771, 20255, 27119], + [2795, 10410, 17361], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [9320, 22102, 27840], + [27057, 32464, 32724], + [16331, 30268, 32309], + [10319, 23935, 29720], + [6189, 16448, 24106], + [3589, 10884, 18808], + [29026, 32624, 32748], + [19226, 31507, 32587], + [12692, 26921, 31203], + [7049, 19532, 27635], + [7727, 15669, 23252], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [28056, 32625, 32748], + [22383, 32075, 32669], + [15417, 27098, 31749], + [18127, 26493, 27190], + [5461, 16384, 21845], + [27982, 32091, 32584], + [19045, 29868, 31972], + [10397, 22266, 27932], + [5990, 13697, 21500], + [1792, 6912, 15104], + [28198, 32501, 32718], + [21534, 31521, 32569], + [11109, 25217, 30017], + [5671, 15124, 26151], + [4681, 14043, 18725], + [28688, 32580, 32741], + [22576, 32079, 32661], + [10627, 22141, 28340], + [9362, 14043, 28087], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [7754, 16948, 22142], + [25670, 32330, 32691], + [15663, 29225, 31994], + [9878, 23288, 29158], + [6419, 17088, 24336], + [3859, 11003, 17039], + [27562, 32595, 32725], + [17575, 30588, 32399], + [10819, 24838, 30309], + [7124, 18686, 25916], + [4479, 12688, 19340], + [28385, 32476, 32673], + [15306, 29005, 31938], + [8937, 21615, 28322], + [5982, 15603, 22786], + [3620, 10267, 16136], + [27280, 32464, 32667], + [15607, 29160, 32004], + [9091, 22135, 28740], + [6232, 16632, 24020], + [4047, 11377, 17672], + [29220, 32630, 32718], + [19650, 31220, 32462], + [13050, 26312, 30827], + [9228, 20870, 27468], + [6146, 15149, 21971], + [30169, 32481, 32623], + [17212, 29311, 31554], + [9911, 21311, 26882], + [4487, 13314, 20372], + [2570, 7772, 12889], + [30924, 32613, 32708], + [19490, 30206, 32107], + [11232, 23998, 29276], + [6769, 17955, 25035], + [4398, 12623, 19214], + [30609, 32627, 32722], + [19370, 30582, 32287], + [10457, 23619, 29409], + [6443, 17637, 24834], + [4645, 13236, 20106], + [8192, 16384, 24576], + ], + [ + [8626, 20271, 26216], + [26707, 32406, 32711], + [16999, 30329, 32286], + [11445, 25123, 30286], + [6411, 18828, 25601], + [6801, 12458, 20248], + [29918, 32682, 32748], + [20649, 31739, 32618], + [12879, 27773, 31581], + [7896, 21751, 28244], + [5260, 14870, 23698], + [29252, 32593, 32731], + [17072, 30460, 32294], + [10653, 24143, 29365], + [6536, 17490, 23983], + [4929, 13170, 20085], + [28137, 32518, 32715], + [18171, 30784, 32407], + [11437, 25436, 30459], + [7252, 18534, 26176], + [4126, 13353, 20978], + [31162, 32726, 32748], + [23017, 32222, 32701], + [15629, 29233, 32046], + [9387, 22621, 29480], + [6922, 17616, 25010], + [28838, 32265, 32614], + [19701, 30206, 31920], + [11214, 22410, 27933], + [5320, 14177, 23034], + [5049, 12881, 17827], + [27484, 32471, 32734], + [21076, 31526, 32561], + [12707, 26303, 31211], + [8169, 21722, 28219], + [6045, 19406, 27042], + [27753, 32572, 32745], + [20832, 31878, 32653], + [13250, 27356, 31674], + [7718, 21508, 29858], + [7209, 18350, 25559], + [8192, 16384, 24576], + ], + ], + [ + [ + [7876, 16901, 21741], + [24001, 31898, 32625], + [14529, 27959, 31451], + [8273, 20818, 27258], + [5278, 14673, 21510], + [2983, 8843, 14039], + [28016, 32574, 32732], + [17471, 30306, 32301], + [10224, 24063, 29728], + [6602, 17954, 25052], + [4002, 11585, 17759], + [30190, 32634, 32739], + [17497, 30282, 32270], + [10229, 23729, 29538], + [6344, 17211, 24440], + [3849, 11189, 17108], + [28570, 32583, 32726], + [17521, 30161, 32238], + [10153, 23565, 29378], + [6455, 17341, 24443], + [3907, 11042, 17024], + [30689, 32715, 32748], + [21546, 31840, 32610], + [13547, 27581, 31459], + [8912, 21757, 28309], + [5548, 15080, 22046], + [30783, 32540, 32685], + [17540, 29528, 31668], + [10160, 21468, 26783], + [4724, 13393, 20054], + [2702, 8174, 13102], + [31648, 32686, 32742], + [20954, 31094, 32337], + [12420, 25698, 30179], + [7304, 19320, 26248], + [4366, 12261, 18864], + [31581, 32723, 32748], + [21373, 31586, 32525], + [12744, 26625, 30885], + [7431, 20322, 26950], + [4692, 13323, 20111], + [8192, 16384, 24576], + ], + [ + [7833, 18369, 24095], + [26650, 32273, 32702], + [16371, 29961, 32191], + [11055, 24082, 29629], + [6892, 18644, 25400], + [5006, 13057, 19240], + [29834, 32666, 32748], + [19577, 31335, 32570], + [12253, 26509, 31122], + [7991, 20772, 27711], + [5677, 15910, 23059], + [30109, 32532, 32720], + [16747, 30166, 32252], + [10134, 23542, 29184], + [5791, 16176, 23556], + [4362, 10414, 17284], + [29492, 32626, 32748], + [19894, 31402, 32525], + [12942, 27071, 30869], + [8346, 21216, 27405], + [6572, 17087, 23859], + [32035, 32735, 32748], + [22957, 31838, 32618], + [14724, 28572, 31772], + [10364, 23999, 29553], + [7004, 18433, 25655], + [27528, 32277, 32681], + [16959, 31171, 32096], + [10486, 23593, 27962], + [8192, 16384, 23211], + [8937, 17873, 20852], + [27715, 32002, 32615], + [15073, 29491, 31676], + [11264, 24576, 28672], + [2341, 18725, 23406], + [7282, 18204, 25486], + [28547, 32213, 32657], + [20788, 29773, 32239], + [6780, 21469, 30508], + [5958, 14895, 23831], + [16384, 21845, 27307], + [8192, 16384, 24576], + ], + ], + [ + [ + [5992, 14304, 19765], + [22612, 31238, 32456], + [13456, 27162, 31087], + [8001, 20062, 26504], + [5168, 14105, 20764], + [2632, 7771, 12385], + [27034, 32344, 32709], + [15850, 29415, 31997], + [9494, 22776, 28841], + [6151, 16830, 23969], + [3461, 10039, 15722], + [30134, 32569, 32731], + [15638, 29422, 31945], + [9150, 21865, 28218], + [5647, 15719, 22676], + [3402, 9772, 15477], + [28530, 32586, 32735], + [17139, 30298, 32292], + [10200, 24039, 29685], + [6419, 17674, 24786], + [3544, 10225, 15824], + [31333, 32726, 32748], + [20618, 31487, 32544], + [12901, 27217, 31232], + [8624, 21734, 28171], + [5104, 14191, 20748], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [11206, 21090, 26561], + [28759, 32279, 32671], + [14171, 27952, 31569], + [9743, 22907, 29141], + [6871, 17886, 24868], + [4960, 13152, 19315], + [31077, 32661, 32748], + [19400, 31195, 32515], + [12752, 26858, 31040], + [8370, 22098, 28591], + [5457, 15373, 22298], + [31697, 32706, 32748], + [17860, 30657, 32333], + [12510, 24812, 29261], + [6180, 19124, 24722], + [5041, 13548, 17959], + [31552, 32716, 32748], + [21908, 31769, 32623], + [14470, 28201, 31565], + [9493, 22982, 28608], + [6858, 17240, 24137], + [32543, 32752, 32756], + [24286, 32097, 32666], + [15958, 29217, 32024], + [10207, 24234, 29958], + [6929, 18305, 25652], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + [ + [ + [4137, 10847, 15682], + [17824, 27001, 30058], + [10204, 22796, 28291], + [6076, 15935, 22125], + [3852, 10937, 16816], + [2252, 6324, 10131], + [25840, 32016, 32662], + [15109, 28268, 31531], + [9385, 22231, 28340], + [6082, 16672, 23479], + [3318, 9427, 14681], + [30594, 32574, 32718], + [16836, 29552, 31859], + [9556, 22542, 28356], + [6305, 16725, 23540], + [3376, 9895, 15184], + [29383, 32617, 32745], + [18891, 30809, 32401], + [11688, 25942, 30687], + [7468, 19469, 26651], + [3909, 11358, 17012], + [31564, 32736, 32748], + [20906, 31611, 32600], + [13191, 27621, 31537], + [8768, 22029, 28676], + [5079, 14109, 20906], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + [ + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + [8192, 16384, 24576], + ], + ], + ], +]); + +pub static av1_default_coeff_base_eob_multi_cdfs: [[[[[u16; + NUM_BASE_LEVELS + 1]; + SIG_COEF_CONTEXTS_EOB]; + PLANE_TYPES]; + TxSize::TX_SIZES]; + TOKEN_CDF_Q_CTXS] = cdf_5d([ + [ + [ + [[17837, 29055], [29600, 31446], [30844, 31878], [24926, 28948]], + [[21365, 30026], [30512, 32423], [31658, 32621], [29630, 31881]], + ], + [ + [[5717, 26477], [30491, 31703], [31550, 32158], [29648, 31491]], + [[12608, 27820], [30680, 32225], [30809, 32335], [31299, 32423]], + ], + [ + [[1786, 12612], [30663, 31625], [32339, 32468], [31148, 31833]], + [[18857, 23865], [31428, 32428], [31744, 32373], [31775, 32526]], + ], + [ + [[1787, 2532], [30832, 31662], [31824, 32682], [32133, 32569]], + [[13751, 22235], [32089, 32409], [27084, 27920], [29291, 32594]], + ], + [ + [[1725, 3449], [31102, 31935], [32457, 32613], [32412, 32649]], + [[10923, 21845], [10923, 21845], [10923, 21845], [10923, 21845]], + ], + ], + [ + [ + [[17560, 29888], [29671, 31549], [31007, 32056], [27286, 30006]], + [[26594, 31212], [31208, 32582], [31835, 32637], [30595, 32206]], + ], + [ + [[15239, 29932], [31315, 32095], [32130, 32434], [30864, 31996]], + [[26279, 30968], [31142, 32495], [31713, 32540], [31929, 32594]], + ], + [ + [[2644, 25198], [32038, 32451], [32639, 32695], [32166, 32518]], + [[17187, 27668], [31714, 32550], [32283, 32678], [31930, 32563]], + ], + [ + [[1044, 2257], [30755, 31923], [32208, 32693], [32244, 32615]], + [[21317, 26207], [29133, 30868], [29311, 31231], [29657, 31087]], + ], + [ + [[478, 1834], [31005, 31987], [32317, 32724], [30865, 32648]], + [[10923, 21845], [10923, 21845], [10923, 21845], [10923, 21845]], + ], + ], + [ + [ + [[20092, 30774], [30695, 32020], [31131, 32103], [28666, 30870]], + [[27258, 31095], [31804, 32623], [31763, 32528], [31438, 32506]], + ], + [ + [[18049, 30489], [31706, 32286], [32163, 32473], [31550, 32184]], + [[27116, 30842], [31971, 32598], [32088, 32576], [32067, 32664]], + ], + [ + [[12854, 29093], [32272, 32558], [32667, 32729], [32306, 32585]], + [[25476, 30366], [32169, 32687], [32479, 32689], [31673, 32634]], + ], + [ + [[2809, 19301], [32205, 32622], [32338, 32730], [31786, 32616]], + [[22737, 29105], [30810, 32362], [30014, 32627], [30528, 32574]], + ], + [ + [[935, 3382], [30789, 31909], [32466, 32756], [30860, 32513]], + [[10923, 21845], [10923, 21845], [10923, 21845], [10923, 21845]], + ], + ], + [ + [ + [[22497, 31198], [31715, 32495], [31606, 32337], [30388, 31990]], + [[27877, 31584], [32170, 32728], [32155, 32688], [32219, 32702]], + ], + [ + [[21457, 31043], [31951, 32483], [32153, 32562], [31473, 32215]], + [[27558, 31151], [32020, 32640], [32097, 32575], [32242, 32719]], + ], + [ + [[19980, 30591], [32219, 32597], [32581, 32706], [31803, 32287]], + [[26473, 30507], [32431, 32723], [32196, 32611], [31588, 32528]], + ], + [ + [[24647, 30463], [32412, 32695], [32468, 32720], [31269, 32523]], + [[28482, 31505], [32152, 32701], [31732, 32598], [31767, 32712]], + ], + [ + [[12358, 24977], [31331, 32385], [32634, 32756], [30411, 32548]], + [[10923, 21845], [10923, 21845], [10923, 21845], [10923, 21845]], + ], + ], +]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/forward.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/forward.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,162 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::cpu_features::CpuFeatureLevel; +use crate::util::*; + +use super::TxType; + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::transform::forward::*; + } else if #[cfg(asm_neon)] { + pub use crate::asm::aarch64::transform::forward::*; + } else { + pub use self::rust::*; + } +} + +pub mod rust { + use super::*; + use std::mem::MaybeUninit; + + use crate::transform::forward_shared::*; + use crate::transform::{av1_round_shift_array, valid_av1_transform, TxSize}; + use simd_helpers::cold_for_target_arch; + + type TxfmFunc = fn(&mut [i32]); + + impl_1d_tx!(); + + impl TxOperations for i32 { + fn zero() -> Self { + 0 + } + + fn tx_mul(self, mul: i32) -> Self { + ((self * mul) + (1 << SHIFT >> 1)) >> SHIFT + } + + fn rshift1(self) -> Self { + (self + i32::from(self < 0)) >> 1 + } + + fn add(self, b: Self) -> Self { + self + b + } + + fn sub(self, b: Self) -> Self { + self - b + } + + fn add_avg(self, b: Self) -> Self { + (self + b) >> 1 + } + + fn sub_avg(self, b: Self) -> Self { + (self - b) >> 1 + } + } + + /// # Panics + /// + /// - If called with an invalid combination of `tx_size` and `tx_type` + #[cold_for_target_arch("x86_64")] + pub fn forward_transform( + input: &[i16], output: &mut [MaybeUninit], stride: usize, + tx_size: TxSize, tx_type: TxType, bd: usize, _cpu: CpuFeatureLevel, + ) { + assert!(valid_av1_transform(tx_size, tx_type)); + + // Note when assigning txfm_size_col, we use the txfm_size from the + // row configuration and vice versa. This is intentionally done to + // accurately perform rectangular transforms. When the transform is + // rectangular, the number of columns will be the same as the + // txfm_size stored in the row cfg struct. It will make no difference + // for square transforms. + let txfm_size_col = tx_size.width(); + let txfm_size_row = tx_size.height(); + + let mut buf = Aligned::<[MaybeUninit; 64 * 64]>::uninit_array(); + let buf = &mut buf.data[..txfm_size_col * txfm_size_row]; + + let cfg = Txfm2DFlipCfg::fwd(tx_type, tx_size, bd); + + let txfm_func_col = get_func(cfg.txfm_type_col); + let txfm_func_row = get_func(cfg.txfm_type_row); + + // Columns + for c in 0..txfm_size_col { + let mut col_coeffs = Aligned::<[MaybeUninit; 64]>::uninit_array(); + let col_coeffs = &mut col_coeffs.data[..txfm_size_row]; + if cfg.ud_flip { + // flip upside down + for r in 0..txfm_size_row { + col_coeffs[r] + .write((input[(txfm_size_row - r - 1) * stride + c]).into()); + } + } else { + for r in 0..txfm_size_row { + col_coeffs[r].write((input[r * stride + c]).into()); + } + } + // SAFETY: The loops above have initialized all txfm_size_row elements + let col_coeffs = unsafe { slice_assume_init_mut(col_coeffs) }; + + av1_round_shift_array(col_coeffs, txfm_size_row, -cfg.shift[0]); + txfm_func_col(col_coeffs); + av1_round_shift_array(col_coeffs, txfm_size_row, -cfg.shift[1]); + if cfg.lr_flip { + for r in 0..txfm_size_row { + // flip from left to right + buf[r * txfm_size_col + (txfm_size_col - c - 1)] + .write(col_coeffs[r]); + } + } else { + for r in 0..txfm_size_row { + buf[r * txfm_size_col + c].write(col_coeffs[r]); + } + } + } + // SAFETY: The loops above have initialized the entire buf + let buf = unsafe { slice_assume_init_mut(buf) }; + + // Rows + for (r, row_coeffs) in buf.chunks_exact_mut(txfm_size_col).enumerate() { + txfm_func_row(row_coeffs); + av1_round_shift_array(row_coeffs, txfm_size_col, -cfg.shift[2]); + + // Store output in at most 32x32 chunks so that the first 32x32 + // coefficients are stored first. When we don't have 64 rows, there is no + // change in order. With 64 rows, the chunks are in this order + // - First 32 rows and first 32 cols + // - Last 32 rows and first 32 cols + // - First 32 rows and last 32 cols + // - Last 32 rows and last 32 cols + + // Output is grouped into 32x32 chunks so a stride of at most 32 is + // used for each chunk. + let output_stride = txfm_size_row.min(32); + + // Split the first 32 rows from the last 32 rows + let output = &mut output + [(r >= 32) as usize * output_stride * txfm_size_col.min(32)..]; + + for cg in (0..txfm_size_col).step_by(32) { + // Split the first 32 cols from the last 32 cols + let output = &mut output[txfm_size_row * cg..]; + + for c in 0..txfm_size_col.min(32) { + output[c * output_stride + (r & 31)] + .write(T::cast_from(row_coeffs[c + cg])); + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/forward_shared.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward_shared.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/forward_shared.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/forward_shared.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1799 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use super::TxSize; +use super::TxType; + +use super::HTX_TAB; +use super::VTX_TAB; + +pub type TxfmShift = [i8; 3]; +pub type TxfmShifts = [TxfmShift; 3]; + +// Shift so that the first shift is 4 - (bd - 8) to align with the initial +// design of daala_tx +// 8 bit 4x4 is an exception and only shifts by 3 in the first stage +const FWD_SHIFT_4X4: TxfmShifts = [[3, 0, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_8X8: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_16X16: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_32X32: TxfmShifts = [[4, -2, 0], [2, 0, 0], [0, 0, 2]]; +const FWD_SHIFT_64X64: TxfmShifts = [[4, -1, -2], [2, 0, -1], [0, 0, 1]]; +const FWD_SHIFT_4X8: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_8X4: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_8X16: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_16X8: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_16X32: TxfmShifts = [[4, -2, 0], [2, 0, 0], [0, 0, 2]]; +const FWD_SHIFT_32X16: TxfmShifts = [[4, -2, 0], [2, 0, 0], [0, 0, 2]]; +const FWD_SHIFT_32X64: TxfmShifts = [[4, -1, -2], [2, 0, -1], [0, 0, 1]]; +const FWD_SHIFT_64X32: TxfmShifts = [[4, -1, -2], [2, 0, -1], [0, 0, 1]]; +const FWD_SHIFT_4X16: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_16X4: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_8X32: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_32X8: TxfmShifts = [[4, -1, 0], [2, 0, 1], [0, 0, 3]]; +const FWD_SHIFT_16X64: TxfmShifts = [[4, -2, 0], [2, 0, 0], [0, 0, 2]]; +const FWD_SHIFT_64X16: TxfmShifts = [[4, -2, 0], [2, 0, 0], [0, 0, 2]]; + +const FWD_SHIFT_4X4_WHT: TxfmShift = [0, 0, 2]; + +pub const FWD_TXFM_SHIFT_LS: [TxfmShifts; TxSize::TX_SIZES_ALL] = [ + FWD_SHIFT_4X4, + FWD_SHIFT_8X8, + FWD_SHIFT_16X16, + FWD_SHIFT_32X32, + FWD_SHIFT_64X64, + FWD_SHIFT_4X8, + FWD_SHIFT_8X4, + FWD_SHIFT_8X16, + FWD_SHIFT_16X8, + FWD_SHIFT_16X32, + FWD_SHIFT_32X16, + FWD_SHIFT_32X64, + FWD_SHIFT_64X32, + FWD_SHIFT_4X16, + FWD_SHIFT_16X4, + FWD_SHIFT_8X32, + FWD_SHIFT_32X8, + FWD_SHIFT_16X64, + FWD_SHIFT_64X16, +]; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TxfmType { + DCT4, + DCT8, + DCT16, + DCT32, + DCT64, + ADST4, + ADST8, + ADST16, + Identity4, + Identity8, + Identity16, + Identity32, + WHT4, +} + +impl TxfmType { + const TX_TYPES_1D: usize = 5; + const AV1_TXFM_TYPE_LS: [[Option; Self::TX_TYPES_1D]; 5] = [ + [ + Some(TxfmType::DCT4), + Some(TxfmType::ADST4), + Some(TxfmType::ADST4), + Some(TxfmType::Identity4), + Some(TxfmType::WHT4), + ], + [ + Some(TxfmType::DCT8), + Some(TxfmType::ADST8), + Some(TxfmType::ADST8), + Some(TxfmType::Identity8), + None, + ], + [ + Some(TxfmType::DCT16), + Some(TxfmType::ADST16), + Some(TxfmType::ADST16), + Some(TxfmType::Identity16), + None, + ], + [Some(TxfmType::DCT32), None, None, Some(TxfmType::Identity32), None], + [Some(TxfmType::DCT64), None, None, None, None], + ]; +} + +#[derive(Debug, Clone, Copy)] +pub struct Txfm2DFlipCfg { + pub tx_size: TxSize, + /// Flip upside down + pub ud_flip: bool, + /// Flip left to right + pub lr_flip: bool, + pub shift: TxfmShift, + pub txfm_type_col: TxfmType, + pub txfm_type_row: TxfmType, +} + +impl Txfm2DFlipCfg { + /// # Panics + /// + /// - If called with an invalid combination of `tx_size` and `tx_type` + pub fn fwd(tx_type: TxType, tx_size: TxSize, bd: usize) -> Self { + let tx_type_1d_col = VTX_TAB[tx_type as usize]; + let tx_type_1d_row = HTX_TAB[tx_type as usize]; + let txw_idx = tx_size.width_index(); + let txh_idx = tx_size.height_index(); + let txfm_type_col = + TxfmType::AV1_TXFM_TYPE_LS[txh_idx][tx_type_1d_col as usize].unwrap(); + let txfm_type_row = + TxfmType::AV1_TXFM_TYPE_LS[txw_idx][tx_type_1d_row as usize].unwrap(); + let (ud_flip, lr_flip) = Self::get_flip_cfg(tx_type); + let shift = if tx_type == TxType::WHT_WHT { + FWD_SHIFT_4X4_WHT + } else { + FWD_TXFM_SHIFT_LS[tx_size as usize][(bd - 8) / 2] + }; + + Txfm2DFlipCfg { + tx_size, + ud_flip, + lr_flip, + shift, + txfm_type_col, + txfm_type_row, + } + } + + /// Determine the flip config, returning `(ud_flip, lr_flip)` + const fn get_flip_cfg(tx_type: TxType) -> (bool, bool) { + use self::TxType::*; + match tx_type { + DCT_DCT | ADST_DCT | DCT_ADST | ADST_ADST | IDTX | V_DCT | H_DCT + | V_ADST | H_ADST | WHT_WHT => (false, false), + FLIPADST_DCT | FLIPADST_ADST | V_FLIPADST => (true, false), + DCT_FLIPADST | ADST_FLIPADST | H_FLIPADST => (false, true), + FLIPADST_FLIPADST => (true, true), + } + } +} + +macro_rules! store_coeffs { + ( $arr:expr, $( $x:expr ),* ) => { + { + let mut i: i32 = -1; + $( + i += 1; + $arr[i as usize] = $x; + )* + } + }; +} + +macro_rules! impl_1d_tx { +() => { + impl_1d_tx! {allow(unused_attributes), } +}; + +($m:meta, $($s:ident),*) => { + pub trait TxOperations: Copy { + $($s)* fn zero() -> Self; + + $($s)* fn tx_mul(self, mul: i32) -> Self; + $($s)* fn rshift1(self) -> Self; + $($s)* fn add(self, b: Self) -> Self; + $($s)* fn sub(self, b: Self) -> Self; + $($s)* fn add_avg(self, b: Self) -> Self; + $($s)* fn sub_avg(self, b: Self) -> Self; + + $($s)* fn copy_fn(self) -> Self { + self + } + } + + #[inline] + fn get_func(t: TxfmType) -> TxfmFunc { + use self::TxfmType::*; + match t { + DCT4 => daala_fdct4, + DCT8 => daala_fdct8, + DCT16 => daala_fdct16, + DCT32 => daala_fdct32, + DCT64 => daala_fdct64, + ADST4 => daala_fdst_vii_4, + ADST8 => daala_fdst8, + ADST16 => daala_fdst16, + Identity4 => fidentity, + Identity8 => fidentity, + Identity16 => fidentity, + Identity32 => fidentity, + WHT4 => fwht4, + } + } + + trait RotateKernelPi4 { + const ADD: $($s)* fn(T, T) -> T; + const SUB: $($s)* fn(T, T) -> T; + + #[$m] + $($s)* fn kernel(p0: T, p1: T, m: (i32, i32)) -> (T, T) { + let t = Self::ADD(p1, p0); + let (a, out0) = (p0.tx_mul::(m.0), t.tx_mul::(m.1)); + let out1 = Self::SUB(a, out0); + (out0, out1) + } +} + +struct RotatePi4Add; +struct RotatePi4AddAvg; +struct RotatePi4Sub; +struct RotatePi4SubAvg; + +impl RotateKernelPi4 for RotatePi4Add { + const ADD: $($s)* fn(T, T) -> T = T::add; + const SUB: $($s)* fn(T, T) -> T = T::sub; +} + +impl RotateKernelPi4 for RotatePi4AddAvg { + const ADD: $($s)* fn(T, T) -> T = T::add_avg; + const SUB: $($s)* fn(T, T) -> T = T::sub; +} + +impl RotateKernelPi4 for RotatePi4Sub { + const ADD: $($s)* fn(T, T) -> T = T::sub; + const SUB: $($s)* fn(T, T) -> T = T::add; +} + +impl RotateKernelPi4 for RotatePi4SubAvg { + const ADD: $($s)* fn(T, T) -> T = T::sub_avg; + const SUB: $($s)* fn(T, T) -> T = T::add; +} + +trait RotateKernel { + const ADD: $($s)* fn(T, T) -> T; + const SUB: $($s)* fn(T, T) -> T; + const SHIFT: $($s)* fn(T) -> T; + + #[$m] + $($s)* fn half_kernel( + p0: (T, T), p1: T, m: (i32, i32, i32), + ) -> (T, T) { + let t = Self::ADD(p1, p0.0); + let (a, b, c) = (p0.1.tx_mul::(m.0), p1.tx_mul::(m.1), t.tx_mul::(m.2)); + let out0 = b.add(c); + let shifted = Self::SHIFT(c); + let out1 = Self::SUB(a, shifted); + (out0, out1) + } + + #[$m] + $($s)* fn kernel(p0: T, p1: T, m: (i32, i32, i32)) -> (T, T) { + Self::half_kernel::((p0, p0), p1, m) + } +} + +trait RotateKernelNeg { + const ADD: $($s)* fn(T, T) -> T; + + #[$m] + $($s)* fn kernel(p0: T, p1: T, m: (i32, i32, i32)) -> (T, T) { + let t = Self::ADD(p0, p1); + let (a, b, c) = (p0.tx_mul::(m.0), p1.tx_mul::(m.1), t.tx_mul::(m.2)); + let out0 = b.sub(c); + let out1 = c.sub(a); + (out0, out1) + } +} + +struct RotateAdd; +struct RotateAddAvg; +struct RotateAddShift; +struct RotateSub; +struct RotateSubAvg; +struct RotateSubShift; +struct RotateNeg; +struct RotateNegAvg; + +impl RotateKernel for RotateAdd { + const ADD: $($s)* fn(T, T) -> T = T::add; + const SUB: $($s)* fn(T, T) -> T = T::sub; + const SHIFT: $($s)* fn(T) -> T = T::copy_fn; +} + +impl RotateKernel for RotateAddAvg { + const ADD: $($s)* fn(T, T) -> T = T::add_avg; + const SUB: $($s)* fn(T, T) -> T = T::sub; + const SHIFT: $($s)* fn(T) -> T = T::copy_fn; +} + +impl RotateKernel for RotateAddShift { + const ADD: $($s)* fn(T, T) -> T = T::add; + const SUB: $($s)* fn(T, T) -> T = T::sub; + const SHIFT: $($s)* fn(T) -> T = T::rshift1; +} + +impl RotateKernel for RotateSub { + const ADD: $($s)* fn(T, T) -> T = T::sub; + const SUB: $($s)* fn(T, T) -> T = T::add; + const SHIFT: $($s)* fn(T) -> T = T::copy_fn; +} + +impl RotateKernel for RotateSubAvg { + const ADD: $($s)* fn(T, T) -> T = T::sub_avg; + const SUB: $($s)* fn(T, T) -> T = T::add; + const SHIFT: $($s)* fn(T) -> T = T::copy_fn; +} + +impl RotateKernel for RotateSubShift { + const ADD: $($s)* fn(T, T) -> T = T::sub; + const SUB: $($s)* fn(T, T) -> T = T::add; + const SHIFT: $($s)* fn(T) -> T = T::rshift1; +} + +impl RotateKernelNeg for RotateNeg { + const ADD: $($s)* fn(T, T) -> T = T::sub; +} + +impl RotateKernelNeg for RotateNegAvg { + const ADD: $($s)* fn(T, T) -> T = T::sub_avg; +} + +#[inline] +#[$m] +$($s)* fn butterfly_add(p0: T, p1: T) -> ((T, T), T) { + let p0 = p0.add(p1); + let p0h = p0.rshift1(); + let p1h = p1.sub(p0h); + ((p0h, p0), p1h) +} + +#[inline] +#[$m] +$($s)* fn butterfly_sub(p0: T, p1: T) -> ((T, T), T) { + let p0 = p0.sub(p1); + let p0h = p0.rshift1(); + let p1h = p1.add(p0h); + ((p0h, p0), p1h) +} + +#[inline] +#[$m] +$($s)* fn butterfly_neg(p0: T, p1: T) -> (T, (T, T)) { + let p1 = p0.sub(p1); + let p1h = p1.rshift1(); + let p0h = p0.sub(p1h); + (p0h, (p1h, p1)) +} + +#[inline] +#[$m] +$($s)* fn butterfly_add_asym(p0: (T, T), p1h: T) -> (T, T) { + let p1 = p1h.add(p0.0); + let p0 = p0.1.sub(p1); + (p0, p1) +} + +#[inline] +#[$m] +$($s)* fn butterfly_sub_asym(p0: (T, T), p1h: T) -> (T, T) { + let p1 = p1h.sub(p0.0); + let p0 = p0.1.add(p1); + (p0, p1) +} + +#[inline] +#[$m] +$($s)* fn butterfly_neg_asym(p0h: T, p1: (T, T)) -> (T, T) { + let p0 = p0h.add(p1.0); + let p1 = p0.sub(p1.1); + (p0, p1) +} + +#[$m] +$($s)* fn daala_fdct_ii_2_asym(p0h: T, p1: (T, T)) -> (T, T) { + butterfly_neg_asym(p0h, p1) +} + +#[$m] +$($s)* fn daala_fdst_iv_2_asym(p0: (T, T), p1h: T) -> (T, T) { + // 473/512 = (Sin[3*Pi/8] + Cos[3*Pi/8])/Sqrt[2] = 0.9238795325112867 + // 3135/4096 = (Sin[3*Pi/8] - Cos[3*Pi/8])*Sqrt[2] = 0.7653668647301795 + // 4433/8192 = Cos[3*Pi/8]*Sqrt[2] = 0.5411961001461971 + RotateAdd::half_kernel::<9, 12, 13>(p0, p1h, (473, 3135, 4433)) +} + +#[$m] +$($s)* fn daala_fdct_ii_4( + q0: T, q1: T, q2: T, q3: T, output: &mut [T], +) { + // +/- Butterflies with asymmetric output. + let (q0h, q3) = butterfly_neg(q0, q3); + let (q1, q2h) = butterfly_add(q1, q2); + + // Embedded 2-point transforms with asymmetric input. + let (q0, q1) = daala_fdct_ii_2_asym(q0h, q1); + let (q3, q2) = daala_fdst_iv_2_asym(q3, q2h); + + store_coeffs!(output, q0, q1, q2, q3); +} + +#[$m] +$($s)* fn daala_fdct4(coeffs: &mut [T]) { + assert!(coeffs.len() >= 4); + let mut temp_out: [T; 4] = [T::zero(); 4]; + daala_fdct_ii_4(coeffs[0], coeffs[1], coeffs[2], coeffs[3], &mut temp_out); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[2]; + coeffs[2] = temp_out[1]; + coeffs[3] = temp_out[3]; +} + +#[$m] +$($s)* fn daala_fdst_vii_4(coeffs: &mut [T]) { + assert!(coeffs.len() >= 4); + + let q0 = coeffs[0]; + let q1 = coeffs[1]; + let q2 = coeffs[2]; + let q3 = coeffs[3]; + let t0 = q1.add(q3); + // t1 = (q0 + q1 - q3)/2 + let t1 = q1.add(q0.sub_avg(t0)); + let t2 = q0.sub(q1); + let t3 = q2; + let t4 = q0.add(q3); + // 7021/16384 ~= 2*Sin[2*Pi/9]/3 ~= 0.428525073124360 + let t0 = t0.tx_mul::<14>(7021); + // 37837/32768 ~= 4*Sin[3*Pi/9]/3 ~= 1.154700538379252 + let t1 = t1.tx_mul::<15>(37837); + // 21513/32768 ~= 2*Sin[4*Pi/9]/3 ~= 0.656538502008139 + let t2 = t2.tx_mul::<15>(21513); + // 37837/32768 ~= 4*Sin[3*Pi/9]/3 ~= 1.154700538379252 + let t3 = t3.tx_mul::<15>(37837); + // 467/2048 ~= 2*Sin[1*Pi/9]/3 ~= 0.228013428883779 + let t4 = t4.tx_mul::<11>(467); + let t3h = t3.rshift1(); + let u4 = t4.add(t3h); + coeffs[0] = t0.add(u4); + coeffs[1] = t1; + coeffs[2] = t0.add(t2.sub(t3h)); + coeffs[3] = t2.add(t3.sub(u4)); +} + +#[$m] +$($s)* fn daala_fdct_ii_2(p0: T, p1: T) -> (T, T) { + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (p1, p0) = RotatePi4SubAvg::kernel::<13, 13>(p1, p0, (11585, 11585)); + (p0, p1) +} + +#[$m] +$($s)* fn daala_fdst_iv_2(p0: T, p1: T) -> (T, T) { + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461971 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + RotateAddAvg::kernel::<13, 14, 12>(p0, p1, (10703, 8867, 3135)) +} + +#[$m] +$($s)* fn daala_fdct_ii_4_asym( + q0h: T, q1: (T, T), q2h: T, q3: (T, T), output: &mut [T], +) { + // +/- Butterflies with asymmetric input. + let (q0, q3) = butterfly_neg_asym(q0h, q3); + let (q1, q2) = butterfly_sub_asym(q1, q2h); + + // Embedded 2-point orthonormal transforms. + let (q0, q1) = daala_fdct_ii_2(q0, q1); + let (q3, q2) = daala_fdst_iv_2(q3, q2); + + store_coeffs!(output, q0, q1, q2, q3); +} + +#[$m] +$($s)* fn daala_fdst_iv_4_asym( + q0: (T, T), q1h: T, q2: (T, T), q3h: T, output: &mut [T], +) { + // Stage 0 + // 9633/16384 = (Sin[7*Pi/16] + Cos[7*Pi/16])/2 = 0.5879378012096793 + // 12873/8192 = (Sin[7*Pi/16] - Cos[7*Pi/16])*2 = 1.5713899167742045 + // 12785/32768 = Cos[7*Pi/16]*2 = 0.3901806440322565 + let (q0, q3) = RotateAddShift::half_kernel::<14, 13, 15>( + q0, + q3h, + (9633, 12873, 12785), + ); + // 11363/16384 = (Sin[5*Pi/16] + Cos[5*Pi/16])/2 = 0.6935199226610738 + // 18081/32768 = (Sin[5*Pi/16] - Cos[5*Pi/16])*2 = 0.5517987585658861 + // 4551/4096 = Cos[5*Pi/16]*2 = 1.1111404660392044 + let (q2, q1) = RotateSubShift::half_kernel::<14, 15, 12>( + q2, + q1h, + (11363, 18081, 4551), + ); + + // Stage 1 + let (q2, q3) = butterfly_sub_asym((q2.rshift1(), q2), q3); + let (q0, q1) = butterfly_sub_asym((q0.rshift1(), q0), q1); + + // Stage 2 + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (q2, q1) = RotatePi4AddAvg::kernel::<13, 13>(q2, q1, (11585, 11585)); + + store_coeffs!(output, q0, q1, q2, q3); +} + +#[$m] +$($s)* fn daala_fdct_ii_8( + r0: T, r1: T, r2: T, r3: T, r4: T, r5: T, r6: T, r7: T, output: &mut [T], +) { + // +/- Butterflies with asymmetric output. + let (r0h, r7) = butterfly_neg(r0, r7); + let (r1, r6h) = butterfly_add(r1, r6); + let (r2h, r5) = butterfly_neg(r2, r5); + let (r3, r4h) = butterfly_add(r3, r4); + + // Embedded 4-point transforms with asymmetric input. + daala_fdct_ii_4_asym(r0h, r1, r2h, r3, &mut output[0..4]); + daala_fdst_iv_4_asym(r7, r6h, r5, r4h, &mut output[4..8]); + output[4..8].reverse(); +} + +#[$m] +$($s)* fn daala_fdct8(coeffs: &mut [T]) { + assert!(coeffs.len() >= 8); + let mut temp_out: [T; 8] = [T::zero(); 8]; + daala_fdct_ii_8( + coeffs[0], + coeffs[1], + coeffs[2], + coeffs[3], + coeffs[4], + coeffs[5], + coeffs[6], + coeffs[7], + &mut temp_out, + ); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[4]; + coeffs[2] = temp_out[2]; + coeffs[3] = temp_out[6]; + coeffs[4] = temp_out[1]; + coeffs[5] = temp_out[5]; + coeffs[6] = temp_out[3]; + coeffs[7] = temp_out[7]; +} + +#[$m] +$($s)* fn daala_fdst_iv_8( + r0: T, r1: T, r2: T, r3: T, r4: T, r5: T, r6: T, r7: T, output: &mut [T], +) { + // Stage 0 + // 17911/16384 = Sin[15*Pi/32] + Cos[15*Pi/32] = 1.0932018670017576 + // 14699/16384 = Sin[15*Pi/32] - Cos[15*Pi/32] = 0.8971675863426363 + // 803/8192 = Cos[15*Pi/32] = 0.0980171403295606 + let (r0, r7) = + RotateAdd::kernel::<14, 14, 13>(r0, r7, (17911, 14699, 803)); + // 20435/16384 = Sin[13*Pi/32] + Cos[13*Pi/32] = 1.24722501298667123 + // 21845/32768 = Sin[13*Pi/32] - Cos[13*Pi/32] = 0.66665565847774650 + // 1189/4096 = Cos[13*Pi/32] = 0.29028467725446233 + let (r6, r1) = + RotateSub::kernel::<14, 15, 12>(r6, r1, (20435, 21845, 1189)); + // 22173/16384 = Sin[11*Pi/32] + Cos[11*Pi/32] = 1.3533180011743526 + // 3363/8192 = Sin[11*Pi/32] - Cos[11*Pi/32] = 0.4105245275223574 + // 15447/32768 = Cos[11*Pi/32] = 0.47139673682599764 + let (r2, r5) = + RotateAdd::kernel::<14, 13, 15>(r2, r5, (22173, 3363, 15447)); + // 23059/16384 = Sin[9*Pi/32] + Cos[9*Pi/32] = 1.4074037375263826 + // 2271/16384 = Sin[9*Pi/32] - Cos[9*Pi/32] = 0.1386171691990915 + // 5197/8192 = Cos[9*Pi/32] = 0.6343932841636455 + let (r4, r3) = + RotateSub::kernel::<14, 14, 13>(r4, r3, (23059, 2271, 5197)); + + // Stage 1 + let (r0, r3h) = butterfly_add(r0, r3); + let (r2, r1h) = butterfly_sub(r2, r1); + let (r5, r6h) = butterfly_add(r5, r6); + let (r7, r4h) = butterfly_sub(r7, r4); + + // Stage 2 + let (r7, r6) = butterfly_add_asym(r7, r6h); + let (r5, r3) = butterfly_add_asym(r5, r3h); + let (r2, r4) = butterfly_add_asym(r2, r4h); + let (r0, r1) = butterfly_sub_asym(r0, r1h); + + // Stage 3 + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + let (r3, r4) = + RotateSubAvg::kernel::<13, 14, 12>(r3, r4, (10703, 8867, 3135)); + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + let (r2, r5) = + RotateNegAvg::kernel::<13, 14, 12>(r2, r5, (10703, 8867, 3135)); + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (r1, r6) = RotatePi4SubAvg::kernel::<13, 13>(r1, r6, (11585, 11585)); + + store_coeffs!(output, r0, r1, r2, r3, r4, r5, r6, r7); +} + +#[$m] +$($s)* fn daala_fdst8(coeffs: &mut [T]) { + assert!(coeffs.len() >= 8); + let mut temp_out: [T; 8] = [T::zero(); 8]; + daala_fdst_iv_8( + coeffs[0], + coeffs[1], + coeffs[2], + coeffs[3], + coeffs[4], + coeffs[5], + coeffs[6], + coeffs[7], + &mut temp_out, + ); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[4]; + coeffs[2] = temp_out[2]; + coeffs[3] = temp_out[6]; + coeffs[4] = temp_out[1]; + coeffs[5] = temp_out[5]; + coeffs[6] = temp_out[3]; + coeffs[7] = temp_out[7]; +} + +#[$m] +$($s)* fn daala_fdst_iv_4( + q0: T, q1: T, q2: T, q3: T, output: &mut [T], +) { + // Stage 0 + // 13623/16384 = (Sin[7*Pi/16] + Cos[7*Pi/16])/Sqrt[2] = 0.831469612302545 + // 4551/4096 = (Sin[7*Pi/16] - Cos[7*Pi/16])*Sqrt[2] = 1.111140466039204 + // 9041/32768 = Cos[7*Pi/16]*Sqrt[2] = 0.275899379282943 + let (q0, q3) = + RotateAddShift::kernel::<14, 12, 11>(q0, q3, (13623, 4551, 565)); + // 16069/16384 = (Sin[5*Pi/16] + Cos[5*Pi/16])/Sqrt[2] = 0.9807852804032304 + // 12785/32768 = (Sin[5*Pi/16] - Cos[5*Pi/16])*Sqrt[2] = 0.3901806440322566 + // 1609/2048 = Cos[5*Pi/16]*Sqrt[2] = 0.7856949583871021 + let (q2, q1) = + RotateSubShift::kernel::<14, 15, 11>(q2, q1, (16069, 12785, 1609)); + + // Stage 1 + let (q2, q3) = butterfly_sub_asym((q2.rshift1(), q2), q3); + let (q0, q1) = butterfly_sub_asym((q0.rshift1(), q0), q1); + + // Stage 2 + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (q2, q1) = RotatePi4AddAvg::kernel::<13, 13>(q2, q1, (11585, 11585)); + + store_coeffs!(output, q0, q1, q2, q3); +} + + +#[$m] +$($s)* fn daala_fdct_ii_8_asym( + r0h: T, r1: (T, T), r2h: T, r3: (T, T), r4h: T, r5: (T, T), r6h: T, + r7: (T, T), output: &mut [T], +) { + // +/- Butterflies with asymmetric input. + let (r0, r7) = butterfly_neg_asym(r0h, r7); + let (r1, r6) = butterfly_sub_asym(r1, r6h); + let (r2, r5) = butterfly_neg_asym(r2h, r5); + let (r3, r4) = butterfly_sub_asym(r3, r4h); + + // Embedded 4-point orthonormal transforms. + daala_fdct_ii_4(r0, r1, r2, r3, &mut output[0..4]); + daala_fdst_iv_4(r7, r6, r5, r4, &mut output[4..8]); + output[4..8].reverse(); +} + +#[$m] +$($s)* fn daala_fdst_iv_8_asym( + r0: (T, T), r1h: T, r2: (T, T), r3h: T, r4: (T, T), r5h: T, r6: (T, T), + r7h: T, output: &mut [T], +) { + // Stage 0 + // 12665/16384 = (Sin[15*Pi/32] + Cos[15*Pi/32])/Sqrt[2] = 0.77301045336274 + // 5197/4096 = (Sin[15*Pi/32] - Cos[15*Pi/32])*Sqrt[2] = 1.26878656832729 + // 2271/16384 = Cos[15*Pi/32]*Sqrt[2] = 0.13861716919909 + let (r0, r7) = + RotateAdd::half_kernel::<14, 12, 14>(r0, r7h, (12665, 5197, 2271)); + // 14449/16384 = Sin[13*Pi/32] + Cos[13*Pi/32])/Sqrt[2] = 0.881921264348355 + // 30893/32768 = Sin[13*Pi/32] - Cos[13*Pi/32])*Sqrt[2] = 0.942793473651995 + // 3363/8192 = Cos[13*Pi/32]*Sqrt[2] = 0.410524527522357 + let (r6, r1) = + RotateSub::half_kernel::<14, 15, 13>(r6, r1h, (14449, 30893, 3363)); + // 15679/16384 = Sin[11*Pi/32] + Cos[11*Pi/32])/Sqrt[2] = 0.956940335732209 + // 1189/2048 = Sin[11*Pi/32] - Cos[11*Pi/32])*Sqrt[2] = 0.580569354508925 + // 5461/8192 = Cos[11*Pi/32]*Sqrt[2] = 0.666655658477747 + let (r2, r5) = + RotateAdd::half_kernel::<14, 11, 13>(r2, r5h, (15679, 1189, 5461)); + // 16305/16384 = (Sin[9*Pi/32] + Cos[9*Pi/32])/Sqrt[2] = 0.9951847266721969 + // 803/4096 = (Sin[9*Pi/32] - Cos[9*Pi/32])*Sqrt[2] = 0.1960342806591213 + // 14699/16384 = Cos[9*Pi/32]*Sqrt[2] = 0.8971675863426364 + let (r4, r3) = + RotateSub::half_kernel::<14, 12, 14>(r4, r3h, (16305, 803, 14699)); + + // Stage 1 + let (r0, r3h) = butterfly_add(r0, r3); + let (r2, r1h) = butterfly_sub(r2, r1); + let (r5, r6h) = butterfly_add(r5, r6); + let (r7, r4h) = butterfly_sub(r7, r4); + + // Stage 2 + let (r7, r6) = butterfly_add_asym(r7, r6h); + let (r5, r3) = butterfly_add_asym(r5, r3h); + let (r2, r4) = butterfly_add_asym(r2, r4h); + let (r0, r1) = butterfly_sub_asym(r0, r1h); + + // Stage 3 + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + let (r3, r4) = + RotateSubAvg::kernel::<9, 14, 12>(r3, r4, (669, 8867, 3135)); + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + let (r2, r5) = + RotateNegAvg::kernel::<9, 14, 12>(r2, r5, (669, 8867, 3135)); + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (r1, r6) = RotatePi4SubAvg::kernel::<12, 13>(r1, r6, (5793, 11585)); + + store_coeffs!(output, r0, r1, r2, r3, r4, r5, r6, r7); +} + +#[$m] +$($s)* fn daala_fdct_ii_16( + s0: T, s1: T, s2: T, s3: T, s4: T, s5: T, s6: T, s7: T, s8: T, s9: T, sa: T, + sb: T, sc: T, sd: T, se: T, sf: T, output: &mut [T], +) { + // +/- Butterflies with asymmetric output. + let (s0h, sf) = butterfly_neg(s0, sf); + let (s1, seh) = butterfly_add(s1, se); + let (s2h, sd) = butterfly_neg(s2, sd); + let (s3, sch) = butterfly_add(s3, sc); + let (s4h, sb) = butterfly_neg(s4, sb); + let (s5, sah) = butterfly_add(s5, sa); + let (s6h, s9) = butterfly_neg(s6, s9); + let (s7, s8h) = butterfly_add(s7, s8); + + // Embedded 8-point transforms with asymmetric input. + daala_fdct_ii_8_asym(s0h, s1, s2h, s3, s4h, s5, s6h, s7, &mut output[0..8]); + daala_fdst_iv_8_asym(sf, seh, sd, sch, sb, sah, s9, s8h, &mut output[8..16]); + output[8..16].reverse(); +} + +#[$m] +$($s)* fn daala_fdct16(coeffs: &mut [T]) { + assert!(coeffs.len() >= 16); + let mut temp_out: [T; 16] = [T::zero(); 16]; + daala_fdct_ii_16( + coeffs[0], + coeffs[1], + coeffs[2], + coeffs[3], + coeffs[4], + coeffs[5], + coeffs[6], + coeffs[7], + coeffs[8], + coeffs[9], + coeffs[10], + coeffs[11], + coeffs[12], + coeffs[13], + coeffs[14], + coeffs[15], + &mut temp_out, + ); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[8]; + coeffs[2] = temp_out[4]; + coeffs[3] = temp_out[12]; + coeffs[4] = temp_out[2]; + coeffs[5] = temp_out[10]; + coeffs[6] = temp_out[6]; + coeffs[7] = temp_out[14]; + coeffs[8] = temp_out[1]; + coeffs[9] = temp_out[9]; + coeffs[10] = temp_out[5]; + coeffs[11] = temp_out[13]; + coeffs[12] = temp_out[3]; + coeffs[13] = temp_out[11]; + coeffs[14] = temp_out[7]; + coeffs[15] = temp_out[15]; +} + +#[$m] +$($s)* fn daala_fdst_iv_16( + s0: T, s1: T, s2: T, s3: T, s4: T, s5: T, s6: T, s7: T, s8: T, s9: T, sa: T, + sb: T, sc: T, sd: T, se: T, sf: T, output: &mut [T], +) { + // Stage 0 + // 24279/32768 = (Sin[31*Pi/64] + Cos[31*Pi/64])/Sqrt[2] = 0.74095112535496 + // 11003/8192 = (Sin[31*Pi/64] - Cos[31*Pi/64])*Sqrt[2] = 1.34311790969404 + // 1137/16384 = Cos[31*Pi/64]*Sqrt[2] = 0.06939217050794 + let (s0, sf) = + RotateAddShift::kernel::<15, 13, 14>(s0, sf, (24279, 11003, 1137)); + // 1645/2048 = (Sin[29*Pi/64] + Cos[29*Pi/64])/Sqrt[2] = 0.8032075314806449 + // 305/256 = (Sin[29*Pi/64] - Cos[29*Pi/64])*Sqrt[2] = 1.1913986089848667 + // 425/2048 = Cos[29*Pi/64]*Sqrt[2] = 0.2075082269882116 + let (se, s1) = + RotateSubShift::kernel::<11, 8, 11>(se, s1, (1645, 305, 425)); + // 14053/32768 = (Sin[27*Pi/64] + Cos[27*Pi/64])/Sqrt[2] = 0.85772861000027 + // 8423/8192 = (Sin[27*Pi/64] - Cos[27*Pi/64])*Sqrt[2] = 1.02820548838644 + // 2815/8192 = Cos[27*Pi/64]*Sqrt[2] = 0.34362586580705 + let (s2, sd) = + RotateAddShift::kernel::<14, 13, 13>(s2, sd, (14053, 8423, 2815)); + // 14811/16384 = (Sin[25*Pi/64] + Cos[25*Pi/64])/Sqrt[2] = 0.90398929312344 + // 7005/8192 = (Sin[25*Pi/64] - Cos[25*Pi/64])*Sqrt[2] = 0.85511018686056 + // 3903/8192 = Cos[25*Pi/64]*Sqrt[2] = 0.47643419969316 + let (sc, s3) = + RotateSubShift::kernel::<14, 13, 13>(sc, s3, (14811, 7005, 3903)); + // 30853/32768 = (Sin[23*Pi/64] + Cos[23*Pi/64])/Sqrt[2] = 0.94154406518302 + // 11039/16384 = (Sin[23*Pi/64] - Cos[23*Pi/64])*Sqrt[2] = 0.67377970678444 + // 9907/16384 = Cos[23*Pi/64]*Sqrt[2] = 0.60465421179080 + let (s4, sb) = + RotateAddShift::kernel::<15, 14, 14>(s4, sb, (30853, 11039, 9907)); + // 15893/16384 = (Sin[21*Pi/64] + Cos[21*Pi/64])/Sqrt[2] = 0.97003125319454 + // 3981/8192 = (Sin[21*Pi/64] - Cos[21*Pi/64])*Sqrt[2] = 0.89716758634264 + // 1489/2048 = Cos[21*Pi/64]*Sqrt[2] = 0.72705107329128 + let (sa, s5) = + RotateSubShift::kernel::<14, 13, 11>(sa, s5, (15893, 3981, 1489)); + // 32413/32768 = (Sin[19*Pi/64] + Cos[19*Pi/64])/Sqrt[2] = 0.98917650996478 + // 601/2048 = (Sin[19*Pi/64] - Cos[19*Pi/64])*Sqrt[2] = 0.29346094891072 + // 13803/16384 = Cos[19*Pi/64]*Sqrt[2] = 0.84244603550942 + let (s6, s9) = + RotateAddShift::kernel::<15, 11, 14>(s6, s9, (32413, 601, 13803)); + // 32729/32768 = (Sin[17*Pi/64] + Cos[17*Pi/64])/Sqrt[2] = 0.99879545620517 + // 201/2048 = (Sin[17*Pi/64] - Cos[17*Pi/64])*Sqrt[2] = 0.09813534865484 + // 1945/2048 = Cos[17*Pi/64]*Sqrt[2] = 0.94972778187775 + let (s8, s7) = + RotateSubShift::kernel::<15, 11, 11>(s8, s7, (32729, 201, 1945)); + + // Stage 1 + let (s0, s7) = butterfly_sub_asym((s0.rshift1(), s0), s7); + let (s8, sf) = butterfly_sub_asym((s8.rshift1(), s8), sf); + let (s4, s3) = butterfly_add_asym((s4.rshift1(), s4), s3); + let (sc, sb) = butterfly_add_asym((sc.rshift1(), sc), sb); + let (s2, s5) = butterfly_sub_asym((s2.rshift1(), s2), s5); + let (sa, sd) = butterfly_sub_asym((sa.rshift1(), sa), sd); + let (s6, s1) = butterfly_add_asym((s6.rshift1(), s6), s1); + let (se, s9) = butterfly_add_asym((se.rshift1(), se), s9); + + // Stage 2 + let ((_s8h, s8), s4h) = butterfly_add(s8, s4); + let ((_s7h, s7), sbh) = butterfly_add(s7, sb); + let ((_sah, sa), s6h) = butterfly_sub(sa, s6); + let ((_s5h, s5), s9h) = butterfly_sub(s5, s9); + let (s0, s3h) = butterfly_add(s0, s3); + let (sd, seh) = butterfly_add(sd, se); + let (s2, s1h) = butterfly_sub(s2, s1); + let (sf, sch) = butterfly_sub(sf, sc); + + // Stage 3 + // 301/256 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 1609/2048 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 12785/32768 = 2*Cos[7*Pi/16] = 0.3901806440322565 + let (s8, s7) = + RotateAddAvg::kernel::<8, 11, 15>(s8, s7, (301, 1609, 12785)); + // 11363/8192 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/8192 = Cos[5*Pi/16] = 0.5555702330196022 + let (s9, s6) = + RotateAdd::kernel::<13, 15, 13>(s9h, s6h, (11363, 9041, 4551)); + // 5681/4096 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/4096 = 2*Cos[5*Pi/16] = 1.1111404660392044 + let (s5, sa) = + RotateNegAvg::kernel::<12, 15, 12>(s5, sa, (5681, 9041, 4551)); + // 9633/8192 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 12873/16384 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 6393/32768 = Cos[7*Pi/16] = 0.1950903220161283 + let (s4, sb) = + RotateNeg::kernel::<13, 14, 15>(s4h, sbh, (9633, 12873, 6393)); + + // Stage 4 + let (s2, sc) = butterfly_add_asym(s2, sch); + let (s0, s1) = butterfly_sub_asym(s0, s1h); + let (sf, se) = butterfly_add_asym(sf, seh); + let (sd, s3) = butterfly_add_asym(sd, s3h); + let (s7, s6) = butterfly_add_asym((s7.rshift1(), s7), s6); + let (s8, s9) = butterfly_sub_asym((s8.rshift1(), s8), s9); + let (sa, sb) = butterfly_sub_asym((sa.rshift1(), sa), sb); + let (s5, s4) = butterfly_add_asym((s5.rshift1(), s5), s4); + + // Stage 5 + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[7*Pi/8] = 0.7653668647301796 + let (sc, s3) = + RotateAddAvg::kernel::<9, 14, 12>(sc, s3, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3870398453221475 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/4096 = 2*Cos[3*Pi/8] = 0.7653668647301796 + let (s2, sd) = + RotateNegAvg::kernel::<9, 14, 12>(s2, sd, (669, 8867, 3135)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (sa, s5) = RotatePi4AddAvg::kernel::<12, 13>(sa, s5, (5793, 11585)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (s6, s9) = RotatePi4AddAvg::kernel::<12, 13>(s6, s9, (5793, 11585)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 11585/8192 = 2*Cos[Pi/4] = 1.4142135623730951 + let (se, s1) = RotatePi4AddAvg::kernel::<12, 13>(se, s1, (5793, 11585)); + + store_coeffs!( + output, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sa, sb, sc, sd, se, sf + ); +} + +#[$m] +$($s)* fn daala_fdst16(coeffs: &mut [T]) { + assert!(coeffs.len() >= 16); + let mut temp_out: [T; 16] = [T::zero(); 16]; + daala_fdst_iv_16( + coeffs[0], + coeffs[1], + coeffs[2], + coeffs[3], + coeffs[4], + coeffs[5], + coeffs[6], + coeffs[7], + coeffs[8], + coeffs[9], + coeffs[10], + coeffs[11], + coeffs[12], + coeffs[13], + coeffs[14], + coeffs[15], + &mut temp_out, + ); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[8]; + coeffs[2] = temp_out[4]; + coeffs[3] = temp_out[12]; + coeffs[4] = temp_out[2]; + coeffs[5] = temp_out[10]; + coeffs[6] = temp_out[6]; + coeffs[7] = temp_out[14]; + coeffs[8] = temp_out[1]; + coeffs[9] = temp_out[9]; + coeffs[10] = temp_out[5]; + coeffs[11] = temp_out[13]; + coeffs[12] = temp_out[3]; + coeffs[13] = temp_out[11]; + coeffs[14] = temp_out[7]; + coeffs[15] = temp_out[15]; +} + +#[$m] +$($s)* fn daala_fdct_ii_16_asym( + s0h: T, s1: (T, T), s2h: T, s3: (T, T), s4h: T, s5: (T, T), s6h: T, + s7: (T, T), s8h: T, s9: (T, T), sah: T, sb: (T, T), sch: T, sd: (T, T), + seh: T, sf: (T, T), output: &mut [T], +) { + // +/- Butterflies with asymmetric input. + let (s0, sf) = butterfly_neg_asym(s0h, sf); + let (s1, se) = butterfly_sub_asym(s1, seh); + let (s2, sd) = butterfly_neg_asym(s2h, sd); + let (s3, sc) = butterfly_sub_asym(s3, sch); + let (s4, sb) = butterfly_neg_asym(s4h, sb); + let (s5, sa) = butterfly_sub_asym(s5, sah); + let (s6, s9) = butterfly_neg_asym(s6h, s9); + let (s7, s8) = butterfly_sub_asym(s7, s8h); + + // Embedded 8-point orthonormal transforms. + daala_fdct_ii_8(s0, s1, s2, s3, s4, s5, s6, s7, &mut output[0..8]); + daala_fdst_iv_8(sf, se, sd, sc, sb, sa, s9, s8, &mut output[8..16]); + output[8..16].reverse(); +} + +#[$m] +$($s)* fn daala_fdst_iv_16_asym( + s0: (T, T), s1h: T, s2: (T, T), s3h: T, s4: (T, T), s5h: T, s6: (T, T), + s7h: T, s8: (T, T), s9h: T, sa: (T, T), sbh: T, sc: (T, T), sdh: T, + se: (T, T), sfh: T, output: &mut [T], +) { + // Stage 0 + // 1073/2048 = (Sin[31*Pi/64] + Cos[31*Pi/64])/2 = 0.5239315652662953 + // 62241/32768 = (Sin[31*Pi/64] - Cos[31*Pi/64])*2 = 1.8994555637555088 + // 201/16384 = Cos[31*Pi/64]*2 = 0.0981353486548360 + let (s0, sf) = + RotateAddShift::half_kernel::<11, 15, 11>(s0, sfh, (1073, 62241, 201)); + // 18611/32768 = (Sin[29*Pi/64] + Cos[29*Pi/64])/2 = 0.5679534922100714 + // 55211/32768 = (Sin[29*Pi/64] - Cos[29*Pi/64])*2 = 1.6848920710188384 + // 601/2048 = Cos[29*Pi/64]*2 = 0.2934609489107235 + let (se, s1) = RotateSubShift::half_kernel::<15, 15, 11>( + se, + s1h, + (18611, 55211, 601), + ); + // 9937/16384 = (Sin[27*Pi/64] + Cos[27*Pi/64])/2 = 0.6065057165489039 + // 1489/1024 = (Sin[27*Pi/64] - Cos[27*Pi/64])*2 = 1.4541021465825602 + // 3981/8192 = Cos[27*Pi/64]*2 = 0.4859603598065277 + let (s2, sd) = + RotateAddShift::half_kernel::<14, 10, 13>(s2, sdh, (9937, 1489, 3981)); + // 10473/16384 = (Sin[25*Pi/64] + Cos[25*Pi/64])/2 = 0.6392169592876205 + // 39627/32768 = (Sin[25*Pi/64] - Cos[25*Pi/64])*2 = 1.2093084235816014 + // 11039/16384 = Cos[25*Pi/64]*2 = 0.6737797067844401 + let (sc, s3) = RotateSubShift::half_kernel::<14, 15, 14>( + sc, + s3h, + (10473, 39627, 11039), + ); + // 2727/4096 = (Sin[23*Pi/64] + Cos[23*Pi/64])/2 = 0.6657721932768628 + // 3903/4096 = (Sin[23*Pi/64] - Cos[23*Pi/64])*2 = 0.9528683993863225 + // 7005/8192 = Cos[23*Pi/64]*2 = 0.8551101868605642 + let (s4, sb) = + RotateAddShift::half_kernel::<12, 12, 13>(s4, sbh, (2727, 3903, 7005)); + // 5619/8192 = (Sin[21*Pi/64] + Cos[21*Pi/64])/2 = 0.6859156770967569 + // 2815/4096 = (Sin[21*Pi/64] - Cos[21*Pi/64])*2 = 0.6872517316141069 + // 8423/8192 = Cos[21*Pi/64]*2 = 1.0282054883864433 + let (sa, s5) = + RotateSubShift::half_kernel::<13, 12, 13>(sa, s5h, (5619, 2815, 8423)); + // 2865/4096 = (Sin[19*Pi/64] + Cos[19*Pi/64])/2 = 0.6994534179865391 + // 13588/32768 = (Sin[19*Pi/64] - Cos[19*Pi/64])*2 = 0.4150164539764232 + // 305/256 = Cos[19*Pi/64]*2 = 1.1913986089848667 + let (s6, s9) = + RotateAddShift::half_kernel::<12, 15, 8>(s6, s9h, (2865, 13599, 305)); + // 23143/32768 = (Sin[17*Pi/64] + Cos[17*Pi/64])/2 = 0.7062550401009887 + // 1137/8192 = (Sin[17*Pi/64] - Cos[17*Pi/64])*2 = 0.1387843410158816 + // 11003/8192 = Cos[17*Pi/64]*2 = 1.3431179096940367 + let (s8, s7) = RotateSubShift::half_kernel::<15, 13, 13>( + s8, + s7h, + (23143, 1137, 11003), + ); + + // Stage 1 + let (s0, s7) = butterfly_sub_asym((s0.rshift1(), s0), s7); + let (s8, sf) = butterfly_sub_asym((s8.rshift1(), s8), sf); + let (s4, s3) = butterfly_add_asym((s4.rshift1(), s4), s3); + let (sc, sb) = butterfly_add_asym((sc.rshift1(), sc), sb); + let (s2, s5) = butterfly_sub_asym((s2.rshift1(), s2), s5); + let (sa, sd) = butterfly_sub_asym((sa.rshift1(), sa), sd); + let (s6, s1) = butterfly_add_asym((s6.rshift1(), s6), s1); + let (se, s9) = butterfly_add_asym((se.rshift1(), se), s9); + + // Stage 2 + let ((_s8h, s8), s4h) = butterfly_add(s8, s4); + let ((_s7h, s7), sbh) = butterfly_add(s7, sb); + let ((_sah, sa), s6h) = butterfly_sub(sa, s6); + let ((_s5h, s5), s9h) = butterfly_sub(s5, s9); + let (s0, s3h) = butterfly_add(s0, s3); + let (sd, seh) = butterfly_add(sd, se); + let (s2, s1h) = butterfly_sub(s2, s1); + let (sf, sch) = butterfly_sub(sf, sc); + + // Stage 3 + // 9633/8192 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 12873/16384 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 6393/32768 = Cos[7*Pi/16] = 0.1950903220161283 + let (s8, s7) = + RotateAdd::kernel::<13, 14, 15>(s8, s7, (9633, 12873, 6393)); + // 22725/16384 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/8192 = Cos[5*Pi/16] = 0.5555702330196022 + let (s9, s6) = + RotateAdd::kernel::<14, 15, 13>(s9h, s6h, (22725, 9041, 4551)); + // 11363/8192 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/8192 = Cos[5*Pi/16] = 0.5555702330196022 + let (s5, sa) = + RotateNeg::kernel::<13, 15, 13>(s5, sa, (11363, 9041, 4551)); + // 9633/32768 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 12873/16384 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 6393/32768 = Cos[7*Pi/16] = 0.1950903220161283 + let (s4, sb) = + RotateNeg::kernel::<13, 14, 15>(s4h, sbh, (9633, 12873, 6393)); + + // Stage 4 + let (s2, sc) = butterfly_add_asym(s2, sch); + let (s0, s1) = butterfly_sub_asym(s0, s1h); + let (sf, se) = butterfly_add_asym(sf, seh); + let (sd, s3) = butterfly_add_asym(sd, s3h); + let (s7, s6) = butterfly_add_asym((s7.rshift1(), s7), s6); + let (s8, s9) = butterfly_sub_asym((s8.rshift1(), s8), s9); + let (sa, sb) = butterfly_sub_asym((sa.rshift1(), sa), sb); + let (s5, s4) = butterfly_add_asym((s5.rshift1(), s5), s4); + + // Stage 5 + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (sc, s3) = + RotateAdd::kernel::<13, 14, 13>(sc, s3, (10703, 8867, 3135)); + // 10703/8192 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3870398453221475 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (s2, sd) = + RotateNeg::kernel::<13, 14, 13>(s2, sd, (10703, 8867, 3135)); + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (sa, s5) = RotatePi4Add::kernel::<13, 13>(sa, s5, (11585, 5793)); + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (s6, s9) = RotatePi4Add::kernel::<13, 13>(s6, s9, (11585, 5793)); + // 11585/8192 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (se, s1) = RotatePi4Add::kernel::<13, 13>(se, s1, (11585, 5793)); + + store_coeffs!( + output, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sa, sb, sc, sd, se, sf + ); +} + +#[$m] +$($s)* fn daala_fdct_ii_32( + t0: T, t1: T, t2: T, t3: T, t4: T, t5: T, t6: T, t7: T, t8: T, t9: T, ta: T, + tb: T, tc: T, td: T, te: T, tf: T, tg: T, th: T, ti: T, tj: T, tk: T, tl: T, + tm: T, tn: T, to: T, tp: T, tq: T, tr: T, ts: T, tt: T, tu: T, tv: T, + output: &mut [T], +) { + // +/- Butterflies with asymmetric output. + let (t0h, tv) = butterfly_neg(t0, tv); + let (t1, tuh) = butterfly_add(t1, tu); + let (t2h, tt) = butterfly_neg(t2, tt); + let (t3, tsh) = butterfly_add(t3, ts); + let (t4h, tr) = butterfly_neg(t4, tr); + let (t5, tqh) = butterfly_add(t5, tq); + let (t6h, tp) = butterfly_neg(t6, tp); + let (t7, toh) = butterfly_add(t7, to); + let (t8h, tn) = butterfly_neg(t8, tn); + let (t9, tmh) = butterfly_add(t9, tm); + let (tah, tl) = butterfly_neg(ta, tl); + let (tb, tkh) = butterfly_add(tb, tk); + let (tch, tj) = butterfly_neg(tc, tj); + let (td, tih) = butterfly_add(td, ti); + let (teh, th) = butterfly_neg(te, th); + let (tf, tgh) = butterfly_add(tf, tg); + + // Embedded 16-point transforms with asymmetric input. + daala_fdct_ii_16_asym( + t0h, + t1, + t2h, + t3, + t4h, + t5, + t6h, + t7, + t8h, + t9, + tah, + tb, + tch, + td, + teh, + tf, + &mut output[0..16], + ); + daala_fdst_iv_16_asym( + tv, + tuh, + tt, + tsh, + tr, + tqh, + tp, + toh, + tn, + tmh, + tl, + tkh, + tj, + tih, + th, + tgh, + &mut output[16..32], + ); + output[16..32].reverse(); +} + +#[$m] +$($s)* fn daala_fdct32(coeffs: &mut [T]) { + assert!(coeffs.len() >= 32); + let mut temp_out: [T; 32] = [T::zero(); 32]; + daala_fdct_ii_32( + coeffs[0], + coeffs[1], + coeffs[2], + coeffs[3], + coeffs[4], + coeffs[5], + coeffs[6], + coeffs[7], + coeffs[8], + coeffs[9], + coeffs[10], + coeffs[11], + coeffs[12], + coeffs[13], + coeffs[14], + coeffs[15], + coeffs[16], + coeffs[17], + coeffs[18], + coeffs[19], + coeffs[20], + coeffs[21], + coeffs[22], + coeffs[23], + coeffs[24], + coeffs[25], + coeffs[26], + coeffs[27], + coeffs[28], + coeffs[29], + coeffs[30], + coeffs[31], + &mut temp_out, + ); + + coeffs[0] = temp_out[0]; + coeffs[1] = temp_out[16]; + coeffs[2] = temp_out[8]; + coeffs[3] = temp_out[24]; + coeffs[4] = temp_out[4]; + coeffs[5] = temp_out[20]; + coeffs[6] = temp_out[12]; + coeffs[7] = temp_out[28]; + coeffs[8] = temp_out[2]; + coeffs[9] = temp_out[18]; + coeffs[10] = temp_out[10]; + coeffs[11] = temp_out[26]; + coeffs[12] = temp_out[6]; + coeffs[13] = temp_out[22]; + coeffs[14] = temp_out[14]; + coeffs[15] = temp_out[30]; + coeffs[16] = temp_out[1]; + coeffs[17] = temp_out[17]; + coeffs[18] = temp_out[9]; + coeffs[19] = temp_out[25]; + coeffs[20] = temp_out[5]; + coeffs[21] = temp_out[21]; + coeffs[22] = temp_out[13]; + coeffs[23] = temp_out[29]; + coeffs[24] = temp_out[3]; + coeffs[25] = temp_out[19]; + coeffs[26] = temp_out[11]; + coeffs[27] = temp_out[27]; + coeffs[28] = temp_out[7]; + coeffs[29] = temp_out[23]; + coeffs[30] = temp_out[15]; + coeffs[31] = temp_out[31]; +} + +#[$m] +$($s)* fn daala_fdct_ii_32_asym( + t0h: T, t1: (T, T), t2h: T, t3: (T, T), t4h: T, t5: (T, T), t6h: T, + t7: (T, T), t8h: T, t9: (T, T), tah: T, tb: (T, T), tch: T, td: (T, T), + teh: T, tf: (T, T), tgh: T, th: (T, T), tih: T, tj: (T, T), tkh: T, + tl: (T, T), tmh: T, tn: (T, T), toh: T, tp: (T, T), tqh: T, tr: (T, T), + tsh: T, tt: (T, T), tuh: T, tv: (T, T), output: &mut [T], +) { + // +/- Butterflies with asymmetric input. + let (t0, tv) = butterfly_neg_asym(t0h, tv); + let (t1, tu) = butterfly_sub_asym(t1, tuh); + let (t2, tt) = butterfly_neg_asym(t2h, tt); + let (t3, ts) = butterfly_sub_asym(t3, tsh); + let (t4, tr) = butterfly_neg_asym(t4h, tr); + let (t5, tq) = butterfly_sub_asym(t5, tqh); + let (t6, tp) = butterfly_neg_asym(t6h, tp); + let (t7, to) = butterfly_sub_asym(t7, toh); + let (t8, tn) = butterfly_neg_asym(t8h, tn); + let (t9, tm) = butterfly_sub_asym(t9, tmh); + let (ta, tl) = butterfly_neg_asym(tah, tl); + let (tb, tk) = butterfly_sub_asym(tb, tkh); + let (tc, tj) = butterfly_neg_asym(tch, tj); + let (td, ti) = butterfly_sub_asym(td, tih); + let (te, th) = butterfly_neg_asym(teh, th); + let (tf, tg) = butterfly_sub_asym(tf, tgh); + + // Embedded 16-point orthonormal transforms. + daala_fdct_ii_16( + t0, + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + ta, + tb, + tc, + td, + te, + tf, + &mut output[0..16], + ); + daala_fdst_iv_16( + tv, + tu, + tt, + ts, + tr, + tq, + tp, + to, + tn, + tm, + tl, + tk, + tj, + ti, + th, + tg, + &mut output[16..32], + ); + output[16..32].reverse(); +} + +#[$m] +$($s)* fn daala_fdst_iv_32_asym( + t0: (T, T), t1h: T, t2: (T, T), t3h: T, t4: (T, T), t5h: T, t6: (T, T), + t7h: T, t8: (T, T), t9h: T, ta: (T, T), tbh: T, tc: (T, T), tdh: T, + te: (T, T), tfh: T, tg: (T, T), thh: T, ti: (T, T), tjh: T, tk: (T, T), + tlh: T, tm: (T, T), tnh: T, to: (T, T), tph: T, tq: (T, T), trh: T, + ts: (T, T), tth: T, tu: (T, T), tvh: T, output: &mut [T], +) { + // Stage 0 + // 5933/8192 = (Sin[63*Pi/128] + Cos[63*Pi/128])/Sqrt[2] = 0.72424708295147 + // 22595/16384 = (Sin[63*Pi/128] - Cos[63*Pi/128])*Sqrt[2] = 1.37908108947413 + // 1137/32768 = Cos[63*Pi/128]*Sqrt[2] = 0.03470653821440 + let (t0, tv) = + RotateAdd::half_kernel::<13, 14, 15>(t0, tvh, (5933, 22595, 1137)); + // 6203/8192 = (Sin[61*Pi/128] + Cos[61*Pi/128])/Sqrt[2] = 0.75720884650648 + // 21403/16384 = (Sin[61*Pi/128] - Cos[61*Pi/128])*Sqrt[2] = 1.30634568590755 + // 3409/32768 = Cos[61*Pi/128]*Sqrt[2] = 0.10403600355271 + let (tu, t1) = + RotateSub::half_kernel::<13, 14, 15>(tu, t1h, (6203, 21403, 3409)); + // 25833/32768 = (Sin[59*Pi/128] + Cos[59*Pi/128])/Sqrt[2] = 0.78834642762661 + // 315/256 = (Sin[59*Pi/128] - Cos[59*Pi/128])*Sqrt[2] = 1.23046318116125 + // 5673/32768 = Cos[59*Pi/128]*Sqrt[2] = 0.17311483704598 + let (t2, tt) = + RotateAdd::half_kernel::<15, 8, 15>(t2, tth, (25833, 315, 5673)); + // 26791/32768 = (Sin[57*Pi/128] + Cos[57*Pi/128])/Sqrt[2] = 0.81758481315158 + // 4717/4096 = (Sin[57*Pi/128] - Cos[57*Pi/128])*Sqrt[2] = 1.15161638283569 + // 7923/32768 = Cos[57*Pi/128]*Sqrt[2] = 0.24177662173374 + let (ts, t3) = + RotateSub::half_kernel::<15, 12, 15>(ts, t3h, (26791, 4717, 7923)); + // 6921/8192 = (Sin[55*Pi/128] + Cos[55*Pi/128])/Sqrt[2] = 0.84485356524971 + // 17531/16384 = (Sin[55*Pi/128] - Cos[55*Pi/128])*Sqrt[2] = 1.06999523977419 + // 10153/32768 = Cos[55*Pi/128]*Sqrt[2] = 0.30985594536261 + let (t4, tr) = + RotateAdd::half_kernel::<13, 14, 15>(t4, trh, (6921, 17531, 10153)); + // 28511/32768 = (Sin[53*Pi/128] + Cos[53*Pi/128])/Sqrt[2] = 0.87008699110871 + // 32303/32768 = (Sin[53*Pi/128] - Cos[53*Pi/128])*Sqrt[2] = 0.98579638445957 + // 1545/4096 = Cos[53*Pi/128]*Sqrt[2] = 0.37718879887893 + let (tq, t5) = + RotateSub::half_kernel::<15, 15, 12>(tq, t5h, (28511, 32303, 1545)); + // 29269/32768 = (Sin[51*Pi/128] + Cos[51*Pi/128])/Sqrt[2] = 0.89322430119552 + // 14733/16384 = (Sin[51*Pi/128] - Cos[51*Pi/128])*Sqrt[2] = 0.89922265930921 + // 1817/4096 = Cos[51*Pi/128]*Sqrt[2] = 0.44361297154091 + let (t6, tp) = + RotateAdd::half_kernel::<15, 14, 12>(t6, tph, (29269, 14733, 1817)); + // 29957/32768 = (Sin[49*Pi/128] + Cos[49*Pi/128])/Sqrt[2] = 0.91420975570353 + // 13279/16384 = (Sin[49*Pi/128] - Cos[49*Pi/128])*Sqrt[2] = 0.81048262800998 + // 8339/16384 = Cos[49*Pi/128]*Sqrt[2] = 0.50896844169854 + let (to, t7) = + RotateSub::half_kernel::<15, 14, 14>(to, t7h, (29957, 13279, 8339)); + // 7643/8192 = (Sin[47*Pi/128] + Cos[47*Pi/128])/Sqrt[2] = 0.93299279883474 + // 11793/16384 = (Sin[47*Pi/128] - Cos[47*Pi/128])*Sqrt[2] = 0.71979007306998 + // 18779/32768 = Cos[47*Pi/128]*Sqrt[2] = 0.57309776229975 + let (t8, tn) = + RotateAdd::half_kernel::<13, 14, 15>(t8, tnh, (7643, 11793, 18779)); + // 15557/16384 = (Sin[45*Pi/128] + Cos[45*Pi/128])/Sqrt[2] = 0.94952818059304 + // 20557/32768 = (Sin[45*Pi/128] - Cos[45*Pi/128])*Sqrt[2] = 0.62736348079778 + // 20835/32768 = Cos[45*Pi/128]*Sqrt[2] = 0.63584644019415 + let (tm, t9) = + RotateSub::half_kernel::<14, 15, 15>(tm, t9h, (15557, 20557, 20835)); + // 31581/32768 = (Sin[43*Pi/128] + Cos[43*Pi/128])/Sqrt[2] = 0.96377606579544 + // 17479/32768 = (Sin[43*Pi/128] - Cos[43*Pi/128])*Sqrt[2] = 0.53342551494980 + // 22841/32768 = Cos[43*Pi/128]*Sqrt[2] = 0.69706330832054 + let (ta, tl) = + RotateAdd::half_kernel::<15, 15, 15>(ta, tlh, (31581, 17479, 22841)); + // 7993/8192 = (Sin[41*Pi/128] + Cos[41*Pi/128])/Sqrt[2] = 0.97570213003853 + // 14359/32768 = (Sin[41*Pi/128] - Cos[41*Pi/128])*Sqrt[2] = 0.43820248031374 + // 3099/4096 = Cos[41*Pi/128]*Sqrt[2] = 0.75660088988166 + let (tk, tb) = + RotateSub::half_kernel::<13, 15, 12>(tk, tbh, (7993, 14359, 3099)); + // 16143/16384 = (Sin[39*Pi/128] + Cos[39*Pi/128])/Sqrt[2] = 0.98527764238894 + // 2801/8192 = (Sin[39*Pi/128] - Cos[39*Pi/128])*Sqrt[2] = 0.34192377752060 + // 26683/32768 = Cos[39*Pi/128]*Sqrt[2] = 0.81431575362864 + let (tc, tj) = + RotateAdd::half_kernel::<14, 13, 15>(tc, tjh, (16143, 2801, 26683)); + // 16261/16384 = (Sin[37*Pi/128] + Cos[37*Pi/128])/Sqrt[2] = 0.99247953459871 + // 4011/16384 = (Sin[37*Pi/128] - Cos[37*Pi/128])*Sqrt[2] = 0.24482135039843 + // 14255/16384 = Cos[37*Pi/128]*Sqrt[2] = 0.87006885939949 + let (ti, td) = + RotateSub::half_kernel::<14, 14, 14>(ti, tdh, (16261, 4011, 14255)); + // 32679/32768 = (Sin[35*Pi/128] + Cos[35*Pi/128])/Sqrt[2] = 0.99729045667869 + // 4821/32768 = (Sin[35*Pi/128] - Cos[35*Pi/128])*Sqrt[2] = 0.14712912719933 + // 30269/32768 = Cos[35*Pi/128]*Sqrt[2] = 0.92372589307902 + let (te, th) = + RotateAdd::half_kernel::<15, 15, 15>(te, thh, (32679, 4821, 30269)); + // 16379/16384 = (Sin[33*Pi/128] + Cos[33*Pi/128])/Sqrt[2] = 0.99969881869620 + // 201/4096 = (Sin[33*Pi/128] - Cos[33*Pi/128])*Sqrt[2] = 0.04908245704582 + // 15977/16384 = Cos[33*Pi/128]*Sqrt[2] = 0.97515759017329 + let (tg, tf) = + RotateSub::half_kernel::<14, 12, 14>(tg, tfh, (16379, 201, 15977)); + + // Stage 1 + let (t0, tfh) = butterfly_add(t0, tf); + let (tv, tgh) = butterfly_sub(tv, tg); + let (th, tuh) = butterfly_add(th, tu); + let (te, t1h) = butterfly_sub(te, t1); + let (t2, tdh) = butterfly_add(t2, td); + let (tt, tih) = butterfly_sub(tt, ti); + let (tj, tsh) = butterfly_add(tj, ts); + let (tc, t3h) = butterfly_sub(tc, t3); + let (t4, tbh) = butterfly_add(t4, tb); + let (tr, tkh) = butterfly_sub(tr, tk); + let (tl, tqh) = butterfly_add(tl, tq); + let (ta, t5h) = butterfly_sub(ta, t5); + let (t6, t9h) = butterfly_add(t6, t9); + let (tp, tmh) = butterfly_sub(tp, tm); + let (tn, toh) = butterfly_add(tn, to); + let (t8, t7h) = butterfly_sub(t8, t7); + + // Stage 2 + let (t0, t7) = butterfly_sub_asym(t0, t7h); + let (tv, to) = butterfly_add_asym(tv, toh); + let (tp, tu) = butterfly_sub_asym(tp, tuh); + let (t6, t1) = butterfly_add_asym(t6, t1h); + let (t2, t5) = butterfly_sub_asym(t2, t5h); + let (tt, tq) = butterfly_add_asym(tt, tqh); + let (tr, ts) = butterfly_sub_asym(tr, tsh); + let (t4, t3) = butterfly_add_asym(t4, t3h); + let (t8, tg) = butterfly_add_asym(t8, tgh); + let (te, tm) = butterfly_sub_asym(te, tmh); + let (tn, tf) = butterfly_add_asym(tn, tfh); + let (th, t9) = butterfly_sub_asym(th, t9h); + let (ta, ti) = butterfly_add_asym(ta, tih); + let (tc, tk) = butterfly_sub_asym(tc, tkh); + let (tl, td) = butterfly_add_asym(tl, tdh); + let (tj, tb) = butterfly_sub_asym(tj, tbh); + + // Stage 3 + // 17911/16384 = Sin[15*Pi/32] + Cos[15*Pi/32] = 1.0932018670017576 + // 14699/16384 = Sin[15*Pi/32] - Cos[15*Pi/32] = 0.8971675863426363 + // 803/8192 = Cos[15*Pi/32] = 0.0980171403295606 + let (tf, tg) = + RotateSub::kernel::<14, 14, 13>(tf, tg, (17911, 14699, 803)); + // 10217/8192 = Sin[13*Pi/32] + Cos[13*Pi/32] = 1.2472250129866712 + // 5461/8192 = Sin[13*Pi/32] - Cos[13*Pi/32] = 0.6666556584777465 + // 1189/4096 = Cos[13*Pi/32] = 0.2902846772544623 + let (th, te) = + RotateAdd::kernel::<13, 13, 12>(th, te, (10217, 5461, 1189)); + // 5543/4096 = Sin[11*Pi/32] + Cos[11*Pi/32] = 1.3533180011743526 + // 3363/8192 = Sin[11*Pi/32] - Cos[11*Pi/32] = 0.4105245275223574 + // 7723/16384 = Cos[11*Pi/32] = 0.4713967368259976 + let (ti, td) = + RotateAdd::kernel::<12, 13, 14>(ti, td, (5543, 3363, 7723)); + // 11529/8192 = Sin[9*Pi/32] + Cos[9*Pi/32] = 1.4074037375263826 + // 2271/16384 = Sin[9*Pi/32] - Cos[9*Pi/32] = 0.1386171691990915 + // 5197/8192 = Cos[9*Pi/32] = 0.6343932841636455 + let (tc, tj) = + RotateSub::kernel::<13, 14, 13>(tc, tj, (11529, 2271, 5197)); + // 11529/8192 = Sin[9*Pi/32] + Cos[9*Pi/32] = 1.4074037375263826 + // 2271/16384 = Sin[9*Pi/32] - Cos[9*Pi/32] = 0.1386171691990915 + // 5197/8192 = Cos[9*Pi/32] = 0.6343932841636455 + let (tb, tk) = + RotateNeg::kernel::<13, 14, 13>(tb, tk, (11529, 2271, 5197)); + // 5543/4096 = Sin[11*Pi/32] + Cos[11*Pi/32] = 1.3533180011743526 + // 3363/8192 = Sin[11*Pi/32] - Cos[11*Pi/32] = 0.4105245275223574 + // 7723/16384 = Cos[11*Pi/32] = 0.4713967368259976 + let (ta, tl) = + RotateNeg::kernel::<12, 13, 14>(ta, tl, (5543, 3363, 7723)); + // 10217/8192 = Sin[13*Pi/32] + Cos[13*Pi/32] = 1.2472250129866712 + // 5461/8192 = Sin[13*Pi/32] - Cos[13*Pi/32] = 0.6666556584777465 + // 1189/4096 = Cos[13*Pi/32] = 0.2902846772544623 + let (t9, tm) = + RotateNeg::kernel::<13, 13, 12>(t9, tm, (10217, 5461, 1189)); + // 17911/16384 = Sin[15*Pi/32] + Cos[15*Pi/32] = 1.0932018670017576 + // 14699/16384 = Sin[15*Pi/32] - Cos[15*Pi/32] = 0.8971675863426363 + // 803/8192 = Cos[15*Pi/32] = 0.0980171403295606 + let (t8, tn) = + RotateNeg::kernel::<14, 14, 13>(t8, tn, (17911, 14699, 803)); + + // Stage 4 + let (t3, t0h) = butterfly_sub(t3, t0); + let (ts, tvh) = butterfly_add(ts, tv); + let (tu, tth) = butterfly_sub(tu, tt); + let (t1, t2h) = butterfly_add(t1, t2); + let ((_toh, to), t4h) = butterfly_add(to, t4); + let ((_tqh, tq), t6h) = butterfly_sub(tq, t6); + let ((_t7h, t7), trh) = butterfly_add(t7, tr); + let ((_t5h, t5), tph) = butterfly_sub(t5, tp); + let (tb, t8h) = butterfly_sub(tb, t8); + let (tk, tnh) = butterfly_add(tk, tn); + let (tm, tlh) = butterfly_sub(tm, tl); + let (t9, tah) = butterfly_add(t9, ta); + let (tf, tch) = butterfly_sub(tf, tc); + let (tg, tjh) = butterfly_add(tg, tj); + let (ti, thh) = butterfly_sub(ti, th); + let (td, teh) = butterfly_add(td, te); + + // Stage 5 + // 301/256 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 1609/2048 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 6393/32768 = Cos[7*Pi/16] = 0.1950903220161283 + let (to, t7) = RotateAdd::kernel::<8, 11, 15>(to, t7, (301, 1609, 6393)); + // 11363/8192 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/8192 = Cos[5*Pi/16] = 0.5555702330196022 + let (tph, t6h) = + RotateAdd::kernel::<13, 15, 13>(tph, t6h, (11363, 9041, 4551)); + // 5681/4096 = Sin[5*Pi/16] + Cos[5*Pi/16] = 1.3870398453221475 + // 9041/32768 = Sin[5*Pi/16] - Cos[5*Pi/16] = 0.2758993792829431 + // 4551/8192 = Cos[5*Pi/16] = 0.5555702330196022 + let (t5, tq) = + RotateNeg::kernel::<12, 15, 13>(t5, tq, (5681, 9041, 4551)); + // 9633/8192 = Sin[7*Pi/16] + Cos[7*Pi/16] = 1.1758756024193586 + // 12873/16384 = Sin[7*Pi/16] - Cos[7*Pi/16] = 0.7856949583871022 + // 6393/32768 = Cos[7*Pi/16] = 0.1950903220161283 + let (t4h, trh) = + RotateNeg::kernel::<13, 14, 15>(t4h, trh, (9633, 12873, 6393)); + + // Stage 6 + let (t1, t0) = butterfly_add_asym(t1, t0h); + let (tu, tv) = butterfly_sub_asym(tu, tvh); + let (ts, t2) = butterfly_sub_asym(ts, t2h); + let (t3, tt) = butterfly_sub_asym(t3, tth); + let (t5, t4) = butterfly_add_asym((t5.rshift1(), t5), t4h); + let (tq, tr) = butterfly_sub_asym((tq.rshift1(), tq), trh); + let (t7, t6) = butterfly_add_asym((t7.rshift1(), t7), t6h); + let (to, tp) = butterfly_sub_asym((to.rshift1(), to), tph); + let (t9, t8) = butterfly_add_asym(t9, t8h); + let (tm, tn) = butterfly_sub_asym(tm, tnh); + let (tk, ta) = butterfly_sub_asym(tk, tah); + let (tb, tl) = butterfly_sub_asym(tb, tlh); + let (ti, tc) = butterfly_add_asym(ti, tch); + let (td, tj) = butterfly_add_asym(td, tjh); + let (tf, te) = butterfly_add_asym(tf, teh); + let (tg, th) = butterfly_sub_asym(tg, thh); + + // Stage 7 + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (t2, tt) = RotateNeg::kernel::<9, 14, 13>(t2, tt, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (ts, t3) = RotateAdd::kernel::<9, 14, 13>(ts, t3, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (ta, tl) = RotateNeg::kernel::<9, 14, 13>(ta, tl, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (tk, tb) = RotateAdd::kernel::<9, 14, 13>(tk, tb, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (tc, tj) = RotateAdd::kernel::<9, 14, 13>(tc, tj, (669, 8867, 3135)); + // 669/512 = Sin[3*Pi/8] + Cos[3*Pi/8] = 1.3065629648763766 + // 8867/16384 = Sin[3*Pi/8] - Cos[3*Pi/8] = 0.5411961001461969 + // 3135/8192 = Cos[3*Pi/8] = 0.3826834323650898 + let (ti, td) = RotateNeg::kernel::<9, 14, 13>(ti, td, (669, 8867, 3135)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (tu, t1) = RotatePi4Add::kernel::<12, 13>(tu, t1, (5793, 5793)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (tq, t5) = RotatePi4Add::kernel::<12, 13>(tq, t5, (5793, 5793)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (tp, t6) = RotatePi4Sub::kernel::<12, 13>(tp, t6, (5793, 5793)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (tm, t9) = RotatePi4Add::kernel::<12, 13>(tm, t9, (5793, 5793)); + // 5793/4096 = Sin[Pi/4] + Cos[Pi/4] = 1.4142135623730951 + // 5793/8192 = Cos[Pi/4] = 0.7071067811865475 + let (te, th) = RotatePi4Add::kernel::<12, 13>(te, th, (5793, 5793)); + + store_coeffs!( + output, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc, td, te, tf, + tg, th, ti, tj, tk, tl, tm, tn, to, tp, tq, tr, ts, tt, tu, tv + ); +} + +#[allow(clippy::identity_op)] +#[$m] +$($s)* fn daala_fdct64(coeffs: &mut [T]) { + assert!(coeffs.len() >= 64); + // Use arrays to avoid ridiculous variable names + let mut asym: [(T, T); 32] = [(T::zero(), T::zero()); 32]; + let mut half: [T; 32] = [T::zero(); 32]; + // +/- Butterflies with asymmetric output. + { + #[$m] + #[inline] + $($s)* fn butterfly_pair( + half: &mut [T; 32], asym: &mut [(T, T); 32], input: &[T], i: usize + ) { + let j = i * 2; + let (ah, c) = butterfly_neg(input[j], input[63 - j]); + let (b, dh) = butterfly_add(input[j + 1], input[63 - j - 1]); + half[i] = ah; + half[31 - i] = dh; + asym[i] = b; + asym[31 - i] = c; + } + butterfly_pair(&mut half, &mut asym, coeffs, 0); + butterfly_pair(&mut half, &mut asym, coeffs, 1); + butterfly_pair(&mut half, &mut asym, coeffs, 2); + butterfly_pair(&mut half, &mut asym, coeffs, 3); + butterfly_pair(&mut half, &mut asym, coeffs, 4); + butterfly_pair(&mut half, &mut asym, coeffs, 5); + butterfly_pair(&mut half, &mut asym, coeffs, 6); + butterfly_pair(&mut half, &mut asym, coeffs, 7); + butterfly_pair(&mut half, &mut asym, coeffs, 8); + butterfly_pair(&mut half, &mut asym, coeffs, 9); + butterfly_pair(&mut half, &mut asym, coeffs, 10); + butterfly_pair(&mut half, &mut asym, coeffs, 11); + butterfly_pair(&mut half, &mut asym, coeffs, 12); + butterfly_pair(&mut half, &mut asym, coeffs, 13); + butterfly_pair(&mut half, &mut asym, coeffs, 14); + butterfly_pair(&mut half, &mut asym, coeffs, 15); + } + + let mut temp_out: [T; 64] = [T::zero(); 64]; + // Embedded 2-point transforms with asymmetric input. + daala_fdct_ii_32_asym( + half[0], + asym[0], + half[1], + asym[1], + half[2], + asym[2], + half[3], + asym[3], + half[4], + asym[4], + half[5], + asym[5], + half[6], + asym[6], + half[7], + asym[7], + half[8], + asym[8], + half[9], + asym[9], + half[10], + asym[10], + half[11], + asym[11], + half[12], + asym[12], + half[13], + asym[13], + half[14], + asym[14], + half[15], + asym[15], + &mut temp_out[0..32], + ); + daala_fdst_iv_32_asym( + asym[31], + half[31], + asym[30], + half[30], + asym[29], + half[29], + asym[28], + half[28], + asym[27], + half[27], + asym[26], + half[26], + asym[25], + half[25], + asym[24], + half[24], + asym[23], + half[23], + asym[22], + half[22], + asym[21], + half[21], + asym[20], + half[20], + asym[19], + half[19], + asym[18], + half[18], + asym[17], + half[17], + asym[16], + half[16], + &mut temp_out[32..64], + ); + temp_out[32..64].reverse(); + + // Store a reordered version of output in temp_out + #[$m] + #[inline] + $($s)* fn reorder_4( + output: &mut [T], i: usize, tmp: [T; 64], j: usize + ) { + output[0 + i * 4] = tmp[0 + j]; + output[1 + i * 4] = tmp[32 + j]; + output[2 + i * 4] = tmp[16 + j]; + output[3 + i * 4] = tmp[48 + j]; + } + reorder_4(coeffs, 0, temp_out, 0); + reorder_4(coeffs, 1, temp_out, 8); + reorder_4(coeffs, 2, temp_out, 4); + reorder_4(coeffs, 3, temp_out, 12); + reorder_4(coeffs, 4, temp_out, 2); + reorder_4(coeffs, 5, temp_out, 10); + reorder_4(coeffs, 6, temp_out, 6); + reorder_4(coeffs, 7, temp_out, 14); + + reorder_4(coeffs, 8, temp_out, 1); + reorder_4(coeffs, 9, temp_out, 9); + reorder_4(coeffs, 10, temp_out, 5); + reorder_4(coeffs, 11, temp_out, 13); + reorder_4(coeffs, 12, temp_out, 3); + reorder_4(coeffs, 13, temp_out, 11); + reorder_4(coeffs, 14, temp_out, 7); + reorder_4(coeffs, 15, temp_out, 15); +} + +#[$m] +$($s)* fn fidentity(_coeffs: &mut [T]) {} + +#[$m] +$($s)* fn fwht4(coeffs: &mut [T]) { + assert!(coeffs.len() >= 4); + let x0 = coeffs[0]; + let x1 = coeffs[1]; + let x2 = coeffs[2]; + let x3 = coeffs[3]; + + let s0 = x0.add(x1); + let s1 = x3.sub(x2); + let s2 = s0.sub_avg(s1); + + let q1 = s2.sub(x2); + let q0 = s0.sub(q1); + let q3 = s2.sub(x1); + let q2 = s1.add(q3); + + store_coeffs!(coeffs, q0, q1, q2, q3); +} + +} + +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/inverse.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/inverse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/inverse.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/inverse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1712 @@ +// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +cfg_if::cfg_if! { + if #[cfg(nasm_x86_64)] { + pub use crate::asm::x86::transform::inverse::*; + } else if #[cfg(asm_neon)] { + pub use crate::asm::aarch64::transform::inverse::*; + } else { + pub use self::rust::*; + } +} + +use crate::tiling::PlaneRegionMut; +use crate::util::*; + +// TODO: move 1d txfm code to rust module. + +use super::clamp_value; +use super::consts::*; +use super::get_1d_tx_types; +use super::half_btf; +use super::TxSize; +use super::TxType; + +/// # Panics +/// +/// - If `input` or `output` have fewer than 4 items. +pub fn av1_iwht4(input: &[i32], output: &mut [i32], _range: usize) { + assert!(input.len() >= 4); + assert!(output.len() >= 4); + + // + let x0 = input[0]; + let x1 = input[1]; + let x2 = input[2]; + let x3 = input[3]; + let s0 = x0 + x1; + let s2 = x2 - x3; + let s4 = (s0 - s2) >> 1; + let s3 = s4 - x3; + let s1 = s4 - x1; + output[0] = s0 - s3; + output[1] = s3; + output[2] = s1; + output[3] = s2 + s1; +} + +static COSPI_INV: [i32; 64] = [ + 4096, 4095, 4091, 4085, 4076, 4065, 4052, 4036, 4017, 3996, 3973, 3948, + 3920, 3889, 3857, 3822, 3784, 3745, 3703, 3659, 3612, 3564, 3513, 3461, + 3406, 3349, 3290, 3229, 3166, 3102, 3035, 2967, 2896, 2824, 2751, 2675, + 2598, 2520, 2440, 2359, 2276, 2191, 2106, 2019, 1931, 1842, 1751, 1660, + 1567, 1474, 1380, 1285, 1189, 1092, 995, 897, 799, 700, 601, 501, 401, 301, + 201, 101, +]; + +static SINPI_INV: [i32; 5] = [0, 1321, 2482, 3344, 3803]; + +const INV_COS_BIT: usize = 12; + +/// # Panics +/// +/// - If `input` or `output` have fewer than 4 items. +pub fn av1_idct4(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 4); + assert!(output.len() >= 4); + + // stage 1 + let stg1 = [input[0], input[2], input[1], input[3]]; + + // stage 2 + let stg2 = [ + half_btf(COSPI_INV[32], stg1[0], COSPI_INV[32], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[32], stg1[0], -COSPI_INV[32], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[48], stg1[2], -COSPI_INV[16], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[16], stg1[2], COSPI_INV[48], stg1[3], INV_COS_BIT), + ]; + + // stage 3 + output[0] = clamp_value(stg2[0] + stg2[3], range); + output[1] = clamp_value(stg2[1] + stg2[2], range); + output[2] = clamp_value(stg2[1] - stg2[2], range); + output[3] = clamp_value(stg2[0] - stg2[3], range); +} + +pub fn av1_iflipadst4(input: &[i32], output: &mut [i32], range: usize) { + av1_iadst4(input, output, range); + output[..4].reverse(); +} + +/// # Panics +/// +/// - If `input` or `output` have fewer than 4 items. +#[inline(always)] +pub fn av1_iadst4(input: &[i32], output: &mut [i32], _range: usize) { + assert!(input.len() >= 4); + assert!(output.len() >= 4); + + let bit = 12; + + let x0 = input[0]; + let x1 = input[1]; + let x2 = input[2]; + let x3 = input[3]; + + // stage 1 + let s0 = SINPI_INV[1] * x0; + let s1 = SINPI_INV[2] * x0; + let s2 = SINPI_INV[3] * x1; + let s3 = SINPI_INV[4] * x2; + let s4 = SINPI_INV[1] * x2; + let s5 = SINPI_INV[2] * x3; + let s6 = SINPI_INV[4] * x3; + + // stage 2 + let s7 = (x0 - x2) + x3; + + // stage 3 + let s0 = s0 + s3; + let s1 = s1 - s4; + let s3 = s2; + let s2 = SINPI_INV[3] * s7; + + // stage 4 + let s0 = s0 + s5; + let s1 = s1 - s6; + + // stage 5 + let x0 = s0 + s3; + let x1 = s1 + s3; + let x2 = s2; + let x3 = s0 + s1; + + // stage 6 + let x3 = x3 - s3; + + output[0] = round_shift(x0, bit); + output[1] = round_shift(x1, bit); + output[2] = round_shift(x2, bit); + output[3] = round_shift(x3, bit); +} + +pub fn av1_iidentity4(input: &[i32], output: &mut [i32], _range: usize) { + output[..4] + .iter_mut() + .zip(input[..4].iter()) + .for_each(|(outp, inp)| *outp = round_shift(SQRT2 * *inp, 12)); +} + +/// # Panics +/// +/// - If `input` or `output` have fewer than 8 items. +pub fn av1_idct8(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 8); + assert!(output.len() >= 8); + + // call idct4 + let temp_in = [input[0], input[2], input[4], input[6]]; + let mut temp_out: [i32; 4] = [0; 4]; + av1_idct4(&temp_in, &mut temp_out, range); + + // stage 0 + + // stage 1 + let stg1 = [input[1], input[5], input[3], input[7]]; + + // stage 2 + let stg2 = [ + half_btf(COSPI_INV[56], stg1[0], -COSPI_INV[8], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[24], stg1[1], -COSPI_INV[40], stg1[2], INV_COS_BIT), + half_btf(COSPI_INV[40], stg1[1], COSPI_INV[24], stg1[2], INV_COS_BIT), + half_btf(COSPI_INV[8], stg1[0], COSPI_INV[56], stg1[3], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + clamp_value(stg2[0] + stg2[1], range), + clamp_value(stg2[0] - stg2[1], range), + clamp_value(-stg2[2] + stg2[3], range), + clamp_value(stg2[2] + stg2[3], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + half_btf(-COSPI_INV[32], stg3[1], COSPI_INV[32], stg3[2], INV_COS_BIT), + half_btf(COSPI_INV[32], stg3[1], COSPI_INV[32], stg3[2], INV_COS_BIT), + stg3[3], + ]; + + // stage 5 + output[0] = clamp_value(temp_out[0] + stg4[3], range); + output[1] = clamp_value(temp_out[1] + stg4[2], range); + output[2] = clamp_value(temp_out[2] + stg4[1], range); + output[3] = clamp_value(temp_out[3] + stg4[0], range); + output[4] = clamp_value(temp_out[3] - stg4[0], range); + output[5] = clamp_value(temp_out[2] - stg4[1], range); + output[6] = clamp_value(temp_out[1] - stg4[2], range); + output[7] = clamp_value(temp_out[0] - stg4[3], range); +} + +pub fn av1_iflipadst8(input: &[i32], output: &mut [i32], range: usize) { + av1_iadst8(input, output, range); + output[..8].reverse(); +} + +/// # Panics +/// +/// - If `input` or `output` have fewer than 8 items. +#[inline(always)] +pub fn av1_iadst8(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 8); + assert!(output.len() >= 8); + + // stage 1 + let stg1 = [ + input[7], input[0], input[5], input[2], input[3], input[4], input[1], + input[6], + ]; + + // stage 2 + let stg2 = [ + half_btf(COSPI_INV[4], stg1[0], COSPI_INV[60], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[60], stg1[0], -COSPI_INV[4], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[20], stg1[2], COSPI_INV[44], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[44], stg1[2], -COSPI_INV[20], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[36], stg1[4], COSPI_INV[28], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[28], stg1[4], -COSPI_INV[36], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[52], stg1[6], COSPI_INV[12], stg1[7], INV_COS_BIT), + half_btf(COSPI_INV[12], stg1[6], -COSPI_INV[52], stg1[7], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + clamp_value(stg2[0] + stg2[4], range), + clamp_value(stg2[1] + stg2[5], range), + clamp_value(stg2[2] + stg2[6], range), + clamp_value(stg2[3] + stg2[7], range), + clamp_value(stg2[0] - stg2[4], range), + clamp_value(stg2[1] - stg2[5], range), + clamp_value(stg2[2] - stg2[6], range), + clamp_value(stg2[3] - stg2[7], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + stg3[1], + stg3[2], + stg3[3], + half_btf(COSPI_INV[16], stg3[4], COSPI_INV[48], stg3[5], INV_COS_BIT), + half_btf(COSPI_INV[48], stg3[4], -COSPI_INV[16], stg3[5], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg3[6], COSPI_INV[16], stg3[7], INV_COS_BIT), + half_btf(COSPI_INV[16], stg3[6], COSPI_INV[48], stg3[7], INV_COS_BIT), + ]; + + // stage 5 + let stg5 = [ + clamp_value(stg4[0] + stg4[2], range), + clamp_value(stg4[1] + stg4[3], range), + clamp_value(stg4[0] - stg4[2], range), + clamp_value(stg4[1] - stg4[3], range), + clamp_value(stg4[4] + stg4[6], range), + clamp_value(stg4[5] + stg4[7], range), + clamp_value(stg4[4] - stg4[6], range), + clamp_value(stg4[5] - stg4[7], range), + ]; + + // stage 6 + let stg6 = [ + stg5[0], + stg5[1], + half_btf(COSPI_INV[32], stg5[2], COSPI_INV[32], stg5[3], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[2], -COSPI_INV[32], stg5[3], INV_COS_BIT), + stg5[4], + stg5[5], + half_btf(COSPI_INV[32], stg5[6], COSPI_INV[32], stg5[7], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[6], -COSPI_INV[32], stg5[7], INV_COS_BIT), + ]; + + // stage 7 + output[0] = stg6[0]; + output[1] = -stg6[4]; + output[2] = stg6[6]; + output[3] = -stg6[2]; + output[4] = stg6[3]; + output[5] = -stg6[7]; + output[6] = stg6[5]; + output[7] = -stg6[1]; +} + +pub fn av1_iidentity8(input: &[i32], output: &mut [i32], _range: usize) { + output[..8] + .iter_mut() + .zip(input[..8].iter()) + .for_each(|(outp, inp)| *outp = 2 * *inp); +} + +fn av1_idct16(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 16); + assert!(output.len() >= 16); + + // call idct8 + let temp_in = [ + input[0], input[2], input[4], input[6], input[8], input[10], input[12], + input[14], + ]; + let mut temp_out: [i32; 8] = [0; 8]; + av1_idct8(&temp_in, &mut temp_out, range); + + // stage 1 + let stg1 = [ + input[1], input[9], input[5], input[13], input[3], input[11], input[7], + input[15], + ]; + + // stage 2 + let stg2 = [ + half_btf(COSPI_INV[60], stg1[0], -COSPI_INV[4], stg1[7], INV_COS_BIT), + half_btf(COSPI_INV[28], stg1[1], -COSPI_INV[36], stg1[6], INV_COS_BIT), + half_btf(COSPI_INV[44], stg1[2], -COSPI_INV[20], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[12], stg1[3], -COSPI_INV[52], stg1[4], INV_COS_BIT), + half_btf(COSPI_INV[52], stg1[3], COSPI_INV[12], stg1[4], INV_COS_BIT), + half_btf(COSPI_INV[20], stg1[2], COSPI_INV[44], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[36], stg1[1], COSPI_INV[28], stg1[6], INV_COS_BIT), + half_btf(COSPI_INV[4], stg1[0], COSPI_INV[60], stg1[7], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + clamp_value(stg2[0] + stg2[1], range), + clamp_value(stg2[0] - stg2[1], range), + clamp_value(-stg2[2] + stg2[3], range), + clamp_value(stg2[2] + stg2[3], range), + clamp_value(stg2[4] + stg2[5], range), + clamp_value(stg2[4] - stg2[5], range), + clamp_value(-stg2[6] + stg2[7], range), + clamp_value(stg2[6] + stg2[7], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + half_btf(-COSPI_INV[16], stg3[1], COSPI_INV[48], stg3[6], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg3[2], -COSPI_INV[16], stg3[5], INV_COS_BIT), + stg3[3], + stg3[4], + half_btf(-COSPI_INV[16], stg3[2], COSPI_INV[48], stg3[5], INV_COS_BIT), + half_btf(COSPI_INV[48], stg3[1], COSPI_INV[16], stg3[6], INV_COS_BIT), + stg3[7], + ]; + + // stage 5 + let stg5 = [ + clamp_value(stg4[0] + stg4[3], range), + clamp_value(stg4[1] + stg4[2], range), + clamp_value(stg4[1] - stg4[2], range), + clamp_value(stg4[0] - stg4[3], range), + clamp_value(-stg4[4] + stg4[7], range), + clamp_value(-stg4[5] + stg4[6], range), + clamp_value(stg4[5] + stg4[6], range), + clamp_value(stg4[4] + stg4[7], range), + ]; + + // stage 6 + let stg6 = [ + stg5[0], + stg5[1], + half_btf(-COSPI_INV[32], stg5[2], COSPI_INV[32], stg5[5], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg5[3], COSPI_INV[32], stg5[4], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[3], COSPI_INV[32], stg5[4], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[2], COSPI_INV[32], stg5[5], INV_COS_BIT), + stg5[6], + stg5[7], + ]; + + // stage 7 + output[0] = clamp_value(temp_out[0] + stg6[7], range); + output[1] = clamp_value(temp_out[1] + stg6[6], range); + output[2] = clamp_value(temp_out[2] + stg6[5], range); + output[3] = clamp_value(temp_out[3] + stg6[4], range); + output[4] = clamp_value(temp_out[4] + stg6[3], range); + output[5] = clamp_value(temp_out[5] + stg6[2], range); + output[6] = clamp_value(temp_out[6] + stg6[1], range); + output[7] = clamp_value(temp_out[7] + stg6[0], range); + output[8] = clamp_value(temp_out[7] - stg6[0], range); + output[9] = clamp_value(temp_out[6] - stg6[1], range); + output[10] = clamp_value(temp_out[5] - stg6[2], range); + output[11] = clamp_value(temp_out[4] - stg6[3], range); + output[12] = clamp_value(temp_out[3] - stg6[4], range); + output[13] = clamp_value(temp_out[2] - stg6[5], range); + output[14] = clamp_value(temp_out[1] - stg6[6], range); + output[15] = clamp_value(temp_out[0] - stg6[7], range); +} + +pub fn av1_iflipadst16(input: &[i32], output: &mut [i32], range: usize) { + av1_iadst16(input, output, range); + output[..16].reverse(); +} + +#[inline(always)] +fn av1_iadst16(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 16); + assert!(output.len() >= 16); + + // stage 1 + let stg1 = [ + input[15], input[0], input[13], input[2], input[11], input[4], input[9], + input[6], input[7], input[8], input[5], input[10], input[3], input[12], + input[1], input[14], + ]; + + // stage 2 + let stg2 = [ + half_btf(COSPI_INV[2], stg1[0], COSPI_INV[62], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[62], stg1[0], -COSPI_INV[2], stg1[1], INV_COS_BIT), + half_btf(COSPI_INV[10], stg1[2], COSPI_INV[54], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[54], stg1[2], -COSPI_INV[10], stg1[3], INV_COS_BIT), + half_btf(COSPI_INV[18], stg1[4], COSPI_INV[46], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[46], stg1[4], -COSPI_INV[18], stg1[5], INV_COS_BIT), + half_btf(COSPI_INV[26], stg1[6], COSPI_INV[38], stg1[7], INV_COS_BIT), + half_btf(COSPI_INV[38], stg1[6], -COSPI_INV[26], stg1[7], INV_COS_BIT), + half_btf(COSPI_INV[34], stg1[8], COSPI_INV[30], stg1[9], INV_COS_BIT), + half_btf(COSPI_INV[30], stg1[8], -COSPI_INV[34], stg1[9], INV_COS_BIT), + half_btf(COSPI_INV[42], stg1[10], COSPI_INV[22], stg1[11], INV_COS_BIT), + half_btf(COSPI_INV[22], stg1[10], -COSPI_INV[42], stg1[11], INV_COS_BIT), + half_btf(COSPI_INV[50], stg1[12], COSPI_INV[14], stg1[13], INV_COS_BIT), + half_btf(COSPI_INV[14], stg1[12], -COSPI_INV[50], stg1[13], INV_COS_BIT), + half_btf(COSPI_INV[58], stg1[14], COSPI_INV[6], stg1[15], INV_COS_BIT), + half_btf(COSPI_INV[6], stg1[14], -COSPI_INV[58], stg1[15], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + clamp_value(stg2[0] + stg2[8], range), + clamp_value(stg2[1] + stg2[9], range), + clamp_value(stg2[2] + stg2[10], range), + clamp_value(stg2[3] + stg2[11], range), + clamp_value(stg2[4] + stg2[12], range), + clamp_value(stg2[5] + stg2[13], range), + clamp_value(stg2[6] + stg2[14], range), + clamp_value(stg2[7] + stg2[15], range), + clamp_value(stg2[0] - stg2[8], range), + clamp_value(stg2[1] - stg2[9], range), + clamp_value(stg2[2] - stg2[10], range), + clamp_value(stg2[3] - stg2[11], range), + clamp_value(stg2[4] - stg2[12], range), + clamp_value(stg2[5] - stg2[13], range), + clamp_value(stg2[6] - stg2[14], range), + clamp_value(stg2[7] - stg2[15], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + stg3[1], + stg3[2], + stg3[3], + stg3[4], + stg3[5], + stg3[6], + stg3[7], + half_btf(COSPI_INV[8], stg3[8], COSPI_INV[56], stg3[9], INV_COS_BIT), + half_btf(COSPI_INV[56], stg3[8], -COSPI_INV[8], stg3[9], INV_COS_BIT), + half_btf(COSPI_INV[40], stg3[10], COSPI_INV[24], stg3[11], INV_COS_BIT), + half_btf(COSPI_INV[24], stg3[10], -COSPI_INV[40], stg3[11], INV_COS_BIT), + half_btf(-COSPI_INV[56], stg3[12], COSPI_INV[8], stg3[13], INV_COS_BIT), + half_btf(COSPI_INV[8], stg3[12], COSPI_INV[56], stg3[13], INV_COS_BIT), + half_btf(-COSPI_INV[24], stg3[14], COSPI_INV[40], stg3[15], INV_COS_BIT), + half_btf(COSPI_INV[40], stg3[14], COSPI_INV[24], stg3[15], INV_COS_BIT), + ]; + + // stage 5 + let stg5 = [ + clamp_value(stg4[0] + stg4[4], range), + clamp_value(stg4[1] + stg4[5], range), + clamp_value(stg4[2] + stg4[6], range), + clamp_value(stg4[3] + stg4[7], range), + clamp_value(stg4[0] - stg4[4], range), + clamp_value(stg4[1] - stg4[5], range), + clamp_value(stg4[2] - stg4[6], range), + clamp_value(stg4[3] - stg4[7], range), + clamp_value(stg4[8] + stg4[12], range), + clamp_value(stg4[9] + stg4[13], range), + clamp_value(stg4[10] + stg4[14], range), + clamp_value(stg4[11] + stg4[15], range), + clamp_value(stg4[8] - stg4[12], range), + clamp_value(stg4[9] - stg4[13], range), + clamp_value(stg4[10] - stg4[14], range), + clamp_value(stg4[11] - stg4[15], range), + ]; + + // stage 6 + let stg6 = [ + stg5[0], + stg5[1], + stg5[2], + stg5[3], + half_btf(COSPI_INV[16], stg5[4], COSPI_INV[48], stg5[5], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[4], -COSPI_INV[16], stg5[5], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg5[6], COSPI_INV[16], stg5[7], INV_COS_BIT), + half_btf(COSPI_INV[16], stg5[6], COSPI_INV[48], stg5[7], INV_COS_BIT), + stg5[8], + stg5[9], + stg5[10], + stg5[11], + half_btf(COSPI_INV[16], stg5[12], COSPI_INV[48], stg5[13], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[12], -COSPI_INV[16], stg5[13], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg5[14], COSPI_INV[16], stg5[15], INV_COS_BIT), + half_btf(COSPI_INV[16], stg5[14], COSPI_INV[48], stg5[15], INV_COS_BIT), + ]; + + // stage 7 + let stg7 = [ + clamp_value(stg6[0] + stg6[2], range), + clamp_value(stg6[1] + stg6[3], range), + clamp_value(stg6[0] - stg6[2], range), + clamp_value(stg6[1] - stg6[3], range), + clamp_value(stg6[4] + stg6[6], range), + clamp_value(stg6[5] + stg6[7], range), + clamp_value(stg6[4] - stg6[6], range), + clamp_value(stg6[5] - stg6[7], range), + clamp_value(stg6[8] + stg6[10], range), + clamp_value(stg6[9] + stg6[11], range), + clamp_value(stg6[8] - stg6[10], range), + clamp_value(stg6[9] - stg6[11], range), + clamp_value(stg6[12] + stg6[14], range), + clamp_value(stg6[13] + stg6[15], range), + clamp_value(stg6[12] - stg6[14], range), + clamp_value(stg6[13] - stg6[15], range), + ]; + + // stage 8 + let stg8 = [ + stg7[0], + stg7[1], + half_btf(COSPI_INV[32], stg7[2], COSPI_INV[32], stg7[3], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[2], -COSPI_INV[32], stg7[3], INV_COS_BIT), + stg7[4], + stg7[5], + half_btf(COSPI_INV[32], stg7[6], COSPI_INV[32], stg7[7], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[6], -COSPI_INV[32], stg7[7], INV_COS_BIT), + stg7[8], + stg7[9], + half_btf(COSPI_INV[32], stg7[10], COSPI_INV[32], stg7[11], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[10], -COSPI_INV[32], stg7[11], INV_COS_BIT), + stg7[12], + stg7[13], + half_btf(COSPI_INV[32], stg7[14], COSPI_INV[32], stg7[15], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[14], -COSPI_INV[32], stg7[15], INV_COS_BIT), + ]; + + // stage 9 + output[0] = stg8[0]; + output[1] = -stg8[8]; + output[2] = stg8[12]; + output[3] = -stg8[4]; + output[4] = stg8[6]; + output[5] = -stg8[14]; + output[6] = stg8[10]; + output[7] = -stg8[2]; + output[8] = stg8[3]; + output[9] = -stg8[11]; + output[10] = stg8[15]; + output[11] = -stg8[7]; + output[12] = stg8[5]; + output[13] = -stg8[13]; + output[14] = stg8[9]; + output[15] = -stg8[1]; +} + +fn av1_iidentity16(input: &[i32], output: &mut [i32], _range: usize) { + output[..16] + .iter_mut() + .zip(input[..16].iter()) + .for_each(|(outp, inp)| *outp = round_shift(SQRT2 * 2 * *inp, 12)); +} + +fn av1_idct32(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 32); + assert!(output.len() >= 32); + + // stage 1; + let stg1 = [ + input[0], input[16], input[8], input[24], input[4], input[20], input[12], + input[28], input[2], input[18], input[10], input[26], input[6], input[22], + input[14], input[30], input[1], input[17], input[9], input[25], input[5], + input[21], input[13], input[29], input[3], input[19], input[11], + input[27], input[7], input[23], input[15], input[31], + ]; + + // stage 2 + let stg2 = [ + stg1[0], + stg1[1], + stg1[2], + stg1[3], + stg1[4], + stg1[5], + stg1[6], + stg1[7], + stg1[8], + stg1[9], + stg1[10], + stg1[11], + stg1[12], + stg1[13], + stg1[14], + stg1[15], + half_btf(COSPI_INV[62], stg1[16], -COSPI_INV[2], stg1[31], INV_COS_BIT), + half_btf(COSPI_INV[30], stg1[17], -COSPI_INV[34], stg1[30], INV_COS_BIT), + half_btf(COSPI_INV[46], stg1[18], -COSPI_INV[18], stg1[29], INV_COS_BIT), + half_btf(COSPI_INV[14], stg1[19], -COSPI_INV[50], stg1[28], INV_COS_BIT), + half_btf(COSPI_INV[54], stg1[20], -COSPI_INV[10], stg1[27], INV_COS_BIT), + half_btf(COSPI_INV[22], stg1[21], -COSPI_INV[42], stg1[26], INV_COS_BIT), + half_btf(COSPI_INV[38], stg1[22], -COSPI_INV[26], stg1[25], INV_COS_BIT), + half_btf(COSPI_INV[6], stg1[23], -COSPI_INV[58], stg1[24], INV_COS_BIT), + half_btf(COSPI_INV[58], stg1[23], COSPI_INV[6], stg1[24], INV_COS_BIT), + half_btf(COSPI_INV[26], stg1[22], COSPI_INV[38], stg1[25], INV_COS_BIT), + half_btf(COSPI_INV[42], stg1[21], COSPI_INV[22], stg1[26], INV_COS_BIT), + half_btf(COSPI_INV[10], stg1[20], COSPI_INV[54], stg1[27], INV_COS_BIT), + half_btf(COSPI_INV[50], stg1[19], COSPI_INV[14], stg1[28], INV_COS_BIT), + half_btf(COSPI_INV[18], stg1[18], COSPI_INV[46], stg1[29], INV_COS_BIT), + half_btf(COSPI_INV[34], stg1[17], COSPI_INV[30], stg1[30], INV_COS_BIT), + half_btf(COSPI_INV[2], stg1[16], COSPI_INV[62], stg1[31], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + stg2[0], + stg2[1], + stg2[2], + stg2[3], + stg2[4], + stg2[5], + stg2[6], + stg2[7], + half_btf(COSPI_INV[60], stg2[8], -COSPI_INV[4], stg2[15], INV_COS_BIT), + half_btf(COSPI_INV[28], stg2[9], -COSPI_INV[36], stg2[14], INV_COS_BIT), + half_btf(COSPI_INV[44], stg2[10], -COSPI_INV[20], stg2[13], INV_COS_BIT), + half_btf(COSPI_INV[12], stg2[11], -COSPI_INV[52], stg2[12], INV_COS_BIT), + half_btf(COSPI_INV[52], stg2[11], COSPI_INV[12], stg2[12], INV_COS_BIT), + half_btf(COSPI_INV[20], stg2[10], COSPI_INV[44], stg2[13], INV_COS_BIT), + half_btf(COSPI_INV[36], stg2[9], COSPI_INV[28], stg2[14], INV_COS_BIT), + half_btf(COSPI_INV[4], stg2[8], COSPI_INV[60], stg2[15], INV_COS_BIT), + clamp_value(stg2[16] + stg2[17], range), + clamp_value(stg2[16] - stg2[17], range), + clamp_value(-stg2[18] + stg2[19], range), + clamp_value(stg2[18] + stg2[19], range), + clamp_value(stg2[20] + stg2[21], range), + clamp_value(stg2[20] - stg2[21], range), + clamp_value(-stg2[22] + stg2[23], range), + clamp_value(stg2[22] + stg2[23], range), + clamp_value(stg2[24] + stg2[25], range), + clamp_value(stg2[24] - stg2[25], range), + clamp_value(-stg2[26] + stg2[27], range), + clamp_value(stg2[26] + stg2[27], range), + clamp_value(stg2[28] + stg2[29], range), + clamp_value(stg2[28] - stg2[29], range), + clamp_value(-stg2[30] + stg2[31], range), + clamp_value(stg2[30] + stg2[31], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + stg3[1], + stg3[2], + stg3[3], + half_btf(COSPI_INV[56], stg3[4], -COSPI_INV[8], stg3[7], INV_COS_BIT), + half_btf(COSPI_INV[24], stg3[5], -COSPI_INV[40], stg3[6], INV_COS_BIT), + half_btf(COSPI_INV[40], stg3[5], COSPI_INV[24], stg3[6], INV_COS_BIT), + half_btf(COSPI_INV[8], stg3[4], COSPI_INV[56], stg3[7], INV_COS_BIT), + clamp_value(stg3[8] + stg3[9], range), + clamp_value(stg3[8] - stg3[9], range), + clamp_value(-stg3[10] + stg3[11], range), + clamp_value(stg3[10] + stg3[11], range), + clamp_value(stg3[12] + stg3[13], range), + clamp_value(stg3[12] - stg3[13], range), + clamp_value(-stg3[14] + stg3[15], range), + clamp_value(stg3[14] + stg3[15], range), + stg3[16], + half_btf(-COSPI_INV[8], stg3[17], COSPI_INV[56], stg3[30], INV_COS_BIT), + half_btf(-COSPI_INV[56], stg3[18], -COSPI_INV[8], stg3[29], INV_COS_BIT), + stg3[19], + stg3[20], + half_btf(-COSPI_INV[40], stg3[21], COSPI_INV[24], stg3[26], INV_COS_BIT), + half_btf(-COSPI_INV[24], stg3[22], -COSPI_INV[40], stg3[25], INV_COS_BIT), + stg3[23], + stg3[24], + half_btf(-COSPI_INV[40], stg3[22], COSPI_INV[24], stg3[25], INV_COS_BIT), + half_btf(COSPI_INV[24], stg3[21], COSPI_INV[40], stg3[26], INV_COS_BIT), + stg3[27], + stg3[28], + half_btf(-COSPI_INV[8], stg3[18], COSPI_INV[56], stg3[29], INV_COS_BIT), + half_btf(COSPI_INV[56], stg3[17], COSPI_INV[8], stg3[30], INV_COS_BIT), + stg3[31], + ]; + + // stage 5 + let stg5 = [ + half_btf(COSPI_INV[32], stg4[0], COSPI_INV[32], stg4[1], INV_COS_BIT), + half_btf(COSPI_INV[32], stg4[0], -COSPI_INV[32], stg4[1], INV_COS_BIT), + half_btf(COSPI_INV[48], stg4[2], -COSPI_INV[16], stg4[3], INV_COS_BIT), + half_btf(COSPI_INV[16], stg4[2], COSPI_INV[48], stg4[3], INV_COS_BIT), + clamp_value(stg4[4] + stg4[5], range), + clamp_value(stg4[4] - stg4[5], range), + clamp_value(-stg4[6] + stg4[7], range), + clamp_value(stg4[6] + stg4[7], range), + stg4[8], + half_btf(-COSPI_INV[16], stg4[9], COSPI_INV[48], stg4[14], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg4[10], -COSPI_INV[16], stg4[13], INV_COS_BIT), + stg4[11], + stg4[12], + half_btf(-COSPI_INV[16], stg4[10], COSPI_INV[48], stg4[13], INV_COS_BIT), + half_btf(COSPI_INV[48], stg4[9], COSPI_INV[16], stg4[14], INV_COS_BIT), + stg4[15], + clamp_value(stg4[16] + stg4[19], range), + clamp_value(stg4[17] + stg4[18], range), + clamp_value(stg4[17] - stg4[18], range), + clamp_value(stg4[16] - stg4[19], range), + clamp_value(-stg4[20] + stg4[23], range), + clamp_value(-stg4[21] + stg4[22], range), + clamp_value(stg4[21] + stg4[22], range), + clamp_value(stg4[20] + stg4[23], range), + clamp_value(stg4[24] + stg4[27], range), + clamp_value(stg4[25] + stg4[26], range), + clamp_value(stg4[25] - stg4[26], range), + clamp_value(stg4[24] - stg4[27], range), + clamp_value(-stg4[28] + stg4[31], range), + clamp_value(-stg4[29] + stg4[30], range), + clamp_value(stg4[29] + stg4[30], range), + clamp_value(stg4[28] + stg4[31], range), + ]; + + // stage 6 + let stg6 = [ + clamp_value(stg5[0] + stg5[3], range), + clamp_value(stg5[1] + stg5[2], range), + clamp_value(stg5[1] - stg5[2], range), + clamp_value(stg5[0] - stg5[3], range), + stg5[4], + half_btf(-COSPI_INV[32], stg5[5], COSPI_INV[32], stg5[6], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[5], COSPI_INV[32], stg5[6], INV_COS_BIT), + stg5[7], + clamp_value(stg5[8] + stg5[11], range), + clamp_value(stg5[9] + stg5[10], range), + clamp_value(stg5[9] - stg5[10], range), + clamp_value(stg5[8] - stg5[11], range), + clamp_value(-stg5[12] + stg5[15], range), + clamp_value(-stg5[13] + stg5[14], range), + clamp_value(stg5[13] + stg5[14], range), + clamp_value(stg5[12] + stg5[15], range), + stg5[16], + stg5[17], + half_btf(-COSPI_INV[16], stg5[18], COSPI_INV[48], stg5[29], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg5[19], COSPI_INV[48], stg5[28], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg5[20], -COSPI_INV[16], stg5[27], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg5[21], -COSPI_INV[16], stg5[26], INV_COS_BIT), + stg5[22], + stg5[23], + stg5[24], + stg5[25], + half_btf(-COSPI_INV[16], stg5[21], COSPI_INV[48], stg5[26], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg5[20], COSPI_INV[48], stg5[27], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[19], COSPI_INV[16], stg5[28], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[18], COSPI_INV[16], stg5[29], INV_COS_BIT), + stg5[30], + stg5[31], + ]; + + // stage 7 + let stg7 = [ + clamp_value(stg6[0] + stg6[7], range), + clamp_value(stg6[1] + stg6[6], range), + clamp_value(stg6[2] + stg6[5], range), + clamp_value(stg6[3] + stg6[4], range), + clamp_value(stg6[3] - stg6[4], range), + clamp_value(stg6[2] - stg6[5], range), + clamp_value(stg6[1] - stg6[6], range), + clamp_value(stg6[0] - stg6[7], range), + stg6[8], + stg6[9], + half_btf(-COSPI_INV[32], stg6[10], COSPI_INV[32], stg6[13], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg6[11], COSPI_INV[32], stg6[12], INV_COS_BIT), + half_btf(COSPI_INV[32], stg6[11], COSPI_INV[32], stg6[12], INV_COS_BIT), + half_btf(COSPI_INV[32], stg6[10], COSPI_INV[32], stg6[13], INV_COS_BIT), + stg6[14], + stg6[15], + clamp_value(stg6[16] + stg6[23], range), + clamp_value(stg6[17] + stg6[22], range), + clamp_value(stg6[18] + stg6[21], range), + clamp_value(stg6[19] + stg6[20], range), + clamp_value(stg6[19] - stg6[20], range), + clamp_value(stg6[18] - stg6[21], range), + clamp_value(stg6[17] - stg6[22], range), + clamp_value(stg6[16] - stg6[23], range), + clamp_value(-stg6[24] + stg6[31], range), + clamp_value(-stg6[25] + stg6[30], range), + clamp_value(-stg6[26] + stg6[29], range), + clamp_value(-stg6[27] + stg6[28], range), + clamp_value(stg6[27] + stg6[28], range), + clamp_value(stg6[26] + stg6[29], range), + clamp_value(stg6[25] + stg6[30], range), + clamp_value(stg6[24] + stg6[31], range), + ]; + + // stage 8 + let stg8 = [ + clamp_value(stg7[0] + stg7[15], range), + clamp_value(stg7[1] + stg7[14], range), + clamp_value(stg7[2] + stg7[13], range), + clamp_value(stg7[3] + stg7[12], range), + clamp_value(stg7[4] + stg7[11], range), + clamp_value(stg7[5] + stg7[10], range), + clamp_value(stg7[6] + stg7[9], range), + clamp_value(stg7[7] + stg7[8], range), + clamp_value(stg7[7] - stg7[8], range), + clamp_value(stg7[6] - stg7[9], range), + clamp_value(stg7[5] - stg7[10], range), + clamp_value(stg7[4] - stg7[11], range), + clamp_value(stg7[3] - stg7[12], range), + clamp_value(stg7[2] - stg7[13], range), + clamp_value(stg7[1] - stg7[14], range), + clamp_value(stg7[0] - stg7[15], range), + stg7[16], + stg7[17], + stg7[18], + stg7[19], + half_btf(-COSPI_INV[32], stg7[20], COSPI_INV[32], stg7[27], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg7[21], COSPI_INV[32], stg7[26], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg7[22], COSPI_INV[32], stg7[25], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg7[23], COSPI_INV[32], stg7[24], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[23], COSPI_INV[32], stg7[24], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[22], COSPI_INV[32], stg7[25], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[21], COSPI_INV[32], stg7[26], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[20], COSPI_INV[32], stg7[27], INV_COS_BIT), + stg7[28], + stg7[29], + stg7[30], + stg7[31], + ]; + + // stage 9 + output[0] = clamp_value(stg8[0] + stg8[31], range); + output[1] = clamp_value(stg8[1] + stg8[30], range); + output[2] = clamp_value(stg8[2] + stg8[29], range); + output[3] = clamp_value(stg8[3] + stg8[28], range); + output[4] = clamp_value(stg8[4] + stg8[27], range); + output[5] = clamp_value(stg8[5] + stg8[26], range); + output[6] = clamp_value(stg8[6] + stg8[25], range); + output[7] = clamp_value(stg8[7] + stg8[24], range); + output[8] = clamp_value(stg8[8] + stg8[23], range); + output[9] = clamp_value(stg8[9] + stg8[22], range); + output[10] = clamp_value(stg8[10] + stg8[21], range); + output[11] = clamp_value(stg8[11] + stg8[20], range); + output[12] = clamp_value(stg8[12] + stg8[19], range); + output[13] = clamp_value(stg8[13] + stg8[18], range); + output[14] = clamp_value(stg8[14] + stg8[17], range); + output[15] = clamp_value(stg8[15] + stg8[16], range); + output[16] = clamp_value(stg8[15] - stg8[16], range); + output[17] = clamp_value(stg8[14] - stg8[17], range); + output[18] = clamp_value(stg8[13] - stg8[18], range); + output[19] = clamp_value(stg8[12] - stg8[19], range); + output[20] = clamp_value(stg8[11] - stg8[20], range); + output[21] = clamp_value(stg8[10] - stg8[21], range); + output[22] = clamp_value(stg8[9] - stg8[22], range); + output[23] = clamp_value(stg8[8] - stg8[23], range); + output[24] = clamp_value(stg8[7] - stg8[24], range); + output[25] = clamp_value(stg8[6] - stg8[25], range); + output[26] = clamp_value(stg8[5] - stg8[26], range); + output[27] = clamp_value(stg8[4] - stg8[27], range); + output[28] = clamp_value(stg8[3] - stg8[28], range); + output[29] = clamp_value(stg8[2] - stg8[29], range); + output[30] = clamp_value(stg8[1] - stg8[30], range); + output[31] = clamp_value(stg8[0] - stg8[31], range); +} + +fn av1_iidentity32(input: &[i32], output: &mut [i32], _range: usize) { + output[..32] + .iter_mut() + .zip(input[..32].iter()) + .for_each(|(outp, inp)| *outp = 4 * *inp); +} + +fn av1_idct64(input: &[i32], output: &mut [i32], range: usize) { + assert!(input.len() >= 64); + assert!(output.len() >= 64); + + // stage 1; + let stg1 = [ + input[0], input[32], input[16], input[48], input[8], input[40], input[24], + input[56], input[4], input[36], input[20], input[52], input[12], + input[44], input[28], input[60], input[2], input[34], input[18], + input[50], input[10], input[42], input[26], input[58], input[6], + input[38], input[22], input[54], input[14], input[46], input[30], + input[62], input[1], input[33], input[17], input[49], input[9], input[41], + input[25], input[57], input[5], input[37], input[21], input[53], + input[13], input[45], input[29], input[61], input[3], input[35], + input[19], input[51], input[11], input[43], input[27], input[59], + input[7], input[39], input[23], input[55], input[15], input[47], + input[31], input[63], + ]; + + // stage 2 + let stg2 = [ + stg1[0], + stg1[1], + stg1[2], + stg1[3], + stg1[4], + stg1[5], + stg1[6], + stg1[7], + stg1[8], + stg1[9], + stg1[10], + stg1[11], + stg1[12], + stg1[13], + stg1[14], + stg1[15], + stg1[16], + stg1[17], + stg1[18], + stg1[19], + stg1[20], + stg1[21], + stg1[22], + stg1[23], + stg1[24], + stg1[25], + stg1[26], + stg1[27], + stg1[28], + stg1[29], + stg1[30], + stg1[31], + half_btf(COSPI_INV[63], stg1[32], -COSPI_INV[1], stg1[63], INV_COS_BIT), + half_btf(COSPI_INV[31], stg1[33], -COSPI_INV[33], stg1[62], INV_COS_BIT), + half_btf(COSPI_INV[47], stg1[34], -COSPI_INV[17], stg1[61], INV_COS_BIT), + half_btf(COSPI_INV[15], stg1[35], -COSPI_INV[49], stg1[60], INV_COS_BIT), + half_btf(COSPI_INV[55], stg1[36], -COSPI_INV[9], stg1[59], INV_COS_BIT), + half_btf(COSPI_INV[23], stg1[37], -COSPI_INV[41], stg1[58], INV_COS_BIT), + half_btf(COSPI_INV[39], stg1[38], -COSPI_INV[25], stg1[57], INV_COS_BIT), + half_btf(COSPI_INV[7], stg1[39], -COSPI_INV[57], stg1[56], INV_COS_BIT), + half_btf(COSPI_INV[59], stg1[40], -COSPI_INV[5], stg1[55], INV_COS_BIT), + half_btf(COSPI_INV[27], stg1[41], -COSPI_INV[37], stg1[54], INV_COS_BIT), + half_btf(COSPI_INV[43], stg1[42], -COSPI_INV[21], stg1[53], INV_COS_BIT), + half_btf(COSPI_INV[11], stg1[43], -COSPI_INV[53], stg1[52], INV_COS_BIT), + half_btf(COSPI_INV[51], stg1[44], -COSPI_INV[13], stg1[51], INV_COS_BIT), + half_btf(COSPI_INV[19], stg1[45], -COSPI_INV[45], stg1[50], INV_COS_BIT), + half_btf(COSPI_INV[35], stg1[46], -COSPI_INV[29], stg1[49], INV_COS_BIT), + half_btf(COSPI_INV[3], stg1[47], -COSPI_INV[61], stg1[48], INV_COS_BIT), + half_btf(COSPI_INV[61], stg1[47], COSPI_INV[3], stg1[48], INV_COS_BIT), + half_btf(COSPI_INV[29], stg1[46], COSPI_INV[35], stg1[49], INV_COS_BIT), + half_btf(COSPI_INV[45], stg1[45], COSPI_INV[19], stg1[50], INV_COS_BIT), + half_btf(COSPI_INV[13], stg1[44], COSPI_INV[51], stg1[51], INV_COS_BIT), + half_btf(COSPI_INV[53], stg1[43], COSPI_INV[11], stg1[52], INV_COS_BIT), + half_btf(COSPI_INV[21], stg1[42], COSPI_INV[43], stg1[53], INV_COS_BIT), + half_btf(COSPI_INV[37], stg1[41], COSPI_INV[27], stg1[54], INV_COS_BIT), + half_btf(COSPI_INV[5], stg1[40], COSPI_INV[59], stg1[55], INV_COS_BIT), + half_btf(COSPI_INV[57], stg1[39], COSPI_INV[7], stg1[56], INV_COS_BIT), + half_btf(COSPI_INV[25], stg1[38], COSPI_INV[39], stg1[57], INV_COS_BIT), + half_btf(COSPI_INV[41], stg1[37], COSPI_INV[23], stg1[58], INV_COS_BIT), + half_btf(COSPI_INV[9], stg1[36], COSPI_INV[55], stg1[59], INV_COS_BIT), + half_btf(COSPI_INV[49], stg1[35], COSPI_INV[15], stg1[60], INV_COS_BIT), + half_btf(COSPI_INV[17], stg1[34], COSPI_INV[47], stg1[61], INV_COS_BIT), + half_btf(COSPI_INV[33], stg1[33], COSPI_INV[31], stg1[62], INV_COS_BIT), + half_btf(COSPI_INV[1], stg1[32], COSPI_INV[63], stg1[63], INV_COS_BIT), + ]; + + // stage 3 + let stg3 = [ + stg2[0], + stg2[1], + stg2[2], + stg2[3], + stg2[4], + stg2[5], + stg2[6], + stg2[7], + stg2[8], + stg2[9], + stg2[10], + stg2[11], + stg2[12], + stg2[13], + stg2[14], + stg2[15], + half_btf(COSPI_INV[62], stg2[16], -COSPI_INV[2], stg2[31], INV_COS_BIT), + half_btf(COSPI_INV[30], stg2[17], -COSPI_INV[34], stg2[30], INV_COS_BIT), + half_btf(COSPI_INV[46], stg2[18], -COSPI_INV[18], stg2[29], INV_COS_BIT), + half_btf(COSPI_INV[14], stg2[19], -COSPI_INV[50], stg2[28], INV_COS_BIT), + half_btf(COSPI_INV[54], stg2[20], -COSPI_INV[10], stg2[27], INV_COS_BIT), + half_btf(COSPI_INV[22], stg2[21], -COSPI_INV[42], stg2[26], INV_COS_BIT), + half_btf(COSPI_INV[38], stg2[22], -COSPI_INV[26], stg2[25], INV_COS_BIT), + half_btf(COSPI_INV[6], stg2[23], -COSPI_INV[58], stg2[24], INV_COS_BIT), + half_btf(COSPI_INV[58], stg2[23], COSPI_INV[6], stg2[24], INV_COS_BIT), + half_btf(COSPI_INV[26], stg2[22], COSPI_INV[38], stg2[25], INV_COS_BIT), + half_btf(COSPI_INV[42], stg2[21], COSPI_INV[22], stg2[26], INV_COS_BIT), + half_btf(COSPI_INV[10], stg2[20], COSPI_INV[54], stg2[27], INV_COS_BIT), + half_btf(COSPI_INV[50], stg2[19], COSPI_INV[14], stg2[28], INV_COS_BIT), + half_btf(COSPI_INV[18], stg2[18], COSPI_INV[46], stg2[29], INV_COS_BIT), + half_btf(COSPI_INV[34], stg2[17], COSPI_INV[30], stg2[30], INV_COS_BIT), + half_btf(COSPI_INV[2], stg2[16], COSPI_INV[62], stg2[31], INV_COS_BIT), + clamp_value(stg2[32] + stg2[33], range), + clamp_value(stg2[32] - stg2[33], range), + clamp_value(-stg2[34] + stg2[35], range), + clamp_value(stg2[34] + stg2[35], range), + clamp_value(stg2[36] + stg2[37], range), + clamp_value(stg2[36] - stg2[37], range), + clamp_value(-stg2[38] + stg2[39], range), + clamp_value(stg2[38] + stg2[39], range), + clamp_value(stg2[40] + stg2[41], range), + clamp_value(stg2[40] - stg2[41], range), + clamp_value(-stg2[42] + stg2[43], range), + clamp_value(stg2[42] + stg2[43], range), + clamp_value(stg2[44] + stg2[45], range), + clamp_value(stg2[44] - stg2[45], range), + clamp_value(-stg2[46] + stg2[47], range), + clamp_value(stg2[46] + stg2[47], range), + clamp_value(stg2[48] + stg2[49], range), + clamp_value(stg2[48] - stg2[49], range), + clamp_value(-stg2[50] + stg2[51], range), + clamp_value(stg2[50] + stg2[51], range), + clamp_value(stg2[52] + stg2[53], range), + clamp_value(stg2[52] - stg2[53], range), + clamp_value(-stg2[54] + stg2[55], range), + clamp_value(stg2[54] + stg2[55], range), + clamp_value(stg2[56] + stg2[57], range), + clamp_value(stg2[56] - stg2[57], range), + clamp_value(-stg2[58] + stg2[59], range), + clamp_value(stg2[58] + stg2[59], range), + clamp_value(stg2[60] + stg2[61], range), + clamp_value(stg2[60] - stg2[61], range), + clamp_value(-stg2[62] + stg2[63], range), + clamp_value(stg2[62] + stg2[63], range), + ]; + + // stage 4 + let stg4 = [ + stg3[0], + stg3[1], + stg3[2], + stg3[3], + stg3[4], + stg3[5], + stg3[6], + stg3[7], + half_btf(COSPI_INV[60], stg3[8], -COSPI_INV[4], stg3[15], INV_COS_BIT), + half_btf(COSPI_INV[28], stg3[9], -COSPI_INV[36], stg3[14], INV_COS_BIT), + half_btf(COSPI_INV[44], stg3[10], -COSPI_INV[20], stg3[13], INV_COS_BIT), + half_btf(COSPI_INV[12], stg3[11], -COSPI_INV[52], stg3[12], INV_COS_BIT), + half_btf(COSPI_INV[52], stg3[11], COSPI_INV[12], stg3[12], INV_COS_BIT), + half_btf(COSPI_INV[20], stg3[10], COSPI_INV[44], stg3[13], INV_COS_BIT), + half_btf(COSPI_INV[36], stg3[9], COSPI_INV[28], stg3[14], INV_COS_BIT), + half_btf(COSPI_INV[4], stg3[8], COSPI_INV[60], stg3[15], INV_COS_BIT), + clamp_value(stg3[16] + stg3[17], range), + clamp_value(stg3[16] - stg3[17], range), + clamp_value(-stg3[18] + stg3[19], range), + clamp_value(stg3[18] + stg3[19], range), + clamp_value(stg3[20] + stg3[21], range), + clamp_value(stg3[20] - stg3[21], range), + clamp_value(-stg3[22] + stg3[23], range), + clamp_value(stg3[22] + stg3[23], range), + clamp_value(stg3[24] + stg3[25], range), + clamp_value(stg3[24] - stg3[25], range), + clamp_value(-stg3[26] + stg3[27], range), + clamp_value(stg3[26] + stg3[27], range), + clamp_value(stg3[28] + stg3[29], range), + clamp_value(stg3[28] - stg3[29], range), + clamp_value(-stg3[30] + stg3[31], range), + clamp_value(stg3[30] + stg3[31], range), + stg3[32], + half_btf(-COSPI_INV[4], stg3[33], COSPI_INV[60], stg3[62], INV_COS_BIT), + half_btf(-COSPI_INV[60], stg3[34], -COSPI_INV[4], stg3[61], INV_COS_BIT), + stg3[35], + stg3[36], + half_btf(-COSPI_INV[36], stg3[37], COSPI_INV[28], stg3[58], INV_COS_BIT), + half_btf(-COSPI_INV[28], stg3[38], -COSPI_INV[36], stg3[57], INV_COS_BIT), + stg3[39], + stg3[40], + half_btf(-COSPI_INV[20], stg3[41], COSPI_INV[44], stg3[54], INV_COS_BIT), + half_btf(-COSPI_INV[44], stg3[42], -COSPI_INV[20], stg3[53], INV_COS_BIT), + stg3[43], + stg3[44], + half_btf(-COSPI_INV[52], stg3[45], COSPI_INV[12], stg3[50], INV_COS_BIT), + half_btf(-COSPI_INV[12], stg3[46], -COSPI_INV[52], stg3[49], INV_COS_BIT), + stg3[47], + stg3[48], + half_btf(-COSPI_INV[52], stg3[46], COSPI_INV[12], stg3[49], INV_COS_BIT), + half_btf(COSPI_INV[12], stg3[45], COSPI_INV[52], stg3[50], INV_COS_BIT), + stg3[51], + stg3[52], + half_btf(-COSPI_INV[20], stg3[42], COSPI_INV[44], stg3[53], INV_COS_BIT), + half_btf(COSPI_INV[44], stg3[41], COSPI_INV[20], stg3[54], INV_COS_BIT), + stg3[55], + stg3[56], + half_btf(-COSPI_INV[36], stg3[38], COSPI_INV[28], stg3[57], INV_COS_BIT), + half_btf(COSPI_INV[28], stg3[37], COSPI_INV[36], stg3[58], INV_COS_BIT), + stg3[59], + stg3[60], + half_btf(-COSPI_INV[4], stg3[34], COSPI_INV[60], stg3[61], INV_COS_BIT), + half_btf(COSPI_INV[60], stg3[33], COSPI_INV[4], stg3[62], INV_COS_BIT), + stg3[63], + ]; + + // stage 5 + let stg5 = [ + stg4[0], + stg4[1], + stg4[2], + stg4[3], + half_btf(COSPI_INV[56], stg4[4], -COSPI_INV[8], stg4[7], INV_COS_BIT), + half_btf(COSPI_INV[24], stg4[5], -COSPI_INV[40], stg4[6], INV_COS_BIT), + half_btf(COSPI_INV[40], stg4[5], COSPI_INV[24], stg4[6], INV_COS_BIT), + half_btf(COSPI_INV[8], stg4[4], COSPI_INV[56], stg4[7], INV_COS_BIT), + clamp_value(stg4[8] + stg4[9], range), + clamp_value(stg4[8] - stg4[9], range), + clamp_value(-stg4[10] + stg4[11], range), + clamp_value(stg4[10] + stg4[11], range), + clamp_value(stg4[12] + stg4[13], range), + clamp_value(stg4[12] - stg4[13], range), + clamp_value(-stg4[14] + stg4[15], range), + clamp_value(stg4[14] + stg4[15], range), + stg4[16], + half_btf(-COSPI_INV[8], stg4[17], COSPI_INV[56], stg4[30], INV_COS_BIT), + half_btf(-COSPI_INV[56], stg4[18], -COSPI_INV[8], stg4[29], INV_COS_BIT), + stg4[19], + stg4[20], + half_btf(-COSPI_INV[40], stg4[21], COSPI_INV[24], stg4[26], INV_COS_BIT), + half_btf(-COSPI_INV[24], stg4[22], -COSPI_INV[40], stg4[25], INV_COS_BIT), + stg4[23], + stg4[24], + half_btf(-COSPI_INV[40], stg4[22], COSPI_INV[24], stg4[25], INV_COS_BIT), + half_btf(COSPI_INV[24], stg4[21], COSPI_INV[40], stg4[26], INV_COS_BIT), + stg4[27], + stg4[28], + half_btf(-COSPI_INV[8], stg4[18], COSPI_INV[56], stg4[29], INV_COS_BIT), + half_btf(COSPI_INV[56], stg4[17], COSPI_INV[8], stg4[30], INV_COS_BIT), + stg4[31], + clamp_value(stg4[32] + stg4[35], range), + clamp_value(stg4[33] + stg4[34], range), + clamp_value(stg4[33] - stg4[34], range), + clamp_value(stg4[32] - stg4[35], range), + clamp_value(-stg4[36] + stg4[39], range), + clamp_value(-stg4[37] + stg4[38], range), + clamp_value(stg4[37] + stg4[38], range), + clamp_value(stg4[36] + stg4[39], range), + clamp_value(stg4[40] + stg4[43], range), + clamp_value(stg4[41] + stg4[42], range), + clamp_value(stg4[41] - stg4[42], range), + clamp_value(stg4[40] - stg4[43], range), + clamp_value(-stg4[44] + stg4[47], range), + clamp_value(-stg4[45] + stg4[46], range), + clamp_value(stg4[45] + stg4[46], range), + clamp_value(stg4[44] + stg4[47], range), + clamp_value(stg4[48] + stg4[51], range), + clamp_value(stg4[49] + stg4[50], range), + clamp_value(stg4[49] - stg4[50], range), + clamp_value(stg4[48] - stg4[51], range), + clamp_value(-stg4[52] + stg4[55], range), + clamp_value(-stg4[53] + stg4[54], range), + clamp_value(stg4[53] + stg4[54], range), + clamp_value(stg4[52] + stg4[55], range), + clamp_value(stg4[56] + stg4[59], range), + clamp_value(stg4[57] + stg4[58], range), + clamp_value(stg4[57] - stg4[58], range), + clamp_value(stg4[56] - stg4[59], range), + clamp_value(-stg4[60] + stg4[63], range), + clamp_value(-stg4[61] + stg4[62], range), + clamp_value(stg4[61] + stg4[62], range), + clamp_value(stg4[60] + stg4[63], range), + ]; + + // stage 6 + let stg6 = [ + half_btf(COSPI_INV[32], stg5[0], COSPI_INV[32], stg5[1], INV_COS_BIT), + half_btf(COSPI_INV[32], stg5[0], -COSPI_INV[32], stg5[1], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[2], -COSPI_INV[16], stg5[3], INV_COS_BIT), + half_btf(COSPI_INV[16], stg5[2], COSPI_INV[48], stg5[3], INV_COS_BIT), + clamp_value(stg5[4] + stg5[5], range), + clamp_value(stg5[4] - stg5[5], range), + clamp_value(-stg5[6] + stg5[7], range), + clamp_value(stg5[6] + stg5[7], range), + stg5[8], + half_btf(-COSPI_INV[16], stg5[9], COSPI_INV[48], stg5[14], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg5[10], -COSPI_INV[16], stg5[13], INV_COS_BIT), + stg5[11], + stg5[12], + half_btf(-COSPI_INV[16], stg5[10], COSPI_INV[48], stg5[13], INV_COS_BIT), + half_btf(COSPI_INV[48], stg5[9], COSPI_INV[16], stg5[14], INV_COS_BIT), + stg5[15], + clamp_value(stg5[16] + stg5[19], range), + clamp_value(stg5[17] + stg5[18], range), + clamp_value(stg5[17] - stg5[18], range), + clamp_value(stg5[16] - stg5[19], range), + clamp_value(-stg5[20] + stg5[23], range), + clamp_value(-stg5[21] + stg5[22], range), + clamp_value(stg5[21] + stg5[22], range), + clamp_value(stg5[20] + stg5[23], range), + clamp_value(stg5[24] + stg5[27], range), + clamp_value(stg5[25] + stg5[26], range), + clamp_value(stg5[25] - stg5[26], range), + clamp_value(stg5[24] - stg5[27], range), + clamp_value(-stg5[28] + stg5[31], range), + clamp_value(-stg5[29] + stg5[30], range), + clamp_value(stg5[29] + stg5[30], range), + clamp_value(stg5[28] + stg5[31], range), + stg5[32], + stg5[33], + half_btf(-COSPI_INV[8], stg5[34], COSPI_INV[56], stg5[61], INV_COS_BIT), + half_btf(-COSPI_INV[8], stg5[35], COSPI_INV[56], stg5[60], INV_COS_BIT), + half_btf(-COSPI_INV[56], stg5[36], -COSPI_INV[8], stg5[59], INV_COS_BIT), + half_btf(-COSPI_INV[56], stg5[37], -COSPI_INV[8], stg5[58], INV_COS_BIT), + stg5[38], + stg5[39], + stg5[40], + stg5[41], + half_btf(-COSPI_INV[40], stg5[42], COSPI_INV[24], stg5[53], INV_COS_BIT), + half_btf(-COSPI_INV[40], stg5[43], COSPI_INV[24], stg5[52], INV_COS_BIT), + half_btf(-COSPI_INV[24], stg5[44], -COSPI_INV[40], stg5[51], INV_COS_BIT), + half_btf(-COSPI_INV[24], stg5[45], -COSPI_INV[40], stg5[50], INV_COS_BIT), + stg5[46], + stg5[47], + stg5[48], + stg5[49], + half_btf(-COSPI_INV[40], stg5[45], COSPI_INV[24], stg5[50], INV_COS_BIT), + half_btf(-COSPI_INV[40], stg5[44], COSPI_INV[24], stg5[51], INV_COS_BIT), + half_btf(COSPI_INV[24], stg5[43], COSPI_INV[40], stg5[52], INV_COS_BIT), + half_btf(COSPI_INV[24], stg5[42], COSPI_INV[40], stg5[53], INV_COS_BIT), + stg5[54], + stg5[55], + stg5[56], + stg5[57], + half_btf(-COSPI_INV[8], stg5[37], COSPI_INV[56], stg5[58], INV_COS_BIT), + half_btf(-COSPI_INV[8], stg5[36], COSPI_INV[56], stg5[59], INV_COS_BIT), + half_btf(COSPI_INV[56], stg5[35], COSPI_INV[8], stg5[60], INV_COS_BIT), + half_btf(COSPI_INV[56], stg5[34], COSPI_INV[8], stg5[61], INV_COS_BIT), + stg5[62], + stg5[63], + ]; + + // stage 7 + let stg7 = [ + clamp_value(stg6[0] + stg6[3], range), + clamp_value(stg6[1] + stg6[2], range), + clamp_value(stg6[1] - stg6[2], range), + clamp_value(stg6[0] - stg6[3], range), + stg6[4], + half_btf(-COSPI_INV[32], stg6[5], COSPI_INV[32], stg6[6], INV_COS_BIT), + half_btf(COSPI_INV[32], stg6[5], COSPI_INV[32], stg6[6], INV_COS_BIT), + stg6[7], + clamp_value(stg6[8] + stg6[11], range), + clamp_value(stg6[9] + stg6[10], range), + clamp_value(stg6[9] - stg6[10], range), + clamp_value(stg6[8] - stg6[11], range), + clamp_value(-stg6[12] + stg6[15], range), + clamp_value(-stg6[13] + stg6[14], range), + clamp_value(stg6[13] + stg6[14], range), + clamp_value(stg6[12] + stg6[15], range), + stg6[16], + stg6[17], + half_btf(-COSPI_INV[16], stg6[18], COSPI_INV[48], stg6[29], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg6[19], COSPI_INV[48], stg6[28], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg6[20], -COSPI_INV[16], stg6[27], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg6[21], -COSPI_INV[16], stg6[26], INV_COS_BIT), + stg6[22], + stg6[23], + stg6[24], + stg6[25], + half_btf(-COSPI_INV[16], stg6[21], COSPI_INV[48], stg6[26], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg6[20], COSPI_INV[48], stg6[27], INV_COS_BIT), + half_btf(COSPI_INV[48], stg6[19], COSPI_INV[16], stg6[28], INV_COS_BIT), + half_btf(COSPI_INV[48], stg6[18], COSPI_INV[16], stg6[29], INV_COS_BIT), + stg6[30], + stg6[31], + clamp_value(stg6[32] + stg6[39], range), + clamp_value(stg6[33] + stg6[38], range), + clamp_value(stg6[34] + stg6[37], range), + clamp_value(stg6[35] + stg6[36], range), + clamp_value(stg6[35] - stg6[36], range), + clamp_value(stg6[34] - stg6[37], range), + clamp_value(stg6[33] - stg6[38], range), + clamp_value(stg6[32] - stg6[39], range), + clamp_value(-stg6[40] + stg6[47], range), + clamp_value(-stg6[41] + stg6[46], range), + clamp_value(-stg6[42] + stg6[45], range), + clamp_value(-stg6[43] + stg6[44], range), + clamp_value(stg6[43] + stg6[44], range), + clamp_value(stg6[42] + stg6[45], range), + clamp_value(stg6[41] + stg6[46], range), + clamp_value(stg6[40] + stg6[47], range), + clamp_value(stg6[48] + stg6[55], range), + clamp_value(stg6[49] + stg6[54], range), + clamp_value(stg6[50] + stg6[53], range), + clamp_value(stg6[51] + stg6[52], range), + clamp_value(stg6[51] - stg6[52], range), + clamp_value(stg6[50] - stg6[53], range), + clamp_value(stg6[49] - stg6[54], range), + clamp_value(stg6[48] - stg6[55], range), + clamp_value(-stg6[56] + stg6[63], range), + clamp_value(-stg6[57] + stg6[62], range), + clamp_value(-stg6[58] + stg6[61], range), + clamp_value(-stg6[59] + stg6[60], range), + clamp_value(stg6[59] + stg6[60], range), + clamp_value(stg6[58] + stg6[61], range), + clamp_value(stg6[57] + stg6[62], range), + clamp_value(stg6[56] + stg6[63], range), + ]; + + // stage 8 + let stg8 = [ + clamp_value(stg7[0] + stg7[7], range), + clamp_value(stg7[1] + stg7[6], range), + clamp_value(stg7[2] + stg7[5], range), + clamp_value(stg7[3] + stg7[4], range), + clamp_value(stg7[3] - stg7[4], range), + clamp_value(stg7[2] - stg7[5], range), + clamp_value(stg7[1] - stg7[6], range), + clamp_value(stg7[0] - stg7[7], range), + stg7[8], + stg7[9], + half_btf(-COSPI_INV[32], stg7[10], COSPI_INV[32], stg7[13], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg7[11], COSPI_INV[32], stg7[12], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[11], COSPI_INV[32], stg7[12], INV_COS_BIT), + half_btf(COSPI_INV[32], stg7[10], COSPI_INV[32], stg7[13], INV_COS_BIT), + stg7[14], + stg7[15], + clamp_value(stg7[16] + stg7[23], range), + clamp_value(stg7[17] + stg7[22], range), + clamp_value(stg7[18] + stg7[21], range), + clamp_value(stg7[19] + stg7[20], range), + clamp_value(stg7[19] - stg7[20], range), + clamp_value(stg7[18] - stg7[21], range), + clamp_value(stg7[17] - stg7[22], range), + clamp_value(stg7[16] - stg7[23], range), + clamp_value(-stg7[24] + stg7[31], range), + clamp_value(-stg7[25] + stg7[30], range), + clamp_value(-stg7[26] + stg7[29], range), + clamp_value(-stg7[27] + stg7[28], range), + clamp_value(stg7[27] + stg7[28], range), + clamp_value(stg7[26] + stg7[29], range), + clamp_value(stg7[25] + stg7[30], range), + clamp_value(stg7[24] + stg7[31], range), + stg7[32], + stg7[33], + stg7[34], + stg7[35], + half_btf(-COSPI_INV[16], stg7[36], COSPI_INV[48], stg7[59], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[37], COSPI_INV[48], stg7[58], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[38], COSPI_INV[48], stg7[57], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[39], COSPI_INV[48], stg7[56], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg7[40], -COSPI_INV[16], stg7[55], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg7[41], -COSPI_INV[16], stg7[54], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg7[42], -COSPI_INV[16], stg7[53], INV_COS_BIT), + half_btf(-COSPI_INV[48], stg7[43], -COSPI_INV[16], stg7[52], INV_COS_BIT), + stg7[44], + stg7[45], + stg7[46], + stg7[47], + stg7[48], + stg7[49], + stg7[50], + stg7[51], + half_btf(-COSPI_INV[16], stg7[43], COSPI_INV[48], stg7[52], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[42], COSPI_INV[48], stg7[53], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[41], COSPI_INV[48], stg7[54], INV_COS_BIT), + half_btf(-COSPI_INV[16], stg7[40], COSPI_INV[48], stg7[55], INV_COS_BIT), + half_btf(COSPI_INV[48], stg7[39], COSPI_INV[16], stg7[56], INV_COS_BIT), + half_btf(COSPI_INV[48], stg7[38], COSPI_INV[16], stg7[57], INV_COS_BIT), + half_btf(COSPI_INV[48], stg7[37], COSPI_INV[16], stg7[58], INV_COS_BIT), + half_btf(COSPI_INV[48], stg7[36], COSPI_INV[16], stg7[59], INV_COS_BIT), + stg7[60], + stg7[61], + stg7[62], + stg7[63], + ]; + + // stage 9 + let stg9 = [ + clamp_value(stg8[0] + stg8[15], range), + clamp_value(stg8[1] + stg8[14], range), + clamp_value(stg8[2] + stg8[13], range), + clamp_value(stg8[3] + stg8[12], range), + clamp_value(stg8[4] + stg8[11], range), + clamp_value(stg8[5] + stg8[10], range), + clamp_value(stg8[6] + stg8[9], range), + clamp_value(stg8[7] + stg8[8], range), + clamp_value(stg8[7] - stg8[8], range), + clamp_value(stg8[6] - stg8[9], range), + clamp_value(stg8[5] - stg8[10], range), + clamp_value(stg8[4] - stg8[11], range), + clamp_value(stg8[3] - stg8[12], range), + clamp_value(stg8[2] - stg8[13], range), + clamp_value(stg8[1] - stg8[14], range), + clamp_value(stg8[0] - stg8[15], range), + stg8[16], + stg8[17], + stg8[18], + stg8[19], + half_btf(-COSPI_INV[32], stg8[20], COSPI_INV[32], stg8[27], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg8[21], COSPI_INV[32], stg8[26], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg8[22], COSPI_INV[32], stg8[25], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg8[23], COSPI_INV[32], stg8[24], INV_COS_BIT), + half_btf(COSPI_INV[32], stg8[23], COSPI_INV[32], stg8[24], INV_COS_BIT), + half_btf(COSPI_INV[32], stg8[22], COSPI_INV[32], stg8[25], INV_COS_BIT), + half_btf(COSPI_INV[32], stg8[21], COSPI_INV[32], stg8[26], INV_COS_BIT), + half_btf(COSPI_INV[32], stg8[20], COSPI_INV[32], stg8[27], INV_COS_BIT), + stg8[28], + stg8[29], + stg8[30], + stg8[31], + clamp_value(stg8[32] + stg8[47], range), + clamp_value(stg8[33] + stg8[46], range), + clamp_value(stg8[34] + stg8[45], range), + clamp_value(stg8[35] + stg8[44], range), + clamp_value(stg8[36] + stg8[43], range), + clamp_value(stg8[37] + stg8[42], range), + clamp_value(stg8[38] + stg8[41], range), + clamp_value(stg8[39] + stg8[40], range), + clamp_value(stg8[39] - stg8[40], range), + clamp_value(stg8[38] - stg8[41], range), + clamp_value(stg8[37] - stg8[42], range), + clamp_value(stg8[36] - stg8[43], range), + clamp_value(stg8[35] - stg8[44], range), + clamp_value(stg8[34] - stg8[45], range), + clamp_value(stg8[33] - stg8[46], range), + clamp_value(stg8[32] - stg8[47], range), + clamp_value(-stg8[48] + stg8[63], range), + clamp_value(-stg8[49] + stg8[62], range), + clamp_value(-stg8[50] + stg8[61], range), + clamp_value(-stg8[51] + stg8[60], range), + clamp_value(-stg8[52] + stg8[59], range), + clamp_value(-stg8[53] + stg8[58], range), + clamp_value(-stg8[54] + stg8[57], range), + clamp_value(-stg8[55] + stg8[56], range), + clamp_value(stg8[55] + stg8[56], range), + clamp_value(stg8[54] + stg8[57], range), + clamp_value(stg8[53] + stg8[58], range), + clamp_value(stg8[52] + stg8[59], range), + clamp_value(stg8[51] + stg8[60], range), + clamp_value(stg8[50] + stg8[61], range), + clamp_value(stg8[49] + stg8[62], range), + clamp_value(stg8[48] + stg8[63], range), + ]; + + // stage 10 + let stg10 = [ + clamp_value(stg9[0] + stg9[31], range), + clamp_value(stg9[1] + stg9[30], range), + clamp_value(stg9[2] + stg9[29], range), + clamp_value(stg9[3] + stg9[28], range), + clamp_value(stg9[4] + stg9[27], range), + clamp_value(stg9[5] + stg9[26], range), + clamp_value(stg9[6] + stg9[25], range), + clamp_value(stg9[7] + stg9[24], range), + clamp_value(stg9[8] + stg9[23], range), + clamp_value(stg9[9] + stg9[22], range), + clamp_value(stg9[10] + stg9[21], range), + clamp_value(stg9[11] + stg9[20], range), + clamp_value(stg9[12] + stg9[19], range), + clamp_value(stg9[13] + stg9[18], range), + clamp_value(stg9[14] + stg9[17], range), + clamp_value(stg9[15] + stg9[16], range), + clamp_value(stg9[15] - stg9[16], range), + clamp_value(stg9[14] - stg9[17], range), + clamp_value(stg9[13] - stg9[18], range), + clamp_value(stg9[12] - stg9[19], range), + clamp_value(stg9[11] - stg9[20], range), + clamp_value(stg9[10] - stg9[21], range), + clamp_value(stg9[9] - stg9[22], range), + clamp_value(stg9[8] - stg9[23], range), + clamp_value(stg9[7] - stg9[24], range), + clamp_value(stg9[6] - stg9[25], range), + clamp_value(stg9[5] - stg9[26], range), + clamp_value(stg9[4] - stg9[27], range), + clamp_value(stg9[3] - stg9[28], range), + clamp_value(stg9[2] - stg9[29], range), + clamp_value(stg9[1] - stg9[30], range), + clamp_value(stg9[0] - stg9[31], range), + stg9[32], + stg9[33], + stg9[34], + stg9[35], + stg9[36], + stg9[37], + stg9[38], + stg9[39], + half_btf(-COSPI_INV[32], stg9[40], COSPI_INV[32], stg9[55], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[41], COSPI_INV[32], stg9[54], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[42], COSPI_INV[32], stg9[53], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[43], COSPI_INV[32], stg9[52], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[44], COSPI_INV[32], stg9[51], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[45], COSPI_INV[32], stg9[50], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[46], COSPI_INV[32], stg9[49], INV_COS_BIT), + half_btf(-COSPI_INV[32], stg9[47], COSPI_INV[32], stg9[48], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[47], COSPI_INV[32], stg9[48], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[46], COSPI_INV[32], stg9[49], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[45], COSPI_INV[32], stg9[50], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[44], COSPI_INV[32], stg9[51], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[43], COSPI_INV[32], stg9[52], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[42], COSPI_INV[32], stg9[53], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[41], COSPI_INV[32], stg9[54], INV_COS_BIT), + half_btf(COSPI_INV[32], stg9[40], COSPI_INV[32], stg9[55], INV_COS_BIT), + stg9[56], + stg9[57], + stg9[58], + stg9[59], + stg9[60], + stg9[61], + stg9[62], + stg9[63], + ]; + + // stage 11 + output[0] = clamp_value(stg10[0] + stg10[63], range); + output[1] = clamp_value(stg10[1] + stg10[62], range); + output[2] = clamp_value(stg10[2] + stg10[61], range); + output[3] = clamp_value(stg10[3] + stg10[60], range); + output[4] = clamp_value(stg10[4] + stg10[59], range); + output[5] = clamp_value(stg10[5] + stg10[58], range); + output[6] = clamp_value(stg10[6] + stg10[57], range); + output[7] = clamp_value(stg10[7] + stg10[56], range); + output[8] = clamp_value(stg10[8] + stg10[55], range); + output[9] = clamp_value(stg10[9] + stg10[54], range); + output[10] = clamp_value(stg10[10] + stg10[53], range); + output[11] = clamp_value(stg10[11] + stg10[52], range); + output[12] = clamp_value(stg10[12] + stg10[51], range); + output[13] = clamp_value(stg10[13] + stg10[50], range); + output[14] = clamp_value(stg10[14] + stg10[49], range); + output[15] = clamp_value(stg10[15] + stg10[48], range); + output[16] = clamp_value(stg10[16] + stg10[47], range); + output[17] = clamp_value(stg10[17] + stg10[46], range); + output[18] = clamp_value(stg10[18] + stg10[45], range); + output[19] = clamp_value(stg10[19] + stg10[44], range); + output[20] = clamp_value(stg10[20] + stg10[43], range); + output[21] = clamp_value(stg10[21] + stg10[42], range); + output[22] = clamp_value(stg10[22] + stg10[41], range); + output[23] = clamp_value(stg10[23] + stg10[40], range); + output[24] = clamp_value(stg10[24] + stg10[39], range); + output[25] = clamp_value(stg10[25] + stg10[38], range); + output[26] = clamp_value(stg10[26] + stg10[37], range); + output[27] = clamp_value(stg10[27] + stg10[36], range); + output[28] = clamp_value(stg10[28] + stg10[35], range); + output[29] = clamp_value(stg10[29] + stg10[34], range); + output[30] = clamp_value(stg10[30] + stg10[33], range); + output[31] = clamp_value(stg10[31] + stg10[32], range); + output[32] = clamp_value(stg10[31] - stg10[32], range); + output[33] = clamp_value(stg10[30] - stg10[33], range); + output[34] = clamp_value(stg10[29] - stg10[34], range); + output[35] = clamp_value(stg10[28] - stg10[35], range); + output[36] = clamp_value(stg10[27] - stg10[36], range); + output[37] = clamp_value(stg10[26] - stg10[37], range); + output[38] = clamp_value(stg10[25] - stg10[38], range); + output[39] = clamp_value(stg10[24] - stg10[39], range); + output[40] = clamp_value(stg10[23] - stg10[40], range); + output[41] = clamp_value(stg10[22] - stg10[41], range); + output[42] = clamp_value(stg10[21] - stg10[42], range); + output[43] = clamp_value(stg10[20] - stg10[43], range); + output[44] = clamp_value(stg10[19] - stg10[44], range); + output[45] = clamp_value(stg10[18] - stg10[45], range); + output[46] = clamp_value(stg10[17] - stg10[46], range); + output[47] = clamp_value(stg10[16] - stg10[47], range); + output[48] = clamp_value(stg10[15] - stg10[48], range); + output[49] = clamp_value(stg10[14] - stg10[49], range); + output[50] = clamp_value(stg10[13] - stg10[50], range); + output[51] = clamp_value(stg10[12] - stg10[51], range); + output[52] = clamp_value(stg10[11] - stg10[52], range); + output[53] = clamp_value(stg10[10] - stg10[53], range); + output[54] = clamp_value(stg10[9] - stg10[54], range); + output[55] = clamp_value(stg10[8] - stg10[55], range); + output[56] = clamp_value(stg10[7] - stg10[56], range); + output[57] = clamp_value(stg10[6] - stg10[57], range); + output[58] = clamp_value(stg10[5] - stg10[58], range); + output[59] = clamp_value(stg10[4] - stg10[59], range); + output[60] = clamp_value(stg10[3] - stg10[60], range); + output[61] = clamp_value(stg10[2] - stg10[61], range); + output[62] = clamp_value(stg10[1] - stg10[62], range); + output[63] = clamp_value(stg10[0] - stg10[63], range); +} + +type InvTxfmFn = fn(input: &[i32], output: &mut [i32], range: usize); + +static INV_TXFM_FNS: [[InvTxfmFn; 5]; 5] = [ + [av1_idct4, av1_idct8, av1_idct16, av1_idct32, av1_idct64], + [ + av1_iadst4, + av1_iadst8, + av1_iadst16, + |_, _, _| unimplemented!(), + |_, _, _| unimplemented!(), + ], + [ + av1_iflipadst4, + av1_iflipadst8, + av1_iflipadst16, + |_, _, _| unimplemented!(), + |_, _, _| unimplemented!(), + ], + [ + av1_iidentity4, + av1_iidentity8, + av1_iidentity16, + av1_iidentity32, + |_, _, _| unimplemented!(), + ], + [ + av1_iwht4, + |_, _, _| unimplemented!(), + |_, _, _| unimplemented!(), + |_, _, _| unimplemented!(), + |_, _, _| unimplemented!(), + ], +]; + +pub(crate) mod rust { + use super::*; + use crate::cpu_features::CpuFeatureLevel; + + use simd_helpers::cold_for_target_arch; + use std::cmp; + + #[cold_for_target_arch("x86_64", "aarch64")] + pub fn inverse_transform_add( + input: &[T::Coeff], output: &mut PlaneRegionMut<'_, T>, _eob: u16, + tx_size: TxSize, tx_type: TxType, bd: usize, _cpu: CpuFeatureLevel, + ) { + let width: usize = tx_size.width(); + let height: usize = tx_size.height(); + + // Only use at most 32 columns and 32 rows of input coefficients. + let input: &[T::Coeff] = &input[..width.min(32) * height.min(32)]; + + // For 64 point transforms, rely on the last 32 columns being initialized + // to zero for filling out missing input coeffs. + let mut buffer = vec![0i32; width * height].into_boxed_slice(); + let rect_type = tx_size.rect_ratio_log2(); + let tx_types_1d = get_1d_tx_types(tx_type); + let lossless = tx_type == TxType::WHT_WHT; + + // perform inv txfm on every row + let range = bd + 8; + let txfm_fn = + INV_TXFM_FNS[tx_types_1d.1 as usize][tx_size.width_log2() - 2]; + // 64 point transforms only signal 32 coeffs. We only take chunks of 32 + // and skip over the last 32 transforms here. + for (r, buffer_slice) in (0..height.min(32)).zip(buffer.chunks_mut(width)) + { + // For 64 point transforms, rely on the last 32 elements being + // initialized to zero for filling out the missing coeffs. + let mut temp_in: [i32; 64] = [0; 64]; + for (raw, clamped) in input[r..] + .iter() + .map(|a| i32::cast_from(*a)) + .step_by(height.min(32)) + .zip(temp_in.iter_mut()) + { + let val = if rect_type.abs() == 1 { + round_shift(raw * INV_SQRT2, SQRT2_BITS) + } else if lossless { + raw >> 2 + } else { + raw + }; + *clamped = clamp_value(val, range); + } + txfm_fn(&temp_in, buffer_slice, range); + } + + // perform inv txfm on every col + let range = cmp::max(bd + 6, 16); + let txfm_fn = + INV_TXFM_FNS[tx_types_1d.0 as usize][tx_size.height_log2() - 2]; + for c in 0..width { + let mut temp_in: [i32; 64] = [0; 64]; + let mut temp_out: [i32; 64] = [0; 64]; + for (raw, clamped) in + buffer[c..].iter().step_by(width).zip(temp_in.iter_mut()) + { + *clamped = clamp_value( + round_shift(*raw, INV_INTERMEDIATE_SHIFTS[tx_size as usize]), + range, + ); + } + txfm_fn(&temp_in, &mut temp_out, range); + for (temp, out) in temp_out + .iter() + .zip(output.rows_iter_mut().map(|row| &mut row[c]).take(height)) + { + let v: i32 = (*out).as_(); + let r = if lossless { *temp } else { round_shift(*temp, 4) }; + let v = clamp(v + r, 0, (1 << bd) - 1); + *out = T::cast_from(v); + } + } + } + + /* From AV1 Spec. + https://aomediacodec.github.io/av1-spec/#2d-inverse-transform-process + */ + const INV_INTERMEDIATE_SHIFTS: [usize; TxSize::TX_SIZES_ALL] = + [0, 1, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2]; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/transform/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/transform/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,619 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +#[macro_use] +pub mod forward_shared; + +pub use self::forward::forward_transform; +pub use self::inverse::inverse_transform_add; + +use crate::context::MI_SIZE_LOG2; +use crate::partition::{BlockSize, BlockSize::*}; +use crate::util::*; + +use TxSize::*; + +pub mod forward; +pub mod inverse; + +pub static RAV1E_TX_TYPES: &[TxType] = &[ + TxType::DCT_DCT, + TxType::ADST_DCT, + TxType::DCT_ADST, + TxType::ADST_ADST, + // TODO: Add a speed setting for FLIPADST + // TxType::FLIPADST_DCT, + // TxType::DCT_FLIPADST, + // TxType::FLIPADST_FLIPADST, + // TxType::ADST_FLIPADST, + // TxType::FLIPADST_ADST, + TxType::IDTX, + TxType::V_DCT, + TxType::H_DCT, + //TxType::V_FLIPADST, + //TxType::H_FLIPADST, +]; + +pub mod consts { + pub static SQRT2_BITS: usize = 12; + pub static SQRT2: i32 = 5793; // 2^12 * sqrt(2) + pub static INV_SQRT2: i32 = 2896; // 2^12 / sqrt(2) +} + +pub const TX_TYPES: usize = 16; +pub const TX_TYPES_PLUS_LL: usize = 17; + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] +pub enum TxType { + DCT_DCT = 0, // DCT in both horizontal and vertical + ADST_DCT = 1, // ADST in vertical, DCT in horizontal + DCT_ADST = 2, // DCT in vertical, ADST in horizontal + ADST_ADST = 3, // ADST in both directions + FLIPADST_DCT = 4, + DCT_FLIPADST = 5, + FLIPADST_FLIPADST = 6, + ADST_FLIPADST = 7, + FLIPADST_ADST = 8, + IDTX = 9, + V_DCT = 10, + H_DCT = 11, + V_ADST = 12, + H_ADST = 13, + V_FLIPADST = 14, + H_FLIPADST = 15, + WHT_WHT = 16, +} + +impl TxType { + /// Compute transform type for inter chroma. + /// + /// + #[inline] + pub fn uv_inter(self, uv_tx_size: TxSize) -> Self { + use TxType::*; + if uv_tx_size.sqr_up() == TX_32X32 { + match self { + IDTX => IDTX, + _ => DCT_DCT, + } + } else if uv_tx_size.sqr() == TX_16X16 { + match self { + V_ADST | H_ADST | V_FLIPADST | H_FLIPADST => DCT_DCT, + _ => self, + } + } else { + self + } + } +} + +/// Transform Size +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)] +pub enum TxSize { + TX_4X4, + TX_8X8, + TX_16X16, + TX_32X32, + TX_64X64, + + TX_4X8, + TX_8X4, + TX_8X16, + TX_16X8, + TX_16X32, + TX_32X16, + TX_32X64, + TX_64X32, + + TX_4X16, + TX_16X4, + TX_8X32, + TX_32X8, + TX_16X64, + TX_64X16, +} + +impl TxSize { + /// Number of square transform sizes + pub const TX_SIZES: usize = 5; + + /// Number of transform sizes (including non-square sizes) + pub const TX_SIZES_ALL: usize = 14 + 5; + + #[inline] + pub const fn width(self) -> usize { + 1 << self.width_log2() + } + + #[inline] + pub const fn width_log2(self) -> usize { + match self { + TX_4X4 | TX_4X8 | TX_4X16 => 2, + TX_8X8 | TX_8X4 | TX_8X16 | TX_8X32 => 3, + TX_16X16 | TX_16X8 | TX_16X32 | TX_16X4 | TX_16X64 => 4, + TX_32X32 | TX_32X16 | TX_32X64 | TX_32X8 => 5, + TX_64X64 | TX_64X32 | TX_64X16 => 6, + } + } + + #[inline] + pub const fn width_index(self) -> usize { + self.width_log2() - TX_4X4.width_log2() + } + + #[inline] + pub const fn height(self) -> usize { + 1 << self.height_log2() + } + + #[inline] + pub const fn height_log2(self) -> usize { + match self { + TX_4X4 | TX_8X4 | TX_16X4 => 2, + TX_8X8 | TX_4X8 | TX_16X8 | TX_32X8 => 3, + TX_16X16 | TX_8X16 | TX_32X16 | TX_4X16 | TX_64X16 => 4, + TX_32X32 | TX_16X32 | TX_64X32 | TX_8X32 => 5, + TX_64X64 | TX_32X64 | TX_16X64 => 6, + } + } + + #[inline] + pub const fn height_index(self) -> usize { + self.height_log2() - TX_4X4.height_log2() + } + + #[inline] + pub const fn width_mi(self) -> usize { + self.width() >> MI_SIZE_LOG2 + } + + #[inline] + pub const fn area(self) -> usize { + 1 << self.area_log2() + } + + #[inline] + pub const fn area_log2(self) -> usize { + self.width_log2() + self.height_log2() + } + + #[inline] + pub const fn height_mi(self) -> usize { + self.height() >> MI_SIZE_LOG2 + } + + #[inline] + pub const fn block_size(self) -> BlockSize { + match self { + TX_4X4 => BLOCK_4X4, + TX_8X8 => BLOCK_8X8, + TX_16X16 => BLOCK_16X16, + TX_32X32 => BLOCK_32X32, + TX_64X64 => BLOCK_64X64, + TX_4X8 => BLOCK_4X8, + TX_8X4 => BLOCK_8X4, + TX_8X16 => BLOCK_8X16, + TX_16X8 => BLOCK_16X8, + TX_16X32 => BLOCK_16X32, + TX_32X16 => BLOCK_32X16, + TX_32X64 => BLOCK_32X64, + TX_64X32 => BLOCK_64X32, + TX_4X16 => BLOCK_4X16, + TX_16X4 => BLOCK_16X4, + TX_8X32 => BLOCK_8X32, + TX_32X8 => BLOCK_32X8, + TX_16X64 => BLOCK_16X64, + TX_64X16 => BLOCK_64X16, + } + } + + #[inline] + pub const fn sqr(self) -> TxSize { + match self { + TX_4X4 | TX_4X8 | TX_8X4 | TX_4X16 | TX_16X4 => TX_4X4, + TX_8X8 | TX_8X16 | TX_16X8 | TX_8X32 | TX_32X8 => TX_8X8, + TX_16X16 | TX_16X32 | TX_32X16 | TX_16X64 | TX_64X16 => TX_16X16, + TX_32X32 | TX_32X64 | TX_64X32 => TX_32X32, + TX_64X64 => TX_64X64, + } + } + + #[inline] + pub const fn sqr_up(self) -> TxSize { + match self { + TX_4X4 => TX_4X4, + TX_8X8 | TX_4X8 | TX_8X4 => TX_8X8, + TX_16X16 | TX_8X16 | TX_16X8 | TX_4X16 | TX_16X4 => TX_16X16, + TX_32X32 | TX_16X32 | TX_32X16 | TX_8X32 | TX_32X8 => TX_32X32, + TX_64X64 | TX_32X64 | TX_64X32 | TX_16X64 | TX_64X16 => TX_64X64, + } + } + + #[inline] + pub fn by_dims(w: usize, h: usize) -> TxSize { + match (w, h) { + (4, 4) => TX_4X4, + (8, 8) => TX_8X8, + (16, 16) => TX_16X16, + (32, 32) => TX_32X32, + (64, 64) => TX_64X64, + (4, 8) => TX_4X8, + (8, 4) => TX_8X4, + (8, 16) => TX_8X16, + (16, 8) => TX_16X8, + (16, 32) => TX_16X32, + (32, 16) => TX_32X16, + (32, 64) => TX_32X64, + (64, 32) => TX_64X32, + (4, 16) => TX_4X16, + (16, 4) => TX_16X4, + (8, 32) => TX_8X32, + (32, 8) => TX_32X8, + (16, 64) => TX_16X64, + (64, 16) => TX_64X16, + _ => unreachable!(), + } + } + + #[inline] + pub const fn is_rect(self) -> bool { + self.width_log2() != self.height_log2() + } + + /// Returns log2(width / height), e.g. `TX_16x4` -> log2(16 / 4) = 2 + #[inline] + pub const fn rect_ratio_log2(self) -> i8 { + self.width_log2() as i8 - self.height_log2() as i8 + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd)] +pub enum TxSet { + // DCT only + TX_SET_DCTONLY, + // DCT + Identity only + TX_SET_INTER_3, // TX_SET_DCT_IDTX + // Discrete Trig transforms w/o flip (4) + Identity (1) + TX_SET_INTRA_2, // TX_SET_DTT4_IDTX + // Discrete Trig transforms w/o flip (4) + Identity (1) + 1D Hor/vert DCT (2) + TX_SET_INTRA_1, // TX_SET_DTT4_IDTX_1DDCT + // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver DCT (2) + TX_SET_INTER_2, // TX_SET_DTT9_IDTX_1DDCT + // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver (6) + TX_SET_INTER_1, // TX_SET_ALL16 +} + +// performs half a butterfly +#[inline] +const fn half_btf(w0: i32, in0: i32, w1: i32, in1: i32, bit: usize) -> i32 { + // Ensure defined behaviour for when w0*in0 + w1*in1 is negative and + // overflows, but w0*in0 + w1*in1 + rounding isn't. + let result = (w0 * in0).wrapping_add(w1 * in1); + // Implement a version of round_shift with wrapping + if bit == 0 { + result + } else { + result.wrapping_add(1 << (bit - 1)) >> bit + } +} + +// clamps value to a signed integer type of bit bits +#[inline] +fn clamp_value(value: i32, bit: usize) -> i32 { + let max_value: i32 = ((1i64 << (bit - 1)) - 1) as i32; + let min_value: i32 = (-(1i64 << (bit - 1))) as i32; + clamp(value, min_value, max_value) +} + +pub fn av1_round_shift_array(arr: &mut [i32], size: usize, bit: i8) { + if bit == 0 { + return; + } + if bit > 0 { + let bit = bit as usize; + arr.iter_mut().take(size).for_each(|i| { + *i = round_shift(*i, bit); + }) + } else { + arr.iter_mut().take(size).for_each(|i| { + *i <<= -bit; + }) + } +} + +#[derive(Debug, Clone, Copy)] +enum TxType1D { + DCT, + ADST, + FLIPADST, + IDTX, + WHT, +} + +const fn get_1d_tx_types(tx_type: TxType) -> (TxType1D, TxType1D) { + match tx_type { + TxType::DCT_DCT => (TxType1D::DCT, TxType1D::DCT), + TxType::ADST_DCT => (TxType1D::ADST, TxType1D::DCT), + TxType::DCT_ADST => (TxType1D::DCT, TxType1D::ADST), + TxType::ADST_ADST => (TxType1D::ADST, TxType1D::ADST), + TxType::FLIPADST_DCT => (TxType1D::FLIPADST, TxType1D::DCT), + TxType::DCT_FLIPADST => (TxType1D::DCT, TxType1D::FLIPADST), + TxType::FLIPADST_FLIPADST => (TxType1D::FLIPADST, TxType1D::FLIPADST), + TxType::ADST_FLIPADST => (TxType1D::ADST, TxType1D::FLIPADST), + TxType::FLIPADST_ADST => (TxType1D::FLIPADST, TxType1D::ADST), + TxType::IDTX => (TxType1D::IDTX, TxType1D::IDTX), + TxType::V_DCT => (TxType1D::DCT, TxType1D::IDTX), + TxType::H_DCT => (TxType1D::IDTX, TxType1D::DCT), + TxType::V_ADST => (TxType1D::ADST, TxType1D::IDTX), + TxType::H_ADST => (TxType1D::IDTX, TxType1D::ADST), + TxType::V_FLIPADST => (TxType1D::FLIPADST, TxType1D::IDTX), + TxType::H_FLIPADST => (TxType1D::IDTX, TxType1D::FLIPADST), + TxType::WHT_WHT => (TxType1D::WHT, TxType1D::WHT), + } +} + +const VTX_TAB: [TxType1D; TX_TYPES_PLUS_LL] = [ + TxType1D::DCT, + TxType1D::ADST, + TxType1D::DCT, + TxType1D::ADST, + TxType1D::FLIPADST, + TxType1D::DCT, + TxType1D::FLIPADST, + TxType1D::ADST, + TxType1D::FLIPADST, + TxType1D::IDTX, + TxType1D::DCT, + TxType1D::IDTX, + TxType1D::ADST, + TxType1D::IDTX, + TxType1D::FLIPADST, + TxType1D::IDTX, + TxType1D::WHT, +]; + +const HTX_TAB: [TxType1D; TX_TYPES_PLUS_LL] = [ + TxType1D::DCT, + TxType1D::DCT, + TxType1D::ADST, + TxType1D::ADST, + TxType1D::DCT, + TxType1D::FLIPADST, + TxType1D::FLIPADST, + TxType1D::FLIPADST, + TxType1D::ADST, + TxType1D::IDTX, + TxType1D::IDTX, + TxType1D::DCT, + TxType1D::IDTX, + TxType1D::ADST, + TxType1D::IDTX, + TxType1D::FLIPADST, + TxType1D::WHT, +]; + +#[inline] +pub const fn valid_av1_transform(tx_size: TxSize, tx_type: TxType) -> bool { + let size_sq = tx_size.sqr_up(); + use TxSize::*; + use TxType::*; + match (size_sq, tx_type) { + (TX_64X64, DCT_DCT) => true, + (TX_64X64, _) => false, + (TX_32X32, DCT_DCT) => true, + (TX_32X32, IDTX) => true, + (TX_32X32, _) => false, + (_, _) => true, + } +} + +#[cfg(any(test, feature = "bench"))] +pub fn get_valid_txfm_types(tx_size: TxSize) -> &'static [TxType] { + let size_sq = tx_size.sqr_up(); + use TxType::*; + if size_sq == TxSize::TX_64X64 { + &[DCT_DCT] + } else if size_sq == TxSize::TX_32X32 { + &[DCT_DCT, IDTX] + } else if size_sq == TxSize::TX_4X4 { + &[ + DCT_DCT, + ADST_DCT, + DCT_ADST, + ADST_ADST, + FLIPADST_DCT, + DCT_FLIPADST, + FLIPADST_FLIPADST, + ADST_FLIPADST, + FLIPADST_ADST, + IDTX, + V_DCT, + H_DCT, + V_ADST, + H_ADST, + V_FLIPADST, + H_FLIPADST, + WHT_WHT, + ] + } else { + &[ + DCT_DCT, + ADST_DCT, + DCT_ADST, + ADST_ADST, + FLIPADST_DCT, + DCT_FLIPADST, + FLIPADST_FLIPADST, + ADST_FLIPADST, + FLIPADST_ADST, + IDTX, + V_DCT, + H_DCT, + V_ADST, + H_ADST, + V_FLIPADST, + H_FLIPADST, + ] + } +} + +#[cfg(test)] +mod test { + use super::TxType::*; + use super::*; + use crate::context::av1_get_coded_tx_size; + use crate::cpu_features::CpuFeatureLevel; + use crate::frame::*; + use rand::random; + use std::mem::MaybeUninit; + + fn test_roundtrip( + tx_size: TxSize, tx_type: TxType, tolerance: i16, + ) { + let cpu = CpuFeatureLevel::default(); + + let coeff_area: usize = av1_get_coded_tx_size(tx_size).area(); + let mut src_storage = [T::cast_from(0); 64 * 64]; + let src = &mut src_storage[..tx_size.area()]; + let mut dst = Plane::from_slice( + &[T::zero(); 64 * 64][..tx_size.area()], + tx_size.width(), + ); + let mut res_storage = [0i16; 64 * 64]; + let res = &mut res_storage[..tx_size.area()]; + let mut freq_storage = [MaybeUninit::uninit(); 64 * 64]; + let freq = &mut freq_storage[..tx_size.area()]; + for ((r, s), d) in + res.iter_mut().zip(src.iter_mut()).zip(dst.data.iter_mut()) + { + *s = T::cast_from(random::()); + *d = T::cast_from(random::()); + *r = i16::cast_from(*s) - i16::cast_from(*d); + } + forward_transform(res, freq, tx_size.width(), tx_size, tx_type, 8, cpu); + // SAFETY: forward_transform initialized freq + let freq = unsafe { slice_assume_init_mut(freq) }; + inverse_transform_add( + freq, + &mut dst.as_region_mut(), + coeff_area.try_into().unwrap(), + tx_size, + tx_type, + 8, + cpu, + ); + + for (s, d) in src.iter().zip(dst.data.iter()) { + assert!(i16::abs(i16::cast_from(*s) - i16::cast_from(*d)) <= tolerance); + } + } + + #[test] + fn log_tx_ratios() { + let combinations = [ + (TxSize::TX_4X4, 0), + (TxSize::TX_8X8, 0), + (TxSize::TX_16X16, 0), + (TxSize::TX_32X32, 0), + (TxSize::TX_64X64, 0), + (TxSize::TX_4X8, -1), + (TxSize::TX_8X4, 1), + (TxSize::TX_8X16, -1), + (TxSize::TX_16X8, 1), + (TxSize::TX_16X32, -1), + (TxSize::TX_32X16, 1), + (TxSize::TX_32X64, -1), + (TxSize::TX_64X32, 1), + (TxSize::TX_4X16, -2), + (TxSize::TX_16X4, 2), + (TxSize::TX_8X32, -2), + (TxSize::TX_32X8, 2), + (TxSize::TX_16X64, -2), + (TxSize::TX_64X16, 2), + ]; + + for &(tx_size, expected) in combinations.iter() { + println!( + "Testing combination {:?}, {:?}", + tx_size.width(), + tx_size.height() + ); + assert!(tx_size.rect_ratio_log2() == expected); + } + } + + fn roundtrips() { + let combinations = [ + (TX_4X4, WHT_WHT, 0), + (TX_4X4, DCT_DCT, 0), + (TX_4X4, ADST_DCT, 0), + (TX_4X4, DCT_ADST, 0), + (TX_4X4, ADST_ADST, 0), + (TX_4X4, FLIPADST_DCT, 0), + (TX_4X4, DCT_FLIPADST, 0), + (TX_4X4, IDTX, 0), + (TX_4X4, V_DCT, 0), + (TX_4X4, H_DCT, 0), + (TX_4X4, V_ADST, 0), + (TX_4X4, H_ADST, 0), + (TX_8X8, DCT_DCT, 1), + (TX_8X8, ADST_DCT, 1), + (TX_8X8, DCT_ADST, 1), + (TX_8X8, ADST_ADST, 1), + (TX_8X8, FLIPADST_DCT, 1), + (TX_8X8, DCT_FLIPADST, 1), + (TX_8X8, IDTX, 0), + (TX_8X8, V_DCT, 0), + (TX_8X8, H_DCT, 0), + (TX_8X8, V_ADST, 0), + (TX_8X8, H_ADST, 1), + (TX_16X16, DCT_DCT, 1), + (TX_16X16, ADST_DCT, 1), + (TX_16X16, DCT_ADST, 1), + (TX_16X16, ADST_ADST, 1), + (TX_16X16, FLIPADST_DCT, 1), + (TX_16X16, DCT_FLIPADST, 1), + (TX_16X16, IDTX, 0), + (TX_16X16, V_DCT, 1), + (TX_16X16, H_DCT, 1), + // 32x transforms only use DCT_DCT and IDTX + (TX_32X32, DCT_DCT, 2), + (TX_32X32, IDTX, 0), + // 64x transforms only use DCT_DCT and IDTX + //(TX_64X64, DCT_DCT, 0), + (TX_4X8, DCT_DCT, 1), + (TX_8X4, DCT_DCT, 1), + (TX_4X16, DCT_DCT, 1), + (TX_16X4, DCT_DCT, 1), + (TX_8X16, DCT_DCT, 1), + (TX_16X8, DCT_DCT, 1), + (TX_8X32, DCT_DCT, 2), + (TX_32X8, DCT_DCT, 2), + (TX_16X32, DCT_DCT, 2), + (TX_32X16, DCT_DCT, 2), + ]; + for &(tx_size, tx_type, tolerance) in combinations.iter() { + println!("Testing combination {:?}, {:?}", tx_size, tx_type); + test_roundtrip::(tx_size, tx_type, tolerance); + } + } + + #[test] + fn roundtrips_u8() { + roundtrips::(); + } + + #[test] + fn roundtrips_u16() { + roundtrips::(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/align.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/align.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/align.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/align.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,77 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::mem::MaybeUninit; + +#[repr(align(64))] +pub struct Align64; + +// A 64 byte aligned piece of data. +// # Examples +// ``` +// let mut x: Aligned<[i16; 64 * 64]> = Aligned::new([0; 64 * 64]); +// assert!(x.data.as_ptr() as usize % 16 == 0); +// +// let mut x: Aligned<[i16; 64 * 64]> = Aligned::uninitialized(); +// assert!(x.data.as_ptr() as usize % 16 == 0); +// ``` +pub struct Aligned { + _alignment: [Align64; 0], + pub data: T, +} + +#[cfg(any(test, feature = "bench"))] +impl Aligned<[T; N]> { + #[inline(always)] + pub fn from_fn(cb: F) -> Self + where + F: FnMut(usize) -> T, + { + Aligned { _alignment: [], data: std::array::from_fn(cb) } + } +} + +impl Aligned<[MaybeUninit; N]> { + #[inline(always)] + pub const fn uninit_array() -> Self { + Aligned { + _alignment: [], + // SAFETY: Uninitialized [MaybeUninit; N] is valid. + data: unsafe { MaybeUninit::uninit().assume_init() }, + } + } +} + +impl Aligned { + pub const fn new(data: T) -> Self { + Aligned { _alignment: [], data } + } + #[allow(clippy::uninit_assumed_init)] + /// # Safety + /// + /// The resulting `Aligned` *must* be written to before it is read from. + pub const unsafe fn uninitialized() -> Self { + Self::new(MaybeUninit::uninit().assume_init()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn is_aligned(ptr: *const T, n: usize) -> bool { + ((ptr as usize) & ((1 << n) - 1)) == 0 + } + + #[test] + fn sanity_stack() { + let a: Aligned<_> = Aligned::new([0u8; 3]); + assert!(is_aligned(a.data.as_ptr(), 4)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/cdf.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/cdf.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/cdf.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/cdf.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,136 @@ +// Copyright (c) 2017-2021, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub const fn cdf( + vars: [u16; VARS], +) -> [u16; CDF_LEN] { + // Ensure that at least one zero is kept at the end + assert!(CDF_LEN > VARS); + + let mut out = [0; CDF_LEN]; + let mut i = 0; + while i < vars.len() { + assert!(vars[i] <= 32768); + out[i] = 32768 - vars[i]; + i += 1; + } + + out +} + +pub const fn cdf_2d< + const VARS: usize, + const CDF_LEN: usize, + const N_2D: usize, +>( + vars: [[u16; VARS]; N_2D], +) -> [[u16; CDF_LEN]; N_2D] { + let mut out = [[0u16; CDF_LEN]; N_2D]; + let mut c = 0; + while c < vars.len() { + out[c] = cdf(vars[c]); + c += 1; + } + + out +} + +pub const fn cdf_3d< + const VARS: usize, + const CDF_LEN: usize, + const N_2D: usize, + const N_3D: usize, +>( + vars: [[[u16; VARS]; N_2D]; N_3D], +) -> [[[u16; CDF_LEN]; N_2D]; N_3D] { + let mut out = [[[0u16; CDF_LEN]; N_2D]; N_3D]; + let mut c = 0; + while c < vars.len() { + out[c] = cdf_2d(vars[c]); + c += 1; + } + + out +} + +pub const fn cdf_4d< + const VARS: usize, + const CDF_LEN: usize, + const N_2D: usize, + const N_3D: usize, + const N_4D: usize, +>( + vars: [[[[u16; VARS]; N_2D]; N_3D]; N_4D], +) -> [[[[u16; CDF_LEN]; N_2D]; N_3D]; N_4D] { + let mut out = [[[[0u16; CDF_LEN]; N_2D]; N_3D]; N_4D]; + let mut c = 0; + while c < vars.len() { + out[c] = cdf_3d(vars[c]); + c += 1; + } + + out +} + +pub const fn cdf_5d< + const VARS: usize, + const CDF_LEN: usize, + const N_2D: usize, + const N_3D: usize, + const N_4D: usize, + const N_5D: usize, +>( + vars: [[[[[u16; VARS]; N_2D]; N_3D]; N_4D]; N_5D], +) -> [[[[[u16; CDF_LEN]; N_2D]; N_3D]; N_4D]; N_5D] { + let mut out = [[[[[0u16; CDF_LEN]; N_2D]; N_3D]; N_4D]; N_5D]; + let mut c = 0; + while c < vars.len() { + out[c] = cdf_4d(vars[c]); + c += 1; + } + + out +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn cdf_len_ok() { + let _: [u16; 5] = cdf([]); + let _: [u16; 5] = cdf([1]); + let _: [u16; 5] = cdf([1, 2, 3, 4]); + } + + #[test] + #[should_panic] + fn cdf_len_panics() { + let _: [u16; 5] = cdf([1, 2, 3, 4, 5]); + } + + #[test] + #[should_panic] + fn cdf_val_panics() { + let _: [u16; 5] = cdf([40000]); + } + + #[test] + fn cdf_vals_ok() { + let cdf: [u16; 5] = cdf([2000, 10000, 32768, 0]); + assert_eq!(cdf, [30768, 22768, 0, 32768, 0]); + } + + #[test] + fn cdf_5d_ok() { + let cdf: [[[[[u16; 4]; 2]; 1]; 1]; 1] = + cdf_5d([[[[[1000, 2000], [3000, 4000]]]]]); + assert_eq!(cdf, [[[[[31768, 30768, 0, 0], [29768, 28768, 0, 0],]]]]) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/kmeans.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/kmeans.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/kmeans.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/kmeans.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,123 @@ +// Copyright (c) 2022-2023, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +/// Find k-means for a sorted slice of integers that can be summed in `i64`. +pub fn kmeans(data: &[T]) -> [T; K] +where + T: Copy, + T: Into, + T: PartialEq, + T: PartialOrd, + i64: TryInto, + >::Error: std::fmt::Debug, +{ + let mut low = [0; K]; + for (i, val) in low.iter_mut().enumerate() { + *val = (i * (data.len() - 1)) / (K - 1); + } + let mut means = low.map(|i| unsafe { *data.get_unchecked(i) }); + let mut high = low; + let mut sum = [0i64; K]; + high[K - 1] = data.len(); + sum[K - 1] = means[K - 1].into(); + + // Constrain complexity to O(n log n) + let limit = 2 * (usize::BITS - data.len().leading_zeros()); + for _ in 0..limit { + for (i, (threshold, (low, high))) in (means.iter().skip(1).zip(&means)) + .map(|(&c1, &c2)| unsafe { + ((c1.into() + c2.into() + 1) >> 1).try_into().unwrap_unchecked() + }) + .zip(low.iter_mut().skip(1).zip(&mut high)) + .enumerate() + { + unsafe { + scan(high, low, sum.get_unchecked_mut(i..=i + 1), data, threshold); + } + } + let mut changed = false; + for (((m, sum), high), low) in + means.iter_mut().zip(&sum).zip(&high).zip(&low) + { + let count = (high - low) as i64; + if count == 0 { + continue; + } + let new_mean = unsafe { + ((sum + (count >> 1)).saturating_div(count)) + .try_into() + .unwrap_unchecked() + }; + changed |= *m != new_mean; + *m = new_mean; + } + if !changed { + break; + } + } + + means +} + +#[inline(never)] +unsafe fn scan( + high: &mut usize, low: &mut usize, sum: &mut [i64], data: &[T], t: T, +) where + T: Copy, + T: Into, + T: PartialEq, + T: PartialOrd, +{ + let mut n = *high; + let mut s = *sum.get_unchecked(0); + for &d in data.get_unchecked(..n).iter().rev().take_while(|&d| *d > t) { + s -= d.into(); + n -= 1; + } + for &d in data.get_unchecked(n..).iter().take_while(|&d| *d <= t) { + s += d.into(); + n += 1; + } + *high = n; + *sum.get_unchecked_mut(0) = s; + + let mut n = *low; + let mut s = *sum.get_unchecked(1); + for &d in data.get_unchecked(n..).iter().take_while(|&d| *d < t) { + s -= d.into(); + n += 1; + } + for &d in data.get_unchecked(..n).iter().rev().take_while(|&d| *d >= t) { + s += d.into(); + n -= 1; + } + *low = n; + *sum.get_unchecked_mut(1) = s; +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn three_means() { + let mut data = [1, 2, 3, 10, 11, 12, 20, 21, 22]; + data.sort_unstable(); + let centroids = kmeans(&data); + assert_eq!(centroids, [2, 11, 21]); + } + + #[test] + fn four_means() { + let mut data = [30, 31, 32, 1, 2, 3, 10, 11, 12, 20, 21, 22]; + data.sort_unstable(); + let centroids = kmeans(&data); + assert_eq!(centroids, [2, 11, 21, 31]); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/logexp.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/logexp.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/logexp.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/logexp.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,360 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +/// Convert an integer into a Q57 fixed-point fraction. +pub const fn q57(v: i32) -> i64 { + debug_assert!(v >= -64 && v <= 63); + (v as i64) << 57 +} + +#[rustfmt::skip] +const ATANH_LOG2: &[i64; 32] = &[ + 0x32B803473F7AD0F4, 0x2F2A71BD4E25E916, 0x2E68B244BB93BA06, + 0x2E39FB9198CE62E4, 0x2E2E683F68565C8F, 0x2E2B850BE2077FC1, + 0x2E2ACC58FE7B78DB, 0x2E2A9E2DE52FD5F2, 0x2E2A92A338D53EEC, + 0x2E2A8FC08F5E19B6, 0x2E2A8F07E51A485E, 0x2E2A8ED9BA8AF388, + 0x2E2A8ECE2FE7384A, 0x2E2A8ECB4D3E4B1A, 0x2E2A8ECA94940FE8, + 0x2E2A8ECA6669811D, 0x2E2A8ECA5ADEDD6A, 0x2E2A8ECA57FC347E, + 0x2E2A8ECA57438A43, 0x2E2A8ECA57155FB4, 0x2E2A8ECA5709D510, + 0x2E2A8ECA5706F267, 0x2E2A8ECA570639BD, 0x2E2A8ECA57060B92, + 0x2E2A8ECA57060008, 0x2E2A8ECA5705FD25, 0x2E2A8ECA5705FC6C, + 0x2E2A8ECA5705FC3E, 0x2E2A8ECA5705FC33, 0x2E2A8ECA5705FC30, + 0x2E2A8ECA5705FC2F, 0x2E2A8ECA5705FC2F +]; + +/// Computes the binary exponential of `logq57`. +/// `logq57`: a log base 2 in Q57 format. +/// Returns a 64 bit integer in Q0 (no fraction). +pub const fn bexp64(logq57: i64) -> i64 { + let ipart = (logq57 >> 57) as i32; + if ipart < 0 { + return 0; + } + if ipart >= 63 { + return 0x7FFFFFFFFFFFFFFF; + } + // z is the fractional part of the log in Q62 format. + // We need 1 bit of headroom since the magnitude can get larger than 1 + // during the iteration, and a sign bit. + let mut z = logq57 - q57(ipart); + let mut w: i64; + if z != 0 { + // Rust has 128 bit multiplies, so it should be possible to do this + // faster without losing accuracy. + z <<= 5; + // w is the exponential in Q61 format (since it also needs headroom and can + // get as large as 2.0); we could get another bit if we dropped the sign, + // but we'll recover that bit later anyway. + // Ideally this should start out as + // \lim_{n->\infty} 2^{61}/\product_{i=1}^n \sqrt{1-2^{-2i}} + // but in order to guarantee convergence we have to repeat iterations 4, + // 13 (=3*4+1), and 40 (=3*13+1, etc.), so it winds up somewhat larger. + w = 0x26A3D0E401DD846D; + let mut i: i64 = 0; + loop { + let mask = -((z < 0) as i64); + w += ((w >> (i + 1)) + mask) ^ mask; + z -= (ATANH_LOG2[i as usize] + mask) ^ mask; + // Repeat iteration 4. + if i >= 3 { + break; + } + z *= 2; + i += 1; + } + loop { + let mask = -((z < 0) as i64); + w += ((w >> (i + 1)) + mask) ^ mask; + z -= (ATANH_LOG2[i as usize] + mask) ^ mask; + // Repeat iteration 13. + if i >= 12 { + break; + } + z *= 2; + i += 1; + } + while i < 32 { + let mask = -((z < 0) as i64); + w += ((w >> (i + 1)) + mask) ^ mask; + z = (z - ((ATANH_LOG2[i as usize] + mask) ^ mask)) * 2; + i += 1; + } + // Skip the remaining iterations unless we really require that much + // precision. + // We could have bailed out earlier for smaller iparts, but that would + // require initializing w from a table, as the limit doesn't converge to + // 61-bit precision until n=30. + let mut wlo: i32 = 0; + if ipart > 30 { + // For these iterations, we just update the low bits, as the high bits + // can't possibly be affected. + // OD_ATANH_LOG2 has also converged (it actually did so one iteration + // earlier, but that's no reason for an extra special case). + loop { + let mask = -((z < 0) as i64); + wlo += (((w >> i) + mask) ^ mask) as i32; + z -= (ATANH_LOG2[31] + mask) ^ mask; + // Repeat iteration 40. + if i >= 39 { + break; + } + z *= 2; + i += 1; + } + while i < 61 { + let mask = -((z < 0) as i64); + wlo += (((w >> i) + mask) ^ mask) as i32; + z = (z - ((ATANH_LOG2[31] + mask) ^ mask)) * 2; + i += 1; + } + } + w = (w << 1) + (wlo as i64); + } else { + w = 1i64 << 62; + } + if ipart < 62 { + w = ((w >> (61 - ipart)) + 1) >> 1; + } + w +} + +/// Computes the binary log of `n`. +/// `n`: a 64-bit integer in Q0 (no fraction). +/// Returns a 64-bit log in Q57. +pub const fn blog64(n: i64) -> i64 { + if n <= 0 { + return -1; + } + let ipart = 63 - n.leading_zeros() as i32; + let w = if ipart > 61 { n >> (ipart - 61) } else { n << (61 - ipart) }; + if (w & (w - 1)) == 0 { + return q57(ipart); + } + // z is the fractional part of the log in Q61 format. + let mut z: i64 = 0; + // Rust has 128 bit multiplies, so it should be possible to do this + // faster without losing accuracy. + // x and y are the cosh() and sinh(), respectively, in Q61 format. + // We are computing z = 2*atanh(y/x) = 2*atanh((w - 1)/(w + 1)). + let mut x = w + (1i64 << 61); + let mut y = w - (1i64 << 61); + // Repeat iteration 4. + // Repeat iteration 13. + // Repeat iteration 40. + let bounds = [3, 12, 39, 61]; + let mut i = 0; + let mut j = 0; + loop { + let end = bounds[j]; + loop { + let mask = -((y < 0) as i64); + // ATANH_LOG2 has converged at iteration 32. + z += ((ATANH_LOG2[if i < 31 { i } else { 31 }] >> i) + mask) ^ mask; + let u = x >> (i + 1); + x -= ((y >> (i + 1)) + mask) ^ mask; + y -= (u + mask) ^ mask; + if i == end { + break; + } + i += 1; + } + j += 1; + if j == bounds.len() { + break; + } + } + z = (z + 8) >> 4; + q57(ipart) + z +} + +/// Computes the binary log of `n`. +/// `n`: an unsigned 32-bit integer in Q0 (no fraction). +/// Returns a signed 32-bit log in Q24. +#[allow(unused)] +pub const fn blog32(n: u32) -> i32 { + if n == 0 { + return -1; + } + let ipart = 31 - n.leading_zeros() as i32; + let n = n as i64; + let w = if ipart > 61 { n >> (ipart - 61) } else { n << (61 - ipart) }; + if (w & (w - 1)) == 0 { + return ipart << 24; + } + // z is the fractional part of the log in Q61 format. + let mut z: i64 = 0; + // Rust has 128 bit multiplies, so it should be possible to do this + // faster without losing accuracy. + // x and y are the cosh() and sinh(), respectively, in Q61 format. + // We are computing z = 2*atanh(y/x) = 2*atanh((w - 1)/(w + 1)). + let mut x = w + (1i64 << 61); + let mut y = w - (1i64 << 61); + // Repeat iteration 4. + // Repeat iteration 13. + let bounds = [3, 12, 29]; + let mut i = 0; + let mut j = 0; + loop { + let end = bounds[j]; + loop { + let mask = -((y < 0) as i64); + z += ((ATANH_LOG2[i] >> i) + mask) ^ mask; + let u = x >> (i + 1); + x -= ((y >> (i + 1)) + mask) ^ mask; + y -= (u + mask) ^ mask; + if i == end { + break; + } + i += 1; + } + j += 1; + if j == bounds.len() { + break; + } + } + const SHIFT: usize = 61 - 24; + z = (z + (1 << SHIFT >> 1)) >> SHIFT; + (ipart << 24) + z as i32 +} + +/// Converts a Q57 fixed-point fraction to Q24 by rounding. +pub const fn q57_to_q24(v: i64) -> i32 { + (((v >> 32) + 1) >> 1) as i32 +} + +/// Converts a Q24 fixed-point fraction to Q57. +pub const fn q24_to_q57(v: i32) -> i64 { + (v as i64) << 33 +} + +/// Binary exponentiation of a `log_scale` with 24-bit fractional precision and +/// saturation. +/// `log_scale`: A binary logarithm in Q24 format. +/// Returns the binary exponential in Q24 format, saturated to 2**47 - 1 if +/// `log_scale` was too large. +pub const fn bexp_q24(log_scale: i32) -> i64 { + if log_scale < 23 << 24 { + let ret = bexp64(((log_scale as i64) << 33) + q57(24)); + if ret < (1i64 << 47) - 1 { + return ret; + } + } + (1i64 << 47) - 1 +} + +/// Polynomial approximation of a binary exponential. +/// Q10 input, Q0 output. +#[allow(unused)] +pub const fn bexp32_q10(z: i32) -> u32 { + let ipart = z >> 10; + let mut n = ((z & ((1 << 10) - 1)) << 4) as u32; + n = ({ + n * (((n * (((n * (((n * 3548) >> 15) + 6817)) >> 15) + 15823)) >> 15) + + 22708) + } >> 15) + + 16384; + if 14 - ipart > 0 { + (n + (1 << (13 - ipart))) >> (14 - ipart) + } else { + n << (ipart - 14) + } +} + +/// Polynomial approximation of a binary logarithm. +/// Q0 input, Q11 output. +pub const fn blog32_q11(w: u32) -> i32 { + if w == 0 { + return -1; + } + let ipart = 32 - w.leading_zeros() as i32; + let n = if ipart - 16 > 0 { w >> (ipart - 16) } else { w << (16 - ipart) } + as i32 + - 32768 + - 16384; + let fpart = ({ + n * (((n * (((n * (((n * -1402) >> 15) + 2546)) >> 15) - 5216)) >> 15) + + 15745) + } >> 15) + - 6797; + (ipart << 11) + (fpart >> 3) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn blog64_vectors() { + assert!(blog64(1793) == 0x159dc71e24d32daf); + assert!(blog64(0x678dde6e5fd29f05) == 0x7d6373ad151ca685); + } + + #[test] + fn bexp64_vectors() { + assert!(bexp64(0x159dc71e24d32daf) == 1793); + assert!((bexp64(0x7d6373ad151ca685) - 0x678dde6e5fd29f05).abs() < 29); + } + + #[test] + fn blog64_bexp64_round_trip() { + for a in 1..=std::u16::MAX as i64 { + let b = std::i64::MAX / a; + let (log_a, log_b, log_ab) = (blog64(a), blog64(b), blog64(a * b)); + assert!((log_a + log_b - log_ab).abs() < 4); + assert!(bexp64(log_a) == a); + assert!((bexp64(log_b) - b).abs() < 128); + assert!((bexp64(log_ab) - a * b).abs() < 128); + } + } + + #[test] + fn blog32_vectors() { + assert_eq!(blog32(0), -1); + assert_eq!(blog32(1793), q57_to_q24(0x159dc71e24d32daf)); + } + + #[test] + fn bexp_q24_vectors() { + assert_eq!(bexp_q24(i32::MAX), (1i64 << 47) - 1); + assert_eq!( + (bexp_q24(q57_to_q24(0x159dc71e24d32daf)) + (1 << 24 >> 1)) >> 24, + 1793 + ); + } + + #[test] + fn blog32_bexp_q24_round_trip() { + for a in 1..=std::u16::MAX as u32 { + let b = (std::u32::MAX >> 9) / a; + let (log_a, log_b, log_ab) = (blog32(a), blog32(b), blog32(a * b)); + assert!((log_a + log_b - log_ab).abs() < 4); + assert!((bexp_q24(log_a) - (i64::from(a) << 24)).abs() < (1 << 24 >> 1)); + assert!(((bexp_q24(log_b) >> 24) - i64::from(b)).abs() < 128); + assert!( + ((bexp_q24(log_ab) >> 24) - i64::from(a) * i64::from(b)).abs() < 128 + ); + } + } + + #[test] + fn blog32_q11_bexp32_q10_round_trip() { + for a in 1..=std::i16::MAX as i32 { + let b = std::i16::MAX as i32 / a; + let (log_a, log_b, log_ab) = ( + blog32_q11(a as u32), + blog32_q11(b as u32), + blog32_q11(a as u32 * b as u32), + ); + assert!((log_a + log_b - log_ab).abs() < 4); + assert!((bexp32_q10((log_a + 1) >> 1) as i32 - a).abs() < 18); + assert!((bexp32_q10((log_b + 1) >> 1) as i32 - b).abs() < 2); + assert!((bexp32_q10((log_ab + 1) >> 1) as i32 - a * b).abs() < 18); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +mod align; +mod cdf; +mod kmeans; +mod logexp; +mod uninit; + +pub use v_frame::math::*; +pub use v_frame::pixel::*; + +pub use align::*; +pub use cdf::*; +pub use uninit::*; + +pub use kmeans::*; +pub(crate) use logexp::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/pixel.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/pixel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/pixel.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/pixel.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2017-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +pub use v_frame::pixel::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/uninit.rs clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/uninit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/util/uninit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/util/uninit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::mem::MaybeUninit; + +pub fn init_slice_repeat_mut( + slice: &'_ mut [MaybeUninit], value: T, +) -> &'_ mut [T] { + // Fill all of slice + for a in slice.iter_mut() { + *a = MaybeUninit::new(value); + } + + // SAFETY: Defined behavior, since all elements of slice are initialized + unsafe { slice_assume_init_mut(slice) } +} + +/// Assume all the elements are initialized. +#[inline(always)] +pub unsafe fn slice_assume_init_mut( + slice: &'_ mut [MaybeUninit], +) -> &'_ mut [T] { + &mut *(slice as *mut [MaybeUninit] as *mut [T]) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,877 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA + +%macro DIR_TABLE 1 ; stride + db 1 * %1 + 0, 2 * %1 + 0 + db 1 * %1 + 0, 2 * %1 - 2 + db -1 * %1 + 2, -2 * %1 + 4 + db 0 * %1 + 2, -1 * %1 + 4 + db 0 * %1 + 2, 0 * %1 + 4 + db 0 * %1 + 2, 1 * %1 + 4 + db 1 * %1 + 2, 2 * %1 + 4 + db 1 * %1 + 0, 2 * %1 + 2 + db 1 * %1 + 0, 2 * %1 + 0 + db 1 * %1 + 0, 2 * %1 - 2 + db -1 * %1 + 2, -2 * %1 + 4 + db 0 * %1 + 2, -1 * %1 + 4 +%endmacro + +dir_table4: DIR_TABLE 16 +dir_table8: DIR_TABLE 32 +pri_taps: dw 4, 4, 3, 3, 2, 2, 3, 3 + +dir_shift: times 2 dw 0x4000 + times 2 dw 0x1000 + +pw_2048: times 2 dw 2048 +pw_m16384: times 2 dw -16384 + +cextern cdef_dir_8bpc_avx2.main + +SECTION .text + +%macro CDEF_FILTER 2 ; w, h + DEFINE_ARGS dst, stride, _, dir, pridmp, pri, sec, tmp + movifnidn prid, r5m + movifnidn secd, r6m + mov dird, r7m + vpbroadcastd m8, [base+pw_2048] + lea dirq, [base+dir_table%1+dirq*2] + test prid, prid + jz .sec_only +%if WIN64 + vpbroadcastw m6, prim + movaps [rsp+16*0], xmm9 + movaps [rsp+16*1], xmm10 +%else + movd xm6, prid + vpbroadcastw m6, xm6 +%endif + lzcnt pridmpd, prid + rorx tmpd, prid, 2 + cmp dword r10m, 0xfff ; if (bpc == 12) + cmove prid, tmpd ; pri >>= 2 + mov tmpd, r8m ; damping + and prid, 4 + sub tmpd, 31 + vpbroadcastd m9, [base+pri_taps+priq+8*0] + vpbroadcastd m10, [base+pri_taps+priq+8*1] + test secd, secd + jz .pri_only +%if WIN64 + movaps r8m, xmm13 + vpbroadcastw m13, secm + movaps r4m, xmm11 + movaps r6m, xmm12 +%else + movd xm0, secd + vpbroadcastw m13, xm0 +%endif + lzcnt secd, secd + xor prid, prid + add pridmpd, tmpd + cmovs pridmpd, prid + add secd, tmpd + lea tmpq, [px] + mov [pri_shift], pridmpq + mov [sec_shift], secq +%rep %1*%2/16 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).pri_sec +%endrep +%if WIN64 + movaps xmm11, r4m + movaps xmm12, r6m + movaps xmm13, r8m +%endif + jmp .pri_end +.pri_only: + add pridmpd, tmpd + cmovs pridmpd, secd + lea tmpq, [px] + mov [pri_shift], pridmpq +%rep %1*%2/16 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).pri +%endrep +.pri_end: +%if WIN64 + movaps xmm9, [rsp+16*0] + movaps xmm10, [rsp+16*1] +%endif +.end: + RET +.sec_only: + mov tmpd, r8m ; damping +%if WIN64 + vpbroadcastw m6, secm +%else + movd xm6, secd + vpbroadcastw m6, xm6 +%endif + tzcnt secd, secd + sub tmpd, secd + mov [sec_shift], tmpq + lea tmpq, [px] +%rep %1*%2/16 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).sec +%endrep + jmp .end +%if %1 == %2 +ALIGN function_align +.pri: + movsx offq, byte [dirq+4] ; off_k0 +%if %1 == 4 + mova m1, [tmpq+32*0] + punpcklqdq m1, [tmpq+32*1] ; 0 2 1 3 + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k0p0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k0p1 +%else + mova xm1, [tmpq+32*0] + vinserti128 m1, [tmpq+32*1], 1 + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+5] ; off_k1 + psubw m2, m1 ; diff_k0p0 + psubw m3, m1 ; diff_k0p1 + pabsw m4, m2 ; adiff_k0p0 + psrlw m5, m4, [pri_shift+gprsize] + psubusw m0, m6, m5 + pabsw m5, m3 ; adiff_k0p1 + pminsw m0, m4 + psrlw m4, m5, [pri_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0p0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k1p0 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k1p1 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + psubw m4, m1 ; diff_k1p0 + psubw m5, m1 ; diff_k1p1 + psignw m2, m3 ; constrain(diff_k0p1) + pabsw m3, m4 ; adiff_k1p0 + paddw m0, m2 ; constrain(diff_k0) + psrlw m2, m3, [pri_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1p1 + pminsw m7, m3 + psrlw m3, m2, [pri_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1p0) + psubusw m4, m6, m3 + pminsw m4, m2 + psignw m4, m5 ; constrain(diff_k1p1) + paddw m7, m4 ; constrain(diff_k1) + pmullw m0, m9 ; pri_tap_k0 + pmullw m7, m10 ; pri_tap_k1 + paddw m0, m7 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + add tmpq, 32*2 + paddw m0, m1 +%if %1 == 4 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r9 ], xm1 + lea dstq, [dstq+strideq*4] +%else + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] +%endif + ret +ALIGN function_align +.sec: + movsx offq, byte [dirq+8] ; off1_k0 +%if %1 == 4 + mova m1, [tmpq+32*0] + punpcklqdq m1, [tmpq+32*1] + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k0s0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k0s1 +%else + mova xm1, [tmpq+32*0] + vinserti128 m1, [tmpq+32*1], 1 + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+0] ; off2_k0 + psubw m2, m1 ; diff_k0s0 + psubw m3, m1 ; diff_k0s1 + pabsw m4, m2 ; adiff_k0s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m0, m6, m5 + pabsw m5, m3 ; adiff_k0s1 + pminsw m0, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k0s2 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k0s3 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+9] ; off1_k1 + psubw m4, m1 ; diff_k0s2 + psubw m5, m1 ; diff_k0s3 + psignw m2, m3 ; constrain(diff_k0s1) + pabsw m3, m4 ; adiff_k0s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k0s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k0s2) + psubusw m4, m6, m3 + pminsw m4, m2 +%if %1 == 4 + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k1s0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k1s1 +%else + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+1] ; off2_k1 + paddw m0, m7 + psignw m4, m5 ; constrain(diff_k0s3) + paddw m0, m4 ; constrain(diff_k0) + psubw m2, m1 ; diff_k1s0 + psubw m3, m1 ; diff_k1s1 + paddw m0, m0 ; sec_tap_k0 + pabsw m4, m2 ; adiff_k1s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m7, m6, m5 + pabsw m5, m3 ; adiff_k1s1 + pminsw m7, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m7, m2 ; constrain(diff_k1s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k1s2 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k1s3 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + paddw m0, m7 + psubw m4, m1 ; diff_k1s2 + psubw m5, m1 ; diff_k1s3 + psignw m2, m3 ; constrain(diff_k1s1) + pabsw m3, m4 ; adiff_k1s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1s2) + psubusw m4, m6, m3 + pminsw m4, m2 + paddw m0, m7 + psignw m4, m5 ; constrain(diff_k1s3) + paddw m0, m4 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + add tmpq, 32*2 + paddw m0, m1 +%if %1 == 4 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r9 ], xm1 + lea dstq, [dstq+strideq*4] +%else + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] +%endif + ret +ALIGN function_align +.pri_sec: + movsx offq, byte [dirq+8] ; off2_k0 +%if %1 == 4 + mova m1, [tmpq+32*0] + punpcklqdq m1, [tmpq+32*1] + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k0s0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k0s1 +%else + mova xm1, [dstq+strideq*0] + vinserti128 m1, [dstq+strideq*1], 1 + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+0] ; off3_k0 + pmaxsw m11, m2, m3 + pminuw m12, m2, m3 + psubw m2, m1 ; diff_k0s0 + psubw m3, m1 ; diff_k0s1 + pabsw m4, m2 ; adiff_k0s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m0, m13, m5 + pabsw m5, m3 ; adiff_k0s1 + pminsw m0, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0s0) + psubusw m2, m13, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k0s2 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k0s3 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+9] ; off2_k1 + psignw m2, m3 ; constrain(diff_k0s1) + pmaxsw m11, m4 + pminuw m12, m4 + pmaxsw m11, m5 + pminuw m12, m5 + psubw m4, m1 ; diff_k0s2 + psubw m5, m1 ; diff_k0s3 + paddw m0, m2 + pabsw m3, m4 ; adiff_k0s2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m13, m2 + pabsw m2, m5 ; adiff_k0s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k0s2) + psubusw m4, m13, m3 + pminsw m4, m2 +%if %1 == 4 + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k1s0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k1s1 +%else + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+1] ; off3_k1 + paddw m0, m7 + psignw m4, m5 ; constrain(diff_k0s3) + pmaxsw m11, m2 + pminuw m12, m2 + pmaxsw m11, m3 + pminuw m12, m3 + paddw m0, m4 ; constrain(diff_k0) + psubw m2, m1 ; diff_k1s0 + psubw m3, m1 ; diff_k1s1 + paddw m0, m0 ; sec_tap_k0 + pabsw m4, m2 ; adiff_k1s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m7, m13, m5 + pabsw m5, m3 ; adiff_k1s1 + pminsw m7, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m7, m2 ; constrain(diff_k1s0) + psubusw m2, m13, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k1s2 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k1s3 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+4] ; off1_k0 + paddw m0, m7 + psignw m2, m3 ; constrain(diff_k1s1) + pmaxsw m11, m4 + pminuw m12, m4 + pmaxsw m11, m5 + pminuw m12, m5 + psubw m4, m1 ; diff_k1s2 + psubw m5, m1 ; diff_k1s3 + pabsw m3, m4 ; adiff_k1s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m13, m2 + pabsw m2, m5 ; adiff_k1s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1s2) + psubusw m4, m13, m3 + pminsw m4, m2 + paddw m0, m7 +%if %1 == 4 + movu m2, [tmpq+offq+32*0] + punpcklqdq m2, [tmpq+offq+32*1] ; k0p0 + neg offq + movu m3, [tmpq+offq+32*0] + punpcklqdq m3, [tmpq+offq+32*1] ; k0p1 +%else + movu xm2, [tmpq+offq+32*0] + vinserti128 m2, [tmpq+offq+32*1], 1 + neg offq + movu xm3, [tmpq+offq+32*0] + vinserti128 m3, [tmpq+offq+32*1], 1 +%endif + movsx offq, byte [dirq+5] ; off1_k1 + psignw m4, m5 ; constrain(diff_k1s3) + pmaxsw m11, m2 + pminuw m12, m2 + pmaxsw m11, m3 + pminuw m12, m3 + psubw m2, m1 ; diff_k0p0 + psubw m3, m1 ; diff_k0p1 + paddw m0, m4 + pabsw m4, m2 ; adiff_k0p0 + psrlw m5, m4, [pri_shift+gprsize] + psubusw m7, m6, m5 + pabsw m5, m3 ; adiff_k0p1 + pminsw m7, m4 + psrlw m4, m5, [pri_shift+gprsize] + psignw m7, m2 ; constrain(diff_k0p0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movu m4, [tmpq+offq+32*0] + punpcklqdq m4, [tmpq+offq+32*1] ; k1p0 + neg offq + movu m5, [tmpq+offq+32*0] + punpcklqdq m5, [tmpq+offq+32*1] ; k1p1 +%else + movu xm4, [tmpq+offq+32*0] + vinserti128 m4, [tmpq+offq+32*1], 1 + neg offq + movu xm5, [tmpq+offq+32*0] + vinserti128 m5, [tmpq+offq+32*1], 1 +%endif + psignw m2, m3 ; constrain(diff_k0p1) + paddw m7, m2 ; constrain(diff_k0) + pmaxsw m11, m4 + pminuw m12, m4 + pmaxsw m11, m5 + pminuw m12, m5 + psubw m4, m1 ; diff_k1p0 + psubw m5, m1 ; diff_k1p1 + pabsw m3, m4 ; adiff_k1p0 + pmullw m7, m9 ; pri_tap_k0 + paddw m0, m7 + psrlw m2, m3, [pri_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1p1 + pminsw m7, m3 + psrlw m3, m2, [pri_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1p0) + psubusw m4, m6, m3 + pminsw m4, m2 + psignw m4, m5 ; constrain(diff_k1p1) + paddw m7, m4 ; constrain(diff_k1) + pmullw m7, m10 ; pri_tap_k1 + paddw m0, m7 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + add tmpq, 32*2 + pmaxsw m11, m1 + pminuw m12, m1 + paddw m0, m1 + pminsw m0, m11 + pmaxsw m0, m12 +%if %1 == 4 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r9 ], xm1 + lea dstq, [dstq+strideq*4] +%else + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] +%endif + ret +%endif +%endmacro + +INIT_YMM avx2 +cglobal cdef_filter_4x4_16bpc, 5, 10, 9, 16*10, dst, stride, left, top, bot, \ + pri, sec, edge +%if WIN64 + %define px rsp+16*6 + %define offq r8 + %define pri_shift rsp+16*2 + %define sec_shift rsp+16*3 +%else + %define px rsp+16*4 + %define offq r4 + %define pri_shift rsp+16*0 + %define sec_shift rsp+16*1 +%endif + %define base r8-dir_table4 + mov edged, r9m + lea r8, [dir_table4] + movu xm0, [dstq+strideq*0] + movu xm1, [dstq+strideq*1] + lea r9, [strideq*3] + movu xm2, [dstq+strideq*2] + movu xm3, [dstq+r9 ] + vpbroadcastd m7, [base+pw_m16384] + mova [px+16*0+0], xm0 + mova [px+16*1+0], xm1 + mova [px+16*2+0], xm2 + mova [px+16*3+0], xm3 + test edgeb, 4 ; HAVE_TOP + jz .no_top + movu xm0, [topq+strideq*0] + movu xm1, [topq+strideq*1] + mova [px-16*2+0], xm0 + mova [px-16*1+0], xm1 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd xm0, [topq+strideq*0-4] + movd xm1, [topq+strideq*1-4] + movd [px-16*2-4], xm0 + movd [px-16*1-4], xm1 + jmp .top_done +.no_top: + mova [px-16*2+0], m7 +.top_no_left: + movd [px-16*2-4], xm7 + movd [px-16*1-4], xm7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movu xm0, [botq+strideq*0] + movu xm1, [botq+strideq*1] + mova [px+16*4+0], xm0 + mova [px+16*5+0], xm1 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd xm0, [botq+strideq*0-4] + movd xm1, [botq+strideq*1-4] + movd [px+16*4-4], xm0 + movd [px+16*5-4], xm1 + jmp .bottom_done +.no_bottom: + mova [px+16*4+0], m7 +.bottom_no_left: + movd [px+16*4-4], xm7 + movd [px+16*5-4], xm7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movd xm0, [leftq+4*0] + movd xm1, [leftq+4*1] + movd xm2, [leftq+4*2] + movd xm3, [leftq+4*3] + movd [px+16*0-4], xm0 + movd [px+16*1-4], xm1 + movd [px+16*2-4], xm2 + movd [px+16*3-4], xm3 + jmp .left_done +.no_left: + REPX {movd [px+16*x-4], xm7}, 0, 1, 2, 3 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+16*x+8], xm7}, -2, -1, 0, 1, 2, 3, 4, 5 +.padding_done: + CDEF_FILTER 4, 4 + +cglobal cdef_filter_4x8_16bpc, 5, 10, 9, 16*14, dst, stride, left, top, bot, \ + pri, sec, edge + mov edged, r9m + movu xm0, [dstq+strideq*0] + movu xm1, [dstq+strideq*1] + lea r9, [strideq*3] + movu xm2, [dstq+strideq*2] + movu xm3, [dstq+r9 ] + lea r6, [dstq+strideq*4] + movu xm4, [r6 +strideq*0] + movu xm5, [r6 +strideq*1] + movu xm6, [r6 +strideq*2] + movu xm7, [r6 +r9 ] + lea r8, [dir_table4] + mova [px+16*0+0], xm0 + mova [px+16*1+0], xm1 + mova [px+16*2+0], xm2 + mova [px+16*3+0], xm3 + mova [px+16*4+0], xm4 + mova [px+16*5+0], xm5 + mova [px+16*6+0], xm6 + mova [px+16*7+0], xm7 + vpbroadcastd m7, [base+pw_m16384] + test edgeb, 4 ; HAVE_TOP + jz .no_top + movu xm0, [topq+strideq*0] + movu xm1, [topq+strideq*1] + mova [px-16*2+0], xm0 + mova [px-16*1+0], xm1 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd xm0, [topq+strideq*0-4] + movd xm1, [topq+strideq*1-4] + movd [px-16*2-4], xm0 + movd [px-16*1-4], xm1 + jmp .top_done +.no_top: + mova [px-16*2+0], m7 +.top_no_left: + movd [px-16*2-4], xm7 + movd [px-16*1-4], xm7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movu xm0, [botq+strideq*0] + movu xm1, [botq+strideq*1] + mova [px+16*8+0], xm0 + mova [px+16*9+0], xm1 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd xm0, [botq+strideq*0-4] + movd xm1, [botq+strideq*1-4] + movd [px+16*8-4], xm0 + movd [px+16*9-4], xm1 + jmp .bottom_done +.no_bottom: + mova [px+16*8+0], m7 +.bottom_no_left: + movd [px+16*8-4], xm7 + movd [px+16*9-4], xm7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movd xm0, [leftq+4*0] + movd xm1, [leftq+4*1] + movd xm2, [leftq+4*2] + movd xm3, [leftq+4*3] + movd [px+16*0-4], xm0 + movd [px+16*1-4], xm1 + movd [px+16*2-4], xm2 + movd [px+16*3-4], xm3 + movd xm0, [leftq+4*4] + movd xm1, [leftq+4*5] + movd xm2, [leftq+4*6] + movd xm3, [leftq+4*7] + movd [px+16*4-4], xm0 + movd [px+16*5-4], xm1 + movd [px+16*6-4], xm2 + movd [px+16*7-4], xm3 + jmp .left_done +.no_left: + REPX {movd [px+16*x-4], xm7}, 0, 1, 2, 3, 4, 5, 6, 7 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+16*x+8], xm7}, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +.padding_done: + CDEF_FILTER 4, 8 + +cglobal cdef_filter_8x8_16bpc, 5, 9, 9, 32*13, dst, stride, left, top, bot, \ + pri, sec, edge +%if WIN64 + %define px rsp+32*4 +%else + %define px rsp+32*3 +%endif + %define base r8-dir_table8 + mov edged, r9m + movu m0, [dstq+strideq*0] + movu m1, [dstq+strideq*1] + lea r6, [dstq+strideq*2] + movu m2, [r6 +strideq*0] + movu m3, [r6 +strideq*1] + lea r6, [r6 +strideq*2] + movu m4, [r6 +strideq*0] + movu m5, [r6 +strideq*1] + lea r6, [r6 +strideq*2] + movu m6, [r6 +strideq*0] + movu m7, [r6 +strideq*1] + lea r8, [dir_table8] + mova [px+32*0+0], m0 + mova [px+32*1+0], m1 + mova [px+32*2+0], m2 + mova [px+32*3+0], m3 + mova [px+32*4+0], m4 + mova [px+32*5+0], m5 + mova [px+32*6+0], m6 + mova [px+32*7+0], m7 + vpbroadcastd m7, [base+pw_m16384] + test edgeb, 4 ; HAVE_TOP + jz .no_top + movu m0, [topq+strideq*0] + movu m1, [topq+strideq*1] + mova [px-32*2+0], m0 + mova [px-32*1+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd xm0, [topq+strideq*0-4] + movd xm1, [topq+strideq*1-4] + movd [px-32*2-4], xm0 + movd [px-32*1-4], xm1 + jmp .top_done +.no_top: + mova [px-32*2+0], m7 + mova [px-32*1+0], m7 +.top_no_left: + movd [px-32*2-4], xm7 + movd [px-32*1-4], xm7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movu m0, [botq+strideq*0] + movu m1, [botq+strideq*1] + mova [px+32*8+0], m0 + mova [px+32*9+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd xm0, [botq+strideq*0-4] + movd xm1, [botq+strideq*1-4] + movd [px+32*8-4], xm0 + movd [px+32*9-4], xm1 + jmp .bottom_done +.no_bottom: + mova [px+32*8+0], m7 + mova [px+32*9+0], m7 +.bottom_no_left: + movd [px+32*8-4], xm7 + movd [px+32*9-4], xm7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movd xm0, [leftq+4*0] + movd xm1, [leftq+4*1] + movd xm2, [leftq+4*2] + movd xm3, [leftq+4*3] + movd [px+32*0-4], xm0 + movd [px+32*1-4], xm1 + movd [px+32*2-4], xm2 + movd [px+32*3-4], xm3 + movd xm0, [leftq+4*4] + movd xm1, [leftq+4*5] + movd xm2, [leftq+4*6] + movd xm3, [leftq+4*7] + movd [px+32*4-4], xm0 + movd [px+32*5-4], xm1 + movd [px+32*6-4], xm2 + movd [px+32*7-4], xm3 + jmp .left_done +.no_left: + REPX {movd [px+32*x-4], xm7}, 0, 1, 2, 3, 4, 5, 6, 7 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+32*x+16], xm7}, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +.padding_done: + CDEF_FILTER 8, 8 + +cglobal cdef_dir_16bpc, 4, 7, 6, src, stride, var, bdmax + lea r6, [dir_shift] + shr bdmaxd, 11 ; 0 for 10bpc, 1 for 12bpc + vpbroadcastd m4, [r6+bdmaxq*4] + lea r6, [strideq*3] + mova xm0, [srcq+strideq*0] + mova xm1, [srcq+strideq*1] + mova xm2, [srcq+strideq*2] + mova xm3, [srcq+r6 ] + lea srcq, [srcq+strideq*4] + vinserti128 m0, [srcq+r6 ], 1 + vinserti128 m1, [srcq+strideq*2], 1 + vinserti128 m2, [srcq+strideq*1], 1 + vinserti128 m3, [srcq+strideq*0], 1 + REPX {pmulhuw x, m4}, m0, m1, m2, m3 + jmp mangle(private_prefix %+ _cdef_dir_8bpc %+ SUFFIX).main + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,622 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +cdef_perm: db 2, 18, 16, 18, 24, 19, 0, 19, 25, 20, 1, 20, 26, 21, 2, 21 + db 3, 26, 3, 26, 28, 27, 4, 27, 29, 28, -1, 28, 30, 29, -1, 29 + db 0, 34, 17, 34, 16, 35, 8, 35, 17, 36, 9, 36, 18, 37, 10, 37 + db 1, 42, 11, 42, 20, 43, 12, 43, 21, 44, -1, 44, 22, 45, -1, 45 +end_perm4: db 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30 + db 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62 +edge_mask4: dw 0xff99, 0xff88, 0xff11, 0xff00 ; 0100, 0101, 0110, 0111 + dw 0x99ff, 0x88ff, 0x11ff, 0x00ff ; 1000, 1001, 1010, 1011 + dw 0x9999, 0x8888, 0x1111, 0x0000 ; 1100, 1101, 1110, 1111 +pri_taps4: dw 64, 32, 48, 48 ; left-shifted by 4 +cdef_dirs4: dw 8, 16, 8, 15, -7,-14, 1, -6 + dw 1, 2, 1, 10, 9, 18, 8, 17 + dw 8, 16, 8, 15, -7,-14, 1, -6 +deint_shuf: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +cdef_dirs8: db 32, 64, 32, 62,-30,-60, 2,-28 + db 2, 4, 2, 36, 34, 68, 32, 66 + db 32, 64, 32, 62,-30,-60, 2,-28 +pri_taps8: dw 4, 4, 2, 2, 3, 3, 3, 3 +sec_taps4: dw 32, 16 +pw_m16384: times 2 dw -16384 +pw_2048: times 2 dw 2048 +pd_268435568: dd 268435568 ; (1 << 28) + (7 << 4) +edge_mask8: dw 0x2121, 0x2020, 0x0101 + +SECTION .text + +%macro CONSTRAIN 7 ; dst, p, px, zero, tresh, shift, tmp + psubw %1, %2, %3 + pabsw %1, %1 + vpcmpgtw k1, %3, %2 + vpsrlvw %7, %1, %6 + psubusw %7, %5, %7 + pminsw %1, %7 + vpsubw %1{k1}, %4, %1 +%endmacro + +; t0 t1 t2 t3 t4 t5 t6 t7 L4 L5 20 21 22 23 24 25 +; T0 T1 T2 T3 T4 T5 T6 T7 L6 L7 30 31 32 33 34 35 +; L0 L1 00 01 02 03 04 05 b0 b1 b2 b3 b4 b5 b6 b7 +; L2 L3 10 11 12 13 14 15 B0 B1 B2 B3 B4 B5 B6 B7 + +INIT_ZMM avx512icl +cglobal cdef_filter_4x4_16bpc, 5, 7, 16, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%define base r6-cdef_dirs4 + lea r6, [cdef_dirs4] + movu xm3, [dstq+strideq*0] + vinserti32x4 ym3, [dstq+strideq*1], 1 + mova xm2, [leftq] + lea r2, [dstq+strideq*2] + vinserti32x4 m3, [r2+strideq*0], 2 + mova m5, [base+cdef_perm] + vinserti32x4 m3, [r2+strideq*1], 3 + vpermt2d m2, m5, m3 + vinserti32x4 m1, m2, [topq+strideq*0-4], 0 + vinserti32x4 m1, [topq+strideq*1-4], 1 + mov r3d, edgem + movifnidn prid, prim + punpcklwd m3, m3 ; px + psrlw m5, 8 + vpbroadcastd m0, [base+pd_268435568] + pxor m12, m12 + cmp r3d, 0x0f + jne .mask_edges + vinserti32x4 m2, [botq+strideq*0-4], 2 + vinserti32x4 m2, [botq+strideq*1-4], 3 +.main: + test prid, prid + jz .sec_only + lzcnt r4d, prid + rorx r3d, prid, 2 + vpbroadcastw m13, prim + cmp dword r10m, 0xfff ; if (bpc == 12) + cmove prid, r3d ; pri >>= 2 + mov r3d, dampingm + and prid, 4 + sub r3d, 31 + vpbroadcastd m15, [base+pri_taps4+priq] + xor prid, prid + add r4d, r3d + cmovns prid, r4d ; pri_shift + mov r4d, dirm + vpbroadcastw m14, prid + mov r5d, secm + vpbroadcastd m9, [base+cdef_dirs4+(r4+2)*4] + call .constrain + test r5d, r5d + jz .end_no_clip + lzcnt r5d, r5d + vpbroadcastw m13, secm + add r3d, r5d + pminuw m6, m3, m8 + pmaxsw m7, m3, m8 + pminuw m6, m9 + pmaxsw m7, m9 + call .constrain_sec + pminuw m6, m8 + pmaxsw m7, m8 + pminuw m6, m9 + pmaxsw m7, m9 + vpbroadcastd m9, [base+cdef_dirs4+(r4+0)*4] + call .constrain + pminuw m6, m8 + pmaxsw m7, m8 + pminuw m6, m9 + pmaxsw m7, m9 + psrldq m8, m6, 2 + vpshldd m3, m0, 8 + psrldq m9, m7, 2 + paddd m0, m3 + pminuw m6, m8 + psrldq m0, 1 + pmaxsw m7, m9 + pmaxsw m0, m6 + pminsw m0, m7 + vpmovdw ym0, m0 + jmp .end +.sec_only: + tzcnt r5d, secm + mov r3d, dampingm + vpbroadcastw m13, secm + mov r4d, dirm + sub r3d, r5d ; sec_shift + call .constrain_sec + vpbroadcastd m9, [base+cdef_dirs4+(r4+0)*4] + call .constrain +.end_no_clip: + mova ym1, [base+end_perm4] + vpshldd m3, m0, 8 ; (px << 8) + ((sum > -8) << 4) + paddd m0, m3 ; (px << 8) + ((sum + (sum > -8) + 7) << 4) + vpermb m0, m1, m0 +.end: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm0, ym0, 1 + movq [r2+strideq*0], xm0 + movhps [r2+strideq*1], xm0 + RET +.mask_edges: + vpbroadcastd m6, [base+pw_m16384] + test r3b, 0x08 + jz .mask_edges_no_bottom ; avoid buffer overread + vinserti32x4 m2, [botq+strideq*0-4], 2 + vinserti32x4 m2, [botq+strideq*1-4], 3 + kmovw k1, [base+edge_mask4-8+r3*2] + jmp .mask_edges_main +.mask_edges_no_bottom: + kmovw k1, [base+edge_mask4+8+r3*2] +.mask_edges_main: + or r3d, 0x04 + vmovdqa32 m1{k1}, m6 ; edge pixels = -16384 + kmovw k1, [base+edge_mask4-8+r3*2] + vmovdqa32 m2{k1}, m6 + jmp .main +.constrain_sec: + vpbroadcastd m9, [base+cdef_dirs4+(r4+4)*4] + vpbroadcastw m14, r3d + vpbroadcastd m15, [base+sec_taps4] +.constrain: + paddw m8, m5, m9 + vpermi2w m8, m1, m2 ; k0p0 k1p0 + psubw m9, m5, m9 + vpermi2w m9, m1, m2 ; k0p1 k1p1 + CONSTRAIN m10, m8, m3, m12, m13, m14, m11 + vpdpwssd m0, m10, m15 + CONSTRAIN m10, m9, m3, m12, m13, m14, m11 + vpdpwssd m0, m10, m15 + ret + +; t0 t1 t2 t3 t4 t5 t6 t7 L4 L5 20 21 22 23 24 25 Lc Ld 60 61 62 63 64 65 +; T0 T1 T2 T3 T4 T5 T6 T7 L6 L7 30 31 32 33 34 35 Le Lf 70 71 72 73 74 75 +; L0 L1 00 01 02 03 04 05 L8 L9 40 41 42 43 44 45 b0 b1 b2 b3 b4 b5 b6 b7 +; L2 L3 10 11 12 13 14 15 La Lb 50 51 52 53 54 55 B0 B1 B2 B3 B4 B5 B6 B7 + +cglobal cdef_filter_4x8_16bpc, 5, 7, 22, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge + lea r6, [cdef_dirs4] + movu xm18, [dstq+strideq*0] + vinserti128 ym18, [dstq+strideq*1], 1 + mova xm1, [leftq+16*0] + mova xm2, [leftq+16*1] + lea r2, [strideq*3] + vinserti32x4 m18, [dstq+strideq*2], 2 + mova m5, [base+cdef_perm] + vinserti32x4 m18, [dstq+r2 ], 3 + vpermt2d m1, m5, m18 + vinserti32x4 m0, m1, [topq+strideq*0-4], 0 + vinserti32x4 m0, [topq+strideq*1-4], 1 + lea r3, [dstq+strideq*4] + movu xm19, [r3+strideq*0] + vinserti128 ym19, [r3+strideq*1], 1 + vinserti32x4 m19, [r3+strideq*2], 2 + vinserti32x4 m19, [r3+r2 ], 3 + mov r3d, edgem + movifnidn prid, prim + vpermt2d m2, m5, m19 + vpbroadcastd m16, [base+pd_268435568] + pxor m12, m12 + punpcklwd m18, m18 ; px (top) + psrlw m5, 8 + punpcklwd m19, m19 ; px (bottom) + mova m17, m16 + vshufi32x4 m1, m2, q3210 + cmp r3d, 0x0f + jne .mask_edges + vinserti32x4 m2, [botq+strideq*0-4], 2 + vinserti32x4 m2, [botq+strideq*1-4], 3 +.main: + test prid, prid + jz .sec_only + lzcnt r4d, prid + rorx r3d, prid, 2 + vpbroadcastw m13, prim + cmp dword r10m, 0xfff ; if (bpc == 12) + cmove prid, r3d ; pri >>= 2 + mov r3d, dampingm + and prid, 4 + sub r3d, 31 + vpbroadcastd m15, [base+pri_taps4+priq] + xor prid, prid + add r4d, r3d + cmovns prid, r4d ; pri_shift + mov r4d, dirm + vpbroadcastw m14, prid + mov r5d, secm + vpbroadcastd m9, [base+cdef_dirs4+(r4+2)*4] + call .constrain + test r5d, r5d + jz .end_no_clip + lzcnt r5d, r5d + vpbroadcastw m13, secm + add r3d, r5d + pminuw m3, m18, m6 + pmaxsw m4, m18, m6 + pminuw m20, m19, m7 + pmaxsw m21, m19, m7 + pminuw m3, m8 + pmaxsw m4, m8 + pminuw m20, m9 + pmaxsw m21, m9 + call .constrain_sec + pminuw m3, m6 + pmaxsw m4, m6 + pminuw m20, m7 + pmaxsw m21, m7 + pminuw m3, m8 + pmaxsw m4, m8 + pminuw m20, m9 + pmaxsw m21, m9 + vpbroadcastd m9, [base+cdef_dirs4+(r4+0)*4] + call .constrain + pminuw m3, m6 + pmaxsw m4, m6 + mov r3, 0xcccccccccccccccc + pminuw m20, m7 + pmaxsw m21, m7 + kmovq k1, r3 + pminuw m3, m8 + pmaxsw m4, m8 + pminuw m20, m9 + pmaxsw m21, m9 + vbroadcasti32x4 m0, [base+deint_shuf] + vpshldd m6, m20, m3, 16 + vmovdqu8 m3{k1}, m20 + vpshldd m18, m16, 8 + vpshldd m7, m21, m4, 16 + vmovdqu8 m4{k1}, m21 + vpshldd m19, m17, 8 + pminuw m3, m6 + paddd m16, m18 + pmaxsw m4, m7 + paddd m17, m19 + psrldq m16, 1 + palignr m16{k1}, m17, m17, 15 + lea r6, [dstq+strideq*4] + pmaxsw m16, m3 + pminsw m16, m4 + pshufb m16, m0 + movq [dstq+strideq*0], xm16 + movhps [r6 +strideq*0], xm16 + vextracti128 xm17, ym16, 1 + movq [dstq+strideq*1], xm17 + movhps [r6 +strideq*1], xm17 + vextracti32x4 xm17, m16, 2 + movq [dstq+strideq*2], xm17 + movhps [r6 +strideq*2], xm17 + vextracti32x4 xm16, m16, 3 + movq [dstq+r2 ], xm16 + movhps [r6 +r2 ], xm16 + RET +.sec_only: + mov r4d, dirm + tzcnt r5d, secm + mov r3d, dampingm + vpbroadcastw m13, secm + sub r3d, r5d ; sec_shift + call .constrain_sec + vpbroadcastd m9, [base+cdef_dirs4+(r4+0)*4] + call .constrain +.end_no_clip: + mova ym20, [base+end_perm4] + vpshldd m18, m16, 8 ; (px << 8) + ((sum > -8) << 4) + vpshldd m19, m17, 8 + paddd m16, m18 ; (px << 8) + ((sum + (sum > -8) + 7) << 4) + paddd m17, m19 + vpermb m16, m20, m16 + vpermb m17, m20, m17 + movq [dstq+strideq*0], xm16 + movhps [dstq+strideq*1], xm16 + vextracti128 xm16, ym16, 1 + movq [dstq+strideq*2], xm16 + movhps [dstq+r2 ], xm16 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm17 + movhps [dstq+strideq*1], xm17 + vextracti128 xm17, ym17, 1 + movq [dstq+strideq*2], xm17 + movhps [dstq+r2 ], xm17 + RET +.mask_edges: + vpbroadcastd m6, [base+pw_m16384] + test r3b, 0x08 + jz .mask_edges_no_bottom ; avoid buffer overread + vinserti32x4 m2, [botq+strideq*0-4], 2 + vinserti32x4 m2, [botq+strideq*1-4], 3 + kmovw k1, [base+edge_mask4-8+r3*2] + jmp .mask_edges_main +.mask_edges_no_bottom: + kmovw k1, [base+edge_mask4+8+r3*2] +.mask_edges_main: + mov r4d, r3d + or r3d, 0x0c + vmovdqa32 m0{k1}, m6 ; edge pixels = -16384 + kmovw k1, [base+edge_mask4-8+r3*2] + or r4d, 0x04 + vmovdqa32 m1{k1}, m6 + kmovw k1, [base+edge_mask4-8+r4*2] + vmovdqa32 m2{k1}, m6 + jmp .main +.constrain_sec: + vpbroadcastd m9, [base+cdef_dirs4+(r4+4)*4] + vpbroadcastw m14, r3d + vpbroadcastd m15, [base+sec_taps4] +.constrain: + paddw m7, m5, m9 + mova m6, m0 + vpermt2w m6, m7, m1 ; k0p0 k1p0 (top) + psubw m9, m5, m9 + mova m8, m0 + vpermi2w m7, m1, m2 ; k0p0 k1p0 (bottom) + CONSTRAIN m10, m6, m18, m12, m13, m14, m11 + vpermt2w m8, m9, m1 ; k0p1 k1p1 (top) + vpdpwssd m16, m10, m15 + CONSTRAIN m10, m7, m19, m12, m13, m14, m11 + vpermi2w m9, m1, m2 ; k0p1 k1p1 (bottom) + vpdpwssd m17, m10, m15 + CONSTRAIN m10, m8, m18, m12, m13, m14, m11 + vpdpwssd m16, m10, m15 + CONSTRAIN m10, m9, m19, m12, m13, m14, m11 + vpdpwssd m17, m10, m15 + ret + +cglobal cdef_filter_8x8_16bpc, 5, 7, 22, 64*6, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%define base r6-cdef_dirs8 + lea r6, [cdef_dirs8] + movu ym17, [dstq+strideq*0] + vinserti32x8 m17, [dstq+strideq*1], 1 + movq xm4, [leftq+8*0] + movq xm5, [leftq+8*1] + psrld m2, [base+cdef_perm], 16 + movq xm6, [leftq+8*2] + movq xm7, [leftq+8*3] + lea r2, [strideq*3] + movu ym16, [topq+strideq*0-4] + vinserti32x8 m16, [topq+strideq*1-4], 1 + lea r3, [dstq+strideq*4] + movu ym18, [dstq+strideq*2] + vinserti32x8 m18, [dstq+r2 ], 1 + movu ym19, [r3+strideq*0] + vinserti32x8 m19, [r3+strideq*1], 1 + movu ym20, [r3+strideq*2] + vinserti32x8 m20, [r3+r2 ], 1 + vshufi32x4 m0, m17, m18, q2020 ; px (top) + mov r3d, edgem + vshufi32x4 m1, m19, m20, q2020 ; px (bottom) + movifnidn prid, prim + vpermt2d m17, m2, m4 + vpermt2d m18, m2, m5 + pxor m12, m12 + vpermt2d m19, m2, m6 + vpermt2d m20, m2, m7 + cmp r3d, 0x0f + jne .mask_edges + movu ym21, [botq+strideq*0-4] + vinserti32x8 m21, [botq+strideq*1-4], 1 +.main: + mova [rsp+64*0], m16 ; top + mova [rsp+64*1], m17 ; 0 1 + mova [rsp+64*2], m18 ; 2 3 + mova [rsp+64*3], m19 ; 4 5 + mova [rsp+64*4], m20 ; 6 7 + mova [rsp+64*5], m21 ; bottom + test prid, prid + jz .sec_only + lzcnt r4d, prid + rorx r3d, prid, 2 + vpbroadcastw m13, prim + cmp dword r10m, 0xfff ; if (bpc == 12) + cmove prid, r3d ; pri >>= 2 + mov r3d, dampingm + and prid, 4 + sub r3d, 31 + add r4d, r3d ; pri_shift + vpbroadcastw m14, r4d + mov r4d, dirm + vpbroadcastd m2, [base+pri_taps8+priq*2+0] + vpbroadcastd m3, [base+pri_taps8+priq*2+4] + movsx r5, byte [base+cdef_dirs8+(r4+2)*2+0] ; k0off1 + pmaxsw m14, m12 + call .constrain + mov r5d, secm + pmullw m16, m8, m2 + pmullw m17, m9, m2 + test r5d, r5d + jnz .pri_sec + movsx r5, byte [base+cdef_dirs8+(r4+2)*2+1] ; k1off1 + call .constrain + pmullw m8, m3 + pmullw m9, m3 + jmp .end_no_clip +.pri_sec: + lzcnt r5d, r5d + add r3d, r5d ; sec_shift + movsx r5, byte [base+cdef_dirs8+(r4+2)*2+1] ; k1off1 + pminuw m18, m0, m4 + pmaxsw m19, m0, m4 + pminuw m20, m1, m5 + pmaxsw m21, m1, m5 + call .min_max_constrain2 + movsx r5, byte [base+cdef_dirs8+(r4+0)*2+0] ; k0off2 + pmullw m8, m3 + pmullw m9, m3 + vpbroadcastw m13, secm + vpbroadcastw m14, r3d + paddw m16, m8 + paddw m17, m9 + call .min_max_constrain + movsx r5, byte [base+cdef_dirs8+(r4+4)*2+0] ; k0off3 + mova m2, m8 + mova m3, m9 + call .min_max_constrain + movsx r5, byte [base+cdef_dirs8+(r4+0)*2+1] ; k1off2 + paddw m2, m8 + paddw m3, m9 + call .min_max_constrain + movsx r5, byte [base+cdef_dirs8+(r4+4)*2+1] ; k1off3 + paddw m2, m2 + paddw m3, m3 + paddw m16, m8 + paddw m17, m9 + call .min_max_constrain + vpbroadcastd m10, [base+pw_2048] + paddw m16, m2 + paddw m17, m3 + paddw m16, m8 + paddw m17, m9 + psraw m8, m16, 15 + psraw m9, m17, 15 + paddw m16, m8 + paddw m17, m9 + pmulhrsw m16, m10 + pmulhrsw m17, m10 + pminuw m18, m4 + pmaxsw m19, m4 + pminuw m20, m5 + pmaxsw m21, m5 + pminuw m18, m6 + pmaxsw m19, m6 + pminuw m20, m7 + pmaxsw m21, m7 + paddw m16, m0 + paddw m17, m1 + pmaxsw m16, m18 + pmaxsw m17, m20 + pminsw m16, m19 + pminsw m17, m21 + jmp .end +.sec_only: + tzcnt r5d, secm + mov r4d, dirm + mov r3d, dampingm + vpbroadcastw m13, secm + sub r3d, r5d + movsx r5, byte [base+cdef_dirs8+(r4+0)*2+0] + vpbroadcastw m14, r3d + call .constrain + movsx r5, byte [base+cdef_dirs8+(r4+4)*2+0] + mova m16, m8 + mova m17, m9 + call .constrain + movsx r5, byte [base+cdef_dirs8+(r4+0)*2+1] + paddw m16, m8 + paddw m17, m9 + call .constrain + movsx r5, byte [base+cdef_dirs8+(r4+4)*2+1] + paddw m16, m16 + paddw m17, m17 + paddw m16, m8 + paddw m17, m9 + call .constrain +.end_no_clip: + vpbroadcastd m10, [base+pw_2048] + paddw m16, m8 + paddw m17, m9 + psraw m8, m16, 15 + psraw m9, m17, 15 + paddw m16, m8 + paddw m17, m9 + pmulhrsw m16, m10 + pmulhrsw m17, m10 + paddw m16, m0 + paddw m17, m1 +.end: + mova [dstq+strideq*0], xm16 + vextracti128 [dstq+strideq*1], ym16, 1 + vextracti32x4 [dstq+strideq*2], m16, 2 + vextracti32x4 [dstq+r2 ], m16, 3 + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm17 + vextracti128 [dstq+strideq*1], ym17, 1 + vextracti32x4 [dstq+strideq*2], m17, 2 + vextracti32x4 [dstq+r2 ], m17, 3 + RET +.mask_edges: + vpbroadcastd m2, [base+pw_m16384] + test r3b, 0x08 + jz .mask_edges_no_bottom ; avoid buffer overread + movu ym21, [botq+strideq*0-4] + vinserti32x8 m21, [botq+strideq*1-4], 1 + jmp .mask_edges_top +.mask_edges_no_bottom: + mova m21, m2 +.mask_edges_top: + test r3b, 0x04 + jnz .mask_edges_main + mova m16, m2 +.mask_edges_main: + and r3d, 0x03 + cmp r3d, 0x03 + je .main + kmovw k1, [base+edge_mask8+r3*2] + vmovdqa32 m16{k1}, m2 ; edge pixels = -16384 + vmovdqa32 m17{k1}, m2 + vmovdqa32 m18{k1}, m2 + vmovdqa32 m19{k1}, m2 + vmovdqa32 m20{k1}, m2 + vmovdqa32 m21{k1}, m2 + jmp .main +ALIGN function_align +.min_max_constrain: + pminuw m18, m4 + pmaxsw m19, m4 + pminuw m20, m5 + pmaxsw m21, m5 +.min_max_constrain2: + pminuw m18, m6 + pmaxsw m19, m6 + pminuw m20, m7 + pmaxsw m21, m7 +.constrain: + %define tmp rsp+gprsize+68 + movu m4, [tmp+r5+64*0] + vshufi32x4 m4, [tmp+r5+64*1], q2020 ; k0p0 (top) + movu m5, [tmp+r5+64*2] + vshufi32x4 m5, [tmp+r5+64*3], q2020 ; k0p0 (bottom) + neg r5 + movu m6, [tmp+r5+64*0] + vshufi32x4 m6, [tmp+r5+64*1], q2020 ; k0p1 (top) + movu m7, [tmp+r5+64*2] + vshufi32x4 m7, [tmp+r5+64*3], q2020 ; k0p1 (bottom) + CONSTRAIN m8, m4, m0, m12, m13, m14, m15 + CONSTRAIN m9, m5, m1, m12, m13, m14, m15 + CONSTRAIN m10, m6, m0, m12, m13, m14, m15 + CONSTRAIN m11, m7, m1, m12, m13, m14, m15 + paddw m8, m10 + paddw m9, m11 + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1033 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; Copyright (c) 2017-2021, The rav1e contributors +; Copyright (c) 2021, Nathan Egge +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA + +%macro DUP8 1-* + %rep %0 + times 8 dw %1 + %rotate 1 + %endrep +%endmacro + +pri_taps: DUP8 4, 2, 3, 3 +dir_table: db 1 * 32 + 0, 2 * 32 + 0 + db 1 * 32 + 0, 2 * 32 - 2 + db -1 * 32 + 2, -2 * 32 + 4 + db 0 * 32 + 2, -1 * 32 + 4 + db 0 * 32 + 2, 0 * 32 + 4 + db 0 * 32 + 2, 1 * 32 + 4 + db 1 * 32 + 2, 2 * 32 + 4 + db 1 * 32 + 0, 2 * 32 + 2 + db 1 * 32 + 0, 2 * 32 + 0 + db 1 * 32 + 0, 2 * 32 - 2 + db -1 * 32 + 2, -2 * 32 + 4 + db 0 * 32 + 2, -1 * 32 + 4 + +dir_shift: times 4 dw 0x4000 + times 4 dw 0x1000 + +pw_128: times 4 dw 128 +pw_2048: times 8 dw 2048 +pw_m16384: times 8 dw -16384 + +cextern cdef_dir_8bpc_ssse3.main +cextern cdef_dir_8bpc_sse4.main +cextern shufw_6543210x + +SECTION .text + +%if ARCH_X86_32 +DECLARE_REG_TMP 5, 3 +%elif WIN64 +DECLARE_REG_TMP 8, 4 +%else +DECLARE_REG_TMP 8, 6 +%endif + +%macro CDEF_FILTER 2 ; w, h +%if ARCH_X86_64 + DEFINE_ARGS dst, stride, _, tmp, pridmp, pri, sec, dir + mova m8, [base+pw_2048] +%else + DEFINE_ARGS dst, pridmp, tmp, sec, pri, _, dir + %define m8 [base+pw_2048] + %define m9 [rsp+16*1+gprsize] + %define m10 [rsp+16*2+gprsize] +%endif + movifnidn prid, r5m + movifnidn secd, r6m + test prid, prid + jz .sec_only + movd m6, r5m +%if ARCH_X86_32 + mov [rsp+24], pridmpd +%endif + bsr pridmpd, prid + lea tmpd, [priq*4] + cmp dword r10m, 0x3ff ; if (bpc == 10) + cmove prid, tmpd ; pri <<= 2 + mov tmpd, r8m ; damping + mov dird, r7m + and prid, 16 + pshufb m6, m7 ; splat + lea dirq, [base+dir_table+dirq*2] + lea priq, [base+pri_taps+priq*2] + test secd, secd + jz .pri_only + mova [rsp], m6 + movd m6, secd + tzcnt secd, secd + sub pridmpd, tmpd + sub tmpd, secd + pshufb m6, m7 + xor secd, secd + neg pridmpd + cmovs pridmpd, secd +%if ARCH_X86_32 + mov [pri_shift+4], secd + mov [sec_shift+4], secd +%endif + mov [pri_shift+0], pridmpq + mov [sec_shift+0], tmpq + lea tmpq, [px] +%if WIN64 + movaps r4m, m9 + movaps r6m, m10 +%elif ARCH_X86_32 + mov pridmpd, [rsp+24] +%endif +%rep %1*%2/8 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).pri_sec +%endrep +%if WIN64 + movaps m9, r4m + movaps m10, r6m +%endif + jmp .end +.pri_only: + sub tmpd, pridmpd + cmovs tmpd, secd +%if ARCH_X86_32 + mov pridmpd, [rsp+24] + mov [pri_shift+4], secd +%endif + mov [pri_shift+0], tmpq + lea tmpq, [px] +%rep %1*%2/8 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).pri +%endrep +.end: + RET +.sec_only: + mov tmpd, r8m ; damping + movd m6, r6m + tzcnt secd, secd + mov dird, r7m + pshufb m6, m7 + sub tmpd, secd + lea dirq, [base+dir_table+dirq*2] +%if ARCH_X86_32 + mov [sec_shift+4], prid +%endif + mov [sec_shift+0], tmpq + lea tmpq, [px] +%rep %1*%2/8 + call mangle(private_prefix %+ _cdef_filter_%1x%1_16bpc %+ SUFFIX).sec +%endrep + jmp .end +%if %1 == %2 + %if ARCH_X86_64 + DEFINE_ARGS dst, stride, _, tmp, off, pri, _, dir + %else + DEFINE_ARGS dst, stride, tmp, off, pri, _, dir + %endif +ALIGN function_align +.pri: + movsx offq, byte [dirq+4] ; off_k0 +%if %1 == 4 + movq m1, [dstq+strideq*0] + movhps m1, [dstq+strideq*1] + movq m2, [tmpq+offq+32*0] ; k0p0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k0p1 + movhps m3, [tmpq+offq+32*1] +%else + mova m1, [dstq] + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+5] ; off_k1 + psubw m2, m1 ; diff_k0p0 + psubw m3, m1 ; diff_k0p1 + pabsw m4, m2 ; adiff_k0p0 + psrlw m5, m4, [pri_shift+gprsize] + psubusw m0, m6, m5 + pabsw m5, m3 ; adiff_k0p1 + pminsw m0, m4 + psrlw m4, m5, [pri_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0p0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k1p0 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k1p1 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + psubw m4, m1 ; diff_k1p0 + psubw m5, m1 ; diff_k1p1 + psignw m2, m3 ; constrain(diff_k0p1) + pabsw m3, m4 ; adiff_k1p0 + paddw m0, m2 ; constrain(diff_k0) + psrlw m2, m3, [pri_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1p1 + pminsw m7, m3 + psrlw m3, m2, [pri_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1p0) + psubusw m4, m6, m3 + pminsw m4, m2 + psignw m4, m5 ; constrain(diff_k1p1) + paddw m7, m4 ; constrain(diff_k1) + pmullw m0, [priq+16*0] ; pri_tap_k0 + pmullw m7, [priq+16*1] ; pri_tap_k1 + paddw m0, m7 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + paddw m0, m1 +%if %1 == 4 + add tmpq, 32*2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] +%else + add tmpq, 32 + mova [dstq], m0 + add dstq, strideq +%endif + ret +ALIGN function_align +.sec: + movsx offq, byte [dirq+8] ; off1_k0 +%if %1 == 4 + movq m1, [dstq+strideq*0] + movhps m1, [dstq+strideq*1] + movq m2, [tmpq+offq+32*0] ; k0s0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k0s1 + movhps m3, [tmpq+offq+32*1] +%else + mova m1, [dstq] + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+0] ; off2_k0 + psubw m2, m1 ; diff_k0s0 + psubw m3, m1 ; diff_k0s1 + pabsw m4, m2 ; adiff_k0s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m0, m6, m5 + pabsw m5, m3 ; adiff_k0s1 + pminsw m0, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k0s2 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k0s3 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + movsx offq, byte [dirq+9] ; off1_k1 + psubw m4, m1 ; diff_k0s2 + psubw m5, m1 ; diff_k0s3 + psignw m2, m3 ; constrain(diff_k0s1) + pabsw m3, m4 ; adiff_k0s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k0s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k0s2) + psubusw m4, m6, m3 + pminsw m4, m2 +%if %1 == 4 + movq m2, [tmpq+offq+32*0] ; k1s0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k1s1 + movhps m3, [tmpq+offq+32*1] +%else + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+1] ; off2_k1 + paddw m0, m7 + psignw m4, m5 ; constrain(diff_k0s3) + paddw m0, m4 ; constrain(diff_k0) + psubw m2, m1 ; diff_k1s0 + psubw m3, m1 ; diff_k1s1 + paddw m0, m0 ; sec_tap_k0 + pabsw m4, m2 ; adiff_k1s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m7, m6, m5 + pabsw m5, m3 ; adiff_k1s1 + pminsw m7, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m7, m2 ; constrain(diff_k1s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k1s2 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k1s3 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + paddw m0, m7 + psubw m4, m1 ; diff_k1s2 + psubw m5, m1 ; diff_k1s3 + psignw m2, m3 ; constrain(diff_k1s1) + pabsw m3, m4 ; adiff_k1s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1s2) + psubusw m4, m6, m3 + pminsw m4, m2 + paddw m0, m7 + psignw m4, m5 ; constrain(diff_k1s3) + paddw m0, m4 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + paddw m0, m1 +%if %1 == 4 + add tmpq, 32*2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] +%else + add tmpq, 32 + mova [dstq], m0 + add dstq, strideq +%endif + ret +ALIGN function_align +.pri_sec: + movsx offq, byte [dirq+8] ; off2_k0 +%if %1 == 4 + movq m1, [dstq+strideq*0] + movhps m1, [dstq+strideq*1] + movq m2, [tmpq+offq+32*0] ; k0s0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k0s1 + movhps m3, [tmpq+offq+32*1] +%else + mova m1, [dstq] + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+0] ; off3_k0 + pabsw m4, m2 +%if ARCH_X86_64 + pabsw m10, m3 + pmaxsw m9, m2, m3 + pminsw m10, m4 +%else + pabsw m7, m3 + pmaxsw m5, m2, m3 + pminsw m4, m7 + mova m9, m5 + mova m10, m4 +%endif + psubw m2, m1 ; diff_k0s0 + psubw m3, m1 ; diff_k0s1 + pabsw m4, m2 ; adiff_k0s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m0, m6, m5 + pabsw m5, m3 ; adiff_k0s1 + pminsw m0, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m0, m2 ; constrain(diff_k0s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k0s2 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k0s3 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + movsx offq, byte [dirq+9] ; off2_k1 + pabsw m7, m4 + psignw m2, m3 + pabsw m3, m5 ; constrain(diff_k0s1) +%if ARCH_X86_64 + pmaxsw m9, m4 + pminsw m10, m7 + pmaxsw m9, m5 + pminsw m10, m3 +%else + pminsw m7, m10 + pminsw m7, m3 + pmaxsw m3, m9, m4 + pmaxsw m3, m5 + mova m10, m7 + mova m9, m3 +%endif + psubw m4, m1 ; diff_k0s2 + psubw m5, m1 ; diff_k0s3 + paddw m0, m2 + pabsw m3, m4 ; adiff_k0s2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k0s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k0s2) + psubusw m4, m6, m3 + pminsw m4, m2 +%if %1 == 4 + movq m2, [tmpq+offq+32*0] ; k1s0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k1s1 + movhps m3, [tmpq+offq+32*1] +%else + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+1] ; off3_k1 + paddw m0, m7 + pabsw m7, m2 + psignw m4, m5 ; constrain(diff_k0s3) + pabsw m5, m3 +%if ARCH_X86_64 + pmaxsw m9, m2 + pminsw m10, m7 + pmaxsw m9, m3 + pminsw m10, m5 +%else + pminsw m7, m10 + pminsw m7, m5 + pmaxsw m5, m9, m2 + pmaxsw m5, m3 + mova m10, m7 + mova m9, m5 +%endif + paddw m0, m4 ; constrain(diff_k0) + psubw m2, m1 ; diff_k1s0 + psubw m3, m1 ; diff_k1s1 + paddw m0, m0 ; sec_tap_k0 + pabsw m4, m2 ; adiff_k1s0 + psrlw m5, m4, [sec_shift+gprsize] + psubusw m7, m6, m5 + pabsw m5, m3 ; adiff_k1s1 + pminsw m7, m4 + psrlw m4, m5, [sec_shift+gprsize] + psignw m7, m2 ; constrain(diff_k1s0) + psubusw m2, m6, m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k1s2 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k1s3 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + movsx offq, byte [dirq+4] ; off1_k0 + paddw m0, m7 + pabsw m7, m4 + psignw m2, m3 ; constrain(diff_k1s1) + pabsw m3, m5 +%if ARCH_X86_64 + pmaxsw m9, m4 + pminsw m10, m7 + pmaxsw m9, m5 + pminsw m10, m3 +%else + pminsw m7, m10 + pminsw m7, m3 + pmaxsw m3, m9, m4 + pmaxsw m3, m5 + mova m10, m7 + mova m9, m3 +%endif + psubw m4, m1 ; diff_k1s2 + psubw m5, m1 ; diff_k1s3 + pabsw m3, m4 ; adiff_k1s2 + paddw m0, m2 + psrlw m2, m3, [sec_shift+gprsize] + psubusw m7, m6, m2 + pabsw m2, m5 ; adiff_k1s3 + pminsw m7, m3 + psrlw m3, m2, [sec_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1s2) + psubusw m4, m6, m3 + pminsw m4, m2 + paddw m0, m7 +%if %1 == 4 + movq m2, [tmpq+offq+32*0] ; k0p0 + movhps m2, [tmpq+offq+32*1] + neg offq + movq m3, [tmpq+offq+32*0] ; k0p1 + movhps m3, [tmpq+offq+32*1] +%else + movu m2, [tmpq+offq] + neg offq + movu m3, [tmpq+offq] +%endif + movsx offq, byte [dirq+5] ; off1_k1 + pabsw m7, m2 + psignw m4, m5 ; constrain(diff_k1s3) + pabsw m5, m3 +%if ARCH_X86_64 + pmaxsw m9, m2 + pminsw m10, m7 + pmaxsw m9, m3 + pminsw m10, m5 +%else + pminsw m7, m10 + pminsw m7, m5 + pmaxsw m5, m9, m2 + pmaxsw m5, m3 + mova m10, m7 + mova m9, m5 +%endif + psubw m2, m1 ; diff_k0p0 + psubw m3, m1 ; diff_k0p1 + paddw m0, m4 + pabsw m4, m2 ; adiff_k0p0 + psrlw m5, m4, [pri_shift+gprsize] + psubusw m7, [rsp+gprsize], m5 + pabsw m5, m3 ; adiff_k0p1 + pminsw m7, m4 + psrlw m4, m5, [pri_shift+gprsize] + psignw m7, m2 ; constrain(diff_k0p0) + psubusw m2, [rsp+gprsize], m4 + pminsw m2, m5 +%if %1 == 4 + movq m4, [tmpq+offq+32*0] ; k1p0 + movhps m4, [tmpq+offq+32*1] + neg offq + movq m5, [tmpq+offq+32*0] ; k1p1 + movhps m5, [tmpq+offq+32*1] +%else + movu m4, [tmpq+offq] + neg offq + movu m5, [tmpq+offq] +%endif + psignw m2, m3 ; constrain(diff_k0p1) + pabsw m3, m4 + paddw m7, m2 ; constrain(diff_k0) + pabsw m2, m5 +%if ARCH_X86_64 + pmaxsw m9, m4 + pminsw m10, m3 + pmaxsw m9, m5 + pminsw m10, m2 +%else + pminsw m3, m10 + pminsw m3, m2 + pmaxsw m2, m9, m4 + pmaxsw m2, m5 + mova m10, m3 + mova m9, m2 +%endif + psubw m4, m1 ; diff_k1p0 + psubw m5, m1 ; diff_k1p1 + pabsw m3, m4 ; adiff_k1p0 + pmullw m7, [priq+16*0] ; pri_tap_k0 + paddw m0, m7 + psrlw m2, m3, [pri_shift+gprsize] + psubusw m7, [rsp+16*0+gprsize], m2 + pabsw m2, m5 ; adiff_k1p1 + pminsw m7, m3 + psrlw m3, m2, [pri_shift+gprsize] + psignw m7, m4 ; constrain(diff_k1p0) + psubusw m4, [rsp+16*0+gprsize], m3 + pminsw m4, m2 + psignw m4, m5 ; constrain(diff_k1p1) + paddw m7, m4 ; constrain(diff_k1) + pmullw m7, [priq+16*1] ; pri_tap_k1 + paddw m0, m7 ; sum + psraw m2, m0, 15 + paddw m0, m2 + pmulhrsw m0, m8 + paddw m0, m1 +%if ARCH_X86_64 + pmaxsw m9, m1 + pminsw m0, m9 +%else + pmaxsw m2, m9, m1 + pminsw m0, m2 +%endif + pminsw m1, m10 + pmaxsw m0, m1 +%if %1 == 4 + add tmpq, 32*2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] +%else + add tmpq, 32 + mova [dstq], m0 + add dstq, strideq +%endif + ret +%endif +%endmacro + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal cdef_filter_4x4_16bpc, 5, 9, 9, 32*10, dst, stride, left, top, bot, \ + pri, sec, edge + %define px rsp+32*4 +%else +cglobal cdef_filter_4x4_16bpc, 2, 7, 8, -32*11, dst, stride, edge, top, left + %define botq topq + %define px rsp+32*5 +%endif + %define base t0-dir_table + %define pri_shift px-16*6 + %define sec_shift px-16*5 + mov edged, r9m + LEA t0, dir_table + movu m0, [dstq+strideq*0] + movu m1, [dstq+strideq*1] + lea t1, [dstq+strideq*2] + movu m2, [t1 +strideq*0] + movu m3, [t1 +strideq*1] + movddup m7, [base+pw_m16384] + mova [px+32*0+0], m0 + mova [px+32*1+0], m1 + mova [px+32*2+0], m2 + mova [px+32*3+0], m3 + test edgeb, 4 ; HAVE_TOP + jz .no_top + movifnidn topq, topmp + movu m0, [topq+strideq*0] + movu m1, [topq+strideq*1] + mova [px-32*2+0], m0 + mova [px-32*1+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd m0, [topq+strideq*0-4] + movd m1, [topq+strideq*1-4] + movd [px-32*2-4], m0 + movd [px-32*1-4], m1 + jmp .top_done +.no_top: + mova [px-32*2+0], m7 + mova [px-32*1+0], m7 +.top_no_left: + movd [px-32*2-4], m7 + movd [px-32*1-4], m7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movifnidn botq, r4mp + movu m0, [botq+strideq*0] + movu m1, [botq+strideq*1] + mova [px+32*4+0], m0 + mova [px+32*5+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd m0, [botq+strideq*0-4] + movd m1, [botq+strideq*1-4] + movd [px+32*4-4], m0 + movd [px+32*5-4], m1 + jmp .bottom_done +.no_bottom: + mova [px+32*4+0], m7 + mova [px+32*5+0], m7 +.bottom_no_left: + movd [px+32*4-4], m7 + movd [px+32*5-4], m7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movifnidn leftq, r2mp + movd m0, [leftq+4*0] + movd m1, [leftq+4*1] + movd m2, [leftq+4*2] + movd m3, [leftq+4*3] + movd [px+32*0-4], m0 + movd [px+32*1-4], m1 + movd [px+32*2-4], m2 + movd [px+32*3-4], m3 + jmp .left_done +.no_left: + REPX {movd [px+32*x-4], m7}, 0, 1, 2, 3 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+32*x+8], m7}, -2, -1, 0, 1, 2, 3, 4, 5 +.padding_done: + CDEF_FILTER 4, 4 + +%if ARCH_X86_64 +cglobal cdef_filter_4x8_16bpc, 5, 9, 9, 32*14, dst, stride, left, top, bot, \ + pri, sec, edge +%else +cglobal cdef_filter_4x8_16bpc, 2, 7, 8, -32*15, dst, stride, edge, top, left +%endif + mov edged, r9m + LEA t0, dir_table + movu m0, [dstq+strideq*0] + movu m1, [dstq+strideq*1] + lea t1, [dstq+strideq*2] + movu m2, [t1 +strideq*0] + movu m3, [t1 +strideq*1] + lea t1, [t1 +strideq*2] + movu m4, [t1 +strideq*0] + movu m5, [t1 +strideq*1] + lea t1, [t1 +strideq*2] + movu m6, [t1 +strideq*0] + movu m7, [t1 +strideq*1] + mova [px+32*0+0], m0 + mova [px+32*1+0], m1 + mova [px+32*2+0], m2 + mova [px+32*3+0], m3 + mova [px+32*4+0], m4 + mova [px+32*5+0], m5 + mova [px+32*6+0], m6 + mova [px+32*7+0], m7 + movddup m7, [base+pw_m16384] + test edgeb, 4 ; HAVE_TOP + jz .no_top + movifnidn topq, topmp + movu m0, [topq+strideq*0] + movu m1, [topq+strideq*1] + mova [px-32*2+0], m0 + mova [px-32*1+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd m0, [topq+strideq*0-4] + movd m1, [topq+strideq*1-4] + movd [px-32*2-4], m0 + movd [px-32*1-4], m1 + jmp .top_done +.no_top: + mova [px-32*2+0], m7 + mova [px-32*1+0], m7 +.top_no_left: + movd [px-32*2-4], m7 + movd [px-32*1-4], m7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movifnidn botq, r4mp + movu m0, [botq+strideq*0] + movu m1, [botq+strideq*1] + mova [px+32*8+0], m0 + mova [px+32*9+0], m1 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd m0, [botq+strideq*0-4] + movd m1, [botq+strideq*1-4] + movd [px+32*8-4], m0 + movd [px+32*9-4], m1 + jmp .bottom_done +.no_bottom: + mova [px+32*8+0], m7 + mova [px+32*9+0], m7 +.bottom_no_left: + movd [px+32*8-4], m7 + movd [px+32*9-4], m7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movifnidn leftq, r2mp + movd m0, [leftq+4*0] + movd m1, [leftq+4*1] + movd m2, [leftq+4*2] + movd m3, [leftq+4*3] + movd [px+32*0-4], m0 + movd [px+32*1-4], m1 + movd [px+32*2-4], m2 + movd [px+32*3-4], m3 + movd m0, [leftq+4*4] + movd m1, [leftq+4*5] + movd m2, [leftq+4*6] + movd m3, [leftq+4*7] + movd [px+32*4-4], m0 + movd [px+32*5-4], m1 + movd [px+32*6-4], m2 + movd [px+32*7-4], m3 + jmp .left_done +.no_left: + REPX {movd [px+32*x-4], m7}, 0, 1, 2, 3, 4, 5, 6, 7 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+32*x+8], m7}, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +.padding_done: + CDEF_FILTER 4, 8 + +%if ARCH_X86_64 +cglobal cdef_filter_8x8_16bpc, 5, 9, 9, 32*14, dst, stride, left, top, bot, \ + pri, sec, edge +%else +cglobal cdef_filter_8x8_16bpc, 2, 7, 8, -32*15, dst, stride, edge, top, left +%endif + mov edged, r9m + LEA t0, dir_table + mova m0, [dstq+strideq*0+ 0] + movd m1, [dstq+strideq*0+16] + mova m2, [dstq+strideq*1+ 0] + movd m3, [dstq+strideq*1+16] + lea t1, [dstq+strideq*2] + mova m4, [t1 +strideq*0+ 0] + movd m5, [t1 +strideq*0+16] + mova m6, [t1 +strideq*1+ 0] + movd m7, [t1 +strideq*1+16] + lea t1, [t1 +strideq*2] + mova [px+32*0+ 0], m0 + movd [px+32*0+16], m1 + mova [px+32*1+ 0], m2 + movd [px+32*1+16], m3 + mova [px+32*2+ 0], m4 + movd [px+32*2+16], m5 + mova [px+32*3+ 0], m6 + movd [px+32*3+16], m7 + mova m0, [t1 +strideq*0+ 0] + movd m1, [t1 +strideq*0+16] + mova m2, [t1 +strideq*1+ 0] + movd m3, [t1 +strideq*1+16] + lea t1, [t1 +strideq*2] + mova m4, [t1 +strideq*0+ 0] + movd m5, [t1 +strideq*0+16] + mova m6, [t1 +strideq*1+ 0] + movd m7, [t1 +strideq*1+16] + mova [px+32*4+ 0], m0 + movd [px+32*4+16], m1 + mova [px+32*5+ 0], m2 + movd [px+32*5+16], m3 + mova [px+32*6+ 0], m4 + movd [px+32*6+16], m5 + mova [px+32*7+ 0], m6 + movd [px+32*7+16], m7 + movddup m7, [base+pw_m16384] + test edgeb, 4 ; HAVE_TOP + jz .no_top + movifnidn topq, topmp + mova m0, [topq+strideq*0+ 0] + mova m1, [topq+strideq*0+16] + mova m2, [topq+strideq*1+ 0] + mova m3, [topq+strideq*1+16] + mova [px-32*2+ 0], m0 + movd [px-32*2+16], m1 + mova [px-32*1+ 0], m2 + movd [px-32*1+16], m3 + test edgeb, 1 ; HAVE_LEFT + jz .top_no_left + movd m0, [topq+strideq*0-4] + movd m1, [topq+strideq*1-4] + movd [px-32*2-4], m0 + movd [px-32*1-4], m1 + jmp .top_done +.no_top: + mova [px-32*2+ 0], m7 + movd [px-32*2+16], m7 + mova [px-32*1+ 0], m7 + movd [px-32*1+16], m7 +.top_no_left: + movd [px-32*2- 4], m7 + movd [px-32*1- 4], m7 +.top_done: + test edgeb, 8 ; HAVE_BOTTOM + jz .no_bottom + movifnidn botq, r4mp + mova m0, [botq+strideq*0+ 0] + movd m1, [botq+strideq*0+16] + mova m2, [botq+strideq*1+ 0] + movd m3, [botq+strideq*1+16] + mova [px+32*8+ 0], m0 + movd [px+32*8+16], m1 + mova [px+32*9+ 0], m2 + movd [px+32*9+16], m3 + test edgeb, 1 ; HAVE_LEFT + jz .bottom_no_left + movd m0, [botq+strideq*0-4] + movd m1, [botq+strideq*1-4] + movd [px+32*8- 4], m0 + movd [px+32*9- 4], m1 + jmp .bottom_done +.no_bottom: + mova [px+32*8+ 0], m7 + movd [px+32*8+16], m7 + mova [px+32*9+ 0], m7 + movd [px+32*9+16], m7 +.bottom_no_left: + movd [px+32*8- 4], m7 + movd [px+32*9- 4], m7 +.bottom_done: + test edgeb, 1 ; HAVE_LEFT + jz .no_left + movifnidn leftq, r2mp + movd m0, [leftq+4*0] + movd m1, [leftq+4*1] + movd m2, [leftq+4*2] + movd m3, [leftq+4*3] + movd [px+32*0- 4], m0 + movd [px+32*1- 4], m1 + movd [px+32*2- 4], m2 + movd [px+32*3- 4], m3 + movd m0, [leftq+4*4] + movd m1, [leftq+4*5] + movd m2, [leftq+4*6] + movd m3, [leftq+4*7] + movd [px+32*4- 4], m0 + movd [px+32*5- 4], m1 + movd [px+32*6- 4], m2 + movd [px+32*7- 4], m3 + jmp .left_done +.no_left: + REPX {movd [px+32*x- 4], m7}, 0, 1, 2, 3, 4, 5, 6, 7 +.left_done: + test edgeb, 2 ; HAVE_RIGHT + jnz .padding_done + REPX {movd [px+32*x+16], m7}, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +.padding_done: + CDEF_FILTER 8, 8 + +%macro CDEF_DIR 0 +%if ARCH_X86_64 +cglobal cdef_dir_16bpc, 4, 7, 16, src, stride, var, bdmax + lea r6, [dir_shift] + shr bdmaxd, 11 ; 0 for 10bpc, 1 for 12bpc + movddup m7, [r6+bdmaxq*8] + lea r6, [strideq*3] + mova m0, [srcq+strideq*0] + mova m1, [srcq+strideq*1] + mova m2, [srcq+strideq*2] + mova m3, [srcq+r6 ] + lea srcq, [srcq+strideq*4] + mova m4, [srcq+strideq*0] + mova m5, [srcq+strideq*1] + mova m6, [srcq+strideq*2] + REPX {pmulhuw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhuw m7, [srcq+r6 ] + pxor m8, m8 + packuswb m9, m0, m1 + packuswb m10, m2, m3 + packuswb m11, m4, m5 + packuswb m12, m6, m7 + REPX {psadbw x, m8}, m9, m10, m11, m12 + packssdw m9, m10 + packssdw m11, m12 + packssdw m9, m11 + jmp mangle(private_prefix %+ _cdef_dir_8bpc %+ SUFFIX).main +%else +cglobal cdef_dir_16bpc, 2, 4, 8, 96, src, stride, var, bdmax + mov bdmaxd, bdmaxm + LEA r2, dir_shift + shr bdmaxd, 11 + movddup m7, [r2+bdmaxq*8] + lea r3, [strideq*3] + pmulhuw m3, m7, [srcq+strideq*0] + pmulhuw m4, m7, [srcq+strideq*1] + pmulhuw m5, m7, [srcq+strideq*2] + pmulhuw m6, m7, [srcq+r3 ] + movddup m1, [r2-dir_shift+pw_128] + lea srcq, [srcq+strideq*4] + pxor m0, m0 + packuswb m2, m3, m4 + psubw m3, m1 + psubw m4, m1 + mova [esp+0x00], m3 + mova [esp+0x10], m4 + packuswb m3, m5, m6 + psadbw m2, m0 + psadbw m3, m0 + psubw m5, m1 + psubw m6, m1 + packssdw m2, m3 + mova [esp+0x20], m5 + mova [esp+0x50], m6 + pmulhuw m4, m7, [srcq+strideq*0] + pmulhuw m5, m7, [srcq+strideq*1] + pmulhuw m6, m7, [srcq+strideq*2] + pmulhuw m7, [srcq+r3 ] + packuswb m3, m4, m5 + packuswb m1, m6, m7 + psadbw m3, m0 + psadbw m1, m0 + packssdw m3, m1 + movddup m1, [r2-dir_shift+pw_128] + LEA r2, shufw_6543210x + jmp mangle(private_prefix %+ _cdef_dir_8bpc %+ SUFFIX).main +%endif +%endmacro + +INIT_XMM ssse3 +CDEF_DIR + +INIT_XMM sse4 +CDEF_DIR diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1772 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +%macro JMP_TABLE 2-* + %xdefine %1_jmptable %%table + %xdefine %%base mangle(private_prefix %+ _%1_avx2) + %%table: + %rep %0 - 1 + dd %%base %+ .%2 - %%table + %rotate 1 + %endrep +%endmacro + +%macro CDEF_FILTER_JMP_TABLE 1 +JMP_TABLE cdef_filter_%1_8bpc, \ + d6k0, d6k1, d7k0, d7k1, \ + d0k0, d0k1, d1k0, d1k1, d2k0, d2k1, d3k0, d3k1, \ + d4k0, d4k1, d5k0, d5k1, d6k0, d6k1, d7k0, d7k1, \ + d0k0, d0k1, d1k0, d1k1 +%endmacro + +SECTION_RODATA 32 + +pd_47130256: dd 4, 7, 1, 3, 0, 2, 5, 6 +blend_4x4: dd 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00 + dd 0x80, 0x00, 0x00 +blend_4x8_0: dd 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +blend_4x8_1: dd 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + dd 0x00, 0x00 +blend_4x8_2: dd 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 + dd 0x0000 +blend_4x8_3: dd 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 + dd 0x0000, 0x0000 +blend_8x8_0: dq 0x00, 0x00, 0x80, 0x80, 0x80, 0x80 +blend_8x8_1: dq 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000 +div_table: dd 840, 420, 280, 210, 168, 140, 120, 105, 420, 210, 140, 105 +shufw_6543210x:db 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15 +shufb_lohi: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 +pw_128: times 2 dw 128 +pw_2048: times 2 dw 2048 +tap_table: ; masks for 8 bit shifts + db 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 + ; weights + db 4, 2, 3, 3, 2, 1 + db -1 * 16 + 1, -2 * 16 + 2 + db 0 * 16 + 1, -1 * 16 + 2 + db 0 * 16 + 1, 0 * 16 + 2 + db 0 * 16 + 1, 1 * 16 + 2 + db 1 * 16 + 1, 2 * 16 + 2 + db 1 * 16 + 0, 2 * 16 + 1 + db 1 * 16 + 0, 2 * 16 + 0 + db 1 * 16 + 0, 2 * 16 - 1 + ; the last 6 are repeats of the first 6 so we don't need to & 7 + db -1 * 16 + 1, -2 * 16 + 2 + db 0 * 16 + 1, -1 * 16 + 2 + db 0 * 16 + 1, 0 * 16 + 2 + db 0 * 16 + 1, 1 * 16 + 2 + db 1 * 16 + 1, 2 * 16 + 2 + db 1 * 16 + 0, 2 * 16 + 1 + +CDEF_FILTER_JMP_TABLE 4x4 +CDEF_FILTER_JMP_TABLE 4x8 +CDEF_FILTER_JMP_TABLE 8x8 + +SECTION .text + +%macro PREP_REGS 2 ; w, h + ; off1/2/3[k] [6 total] from [tapq+12+(dir+0/2/6)*2+k] + mov dird, r7m + lea tableq, [cdef_filter_%1x%2_8bpc_jmptable] + lea dirq, [tableq+dirq*2*4] +%if %1 == 4 + %if %2 == 4 + DEFINE_ARGS dst, stride, left, top, bot, pri, sec, \ + table, dir, dirjmp, stride3, k + %else + DEFINE_ARGS dst, stride, left, top, bot, pri, sec, \ + table, dir, dirjmp, dst4, stride3, k + lea dst4q, [dstq+strideq*4] + %endif +%else + DEFINE_ARGS dst, stride, h, top1, bot, pri, sec, \ + table, dir, dirjmp, top2, stride3, k + mov hq, -8 + lea top1q, [top1q+strideq*0] + lea top2q, [top1q+strideq*1] +%endif +%if %1 == 4 + lea stride3q, [strideq*3] +%endif +%endmacro + +%macro LOAD_BLOCK 2-3 0 ; w, h, init_min_max + mov kd, 1 + pxor m15, m15 ; sum +%if %2 == 8 + pxor m12, m12 + %if %1 == 4 + movd xm4, [dstq +strideq*0] + movd xm6, [dstq +strideq*1] + movd xm5, [dstq +strideq*2] + movd xm7, [dstq +stride3q ] + vinserti128 m4, [dst4q+strideq*0], 1 + vinserti128 m6, [dst4q+strideq*1], 1 + vinserti128 m5, [dst4q+strideq*2], 1 + vinserti128 m7, [dst4q+stride3q ], 1 + punpckldq m4, m6 + punpckldq m5, m7 + %else + movq xm4, [dstq+strideq*0] + movq xm5, [dstq+strideq*1] + vinserti128 m4, [dstq+strideq*2], 1 + vinserti128 m5, [dstq+stride3q ], 1 + %endif + punpcklqdq m4, m5 +%else + movd xm4, [dstq+strideq*0] + movd xm5, [dstq+strideq*1] + vinserti128 m4, [dstq+strideq*2], 1 + vinserti128 m5, [dstq+stride3q ], 1 + punpckldq m4, m5 +%endif +%if %3 == 1 + mova m7, m4 ; min + mova m8, m4 ; max +%endif +%endmacro + +%macro ACCUMULATE_TAP_BYTE 7-8 0 ; tap_offset, shift, mask, strength + ; mul_tap, w, h, clip + ; load p0/p1 + movsxd dirjmpq, [dirq+kq*4+%1*2*4] + add dirjmpq, tableq + call dirjmpq + +%if %8 == 1 + pmaxub m7, m5 + pminub m8, m5 + pmaxub m7, m6 + pminub m8, m6 +%endif + + ; accumulate sum[m15] over p0/p1 +%if %7 == 4 + punpcklbw m5, m6 + punpcklbw m6, m4, m4 + psubusb m9, m5, m6 + psubusb m5, m6, m5 + por m9, m5 ; abs_diff_p01(p01 - px) + pcmpeqb m5, m9 + por m5, %5 + psignb m6, %5, m5 + psrlw m5, m9, %2 ; emulate 8-bit shift + pand m5, %3 + psubusb m5, %4, m5 + pminub m5, m9 + pmaddubsw m5, m6 + paddw m15, m5 +%else + psubusb m9, m5, m4 + psubusb m5, m4, m5 + psubusb m11, m6, m4 + psubusb m6, m4, m6 + por m9, m5 ; abs_diff_p0(p0 - px) + por m11, m6 ; abs_diff_p1(p1 - px) + pcmpeqb m5, m9 + pcmpeqb m6, m11 + punpckhbw m10, m9, m11 + punpcklbw m9, m11 + por m5, %5 + por m11, m6, %5 + punpckhbw m6, m5, m11 + punpcklbw m5, m11 + psignb m11, %5, m6 + psrlw m6, m10, %2 ; emulate 8-bit shift + pand m6, %3 + psubusb m6, %4, m6 + pminub m6, m10 + pmaddubsw m6, m11 + paddw m12, m6 + psignb m11, %5, m5 + psrlw m5, m9, %2 ; emulate 8-bit shift + pand m5, %3 + psubusb m5, %4, m5 + pminub m5, m9 + pmaddubsw m5, m11 + paddw m15, m5 +%endif +%endmacro + +%macro ADJUST_PIXEL 4-5 0 ; w, h, zero, pw_2048, clip +%if %2 == 4 + %if %5 == 1 + punpcklbw m4, %3 + %endif + pcmpgtw %3, m15 + paddw m15, %3 + pmulhrsw m15, %4 + %if %5 == 0 + packsswb m15, m15 + paddb m4, m15 + %else + paddw m4, m15 + packuswb m4, m4 ; clip px in [0x0,0xff] + pminub m4, m7 + pmaxub m4, m8 + %endif + vextracti128 xm5, m4, 1 + movd [dstq+strideq*0], xm4 + movd [dstq+strideq*2], xm5 + pextrd [dstq+strideq*1], xm4, 1 + pextrd [dstq+stride3q ], xm5, 1 +%else + pcmpgtw m6, %3, m12 + pcmpgtw m5, %3, m15 + paddw m12, m6 + paddw m15, m5 + %if %5 == 1 + punpckhbw m5, m4, %3 + punpcklbw m4, %3 + %endif + pmulhrsw m12, %4 + pmulhrsw m15, %4 + %if %5 == 0 + packsswb m15, m12 + paddb m4, m15 + %else + paddw m5, m12 + paddw m4, m15 + packuswb m4, m5 ; clip px in [0x0,0xff] + pminub m4, m7 + pmaxub m4, m8 + %endif + vextracti128 xm5, m4, 1 + %if %1 == 4 + movd [dstq +strideq*0], xm4 + movd [dst4q+strideq*0], xm5 + pextrd [dstq +strideq*1], xm4, 1 + pextrd [dst4q+strideq*1], xm5, 1 + pextrd [dstq +strideq*2], xm4, 2 + pextrd [dst4q+strideq*2], xm5, 2 + pextrd [dstq +stride3q ], xm4, 3 + pextrd [dst4q+stride3q ], xm5, 3 + %else + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*2], xm5 + movhps [dstq+strideq*1], xm4 + movhps [dstq+stride3q ], xm5 + %endif +%endif +%endmacro + +%macro BORDER_PREP_REGS 2 ; w, h + ; off1/2/3[k] [6 total] from [tapq+12+(dir+0/2/6)*2+k] + mov dird, r7m + lea dirq, [tableq+dirq*2+14] +%if %1*%2*2/mmsize > 1 + %if %1 == 4 + DEFINE_ARGS dst, stride, k, dir, stk, pri, sec, stride3, h, off + %else + DEFINE_ARGS dst, stride, k, dir, stk, pri, sec, h, off + %endif + mov hd, %1*%2*2/mmsize +%else + DEFINE_ARGS dst, stride, k, dir, stk, pri, sec, stride3, off +%endif + lea stkq, [px] + pxor m11, m11 +%endmacro + +%macro BORDER_LOAD_BLOCK 2-3 0 ; w, h, init_min_max + mov kd, 1 +%if %1 == 4 + movq xm4, [stkq+32*0] + movhps xm4, [stkq+32*1] + movq xm5, [stkq+32*2] + movhps xm5, [stkq+32*3] + vinserti128 m4, xm5, 1 +%else + mova xm4, [stkq+32*0] ; px + vinserti128 m4, [stkq+32*1], 1 +%endif + pxor m15, m15 ; sum +%if %3 == 1 + mova m7, m4 ; max + mova m8, m4 ; min +%endif +%endmacro + +%macro ACCUMULATE_TAP_WORD 6-7 0 ; tap_offset, shift, mask, strength + ; mul_tap, w, clip + ; load p0/p1 + movsx offq, byte [dirq+kq+%1] ; off1 +%if %6 == 4 + movq xm5, [stkq+offq*2+32*0] ; p0 + movq xm6, [stkq+offq*2+32*2] + movhps xm5, [stkq+offq*2+32*1] + movhps xm6, [stkq+offq*2+32*3] + vinserti128 m5, xm6, 1 +%else + movu xm5, [stkq+offq*2+32*0] ; p0 + vinserti128 m5, [stkq+offq*2+32*1], 1 +%endif + neg offq ; -off1 +%if %6 == 4 + movq xm6, [stkq+offq*2+32*0] ; p1 + movq xm9, [stkq+offq*2+32*2] + movhps xm6, [stkq+offq*2+32*1] + movhps xm9, [stkq+offq*2+32*3] + vinserti128 m6, xm9, 1 +%else + movu xm6, [stkq+offq*2+32*0] ; p1 + vinserti128 m6, [stkq+offq*2+32*1], 1 +%endif +%if %7 == 1 + ; out of bounds values are set to a value that is a both a large unsigned + ; value and a negative signed value. + ; use signed max and unsigned min to remove them + pmaxsw m7, m5 ; max after p0 + pminuw m8, m5 ; min after p0 + pmaxsw m7, m6 ; max after p1 + pminuw m8, m6 ; min after p1 +%endif + + ; accumulate sum[m15] over p0/p1 + ; calculate difference before converting + psubw m5, m4 ; diff_p0(p0 - px) + psubw m6, m4 ; diff_p1(p1 - px) + + ; convert to 8-bits with signed saturation + ; saturating to large diffs has no impact on the results + packsswb m5, m6 + + ; group into pairs so we can accumulate using maddubsw + pshufb m5, m12 + pabsb m9, m5 + psignb m10, %5, m5 + psrlw m5, m9, %2 ; emulate 8-bit shift + pand m5, %3 + psubusb m5, %4, m5 + + ; use unsigned min since abs diff can equal 0x80 + pminub m5, m9 + pmaddubsw m5, m10 + paddw m15, m5 +%endmacro + +%macro BORDER_ADJUST_PIXEL 2-3 0 ; w, pw_2048, clip + pcmpgtw m9, m11, m15 + paddw m15, m9 + pmulhrsw m15, %2 + paddw m4, m15 +%if %3 == 1 + pminsw m4, m7 + pmaxsw m4, m8 +%endif + packuswb m4, m4 + vextracti128 xm5, m4, 1 +%if %1 == 4 + movd [dstq+strideq*0], xm4 + pextrd [dstq+strideq*1], xm4, 1 + movd [dstq+strideq*2], xm5 + pextrd [dstq+stride3q ], xm5, 1 +%else + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*1], xm5 +%endif +%endmacro + +%macro CDEF_FILTER 2 ; w, h +INIT_YMM avx2 +cglobal cdef_filter_%1x%2_8bpc, 5, 11, 0, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%assign stack_offset_entry stack_offset + mov edged, edgem + cmp edged, 0xf + jne .border_block + + PUSH r11 + PUSH r12 +%if %2 == 4 +%assign regs_used 13 + ALLOC_STACK 0x60, 16 + pmovzxbw xm0, [leftq+1] + vpermq m0, m0, q0110 + psrldq m1, m0, 4 + vpalignr m2, m0, m0, 12 + movu [rsp+0x10], m0 + movu [rsp+0x28], m1 + movu [rsp+0x40], m2 +%elif %1 == 4 +%assign regs_used 14 + PUSH r13 + ALLOC_STACK 8*2+%1*%2*1, 16 + pmovzxwd m0, [leftq] + mova [rsp+0x10], m0 +%else +%assign regs_used 15 + PUSH r13 + PUSH r14 + ALLOC_STACK 8*4+%1*%2*2+32, 16 + lea r11, [strideq*3] + movu xm4, [dstq+strideq*2] + pmovzxwq m0, [leftq+0] + pmovzxwq m1, [leftq+8] + vinserti128 m4, [dstq+r11], 1 + pmovzxbd m2, [leftq+1] + pmovzxbd m3, [leftq+9] + mov [rsp+16], botq + mova [rsp+0x20], m0 + mova [rsp+0x40], m1 + mova [rsp+0x60], m2 + mova [rsp+0x80], m3 + mova [rsp+0xa0], m4 + lea botq, [dstq+strideq*4] +%endif + + DEFINE_ARGS dst, stride, left, top, bot, pri, secdmp, zero, pridmp, damping + mov dampingd, r8m + xor zerod, zerod + movifnidn prid, prim + sub dampingd, 31 + movifnidn secdmpd, secdmpm + test prid, prid + jz .sec_only + movd xm0, prid + lzcnt pridmpd, prid + add pridmpd, dampingd + cmovs pridmpd, zerod + mov [rsp+0], pridmpq ; pri_shift + test secdmpd, secdmpd + jz .pri_only + movd xm1, secdmpd + lzcnt secdmpd, secdmpd + add secdmpd, dampingd + mov [rsp+8], secdmpq ; sec_shift + + DEFINE_ARGS dst, stride, left, top, bot, pri, secdmp, table, pridmp + lea tableq, [tap_table] + vpbroadcastb m13, [tableq+pridmpq] ; pri_shift_mask + vpbroadcastb m14, [tableq+secdmpq] ; sec_shift_mask + + ; pri/sec_taps[k] [4 total] + DEFINE_ARGS dst, stride, left, top, bot, pri, sec, table, dir + vpbroadcastb m0, xm0 ; pri_strength + vpbroadcastb m1, xm1 ; sec_strength + and prid, 1 + lea priq, [tableq+priq*2+8] ; pri_taps + lea secq, [tableq+12] ; sec_taps + + PREP_REGS %1, %2 +%if %1*%2 > mmsize +.v_loop: +%endif + LOAD_BLOCK %1, %2, 1 +.k_loop: + vpbroadcastb m2, [priq+kq] ; pri_taps + vpbroadcastb m3, [secq+kq] ; sec_taps + ACCUMULATE_TAP_BYTE 2, [rsp+0], m13, m0, m2, %1, %2, 1 ; dir + 0 + ACCUMULATE_TAP_BYTE 4, [rsp+8], m14, m1, m3, %1, %2, 1 ; dir + 2 + ACCUMULATE_TAP_BYTE 0, [rsp+8], m14, m1, m3, %1, %2, 1 ; dir - 2 + dec kq + jge .k_loop + + vpbroadcastd m10, [pw_2048] + pxor m9, m9 + ADJUST_PIXEL %1, %2, m9, m10, 1 +%if %1*%2 > mmsize + lea dstq, [dstq+strideq*4] + lea top1q, [rsp+0xa0] + lea top2q, [rsp+0xb0] + mov botq, [rsp+16] + add hq, 4 + jl .v_loop +%endif + RET + +.pri_only: + DEFINE_ARGS dst, stride, left, top, bot, pri, _, table, pridmp + lea tableq, [tap_table] + vpbroadcastb m13, [tableq+pridmpq] ; pri_shift_mask + ; pri/sec_taps[k] [4 total] + DEFINE_ARGS dst, stride, left, top, bot, pri, _, table, dir + vpbroadcastb m0, xm0 ; pri_strength + and prid, 1 + lea priq, [tableq+priq*2+8] ; pri_taps + PREP_REGS %1, %2 + vpbroadcastd m3, [pw_2048] + pxor m1, m1 +%if %1*%2 > mmsize +.pri_v_loop: +%endif + LOAD_BLOCK %1, %2 +.pri_k_loop: + vpbroadcastb m2, [priq+kq] ; pri_taps + ACCUMULATE_TAP_BYTE 2, [rsp+0], m13, m0, m2, %1, %2 ; dir + 0 + dec kq + jge .pri_k_loop + ADJUST_PIXEL %1, %2, m1, m3 +%if %1*%2 > mmsize + lea dstq, [dstq+strideq*4] + lea top1q, [rsp+0xa0] + lea top2q, [rsp+0xb0] + mov botq, [rsp+16] + add hq, 4 + jl .pri_v_loop +%endif + RET + +.sec_only: + DEFINE_ARGS dst, stride, left, top, bot, _, secdmp, zero, _, damping + movd xm1, secdmpd + lzcnt secdmpd, secdmpd + add secdmpd, dampingd + mov [rsp+8], secdmpq ; sec_shift + DEFINE_ARGS dst, stride, left, top, bot, _, secdmp, table + lea tableq, [tap_table] + vpbroadcastb m14, [tableq+secdmpq] ; sec_shift_mask + ; pri/sec_taps[k] [4 total] + DEFINE_ARGS dst, stride, left, top, bot, _, sec, table, dir + vpbroadcastb m1, xm1 ; sec_strength + lea secq, [tableq+12] ; sec_taps + PREP_REGS %1, %2 + vpbroadcastd m2, [pw_2048] + pxor m0, m0 +%if %1*%2 > mmsize +.sec_v_loop: +%endif + LOAD_BLOCK %1, %2 +.sec_k_loop: + vpbroadcastb m3, [secq+kq] ; sec_taps + ACCUMULATE_TAP_BYTE 4, [rsp+8], m14, m1, m3, %1, %2 ; dir + 2 + ACCUMULATE_TAP_BYTE 0, [rsp+8], m14, m1, m3, %1, %2 ; dir - 2 + dec kq + jge .sec_k_loop + ADJUST_PIXEL %1, %2, m0, m2 +%if %1*%2 > mmsize + lea dstq, [dstq+strideq*4] + lea top1q, [rsp+0xa0] + lea top2q, [rsp+0xb0] + mov botq, [rsp+16] + add hq, 4 + jl .sec_v_loop +%endif + RET + +.d0k0: +%if %1 == 4 + %if %2 == 4 + vpbroadcastq m6, [dstq+strideq*1-1] + vpbroadcastq m10, [dstq+strideq*2-1] + movd xm5, [topq+strideq*1+1] + movd xm9, [dstq+strideq*0+1] + psrldq m11, m6, 2 + psrldq m12, m10, 2 + vinserti128 m6, [dstq+stride3q -1], 1 + vinserti128 m10, [botq -1], 1 + vpblendd m5, m11, 0x10 + vpblendd m9, m12, 0x10 + movu m11, [blend_4x4+16] + punpckldq m6, m10 + punpckldq m5, m9 + vpblendvb m6, [rsp+gprsize+0x28], m11 + %else + movd xm5, [topq +strideq*1+1] + movq xm6, [dstq +strideq*1-1] + movq xm10, [dstq +stride3q -1] + movq xm11, [dst4q+strideq*1-1] + pinsrd xm5, [dstq +strideq*0+1], 1 + movhps xm6, [dstq +strideq*2-1] + movhps xm10, [dst4q+strideq*0-1] + movhps xm11, [dst4q+strideq*2-1] + psrldq xm9, xm6, 2 + shufps xm5, xm9, q2010 ; -1 +0 +1 +2 + shufps xm6, xm10, q2020 ; +1 +2 +3 +4 + psrldq xm9, xm11, 2 + psrldq xm10, 2 + shufps xm10, xm9, q2020 ; +3 +4 +5 +6 + movd xm9, [dst4q+stride3q -1] + pinsrd xm9, [botq -1], 1 + shufps xm11, xm9, q1020 ; +5 +6 +7 +8 + pmovzxbw m9, [leftq+3] + vinserti128 m6, xm11, 1 + movu m11, [blend_4x8_0+4] + vinserti128 m5, xm10, 1 + vpblendvb m6, m9, m11 + %endif +%else + lea r13, [blend_8x8_0+16] + movq xm5, [top2q +1] + vbroadcasti128 m10, [dstq+strideq*1-1] + vbroadcasti128 m11, [dstq+strideq*2-1] + movhps xm5, [dstq+strideq*0+1] + vinserti128 m6, m10, [dstq+stride3q-1], 1 + vinserti128 m9, m11, [botq -1], 1 + psrldq m10, 2 + psrldq m11, 2 + punpcklqdq m6, m9 + movu m9, [r13+hq*2*1+16*1] + punpcklqdq m10, m11 + vpblendd m5, m10, 0xF0 + vpblendvb m6, [rsp+gprsize+0x60+hq*8+64+8*1], m9 +%endif + ret +.d1k0: +.d2k0: +.d3k0: +%if %1 == 4 + %if %2 == 4 + movq xm6, [dstq+strideq*0-1] + movq xm9, [dstq+strideq*1-1] + vinserti128 m6, [dstq+strideq*2-1], 1 + vinserti128 m9, [dstq+stride3q -1], 1 + movu m11, [rsp+gprsize+0x10] + pcmpeqd m12, m12 + psrldq m5, m6, 2 + psrldq m10, m9, 2 + psrld m12, 24 + punpckldq m6, m9 + punpckldq m5, m10 + vpblendvb m6, m11, m12 + %else + movq xm6, [dstq +strideq*0-1] + movq xm9, [dstq +strideq*2-1] + movhps xm6, [dstq +strideq*1-1] + movhps xm9, [dstq +stride3q -1] + movq xm10, [dst4q+strideq*0-1] + movhps xm10, [dst4q+strideq*1-1] + psrldq xm5, xm6, 2 + psrldq xm11, xm9, 2 + shufps xm5, xm11, q2020 + movq xm11, [dst4q+strideq*2-1] + movhps xm11, [dst4q+stride3q -1] + shufps xm6, xm9, q2020 + shufps xm9, xm10, xm11, q2020 + vinserti128 m6, xm9, 1 + pmovzxbw m9, [leftq+1] + psrldq xm10, 2 + psrldq xm11, 2 + shufps xm10, xm11, q2020 + vpbroadcastd m11, [blend_4x8_0+4] + vinserti128 m5, xm10, 1 + vpblendvb m6, m9, m11 + %endif +%else + movu xm5, [dstq+strideq*0-1] + movu xm9, [dstq+strideq*1-1] + vinserti128 m5, [dstq+strideq*2-1], 1 + vinserti128 m9, [dstq+stride3q -1], 1 + movu m10, [blend_8x8_0+16] + punpcklqdq m6, m5, m9 + vpblendvb m6, [rsp+gprsize+0x60+hq*8+64], m10 + psrldq m5, 2 + psrldq m9, 2 + punpcklqdq m5, m9 +%endif + ret +.d4k0: +%if %1 == 4 + %if %2 == 4 + vpbroadcastq m10, [dstq+strideq*1-1] + vpbroadcastq m11, [dstq+strideq*2-1] + movd xm6, [topq+strideq*1-1] + movd xm9, [dstq+strideq*0-1] + psrldq m5, m10, 2 + psrldq m12, m11, 2 + vpblendd m6, m10, 0x10 + vpblendd m9, m11, 0x10 + movu m10, [blend_4x4] + vinserti128 m5, [dstq+stride3q +1], 1 + vinserti128 m12, [botq +1], 1 + punpckldq m6, m9 + punpckldq m5, m12 + vpblendvb m6, [rsp+gprsize+0x40], m10 + %else + movd xm6, [topq +strideq*1-1] + movq xm9, [dstq +strideq*1-1] + movq xm10, [dstq +stride3q -1] + movq xm11, [dst4q+strideq*1-1] + pinsrd xm6, [dstq +strideq*0-1], 1 + movhps xm9, [dstq +strideq*2-1] + movhps xm10, [dst4q+strideq*0-1] + movhps xm11, [dst4q+strideq*2-1] + psrldq xm5, xm9, 2 + shufps xm6, xm9, q2010 + psrldq xm9, xm10, 2 + shufps xm5, xm9, q2020 + shufps xm10, xm11, q2020 + movd xm9, [dst4q+stride3q +1] + vinserti128 m6, xm10, 1 + pinsrd xm9, [botq +1], 1 + psrldq xm11, 2 + pmovzxbw m10, [leftq-1] + shufps xm11, xm9, q1020 + movu m9, [blend_4x8_0] + vinserti128 m5, xm11, 1 + vpblendvb m6, m10, m9 + %endif +%else + lea r13, [blend_8x8_0+8] + movq xm6, [top2q -1] + vbroadcasti128 m5, [dstq+strideq*1-1] + vbroadcasti128 m9, [dstq+strideq*2-1] + movhps xm6, [dstq+strideq*0-1] + movu m11, [r13+hq*2*1+16*1] + punpcklqdq m10, m5, m9 + vinserti128 m5, [dstq+stride3q -1], 1 + vinserti128 m9, [botq -1], 1 + vpblendd m6, m10, 0xF0 + vpblendvb m6, [rsp+gprsize+0x60+hq*8+64-8*1], m11 + psrldq m5, 2 + psrldq m9, 2 + punpcklqdq m5, m9 +%endif + ret +.d5k0: +.d6k0: +.d7k0: +%if %1 == 4 + %if %2 == 4 + movd xm6, [topq+strideq*1 ] + vpbroadcastd m5, [dstq+strideq*1 ] + vpbroadcastd m9, [dstq+strideq*2 ] + vpblendd xm6, [dstq+strideq*0-4], 0x2 + vpblendd m5, m9, 0x22 + vpblendd m6, m5, 0x30 + vinserti128 m5, [dstq+stride3q ], 1 + vpblendd m5, [botq -20], 0x20 + %else + movd xm6, [topq +strideq*1] + movd xm5, [dstq +strideq*1] + movd xm9, [dstq +stride3q ] + movd xm10, [dst4q+strideq*1] + movd xm11, [dst4q+stride3q ] + pinsrd xm6, [dstq +strideq*0], 1 + pinsrd xm5, [dstq +strideq*2], 1 + pinsrd xm9, [dst4q+strideq*0], 1 + pinsrd xm10, [dst4q+strideq*2], 1 + pinsrd xm11, [botq ], 1 + punpcklqdq xm6, xm5 + punpcklqdq xm5, xm9 + punpcklqdq xm9, xm10 + punpcklqdq xm10, xm11 + vinserti128 m6, xm9, 1 + vinserti128 m5, xm10, 1 + %endif +%else + movq xm6, [top2q ] + movq xm5, [dstq+strideq*1] + movq xm9, [dstq+stride3q ] + movhps xm6, [dstq+strideq*0] + movhps xm5, [dstq+strideq*2] + movhps xm9, [botq ] + vinserti128 m6, xm5, 1 + vinserti128 m5, xm9, 1 +%endif + ret +.d0k1: +%if %1 == 4 + %if %2 == 4 + movd xm6, [dstq+strideq*2-2] + movd xm9, [dstq+stride3q -2] + movd xm5, [topq+strideq*0+2] + movd xm10, [topq+strideq*1+2] + pinsrw xm6, [leftq+4], 0 + pinsrw xm9, [leftq+6], 0 + vinserti128 m5, [dstq+strideq*0+2], 1 + vinserti128 m10, [dstq+strideq*1+2], 1 + vinserti128 m6, [botq+strideq*0-2], 1 + vinserti128 m9, [botq+strideq*1-2], 1 + punpckldq m5, m10 + punpckldq m6, m9 + %else + movq xm6, [dstq +strideq*2-2] + movd xm10, [dst4q+strideq*2-2] + movd xm5, [topq +strideq*0+2] + movq xm9, [dst4q+strideq*0-2] + movhps xm6, [dstq +stride3q -2] + pinsrw xm10, [dst4q+stride3q ], 3 + pinsrd xm5, [topq +strideq*1+2], 1 + movhps xm9, [dst4q+strideq*1-2] + pinsrd xm10, [botq +strideq*0-2], 2 + pinsrd xm5, [dstq +strideq*0+2], 2 + pinsrd xm10, [botq +strideq*1-2], 3 + pinsrd xm5, [dstq +strideq*1+2], 3 + shufps xm11, xm6, xm9, q3131 + shufps xm6, xm9, q2020 + movu m9, [blend_4x8_3+8] + vinserti128 m6, xm10, 1 + vinserti128 m5, xm11, 1 + vpblendvb m6, [rsp+gprsize+0x10+8], m9 + %endif +%else + lea r13, [blend_8x8_1+16] + movq xm6, [dstq+strideq*2-2] + movq xm9, [dstq+stride3q -2] + movq xm5, [top1q +2] + movq xm10, [top2q +2] + movu m11, [r13+hq*2*2+16*2] + vinserti128 m6, [botq+strideq*0-2], 1 + vinserti128 m9, [botq+strideq*1-2], 1 + vinserti128 m5, [dstq+strideq*0+2], 1 + vinserti128 m10, [dstq+strideq*1+2], 1 + punpcklqdq m6, m9 + punpcklqdq m5, m10 + vpblendvb m6, [rsp+gprsize+0x20+hq*8+64+8*2], m11 +%endif + ret +.d1k1: +%if %1 == 4 + %if %2 == 4 + vpbroadcastq m6, [dstq+strideq*1-2] + vpbroadcastq m9, [dstq+strideq*2-2] + movd xm5, [topq+strideq*1+2] + movd xm10, [dstq+strideq*0+2] + psrldq m11, m6, 4 + psrldq m12, m9, 4 + vpblendd m5, m11, 0x10 + movq xm11, [leftq+2] + vinserti128 m6, [dstq+stride3q-2], 1 + punpckldq xm11, xm11 + vpblendd m10, m12, 0x10 + pcmpeqd m12, m12 + pmovzxwd m11, xm11 + psrld m12, 16 + punpckldq m6, m9 + vpbroadcastd m9, [botq-2] + vpblendvb m6, m11, m12 + punpckldq m5, m10 + vpblendd m6, m9, 0x20 + %else + movd xm5, [topq +strideq*1+2] + movq xm6, [dstq +strideq*1-2] + movq xm9, [dstq +stride3q -2] + movq xm10, [dst4q+strideq*1-2] + movd xm11, [dst4q+stride3q -2] + pinsrd xm5, [dstq +strideq*0+2], 1 + movhps xm6, [dstq +strideq*2-2] + movhps xm9, [dst4q+strideq*0-2] + movhps xm10, [dst4q+strideq*2-2] + pinsrd xm11, [botq -2], 1 + shufps xm5, xm6, q3110 + shufps xm6, xm9, q2020 + shufps xm9, xm10, q3131 + shufps xm10, xm11, q1020 + movu m11, [blend_4x8_2+4] + vinserti128 m6, xm10, 1 + vinserti128 m5, xm9, 1 + vpblendvb m6, [rsp+gprsize+0x10+4], m11 + %endif +%else + lea r13, [blend_8x8_1+16] + movq xm5, [top2q +2] + vbroadcasti128 m6, [dstq+strideq*1-2] + vbroadcasti128 m9, [dstq+strideq*2-2] + movhps xm5, [dstq+strideq*0+2] + shufps m10, m6, m9, q2121 + vinserti128 m6, [dstq+stride3q -2], 1 + vinserti128 m9, [botq -2], 1 + movu m11, [r13+hq*2*1+16*1] + vpblendd m5, m10, 0xF0 + punpcklqdq m6, m9 + vpblendvb m6, [rsp+gprsize+0x20+hq*8+64+8*1], m11 +%endif + ret +.d2k1: +%if %1 == 4 + %if %2 == 4 + movq xm11, [leftq] + movq xm6, [dstq+strideq*0-2] + movq xm9, [dstq+strideq*1-2] + vinserti128 m6, [dstq+strideq*2-2], 1 + vinserti128 m9, [dstq+stride3q -2], 1 + punpckldq xm11, xm11 + psrldq m5, m6, 4 + psrldq m10, m9, 4 + pmovzxwd m11, xm11 + punpckldq m6, m9 + punpckldq m5, m10 + pblendw m6, m11, 0x05 + %else + movq xm5, [dstq +strideq*0-2] + movq xm9, [dstq +strideq*2-2] + movq xm10, [dst4q+strideq*0-2] + movq xm11, [dst4q+strideq*2-2] + movhps xm5, [dstq +strideq*1-2] + movhps xm9, [dstq +stride3q -2] + movhps xm10, [dst4q+strideq*1-2] + movhps xm11, [dst4q+stride3q -2] + shufps xm6, xm5, xm9, q2020 + shufps xm5, xm9, q3131 + shufps xm9, xm10, xm11, q2020 + shufps xm10, xm11, q3131 + pmovzxwd m11, [leftq] + vinserti128 m6, xm9, 1 + vinserti128 m5, xm10, 1 + pblendw m6, m11, 0x55 + %endif +%else + mova m11, [rsp+gprsize+0x20+hq*8+64] + movu xm5, [dstq+strideq*0-2] + movu xm9, [dstq+strideq*1-2] + vinserti128 m5, [dstq+strideq*2-2], 1 + vinserti128 m9, [dstq+stride3q -2], 1 + shufps m6, m5, m9, q1010 + shufps m5, m9, q2121 + pblendw m6, m11, 0x11 +%endif + ret +.d3k1: +%if %1 == 4 + %if %2 == 4 + vpbroadcastq m11, [dstq+strideq*1-2] + vpbroadcastq m12, [dstq+strideq*2-2] + movd xm6, [topq+strideq*1-2] + movd xm9, [dstq+strideq*0-2] + pblendw m11, [leftq-16+2], 0x01 + pblendw m12, [leftq-16+4], 0x01 + pinsrw xm9, [leftq- 0+0], 0 + psrldq m5, m11, 4 + psrldq m10, m12, 4 + vinserti128 m5, [dstq+stride3q +2], 1 + vinserti128 m10, [botq +2], 1 + vpblendd m6, m11, 0x10 + vpblendd m9, m12, 0x10 + punpckldq m6, m9 + punpckldq m5, m10 + %else + movd xm6, [topq +strideq*1-2] + movq xm5, [dstq +strideq*1-2] + movq xm9, [dstq +stride3q -2] + movq xm10, [dst4q+strideq*1-2] + movd xm11, [dst4q+stride3q +2] + pinsrw xm6, [dstq +strideq*0 ], 3 + movhps xm5, [dstq +strideq*2-2] + movhps xm9, [dst4q+strideq*0-2] + movhps xm10, [dst4q+strideq*2-2] + pinsrd xm11, [botq +2], 1 + shufps xm6, xm5, q2010 + shufps xm5, xm9, q3131 + shufps xm9, xm10, q2020 + shufps xm10, xm11, q1031 + movu m11, [blend_4x8_2] + vinserti128 m6, xm9, 1 + vinserti128 m5, xm10, 1 + vpblendvb m6, [rsp+gprsize+0x10-4], m11 + %endif +%else + lea r13, [blend_8x8_1+8] + movq xm6, [top2q -2] + vbroadcasti128 m5, [dstq+strideq*1-2] + vbroadcasti128 m10, [dstq+strideq*2-2] + movhps xm6, [dstq+strideq*0-2] + punpcklqdq m9, m5, m10 + vinserti128 m5, [dstq+stride3q -2], 1 + vinserti128 m10, [botq -2], 1 + movu m11, [r13+hq*2*1+16*1] + vpblendd m6, m9, 0xF0 + shufps m5, m10, q2121 + vpblendvb m6, [rsp+gprsize+0x20+hq*8+64-8*1], m11 +%endif + ret +.d4k1: +%if %1 == 4 + %if %2 == 4 + vinserti128 m6, [dstq+strideq*0-2], 1 + vinserti128 m9, [dstq+strideq*1-2], 1 + movd xm5, [dstq+strideq*2+2] + movd xm10, [dstq+stride3q +2] + pblendw m6, [leftq-16+0], 0x01 + pblendw m9, [leftq-16+2], 0x01 + vinserti128 m5, [botq+strideq*0+2], 1 + vinserti128 m10, [botq+strideq*1+2], 1 + vpblendd m6, [topq+strideq*0-2], 0x01 + vpblendd m9, [topq+strideq*1-2], 0x01 + punpckldq m5, m10 + punpckldq m6, m9 + %else + movd xm6, [topq +strideq*0-2] + movq xm5, [dstq +strideq*2-2] + movq xm9, [dst4q+strideq*0-2] + movd xm10, [dst4q+strideq*2+2] + pinsrd xm6, [topq +strideq*1-2], 1 + movhps xm5, [dstq +stride3q -2] + movhps xm9, [dst4q+strideq*1-2] + pinsrd xm10, [dst4q+stride3q +2], 1 + pinsrd xm6, [dstq +strideq*0-2], 2 + pinsrd xm10, [botq +strideq*0+2], 2 + pinsrd xm6, [dstq +strideq*1-2], 3 + pinsrd xm10, [botq +strideq*1+2], 3 + shufps xm11, xm5, xm9, q2020 + shufps xm5, xm9, q3131 + movu m9, [blend_4x8_3] + vinserti128 m6, xm11, 1 + vinserti128 m5, xm10, 1 + vpblendvb m6, [rsp+gprsize+0x10-8], m9 + %endif +%else + lea r13, [blend_8x8_1] + movu m11, [r13+hq*2*2+16*2] + movq xm6, [top1q -2] + movq xm9, [top2q -2] + movq xm5, [dstq+strideq*2+2] + movq xm10, [dstq+stride3q +2] + vinserti128 m6, [dstq+strideq*0-2], 1 + vinserti128 m9, [dstq+strideq*1-2], 1 + vinserti128 m5, [botq+strideq*0+2], 1 + vinserti128 m10, [botq+strideq*1+2], 1 + punpcklqdq m6, m9 + vpblendvb m6, [rsp+gprsize+0x20+hq*8+64-8*2], m11 + punpcklqdq m5, m10 +%endif + ret +.d5k1: +%if %1 == 4 + %if %2 == 4 + movd xm6, [topq+strideq*0-1] + movd xm9, [topq+strideq*1-1] + movd xm5, [dstq+strideq*2+1] + movd xm10, [dstq+stride3q +1] + pcmpeqd m12, m12 + pmovzxbw m11, [leftq-8+1] + psrld m12, 24 + vinserti128 m6, [dstq+strideq*0-1], 1 + vinserti128 m9, [dstq+strideq*1-1], 1 + vinserti128 m5, [botq+strideq*0+1], 1 + vinserti128 m10, [botq+strideq*1+1], 1 + punpckldq m6, m9 + pxor m9, m9 + vpblendd m12, m9, 0x0F + punpckldq m5, m10 + vpblendvb m6, m11, m12 + %else + movd xm6, [topq +strideq*0-1] + movq xm5, [dstq +strideq*2-1] + movq xm9, [dst4q+strideq*0-1] + movd xm10, [dst4q+strideq*2+1] + pinsrd xm6, [topq +strideq*1-1], 1 + movhps xm5, [dstq +stride3q -1] + movhps xm9, [dst4q+strideq*1-1] + pinsrd xm10, [dst4q+stride3q +1], 1 + pinsrd xm6, [dstq +strideq*0-1], 2 + pinsrd xm10, [botq +strideq*0+1], 2 + pinsrd xm6, [dstq +strideq*1-1], 3 + pinsrd xm10, [botq +strideq*1+1], 3 + shufps xm11, xm5, xm9, q2020 + vinserti128 m6, xm11, 1 + pmovzxbw m11, [leftq-3] + psrldq xm5, 2 + psrldq xm9, 2 + shufps xm5, xm9, q2020 + movu m9, [blend_4x8_1] + vinserti128 m5, xm10, 1 + vpblendvb m6, m11, m9 + %endif +%else + lea r13, [blend_8x8_0] + movu m11, [r13+hq*2*2+16*2] + movq xm6, [top1q -1] + movq xm9, [top2q -1] + movq xm5, [dstq+strideq*2+1] + movq xm10, [dstq+stride3q +1] + vinserti128 m6, [dstq+strideq*0-1], 1 + vinserti128 m9, [dstq+strideq*1-1], 1 + vinserti128 m5, [botq+strideq*0+1], 1 + vinserti128 m10, [botq+strideq*1+1], 1 + punpcklqdq m6, m9 + punpcklqdq m5, m10 + vpblendvb m6, [rsp+gprsize+0x60+hq*8+64-8*2], m11 +%endif + ret +.d6k1: +%if %1 == 4 + %if %2 == 4 + movd xm6, [topq+strideq*0] + movd xm9, [topq+strideq*1] + movd xm5, [dstq+strideq*2] + movd xm10, [dstq+stride3q ] + vinserti128 m6, [dstq+strideq*0], 1 + vinserti128 m9, [dstq+strideq*1], 1 + vinserti128 m5, [botq+strideq*0], 1 + vinserti128 m10, [botq+strideq*1], 1 + punpckldq m6, m9 + punpckldq m5, m10 + %else + movd xm5, [dstq +strideq*2] + movd xm6, [topq +strideq*0] + movd xm9, [dst4q+strideq*2] + pinsrd xm5, [dstq +stride3q ], 1 + pinsrd xm6, [topq +strideq*1], 1 + pinsrd xm9, [dst4q+stride3q ], 1 + pinsrd xm5, [dst4q+strideq*0], 2 + pinsrd xm6, [dstq +strideq*0], 2 + pinsrd xm9, [botq +strideq*0], 2 + pinsrd xm5, [dst4q+strideq*1], 3 + pinsrd xm6, [dstq +strideq*1], 3 + pinsrd xm9, [botq +strideq*1], 3 + vinserti128 m6, xm5, 1 + vinserti128 m5, xm9, 1 + %endif +%else + movq xm5, [dstq+strideq*2] + movq xm9, [botq+strideq*0] + movq xm6, [top1q ] + movq xm10, [dstq+strideq*0] + movhps xm5, [dstq+stride3q ] + movhps xm9, [botq+strideq*1] + movhps xm6, [top2q ] + movhps xm10, [dstq+strideq*1] + vinserti128 m5, xm9, 1 + vinserti128 m6, xm10, 1 +%endif + ret +.d7k1: +%if %1 == 4 + %if %2 == 4 + movd xm5, [dstq+strideq*2-1] + movd xm9, [dstq+stride3q -1] + movd xm6, [topq+strideq*0+1] + movd xm10, [topq+strideq*1+1] + pinsrb xm5, [leftq+ 5], 0 + pinsrb xm9, [leftq+ 7], 0 + vinserti128 m6, [dstq+strideq*0+1], 1 + vinserti128 m10, [dstq+strideq*1+1], 1 + vinserti128 m5, [botq+strideq*0-1], 1 + vinserti128 m9, [botq+strideq*1-1], 1 + punpckldq m6, m10 + punpckldq m5, m9 + %else + movd xm6, [topq +strideq*0+1] + movq xm9, [dstq +strideq*2-1] + movq xm10, [dst4q+strideq*0-1] + movd xm11, [dst4q+strideq*2-1] + pinsrd xm6, [topq +strideq*1+1], 1 + movhps xm9, [dstq +stride3q -1] + movhps xm10, [dst4q+strideq*1-1] + pinsrd xm11, [dst4q+stride3q -1], 1 + pinsrd xm6, [dstq +strideq*0+1], 2 + pinsrd xm11, [botq +strideq*0-1], 2 + pinsrd xm6, [dstq +strideq*1+1], 3 + pinsrd xm11, [botq +strideq*1-1], 3 + shufps xm5, xm9, xm10, q2020 + vinserti128 m5, xm11, 1 + pmovzxbw m11, [leftq+5] + psrldq xm9, 2 + psrldq xm10, 2 + shufps xm9, xm10, q2020 + movu m10, [blend_4x8_1+8] + vinserti128 m6, xm9, 1 + vpblendvb m5, m11, m10 + %endif +%else + lea r13, [blend_8x8_0+16] + movq xm5, [dstq+strideq*2-1] + movq xm9, [botq+strideq*0-1] + movq xm6, [top1q +1] + movq xm10, [dstq+strideq*0+1] + movhps xm5, [dstq+stride3q -1] + movhps xm9, [botq+strideq*1-1] + movhps xm6, [top2q +1] + movhps xm10, [dstq+strideq*1+1] + movu m11, [r13+hq*2*2+16*2] + vinserti128 m5, xm9, 1 + vinserti128 m6, xm10, 1 + vpblendvb m5, [rsp+gprsize+0x60+hq*8+64+8*2], m11 +%endif + ret + +.border_block: + DEFINE_ARGS dst, stride, left, top, bot, pri, sec, stride3, dst4, edge +%define rstk rsp +%assign stack_offset stack_offset_entry +%assign regs_used 11 + ALLOC_STACK 2*16+(%2+4)*32, 16 +%define px rsp+2*16+2*32 + + pcmpeqw m14, m14 + psllw m14, 15 ; 0x8000 + + ; prepare pixel buffers - body/right +%if %1 == 4 + INIT_XMM avx2 +%endif +%if %2 == 8 + lea dst4q, [dstq+strideq*4] +%endif + lea stride3q, [strideq*3] + test edgeb, 2 ; have_right + jz .no_right + pmovzxbw m1, [dstq+strideq*0] + pmovzxbw m2, [dstq+strideq*1] + pmovzxbw m3, [dstq+strideq*2] + pmovzxbw m4, [dstq+stride3q] + mova [px+0*32], m1 + mova [px+1*32], m2 + mova [px+2*32], m3 + mova [px+3*32], m4 +%if %2 == 8 + pmovzxbw m1, [dst4q+strideq*0] + pmovzxbw m2, [dst4q+strideq*1] + pmovzxbw m3, [dst4q+strideq*2] + pmovzxbw m4, [dst4q+stride3q] + mova [px+4*32], m1 + mova [px+5*32], m2 + mova [px+6*32], m3 + mova [px+7*32], m4 +%endif + jmp .body_done +.no_right: +%if %1 == 4 + movd xm1, [dstq+strideq*0] + movd xm2, [dstq+strideq*1] + movd xm3, [dstq+strideq*2] + movd xm4, [dstq+stride3q] + pmovzxbw xm1, xm1 + pmovzxbw xm2, xm2 + pmovzxbw xm3, xm3 + pmovzxbw xm4, xm4 + movq [px+0*32], xm1 + movq [px+1*32], xm2 + movq [px+2*32], xm3 + movq [px+3*32], xm4 +%else + pmovzxbw xm1, [dstq+strideq*0] + pmovzxbw xm2, [dstq+strideq*1] + pmovzxbw xm3, [dstq+strideq*2] + pmovzxbw xm4, [dstq+stride3q] + mova [px+0*32], xm1 + mova [px+1*32], xm2 + mova [px+2*32], xm3 + mova [px+3*32], xm4 +%endif + movd [px+0*32+%1*2], xm14 + movd [px+1*32+%1*2], xm14 + movd [px+2*32+%1*2], xm14 + movd [px+3*32+%1*2], xm14 +%if %2 == 8 + %if %1 == 4 + movd xm1, [dst4q+strideq*0] + movd xm2, [dst4q+strideq*1] + movd xm3, [dst4q+strideq*2] + movd xm4, [dst4q+stride3q] + pmovzxbw xm1, xm1 + pmovzxbw xm2, xm2 + pmovzxbw xm3, xm3 + pmovzxbw xm4, xm4 + movq [px+4*32], xm1 + movq [px+5*32], xm2 + movq [px+6*32], xm3 + movq [px+7*32], xm4 + %else + pmovzxbw xm1, [dst4q+strideq*0] + pmovzxbw xm2, [dst4q+strideq*1] + pmovzxbw xm3, [dst4q+strideq*2] + pmovzxbw xm4, [dst4q+stride3q] + mova [px+4*32], xm1 + mova [px+5*32], xm2 + mova [px+6*32], xm3 + mova [px+7*32], xm4 + %endif + movd [px+4*32+%1*2], xm14 + movd [px+5*32+%1*2], xm14 + movd [px+6*32+%1*2], xm14 + movd [px+7*32+%1*2], xm14 +%endif +.body_done: + + ; top + test edgeb, 4 ; have_top + jz .no_top + test edgeb, 1 ; have_left + jz .top_no_left + test edgeb, 2 ; have_right + jz .top_no_right + pmovzxbw m1, [topq+strideq*0-(%1/2)] + pmovzxbw m2, [topq+strideq*1-(%1/2)] + movu [px-2*32-%1], m1 + movu [px-1*32-%1], m2 + jmp .top_done +.top_no_right: + pmovzxbw m1, [topq+strideq*0-%1] + pmovzxbw m2, [topq+strideq*1-%1] + movu [px-2*32-%1*2], m1 + movu [px-1*32-%1*2], m2 + movd [px-2*32+%1*2], xm14 + movd [px-1*32+%1*2], xm14 + jmp .top_done +.top_no_left: + test edgeb, 2 ; have_right + jz .top_no_left_right + pmovzxbw m1, [topq+strideq*0] + pmovzxbw m2, [topq+strideq*1] + mova [px-2*32+0], m1 + mova [px-1*32+0], m2 + movd [px-2*32-4], xm14 + movd [px-1*32-4], xm14 + jmp .top_done +.top_no_left_right: +%if %1 == 4 + movd xm1, [topq+strideq*0] + pinsrd xm1, [topq+strideq*1], 1 + pmovzxbw xm1, xm1 + movq [px-2*32+0], xm1 + movhps [px-1*32+0], xm1 +%else + pmovzxbw xm1, [topq+strideq*0] + pmovzxbw xm2, [topq+strideq*1] + mova [px-2*32+0], xm1 + mova [px-1*32+0], xm2 +%endif + movd [px-2*32-4], xm14 + movd [px-1*32-4], xm14 + movd [px-2*32+%1*2], xm14 + movd [px-1*32+%1*2], xm14 + jmp .top_done +.no_top: + movu [px-2*32-%1], m14 + movu [px-1*32-%1], m14 +.top_done: + + ; left + test edgeb, 1 ; have_left + jz .no_left + pmovzxbw xm1, [leftq+ 0] +%if %2 == 8 + pmovzxbw xm2, [leftq+ 8] +%endif + movd [px+0*32-4], xm1 + pextrd [px+1*32-4], xm1, 1 + pextrd [px+2*32-4], xm1, 2 + pextrd [px+3*32-4], xm1, 3 +%if %2 == 8 + movd [px+4*32-4], xm2 + pextrd [px+5*32-4], xm2, 1 + pextrd [px+6*32-4], xm2, 2 + pextrd [px+7*32-4], xm2, 3 +%endif + jmp .left_done +.no_left: + movd [px+0*32-4], xm14 + movd [px+1*32-4], xm14 + movd [px+2*32-4], xm14 + movd [px+3*32-4], xm14 +%if %2 == 8 + movd [px+4*32-4], xm14 + movd [px+5*32-4], xm14 + movd [px+6*32-4], xm14 + movd [px+7*32-4], xm14 +%endif +.left_done: + + ; bottom + DEFINE_ARGS dst, stride, _, _, bot, pri, sec, stride3, _, edge + test edgeb, 8 ; have_bottom + jz .no_bottom + test edgeb, 1 ; have_left + jz .bottom_no_left + test edgeb, 2 ; have_right + jz .bottom_no_right + pmovzxbw m1, [botq+strideq*0-(%1/2)] + pmovzxbw m2, [botq+strideq*1-(%1/2)] + movu [px+(%2+0)*32-%1], m1 + movu [px+(%2+1)*32-%1], m2 + jmp .bottom_done +.bottom_no_right: + pmovzxbw m1, [botq+strideq*0-%1] + pmovzxbw m2, [botq+strideq*1-%1] + movu [px+(%2+0)*32-%1*2], m1 + movu [px+(%2+1)*32-%1*2], m2 +%if %1 == 8 + movd [px+(%2-1)*32+%1*2], xm14 ; overwritten by previous movu +%endif + movd [px+(%2+0)*32+%1*2], xm14 + movd [px+(%2+1)*32+%1*2], xm14 + jmp .bottom_done +.bottom_no_left: + test edgeb, 2 ; have_right + jz .bottom_no_left_right + pmovzxbw m1, [botq+strideq*0] + pmovzxbw m2, [botq+strideq*1] + mova [px+(%2+0)*32+0], m1 + mova [px+(%2+1)*32+0], m2 + movd [px+(%2+0)*32-4], xm14 + movd [px+(%2+1)*32-4], xm14 + jmp .bottom_done +.bottom_no_left_right: +%if %1 == 4 + movd xm1, [botq+strideq*0] + pinsrd xm1, [botq+strideq*1], 1 + pmovzxbw xm1, xm1 + movq [px+(%2+0)*32+0], xm1 + movhps [px+(%2+1)*32+0], xm1 +%else + pmovzxbw xm1, [botq+strideq*0] + pmovzxbw xm2, [botq+strideq*1] + mova [px+(%2+0)*32+0], xm1 + mova [px+(%2+1)*32+0], xm2 +%endif + movd [px+(%2+0)*32-4], xm14 + movd [px+(%2+1)*32-4], xm14 + movd [px+(%2+0)*32+%1*2], xm14 + movd [px+(%2+1)*32+%1*2], xm14 + jmp .bottom_done +.no_bottom: + movu [px+(%2+0)*32-%1], m14 + movu [px+(%2+1)*32-%1], m14 +.bottom_done: + + ; actual filter + INIT_YMM avx2 + DEFINE_ARGS dst, stride, _, pridmp, damping, pri, secdmp, stride3, zero +%undef edged + ; register to shuffle values into after packing + vbroadcasti128 m12, [shufb_lohi] + + mov dampingd, r8m + xor zerod, zerod + movifnidn prid, prim + sub dampingd, 31 + movifnidn secdmpd, secdmpm + test prid, prid + jz .border_sec_only + movd xm0, prid + lzcnt pridmpd, prid + add pridmpd, dampingd + cmovs pridmpd, zerod + mov [rsp+0], pridmpq ; pri_shift + test secdmpd, secdmpd + jz .border_pri_only + movd xm1, secdmpd + lzcnt secdmpd, secdmpd + add secdmpd, dampingd + mov [rsp+8], secdmpq ; sec_shift + + DEFINE_ARGS dst, stride, _, pridmp, table, pri, secdmp, stride3 + lea tableq, [tap_table] + vpbroadcastb m13, [tableq+pridmpq] ; pri_shift_mask + vpbroadcastb m14, [tableq+secdmpq] ; sec_shift_mask + + ; pri/sec_taps[k] [4 total] + DEFINE_ARGS dst, stride, _, dir, table, pri, sec, stride3 + vpbroadcastb m0, xm0 ; pri_strength + vpbroadcastb m1, xm1 ; sec_strength + and prid, 1 + lea priq, [tableq+priq*2+8] ; pri_taps + lea secq, [tableq+12] ; sec_taps + + BORDER_PREP_REGS %1, %2 +%if %1*%2*2/mmsize > 1 +.border_v_loop: +%endif + BORDER_LOAD_BLOCK %1, %2, 1 +.border_k_loop: + vpbroadcastb m2, [priq+kq] ; pri_taps + vpbroadcastb m3, [secq+kq] ; sec_taps + ACCUMULATE_TAP_WORD 0*2, [rsp+0], m13, m0, m2, %1, 1 + ACCUMULATE_TAP_WORD 2*2, [rsp+8], m14, m1, m3, %1, 1 + ACCUMULATE_TAP_WORD 6*2, [rsp+8], m14, m1, m3, %1, 1 + dec kq + jge .border_k_loop + + vpbroadcastd m10, [pw_2048] + BORDER_ADJUST_PIXEL %1, m10, 1 +%if %1*%2*2/mmsize > 1 + %define vloop_lines (mmsize/(%1*2)) + lea dstq, [dstq+strideq*vloop_lines] + add stkq, 32*vloop_lines + dec hd + jg .border_v_loop +%endif + RET + +.border_pri_only: + DEFINE_ARGS dst, stride, _, pridmp, table, pri, _, stride3 + lea tableq, [tap_table] + vpbroadcastb m13, [tableq+pridmpq] ; pri_shift_mask + DEFINE_ARGS dst, stride, _, dir, table, pri, _, stride3 + vpbroadcastb m0, xm0 ; pri_strength + and prid, 1 + lea priq, [tableq+priq*2+8] ; pri_taps + BORDER_PREP_REGS %1, %2 + vpbroadcastd m1, [pw_2048] +%if %1*%2*2/mmsize > 1 +.border_pri_v_loop: +%endif + BORDER_LOAD_BLOCK %1, %2 +.border_pri_k_loop: + vpbroadcastb m2, [priq+kq] ; pri_taps + ACCUMULATE_TAP_WORD 0*2, [rsp+0], m13, m0, m2, %1 + dec kq + jge .border_pri_k_loop + BORDER_ADJUST_PIXEL %1, m1 +%if %1*%2*2/mmsize > 1 + %define vloop_lines (mmsize/(%1*2)) + lea dstq, [dstq+strideq*vloop_lines] + add stkq, 32*vloop_lines + dec hd + jg .border_pri_v_loop +%endif + RET + +.border_sec_only: + DEFINE_ARGS dst, stride, _, _, damping, _, secdmp, stride3 + movd xm1, secdmpd + lzcnt secdmpd, secdmpd + add secdmpd, dampingd + mov [rsp+8], secdmpq ; sec_shift + DEFINE_ARGS dst, stride, _, _, table, _, secdmp, stride3 + lea tableq, [tap_table] + vpbroadcastb m14, [tableq+secdmpq] ; sec_shift_mask + DEFINE_ARGS dst, stride, _, dir, table, _, sec, stride3 + vpbroadcastb m1, xm1 ; sec_strength + lea secq, [tableq+12] ; sec_taps + BORDER_PREP_REGS %1, %2 + vpbroadcastd m0, [pw_2048] +%if %1*%2*2/mmsize > 1 +.border_sec_v_loop: +%endif + BORDER_LOAD_BLOCK %1, %2 +.border_sec_k_loop: + vpbroadcastb m3, [secq+kq] ; sec_taps + ACCUMULATE_TAP_WORD 2*2, [rsp+8], m14, m1, m3, %1 + ACCUMULATE_TAP_WORD 6*2, [rsp+8], m14, m1, m3, %1 + dec kq + jge .border_sec_k_loop + BORDER_ADJUST_PIXEL %1, m0 +%if %1*%2*2/mmsize > 1 + %define vloop_lines (mmsize/(%1*2)) + lea dstq, [dstq+strideq*vloop_lines] + add stkq, 32*vloop_lines + dec hd + jg .border_sec_v_loop +%endif + RET +%endmacro + +CDEF_FILTER 8, 8 +CDEF_FILTER 4, 8 +CDEF_FILTER 4, 4 + +INIT_YMM avx2 +cglobal cdef_dir_8bpc, 3, 4, 6, src, stride, var, stride3 + lea stride3q, [strideq*3] + movq xm0, [srcq+strideq*0] + movq xm1, [srcq+strideq*1] + movq xm2, [srcq+strideq*2] + movq xm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m4, [srcq+stride3q ] + vpbroadcastq m5, [srcq+strideq*2] + vpblendd m0, m4, 0xf0 + vpblendd m1, m5, 0xf0 + vpbroadcastq m4, [srcq+strideq*1] + vpbroadcastq m5, [srcq+strideq*0] + vpblendd m2, m4, 0xf0 + vpblendd m3, m5, 0xf0 + pxor m4, m4 + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 +cglobal_label .main + vpbroadcastd m4, [pw_128] + PROLOGUE 3, 4, 15 + psubw m0, m4 + psubw m1, m4 + psubw m2, m4 + psubw m3, m4 + + ; shuffle registers to generate partial_sum_diag[0-1] together + vperm2i128 m7, m0, m0, 0x01 + vperm2i128 m6, m1, m1, 0x01 + vperm2i128 m5, m2, m2, 0x01 + vperm2i128 m4, m3, m3, 0x01 + + ; start with partial_sum_hv[0-1] + paddw m8, m0, m1 + paddw m9, m2, m3 + phaddw m10, m0, m1 + phaddw m11, m2, m3 + paddw m8, m9 + phaddw m10, m11 + vextracti128 xm9, m8, 1 + vextracti128 xm11, m10, 1 + paddw xm8, xm9 ; partial_sum_hv[1] + phaddw xm10, xm11 ; partial_sum_hv[0] + vinserti128 m8, xm10, 1 + vpbroadcastd m9, [div_table+44] + pmaddwd m8, m8 + pmulld m8, m9 ; cost6[2a-d] | cost2[a-d] + + ; create aggregates [lower half]: + ; m9 = m0:01234567+m1:x0123456+m2:xx012345+m3:xxx01234+ + ; m4:xxxx0123+m5:xxxxx012+m6:xxxxxx01+m7:xxxxxxx0 + ; m10= m1:7xxxxxxx+m2:67xxxxxx+m3:567xxxxx+ + ; m4:4567xxxx+m5:34567xxx+m6:234567xx+m7:1234567x + ; and [upper half]: + ; m9 = m0:xxxxxxx0+m1:xxxxxx01+m2:xxxxx012+m3:xxxx0123+ + ; m4:xxx01234+m5:xx012345+m6:x0123456+m7:01234567 + ; m10= m0:1234567x+m1:234567xx+m2:34567xxx+m3:4567xxxx+ + ; m4:567xxxxx+m5:67xxxxxx+m6:7xxxxxxx + ; and then shuffle m11 [shufw_6543210x], unpcklwd, pmaddwd, pmulld, paddd + + pslldq m9, m1, 2 + psrldq m10, m1, 14 + pslldq m11, m2, 4 + psrldq m12, m2, 12 + pslldq m13, m3, 6 + psrldq m14, m3, 10 + paddw m9, m11 + paddw m10, m12 + paddw m9, m13 + paddw m10, m14 + pslldq m11, m4, 8 + psrldq m12, m4, 8 + pslldq m13, m5, 10 + psrldq m14, m5, 6 + paddw m9, m11 + paddw m10, m12 + paddw m9, m13 + paddw m10, m14 + pslldq m11, m6, 12 + psrldq m12, m6, 4 + pslldq m13, m7, 14 + psrldq m14, m7, 2 + paddw m9, m11 + paddw m10, m12 + paddw m9, m13 + paddw m10, m14 ; partial_sum_diag[0/1][8-14,zero] + vbroadcasti128 m14, [shufw_6543210x] + vbroadcasti128 m13, [div_table+16] + vbroadcasti128 m12, [div_table+0] + paddw m9, m0 ; partial_sum_diag[0/1][0-7] + pshufb m10, m14 + punpckhwd m11, m9, m10 + punpcklwd m9, m10 + pmaddwd m11, m11 + pmaddwd m9, m9 + pmulld m11, m13 + pmulld m9, m12 + paddd m9, m11 ; cost0[a-d] | cost4[a-d] + + ; merge horizontally and vertically for partial_sum_alt[0-3] + paddw m10, m0, m1 + paddw m11, m2, m3 + paddw m12, m4, m5 + paddw m13, m6, m7 + phaddw m0, m4 + phaddw m1, m5 + phaddw m2, m6 + phaddw m3, m7 + + ; create aggregates [lower half]: + ; m4 = m10:01234567+m11:x0123456+m12:xx012345+m13:xxx01234 + ; m11= m11:7xxxxxxx+m12:67xxxxxx+m13:567xxxxx + ; and [upper half]: + ; m4 = m10:xxx01234+m11:xx012345+m12:x0123456+m13:01234567 + ; m11= m10:567xxxxx+m11:67xxxxxx+m12:7xxxxxxx + ; and then pshuflw m11 3012, unpcklwd, pmaddwd, pmulld, paddd + + pslldq m4, m11, 2 + psrldq m11, 14 + pslldq m5, m12, 4 + psrldq m12, 12 + pslldq m6, m13, 6 + psrldq m13, 10 + paddw m4, m10 + paddw m11, m12 + vpbroadcastd m12, [div_table+44] + paddw m5, m6 + paddw m11, m13 ; partial_sum_alt[3/2] right + vbroadcasti128 m13, [div_table+32] + paddw m4, m5 ; partial_sum_alt[3/2] left + pshuflw m5, m11, q3012 + punpckhwd m6, m11, m4 + punpcklwd m4, m5 + pmaddwd m6, m6 + pmaddwd m4, m4 + pmulld m6, m12 + pmulld m4, m13 + paddd m4, m6 ; cost7[a-d] | cost5[a-d] + + ; create aggregates [lower half]: + ; m5 = m0:01234567+m1:x0123456+m2:xx012345+m3:xxx01234 + ; m1 = m1:7xxxxxxx+m2:67xxxxxx+m3:567xxxxx + ; and [upper half]: + ; m5 = m0:xxx01234+m1:xx012345+m2:x0123456+m3:01234567 + ; m1 = m0:567xxxxx+m1:67xxxxxx+m2:7xxxxxxx + ; and then pshuflw m1 3012, unpcklwd, pmaddwd, pmulld, paddd + + pslldq m5, m1, 2 + psrldq m1, 14 + pslldq m6, m2, 4 + psrldq m2, 12 + pslldq m7, m3, 6 + psrldq m3, 10 + paddw m5, m0 + paddw m1, m2 + paddw m6, m7 + paddw m1, m3 ; partial_sum_alt[0/1] right + paddw m5, m6 ; partial_sum_alt[0/1] left + pshuflw m0, m1, q3012 + punpckhwd m1, m5 + punpcklwd m5, m0 + pmaddwd m1, m1 + pmaddwd m5, m5 + pmulld m1, m12 + pmulld m5, m13 + paddd m5, m1 ; cost1[a-d] | cost3[a-d] + + mova xm0, [pd_47130256+ 16] + mova m1, [pd_47130256] + phaddd m9, m8 + phaddd m5, m4 + phaddd m9, m5 + vpermd m0, m9 ; cost[0-3] + vpermd m1, m9 ; cost[4-7] | cost[0-3] + + ; now find the best cost + pmaxsd xm2, xm0, xm1 + pshufd xm3, xm2, q1032 + pmaxsd xm2, xm3 + pshufd xm3, xm2, q2301 + pmaxsd xm2, xm3 ; best cost + + ; find the idx using minpos + ; make everything other than the best cost negative via subtraction + ; find the min of unsigned 16-bit ints to sort out the negative values + psubd xm4, xm1, xm2 + psubd xm3, xm0, xm2 + packssdw xm3, xm4 + phminposuw xm3, xm3 + + ; convert idx to 32-bits + psrld xm3, 16 + movd eax, xm3 + + ; get idx^4 complement + vpermd m3, m1 + psubd xm2, xm3 + psrld xm2, 10 + movd [varq], xm2 + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,860 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +%macro DUP4 1-* + %rep %0 + times 4 db %1 + %rotate 1 + %endrep +%endmacro + +%macro DIRS 16 ; cdef_directions[] + %rep 4 + 16 + 4 ; 6 7 0 1 2 3 4 5 6 7 0 1 + ; masking away unused bits allows us to use a single vpaddd {1to16} + ; instruction instead of having to do vpbroadcastd + paddb + db %13 & 0x3f, -%13 & 0x3f + %rotate 1 + %endrep +%endmacro + +SECTION_RODATA 64 + +lut_perm_4x4: db 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 + db 16, 17, 0, 1, 2, 3, 4, 5, 18, 19, 8, 9, 10, 11, 12, 13 + db 20, 21, 80, 81, 82, 83, 84, 85, 22, 23, 32, 33, 34, 35, 36, 37 + db 98, 99,100,101,102,103,104,105, 50, 51, 52, 53, 54, 55, 56, 57 +lut_perm_4x8a: db 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 + db 96, 97, 0, 1, 2, 3, 4, 5, 98, 99, 8, 9, 10, 11, 12, 13 +lut_perm_4x8b:db 100,101, 16, 17, 18, 19, 20, 21,102,103, 24, 25, 26, 27, 28, 29 + db 104,105, 32, 33, 34, 35, 36, 37,106,107, 40, 41, 42, 43, 44, 45 + db 108,109, 48, 49, 50, 51, 52, 53,110,111, 56, 57, 58, 59, 60, 61 + db 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 +pd_01234567: dd 0, 1, 2, 3, 4, 5, 6, 7 +lut_perm_8x8a: db 32, 33, 34, 35, 36, 37, 38, 39, 48, 49, 50, 51, 52, 53, 54, 55 + db 36, 37, 38, 39, 40, 41, 42, 43, 52, 53, 54, 55, 56, 57, 58, 59 +lut_perm_8x8b: db 12, 13, 0, 1, 2, 3, 4, 5, 14, 15, 16, 17, 18, 19, 20, 21 + db 2, 3, 4, 5, 6, 7, 8, 9, 18, 19, 20, 21, 22, 23, 24, 25 + db 28, 29, 32, 33, 34, 35, 36, 37, 30, 31, 48, 49, 50, 51, 52, 53 + db 34, 35, 36, 37, 38, 39, 40, 41, 50, 51, 52, 53, 54, 55, 56, 57 +end_perm: db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63 +end_perm_clip: db 0, 4, 8, 12, 2, 6, 10, 14, 16, 20, 24, 28, 18, 22, 26, 30 + db 32, 36, 40, 44, 34, 38, 42, 46, 48, 52, 56, 60, 50, 54, 58, 62 + db 1, 5, 9, 13, 3, 7, 11, 15, 17, 21, 25, 29, 19, 23, 27, 31 + db 33, 37, 41, 45, 35, 39, 43, 47, 49, 53, 57, 61, 51, 55, 59, 63 +edge_mask: dq 0x00003c3c3c3c0000, 0x00003f3f3f3f0000 ; 0000, 0001 + dq 0x0000fcfcfcfc0000, 0x0000ffffffff0000 ; 0010, 0011 + dq 0x00003c3c3c3c3c3c, 0x00003f3f3f3f3f3f ; 0100, 0101 + dq 0x0000fcfcfcfcfcfc, 0x0000ffffffffffff ; 0110, 0111 + dq 0x3c3c3c3c3c3c0000, 0x3f3f3f3f3f3f0000 ; 1000, 1001 + dq 0xfcfcfcfcfcfc0000, 0xffffffffffff0000 ; 1010, 1011 + dq 0x3c3c3c3c3c3c3c3c, 0x3f3f3f3f3f3f3f3f ; 1100, 1101 + dq 0xfcfcfcfcfcfcfcfc, 0xffffffffffffffff ; 1110, 1111 +px_idx: DUP4 18, 19, 20, 21, 26, 27, 28, 29, 34, 35, 36, 37, 42, 43, 44, 45 +cdef_dirs: DIRS -7,-14, 1, -6, 1, 2, 1, 10, 9, 18, 8, 17, 8, 16, 8, 15 +gf_shr: dq 0x0102040810204080, 0x0102040810204080 ; >> 0, >> 0 + dq 0x0204081020408000, 0x0408102040800000 ; >> 1, >> 2 + dq 0x0810204080000000, 0x1020408000000000 ; >> 3, >> 4 + dq 0x2040800000000000, 0x4080000000000000 ; >> 5, >> 6 +pri_tap: db 64, 64, 32, 32, 48, 48, 48, 48 ; left-shifted by 4 +sec_tap: db 32, 32, 16, 16 +pd_268435568: dd 268435568 + +SECTION .text + +%if WIN64 +DECLARE_REG_TMP 4 +%else +DECLARE_REG_TMP 8 +%endif + +; lut: +; t0 t1 t2 t3 t4 t5 t6 t7 +; T0 T1 T2 T3 T4 T5 T6 T7 +; L0 L1 00 01 02 03 04 05 +; L2 L3 10 11 12 13 14 15 +; L4 L5 20 21 22 23 24 25 +; L6 L7 30 31 32 33 34 35 +; b0 b1 b2 b3 b4 b5 b6 b7 +; B0 B1 B2 B3 B4 B5 B6 B7 + +INIT_ZMM avx512icl +cglobal cdef_filter_4x4_8bpc, 5, 8, 13, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%define base r7-edge_mask + movq xmm0, [dstq+strideq*0] + movhps xmm0, [dstq+strideq*1] + lea r7, [edge_mask] + movq xmm1, [topq+strideq*0-2] + movhps xmm1, [topq+strideq*1-2] + mov r6d, edgem + vinserti32x4 ym0, ymm0, [leftq], 1 + lea r2, [strideq*3] + vinserti32x4 ym1, ymm1, [dstq+strideq*2], 1 + mova m5, [base+lut_perm_4x4] + vinserti32x4 m0, [dstq+r2], 2 + test r6b, 0x08 ; avoid buffer overread + jz .main + vinserti32x4 m1, [botq+strideq*0-4], 2 + vinserti32x4 m0, [botq+strideq*1-4], 3 +.main: + movifnidn prid, prim + mov t0d, dirm + mova m3, [base+px_idx] + mov r3d, dampingm + vpermi2b m5, m0, m1 ; lut + vpbroadcastd m0, [base+pd_268435568] ; (1 << 28) + (7 << 4) + pxor m7, m7 + lea r3, [r7+r3*8] ; gf_shr + (damping - 30) * 8 + vpermb m6, m3, m5 ; px + cmp r6d, 0x0f + jne .mask_edges ; mask edges only if required + test prid, prid + jz .sec_only + vpaddd m1, m3, [base+cdef_dirs+(t0+2)*4] {1to16} ; dir + vpermb m1, m1, m5 ; k0p0 k0p1 k1p0 k1p1 +%macro CDEF_FILTER_4x4_PRI 0 + vpcmpub k1, m6, m1, 6 ; px > pN + psubb m2, m1, m6 + lzcnt r6d, prid + vpsubb m2{k1}, m6, m1 ; abs(diff) + vpbroadcastb m4, prid + and prid, 1 + vgf2p8affineqb m9, m2, [r3+r6*8] {1to8}, 0 ; abs(diff) >> shift + movifnidn secd, secm + vpbroadcastd m10, [base+pri_tap+priq*4] + vpsubb m10{k1}, m7, m10 ; apply_sign(pri_tap) + psubusb m4, m9 ; imax(0, pri_strength - (abs(diff) >> shift))) + pminub m2, m4 + vpdpbusd m0, m2, m10 ; sum +%endmacro + CDEF_FILTER_4x4_PRI + test secd, secd + jz .end_no_clip + call .sec +.end_clip: + pminub m4, m6, m1 + pmaxub m1, m6 + pminub m5, m2, m3 + pmaxub m2, m3 + pminub m4, m5 + pmaxub m2, m1 + psrldq m1, m4, 2 + psrldq m3, m2, 2 + pminub m1, m4 + vpcmpw k1, m0, m7, 1 + vpshldd m6, m0, 8 + pmaxub m2, m3 + pslldq m3, m1, 1 + psubw m7, m0 + paddusw m0, m6 ; clip >0xff + vpsubusw m0{k1}, m6, m7 ; clip <0x00 + pslldq m4, m2, 1 + pminub m1, m3 + pmaxub m2, m4 + pmaxub m0, m1 + pminub m0, m2 + jmp .end +.sec_only: + movifnidn secd, secm + call .sec +.end_no_clip: + vpshldd m6, m0, 8 ; (px << 8) + ((sum > -8) << 4) + paddw m0, m6 ; (px << 8) + ((sum + (sum > -8) + 7) << 4) +.end: + mova xm1, [base+end_perm] + vpermb m0, m1, m0 ; output in bits 8-15 of each dword + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + RET +.mask_edges_sec_only: + movifnidn secd, secm + call .mask_edges_sec + jmp .end_no_clip +ALIGN function_align +.mask_edges: + vpbroadcastq m8, [base+edge_mask+r6*8] + test prid, prid + jz .mask_edges_sec_only + vpaddd m2, m3, [base+cdef_dirs+(t0+2)*4] {1to16} + vpshufbitqmb k1, m8, m2 ; index in-range + mova m1, m6 + vpermb m1{k1}, m2, m5 + CDEF_FILTER_4x4_PRI + test secd, secd + jz .end_no_clip + call .mask_edges_sec + jmp .end_clip +.mask_edges_sec: + vpaddd m4, m3, [base+cdef_dirs+(t0+4)*4] {1to16} + vpaddd m9, m3, [base+cdef_dirs+(t0+0)*4] {1to16} + vpshufbitqmb k1, m8, m4 + mova m2, m6 + vpermb m2{k1}, m4, m5 + vpshufbitqmb k1, m8, m9 + mova m3, m6 + vpermb m3{k1}, m9, m5 + jmp .sec_main +ALIGN function_align +.sec: + vpaddd m2, m3, [base+cdef_dirs+(t0+4)*4] {1to16} ; dir + 2 + vpaddd m3, [base+cdef_dirs+(t0+0)*4] {1to16} ; dir - 2 + vpermb m2, m2, m5 ; k0s0 k0s1 k1s0 k1s1 + vpermb m3, m3, m5 ; k0s2 k0s3 k1s2 k1s3 +.sec_main: + vpbroadcastd m8, [base+sec_tap] + vpcmpub k1, m6, m2, 6 + psubb m4, m2, m6 + vpbroadcastb m12, secd + lzcnt secd, secd + vpsubb m4{k1}, m6, m2 + vpcmpub k2, m6, m3, 6 + vpbroadcastq m11, [r3+secq*8] + gf2p8affineqb m10, m4, m11, 0 + psubb m5, m3, m6 + mova m9, m8 + vpsubb m8{k1}, m7, m8 + psubusb m10, m12, m10 + vpsubb m5{k2}, m6, m3 + pminub m4, m10 + vpdpbusd m0, m4, m8 + gf2p8affineqb m11, m5, m11, 0 + vpsubb m9{k2}, m7, m9 + psubusb m12, m11 + pminub m5, m12 + vpdpbusd m0, m5, m9 + ret + +DECLARE_REG_TMP 2, 7 + +; lut top lut bottom +; t0 t1 t2 t3 t4 t5 t6 t7 L4 L5 20 21 22 23 24 25 +; T0 T1 T2 T3 T4 T5 T6 T7 L6 L7 30 31 32 33 34 35 +; L0 L1 00 01 02 03 04 05 L8 L9 40 41 42 43 44 45 +; L2 L3 10 11 12 13 14 15 La Lb 50 51 52 53 54 55 +; L4 L5 20 21 22 23 24 25 Lc Ld 60 61 62 63 64 65 +; L6 L7 30 31 32 33 34 35 Le Lf 70 71 72 73 74 75 +; L8 L9 40 41 42 43 44 45 b0 b1 b2 b3 b4 b5 b6 b7 +; La Lb 50 51 52 53 54 55 B0 B1 B2 B3 B4 B5 B6 B7 + +cglobal cdef_filter_4x8_8bpc, 5, 9, 22, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%define base r8-edge_mask + vpbroadcastd ym21, strided + mov r6d, edgem + lea r8, [edge_mask] + movq xm1, [topq+strideq*0-2] + pmulld ym21, [base+pd_01234567] + kxnorb k1, k1, k1 + movq xm2, [topq+strideq*1-2] + vpgatherdq m0{k1}, [dstq+ym21] ; +0+1 +2+3 +4+5 +6+7 + mova m14, [base+lut_perm_4x8a] + movu m15, [base+lut_perm_4x8b] + test r6b, 0x08 ; avoid buffer overread + jz .main + vinserti32x4 ym1, [botq+strideq*0-2], 1 + vinserti32x4 ym2, [botq+strideq*1-2], 1 +.main: + punpcklqdq ym1, ym2 + vinserti32x4 m1, [leftq], 2 ; -2-1 +8+9 left ____ + movifnidn prid, prim + mov t0d, dirm + mova m16, [base+px_idx] + mov r3d, dampingm + vpermi2b m14, m0, m1 ; lut top + vpermi2b m15, m0, m1 ; lut bottom + vpbroadcastd m0, [base+pd_268435568] ; (1 << 28) + (7 << 4) + pxor m20, m20 + lea r3, [r8+r3*8] ; gf_shr + (damping - 30) * 8 + vpermb m2, m16, m14 ; pxt + vpermb m3, m16, m15 ; pxb + mova m1, m0 + cmp r6b, 0x0f + jne .mask_edges ; mask edges only if required + test prid, prid + jz .sec_only + vpaddd m6, m16, [base+cdef_dirs+(t0+2)*4] {1to16} ; dir + vpermb m4, m6, m14 ; pNt k0p0 k0p1 k1p0 k1p1 + vpermb m5, m6, m15 ; pNb +%macro CDEF_FILTER_4x8_PRI 0 + vpcmpub k1, m2, m4, 6 ; pxt > pNt + vpcmpub k2, m3, m5, 6 ; pxb > pNb + psubb m6, m4, m2 + psubb m7, m5, m3 + lzcnt r6d, prid + vpsubb m6{k1}, m2, m4 ; abs(diff_top) + vpsubb m7{k2}, m3, m5 ; abs(diff_bottom) + vpbroadcastb m13, prid + vpbroadcastq m9, [r3+r6*8] + and prid, 1 + vpbroadcastd m11, [base+pri_tap+priq*4] + vgf2p8affineqb m8, m6, m9, 0 ; abs(dt) >> shift + vgf2p8affineqb m9, m7, m9, 0 ; abs(db) >> shift + mova m10, m11 + movifnidn t1d, secm + vpsubb m10{k1}, m20, m11 ; apply_sign(pri_tap_top) + vpsubb m11{k2}, m20, m11 ; apply_sign(pri_tap_bottom) + psubusb m12, m13, m8 ; imax(0, pri_strength - (abs(dt) >> shift))) + psubusb m13, m13, m9 ; imax(0, pri_strength - (abs(db) >> shift))) + pminub m6, m12 + pminub m7, m13 + vpdpbusd m0, m6, m10 ; sum top + vpdpbusd m1, m7, m11 ; sum bottom +%endmacro + CDEF_FILTER_4x8_PRI + test t1d, t1d ; sec + jz .end_no_clip + call .sec +.end_clip: + pminub m10, m4, m2 + pminub m12, m6, m8 + pminub m11, m5, m3 + pminub m13, m7, m9 + pmaxub m4, m2 + pmaxub m6, m8 + pmaxub m5, m3 + pmaxub m7, m9 + pminub m10, m12 + pminub m11, m13 + pmaxub m4, m6 + pmaxub m5, m7 + mov r2d, 0xAAAAAAAA + kmovd k1, r2d + kxnorb k2, k2, k2 ; hw lw + vpshrdd m12, m0, m1, 16 ; m1lw m0hw + vpshrdd m6, m10, m11, 16 ; m11lw m10hw + vpshrdd m8, m4, m5, 16 ; m5lw m4hw + vpblendmw m7{k1}, m10, m11 ; m11hw m10lw + vpblendmw m9{k1}, m4, m5 ; m5hw m4lw + vpblendmw m4{k1}, m0, m12 ; m1lw m0lw + vpblendmw m5{k1}, m12, m1 ; m1hw m0hw + vpshrdd m2, m3, 16 + pminub m6, m7 + pmaxub m8, m9 + mova ym14, [base+end_perm] + vpcmpw k1, m4, m20, 1 + vpshldw m2, m5, 8 + pslldq m7, m6, 1 + pslldq m9, m8, 1 + psubw m5, m20, m4 + paddusw m0, m4, m2 ; clip >0xff + pminub m6, m7 + pmaxub m8, m9 + psubusw m0{k1}, m2, m5 ; clip <0x00 + pmaxub m0, m6 + pminub m0, m8 + vpermb m0, m14, m0 + vpscatterdd [dstq+ym21]{k2}, ym0 + RET +.sec_only: + movifnidn t1d, secm + call .sec +.end_no_clip: + mova ym4, [base+end_perm] + kxnorb k1, k1, k1 + vpshldd m2, m0, 8 ; (px << 8) + ((sum > -8) << 4) + vpshldd m3, m1, 8 + paddw m0, m2 ; (px << 8) + ((sum + (sum > -8) + 7) << 4) + paddw m1, m3 + pslld m0, 16 + vpshrdd m0, m1, 16 + vpermb m0, m4, m0 ; output in bits 8-15 of each word + vpscatterdd [dstq+ym21]{k1}, ym0 + RET +.mask_edges_sec_only: + movifnidn t1d, secm + call .mask_edges_sec + jmp .end_no_clip +ALIGN function_align +.mask_edges: + mov t1d, r6d + or r6d, 8 ; top 4x4 has bottom + or t1d, 4 ; bottom 4x4 has top + vpbroadcastq m17, [base+edge_mask+r6*8] + vpbroadcastq m18, [base+edge_mask+t1*8] + test prid, prid + jz .mask_edges_sec_only + vpaddd m6, m16, [base+cdef_dirs+(t0+2)*4] {1to16} + vpshufbitqmb k1, m17, m6 ; index in-range + vpshufbitqmb k2, m18, m6 + mova m4, m2 + mova m5, m3 + vpermb m4{k1}, m6, m14 + vpermb m5{k2}, m6, m15 + CDEF_FILTER_4x8_PRI + test t1d, t1d + jz .end_no_clip + call .mask_edges_sec + jmp .end_clip +.mask_edges_sec: + vpaddd m10, m16, [base+cdef_dirs+(t0+4)*4] {1to16} + vpaddd m11, m16, [base+cdef_dirs+(t0+0)*4] {1to16} + vpshufbitqmb k1, m17, m10 + vpshufbitqmb k2, m18, m10 + vpshufbitqmb k3, m17, m11 + vpshufbitqmb k4, m18, m11 + mova m6, m2 + mova m7, m3 + mova m8, m2 + mova m9, m3 + vpermb m6{k1}, m10, m14 + vpermb m7{k2}, m10, m15 + vpermb m8{k3}, m11, m14 + vpermb m9{k4}, m11, m15 + jmp .sec_main +ALIGN function_align +.sec: + vpaddd m8, m16, [base+cdef_dirs+(t0+4)*4] {1to16} ; dir + 2 + vpaddd m9, m16, [base+cdef_dirs+(t0+0)*4] {1to16} ; dir - 2 + vpermb m6, m8, m14 ; pNt k0s0 k0s1 k1s0 k1s1 + vpermb m7, m8, m15 ; pNb + vpermb m8, m9, m14 ; pNt k0s2 k0s3 k1s2 k1s3 + vpermb m9, m9, m15 ; pNb +.sec_main: + vpbroadcastb m18, t1d + lzcnt t1d, t1d + vpcmpub k1, m2, m6, 6 + vpcmpub k2, m3, m7, 6 + vpcmpub k3, m2, m8, 6 + vpcmpub k4, m3, m9, 6 + vpbroadcastq m17, [r3+t1*8] + psubb m10, m6, m2 + psubb m11, m7, m3 + psubb m12, m8, m2 + psubb m13, m9, m3 + vpsubb m10{k1}, m2, m6 ; abs(dt0) + vpsubb m11{k2}, m3, m7 ; abs(db0) + vpsubb m12{k3}, m2, m8 ; abs(dt1) + vpsubb m13{k4}, m3, m9 ; abs(db1) + vpbroadcastd m19, [base+sec_tap] + gf2p8affineqb m14, m10, m17, 0 ; abs(dt0) >> shift + gf2p8affineqb m15, m11, m17, 0 ; abs(db0) >> shift + gf2p8affineqb m16, m12, m17, 0 ; abs(dt1) >> shift + gf2p8affineqb m17, m13, m17, 0 ; abs(db1) >> shift + psubusb m14, m18, m14 ; imax(0, sec_strength - (abs(dt0) >> shift))) + psubusb m15, m18, m15 ; imax(0, sec_strength - (abs(db0) >> shift))) + psubusb m16, m18, m16 ; imax(0, sec_strength - (abs(dt1) >> shift))) + psubusb m17, m18, m17 ; imax(0, sec_strength - (abs(db1) >> shift))) + pminub m10, m14 + pminub m11, m15 + pminub m12, m16 + pminub m13, m17 + mova m14, m19 + mova m15, m19 + mova m16, m19 + vpsubb m14{k1}, m20, m19 ; apply_sign(sec_tap_top_0) + vpsubb m15{k2}, m20, m19 ; apply_sign(sec_tap_bottom_0) + vpsubb m16{k3}, m20, m19 ; apply_sign(sec_tap_top_1) + vpsubb m19{k4}, m20, m19 ; apply_sign(sec_tap_bottom_1) + vpdpbusd m0, m10, m14 + vpdpbusd m1, m11, m15 + vpdpbusd m0, m12, m16 + vpdpbusd m1, m13, m19 + ret + +; lut tl lut tr +; t0 t1 t2 t3 t4 t5 t6 t7 t4 t5 t6 t7 t8 t9 ta tb +; T0 T1 T2 T3 T4 T5 T6 T7 T4 T5 T6 T7 T8 T9 Ta Tb +; L0 L1 00 01 02 03 04 05 02 03 04 05 06 07 08 09 +; L2 L3 10 11 12 13 14 15 12 13 14 15 16 17 18 19 +; L4 L5 20 21 22 23 24 25 22 23 24 25 26 27 28 29 +; L6 L7 30 31 32 33 34 35 32 33 34 35 36 37 38 39 +; L8 L9 40 41 42 43 44 45 42 43 44 45 46 47 48 49 +; La Lb 50 51 52 53 54 55 52 53 54 55 56 57 58 59 +; lut bl lut br +; L4 L5 20 21 22 23 24 25 22 23 24 25 26 27 28 29 +; L6 L7 30 31 32 33 34 35 32 33 34 35 36 37 38 39 +; L8 L9 40 41 42 43 44 45 42 43 44 45 46 47 48 49 +; La Lb 50 51 52 53 54 55 52 53 54 55 56 57 58 59 +; Lc Ld 60 61 62 63 64 65 62 63 64 65 66 67 68 69 +; Le Lf 70 71 72 73 74 75 72 73 74 75 76 77 78 79 +; b0 b1 b2 b3 b4 b5 b6 b7 b4 b5 b6 b7 b8 b9 ba bb +; B0 B1 B2 B3 B4 B5 B6 B7 B4 B5 B6 B7 B8 B9 Ba Bb + +cglobal cdef_filter_8x8_8bpc, 5, 11, 32, 4*64, dst, stride, left, top, bot, \ + pri, sec, dir, damping, edge +%define base r8-edge_mask + movu xm16, [dstq+strideq*0] + pinsrd xm16, [leftq+4*0], 3 + mov r6d, edgem + vinserti128 ym16, [dstq+strideq*1], 1 + lea r10, [dstq+strideq*4] + movu xm17, [dstq+strideq*2] + vinserti32x4 m16, [topq+strideq*0-2], 2 + lea r9, [strideq*3] + pinsrd xm17, [leftq+4*1], 3 + vinserti32x4 m16, [topq+strideq*1-2], 3 ; 0 1 t T + lea r8, [edge_mask] + vinserti128 ym17, [dstq+r9 ], 1 + vpbroadcastd ym18, [leftq+4*2] + vpblendd ym17, ym18, 0x80 + movu xm18, [r10 +strideq*2] + vinserti32x4 m17, [r10 +strideq*0], 2 + pinsrd xm18, [leftq+4*3], 3 + vinserti32x4 m17, [r10 +strideq*1], 3 ; 2 3 4 5 + vinserti128 ym18, [r10 +r9 ], 1 + test r6b, 0x08 ; avoid buffer overread + jz .main + vinserti32x4 m18, [botq+strideq*0-2], 2 + vinserti32x4 m18, [botq+strideq*1-2], 3 ; 6 7 b B +.main: + mova m0, [base+lut_perm_8x8a] + movu m1, [base+lut_perm_8x8b] + mova m30, [base+px_idx] + vpermb m16, m0, m16 + movifnidn prid, prim + vpermb m17, m1, m17 + mov t0d, dirm + vpermb m18, m0, m18 + mov r3d, dampingm + vshufi32x4 m12, m16, m17, q2020 ; lut tl + vshufi32x4 m13, m16, m17, q3131 ; lut tr + vshufi32x4 m14, m17, m18, q0220 ; lut bl + vshufi32x4 m15, m17, m18, q1331 ; lut br + vpbroadcastd m0, [base+pd_268435568] ; (1 << 28) + (7 << 4) + pxor m31, m31 + lea r3, [r8+r3*8] ; gf_shr + (damping - 30) * 8 + vpermb m4, m30, m12 ; pxtl + mova m1, m0 + vpermb m5, m30, m13 ; pxtr + mova m2, m0 + vpermb m6, m30, m14 ; pxbl + mova m3, m0 + vpermb m7, m30, m15 ; pxbr + cmp r6b, 0x0f + jne .mask_edges ; mask edges only if required + test prid, prid + jz .sec_only + vpaddd m11, m30, [base+cdef_dirs+(t0+2)*4] {1to16} ; dir + vpermb m8, m11, m12 ; pNtl k0p0 k0p1 k1p0 k1p1 + vpermb m9, m11, m13 ; pNtr + vpermb m10, m11, m14 ; pNbl + vpermb m11, m11, m15 ; pNbr +%macro CDEF_FILTER_8x8_PRI 0 + vpcmpub k1, m4, m8, 6 ; pxtl > pNtl + vpcmpub k2, m5, m9, 6 ; pxtr > pNtr + vpcmpub k3, m6, m10, 6 ; pxbl > pNbl + vpcmpub k4, m7, m11, 6 ; pxbr > pNbr + psubb m16, m8, m4 + psubb m17, m9, m5 + psubb m18, m10, m6 + psubb m19, m11, m7 + lzcnt r6d, prid + vpsubb m16{k1}, m4, m8 ; abs(diff_tl) + vpsubb m17{k2}, m5, m9 ; abs(diff_tr) + vpsubb m18{k3}, m6, m10 ; abs(diff_bl) + vpsubb m19{k4}, m7, m11 ; abs(diff_br) + vpbroadcastq m28, [r3+r6*8] + vpbroadcastb m29, prid + and prid, 1 + vpbroadcastd m27, [base+pri_tap+priq*4] + vgf2p8affineqb m20, m16, m28, 0 ; abs(dtl) >> shift + vgf2p8affineqb m21, m17, m28, 0 ; abs(dtr) >> shift + vgf2p8affineqb m22, m18, m28, 0 ; abs(dbl) >> shift + vgf2p8affineqb m23, m19, m28, 0 ; abs(dbl) >> shift + mova m24, m27 + mova m25, m27 + mova m26, m27 + movifnidn t1d, secm + vpsubb m24{k1}, m31, m27 ; apply_sign(pri_tap_tl) + vpsubb m25{k2}, m31, m27 ; apply_sign(pri_tap_tr) + vpsubb m26{k3}, m31, m27 ; apply_sign(pri_tap_tl) + vpsubb m27{k4}, m31, m27 ; apply_sign(pri_tap_tr) + psubusb m20, m29, m20 ; imax(0, pri_strength - (abs(dtl) >> shift))) + psubusb m21, m29, m21 ; imax(0, pri_strength - (abs(dtr) >> shift))) + psubusb m22, m29, m22 ; imax(0, pri_strength - (abs(dbl) >> shift))) + psubusb m23, m29, m23 ; imax(0, pri_strength - (abs(dbr) >> shift))) + pminub m16, m20 + pminub m17, m21 + pminub m18, m22 + pminub m19, m23 + vpdpbusd m0, m16, m24 ; sum tl + vpdpbusd m1, m17, m25 ; sum tr + vpdpbusd m2, m18, m26 ; sum bl + vpdpbusd m3, m19, m27 ; sum br +%endmacro + CDEF_FILTER_8x8_PRI + test t1d, t1d ; sec + jz .end_no_clip + call .sec +.end_clip: + pminub m20, m8, m4 + pminub m24, m12, m16 + pminub m21, m9, m5 + pminub m25, m13, m17 + pminub m22, m10, m6 + pminub m26, m14, m18 + pminub m23, m11, m7 + pminub m27, m15, m19 + pmaxub m8, m4 + pmaxub m12, m16 + pmaxub m9, m5 + pmaxub m13, m17 + pmaxub m10, m6 + pmaxub m14, m18 + pmaxub m11, m7 + pmaxub m15, m19 + pminub m20, m24 + pminub m21, m25 + pminub m22, m26 + pminub m23, m27 + pmaxub m8, m12 + pmaxub m9, m13 + pmaxub m10, m14 + pmaxub m11, m15 + mov r2d, 0xAAAAAAAA + kmovd k1, r2d + vpshrdd m24, m0, m1, 16 + vpshrdd m25, m2, m3, 16 + vpshrdd m12, m20, m21, 16 + vpshrdd m14, m22, m23, 16 + vpshrdd m16, m8, m9, 16 + vpshrdd m18, m10, m11, 16 + vpblendmw m13{k1}, m20, m21 + vpblendmw m15{k1}, m22, m23 + vpblendmw m17{k1}, m8, m9 + vpblendmw m19{k1}, m10, m11 + vpblendmw m20{k1}, m0, m24 + vpblendmw m21{k1}, m24, m1 + vpblendmw m22{k1}, m2, m25 + vpblendmw m23{k1}, m25, m3 + vpshrdd m4, m5, 16 + vpshrdd m6, m7, 16 + pminub m12, m13 + pminub m14, m15 + pmaxub m16, m17 + pmaxub m18, m19 + mova m8, [base+end_perm_clip] + vpcmpw k2, m20, m31, 1 + vpcmpw k3, m22, m31, 1 + vpshldw m4, m21, 8 + vpshldw m6, m23, 8 + kunpckdq k1, k1, k1 + kxnorb k4, k4, k4 + vpshrdw m11, m12, m14, 8 + vpshrdw m15, m16, m18, 8 + vpblendmb m13{k1}, m12, m14 + vpblendmb m17{k1}, m16, m18 + psubw m21, m31, m20 + psubw m23, m31, m22 + paddusw m0, m20, m4 ; clip >0xff + paddusw m1, m22, m6 + pminub m11, m13 + pmaxub m15, m17 + psubusw m0{k2}, m4, m21 ; clip <0x00 + psubusw m1{k3}, m6, m23 + psrlw m0, 8 + vmovdqu8 m0{k1}, m1 + pmaxub m0, m11 + pminub m0, m15 + vpermb m0, m8, m0 + vextracti32x4 xm1, m0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*2], xm1 + movq [r10 +strideq*0], xm2 + movq [r10 +strideq*2], xm3 + movhps [dstq+strideq*1], xm0 + movhps [dstq+r9 ], xm1 + movhps [r10 +strideq*1], xm2 + movhps [r10 +r9 ], xm3 + RET +.sec_only: + movifnidn t1d, secm + call .sec +.end_no_clip: + mova xm8, [base+end_perm] + kxnorb k1, k1, k1 + vpshldd m4, m0, 8 ; (px << 8) + ((sum > -8) << 4) + vpshldd m5, m1, 8 + vpshldd m6, m2, 8 + vpshldd m7, m3, 8 + paddw m0, m4 ; (px << 8) + ((sum + (sum > -8) + 7) << 4) + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + vpermb m0, m8, m0 + vpermb m1, m8, m1 + vpermb m2, m8, m2 + vpermb m3, m8, m3 + punpckldq m4, m0, m1 + punpckhdq m0, m1 + punpckldq m5, m2, m3 + punpckhdq m2, m3 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*2], xm0 + movq [r10 +strideq*0], xm5 + movq [r10 +strideq*2], xm2 + movhps [dstq+strideq*1], xm4 + movhps [dstq+r9 ], xm0 + movhps [r10 +strideq*1], xm5 + movhps [r10 +r9 ], xm2 + RET +.mask_edges_sec_only: + movifnidn t1d, secm + call .mask_edges_sec + jmp .end_no_clip +ALIGN function_align +.mask_edges: + mov t0d, r6d + mov t1d, r6d + or t0d, 0xA ; top-left 4x4 has bottom and right + or t1d, 0x9 ; top-right 4x4 has bottom and left + vpbroadcastq m26, [base+edge_mask+t0*8] + vpbroadcastq m27, [base+edge_mask+t1*8] + mov t1d, r6d + or r6d, 0x6 ; bottom-left 4x4 has top and right + or t1d, 0x5 ; bottom-right 4x4 has top and left + vpbroadcastq m28, [base+edge_mask+r6*8] + vpbroadcastq m29, [base+edge_mask+t1*8] + mov t0d, dirm + test prid, prid + jz .mask_edges_sec_only + vpaddd m20, m30, [base+cdef_dirs+(t0+2)*4] {1to16} + vpshufbitqmb k1, m26, m20 ; index in-range + vpshufbitqmb k2, m27, m20 + vpshufbitqmb k3, m28, m20 + vpshufbitqmb k4, m29, m20 + mova m8, m4 + mova m9, m5 + mova m10, m6 + mova m11, m7 + vpermb m8{k1}, m20, m12 + vpermb m9{k2}, m20, m13 + vpermb m10{k3}, m20, m14 + vpermb m11{k4}, m20, m15 + mova [rsp+0x00], m26 + mova [rsp+0x40], m27 + mova [rsp+0x80], m28 + mova [rsp+0xC0], m29 + CDEF_FILTER_8x8_PRI + test t1d, t1d + jz .end_no_clip + mova m26, [rsp+0x00] + mova m27, [rsp+0x40] + mova m28, [rsp+0x80] + mova m29, [rsp+0xC0] + call .mask_edges_sec + jmp .end_clip +.mask_edges_sec: + vpaddd m20, m30, [base+cdef_dirs+(t0+4)*4] {1to16} + vpaddd m21, m30, [base+cdef_dirs+(t0+0)*4] {1to16} + vpshufbitqmb k1, m26, m20 + vpshufbitqmb k2, m27, m20 + vpshufbitqmb k3, m28, m20 + vpshufbitqmb k4, m29, m20 + mova m16, m4 + mova m17, m5 + mova m18, m6 + mova m19, m7 + vpermb m16{k1}, m20, m12 + vpermb m17{k2}, m20, m13 + vpermb m18{k3}, m20, m14 + vpermb m19{k4}, m20, m15 + vpshufbitqmb k1, m26, m21 + vpshufbitqmb k2, m27, m21 + vpshufbitqmb k3, m28, m21 + vpshufbitqmb k4, m29, m21 + vpermb m12, m21, m12 + vpermb m13, m21, m13 + vpermb m14, m21, m14 + vpermb m15, m21, m15 + vpblendmb m12{k1}, m4, m12 + vpblendmb m13{k2}, m5, m13 + vpblendmb m14{k3}, m6, m14 + vpblendmb m15{k4}, m7, m15 + jmp .sec_main +ALIGN function_align +.sec: + vpaddd m20, m30, [base+cdef_dirs+(t0+4)*4] {1to16} ; dir + 2 + vpaddd m21, m30, [base+cdef_dirs+(t0+0)*4] {1to16} ; dir - 2 + vpermb m16, m20, m12 ; pNtl k0s0 k0s1 k1s0 k1s1 + vpermb m17, m20, m13 ; pNtr + vpermb m18, m20, m14 ; pNbl + vpermb m19, m20, m15 ; pNbr + vpermb m12, m21, m12 ; pNtl k0s2 k0s3 k1s2 k1s3 + vpermb m13, m21, m13 ; pNtr + vpermb m14, m21, m14 ; pNbl + vpermb m15, m21, m15 ; pNbr +.sec_main: +%macro CDEF_FILTER_8x8_SEC 4-5 0 ; load constants + vpcmpub k1, m4, %1, 6 + vpcmpub k2, m5, %2, 6 + vpcmpub k3, m6, %3, 6 + vpcmpub k4, m7, %4, 6 + psubb m20, %1, m4 + psubb m21, %2, m5 + psubb m22, %3, m6 + psubb m23, %4, m7 +%if %5 + vpbroadcastb m28, t1d + lzcnt t1d, t1d + vpbroadcastq m29, [r3+t1*8] +%endif + vpsubb m20{k1}, m4, %1 + vpsubb m21{k2}, m5, %2 + vpsubb m22{k3}, m6, %3 + vpsubb m23{k4}, m7, %4 + gf2p8affineqb m24, m20, m29, 0 + gf2p8affineqb m25, m21, m29, 0 + gf2p8affineqb m26, m22, m29, 0 + gf2p8affineqb m27, m23, m29, 0 +%if %5 + vpbroadcastd m30, [base+sec_tap] +%endif + psubusb m24, m28, m24 + psubusb m25, m28, m25 + psubusb m26, m28, m26 + psubusb m27, m28, m27 + pminub m20, m24 + pminub m21, m25 + pminub m22, m26 + pminub m23, m27 + mova m24, m30 + mova m25, m30 + mova m26, m30 + mova m27, m30 + vpsubb m24{k1}, m31, m30 + vpsubb m25{k2}, m31, m30 + vpsubb m26{k3}, m31, m30 + vpsubb m27{k4}, m31, m30 + vpdpbusd m0, m20, m24 + vpdpbusd m1, m21, m25 + vpdpbusd m2, m22, m26 + vpdpbusd m3, m23, m27 +%endmacro + CDEF_FILTER_8x8_SEC m16, m17, m18, m19, 1 + CDEF_FILTER_8x8_SEC m12, m13, m14, m15 + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_dist.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_dist.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_dist.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_dist.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,233 @@ +; Copyright (c) 2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION .text + +%if ARCH_X86_64 + +; m0: zero register +; m1: src input +; m2: dst input +; m3 = sum(src_{i,j}) +; m4 = sum(src_{i,j}^2) +; m5 = sum(dst_{i,j}) +; m6 = sum(dst_{i,j}^2) +; m7 = sum(src_{i,j} * dst_{i,j}) +; m8: tmp register +%macro CDEF_DIST_W8_SSE2 0 + psadbw m8, m1, m0 ; sum pixel values + paddd m3, m8 ; accumulate + punpcklbw m1, m0 ; convert to 16-bits + pmaddwd m8, m1, m1 ; square and horz add + paddd m4, m8 ; accumulate + psadbw m8, m2, m0 ; same as above, but for dst + paddd m5, m8 + punpcklbw m2, m0 + pmaddwd m8, m2, m2 + paddd m6, m8 + pmaddwd m8, m1, m2 ; src_{i,j} * dst_{i,j} (and horz add) + paddd m7, m8 +%endmacro + +; Refine sums into variances and sse +; parameter: scale log2 relative to 8x8 +%macro CDEF_DIST_REFINE_SSE2 1 + ; Compute [sum(src)^2, sum(dst)^2] + punpckldq m3, m5 ; store sums in a single vector + pcmpeqd m0, m0 ; -1 (for rounding) + pmaddwd m3, m3 + + ; Divide by area and round + pslld m0, 5 - %1 + psubd m3, m0 ; + (1 << (5 - %1)) + psrld m3, 6 - %1 + + pshufd m0, m7, q3232 ; reduce sum(src * dst) + punpckldq m1, m4, m6 ; reduce [sum(src^2), sum(dst^2)] + paddd m7, m0 + punpckhdq m4, m6 + paddd m1, m4 + paddd m7, m7 ; 2 * sum(src * dst) [Partially reduced; len 2] + pshufd m0, m1, q3232 + + ; Equivelent to: + ; paddd m1, m0 + ; psubd m0, m1, m7 ; sse = sum(src^2) + sum(dst^2) - sum(src * dst) + ; but with fewer dependancies + psubd m7, m1 + paddd m1, m0 ; [sum(src^2), sum(dst^2)] + psubd m0, m7 ; sse (Needs reducing; len 2) + + psubd m1, m3 ; [src variance, dst variance] + ; Scale up the variances up to 8x8 + ; TODO: this can be handled inside ssim boost in the future +%if %1 != 0 + pslld m1, %1 +%endif + movq [ret_ptrq], m1 + + ; Final reduce for sse + pshuflw m2, m0, q3232 + paddd m0, m2 + movd [ret_ptrq+8], m0 +%endmacro + +INIT_XMM sse2 +cglobal cdef_dist_kernel_4x4, 5, 5, 9, \ + src, src_stride, dst, dst_stride, ret_ptr + pxor m0, m0 + movd m1, [srcq] + movd m2, [srcq+src_strideq] + punpckldq m1, m2 + movd m2, [dstq] + movd m8, [dstq+dst_strideq] + lea srcq, [srcq+2*src_strideq] + lea dstq, [dstq+2*dst_strideq] + punpckldq m2, m8 + psadbw m3, m1, m0 + punpcklbw m1, m0 + pmaddwd m4, m1, m1 + psadbw m5, m2, m0 + punpcklbw m2, m0 + pmaddwd m6, m2, m2 + pmaddwd m7, m1, m2 + + movd m1, [srcq] + movd m2, [srcq+src_strideq] + punpckldq m1, m2 + movd m2, [dstq] + movd m8, [dstq+dst_strideq] + punpckldq m2, m8 + CDEF_DIST_W8_SSE2 + + CDEF_DIST_REFINE_SSE2 2 + RET + +cglobal cdef_dist_kernel_4x8, 5, 7, 9, \ + src, src_stride, dst, dst_stride, ret_ptr, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + + pxor m0, m0 + movd m1, [srcq] + movd m2, [srcq+src_strideq] + punpckldq m1, m2 + movd m2, [dstq] + movd m8, [dstq+dst_strideq] + punpckldq m2, m8 + psadbw m3, m1, m0 + punpcklbw m1, m0 + pmaddwd m4, m1, m1 + psadbw m5, m2, m0 + punpcklbw m2, m0 + pmaddwd m6, m2, m2 + pmaddwd m7, m1, m2 + + movd m1, [srcq+2*src_strideq] + movd m2, [srcq+src_stride3q] + punpckldq m1, m2 + movd m2, [dstq+2*dst_strideq] + movd m8, [dstq+dst_stride3q] + lea srcq, [srcq+4*src_strideq] + lea dstq, [dstq+4*dst_strideq] + punpckldq m2, m8 + CDEF_DIST_W8_SSE2 + movd m1, [srcq] + movd m2, [srcq+src_strideq] + punpckldq m1, m2 + movd m2, [dstq] + movd m8, [dstq+dst_strideq] + punpckldq m2, m8 + CDEF_DIST_W8_SSE2 + movd m1, [srcq+2*src_strideq] + movd m2, [srcq+src_stride3q] + punpckldq m1, m2 + movd m2, [dstq+2*dst_strideq] + movd m8, [dstq+dst_stride3q] + punpckldq m2, m8 + CDEF_DIST_W8_SSE2 + + CDEF_DIST_REFINE_SSE2 1 + RET + +cglobal cdef_dist_kernel_8x4, 5, 5, 9, \ + src, src_stride, dst, dst_stride, ret_ptr + pxor m0, m0 + movq m1, [srcq] + psadbw m3, m1, m0 + punpcklbw m1, m0 + pmaddwd m4, m1, m1 + movq m2, [dstq] + psadbw m5, m2, m0 + punpcklbw m2, m0 + pmaddwd m6, m2, m2 + pmaddwd m7, m1, m2 + + movq m1, [srcq+src_strideq] + movq m2, [dstq+dst_strideq] + lea srcq, [srcq+2*src_strideq] + lea dstq, [dstq+2*dst_strideq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq] + movq m2, [dstq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+src_strideq] + movq m2, [dstq+dst_strideq] + CDEF_DIST_W8_SSE2 + + CDEF_DIST_REFINE_SSE2 1 + RET + +cglobal cdef_dist_kernel_8x8, 5, 7, 9, \ + src, src_stride, dst, dst_stride, ret_ptr, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + + pxor m0, m0 + movq m1, [srcq] + psadbw m3, m1, m0 + punpcklbw m1, m0 + pmaddwd m4, m1, m1 + movq m2, [dstq] + psadbw m5, m2, m0 + punpcklbw m2, m0 + pmaddwd m6, m2, m2 + pmaddwd m7, m1, m2 + + movq m1, [srcq+src_strideq] + movq m2, [dstq+dst_strideq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+2*src_strideq] + movq m2, [dstq+2*dst_strideq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+src_stride3q] + movq m2, [dstq+dst_stride3q] + CDEF_DIST_W8_SSE2 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + + movq m1, [srcq] + movq m2, [dstq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+src_strideq] + movq m2, [dstq+dst_strideq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+2*src_strideq] + movq m2, [dstq+2*dst_strideq] + CDEF_DIST_W8_SSE2 + movq m1, [srcq+src_stride3q] + movq m2, [dstq+dst_stride3q] + CDEF_DIST_W8_SSE2 + + CDEF_DIST_REFINE_SSE2 0 + RET +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_rav1e.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_rav1e.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_rav1e.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_rav1e.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,266 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 +pd_47130256: dd 4, 7, 1, 3, 0, 2, 5, 6 +div_table: dd 840, 420, 280, 210, 168, 140, 120, 105 + dd 420, 210, 140, 105 +shufw_6543210x: db 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15 +shufb_lohi: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 +tap_table: ; masks for 8 bit shifts + db 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 + ; weights + db 4, 2, 3, 3, 2, 1 + db 0, 0 ; padding + db -1, -2, 0, 0, 1, 2, 0, 0 + db 0, -1, 0, 1, 1, 2, 0, 0 + db 0, 0, 1, 2, -1, -2, 0, 0 + db 0, 1, 1, 2, 0, -1, 0, 0 + db 1, 2, 1, 2, 0, 0, 0, 0 + db 1, 2, 1, 2, 0, 1, 0, 0 + db 1, 2, -1, -2, 1, 2, 0, 0 + db 1, 2, 0, -1, 1, 2, 0, 0 + + db 1, 2, 1, 2, 0, 0, 0, 0 + db 1, 2, 1, 2, 0, -1, 0, 0 + db 1, 2, 1, 2, 1, 2, 0, 0 + db 1, 2, 0, 1, 1, 2, 0, 0 + db 1, 2, 0, 0, 1, 2, 0, 0 + db 0, 1, 0, -1, 1, 2, 0, 0 + db 0, 0, 1, 2, 1, 2, 0, 0 + db 0, -1, 1, 2, 0, 1, 0, 0 +pw_128: times 2 dw 128 +pw_2048: times 2 dw 2048 + +SECTION .text + +; stride unused +%macro ACCUMULATE_TAP 7 ; tap_offset, shift, mask, strength, mul_tap, w, stride + ; load p0/p1 + movsx offq, dword [offsets+kq*4+%1] ; off1 +%if %6 == 4 + movq xm5, [tmp0q+offq*2] ; p0 + movq xm6, [tmp2q+offq*2] + movhps xm5, [tmp1q+offq*2] + movhps xm6, [tmp3q+offq*2] + vinserti128 m5, xm6, 1 +%else + movu xm5, [tmp0q+offq*2] ; p0 + vinserti128 m5, [tmp1q+offq*2], 1 +%endif + neg offq ; -off1 +%if %6 == 4 + movq xm6, [tmp0q+offq*2] ; p1 + movq xm9, [tmp2q+offq*2] + movhps xm6, [tmp1q+offq*2] + movhps xm9, [tmp3q+offq*2] + vinserti128 m6, xm9, 1 +%else + movu xm6, [tmp0q+offq*2] ; p1 + vinserti128 m6, [tmp1q+offq*2], 1 +%endif + ; out of bounds values are set to a value that is a both a large unsigned + ; value and a negative signed value. + ; use signed max and unsigned min to remove them + pmaxsw m7, m5 ; max after p0 + pminuw m8, m5 ; min after p0 + pmaxsw m7, m6 ; max after p1 + pminuw m8, m6 ; min after p1 + + ; accumulate sum[m15] over p0/p1 + ; calculate difference before converting + psubw m5, m4 ; diff_p0(p0 - px) + psubw m6, m4 ; diff_p1(p1 - px) + + ; convert to 8-bits with signed saturation + ; saturating to large diffs has no impact on the results + packsswb m5, m6 + + ; group into pairs so we can accumulate using maddubsw + pshufb m5, m12 + pabsb m9, m5 + psignb m10, %5, m5 + psrlw m5, m9, %2 ; emulate 8-bit shift + pand m5, %3 + psubusb m5, %4, m5 + + ; use unsigned min since abs diff can equal 0x80 + pminub m5, m9 + pmaddubsw m5, m10 + paddw m15, m5 +%endmacro + +%macro CDEF_FILTER 2 ; w, h +INIT_YMM avx2 +%if %1*%2*2/mmsize > 1 + %if %1 == 4 +cglobal cdef_filter_%1x%2, 4, 13, 16, 64 + %else +cglobal cdef_filter_%1x%2, 4, 11, 16, 64 + %endif +%else +cglobal cdef_filter_%1x%2, 4, 12, 16, 64 +%endif +%define offsets rsp+32 + DEFINE_ARGS dst, dst_stride, tmp, tmp_stride, pri, sec, pridmp, table, \ + secdmp, damping, dir + lea tableq, [tap_table] + + ; off1/2/3[k] [6 total] + movd xm2, tmp_strided + vpbroadcastd m2, xm2 + mov dird, r6m + pmovsxbd m3, [tableq+dirq*8+16] + pmulld m2, m3 + pmovsxbd m4, [tableq+dirq*8+16+64] + paddd m2, m4 + mova [offsets], m2 + + ; register to shuffle values into after packing + vbroadcasti128 m12, [shufb_lohi] + + movifnidn prid, prim + mov dampingd, r7m + lzcnt pridmpd, prid +%if UNIX64 + movd xm0, prid + movd xm1, secd +%endif + lzcnt secdmpd, secm + sub dampingd, 31 + DEFINE_ARGS dst, dst_stride, tmp, tmp_stride, pri, sec, pridmp, table, \ + secdmp, damping, zero + xor zerod, zerod + add pridmpd, dampingd + cmovl pridmpd, zerod + add secdmpd, dampingd + cmovl secdmpd, zerod + mov [rsp+0], pridmpq ; pri_shift + mov [rsp+8], secdmpq ; sec_shift + + DEFINE_ARGS dst, dst_stride, tmp, tmp_stride, pri, sec, pridmp, table, \ + secdmp + vpbroadcastb m13, [tableq+pridmpq] ; pri_shift_mask + vpbroadcastb m14, [tableq+secdmpq] ; sec_shift_mask + + ; pri/sec_taps[k] [4 total] + DEFINE_ARGS dst, dst_stride, tmp, tmp_stride, pri, sec, dummy, table, \ + secdmp +%if UNIX64 + vpbroadcastb m0, xm0 ; pri_strength + vpbroadcastb m1, xm1 ; sec_strength +%else + vpbroadcastb m0, prim + vpbroadcastb m1, secm +%endif + and prid, 1 + lea priq, [tableq+priq*2+8] ; pri_taps + lea secq, [tableq+12] ; sec_taps +%if %1*%2*2/mmsize > 1 + %if %1 == 4 + DEFINE_ARGS dst, dst_stride, tmp0, tmp_stride, pri, sec, dst_stride3, h, off, k, tmp1, tmp2, tmp3 + lea dst_stride3q, [dst_strideq*3] + %else + DEFINE_ARGS dst, dst_stride, tmp0, tmp_stride, pri, sec, h, off, k, tmp1 + %endif + mov hd, %1*%2*2/mmsize +%else + DEFINE_ARGS dst, dst_stride, tmp0, tmp_stride, pri, sec, dst_stride3, off, k, tmp1, tmp2, tmp3 + lea dst_stride3q, [dst_strideq*3] +%endif + pxor m11, m11 +%if %1*%2*2/mmsize > 1 +.v_loop: +%endif + lea tmp1q, [tmp0q+tmp_strideq*2] +%if %1 == 4 + lea tmp2q, [tmp0q+tmp_strideq*4] + lea tmp3q, [tmp1q+tmp_strideq*4] +%endif + mov kd, 1 +%if %1 == 4 + movq xm4, [tmp0q] + movhps xm4, [tmp1q] + movq xm5, [tmp2q] + movhps xm5, [tmp3q] + vinserti128 m4, xm5, 1 +%else + mova xm4, [tmp0q] ; px + vinserti128 m4, [tmp1q], 1 +%endif + pxor m15, m15 ; sum + mova m7, m4 ; max + mova m8, m4 ; min +.k_loop: + vpbroadcastb m2, [priq+kq] ; pri_taps + vpbroadcastb m3, [secq+kq] ; sec_taps + + ACCUMULATE_TAP 0*8, [rsp+0], m13, m0, m2, %1, %3 + ACCUMULATE_TAP 1*8, [rsp+8], m14, m1, m3, %1, %3 + ACCUMULATE_TAP 2*8, [rsp+8], m14, m1, m3, %1, %3 + + dec kq + jge .k_loop + + vpbroadcastd m10, [pw_2048] + pcmpgtw m9, m11, m15 + paddw m15, m9 + pmulhrsw m15, m10 + paddw m4, m15 + pminsw m4, m7 + pmaxsw m4, m8 + packuswb m4, m4 + vextracti128 xm5, m4, 1 +%if %1 == 4 + movd [dstq+dst_strideq*0], xm4 + pextrd [dstq+dst_strideq*1], xm4, 1 + movd [dstq+dst_strideq*2], xm5 + pextrd [dstq+dst_stride3q], xm5, 1 +%else + movq [dstq+dst_strideq*0], xm4 + movq [dstq+dst_strideq*1], xm5 +%endif + +%if %1*%2*2/mmsize > 1 + %define vloop_lines (mmsize/(%1*2)) + lea dstq, [dstq+dst_strideq*vloop_lines] + lea tmp0q, [tmp0q+tmp_strideq*2*vloop_lines] + dec hd + jg .v_loop +%endif + + RET +%endmacro + +CDEF_FILTER 8, 8 +CDEF_FILTER 4, 8 +CDEF_FILTER 4, 4 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/cdef_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/cdef_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1357 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; Copyright © 2019, VideoLabs +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +%macro DUP8 1-* + %rep %0 + times 8 db %1 + %rotate 1 + %endrep +%endmacro + +div_table_sse4: dd 840, 420, 280, 210, 168, 140, 120, 105 + dd 420, 210, 140, 105, 105, 105, 105, 105 +div_table_ssse3: dw 840, 840, 420, 420, 280, 280, 210, 210 + dw 168, 168, 140, 140, 120, 120, 105, 105 + dw 420, 420, 210, 210, 140, 140, 105, 105 + dw 105, 105, 105, 105, 105, 105, 105, 105 +const shufw_6543210x, \ + db 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15 +shufb_lohi: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 +pw_8: times 8 dw 8 +pw_128: times 8 dw 128 +pw_256: times 8 dw 256 +pw_2048: times 8 dw 2048 +pw_0x7FFF: times 8 dw 0x7FFF +pw_0x8000: times 8 dw 0x8000 +tap_table: ; masks for 8-bit shift emulation + DUP8 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 + ; weights + DUP8 4, 2, 3, 3, 2, 1 + ; taps indices + db -1 * 16 + 1, -2 * 16 + 2 + db 0 * 16 + 1, -1 * 16 + 2 + db 0 * 16 + 1, 0 * 16 + 2 + db 0 * 16 + 1, 1 * 16 + 2 + db 1 * 16 + 1, 2 * 16 + 2 + db 1 * 16 + 0, 2 * 16 + 1 + db 1 * 16 + 0, 2 * 16 + 0 + db 1 * 16 + 0, 2 * 16 - 1 + ; the last 6 are repeats of the first 6 so we don't need to & 7 + db -1 * 16 + 1, -2 * 16 + 2 + db 0 * 16 + 1, -1 * 16 + 2 + db 0 * 16 + 1, 0 * 16 + 2 + db 0 * 16 + 1, 1 * 16 + 2 + db 1 * 16 + 1, 2 * 16 + 2 + db 1 * 16 + 0, 2 * 16 + 1 + +SECTION .text + +%macro movif32 2 + %if ARCH_X86_32 + mov %1, %2 + %endif +%endmacro + +%macro PMOVZXBW 2-3 0 ; %3 = half + %if cpuflag(sse4) && %3 == 0 + pmovzxbw %1, %2 + %else + %if %3 == 1 + movd %1, %2 + %else + movq %1, %2 + %endif + punpcklbw %1, m7 + %endif +%endmacro + +%macro PSHUFB_0 2 + %if cpuflag(ssse3) + pshufb %1, %2 + %else + punpcklbw %1, %1 + pshuflw %1, %1, q0000 + punpcklqdq %1, %1 + %endif +%endmacro + +%macro MOVDDUP 2 +%if cpuflag(ssse3) + movddup %1, %2 +%else + movq %1, %2 + punpcklqdq %1, %1 +%endif +%endmacro + +%macro ACCUMULATE_TAP 7 ; tap_offset, shift, shift_mask, strength, mul_tap, w, minmax + ; load p0/p1 + movsx offq, byte [dirq+kq+%1+14*8] ; off1 + %if %6 == 4 + movq m5, [stkq+offq*2+32*0] ; p0 + movhps m5, [stkq+offq*2+32*1] + %else + movu m5, [stkq+offq*2+32*0] ; p0 + %endif + neg offq ; -off1 + %if %6 == 4 + movq m6, [stkq+offq*2+32*0] ; p1 + movhps m6, [stkq+offq*2+32*1] + %else + movu m6, [stkq+offq*2+32*0] ; p1 + %endif + %if %7 + %if cpuflag(sse4) + ; out of bounds values are set to a value that is a both a large unsigned + ; value and a negative signed value. + ; use signed max and unsigned min to remove them + pmaxsw m7, m5 + pminuw m8, m5 + pmaxsw m7, m6 + pminuw m8, m6 + %else + pcmpeqw m3, m14, m5 + pminsw m8, m5 ; min after p0 + pandn m3, m5 + pmaxsw m7, m3 ; max after p0 + pcmpeqw m3, m14, m6 + pminsw m8, m6 ; min after p1 + pandn m3, m6 + pmaxsw m7, m3 ; max after p1 + %endif + %endif + + ; accumulate sum[m13] over p0/p1 + psubw m5, m4 ; diff_p0(p0 - px) + psubw m6, m4 ; diff_p1(p1 - px) + packsswb m5, m6 ; convert pixel diff to 8-bit + %if cpuflag(ssse3) + pshufb m5, m13 ; group diffs p0 and p1 into pairs + pabsb m6, m5 + psignb m3, %5, m5 + %else + movlhps m6, m5 + punpckhbw m6, m5 + pxor m5, m5 + pcmpgtb m5, m6 + paddb m6, m5 + pxor m6, m5 + paddb m3, %5, m5 + pxor m3, m5 + %endif + pand m9, %3, m6 ; emulate 8-bit shift + psrlw m9, %2 + psubusb m5, %4, m9 + pminub m5, m6 ; constrain(diff_p) + %if cpuflag(ssse3) + pmaddubsw m5, m3 ; constrain(diff_p) * taps + %else + psrlw m9, m5, 8 + psraw m6, m3, 8 + psllw m5, 8 + psllw m3, 8 + pmullw m9, m6 + pmulhw m5, m3 + paddw m5, m9 + %endif + paddw m0, m5 +%endmacro + +%macro LOAD_BODY 3 ; dst, src, block_width + %if %3 == 4 + PMOVZXBW m0, [%2+strideq*0] + PMOVZXBW m1, [%2+strideq*1] + PMOVZXBW m2, [%2+strideq*2] + PMOVZXBW m3, [%2+stride3q] + mova [%1+32*0], m0 + mova [%1+32*1], m1 + mova [%1+32*2], m2 + mova [%1+32*3], m3 + %else + movu m0, [%2+strideq*0] + movu m1, [%2+strideq*1] + movu m2, [%2+strideq*2] + movu m3, [%2+stride3q] + punpcklbw m4, m0, m7 + punpckhbw m0, m7 + mova [%1+32*0+ 0], m4 + mova [%1+32*0+16], m0 + punpcklbw m4, m1, m7 + punpckhbw m1, m7 + mova [%1+32*1+ 0], m4 + mova [%1+32*1+16], m1 + punpcklbw m4, m2, m7 + punpckhbw m2, m7 + mova [%1+32*2+ 0], m4 + mova [%1+32*2+16], m2 + punpcklbw m4, m3, m7 + punpckhbw m3, m7 + mova [%1+32*3+ 0], m4 + mova [%1+32*3+16], m3 + %endif +%endmacro + +%macro CDEF_FILTER_END 2 ; w, minmax + pxor m6, m6 + pcmpgtw m6, m0 + paddw m0, m6 + %if cpuflag(ssse3) + pmulhrsw m0, m15 + %else + paddw m0, m15 + psraw m0, 4 + %endif + paddw m4, m0 + %if %2 + pminsw m4, m7 + pmaxsw m4, m8 + %endif + packuswb m4, m4 + %if %1 == 4 + movd [dstq+strideq*0], m4 + psrlq m4, 32 + movd [dstq+strideq*1], m4 + add stkq, 32*2 + lea dstq, [dstq+strideq*2] + %else + movq [dstq], m4 + add stkq, 32 + add dstq, strideq + %endif +%endmacro + +%macro CDEF_FILTER 2 ; w, h + %if ARCH_X86_64 +cglobal cdef_filter_%1x%2_8bpc, 5, 9, 16, 3 * 16 + (%2+4)*32, \ + dst, stride, left, top, bot, pri, dst4, edge, \ + stride3 + %define px rsp+3*16+2*32 + %define base 0 + %else +cglobal cdef_filter_%1x%2_8bpc, 2, 7, 8, - 7 * 16 - (%2+4)*32, \ + dst, stride, left, edge, stride3 + %define topq r2 + %define botq r2 + %define dst4q r2 + LEA r5, tap_table + %define px esp+7*16+2*32 + %define base r5-tap_table + %endif + mov edged, r9m + %if cpuflag(sse4) + %define OUT_OF_BOUNDS_MEM [base+pw_0x8000] + %else + %define OUT_OF_BOUNDS_MEM [base+pw_0x7FFF] + %endif + mova m6, OUT_OF_BOUNDS_MEM + pxor m7, m7 + + ; prepare pixel buffers - body/right + %if %2 == 8 + lea dst4q, [dstq+strideq*4] + %endif + lea stride3q, [strideq*3] + test edgeb, 2 ; have_right + jz .no_right + LOAD_BODY px, dstq, %1 + %if %2 == 8 + LOAD_BODY px+4*32, dst4q, %1 + %endif + jmp .body_done +.no_right: + PMOVZXBW m0, [dstq+strideq*0], %1 == 4 + PMOVZXBW m1, [dstq+strideq*1], %1 == 4 + PMOVZXBW m2, [dstq+strideq*2], %1 == 4 + PMOVZXBW m3, [dstq+stride3q ], %1 == 4 + mova [px+32*0], m0 + mova [px+32*1], m1 + mova [px+32*2], m2 + mova [px+32*3], m3 + movd [px+32*0+%1*2], m6 + movd [px+32*1+%1*2], m6 + movd [px+32*2+%1*2], m6 + movd [px+32*3+%1*2], m6 + %if %2 == 8 + PMOVZXBW m0, [dst4q+strideq*0], %1 == 4 + PMOVZXBW m1, [dst4q+strideq*1], %1 == 4 + PMOVZXBW m2, [dst4q+strideq*2], %1 == 4 + PMOVZXBW m3, [dst4q+stride3q ], %1 == 4 + mova [px+32*4], m0 + mova [px+32*5], m1 + mova [px+32*6], m2 + mova [px+32*7], m3 + movd [px+32*4+%1*2], m6 + movd [px+32*5+%1*2], m6 + movd [px+32*6+%1*2], m6 + movd [px+32*7+%1*2], m6 + %endif +.body_done: + + ; top + movifnidn topq, r3mp + test edgeb, 4 ; have_top + jz .no_top + test edgeb, 1 ; have_left + jz .top_no_left + test edgeb, 2 ; have_right + jz .top_no_right + %if %1 == 4 + PMOVZXBW m0, [topq+strideq*0-2] + PMOVZXBW m1, [topq+strideq*1-2] + %else + movu m0, [topq+strideq*0-4] + movu m1, [topq+strideq*1-4] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + movu [px-32*2+8], m2 + movu [px-32*1+8], m3 + %endif + movu [px-32*2-%1], m0 + movu [px-32*1-%1], m1 + jmp .top_done +.top_no_right: + %if %1 == 4 + PMOVZXBW m0, [topq+strideq*0-%1] + PMOVZXBW m1, [topq+strideq*1-%1] + movu [px-32*2-8], m0 + movu [px-32*1-8], m1 + %else + movu m0, [topq+strideq*0-%1] + movu m1, [topq+strideq*1-%2] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + mova [px-32*2-16], m0 + mova [px-32*2+ 0], m2 + mova [px-32*1-16], m1 + mova [px-32*1+ 0], m3 + %endif + movd [px-32*2+%1*2], m6 + movd [px-32*1+%1*2], m6 + jmp .top_done +.top_no_left: + test edgeb, 2 ; have_right + jz .top_no_left_right + %if %1 == 4 + PMOVZXBW m0, [topq+strideq*0] + PMOVZXBW m1, [topq+strideq*1] + %else + movu m0, [topq+strideq*0] + movu m1, [topq+strideq*1] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + movd [px-32*2+16], m2 + movd [px-32*1+16], m3 + %endif + movd [px-32*2- 4], m6 + movd [px-32*1- 4], m6 + mova [px-32*2+ 0], m0 + mova [px-32*1+ 0], m1 + jmp .top_done +.top_no_left_right: + PMOVZXBW m0, [topq+strideq*0], %1 == 4 + PMOVZXBW m1, [topq+strideq*1], %1 == 4 + movd [px-32*2-4], m6 + movd [px-32*1-4], m6 + mova [px-32*2+0], m0 + mova [px-32*1+0], m1 + movd [px-32*2+%1*2], m6 + movd [px-32*1+%1*2], m6 + jmp .top_done +.no_top: + movu [px-32*2- 4], m6 + movu [px-32*1- 4], m6 + %if %1 == 8 + movq [px-32*2+12], m6 + movq [px-32*1+12], m6 + %endif +.top_done: + + ; left + test edgeb, 1 ; have_left + jz .no_left + movifnidn leftq, leftmp + %if %2 == 4 + movq m0, [leftq] + %else + movu m0, [leftq] + %endif + %if %2 == 4 + punpcklbw m0, m7 + %else + punpckhbw m1, m0, m7 + punpcklbw m0, m7 + movhlps m3, m1 + movd [px+32*4-4], m1 + movd [px+32*6-4], m3 + psrlq m1, 32 + psrlq m3, 32 + movd [px+32*5-4], m1 + movd [px+32*7-4], m3 + %endif + movhlps m2, m0 + movd [px+32*0-4], m0 + movd [px+32*2-4], m2 + psrlq m0, 32 + psrlq m2, 32 + movd [px+32*1-4], m0 + movd [px+32*3-4], m2 + jmp .left_done +.no_left: + movd [px+32*0-4], m6 + movd [px+32*1-4], m6 + movd [px+32*2-4], m6 + movd [px+32*3-4], m6 + %if %2 == 8 + movd [px+32*4-4], m6 + movd [px+32*5-4], m6 + movd [px+32*6-4], m6 + movd [px+32*7-4], m6 + %endif +.left_done: + + ; bottom + movifnidn botq, r4mp + test edgeb, 8 ; have_bottom + jz .no_bottom + test edgeb, 1 ; have_left + jz .bottom_no_left + test edgeb, 2 ; have_right + jz .bottom_no_right + %if %1 == 4 + PMOVZXBW m0, [botq+strideq*0-(%1/2)] + PMOVZXBW m1, [botq+strideq*1-(%1/2)] + %else + movu m0, [botq+strideq*0-4] + movu m1, [botq+strideq*1-4] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + movu [px+32*(%2+0)+8], m2 + movu [px+32*(%2+1)+8], m3 + %endif + movu [px+32*(%2+0)-%1], m0 + movu [px+32*(%2+1)-%1], m1 + jmp .bottom_done +.bottom_no_right: + %if %1 == 4 + PMOVZXBW m0, [botq+strideq*0-4] + PMOVZXBW m1, [botq+strideq*1-4] + movu [px+32*(%2+0)-8], m0 + movu [px+32*(%2+1)-8], m1 + %else + movu m0, [botq+strideq*0-8] + movu m1, [botq+strideq*1-8] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + mova [px+32*(%2+0)-16], m0 + mova [px+32*(%2+0)+ 0], m2 + mova [px+32*(%2+1)-16], m1 + mova [px+32*(%2+1)+ 0], m3 + movd [px+32*(%2-1)+16], m6 ; overwritten by first mova + %endif + movd [px+32*(%2+0)+%1*2], m6 + movd [px+32*(%2+1)+%1*2], m6 + jmp .bottom_done +.bottom_no_left: + test edgeb, 2 ; have_right + jz .bottom_no_left_right + %if %1 == 4 + PMOVZXBW m0, [botq+strideq*0] + PMOVZXBW m1, [botq+strideq*1] + %else + movu m0, [botq+strideq*0] + movu m1, [botq+strideq*1] + punpckhbw m2, m0, m7 + punpcklbw m0, m7 + punpckhbw m3, m1, m7 + punpcklbw m1, m7 + mova [px+32*(%2+0)+16], m2 + mova [px+32*(%2+1)+16], m3 + %endif + mova [px+32*(%2+0)+ 0], m0 + mova [px+32*(%2+1)+ 0], m1 + movd [px+32*(%2+0)- 4], m6 + movd [px+32*(%2+1)- 4], m6 + jmp .bottom_done +.bottom_no_left_right: + PMOVZXBW m0, [botq+strideq*0], %1 == 4 + PMOVZXBW m1, [botq+strideq*1], %1 == 4 + mova [px+32*(%2+0)+ 0], m0 + mova [px+32*(%2+1)+ 0], m1 + movd [px+32*(%2+0)+%1*2], m6 + movd [px+32*(%2+1)+%1*2], m6 + movd [px+32*(%2+0)- 4], m6 + movd [px+32*(%2+1)- 4], m6 + jmp .bottom_done +.no_bottom: + movu [px+32*(%2+0)- 4], m6 + movu [px+32*(%2+1)- 4], m6 + %if %1 == 8 + movq [px+32*(%2+0)+12], m6 + movq [px+32*(%2+1)+12], m6 + %endif +.bottom_done: + + ; actual filter + %if ARCH_X86_64 + DEFINE_ARGS dst, stride, _, pridmp, damping, pri, sec + mova m13, [shufb_lohi] + %if cpuflag(ssse3) + mova m15, [pw_2048] + %else + mova m15, [pw_8] + %endif + mova m14, m6 + %else + DEFINE_ARGS dst, pridmp, sec, damping, pri, tap + %xdefine m8 m1 + %xdefine m9 m2 + %xdefine m10 m0 + %xdefine m13 [base+shufb_lohi] + %xdefine m14 OUT_OF_BOUNDS_MEM + %if cpuflag(ssse3) + %xdefine m15 [base+pw_2048] + %else + %xdefine m15 [base+pw_8] + %endif + %endif + movifnidn prid, r5m + movifnidn secd, r6m + mov dampingd, r8m + movif32 [esp+0x3C], r1d + test prid, prid + jz .sec_only + movd m1, r5m + bsr pridmpd, prid + test secd, secd + jz .pri_only + movd m10, r6m + tzcnt secd, secd + and prid, 1 + sub pridmpd, dampingd + sub secd, dampingd + xor dampingd, dampingd + add prid, prid + neg pridmpd + cmovs pridmpd, dampingd + neg secd + PSHUFB_0 m1, m7 + PSHUFB_0 m10, m7 + %if ARCH_X86_64 + DEFINE_ARGS dst, stride, _, pridmp, tap, pri, sec + lea tapq, [tap_table] + MOVDDUP m11, [tapq+pridmpq*8] ; pri_shift_mask + MOVDDUP m12, [tapq+secq*8] ; sec_shift_mask + mov [rsp+0x00], pridmpq ; pri_shift + mov [rsp+0x10], secq ; sec_shift + DEFINE_ARGS dst, stride, h, dir, tap, pri, stk, k, off + %else + MOVDDUP m2, [tapq+pridmpq*8] + MOVDDUP m3, [tapq+secq*8] + mov [esp+0x04], dampingd ; zero upper 32 bits of psrlw + mov [esp+0x34], dampingd ; source operand in ACCUMULATE_TAP + mov [esp+0x00], pridmpd + mov [esp+0x30], secd + DEFINE_ARGS dst, stride, dir, stk, pri, tap, h + %define offq dstq + %define kd strided + %define kq strideq + mova [esp+0x10], m2 + mova [esp+0x40], m3 + mova [esp+0x20], m1 + mova [esp+0x50], m10 + %endif + mov dird, r7m + lea stkq, [px] + lea priq, [tapq+8*8+priq*8] ; pri_taps + mov hd, %1*%2/8 + lea dirq, [tapq+dirq*2] +.v_loop: + movif32 [esp+0x38], dstd + mov kd, 1 + %if %1 == 4 + movq m4, [stkq+32*0] + movhps m4, [stkq+32*1] + %else + mova m4, [stkq+32*0] ; px + %endif + pxor m0, m0 ; sum + mova m7, m4 ; max + mova m8, m4 ; min +.k_loop: + MOVDDUP m2, [priq+kq*8] + %if ARCH_X86_64 + ACCUMULATE_TAP 0*2, [rsp+0x00], m11, m1, m2, %1, 1 + MOVDDUP m2, [tapq+12*8+kq*8] + ACCUMULATE_TAP 2*2, [rsp+0x10], m12, m10, m2, %1, 1 + ACCUMULATE_TAP 6*2, [rsp+0x10], m12, m10, m2, %1, 1 + %else + ACCUMULATE_TAP 0*2, [esp+0x00], [esp+0x10], [esp+0x20], m2, %1, 1 + MOVDDUP m2, [tapq+12*8+kq*8] + ACCUMULATE_TAP 2*2, [esp+0x30], [esp+0x40], [esp+0x50], m2, %1, 1 + MOVDDUP m2, [tapq+12*8+kq*8] + ACCUMULATE_TAP 6*2, [esp+0x30], [esp+0x40], [esp+0x50], m2, %1, 1 + %endif + dec kd + jge .k_loop + movif32 dstq, [esp+0x38] + movif32 strideq, [esp+0x3C] + CDEF_FILTER_END %1, 1 + dec hd + jg .v_loop + RET + +.pri_only: +%if ARCH_X86_64 + DEFINE_ARGS dst, stride, zero, pridmp, damping, pri, tap + lea tapq, [tap_table] + %else + DEFINE_ARGS dst, pridmp, zero, damping, pri, tap + %endif + and prid, 1 + xor zerod, zerod + sub dampingd, pridmpd + cmovs dampingd, zerod + add prid, prid + PSHUFB_0 m1, m7 + MOVDDUP m7, [tapq+dampingq*8] + mov [rsp+0x00], dampingq + %if ARCH_X86_64 + DEFINE_ARGS dst, stride, h, dir, stk, pri, tap, k, off + %else + mov [rsp+0x04], zerod + DEFINE_ARGS dst, stride, dir, stk, pri, tap, h + %endif + mov dird, r7m + lea stkq, [px] + lea priq, [tapq+8*8+priq*8] + mov hd, %1*%2/8 + lea dirq, [tapq+dirq*2] +.pri_v_loop: + movif32 [esp+0x38], dstd + mov kd, 1 + %if %1 == 4 + movq m4, [stkq+32*0] + movhps m4, [stkq+32*1] + %else + mova m4, [stkq+32*0] + %endif + pxor m0, m0 +.pri_k_loop: + MOVDDUP m2, [priq+kq*8] + ACCUMULATE_TAP 0*2, [rsp], m7, m1, m2, %1, 0 + dec kd + jge .pri_k_loop + movif32 dstq, [esp+0x38] + movif32 strideq, [esp+0x3C] + CDEF_FILTER_END %1, 0 + dec hd + jg .pri_v_loop + RET + +.sec_only: +%if ARCH_X86_64 + DEFINE_ARGS dst, stride, zero, dir, damping, tap, sec +%else + DEFINE_ARGS dst, stride, sec, damping, dir, tap, zero +%endif + movd m1, r6m + tzcnt secd, secd + mov dird, r7m + xor zerod, zerod + sub dampingd, secd + cmovs dampingd, zerod + PSHUFB_0 m1, m7 + %if ARCH_X86_64 + lea tapq, [tap_table] + %else + mov [rsp+0x04], zerod + %endif + mov [rsp+0x00], dampingq + MOVDDUP m7, [tapq+dampingq*8] + lea dirq, [tapq+dirq*2] + %if ARCH_X86_64 + DEFINE_ARGS dst, stride, h, dir, stk, tap, off, k + %else + DEFINE_ARGS dst, stride, off, stk, dir, tap, h + %endif + lea stkq, [px] + mov hd, %1*%2/8 +.sec_v_loop: + mov kd, 1 + %if %1 == 4 + movq m4, [stkq+32*0] + movhps m4, [stkq+32*1] + %else + mova m4, [stkq+32*0] + %endif + pxor m0, m0 +.sec_k_loop: + MOVDDUP m2, [tapq+12*8+kq*8] + ACCUMULATE_TAP 2*2, [rsp], m7, m1, m2, %1, 0 + %if ARCH_X86_32 + MOVDDUP m2, [tapq+12*8+kq*8] + %endif + ACCUMULATE_TAP 6*2, [rsp], m7, m1, m2, %1, 0 + dec kd + jge .sec_k_loop + movif32 strideq, [esp+0x3C] + CDEF_FILTER_END %1, 0 + dec hd + jg .sec_v_loop + RET +%endmacro + +%macro MULLD 2 + %if cpuflag(sse4) + pmulld %1, %2 + %else + %if ARCH_X86_32 + %define m15 m1 + %endif + pmulhuw m15, %1, %2 + pmullw %1, %2 + pslld m15, 16 + paddd %1, m15 + %endif +%endmacro + +%macro CDEF_DIR 0 + %if ARCH_X86_64 +cglobal cdef_dir_8bpc, 3, 7, 16, src, stride, var + lea r6, [strideq*3] + movq m1, [srcq+strideq*0] + movhps m1, [srcq+strideq*1] + movq m3, [srcq+strideq*2] + movhps m3, [srcq+r6 ] + lea srcq, [srcq+strideq*4] + movq m5, [srcq+strideq*0] + movhps m5, [srcq+strideq*1] + movq m7, [srcq+strideq*2] + movhps m7, [srcq+r6 ] + + pxor m8, m8 + psadbw m9, m1, m8 + psadbw m2, m3, m8 + psadbw m4, m5, m8 + psadbw m6, m7, m8 + packssdw m9, m2 + packssdw m4, m6 + packssdw m9, m4 + + punpcklbw m0, m1, m8 + punpckhbw m1, m8 + punpcklbw m2, m3, m8 + punpckhbw m3, m8 + punpcklbw m4, m5, m8 + punpckhbw m5, m8 + punpcklbw m6, m7, m8 + punpckhbw m7, m8 +cglobal_label .main + mova m8, [pw_128] + psubw m0, m8 + psubw m1, m8 + psubw m2, m8 + psubw m3, m8 + psubw m4, m8 + psubw m5, m8 + psubw m6, m8 + psubw m7, m8 + psllw m8, 3 + psubw m9, m8 ; partial_sum_hv[0] + + paddw m8, m0, m1 + paddw m10, m2, m3 + paddw m8, m4 + paddw m10, m5 + paddw m8, m6 + paddw m10, m7 + paddw m8, m10 ; partial_sum_hv[1] + + pmaddwd m8, m8 + pmaddwd m9, m9 + phaddd m9, m8 + SWAP m8, m9 + MULLD m8, [div_table%+SUFFIX+48] + + pslldq m9, m1, 2 + psrldq m10, m1, 14 + pslldq m11, m2, 4 + psrldq m12, m2, 12 + pslldq m13, m3, 6 + psrldq m14, m3, 10 + paddw m9, m0 + paddw m10, m12 + paddw m11, m13 + paddw m10, m14 ; partial_sum_diag[0] top/right half + paddw m9, m11 ; partial_sum_diag[0] top/left half + pslldq m11, m4, 8 + psrldq m12, m4, 8 + pslldq m13, m5, 10 + psrldq m14, m5, 6 + paddw m9, m11 + paddw m10, m12 + paddw m9, m13 + paddw m10, m14 + pslldq m11, m6, 12 + psrldq m12, m6, 4 + pslldq m13, m7, 14 + psrldq m14, m7, 2 + paddw m9, m11 + paddw m10, m12 + paddw m9, m13 ; partial_sum_diag[0][0-7] + paddw m10, m14 ; partial_sum_diag[0][8-14,zero] + pshufb m10, [shufw_6543210x] + punpckhwd m11, m9, m10 + punpcklwd m9, m10 + pmaddwd m11, m11 + pmaddwd m9, m9 + MULLD m11, [div_table%+SUFFIX+16] + MULLD m9, [div_table%+SUFFIX+0] + paddd m9, m11 ; cost[0a-d] + + pslldq m10, m0, 14 + psrldq m11, m0, 2 + pslldq m12, m1, 12 + psrldq m13, m1, 4 + pslldq m14, m2, 10 + psrldq m15, m2, 6 + paddw m10, m12 + paddw m11, m13 + paddw m10, m14 + paddw m11, m15 + pslldq m12, m3, 8 + psrldq m13, m3, 8 + pslldq m14, m4, 6 + psrldq m15, m4, 10 + paddw m10, m12 + paddw m11, m13 + paddw m10, m14 + paddw m11, m15 + pslldq m12, m5, 4 + psrldq m13, m5, 12 + pslldq m14, m6, 2 + psrldq m15, m6, 14 + paddw m10, m12 + paddw m11, m13 + paddw m10, m14 + paddw m11, m15 ; partial_sum_diag[1][8-14,zero] + paddw m10, m7 ; partial_sum_diag[1][0-7] + pshufb m11, [shufw_6543210x] + punpckhwd m12, m10, m11 + punpcklwd m10, m11 + pmaddwd m12, m12 + pmaddwd m10, m10 + MULLD m12, [div_table%+SUFFIX+16] + MULLD m10, [div_table%+SUFFIX+0] + paddd m10, m12 ; cost[4a-d] + phaddd m9, m10 ; cost[0a/b,4a/b] + + paddw m10, m0, m1 + paddw m11, m2, m3 + paddw m12, m4, m5 + paddw m13, m6, m7 + phaddw m0, m4 + phaddw m1, m5 + phaddw m2, m6 + phaddw m3, m7 + + ; m0-3 are horizontal sums (x >> 1), m10-13 are vertical sums (y >> 1) + pslldq m4, m11, 2 + psrldq m5, m11, 14 + pslldq m6, m12, 4 + psrldq m7, m12, 12 + pslldq m14, m13, 6 + psrldq m15, m13, 10 + paddw m4, m10 + paddw m5, m7 + paddw m4, m6 + paddw m5, m15 ; partial_sum_alt[3] right + paddw m4, m14 ; partial_sum_alt[3] left + pshuflw m6, m5, q3012 + punpckhwd m5, m4 + punpcklwd m4, m6 + pmaddwd m5, m5 + pmaddwd m4, m4 + MULLD m5, [div_table%+SUFFIX+48] + MULLD m4, [div_table%+SUFFIX+32] + paddd m4, m5 ; cost[7a-d] + + pslldq m5, m10, 6 + psrldq m6, m10, 10 + pslldq m7, m11, 4 + psrldq m10, m11, 12 + pslldq m11, m12, 2 + psrldq m12, 14 + paddw m5, m7 + paddw m6, m10 + paddw m5, m11 + paddw m6, m12 + paddw m5, m13 + pshuflw m7, m6, q3012 + punpckhwd m6, m5 + punpcklwd m5, m7 + pmaddwd m6, m6 + pmaddwd m5, m5 + MULLD m6, [div_table%+SUFFIX+48] + MULLD m5, [div_table%+SUFFIX+32] + paddd m5, m6 ; cost[5a-d] + + pslldq m6, m1, 2 + psrldq m7, m1, 14 + pslldq m10, m2, 4 + psrldq m11, m2, 12 + pslldq m12, m3, 6 + psrldq m13, m3, 10 + paddw m6, m0 + paddw m7, m11 + paddw m6, m10 + paddw m7, m13 ; partial_sum_alt[3] right + paddw m6, m12 ; partial_sum_alt[3] left + pshuflw m10, m7, q3012 + punpckhwd m7, m6 + punpcklwd m6, m10 + pmaddwd m7, m7 + pmaddwd m6, m6 + MULLD m7, [div_table%+SUFFIX+48] + MULLD m6, [div_table%+SUFFIX+32] + paddd m6, m7 ; cost[1a-d] + + pshufd m0, m0, q1032 + pshufd m1, m1, q1032 + pshufd m2, m2, q1032 + pshufd m3, m3, q1032 + + pslldq m10, m0, 6 + psrldq m11, m0, 10 + pslldq m12, m1, 4 + psrldq m13, m1, 12 + pslldq m14, m2, 2 + psrldq m2, 14 + paddw m10, m12 + paddw m11, m13 + paddw m10, m14 + paddw m11, m2 + paddw m10, m3 + pshuflw m12, m11, q3012 + punpckhwd m11, m10 + punpcklwd m10, m12 + pmaddwd m11, m11 + pmaddwd m10, m10 + MULLD m11, [div_table%+SUFFIX+48] + MULLD m10, [div_table%+SUFFIX+32] + paddd m10, m11 ; cost[3a-d] + + phaddd m9, m8 ; cost[0,4,2,6] + phaddd m6, m10 + phaddd m5, m4 + phaddd m6, m5 ; cost[1,3,5,7] + pshufd m4, m9, q3120 + + ; now find the best cost + %if cpuflag(sse4) + pmaxsd m9, m6 + pshufd m0, m9, q1032 + pmaxsd m0, m9 + pshufd m1, m0, q2301 + pmaxsd m0, m1 ; best cost + %else + pcmpgtd m0, m9, m6 + pand m9, m0 + pandn m0, m6 + por m9, m0 + pshufd m1, m9, q1032 + pcmpgtd m0, m9, m1 + pand m9, m0 + pandn m0, m1 + por m9, m0 + pshufd m1, m9, q2301 + pcmpgtd m0, m9, m1 + pand m9, m0 + pandn m0, m1 + por m0, m9 + %endif + + ; get direction and variance + punpckhdq m1, m4, m6 + punpckldq m4, m6 + psubd m2, m0, m1 + psubd m3, m0, m4 +%if WIN64 + WIN64_RESTORE_XMM + %define tmp rsp+stack_offset+8 +%else + %define tmp rsp-40 +%endif + mova [tmp+0x00], m2 ; emulate ymm in stack + mova [tmp+0x10], m3 + pcmpeqd m1, m0 ; compute best cost mask + pcmpeqd m4, m0 + packssdw m4, m1 + pmovmskb eax, m4 ; get byte-idx from mask + tzcnt eax, eax + mov r1d, [tmp+rax*2] ; get idx^4 complement from emulated ymm + shr eax, 1 ; get direction by converting byte-idx to word-idx + shr r1d, 10 + mov [varq], r1d + %else +cglobal cdef_dir_8bpc, 2, 4, 8, 96, src, stride, var, stride3 +%define base r2-shufw_6543210x + LEA r2, shufw_6543210x + pxor m0, m0 + lea stride3q, [strideq*3] + movq m5, [srcq+strideq*0] + movhps m5, [srcq+strideq*1] + movq m7, [srcq+strideq*2] + movhps m7, [srcq+stride3q] + mova m1, [base+pw_128] + psadbw m2, m5, m0 + psadbw m3, m7, m0 + packssdw m2, m3 + punpcklbw m4, m5, m0 + punpckhbw m5, m0 + punpcklbw m6, m7, m0 + punpckhbw m7, m0 + psubw m4, m1 + psubw m5, m1 + psubw m6, m1 + psubw m7, m1 + + mova [esp+0x00], m4 + mova [esp+0x10], m5 + mova [esp+0x20], m6 + mova [esp+0x50], m7 + + lea srcq, [srcq+strideq*4] + movq m5, [srcq+strideq*0] + movhps m5, [srcq+strideq*1] + movq m7, [srcq+strideq*2] + movhps m7, [srcq+stride3q] + psadbw m3, m5, m0 + psadbw m0, m7 + packssdw m3, m0 + pxor m0, m0 + punpcklbw m4, m5, m0 + punpckhbw m5, m0 + punpcklbw m6, m7, m0 + punpckhbw m7, m0 +cglobal_label .main + psubw m4, m1 + psubw m5, m1 + psubw m6, m1 + psubw m7, m1 + packssdw m2, m3 + psllw m1, 3 + psubw m2, m1 ; partial_sum_hv[0] + pmaddwd m2, m2 + + mova m3, [esp+0x50] + mova m0, [esp+0x00] + paddw m0, [esp+0x10] + paddw m1, m3, [esp+0x20] + paddw m0, m4 + paddw m1, m5 + paddw m0, m6 + paddw m1, m7 + paddw m0, m1 ; partial_sum_hv[1] + pmaddwd m0, m0 + + phaddd m2, m0 + MULLD m2, [base+div_table%+SUFFIX+48] + mova [esp+0x30], m2 + + mova m1, [esp+0x10] + pslldq m0, m1, 2 + psrldq m1, 14 + paddw m0, [esp+0x00] + pslldq m2, m3, 6 + psrldq m3, 10 + paddw m0, m2 + paddw m1, m3 + mova m3, [esp+0x20] + pslldq m2, m3, 4 + psrldq m3, 12 + paddw m0, m2 ; partial_sum_diag[0] top/left half + paddw m1, m3 ; partial_sum_diag[0] top/right half + pslldq m2, m4, 8 + psrldq m3, m4, 8 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m5, 10 + psrldq m3, m5, 6 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m6, 12 + psrldq m3, m6, 4 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m7, 14 + psrldq m3, m7, 2 + paddw m0, m2 ; partial_sum_diag[0][0-7] + paddw m1, m3 ; partial_sum_diag[0][8-14,zero] + mova m3, [esp+0x50] + pshufb m1, [base+shufw_6543210x] + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmaddwd m2, m2 + pmaddwd m0, m0 + MULLD m2, [base+div_table%+SUFFIX+16] + MULLD m0, [base+div_table%+SUFFIX+ 0] + paddd m0, m2 ; cost[0a-d] + mova [esp+0x40], m0 + + mova m1, [esp+0x00] + pslldq m0, m1, 14 + psrldq m1, 2 + paddw m0, m7 + pslldq m2, m3, 8 + psrldq m3, 8 + paddw m0, m2 + paddw m1, m3 + mova m3, [esp+0x20] + pslldq m2, m3, 10 + psrldq m3, 6 + paddw m0, m2 + paddw m1, m3 + mova m3, [esp+0x10] + pslldq m2, m3, 12 + psrldq m3, 4 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m4, 6 + psrldq m3, m4, 10 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m5, 4 + psrldq m3, m5, 12 + paddw m0, m2 + paddw m1, m3 + pslldq m2, m6, 2 + psrldq m3, m6, 14 + paddw m0, m2 ; partial_sum_diag[1][0-7] + paddw m1, m3 ; partial_sum_diag[1][8-14,zero] + mova m3, [esp+0x50] + pshufb m1, [base+shufw_6543210x] + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmaddwd m2, m2 + pmaddwd m0, m0 + MULLD m2, [base+div_table%+SUFFIX+16] + MULLD m0, [base+div_table%+SUFFIX+ 0] + paddd m0, m2 ; cost[4a-d] + phaddd m1, [esp+0x40], m0 ; cost[0a/b,4a/b] + phaddd m1, [esp+0x30] ; cost[0,4,2,6] + mova [esp+0x30], m1 + + phaddw m0, [esp+0x00], m4 + phaddw m1, [esp+0x10], m5 + paddw m4, m5 + mova m2, [esp+0x20] + paddw m5, m2, m3 + phaddw m2, m6 + paddw m6, m7 + phaddw m3, m7 + mova m7, [esp+0x00] + paddw m7, [esp+0x10] + mova [esp+0x00], m0 + mova [esp+0x10], m1 + mova [esp+0x20], m2 + + pslldq m1, m4, 4 + pslldq m2, m6, 6 + pslldq m0, m5, 2 + paddw m1, m2 + paddw m0, m7 + psrldq m2, m5, 14 + paddw m0, m1 ; partial_sum_alt[3] left + psrldq m1, m4, 12 + paddw m1, m2 + psrldq m2, m6, 10 + paddw m1, m2 ; partial_sum_alt[3] right + pshuflw m1, m1, q3012 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmaddwd m2, m2 + pmaddwd m0, m0 + MULLD m2, [base+div_table%+SUFFIX+48] + MULLD m0, [base+div_table%+SUFFIX+32] + paddd m0, m2 ; cost[7a-d] + mova [esp+0x40], m0 + + pslldq m0, m7, 6 + psrldq m7, 10 + pslldq m1, m5, 4 + psrldq m5, 12 + pslldq m2, m4, 2 + psrldq m4, 14 + paddw m0, m6 + paddw m7, m5 + paddw m0, m1 + paddw m7, m4 + paddw m0, m2 + pshuflw m2, m7, q3012 + punpckhwd m7, m0 + punpcklwd m0, m2 + pmaddwd m7, m7 + pmaddwd m0, m0 + MULLD m7, [base+div_table%+SUFFIX+48] + MULLD m0, [base+div_table%+SUFFIX+32] + paddd m0, m7 ; cost[5a-d] + mova [esp+0x50], m0 + + mova m7, [esp+0x10] + mova m2, [esp+0x20] + pslldq m0, m7, 2 + psrldq m7, 14 + pslldq m4, m2, 4 + psrldq m2, 12 + pslldq m5, m3, 6 + psrldq m6, m3, 10 + paddw m0, [esp+0x00] + paddw m7, m2 + paddw m4, m5 + paddw m7, m6 ; partial_sum_alt[3] right + paddw m0, m4 ; partial_sum_alt[3] left + pshuflw m2, m7, q3012 + punpckhwd m7, m0 + punpcklwd m0, m2 + pmaddwd m7, m7 + pmaddwd m0, m0 + MULLD m7, [base+div_table%+SUFFIX+48] + MULLD m0, [base+div_table%+SUFFIX+32] + paddd m0, m7 ; cost[1a-d] + SWAP m0, m4 + + pshufd m0, [esp+0x00], q1032 + pshufd m1, [esp+0x10], q1032 + pshufd m2, [esp+0x20], q1032 + pshufd m3, m3, q1032 + mova [esp+0x00], m4 + + pslldq m4, m0, 6 + psrldq m0, 10 + pslldq m5, m1, 4 + psrldq m1, 12 + pslldq m6, m2, 2 + psrldq m2, 14 + paddw m4, m3 + paddw m0, m1 + paddw m5, m6 + paddw m0, m2 + paddw m4, m5 + pshuflw m2, m0, q3012 + punpckhwd m0, m4 + punpcklwd m4, m2 + pmaddwd m0, m0 + pmaddwd m4, m4 + MULLD m0, [base+div_table%+SUFFIX+48] + MULLD m4, [base+div_table%+SUFFIX+32] + paddd m4, m0 ; cost[3a-d] + + mova m1, [esp+0x00] + mova m2, [esp+0x50] + mova m0, [esp+0x30] ; cost[0,4,2,6] + phaddd m1, m4 + phaddd m2, [esp+0x40] ; cost[1,3,5,7] + phaddd m1, m2 + pshufd m2, m0, q3120 + + ; now find the best cost + %if cpuflag(sse4) + pmaxsd m0, m1 + pshufd m3, m0, q1032 + pmaxsd m3, m0 + pshufd m0, m3, q2301 + pmaxsd m0, m3 + %else + pcmpgtd m3, m0, m1 + pand m0, m3 + pandn m3, m1 + por m0, m3 + pshufd m4, m0, q1032 + pcmpgtd m3, m0, m4 + pand m0, m3 + pandn m3, m4 + por m0, m3 + pshufd m4, m0, q2301 + pcmpgtd m3, m0, m4 + pand m0, m3 + pandn m3, m4 + por m0, m3 + %endif + + ; get direction and variance + mov vard, varm + punpckhdq m3, m2, m1 + punpckldq m2, m1 + psubd m1, m0, m3 + psubd m4, m0, m2 + mova [esp+0x00], m1 ; emulate ymm in stack + mova [esp+0x10], m4 + pcmpeqd m3, m0 ; compute best cost mask + pcmpeqd m2, m0 + packssdw m2, m3 + pmovmskb eax, m2 ; get byte-idx from mask + tzcnt eax, eax + mov r1d, [esp+eax*2] ; get idx^4 complement from emulated ymm + shr eax, 1 ; get direction by converting byte-idx to word-idx + shr r1d, 10 + mov [vard], r1d + %endif + + RET +%endmacro + +INIT_XMM sse4 +CDEF_FILTER 8, 8 +CDEF_FILTER 4, 8 +CDEF_FILTER 4, 4 +CDEF_DIR + +INIT_XMM ssse3 +CDEF_FILTER 8, 8 +CDEF_FILTER 4, 8 +CDEF_FILTER 4, 4 +CDEF_DIR + +INIT_XMM sse2 +CDEF_FILTER 8, 8 +CDEF_FILTER 4, 8 +CDEF_FILTER 4, 4 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2248 @@ +; Copyright © 2021-2022, VideoLAN and dav1d authors +; Copyright © 2021-2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 16 +pb_mask: db 0,128,128, 0,128, 0, 0,128,128, 0, 0,128, 0,128,128, 0 +gen_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +gen_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +next_upperbit_mask: dw 0x100B, 0x2016, 0x402C, 0x8058 +pw_27_17_17_27: dw 27, 17, 17, 27 +pw_23_22: dw 23, 22, 0, 32 +pw_seed_xor: times 2 dw 0xb524 + times 2 dw 0x49d8 +gen_ar0_shift: times 4 db 128 + times 4 db 64 + times 4 db 32 + times 4 db 16 +pd_16: dd 16 +pd_m65536: dd -65536 +pb_1: times 4 db 1 +grain_max: times 2 dw 511 + times 2 dw 2047 +grain_min: times 2 dw -512 + times 2 dw -2048 +fg_max: times 2 dw 1023 + times 2 dw 4095 + times 2 dw 960 + times 2 dw 3840 + times 2 dw 940 + times 2 dw 3760 +fg_min: times 2 dw 0 + times 2 dw 64 + times 2 dw 256 +uv_offset_mul: dd 256 + dd 1024 +hmul_bits: dw 32768, 16384, 8192, 4096 +round: dw 2048, 1024, 512 +mul_bits: dw 256, 128, 64, 32, 16, 8 +round_vals: dw 32, 64, 128, 256, 512, 1024 +pb_8_9_0_1: db 8, 9, 0, 1 + +%macro JMP_TABLE 1-* + %xdefine %1_table %%table + %xdefine %%base %1_table + %xdefine %%prefix mangle(private_prefix %+ _%1) + %%table: + %rep %0 - 1 + dd %%prefix %+ .ar%2 - %%base + %rotate 1 + %endrep +%endmacro + +JMP_TABLE generate_grain_y_16bpc_avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_420_16bpc_avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_422_16bpc_avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_444_16bpc_avx2, 0, 1, 2, 3 + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +INIT_YMM avx2 +cglobal generate_grain_y_16bpc, 3, 9, 14, buf, fg_data, bdmax +%define base r4-generate_grain_y_16bpc_avx2_table + lea r4, [generate_grain_y_16bpc_avx2_table] + vpbroadcastw xm0, [fg_dataq+FGData.seed] + mov r6d, [fg_dataq+FGData.grain_scale_shift] + movq xm1, [base+next_upperbit_mask] + mov r3, -73*82*2 + movsxd r5, [fg_dataq+FGData.ar_coeff_lag] + lea r7d, [bdmaxq+1] + movq xm4, [base+mul_bits] + shr r7d, 11 ; 0 for 10bpc, 2 for 12bpc + movq xm5, [base+hmul_bits] + sub r6, r7 + mova xm6, [base+pb_mask] + sub bufq, r3 + vpbroadcastw xm7, [base+round+r6*2-2] + lea r6, [gaussian_sequence] + movsxd r5, [r4+r5*4] +.loop: + pand xm2, xm0, xm1 + psrlw xm3, xm2, 10 + por xm2, xm3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw xm2, xm4 ; bits 0x0f00 are set + pmulhuw xm0, xm5 + pshufb xm3, xm6, xm2 ; set 15th bit for next 4 seeds + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm2, xm0 ; aggregate each bit into next seed's high bit + por xm3, xm2 ; 4 next output seeds + pshuflw xm0, xm3, q3333 + psrlw xm3, 5 + pand xm2, xm0, xm1 + movq r7, xm3 + psrlw xm3, xm2, 10 + por xm2, xm3 + pmullw xm2, xm4 + pmulhuw xm0, xm5 + movzx r8d, r7w + pshufb xm3, xm6, xm2 + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm0, xm2 + movd xm2, [r6+r8*2] + rorx r8, r7, 32 + por xm3, xm0 + shr r7d, 16 + pinsrw xm2, [r6+r7*2], 1 + pshuflw xm0, xm3, q3333 + movzx r7d, r8w + psrlw xm3, 5 + pinsrw xm2, [r6+r7*2], 2 + shr r8d, 16 + movq r7, xm3 + pinsrw xm2, [r6+r8*2], 3 + movzx r8d, r7w + pinsrw xm2, [r6+r8*2], 4 + rorx r8, r7, 32 + shr r7d, 16 + pinsrw xm2, [r6+r7*2], 5 + movzx r7d, r8w + pinsrw xm2, [r6+r7*2], 6 + shr r8d, 16 + pinsrw xm2, [r6+r8*2], 7 + paddw xm2, xm2 ; otherwise bpc=12 w/ grain_scale_shift=0 + pmulhrsw xm2, xm7 ; shifts by 0, which pmulhrsw does not support + mova [bufq+r3], xm2 + add r3, 8*2 + jl .loop + + ; auto-regression code + add r5, r4 + jmp r5 + +.ar1: + DEFINE_ARGS buf, fg_data, max, shift, val3, min, cf3, x, val0 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_y+3] + movd xm4, [fg_dataq+FGData.ar_coeffs_y] + DEFINE_ARGS buf, h, max, shift, val3, min, cf3, x, val0 + pinsrb xm4, [base+pb_1], 3 + pmovsxbw xm4, xm4 + pshufd xm5, xm4, q1111 + pshufd xm4, xm4, q0000 + vpbroadcastw xm3, [base+round_vals+shiftq*2-12] ; rnd + sub bufq, 2*(82*73-(82*3+79)) + mov hd, 70 + sar maxd, 1 + mov mind, maxd + xor mind, -1 +.y_loop_ar1: + mov xq, -76 + movsx val3d, word [bufq+xq*2-2] +.x_loop_ar1: + movu xm0, [bufq+xq*2-82*2-2] ; top/left + psrldq xm2, xm0, 2 ; top + psrldq xm1, xm0, 4 ; top/right + punpcklwd xm0, xm2 + punpcklwd xm1, xm3 + pmaddwd xm0, xm4 + pmaddwd xm1, xm5 + paddd xm0, xm1 +.x_loop_ar1_inner: + movd val0d, xm0 + psrldq xm0, 4 + imul val3d, cf3d + add val3d, val0d + sarx val3d, val3d, shiftd + movsx val0d, word [bufq+xq*2] + add val3d, val0d + cmp val3d, maxd + cmovg val3d, maxd + cmp val3d, mind + cmovl val3d, mind + mov word [bufq+xq*2], val3w + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xb, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 +.x_loop_ar1_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar1 +.ar0: + RET + +.ar2: + DEFINE_ARGS buf, fg_data, bdmax, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movq xm0, [fg_dataq+FGData.ar_coeffs_y+5] ; cf5-11 + vinserti128 m0, [fg_dataq+FGData.ar_coeffs_y+0], 1 ; cf0-4 + vpbroadcastw xm10, [base+round_vals-12+shiftq*2] + pxor m1, m1 + punpcklwd xm10, xm1 + pcmpgtb m1, m0 + punpcklbw m0, m1 ; cf5-11,0-4 + vpermq m1, m0, q3333 ; cf4 + vbroadcasti128 m11, [base+gen_shufA] + pshufd m6, m0, q0000 ; cf[5,6], cf[0-1] + vbroadcasti128 m12, [base+gen_shufB] + pshufd m7, m0, q1111 ; cf[7,8], cf[2-3] + punpckhwd xm1, xm0 + pshufhw xm9, xm0, q2121 + pshufd xm8, xm1, q0000 ; cf[4,9] + sar bdmaxd, 1 + punpckhqdq xm9, xm9 ; cf[10,11] + movd xm4, bdmaxd ; max_grain + pcmpeqd xm5, xm5 + sub bufq, 2*(82*73-(82*3+79)) + pxor xm5, xm4 ; min_grain + DEFINE_ARGS buf, fg_data, h, x + mov hd, 70 +.y_loop_ar2: + mov xq, -76 +.x_loop_ar2: + vbroadcasti128 m2, [bufq+xq*2-82*4-4] ; y=-2,x=[-2,+5] + vinserti128 m1, m2, [bufq+xq*2-82*2-4], 0 ; y=-1,x=[-2,+5] + pshufb m0, m1, m11 ; y=-1/-2,x=[-2/-1,-1/+0,+0/+1,+1/+2] + pmaddwd m0, m6 + punpckhwd xm2, xm1 ; y=-2/-1 interleaved, x=[+2,+5] + pshufb m1, m12 ; y=-1/-2,x=[+0/+1,+1/+2,+2/+3,+3/+4] + pmaddwd m1, m7 + pmaddwd xm2, xm8 + paddd m0, m1 + vextracti128 xm1, m0, 1 + paddd xm0, xm10 + paddd xm2, xm0 + movu xm0, [bufq+xq*2-4] ; y=0,x=[-2,+5] + paddd xm2, xm1 + pmovsxwd xm1, [bufq+xq*2] ; in dwords, y=0,x=[0,3] +.x_loop_ar2_inner: + pmaddwd xm3, xm9, xm0 + psrldq xm0, 2 + paddd xm3, xm2 + psrldq xm2, 4 ; shift top to next pixel + psrad xm3, [fg_dataq+FGData.ar_coeff_shift] + ; skip packssdw because we only care about one value + paddd xm3, xm1 + pminsd xm3, xm4 + psrldq xm1, 4 + pmaxsd xm3, xm5 + pextrw [bufq+xq*2], xm3, 0 + punpcklwd xm3, xm3 + pblendw xm0, xm3, 0010b + inc xq + jz .x_loop_ar2_end + test xb, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 +.x_loop_ar2_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar2 + RET + +.ar3: + DEFINE_ARGS buf, fg_data, bdmax, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + sar bdmaxd, 1 + movq xm7, [fg_dataq+FGData.ar_coeffs_y+ 0] ; cf0-6 + movd xm0, [fg_dataq+FGData.ar_coeffs_y+14] ; cf14-16 + pinsrb xm7, [fg_dataq+FGData.ar_coeffs_y+13], 7 ; cf0-6,13 + pinsrb xm0, [base+pb_1], 3 ; cf14-16,pb_1 + movd xm1, [fg_dataq+FGData.ar_coeffs_y+21] ; cf21-23 + vinserti128 m7, [fg_dataq+FGData.ar_coeffs_y+ 7], 1 ; cf7-13 + vinserti128 m0, [fg_dataq+FGData.ar_coeffs_y+17], 1 ; cf17-20 + vpbroadcastw xm11, [base+round_vals+shiftq*2-12] + movd xm12, bdmaxd ; max_grain + punpcklbw m7, m7 ; sign-extension + punpcklbw m0, m0 ; sign-extension + punpcklbw xm1, xm1 + REPX {psraw x, 8}, m7, m0, xm1 + pshufd m4, m7, q0000 ; cf[0,1] | cf[7,8] + pshufd m5, m7, q1111 ; cf[2,3] | cf[9,10] + pshufd m6, m7, q2222 ; cf[4,5] | cf[11,12] + pshufd xm7, xm7, q3333 ; cf[6,13] + pshufd m8, m0, q0000 ; cf[14,15] | cf[17,18] + pshufd m9, m0, q1111 ; cf[16],pw_1 | cf[19,20] + paddw xm0, xm11, xm11 + pcmpeqd xm13, xm13 + pblendw xm10, xm1, xm0, 00001000b + pxor xm13, xm12 ; min_grain + DEFINE_ARGS buf, fg_data, h, x + sub bufq, 2*(82*73-(82*3+79)) + mov hd, 70 +.y_loop_ar3: + mov xq, -76 +.x_loop_ar3: + movu xm0, [bufq+xq*2-82*6-6+ 0] ; y=-3,x=[-3,+4] + vinserti128 m0, [bufq+xq*2-82*4-6+ 0], 1 ; y=-3/-2,x=[-3,+4] + movq xm1, [bufq+xq*2-82*6-6+16] ; y=-3,x=[+5,+8] + vinserti128 m1, [bufq+xq*2-82*4-6+16], 1 ; y=-3/-2,x=[+5,+12] + palignr m3, m1, m0, 2 ; y=-3/-2,x=[-2,+5] + palignr m1, m0, 12 ; y=-3/-2,x=[+3,+6] + punpckhwd m2, m0, m3 ; y=-3/-2,x=[+1/+2,+2/+3,+3/+4,+4/+5] + punpcklwd m0, m3 ; y=-3/-2,x=[-3/-2,-2/-1,-1/+0,+0/+1] + shufps m3, m0, m2, q1032 ; y=-3/-2,x=[-1/+0,+0/+1,+1/+2,+2/+3] + pmaddwd m0, m4 + pmaddwd m2, m6 + pmaddwd m3, m5 + paddd m0, m2 + movu xm2, [bufq+xq*2-82*2-6+ 0] ; y=-1,x=[-3,+4] + vinserti128 m2, [bufq+xq*2-82*2-6+ 6], 1 ; y=-1,x=[+1,+8] + paddd m0, m3 + psrldq m3, m2, 2 + punpcklwd m3, m2, m3 ; y=-1,x=[-3/-2,-2/-1,-1/+0,+0/+1] + pmaddwd m3, m8 ; x=[+0/+1,+1/+2,+2/+3,+3/+4] + paddd m0, m3 + psrldq m3, m2, 4 + psrldq m2, 6 + vpblendd m2, m11, 0x0f ; rounding constant + punpcklwd m3, m2 ; y=-1,x=[-1/rnd,+0/rnd,+1/rnd,+2/rnd] + pmaddwd m3, m9 ; x=[+2/+3,+3/+4,+4/+5,+5,+6] + vextracti128 xm2, m1, 1 + punpcklwd xm1, xm2 + pmaddwd xm1, xm7 ; y=-3/-2 interleaved,x=[+3,+4,+5,+6] + paddd m0, m3 + vextracti128 xm2, m0, 1 + paddd xm0, xm1 + movu xm1, [bufq+xq*2-6] ; y=0,x=[-3,+4] + paddd xm0, xm2 +.x_loop_ar3_inner: + pmaddwd xm2, xm1, xm10 + pshuflw xm3, xm2, q1032 + paddd xm2, xm0 ; add top + paddd xm2, xm3 ; left+cur + psrldq xm0, 4 + psrad xm2, [fg_dataq+FGData.ar_coeff_shift] + ; skip packssdw because we only care about one value + pminsd xm2, xm12 + pmaxsd xm2, xm13 + pextrw [bufq+xq*2], xm2, 0 + pslldq xm2, 4 + psrldq xm1, 2 + pblendw xm1, xm2, 0100b + inc xq + jz .x_loop_ar3_end + test xb, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 +.x_loop_ar3_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar3 + RET + +%macro GEN_GRAIN_UV_FN 3 ; ss_name, ss_x, ss_y +INIT_XMM avx2 +cglobal generate_grain_uv_%1_16bpc, 4, 11, 8, buf, bufy, fg_data, uv, bdmax +%define base r8-generate_grain_uv_%1_16bpc_avx2_table + lea r8, [generate_grain_uv_%1_16bpc_avx2_table] + movifnidn bdmaxd, bdmaxm + vpbroadcastw xm0, [fg_dataq+FGData.seed] + mov r5d, [fg_dataq+FGData.grain_scale_shift] + movq xm1, [base+next_upperbit_mask] + lea r6d, [bdmaxq+1] + movq xm4, [base+mul_bits] + shr r6d, 11 ; 0 for 10bpc, 2 for 12bpc + movq xm5, [base+hmul_bits] + sub r5, r6 + mova xm6, [base+pb_mask] + vpbroadcastd xm2, [base+pw_seed_xor+uvq*4] + vpbroadcastw xm7, [base+round+r5*2-2] + pxor xm0, xm2 + lea r6, [gaussian_sequence] +%if %2 + mov r7d, 73-35*%3 + add bufq, 44*2 +.loop_y: + mov r5, -44*2 +%else + mov r5, -82*73*2 + sub bufq, r5 +%endif +.loop_x: + pand xm2, xm0, xm1 + psrlw xm3, xm2, 10 + por xm2, xm3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw xm2, xm4 ; bits 0x0f00 are set + pmulhuw xm0, xm5 + pshufb xm3, xm6, xm2 ; set 15th bit for next 4 seeds + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm2, xm0 ; aggregate each bit into next seed's high bit + por xm2, xm3 ; 4 next output seeds + pshuflw xm0, xm2, q3333 + psrlw xm2, 5 + movq r10, xm2 + movzx r9d, r10w + movd xm2, [r6+r9*2] + rorx r9, r10, 32 + shr r10d, 16 + pinsrw xm2, [r6+r10*2], 1 + movzx r10d, r9w + pinsrw xm2, [r6+r10*2], 2 + shr r9d, 16 + pinsrw xm2, [r6+r9*2], 3 + paddw xm2, xm2 ; otherwise bpc=12 w/ grain_scale_shift=0 + pmulhrsw xm2, xm7 ; shifts by 0, which pmulhrsw does not support + movq [bufq+r5], xm2 + add r5, 8 + jl .loop_x +%if %2 + add bufq, 82*2 + dec r7d + jg .loop_y +%endif + + ; auto-regression code + movsxd r6, [fg_dataq+FGData.ar_coeff_lag] + movsxd r6, [r8+r6*4] + add r6, r8 + jmp r6 + +INIT_YMM avx2 +.ar0: + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + vpbroadcastb m0, [fg_dataq+FGData.ar_coeffs_uv+uvq] + sar bdmaxd, 1 + vpbroadcastd m4, [base+gen_ar0_shift-24+shiftq*4] + movd xm6, bdmaxd + pcmpeqw m7, m7 + pmaddubsw m4, m0 ; ar_coeff << (14 - shift) + vpbroadcastw m6, xm6 ; max_gain + pxor m7, m6 ; min_grain + DEFINE_ARGS buf, bufy, h, x +%if %2 + vpbroadcastw m5, [base+hmul_bits+2+%3*2] + sub bufq, 2*(82*(73-35*%3)+82-(82*3+41)) +%else + sub bufq, 2*(82*70-3) +%endif + add bufyq, 2*(3+82*3) + mov hd, 70-35*%3 +.y_loop_ar0: +%if %2 + ; first 32 pixels + movu xm0, [bufyq+16*0] + vinserti128 m0, [bufyq+16*2], 1 + movu xm1, [bufyq+16*1] + vinserti128 m1, [bufyq+16*3], 1 +%if %3 + movu xm2, [bufyq+82*2+16*0] + vinserti128 m2, [bufyq+82*2+16*2], 1 + movu xm3, [bufyq+82*2+16*1] + vinserti128 m3, [bufyq+82*2+16*3], 1 + paddw m0, m2 + paddw m1, m3 +%endif + phaddw m0, m1 + movu xm1, [bufyq+16*4] + vinserti128 m1, [bufyq+16*6], 1 + movu xm2, [bufyq+16*5] + vinserti128 m2, [bufyq+16*7], 1 +%if %3 + movu xm3, [bufyq+82*2+16*4] + vinserti128 m3, [bufyq+82*2+16*6], 1 + paddw m1, m3 + movu xm3, [bufyq+82*2+16*5] + vinserti128 m3, [bufyq+82*2+16*7], 1 + paddw m2, m3 +%endif + phaddw m1, m2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 +%else + xor xd, xd +.x_loop_ar0: + movu m0, [bufyq+xq*2] + movu m1, [bufyq+xq*2+32] +%endif + paddw m0, m0 + paddw m1, m1 + pmulhrsw m0, m4 + pmulhrsw m1, m4 +%if %2 + paddw m0, [bufq+ 0] + paddw m1, [bufq+32] +%else + paddw m0, [bufq+xq*2+ 0] + paddw m1, [bufq+xq*2+32] +%endif + pminsw m0, m6 + pminsw m1, m6 + pmaxsw m0, m7 + pmaxsw m1, m7 +%if %2 + movu [bufq+ 0], m0 + movu [bufq+32], m1 + + ; last 6 pixels + movu xm0, [bufyq+32*4] + movu xm1, [bufyq+32*4+16] +%if %3 + paddw xm0, [bufyq+32*4+82*2] + paddw xm1, [bufyq+32*4+82*2+16] +%endif + phaddw xm0, xm1 + movu xm1, [bufq+32*2] + pmulhrsw xm0, xm5 + paddw xm0, xm0 + pmulhrsw xm0, xm4 + paddw xm0, xm1 + pminsw xm0, xm6 + pmaxsw xm0, xm7 + vpblendd xm0, xm1, 0x08 + movu [bufq+32*2], xm0 +%else + movu [bufq+xq*2+ 0], m0 + movu [bufq+xq*2+32], m1 + add xd, 32 + cmp xd, 64 + jl .x_loop_ar0 + + ; last 12 pixels + movu m0, [bufyq+64*2] + movu m1, [bufq+64*2] + paddw m0, m0 + pmulhrsw m0, m4 + paddw m0, m1 + pminsw m0, m6 + pmaxsw m0, m7 + vpblendd m0, m1, 0xc0 + movu [bufq+64*2], m0 +%endif + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar0 + RET + +INIT_XMM avx2 +.ar1: + DEFINE_ARGS buf, bufy, fg_data, uv, max, cf3, min, val3, x, shift + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_uv+uvq+3] + movd xm4, [fg_dataq+FGData.ar_coeffs_uv+uvq] + pinsrb xm4, [fg_dataq+FGData.ar_coeffs_uv+uvq+4], 3 + DEFINE_ARGS buf, bufy, h, val0, max, cf3, min, val3, x, shift + pmovsxbw xm4, xm4 + pshufd xm5, xm4, q1111 + pshufd xm4, xm4, q0000 + pmovsxwd xm3, [base+round_vals+shiftq*2-12] ; rnd + vpbroadcastw xm6, [base+hmul_bits+2+%3*2] + vpbroadcastd xm3, xm3 +%if %2 + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 + sar maxd, 1 + mov mind, maxd + xor mind, -1 +.y_loop_ar1: + mov xq, -(76>>%2) + movsx val3d, word [bufq+xq*2-2] +.x_loop_ar1: + movu xm0, [bufq+xq*2-82*2-2] ; top/left +%if %2 + movu xm2, [bufyq+xq*4] +%else + movq xm2, [bufyq+xq*2] +%endif +%if %2 +%if %3 + phaddw xm2, [bufyq+xq*4+82*2] + punpckhqdq xm1, xm2, xm2 + paddw xm2, xm1 +%else + phaddw xm2, xm2 +%endif + pmulhrsw xm2, xm6 +%endif + psrldq xm1, xm0, 4 ; top/right + punpcklwd xm1, xm2 + psrldq xm2, xm0, 2 ; top + punpcklwd xm0, xm2 + pmaddwd xm1, xm5 + pmaddwd xm0, xm4 + paddd xm1, xm3 + paddd xm0, xm1 +.x_loop_ar1_inner: + movd val0d, xm0 + psrldq xm0, 4 + imul val3d, cf3d + add val3d, val0d + sarx val3d, val3d, shiftd + movsx val0d, word [bufq+xq*2] + add val3d, val0d + cmp val3d, maxd + cmovg val3d, maxd + cmp val3d, mind + cmovl val3d, mind + mov word [bufq+xq*2], val3w + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xb, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 +.x_loop_ar1_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar1 + RET + +INIT_YMM avx2 +.ar2: +%if WIN64 + ; xmm6 and xmm7 already saved + %assign xmm_regs_used 13 + %2 + %assign stack_size_padded 136 + SUB rsp, stack_size_padded + movaps [rsp+16*2], xmm8 + movaps [rsp+16*3], xmm9 + movaps [rsp+16*4], xmm10 + movaps [rsp+16*5], xmm11 + movaps [rsp+16*6], xmm12 +%if %2 + movaps [rsp+16*7], xmm13 +%endif +%endif + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + vbroadcasti128 m10, [base+gen_shufA] + sar bdmaxd, 1 + vbroadcasti128 m11, [base+gen_shufB] + movd xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 5] + pinsrb xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+12], 4 + pinsrb xm7, [base+pb_1], 5 + pinsrw xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+10], 3 + movhps xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 0] + pinsrb xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 9], 13 + pmovsxbw m7, xm7 + movd xm8, bdmaxd ; max_grain + pshufd m4, m7, q0000 + vpbroadcastw xm12, [base+round_vals-12+shiftq*2] + pshufd m5, m7, q1111 + pcmpeqd xm9, xm9 + pshufd m6, m7, q2222 + pxor xm9, xm8 ; min_grain + pshufd xm7, xm7, q3333 + DEFINE_ARGS buf, bufy, fg_data, h, x +%if %2 + vpbroadcastw xm13, [base+hmul_bits+2+%3*2] + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 +.y_loop_ar2: + mov xq, -(76>>%2) +.x_loop_ar2: + vbroadcasti128 m3, [bufq+xq*2-82*2-4] ; y=-1,x=[-2,+5] + vinserti128 m2, m3, [bufq+xq*2-82*4-4], 1 ; y=-2,x=[-2,+5] + pshufb m0, m2, m10 ; y=-1/-2,x=[-2/-1,-1/+0,+0/+1,+1/+2] + pmaddwd m0, m4 + pshufb m1, m2, m11 ; y=-1/-2,x=[+0/+1,+1/+2,+2/+3,+3/+4] + pmaddwd m1, m5 + punpckhwd m2, m3 ; y=-2/-1 interleaved, x=[+2,+5] +%if %2 + movu xm3, [bufyq+xq*4] +%if %3 + paddw xm3, [bufyq+xq*4+82*2] +%endif + phaddw xm3, xm3 + pmulhrsw xm3, xm13 +%else + movq xm3, [bufyq+xq*2] +%endif + punpcklwd xm3, xm12 ; luma, round interleaved + vpblendd m2, m3, 0x0f + pmaddwd m2, m6 + paddd m1, m0 + movu xm0, [bufq+xq*2-4] ; y=0,x=[-2,+5] + paddd m2, m1 + vextracti128 xm1, m2, 1 + paddd xm2, xm1 + pshufd xm1, xm0, q3321 + pmovsxwd xm1, xm1 ; y=0,x=[0,3] in dword +.x_loop_ar2_inner: + pmaddwd xm3, xm7, xm0 + paddd xm3, xm2 + psrldq xm2, 4 ; shift top to next pixel + psrad xm3, [fg_dataq+FGData.ar_coeff_shift] + ; we do not need to packssdw since we only care about one value + paddd xm3, xm1 + psrldq xm1, 4 + pminsd xm3, xm8 + pmaxsd xm3, xm9 + pextrw [bufq+xq*2], xm3, 0 + psrldq xm0, 2 + pslldq xm3, 2 + pblendw xm0, xm3, 00000010b + inc xq + jz .x_loop_ar2_end + test xb, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 +.x_loop_ar2_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar2 + RET + +.ar3: +%if WIN64 + ; xmm6 and xmm7 already saved + %assign stack_offset 32 + %assign xmm_regs_used 14 + %2 + %assign stack_size_padded 152 + SUB rsp, stack_size_padded + movaps [rsp+16*2], xmm8 + movaps [rsp+16*3], xmm9 + movaps [rsp+16*4], xmm10 + movaps [rsp+16*5], xmm11 + movaps [rsp+16*6], xmm12 + movaps [rsp+16*7], xmm13 +%if %2 + movaps [rsp+16*8], xmm14 +%endif +%endif + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + vpbroadcastw xm11, [base+round_vals-12+shiftq*2] + sar bdmaxd, 1 + movq xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 0] + pinsrb xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+24], 7 ; luma + movhps xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 7] + pmovsxbw m7, xm7 +%if %2 + vpbroadcastw xm14, [base+hmul_bits+2+%3*2] +%endif + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + movd xm0, [fg_dataq+FGData.ar_coeffs_uv+uvq+14] + pinsrb xm0, [base+pb_1], 3 + pinsrd xm0, [fg_dataq+FGData.ar_coeffs_uv+uvq+21], 1 + pinsrd xm0, [fg_dataq+FGData.ar_coeffs_uv+uvq+17], 2 + pmovsxbw m0, xm0 + movd xm12, bdmaxd ; max_grain + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pcmpeqd xm13, xm13 + punpckhqdq xm10, xm0, xm0 + pxor xm13, xm12 ; min_grain + pinsrw xm10, [base+round_vals-10+shiftq*2], 3 + DEFINE_ARGS buf, bufy, fg_data, h, unused, x +%if %2 + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 +.y_loop_ar3: + mov xq, -(76>>%2) +.x_loop_ar3: + movu xm2, [bufq+xq*2-82*6-6+ 0] ; y=-3,x=[-3,+4] + vinserti128 m2, [bufq+xq*2-82*4-6+ 0], 1 ; y=-3/-2,x=[-3,+4] + movq xm1, [bufq+xq*2-82*6-6+16] ; y=-3,x=[+5,+8] + vinserti128 m1, [bufq+xq*2-82*4-6+16], 1 ; y=-3/-2,x=[+5,+12] + palignr m3, m1, m2, 2 ; y=-3/-2,x=[-2,+5] + palignr m1, m2, 12 ; y=-3/-2,x=[+3,+6] + punpcklwd m0, m2, m3 ; y=-3/-2,x=[-3/-2,-2/-1,-1/+0,+0/+1] + punpckhwd m2, m3 ; y=-3/-2,x=[+1/+2,+2/+3,+3/+4,+4/+5] + shufps m3, m0, m2, q1032 ; y=-3/-2,x=[-1/+0,+0/+1,+1/+2,+2/+3] + pmaddwd m0, m4 + pmaddwd m2, m6 + pmaddwd m3, m5 + paddd m0, m2 + paddd m0, m3 + movu xm2, [bufq+xq*2-82*2-6+ 0] ; y=-1,x=[-3,+4] + vinserti128 m2, [bufq+xq*2-82*2-6+ 6], 1 ; y=-1,x=[+1,+8] +%if %2 + movu xm3, [bufyq+xq*4] +%if %3 + paddw xm3, [bufyq+xq*4+82*2] +%endif + phaddw xm3, xm3 + pmulhrsw xm3, xm14 +%else + movq xm3, [bufyq+xq*2] +%endif + punpcklwd m1, m3 + pmaddwd m1, m7 + paddd m0, m1 + psrldq m1, m2, 4 + psrldq m3, m2, 6 + vpblendd m3, m11, 0x0f ; rounding constant + punpcklwd m1, m3 ; y=-1,x=[-1/rnd,+0/rnd,+1/rnd,+2/rnd] + pmaddwd m1, m9 ; x=[+2/+3,+3/+4,+4/+5,+5,+6] + psrldq m3, m2, 2 + punpcklwd m2, m3 ; y=-1,x=[-3/-2,-2/-1,-1/+0,+0/+1] + pmaddwd m2, m8 ; x=[+0/+1,+1/+2,+2/+3,+3/+4] + paddd m0, m1 + movu xm1, [bufq+xq*2-6] ; y=0,x=[-3,+4] + paddd m0, m2 + vextracti128 xm2, m0, 1 + paddd xm0, xm2 +.x_loop_ar3_inner: + pmaddwd xm2, xm1, xm10 + pshuflw xm3, xm2, q1032 + paddd xm2, xm0 ; add top + paddd xm2, xm3 ; left+cur + psrldq xm0, 4 + psrad xm2, [fg_dataq+FGData.ar_coeff_shift] + psrldq xm1, 2 + ; no need to packssdw since we only care about one value + pminsd xm2, xm12 + pmaxsd xm2, xm13 + pextrw [bufq+xq*2], xm2, 0 + pslldq xm2, 4 + pblendw xm1, xm2, 00000100b + inc xq + jz .x_loop_ar3_end + test xb, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 +.x_loop_ar3_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar3 + RET +%endmacro + +cglobal fgy_32x32xn_16bpc, 6, 14, 16, dst, src, stride, fg_data, w, scaling, \ + grain_lut, unused, sby, see +%define base r11-grain_min + lea r11, [grain_min] + mov r6d, r9m ; bdmax + mov r9d, [fg_dataq+FGData.clip_to_restricted_range] + mov r7d, [fg_dataq+FGData.scaling_shift] + mov sbyd, sbym + vpbroadcastd m8, r9m + shr r6d, 11 ; is_12bpc + vpbroadcastd m9, [base+grain_min+r6*4] + shlx r10d, r9d, r6d + vpbroadcastd m10, [base+grain_max+r6*4] + lea r9d, [r6+r9*4] + vpbroadcastw m11, [base+mul_bits+r7*2-12] + vpbroadcastd m12, [base+fg_min+r10*4] + vpbroadcastd m13, [base+fg_max+r9*4] + test sbyd, sbyd + setnz r7b + vpbroadcastd m14, [base+pd_16] + test r7b, [fg_dataq+FGData.overlap_flag] + jnz .vertical_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak + + lea src_bakq, [srcq+wq*2] + neg wq + sub dstq, srcq + +.loop_x: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y: + ; scaling[src] + mova m0, [srcq+ 0] + mova m1, [srcq+32] + pand m4, m8, m0 + psrld m3, m0, 16 + mova m6, m9 + vpgatherdd m2, [scalingq+m4-0], m9 + pand m3, m8 + mova m9, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pand m5, m8, m1 + mova m6, m9 + vpgatherdd m3, [scalingq+m5-0], m9 + pblendw m4, m2, 0x55 + psrld m2, m1, 16 + mova m9, m6 + pand m2, m8 + vpgatherdd m5, [scalingq+m2-2], m6 + pblendw m5, m3, 0x55 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m4, [grain_lutq+offxyq*2] + pmulhrsw m5, [grain_lutq+offxyq*2+32] + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+32], m1 + + add srcq, strideq + add grain_lutq, 82*2 + dec hd + jg .loop_y + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + cmp byte [fg_dataq+FGData.overlap_flag], 0 + je .loop_x + movq xm7, [pw_27_17_17_27] + cmp dword r8m, 0 ; sby + jne .loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +.loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, left_offxy + + lea left_offxyd, [offyq+32] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, left_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y_h_overlap: + ; scaling[src] + mova m0, [srcq+ 0] + mova m1, [srcq+32] + pand m4, m8, m0 + psrld m3, m0, 16 + mova m6, m9 + vpgatherdd m2, [scalingq+m4-0], m9 + pand m3, m8 + mova m9, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pand m5, m8, m1 + mova m6, m9 + vpgatherdd m3, [scalingq+m5-0], m9 + pblendw m4, m2, 0x55 + psrld m2, m1, 16 + mova m9, m6 + pand m2, m8 + vpgatherdd m5, [scalingq+m2-2], m6 + pblendw m5, m3, 0x55 + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq*2] + movd xm6, [grain_lutq+left_offxyq*2] + punpcklwd xm6, xm3 + pmaddwd xm6, xm7 + paddd xm6, xm14 + psrad xm6, 5 + packssdw xm6, xm6 + pmaxsw xm6, xm9 + pminsw xm6, xm10 + vpblendd m3, m6, 0x01 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m4, m3 + pmulhrsw m5, [grain_lutq+offxyq*2+32] + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+32], m1 + + add srcq, strideq + add grain_lutq, 82*2 + dec hd + jg .loop_y_h_overlap + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + cmp dword r8m, 0 ; sby + jne .loop_x_hv_overlap + jmp .loop_x_h_overlap + +.vertical_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused1, \ + sby, see, src_bak + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + + lea src_bakq, [srcq+wq*2] + neg wq + sub dstq, srcq + +.loop_x_v_overlap: + vpbroadcastd m15, [pw_27_17_17_27] + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, unused, top_offxy + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, unused, top_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +.loop_y_v_overlap: + ; scaling[src] + mova m0, [srcq+ 0] + mova m1, [srcq+32] + pand m4, m8, m0 + psrld m3, m0, 16 + mova m6, m9 + vpgatherdd m2, [scalingq+m4-0], m9 + pand m3, m8 + mova m9, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pand m5, m8, m1 + mova m6, m9 + vpgatherdd m3, [scalingq+m5-0], m9 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m9, m6 + pand m4, m8 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m6, [grain_lutq+offxyq*2] + movu m5, [grain_lutq+top_offxyq*2] + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + pmaddwd m4, m15 + pmaddwd m5, m15 + movu m7, [grain_lutq+offxyq*2+32] + movu m6, [grain_lutq+top_offxyq*2+32] + paddd m4, m14 + paddd m5, m14 + psrad m4, 5 + psrad m5, 5 + packssdw m4, m5 + punpcklwd m5, m6, m7 + punpckhwd m6, m7 + pmaddwd m5, m15 + pmaddwd m6, m15 + paddd m5, m14 + paddd m6, m14 + psrad m5, 5 + psrad m6, 5 + packssdw m5, m6 + pmaxsw m4, m9 + pmaxsw m5, m9 + pminsw m4, m10 + pminsw m5, m10 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m11 + pmaddubsw m3, m11 + paddw m2, m2 + paddw m3, m3 + pmulhrsw m4, m2 + pmulhrsw m5, m3 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+32], m1 + + add srcq, strideq + add grain_lutq, 82*2 + dec hb + jz .end_y_v_overlap + vpbroadcastd m15, [pw_27_17_17_27+4] ; swap weights for second v-overlap line + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + add hd, 0x80000000 + jnc .loop_y_v_overlap + jmp .loop_y +.end_y_v_overlap: + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap + +.loop_x_hv_overlap: + vpbroadcastd m15, [pw_27_17_17_27] + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyd, [top_offxyq+32] + lea left_offxyd, [offyq+32] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, left_offxy, top_offxy, topleft_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +.loop_y_hv_overlap: + ; scaling[src] + mova m0, [srcq+ 0] + mova m1, [srcq+32] + pand m4, m8, m0 + psrld m3, m0, 16 + mova m6, m9 + vpgatherdd m2, [scalingq+m4-0], m9 + pand m3, m8 + mova m9, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pand m5, m8, m1 + mova m6, m9 + vpgatherdd m3, [scalingq+m5-0], m9 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m9, m6 + pand m4, m8 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m7, [grain_lutq+offxyq*2] + movd xm6, [grain_lutq+left_offxyq*2] + movu m5, [grain_lutq+top_offxyq*2] + movd xm4, [grain_lutq+topleft_offxyq*2] + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklwd xm6, xm7 + punpcklwd xm4, xm5 + punpcklqdq xm6, xm4 + movddup xm4, [pw_27_17_17_27] + pmaddwd xm6, xm4 + paddd xm6, xm14 + psrad xm6, 5 + packssdw xm6, xm6 + pmaxsw xm6, xm9 + pminsw xm6, xm10 + pshuflw xm4, xm6, q1032 + vpblendd m6, m7, 0xfe + vpblendd m4, m5, 0xfe + ; followed by v interpolation (top | cur -> cur) + punpckhwd m5, m7 + pmaddwd m5, m15 + punpcklwd m4, m6 + pmaddwd m4, m15 + movu m7, [grain_lutq+offxyq*2+32] + movu m6, [grain_lutq+top_offxyq*2+32] + paddd m5, m14 + paddd m4, m14 + psrad m5, 5 + psrad m4, 5 + packssdw m4, m5 + punpcklwd m5, m6, m7 + punpckhwd m6, m7 + pmaddwd m5, m15 + pmaddwd m6, m15 + paddd m5, m14 + paddd m6, m14 + psrad m5, 5 + psrad m6, 5 + packssdw m5, m6 + pmaxsw m4, m9 + pmaxsw m5, m9 + pminsw m4, m10 + pminsw m5, m10 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m11 + pmaddubsw m3, m11 + paddw m2, m2 + paddw m3, m3 + pmulhrsw m4, m2 + pmulhrsw m5, m3 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+32], m1 + + add srcq, strideq + add grain_lutq, 82*2 + dec hb + jz .end_y_hv_overlap + vpbroadcastd m15, [pw_27_17_17_27+4] ; swap weights for second v-overlap line + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + add hd, 0x80000000 + jnc .loop_y_hv_overlap + movq xm7, [pw_27_17_17_27] + jmp .loop_y_h_overlap +.end_y_hv_overlap: + add wq, 32 + lea srcq, [src_bakq+wq*2] + jl .loop_x_hv_overlap +.end: + RET + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +cglobal fguv_32x32xn_i%1_16bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, luma, lstride, uv_pl, is_id +%define base r12-grain_min + lea r12, [grain_min] + mov r9d, r13m ; bdmax + mov r7d, [fg_dataq+FGData.scaling_shift] + mov r11d, is_idm + mov sbyd, sbym + vpbroadcastw m11, [base+mul_bits+r7*2-12] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] + shr r9d, 11 ; is_12bpc + vpbroadcastd m8, [base+grain_min+r9*4] + shlx r10d, r6d, r9d + vpbroadcastd m9, [base+grain_max+r9*4] + vpbroadcastw m10, r13m + shlx r6d, r6d, r11d + vpbroadcastd m12, [base+fg_min+r10*4] + lea r6d, [r9+r6*2] + vpbroadcastd m13, [base+fg_max+r6*4] + test sbyd, sbyd + setnz r7b + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_hor, ss_ver + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused, sby, see, overlap + +%if %1 + mov r6d, r11m + vpbroadcastd m0, [base+pb_8_9_0_1] + vpbroadcastd m1, [base+uv_offset_mul+r9*4] + vbroadcasti128 m14, [fg_dataq+FGData.uv_mult+r6*4] + vpbroadcastd m15, [fg_dataq+FGData.uv_offset+r6*4] + pshufb m14, m0 ; { uv_luma_mult, uv_mult } + pmaddwd m15, m1 +%else +%if %2 + vpbroadcastq m15, [base+pw_23_22] +%else + vpbroadcastq m15, [base+pw_27_17_17_27] +%endif + vpbroadcastd m14, [base+pd_16] +%endif + test r7b, [fg_dataq+FGData.overlap_flag] + jnz %%vertical_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused2, unused3, see, unused4, unused5, unused6, luma, lstride + + mov lumaq, r9mp + mov lstrideq, r10mp + lea r10, [srcq+wq*2] + lea r11, [dstq+wq*2] + lea r12, [lumaq+wq*(2<<%2)] + mov r9mp, r10 + mov r11mp, r11 + mov r12mp, r12 + neg wq + +%%loop_x: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, unused1, unused2, unused3, luma, lstride + + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+(3+(6>>%2))] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, unused1, unused2, unused3, luma, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y: + ; luma_src +%if %2 + mova xm2, [lumaq+lstrideq*0+ 0] + vinserti128 m2, [lumaq+lstrideq*0+32], 1 + mova xm4, [lumaq+lstrideq*0+16] + vinserti128 m4, [lumaq+lstrideq*0+48], 1 + mova xm3, [lumaq+lstrideq*(1<<%3)+ 0] + vinserti128 m3, [lumaq+lstrideq*(1<<%3)+32], 1 + mova xm5, [lumaq+lstrideq*(1<<%3)+16] + vinserti128 m5, [lumaq+lstrideq*(1<<%3)+48], 1 + phaddw m2, m4 + phaddw m3, m5 + pxor m4, m4 + pavgw m2, m4 + pavgw m3, m4 +%elif %1 + mova m2, [lumaq+ 0] + mova m3, [lumaq+32] +%endif +%if %1 + mova m0, [srcq] +%if %2 + mova m1, [srcq+strideq] +%else + mova m1, [srcq+32] +%endif + punpckhwd m4, m2, m0 + punpcklwd m2, m0 + punpckhwd m5, m3, m1 + punpcklwd m3, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m4, m2, m5, m3 + REPX {paddd x, m15}, m4, m2, m5, m3 + REPX {psrad x, 6 }, m4, m2, m5, m3 + packusdw m2, m4 + packusdw m3, m5 + pminuw m2, m10 + pminuw m3, m10 ; clip_pixel() +%elif %2 + pand m2, m10 + pand m3, m10 +%else + pand m2, m10, [lumaq+ 0] + pand m3, m10, [lumaq+32] +%endif + + ; scaling[luma_src] + vpbroadcastd m7, [pd_m65536] + pandn m4, m7, m2 + mova m6, m7 + vpgatherdd m5, [scalingq+m4-0], m7 + psrld m2, 16 + mova m7, m6 + vpgatherdd m4, [scalingq+m2-2], m6 + pblendw m4, m5, 0x55 + pandn m5, m7, m3 + mova m6, m7 + vpgatherdd m2, [scalingq+m5-0], m7 + psrld m3, 16 + vpgatherdd m5, [scalingq+m3-2], m6 + pblendw m5, m2, 0x55 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m4, [grain_lutq+offxyq*2] +%if %2 + pmulhrsw m5, [grain_lutq+offxyq*2+82*2] +%else + pmulhrsw m5, [grain_lutq+offxyq*2+32] +%endif + + ; dst = clip_pixel(src, noise) +%if %1 + paddw m0, m4 + paddw m1, m5 +%else + paddw m0, m4, [srcq] +%if %2 + paddw m1, m5, [srcq+strideq] +%else + paddw m1, m5, [srcq+32] +%endif +%endif + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq], m0 +%if %2 + mova [dstq+strideq], m1 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + mova [dstq+32], m1 + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82*(2<<%2) +%if %2 + sub hb, 2 +%else + dec hb +%endif + jg %%loop_y + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + cmp byte [fg_dataq+FGData.overlap_flag], 0 + je %%loop_x + cmp dword r8m, 0 ; sby + jne %%loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, unused1, unused2, luma, lstride + + lea left_offxyd, [offyq+(32>>%2)] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, unused1, unused2, luma, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y_h_overlap: + ; luma_src +%if %2 + mova xm2, [lumaq+lstrideq*0+ 0] + vinserti128 m2, [lumaq+lstrideq*0+32], 1 + mova xm4, [lumaq+lstrideq*0+16] + vinserti128 m4, [lumaq+lstrideq*0+48], 1 + mova xm3, [lumaq+lstrideq*(1<<%3)+ 0] + vinserti128 m3, [lumaq+lstrideq*(1<<%3)+32], 1 + mova xm5, [lumaq+lstrideq*(1<<%3)+16] + vinserti128 m5, [lumaq+lstrideq*(1<<%3)+48], 1 + phaddw m2, m4 + phaddw m3, m5 + pxor m4, m4 + pavgw m2, m4 + pavgw m3, m4 +%elif %1 + mova m2, [lumaq] + mova m3, [lumaq+32] +%endif +%if %1 + mova m0, [srcq] +%if %2 + mova m1, [srcq+strideq] +%else + mova m1, [srcq+32] +%endif + punpckhwd m4, m2, m0 + punpcklwd m2, m0 + punpckhwd m5, m3, m1 + punpcklwd m3, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m4, m2, m5, m3 + REPX {paddd x, m15}, m4, m2, m5, m3 + REPX {psrad x, 6 }, m4, m2, m5, m3 + packusdw m2, m4 + packusdw m3, m5 + pminuw m2, m10 ; clip_pixel() + pminuw m3, m10 +%elif %2 + pand m2, m10 + pand m3, m10 +%else + pand m2, m10, [lumaq+ 0] + pand m3, m10, [lumaq+32] +%endif + + ; scaling[luma_src] + vpbroadcastd m7, [pd_m65536] + pandn m4, m7, m2 + mova m6, m7 + vpgatherdd m5, [scalingq+m4-0], m7 + psrld m2, 16 + mova m7, m6 + vpgatherdd m4, [scalingq+m2-2], m6 + pblendw m4, m5, 0x55 + pandn m5, m7, m3 + mova m6, m7 + vpgatherdd m2, [scalingq+m5-0], m7 + psrld m3, 16 + vpgatherdd m5, [scalingq+m3-2], m6 + pblendw m5, m2, 0x55 + + ; grain = grain_lut[offy+y][offx+x] + movu m2, [grain_lutq+offxyq*2] +%if %2 + movu m3, [grain_lutq+offxyq*2+82*2] +%else + movu m3, [grain_lutq+offxyq*2+32] +%endif + movd xm6, [grain_lutq+left_offxyq*2] +%if %2 + pinsrw xm6, [grain_lutq+left_offxyq*2+82*2], 2 ; {left0, left1} + punpckldq xm7, xm2, xm3 ; {cur0, cur1} + punpcklwd xm6, xm7 ; {left0, cur0, left1, cur1} +%else + punpcklwd xm6, xm2 +%endif +%if %1 +%if %2 + vpbroadcastq xm7, [pw_23_22] +%else + movq xm7, [pw_27_17_17_27] +%endif + pmaddwd xm6, xm7 + vpbroadcastd xm7, [pd_16] + paddd xm6, xm7 +%else + pmaddwd xm6, xm15 + paddd xm6, xm14 +%endif + psrad xm6, 5 + packssdw xm6, xm6 + pmaxsw xm6, xm8 + pminsw xm6, xm9 + vpblendd m2, m6, 0x01 +%if %2 + pshuflw xm6, xm6, q1032 + vpblendd m3, m6, 0x01 +%endif + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + + ; dst = clip_pixel(src, noise) +%if %1 + paddw m0, m2 + paddw m1, m3 +%else + paddw m0, m2, [srcq] +%if %2 + paddw m1, m3, [srcq+strideq] +%else + paddw m1, m3, [srcq+32] +%endif +%endif + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq], m0 +%if %2 + mova [dstq+strideq], m1 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + mova [dstq+32], m1 + add srcq, strideq + add dstq, strideq + add lumaq, r10mp +%endif + add grain_lutq, 82*(2<<%2) +%if %2 + sub hb, 2 +%else + dec hb +%endif + jg %%loop_y_h_overlap + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + cmp dword r8m, 0 ; sby + jne %%loop_x_hv_overlap + jmp %%loop_x_h_overlap + +%%vertical_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, \ + sby, see, unused1, unused2, unused3, lstride + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, unused1, top_offxy, unused2, luma, lstride + + mov lumaq, r9mp + mov lstrideq, r10mp + lea r10, [srcq+wq*2] + lea r11, [dstq+wq*2] + lea r12, [lumaq+wq*(2<<%2)] + mov r9mp, r10 + mov r11mp, r11 + mov r12mp, r12 + neg wq + +%%loop_x_v_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, unused1, top_offxy, unused2, luma, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +%if %2 == 0 + lea r10, [pw_27_17_17_27] +%endif +%%loop_y_v_overlap: + ; luma_src +%if %2 + mova xm2, [lumaq+lstrideq*0+ 0] + vinserti128 m2, [lumaq+lstrideq*0+32], 1 + mova xm4, [lumaq+lstrideq*0+16] + vinserti128 m4, [lumaq+lstrideq*0+48], 1 + mova xm3, [lumaq+lstrideq*(1<<%3)+ 0] + vinserti128 m3, [lumaq+lstrideq*(1<<%3)+32], 1 + mova xm5, [lumaq+lstrideq*(1<<%3)+16] + vinserti128 m5, [lumaq+lstrideq*(1<<%3)+48], 1 + phaddw m2, m4 + phaddw m3, m5 + pxor m4, m4 + pavgw m2, m4 + pavgw m3, m4 +%elif %1 + mova m2, [lumaq] + mova m3, [lumaq+32] +%endif +%if %1 + mova m0, [srcq] +%if %2 + mova m1, [srcq+strideq] +%else + mova m1, [srcq+32] +%endif + punpckhwd m4, m2, m0 + punpcklwd m2, m0 + punpckhwd m5, m3, m1 + punpcklwd m3, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m4, m2, m5, m3 + REPX {paddd x, m15}, m4, m2, m5, m3 + REPX {psrad x, 6 }, m4, m2, m5, m3 + packusdw m2, m4 + packusdw m3, m5 + pminuw m2, m10 ; clip_pixel() + pminuw m3, m10 +%elif %2 + pand m2, m10 + pand m3, m10 +%else + pand m2, m10, [lumaq+ 0] + pand m3, m10, [lumaq+32] +%endif + + ; scaling[luma_src] + vpbroadcastd m7, [pd_m65536] + pandn m4, m7, m2 + mova m6, m7 + vpgatherdd m5, [scalingq+m4-0], m7 + psrld m2, 16 + mova m7, m6 + vpgatherdd m4, [scalingq+m2-2], m6 + pblendw m4, m5, 0x55 + pandn m5, m7, m3 + mova m6, m7 + vpgatherdd m2, [scalingq+m5-0], m7 + psrld m3, 16 + vpgatherdd m5, [scalingq+m3-2], m6 + pblendw m5, m2, 0x55 + + ; grain = grain_lut[offy+y][offx+x] + movu m6, [grain_lutq+offxyq*2] + movu m3, [grain_lutq+top_offxyq*2] + punpcklwd m2, m3, m6 + punpckhwd m3, m6 ; { top, cur } +%if %3 + vpbroadcastd m0, [pw_23_22] +%elif %2 + vpbroadcastd m0, [pw_27_17_17_27] +%else + vpbroadcastd m0, [r10] +%endif + REPX {pmaddwd x, m0}, m2, m3 +%if %1 + vpbroadcastd m1, [pd_16] + REPX {paddd x, m1}, m2, m3 +%else + REPX {paddd x, m14}, m2, m3 +%endif + REPX {psrad x, 5}, m2, m3 + packssdw m2, m3 +%if %2 + movu m3, [grain_lutq+offxyq*2+82*2] +%else + movu m3, [grain_lutq+offxyq*2+32] +%endif +%if %3 + pmaxsw m2, m8 + pminsw m2, m9 +%else +%if %2 + movu m7, [grain_lutq+top_offxyq*2+82*2] + punpckhwd m6, m3, m7 ; { cur, top } + punpcklwd m3, m7 +%else + movu m7, [grain_lutq+top_offxyq*2+32] + punpckhwd m6, m7, m3 + punpcklwd m3, m7, m3 ; { top, cur } +%endif + pmaddwd m6, m0 + pmaddwd m3, m0 +%if %1 + paddd m6, m1 + paddd m3, m1 +%else + paddd m6, m14 + paddd m3, m14 +%endif + psrad m6, 5 + psrad m3, 5 + packssdw m3, m6 + pmaxsw m2, m8 + pmaxsw m3, m8 + pminsw m2, m9 + pminsw m3, m9 +%endif + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + + ; dst = clip_pixel(src, noise) + paddw m0, m2, [srcq] +%if %2 + paddw m1, m3, [srcq+strideq] +%else + paddw m1, m3, [srcq+32] +%endif + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq], m0 +%if %2 + mova [dstq+strideq], m1 + sub hb, 2 +%else + mova [dstq+32], m1 + dec hb +%endif + jle %%end_y_v_overlap +%if %2 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82*(2<<%2) +%if %2 + jmp %%loop_y +%else + add hd, 0x80000000 + jc %%loop_y + add r10, 4 + jmp %%loop_y_v_overlap +%endif +%%end_y_v_overlap: + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap +%%loop_x_hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy, luma, lstride + +%if %2 == 0 + lea r14, [pw_27_17_17_27] +%endif + lea topleft_offxyq, [top_offxyq+(32>>%2)] + lea left_offxyq, [offyq+(32>>%2)] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy, luma, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +%%loop_y_hv_overlap: + ; luma_src +%if %2 + mova xm2, [lumaq+lstrideq*0+ 0] + vinserti128 m2, [lumaq+lstrideq*0+32], 1 + mova xm4, [lumaq+lstrideq*0+16] + vinserti128 m4, [lumaq+lstrideq*0+48], 1 + mova xm3, [lumaq+lstrideq*(1<<%3)+ 0] + vinserti128 m3, [lumaq+lstrideq*(1<<%3)+32], 1 + mova xm5, [lumaq+lstrideq*(1<<%3)+16] + vinserti128 m5, [lumaq+lstrideq*(1<<%3)+48], 1 + phaddw m2, m4 + phaddw m3, m5 + pxor m4, m4 + pavgw m2, m4 + pavgw m3, m4 +%elif %1 + mova m2, [lumaq] + mova m3, [lumaq+32] +%endif +%if %1 + mova m0, [srcq] +%if %2 + mova m1, [srcq+strideq] +%else + mova m1, [srcq+32] +%endif + punpckhwd m4, m2, m0 + punpcklwd m2, m0 + punpckhwd m5, m3, m1 + punpcklwd m3, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m4, m2, m5, m3 + REPX {paddd x, m15}, m4, m2, m5, m3 + REPX {psrad x, 6 }, m4, m2, m5, m3 + packusdw m2, m4 + packusdw m3, m5 + pminuw m2, m10 ; clip_pixel() + pminuw m3, m10 +%elif %2 + pand m2, m10 + pand m3, m10 +%else + pand m2, m10, [lumaq+ 0] + pand m3, m10, [lumaq+32] +%endif + + ; scaling[luma_src] + vpbroadcastd m7, [pd_m65536] + pandn m4, m7, m2 + mova m6, m7 + vpgatherdd m5, [scalingq+m4-0], m7 + psrld m2, 16 + mova m7, m6 + vpgatherdd m4, [scalingq+m2-2], m6 + pblendw m4, m5, 0x55 + pandn m5, m7, m3 + mova m6, m7 + vpgatherdd m2, [scalingq+m5-0], m7 + psrld m3, 16 + vpgatherdd m5, [scalingq+m3-2], m6 + pblendw m5, m2, 0x55 + + ; grain = grain_lut[offy+y][offx+x] + movu m0, [grain_lutq+offxyq*2] + movd xm2, [grain_lutq+left_offxyq*2] + movu m6, [grain_lutq+top_offxyq*2] +%if %2 + pinsrw xm2, [grain_lutq+left_offxyq*2+82*2], 2 + movu m3, [grain_lutq+offxyq*2+82*2] + punpckldq xm1, xm0, xm3 ; { cur0, cur1 } +%if %3 + vinserti128 m2, [grain_lutq+topleft_offxyq*2], 1 ; { left0, left1, top/left } + vinserti128 m1, [grain_lutq+top_offxyq*2], 1 ; { cur0, cur1, top0 } +%else + vinserti128 m2, [grain_lutq+topleft_offxyq*2+82*2], 1 + vpbroadcastd m7, [grain_lutq+topleft_offxyq*2] + vpblendd m2, m7, 0x20 + movd xm7, [grain_lutq+top_offxyq*2+82*2] + punpckldq xm7, xm6 + vinserti128 m1, xm7, 1 + movu m7, [grain_lutq+top_offxyq*2+82*2] +%endif + punpcklwd m2, m1 ; { cur, left } +%if %1 + vpbroadcastq m1, [pw_23_22] + pmaddwd m2, m1 + vpbroadcastd m1, [pd_16] + paddd m2, m1 + psrad m2, 5 + packssdw m2, m2 + vpermq m2, m2, q3120 +%else + pmaddwd m2, m15 + paddd m2, m14 + psrad m2, 5 + vextracti128 xm1, m2, 1 + packssdw xm2, xm1 +%endif +%else + pinsrd xm2, [grain_lutq+topleft_offxyq*2], 1 + movu m3, [grain_lutq+offxyq*2+32] + movu m7, [grain_lutq+top_offxyq*2+32] + punpckldq xm1, xm0, xm6 + punpcklwd xm2, xm1 ; { cur, left } +%if %1 + movddup xm1, [pw_27_17_17_27] + pmaddwd xm2, xm1 + vpbroadcastd m1, [pd_16] + paddd xm2, xm1 +%else + pmaddwd xm2, xm15 + paddd xm2, xm14 +%endif + psrad xm2, 5 + packssdw xm2, xm2 +%endif + pmaxsw xm2, xm8 + pminsw xm2, xm9 + vpblendd m0, m2, 0x01 +%if %2 + pshufd xm2, xm2, q0321 + vpblendd m3, m2, 0x01 +%if %3 == 0 + pshufd xm2, xm2, q0321 + vpblendd m7, m2, 0x01 +%endif +%endif + pshuflw xm2, xm2, q1032 + vpblendd m2, m6, 0xfe + punpckhwd m6, m0 ; { top, cur } + punpcklwd m2, m0 +%if %3 + vpbroadcastd m0, [pw_23_22] +%elif %2 + vpbroadcastd m0, [pw_27_17_17_27] +%else + vpbroadcastd m0, [r14] +%endif + pmaddwd m6, m0 + pmaddwd m2, m0 +%if %1 + paddd m6, m1 + paddd m2, m1 +%else + paddd m6, m14 + paddd m2, m14 +%endif + psrad m6, 5 + psrad m2, 5 + packssdw m2, m6 + +%if %3 + pmaxsw m2, m8 + pminsw m2, m9 +%else +%if %2 + punpckhwd m6, m3, m7 + punpcklwd m3, m7 ; { cur, top } +%else + punpckhwd m6, m7, m3 + punpcklwd m3, m7, m3 ; { top, cur } +%endif + REPX {pmaddwd x, m0}, m6, m3 +%if %1 + REPX {paddd x, m1}, m6, m3 +%else + REPX {paddd x, m14}, m6, m3 +%endif + REPX {psrad x, 5}, m6, m3 + packssdw m3, m6 + pmaxsw m2, m8 + pmaxsw m3, m8 + pminsw m2, m9 + pminsw m3, m9 +%endif + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m4, m11 + pmaddubsw m5, m11 + paddw m4, m4 + paddw m5, m5 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + + ; dst = clip_pixel(src, noise) + paddw m0, m2, [srcq] +%if %2 + paddw m1, m3, [srcq+strideq] +%else + paddw m1, m3, [srcq+32] +%endif + pmaxsw m0, m12 + pmaxsw m1, m12 + pminsw m0, m13 + pminsw m1, m13 + mova [dstq], m0 +%if %2 + mova [dstq+strideq], m1 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + mova [dstq+32], m1 + add srcq, strideq + add dstq, strideq + add lumaq, r10mp +%endif + add grain_lutq, 82*(2<<%2) +%if %2 + sub hb, 2 + jg %%loop_y_h_overlap +%else + dec hb + jle %%end_y_hv_overlap + add hd, 0x80000000 + jc %%loop_y_h_overlap + add r14, 4 + jmp %%loop_y_hv_overlap +%endif +%%end_y_hv_overlap: + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + jmp %%loop_x_hv_overlap +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 +.end: + RET +%endmacro + +GEN_GRAIN_UV_FN 420, 1, 1 +FGUV_FN 420, 1, 1 +GEN_GRAIN_UV_FN 422, 1, 0 +FGUV_FN 422, 1, 0 +GEN_GRAIN_UV_FN 444, 0, 0 +FGUV_FN 444, 0, 0 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,932 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 +pb_0to63: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + db 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + db 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 + db 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 +scale_mask: db -1, -1, 0, -1, -1, -1, 4, -1, -1, -1, 8, -1, -1, -1, 12, -1 +scale_shift: dw 7, 7, 6, 6, 5, 5, 4, 4 +pw_27_17_17_27: dw 108, 68, 68, 108, 27, 17, 17, 27 +pw_23_22: dw 92, 88, 0, 128, 23, 22, 0, 32 +fg_min: times 2 dw 0 + times 2 dw 64 + times 2 dw 256 +fg_max: times 2 dw 1023 + times 2 dw 4095 + times 2 dw 960 + times 2 dw 3840 + times 2 dw 940 + times 2 dw 3760 +scale_rnd: dd 64 + dd 16 +uv_offset_mul: dd 256 + dd 1024 +pb_8_9_0_1: db 8, 9, 0, 1 + +SECTION .text + +INIT_ZMM avx512icl +cglobal fgy_32x32xn_16bpc, 6, 15, 21, dst, src, stride, fg_data, w, scaling, \ + grain_lut, offx, sby, see, offy, src_bak +%define base r11-fg_min + lea r11, [fg_min] + mov r6d, r9m ; bdmax + mov r9d, [fg_dataq+FGData.clip_to_restricted_range] + mov r7d, [fg_dataq+FGData.scaling_shift] + mov sbyd, sbym + vpbroadcastd m6, r9m + shr r6d, 11 ; is_12bpc + vbroadcasti32x4 m7, [base+scale_mask] + shlx r10d, r9d, r6d + vpbroadcastd m10, [base+scale_shift+r7*4-32] + lea r9d, [r6+r9*4] + vpbroadcastd m8, [base+fg_min+r10*4] + kxnorw k1, k1, k1 ; 0xffff + vpbroadcastd m9, [base+fg_max+r9*4] + mov r12, 0xeeeeeeeeeeeeeeee + vpbroadcastd m19, [base+scale_rnd+r6*4] + kshiftrb k2, k1, 4 ; 0xf + vpbroadcastq xm20, [base+pw_27_17_17_27+r6*8] + kmovq k3, r12 + vpbroadcastd m11, [base+scale_shift+r6*8+4] + test sbyd, sbyd + setnz r7b + vpbroadcastd m12, [base+pw_27_17_17_27+r6*8+0] + vpbroadcastd m13, [base+pw_27_17_17_27+r6*8+4] + test r7b, [fg_dataq+FGData.overlap_flag] + jnz .v_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + lea src_bakq, [srcq+wq*2] + neg wq + sub dstq, srcq + +.loop_x: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, h, \ + sby, see, offxy, src_bak + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y: + movu m4, [grain_lutq+offxyq*2+82*0] + movu m5, [grain_lutq+offxyq*2+82*2] + call .add_noise + sub hb, 2 + jg .loop_y + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + cmp byte [fg_dataq+FGData.overlap_flag], 0 + je .loop_x + test sbyd, sbyd + jnz .hv_overlap + + ; horizontal overlap (without vertical overlap) +.loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, offx, \ + sby, see, offy, src_bak, left_offxy + + lea left_offxyd, [offyq+73] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, h, \ + sby, see, offxy, src_bak, left_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y_h_overlap: + movu m4, [grain_lutq+offxyq*2+82*0] + movu m5, [grain_lutq+offxyq*2+82*2] + movd xm17, [grain_lutq+left_offxyq*2-82*1] + pinsrd xm17, [grain_lutq+left_offxyq*2+82*1], 1 + punpckldq xm16, xm4, xm5 + punpcklwd xm17, xm16 + mova xm16, xm19 + vpdpwssd xm16, xm20, xm17 + psrad xm16, 1 + packssdw xm16, xm16 + vpsravw xm16, xm11 + vmovdqu8 m4{k2}, m16 + vpalignr m5{k2}, m16, m16, 4 + call .add_noise + sub hb, 2 + jg .loop_y_h_overlap + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + test sbyd, sbyd + jnz .hv_overlap + jmp .loop_x_h_overlap + +.v_overlap: + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + lea src_bakq, [srcq+wq*2] + neg wq + sub dstq, srcq + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, offx, \ + sby, see, offy, src_bak, _, top_offxy + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, h, \ + sby, see, offxy, src_bak, _, top_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + + movu m16, [grain_lutq+offxyq*2+82*0] + movu m0, [grain_lutq+top_offxyq*2+82*0] + movu m17, [grain_lutq+offxyq*2+82*2] + movu m1, [grain_lutq+top_offxyq*2+82*2] + punpckhwd m4, m0, m16 + punpcklwd m0, m16 + punpckhwd m5, m1, m17 + punpcklwd m1, m17 + call .add_noise_v + sub hb, 2 + jg .loop_y + add wq, 32 + jge .end + lea srcq, [src_bakq+wq*2] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump back + ; to .v_overlap, and instead always fall-through to .hv_overlap +.hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, offx, \ + sby, see, offy, src_bak, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyd, [top_offxyq+73] + lea left_offxyd, [offyq+73] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, h, \ + sby, see, offxy, src_bak, left_offxy, top_offxy, topleft_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + + movu m5, [grain_lutq+offxyq*2+82*0] + movu m0, [grain_lutq+top_offxyq*2+82*0] + movd xm17, [grain_lutq+left_offxyq*2-82*1] + pinsrd xm17, [grain_lutq+topleft_offxyq*2-82*1], 1 + movu m2, [grain_lutq+offxyq*2+82*2] + movu m1, [grain_lutq+top_offxyq*2+82*2] + movd xm18, [grain_lutq+left_offxyq*2+82*1] + pinsrd xm18, [grain_lutq+topleft_offxyq*2+82*1], 1 + punpckldq xm16, xm5, xm0 + punpcklwd xm17, xm16 + mova xm16, xm19 + vpdpwssd xm16, xm20, xm17 + punpckldq xm17, xm2, xm1 + punpcklwd xm18, xm17 + mova xm17, xm19 + vpdpwssd xm17, xm20, xm18 + punpckhwd m4, m0, m5 + punpcklwd m0, m5 + punpckhwd m5, m1, m2 + punpcklwd m1, m2 + psrad xm16, 1 + psrad xm17, 1 + packssdw xm16, xm17 + vpsravw xm16, xm11 + vpshuflw m0{k2}, m16, q1302 + punpckhqdq xm16, xm16 + vpshuflw m1{k2}, m16, q1302 + call .add_noise_v + sub hb, 2 + jg .loop_y_h_overlap + add wq, 32 + lea srcq, [src_bakq+wq*2] + jl .hv_overlap +.end: + RET +ALIGN function_align +.add_noise_v: + mova m2, m19 + vpdpwssd m2, m12, m4 + mova m3, m19 + vpdpwssd m3, m13, m5 + mova m4, m19 + vpdpwssd m4, m12, m0 + mova m5, m19 + vpdpwssd m5, m13, m1 + REPX {psrad x, 1}, m2, m3, m4, m5 + packssdw m4, m2 + packssdw m5, m3 + vpsravw m4, m11 + vpsravw m5, m11 +.add_noise: + mova m0, [srcq+strideq*0] + mova m1, [srcq+strideq*1] + kmovw k4, k1 + pand m16, m6, m0 + psrld m3, m0, 16 + vpgatherdd m2{k4}, [scalingq+m16] + vpcmpud k4, m3, m6, 2 ; px <= bdmax + vpgatherdd m16{k4}, [scalingq+m3] + kmovw k4, k1 + pand m17, m6, m1 + vpgatherdd m3{k4}, [scalingq+m17] + vpshufb m2{k3}, m16, m7 + psrld m16, m1, 16 + vpcmpud k4, m16, m6, 2 + vpgatherdd m17{k4}, [scalingq+m16] + vpshufb m3{k3}, m17, m7 + vpsllvw m2, m10 + vpsllvw m3, m10 + pmulhrsw m4, m2 + pmulhrsw m5, m3 + add grain_lutq, 82*4 + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m8 + pmaxsw m1, m8 + pminsw m0, m9 + pminsw m1, m9 + mova [dstq+srcq], m0 + add srcq, strideq + mova [dstq+srcq], m1 + add srcq, strideq + ret + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +cglobal fguv_32x32xn_i%1_16bpc, 6, 15, 22, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, luma, lstride, uv_pl, is_id +%define base r12-fg_min + lea r12, [fg_min] + mov r9d, r13m ; bdmax + mov r7d, [fg_dataq+FGData.scaling_shift] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] + mov r11d, is_idm + kxnorw k1, k1, k1 ; 0xffff + vpbroadcastd m5, r13m + mov r13, 0xeeeeeeeeeeeeeeee + vbroadcasti32x4 m6, [base+scale_mask] + shr r9d, 11 ; is_12bpc + vpbroadcastd m7, [base+scale_shift+r7*4-32] + shlx r10d, r6d, r9d + mov sbyd, sbym + shlx r6d, r6d, r11d + vpbroadcastd m8, [base+fg_min+r10*4] + lea r6d, [r9+r6*2] + vpbroadcastd m9, [base+fg_max+r6*4] + kmovq k2, r13 + vpbroadcastd m20, [base+scale_rnd+r9*4] + packssdw m4, m5, m5 + vpbroadcastd m21, [base+scale_shift+r9*8+4] +%if %2 + mova m12, [base+pb_0to63] ; pw_even + mov r13d, 0x0101 + vpbroadcastq m10, [base+pw_23_22+r9*8] + kmovw k3, r13d +%if %3 + pshufd m11, m10, q0000 +%else + vpbroadcastd ym16, [base+pw_27_17_17_27+r9*8+0] + vpbroadcastd m11, [base+pw_27_17_17_27+r9*8+4] + vmovdqu16 m11{k1}, m16 +%endif + psrlw m13, m12, 8 ; pw_odd +%else + vpbroadcastq m10, [base+pw_27_17_17_27+r9*8] + kshiftrb k3, k1, 7 ; 0x01 + kshiftrb k4, k1, 4 ; 0x0f + pshufd m11, m10, q0000 +%endif + mov lstrideq, r10mp + test sbyd, sbyd + setnz r7b + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_hor, ss_ver + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + _, sby, see, lstride + +%if %1 + mov r6d, r11m + vpbroadcastd m0, [base+uv_offset_mul+r9*4] + vpbroadcastd m1, [base+pb_8_9_0_1] + vpbroadcastd m14, [fg_dataq+FGData.uv_offset+r6*4] + vbroadcasti32x4 m15, [fg_dataq+FGData.uv_mult+r6*4] + pmaddwd m14, m0 + pshufb m15, m1 ; { uv_luma_mult, uv_mult } +%endif + test r7b, [fg_dataq+FGData.overlap_flag] + jnz %%v_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, lstride, luma + + mov lumaq, r9mp + lea r12, [srcq+wq*2] + lea r13, [dstq+wq*2] + lea r14, [lumaq+wq*(2<<%2)] + mov r9mp, r12 + mov r10mp, r13 + mov r11mp, r14 + neg wq + +%%loop_x: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+(3+(6>>%2))] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, lstride, luma + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y: +%if %2 + movu ym18, [grain_lutq+offxyq*2+82*0] + vinserti32x8 m18, [grain_lutq+offxyq*2+82*2], 1 + movu ym19, [grain_lutq+offxyq*2+82*4] + vinserti32x8 m19, [grain_lutq+offxyq*2+82*6], 1 +%else + movu m18, [grain_lutq+offxyq*2+82*0] + movu m19, [grain_lutq+offxyq*2+82*2] +%endif + call %%add_noise + sub hb, 2<<%2 + jg %%loop_y + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r10mp + mov lumaq, r11mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + cmp byte [fg_dataq+FGData.overlap_flag], 0 + je %%loop_x + cmp dword r8m, 0 ; sby + jne %%hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, lstride, luma, left_offxy + + lea left_offxyd, [offyq+(32>>%2)] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, lstride, luma, left_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y_h_overlap: +%if %2 + movu ym18, [grain_lutq+offxyq*2+82*0] + vinserti32x8 m18, [grain_lutq+offxyq*2+82*2], 1 + movu ym19, [grain_lutq+offxyq*2+82*4] + vinserti32x8 m19, [grain_lutq+offxyq*2+82*6], 1 + movd xm16, [grain_lutq+left_offxyq*2+82*0] + vinserti32x4 m16, [grain_lutq+left_offxyq*2+82*2], 2 + movd xm17, [grain_lutq+left_offxyq*2+82*4] + vinserti32x4 m17, [grain_lutq+left_offxyq*2+82*6], 2 + punpckldq m16, m17 + punpckldq m17, m18, m19 + punpcklwd m16, m17 + mova m17, m20 + vpdpwssd m17, m16, m10 + psrad m17, 1 + packssdw m17, m17 + vpsravw m17, m21 +%else + movu m18, [grain_lutq+offxyq*2+82*0] + movu m19, [grain_lutq+offxyq*2+82*2] + movd xm16, [grain_lutq+left_offxyq*2+82*0] + pinsrd xm16, [grain_lutq+left_offxyq*2+82*2], 1 + punpckldq xm17, xm18, xm19 + punpcklwd xm16, xm17 + mova xm17, xm20 + vpdpwssd xm17, xm16, xm10 + psrad xm17, 1 + packssdw xm17, xm17 + vpsravw xm17, xm21 +%endif + vmovdqa32 m18{k3}, m17 + vpshufd m19{k3}, m17, q0321 + call %%add_noise + sub hb, 2<<%2 + jg %%loop_y_h_overlap + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r10mp + mov lumaq, r11mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + cmp dword r8m, 0 ; sby + jne %%hv_overlap + jmp %%loop_x_h_overlap + +%%v_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + _, sby, see, lstride + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, lstride, luma, _, top_offxy + + mov lumaq, r9mp + lea r12, [srcq+wq*2] + lea r13, [dstq+wq*2] + lea r14, [lumaq+wq*(2<<%2)] + mov r9mp, r12 + mov r10mp, r13 + mov r11mp, r14 + neg wq + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, lstride, luma, _, top_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + +%if %3 + movu ym16, [grain_lutq+offxyq*2+82*0] + movu ym1, [grain_lutq+top_offxyq*2+82*0] + vbroadcasti32x8 m18, [grain_lutq+offxyq*2+82*2] + movu ym19, [grain_lutq+offxyq*2+82*4] + vinserti32x8 m19, [grain_lutq+offxyq*2+82*6], 1 + punpcklwd ym17, ym1, ym16 + punpckhwd ym1, ym16 +%elif %2 + movu ym18, [grain_lutq+offxyq*2+82*0] + vinserti32x8 m18, [grain_lutq+offxyq*2+82*2], 1 + movu ym17, [grain_lutq+top_offxyq*2+82*0] + vinserti32x8 m17, [grain_lutq+top_offxyq*2+82*2], 1 + movu ym19, [grain_lutq+offxyq*2+82*4] + vinserti32x8 m19, [grain_lutq+offxyq*2+82*6], 1 + punpcklwd m16, m17, m18 + punpckhwd m17, m18 +%else + movu m18, [grain_lutq+offxyq*2+82*0] + movu m19, [grain_lutq+top_offxyq*2+82*0] + movu m2, [grain_lutq+offxyq*2+82*2] + movu m16, [grain_lutq+top_offxyq*2+82*2] + punpckhwd m1, m19, m18 + punpcklwd m19, m18 + punpckhwd m18, m2, m16 + punpcklwd m2, m16 +%endif + call %%add_noise_v + sub hb, 2<<%2 + jg %%loop_y + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r10mp + mov lumaq, r11mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump back + ; to %%v_overlap, and instead always fall-through to %%hv_overlap +%%hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, lstride, luma, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyq, [top_offxyq+(32>>%2)] + lea left_offxyq, [offyq+(32>>%2)] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, lstride, luma, left_offxy, top_offxy, topleft_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + + ; grain = grain_lut[offy+y][offx+x] +%if %2 + movd xm16, [grain_lutq+left_offxyq*2+82*0] + vinserti32x4 m16, [grain_lutq+left_offxyq*2+82*2], 2 + movd xm17, [grain_lutq+left_offxyq*2+82*4] + vinserti32x4 m17, [grain_lutq+left_offxyq*2+82*6], 2 + movu ym18, [grain_lutq+offxyq*2+82*0] + vinserti32x8 m18, [grain_lutq+offxyq*2+82*2], 1 + movu ym19, [grain_lutq+offxyq*2+82*4] + vinserti32x8 m19, [grain_lutq+offxyq*2+82*6], 1 + punpckldq m16, m17 + punpckldq m17, m18, m19 + punpcklwd m16, m17 + movu ym1, [grain_lutq+top_offxyq*2+82*0] + movd xm17, [grain_lutq+topleft_offxyq*2+82*0] + mova m0, m20 + vpdpwssd m0, m16, m10 +%if %3 + punpcklwd xm17, xm1 + mova xm16, xm20 + vpdpwssd xm16, xm17, xm10 + psrad xm16, 1 +%else + vinserti32x8 m1, [grain_lutq+top_offxyq*2+82*2], 1 + vinserti32x4 m17, [grain_lutq+topleft_offxyq*2+82*2], 2 + punpcklwd m17, m1 + mova m16, m20 + vpdpwssd m16, m17, m10 + psrad m16, 1 +%endif + psrad m0, 1 + packssdw m0, m16 + vpsravw m0, m21 + vmovdqa32 m18{k3}, m0 + vpshufd m19{k3}, m0, q0321 +%if %3 + vpunpckhdq ym1{k3}, ym0, ym0 + punpcklwd ym17, ym1, ym18 + punpckhwd ym1, ym18 +%else + vpunpckhdq m1{k3}, m0, m0 + punpcklwd m16, m1, m18 + punpckhwd m17, m1, m18 +%endif +%else + movu m18, [grain_lutq+offxyq*2+82*0] + movu m19, [grain_lutq+top_offxyq*2+82*0] + movd xm17, [grain_lutq+left_offxyq*2+82*0] + pinsrd xm17, [grain_lutq+topleft_offxyq*2+82*0], 1 + punpckldq xm16, xm18, xm19 + punpcklwd xm17, xm16 + movu m2, [grain_lutq+offxyq*2+82*2] + movu m0, [grain_lutq+top_offxyq*2+82*2] + movd xm16, [grain_lutq+left_offxyq*2+82*2] + pinsrd xm16, [grain_lutq+topleft_offxyq*2+82*2], 1 + punpckldq xm1, xm2, xm0 + punpcklwd xm1, xm16, xm1 + mova xm16, xm20 + vpdpwssd xm16, xm17, xm10 + mova xm17, xm20 + vpdpwssd xm17, xm1, xm10 + punpckhwd m1, m19, m18 + punpcklwd m19, m18 + punpckhwd m18, m2, m0 + punpcklwd m2, m0 + psrad xm16, 1 + psrad xm17, 1 + packssdw xm16, xm17 + vpsravw xm16, xm21 + vpshuflw m19{k4}, m16, q1302 + punpckhqdq xm16, xm16 + vpshuflw m2{k4}, m16, q3120 +%endif + call %%add_noise_v + sub hb, 2<<%2 + jg %%loop_y_h_overlap + add wq, 32>>%2 + jge .end + mov srcq, r9mp + mov dstq, r10mp + mov lumaq, r11mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] + jmp %%hv_overlap + +ALIGN function_align +%%add_noise_v: +%if %3 + mova ym16, ym20 + vpdpwssd ym16, ym17, ym11 + mova ym17, ym20 + vpdpwssd ym17, ym1, ym11 + psrad ym16, 1 + psrad ym17, 1 + packssdw ym16, ym17 + vpsravw m18{k1}, m16, m21 +%elif %2 + mova m18, m20 + vpdpwssd m18, m16, m11 + mova m16, m20 + vpdpwssd m16, m17, m11 + psrad m18, 1 + psrad m16, 1 + packssdw m18, m16 + vpsravw m18, m21 +%else + mova m16, m20 + vpdpwssd m16, m1, m11 + mova m17, m20 + vpdpwssd m17, m18, m11 + mova m18, m20 + vpdpwssd m18, m19, m11 + mova m19, m20 + vpdpwssd m19, m2, m11 + REPX {psrad x, 1}, m16, m17, m18, m19 + packssdw m18, m16 + packssdw m19, m17 + vpsravw m18, m21 + vpsravw m19, m21 +%endif +%%add_noise: +%if %2 + mova m2, [lumaq+lstrideq*(0<<%3)] + mova m0, [lumaq+lstrideq*(1<<%3)] + lea lumaq, [lumaq+lstrideq*(2<<%3)] + mova m3, [lumaq+lstrideq*(0<<%3)] + mova m1, [lumaq+lstrideq*(1<<%3)] + mova m16, m12 + vpermi2w m16, m2, m0 + vpermt2w m2, m13, m0 + mova m17, m12 + vpermi2w m17, m3, m1 + vpermt2w m3, m13, m1 + pavgw m2, m16 + pavgw m3, m17 +%elif %1 + mova m2, [lumaq+lstrideq*0] + mova m3, [lumaq+lstrideq*1] +%endif +%if %2 + mova ym16, [srcq+strideq*0] + vinserti32x8 m16, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] +%else + mova m16, [srcq+strideq*0] +%endif +%if %1 + punpckhwd m17, m2, m16 + mova m0, m14 + vpdpwssd m0, m17, m15 + punpcklwd m17, m2, m16 + mova m2, m14 + vpdpwssd m2, m17, m15 +%endif +%if %2 + mova ym17, [srcq+strideq*0] + vinserti32x8 m17, [srcq+strideq*1], 1 +%else + mova m17, [srcq+strideq*1] +%endif +%if %1 + psrad m0, 6 + psrad m2, 6 + packusdw m2, m0 + punpckhwd m0, m3, m17 + mova m1, m14 + vpdpwssd m1, m15, m0 + punpcklwd m0, m3, m17 + mova m3, m14 + vpdpwssd m3, m15, m0 + psrad m1, 6 + psrad m3, 6 + packusdw m3, m1 + pminuw m2, m4 + pminuw m3, m4 + +.add_noise_main: + ; scaling[luma_src] + kmovw k5, k1 + pand m1, m5, m2 + vpgatherdd m0{k5}, [scalingq+m1] + kmovw k5, k1 + psrld m2, 16 + vpgatherdd m1{k5}, [scalingq+m2] + vpshufb m0{k2}, m1, m6 + kmovw k5, k1 + psrld m1, m3, 16 + vpgatherdd m2{k5}, [scalingq+m1] + kmovw k5, k1 + pand m3, m5 + vpgatherdd m1{k5}, [scalingq+m3] + vpshufb m1{k2}, m2, m6 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + vpsllvw m0, m7 + vpsllvw m1, m7 + pmulhrsw m18, m0 + pmulhrsw m19, m1 + add grain_lutq, 82*(4<<%2) + lea lumaq, [lumaq+lstrideq*(2<<%3)] + lea srcq, [srcq+strideq*2] + paddw m16, m18 + paddw m17, m19 + pmaxsw m16, m8 + pmaxsw m17, m8 + pminsw m16, m9 + pminsw m17, m9 +%if %2 + mova [dstq+strideq*0], ym16 + vextracti32x8 [dstq+strideq*1], m16, 1 + lea dstq, [dstq+strideq*2] + mova [dstq+strideq*0], ym17 + vextracti32x8 [dstq+strideq*1], m17, 1 +%else + mova [dstq+strideq*0], m16 + mova [dstq+strideq*1], m17 +%endif + lea dstq, [dstq+strideq*2] + ret +%else +%if %2 + pand m2, m4 + pand m3, m4 +%else + pand m2, m4, [lumaq+lstrideq*0] + pand m3, m4, [lumaq+lstrideq*1] +%endif + jmp .add_noise_main +%endif +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 +.end: + RET +%endmacro + +FGUV_FN 420, 1, 1 +FGUV_FN 422, 1, 0 +FGUV_FN 444, 0, 0 + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3421 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +SECTION_RODATA 16 +pd_16: times 4 dd 16 +pw_1: times 8 dw 1 +pw_16384: times 8 dw 16384 +pw_8192: times 8 dw 8192 +pw_23_22: dw 23, 22 + times 3 dw 0, 32 +pb_mask: db 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0 +pw_27_17_17_27: dw 27, 17, 17, 27 + times 2 dw 0, 32 +rnd_next_upperbit_mask: dw 0x100B, 0x2016, 0x402C, 0x8058 +pw_seed_xor: times 2 dw 0xb524 + times 2 dw 0x49d8 +pb_1: times 4 db 1 +hmul_bits: dw 32768, 16384, 8192, 4096 +round: dw 2048, 1024, 512 +mul_bits: dw 256, 128, 64, 32, 16 +round_vals: dw 32, 64, 128, 256, 512, 1024 +max: dw 256*4-1, 240*4, 235*4, 256*16-1, 240*16, 235*16 +min: dw 0, 16*4, 16*16 +; these two should be next to each other +pw_4: times 2 dw 4 +pw_16: times 2 dw 16 + +%macro JMP_TABLE 1-* + %xdefine %1_table %%table + %xdefine %%base %1_table + %xdefine %%prefix mangle(private_prefix %+ _%1) + %%table: + %rep %0 - 1 + dd %%prefix %+ .ar%2 - %%base + %rotate 1 + %endrep +%endmacro + +JMP_TABLE generate_grain_y_16bpc_ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_420_16bpc_ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_422_16bpc_ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_444_16bpc_ssse3, 0, 1, 2, 3 + +SECTION .text + +%if ARCH_X86_32 +%undef base +%define PIC_ptr(a) base+a +%else +%define PIC_ptr(a) a +%endif + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +%macro vpgatherdw 5-8 8, 1 ; dst, src, base, tmp_gpr[x2], cnt, stride, tmp_xmm_reg +%assign %%idx 0 +%define %%tmp %2 +%if %0 == 8 +%define %%tmp %8 +%endif +%rep (%6/2) +%if %%idx == 0 + movd %5 %+ d, %2 + pshuflw %%tmp, %2, q3232 +%else + movd %5 %+ d, %%tmp +%if %6 == 8 +%if %%idx == 2 + punpckhqdq %%tmp, %%tmp +%elif %%idx == 4 + psrlq %%tmp, 32 +%endif +%endif +%endif + movzx %4 %+ d, %5 %+ w + shr %5 %+ d, 16 + +%if %%idx == 0 + movd %1, [%3+%4*%7] +%else + pinsrw %1, [%3+%4*%7], %%idx + 0 +%endif + pinsrw %1, [%3+%5*%7], %%idx + 1 +%assign %%idx %%idx+2 +%endrep +%endmacro + +%macro SPLATD 2 ; dst, src +%ifnidn %1, %2 + movd %1, %2 +%endif + pshufd %1, %1, q0000 +%endmacro + +%macro SPLATW 2 ; dst, src +%ifnidn %1, %2 + movd %1, %2 +%endif + pshuflw %1, %1, q0000 + punpcklqdq %1, %1 +%endmacro + + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal generate_grain_y_16bpc, 3, 8, 16, buf, fg_data, bdmax + lea r4, [pb_mask] +%define base r4-pb_mask +%else +cglobal generate_grain_y_16bpc, 3, 6, 8, buf, fg_data, bdmax + LEA r4, $$ +%define base r4-$$ +%endif + movq m1, [base+rnd_next_upperbit_mask] + movq m4, [base+mul_bits] + movq m7, [base+hmul_bits] + mov r3d, [fg_dataq+FGData.grain_scale_shift] + lea r5d, [bdmaxq+1] + shr r5d, 11 ; 0 for 10bpc, 2 for 12bpc + sub r3, r5 + SPLATW m6, [base+round+r3*2-2] + mova m5, [base+pb_mask] + SPLATW m0, [fg_dataq+FGData.seed] + mov r3, -73*82*2 + sub bufq, r3 +%if ARCH_X86_64 + lea r6, [gaussian_sequence] +%endif +.loop: + pand m2, m0, m1 + psrlw m3, m2, 10 + por m2, m3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw m2, m4 ; bits 0x0f00 are set + pshufb m3, m5, m2 ; set 15th bit for next 4 seeds + psllq m2, m3, 30 + por m2, m3 + psllq m3, m2, 15 + por m2, m3 ; aggregate each bit into next seed's high bit + pmulhuw m3, m0, m7 + por m2, m3 ; 4 next output seeds + pshuflw m0, m2, q3333 + psrlw m2, 5 +%if ARCH_X86_64 + vpgatherdw m3, m2, r6, r5, r7, 4, 2 +%else + vpgatherdw m3, m2, base+gaussian_sequence, r5, r2, 4, 2 +%endif + paddw m3, m3 ; otherwise bpc=12 w/ grain_scale_shift=0 + ; shifts by 0, which pmulhrsw does not support + pmulhrsw m3, m6 + movq [bufq+r3], m3 + add r3, 4*2 + jl .loop + + ; auto-regression code + movsxd r3, [fg_dataq+FGData.ar_coeff_lag] + movsxd r3, [base+generate_grain_y_16bpc_ssse3_table+r3*4] + lea r3, [r3+base+generate_grain_y_16bpc_ssse3_table] + jmp r3 + +.ar1: +%if WIN64 + DEFINE_ARGS shift, fg_data, max, buf, val3, min, cf3, x, val0 + lea bufq, [r0-2*(82*73-(82*3+79))] + PUSH r8 +%else +%if ARCH_X86_64 + DEFINE_ARGS buf, fg_data, max, shift, val3, min, cf3, x, val0 +%else ; x86-32 + DEFINE_ARGS buf, fg_data, min, val3, x, cf3, val0 + PUSH r6 +%define shiftd r1d +%endif + sub bufq, 2*(82*73-(82*3+79)) +%endif + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_y+3] + movd m4, [fg_dataq+FGData.ar_coeffs_y] + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] +%if WIN64 + DEFINE_ARGS shift, h, max, buf, val3, min, cf3, x, val0 +%elif ARCH_X86_64 + DEFINE_ARGS buf, h, max, shift, val3, min, cf3, x, val0 +%else ; x86-32 +%undef shiftd + DEFINE_ARGS buf, shift, min, val3, x, cf3, val0 +%define hd dword r0m +%define maxd dword minm +%endif +%if cpuflag(sse4) + pmovsxbw m4, m4 +%else + pxor m3, m3 + pcmpgtb m3, m4 + punpcklbw m4, m3 +%endif + pinsrw m4, [base+pw_1], 3 + pshufd m5, m4, q1111 + pshufd m4, m4, q0000 + SPLATW m3, [base+round_vals+shiftq*2-12] ; rnd + mov hd, 70 + sar maxd, 1 + mov mind, maxd + xor mind, -1 +.y_loop_ar1: + mov xq, -76 + movsx val3d, word [bufq+xq*2-2] +.x_loop_ar1: + movu m0, [bufq+xq*2-82*2-2] ; top/left + psrldq m2, m0, 2 ; top + psrldq m1, m0, 4 ; top/right + punpcklwd m0, m2 + punpcklwd m1, m3 + pmaddwd m0, m4 + pmaddwd m1, m5 + paddd m0, m1 +.x_loop_ar1_inner: + movd val0d, m0 + psrldq m0, 4 + imul val3d, cf3d + add val3d, val0d + sar val3d, shiftb + movsx val0d, word [bufq+xq*2] + add val3d, val0d + cmp val3d, maxd + cmovg val3d, maxd + cmp val3d, mind + cmovl val3d, mind + mov word [bufq+xq*2], val3w + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xq, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 + +.x_loop_ar1_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar1 +%if WIN64 + POP r8 +%elif ARCH_X86_32 + POP r6 +%undef maxd +%undef hd +%endif +.ar0: + RET + +.ar2: +%if ARCH_X86_32 +%assign stack_offset_old stack_offset + ALLOC_STACK -16*8 +%endif + DEFINE_ARGS buf, fg_data, bdmax, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m0, [base+round_vals-12+shiftq*2] + pshuflw m0, m0, q0000 + movu m6, [fg_dataq+FGData.ar_coeffs_y+0] ; cf0-11 + pxor m2, m2 + punpcklwd m0, m2 + pcmpgtb m2, m6 + punpckhbw m3, m6, m2 + punpcklbw m6, m2 + pshufd m2, m6, q3333 + pshufd m1, m6, q2222 + pshufd m7, m6, q1111 + pshufd m6, m6, q0000 + pshufd m4, m3, q1111 + pshufd m3, m3, q0000 +%if ARCH_X86_64 + SWAP 0, 12 + SWAP 1, 8 + SWAP 2, 9 + SWAP 3, 10 + SWAP 4, 11 +%else +%define m12 [rsp+0*16] +%define m8 [rsp+1*16] +%define m9 [rsp+2*16] +%define m10 [rsp+3*16] +%define m11 [rsp+4*16] + mova m12, m0 + mova m8, m1 + mova m9, m2 + mova m10, m3 + mova m11, m4 + mov bdmaxd, bdmaxm +%endif + sar bdmaxd, 1 + SPLATW m0, bdmaxd ; max_grain + pcmpeqw m1, m1 +%if !cpuflag(sse4) + pcmpeqw m2, m2 + psrldq m2, 14 + pslldq m2, 2 + pxor m2, m1 +%endif + pxor m1, m0 ; min_grain +%if ARCH_X86_64 + SWAP 0, 13 + SWAP 1, 14 + SWAP 2, 15 +%else +%define m13 [rsp+5*16] +%define m14 [rsp+6*16] + mova m13, m0 + mova m14, m1 +%if !cpuflag(sse4) +%define m15 [rsp+7*16] + mova m15, m2 +%endif +%endif + sub bufq, 2*(82*73-(82*3+79)) + DEFINE_ARGS buf, fg_data, h, x + mov hd, 70 +.y_loop_ar2: + mov xq, -76 + +.x_loop_ar2: + movu m0, [bufq+xq*2-82*4-4] ; y=-2,x=[-2,+5] + movu m1, [bufq+xq*2-82*2-4] ; y=-1,x=[-2,+5] + psrldq m2, m0, 2 + psrldq m3, m0, 4 + psrldq m4, m0, 6 + psrldq m5, m0, 8 + punpcklwd m0, m2 + punpcklwd m3, m4 + punpcklwd m5, m1 + psrldq m2, m1, 2 + psrldq m4, m1, 4 + punpcklwd m2, m4 + psrldq m4, m1, 6 + psrldq m1, 8 + punpcklwd m4, m1 + pmaddwd m0, m6 + pmaddwd m3, m7 + pmaddwd m5, m8 + pmaddwd m2, m9 + pmaddwd m4, m10 + paddd m0, m3 + paddd m5, m2 + paddd m0, m4 + paddd m0, m5 ; accumulated top 2 rows + paddd m0, m12 + + movu m1, [bufq+xq*2-4] ; y=0,x=[-2,+5] + pshufd m4, m1, q3321 + pxor m2, m2 + pcmpgtw m2, m4 + punpcklwd m4, m2 ; in dwords, y=0,x=[0,3] +.x_loop_ar2_inner: + pmaddwd m2, m1, m11 + paddd m2, m0 + psrldq m0, 4 ; shift top to next pixel + psrad m2, [fg_dataq+FGData.ar_coeff_shift] + paddd m2, m4 + packssdw m2, m2 + pminsw m2, m13 + pmaxsw m2, m14 + psrldq m4, 4 + pslldq m2, 2 + psrldq m1, 2 +%if cpuflag(sse4) + pblendw m1, m2, 00000010b +%else + pand m1, m15 + pandn m3, m15, m2 + por m1, m3 +%endif + ; overwrite previous pixel, this should be ok + movd [bufq+xq*2-2], m1 + inc xq + jz .x_loop_ar2_end + test xq, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 + +.x_loop_ar2_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar2 +%if ARCH_X86_32 +%undef m8 +%undef m9 +%undef m10 +%undef m11 +%undef m12 +%undef m13 +%undef m14 +%undef m15 +%endif + RET + +.ar3: + DEFINE_ARGS buf, fg_data, bdmax, shift +%if WIN64 + mov r6, rsp + and rsp, ~15 + sub rsp, 64 + %define tmp rsp +%elif ARCH_X86_64 + %define tmp rsp+stack_offset-72 +%else +%assign stack_offset stack_offset_old + ALLOC_STACK -16*12 + %define tmp rsp + mov bdmaxd, bdmaxm +%endif + sar bdmaxd, 1 + SPLATW m7, bdmaxd ; max_grain + pcmpeqw m6, m6 +%if !cpuflag(sse4) + pcmpeqw m4, m4 + psrldq m4, 14 + pslldq m4, 4 + pxor m4, m6 +%endif + pxor m6, m7 ; min_grain + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + +%if ARCH_X86_64 + SWAP 6, 14 + SWAP 7, 15 +%else +%define m14 [rsp+10*16] +%define m15 [esp+11*16] + mova m14, m6 + mova m15, m7 +%endif + + ; build cf0-1 until 18-19 in m5-12 and r0/1 + pxor m1, m1 + movu m0, [fg_dataq+FGData.ar_coeffs_y+ 0] ; cf0-15 + pcmpgtb m1, m0 + punpckhbw m2, m0, m1 + punpcklbw m0, m1 + +%if cpuflag(sse4) + pshufd m4, m2, q3333 +%else + pshufd m5, m2, q3333 + mova [tmp+48], m5 +%endif + pshufd m3, m2, q2222 + pshufd m1, m2, q0000 + pshufd m2, m2, q1111 + pshufd m7, m0, q2222 + pshufd m6, m0, q1111 + pshufd m5, m0, q0000 + pshufd m0, m0, q3333 + +%if ARCH_X86_64 + SWAP 0, 8 + SWAP 1, 9 + SWAP 2, 10 + SWAP 3, 11 + SWAP 4, 12 +%else +%define m8 [rsp+4*16] +%define m9 [esp+5*16] +%define m10 [rsp+6*16] +%define m11 [esp+7*16] +%define m12 [rsp+8*16] + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 + mova m12, m4 +%endif + + ; build cf20,round in r2 + ; build cf21-23,round*2 in m13 + pxor m1, m1 + movq m0, [fg_dataq+FGData.ar_coeffs_y+16] ; cf16-23 + pcmpgtb m1, m0 + punpcklbw m0, m1 + pshufd m1, m0, q0000 + pshufd m2, m0, q1111 + mova [tmp+ 0], m1 + mova [tmp+16], m2 + psrldq m3, m0, 10 + pinsrw m3, [base+round_vals+shiftq*2-10], 3 + +%if ARCH_X86_64 + SWAP 3, 13 +%else +%define m13 [esp+9*16] + mova m13, m3 +%endif + + pinsrw m0, [base+round_vals+shiftq*2-12], 5 + pshufd m3, m0, q2222 + mova [tmp+32], m3 + + DEFINE_ARGS buf, fg_data, h, x + sub bufq, 2*(82*73-(82*3+79)) + mov hd, 70 +.y_loop_ar3: + mov xq, -76 + +.x_loop_ar3: + movu m0, [bufq+xq*2-82*6-6+ 0] ; y=-3,x=[-3,+4] + movd m1, [bufq+xq*2-82*6-6+16] ; y=-3,x=[+5,+6] + palignr m2, m1, m0, 2 ; y=-3,x=[-2,+5] + palignr m1, m1, m0, 12 ; y=-3,x=[+3,+6] + punpckhwd m3, m0, m2 ; y=-3,x=[+1/+2,+2/+3,+3/+4,+4/+5] + punpcklwd m0, m2 ; y=-3,x=[-3/-2,-2/-1,-1/+0,+0/+1] + shufps m2, m0, m3, q1032 ; y=-3,x=[-1/+0,+0/+1,+1/+2,+2/+3] + + pmaddwd m0, m5 + pmaddwd m2, m6 + pmaddwd m3, m7 + paddd m0, m2 + paddd m0, m3 + ; m0 = top line first 6 multiplied by cf, m1 = top line last entry + + movu m2, [bufq+xq*2-82*4-6+ 0] ; y=-2,x=[-3,+4] + movd m3, [bufq+xq*2-82*4-6+16] ; y=-2,x=[+5,+6] + punpcklwd m1, m2 ; y=-3/-2,x=[+3/-3,+4/-2,+5/-1,+6/+0] + palignr m4, m3, m2, 2 ; y=-3,x=[-2,+5] + palignr m3, m3, m2, 4 ; y=-3,x=[-1,+6] + punpckhwd m2, m4, m3 ; y=-2,x=[+2/+3,+3/+4,+4/+5,+5/+6] + punpcklwd m4, m3 ; y=-2,x=[-2/-1,-1/+0,+0/+1,+1/+2] + shufps m3, m4, m2, q1032 ; y=-2,x=[+0/+1,+1/+2,+2/+3,+3/+4] + + pmaddwd m1, m8 + pmaddwd m4, m9 + pmaddwd m3, m10 + pmaddwd m2, m11 + paddd m1, m4 + paddd m3, m2 + paddd m0, m1 + paddd m0, m3 + ; m0 = top 2 lines multiplied by cf + + movu m1, [bufq+xq*2-82*2-6+ 0] ; y=-1,x=[-3,+4] + movd m2, [bufq+xq*2-82*2-6+16] ; y=-1,x=[+5,+6] + palignr m3, m2, m1, 2 ; y=-1,x=[-2,+5] + palignr m2, m2, m1, 12 ; y=-1,x=[+3,+6] + punpckhwd m4, m1, m3 ; y=-1,x=[+1/+2,+2/+3,+3/+4,+4/+5] + punpcklwd m1, m3 ; y=-1,x=[-3/-2,-2/-1,-1/+0,+0/+1] + shufps m3, m1, m4, q1032 ; y=-1,x=[-1/+0,+0/+1,+1/+2,+2/+3] + punpcklwd m2, [base+pw_1] + +%if cpuflag(sse4) + pmaddwd m1, m12 +%else + pmaddwd m1, [tmp+48] +%endif + pmaddwd m3, [tmp+ 0] + pmaddwd m4, [tmp+16] + pmaddwd m2, [tmp+32] + paddd m1, m3 + paddd m4, m2 + paddd m0, m1 + paddd m0, m4 + ; m0 = top 3 lines multiplied by cf plus rounding for downshift + + movu m1, [bufq+xq*2-6] ; y=0,x=[-3,+4] +.x_loop_ar3_inner: + pmaddwd m2, m1, m13 + pshufd m3, m2, q1111 + paddd m2, m3 ; left+cur + paddd m2, m0 ; add top + psrldq m0, 4 + psrad m2, [fg_dataq+FGData.ar_coeff_shift] + packssdw m2, m2 + pminsw m2, m15 + pmaxsw m2, m14 + pslldq m2, 4 + psrldq m1, 2 +%if cpuflag(sse4) + pblendw m1, m2, 00000100b +%else + pand m1, m12 + pandn m3, m12, m2 + por m1, m3 +%endif + ; overwrite a couple of pixels, should be ok + movq [bufq+xq*2-4], m1 + inc xq + jz .x_loop_ar3_end + test xq, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 + +.x_loop_ar3_end: + add bufq, 82*2 + dec hd + jg .y_loop_ar3 +%if WIN64 + mov rsp, r6 +%elif ARCH_X86_32 +%undef m8 +%undef m9 +%undef m10 +%undef m11 +%undef m12 +%undef m13 +%undef m14 +%undef m15 +%endif + RET + +%macro generate_grain_uv_fn 3 ; ss_name, ss_x, ss_y +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal generate_grain_uv_%1_16bpc, 4, 11, 16, buf, bufy, fg_data, uv, bdmax, x, gaussian_reg, h, pic_reg +%define base r8-pb_mask + lea r8, [pb_mask] + movifnidn bdmaxd, bdmaxm + lea r6d, [bdmaxq+1] +%else +cglobal generate_grain_uv_%1_16bpc, 1, 7, 8, buf, x, pic_reg, fg_data, h +%define base r2-$$ + LEA r2, $$ + mov fg_dataq, r2m + mov r6d, r4m + inc r6d +%endif + movq m1, [base+rnd_next_upperbit_mask] + movq m4, [base+mul_bits] + movq m7, [base+hmul_bits] + mov r5d, [fg_dataq+FGData.grain_scale_shift] + shr r6d, 11 ; 0 for 10bpc, 2 for 12bpc + sub r5, r6 + SPLATW m6, [base+round+r5*2-2] + mova m5, [base+pb_mask] + SPLATW m0, [fg_dataq+FGData.seed] +%if ARCH_X86_64 + SPLATW m2, [base+pw_seed_xor+uvq*4] +%else + mov r5d, r3m + SPLATW m2, [base+pw_seed_xor+r5*4] +%endif + pxor m0, m2 +%if ARCH_X86_64 + lea r6, [gaussian_sequence] +%endif +%if %2 + mov hd, 73-35*%3 + add bufq, 44*2 +.loop_y: + mov xq, -44 +%else + mov xq, -82*73 + add bufq, 82*73*2 +%endif +.loop_x: + pand m2, m0, m1 + psrlw m3, m2, 10 + por m2, m3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw m2, m4 ; bits 0x0f00 are set + pshufb m3, m5, m2 ; set 15th bit for next 4 seeds + psllq m2, m3, 30 + por m2, m3 + psllq m3, m2, 15 + por m2, m3 ; aggregate each bit into next seed's high bit + pmulhuw m3, m0, m7 + por m2, m3 ; 4 next output seeds + pshuflw m0, m2, q3333 + psrlw m2, 5 +%if ARCH_X86_64 + vpgatherdw m3, m2, r6, r9, r10, 4, 2 +%else + vpgatherdw m3, m2, base+gaussian_sequence, r5, r6, 4, 2 +%endif + paddw m3, m3 ; otherwise bpc=12 w/ grain_scale_shift=0 + ; shifts by 0, which pmulhrsw does not support + pmulhrsw m3, m6 + movq [bufq+xq*2], m3 + add xq, 4 + jl .loop_x +%if %2 + add bufq, 82*2 + dec hd + jg .loop_y +%endif + + ; auto-regression code + movsxd r5, [fg_dataq+FGData.ar_coeff_lag] + movsxd r5, [base+generate_grain_uv_%1_16bpc_ssse3_table+r5*4] + lea r5, [r5+base+generate_grain_uv_%1_16bpc_ssse3_table] + jmp r5 + +.ar0: +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift +%else + DEFINE_ARGS buf, bufy, pic_reg, fg_data, uv, shift +%assign stack_offset_old stack_offset + ALLOC_STACK -16*2 + mov bufyq, r1m + mov uvd, r3m +%endif + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m4, [fg_dataq+FGData.ar_coeffs_uv+uvq] + SPLATW m3, [base+hmul_bits+shiftq*2-10] +%if ARCH_X86_64 + sar bdmaxd, 1 + SPLATW m1, bdmaxd ; max_gain +%else + SPLATW m1, r4m + psraw m1, 1 +%endif + pcmpeqw m7, m7 + pxor m7, m1 ; min_grain +%if ARCH_X86_64 + SWAP 1, 14 + DEFINE_ARGS buf, bufy, h, x +%else +%define m14 [rsp+0*16] + mova m14, m1 + DEFINE_ARGS buf, bufy, pic_reg, h, x +%endif + pxor m5, m5 + pcmpgtb m5, m4 + punpcklbw m4, m5 +%if %2 + SPLATW m6, [base+hmul_bits+2+%3*2] +%endif + SPLATW m4, m4 + pxor m5, m5 +%if %2 +%if !cpuflag(sse4) + pcmpeqw m2, m2 + pslldq m2, 12 +%if ARCH_X86_64 + SWAP 2, 12 +%else +%define m12 [rsp+1*16] + mova m12, m2 +%endif +%endif +%endif +%if %2 + sub bufq, 2*(82*(73-35*%3)+82-(82*3+41)) +%else + sub bufq, 2*(82*70-3) +%endif + add bufyq, 2*(3+82*3) + mov hd, 70-35*%3 +.y_loop_ar0: + ; first 32 pixels + xor xd, xd +.x_loop_ar0: + movu m0, [bufyq+xq*(2<<%2)] +%if %2 +%if %3 + movu m2, [bufyq+xq*4+82*2] + paddw m0, m2 +%endif + movu m1, [bufyq+xq*4 +16] +%if %3 + movu m2, [bufyq+xq*4+82*2+16] + paddw m1, m2 +%endif + phaddw m0, m1 + pmulhrsw m0, m6 +%endif + punpckhwd m1, m0, m5 + punpcklwd m0, m5 + REPX {pmaddwd x, m4}, m0, m1 + REPX {psrad x, 5}, m0, m1 + packssdw m0, m1 + pmulhrsw m0, m3 + movu m1, [bufq+xq*2] + paddw m0, m1 + pminsw m0, m14 + pmaxsw m0, m7 + cmp xd, 72-40*%2 + je .end + movu [bufq+xq*2], m0 + add xd, 8 + jmp .x_loop_ar0 + + ; last 6/4 pixels +.end: +%if %2 +%if cpuflag(sse4) + pblendw m0, m1, 11000000b +%else + pand m1, m12 + pandn m2, m12, m0 + por m0, m1, m2 +%endif + movu [bufq+xq*2], m0 +%else + movq [bufq+xq*2], m0 +%endif + + add bufq, 82*2 + add bufyq, 82*(2<<%3) + dec hd + jg .y_loop_ar0 +%if ARCH_X86_32 +%undef m12 +%undef m14 +%endif + RET + +.ar1: +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, fg_data, uv, max, cf3, min, val3, x +%else +%assign stack_offset stack_offset_old +%xdefine rstk rsp +%assign stack_size_padded 0 + DEFINE_ARGS buf, shift, pic_reg, fg_data, uv, bufy, cf3 + mov bufyq, r1m + mov uvd, r3m +%endif + imul uvd, 28 + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_uv+uvq+3] + movq m4, [fg_dataq+FGData.ar_coeffs_uv+uvq] +%if WIN64 + DEFINE_ARGS shift, bufy, h, buf, max, cf3, min, val3, x, val0 +%if %2 + lea bufq, [r0-2*(82*(73-35*%3)+44-(82*3+41))] +%else + lea bufq, [r0-2*(82*69+3)] +%endif +%else +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, h, shift, max, cf3, min, val3, x, val0 +%else + DEFINE_ARGS buf, shift, pic_reg, fg_data, val0, bufy, cf3 +%define hd dword r1m +%define mind dword r3m +%define maxd dword r4m +%endif +%if %2 + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif +%endif +%if ARCH_X86_64 + mov shiftd, [r2+FGData.ar_coeff_shift] +%else + mov shiftd, [r3+FGData.ar_coeff_shift] +%endif + pxor m5, m5 + pcmpgtb m5, m4 + punpcklbw m4, m5 ; cf0-4 in words + pshuflw m4, m4, q2100 + psrldq m4, 2 ; cf0-3,4 in words + pshufd m5, m4, q1111 + pshufd m4, m4, q0000 + movd m3, [base+round_vals+shiftq*2-12] ; rnd + pxor m6, m6 + punpcklwd m3, m6 +%if %2 + SPLATW m6, [base+hmul_bits+2+%3*2] +%endif + SPLATD m3, m3 + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 + sar maxd, 1 +%if ARCH_X86_64 + mov mind, maxd + xor mind, -1 +%else + DEFINE_ARGS buf, shift, val3, x, val0, bufy, cf3 + mov r2, maxd + xor r2, -1 + mov mind, r2 +%endif +.y_loop_ar1: + mov xq, -(76>>%2) + movsx val3d, word [bufq+xq*2-2] +.x_loop_ar1: + movu m0, [bufq+xq*2-82*2-2] ; top/left +%if %2 + movu m7, [bufyq+xq*4] +%if %3 + movu m1, [bufyq+xq*4+82*2] + phaddw m7, m1 +%else + phaddw m7, m7 +%endif +%else + movq m7, [bufyq+xq*2] +%endif + psrldq m2, m0, 2 ; top + psrldq m1, m0, 4 ; top/right + punpcklwd m0, m2 +%if %2 +%if %3 + pshufd m2, m7, q3232 + paddw m7, m2 +%endif + pmulhrsw m7, m6 +%endif + punpcklwd m1, m7 + pmaddwd m0, m4 + pmaddwd m1, m5 + paddd m0, m1 + paddd m0, m3 +.x_loop_ar1_inner: + movd val0d, m0 + psrldq m0, 4 + imul val3d, cf3d + add val3d, val0d + sar val3d, shiftb + movsx val0d, word [bufq+xq*2] + add val3d, val0d + cmp val3d, maxd + cmovg val3d, maxd + cmp val3d, mind + cmovl val3d, mind + mov word [bufq+xq*2], val3w + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xq, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 + +.x_loop_ar1_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar1 +%if ARCH_X86_32 +%undef maxd +%undef mind +%undef hd +%endif + RET + +.ar2: +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift +%else + DEFINE_ARGS buf, bufy, pic_reg, fg_data, uv, shift + ALLOC_STACK -16*8 + mov bufyq, r1m + mov uvd, r3m +%endif + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 +%if ARCH_X86_64 + sar bdmaxd, 1 + SPLATW m5, bdmaxd ; max_grain +%else + SPLATW m5, r4m + psraw m5, 1 +%endif + pcmpeqw m6, m6 +%if !cpuflag(sse4) + pcmpeqw m7, m7 + psrldq m7, 14 + pslldq m7, 2 + pxor m7, m6 +%endif + pxor m6, m5 ; min_grain +%if %2 && cpuflag(sse4) + SPLATW m7, [base+hmul_bits+2+%3*2] +%endif + +%if ARCH_X86_64 + SWAP 5, 13 + SWAP 6, 14 + SWAP 7, 15 +%else +%define m13 [rsp+5*16] +%define m14 [rsp+6*16] +%define m15 [rsp+7*16] + mova m13, m5 + mova m14, m6 + mova m15, m7 +%endif + + ; coef values + movu m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+0] + pxor m1, m1 + pcmpgtb m1, m0 + punpckhbw m2, m0, m1 + punpcklbw m0, m1 + pinsrw m2, [base+round_vals-12+shiftq*2], 5 + + pshufd m6, m0, q0000 + pshufd m7, m0, q1111 + pshufd m1, m0, q3333 + pshufd m0, m0, q2222 + pshufd m3, m2, q1111 + pshufd m4, m2, q2222 + pshufd m2, m2, q0000 + +%if ARCH_X86_64 + SWAP 0, 8 + SWAP 1, 9 + SWAP 2, 10 + SWAP 3, 11 + SWAP 4, 12 +%else +%define m8 [rsp+0*16] +%define m9 [rsp+1*16] +%define m10 [rsp+2*16] +%define m11 [rsp+3*16] +%define m12 [rsp+4*16] + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 + mova m12, m4 +%endif + +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, fg_data, h, x +%else + DEFINE_ARGS buf, bufy, pic_reg, fg_data, h, x +%endif +%if %2 + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 +.y_loop_ar2: + mov xq, -(76>>%2) + +.x_loop_ar2: + movu m0, [bufq+xq*2-82*4-4] ; y=-2,x=[-2,+5] + movu m5, [bufq+xq*2-82*2-4] ; y=-1,x=[-2,+5] + psrldq m4, m0, 2 ; y=-2,x=[-1,+5] + psrldq m1, m0, 4 ; y=-2,x=[-0,+5] + psrldq m3, m0, 6 ; y=-2,x=[+1,+5] + psrldq m2, m0, 8 ; y=-2,x=[+2,+5] + punpcklwd m0, m4 ; y=-2,x=[-2/-1,-1/+0,+0/+1,+1/+2] + punpcklwd m1, m3 ; y=-2,x=[+0/+1,+1/+2,+2/+3,+3/+4] + punpcklwd m2, m5 ; y=-2/-1,x=[+2/-2,+3/-1,+4/+0,+5/+1] + pmaddwd m0, m6 + pmaddwd m1, m7 + pmaddwd m2, m8 + paddd m0, m1 + paddd m0, m2 + psrldq m3, m5, 2 ; y=-1,x=[-1,+5] + psrldq m1, m5, 4 ; y=-1,x=[-0,+5] + psrldq m4, m5, 6 ; y=-1,x=[+1,+5] + psrldq m2, m5, 8 ; y=-1,x=[+2,+5] + punpcklwd m3, m1 + punpcklwd m4, m2 + pmaddwd m3, m9 + pmaddwd m4, m10 + paddd m3, m4 + paddd m0, m3 + + ; luma component & rounding +%if %2 + movu m1, [bufyq+xq*4] +%if %3 + movu m2, [bufyq+xq*4+82*2] + phaddw m1, m2 + pshufd m2, m1, q3232 + paddw m1, m2 +%else + phaddw m1, m1 +%endif +%if cpuflag(sse4) + pmulhrsw m1, m15 +%elif %3 + pmulhrsw m1, [base+pw_8192] +%else + pmulhrsw m1, [base+pw_16384] +%endif +%else + movq m1, [bufyq+xq*2] +%endif + punpcklwd m1, [base+pw_1] + pmaddwd m1, m12 + paddd m0, m1 + + movu m1, [bufq+xq*2-4] ; y=0,x=[-2,+5] + pshufd m2, m1, q3321 + pxor m3, m3 + pcmpgtw m3, m2 + punpcklwd m2, m3 ; y=0,x=[0,3] in dword +.x_loop_ar2_inner: + pmaddwd m3, m1, m11 + paddd m3, m0 + psrldq m0, 4 ; shift top to next pixel + psrad m3, [fg_dataq+FGData.ar_coeff_shift] + ; we do not need to packssdw since we only care about one value + paddd m3, m2 + packssdw m3, m3 + pminsw m3, m13 + pmaxsw m3, m14 + psrldq m1, 2 + pslldq m3, 2 + psrldq m2, 4 +%if cpuflag(sse4) + pblendw m1, m3, 00000010b +%else + pand m1, m15 + pandn m4, m15, m3 + por m1, m4 +%endif + ; overwrite previous pixel, should be ok + movd [bufq+xq*2-2], m1 + inc xq + jz .x_loop_ar2_end + test xq, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 + +.x_loop_ar2_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar2 +%if ARCH_X86_32 +%undef m13 +%undef m14 +%undef m15 +%endif + RET + +.ar3: +%if ARCH_X86_64 + DEFINE_ARGS buf, bufy, fg_data, uv, bdmax, shift +%if WIN64 + mov r6, rsp + and rsp, ~15 + sub rsp, 96 + %define tmp rsp +%else + %define tmp rsp+stack_offset-120 +%endif +%else + DEFINE_ARGS buf, bufy, pic_reg, fg_data, uv, shift +%assign stack_offset stack_offset_old + ALLOC_STACK -16*14 + mov bufyq, r1m + mov uvd, r3m + %define tmp rsp +%endif + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + SPLATW m4, [base+round_vals-12+shiftq*2] + pxor m5, m5 + pcmpgtw m5, m4 + punpcklwd m4, m5 +%if ARCH_X86_64 + sar bdmaxd, 1 + SPLATW m6, bdmaxd ; max_grain +%else + SPLATW m6, r4m + psraw m6, 1 +%endif + pcmpeqw m7, m7 +%if !cpuflag(sse4) + pcmpeqw m3, m3 + psrldq m3, 14 + pslldq m3, 4 + pxor m3, m7 +%endif + pxor m7, m6 ; min_grain +%if %2 && cpuflag(sse4) + SPLATW m3, [base+hmul_bits+2+%3*2] +%endif + +%if ARCH_X86_64 + SWAP 3, 11 + SWAP 4, 12 + SWAP 6, 14 + SWAP 7, 15 +%else +%define m11 [rsp+ 9*16] +%define m12 [rsp+10*16] +%define m14 [rsp+12*16] +%define m15 [rsp+13*16] + mova m11, m3 + mova m12, m4 + mova m14, m6 + mova m15, m7 +%endif + + ; cf from y=-3,x=-3 until y=-3,x=-2 + movu m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 0] + pxor m1, m1 + pcmpgtb m1, m0 + punpckhbw m2, m0, m1 + punpcklbw m0, m1 + pshufd m1, m0, q0000 + pshufd m3, m0, q1111 + pshufd m4, m0, q2222 + pshufd m0, m0, q3333 + pshufd m5, m2, q0000 + pshufd m6, m2, q1111 + mova [tmp+16*0], m1 + mova [tmp+16*1], m3 + mova [tmp+16*2], m4 + mova [tmp+16*3], m0 + mova [tmp+16*4], m5 + mova [tmp+16*5], m6 + pshufd m6, m2, q2222 + pshufd m7, m2, q3333 + + ; cf from y=-1,x=-1 to y=0,x=-1 + luma component + movu m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+16] + pxor m1, m1 + pcmpgtb m1, m0 + punpckhbw m2, m0, m1 ; luma + punpcklbw m0, m1 + pshufd m3, m0, q3232 + psrldq m5, m0, 10 + ; y=0,x=[-3 to -1] + "1.0" for current pixel + pinsrw m5, [base+round_vals-10+shiftq*2], 3 + ; y=-1,x=[-1 to +2] + pshufd m1, m0, q0000 + pshufd m0, m0, q1111 + ; y=-1,x=+3 + luma + punpcklwd m3, m2 + pshufd m3, m3, q0000 + +%if ARCH_X86_64 + SWAP 1, 8 + SWAP 0, 9 + SWAP 3, 10 + SWAP 5, 13 + DEFINE_ARGS buf, bufy, fg_data, h, x +%else +%define m8 [rsp+ 6*16] +%define m9 [rsp+ 7*16] +%define m10 [rsp+ 8*16] +%define m13 [rsp+11*16] + mova m8, m1 + mova m9, m0 + mova m10, m3 + mova m13, m5 + DEFINE_ARGS buf, bufy, pic_reg, fg_data, h, x +%endif +%if %2 + sub bufq, 2*(82*(73-35*%3)+44-(82*3+41)) +%else + sub bufq, 2*(82*69+3) +%endif + add bufyq, 2*(79+82*3) + mov hd, 70-35*%3 +.y_loop_ar3: + mov xq, -(76>>%2) + +.x_loop_ar3: + ; first line + movu m0, [bufq+xq*2-82*6-6+ 0] ; y=-3,x=[-3,+4] + movd m1, [bufq+xq*2-82*6-6+16] ; y=-3,x=[+5,+6] + palignr m2, m1, m0, 2 ; y=-3,x=[-2,+5] + palignr m1, m1, m0, 12 ; y=-3,x=[+3,+6] + punpckhwd m3, m0, m2 ; y=-3,x=[+1/+2,+2/+3,+3/+4,+4/+5] + punpcklwd m0, m2 ; y=-3,x=[-3/-2,-2/-1,-1/+0,+0/+1] + shufps m2, m0, m3, q1032 ; y=-3,x=[-1/+0,+0/+1,+1/+2,+2/+3] + + pmaddwd m0, [tmp+0*16] + pmaddwd m2, [tmp+1*16] + pmaddwd m3, [tmp+2*16] + paddd m0, m2 + paddd m0, m3 ; first 6 x of top y + + ; second line [m0/1 are busy] + movu m2, [bufq+xq*2-82*4-6+ 0] ; y=-2,x=[-3,+4] + movd m3, [bufq+xq*2-82*4-6+16] ; y=-2,x=[+5,+6] + punpcklwd m1, m2 ; y=-3/-2,x=[+3/-3,+4/-2,+5/-1,+6/+0] + palignr m4, m3, m2, 2 ; y=-2,x=[-2,+5] + palignr m3, m3, m2, 4 ; y=-2,x=[-2,+5] + punpckhwd m5, m4, m3 ; y=-2,x=[+2/+3,+3/+4,+4/+5,+5/+6] + punpcklwd m4, m3 ; y=-2,x=[-2/-1,-1/+0,+0/+1,+1/+2] + shufps m3, m4, m5, q1032 ; t=-2,x=[+0/+1,+1/+2,+2/+3,+3/+4] + pmaddwd m1, [tmp+3*16] + pmaddwd m4, [tmp+4*16] + pmaddwd m3, [tmp+5*16] + pmaddwd m5, m6 + paddd m1, m4 + paddd m3, m5 + paddd m0, m1 + paddd m0, m3 ; top 2 lines + + ; third line [m0 is busy] & luma + round + movu m1, [bufq+xq*2-82*2-6+ 0] ; y=-1,x=[-3,+4] + movd m2, [bufq+xq*2-82*2-6+16] ; y=-1,x=[+5,+6] +%if %2 + movu m5, [bufyq+xq*4] +%if %3 + movu m4, [bufyq+xq*4+82*2] + phaddw m5, m4 +%else + phaddw m5, m5 +%endif +%else + movq m5, [bufyq+xq*2] +%endif + palignr m3, m2, m1, 2 ; y=-1,x=[-2,+5] + palignr m2, m2, m1, 12 ; y=-1,x=[+3,+6] +%if %3 + pshufd m4, m5, q3232 + paddw m5, m4 +%endif +%if %2 +%if cpuflag(sse4) + pmulhrsw m5, m11 +%elif %3 + pmulhrsw m5, [base+pw_8192] +%else + pmulhrsw m5, [base+pw_16384] +%endif +%endif + punpckhwd m4, m1, m3 ; y=-1,x=[+1/+2,+2/+3,+3/+4,+4/+5] + punpcklwd m1, m3 ; y=-1,x=[-3/-2,-2/-1,-1/+0,+0/+1] + shufps m3, m1, m4, q1032 ; y=-1,x=[-1/+0,+0/+1,+1/+2,+2/+3] + punpcklwd m2, m5 + pmaddwd m1, m7 + pmaddwd m3, m8 + pmaddwd m4, m9 + pmaddwd m2, m10 + paddd m1, m3 + paddd m4, m2 + paddd m0, m12 ; += round + paddd m1, m4 + paddd m0, m1 + + movu m1, [bufq+xq*2-6] ; y=0,x=[-3,+4] +.x_loop_ar3_inner: + pmaddwd m2, m1, m13 + pshufd m3, m2, q1111 + paddd m2, m3 ; left+cur + paddd m2, m0 ; add top + psrldq m0, 4 + psrad m2, [fg_dataq+FGData.ar_coeff_shift] + packssdw m2, m2 + pminsw m2, m14 + pmaxsw m2, m15 + pslldq m2, 4 + psrldq m1, 2 +%if cpuflag(sse4) + pblendw m1, m2, 00000100b +%else + pand m1, m11 + pandn m3, m11, m2 + por m1, m3 +%endif + ; overwrite previous pixels, should be ok + movq [bufq+xq*2-4], m1 + inc xq + jz .x_loop_ar3_end + test xq, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 + +.x_loop_ar3_end: + add bufq, 82*2 + add bufyq, 82*2<<%3 + dec hd + jg .y_loop_ar3 +%if WIN64 + mov rsp, r6 +%elif ARCH_X86_32 +%undef m8 +%undef m9 +%undef m10 +%undef m11 +%undef m12 +%undef m13 +%undef m14 +%undef m15 +%endif + RET +%endmacro + +generate_grain_uv_fn 420, 1, 1 +generate_grain_uv_fn 422, 1, 0 +generate_grain_uv_fn 444, 0, 0 + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +INIT_XMM ssse3 +%if ARCH_X86_32 +%if STACK_ALIGNMENT < mmsize +cglobal fgy_32x32xn_16bpc, 0, 7, 8, 0-(8 * mmsize + 12 * gprsize), \ + dst, src, scaling, unused1, fg_data, picptr, unused2 + ; copy stack arguments to new position post-alignment, so that we + ; don't have to keep the old stack location in a separate register + mov r0, r0m + mov r1, r2m + mov r2, r4m + mov r3, r6m + mov r4, r7m + mov r5, r8m + +%define r0m [rsp+8*mmsize+ 3*gprsize] +%define r2m [rsp+8*mmsize+ 5*gprsize] +%define r4m [rsp+8*mmsize+ 7*gprsize] +%define r6m [rsp+8*mmsize+ 9*gprsize] +%define r7m [rsp+8*mmsize+10*gprsize] +%define r8m [rsp+8*mmsize+11*gprsize] + + mov r0m, r0 + mov r2m, r1 + mov r4m, r2 + mov r6m, r3 + mov r7m, r4 + mov r8m, r5 +%else +cglobal fgy_32x32xn_16bpc, 0, 7, 8, 8 * mmsize + 4 * gprsize, \ + dst, src, scaling, unused1, fg_data, picptr, unused2 +%endif + mov srcq, srcm + mov scalingq, r5m + mov fg_dataq, r3m +%if STACK_ALIGNMENT < mmsize + mov r6, r9m + +%define r9m [rsp+8*mmsize+ 4*gprsize] +%define r3m [rsp+8*mmsize+ 6*gprsize] +%define r5m [rsp+8*mmsize+ 8*gprsize] + + mov r9m, r6 +%endif + LEA r5, $$ +%define base r5-$$ + mov r5m, picptrq +%else +cglobal fgy_32x32xn_16bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, grain_lut + lea r8, [pb_mask] +%define base r8-pb_mask +%endif + mov r6d, [fg_dataq+FGData.scaling_shift] + SPLATW m3, [base+mul_bits+r6*2-14] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] +%if ARCH_X86_32 + DECLARE_REG_TMP 0, 3 +%else + DECLARE_REG_TMP 9, 10 +%endif + mov t0d, r9m ; bdmax + sar t0d, 11 ; is_12bpc + inc t0d + mov t1d, r6d + imul t1d, t0d + dec t0d + SPLATW m5, [base+min+t1*2] + lea t0d, [t0d*3] + lea t0d, [r6d*2+t0d] + SPLATW m4, [base+max+t0*2] + SPLATW m2, r9m + + pcmpeqw m1, m1 + psraw m7, m2, 1 ; max_grain + pxor m1, m7 ; min_grain + SPLATD m6, [base+pd_16] + + SCRATCH 1, 9, 0 + SCRATCH 2, 10, 1 + SCRATCH 3, 11, 2 + SCRATCH 4, 12, 3 + SCRATCH 5, 13, 4 + SCRATCH 6, 14, 5 + SCRATCH 7, 15, 6 + + mova m6, [base+pw_27_17_17_27] ; for horizontal filter + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, unused2 + DECLARE_REG_TMP 0 +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused1, \ + sby, see + DECLARE_REG_TMP 7 +%endif + + mov sbyd, r8m + movzx t0d, byte [fg_dataq+FGData.overlap_flag] + test t0d, t0d + jz .no_vertical_overlap + test sbyd, sbyd + jnz .vertical_overlap +.no_vertical_overlap: + mov dword r8m, t0d + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, fg_data, picptr, unused + imul seed, (173 << 24) | 37 +%else + imul seed, sbyd, (173 << 24) | 37 +%endif + add seed, (105 << 24) | 178 + rol seed, 8 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + + mov r3m, seed + mov wq, r4m +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused1, unused2, see, src_bak +%endif + + lea src_bakq, [srcq+wq*2] + mov r9mp, src_bakq + neg wq + sub dstmp, srcq +%if ARCH_X86_32 + mov r4m, wq +%endif + +.loop_x: +%if ARCH_X86_32 + mov seed, r3m +%endif + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164 + lea offyq, [offyq+offxq*2+747] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak +%endif + +.loop_x_odd: + movzx hd, word r7m + mov grain_lutq, grain_lutmp +.loop_y: + ; src + pand m0, m10, [srcq+ 0] + pand m1, m10, [srcq+16] ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m2, m0, scalingq-1, r0, r5, 8, 1, m4 + vpgatherdw m3, m1, scalingq-1, r0, r5, 8, 1, m4 +%else + vpgatherdw m2, m0, scalingq-1, r11, r13, 8, 1, m4 + vpgatherdw m3, m1, scalingq-1, r11, r13, 8, 1, m4 +%endif + REPX {psrlw x, 8}, m2, m3 + + ; grain = grain_lut[offy+y][offx+x] + movu m4, [grain_lutq+offxyq*2] + movu m5, [grain_lutq+offxyq*2+16] + + ; noise = round2(scaling[src] * grain, scaling_shift) + REPX {pmullw x, m11}, m2, m3 + pmulhrsw m4, m2 + pmulhrsw m5, m3 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+16], m1 + + add srcq, r2mp ; src += stride + add grain_lutq, 82*2 + dec hd + jg .loop_y + +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end +%if ARCH_X86_32 + mov srcq, r9mp + add srcq, r4mp + add srcq, r4mp +%else + mov src_bakq, r9mp + lea srcq, [src_bakq+wq*2] +%endif + btc dword r8m, 2 + jc .next_blk + add offxyd, 16 + test dword r8m, 2 + jz .loop_x_odd +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r12d, 16 ; top_offxy += 16 +%endif + jmp .loop_x_odd_v_overlap + +.next_blk: + test dword r8m, 1 + jz .loop_x + + ; r8m = sbym + test dword r8m, 2 + jnz .loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +.loop_x_h_overlap: +%if ARCH_X86_32 + add offxyd, 16 + mov [rsp+8*mmsize+0*gprsize], offxyd + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + mov seed, r3m +%endif + + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, h, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, left_offxy + + lea left_offxyd, [offyd+16] ; previous column's offy*stride+offx + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164 + lea offyq, [offyq+offxq*2+747] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, left_offxy +%endif + + mov hd, dword r7m + mov grain_lutq, grain_lutmp +.loop_y_h_overlap: + ; grain = grain_lut[offy+y][offx+x] + movu m5, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r5, [rsp+8*mmsize+0*gprsize] + movd m4, [grain_lutq+r5*2] +%else + movd m4, [grain_lutq+left_offxyq*2] +%endif + punpcklwd m4, m5 + pmaddwd m4, m6 + paddd m4, m14 + psrad m4, 5 + packssdw m4, m4 + pminsw m4, m15 + pmaxsw m4, m9 + shufps m4, m5, q3210 + + ; src + pand m0, m10, [srcq+ 0] + pand m1, m10, [srcq+16] ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m2, m0, scalingq-1, r0, r5, 8, 1, m5 + vpgatherdw m3, m1, scalingq-1, r0, r5, 8, 1, m5 +%else + vpgatherdw m2, m0, scalingq-1, r13, r14, 8, 1, m5 + vpgatherdw m3, m1, scalingq-1, r13, r14, 8, 1, m5 +%endif + REPX {psrlw x, 8}, m2, m3 + + ; noise = round2(scaling[src] * grain, scaling_shift) + movu m5, [grain_lutq+offxyq*2+16] + REPX {pmullw x, m11}, m2, m3 + pmulhrsw m4, m2 + pmulhrsw m5, m3 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+16], m1 + + add srcq, r2mp + add grain_lutq, 82*2 + dec hd + jg .loop_y_h_overlap + +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end +%if ARCH_X86_32 + mov srcq, r9mp + add srcq, r4mp + add srcq, r4mp +%else + mov src_bakq, r9mp + lea srcq, [src_bakq+wq*2] +%endif + or dword r8m, 4 + add offxyd, 16 + + ; r8m = sbym + test dword r8m, 2 + jz .loop_x_odd +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r12d, 16 ; top_offxy += 16 +%endif + jmp .loop_x_odd_v_overlap + +.end: + RET + +.vertical_overlap: + or t0d, 2 + mov r8m, t0d + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, unused +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused1, \ + sby, see +%endif + + movzx sbyd, sbyb +%if ARCH_X86_32 + imul r4, [fg_dataq+FGData.seed], 0x00010001 + DEFINE_ARGS dst, src, scaling, sby, see, picptr, unused +%else + imul seed, [fg_dataq+FGData.seed], 0x00010001 +%endif + imul t0d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add t0d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and t0d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, t0d +%if ARCH_X86_32 + xor sbyd, seed + + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + + mov r3m, seed + mov wq, r4m +%else + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused1, unused2, see, src_bak +%endif + + lea src_bakq, [srcq+wq*2] + mov r9mp, src_bakq + neg wq + sub dstmp, srcq +%if ARCH_X86_32 + mov r4m, wq +%endif + +.loop_x_v_overlap: +%if ARCH_X86_32 + mov r5, r5m + SPLATD m7, [base+pw_27_17_17_27] + mov seed, r3m +%else + SPLATD m7, [pw_27_17_17_27] +%endif + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp t0b ; parity of top_seed + shr seed, 16 + shl t0d, 16 + test seeb, seeh + setp t0b ; parity of cur_seed + or r6d, 0x00010001 + xor t0d, r6d + mov seed, t0d + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, unused, top_offxy + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*2+0x10001*747+32*82] + +%if ARCH_X86_32 + DEFINE_ARGS top_offxy, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, unused, top_offxy +%endif + + movzx top_offxyd, offxyw +%if ARCH_X86_32 + mov [rsp+8*mmsize+1*gprsize], top_offxyd + + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + shr offxyd, 16 + +.loop_x_odd_v_overlap: +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m7, [PIC_ptr(pw_27_17_17_27)] + mov hd, dword r7m + mov grain_lutq, grain_lutmp +.loop_y_v_overlap: + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r5, [rsp+8*mmsize+1*gprsize] + movu m2, [grain_lutq+r5*2] +%else + movu m2, [grain_lutq+top_offxyq*2] +%endif + punpckhwd m4, m2, m3 + punpcklwd m2, m3 + REPX {pmaddwd x, m7}, m4, m2 + REPX {paddd x, m14}, m4, m2 + REPX {psrad x, 5}, m4, m2 + packssdw m2, m4 + pminsw m2, m15 + pmaxsw m2, m9 + movu m4, [grain_lutq+offxyq*2+16] +%if ARCH_X86_32 + movu m3, [grain_lutq+r5*2+16] +%else + movu m3, [grain_lutq+top_offxyq*2+16] +%endif + punpckhwd m5, m3, m4 + punpcklwd m3, m4 + REPX {pmaddwd x, m7}, m5, m3 + REPX {paddd x, m14}, m5, m3 + REPX {psrad x, 5}, m5, m3 + packssdw m3, m5 + pminsw m3, m15 + pmaxsw m3, m9 + + ; src + pand m0, m10, [srcq+ 0] ; m0-1: src as word + pand m1, m10, [srcq+16] ; m0-1: src as word + + ; scaling[src] + ; noise = round2(scaling[src] * grain, scaling_shift) +%if ARCH_X86_32 + vpgatherdw m4, m0, scalingq-1, r0, r5, 8, 1, m5 +%else + vpgatherdw m4, m0, scalingq-1, r11, r13, 8, 1, m5 +%endif + psrlw m4, 8 + pmullw m4, m11 + pmulhrsw m4, m2 +%if ARCH_X86_32 + vpgatherdw m5, m1, scalingq-1, r0, r5, 8, 1, m2 +%else + vpgatherdw m5, m1, scalingq-1, r11, r13, 8, 1, m2 +%endif + psrlw m5, 8 + pmullw m5, m11 + pmulhrsw m5, m3 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+16], m1 + + add srcq, r2mp + add grain_lutq, 82*2 + dec hw + jz .end_y_v_overlap + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m7, [PIC_ptr(pw_27_17_17_27)+4] + xor hd, 0x10000 + test hd, 0x10000 + jnz .loop_y_v_overlap + jmp .loop_y + +.end_y_v_overlap: +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end_hv +%if ARCH_X86_32 + mov srcq, r9mp + add srcq, r4mp + add srcq, r4mp +%else + mov src_bakq, r9mp + lea srcq, [src_bakq+wq*2] +%endif + btc dword r8m, 2 + jc .next_blk_v +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add top_offxyd, 16 +%endif + add offxyd, 16 + jmp .loop_x_odd_v_overlap + +.next_blk_v: + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap + +.loop_x_hv_overlap: +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + + mov r0, [rsp+8*mmsize+1*gprsize] + add r3, 16 + add r0, 16 + mov [rsp+8*mmsize+0*gprsize], r3 ; left_offxy + mov [rsp+8*mmsize+2*gprsize], r0 ; topleft_offxy + + mov seed, r3m + xor r0, r0 +%else + ; we assume from the block above that bits 8-15 of r7d are zero'ed +%endif + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp t0b ; parity of top_seed + shr seed, 16 + shl t0d, 16 + test seeb, seeh + setp t0b ; parity of cur_seed + or r6d, 0x00010001 + xor t0d, r6d + mov seed, t0d + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, src_bak, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyq, [top_offxyq+16] + lea left_offxyq, [offyq+16] + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*2+0x10001*747+32*82] + +%if ARCH_X86_32 + DEFINE_ARGS top_offxy, src, scaling, offxy, w, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, src_bak, left_offxy, top_offxy, topleft_offxy +%endif + + movzx top_offxyd, offxyw +%if ARCH_X86_32 + mov [rsp+8*mmsize+1*gprsize], top_offxyd + + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + shr offxyd, 16 + +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m7, [PIC_ptr(pw_27_17_17_27)] + + movzx hd, word r7m + mov grain_lutq, grain_lutmp +.loop_y_hv_overlap: + ; grain = grain_lut[offy+y][offx+x] + movu m2, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r0, [rsp+8*mmsize+1*gprsize] ; top_offxy + mov r5, [rsp+8*mmsize+0*gprsize] ; left_offxy + movu m4, [grain_lutq+r0*2] + movd m5, [grain_lutq+r5*2] + mov r5, [rsp+8*mmsize+2*gprsize] ; topleft_offxy + movd m3, [grain_lutq+r5*2] +%else + movu m4, [grain_lutq+top_offxyq*2] + movd m5, [grain_lutq+left_offxyq*2] + movd m3, [grain_lutq+topleft_offxyq*2] +%endif + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklwd m5, m2 + punpcklwd m3, m4 + REPX {pmaddwd x, m6}, m5, m3 + REPX {paddd x, m14}, m5, m3 + REPX {psrad x, 5}, m5, m3 + packssdw m5, m3 + pminsw m5, m15 + pmaxsw m5, m9 + shufps m3, m5, m2, q3210 + shufps m5, m4, q3232 + ; followed by v interpolation (top | cur -> cur) + movu m0, [grain_lutq+offxyq*2+16] +%if ARCH_X86_32 + movu m1, [grain_lutq+r0*2+16] +%else + movu m1, [grain_lutq+top_offxyq*2+16] +%endif + punpcklwd m2, m5, m3 + punpckhwd m5, m3 + punpcklwd m3, m1, m0 + punpckhwd m1, m0 + REPX {pmaddwd x, m7}, m2, m5, m3, m1 + REPX {paddd x, m14}, m2, m5, m3, m1 + REPX {psrad x, 5}, m2, m5, m3, m1 + packssdw m2, m5 + packssdw m3, m1 + REPX {pminsw x, m15}, m2, m3 + REPX {pmaxsw x, m9}, m2, m3 + + ; src + pand m0, m10, [srcq+ 0] + pand m1, m10, [srcq+16] ; m0-1: src as word + + ; scaling[src] + ; noise = round2(scaling[src] * grain, scaling_shift) +%if ARCH_X86_32 + vpgatherdw m4, m0, scalingq-1, r0, r5, 8, 1, m5 +%else + vpgatherdw m4, m0, scalingq-1, r14, r10, 8, 1, m5 +%endif + psrlw m4, 8 + pmullw m4, m11 + pmulhrsw m2, m4 +%if ARCH_X86_32 + vpgatherdw m5, m1, scalingq-1, r0, r5, 8, 1, m4 +%else + vpgatherdw m5, m1, scalingq-1, r14, r10, 8, 1, m4 +%endif + psrlw m5, 8 + pmullw m5, m11 + pmulhrsw m3, m5 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+srcq+ 0], m0 + mova [dstq+srcq+16], m1 + + add srcq, r2mp + add grain_lutq, 82*2 + dec hw + jz .end_y_hv_overlap + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m7, [PIC_ptr(pw_27_17_17_27)+4] + xor hd, 0x10000 + test hd, 0x10000 + jnz .loop_y_hv_overlap + jmp .loop_y_h_overlap + +.end_y_hv_overlap: + or dword r8m, 4 +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end_hv +%if ARCH_X86_32 + mov r5, r5m + add offxyd, 16 + add dword [rsp+8*mmsize+1*gprsize], 16 ; top_offxy += 16 + mov srcq, r9mp + add srcq, r4mp + add srcq, r4mp +%else + add offxyd, 16 + add top_offxyd, 16 + mov src_bakq, r9mp + lea srcq, [src_bakq+wq*2] +%endif + jmp .loop_x_odd_v_overlap + +.end_hv: + RET +%if ARCH_X86_32 + DECLARE_ARG 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +%endif + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +INIT_XMM ssse3 +%if ARCH_X86_32 +%if STACK_ALIGNMENT < mmsize +cglobal fguv_32x32xn_i%1_16bpc, 0, 7, 8, 0-(8 * mmsize + 16 * gprsize), \ + tmp, src, scaling, h, fg_data, picptr, unused + mov r0, r0m + mov r1, r1m + mov r2, r2m + mov r4, r3m + mov r3, r4m + mov r5, r5m +%define r0m [rsp+8*mmsize+ 3*gprsize] +%define r1m [rsp+8*mmsize+ 4*gprsize] +%define r2m [rsp+8*mmsize+ 5*gprsize] +%define r3m [rsp+8*mmsize+ 6*gprsize] +%define r4m [rsp+8*mmsize+ 7*gprsize] +%define r5m [rsp+8*mmsize+ 8*gprsize] + mov r0m, r0 + mov r2m, r2 + mov r4m, r3 + mov r5m, r5 + + mov r0, r6m + mov r2, r7m + mov r3, r8m + mov r5, r9m +%define r6m [rsp+8*mmsize+ 9*gprsize] +%define r7m [rsp+8*mmsize+10*gprsize] +%define r8m [rsp+8*mmsize+11*gprsize] +%define r9m [rsp+8*mmsize+12*gprsize] + mov r6m, r0 + mov r7m, r2 + mov r8m, r3 + mov r9m, r5 + + mov r2, r10m + mov r3, r11m + mov r5, r12m + mov r0, r13m +%define r10m [rsp+8*mmsize+13*gprsize] +%define r11m [rsp+8*mmsize+14*gprsize] +%define r12m [rsp+8*mmsize+15*gprsize] + mov r10m, r2 + mov r11m, r3 + mov r12m, r5 + + SPLATW m2, r13m +%else +cglobal fguv_32x32xn_i%1_16bpc, 0, 7, 8, 8 * mmsize + (4) * gprsize, \ + tmp, src, scaling, h, fg_data, picptr, unused + mov srcq, srcm + mov fg_dataq, r3m +%endif + LEA r5, $$ +%define base r5-$$ + + DECLARE_REG_TMP 0, 2, 3 +%else +cglobal fguv_32x32xn_i%1_16bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, luma, lstride, uv_pl, is_id +%define base r8-pb_mask + lea r8, [pb_mask] + + DECLARE_REG_TMP 9, 10, 11 +%endif + mov r6d, [fg_dataq+FGData.scaling_shift] + SPLATW m3, [base+mul_bits+r6*2-14] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] +%if STACK_ALIGNMENT >= mmsize + mov t0d, r13m ; bdmax +%endif + sar t0d, 11 ; is_12bpc + inc t0d + mov t1d, r6d + imul t1d, t0d + dec t0d + SPLATW m5, [base+min+t1*2] + lea t1d, [t0d*3] + mov t2d, r12m + inc t2d + imul r6d, t2d + add t1d, r6d + SPLATW m4, [base+max+t1*2] +%if STACK_ALIGNMENT >= mmsize + SPLATW m2, r13m +%endif + + SCRATCH 2, 10, 2 + SCRATCH 3, 11, 3 + SCRATCH 4, 12, 4 + SCRATCH 5, 13, 5 + +%define mzero m7 + +%if %3 + SPLATD m2, [base+pw_23_22] +%endif + +%if ARCH_X86_32 + mov scalingq, r5m + mov r5m, r5 +%else + mov r13mp, strideq +%endif + + pcmpeqw m0, m0 + psraw m1, m10, 1 + pxor m0, m1 + + SCRATCH 0, 8, 0 + SCRATCH 1, 9, 1 + + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_h, ss_v +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap + + DECLARE_REG_TMP 0 +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, sby, see, overlap + + DECLARE_REG_TMP 9 +%endif + +%if %1 + mov r6d, r11m + SPLATW m0, [fg_dataq+FGData.uv_mult+r6*4] + SPLATW m1, [fg_dataq+FGData.uv_luma_mult+r6*4] + punpcklwd m6, m1, m0 + SPLATW m5, [fg_dataq+FGData.uv_offset+r6*4] + SPLATD m7, [base+pw_4+t0*4] + pmullw m5, m7 +%else + SPLATD m6, [base+pd_16] +%if %2 + mova m5, [base+pw_23_22] +%else + mova m5, [base+pw_27_17_17_27] +%endif +%endif + + SCRATCH 6, 14, 6 + SCRATCH 5, 15, 7 + +%if ARCH_X86_32 + DECLARE_REG_TMP 0 +%else + DECLARE_REG_TMP 7 +%endif + + mov sbyd, r8m + mov t0d, [fg_dataq+FGData.overlap_flag] + test t0d, t0d + jz %%no_vertical_overlap + test sbyd, sbyd + jnz %%vertical_overlap + +%%no_vertical_overlap: + mov r8m, t0d +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, fg_data, picptr, overlap + imul seed, (173 << 24) | 37 +%else + imul seed, sbyd, (173 << 24) | 37 +%endif + add seed, (105 << 24) | 178 + rol seed, 8 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, see, w, picptr, luma + + mov dstq, r0mp + mov lumaq, r9mp + mov wq, r4m + lea r3, [srcq+wq*2] + mov r1mp, r3 + lea r3, [dstq+wq*2] + mov r11mp, r3 + lea r3, [lumaq+wq*(2<<%2)] + mov r12mp, r3 +%if %3 + shl r10mp, 1 +%endif +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused2, unused3, see, unused4, unused5, unused6, luma, lstride + + mov lstrideq, r10mp +%if %3 + add lstrideq, lstrideq +%endif + mov lumaq, r9mp + lea r10, [srcq+wq*2] + lea r11, [dstq+wq*2] + lea r12, [lumaq+wq*(2<<%2)] + mov r10mp, r10 + mov r11mp, r11 + mov r12mp, r12 +%endif + neg wq +%if ARCH_X86_32 + mov r4mp, wq +%endif + +%%loop_x: +%if ARCH_X86_32 + mov seed, r3m +%endif + + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, unused1, unused2, unused3, luma, lstride + + mov offxd, seed + mov offyd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyq, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, unused1, unused2, unused3, luma, lstride +%endif + +%if %2 == 0 +%%loop_x_odd: +%endif + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y: + ; src + mova m0, [srcq] + mova m1, [srcq+16] ; m0-1: src as word + + ; luma_src + pxor mzero, mzero +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, luma, grain_lut + + mov lumaq, r9m +%endif + mova m4, [lumaq+ 0] + mova m6, [lumaq+(16<<%2)] +%if %2 + phaddw m4, [lumaq+16] + phaddw m6, [lumaq+48] +%endif +%if ARCH_X86_32 + add lumaq, r10mp + mov r9m, lumaq +%endif +%if %2 + pavgw m4, mzero + pavgw m6, mzero +%endif + +%if %1 + punpckhwd m3, m4, m0 + punpcklwd m4, m0 + punpckhwd m5, m6, m1 + punpcklwd m6, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m3, m4, m5, m6 + REPX {psrad x, 6}, m3, m4, m5, m6 + packssdw m4, m3 + packssdw m6, m5 + REPX {paddw x, m15}, m4, m6 + REPX {pmaxsw x, mzero}, m4, m6 + REPX {pminsw x, m10}, m4, m6 ; clip_pixel() +%else + REPX {pand x, m10}, m4, m6 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m3, m4, scalingq-1, r0, r5, 8, 1 + vpgatherdw m5, m6, scalingq-1, r0, r5, 8, 1 +%else + vpgatherdw m3, m4, scalingq-1, r10, r12, 8, 1 + vpgatherdw m5, m6, scalingq-1, r10, r12, 8, 1 +%endif + REPX {psrlw x, 8}, m3, m5 + + ; grain = grain_lut[offy+y][offx+x] + movu m4, [grain_lutq+offxyq*2] + movu m6, [grain_lutq+offxyq*2+16] + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + REPX {pmullw x, m11}, m3, m5 + pmulhrsw m4, m3 + pmulhrsw m6, m5 + + ; dst = clip_pixel(src, noise) + paddw m0, m4 + paddw m1, m6 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+ 0], m0 + mova [dstq+16], m1 + +%if ARCH_X86_32 + add srcq, r2mp + add dstq, r2mp + mov dstmp, dstq +%else + add srcq, r13mp + add dstq, r13mp + add lumaq, lstrideq +%endif + add grain_lutq, 82*2 + dec hd + jg %%loop_y + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, w, picptr, luma + + mov wq, r4mp +%endif + add wq, 16 + jge %%end +%if ARCH_X86_32 + mov srcq, r1mp +%else + mov srcq, r10mp +%endif + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] +%if ARCH_X86_32 + mov r0m, dstq + mov r9m, lumaq + mov r4m, wq +%endif +%if %2 == 0 + btc dword r8m, 2 + jc %%next_blk + add offxyd, 16 + test dword r8m, 2 + jz %%loop_x_odd +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r11d, 16 +%endif + jmp %%loop_x_odd_v_overlap +%%next_blk: +%endif + test dword r8m, 1 + je %%loop_x + + ; r8m = sbym + test dword r8m, 2 + jnz %%loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: +%if ARCH_X86_32 + add offxyd, 16 + mov [rsp+8*mmsize+0*gprsize], offxyd + + DEFINE_ARGS dst, src, scaling, see, w, picptr, grain_lut + + mov seed, r3m +%endif + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, unused1, unused2, luma, lstride + + lea left_offxyd, [offyd+16] ; previous column's offy*stride+offx + mov offxd, seed + mov offyd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyq, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, unused1, unused2, luma, lstride +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y_h_overlap: + mova m0, [srcq] + mova m1, [srcq+16] + + ; luma_src + pxor mzero, mzero +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, luma, grain_lut + mov lumaq, r9m +%endif + mova m4, [lumaq+ 0] + mova m6, [lumaq+(16<<%2)] +%if %2 + phaddw m4, [lumaq+16] + phaddw m6, [lumaq+48] +%endif +%if ARCH_X86_32 + add lumaq, r10mp + mov r9m, lumaq +%endif +%if %2 + pavgw m4, mzero + pavgw m6, mzero +%endif + +%if %1 + punpckhwd m3, m4, m0 + punpcklwd m4, m0 + punpckhwd m5, m6, m1 + punpcklwd m6, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m3, m4, m5, m6 + REPX {psrad x, 6}, m3, m4, m5, m6 + packssdw m4, m3 + packssdw m6, m5 + REPX {paddw x, m15}, m4, m6 + REPX {pmaxsw x, mzero}, m4, m6 + REPX {pminsw x, m10}, m4, m6 ; clip_pixel() +%else + REPX {pand x, m10}, m4, m6 +%endif + + ; grain = grain_lut[offy+y][offx+x] + movu m7, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r5, [rsp+8*mmsize+0*gprsize] + movd m5, [grain_lutq+r5*2] +%else + movd m5, [grain_lutq+left_offxyq*2+ 0] +%endif + punpcklwd m5, m7 ; {left0, cur0} +%if %1 +%if ARCH_X86_32 + mov r5, r5m +%endif +%if %2 + pmaddwd m5, [PIC_ptr(pw_23_22)] +%else + pmaddwd m5, [PIC_ptr(pw_27_17_17_27)] +%endif + paddd m5, [PIC_ptr(pd_16)] +%else + pmaddwd m5, m15 + paddd m5, m14 +%endif + psrad m5, 5 + packssdw m5, m5 + pmaxsw m5, m8 + pminsw m5, m9 + shufps m5, m7, q3210 + movu m3, [grain_lutq+offxyq*2+16] + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m4, scalingq-1, r0, r5, 8, 1 + vpgatherdw m4, m6, scalingq-1, r0, r5, 8, 1 +%else + vpgatherdw m7, m4, scalingq-1, r2, r12, 8, 1 + vpgatherdw m4, m6, scalingq-1, r2, r12, 8, 1 +%endif + REPX {psrlw x, 8}, m7, m4 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + REPX {pmullw x, m11}, m7, m4 + pmulhrsw m5, m7 + pmulhrsw m3, m4 + + ; dst = clip_pixel(src, noise) + paddw m0, m5 + paddw m1, m3 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+ 0], m0 + mova [dstq+16], m1 + +%if ARCH_X86_32 + add srcq, r2mp + add dstq, r2mp + mov dstmp, dstq +%else + add srcq, r13mp + add dstq, r13mp + add lumaq, lstrideq +%endif + add grain_lutq, 82*2 + dec hd + jg %%loop_y_h_overlap + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, w, luma, grain_lut + mov wq, r4mp +%endif + add wq, 16 + jge %%end +%if ARCH_X86_32 + mov srcq, r1mp +%else + mov srcq, r10mp +%endif + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] +%if ARCH_X86_32 + mov r0mp, dstq + mov r9mp, lumaq + mov r4m, wq +%endif + +%if %2 + ; r8m = sbym + test dword r8m, 2 + jne %%loop_x_hv_overlap + jmp %%loop_x_h_overlap +%else + or dword r8m, 4 + add offxyd, 16 + + ; r8m = sbym + test dword r8m, 2 + jz %%loop_x_odd +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r11d, 16 ; top_offxy += 16 +%endif + jmp %%loop_x_odd_v_overlap +%endif + +%%end: + RET + +%%vertical_overlap: + or t0d, 2 + mov r8m, t0d + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, \ + sby, see, unused1, unused2, unused3, lstride +%endif + + movzx sbyd, sbyb +%if ARCH_X86_32 + imul r4, [fg_dataq+FGData.seed], 0x00010001 + + DEFINE_ARGS tmp, src, scaling, sby, see, picptr, unused +%else + imul seed, [fg_dataq+FGData.seed], 0x00010001 +%endif + imul t0d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add t0d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and t0d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, t0d +%if ARCH_X86_32 + xor sbyd, seed + + DEFINE_ARGS dst, src, scaling, see, w, picptr, luma + + mov r3m, seed + mov dstq, r0mp + mov lumaq, r9mp + mov wq, r4m + lea r3, [srcq+wq*2] + mov r1mp, r3 + lea r3, [dstq+wq*2] + mov r11mp, r3 + lea r3, [lumaq+wq*(2<<%2)] + mov r12mp, r3 +%if %3 + shl r10mp, 1 +%endif +%else + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused1, unused2, see, unused3, unused4, unused5, luma, lstride + + mov lstrideq, r10mp +%if %3 + add lstrideq, lstrideq +%endif + mov lumaq, r9mp + lea r10, [srcq+wq*2] + lea r11, [dstq+wq*2] + lea r12, [lumaq+wq*(2<<%2)] + mov r10mp, r10 + mov r11mp, r11 + mov r12mp, r12 +%endif + neg wq +%if ARCH_X86_32 + mov r4m, wq +%endif + +%%loop_x_v_overlap: +%if ARCH_X86_32 + mov seed, r3m + xor t0d, t0d +%else + ; we assume from the block above that bits 8-15 of r7d are zero'ed +%endif + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp t0b ; parity of top_seed + shr seed, 16 + shl t0d, 16 + test seeb, seeh + setp t0b ; parity of cur_seed + or r6d, 0x00010001 + xor t0d, r6d + mov seed, t0d + ror seed, 1 ; updated (cur_seed << 16) | top_seed +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, unused1, top_offxy, unused2, luma, lstride + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + +%if ARCH_X86_32 + DEFINE_ARGS top_offxy, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, unused1, top_offxy, unused2, luma, lstride +%endif + movzx top_offxyd, offxyw +%if ARCH_X86_32 + mov [rsp+8*mmsize+1*gprsize], top_offxyd + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + shr offxyd, 16 + +%if %2 == 0 +%%loop_x_odd_v_overlap: +%endif +%if %3 == 0 +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m2, [PIC_ptr(pw_27_17_17_27)] +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y_v_overlap: + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r0, [rsp+mmsize*8+gprsize*1] ; top_offxy + movu m5, [grain_lutq+r0*2] +%else + movu m5, [grain_lutq+top_offxyq*2] +%endif + punpckhwd m7, m5, m3 + punpcklwd m5, m3 ; {top/cur interleaved} + REPX {pmaddwd x, m2}, m7, m5 +%if %1 +%if ARCH_X86_32 + mov r5, r5m +%endif + REPX {paddd x, [PIC_ptr(pd_16)]}, m7, m5 +%else + REPX {paddd x, m14}, m7, m5 +%endif + REPX {psrad x, 5}, m7, m5 + packssdw m3, m5, m7 + pmaxsw m3, m8 + pminsw m3, m9 + + ; grain = grain_lut[offy+y][offx+x] + movu m4, [grain_lutq+offxyq*2+16] +%if ARCH_X86_32 + movu m5, [grain_lutq+r0*2+16] +%else + movu m5, [grain_lutq+top_offxyq*2+16] +%endif + punpckhwd m7, m5, m4 + punpcklwd m5, m4 ; {top/cur interleaved} + REPX {pmaddwd x, m2}, m7, m5 +%if %1 + REPX {paddd x, [PIC_ptr(pd_16)]}, m7, m5 +%else + REPX {paddd x, m14}, m7, m5 +%endif + REPX {psrad x, 5}, m7, m5 + packssdw m4, m5, m7 + pmaxsw m4, m8 + pminsw m4, m9 + + ; src + mova m0, [srcq] + mova m1, [srcq+16] + + ; luma_src + pxor mzero, mzero +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, luma, grain_lut + + mov lumaq, r9mp +%endif + mova m5, [lumaq+ 0] + mova m6, [lumaq+(16<<%2)] +%if %2 + phaddw m5, [lumaq+16] + phaddw m6, [lumaq+48] +%endif +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif +%if %2 + pavgw m5, mzero + pavgw m6, mzero +%endif + +%if %1 + punpckhwd m7, m5, m0 + punpcklwd m5, m0 + REPX {pmaddwd x, m14}, m7, m5 + REPX {psrad x, 6}, m7, m5 + packssdw m5, m7 + punpckhwd m7, m6, m1 + punpcklwd m6, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m7, m6 + REPX {psrad x, 6}, m7, m6 + packssdw m6, m7 + pxor mzero, mzero + REPX {paddw x, m15}, m5, m6 + REPX {pmaxsw x, mzero}, m5, m6 + REPX {pminsw x, m10}, m5, m6 ; clip_pixel() +%else + REPX {pand x, m10}, m5, m6 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m5, scalingq-1, r0, r5, 8, 1 + vpgatherdw m5, m6, scalingq-1, r0, r5, 8, 1 +%else + vpgatherdw m7, m5, scalingq-1, r10, r12, 8, 1 + vpgatherdw m5, m6, scalingq-1, r10, r12, 8, 1 +%endif + REPX {psrlw x, 8}, m7, m5 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + REPX {pmullw x, m11}, m7, m5 + pmulhrsw m3, m7 + pmulhrsw m4, m5 + + ; dst = clip_pixel(src, noise) + paddw m0, m3 + paddw m1, m4 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+ 0], m0 + mova [dstq+16], m1 + + dec hw + jle %%end_y_v_overlap +%if ARCH_X86_32 + add srcq, r2mp + add dstq, r2mp + mov dstmp, dstq +%else + add srcq, r13mp + add dstq, r13mp + add lumaq, lstrideq +%endif + add grain_lutq, 82*2 +%if %3 + jmp %%loop_y +%else + btc hd, 16 + jc %%loop_y +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m2, [PIC_ptr(pw_27_17_17_27)+4] + jmp %%loop_y_v_overlap +%endif + +%%end_y_v_overlap: +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, w, luma, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end_hv +%if ARCH_X86_32 + mov srcq, r1mp +%else + mov srcq, r10mp +%endif + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] +%if ARCH_X86_32 + mov r0mp, dstq + mov r9mp, lumaq + mov r4m, wq +%endif + +%if %2 + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap +%else + btc dword r8m, 2 + jc %%loop_x_hv_overlap + add offxyd, 16 +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r11d, 16 +%endif + jmp %%loop_x_odd_v_overlap +%endif + +%%loop_x_hv_overlap: +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, w, picptr, grain_lut + + mov t0d, [rsp+mmsize*8+gprsize*1] ; top_offxy + add offxyd, 16 + add t0d, 16 + mov [rsp+mmsize*8+gprsize*0], offxyd ; left_offxyd + mov [rsp+mmsize*8+gprsize*2], t0d ; topleft_offxyd + + DEFINE_ARGS dst, src, scaling, see, w, picptr, grain_lut + + mov seed, r3m + xor t0d, t0d +%else + ; we assume from the block above that bits 8-15 of r7d are zero'ed +%endif + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp t0b ; parity of top_seed + shr seed, 16 + shl t0d, 16 + test seeb, seeh + setp t0b ; parity of cur_seed + or r6d, 0x00010001 + xor t0d, r6d + mov seed, t0d + ror seed, 1 ; updated (cur_seed << 16) | top_seed +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy, luma, lstride + + lea topleft_offxyq, [top_offxyq+16] + lea left_offxyq, [offyq+16] + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, top_offxy +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy, luma, lstride +%endif + movzx top_offxyd, offxyw +%if ARCH_X86_32 + mov [rsp+8*mmsize+1*gprsize], top_offxyd + + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + shr offxyd, 16 + +%if %3 == 0 +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m2, [PIC_ptr(pw_27_17_17_27)] +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y_hv_overlap: + ; grain = grain_lut[offy+y][offx+x] +%if ARCH_X86_32 + mov r5, [rsp+8*mmsize+0*gprsize] ; left_offxy + mov r0, [rsp+8*mmsize+1*gprsize] ; top_offxy + movd m5, [grain_lutq+r5*2] +%else + movd m5, [grain_lutq+left_offxyq*2] +%endif + movu m7, [grain_lutq+offxyq*2] +%if ARCH_X86_32 + mov r5, [rsp+8*mmsize+2*gprsize] + movu m4, [grain_lutq+r0*2] +%if %2 + pinsrw m5, [grain_lutq+r5*2], 2 +%else + movd m3, [grain_lutq+r5*2] +%endif +%else + movu m4, [grain_lutq+top_offxyq*2] +%if %2 + pinsrw m5, [grain_lutq+topleft_offxyq*2], 2 ; { left, _, top/left } +%else + movd m3, [grain_lutq+topleft_offxyq*2] +%endif +%endif +%if %2 == 0 + punpckldq m5, m3 +%endif + punpckldq m3, m7, m4 ; { cur0/1,top0/1,cur2/3,top2/3 } + punpcklwd m5, m3 ; { left/cur0,_/cur1,topleft/top0,_/top1 } +%if %1 +%if ARCH_X86_32 + mov r5, r5m +%endif +%if %2 + movddup m0, [PIC_ptr(pw_23_22)] +%else + movddup m0, [PIC_ptr(pw_27_17_17_27)] +%endif +%else + pshufd m0, m15, q1010 +%endif + pmaddwd m5, m0 +%if %1 + paddd m5, [PIC_ptr(pd_16)] +%else + paddd m5, m14 +%endif + psrad m5, 5 + packssdw m5, m5 + pmaxsw m5, m8 + pminsw m5, m9 + shufps m5, m3, q3210 ; cur0/1,top0/1,cur2/3,top2/3 + shufps m3, m5, m7, q3220 ; cur0-7 post-h_filter + shufps m5, m4, q3231 ; top0-7 post-h_filter + + punpckhwd m7, m5, m3 + punpcklwd m5, m3 ; {top/cur interleaved} + REPX {pmaddwd x, m2}, m7, m5 +%if %1 + REPX {paddd x, [PIC_ptr(pd_16)]}, m5, m7 +%else + REPX {paddd x, m14}, m5, m7 +%endif + REPX {psrad x, 5}, m5, m7 + packssdw m3, m5, m7 + pmaxsw m3, m8 + pminsw m3, m9 + + ; right half + movu m4, [grain_lutq+offxyq*2+16] +%if ARCH_X86_32 + movu m0, [grain_lutq+r0*2+16] +%else + movu m0, [grain_lutq+top_offxyq*2+16] +%endif + punpckhwd m1, m0, m4 + punpcklwd m0, m4 ; {top/cur interleaved} + REPX {pmaddwd x, m2}, m1, m0 +%if %1 + REPX {paddd x, [PIC_ptr(pd_16)]}, m1, m0 +%else + REPX {paddd x, m14}, m1, m0 +%endif + REPX {psrad x, 5}, m1, m0 + packssdw m4, m0, m1 + pmaxsw m4, m8 + pminsw m4, m9 + + ; src + mova m0, [srcq] + mova m1, [srcq+16] + + ; luma_src + pxor mzero, mzero +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, luma, grain_lut + + mov lumaq, r9mp +%endif + mova m6, [lumaq+ 0] + mova m5, [lumaq+(16<<%2)] +%if %2 + phaddw m6, [lumaq+16] + phaddw m5, [lumaq+48] +%endif +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif +%if %2 + pavgw m6, mzero + pavgw m5, mzero +%endif + +%if %1 + punpckhwd m7, m6, m0 + punpcklwd m6, m0 + REPX {pmaddwd x, m14}, m7, m6 + REPX {psrad x, 6}, m7, m6 + packssdw m6, m7 + punpckhwd m7, m5, m1 + punpcklwd m5, m1 ; { luma, chroma } + REPX {pmaddwd x, m14}, m7, m5 + REPX {psrad x, 6}, m7, m5 + packssdw m5, m7 + pxor mzero, mzero + REPX {paddw x, m15}, m6, m5 + REPX {pmaxsw x, mzero}, m6, m5 + REPX {pminsw x, m10}, m6, m5 ; clip_pixel() +%else + REPX {pand x, m10}, m6, m5 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m6, scalingq-1, r0, r5, 8, 1 + vpgatherdw m6, m5, scalingq-1, r0, r5, 8, 1 +%else +%if %3 == 0 + ; register shortage :) + push r12 +%endif + vpgatherdw m7, m6, scalingq-1, r2, r12, 8, 1 + vpgatherdw m6, m5, scalingq-1, r2, r12, 8, 1 +%if %3 == 0 + pop r12 +%endif +%endif + REPX {psrlw x, 8}, m7, m6 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + REPX {pmullw x, m11}, m7, m6 + pmulhrsw m3, m7 + pmulhrsw m4, m6 + + ; dst = clip_pixel(src, noise) + paddw m0, m3 + paddw m1, m4 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + movifnidn dstq, dstmp + mova [dstq+ 0], m0 + mova [dstq+16], m1 + +%if ARCH_X86_32 + add srcq, r2mp + add dstq, r2mp + mov dstmp, dstq +%else + add srcq, r13mp + add dstq, r13mp + add lumaq, lstrideq +%endif + add grain_lutq, 82*2 + dec hw +%if %3 + jg %%loop_y_h_overlap +%else + jle %%end_y_hv_overlap + btc hd, 16 + jc %%loop_y_h_overlap +%if ARCH_X86_32 + mov r5, r5m +%endif + SPLATD m2, [PIC_ptr(pw_27_17_17_27)+4] + jmp %%loop_y_hv_overlap +%%end_y_hv_overlap: +%endif +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, w, luma, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end_hv +%if ARCH_X86_32 + mov srcq, r1mp +%else + mov srcq, r10mp +%endif + mov dstq, r11mp + mov lumaq, r12mp + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + lea lumaq, [lumaq+wq*(2<<%2)] +%if ARCH_X86_32 + mov dstmp, dstq + mov r9mp, lumaq + mov r4m, wq +%endif +%if %2 + jmp %%loop_x_hv_overlap +%else + or dword r8m, 4 + add offxyd, 16 +%if ARCH_X86_32 + add dword [rsp+8*mmsize+1*gprsize], 16 +%else + add r11d, 16 ; top_offxy += 16 +%endif + jmp %%loop_x_odd_v_overlap +%endif + +%%end_hv: + RET +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 + +%if STACK_ALIGNMENT < mmsize +DECLARE_ARG 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 +%endif +%endmacro + +FGUV_FN 420, 1, 1 +FGUV_FN 422, 1, 0 +FGUV_FN 444, 0, 0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2107 @@ +; Copyright © 2019-2022, VideoLAN and dav1d authors +; Copyright © 2019-2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 +pb_mask: db 0,128,128, 0,128, 0, 0,128,128, 0, 0,128, 0,128,128, 0 +gen_shufE: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +gen_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +gen_shufB: db 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11 +gen_shufC: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +gen_shufD: db 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15 +; note: the order of (some of) the following constants matter +pb_27_17: times 2 db 27, 17 +byte_blend: db 0, 0, 0, -1 +pb_27_17_17_27: db 27, 17, 17, 27, 0, 32, 0, 32 +pb_17_27: times 2 db 17, 27 +pb_1: times 4 db 1 +pb_23_22: db 23, 22, 0, 32, 0, 32, 0, 32 +next_upperbit_mask: dw 0x100B, 0x2016, 0x402C, 0x8058 +pw_seed_xor: times 2 dw 0xb524 + times 2 dw 0x49d8 +fg_min: times 4 db 0 + times 4 db 16 +fg_max: times 4 db 255 + times 4 db 240 + times 4 db 235 +pd_m65536: dd -65536 +pw_8: times 2 dw 8 +pw_1024: times 2 dw 1024 +hmul_bits: dw 32768, 16384, 8192, 4096 +round: dw 2048, 1024, 512 +mul_bits: dw 256, 128, 64, 32, 16 +round_vals: dw 32, 64, 128, 256, 512 +pw_1: dw 1 + +%macro JMP_TABLE 2-* + %1_8bpc_%2_table: + %xdefine %%base %1_8bpc_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %rep %0 - 2 + dd %%prefix %+ .ar%3 - %%base + %rotate 1 + %endrep +%endmacro + +JMP_TABLE generate_grain_y, avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_420, avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_422, avx2, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_444, avx2, 0, 1, 2, 3 + +SECTION .text + +INIT_YMM avx2 +cglobal generate_grain_y_8bpc, 2, 9, 8, buf, fg_data +%define base r4-generate_grain_y_8bpc_avx2_table + lea r4, [generate_grain_y_8bpc_avx2_table] + vpbroadcastw xm0, [fg_dataq+FGData.seed] + mov r6d, [fg_dataq+FGData.grain_scale_shift] + movq xm1, [base+next_upperbit_mask] + movsxd r5, [fg_dataq+FGData.ar_coeff_lag] + movq xm4, [base+mul_bits] + movq xm5, [base+hmul_bits] + mov r7, -73*82 + mova xm6, [base+pb_mask] + sub bufq, r7 + vpbroadcastw xm7, [base+round+r6*2] + lea r6, [gaussian_sequence] + movsxd r5, [r4+r5*4] +.loop: + pand xm2, xm0, xm1 + psrlw xm3, xm2, 10 + por xm2, xm3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw xm2, xm4 ; bits 0x0f00 are set + pmulhuw xm0, xm5 + pshufb xm3, xm6, xm2 ; set 15th bit for next 4 seeds + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm2, xm0 ; aggregate each bit into next seed's high bit + por xm3, xm2 ; 4 next output seeds + pshuflw xm0, xm3, q3333 + psrlw xm3, 5 + pand xm2, xm0, xm1 + movq r2, xm3 + psrlw xm3, xm2, 10 + por xm2, xm3 + pmullw xm2, xm4 + pmulhuw xm0, xm5 + movzx r3d, r2w + pshufb xm3, xm6, xm2 + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm0, xm2 + movd xm2, [r6+r3*2] + rorx r3, r2, 32 + por xm3, xm0 + shr r2d, 16 + pinsrw xm2, [r6+r2*2], 1 + pshuflw xm0, xm3, q3333 + movzx r2d, r3w + psrlw xm3, 5 + pinsrw xm2, [r6+r2*2], 2 + shr r3d, 16 + movq r2, xm3 + pinsrw xm2, [r6+r3*2], 3 + movzx r3d, r2w + pinsrw xm2, [r6+r3*2], 4 + rorx r3, r2, 32 + shr r2d, 16 + pinsrw xm2, [r6+r2*2], 5 + movzx r2d, r3w + pinsrw xm2, [r6+r2*2], 6 + shr r3d, 16 + pinsrw xm2, [r6+r3*2], 7 + pmulhrsw xm2, xm7 + packsswb xm2, xm2 + movq [bufq+r7], xm2 + add r7, 8 + jl .loop + + ; auto-regression code + add r5, r4 + jmp r5 + +.ar1: + DEFINE_ARGS buf, fg_data, cf3, shift, val3, min, max, x, val0 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_y+3] + movd xm5, [fg_dataq+FGData.ar_coeffs_y] + mova xm2, [base+gen_shufC] + DEFINE_ARGS buf, h, cf3, shift, val3, min, max, x, val0 + pinsrb xm5, [base+pb_1], 3 + vpbroadcastw xm3, [base+round_vals+shiftq*2-12] ; rnd + pmovsxbw xm5, xm5 + pshufd xm4, xm5, q0000 + pshufd xm5, xm5, q1111 + sub bufq, 82*73-(82*3+79) + mov hd, 70 + mov mind, -128 + mov maxd, 127 +.y_loop_ar1: + mov xq, -76 + movsx val3d, byte [bufq+xq-1] +.x_loop_ar1: + pmovsxbw xm1, [bufq+xq-82-3] + pshufb xm0, xm1, xm2 + punpckhwd xm1, xm3 + pmaddwd xm0, xm4 + pmaddwd xm1, xm5 + paddd xm0, xm1 +.x_loop_ar1_inner: + movd val0d, xm0 + psrldq xm0, 4 + imul val3d, cf3d + add val3d, val0d + movsx val0d, byte [bufq+xq] + sarx val3d, val3d, shiftd + add val3d, val0d + cmp val3d, maxd + cmovns val3d, maxd + cmp val3d, mind + cmovs val3d, mind + mov [bufq+xq], val3b + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xb, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 +.x_loop_ar1_end: + add bufq, 82 + dec hd + jg .y_loop_ar1 +.ar0: + RET + +.ar2: +%if WIN64 + ; xmm6 and xmm7 already saved + %assign xmm_regs_used 16 + %assign stack_size_padded 168 + SUB rsp, stack_size_padded + movaps [rsp+16*2], xmm8 + movaps [rsp+16*3], xmm9 + movaps [rsp+16*4], xmm10 + movaps [rsp+16*5], xmm11 + movaps [rsp+16*6], xmm12 + movaps [rsp+16*7], xmm13 + movaps [rsp+16*8], xmm14 + movaps [rsp+16*9], xmm15 +%endif + DEFINE_ARGS buf, fg_data, h, x + mov r6d, [fg_dataq+FGData.ar_coeff_shift] + pmovsxbw xm7, [fg_dataq+FGData.ar_coeffs_y+0] ; cf0-7 + movd xm9, [fg_dataq+FGData.ar_coeffs_y+8] ; cf8-11 + vpbroadcastd xm10, [base+round_vals-14+r6*2] + movd xm11, [base+byte_blend+1] + pmovsxbw xm9, xm9 + pshufd xm4, xm7, q0000 + mova xm12, [base+gen_shufA] + pshufd xm5, xm7, q3333 + mova xm13, [base+gen_shufB] + pshufd xm6, xm7, q1111 + mova xm14, [base+gen_shufC] + pshufd xm7, xm7, q2222 + mova xm15, [base+gen_shufD] + pshufd xm8, xm9, q0000 + psrld xm10, 16 + pshufd xm9, xm9, q1111 + sub bufq, 82*73-(82*3+79) + mov hd, 70 +.y_loop_ar2: + mov xq, -76 +.x_loop_ar2: + pmovsxbw xm0, [bufq+xq-82*2-2] ; y=-2,x=[-2,+5] + pmovsxbw xm1, [bufq+xq-82*1-2] ; y=-1,x=[-2,+5] + pshufb xm2, xm0, xm12 + pmaddwd xm2, xm4 + pshufb xm3, xm1, xm13 + pmaddwd xm3, xm5 + paddd xm2, xm3 + pshufb xm3, xm0, xm14 + pmaddwd xm3, xm6 + punpckhqdq xm0, xm0 + punpcklwd xm0, xm1 + pmaddwd xm0, xm7 + pshufb xm1, xm15 + pmaddwd xm1, xm8 + paddd xm2, xm10 + paddd xm2, xm3 + paddd xm0, xm1 + paddd xm2, xm0 + movq xm0, [bufq+xq-2] ; y=0,x=[-2,+5] +.x_loop_ar2_inner: + pmovsxbw xm1, xm0 + pmaddwd xm3, xm9, xm1 + psrldq xm1, 4 ; y=0,x=0 + paddd xm3, xm2 + psrldq xm2, 4 ; shift top to next pixel + psrad xm3, [fg_dataq+FGData.ar_coeff_shift] + ; don't packssdw since we only care about one value + paddw xm3, xm1 + packsswb xm3, xm3 + pextrb [bufq+xq], xm3, 0 + pslldq xm3, 2 + vpblendvb xm0, xm3, xm11 + psrldq xm0, 1 + inc xq + jz .x_loop_ar2_end + test xb, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 +.x_loop_ar2_end: + add bufq, 82 + dec hd + jg .y_loop_ar2 + RET + +INIT_YMM avx2 +.ar3: +%if WIN64 + ; xmm6 and xmm7 already saved + %assign stack_offset 16 + ALLOC_STACK 16*14 + %assign stack_size stack_size - 16*4 + %assign xmm_regs_used 12 + movaps [rsp+16*12], xmm8 + movaps [rsp+16*13], xmm9 + movaps [rsp+16*14], xmm10 + movaps [rsp+16*15], xmm11 +%else + ALLOC_STACK 16*12 +%endif + mov r6d, [fg_dataq+FGData.ar_coeff_shift] + movd xm11, [base+byte_blend] + pmovsxbw m1, [fg_dataq+FGData.ar_coeffs_y+ 0] ; cf0-15 + pmovsxbw xm2, [fg_dataq+FGData.ar_coeffs_y+16] ; cf16-23 + pshufd m0, m1, q0000 + mova [rsp+16* 0], m0 + pshufd m0, m1, q1111 + mova [rsp+16* 2], m0 + pshufd m0, m1, q2222 + mova [rsp+16* 4], m0 + pshufd m1, m1, q3333 + mova [rsp+16* 6], m1 + pshufd xm0, xm2, q0000 + mova [rsp+16* 8], xm0 + pshufd xm0, xm2, q1111 + mova [rsp+16* 9], xm0 + psrldq xm7, xm2, 10 + mova m8, [base+gen_shufA] + pinsrw xm2, [base+pw_1], 5 + mova m9, [base+gen_shufC] + pshufd xm2, xm2, q2222 + movu m10, [base+gen_shufE] + vpbroadcastw xm6, [base+round_vals-12+r6*2] + pinsrw xm7, [base+round_vals+r6*2-10], 3 + mova [rsp+16*10], xm2 + DEFINE_ARGS buf, fg_data, h, x + sub bufq, 82*73-(82*3+79) + mov hd, 70 +.y_loop_ar3: + mov xq, -76 +.x_loop_ar3: + movu xm5, [bufq+xq-82*3-3] ; y=-3,x=[-3,+12] + vinserti128 m5, [bufq+xq-82*2-3], 1 ; y=-2,x=[-3,+12] + movu xm4, [bufq+xq-82*1-3] ; y=-1,x=[-3,+12] + punpcklbw m3, m5, m5 + punpckhwd m5, m4 + psraw m3, 8 + punpcklbw m5, m5 + psraw m5, 8 + punpcklbw xm4, xm4 + psraw xm4, 8 + pshufb m0, m3, m8 + pmaddwd m0, [rsp+16*0] + pshufb m1, m3, m9 + pmaddwd m1, [rsp+16*2] + shufps m2, m3, m5, q1032 + paddd m0, m1 + pshufb m1, m2, m8 + vperm2i128 m3, m4, 0x21 + pmaddwd m1, [rsp+16*4] + shufps xm2, xm3, q1021 + vpblendd m2, m3, 0xf0 + pshufb m2, m10 + paddd m0, m1 + pmaddwd m2, [rsp+16*6] + pshufb xm1, xm4, xm9 + pmaddwd xm1, [rsp+16*8] + shufps xm4, xm5, q1132 + paddd m0, m2 + pshufb xm2, xm4, xm8 + pshufd xm4, xm4, q2121 + pmaddwd xm2, [rsp+16*9] + punpcklwd xm4, xm6 + pmaddwd xm4, [rsp+16*10] + vextracti128 xm3, m0, 1 + paddd xm0, xm1 + movq xm1, [bufq+xq-3] ; y=0,x=[-3,+4] + paddd xm2, xm4 + paddd xm0, xm2 + paddd xm0, xm3 +.x_loop_ar3_inner: + pmovsxbw xm2, xm1 + pmaddwd xm2, xm7 + pshufd xm3, xm2, q1111 + paddd xm2, xm0 ; add top + paddd xm2, xm3 ; left+cur + psrldq xm0, 4 + psrad xm2, [fg_dataq+FGData.ar_coeff_shift] + ; don't packssdw since we only care about one value + packsswb xm2, xm2 + pextrb [bufq+xq], xm2, 0 + pslldq xm2, 3 + vpblendvb xm1, xm2, xm11 + psrldq xm1, 1 + inc xq + jz .x_loop_ar3_end + test xb, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 +.x_loop_ar3_end: + add bufq, 82 + dec hd + jg .y_loop_ar3 + RET + +%macro GEN_GRAIN_UV_FN 3 ; ss_name, ss_x, ss_y +INIT_XMM avx2 +cglobal generate_grain_uv_%1_8bpc, 4, 10, 16, buf, bufy, fg_data, uv +%define base r4-generate_grain_uv_%1_8bpc_avx2_table + lea r4, [generate_grain_uv_%1_8bpc_avx2_table] + vpbroadcastw xm0, [fg_dataq+FGData.seed] + mov r6d, [fg_dataq+FGData.grain_scale_shift] + movq xm1, [base+next_upperbit_mask] + movq xm4, [base+mul_bits] + movq xm5, [base+hmul_bits] + mova xm6, [base+pb_mask] + vpbroadcastw xm7, [base+round+r6*2] + vpbroadcastd xm2, [base+pw_seed_xor+uvq*4] + pxor xm0, xm2 + lea r6, [gaussian_sequence] +%if %2 + mov r7d, 73-35*%3 + add bufq, 44 +.loop_y: + mov r5, -44 +%else + mov r5, -73*82 + sub bufq, r5 +%endif +.loop: + pand xm2, xm0, xm1 + psrlw xm3, xm2, 10 + por xm2, xm3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw xm2, xm4 ; bits 0x0f00 are set + pmulhuw xm0, xm5 + pshufb xm3, xm6, xm2 ; set 15th bit for next 4 seeds + psllq xm2, xm3, 30 + por xm2, xm3 + psllq xm3, xm2, 15 + por xm2, xm0 ; aggregate each bit into next seed's high bit + por xm2, xm3 ; 4 next output seeds + pshuflw xm0, xm2, q3333 + psrlw xm2, 5 + movq r8, xm2 + movzx r9d, r8w + movd xm2, [r6+r9*2] + rorx r9, r8, 32 + shr r8d, 16 + pinsrw xm2, [r6+r8*2], 1 + movzx r8d, r9w + pinsrw xm2, [r6+r8*2], 2 + shr r9d, 16 + pinsrw xm2, [r6+r9*2], 3 + pmulhrsw xm2, xm7 + packsswb xm2, xm2 + movd [bufq+r5], xm2 + add r5, 4 + jl .loop +%if %2 + add bufq, 82 + dec r7d + jg .loop_y +%endif + + ; auto-regression code + movsxd r6, [fg_dataq+FGData.ar_coeff_lag] + movsxd r6, [base+generate_grain_uv_%1_8bpc_avx2_table+r6*4] + add r6, r4 + jmp r6 + +INIT_YMM avx2 +.ar0: + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd xm2, [fg_dataq+FGData.ar_coeffs_uv+uvq] + movd xm3, [base+hmul_bits+shiftq*2] + DEFINE_ARGS buf, bufy, h + pmovsxbw xm2, xm2 +%if %2 + vpbroadcastd m7, [base+pb_1] + vpbroadcastw m6, [base+hmul_bits+2+%3*2] +%endif + vpbroadcastw m2, xm2 + vpbroadcastw m3, xm3 + pxor m12, m12 +%if %2 + sub bufq, 82*(73-35*%3)+82-(82*3+41) +%else + sub bufq, 82*70-3 +%endif + add bufyq, 3+82*3 + mov hd, 70-35*%3 +.y_loop_ar0: +%if %2 + ; first 32 pixels + movu xm4, [bufyq] + vinserti128 m4, [bufyq+32], 1 +%if %3 + movu xm0, [bufyq+82] + vinserti128 m0, [bufyq+82+32], 1 +%endif + movu xm5, [bufyq+16] + vinserti128 m5, [bufyq+48], 1 +%if %3 + movu xm1, [bufyq+82+16] + vinserti128 m1, [bufyq+82+48], 1 +%endif + pmaddubsw m4, m7, m4 +%if %3 + pmaddubsw m0, m7, m0 +%endif + pmaddubsw m5, m7, m5 +%if %3 + pmaddubsw m1, m7, m1 + paddw m4, m0 + paddw m5, m1 +%endif + pmulhrsw m4, m6 + pmulhrsw m5, m6 +%else + xor r3d, r3d + ; first 32x2 pixels +.x_loop_ar0: + movu m4, [bufyq+r3] + pcmpgtb m0, m12, m4 + punpckhbw m5, m4, m0 + punpcklbw m4, m0 +%endif + pmullw m4, m2 + pmullw m5, m2 + pmulhrsw m4, m3 + pmulhrsw m5, m3 +%if %2 + movu m1, [bufq] +%else + movu m1, [bufq+r3] +%endif + pcmpgtb m8, m12, m1 + punpcklbw m0, m1, m8 + punpckhbw m1, m8 + paddw m0, m4 + paddw m1, m5 + packsswb m0, m1 +%if %2 + movu [bufq], m0 +%else + movu [bufq+r3], m0 + add r3d, 32 + cmp r3d, 64 + jl .x_loop_ar0 +%endif + + ; last 6/12 pixels + movu xm4, [bufyq+32*2] +%if %2 +%if %3 + movu xm5, [bufyq+32*2+82] +%endif + pmaddubsw xm4, xm7, xm4 +%if %3 + pmaddubsw xm5, xm7, xm5 + paddw xm4, xm5 +%endif + movq xm0, [bufq+32] + pmulhrsw xm4, xm6 + pmullw xm4, xm2 + pmulhrsw xm4, xm3 + pcmpgtb xm5, xm12, xm0 + punpcklbw xm5, xm0, xm5 + paddw xm4, xm5 + packsswb xm4, xm4 + pblendw xm0, xm4, xm0, 1000b + movq [bufq+32], xm0 +%else + movu xm0, [bufq+64] + pcmpgtb xm1, xm12, xm4 + punpckhbw xm5, xm4, xm1 + punpcklbw xm4, xm1 + pmullw xm5, xm2 + pmullw xm4, xm2 + vpblendd xm1, xm3, xm12, 0x0c + pmulhrsw xm5, xm1 + pmulhrsw xm4, xm3 + pcmpgtb xm1, xm12, xm0 + punpckhbw xm8, xm0, xm1 + punpcklbw xm0, xm1 + paddw xm5, xm8 + paddw xm0, xm4 + packsswb xm0, xm5 + movu [bufq+64], xm0 +%endif + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar0 + RET + +INIT_XMM avx2 +.ar1: + DEFINE_ARGS buf, bufy, fg_data, uv, val3, cf3, min, max, x, shift + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_uv+uvq+3] + movd xm4, [fg_dataq+FGData.ar_coeffs_uv+uvq] + pinsrb xm4, [fg_dataq+FGData.ar_coeffs_uv+uvq+4], 3 + DEFINE_ARGS buf, bufy, h, val0, val3, cf3, min, max, x, shift + pmovsxbw xm4, xm4 + pshufd xm5, xm4, q1111 + pshufd xm4, xm4, q0000 + pmovsxwd xm3, [base+round_vals+shiftq*2-12] ; rnd +%if %2 + vpbroadcastd xm7, [base+pb_1] + vpbroadcastw xm6, [base+hmul_bits+2+%3*2] +%endif + vpbroadcastd xm3, xm3 +%if %2 + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*70-(82-3) +%endif + add bufyq, 79+82*3 + mov hd, 70-35*%3 + mov mind, -128 + mov maxd, 127 +.y_loop_ar1: + mov xq, -(76>>%2) + movsx val3d, byte [bufq+xq-1] +.x_loop_ar1: + pmovsxbw xm0, [bufq+xq-82-1] ; top/left +%if %2 + movq xm8, [bufyq+xq*2] +%if %3 + movq xm9, [bufyq+xq*2+82] +%endif +%endif + psrldq xm2, xm0, 2 ; top + psrldq xm1, xm0, 4 ; top/right +%if %2 + pmaddubsw xm8, xm7, xm8 +%if %3 + pmaddubsw xm9, xm7, xm9 + paddw xm8, xm9 +%endif + pmulhrsw xm8, xm6 +%else + pmovsxbw xm8, [bufyq+xq] +%endif + punpcklwd xm0, xm2 + punpcklwd xm1, xm8 + pmaddwd xm0, xm4 + pmaddwd xm1, xm5 + paddd xm0, xm1 + paddd xm0, xm3 +.x_loop_ar1_inner: + movd val0d, xm0 + psrldq xm0, 4 + imul val3d, cf3d + add val3d, val0d + sarx val3d, val3d, shiftd + movsx val0d, byte [bufq+xq] + add val3d, val0d + cmp val3d, maxd + cmovns val3d, maxd + cmp val3d, mind + cmovs val3d, mind + mov byte [bufq+xq], val3b + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xq, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 + +.x_loop_ar1_end: + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar1 + RET + +.ar2: + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + vpbroadcastw xm13, [base+round_vals-12+shiftq*2] + pmovsxbw xm7, [fg_dataq+FGData.ar_coeffs_uv+uvq+0] ; cf0-7 + pmovsxbw xm0, [fg_dataq+FGData.ar_coeffs_uv+uvq+8] ; cf8-12 + pinsrw xm0, [base+pw_1], 5 +%if %2 + vpbroadcastw xm12, [base+hmul_bits+2+%3*2] + vpbroadcastd xm11, [base+pb_1] +%endif + DEFINE_ARGS buf, bufy, fg_data, h, unused, x + pshufd xm4, xm7, q0000 + pshufd xm5, xm7, q3333 + pshufd xm6, xm7, q1111 + pshufd xm7, xm7, q2222 + pshufd xm8, xm0, q0000 + pshufd xm9, xm0, q1111 + pshufd xm10, xm0, q2222 +%if %2 + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*70-(82-3) +%endif + add bufyq, 79+82*3 + mov hd, 70-35*%3 +.y_loop_ar2: + mov xq, -(76>>%2) + +.x_loop_ar2: + pmovsxbw xm0, [bufq+xq-82*2-2] ; y=-2,x=[-2,+5] + pmovsxbw xm1, [bufq+xq-82*1-2] ; y=-1,x=[-2,+5] + pshufb xm2, xm0, [base+gen_shufA] + pmaddwd xm2, xm4 + pshufb xm3, xm1, [base+gen_shufB] + pmaddwd xm3, xm5 + paddd xm2, xm3 + pshufb xm3, xm0, [base+gen_shufC] + pmaddwd xm3, xm6 + punpckhqdq xm0, xm0 ; y=-2,x=[+2,+5] + punpcklwd xm0, xm1 + pmaddwd xm0, xm7 + pshufb xm1, [gen_shufD] + pmaddwd xm1, xm8 + paddd xm2, xm3 + paddd xm0, xm1 + paddd xm2, xm0 + +%if %2 + movq xm0, [bufyq+xq*2] +%if %3 + movq xm3, [bufyq+xq*2+82] +%endif + pmaddubsw xm0, xm11, xm0 +%if %3 + pmaddubsw xm3, xm11, xm3 + paddw xm0, xm3 +%endif + pmulhrsw xm0, xm12 +%else + pmovsxbw xm0, [bufyq+xq] +%endif + punpcklwd xm0, xm13 + pmaddwd xm0, xm10 + paddd xm2, xm0 + + movq xm0, [bufq+xq-2] ; y=0,x=[-2,+5] +.x_loop_ar2_inner: + pmovsxbw xm0, xm0 + pmaddwd xm3, xm0, xm9 + psrldq xm0, 2 + paddd xm3, xm2 + psrldq xm2, 4 ; shift top to next pixel + psrad xm3, [fg_dataq+FGData.ar_coeff_shift] + pslldq xm3, 2 + paddw xm3, xm0 + pblendw xm0, xm3, 00000010b + packsswb xm0, xm0 + pextrb [bufq+xq], xm0, 1 + inc xq + jz .x_loop_ar2_end + test xb, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 + +.x_loop_ar2_end: + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar2 + RET + +INIT_YMM avx2 +.ar3: + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + pmovsxbw m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 0] ; cf0-15 + pmovsxbw xm1, [fg_dataq+FGData.ar_coeffs_uv+uvq+16] ; cf16-23 + vpbroadcastb xm2, [fg_dataq+FGData.ar_coeffs_uv+uvq+24] ; cf24 [luma] + movd xm13, [base+round_vals-10+shiftq*2] + vpbroadcastd xm14, [base+round_vals-14+shiftq*2] + pshufd m6, m0, q0000 + pshufd m7, m0, q1111 + pshufd m8, m0, q2222 + pshufd m9, m0, q3333 + pshufd xm10, xm1, q0000 + pshufd xm11, xm1, q1111 + pshufhw xm12, xm1, q0000 + psraw xm2, 8 + palignr xm13, xm1, 10 + punpckhwd xm12, xm2 ; interleave luma cf + psrld xm14, 16 + DEFINE_ARGS buf, bufy, fg_data, h, unused, x +%if %2 + vpbroadcastw xm15, [base+hmul_bits+2+%3*2] + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*70-(82-3) +%endif + add bufyq, 79+82*3 + mov hd, 70-35*%3 +.y_loop_ar3: + mov xq, -(76>>%2) +.x_loop_ar3: + vbroadcasti128 m3, [bufq+xq-82*2-3] ; y=-2,x=[-3,+12 + palignr xm1, xm3, [bufq+xq-82*3-9], 6 ; y=-3,x=[-3,+12] + vbroadcasti128 m4, [bufq+xq-82*1-3] ; y=-1,x=[-3,+12] + vpblendd m3, m1, 0x0f + pxor m0, m0 + pcmpgtb m2, m0, m3 + pcmpgtb m0, m4 + punpcklbw m1, m3, m2 + punpckhbw m3, m2 + punpcklbw m2, m4, m0 + punpckhbw xm4, xm0 + pshufb m0, m1, [base+gen_shufA] + pmaddwd m0, m6 + pshufb m5, m1, [base+gen_shufC] + pmaddwd m5, m7 + shufps m1, m3, q1032 + paddd m0, m5 + pshufb m5, m1, [base+gen_shufA] + pmaddwd m5, m8 + shufps xm1, xm3, q2121 + vpblendd m1, m2, 0xf0 + pshufb m1, [base+gen_shufE] + pmaddwd m1, m9 + paddd m0, m5 + pshufb xm3, xm2, [base+gen_shufC] + paddd m0, m1 + pmaddwd xm3, xm10 + palignr xm1, xm4, xm2, 2 + punpckhwd xm1, xm2, xm1 + pmaddwd xm1, xm11 + palignr xm4, xm2, 12 + paddd xm3, xm1 +%if %2 + vpbroadcastd xm5, [base+pb_1] + movq xm1, [bufyq+xq*2] + pmaddubsw xm1, xm5, xm1 +%if %3 + movq xm2, [bufyq+xq*2+82] + pmaddubsw xm5, xm2 + paddw xm1, xm5 +%endif + pmulhrsw xm1, xm15 +%else + pmovsxbw xm1, [bufyq+xq] +%endif + punpcklwd xm4, xm1 + pmaddwd xm4, xm12 + movq xm1, [bufq+xq-3] ; y=0,x=[-3,+4] + vextracti128 xm2, m0, 1 + paddd xm0, xm14 + paddd xm3, xm4 + paddd xm0, xm3 + paddd xm0, xm2 +.x_loop_ar3_inner: + pmovsxbw xm1, xm1 + pmaddwd xm2, xm13, xm1 + pshuflw xm3, xm2, q1032 + paddd xm2, xm0 ; add top + paddd xm2, xm3 ; left+cur + psrldq xm0, 4 + psrad xm2, [fg_dataq+FGData.ar_coeff_shift] + psrldq xm1, 2 + ; don't packssdw, we only care about one value + punpckldq xm2, xm2 + pblendw xm1, xm2, 0100b + packsswb xm1, xm1 + pextrb [bufq+xq], xm1, 2 + inc xq + jz .x_loop_ar3_end + test xb, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 +.x_loop_ar3_end: + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar3 + RET +%endmacro + +INIT_YMM avx2 +cglobal fgy_32x32xn_8bpc, 6, 13, 15, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, see, overlap +%define base r9-pd_m65536 + lea r9, [pd_m65536] + mov r6d, [fg_dataq+FGData.scaling_shift] + mov r7d, [fg_dataq+FGData.clip_to_restricted_range] + mov sbyd, sbym + mov overlapd, [fg_dataq+FGData.overlap_flag] + vpbroadcastd m8, [base+pd_m65536] + vpbroadcastw m9, [base+mul_bits+r6*2-14] + vpbroadcastd m10, [base+fg_min+r7*4] + vpbroadcastd m11, [base+fg_max+r7*8] + vpbroadcastd m12, [base+pw_1024] + movq xm13, [base+pb_27_17_17_27] + test sbyd, sbyd + setnz r7b + pxor m7, m7 + test r7b, overlapb + jnz .vertical_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, overlap + + lea src_bakq, [srcq+wq] + neg wq + sub dstq, srcq + +.loop_x: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, overlap + + mov hd, hm + mov grain_lutq, grain_lutmp +.loop_y: + ; src + mova m2, [srcq] + punpcklbw m0, m2, m7 + punpckhbw m1, m2, m7 + + ; scaling[src] + pandn m4, m8, m0 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, m0, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m1 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m5, [grain_lutq+offxyq] + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 + mova [dstq+srcq], m0 + + add srcq, strideq + add grain_lutq, 82 + dec hd + jg .loop_y + + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + test overlapd, overlapd + jz .loop_x + + ; r8m = sbym + cmp dword r8m, 0 + jne .loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +.loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, left_offxy + + lea left_offxyd, [offyq+32] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offyd, [offyq+offxq*2+747] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, left_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y_h_overlap: + ; src + mova m2, [srcq] + punpcklbw m0, m2, m7 + punpckhbw m1, m2, m7 + + ; scaling[src] + pandn m4, m8, m0 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, m0, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m1 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m5, [grain_lutq+offxyq] + movd xm4, [grain_lutq+left_offxyq] + punpcklbw xm4, xm5 + pmaddubsw xm4, xm13, xm4 + pmulhrsw xm4, xm12 + packsswb xm4, xm4 + vpblendd m4, m5, 0xfe + punpckhbw m5, m7 + punpcklbw m4, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 + mova [dstq+srcq], m0 + + add srcq, strideq + add grain_lutq, 82 + dec hd + jg .loop_y_h_overlap + + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + + ; r8m = sbym + cmp dword r8m, 0 + jne .loop_x_hv_overlap + jmp .loop_x_h_overlap + +.vertical_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + unused, sby, see, overlap + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, overlap + + lea src_bakq, [srcq+wq] + neg wq + sub dstq, srcq + +.loop_x_v_overlap: + vpbroadcastd m14, [pb_27_17] + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, overlap, top_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +.loop_y_v_overlap: + ; src + mova m2, [srcq] + punpcklbw m0, m2, m7 + punpckhbw m1, m2, m7 + + ; scaling[src] + pandn m4, m8, m0 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, m0, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m1 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m6, [grain_lutq+offxyq] + movu m4, [grain_lutq+top_offxyq] + punpcklbw m5, m4, m6 + punpckhbw m4, m6 + pmaddubsw m5, m14, m5 + pmaddubsw m4, m14, m4 + pmulhrsw m5, m12 + pmulhrsw m4, m12 + packsswb m5, m4 + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 + mova [dstq+srcq], m0 + + add srcq, strideq + add grain_lutq, 82 + dec hb + jz .end_y_v_overlap + vpbroadcastd m14, [pb_17_27] ; swap weights for second v-overlap line + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + add hd, 0x80000000 + jnc .loop_y_v_overlap + jmp .loop_y +.end_y_v_overlap: + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap +.loop_x_hv_overlap: + vpbroadcastd m14, [pb_27_17] + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyd, [top_offxyq+32] + lea left_offxyd, [offyq+32] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*2+0x10001*747+32*82] + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +.loop_y_hv_overlap: + ; src + mova m2, [srcq] + punpcklbw m0, m2, m7 + punpckhbw m1, m2, m7 + + ; scaling[src] + pandn m4, m8, m0 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, m0, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m1 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + pblendw m2, m4, 0xaa + psrld m4, m1, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m4-2], m6 + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] + movu m6, [grain_lutq+offxyq] + movd xm7, [grain_lutq+left_offxyq] + movu m4, [grain_lutq+top_offxyq] + movd xm5, [grain_lutq+topleft_offxyq] + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw xm7, xm6 + punpcklbw xm5, xm4 + pmaddubsw xm7, xm13, xm7 + pmaddubsw xm5, xm13, xm5 + pmulhrsw xm7, xm12 + pmulhrsw xm5, xm12 + packsswb xm7, xm7 + packsswb xm5, xm5 + vpblendd m7, m6, 0xfe + vpblendd m5, m4, 0xfe + ; followed by v interpolation (top | cur -> cur) + punpckhbw m4, m6 + punpcklbw m5, m7 + pmaddubsw m4, m14, m4 + pmaddubsw m5, m14, m5 + pmulhrsw m4, m12 + pmulhrsw m5, m12 + pxor m7, m7 + packsswb m5, m4 + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 + mova [dstq+srcq], m0 + + add srcq, strideq + add grain_lutq, 82 + dec hb + jz .end_y_hv_overlap + vpbroadcastd m14, [pb_17_27] ; swap weights for second v-overlap line + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + add hd, 0x80000000 + jnc .loop_y_hv_overlap + jmp .loop_y_h_overlap +.end_y_hv_overlap: + add wq, 32 + lea srcq, [src_bakq+wq] + jl .loop_x_hv_overlap +.end: + RET + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +cglobal fguv_32x32xn_i%1_8bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, luma, overlap, uv_pl, is_id +%define base r11-pd_m65536 + lea r11, [pd_m65536] + mov r6d, [fg_dataq+FGData.scaling_shift] + mov r7d, [fg_dataq+FGData.clip_to_restricted_range] + mov r9d, is_idm + mov sbyd, sbym + mov overlapd, [fg_dataq+FGData.overlap_flag] + vpbroadcastd m8, [base+pd_m65536] + vpbroadcastw m9, [base+mul_bits+r6*2-14] + vpbroadcastd m10, [base+fg_min+r7*4] + shlx r7d, r7d, r9d + vpbroadcastd m11, [base+fg_max+r7*4] + vpbroadcastd m12, [base+pw_1024] + pxor m7, m7 + test sbyd, sbyd + setnz r7b + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_hor, ss_ver + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, \ + h, sby, see, overlap, uv_pl +%if %1 + mov r6d, uv_plm + vpbroadcastd m0, [base+pw_8] + vbroadcasti128 m14, [fg_dataq+FGData.uv_mult+r6*4] + vpbroadcastw m15, [fg_dataq+FGData.uv_offset+r6*4] + pshufb m14, m0 ; uv_luma_mult, uv_mult +%elif %2 + vpbroadcastq m15, [base+pb_23_22] +%else + vpbroadcastq xm15, [base+pb_27_17_17_27] +%endif +%if %3 + vpbroadcastw m13, [base+pb_23_22] +%elif %2 + pshufd m13, [base+pb_27_17], q0000 ; 8x27_17, 8x17_27 +%endif + test r7b, overlapb + jnz %%vertical_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + unused2, unused3, see, overlap, unused4, unused5, lstride + + mov lumaq, r9mp + lea r12, [srcq+wq] + lea r13, [dstq+wq] + lea r14, [lumaq+wq*(1+%2)] + mov r11mp, r12 + mov r12mp, r13 + mov lstrideq, r10mp + neg wq + +%%loop_x: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, overlap, unused1, unused2, lstride + + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, overlap, unused1, unused2, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y: + ; src +%if %2 + mova xm3, [lumaq+lstrideq*0+ 0] + vinserti128 m3, [lumaq+lstrideq*(1+%3) +0], 1 + vpbroadcastd m2, [pb_1] + mova xm0, [lumaq+lstrideq*0+16] + vinserti128 m0, [lumaq+lstrideq*(1+%3)+16], 1 + mova xm1, [srcq] + vinserti128 m1, [srcq+strideq], 1 + pmaddubsw m3, m2 + pmaddubsw m0, m2 + pavgw m3, m7 + pavgw m0, m7 +%else + mova m2, [lumaq] + mova m1, [srcq] +%endif +%if %1 +%if %2 + packuswb m2, m3, m0 ; luma +%endif + punpckhbw m3, m2, m1 + punpcklbw m2, m1 ; { luma, chroma } + pmaddubsw m3, m14 + pmaddubsw m2, m14 + psraw m3, 6 + psraw m2, 6 + paddw m3, m15 + paddw m2, m15 + packuswb m2, m3 ; pack+unpack = clip +%endif +%if %1 || %2 == 0 + punpcklbw m3, m2, m7 + punpckhbw m0, m2, m7 +%endif + + ; scaling[luma_src] + pandn m4, m8, m3 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m0 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + psrld m0, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m0-2], m6 + pblendw m2, m4, 0xaa + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] +%if %2 + movu xm5, [grain_lutq+offxyq+ 0] + vinserti128 m5, [grain_lutq+offxyq+82], 1 +%else + movu m5, [grain_lutq+offxyq] +%endif + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; unpack chroma_source + punpcklbw m0, m1, m7 + punpckhbw m1, m7 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 +%if %2 + mova [dstq], xm0 + vextracti128 [dstq+strideq], m0, 1 +%else + mova [dstq], m0 +%endif + +%if %2 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82<<%2 + sub hb, 1+%2 + jg %%loop_y + + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r14+wq*(1+%2)] + add srcq, wq + add dstq, wq + test overlapd, overlapd + jz %%loop_x + + ; r8m = sbym + cmp dword r8m, 0 + jne %%loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xEFF4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, unused1, unused2, lstride + + lea left_offxyd, [offyq+(32>>%2)] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, unused1, unused2, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y_h_overlap: + ; src +%if %2 + mova xm3, [lumaq+lstrideq*0+ 0] + vinserti128 m3, [lumaq+lstrideq*(1+%3)+ 0], 1 + vpbroadcastd m2, [pb_1] + mova xm0, [lumaq+lstrideq*0+16] + vinserti128 m0, [lumaq+lstrideq*(1+%3)+16], 1 + mova xm1, [srcq] + vinserti128 m1, [srcq+strideq], 1 + pmaddubsw m3, m2 + pmaddubsw m0, m2 + pavgw m3, m7 + pavgw m0, m7 +%else + mova m2, [lumaq] + mova m1, [srcq] +%endif +%if %1 +%if %2 + packuswb m2, m3, m0 ; luma +%endif + punpckhbw m3, m2, m1 + punpcklbw m2, m1 ; { luma, chroma } + pmaddubsw m3, m14 + pmaddubsw m2, m14 + psraw m3, 6 + psraw m2, 6 + paddw m3, m15 + paddw m2, m15 + packuswb m2, m3 ; pack+unpack = clip +%endif +%if %1 || %2 == 0 + punpcklbw m3, m2, m7 + punpckhbw m0, m2, m7 +%endif + + ; scaling[luma_src] + pandn m4, m8, m3 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m0 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + psrld m0, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m0-2], m6 + pblendw m2, m4, 0xaa + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] +%if %2 + movu xm5, [grain_lutq+offxyq+ 0] + vinserti128 m5, [grain_lutq+offxyq+82], 1 + movd xm4, [grain_lutq+left_offxyq+ 0] + vinserti128 m4, [grain_lutq+left_offxyq+82], 1 + punpcklbw m4, m5 +%if %1 + vpbroadcastq m0, [pb_23_22] + pmaddubsw m4, m0, m4 +%else + pmaddubsw m4, m15, m4 +%endif + pmulhrsw m4, m12 + packsswb m4, m4 + vpblendd m4, m5, 0xee +%else + movu m5, [grain_lutq+offxyq] + movd xm4, [grain_lutq+left_offxyq] + punpcklbw xm4, xm5 +%if %1 + movq xm0, [pb_27_17_17_27] + pmaddubsw xm4, xm0, xm4 +%else + pmaddubsw xm4, xm15, xm4 +%endif + pmulhrsw xm4, xm12 + packsswb xm4, xm4 + vpblendd m4, m5, 0xfe +%endif + punpckhbw m5, m7 + punpcklbw m4, m7 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; unpack chroma_source + punpcklbw m0, m1, m7 + punpckhbw m1, m7 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 +%if %2 + mova [dstq], xm0 + vextracti128 [dstq+strideq], m0, 1 +%else + mova [dstq], m0 +%endif + +%if %2 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82*(1+%2) + sub hb, 1+%2 + jg %%loop_y_h_overlap + + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r14+wq*(1+%2)] + add srcq, wq + add dstq, wq + + ; r8m = sbym + cmp dword r8m, 0 + jne %%loop_x_hv_overlap + jmp %%loop_x_h_overlap + +%%vertical_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, \ + sby, see, overlap, unused1, unused2, lstride + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + unused1, unused2, see, overlap, unused3, unused4, lstride + + mov lumaq, r9mp + lea r12, [srcq+wq] + lea r13, [dstq+wq] + lea r14, [lumaq+wq*(1+%2)] + mov r11mp, r12 + mov r12mp, r13 + mov lstrideq, r10mp + neg wq + +%%loop_x_v_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, overlap, top_offxy, unused, lstride + + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, overlap, top_offxy, unused, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +%if %2 == 0 + vpbroadcastd m13, [pb_27_17] +%endif +%%loop_y_v_overlap: + ; src +%if %2 + mova xm3, [lumaq+lstrideq*0+ 0] + vinserti128 m3, [lumaq+lstrideq*(1+%3)+ 0], 1 + vpbroadcastd m2, [pb_1] + mova xm0, [lumaq+lstrideq*0+16] + vinserti128 m0, [lumaq+lstrideq*(1+%3)+16], 1 + mova xm1, [srcq] + vinserti128 m1, [srcq+strideq], 1 + pmaddubsw m3, m2 + pmaddubsw m0, m2 + pavgw m3, m7 + pavgw m0, m7 +%else + mova m2, [lumaq] + mova m1, [srcq] +%endif +%if %1 +%if %2 + packuswb m2, m3, m0 ; luma +%endif + punpckhbw m3, m2, m1 + punpcklbw m2, m1 ; { luma, chroma } + pmaddubsw m3, m14 + pmaddubsw m2, m14 + psraw m3, 6 + psraw m2, 6 + paddw m3, m15 + paddw m2, m15 + packuswb m2, m3 ; pack+unpack = clip +%endif +%if %1 || %2 == 0 + punpcklbw m3, m2, m7 + punpckhbw m0, m2, m7 +%endif + + ; scaling[luma_src] + pandn m4, m8, m3 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m0 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + psrld m0, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m0-2], m6 + pblendw m2, m4, 0xaa + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] +%if %3 == 0 +%if %2 + movu xm0, [grain_lutq+offxyq] + vinserti128 m0, [grain_lutq+offxyq+82], 1 + movu xm4, [grain_lutq+top_offxyq] + vinserti128 m4, [grain_lutq+top_offxyq+82], 1 +%else + movu m0, [grain_lutq+offxyq] + movu m4, [grain_lutq+top_offxyq] +%endif + punpcklbw m5, m4, m0 + punpckhbw m4, m0 + pmaddubsw m5, m13, m5 + pmaddubsw m4, m13, m4 + pmulhrsw m5, m12 + pmulhrsw m4, m12 + packsswb m5, m4 +%else + movq xm4, [grain_lutq+offxyq] + vinserti128 m4, [grain_lutq+offxyq+8], 1 + movq xm5, [grain_lutq+top_offxyq] + vinserti128 m5, [grain_lutq+top_offxyq+8], 1 + punpcklbw m5, m4 + pmaddubsw m5, m13, m5 + pmulhrsw m5, m12 + vextracti128 xm4, m5, 1 + packsswb xm5, xm4 + ; only interpolate first line, insert second line unmodified + vinserti128 m5, [grain_lutq+offxyq+82], 1 +%endif + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; unpack chroma_source + punpcklbw m0, m1, m7 + punpckhbw m1, m7 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 +%if %2 + mova [dstq], xm0 + vextracti128 [dstq+strideq], m0, 1 +%else + mova [dstq], m0 +%endif + + sub hb, 1+%2 + jle %%end_y_v_overlap +%if %2 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82<<%2 +%if %2 == 0 + vpbroadcastd m13, [pb_17_27] + add hd, 0x80000000 + jnc %%loop_y_v_overlap +%endif + jmp %%loop_y + +%%end_y_v_overlap: + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r14+wq*(1+%2)] + add srcq, wq + add dstq, wq + + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap + +%%loop_x_hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy, lstride + + lea topleft_offxyd, [top_offxyq+(32>>%2)] + lea left_offxyd, [offyq+(32>>%2)] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy, lstride + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 +%if %2 == 0 + vpbroadcastd m13, [pb_27_17] +%endif +%%loop_y_hv_overlap: + ; src +%if %2 + mova xm3, [lumaq+lstrideq*0+ 0] + vinserti128 m3, [lumaq+lstrideq*(1+%3)+ 0], 1 + vpbroadcastd m2, [pb_1] + mova xm0, [lumaq+lstrideq*0+16] + vinserti128 m0, [lumaq+lstrideq*(1+%3)+16], 1 + mova xm1, [srcq] + vinserti128 m1, [srcq+strideq], 1 + pmaddubsw m3, m2 + pmaddubsw m0, m2 + pavgw m3, m7 + pavgw m0, m7 +%else + mova m2, [lumaq] + mova m1, [srcq] +%endif +%if %1 +%if %2 + packuswb m2, m3, m0 ; luma +%endif + punpckhbw m3, m2, m1 + punpcklbw m2, m1 ; { luma, chroma } + pmaddubsw m3, m14 + pmaddubsw m2, m14 + psraw m3, 6 + psraw m2, 6 + paddw m3, m15 + paddw m2, m15 + packuswb m2, m3 ; pack+unpack = clip +%endif +%if %1 || %2 == 0 + punpcklbw m3, m2, m7 + punpckhbw m0, m2, m7 +%endif + + ; scaling[luma_src] + pandn m4, m8, m3 + mova m6, m8 + vpgatherdd m2, [scalingq+m4-0], m8 + psrld m3, 16 + mova m8, m6 + vpgatherdd m4, [scalingq+m3-2], m6 + pandn m5, m8, m0 + mova m6, m8 + vpgatherdd m3, [scalingq+m5-0], m8 + psrld m0, 16 + mova m8, m6 + vpgatherdd m5, [scalingq+m0-2], m6 + pblendw m2, m4, 0xaa + pblendw m3, m5, 0xaa + + ; grain = grain_lut[offy+y][offx+x] +%if %2 + movu xm4, [grain_lutq+offxyq] + vinserti128 m4, [grain_lutq+offxyq+82], 1 + movd xm0, [grain_lutq+left_offxyq] + vinserti128 m0, [grain_lutq+left_offxyq+82], 1 + movd xm6, [grain_lutq+topleft_offxyq] +%if %3 + movq xm5, [grain_lutq+top_offxyq] + vinserti128 m5, [grain_lutq+top_offxyq+8], 1 +%else + vinserti128 m6, [grain_lutq+topleft_offxyq+82], 1 + movu xm5, [grain_lutq+top_offxyq] + vinserti128 m5, [grain_lutq+top_offxyq+82], 1 +%endif + + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw m0, m4 +%if %3 + punpcklbw xm6, xm5 +%else + punpcklbw m6, m5 +%endif + punpcklqdq m0, m6 +%if %1 + vpbroadcastq m6, [pb_23_22] + pmaddubsw m0, m6, m0 +%else + pmaddubsw m0, m15, m0 +%endif + pmulhrsw m0, m12 + packsswb m0, m0 + vpblendd m4, m0, 0x11 +%if %3 + pshuflw xm0, xm0, q1032 + vpblendd m5, m0, 0x01 +%else + pshuflw m0, m0, q1032 + vpblendd m5, m0, 0x11 +%endif +%else + movu m4, [grain_lutq+offxyq] + movd xm0, [grain_lutq+left_offxyq] + movu m5, [grain_lutq+top_offxyq] + movd xm6, [grain_lutq+topleft_offxyq] + punpcklbw xm0, xm4 + punpcklbw xm6, xm5 + punpcklqdq xm0, xm6 +%if %1 + vpbroadcastq xm6, [pb_27_17_17_27] + pmaddubsw xm0, xm6, xm0 +%else + pmaddubsw xm0, xm15, xm0 +%endif + pmulhrsw xm0, xm12 + packsswb xm0, xm0 + vpblendd m4, m0, 0x01 + pshuflw xm0, xm0, q1032 + vpblendd m5, m0, 0x01 +%endif + + ; followed by v interpolation (top | cur -> cur) +%if %3 + vpermq m0, m4, q3120 + punpcklbw m5, m0 + pmaddubsw m5, m13, m5 + pmulhrsw m5, m12 + vextracti128 xm0, m5, 1 + packsswb xm5, xm0 + vpblendd m5, m4, 0xf0 +%else + punpckhbw m0, m5, m4 + punpcklbw m5, m4 + pmaddubsw m4, m13, m0 + pmaddubsw m5, m13, m5 + pmulhrsw m4, m12 + pmulhrsw m5, m12 + packsswb m5, m4 +%endif + punpcklbw m4, m5, m7 + punpckhbw m5, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmaddubsw m2, m4 + pmaddubsw m3, m5 + pmulhrsw m2, m9 + pmulhrsw m3, m9 + + ; unpack chroma source + punpcklbw m0, m1, m7 + punpckhbw m1, m7 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + pmaxub m0, m10 + pminub m0, m11 +%if %2 + mova [dstq], xm0 + vextracti128 [dstq+strideq], m0, 1 +%else + mova [dstq], m0 +%endif + +%if %2 + lea srcq, [srcq+strideq*2] + lea dstq, [dstq+strideq*2] + lea lumaq, [lumaq+lstrideq*(2<<%3)] +%else + add srcq, strideq + add dstq, strideq + add lumaq, lstrideq +%endif + add grain_lutq, 82<<%2 + sub hb, 1+%2 +%if %2 + jg %%loop_y_h_overlap +%else + je %%end_y_hv_overlap + vpbroadcastd m13, [pb_17_27] + add hd, 0x80000000 + jnc %%loop_y_hv_overlap + jmp %%loop_y_h_overlap +%endif + +%%end_y_hv_overlap: + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r14+wq*(1+%2)] + add srcq, wq + add dstq, wq + jmp %%loop_x_hv_overlap +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 +.end: + RET +%endmacro + +GEN_GRAIN_UV_FN 420, 1, 1 +FGUV_FN 420, 1, 1 +GEN_GRAIN_UV_FN 422, 1, 0 +FGUV_FN 422, 1, 0 +GEN_GRAIN_UV_FN 444, 0, 0 +FGUV_FN 444, 0, 0 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,813 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +pb_even: db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 + db 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94 + db 96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126 +pb_odd: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + db 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95 + db 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127 +interleave_hl: db 8, 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7 +pb_27_17_17_27: db 27, 17, 17, 27, 0, 32, 0, 32 +pb_23_22_0_32: db 23, 22, 0, 32, 0, 32, 0, 32 +pb_27_17: times 2 db 27, 17 +pb_23_22: times 2 db 23, 22 +pw_8: times 2 dw 8 +pw_1024: times 2 dw 1024 +pb_17_27: times 2 db 17, 27 +fg_max: times 4 db 255 + times 4 db 240 + times 4 db 235 +fg_min: times 4 db 0 + times 4 db 16 +noise_rnd: times 2 dw 128 + times 2 dw 64 + times 2 dw 32 + times 2 dw 16 + +SECTION .text + +INIT_ZMM avx512icl +cglobal fgy_32x32xn_8bpc, 6, 13, 22, dst, src, stride, fg_data, w, scaling, \ + grain_lut, h, sby, see, overlap +%define base r11-fg_min + lea r11, [fg_min] + mov r6d, [fg_dataq+FGData.scaling_shift] + mov r7d, [fg_dataq+FGData.clip_to_restricted_range] + mov sbyd, sbym + mov overlapd, [fg_dataq+FGData.overlap_flag] + mov r12, 0x0000000f0000000f ; h_overlap mask + mova m0, [scalingq+64*0] + mova m1, [scalingq+64*1] + mova m2, [scalingq+64*2] + mova m3, [scalingq+64*3] + kmovq k1, r12 + vbroadcasti32x4 m4, [base+interleave_hl] + vpbroadcastd ym16, [base+pb_27_17] + vpbroadcastd m12, [base+pb_17_27] + vpbroadcastd m6, [base+noise_rnd+r6*4-32] + test sbyd, sbyd + setnz r6b + vpbroadcastd m7, [base+fg_min+r7*4] + vpbroadcastd m8, [base+fg_max+r7*8] + pxor m5, m5 + vpbroadcastd m9, [base+pw_1024] + vpbroadcastq m10, [base+pb_27_17_17_27] + vmovdqa64 m12{k1}, m16 + test r6b, overlapb + jnz .v_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, src_bak, w, offx, offy, \ + h, sby, see, overlap + + lea src_bakq, [srcq+wq] + neg wq + sub dstq, srcq +.loop_x: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offxd, [offyq+offxq*2+829] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, src_bak, w, offxy, grain_lut, \ + h, sby, see, overlap + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y: + movu ym21, [grain_lutq+offxyq-82] + vinserti32x8 m21, [grain_lutq+offxyq+ 0], 1 + call .add_noise + sub hb, 2 + jg .loop_y + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + test overlapd, overlapd + jz .loop_x + test sbyd, sbyd + jnz .hv_overlap + +.loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, src_bak, w, offx, offy, \ + h, sby, see, left_offxy + + rorx offyd, seed, 8 + mov left_offxyd, offxd ; previous column's offy*stride + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164 + lea offxd, [offyq+offxq*2+829] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, src_bak, w, offxy, grain_lut, \ + h, sby, see, left_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm +.loop_y_h_overlap: + movu ym20, [grain_lutq+offxyq-82] + vinserti32x8 m20, [grain_lutq+offxyq+ 0], 1 + movd xm19, [grain_lutq+left_offxyq-50] + vinserti32x4 m19, [grain_lutq+left_offxyq+32], 2 + punpcklbw m19, m20 + pmaddubsw m19, m10, m19 + pmulhrsw m19, m9 + punpckhbw m21, m20, m5 + packsswb m20{k1}, m19, m19 + punpcklbw m20, m5, m20 + call .add_noise_h + sub hb, 2 + jg .loop_y_h_overlap + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + test sbyd, sbyd + jnz .hv_overlap + jmp .loop_x_h_overlap + +.v_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, offy, offx, \ + h, sby, see, overlap + + movzx r6d, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, r6d, 173 * 0x00010001 + imul r6d, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add r6d, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and r6d, 0xff00ff00 + xor seed, r7d + xor seed, r6d ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, src_bak, w, offx, offy, \ + h, sby, see, overlap + + lea src_bakq, [srcq+wq] + neg wq + sub dstq, srcq + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offxd, [offyq+offxq*2+0x10001*829+32*82] + + DEFINE_ARGS dst, src, stride, src_bak, w, offxy, grain_lut, \ + h, sby, see, overlap, top_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + movu ym19, [grain_lutq+offxyq-82] + vinserti32x8 m19, [grain_lutq+offxyq+ 0], 1 + movu ym21, [grain_lutq+top_offxyq-82] + vinserti32x8 m21, [grain_lutq+top_offxyq+ 0], 1 + punpckhbw m20, m21, m19 + punpcklbw m21, m19 + call .add_noise_v + sub hb, 2 + jg .loop_y + add wq, 32 + jge .end + lea srcq, [src_bakq+wq] + + ; since fg_dataq.overlap is guaranteed to be set, we never jump back + ; to .v_overlap, and instead always fall-through to h+v overlap +.hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, src_bak, w, offx, offy, \ + h, sby, see, left_offxy, top_offxy, topleft_offxy + + mov topleft_offxyd, top_offxyd + rorx offyd, seed, 8 + mov left_offxyd, offxd + rorx offxd, seed, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offxd, [offyq+offxq*2+0x10001*829+32*82] + + DEFINE_ARGS dst, src, stride, src_bak, w, offxy, grain_lut, \ + h, sby, see, left_offxy, top_offxy, topleft_offxy + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + movu ym19, [grain_lutq+offxyq-82] + vinserti32x8 m19, [grain_lutq+offxyq+ 0], 1 + movd xm16, [grain_lutq+left_offxyq-50] + vinserti32x4 m16, [grain_lutq+left_offxyq+32], 2 + movu ym21, [grain_lutq+top_offxyq-82] + vinserti32x8 m21, [grain_lutq+top_offxyq+ 0], 1 + movd xm17, [grain_lutq+topleft_offxyq-50] + vinserti32x4 m17, [grain_lutq+topleft_offxyq+32], 2 + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw m16, m19 + pmaddubsw m16, m10, m16 + punpcklbw m17, m21 + pmaddubsw m17, m10, m17 + punpckhbw m20, m21, m19 + pmulhrsw m16, m9 + pmulhrsw m17, m9 + packsswb m19{k1}, m16, m16 + packsswb m21{k1}, m17, m17 + ; followed by v interpolation (top | cur -> cur) + punpcklbw m21, m19 + call .add_noise_v + sub hb, 2 + jg .loop_y_h_overlap + add wq, 32 + lea srcq, [src_bakq+wq] + jl .hv_overlap +.end: + RET +ALIGN function_align +.add_noise_v: + pmaddubsw m20, m12, m20 + pmaddubsw m21, m12, m21 + pmulhrsw m20, m9 + pmulhrsw m21, m9 + packsswb m21, m20 +.add_noise: + punpcklbw m20, m5, m21 + punpckhbw m21, m5 +.add_noise_h: + mova ym18, [srcq+strideq*0] + vinserti32x8 m18, [srcq+strideq*1], 1 + mova m19, m0 + punpcklbw m16, m18, m5 + vpermt2b m19, m18, m1 ; scaling[ 0..127] + vpmovb2m k2, m18 + punpckhbw m17, m18, m5 + vpermi2b m18, m2, m3 ; scaling[128..255] + vmovdqu8 m19{k2}, m18 ; scaling[src] + pshufb m19, m4 + pmaddubsw m18, m19, m20 + pmaddubsw m19, m21 + add grain_lutq, 82*2 + pmulhrsw m18, m6 ; noise + pmulhrsw m19, m6 + paddw m16, m18 + paddw m17, m19 + packuswb m16, m17 + pmaxub m16, m7 + pminub m16, m8 + mova [dstq+srcq], ym16 + add srcq, strideq + vextracti32x8 [dstq+srcq], m16, 1 + add srcq, strideq + ret + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +cglobal fguv_32x32xn_i%1_8bpc, 6, 14+%2, 22, dst, src, stride, fg_data, w, \ + scaling, grain_lut, h, sby, luma, \ + overlap, uv_pl, is_id, _, stride3 + lea r11, [fg_min] + mov r6d, [fg_dataq+FGData.scaling_shift] + mov r7d, [fg_dataq+FGData.clip_to_restricted_range] + mov r9d, is_idm + mov sbyd, sbym + mov overlapd, [fg_dataq+FGData.overlap_flag] +%if %2 + mov r12, 0x000f000f000f000f ; h_overlap mask + vpbroadcastq m10, [base+pb_23_22_0_32] + lea stride3q, [strideq*3] +%else + mov r12, 0x0000000f0000000f + vpbroadcastq m10, [base+pb_27_17_17_27] +%endif + mova m0, [scalingq+64*0] + mova m1, [scalingq+64*1] + mova m2, [scalingq+64*2] + mova m3, [scalingq+64*3] + kmovq k1, r12 + vbroadcasti32x4 m4, [base+interleave_hl] + vpbroadcastd m6, [base+noise_rnd+r6*4-32] + vpbroadcastd m7, [base+fg_min+r7*4] + shlx r7d, r7d, r9d + vpbroadcastd m8, [base+fg_max+r7*4] + test sbyd, sbyd + setnz r7b + vpbroadcastd m9, [base+pw_1024] + mova m11, [base+pb_even] + mova m12, [base+pb_odd] + pxor m5, m5 + mov r5, r10mp ; lstride + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_hor, ss_ver + DEFINE_ARGS dst, src, stride, fg_data, w, lstride, grain_lut, \ + h, sby, see, overlap, uv_pl, _, _, stride3 +%if %1 + mov r6d, uv_plm + vpbroadcastd m16, [base+pw_8] + vbroadcasti32x4 m14, [fg_dataq+FGData.uv_mult+r6*4] + vpbroadcastw m15, [fg_dataq+FGData.uv_offset+r6*4] + pshufb m14, m16 ; uv_luma_mult, uv_mult +%endif + test r7b, overlapb + jnz %%v_overlap + + imul seed, sbyd, (173 << 24) | 37 + add seed, (105 << 24) | 178 + rorx seed, seed, 24 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + offx, offy, see, overlap, _, _, _, stride3 + + mov lumaq, r9mp + lea r11, [srcq+wq] + lea r12, [dstq+wq] + lea r13, [lumaq+wq*(1+%2)] + mov r11mp, r11 + mov r12mp, r12 + neg wq + +%%loop_x: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + h, offxy, see, overlap, _, _, _, stride3 + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y: +%if %2 + movu xm21, [grain_lutq+offxyq+82*0] + vinserti128 ym21, [grain_lutq+offxyq+82*1], 1 + vinserti32x4 m21, [grain_lutq+offxyq+82*2], 2 + vinserti32x4 m21, [grain_lutq+offxyq+82*3], 3 +%else + movu ym21, [grain_lutq+offxyq+82*0] + vinserti32x8 m21, [grain_lutq+offxyq+82*1], 1 +%endif + call %%add_noise + sub hb, 2<<%2 + jg %%loop_y + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r13+wq*(1<<%2)] + add srcq, wq + add dstq, wq + test overlapd, overlapd + jz %%loop_x + cmp dword r8m, 0 ; sby + jne %%hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: + rorx r6, seeq, 1 + or seed, 0xeff4 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + offx, offy, see, left_offxy, _, _, _, stride3 + + lea left_offxyd, [offyq+(32>>%2)] ; previous column's offy*stride+offx + rorx offyd, seed, 8 + rorx offxq, seeq, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyd, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + h, offxy, see, left_offxy, _, _, _, stride3 + + mov grain_lutq, grain_lutmp + mov hd, hm +%%loop_y_h_overlap: +%if %2 + movu xm20, [grain_lutq+offxyq +82*0] + movd xm19, [grain_lutq+left_offxyq+82*0] + vinserti32x4 ym20, [grain_lutq+offxyq +82*1], 1 + vinserti32x4 ym19, [grain_lutq+left_offxyq+82*1], 1 + vinserti32x4 m20, [grain_lutq+offxyq +82*2], 2 + vinserti32x4 m19, [grain_lutq+left_offxyq+82*2], 2 + vinserti32x4 m20, [grain_lutq+offxyq +82*3], 3 + vinserti32x4 m19, [grain_lutq+left_offxyq+82*3], 3 +%else + movu ym20, [grain_lutq+offxyq + 0] + movd xm19, [grain_lutq+left_offxyq+ 0] + vinserti32x8 m20, [grain_lutq+offxyq +82], 1 + vinserti32x4 m19, [grain_lutq+left_offxyq+82], 2 +%endif + punpcklbw m19, m20 + pmaddubsw m19, m10, m19 + punpckhbw m21, m20, m5 + pmulhrsw m19, m9 + vpacksswb m20{k1}, m19, m19 + punpcklbw m20, m5, m20 + call %%add_noise_h + sub hb, 2<<%2 + jg %%loop_y_h_overlap + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r13+wq*(1<<%2)] + add srcq, wq + add dstq, wq + cmp dword r8m, 0 ; sby + jne %%hv_overlap + jmp %%loop_x_h_overlap + +%%v_overlap: + DEFINE_ARGS dst, src, stride, fg_data, w, lstride, grain_lut, \ + _, sby, see, overlap, _, _, _, stride3 + + movzx sbyd, sbyb + imul seed, [fg_dataq+FGData.seed], 0x00010001 + imul r7d, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add r7d, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and r7d, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, r7d + xor seed, sbyd ; (cur_seed << 16) | top_seed + +%if %3 + vpbroadcastd m13, [base+pb_23_22] + kxnorw k3, k3, k3 ; v_overlap mask +%elif %2 + vbroadcasti32x8 m13, [base+pb_27_17] + kxnord k3, k3, k3 + pshufd m13, m13, q0000 ; 8x27_17, 8x17_27 +%else + vpbroadcastd ym16, [base+pb_27_17] + vpbroadcastd m13, [base+pb_17_27] + vmovdqa64 m13{k1}, m16 +%endif + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + offx, offy, see, overlap, top_offxy, _, _, stride3 + + mov lumaq, r9mp + lea r11, [srcq+wq] + lea r12, [dstq+wq] + lea r13, [lumaq+wq*(1<<%2)] + mov r11mp, r11 + mov r12mp, r12 + neg wq + + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0x000f000f + and offxd, 0x000f000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + h, offxy, see, overlap, top_offxy, _, _, stride3 + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + +%if %3 + movu xm18, [grain_lutq+offxyq+82*0] + movu xm20, [grain_lutq+top_offxyq+82*0] + ; only interpolate first line, insert remaining line unmodified + vbroadcasti128 ym21, [grain_lutq+offxyq+82*1] + vinserti32x4 m21, [grain_lutq+offxyq+82*2], 2 + vinserti32x4 m21, [grain_lutq+offxyq+82*3], 3 + punpcklbw xm19, xm20, xm18 + punpckhbw xm20, xm18 +%elif %2 + movu xm18, [grain_lutq+offxyq+82*0] + vinserti128 ym18, [grain_lutq+offxyq+82*1], 1 + movu xm20, [grain_lutq+top_offxyq+82*0] + vinserti32x4 ym20, [grain_lutq+top_offxyq+82*1], 1 + vbroadcasti32x4 m21, [grain_lutq+offxyq+82*2] + vinserti32x4 m21, [grain_lutq+offxyq+82*3], 3 + punpcklbw ym19, ym20, ym18 + punpckhbw ym20, ym18 +%else + movu ym21, [grain_lutq+offxyq+82*0] + vinserti32x8 m21, [grain_lutq+offxyq+82*1], 1 + movu ym20, [grain_lutq+top_offxyq+82*0] + vinserti32x8 m20, [grain_lutq+top_offxyq+82*1], 1 +%endif + call %%add_noise_v + sub hb, 2<<%2 + jg %%loop_y + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r13+wq*(1<<%2)] + add srcq, wq + add dstq, wq + +%%hv_overlap: + ; we assume from the block above that bits 8-15 of r7d are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp r7b ; parity of top_seed + shr seed, 16 + shl r7d, 16 + test seeb, seeh + setp r7b ; parity of cur_seed + or r6d, 0x00010001 + xor r7d, r6d + rorx seed, r7d, 1 ; updated (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy, _, stride3 + + lea topleft_offxyd, [top_offxyq+(32>>%2)] + lea left_offxyd, [offyq+(32>>%2)] + rorx offyd, seed, 8 + rorx offxd, seed, 12 + and offyd, 0x000f000f + and offxd, 0x000f000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyd, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + + DEFINE_ARGS dst, src, stride, luma, w, lstride, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy, _, stride3 + + mov grain_lutq, grain_lutmp + mov hd, hm + movzx top_offxyd, offxyw + shr offxyd, 16 + +%if %2 + movu xm21, [grain_lutq+offxyq+82*0] + movd xm16, [grain_lutq+left_offxyq+82*0] + vinserti128 ym21, [grain_lutq+offxyq+82*1], 1 + vinserti128 ym16, [grain_lutq+left_offxyq+82*1], 1 + vinserti32x4 m21, [grain_lutq+offxyq+82*2], 2 + vinserti32x4 m16, [grain_lutq+left_offxyq+82*2], 2 + vinserti32x4 m21, [grain_lutq+offxyq+82*3], 3 + vinserti32x4 m16, [grain_lutq+left_offxyq+82*3], 3 + movd xm18, [grain_lutq+topleft_offxyq+82*0] + movu xm20, [grain_lutq+top_offxyq] + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw m16, m21 +%if %3 + punpcklbw xm18, xm20 +%else + vinserti128 ym18, [grain_lutq+topleft_offxyq+82*1], 1 + vinserti128 ym20, [grain_lutq+top_offxyq+82*1], 1 + punpcklbw ym18, ym20 +%endif + punpcklqdq m16, m18 + pmaddubsw m16, m10, m16 + pmulhrsw m16, m9 + packsswb m16, m16 + vmovdqu8 m21{k1}, m16 +%if %3 + vpalignr xm20{k1}, xm16, xm16, 4 + punpcklbw xm19, xm20, xm21 + punpckhbw xm20, xm21 +%else + vpalignr ym20{k1}, ym16, ym16, 4 + punpcklbw ym19, ym20, ym21 + punpckhbw ym20, ym21 +%endif +%else + movu ym21, [grain_lutq+offxyq+82*0] + vinserti32x8 m21, [grain_lutq+offxyq+82*1], 1 + movd xm16, [grain_lutq+left_offxyq+82*0] + vinserti32x4 m16, [grain_lutq+left_offxyq+82*1], 2 + movu ym20, [grain_lutq+top_offxyq+82*0] + vinserti32x8 m20, [grain_lutq+top_offxyq+82*1], 1 + movd xm18, [grain_lutq+topleft_offxyq+82*0] + vinserti32x4 m18, [grain_lutq+topleft_offxyq+82*1], 2 + punpcklbw m16, m21 + punpcklbw m18, m20 + punpcklqdq m16, m18 + pmaddubsw m16, m10, m16 + pmulhrsw m16, m9 + packsswb m16, m16 + vpalignr m20{k1}, m16, m16, 4 + vmovdqu8 m21{k1}, m16 +%endif + call %%add_noise_v + sub hb, 2<<%2 + jg %%loop_y_h_overlap + add wq, 32>>%2 + jge .end + mov srcq, r11mp + mov dstq, r12mp + lea lumaq, [r13+wq*(1<<%2)] + add srcq, wq + add dstq, wq + jmp %%hv_overlap +ALIGN function_align +%%add_noise_v: +%if %3 + pmaddubsw xm19, xm13, xm19 + pmaddubsw xm20, xm13, xm20 + pmulhrsw xm19, xm9 + pmulhrsw xm20, xm9 + vpacksswb m21{k3}, m19, m20 +%elif %2 + pmaddubsw ym19, ym13, ym19 + pmaddubsw ym20, ym13, ym20 + pmulhrsw ym19, ym9 + pmulhrsw ym20, ym9 + vpacksswb m21{k3}, m19, m20 +%else + punpcklbw m19, m20, m21 + punpckhbw m20, m21 + pmaddubsw m19, m13, m19 + pmaddubsw m20, m13, m20 + pmulhrsw m19, m9 + pmulhrsw m20, m9 + packsswb m21, m19, m20 +%endif +%%add_noise: + punpcklbw m20, m5, m21 + punpckhbw m21, m5 +%%add_noise_h: + mova ym18, [lumaq+lstrideq*(0<<%3)] + vinserti32x8 m18, [lumaq+lstrideq*(1<<%3)], 1 +%if %2 + lea lumaq, [lumaq+lstrideq*(2<<%3)] + mova ym16, [lumaq+lstrideq*(0<<%3)] + vinserti32x8 m16, [lumaq+lstrideq*(1<<%3)], 1 + mova xm17, [srcq+strideq*0] + mova m19, m11 + vpermi2b m19, m18, m16 + vinserti128 ym17, [srcq+strideq*1], 1 + vpermt2b m18, m12, m16 + vinserti32x4 m17, [srcq+strideq*2], 2 + pavgb m18, m19 + vinserti32x4 m17, [srcq+stride3q ], 3 +%else + mova ym17, [srcq+strideq*0] + vinserti32x8 m17, [srcq+strideq*1], 1 +%endif +%if %1 + punpckhbw m19, m18, m17 + punpcklbw m18, m17 ; { luma, chroma } + pmaddubsw m19, m14 + pmaddubsw m18, m14 + psraw m19, 6 + psraw m18, 6 + paddw m19, m15 + paddw m18, m15 + packuswb m18, m19 +.add_noise_main: + mova m19, m0 + vpermt2b m19, m18, m1 ; scaling[ 0..127] + vpmovb2m k2, m18 + vpermi2b m18, m2, m3 ; scaling[128..255] + vmovdqu8 m19{k2}, m18 ; scaling[src] + pshufb m19, m4 + pmaddubsw m18, m19, m20 + pmaddubsw m19, m21 + add grain_lutq, 82*2<<%2 + lea lumaq, [lumaq+lstrideq*(2<<%3)] + lea srcq, [srcq+strideq*(2<<%2)] + pmulhrsw m18, m6 ; noise + pmulhrsw m19, m6 + punpcklbw m16, m17, m5 ; chroma + punpckhbw m17, m5 + paddw m16, m18 + paddw m17, m19 + packuswb m16, m17 + pmaxub m16, m7 + pminub m16, m8 +%if %2 + mova [dstq+strideq*0], xm16 + vextracti128 [dstq+strideq*1], ym16, 1 + vextracti32x4 [dstq+strideq*2], m16, 2 + vextracti32x4 [dstq+stride3q ], m16, 3 +%else + mova [dstq+strideq*0], ym16 + vextracti32x8 [dstq+strideq*1], m16, 1 +%endif + lea dstq, [dstq+strideq*(2<<%2)] + ret +%else + jmp .add_noise_main +%endif +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 +.end: + RET +%endmacro + +FGUV_FN 420, 1, 1 +FGUV_FN 422, 1, 0 +FGUV_FN 444, 0, 0 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_common.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_common.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_common.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_common.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +; Copyright © 2019-2022, VideoLAN and dav1d authors +; Copyright © 2019-2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +struc FGData + .seed: resd 1 + .num_y_points: resd 1 + .y_points: resb 14 * 2 + .chroma_scaling_from_luma: resd 1 + .num_uv_points: resd 2 + .uv_points: resb 2 * 10 * 2 + .scaling_shift: resd 1 + .ar_coeff_lag: resd 1 + .ar_coeffs_y: resb 24 + .ar_coeffs_uv: resb 2 * 28 ; includes padding + .ar_coeff_shift: resq 1 + .grain_scale_shift: resd 1 + .uv_mult: resd 2 + .uv_luma_mult: resd 2 + .uv_offset: resd 2 + .overlap_flag: resd 1 + .clip_to_restricted_range: resd 1 +endstruc + +cextern gaussian_sequence diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/filmgrain_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3233 @@ +; Copyright © 2019-2021, VideoLAN and dav1d authors +; Copyright © 2019, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" +%include "x86/filmgrain_common.asm" + +SECTION_RODATA + +pw_1024: times 8 dw 1024 +pb_27_17_17_27: db 27, 17, 17, 27 + times 6 db 0, 32 +pb_23_22_h: db 23, 22 + times 7 db 0, 32 +pb_27_17: times 8 db 27, 17 +pb_17_27: times 8 db 17, 27 +pb_23_22: times 8 db 23, 22 +pb_mask: db 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0 +rnd_next_upperbit_mask: dw 0x100B, 0x2016, 0x402C, 0x8058 +byte_blend: db 0, 0, 0, 0xff, 0, 0, 0, 0 +pw_seed_xor: times 2 dw 0xb524 + times 2 dw 0x49d8 +pb_1: times 4 db 1 +hmul_bits: dw 32768, 16384, 8192, 4096 +round: dw 2048, 1024, 512 +mul_bits: dw 256, 128, 64, 32, 16 +round_vals: dw 32, 64, 128, 256, 512 +max: dw 255, 240, 235 +min: dw 0, 16 +pw_1: dw 1 + +%macro JMP_TABLE 2-* + %xdefine %1_8bpc_%2_table %%table + %xdefine %%base %1_8bpc_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .ar%3 - %%base + %rotate 1 + %endrep +%endmacro + +JMP_TABLE generate_grain_y, ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_420, ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_422, ssse3, 0, 1, 2, 3 +JMP_TABLE generate_grain_uv_444, ssse3, 0, 1, 2, 3 + +SECTION .text + +%if ARCH_X86_32 +%define PIC_ptr(a) base+a +%else +%define PIC_ptr(a) a +%endif + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +INIT_XMM ssse3 +cglobal generate_grain_y_8bpc, 2, 7 + 2 * ARCH_X86_64, 16, buf, fg_data + LEA r4, $$ +%define base r4-$$ + movq m1, [base+rnd_next_upperbit_mask] + movq m4, [base+mul_bits] + movq m7, [base+hmul_bits] + mov r2d, [fg_dataq+FGData.grain_scale_shift] + movd m2, [base+round+r2*2] + movd m0, [fg_dataq+FGData.seed] + mova m5, [base+pb_mask] + pshuflw m2, m2, q0000 + pshuflw m0, m0, q0000 + mov r2, -73*82 + sub bufq, r2 + lea r3, [base+gaussian_sequence] +.loop: + pand m6, m0, m1 + psrlw m3, m6, 10 + por m6, m3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw m6, m4 ; bits 0x0f00 are set + pshufb m3, m5, m6 ; set 15th bit for next 4 seeds + psllq m6, m3, 30 + por m3, m6 + psllq m6, m3, 15 + por m3, m6 ; aggregate each bit into next seed's high bit + pmulhuw m6, m0, m7 + por m3, m6 ; 4 next output seeds + pshuflw m0, m3, q3333 + psrlw m3, 5 +%if ARCH_X86_64 + movq r6, m3 + mov r8, r6 + movzx r5d, r6w + shr r6d, 16 + shr r8, 32 + movzx r7, r8w + shr r8, 16 + + movd m6, [r3+r5*2] + pinsrw m6, [r3+r6*2], 1 + pinsrw m6, [r3+r7*2], 2 + pinsrw m6, [r3+r8*2], 3 +%else + movd r6, m3 + pshuflw m3, m3, q3232 + movzx r5, r6w + shr r6, 16 + + movd m6, [r3+r5*2] + pinsrw m6, [r3+r6*2], 1 + + movd r6, m3 + movzx r5, r6w + shr r6, 16 + + pinsrw m6, [r3+r5*2], 2 + pinsrw m6, [r3+r6*2], 3 +%endif + pmulhrsw m6, m2 + packsswb m6, m6 + movd [bufq+r2], m6 + add r2, 4 + jl .loop + + ; auto-regression code + movsxd r2, [fg_dataq+FGData.ar_coeff_lag] + movsxd r2, [base+generate_grain_y_8bpc_ssse3_table+r2*4] + lea r2, [r2+base+generate_grain_y_8bpc_ssse3_table] + jmp r2 + +.ar1: +%if ARCH_X86_32 + DEFINE_ARGS buf, fg_data, cf3, unused, val3, min, max +%elif WIN64 + DEFINE_ARGS shift, fg_data, cf3, buf, val3, min, max, x, val0 + mov bufq, r0 +%else + DEFINE_ARGS buf, fg_data, cf3, shift, val3, min, max, x, val0 +%endif + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_y+3] + movd m4, [fg_dataq+FGData.ar_coeffs_y] + mov ecx, [fg_dataq+FGData.ar_coeff_shift] +%if ARCH_X86_32 + mov r1m, cf3d + DEFINE_ARGS buf, shift, val3, min, max, x, val0 +%define hd r0mp +%define cf3d r1mp +%elif WIN64 + DEFINE_ARGS shift, h, cf3, buf, val3, min, max, x, val0 +%else + DEFINE_ARGS buf, h, cf3, shift, val3, min, max, x, val0 +%endif + pxor m6, m6 + pcmpgtb m7, m6, m4 + punpcklbw m4, m7 + pinsrw m4, [base+pw_1], 3 + pshufd m5, m4, q1111 + pshufd m4, m4, q0000 + movd m3, [base+round_vals+shiftq*2-12] ; rnd + pshuflw m3, m3, q0000 + sub bufq, 82*73-(82*3+79) + mov hd, 70 + mov mind, -128 + mov maxd, 127 +.y_loop_ar1: + mov xq, -76 + movsx val3d, byte [bufq+xq-1] +.x_loop_ar1: + movq m0, [bufq+xq-82-1] ; top/left + pcmpgtb m7, m6, m0 + punpcklbw m0, m7 + psrldq m2, m0, 2 ; top + psrldq m1, m0, 4 ; top/right + punpcklwd m0, m2 + punpcklwd m1, m3 + pmaddwd m0, m4 + pmaddwd m1, m5 + paddd m0, m1 +.x_loop_ar1_inner: + movd val0d, m0 + psrldq m0, 4 + imul val3d, cf3d + add val3d, val0d + sar val3d, shiftb + movsx val0d, byte [bufq+xq] + add val3d, val0d + cmp val3d, maxd + cmovns val3d, maxd + cmp val3d, mind + cmovs val3d, mind + mov byte [bufq+xq], val3b + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xq, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 + +.x_loop_ar1_end: + add bufq, 82 + dec hd + jg .y_loop_ar1 +.ar0: + RET + +.ar2: +%if ARCH_X86_32 +%assign stack_offset_old stack_offset + ALLOC_STACK -16*8 +%endif + DEFINE_ARGS buf, fg_data, shift + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m6, [base+round_vals-12+shiftq*2] + movd m7, [base+byte_blend+1] + SCRATCH 7, 15, 7 + movq m0, [fg_dataq+FGData.ar_coeffs_y+0] ; cf0-7 + movd m1, [fg_dataq+FGData.ar_coeffs_y+8] ; cf8-11 + pxor m7, m7 + pshuflw m6, m6, q0000 + punpcklwd m6, m7 + pcmpgtb m4, m7, m0 + pcmpgtb m5, m7, m1 + punpcklbw m0, m4 + punpcklbw m1, m5 + DEFINE_ARGS buf, fg_data, h, x + pshufd m4, m1, q0000 + pshufd m5, m1, q1111 + pshufd m3, m0, q3333 + pshufd m2, m0, q2222 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + SCRATCH 0, 8, 0 + SCRATCH 1, 9, 1 + SCRATCH 2, 10, 2 + SCRATCH 3, 11, 3 + SCRATCH 4, 12, 4 + SCRATCH 5, 13, 5 + SCRATCH 6, 14, 6 + sub bufq, 82*73-(82*3+79) + mov hd, 70 +.y_loop_ar2: + mov xq, -76 + +.x_loop_ar2: + movq m0, [bufq+xq-82*2-2] ; y=-2,x=[-2,+5] + movhps m0, [bufq+xq-82*1-2] ; y=-1,x=[-2,+5] + pcmpgtb m2, m7, m0 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 + psrldq m5, m0, 2 ; y=-2,x=[-1,+5] + psrldq m3, m1, 2 ; y=-1,x=[-1,+5] + psrldq m4, m1, 4 ; y=-1,x=[+0,+5] + punpcklwd m2, m0, m5 + punpcklwd m3, m4 + pmaddwd m2, m8 + pmaddwd m3, m11 + paddd m2, m3 + + psrldq m4, m0, 4 ; y=-2,x=[+0,+5] + psrldq m5, m0, 6 ; y=-2,x=[+1,+5] + psrldq m6, m0, 8 ; y=-2,x=[+2,+5] + punpcklwd m4, m5 + punpcklwd m6, m1 + psrldq m5, m1, 6 ; y=-1,x=[+1,+5] + psrldq m1, m1, 8 ; y=-1,x=[+2,+5] + punpcklwd m5, m1 + pmaddwd m4, m9 + pmaddwd m6, m10 + pmaddwd m5, m12 + paddd m4, m6 + paddd m2, m5 + paddd m2, m4 + paddd m2, m14 + + movq m0, [bufq+xq-2] ; y=0,x=[-2,+5] +.x_loop_ar2_inner: + pcmpgtb m4, m7, m0 + punpcklbw m1, m0, m4 + pmaddwd m3, m1, m13 + paddd m3, m2 + psrldq m1, 4 ; y=0,x=0 + psrldq m2, 4 ; shift top to next pixel + psrad m3, [fg_dataq+FGData.ar_coeff_shift] + ; don't packssdw since we only care about one value + paddw m3, m1 + packsswb m3, m3 + pslldq m3, 2 + pand m3, m15 + pandn m1, m15, m0 + por m0, m1, m3 + psrldq m0, 1 + ; overwrite 2 pixels, but that's ok + movd [bufq+xq-1], m0 + inc xq + jz .x_loop_ar2_end + test xq, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 + +.x_loop_ar2_end: + add bufq, 82 + dec hd + jg .y_loop_ar2 + RET + +.ar3: + DEFINE_ARGS buf, fg_data, shift +%if ARCH_X86_32 +%assign stack_offset stack_offset_old + ALLOC_STACK -16*14 +%elif WIN64 + SUB rsp, 16*6 +%assign stack_size_padded (stack_size_padded+16*6) +%assign stack_size (stack_size+16*6) +%else + ALLOC_STACK -16*6 +%endif + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m6, [base+round_vals-12+shiftq*2] + movd m7, [base+byte_blend] + movu m0, [fg_dataq+FGData.ar_coeffs_y+ 0] ; cf0-15 + movq m2, [fg_dataq+FGData.ar_coeffs_y+16] ; cf16-23 + pxor m3, m3 + pcmpgtb m4, m3, m0 + pcmpgtb m3, m2 + pshuflw m6, m6, q0000 + SCRATCH 6, 14, 12 + SCRATCH 7, 15, 13 + punpckhbw m1, m0, m4 + punpcklbw m0, m4 + punpcklbw m2, m3 + pshufd m3, m0, q1111 + pshufd m4, m0, q2222 + pshufd m5, m0, q3333 + pshufd m0, m0, q0000 + mova [rsp+ 0*16], m0 + mova [rsp+ 1*16], m3 + mova [rsp+ 2*16], m4 + mova [rsp+ 3*16], m5 + pshufd m6, m1, q1111 + pshufd m7, m1, q2222 + pshufd m5, m1, q3333 + pshufd m1, m1, q0000 + pshufd m3, m2, q1111 + psrldq m0, m2, 10 + pinsrw m2, [base+pw_1], 5 + pshufd m4, m2, q2222 + pshufd m2, m2, q0000 + pinsrw m0, [base+round_vals+shiftq*2-10], 3 + mova [rsp+ 4*16], m1 + mova [rsp+ 5*16], m6 + SCRATCH 7, 8, 6 + SCRATCH 5, 9, 7 + SCRATCH 2, 10, 8 + SCRATCH 3, 11, 9 + SCRATCH 4, 12, 10 + SCRATCH 0, 13, 11 + DEFINE_ARGS buf, fg_data, h, x + sub bufq, 82*73-(82*3+79) + mov hd, 70 +.y_loop_ar3: + mov xq, -76 + +.x_loop_ar3: + movu m0, [bufq+xq-82*3-3] ; y=-3,x=[-3,+12] + pxor m3, m3 + pcmpgtb m3, m0 + punpckhbw m2, m0, m3 + punpcklbw m0, m3 + + psrldq m5, m0, 2 + psrldq m6, m0, 4 + psrldq m7, m0, 6 + punpcklwd m4, m0, m5 + punpcklwd m6, m7 + pmaddwd m4, [rsp+ 0*16] + pmaddwd m6, [rsp+ 1*16] + paddd m4, m6 + + movu m1, [bufq+xq-82*2-3] ; y=-2,x=[-3,+12] + pxor m5, m5 + pcmpgtb m5, m1 + punpckhbw m3, m1, m5 + punpcklbw m1, m5 + palignr m6, m2, m0, 10 + palignr m7, m2, m0, 12 + psrldq m0, 8 + punpcklwd m0, m6 + punpcklwd m7, m1 + pmaddwd m0, [rsp+ 2*16] + pmaddwd m7, [rsp+ 3*16] + paddd m0, m7 + paddd m0, m4 + + psrldq m4, m1, 2 + psrldq m5, m1, 4 + psrldq m6, m1, 6 + psrldq m7, m1, 8 + punpcklwd m4, m5 + punpcklwd m6, m7 + pmaddwd m4, [rsp+ 4*16] + pmaddwd m6, [rsp+ 5*16] + paddd m4, m6 + paddd m0, m4 + + movu m2, [bufq+xq-82*1-3] ; y=-1,x=[-3,+12] + pxor m7, m7 + pcmpgtb m7, m2 + punpckhbw m5, m2, m7 + punpcklbw m2, m7 + palignr m7, m3, m1, 10 + palignr m3, m1, 12 + psrldq m1, m2, 2 + punpcklwd m7, m3 + punpcklwd m3, m2, m1 + pmaddwd m7, m8 + pmaddwd m3, m9 + paddd m7, m3 + paddd m0, m7 + + psrldq m6, m2, 4 + psrldq m1, m2, 6 + psrldq m3, m2, 8 + palignr m4, m5, m2, 10 + palignr m5, m5, m2, 12 + + punpcklwd m6, m1 + punpcklwd m3, m4 + punpcklwd m5, m14 + pmaddwd m6, m10 + pmaddwd m3, m11 + pmaddwd m5, m12 + paddd m0, m6 + paddd m3, m5 + paddd m0, m3 + + movq m1, [bufq+xq-3] ; y=0,x=[-3,+4] +.x_loop_ar3_inner: + pxor m5, m5 + pcmpgtb m5, m1 + punpcklbw m2, m1, m5 + pmaddwd m2, m13 + pshufd m3, m2, q1111 + paddd m2, m3 ; left+cur + paddd m2, m0 ; add top + psrldq m0, 4 + psrad m2, [fg_dataq+FGData.ar_coeff_shift] + ; don't packssdw since we only care about one value + packsswb m2, m2 + pslldq m2, 3 + pand m2, m15 + pandn m3, m15, m1 + por m1, m2, m3 + movd [bufq+xq-3], m1 + psrldq m1, 1 + inc xq + jz .x_loop_ar3_end + test xq, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 + +.x_loop_ar3_end: + add bufq, 82 + dec hd + jg .y_loop_ar3 + RET + +%macro generate_grain_uv_fn 3 ; ss_name, ss_x, ss_y +INIT_XMM ssse3 +cglobal generate_grain_uv_%1_8bpc, 1, 7 + 3 * ARCH_X86_64, 16, buf, bufy, fg_data, uv + movifnidn r2, r2mp + movifnidn r3, r3mp + LEA r4, $$ +%define base r4-$$ + movq m1, [base+rnd_next_upperbit_mask] + movq m4, [base+mul_bits] + movq m7, [base+hmul_bits] + mov r5d, [fg_dataq+FGData.grain_scale_shift] + movd m6, [base+round+r5*2] + mova m5, [base+pb_mask] + movd m0, [fg_dataq+FGData.seed] + movd m2, [base+pw_seed_xor+uvq*4] + pxor m0, m2 + pshuflw m6, m6, q0000 + pshuflw m0, m0, q0000 + lea r6, [base+gaussian_sequence] +%if %2 +%if ARCH_X86_64 + mov r7d, 73-35*%3 +%else + mov r3mp, 73-35*%3 +%endif + add bufq, 44 +.loop_y: + mov r5, -44 +.loop_x: +%else + mov r5, -82*73 + sub bufq, r5 +.loop: +%endif + pand m2, m0, m1 + psrlw m3, m2, 10 + por m2, m3 ; bits 0xf, 0x1e, 0x3c and 0x78 are set + pmullw m2, m4 ; bits 0x0f00 are set + pshufb m3, m5, m2 ; set 15th bit for next 4 seeds + psllq m2, m3, 30 + por m3, m2 + psllq m2, m3, 15 + por m3, m2 ; aggregate each bit into next seed's high bit + pmulhuw m2, m0, m7 + por m2, m3 ; 4 next output seeds + pshuflw m0, m2, q3333 + psrlw m2, 5 +%if ARCH_X86_64 + movd r9d, m2 + pshuflw m2, m2, q3232 + movzx r8, r9w + shr r9, 16 + + movd m3, [r6+r8*2] + pinsrw m3, [r6+r9*2], 1 + + movd r9d, m2 + movzx r8, r9w + shr r9, 16 + + pinsrw m3, [r6+r8*2], 2 + pinsrw m3, [r6+r9*2], 3 +%else + movd r2, m2 + pshuflw m2, m2, q3232 + movzx r1, r2w + shr r2, 16 + + movd m3, [r6+r1*2] + pinsrw m3, [r6+r2*2], 1 + + movd r2, m2 + movzx r1, r2w + shr r2, 16 + + pinsrw m3, [r6+r1*2], 2 + pinsrw m3, [r6+r2*2], 3 +%endif + pmulhrsw m3, m6 + packsswb m3, m3 + movd [bufq+r5], m3 + add r5, 4 +%if %2 + jl .loop_x + add bufq, 82 +%if ARCH_X86_64 + dec r7d +%else + dec r3mp +%endif + jg .loop_y +%else + jl .loop +%endif + +%if ARCH_X86_32 + mov r2, r2mp +%endif + + ; auto-regression code + movsxd r5, [fg_dataq+FGData.ar_coeff_lag] + movsxd r5, [base+generate_grain_uv_%1_8bpc_ssse3_table+r5*4] + lea r5, [r5+base+generate_grain_uv_%1_8bpc_ssse3_table] + jmp r5 + +.ar0: + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + movifnidn bufyq, bufymp +%if ARCH_X86_32 +%assign stack_offset_old stack_offset + ALLOC_STACK -2*16 +%endif + imul uvd, 28 + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m5, [fg_dataq+FGData.ar_coeffs_uv+uvq] + movd m4, [base+hmul_bits+shiftq*2] + DEFINE_ARGS buf, bufy, h, x + pxor m0, m0 + pcmpgtb m0, m5 + punpcklbw m5, m0 + movd m7, [base+pb_1] +%if %2 + movd m6, [base+hmul_bits+2+%3*2] +%endif + pshuflw m5, m5, q0000 + pshuflw m4, m4, q0000 + pshufd m7, m7, q0000 +%if %2 + pshuflw m6, m6, q0000 +%endif + punpcklqdq m5, m5 + punpcklqdq m4, m4 +%if %2 + punpcklqdq m6, m6 +%endif + pcmpeqw m1, m1 + pslldq m1, 12>>%2 + SCRATCH 1, 8, 0 + SCRATCH 4, 9, 1 +%if %2 + sub bufq, 82*(73-35*%3)+82-(82*3+41) +%else + sub bufq, 82*70-3 +%endif + add bufyq, 3+82*3 + mov hd, 70-35*%3 +.y_loop_ar0: + xor xd, xd +.x_loop_ar0: + ; first 32 pixels +%if %2 + movu m1, [bufyq+xq*2] +%if %3 + movu m2, [bufyq+xq*2+82] +%endif + movu m3, [bufyq+xq*2+16] +%if %3 + movu m4, [bufyq+xq*2+82+16] +%endif + pmaddubsw m0, m7, m1 +%if %3 + pmaddubsw m1, m7, m2 +%endif + pmaddubsw m2, m7, m3 +%if %3 + pmaddubsw m3, m7, m4 + paddw m0, m1 + paddw m2, m3 +%endif + pmulhrsw m0, m6 + pmulhrsw m2, m6 +%else + movu m0, [bufyq+xq] + pxor m6, m6 + pcmpgtb m6, m0 + punpckhbw m2, m0, m6 + punpcklbw m0, m6 +%endif + pmullw m0, m5 + pmullw m2, m5 + pmulhrsw m0, m9 + pmulhrsw m2, m9 + movu m1, [bufq+xq] + pxor m4, m4 + pcmpgtb m4, m1 + punpckhbw m3, m1, m4 +%if %2 + punpcklbw m1, m4 + paddw m2, m3 + paddw m0, m1 +%else + punpcklbw m6, m1, m4 + paddw m2, m3 + paddw m0, m6 +%endif + packsswb m0, m2 +%if %2 + movu [bufq+xq], m0 + add xd, 16 + cmp xd, 32 + jl .x_loop_ar0 + + ; last 6/12 pixels + movu m1, [bufyq+xq*(1+%2)] +%if %3 + movu m2, [bufyq+xq*2+82] +%endif + pmaddubsw m0, m7, m1 +%if %3 + pmaddubsw m1, m7, m2 + paddw m0, m1 +%endif + pmulhrsw m0, m6 + pmullw m0, m5 + pmulhrsw m0, m9 + movq m1, [bufq+xq] + pxor m4, m4 + pcmpgtb m4, m1 + punpcklbw m2, m1, m4 + paddw m0, m2 + packsswb m0, m0 + pandn m2, m8, m0 + pand m1, m8 + por m2, m1 + movq [bufq+xq], m2 +%else + add xd, 16 + cmp xd, 80 + je .y_loop_final_ar0 + movu [bufq+xq-16], m0 + jmp .x_loop_ar0 +.y_loop_final_ar0: + pandn m2, m8, m0 + pand m1, m8 + por m2, m1 + movu [bufq+xq-16], m2 +%endif + + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar0 + RET + +.ar1: +%if ARCH_X86_32 +%assign stack_offset stack_offset_old +%assign stack_size_padded 0 +%xdefine rstk rsp +%endif + DEFINE_ARGS buf, bufy, fg_data, uv, val3, cf3, min, max, x + imul uvd, 28 + movsx cf3d, byte [fg_dataq+FGData.ar_coeffs_uv+uvq+3] + movd m4, [fg_dataq+FGData.ar_coeffs_uv+uvq-1] + pinsrw m4, [fg_dataq+FGData.ar_coeffs_uv+uvq+4], 2 +%if ARCH_X86_32 + mov r3mp, cf3d + DEFINE_ARGS buf, shift, fg_data, val3, min, max, x +%elif WIN64 + DEFINE_ARGS shift, bufy, fg_data, buf, val3, cf3, min, max, x + mov bufq, r0 +%else + DEFINE_ARGS buf, bufy, fg_data, shift, val3, cf3, min, max, x +%endif + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + movd m3, [base+round_vals+shiftq*2-12] ; rnd +%if %2 + movd m7, [base+pb_1] + movd m6, [base+hmul_bits+2+%3*2] +%endif + psrldq m4, 1 +%if ARCH_X86_32 + DEFINE_ARGS buf, shift, val0, val3, min, max, x +%elif WIN64 + DEFINE_ARGS shift, bufy, h, buf, val3, cf3, min, max, x, val0 +%else + DEFINE_ARGS buf, bufy, h, shift, val3, cf3, min, max, x, val0 +%endif + pxor m5, m5 + punpcklwd m3, m5 +%if %2 + punpcklwd m6, m6 +%endif + pcmpgtb m5, m4 + punpcklbw m4, m5 + pshufd m5, m4, q1111 + pshufd m4, m4, q0000 + pshufd m3, m3, q0000 +%if %2 + pshufd m7, m7, q0000 + pshufd m6, m6, q0000 + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*69+3 +%endif +%if ARCH_X86_32 + add r1mp, 79+82*3 + mov r0mp, 70-35*%3 +%else + add bufyq, 79+82*3 + mov hd, 70-35*%3 +%endif + mov mind, -128 + mov maxd, 127 +.y_loop_ar1: + mov xq, -(76>>%2) + movsx val3d, byte [bufq+xq-1] +.x_loop_ar1: +%if %2 +%if ARCH_X86_32 + mov r2, r1mp + movq m0, [r2+xq*2] +%if %3 + movq m1, [r2+xq*2+82] +%endif +%else + movq m0, [bufyq+xq*2] +%if %3 + movq m1, [bufyq+xq*2+82] +%endif +%endif + pmaddubsw m2, m7, m0 +%if %3 + pmaddubsw m0, m7, m1 + paddw m2, m0 +%endif + pmulhrsw m2, m6 +%else +%if ARCH_X86_32 + mov r2, r1mp + movd m2, [r2+xq] +%else + movd m2, [bufyq+xq] +%endif + pxor m0, m0 + pcmpgtb m0, m2 + punpcklbw m2, m0 +%endif + + movq m0, [bufq+xq-82-1] ; top/left + pxor m1, m1 + pcmpgtb m1, m0 + punpcklbw m0, m1 + psrldq m1, m0, 4 ; top/right + punpcklwd m1, m2 + psrldq m2, m0, 2 ; top + punpcklwd m0, m2 + pmaddwd m0, m4 + pmaddwd m1, m5 + paddd m0, m1 + paddd m0, m3 +.x_loop_ar1_inner: + movd val0d, m0 + psrldq m0, 4 +%if ARCH_X86_32 + imul val3d, r3mp +%else + imul val3d, cf3d +%endif + add val3d, val0d + sar val3d, shiftb + movsx val0d, byte [bufq+xq] + add val3d, val0d + cmp val3d, maxd + cmovns val3d, maxd + cmp val3d, mind + cmovs val3d, mind + mov byte [bufq+xq], val3b + ; keep val3d in-place as left for next x iteration + inc xq + jz .x_loop_ar1_end + test xq, 3 + jnz .x_loop_ar1_inner + jmp .x_loop_ar1 + +.x_loop_ar1_end: + add bufq, 82 +%if ARCH_X86_32 + add r1mp, 82<<%3 + dec r0mp +%else + add bufyq, 82<<%3 + dec hd +%endif + jg .y_loop_ar1 + RET + +.ar2: +%if ARCH_X86_32 +%assign stack_offset stack_offset_old +%assign stack_size_padded 0 +%xdefine rstk rsp + ALLOC_STACK -8*16 +%endif + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + movifnidn bufyq, bufymp + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + movd m7, [base+round_vals-12+shiftq*2] + movu m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+0] ; cf0-12 + pxor m2, m2 + pcmpgtb m2, m0 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 + pinsrw m1, [base+pw_1], 5 + punpcklwd m7, m7 + pshufd m7, m7, q0000 + DEFINE_ARGS buf, bufy, fg_data, h, unused, x + pshufd m4, m1, q0000 + pshufd m5, m1, q1111 + pshufd m6, m1, q2222 + pshufd m3, m0, q3333 + pshufd m2, m0, q2222 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + SCRATCH 0, 8, 0 + SCRATCH 1, 9, 1 + SCRATCH 2, 10, 2 + SCRATCH 3, 11, 3 + SCRATCH 4, 12, 4 + SCRATCH 5, 13, 5 + SCRATCH 6, 14, 6 + SCRATCH 7, 15, 7 +%if %2 + movd m7, [base+hmul_bits+2+%3*2] + movd m6, [base+pb_1] + punpcklwd m7, m7 + pshufd m6, m6, q0000 + pshufd m7, m7, q0000 + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*69+3 +%endif + add bufyq, 79+82*3 + mov hd, 70-35*%3 +.y_loop_ar2: + mov xq, -(76>>%2) + +.x_loop_ar2: + pxor m2, m2 + movq m0, [bufq+xq-82*2-2] ; y=-2,x=[-2,+5] + movhps m0, [bufq+xq-82*1-2] ; y=-1,x=[-2,+5] + pcmpgtb m2, m0 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 + psrldq m5, m0, 2 ; y=-2,x=[-1,+5] + psrldq m3, m1, 2 ; y=-1,x=[-1,+5] + psrldq m4, m1, 4 ; y=-1,x=[+0,+5] + punpcklwd m2, m0, m5 + punpcklwd m3, m4 + pmaddwd m2, m8 + pmaddwd m3, m11 + paddd m2, m3 + + psrldq m4, m0, 4 ; y=-2,x=[+0,+5] + psrldq m5, m0, 6 ; y=-2,x=[+1,+5] + psrldq m0, 8 ; y=-2,x=[+2,+5] + punpcklwd m4, m5 + punpcklwd m0, m1 + psrldq m3, m1, 6 ; y=-1,x=[+1,+5] + psrldq m1, m1, 8 ; y=-1,x=[+2,+5] + punpcklwd m3, m1 + pmaddwd m4, m9 + pmaddwd m0, m10 + pmaddwd m3, m12 + paddd m4, m0 + paddd m2, m3 + paddd m2, m4 + +%if %2 + movq m1, [bufyq+xq*2] +%if %3 + movq m3, [bufyq+xq*2+82] +%endif + pmaddubsw m0, m6, m1 +%if %3 + pmaddubsw m1, m6, m3 + paddw m0, m1 +%endif + pmulhrsw m0, m7 +%else + movd m0, [bufyq+xq] + pxor m1, m1 + pcmpgtb m1, m0 + punpcklbw m0, m1 +%endif + punpcklwd m0, m15 + pmaddwd m0, m14 + paddd m2, m0 + + movq m0, [bufq+xq-2] ; y=0,x=[-2,+5] + pxor m4, m4 + movd m5, [base+byte_blend+1] + punpcklbw m5, m5 +.x_loop_ar2_inner: + pcmpgtb m1, m4, m0 + punpcklbw m0, m1 + pmaddwd m3, m0, m13 + paddd m3, m2 + psrldq m2, 4 ; shift top to next pixel + psrad m3, [fg_dataq+FGData.ar_coeff_shift] + pslldq m3, 4 + pand m3, m5 + paddw m0, m3 + packsswb m0, m0 + movd [bufq+xq-2], m0 + psrldq m0, 1 + inc xq + jz .x_loop_ar2_end + test xq, 3 + jnz .x_loop_ar2_inner + jmp .x_loop_ar2 + +.x_loop_ar2_end: + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar2 + RET + +.ar3: +%if ARCH_X86_32 +%assign stack_offset stack_offset_old +%assign stack_size_padded 0 +%xdefine rstk rsp +%endif + DEFINE_ARGS buf, bufy, fg_data, uv, unused, shift + movifnidn bufyq, bufymp +%if ARCH_X86_32 + ALLOC_STACK -15*16 +%else + SUB rsp, 16*7 +%assign stack_size_padded (stack_size_padded+16*7) +%assign stack_size (stack_size+16*7) +%endif + mov shiftd, [fg_dataq+FGData.ar_coeff_shift] + imul uvd, 28 + + movu m0, [fg_dataq+FGData.ar_coeffs_uv+uvq+ 0] ; cf0-15 + pxor m3, m3 + pcmpgtb m3, m0 + punpckhbw m1, m0, m3 + punpcklbw m0, m3 + pshufd m2, m0, q1111 + pshufd m3, m0, q2222 + pshufd m4, m0, q3333 + pshufd m0, m0, q0000 + pshufd m5, m1, q1111 + pshufd m6, m1, q2222 + pshufd m7, m1, q3333 + pshufd m1, m1, q0000 + mova [rsp+ 0*16], m0 + mova [rsp+ 1*16], m2 + mova [rsp+ 2*16], m3 + mova [rsp+ 3*16], m4 + mova [rsp+ 4*16], m1 + mova [rsp+ 5*16], m5 + mova [rsp+ 6*16], m6 + SCRATCH 7, 8, 7 + + movu m2, [fg_dataq+FGData.ar_coeffs_uv+uvq+16] ; cf16-24 [24=luma] + pxor m4, m4 + pcmpgtb m4, m2 + punpckhbw m5, m2, m4 + punpcklbw m2, m4 + pshufd m4, m2, q3232 + punpcklwd m3, m4, m5 + pshuflw m5, m4, q3321 + pshufd m4, m3, q0000 + pshufd m3, m2, q1111 + pshufd m2, m2, q0000 + pinsrw m5, [base+round_vals+shiftq*2-10], 3 + SCRATCH 2, 9, 8 + SCRATCH 3, 10, 9 + SCRATCH 4, 11, 10 + SCRATCH 5, 12, 11 + + movd m2, [base+round_vals-12+shiftq*2] +%if %2 + movd m1, [base+pb_1] + movd m3, [base+hmul_bits+2+%3*2] +%endif + pxor m0, m0 + punpcklwd m2, m0 +%if %2 + punpcklwd m3, m3 +%endif + pshufd m2, m2, q0000 +%if %2 + pshufd m1, m1, q0000 + pshufd m3, m3, q0000 + SCRATCH 1, 13, 12 +%endif + SCRATCH 2, 14, 13 +%if %2 + SCRATCH 3, 15, 14 +%endif + + DEFINE_ARGS buf, bufy, fg_data, h, unused, x +%if %2 + sub bufq, 82*(73-35*%3)+44-(82*3+41) +%else + sub bufq, 82*69+3 +%endif + add bufyq, 79+82*3 + mov hd, 70-35*%3 +.y_loop_ar3: + mov xq, -(76>>%2) + +.x_loop_ar3: + movu m0, [bufq+xq-82*3-3] ; y=-3,x=[-3,+12] + pxor m4, m4 + pcmpgtb m4, m0 + punpckhbw m3, m0, m4 + punpcklbw m0, m4 + + psrldq m5, m0, 2 + psrldq m6, m0, 4 + psrldq m7, m0, 6 + punpcklwd m4, m0, m5 + punpcklwd m6, m7 + pmaddwd m4, [rsp+ 0*16] + pmaddwd m6, [rsp+ 1*16] + paddd m4, m6 + + palignr m2, m3, m0, 10 + palignr m3, m0, 12 + psrldq m0, 8 + + movu m1, [bufq+xq-82*2-3] ; y=-2,x=[-3,+12] + pxor m6, m6 + pcmpgtb m6, m1 + punpckhbw m5, m1, m6 + punpcklbw m1, m6 + + punpcklwd m0, m2 + punpcklwd m3, m1 + pmaddwd m0, [rsp+ 2*16] + pmaddwd m3, [rsp+ 3*16] + paddd m0, m3 + paddd m0, m4 + + movu m2, [bufq+xq-82*1-3] ; y=-1,x=[-3,+12] + pxor m7, m7 + pcmpgtb m7, m2 + punpckhbw m6, m2, m7 + punpcklbw m2, m7 + + palignr m3, m5, m1, 10 + palignr m5, m1, 12 + psrldq m4, m2, 2 + + punpcklwd m3, m5 + punpcklwd m5, m2, m4 + pmaddwd m3, [rsp+ 6*16] + pmaddwd m5, m8 + paddd m3, m5 + paddd m0, m3 + + psrldq m3, m1, 2 + psrldq m4, m1, 4 + psrldq m5, m1, 6 + psrldq m1, 8 + + punpcklwd m3, m4 + punpcklwd m5, m1 + pmaddwd m3, [rsp+ 4*16] + pmaddwd m5, [rsp+ 5*16] + paddd m3, m5 + paddd m0, m3 + +%if %2 + movq m1, [bufyq+xq*2] +%if %3 + movq m3, [bufyq+xq*2+82] +%endif + pmaddubsw m7, m13, m1 +%if %3 + pmaddubsw m5, m13, m3 + paddw m7, m5 +%endif + pmulhrsw m7, m15 +%else + movd m7, [bufyq+xq] + pxor m1, m1 + pcmpgtb m1, m7 + punpcklbw m7, m1 +%endif + + psrldq m1, m2, 4 + psrldq m3, m2, 6 + palignr m4, m6, m2, 10 + palignr m6, m2, 12 + psrldq m2, 8 + + punpcklwd m1, m3 + punpcklwd m2, m4 + punpcklwd m6, m7 + pmaddwd m1, m9 + pmaddwd m2, m10 + pmaddwd m6, m11 + paddd m1, m2 + paddd m0, m6 + paddd m0, m1 + paddd m0, m14 + + movq m1, [bufq+xq-3] ; y=0,x=[-3,+4] + pxor m4, m4 + movd m5, [base+byte_blend] +.x_loop_ar3_inner: + pcmpgtb m2, m4, m1 + punpcklbw m3, m1, m2 + pmaddwd m2, m3, m12 + pshufd m3, m2, q1111 + paddd m2, m3 ; left+cur + paddd m2, m0 ; add top + psrldq m0, 4 + psrad m2, [fg_dataq+FGData.ar_coeff_shift] + ; don't packssdw, we only care about one value + packsswb m2, m2 + pandn m3, m5, m1 + pslld m2, 24 + pand m2, m5 + por m1, m2, m3 + movd [bufq+xq-3], m1 + psrldq m1, 1 + inc xq + jz .x_loop_ar3_end + test xq, 3 + jnz .x_loop_ar3_inner + jmp .x_loop_ar3 + +.x_loop_ar3_end: + add bufq, 82 + add bufyq, 82<<%3 + dec hd + jg .y_loop_ar3 + RET +%endmacro + +generate_grain_uv_fn 420, 1, 1 +generate_grain_uv_fn 422, 1, 0 +generate_grain_uv_fn 444, 0, 0 + +%macro vpgatherdw 5-6 ; dst, src, base, tmp_gpr[x2], tmp_xmm_reg +%assign %%idx 0 +%define %%tmp %2 +%if %0 == 6 +%define %%tmp %6 +%endif +%rep 4 +%if %%idx == 0 + movd %5 %+ d, %2 + pshuflw %%tmp, %2, q3232 +%else + movd %5 %+ d, %%tmp +%if %%idx == 2 + punpckhqdq %%tmp, %%tmp +%elif %%idx == 4 + psrlq %%tmp, 32 +%endif +%endif + movzx %4 %+ d, %5 %+ w + shr %5 %+ d, 16 + +%if %%idx == 0 + movd %1, [%3+%4] +%else + pinsrw %1, [%3+%4], %%idx + 0 +%endif + pinsrw %1, [%3+%5], %%idx + 1 +%assign %%idx %%idx+2 +%endrep +%endmacro + +INIT_XMM ssse3 +; fgy_32x32xn(dst, src, stride, fg_data, w, scaling, grain_lut, h, sby) +%if ARCH_X86_32 +%if STACK_ALIGNMENT < mmsize +cglobal fgy_32x32xn_8bpc, 0, 7, 16, 0 - (5 * mmsize + 16 * gprsize), \ + dst, src, scaling, unused1, fg_data, picptr, unused2 + ; copy stack arguments to new position post-alignment, so that we + ; don't have to keep the old stack location in a separate register + mov r0, r0m + mov r1, r2m + mov r2, r4m + mov r3, r6m + mov r4, r7m + mov r5, r8m + + mov [rsp+5*mmsize+ 4*gprsize], r0 + mov [rsp+5*mmsize+ 6*gprsize], r1 + mov [rsp+5*mmsize+ 8*gprsize], r2 + mov [rsp+5*mmsize+10*gprsize], r3 + mov [rsp+5*mmsize+11*gprsize], r4 + mov [rsp+5*mmsize+12*gprsize], r5 +%else +cglobal fgy_32x32xn_8bpc, 0, 7, 16, 5 * mmsize + 4 * gprsize, \ + dst, src, scaling, unused1, fg_data, picptr, unused2 +%endif + mov srcq, srcm + mov fg_dataq, r3m + mov scalingq, r5m +%if STACK_ALIGNMENT < mmsize +%define r0m [rsp+5*mmsize+ 4*gprsize] +%define r1m [rsp+5*mmsize+ 5*gprsize] +%define r2m [rsp+5*mmsize+ 6*gprsize] +%define r3m [rsp+5*mmsize+ 7*gprsize] +%define r4m [rsp+5*mmsize+ 8*gprsize] +%define r5m [rsp+5*mmsize+ 9*gprsize] +%define r6m [rsp+5*mmsize+10*gprsize] +%define r7m [rsp+5*mmsize+11*gprsize] +%define r8m [rsp+5*mmsize+12*gprsize] +%endif + LEA r5, pb_mask +%define base r5-pb_mask + mov r5m, picptrq +%else +cglobal fgy_32x32xn_8bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, grain_lut + lea r7, [pb_mask] +%define base r7-pb_mask +%endif + mov r6d, [fg_dataq+FGData.scaling_shift] + movd m3, [base+mul_bits+r6*2-14] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] + movd m4, [base+max+r6*4] + movd m5, [base+min+r6*2] + punpcklwd m3, m3 + punpcklwd m4, m4 + punpcklwd m5, m5 + pshufd m3, m3, q0000 + pshufd m4, m4, q0000 + pshufd m5, m5, q0000 + SCRATCH 3, 11, 0 + SCRATCH 4, 12, 1 + SCRATCH 5, 13, 2 + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, sby, see, overlap +%endif + + mov sbyd, r8m + mov overlapd, [fg_dataq+FGData.overlap_flag] ; left_overlap: overlap & 1 + test overlapd, overlapd + jz .no_vertical_overlap + mova m6, [base+pw_1024] + mova m7, [base+pb_27_17_17_27] + SCRATCH 6, 14, 3 + SCRATCH 7, 15, 4 + test sbyd, sbyd + jnz .vertical_overlap + ; fall-through + +.no_vertical_overlap: + mov r8m, overlapd +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, fg_data, picptr, unused + imul seed, (173 << 24) | 37 +%else + imul seed, sbyd, (173 << 24) | 37 +%endif + add seed, (105 << 24) | 178 + rol seed, 8 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + + mov r3m, seed + mov wq, r4m +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + unused1, unused2, see, unused3 +%endif + + lea src_bakq, [srcq+wq] + neg wq + sub dstmp, srcq +%if ARCH_X86_32 + mov r1m, src_bakq + mov r4m, wq + DEFINE_ARGS dst, src, scaling, see, unused1, unused2, unused3 +%endif + +.loop_x: +%if ARCH_X86_32 + mov seed, r3m +%endif + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, unused + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164 + lea offyq, [offyq+offxq*2+747] ; offy*stride+offx + +%if ARCH_X86_32 + ; r0m=dst, r1m=src_bak, r2m=stride, r3m=see, r4m=w, r5m=picptr, + ; r6m=grain_lut, r7m=h, r8m=overlap_v|h + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, unused +%endif + +.loop_x_odd: + mov hd, r7m + mov grain_lutq, grain_lutmp +.loop_y: + ; src + mova m0, [srcq] + pxor m2, m2 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m4, m0, scalingq-1, r0, r5, m3 + vpgatherdw m5, m1, scalingq-1, r0, r5, m3 +%else + vpgatherdw m4, m0, scalingq-1, r12, r13, m3 + vpgatherdw m5, m1, scalingq-1, r12, r13, m3 +%endif + REPX {psrlw x, 8}, m4, m5 + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq] + pcmpgtb m7, m2, m3 + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmullw m2, m4 + pmullw m3, m5 + pmulhrsw m2, m11 + pmulhrsw m3, m11 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + + add srcq, r2mp + add grain_lutq, 82 + dec hd + jg .loop_y + +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end +%if ARCH_X86_32 + mov srcq, r1mp + add srcq, r4mp +%else + lea srcq, [src_bakq+wq] +%endif + btc dword r8m, 2 + jc .next_blk + + add offxyd, 16 + test dword r8m, 2 ; r8m & 2 = have_top_overlap + jz .loop_x_odd + +%if ARCH_X86_32 + add dword [rsp+5*mmsize+1*gprsize], 16 +%else + add r11d, 16 ; top_offxyd +%endif + jnz .loop_x_odd_v_overlap + +.next_blk: + test dword r8m, 1 + jz .loop_x + + test dword r8m, 2 + jnz .loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +.loop_x_h_overlap: +%if ARCH_X86_32 + ; r0m=dst, r1m=src_bak, r2m=stride, r3m=see, r4m=w, r5m=picptr, + ; r6m=grain_lut, r7m=h, r8m=overlap_v|h + DEFINE_ARGS dst, src, scaling, offxy, unused1, unused2, unused3 + + add offxyd, 16 ; left_offxyd + mov [rsp+5*mmsize+0*gprsize], offxyd + + DEFINE_ARGS dst, src, scaling, see, unused1, unused2, unused3 + + mov seed, r3m +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, left_offxy + + lea left_offxyd, [offyd+16] ; previous column's offy*stride+offx +%endif + + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164 + lea offyq, [offyq+offxq*2+747] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, left_offxy +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +.loop_y_h_overlap: + ; src + mova m0, [srcq] + pxor m2, m2 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m4, m0, scalingq-1, r0, r5, m3 + vpgatherdw m5, m1, scalingq-1, r0, r5, m3 +%else + vpgatherdw m4, m0, scalingq-1, r12, r13, m3 + vpgatherdw m5, m1, scalingq-1, r12, r13, m3 +%endif + REPX {psrlw x, 8}, m4, m5 + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq] +%if ARCH_X86_32 + mov r5, [rsp+5*mmsize+0*gprsize] + movd m7, [grain_lutq+r5] +%else + movd m7, [grain_lutq+left_offxyq] +%endif + punpcklbw m7, m3 + pmaddubsw m6, m15, m7 + pmulhrsw m6, m14 + packsswb m6, m6 + shufps m6, m3, q3210 + pcmpgtb m2, m6 + punpcklbw m7, m6, m2 + punpckhbw m6, m2 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmullw m7, m4 + pmullw m6, m5 + pmulhrsw m7, m11 + pmulhrsw m6, m11 + + ; dst = clip_pixel(src, noise) + paddw m0, m7 + paddw m1, m6 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + + add srcq, r2mp + add grain_lutq, 82 + dec hd + jg .loop_y_h_overlap + +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end +%if ARCH_X86_32 + mov srcq, r1m + add srcq, r4m +%else + lea srcq, [src_bakq+wq] +%endif + xor dword r8m, 4 + add offxyd, 16 + + ; since this half-block had left-overlap, the next does not + test dword r8m, 2 ; have_top_overlap + jz .loop_x_odd +%if ARCH_X86_32 + add dword [rsp+5*mmsize+1*gprsize], 16 +%else + add r11d, 16 ; top_offxyd +%endif + jmp .loop_x_odd_v_overlap + +.end: + RET + +.vertical_overlap: +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, tmp, sby, see, overlap +%endif + + or overlapd, 2 ; top_overlap: overlap & 2 + mov r8m, overlapd + movzx sbyd, sbyb +%if ARCH_X86_32 + imul r4, [fg_dataq+FGData.seed], 0x00010001 + DEFINE_ARGS tmp, src, scaling, sby, see, picptr, unused +%else + imul seed, [fg_dataq+FGData.seed], 0x00010001 +%endif + imul tmpd, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add tmpd, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and tmpd, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, tmpd +%if ARCH_X86_32 + xor sbyd, seed ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, scaling, see, w, picptr, src_bak + + mov r3m, seed + mov wq, r4m +%else + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + tmp, unused2, see, unused3 +%endif + + lea src_bakq, [srcq+wq] + neg wq + sub dstmp, srcq +%if ARCH_X86_32 + mov r1m, src_bakq + mov r4m, wq + DEFINE_ARGS tmp, src, scaling, see, unused1, picptr, unused2 +%endif + +.loop_x_v_overlap: +%if ARCH_X86_32 + mov seed, r3m +%endif + ; we assume from the block above that bits 8-15 of tmpd are zero'ed, + ; because of the 'and tmpd, 0x00ff00ff' above + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp tmpb ; parity of top_seed + shr seed, 16 + shl tmpd, 16 + test seeb, seeh + setp tmpb ; parity of cur_seed + or r6d, 0x00010001 + xor tmpd, r6d + mov seed, tmpd + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, unused, top_offxy + + mov offyd, seed + mov offxd, seed +%endif + + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*2+0x10001*747+32*82] + +%if ARCH_X86_32 + DEFINE_ARGS top_offxy, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, unused, top_offxy +%endif + + movzx top_offxyd, offxyw +%if ARCH_X86_32 + mov [rsp+5*mmsize+1*gprsize], top_offxyd + + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + shr offxyd, 16 + +.loop_x_odd_v_overlap: +%if ARCH_X86_32 + mov r5, r5m + lea r5, [base+pb_27_17] + mov [rsp+5*mmsize+12], r5 +%else + mova m8, [pb_27_17] +%endif + mov hd, r7m + mov grain_lutq, grain_lutmp +.loop_y_v_overlap: + ; src + mova m0, [srcq] + pxor m2, m2 + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m4, m0, scalingq-1, r0, r5, m3 + vpgatherdw m5, m1, scalingq-1, r0, r5, m3 +%else + vpgatherdw m4, m0, scalingq-1, r12, r13, m3 + vpgatherdw m5, m1, scalingq-1, r12, r13, m3 +%endif + REPX {psrlw x, 8}, m4, m5 + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq] +%if ARCH_X86_32 + mov r5, [rsp+5*mmsize+1*gprsize] + movu m7, [grain_lutq+r5] +%else + movu m7, [grain_lutq+top_offxyq] +%endif + punpckhbw m6, m7, m3 + punpcklbw m7, m3 +%if ARCH_X86_32 + mov r5, [rsp+5*mmsize+12] + pmaddubsw m3, [r5], m6 + pmaddubsw m6, [r5], m7 +%else + pmaddubsw m3, m8, m6 + pmaddubsw m6, m8, m7 +%endif + pmulhrsw m3, m14 + pmulhrsw m6, m14 + packsswb m6, m3 + pcmpgtb m7, m2, m6 + punpcklbw m2, m6, m7 + punpckhbw m6, m7 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmullw m2, m4 + pmullw m6, m5 + pmulhrsw m2, m11 + pmulhrsw m6, m11 + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m6 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + +%if ARCH_X86_32 + add dword [rsp+5*mmsize+12], mmsize +%else + mova m8, [pb_17_27] +%endif + add srcq, r2mp + add grain_lutq, 82 + dec hw + jz .end_y_v_overlap + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + btc hd, 16 + jnc .loop_y_v_overlap + jmp .loop_y + +.end_y_v_overlap: +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end_hv +%if ARCH_X86_32 + mov srcq, r1mp + add srcq, r4mp +%else + lea srcq, [src_bakq+wq] +%endif + btc dword r8m, 2 + jc .loop_x_hv_overlap + add offxyd, 16 +%if ARCH_X86_32 + add dword [rsp+5*mmsize+1*gprsize], 16 +%else + add top_offxyd, 16 +%endif + jmp .loop_x_odd_v_overlap + +.loop_x_hv_overlap: +%if ARCH_X86_32 + mov r5, r5m + lea r5, [base+pb_27_17] + mov [rsp+5*mmsize+12], r5 + + DEFINE_ARGS tmp, src, scaling, offxy, w, picptr, src_bak + + mov r5, [rsp+5*mmsize+1*gprsize] + mov r4, offxyd + add r5, 16 + add r4, 16 + mov [rsp+5*mmsize+2*gprsize], r5 ; topleft_offxy + mov [rsp+5*mmsize+0*gprsize], r4 ; left_offxy + + DEFINE_ARGS tmp, src, scaling, see, w, picptr, src_bak + + xor tmpd, tmpd + mov seed, r3m +%else + mova m8, [pb_27_17] + + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + tmp, unused2, see, unused3 + + ; we assume from the block above that bits 8-15 of tmpd are zero'ed +%endif + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp tmpb ; parity of top_seed + shr seed, 16 + shl tmpd, 16 + test seeb, seeh + setp tmpb ; parity of cur_seed + or r6d, 0x00010001 + xor tmpd, r6d + mov seed, tmpd + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, unused1, unused2, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy + + lea topleft_offxyq, [top_offxyq+16] + lea left_offxyq, [offyq+16] + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*2+0x10001*747+32*82] + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut + + movzx r5, offxyw ; top_offxy + mov [rsp+5*mmsize+1*gprsize], r5 +%else + DEFINE_ARGS dst, src, stride, src_bak, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy + + movzx top_offxyd, offxyw +%endif + shr offxyd, 16 + + mov hd, r7m + mov grain_lutq, grain_lutmp +.loop_y_hv_overlap: + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq] +%if ARCH_X86_32 + mov r5, [rsp+5*mmsize+1*gprsize] ; top_offxy + mov r0, [rsp+5*mmsize+0*gprsize] ; left_offxy + movu m6, [grain_lutq+r5] + mov r5, [rsp+5*mmsize+2*gprsize] ; topleft_offxy + movd m4, [grain_lutq+r0] + movd m7, [grain_lutq+r5] +%else + movu m6, [grain_lutq+top_offxyq] + movd m4, [grain_lutq+left_offxyq] + movd m7, [grain_lutq+topleft_offxyq] +%endif + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw m4, m3 + punpcklbw m7, m6 + pmaddubsw m2, m15, m4 + pmaddubsw m4, m15, m7 + pmulhrsw m2, m14 + pmulhrsw m4, m14 + packsswb m2, m2 + packsswb m4, m4 + shufps m2, m3, q3210 + shufps m4, m6, q3210 + ; followed by v interpolation (top | cur -> cur) + punpcklbw m3, m4, m2 + punpckhbw m4, m2 +%if ARCH_X86_32 + mov r5, [rsp+5*mmsize+12] + pmaddubsw m7, [r5], m4 + pmaddubsw m4, [r5], m3 +%else + pmaddubsw m7, m8, m4 + pmaddubsw m4, m8, m3 +%endif + pmulhrsw m7, m14 + pmulhrsw m4, m14 + packsswb m4, m7 + pxor m2, m2 + pcmpgtb m7, m2, m4 + punpcklbw m3, m4, m7 + punpckhbw m4, m7 + + ; src + mova m0, [srcq] + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m5, m0, scalingq-1, r0, r5, m7 + vpgatherdw m6, m1, scalingq-1, r0, r5, m7 +%else + vpgatherdw m5, m0, scalingq-1, r13, r14, m7 + vpgatherdw m6, m1, scalingq-1, r13, r14, m7 +%endif + REPX {psrlw x, 8}, m5, m6 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmullw m3, m5 + pmullw m4, m6 + pmulhrsw m3, m11 + pmulhrsw m4, m11 + + ; dst = clip_pixel(src, noise) + paddw m0, m3 + paddw m1, m4 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + +%if ARCH_X86_32 + add dword [rsp+5*mmsize+12], mmsize +%else + mova m8, [pb_17_27] +%endif + add srcq, r2mp + add grain_lutq, 82 + dec hw + jz .end_y_hv_overlap + ; 2 lines get vertical overlap, then fall back to non-overlap code for + ; remaining (up to) 30 lines + btc hd, 16 + jnc .loop_y_hv_overlap + jmp .loop_y_h_overlap + +.end_y_hv_overlap: +%if ARCH_X86_32 + add r4mp, 16 +%else + add wq, 16 +%endif + jge .end_hv +%if ARCH_X86_32 + mov srcq, r1m + add srcq, r4m +%else + lea srcq, [src_bakq+wq] +%endif + xor dword r8m, 4 + add offxyd, 16 +%if ARCH_X86_32 + add dword [rsp+5*mmsize+1*gprsize], 16 +%else + add top_offxyd, 16 +%endif + jmp .loop_x_odd_v_overlap + +.end_hv: + RET + +%macro FGUV_FN 3 ; name, ss_hor, ss_ver +INIT_XMM ssse3 +%if ARCH_X86_32 +; fguv_32x32xn_i420_ssse3(dst, src, stride, fg_data, w, scaling, grain_lut, h, +; sby, luma, lstride, uv_pl, is_id) +%if STACK_ALIGNMENT < mmsize +DECLARE_ARG 0, 1, 2, 3, 4, 5, 6, 7, 8 +cglobal fguv_32x32xn_i%1_8bpc, 0, 7, 8, 0 - (7 * mmsize + (13 + 3) * gprsize), \ + tmp, src, scaling, h, fg_data, picptr, unused + mov r0, r0m + mov r1, r2m + mov r2, r4m + mov r3, r6m + mov r4, r7m + mov [rsp+7*mmsize+3*gprsize], r0 + mov [rsp+7*mmsize+5*gprsize], r1 + mov [rsp+7*mmsize+7*gprsize], r2 + mov [rsp+7*mmsize+9*gprsize], r3 + mov [rsp+7*mmsize+10*gprsize], r4 + + mov r0, r8m + mov r1, r9m + mov r2, r10m + mov r4, r11m + mov r3, r12m + mov [rsp+7*mmsize+11*gprsize], r0 + mov [rsp+7*mmsize+12*gprsize], r1 + mov [rsp+7*mmsize+13*gprsize], r2 + mov [rsp+7*mmsize+14*gprsize], r4 +%else +cglobal fguv_32x32xn_i%1_8bpc, 0, 7, 8, 7 * mmsize + (4) * gprsize, \ + tmp, src, scaling, h, fg_data, picptr, unused +%endif + mov srcq, srcm + mov fg_dataq, r3m + mov scalingq, r5m +%if STACK_ALIGNMENT < mmsize +%define r0m [rsp+7*mmsize+ 3*gprsize] +%define r1m [rsp+7*mmsize+ 4*gprsize] +%define r2m [rsp+7*mmsize+ 5*gprsize] +%define r3m [rsp+7*mmsize+ 6*gprsize] +%define r4m [rsp+7*mmsize+ 7*gprsize] +%define r5m [rsp+7*mmsize+ 8*gprsize] +%define r6m [rsp+7*mmsize+ 9*gprsize] +%define r7m [rsp+7*mmsize+10*gprsize] +%define r8m [rsp+7*mmsize+11*gprsize] +%define r9m [rsp+7*mmsize+12*gprsize] +%define r10m [rsp+7*mmsize+13*gprsize] +%define r11m [rsp+7*mmsize+14*gprsize] +%define r12m [rsp+7*mmsize+15*gprsize] +%endif + LEA r5, pb_mask +%define base r5-pb_mask + mov r5m, r5 +%else +cglobal fguv_32x32xn_i%1_8bpc, 6, 15, 16, dst, src, stride, fg_data, w, scaling, \ + grain_lut, tmp, sby, luma, lstride, uv_pl, is_id + lea r8, [pb_mask] +%define base r8-pb_mask +%endif + mov r6d, [fg_dataq+FGData.scaling_shift] + movd m3, [base+mul_bits+r6*2-14] + mov r6d, [fg_dataq+FGData.clip_to_restricted_range] + lea tmpd, [r6d*2] +%if ARCH_X86_32 && STACK_ALIGNMENT < mmsize + test r3, r3 +%else + cmp dword r12m, 0 ; is_idm +%endif + movd m5, [base+min+r6*2] + cmovne r6d, tmpd + movd m4, [base+max+r6*2] + punpcklwd m3, m3 + punpcklwd m5, m5 + punpcklwd m4, m4 + pshufd m3, m3, q0000 + pshufd m5, m5, q0000 + pshufd m4, m4, q0000 + SCRATCH 3, 11, 0 + SCRATCH 4, 12, 1 + SCRATCH 5, 13, 2 + + cmp byte [fg_dataq+FGData.chroma_scaling_from_luma], 0 + jne .csfl + +%macro %%FGUV_32x32xN_LOOP 3 ; not-csfl, ss_hor, ss_ver +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, unused, sby, see, overlap +%endif + +%if %1 + mov r6d, dword r11m + movd m0, [fg_dataq+FGData.uv_mult+r6*4] + movd m1, [fg_dataq+FGData.uv_luma_mult+r6*4] + punpcklbw m6, m1, m0 + movd m7, [fg_dataq+FGData.uv_offset+r6*4] + punpcklwd m6, m6 + punpcklwd m7, m7 + pshufd m6, m6, q0000 + pshufd m7, m7, q0000 + SCRATCH 6, 14, 3 + SCRATCH 7, 15, 4 +%endif + + mov sbyd, r8m + mov overlapd, [fg_dataq+FGData.overlap_flag] ; left_overlap: overlap & 1 + test overlapd, overlapd + jz %%no_vertical_overlap +%if ARCH_X86_32 +%if %2 + mova m1, [base+pb_23_22_h] +%else + mova m1, [base+pb_27_17_17_27] +%endif + mova m0, [base+pw_1024] +%else +%if %2 + mova m1, [pb_23_22_h] +%else + mova m1, [pb_27_17_17_27] +%endif + mova m0, [pw_1024] +%endif + SCRATCH 0, 8, 5 + SCRATCH 1, 9, 6 + test sbyd, sbyd + jnz %%vertical_overlap + ; fall-through + +%%no_vertical_overlap: + mov r8m, overlapd +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, see, fg_data, picptr, overlap + imul seed, (173 << 24) | 37 +%else + imul seed, sbyd, (173 << 24) | 37 +%endif + add seed, (105 << 24) | 178 + rol seed, 8 + movzx seed, seew + xor seed, [fg_dataq+FGData.seed] + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS luma, src, scaling, see, w, picptr, src_bak +%define luma_bakq lumaq + + mov wq, r4m +%if %3 + shl r10mp, 1 +%endif +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + unused2, unused3, see, overlap, unused4, src_bak, lstride, luma_bak + + mov lstrideq, r10mp +%endif + + mov lumaq, r9mp + lea src_bakq, [srcq+wq] + lea luma_bakq, [lumaq+wq*(1+%2)] + neg wq + sub r0mp, srcq +%if ARCH_X86_32 + mov r1m, src_bakq + mov r11m, luma_bakq + mov r4m, wq + + DEFINE_ARGS tmp, src, scaling, see, unused1, picptr, unused2 +%else + mov r11mp, src_bakq + mov r12mp, strideq +%endif + +%%loop_x: +%if ARCH_X86_32 + mov seed, r3m +%endif + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, overlap, unused1, unused2, lstride + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyq, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+(3+(6>>%2))] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, overlap, unused1, unused2, lstride, luma_bak +%endif + +%%loop_x_odd: + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y: + ; src +%if ARCH_X86_32 + mov lumaq, r9mp +%endif +%if %2 + mova m4, [lumaq+ 0] + mova m6, [lumaq+16] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq + mov r5, r5m + movd m7, [base+pb_1] +%else + movd m7, [pb_1] +%endif + pshufd m7, m7, q0000 + pxor m2, m2 + pmaddubsw m4, m7 + pmaddubsw m6, m7 + pavgw m4, m2 + pavgw m6, m2 +%else + mova m4, [lumaq] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif + pxor m2, m2 +%endif + +%if %1 +%if %2 + packuswb m4, m6 ; luma +%endif + punpckhbw m6, m4, m0 + punpcklbw m4, m0 ; { luma, chroma } + pmaddubsw m6, m14 + pmaddubsw m4, m14 + psraw m6, 6 + psraw m4, 6 + paddw m6, m15 + paddw m4, m15 + packuswb m4, m6 ; pack+unpack = clip + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%elif %2 == 0 + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m4, scalingq-1, r0, r5 + vpgatherdw m5, m6, scalingq-1, r0, r5 +%else + vpgatherdw m7, m4, scalingq-1, r12, r2 + vpgatherdw m5, m6, scalingq-1, r12, r2 +%endif + REPX {psrlw x, 8}, m7, m5 + + ; unpack chroma_source + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq+ 0] + pcmpgtb m6, m2, m3 + punpcklbw m2, m3, m6 + punpckhbw m3, m6 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmullw m2, m7 + pmullw m3, m5 + pmulhrsw m2, m11 + pmulhrsw m3, m11 + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + +%if ARCH_X86_32 + add srcq, r2mp + ; we already incremented lumaq above +%else + add srcq, r12mp +%if %3 + lea lumaq, [lumaq+lstrideq*2] +%else + add lumaq, lstrideq +%endif +%endif + add grain_lutq, 82 + dec hw + jg %%loop_y + +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, w, picptr, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end +%if ARCH_X86_32 + mov srcq, r1mp + mov lumaq, r11mp +%else + mov srcq, r11mp +%endif + lea lumaq, [luma_bakq+wq*(1+%2)] + add srcq, wq +%if ARCH_X86_32 + mov r4m, wq + mov r9m, lumaq +%endif +%if %2 == 0 + ; adjust top_offxy +%if ARCH_X86_32 + add dword [rsp+7*mmsize+1*gprsize], 16 +%else + add r11d, 16 +%endif + add offxyd, 16 + btc dword r8m, 2 + jc %%loop_x_even + test dword r8m, 2 + jz %%loop_x_odd + jmp %%loop_x_odd_v_overlap +%%loop_x_even: +%endif + test dword r8m, 1 + jz %%loop_x + + ; r8m = sbym + test dword r8m, 2 + jne %%loop_x_hv_overlap + + ; horizontal overlap (without vertical overlap) +%%loop_x_h_overlap: +%if ARCH_X86_32 +%if %2 + lea r6, [offxyd+16] + mov [rsp+7*mmsize+0*gprsize], r6 +%else + mov [rsp+7*mmsize+0*gprsize], offxyd +%endif + + DEFINE_ARGS luma, src, scaling, see, w, picptr, grain_lut + + mov seed, r3m +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, unused1, unused2, lstride + +%if %2 + lea left_offxyd, [offyd+16] ; previous column's offy*stride+offx +%else + mov left_offxyd, offyd +%endif +%endif + mov r6d, seed + or seed, 0xEFF4 + shr r6d, 1 + test seeb, seeh + lea seed, [r6+0x8000] + cmovp seed, r6d ; updated seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS luma, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, unused1, unused2, lstride + + mov offyd, seed + mov offxd, seed +%endif + ror offyd, 8 + shr offxd, 12 + and offyd, 0xf + imul offyd, 164>>%3 + lea offyq, [offyq+offxq*(2-%2)+(3+(6>>%3))*82+3+(6>>%2)] ; offy*stride+offx + +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, unused1, unused2, lstride, luma_bak +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +%%loop_y_h_overlap: + ; src +%if ARCH_X86_32 + mov lumaq, r9mp +%endif +%if %2 + mova m4, [lumaq+ 0] + mova m6, [lumaq+16] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq + mov r5, r5m + movd m7, [base+pb_1] +%else + movd m7, [pb_1] +%endif + pshufd m7, m7, q0000 + pxor m2, m2 + pmaddubsw m4, m7 + pmaddubsw m6, m7 + pavgw m4, m2 + pavgw m6, m2 +%else + mova m4, [lumaq] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif + pxor m2, m2 +%endif + +%if %1 +%if %2 + packuswb m4, m6 ; luma +%endif + punpckhbw m6, m4, m0 + punpcklbw m4, m0 ; { luma, chroma } + pmaddubsw m6, m14 + pmaddubsw m4, m14 + psraw m6, 6 + psraw m4, 6 + paddw m6, m15 + paddw m4, m15 + packuswb m4, m6 ; pack+unpack = clip + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%elif %2 == 0 + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m4, scalingq-1, r0, r5 + vpgatherdw m5, m6, scalingq-1, r0, r5 +%else + vpgatherdw m7, m4, scalingq-1, r12, r2 + vpgatherdw m5, m6, scalingq-1, r12, r2 +%endif + REPX {psrlw x, 8}, m7, m5 + + ; unpack chroma_source + punpckhbw m1, m0, m2 + punpcklbw m0, m2 ; m0-1: src as word + + ; grain = grain_lut[offy+y][offx+x] + movu m4, [grain_lutq+offxyq+ 0] +%if ARCH_X86_32 + mov r0, [rsp+7*mmsize+0*gprsize] + movd m2, [grain_lutq+r0+ 0] +%else + movd m2, [grain_lutq+left_offxyq+ 0] +%endif + punpcklbw m2, m4 + pmaddubsw m3, m9, m2 + pmulhrsw m3, m8 + packsswb m3, m3 + shufps m3, m4, q3210 + pxor m4, m4 + pcmpgtb m4, m3 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmullw m2, m7 + pmullw m3, m5 + pmulhrsw m2, m11 + pmulhrsw m3, m11 + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m13 + pmaxsw m1, m13 + pminsw m0, m12 + pminsw m1, m12 + packuswb m0, m1 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + +%if ARCH_X86_32 + add srcq, r2mp + ; lumaq has already been incremented above +%else + add srcq, r12mp +%if %3 + lea lumaq, [lumaq+lstrideq*2] +%else + add lumaq, lstrideq +%endif +%endif + add grain_lutq, 82 + dec hw + jg %%loop_y_h_overlap + +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, w, picptr, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end +%if ARCH_X86_32 + mov srcq, r1mp + mov lumaq, r11mp +%else + mov srcq, r11mp +%endif + lea lumaq, [luma_bakq+wq*(1+%2)] + add srcq, wq +%if ARCH_X86_32 + mov r4m, wq + mov r9m, lumaq +%endif +%if %2 == 0 + xor dword r8m, 4 + ; adjust top_offxyd +%if ARCH_X86_32 + add dword [rsp+7*mmsize+1*gprsize], 16 +%else + add r11d, 16 +%endif + add offxyd, 16 +%endif + + ; r8m = sbym + test dword r8m, 2 +%if %2 + jne %%loop_x_hv_overlap + jmp %%loop_x_h_overlap +%else + jne %%loop_x_odd_v_overlap + jmp %%loop_x_odd +%endif + +%%end: + RET + +%%vertical_overlap: +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, sby, fg_data, picptr, overlap +%else + DEFINE_ARGS dst, src, stride, fg_data, w, scaling, grain_lut, tmp, sby, see, overlap +%endif + + or overlapd, 2 ; top_overlap: overlap & 2 + mov r8m, overlapd + movzx sbyd, sbyb +%if ARCH_X86_32 + imul r4, [fg_dataq+FGData.seed], 0x00010001 + DEFINE_ARGS tmp, src, scaling, sby, see, picptr, unused +%else + imul seed, [fg_dataq+FGData.seed], 0x00010001 +%endif + imul tmpd, sbyd, 173 * 0x00010001 + imul sbyd, 37 * 0x01000100 + add tmpd, (105 << 16) | 188 + add sbyd, (178 << 24) | (141 << 8) + and tmpd, 0x00ff00ff + and sbyd, 0xff00ff00 + xor seed, tmpd +%if ARCH_X86_32 + xor sbyd, seed ; (cur_seed << 16) | top_seed + + DEFINE_ARGS luma, src, scaling, see, w, picptr, src_bak + + mov r3m, seed + mov wq, r4m +%if %3 + shl r10mp, 1 +%endif +%else + xor seed, sbyd ; (cur_seed << 16) | top_seed + + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + tmp, unused2, see, overlap, unused3, src_bak, lstride, luma_bak + + mov lstrideq, r10mp +%endif + + mov lumaq, r9mp + lea src_bakq, [srcq+wq] + lea luma_bakq, [lumaq+wq*(1+%2)] + neg wq + sub r0mp, srcq +%if ARCH_X86_32 + mov r1m, src_bakq + mov r11m, luma_bakq + mov r4m, wq + + DEFINE_ARGS tmp, src, scaling, see, unused1, picptr, unused2 +%else + mov r11mp, src_bakq + mov r12mp, strideq +%endif + +%%loop_x_v_overlap: +%if ARCH_X86_32 + mov seed, r3m + xor tmpd, tmpd +%endif + ; we assume from the block above that bits 8-15 of tmpd are zero'ed + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp tmpb ; parity of top_seed + shr seed, 16 + shl tmpd, 16 + test seeb, seeh + setp tmpb ; parity of cur_seed + or r6d, 0x00010001 + xor tmpd, r6d + mov seed, tmpd + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS dst, src, scaling, offy, h, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, overlap, top_offxy, unused, lstride + + mov offxd, seed + mov offyd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + +%if ARCH_X86_32 + DEFINE_ARGS tmp, src, scaling, offxy, h, picptr, top_offxy +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, overlap, top_offxy, unused, lstride, luma_bak +%endif + + movzx top_offxyd, offxyw + shr offxyd, 16 +%if ARCH_X86_32 + mov [rsp+7*mmsize+1*gprsize], top_offxyd + + DEFINE_ARGS luma, src, scaling, offxy, h, picptr, grain_lut +%endif + +%%loop_x_odd_v_overlap: + mov hd, r7m + mov grain_lutq, grain_lutmp +%if ARCH_X86_32 + mov r5, r5m +%endif +%if %3 + mova m1, [PIC_ptr(pb_23_22)] +%else + mova m1, [PIC_ptr(pb_27_17)] +%endif +%%loop_y_v_overlap: +%if ARCH_X86_32 + mov lumaq, r9mp +%endif +%if %2 + mova m4, [lumaq+ 0] + mova m6, [lumaq+16] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq + mov r5, r5m + movd m7, [base+pb_1] +%else + movd m7, [pb_1] +%endif + pshufd m7, m7, q0000 + pxor m2, m2 + pmaddubsw m4, m7 + pmaddubsw m6, m7 + pavgw m4, m2 + pavgw m6, m2 +%else + mova m4, [lumaq] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif + pxor m2, m2 +%endif + +%if %1 +%if %2 + packuswb m4, m6 ; luma +%endif + punpckhbw m6, m4, m0 + punpcklbw m4, m0 ; { luma, chroma } + pmaddubsw m6, m14 + pmaddubsw m4, m14 + psraw m6, 6 + psraw m4, 6 + paddw m6, m15 + paddw m4, m15 + packuswb m4, m6 ; pack+unpack = clip + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%elif %2 == 0 + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%endif + + ; scaling[luma_src] +%if ARCH_X86_32 + vpgatherdw m7, m4, scalingq-1, r0, r5 + vpgatherdw m5, m6, scalingq-1, r0, r5 +%else + vpgatherdw m7, m4, scalingq-1, r12, r2 + vpgatherdw m5, m6, scalingq-1, r12, r2 +%endif + REPX {psrlw x, 8}, m7, m5 + + ; grain = grain_lut[offy+y][offx+x] + movu m3, [grain_lutq+offxyq] +%if ARCH_X86_32 + mov r0, [rsp+7*mmsize+1*gprsize] + movu m4, [grain_lutq+r0] +%else + movu m4, [grain_lutq+top_offxyq] +%endif + punpckhbw m6, m4, m3 + punpcklbw m4, m3 + pmaddubsw m2, m1, m6 + pmaddubsw m3, m1, m4 + pmulhrsw m2, m8 + pmulhrsw m3, m8 + packsswb m3, m2 + pxor m6, m6 + pcmpgtb m6, m3 + punpcklbw m2, m3, m6 + punpckhbw m3, m6 + + ; noise = round2(scaling[luma_src] * grain, scaling_shift) + pmullw m2, m7 + pmullw m3, m5 + pmulhrsw m2, m11 + pmulhrsw m3, m11 + + ; unpack chroma_source + pxor m4, m4 + punpckhbw m6, m0, m4 + punpcklbw m0, m4 ; m0-1: src as word + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m6, m3 + pmaxsw m0, m13 + pmaxsw m6, m13 + pminsw m0, m12 + pminsw m6, m12 + packuswb m0, m6 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + + dec hw + je %%end_y_v_overlap +%if ARCH_X86_32 + add srcq, r2mp + ; lumaq has already been incremented above +%else + add srcq, r12mp +%if %3 + lea lumaq, [lumaq+lstrideq*2] +%else + add lumaq, lstrideq +%endif +%endif + add grain_lutq, 82 +%if %3 == 0 + btc hd, 16 +%if ARCH_X86_32 + mov r5, r5m +%endif + mova m1, [PIC_ptr(pb_17_27)] + jnc %%loop_y_v_overlap +%endif + jmp %%loop_y + +%%end_y_v_overlap: +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, w, picptr, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end_hv +%if ARCH_X86_32 + mov srcq, r1mp + mov lumaq, r11mp +%else + mov srcq, r11mp +%endif + lea lumaq, [luma_bakq+wq*(1+%2)] + add srcq, wq +%if ARCH_X86_32 + mov r4m, wq + mov r9m, lumaq +%endif + +%if %2 + ; since fg_dataq.overlap is guaranteed to be set, we never jump + ; back to .loop_x_v_overlap, and instead always fall-through to + ; h+v overlap +%else +%if ARCH_X86_32 + add dword [rsp+7*mmsize+1*gprsize], 16 +%else + add top_offxyd, 16 +%endif + add offxyd, 16 + btc dword r8m, 2 + jnc %%loop_x_odd_v_overlap +%endif + +%%loop_x_hv_overlap: +%if ARCH_X86_32 + DEFINE_ARGS tmp, src, scaling, offxy, w, picptr, unused + + mov r6, [rsp+7*mmsize+1*gprsize] +%if %2 + lea r0, [r3d+16] + add r6, 16 + mov [rsp+7*mmsize+0*gprsize], r0 ; left_offxy +%else + mov [rsp+7*mmsize+0*gprsize], r3 ; left_offxy +%endif + mov [rsp+7*mmsize+2*gprsize], r6 ; topleft_offxy + + DEFINE_ARGS tmp, src, scaling, see, w, picptr, unused + + mov seed, r3m + xor tmpd, tmpd +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + tmp, offxy, see, left_offxy, top_offxy, topleft_offxy, lstride + +%if %2 + lea topleft_offxyq, [top_offxyq+16] + lea left_offxyq, [offxyq+16] +%else + mov topleft_offxyq, top_offxyq + mov left_offxyq, offxyq +%endif + + ; we assume from the block above that bits 8-15 of tmpd are zero'ed +%endif + mov r6d, seed + or seed, 0xeff4eff4 + test seeb, seeh + setp tmpb ; parity of top_seed + shr seed, 16 + shl tmpd, 16 + test seeb, seeh + setp tmpb ; parity of cur_seed + or r6d, 0x00010001 + xor tmpd, r6d + mov seed, tmpd + ror seed, 1 ; updated (cur_seed << 16) | top_seed + +%if ARCH_X86_32 + mov r3m, seed + + DEFINE_ARGS tmp, src, scaling, offy, w, picptr, offx + + mov offxd, offyd +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + offx, offy, see, left_offxy, top_offxy, topleft_offxy, lstride + + mov offxd, seed + mov offyd, seed +%endif + ror offyd, 8 + ror offxd, 12 + and offyd, 0xf000f + and offxd, 0xf000f + imul offyd, 164>>%3 + ; offxy=offy*stride+offx, (cur_offxy << 16) | top_offxy + lea offyq, [offyq+offxq*(2-%2)+0x10001*((3+(6>>%3))*82+3+(6>>%2))+(32>>%3)*82] + +%if ARCH_X86_32 + DEFINE_ARGS top_offxy, src, scaling, offxy, h, picptr, grain_lut +%else + DEFINE_ARGS dst, src, stride, luma, w, scaling, grain_lut, \ + h, offxy, see, left_offxy, top_offxy, topleft_offxy, lstride, luma_bak +%endif + + movzx top_offxyd, offxyw + shr offxyd, 16 +%if ARCH_X86_32 + mov [rsp+7*mmsize+1*gprsize], top_offxyd +%endif + + mov hd, r7m + mov grain_lutq, grain_lutmp +%if ARCH_X86_32 + mov r5, r5m +%endif +%if %3 + mova m3, [PIC_ptr(pb_23_22)] +%else + mova m3, [PIC_ptr(pb_27_17)] +%endif +%%loop_y_hv_overlap: + ; grain = grain_lut[offy+y][offx+x] +%if ARCH_X86_32 + mov r0, [rsp+7*mmsize+2*gprsize] ; topleft_offxy + mov r5, [rsp+7*mmsize+1*gprsize] ; top_offxy + movd m1, [grain_lutq+r0] + mov r0, [rsp+7*mmsize+0*gprsize] ; left_offxy +%else + movd m1, [grain_lutq+topleft_offxyq] +%endif + movu m2, [grain_lutq+offxyq] +%if ARCH_X86_32 + movu m6, [grain_lutq+r5] + movd m4, [grain_lutq+r0] +%else + movu m6, [grain_lutq+top_offxyq] + movd m4, [grain_lutq+left_offxyq] +%endif + ; do h interpolation first (so top | top/left -> top, left | cur -> cur) + punpcklbw m1, m6 + punpcklbw m4, m2 + pmaddubsw m0, m9, m1 + pmaddubsw m1, m9, m4 + REPX {pmulhrsw x, m8}, m0, m1 + packsswb m0, m1 + shufps m4, m0, m2, q3232 + shufps m0, m6, q3210 + ; followed by v interpolation (top | cur -> cur) + punpcklbw m2, m0, m4 + punpckhbw m0, m4 + pmaddubsw m4, m3, m0 + pmaddubsw m1, m3, m2 + pmulhrsw m4, m8 + pmulhrsw m1, m8 + packsswb m1, m4 + + ; src +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, w, picptr, grain_lut + + mov lumaq, r9mp +%endif +%if %2 + mova m4, [lumaq+ 0] + mova m6, [lumaq+16] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq + mov r5, r5m + movd m7, [base+pb_1] +%else + movd m7, [pb_1] +%endif + pshufd m7, m7, q0000 + pxor m2, m2 + pmaddubsw m4, m7 + pmaddubsw m6, m7 + pavgw m4, m2 + pavgw m6, m2 +%else + mova m4, [lumaq] + mova m0, [srcq] +%if ARCH_X86_32 + add lumaq, r10mp + mov r9mp, lumaq +%endif + pxor m2, m2 +%endif + +%if %1 +%if %2 + packuswb m4, m6 ; luma +%endif + punpckhbw m6, m4, m0 + punpcklbw m4, m0 ; { luma, chroma } + pmaddubsw m6, m14 + pmaddubsw m4, m14 + psraw m6, 6 + psraw m4, 6 + paddw m6, m15 + paddw m4, m15 + packuswb m4, m6 ; pack+unpack = clip + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%elif %2 == 0 + punpckhbw m6, m4, m2 + punpcklbw m4, m2 +%endif + + ; scaling[src] +%if ARCH_X86_32 + vpgatherdw m7, m4, scalingq-1, r0, r5 + vpgatherdw m5, m6, scalingq-1, r0, r5 +%else +%if %3 + vpgatherdw m7, m4, scalingq-1, r2, r12 + vpgatherdw m5, m6, scalingq-1, r2, r12 +%else + vpgatherdw m7, m4, scalingq-1, r2, r13 + vpgatherdw m5, m6, scalingq-1, r2, r13 +%endif +%endif + REPX {psrlw x, 8}, m7, m5 + + ; unpack grain + pxor m4, m4 + pcmpgtb m4, m1 + punpcklbw m2, m1, m4 + punpckhbw m1, m4 + + ; noise = round2(scaling[src] * grain, scaling_shift) + pmullw m2, m7 + pmullw m1, m5 + pmulhrsw m2, m11 + pmulhrsw m1, m11 + +%if ARCH_X86_32 + DEFINE_ARGS dst, src, scaling, offxy, h, picptr, grain_lut +%endif + + ; unpack chroma source + pxor m4, m4 + punpckhbw m5, m0, m4 + punpcklbw m0, m4 ; m0-1: src as word + + ; dst = clip_pixel(src, noise) + paddw m0, m2 + paddw m5, m1 + pmaxsw m0, m13 + pmaxsw m5, m13 + pminsw m0, m12 + pminsw m5, m12 + packuswb m0, m5 + movifnidn dstq, dstmp + mova [dstq+srcq], m0 + +%if ARCH_X86_32 + add srcq, r2mp + ; lumaq has been adjusted above already +%else + add srcq, r12mp +%if %3 + lea lumaq, [lumaq+lstrideq*(1+%2)] +%else + add lumaq, r10mp +%endif +%endif + add grain_lutq, 82 + dec hw +%if %3 + jg %%loop_y_h_overlap +%else + jle %%end_y_hv_overlap +%if ARCH_X86_32 + mov r5, r5m +%endif + mova m3, [PIC_ptr(pb_17_27)] + btc hd, 16 + jnc %%loop_y_hv_overlap +%if ARCH_X86_64 + mov lstrideq, r10mp +%endif + jmp %%loop_y_h_overlap +%%end_y_hv_overlap: +%if ARCH_X86_64 + mov lstrideq, r10mp +%endif +%endif + +%if ARCH_X86_32 + DEFINE_ARGS luma, src, scaling, offxy, w, picptr, grain_lut + + mov wq, r4m +%endif + add wq, 16 + jge %%end_hv +%if ARCH_X86_32 + mov srcq, r1mp + mov lumaq, r11mp +%else + mov srcq, r11mp +%endif + lea lumaq, [luma_bakq+wq*(1+%2)] + add srcq, wq +%if ARCH_X86_32 + mov r4m, wq + mov r9m, lumaq +%endif +%if %2 + jmp %%loop_x_hv_overlap +%else +%if ARCH_X86_32 + add dword [rsp+7*mmsize+1*gprsize], 16 +%else + add top_offxyd, 16 +%endif + add offxyd, 16 + xor dword r8m, 4 + jmp %%loop_x_odd_v_overlap +%endif + +%%end_hv: + RET +%endmacro + + %%FGUV_32x32xN_LOOP 1, %2, %3 +.csfl: + %%FGUV_32x32xN_LOOP 0, %2, %3 +%endmacro + +FGUV_FN 420, 1, 1 + +%if STACK_ALIGNMENT < mmsize +DECLARE_ARG 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 +%endif + +FGUV_FN 422, 1, 0 + +%if STACK_ALIGNMENT < mmsize +DECLARE_ARG 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 +%endif + +FGUV_FN 444, 0, 0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4992 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHTS 1-* +const smooth_weights_1d_16bpc ; sm_weights[] << 7 + %rep %0 + dw %1*128 + %rotate 1 + %endrep +const smooth_weights_2d_16bpc ; sm_weights[], 256 - sm_weights[] + %rep %0 + dw %1, 256-%1 + %rotate 1 + %endrep +%endmacro + +SMOOTH_WEIGHTS 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +%if ARCH_X86_64 + +ipred_hv_shuf: db 6, 7, 6, 7, 0, 1, 2, 3, 2, 3, 2, 3, 8, 9, 10, 11 + db 4, 5, 4, 5, 4, 5, 6, 7, 0, 1, 0, 1, 12, 13, 14, 15 +filter_shuf1: db 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 14, 15, 12, 13, -1, -1 +filter_shuf2: db 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4, 5, 2, 3, -1, -1 +filter_shuf3: db 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 8, 9, -1, -1 +pal_pred_shuf: db 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 + dw 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 +z_filter_t0: db 55,127, 39,127, 39,127, 7, 15, 31, 7, 15, 31, 0, 3, 31, 0 +z_filter_t1: db 39, 63, 19, 47, 19, 47, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 +z_filter_wh: db 7, 7, 11, 11, 15, 15, 19, 19, 19, 23, 23, 23, 31, 31, 31, 39 + db 39, 39, 47, 47, 47, 63, 63, 63, 79, 79, 79, -1 +pw_m1024: times 2 dw -1024 +pw_1to16: dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +pw_16to1: dw 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 +z2_ymul: dw 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4 +z2_ymul8: dw 1, 2, 5, 6, 3, 4, 7, 8, 5, 6, 16, 16, 7, 8 +pb_90: times 4 db 90 +z2_y_shuf_h4: dd 3, 7, 2, 6, 1, 5, 0, 4 +z_upsample: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_x_shuf: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +z2_y_shuf: db 6, 7, 14, 15, 4, 5, 12, 13, 4, 5, 12, 13, 2, 3, 10, 11 +z2_y_shuf_us: db 6, 7, 14, 15, 2, 3, 10, 11, 4, 5, 12, 13, 0, 1, 8, 9 +z_filter_k: dw 4, 4, 5, 5, 4, 4 + dw 8, 8, 6, 6, 4, 4 + dw 0, 0, 0, 0, 2, 2 + +%define pw_2 (z_filter_k+32) +%define pw_4 (z_filter_k+ 0) +%define pw_16 (z2_ymul8 +20) + +pw_1: times 2 dw 1 +pw_3: times 2 dw 3 +pw_62: times 2 dw 62 +pw_512: times 2 dw 512 +pw_2048: times 2 dw 2048 +pd_8: dd 8 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_16bpc_avx2_table (ipred_dc_16bpc_avx2_table + 10*4) +%define ipred_cfl_splat_16bpc_avx2_table (ipred_cfl_16bpc_avx2_table + 8*4) + +JMP_TABLE ipred_dc_16bpc, avx2, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left_16bpc, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_h_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2_16bpc, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3_16bpc, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_filter_16bpc, avx2, w4, w8, w16, w32 +JMP_TABLE ipred_cfl_16bpc, avx2, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left_16bpc, avx2, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_444_16bpc, avx2, w4, w8, w16, w32 +JMP_TABLE pal_pred_16bpc, avx2, w4, w8, w16, w32, w64 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_YMM avx2 +cglobal ipred_dc_top_16bpc, 3, 7, 6, dst, stride, tl, w, h + movifnidn hd, hm + add tlq, 2 + movd xm4, wd + pxor xm3, xm3 + pavgw xm4, xm3 + tzcnt wd, wd + movd xm5, wd + movu m0, [tlq] + lea r5, [ipred_dc_left_16bpc_avx2_table] + movsxd r6, [r5+wq*4] + add r6, r5 + add r5, ipred_dc_splat_16bpc_avx2_table-ipred_dc_left_16bpc_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + mov hd, hm + sub tlq, hq + movd xm4, hd + sub tlq, hq + pxor xm3, xm3 + pavgw xm4, xm3 + tzcnt r6d, hd + movd xm5, r6d + movu m0, [tlq] + lea r5, [ipred_dc_left_16bpc_avx2_table] + movsxd r6, [r5+r6*4] + add r6, r5 + add r5, ipred_dc_splat_16bpc_avx2_table-ipred_dc_left_16bpc_avx2_table + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + paddw m0, [tlq+96] + paddw m0, [tlq+64] +.h32: + paddw m0, [tlq+32] +.h16: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h8: + psrldq xm1, xm0, 8 + paddw xm0, xm1 +.h4: + punpcklwd xm0, xm3 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + paddd xm0, xm4 + psrld xm0, xm5 + lea stride3q, [strideq*3] + vpbroadcastw m0, xm0 + mova m1, m0 + mova m2, m0 + mova m3, m0 + jmp wq + +cglobal ipred_dc_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm4, r5d + tzcnt r5d, r5d + movd xm5, r5d + lea r5, [ipred_dc_16bpc_avx2_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pxor m3, m3 + psrlw xm4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movq xm0, [tlq-8] + jmp wq +.w4: + movq xm1, [tlq+2] + paddw m0, m4 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrld m1, m0, 16 + paddw m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + lea r2d, [hq*2] + mov r6d, 0xAAAB6667 + shrx r6d, r6d, r2d + punpckhwd xm1, xm0, xm3 + punpcklwd xm0, xm3 + paddd xm0, xm1 + movd xm1, r6d + psrld xm0, 2 + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w4_end: + vpbroadcastw xm0, xm0 +.s4: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + mova xm0, [tlq-16] + jmp wq +.w8: + vextracti128 xm1, m0, 1 + paddw xm0, [tlq+2] + paddw xm0, xm4 + paddw xm0, xm1 + psrld xm1, xm0, 16 + paddw xm0, xm1 + pblendw xm0, xm3, 0xAA + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w8_end: + vpbroadcastw xm0, xm0 +.s8: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova m0, [tlq-32] + jmp wq +.w16: + paddw m0, [tlq+2] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpckhwd xm1, xm0, xm3 + punpcklwd xm0, xm3 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-32] + jmp wq +.w32: + paddw m0, [tlq+ 2] + paddw m0, [tlq+34] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm3 + punpckhwd xm0, xm3 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x6667AAAB + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w32_end: + vpbroadcastw m0, xm0 + mova m1, m0 +.s32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m0 + mova [dstq+stride3q +32*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-128] + mova m1, [tlq- 96] + paddw m0, [tlq- 64] + paddw m1, [tlq- 32] + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 2] + paddw m0, [tlq+34] + paddw m1, [tlq+66] + paddw m0, [tlq+98] + paddw m0, m1 + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm3 + punpckhwd xm0, xm3 + paddd xm1, xm4 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 64 + je .w64_end + mov r6d, 0x6667AAAB + shrx r6d, r6d, hd + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w64_end: + vpbroadcastw m0, xm0 + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s64: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s64 + RET + +cglobal ipred_dc_128_16bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + mov r6d, r8m + shr r6d, 11 + lea r5, [ipred_dc_splat_16bpc_avx2_table] + tzcnt wd, wd + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_16bpc_avx2_table+pw_512+r6*4] + mova m1, m0 + mova m2, m0 + mova m3, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movu m0, [tlq+ 2] + movu m1, [tlq+34] + movu m2, [tlq+66] + movu m3, [tlq+98] + lea r5, [ipred_dc_splat_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +%macro IPRED_H 2 ; w, store_type + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + vpbroadcastw m2, [tlq-6] + vpbroadcastw m3, [tlq-8] + sub tlq, 8 + mov%2 [dstq+strideq*0], m0 + mov%2 [dstq+strideq*1], m1 + mov%2 [dstq+strideq*2], m2 + mov%2 [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +ALIGN function_align +%endmacro + +cglobal ipred_h_16bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + lea r5, [ipred_h_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +INIT_XMM avx2 +.w4: + IPRED_H 4, q +.w8: + IPRED_H 8, a +INIT_YMM avx2 +.w16: + IPRED_H 16, a +.w32: + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + vpbroadcastw m2, [tlq-6] + vpbroadcastw m3, [tlq-8] + sub tlq, 8 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m2 + mova [dstq+strideq*2+32*1], m2 + mova [dstq+stride3q +32*0], m3 + mova [dstq+stride3q +32*1], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +.w64: + vpbroadcastw m0, [tlq-2] + vpbroadcastw m1, [tlq-4] + sub tlq, 4 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*0+32*2], m0 + mova [dstq+strideq*0+32*3], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m1 + mova [dstq+strideq*1+32*3], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64 + RET + +%macro PAETH 3 ; top, signed_ldiff, ldiff + paddw m0, m%2, m1 + psubw m7, m3, m0 ; tldiff + psubw m0, m%1 ; tdiff + pabsw m7, m7 + pabsw m0, m0 + pminsw m7, m0 + pcmpeqw m0, m7 + pcmpgtw m7, m%3, m7 + vpblendvb m0, m3, m%1, m0 + vpblendvb m0, m1, m0, m7 +%endmacro + +cglobal ipred_paeth_16bpc, 3, 6, 8, dst, stride, tl, w, h +%define base r5-ipred_paeth_16bpc_avx2_table + movifnidn hd, hm + lea r5, [ipred_paeth_16bpc_avx2_table] + tzcnt wd, wd + movsxd wq, [r5+wq*4] + vpbroadcastw m3, [tlq] ; topleft + add wq, r5 + jmp wq +.w4: + vpbroadcastq m2, [tlq+2] ; top + movsldup m6, [base+ipred_hv_shuf] + lea r3, [strideq*3] + psubw m4, m2, m3 + pabsw m5, m4 +.w4_loop: + sub tlq, 8 + vpbroadcastq m1, [tlq] + pshufb m1, m6 ; left + PAETH 2, 4, 5 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + vbroadcasti128 m2, [tlq+2] + movsldup m6, [base+ipred_hv_shuf] + psubw m4, m2, m3 + pabsw m5, m4 +.w8_loop: + sub tlq, 4 + vpbroadcastd m1, [tlq] + pshufb m1, m6 + PAETH 2, 4, 5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + movu m2, [tlq+2] + psubw m4, m2, m3 + pabsw m5, m4 +.w16_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m2, [tlq+2] + movu m6, [tlq+34] +%if WIN64 + movaps r4m, xmm8 + movaps r6m, xmm9 +%endif + psubw m4, m2, m3 + psubw m8, m6, m3 + pabsw m5, m4 + pabsw m9, m8 +.w32_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq+32*0], m0 + PAETH 6, 8, 9 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w32_loop +%if WIN64 + movaps xmm8, r4m + movaps xmm9, r6m +%endif + RET +ALIGN function_align +.w64: + WIN64_SPILL_XMM 16 + movu m2, [tlq+ 2] + movu m6, [tlq+34] + movu m10, [tlq+66] + movu m13, [tlq+98] + psubw m4, m2, m3 + psubw m8, m6, m3 + psubw m11, m10, m3 + psubw m14, m13, m3 + pabsw m5, m4 + pabsw m9, m8 + pabsw m12, m11 + pabsw m15, m14 +.w64_loop: + sub tlq, 2 + vpbroadcastw m1, [tlq] + PAETH 2, 4, 5 + mova [dstq+32*0], m0 + PAETH 6, 8, 9 + mova [dstq+32*1], m0 + PAETH 10, 11, 12 + mova [dstq+32*2], m0 + PAETH 13, 14, 15 + mova [dstq+32*3], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_16bpc, 3, 7, 6, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_16bpc_avx2_table + lea r6, [ipred_smooth_v_16bpc_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea weightsq, [base+smooth_weights_1d_16bpc+hq*4] + neg hq + vpbroadcastw m5, [tlq+hq*2] ; bottom + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [tlq+2] ; top + movsldup m3, [base+ipred_hv_shuf] + lea r6, [strideq*3] + psubw m4, m5 ; top - bottom +.w4_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m3 + pmulhrsw m0, m4 + paddw m0, m5 + vextracti128 xm1, m0, 1 + movhps [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movq [dstq+r6 ], xm0 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop +.ret: + RET +.w8: + vbroadcasti128 m4, [tlq+2] + movsldup m3, [base+ipred_hv_shuf] + lea r6, [strideq*3] + psubw m4, m5 +.w8_loop: + vpbroadcastd m0, [weightsq+hq*2+0] + vpbroadcastd m1, [weightsq+hq*2+4] + pshufb m0, m3 + pshufb m1, m3 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + vextracti128 [dstq+strideq*0], m0, 1 + mova [dstq+strideq*1], xm0 + vextracti128 [dstq+strideq*2], m1, 1 + mova [dstq+r6 ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + movu m4, [tlq+2] + lea r6, [strideq*3] + psubw m4, m5 +.w16_loop: + vpbroadcastw m0, [weightsq+hq*2+0] + vpbroadcastw m1, [weightsq+hq*2+2] + vpbroadcastw m2, [weightsq+hq*2+4] + vpbroadcastw m3, [weightsq+hq*2+6] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r6 ], m3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + WIN64_SPILL_XMM 7 + movu m4, [tlq+ 2] + movu m6, [tlq+34] + psubw m4, m5 + psubw m6, m5 +.w32_loop: + vpbroadcastw m1, [weightsq+hq*2+0] + vpbroadcastw m3, [weightsq+hq*2+2] + pmulhrsw m0, m4, m1 + pmulhrsw m1, m6 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m6 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + WIN64_SPILL_XMM 8 + movu m3, [tlq+ 2] + movu m4, [tlq+34] + movu m6, [tlq+66] + movu m7, [tlq+98] + REPX {psubw x, m5}, m3, m4, m6, m7 +.w64_loop: + vpbroadcastw m2, [weightsq+hq*2] + pmulhrsw m0, m3, m2 + pmulhrsw m1, m4, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*0], m0 + pmulhrsw m0, m6, m2 + mova [dstq+32*1], m1 + pmulhrsw m1, m7, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + add dstq, strideq + inc hq + jl .w64_loop + RET + +cglobal ipred_smooth_h_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 +%define base r6-ipred_smooth_h_16bpc_avx2_table + lea r6, [ipred_smooth_h_16bpc_avx2_table] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m5, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [r6+wq*4] + sub tlq, hq + lea stride3q, [strideq*3] + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [base+smooth_weights_1d_16bpc+4*2] + movsldup m3, [base+ipred_hv_shuf] +.w4_loop: + vpbroadcastq m0, [tlq+hq-8] ; left + pshufb m0, m3 + psubw m0, m5 ; left - right + pmulhrsw m0, m4 + paddw m0, m5 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w4_loop + RET +.w8: + vbroadcasti128 m4, [base+smooth_weights_1d_16bpc+8*2] + movsldup m3, [base+ipred_hv_shuf] +.w8_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastd m1, [tlq+hq-8] + pshufb m0, m3 + pshufb m1, m3 + psubw m0, m5 + psubw m1, m5 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w8_loop + RET +.w16: + movu m4, [base+smooth_weights_1d_16bpc+16*2] +.w16_loop: + vpbroadcastq m3, [tlq+hq-8] + punpcklwd m3, m3 + psubw m3, m5 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w16_loop + RET +.w32: + WIN64_SPILL_XMM 7 + movu m4, [base+smooth_weights_1d_16bpc+32*2] + movu m6, [base+smooth_weights_1d_16bpc+32*3] +.w32_loop: + vpbroadcastw m1, [tlq+hq-2] + vpbroadcastw m3, [tlq+hq-4] + psubw m1, m5 + psubw m3, m5 + pmulhrsw m0, m4, m1 + pmulhrsw m1, m6 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m6 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w32_loop + RET +.w64: + WIN64_SPILL_XMM 8 + movu m3, [base+smooth_weights_1d_16bpc+32*4] + movu m4, [base+smooth_weights_1d_16bpc+32*5] + movu m6, [base+smooth_weights_1d_16bpc+32*6] + movu m7, [base+smooth_weights_1d_16bpc+32*7] +.w64_loop: + vpbroadcastw m2, [tlq+hq-2] + psubw m2, m5 + pmulhrsw m0, m3, m2 + pmulhrsw m1, m4, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*0], m0 + pmulhrsw m0, m6, m2 + mova [dstq+32*1], m1 + pmulhrsw m1, m7, m2 + paddw m0, m5 + paddw m1, m5 + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + add dstq, strideq + sub hq, 1*2 + jg .w64_loop + RET + +%macro SMOOTH_2D_END 6 ; src[1-2], mul[1-2], add[1-2] + pmaddwd m0, m%1, m%3 + pmaddwd m1, m%2, m%4 + paddd m0, m%5 + paddd m1, m%6 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m5 +%endmacro + +cglobal ipred_smooth_16bpc, 3, 7, 6, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_16bpc_avx2_table + lea r6, [ipred_smooth_16bpc_avx2_table] + mov wd, wm + vpbroadcastw m4, [tlq+wq*2] ; right + tzcnt wd, wd + mov hd, hm + sub tlq, hq + sub tlq, hq + movsxd wq, [r6+wq*4] + pxor m5, m5 + add wq, r6 + lea v_weightsq, [base+smooth_weights_2d_16bpc+hq*4] + jmp wq +.w4: + WIN64_SPILL_XMM 11 + vpbroadcastw m0, [tlq] ; bottom + vpbroadcastq m6, [tlq+hq*2+2] + movsldup m7, [base+ipred_hv_shuf] + movshdup m9, [base+ipred_hv_shuf] + vbroadcasti128 m10, [base+smooth_weights_2d_16bpc+4*4] + punpcklwd m6, m0 ; top, bottom + punpcklqdq m8, m9, m9 + punpckhqdq m9, m9 + lea r3, [strideq*3] +.w4_loop: + vpbroadcastq m3, [tlq+hq*2-8] + vbroadcasti128 m1, [v_weightsq] + pshufb m3, m7 + punpcklwd m2, m3, m4 ; left, right + punpckhwd m3, m4 + pmaddwd m2, m10 + pmaddwd m3, m10 + pshufb m0, m1, m8 + pshufb m1, m9 + SMOOTH_2D_END 0, 1, 6, 6, 2, 3 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + add v_weightsq, 16 + sub hd, 4 + jg .w4_loop + RET +.w8: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + vpbroadcastw m0, [tlq] ; bottom + vbroadcasti128 m7, [tlq+hq*2+2] + movsldup m8, [base+ipred_hv_shuf] + movshdup m9, [base+ipred_hv_shuf] + vbroadcasti128 m10, [base+smooth_weights_2d_16bpc+8*4+16*0] + vbroadcasti128 m11, [base+smooth_weights_2d_16bpc+8*4+16*1] + punpcklwd m6, m7, m0 ; top, bottom + punpckhwd m7, m0 +.w8_loop: + vpbroadcastd m3, [tlq+hq*2-4] + vpbroadcastq m1, [v_weightsq] + pshufb m3, m8 + punpcklwd m2, m3, m4 ; left, right + punpckhwd m3, m4 + pmaddwd m2, m10 + pmaddwd m3, m11 + pshufb m1, m9 + SMOOTH_2D_END 1, 1, 6, 7, 2, 3 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add v_weightsq, 8 + sub hd, 2 + jg .w8_loop + RET +.w16: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 11 + vpbroadcastw m0, [tlq] ; bottom + movu m7, [tlq+hq*2+2] + mova xm8, [base+smooth_weights_2d_16bpc+16*4+16*0] + mova xm9, [base+smooth_weights_2d_16bpc+16*4+16*1] + vinserti128 m8, [base+smooth_weights_2d_16bpc+16*4+16*2], 1 + vinserti128 m9, [base+smooth_weights_2d_16bpc+16*4+16*3], 1 + punpcklwd m6, m7, m0 ; top, bottom + punpckhwd m7, m0 +.w16_loop: + vpbroadcastd m3, [tlq+hq*2-4] + vpbroadcastd m1, [v_weightsq+0] + punpcklwd m3, m4 ; left, right + pshufd m2, m3, q1111 + pmaddwd m10, m8, m2 + pmaddwd m2, m9 + pshufd m3, m3, q0000 + SMOOTH_2D_END 1, 1, 6, 7, 10, 2 + vpbroadcastd m1, [v_weightsq+4] + pmaddwd m2, m8, m3 + pmaddwd m3, m9 + mova [dstq+strideq*0], m0 + SMOOTH_2D_END 1, 1, 6, 7, 2, 3 + mova [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + add v_weightsq, 8 + sub hq, 2 + jg .w16_loop + RET +.w32: +%assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastw m0, [tlq] ; bottom + movu m7, [tlq+hq*2+ 2] + movu m9, [tlq+hq*2+34] + mova xm10, [base+smooth_weights_2d_16bpc+32*4+16*0] + mova xm11, [base+smooth_weights_2d_16bpc+32*4+16*1] + vinserti128 m10, [base+smooth_weights_2d_16bpc+32*4+16*2], 1 + vinserti128 m11, [base+smooth_weights_2d_16bpc+32*4+16*3], 1 + mova xm12, [base+smooth_weights_2d_16bpc+32*4+16*4] + mova xm13, [base+smooth_weights_2d_16bpc+32*4+16*5] + vinserti128 m12, [base+smooth_weights_2d_16bpc+32*4+16*6], 1 + vinserti128 m13, [base+smooth_weights_2d_16bpc+32*4+16*7], 1 + punpcklwd m6, m7, m0 + punpckhwd m7, m0 + punpcklwd m8, m9, m0 + punpckhwd m9, m0 +.w32_loop: + vpbroadcastw m3, [tlq+hq*2-2] + vpbroadcastd m14, [v_weightsq] + punpcklwd m3, m4 + pmaddwd m1, m10, m3 + pmaddwd m2, m11, m3 + pmaddwd m0, m6, m14 + paddd m0, m1 + pmaddwd m1, m7, m14 + paddd m1, m2 + pmaddwd m2, m12, m3 + pmaddwd m3, m13 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m5 + mova [dstq+32*0], m0 + SMOOTH_2D_END 14, 14, 8, 9, 2, 3 + mova [dstq+32*1], m0 + add dstq, strideq + add v_weightsq, 4 + dec hd + jg .w32_loop + RET +.w64: +%assign stack_offset stack_offset - stack_size_padded + PROLOGUE 0, 11, 16, dst, stride, tl, tl_base, h, v_weights, dummy, v_weights_base, x, y, dst_base + mov dst_baseq, dstq + mov tl_baseq, tlq + mov v_weights_baseq, v_weightsq + xor xq, xq +.w64_loop_x: + mov yq, hq + lea tlq, [tl_baseq+hq*2] + vpbroadcastw m0, [tl_baseq] ; bottom + movu m7, [tlq+xq*2+ 2] + movu m9, [tlq+xq*2+34] + mova xm10, [base+smooth_weights_2d_16bpc+64*4+16*0] + mova xm11, [base+smooth_weights_2d_16bpc+64*4+16*1] + vinserti128 m10, [base+smooth_weights_2d_16bpc+64*4+16*2], 1 + vinserti128 m11, [base+smooth_weights_2d_16bpc+64*4+16*3], 1 + mova xm12, [base+smooth_weights_2d_16bpc+64*4+16*4] + mova xm13, [base+smooth_weights_2d_16bpc+64*4+16*5] + vinserti128 m12, [base+smooth_weights_2d_16bpc+64*4+16*6], 1 + vinserti128 m13, [base+smooth_weights_2d_16bpc+64*4+16*7], 1 + punpcklwd m6, m7, m0 + punpckhwd m7, m0 + punpcklwd m8, m9, m0 + punpckhwd m9, m0 + lea tlq, [tl_baseq-2] +.w64_loop_y: + vpbroadcastw m3, [tlq+yq*2] + vpbroadcastd m1, [v_weightsq] + punpcklwd m3, m4 + pmaddwd m14, m10, m3 + pmaddwd m15, m11, m3 + pmaddwd m2, m12, m3 + pmaddwd m3, m13 + pmaddwd m0, m6, m1 + paddd m0, m14 + pmaddwd m14, m7, m1 + paddd m14, m15 + psrld m0, 8 + psrld m14, 8 + packssdw m0, m14 + pavgw m0, m5 + mova [dstq+32*0], m0 + SMOOTH_2D_END 8, 9, 1, 1, 2, 3 + mova [dstq+32*1], m0 + add dstq, strideq + add v_weightsq, 4 + dec yq + jg .w64_loop_y + lea dstq, [dst_baseq+32*2] + add r6, 16*8 + mov v_weightsq, v_weights_baseq + add xq, 32 + test xb, 64 + jz .w64_loop_x + RET + +cglobal ipred_z1_16bpc, 3, 8, 0, dst, stride, tl, w, h, angle, dx, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z1_16bpc_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea r7, [dr_intra_derivative] + movsxd wq, [r6+wq*4] + add tlq, 2 + add wq, r6 + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + movzx dxd, word [r7+dxq] + xor angled, 0x4ff ; d = 90 - angle + vpbroadcastd m5, [pw_62] + jmp wq +.w4: + ALLOC_STACK -64, 7 + cmp angleb, 40 + jae .w4_no_upsample + lea r3d, [angleq-1024] + sar r3d, 7 + add r3d, hd + jg .w4_no_upsample ; !enable_intra_edge_filter || h > 8 || (h == 8 && is_sm) + vpbroadcastw xm3, [tlq+14] + movu xm1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + palignr xm0, xm3, xm1, 4 ; 3 4 5 6 7 8 8 8 + paddw xm0, [tlq- 2] ; 0 1 2 3 4 5 6 7 + add dxd, dxd + palignr xm2, xm3, xm1, 2 ; 2 3 4 5 6 7 8 8 + paddw xm2, xm1 ; -1 * a + 9 * b + 9 * c + -1 * d + psubw xm0, xm2, xm0 ; = (b + c - a - d + (b + c) << 3 + 8) >> 4 + psraw xm0, 3 ; = ((b + c - a - d) >> 3 + b + c + 1) >> 1 + pxor xm4, xm4 + paddw xm2, xm0 + vpbroadcastw xm0, r8m ; pixel_max + mova [rsp+32], xm3 + movd xm3, dxd + pmaxsw xm2, xm4 + mov r3d, dxd + pavgw xm2, xm4 + vpbroadcastw m3, xm3 + pminsw xm2, xm0 + punpcklwd xm0, xm1, xm2 + punpckhwd xm1, xm2 + lea r5, [strideq*3] + pslldq m2, m3, 8 + mova [rsp+ 0], xm0 + mova [rsp+16], xm1 + paddw m6, m3, m3 + paddw m3, m2 + vpblendd m4, m6, 0xf0 + paddw m6, m6 + paddw m3, m4 ; xpos0 xpos1 xpos2 xpos3 + vbroadcasti128 m4, [z_upsample] +.w4_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + movu xm2, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base2 + vinserti128 m1, [rsp+r3*2], 1 ; 0 2 + lea r3d, [r2+dxq] + shr r2d, 6 ; base3 + vinserti128 m2, [rsp+r2*2], 1 ; 1 3 + pshufb m1, m4 + pshufb m2, m4 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m5, m3 ; frac + psllw m2, 9 ; (a * (64 - frac) + b * frac + 32) >> 6 + psubw m1, m0 ; = a + (((b - a) * frac + 32) >> 6) + pmulhrsw m1, m2 ; = a + (((b - a) * (frac << 9) + 16384) >> 15) + paddw m3, m6 ; xpos += dx + paddw m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r5 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; w4/w8/w16 +%define base r3-z_filter_t0 + movd xm0, maxbased + lea r3, [z_filter_t0] + movd xm1, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m1, xm1 + pcmpeqb m0, [base+z_filter_wh] + mova xm2, [r3+angleq*8] + pand m0, m1 + pcmpgtb m0, m2 + pmovmskb r5d, m0 + ret +.w4_no_upsample: + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea maxbased, [hq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastw xm3, [tlq+14] + mova xm0, [tlq- 2] ; 0 1 2 3 4 5 6 7 + vpbroadcastd xm1, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd xm4, [base+z_filter_k-4+r5*4+12*0] + palignr xm2, xm3, xm0, 4 ; 2 3 4 5 6 7 8 8 + pmullw xm1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + paddw xm2, xm0 + pmullw xm2, xm4 + movd [rsp+16], xm3 + cmp r5d, 3 + jne .w4_3tap + paddw xm1, xm2 + palignr xm2, xm3, xm0, 6 ; 3 4 5 6 7 8 8 8 + pblendw xm0, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 + movzx r3d, word [tlq+14] + movzx r2d, word [tlq+12] + inc maxbased + paddw xm2, xm0 + sub r2d, r3d + paddw xm2, xm2 + lea r2d, [r2+r3*8+4] + shr r2d, 3 ; (1 * top[6] + 7 * top[7] + 4) >> 3 + mov [rsp+16], r2w +.w4_3tap: + pxor xm0, xm0 + paddw xm1, xm2 + mov tlq, rsp + psrlw xm1, 3 + cmp hd, 8 + sbb maxbased, -1 + pavgw xm0, xm1 + mova [tlq], xm0 +.w4_main: + movd xm3, dxd + vpbroadcastq m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] ; top[max_base_x] + shl maxbased, 6 + vpbroadcastw m3, xm3 + movd xm0, maxbased + mov r3d, dxd ; xpos + vpbroadcastw m0, xm0 + paddw m4, m3, m3 + psubw m1, m0 ; -max_base_x + vpblendd m3, m4, 0xcc + paddw m0, m4, m3 + vpblendd m3, m0, 0xf0 ; xpos0 xpos1 xpos2 xpos3 + paddw m4, m4 + paddw m3, m1 +.w4_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [tlq+r3*2] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + movu xm2, [tlq+r5*2] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + vinserti128 m1, [tlq+r3*2], 1 ; 0 2 + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + vinserti128 m2, [tlq+r5*2], 1 ; 1 3 + punpcklqdq m0, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + vpblendd m1, m2, 0xcc + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 ; xpos < max_base_x + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w4_loop + lea r6, [strideq*3] +.w4_end_loop: + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + movq [dstq+strideq*2], xm6 + movq [dstq+r6 ], xm6 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_end_loop +.w4_end: + RET +.w8: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 7 + lea r3d, [angleq+216] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + movu m2, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g _ + movu m0, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g _ _ + movu m1, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + cmp hd, 4 + jne .w8_upsample_h8 ; awkward single-pixel edge case + vpblendd m0, m2, 0x20 ; 3 4 5 6 7 8 9 a b c c _ _ _ _ _ +.w8_upsample_h8: + paddw m2, m1 + paddw m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + add dxd, dxd + psubw m0, m2, m0 + psraw m0, 3 + pxor m4, m4 + paddw m2, m0 + vpbroadcastw m0, r8m + movd xm3, dxd + pmaxsw m2, m4 + mov r3d, dxd + pavgw m2, m4 + vpbroadcastw m3, xm3 + pminsw m2, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + vbroadcasti128 m4, [z_upsample] + mova [rsp+ 0], xm0 + mova [rsp+16], xm1 + paddw m6, m3, m3 + vextracti128 [rsp+32], m0, 1 + vextracti128 [rsp+48], m1, 1 + vpblendd m3, m6, 0xf0 ; xpos0 xpos1 +.w8_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm1, [rsp+r3*2] + movu xm2, [rsp+r3*2+16] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + vinserti128 m1, [rsp+r2*2], 1 + vinserti128 m2, [rsp+r2*2+16], 1 + pshufb m1, m4 + pshufb m2, m4 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m3, m6 + paddw m0, m1 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_upsample_loop + RET +.w8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(h+7, 15) + jmp .w8_main +.w8_no_upsample: + lea maxbased, [hq+7] + test angled, 0x400 + jnz .w8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w8_main + popcnt r5d, r5d + vpbroadcastd m1, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movu m2, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m2 + cmp hd, 8 + jl .w8_filter_h4 + punpckhwd m2, m2 + vpblendd m3, m2, [tlq+2], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + je .w8_filter_end ; 8x4 and 8x8 are always 3-tap + movzx r3d, word [tlq+30] + mov maxbased, 16 + mov [rsp+32], r3d + cmp r5d, 3 + jne .w8_filter_end + punpcklwd xm6, xm0, xm0 + vpblendd m2, [tlq+4], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g g g + vpblendd m6, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movzx r5d, word [tlq+28] + mov [rsp+34], r3w + paddw m2, m6 + sub r5d, r3d + inc maxbased + paddw m2, m2 + lea r3d, [r5+r3*8+4] + paddw m1, m2 + shr r3d, 3 + mov [rsp+32], r3w + jmp .w8_filter_end +.w8_filter_h4: + pshuflw m3, m2, q3321 + vinserti128 m3, [tlq+2], 0 ; 2 3 4 5 6 7 8 9 a b c c _ _ _ _ +.w8_filter_end: + paddw m0, m3 + pmullw m0, m4 + mov tlq, rsp + pxor m2, m2 + paddw m0, m1 + psrlw m0, 3 + pavgw m0, m2 + mova [tlq], m0 +.w8_main: + movd xm3, dxd + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m3, xm3 + movd xm0, maxbased + mov r3d, dxd + vpbroadcastw m0, xm0 + paddw m4, m3, m3 + psubw m1, m0 + vpblendd m3, m4, 0xf0 ; xpos0 xpos1 + paddw m3, m1 +.w8_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + movu xm0, [tlq+r3*2] + movu xm1, [tlq+r3*2+2] + lea r3d, [r5+dxq] + shr r5d, 6 + vinserti128 m0, [tlq+r5*2], 1 + vinserti128 m1, [tlq+r5*2+2], 1 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w8_loop +.w8_end_loop: + mova [dstq+strideq*0], xm6 + mova [dstq+strideq*1], xm6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_end_loop +.w8_end: + RET +.w16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(h+15, 31) + jmp .w16_main +.w16: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 7 + lea maxbased, [hq+15] + test angled, 0x400 + jnz .w16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w16_main + popcnt r5d, r5d + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + cmp r5d, 3 + jne .w16_filter_3tap + vpbroadcastd m2, [base+pw_3] + punpcklwd xm0, xm0 + vpblendd m0, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m1, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m0, m2 + pavgw m0, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m0, m1 + psrlw m0, 2 + movu m3, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m3, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + cmp hd, 8 + jl .w16_filter_5tap_h4 + punpckhwd m3, m3 + je .w16_filter_5tap_h8 + vpblendd m4, m3, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m3, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + movzx r3d, word [tlq+62] + movzx r2d, word [tlq+60] + pavgw m2, m4 + sub r2d, r3d + paddw m1, m3 + lea r2d, [r2+r3*8+4] + paddw m1, m2 + shr r2d, 3 + psrlw m1, 2 + mov [rsp+66], r3w + mov [rsp+64], r2w + mov tlq, rsp + mov r3d, 33 + cmp hd, 16 + cmovg maxbased, r3d + jmp .w16_filter_end2 +.w16_filter_5tap_h8: + vpblendd xm4, xm3, [tlq+36], 0x07 ; 4 5 6 7 8 9 9 9 + vpblendd xm3, [tlq+34], 0x07 ; 3 4 5 6 7 8 9 9 + pavgw xm2, xm4 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 + jmp .w16_filter_end2 +.w16_filter_5tap_h4: + pshuflw xm4, xm3, q3332 ; 4 5 5 5 + pshuflw xm3, xm3, q3321 ; 3 4 5 5 + pavgw xm2, xm4 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 + jmp .w16_filter_end2 +.w16_filter_3tap: + vpbroadcastd m3, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + pmullw m0, m3, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + movu m2, [tlq+32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m4 + pmullw m3, m2 + paddw m0, m1 + cmp hd, 8 + je .w16_filter_3tap_h8 + jl .w16_filter_3tap_h4 + punpckhwd m2, m2 + vpblendd m2, [tlq+34], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + jmp .w16_filter_end +.w16_filter_3tap_h4: + pshuflw xm2, xm2, q3321 ; 2 3 4 4 _ _ _ _ + jmp .w16_filter_end +.w16_filter_3tap_h8: + psrldq xm2, 2 + pshufhw xm2, xm2, q2210 ; 2 3 4 5 6 7 8 8 +.w16_filter_end: + paddw m2, [tlq+30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + pmullw m2, m4 + psrlw m0, 3 + pxor m1, m1 + paddw m2, m3 + psrlw m2, 3 + pavgw m0, m1 + pavgw m1, m2 +.w16_filter_end2: + mov tlq, rsp + mova [tlq+ 0], m0 + mova [tlq+32], m1 +.w16_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r3d, dxd + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + psubw m3, m0 +.w16_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + lea r3d, [r5+dxq] + shr r5d, 6 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m1, m0 + movu m0, [tlq+r5*2] + vpblendvb m2, m6, m1, m2 + movu m1, [tlq+r5*2+2] + mova [dstq+strideq*0], m2 + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+strideq*1], m0 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w16_loop +.w16_end_loop: + mova [dstq+strideq*0], m6 + mova [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_end_loop +.w16_end: + RET +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK -160, 8 + lea maxbased, [hq+31] + mov r3d, 63 + cmp hd, 32 + cmova maxbased, r3d + test angled, 0x400 + jnz .w32_main + vpbroadcastd m2, [pw_3] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + vpblendd m1, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m0, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m1, m2 + paddw m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pavgw m1, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + mov r3, rsp + paddw m0, m1 + lea r5d, [maxbaseq-31] + psrlw m0, 2 + mova [r3], m0 +.w32_filter_loop: + mova m0, [tlq+30] + paddw m1, m2, [tlq+28] + add tlq, 32 + paddw m0, [tlq+0] + pavgw m1, [tlq+4] + paddw m0, [tlq+2] + add r3, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r3], m0 + sub r5d, 16 + jg .w32_filter_loop + movu m0, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + punpckhwd m1, m0, m0 + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m0, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + jl .w32_filter_h8 + vpblendd m3, m1, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m1, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + movzx r5d, word [tlq+62] + movzx r2d, word [tlq+60] + pavgw m2, m3 + sub r2d, r5d + paddw m0, m1 + lea r2d, [r2+r5*8+4] + paddw m0, m2 + shr r2d, 3 + psrlw m0, 2 + mova [r3+32], m0 + mov [r3+66], r5w + mov [r3+64], r2w + mov tlq, rsp + mov r3d, 65 + cmp hd, 64 + cmove maxbased, r3d + jmp .w32_main +.w32_filter_h8: + vpblendd xm3, xm1, [tlq+36], 0x07 ; 4 5 6 7 8 9 9 9 + vpblendd xm1, [tlq+34], 0x07 ; 3 4 5 6 7 8 9 9 + pavgw xm2, xm3 + paddw xm0, xm1 + mov tlq, rsp + paddw xm0, xm2 + psrlw xm0, 2 + mova [r3+32], xm0 +.w32_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r5d, dxd + vpbroadcastd m7, [pw_m1024] ; -16 * 64 + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + psubw m3, m0 +.w32_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + psraw m1, m3, 15 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*0], m0 + movu m0, [tlq+r3*2+32] + movu m1, [tlq+r3*2+34] + add r5d, dxd + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m7, m3 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+32*1], m0 + dec hd + jz .w32_end + add dstq, strideq + cmp r5d, maxbased + jb .w32_loop +.w32_end_loop: + mova [dstq+32*0], m6 + mova [dstq+32*1], m6 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + %assign stack_offset org_stack_offset + ALLOC_STACK -256, 10 + lea maxbased, [hq+63] + test angled, 0x400 + jnz .w64_main + vpbroadcastd m2, [pw_3] + mova m0, [tlq-2] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + vpblendd m1, [tlq-4], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m0, [tlq+0] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + paddw m1, m2 + paddw m0, [tlq+2] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pavgw m1, [tlq+4] ; 3 4 5 6 7 8 9 a b c d e f g h i + mov r3, rsp + paddw m0, m1 + lea r5d, [hq+32] + psrlw m0, 2 + mova [r3], m0 +.w64_filter_loop: + mova m0, [tlq+30] + paddw m1, m2, [tlq+28] + add tlq, 32 + paddw m0, [tlq+0] + pavgw m1, [tlq+4] + paddw m0, [tlq+2] + add r3, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r3], m0 + sub r5d, 16 + jg .w64_filter_loop + movu m0, [tlq+32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + punpckhwd m1, m0, m0 + paddw m2, [tlq+28] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m0, [tlq+30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq+36], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m1, [tlq+34], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + pavgw m2, m3 + paddw m0, m1 + paddw m0, m2 + mov tlq, rsp + psrlw m0, 2 + mova [r3+32], m0 +.w64_main: + movd xm4, dxd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + movd xm0, maxbased + mov r5d, dxd + vpbroadcastd m7, [pw_m1024] ; -16 * 64 + vpbroadcastw m0, xm0 + paddw m3, m4, [z_base_inc] + paddw m8, m7, m7 ; -32 * 64 + psubw m3, m0 + paddw m9, m8, m7 ; -48 * 64 +.w64_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3*2] + movu m1, [tlq+r3*2+2] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + psraw m1, m3, 15 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*0], m0 + movu m0, [tlq+r3*2+32] + movu m1, [tlq+r3*2+34] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m7, m3 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*1], m0 + movu m0, [tlq+r3*2+64] + movu m1, [tlq+r3*2+66] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m8, m3 + vpblendvb m0, m6, m0, m1 + mova [dstq+32*2], m0 + movu m0, [tlq+r3*2+96] + movu m1, [tlq+r3*2+98] + add r5d, dxd + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m9, m3 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [dstq+32*3], m0 + dec hd + jz .w64_end + add dstq, strideq + cmp r5d, maxbased + jb .w64_loop +.w64_end_loop: + mova [dstq+32*0], m6 + mova [dstq+32*1], m6 + mova [dstq+32*2], m6 + mova [dstq+32*3], m6 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET + +cglobal ipred_z2_16bpc, 3, 12, 12, 352, dst, stride, tl, w, h, angle, dx, dy +%define base r9-z_filter_t0 + lea r9, [ipred_z2_16bpc_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea dxq, [dr_intra_derivative-90] + movsxd wq, [r9+wq*4] + mova m1, [tlq- 0] + movzx dyd, angleb + xor angled, 0x400 + mova m2, [tlq- 32] + mov r8, dxq + sub dxq, dyq + mova m3, [tlq- 64] + add wq, r9 + add r9, z_filter_t0-ipred_z2_16bpc_avx2_table + mova m4, [tlq- 96] + and dyd, ~1 + mova m5, [tlq-128] + and dxq, ~1 + movzx dyd, word [r8+dyq] ; angle - 90 + movzx dxd, word [dxq+270] ; 180 - angle + vpbroadcastd m11, [base+pw_62] + mova [rsp+128], m1 + mova [rsp+ 96], m2 + mova [rsp+ 64], m3 + neg dxd + mova [rsp+ 32], m4 + neg dyq + mova [rsp+ 0], m5 + jmp wq +.w4: + vbroadcasti128 m10, [base+z2_x_shuf] + vpbroadcastq m6, [base+z_base_inc+2] + lea r8d, [dxq+(65<<6)] ; xpos + mov r10d, (63-4)<<6 + test angled, 0x400 + jnz .w4_main ; !enable_intra_edge_filter + lea r3d, [hq+2] + add angled, 1022 + shl r3d, 6 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + movq xm0, [tlq+2] ; 1 2 3 4 + movq xm1, [tlq+0] ; 0 1 2 3 + pshuflw xm2, xm0, q3321 ; 2 3 4 4 + pshuflw xm3, xm1, q2100 ; 0 0 1 2 + vpbroadcastw xm4, r8m ; pixel_max + vbroadcasti128 m10, [base+z_upsample] + paddw xm1, xm0 + paddw xm2, xm3 + lea r8d, [r8+dxq+(1<<6)] + psubw xm2, xm1, xm2 + add dxd, dxd + psraw xm2, 3 + pxor xm3, xm3 + sub r10d, 3<<6 + paddw xm1, xm2 + paddw m6, m6 + pmaxsw xm1, xm3 + sub angled, 1075 ; angle - 53 + pavgw xm1, xm3 + lea r3d, [hq+3] + pminsw xm1, xm4 + xor angled, 0x7f ; 180 - angle + punpcklwd xm1, xm0 + movu [rsp+130], xm1 + call .filter_strength + jmp .w4_filter_left +ALIGN function_align +.filter_strength: + movd xm8, r3d + mov r3d, angled + movd xm7, angled + vpbroadcastb m8, xm8 + shr r3d, 8 ; is_sm << 1 + vpbroadcastb m7, xm7 + pcmpeqb m8, [base+z_filter_wh] + mova xm9, [r9+r3*8] + pand m0, m8, m7 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + ret +ALIGN function_align +.upsample_left: ; h4/h8 + mova xm0, [tlq-16] ; 8 7 6 5 4 3 2 1 + movu xm1, [tlq-14] ; 7 6 5 4 3 2 1 0 + vpbroadcastw xm4, r8m ; pixel_max + cmp hd, 8 + je .upsample_left_h8 + pshufhw xm2, xm0, q2100 ; _ _ _ _ 4 4 3 2 + pshufhw xm3, xm1, q3321 ; _ _ _ _ 2 1 0 0 + jmp .upsample_left_end +.upsample_left_h8: + pblendw xm2, xm0, [tlq-18], 0xfe ; 8 8 7 6 5 4 3 2 + pblendw xm3, xm1, [tlq-12], 0x7f ; 6 5 4 3 2 1 0 0 +.upsample_left_end: + paddw xm1, xm0 + paddw xm2, xm3 + psubw xm2, xm1, xm2 + add dyq, dyq + psraw xm2, 3 + pxor xm3, xm3 + paddw xm1, xm2 + pmaxsw xm1, xm3 + pavgw xm1, xm3 + pminsw xm1, xm4 + punpcklwd xm2, xm0, xm1 + punpckhwd xm0, xm1 + mova [rsp+ 96+gprsize], xm2 + mova [rsp+112+gprsize], xm0 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + sub angled, 1112 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w4_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*0] + psrldq xm0, xm1, 2 ; 1 2 3 4 + pshuflw xm2, xm1, q2100 ; 0 0 1 2 + pmullw xm4, xm0 + pshuflw xm3, xm0, q3321 ; 2 3 4 4 + paddw xm1, xm3 + pshuflw xm3, xm0, q3332 ; 3 4 4 4 + pmullw xm1, xm5 + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*2] + paddw xm2, xm3 + vpbroadcastd xm3, r6m ; max_width + pmullw xm2, xm5 + packssdw xm3, xm3 + paddw xm1, xm4 + paddw xm1, xm2 + psubw xm3, [base+pw_1to16] + pxor xm4, xm4 + psrlw xm1, 3 + pminsw xm3, xm11 ; clip to byte range since there's no variable word blend + pavgw xm1, xm4 + vpblendvb xm1, xm0, xm3 + movq [rsp+130], xm1 +.w4_no_filter_above: + lea r3d, [hq+2] + add angled, 973 ; angle + 883 + shl r3d, 6 + test r3d, angled + jz .w4_upsample_left ; angle <= 140 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm0, [base+pb_90] + psubb xm0, xm7 ; 180 - angle + pand xm0, xm8 ; reuse from previous filter_strength call + pcmpgtb xm0, xm9 + pmovmskb r3d, xm0 +.w4_filter_left: + test r3d, r3d + jz .w4_main + popcnt r3d, r3d + mova m0, [tlq-32] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + vpbroadcastd m5, r7m ; max_height + cmp r3d, 3 + je .w4_filter_left_s3 + vpbroadcastd m2, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pmullw m2, m0 + cmp hd, 8 + jl .w4_filter_left_h4 + movu m4, [tlq-34] + punpcklwd m1, m0, m0 + vpblendd m1, m4, 0xee ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + je .w4_filter_left_end + vpblendd m1, m4, 0x10 ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + jmp .w4_filter_left_end +.w4_upsample_left: + call .upsample_left + mov r11, -16 + vbroadcasti128 m9, [base+z_upsample] + jmp .w4_main_upsample_left +.w4_filter_left_s3: ; can only be h16 + movu m2, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m4, [base+pw_3] + paddw m1, m0, m2 + punpckhwd m2, m2 + vpblendd m2, [tlq-28], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + punpcklwd xm3, xm0, xm0 + paddw m2, m4 + vpblendd m4, m3, [tlq-34], 0xfe ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + vpblendd m3, [tlq-36], 0xfe ; 0 0 0 1 2 3 4 5 6 8 8 9 a b c d + paddw m1, m4 + pavgw m2, m3 + paddw m1, m2 + psrlw m1, 2 + jmp .w4_filter_left_end2 +.w4_filter_left_h4: + pshufhw m1, m0, q2100 ; _ _ _ _ _ _ _ _ _ _ _ _ c c d e +.w4_filter_left_end: + paddw m1, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m3 + paddw m1, m2 + pxor m2, m2 + psrlw m1, 3 + pavgw m1, m2 +.w4_filter_left_end2: + packssdw m5, m5 + psubw m5, [base+pw_16to1] + pminsw m5, m11 + vpblendvb m1, m0, m5 + mova [rsp+96], m1 +.w4_main: + vbroadcasti128 m9, [base+z2_x_shuf] + mov r11, -8 +.w4_main_upsample_left: + movd xm5, dyd + mova m4, [base+z2_y_shuf_h4] + mov r2d, r8d + movd xm0, dxd + vpbroadcastw m5, xm5 + rorx r5, dyq, 5 + lea r8d, [dyq*3] + pmullw m5, [base+z2_ymul] + rorx r9, dyq, 4 + sar dyd, 6 + vpbroadcastw m0, xm0 + sar r8d, 6 + pand m5, m11 ; frac_y + neg dyd + psllw m5, 9 + add r5d, dyd + add r8d, dyd + add r9d, dyd + paddw m7, m0, m0 + lea dyq, [rsp+dyq*2+126] + vpblendd m0, m7, 0xcc + add dyq, r11 + neg r5d + paddw m1, m0, m7 + neg r8d + vpblendd m0, m1, 0xf0 ; xpos0 xpos1 xpos2 xpos3 + neg r9d + paddw m7, m7 + paddw m6, m0 +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm1, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu xm3, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + vinserti128 m1, [rsp+r2*2], 1 + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + vinserti128 m3, [rsp+r3*2], 1 + pshufb m1, m10 ; a0 a1 a2 a3 A0 A1 A2 A3 + pshufb m3, m10 ; b0 b1 b2 b3 B0 B1 B2 B3 + pand m2, m11, m6 + punpcklqdq m0, m1, m3 + punpckhqdq m1, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w4_toponly + movu xm2, [dyq] + vinserti128 m2, [dyq+r8*2], 1 + movu xm3, [dyq+r5*2] + vinserti128 m3, [dyq+r9*2], 1 + pshufb m2, m9 + pshufb m3, m9 + punpckhwd m1, m2, m3 ; a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m2, m3 + psubw m2, m1 + pmulhrsw m2, m5 + psraw m3, m6, 15 ; base_x < topleft + paddw m1, m2 + vpermd m1, m4, m1 ; a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3 + vpblendvb m0, m1, m3 +.w4_toponly: + paddw m6, m7 ; xpos += dx + lea r3, [strideq*3] + add dyq, r11 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r2d, r10d + jge .w4_loop +.w4_leftonly_loop: + movu xm1, [dyq] + vinserti128 m1, [dyq+r8*2], 1 + movu xm2, [dyq+r5*2] + vinserti128 m2, [dyq+r9*2], 1 + add dyq, r11 + pshufb m1, m9 + pshufb m2, m9 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + psubw m1, m0 + pmulhrsw m1, m5 + paddw m0, m1 + vpermd m0, m4, m0 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + RET +.w8: + mov r10d, hd + test angled, 0x400 + jnz .w8_main + lea r3d, [angleq+126] + xor r8d, r8d + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + movu xm0, [tlq+2] ; 1 2 3 4 5 6 7 8 + mova xm1, [tlq+0] ; 0 1 2 3 4 5 6 7 + pblendw xm2, xm0, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 8 + pblendw xm3, xm1, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 + vpbroadcastw xm4, r8m ; pixel_max + paddw xm1, xm0 + paddw xm2, xm3 + not r8d + psubw xm2, xm1, xm2 + add dxd, dxd + psraw xm2, 3 + sub angled, 53 ; angle - 53 + pxor xm3, xm3 + paddw xm2, xm1 + lea r3d, [hq+7] + pmaxsw xm2, xm3 + xor angled, 0x7f ; 180 - angle + pavgw xm2, xm3 + pminsw xm2, xm4 + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 + movu [rsp+130], xm1 + movu [rsp+146], xm2 + call .filter_strength + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + sub angled, 90 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w8_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd xm5, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm6, [base+z_filter_k-4+r3*4+12*2] + movu xm0, [tlq+2] ; 1 2 3 4 5 6 7 8 x + pblendw xm2, xm1, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 x + pmullw xm4, xm0 + pblendw xm3, xm0, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 8 x + paddw xm1, xm3 + vpblendd xm3, [tlq+6], 0x07 ; 3 4 5 6 7 8 8 8 x + paddw xm2, xm3 + vpbroadcastd xm3, r6m ; max_width + pmullw xm1, xm5 + pmullw xm2, xm6 + packssdw xm3, xm3 + paddw xm1, xm4 + paddw xm1, xm2 + psubw xm3, [base+pw_1to16] + pxor xm4, xm4 + psrlw xm1, 3 + pminsw xm3, xm11 + pavgw xm1, xm4 + vpblendvb xm1, xm0, xm3 + movu [rsp+130], xm1 +.w8_no_filter_above: + lea r3d, [angleq-51] + mov r3b, hb + cmp r3d, 8 + jbe .w8_upsample_left ; angle > 140 && h <= 8 && !is_sm + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 +.w8_filter_left: + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + cmp r3d, 3 + jne .w8_filter_left_s12 + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m7, [base+pw_16] + cmp hd, 16 ; flags needed for later + jmp .filter_left_s3b +.w8_upsample_left: + call .upsample_left + vbroadcasti128 m7, [base+z2_y_shuf_us] + lea r11, [rsp+118] + mov r8, -8 + jmp .w8_main_upsample_left +.w16_filter_left_s12: + xor r8d, r8d +.w8_filter_left_s12: + mova m0, [tlq-32] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + vpbroadcastd m5, r7m ; max_height + vpbroadcastd m2, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pmullw m2, m0 + cmp hd, 8 + jl .w8_filter_left_h4 + movu m4, [tlq-34] + punpcklwd m1, m0, m0 + vpblendd m1, m4, 0xee ; 0 0 1 2 3 4 5 6 8 8 9 a b c d e + je .w8_filter_left_end + vpblendd m1, m4, 0x10 ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + jmp .w8_filter_left_end +.w8_filter_left_h4: + pshufhw m1, m0, q2100 ; _ _ _ _ _ _ _ _ _ _ _ _ c c d e +.w8_filter_left_end: + paddw m1, [tlq-30] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pmullw m1, m3 + paddw m1, m2 + pxor m2, m2 + psrlw m1, 3 + pavgw m1, m2 + packssdw m5, m5 + psubw m5, [base+pw_16to1] + pminsw m5, m11 + vpblendvb m1, m0, m5 + mova [rsp+96], m1 + test r8d, r8d + jz .w8_main +; upsample_main + vbroadcasti128 m10, [base+z_upsample] + vbroadcasti128 m7, [base+z2_y_shuf] + lea r5, [rsp+120] + movd xm1, dyd + vbroadcasti128 m4, [base+z_base_inc+2] + movd xm2, dxd + vpbroadcastw m1, xm1 + vpbroadcastw m2, xm2 + mov r7, dstq + paddw m4, m4 + pmullw m0, m1, [base+z2_ymul8] + paddw m5, m2, m2 + psllw xm1, 3 + vpblendd m2, m5, 0xf0 + lea r2d, [dxq+(66<<6)] ; xpos + paddw m4, m2 + pshufd m6, m0, q2020 + psraw xm0, 6 + pxor xm1, xm1 + psubw xm8, xm1, xm0 + pand m6, m11 + punpckhwd xm9, xm8, xm1 + psllw m6, 9 + punpcklwd xm8, xm1 +.w8_upsample_above_loop: + lea r3d, [r2+dxq] + shr r2d, 6 + movu xm1, [rsp+r2*2] + movu xm2, [rsp+r2*2+16] + lea r2d, [r3+dxq] + shr r3d, 6 + vinserti128 m1, [rsp+r3*2], 1 + vinserti128 m2, [rsp+r3*2+16], 1 + pshufb m1, m10 + pshufb m2, m10 + punpcklqdq m0, m1, m2 ; a0 b0 c0 d0 e0 f0 g0 h0 + punpckhqdq m1, m2 + pand m2, m11, m4 + psubw m1, m0 + psllw m2, 9 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w8_upsample_above_toponly + mova m1, m5 + vpgatherdq m3, [r5+xm9*2], m5 + mova m5, m1 + vpgatherdq m2, [r5+xm8*2], m1 + pshufb m3, m7 + pshufb m2, m7 + punpckldq m1, m2, m3 + punpckhdq m2, m3 + psubw m2, m1 + pmulhrsw m2, m6 + paddw m1, m2 + vpermq m1, m1, q3120 + psraw m2, m4, 15 + vpblendvb m0, m1, m2 +.w8_upsample_above_toponly: + paddw m4, m5 + sub r5, 4 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_ret + lea dstq, [dstq+strideq*2] + jmp .w8_upsample_above_loop +.w8_main: + vbroadcasti128 m7, [base+z2_y_shuf] + lea r11, [rsp+120] + mov r8, -4 +.w8_main_upsample_left: + movd xm1, dyd + vbroadcasti128 m4, [base+z_base_inc+2] + movd xm2, dxd + vpbroadcastw m1, xm1 + vpbroadcastw m2, xm2 + mov r7, dstq + pmullw m0, m1, [base+z2_ymul8] + paddw m5, m2, m2 + psllw xm1, 3 + vpblendd m2, m5, 0xf0 ; xpos0 xpos1 + lea r9d, [dxq+(65<<6)] ; xpos + paddw m4, m2 + movd [rsp+284], xm1 +.w8_loop0: + mov r2d, r9d + mova [rsp+288], m0 + mov r5, r11 + mova [rsp+320], m4 + pshufd m6, m0, q2020 + psraw xm0, 6 + pxor xm1, xm1 + psubw xm8, xm1, xm0 ; base_y + pand m6, m11 ; frac_y + punpckhwd xm9, xm8, xm1 ; base_y 2 3 6 7 + psllw m6, 9 + punpcklwd xm8, xm1 ; base_y 0 1 4 5 +.w8_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2*2] + movu xm1, [rsp+r2*2+2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vinserti128 m0, [rsp+r3*2], 1 + vinserti128 m1, [rsp+r3*2+2], 1 + pand m2, m11, m4 + psubw m1, m0 + psllw m2, 9 + pmulhrsw m1, m2 + paddw m0, m1 + cmp r3d, 64 + jge .w8_toponly + mova m1, m5 + vpgatherdq m3, [r5+xm9*2], m5 + mova m5, m1 + vpgatherdq m2, [r5+xm8*2], m1 + pshufb m3, m7 ; c0 d0 c1 d1 g0 h0 g1 h1 + pshufb m2, m7 ; a0 b0 a1 b1 e0 f0 e1 f1 + punpckldq m1, m2, m3 ; a0 b0 c0 d0 a1 b1 c1 d1 e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m2, m3 + psubw m2, m1 + pmulhrsw m2, m6 + paddw m1, m2 + vpermq m1, m1, q3120 + psraw m2, m4, 15 ; base_x < topleft + vpblendvb m0, m1, m2 +.w8_toponly: + paddw m4, m5 ; xpos += dx + add r5, r8 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r2d, (63-8)<<6 + jge .w8_loop +.w8_leftonly_loop: + mova m0, m5 + vpgatherdq m4, [r5+xm9*2], m5 + mova m5, m0 + vpgatherdq m3, [r5+xm8*2], m0 + add r5, r8 + pshufb m2, m4, m7 + pshufb m1, m3, m7 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + psubw m1, m0 + pmulhrsw m1, m6 + paddw m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_leftonly_loop +.w8_end: + sub r10d, 1<<8 + jl .w8_ret + vpbroadcastd m0, [rsp+284] + add r7, 16 + paddw m0, [rsp+288] ; base_y += 8*dy + add r9d, 8<<6 + vpbroadcastd m4, [pw_512] + movzx hd, r10b + paddw m4, [rsp+320] ; base_x += 8*64 + mov dstq, r7 + jmp .w8_loop0 +.w8_ret: + RET +.w16: + movd xm0, [tlq+32] + lea r10d, [hq+(1<<8)] + movd [rsp+160], xm0 + test angled, 0x400 + jnz .w8_main + lea r3d, [hq+15] + sub angled, 90 + call .filter_strength + test r3d, r3d + jz .w16_no_filter_above + popcnt r3d, r3d + vpbroadcastd m4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m5, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m6, [base+z_filter_k-4+r3*4+12*2] + movu m0, [tlq+2] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + punpcklwd xm2, xm1, xm1 + vpblendd m2, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + punpckhwd m3, m0, m0 + pmullw m4, m0 + vpblendd m3, [tlq+4], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + paddw m1, m3 + vpblendd m3, [tlq+6], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g g g + paddw m2, m3 + vpbroadcastd m3, r6m ; max_width + pmullw m1, m5 + pmullw m2, m6 + packssdw m3, m3 + paddw m1, m4 + paddw m1, m2 + psubw m3, [base+pw_1to16] + pxor m4, m4 + psrlw m1, 3 + pminsw m3, m11 + pavgw m1, m4 + vpblendvb m1, m0, m3 + movu [rsp+130], m1 +.w16_no_filter_above: + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + cmp r3d, 3 + jne .w16_filter_left_s12 + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m7, [base+pw_16] + cmp hd, 4 + jne .filter_left_s3 + movq xm0, [tlq-8] ; 0 1 2 3 + movq xm1, [tlq-6] ; 1 2 3 4 + vpbroadcastd xm5, r7m ; max_height + movq xm4, [base+pw_16to1+24] ; 4to1 + pshuflw xm2, xm0, q2100 ; 0 0 1 2 + pshuflw xm3, xm1, q3321 ; 2 3 4 4 + paddw xm1, xm0 + paddw xm1, xm2 + pshuflw xm2, xm0, q1000 ; 0 0 0 1 + paddw xm3, xm6 + packssdw xm5, xm5 + pavgw xm2, xm3 + psubw xm5, xm4 + paddw xm1, xm2 + pminsw xm5, xm11 + psrlw xm1, 2 + vpblendvb xm1, xm0, xm5 + movq [rsp+120], xm1 + jmp .w8_main +.w32: + mova m2, [tlq+32] + movd xm0, [tlq+64] + lea r10d, [hq+(3<<8)] + mova [rsp+160], m2 + movd [rsp+192], xm0 + test angled, 0x400 + jnz .w8_main + vpbroadcastd m6, [base+pw_3] + vpbroadcastd m0, r6m ; max_width + vpbroadcastd m7, [base+pw_16] + mov r3d, 32 + packssdw m0, m0 + psubw m0, [base+pw_1to16] + pminsw m8, m0, m11 + psubw m9, m8, m7 +.w32_filter_above: + movu m0, [tlq+2] + punpcklwd xm4, xm1, xm1 + paddw m2, m6, [tlq+6] + paddw m1, m0 + vpblendd m4, [tlq-2], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m1, [tlq+4] + movu m3, [tlq+r3+2] + paddw m5, m6, [tlq+r3-2] + pavgw m2, m4 + punpckhwd m4, m3, m3 + paddw m1, m2 + vpblendd m2, m4, [tlq+r3+6], 0x7f ; 4 5 6 7 8 9 a b c d e f g h h h + vpblendd m4, [tlq+r3+4], 0x7f ; 3 4 5 6 7 8 9 a b c d e f g h h + pavgw m2, m5 + paddw m5, m3, [tlq+r3] + paddw m4, m5 + psrlw m1, 2 + paddw m2, m4 + vpblendvb m1, m0, m8 + psrlw m2, 2 + vpblendvb m2, m3, m9 + movu [rsp+130], m1 + movu [rsp+r3+130], m2 +.filter_left_s3: + cmp hd, 16 + jl .filter_left_s3_h8 ; h8 +.filter_left_s3b: + mova m0, [tlq-32] ; 2 3 4 5 6 7 8 9 a b c d e f g h + movu m2, [tlq-30] ; 3 4 5 6 7 8 9 a b c d e f g h i + vpbroadcastd m5, r7m ; max_height + paddw m1, m0, m2 + punpckhwd m2, m2 + mov r3d, hd + vpblendd m2, [tlq-28], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + packssdw m5, m5 + not r3 + psubw m5, [base+pw_16to1] + paddw m2, m6 + pminsw m8, m11, m5 + je .filter_left_s3_end ; h16 + paddw m1, [tlq-34] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m2, [tlq-36] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m2 + psrlw m1, 2 + vpblendvb m3, m1, m0, m8 + mova m0, [tlq-64] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m0, [tlq-62] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m2, m6, [tlq-60] ; 4 5 6 7 8 9 a b c d e f g h i j + psubw m8, m7 + mova [rsp+96], m3 + jnp .filter_left_s3_end ; h32 + mova m5, [tlq-96] + paddw m1, [tlq-66] + pavgw m2, [tlq-68] + paddw m1, m2 + paddw m4, m5, [tlq-94] + paddw m2, m6, [tlq-92] + psrlw m1, 2 + paddw m4, [tlq- 98] + pavgw m2, [tlq-100] + vpblendvb m3, m1, m0, m8 + mova m0, [tlq-128] + psubw m8, m7 + paddw m4, m2 + paddw m1, m0, [tlq-126] + paddw m2, m6, [tlq-124] + psrlw m4, 2 + mova [rsp+64], m3 + vpblendvb m4, m5, m8 + psubw m8, m7 + mova [rsp+32], m4 +.filter_left_s3_end: + punpcklwd xm3, xm0, xm0 + vpblendd m4, m3, [tlq+r3*2], 0xfe ; 2 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, [tlq+r3*2-2], 0xfe ; 2 2 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m4 + pavgw m2, m3 + paddw m1, m2 + psrlw m1, 2 + vpblendvb m1, m0, m8 + mova [rsp+r3*2+130], m1 + jmp .w8_main +.filter_left_s3_h8: + mova xm0, [tlq-16] ; 0 1 2 3 4 5 6 7 + movu xm3, [tlq-14] ; 1 2 3 4 5 6 7 8 + pblendw xm2, xm0, [tlq-18], 0xfe ; 0 0 1 2 3 4 5 6 + vpbroadcastd xm5, r7m ; max_height + paddw xm1, xm0, xm3 + pblendw xm3, [tlq-12], 0x7f ; 2 3 4 5 6 7 8 8 + paddw xm1, xm2 + vpblendd xm2, [tlq-20], 0x0e ; 0 0 0 1 2 3 4 5 + paddw xm3, xm6 + packssdw xm5, xm5 + pavgw xm2, xm3 + psubw xm5, [base+pw_16to1+16] ; 8to1 + paddw xm1, xm2 + pminsw xm5, xm11 + psrlw xm1, 2 + vpblendvb xm1, xm0, xm5 + mova [rsp+112], xm1 + jmp .w8_main +.w64: + mova m2, [tlq+ 32] + mova m3, [tlq+ 64] + mova m4, [tlq+ 96] + movd xm0, [tlq+128] + lea r10d, [hq+(7<<8)] + mova [rsp+160], m2 + mova [rsp+192], m3 + mova [rsp+224], m4 + movd [rsp+256], xm0 + test angled, 0x400 + jnz .w8_main + vpbroadcastd m6, [base+pw_3] + movu m0, [tlq+34] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m2, m6, [tlq+30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m5, m0, [tlq+32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m2, [tlq+38] ; 4 5 6 7 8 9 a b c d e f g h h h + paddw m5, [tlq+36] ; 3 4 5 6 7 8 9 a b c d e f g h h + movu m4, [tlq+66] + paddw m3, m6, [tlq+62] + paddw m7, m4, [tlq+64] + pavgw m3, [tlq+70] + paddw m7, [tlq+68] + paddw m2, m5 + vpbroadcastd m5, r6m ; max_width + mov r3d, 96 + packssdw m5, m5 + paddw m3, m7 + psubw m5, [base+pw_1to16] + psrlw m2, 2 + vpbroadcastd m7, [base+pw_16] + psrlw m3, 2 + pminsw m8, m11, m5 + psubw m9, m8, m7 + vpblendvb m2, m0, m9 + psubw m9, m7 + vpblendvb m3, m4, m9 + psubw m9, m7 + movu [rsp+162], m2 + movu [rsp+194], m3 + jmp .w32_filter_above + +cglobal ipred_z3_16bpc, 4, 9, 0, dst, stride, tl, w, h, angle, dy, org_w, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z3_16bpc_avx2_table] + tzcnt hd, hm + movifnidn angled, anglem + lea r7, [dr_intra_derivative+45*2-1] + sub tlq, 2 + movsxd hq, [r6+hq*4] + sub angled, 180 + add hq, r6 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + movzx dyd, word [r7+dyq] + vpbroadcastd m5, [pw_62] + mov org_wd, wd + jmp hq +.h4: + ALLOC_STACK -64, 7 + lea r7, [strideq*3] + cmp angleb, 40 + jae .h4_no_upsample + lea r4d, [angleq-1024] + sar r4d, 7 + add r4d, wd + jg .h4_no_upsample ; !enable_intra_edge_filter || w > 8 || (w == 8 && is_sm) + mova xm2, [tlq-14] ; 0 1 2 3 4 5 6 7 + pblendw xm1, xm2, [tlq-16], 0xfe ; 0 0 1 2 3 4 5 6 + vpblendd xm0, xm1, [tlq-18], 0x0e ; 0 0 0 1 2 3 4 5 + pshufd xm3, xm1, q0000 + paddw xm1, xm2 + paddw xm0, [tlq-12] ; 1 2 3 4 5 6 7 8 + vpbroadcastw xm4, r8m ; pixel_max + add dyd, dyd + psubw xm0, xm1, xm0 + mova [rsp+ 0], xm3 + movd xm3, dyd + psraw xm0, 3 + neg dyd + paddw xm1, xm0 + pxor xm0, xm0 + lea r2d, [dyq+(16<<6)+63] ; ypos + pmaxsw xm1, xm0 + pavgw xm1, xm0 + vpbroadcastw m3, xm3 + pminsw xm1, xm4 + punpckhwd xm0, xm1, xm2 + punpcklwd xm1, xm2 + paddw m2, m3, m3 + mova [rsp+32], xm0 + punpcklwd m3, m2 + mova [rsp+16], xm1 + paddw m4, m2, m2 + paddw m2, m3 + vpblendd m3, m2, 0xf0 ; ypos0 ypos1 ypos2 ypos3 +.h4_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 + movu xm1, [rsp+r2*2] + lea r2d, [r4+dyq] + shr r4d, 6 + movu xm2, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 + vinserti128 m1, [rsp+r2*2], 1 + lea r2d, [r4+dyq] + shr r4d, 6 + vinserti128 m2, [rsp+r4*2], 1 + psrld m0, m1, 16 + pblendw m0, m2, 0xaa ; a3 b3 a2 b2 a1 b1 a0 b0 c3 d3 c2 d2 c1 d1 c0 d0 + pslld m2, 16 + pblendw m1, m2, 0xaa + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m3, m4 + paddw m1, m0 + vextracti128 xm2, m1, 1 + punpckhdq xm0, xm1, xm2 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq xm1, xm2 ; a3 b3 c3 d3 a2 b2 c2 d2 + movhps [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movhps [dstq+strideq*2], xm1 + movq [dstq+r7 ], xm1 + add dstq, 8 + sub wd, 4 + jg .h4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; h4/h8/h16 +%define base r4-z_filter_t0 + lea r4, [z_filter_t0] + movd xm0, maxbased + movd xm1, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m1, xm1 + pcmpeqb m0, [base+z_filter_wh] + pand m0, m1 + mova xm1, [r4+angleq*8] + pcmpgtb m0, m1 + pmovmskb r5d, m0 + ret +.h4_no_upsample: + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea maxbased, [wq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + popcnt r5d, r5d + mova xm0, [tlq-14] ; 0 1 2 3 4 5 6 7 + movu xm3, [tlq-12] ; 1 2 3 4 5 6 7 8 + vpbroadcastd xm2, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd xm4, [base+z_filter_k-4+r5*4+12*0] + pmullw xm2, xm0 + pblendw xm0, [tlq-16], 0xfe ; 0 0 1 2 3 4 5 6 + paddw xm1, xm0, xm3 + movd [rsp+12], xm0 + pmullw xm1, xm4 + cmp r5d, 3 + jne .h4_filter_3tap + pblendw xm3, [tlq-10], 0x7f ; 2 3 4 5 6 7 8 8 + vpblendd xm0, [tlq-18], 0x0e ; 0 0 0 1 2 3 4 5 + movzx r4d, word [tlq-14] + movzx r2d, word [tlq-12] + inc maxbased + paddw xm1, xm2 + paddw xm0, xm3 + sub r2d, r4d + paddw xm2, xm0, xm0 + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+14], r2w +.h4_filter_3tap: + pxor xm0, xm0 + paddw xm1, xm2 + lea tlq, [rsp+30] + psrlw xm1, 3 + cmp wd, 8 + sbb maxbased, -1 + pavgw xm0, xm1 + mova [rsp+16], xm0 +.h4_main: + movd xm3, dyd + neg maxbaseq + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m3, xm3 + lea r4d, [maxbaseq+3*64] + neg dyq + movd xm2, r4d + sub tlq, 8 + lea r4, [dyq+63] ; ypos + punpcklwd m1, m1 + paddw m0, m3, m3 + vpbroadcastw m2, xm2 + punpcklwd m3, m0 + paddw m4, m0, m0 + paddw m0, m3 + psubw m2, m1 + vpblendd m3, m0, 0xf0 ; ypos0 ypos1 ypos2 ypos3 + or maxbased, 63 + paddw m3, m2 +.h4_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu xm1, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + movu xm2, [tlq+r5*2] + lea r5, [r4+dyq] + sar r4, 6 ; base2 + vinserti128 m1, [tlq+r4*2], 1 + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vinserti128 m2, [tlq+r5*2], 1 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + pand m2, m5, m3 + palignr m0, m1, 4 ; a3 b3 a2 b2 a1 b1 a0 b0 c3 d3 c2 d2 c1 d1 c0 d0 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m3, 15 ; ypos < max_base_y + paddw m3, m4 + paddw m1, m0 + vpblendvb m1, m6, m1, m2 + vextracti128 xm2, m1, 1 + punpckhdq xm0, xm1, xm2 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq xm1, xm2 ; a3 b3 c3 d3 a2 b2 c2 d2 + movhps [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movhps [dstq+strideq*2], xm1 + movq [dstq+r7 ], xm1 + sub wd, 4 + jz .h4_end + add dstq, 8 + cmp r4d, maxbased + jg .h4_loop +.h4_end_loop: + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + movq [dstq+strideq*2], xm6 + movq [dstq+r7 ], xm6 + add dstq, 8 + sub wd, 4 + jg .h4_end_loop +.h4_end: + RET +.h8: + lea r4d, [angleq+216] + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 8 + mov r4b, wb + lea r7, [strideq*3] + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m2, [tlq-30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw m1, m2, [tlq-32] ; _ 0 1 2 3 4 5 6 7 8 9 a b c d e + movu m0, [tlq-34] ; _ _ 0 1 2 3 4 5 6 7 8 9 a b c d + cmp wd, 8 + je .h8_upsample_w8 + pshufhw xm3, xm2, q1000 + vpblendd m0, m3, 0x0f ; _ _ _ _ 4 4 4 5 6 7 8 9 a b c d +.h8_upsample_w8: + paddw m0, [tlq-28] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastw m4, r8m ; pixel_max + add dyd, dyd + psubw m0, m1, m0 + movd xm6, dyd + psraw m0, 3 + neg dyd + paddw m1, m0 + pxor m0, m0 + pmaxsw m1, m0 + lea r4d, [dyq+(16<<6)+63] ; ypos + pavgw m1, m0 + vpbroadcastw m6, xm6 + pminsw m1, m4 + punpckhwd m0, m1, m2 + punpcklwd m1, m2 + vextracti128 [rsp+48], m0, 1 + vextracti128 [rsp+32], m1, 1 + paddw m7, m6, m6 + mova [rsp+16], xm0 + mova [rsp+ 0], xm1 + punpcklwd m6, m7 ; ypos0 ypos1 +.h8_upsample_loop: + lea r2d, [r4+dyq] + shr r4d, 6 ; base0 + movu m1, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 ; base1 + movu m2, [rsp+r2*2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base2 + movu m3, [rsp+r4*2] + lea r4d, [r2+dyq] + shr r2d, 6 ; base3 + movu m4, [rsp+r2*2] + psrld m0, m1, 16 + pblendw m0, m2, 0xaa ; a7 b7 a6 b6 a5 b5 a4 b4 a3 b3 a2 b2 a1 b1 a0 b0 + pslld m2, 16 + pblendw m1, m2, 0xaa + psrld m2, m3, 16 + pblendw m2, m4, 0xaa ; c7 d7 c6 d6 c5 d5 c4 d4 c3 d3 c2 d2 c1 d1 c0 d0 + pslld m4, 16 + pblendw m3, m4, 0xaa + pand m4, m5, m6 + paddw m6, m7 + psllw m4, 9 + psubw m1, m0 + pmulhrsw m1, m4 + pand m4, m5, m6 + psllw m4, 9 + psubw m3, m2 + pmulhrsw m3, m4 + paddw m6, m7 + lea r2, [dstq+strideq*4] + paddw m1, m0 + paddw m3, m2 + punpckhdq m0, m1, m3 ; a5 b5 c5 d5 a4 b4 c4 d4 a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq m1, m3 ; a7 b7 c7 d7 a6 b6 c6 d6 a3 b3 c3 d3 a2 b2 c2 d2 + vextracti128 xm2, m0, 1 + vextracti128 xm3, m1, 1 + movhps [r2 +strideq*0], xm0 + movq [r2 +strideq*1], xm0 + movhps [r2 +strideq*2], xm1 + movq [r2 +r7 ], xm1 + movhps [dstq+strideq*0], xm2 + movq [dstq+strideq*1], xm2 + movhps [dstq+strideq*2], xm3 + movq [dstq+r7 ], xm3 + add dstq, 8 + sub wd, 4 + jg .h8_upsample_loop + RET +.h8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(w+7, 15) + jmp .h8_main +.h8_no_upsample: + lea maxbased, [wq+7] + test angled, 0x400 + jnz .h8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h8_main + popcnt r5d, r5d + mova m0, [tlq-30] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movu m3, [tlq-28] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m2, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m4, [base+z_filter_k-4+r5*4+12*0] + pmullw m2, m0 + cmp wd, 8 + jl .h8_filter_w4 + punpcklwd xm0, xm0 + vpblendd m1, m0, [tlq-32], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movd [rsp+28], xm0 + paddw m1, m3 + mov r4d, 16 + pmullw m1, m4 + cmovg maxbased, r4d + cmp r5d, 3 + jne .h8_filter_3tap + punpckhwd m3, m3 + vpblendd m0, [tlq-34], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m3, [tlq-26], 0x7f ; 2 3 4 5 6 7 8 9 a b c d e f g g + movzx r4d, word [tlq-30] + movzx r2d, word [tlq-28] + inc maxbased + paddw m1, m2 + paddw m0, m3 + sub r2d, r4d + paddw m2, m0, m0 + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+30], r2w + jmp .h8_filter_3tap +.h8_filter_w4: + pshufhw xm1, xm0, q2100 + vinserti128 m1, [tlq-16], 1 ; _ _ _ _ 4 4 5 6 7 8 9 a b c d e + paddw m1, m3 + pmullw m1, m4 +.h8_filter_3tap: + pxor m0, m0 + paddw m1, m2 + lea tlq, [rsp+62] + psrlw m1, 3 + pavgw m0, m1 + mova [rsp+32], m0 +.h8_main: + movd xm4, dyd + neg maxbaseq + vbroadcasti128 m1, [z_base_inc] + vpbroadcastw m7, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + lea r4d, [maxbaseq+7*64] + neg dyq + movd xm2, r4d + sub tlq, 16 + lea r4, [dyq+63] + paddw m6, m4, m4 + vpbroadcastw m2, xm2 + vpblendd m4, m6, 0xf0 ; ypos0 ypos1 + psubw m2, m1 + or maxbased, 63 + paddw m4, m2 +.h8_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu xm0, [tlq+r4*2+2] + movu xm1, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + vinserti128 m0, [tlq+r5*2+2], 1 + vinserti128 m1, [tlq+r5*2], 1 + lea r5, [r4+dyq] + sar r4, 6 ; base2 + pand m3, m5, m4 + psllw m3, 9 + psubw m1, m0 + pmulhrsw m1, m3 + psraw m3, m4, 15 + paddw m4, m6 + paddw m0, m1 + movu xm1, [tlq+r4*2+2] + movu xm2, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vpblendvb m0, m7, m0, m3 + vinserti128 m1, [tlq+r5*2+2], 1 + vinserti128 m2, [tlq+r5*2], 1 + pand m3, m5, m4 + psllw m3, 9 + psubw m2, m1 + pmulhrsw m2, m3 + psraw m3, m4, 15 + paddw m4, m6 + lea r5, [dstq+strideq*4] + paddw m1, m2 + vpblendvb m1, m7, m1, m3 + punpckhwd m2, m0, m1 ; a3 c3 a2 c2 a1 c1 a0 c0 b3 d3 b2 d2 b1 d1 b0 d0 + vextracti128 xm3, m2, 1 + punpcklwd m0, m1 ; a7 c7 a6 c6 a5 c5 a4 c5 b7 d7 b6 d6 b5 d5 b4 d4 + punpckhwd xm1, xm2, xm3 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpcklwd xm2, xm3 ; a3 b3 c3 d3 a2 b2 c2 d2 + vextracti128 xm3, m0, 1 + movhps [dstq+strideq*0], xm1 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movq [dstq+r7 ], xm2 + punpckhwd xm1, xm0, xm3 ; a5 b5 c5 d5 a4 b4 c4 d4 + punpcklwd xm0, xm3 ; a7 b7 c7 d7 a6 b6 c6 d6 + movhps [r5 +strideq*0], xm1 + movq [r5 +strideq*1], xm1 + movhps [r5 +strideq*2], xm0 + movq [r5 +r7 ], xm0 + sub wd, 4 + jz .h8_end + add dstq, 8 + cmp r4d, maxbased + jg .h8_loop + lea r6, [strideq*5] + lea r2, [strideq+r7*2] ; stride*7 + test wd, 4 + jz .h8_end_loop + movq [dstq+strideq*0], xm7 + movq [dstq+strideq*1], xm7 + movq [dstq+strideq*2], xm7 + movq [dstq+r7 ], xm7 + movq [dstq+strideq*4], xm7 + movq [dstq+r6 ], xm7 + movq [dstq+r7*2 ], xm7 + movq [dstq+r2 ], xm7 + add dstq, 8 + sub wd, 4 + jz .h8_end +.h8_end_loop: + mova [dstq+strideq*0], xm7 + mova [dstq+strideq*1], xm7 + mova [dstq+strideq*2], xm7 + mova [dstq+r7 ], xm7 + mova [dstq+strideq*4], xm7 + mova [dstq+r6 ], xm7 + mova [dstq+r7*2 ], xm7 + mova [dstq+r2 ], xm7 + add dstq, 16 + sub wd, 8 + jg .h8_end_loop +.h8_end: + RET +.h16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(w+15, 31) + jmp .h16_main +ALIGN function_align +.h16: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 10 + lea maxbased, [wq+15] + lea r7, [strideq*3] + test angled, 0x400 + jnz .h16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h16_main ; filter_strength == 0 + popcnt r5d, r5d + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + paddw m1, m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpbroadcastd m6, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pmullw m2, m6, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + pmullw m1, m7 + paddw m1, m2 + cmp wd, 8 + jg .h16_filter_w16 + mova xm3, [tlq-46] ; 0 1 2 3 4 5 6 7 + pmullw xm6, xm3 + jl .h16_filter_w4 + pblendw xm3, [tlq-48], 0xfe ; 0 0 1 2 3 4 5 6 + cmp r5d, 3 + jne .h16_filter_w8_3tap + vpblendd xm4, xm3, [tlq-50], 0x0e ; 0 0 0 1 2 3 4 5 +.h16_filter_w8_5tap: + punpckhwd m0, m0 + vpblendd m0, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw xm4, [tlq-42] ; 2 3 4 5 6 7 8 9 + paddw m0, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + paddw xm4, xm4 + paddw m0, m0 + paddw xm6, xm4 + paddw m1, m0 +.h16_filter_w8_3tap: + paddw xm3, [tlq-44] ; 1 2 3 4 5 6 7 8 + pmullw xm3, xm7 + pxor m0, m0 + paddw xm3, xm6 + psrlw xm3, 3 + pavgw xm3, xm0 + mova [rsp+48], xm3 + jmp .h16_filter_end +.h16_filter_w4: + pshufhw xm3, xm3, q2100 ; _ _ _ _ 4 4 5 6 + cmp r5d, 3 + jne .h16_filter_w8_3tap + pshufhw xm4, xm3, q2100 ; _ _ _ _ 4 4 4 5 + jmp .h16_filter_w8_5tap +.h16_filter_w16: + mova m3, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + pmullw m6, m3 + punpcklwd xm3, xm3 + vpblendd m4, m3, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + paddw m4, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + mov r4d, 32 + cmp wd, 16 + cmovg maxbased, r4d + movd [rsp+28], xm3 + pmullw m4, m7 + cmp r5d, 3 + jne .h16_filter_w16_3tap + punpckhwd m0, m0 + vpblendd m3, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m0, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m3, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + movzx r4d, word [tlq-62] + movzx r2d, word [tlq-60] + or maxbased, 1 + paddw m3, m3 + sub r2d, r4d + paddw m0, m0 + lea r2d, [r2+r4*8+4] + paddw m4, m3 + shr r2d, 3 + paddw m1, m0 + mov [rsp+30], r2w +.h16_filter_w16_3tap: + pxor m0, m0 + paddw m4, m6 + psrlw m4, 3 + pavgw m4, m0 + mova [rsp+32], m4 +.h16_filter_end: + psrlw m1, 3 + lea tlq, [rsp+94] + pavgw m1, m0 + mova [rsp+64], m1 +.h16_main: + movd xm8, dyd + neg maxbaseq + vpbroadcastw m9, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m8, xm8 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + movd xm7, r4d + sub tlq, 32 + lea r4, [dyq+63] + vpbroadcastw m7, xm7 + or maxbased, 63 + psubw m7, [z_base_inc] +.h16_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + movu m0, [tlq+r4*2+2] + movu m2, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + movu m1, [tlq+r5*2+2] + movu m3, [tlq+r5*2] + lea r5, [r4+dyq] + sar r4, 6 ; base3 + pand m6, m5, m7 + psllw m6, 9 + psubw m2, m0 + pmulhrsw m2, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m0, m2 + movu m2, [tlq+r4*2+2] + movu m4, [tlq+r4*2] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + vpblendvb m0, m9, m0, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m3, m1 + pmulhrsw m3, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m1, m3 + vpblendvb m1, m9, m1, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m4, m2 + pmulhrsw m4, m6 + psraw m6, m7, 15 + paddw m7, m8 + paddw m2, m4 + movu m3, [tlq+r5*2+2] + movu m4, [tlq+r5*2] + vpblendvb m2, m9, m2, m6 + pand m6, m5, m7 + psllw m6, 9 + psubw m4, m3 + pmulhrsw m4, m6 + psraw m6, m7, 15 + paddw m7, m8 + lea r5, [dstq+strideq*4] + paddw m3, m4 + vpblendvb m3, m9, m3, m6 + punpckhwd m4, m0, m1 ; ab bb aa ba a9 b9 a8 b8 a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m0, m1 ; af bf ae be ad bd ac bc a7 b7 a6 b6 a5 b5 a4 b4 + punpckhwd m1, m2, m3 ; cb db ca da c9 d9 c8 d8 c3 d3 c2 d2 c1 d1 c0 d0 + punpcklwd m2, m3 ; cf df ce de cd dd cc dc c7 d7 c6 d6 c5 d5 c4 d4 + punpckhdq m3, m4, m1 ; a9 b9 c9 d9 a8 b8 c8 d8 a1 b1 c1 d1 a0 b0 c0 d0 + vextracti128 xm6, m3, 1 + punpckldq m4, m1 ; ab bb cb db aa ba ca da a3 b3 c3 d3 a2 b2 c2 d2 + punpckhdq m1, m0, m2 ; ad bd cd dd ac bc cc dc a5 b5 c5 d5 a4 b4 c4 d4 + punpckldq m0, m2 ; af bf cf df ae be ce de a7 b7 c7 d7 a6 b6 c6 d6 + vextracti128 xm2, m4, 1 + movhps [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm6 + vextracti128 xm6, m1, 1 + movhps [dstq+strideq*2], xm2 + movq [dstq+r7 ], xm2 + vextracti128 xm2, m0, 1 + movhps [r5 +strideq*0], xm6 + movq [r5 +strideq*1], xm6 + movhps [r5 +strideq*2], xm2 + movq [r5 +r7 ], xm2 + lea r5, [dstq+strideq*8] + movhps [r5 +strideq*0], xm3 + movq [r5 +strideq*1], xm3 + movhps [r5 +strideq*2], xm4 + movq [r5 +r7 ], xm4 + lea r5, [r5+strideq*4] + movhps [r5 +strideq*0], xm1 + movq [r5 +strideq*1], xm1 + movhps [r5 +strideq*2], xm0 + movq [r5 +r7 ], xm0 + sub wd, 4 + jz .h16_end + add dstq, 8 + cmp r4d, maxbased + jg .h16_loop + mov hd, 4 +.h16_end_loop0: + mov r6d, wd + mov r2, dstq + test wb, 4 + jz .h16_end_loop + movq [dstq+strideq*0], xm9 + movq [dstq+strideq*1], xm9 + movq [dstq+strideq*2], xm9 + movq [dstq+r7 ], xm9 + and r6d, 120 + jz .h16_end_w4 + add dstq, 8 +.h16_end_loop: + mova [dstq+strideq*0], xm9 + mova [dstq+strideq*1], xm9 + mova [dstq+strideq*2], xm9 + mova [dstq+r7 ], xm9 + add dstq, 16 + sub r6d, 8 + jg .h16_end_loop +.h16_end_w4: + lea dstq, [r2+strideq*4] + dec hd + jg .h16_end_loop0 +.h16_end: + RET +.h32: + %assign stack_offset org_stack_offset + ALLOC_STACK -160, 9 + lea maxbased, [wq+31] + and maxbased, 31 + or maxbased, 32 ; imin(w+31, 63) + test angled, 0x400 + jnz .h32_main + vpbroadcastd m2, [pw_3] + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + punpckhwd m1, m0, m0 + vpblendd m1, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m0, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m2 + paddw m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m1, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + lea r4, [rsp+128] + paddw m0, m1 + lea r5d, [maxbaseq-31] + psrlw m0, 2 + mova [r4], m0 +.h32_filter_loop: + mova m0, [tlq-62] + paddw m1, m2, [tlq-66] + paddw m0, [tlq-64] + pavgw m1, [tlq-58] + paddw m0, [tlq-60] + sub tlq, 32 + sub r4, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r4], m0 + sub r5d, 16 + jg .h32_filter_loop + jl .h32_filter_h8 + mova m0, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + paddw m2, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m1, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + movzx r5d, word [tlq-62] + movzx r2d, word [tlq-60] + pavgw m2, m3 + sub r2d, r5d + paddw m0, m1 + lea r2d, [r2+r5*8+4] + paddw m0, m2 + shr r2d, 3 + psrlw m0, 2 + mova [r4-32], m0 + mov [r4-36], r5w + mov [r4-34], r2w + lea tlq, [rsp+158] + mov r4d, 65 + cmp wd, 64 + cmove maxbased, r4d + jmp .h32_main +.h32_filter_h8: + mova xm0, [tlq-46] ; 0 1 2 3 4 5 6 7 + pblendw xm1, xm0, [tlq-48], 0xfe ; 0 0 1 2 3 4 5 6 + paddw xm2, [tlq-42] ; 2 3 4 5 6 7 8 9 + paddw xm0, [tlq-44] ; 1 2 3 4 5 6 7 8 + vpblendd xm3, xm1, [tlq-50], 0x0e ; 0 0 0 1 2 3 4 5 + lea tlq, [rsp+158] + pavgw xm2, xm3 + paddw xm0, xm1 + paddw xm0, xm2 + psrlw xm0, 2 + mova [r4-16], xm0 +.h32_main: + movd xm6, dyd + neg maxbaseq + vpbroadcastw m7, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m6, xm6 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + movd xm4, r4d + vpbroadcastd m8, [pw_m1024] + lea r4, [dyq+63] + vpbroadcastw m4, xm4 + or maxbased, 63 + psubw m4, [z_base_inc] +.h32_loop: + mov r5, r4 + sar r5, 6 + movu m1, [tlq+r5*2-64] + movu m0, [tlq+r5*2-62] + pand m3, m5, m4 + psllw m3, 9 + psubw m1, m0 + pmulhrsw m1, m3 + pcmpgtw m2, m8, m4 + paddw m0, m1 + vpblendvb m0, m7, m0, m2 + movu m2, [tlq+r5*2-32] + movu m1, [tlq+r5*2-30] + add r4, dyq + sub rsp, 64 + psubw m2, m1 + pmulhrsw m2, m3 + psraw m3, m4, 15 + paddw m4, m6 + mova [rsp+32*0], m0 + paddw m1, m2 + vpblendvb m1, m7, m1, m3 + mova [rsp+32*1], m1 + dec wd + jz .h32_transpose + cmp r4d, maxbased + jg .h32_loop +.h32_end_loop: + sub rsp, 64 + mova [rsp+32*0], m7 + mova [rsp+32*1], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + lea r3, [strideq*3] + lea r4, [strideq*5] + mov r8, dstq + lea r5, [strideq+r3*2] +.h32_transpose_loop0: + lea r6, [rsp+32] + lea r2, [r8+org_wq*2-16] +.h32_transpose_loop: + mova m0, [r6+64*7] + mova m1, [r6+64*6] + mova m2, [r6+64*5] + mova m3, [r6+64*4] + mova m4, [r6+64*3] + mova m5, [r6+64*2] + mova m6, [r6+64*1] + mova m7, [r6+64*0] + punpckhwd m8, m0, m1 ; a3 b3 a2 b2 a1 b1 a0 b0 + punpcklwd m0, m1 ; a7 b7 a6 b6 a5 b5 a4 b4 + punpckhwd m1, m2, m3 ; c3 d3 c2 d2 c1 d1 c0 d0 + punpcklwd m2, m3 ; c7 d7 c6 d6 c5 d5 c4 d4 + punpckhwd m3, m4, m5 ; e3 f3 e2 f2 e1 f1 e0 f0 + punpcklwd m4, m5 ; e7 f7 e6 f6 e5 f5 e4 f4 + punpckhwd m5, m6, m7 ; g3 h3 g2 h2 g1 h1 g0 h0 + punpcklwd m6, m7 ; g7 h7 g6 h6 g5 h5 g4 h4 + lea dstq, [r2+strideq*8] + sub r6, 32 + punpckhdq m7, m8, m1 ; a1 b1 c1 d1 a0 b0 c0 d0 + punpckldq m8, m1 ; a3 b3 c3 d3 a2 b2 c2 d2 + punpckhdq m1, m3, m5 ; e1 f1 g1 h1 e0 f0 g0 h0 + punpckldq m3, m5 ; e3 f3 g3 h3 e2 f2 g2 h2 + punpckhqdq m5, m7, m1 ; 8 0 + vextracti128 [r2 +strideq*0], m5, 1 + punpcklqdq m7, m1 ; 9 1 + mova [dstq+strideq*0], xm5 + punpckhqdq m1, m8, m3 ; 10 2 + vextracti128 [r2 +strideq*1], m7, 1 + punpcklqdq m8, m3 ; 11 3 + mova [dstq+strideq*1], xm7 + punpckhdq m3, m0, m2 ; a5 b5 c5 d5 a4 b4 c4 d4 + vextracti128 [r2 +strideq*2], m1, 1 + punpckldq m0, m2 ; a7 b7 c7 d7 a6 b6 c6 d6 + mova [dstq+strideq*2], xm1 + punpckhdq m2, m4, m6 ; e5 f5 g5 h5 e4 f4 g4 h4 + vextracti128 [r2 +r3 ], m8, 1 + punpckldq m4, m6 ; e7 f7 g7 h7 e6 f6 g6 h6 + mova [dstq+r3 ], xm8 + punpckhqdq m6, m3, m2 ; 12 4 + vextracti128 [r2 +strideq*4], m6, 1 + punpcklqdq m3, m2 ; 13 5 + mova [dstq+strideq*4], xm6 + punpckhqdq m2, m0, m4 ; 14 6 + vextracti128 [r2 +r4 ], m3, 1 + punpcklqdq m0, m4 ; 15 7 + mova [dstq+r4 ], xm3 + vextracti128 [r2 +r3*2 ], m2, 1 + mova [dstq+r3*2 ], xm2 + vextracti128 [r2 +r5 ], m0, 1 + mova [dstq+r5 ], xm0 + lea r2, [dstq+strideq*8] + cmp r6, rsp + jae .h32_transpose_loop + add rsp, 64*8 + sub org_wd, 8 + jg .h32_transpose_loop0 +.h32_end: + RET +.h64: + %assign stack_offset org_stack_offset + ALLOC_STACK -256, 10 + lea maxbased, [wq+63] + test angled, 0x400 + jnz .h64_main + vpbroadcastd m2, [pw_3] + movu m0, [tlq-28] ; 3 4 5 6 7 8 9 a b c d e f g h i + punpckhwd m1, m0, m0 + vpblendd m1, [tlq-26], 0x7f ; 4 5 6 7 8 9 a b c d e f g h i i + paddw m0, [tlq-30] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m1, m2 + paddw m0, [tlq-32] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + pavgw m1, [tlq-34] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + lea r4, [rsp+224] + paddw m0, m1 + lea r5d, [wq+32] + psrlw m0, 2 + mova [r4], m0 +.h64_filter_loop: + mova m0, [tlq-62] + paddw m1, m2, [tlq-66] + paddw m0, [tlq-64] + pavgw m1, [tlq-58] + paddw m0, [tlq-60] + sub tlq, 32 + sub r4, 32 + paddw m0, m1 + psrlw m0, 2 + mova [r4], m0 + sub r5d, 16 + jg .h64_filter_loop + mova m0, [tlq-62] ; 0 1 2 3 4 5 6 7 8 9 a b c d e f + punpcklwd xm1, xm0, xm0 + paddw m2, [tlq-58] ; 2 3 4 5 6 7 8 9 a b c d e f g h + paddw m0, [tlq-60] ; 1 2 3 4 5 6 7 8 9 a b c d e f g + vpblendd m3, m1, [tlq-66], 0xfe ; 0 0 0 1 2 3 4 5 6 7 8 9 a b c d + vpblendd m1, [tlq-64], 0xfe ; 0 0 1 2 3 4 5 6 7 8 9 a b c d e + lea tlq, [rsp+254] + pavgw m2, m3 + paddw m0, m1 + paddw m0, m2 + psrlw m0, 2 + mova [r4-32], m0 +.h64_main: + neg maxbaseq + movd xm4, dyd + vpbroadcastw m6, [tlq+maxbaseq*2] + shl maxbased, 6 + vpbroadcastw m4, xm4 + lea r4d, [maxbaseq+dyq+15*64] + neg dyq + vpbroadcastd m7, [pw_m1024] + movd xm3, r4d + lea r4, [dyq+63] + paddw m8, m7, m7 + vpbroadcastw m3, xm3 + or maxbased, 63 + paddw m9, m8, m7 + psubw m3, [z_base_inc] +.h64_loop: + mov r5, r4 + sar r5, 6 + movu m1, [tlq+r5*2-128] + movu m0, [tlq+r5*2-126] + pand m2, m5, m3 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + sub rsp, 128 + paddw m0, m1 + pcmpgtw m1, m9, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*0], m0 + movu m1, [tlq+r5*2-96] + movu m0, [tlq+r5*2-94] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m8, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*1], m0 + movu m1, [tlq+r5*2-64] + movu m0, [tlq+r5*2-62] + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + pcmpgtw m1, m7, m3 + vpblendvb m0, m6, m0, m1 + mova [rsp+32*2], m0 + movu m1, [tlq+r5*2-32] + movu m0, [tlq+r5*2-30] + psubw m1, m0 + pmulhrsw m1, m2 + add r4, dyq + psraw m2, m3, 15 + paddw m3, m4 + paddw m0, m1 + vpblendvb m0, m6, m0, m2 + mova [rsp+32*3], m0 + dec wd + jz .h64_transpose + cmp r4d, maxbased + jg .h64_loop +.h64_end_loop: + sub rsp, 128 + mova [rsp+32*0], m6 + mova [rsp+32*1], m6 + mova [rsp+32*2], m6 + mova [rsp+32*3], m6 + dec wd + jg .h64_end_loop +.h64_transpose: + lea r2, [strideq*3] + lea r3, [strideq*5] + mov r5, dstq + lea r4, [strideq+r2*2] +.h64_transpose_loop0: + lea r6, [rsp+112] + lea dstq, [r5+org_wq*2-32] +.h64_transpose_loop: + mova xm0, [r6+128*15] + vinserti128 m0, [r6+128* 7], 1 + mova xm1, [r6+128*14] + vinserti128 m1, [r6+128* 6], 1 + mova xm2, [r6+128*13] + vinserti128 m2, [r6+128* 5], 1 + mova xm3, [r6+128*12] + vinserti128 m3, [r6+128* 4], 1 + mova xm4, [r6+128*11] + vinserti128 m4, [r6+128* 3], 1 + mova xm5, [r6+128*10] + vinserti128 m5, [r6+128* 2], 1 + mova xm6, [r6+128* 9] + vinserti128 m6, [r6+128* 1], 1 + mova xm7, [r6+128* 8] + vinserti128 m7, [r6+128* 0], 1 + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m6, m7 + punpcklwd m6, m7 + sub r6, 16 + punpckhdq m7, m8, m1 + punpckldq m8, m1 + punpckhdq m1, m3, m5 + punpckldq m3, m5 + punpckhqdq m5, m7, m1 + punpcklqdq m7, m1 + punpckhqdq m1, m8, m3 + punpcklqdq m8, m3 + punpckhdq m3, m0, m2 + mova [dstq+strideq*0], m5 + punpckldq m0, m2 + mova [dstq+strideq*1], m7 + punpckhdq m2, m4, m6 + mova [dstq+strideq*2], m1 + punpckldq m4, m6 + mova [dstq+r2 ], m8 + punpckhqdq m6, m3, m2 + mova [dstq+strideq*4], m6 + punpcklqdq m3, m2 + mova [dstq+r3 ], m3 + punpckhqdq m2, m0, m4 + mova [dstq+r2*2 ], m2 + punpcklqdq m0, m4 + mova [dstq+r4 ], m0 + lea dstq, [dstq+strideq*8] + cmp r6, rsp + jae .h64_transpose_loop + add rsp, 128*16 + sub org_wd, 16 + jg .h64_transpose_loop0 +.h64_end: + RET + +%macro FILTER_1BLK 5 ; dst, src, tmp, shuf, bdmax +%ifnum %4 + pshufb xm%2, xm%4 +%else + pshufb xm%2, %4 +%endif + vinserti128 m%2, xm%2, 1 + pshufd m%1, m%2, q0000 + pmaddwd m%1, m2 + pshufd m%3, m%2, q1111 + pmaddwd m%3, m3 + paddd m%1, m1 + paddd m%1, m%3 + pshufd m%3, m%2, q2222 + pmaddwd m%3, m4 + paddd m%1, m%3 + pshufd m%3, m%2, q3333 + pmaddwd m%3, m5 + paddd m%1, m%3 + psrad m%1, 4 + packusdw m%1, m%1 + pminsw m%1, m%5 +%endmacro + +%macro FILTER_2BLK 7 ; dst, src, tmp_dst, tmp_src, tmp, shuf, bdmax + pshufb m%2, m%6 + vpermq m%4, m%2, q3232 + vinserti128 m%2, xm%2, 1 + pshufd m%1, m%2, q0000 + pshufd m%3, m%4, q0000 + pmaddwd m%1, m2 + pmaddwd m%3, m2 + paddd m%1, m1 + paddd m%3, m1 + pshufd m%5, m%2, q1111 + pmaddwd m%5, m3 + paddd m%1, m%5 + pshufd m%5, m%4, q1111 + pmaddwd m%5, m3 + paddd m%3, m%5 + pshufd m%5, m%2, q2222 + pmaddwd m%5, m4 + paddd m%1, m%5 + pshufd m%5, m%4, q2222 + pmaddwd m%5, m4 + paddd m%3, m%5 + pshufd m%5, m%2, q3333 + pmaddwd m%5, m5 + paddd m%1, m%5 + pshufd m%5, m%4, q3333 + pmaddwd m%5, m5 + paddd m%3, m%5 + psrad m%1, 4 + psrad m%3, 4 + packusdw m%1, m%3 + pminsw m%1, m%7 +%endmacro + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. One redundant +; block is calculated for w8 and w16, two for w32. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 5 1 2 3 5 b c d f +; 2 2 3 2 4 5 7 2 4 5 7 c e f h +; 3 3 4 4 6 7 9 4 6 7 9 e g h j +; ___ 4 ___ 4 5 ___ 6 8 9 a ___ 6 8 9 a g i j k ___ +; 5 8 8 i + +cglobal ipred_filter_16bpc, 3, 9, 0, dst, stride, tl, w, h, filter +%assign org_stack_offset stack_offset +%define base r6-ipred_filter_16bpc_avx2_table + lea r6, [filter_intra_taps] + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + add filterq, r6 + lea r6, [ipred_filter_16bpc_avx2_table] + vbroadcasti128 m0, [tlq-6] + movsxd wq, [r6+wq*4] + vpbroadcastd m1, [base+pd_8] + pmovsxbw m2, [filterq+16*0] + pmovsxbw m3, [filterq+16*1] + pmovsxbw m4, [filterq+16*2] + pmovsxbw m5, [filterq+16*3] + add wq, r6 + mov hd, hm + jmp wq +.w4: + WIN64_SPILL_XMM 10 + mova xm8, [base+filter_shuf2] + vpbroadcastw m9, r8m ; bitdepth_max + lea r7, [6+hq*2] + sub tlq, r7 + jmp .w4_loop_start +.w4_loop: + pinsrq xm0, [tlq+hq*2], 0 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER_1BLK 6, 0, 7, 8, 9 + vextracti128 xm0, m6, 1 + movq [dstq+strideq*0], xm6 + movq [dstq+strideq*1], xm0 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vbroadcasti128 m14, [base+filter_shuf3] + vpbroadcastw m15, r8m ; bitdepth_max + FILTER_1BLK 10, 0, 7, [base+filter_shuf2], 15 + vpermq m6, m10, q1302 ; ____ ____ | ____ 4321 + pslldq m8, m0, 4 + psrldq m7, m6, 2 + psrldq m0, m6, 10 + punpcklwd m7, m0 + vpblendd m8, m6, 0x33 ; _0__ 4321 | ____ 4321 + vpblendd m8, m7, 0x40 ; _056 4321 | ____ 4321 + vpblendd m8, [tlq-6], 0x30 ; _056 4321 | ____ 4321 + lea r7, [16+hq*2] + sub tlq, r7 + jmp .w8_loop_start +.w8_loop: + vpermq m8, m9, q1302 ; ____ 4321 | ____ 4321 + vpermq m6, m9, q2031 + psrldq m0, m6, 2 + psrldq m6, 10 + punpcklwd m6, m0 + vpblendd m8, m7, 0x80 ; _0__ 4321 | ____ 4321 + vpblendd m8, m6, 0x40 ; _056 4321 | ____ 4321 + mova m10, m9 +.w8_loop_start: + vpblendd m8, [tlq+hq*2], 0x0C ; _056 4321 | _056 4321 + call .main + vpblendd m10, m9, 0xCC + mova [dstq+strideq*0], xm10 + vextracti128 [dstq+strideq*1], m10, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + %assign stack_offset stack_offset - stack_size_padded + ALLOC_STACK 32, 16 + vpbroadcastw m15, r8m ; bitdepth_max + sub hd, 2 + TAIL_CALL .w16_main, 0 +.w16_main: + mova xm10, [base+filter_shuf2] + FILTER_1BLK 13, 0, 6, 10, 15 + vpermq m12, m13, q3120 + mova xm14, [base+filter_shuf3] + vinserti128 m14, [base+filter_shuf1], 1 + vpbroadcastq m0, [tlq+10] + vpblendd m0, [tlq-16], 0x4C ; ___0 4321 | _056 ____ + psrldq m6, m12, 8 + vpblendd m0, m6, 0x03 ; ___0 4321 | _056 4321 + punpcklwd m6, m12 + vpblendd m0, m6, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 12, 0, 6, 7, 8, 14, 15 + vpblendd m13, m12, 0xCC + vpermq m12, m12, q2031 ; 6___ 5___ + psrldq xm6, xm12, 2 + psrldq xm8, xm12, 12 + vpblendd xm6, xm8, 0x01 + pblendw xm6, [tlq+10], 0xF8 ; 4321 056_ + FILTER_1BLK 11, 6, 8, 10, 15 + vpermq m11, m11, q3120 + pshufd m9, m11, q1032 + movu m8, [tlq+6] ; __43 210_ | ____ ____ + pshufd m8, m8, q3021 ; __0_ 4321 | ____ ____ + pshufhw m8, m8, q3201 ; ___0 4321 | ____ ____ + vpblendd m9, m8, 0x70 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 + lea r7, [20+hq*2] + sub tlq, r7 + vpermq m6, m12, q0123 ; ____ 4321 | ____ 4321 + jmp .w16_loop_start +.w16_loop: + vpermq m13, m13, q3322 + vpermq m11, m9, q2020 + vpermq m9, m9, q1302 + vpermq m6, m12, q0123 + psrldq m7, 4 + vpblendd m13, m10, 0xCC + vpblendd m9, m7, 0x40 + mova m0, [rsp+8] + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 +.w16_loop_start: + mova m13, m12 + vpblendd m0, [tlq+hq*2], 0x0C + psrldq m7, m12, 8 + punpcklwd m7, m12 + vpblendd m0, m6, 0x33 ; ___0 4321 | _056 4321 + vpblendd m0, m7, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 10, 0, 6, 7, 8, 14, 15 + vpermq m12, m10, q2031 + mova [rsp+8], m0 + psrldq m8, m11, 8 + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 10 + psrldq xm0, xm13, 2 + punpcklwd m8, m11 + punpcklwd xm7, xm6 + vpblendd m8, m9, 0x73 ; 56_0 4321 | ____ 4321 + vpblendd m8, m7, 0x04 ; 56_0 4321 | __56 4321 + vpblendd m8, m0, 0x08 ; 56_0 4321 | _056 4321 + call .main + vpermq m8, m11, q3120 + vpblendd m6, m8, m9, 0xCC + mova [dstq+strideq*0+16], xm6 + vextracti128 [dstq+strideq*1+16], m6, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + vpermq m8, m9, q3120 + vextracti128 xm0, m8, 1 ; 4321 ____ + pshufd xm11, xm11, q1032 + vpblendd xm0, xm11, 0x02 ; 4321 0___ + psrldq xm6, xm8, 2 + psrldq xm7, xm8, 12 + pblendw xm0, xm6, 0x4 ; 4321 05__ + pblendw xm0, xm7, 0x2 ; 4321 056_ + FILTER_1BLK 6, 0, 7, [base+filter_shuf2], 15 + vpermq m12, m13, q1302 + vpblendd m12, m10, 0xCC + vpblendd m9, m6, 0xCC + mova [dstq+strideq*0+ 0], xm12 + mova [dstq+strideq*0+16], xm9 + vextracti128 [dstq+strideq*1+ 0], m12, 1 + vextracti128 [dstq+strideq*1+16], m9, 1 + ret +ALIGN function_align +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK 64, 16 + vpbroadcastw m15, r8m ; bitdepth_max + sub hd, 2 + lea r3, [dstq+32] + lea r5d, [hd*2+20] + call .w16_main + mov dstq, r3 + lea tlq, [tlq+r5+32] + sub r5d, 20 + shr r5d, 1 + sub r5d, 2 + lea r4, [dstq+strideq*2-2] +DEFINE_ARGS dst, stride, tl, stride3, left, h + lea stride3q, [strideq*3] + movu m8, [tlq-6] ; 4321 0___ + mova xm10, [base+filter_shuf2] + pinsrw xm0, xm8, [dstq+strideq*0-2], 2 + pinsrw xm0, xm0, [dstq+strideq*1-2], 1 ; 4321 056_ + pinsrw xm9, [leftq+strideq*0], 5 + pinsrw xm9, [leftq+strideq*1], 4 + FILTER_1BLK 13, 0, 6, 10, 15 + vpermq m12, m13, q3120 + mova xm14, [base+filter_shuf3] + vinserti128 m14, [base+filter_shuf1], 1 + psrldq m6, m12, 8 + punpcklwd m7, m6, m12 + vpblendd m0, m6, 0x03 ; ___0 ____ | _0__ 4321 + vpblendd m0, m7, 0x80 ; 56_0 ____ | _0__ 4321 + vpblendd m0, m8, 0x30 ; 56_0 4321 | _0__ 4321 + vpblendd m0, m9, 0x04 ; 56_0 4321 | _056 4321 + FILTER_2BLK 12, 0, 6, 7, 8, 14, 15 + vpblendd m13, m12, 0xCC + pinsrw xm9, [leftq+strideq*2], 3 + pinsrw xm9, [leftq+stride3q ], 2 + lea leftq, [leftq+strideq*4] + pinsrw xm9, [leftq+strideq*0], 1 + pinsrw xm9, [leftq+strideq*1], 0 + movq [rsp+32], xm9 + mov r7d, 1 + pslldq m8, m9, 4 + vpblendd m0, m8, 0x0C ; ___0 ____ | _056 ____ + vpermq m12, m12, q2031 ; 6___ 5___ + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 12 + vpblendd xm6, xm7, 0x01 ; ____ _56_ + pblendw xm6, [tlq+10], 0xF8 ; 4321 056_ + FILTER_1BLK 11, 6, 7, 10, 15 + vpermq m11, m11, q3120 + pshufd m9, m11, q1032 + vbroadcasti128 m8, [tlq+22] ; __43 210_ | ____ ____ + pshufd m8, m8, q3021 ; __0_ 4321 | ____ ____ + pshufhw m8, m8, q3201 ; ___0 4321 | ____ ____ + vpblendd m9, m8, 0x70 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 + vpermq m6, m12, q0123 ; ____ 4321 | ____ 4321 + jmp .w32_loop_start +.w32_loop_last: + mova m0, [rsp+0] + jmp .w32_loop +.w32_loop_left: + mova m0, [rsp+0] + vpblendd m0, [rsp+32+r7*4-12], 0x0C + dec r7d + jg .w32_loop + cmp hd, 2 + je .w32_loop + pinsrw xm6, [rsp+32], 6 + pinsrw xm6, [leftq+strideq*2], 5 + pinsrw xm6, [leftq+stride3q ], 4 + lea leftq, [leftq+strideq*4] + pinsrw xm6, [leftq+strideq*0], 3 + pinsrw xm6, [leftq+strideq*1], 2 + pinsrw xm6, [leftq+strideq*2], 1 + pinsrw xm6, [leftq+stride3q ], 0 + lea leftq, [leftq+strideq*4] + movu [rsp+36], xm6 + pinsrw xm6, [leftq+strideq*0], 1 + pinsrw xm6, [leftq+strideq*1], 0 + movd [rsp+32], xm6 + mov r7d, 4 +.w32_loop: + vpermq m13, m13, q3322 + vpermq m11, m9, q2020 + vpermq m9, m9, q1302 + vpermq m6, m12, q0123 + psrldq m7, 4 + vpblendd m13, m10, 0xCC + vpblendd m9, m7, 0x40 ; ___0 4321 | ____ 4321 + mova [dstq+strideq*0], xm13 + vextracti128 [dstq+strideq*1], m13, 1 +.w32_loop_start: + mova m13, m12 + psrldq m7, m12, 8 + punpcklwd m7, m12 + vpblendd m0, m6, 0x33 ; ___0 4321 | _056 4321 + vpblendd m0, m7, 0x80 ; 56_0 4321 | _056 4321 + FILTER_2BLK 10, 0, 6, 7, 8, 14, 15 + vpermq m12, m10, q2031 + mova [rsp+0], m0 + psrldq m8, m11, 8 + psrldq xm6, xm12, 2 + psrldq xm7, xm12, 10 + psrldq xm0, xm13, 2 + punpcklwd m8, m11 + punpcklwd xm7, xm6 + vpblendd m8, m9, 0x73 ; 56_0 4321 | ____ 4321 + vpblendd m8, m7, 0x04 ; 56_0 4321 | __56 4321 + vpblendd m8, m0, 0x08 ; 56_0 4321 | _056 4321 + call .main + vpermq m8, m11, q3120 + vpblendd m6, m8, m9, 0xCC + mova [dstq+strideq*0+16], xm6 + vextracti128 [dstq+strideq*1+16], m6, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop_left + jz .w32_loop_last + vpermq m8, m9, q3120 + vextracti128 xm0, m8, 1 ; 4321 ____ + pshufd xm11, xm11, q1032 + vpblendd xm0, xm11, 0x02 ; 4321 0___ + psrldq xm6, xm8, 2 + psrldq xm7, xm8, 12 + pblendw xm0, xm6, 0x4 ; 4321 05__ + pblendw xm0, xm7, 0x2 ; 4321 056_ + FILTER_1BLK 6, 0, 7, [base+filter_shuf2], 15 + vpermq m12, m13, q1302 + vpblendd m12, m10, 0xCC + vpblendd m9, m6, 0xCC + mova [dstq+strideq*0+ 0], xm12 + mova [dstq+strideq*0+16], xm9 + vextracti128 [dstq+strideq*1+ 0], m12, 1 + vextracti128 [dstq+strideq*1+16], m9, 1 + RET +.main: + FILTER_2BLK 9, 8, 6, 7, 0, 14, 15 + ret + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +cglobal ipred_cfl_top_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + add tlq, 2 + movd xm4, wd + pxor m6, m6 + vpbroadcastw m7, r7m + pavgw xm4, xm6 + tzcnt wd, wd + movd xm5, wd + movu m0, [tlq] + lea t0, [ipred_cfl_left_16bpc_avx2_table] + movsxd r6, [t0+wq*4] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_avx2_table-ipred_cfl_left_16bpc_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +cglobal ipred_cfl_left_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + sub tlq, hq + movd xm4, hd + sub tlq, hq + pxor m6, m6 + vpbroadcastw m7, r7m + pavgw xm4, xm6 + tzcnt r6d, hd + movd xm5, r6d + movu m0, [tlq] + lea t0, [ipred_cfl_left_16bpc_avx2_table] + movsxd r6, [t0+r6*4] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_avx2_table-ipred_cfl_left_16bpc_avx2_table + tzcnt wd, wd + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + paddw m0, [tlq+32] +.h16: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h8: + psrldq xm1, xm0, 8 + paddw xm0, xm1 +.h4: + punpcklwd xm0, xm6 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + paddd xm0, xm4 + psrld xm0, xm5 + vpbroadcastw m0, xm0 + jmp wq + +cglobal ipred_cfl_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd xm4, t0d + tzcnt t0d, t0d + movd xm5, t0d + lea t0, [ipred_cfl_16bpc_avx2_table] + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + psrlw xm4, 1 + pxor m6, m6 + vpbroadcastw m7, r7m + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movq xm0, [tlq-8] + jmp wq +.w4: + movq xm1, [tlq+2] + paddw m0, m4 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrld m1, m0, 16 + paddw m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + lea r2d, [hq*2] + mov r6d, 0xAAAB6667 + shrx r6d, r6d, r2d + punpckhwd xm1, xm0, xm6 + punpcklwd xm0, xm6 + paddd xm0, xm1 + movd xm1, r6d + psrld xm0, 2 + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w4_end: + vpbroadcastw m0, xm0 +.s4: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + IPRED_CFL 4 + pmaxsw m4, m6 + pminsw m4, m7 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*2], xm5 + movhps [dstq+strideq*1], xm4 + movhps [dstq+r6 ], xm5 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + mova xm0, [tlq-16] + jmp wq +.w8: + vextracti128 xm1, m0, 1 + paddw xm0, [tlq+2] + paddw xm0, xm4 + paddw xm0, xm1 + psrld xm1, xm0, 16 + paddw xm0, xm1 + pblendw xm0, xm6, 0xAA + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w8_end: + vpbroadcastw m0, xm0 +.s8: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+strideq*0], xm4 + mova [dstq+strideq*2], xm5 + vextracti128 [dstq+strideq*1], m4, 1 + vextracti128 [dstq+r6 ], m5, 1 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova m0, [tlq-32] + jmp wq +.w16: + paddw m0, [tlq+2] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpckhwd xm1, xm0, xm6 + punpcklwd xm0, xm6 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+strideq*0], m4 + mova [dstq+strideq*1], m5 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-32] + jmp wq +.w32: + paddw m0, [tlq+ 2] + paddw m0, [tlq+34] + vextracti128 xm1, m0, 1 + paddw xm0, xm4 + paddw xm0, xm1 + punpcklwd xm1, xm0, xm6 + punpckhwd xm0, xm6 + paddd xm0, xm1 + psrlq xm1, xm0, 32 + paddd xm0, xm1 + psrldq xm1, xm0, 8 + paddd xm0, xm1 + psrld xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x6667AAAB + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 + psrlw xm0, 1 +.w32_end: + vpbroadcastw m0, xm0 +.s32: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + pmaxsw m4, m6 + pmaxsw m5, m6 + pminsw m4, m7 + pminsw m5, m7 + mova [dstq+32*0], m4 + mova [dstq+32*1], m5 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + mov r6d, r7m + shr r6d, 11 + lea t0, [ipred_cfl_splat_16bpc_avx2_table] + tzcnt wd, wd + movifnidn hd, hm + movsxd wq, [t0+wq*4] + vpbroadcastd m0, [t0-ipred_cfl_splat_16bpc_avx2_table+pw_512+r6*4] + pxor m6, m6 + vpbroadcastw m7, r7m + add wq, t0 + movifnidn acq, acmp + jmp wq + +cglobal ipred_cfl_ac_420_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_2] + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + jg .w16 + je .w8 +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + mova xm0, [ypxq+strideq*2] + mova xm1, [ypxq+r3 ] + vinserti128 m0, [ypxq+strideq*0], 1 + vinserti128 m1, [ypxq+strideq*1], 1 + lea ypxq, [ypxq+strideq*4] + pmaddwd m0, m5 + pmaddwd m1, m5 + paddd m0, m1 + vextracti128 xm1, m0, 1 + paddd m4, m0 + packssdw xm1, xm0 + mova [acq], xm1 + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .dc + vpermq m1, m1, q1111 + pslld xm0, 2 +.w4_hpad_loop: + mova [acq], m1 + paddd m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .dc +.w8: + mov r5, acq + test wpadd, wpadd + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + vextracti128 xm1, m0, 1 + paddd m4, m0 + packssdw xm1, xm0, xm1 + mova [acq], xm1 + add acq, 16 + dec hd + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz .dc + vinserti128 m1, xm1, 1 + pslld m0, 2 + jmp .hpad +.w8_wpad1: + pmaddwd xm0, xm5, [ypxq+strideq*0] + pmaddwd xm3, xm5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd xm0, xm3 + pshufd xm3, xm0, q3333 + packssdw xm1, xm0, xm3 + paddd xm0, xm3 + paddd xm4, xm0 + mova [acq], xm1 + add acq, 16 + dec hd + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad: + mova m0, [ypxq+strideq*0+ 0] + mova m1, [ypxq+strideq*1+ 0] + cmp wpadd, 2 + jl .w16_wpad1 + je .w16_wpad2 + vpbroadcastd m2, [ypxq+strideq*0+12] + vpbroadcastd m3, [ypxq+strideq*1+12] + vpblendd m0, m2, 0xf0 + vpblendd m1, m3, 0xf0 + jmp .w16_wpad_end +.w16_wpad2: + vpbroadcastd m2, [ypxq+strideq*0+28] + vpbroadcastd m3, [ypxq+strideq*1+28] + jmp .w16_wpad_end +.w16_wpad1: + vpbroadcastd m2, [ypxq+strideq*0+44] + vpbroadcastd m3, [ypxq+strideq*1+44] + vinserti128 m2, [ypxq+strideq*0+32], 0 + vinserti128 m3, [ypxq+strideq*1+32], 0 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + REPX {pmaddwd x, m5}, m0, m1, m2, m3 + paddd m0, m1 + paddd m2, m3 + packssdw m1, m0, m2 + paddd m0, m2 + vpermq m1, m1, q3120 + paddd m4, m0 + mova [acq], m1 + add acq, 32 + dec hd + jg .w16_wpad + jmp .w16_hpad +.w16: + mov r5, acq + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmaddwd m0, m5, [ypxq+strideq*0+ 0] + pmaddwd m2, m5, [ypxq+strideq*0+32] + pmaddwd m1, m5, [ypxq+strideq*1+ 0] + pmaddwd m3, m5, [ypxq+strideq*1+32] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + paddd m2, m3 + packssdw m1, m0, m2 + paddd m0, m2 + vpermq m1, m1, q3120 + paddd m4, m0 + mova [acq], m1 + add acq, 32 + dec hd + jg .w16_loop +.w16_hpad: + add hpadd, hpadd + jz .dc + paddd m0, m0 +.hpad: + mova [acq+32*0], m1 + paddd m4, m0 + mova [acq+32*1], m1 + add acq, 32*2 + sub hpadd, 4 + jg .hpad +.dc: + vextracti128 xm1, m4, 1 + sub r5, acq ; -w*h*2 + tzcnt r1d, r5d + paddd xm4, xm1 + sub r1d, 2 + punpckhqdq xm1, xm4, xm4 + movd xm0, r1d + paddd xm1, xm4 + pshuflw xm4, xm1, q1032 + paddd xm1, xm4 + psrld xm1, xm0 + pxor xm0, xm0 + pavgw xm1, xm0 + vpbroadcastw m1, xm1 +.dc_loop: + mova m0, [acq+r5] + psubw m0, m1 + mova [acq+r5], m0 + add r5, 32 + jl .dc_loop + RET + +cglobal ipred_cfl_ac_422_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_4] + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + jg .w16 + je .w8 +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + mova xm0, [ypxq+strideq*0] + mova xm1, [ypxq+strideq*1] + vinserti128 m0, [ypxq+strideq*2], 1 + vinserti128 m1, [ypxq+r3 ], 1 + lea ypxq, [ypxq+strideq*4] + pmaddwd m0, m5 + pmaddwd m1, m5 + paddd m4, m0 + packssdw m0, m1 + paddd m4, m1 + mova [acq], m0 + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vextracti128 xm1, m1, 1 + vpermq m0, m0, q3333 + pslld xm1, 2 +.w4_hpad_loop: + mova [acq], m0 + paddd m4, m1 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w8: + mov r5, acq + test wpadd, wpadd + jnz .w8_wpad1 +.w8_loop: + pmaddwd m1, m5, [ypxq+strideq*0] + pmaddwd m0, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m4, m1 + packssdw m1, m0 + paddd m4, m0 + vpermq m2, m1, q3120 + mova [acq], m2 + add acq, 32 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vpermq m1, m1, q3131 + pslld m0, 2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w8_wpad1: + vpbroadcastd m1, [ypxq+strideq*0+12] + vpbroadcastd m0, [ypxq+strideq*1+12] + vinserti128 m1, [ypxq+strideq*0+ 0], 0 + vinserti128 m0, [ypxq+strideq*1+ 0], 0 + lea ypxq, [ypxq+strideq*2] + pmaddwd m1, m5 + pmaddwd m0, m5 + paddd m4, m1 + packssdw m1, m0 + paddd m4, m0 + vpermq m2, m1, q3120 + mova [acq], m2 + add acq, 32 + sub hd, 2 + jg .w8_wpad1 + jmp .w8_hpad +.w16: + mov r5, acq + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmaddwd m2, m5, [ypxq+strideq*0+ 0] + pmaddwd m1, m5, [ypxq+strideq*0+32] + pmaddwd m0, m5, [ypxq+strideq*1+ 0] + pmaddwd m3, m5, [ypxq+strideq*1+32] + lea ypxq, [ypxq+strideq*2] + paddd m4, m2 + packssdw m2, m1 + paddd m4, m1 + packssdw m1, m0, m3 + paddd m0, m3 + vpermq m2, m2, q3120 + paddd m4, m0 + vpermq m1, m1, q3120 + mova [acq+32*0], m2 + mova [acq+32*1], m1 + add acq, 32*2 + sub hd, 2 + jg .w16_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).w16_hpad +.w16_wpad: + mova m2, [ypxq+strideq*0+ 0] + mova m0, [ypxq+strideq*1+ 0] + cmp wpadd, 2 + jl .w16_wpad1 + je .w16_wpad2 + vpbroadcastd m1, [ypxq+strideq*0+12] + vpbroadcastd m3, [ypxq+strideq*1+12] + vpblendd m2, m1, 0xf0 + vpblendd m0, m3, 0xf0 + jmp .w16_wpad_end +.w16_wpad2: + vpbroadcastd m1, [ypxq+strideq*0+28] + vpbroadcastd m3, [ypxq+strideq*1+28] + jmp .w16_wpad_end +.w16_wpad1: + vpbroadcastd m1, [ypxq+strideq*0+44] + vpbroadcastd m3, [ypxq+strideq*1+44] + vinserti128 m1, [ypxq+strideq*0+32], 0 + vinserti128 m3, [ypxq+strideq*1+32], 0 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + REPX {pmaddwd x, m5}, m2, m0, m1, m3 + paddd m4, m2 + packssdw m2, m1 + paddd m4, m1 + packssdw m1, m0, m3 + paddd m0, m3 + vpermq m2, m2, q3120 + paddd m4, m0 + vpermq m1, m1, q3120 + mova [acq+32*0], m2 + mova [acq+32*1], m1 + add acq, 32*2 + sub hd, 2 + jg .w16_wpad + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).w16_hpad + +cglobal ipred_cfl_ac_444_16bpc, 4, 7, 6, ac, ypx, stride, wpad, hpad, w, h + lea r6, [ipred_cfl_ac_444_16bpc_avx2_table] + tzcnt wd, wm + movifnidn hpadd, hpadm + vpbroadcastd m5, [pw_1] + movsxd wq, [r6+wq*4] + shl hpadd, 2 + add wq, r6 + mov hd, hm + pxor m4, m4 + sub hd, hpadd + jmp wq +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + movq xm0, [ypxq+strideq*0] + movhps xm0, [ypxq+strideq*1] + vpbroadcastq m1, [ypxq+strideq*2] + vpbroadcastq m2, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + psllw m0, 3 + pmaddwd m1, m0, m5 + mova [acq], m0 + add acq, 32 + paddd m4, m1 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vpermq m0, m0, q3333 + paddd m1, m1 + mova [acq+32*0], m0 + vpermq m1, m1, q3333 + mova [acq+32*1], m0 + add acq, 32*2 + paddd m4, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w8: + lea r3, [strideq*3] + mov r5, acq +.w8_loop: + mova xm2, [ypxq+strideq*0] + vinserti128 m2, [ypxq+strideq*1], 1 + mova xm1, [ypxq+strideq*2] + vinserti128 m1, [ypxq+r3 ], 1 + lea ypxq, [ypxq+strideq*4] + psllw m2, 3 + psllw m1, 3 + mova [acq+32*0], m2 + pmaddwd m2, m5 + mova [acq+32*1], m1 + pmaddwd m0, m1, m5 + add acq, 32*2 + paddd m4, m2 + paddd m4, m0 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + vperm2i128 m1, m1, 0x11 + pslld m0, 2 + pxor m2, m2 + vpblendd m0, m2, 0x0f + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w16_wpad2: + vpbroadcastw m3, [ypxq+strideq*0+14] + vpbroadcastw m0, [ypxq+strideq*1+14] + vpblendd m2, m3, 0xf0 + vpblendd m1, m0, 0xf0 + jmp .w16_wpad_end +.w16: + mov r5, acq +.w16_loop: + mova m2, [ypxq+strideq*0] + mova m1, [ypxq+strideq*1] + test wpadd, wpadd + jnz .w16_wpad2 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + psllw m2, 3 + psllw m1, 3 + mova [acq+32*0], m2 + pmaddwd m2, m5 + mova [acq+32*1], m1 + pmaddwd m0, m1, m5 + add acq, 32*2 + paddd m4, m2 + paddd m4, m0 + sub hd, 2 + jg .w16_loop + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + paddd m0, m0 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).hpad +.w32: + mov r5, acq + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + mova m0, [ypxq+ 0] + mova m1, [ypxq+32] + add ypxq, strideq + psllw m0, 3 + psllw m1, 3 + pmaddwd m2, m0, m5 + mova [acq+32*0], m0 + pmaddwd m3, m1, m5 + mova [acq+32*1], m1 + add acq, 32*2 + paddd m2, m3 + paddd m4, m2 + dec hd + jg .w32_loop +.w32_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc + paddd m2, m2 +.w32_hpad_loop: + mova [acq+32*0], m0 + mova [acq+32*1], m1 + paddd m4, m2 + mova [acq+32*2], m0 + mova [acq+32*3], m1 + add acq, 32*4 + sub hpadd, 2 + jg .w32_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_avx2).dc +.w32_wpad: + mova m0, [ypxq+ 0] + cmp wpadd, 4 + jl .w32_wpad2 + je .w32_wpad4 + vpbroadcastw m1, [ypxq+14] + vpblendd m0, m1, 0xf0 + jmp .w32_wpad_end +.w32_wpad4: + vpbroadcastw m1, [ypxq+30] + jmp .w32_wpad_end +.w32_wpad2: + vpbroadcastw m1, [ypxq+46] + vinserti128 m1, [ypxq+32], 0 +.w32_wpad_end: + add ypxq, strideq + psllw m0, 3 + psllw m1, 3 + pmaddwd m2, m0, m5 + mova [acq+32*0], m0 + pmaddwd m3, m1, m5 + mova [acq+32*1], m1 + add acq, 32*2 + paddd m2, m3 + paddd m4, m2 + dec hd + jg .w32_wpad + jmp .w32_hpad + +cglobal pal_pred_16bpc, 4, 6, 5, dst, stride, pal, idx, w, h + vbroadcasti128 m3, [palq] + lea r2, [pal_pred_16bpc_avx2_table] + tzcnt wd, wm + vbroadcasti128 m4, [pal_pred_shuf] + movifnidn hd, hm + movsxd wq, [r2+wq*4] + pshufb m3, m4 + punpckhqdq m4, m3, m3 + add wq, r2 +DEFINE_ARGS dst, stride, stride3, idx, w, h + lea stride3q, [strideq*3] + jmp wq +.w4: + mova xm2, [idxq] + add idxq, 16 + pshufb xm1, xm3, xm2 + pshufb xm2, xm4, xm2 + punpcklbw xm0, xm1, xm2 + punpckhbw xm1, xm2 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+strideq*1], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + movu m2, [idxq] ; only 16-byte alignment + add idxq, 32 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + vextracti128 [dstq+strideq*2], m0, 1 + vextracti128 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0+ 0], m0 + mova [dstq+strideq*0+32], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*1+ 0], m0 + mova [dstq+strideq*1+32], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + vpermq m2, [idxq+ 0], q3120 + vpermq m5, [idxq+32], q3120 + add idxq, 64 + pshufb m1, m3, m2 + pshufb m2, m4, m2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+ 0], m0 + mova [dstq+32], m1 + pshufb m1, m3, m5 + pshufb m2, m4, m5 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+64], m0 + mova [dstq+96], m1 + add dstq, strideq + dec hd + jg .w64 + RET + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,833 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +ipred_shuf: db 14, 15, 14, 15, 0, 1, 2, 3, 6, 7, 6, 7, 0, 1, 2, 3 + db 10, 11, 10, 11, 8, 9, 10, 11, 2, 3, 2, 3, 8, 9, 10, 11 + db 12, 13, 12, 13, 4, 5, 6, 7, 4, 5, 4, 5, 4, 5, 6, 7 + db 8, 9, 8, 9, 12, 13, 14, 15, 0, 1, 0, 1, 12, 13, 14, 15 +smooth_perm: db 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30 + db 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 81, 82, 85, 86, 89, 90, 93, 94 + db 97, 98,101,102,105,106,109,110,113,114,117,118,121,122,125,126 +pal_pred_perm: db 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39 + db 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47 + db 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55 + db 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63 +filter_permA: times 4 db 6, 7, 8, 9, 14, 15, 4, 5 + times 4 db 10, 11, 12, 13, 2, 3, -1, -1 +filter_permB: times 4 db 22, 23, 24, 25, 30, 31, 6, 7 + times 4 db 26, 27, 28, 29, 14, 15, -1, -1 +filter_permC: dd 8 ; dq 8, 10, 1, 11, 0, 9 +pw_1: times 2 dw 1 + dd 10 +filter_rnd: dd 32 + dd 1 + dd 8 + dd 11 +filter_shift: times 2 dw 6 + dd 0 + times 2 dw 4 + dd 9 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +JMP_TABLE ipred_paeth_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_16bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE pal_pred_16bpc, avx512icl, w4, w8, w16, w32, w64 + +cextern smooth_weights_1d_16bpc +cextern smooth_weights_2d_16bpc +cextern filter_intra_taps + +SECTION .text + +%macro PAETH 3 ; top, signed_ldiff, ldiff + paddw m0, m%2, m2 + psubw m1, m0, m3 ; tldiff + psubw m0, m%1 ; tdiff + pabsw m1, m1 + pabsw m0, m0 + pcmpgtw k1, m0, m1 + pminsw m0, m1 + pcmpgtw k2, m%3, m0 + vpblendmw m0{k1}, m%1, m3 + vpblendmw m0{k2}, m2, m0 +%endmacro + +INIT_ZMM avx512icl +cglobal ipred_paeth_16bpc, 3, 7, 10, dst, stride, tl, w, h +%define base r6-ipred_paeth_16bpc_avx512icl_table + lea r6, [ipred_paeth_16bpc_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastw m3, [tlq] ; topleft + add wq, r6 + jmp wq +.w4: + vpbroadcastq m4, [tlq+2] ; top + movsldup m7, [base+ipred_shuf] + lea r6, [strideq*3] + psubw m5, m4, m3 + pabsw m6, m5 +.w4_loop: + sub tlq, 16 + vbroadcasti32x4 m2, [tlq] + pshufb m2, m7 ; left + PAETH 4, 5, 6 + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm8, ym0, 1 + vextracti32x4 xm9, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm8 + movq [dstq+r6 ], xm9 + sub hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm8 + movhps [dstq+r6 ], xm9 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.w4_end: + RET +.w8: + vbroadcasti32x4 m4, [tlq+2] + movsldup m7, [base+ipred_shuf] + lea r6, [strideq*3] + psubw m5, m4, m3 + pabsw m6, m5 +.w8_loop: + sub tlq, 8 + vpbroadcastq m2, [tlq] + pshufb m2, m7 + PAETH 4, 5, 6 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + vbroadcasti32x8 m4, [tlq+2] + movsldup m7, [base+ipred_shuf] + psubw m5, m4, m3 + pabsw m6, m5 +.w16_loop: + sub tlq, 4 + vpbroadcastd m2, [tlq] + pshufb m2, m7 + PAETH 4, 5, 6 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + movu m4, [tlq+2] + psubw m5, m4, m3 + pabsw m6, m5 +.w32_loop: + sub tlq, 2 + vpbroadcastw m2, [tlq] + PAETH 4, 5, 6 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +.w64: + movu m4, [tlq+ 2] + movu m7, [tlq+66] + psubw m5, m4, m3 + psubw m8, m7, m3 + pabsw m6, m5 + pabsw m9, m8 +.w64_loop: + sub tlq, 2 + vpbroadcastw m2, [tlq] + PAETH 4, 5, 6 + mova [dstq+64*0], m0 + PAETH 7, 8, 9 + mova [dstq+64*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_16bpc, 3, 7, 7, dst, stride, tl, w, h, weights, stride3 +%define base r6-$$ + lea r6, [$$] + tzcnt wd, wm + mov hd, hm + movsxd wq, [base+ipred_smooth_v_16bpc_avx512icl_table+wq*4] + lea weightsq, [base+smooth_weights_1d_16bpc+hq*4] + neg hq + vpbroadcastw m6, [tlq+hq*2] ; bottom + lea wq, [base+ipred_smooth_v_16bpc_avx512icl_table+wq] + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastq m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w4_loop: + vbroadcasti32x4 m3, [weightsq+hq*2] + pshufb m3, m4 + pmulhrsw m3, m5 + paddw m3, m6 + vextracti32x4 xm0, m3, 3 + vextracti32x4 xm1, ym3, 1 + vextracti32x4 xm2, m3, 2 + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + add hq, 8 + jg .end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jl .w4_loop +.end: + RET +.w8: + vbroadcasti32x4 m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w8_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m4 + pmulhrsw m0, m5 + paddw m0, m6 + vextracti32x4 [dstq+strideq*0], m0, 3 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + vbroadcasti32x8 m5, [tlq+2] ; top + movsldup m4, [ipred_shuf] + psubw m5, m6 ; top - bottom +.w16_loop: + vpbroadcastd m0, [weightsq+hq*2+0] + vpbroadcastd m1, [weightsq+hq*2+4] + pshufb m0, m4 + pshufb m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + paddw m0, m6 + paddw m1, m6 + vextracti32x8 [dstq+strideq*0], m0, 1 + mova [dstq+strideq*1], ym0 + vextracti32x8 [dstq+strideq*2], m1, 1 + mova [dstq+stride3q ], ym1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + movu m5, [tlq+2] + psubw m5, m6 +.w32_loop: + vpbroadcastw m0, [weightsq+hq*2+0] + vpbroadcastw m1, [weightsq+hq*2+2] + vpbroadcastw m2, [weightsq+hq*2+4] + vpbroadcastw m3, [weightsq+hq*2+6] + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w32_loop + RET +.w64: + movu m4, [tlq+ 2] + movu m5, [tlq+66] + psubw m4, m6 + psubw m5, m6 +.w64_loop: + vpbroadcastw m1, [weightsq+hq*2+0] + vpbroadcastw m3, [weightsq+hq*2+2] + pmulhrsw m0, m4, m1 + pmulhrsw m1, m5 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m5 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + mova [dstq+strideq*1+64*0], m2 + mova [dstq+strideq*1+64*1], m3 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w64_loop + RET + +cglobal ipred_smooth_h_16bpc, 3, 7, 7, dst, stride, tl, w, h, stride3 + lea r6, [$$] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m6, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [base+ipred_smooth_h_16bpc_avx512icl_table+wq*4] + sub tlq, hq + lea stride3q, [strideq*3] + lea wq, [base+ipred_smooth_h_16bpc_avx512icl_table+wq] + jmp wq +.w4: + movsldup m4, [base+ipred_shuf] + vpbroadcastq m5, [base+smooth_weights_1d_16bpc+4*2] +.w4_loop: + vbroadcasti32x4 m0, [tlq+hq-16] ; left + pshufb m0, m4 + psubw m0, m6 ; left - right + pmulhrsw m0, m5 + paddw m0, m6 + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm2, ym0, 1 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + sub hd, 8*2 + jl .end + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.end: + RET +.w8: + movsldup m4, [base+ipred_shuf] + vbroadcasti32x4 m5, [base+smooth_weights_1d_16bpc+8*2] +.w8_loop: + vpbroadcastq m0, [tlq+hq-8] ; left + pshufb m0, m4 + psubw m0, m6 ; left - right + pmulhrsw m0, m5 + paddw m0, m6 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w8_loop + RET +.w16: + movsldup m4, [base+ipred_shuf] + vbroadcasti32x8 m5, [base+smooth_weights_1d_16bpc+16*2] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastd m1, [tlq+hq-8] + pshufb m0, m4 + pshufb m1, m4 + psubw m0, m6 + psubw m1, m6 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + paddw m0, m6 + paddw m1, m6 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w16_loop + RET +.w32: + movu m5, [base+smooth_weights_1d_16bpc+32*2] +.w32_loop: + vpbroadcastq m3, [tlq+hq-8] + punpcklwd m3, m3 + psubw m3, m6 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hq, 4*2 + jg .w32_loop + RET +.w64: + movu m4, [base+smooth_weights_1d_16bpc+64*2] + movu m5, [base+smooth_weights_1d_16bpc+64*3] +.w64_loop: + vpbroadcastw m1, [tlq+hq-2] + vpbroadcastw m3, [tlq+hq-4] + psubw m1, m6 + psubw m3, m6 + pmulhrsw m0, m4, m1 + pmulhrsw m1, m5 + pmulhrsw m2, m4, m3 + pmulhrsw m3, m5 + REPX {paddw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + mova [dstq+strideq*1+64*0], m2 + mova [dstq+strideq*1+64*1], m3 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w64_loop + RET + +cglobal ipred_smooth_16bpc, 3, 7, 16, dst, stride, tl, w, h, v_weights, stride3 + lea r6, [$$] + mov wd, wm + movifnidn hd, hm + vpbroadcastw m13, [tlq+wq*2] ; right + tzcnt wd, wd + add hd, hd + movsxd wq, [base+ipred_smooth_16bpc_avx512icl_table+wq*4] + mov r5d, 0x55555555 + sub tlq, hq + mova m14, [base+smooth_perm] + kmovd k1, r5d + vpbroadcastw m0, [tlq] ; bottom + mov r5, 0x3333333333333333 + pxor m15, m15 + lea wq, [base+ipred_smooth_16bpc_avx512icl_table+wq] + kmovq k2, r5 + lea v_weightsq, [base+smooth_weights_2d_16bpc+hq*2] + jmp wq +.w4: + vpbroadcastq m5, [tlq+hq+2] + movshdup m3, [base+ipred_shuf] + movsldup m4, [base+ipred_shuf] + vbroadcasti32x4 m6, [base+smooth_weights_2d_16bpc+4*4] + lea stride3q, [strideq*3] + punpcklwd m5, m0 ; top, bottom +.w4_loop: + vbroadcasti32x4 m0, [v_weightsq] + vpbroadcastq m2, [tlq+hq-8] + mova m1, m13 + pshufb m0, m3 + pmaddwd m0, m5 + pshufb m1{k2}, m2, m4 ; left, right + vpdpwssd m0, m1, m6 + vpermb m0, m14, m0 + pavgw ym0, ym15 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + add v_weightsq, 4*4 + sub hd, 4*2 + jg .w4_loop + RET +.w8: + vbroadcasti32x4 ym5, [tlq+hq+2] + movshdup m6, [base+ipred_shuf] + movsldup m7, [base+ipred_shuf] + pmovzxwd m5, ym5 + vbroadcasti32x8 m8, [base+smooth_weights_2d_16bpc+8*4] + lea stride3q, [strideq*3] + vpblendmw m5{k1}, m0, m5 ; top, bottom +.w8_loop: + vpbroadcastq m0, [v_weightsq+0] + vpbroadcastq m1, [v_weightsq+8] + vpbroadcastd m3, [tlq+hq-4] + vpbroadcastd m4, [tlq+hq-8] + pshufb m0, m6 + pmaddwd m0, m5 + pshufb m1, m6 + pmaddwd m1, m5 + mova m2, m13 + pshufb m2{k2}, m3, m7 ; left, right + mova m3, m13 + pshufb m3{k2}, m4, m7 + vpdpwssd m0, m2, m8 + vpdpwssd m1, m3, m8 + add v_weightsq, 4*4 + vpermt2b m0, m14, m1 + pavgw m0, m15 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w8_loop + RET +.w16: + pmovzxwd m5, [tlq+hq+2] + mova m6, [base+smooth_weights_2d_16bpc+16*4] + vpblendmw m5{k1}, m0, m5 ; top, bottom +.w16_loop: + vpbroadcastd m0, [v_weightsq+0] + vpbroadcastd m1, [v_weightsq+4] + pmaddwd m0, m5 + pmaddwd m1, m5 + mova m2, m13 + vpbroadcastw m2{k1}, [tlq+hq-2] ; left, right + mova m3, m13 + vpbroadcastw m3{k1}, [tlq+hq-4] + vpdpwssd m0, m2, m6 + vpdpwssd m1, m3, m6 + add v_weightsq, 2*4 + vpermt2b m0, m14, m1 + pavgw m0, m15 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w16_loop + RET +.w32: + pmovzxwd m5, [tlq+hq+ 2] + pmovzxwd m6, [tlq+hq+34] + mova m7, [base+smooth_weights_2d_16bpc+32*4] + mova m8, [base+smooth_weights_2d_16bpc+32*6] + vpblendmw m5{k1}, m0, m5 ; top, bottom + vpblendmw m6{k1}, m0, m6 +.w32_loop: + vpbroadcastd m2, [v_weightsq+0] + vpbroadcastd m3, [v_weightsq+4] + pmaddwd m0, m5, m2 + pmaddwd m2, m6 + pmaddwd m1, m5, m3 + pmaddwd m3, m6 + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-2] ; left, right + vpdpwssd m0, m4, m7 + vpdpwssd m2, m4, m8 + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-4] + vpdpwssd m1, m4, m7 + vpdpwssd m3, m4, m8 + add v_weightsq, 2*4 + vpermt2b m0, m14, m2 + vpermt2b m1, m14, m3 + pavgw m0, m15 + pavgw m1, m15 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hq, 2*2 + jg .w32_loop + RET +.w64: + pmovzxwd m5, [tlq+hq+ 2] + pmovzxwd m6, [tlq+hq+34] + pmovzxwd m7, [tlq+hq+66] + pmovzxwd m8, [tlq+hq+98] + mova m9, [base+smooth_weights_2d_16bpc+64*4] + vpblendmw m5{k1}, m0, m5 ; top, bottom + mova m10, [base+smooth_weights_2d_16bpc+64*5] + vpblendmw m6{k1}, m0, m6 + mova m11, [base+smooth_weights_2d_16bpc+64*6] + vpblendmw m7{k1}, m0, m7 + mova m12, [base+smooth_weights_2d_16bpc+64*7] + vpblendmw m8{k1}, m0, m8 +.w64_loop: + vpbroadcastd m3, [v_weightsq] + mova m4, m13 + vpbroadcastw m4{k1}, [tlq+hq-2] ; left, right + pmaddwd m0, m5, m3 + pmaddwd m2, m6, m3 + pmaddwd m1, m7, m3 + pmaddwd m3, m8 + vpdpwssd m0, m4, m9 + vpdpwssd m2, m4, m10 + vpdpwssd m1, m4, m11 + vpdpwssd m3, m4, m12 + add v_weightsq, 1*4 + vpermt2b m0, m14, m2 + vpermt2b m1, m14, m3 + pavgw m0, m15 + pavgw m1, m15 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + sub hd, 1*2 + jg .w64_loop + RET + +cglobal pal_pred_16bpc, 4, 7, 4, dst, stride, pal, idx, w, h, stride3 + lea r6, [pal_pred_16bpc_avx512icl_table] + tzcnt wd, wm + mova m2, [pal_pred_perm] + movsxd wq, [r6+wq*4] + mova xm3, [palq] + movifnidn hd, hm + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + pmovzxbw ym0, [idxq] + add idxq, 16 + vpermw ym0, ym0, ym3 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pmovzxbw m0, [idxq] + add idxq, 32 + vpermw m0, m0, m3 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + vpermb m1, m2, [idxq] + add idxq, 64 + vpermw m0, m1, m3 + psrlw m1, 8 + vpermw m1, m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + dec hd + jg .w64 + RET + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. +; w4 w8 w16 w32 +; 1 1 2 1 2 5 6 1 2 5 6 9 a d e +; 2 2 3 2 3 6 7 2 3 6 7 a b e f +; 3 3 4 3 4 7 8 3 4 7 8 b c f g +; 4 4 5 4 5 8 9 4 5 8 9 c d g h + +cglobal ipred_filter_16bpc, 4, 7, 14, dst, stride, tl, w, h, filter, top +%define base r6-$$ + lea r6, [$$] +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + movifnidn hd, hm + movu xm0, [tlq-6] + pmovsxbw m7, [base+filter_intra_taps+filterq+32*0] + pmovsxbw m8, [base+filter_intra_taps+filterq+32*1] + mov r5d, r8m ; bitdepth_max + movsldup m9, [base+filter_permA] + movshdup m10, [base+filter_permA] + shr r5d, 11 ; is_12bpc + jnz .12bpc + psllw m7, 2 ; upshift multipliers so that packusdw + psllw m8, 2 ; will perform clipping for free +.12bpc: + vpbroadcastd m5, [base+filter_rnd+r5*8] + vpbroadcastd m6, [base+filter_shift+r5*8] + sub wd, 8 + jl .w4 +.w8: + call .main4 + movsldup m11, [filter_permB] + lea r5d, [hq*2+2] + movshdup m12, [filter_permB] + lea topq, [tlq+2] + mova m13, [filter_permC] + sub hd, 4 + vinserti32x4 ym0, [topq], 1 ; a0 b0 t0 t1 + sub tlq, r5 +%if WIN64 + push r7 + push r8 +%endif + mov r7, dstq + mov r8d, hd +.w8_loop: + movlps xm4, xm0, [tlq+hq*2] + call .main8 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jge .w8_loop + test wd, wd + jz .end + mov r2d, 0x0d + kmovb k1, r2d + lea r2, [strideq*3] +.w16: + movd xmm0, [r7+strideq*1+12] + vpblendd xmm0, [topq+8], 0x0e ; t1 t2 + pinsrw xm4, xmm0, [r7+strideq*0+14], 2 + call .main8 + add r7, 16 + vinserti32x4 ym0, [topq+16], 1 ; a2 b2 t2 t3 + mov hd, r8d + mov dstq, r7 + add topq, 16 +.w16_loop: + movd xmm1, [dstq+strideq*2-4] + punpcklwd xm4, xmm1, xmm0 + movd xmm0, [dstq+r2-4] + shufps xm4{k1}, xmm0, xm0, q3210 + call .main8 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jge .w16_loop + sub wd, 8 + jg .w16 +.end: + vpermb m2, m11, m0 + mova ym1, ym5 + vpdpwssd m1, m2, m7 + vpermb m2, m12, m0 + vpdpwssd m1, m2, m8 +%if WIN64 + pop r8 + pop r7 +%endif + vextracti32x8 ym2, m1, 1 + paddd ym1, ym2 + packusdw ym1, ym1 + vpsrlvw ym1, ym6 + vpermt2q m0, m13, m1 + vextracti32x4 [dstq+strideq*0], m0, 2 + vextracti32x4 [dstq+strideq*1], ym0, 1 + RET +.w4_loop: + movlps xm0, [tlq-10] + lea dstq, [dstq+strideq*2] + sub tlq, 4 +.w4: + call .main4 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.main4: + vpermb m2, m9, m0 + mova ym1, ym5 + vpdpwssd m1, m2, m7 + vpermb m0, m10, m0 + vpdpwssd m1, m0, m8 + vextracti32x8 ym0, m1, 1 + paddd ym0, ym1 + vextracti32x4 xm1, ym0, 1 + packusdw xm0, xm1 ; clip + vpsrlvw xm0, xm6 + ret +ALIGN function_align +.main8: + vpermb m3, m11, m0 + mova ym2, ym5 + vpdpwssd m2, m3, m7 + vpermb m3, m9, m4 + mova ym1, ym5 + vpdpwssd m1, m3, m7 + vpermb m3, m12, m0 + vpdpwssd m2, m3, m8 + vpermb m3, m10, m4 + vpdpwssd m1, m3, m8 + vextracti32x8 ym4, m2, 1 + vextracti32x8 ym3, m1, 1 + paddd ym2, ym4 + paddd ym1, ym3 + packusdw ym1, ym2 ; clip + vpsrlvw ym1, ym6 + vpermt2q m0, m13, m1 ; c0 d0 b0 b1 a0 a1 + vextracti32x4 [dstq+strideq*0], m0, 2 + vextracti32x4 [dstq+strideq*1], ym0, 1 + ret + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4076 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA + +filter_shuf: db 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4, 5, 2, 3, -1, -1 +pal_pred_shuf: db 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 +z_base_inc_z2: dw 7*64, 6*64, 5*64, 4*64, 3*64, 2*64, 1*64, 0*64 +z_upsample: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_upsample_l: db -1, -1, -2, -1, -3, -1, -4, -1, 8, 9, 8, 9, 10, 11, 12, 13 + db 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 +z2_top_shufA: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +z2_top_shufB: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +z2_left_shufA: db 14, 15, 12, 13, 10, 11, 8, 9, 12, 13, 10, 11, 8, 9, 6, 7 +z2_left_shufB: db 14, 15, 10, 11, 6, 7, 2, 3, 12, 13, 8, 9, 4, 5, 0, 1 +z_filt_wh16: db 19, 19, 19, 23, 23, 23, 31, 31, 31, 47, 47, 47, 79, 79, 79, -1 +z_filt_t_w48: db 55,127, 7,127, 15, 31, 39, 31,127, 39,127, 39, 7, 15, 31, 15 + db 39, 63, 3, 63, 3, 3, 19, 3, 47, 19, 47, 19, 3, 3, 3, 3 +z_filt_t_w16: db 15, 31, 7, 15, 31, 7, 3, 31, 3, 3, 3, 3, 3, 3, 0, 0 +z_filt_wh4: db 7, 7, 19, 7, +z_filt_wh8: db 19, 19, 11, 19, 11, 15, 15, 15, 23, 23, 23, 23, 39, 39, 39, 39 +ALIGN 8 +pb_2_3: times 4 db 2, 3 +z2_dy_offset: dw 96*64, 96*64, 95*64, 95*64 +z_filt_k: times 4 dw 8 + times 4 dw 6 + times 4 dw 4 + times 4 dw 5 +pw_m3584: times 4 dw -3584 +pw_m3072: times 4 dw -3072 +pw_m2560: times 4 dw -2560 +pw_m2048: times 4 dw -2048 +pw_m1536: times 4 dw -1536 +pw_m1024: times 4 dw -1024 +pw_m512: times 4 dw -512 +pw_1: times 4 dw 1 +pw_2: times 4 dw 2 +pw_3: times 4 dw 3 +pw_62: times 4 dw 62 +pw_256: times 4 dw 256 +pw_512: times 4 dw 512 +pw_2048: times 4 dw 2048 + +%define pw_4 (z_filt_k+8*2) +%define pw_8 (z_filt_k+8*0) +%define pw_m1to4 z2_upsample_l + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_16bpc_ssse3_table (ipred_dc_16bpc_ssse3_table + 10*4) +%define ipred_dc_128_16bpc_ssse3_table (ipred_dc_16bpc_ssse3_table + 15*4) +%define ipred_cfl_splat_16bpc_ssse3_table (ipred_cfl_16bpc_ssse3_table + 8*4) + +JMP_TABLE ipred_dc_left_16bpc, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_dc_16bpc, ssse3, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4, \ + s4-15*4, s8-15*4, s16c-15*4, s32c-15*4, s64-15*4 +JMP_TABLE ipred_h_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2_16bpc, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3_16bpc, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_cfl_16bpc, ssse3, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left_16bpc, ssse3, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_444_16bpc, ssse3, w4, w8, w16, w32 +JMP_TABLE pal_pred_16bpc, ssse3, w4, w8, w16, w32, w64 + +cextern smooth_weights_1d_16bpc +cextern smooth_weights_2d_16bpc +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_XMM ssse3 +cglobal ipred_dc_top_16bpc, 3, 7, 6, dst, stride, tl, w, h + LEA r5, ipred_dc_left_16bpc_ssse3_table + movd m4, wm + tzcnt wd, wm + add tlq, 2 + movifnidn hd, hm + pxor m3, m3 + pavgw m4, m3 + movd m5, wd + movu m0, [tlq] + movsxd r6, [r5+wq*4] + add r6, r5 + add r5, ipred_dc_128_16bpc_ssse3_table-ipred_dc_left_16bpc_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_16bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_left_16bpc_ssse3_table + mov hd, hm + movd m4, hm + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + pxor m3, m3 + sub tlq, hq + pavgw m4, m3 + movd m5, r6d + movu m0, [tlq] + movsxd r6, [r5+r6*4] + add r6, r5 + add r5, ipred_dc_128_16bpc_ssse3_table-ipred_dc_left_16bpc_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m2, [tlq+112] + movu m1, [tlq+ 96] + paddw m0, m2 + movu m2, [tlq+ 80] + paddw m1, m2 + movu m2, [tlq+ 64] + paddw m0, m2 + paddw m0, m1 +.h32: + movu m1, [tlq+ 48] + movu m2, [tlq+ 32] + paddw m1, m2 + paddw m0, m1 +.h16: + movu m1, [tlq+ 16] + paddw m0, m1 +.h8: + movhlps m1, m0 + paddw m0, m1 +.h4: + punpcklwd m0, m3 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + lea stride3q, [strideq*3] + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +cglobal ipred_dc_16bpc, 4, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd m4, r5d + tzcnt r5d, r5d + movd m5, r5d + LEA r5, ipred_dc_16bpc_ssse3_table + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pxor m3, m3 + psrlw m4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movq m0, [tlq-8] + jmp wq +.w4: + movq m1, [tlq+2] + paddw m1, m0 + punpckhwd m0, m3 + punpcklwd m1, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 + jmp .w4_end +.w4_mul: + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 16 + cmove r2d, r3d + psrld m0, 2 + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w4_end: + pshuflw m0, m0, q0000 +.s4: + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movq [dstq+strideq*2], m0 + movq [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +.h8: + mova m0, [tlq-16] + jmp wq +.w8: + movu m1, [tlq+2] + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 8 + je .w8_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 32 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +.h16: + mova m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w16: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + paddw m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 16 + je .w16_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + test hd, 8|32 + cmovz r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16c: + mova m1, m0 +.s16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*2+16*0], m0 + mova [dstq+strideq*2+16*1], m1 + mova [dstq+stride3q +16*0], m0 + mova [dstq+stride3q +16*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-48] + paddw m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w32: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + movu m2, [tlq+34] + paddw m0, m2 + movu m2, [tlq+50] + paddw m1, m2 + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 32 + je .w32_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 8 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32c: + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s32: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + mova [dstq+strideq*0+16*2], m2 + mova [dstq+strideq*0+16*3], m3 + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*3], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s32 + RET +.h64: + mova m0, [tlq-128] + mova m1, [tlq-112] + paddw m0, [tlq- 96] + paddw m1, [tlq- 80] + paddw m0, [tlq- 64] + paddw m1, [tlq- 48] + paddw m0, [tlq- 32] + paddw m1, [tlq- 16] + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 2] + movu m2, [tlq+ 18] + paddw m1, m2 + movu m2, [tlq+ 34] + paddw m0, m2 + movu m2, [tlq+ 50] + paddw m1, m2 + movu m2, [tlq+ 66] + paddw m0, m2 + movu m2, [tlq+ 82] + paddw m1, m2 + movu m2, [tlq+ 98] + paddw m0, m2 + movu m2, [tlq+114] + paddw m1, m2 + paddw m0, m1 + punpcklwd m1, m0, m3 + punpckhwd m0, m3 + paddd m0, m1 + paddd m4, m0 + punpckhqdq m0, m0 + paddd m0, m4 + pshuflw m1, m0, q1032 + paddd m0, m1 + psrld m0, m5 + cmp hd, 64 + je .w64_end + mov r2d, 0xAAAB + mov r3d, 0x6667 + cmp hd, 16 + cmove r2d, r3d + movd m1, r2d + pmulhuw m0, m1 + psrlw m0, 1 +.w64_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m0 + mova [dstq+16*2], m0 + mova [dstq+16*3], m0 + mova [dstq+16*4], m0 + mova [dstq+16*5], m0 + mova [dstq+16*6], m0 + mova [dstq+16*7], m0 + add dstq, strideq + dec hd + jg .s64 + RET + +cglobal ipred_dc_128_16bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + mov r6d, r8m + LEA r5, ipred_dc_128_16bpc_ssse3_table + tzcnt wd, wm + shr r6d, 11 + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m0, [r5-ipred_dc_128_16bpc_ssse3_table+pw_512+r6*8] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_16bpc, 4, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_16bpc_ssse3_table + movifnidn hd, hm + movu m0, [tlq+ 2] + movu m1, [tlq+ 18] + movu m2, [tlq+ 34] + movu m3, [tlq+ 50] + cmp wd, 64 + je .w64 + tzcnt wd, wd + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w64: + WIN64_SPILL_XMM 8 + movu m4, [tlq+ 66] + movu m5, [tlq+ 82] + movu m6, [tlq+ 98] + movu m7, [tlq+114] +.w64_loop: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + mova [dstq+16*4], m4 + mova [dstq+16*5], m5 + mova [dstq+16*6], m6 + mova [dstq+16*7], m7 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_h_16bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 +%define base r5-ipred_h_16bpc_ssse3_table + tzcnt wd, wm + LEA r5, ipred_h_16bpc_ssse3_table + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m2, [base+pw_256] + movddup m3, [base+pb_2_3] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + sub tlq, 8 + movq m3, [tlq] + pshuflw m0, m3, q3333 + pshuflw m1, m3, q2222 + pshuflw m2, m3, q1111 + pshuflw m3, m3, q0000 + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m1 + movq [dstq+strideq*2], m2 + movq [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + sub tlq, 8 + movq m3, [tlq] + punpcklwd m3, m3 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + sub tlq, 4 + movd m1, [tlq] + pshufb m0, m1, m3 + pshufb m1, m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m0 + mova [dstq+strideq*1+16*0], m1 + mova [dstq+strideq*1+16*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16 + RET +.w32: + sub tlq, 4 + movd m1, [tlq] + pshufb m0, m1, m3 + pshufb m1, m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m0 + mova [dstq+strideq*0+16*2], m0 + mova [dstq+strideq*0+16*3], m0 + mova [dstq+strideq*1+16*0], m1 + mova [dstq+strideq*1+16*1], m1 + mova [dstq+strideq*1+16*2], m1 + mova [dstq+strideq*1+16*3], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +.w64: + sub tlq, 2 + movd m0, [tlq] + pshufb m0, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m0 + mova [dstq+16*2], m0 + mova [dstq+16*3], m0 + mova [dstq+16*4], m0 + mova [dstq+16*5], m0 + mova [dstq+16*6], m0 + mova [dstq+16*7], m0 + add dstq, strideq + dec hd + jg .w64 + RET + +cglobal ipred_paeth_16bpc, 4, 6, 8, dst, stride, tl, w, h, left +%define base r5-ipred_paeth_16bpc_ssse3_table + movifnidn hd, hm + pshuflw m4, [tlq], q0000 + mov leftq, tlq + add hd, hd + punpcklqdq m4, m4 ; topleft + sub leftq, hq + and wd, ~7 + jnz .w8 + movddup m5, [tlq+2] ; top + psubw m6, m5, m4 + pabsw m7, m6 +.w4_loop: + movd m1, [leftq+hq-4] + punpcklwd m1, m1 + punpckldq m1, m1 ; left +%macro PAETH 0 + paddw m0, m6, m1 + psubw m2, m4, m0 ; tldiff + psubw m0, m5 ; tdiff + pabsw m2, m2 + pabsw m0, m0 + pminsw m2, m0 + pcmpeqw m0, m2 + pand m3, m5, m0 + pandn m0, m4 + por m0, m3 + pcmpgtw m3, m7, m2 + pand m0, m3 + pandn m3, m1 + por m0, m3 +%endmacro + PAETH + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2*2 + jg .w4_loop + RET +.w8: +%if ARCH_X86_32 + PUSH r6 + %define r7d hm + %assign regs_used 7 +%elif WIN64 + movaps r4m, m8 + PUSH r7 + %assign regs_used 8 +%endif +%if ARCH_X86_64 + movddup m8, [pw_256] +%endif + lea tlq, [tlq+wq*2+2] + neg wq + mov r7d, hd +.w8_loop0: + movu m5, [tlq+wq*2] + mov r6, dstq + add dstq, 16 + psubw m6, m5, m4 + pabsw m7, m6 +.w8_loop: + movd m1, [leftq+hq-2] +%if ARCH_X86_64 + pshufb m1, m8 +%else + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 +%endif + PAETH + mova [r6], m0 + add r6, strideq + sub hd, 1*2 + jg .w8_loop + mov hd, r7d + add wq, 8 + jl .w8_loop0 +%if WIN64 + movaps m8, r4m +%endif + RET + +%if ARCH_X86_64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 4 +%endif + +cglobal ipred_smooth_v_16bpc, 4, 6, 6, dst, stride, tl, w, h, weights + LEA weightsq, smooth_weights_1d_16bpc + mov hd, hm + lea weightsq, [weightsq+hq*4] + neg hq + movd m5, [tlq+hq*2] ; bottom + pshuflw m5, m5, q0000 + punpcklqdq m5, m5 + cmp wd, 4 + jne .w8 + movddup m4, [tlq+2] ; top + lea r3, [strideq*3] + psubw m4, m5 ; top - bottom +.w4_loop: + movq m1, [weightsq+hq*2] + punpcklwd m1, m1 + pshufd m0, m1, q1100 + punpckhdq m1, m1 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop + RET +.w8: +%if ARCH_X86_32 + PUSH r6 + %assign regs_used 7 + mov hm, hq + %define hq hm +%elif WIN64 + PUSH r7 + %assign regs_used 8 +%endif +.w8_loop0: + mov t0, hq + movu m4, [tlq+2] + add tlq, 16 + mov r6, dstq + add dstq, 16 + psubw m4, m5 +.w8_loop: + movq m3, [weightsq+t0*2] + punpcklwd m3, m3 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [r6+strideq*0], m0 + mova [r6+strideq*1], m1 + lea r6, [r6+strideq*2] + mova [r6+strideq*0], m2 + mova [r6+strideq*1], m3 + lea r6, [r6+strideq*2] + add t0, 4 + jl .w8_loop + sub wd, 8 + jg .w8_loop0 + RET + +cglobal ipred_smooth_h_16bpc, 3, 6, 6, dst, stride, tl, w, h, weights + LEA weightsq, smooth_weights_1d_16bpc + mov wd, wm + movifnidn hd, hm + movd m5, [tlq+wq*2] ; right + sub tlq, 8 + add hd, hd + pshuflw m5, m5, q0000 + sub tlq, hq + punpcklqdq m5, m5 + cmp wd, 4 + jne .w8 + movddup m4, [weightsq+4*2] + lea r3, [strideq*3] +.w4_loop: + movq m1, [tlq+hq] ; left + punpcklwd m1, m1 + psubw m1, m5 ; left - right + pshufd m0, m1, q3322 + punpckldq m1, m1 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + paddw m0, m5 + paddw m1, m5 + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movhps [dstq+strideq*2], m1 + movq [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4*2 + jg .w4_loop + RET +.w8: + lea weightsq, [weightsq+wq*4] + neg wq +%if ARCH_X86_32 + PUSH r6 + %assign regs_used 7 + %define hd hm +%elif WIN64 + PUSH r7 + %assign regs_used 8 +%endif +.w8_loop0: + mov t0d, hd + mova m4, [weightsq+wq*2] + mov r6, dstq + add dstq, 16 +.w8_loop: + movq m3, [tlq+t0*(1+ARCH_X86_32)] + punpcklwd m3, m3 + psubw m3, m5 + pshufd m0, m3, q3333 + pshufd m1, m3, q2222 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + REPX {paddw x, m5}, m0, m1, m2, m3 + mova [r6+strideq*0], m0 + mova [r6+strideq*1], m1 + lea r6, [r6+strideq*2] + mova [r6+strideq*0], m2 + mova [r6+strideq*1], m3 + lea r6, [r6+strideq*2] + sub t0d, 4*(1+ARCH_X86_64) + jg .w8_loop + add wq, 8 + jl .w8_loop0 + RET + +%if ARCH_X86_64 +DECLARE_REG_TMP 10 +%else +DECLARE_REG_TMP 3 +%endif + +cglobal ipred_smooth_16bpc, 3, 7, 8, dst, stride, tl, w, h, \ + h_weights, v_weights, top + LEA h_weightsq, smooth_weights_2d_16bpc + mov wd, wm + mov hd, hm + movd m7, [tlq+wq*2] ; right + lea v_weightsq, [h_weightsq+hq*8] + neg hq + movd m6, [tlq+hq*2] ; bottom + pshuflw m7, m7, q0000 + pshuflw m6, m6, q0000 + cmp wd, 4 + jne .w8 + movq m4, [tlq+2] ; top + mova m5, [h_weightsq+4*4] + punpcklwd m4, m6 ; top, bottom + pxor m6, m6 +.w4_loop: + movq m1, [v_weightsq+hq*4] + sub tlq, 4 + movd m3, [tlq] ; left + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + pmaddwd m0, m4 + punpcklwd m3, m7 ; left, right + pmaddwd m1, m4 + pshufd m2, m3, q1111 + pshufd m3, m3, q0000 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pavgw m0, m6 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w4_loop + RET +.w8: +%if ARCH_X86_32 + lea h_weightsq, [h_weightsq+wq*4] + mov t0, tlq + mov r1m, tlq + mov r2m, hq + %define m8 [h_weightsq+16*0] + %define m9 [h_weightsq+16*1] +%else +%if WIN64 + movaps r4m, m8 + movaps r6m, m9 + PUSH r7 + PUSH r8 +%endif + PUSH r9 + PUSH r10 + %assign regs_used 11 + lea h_weightsq, [h_weightsq+wq*8] + lea topq, [tlq+wq*2] + neg wq + mov r8, tlq + mov r9, hq +%endif + punpcklqdq m6, m6 +.w8_loop0: +%if ARCH_X86_32 + movu m5, [t0+2] + add t0, 16 + mov r0m, t0 +%else + movu m5, [topq+wq*2+2] + mova m8, [h_weightsq+wq*4+16*0] + mova m9, [h_weightsq+wq*4+16*1] +%endif + mov t0, dstq + add dstq, 16 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 +.w8_loop: + movd m1, [v_weightsq+hq*4] + sub tlq, 2 + movd m3, [tlq] ; left + pshufd m1, m1, q0000 + pmaddwd m0, m4, m1 + pshuflw m3, m3, q0000 + pmaddwd m1, m5 + punpcklwd m3, m7 ; left, right + pmaddwd m2, m8, m3 + pmaddwd m3, m9 + paddd m0, m2 + paddd m1, m3 + psrld m0, 8 + psrld m1, 8 + packssdw m0, m1 + pxor m1, m1 + pavgw m0, m1 + mova [t0], m0 + add t0, strideq + inc hq + jl .w8_loop +%if ARCH_X86_32 + mov t0, r0m + mov tlq, r1m + add h_weightsq, 16*2 + mov hq, r2m + sub dword wm, 8 + jg .w8_loop0 +%else + mov tlq, r8 + mov hq, r9 + add wq, 8 + jl .w8_loop0 +%endif +%if WIN64 + movaps m8, r4m + movaps m9, r6m +%endif + RET + +%if ARCH_X86_64 +cglobal ipred_z1_16bpc, 3, 8, 8, 16*18, dst, stride, tl, w, h, angle, dx + %define base r7-$$ + %define bdmaxm r8m + lea r7, [$$] +%else +cglobal ipred_z1_16bpc, 3, 7, 8, -16*18, dst, stride, tl, w, h, angle, dx + %define base r1-$$ + %define stridemp [rsp+4*0] + %define bdmaxm [rsp+4*1] + mov r3, r8m + mov stridemp, r1 + mov bdmaxm, r3 + LEA r1, $$ +%endif + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + add tlq, 2 + movsxd wq, [base+ipred_z1_16bpc_ssse3_table+wq*4] + mov dxd, angled + movddup m0, [base+pw_256] + and dxd, 0x7e + movddup m7, [base+pw_62] + add angled, 165 ; ~90 + lea wq, [base+wq+ipred_z1_16bpc_ssse3_table] + movzx dxd, word [base+dr_intra_derivative+dxq] + xor angled, 0x4ff ; d = 90 - angle + jmp wq +.w4: + lea r3d, [angleq+88] + test r3d, 0x480 + jnz .w4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r3d, 9 + add r3d, hd + cmp r3d, 8 + jg .w4_no_upsample ; h > 8 || (w == h && is_sm) + movd m3, [tlq+14] + movu m2, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + movd m1, bdmaxm + pshufb m3, m0 + palignr m4, m3, m2, 4 ; 3 4 5 6 7 8 8 8 + paddw m4, [tlq- 2] ; 0 1 2 3 4 5 6 7 + add dxd, dxd + mova [rsp+32], m3 + palignr m3, m2, 2 ; 2 3 4 5 6 7 8 8 + pshufb m1, m0 + paddw m3, m2 ; -1 * a + 9 * b + 9 * c + -1 * d + psubw m5, m3, m4 ; = (b + c - a - d + (b + c) << 3 + 8) >> 4 + movd m4, dxd + psraw m5, 3 ; = ((b + c - a - d) >> 3 + b + c + 1) >> 1 + paddw m3, m5 + pxor m5, m5 + pmaxsw m3, m5 + mov r3d, dxd + pavgw m3, m5 + pshufb m4, m0 + pminsw m3, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + mova m3, [base+z_upsample] + movifnidn strideq, stridemp + mova [rsp+ 0], m1 + paddw m5, m4, m4 + mova [rsp+16], m2 + punpcklqdq m4, m5 ; xpos0 xpos1 +.w4_upsample_loop: + lea r2d, [r3+dxq] + shr r3d, 6 ; base0 + movu m1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base1 + movu m2, [rsp+r2*2] + pshufb m1, m3 + pshufb m2, m3 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m7, m4 ; frac + psllw m2, 9 ; (a * (64 - frac) + b * frac + 32) >> 6 + psubw m1, m0 ; = a + (((b - a) * frac + 32) >> 6) + pmulhrsw m1, m2 ; = a + (((b - a) * (frac << 9) + 16384) >> 15) + paddw m4, m5 ; xpos += dx + paddw m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_upsample_loop + RET +.w4_no_upsample: + mov r3d, 7 ; max_base + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea r3d, [hq+3] + movd m1, r3d + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + pcmpeqb m1, [base+z_filt_wh4] + pand m1, m3 + pcmpgtb m1, [base+z_filt_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r3d, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x55555555 + movd m3, [tlq+r3*2] + shr r5d, 30 ; filter_strength + movd [rsp+12], m1 + pshuflw m3, m3, q0000 + mova [rsp+16*1], m2 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m3 + cmp hd, 8 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w4_main: + lea tlq, [tlq+r3*2] + movd m4, dxd + movddup m1, [base+z_base_inc] ; base_inc << 6 + movd m6, [tlq] ; top[max_base_x] + shl r3d, 6 + movd m3, r3d + pshufb m4, m0 + mov r5d, dxd ; xpos + pshufb m6, m0 + sub r5, r3 + pshufb m3, m0 + paddw m5, m4, m4 + psubw m3, m1 ; max_base_x + punpcklqdq m4, m5 ; xpos0 xpos1 + movifnidn strideq, stridemp +.w4_loop: + lea r3, [r5+dxq] + sar r5, 6 ; base0 + movq m0, [tlq+r5*2+0] + movq m1, [tlq+r5*2+2] + lea r5, [r3+dxq] + sar r3, 6 ; base1 + movhps m0, [tlq+r3*2+0] + movhps m1, [tlq+r3*2+2] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 ; xpos < max_base_x + paddw m4, m5 ; xpos += dx + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jz .w4_end + lea dstq, [dstq+strideq*2] + test r5d, r5d + jl .w4_loop +.w4_end_loop: + movq [dstq+strideq*0], m6 + movq [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_end_loop +.w4_end: + RET +.w8: + lea r3d, [angleq+88] + and r3d, ~0x7f + or r3d, hd + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + movu m1, [tlq+ 0] ; 1 2 3 4 5 6 7 8 + movu m5, [tlq+ 2] ; 2 3 4 5 6 7 8 9 + movu m3, [tlq+ 4] ; 3 4 5 6 7 8 9 a + paddw m5, m1 + paddw m3, [tlq- 2] ; 0 1 2 3 4 5 6 7 + psubw m2, m5, m3 + movu m6, [tlq+18] ; a b c d e f g _ + psraw m2, 3 + movu m3, [tlq+20] ; b c d e f g _ _ + paddw m5, m2 + movu m2, [tlq+16] ; 9 a b c d e f g + paddw m6, m2 + add dxd, dxd + cmp hd, 4 + jne .w8_upsample_h8 ; awkward single-pixel edge case + pshuflw m3, m3, q1110 ; b c c _ _ _ _ _ +.w8_upsample_h8: + paddw m3, [tlq+14] ; 8 9 a b c d e f + psubw m4, m6, m3 + movd m3, bdmaxm + psraw m4, 3 + mov r3d, dxd + paddw m6, m4 + pxor m4, m4 + pmaxsw m5, m4 + pmaxsw m6, m4 + pshufb m3, m0 + pavgw m5, m4 + pavgw m6, m4 + movd m4, dxd + pminsw m5, m3 + pminsw m6, m3 + mova m3, [base+z_upsample] + pshufb m4, m0 + movifnidn strideq, stridemp + punpcklwd m0, m1, m5 + mova [rsp+ 0], m0 + punpckhwd m1, m5 + mova [rsp+16], m1 + punpcklwd m0, m2, m6 + mova [rsp+32], m0 + punpckhwd m2, m6 + mova [rsp+48], m2 + mova m5, m4 +.w8_upsample_loop: + mov r2d, r3d + shr r2d, 6 + movu m1, [rsp+r2*2+ 0] + movu m2, [rsp+r2*2+16] + add r3d, dxd + pshufb m1, m3 + pshufb m2, m3 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w8_upsample_loop + RET +.w8_no_upsample: + lea r3d, [hq+7] + movd m1, r3d + and r3d, 7 + or r3d, 8 ; imin(h+7, 15) + test angled, 0x400 + jnz .w8_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movu m2, [base+z_filt_wh8] + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pcmpeqb m2, m1 + pand m2, m3 + pcmpgtb m2, m4 + pmovmskb r5d, m2 + test r5d, r5d + jz .w8_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x55555555 + movu m3, [tlq+16*1] + movd m4, [tlq+r3*2] + shr r5d, 30 ; filter_strength + movd [rsp+12], m1 + mova [rsp+16*1], m2 + pshuflw m4, m4, q0000 + mova [rsp+16*2], m3 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m4 + cmp hd, 16 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w8_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 + movifnidn strideq, stridemp +.w8_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+0] + movu m1, [tlq+r3*2+2] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + psraw m2, m4, 15 ; xpos < max_base_x + paddw m4, m5 ; xpos += dx + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [dstq], m0 + dec hd + jz .w8_end + add dstq, strideq + add r5, dxq + jl .w8_loop +.w8_end_loop: + mova [dstq], m6 + add dstq, strideq + dec hd + jg .w8_end_loop +.w8_end: + RET +.w16: +%if ARCH_X86_32 + %define strideq r3 +%endif + lea r3d, [hq+15] + movd m1, r3d + and r3d, 15 + or r3d, 16 ; imin(h+15, 31) + test angled, 0x400 + jnz .w16_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m1, [base+z_filt_wh16] + pand m1, m3 + pcmpgtb m1, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w16_main ; filter_strength == 0 + pshuflw m1, [tlq-2], q0000 + movu m2, [tlq+16*0] + imul r5d, 0x24924924 + movu m3, [tlq+16*1] + movu m4, [tlq+16*2] + shr r5d, 30 + movu m5, [tlq+16*3] + movd m6, [tlq+r3*2] + adc r5d, -1 ; filter_strength + movd [rsp+12], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + pshuflw m6, m6, q0000 + mova [rsp+16*3], m4 + mova [rsp+16*4], m5 + lea r2d, [r3+2] + movq [rsp+r3*2+18], m6 + cmp hd, 32 + cmovae r3d, r2d + lea tlq, [rsp+16*1] + call .filter_edge +.w16_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w16_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + movddup m3, [base+pw_m512] + paddw m1, m2 + psraw m2, m4, 15 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*0], m0 + por m1, m3 + mova [dstq+16*1], m1 + dec hd + jz .w16_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w16_loop +.w16_end_loop: + mova [dstq+16*0], m6 + mova [dstq+16*1], m6 + add dstq, strideq + dec hd + jg .w16_end_loop +.w16_end: + RET +.w32: + lea r3d, [hq+31] + and r3d, 31 + or r3d, 32 ; imin(h+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + call .filter_copy + lea r5d, [r3+2] + cmp hd, 64 + cmove r3d, r5d + call .filter_edge_s3 +.w32_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w32_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + psraw m2, m4, 15 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m512] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*0], m0 + por m1, m2 + mova [dstq+16*1], m1 + movu m0, [tlq+r3*2+32] + movu m2, [tlq+r3*2+34] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+48] + paddw m0, m2 + movu m2, [tlq+r3*2+50] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m1024] + movddup m3, [base+pw_m1536] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*2], m0 + por m1, m3 + mova [dstq+16*3], m1 + dec hd + jz .w32_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w32_loop +.w32_end_loop: + REPX {mova [dstq+16*x], m6}, 0, 1, 2, 3 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + lea r3d, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + call .filter_copy + call .filter_edge_s3 +.w64_main: + lea tlq, [tlq+r3*2] + movd m5, dxd + mova m4, [base+z_base_inc] + shl r3d, 6 + movd m6, [tlq] ; top[max_base_x] + movd m1, r3d + pshufb m5, m0 + mov r5d, dxd ; xpos + pshufb m1, m0 + sub r5, r3 + psubw m4, m1 ; max_base_x + pshufb m6, m0 + paddw m4, m5 +.w64_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3*2+ 0] + movu m2, [tlq+r3*2+ 2] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+16] + paddw m0, m2 + movu m2, [tlq+r3*2+18] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + psraw m2, m4, 15 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m512] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*0], m0 + por m1, m2 + mova [dstq+16*1], m1 + movu m0, [tlq+r3*2+32] + movu m2, [tlq+r3*2+34] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+48] + paddw m0, m2 + movu m2, [tlq+r3*2+50] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m1024] + pcmpgtw m2, m4 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m1536] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*2], m0 + por m1, m2 + mova [dstq+16*3], m1 + movu m0, [tlq+r3*2+64] + movu m2, [tlq+r3*2+66] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+80] + paddw m0, m2 + movu m2, [tlq+r3*2+82] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m2048] + pcmpgtw m2, m4 + pand m0, m2 + pandn m2, m6 + por m0, m2 + movddup m2, [base+pw_m2560] + pcmpgtw m2, m4 + pand m1, m2 + pandn m2, m6 + mova [dstq+16*4], m0 + por m1, m2 + mova [dstq+16*5], m1 + movu m0, [tlq+r3*2+96] + movu m2, [tlq+r3*2+98] + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r3*2+112] + paddw m0, m2 + movu m2, [tlq+r3*2+114] + psubw m2, m1 + pmulhrsw m2, m3 + paddw m1, m2 + movddup m2, [base+pw_m3072] + movddup m3, [base+pw_m3584] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [dstq+16*6], m0 + por m1, m3 + mova [dstq+16*7], m1 + dec hd + jz .w64_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w64_loop +.w64_end_loop: + REPX {mova [dstq+16*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET +ALIGN function_align +.filter_copy: + pshuflw m2, [tlq-2], q0000 + pshuflw m3, [tlq+r3*2], q0000 + xor r5d, r5d + movd [rsp+gprsize+12], m2 +.filter_copy_loop: + movu m1, [tlq+r5*2+16*0] + movu m2, [tlq+r5*2+16*1] + add r5d, 16 + mova [rsp+r5*2+gprsize-16*1], m1 + mova [rsp+r5*2+gprsize-16*0], m2 + cmp r5d, r3d + jle .filter_copy_loop + lea tlq, [rsp+gprsize+16*1] + movq [tlq+r3*2+2], m3 + ret +.filter_edge: + cmp r5d, 3 + je .filter_edge_s3 + movddup m4, [base+z_filt_k+r5*8-8] + movddup m5, [base+z_filt_k+r5*8+8] + xor r5d, r5d + movddup m6, [base+pw_8] + movu m2, [tlq-2] + jmp .filter_edge_start +.filter_edge_loop: + movu m2, [tlq+r5*2-2] + mova [tlq+r5*2-16], m1 +.filter_edge_start: + pmullw m1, m4, [tlq+r5*2] + movu m3, [tlq+r5*2+2] + paddw m2, m3 + pmullw m2, m5 + add r5d, 8 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 4 + cmp r5d, r3d + jl .filter_edge_loop + mova [tlq+r5*2-16], m1 + ret +.filter_edge_s3: + movddup m5, [base+pw_3] + xor r5d, r5d + movu m2, [tlq-2] + movu m3, [tlq-4] + jmp .filter_edge_s3_start +.filter_edge_s3_loop: + movu m2, [tlq+r5*2-2] + movu m3, [tlq+r5*2-4] + mova [tlq+r5*2-16], m1 +.filter_edge_s3_start: + paddw m2, [tlq+r5*2+0] + paddw m3, m5 + movu m1, [tlq+r5*2+2] + movu m4, [tlq+r5*2+4] + add r5d, 8 + paddw m1, m2 + pavgw m3, m4 + paddw m1, m3 + psrlw m1, 2 + cmp r5d, r3d + jl .filter_edge_s3_loop + mova [tlq+r5*2-16], m1 + ret + +%if ARCH_X86_64 +cglobal ipred_z2_16bpc, 4, 12, 11, 16*24, dst, stride, tl, w, h, angle, dx, _, dy + %define base r7-$$ + %define maxwm r6m + %define maxhm r7m + %define bdmaxm r8m + lea r7, [$$] + mov hd, hm + movddup m8, [base+pw_62] + lea r9d, [wq-4] + shl r9d, 6 + mova m9, [base+z2_top_shufA] + or r9d, hd + mova m10, [base+z2_left_shufA] +%else +cglobal ipred_z2_16bpc, 4, 7, 8, -16*27, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define r9b byte [rsp+16*26+4*0] + %define r9d dword [rsp+16*26+4*0] + %define r10d dword [rsp+16*26+4*1] + %define r11d dword [rsp+16*26+4*2] + %define maxwm [rsp+16*2+4*0] + %define maxhm [rsp+16*2+4*1] + %define bdmaxm [rsp+16*2+4*2] + %define stridemp [rsp+16*26+4*3] + %define strideq r3 + %define dyd r4 + %define dyq r4 + mov stridemp, r1 + mov r1d, r6m + mov r4d, r7m + mov r5d, r8m + mov maxwm, r1d + mov maxhm, r4d + mov bdmaxm, r5d + LEA r1, $$ + lea hd, [wq-4] + mova m0, [base+z2_top_shufA] + shl hd, 6 + mova m1, [base+z2_left_shufA] + or hd, hm + mova [rsp+16*24], m0 + mov r9d, hd + mova [rsp+16*25], m1 +%endif + tzcnt wd, wd + movifnidn angled, anglem + mova m0, [tlq-16*8] + mova m1, [tlq-16*7] + mova m2, [tlq-16*6] + mova m3, [tlq-16*5] + movsxd wq, [base+ipred_z2_16bpc_ssse3_table+wq*4] +%if ARCH_X86_64 + movzx dxd, angleb +%else + movzx dxd, byte anglem +%endif + mova m4, [tlq-16*4] + mova m5, [tlq-16*3] + mova m6, [tlq-16*2] + mova m7, [tlq-16*1] + mova [rsp+16* 5], m0 + xor angled, 0x400 + mova [rsp+16* 6], m1 + mov dyd, dxd + mova [rsp+16* 7], m2 + neg dxq + mova [rsp+16* 8], m3 + and dyd, ~1 + mova [rsp+16* 9], m4 + and dxq, ~1 + mova [rsp+16*10], m5 + lea wq, [base+ipred_z2_16bpc_ssse3_table+wq] + mova [rsp+16*11], m6 + pxor m3, m3 + mova [rsp+16*12], m7 + movzx dyd, word [base+dr_intra_derivative+dyq-90] ; angle - 90 + movzx dxd, word [base+dr_intra_derivative+dxq+180] ; 180 - angle + movddup m0, [base+pw_256] ; 4<<6 + movd m4, [tlq] + movu m5, [tlq+16*0+2] + movu m6, [tlq+16*1+2] + movsldup m1, [base+z2_dy_offset] + pshufb m4, m0 + movq m7, [base+z_base_inc+2] + mov r11d, (112-4)<<6 + mova [rsp+16*13], m4 + neg dxd + mova [rsp+16*14], m5 + or dyd, 4<<16 + mova [rsp+16*15], m6 +%if ARCH_X86_64 + lea r10d, [dxq+(112<<6)] ; xpos +%else + mov [rsp+8*3], dyd + lea r4d, [dxq+(112<<6)] + mov r10d, r4d + movzx hd, r9b +%endif + movq [rsp+8*0], m1 + movq [rsp+8*1], m0 + movq [rsp+8*2], m7 + jmp wq +.w4: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+2] + add angled, 1022 + pshuflw m1, m5, q3333 + shl r3d, 6 + movq [rsp+16*14+8], m1 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + movd m2, r3d + movd m7, angled + shr angled, 8 ; is_sm << 1 + pshufb m2, m3 + pshufb m7, m3 + pcmpeqb m2, [base+z_filt_wh4] + pand m7, m2 + pcmpgtb m7, [base+z_filt_t_w48+angleq*8] + jmp .w8_filter_left +.upsample_above: ; w4/w8 + paddw m2, m5, [tlq] + movu m1, [rsp+gprsize+16*14+2] + movu m4, [rsp+gprsize+16*14-4] +%if ARCH_X86_64 + movd m6, r9m ; bdmax, offset due to call +%else + movd m6, [rsp+gprsize+16*2+4*2] +%endif + paddw m4, m1 + psubw m1, m2, m4 + pshufb m6, m0 + psraw m1, 3 + paddw m2, m1 + add dxd, dxd + pmaxsw m2, m3 + paddw m7, m7 + pavgw m2, m3 + pminsw m2, m6 +%if ARCH_X86_64 + mova m9, [base+z2_top_shufB] + lea r10d, [dxq+(113<<6)] + mov r11d, (112-7)<<6 +%else + mova m1, [base+z2_top_shufB] + lea r3d, [dxq+(113<<6)] + mov dword [rsp+gprsize+16*26+4*2], (112-7)<<6 + mov [rsp+gprsize+16*26+4*1], r3d + mova [rsp+gprsize+16*24], m1 +%endif + punpcklwd m1, m2, m5 + punpckhwd m2, m5 + movq [rsp+gprsize+8*2], m7 + mova [rsp+gprsize+16*14], m1 + mova [rsp+gprsize+16*15], m2 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + mov [rsp+16*4], angled + sub angled, 1112 ; angle - 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + mova m4, [base+z_filt_wh4] + movd m7, r3d + mova m5, [base+z_filt_t_w48+angleq*8] + mov r3d, 4 + call .w8_filter_top + mov angled, [rsp+16*4] + lea r3d, [hq+2] + sub angled, 139 + shl r3d, 6 + test r3d, angled + jnz .w8_filter_left ; angle <= 140 || h > 8 || (is_sm && h == 8) +.upsample_left: ; w4/w8 + mova m2, [tlq-16] + lea r3d, [hq-4] + movu m3, [tlq-14] + movu m4, [rsp+16*12+4] + pshufb m1, m2, [base+z2_upsample_l+r3*4] + movd m6, bdmaxm + pxor m5, m5 + paddw m3, m2 + paddw m4, m1 + psubw m1, m3, m4 + movshdup m4, [base+z2_dy_offset] + psraw m1, 3 + pshufb m6, m0 + paddw m3, m1 + pmaxsw m3, m5 + pavgw m3, m5 + pminsw m3, m6 +%if ARCH_X86_64 + mova m10, [base+z2_left_shufB] + add dyd, dyd +%else + mova m1, [base+z2_left_shufB] + shl dword [rsp+8*3], 1 + mova [rsp+16*25], m1 +%endif + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + movq [rsp+8*0], m4 + mova [rsp+16*12], m1 + mova [rsp+16*11], m2 +.w4_main: + movd m6, dxd +%if ARCH_X86_64 + movd m3, dyd +%else + movd m3, [rsp+8*3] +%endif + pshufb m6, m0 + movddup m0, [rsp+8*2] + paddw m7, m6, m6 + movq m5, [base+pw_m1to4] + pshuflw m4, m3, q0000 + punpcklqdq m6, m7 + pmullw m4, m5 + pshuflw m3, m3, q1111 + paddw m6, m0 + mov r2d, r10d + pshuflw m0, m4, q3333 + psubw m4, [rsp+8*0] + movq [rsp+8*3], m3 + movq [rsp+8*5], m0 ; dy*4 + mov r5, dstq +.w4_loop0: + mova [rsp+16*4], m6 + movq [rsp+8*4], m4 +%if ARCH_X86_64 + pand m0, m8, m4 +%else + movq m0, [base+pw_62] + pand m0, m4 +%endif + psraw m4, 6 + psllw m0, 9 ; frac_y << 9 + movq [rsp+8*7], m0 + pabsw m4, m4 + movq [rsp+8*6], m4 + movzx hd, r9b +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu m2, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu m1, [rsp+r3*2] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movu m3, [rsp+r2*2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movu m4, [rsp+r3*2] +%if ARCH_X86_64 + REPX {pshufb x, m9}, m2, m1, m3, m4 +%else + mova m0, [rsp+16*24] + REPX {pshufb x, m0}, m2, m1, m3, m4 +%endif + punpcklqdq m0, m2, m1 + punpckhqdq m2, m1 + punpcklqdq m1, m3, m4 + punpckhqdq m3, m4 +%if ARCH_X86_64 + pand m5, m8, m6 +%else + movddup m5, [base+pw_62] + pand m5, m6 +%endif + psllw m5, 9 + psubw m2, m0 + pmulhrsw m2, m5 + paddw m5, m6, m7 + psubw m3, m1 + paddw m0, m2 +%if ARCH_X86_64 + pand m2, m8, m5 +%else + movddup m2, [base+pw_62] + pand m2, m5 +%endif + psllw m2, 9 + pmulhrsw m3, m2 + paddw m1, m3 + cmp r3d, 111 ; topleft + jge .w4_toponly + mova [rsp+16*22], m0 + mova [rsp+16*23], m1 + movzx r3d, byte [rsp+8*6+0] ; base_y0 + movu m3, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+2] ; base_y1 + movu m2, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+4] ; base_y2 + movu m4, [rsp+r3*2] + movzx r3d, byte [rsp+8*6+6] ; base_y3 + movu m0, [rsp+r3*2] +%if ARCH_X86_64 + REPX {pshufb x, m10}, m3, m2, m4, m0 +%else + mova m1, [rsp+16*25] + REPX {pshufb x, m1}, m3, m2, m4, m0 +%endif + punpcklwd m1, m3, m2 + punpckhwd m3, m2 ; 01 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 ; 23 + punpckldq m0, m1, m2 ; y0 d1 + punpckhdq m1, m2 ; y2 y3 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + movddup m4, [rsp+8*7] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + psraw m6, 15 ; base_x < topleft + psraw m4, m5, 15 + paddw m0, m2 + paddw m1, m3 + pand m0, m6 + pandn m6, [rsp+16*22] + pand m1, m4 + pandn m4, [rsp+16*23] + por m0, m6 + por m1, m4 +.w4_toponly: + movifnidn strideq, stridemp + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jz .w4_end + movq m4, [rsp+8*6] + paddsw m6, m5, m7 ; xpos += dx + movq m5, [rsp+8*3] + psubw m4, m5 + lea dstq, [dstq+strideq*2] + movq [rsp+8*6], m4 + cmp r2d, r11d + jge .w4_loop +.w4_leftonly_loop: + movzx r2d, byte [rsp+8*6+0] ; base_y0 + movu m3, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+2] ; base_y1 + movu m2, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+4] ; base_y2 + movu m6, [rsp+r2*2] + movzx r2d, byte [rsp+8*6+6] ; base_y3 + movu m0, [rsp+r2*2] + psubw m4, m5 +%if ARCH_X86_64 + REPX {pshufb x, m10}, m3, m2, m6, m0 +%else + mova m1, [rsp+16*25] + REPX {pshufb x, m1}, m3, m2, m6, m0 +%endif + movq [rsp+8*6], m4 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m6, m0 + punpckhwd m6, m0 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m6 + punpckhdq m3, m6 + movddup m6, [rsp+8*7] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m6 + pmulhrsw m3, m6 + paddw m0, m2 + paddw m1, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + sub r9d, 1<<8 + jl .w4_ret + movq m4, [rsp+8*5] + add r5, 8 + mov dstq, r5 + paddw m4, [rsp+8*4] ; base_y += 4*dy + movzx r2d, word [rsp+8*1] + movddup m6, [rsp+8*1] + paddw m6, [rsp+16*4] ; base_x += (4 << upsample_above) + add r2d, r10d + mov r10d, r2d + jmp .w4_loop0 +.w4_ret: + RET +.w8: + test angled, 0x400 + jnz .w4_main + lea r3d, [angleq+126] + pshufhw m1, m5, q3333 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + movhps [rsp+16*15], m1 + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + call .upsample_above + sub angled, 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + movu m1, [base+z_filt_wh8] + movd m2, r3d + movd m7, angled + shr angled, 8 ; is_sm << 1 + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pshufb m2, m3 + pshufb m7, m3 + pcmpeqb m2, m1 + movq m1, [base+pw_512] + pand m7, m2 + pcmpgtb m7, m4 + movq [rsp+8*1], m1 ; 8<<6 + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + mov [rsp+16*4], angled + sub angled, 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m4, [base+z_filt_wh8] + movd m7, r3d + psrldq m5, [base+z_filt_t_w48+angleq*8], 4 + mov r3d, 8 + call .w8_filter_top + mov r3d, [rsp+16*4] + sub r3d, 141 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + cmp r3d, 8 + jbe .upsample_left ; angle > 140 && h <= 8 && !is_sm +.w8_filter_left: + pmovmskb r5d, m7 + test r5d, r5d + jz .w4_main + imul r5d, 0x55555555 + neg hq + mov r3, tlq + movd m1, [tlq+hq*2] + shr r5d, 30 ; filter_strength + lea tlq, [rsp+16*13-2] + pshuflw m1, m1, q0000 + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge + jmp .filter_left_end +.w8_filter_top: + REPX {pshufb x, m3}, m2, m1, m7 + pcmpeqb m2, m4 + pand m1, m2 + pand m7, m2 + pcmpgtb m1, m5 + pcmpgtb m7, m5 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_filter_top_end ; filter_strength == 0 + imul r5d, 0x55555555 + mov [dstq], tlq + lea tlq, [rsp+16*14+gprsize] + shr r5d, 30 ; filter_strength + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge +%if ARCH_X86_64 + mov r3d, r7m ; maxw, offset due to call +%else + mov r3d, [rsp+16*2+4*1] +%endif + mov tlq, [dstq] + cmp r3d, 8 + jge .w8_filter_top_end + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14+gprsize], m1 + movu [rsp+r3*2+16*15+gprsize], m2 +.w8_filter_top_end: + ret +.w16: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+15] + sub angled, 90 + movd m2, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movd m7, r3d + REPX {pshufb x, m3}, m2, m1, m7 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m2, [base+z_filt_wh16] + pand m1, m2 + pand m7, m2 + pcmpgtb m1, m4 + pcmpgtb m7, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w16_filter_left ; filter_strength == 0 + imul r5d, 0x24924924 + pshufhw m6, m6, q3333 + mov [dstq], tlq + lea tlq, [rsp+16*14] + shr r5d, 30 + movhps [tlq+16*2], m6 + adc r5d, -1 ; filter_strength + mov r3d, 16 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 16 + jge .w16_filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 +.w16_filter_left: + pmovmskb r5d, m7 + test r5d, r5d + jz .w4_main + imul r5d, 0x24924924 + neg hq + mov r3, tlq + movd m1, [tlq+hq*2] + shr r5d, 30 + lea tlq, [rsp+16*13-2] + pshuflw m1, m1, q0000 + adc r5d, -1 ; filter_strength + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge + jmp .filter_left_end +.w32: + movu m1, [tlq+16*2+2] + movu m2, [tlq+16*3+2] + mova [rsp+16*16], m1 + mova [rsp+16*17], m2 + test angled, 0x400 + jnz .w4_main + mov [dstq], tlq + lea tlq, [rsp+16*14] + pshufhw m2, m2, q3333 + mov r3d, 32 + movhps [tlq+16*4], m2 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge_s3 + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 32 + jge .filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 + cmp r3d, 16 + jge .filter_left + movu m1, [tlq+r3*2+16*2+2] + movu m2, [tlq+r3*2+16*3+2] + movu [rsp+r3*2+16*16], m1 + movu [rsp+r3*2+16*17], m2 +.filter_left: + neg hq + mov r3, tlq + pshuflw m1, [tlq+hq*2], q0000 + lea tlq, [rsp+16*13-2] + movq [tlq+hq*2-6], m1 + call mangle(private_prefix %+ _ipred_z3_16bpc_ssse3).filter_edge_s3 +.filter_left_end: + mov r2d, maxhm + cmp r2d, hd + jge .w4_main + neg r2 + movu m1, [r3+r2*2-16*1] + movu m2, [r3+r2*2-16*2] + movu [rsp+r2*2+16*12], m1 + movu [rsp+r2*2+16*11], m2 + cmp r2d, -48 + jle .w4_main + movu m1, [r3+r2*2-16*3] + movu m2, [r3+r2*2-16*4] + movu [rsp+r2*2+16*10], m1 + movu [rsp+r2*2+16* 9], m2 + cmp r2d, -32 + jle .w4_main + movu m1, [r3+r2*2-16*5] + movu m2, [r3+r2*2-16*6] + movu [rsp+r2*2+16* 8], m1 + movu [rsp+r2*2+16* 7], m2 + cmp r2d, -16 + jle .w4_main + movu m1, [r3+r2*2-16*7] + movu m2, [r3+r2*2-16*8] + movu [rsp+r2*2+16* 6], m1 + movu [rsp+r2*2+16* 5], m2 + jmp .w4_main +.w64: + movu m1, [tlq+16*2+2] + movu m2, [tlq+16*3+2] + movu m3, [tlq+16*4+2] + movu m4, [tlq+16*5+2] + movu m5, [tlq+16*6+2] + movu m6, [tlq+16*7+2] + mov [dstq], tlq + lea tlq, [rsp+16*14] + mova [tlq+16*2], m1 + mova [tlq+16*3], m2 + mova [tlq+16*4], m3 + mova [tlq+16*5], m4 + mova [tlq+16*6], m5 + mova [tlq+16*7], m6 + test angled, 0x400 + jnz .w4_main + pshufhw m6, m6, q3333 + mov r3d, 64 + movhps [tlq+16*8], m6 + call mangle(private_prefix %+ _ipred_z1_16bpc_ssse3).filter_edge_s3 + mov r3d, maxwm + mov tlq, [dstq] + cmp r3d, 64 + jge .filter_left + movu m1, [tlq+r3*2+16*0+2] + movu m2, [tlq+r3*2+16*1+2] + movu [rsp+r3*2+16*14], m1 + movu [rsp+r3*2+16*15], m2 + cmp r3d, 48 + jge .filter_left + movu m1, [tlq+r3*2+16*2+2] + movu m2, [tlq+r3*2+16*3+2] + movu [rsp+r3*2+16*16], m1 + movu [rsp+r3*2+16*17], m2 + cmp r3d, 32 + jge .filter_left + movu m1, [tlq+r3*2+16*4+2] + movu m2, [tlq+r3*2+16*5+2] + movu [rsp+r3*2+16*18], m1 + movu [rsp+r3*2+16*19], m2 + cmp r3d, 16 + jge .filter_left + movu m1, [tlq+r3*2+16*6+2] + movu m2, [tlq+r3*2+16*7+2] + movu [rsp+r3*2+16*20], m1 + movu [rsp+r3*2+16*21], m2 + jmp .filter_left + +%if ARCH_X86_64 +cglobal ipred_z3_16bpc, 4, 9, 8, 16*18, dst, stride, tl, w, h, angle, dy, _, org_w + %define base r7-$$ + lea r7, [$$] + mov org_wd, wd +%else +cglobal ipred_z3_16bpc, 4, 7, 8, -16*18, dst, stride, tl, w, h, angle, dy + %define base r1-$$ + %define org_wd r5 + %define org_wq r5 + movd m6, r8m ; pixel_max + mov [dstq+4*0], strideq + LEA r1, $$ + mov [dstq+4*1], wd +%endif + tzcnt hd, hm + movifnidn angled, anglem + sub tlq, 2 + movsxd hq, [base+ipred_z3_16bpc_ssse3_table+hq*4] + sub angled, 180 + movddup m0, [base+pw_256] + mov dyd, angled + neg dyd + xor angled, 0x400 + movddup m7, [base+pw_62] + or dyq, ~0x7e + lea hq, [base+ipred_z3_16bpc_ssse3_table+hq] + movzx dyd, word [base+dr_intra_derivative+45*2-1+dyq] + jmp hq +.h4: + lea r4d, [angleq+88] + test r4d, 0x480 + jnz .h4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r4d, 9 + add r4d, wd + cmp r4d, 8 + jg .h4_no_upsample ; w > 8 || (w == 8 && is_sm) + mova m2, [tlq-14] ; 7 6 5 4 3 2 1 0 + movu m3, [tlq-12] ; 8 7 6 5 4 3 2 1 +%if ARCH_X86_64 + movd m6, r8m +%endif + pshufb m4, m2, m0 + mov tlq, rsp + palignr m1, m2, m4, 14 ; 8 8 7 6 5 4 3 2 + add dyd, dyd + palignr m5, m2, m4, 12 ; 8 8 8 7 6 5 4 3 + paddw m1, m2 + paddw m3, m5 + psubw m5, m1, m3 + mova m3, [base+z_upsample] + mova [tlq+ 0], m4 + movd m4, dyd + psraw m5, 3 + neg dyd + paddw m1, m5 + pxor m5, m5 + lea r5d, [dyq+(16<<6)+63] ; ypos + pmaxsw m1, m5 + pshufb m6, m0 + shl wd, 3 + pavgw m1, m5 + pshufb m4, m0 + pminsw m1, m6 + sub rsp, wq + punpckhwd m0, m1, m2 + paddw m5, m4, m4 + punpcklwd m1, m2 + mova [tlq+32], m0 + movsd m4, m5 + mova [tlq+16], m1 +.h4_upsample_loop: + lea r4d, [r5+dyq] + sar r5d, 6 + movu m2, [tlq+r5*2] + lea r5d, [r4+dyq] + sar r4d, 6 + movu m1, [tlq+r4*2] + pshufb m2, m3 + pshufb m1, m3 + punpckhqdq m0, m1, m2 + punpcklqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jg .h4_upsample_loop + or r3d, 4*2 + jmp .end_transpose +.h4_no_upsample: + mov r4d, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea r4d, [wq+3] + movd m1, r4d + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + pcmpeqb m1, [base+z_filt_wh4] + pand m1, m3 + pcmpgtb m1, [base+z_filt_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r4d, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + imul r5d, 0x55555555 + mova m2, [tlq-14] + neg r4 + movd m3, [tlq+r4*2] + shr r5d, 30 + movd [rsp+16*17], m1 + pshuflw m3, m3, q0000 + mova [rsp+16*16], m2 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m3 + cmp wd, 8 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h4_main: + movd m4, dyd + sub tlq, r4 + movddup m1, [base+z_base_inc_z2+8] ; base_inc << 6 + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m4, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] ; ypos + pshufb m3, m0 + shl wd, 3 + paddw m5, m4, m4 + sub rsp, wq + psubw m3, m1 ; max_base_y + movsd m4, m5 ; ypos1 ypos0 +.h4_loop: + lea r4, [r5+dyq] + sar r5, 6 + movddup m0, [tlq+r5*2-6] + movddup m1, [tlq+r5*2-8] + lea r5, [r4+dyq] + sar r4, 6 + movlps m0, [tlq+r4*2-6] + movlps m1, [tlq+r4*2-8] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 + paddw m4, m5 + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [rsp+wq-16], m0 + sub wd, 16 + jz .h4_transpose + test r5d, r5d + jg .h4_loop +.h4_end_loop: + mova [rsp+wq-16], m6 + sub wd, 16 + jg .h4_end_loop +.h4_transpose: + or r3d, 4*2 + jmp .end_transpose +.h8: + lea r4d, [angleq+88] + and r4d, ~0x7f + or r4d, wd + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m2, [tlq-30] ; g f e d c b a 9 + movu m1, [tlq-32] ; _ g f e d c b a + movu m3, [tlq-16] ; 9 8 7 6 5 4 3 2 + paddw m3, [tlq-14] ; 8 7 6 5 4 3 2 1 + pshufd m4, m2, q2100 ; _ _ g f e d c b + paddw m1, m2 + movu m5, [tlq-28] ; f e d c b a 9 8 + add dyd, dyd + cmp wd, 8 + je .h8_upsample_w8 + pshufhw m4, m2, q1000 ; _ _ _ _ c c c b +.h8_upsample_w8: + paddw m4, m5 + psubw m5, m1, m4 + movu m4, [tlq-18] ; a 9 8 7 6 5 4 3 + psraw m5, 3 + paddw m1, m5 + movu m5, [tlq-12] ; 7 6 5 4 3 2 1 0 +%if ARCH_X86_64 + movd m6, r8m ; pixel_max +%endif + paddw m4, m5 + shl wd, 4 + psubw m5, m3, m4 + movd m4, dyd + psraw m5, 3 + neg dyd + paddw m3, m5 + pshufb m6, m0 + mova m5, [tlq-14] + pshufb m4, m0 + pxor m0, m0 + pmaxsw m1, m0 + pmaxsw m3, m0 + mov tlq, rsp + pavgw m1, m0 + pavgw m3, m0 + sub rsp, wq + pminsw m1, m6 + pminsw m6, m3 + mova m3, [base+z_upsample] + lea r5d, [dyq+(16<<6)+63] ; ypos + punpcklwd m0, m1, m2 + mova [tlq+16*0], m0 + punpckhwd m1, m2 + mova [tlq+16*1], m1 + punpcklwd m0, m6, m5 + mova [tlq+16*2], m0 + punpckhwd m6, m5 + mova [tlq+16*3], m6 + mova m5, m4 +.h8_upsample_loop: + mov r4d, r5d + sar r4d, 6 + movu m1, [tlq+r4*2+16*0] + movu m2, [tlq+r4*2+16*1] + add r5d, dyd + pshufb m2, m3 + pshufb m1, m3 + punpckhqdq m0, m1, m2 + punpcklqdq m1, m2 + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m4, m5 + paddw m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jg .h8_upsample_loop + or r3d, 8*2 + jmp .end_transpose +.h8_no_upsample: + lea r4d, [wq+7] + movd m1, r4d + and r4d, 7 + or r4d, 8 ; imin(w+7, 15) + test angled, 0x400 + jnz .h8_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movu m2, [base+z_filt_wh8] + psrldq m4, [base+z_filt_t_w48+angleq*8], 4 + pcmpeqb m2, m1 + pand m2, m3 + pcmpgtb m2, m4 + pmovmskb r5d, m2 + test r5d, r5d + jz .h8_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + imul r5d, 0x55555555 + mova m2, [tlq-16*1+2] + neg r4 + mova m3, [tlq-16*2+2] + shr r5d, 30 + movd m4, [tlq+r4*2] + movd [rsp+16*17], m1 + mova [rsp+16*16], m2 + pshuflw m4, m4, q0000 + mova [rsp+16*15], m3 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m4 + cmp wd, 16 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h8_main: + sub tlq, r4 + movd m4, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m4, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + shl wd, 4 + mova m5, m4 + sub rsp, wq + psubw m3, [base+z_base_inc_z2] +.h8_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m1, [tlq+r4*2-16] + pand m2, m7, m4 + psllw m2, 9 + psubw m1, m0 + pmulhrsw m1, m2 + pcmpgtw m2, m3, m4 + paddw m4, m5 + paddw m0, m1 + pand m0, m2 + pandn m2, m6 + por m0, m2 + mova [rsp+wq-16], m0 + sub wd, 8*2 + jz .h8_transpose + add r5, dyq + jg .h8_loop +.h8_end_loop: + mova [rsp+wq-16], m6 + sub wd, 8*2 + jg .h8_end_loop +.h8_transpose: + or r3d, 8*2 + jmp .end_transpose +.h16: + lea r4d, [wq+15] + movd m1, r4d + and r4d, 15 + or r4d, 16 ; imin(w+15, 31) + test angled, 0x400 + jnz .h16_main + movd m3, angled + shr angled, 8 ; is_sm << 1 + pxor m2, m2 + pshufb m1, m2 + pshufb m3, m2 + movq m4, [base+z_filt_t_w16+angleq*4] + pcmpeqb m1, [base+z_filt_wh16] + pand m1, m3 + pcmpgtb m1, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .h16_main ; filter_strength == 0 + pshuflw m1, [tlq+2], q0000 + mova m2, [tlq-16*1+2] + imul r5d, 0x24924924 + mova m3, [tlq-16*2+2] + neg r4 + mova m4, [tlq-16*3+2] + shr r5d, 30 + mova m5, [tlq-16*4+2] + movd m6, [tlq+r4*2] + adc r5d, -1 ; filter_strength + movd [rsp+16*17], m1 + mova [rsp+16*16], m2 + mova [rsp+16*15], m3 + pshuflw m6, m6, q0000 + mova [rsp+16*14], m4 + mova [rsp+16*13], m5 + lea r2, [r4-2] + movq [rsp+16*17+r4*2-10], m6 + cmp wd, 32 + cmovae r4, r2 + lea tlq, [rsp+16*17-2] + call .filter_edge +.h16_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + shl wd, 5 + paddw m4, m5, [base+z_base_inc_z2] + sub rsp, wq + psubw m4, m3 +.h16_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m2, [tlq+r4*2-16] + pand m3, m7, m4 + psllw m3, 9 + psubw m2, m0 + pmulhrsw m2, m3 + movu m1, [tlq+r4*2-30] + paddw m0, m2 + movu m2, [tlq+r4*2-32] + psubw m2, m1 + pmulhrsw m2, m3 + movddup m3, [base+pw_m512] + paddw m1, m2 + psraw m2, m4, 15 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+wq-16*1], m0 + por m1, m3 + mova [rsp+wq-16*2], m1 + sub wd, 16*2 + jz .h16_transpose + add r5, dyq + jg .h16_loop +.h16_end_loop: + mova [rsp+wq-16*1], m6 + mova [rsp+wq-16*2], m6 + sub wd, 16*2 + jg .h16_end_loop +.h16_transpose: + or r3d, 16*2 + jmp .end_transpose +.h32: + lea r4d, [wq+31] + and r4d, 31 + or r4d, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + call .filter_copy + lea r5, [r4-2] + cmp wd, 64 + cmove r4, r5 + call .filter_edge_s3 +.h32_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + paddw m4, m5, [base+z_base_inc_z2] + psubw m4, m3 +.h32_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2-14] + movu m3, [tlq+r4*2-16] + pand m2, m7, m4 + psllw m2, 9 + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-30] + paddw m0, m3 + movu m3, [tlq+r4*2-32] + psubw m3, m1 + pmulhrsw m3, m2 + sub rsp, 16*4 + paddw m1, m3 + psraw m3, m4, 15 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m512] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*3], m0 + por m1, m3 + mova [rsp+16*2], m1 + movu m0, [tlq+r4*2-46] + movu m3, [tlq+r4*2-48] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-62] + paddw m0, m3 + movu m3, [tlq+r4*2-64] + psubw m3, m1 + pmulhrsw m3, m2 + movddup m2, [base+pw_m1024] + paddw m1, m3 + movddup m3, [base+pw_m1536] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+16*1], m0 + por m1, m3 + mova [rsp+16*0], m1 + dec wd + jz .h32_transpose + add r5, dyq + jg .h32_loop +.h32_end_loop: + sub rsp, 16*4 + REPX {mova [rsp+16*x], m6}, 3, 2, 1, 0 + dec wd + jg .h32_end_loop +.h32_transpose: + or r3d, 32*2 + jmp .end_transpose +.h64: + lea r4d, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + call .filter_copy + call .filter_edge_s3 +.h64_main: + sub tlq, r4 + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m6, [tlq] + movd m3, r4d + pshufb m5, m0 + neg dyq + pshufb m6, m0 + lea r5, [dyq+r4+63] + pshufb m3, m0 + paddw m4, m5, [base+z_base_inc_z2] + psubw m4, m3 +.h64_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4*2- 14] + movu m3, [tlq+r4*2- 16] + pand m2, m7, m4 + psllw m2, 9 + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 30] + paddw m0, m3 + movu m3, [tlq+r4*2- 32] + psubw m3, m1 + pmulhrsw m3, m2 + sub rsp, 16*8 + paddw m1, m3 + psraw m3, m4, 15 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m512] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*7], m0 + por m1, m3 + mova [rsp+16*6], m1 + movu m0, [tlq+r4*2- 46] + movu m3, [tlq+r4*2- 48] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 62] + paddw m0, m3 + movu m3, [tlq+r4*2- 64] + psubw m3, m1 + pmulhrsw m3, m2 + paddw m1, m3 + movddup m3, [base+pw_m1024] + pcmpgtw m3, m4 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m1536] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*5], m0 + por m1, m3 + mova [rsp+16*4], m1 + movu m0, [tlq+r4*2- 78] + movu m3, [tlq+r4*2- 80] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2- 94] + paddw m0, m3 + movu m3, [tlq+r4*2- 96] + psubw m3, m1 + pmulhrsw m3, m2 + paddw m1, m3 + movddup m3, [base+pw_m2048] + pcmpgtw m3, m4 + pand m0, m3 + pandn m3, m6 + por m0, m3 + movddup m3, [base+pw_m2560] + pcmpgtw m3, m4 + pand m1, m3 + pandn m3, m6 + mova [rsp+16*3], m0 + por m1, m3 + mova [rsp+16*2], m1 + movu m0, [tlq+r4*2-110] + movu m3, [tlq+r4*2-112] + psubw m3, m0 + pmulhrsw m3, m2 + movu m1, [tlq+r4*2-126] + paddw m0, m3 + movu m3, [tlq+r4*2-128] + psubw m3, m1 + pmulhrsw m3, m2 + movddup m2, [base+pw_m3072] + paddw m1, m3 + movddup m3, [base+pw_m3584] + pcmpgtw m2, m4 + pcmpgtw m3, m4 + paddw m4, m5 + pand m0, m2 + pandn m2, m6 + pand m1, m3 + pandn m3, m6 + por m0, m2 + mova [rsp+16*1], m0 + por m1, m3 + mova [rsp+16*0], m1 + dec wd + jz .h64_transpose + add r5, dyq + jg .h64_loop +.h64_end_loop: + sub rsp, 16*8 + REPX {mova [rsp+16*x], m6}, 7, 6, 5, 4, 3, 2, 1, 0 + dec wd + jg .h64_end_loop +.h64_transpose: + add r3d, 64*2 +.end_transpose: +%if ARCH_X86_64 + lea r7, [strideq*3] +%else + mov strideq, [dstq+4*0] + mov org_wd, [dstq+4*1] +%endif + lea r4d, [r3*3] +.end_transpose_loop: + lea r2, [rsp+r3-8] + lea r6, [dstq+org_wq*2-8] +.end_transpose_loop_y: + movq m0, [r2+r4 ] + movq m1, [r2+r3*2] + movq m2, [r2+r3*1] + movq m3, [r2+r3*0] + sub r2, 8 + punpcklwd m0, m1 + punpcklwd m2, m3 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + movhps [r6+strideq*0], m1 + movq [r6+strideq*1], m1 +%if ARCH_X86_64 + movhps [r6+strideq*2], m0 + movq [r6+r7 ], m0 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m0 + movq [r6+strideq*1], m0 + lea r6, [r6+strideq*2] +%endif + cmp r2, rsp + jae .end_transpose_loop_y + lea rsp, [rsp+r3*4] + sub org_wd, 4 + jg .end_transpose_loop + RET +.filter_copy: + neg r4 + pshuflw m2, [tlq+2], q0000 + xor r5d, r5d + pshuflw m3, [tlq+r4*2], q0000 + movq [rsp+gprsize+16*17], m2 +.filter_copy_loop: + mova m1, [tlq+r5*2-16*1+2] + mova m2, [tlq+r5*2-16*2+2] + sub r5, 16 + mova [rsp+r5*2+gprsize+16*18], m1 + mova [rsp+r5*2+gprsize+16*17], m2 + cmp r5d, r4d + jg .filter_copy_loop + lea tlq, [rsp+gprsize+16*17-2] + movq [tlq+r4*2-8], m3 + ret +.filter_edge: + cmp r5d, 3 + je .filter_edge_s3 + movddup m4, [base+z_filt_k+r5*8-8] + movddup m5, [base+z_filt_k+r5*8+8] + xor r5d, r5d + movddup m6, [base+pw_8] + movu m2, [tlq-12] + jmp .filter_edge_start +.filter_edge_loop: + movu m2, [tlq+r5*2-12] + mova [tlq+r5*2+2], m1 +.filter_edge_start: + pmullw m1, m4, [tlq+r5*2-14] + movu m3, [tlq+r5*2-16] + sub r5, 8 + paddw m2, m3 + pmullw m2, m5 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 4 + cmp r5d, r4d + jg .filter_edge_loop + mova [tlq+r5*2+2], m1 + neg r4d + ret +.filter_edge_s3: + movddup m5, [base+pw_3] + xor r5d, r5d + movu m2, [tlq-12] + movu m3, [tlq-10] + jmp .filter_edge_s3_start +.filter_edge_s3_loop: + movu m2, [tlq+r5*2-12] + movu m3, [tlq+r5*2-10] + mova [tlq+r5*2+2], m1 +.filter_edge_s3_start: + paddw m2, [tlq+r5*2-14] + paddw m3, m5 + movu m1, [tlq+r5*2-16] + movu m4, [tlq+r5*2-18] + sub r5, 8 + paddw m1, m2 + pavgw m3, m4 + paddw m1, m3 + psrlw m1, 2 + cmp r5d, r4d + jg .filter_edge_s3_loop + mova [tlq+r5*2+2], m1 + neg r4d + ret + +%if ARCH_X86_64 +cglobal ipred_filter_16bpc, 4, 7, 16, dst, stride, tl, w, h, filter +%else +cglobal ipred_filter_16bpc, 4, 7, 8, -16*8, dst, stride, tl, w, h, filter +%define m8 [esp+16*0] +%define m9 [esp+16*1] +%define m10 [esp+16*2] +%define m11 [esp+16*3] +%define m12 [esp+16*4] +%define m13 [esp+16*5] +%define m14 [esp+16*6] +%define m15 [esp+16*7] +%endif +%define base r6-$$ + movifnidn hd, hm + movd m6, r8m ; bitdepth_max +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + LEA r6, $$ + shl filterd, 6 + movu m0, [tlq-6] ; __ l1 l0 tl t0 t1 t2 t3 + mova m1, [base+filter_intra_taps+filterq+16*0] + mova m2, [base+filter_intra_taps+filterq+16*1] + mova m3, [base+filter_intra_taps+filterq+16*2] + mova m4, [base+filter_intra_taps+filterq+16*3] + pxor m5, m5 +%if ARCH_X86_64 + punpcklbw m8, m5, m1 ; place 8-bit coefficients in the upper + punpckhbw m9, m5, m1 ; half of each 16-bit word to avoid + punpcklbw m10, m5, m2 ; having to perform sign-extension. + punpckhbw m11, m5, m2 + punpcklbw m12, m5, m3 + punpckhbw m13, m5, m3 + punpcklbw m14, m5, m4 + punpckhbw m15, m5, m4 +%else + punpcklbw m7, m5, m1 + mova m8, m7 + punpckhbw m7, m5, m1 + mova m9, m7 + punpcklbw m7, m5, m2 + mova m10, m7 + punpckhbw m7, m5, m2 + mova m11, m7 + punpcklbw m7, m5, m3 + mova m12, m7 + punpckhbw m7, m5, m3 + mova m13, m7 + punpcklbw m7, m5, m4 + mova m14, m7 + punpckhbw m7, m5, m4 + mova m15, m7 +%endif + mova m7, [base+filter_shuf] + add hd, hd + mov r5, dstq + pshuflw m6, m6, q0000 + mov r6, tlq + punpcklqdq m6, m6 + sub tlq, hq +.left_loop: + pshufb m0, m7 ; tl t0 t1 t2 t3 l0 l1 __ + pshufd m1, m0, q0000 + pmaddwd m2, m8, m1 + pmaddwd m1, m9 + pshufd m4, m0, q1111 + pmaddwd m3, m10, m4 + pmaddwd m4, m11 + paddd m2, m3 + paddd m1, m4 + pshufd m4, m0, q2222 + pmaddwd m3, m12, m4 + pmaddwd m4, m13 + paddd m2, m3 + paddd m1, m4 + pshufd m3, m0, q3333 + pmaddwd m0, m14, m3 + pmaddwd m3, m15 + paddd m0, m2 + paddd m1, m3 + psrad m0, 11 ; x >> 3 + psrad m1, 11 + packssdw m0, m1 + pmaxsw m0, m5 + pavgw m0, m5 ; (x + 8) >> 4 + pminsw m0, m6 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movlps m0, [tlq+hq-10] + lea dstq, [dstq+strideq*2] + sub hd, 2*2 + jg .left_loop + sub wd, 4 + jz .end + sub tld, r6d ; -h*2 + sub r6, r5 ; tl-dst +.right_loop0: + add r5, 8 + mov hd, tld + movu m0, [r5+r6] ; tl t0 t1 t2 t3 __ __ __ + mov dstq, r5 +.right_loop: + pshufd m2, m0, q0000 + pmaddwd m1, m8, m2 + pmaddwd m2, m9 + pshufd m4, m0, q1111 + pmaddwd m3, m10, m4 + pmaddwd m4, m11 + pinsrw m0, [dstq+strideq*0-2], 5 + paddd m1, m3 + paddd m2, m4 + pshufd m0, m0, q2222 + movddup m4, [dstq+strideq*1-8] + pmaddwd m3, m12, m0 + pmaddwd m0, m13 + paddd m1, m3 + paddd m0, m2 + pshuflw m2, m4, q3333 + punpcklwd m2, m5 + pmaddwd m3, m14, m2 + pmaddwd m2, m15 + paddd m1, m3 + paddd m0, m2 + psrad m1, 11 + psrad m0, 11 + packssdw m0, m1 + pmaxsw m0, m5 + pavgw m0, m5 + pminsw m0, m6 + movhps [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + palignr m0, m4, 14 + lea dstq, [dstq+strideq*2] + add hd, 2*2 + jl .right_loop + sub wd, 4 + jg .right_loop0 +.end: + RET + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal ipred_cfl_top_16bpc, 4, 7, 8, dst, stride, tl, w, h, ac + LEA t0, ipred_cfl_left_16bpc_ssse3_table + movd m4, wd + tzcnt wd, wd + movifnidn hd, hm + add tlq, 2 + movsxd r6, [t0+wq*4] + movd m5, wd + jmp mangle(private_prefix %+ _ipred_cfl_left_16bpc_ssse3.start) + +cglobal ipred_cfl_left_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + LEA t0, ipred_cfl_left_16bpc_ssse3_table + tzcnt wd, wm + lea r6d, [hq*2] + movd m4, hd + sub tlq, r6 + tzcnt r6d, hd + movd m5, r6d + movsxd r6, [t0+r6*4] +.start: + movd m7, r7m + movu m0, [tlq] + add r6, t0 + add t0, ipred_cfl_splat_16bpc_ssse3_table-ipred_cfl_left_16bpc_ssse3_table + movsxd wq, [t0+wq*4] + pxor m6, m6 + pshuflw m7, m7, q0000 + pcmpeqw m3, m3 + add wq, t0 + movifnidn acq, acmp + pavgw m4, m6 + punpcklqdq m7, m7 + jmp r6 +.h32: + movu m1, [tlq+48] + movu m2, [tlq+32] + paddw m0, m1 + paddw m0, m2 +.h16: + movu m1, [tlq+16] + paddw m0, m1 +.h8: + pshufd m1, m0, q1032 + paddw m0, m1 +.h4: + pmaddwd m0, m3 + psubd m4, m0 + pshuflw m0, m4, q1032 + paddd m0, m4 + psrld m0, m5 + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +%macro IPRED_CFL 2 ; dst, src + pabsw m%1, m%2 + pmulhrsw m%1, m2 + psignw m%2, m1 + psignw m%1, m%2 + paddw m%1, m0 + pmaxsw m%1, m6 + pminsw m%1, m7 +%endmacro + +cglobal ipred_cfl_16bpc, 4, 7, 8, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd m4, t0d + tzcnt t0d, t0d + movd m5, t0d + LEA t0, ipred_cfl_16bpc_ssse3_table + tzcnt wd, wd + movd m7, r7m + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + psrlw m4, 1 + pxor m6, m6 + pshuflw m7, m7, q0000 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + pcmpeqw m3, m3 + punpcklqdq m7, m7 + jmp r6 +.h4: + movq m0, [tlq-8] + jmp wq +.w4: + movq m1, [tlq+2] + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + cmp hd, 4 + jg .w4_mul + psrld m0, 3 + jmp .w4_end +.w4_mul: + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 16 + cmove r6d, r2d + movd m1, r6d + psrld m0, 2 + pmulhuw m0, m1 + psrlw m0, 1 +.w4_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s4: + movd m1, alpham + lea r6, [strideq*3] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + movq [dstq+strideq*0], m3 + movhps [dstq+strideq*1], m3 + movq [dstq+strideq*2], m4 + movhps [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4_loop + RET +.h8: + mova m0, [tlq-16] + jmp wq +.w8: + movu m1, [tlq+2] + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 32 + cmove r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+strideq*0], m3 + mova [dstq+strideq*1], m4 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s8_loop + RET +.h16: + mova m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w16: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + add acq, 16*2 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*0], m3 + mova [dstq+16*1], m4 + add dstq, strideq + dec hd + jg .s16_loop + RET +.h32: + mova m0, [tlq-64] + paddw m0, [tlq-48] + paddw m0, [tlq-32] + paddw m0, [tlq-16] + jmp wq +.w32: + movu m1, [tlq+ 2] + movu m2, [tlq+18] + paddw m1, m2 + movu m2, [tlq+34] + paddw m1, m2 + movu m2, [tlq+50] + paddw m1, m2 + paddw m0, m1 + pmaddwd m0, m3 + psubd m4, m0 + pshufd m0, m4, q1032 + paddd m0, m4 + pshuflw m4, m0, q1032 + paddd m0, m4 + psrld m0, m5 + cmp hd, 32 + je .w32_end + mov r6d, 0xAAAB + mov r2d, 0x6667 + cmp hd, 8 + cmove r6d, r2d + movd m1, r6d + pmulhuw m0, m1 + psrlw m0, 1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq+16*0] + mova m5, [acq+16*1] + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*0], m3 + mova [dstq+16*1], m4 + mova m4, [acq+16*2] + mova m5, [acq+16*3] + add acq, 16*4 + IPRED_CFL 3, 4 + IPRED_CFL 4, 5 + mova [dstq+16*2], m3 + mova [dstq+16*3], m4 + add dstq, strideq + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_16bpc, 3, 7, 8, dst, stride, tl, w, h, ac + tzcnt wd, wm + LEA t0, ipred_cfl_splat_16bpc_ssse3_table + mov r6d, r7m + movifnidn hd, hm + shr r6d, 11 + movd m7, r7m + movsxd wq, [t0+wq*4] + movddup m0, [t0-ipred_cfl_splat_16bpc_ssse3_table+pw_512+r6*8] + pshuflw m7, m7, q0000 + pxor m6, m6 + add wq, t0 + movifnidn acq, acmp + punpcklqdq m7, m7 + jmp wq + +cglobal ipred_cfl_ac_420_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm +%if ARCH_X86_32 && PIC + pcmpeqw m5, m5 + pabsw m5, m5 + paddw m5, m5 +%else + movddup m5, [pw_2] +%endif + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + mov r5, acq + jg .w16 + je .w8 + lea r3, [strideq*3] +.w4_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + pmaddwd m2, m5, [ypxq+strideq*2] + pmaddwd m3, m5, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + paddd m0, m1 + paddd m2, m3 + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .dc + punpckhqdq m0, m0 + pslld m2, 2 +.w4_hpad: + mova [acq+16*0], m0 + paddd m4, m2 + mova [acq+16*1], m0 + add acq, 16*2 + sub hpadd, 4 + jg .w4_hpad + jmp .dc +.w8: +%if ARCH_X86_32 + cmp dword wpadm, 0 +%else + test wpadd, wpadd +%endif + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m2, m5, [ypxq+strideq*1+16*0] + pmaddwd m1, m5, [ypxq+strideq*0+16*1] + pmaddwd m3, m5, [ypxq+strideq*1+16*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m2 + paddd m1, m3 + paddd m2, m0, m1 + packssdw m0, m1 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + dec hd + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz .dc + pslld m2, 2 + mova m1, m0 + jmp .hpad +.w8_wpad1: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + paddd m0, m1 + pshufd m1, m0, q3333 + paddd m2, m0, m1 + packssdw m0, m1 + paddd m4, m2 + mova [acq], m0 + add acq, 16 + dec hd + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad3: + pshufd m3, m0, q3333 + mova m1, m3 + mova m2, m3 + jmp .w16_wpad_end +.w16_wpad2: + pshufd m1, m3, q3333 + mova m2, m1 + jmp .w16_wpad_end +.w16_wpad1: + pshufd m2, m1, q3333 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + WIN64_SPILL_XMM 7 +.w16_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m6, m5, [ypxq+strideq*1+16*0] + paddd m0, m6 + cmp wpadd, 2 + jg .w16_wpad3 + pmaddwd m3, m5, [ypxq+strideq*0+16*1] + pmaddwd m6, m5, [ypxq+strideq*1+16*1] + paddd m3, m6 + je .w16_wpad2 + pmaddwd m1, m5, [ypxq+strideq*0+16*2] + pmaddwd m6, m5, [ypxq+strideq*1+16*2] + paddd m1, m6 + jp .w16_wpad1 + pmaddwd m2, m5, [ypxq+strideq*0+16*3] + pmaddwd m6, m5, [ypxq+strideq*1+16*3] + paddd m2, m6 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + paddd m6, m0, m3 + packssdw m0, m3 + paddd m6, m1 + mova [acq+16*0], m0 + packssdw m1, m2 + paddd m2, m6 + mova [acq+16*1], m1 + add acq, 16*2 + paddd m4, m2 + dec hd + jg .w16_loop + WIN64_RESTORE_XMM + add hpadd, hpadd + jz .dc + paddd m2, m2 +.hpad: + mova [acq+16*0], m0 + mova [acq+16*1], m1 + paddd m4, m2 + mova [acq+16*2], m0 + mova [acq+16*3], m1 + add acq, 16*4 + sub hpadd, 4 + jg .hpad +.dc: + sub r5, acq ; -w*h*2 + pshufd m2, m4, q1032 + tzcnt r1d, r5d + paddd m2, m4 + sub r1d, 2 + pshufd m4, m2, q2301 + movd m0, r1d + paddd m2, m4 + psrld m2, m0 + pxor m0, m0 + pavgw m2, m0 + packssdw m2, m2 +.dc_loop: + mova m0, [acq+r5+16*0] + mova m1, [acq+r5+16*1] + psubw m0, m2 + psubw m1, m2 + mova [acq+r5+16*0], m0 + mova [acq+r5+16*1], m1 + add r5, 16*2 + jl .dc_loop + RET + +cglobal ipred_cfl_ac_422_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h + movifnidn hpadd, hpadm +%if ARCH_X86_32 && PIC + pcmpeqw m5, m5 + pabsw m5, m5 + psllw m5, 2 +%else + movddup m5, [pw_4] +%endif + mov hd, hm + shl hpadd, 2 + pxor m4, m4 + sub hd, hpadd + cmp dword wm, 8 + mov r5, acq + jg .w16 + je .w8 + lea r3, [strideq*3] +.w4_loop: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m3, m5, [ypxq+strideq*1] + pmaddwd m1, m5, [ypxq+strideq*2] + pmaddwd m2, m5, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + paddd m4, m0 + packssdw m0, m3 + paddd m3, m1 + packssdw m1, m2 + paddd m4, m2 + paddd m4, m3 + mova [acq+16*0], m0 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + punpckhqdq m1, m1 + pslld m2, 3 + mova [acq+16*0], m1 + mova [acq+16*1], m1 + paddd m4, m2 + mova [acq+16*2], m1 + mova [acq+16*3], m1 + add acq, 16*4 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w8: +%if ARCH_X86_32 + cmp dword wpadm, 0 +%else + test wpadd, wpadd +%endif + jnz .w8_wpad1 +.w8_loop: + pmaddwd m0, m5, [ypxq+strideq*0+16*0] + pmaddwd m2, m5, [ypxq+strideq*0+16*1] + pmaddwd m1, m5, [ypxq+strideq*1+16*0] + pmaddwd m3, m5, [ypxq+strideq*1+16*1] + lea ypxq, [ypxq+strideq*2] + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + mova [acq+16*0], m0 + paddd m2, m1, m3 + packssdw m1, m3 + paddd m4, m2 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + pslld m2, 2 + mova m0, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w8_wpad1: + pmaddwd m0, m5, [ypxq+strideq*0] + pmaddwd m1, m5, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + pshufd m2, m0, q3333 + pshufd m3, m1, q3333 + paddd m4, m0 + packssdw m0, m2 + paddd m4, m2 + paddd m2, m1, m3 + packssdw m1, m3 + paddd m4, m2 + mova [acq+16*0], m0 + mova [acq+16*1], m1 + add acq, 16*2 + sub hd, 2 + jg .w8_wpad1 + jmp .w8_hpad +.w16_wpad3: + pshufd m3, m0, q3333 + mova m1, m3 + mova m2, m3 + jmp .w16_wpad_end +.w16_wpad2: + pshufd m1, m3, q3333 + mova m2, m1 + jmp .w16_wpad_end +.w16_wpad1: + pshufd m2, m1, q3333 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + WIN64_SPILL_XMM 7 +.w16_loop: + pmaddwd m0, m5, [ypxq+16*0] + cmp wpadd, 2 + jg .w16_wpad3 + pmaddwd m3, m5, [ypxq+16*1] + je .w16_wpad2 + pmaddwd m1, m5, [ypxq+16*2] + jp .w16_wpad1 + pmaddwd m2, m5, [ypxq+16*3] +.w16_wpad_end: + add ypxq, strideq + paddd m6, m0, m3 + packssdw m0, m3 + mova [acq+16*0], m0 + paddd m6, m1 + packssdw m1, m2 + paddd m2, m6 + mova [acq+16*1], m1 + add acq, 16*2 + paddd m4, m2 + dec hd + jg .w16_loop + WIN64_RESTORE_XMM + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + paddd m2, m2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad + +cglobal ipred_cfl_ac_444_16bpc, 3, 7, 6, ac, ypx, stride, wpad, hpad, w, h +%define base r6-ipred_cfl_ac_444_16bpc_ssse3_table + LEA r6, ipred_cfl_ac_444_16bpc_ssse3_table + tzcnt wd, wm + movifnidn hpadd, hpadm + pxor m4, m4 + movsxd wq, [r6+wq*4] + movddup m5, [base+pw_1] + add wq, r6 + mov hd, hm + shl hpadd, 2 + sub hd, hpadd + jmp wq +.w4: + lea r3, [strideq*3] + mov r5, acq +.w4_loop: + movq m0, [ypxq+strideq*0] + movhps m0, [ypxq+strideq*1] + movq m1, [ypxq+strideq*2] + movhps m1, [ypxq+r3 ] + lea ypxq, [ypxq+strideq*4] + psllw m0, 3 + psllw m1, 3 + mova [acq+16*0], m0 + pmaddwd m0, m5 + mova [acq+16*1], m1 + pmaddwd m2, m5, m1 + add acq, 16*2 + paddd m4, m0 + paddd m4, m2 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + punpckhqdq m1, m1 + mova [acq+16*0], m1 + pslld m2, 2 + mova [acq+16*1], m1 + punpckhqdq m2, m2 + mova [acq+16*2], m1 + paddd m4, m2 + mova [acq+16*3], m1 + add acq, 16*4 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w8: + mov r5, acq +.w8_loop: + mova m0, [ypxq+strideq*0] + mova m1, [ypxq+strideq*1] + lea ypxq, [ypxq+strideq*2] + psllw m0, 3 + psllw m1, 3 + mova [acq+16*0], m0 + pmaddwd m0, m5 + mova [acq+16*1], m1 + pmaddwd m2, m5, m1 + add acq, 16*2 + paddd m4, m0 + paddd m4, m2 + sub hd, 2 + jg .w8_loop +.w8_hpad: + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + pslld m2, 2 + mova m0, m1 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w16_wpad2: + pshufhw m3, m2, q3333 + pshufhw m1, m0, q3333 + punpckhqdq m3, m3 + punpckhqdq m1, m1 + jmp .w16_wpad_end +.w16: + movifnidn wpadd, wpadm + mov r5, acq +.w16_loop: + mova m2, [ypxq+strideq*0+16*0] + mova m0, [ypxq+strideq*1+16*0] + psllw m2, 3 + psllw m0, 3 + test wpadd, wpadd + jnz .w16_wpad2 + mova m3, [ypxq+strideq*0+16*1] + mova m1, [ypxq+strideq*1+16*1] + psllw m3, 3 + psllw m1, 3 +.w16_wpad_end: + lea ypxq, [ypxq+strideq*2] + mova [acq+16*0], m2 + pmaddwd m2, m5 + mova [acq+16*1], m3 + pmaddwd m3, m5 + paddd m4, m2 + pmaddwd m2, m5, m0 + mova [acq+16*2], m0 + paddd m4, m3 + pmaddwd m3, m5, m1 + mova [acq+16*3], m1 + add acq, 16*4 + paddd m2, m3 + paddd m4, m2 + sub hd, 2 + jg .w16_loop + add hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + paddd m2, m2 + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).hpad +.w32_wpad6: + pshufhw m1, m0, q3333 + punpckhqdq m1, m1 + mova m2, m1 + mova m3, m1 + jmp .w32_wpad_end +.w32_wpad4: + pshufhw m2, m1, q3333 + punpckhqdq m2, m2 + mova m3, m2 + jmp .w32_wpad_end +.w32_wpad2: + pshufhw m3, m2, q3333 + punpckhqdq m3, m3 + jmp .w32_wpad_end +.w32: + movifnidn wpadd, wpadm + mov r5, acq + WIN64_SPILL_XMM 8 +.w32_loop: + mova m0, [ypxq+16*0] + psllw m0, 3 + cmp wpadd, 4 + jg .w32_wpad6 + mova m1, [ypxq+16*1] + psllw m1, 3 + je .w32_wpad4 + mova m2, [ypxq+16*2] + psllw m2, 3 + jnp .w32_wpad2 + mova m3, [ypxq+16*3] + psllw m3, 3 +.w32_wpad_end: + add ypxq, strideq + pmaddwd m6, m5, m0 + mova [acq+16*0], m0 + pmaddwd m7, m5, m1 + mova [acq+16*1], m1 + paddd m6, m7 + pmaddwd m7, m5, m2 + mova [acq+16*2], m2 + paddd m6, m7 + pmaddwd m7, m5, m3 + mova [acq+16*3], m3 + add acq, 16*4 + paddd m6, m7 + paddd m4, m6 + dec hd + jg .w32_loop +%if WIN64 + mova m5, m6 + WIN64_RESTORE_XMM + SWAP 5, 6 +%endif + test hpadd, hpadd + jz mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc +.w32_hpad_loop: + mova [acq+16*0], m0 + mova [acq+16*1], m1 + paddd m4, m6 + mova [acq+16*2], m2 + mova [acq+16*3], m3 + add acq, 16*4 + dec hpadd + jg .w32_hpad_loop + jmp mangle(private_prefix %+ _ipred_cfl_ac_420_16bpc_ssse3).dc + +cglobal pal_pred_16bpc, 4, 5, 5, dst, stride, pal, idx, w, h +%define base r2-pal_pred_16bpc_ssse3_table +%if ARCH_X86_32 + %define hd r2d +%endif + mova m3, [palq] + LEA r2, pal_pred_16bpc_ssse3_table + tzcnt wd, wm + pshufb m3, [base+pal_pred_shuf] + movsxd wq, [r2+wq*4] + pshufd m4, m3, q1032 + add wq, r2 + movifnidn hd, hm + jmp wq +.w4: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4 + RET +.w8: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8 + RET +.w16: + mova m0, [idxq] + add idxq, 16 + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16 + RET +.w32: + mova m0, [idxq+16*0] + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova m2, [idxq+16*1] + add idxq, 16*2 + mova [dstq+16*0], m0 + pshufb m0, m3, m2 + mova [dstq+16*1], m1 + pshufb m1, m4, m2 + punpcklbw m2, m0, m1 + punpckhbw m0, m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m0 + add dstq, strideq + dec hd + jg .w32 + RET +.w64: + mova m0, [idxq+16*0] + pshufb m1, m3, m0 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova m2, [idxq+16*1] + mova [dstq+16*0], m0 + pshufb m0, m3, m2 + mova [dstq+16*1], m1 + pshufb m1, m4, m2 + punpcklbw m2, m0, m1 + punpckhbw m0, m1 + mova m1, [idxq+16*2] + mova [dstq+16*2], m2 + pshufb m2, m3, m1 + mova [dstq+16*3], m0 + pshufb m0, m4, m1 + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + mova m0, [idxq+16*3] + add idxq, 16*4 + mova [dstq+16*4], m1 + pshufb m1, m3, m0 + mova [dstq+16*5], m2 + pshufb m2, m4, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + add dstq, strideq + dec hd + jg .w64 + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5387 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +; sm_weights[], but modified to precalculate x and 256-x with offsets to +; enable efficient use of pmaddubsw (which requires signed values) +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +pb_1to32: db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + db 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +pb_32to1: db 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17 +pb_16to1: db 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 +z_filter_wh: db 7, 7, 11, 11, 15, 15, 19, 19, 19, 23, 23, 23, 31, 31, 31, 39 + db 39, 39, 47, 47, 47, 63, 63, 63, 79, 79, 79, -1 +z_filter_k: db 0, 16, 0, 16, 0, 20, 0, 20, 8, 16, 8, 16 + db 32, 16, 32, 16, 24, 20, 24, 20, 16, 16, 16, 16 + db 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0 +z_filter_s: db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 + db 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15 + db 15, 15, 15, 15, 15, 15, 15, 15 ; should be in one cache line +pb_128: times 4 db 128 ; those are just placed here for alignment. +pb_36_m4: times 2 db 36, -4 +z3_shuf: db 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0 +z_filter_t0: db 55,127, 39,127, 39,127, 7, 15, 31, 7, 15, 31, 0, 3, 31, 0 +z_filter_t1: db 39, 63, 19, 47, 19, 47, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 +z_upsample1: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z_upsample2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8 +z2_upsample: db 7, 6, 15, 14, 5, 4, 13, 12, 3, 2, 11, 10, 1, 0, 9, 8 +z1_shuf_w4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +z2_shuf_h2: db 3, 2, 7, 6, 11, 10, 15, 14, 2, 1, 6, 5, 10, 9, 14, 13 +z2_shuf_h4: db 7, 6, 15, 14, 6, 5, 14, 13, 5, 4, 13, 12, 4, 3, 12, 11 +z3_shuf_w4: db 4, 3, 3, 2, 2, 1, 1, 0, 12, 11, 11, 10, 10, 9, 9, 8 +z_transpose4: db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 + dw 16*64, 17*64, 18*64, 19*64, 20*64, 21*64, 22*64, 23*64 +z2_base_inc: dw 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64, 8*64 + dw 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64, 16*64 +z2_ymul: dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +z2_y_shuf_h4: db 90, 90, 90, 90, 14, 14, 14, 14, 27, 27, 27, 27, 31, 31, 31, 31 ; 2, 6, 3, 7 + db 32, 32, 32, 32, 12, 12, 12, 12, 1, 0, 1, 0, 5, -1, -1, -1 ; 0, 4, 1, 5 +; vpermd indices in bits 4..6 of filter_shuf1: 0, 2, 6, 4, 1, 3, 7, 5 +filter_shuf1: db 10, 4, 10, 4, 37, 6, 5, 6,103, 9, 7, 9, 72, -1, 8, -1 + db 16, 4, 0, 4, 53, 6, 5, 6,119, 11, 7, 11, 95, -1, 15, -1 +filter_shuf2: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 2, 7, 2, 1, -1, 1, -1 +filter_shuf3: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 11, 7, 11; 15, -1, 15, -1 +pb_127_m127: times 2 db 127, -127 +ipred_v_shuf: db 0, 1, 0, 1, 4, 5, 4, 5, 8, 9, 8, 9, 12, 13, 12, 13 + db 2, 3, 2, 3, 6, 7, 6, 7, 10, 11, 10, 11, 14, 15, 14, 15 +ipred_h_shuf: db 7, 7, 7, 7, 3, 3, 3, 3, 5, 5, 5, 5, 1, 1, 1, 1 + db 6, 6, 6, 6, 2, 2, 2, 2, 4, 4, 4, 4; 0, 0, 0, 0 +pw_64: times 2 dw 64 + +cfl_ac_444_w16_pad1_shuffle: db 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1 + times 9 db 7, -1 +cfl_ac_w16_pad_shuffle: ; w=16, w_pad=1 + db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ; w=8, w_pad=1 as well as second half of previous one +cfl_ac_w8_pad1_shuffle: db 0, 1, 2, 3, 4, 5 + times 5 db 6, 7 + ; w=16,w_pad=2 + db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + times 8 db 14, 15 + ; w=16,w_pad=3 + db 0, 1, 2, 3, 4, 5 + times 13 db 6, 7 +pb_15to0: db 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +%define pb_0to15 cfl_ac_w16_pad_shuffle +%define pb_1 (ipred_h_shuf+12) +%define pb_2 (ipred_h_shuf+20) +%define pb_3 (ipred_h_shuf+ 4) +%define pb_4 (ipred_h_shuf+24) +%define pb_5 (ipred_h_shuf+ 8) +%define pb_7 (ipred_h_shuf+ 0) +%define pb_8 (z_upsample2 +12) +%define pb_12 (z2_y_shuf_h4+20) +%define pb_14 (z2_y_shuf_h4+ 4) +%define pb_15 (z_filter_s +32) +%define pb_27 (z2_y_shuf_h4+ 8) +%define pb_31 (z2_y_shuf_h4+12) +%define pb_32 (z2_y_shuf_h4+16) +%define pb_90 (z2_y_shuf_h4+ 0) +%define pw_1 (z2_y_shuf_h4+24) +%define pw_8 (z_filter_k +32) + +pw_62: times 2 dw 62 +pw_128: times 2 dw 128 +pw_255: times 2 dw 255 +pw_512: times 2 dw 512 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_avx2_table (ipred_dc_avx2_table + 10*4) +%define ipred_cfl_splat_avx2_table (ipred_cfl_avx2_table + 8*4) + +JMP_TABLE ipred_smooth, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_filter, avx2, w4, w8, w16, w32 +JMP_TABLE ipred_dc, avx2, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_h, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2, avx2, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3, avx2, h4, h8, h16, h32, h64 +JMP_TABLE ipred_cfl, avx2, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left, avx2, h4, h8, h16, h32 +JMP_TABLE ipred_cfl_ac_420, avx2, w16_pad1, w16_pad2, w16_pad3 +JMP_TABLE ipred_cfl_ac_422, avx2, w16_pad1, w16_pad2, w16_pad3 +JMP_TABLE ipred_cfl_ac_444, avx2, w32_pad1, w32_pad2, w32_pad3, w4, w8, w16, w32 +JMP_TABLE pal_pred, avx2, w4, w8, w16, w32, w64 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +INIT_YMM avx2 +cglobal ipred_dc_top_8bpc, 3, 7, 6, dst, stride, tl, w, h + lea r5, [ipred_dc_left_avx2_table] + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + shrx r6d, r6d, wd + movd xm3, r6d + movsxd r6, [r5+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_avx2_table-ipred_dc_left_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov r5d, 0x8000 + shrx r5d, r5d, r6d + movd xm3, r5d + lea r5, [ipred_dc_left_avx2_table] + movsxd r6, [r5+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_avx2_table-ipred_dc_left_avx2_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m1, [tlq+32] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h32: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddw xm0, xm1 +.h4: + pmaddwd xm0, xm2 + pmulhrsw xm0, xm3 + lea stride3q, [strideq*3] + vpbroadcastb m0, xm0 + mova m1, m0 + jmp wq + +cglobal ipred_dc_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm4, r5d + tzcnt r5d, r5d + movd xm5, r5d + lea r5, [ipred_dc_avx2_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + pcmpeqd m3, m3 + psrlw xm4, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd xm0, [tlq-4] + pmaddubsw xm0, xm3 + jmp wq +.w4: + movd xm1, [tlq+1] + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm1 + pmaddwd xm0, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddw xm0, xm1 + shrx r6d, r6d, r2d + psrlq xm1, xm0, 32 + paddw xm0, xm1 + movd xm1, r6d + psrlw xm0, 2 + pmulhuw xm0, xm1 +.w4_end: + vpbroadcastb xm0, xm0 +.s4: + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm0 + movd [dstq+strideq*2], xm0 + movd [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + movq xm0, [tlq-8] + pmaddubsw xm0, xm3 + jmp wq +.w8: + movq xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + punpckhqdq xm2, xm0, xm0 + paddw xm0, xm2 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w8_end: + vpbroadcastb xm0, xm0 +.s8: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova xm0, [tlq-16] + pmaddubsw xm0, xm3 + jmp wq +.w16: + movu xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w16_end: + vpbroadcastb xm0, xm0 +.s16: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w32_end: + vpbroadcastb m0, xm0 +.s32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-64] + mova m1, [tlq-32] + pmaddubsw m0, m3 + pmaddubsw m1, m3 + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 1] + movu m2, [tlq+33] + pmaddubsw m1, m3 + pmaddubsw m2, m3 + paddw m0, m1 + paddw m0, m2 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 64 + je .w64_end + mov r6d, 0x33345556 + shrx r6d, r6d, hd + movd xm1, r6d + pmulhuw xm0, xm1 +.w64_end: + vpbroadcastb m0, xm0 + mova m1, m0 +.s64: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m0 + mova [dstq+stride3q +32*1], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s64 + RET + +cglobal ipred_dc_128_8bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_avx2_table+pb_128] + mova m1, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_avx2_table] + tzcnt wd, wm + movu m0, [tlq+ 1] + movu m1, [tlq+33] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +%macro IPRED_H 2 ; w, store_type + vpbroadcastb m0, [tlq-1] + vpbroadcastb m1, [tlq-2] + vpbroadcastb m2, [tlq-3] + sub tlq, 4 + vpbroadcastb m3, [tlq+0] + mov%2 [dstq+strideq*0], m0 + mov%2 [dstq+strideq*1], m1 + mov%2 [dstq+strideq*2], m2 + mov%2 [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +ALIGN function_align +%endmacro + +INIT_XMM avx2 +cglobal ipred_h_8bpc, 3, 6, 4, dst, stride, tl, w, h, stride3 + lea r5, [ipred_h_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + IPRED_H 4, d +.w8: + IPRED_H 8, q +.w16: + IPRED_H 16, a +INIT_YMM avx2 +.w32: + IPRED_H 32, a +.w64: + vpbroadcastb m0, [tlq-1] + vpbroadcastb m1, [tlq-2] + vpbroadcastb m2, [tlq-3] + sub tlq, 4 + vpbroadcastb m3, [tlq+0] + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m0 + mova [dstq+strideq*1+32*0], m1 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*2+32*0], m2 + mova [dstq+strideq*2+32*1], m2 + mova [dstq+stride3q +32*0], m3 + mova [dstq+stride3q +32*1], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64 + RET + +%macro PAETH 2 ; top, ldiff + pavgb m1, m%1, m3 ; Calculating tldiff normally requires + pxor m0, m%1, m3 ; 10-bit intermediates, but we can do it + pand m0, m4 ; in 8-bit with some tricks which avoids + psubusb m2, m5, m1 ; having to unpack everything to 16-bit. + psubb m1, m0 + psubusb m1, m5 + por m1, m2 + paddusb m1, m1 + por m1, m0 ; min(tldiff, 255) + psubusb m2, m5, m3 + psubusb m0, m3, m5 + por m2, m0 ; tdiff + pminub m2, m%2 + pcmpeqb m0, m%2, m2 ; ldiff <= tdiff + vpblendvb m0, m%1, m3, m0 + pminub m1, m2 + pcmpeqb m1, m2 ; ldiff <= tldiff || tdiff <= tldiff + vpblendvb m0, m5, m0, m1 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 6, 9, dst, stride, tl, w, h +%define base r5-ipred_paeth_avx2_table + lea r5, [ipred_paeth_avx2_table] + tzcnt wd, wm + vpbroadcastb m5, [tlq] ; topleft + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m4, [base+pb_1] + add wq, r5 + jmp wq +.w4: + vpbroadcastd m6, [tlq+1] ; top + mova m8, [base+ipred_h_shuf] + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + sub tlq, 8 + vpbroadcastq m3, [tlq] + pshufb m3, m8 ; left + PAETH 6, 7 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + vpbroadcastq m6, [tlq+1] + mova m8, [base+ipred_h_shuf] + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + sub tlq, 4 + vpbroadcastd m3, [tlq] + pshufb m3, m8 + PAETH 6, 7 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m6, [tlq+1] + mova xm8, xm4 ; lower half = 1, upper half = 0 + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + sub tlq, 2 + vpbroadcastd m3, [tlq] + pshufb m3, m8 + PAETH 6, 7 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w32_loop: + dec tlq + vpbroadcastb m3, [tlq] + PAETH 6, 7 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m6, [tlq+ 1] + movu m7, [tlq+33] +%if WIN64 + movaps r4m, xmm9 +%endif + psubusb m8, m5, m6 + psubusb m0, m6, m5 + psubusb m9, m5, m7 + psubusb m1, m7, m5 + por m8, m0 + por m9, m1 +.w64_loop: + dec tlq + vpbroadcastb m3, [tlq] + PAETH 6, 8 + mova [dstq+32*0], m0 + PAETH 7, 9 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop +%if WIN64 + movaps xmm9, r4m +%endif + RET + +%macro SMOOTH 6 ; src[1-2], mul[1-2], add[1-2] + ; w * a = (w - 128) * a + 128 * a + ; (256 - w) * b = (127 - w) * b + 129 * b + pmaddubsw m0, m%3, m%1 + pmaddubsw m1, m%4, m%2 + paddw m0, m%5 + paddw m1, m%6 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +cglobal ipred_smooth_v_8bpc, 3, 7, 0, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_avx2_table + lea r6, [ipred_smooth_v_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m0, [base+pb_127_m127] + vpbroadcastd m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + vpbroadcastb m5, [tlq+hq] ; bottom + add wq, r6 + jmp wq +.w4: + vpbroadcastd m2, [tlq+1] + punpcklbw m2, m5 ; top, bottom + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + punpckldq m4, m5, m5 + punpckhdq m5, m5 + pmaddubsw m3, m2, m0 + paddw m1, m2 ; 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; 128 * top + 129 * bottom + 128 +.w4_loop: + vbroadcasti128 m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 1 + pextrd [dstq+r3 ], xm1, 1 + cmp hd, -4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm1, 2 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + add hq, 8 + jl .w4_loop +.ret: + RET +ALIGN function_align +.w8: + vpbroadcastq m2, [tlq+1] + punpcklbw m2, m5 + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + pshufd m4, m5, q0000 + pshufd m5, m5, q1111 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 +.w8_loop: + vpbroadcastq m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +ALIGN function_align +.w16: + WIN64_SPILL_XMM 7 + vbroadcasti128 m3, [tlq+1] + mova m6, [base+ipred_v_shuf] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w16_loop: + vpbroadcastd m1, [weightsq+hq*2] + pshufb m1, m6 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w16_loop + RET +ALIGN function_align +.w32: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 6 + movu m3, [tlq+1] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w32_loop: + vpbroadcastw m1, [weightsq+hq*2] + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m0 + add dstq, strideq + inc hq + jl .w32_loop + RET +ALIGN function_align +.w64: + WIN64_SPILL_XMM 11 + movu m4, [tlq+ 1] + movu m8, [tlq+33] + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m7, m8, m5 + punpckhbw m8, m5 + pmaddubsw m5, m3, m0 + pmaddubsw m6, m4, m0 + pmaddubsw m9, m7, m0 + pmaddubsw m10, m8, m0 + paddw m2, m1, m3 + paddw m5, m2 + paddw m2, m1, m4 + paddw m6, m2 + paddw m0, m1, m7 + paddw m9, m0 + paddw m1, m8 + paddw m10, m1 +.w64_loop: + vpbroadcastw m2, [weightsq+hq*2] + SMOOTH 2, 2, 3, 4, 5, 6 + mova [dstq+32*0], m0 + SMOOTH 2, 2, 7, 8, 9, 10 + mova [dstq+32*1], m0 + add dstq, strideq + inc hq + jl .w64_loop + RET + +%macro SETUP_STACK_FRAME 3 ; stack_size, regs_used, xmm_regs_used + %assign stack_offset 0 + %assign stack_size_padded 0 + %assign regs_used %2 + %xdefine rstk rsp + SETUP_STACK_POINTER %1 + %if regs_used != %2 && WIN64 + PUSH r%2 + %endif + ALLOC_STACK %1, %3 +%endmacro + +cglobal ipred_smooth_h_8bpc, 3, 7, 0, dst, stride, tl, w, h +%define base r6-ipred_smooth_h_avx2_table + lea r6, [ipred_smooth_h_avx2_table] + mov wd, wm + vpbroadcastb m3, [tlq+wq] ; right + tzcnt wd, wd + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m4, [base+pb_127_m127] + vpbroadcastd m5, [base+pw_128] + add wq, r6 + jmp wq +.w4: + WIN64_SPILL_XMM 8 + vpbroadcastq m6, [base+smooth_weights+4*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 8 + sub tlq, hq + lea r3, [strideq*3] +.w4_loop: + vpbroadcastq m2, [tlq+hq] + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 8 + vbroadcasti128 m6, [base+smooth_weights+8*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq +.w8_loop: + vpbroadcastd m2, [tlq+hq] + pshufb m2, m7 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 + paddw m0, m1 + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + SETUP_STACK_FRAME 32*4, 7, 8 + lea r3, [rsp+64*2-4] + call .prep ; only worthwhile for for w16 and above + sub tlq, 2 + vpbroadcastd xm6, [base+pb_1] + mova xm7, [base+ipred_v_shuf+16] + vinserti128 m7, [base+ipred_v_shuf+ 0], 1 + vbroadcasti128 m4, [base+smooth_weights+16*2] + vbroadcasti128 m5, [base+smooth_weights+16*3] +.w16_loop: + vpbroadcastd m1, [tlq+hq] + vpbroadcastd m2, [r3+hq*2] + pshufb m1, m6 + punpcklbw m1, m3 + pshufb m2, m7 + SMOOTH 4, 5, 1, 1, 2, 2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + SETUP_STACK_FRAME 32*4, 7, 6 + lea r3, [rsp+64*2-2] + call .prep + dec tlq + mova xm4, [base+smooth_weights+16*4] + vinserti128 m4, [base+smooth_weights+16*6], 1 + mova xm5, [base+smooth_weights+16*5] + vinserti128 m5, [base+smooth_weights+16*7], 1 +.w32_loop: + vpbroadcastb m1, [tlq+hq] + punpcklbw m1, m3 + vpbroadcastw m2, [r3+hq*2] + SMOOTH 4, 5, 1, 1, 2, 2 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + SETUP_STACK_FRAME 32*4, 7, 9 + lea r3, [rsp+64*2-2] + call .prep + add r6, smooth_weights+16*15-ipred_smooth_h_avx2_table + dec tlq + mova xm5, [r6-16*7] + vinserti128 m5, [r6-16*5], 1 + mova xm6, [r6-16*6] + vinserti128 m6, [r6-16*4], 1 + mova xm7, [r6-16*3] + vinserti128 m7, [r6-16*1], 1 + mova xm8, [r6-16*2] + vinserti128 m8, [r6-16*0], 1 +.w64_loop: + vpbroadcastb m2, [tlq+hq] + punpcklbw m2, m3 + vpbroadcastw m4, [r3+hq*2] + SMOOTH 5, 6, 2, 2, 4, 4 + mova [dstq+32*0], m0 + SMOOTH 7, 8, 2, 2, 4, 4 + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +ALIGN function_align +.prep: + vpermq m2, [tlq-32*1], q3120 + punpckhbw m1, m2, m3 + punpcklbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m1, m5 ; 1 * left + 256 * right + 128 + paddw m0, m1 ; 128 * left + 129 * right + 128 + pmaddubsw m1, m2, m4 + paddw m2, m5 + paddw m1, m2 + vpermq m2, [tlq-32*2], q3120 + mova [rsp+gprsize+32*3], m0 + mova [rsp+gprsize+32*2], m1 + punpckhbw m1, m2, m3 + punpcklbw m2, m3 + pmaddubsw m0, m1, m4 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m2, m5 + paddw m1, m2 + mova [rsp+gprsize+32*1], m0 + mova [rsp+gprsize+32*0], m1 + sub r3, hq + sub tlq, hq + sub r3, hq + ret + +%macro SMOOTH_2D_END 6 ; src[1-2], mul[1-2], add[1-2] + pmaddubsw m0, m%3, m%1 + pmaddubsw m1, m%4, m%2 +%ifnum %5 + paddw m0, m%5 +%else + paddw m0, %5 +%endif +%ifnum %6 + paddw m1, m%6 +%else + paddw m1, %6 +%endif + pavgw m0, m2 + pavgw m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +cglobal ipred_smooth_8bpc, 3, 7, 0, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_avx2_table + lea r6, [ipred_smooth_avx2_table] + mov wd, wm + vpbroadcastb m4, [tlq+wq] ; right + tzcnt wd, wd + mov hd, hm + mov r5, tlq + sub r5, hq + movsxd wq, [r6+wq*4] + vpbroadcastd m5, [base+pb_127_m127] + vpbroadcastb m0, [r5] ; bottom + vpbroadcastd m3, [base+pw_255] + add wq, r6 + lea v_weightsq, [base+smooth_weights+hq*2] + jmp wq +.w4: + WIN64_SPILL_XMM 12 + mova m10, [base+ipred_h_shuf] + vpbroadcastq m11, [base+smooth_weights+4*2] + mova m7, [base+ipred_v_shuf] + vpbroadcastd m8, [tlq+1] + sub tlq, 8 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m8, m0 ; top, bottom + pshufd m6, m7, q2200 + pshufd m7, m7, q3311 + pmaddubsw m9, m8, m5 + paddw m3, m8 ; 1 * top + 255 * bottom + 255 + paddw m9, m3 ; 128 * top + 129 * bottom + 255 +.w4_loop: + vpbroadcastq m1, [tlq+hq] + pshufb m1, m10 + punpcklbw m0, m1, m4 ; left, right + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 ; 127 * left - 127 * right + pmaddubsw m3, m1, m5 + paddw m2, m0 ; 128 * left + 129 * right + paddw m3, m1 + pmaddubsw m0, m11 + pmaddubsw m1, m11 + paddw m2, m0 + paddw m3, m1 + vbroadcasti128 m1, [v_weightsq] + add v_weightsq, 16 + pshufb m0, m1, m6 + pshufb m1, m7 + SMOOTH_2D_END 0, 1, 8, 8, 9, 9 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r3 ], xm1, 2 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+r3 ], xm1, 3 + lea dstq, [dstq+strideq*4] + sub hd, 8 + jg .w4_loop +.ret: + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + mova m10, [base+ipred_h_shuf] + vbroadcasti128 m11, [base+smooth_weights+8*2] + mova m7, [base+ipred_v_shuf] + vpbroadcastq m8, [tlq+1] + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m8, m0 + pshufd m6, m7, q0000 + pshufd m7, m7, q1111 + pmaddubsw m9, m8, m5 + paddw m3, m8 + paddw m9, m3 +.w8_loop: + vpbroadcastd m1, [tlq+hq] + pshufb m1, m10 + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 + pmaddubsw m3, m1, m5 + paddw m2, m0 + paddw m3, m1 + pmaddubsw m0, m11 + pmaddubsw m1, m11 + paddw m2, m0 + paddw m3, m1 + vpbroadcastq m1, [v_weightsq] + add v_weightsq, 8 + pshufb m0, m1, m6 + pshufb m1, m7 + SMOOTH_2D_END 0, 1, 8, 8, 9, 9 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+r3 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +ALIGN function_align +.w16: + SETUP_STACK_FRAME 32*4, 7, 14 + vbroadcasti128 m11, [tlq+1] + lea r3, [rsp+64*2-4] + punpcklbw m10, m11, m0 ; top, bottom + punpckhbw m11, m0 + call .prep_v + sub tlq, 2 + pmaddubsw m12, m10, m5 + pmaddubsw m13, m11, m5 + vpbroadcastd xm5, [base+pb_1] + mova m9, [base+ipred_v_shuf] + vbroadcasti128 m6, [base+smooth_weights+16*2] + vbroadcasti128 m7, [base+smooth_weights+16*3] + vperm2i128 m8, m9, m9, 0x01 + paddw m0, m10, m3 + paddw m3, m11 + paddw m12, m0 + paddw m13, m3 +.w16_loop: + vpbroadcastd m3, [tlq+hq] + vpbroadcastd m0, [r3+hq*2] + vpbroadcastd m1, [v_weightsq] + add v_weightsq, 4 + pshufb m3, m5 + punpcklbw m3, m4 ; left, right + pmaddubsw m2, m3, m6 + pmaddubsw m3, m7 + pshufb m0, m8 + pshufb m1, m9 + paddw m2, m0 + paddw m3, m0 + SMOOTH_2D_END 1, 1, 10, 11, 12, 13 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + SETUP_STACK_FRAME 32*4, 7, 11 + movu m8, [tlq+1] + lea r3, [rsp+64*2-2] + punpcklbw m7, m8, m0 + punpckhbw m8, m0 + call .prep_v + dec tlq + pmaddubsw m9, m7, m5 + pmaddubsw m10, m8, m5 + mova xm5, [base+smooth_weights+16*4] + vinserti128 m5, [base+smooth_weights+16*6], 1 + mova xm6, [base+smooth_weights+16*5] + vinserti128 m6, [base+smooth_weights+16*7], 1 + paddw m0, m7, m3 + paddw m3, m8 + paddw m9, m0 + paddw m10, m3 +.w32_loop: + vpbroadcastb m3, [tlq+hq] + punpcklbw m3, m4 + vpbroadcastw m0, [r3+hq*2] + vpbroadcastw m1, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m3, m5 + pmaddubsw m3, m6 + paddw m2, m0 + paddw m3, m0 + SMOOTH_2D_END 1, 1, 7, 8, 9, 10 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + SETUP_STACK_FRAME 32*8, 7, 16 + movu m13, [tlq+1 ] + movu m15, [tlq+33] + add r6, smooth_weights+16*15-ipred_smooth_avx2_table + lea r3, [rsp+64*2-2] + punpcklbw m12, m13, m0 + punpckhbw m13, m0 + punpcklbw m14, m15, m0 + punpckhbw m15, m0 + call .prep_v + dec tlq + pmaddubsw m0, m12, m5 + pmaddubsw m1, m13, m5 + pmaddubsw m2, m14, m5 + pmaddubsw m5, m15, m5 + mova xm8, [r6-16*7] + vinserti128 m8, [r6-16*5], 1 + mova xm9, [r6-16*6] + vinserti128 m9, [r6-16*4], 1 + mova xm10, [r6-16*3] + vinserti128 m10, [r6-16*1], 1 + mova xm11, [r6-16*2] + vinserti128 m11, [r6-16*0], 1 + lea r6, [rsp+32*4] + paddw m0, m3 + paddw m1, m3 + paddw m2, m3 + paddw m3, m5 + paddw m0, m12 + paddw m1, m13 + paddw m2, m14 + paddw m3, m15 + mova [r6+32*0], m0 + mova [r6+32*1], m1 + mova [r6+32*2], m2 + mova [r6+32*3], m3 +.w64_loop: + vpbroadcastb m5, [tlq+hq] + punpcklbw m5, m4 + vpbroadcastw m6, [r3+hq*2] + vpbroadcastw m7, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m5, m8 + pmaddubsw m3, m5, m9 + paddw m2, m6 + paddw m3, m6 + SMOOTH_2D_END 7, 7, 12, 13, [r6+32*0], [r6+32*1] + mova [dstq+32*0], m0 + pmaddubsw m2, m5, m10 + pmaddubsw m3, m5, m11 + paddw m2, m6 + paddw m3, m6 + SMOOTH_2D_END 7, 7, 14, 15, [r6+32*2], [r6+32*3] + mova [dstq+32*1], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +ALIGN function_align +.prep_v: + vpermq m2, [tlq-32*1], q3120 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + pmaddubsw m0, m1, m5 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m2, m5 + paddw m1, m2 + vpermq m2, [tlq-32*2], q3120 + mova [rsp+gprsize+32*3], m0 + mova [rsp+gprsize+32*2], m1 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + pmaddubsw m0, m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m5 + paddw m1, m2 + mova [rsp+gprsize+32*1], m0 + mova [rsp+gprsize+32*0], m1 + sub r3, hq + sub tlq, hq + sub r3, hq + ret + +cglobal ipred_z1_8bpc, 3, 8, 0, dst, stride, tl, w, h, angle, dx, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z1_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea r7, [dr_intra_derivative] + inc tlq + movsxd wq, [r6+wq*4] + add wq, r6 + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + movzx dxd, word [r7+dxq] + xor angled, 0x4ff ; d = 90 - angle + vpbroadcastd m3, [pw_512] + vpbroadcastd m4, [pw_62] + vpbroadcastd m5, [pw_64] + jmp wq +.w4: + cmp angleb, 40 + jae .w4_no_upsample + lea r3d, [angleq-1024] + sar r3d, 7 + add r3d, hd + jg .w4_no_upsample ; !enable_intra_edge_filter || h > 8 || (h == 8 && is_sm) + ALLOC_STACK -32, 8 + mova xm1, [tlq-1] + pshufb xm0, xm1, [z_upsample1] + pshufb xm1, [z_upsample2] + vpbroadcastd xm2, [pb_36_m4] ; upshifted by 2 to be able to reuse + add dxd, dxd ; pw_512 (which is already in m3) + pmaddubsw xm0, xm2 ; for rounding instead of pw_2048 + pextrd [rsp+16], xm1, 3 ; top[max_base_x] + pmaddubsw xm1, xm2 + movd xm7, dxd + mov r3d, dxd ; xpos + vpbroadcastw m7, xm7 + paddw xm1, xm0 + movq xm0, [tlq] + pmulhrsw xm1, xm3 + pslldq m6, m7, 8 + paddw xm2, xm7, xm7 + lea r2, [strideq*3] + paddw m6, m7 + packuswb xm1, xm1 + paddw m6, m2 ; xpos2 xpos3 xpos0 xpos1 + punpcklbw xm0, xm1 + psllw m7, 2 + mova [rsp], xm0 +.w4_upsample_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + vpbroadcastq m1, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vpbroadcastq m2, [rsp+r5] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + movq xm0, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + movhps xm0, [rsp+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + paddw m6, m7 ; xpos += dx + pmulhrsw m0, m3 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r2 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; w4/w8/w16 + ; The C version uses a lot of branches, but we can do all the comparisons + ; in parallel and use popcnt to get the final filter strength value. +%define base r3-z_filter_t0 + lea r3, [z_filter_t0] + movd xm0, maxbased + movd xm2, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m2, xm2 + pcmpeqb m1, m0, [base+z_filter_wh] + pand m1, m2 + mova xm2, [r3+angleq*8] ; upper ymm half zero in both cases + pcmpgtb m1, m2 + pmovmskb r5d, m1 + ret +.w4_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -16, 11 + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea maxbased, [hq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m7, [base+pb_8] + vbroadcasti128 m2, [tlq-1] + pminub m1, m7, [base+z_filter_s] + vpbroadcastd m8, [base+z_filter_k-4+r5*4+12*0] + pminub m7, [base+z_filter_s+8] + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m10, [base+z_filter_k-4+r5*4+12*2] + pshufb m0, m2, m1 + shufps m1, m7, q2121 + pmaddubsw m0, m8 + pshufb m1, m2, m1 + pmaddubsw m1, m9 + pshufb m2, m7 + pmaddubsw m2, m10 + paddw m0, m1 + paddw m0, m2 + pmulhrsw m0, m3 + mov r3d, 9 + mov tlq, rsp + cmp hd, 4 + cmovne maxbased, r3d + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [tlq], xm0 +.w4_main: + movd xm6, dxd + vpbroadcastq m0, [z_base_inc] ; base_inc << 6 + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + mov r3d, dxd ; xpos + movd xm9, maxbased + vpbroadcastw m9, xm9 + vbroadcasti128 m8, [z1_shuf_w4] + psrlw m7, 8 ; top[max_base_x] + paddw m10, m6, m6 + psubw m9, m0 ; max_base_x + vpblendd m6, m10, 0xcc + mova xm0, xm10 + paddw m6, m0 ; xpos2 xpos3 xpos0 xpos1 + paddw m10, m10 +.w4_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + vpbroadcastq m1, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vpbroadcastq m2, [tlq+r5] + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + movq xm0, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + movhps xm0, [tlq+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + pcmpgtw m1, m9, m6 ; base < max_base_x + pmulhrsw m0, m3 + paddw m6, m10 ; xpos += dx + lea r5, [dstq+strideq*2] + vpblendvb m0, m7, m0, m1 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [r5 +strideq*0], xm0 + pextrd [r5 +strideq*1], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r3d, maxbased + jb .w4_loop + packuswb xm7, xm7 + lea r6, [strideq*3] +.w4_end_loop: + movd [dstq+strideq*0], xm7 + movd [dstq+strideq*1], xm7 + movd [dstq+strideq*2], xm7 + movd [dstq+r6 ], xm7 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_end_loop +.w4_end: + RET +ALIGN function_align +.w8: + lea r3d, [angleq+216] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 8 + movu xm2, [z_filter_s+6] + mova xm0, [tlq-1] + movd xm6, hd + vinserti128 m0, [tlq+7], 1 + vpbroadcastb xm6, xm6 + vbroadcasti128 m1, [z_upsample1] + pminub xm6, xm2 + vpbroadcastd m7, [pb_36_m4] + vinserti128 m2, xm6, 1 + add dxd, dxd + pshufb m1, m0, m1 + pshufb m2, m0, m2 + movd xm6, dxd + pmaddubsw m1, m7 + pmaddubsw m2, m7 + vpbroadcastw m6, xm6 + mov r3d, dxd + psrldq m0, 1 + lea r2, [strideq*3] + paddw m7, m6, m6 + paddw m1, m2 + vpblendd m6, m7, 0xf0 + pmulhrsw m1, m3 + pslldq m2, m7, 8 + paddw m7, m7 + paddw m6, m2 + packuswb m1, m1 + punpcklbw m0, m1 + mova [rsp], m0 +.w8_upsample_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + movu xm0, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [rsp+r5], 1 + lea r5d, [r3+dxq] + shr r3d, 6 ; base2 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + punpcklqdq m1, m2, m2 ; frac0 frac1 + pmaddubsw m0, m1 + movu xm1, [rsp+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base3 + vinserti128 m1, [rsp+r5], 1 + punpckhqdq m2, m2 ; frac2 frac3 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + paddw m6, m7 + pmulhrsw m1, m3 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r2 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_upsample_loop + RET +.w8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(h+7, 15) + jmp .w8_main +.w8_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 10 + lea maxbased, [hq+7] + test angled, 0x400 + jnz .w8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w8_main ; filter_strength == 0 + popcnt r5d, r5d + movu xm2, [tlq] + pminub xm1, xm0, [base+z_filter_s+14] + vinserti128 m2, [tlq-1], 1 + vinserti128 m1, [base+z_filter_s+ 0], 1 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pminub xm0, [base+z_filter_s+22] + vinserti128 m0, [base+z_filter_s+ 8], 1 + pshufb m6, m2, m1 + pmaddubsw m6, m7 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*1] + movzx r3d, byte [tlq+15] + shufps m1, m0, q2121 + pshufb m1, m2, m1 + pmaddubsw m1, m7 + paddw m1, m6 + sub r5d, 3 + jnz .w8_3tap + ; filter_strength == 3 uses a 5-tap filter instead of a 3-tap one, + ; which also results in an awkward edge case where out[w*2] is + ; slightly different from out[max_base_x] when h > w. + vpbroadcastd m7, [z_filter_k+4*8] + movzx r2d, byte [tlq+14] + pshufb m2, m0 + pmaddubsw m2, m7 + sub r2d, r3d + lea r2d, [r2+r3*8+4] + shr r2d, 3 ; (tlq[w*2-2] + tlq[w*2-1]*7 + 4) >> 3 + mov [rsp+16], r2b + paddw m1, m2 +.w8_3tap: + pmulhrsw m1, m3 + sar r5d, 1 + mov tlq, rsp + add r5d, 17 ; w*2 + (filter_strength == 3) + cmp hd, 16 + cmovns maxbased, r5d + mov [tlq+r5], r3b + vextracti128 xm0, m1, 1 + packuswb xm0, xm1 + mova [tlq], xm0 +.w8_main: + movd xm2, dxd + vbroadcasti128 m0, [z_base_inc] + vpbroadcastw m2, xm2 + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + psrlw m7, 8 + psubw m9, m0 + mov r3d, dxd + paddw m6, m2, m2 + vpblendd m2, m6, 0xf0 +.w8_loop: + lea r5d, [r3+dxq] + shr r3d, 6 + pand m0, m4, m2 + psubw m1, m5, m0 + psllw m0, 8 + por m1, m0 + movu xm0, [tlq+r3] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [tlq+r5], 1 + pshufb m0, m8 + pmaddubsw m0, m1 + pcmpgtw m1, m9, m2 + paddw m2, m6 + pmulhrsw m0, m3 + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + sub hd, 2 + jz .w8_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w8_loop + packuswb xm7, xm7 +.w8_end_loop: + movq [dstq+strideq*0], xm7 + movq [dstq+strideq*1], xm7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_end_loop +.w8_end: + RET +.w16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(h+15, 31) + jmp .w16_main +ALIGN function_align +.w16: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 12 + lea maxbased, [hq+15] + test angled, 0x400 + jnz .w16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .w16_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m1, [base+pb_12] + vbroadcasti128 m6, [base+z_filter_s+8] + vinserti128 m2, m6, [base+z_filter_s], 0 + vinserti128 m6, [base+z_filter_s+16], 1 + mova xm10, [tlq-1] + vinserti128 m10, [tlq+3], 1 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*0] + vbroadcasti128 m7, [base+z_filter_s+14] + vinserti128 m8, m7, [base+z_filter_s+6], 0 + vinserti128 m7, [base+z_filter_s+22], 1 + psubw m0, m1 + movu xm11, [tlq+12] + vinserti128 m11, [tlq+16], 1 + pminub m8, m0 + pminub m7, m0 + pshufb m0, m10, m2 + shufps m2, m6, q2121 + pmaddubsw m0, m9 + pshufb m1, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m1, m9 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + movzx r3d, byte [tlq+31] + pshufb m2, m10, m2 + pmaddubsw m2, m9 + pshufb m8, m11, m8 + pmaddubsw m8, m9 + paddw m0, m2 + paddw m1, m8 + sub r5d, 3 + jnz .w16_3tap + vpbroadcastd m9, [z_filter_k+4*8] + movzx r2d, byte [tlq+30] + pshufb m10, m6 + pmaddubsw m10, m9 + pshufb m11, m7 + pmaddubsw m11, m9 + sub r2d, r3d + lea r2d, [r2+r3*8+4] + shr r2d, 3 + mov [rsp+32], r2b + paddw m0, m10 + paddw m1, m11 +.w16_3tap: + pmulhrsw m0, m3 + pmulhrsw m1, m3 + sar r5d, 1 + mov tlq, rsp + add r5d, 33 + cmp hd, 32 + cmovns maxbased, r5d + mov [tlq+r5], r3b + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [tlq], m0 +.w16_main: + movd xm6, dxd + vbroadcasti128 m0, [z_base_inc] + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + mov r3d, dxd + psubw m9, m0 + paddw m11, m6, m6 + psubw m10, m9, m3 ; 64*8 + vpblendd m6, m11, 0xf0 +.w16_loop: + lea r5d, [r3+dxq] + shr r3d, 6 ; base0 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r3+0] + movu xm1, [tlq+r3+8] + lea r3d, [r5+dxq] + shr r5d, 6 ; base1 + vinserti128 m0, [tlq+r5+0], 1 + vinserti128 m1, [tlq+r5+8], 1 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r3d, maxbased + jb .w16_loop +.w16_end_loop: + mova [dstq+strideq*0], xm7 + mova [dstq+strideq*1], xm7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_end_loop +.w16_end: + RET +ALIGN function_align +.w32: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 15 + lea r3d, [hq+31] + mov maxbased, 63 + cmp hd, 32 + cmovs maxbased, r3d + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + vbroadcasti128 m0, [pb_0to15] + sub r3d, 29 ; h+2 + movu xm13, [tlq+29] ; 32-39 + movd xm1, r3d + movu xm14, [tlq+37] ; 40-47 + sub r3d, 8 ; h-6 + vinserti128 m14, [tlq+51], 1 ; 56-63 + vpbroadcastb xm1, xm1 + mova xm11, [tlq- 1] ; 0- 7 + vinserti128 m11, [tlq+13], 1 ; 16-23 + movd xm2, r3d + movu xm12, [tlq+ 5] ; 8-15 + vinserti128 m12, [tlq+19], 1 ; 24-31 + pminub xm1, xm0 ; clip 32x8 + mova m7, [z_filter_s+0] + pshufb xm13, xm1 + vpbroadcastd m1, [pb_12] + vpbroadcastb xm2, xm2 + vinserti128 m13, [tlq+43], 1 ; 48-55 + vinserti128 m8, m7, [z_filter_s+4], 1 + vpblendd m2, m1, 0xf0 + vinserti128 m7, [z_filter_s+12], 0 + pminub m2, m0 ; clip 32x16 and 32x(32|64) + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m14, m2 + pshufb m0, m11, m8 + shufps m8, m7, q1021 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m8 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m8 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m8 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m7 + pmaddubsw m12, m9 + movzx r3d, byte [tlq+63] + movzx r2d, byte [tlq+62] + paddw m0, m11 + paddw m2, m12 + pshufb m13, m7 + pmaddubsw m13, m9 + pshufb m14, m7 + pmaddubsw m14, m9 + paddw m1, m13 + paddw m6, m14 + sub r2d, r3d + lea r2d, [r2+r3*8+4] ; edge case for 32x64 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + shr r2d, 3 + mov [rsp+64], r2b + mov tlq, rsp + mov [tlq+65], r3b + mov r3d, 65 + cmp hd, 64 + cmove maxbased, r3d + packuswb m0, m2 + packuswb m1, m6 + mova [tlq+ 0], m0 + mova [tlq+32], m1 +.w32_main: + movd xm6, dxd + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m6, xm6 + movd xm9, maxbased + vbroadcasti128 m8, [z_filter_s+2] + vpbroadcastw m9, xm9 + mov r5d, dxd + psubw m9, [z_base_inc] + mova m11, m6 + psubw m10, m9, m3 ; 64*8 +.w32_loop: + mov r3d, r5d + shr r3d, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu m0, [tlq+r3+0] + movu m1, [tlq+r3+8] + add r5d, dxd + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [dstq], m0 + dec hd + jz .w32_end + add dstq, strideq + cmp r5d, maxbased + jb .w32_loop + test hb, 1 + jz .w32_end_loop + mova [dstq], m7 + add dstq, strideq + dec hd + jz .w32_end +.w32_end_loop: + mova [dstq+strideq*0], m7 + mova [dstq+strideq*1], m7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_end_loop +.w32_end: + RET +ALIGN function_align +.w64: + %assign stack_offset org_stack_offset + ALLOC_STACK -128, 16 + lea maxbased, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + mova xm11, [tlq- 1] ; 0- 7 + vinserti128 m11, [tlq+13], 1 ; 16-23 + movu xm12, [tlq+ 5] ; 8-15 + vinserti128 m12, [tlq+19], 1 ; 24-31 + mova m7, [z_filter_s+0] + vinserti128 m8, m7, [z_filter_s+4], 1 + vinserti128 m7, [z_filter_s+12], 0 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + movu xm13, [tlq+29] ; 32-39 + vinserti128 m13, [tlq+43], 1 ; 48-55 + movu xm14, [tlq+37] ; 40-47 + vinserti128 m14, [tlq+51], 1 ; 56-63 + pshufb m0, m11, m8 + shufps m8, m7, q1021 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + shufps m15, m8, m7, q2121 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m15 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m10, [z_filter_k+4*2+12*2] + pshufb m11, m15 + pmaddubsw m11, m10 + pshufb m12, m7 + pmaddubsw m12, m10 + pshufb m13, m7 + pmaddubsw m13, m10 + pshufb m14, m7 + pmaddubsw m14, m10 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + movu xm11, [tlq+ 61] ; 64- 71 + vinserti128 m11, [tlq+ 75], 1 ; 80- 87 + movu xm12, [tlq+ 69] ; 72- 79 + vinserti128 m12, [tlq+ 83], 1 ; 88- 95 + movu xm13, [tlq+ 93] ; 96-103 + vinserti128 m13, [tlq+107], 1 ; 112-119 + movu xm14, [tlq+101] ; 104-111 + vinserti128 m14, [tlq+115], 1 ; 120-127 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + lea r3d, [hq-20] + mov tlq, rsp + packuswb m0, m2 + packuswb m1, m6 + vpbroadcastd xm2, [pb_14] + vbroadcasti128 m6, [pb_0to15] + mova [tlq+32*0], m0 + mova [tlq+32*1], m1 + movd xm0, r3d + vpbroadcastd m1, [pb_12] + vpbroadcastb m0, xm0 + paddb m0, m2 + pminub m0, m6 ; clip 64x16 and 64x32 + pshufb m12, m0 + pminub m1, m6 ; clip 64x64 + pshufb m14, m1 + pshufb m0, m11, m7 + pmaddubsw m0, m10 + pshufb m2, m12, m7 + pmaddubsw m2, m10 + pshufb m1, m13, m7 + pmaddubsw m1, m10 + pshufb m6, m14, m7 + pmaddubsw m6, m10 + pshufb m7, m11, m15 + pmaddubsw m7, m9 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m0, m7 + pshufb m7, m13, m15 + pmaddubsw m7, m9 + paddw m2, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m1, m7 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m8 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + packuswb m0, m2 + packuswb m1, m6 + mova [tlq+32*2], m0 + mova [tlq+32*3], m1 +.w64_main: + movd xm12, dxd + vpbroadcastb m7, [tlq+maxbaseq] + lea r3d, [dxq-64] + shl maxbased, 6 + vpbroadcastw m12, xm12 + sub r3d, maxbased + vbroadcasti128 m8, [z_filter_s+2] + movd xm6, r3d + mov r5d, dxd + mova m10, [pb_1to32] + vpbroadcastd m11, [pb_32] + vpbroadcastw m6, xm6 +.w64_loop: + mov r3d, r5d + shr r3d, 6 + movu m0, [tlq+r3+ 0] + movu m1, [tlq+r3+ 8] + pand m2, m4, m6 + psubw m9, m5, m2 + psllw m2, 8 + por m9, m2 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + psraw m2, m6, 6 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packsswb m2, m2 + paddb m2, m10 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [dstq+ 0], m0 + movu m0, [tlq+r3+32] + movu m1, [tlq+r3+40] + add r5d, dxd + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + paddb m2, m11 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + paddw m6, m12 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [dstq+32], m0 + dec hd + jz .w64_end + add dstq, strideq + cmp r5d, maxbased + jb .w64_loop +.w64_end_loop: + mova [dstq+ 0], m7 + mova [dstq+32], m7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET + +cglobal ipred_z2_8bpc, 3, 10, 16, 224, dst, stride, tl, w, h, angle, dx, dy +%define base r9-z_filter_t0 + lea r9, [ipred_z2_avx2_table] + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + lea dxq, [dr_intra_derivative-90] + movsxd wq, [r9+wq*4] + movzx dyd, angleb + xor angled, 0x400 + mov r8, dxq + sub dxq, dyq + add wq, r9 + add r9, z_filter_t0-ipred_z2_avx2_table + mova m2, [tlq-64] + mova m0, [tlq-32] + mova m1, [tlq] + and dyd, ~1 + and dxq, ~1 + movzx dyd, word [r8+dyq] ; angle - 90 + movzx dxd, word [dxq+270] ; 180 - angle + vpbroadcastd m13, [base+pw_512] + vpbroadcastd m14, [base+pw_62] + vpbroadcastd m15, [base+pw_64] + mova [rsp+ 0], m2 + mova [rsp+32], m0 + mova [rsp+64], m1 + neg dxd + neg dyd + jmp wq +.w4: + vpbroadcastq m6, [base+z2_base_inc] ; base_inc << 6 + vbroadcasti128 m10, [base+z1_shuf_w4] + vbroadcasti128 m11, [base+z2_shuf_h4] + lea r2d, [dxq+(65<<6)] ; xpos + movd xm5, dyd + mov r8d, (63-4)<<6 + mov dyq, -4 + pshuflw xm5, xm5, q0000 + pmullw xm5, [base+z2_ymul] + test angled, 0x400 + jnz .w4_main ; !enable_intra_edge_filter + lea r3d, [hq+2] + add angled, 1022 + shl r3d, 6 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm3, [base+pb_4] + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + call .filter_strength + jmp .w4_filter_left +ALIGN function_align +.filter_strength: + movd xm8, r3d + mov r3d, angled + movd xm7, angled + vpbroadcastb m8, xm8 + shr r3d, 8 ; is_sm << 1 + vpbroadcastb m7, xm7 + pcmpeqb m8, [base+z_filter_wh] + mova xm9, [r9+r3*8] + pand m0, m8, m7 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + ret +ALIGN function_align +.upsample_above: ; w4/w8 + pshufb xm2, xm1, [base+z_upsample1-2] + pminub xm3, [base+z_filter_s+4] + vpbroadcastd xm4, [base+pb_36_m4] + vbroadcasti128 m10, [base+pb_0to15] + pshufb xm3, xm1, xm3 + pmaddubsw xm2, xm4 + pmaddubsw xm3, xm4 + lea r2d, [r2+dxq+(1<<6)] + add dxd, dxd + paddw xm2, xm3 + pmulhrsw xm2, xm13 + sub r8d, 3<<6 + paddw m6, m6 + packuswb xm2, xm2 + punpcklbw xm1, xm2 + mova [rsp+gprsize+64], xm1 + ret +ALIGN function_align +.upsample_left: ; h4/h8 + mov r3d, hd + and r3d, 4 + movd xm2, [rsp+gprsize+64] + movddup xm0, [rsp+gprsize+56] + movd xm1, r3d + palignr xm2, xm0, 1 + vpbroadcastb xm1, xm1 + pshufb xm2, [base+z_filter_s+18] + vpbroadcastd xm3, [base+pb_36_m4] + pmaxub xm1, [base+z_upsample1-2] + pshufb xm1, xm0, xm1 + pmaddubsw xm2, xm3 + pmaddubsw xm1, xm3 + paddw xm5, xm5 + add dyq, dyq + paddw xm1, xm2 + pmulhrsw xm1, xm13 + vbroadcasti128 m11, [base+z2_upsample] + paddw xm5, xm15 + packuswb xm1, xm1 + punpcklbw xm0, xm1 + mova [rsp+gprsize+48], xm0 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + sub angled, 1112 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w4_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm2, [base+pb_4] + pminub xm2, [base+z_filter_s] + vpbroadcastd xm0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + pshufb xm3, xm1, xm2 ; 00 01 12 23 + pshufd xm2, xm2, q0321 + pmaddubsw xm0, xm3, xm0 + pshufb xm2, xm1, xm2 ; 12 23 34 44 + pmaddubsw xm2, xm4 + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*2] + punpckhqdq xm3, xm3 ; 34 44 44 44 + pmaddubsw xm3, xm4 + movd xm4, r6m ; max_width + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw xm0, xm2 + paddw xm0, xm3 + pmulhrsw xm0, xm13 + psubb xm4, [base+pb_1to32] + psrlq xm1, 8 + packuswb xm0, xm0 + vpblendvb xm0, xm1, xm4 + movd [rsp+65], xm0 +.w4_no_filter_above: + lea r3d, [hq+2] + add angled, 973 ; angle + 883 + shl r3d, 6 + test r3d, angled + jz .w4_upsample_left ; angle <= 140 || h > 8 || (is_sm && h == 8) + vpbroadcastd xm0, [base+pb_90] + psubb xm0, xm7 ; 180 - angle + pand xm0, xm8 ; reuse from previous filter_strength call + pcmpgtb xm0, xm9 + pmovmskb r3d, xm0 +.w4_filter_left: + test r3d, r3d + jz .w4_main + popcnt r3d, r3d + mov r5d, 10 + cmp hd, 16 + movu xm2, [rsp+49] + vinserti128 m2, [rsp+43], 1 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + vinserti128 m3, m1, [z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 55 55 56 67 78 89 9a ab + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + vpbroadcastb m0, xm0 + pmaxub m0, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*0] + pshufb m0, m2, m0 + pmaddubsw m0, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*1] + pshufb m1, m2, m1 + pmaddubsw m1, m3 + vpbroadcastd m3, [base+z_filter_k-4+r3*4+12*2] + pshufb m2, m4 + pmaddubsw m2, m3 + movd xm4, r7m ; max_height + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + psubb xm4, [base+pb_16to1] + paddw m1, m0 + paddw m1, m2 + pmulhrsw m1, m13 + vextracti128 xm0, m1, 1 + packuswb xm0, xm1 + vpblendvb xm0, [rsp+48], xm4 + mova [rsp+48], xm0 + jmp .w4_main +.w4_upsample_left: + call .upsample_left +.w4_main: + movd xm0, dxd + mova m12, [base+z2_y_shuf_h4] + lea r5, [rsp+56] ; left-7 + vpbroadcastw m0, xm0 + lea r9, [strideq*3] + psraw xm1, xm5, 6 + pand xm5, xm14 ; frac_y + pxor xm2, xm2 + paddw m7, m0, m0 + psubw xm4, xm2, xm1 ; base_y + vpblendd m0, m7, 0xcc + mova xm1, xm7 + punpcklwd xm4, xm2 + paddw m0, m1 ; xpos2 xpos3 xpos0 xpos1 + psubw xm1, xm15, xm5 ; 64-frac_y + psllw xm5, 8 + paddw m7, m7 + paddw m6, m0 + por xm5, xm1 ; 64-frac_y, frac_y + vpbroadcastq m5, xm5 +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + vpbroadcastq m1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vpbroadcastq m2, [rsp+r3] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movq xm0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movhps xm0, [rsp+r3] + vpblendd m1, m2, 0xc0 + pand m2, m14, m6 ; frac_x + vpblendd m0, m1, 0xf0 + psubw m1, m15, m2 ; 64-frac_x + psllw m2, 8 + pshufb m0, m10 + por m1, m2 ; 64-frac_x, frac_x + pmaddubsw m0, m1 + cmp r3d, 64 + jge .w4_toponly + mova m1, m7 ; arbitrary negative value + vpgatherdq m3, [r5+xm4], m1 + pshufb m1, m3, m11 + vpermd m1, m12, m1 + pmaddubsw m1, m5 + psraw m2, m6, 15 ; base_x < topleft + vpblendvb m0, m1, m2 +.w4_toponly: + pmulhrsw m0, m13 + paddw m6, m7 ; xpos += dx + add r5, dyq + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r9 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + sub hd, 4 + jz .w4_end + lea dstq, [dstq+strideq*4] + cmp r2d, r8d + jge .w4_loop +.w4_leftonly_loop: + mova m1, m7 + vpgatherdq m2, [r5+xm4], m1 + add r5, dyq + pshufb m0, m2, m11 + vpermd m0, m12, m0 + pmaddubsw m0, m5 + pmulhrsw m0, m13 + packuswb m0, m0 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*2], xm0 + pextrd [dstq+r9 ], xm0, 1 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + RET +.w8: + vbroadcasti128 m6, [base+z2_base_inc] ; base_inc << 6 + movd xm5, dyd + vbroadcasti128 m10, [base+z_filter_s+2] + vbroadcasti128 m11, [base+z2_shuf_h4] + lea r2d, [dxq+(65<<6)] ; xpos + vpbroadcastw xm5, xm5 + mov r8d, (63-8)<<6 + mov dyq, -4 + pmullw xm5, [base+z2_ymul] + test angled, 0x400 + jnz .w8_main + lea r3d, [angleq+126] + mov r3b, hb + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + vpbroadcastd xm3, [base+pb_8] + movhps [rsp+80], xm1 + call .upsample_above + sub angled, 53 ; angle - 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + call .filter_strength + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + sub angled, 90 ; angle - 90 + call .filter_strength + test r3d, r3d + jz .w8_no_filter_above + popcnt r3d, r3d + vpbroadcastd xm3, [base+pb_8] + pminub xm3, [base+z_filter_s+8] + vpbroadcastd xm0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*1] + pshufb xm2, xm1, [base+z_filter_s] ; 00 01 12 23 34 45 56 67 + pmaddubsw xm0, xm2, xm0 + pshufb xm3, xm1, xm3 ; 34 45 56 67 78 88 88 88 + shufps xm2, xm3, q2121 ; 12 23 34 45 56 67 78 88 + pmaddubsw xm2, xm4 + vpbroadcastd xm4, [base+z_filter_k-4+r3*4+12*2] + pmaddubsw xm3, xm4 + movd xm4, r6m ; max_width + pminuw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw xm0, xm2 + paddw xm0, xm3 + pmulhrsw xm0, xm13 + psubb xm4, [base+pb_1to32] + psrldq xm1, 1 + packuswb xm0, xm0 + vpblendvb xm0, xm1, xm4 + movq [rsp+65], xm0 +.w8_no_filter_above: + lea r3d, [angleq-51] + mov r3b, hb + cmp r3d, 8 + jbe .w8_upsample_left ; angle > 140 && h <= 8 && !is_sm + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 +.w8_filter_left: + test r3d, r3d + jz .w8_main + popcnt r3d, r3d + vpbroadcastd m7, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m8, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m9, [base+z_filter_k-4+r3*4+12*2] + cmp hd, 32 + jne .w8_filter_left_h16 + movu xm2, [rsp+27] + vinserti128 m2, [rsp+35], 1 + vpbroadcastd xm0, [base+pb_5] + vbroadcasti128 m3, [base+z_filter_s+ 8] + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + pmaxub m3, m0 + pshufb m3, m2, m3 + pmaddubsw m3, m7 + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + paddw m3, m1 + paddw m3, m2 + pmulhrsw m3, m13 + jmp .w8_filter_left_top16 +.w8_filter_left_h16: + mov r5d, 10 + cmp hd, 16 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vpbroadcastb m0, xm0 +.w8_filter_left_top16: + vbroadcasti128 m1, [base+z_filter_s+12] + vinserti128 m2, m1, [base+z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 55 55 56 67 78 89 9a ab + vbroadcasti128 m4, [base+z_filter_s+16] + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + pmaxub m0, m2 + movu xm2, [rsp+49] + vinserti128 m2, [rsp+43], 1 + pshufb m0, m2, m0 + pmaddubsw m0, m7 + movd xm7, r7m ; max_height + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + pminsw xm7, xm15 + paddw m1, m0 + vpbroadcastb m7, xm7 + paddw m1, m2 + pmulhrsw m1, m13 + psubb m7, [base+pb_32to1] + packuswb m3, m1 + vpermq m3, m3, q1320 + vpblendvb m3, [rsp+32], m7 + mova [rsp+32], m3 + jmp .w8_main +.w8_upsample_left: + call .upsample_left +.w8_main: + movd xm3, dxd + lea r5, [rsp+56] ; left-7 + pshufd xm1, xm5, q3120 + pand xm5, xm14 + vpbroadcastw m3, xm3 + pxor xm0, xm0 + psubw xm2, xm15, xm5 + psraw xm1, 6 + lea r9, [strideq*3] + paddw m7, m3, m3 + psubw xm9, xm0, xm1 ; base_y + psllw xm5, 8 + punpcklwd xm8, xm9, xm0 ; base_y 0, 1, 4, 5 + vpblendd m3, m7, 0xf0 ; xpos0 xpos1 + por xm5, xm2 ; 64-frac_y, frac_y + punpckhwd xm9, xm0 ; base_y 2, 3, 6, 7 + paddw m6, m3 + vinserti128 m12, m5, xm5, 1 +.w8_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + vinserti128 m0, [rsp+r3], 1 + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movu xm1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + vinserti128 m1, [rsp+r3], 1 + pand m2, m14, m6 + paddsw m4, m6, m7 + psubw m5, m15, m2 + psllw m2, 8 + pshufb m0, m10 + por m2, m5 + pmaddubsw m0, m2 + pand m2, m14, m4 + psubw m5, m15, m2 + psllw m2, 8 + pshufb m1, m10 + por m2, m5 + pmaddubsw m1, m2 + cmp r3d, 64 + jge .w8_toponly + mova m5, m7 + vpgatherdq m3, [r5+xm9], m7 + mova m7, m5 + vpgatherdq m2, [r5+xm8], m5 + pshufb m3, m11 + pshufb m2, m11 + punpckldq m5, m2, m3 ; a0 b0 c0 d0 a1 b1 c1 d1 e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m2, m3 ; a2 b2 c2 d2 a3 b3 c3 d3 e2 f2 g2 h2 e3 f3 g3 h3 + vpermq m5, m5, q3120 ; y0 y1 + vpermq m2, m2, q3120 ; y2 y3 + pmaddubsw m5, m12 + pmaddubsw m2, m12 + psraw m6, 15 ; base_x < topleft + vpblendvb m0, m5, m6 + psraw m3, m4, 15 + vpblendvb m1, m2, m3 +.w8_toponly: + pmulhrsw m0, m13 + pmulhrsw m1, m13 + paddw m6, m4, m7 ; xpos += dx + add r5, dyq + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r9 ], xm1 + sub hd, 4 + jz .w8_end + lea dstq, [dstq+strideq*4] + cmp r2d, r8d + jge .w8_loop +.w8_leftonly_loop: + mova m0, m7 + vpgatherdq m5, [r5+xm9], m7 + mova m7, m0 + vpgatherdq m3, [r5+xm8], m0 + add r5, dyq + pshufb m2, m5, m11 + pshufb m1, m3, m11 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 + pmaddubsw m0, m12 + pmaddubsw m1, m12 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*2], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+r9 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_leftonly_loop +.w8_end: + RET +.w16: + mov r8d, hd + test angled, 0x400 + jnz .w16_main + lea r3d, [hq+15] + sub angled, 90 + call .filter_strength + test r3d, r3d + jz .w16_no_filter_above + popcnt r3d, r3d + vbroadcasti128 m6, [tlq+1] + mova xm2, [base+z_filter_s] + vinserti128 m2, [base+z_filter_s+14], 1 ; 00 01 12 23 34 45 56 67 67 78 89 9a ab bc cd de + movu xm3, [base+z_filter_s+8] + vinserti128 m3, [base+z_filter_s+22], 1 ; 34 45 56 67 78 89 9a ab ab bc cd de ef ff ff ff + vpblendd m1, m6, 0xf0 + vpbroadcastd m0, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m4, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m5, [base+z_filter_k-4+r3*4+12*2] + pshufb m2, m1, m2 + pshufb m1, m3 + pmaddubsw m0, m2, m0 + shufps m2, m1, q2121 ; 12 23 34 45 56 67 78 89 89 9a ab bc cd de ef ff + pmaddubsw m2, m4 + pmaddubsw m1, m5 + movd xm4, r6m ; max_width + pminsw xm4, xm15 + vpbroadcastb xm4, xm4 + paddw m0, m2 + paddw m0, m1 + pmulhrsw m0, m13 + psubb xm4, [base+pb_1to32] + vextracti128 xm2, m0, 1 + packuswb xm0, xm2 + vpblendvb xm0, xm6, xm4 + movu [rsp+65], xm0 +.w16_no_filter_above: + vpbroadcastd m0, [base+pb_90] + psubb m0, m7 + pand m0, m8 + pcmpgtb m0, m9 + pmovmskb r3d, m0 + test r3d, r3d + jz .w16_main + popcnt r3d, r3d + vpbroadcastd m7, [base+z_filter_k-4+r3*4+12*0] + vpbroadcastd m8, [base+z_filter_k-4+r3*4+12*1] + vpbroadcastd m9, [base+z_filter_k-4+r3*4+12*2] +.w16_filter_left: + movd xm6, r7m ; max_height + pminsw xm6, xm15 + vpbroadcastb m6, xm6 + cmp hd, 32 + jl .w16_filter_left_h16 + vpbroadcastd xm0, [base+pb_5] + vbroadcasti128 m10, [base+z_filter_s+ 8] + vbroadcasti128 m11, [base+z_filter_s+12] + vbroadcasti128 m12, [base+z_filter_s+16] + je .w16_filter_left_h32 + movu m3, [tlq-69] + movu m5, [tlq-61] + pmaxub m1, m10, m0 + pshufb m1, m3, m1 + pmaddubsw m1, m7 + pshufb m2, m3, m11 + pmaddubsw m2, m8 + pshufb m3, m12 + pmaddubsw m3, m9 + paddw m1, m2 + pshufb m2, m5, m10 + pmaddubsw m2, m7 + pshufb m4, m5, m11 + pmaddubsw m4, m8 + pshufb m5, m12 + pmaddubsw m5, m9 + paddw m1, m3 + vpbroadcastd m3, [base+pb_32] + paddb m3, [base+pb_32to1] + paddw m2, m4 + paddw m2, m5 + pmulhrsw m1, m13 + pmulhrsw m2, m13 + psubb m3, m6, m3 + packuswb m1, m2 + vpblendvb m1, [tlq-64], m3 + mova [rsp], m1 + jmp .w16_filter_left_top32 +.w16_filter_left_h32: + pmaxub m10, m0 +.w16_filter_left_top32: + movu xm2, [tlq-37] + vinserti128 m2, [tlq-29], 1 + pshufb m3, m2, m10 + pshufb m1, m2, m11 + pshufb m2, m12 + pmaddubsw m3, m7 + pmaddubsw m1, m8 + pmaddubsw m2, m9 + paddw m3, m1 + paddw m3, m2 + pmulhrsw m3, m13 + jmp .w16_filter_left_top16 +.w16_filter_left_h16: + mov r5d, 10 + cmp hd, 16 + cmovs r5d, hd + xor r5d, 15 ; h == 16 ? 5 : 15 - h + movd xm0, r5d + vpbroadcastb m0, xm0 +.w16_filter_left_top16: + movu xm2, [tlq-15] + vinserti128 m2, [tlq-21], 1 + vbroadcasti128 m1, [base+z_filter_s+12] + vbroadcasti128 m4, [base+z_filter_s+16] + vinserti128 m5, m1, [base+z_filter_s+8], 1 ; 56 67 78 89 9a ab bc cd 34 45 56 67 78 89 9a ab + vpblendd m1, m4, 0x0f ; 78 89 9a ab bc cd de ef 56 67 78 89 9a ab bc cd + vinserti128 m4, [base+z_filter_s+20], 0 ; 9a ab bc cd de ef ff ff 78 89 9a ab bc cd de ef + pmaxub m0, m5 + pshufb m0, m2, m0 + pmaddubsw m0, m7 + pshufb m1, m2, m1 + pmaddubsw m1, m8 + pshufb m2, m4 + pmaddubsw m2, m9 + psubb m6, [base+pb_32to1] + paddw m1, m0 + paddw m1, m2 + pmulhrsw m1, m13 + packuswb m3, m1 + vpermq m3, m3, q1320 + vpblendvb m3, [tlq-32], m6 + mova [rsp+32], m3 +.w16_main: + movd xm1, dyd + vbroadcasti128 m10, [base+z_filter_s+2] + movd xm7, dxd + vbroadcasti128 m11, [base+z2_shuf_h2] + vpbroadcastw m1, xm1 + vpbroadcastw m7, xm7 + mov r7, dstq + pmullw m0, m1, [base+z2_ymul] + psllw xm1, 4 + paddw m6, m7, [base+z2_base_inc] + lea r9d, [dxq+(65<<6)] ; xpos + movd [rsp+156], xm1 +.w16_loop0: + mov r2d, r9d + mova [rsp+160], m0 + lea r5, [rsp+60] ; left-3 + mova [rsp+192], m6 + pxor m1, m1 + psraw m2, m0, 6 + pand m0, m14 + psubw m9, m1, m2 ; base_y + psubw m12, m15, m0 + punpcklwd m8, m9, m1 ; base_y 0, 1, 2, 3, 8, 9, 10, 11 + psllw m0, 8 + punpckhwd m9, m1 ; base_y 4, 5, 6, 7, 12, 13, 14, 15 + por m12, m0 ; 64-frac_y, frac_y +.w16_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movu xm0, [rsp+r2] + vinserti128 m0, [rsp+r2+8], 1 + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movu xm1, [rsp+r3] + vinserti128 m1, [rsp+r3+8], 1 + pand m2, m14, m6 + paddsw m5, m6, m7 + psubw m3, m15, m2 + psllw m2, 8 + pshufb m0, m10 + por m2, m3 + pmaddubsw m0, m2 + pand m2, m14, m5 + psubw m3, m15, m2 + psllw m2, 8 + pshufb m1, m10 + por m2, m3 + pmaddubsw m1, m2 + cmp r3d, 64 + jge .w16_toponly + punpckhwd m2, m5, m5 ; mask out unnecessary loads + vpgatherdd m4, [r5+m9], m2 + punpcklwd m2, m5, m5 + vpgatherdd m3, [r5+m8], m2 + pshufb m4, m11 ; e0 f0 g0 h0 e1 f1 g1 h1 m0 n0 o0 p0 m1 n1 o1 p1 + pshufb m3, m11 ; a0 b0 c0 d0 a1 b1 c1 d1 i0 j0 k0 l0 i1 j1 k1 l1 + punpcklqdq m2, m3, m4 ; y0 + punpckhqdq m3, m4 ; y1 + pmaddubsw m2, m12 + pmaddubsw m3, m12 + psraw m6, 15 ; base_x < topleft + vpblendvb m0, m2, m6 + psraw m6, m5, 15 + vpblendvb m1, m3, m6 +.w16_toponly: + pmulhrsw m0, m13 + pmulhrsw m1, m13 + paddw m6, m5, m7 ; xpos += dx + sub r5, 2 + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + sub hd, 2 + jz .w16_end + lea dstq, [dstq+strideq*2] + cmp r2d, (63-16)<<6 + jge .w16_loop +.w16_leftonly_loop: + mova m0, m7 + vpgatherdd m4, [r5+m9], m7 + mova m7, m0 + vpgatherdd m3, [r5+m8], m0 + sub r5, 2 + pshufb m2, m4, m11 + pshufb m1, m3, m11 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pmaddubsw m0, m12 + pmaddubsw m1, m12 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_leftonly_loop +.w16_end: + sub r8d, 1<<8 + jl .w16_ret + vpbroadcastd m0, [rsp+156] + paddw m0, [rsp+160] ; base_y += 16*dy + paddw m6, m13, [rsp+192] + add r7, 16 + add r9d, 16<<6 + movzx hd, r8b + mov dstq, r7 + paddw m6, m13 ; base_x += 16*64 + jmp .w16_loop0 +.w16_ret: + RET +.w32: + mova m2, [tlq+32] + lea r8d, [hq+(1<<8)] + mova [rsp+96], m2 + test angled, 0x400 + jnz .w16_main + vpbroadcastd m7, [base+z_filter_k+4*2+12*0] + vpbroadcastd m8, [base+z_filter_k+4*2+12*1] + vpbroadcastd m9, [base+z_filter_k+4*2+12*2] + mova xm5, [base+z_filter_s] + vinserti128 m5, [base+z_filter_s+10], 1 ; 00 01 12 23 34 45 56 67 45 56 67 78 89 9a ab bc + vinserti128 m1, [tlq+11], 1 + movu xm6, [base+z_filter_s+12] + vinserti128 m6, [base+z_filter_s+22], 1 ; 56 67 78 89 9a ab bc cd ab bc cd de ef ff ff ff + movu xm3, [tlq+ 6] + vinserti128 m3, [tlq+17], 1 + movd xm0, r6m ; max_width + pminsw xm0, xm15 + vpbroadcastb m10, xm0 +.w32_filter_above: + pshufb m0, m1, m5 + shufps m4, m5, m6, q1021 ; 12 23 34 45 56 67 78 89 67 78 89 9a ab bc cd de + pmaddubsw m0, m7 + pshufb m2, m1, m4 + shufps m5, m6, q2132 ; 34 45 56 67 78 89 9a ab 89 9a ab bc cd de ef ff + pmaddubsw m2, m8 + pshufb m1, m5 + pmaddubsw m1, m9 + paddw m0, m2 + paddw m0, m1 + pshufb m1, m3, m4 + pmaddubsw m1, m7 + pshufb m2, m3, m5 + pmaddubsw m2, m8 + pshufb m3, m6 + pmaddubsw m3, m9 + paddw m1, m2 + paddw m1, m3 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + psubb m10, [base+pb_1to32] + packuswb m0, m1 + vpblendvb m0, [tlq+1], m10 + movu [rsp+65], m0 + jmp .w16_filter_left +.w64: + mova m2, [tlq+32] + mov r3d, [tlq+64] + lea r8d, [hq+(3<<8)] + mova [rsp+ 96], m2 + mov [rsp+128], r3d + test angled, 0x400 + jnz .w16_main + vpbroadcastd m7, [base+z_filter_k+4*2+12*0] + vpbroadcastd m8, [base+z_filter_k+4*2+12*1] + vpbroadcastd m9, [base+z_filter_k+4*2+12*2] + movu xm6, [base+z_filter_s+ 4] + vinserti128 m6, [base+z_filter_s+10], 1 ; 12 23 34 45 56 67 78 89 45 56 67 78 89 9a ab bc + movu xm3, [tlq+30] + vinserti128 m3, [tlq+43], 1 + movu xm5, [base+z_filter_s+16] + vinserti128 m5, [base+z_filter_s+22], 1 ; 78 89 9a ab bc cd de ef ab bc cd de ef ff ff ff + pshufb m0, m3, m6 + shufps m4, m6, m5, q1021 ; 34 45 56 67 78 89 9a ab 67 78 89 9a ab bc cd de + pmaddubsw m0, m7 + pshufb m2, m3, m4 + shufps m6, m5, q2132 ; 56 67 78 89 9a ab bc cd 89 9a ab bc cd de ef ff + pmaddubsw m2, m8 + pshufb m3, m6 + pmaddubsw m3, m9 + paddw m0, m2 + paddw m0, m3 + movu xm2, [tlq+36] + vinserti128 m2, [tlq+49], 1 + pshufb m4, m2, m4 + pmaddubsw m4, m7 + pshufb m3, m2, m6 + pmaddubsw m3, m8 + pshufb m2, m5 + pmaddubsw m2, m9 + movd xm5, r6m ; max_width + pminsw xm5, xm15 + vpbroadcastb m10, xm5 + paddw m3, m4 + paddw m2, m3 + vpbroadcastd m3, [base+pb_32] + pmulhrsw m0, m13 + pmulhrsw m2, m13 + mova xm5, [base+z_filter_s] + vinserti128 m5, [base+z_filter_s+6], 1 + psubb m3, m10, m3 + psubb m3, [base+pb_1to32] + vinserti128 m1, [tlq+13], 1 + packuswb m0, m2 + vpblendvb m0, [tlq+33], m3 + movu xm3, [tlq+ 6] + vinserti128 m3, [tlq+19], 1 + movu [rsp+97], m0 + jmp .w32_filter_above + +cglobal ipred_z3_8bpc, 4, 9, 0, dst, stride, tl, w, h, angle, dy, org_w, maxbase + %assign org_stack_offset stack_offset + lea r6, [ipred_z3_avx2_table] + tzcnt hd, hm + movifnidn angled, anglem + lea r7, [dr_intra_derivative+45*2-1] + dec tlq + movsxd hq, [r6+hq*4] + sub angled, 180 + add hq, r6 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + movzx dyd, word [r7+dyq] + vpbroadcastd m3, [pw_512] + vpbroadcastd m4, [pw_62] + vpbroadcastd m5, [pw_64] + mov org_wd, wd + jmp hq +.h4: + lea r7, [strideq*3] + cmp angleb, 40 + jae .h4_no_upsample + lea r4d, [angleq-1024] + sar r4d, 7 + add r4d, wd + jg .h4_no_upsample ; !enable_intra_edge_filter || w > 8 || (w == 8 && is_sm) + ALLOC_STACK -32, 9 + movu xm8, [tlq-7] + pshufb xm0, xm8, [z_upsample1-4] + vpbroadcastb xm2, xm8 + pshufb xm1, xm8, [z_filter_s+2] + mova [rsp+16], xm2 ; top[max_base_y] + vpbroadcastd xm2, [pb_36_m4] + add dyd, dyd + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + movd xm7, dyd + mov r2d, dyd + vpbroadcastw m7, xm7 + paddw xm1, xm0 + pmulhrsw xm1, xm3 + pslldq m6, m7, 8 + paddw xm2, xm7, xm7 + paddw m6, m7 + packuswb xm1, xm1 + paddw m6, m2 + punpcklbw xm1, xm8 + mova xm8, [z_transpose4] + psllw m7, 2 + pshufb xm1, [pb_15to0] + mova [rsp], xm1 +.h4_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 + vpbroadcastq m1, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 + vpbroadcastq m2, [rsp+r4] + lea r4d, [r2+dyq] + shr r2d, 6 + movq xm0, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 + movhps xm0, [rsp+r4] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 + psllw m2, 8 + por m1, m2 + pmaddubsw m0, m1 + paddw m6, m7 + pmulhrsw m0, m3 + vextracti128 xm1, m0, 1 + packuswb xm1, xm0 + pshufb xm1, xm8 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r7 ], xm1, 3 + add dstq, 4 + sub wd, 4 + jg .h4_upsample_loop + RET +ALIGN function_align +.filter_strength: ; h4/h8/h16 +%define base r4-z_filter_t0 + lea r4, [z_filter_t0] + movd xm0, maxbased + movd xm2, angled + shr angled, 8 ; is_sm << 1 + vpbroadcastb m0, xm0 + vpbroadcastb m2, xm2 + pcmpeqb m1, m0, [base+z_filter_wh] + pand m1, m2 + mova xm2, [r4+angleq*8] + pcmpgtb m1, m2 + pmovmskb r5d, m1 + ret +.h4_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -16, 12 + mov maxbased, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea maxbased, [wq+3] + call .filter_strength + mov maxbased, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m7, [base+pb_7] + vbroadcasti128 m2, [tlq-14] + pmaxub m1, m7, [base+z_filter_s-4] + vpbroadcastd m8, [base+z_filter_k-4+r5*4+12*0] + pmaxub m7, [base+z_filter_s+4] + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + vpbroadcastd m10, [base+z_filter_k-4+r5*4+12*2] + pshufb m0, m2, m1 + shufps m1, m7, q2121 + pmaddubsw m0, m8 + pshufb m1, m2, m1 + pmaddubsw m1, m9 + pshufb m2, m7 + pmaddubsw m2, m10 + paddw m0, m1 + paddw m0, m2 + pmulhrsw m0, m3 + mov r4d, 9 + lea tlq, [rsp+15] + cmp wd, 4 + cmovne maxbased, r4d + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [rsp], xm0 +.h4_main: + movd xm6, dyd + vpbroadcastq m0, [z_base_inc] ; base_inc << 6 + mov r4, tlq + sub tlq, 4 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] ; ypos + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf_w4] + add maxbased, 64 + vpbroadcastw m9, xm9 + psrlw m7, 8 ; top[max_base_y] + paddw m10, m6, m6 + psubw m9, m0 ; max_base_y + vpblendd m6, m10, 0xcc + mova xm0, xm10 + paddw m6, m0 ; ypos2 ypos3 ypos0 ypos1 + paddw m10, m10 + mova xm11, [z_transpose4] +.h4_loop: + lea r5, [r4+dyq] + sar r4, 6 ; base0 + vpbroadcastq m1, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 ; base1 + vpbroadcastq m2, [tlq+r5] + lea r5, [r4+dyq] + sar r4, 6 ; base2 + movq xm0, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 ; base3 + movhps xm0, [tlq+r5] + vpblendd m1, m2, 0xc0 + pand m2, m4, m6 ; frac + vpblendd m0, m1, 0xf0 + psubw m1, m5, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + pcmpgtw m1, m9, m6 ; base < max_base_y + pmulhrsw m0, m3 + paddw m6, m10 ; ypos += dy + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + packuswb xm1, xm0 + pshufb xm1, xm11 ; transpose + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r7 ], xm1, 3 + sub wd, 4 + jz .h4_end + add dstq, 4 + cmp r4d, maxbased + jg .h4_loop + packuswb xm7, xm7 +.h4_end_loop: + movd [dstq+strideq*0], xm7 + movd [dstq+strideq*1], xm7 + movd [dstq+strideq*2], xm7 + movd [dstq+r7 ], xm7 + add dstq, 4 + sub wd, 4 + jg .h4_end_loop +.h4_end: + RET +ALIGN function_align +.h8: + lea r4d, [angleq+216] + mov r4b, wb + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 8 + and r4d, 4 + mova xm0, [tlq-15] + vinserti128 m0, [tlq- 9], 1 + movd xm1, r4d + movu xm2, [z_filter_s+2] + vinserti128 m2, [z_filter_s+6], 1 + vpbroadcastb xm1, xm1 ; w & 4 + vpbroadcastd m7, [pb_36_m4] + pmaxub xm1, [z_upsample1-4] ; clip 4x8 + vinserti128 m1, [z_upsample1], 1 + add dyd, dyd + pshufb m1, m0, m1 + pshufb m2, m0, m2 + vinserti128 m0, [tlq-7], 1 + movd xm6, dyd + pmaddubsw m1, m7 + pmaddubsw m2, m7 + vpbroadcastw m6, xm6 + mov r2d, dyd + lea r5, [strideq*3] + paddw m7, m6, m6 + paddw m1, m2 + vpblendd m6, m7, 0xf0 + pmulhrsw m1, m3 + pslldq m2, m7, 8 + paddw m7, m7 + paddw m6, m2 + vbroadcasti128 m2, [pb_15to0] + packuswb m1, m1 + punpcklbw m1, m0 + pshufb m1, m2 + vextracti128 [rsp+ 0], m1, 1 + mova [rsp+16], xm1 +.h8_upsample_loop: + lea r4d, [r2+dyq] + shr r2d, 6 ; base0 + movu xm0, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base1 + vinserti128 m0, [rsp+r4], 1 + lea r4d, [r2+dyq] + shr r2d, 6 ; base2 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + punpcklqdq m1, m2, m2 ; frac0 frac1 + pmaddubsw m0, m1 + movu xm1, [rsp+r2] + lea r2d, [r4+dyq] + shr r4d, 6 ; base3 + vinserti128 m1, [rsp+r4], 1 + punpckhqdq m2, m2 ; frac2 frac3 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + paddw m6, m7 + pmulhrsw m1, m3 + lea r4, [dstq+strideq*4] + psllw m1, 8 + por m0, m1 + vextracti128 xm1, m0, 1 + punpcklbw xm2, xm0, xm1 + punpckhbw xm0, xm1 + movd [dstq+strideq*0], xm2 + pextrd [dstq+strideq*1], xm2, 1 + pextrd [dstq+strideq*2], xm2, 2 + pextrd [dstq+r5 ], xm2, 3 + movd [r4 +strideq*0], xm0 + pextrd [r4 +strideq*1], xm0, 1 + pextrd [r4 +strideq*2], xm0, 2 + pextrd [r4 +r5 ], xm0, 3 + add dstq, 4 + sub wd, 4 + jg .h8_upsample_loop + RET +.h8_no_intra_edge_filter: + and maxbased, 7 + or maxbased, 8 ; imin(w+7, 15) + jmp .h8_main +.h8_no_upsample: + %assign stack_offset org_stack_offset + ALLOC_STACK -32, 10 + lea maxbased, [wq+7] + test angled, 0x400 + jnz .h8_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h8_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd xm6, [base+pb_15] + pcmpeqb xm1, xm1 + psubusb xm6, xm0 + psubb xm6, xm1 ; w == 4 ? 5 : 1 + movu xm2, [tlq-16] + pmaxub xm1, xm6, [base+z_filter_s] + vinserti128 m2, [tlq-14], 1 + vinserti128 m1, [base+z_filter_s+12], 1 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*0] + pmaxub xm6, [base+z_filter_s+ 8] + vinserti128 m6, [base+z_filter_s+20], 1 + pshufb m0, m2, m1 + pmaddubsw m0, m7 + vpbroadcastd m7, [base+z_filter_k-4+r5*4+12*1] + movzx r4d, byte [tlq-15] + shufps m1, m6, q2121 + pshufb m1, m2, m1 + pmaddubsw m1, m7 + paddw m0, m1 + sub r5d, 3 + jnz .h8_3tap + vpbroadcastd m7, [z_filter_k+4*8] + movzx r2d, byte [tlq-14] + pshufb m2, m6 + pmaddubsw m2, m7 + sub r2d, r4d + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+15], r2b + paddw m0, m2 +.h8_3tap: + pmulhrsw m0, m3 + sar r5d, 1 + lea tlq, [rsp+31] + add r5d, 17 + cmp wd, 16 + cmovns maxbased, r5d + neg r5 + mov [tlq+r5], r4b + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + mova [tlq-15], xm0 +.h8_main: + movd xm2, dyd + vbroadcasti128 m0, [z_base_inc] + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m2, xm2 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psrlw m7, 8 + psubw m9, m0 + paddw m6, m2, m2 + vpblendd m2, m6, 0x0f +.h8_loop: + lea r5, [r4+dyq] + sar r4, 6 + pand m0, m4, m2 + psubw m1, m5, m0 + psllw m0, 8 + por m1, m0 + vbroadcasti128 m0, [tlq+r4] + lea r4, [r5+dyq] + sar r5, 6 + vinserti128 m0, [tlq+r5], 0 + sub rsp, 8*2 + pshufb m0, m8 + pmaddubsw m0, m1 + pcmpgtw m1, m9, m2 + paddw m2, m6 + pmulhrsw m0, m3 + vpblendvb m0, m7, m0, m1 + vextracti128 xm1, m0, 1 + psllw xm0, 8 + por xm0, xm1 ; interleave rows (partial transpose) + mova [rsp], xm0 + sub wd, 2 + jz .h8_transpose + cmp r4d, maxbased + jg .h8_loop + packuswb xm0, xm7, xm7 +.h8_end_loop: + sub rsp, 8*2 + mova [rsp], xm0 + sub wd, 2 + jg .h8_end_loop +.h8_transpose: + mova xm2, [rsp+16*1] + sub org_wd, 8 + lea r2, [strideq*3] + lea r6, [dstq+org_wq] + cmovns dstq, r6 + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 + lea r6, [dstq+strideq*4] + jge .h8_w8 + add rsp, 16*2 + movd [dstq+strideq*0], xm1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+r2 ], xm1, 3 + movd [r6 +strideq*0], xm2 + pextrd [r6 +strideq*1], xm2, 1 + pextrd [r6 +strideq*2], xm2, 2 + pextrd [r6 +r2 ], xm2, 3 + jmp .h8_end +.h8_w8_loop: + mova xm0, [rsp+16*0] + mova xm2, [rsp+16*1] + punpcklwd xm1, xm2, xm0 + punpckhwd xm2, xm0 +.h8_w8: ; w8/w16/w32 + mova xm0, [rsp+16*2] + mova xm4, [rsp+16*3] + add rsp, 16*4 + punpcklwd xm3, xm4, xm0 + punpckhwd xm4, xm0 + punpckldq xm0, xm3, xm1 + punpckhdq xm3, xm1 + punpckldq xm1, xm4, xm2 + punpckhdq xm4, xm2 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm3 + movhps [dstq+r2 ], xm3 + movq [r6 +strideq*0], xm1 + movhps [r6 +strideq*1], xm1 + movq [r6 +strideq*2], xm4 + movhps [r6 +r2 ], xm4 + sub dstq, 8 + sub r6, 8 + sub org_wd, 8 + jge .h8_w8_loop +.h8_end: + RET +.h16_no_intra_edge_filter: + and maxbased, 15 + or maxbased, 16 ; imin(w+15, 31) + jmp .h16_main +ALIGN function_align +.h16: + %assign stack_offset org_stack_offset + ALLOC_STACK -64, 12 + lea maxbased, [wq+15] + test angled, 0x400 + jnz .h16_no_intra_edge_filter + call .filter_strength + test r5d, r5d + jz .h16_main ; filter_strength == 0 + popcnt r5d, r5d + vpbroadcastd m11, [base+pb_27] + vpbroadcastd m1, [base+pb_1] + vbroadcasti128 m6, [base+z_filter_s+12] + vinserti128 m2, m6, [base+z_filter_s+4], 0 + vinserti128 m6, [base+z_filter_s+20], 1 + movu xm10, [tlq-18] + vinserti128 m10, [tlq-14], 1 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*0] + vbroadcasti128 m7, [base+z_filter_s+8] + vinserti128 m8, m7, [base+z_filter_s+0], 0 + vinserti128 m7, [base+z_filter_s+16], 1 + psubusb m11, m0 + por m1, m11 + movu xm11, [tlq-32] + vinserti128 m11, [tlq-28], 1 + pmaxub m8, m1 + pmaxub m7, m1 + pshufb m0, m10, m2 + shufps m2, m6, q2121 + pmaddubsw m0, m9 + pshufb m1, m11, m8 + shufps m8, m7, q2121 + pmaddubsw m1, m9 + vpbroadcastd m9, [base+z_filter_k-4+r5*4+12*1] + movzx r4d, byte [tlq-31] + pshufb m2, m10, m2 + pmaddubsw m2, m9 + pshufb m8, m11, m8 + pmaddubsw m8, m9 + paddw m0, m2 + paddw m1, m8 + sub r5d, 3 + jnz .h16_3tap + vpbroadcastd m9, [z_filter_k+4*8] + movzx r2d, byte [tlq-30] + pshufb m10, m6 + pmaddubsw m10, m9 + pshufb m11, m7 + pmaddubsw m11, m9 + sub r2d, r4d + lea r2d, [r2+r4*8+4] + shr r2d, 3 + mov [rsp+31], r2b + paddw m0, m10 + paddw m1, m11 +.h16_3tap: + pmulhrsw m0, m3 + pmulhrsw m1, m3 + sar r5d, 1 + lea tlq, [rsp+63] + add r5d, 33 + cmp wd, 32 + cmovns maxbased, r5d + neg r5 + mov [tlq+r5], r4b + packuswb m0, m1 + vpermq m0, m0, q2031 + mova [tlq-31], m0 +.h16_main: + movd xm6, dyd + vbroadcasti128 m0, [z_base_inc] + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psubw m9, m0 + paddw m11, m6, m6 + psubw m10, m9, m3 ; 64*8 + vpblendd m6, m11, 0xf0 +.h16_loop: + lea r5, [r4+dyq] + sar r4, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r4-0] + movu xm1, [tlq+r4-8] + lea r4, [r5+dyq] + sar r5, 6 + vinserti128 m0, [tlq+r5-0], 1 + vinserti128 m1, [tlq+r5-8], 1 + sub rsp, 32 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + vpermq m0, m0, q3120 + mova [rsp], m0 + sub wd, 2 + jz .h16_transpose + cmp r4d, maxbased + jg .h16_loop + mova m0, m7 +.h16_end_loop: + sub rsp, 32 + mova [rsp], m7 + sub wd, 2 + jg .h16_end_loop +.h16_transpose: + mova m2, [rsp+32*1] + sub org_wd, 8 + lea r2, [strideq*3] + lea r6, [dstq+org_wq] + cmovns dstq, r6 + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + lea r3, [strideq*5] + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + lea r4, [strideq+r2*2] ; stride*7 + jge .h16_w8 + add rsp, 32*2 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + vextracti128 xm0, m0, 1 + movd [dstq+strideq*4], xm1 + pextrd [dstq+r3 ], xm1, 1 + pextrd [dstq+r2*2 ], xm1, 2 + pextrd [dstq+r4 ], xm1, 3 + lea dstq, [dstq+strideq*8] + vextracti128 xm1, m1, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + movd [dstq+strideq*4], xm1 + pextrd [dstq+r3 ], xm1, 1 + pextrd [dstq+r2*2 ], xm1, 2 + pextrd [dstq+r4 ], xm1, 3 + jmp .h16_end +.h16_w8_loop: + mova m0, [rsp+32*0] + mova m2, [rsp+32*1] + punpcklbw m1, m2, m0 + punpckhbw m2, m0 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 +.h16_w8: + mova m2, [rsp+32*2] + mova m4, [rsp+32*3] + lea r6, [dstq+strideq*8] + add rsp, 32*4 + punpcklbw m3, m4, m2 + punpckhbw m4, m2 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + punpckldq m4, m2, m0 + punpckhdq m2, m0 + punpckldq m0, m3, m1 + punpckhdq m3, m1 + movq [dstq+strideq*0], xm4 + movhps [dstq+strideq*1], xm4 + vextracti128 xm4, m4, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+r2 ], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*4], xm0 + movhps [dstq+r3 ], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+r2*2 ], xm3 + movhps [dstq+r4 ], xm3 + vextracti128 xm3, m3, 1 + movq [r6+strideq*0], xm4 + movhps [r6+strideq*1], xm4 + movq [r6+strideq*2], xm2 + movhps [r6+r2 ], xm2 + movq [r6+strideq*4], xm0 + movhps [r6+r3 ], xm0 + movq [r6+r2*2 ], xm3 + movhps [r6+r4 ], xm3 + sub dstq, 8 + sub org_wd, 8 + jge .h16_w8_loop +.h16_end: + RET +ALIGN function_align +.h32: + %assign stack_offset org_stack_offset + ALLOC_STACK -96, 15 + lea maxbased, [wq+31] + and maxbased, 31 + or maxbased, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + vbroadcasti128 m0, [pb_0to15] + mov r4d, 21 + mov r5d, 3 + movu xm11, [tlq-66] ; 56-63 + vinserti128 m11, [tlq-52], 1 ; 40-47 + sub r4d, wd ; 21-w + cmovns r5d, r4d + movu xm12, [tlq-58] ; 48-55 + vinserti128 m12, [tlq-44], 1 ; 32-39 + sub r4d, 8 ; 13-w + movd xm1, r5d + movu xm13, [tlq-34] ; 24-31 + vinserti128 m13, [tlq-20], 1 ; 8-15 + movd xm2, r4d + vpbroadcastb m1, xm1 + movu xm14, [tlq-28] ; 16-23 + vinserti128 m14, [tlq-14], 1 ; 0- 7 + vpbroadcastb m2, xm2 + pmaxsb m1, m0 ; clip 16x32 and (32|64)x32 + movu m7, [z_filter_s+4] + pshufb m11, m1 + vinserti128 m8, m7, [z_filter_s+8], 1 + vinserti128 m7, [z_filter_s+16], 0 + pmaxsb m2, m0 ; clip 8x32 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m12, m2 + pshufb m0, m11, m8 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + shufps m8, m7, q1021 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m10, m11, m8 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m8 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m8 + pmaddubsw m10, m9 + shufps m8, m7, q2121 + paddw m1, m10 + pshufb m10, m14, m8 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + movzx r4d, byte [tlq-63] + movzx r2d, byte [tlq-62] + paddw m0, m11 + paddw m2, m12 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m7 + pmaddubsw m14, m9 + paddw m1, m13 + paddw m6, m14 + sub r2d, r4d + lea r2d, [r2+r4*8+4] ; edge case for 64x32 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + shr r2d, 3 + mov [rsp+31], r2b + lea tlq, [rsp+95] + mov [tlq-65], r4b + mov r4d, 65 + cmp wd, 64 + cmove maxbased, r4d + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-63], m0 + mova [tlq-31], m1 +.h32_main: + movd xm6, dyd + mov r4, tlq + sub tlq, 8 + neg dyq + vpbroadcastw m6, xm6 + sub r4, maxbaseq + shl maxbased, 6 + vpbroadcastb m7, [r4] + lea r4, [dyq+63] + movd xm9, maxbased + not maxbased + vbroadcasti128 m8, [z3_shuf] + add maxbased, 64 + vpbroadcastw m9, xm9 + psubw m9, [z_base_inc] + mova m11, m6 + psubw m10, m9, m3 ; 64*8 +.h32_loop: + mov r5, r4 + sar r5, 6 + pand m1, m4, m6 + psubw m2, m5, m1 + psllw m1, 8 + por m2, m1 + movu xm0, [tlq+r5- 0] + vinserti128 m0, [tlq+r5-16], 1 + movu xm1, [tlq+r5- 8] + vinserti128 m1, [tlq+r5-24], 1 + sub rsp, 32 + add r4, dyq + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + pcmpgtw m1, m9, m6 + pcmpgtw m2, m10, m6 + packsswb m1, m2 + paddw m6, m11 + vpblendvb m0, m7, m0, m1 + mova [rsp], m0 + dec wd + jz .h32_transpose + cmp r4d, maxbased + jg .h32_loop +.h32_end_loop: + sub rsp, 32 + mova [rsp], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + lea dstq, [dstq+org_wq-8] + lea r2, [strideq*3] + lea r3, [strideq*5] + lea r4, [strideq+r2*2] ; stride*7 +.h32_w8_loop: + mova m7, [rsp+32*0] + mova m6, [rsp+32*1] + mova m5, [rsp+32*2] + mova m4, [rsp+32*3] + mova m3, [rsp+32*4] + mova m2, [rsp+32*5] + mova m1, [rsp+32*6] + mova m0, [rsp+32*7] + lea r6, [dstq+strideq*8] + add rsp, 32*8 + punpcklbw m8, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklwd m7, m8, m1 + punpckhwd m8, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpckldq m6, m7, m2 + punpckhdq m7, m2 + punpckldq m2, m8, m3 + punpckhdq m8, m3 + punpckldq m3, m1, m5 + punpckhdq m1, m5 + punpckldq m5, m0, m4 + punpckhdq m0, m4 + movq [dstq+strideq*0], xm6 + movhps [dstq+strideq*1], xm6 + vextracti128 xm6, m6, 1 + movq [dstq+strideq*2], xm7 + movhps [dstq+r2 ], xm7 + vextracti128 xm7, m7, 1 + movq [dstq+strideq*4], xm2 + movhps [dstq+r3 ], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+r2*2 ], xm8 + movhps [dstq+r4 ], xm8 + vextracti128 xm8, m8, 1 + movq [r6+strideq*0], xm3 + movhps [r6+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [r6+strideq*2], xm1 + movhps [r6+r2 ], xm1 + vextracti128 xm1, m1, 1 + movq [r6+strideq*4], xm5 + movhps [r6+r3 ], xm5 + vextracti128 xm5, m5, 1 + movq [r6+r2*2 ], xm0 + movhps [r6+r4 ], xm0 + lea r6, [r6+strideq*8] + vextracti128 xm0, m0, 1 + movq [r6+strideq*0], xm6 + movhps [r6+strideq*1], xm6 + movq [r6+strideq*2], xm7 + movhps [r6+r2 ], xm7 + movq [r6+strideq*4], xm2 + movhps [r6+r3 ], xm2 + movq [r6+r2*2 ], xm8 + movhps [r6+r4 ], xm8 + lea r6, [r6+strideq*8] + movq [r6+strideq*0], xm3 + movhps [r6+strideq*1], xm3 + movq [r6+strideq*2], xm1 + movhps [r6+r2 ], xm1 + movq [r6+strideq*4], xm5 + movhps [r6+r3 ], xm5 + movq [r6+r2*2 ], xm0 + movhps [r6+r4 ], xm0 + sub dstq, 8 + sub org_wd, 8 + jg .h32_w8_loop + RET +ALIGN function_align +.h64: + %assign stack_offset org_stack_offset + ALLOC_STACK -128, 16 + lea maxbased, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + mov r4d, 21 + vpbroadcastb xm11, [tlq-127] + vpblendd xm11, [tlq-130], 0x0e ; 120-127 + sub r4d, wd ; 21-w + mov r5d, 3 + vinserti128 m11, [tlq-116], 1 ; 104-111 + movu m7, [z_filter_s+4] + cmp wd, 32 + cmove r4d, r5d + vinserti128 m8, m7, [z_filter_s+8], 1 + vbroadcasti128 m6, [pb_0to15] + movd xm1, r4d + vpbroadcastd m9, [z_filter_k+4*2+12*0] + movu xm12, [tlq-122] ; 112-119 + vinserti128 m12, [tlq-108], 1 ; 96-103 + vpbroadcastb m1, xm1 + movu xm13, [tlq- 98] ; 88- 95 + vinserti128 m13, [tlq- 84], 1 ; 72- 79 + movu xm14, [tlq- 90] ; 80- 87 + vinserti128 m14, [tlq- 76], 1 ; 64- 71 + vinserti128 m7, [z_filter_s+16], 0 + pshufb m0, m11, m8 + pmaddubsw m0, m9 + pshufb m2, m12, m8 + pmaddubsw m2, m9 + pmaxsb m1, m6 ; clip (16|32)x64 + pshufb m13, m1 + pshufb m1, m13, m8 + pmaddubsw m1, m9 + pshufb m6, m14, m8 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + shufps m15, m8, m7, q1021 + pshufb m10, m11, m15 + pmaddubsw m10, m9 + paddw m0, m10 + pshufb m10, m12, m15 + pmaddubsw m10, m9 + paddw m2, m10 + pshufb m10, m13, m15 + pmaddubsw m10, m9 + paddw m1, m10 + pshufb m10, m14, m15 + pmaddubsw m10, m9 + paddw m6, m10 + vpbroadcastd m9, [z_filter_k+4*2+12*2] + shufps m10, m8, m7, q2132 + pshufb m11, m10 + pmaddubsw m11, m9 + pshufb m12, m10 + pmaddubsw m12, m9 + pshufb m13, m10 + pmaddubsw m13, m9 + pshufb m14, m10 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + movu xm11, [tlq-66] ; 56-63 + vinserti128 m11, [tlq-52], 1 ; 40-47 + movu xm12, [tlq-58] ; 48-55 + vinserti128 m12, [tlq-44], 1 ; 32-39 + movu xm13, [tlq-34] ; 24-31 + vinserti128 m13, [tlq-20], 1 ; 8-15 + movu xm14, [tlq-28] ; 16-23 + vinserti128 m14, [tlq-14], 1 ; 0- 7 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + lea tlq, [rsp+127] + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-127], m0 + mova [tlq- 95], m1 + pshufb m0, m11, m10 + pmaddubsw m0, m9 + pshufb m2, m12, m10 + pmaddubsw m2, m9 + pshufb m1, m13, m10 + pmaddubsw m1, m9 + pshufb m6, m14, m7 + pmaddubsw m6, m9 + vpbroadcastd m9, [z_filter_k+4*2+12*1] + pshufb m7, m11, m15 + pmaddubsw m7, m9 + paddw m0, m7 + pshufb m7, m12, m15 + pmaddubsw m7, m9 + paddw m2, m7 + pshufb m7, m13, m15 + pmaddubsw m7, m9 + paddw m1, m7 + pshufb m7, m14, m10 + pmaddubsw m7, m9 + paddw m6, m7 + vpbroadcastd m9, [z_filter_k+4*2+12*0] + pshufb m11, m8 + pmaddubsw m11, m9 + pshufb m12, m8 + pmaddubsw m12, m9 + pshufb m13, m8 + pmaddubsw m13, m9 + pshufb m14, m15 + pmaddubsw m14, m9 + paddw m0, m11 + paddw m2, m12 + paddw m1, m13 + paddw m6, m14 + pmulhrsw m0, m3 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + pmulhrsw m6, m3 + packuswb m0, m2 + packuswb m1, m6 + mova [tlq-63], m0 + mova [tlq-31], m1 +.h64_main: + movd xm12, dyd + neg maxbaseq + vbroadcasti128 m8, [z3_shuf] + vpbroadcastb m7, [tlq+maxbaseq] + shl maxbased, 6 + vpbroadcastw m12, xm12 + lea r5d, [dyq+maxbaseq-64] + neg dyq + or maxbased, 63 + lea r4, [dyq+63] + movd xm6, r5d + mova xm10, [pb_1to32+16] + vinserti128 m10, [pb_1to32], 1 + vpbroadcastd m11, [pb_32] + vpbroadcastw m6, xm6 +.h64_loop: + mov r5, r4 + sar r5, 6 + movu m0, [tlq+r5-24] + movu m1, [tlq+r5-32] + pand m2, m4, m6 + psubw m9, m5, m2 + psllw m2, 8 + por m9, m2 + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + psraw m2, m6, 6 + sub rsp, 64 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packsswb m2, m2 + paddb m2, m10 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [rsp+32], m0 + movu m0, [tlq+r5-56] + movu m1, [tlq+r5-64] + add r4, dyq + pshufb m0, m8 + pshufb m1, m8 + pmaddubsw m0, m9 + pmaddubsw m1, m9 + paddb m2, m11 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + paddw m6, m12 + packuswb m0, m1 + vpblendvb m0, m7, m0, m2 + mova [rsp], m0 + dec wd + jz .h64_transpose + cmp r4d, maxbased + jg .h64_loop +.h64_end_loop: + sub rsp, 64 + mova [rsp+32], m7 + mova [rsp+ 0], m7 + dec wd + jg .h64_end_loop +.h64_transpose: + lea r2, [strideq*3] + lea r3, [strideq*5] + imul r5, strideq, -8 + lea dstq, [dstq+org_wq-16] + lea r4, [strideq+r2*2] ; stride*7 +.h64_transpose_loop0: + lea r6, [rsp+16*3] +.h64_transpose_loop: + mova xm0, [r6+64*15] + vinserti128 m0, [r6+64* 7], 1 + mova xm1, [r6+64*14] + vinserti128 m1, [r6+64* 6], 1 + mova xm2, [r6+64*13] + vinserti128 m2, [r6+64* 5], 1 + mova xm3, [r6+64*12] + vinserti128 m3, [r6+64* 4], 1 + mova xm4, [r6+64*11] + vinserti128 m4, [r6+64* 3], 1 + mova xm5, [r6+64*10] + vinserti128 m5, [r6+64* 2], 1 + mova xm6, [r6+64* 9] + vinserti128 m6, [r6+64* 1], 1 + mova xm7, [r6+64* 8] + vinserti128 m7, [r6+64* 0], 1 + sub r6, 16 + punpcklbw m8, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklwd m7, m8, m1 + punpckhwd m8, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpckldq m6, m7, m2 + punpckhdq m7, m2 + punpckldq m2, m8, m3 + punpckhdq m8, m3 + punpckldq m3, m1, m5 + punpckhdq m1, m5 + punpckldq m5, m0, m4 + punpckhdq m0, m4 + vpermq m6, m6, q3120 + vpermq m7, m7, q3120 + vpermq m2, m2, q3120 + vpermq m8, m8, q3120 + vpermq m3, m3, q3120 + vpermq m1, m1, q3120 + vpermq m5, m5, q3120 + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm6 + vextracti128 [dstq+strideq*1], m6, 1 + mova [dstq+strideq*2], xm7 + vextracti128 [dstq+r2 ], m7, 1 + mova [dstq+strideq*4], xm2 + vextracti128 [dstq+r3 ], m2, 1 + mova [dstq+r2*2 ], xm8 + vextracti128 [dstq+r4 ], m8, 1 + sub dstq, r5 + mova [dstq+strideq*0], xm3 + vextracti128 [dstq+strideq*1], m3, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+r2 ], m1, 1 + mova [dstq+strideq*4], xm5 + vextracti128 [dstq+r3 ], m5, 1 + mova [dstq+r2*2 ], xm0 + vextracti128 [dstq+r4 ], m0, 1 + sub dstq, r5 + cmp r6, rsp + jae .h64_transpose_loop + add rsp, 64*16 + lea dstq, [dstq+r5*8-16] + sub org_wd, 16 + jg .h64_transpose_loop0 +.h64_end: + RET + +%macro FILTER_XMM 4 ; dst, src, tmp, shuf +%ifnum %4 + pshufb xm%2, xm%4 +%else + pshufb xm%2, %4 +%endif + pshufd xm%1, xm%2, q0000 ; p0 p1 + pmaddubsw xm%1, xm2 + pshufd xm%3, xm%2, q1111 ; p2 p3 + pmaddubsw xm%3, xm3 + paddw xm%1, xm1 + paddw xm%1, xm%3 + pshufd xm%3, xm%2, q2222 ; p4 p5 + pmaddubsw xm%3, xm4 + paddw xm%1, xm%3 + pshufd xm%3, xm%2, q3333 ; p6 __ + pmaddubsw xm%3, xm5 + paddw xm%1, xm%3 + psraw xm%1, 4 + packuswb xm%1, xm%1 +%endmacro + +%macro FILTER_YMM 4 ; dst, src, tmp, shuf + pshufb m%2, m%4 + pshufd m%1, m%2, q0000 + pmaddubsw m%1, m2 + pshufd m%3, m%2, q1111 + pmaddubsw m%3, m3 + paddw m%1, m1 + paddw m%1, m%3 + pshufd m%3, m%2, q2222 + pmaddubsw m%3, m4 + paddw m%1, m%3 + pshufd m%3, m%2, q3333 + pmaddubsw m%3, m5 + paddw m%1, m%3 + psraw m%1, 4 + vperm2i128 m%3, m%1, m%1, 0x01 + packuswb m%1, m%3 +%endmacro + +; The ipred_filter SIMD processes 4x2 blocks in the following order which +; increases parallelism compared to doing things row by row. One redundant +; block is calculated for w8 and w16, two for w32. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 5 1 2 3 5 b c d f +; 2 2 3 2 4 5 7 2 4 5 7 c e f h +; 3 3 4 4 6 7 9 4 6 7 9 e g h j +; ___ 4 ___ 4 5 ___ 6 8 9 a ___ 6 8 9 a g i j k ___ +; 5 8 8 i + +cglobal ipred_filter_8bpc, 3, 7, 0, dst, stride, tl, w, h, filter +%define base r6-ipred_filter_avx2_table + lea r6, [filter_intra_taps] + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + add filterq, r6 + lea r6, [ipred_filter_avx2_table] + movq xm0, [tlq-3] ; _ 6 5 0 1 2 3 4 + movsxd wq, [r6+wq*4] + vpbroadcastd m1, [base+pw_8] + vbroadcasti128 m2, [filterq+16*0] + vbroadcasti128 m3, [filterq+16*1] + vbroadcasti128 m4, [filterq+16*2] + vbroadcasti128 m5, [filterq+16*3] + add wq, r6 + mov hd, hm + jmp wq +.w4: + WIN64_SPILL_XMM 9 + mova xm8, [base+filter_shuf2] + sub tlq, 3 + sub tlq, hq + jmp .w4_loop_start +.w4_loop: + pinsrd xm0, xm6, [tlq+hq], 0 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER_XMM 6, 0, 7, 8 + movd [dstq+strideq*0], xm6 + pextrd [dstq+strideq*1], xm6, 1 + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 10 + mova m8, [base+filter_shuf1] + FILTER_XMM 7, 0, 6, [base+filter_shuf2] + vpbroadcastd m0, [tlq+4] + vpbroadcastd m6, [tlq+5] + sub tlq, 4 + sub tlq, hq + vpbroadcastq m7, xm7 + vpblendd m7, m6, 0x20 +.w8_loop: + vpbroadcastd xm6, [tlq+hq] + palignr m6, m0, 12 + vpblendd m0, m6, m7, 0xeb ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm6, xm7 + call .main + vpblendd xm6, xm7, 0x0c + pshufd xm6, xm6, q3120 + movq [dstq+strideq*0], xm6 + movhps [dstq+strideq*1], xm6 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + %assign xmm_regs_used 15 + %assign stack_size_padded 0x98 + SUB rsp, stack_size_padded +%endif + sub hd, 2 + TAIL_CALL .w16_main, 0 +.w16_main: +%if WIN64 + movaps [rsp+0xa8], xmm6 + movaps [rsp+0xb8], xmm7 + movaps [rsp+0x28], xmm8 + movaps [rsp+0x38], xmm9 + movaps [rsp+0x48], xmm10 + movaps [rsp+0x58], xmm11 + movaps [rsp+0x68], xmm12 + movaps [rsp+0x78], xmm13 + movaps [rsp+0x88], xmm14 +%endif + FILTER_XMM 12, 0, 7, [base+filter_shuf2] + vpbroadcastd m0, [tlq+5] + vpblendd m0, [tlq-12], 0x14 + mova m8, [base+filter_shuf1] + vpbroadcastq m7, xm12 + vpblendd m0, m7, 0xc2 ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + call .main ; c0 d0 a1 b1 a1 b1 c0 d0 + movlps xm9, xm7, [tlq+5] ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + vinserti128 m14, m8, [base+filter_shuf3], 0 + vpblendd xm12, xm7, 0x0c ; a0 b0 a1 b1 + FILTER_XMM 6, 9, 10, 14 + vpbroadcastq m6, xm6 ; a2 b2 __ __ __ __ a2 b2 + vpbroadcastd m9, [tlq+13] + vpbroadcastd m10, [tlq+12] + psrld m11, m8, 4 + vpblendd m6, m9, 0x20 ; top + sub tlq, 6 + sub tlq, hq +.w16_loop: + vpbroadcastd xm9, [tlq+hq] + palignr m9, m0, 12 + vpblendd m0, m9, m7, 0xe2 ; _ _ _ _ 1 2 3 4 6 5 0 _ _ _ _ _ + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm13, xm7 + call .main ; e0 f0 c1 d1 c1 d1 e0 f0 + vpblendd m9, m12, m10, 0xf0 + vpblendd m12, m6, 0xc0 + pshufd m9, m9, q3333 + vpblendd m9, m6, 0xee + vpblendd m10, m9, m7, 0x0c ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_YMM 6, 10, 9, 14 ; c2 d2 a3 b3 a3 b3 c2 d2 + vpblendd m12, m6, 0x30 ; a0 b0 a1 b1 a3 b3 a2 b2 + vpermd m9, m11, m12 ; a0 a1 a2 a3 b0 b1 b2 b3 + vpblendd xm12, xm13, xm7, 0x0c ; c0 d0 c1 d1 + mova [dstq+strideq*0], xm9 + vextracti128 [dstq+strideq*1], m9, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + vpblendd xm7, xm6, xm10, 0x04 ; _ _ _ 5 _ _ _ 6 0 _ _ _ 1 2 3 4 + pshufd xm7, xm7, q1032 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_XMM 0, 7, 9, [base+filter_shuf1+16] + vpblendd xm6, xm0, 0x0c ; c2 d2 c3 d3 + shufps xm0, xm12, xm6, q2020 ; c0 c1 c2 c3 + shufps xm6, xm12, xm6, q3131 ; d0 d1 d2 d3 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm6 + ret +ALIGN function_align +.w32: + sub rsp, stack_size_padded + sub hd, 2 + lea r3, [dstq+16] + lea r5d, [hq-2] + call .w16_main + add tlq, r5 + mov dstq, r3 + lea r3, [strideq-4] + lea r4, [r3+strideq*2] + movq xm0, [tlq+21] + pinsrd xm0, [dstq-4], 2 + pinsrd xm0, [dstq+r3*1], 3 + FILTER_XMM 12, 0, 7, 14 ; a0 b0 a0 b0 + movq xm7, [dstq+r3*2] + pinsrd xm7, [dstq+r4], 2 + palignr xm7, xm0, 12 ; 0 _ _ _ _ _ _ _ _ _ _ 5 _ _ _ 6 + vpbroadcastd m0, [tlq+28] + vpbroadcastd m9, [tlq+29] + vbroadcasti128 m8, [base+filter_shuf1+16] + vpblendd m0, m9, 0x20 + vpblendd m0, m7, 0x0f + vpbroadcastq m7, xm12 + vpblendd m0, m7, 0xc2 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + call .main ; c0 d0 a1 b1 a1 b1 c0 d0 + add r3, 2 + lea r4, [r4+strideq*2] + movlps xm9, xm7, [tlq+29] ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + vpblendd xm12, xm7, 0x0c ; a0 b0 a1 b1 + FILTER_XMM 6, 9, 10, 14 + vpbroadcastq m6, xm6 ; a2 b2 __ __ __ __ a2 b2 + vpbroadcastd m9, [tlq+37] + vpbroadcastd m10, [tlq+36] + vpblendd m6, m9, 0x20 ; top +.w32_loop: + movq xm9, [dstq+r3*4] + pinsrd xm9, [dstq+r4], 2 +.w32_loop_last: + palignr m9, m0, 12 + vpblendd m0, m9, m7, 0xe2 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + mova xm13, xm7 ; c0 d0 + call .main ; e0 f0 c1 d1 c1 d1 e0 f0 + vpblendd m9, m12, m10, 0xf0 + vpblendd m12, m6, 0xc0 + pshufd m9, m9, q3333 + vpblendd m9, m6, 0xee + vpblendd m10, m9, m7, 0x0c ; _ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_YMM 6, 10, 9, 14 ; c2 d2 a3 b3 a3 b3 c2 d2 + vpblendd m12, m6, 0x30 ; a0 b0 a1 b1 a3 b3 a2 b2 + vpermd m9, m11, m12 ; a0 a1 a2 a3 b0 b1 b2 b3 + vpblendd xm12, xm13, xm7, 0x0c ; c0 d0 c1 d1 + mova [dstq+strideq*0], xm9 + vextracti128 [dstq+strideq*1], m9, 1 + lea dstq, [dstq+strideq*2] + sub r5d, 2 + jg .w32_loop + jz .w32_loop_last + vpblendd xm7, xm6, xm10, 0x04 ; _ _ _ 5 _ _ _ 6 0 _ _ _ 1 2 3 4 + pshufd xm7, xm7, q1032 ; 0 _ _ _ 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER_XMM 0, 7, 9, [base+filter_shuf1+16] + vpblendd xm6, xm0, 0x0c ; c2 d2 c3 d3 + shufps xm0, xm12, xm6, q2020 ; c0 c1 c2 c3 + shufps xm6, xm12, xm6, q3131 ; d0 d1 d2 d3 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm6 + RET +ALIGN function_align +.main: + FILTER_YMM 7, 0, 9, 8 + ret + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +cglobal ipred_cfl_top_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + lea t0, [ipred_cfl_left_avx2_table] + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + shrx r6d, r6d, wd + movd xm3, r6d + movsxd r6, [t0+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_avx2_table-ipred_cfl_left_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +cglobal ipred_cfl_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov t0d, 0x8000 + shrx t0d, t0d, r6d + movd xm3, t0d + lea t0, [ipred_cfl_left_avx2_table] + movsxd r6, [t0+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_avx2_table-ipred_cfl_left_avx2_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + vextracti128 xm1, m0, 1 + paddw xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddw xm0, xm1 +.h4: + pmaddwd xm0, xm2 + pmulhrsw xm0, xm3 + vpbroadcastw m0, xm0 + jmp wq + +cglobal ipred_cfl_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd xm4, t0d + tzcnt t0d, t0d + movd xm5, t0d + lea t0, [ipred_cfl_avx2_table] + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+4*4] + pcmpeqd m3, m3 + psrlw xm4, 1 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movd xm0, [tlq-4] + pmaddubsw xm0, xm3 + jmp wq +.w4: + movd xm1, [tlq+1] + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm1 + pmaddwd xm0, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddw xm0, xm1 + shrx r6d, r6d, r2d + psrlq xm1, xm0, 32 + paddw xm0, xm1 + movd xm1, r6d + psrlw xm0, 2 + pmulhuw xm0, xm1 +.w4_end: + vpbroadcastw m0, xm0 +.s4: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + IPRED_CFL 4 + packuswb m4, m4 + vextracti128 xm5, m4, 1 + movd [dstq+strideq*0], xm4 + pextrd [dstq+strideq*1], xm4, 1 + movd [dstq+strideq*2], xm5 + pextrd [dstq+r6 ], xm5, 1 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + movq xm0, [tlq-8] + pmaddubsw xm0, xm3 + jmp wq +.w8: + movq xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + punpckhqdq xm2, xm0, xm0 + paddw xm0, xm2 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w8_end: + vpbroadcastw m0, xm0 +.s8: + vpbroadcastw m1, alpham + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*1], xm5 + movhps [dstq+strideq*2], xm4 + movhps [dstq+r6 ], xm5 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova xm0, [tlq-16] + pmaddubsw xm0, xm3 + jmp wq +.w16: + movu xm1, [tlq+1] + vextracti128 xm2, m0, 1 + pmaddubsw xm1, xm3 + psubw xm0, xm4 + paddw xm0, xm2 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w16_end: + vpbroadcastw m0, xm0 +.s16: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vpermq m4, m4, q3120 + mova [dstq+strideq*0], xm4 + vextracti128 [dstq+strideq*1], m4, 1 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + psubw xm0, xm4 + paddw xm0, xm1 + punpckhqdq xm1, xm0, xm0 + paddw xm0, xm1 + psrlq xm1, xm0, 32 + paddw xm0, xm1 + pmaddwd xm0, xm3 + psrlw xm0, xm5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xm1, r6d + pmulhuw xm0, xm1 +.w32_end: + vpbroadcastw m0, xm0 +.s32: + vpbroadcastw m1, alpham + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+32] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + vpermq m4, m4, q3120 + mova [dstq], m4 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +cglobal ipred_cfl_128_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + lea t0, [ipred_cfl_splat_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [t0+wq*4] + vpbroadcastd m0, [t0-ipred_cfl_splat_avx2_table+pw_128] + add wq, t0 + movifnidn acq, acmp + jmp wq + +cglobal ipred_cfl_ac_420_8bpc, 4, 9, 5, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + mov ac_bakq, acq + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + vpbroadcastd m2, [pb_2] + pxor m4, m4 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq xm0, [yq] + movq xm1, [yq+strideq] + movhps xm0, [yq+strideq*2] + movhps xm1, [yq+stride3q] + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + paddw xm0, xm1 + mova [acq], xm0 + paddw xm4, xm0 + lea yq, [yq+strideq*4] + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg + vpermq m0, m0, q1111 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova xm0, [yq] + mova xm1, [yq+strideq] + vinserti128 m0, [yq+strideq*2], 1 + vinserti128 m1, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg + jmp .w8_hpad +.w8_wpad: + vbroadcasti128 m3, [cfl_ac_w8_pad1_shuffle] +.w8_wpad_loop: + movq xm0, [yq] + movq xm1, [yq+strideq] + vinserti128 m0, [yq+strideq*2], 1 + vinserti128 m1, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufb m0, m3 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w8_hpad: + vpermq m0, m0, q3232 +.w8_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad_loop + jmp .calc_avg + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad_loop +.w16_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_420_avx2_table] + shl wpadd, 2 + mova m3, [iptrq+cfl_ac_w16_pad_shuffle- \ + ipred_cfl_ac_420_avx2_table+wpadq*8-32] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w16_pad3: + vpbroadcastq m0, [yq] + vpbroadcastq m1, [yq+strideq] + jmp .w16_wpad_end +.w16_pad2: + vbroadcasti128 m0, [yq] + vbroadcasti128 m1, [yq+strideq] + jmp .w16_wpad_end +.w16_pad1: + mova m0, [yq] + mova m1, [yq+strideq] + ; fall-through +.w16_wpad_end: + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufb m0, m3 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jz .w16_wpad_done + jmp iptrq +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w16_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + dec hpadd + jg .w16_hpad_loop + ; fall-through + +.calc_avg: + vpbroadcastd m2, [pw_1] + pmaddwd m0, m4, m2 + vextracti128 xm1, m0, 1 + tzcnt r1d, szd + paddd xm0, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal ipred_cfl_ac_422_8bpc, 4, 9, 6, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + mov ac_bakq, acq + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + vpbroadcastd m2, [pb_4] + pxor m4, m4 + pxor m5, m5 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq xm1, [yq] + movhps xm1, [yq+strideq] + movq xm0, [yq+strideq*2] + movhps xm0, [yq+stride3q] + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm2 + mova [acq], xm1 + mova [acq+16], xm0 + paddw xm4, xm0 + paddw xm5, xm1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg + vpermq m0, m0, q1111 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova xm1, [yq] + vinserti128 m1, [yq+strideq], 1 + mova xm0, [yq+strideq*2] + vinserti128 m0, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg + jmp .w8_hpad +.w8_wpad: + vbroadcasti128 m3, [cfl_ac_w8_pad1_shuffle] +.w8_wpad_loop: + movq xm1, [yq] + vinserti128 m1, [yq+strideq], 1 + movq xm0, [yq+strideq*2] + vinserti128 m0, [yq+stride3q], 1 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pshufb m0, m3 + pshufb m1, m3 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w8_hpad: + vpermq m0, m0, q3232 +.w8_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad_loop + jmp .calc_avg + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m1, [yq] + mova m0, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad_loop +.w16_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_422_avx2_table] + shl wpadd, 2 + mova m3, [iptrq+cfl_ac_w16_pad_shuffle- \ + ipred_cfl_ac_422_avx2_table+wpadq*8-32] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w16_pad3: + vpbroadcastq m1, [yq] + vpbroadcastq m0, [yq+strideq] + jmp .w16_wpad_end +.w16_pad2: + vbroadcasti128 m1, [yq] + vbroadcasti128 m0, [yq+strideq] + jmp .w16_wpad_end +.w16_pad1: + mova m1, [yq] + mova m0, [yq+strideq] + ; fall-through +.w16_wpad_end: + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pshufb m0, m3 + pshufb m1, m3 + mova [acq], m1 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jz .w16_wpad_done + jmp iptrq +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w16_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddw m4, m0 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + ; fall-through + +.calc_avg: + vpbroadcastd m2, [pw_1] + pmaddwd m5, m5, m2 + pmaddwd m0, m4, m2 + paddd m0, m5 + vextracti128 xm1, m0, 1 + tzcnt r1d, szd + paddd xm0, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal ipred_cfl_ac_444_8bpc, 4, 9, 6, ac, y, stride, wpad, hpad, w, h, sz, ac_bak + movifnidn hpadd, hpadm + movifnidn wd, wm + mov hd, hm + mov szd, wd + imul szd, hd + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + vpbroadcastd m5, [pw_1] + tzcnt r8d, wd + lea r5, [ipred_cfl_ac_444_avx2_table] + movsxd r8, [r5+r8*4+12] + add r5, r8 + + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, sz, ac_bak + mov ac_bakq, acq + jmp r5 + +.w4: + lea stride3q, [strideq*3] + pxor xm2, xm2 +.w4_loop: + movd xm1, [yq] + movd xm0, [yq+strideq*2] + pinsrd xm1, [yq+strideq], 1 + pinsrd xm0, [yq+stride3q], 1 + punpcklbw xm1, xm2 + punpcklbw xm0, xm2 + psllw xm1, 3 + psllw xm0, 3 + mova [acq], xm1 + mova [acq+16], xm0 + paddw xm1, xm0 + paddw xm4, xm1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_mul + pshufd xm0, xm0, q3232 + paddw xm1, xm0, xm0 +.w4_hpad_loop: + mova [acq], xm0 + mova [acq+16], xm0 + paddw xm4, xm1 + add acq, 32 + sub hpadd, 4 + jg .w4_hpad_loop + jmp .calc_avg_mul + +.w8: + lea stride3q, [strideq*3] + pxor m2, m2 +.w8_loop: + movq xm1, [yq] + movq xm0, [yq+strideq*2] + vinserti128 m1, [yq+strideq], 1 + vinserti128 m0, [yq+stride3q], 1 + punpcklbw m1, m2 + punpcklbw m0, m2 + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + paddw m4, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_mul + vpermq m0, m0, q3232 + paddw m1, m0, m0 +.w8_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddw m4, m1 + add acq, 64 + sub hpadd, 4 + jg .w8_hpad_loop + jmp .calc_avg_mul + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + pmovzxbw m1, [yq] + pmovzxbw m0, [yq+strideq] + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + pmaddwd m1, m5 + paddd m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg + jmp .w16_hpad +.w16_wpad: + mova m3, [cfl_ac_444_w16_pad1_shuffle] +.w16_wpad_loop: + vpbroadcastq m1, [yq] + vpbroadcastq m0, [yq+strideq] + pshufb m1, m3 + pshufb m0, m3 + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m1, m0 + pmaddwd m1, m5 + paddd m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_wpad_loop + test hpadd, hpadd + jz .calc_avg +.w16_hpad: + paddw m1, m0, m0 + pmaddwd m1, m5 +.w16_hpad_loop: + mova [acq], m0 + mova [acq+32], m0 + paddd m4, m1 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + jmp .calc_avg + +.w32: + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + pmovzxbw m1, [yq] + pmovzxbw m0, [yq+16] + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m2, m1, m0 + pmaddwd m2, m5 + paddd m4, m2 + add yq, strideq + add acq, 64 + dec hd + jg .w32_loop + test hpadd, hpadd + jz .calc_avg + jmp .w32_hpad_loop +.w32_wpad: + DEFINE_ARGS ac, y, stride, wpad, hpad, iptr, h, sz, ac_bak + lea iptrq, [ipred_cfl_ac_444_avx2_table] + add wpadd, wpadd + mova m3, [iptrq+cfl_ac_444_w16_pad1_shuffle-ipred_cfl_ac_444_avx2_table] + movsxd wpadq, [iptrq+wpadq+4] + add iptrq, wpadq + jmp iptrq +.w32_pad3: + vpbroadcastq m1, [yq] + pshufb m1, m3 + vpermq m0, m1, q3232 + jmp .w32_wpad_end +.w32_pad2: + pmovzxbw m1, [yq] + pshufhw m0, m1, q3333 + vpermq m0, m0, q3333 + jmp .w32_wpad_end +.w32_pad1: + pmovzxbw m1, [yq] + vpbroadcastq m0, [yq+16] + pshufb m0, m3 + ; fall-through +.w32_wpad_end: + psllw m1, 3 + psllw m0, 3 + mova [acq], m1 + mova [acq+32], m0 + paddw m2, m1, m0 + pmaddwd m2, m5 + paddd m4, m2 + add yq, strideq + add acq, 64 + dec hd + jz .w32_wpad_done + jmp iptrq +.w32_wpad_done: + test hpadd, hpadd + jz .calc_avg +.w32_hpad_loop: + mova [acq], m1 + mova [acq+32], m0 + paddd m4, m2 + add acq, 64 + dec hpadd + jg .w32_hpad_loop + jmp .calc_avg + +.calc_avg_mul: + pmaddwd m4, m5 +.calc_avg: + vextracti128 xm1, m4, 1 + tzcnt r1d, szd + paddd xm0, xm4, xm1 + movd xm2, r1d + movd xm3, szd + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 + psrad xm3, 1 + psrlq xm1, xm0, 32 + paddd xm0, xm3 + paddd xm0, xm1 + psrad xm0, xm2 + vpbroadcastw m0, xm0 +.sub_loop: + mova m1, [ac_bakq] + psubw m1, m0 + mova [ac_bakq], m1 + add ac_bakq, 32 + sub szd, 16 + jg .sub_loop + RET + +cglobal pal_pred_8bpc, 4, 6, 5, dst, stride, pal, idx, w, h + vbroadcasti128 m4, [palq] + lea r2, [pal_pred_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r2+wq*4] + packuswb m4, m4 + add wq, r2 + lea r2, [strideq*3] + jmp wq +.w4: + pshufb xm0, xm4, [idxq] + add idxq, 16 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+r2 ], xm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + pshufb xm0, xm4, [idxq+16*0] + pshufb xm1, xm4, [idxq+16*1] + add idxq, 16*2 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r2 ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + add idxq, 32*2 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+r2 ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +ALIGN function_align +.w32: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + pshufb m2, m4, [idxq+32*2] + pshufb m3, m4, [idxq+32*3] + add idxq, 32*4 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r2 ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +ALIGN function_align +.w64: + pshufb m0, m4, [idxq+32*0] + pshufb m1, m4, [idxq+32*1] + pshufb m2, m4, [idxq+32*2] + pshufb m3, m4, [idxq+32*3] + add idxq, 32*4 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64 + RET + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1432 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +; dav1d_filter_intra_taps[], reordered for VNNI: p1 p2 p3 p4, p6 p5 p0 __ +filter_taps: db 10, 0, 0, 0, 2, 10, 0, 0, 1, 1, 10, 0, 1, 1, 2, 10 + db 6, 0, 0, 0, 2, 6, 0, 0, 2, 2, 6, 0, 1, 2, 2, 6 + db 0, 12, -6, 0, 0, 9, -5, 0, 0, 7, -3, 0, 0, 5, -3, 0 + db 12, 2, -4, 0, 9, 2, -3, 0, 7, 2, -3, 0, 5, 3, -3, 0 + db 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16 + db 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16 + db 0, 10,-10, 0, 0, 6, -6, 0, 0, 4, -4, 0, 0, 2, -2, 0 + db 10, 0,-10, 0, 6, 0, -6, 0, 4, 0, -4, 0, 2, 0, -2, 0 + db 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 8 + db 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4 + db 0, 16, -8, 0, 0, 16, -8, 0, 0, 16, -8, 0, 0, 16, -8, 0 + db 16, 0, -4, 0, 16, 0, -4, 0, 16, 0, -4, 0, 16, 0, -4, 0 + db 8, 0, 0, 0, 3, 8, 0, 0, 2, 3, 8, 0, 1, 2, 3, 8 + db 4, 0, 0, 0, 3, 4, 0, 0, 2, 3, 4, 0, 2, 2, 3, 4 + db 0, 10, -2, 0, 0, 6, -1, 0, 0, 4, -1, 0, 0, 2, 0, 0 + db 10, 3, -1, 0, 6, 4, -1, 0, 4, 4, -1, 0, 3, 3, -1, 0 + db 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 14 + db 12, 0, 0, 0, 1, 12, 0, 0, 0, 0, 12, 0, 0, 0, 1, 12 + db 0, 14,-12, 0, 0, 12,-10, 0, 0, 11, -9, 0, 0, 10, -8, 0 + db 14, 0,-10, 0, 12, 0, -9, 0, 11, 1, -8, 0, 9, 1, -7, 0 +filter_perm: db 0, 1, 2, 3, 24, 25, 26, 27, 4, 5, 6, 7, 28, 29, 30, 31 + db 15, 11, 7, 3, 15, 11, 7, 3, 15, 11, 7, 3, 15, 11, 7,131 + db 31, 27, 23, 19, 31, 27, 23, 19, 31, 27, 23, 19, 31, 27, 23,147 + db 47, 43, 39, 35, 47, 43, 39, 35, 47, 43, 39, 35, 47, 43, 39,163 +filter_end: dd 2, 3, 16, 17, -1, -1, 20, 21, 0, 6, 24, 30, 1, 7, 25, 31 +smooth_shuf: db 7, 7, 7, 7, 0, 1, 0, 1, 3, 3, 3, 3, 8, 9, 8, 9 + db 5, 5, 5, 5, 4, 5, 4, 5, 1, 1, 1, 1, 12, 13, 12, 13 + db 6, 6, 6, 6, 2, 3, 2, 3, 2, 2, 2, 2, 10, 11, 10, 11 + db 4, 4, 4, 4, 6, 7, 6, 7, 0, 0, 0, 0, 14, 15, 14, 15 +smooth_endA: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + db 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95 + db 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127 +smooth_endB: db 1, 3, 5, 7, 9, 11, 13, 15, 65, 67, 69, 71, 73, 75, 77, 79 + db 17, 19, 21, 23, 25, 27, 29, 31, 81, 83, 85, 87, 89, 91, 93, 95 + db 33, 35, 37, 39, 41, 43, 45, 47, 97, 99,101,103,105,107,109,111 + db 49, 51, 53, 55, 57, 59, 61, 63,113,115,117,119,121,123,125,127 +ipred_h_shuf: db 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4 + db 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 + +pb_127_m127: times 2 db 127, -127 +pb_128: times 4 db 128 +pw_128: times 2 dw 128 +pw_255: times 2 dw 255 + +%define pb_1 (ipred_h_shuf+24) +%define pb_2 (ipred_h_shuf+20) +%define pb_3 (ipred_h_shuf+16) +%define pd_8 (filter_taps+128) + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_8bpc_avx512icl_table (ipred_dc_8bpc_avx512icl_table + 10*4) + +JMP_TABLE ipred_h_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h_8bpc, avx512icl, w4, w8, w16, w32, w64 +JMP_TABLE ipred_dc_8bpc, avx512icl, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left_8bpc, avx512icl, h4, h8, h16, h32, h64 +JMP_TABLE pal_pred_8bpc, avx512icl, w4, w8, w16, w32, w64 + +SECTION .text + +INIT_ZMM avx512icl +cglobal ipred_dc_top_8bpc, 3, 7, 5, dst, stride, tl, w, h + lea r5, [ipred_dc_left_8bpc_avx512icl_table] + movd xm0, wm + tzcnt wd, wm + inc tlq + movifnidn hd, hm + movu ym1, [tlq] + movd xmm3, wd + movsxd r6, [r5+wq*4] + vpbroadcastd ym2, [r5-ipred_dc_left_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + vpdpbusd ym0, ym1, ym2 + add r6, r5 + add r5, ipred_dc_splat_8bpc_avx512icl_table-ipred_dc_left_8bpc_avx512icl_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +cglobal ipred_dc_left_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_left_8bpc_avx512icl_table] + mov hd, hm + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movd xm0, hm + movu ym1, [tlq] + movd xmm3, r6d + movsxd r6, [r5+r6*4] + vpbroadcastd ym2, [r5-ipred_dc_left_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + vpdpbusd ym0, ym1, ym2 + add r6, r5 + add r5, ipred_dc_splat_8bpc_avx512icl_table-ipred_dc_left_8bpc_avx512icl_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu ym1, [tlq+32] ; unaligned when jumping here from dc_top + vpdpbusd ym0, ym1, ym2 +.h32: + vextracti32x4 xm1, ym0, 1 + paddd xm0, xm1 +.h16: + punpckhqdq xm1, xm0, xm0 + paddd xm0, xm1 +.h8: + psrlq xm1, xm0, 32 + paddd xm0, xm1 +.h4: + vpsrlvd xm0, xmm3 + lea stride3q, [strideq*3] + vpbroadcastb m0, xm0 + jmp wq + +cglobal ipred_dc_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd xm0, r5d + tzcnt r5d, r5d + movd xmm4, r5d + lea r5, [ipred_dc_8bpc_avx512icl_table] + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+5*4] + vpbroadcastd ym3, [r5-ipred_dc_8bpc_avx512icl_table+pb_1] + psrld xm0, 1 + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd xmm1, [tlq-4] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w4: + movd xmm1, [tlq+1] + vpdpbusd xm0, xmm1, xm3 + cmp hd, 4 + jg .w4_mul + psrlw xmm0, xm0, 3 + jmp .w4_end +.w4_mul: + punpckhqdq xmm1, xm0, xm0 + lea r2d, [hq*2] + mov r6d, 0x55563334 + paddd xmm1, xm0 + shrx r6d, r6d, r2d + psrlq xmm0, xmm1, 32 + paddd xmm0, xmm1 + movd xmm1, r6d + psrld xmm0, 2 + pmulhuw xmm0, xmm1 +.w4_end: + vpbroadcastb xm0, xmm0 +.s4: + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm0 + movd [dstq+strideq*2], xm0 + movd [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +.h8: + movq xmm1, [tlq-8] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w8: + movq xmm1, [tlq+1] + vextracti32x4 xm2, ym0, 1 + vpdpbusd xm0, xmm1, xm3 + paddd xmm2, xm2, xm0 + punpckhqdq xmm0, xmm2, xmm2 + paddd xmm0, xmm2 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmove r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w8_end: + vpbroadcastb xm0, xmm0 +.s8: + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm0 + movq [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +.h16: + mova xmm1, [tlq-16] + vpdpbusd xm0, xmm1, xm3 + jmp wq +.w16: + movu xmm1, [tlq+1] + vextracti32x4 xm2, ym0, 1 + vpdpbusd xm0, xmm1, xm3 + paddd xmm2, xm2, xm0 + punpckhqdq xmm0, xmm2, xmm2 + paddd xmm0, xmm2 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hb, 8|32 + cmovz r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w16_end: + vpbroadcastb xm0, xmm0 +.s16: + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm0 + mova [dstq+strideq*2], xm0 + mova [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +.h32: + mova ym1, [tlq-32] + vpdpbusd ym0, ym1, ym3 + jmp wq +.w32: + movu ym1, [tlq+1] + vpdpbusd ym0, ym1, ym3 + vextracti32x4 xm1, ym0, 1 + paddd xmm1, xm1, xm0 + punpckhqdq xmm0, xmm1, xmm1 + paddd xmm0, xmm1 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x33345556 + shrx r6d, r6d, r2d + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w32_end: + vpbroadcastb ym0, xmm0 +.s32: + mova [dstq+strideq*0], ym0 + mova [dstq+strideq*1], ym0 + mova [dstq+strideq*2], ym0 + mova [dstq+stride3q ], ym0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +.h64: + mova ym1, [tlq-64] + mova ym2, [tlq-32] + vpdpbusd ym0, ym1, ym3 + vpdpbusd ym0, ym2, ym3 + jmp wq +.w64: + movu ym1, [tlq+ 1] + movu ym2, [tlq+33] + vpdpbusd ym0, ym1, ym3 + vpdpbusd ym0, ym2, ym3 + vextracti32x4 xm1, ym0, 1 + paddd xmm1, xm1, xm0 + punpckhqdq xmm0, xmm1, xmm1 + paddd xmm0, xmm1 + psrlq xmm1, xmm0, 32 + paddd xmm0, xmm1 + vpsrlvd xmm0, xmm4 + cmp hd, 64 + je .w64_end + mov r6d, 0x33345556 + shrx r6d, r6d, hd + movd xmm1, r6d + pmulhuw xmm0, xmm1 +.w64_end: + vpbroadcastb m0, xmm0 +.s64: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s64 + RET + +cglobal ipred_dc_128_8bpc, 2, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_8bpc_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m0, [r5-ipred_dc_splat_8bpc_avx512icl_table+pb_128] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_v_8bpc, 3, 7, 5, dst, stride, tl, w, h, stride3 + lea r5, [ipred_dc_splat_8bpc_avx512icl_table] + tzcnt wd, wm + movu m0, [tlq+1] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +cglobal ipred_h_8bpc, 3, 7, 8, dst, stride, tl, w, h, stride3 +%define base r6-ipred_h_8bpc_avx512icl_table + lea r6, [ipred_h_8bpc_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea stride3q, [strideq*3] + sub tlq, hq + add wq, r6 + jmp wq +.w4: + mova xmm1, [base+ipred_h_shuf+16] +.w4_loop: + movd xmm0, [tlq+hq-4] + pshufb xmm0, xmm1 + movd [dstq+strideq*0], xmm0 + pextrd [dstq+strideq*1], xmm0, 1 + pextrd [dstq+strideq*2], xmm0, 2 + pextrd [dstq+stride3q ], xmm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +.w8: + movsldup xmm2, [base+ipred_h_shuf+16] + movshdup xmm3, [base+ipred_h_shuf+16] +.w8_loop: + movd xmm1, [tlq+hq-4] + pshufb xmm0, xmm1, xmm2 + pshufb xmm1, xmm3 + movq [dstq+strideq*0], xmm0 + movq [dstq+strideq*1], xmm1 + movhps [dstq+strideq*2], xmm0 + movhps [dstq+stride3q ], xmm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + movsldup m1, [base+smooth_shuf] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + pshufb m0, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + vpbroadcastd ym3, [base+pb_1] + vpord m2, m3, [base+pb_2] {1to16} +.w32_loop: + vpbroadcastd m1, [tlq+hq-4] + pshufb m0, m1, m2 + pshufb m1, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32_loop + RET +.w64: + vpbroadcastd m4, [base+pb_3] + vpbroadcastd m5, [base+pb_2] + vpbroadcastd m6, [base+pb_1] + pxor m7, m7 +.w64_loop: + vpbroadcastd m3, [tlq+hq-4] + pshufb m0, m3, m4 + pshufb m1, m3, m5 + pshufb m2, m3, m6 + pshufb m3, m7 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64_loop + RET + +%macro PAETH 0 + psubusb m1, m5, m4 + psubusb m0, m4, m5 + por m1, m0 ; tdiff + pavgb m2, m6, m4 + vpcmpub k1, m1, m7, 1 ; tdiff < ldiff + vpblendmb m0{k1}, m4, m6 + vpternlogd m4, m6, m8, 0x28 ; (m4 ^ m6) & m8 + psubusb m3, m5, m2 + psubb m2, m4 + psubusb m2, m5 + por m2, m3 + pminub m1, m7 + paddusb m2, m2 + por m2, m4 ; min(tldiff, 255) + vpcmpub k1, m2, m1, 1 ; tldiff < ldiff && tldiff < tdiff + vmovdqu8 m0{k1}, m5 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 7, 10, dst, stride, tl, w, h, top, stride3 + lea r6, [ipred_paeth_8bpc_avx512icl_table] + tzcnt wd, wm + vpbroadcastb m5, [tlq] ; topleft + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m8, [r6-ipred_paeth_8bpc_avx512icl_table+pb_1] + lea topq, [tlq+1] + sub tlq, hq + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +INIT_YMM avx512icl +.w4: + vpbroadcastd m6, [topq] + mova m9, [ipred_h_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + vpbroadcastq m4, [tlq+hq-8] + pshufb m4, m9 ; left + PAETH + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm0, 3 + sub hd, 8 + jl .w4_ret + vextracti32x4 xm0, m0, 1 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm0, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.w4_ret: + RET +INIT_ZMM avx512icl +.w8: + vpbroadcastq m6, [topq] + movsldup m9, [smooth_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + vpbroadcastq m4, [tlq+hq-8] + pshufb m4, m9 + PAETH + vextracti32x4 xm1, m0, 2 + vextracti32x4 xm2, ym0, 1 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + sub hd, 8 + jl .w8_ret + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + jg .w8_loop +.w8_ret: + RET +.w16: + vbroadcasti32x4 m6, [topq] + movsldup m9, [smooth_shuf] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + vpbroadcastd m4, [tlq+hq-4] + pshufb m4, m9 + PAETH + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + vbroadcasti32x8 m6, [topq] + mova ym9, ym8 + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w32_loop: + vpbroadcastd m4, [tlq+hq-2] + pshufb m4, m9 + PAETH + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + movu m6, [topq] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w64_loop: + vpbroadcastb m4, [tlq+hq-1] + PAETH + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_v_8bpc, 3, 7, 7, dst, stride, tl, w, h, weights, stride3 +%define base r6-ipred_smooth_v_8bpc_avx512icl_table + lea r6, [ipred_smooth_v_8bpc_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m0, [base+pb_127_m127] + vpbroadcastd m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + vpbroadcastb m4, [tlq+hq] ; bottom + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastd m2, [tlq+1] + movshdup m5, [smooth_shuf] + mova ym6, [smooth_endA] + punpcklbw m2, m4 ; top, bottom + pmaddubsw m3, m2, m0 + paddw m1, m2 ; 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; 128 * top + 129 * bottom + 128 +.w4_loop: + vbroadcasti32x4 m0, [weightsq+hq*2] + pshufb m0, m5 + pmaddubsw m0, m2, m0 + paddw m0, m3 + vpermb m0, m6, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + add hq, 8 + jg .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jl .w4_loop +.ret: + RET +.w8: + vpbroadcastq m2, [tlq+1] + movshdup m5, [smooth_shuf] + mova ym6, [smooth_endA] + punpcklbw m2, m4 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 +.w8_loop: + vpbroadcastq m0, [weightsq+hq*2] + pshufb m0, m5 + pmaddubsw m0, m2, m0 + paddw m0, m3 + vpermb m0, m6, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w8_loop + RET +.w16: + vbroadcasti32x4 m3, [tlq+1] + movshdup m6, [smooth_shuf] + mova m7, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w16_loop: + vpbroadcastq m1, [weightsq+hq*2] + pshufb m1, m6 + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m7, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w16_loop + RET +.w32: + vbroadcasti32x8 m3, [tlq+1] + movshdup m6, [smooth_shuf] + mova m7, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w32_loop: + vpbroadcastd m1, [weightsq+hq*2] + pshufb m1, m6 + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m7, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + movu m3, [tlq+1] + mova m6, [smooth_endB] + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 +.w64_loop: + vpbroadcastw m1, [weightsq+hq*2] + pmaddubsw m0, m2, m1 + pmaddubsw m1, m3, m1 + paddw m0, m4 + paddw m1, m5 + vpermt2b m0, m6, m1 + mova [dstq], m0 + add dstq, strideq + inc hq + jl .w64_loop + RET + +cglobal ipred_smooth_h_8bpc, 4, 7, 11, dst, stride, tl, w, h, stride3 +%define base r5-ipred_smooth_h_8bpc_avx512icl_table + lea r5, [ipred_smooth_h_8bpc_avx512icl_table] + mov r6d, wd + tzcnt wd, wd + vpbroadcastb m4, [tlq+r6] ; right + mov hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m5, [base+pb_127_m127] + vpbroadcastd m6, [base+pw_128] + sub tlq, hq + add wq, r5 + vpmovb2m k1, m6 + lea stride3q, [strideq*3] + jmp wq +.w4: + movsldup m3, [smooth_shuf] + vpbroadcastq m7, [smooth_weights+4*2] + mova ym8, [smooth_endA] +.w4_loop: + vpbroadcastq m0, [tlq+hq-8] + mova m2, m4 + vpshufb m2{k1}, m0, m3 ; left, right + pmaddubsw m0, m2, m5 + pmaddubsw m1, m2, m7 + paddw m2, m6 + paddw m0, m2 + paddw m0, m1 + vpermb m0, m8, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + sub hd, 8 + jl .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.ret: + RET +.w8: + movsldup m3, [smooth_shuf] + vbroadcasti32x4 m7, [smooth_weights+8*2] + mova ym8, [smooth_endA] +.w8_loop: + vpbroadcastd m0, [tlq+hq-4] + mova m2, m4 + vpshufb m2{k1}, m0, m3 + pmaddubsw m0, m2, m5 + pmaddubsw m1, m2, m7 + paddw m2, m6 + paddw m0, m2 + paddw m0, m1 + vpermb m0, m8, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + movsldup m7, [smooth_shuf] + vbroadcasti32x4 m8, [smooth_weights+16*2] + vbroadcasti32x4 m9, [smooth_weights+16*3] + mova m10, [smooth_endB] +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + mova m3, m4 + vpshufb m3{k1}, m0, m7 + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m8 + pmaddubsw m1, m3, m9 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m10, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + mova m10, [smooth_endA] + vpbroadcastd ym7, [pb_1] + vbroadcasti32x8 m8, [smooth_weights+32*2] + vbroadcasti32x8 m9, [smooth_weights+32*3] + vshufi32x4 m10, m10, q3120 +.w32_loop: + vpbroadcastd m0, [tlq+hq-2] + mova m3, m4 + vpshufb m3{k1}, m0, m7 + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m8 + pmaddubsw m1, m3, m9 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m10, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + mova m7, [smooth_weights+64*2] + mova m8, [smooth_weights+64*3] + mova m9, [smooth_endA] +.w64_loop: + mova m3, m4 + vpbroadcastb m3{k1}, [tlq+hq-1] + pmaddubsw m2, m3, m5 + pmaddubsw m0, m3, m7 + pmaddubsw m1, m3, m8 + paddw m3, m6 + paddw m2, m3 + paddw m0, m2 + paddw m1, m2 + vpermt2b m0, m9, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal ipred_smooth_8bpc, 4, 7, 16, dst, stride, tl, w, h, v_weights, stride3 +%define base r5-ipred_smooth_8bpc_avx512icl_table + lea r5, [ipred_smooth_8bpc_avx512icl_table] + mov r6d, wd + tzcnt wd, wd + mov hd, hm + vpbroadcastb m6, [tlq+r6] ; right + sub tlq, hq + movsxd wq, [r5+wq*4] + vpbroadcastd m7, [base+pb_127_m127] + vpbroadcastb m0, [tlq] ; bottom + vpbroadcastd m1, [base+pw_255] + add wq, r5 + lea v_weightsq, [base+smooth_weights+hq*2] + vpmovb2m k1, m1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vpbroadcastd m8, [tlq+hq+1] + movsldup m4, [smooth_shuf] + movshdup m5, [smooth_shuf] + vpbroadcastq m9, [smooth_weights+4*2] + mova ym11, [smooth_endA] + + punpcklbw m8, m0 ; top, bottom + pmaddubsw m10, m8, m7 + paddw m1, m8 ; 1 * top + 256 * bottom + 255 + paddw m10, m1 ; 128 * top + 129 * bottom + 255 +.w4_loop: + vpbroadcastq m1, [tlq+hq-8] + vbroadcasti32x4 m0, [v_weightsq] + add v_weightsq, 16 + mova m2, m6 + vpshufb m2{k1}, m1, m4 ; left, right + pmaddubsw m1, m2, m7 ; 127 * left - 127 * right + pshufb m0, m5 + pmaddubsw m0, m8, m0 + paddw m1, m2 ; 128 * left + 129 * right + pmaddubsw m2, m9 + paddw m0, m10 + paddw m1, m2 + pavgw m0, m1 + vpermb m0, m11, m0 + vextracti32x4 xm1, ym0, 1 + movd [dstq+strideq*0], xm0 + movd [dstq+strideq*1], xm1 + pextrd [dstq+strideq*2], xm0, 2 + pextrd [dstq+stride3q ], xm1, 2 + sub hd, 8 + jl .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 1 + pextrd [dstq+strideq*1], xm1, 1 + pextrd [dstq+strideq*2], xm0, 3 + pextrd [dstq+stride3q ], xm1, 3 + lea dstq, [dstq+strideq*4] + jg .w4_loop +.ret: + RET +.w8: + vpbroadcastq m8, [tlq+hq+1] + movsldup m4, [smooth_shuf] + movshdup m5, [smooth_shuf] + vbroadcasti32x4 m9, [smooth_weights+8*2] + mova ym11, [smooth_endA] + punpcklbw m8, m0 + pmaddubsw m10, m8, m7 + paddw m1, m8 + paddw m10, m1 +.w8_loop: + vpbroadcastd m1, [tlq+hq-4] + vpbroadcastq m0, [v_weightsq] + add v_weightsq, 8 + mova m2, m6 + vpshufb m2{k1}, m1, m4 + pmaddubsw m1, m2, m7 + pshufb m0, m5 + pmaddubsw m0, m8, m0 + paddw m1, m2 + pmaddubsw m2, m9 + paddw m0, m10 + paddw m1, m2 + pavgw m0, m1 + vpermb m0, m11, m0 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8_loop + RET +.w16: + vbroadcasti32x4 m9, [tlq+hq+1] + movsldup m5, [smooth_shuf] + movshdup m10, [smooth_shuf] + vbroadcasti32x4 m11, [smooth_weights+16*2] + vbroadcasti32x4 m12, [smooth_weights+16*3] + mova m15, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m13, m8, m7 + pmaddubsw m14, m9, m7 + paddw m0, m1, m8 + paddw m1, m9 + paddw m13, m0 + paddw m14, m1 +.w16_loop: + vpbroadcastd m0, [tlq+hq-4] + vpbroadcastq m1, [v_weightsq] + add v_weightsq, 8 + mova m4, m6 + vpshufb m4{k1}, m0, m5 + pmaddubsw m2, m4, m7 + pshufb m1, m10 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m11 + pmaddubsw m4, m12 + paddw m0, m13 + paddw m1, m14 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m15, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + vbroadcasti32x8 m9, [tlq+hq+1] + movshdup m10, [smooth_shuf] + mova m12, [smooth_weights+32*2] + vpbroadcastd ym5, [pb_1] + mova m15, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m13, m8, m7 + pmaddubsw m14, m9, m7 + vshufi32x4 m11, m12, m12, q2020 + vshufi32x4 m12, m12, q3131 + paddw m0, m1, m8 + paddw m1, m9 + paddw m13, m0 + paddw m14, m1 +.w32_loop: + vpbroadcastd m0, [tlq+hq-2] + vpbroadcastd m1, [v_weightsq] + add v_weightsq, 4 + mova m4, m6 + vpshufb m4{k1}, m0, m5 + pmaddubsw m2, m4, m7 + pshufb m1, m10 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m11 + pmaddubsw m4, m12 + paddw m0, m13 + paddw m1, m14 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m15, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + movu m9, [tlq+hq+1] + mova m11, [smooth_weights+64*2] + mova m2, [smooth_weights+64*3] + mova m14, [smooth_endB] + punpcklbw m8, m9, m0 + punpckhbw m9, m0 + pmaddubsw m12, m8, m7 + pmaddubsw m13, m9, m7 + vshufi32x4 m10, m11, m2, q2020 + vshufi32x4 m11, m2, q3131 + paddw m0, m1, m8 + paddw m1, m9 + paddw m12, m0 + paddw m13, m1 +.w64_loop: + mova m4, m6 + vpbroadcastb m4{k1}, [tlq+hq-1] + vpbroadcastw m1, [v_weightsq] + add v_weightsq, 2 + pmaddubsw m2, m4, m7 + pmaddubsw m0, m8, m1 + pmaddubsw m1, m9, m1 + paddw m2, m4 + pmaddubsw m3, m4, m10 + pmaddubsw m4, m11 + paddw m0, m12 + paddw m1, m13 + paddw m3, m2 + paddw m4, m2 + pavgw m0, m3 + pavgw m1, m4 + vpermt2b m0, m14, m1 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET + +cglobal pal_pred_8bpc, 4, 7, 5, dst, stride, pal, idx, w, h, stride3 + lea r6, [pal_pred_8bpc_avx512icl_table] + tzcnt wd, wm + vbroadcasti32x4 m4, [palq] + movifnidn hd, hm + movsxd wq, [r6+wq*4] + packuswb m4, m4 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.w4: + pshufb xmm0, xm4, [idxq] + add idxq, 16 + movd [dstq+strideq*0], xmm0 + pextrd [dstq+strideq*1], xmm0, 1 + pextrd [dstq+strideq*2], xmm0, 2 + pextrd [dstq+stride3q ], xmm0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pshufb xmm0, xm4, [idxq+16*0] + pshufb xmm1, xm4, [idxq+16*1] + add idxq, 16*2 + movq [dstq+strideq*0], xmm0 + movhps [dstq+strideq*1], xmm0 + movq [dstq+strideq*2], xmm1 + movhps [dstq+stride3q ], xmm1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pshufb m0, m4, [idxq] + add idxq, 64 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +.w32: + pshufb m0, m4, [idxq+64*0] + pshufb m1, m4, [idxq+64*1] + add idxq, 64*2 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w32 + RET +.w64: + pshufb m0, m4, [idxq+64*0] + pshufb m1, m4, [idxq+64*1] + pshufb m2, m4, [idxq+64*2] + pshufb m3, m4, [idxq+64*3] + add idxq, 64*4 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w64 + RET + +; The ipred_filter code processes 4x2 blocks in the following order +; which increases parallelism compared to doing things row by row. +; Some redundant blocks are calculated for w > 4. +; w4 w8 w16 w32 +; 1 1 2 1 2 3 4 1 2 3 4 9 a b c +; 2 2 3 2 3 4 5 2 3 4 5 a b c d +; 3 3 4 3 4 5 6 3 4 5 6 b c d e +; 4 4 5 4 5 6 7 4 5 6 7 c d e f +; 5 5 6 5 6 7 8 5 6 7 8 d e f g +; 6 6 7 6 7 8 9 6 7 8 9 e f g h +; 7 7 8 7 8 9 a 7 8 9 a f g h i +; ___ 8 ___ 8 9 ___ 8 9 a b ___ 8 9 a b g h i j ___ +; 9 9 a b h i j +; a b i j +; b j + +cglobal ipred_filter_8bpc, 4, 7, 14, dst, stride, tl, w, h, flt +%define base r6-filter_taps + lea r6, [filter_taps] +%ifidn fltd, fltm + movzx fltd, fltb +%else + movzx fltd, byte fltm +%endif + vpbroadcastd xmm2, [tlq+1] ; t0 t0 t0 t0 + movifnidn hd, hm + shl fltd, 6 + vpbroadcastd m6, [base+pd_8] + vpbroadcastd xmm3, [tlq-2] ; l1 l0 tl __ + vbroadcasti32x4 m7, [r6+fltq+16*0] ; p1 p2 p3 p4 + vbroadcasti32x4 m8, [r6+fltq+16*1] + vbroadcasti32x4 m9, [r6+fltq+16*2] ; p6 p5 p0 __ + vbroadcasti32x4 m10, [r6+fltq+16*3] + mova xmm0, xm6 + vpdpbusd xmm0, xmm2, xm7 + mova xmm1, xm6 + vpdpbusd xmm1, xmm2, xm8 + vpdpbusd xmm0, xmm3, xm9 + vpdpbusd xmm1, xmm3, xm10 + packssdw xmm0, xmm1 + cmp wd, 8 + jb .w4 + vpbroadcastd ym2, [tlq+5] + mova m11, [base+filter_perm] + mov r5, 0xffffffffffff000f + psrldq xmm2, 1 ; __ t0 + kmovq k1, r5 ; 0x000f + psraw xm5, xmm0, 4 + packuswb xmm2, xm5 ; __ t0 a0 b0 + pshufd ym2{k1}, ymm2, q3333 ; b0 b0 b0 b0 t1 t1 t1 t1 + je .w8 + kxnorb k3, k3, k3 ; 0x00ff + vpbroadcastd xm3, [tlq-4] + kandnq k2, k3, k1 ; 0xffffffffffff0000 + vpermb ym3{k2}, ym11, ymm2 ; l3 l2 l1 __ b3 a3 t3 __ + mova ym0, ym6 + vpdpbusd ym0, ym2, ym7 + mova ym1, ym6 + vpdpbusd ym1, ym2, ym8 + pshufb ym5{k2}, ym2, ym11 ; a0 b0 __ t0 + vpbroadcastd m2, [tlq+9] + vpdpbusd ym0, ym3, ym9 + vpdpbusd ym1, ym3, ym10 + vpbroadcastd xm3, [tlq-6] ; l5 l4 l3 __ + kunpckbw k4, k1, k3 ; 0x0fff + packssdw ym0, ym1 + psraw ym0, 4 ; a0 d0 a1 b1 + packuswb ym5, ym0 ; a0 b0 c0 d0 __ t1 a1 b1 + pshufd m2{k3}, m5, q3333 ; d0 d0 d0 d0 b1 b1 b1 b1 t2 t2 t2 t2 + vpermb m3{k2}, m11, m5 ; l5 l4 l3 __ d3 c3 b3 __ b7 a7 t7 __ + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + psrldq m0, m2, 1 ; __ d0 __ b0 __ t0 + vpbroadcastd m2, [tlq+13] + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + mova m12, [base+filter_end] + lea r5d, [hq-6] + mov r6, dstq + cmovp hd, r5d ; w == 16 ? h : h - 6 + packssdw m4, m1 + psraw m4, 4 ; e0 f0 c1 d1 a2 b2 + packuswb m0, m4 ; __ d0 e0 f0 __ b1 c1 d1 __ t2 a2 b2 + pshufd m2{k4}, m0, q3333 ; f0 f0 f0 f0 d1 d1 d1 d1 b2 b2 b2 b2 t3 t3 t3 t3 +.w16_loop: + vpbroadcastd xm3, [tlq-8] + vpermb m3{k2}, m11, m0 ; l7 l6 l5 __ f3 e3 d3 __ d7 c7 b7 __ bb ab tb __ + mova m1, m6 + vpdpbusd m1, m2, m7 + mova m0, m6 + vpdpbusd m0, m2, m8 + sub tlq, 2 + vpdpbusd m1, m3, m9 + vpdpbusd m0, m3, m10 + packssdw m1, m0 + mova m0, m4 + psraw m4, m1, 4 ; g0 h0 e1 f1 c2 d2 a3 b3 + packuswb m0, m4 ; e0 f0 g0 h0 c1 d1 e1 f1 a2 b2 c2 d2 __ __ a3 b3 + pshufd m2, m0, q3333 ; h0 h0 h0 h0 f1 f1 f1 f1 d2 d2 d2 d2 b3 b3 b3 b3 + vpermt2d m5, m12, m0 ; c0 d0 e0 f0 __ __ c1 d1 a0 a1 a2 a3 b0 b1 b2 b3 + vextracti32x4 [dstq+strideq*0], m5, 2 + vextracti32x4 [dstq+strideq*1], m5, 3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + cmp wd, 16 + je .ret + mova xm13, [filter_perm+16] + mova xmm3, [r6+strideq*0] + punpckhdq xmm3, [r6+strideq*1] + vpbroadcastd m2{k1}, [tlq+r5+17] ; t4 t4 t4 t4 f1 f1 f1 f1 d2 d2 d2 d2 b3 b3 b3 b3 + pinsrb xm3, xmm3, [tlq+r5+16], 7 + pshufb xm3, xm13 + vpermb m3{k2}, m11, m0 ; bf af tf __ h3 g3 f3 __ f7 e7 d7 __ db cb bb __ + mova m0, m6 + vpdpbusd m0, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kunpckbw k5, k3, k1 ; 0xff0f + lea r3, [strideq*3] + vpdpbusd m0, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m0, m1 + psraw m0, 4 ; a4 b4 g1 h1 e2 f2 c3 d3 + packuswb m4, m0 ; g0 h0 a4 b4 e1 f1 g1 h1 c2 d2 e2 f2 __ __ c3 d3 + vpblendmb m1{k3}, m4, m2 ; __ t4 a4 b4 e1 f1 g1 h1 c2 d2 e2 f2 __ __ c3 d3 + vpbroadcastd ym2, [tlq+r5+21] + pshufd m2{k5}, m4, q3333 ; b4 b4 b4 b4 t5 t5 t5 t5 f2 f2 f2 f2 d3 d3 d3 d3 + vpermt2d m5, m12, m4 ; e0 f0 g0 h0 __ __ e1 f1 c0 c1 c2 c3 d0 d1 d2 d3 + vextracti32x4 [dstq+strideq*0], m5, 2 + vextracti32x4 [dstq+strideq*1], m5, 3 + punpckhqdq xmm3, [r6+r3] + pinsrb xmm3, [r6+strideq*2+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; df cf bf __ bj aj tj __ h7 g7 f7 __ fb eb db __ + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kxnord k3, k3, k4 ; 0xfffff0ff + lea r4, [strideq*5] + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m4, m1 + psraw m4, 4 ; c4 d4 a5 b5 g2 h2 e3 f3 + packuswb m0, m4 ; a4 b4 c4 d4 g1 h1 a5 b5 e2 f2 g2 h2 __ __ e3 f3 + vpblendmw m1{k3}, m2, m0 ; a4 b4 c4 d4 __ t5 a5 b5 e2 f2 g2 h2 __ __ e3 f3 + vpbroadcastd m2, [tlq+r5+25] + pshufd m2{k3}, m0, q3333 ; d4 d4 d4 d4 b5 b5 b5 b5 t6 t6 t6 t6 f3 f3 f3 f3 + vpermt2d m5, m12, m0 ; g0 h0 a4 b4 __ __ g1 h1 e0 e1 e2 e3 f0 f1 f2 f3 + vextracti32x4 [dstq+strideq*2], m5, 2 + vextracti32x4 [dstq+r3 ], m5, 3 + punpckhqdq xmm3, [r6+r4] + pinsrb xmm3, [r6+strideq*4+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; ff ef df __ dj cj bj __ bn an tn __ hb hb fb __ + mova m0, m6 + vpdpbusd m0, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + kunpckwd k1, k1, k2 ; 0x000f0000 + vpdpbusd m0, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m0, m1 + psraw m0, 4 ; e4 f4 c5 d5 a6 b6 g3 h3 + packuswb m4, m0 ; c4 d4 e4 f4 a5 b5 c5 d5 g2 h2 a6 b6 __ __ g3 h3 + vpblendmw m1{k1}, m4, m2 ; c4 d4 e4 f4 a5 b5 c5 d5 __ t6 a6 b6 __ __ g3 h3 + vpbroadcastd m2, [tlq+r5+29] + pshufd m2{k4}, m4, q3333 ; f4 f4 f4 f4 d5 d5 d5 d5 b6 b6 b6 b6 t7 t7 t7 t7 + vpermt2d m5, m12, m4 ; a4 b4 c4 d4 __ __ a5 b5 g0 g1 g2 g3 h0 h1 h2 h3 + vextracti32x4 [dstq+strideq*4], m5, 2 + vextracti32x4 [dstq+r4 ], m5, 3 + lea r0, [strideq+r3*2] +.w32_loop: + punpckhqdq xmm3, [r6+r0] + pinsrb xmm3, [r6+r3*2+15], 11 + pshufb xm3, xmm3, xm13 + vpermb m3{k2}, m11, m1 ; hf gf ff __ fj ej dj __ dn cn bn __ br ar tr __ +.w32_loop_tail: + mova m4, m6 + vpdpbusd m4, m2, m7 + mova m1, m6 + vpdpbusd m1, m2, m8 + vpdpbusd m4, m3, m9 + vpdpbusd m1, m3, m10 + packssdw m4, m1 + mova m1, m0 + psraw m0, m4, 4 ; g4 h4 e5 f5 c6 d6 a7 b7 + packuswb m1, m0 ; e4 f4 g4 h4 c5 d5 e5 f5 a6 b6 c6 d6 __ __ a7 b7 + pshufd m2, m1, q3333 ; h4 h4 h4 h4 f5 f5 f5 f5 d6 d6 d6 d6 b7 b7 b7 b7 + vpermt2d m5, m12, m1 ; c4 d4 e4 f4 __ __ c5 d5 a4 a5 a6 a7 b4 b5 b6 b7 + vextracti32x4 [r6+strideq*0+16], m5, 2 + vextracti32x4 [r6+strideq*1+16], m5, 3 + lea r6, [r6+strideq*2] + sub r5d, 2 + jg .w32_loop + vpermb m3, m11, m1 + cmp r5d, -6 + jg .w32_loop_tail +.ret: + RET +.w8: + vpermb ym3, ym11, ymm2 +.w8_loop: + vpbroadcastd ym3{k1}, [tlq-4] ; l3 l2 l1 __ b3 a3 t3 __ + mova ym0, ym6 + vpdpbusd ym0, ym2, ym7 + mova ym1, ym6 + vpdpbusd ym1, ym2, ym8 + sub tlq, 2 + vpdpbusd ym0, ym3, ym9 + vpdpbusd ym1, ym3, ym10 + mova ym3, ym5 + packssdw ym0, ym1 + psraw ym5, ym0, 4 ; c0 d0 a1 b1 + packuswb ym3, ym5 ; a0 b0 c0 d0 __ __ a1 b1 + pshufd ym2, ym3, q3333 ; d0 d0 d0 d0 b1 b1 b1 b1 + vpermb ym3, ym11, ym3 ; a0 a1 b0 b1 + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +.w4_loop: + vpbroadcastd xmm3, [tlq-4] ; l3 l2 l1 __ + mova xmm0, xm6 + vpdpbusd xmm0, xmm2, xm7 + mova xmm1, xm6 + vpdpbusd xmm1, xmm2, xm8 + sub tlq, 2 + vpdpbusd xmm0, xmm3, xm9 + vpdpbusd xmm1, xmm3, xm10 + packssdw xmm0, xmm1 +.w4: + psraw xmm0, 4 ; a0 b0 + packuswb xmm0, xmm0 + movd [dstq+strideq*0], xmm0 + pshufd xmm2, xmm0, q1111 ; b0 b0 b0 b0 + movd [dstq+strideq*1], xmm2 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/ipred_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/ipred_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5398 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +%macro SMOOTH_WEIGHT_TABLE 1-* + %rep %0 + db %1-128, 127-%1 + %rotate 1 + %endrep +%endmacro + +; sm_weights[], but modified to precalculate x and 256-x with offsets to +; enable efficient use of pmaddubsw (which requires signed values) +smooth_weights: SMOOTH_WEIGHT_TABLE \ + 0, 0, 255, 128, 255, 149, 85, 64, \ + 255, 197, 146, 105, 73, 50, 37, 32, \ + 255, 225, 196, 170, 145, 123, 102, 84, \ + 68, 54, 43, 33, 26, 20, 17, 16, \ + 255, 240, 225, 210, 196, 182, 169, 157, \ + 145, 133, 122, 111, 101, 92, 83, 74, \ + 66, 59, 52, 45, 39, 34, 29, 25, \ + 21, 17, 14, 12, 10, 9, 8, 8, \ + 255, 248, 240, 233, 225, 218, 210, 203, \ + 196, 189, 182, 176, 169, 163, 156, 150, \ + 144, 138, 133, 127, 121, 116, 111, 106, \ + 101, 96, 91, 86, 82, 77, 73, 69, \ + 65, 61, 57, 54, 50, 47, 44, 41, \ + 38, 35, 32, 29, 27, 25, 22, 20, \ + 18, 16, 15, 13, 12, 10, 9, 8, \ + 7, 6, 6, 5, 5, 4, 4, 4 + +ipred_v_shuf: db 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7 +ipred_h_shuf: db 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 +ipred_paeth_shuf: db 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 +z_upsample1: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z_upsample2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8 +z_transpose4: db 8, 12, 0, 4, 9, 13, 1, 5, 10, 14, 2, 6, 11, 15, 3, 7 +z3_shuf: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +z3_shuf_h4: db 4, 3, 3, 2, 2, 1, 1, 0, 12, 11, 11, 10, 10, 9, 9, 8 +filter_shuf1: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 2, 7, 2, 1, -1, 1, -1 +filter_shuf2: db 3, 4, 3, 4, 5, 6, 5, 6, 7, 11, 7, 11, 15, -1, 15, -1 +z_filter_wh4: db 7, 7, 19, 7, +z_filter_wh8: db 19, 19, 11, 19, 11, 15, 15, 15, 23, 23, 23, 23, 39, 39, 39, 39 +pd_32768: dd 32768 +z3_filter_k_tail: db 64, 0, 64, 0, 64, 0, 56, 8 +z1_shuf_w4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +pb_0to15: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +pb_15to0: db 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +z_base_inc: dw 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 +z3_base_inc: dw 7*64, 6*64, 5*64, 4*64, 3*64, 2*64, 1*64, 0*64 +z_filter_wh16: db 19, 19, 19, 23, 23, 23, 31, 31, 31, 47, 47, 47, 79, 79, 79, -1 +z_filter_t_w48: db 55,127, 7,127, 15, 31, 39, 31,127, 39,127, 39, 7, 15, 31, 15 + db 39, 63, 3, 63, 3, 3, 19, 3, 47, 19, 47, 19, 3, 3, 3, 3 +z_filter_t_w16: db 15, 31, 7, 15, 31, 7, 3, 31, 3, 3, 3, 3, 3, 3, 0, 0 +z_filter_s: db 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 + db 7, 8, 8, 9, 9, 10, 10, 11 +z_filter_k_tail: db 0, 64, 0, 64, 8, 56, 0, 64 +z2_h_shuf: db 7, 6, 15, 14, 6, 5, 14, 13, 5, 4, 13, 12, 4, 3, 12, 11 +z2_upsample: db 7, 6, 15, 14, 5, 4, 13, 12, 3, 2, 11, 10, 1, 0, 9, 8 +z2_dy_offset: dw 88*64, 88*64, 87*64, 87*64 +pw_m1to4: dw -1, -2, -3, -4 +z_filter_k: times 4 db 0, 16 + times 4 db 0, 20 + times 4 db 8, 16 + times 4 db 32, 16 + times 4 db 24, 20 + times 4 db 16, 16 + times 4 db 0, 0 + times 4 db 0, 0 +pw_8: times 8 db 8, 0 +pb_3: times 16 db 3 +pb_16: times 16 db 16 +pw_62: times 8 dw 62 +pw_64: times 8 dw 64 +pw_256: times 8 dw 256 +pw_512: times 8 dw 512 +pw_m256: times 8 dw -256 +pb_2: times 8 db 2 +pb_4: times 8 db 4 +pb_8: times 8 db 8 +pb_128: times 8 db 128 +pb_m16: times 8 db -16 +pw_128: times 4 dw 128 +pw_255: times 4 dw 255 +pb_36_m4: times 4 db 36, -4 +pb_127_m127: times 4 db 127, -127 + +%macro JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - 2*4) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%base %+ .%3 - (%%table - 2*4) + %rotate 1 + %endrep +%endmacro + +%define ipred_dc_splat_ssse3_table (ipred_dc_ssse3_table + 10*4) +%define ipred_cfl_splat_ssse3_table (ipred_cfl_ssse3_table + 8*4) + +JMP_TABLE ipred_h, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_dc, ssse3, h4, h8, h16, h32, h64, w4, w8, w16, w32, w64, \ + s4-10*4, s8-10*4, s16-10*4, s32-10*4, s64-10*4 +JMP_TABLE ipred_dc_left, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE ipred_smooth, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_v, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_smooth_h, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_paeth, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z1, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z2, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_z3, ssse3, h4, h8, h16, h32, h64 +JMP_TABLE pal_pred, ssse3, w4, w8, w16, w32, w64 +JMP_TABLE ipred_cfl, ssse3, h4, h8, h16, h32, w4, w8, w16, w32, \ + s4-8*4, s8-8*4, s16-8*4, s32-8*4 +JMP_TABLE ipred_cfl_left, ssse3, h4, h8, h16, h32 +JMP_TABLE ipred_filter, ssse3, w4, w8, w16, w32 + +cextern dr_intra_derivative +cextern filter_intra_taps + +SECTION .text + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_h_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro IPRED_SET 3 ; width, stride, stride size pshuflw_imm8 + pshuflw m1, m0, %3 ; extend 8 byte for 2 pos + punpcklqdq m1, m1 + mova [dstq + %2], m1 +%if %1 > 16 + mova [dstq + 16 + %2], m1 +%endif +%if %1 > 32 + mova [dstq + 32 + %2], m1 + mova [dstq + 48 + %2], m1 +%endif +%endmacro + +%macro IPRED_H 1 ; width + sub tlq, 4 + movd m0, [tlq] ; get 4 bytes of topleft data + punpcklbw m0, m0 ; extend 2 byte +%if %1 == 4 + pshuflw m1, m0, q2233 + movd [dstq+strideq*0], m1 + psrlq m1, 32 + movd [dstq+strideq*1], m1 + pshuflw m0, m0, q0011 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+stride3q ], m0 + +%elif %1 == 8 + punpcklwd m0, m0 + punpckhdq m1, m0, m0 + punpckldq m0, m0 + movq [dstq+strideq*1], m1 + movhps [dstq+strideq*0], m1 + movq [dstq+stride3q ], m0 + movhps [dstq+strideq*2], m0 +%else + IPRED_SET %1, 0, q3333 + IPRED_SET %1, strideq, q2222 + IPRED_SET %1, strideq*2, q1111 + IPRED_SET %1, stride3q, q0000 +%endif + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w%1 + RET +%endmacro + +INIT_XMM ssse3 +cglobal ipred_h_8bpc, 3, 6, 2, dst, stride, tl, w, h, stride3 + LEA r5, ipred_h_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq +.w4: + IPRED_H 4 +.w8: + IPRED_H 8 +.w16: + IPRED_H 16 +.w32: + IPRED_H 32 +.w64: + IPRED_H 64 + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_v_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_v_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_ssse3_table + tzcnt wd, wm + movu m0, [tlq+ 1] + movu m1, [tlq+17] + movu m2, [tlq+33] + movu m3, [tlq+49] + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + movifnidn hd, hm + movifnidn wd, wm + tzcnt r6d, hd + lea r5d, [wq+hq] + movd m4, r5d + tzcnt r5d, r5d + movd m5, r5d + LEA r5, ipred_dc_ssse3_table + tzcnt wd, wd + movsxd r6, [r5+r6*4] + movsxd wq, [r5+wq*4+20] + pcmpeqd m3, m3 + psrlw m4, 1 ; dc = (width + height) >> 1; + add r6, r5 + add wq, r5 + lea stride3q, [strideq*3] + jmp r6 +.h4: + movd m0, [tlq-4] + pmaddubsw m0, m3 + jmp wq +.w4: + movd m1, [tlq+1] + pmaddubsw m1, m3 + psubw m0, m4 + paddw m0, m1 + pmaddwd m0, m3 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 ; dc >>= ctz(width + height); + jmp .w4_end +.w4_mul: + punpckhqdq m1, m0, m0 + paddw m0, m1 + psrlq m1, m0, 32 + paddw m0, m1 + psrlw m0, 2 + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8 + cmovz r6d, r2d + movd m5, r6d + pmulhuw m0, m5 +.w4_end: + pxor m1, m1 + pshufb m0, m1 +.s4: + movd [dstq+strideq*0], m0 + movd [dstq+strideq*1], m0 + movd [dstq+strideq*2], m0 + movd [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s4 + RET +ALIGN function_align +.h8: + movq m0, [tlq-8] + pmaddubsw m0, m3 + jmp wq +.w8: + movq m1, [tlq+1] + pmaddubsw m1, m3 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w8_end: + pxor m1, m1 + pshufb m0, m1 +.s8: + movq [dstq+strideq*0], m0 + movq [dstq+strideq*1], m0 + movq [dstq+strideq*2], m0 + movq [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s8 + RET +ALIGN function_align +.h16: + mova m0, [tlq-16] + pmaddubsw m0, m3 + jmp wq +.w16: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w16_end: + pxor m1, m1 + pshufb m0, m1 +.s16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m0 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s16 + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + mova m2, [tlq-16] + pmaddubsw m2, m3 + paddw m0, m2 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + movu m2, [tlq+17] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 64|16 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w32_end: + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 +.s32: + mova [dstq], m0 + mova [dstq+16], m1 + mova [dstq+strideq], m0 + mova [dstq+strideq+16], m1 + mova [dstq+strideq*2], m0 + mova [dstq+strideq*2+16], m1 + mova [dstq+stride3q], m0 + mova [dstq+stride3q+16], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .s32 + RET +ALIGN function_align +.h64: + mova m0, [tlq-64] + mova m1, [tlq-48] + pmaddubsw m0, m3 + pmaddubsw m1, m3 + paddw m0, m1 + mova m1, [tlq-32] + pmaddubsw m1, m3 + paddw m0, m1 + mova m1, [tlq-16] + pmaddubsw m1, m3 + paddw m0, m1 + jmp wq +.w64: + movu m1, [tlq+ 1] + movu m2, [tlq+17] + pmaddubsw m1, m3 + pmaddubsw m2, m3 + paddw m1, m2 + movu m2, [tlq+33] + pmaddubsw m2, m3 + paddw m1, m2 + movu m2, [tlq+49] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 64 + je .w64_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w64_end: + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 + mova m2, m0 + mova m3, m0 +.s64: + mova [dstq], m0 + mova [dstq+16], m1 + mova [dstq+32], m2 + mova [dstq+48], m3 + mova [dstq+strideq], m0 + mova [dstq+strideq+16], m1 + mova [dstq+strideq+32], m2 + mova [dstq+strideq+48], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .s64 + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_left_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_left_ssse3_table + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + movd m3, [r5-ipred_dc_left_ssse3_table+pd_32768] + movd m2, r6d + psrld m3, m2 + movsxd r6, [r5+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_ssse3_table-ipred_dc_left_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 +.h64: + movu m1, [tlq+48] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 + movu m1, [tlq+32] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h32: + movu m1, [tlq+16] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h16: + pshufd m1, m0, q3232 ; psrlq m1, m0, 16 + paddw m0, m1 +.h8: + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 +.h4: + pmaddwd m0, m2 + pmulhrsw m0, m3 + lea stride3q, [strideq*3] + pxor m1, m1 + pshufb m0, m1 + mova m1, m0 + mova m2, m0 + mova m3, m0 + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_128_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_128_8bpc, 2, 7, 6, dst, stride, tl, w, h, stride3 + LEA r5, ipred_dc_splat_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + movddup m0, [r5-ipred_dc_splat_ssse3_table+pb_128] + mova m1, m0 + mova m2, m0 + mova m3, m0 + add wq, r5 + lea stride3q, [strideq*3] + jmp wq + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_dc_top_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_dc_top_8bpc, 3, 7, 6, dst, stride, tl, w, h + LEA r5, ipred_dc_left_ssse3_table + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + movd m3, [r5-ipred_dc_left_ssse3_table+pd_32768] + movd m2, wd + psrld m3, m2 + movsxd r6, [r5+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, r5 + add r5, ipred_dc_splat_ssse3_table-ipred_dc_left_ssse3_table + movsxd wq, [r5+wq*4] + add wq, r5 + jmp r6 + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_v_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro SMOOTH 6 ; src[1-2], mul[1-2], add[1-2] + ; w * a = (w - 128) * a + 128 * a + ; (256 - w) * b = (127 - w) * b + 129 * b + ; => w * a + (256 - w) * b = [(w - 128) * a + (127 - w) * b] + [128 * a + 129 * b] + pmaddubsw m6, m%3, m%1 + pmaddubsw m0, m%4, m%2 ; (w - 128) * a + (127 - w) * b + paddw m6, m%5 + paddw m0, m%6 ; [(w - 128) * a + (127 - w) * b] + [128 * a + 129 * b + 128] + psrlw m6, 8 + psrlw m0, 8 + packuswb m6, m0 +%endmacro + +cglobal ipred_smooth_v_8bpc, 3, 7, 7, dst, stride, tl, w, h, weights +%define base r6-ipred_smooth_v_ssse3_table + LEA r6, ipred_smooth_v_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + lea weightsq, [base+smooth_weights+hq*4] + neg hq + movd m5, [tlq+hq] + pxor m2, m2 + pshufb m5, m2 + add wq, r6 + jmp wq +.w4: + movd m2, [tlq+1] + punpckldq m2, m2 + punpcklbw m2, m5 ; top, bottom + lea r3, [strideq*3] + mova m4, [base+ipred_v_shuf] + mova m5, m4 + punpckldq m4, m4 + punpckhdq m5, m5 + pmaddubsw m3, m2, m0 ; m3: 127 * top - 127 * bottom + paddw m1, m2 ; m1: 1 * top + 256 * bottom + 128, overflow is ok + paddw m3, m1 ; m3: 128 * top + 129 * bottom + 128 +.w4_loop: + movu m1, [weightsq+hq*2] + pshufb m0, m1, m4 ;m2, m3, m4 and m5 should be stable in loop + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + movd [dstq+strideq*0], m6 + pshuflw m1, m6, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m6, m6 + movd [dstq+strideq*2], m6 + psrlq m6, 32 + movd [dstq+r3 ], m6 + lea dstq, [dstq+strideq*4] + add hq, 4 + jl .w4_loop + RET +ALIGN function_align +.w8: + movq m2, [tlq+1] + punpcklbw m2, m5 + mova m5, [base+ipred_v_shuf] + lea r3, [strideq*3] + pshufd m4, m5, q0000 + pshufd m5, m5, q1111 + pmaddubsw m3, m2, m0 + paddw m1, m2 + paddw m3, m1 ; m3 is output for loop +.w8_loop: + movq m1, [weightsq+hq*2] + pshufb m0, m1, m4 + pshufb m1, m5 + SMOOTH 0, 1, 2, 2, 3, 3 + movq [dstq+strideq*0], m6 + movhps [dstq+strideq*1], m6 + lea dstq, [dstq+strideq*2] + add hq, 2 + jl .w8_loop + RET +ALIGN function_align +.w16: + movu m3, [tlq+1] + punpcklbw m2, m3, m5 + punpckhbw m3, m5 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 ; m4 and m5 is output for loop +.w16_loop: + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add dstq, strideq + add hq, 1 + jl .w16_loop + RET +ALIGN function_align +.w32: +%if WIN64 + movaps [rsp+24], xmm7 + %define xmm_regs_used 8 +%endif + mova m7, m5 +.w32_loop_init: + mov r3d, 2 +.w32_loop: + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + movu m3, [tlq+1] + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add tlq, 16 + add dstq, 16 + dec r3d + jg .w32_loop + lea dstq, [dstq-32+strideq] + sub tlq, 32 + add hq, 1 + jl .w32_loop_init + RET +ALIGN function_align +.w64: +%if WIN64 + movaps [rsp+24], xmm7 + %define xmm_regs_used 8 +%endif + mova m7, m5 +.w64_loop_init: + mov r3d, 4 +.w64_loop: + movddup m0, [base+pb_127_m127] + movddup m1, [base+pw_128] + movu m3, [tlq+1] + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + pmaddubsw m4, m2, m0 + pmaddubsw m5, m3, m0 + paddw m0, m1, m2 + paddw m1, m3 + paddw m4, m0 + paddw m5, m1 + movd m1, [weightsq+hq*2] + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + SMOOTH 1, 1, 2, 3, 4, 5 + mova [dstq], m6 + add tlq, 16 + add dstq, 16 + dec r3d + jg .w64_loop + lea dstq, [dstq-64+strideq] + sub tlq, 64 + add hq, 1 + jl .w64_loop_init + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_h_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +cglobal ipred_smooth_h_8bpc, 3, 7, 8, dst, stride, tl, w, h +%define base r6-ipred_smooth_h_ssse3_table + LEA r6, ipred_smooth_h_ssse3_table + mov wd, wm + movd m3, [tlq+wq] + pxor m1, m1 + pshufb m3, m1 ; right + tzcnt wd, wd + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m4, [base+pb_127_m127] + movddup m5, [base+pw_128] + add wq, r6 + jmp wq +.w4: + movddup m6, [base+smooth_weights+4*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + sub tlq, hq + lea r3, [strideq*3] +.w4_loop: + movd m2, [tlq+hq] ; left + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r3 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova m6, [base+smooth_weights+8*2] + mova m7, [base+ipred_h_shuf] + sub tlq, 4 + sub tlq, hq + punpckldq m7, m7 +.w8_loop: + movd m2, [tlq+hq] ; left + pshufb m2, m7 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m6 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + mova m6, [base+smooth_weights+16*2] + mova m7, [base+smooth_weights+16*3] + sub tlq, 1 + sub tlq, hq +.w16_loop: + pxor m1, m1 + movd m2, [tlq+hq] ; left + pshufb m2, m1 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m6 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + lea dstq, [dstq+strideq] + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + sub tlq, 1 + sub tlq, hq + pxor m6, m6 +.w32_loop_init: + mov r5, 2 + lea r3, [base+smooth_weights+16*4] +.w32_loop: + mova m7, [r3] + add r3, 16 + movd m2, [tlq+hq] ; left + pshufb m2, m6 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m7 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + mova m7, [r3] + add r3, 16 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 16 + dec r5 + jg .w32_loop + lea dstq, [dstq-32+strideq] + sub hd, 1 + jg .w32_loop_init + RET +ALIGN function_align +.w64: + sub tlq, 1 + sub tlq, hq + pxor m6, m6 +.w64_loop_init: + mov r5, 4 + lea r3, [base+smooth_weights+16*8] +.w64_loop: + mova m7, [r3] + add r3, 16 + movd m2, [tlq+hq] ; left + pshufb m2, m6 + punpcklbw m1, m2, m3 ; left, right + punpckhbw m2, m3 + pmaddubsw m0, m1, m4 ; 127 * left - 127 * right + paddw m0, m1 ; 128 * left + 129 * right + pmaddubsw m1, m7 + paddw m1, m5 + paddw m0, m1 + pmaddubsw m1, m2, m4 + paddw m1, m2 + mova m7, [r3] + add r3, 16 + pmaddubsw m2, m7 + paddw m2, m5 + paddw m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 16 + dec r5 + jg .w64_loop + lea dstq, [dstq-64+strideq] + sub hd, 1 + jg .w64_loop_init + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_ipred_smooth_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int a); +;--------------------------------------------------------------------------------------- +%macro SMOOTH_2D_END 7 ; src[1-2], mul[1-2], add[1-2], m3 + pmaddubsw m6, m%3, m%1 + mova m0, m6 + pmaddubsw m6, m%4, m%2 + mova m1, m6 +%ifnum %5 + paddw m0, m%5 +%else + paddw m0, %5 +%endif +%ifnum %6 + paddw m1, m%6 +%else + paddw m1, %6 +%endif +%ifnum %7 +%else + mova m3, %7 +%endif + pavgw m0, m2 + pavgw m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 +%endmacro + +%macro SMOOTH_OUTPUT_16B 12 ; m1, [buffer1, buffer2, buffer3, buffer4,] [w1, w2,] m3, m7, [m0, m4, m5] + mova m1, [rsp+16*%1] ; top + punpckhbw m6, m1, m0 ; top, bottom + punpcklbw m1, m0 ; top, bottom + pmaddubsw m2, m1, m5 + mova [rsp+16*%2], m1 + paddw m1, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m1 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*%3], m2 + pmaddubsw m2, m6, m5 + mova [rsp+16*%4], m6 + paddw m6, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m6 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*%5], m2 + movd m1, [tlq+hq] ; left + pshufb m1, [base+pb_3] ; topleft[-(1 + y)] + punpcklbw m1, m4 ; left, right + pmaddubsw m2, m1, m5 ; 127 * left - 127 * right + paddw m2, m1 ; 128 * left + 129 * right + mova m3, m2 + pmaddubsw m0, m1, %6 ; weights_hor = &dav1d_sm_weights[width]; + pmaddubsw m1, %7 + paddw m2, m3, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + mova m7, [rsp+16*%9] + pshufb m1, m7 + mova [rsp+16*%8], m3 + mova m4, [rsp+16*%2] + mova m5, [rsp+16*%3] + mova m3, [rsp+16*%4] + mova m7, [rsp+16*%5] + SMOOTH_2D_END 1, 1, 4, 3, 5, 7, [rsp+16*%8] + mova [dstq], m0 + movddup m3, [base+pw_255] ; recovery + mova m0, [rsp+16*%10] ; recovery + mova m4, [rsp+16*%11] ; recovery + mova m5, [rsp+16*%12] ; recovery +%endmacro + +cglobal ipred_smooth_8bpc, 3, 7, 8, -13*16, dst, stride, tl, w, h, v_weights +%define base r6-ipred_smooth_ssse3_table + mov wd, wm + mov hd, hm + LEA r6, ipred_smooth_ssse3_table + movd m4, [tlq+wq] ; right + pxor m2, m2 + pshufb m4, m2 + tzcnt wd, wd + mov r5, tlq + sub r5, hq + movsxd wq, [r6+wq*4] + movddup m5, [base+pb_127_m127] + movd m0, [r5] + pshufb m0, m2 ; bottom + movddup m3, [base+pw_255] + add wq, r6 + lea v_weightsq, [base+smooth_weights+hq*2] ; weights_ver = &dav1d_sm_weights[height] + jmp wq +.w4: + mova m7, [base+ipred_v_shuf] + movd m1, [tlq+1] ; left + pshufd m1, m1, q0000 + sub tlq, 4 + lea r3, [strideq*3] + sub tlq, hq + punpcklbw m1, m0 ; top, bottom + pshufd m6, m7, q1100 + pshufd m7, m7, q3322 + pmaddubsw m2, m1, m5 + paddw m3, m1 ; 1 * top + 255 * bottom + 255 + paddw m2, m3 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + movq m1, [base+smooth_weights+4*2] ; weights_hor = &dav1d_sm_weights[width]; + punpcklqdq m1, m1 + mova [rsp+16*2], m1 + mova [rsp+16*3], m4 + mova [rsp+16*4], m6 + mova [rsp+16*5], m5 +.w4_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+ipred_h_shuf] + punpcklbw m0, m1, m4 ; left, right + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 ; 127 * left - 127 * right + pmaddubsw m3, m1, m5 + paddw m2, m0 ; 128 * left + 129 * right + paddw m3, m1 + mova m4, [rsp+16*2] + pmaddubsw m0, m4 + pmaddubsw m1, m4 + paddw m2, m0 + paddw m3, m1 + movq m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 8 + pshufb m0, m1, m6 + pshufb m1, m7 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + SMOOTH_2D_END 0, 1, 4, 4, 5, 5, 3 + mova m4, [rsp+16*3] + mova m6, [rsp+16*4] + mova m5, [rsp+16*5] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r3 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova m7, [base+ipred_v_shuf] + movq m1, [tlq+1] ; left + punpcklqdq m1, m1 + sub tlq, 4 + sub tlq, hq + punpcklbw m1, m0 + pshufd m6, m7, q0000 + pshufd m7, m7, q1111 + pmaddubsw m2, m1, m5 + paddw m3, m1 + paddw m2, m3 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova m1, [base+smooth_weights+8*2] ; weights_hor = &dav1d_sm_weights[width]; + mova [rsp+16*2], m1 + mova [rsp+16*3], m4 + mova [rsp+16*4], m6 + mova [rsp+16*5], m5 +.w8_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+ipred_h_shuf] + pshufd m1, m1, q1100 + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + pmaddubsw m2, m0, m5 + pmaddubsw m3, m1, m5 + paddw m2, m0 + paddw m3, m1 + mova m4, [rsp+16*2] + pmaddubsw m0, m4 + pmaddubsw m1, m4 + paddw m2, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 4 + pshufb m0, m1, m6 + pshufb m1, m7 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + SMOOTH_2D_END 0, 1, 4, 4, 5, 5, 3 + mova m4, [rsp+16*3] + mova m6, [rsp+16*4] + mova m5, [rsp+16*5] + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + mova m7, [base+ipred_v_shuf] + movu m1, [tlq+1] ; left + sub tlq, 4 + sub tlq, hq + punpckhbw m6, m1, m0 ; top, bottom + punpcklbw m1, m0 ; top, bottom + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + pmaddubsw m2, m6, m5 + mova [rsp+16*5], m6 + paddw m6, m3 ; 1 * top + 255 * bottom + 255 + paddw m2, m6 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*6], m2 + pmaddubsw m2, m1, m5 + paddw m3, m1 ; 1 * top + 255 * bottom + 255 + mova [rsp+16*0], m1 + paddw m2, m3 ; 128 * top + 129 * bottom + 255 + mova [rsp+16*1], m2 + mova [rsp+16*3], m4 + mova [rsp+16*4], m5 +.w16_loop: + movd m1, [tlq+hq] ; left + pshufb m1, [base+pb_3] ; topleft[-(1 + y)] + punpcklbw m1, m4 ; left, right + pmaddubsw m2, m1, m5 ; 127 * left - 127 * right + paddw m2, m1 ; 128 * left + 129 * right + mova m0, m1 + mova m3, m2 + pmaddubsw m0, [base+smooth_weights+16*2] ; weights_hor = &dav1d_sm_weights[width]; + pmaddubsw m1, [base+smooth_weights+16*3] + paddw m2, m0 + paddw m3, m1 + movd m1, [v_weightsq] ; weights_ver = &dav1d_sm_weights[height]; + add v_weightsq, 2 + mova m7, [rsp+16*2] + pshufb m1, m7 + mova [rsp+16*7], m3 + mova m4, [rsp+16*0] + mova m5, [rsp+16*1] + mova m3, [rsp+16*5] + mova m7, [rsp+16*6] + SMOOTH_2D_END 1, 1, 4, 3, 5, 7, [rsp+16*7] + mova m4, [rsp+16*3] + mova m5, [rsp+16*4] + mova [dstq], m0 + lea dstq, [dstq+strideq] + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m1, [tlq+1] ; top topleft[1 + x] + movu m2, [tlq+17] ; top + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + sub tlq, 4 + sub tlq, hq + mova m7, [base+ipred_v_shuf] + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + mova [rsp+16*3], m0 + mova [rsp+16*4], m4 + mova [rsp+16*5], m5 +.w32_loop: + SMOOTH_OUTPUT_16B 0, 6, 7, 8, 9, [base+smooth_weights+16*4], [base+smooth_weights+16*5], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 1, 6, 7, 8, 9, [base+smooth_weights+16*6], [base+smooth_weights+16*7], 10, 2, 3, 4, 5 + lea dstq, [dstq-16+strideq] + add v_weightsq, 2 + sub hd, 1 + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m1, [tlq+1] ; top topleft[1 + x] + movu m2, [tlq+17] ; top + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + movu m1, [tlq+33] ; top + movu m2, [tlq+49] ; top + mova [rsp+16*11], m1 + mova [rsp+16*12], m2 + sub tlq, 4 + sub tlq, hq + mova m7, [base+ipred_v_shuf] + pshufd m7, m7, q0000 + mova [rsp+16*2], m7 + mova [rsp+16*3], m0 + mova [rsp+16*4], m4 + mova [rsp+16*5], m5 +.w64_loop: + SMOOTH_OUTPUT_16B 0, 6, 7, 8, 9, [base+smooth_weights+16*8], [base+smooth_weights+16*9], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 1, 6, 7, 8, 9, [base+smooth_weights+16*10], [base+smooth_weights+16*11], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 11, 6, 7, 8, 9, [base+smooth_weights+16*12], [base+smooth_weights+16*13], 10, 2, 3, 4, 5 + add dstq, 16 + SMOOTH_OUTPUT_16B 12, 6, 7, 8, 9, [base+smooth_weights+16*14], [base+smooth_weights+16*15], 10, 2, 3, 4, 5 + lea dstq, [dstq-48+strideq] + add v_weightsq, 2 + sub hd, 1 + jg .w64_loop + RET + +%if ARCH_X86_64 +cglobal ipred_z1_8bpc, 3, 8, 11, 16*12, dst, stride, tl, w, h, angle, dx + %define base r7-$$ + lea r7, [$$] + mova m8, [base+pw_62] + mova m9, [base+pw_64] + mova m10, [base+pw_512] +%else +cglobal ipred_z1_8bpc, 3, 7, 8, -16*13, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define strideq r3 + %define stridemp dword [rsp+16*12] + mov stridemp, r1 + LEA r1, $$ +%endif + tzcnt wd, wm + movifnidn angled, anglem + movifnidn hd, hm + inc tlq + movsxd wq, [base+ipred_z1_ssse3_table+wq*4] + mov dxd, angled + and dxd, 0x7e + add angled, 165 ; ~90 + lea wq, [base+wq+ipred_z1_ssse3_table] + movzx dxd, word [base+dr_intra_derivative+dxq] + xor angled, 0x4ff ; d = 90 - angle + jmp wq +.w4: + lea r3d, [angleq+88] + test r3d, 0x480 + jnz .w4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r3d, 9 + add r3d, hd + cmp r3d, 8 + jg .w4_no_upsample ; h > 8 || (w == h && is_sm) + mova m1, [tlq-1] + pshufb m0, m1, [base+z_upsample1] + pshufb m1, [base+z_upsample2] + movddup m2, [base+pb_36_m4] + add dxd, dxd + pmaddubsw m0, m2 + pshufd m7, m1, q3333 + movd [rsp+16], m7 ; top[max_base_x] + pmaddubsw m1, m2 + movd m6, dxd + mov r5d, dxd ; xpos + pshufb m6, [base+pw_256] + paddw m1, m0 + movq m0, [tlq] + pmulhrsw m1, m10 + paddw m7, m6, m6 + punpcklqdq m6, m7 ; xpos0 xpos1 + packuswb m1, m1 + punpcklbw m0, m1 + movifnidn strideq, stridemp + mova [rsp], m0 +.w4_upsample_loop: + lea r2d, [r5+dxq] + shr r5d, 6 ; base0 + movq m0, [rsp+r5] + lea r5d, [r2+dxq] + shr r2d, 6 ; base1 + movhps m0, [rsp+r2] + pand m2, m8, m6 ; frac + psubw m1, m9, m2 ; 64-frac + psllw m2, 8 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + paddw m6, m7 ; xpos += dx + pmulhrsw m0, m10 + packuswb m0, m0 + movd [dstq+strideq*0], m0 + pshuflw m0, m0, q1032 + movd [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_upsample_loop + RET +.w4_no_upsample: + mov r3d, 7 ; max_base + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w4_main + lea r3d, [hq+3] + movd m0, r3d + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + pcmpeqb m1, m0, [base+z_filter_wh4] + pand m1, m2 + pcmpgtb m1, [base+z_filter_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r3d, 7 + test r5d, r5d + jz .w4_main ; filter_strength == 0 + mova m3, [tlq-1] + imul r5d, 0x55555555 + movu m7, [base+z_filter_s+8] + shr r5d, 30 ; filter_strength + movddup m0, [base+pb_8] + pminub m7, m0 + pshufb m0, m3, [base+z_filter_s] + movddup m4, [base+z_filter_k-8+r5*8+24*0] + pshufb m3, m7 + movddup m5, [base+z_filter_k-8+r5*8+24*1] + shufps m2, m0, m3, q2121 + movddup m6, [base+z_filter_k-8+r5*8+24*2] + pmaddubsw m0, m4 + pmaddubsw m1, m2, m4 + pmaddubsw m2, m5 + paddd m5, m6 + pmaddubsw m4, m3, m5 + pmaddubsw m3, m6 + paddw m0, m2 + paddw m1, m4 + paddw m0, m3 + pshufd m1, m1, q3333 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + mov r5d, 9 + mov tlq, rsp + cmp hd, 4 + cmovne r3d, r5d + packuswb m0, m1 + mova [tlq], m0 +.w4_main: + add tlq, r3 + movd m5, dxd + movddup m0, [base+z_base_inc] ; base_inc << 6 + movd m7, [tlq] ; top[max_base_x] + shl r3d, 6 + movd m4, r3d + pshufb m5, [base+pw_256] + mov r5d, dxd ; xpos + pshufb m7, [base+pw_m256] + sub r5, r3 + pshufb m4, [base+pw_256] + mova m3, [base+z1_shuf_w4] + paddw m6, m5, m5 + psubw m4, m0 ; max_base_x + punpcklqdq m5, m6 ; xpos0 xpos1 +.w4_loop: + lea r3, [r5+dxq] + sar r5, 6 ; base0 + movq m0, [tlq+r5] + lea r5, [r3+dxq] + sar r3, 6 ; base1 + movhps m0, [tlq+r3] + pand m2, m8, m5 ; frac + psubw m1, m9, m2 ; 64-frac + psllw m2, 8 + pshufb m0, m3 + por m1, m2 ; 64-frac, frac + pmaddubsw m0, m1 + movifnidn strideq, stridemp + pcmpgtw m1, m4, m5 ; base < max_base_x + pmulhrsw m0, m10 + paddw m5, m6 ; xpos += dx + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movd [dstq+strideq*0], m0 + pshuflw m0, m0, q1032 + movd [dstq+strideq*1], m0 + sub hd, 2 + jz .w4_end + lea dstq, [dstq+strideq*2] + test r5d, r5d + jl .w4_loop + packuswb m7, m7 +.w4_end_loop: + movd [dstq+strideq*0], m7 + movd [dstq+strideq*1], m7 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_end_loop +.w4_end: + RET +.w8: + lea r3d, [angleq+88] + and r3d, ~0x7f + or r3d, hd + cmp r3d, 8 + ja .w8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || h > 8 + mova m5, [base+z_upsample1] + movu m3, [base+z_filter_s+6] + movd m4, hd + mova m0, [tlq-1] + movu m1, [tlq+7] + pxor m7, m7 + pshufb m4, m7 + movddup m7, [base+pb_36_m4] + pminub m4, m3 + add dxd, dxd + pshufb m2, m0, m5 + pmaddubsw m2, m7 + pshufb m0, m3 + pmaddubsw m0, m7 + movd m6, dxd + pshufb m3, m1, m5 + pmaddubsw m3, m7 + pshufb m1, m4 + pmaddubsw m1, m7 + pshufb m6, [base+pw_256] + mov r5d, dxd + paddw m2, m0 + paddw m7, m6, m6 + paddw m3, m1 + punpcklqdq m6, m7 ; xpos0 xpos1 + movu m1, [tlq] + pmulhrsw m2, m10 + pmulhrsw m3, m10 + packuswb m2, m3 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + movifnidn strideq, stridemp + mova [rsp+16*0], m0 + mova [rsp+16*1], m1 +.w8_upsample_loop: + lea r2d, [r5+dxq] + shr r5d, 6 ; base0 + movu m0, [rsp+r5] + lea r5d, [r2+dxq] + shr r2d, 6 ; base1 + movu m1, [rsp+r2] + pand m2, m8, m6 + psubw m3, m9, m2 + psllw m2, 8 + por m3, m2 + punpcklqdq m2, m3, m3 ; frac0 + pmaddubsw m0, m2 + punpckhqdq m3, m3 ; frac1 + pmaddubsw m1, m3 + paddw m6, m7 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_upsample_loop + RET +.w8_no_upsample: + lea r3d, [hq+7] + movd m0, r3d + and r3d, 7 + or r3d, 8 ; imin(h+7, 15) + test angled, 0x400 + jnz .w8_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movu m1, [base+z_filter_wh8] + psrldq m3, [base+z_filter_t_w48+angleq*8], 4 + pcmpeqb m1, m0 + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_main ; filter_strength == 0 + movd m3, [tlq-1] + movu m0, [tlq+16*0] + imul r5d, 0x55555555 + movu m1, [tlq+16*1] + shr r5d, 30 ; filter_strength + movd m2, [tlq+r3] + lea tlq, [rsp+16*4] + sub r5, 3 + mova [tlq-16*1], m0 + pxor m7, m7 + mova [tlq+16*0], m1 + pshufb m3, m7 + pshufb m2, m7 + mova [tlq-16*2], m3 + movq [tlq+r3-15], m2 + call .filter_edge + sar r5d, 1 + add r5d, 17 + cmp hd, 8 + cmova r3d, r5d +.w8_main: + add tlq, r3 + movd m5, dxd + movd m7, [tlq] + shl r3d, 6 + movu m3, [base+z_filter_s+2] + movd m4, r3d + pshufb m5, [base+pw_256] + mov r5d, dxd + pshufb m7, [base+pw_m256] + sub r5, r3 + pshufb m4, [base+pw_256] + psubw m4, [base+z_base_inc] + mova m6, m5 +.w8_loop: + mov r3, r5 + sar r3, 6 + movu m0, [tlq+r3] + pand m1, m8, m5 + psubw m2, m9, m1 + psllw m1, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [dstq], m0 + dec hd + jz .w8_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w8_loop + packuswb m7, m7 +.w8_end_loop: + movq [dstq], m7 + add dstq, strideq + dec hd + jg .w8_end_loop +.w8_end: + RET +.w16: + lea r3d, [hq+15] + movd m0, r3d + and r3d, 15 + or r3d, 16 ; imin(h+15, 31) + test angled, 0x400 + jnz .w16_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m0, [base+z_filter_wh16] + pand m0, m2 + pcmpgtb m0, m3 + pmovmskb r5d, m0 + test r5d, r5d + jz .w16_main ; filter_strength == 0 + movd m4, [tlq-1] + movu m0, [tlq+16*0] + imul r5d, 0x24924924 + movu m1, [tlq+16*1] + shr r5d, 30 + movd m2, [tlq+30] + adc r5, -4 ; filter_strength-3 + movd m3, [tlq+r3] + lea tlq, [rsp+16*4] + mova [tlq-16*1], m0 + pxor m7, m7 + mova [tlq+16*0], m1 + pshufb m4, m7 + movd [rsp], m2 + pshufb m3, m7 + mova [tlq-16*2], m4 + movd [tlq+r3-16], m3 + call .filter_edge + cmp hd, 16 + jle .w16_main + pshuflw m0, [rsp], q0000 + sar r5, 1 + movd m1, [base+z_filter_k_tail+4+r5*4] + lea r3d, [r5+33] + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq+32], m0 +.w16_main: + add tlq, r3 + movd m5, dxd + movd m7, [tlq] + movd m4, r3d + shl r3d, 6 + pshufb m5, [base+pw_256] + pxor m6, m6 + pshufb m7, m6 + mov r5d, dxd + pshufb m4, m6 + sub r5, r3 + psubb m4, [base+pb_0to15] + mova m6, m5 +.w16_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+0] + pand m0, m8, m5 + movu m2, [tlq+r3+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m3, m5, 6 + packsswb m3, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + paddw m5, m6 + pcmpgtb m2, m4, m3 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq], m0 + dec hd + jz .w16_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w16_loop +.w16_end_loop: + mova [dstq], m7 + add dstq, strideq + dec hd + jg .w16_end_loop +.w16_end: + RET +.w32: + lea r3d, [hq+31] + and r3d, 31 + or r3d, 32 ; imin(h+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w32_main + movd m6, [tlq-1] + movu m0, [tlq+16*0] + movu m1, [tlq+16*1] + movu m2, [tlq+16*2] + movu m3, [tlq+16*3] + movd m4, [tlq+62] + movd m5, [tlq+r3] + lea tlq, [rsp+16*6] + mova [tlq-16*3], m0 + pxor m7, m7 + mova [tlq-16*2], m1 + pshufb m6, m7 + mova [tlq-16*1], m2 + xor r5d, r5d ; filter_strength = 3 + mova [tlq+16*0], m3 + movd [rsp], m4 + pshufb m5, m7 + mova [tlq-16*4], m6 + movd [tlq+r3-48], m5 + call .filter_edge + sub tlq, 16*2 + call .filter_edge + cmp hd, 32 + jle .w32_main + pshuflw m0, [rsp], q0000 + movd m1, [base+z_filter_k_tail+4] + add r3d, 2 + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq+64], m0 +.w32_main: + add tlq, r3 + movd m0, r3d + movd m7, [tlq] + shl r3d, 6 + movd m5, dxd + pxor m6, m6 + mov r5d, dxd + pshufb m0, m6 + pshufb m5, [base+pw_256] + sub r5, r3 + pshufb m7, m6 + psubb m0, [base+pb_0to15] + movddup m1, [base+pb_m16] + mova [rsp+16*0], m0 + paddb m0, m1 + mova [rsp+16*1], m0 + mova m6, m5 +.w32_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+16*0+0] + pand m0, m8, m5 + movu m2, [tlq+r3+16*0+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m4, m5, 6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m4, m4 + pcmpgtb m2, [rsp+16*0], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*1+0] + movu m2, [tlq+r3+16*1+1] + mova [dstq+16*0], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*1], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq+16*1], m0 + dec hd + jz .w32_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w32_loop +.w32_end_loop: + mova [dstq+16*0], m7 + mova [dstq+16*1], m7 + add dstq, strideq + dec hd + jg .w32_end_loop +.w32_end: + RET +.w64: + lea r3d, [hq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .w64_main + movd m4, [tlq-1] + movu m0, [tlq+16*0] + movu m1, [tlq+16*1] + movu m2, [tlq+16*2] + movu m3, [tlq+16*3] + mova [rsp+16*3], m0 + pxor m7, m7 + mova [rsp+16*4], m1 + pshufb m4, m7 + mova [rsp+16*5], m2 + mova [rsp+16*6], m3 + mova [rsp+16*2], m4 + movu m0, [tlq+16*4] + movu m1, [tlq+16*5] + movu m2, [tlq+16*6] + movu m3, [tlq+16*7] + movd m4, [tlq+r3] + lea tlq, [rsp+16*10] + mova [tlq-16*3], m0 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*2], m1 + pshufb m4, m7 + mova [tlq-16*1], m2 + mova [tlq+16*0], m3 + movd [tlq+r3-16*7], m4 + cmp hd, 64 + jl .w64_filter96 ; skip one call if the last 32 bytes aren't used + call .filter_edge +.w64_filter96: + sub tlq, 16*2 + call .filter_edge + sub tlq, 16*2 + call .filter_edge + sub tlq, 16*2 + call .filter_edge +.w64_main: + add tlq, r3 + movd m0, r3d + movd m7, [tlq] + shl r3d, 6 + movd m5, dxd + pxor m6, m6 + mov r5d, dxd + pshufb m0, m6 + sub r5, r3 + pshufb m5, [base+pw_256] + pshufb m7, m6 + psubb m0, [base+pb_0to15] + movddup m1, [base+pb_m16] + mova [rsp+16*0], m0 + paddb m0, m1 + mova [rsp+16*1], m0 + paddb m0, m1 + mova [rsp+16*2], m0 + paddb m0, m1 + mova [rsp+16*3], m0 + mova m6, m5 +.w64_loop: + mov r3, r5 + sar r3, 6 + movu m1, [tlq+r3+16*0+0] + pand m0, m8, m5 + movu m2, [tlq+r3+16*0+1] + psubw m3, m9, m0 + psllw m0, 8 + por m3, m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + psrlw m4, m5, 6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m4, m4 + pcmpgtb m2, [rsp+16*0], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*1+0] + movu m2, [tlq+r3+16*1+1] + mova [dstq+16*0], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*1], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*2+0] + movu m2, [tlq+r3+16*2+1] + mova [dstq+16*1], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*2], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + movu m1, [tlq+r3+16*3+0] + movu m2, [tlq+r3+16*3+1] + mova [dstq+16*2], m0 + punpcklbw m0, m1, m2 + pmaddubsw m0, m3 + punpckhbw m1, m2 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pcmpgtb m2, [rsp+16*3], m4 + packuswb m0, m1 + pand m0, m2 + pandn m2, m7 + por m0, m2 + mova [dstq+16*3], m0 + dec hd + jz .w64_end + movifnidn strideq, stridemp + add dstq, strideq + add r5, dxq + jl .w64_loop +.w64_end_loop: + mova [dstq+16*0], m7 + mova [dstq+16*1], m7 + mova [dstq+16*2], m7 + mova [dstq+16*3], m7 + add dstq, strideq + dec hd + jg .w64_end_loop +.w64_end: + RET +ALIGN function_align +.filter_edge: ; 32 pixels/iteration + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + movu m2, [tlq-18] + movu m1, [tlq-17] + movu m3, [tlq- 2] + movu m4, [tlq- 1] + punpcklbw m0, m2, m1 + pmaddubsw m0, m7 + punpckhbw m2, m1 + pmaddubsw m2, m7 + punpcklbw m1, m3, m4 + pmaddubsw m1, m7 + punpckhbw m3, m4 + pmaddubsw m3, m7 + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + mova m5, [tlq-16] + movu m6, [tlq-15] + punpcklbw m4, m5, m6 + pmaddubsw m4, m7 + punpckhbw m5, m6 + pmaddubsw m5, m7 + paddw m0, m4 + paddw m2, m5 + mova m5, [tlq+ 0] + movu m6, [tlq+ 1] + punpcklbw m4, m5, m6 + pmaddubsw m4, m7 + punpckhbw m5, m6 + pmaddubsw m5, m7 + paddw m1, m4 + paddw m3, m5 + test r5d, r5d + jnz .filter_end ; 3-tap + movddup m7, [base+z_filter_k+8*8] + movu m5, [tlq-14] + movu m6, [tlq+ 2] + punpcklbw m4, m5, m5 + pmaddubsw m4, m7 + punpckhbw m5, m5 + pmaddubsw m5, m7 + paddw m0, m4 + paddw m2, m5 + punpcklbw m5, m6, m6 + pmaddubsw m5, m7 + punpckhbw m6, m6 + pmaddubsw m6, m7 + paddw m1, m5 + paddw m3, m6 +.filter_end: +%if ARCH_X86_64 + REPX {pmulhrsw x, m10}, m0, m2, m1, m3 +%else + mova m4, m10 + REPX {pmulhrsw x, m4 }, m0, m2, m1, m3 +%endif + packuswb m0, m2 + packuswb m1, m3 + mova [tlq+16*0], m0 + mova [tlq+16*1], m1 + ret + +%if ARCH_X86_64 +cglobal ipred_z2_8bpc, 4, 12, 13, 16*16, dst, stride, tl, w, h, angle, dx, _, dy + %define base r7-$$ + %define maxwm r6m + %define maxhm r7m + lea r7, [$$] + mov hd, hm + mova m8, [base+pw_62] + mova m9, [base+pw_64] + lea r9d, [wq-4] + mova m10, [base+pw_512] + shl r9d, 6 + mova m11, [base+z1_shuf_w4] + or r9d, hd + mova m12, [base+z2_h_shuf] +%else +cglobal ipred_z2_8bpc, 4, 7, 8, -16*20, dst, _, tl, w, h, angle, dx + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define m11 [rsp+16*16] + %define m12 [rsp+16*17] + %define r9b byte [rsp+16*18+4*0] + %define r9d dword [rsp+16*18+4*0] + %define r10d dword [rsp+16*18+4*1] + %define r11d dword [rsp+16*18+4*2] + %define maxwm [rsp+16*18+4*3] + %define maxhm [rsp+16*19+4*0] + %define stridemp [rsp+16*19+4*1] + %define strideq r3 + %define dyd r4 + %define dyq r4 + mov stridemp, r1 + mov r1d, r6m + mov r4d, r7m + mov maxwm, r1d + mov maxhm, r4d + LEA r1, $$ + lea hd, [wq-4] + mova m0, [base+z1_shuf_w4] + shl hd, 6 + mova m1, [base+z2_h_shuf] + or hd, hm + mova m11, m0 + mov r9d, hd + mova m12, m1 +%endif + tzcnt wd, wd + movifnidn angled, anglem + movsxd wq, [base+ipred_z2_ssse3_table+wq*4] +%if ARCH_X86_64 + movzx dxd, angleb +%else + movzx dxd, byte anglem +%endif + xor angled, 0x400 + mova m0, [tlq-16*4] + mov dyd, dxd + mova m1, [tlq-16*3] + neg dxq + mova m2, [tlq-16*2] + and dyd, ~1 + mova m3, [tlq-16*1] + and dxq, ~1 + movd m4, [tlq] + movu m5, [tlq+16*0+1] + movu m6, [tlq+16*1+1] + movzx dyd, word [base+dr_intra_derivative+dyq-90] ; angle - 90 + movzx dxd, word [base+dr_intra_derivative+dxq+180] ; 180 - angle + mova [rsp+16*2], m0 + pxor m7, m7 + mova [rsp+16*3], m1 + pshufb m4, m7 + mova [rsp+16*4], m2 + lea wq, [base+ipred_z2_ssse3_table+wq] + mova [rsp+16*5], m3 + neg dxd + mova [rsp+16*6], m4 + or dyd, 4<<16 + mova [rsp+16*7], m4 + mova [rsp+16*8], m5 + mova [rsp+16*9], m6 + movq m0, [base+z_base_inc+2] + movsldup m1, [base+z2_dy_offset] + movq m2, [base+pw_256] ; 4<<6 + movq [rsp+16*14+8*0], m0 + movq [rsp+16*15+8*0], m1 + movq [rsp+16*15+8*1], m2 +%if ARCH_X86_64 + lea r10d, [dxq+(128<<6)] ; xpos +%else + mov [rsp+16*7+4*1], dyd + lea r4d, [dxq+(128<<6)] + mov r10d, r4d + movzx hd, r9b +%endif + mov r11d, (128-4)<<6 + jmp wq +.w4: + test angled, 0x400 + jnz .w4_main + movd m5, [tlq+4] + lea r3d, [hq+2] + add angled, 1022 + pshufb m5, m7 + shl r3d, 6 + movd [rsp+16*8+4], m5 + test r3d, angled + jnz .w4_no_upsample_above ; angle >= 130 || h > 8 || (is_sm && h == 8) + call .upsample_above + sub angled, 1075 ; angle - 53 + lea r3d, [hq+3] + xor angled, 0x7f ; 180 - angle + movd m0, r3d + movd m6, angled + shr angled, 8 ; is_sm << 1 + pshufb m0, m7 + pshufb m6, m7 + pcmpeqb m0, [base+z_filter_wh4] + pand m6, m0 + pcmpgtb m6, [base+z_filter_t_w48+angleq*8] + jmp .w8_filter_left +.upsample_above: ; w4/w8 + movq m3, [rsp+gprsize+16*8-2] + movq m1, [rsp+gprsize+16*8-1] + movq m0, [rsp+gprsize+16*8+0] + movq m4, [rsp+gprsize+16*8+1] + movddup m5, [base+pb_36_m4] + punpcklbw m1, m3 + punpcklbw m2, m0, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 +%if ARCH_X86_64 + mova m11, [base+pb_0to15] + lea r10d, [r10+dxq+(1<<6)] + mov r11d, (128-7)<<6 +%else + mova m3, [base+pb_0to15] + mov r3d, [rsp+gprsize+16*18+4*1] + mov dword [rsp+gprsize+16*18+4*2], (128-7)<<6 + lea r3d, [r3+dxq+(1<<6)] + mov [rsp+gprsize+16*18+4*1], r3d + mova [rsp+gprsize+16*16], m3 +%endif + add dxd, dxd + paddw m1, m2 + pmulhrsw m1, m10 + movq m2, [rsp+gprsize+16*14] + paddw m2, m2 + movq [rsp+gprsize+16*14], m2 + packuswb m1, m1 + punpcklbw m1, m0 + mova [rsp+gprsize+16*8], m1 + ret +.w4_no_upsample_above: + lea r3d, [hq+3] + mov [rsp], angled + sub angled, 1112 ; angle - 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m3, [base+z_filter_wh4] + mova m4, [base+z_filter_t_w48+angleq*8] + call .w8_filter_top + mov angled, [rsp] + lea r3d, [hq+2] + sub angled, 139 + shl r3d, 6 + test r3d, angled + jnz .w8_filter_left ; angle <= 140 || h > 8 || (is_sm && h == 8) +.upsample_left: ; w4/w8 + neg hq + movd m0, [tlq+hq] + pshufb m0, m7 + movd [rsp+16*6+hq-4], m0 + movq m3, [rsp+16*5+7] + movq m0, [rsp+16*5+8] + movq m2, [rsp+16*5+9] + movq m4, [rsp+16*5+10] + movddup m5, [base+pb_36_m4] + punpcklbw m1, m0, m3 + punpcklbw m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + movshdup m3, [base+z2_dy_offset] +%if ARCH_X86_64 + mova m12, [base+z2_upsample] + add dyd, dyd +%else + mova m4, [base+z2_upsample] + shl dword [rsp+16*7+4*1], 1 + mova m12, m4 +%endif + paddw m1, m2 + pmulhrsw m1, m10 + movq [rsp+16*15], m3 + packuswb m1, m1 + punpcklbw m0, m1 + mova [rsp+16*5], m0 +.w4_main: + movd m6, dxd +%if ARCH_X86_64 + movd m3, dyd +%else + movd m3, [rsp+16*7+4*1] +%endif + movddup m0, [rsp+16*14+8*0] + pshufb m6, [base+pw_256] + paddw m7, m6, m6 + movq m5, [base+pw_m1to4] + pshuflw m4, m3, q0000 + punpcklqdq m6, m7 + pmullw m4, m5 + pshuflw m3, m3, q1111 + paddw m6, m0 + mov r2d, r10d + pshuflw m0, m4, q3333 + psubw m4, [rsp+16*15] + movq [rsp+16*6+8*1], m3 + movq [rsp+8*1], m0 ; dy*4 + mov r5, dstq +.w4_loop0: + mova [rsp+16*12], m6 + movq [rsp+8*0], m4 + pand m0, m4, m8 + psraw m4, 6 + psubw m1, m9, m0 + psllw m0, 8 + por m0, m1 ; 64-frac_y, frac_y + movq [rsp+8*3], m0 + pabsw m4, m4 + movq [rsp+8*2], m4 + movzx hd, r9b +.w4_loop: + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x0 + movq m0, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x1 + movhps m0, [rsp+r3] + lea r3d, [r2+dxq] + shr r2d, 6 ; base_x2 + movq m1, [rsp+r2] + lea r2d, [r3+dxq] + shr r3d, 6 ; base_x3 + movhps m1, [rsp+r3] + pand m2, m8, m6 + paddsw m5, m6, m7 + psubw m3, m9, m2 + psllw m2, 8 + pshufb m0, m11 + por m2, m3 + pmaddubsw m0, m2 + pand m2, m8, m5 + psubw m3, m9, m2 + psllw m2, 8 + pshufb m1, m11 + por m2, m3 + pmaddubsw m1, m2 + cmp r3d, 127 ; topleft + jge .w4_toponly + movzx r3d, byte [rsp+8*2+0] ; base_y0 + movq m3, [rsp+r3] + movzx r3d, byte [rsp+8*2+2] ; base_y1 + movhps m3, [rsp+r3] + movzx r3d, byte [rsp+8*2+4] ; base_y2 + movq m4, [rsp+r3] + movzx r3d, byte [rsp+8*2+6] ; base_y3 + movhps m4, [rsp+r3] + pshufb m3, m12 + pshufb m4, m12 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + movddup m4, [rsp+8*3] + pmaddubsw m2, m4 + pmaddubsw m3, m4 + psraw m6, 15 ; base_x < topleft + pand m2, m6 + pandn m6, m0 + por m0, m2, m6 + psraw m6, m5, 15 + pand m3, m6 + pandn m6, m1 + por m1, m3, m6 +.w4_toponly: + pmulhrsw m0, m10 + pmulhrsw m1, m10 + movifnidn strideq, stridemp + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + punpckhqdq m0, m0 + movd [dstq+strideq*0], m0 + psrlq m0, 32 + movd [dstq+strideq*1], m0 + sub hd, 4 + jz .w4_end + movq m4, [rsp+8*2] + movq m3, [rsp+16*6+8*1] + paddw m6, m5, m7 ; xpos += dx + psubw m4, m3 + movq [rsp+8*2], m4 + lea dstq, [dstq+strideq*2] + cmp r2d, r11d + jge .w4_loop + movddup m5, [rsp+8*3] +.w4_leftonly_loop: + movzx r2d, byte [rsp+8*2+0] ; base_y0 + movq m1, [rsp+r2] + movzx r2d, byte [rsp+8*2+2] ; base_y1 + movhps m1, [rsp+r2] + movzx r2d, byte [rsp+8*2+4] ; base_y2 + movq m2, [rsp+r2] + movzx r2d, byte [rsp+8*2+6] ; base_y3 + movhps m2, [rsp+r2] + psubw m4, m3 + pshufb m1, m12 + pshufb m2, m12 + movq [rsp+8*2], m4 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + punpckhqdq m0, m0 + movd [dstq+strideq*0], m0 + psrlq m0, 32 + movd [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 4 + jg .w4_leftonly_loop +.w4_end: + sub r9d, 1<<8 + jl .w4_ret + movq m4, [rsp+8*1] + add r5, 4 + mov dstq, r5 + paddw m4, [rsp+8*0] ; base_y += 4*dy + movzx r2d, word [rsp+16*15+8*1] + movddup m6, [rsp+16*15+8*1] + paddw m6, [rsp+16*12] ; base_x += (4 << upsample_above) + add r2d, r10d + mov r10d, r2d + jmp .w4_loop0 +.w4_ret: + RET +.w8: + test angled, 0x400 + jnz .w4_main + movd m5, [tlq+8] + lea r3d, [angleq+126] + pshufb m5, m7 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + movd [rsp+16*8+8], m5 + cmp r3d, 8 + ja .w8_no_upsample_above ; angle >= 130 || h > 8 || is_sm + call .upsample_above + sub angled, 53 + lea r3d, [hq+7] + xor angled, 0x7f ; 180 - angle + movu m1, [base+z_filter_wh8] + movd m0, r3d + movd m6, angled + shr angled, 8 ; is_sm << 1 + psrldq m2, [base+z_filter_t_w48+angleq*8], 4 + pshufb m0, m7 + pshufb m6, m7 + pcmpeqb m0, m1 + pand m6, m0 + pcmpgtb m6, m2 +%if ARCH_X86_64 + movq [rsp+16*15+8*1], m10 ; 8<<6 +%else + movq m0, m10 + movq [rsp+16*15+8*1], m0 +%endif + jmp .w8_filter_left +.w8_no_upsample_above: + lea r3d, [hq+7] + mov [rsp], angled + sub angled, 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movu m3, [base+z_filter_wh8] + psrldq m4, [base+z_filter_t_w48+angleq*8], 4 + call .w8_filter_top + mov r3d, [rsp] + sub r3d, 141 +%if ARCH_X86_64 + mov r3b, hb +%else + xor r3b, r3b + or r3d, hd +%endif + cmp r3d, 8 + jbe .upsample_left ; angle > 140 && h <= 8 && !is_sm +.w8_filter_left: + pmovmskb r5d, m6 + test r5d, r5d + jz .w4_main + imul r5d, 0x55555555 + mov r3, tlq + shr r5d, 30 + sub r5, 3 ; filter_strength-3 + jmp .filter_left +.w8_filter_top: + movd m6, r3d + REPX {pshufb x, m7}, m0, m1, m6 + pcmpeqb m0, m3 + pand m1, m0 + pand m6, m0 + pcmpgtb m1, m4 + pcmpgtb m6, m4 + pmovmskb r5d, m1 + test r5d, r5d + jz .w8_filter_top_end ; filter_strength == 0 + imul r5d, 0x55555555 + movq m0, [rsp+gprsize+16*8-2] + shr r5d, 30 + movq m1, [rsp+gprsize+16*8-1] + sub r5, 3 ; filter_strength-3 + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + punpcklbw m0, m1 + pmaddubsw m0, m7 + movq m1, [rsp+gprsize+16*8+0] + movq m2, [rsp+gprsize+16*8+1] + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + punpcklbw m1, m2 + pmaddubsw m1, m7 + movq m2, [rsp+gprsize+16*8+2] + movddup m7, [base+z_filter_k+8*2+r5*8+24*2] + punpcklbw m2, m2 + pmaddubsw m2, m7 + paddw m0, m1 + paddw m0, m2 +%if ARCH_X86_64 + mov r3d, r7m ; maxw, offset due to call +%else + mov r3d, [rsp+gprsize+16*18+4*3] +%endif + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + movq [rsp+gprsize+16*8], m0 + cmp r3d, 8 + jge .w8_filter_top_end + movq m0, [tlq+r3+1] + movq [rsp+gprsize+r3+16*8], m0 +.w8_filter_top_end: + ret +.w16: + test angled, 0x400 + jnz .w4_main + lea r3d, [hq+15] + sub angled, 90 + movd m0, r3d + mov r3d, 90 + movd m1, angled + sub r3d, angled ; 180 - angle + shr angled, 8 ; is_sm << 1 + movd m6, r3d + REPX {pshufb x, m7}, m0, m1, m6 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m0, [base+z_filter_wh16] + pand m1, m0 + pand m6, m0 + pcmpgtb m1, m3 + pcmpgtb m6, m3 + pmovmskb r5d, m1 + mov r3, tlq + test r5d, r5d + jz .w16_filter_left ; filter_strength == 0 + imul r5d, 0x24924924 + pshufb m5, [base+z_filter_t_w16] ; tlq[16] + shr r5d, 30 + adc r5, -4 ; filter_strength-3 + movd [rsp+16*9], m5 + movddup m7, [base+z_filter_k+8*2+r5*8+24*0] + movu m1, [rsp+16*8-2] + movu m2, [rsp+16*8-1] + punpcklbw m0, m1, m2 + pmaddubsw m0, m7 + punpckhbw m1, m2 + pmaddubsw m1, m7 + movddup m7, [base+z_filter_k+8*2+r5*8+24*1] + mova m3, [rsp+16*8+0] + movu m4, [rsp+16*8+1] + punpcklbw m2, m3, m4 + pmaddubsw m2, m7 + punpckhbw m3, m4 + pmaddubsw m3, m7 + paddw m0, m2 + paddw m1, m3 + test r5d, r5d + jnz .w16_filter_end ; 3-tap + movddup m7, [base+z_filter_k+8*8] + movu m3, [rsp+16*8+2] + punpcklbw m2, m3, m3 + pmaddubsw m2, m7 + punpckhbw m3, m3 + pmaddubsw m3, m7 + paddw m0, m2 + paddw m1, m3 +.w16_filter_end: + mov r2d, maxwm + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*8], m0 + cmp r2d, 16 + jge .w16_filter_left + movu m0, [r3+r2+1] + movu [rsp+r2+16*8], m0 +.w16_filter_left: + pmovmskb r5d, m6 + test r5d, r5d + jz .w4_main + imul r5d, 0x24924924 + shr r5d, 30 + adc r5, -4 ; filter_strength-3 + jmp .filter_left +.w32: + test angled, 0x400 + jnz .w4_main + pshufb m6, [base+z_filter_t_w16] ; tlq[32] + mov r3, tlq + lea tlq, [rsp+16*9] + movd [tlq+16*1], m6 + xor r5d, r5d ; filter_strength = 3 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mov r2d, maxwm + mova [rsp+16*8], m0 + mova [rsp+16*9], m1 + cmp r2d, 32 + jge .filter_left + movu m0, [r3+r2+16*0+1] + movu m1, [r3+r2+16*1+1] + movu [rsp+r2+16*8], m0 + movu [rsp+r2+16*9], m1 + jmp .filter_left +.w64: + movu m0, [tlq+16*2+1] + movu m1, [tlq+16*3+1] + mova [rsp+16*10], m0 + mova [rsp+16*11], m1 + test angled, 0x400 + jnz .w4_main + pshufb m1, [base+z_filter_t_w16] ; tlq[64] + mov r3, tlq + lea tlq, [rsp+16*11] + movd [tlq+16*1], m1 + xor r5d, r5d ; filter_strength = 3 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mova m2, [tlq+16*2] + mova m3, [tlq+16*3] + mov r2d, maxwm + mova [rsp+16* 8], m0 + mova [rsp+16* 9], m1 + mova [rsp+16*10], m2 + mova [rsp+16*11], m3 + cmp r2d, 64 + jge .filter_left + movu m0, [r3+r2+16*0+1] + movu m1, [r3+r2+16*1+1] + movu [rsp+r2+16* 8], m0 + movu [rsp+r2+16* 9], m1 + cmp r2d, 32 + jge .filter_left + movu m0, [r3+r2+16*2+1] + movu m1, [r3+r2+16*3+1] + movu [rsp+r2+16*10], m0 + movu [rsp+r2+16*11], m1 +.filter_left: + neg hq + movd m0, [r3+hq] + pxor m1, m1 + pshufb m0, m1 + movd [rsp+16*6+hq-4], m0 + lea tlq, [rsp+16*5] + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + cmp hd, -32 + jge .filter_left_end + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + mova m0, [tlq+16*0] + mova m1, [tlq+16*1] + mova [rsp+16*2], m0 + mova [rsp+16*3], m1 +.filter_left_end: + mov r2d, maxhm + mova m0, [rsp+16*5] + mova m1, [rsp+16*6] + mova m2, [rsp+16*7] + neg r2 + mova [rsp+16*4], m0 + mova [rsp+16*5], m1 + mova [rsp+16*6], m2 + cmp r2d, hd + jle .w4_main + movu m0, [r3+r2-16*2] + movu m1, [r3+r2-16*1] + movu [rsp+r2+16*4], m0 + movu [rsp+r2+16*5], m1 + cmp r2d, -32 + jle .w4_main + movu m0, [r3+r2-16*4] + movu m1, [r3+r2-16*3] + movu [rsp+r2+16*2], m0 + movu [rsp+r2+16*3], m1 + jmp .w4_main + +%if ARCH_X86_64 +cglobal ipred_z3_8bpc, 4, 9, 11, 16*10, dst, stride, tl, w, h, angle, dy, _, org_w + %define base r7-$$ + lea r7, [$$] + mova m8, [base+pw_62] + mova m9, [base+pw_64] + mova m10, [base+pw_512] + mov org_wd, wd +%else +cglobal ipred_z3_8bpc, 4, 7, 8, -16*10, dst, stride, tl, w, h, angle, dy + %define base r1-$$ + %define m8 [base+pw_62] + %define m9 [base+pw_64] + %define m10 [base+pw_512] + %define org_wd r5 + %define org_wq r5 + mov [dstq+strideq*0], strideq + mov [dstq+strideq*1], wd + LEA r1, $$ +%endif + tzcnt hd, hm + movifnidn angled, anglem + dec tlq + movsxd hq, [base+ipred_z3_ssse3_table+hq*4] + sub angled, 180 + mov dyd, angled + neg dyd + xor angled, 0x400 + or dyq, ~0x7e + lea hq, [base+ipred_z3_ssse3_table+hq] + movzx dyd, word [base+dr_intra_derivative+45*2-1+dyq] + jmp hq +.h4: + lea r4d, [angleq+88] + test r4d, 0x480 + jnz .h4_no_upsample ; !enable_intra_edge_filter || angle >= 40 + sar r4d, 9 + add r4d, wd + cmp r4d, 8 + jg .h4_no_upsample ; w > 8 || (w == 8 && is_sm) + movu m3, [tlq-7] + movu m1, [base+z_upsample1-4] + movu m4, [base+z_filter_s+2] + pshufb m0, m3, m1 + pxor m1, m1 + pshufb m2, m3, m1 + pshufb m1, m3, m4 + mova [rsp+16], m2 ; top[max_base_y] + movddup m2, [base+pb_36_m4] + add dyd, dyd + pmaddubsw m0, m2 + pmaddubsw m1, m2 + movd m5, dyd + mov r5d, dyd + pshufb m5, [base+pw_256] + paddw m0, m1 + pmulhrsw m0, m10 + shl wd, 2 + mov tlq, rsp + sub rsp, wq + packuswb m0, m0 + punpcklbw m0, m3 + paddw m6, m5, m5 + punpcklqdq m5, m6 + pshufb m0, [base+pb_15to0] + mova [tlq], m0 +.h4_upsample_loop: + lea r4d, [r5+dyq] + shr r5d, 6 + movq m0, [tlq+r5] + lea r5d, [r4+dyq] + shr r4d, 6 + movhps m0, [tlq+r4] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + por m1, m2 + pmaddubsw m0, m1 + paddw m5, m6 + pmulhrsw m0, m10 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jg .h4_upsample_loop + jmp .h4_transpose +.h4_no_upsample: + mov r4d, 7 + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h4_main + lea r4d, [wq+3] + movd m0, r4d + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + pcmpeqb m1, m0, [base+z_filter_wh4] + pand m1, m2 + pcmpgtb m1, [base+z_filter_t_w48+angleq*8] + pmovmskb r5d, m1 + mov r4d, 7 + test r5d, r5d + jz .h4_main ; filter_strength == 0 + movu m2, [tlq-7] + imul r5d, 0x55555555 + movu m3, [base+z_filter_s-2] + shr r5d, 30 ; filter_strength + mova m4, [base+z_upsample2] + movddup m5, [base+z_filter_k-8+r5*8+24*0] + movddup m6, [base+z_filter_k-8+r5*8+24*1] + movddup m7, [base+z_filter_k-8+r5*8+24*2] + pshufb m0, m2, m3 + shufps m3, m4, q2121 + pmaddubsw m1, m0, m5 + pmaddubsw m0, m6 + pshufb m5, m2, m3 + pmaddubsw m3, m5, m6 + pmaddubsw m5, m7 + pshufb m2, m4 + pmaddubsw m2, m7 + paddw m0, m1 + paddw m1, m3 + paddw m0, m5 + paddw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + lea r2d, [r4+2] + cmp wd, 4 + cmovne r4d, r2d + pshufd m0, m0, q0000 + lea tlq, [rsp+15] + packuswb m0, m1 + mova [rsp], m0 +.h4_main: + movd m5, dyd + movddup m0, [base+z_base_inc] ; base_inc << 6 + sub tlq, r4 + shl r4d, 6 + movd m7, [tlq] + movd m4, r4d + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, [base+pw_m256] + mova m3, [base+z3_shuf_h4] + lea r5, [dyq+r4+63] ; ypos + pshufb m4, [base+pw_256] + psubw m4, m0 ; max_base_y + shl wd, 2 + paddw m6, m5, m5 + sub rsp, wq + punpcklqdq m5, m6 +.h4_loop: + lea r4, [r5+dyq] + sar r5, 6 + movq m0, [tlq+r5-4] + lea r5, [r4+dyq] + sar r4, 6 + movhps m0, [tlq+r4-4] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jz .h4_transpose + test r5d, r5d + jg .h4_loop + packuswb m7, m7 +.h4_end_loop: + movq [rsp+wq-8], m7 + sub wd, 8 + jg .h4_end_loop +.h4_transpose: + mova m1, [base+z_transpose4] +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + lea r2, [strideq*3] + lea dstq, [dstq+org_wq-4] +.h4_transpose_loop: + mova m0, [rsp] + add rsp, 16 + pshufb m0, m1 + movd [dstq+strideq*0], m0 + pshuflw m2, m0, q1032 + movd [dstq+strideq*1], m2 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r2 ], m0 + sub dstq, 4 + sub org_wd, 4 + jg .h4_transpose_loop + RET +.h8: + lea r4d, [angleq+88] + and r4d, ~0x7f + or r4d, wd + cmp r4d, 8 + ja .h8_no_upsample ; !enable_intra_edge_filter || is_sm || d >= 40 || w > 8 + mova m4, [tlq-15] + and r4d, 4 + movu m3, [tlq- 9] + movd m1, r4d + movu m2, [base+z_filter_s+2] + pxor m0, m0 + movu m5, [base+z_filter_s+6] + movddup m7, [base+pb_36_m4] + pshufb m1, m0 ; w & 4 + movu m0, [base+z_upsample1-4] + pmaxub m1, m0 ; clip 4x8 + add dyd, dyd + pshufb m0, m4, m1 + pmaddubsw m0, m7 + pshufb m1, m4, m2 + pmaddubsw m1, m7 + pshufb m2, m3, [base+z_upsample1] + pmaddubsw m2, m7 + pshufb m3, m5 + pmaddubsw m3, m7 + movd m5, dyd + neg dyq + paddw m1, m0 + paddw m2, m3 + pmulhrsw m1, m10 + pmulhrsw m2, m10 + shl wd, 3 + lea tlq, [rsp+16] + pshufb m5, [base+pw_256] + sub rsp, wq + packuswb m1, m2 + lea r5, [dyq+63] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + mova [tlq-16*1], m0 + mova [tlq-16*0], m1 + paddw m6, m5, m5 + punpcklqdq m5, m6 +.h8_upsample_loop: + lea r4, [r5+dyq] + sar r5, 6 + movu m0, [tlq+r5] + lea r5, [r4+dyq] + sar r4, 6 + movu m1, [tlq+r4] + pand m3, m8, m5 + psubw m2, m9, m3 + psllw m2, 8 + por m3, m2 + pshufd m2, m3, q1010 + pmaddubsw m0, m2 + punpckhqdq m3, m3 + pmaddubsw m1, m3 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m1, m0 + mova [rsp+wq-16], m1 + sub wd, 16 + jg .h8_upsample_loop + jmp .h8_transpose +.h8_no_upsample: + lea r4d, [wq+7] + movd m0, r4d + and r4d, 7 + or r4d, 8 ; imin(w+7, 15) + test angled, 0x400 + jnz .h8_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movu m1, [base+z_filter_wh8] + psrldq m3, [base+z_filter_t_w48+angleq*8], 4 + pcmpeqb m1, m0 + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .h8_main ; filter_strength == 0 + mova m0, [tlq-15] + imul r5d, 0x55555555 + movd m1, [tlq+1] + neg r4 + movd m2, [tlq+r4] + shr r5d, 30 + pxor m7, m7 + lea tlq, [rsp+16*2] + sub r5, 3 ; filter_strength-3 + mova [tlq+16*0], m0 + pshufb m1, m7 + mova [tlq+16*1], m1 + pshufb m2, m7 + movq [tlq+r4+8], m2 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sar r5d, 1 + add tlq, 31 + add r5d, 17 + cmp wd, 8 + cmova r4d, r5d +.h8_main: + movd m5, dyd + sub tlq, r4 + shl r4d, 6 + movd m7, [tlq] + movd m4, r4d + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, [base+pw_m256] + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, [base+pw_256] + psubw m4, [base+z3_base_inc] + shl wd, 3 + mova m6, m5 + sub rsp, wq +.h8_loop: + mov r4, r5 + sar r4, 6 + movu m0, [tlq+r4-8] + pand m2, m8, m5 + psubw m1, m9, m2 + psllw m2, 8 + pshufb m0, m3 + por m1, m2 + pmaddubsw m0, m1 + pcmpgtw m1, m4, m5 + paddw m5, m6 + pmulhrsw m0, m10 + pand m0, m1 + pandn m1, m7 + por m0, m1 + packuswb m0, m0 + movq [rsp+wq-8], m0 + sub wd, 8 + jz .h8_transpose + add r5, dyq + jg .h8_loop + packuswb m7, m7 +.h8_end_loop: + movq [rsp+wq-8], m7 + sub wd, 8 + jg .h8_end_loop +.h8_transpose: +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + or r3d, 8 + cmp org_wd, 4 +%if ARCH_X86_64 + jne .end_transpose_main +%else + jne .end_transpose_loop +%endif + mova m1, [rsp+16*1] + mova m0, [rsp+16*0] + lea r2, [strideq*3] + add rsp, 16*2 + punpcklbw m2, m1, m0 + punpckhbw m1, m0 + punpckhbw m0, m1, m2 + punpcklbw m1, m2 +.write_4x8_end: + call .write_4x8 + RET +.write_4x8: + movd [dstq+r2 ], m0 + pshuflw m4, m0, q1032 + movd [dstq+strideq*2], m4 + punpckhqdq m0, m0 + movd [dstq+strideq*1], m0 + psrlq m0, 32 + movd [dstq+strideq*0], m0 + lea dstq, [dstq+strideq*4] + movd [dstq+r2 ], m1 + pshuflw m4, m1, q1032 + movd [dstq+strideq*2], m4 + punpckhqdq m1, m1 + movd [dstq+strideq*1], m1 + psrlq m1, 32 + movd [dstq+strideq*0], m1 + ret +.h16: + lea r4d, [wq+15] + movd m0, r4d + and r4d, 15 + or r4d, 16 ; imin(w+15, 31) + test angled, 0x400 + jnz .h16_main + movd m2, angled + shr angled, 8 ; is_sm << 1 + pxor m1, m1 + pshufb m0, m1 + pshufb m2, m1 + movq m3, [base+z_filter_t_w16+angleq*4] + pcmpeqb m1, m0, [base+z_filter_wh16] + pand m1, m2 + pcmpgtb m1, m3 + pmovmskb r5d, m1 + test r5d, r5d + jz .h16_main ; filter_strength == 0 + mova m0, [tlq-16*2+1] + imul r5d, 0x24924924 + mova m1, [tlq-16*1+1] + neg r4 + movd m2, [tlq-16*0+1] + shr r5d, 30 + movd m3, [tlq+r4] + adc r5, -4 ; filter_strength-3 + pxor m7, m7 + lea tlq, [rsp+16*2] + mova [tlq-16*1], m0 + pshufb m2, m7 + mova [tlq+16*0], m1 + pshufb m3, m7 + mova [tlq+16*1], m2 + movq [tlq+r4+8], m3 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + add tlq, 31 + cmp wd, 16 + jle .h16_main + pshuflw m0, [tlq-47], q0000 + sar r5, 1 + movq m1, [base+z3_filter_k_tail+r5*4] + lea r4d, [r5+33] + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq-35], m0 +.h16_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + shl wd, 4 + mova m6, m5 + sub rsp, wq +.h16_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*2] + por m2, m1 + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + psrlw m2, m5, 6 + paddw m5, m6 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + pand m0, m1 + pandn m1, m7 + por m0, m1 + mova [rsp+wq-16], m0 + sub wd, 16 + jz .h16_transpose + add r5, dyq + jg .h16_loop +.h16_end_loop: + mova [rsp+wq-16], m7 + sub wd, 16 + jg .h16_end_loop +.h16_transpose: +%if ARCH_X86_32 + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif + or r3d, 16 + cmp org_wd, 4 +%if ARCH_X86_64 + jne .end_transpose_main +%else + jne .end_transpose_loop +%endif +.h16_transpose_w4: + mova m2, [rsp+16*3] + mova m4, [rsp+16*2] + mova m3, [rsp+16*1] + mova m0, [rsp+16*0] + lea r2, [strideq*3] + add rsp, 16*4 + punpckhbw m1, m2, m4 + punpcklbw m2, m4 + punpckhbw m4, m3, m0 + punpcklbw m3, m0 + punpckhwd m0, m1, m4 + punpcklwd m1, m4 + call .write_4x8 + lea dstq, [dstq+strideq*4] + punpckhwd m0, m2, m3 + punpcklwd m1, m2, m3 + jmp .write_4x8_end +.h32: + lea r4d, [wq+31] + and r4d, 31 + or r4d, 32 ; imin(w+31, 63) + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h32_main + mova m0, [tlq-16*4+1] + mova m1, [tlq-16*3+1] + mova m2, [tlq-16*2+1] + mova m3, [tlq-16*1+1] + movd m4, [tlq-16*0+1] + neg r4 + movd m5, [tlq+r4] + pxor m7, m7 + lea tlq, [rsp+16*4] + mova [tlq-16*3], m0 + mova [tlq-16*2], m1 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*1], m2 + pshufb m4, m7 + mova [tlq+16*0], m3 + pshufb m5, m7 + mova [tlq+16*1], m4 + movq [tlq+r4+8], m5 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + add tlq, 63 + cmp wd, 32 + jle .h32_main + pshuflw m0, [tlq-79], q0000 + movq m1, [base+z3_filter_k_tail] + add r4d, 2 + pmaddubsw m0, m1 +%if ARCH_X86_64 + pmulhrsw m0, m10 +%else + pmulhrsw m0, m4 +%endif + packuswb m0, m0 + movd [tlq-67], m0 +.h32_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + mova m6, m5 +.h32_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*4] + por m2, m1 + movu m1, [tlq+r4-8*3] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + sub rsp, 32 + packuswb m0, m1 + mova [rsp+16*0], m0 + movu m0, [tlq+r4-8*2] + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + psrlw m2, m5, 6 + paddw m5, m6 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + pand m0, m1 + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + mova [rsp+16*1], m0 + pand m0, m1, [rsp+16*0] + pandn m1, m7 + por m0, m1 + mova [rsp+16*0], m0 + dec wd + jz .h32_transpose + add r5, dyq + jg .h32_loop +.h32_end_loop: + sub rsp, 32 + mova [rsp+16*1], m7 + mova [rsp+16*0], m7 + dec wd + jg .h32_end_loop +.h32_transpose: + or r3d, 32 + jmp .end_transpose_main +.h64: + lea r4d, [wq+63] + test angled, 0x400 ; !enable_intra_edge_filter + jnz .h64_main + mova m0, [tlq-16*8+1] + mova m1, [tlq-16*7+1] + mova m2, [tlq-16*6+1] + mova m3, [tlq-16*5+1] + mova [rsp+16*1], m0 + mova [rsp+16*2], m1 + mova [rsp+16*3], m2 + mova [rsp+16*4], m3 + mova m0, [tlq-16*4+1] + mova m1, [tlq-16*3+1] + mova m2, [tlq-16*2+1] + mova m3, [tlq-16*1+1] + movd m4, [tlq-16*0+1] + neg r4 + movd m5, [tlq+r4] + pxor m7, m7 + lea tlq, [rsp+16*8] + mova [tlq-16*3], m0 + mova [tlq-16*2], m1 + xor r5d, r5d ; filter_strength = 3 + mova [tlq-16*1], m2 + pshufb m4, m7 + mova [tlq+16*0], m3 + pshufb m5, m7 + mova [tlq+16*1], m4 + movq [tlq+r4+8], m5 + neg r4d + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge + sub tlq, 16*2 + cmp wd, 64 + jl .h64_filter96 ; skip one call if the last 32 bytes aren't used + call mangle(private_prefix %+ _ipred_z1_8bpc_ssse3).filter_edge +.h64_filter96: + add tlq, 127 +.h64_main: + movd m5, dyd + sub tlq, r4 + movd m4, r4d + shl r4d, 6 + movd m7, [tlq] + pxor m6, m6 + pshufb m5, [base+pw_256] + neg dyq + pshufb m7, m6 + mova m3, [base+z3_shuf] + lea r5, [dyq+r4+63] + pshufb m4, m6 + psubb m4, [base+pb_15to0] + mova m6, m5 +.h64_loop: + mov r4, r5 + pand m2, m8, m5 + sar r4, 6 + psubw m1, m9, m2 + psllw m2, 8 + movu m0, [tlq+r4-8*8] + por m2, m1 + movu m1, [tlq+r4-8*7] + pshufb m0, m3 + pmaddubsw m0, m2 + pshufb m1, m3 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + sub rsp, 64 + packuswb m0, m1 + mova [rsp+16*0], m0 + movu m0, [tlq+r4-8*6] + movu m1, [tlq+r4-8*5] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*1], m0 + movu m0, [tlq+r4-8*4] + movu m1, [tlq+r4-8*3] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + packuswb m0, m1 + mova [rsp+16*2], m0 + movu m0, [tlq+r4-8*2] + movu m1, [tlq+r4-8*1] + pshufb m0, m3 + pshufb m1, m3 + pmaddubsw m0, m2 + pmaddubsw m1, m2 + pmulhrsw m0, m10 + pmulhrsw m1, m10 + psrlw m2, m5, 6 + paddw m5, m6 + packsswb m2, m2 + packuswb m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + pand m0, m1 + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + mova [rsp+16*3], m0 + pand m0, m1, [rsp+16*2] + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + paddsb m2, [base+pb_16] + mova [rsp+16*2], m0 + pand m0, m1, [rsp+16*1] + pandn m1, m7 + por m0, m1 + pcmpgtb m1, m4, m2 + mova [rsp+16*1], m0 + pand m0, m1, [rsp+16*0] + pandn m1, m7 + por m0, m1 + mova [rsp+16*0], m0 + dec wd + jz .h64_transpose + add r5, dyq + jg .h64_loop +.h64_end_loop: + sub rsp, 64 + mova [rsp+16*3], m7 + mova [rsp+16*2], m7 + mova [rsp+16*1], m7 + mova [rsp+16*0], m7 + dec wd + jg .h64_end_loop +.h64_transpose: + or r3d, 64 +.end_transpose_main: +%if ARCH_X86_64 + lea r5, [r3*3] + lea r7, [strideq*3] +%else + mov strideq, [dstq] + mov org_wd, [dstq+strideq] +%endif +.end_transpose_loop: + lea r4, [rsp+r3-8] + lea r6, [dstq+org_wq-8] +.end_transpose_loop_y: + movq m0, [r4+r3*1] + movq m4, [r4+r3*0] +%if ARCH_X86_64 + movq m1, [r4+r5 ] + movq m5, [r4+r3*2] + lea r2, [r4+r3*4] +%else + lea r2, [r4+r3*2] + movq m1, [r2+r3*1] + movq m5, [r2+r3*0] + lea r2, [r2+r3*2] +%endif + movq m2, [r2+r3*1] + movq m6, [r2+r3*0] +%if ARCH_X86_64 + movq m3, [r2+r5 ] + movq m7, [r2+r3*2] +%else + lea r2, [r2+r3*2] + movq m3, [r2+r3*1] + movq m7, [r2+r3*0] +%endif + sub r4, 8 + punpcklbw m0, m4 + punpcklbw m1, m5 + punpcklbw m2, m6 + punpcklbw m3, m7 + punpckhwd m4, m1, m0 + punpcklwd m1, m0 + punpckhwd m0, m3, m2 + punpcklwd m3, m2 + punpckhdq m2, m3, m1 + punpckldq m3, m1 + punpckldq m1, m0, m4 + punpckhdq m0, m4 + movhps [r6+strideq*0], m0 + movq [r6+strideq*1], m0 +%if ARCH_X86_64 + movhps [r6+strideq*2], m1 + movq [r6+r7 ], m1 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m1 + movq [r6+strideq*1], m1 + lea r6, [r6+strideq*2] +%endif + movhps [r6+strideq*0], m2 + movq [r6+strideq*1], m2 +%if ARCH_X86_64 + movhps [r6+strideq*2], m3 + movq [r6+r7 ], m3 + lea r6, [r6+strideq*4] +%else + lea r6, [r6+strideq*2] + movhps [r6+strideq*0], m3 + movq [r6+strideq*1], m3 + lea r6, [r6+strideq*2] +%endif + cmp r4, rsp + jae .end_transpose_loop_y + lea rsp, [rsp+r3*8] + sub org_wd, 8 + jg .end_transpose_loop + RET + +;--------------------------------------------------------------------------------------- +;int dav1d_pal_pred_ssse3(pixel *dst, const ptrdiff_t stride, const uint16_t *const pal, +; const uint8_t *idx, const int w, const int h); +;--------------------------------------------------------------------------------------- +cglobal pal_pred_8bpc, 4, 6, 5, dst, stride, pal, idx, w, h + mova m4, [palq] + LEA r2, pal_pred_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r2+wq*4] + packuswb m4, m4 + add wq, r2 + lea r2, [strideq*3] + jmp wq +.w4: + pshufb m0, m4, [idxq] + add idxq, 16 + movd [dstq ], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq ], m1 + punpckhqdq m0, m0 + movd [dstq+strideq*2], m0 + psrlq m0, 32 + movd [dstq+r2 ], m0 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + add idxq, 32 + movq [dstq ], m0 + movhps [dstq+strideq ], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r2 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+strideq ], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r2 ], m3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16 + RET +ALIGN function_align +.w32: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+16 ], m1 + mova [dstq+strideq ], m2 + mova [dstq+strideq+16], m3 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32 + RET +ALIGN function_align +.w64: + pshufb m0, m4, [idxq] + pshufb m1, m4, [idxq+16] + pshufb m2, m4, [idxq+32] + pshufb m3, m4, [idxq+48] + add idxq, 64 + mova [dstq ], m0 + mova [dstq+16], m1 + mova [dstq+32], m2 + mova [dstq+48], m3 + add dstq, strideq + sub hd, 1 + jg .w64 + RET + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +%macro IPRED_CFL 1 ; ac in, unpacked pixels out + psignw m3, m%1, m1 + pabsw m%1, m%1 + pmulhrsw m%1, m2 + psignw m%1, m3 + paddw m%1, m0 +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal ipred_cfl_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + movifnidn wd, wm + movifnidn hd, hm + tzcnt r6d, hd + lea t0d, [wq+hq] + movd m4, t0d + tzcnt t0d, t0d + movd m5, t0d + LEA t0, ipred_cfl_ssse3_table + tzcnt wd, wd + movsxd r6, [t0+r6*4] + movsxd wq, [t0+wq*4+16] + pcmpeqd m3, m3 + psrlw m4, 1 + add r6, t0 + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h4: + movd m0, [tlq-4] + pmaddubsw m0, m3 + jmp wq +.w4: + movd m1, [tlq+1] + pmaddubsw m1, m3 + psubw m0, m4 + paddw m0, m1 + pmaddwd m0, m3 + cmp hd, 4 + jg .w4_mul + psrlw m0, 3 ; dc >>= ctz(width + height); + jmp .w4_end +.w4_mul: + punpckhqdq m1, m0, m0 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + psrlw m0, 2 + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8 + cmovz r6d, r2d + movd m5, r6d + pmulhuw m0, m5 +.w4_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s4: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s4_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movd [dstq+strideq*0], m4 + pshuflw m4, m4, q1032 + movd [dstq+strideq*1], m4 + punpckhqdq m4, m4 + movd [dstq+strideq*2], m4 + psrlq m4, 32 + movd [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + add acq, 32 + sub hd, 4 + jg .s4_loop + RET +ALIGN function_align +.h8: + movq m0, [tlq-8] + pmaddubsw m0, m3 + jmp wq +.w8: + movq m1, [tlq+1] + pmaddubsw m1, m3 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + paddw m0, m1 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 8 + je .w8_end + mov r6d, 0x5556 + mov r2d, 0x3334 + cmp hd, 32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w8_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s8: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + lea r6, [strideq*3] + pabsw m2, m1 + psllw m2, 9 +.s8_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movq [dstq ], m4 + movhps [dstq+strideq ], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + movq [dstq+strideq*2], m4 + movhps [dstq+r6 ], m4 + lea dstq, [dstq+strideq*4] + add acq, 64 + sub hd, 4 + jg .s8_loop + RET +ALIGN function_align +.h16: + mova m0, [tlq-16] + pmaddubsw m0, m3 + jmp wq +.w16: + movu m1, [tlq+1] + pmaddubsw m1, m3 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 16 + je .w16_end + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 8|32 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w16_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s16: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s16_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq+strideq], m4 + lea dstq, [dstq+strideq*2] + add acq, 64 + sub hd, 2 + jg .s16_loop + RET +ALIGN function_align +.h32: + mova m0, [tlq-32] + pmaddubsw m0, m3 + mova m2, [tlq-16] + pmaddubsw m2, m3 + paddw m0, m2 + jmp wq +.w32: + movu m1, [tlq+1] + pmaddubsw m1, m3 + movu m2, [tlq+17] + pmaddubsw m2, m3 + paddw m1, m2 + paddw m0, m1 + psubw m4, m0 + punpckhqdq m0, m0 + psubw m0, m4 + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 + pmaddwd m0, m3 + psrlw m0, m5 + cmp hd, 32 + je .w32_end + lea r2d, [hq*2] + mov r6d, 0x5556 + mov r2d, 0x3334 + test hd, 64|16 + cmovz r6d, r2d + movd m1, r6d + pmulhuw m0, m1 +.w32_end: + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 +.s32: + movd m1, alpham + pshuflw m1, m1, q0000 + punpcklqdq m1, m1 + pabsw m2, m1 + psllw m2, 9 +.s32_loop: + mova m4, [acq] + mova m5, [acq+16] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq], m4 + mova m4, [acq+32] + mova m5, [acq+48] + IPRED_CFL 4 + IPRED_CFL 5 + packuswb m4, m5 + mova [dstq+16], m4 + add dstq, strideq + add acq, 64 + dec hd + jg .s32_loop + RET + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_left_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_left_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + mov hd, hm ; zero upper half + tzcnt r6d, hd + sub tlq, hq + tzcnt wd, wm + movu m0, [tlq] + mov t0d, 0x8000 + movd m3, t0d + movd m2, r6d + psrld m3, m2 + LEA t0, ipred_cfl_left_ssse3_table + movsxd r6, [t0+r6*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_ssse3_table-ipred_cfl_left_ssse3_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 +.h32: + movu m1, [tlq+16] ; unaligned when jumping here from dc_top + pmaddubsw m1, m2 + paddw m0, m1 +.h16: + pshufd m1, m0, q3232 ; psrlq m1, m0, 16 + paddw m0, m1 +.h8: + pshuflw m1, m0, q1032 ; psrlq m1, m0, 32 + paddw m0, m1 +.h4: + pmaddwd m0, m2 + pmulhrsw m0, m3 + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + jmp wq + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_top_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_top_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + LEA t0, ipred_cfl_left_ssse3_table + tzcnt wd, wm + inc tlq + movu m0, [tlq] + movifnidn hd, hm + mov r6d, 0x8000 + movd m3, r6d + movd m2, wd + psrld m3, m2 + movsxd r6, [t0+wq*4] + pcmpeqd m2, m2 + pmaddubsw m0, m2 + add r6, t0 + add t0, ipred_cfl_splat_ssse3_table-ipred_cfl_left_ssse3_table + movsxd wq, [t0+wq*4] + add wq, t0 + movifnidn acq, acmp + jmp r6 + +;--------------------------------------------------------------------------------------- +;void dav1d_ipred_cfl_128_ssse3(pixel *dst, const ptrdiff_t stride, const pixel *const topleft, +; const int width, const int height, const int16_t *ac, const int alpha); +;--------------------------------------------------------------------------------------- +cglobal ipred_cfl_128_8bpc, 3, 7, 6, dst, stride, tl, w, h, ac, alpha + tzcnt wd, wm + movifnidn hd, hm + LEA r6, ipred_cfl_splat_ssse3_table + movsxd wq, [r6+wq*4] + movddup m0, [r6-ipred_cfl_splat_ssse3_table+pw_128] + add wq, r6 + movifnidn acq, acmp + jmp wq + +%macro RELOAD_ACQ_32 1 + mov acq, ac_bakq ; restore acq +%endmacro + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_420_8bpc, 4, 8, 7, ac, y, stride, wpad, hpad, w, h, ac_bak +DECLARE_REG_TMP 7 + movddup m2, [pb_2] +%else +cglobal ipred_cfl_ac_420_8bpc, 4, 7, 7, ac, y, stride, wpad, hpad, w, h +DECLARE_REG_TMP 4 +%define ac_bakq acmp + mov t0d, 0x02020202 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m5, t0d + movifnidn hpadd, hpadm +%if ARCH_X86_64 + mov ac_bakq, acq +%endif + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq m0, [yq] + movq m1, [yq+strideq] + movhps m0, [yq+strideq*2] + movhps m1, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 16 + sub hd, 2 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4_8 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop + jmp .calc_avg_4_8 +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + mova m0, [yq+strideq*2] + mova m1, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 2 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_4_8 + jmp .w8_hpad +.w8_wpad: ; wpadd=1 + movddup m0, [yq] + movddup m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufhw m0, m0, q3333 + mova [acq], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 16 + sub hd, 1 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_4_8 +.w8_hpad: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 1 + jg .w8_hpad + jmp .calc_avg_4_8 +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + mova m6, [yq+16] + mova m1, [yq+strideq+16] + pmaddubsw m6, m2 + pmaddubsw m1, m2 + paddw m6, m1 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_loop + test hpadd, hpadd + jz .calc_avg16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movddup m0, [yq] + movddup m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + pshufhw m0, m0, q3333 + mova [acq], m0 + paddw m4, m0 + mova m6, m0 + punpckhqdq m6, m0, m0 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + pshufhw m6, m0, q3333 + punpckhqdq m6, m6 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m0, [yq] + mova m1, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + paddw m0, m1 + mova [acq], m0 + paddw m4, m0 + movddup m6, [yq+16] + movddup m1, [yq+strideq+16] + pmaddubsw m6, m2 + pmaddubsw m1, m2 + paddw m6, m1 + pshufhw m6, m6, q3333 + mova [acq+16], m6 + paddw m4, m6 + lea yq, [yq+strideq*2] + add acq, 32 + dec hd + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg16 +.w16_hpad_loop: + mova [acq], m0 + paddw m4, m0 + mova [acq+16], m6 + paddw m4, m6 + add acq, 32 + dec hpadd + jg .w16_hpad_loop + jmp .calc_avg16 + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif +.calc_avg_4_8: + psrlw m2, 9 + pmaddwd m4, m2 + jmp .calc_avg +.calc_avg16: + psrld m0, m4, 16 + pslld m4, 16 + psrld m4, 16 + paddd m4, m0 +.calc_avg: + movd szd, m5 + psrad m5, 1 + tzcnt r1d, szd + paddd m4, m5 + movd m1, r1d + pshufd m0, m4, q2301 + paddd m0, m4 + pshufd m4, m0, q1032 + paddd m0, m4 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq +.sub_loop: + mova m1, [acq] + psubw m1, m0 ; ac[x] -= sum; + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_422_8bpc, 4, 8, 7, ac, y, stride, wpad, hpad, w, h, ac_bak + movddup m2, [pb_4] +%else +cglobal ipred_cfl_ac_422_8bpc, 4, 7, 7, ac, y, stride, wpad, hpad, w, h + mov t0d, 0x04040404 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m6, t0d + movifnidn hpadd, hpadm +%if ARCH_X86_64 + mov ac_bakq, acq +%endif + shl hpadd, 2 + sub hd, hpadd + pxor m4, m4 + pxor m5, m5 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movq m1, [yq] + movhps m1, [yq+strideq] + movq m0, [yq+strideq*2] + movhps m0, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m4, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop + jmp .calc_avg_4 +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + mova m1, [yq] + mova m0, [yq+strideq] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m0 + paddw m5, m1 + mova m1, [yq+strideq*2] + mova m0, [yq+stride3q] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w8_hpad +.w8_wpad: + movddup m1, [yq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + movddup m0, [yq+strideq] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + sub hd, 2 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_8_16 +.w8_hpad: + mova [acq], m0 + paddw m4, m0 + mova [acq+16], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad + jmp .calc_avg_8_16 +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m1, [yq] + mova m0, [yq+16] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m0 + paddw m5, m1 + mova m1, [yq+strideq] + mova m0, [yq+strideq+16] + pmaddubsw m0, m2 + pmaddubsw m1, m2 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m0 + paddw m4, m1 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movddup m1, [yq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movddup m1, [yq+strideq] + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq+32], m1 + paddw m4, m1 + punpckhqdq m0, m1, m1 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + mova m1, [yq] + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + pshufhw m1, m1, q3333 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + mova m1, [yq+strideq] + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + mova m0, m1 + pshufhw m0, m0, q3333 + punpckhqdq m0, m0 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m1, [yq] + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + movddup m0, [yq+16] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m5, m0 + mova m1, [yq+strideq] + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + movddup m0, [yq+strideq+16] + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg_8_16 +.w16_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m1 + paddw m5, m0 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m1 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop + jmp .calc_avg_8_16 + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif +.calc_avg_4: + psrlw m2, 10 + pmaddwd m5, m2 + pmaddwd m0, m4, m2 + jmp .calc_avg +.calc_avg_8_16: + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, m4 + psrld m0, 16 + pslld m4, 16 + psrld m4, 16 + paddd m0, m4 +.calc_avg: + paddd m5, m0 + movd szd, m6 + psrad m6, 1 + tzcnt r1d, szd ; const int log2sz = ctz(width) + ctz(height); + paddd m5, m6 + movd m1, r1d + pshufd m0, m5, q2301 + paddd m0, m5 + pshufd m5, m0, q1032 + paddd m0, m5 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq ; ac = ac_orig +.sub_loop: + mova m1, [acq] + psubw m1, m0 + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +%if ARCH_X86_64 +cglobal ipred_cfl_ac_444_8bpc, 4, 8, 7, -4*16, ac, y, stride, wpad, hpad, w, h, ac_bak + movddup m2, [pb_4] +%else +cglobal ipred_cfl_ac_444_8bpc, 4, 7, 7, -5*16, ac, y, stride, wpad, hpad, w, h +%define ac_bakq [rsp+16*4] + mov t0d, 0x04040404 + movd m2, t0d + pshufd m2, m2, q0000 +%endif + movifnidn wd, wm + movifnidn hpadd, hpadm + movd m0, hpadd + mov t0d, hm + mov hd, t0d + imul t0d, wd + movd m6, t0d + movd hpadd, m0 + mov ac_bakq, acq + shl hpadd, 2 + sub hd, hpadd + pxor m5, m5 + pxor m4, m4 + cmp wd, 16 + jg .w32 + cmp wd, 8 + jg .w16 + je .w8 + ; fall-through + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h, ac_bak +%else + DEFINE_ARGS ac, y, stride, wpad, hpad, stride3, h +%endif +.w4: + lea stride3q, [strideq*3] +.w4_loop: + movd m1, [yq] + movd m3, [yq+strideq] + punpckldq m1, m3 + punpcklbw m1, m1 + movd m0, [yq+strideq*2] + movd m3, [yq+stride3q] + punpckldq m0, m3 + punpcklbw m0, m0 + pmaddubsw m1, m2 + pmaddubsw m0, m2 + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m0 + paddw m5, m1 + lea yq, [yq+strideq*4] + add acq, 32 + sub hd, 4 + jg .w4_loop + test hpadd, hpadd + jz .calc_avg_4 + punpckhqdq m0, m0 +.w4_hpad_loop: + mova [acq], m0 + paddw m5, m0 + add acq, 16 + sub hpadd, 2 + jg .w4_hpad_loop +.calc_avg_4: + psrlw m2, 10 + pmaddwd m5, m2 + jmp .calc_avg + +.w8: + lea stride3q, [strideq*3] + test wpadd, wpadd + jnz .w8_wpad +.w8_loop: + movq m1, [yq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + movq m0, [yq+strideq] + punpcklbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + movq m1, [yq+strideq*2] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + movq m0, [yq+stride3q] + punpcklbw m0, m0 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*4] + add acq, 64 + sub hd, 4 + jg .w8_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w8_hpad +.w8_wpad: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pmaddubsw m1, m2 + pshufhw m1, m1, q3333 + mova [acq], m1 + paddw m5, m1 + movd m0, [yq+strideq] + punpcklbw m0, m0 + punpcklqdq m0, m0 + pmaddubsw m0, m2 + pshufhw m0, m0, q3333 + mova [acq+16], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 32 + sub hd, 2 + jg .w8_wpad + test hpadd, hpadd + jz .calc_avg_8_16 +.w8_hpad: + mova [acq], m0 + paddw m5, m0 + mova [acq+16], m0 + paddw m4, m0 + add acq, 32 + sub hpadd, 2 + jg .w8_hpad + jmp .calc_avg_8_16 + +.w16: + test wpadd, wpadd + jnz .w16_wpad +.w16_loop: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + mova m0, [yq+strideq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_loop + test hpadd, hpadd + jz .calc_avg_8_16 + jmp .w16_hpad_loop +.w16_wpad: + cmp wpadd, 2 + jl .w16_pad1 + je .w16_pad2 +.w16_pad3: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movd m1, [yq+strideq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhqdq m0, m1, m1 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad3 + jmp .w16_wpad_done +.w16_pad2: + movq m1, [yq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + pshufhw m1, m1, q3333 + punpckhqdq m1, m1 + mova [acq+16], m1 + paddw m5, m1 + movq m1, [yq+strideq] + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + mova m0, m1 + pshufhw m0, m0, q3333 + punpckhqdq m0, m0 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad2 + jmp .w16_wpad_done +.w16_pad1: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0 + mova m0, [yq+strideq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq+32], m1 + paddw m4, m1 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+48], m0 + paddw m4, m0 + lea yq, [yq+strideq*2] + add acq, 64 + sub hd, 2 + jg .w16_pad1 +.w16_wpad_done: + test hpadd, hpadd + jz .calc_avg_8_16 +.w16_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m4, m1 + paddw m5, m0 + mova [acq+32], m1 + mova [acq+48], m0 + paddw m4, m1 + paddw m5, m0 + add acq, 64 + sub hpadd, 2 + jg .w16_hpad_loop +.calc_avg_8_16: + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, m4 + psrld m0, 16 + pslld m4, 16 + psrld m4, 16 + paddd m0, m4 + paddd m5, m0 + jmp .calc_avg + +.w32: + pxor m0, m0 + mova [rsp ], m0 + mova [rsp+16], m0 + mova [rsp+32], m0 + mova [rsp+48], m0 + test wpadd, wpadd + jnz .w32_wpad +.w32_loop: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m4, [yq+16] + mova m3, m4 + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + punpckhbw m4, m4 + pmaddubsw m4, m2 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_loop + test hpadd, hpadd + jz .calc_avg_32 + jmp .w32_hpad_loop +.w32_wpad: + cmp wpadd, 2 + jl .w32_pad1 + je .w32_pad2 + cmp wpadd, 4 + jl .w32_pad3 + je .w32_pad4 + cmp wpadd, 6 + jl .w32_pad5 + je .w32_pad6 +.w32_pad7: + movd m1, [yq] + punpcklbw m1, m1 + punpcklqdq m1, m1 + pshufhw m1, m1, q3333 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + mova m0, m1 + punpckhqdq m0, m0 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad7 + jmp .w32_wpad_done +.w32_pad6: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + pshufhw m0, m1, q3333 + punpckhqdq m0, m0 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad6 + jmp .w32_wpad_done +.w32_pad5: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + mova m5, [rsp] + paddw m5, m1 + mova [rsp ], m5 + punpckhbw m0, m0 + punpcklqdq m0, m0 + pshufhw m0, m0, q3333 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + punpckhqdq m3, m3 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad5 + jmp .w32_wpad_done +.w32_pad4: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, m0 + pshufhw m3, m3, q3333 + punpckhqdq m3, m3 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad4 + jmp .w32_wpad_done +.w32_pad3: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + movd m3, [yq+16] + punpcklbw m3, m3 + punpcklqdq m3, m3 + pshufhw m3, m3, q3333 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + mova m4, m3 + punpckhqdq m4, m4 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad3 + jmp .w32_wpad_done +.w32_pad2: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m3, [yq+16] + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + pshufhw m4, m3, q3333 + punpckhqdq m4, m4 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad2 + jmp .w32_wpad_done +.w32_pad1: + mova m0, [yq] + mova m1, m0 + punpcklbw m1, m1 + pmaddubsw m1, m2 + mova [acq], m1 + paddw m5, m1, [rsp] + mova [rsp ], m5 + punpckhbw m0, m0 + pmaddubsw m0, m2 + mova [acq+16], m0 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova m4, [yq+16] + mova m3, m4 + punpcklbw m3, m3 + pmaddubsw m3, m2 + mova [acq+32], m3 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + punpckhbw m4, m4 + punpcklqdq m4, m4 + pshufhw m4, m4, q3333 + pmaddubsw m4, m2 + mova [acq+48], m4 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + lea yq, [yq+strideq] + add acq, 64 + sub hd, 1 + jg .w32_pad1 +.w32_wpad_done: + test hpadd, hpadd + jz .calc_avg_32 +.w32_hpad_loop: + mova [acq], m1 + mova [acq+16], m0 + paddw m5, m1, [rsp] + mova [rsp ], m5 + paddw m5, m0, [rsp+16] + mova [rsp+16], m5 + mova [acq+32], m3 + mova [acq+48], m4 + paddw m5, m3, [rsp+32] + mova [rsp+32], m5 + paddw m5, m4, [rsp+48] + mova [rsp+48], m5 + add acq, 64 + sub hpadd, 1 + jg .w32_hpad_loop + +%if ARCH_X86_64 + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h, ac_bak +%else + DEFINE_ARGS ac, y, iptr, wpad, hpad, sz, h +%endif + +.calc_avg_32: + mova m5, [rsp] + mova m0, m5 + psrld m5, 16 + pslld m0, 16 + psrld m0, 16 + paddd m5, m0 + mova m0, [rsp+16] + mova m3, m0 + psrld m0, 16 + pslld m3, 16 + psrld m3, 16 + paddd m0, m3 + paddd m5, m0 + mova m0, [rsp+32] + mova m3, m0 + psrld m0, 16 + pslld m3, 16 + psrld m3, 16 + paddd m0, m3 + mova m1, [rsp+48] + mova m3, m1 + psrld m1, 16 + pslld m3, 16 + psrld m3, 16 + paddd m1, m3 + paddd m1, m0 + paddd m5, m1 +.calc_avg: + movd szd, m6 + psrad m6, 1 + tzcnt r1d, szd ; const int log2sz = ctz(width) + ctz(height); + paddd m5, m6 + movd m1, r1d + pshufd m0, m5, q2301 + paddd m0, m5 + pshufd m5, m0, q1032 + paddd m0, m5 + psrad m0, m1 ; sum >>= log2sz; + packssdw m0, m0 + RELOAD_ACQ_32 acq ; ac = ac_orig +.sub_loop: + mova m1, [acq] + psubw m1, m0 + mova [acq], m1 + add acq, 16 + sub szd, 8 + jg .sub_loop + RET + +; %1 simd register that hold the mask and will hold the result +; %2 simd register that holds the "true" values +; %3 location of the "false" values (simd register/memory) +%macro BLEND 3 ; mask, true, false + pand %2, %1 + pandn %1, %3 + por %1, %2 +%endmacro + +%macro PAETH 2 ; top, ldiff + pavgb m1, m%1, m3 + pxor m0, m%1, m3 + pand m0, m4 + psubusb m2, m5, m1 + psubb m1, m0 + psubusb m1, m5 + por m1, m2 + paddusb m1, m1 + por m1, m0 ; min(tldiff, 255) + psubusb m2, m5, m3 + psubusb m0, m3, m5 + por m2, m0 ; tdiff +%ifnum %2 + pminub m2, m%2 + pcmpeqb m0, m%2, m2 ; ldiff <= tdiff +%else + mova m0, %2 + pminub m2, m0 + pcmpeqb m0, m2 +%endif + pminub m1, m2 + pcmpeqb m1, m2 ; ldiff <= tldiff && tdiff <= tldiff + mova m2, m3 + BLEND m0, m2, m%1 + BLEND m1, m0, m5 +%endmacro + +cglobal ipred_paeth_8bpc, 3, 6, 8, -7*16, dst, stride, tl, w, h +%define base r5-ipred_paeth_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + pxor m0, m0 + movd m5, [tlq] + pshufb m5, m0 + LEA r5, ipred_paeth_ssse3_table + movsxd wq, [r5+wq*4] + movddup m4, [base+ipred_paeth_shuf] + add wq, r5 + jmp wq +.w4: + movd m6, [tlq+1] ; top + pshufd m6, m6, q0000 + lea r3, [strideq*3] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 ; ldiff +.w4_loop: + sub tlq, 4 + movd m3, [tlq] + mova m1, [base+ipred_h_shuf] + pshufb m3, m1 ; left + PAETH 6, 7 + movd [dstq ], m1 + pshuflw m0, m1, q1032 + movd [dstq+strideq ], m0 + punpckhqdq m1, m1 + movd [dstq+strideq*2], m1 + psrlq m1, 32 + movd [dstq+r3 ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4_loop + RET +ALIGN function_align +.w8: + movddup m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w8_loop: + sub tlq, 2 + movd m3, [tlq] + pshufb m3, [base+ipred_paeth_shuf] + PAETH 6, 7 + movq [dstq ], m1 + movhps [dstq+strideq], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 +.w16_loop: + sub tlq, 1 + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + PAETH 6, 7 + mova [dstq], m1 + add dstq, strideq + sub hd, 1 + jg .w16_loop + RET +ALIGN function_align +.w32: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp ], m6 + mova [rsp+16], m7 + movu m6, [tlq+17] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+32], m6 +.w32_loop: + dec tlq + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + mova m6, [rsp] + PAETH 6, [rsp+16] + mova [dstq ], m1 + mova m6, [rsp+32] + PAETH 6, 7 + mova [dstq+16], m1 + add dstq, strideq + dec hd + jg .w32_loop + RET +ALIGN function_align +.w64: + movu m6, [tlq+1] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp ], m6 + mova [rsp+16], m7 + movu m6, [tlq+17] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+32], m6 + mova [rsp+48], m7 + movu m6, [tlq+33] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+64], m6 + mova [rsp+80], m7 + movu m6, [tlq+49] + psubusb m7, m5, m6 + psubusb m0, m6, m5 + por m7, m0 + mova [rsp+96], m6 +.w64_loop: + dec tlq + movd m3, [tlq] + pxor m1, m1 + pshufb m3, m1 + mova m6, [rsp] + PAETH 6, [rsp+16] + mova [dstq ], m1 + mova m6, [rsp+32] + PAETH 6, [rsp+48] + mova [dstq+16], m1 + mova m6, [rsp+64] + PAETH 6, [rsp+80] + mova [dstq+32], m1 + mova m6, [rsp+96] + PAETH 6, 7 + mova [dstq+48], m1 + add dstq, strideq + dec hd + jg .w64_loop + RET + + +%macro FILTER 4 ;dst, src, tmp, shuf +%ifnum %4 + pshufb m%2, m%4 +%else + pshufb m%2, %4 +%endif + pshufd m%1, m%2, q0000 ;p0 p1 + pmaddubsw m%1, m2 + pshufd m%3, m%2, q1111 ;p2 p3 + pmaddubsw m%3, m3 + paddw m%1, [base+pw_8] + paddw m%1, m%3 + pshufd m%3, m%2, q2222 ;p4 p5 + pmaddubsw m%3, m4 + paddw m%1, m%3 + pshufd m%3, m%2, q3333 ;p6 __ + pmaddubsw m%3, m5 + paddw m%1, m%3 + psraw m%1, 4 + packuswb m%1, m%1 +%endmacro + +cglobal ipred_filter_8bpc, 3, 7, 8, dst, stride, tl, w, h, filter +%define base r6-$$ + LEA r6, $$ + tzcnt wd, wm +%ifidn filterd, filterm + movzx filterd, filterb +%else + movzx filterd, byte filterm +%endif + shl filterd, 6 + lea filterq, [base+filter_intra_taps+filterq] + movq m0, [tlq-3] ;_ 6 5 0 1 2 3 4 + movsxd wq, [base+ipred_filter_ssse3_table+wq*4] + mova m2, [filterq+16*0] + mova m3, [filterq+16*1] + mova m4, [filterq+16*2] + mova m5, [filterq+16*3] + lea wq, [base+ipred_filter_ssse3_table+wq] + mov hd, hm + jmp wq +.w4: + mova m1, [base+filter_shuf1] + sub tlq, 3 + sub tlq, hq + jmp .w4_loop_start +.w4_loop: + movd m0, [tlq+hq] + punpckldq m0, m6 + lea dstq, [dstq+strideq*2] +.w4_loop_start: + FILTER 6, 0, 7, 1 + movd [dstq+strideq*0], m6 + pshuflw m6, m6, q1032 + movd [dstq+strideq*1], m6 + sub hd, 2 + jg .w4_loop + RET + +ALIGN function_align +.w8: + movq m6, [tlq+1] ;_ _ _ 0 1 2 3 4 + sub tlq, 5 + sub tlq, hq + +.w8_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + FILTER 0, 6, 1, [base+filter_shuf2] + + punpckldq m6, m7, m0 + movq [dstq+strideq*0], m6 + punpckhqdq m6, m6 + movq [dstq+strideq*1], m6 + + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET + +ALIGN function_align +.w16: + movu m6, [tlq+1] ;top row + sub tlq, 5 + sub tlq, hq + +.w16_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+4+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+8+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movd [dstq+12+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+strideq*1], m6 + + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w16_loop + RET + +ALIGN function_align +.w32: + movu m6, [tlq+1] ;top row + lea filterq, [tlq+17] + sub tlq, 5 + sub tlq, hq + +.w32_loop: + FILTER 7, 0, 1, [base+filter_shuf1] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+4+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+8+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movu m1, [filterq] + punpckldq m0, m7, m1 ;_ _ _ 0 1 2 3 4 _ _ _ _ _ _ _ _ + punpcklqdq m0, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+12+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+strideq*1], m6 + + mova m6, m1 + + FILTER 7, 0, 6, [base+filter_shuf2] + punpcklqdq m0, m1, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+16+strideq*0], m7 + psrlq m7, 32 + palignr m7, m1, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m7, m6 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+20+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + + FILTER 7, 0, 1, [base+filter_shuf2] + punpcklqdq m0, m6, m7 ;_ _ _ 0 1 2 3 4 _ _ _ 5 _ _ _ 6 + movd [dstq+24+strideq*0], m7 + psrlq m7, 32 + palignr m7, m6, 4 + + FILTER 6, 0, 1, [base+filter_shuf2] + movd [dstq+28+strideq*0], m6 + psrlq m6, 32 + palignr m6, m7, 4 + mova [dstq+16+strideq*1], m6 + + mova m6, [dstq+strideq*1] + movd m0, [tlq+hq] ;_ 6 5 0 + punpckldq m0, m6 ;_ 6 5 0 1 2 3 4 + lea filterq, [dstq+16+strideq*1] + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8599 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; Copyright © 2021, Matthias Dressel +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 +itx4_shuf: dd 0x50401600, 0xd0c09284, 0x70603422, 0xf0e0b0a6 + dd 0x50401701, 0xd0c09385, 0x70603523, 0xf0e0b1a7 +idct4_12_shuf: dd 0, 2, 4, 6, 1, 3, 5, 7 +idct4_12_shuf2: dd 2, 0, 6, 4, 3, 1, 7, 5 +iadst8_12_shuf: dd 0, 4, 1, 5, 2, 6, 3, 7 +idct16_12_shuf: dd 0, 4, 1, 5, 3, 7, 2, 6 +iadst16_12_shuf: dd 3, 7, 0, 4, 2, 6, 1, 5 +pw_2048_m2048: dw 2048, 2048, 2048, 2048, -2048, -2048, -2048, -2048 +idct4_shuf: db 0, 1, 4, 5, 12, 13, 8, 9, 2, 3, 6, 7, 14, 15, 10, 11 +idct32_shuf: db 0, 1, 8, 9, 4, 5, 12, 13, 2, 3, 10, 11, 6, 7, 14, 15 + +%macro COEF_PAIR 2-3 0 +pd_%1_%2: dd %1, %1, %2, %2 +%define pd_%1 (pd_%1_%2 + 4*0) +%define pd_%2 (pd_%1_%2 + 4*2) +%if %3 +dd -%2, -%2 +%define pd_%2_m%2 pd_%2 +%endif +%endmacro + +COEF_PAIR 201, 995 +COEF_PAIR 401, 1931 +COEF_PAIR 799, 3406 +COEF_PAIR 1380, 601 +COEF_PAIR 1751, 2440 +COEF_PAIR 2598, 1189 +COEF_PAIR 2751, 2106 +COEF_PAIR 2896, 1567, 1 +COEF_PAIR 2896, 3784, 1 +COEF_PAIR 3035, 3513 +COEF_PAIR 3166, 3920 +COEF_PAIR 3703, 3290 +COEF_PAIR 3857, 4052 +COEF_PAIR 4017, 2276 +COEF_PAIR 4076, 3612 +COEF_PAIR 4091, 3973 + +pd_8: dd 8 +pd_m601: dd -601 +pd_m1189: dd -1189 +pd_m1380: dd -1380 +pd_m2106: dd -2106 +pd_m2598: dd -2598 +pd_m2751: dd -2751 +pd_m3344: dd -3344 +pd_1024: dd 1024 +pd_1321: dd 1321 +pd_1448: dd 1448 +pd_1697: dd 1697 +pd_2482: dd 2482 +pd_3072: dd 3072 ; 1024 + 2048 +pd_3803: dd 3803 +pd_5119: dd 5119 ; 1024 + 4096 - 1 +pd_5120: dd 5120 ; 1024 + 4096 +pd_5793: dd 5793 +pd_6144: dd 6144 ; 2048 + 4096 +pd_17408: dd 17408 ; 1024 + 16384 + +pixel_10bpc_max: times 2 dw 0x03ff +pixel_12bpc_max: times 2 dw 0x0fff +dconly_10bpc: times 2 dw 0x7c00 +dconly_12bpc: times 2 dw 0x7000 +clip_18b_min: dd -0x20000 +clip_18b_max: dd 0x1ffff +clip_20b_min: dd -0x80000 +clip_20b_max: dd 0x7ffff + +const idct64_mul_16bpc +dd 4095, 101, 2967, -2824, 3745, 1660, 3822, -1474, 401, 4076, 799, 4017 +dd -700, 4036, 2359, 3349, -2191, 3461, 897, 3996, -2598, -3166, -4017, -799 +dd 4065, 501, 3229, -2520, 3564, 2019, 3948, -1092, 1931, 3612, 3406, 2276 +dd -301, 4085, 2675, 3102, -1842, 3659, 1285, 3889, -1189, -3920, -2276, -3406 + +cextern deint_shuf +cextern idct64_mul +cextern pw_1697x8 +cextern pw_1697x16 +cextern pw_1567_3784 +cextern pw_m1567_m3784 +cextern pw_m3784_1567 +cextern pw_2896_2896 +cextern pw_m2896_2896 +cextern pw_5 +cextern pw_2048 +cextern pw_4096 +cextern pw_8192 +cextern pw_16384 +cextern pw_2896x8 +cextern pd_2048 + +cextern idct_4x8_internal_8bpc_avx2.main +cextern idct_4x16_internal_8bpc_avx2.main +cextern idct_8x8_internal_8bpc_avx2.main +cextern idct_8x16_internal_8bpc_avx2.main +cextern idct_16x4_internal_8bpc_avx2.main +cextern idct_16x8_internal_8bpc_avx2.main +cextern idct_16x16_internal_8bpc_avx2.main +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx2.main +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx2.main_fast +cextern inv_txfm_add_dct_dct_16x32_8bpc_avx2.main_oddhalf +cextern inv_txfm_add_dct_dct_16x32_8bpc_avx2.main_oddhalf_fast +cextern inv_txfm_add_dct_dct_16x64_8bpc_avx2.main_part1 +cextern inv_txfm_add_dct_dct_16x64_8bpc_avx2.main_part2_internal + +cextern iadst_4x4_internal_8bpc_avx2.main +cextern iadst_4x8_internal_8bpc_avx2.main_pass2 +cextern iadst_4x16_internal_8bpc_avx2.main2 +cextern iadst_8x4_internal_8bpc_avx2.main +cextern iadst_8x8_internal_8bpc_avx2.main_pass2 +cextern iadst_8x16_internal_8bpc_avx2.main +cextern iadst_8x16_internal_8bpc_avx2.main_pass2_end +cextern iadst_16x4_internal_8bpc_avx2.main +cextern iadst_16x8_internal_8bpc_avx2.main +cextern iadst_16x8_internal_8bpc_avx2.main_pass2_end +cextern iadst_16x16_internal_8bpc_avx2.main +cextern iadst_16x16_internal_8bpc_avx2.main_pass2_end + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +%macro WRAP_XMM 1+ + INIT_XMM cpuname + %1 + INIT_YMM cpuname +%endmacro + +%macro IWHT4_1D_PACKED 0 + ; m0 = in0 in2, m1 = in1 in3 + psubd m2, m0, m1 ; t2 + paddd xm0, xm1 ; t0 + vpermq m2, m2, q3322 + vpermq m0, m0, q1100 + vpermq m1, m1, q3120 + psubd m3, m0, m2 + psrad m3, 1 + psubd m3, m1 ; t1 t3 + psubd m0, m3 ; ____ out0 + paddd m2, m3 ; out3 ____ +%endmacro + +INIT_YMM avx2 +cglobal inv_txfm_add_wht_wht_4x4_16bpc, 3, 7, 6, dst, stride, c, eob, bdmax + mova xm0, [cq+16*0] + vinserti128 m0, [cq+16*2], 1 + mova xm1, [cq+16*1] + vinserti128 m1, [cq+16*3], 1 + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + lea r6, [dstq+strideq*2] + psrad m0, 2 + psrad m1, 2 + IWHT4_1D_PACKED + punpckhdq m0, m3 + punpckldq m3, m2 + punpckhqdq m1, m0, m3 + punpcklqdq m0, m3 + IWHT4_1D_PACKED + vpblendd m0, m2, 0x33 + packssdw m0, m3 + vextracti128 xm2, m0, 1 + punpckhdq xm1, xm0, xm2 ; out2 out1 + punpckldq xm0, xm2 ; out3 out0 + movq xm2, [r6 +strideq*1] + movhps xm2, [dstq+strideq*0] + movq xm3, [r6 +strideq*0] + movhps xm3, [dstq+strideq*1] +%ifidn bdmaxd, bdmaxm + movd xm5, bdmaxd + vpbroadcastw xm5, xm5 +%else ; win64: load from stack + vpbroadcastw xm5, bdmaxm +%endif + paddsw xm0, xm2 + paddsw xm1, xm3 + pmaxsw xm0, xm4 + pmaxsw xm1, xm4 + pminsw xm0, xm5 + pminsw xm1, xm5 + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movq [r6 +strideq*0], xm1 + movq [r6 +strideq*1], xm0 + RET + +; dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +; dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +; flags: 1 = packed, 2 = inv_dst2 +; skip round/shift if rnd is not a number +%macro ITX_MULSUB_2D 8-9 0 ; dst/src[1-2], tmp[1-3], rnd, coef[1-2], flags +%if %8 < 32 + pmulld m%4, m%1, m%8 + pmulld m%3, m%2, m%8 +%else +%if %9 & 1 + vbroadcasti128 m%3, [pd_%8] +%else + vpbroadcastd m%3, [pd_%8] +%endif + pmulld m%4, m%1, m%3 + pmulld m%3, m%2 +%endif +%if %7 < 32 + pmulld m%1, m%7 + pmulld m%2, m%7 +%else +%if %9 & 1 + vbroadcasti128 m%5, [pd_%7] +%else + vpbroadcastd m%5, [pd_%7] +%endif + pmulld m%1, m%5 + pmulld m%2, m%5 +%endif +%if %9 & 2 + psubd m%4, m%6, m%4 + psubd m%2, m%4, m%2 +%else +%ifnum %6 + paddd m%4, m%6 +%endif + paddd m%2, m%4 +%endif +%ifnum %6 + paddd m%1, m%6 +%endif + psubd m%1, m%3 +%ifnum %6 + psrad m%2, 12 + psrad m%1, 12 +%endif +%endmacro + +%macro INV_TXFM_FN 4-5 10 ; type1, type2, eob_offset, size, bitdepth +cglobal inv_txfm_add_%1_%2_%4_%5bpc, 4, 5, 0, dst, stride, c, eob, tx2 + %define %%p1 m(i%1_%4_internal_%5bpc) + ; Jump to the 1st txfm function if we're not taking the fast path, which + ; in turn performs an indirect jump to the 2nd txfm function. + lea tx2q, [m(i%2_%4_internal_%5bpc).pass2] +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else +%if %3 + add eobd, %3 +%endif + ; jump to the 1st txfm function unless it's located directly after this + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endmacro + +%macro INV_TXFM_4X4_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 4x4, %3 +%ifidn %1_%2, dct_dct + vpbroadcastd xm2, [dconly_%3bpc] +%if %3 = 10 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 4 +.dconly2: + add r6d, 128 + sar r6d, 8 +.dconly3: + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + movd xm0, r6d + paddsw xm0, xm2 + vpbroadcastw xm0, xm0 +.dconly_loop: + movq xm1, [dstq+strideq*0] + movhps xm1, [dstq+strideq*1] + paddsw xm1, xm0 + psubusw xm1, xm2 + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + WRAP_XMM RET +%else + jmp m(inv_txfm_add_dct_dct_4x4_10bpc).dconly +%endif +%endif +%endmacro + +%macro IDCT4_1D_PACKED 6 ; dst/src[1-2], tmp[1-3], rnd + ITX_MULSUB_2D %1, %2, %3, %4, %5, %6, 2896_1567, 2896_3784, 1 + punpckhqdq m%3, m%2, m%1 ; t3 t2 + punpcklqdq m%2, m%1 ; t0 t1 + paddd m%1, m%2, m%3 ; out0 out1 + psubd m%2, m%3 ; out3 out2 +%endmacro + +%macro IDCT4_1D_PACKED_WORD 6 ; dst/src[1-2], tmp[1-3], rnd + vpbroadcastd m%5, [pw_m3784_1567] + punpckhwd m%3, m%2, m%1 + vpbroadcastd m%4, [pw_1567_3784] + punpcklwd m%2, m%1 + vpbroadcastd m%1, [pw_m2896_2896] + pmaddwd m%5, m%3 + pmaddwd m%3, m%4 + vpbroadcastd m%4, [pw_2896_2896] + pmaddwd m%1, m%2 + pmaddwd m%2, m%4 + REPX {paddd x, m%6}, m%5, m%3, m%1, m%2 + REPX {psrad x, 12 }, m%5, m%3, m%1, m%2 + packssdw m%3, m%5 ; t3 t2 + packssdw m%2, m%1 ; t0 t1 + paddsw m%1, m%2, m%3 ; out0 out1 + psubsw m%2, m%3 ; out3 out2 +%endmacro + +INV_TXFM_4X4_FN dct, dct +INV_TXFM_4X4_FN dct, identity +INV_TXFM_4X4_FN dct, adst +INV_TXFM_4X4_FN dct, flipadst + +cglobal idct_4x4_internal_10bpc, 0, 7, 6, dst, stride, c, eob, tx2 + call .main + vbroadcasti128 m2, [idct4_shuf] + packssdw m0, m1 + pshufb m0, m2 + jmp tx2q +.pass2: + vextracti128 xm1, m0, 1 + WRAP_XMM IDCT4_1D_PACKED_WORD 0, 1, 2, 3, 4, 5 + packssdw xm5, xm5 ; pw_2048 + pmulhrsw xm0, xm5 + pmulhrsw xm1, xm5 + movq xm2, [dstq+strideq*0] + movhps xm2, [dstq+strideq*1] + lea r6, [dstq+strideq*2] + movq xm3, [r6 +strideq*1] + movhps xm3, [r6 +strideq*0] + vpbroadcastd xm5, [pixel_10bpc_max] + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + paddw xm0, xm2 + paddw xm1, xm3 + pmaxsw xm0, xm4 + pmaxsw xm1, xm4 + pminsw xm0, xm5 + pminsw xm1, xm5 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movhps [r6 +strideq*0], xm1 + movq [r6 +strideq*1], xm1 + RET +ALIGN function_align +.main: + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m5, [pd_2048] +.main2: + IDCT4_1D_PACKED 0, 1, 2, 3, 4, 5 + ret + +INV_TXFM_4X4_FN adst, dct +INV_TXFM_4X4_FN adst, adst +INV_TXFM_4X4_FN adst, flipadst +INV_TXFM_4X4_FN adst, identity + +%macro IADST4_1D 0 + vpbroadcastd m5, [pd_1321] + vpbroadcastd m7, [pd_2482] + pmulld m4, m0, m5 ; 1321*in0 + pmulld m6, m3, m7 ; 2482*in3 + paddd m4, m6 ; 1321*in0 + 2482*in3 + pmulld m6, m0, m7 ; 2482*in0 + paddd m0, m3 ; in0 + in3 + paddd m7, m5 ; pd_3803 + pmulld m5, m2 ; 1321*in2 + pmulld m3, m7 ; 3803*in3 + pmulld m7, m2 ; 3803*in2 + psubd m2, m0 ; in2 - in0 - in3 + vpbroadcastd m0, [pd_m3344] + pmulld m1, m0 ; -t3 + pmulld m2, m0 ; out2 (unrounded) + psubd m6, m5 ; 2482*in0 - 1321*in2 + paddd m4, m7 ; t0 + psubd m6, m3 ; t1 + paddd m3, m4, m6 + psubd m4, m1 ; out0 (unrounded) + psubd m6, m1 ; out1 (unrounded) + paddd m3, m1 ; out3 (unrounded) +%endmacro + +cglobal iadst_4x4_internal_10bpc, 0, 7, 6, dst, stride, c, eob, tx2 + call .main + vinserti128 m0, m4, xm6, 1 + vinserti128 m1, m2, xm3, 1 +.pass1_end: + vpbroadcastd m5, [pd_2048] + mova m2, [itx4_shuf] + paddd m0, m5 + paddd m1, m5 + psrad m0, 12 + psrad m1, 12 + packssdw m0, m1 + vpermd m0, m2, m0 + psrld m2, 4 + pshufb m0, m2 +%if WIN64 + movaps xmm6, [rsp+ 8] + movaps xmm7, [rsp+24] +%endif + jmp tx2q +.pass2: + lea r6, [deint_shuf+128] + vextracti128 xm1, m0, 1 + call m(iadst_4x4_internal_8bpc).main +.end: + vpbroadcastd xm4, [pw_2048] + movq xm2, [dstq+strideq*0] + movhps xm2, [dstq+strideq*1] + lea r6, [dstq+strideq*2] + movq xm3, [r6 +strideq*0] + movhps xm3, [r6 +strideq*1] + vpbroadcastd xm5, [pixel_10bpc_max] + pmulhrsw xm0, xm4 + pmulhrsw xm1, xm4 + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + paddw xm0, xm2 + paddw xm1, xm3 + pmaxsw xm0, xm4 + pmaxsw xm1, xm4 + pminsw xm0, xm5 + pminsw xm1, xm5 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [r6 +strideq*0], xm1 + movhps [r6 +strideq*1], xm1 + RET +ALIGN function_align +.main: + mova xm0, [cq+16*0] + mova xm1, [cq+16*1] + mova xm2, [cq+16*2] + mova xm3, [cq+16*3] +%if WIN64 + movaps [rsp+16], xmm6 + movaps [rsp+32], xmm7 +%endif +.main2: + WRAP_XMM IADST4_1D + ret + +INV_TXFM_4X4_FN flipadst, dct +INV_TXFM_4X4_FN flipadst, adst +INV_TXFM_4X4_FN flipadst, flipadst +INV_TXFM_4X4_FN flipadst, identity + +cglobal iflipadst_4x4_internal_10bpc, 0, 7, 6, dst, stride, c, eob, tx2 + call m(iadst_4x4_internal_10bpc).main + vinserti128 m0, m3, xm2, 1 + vinserti128 m1, m6, xm4, 1 + jmp m(iadst_4x4_internal_10bpc).pass1_end +.pass2: + lea r6, [deint_shuf+128] + vextracti128 xm1, m0, 1 + call m(iadst_4x4_internal_8bpc).main + vpbroadcastd xm4, [pw_2048] + movq xm3, [dstq+strideq*1] + movhps xm3, [dstq+strideq*0] + lea r6, [dstq+strideq*2] + movq xm2, [r6 +strideq*1] + movhps xm2, [r6 +strideq*0] + vpbroadcastd xm5, [pixel_10bpc_max] + pmulhrsw xm0, xm4 + pmulhrsw xm1, xm4 + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + paddw xm0, xm2 + paddw xm1, xm3 + pmaxsw xm0, xm4 + pmaxsw xm1, xm4 + pminsw xm0, xm5 + pminsw xm1, xm5 + movhps [dstq+strideq*0], xm1 + movq [dstq+strideq*1], xm1 + movhps [r6 +strideq*0], xm0 + movq [r6 +strideq*1], xm0 + RET + +INV_TXFM_4X4_FN identity, dct +INV_TXFM_4X4_FN identity, adst +INV_TXFM_4X4_FN identity, flipadst +INV_TXFM_4X4_FN identity, identity + +cglobal iidentity_4x4_internal_10bpc, 0, 7, 6, dst, stride, c, eob, tx2 + vpbroadcastd m1, [pd_5793] + pmulld m0, m1, [cq+32*0] + pmulld m1, [cq+32*1] + vpbroadcastd m5, [pd_2048] + mova m3, [itx4_shuf] + paddd m0, m5 + paddd m1, m5 + psrad m0, 12 + psrad m1, 12 + packssdw m0, m1 + vpermd m0, m3, m0 + psrld m3, 4 + pshufb m0, m3 + jmp tx2q +.pass2: + vpbroadcastd m1, [pw_1697x8] + movq xm2, [dstq+strideq*0] + movhps xm2, [dstq+strideq*1] + lea r6, [dstq+strideq*2] + pmulhrsw m1, m0 + paddsw m0, m1 + movq xm3, [r6 +strideq*0] + movhps xm3, [r6 +strideq*1] + vpbroadcastd xm4, [pixel_10bpc_max] + packssdw m5, m5 ; pw_2048 + pmulhrsw m0, m5 + pxor m5, m5 + mova [cq+32*0], m5 + mova [cq+32*1], m5 + vextracti128 xm1, m0, 1 + paddw xm0, xm2 + paddw xm1, xm3 + pmaxsw xm0, xm5 + pmaxsw xm1, xm5 + pminsw xm0, xm4 + pminsw xm1, xm4 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [r6 +strideq*0], xm1 + movhps [r6 +strideq*1], xm1 + RET + +INV_TXFM_4X4_FN dct, dct, 12 +INV_TXFM_4X4_FN dct, identity, 12 +INV_TXFM_4X4_FN dct, adst, 12 +INV_TXFM_4X4_FN dct, flipadst, 12 + +cglobal idct_4x4_internal_12bpc, 0, 7, 8, dst, stride, c, eob, tx2 + call m(idct_4x4_internal_10bpc).main + mova m3, [idct4_12_shuf] + mova m4, [idct4_12_shuf2] + vpermd m2, m4, m1 + vpermd m1, m3, m0 + jmp m(iadst_4x4_internal_12bpc).pass1_end2 +.pass2: + vpbroadcastd m5, [pd_2048] + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 + call m(idct_4x4_internal_10bpc).main2 + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + jmp m(iadst_4x4_internal_12bpc).end + +INV_TXFM_4X4_FN adst, dct, 12 +INV_TXFM_4X4_FN adst, adst, 12 +INV_TXFM_4X4_FN adst, flipadst, 12 +INV_TXFM_4X4_FN adst, identity, 12 + +cglobal iadst_4x4_internal_12bpc, 0, 7, 8, dst, stride, c, eob, tx2 + call m(iadst_4x4_internal_10bpc).main + vinserti128 m1, m4, xm6, 1 + vinserti128 m2, xm3, 1 +.pass1_end: + mova m3, [itx4_shuf] + vpbroadcastd m5, [pd_1024] + psrad m1, 1 + psrad m2, 1 + vpermd m1, m3, m1 + vpermd m2, m3, m2 + paddd m1, m5 + paddd m2, m5 + psrad m1, 11 + psrad m2, 11 +.pass1_end2: + vpbroadcastd m3, [clip_18b_min] + vpbroadcastd m4, [clip_18b_max] + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + pmaxsd m0, m3 + pmaxsd m1, m3 + pminsd m0, m4 + pminsd m1, m4 + jmp tx2q +.pass2: + call .main_pass2 + vinserti128 m0, m4, xm6, 1 + vinserti128 m1, m2, xm3, 1 +.pass2_end: + vpbroadcastd m5, [pd_2048] + paddd m0, m5 + paddd m1, m5 + psrad m0, 12 + psrad m1, 12 +.end: +%if WIN64 + WIN64_RESTORE_XMM_INTERNAL + %assign xmm_regs_used 6 +%endif +.end2: + vpbroadcastd m4, [pw_16384] + movq xm2, [dstq+strideq*0] + movq xm3, [dstq+strideq*1] + lea r6, [dstq+strideq*2] + movhps xm2, [r6 +strideq*0] ; dst0 dst2 + movhps xm3, [r6 +strideq*1] ; dst1 dst3 + vpbroadcastd m5, [pixel_12bpc_max] + vinserti128 m2, xm3, 1 + psrad m0, 3 + psrad m1, 3 + packssdw m0, m1 ; t0 t2 t1 t3 + pmulhrsw m0, m4 + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + paddw m0, m2 ; out0 out2 out1 out3 + pmaxsw m0, m4 + pminsw m0, m5 + vextracti128 xm1, m0, 1 ; out1 out3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [r6 +strideq*0], xm0 + movhps [r6 +strideq*1], xm1 + RET +.main_pass2: + vextracti128 xm3, m1, 1 + mova xm2, xm1 + vextracti128 xm1, m0, 1 + jmp m(iadst_4x4_internal_10bpc).main2 + +INV_TXFM_4X4_FN flipadst, dct, 12 +INV_TXFM_4X4_FN flipadst, adst, 12 +INV_TXFM_4X4_FN flipadst, flipadst, 12 +INV_TXFM_4X4_FN flipadst, identity, 12 + +cglobal iflipadst_4x4_internal_12bpc, 0, 7, 8, dst, stride, c, eob, tx2 + call m(iadst_4x4_internal_10bpc).main + vinserti128 m1, m3, xm2, 1 + vinserti128 m2, m6, xm4, 1 + jmp m(iadst_4x4_internal_12bpc).pass1_end +.pass2: + call m(iadst_4x4_internal_12bpc).main_pass2 + vinserti128 m0, m3, xm2, 1 + vinserti128 m1, m6, xm4, 1 + jmp m(iadst_4x4_internal_12bpc).pass2_end + +INV_TXFM_4X4_FN identity, dct, 12 +INV_TXFM_4X4_FN identity, adst, 12 +INV_TXFM_4X4_FN identity, flipadst, 12 +INV_TXFM_4X4_FN identity, identity, 12 + +cglobal iidentity_4x4_internal_12bpc, 0, 7, 8, dst, stride, c, eob, tx2 + mova m2, [itx4_shuf] + vpbroadcastd m3, [pd_1697] + vpermd m0, m2, [cq+32*0] + vpermd m2, m2, [cq+32*1] + vpbroadcastd m5, [pd_2048] + pmulld m1, m3, m0 + pmulld m3, m2 + paddd m1, m5 + paddd m3, m5 + psrad m1, 12 + psrad m3, 12 + paddd m1, m0 + paddd m2, m3 + jmp m(iadst_4x4_internal_12bpc).pass1_end2 +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 + vpbroadcastd m3, [pd_5793] + vpbroadcastd m5, [pd_2048] + pmulld m0, m3 + pmulld m1, m3 + paddd m0, m5 ; 2048 + paddd m1, m5 + psrad m0, 12 + psrad m1, 12 + jmp m(iadst_4x4_internal_12bpc).end + +%macro INV_TXFM_4X8_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 4x8, %3 +%ifidn %1_%2, dct_dct + vpbroadcastd xm2, [dconly_%3bpc] +%if %3 = 10 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 8 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + jmp m(inv_txfm_add_dct_dct_4x4_10bpc).dconly2 +%else + jmp m(inv_txfm_add_dct_dct_4x8_10bpc).dconly +%endif +%endif +%endmacro + +%macro IDCT4_1D 8 ; src[1-4], tmp[1-3], rnd + ITX_MULSUB_2D %2, %4, %5, %6, %7, %8, 1567, 3784 ; t2, t3 + vpbroadcastd m%5, [pd_2896] + pmulld m%1, m%5 + pmulld m%3, m%5 + paddd m%1, m%8 + paddd m%5, m%1, m%3 + psubd m%1, m%3 + psrad m%5, 12 ; t0 + psrad m%1, 12 ; t1 + psubd m%3, m%1, m%2 + paddd m%2, m%1 + paddd m%1, m%5, m%4 + psubd m%4, m%5, m%4 +%endmacro + +INV_TXFM_4X8_FN dct, dct +INV_TXFM_4X8_FN dct, identity +INV_TXFM_4X8_FN dct, adst +INV_TXFM_4X8_FN dct, flipadst + +cglobal idct_4x8_internal_10bpc, 0, 7, 8, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m3, [pd_2896] + pmulld m0, m3, [cq+32*0] + pmulld m1, m3, [cq+32*1] + pmulld m2, m3, [cq+32*2] + pmulld m3, m3, [cq+32*3] + vpbroadcastd m7, [pd_2048] + REPX {paddd x, m7}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + IDCT4_1D 0, 1, 2, 3, 4, 5, 6, 7 + jmp tx2q +.pass2: + packssdw m0, m2 + packssdw m1, m3 + lea r6, [deint_shuf+128] + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhdq m1, m0, m2 ; 2 3 + punpckldq m0, m2 ; 0 1 + vextracti128 xm2, m0, 1 ; 4 5 + vextracti128 xm3, m1, 1 ; 6 7 + call m(idct_4x8_internal_8bpc).main + vpbroadcastd xm4, [pw_2048] + REPX {pmulhrsw x, xm4}, xm0, xm1, xm2, xm3 + lea r3, [strideq*3] + lea r6, [dstq+strideq*4] + movq xm4, [dstq+strideq*0] + movhps xm4, [dstq+strideq*1] + movq xm5, [dstq+r3 ] + movhps xm5, [dstq+strideq*2] + movq xm6, [r6 +strideq*0] + movhps xm6, [r6 +strideq*1] + movq xm7, [r6 +r3 ] + movhps xm7, [r6 +strideq*2] + paddw xm0, xm4 ; 0 1 + paddw xm1, xm5 ; 3 2 + paddw xm2, xm6 ; 4 5 + paddw xm3, xm7 ; 7 6 + vpbroadcastd xm5, [pixel_10bpc_max] + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + REPX {pmaxsw x, xm4}, xm0, xm1, xm2, xm3 + REPX {pminsw x, xm5}, xm0, xm1, xm2, xm3 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movhps [dstq+strideq*2], xm1 + movq [dstq+r3 ], xm1 + movq [r6 +strideq*0], xm2 + movhps [r6 +strideq*1], xm2 + movhps [r6 +strideq*2], xm3 + movq [r6 +r3 ], xm3 + RET + +INV_TXFM_4X8_FN adst, dct +INV_TXFM_4X8_FN adst, adst +INV_TXFM_4X8_FN adst, flipadst +INV_TXFM_4X8_FN adst, identity + +cglobal iadst_4x8_internal_10bpc, 0, 7, 8, dst, stride, c, eob, tx2 + call m(iadst_8x4_internal_10bpc).main + vpbroadcastd m5, [pd_2048] + paddd m0, m5, m4 + paddd m1, m5, m6 + paddd m2, m5 + paddd m3, m5 +.pass1_end: + REPX {psrad x, 12}, m0, m1, m2, m3 + jmp tx2q +.pass2: + call .pass2_main + mova xm4, [pw_2048_m2048] + REPX {pmulhrsw x, xm4}, xm0, xm1, xm2, xm3 +.end: + lea r3, [strideq*3] + lea r6, [dstq+strideq*4] + movq xm4, [dstq+strideq*0] + movhps xm4, [dstq+strideq*1] + movq xm5, [dstq+strideq*2] + movhps xm5, [dstq+r3 ] + movq xm6, [r6 +strideq*0] + movhps xm6, [r6 +strideq*1] + movq xm7, [r6 +strideq*2] + movhps xm7, [r6 +r3 ] + paddw xm0, xm4 ; 0 1 + paddw xm1, xm5 ; 2 3 + paddw xm2, xm6 ; 4 5 + paddw xm3, xm7 ; 6 7 + vpbroadcastd xm5, [pixel_10bpc_max] + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + REPX {pmaxsw x, xm4}, xm0, xm1, xm2, xm3 + REPX {pminsw x, xm5}, xm0, xm1, xm2, xm3 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + movq [r6 +strideq*0], xm2 + movhps [r6 +strideq*1], xm2 + movq [r6 +strideq*2], xm3 + movhps [r6 +r3 ], xm3 + RET +ALIGN function_align +.pass2_main: + packssdw m0, m2 + packssdw m1, m3 + lea r6, [deint_shuf+128] + punpcklwd m4, m0, m1 + punpckhwd m0, m1 + punpckhdq m5, m4, m0 + punpckldq m4, m0 + vextracti128 xm2, m4, 1 ; 4 5 + vextracti128 xm3, m5, 1 ; 6 7 + pshufd xm4, xm4, q1032 ; 1 0 + pshufd xm5, xm5, q1032 ; 3 2 + jmp m(iadst_4x8_internal_8bpc).main_pass2 +ALIGN function_align +.main: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] +.main2: + vbroadcasti128 m0, [cq+16*0] + vbroadcasti128 m2, [cq+16*2] + vbroadcasti128 m3, [cq+16*5] + vbroadcasti128 m1, [cq+16*7] + vpbroadcastd m6, [pd_2896] + shufpd m0, m2, 0x0c ; 0 2 + shufpd m1, m3, 0x0c ; 7 5 + vbroadcasti128 m2, [cq+16*4] + vbroadcasti128 m4, [cq+16*6] + vbroadcasti128 m5, [cq+16*1] + vbroadcasti128 m3, [cq+16*3] + vpbroadcastd m7, [pd_2048] + shufpd m2, m4, 0x0c ; 4 6 + shufpd m3, m5, 0x0c ; 3 1 + REPX {pmulld x, m6}, m0, m1, m2, m3 + REPX {paddd x, m7}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 +.main3: + ITX_MULSUB_2D 1, 0, 4, 5, 6, 7, 401_1931, 4076_3612, 1 + ITX_MULSUB_2D 3, 2, 4, 5, 6, 7, 3166_3920, 2598_1189, 1 + psubd m4, m0, m2 ; t4 t6 + paddd m0, m2 ; t0 t2 + psubd m2, m1, m3 ; t5 t7 + paddd m1, m3 ; t1 t3 + REPX {pmaxsd x, m8}, m4, m2, m0, m1 + REPX {pminsd x, m9}, m4, m2, m0, m1 + pxor m5, m5 + psubd m5, m4 + vpblendd m4, m2, 0xcc ; t4 t7 + vpblendd m2, m5, 0xcc ; t5 -t6 + ITX_MULSUB_2D 4, 2, 3, 5, 6, 7, 1567, 3784 + vpbroadcastd m5, [pd_2896] + vbroadcasti128 m6, [pw_2048_m2048] ; + + - - + punpckhqdq m3, m0, m1 + punpcklqdq m0, m1 + psubd m1, m0, m3 ; t2 t3 + paddd m0, m3 ; out0 -out7 + punpckhqdq m3, m4, m2 ; t7a t6a + punpcklqdq m4, m2 ; t5a t4a + psubd m2, m4, m3 ; t7 t6 + paddd m4, m3 ; out6 -out1 + REPX {pmaxsd x, m8}, m1, m2 + REPX {pminsd x, m9}, m1, m2 + vpblendd m3, m1, m2, 0xcc + shufpd m1, m2, 0x05 + pmulld m3, m5 + pmulld m5, m1 + psignd m0, m6 ; out0 out7 + psignd m4, m6 ; out6 out1 + paddd m3, m7 + psubd m2, m3, m5 + paddd m5, m3 + psrad m2, 12 ; out4 -out5 + psrad m5, 12 ; -out3 out2 + ret + +INV_TXFM_4X8_FN flipadst, dct +INV_TXFM_4X8_FN flipadst, adst +INV_TXFM_4X8_FN flipadst, flipadst +INV_TXFM_4X8_FN flipadst, identity + +cglobal iflipadst_4x8_internal_10bpc, 0, 7, 8, dst, stride, c, eob, tx2 + call m(iadst_8x4_internal_10bpc).main + vpbroadcastd m5, [pd_2048] + paddd m0, m5, m3 + paddd m1, m5, m2 + paddd m2, m5, m6 + paddd m3, m5, m4 + jmp m(iadst_4x8_internal_10bpc).pass1_end +.pass2: + call m(iadst_4x8_internal_10bpc).pass2_main + mova xm4, [pw_2048_m2048] + REPX {pmulhrsw x, xm4}, xm3, xm2, xm1, xm0 + lea r3, [strideq*3] + lea r6, [dstq+strideq*4] + movq xm4, [dstq+strideq*1] + movhps xm4, [dstq+strideq*0] + movq xm5, [dstq+r3 ] + movhps xm5, [dstq+strideq*2] + movq xm6, [r6 +strideq*1] + movhps xm6, [r6 +strideq*0] + movq xm7, [r6 +r3 ] + movhps xm7, [r6 +strideq*2] + paddw xm3, xm4 ; 1 0 + paddw xm2, xm5 ; 3 2 + paddw xm1, xm6 ; 5 4 + paddw xm0, xm7 ; 7 6 + vpbroadcastd xm5, [pixel_10bpc_max] + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + REPX {pmaxsw x, xm4}, xm3, xm2, xm1, xm0 + REPX {pminsw x, xm5}, xm3, xm2, xm1, xm0 + movhps [dstq+strideq*0], xm3 + movq [dstq+strideq*1], xm3 + movhps [dstq+strideq*2], xm2 + movq [dstq+r3 ], xm2 + movhps [r6 +strideq*0], xm1 + movq [r6 +strideq*1], xm1 + movhps [r6 +strideq*2], xm0 + movq [r6 +r3 ], xm0 + RET + +INV_TXFM_4X8_FN identity, dct +INV_TXFM_4X8_FN identity, adst +INV_TXFM_4X8_FN identity, flipadst +INV_TXFM_4X8_FN identity, identity + +cglobal iidentity_4x8_internal_10bpc, 0, 7, 8, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m3, [pd_2896] + pmulld m0, m3, [cq+32*0] + pmulld m1, m3, [cq+32*1] + pmulld m2, m3, [cq+32*2] + pmulld m3, [cq+32*3] + vpbroadcastd m5, [pd_2048] + vpbroadcastd m4, [pd_5793] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + REPX {pmulld x, m4}, m0, m1, m2, m3 + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + jmp tx2q +.pass2: + vpbroadcastd m6, [pixel_10bpc_max] + call .pass2_end + RET +ALIGN function_align +.pass2_end: + vpbroadcastd m4, [pw_4096] + packssdw m0, m2 + packssdw m1, m3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmulhrsw m2, m4 + pmulhrsw m0, m4 + punpckhdq m1, m0, m2 ; 2 3 6 7 + punpckldq m0, m2 ; 0 1 4 5 + lea r3, [strideq*3] + lea r6, [dstq+strideq*4] + movq xm2, [dstq+strideq*0] + movhps xm2, [dstq+strideq*1] + vpbroadcastq m4, [r6 +strideq*0] + vpbroadcastq m5, [r6 +strideq*1] + movq xm3, [dstq+strideq*2] + movhps xm3, [dstq+r3 ] + vpblendd m2, m4, 0x30 + vpblendd m2, m5, 0xc0 + vpbroadcastq m4, [r6 +strideq*2] + vpbroadcastq m5, [r6 +r3 ] + vpblendd m3, m4, 0x30 + vpblendd m3, m5, 0xc0 + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + paddw m0, m2 ; out0 out1 out4 out5 + paddw m1, m3 ; out2 out3 out6 out7 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m6 + pminsw m1, m6 + vextracti128 xm2, m0, 1 ; out4 out5 + vextracti128 xm3, m1, 1 ; out6 out7 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + movq [r6 +strideq*0], xm2 + movhps [r6 +strideq*1], xm2 + movq [r6 +strideq*2], xm3 + movhps [r6 +r3 ], xm3 + ret + +INV_TXFM_4X8_FN dct, dct, 12 +INV_TXFM_4X8_FN dct, identity, 12 +INV_TXFM_4X8_FN dct, adst, 12 +INV_TXFM_4X8_FN dct, flipadst, 12 + +cglobal idct_4x8_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + jmp m(idct_4x8_internal_10bpc).pass1 +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + ; transpose & interleave + pshufd m0, m0, q1320 + pshufd m1, m1, q1320 + pshufd m2, m2, q1320 + pshufd m3, m3, q1320 + punpckldq m4, m0, m1 + punpckhdq m0, m1 + punpckldq m5, m2, m3 + punpckhdq m2, m3 + vpermq m0, m0, q3102 + vpermq m2, m2, q3102 + vperm2i128 m1, m0, m2, 0x31 ; 1 5 (interleaved) + vperm2i128 m3, m0, m2, 0x20 ; 7 3 (interleaved) + vperm2i128 m0, m4, m5, 0x20 ; 0 2 (interleaved) + vperm2i128 m2, m4, m5, 0x31 ; 4 6 (interleaved) + vpbroadcastd m7, [pd_2048] + call m(idct_8x4_internal_10bpc).main + psubd m3, m0, m4 ; out7 out6 + paddd m0, m4 ; out0 out1 + paddd m1, m2, m5 ; out3 out2 + psubd m2, m5 ; out4 out5 + pshufd m1, m1, q1032 + pshufd m3, m3, q1032 + jmp m(iadst_4x8_internal_12bpc).end + +INV_TXFM_4X8_FN adst, dct, 12 +INV_TXFM_4X8_FN adst, adst, 12 +INV_TXFM_4X8_FN adst, flipadst, 12 +INV_TXFM_4X8_FN adst, identity, 12 + +cglobal iadst_4x8_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + call m(iadst_8x4_internal_10bpc).main + psrad m0, m4, 1 + psrad m1, m6, 1 + psrad m2, 1 + psrad m3, 1 +.pass1_end: + vpbroadcastd m5, [pd_1024] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 11}, m0, m1, m2, m3 + jmp tx2q +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + call .pass2_main + vpblendd m3, m0, m4, 0x33 ; out6 out7 + vpblendd m0, m4, 0xcc ; out0 out1 + pshufd m1, m5, q1032 + psignd m2, m6 ; out4 out5 + psignd m1, m6 ; out2 out3 +.end: + vpbroadcastd m4, [pw_16384] + REPX {psrad x, 3}, m0, m1, m2, m3 + packssdw m0, m2 ; 0 1 4 5 (interleaved) + packssdw m1, m3 ; 2 3 6 7 (interleaved) + mova m2, [iadst8_12_shuf] + vpermd m0, m2, m0 ; 0 1 4 5 + vpermd m1, m2, m1 ; 2 3 6 7 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + lea r3, [strideq*3] + lea r6, [dstq+strideq*4] + movq xm4, [dstq+strideq*0] + movhps xm4, [dstq+strideq*1] + movq xm5, [dstq+strideq*2] + movhps xm5, [dstq+r3 ] + movq xm6, [r6 +strideq*0] + movhps xm6, [r6 +strideq*1] + vinserti128 m4, xm6, 1 + movq xm7, [r6 +strideq*2] + movhps xm7, [r6 +r3 ] + vinserti128 m5, xm7, 1 + paddw m0, m4 ; 0 1 4 5 + paddw m1, m5 ; 2 3 6 7 + vpbroadcastd m5, [pixel_12bpc_max] + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + REPX {pmaxsw x, m4}, m0, m1 + REPX {pminsw x, m5}, m0, m1 + vextracti128 xm2, m0, 1 ; out4 out5 + vextracti128 xm3, m1, 1 ; out6 out7 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + movq [dstq+strideq*2], xm1 + movhps [dstq+r3 ], xm1 + movq [r6 +strideq*0], xm2 + movhps [r6 +strideq*1], xm2 + movq [r6 +strideq*2], xm3 + movhps [r6 +r3 ], xm3 + RET +ALIGN function_align +.pass2_main: + ; transpose & interleave + pshufd m0, m0, q1320 + pshufd m1, m1, q1320 + pshufd m2, m2, q1320 + pshufd m3, m3, q1320 + punpckldq m4, m0, m1 + punpckhdq m0, m1 + punpckldq m5, m2, m3 + punpckhdq m2, m3 + vperm2i128 m1, m0, m2, 0x31 ; 7 5 (interleaved) + vperm2i128 m3, m0, m2, 0x20 ; 3 1 (interleaved) + vperm2i128 m0, m4, m5, 0x20 ; 0 2 (interleaved) + vperm2i128 m2, m4, m5, 0x31 ; 4 6 (interleaved) + vpbroadcastd m7, [pd_2048] + jmp m(iadst_4x8_internal_10bpc).main3 + +INV_TXFM_4X8_FN flipadst, dct, 12 +INV_TXFM_4X8_FN flipadst, adst, 12 +INV_TXFM_4X8_FN flipadst, flipadst, 12 +INV_TXFM_4X8_FN flipadst, identity, 12 + +cglobal iflipadst_4x8_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + call m(iadst_8x4_internal_10bpc).main + psrad m0, m3, 1 + psrad m1, m2, 1 + psrad m2, m6, 1 + psrad m3, m4, 1 + jmp m(iadst_4x8_internal_12bpc).pass1_end +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + call m(iadst_4x8_internal_12bpc).pass2_main + shufpd m3, m4, m0, 0x05 ; out1 out0 + shufpd m0, m4, 0x05 ; out7 out6 + psignd m2, m6 + pshufd m6, m6, q1032 + pshufd m1, m2, q1032 ; out5 out4 + psignd m2, m5, m6 ; out3 out2 + jmp m(iadst_4x8_internal_12bpc).end + +INV_TXFM_4X8_FN identity, dct, 12 +INV_TXFM_4X8_FN identity, adst, 12 +INV_TXFM_4X8_FN identity, flipadst, 12 +INV_TXFM_4X8_FN identity, identity, 12 + +cglobal iidentity_4x8_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + jmp m(iidentity_4x8_internal_10bpc).pass1 +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 + ; m2 = in4 in5 + ; m3 = in6 in7 + vpbroadcastd m6, [pixel_12bpc_max] + call m(iidentity_4x8_internal_10bpc).pass2_end + RET + +%macro INV_TXFM_4X16_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 4x16, %3 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + vpbroadcastd xm2, [dconly_%3bpc] + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 384 + sar r6d, 9 + jmp m(inv_txfm_add_dct_dct_4x4_10bpc).dconly3 +%endif +%endmacro + +INV_TXFM_4X16_FN dct, dct +INV_TXFM_4X16_FN dct, identity +INV_TXFM_4X16_FN dct, adst +INV_TXFM_4X16_FN dct, flipadst + +cglobal idct_4x16_internal_10bpc, 0, 7, 11, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m10, [pd_3072] + mova m1, [cq+32*2] + mova m3, [cq+32*6] + mova m5, [cq+32*3] + mova m7, [cq+32*7] + call .pass1_main + pmulld m0, m6, [cq+32*0] + pmulld m2, m6, [cq+32*4] + pmulld m4, m6, [cq+32*1] + pmulld m6, [cq+32*5] + call .pass1_main2 + REPX {psrad x, 1}, m0, m1, m2, m3, m4, m5, m6, m7 + jmp tx2q +.pass2: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + lea r6, [deint_shuf+128] + punpcklwd m4, m2, m3 + punpckhwd m2, m3 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhdq m1, m0, m4 ; 2 3 + punpckldq m0, m4 ; 0 1 + punpckldq m4, m5, m2 ; 8 9 + punpckhdq m5, m2 ; a b + vextracti128 xm2, m0, 1 ; 4 5 + vextracti128 xm3, m1, 1 ; 6 7 + vextracti128 xm6, m4, 1 ; c d + vextracti128 xm7, m5, 1 ; e f + call m(idct_4x16_internal_8bpc).main + vpbroadcastd m9, [pw_2048] + vinserti128 m0, m0, xm1, 1 ; 0 1 3 2 + vinserti128 m1, m2, xm3, 1 ; 4 5 7 6 + vinserti128 m2, m4, xm5, 1 ; 8 9 b a + vinserti128 m3, m6, xm7, 1 ; c d f e + vpbroadcastd m8, [pixel_10bpc_max] + call .pass2_end + RET +ALIGN function_align +.pass1_main: + vpbroadcastd m4, [pd_3784] + vpbroadcastd m8, [pd_1567] + vpbroadcastd m9, [pd_2048] + vpbroadcastd m6, [pd_1448] + ITX_MULSUB_2D 1, 3, 0, 2, _, 9, 8, 4 ; t2l, t3l + ITX_MULSUB_2D 5, 7, 4, 2, _, 9, 8, 4 ; t2h, t3h + ret +ALIGN function_align +.pass1_main2: + paddd m0, m10 + paddd m4, m10 + paddd m8, m0, m2 + psubd m0, m2 + paddd m9, m4, m6 + psubd m4, m6 + REPX {psrad x, 11}, m8, m0, m9, m4 ; t0l, t1l, t0h, t1h + psubd m2, m0, m1 + paddd m1, m0 + psubd m6, m4, m5 + paddd m5, m4 + paddd m0, m8, m3 + psubd m3, m8, m3 + paddd m4, m9, m7 + psubd m7, m9, m7 + ret +ALIGN function_align +.pass2_end: + lea r6, [strideq*3] + pxor m7, m7 + pmulhrsw m0, m9 + call .write_4x4 + pmulhrsw m0, m1, m9 + call .write_4x4 + pmulhrsw m0, m2, m9 + call .write_4x4 + pmulhrsw m0, m3, m9 + call .write_4x4 + ret +ALIGN function_align +.write_4x4: + movq xm4, [dstq+strideq*0] + movhps xm4, [dstq+strideq*1] + vpbroadcastq m5, [dstq+strideq*2] + vpbroadcastq m6, [dstq+r6 ] + mova [cq+32*0], m7 + mova [cq+32*1], m7 + add cq, 32*2 + vpblendd m4, m5, 0xc0 + vpblendd m4, m6, 0x30 + paddw m4, m0 + pmaxsw m4, m7 + pminsw m4, m8 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movhps [dstq+strideq*1], xm4 + movhps [dstq+strideq*2], xm5 + movq [dstq+r6 ], xm5 + lea dstq, [dstq+strideq*4] + ret + +INV_TXFM_4X16_FN adst, dct +INV_TXFM_4X16_FN adst, adst +INV_TXFM_4X16_FN adst, flipadst +INV_TXFM_4X16_FN adst, identity + +cglobal iadst_4x16_internal_10bpc, 0, 7, 11, dst, stride, c, eob, tx2 + call m(iadst_16x4_internal_10bpc).main + vpbroadcastd m6, [pd_6144] + call m(iadst_16x4_internal_10bpc).main_end + psrad m0, m4, 13 + psrad m1, m5, 13 + psrad m2, 13 + psrad m3, 13 + psrad m4, m8, 13 + psrad m5, m9, 13 + psrad m6, 13 + psrad m7, 13 + jmp tx2q +.pass2: + call .pass2_main + vpbroadcastd m5, [pw_2048] + vpbroadcastd m8, [pixel_10bpc_max] + lea r6, [strideq*3] + vpblendd m4, m3, m0, 0xcc ; -out3 out0 out2 -out1 + pshufd m2, m2, q1032 ; -out11 out8 out10 -out9 + vpblendd m3, m0, 0x33 ; -out15 out12 out14 -out13 + pxor m7, m7 + psubw m9, m7, m5 + vpblendd m9, m5, 0x3c ; -2048 2048 2048 -2048 + pmulhrsw m0, m4, m9 + call .write_4x4 + pmulhrsw m0, m1, m9 + call .write_4x4 + pmulhrsw m0, m2, m9 + call .write_4x4 + pmulhrsw m0, m3, m9 + call .write_4x4 + RET +ALIGN function_align +.write_4x4: + movq xm4, [dstq+r6 ] + movhps xm4, [dstq+strideq*0] + vpbroadcastq m5, [dstq+strideq*1] + vpbroadcastq m6, [dstq+strideq*2] + mova [cq+32*0], m7 + mova [cq+32*1], m7 + add cq, 32*2 + vpblendd m4, m5, 0xc0 + vpblendd m4, m6, 0x30 + paddw m4, m0 + pmaxsw m4, m7 + pminsw m4, m8 + vextracti128 xm5, m4, 1 + movhps [dstq+strideq*0], xm4 + movhps [dstq+strideq*1], xm5 + movq [dstq+strideq*2], xm5 + movq [dstq+r6 ], xm4 + lea dstq, [dstq+strideq*4] + ret +ALIGN function_align +.pass2_main: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + lea r6, [deint_shuf+128] + punpcklwd m4, m2, m3 + punpckhwd m2, m3 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhdq m1, m0, m4 + punpckldq m0, m4 + punpckldq m4, m5, m2 + punpckhdq m5, m2 + vpblendd m3, m0, m1, 0x33 + vpblendd m0, m1, 0xcc + shufpd m2, m5, m4, 0x05 + shufpd m4, m5, 0x05 + vperm2i128 m1, m0, m3, 0x31 ; 4 7 6 5 + vinserti128 m0, xm3, 1 ; 0 3 2 1 + vperm2i128 m3, m2, m4, 0x31 ; c f e d ; ???? + vinserti128 m2, xm4, 1 ; b 8 9 a + call m(iadst_4x16_internal_8bpc).main2 + vpbroadcastd m5, [pw_2896x8] + paddsw m1, m2, m4 + psubsw m2, m4 + pmulhrsw m1, m5 ; -out7 out4 out6 -out5 + pmulhrsw m2, m5 ; out8 -out11 -out9 out10 + ret +ALIGN function_align +.main: + vbroadcasti128 m0, [cq+16* 0] + vbroadcasti128 m4, [cq+16* 2] + vbroadcasti128 m1, [cq+16*15] + vbroadcasti128 m5, [cq+16*13] + vbroadcasti128 m2, [cq+16* 4] + vbroadcasti128 m6, [cq+16* 6] + vbroadcasti128 m3, [cq+16*11] + vbroadcasti128 m7, [cq+16* 9] + shufpd m0, m4, 0x0c ; 0 2 + shufpd m1, m5, 0x0c ; 15 13 + shufpd m2, m6, 0x0c ; 4 6 + shufpd m3, m7, 0x0c ; 11 9 + vbroadcasti128 m4, [cq+16* 8] + vbroadcasti128 m6, [cq+16*10] + vbroadcasti128 m5, [cq+16* 7] + vbroadcasti128 m7, [cq+16* 5] + shufpd m4, m6, 0x0c ; 8 10 + shufpd m5, m7, 0x0c ; 7 5 + vbroadcasti128 m6, [cq+16*12] + vbroadcasti128 m7, [cq+16*14] + shufpd m6, m7, 0x0c ; 12 14 + vbroadcasti128 m7, [cq+16* 3] + vbroadcasti128 m8, [cq+16* 1] + shufpd m7, m8, 0x0c ; 3 1 +.main2: + ; expects: m12 = clip_min m13 = clip_max + vpbroadcastd m11, [pd_2048] + ITX_MULSUB_2D 1, 0, 8, 9, 10, 11, 201_995, 4091_3973, 1 + ITX_MULSUB_2D 3, 2, 8, 9, 10, 11, 1751_2440, 3703_3290, 1 + ITX_MULSUB_2D 5, 4, 8, 9, 10, 11, 3035_3513, 2751_2106, 1 + ITX_MULSUB_2D 7, 6, 8, 9, 10, 11, 3857_4052, 1380_601, 1 + psubd m8, m0, m4 ; t8a t10a + paddd m0, m4 ; t0a t2a + psubd m4, m1, m5 ; t9a t11a + paddd m1, m5 ; t1a t3a + psubd m5, m2, m6 ; t12a t14a + paddd m2, m6 ; t4a t6a + psubd m6, m3, m7 ; t13a t15a + paddd m3, m7 ; t5a t7a + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m8 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m8 + ITX_MULSUB_2D 8, 4, 7, 9, 10, 11, 799_3406, 4017_2276, 1 + ITX_MULSUB_2D 6, 5, 7, 9, 10, 11, 4017_2276, 10, 1 + psubd m7, m0, m2 ; t4 t6 + paddd m0, m2 ; t0 t2 + psubd m2, m1, m3 ; t5 t7 + paddd m1, m3 ; t1 t3 + psubd m3, m4, m6 ; t12a t14a + paddd m4, m6 ; t8a t10a + psubd m6, m8, m5 ; t13a t15a + paddd m8, m5 ; t9a t11a + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m6, m7, m8 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m6, m7, m8 + punpcklqdq m5, m3, m7 ; t12a t4 + punpckhqdq m3, m7 ; t14a t6 + punpckhqdq m7, m6, m2 ; t15a t7 + punpcklqdq m6, m2 ; t13a t5 + ITX_MULSUB_2D 7, 3, 2, 9, 10, 11, 3784, 1567 + ITX_MULSUB_2D 5, 6, 2, 9, 10, 11, 1567, 10 + vpbroadcastd m10, [pd_2896] + vbroadcasti128 m9, [pw_2048_m2048] ; + + - - + punpckhqdq m2, m4, m0 ; t10a t2 + punpcklqdq m4, m0 ; t8a t0 + punpckhqdq m0, m8, m1 ; t11a t3 + punpcklqdq m8, m1 ; t9a t1 + paddd m1, m6, m7 ; out2 -out3 + psubd m6, m7 ; t14a t6 + paddd m7, m5, m3 ; -out13 out12 + psubd m5, m3 ; t15a t7 + psubd m3, m8, m0 ; t11 t3a + paddd m8, m0 ; out14 -out15 + paddd m0, m4, m2 ; -out1 out0 + psubd m4, m2 ; t10 t2a + REPX {pmaxsd x, m12}, m6, m5, m3, m4 + REPX {pminsd x, m13}, m6, m5, m3, m4 + REPX {pmulld x, m10}, m6, m5, m3, m4 + paddd m6, m11 + paddd m4, m11 + paddd m2, m6, m5 ; -out5 out4 + psubd m6, m5 ; out10 -out11 + psubd m5, m4, m3 ; -out9 out8 + paddd m3, m4 ; out6 -out7 + REPX {psrad x, 12}, m2, m3, m5, m6 + REPX {psignd x, m9}, m1, m8, m3, m6 + pshufd m9, m9, q1032 + REPX {psignd x, m9}, m0, m7, m2, m5 + ret + +INV_TXFM_4X16_FN flipadst, dct +INV_TXFM_4X16_FN flipadst, adst +INV_TXFM_4X16_FN flipadst, flipadst +INV_TXFM_4X16_FN flipadst, identity + +cglobal iflipadst_4x16_internal_10bpc, 0, 7, 11, dst, stride, c, eob, tx2 +.pass1: + call m(iadst_16x4_internal_10bpc).main + vpbroadcastd m6, [pd_6144] + call m(iadst_16x4_internal_10bpc).main_end + psrad m0, m3, 13 + psrad m1, m2, 13 + psrad m2, m5, 13 + psrad m3, m4, 13 + psrad m4, m7, 13 + psrad m5, m6, 13 + psrad m6, m9, 13 + psrad m7, m8, 13 + jmp tx2q +.pass2: + call m(iadst_4x16_internal_10bpc).pass2_main + vpbroadcastd m5, [pw_2048] + vpbroadcastd m8, [pixel_10bpc_max] + lea r6, [strideq*3] + vpblendd m4, m3, m0, 0x33 ; -out0 out3 out1 -out2 + pshufd m2, m2, q1032 ; -out11 out8 out10 -out9 + vpblendd m3, m0, 0xcc ; -out12 out15 out13 -out14 + pxor m7, m7 + psubw m9, m7, m5 + vpblendd m9, m5, 0x3c ; -2048 2048 2048 -2048 + pmulhrsw m0, m4, m9 + call .write_4x4 + pmulhrsw m0, m2, m9 + call .write_4x4 + pmulhrsw m0, m1, m9 + call .write_4x4 + pmulhrsw m0, m3, m9 + call .write_4x4 + RET +ALIGN function_align +.write_4x4: + movq xm4, [dstq+strideq*0] + movhps xm4, [dstq+r6 ] + vpbroadcastq m5, [dstq+strideq*1] + vpbroadcastq m6, [dstq+strideq*2] + mova [cq+32*0], m7 + mova [cq+32*1], m7 + add cq, 32*2 + vpblendd m4, m5, 0x30 + vpblendd m4, m6, 0xc0 + paddw m4, m0 + pmaxsw m4, m7 + pminsw m4, m8 + vextracti128 xm5, m4, 1 + movq [dstq+strideq*0], xm4 + movq [dstq+strideq*1], xm5 + movhps [dstq+strideq*2], xm5 + movhps [dstq+r6 ], xm4 + lea dstq, [dstq+strideq*4] + ret + +INV_TXFM_4X16_FN identity, dct +INV_TXFM_4X16_FN identity, adst +INV_TXFM_4X16_FN identity, flipadst +INV_TXFM_4X16_FN identity, identity + +cglobal iidentity_4x16_internal_10bpc, 0, 7, 11, dst, stride, c, eob, tx2 + vpbroadcastd m7, [pd_5793] + pmulld m0, m7, [cq+32*0] + pmulld m4, m7, [cq+32*1] + pmulld m1, m7, [cq+32*2] + pmulld m5, m7, [cq+32*3] + pmulld m2, m7, [cq+32*4] + pmulld m6, m7, [cq+32*5] + pmulld m3, m7, [cq+32*6] + pmulld m7, [cq+32*7] + vpbroadcastd m8, [pd_6144] + REPX {paddd x, m8}, m0, m4, m1, m5, m2, m6, m3, m7 + REPX {psrad x, 13}, m0, m4, m1, m5, m2, m6, m3, m7 + jmp tx2q +.pass2: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + vpbroadcastd m7, [pw_1697x16] + vpbroadcastd m8, [pw_2048] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + REPX {paddsw x, x}, m0, m1, m2, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + vpbroadcastd m4, [pixel_10bpc_max] + call .pass2_end + RET +ALIGN function_align +.pass2_end: + punpckhwd m7, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + lea r6, [strideq*5] + pxor m3, m3 + punpckhdq m5, m0, m2 ; 2 3 6 7 + punpckldq m0, m2 ; 0 1 4 5 + punpckldq m6, m7, m1 ; 8 9 c d + punpckhdq m7, m1 ; a b e f + pmulhrsw m0, m8 + call .write_2x4x2 + pmulhrsw m0, m5, m8 + call .write_2x4x2 + pmulhrsw m0, m6, m8 + lea dstq, [dstq+strideq*4] + call .write_2x4x2 + pmulhrsw m0, m7, m8 + call .write_2x4x2 + ret +ALIGN function_align +.write_2x4x2: + movq xm1, [dstq+strideq*0] + movhps xm1, [dstq+strideq*1] + vpbroadcastq m2, [dstq+strideq*4] + vpblendd m1, m2, 0x30 + vpbroadcastq m2, [dstq+r6 ] + vpblendd m1, m2, 0xc0 + mova [cq+32*0], m3 + mova [cq+32*1], m3 + add cq, 32*2 + paddw m1, m0 + pmaxsw m1, m3 + pminsw m1, m4 + vextracti128 xm2, m1, 1 + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + movq [dstq+strideq*4], xm2 + movhps [dstq+r6 ], xm2 + lea dstq, [dstq+strideq*2] + ret + +INV_TXFM_4X16_FN dct, dct, 12 +INV_TXFM_4X16_FN dct, identity, 12 +INV_TXFM_4X16_FN dct, adst, 12 +INV_TXFM_4X16_FN dct, flipadst, 12 + +cglobal idct_4x16_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + jmp m(idct_4x16_internal_10bpc).pass1 +.pass2: + punpckldq m8, m0, m1 + punpckhdq m0, m1 + punpckldq m9, m2, m3 + punpckhdq m2, m3 + punpckldq m1, m4, m5 + punpckhdq m4, m5 + punpckldq m3, m6, m7 + punpckhdq m6, m7 + punpcklqdq m5, m0, m2 ; 2 6 + punpckhqdq m12, m0, m2 ; 3 7 + punpcklqdq m0, m8, m9 ; 0 4 + punpckhqdq m10, m8, m9 ; 1 5 + punpcklqdq m2, m1, m3 ; 8 12 + punpckhqdq m13, m1, m3 ; 9 13 + punpcklqdq m9, m4, m6 ; 10 14 + punpckhqdq m4, m6 ; 11 15 + vperm2i128 m1, m5, m9, 0x20 ; 2 10 + vperm2i128 m3, m9, m5, 0x31 ; 14 6 + vpermq m11, m4, q1302 ; 15 11 + ; interleave + REPX {vpermq x, x, q3120}, m0, m1, m2, m3, m10 + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3, m10, m11, m12, m13 + REPX {pminsd x, m9}, m0, m1, m2, m3, m10, m11, m12, m13 + call m(idct_16x4_internal_10bpc).pass1_main + vpermq m6, m12, q1302 ; 7 3 + vpermq m5, m13, q3120 ; 9 13 + call m(idct_16x4_internal_10bpc).pass1_main2 + call m(idct_16x4_internal_10bpc).pass1_main3 + REPX {psrad x, 3}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m1, m2, m3 + packssdw m2, m4, m5 + packssdw m3, m6, m7 + mova m4, [idct16_12_shuf] + REPX {vpermd x, m4, x}, m0, m1, m2, m3 + vpbroadcastd m9, [pw_16384] + vpbroadcastd m8, [pixel_12bpc_max] + call m(idct_4x16_internal_10bpc).pass2_end + RET + +INV_TXFM_4X16_FN adst, dct, 12 +INV_TXFM_4X16_FN adst, adst, 12 +INV_TXFM_4X16_FN adst, flipadst, 12 +INV_TXFM_4X16_FN adst, identity, 12 + +cglobal iadst_4x16_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + call .main_pass1 + psrad m0, m4, 12 + psrad m1, m5, 12 + psrad m2, 12 + psrad m3, 12 + psrad m4, m8, 12 + psrad m5, m9, 12 + psrad m6, 12 + psrad m7, 12 + jmp tx2q +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call .transpose_16x4 + call m(iadst_4x16_internal_10bpc).main2 + pshufd m4, m5, q1032 + psrad m5, m6, 3 + pshufd m6, m7, q1032 + psrad m7, m8, 3 + REPX {pshufd x, x, q1032}, m0, m2 + REPX {psrad x, 3}, m0, m1, m2, m3, m4, m6 +.pass2_end: + packssdw m0, m1 + packssdw m1, m2, m3 + packssdw m2, m4, m5 + packssdw m3, m6, m7 + mova m4, [iadst16_12_shuf] + REPX {vpermd x, m4, x}, m0, m1, m2, m3 + vpbroadcastd m9, [pw_16384] + vpbroadcastd m8, [pixel_12bpc_max] + lea r6, [strideq*3] + pxor m7, m7 + pmulhrsw m0, m9 + call m(iadst_4x16_internal_10bpc).write_4x4 + pmulhrsw m0, m9, m1 + call m(iadst_4x16_internal_10bpc).write_4x4 + pmulhrsw m0, m9, m2 + call m(iadst_4x16_internal_10bpc).write_4x4 + pmulhrsw m0, m9, m3 + call m(iadst_4x16_internal_10bpc).write_4x4 + RET +ALIGN function_align +.transpose_16x4: + ; transpose & interleave + punpckldq m8, m0, m1 + punpckhdq m0, m1 + punpckldq m9, m2, m3 + punpckhdq m2, m3 + punpckldq m1, m4, m5 + punpckhdq m4, m5 + punpckldq m3, m6, m7 + punpckhdq m6, m7 + punpcklqdq m10, m8, m0 + punpckhqdq m0, m8 + punpcklqdq m11, m9, m2 + punpckhqdq m2, m9 + punpcklqdq m8, m1, m4 + punpckhqdq m4, m1 + punpcklqdq m9, m3, m6 + punpckhqdq m6, m3 + vperm2i128 m5, m0, m2, 0x31 ; 7 5 + vperm2i128 m7, m0, m2, 0x20 ; 3 1 + vperm2i128 m0, m10, m11, 0x20 ; 0 2 + vperm2i128 m2, m10, m11, 0x31 ; 4 6 + vperm2i128 m1, m4, m6, 0x31 ; 15 13 + vperm2i128 m3, m4, m6, 0x20 ; 11 9 + vperm2i128 m4, m8, m9, 0x20 ; 8 10 + vperm2i128 m6, m8, m9, 0x31 ; 12 14 + ret +ALIGN function_align +.main_pass1: + call m(iadst_16x4_internal_10bpc).main + vpbroadcastd m6, [pd_3072] + paddd m10, m4, m5 + psubd m4, m3 + psubd m5, m3 + paddd m3, m10 + psubd m8, m7, m1 + paddd m7, m9 + psubd m9, m1 + paddd m7, m1 + REPX {psrad x, 1 }, m4, m5, m2, m3, m8, m9, m0, m7 + REPX {paddd x, m6}, m4, m5, m2, m3, m8, m9, m7 + paddd m6, m0 + ret + +INV_TXFM_4X16_FN flipadst, dct, 12 +INV_TXFM_4X16_FN flipadst, adst, 12 +INV_TXFM_4X16_FN flipadst, flipadst, 12 +INV_TXFM_4X16_FN flipadst, identity, 12 + +cglobal iflipadst_4x16_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + call m(iadst_4x16_internal_12bpc).main_pass1 + psrad m0, m3, 12 + psrad m1, m2, 12 + psrad m2, m5, 12 + psrad m3, m4, 12 + psrad m4, m7, 12 + psrad m5, m6, 12 + psrad m6, m9, 12 + psrad m7, m8, 12 + jmp tx2q +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(iadst_4x16_internal_12bpc).transpose_16x4 + call m(iadst_4x16_internal_10bpc).main2 + pshufd m4, m3, q1032 + psrad m3, m5, 3 + psrad m5, m2, 3 + pshufd m2, m6, q1032 + pshufd m6, m1, q1032 + psrad m1, m7, 3 + psrad m7, m0, 3 + pshufd m0, m8, q1032 + REPX {psrad x, 3}, m0, m2, m4, m6 + jmp m(iadst_4x16_internal_12bpc).pass2_end + +INV_TXFM_4X16_FN identity, dct, 12 +INV_TXFM_4X16_FN identity, adst, 12 +INV_TXFM_4X16_FN identity, flipadst, 12 +INV_TXFM_4X16_FN identity, identity, 12 + +cglobal iidentity_4x16_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m8, [pd_1697] + mova m0, [cq+32*0] + mova m4, [cq+32*1] + mova m1, [cq+32*2] + mova m5, [cq+32*3] + vpbroadcastd m9, [pd_6144] + pmulld m2, m8, m0 + pmulld m6, m8, m4 + pmulld m3, m8, m1 + pmulld m7, m8, m5 + mova m10, [cq+32*4] + mova m11, [cq+32*5] + mova m12, [cq+32*6] + mova m13, [cq+32*7] + REPX {paddd x, m9}, m2, m6, m3, m7 + REPX {psrad x, 12}, m2, m6, m3, m7 + paddd m0, m2 + pmulld m2, m8, m10 + paddd m4, m6 + pmulld m6, m8, m11 + paddd m1, m3 + pmulld m3, m8, m12 + paddd m5, m7 + pmulld m7, m8, m13 + REPX {psrad x, 1 }, m0, m4, m1, m5 + REPX {paddd x, m9}, m2, m6, m3, m7 + REPX {psrad x, 12}, m2, m6, m3, m7 + paddd m2, m10 + paddd m6, m11 + paddd m3, m12 + paddd m7, m13 + REPX {psrad x, 1 }, m2, m6, m3, m7 + jmp tx2q +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + vpbroadcastd m8, [pd_5793] + vpbroadcastd m9, [pd_1024] + REPX {pmulld x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {paddd x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 14}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + vpbroadcastd m8, [pw_16384] + vpbroadcastd m4, [pixel_12bpc_max] + call m(iidentity_4x16_internal_10bpc).pass2_end + RET + +%macro INV_TXFM_8X4_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 8x4, %3 +%ifidn %1_%2, dct_dct + vpbroadcastd m2, [dconly_%3bpc] +%if %3 = 10 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 4 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 128 + sar r6d, 8 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly3 +%else + jmp m(inv_txfm_add_dct_dct_8x4_10bpc).dconly +%endif +%endif +%endmacro + +INV_TXFM_8X4_FN dct, dct +INV_TXFM_8X4_FN dct, identity +INV_TXFM_8X4_FN dct, adst +INV_TXFM_8X4_FN dct, flipadst + +cglobal idct_8x4_internal_10bpc, 0, 7, 10, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] +.pass1: + vbroadcasti128 m1, [cq+16*1] + vbroadcasti128 m0, [cq+16*5] + vbroadcasti128 m2, [cq+16*3] + vbroadcasti128 m3, [cq+16*7] + vpbroadcastd m6, [pd_2896] + shufpd m1, m0, 0x0c ; 1 5 + shufpd m3, m2, 0x0c ; 7 3 + vbroadcasti128 m0, [cq+16*0] + vbroadcasti128 m4, [cq+16*2] + vbroadcasti128 m2, [cq+16*4] + vbroadcasti128 m5, [cq+16*6] + vpbroadcastd m7, [pd_2048] + shufpd m0, m4, 0x0c ; 0 2 + shufpd m2, m5, 0x0c ; 4 6 + REPX {pmulld x, m6}, m1, m3, m0, m2 + REPX {paddd x, m7}, m1, m3, m0, m2 + REPX {psrad x, 12}, m1, m3, m0, m2 + call .main + psubd m3, m0, m4 ; out7 out6 (interleaved) + paddd m0, m4 ; out0 out1 (interleaved) + paddd m1, m2, m5 ; out3 out2 (interleaved) + psubd m2, m5 ; out4 out5 (interleaved) + pshufd m1, m1, q1032 + pshufd m3, m3, q1032 + jmp tx2q +.pass2: + vbroadcasti128 m4, [deint_shuf] + packssdw m0, m1 + packssdw m2, m3 + vperm2i128 m1, m0, m2, 0x31 + vinserti128 m0, xm2, 1 + pshufb m0, m4 + pshufb m1, m4 + IDCT4_1D_PACKED_WORD 0, 1, 2, 3, 4, 7 + vpermq m0, m0, q3120 ; out0 out1 + vpermq m2, m1, q2031 ; out2 out3 + jmp m(iadst_8x4_internal_10bpc).end +ALIGN function_align +.main: + ITX_MULSUB_2D 1, 3, 4, 5, 6, 7, 799_3406, 4017_2276, 1 + IDCT4_1D_PACKED 0, 2, 4, 5, 6, 7 + vpbroadcastd m6, [pd_2896] + punpcklqdq m4, m1, m3 ; t4a t7a + punpckhqdq m1, m3 ; t5a t6a + psubd m3, m4, m1 ; t5a t6a + paddd m4, m1 ; t4 t7 + REPX {pmaxsd x, m8}, m3, m4, m0, m2 + REPX {pminsd x, m9}, m3, m4, m0, m2 + pmulld m3, m6 + pshufd m1, m3, q1032 + paddd m3, m7 + psubd m5, m3, m1 + paddd m1, m3 + psrad m5, 12 + psrad m1, 12 + vpblendd m5, m4, 0x33 ; t4 t5 + punpckhqdq m4, m1 ; t7 t6 + ret + +INV_TXFM_8X4_FN adst, dct +INV_TXFM_8X4_FN adst, adst +INV_TXFM_8X4_FN adst, flipadst +INV_TXFM_8X4_FN adst, identity + +cglobal iadst_8x4_internal_10bpc, 0, 7, 10, dst, stride, c, eob, tx2 + call m(iadst_4x8_internal_10bpc).main + vpblendd m3, m0, m4, 0x33 ; out6 out7 + vpblendd m0, m4, 0xcc ; out0 out1 + pshufd m1, m5, q1032 + psignd m2, m6 ; out4 out5 + psignd m1, m6 ; out2 out3 + jmp tx2q +.pass2: + call .pass2_main + vpermq m0, m0, q3120 ; out0 out1 + vpermq m2, m1, q3120 ; out2 out3 +.end: + vpbroadcastd m1, [pw_2048] + pmulhrsw m0, m1 + pmulhrsw m1, m2 + vpbroadcastd m5, [pixel_10bpc_max] +.end2: + mova xm2, [dstq+strideq*0] + vinserti128 m2, [dstq+strideq*1], 1 + lea r6, [dstq+strideq*2] + mova xm3, [r6 +strideq*0] + vinserti128 m3, [r6 +strideq*1], 1 + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m5 + pminsw m1, m5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [r6 +strideq*0], xm1 + vextracti128 [r6 +strideq*1], m1, 1 + RET +ALIGN function_align +.pass2_main: + vbroadcasti128 m4, [deint_shuf] + packssdw m0, m1 + packssdw m2, m3 + lea r6, [deint_shuf+128] + vperm2i128 m1, m0, m2, 0x31 + vinserti128 m0, xm2, 1 + pshufb m0, m4 + pshufb m1, m4 + jmp m(iadst_8x4_internal_8bpc).main +ALIGN function_align +.main: + vpbroadcastd m1, [pd_2896] + pmulld m0, m1, [cq+32*0] + pmulld m3, m1, [cq+32*3] + pmulld m2, m1, [cq+32*2] + pmulld m1, [cq+32*1] + vpbroadcastd m4, [pd_2048] + REPX {paddd x, m4}, m0, m3, m2, m1 + REPX {psrad x, 12}, m0, m3, m2, m1 +.main2: + IADST4_1D + ret + +INV_TXFM_8X4_FN flipadst, dct +INV_TXFM_8X4_FN flipadst, adst +INV_TXFM_8X4_FN flipadst, flipadst +INV_TXFM_8X4_FN flipadst, identity + +cglobal iflipadst_8x4_internal_10bpc, 0, 5, 10, dst, stride, c, eob, tx2 + call m(iadst_4x8_internal_10bpc).main + shufpd m3, m4, m0, 0x05 + shufpd m0, m4, 0x05 + psignd m2, m6 + pshufd m6, m6, q1032 + pshufd m1, m2, q1032 + psignd m2, m5, m6 + jmp tx2q +.pass2: + call m(iadst_8x4_internal_10bpc).pass2_main + vpermq m2, m0, q2031 + vpermq m0, m1, q2031 + jmp m(iadst_8x4_internal_10bpc).end + +INV_TXFM_8X4_FN identity, dct +INV_TXFM_8X4_FN identity, adst +INV_TXFM_8X4_FN identity, flipadst +INV_TXFM_8X4_FN identity, identity + +cglobal iidentity_8x4_internal_10bpc, 0, 7, 10, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m4, [pd_2896] + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpermq m2, [cq+32*2], q3120 + vpermq m3, [cq+32*3], q3120 + vpbroadcastd m7, [pd_2048] + REPX {pmulld x, m4}, m0, m1, m2, m3 + REPX {paddd x, m7}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + REPX {paddd x, x }, m0, m1, m2, m3 + jmp tx2q +.pass2: + vpbroadcastd m5, [pixel_10bpc_max] + vpbroadcastd m4, [pw_1697x8] + packssdw m0, m1 + packssdw m2, m3 + pmulhrsw m1, m4, m0 + pmulhrsw m4, m2 + paddsw m0, m1 + paddsw m2, m4 + packssdw m7, m7 ; pw_2048 +.pass2_end: + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + lea r6, [dstq+strideq*2] + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmulhrsw m2, m7 + pmulhrsw m0, m7 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + mova xm2, [dstq+strideq*0] + vinserti128 m2, [r6 +strideq*0], 1 + mova xm3, [dstq+strideq*1] + vinserti128 m3, [r6 +strideq*1], 1 + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m5 + pminsw m1, m5 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + vextracti128 [r6 +strideq*0], m0, 1 + vextracti128 [r6 +strideq*1], m1, 1 + RET + +INV_TXFM_8X4_FN dct, dct, 12 +INV_TXFM_8X4_FN dct, identity, 12 +INV_TXFM_8X4_FN dct, adst, 12 +INV_TXFM_8X4_FN dct, flipadst, 12 + +cglobal idct_8x4_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_20b_min] + vpbroadcastd m9, [clip_20b_max] + jmp m(idct_8x4_internal_10bpc).pass1 +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + call m(iadst_8x4_internal_12bpc).transpose_4x8 + IDCT4_1D 0, 1, 2, 3, 4, 5, 6, 7 + jmp m(iadst_8x4_internal_12bpc).end + +INV_TXFM_8X4_FN adst, dct, 12 +INV_TXFM_8X4_FN adst, adst, 12 +INV_TXFM_8X4_FN adst, flipadst, 12 +INV_TXFM_8X4_FN adst, identity, 12 + +cglobal iadst_8x4_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_20b_min] + vpbroadcastd m9, [clip_20b_max] + call m(iadst_4x8_internal_10bpc).main2 + vpblendd m3, m0, m4, 0x33 ; out6 out7 + vpblendd m0, m4, 0xcc ; out0 out1 + pshufd m1, m5, q1032 + psignd m2, m6 ; out4 out5 + psignd m1, m6 ; out2 out3 + jmp tx2q +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + call .pass2_main + vpbroadcastd m5, [pd_2048] + paddd m0, m5, m4 + paddd m1, m5, m6 + paddd m2, m5 + paddd m3, m5 +.pass2_end: + REPX {psrad x, 12}, m0, m1, m2, m3 +.end: + vpbroadcastd m4, [pw_16384] + REPX {psrad x, 3}, m0, m1, m2, m3 + packssdw m0, m1 + packssdw m2, m3 + pmulhrsw m0, m4 + pmulhrsw m1, m2, m4 + vpermq m0, m0, q3120 ; out0 out1 + vpermq m1, m1, q3120 ; out2 out3 + vpbroadcastd m5, [pixel_12bpc_max] + jmp m(iadst_8x4_internal_10bpc).end2 +ALIGN function_align +.pass2_main: + call .transpose_4x8 + jmp m(iadst_8x4_internal_10bpc).main2 +ALIGN function_align +.transpose_4x8: + ; deinterleave + pshufd m0, m0, q3120 + pshufd m1, m1, q3120 + pshufd m2, m2, q3120 + pshufd m3, m3, q3120 + ; transpose + punpcklqdq m4, m0, m1 + punpckhqdq m0, m1 + punpcklqdq m5, m2, m3 + punpckhqdq m2, m3 + vperm2i128 m1, m0, m2, 0x20 ; out1 + vperm2i128 m3, m0, m2, 0x31 ; out3 + vperm2i128 m2, m4, m5, 0x31 ; out2 + vperm2i128 m0, m4, m5, 0x20 ; out0 + ret + +INV_TXFM_8X4_FN flipadst, dct, 12 +INV_TXFM_8X4_FN flipadst, adst, 12 +INV_TXFM_8X4_FN flipadst, flipadst, 12 +INV_TXFM_8X4_FN flipadst, identity, 12 + +cglobal iflipadst_8x4_internal_12bpc, 0, 5, 10, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_20b_min] + vpbroadcastd m9, [clip_20b_max] + call m(iadst_4x8_internal_10bpc).main2 + shufpd m3, m4, m0, 0x05 + shufpd m0, m4, 0x05 + psignd m2, m6 + pshufd m6, m6, q1032 + pshufd m1, m2, q1032 + psignd m2, m5, m6 + jmp tx2q +.pass2: + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + call m(iadst_8x4_internal_12bpc).pass2_main + vpbroadcastd m5, [pd_2048] + paddd m0, m5, m3 + paddd m1, m5, m2 + paddd m3, m5, m4 + paddd m2, m5, m6 + jmp m(iadst_8x4_internal_12bpc).pass2_end + +INV_TXFM_8X4_FN identity, dct, 12 +INV_TXFM_8X4_FN identity, adst, 12 +INV_TXFM_8X4_FN identity, flipadst, 12 +INV_TXFM_8X4_FN identity, identity, 12 + +cglobal iidentity_8x4_internal_12bpc, 0, 7, 10, dst, stride, c, eob, tx2 + jmp m(iidentity_8x4_internal_10bpc).pass1 +.pass2: + ; m0 = in0 in1 (interleaved) + ; m1 = in2 in3 (interleaved) + ; m2 = in4 in5 (interleaved) + ; m3 = in6 in7 (interleaved) + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] + REPX {pmaxsd x, m8}, m0, m1, m2, m3 + REPX {pminsd x, m9}, m0, m1, m2, m3 + vpbroadcastd m4, [pd_5793] + REPX {pmulld x, m4}, m0, m1, m2, m3 + REPX {paddd x, m7}, m0, m1, m2, m3 + REPX {psrad x, 15}, m0, m1, m2, m3 + vpbroadcastd m5, [pixel_12bpc_max] + vpbroadcastd m7, [pw_16384] + packssdw m0, m1 + packssdw m2, m3 + jmp m(iidentity_8x4_internal_10bpc).pass2_end + +%macro INV_TXFM_8X8_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 8x8, %3 +%ifidn %1_%2, dct_dct + vpbroadcastd m2, [dconly_%3bpc] +%if %3 = 10 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 8 +.dconly2: + add r6d, 384 + sar r6d, 9 +.dconly3: + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + movd xm0, r6d + paddsw xm0, xm2 + vpbroadcastw m0, xm0 +.dconly_loop: + mova xm1, [dstq+strideq*0] + vinserti128 m1, [dstq+strideq*1], 1 + paddsw m1, m0 + psubusw m1, m2 + mova [dstq+strideq*0], xm1 + vextracti128 [dstq+strideq*1], m1, 1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%else + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly +%endif +%endif +%endmacro + +%macro IADST8_1D 14 ; src[1-8], tmp[1-3], pd_2048, clip[1-2] + ITX_MULSUB_2D %8, %1, %9, %10, %11, %12, 401, 4076 ; t1a, t0a + ITX_MULSUB_2D %2, %7, %9, %10, %11, %12, 3920, 1189 ; t7a, t6a + ITX_MULSUB_2D %6, %3, %9, %10, %11, %12, 1931, 3612 ; t3a, t2a + ITX_MULSUB_2D %4, %5, %9, %10, %11, %12, 3166, 2598 ; t5a, t4a + psubd m%9, m%3, m%7 ; t6 + paddd m%3, m%7 ; t2 + psubd m%7, m%1, m%5 ; t4 + paddd m%1, m%5 ; t0 + psubd m%5, m%6, m%2 ; t7 + paddd m%6, m%2 ; t3 + psubd m%2, m%8, m%4 ; t5 + paddd m%8, m%4 ; t1 + REPX {pmaxsd x, m%13}, m%7, m%2, m%9, m%5, m%3, m%1, m%6, m%8 + REPX {pminsd x, m%14}, m%7, m%2, m%9, m%5, m%3, m%1, m%6, m%8 + ITX_MULSUB_2D %7, %2, %4, %10, %11, %12, 1567, 3784 ; t5a, t4a + ITX_MULSUB_2D %5, %9, %4, %10, %11, %12, 3784, %11 ; t6a, t7a + psubd m%10, m%7, m%9 ; t7 + paddd m%7, m%9 ; out6 + vpbroadcastd m%9, [pd_1448] + psubd m%4, m%8, m%6 ; t3 + paddd m%8, m%6 ; -out7 + psubd m%6, m%1, m%3 ; t2 + paddd m%1, m%3 ; out0 + psubd m%3, m%2, m%5 ; t6 + paddd m%2, m%5 ; -out1 + REPX {pmaxsd x, m%13}, m%6, m%4, m%3, m%10 + REPX {pminsd x, m%14}, m%6, m%4, m%3, m%10 + REPX {pmulld x, m%9 }, m%6, m%4, m%3, m%10 + psubd m%5, m%6, m%4 ; (t2 - t3) * 1448 + paddd m%4, m%6 ; (t2 + t3) * 1448 + psubd m%6, m%3, m%10 ; (t6 - t7) * 1448 + paddd m%3, m%10 ; (t6 + t7) * 1448 +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, identity +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst + +cglobal idct_8x8_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + mova m4, [cq+32*4] + mova m5, [cq+32*5] + mova m6, [cq+32*6] + mova m7, [cq+32*7] + vpbroadcastd m11, [pd_2048] + call .main + call .round_shift1 + jmp tx2q +.pass2: + call .transpose_8x8_packed + call m(idct_8x8_internal_8bpc).main + vpbroadcastd m12, [pw_2048] + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call .write_8x4_start + pmulhrsw m0, m2, m12 + pmulhrsw m1, m3, m12 + call .write_8x4 + RET +ALIGN function_align +.write_8x4_start: + vpbroadcastd m11, [pixel_10bpc_max] + lea r6, [strideq*3] + pxor m10, m10 +.write_8x4: + mova xm8, [dstq+strideq*0] + vinserti128 m8, [dstq+strideq*1], 1 + mova xm9, [dstq+strideq*2] + vinserti128 m9, [dstq+r6 ], 1 + mova [cq+32*0], m10 + mova [cq+32*1], m10 + mova [cq+32*2], m10 + mova [cq+32*3], m10 + add cq, 32*4 + paddw m0, m8 + paddw m1, m9 + pmaxsw m0, m10 + pmaxsw m1, m10 + pminsw m0, m11 + pminsw m1, m11 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+r6 ], m1, 1 + lea dstq, [dstq+strideq*4] + ret +ALIGN function_align +.transpose_8x8_packed: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + lea r6, [deint_shuf+128] + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckhdq m2, m4, m1 + punpckldq m4, m1 + vinserti128 m1, m3, xm2, 1 + vperm2i128 m3, m2, 0x31 + vperm2i128 m2, m0, m4, 0x31 + vinserti128 m0, xm4, 1 + ret +ALIGN function_align +.main_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 +.main: + ITX_MULSUB_2D 5, 3, 8, 9, 10, 11, 3406, 2276 ; t5a t6a + ITX_MULSUB_2D 1, 7, 8, 9, 10, 11, 799, 4017 ; t4a t7a + ITX_MULSUB_2D 2, 6, 8, 9, 10, 11, 1567, 3784 ; t2 t3 + paddd m8, m1, m5 ; t4 + psubd m1, m5 ; t5a + paddd m9, m7, m3 ; t7 + psubd m7, m3 ; t6a + vpbroadcastd m3, [pd_2896] + REPX {pmaxsd x, m12}, m1, m8, m7, m9 + REPX {pminsd x, m13}, m1, m8, m7, m9 + REPX {pmulld x, m3 }, m0, m4, m7, m1 + paddd m0, m11 + paddd m7, m11 + psubd m5, m0, m4 + paddd m0, m4 + psubd m4, m7, m1 + paddd m7, m1 + REPX {psrad x, 12 }, m5, m0, m4, m7 + psubd m3, m0, m6 ; dct4 out3 + paddd m0, m6 ; dct4 out0 + paddd m6, m5, m2 ; dct4 out1 + psubd m5, m2 ; dct4 out2 + REPX {pmaxsd x, m12}, m0, m6, m5, m3 + REPX {pminsd x, m13}, m0, m6, m5, m3 + ret +ALIGN function_align +.round_shift1: + pcmpeqd m1, m1 + REPX {psubd x, m1}, m0, m6, m5, m3 + paddd m1, m6, m7 ; out1 + psubd m6, m7 ; out6 + psubd m7, m0, m9 ; out7 + paddd m0, m9 ; out0 + paddd m2, m5, m4 ; out2 + psubd m5, m4 ; out5 + psubd m4, m3, m8 ; out4 + paddd m3, m8 ; out3 + REPX {psrad x, 1 }, m0, m1, m2, m3, m4, m5, m6, m7 + ret + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, adst +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity + +cglobal iadst_8x8_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + call .main + call .main_end + jmp tx2q +.pass2: + call m(idct_8x8_internal_10bpc).transpose_8x8_packed + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call m(iadst_8x8_internal_8bpc).main_pass2 + vpbroadcastd m5, [pw_2048] + vpbroadcastd xm12, [pw_4096] + psubw m12, m5 + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m0, m2, m12 + pmulhrsw m1, m3, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +ALIGN function_align +.main: + mova m0, [cq+32*0] + mova m7, [cq+32*7] + mova m1, [cq+32*1] + mova m6, [cq+32*6] + mova m2, [cq+32*2] + mova m5, [cq+32*5] + mova m3, [cq+32*3] + mova m4, [cq+32*4] + vpbroadcastd m11, [pd_2048] +.main2: + IADST8_1D 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 + psrld m8, 10 ; pd_1 + vpbroadcastd m9, [pd_3072] + ret +ALIGN function_align +.main_end: + paddd m0, m8 + psubd m1, m8, m1 + paddd m6, m8 + psubd m7, m8, m7 + REPX {psrad x, 1 }, m0, m1, m6, m7 + ; (1 + ((x + 1024) >> 11)) >> 1 = (3072 + x) >> 12 + ; (1 - ((x + 1024) >> 11)) >> 1 = (3071 - x) >> 12 + psubd m8, m9, m8 ; pd_3071 + paddd m2, m9 + psubd m3, m8, m3 + paddd m4, m9 + psubd m5, m8, m5 + REPX {psrad x, 12}, m2, m3, m4, m5 + ret + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, flipadst +INV_TXFM_8X8_FN flipadst, identity + +cglobal iflipadst_8x8_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + call m(iadst_8x8_internal_10bpc).main + call .main_end + jmp tx2q +.pass2: + call m(idct_8x8_internal_10bpc).transpose_8x8_packed + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call m(iadst_8x8_internal_8bpc).main_pass2 + vpbroadcastd m12, [pw_2048] + vpbroadcastd xm5, [pw_4096] + psubw m12, m5 + vpermq m8, m3, q2031 + vpermq m9, m2, q2031 + vpermq m2, m1, q2031 + vpermq m3, m0, q2031 + pmulhrsw m0, m8, m12 + pmulhrsw m1, m9, m12 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m0, m2, m12 + pmulhrsw m1, m3, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +ALIGN function_align +.main_end: + paddd m10, m8, m0 + psubd m0, m8, m7 + psubd m7, m8, m1 + paddd m1, m8, m6 + psrad m0, 1 + psrad m1, 1 + psrad m6, m7, 1 + psrad m7, m10, 1 + psubd m8, m9, m8 ; pd_6143 + psubd m10, m8, m5 + paddd m5, m9, m2 + psubd m2, m8, m3 + paddd m3, m9, m4 + psrad m4, m2, 12 + psrad m2, m10, 12 + psrad m3, 12 + psrad m5, 12 + ret + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 +.pass1: + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + mova m4, [cq+32*4] + mova m5, [cq+32*5] + mova m6, [cq+32*6] + mova m7, [cq+32*7] + jmp tx2q +.pass2: + packssdw m3, m7 + vpbroadcastd m7, [pixel_10bpc_max] +.pass2_main: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + vpbroadcastd m12, [pw_4096] + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m1 + punpckhdq m4, m1 + punpckhqdq m1, m0, m2 ; 1 5 + punpcklqdq m0, m2 ; 0 4 + punpcklqdq m2, m3, m4 ; 2 6 + punpckhqdq m3, m4 ; 3 7 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call .write_2x8x2_start + pmulhrsw m0, m2, m12 + pmulhrsw m1, m3, m12 + call .write_2x8x2_zero + RET +.write_2x8x2_start: + lea r6, [strideq*5] + pxor m6, m6 +.write_2x8x2_zero: + mova [cq+32*0], m6 + mova [cq+32*1], m6 + mova [cq+32*2], m6 + mova [cq+32*3], m6 + add cq, 32*4 +.write_2x8x2: + mova xm4, [dstq+strideq*0] + vinserti128 m4, [dstq+strideq*4], 1 + mova xm5, [dstq+strideq*1] + vinserti128 m5, [dstq+r6 ], 1 + paddw m0, m4 + paddw m1, m5 + pmaxsw m0, m6 + pmaxsw m1, m6 + pminsw m0, m7 + pminsw m1, m7 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + vextracti128 [dstq+strideq*4], m0, 1 + vextracti128 [dstq+r6 ], m1, 1 + lea dstq, [dstq+strideq*2] + ret + +%macro TRANSPOSE_8X8_DWORD 12 ; src/dst[1-8], tmp[1-4] + punpckldq m%9, m%1, m%2 ; aibj emfn + punpckhdq m%1, m%2 ; ckdl gohp + punpckldq m%10, m%3, m%4 ; qyrz uCvD + punpckhdq m%3, m%4 ; sAtB wExF + punpckldq m%11, m%5, m%6 ; GOHP KSLT + punpckhdq m%5, m%6 ; IQJR MUNV + punpckldq m%12, m%7, m%8 ; WeXf aibj + punpckhdq m%7, m%8 ; YgZh ckdl + punpcklqdq m%2, m%9, m%10 ; aiqy emuC + punpckhqdq m%9, m%10 ; bjrz fnvD + punpcklqdq m%4, m%1, m%3 ; cksA gowE + punpckhqdq m%10, m%1, m%3 ; dltB hpxF + punpcklqdq m%6, m%11, m%12 ; GOWe KSai + punpckhqdq m%11, m%12 ; HPXf LTbj + punpcklqdq m%8, m%5, m%7 ; IQYg MUck + punpckhqdq m%12, m%5, m%7 ; JRZh NVdl + vperm2i128 m%1, m%2, m%6, 0x20 ; out0 + vperm2i128 m%5, m%2, m%6, 0x31 ; out4 + vperm2i128 m%2, m%9, m%11, 0x20 ; out1 + vperm2i128 m%6, m%9, m%11, 0x31 ; out5 + vperm2i128 m%3, m%4, m%8, 0x20 ; out2 + vperm2i128 m%7, m%4, m%8, 0x31 ; out6 + vperm2i128 m%4, m%10, m%12, 0x20 ; out3 + vperm2i128 m%8, m%10, m%12, 0x31 ; out7 +%endmacro + +INV_TXFM_8X8_FN dct, dct, 12 +INV_TXFM_8X8_FN dct, identity, 12 +INV_TXFM_8X8_FN dct, adst, 12 +INV_TXFM_8X8_FN dct, flipadst, 12 + +cglobal idct_8x8_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(idct_8x8_internal_10bpc).pass1 +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call .transpose_8x8 + vpbroadcastd m11, [pd_2048] + call m(idct_8x8_internal_10bpc).main + call .round_shift4 + jmp m(iadst_8x8_internal_12bpc).pass2_end +ALIGN function_align +.write_8x4_start: + vpbroadcastd m11, [pixel_12bpc_max] + lea r6, [strideq*3] + pxor m10, m10 + ret +ALIGN function_align +.transpose_8x8: + TRANSPOSE_8X8_DWORD 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + ret +ALIGN function_align +.round_shift4: + vpbroadcastd m1, [pd_8] + REPX {paddd x, m1}, m0, m6, m5, m3 + paddd m1, m6, m7 ; out1 + psubd m6, m7 ; out6 + psubd m7, m0, m9 ; out7 + paddd m0, m9 ; out0 + paddd m2, m5, m4 ; out2 + psubd m5, m4 ; out5 + psubd m4, m3, m8 ; out4 + paddd m3, m8 ; out3 + REPX {psrad x, 4}, m0, m1, m2, m3, m4, m5, m6, m7 + ret + +INV_TXFM_8X8_FN adst, dct, 12 +INV_TXFM_8X8_FN adst, adst, 12 +INV_TXFM_8X8_FN adst, flipadst, 12 +INV_TXFM_8X8_FN adst, identity, 12 + +cglobal iadst_8x8_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iadst_8x8_internal_10bpc).pass1 +.pass2: + call .pass2_main +.pass2_end: + packssdw m0, m1 + packssdw m1, m2, m3 + REPX {vpermq x, x, q3120}, m0, m1 + call m(idct_8x8_internal_12bpc).write_8x4_start + call m(idct_8x8_internal_10bpc).write_8x4 + packssdw m0, m4, m5 + packssdw m1, m6, m7 + REPX {vpermq x, x, q3120}, m0, m1 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +ALIGN function_align +.pass2_main: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x8_internal_12bpc).transpose_8x8 + vpbroadcastd m11, [pd_2048] +.pass2_main2: + call m(iadst_8x8_internal_10bpc).main2 + pslld m9, m8, 3 ; pd_8 + paddd m0, m9 + psubd m1, m9, m1 ; 8+x + paddd m6, m9 + psubd m7, m9, m7 + REPX {psrad x, 4}, m0, m1, m6, m7 + vpbroadcastd m9, [pd_17408] + psubd m8, m9, m8 ; 17407 + paddd m2, m9 + psubd m3, m8, m3 + paddd m4, m9 + psubd m5, m8, m5 + REPX {psrad x, 15}, m2, m3, m4, m5 + ret + +INV_TXFM_8X8_FN flipadst, dct, 12 +INV_TXFM_8X8_FN flipadst, adst, 12 +INV_TXFM_8X8_FN flipadst, flipadst, 12 +INV_TXFM_8X8_FN flipadst, identity, 12 + +cglobal iflipadst_8x8_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iflipadst_8x8_internal_10bpc).pass1 +.pass2: + call m(iadst_8x8_internal_12bpc).pass2_main + packssdw m7, m7, m6 + packssdw m6, m1, m0 + packssdw m1, m5, m4 + vpermq m0, m7, q3120 + vpermq m1, m1, q3120 + call m(idct_8x8_internal_12bpc).write_8x4_start + call m(idct_8x8_internal_10bpc).write_8x4 + packssdw m0, m3, m2 + vpermq m0, m0, q3120 + vpermq m1, m6, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + RET + +INV_TXFM_8X8_FN identity, dct, 12 +INV_TXFM_8X8_FN identity, adst, 12 +INV_TXFM_8X8_FN identity, flipadst, 12 +INV_TXFM_8X8_FN identity, identity, 12 + +cglobal iidentity_8x8_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + jmp m(iidentity_8x8_internal_10bpc).pass1 +.pass2: + packssdw m3, m7 + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(iidentity_8x8_internal_10bpc).pass2_main + +%macro INV_TXFM_8X16_FN 2-4 0,10 ; type1, type2, eob_offset, bitdepth + INV_TXFM_FN %1, %2, %3, 8x16, %4 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + vpbroadcastd m2, [dconly_%4bpc] + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly2 +%endif +%endmacro + +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, identity, 35 +INV_TXFM_8X16_FN dct, adst +INV_TXFM_8X16_FN dct, flipadst + +cglobal idct_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + vpbroadcastd m14, [pd_2896] + vpbroadcastd m11, [pd_2048] + cmp eobd, 43 + jl .fast + add cq, 32 + call .pass1_main + sub cq, 32 + mova [cq+32* 1], m0 + mova [cq+32* 3], m1 + mova [cq+32* 5], m2 + mova [cq+32* 7], m3 + mova [cq+32* 9], m4 + mova [cq+32*11], m5 + mova [cq+32*13], m6 + mova m15, m7 + call .pass1_main + mova m8, [cq+32* 1] + mova m9, [cq+32* 3] + mova m10, [cq+32* 5] + mova m11, [cq+32* 7] + mova m12, [cq+32* 9] + mova m13, [cq+32*11] + mova m14, [cq+32*13] + jmp tx2q +.fast: + call .pass1_main + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call .transpose + call m(idct_8x16_internal_8bpc).main + vpbroadcastd m12, [pw_2048] + REPX {vpermq x, x, q3120}, m0, m2, m4, m6 + REPX {vpermq x, x, q2031}, m1, m3, m5, m7 +.end: + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m0, m2, m12 + pmulhrsw m1, m3, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m0, m4, m12 + pmulhrsw m1, m5, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m0, m6, m12 + pmulhrsw m1, m7, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +ALIGN function_align +.transpose: + packssdw m0, m8 + packssdw m1, m9 + packssdw m2, m10 + packssdw m3, m11 + packssdw m4, m12 + packssdw m5, m13 + packssdw m6, m14 + packssdw m7, m15 + lea r6, [deint_shuf+128] + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpcklwd m3, m4, m5 + punpckhwd m4, m5 + punpckhwd m5, m6, m7 + punpcklwd m6, m7 + punpckhdq m7, m3, m6 + punpckldq m3, m6 + punpckhdq m6, m4, m5 + punpckldq m4, m5 + punpckhdq m5, m8, m1 + punpckldq m8, m1 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + vperm2i128 m2, m0, m3, 0x31 + vinserti128 m0, xm3, 1 + vperm2i128 m3, m1, m7, 0x31 + vinserti128 m1, xm7, 1 + vperm2i128 m7, m5, m6, 0x31 + vinserti128 m5, xm6, 1 + vperm2i128 m6, m8, m4, 0x31 + vinserti128 m4, m8, xm4, 1 + ret +ALIGN function_align +.pass1_main: + pmulld m0, m14, [cq+32* 0] + pmulld m1, m14, [cq+32* 2] + pmulld m2, m14, [cq+32* 4] + pmulld m3, m14, [cq+32* 6] + pmulld m4, m14, [cq+32* 8] + pmulld m5, m14, [cq+32*10] + pmulld m6, m14, [cq+32*12] + pmulld m7, m14, [cq+32*14] + call m(idct_8x8_internal_10bpc).main_rect2 + jmp m(idct_8x8_internal_10bpc).round_shift1 +ALIGN function_align +.main_evenhalf: + paddd m1, m6, m7 ; idct8 out1 + psubd m6, m7 ; idct8 out6 + psubd m7, m0, m9 ; idct8 out7 + paddd m0, m9 ; idct8 out0 + paddd m2, m5, m4 ; idct8 out2 + psubd m5, m4 ; idct8 out5 + psubd m4, m3, m8 ; idct8 out4 + paddd m3, m8 ; idct8 out3 + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + ret +.main_oddhalf_fast_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_oddhalf_fast: ; lower half zero + vpbroadcastd m7, [pd_4076] + vpbroadcastd m8, [pd_401] + vpbroadcastd m6, [pd_m1189] + vpbroadcastd m9, [pd_3920] + vpbroadcastd m5, [pd_3612] + vpbroadcastd m10, [pd_1931] + vpbroadcastd m4, [pd_m2598] + vpbroadcastd m15, [pd_3166] + pmulld m7, m0 + pmulld m0, m8 + pmulld m6, m1 + pmulld m1, m9 + pmulld m5, m2 + pmulld m2, m10 + pmulld m4, m3 + pmulld m3, m15 + jmp .main_oddhalf_fast2 +.main_oddhalf_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 +.main_oddhalf: + ITX_MULSUB_2D 0, 7, 8, 9, 10, _, 401, 4076 ; t8a, t15a + ITX_MULSUB_2D 6, 1, 8, 9, 10, _, 3920, 1189 ; t11a, t12a + ITX_MULSUB_2D 2, 5, 8, 9, 10, _, 1931, 3612 ; t10a, t13a + ITX_MULSUB_2D 4, 3, 8, 9, 10, _, 3166, 2598 ; t9a, t14a +.main_oddhalf_fast2: + REPX {paddd x, m11}, m0, m7, m6, m1, m2, m5, m4, m3 + REPX {psrad x, 12 }, m0, m4, m6, m2, m1, m5, m7, m3 + psubd m8, m0, m4 ; t9 + paddd m0, m4 ; t8 + psubd m4, m6, m2 ; t10 + paddd m2, m6 ; t11 + psubd m6, m1, m5 ; t13 + paddd m5, m1 ; t12 + psubd m1, m7, m3 ; t14 + paddd m7, m3 ; t15 + REPX {pmaxsd x, m12}, m8, m1, m4, m6, m0, m2, m5, m7 + REPX {pminsd x, m13}, m8, m1, m4, m6, m0, m2, m5, m7 + vpbroadcastd m15, [pd_3784] + vpbroadcastd m10, [pd_1567] + ITX_MULSUB_2D 1, 8, 3, 9, _, 11, 10, 15 + ITX_MULSUB_2D 6, 4, 3, 9, _, 11, 10, 15, 2 + psubd m3, m1, m4 ; t10 + paddd m1, m4 ; t9 + psubd m4, m0, m2 ; t11a + paddd m0, m2 ; t8a + psubd m2, m8, m6 ; t13 + paddd m6, m8 ; t14 + psubd m8, m7, m5 ; t12a + paddd m7, m5 ; t15a + REPX {pmaxsd x, m12}, m2, m8, m3, m4, m0, m1, m6, m7 + REPX {pminsd x, m13}, m2, m8, m3, m4, m0, m1, m6, m7 + REPX {pmulld x, m14}, m2, m8, m3, m4 + paddd m2, m11 + paddd m8, m11 + paddd m5, m2, m3 ; t13a + psubd m2, m3 ; t10a + psubd m3, m8, m4 ; t11 + paddd m4, m8 ; t12 + REPX {psrad x, 12}, m5, m2, m3, m4 + mova [r6-32*4], m7 + mova [r6-32*3], m6 + mova [r6-32*2], m5 + mova [r6-32*1], m4 + mova [r6+32*0], m3 + mova [r6+32*1], m2 + mova [r6+32*2], m1 + mova [r6+32*3], m0 + ret + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, adst +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, identity, 35 + +cglobal iadst_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + vpbroadcastd m14, [pd_2896] + vpbroadcastd m11, [pd_2048] + cmp eobd, 43 + jl .fast + add cq, 32 + call .pass1_main + call m(iadst_8x8_internal_10bpc).main_end + sub cq, 32 + mova [cq+32* 1], m0 + mova [cq+32* 3], m1 + mova [cq+32* 5], m2 + mova [cq+32* 7], m3 + mova [cq+32* 9], m4 + mova [cq+32*11], m5 + mova [cq+32*13], m6 + mova m15, m7 + call .pass1_main + call m(iadst_8x8_internal_10bpc).main_end + mova m8, [cq+32* 1] + mova m9, [cq+32* 3] + mova m10, [cq+32* 5] + mova m11, [cq+32* 7] + mova m12, [cq+32* 9] + mova m13, [cq+32*11] + mova m14, [cq+32*13] + jmp tx2q +.fast: + call .pass1_main + call m(iadst_8x8_internal_10bpc).main_end + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call m(idct_8x16_internal_10bpc).transpose + call m(iadst_8x16_internal_8bpc).main + call m(iadst_8x16_internal_8bpc).main_pass2_end + vpbroadcastd m8, [pw_2048] + vpbroadcastd xm12, [pw_4096] + REPX {vpermq x, x, q2031}, m0, m1, m2, m3 + REPX {vpermq x, x, q3120}, m4, m5, m6, m7 + psubw m12, m8 + jmp m(idct_8x16_internal_10bpc).end +ALIGN function_align +.pass1_main: + pmulld m0, m14, [cq+32* 0] + pmulld m7, m14, [cq+32*14] + pmulld m1, m14, [cq+32* 2] + pmulld m6, m14, [cq+32*12] + pmulld m2, m14, [cq+32* 4] + pmulld m5, m14, [cq+32*10] + pmulld m3, m14, [cq+32* 6] + pmulld m4, m14, [cq+32* 8] + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 + jmp m(iadst_8x8_internal_10bpc).main2 + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst +INV_TXFM_8X16_FN flipadst, identity, 35 + +cglobal iflipadst_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + vpbroadcastd m14, [pd_2896] + vpbroadcastd m11, [pd_2048] + cmp eobd, 43 + jl .fast + add cq, 32 + call m(iadst_8x16_internal_10bpc).pass1_main + call m(iflipadst_8x8_internal_10bpc).main_end + sub cq, 32 + mova [cq+32* 1], m0 + mova [cq+32* 3], m1 + mova [cq+32* 5], m2 + mova [cq+32* 7], m3 + mova [cq+32* 9], m4 + mova [cq+32*11], m5 + mova [cq+32*13], m6 + mova m15, m7 + call m(iadst_8x16_internal_10bpc).pass1_main + call m(iflipadst_8x8_internal_10bpc).main_end + mova m8, [cq+32* 1] + mova m9, [cq+32* 3] + mova m10, [cq+32* 5] + mova m11, [cq+32* 7] + mova m12, [cq+32* 9] + mova m13, [cq+32*11] + mova m14, [cq+32*13] + jmp tx2q +.fast: + call m(iadst_8x16_internal_10bpc).pass1_main + call m(iflipadst_8x8_internal_10bpc).main_end + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call m(idct_8x16_internal_10bpc).transpose + call m(iadst_8x16_internal_8bpc).main + call m(iadst_8x16_internal_8bpc).main_pass2_end + vpbroadcastd m12, [pw_2048] + vpbroadcastd xm13, [pw_4096] + mova m11, m0 + vpermq m0, m7, q2031 + mova m10, m1 + vpermq m1, m6, q2031 + mova m9, m2 + vpermq m2, m5, q2031 + mova m8, m3 + vpermq m3, m4, q2031 + vpermq m4, m8, q3120 + vpermq m5, m9, q3120 + vpermq m6, m10, q3120 + vpermq m7, m11, q3120 + psubw m12, m13 + jmp m(idct_8x16_internal_10bpc).end + +INV_TXFM_8X16_FN identity, dct +INV_TXFM_8X16_FN identity, adst +INV_TXFM_8X16_FN identity, flipadst +INV_TXFM_8X16_FN identity, identity + +%macro IDTX16 3-4 ; src/dst, tmp, pw_1697x16, [pw_16384] + pmulhrsw m%2, m%3, m%1 +%if %0 == 4 ; if downshifting by 1 +%ifnum %4 + pmulhrsw m%2, m%4 +%else ; without rounding + psraw m%2, 1 +%endif +%else + paddsw m%1, m%1 +%endif + paddsw m%1, m%2 +%endmacro + +cglobal iidentity_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m15, [pd_2896] + pmulld m0, m15, [cq+32* 0] + pmulld m8, m15, [cq+32* 1] + pmulld m1, m15, [cq+32* 2] + pmulld m9, m15, [cq+32* 3] + pmulld m2, m15, [cq+32* 4] + pmulld m10, m15, [cq+32* 5] + pmulld m3, m15, [cq+32* 6] + pmulld m11, m15, [cq+32* 7] + pmulld m4, m15, [cq+32* 8] + pmulld m12, m15, [cq+32* 9] + pmulld m5, m15, [cq+32*10] + pmulld m13, m15, [cq+32*11] + pmulld m6, m15, [cq+32*12] + pmulld m14, m15, [cq+32*13] + pmulld m7, m15, [cq+32*14] + pmulld m15, [cq+32*15] + mova [cq], m7 + vpbroadcastd m7, [pd_2048] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + paddd m7, [cq] + REPX {psrad x, 12}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + packssdw m0, m8 + packssdw m1, m9 + packssdw m2, m10 + packssdw m3, m11 + packssdw m4, m12 + packssdw m5, m13 + packssdw m6, m14 + packssdw m13, m7, m15 + vpbroadcastd m8, [pw_1697x16] + REPX {IDTX16 x, 9, 8}, 0, 1, 2, 3, 4, 5, 6, 13 + vpbroadcastd m7, [pixel_10bpc_max] + vpbroadcastd m12, [pw_2048] + call .pass2_end + RET +ALIGN function_align +.pass2_end: + punpckhwd m9, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m13 + punpcklwd m6, m13 + punpckhwd m13, m4, m5 + punpcklwd m4, m5 + punpcklwd m5, m2, m3 + punpckhwd m2, m3 + punpckhdq m3, m0, m5 + punpckldq m0, m5 + punpckhdq m11, m9, m2 + punpckldq m9, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckldq m6, m13, m1 + punpckhdq m13, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m8, m9, m6 + punpckhqdq m9, m6 + punpcklqdq m10, m11, m13 + punpckhqdq m11, m13 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(iidentity_8x8_internal_10bpc).write_2x8x2_start + pmulhrsw m0, m12, m2 + pmulhrsw m1, m12, m3 + call m(iidentity_8x8_internal_10bpc).write_2x8x2_zero + pmulhrsw m0, m12, m8 + pmulhrsw m1, m12, m9 + lea dstq, [dstq+strideq*4] + call m(iidentity_8x8_internal_10bpc).write_2x8x2_zero + pmulhrsw m0, m12, m10 + pmulhrsw m1, m12, m11 + call m(iidentity_8x8_internal_10bpc).write_2x8x2_zero + ret + +INV_TXFM_8X16_FN dct, dct, 0, 12 +INV_TXFM_8X16_FN dct, identity, 35, 12 +INV_TXFM_8X16_FN dct, adst, 0, 12 +INV_TXFM_8X16_FN dct, flipadst, 0, 12 + +cglobal idct_8x16_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(idct_8x16_internal_10bpc).pass1 +.pass2: + lea r6, [rsp+32*4] + call .transpose + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + mova [cq+32* 8], m0 + mova [cq+32*10], m2 + mova [cq+32*12], m4 + mova [cq+32*14], m6 + pmaxsd m0, m12, [cq+32* 1] + pmaxsd m4, m12, m1 + pmaxsd m1, m12, [cq+32* 3] + pmaxsd m2, m12, [cq+32* 5] + pmaxsd m6, m12, m5 + pmaxsd m5, m12, m3 + pmaxsd m3, m12, [cq+32* 7] + pmaxsd m7, m12 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + vpbroadcastd m11, [pd_2048] + vpbroadcastd m14, [pd_2896] + call m(idct_8x16_internal_10bpc).main_oddhalf + pmaxsd m0, m12, [cq+32* 0] + pmaxsd m1, m12, [cq+32* 2] + pmaxsd m2, m12, [cq+32* 4] + pmaxsd m3, m12, [cq+32* 6] + pmaxsd m4, m12, [cq+32* 8] + pmaxsd m5, m12, [cq+32*10] + pmaxsd m6, m12, [cq+32*12] + pmaxsd m7, m12, [cq+32*14] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + vpbroadcastd m11, [pd_8] + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_16x8_internal_10bpc).pass1_rotations + REPX {psrad x, 4}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 +.end: + packssdw m0, m1 + packssdw m1, m2, m3 + packssdw m2, m4, m5 + packssdw m3, m6, m7 + packssdw m4, m8, m9 + packssdw m5, m10, m11 + packssdw m6, m12, m13 + packssdw m7, m14, m15 + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 + call m(idct_8x8_internal_12bpc).write_8x4_start + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m2, q3120 + vpermq m1, m3, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m4, q3120 + vpermq m1, m5, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m6, q3120 + vpermq m1, m7, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +ALIGN function_align +.transpose: + mova [cq+32* 8], m8 + mova [cq+32* 9], m9 + mova [cq+32*10], m10 + mova [cq+32*11], m11 + call m(idct_8x8_internal_12bpc).transpose_8x8 + mova [cq+32* 0], m0 + mova [cq+32* 1], m1 + mova [cq+32* 2], m2 + mova [cq+32* 3], m3 + mova [cq+32* 4], m4 + mova [cq+32* 5], m5 + mova [cq+32* 6], m6 + mova [cq+32* 7], m7 + mova m0, [cq+32* 8] + mova m1, [cq+32* 9] + mova m2, [cq+32*10] + mova m3, [cq+32*11] + mova m4, m12 + mova m5, m13 + mova m6, m14 + mova m7, m15 + jmp m(idct_8x8_internal_12bpc).transpose_8x8 + +INV_TXFM_8X16_FN adst, dct, 0, 12 +INV_TXFM_8X16_FN adst, adst, 0, 12 +INV_TXFM_8X16_FN adst, flipadst, 0, 12 +INV_TXFM_8X16_FN adst, identity, 35, 12 + +cglobal iadst_8x16_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iadst_8x16_internal_10bpc).pass1 +.pass2: + lea r6, [rsp+32*4] + call .pass2_main + call m(iadst_16x8_internal_10bpc).pass1_rotations +.pass2_end: + REPX {psrad x, 4 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 15}, m4, m5, m6, m7, m8, m9, m10, m11 + jmp m(idct_8x16_internal_12bpc).end +ALIGN function_align +.pass2_main: + call m(idct_8x16_internal_12bpc).transpose + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] + mova [cq+32* 8], m0 + mova [cq+32*11], m3 + mova [cq+32*12], m4 + mova [cq+32*15], m7 + pmaxsd m0, m13, [cq+32* 2] ; 2 + pmaxsd m3, m13, m1 ; 9 + pmaxsd m1, m13, m5 ; 13 + pmaxsd m4, m13, m2 ; 10 + pmaxsd m2, m13, [cq+32* 6] ; 6 + pmaxsd m5, m13, [cq+32* 5] ; 5 + pmaxsd m6, m13, m6 ; 14 + pmaxsd m7, m13, [cq+32* 1] ; 1 + REPX {pminsd x, m14}, m0, m1, m2, m3, m4, m5, m6, m7 + vpbroadcastd m12, [pd_2048] + vpbroadcastd m15, [pd_2896] + call m(iadst_16x8_internal_10bpc).main_part1 + pmaxsd m0, m13, [cq+32* 0] ; 0 + pmaxsd m1, m13, [cq+32*15] ; 15 + pmaxsd m2, m13, [cq+32* 4] ; 4 + pmaxsd m3, m13, [cq+32*11] ; 11 + pmaxsd m4, m13, [cq+32* 8] ; 8 + pmaxsd m5, m13, [cq+32* 7] ; 7 + pmaxsd m6, m13, [cq+32*12] ; 12 + pmaxsd m7, m13, [cq+32* 3] ; 3 + REPX {pminsd x, m14}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(iadst_16x8_internal_10bpc).main_part2 + vpbroadcastd m14, [pd_17408] + psrld m15, 11 ; pd_1 + psubd m13, m14, m15 ; pd_17407 + pslld m15, 3 ; pd_8 + ret + +INV_TXFM_8X16_FN flipadst, dct, 0, 12 +INV_TXFM_8X16_FN flipadst, adst, 0, 12 +INV_TXFM_8X16_FN flipadst, flipadst, 0, 12 +INV_TXFM_8X16_FN flipadst, identity, 35, 12 + +cglobal iflipadst_8x16_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iflipadst_8x16_internal_10bpc).pass1 +.pass2: + lea r6, [rsp+32*4] + call m(iadst_8x16_internal_12bpc).pass2_main + call m(iflipadst_16x8_internal_10bpc).pass1_rotations + jmp m(iadst_8x16_internal_12bpc).pass2_end + +INV_TXFM_8X16_FN identity, dct, 0, 12 +INV_TXFM_8X16_FN identity, adst, 0, 12 +INV_TXFM_8X16_FN identity, flipadst, 0, 12 +INV_TXFM_8X16_FN identity, identity, 0, 12 + +cglobal iidentity_8x16_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + jmp m(iidentity_8x16_internal_10bpc).pass1 +.pass2: + call .pass2_main + packssdw m0, m8 + packssdw m1, m9 + packssdw m2, m10 + packssdw m3, m11 + packssdw m4, m12 + packssdw m5, m13 + packssdw m6, m14 + packssdw m13, m7, m15 + vpbroadcastd m7, [pixel_12bpc_max] + vpbroadcastd m12, [pw_16384] + call m(iidentity_8x16_internal_10bpc).pass2_end + RET +ALIGN function_align +.pass2_main: + mova [cq], m7 + vpbroadcastd m7, [clip_18b_min] + REPX {pmaxsd x, m7}, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + pmaxsd m7, [cq] + mova [cq], m15 + vpbroadcastd m15, [clip_18b_max] + REPX {pminsd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + pminsd m15, [cq] + mova [cq], m7 + vpbroadcastd m7, [pd_5793] + REPX {pmulld x, m7}, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + pmulld m7, [cq] + mova [cq], m15 + vpbroadcastd m15, [pd_1024] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + paddd m15, [cq] + REPX {psrad x, 14}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + ret + +%macro INV_TXFM_16X4_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 16x4, %3 +%ifidn %1_%2, dct_dct + vpbroadcastd m3, [dconly_%3bpc] +%if %3 = 10 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 4 +.dconly2: + add r6d, 384 + sar r6d, 9 +.dconly3: + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + movd xm0, r6d + paddsw xm0, xm3 + vpbroadcastw m0, xm0 +.dconly_loop: + paddsw m1, m0, [dstq+strideq*0] + paddsw m2, m0, [dstq+strideq*1] + psubusw m1, m3 + psubusw m2, m3 + mova [dstq+strideq*0], m1 + mova [dstq+strideq*1], m2 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%else + jmp m(inv_txfm_add_dct_dct_16x4_10bpc).dconly +%endif +%endif +%endmacro + +INV_TXFM_16X4_FN dct, dct +INV_TXFM_16X4_FN dct, identity +INV_TXFM_16X4_FN dct, adst +INV_TXFM_16X4_FN dct, flipadst + +cglobal idct_16x4_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_18b_min] + vpbroadcastd m9, [clip_18b_max] +.pass1: + vbroadcasti128 m0, [cq+16* 0] + vbroadcasti128 m4, [cq+16* 4] + vbroadcasti128 m1, [cq+16* 2] + vbroadcasti128 m7, [cq+16* 6] + vbroadcasti128 m5, [cq+16*10] + vbroadcasti128 m2, [cq+16* 8] + vbroadcasti128 m6, [cq+16*12] + vbroadcasti128 m3, [cq+16*14] + shufpd m0, m4, 0x0c ; 0 4 + shufpd m1, m5, 0x0c ; 2 10 + shufpd m2, m6, 0x0c ; 8 12 + shufpd m3, m7, 0x0c ; 14 6 + call .pass1_main + vbroadcasti128 m10, [cq+16* 1] + vbroadcasti128 m4, [cq+16* 5] + vbroadcasti128 m11, [cq+16*15] + vbroadcasti128 m5, [cq+16*11] + shufpd m10, m4, 0x0c ; 1 5 + shufpd m11, m5, 0x0c ; 15 11 + vbroadcasti128 m5, [cq+16* 9] + vbroadcasti128 m4, [cq+16*13] + shufpd m5, m4, 0x0c ; 9 13 + vbroadcasti128 m6, [cq+16* 7] + vbroadcasti128 m4, [cq+16* 3] + shufpd m6, m4, 0x0c ; 7 3 + call .pass1_main2 + pcmpeqd m4, m4 + REPX {psubd x, m4}, m0, m1, m2, m3 + call .pass1_main3 + REPX {psrad x, 1 }, m0, m1, m2, m3, m4, m5, m6, m7 + jmp tx2q +.pass2: + call .transpose_4x16_packed + lea r6, [deint_shuf+128] + call m(idct_16x4_internal_8bpc).main +.end: + vpbroadcastd m4, [pw_2048] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + vpbroadcastd m5, [pixel_10bpc_max] +.end2: + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] +.end3: + lea r6, [dstq+strideq*2] + paddw m2, [r6 +strideq*0] + paddw m3, [r6 +strideq*1] + pxor m4, m4 + REPX {mova [cq+32*x], m4}, 0, 1, 2, 3, 4, 5, 6, 7 + REPX {pmaxsw x, m4}, m0, m1, m2, m3 + REPX {pminsw x, m5}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [r6 +strideq*0], m2 + mova [r6 +strideq*1], m3 + RET +ALIGN function_align +.pass1_main: + vpbroadcastd m7, [pd_2048] + call m(idct_8x4_internal_10bpc).main + psubd m3, m0, m4 ; idct8 out7 out6 + paddd m0, m4 ; idct8 out0 out1 + paddd m1, m2, m5 ; idct8 out3 out2 + psubd m2, m5 ; idct8 out4 out5 + ret +ALIGN function_align +.pass1_main2: + ITX_MULSUB_2D 10, 11, 4, 12, 13, 7, 401_1931, 4076_3612, 1 + ITX_MULSUB_2D 5, 6, 4, 12, 13, 7, 3166_3920, 2598_1189, 1 + vbroadcasti128 m12, [pd_3784_m3784] + psubd m4, m10, m5 + paddd m10, m5 ; t8 t11 + psignd m4, m12 ; t9 t10 + psubd m5, m11, m6 + paddd m11, m6 ; t15 t12 + psignd m5, m12 ; t14 t13 + vpbroadcastd m6, [pd_1567] + vpbroadcastd m13, [pd_3784] + REPX {pmaxsd x, m8}, m5, m4 + REPX {pminsd x, m9}, m5, m4 + pmulld m12, m5 + pmulld m5, m6 + vbroadcasti128 m6, [pd_1567_m1567] + pmulld m13, m4 + pmulld m4, m6 + REPX {pmaxsd x, m8}, m10, m11, m0, m1 + REPX {pminsd x, m9}, m10, m11, m0, m1 + paddd m12, m7 + paddd m5, m7 + paddd m4, m12 + psubd m5, m13 + psrad m4, 12 ; t14a t10a + psrad m5, 12 ; t9a t13a + vpbroadcastd m12, [pd_2896] + punpckhqdq m6, m11, m5 + punpcklqdq m11, m4 + punpckhqdq m4, m10, m4 + punpcklqdq m10, m5 + psubd m5, m11, m6 ; t12a t13 + paddd m11, m6 ; t15a t14 + psubd m6, m10, m4 ; t11a t10 + paddd m10, m4 ; t8a t9 + REPX {pmaxsd x, m8}, m5, m6 + REPX {pminsd x, m9}, m5, m6 + pmulld m5, m12 + pmulld m6, m12 + REPX {pmaxsd x, m8}, m2, m3, m11, m10 + REPX {pminsd x, m9}, m2, m3, m11, m10 + ret +ALIGN function_align +.pass1_main3: + paddd m5, m7 + psubd m4, m5, m6 + paddd m5, m6 + psrad m4, 12 ; t11 t10a + psrad m5, 12 ; t12 t13a + psubd m7, m0, m11 ; out15 out14 + paddd m0, m11 ; out0 out1 + psubd m6, m1, m5 ; out12 out13 + paddd m1, m5 ; out3 out2 + psubd m5, m2, m4 ; out11 out10 + paddd m2, m4 ; out4 out5 + psubd m4, m3, m10 ; out8 out9 + paddd m3, m10 ; out7 out6 + REPX {pshufd x, x, q1032}, m1, m3, m5, m7 + ret +ALIGN function_align +.transpose_4x16_packed: + vbroadcasti128 m8, [deint_shuf] + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + REPX {pshufb x, m8}, m0, m2, m4, m6 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpckhqdq m2, m4, m6 + punpcklqdq m4, m6 + vperm2i128 m3, m1, m2, 0x31 + vinserti128 m1, xm2, 1 + vperm2i128 m2, m0, m4, 0x31 + vinserti128 m0, xm4, 1 + ret + +INV_TXFM_16X4_FN adst, dct +INV_TXFM_16X4_FN adst, adst +INV_TXFM_16X4_FN adst, flipadst +INV_TXFM_16X4_FN adst, identity + +cglobal iadst_16x4_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + call m(iadst_4x16_internal_10bpc).main + psrad m11, 11 ; pd_1 + REPX {paddd x, m11}, m0, m1, m2, m3 + paddd m4, m5, m11 + paddd m5, m6, m11 + paddd m6, m7, m11 + paddd m7, m8, m11 +.pass1_end: + REPX {pshufd x, x, q1032}, m0, m2, m4, m6 + REPX {psrad x, 1}, m0, m1, m2, m3, m4, m5, m6, m7 + jmp tx2q +.pass2: + call m(idct_16x4_internal_10bpc).transpose_4x16_packed + lea r6, [deint_shuf+128] + call m(iadst_16x4_internal_8bpc).main + jmp m(idct_16x4_internal_10bpc).end +ALIGN function_align +.main: + vpbroadcastd m6, [pd_1321] + mova m0, [cq+32*0] + mova m1, [cq+32*1] + vpbroadcastd m7, [pd_2482] + mova m2, [cq+32*6] + mova m3, [cq+32*7] + pmulld m4, m0, m6 + pmulld m5, m1, m6 ; 1321*in0 + pmulld m9, m2, m7 + pmulld m8, m3, m7 ; 2482*in3 + paddd m4, m9 + paddd m8, m5 ; 1321*in0 + 2482*in3 + pmulld m5, m0, m7 + pmulld m9, m1, m7 ; 2482*in0 + paddd m0, m2 + paddd m1, m3 ; in0 + in3 + paddd m7, m6 ; pd_3803 + pmulld m2, m7 + pmulld m3, m7 ; 3803*in3 + psubd m5, m2 + psubd m9, m3 ; 2482*in0 - 3803*in3 + mova m2, [cq+32*4] + pmulld m10, m7, m2 + pmulld m3, m6, m2 + psubd m2, m0 + mova m0, [cq+32*5] + pmulld m7, m0 ; 3803*in2 + pmulld m6, m0 ; 1321*in2 + psubd m0, m1 ; in2 - in0 - in3 + vpbroadcastd m1, [pd_m3344] + paddd m4, m10 + paddd m7, m8 ; t0 + psubd m5, m3 + psubd m9, m6 ; t1 + pmulld m2, m1 + pmulld m0, m1 ; t2 + pmulld m3, m1, [cq+32*2] + pmulld m1, [cq+32*3] ; -t3 + ret +ALIGN function_align +.main_end: + ; expects: m6 = rnd + paddd m5, m6 + paddd m9, m6 + paddd m10, m4, m5 + paddd m4, m6 + paddd m8, m7, m6 + paddd m7, m9 + psubd m4, m3 ; out0 (unshifted) + psubd m5, m3 ; out1 (unshifted) + paddd m2, m6 ; out2 (unshifted) + paddd m3, m10 ; out3 (unshifted) + psubd m8, m1 ; out4 (unshifted) + psubd m9, m1 ; out5 (unshifted) + paddd m6, m0 ; out6 (unshifted) + paddd m7, m1 ; out7 (unshifted) + ret + +INV_TXFM_16X4_FN flipadst, dct +INV_TXFM_16X4_FN flipadst, adst +INV_TXFM_16X4_FN flipadst, flipadst +INV_TXFM_16X4_FN flipadst, identity + +cglobal iflipadst_16x4_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + call m(iadst_4x16_internal_10bpc).main + psrad m11, 11 ; pd_1 + paddd m4, m3, m11 + paddd m3, m5, m11 + paddd m5, m2, m11 + paddd m2, m6, m11 + paddd m6, m1, m11 + paddd m1, m7, m11 + paddd m7, m0, m11 + paddd m0, m8, m11 + jmp m(iadst_16x4_internal_10bpc).pass1_end +.pass2: + call m(idct_16x4_internal_10bpc).transpose_4x16_packed + lea r6, [deint_shuf+128] + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m4, [pw_2048] + pmulhrsw m5, m3, m4 + pmulhrsw m6, m2, m4 + pmulhrsw m2, m1, m4 + pmulhrsw m3, m0, m4 + paddw m0, m5, [dstq+strideq*0] + paddw m1, m6, [dstq+strideq*1] + vpbroadcastd m5, [pixel_10bpc_max] + jmp m(idct_16x4_internal_10bpc).end3 + +INV_TXFM_16X4_FN identity, dct +INV_TXFM_16X4_FN identity, adst +INV_TXFM_16X4_FN identity, flipadst +INV_TXFM_16X4_FN identity, identity + +cglobal iidentity_16x4_internal_10bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m8, [pd_5793] + vpermq m0, [cq+32*0], q3120 ; 0 1 + vpermq m1, [cq+32*1], q3120 ; 2 3 + vpermq m2, [cq+32*2], q3120 ; 4 5 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m4, [cq+32*4], q3120 ; 8 9 + vpermq m5, [cq+32*5], q3120 ; a b + vpermq m6, [cq+32*6], q3120 ; c d + vpermq m7, [cq+32*7], q3120 ; e f + vpbroadcastd m9, [pd_3072] + REPX {pmulld x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {paddd x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12}, m0, m1, m2, m3, m4, m5, m6, m7 + jmp tx2q +.pass2: + call m(idct_16x4_internal_10bpc).transpose_4x16_packed + vpbroadcastd m7, [pw_1697x8] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(idct_16x4_internal_10bpc).end + +INV_TXFM_16X4_FN dct, dct, 12 +INV_TXFM_16X4_FN dct, identity, 12 +INV_TXFM_16X4_FN dct, adst, 12 +INV_TXFM_16X4_FN dct, flipadst, 12 + +cglobal idct_16x4_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m8, [clip_20b_min] + vpbroadcastd m9, [clip_20b_max] + jmp m(idct_16x4_internal_10bpc).pass1 +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + ; deinterleave + REPX {pshufd x, x, q3120}, m0, m1, m2, m3, m4, m5, m6, m7 + ; transpose + punpcklqdq m8, m0, m1 + punpckhqdq m0, m1 + punpcklqdq m9, m2, m3 + punpckhqdq m2, m3 + punpcklqdq m10, m4, m5 + punpckhqdq m4, m5 + punpcklqdq m11, m6, m7 + punpckhqdq m6, m7 + vperm2i128 m3, m0, m2, 0x31 ; out6 + vperm2i128 m1, m0, m2, 0x20 ; out2 + vperm2i128 m7, m4, m6, 0x31 ; out7 + vperm2i128 m5, m4, m6, 0x20 ; out3 + vperm2i128 m13, m10, m11, 0x31 ; out5 + vperm2i128 m12, m10, m11, 0x20 ; out1 + vperm2i128 m11, m8, m9, 0x31 ; out4 + vperm2i128 m10, m8, m9, 0x20 ; out0 + call m(idct_4x16_internal_10bpc).pass1_main + pmulld m0, m6, m10 + pmulld m2, m6, m11 + pmulld m4, m6, m12 + pmulld m6, m13 + vpbroadcastd m10, [pd_17408] + call m(idct_4x16_internal_10bpc).pass1_main2 + REPX {psrad x, 4}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + vpbroadcastd m5, [pixel_12bpc_max] + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 + jmp m(idct_16x4_internal_10bpc).end2 + +INV_TXFM_16X4_FN adst, dct, 12 +INV_TXFM_16X4_FN adst, adst, 12 +INV_TXFM_16X4_FN adst, flipadst, 12 +INV_TXFM_16X4_FN adst, identity, 12 + +cglobal iadst_16x4_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iadst_16x4_internal_10bpc).pass1 +.pass2: + call .pass2_main + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + jmp m(idct_16x4_internal_10bpc).end2 +ALIGN function_align +.pass2_main: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m6, m7 + pmaxsd m8, m4, m12 + pmaxsd m9, m5, m12 + REPX {pminsd x, m13}, m0, m1, m2, m3 + call m(iadst_8x4_internal_12bpc).transpose_4x8 + mova [cq+32*0], m0 + mova [cq+32*2], m1 + mova [cq+32*4], m2 + mova [cq+32*6], m3 + pminsd m0, m8, m13 + pminsd m1, m9, m13 + pminsd m2, m6, m13 + pminsd m3, m7, m13 + call m(iadst_8x4_internal_12bpc).transpose_4x8 + mova [cq+32*1], m0 + mova [cq+32*3], m1 + mova [cq+32*5], m2 + mova [cq+32*7], m3 + call m(iadst_16x4_internal_10bpc).main + vpbroadcastd m6, [pd_2048] + call m(iadst_16x4_internal_10bpc).main_end + psrad m0, m4, 15 + psrad m1, m5, 15 + psrad m2, 15 + psrad m3, 15 + psrad m4, m8, 15 + psrad m5, m9, 15 + psrad m6, 15 + psrad m7, 15 + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + vpbroadcastd m4, [pw_16384] + vpbroadcastd m5, [pixel_12bpc_max] + ret + +INV_TXFM_16X4_FN flipadst, dct, 12 +INV_TXFM_16X4_FN flipadst, adst, 12 +INV_TXFM_16X4_FN flipadst, flipadst, 12 +INV_TXFM_16X4_FN flipadst, identity, 12 + +cglobal iflipadst_16x4_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(iflipadst_16x4_internal_10bpc).pass1 +.pass2: + call m(iadst_16x4_internal_12bpc).pass2_main + vpermq m7, m0, q3120 + vpermq m6, m1, q3120 + vpermq m1, m2, q3120 + vpermq m0, m3, q3120 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + pmulhrsw m2, m6, m4 + pmulhrsw m3, m7, m4 + jmp m(idct_16x4_internal_10bpc).end2 + +INV_TXFM_16X4_FN identity, dct, 12 +INV_TXFM_16X4_FN identity, adst, 12 +INV_TXFM_16X4_FN identity, flipadst, 12 +INV_TXFM_16X4_FN identity, identity, 12 + +cglobal iidentity_16x4_internal_12bpc, 0, 7, 14, dst, stride, c, eob, tx2 + vpbroadcastd m8, [pd_1697] + vpermq m0, [cq+32*0], q3120 ; 0 1 + vpermq m1, [cq+32*1], q3120 ; 2 3 + vpermq m2, [cq+32*2], q3120 ; 4 5 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpbroadcastd m9, [pd_3072] + pmulld m4, m8, m0 + pmulld m5, m8, m1 + pmulld m6, m8, m2 + pmulld m7, m8, m3 + vpermq m10, [cq+32*4], q3120 ; 8 9 + vpermq m11, [cq+32*5], q3120 ; a b + vpermq m12, [cq+32*6], q3120 ; c d + vpermq m13, [cq+32*7], q3120 ; e f + REPX {paddd x, m9}, m4, m5, m6, m7 + REPX {psrad x, 12}, m4, m5, m6, m7 + paddd m0, m4 + pmulld m4, m8, m10 + paddd m1, m5 + pmulld m5, m8, m11 + paddd m2, m6 + pmulld m6, m8, m12 + paddd m3, m7 + pmulld m7, m8, m13 + REPX {paddd x, m9}, m4, m5, m6, m7 + REPX {psrad x, 12}, m4, m5, m6, m7 + paddd m4, m10 + paddd m5, m11 + paddd m6, m12 + paddd m7, m13 + jmp tx2q +.pass2: + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + vpbroadcastd m8, [pd_5793] + vpbroadcastd m9, [pd_2048] + REPX {pmulld x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {paddd x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 15}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_16x4_internal_10bpc).transpose_4x16_packed + vpbroadcastd m4, [pw_16384] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + vpbroadcastd m5, [pixel_12bpc_max] + jmp m(idct_16x4_internal_10bpc).end2 + +%macro INV_TXFM_16X8_FN 2-3 10 ; type1, type2, bitdepth + INV_TXFM_FN %1, %2, 0, 16x8, %3 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_%3bpc] + mov [cq], eobd ; 0 + or r3d, 8 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + jmp m(inv_txfm_add_dct_dct_16x4_10bpc).dconly2 +%endif +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, identity +INV_TXFM_16X8_FN dct, adst +INV_TXFM_16X8_FN dct, flipadst + +cglobal idct_16x8_internal_10bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + vpbroadcastd m14, [pd_2896] + pmulld m0, m14, [cq+32* 1] + pmulld m1, m14, [cq+32* 3] + pmulld m2, m14, [cq+32* 5] + pmulld m3, m14, [cq+32* 7] + pmulld m4, m14, [cq+32* 9] + pmulld m5, m14, [cq+32*11] + pmulld m6, m14, [cq+32*13] + pmulld m7, m14, [cq+32*15] + vpbroadcastd m11, [pd_2048] + lea r6, [rsp+32*4] + call m(idct_8x16_internal_10bpc).main_oddhalf_rect2 + pmulld m0, m14, [cq+32* 0] + pmulld m1, m14, [cq+32* 2] + pmulld m2, m14, [cq+32* 4] + pmulld m3, m14, [cq+32* 6] + pmulld m4, m14, [cq+32* 8] + pmulld m5, m14, [cq+32*10] + pmulld m6, m14, [cq+32*12] + pmulld m7, m14, [cq+32*14] + call m(idct_8x8_internal_10bpc).main_rect2 + call m(idct_8x16_internal_10bpc).main_evenhalf + psrld m11, 11 ; pd_1 + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + call .pass1_rotations + REPX {psrad x, 1}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call .transpose + call m(idct_16x8_internal_8bpc).main + vpbroadcastd m10, [pw_2048] +.end: + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pmulhrsw m2, m10 + pmulhrsw m3, m10 + call .write_16x4_start +.end2: + pmulhrsw m0, m4, m10 + pmulhrsw m1, m5, m10 + pmulhrsw m2, m6, m10 + pmulhrsw m3, m7, m10 + call .write_16x4_zero + RET +ALIGN function_align +.pass1_rotations: + mova m14, [r6-32*4] + mova m13, [r6-32*3] + mova m12, [r6-32*2] + mova m11, [r6-32*1] + mova m10, [r6+32*0] + mova m9, [r6+32*1] + mova m8, [r6+32*2] + psubd m15, m0, m14 ; out15 + paddd m0, m14 ; out0 + psubd m14, m1, m13 ; out14 + paddd m1, m13 ; out1 + psubd m13, m2, m12 ; out13 + paddd m2, m12 ; out2 + psubd m12, m3, m11 ; out12 + paddd m3, m11 ; out3 + psubd m11, m4, m10 ; out11 + paddd m4, m10 ; out4 + psubd m10, m5, m9 ; out10 + paddd m5, m9 ; out5 + psubd m9, m6, m8 ; out9 + paddd m6, m8 ; out6 + psubd m8, m7, [r6+32*3] ; out8 + paddd m7, [r6+32*3] ; out7 + ret +ALIGN function_align +.transpose: + lea r6, [deint_shuf+128] +.transpose2: + packssdw m0, m8 + packssdw m1, m9 + packssdw m2, m10 + packssdw m3, m11 + packssdw m4, m12 + packssdw m5, m13 + packssdw m6, m14 + packssdw m7, m15 +.transpose3: + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + punpckhwd m3, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m6, m7 + punpcklwd m6, m7 + punpckhdq m7, m4, m6 + punpckldq m4, m6 + punpckldq m6, m8, m2 + punpckhdq m8, m2 + punpckhdq m2, m0, m1 + punpckldq m0, m1 + punpckhdq m1, m3, m5 + punpckldq m3, m5 + punpcklqdq m5, m6, m3 + punpckhqdq m6, m3 + punpckhqdq m3, m2, m7 + punpcklqdq m2, m7 + punpcklqdq m7, m8, m1 + punpckhqdq m8, m1 + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + vperm2i128 m4, m0, m5, 0x31 + vinserti128 m0, xm5, 1 + vperm2i128 m5, m1, m6, 0x31 + vinserti128 m1, xm6, 1 + vperm2i128 m6, m2, m7, 0x31 + vinserti128 m2, xm7, 1 + vperm2i128 m7, m3, m8, 0x31 + vinserti128 m3, xm8, 1 + ret +ALIGN function_align +.write_16x4_start: + vpbroadcastd m9, [pixel_10bpc_max] + lea r3, [strideq*3] + pxor m8, m8 +.write_16x4_zero: + REPX {mova [cq+32*x], m8}, 0, 1, 2, 3, 4, 5, 6, 7 + add cq, 32*8 +.write_16x4: + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] + paddw m2, [dstq+strideq*2] + paddw m3, [dstq+r3 ] + REPX {pmaxsw x, m8}, m0, m1, m2, m3 + REPX {pminsw x, m9}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r3 ], m3 + lea dstq, [dstq+strideq*4] + ret + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, adst +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, identity + +cglobal iadst_16x8_internal_10bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] +.pass1: + lea r6, [rsp+32*4] + call .main + vpbroadcastd m14, [pd_3072] + psrld m15, 11 ; pd_1 + psubd m13, m14, m15 ; pd_3071 + call .pass1_rotations +.pass1_end: + REPX {psrad x, 1 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 12}, m4, m5, m6, m7, m8, m9, m10, m11 + jmp tx2q +.pass2: + call m(idct_16x8_internal_10bpc).transpose + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass2_end + vpbroadcastd m10, [pw_2048] + pxor m11, m11 + psubw m11, m10 + pmulhrsw m0, m10 + pmulhrsw m1, m11 + pmulhrsw m2, m10 + pmulhrsw m3, m11 + call m(idct_16x8_internal_10bpc).write_16x4_start + pmulhrsw m0, m4, m10 + pmulhrsw m1, m5, m11 + pmulhrsw m2, m6, m10 + pmulhrsw m3, m7, m11 + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET +ALIGN function_align +.pass1_rotations: + paddd m0, m15 + psubd m1, m15, m1 + paddd m2, m15 + psubd m3, m15, m3 + paddd m4, m14 + psubd m5, m13, m5 + paddd m6, m14 + psubd m7, m13, m7 + paddd m8, m14, m9 + psubd m9, m13, m10 + paddd m10, m14, m11 + psubd m11, m13, m12 + paddd m12, m15, [r6-32*1] + psubd m13, m15, [r6-32*2] + paddd m14, m15, [r6-32*3] + psubd m15, [r6-32*4] + ret +ALIGN function_align +.main: + ; expects: m13 = clip_min m14 = clip_max + vpbroadcastd m15, [pd_2896] + pmulld m0, m15, [cq+32* 2] + pmulld m1, m15, [cq+32*13] + pmulld m2, m15, [cq+32* 6] + pmulld m3, m15, [cq+32* 9] + pmulld m4, m15, [cq+32*10] + pmulld m5, m15, [cq+32* 5] + pmulld m6, m15, [cq+32*14] + pmulld m7, m15, [cq+32* 1] + vpbroadcastd m12, [pd_2048] + REPX {paddd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 + call .main_part1 + pmulld m0, m15, [cq+32* 0] + pmulld m1, m15, [cq+32*15] + pmulld m2, m15, [cq+32* 4] + pmulld m3, m15, [cq+32*11] + pmulld m4, m15, [cq+32* 8] + pmulld m5, m15, [cq+32* 7] + pmulld m6, m15, [cq+32*12] + pmulld m7, m15, [cq+32* 3] + REPX {paddd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 +.main_part2: + ITX_MULSUB_2D 1, 0, 8, 9, 10, 12, 201, 4091 + ITX_MULSUB_2D 3, 2, 8, 9, 10, 12, 1751, 3703 + ITX_MULSUB_2D 5, 4, 8, 9, 10, 12, 3035, 2751 + ITX_MULSUB_2D 7, 6, 8, 9, 10, 12, 3857, 1380 + psubd m8, m0, m4 ; t8a + paddd m0, m4 ; t0a + psubd m4, m1, m5 ; t9a + paddd m1, m5 ; t1a + psubd m5, m2, m6 ; t12a + paddd m2, m6 ; t4a + psubd m6, m3, m7 ; t13a + paddd m7, m3 ; t5a + REPX {pmaxsd x, m13}, m8, m4, m5, m6, m0, m1, m2, m7 + REPX {pminsd x, m14}, m8, m4, m5, m6, m0, m1, m2, m7 + vpbroadcastd m11, [pd_4017] + vpbroadcastd m10, [pd_799] + ITX_MULSUB_2D 8, 4, 3, 9, _, 12, 10, 11 + ITX_MULSUB_2D 6, 5, 3, 9, _, 12, 11, 10 + psubd m3, m0, m2 ; t4 + paddd m0, m2 ; t0 + psubd m2, m1, m7 ; t5 + paddd m1, m7 ; t1 + psubd m7, m4, m6 ; t12a + paddd m4, m6 ; t8a + psubd m6, m8, m5 ; t13a + paddd m5, m8 ; t9a + REPX {pmaxsd x, m13}, m3, m2, m7, m6, m0, m1, m4, m5 + REPX {pminsd x, m14}, m3, m2, m7, m6, m0, m1, m4, m5 + vpbroadcastd m11, [pd_3784] + vpbroadcastd m10, [pd_1567] + ITX_MULSUB_2D 3, 2, 8, 9, _, 12, 10, 11 + ITX_MULSUB_2D 7, 6, 8, 9, _, 12, 10, 11 + pminsd m10, m14, [r6-32*4] ; t2 + pminsd m8, m14, [r6-32*3] ; t3 + psubd m9, m0, m10 ; t2a + paddd m0, m10 ; out0 + psubd m10, m1, m8 ; t3a + paddd m1, m8 ; -out15 + pmaxsd m9, m13 + pmaxsd m10, m13 + pminsd m9, m14 + pminsd m10, m14 + mova [r6-32*4], m1 + mova m11, [r6-32*1] ; t7a + mova m1, [r6-32*2] ; t6a + psubd m8, m3, m11 ; t7 + paddd m11, m3 ; out12 + paddd m3, m2, m1 ; -out3 + psubd m2, m1 ; t6 + pmaxsd m8, m13 + pmaxsd m2, m13 + pminsd m8, m14 + pminsd m2, m14 + mova [r6-32*1], m11 + mova [r6-32*3], m2 + mova m1, [r6+32*3] ; t15 + mova m2, [r6+32*2] ; t14 + paddd m12, m7, m1 ; -out13 + psubd m7, m1 ; t15a + psubd m11, m6, m2 ; t14a + paddd m2, m6 ; out2 + pmaxsd m7, m13 + pmaxsd m11, m13 + pminsd m7, m14 + pminsd m11, m14 + mova [r6-32*2], m12 + pminsd m1, m14, [r6+32*0] ; t10a + pminsd m12, m14, [r6+32*1] ; t11a + psubd m6, m4, m1 ; t10 + paddd m1, m4 ; -out1 + psubd m4, m5, m12 ; t11 + paddd m5, m12 ; out14 + vpbroadcastd m12, [pd_1448] + pmaxsd m6, m13 + pmaxsd m4, m13 + pminsd m6, m14 + pminsd m4, m14 + REPX {pmulld x, m12}, m9, m10, m8, m7, m11, m6, m4 + pmulld m12, [r6-32*3] ; t6 + mova [r6-32*3], m5 + paddd m5, m11, m7 ; -out5 (unshifted) + psubd m11, m7 ; out10 (unshifted) + paddd m7, m9, m10 ; -out7 (unshifted) + psubd m9, m10 ; out8 (unshifted) + psubd m10, m6, m4 ; -out9 (unshifted) + paddd m6, m4 ; out6 (unshifted) + paddd m4, m12, m8 ; out4 (unshifted) + psubd m12, m8 ; -out11 (unshifted) + ret +.main_part1: + ITX_MULSUB_2D 1, 0, 8, 9, 10, 12, 995, 3973 + ITX_MULSUB_2D 3, 2, 8, 9, 10, 12, 2440, 3290 + ITX_MULSUB_2D 5, 4, 8, 9, 10, 12, 3513, 2106 + ITX_MULSUB_2D 7, 6, 8, 9, 10, 12, 4052, 601 + psubd m8, m0, m4 ; t10a + paddd m0, m4 ; t2a + psubd m4, m1, m5 ; t11a + paddd m1, m5 ; t3a + psubd m5, m2, m6 ; t14a + paddd m2, m6 ; t6a + psubd m6, m3, m7 ; t15a + paddd m7, m3 ; t7a + REPX {pmaxsd x, m13}, m8, m4, m5, m6, m0, m1, m2, m7 + REPX {pminsd x, m14}, m8, m4, m5, m6, m0, m1, m2, m7 + vpbroadcastd m11, [pd_2276] + vpbroadcastd m10, [pd_3406] + ITX_MULSUB_2D 8, 4, 3, 9, _, 12, 10, 11 + ITX_MULSUB_2D 6, 5, 3, 9, _, 12, 11, 10 + psubd m3, m0, m2 ; t6 + paddd m0, m2 ; t2 + psubd m2, m1, m7 ; t7 + paddd m1, m7 ; t3 + psubd m7, m4, m6 ; t14a + paddd m4, m6 ; t10a + psubd m6, m8, m5 ; t15a + paddd m5, m8 ; t11a + REPX {pmaxsd x, m13}, m3, m2, m7, m6, m0, m1, m4, m5 + REPX {pminsd x, m14}, m3, m2, m7, m6 ; clip the rest later + vpbroadcastd m11, [pd_1567] + vpbroadcastd m10, [pd_3784] + ITX_MULSUB_2D 2, 3, 8, 9, _, 12, 10, 11 + ITX_MULSUB_2D 6, 7, 8, 9, _, 12, 10, 11 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6-32*2], m2 + mova [r6-32*1], m3 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + ret + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst +INV_TXFM_16X8_FN flipadst, identity + +cglobal iflipadst_16x8_internal_10bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] +.pass1: + lea r6, [rsp+32*4] + call m(iadst_16x8_internal_10bpc).main + vpbroadcastd m14, [pd_3072] + psrld m15, 11 + psubd m13, m14, m15 + call .pass1_rotations + jmp m(iadst_16x8_internal_10bpc).pass1_end +.pass2: + call m(idct_16x8_internal_10bpc).transpose + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass2_end + vpbroadcastd m10, [pw_2048] + pxor m11, m11 + psubw m11, m10 + mova m12, m0 + pmulhrsw m0, m7, m11 + mova m7, m1 + pmulhrsw m1, m6, m10 + mova m6, m2 + pmulhrsw m2, m5, m11 + mova m5, m3 + pmulhrsw m3, m4, m10 + call m(idct_16x8_internal_10bpc).write_16x4_start + pmulhrsw m0, m5, m11 + pmulhrsw m1, m6, m10 + pmulhrsw m2, m7, m11 + pmulhrsw m3, m12, m10 + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET +ALIGN function_align +.pass1_rotations: + psubd m8, m13, m7 + paddd m7, m14, m9 + paddd m9, m14, m6 + psubd m6, m13, m10 + psubd m10, m13, m5 + paddd m5, m14, m11 + paddd m11, m14, m4 + psubd m4, m13, m12 + psubd m12, m15, m3 + paddd m3, m15, [r6-32*1] + paddd m13, m15, m2 + psubd m2, m15, [r6-32*2] + psubd m14, m15, m1 + mova m1, m15 + paddd m15, m0 + psubd m0, m1, [r6-32*4] + paddd m1, [r6-32*3] + ret + +INV_TXFM_16X8_FN identity, dct +INV_TXFM_16X8_FN identity, adst +INV_TXFM_16X8_FN identity, flipadst +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_10bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 +.pass1: + vpbroadcastd m15, [pd_2896] + pmulld m0, m15, [cq+32* 0] + pmulld m1, m15, [cq+32* 1] + pmulld m2, m15, [cq+32* 2] + pmulld m3, m15, [cq+32* 3] + pmulld m4, m15, [cq+32* 4] + pmulld m5, m15, [cq+32* 5] + pmulld m6, m15, [cq+32* 6] + pmulld m7, m15, [cq+32* 7] + pmulld m8, m15, [cq+32* 8] + pmulld m9, m15, [cq+32* 9] + pmulld m10, m15, [cq+32*10] + pmulld m11, m15, [cq+32*11] + pmulld m12, m15, [cq+32*12] + pmulld m13, m15, [cq+32*13] + pmulld m14, m15, [cq+32*14] + pmulld m15, [cq+32*15] + mova [rsp], m7 + vpbroadcastd m7, [pd_2048] + REPX {paddd x, m7 }, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + paddd m7, [rsp] + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + mova [rsp], m15 + vpbroadcastd m15, [pd_5793] + REPX {pmulld x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + pmulld m15, [rsp] + mova [rsp], m7 + vpbroadcastd m7, [pd_3072] + REPX {paddd x, m7 }, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + paddd m7, [rsp] + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call m(idct_16x8_internal_10bpc).transpose + vpbroadcastd m10, [pw_4096] + jmp m(idct_16x8_internal_10bpc).end + +INV_TXFM_16X8_FN dct, dct, 12 +INV_TXFM_16X8_FN dct, identity, 12 +INV_TXFM_16X8_FN dct, adst, 12 +INV_TXFM_16X8_FN dct, flipadst, 12 + +cglobal idct_16x8_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(idct_16x8_internal_10bpc).pass1 +.pass2: + call .pass2_main + RET +ALIGN function_align +.pass2_main: + call m(idct_8x16_internal_12bpc).transpose + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m11, [pd_2048] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x8_internal_12bpc).round_shift4 + mova [cq+32* 8], m0 + mova [cq+32* 9], m1 + mova [cq+32*10], m2 + mova [cq+32*11], m3 + mova [cq+32*12], m4 + mova [cq+32*13], m5 + mova [cq+32*14], m6 + mova [cq+32*15], m7 + pmaxsd m0, m12, [cq+32*0] + pmaxsd m1, m12, [cq+32*1] + pmaxsd m2, m12, [cq+32*2] + pmaxsd m3, m12, [cq+32*3] + pmaxsd m4, m12, [cq+32*4] + pmaxsd m5, m12, [cq+32*5] + pmaxsd m6, m12, [cq+32*6] + pmaxsd m7, m12, [cq+32*7] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x8_internal_12bpc).round_shift4 +.end: + packssdw m0, [cq+32* 8] + packssdw m1, [cq+32* 9] + packssdw m2, [cq+32*10] + packssdw m3, [cq+32*11] + packssdw m4, [cq+32*12] + packssdw m5, [cq+32*13] + packssdw m6, [cq+32*14] + packssdw m7, [cq+32*15] + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 + call .write_16x4_start + call m(idct_16x8_internal_10bpc).write_16x4_zero + vpermq m0, m4, q3120 + vpermq m1, m5, q3120 + vpermq m2, m6, q3120 + vpermq m3, m7, q3120 + jmp m(idct_16x8_internal_10bpc).write_16x4_zero +ALIGN function_align +.write_16x4_start: + vpbroadcastd m9, [pixel_12bpc_max] + lea r3, [strideq*3] + pxor m8, m8 + ret + +INV_TXFM_16X8_FN adst, dct, 12 +INV_TXFM_16X8_FN adst, adst, 12 +INV_TXFM_16X8_FN adst, flipadst, 12 +INV_TXFM_16X8_FN adst, identity, 12 + +cglobal iadst_16x8_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_20b_min] + vpbroadcastd m14, [clip_20b_max] + jmp m(iadst_16x8_internal_10bpc).pass1 +.pass2: + call .pass2_main + call m(idct_16x8_internal_12bpc).end + RET +ALIGN function_align +.pass2_main: + call m(idct_8x16_internal_12bpc).transpose + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m11, [pd_2048] + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(iadst_8x8_internal_12bpc).pass2_main2 + mova [cq+32* 8], m0 + mova [cq+32* 9], m1 + mova [cq+32*10], m2 + mova [cq+32*11], m3 + mova [cq+32*12], m4 + mova [cq+32*13], m5 + mova [cq+32*14], m6 + mova [cq+32*15], m7 + pmaxsd m0, m12, [cq+32*0] + pmaxsd m1, m12, [cq+32*1] + pmaxsd m2, m12, [cq+32*2] + pmaxsd m3, m12, [cq+32*3] + pmaxsd m4, m12, [cq+32*4] + pmaxsd m5, m12, [cq+32*5] + pmaxsd m6, m12, [cq+32*6] + pmaxsd m7, m12, [cq+32*7] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(iadst_8x8_internal_12bpc).pass2_main2 + ret + +INV_TXFM_16X8_FN flipadst, dct, 12 +INV_TXFM_16X8_FN flipadst, adst, 12 +INV_TXFM_16X8_FN flipadst, flipadst, 12 +INV_TXFM_16X8_FN flipadst, identity, 12 + +cglobal iflipadst_16x8_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_20b_min] + vpbroadcastd m14, [clip_20b_max] + jmp m(iflipadst_16x8_internal_10bpc).pass1 +.pass2: + call m(iadst_16x8_internal_12bpc).pass2_main + packssdw m13, m0, [cq+32* 8] + packssdw m12, m1, [cq+32* 9] + packssdw m11, m2, [cq+32*10] + packssdw m10, m3, [cq+32*11] + packssdw m3, m4, [cq+32*12] + packssdw m2, m5, [cq+32*13] + packssdw m1, m6, [cq+32*14] + packssdw m0, m7, [cq+32*15] + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 + call m(idct_16x8_internal_12bpc).write_16x4_start + call m(idct_16x8_internal_10bpc).write_16x4_zero + vpermq m0, m10, q3120 + vpermq m1, m11, q3120 + vpermq m2, m12, q3120 + vpermq m3, m13, q3120 + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET + +INV_TXFM_16X8_FN identity, dct, 12 +INV_TXFM_16X8_FN identity, adst, 12 +INV_TXFM_16X8_FN identity, flipadst, 12 +INV_TXFM_16X8_FN identity, identity, 12 + +cglobal iidentity_16x8_internal_12bpc, 0, 7, 16, 32*8, dst, stride, c, eob, tx2 + jmp m(iidentity_16x8_internal_10bpc).pass1 +.pass2: + call m(idct_16x8_internal_10bpc).transpose2 + vpbroadcastd m10, [pw_4096] + pmulhrsw m0, m10 + pmulhrsw m1, m10 + pmulhrsw m2, m10 + pmulhrsw m3, m10 + call m(idct_16x8_internal_12bpc).write_16x4_start + call m(idct_16x8_internal_10bpc).write_16x4_zero + jmp m(idct_16x8_internal_10bpc).end2 + +%macro INV_TXFM_16X16_FN 2-4 0,10 ; type1, type2, eob_offset, bitdepth + INV_TXFM_FN %1, %2, %3, 16x16, %4 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_%4bpc] + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_16x4_10bpc).dconly3 +%endif +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, identity, 28 +INV_TXFM_16X16_FN dct, adst +INV_TXFM_16X16_FN dct, flipadst + +cglobal idct_16x16_internal_10bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] +.pass1: + vpbroadcastd m11, [pd_2048] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*4] + sub eobd, 36 + jl .fast + add cq, 32 + call .main + sub cq, 32 + mova m10, [r6-32*4] + mova m9, [r6-32*3] + mova m8, [r6-32*2] + psubd m15, m0, m10 ; out15 + paddd m0, m10 ; out0 + psubd m10, m1, m9 ; out14 + paddd m1, m9 ; out1 + psubd m9, m2, m8 ; out13 + paddd m2, m8 ; out2 + REPX {psrad x, 2}, m0, m1, m2 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6-32*2], m2 + mova m2, [r6-32*1] + mova m1, [r6+32*0] + mova m0, [r6+32*1] + REPX {psrad x, 2}, m9, m10, m15 + psubd m8, m3, m2 ; out12 + paddd m3, m2 ; out3 + psubd m2, m4, m1 ; out11 + paddd m4, m1 ; out4 + psubd m1, m5, m0 ; out10 + paddd m5, m0 ; out5 + REPX {psrad x, 2}, m3, m4, m5 + mova [r6-32*1], m3 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova m4, [r6+32*2] + mova m3, [r6+32*3] + REPX {psrad x, 2}, m1, m2, m8 + psubd m5, m6, m4 ; out9 + paddd m6, m4 ; out6 + psubd m4, m7, m3 ; out8 + paddd m7, m3 ; out7 + REPX {psrad x, 2}, m6, m7, m4, m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + add r6, 32*8 + mova [r6-32*4], m4 + mova [r6-32*3], m5 + mova [r6-32*2], m1 + mova [r6-32*1], m2 + mova [r6+32*0], m8 + mova [r6+32*1], m9 + mova [r6+32*2], m10 + mova [r6+32*3], m15 +.fast: + add r6, 32*8 + call .main + mova m14, [r6-32*4] + mova m13, [r6-32*3] + mova m12, [r6-32*2] + mova m11, [r6-32*1] + mova m10, [r6+32*0] + mova m9, [r6+32*1] + mova m8, [r6+32*2] + psubd m15, m0, m14 ; out15 + paddd m0, m14 ; out0 + psubd m14, m1, m13 ; out14 + paddd m1, m13 ; out1 + psubd m13, m2, m12 ; out13 + paddd m2, m12 ; out2 + psubd m12, m3, m11 ; out12 + paddd m3, m11 ; out3 + psubd m11, m4, m10 ; out11 + paddd m4, m10 ; out4 + psubd m10, m5, m9 ; out10 + paddd m5, m9 ; out5 + psubd m9, m6, m8 ; out9 + paddd m6, m8 ; out6 + psubd m8, m7, [r6+32*3] ; out8 + paddd m7, [r6+32*3] ; out7 + sub r6, 32*8 + REPX {psrad x, 2}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call .transpose + lea r6, [pw_5+128] + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] +.end: + call .write_16x16 + RET +ALIGN function_align +.write_16x16: + mova [rsp+gprsize+32*0], m8 + mova [rsp+gprsize+32*1], m9 + mova [rsp+gprsize+32*2], m12 + vpbroadcastd m12, [pw_2048] + pmulhrsw m0, m12 + pmulhrsw m1, m12 + pmulhrsw m2, m12 + pmulhrsw m3, m12 + call m(idct_16x8_internal_10bpc).write_16x4_start +.write_16x16_2: + pmulhrsw m0, m12, m4 + pmulhrsw m1, m12, m5 + pmulhrsw m2, m12, m6 + pmulhrsw m3, m12, m7 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m12, [rsp+gprsize+32*0] + pmulhrsw m1, m12, [rsp+gprsize+32*1] + pmulhrsw m2, m12, m10 + pmulhrsw m3, m12, m11 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m12, [rsp+gprsize+32*2] + pmulhrsw m1, m12, m13 + pmulhrsw m2, m12, m14 + pmulhrsw m3, m12, m15 + jmp m(idct_16x8_internal_10bpc).write_16x4_zero +ALIGN function_align +.transpose: + test eobd, eobd + jl .transpose_fast + packssdw m8, [r6-32*4] + packssdw m9, [r6-32*3] + packssdw m10, [r6-32*2] + packssdw m11, [r6-32*1] + packssdw m12, [r6+32*0] + packssdw m13, [r6+32*1] + packssdw m14, [r6+32*2] + packssdw m15, [r6+32*3] + sub r6, 32*8 + packssdw m0, [r6-32*4] + packssdw m1, [r6-32*3] + packssdw m2, [r6-32*2] + packssdw m3, [r6-32*1] + packssdw m4, [r6+32*0] + packssdw m5, [r6+32*1] + packssdw m6, [r6+32*2] + packssdw m7, [r6+32*3] + mova [r6], m8 + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + punpckhwd m3, m6, m7 + punpcklwd m6, m7 + punpcklwd m7, m4, m5 + punpckhwd m4, m5 + punpckldq m5, m8, m2 + punpckhdq m8, m2 + punpckhdq m2, m0, m1 + punpckldq m0, m1 + punpckhdq m1, m7, m6 + punpckldq m7, m6 + punpckhdq m6, m4, m3 + punpckldq m4, m3 + punpckhqdq m3, m2, m1 + punpcklqdq m2, m1 + punpckhqdq m1, m0, m7 + punpcklqdq m0, m7 + punpcklqdq m7, m8, m6 + punpckhqdq m8, m6 + punpckhqdq m6, m5, m4 + punpcklqdq m5, m4 + mova m4, [r6] + mova [r6], m8 + punpcklwd m8, m4, m9 + punpckhwd m4, m9 + punpcklwd m9, m10, m11 + punpckhwd m10, m11 + punpckhwd m11, m14, m15 + punpcklwd m14, m15 + punpckhwd m15, m12, m13 + punpcklwd m12, m13 + punpckldq m13, m4, m10 + punpckhdq m4, m10 + punpckhdq m10, m8, m9 + punpckldq m8, m9 + punpckhdq m9, m12, m14 + punpckldq m12, m14 + punpckhdq m14, m15, m11 + punpckldq m15, m11 + punpckhqdq m11, m10, m9 + punpcklqdq m10, m9 + punpckhqdq m9, m8, m12 + punpcklqdq m8, m12 + punpcklqdq m12, m13, m15 + punpckhqdq m13, m15 + punpckhqdq m15, m4, m14 + punpcklqdq m14, m4, m14 + vperm2i128 m4, m0, m8, 0x31 + vinserti128 m0, xm8, 1 + vinserti128 m8, m5, xm12, 1 + vperm2i128 m12, m5, 0x13 + vperm2i128 m5, m1, m9, 0x31 + vinserti128 m1, xm9, 1 + vinserti128 m9, m6, xm13, 1 + vperm2i128 m13, m6, 0x13 + vperm2i128 m6, m2, m10, 0x31 + vinserti128 m2, xm10, 1 + vinserti128 m10, m7, xm14, 1 + vperm2i128 m14, m7, 0x13 + vperm2i128 m7, m3, m11, 0x31 + vinserti128 m3, xm11, 1 + mova xm11, [r6] + vinserti128 m11, xm15, 1 + vinserti128 m15, [r6+16], 0 + ret +.transpose_fast: + call m(idct_16x8_internal_10bpc).transpose2 + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + ret +ALIGN function_align +.main: + mova m0, [cq+64* 1] + mova m1, [cq+64* 3] + mova m2, [cq+64* 5] + mova m3, [cq+64* 7] + mova m4, [cq+64* 9] + mova m5, [cq+64*11] + mova m6, [cq+64*13] + mova m7, [cq+64*15] + call m(idct_8x16_internal_10bpc).main_oddhalf + mova m0, [cq+64* 0] + mova m1, [cq+64* 2] + mova m2, [cq+64* 4] + mova m3, [cq+64* 6] + mova m4, [cq+64* 8] + mova m5, [cq+64*10] + mova m6, [cq+64*12] + mova m7, [cq+64*14] + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + psrld m10, m11, 10 ; pd_2 + REPX {paddd x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 + ret + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, adst +INV_TXFM_16X16_FN adst, flipadst + +cglobal iadst_16x16_internal_10bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] +.pass1: + vpbroadcastd m15, [pd_2896] + lea r6, [rsp+32*4] + sub eobd, 36 + jl .fast + add cq, 32 + call .main + sub cq, 32 + vpbroadcastd m8, [pd_5120] + paddd m4, m8 + paddd m6, m8 + paddd m9, m8 + paddd m11, m8 + vpbroadcastd m8, [pd_5119] + psubd m5, m8, m5 + psubd m7, m8, m7 + psubd m10, m8, m10 + psubd m12, m8, m12 + REPX {psrad x, 13}, m4, m5, m6, m7, m9, m10, m11, m12 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + psrld m4, m15, 10 ; pd_2 + paddd m0, m4 + psubd m1, m4, m1 + paddd m2, m4 + psubd m3, m4, m3 + psubd m7, m4, [r6-32*4] + paddd m6, m4, [r6-32*3] + psubd m5, m4, [r6-32*2] + paddd m4, [r6-32*1] + REPX {psrad x, 2 }, m0, m1, m2, m3, m4, m5, m6, m7 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6-32*2], m2 + mova [r6-32*1], m3 + add r6, 32*8 + mova [r6-32*4], m9 + mova [r6-32*3], m10 + mova [r6-32*2], m11 + mova [r6-32*1], m12 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 +.fast: + add r6, 32*8 + call .main + vpbroadcastd m14, [pd_5120] + vpbroadcastd m13, [pd_5119] + psrld m15, 10 ; pd_2 + paddd m0, m15 + psubd m1, m15, m1 + paddd m2, m15 + psubd m3, m15, m3 + paddd m4, m14 + psubd m5, m13, m5 + paddd m6, m14 + psubd m7, m13, m7 + paddd m8, m14, m9 + psubd m9, m13, m10 + paddd m10, m14, m11 + psubd m11, m13, m12 + paddd m12, m15, [r6-32*1] + psubd m13, m15, [r6-32*2] + paddd m14, m15, [r6-32*3] + psubd m15, [r6-32*4] +.pass1_end: + REPX {psrad x, 2 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 13}, m4, m5, m6, m7, m8, m9, m10, m11 + sub r6, 32*8 + jmp tx2q +.pass2: + call m(idct_16x16_internal_10bpc).transpose + lea r6, [pw_5+128] + mova [rsp], m15 + call m(iadst_16x16_internal_8bpc).main + call m(iadst_16x16_internal_8bpc).main_pass2_end + mova [rsp+32*0], m8 + mova [rsp+32*2], m12 + mova [rsp+32*3], m13 + vpbroadcastd m12, [pw_2048] + pxor m13, m13 + psubw m13, m12 + pmulhrsw m0, m12 + pmulhrsw m1, m13, [rsp+32*1] + mova [rsp+32*1], m9 + pmulhrsw m2, m12 + pmulhrsw m3, m13 + call m(idct_16x8_internal_10bpc).write_16x4_start + pmulhrsw m0, m12, m4 + pmulhrsw m1, m13, m5 + pmulhrsw m2, m12, m6 + pmulhrsw m3, m13, m7 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m12, [rsp+32*0] + pmulhrsw m1, m13, [rsp+32*1] + pmulhrsw m2, m12, m10 + pmulhrsw m3, m13, m11 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m12, [rsp+32*2] + pmulhrsw m1, m13, [rsp+32*3] + pmulhrsw m2, m12, m14 + pmulhrsw m3, m13, m15 + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET +ALIGN function_align +.main: + mova m0, [cq+64* 2] + mova m1, [cq+64*13] + mova m2, [cq+64* 6] + mova m3, [cq+64* 9] + mova m4, [cq+64*10] + mova m5, [cq+64* 5] + mova m6, [cq+64*14] + mova m7, [cq+64* 1] + vpbroadcastd m12, [pd_2048] + call m(iadst_16x8_internal_10bpc).main_part1 + mova m0, [cq+64* 0] + mova m1, [cq+64*15] + mova m2, [cq+64* 4] + mova m3, [cq+64*11] + mova m4, [cq+64* 8] + mova m5, [cq+64* 7] + mova m6, [cq+64*12] + mova m7, [cq+64* 3] + jmp m(iadst_16x8_internal_10bpc).main_part2 + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_10bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] +.pass1: + vpbroadcastd m15, [pd_2896] + lea r6, [rsp+32*4] + sub eobd, 36 + jl .fast + add cq, 32 + call m(iadst_16x16_internal_10bpc).main + sub cq, 32 + vpbroadcastd m8, [pd_5120] + paddd m11, m8 + paddd m9, m8 + paddd m6, m8 + paddd m4, m8 + vpbroadcastd m8, [pd_5119] + psubd m12, m8, m12 + psubd m10, m8, m10 + psubd m7, m8, m7 + psubd m5, m8, m5 + REPX {psrad x, 13}, m12, m11, m10, m9, m7, m6, m5, m4 + mova [r6+32*0], m12 + mova [r6+32*1], m11 + mova [r6+32*2], m10 + mova [r6+32*3], m9 + psrld m9, m15, 10 ; pd_2 + psubd m3, m9, m3 + paddd m2, m9 + psubd m1, m9, m1 + paddd m0, m9 + psubd m12, m9, [r6-32*4] + paddd m11, m9, [r6-32*3] + psubd m10, m9, [r6-32*2] + paddd m9, [r6-32*1] + REPX {psrad x, 2 }, m12, m11, m10, m9, m3, m2, m1, m0 + mova [r6-32*4], m12 + mova [r6-32*3], m11 + mova [r6-32*2], m10 + mova [r6-32*1], m9 + add r6, 32*8 + mova [r6-32*4], m7 + mova [r6-32*3], m6 + mova [r6-32*2], m5 + mova [r6-32*1], m4 + mova [r6+32*0], m3 + mova [r6+32*1], m2 + mova [r6+32*2], m1 + mova [r6+32*3], m0 +.fast: + add r6, 32*8 + call m(iadst_16x16_internal_10bpc).main + vpbroadcastd m14, [pd_5120] + vpbroadcastd m13, [pd_5119] + psrld m15, 10 ; pd_2 + psubd m8, m13, m7 + paddd m7, m14, m9 + paddd m9, m14, m6 + psubd m6, m13, m10 + psubd m10, m13, m5 + paddd m5, m14, m11 + paddd m11, m14, m4 + psubd m4, m13, m12 + psubd m12, m15, m3 + paddd m3, m15, [r6-32*1] + paddd m13, m15, m2 + psubd m2, m15, [r6-32*2] + psubd m14, m15, m1 + mova m1, m15 + paddd m15, m0 + psubd m0, m1, [r6-32*4] + paddd m1, [r6-32*3] + jmp m(iadst_16x16_internal_10bpc).pass1_end +.pass2: + call m(idct_16x16_internal_10bpc).transpose + lea r6, [pw_5+128] + mova [rsp], m15 + call m(iadst_16x16_internal_8bpc).main + call m(iadst_16x16_internal_8bpc).main_pass2_end + mova [rsp+32*3], m3 + mova [rsp+32*2], m2 + mova [rsp+32*0], m0 + mova m2, m13 + mova m3, m12 + vpbroadcastd m12, [pw_2048] + pxor m13, m13 + psubw m13, m12 + pmulhrsw m0, m13, m15 + pmulhrsw m1, m12, m14 + pmulhrsw m2, m13 + pmulhrsw m3, m12 + mova m14, m8 + mova m15, m9 + call m(idct_16x8_internal_10bpc).write_16x4_start + pmulhrsw m0, m13, m11 + pmulhrsw m1, m12, m10 + pmulhrsw m2, m13, m15 + pmulhrsw m3, m12, m14 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m13, m7 + pmulhrsw m1, m12, m6 + pmulhrsw m2, m13, m5 + pmulhrsw m3, m12, m4 + call m(idct_16x8_internal_10bpc).write_16x4_zero + pmulhrsw m0, m13, [rsp+32*3] + pmulhrsw m1, m12, [rsp+32*2] + pmulhrsw m2, m13, [rsp+32*1] + pmulhrsw m3, m12, [rsp+32*0] + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET + +INV_TXFM_16X16_FN identity, dct, -92 +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_10bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m15, [pd_5793] + vpbroadcastd m7, [pd_5120] + lea r6, [rsp+32*4] + sub eobd, 36 + jl .fast + mov r3, -32*8*4 +.righthalf: + pmulld m0, m15, [cq+r3+32*33] + pmulld m1, m15, [cq+r3+32*35] + pmulld m2, m15, [cq+r3+32*37] + pmulld m3, m15, [cq+r3+32*39] + add r6, 32*4 + REPX {paddd x, m7}, m0, m1, m2, m3 + REPX {psrad x, 13}, m0, m1, m2, m3 + mova [r6+32*0], m0 + mova [r6+32*1], m1 + mova [r6+32*2], m2 + mova [r6+32*3], m3 + add r3, 32*8 + jl .righthalf +.fast: + pmulld m0, m15, [cq+64* 0] + pmulld m1, m15, [cq+64* 1] + pmulld m2, m15, [cq+64* 2] + pmulld m3, m15, [cq+64* 3] + pmulld m4, m15, [cq+64* 4] + pmulld m5, m15, [cq+64* 5] + pmulld m6, m15, [cq+64* 6] + pmulld m8, m15, [cq+64* 7] + mova [cq], m8 + pmulld m8, m15, [cq+64* 8] + pmulld m9, m15, [cq+64* 9] + pmulld m10, m15, [cq+64*10] + pmulld m11, m15, [cq+64*11] + pmulld m12, m15, [cq+64*12] + pmulld m13, m15, [cq+64*13] + pmulld m14, m15, [cq+64*14] + pmulld m15, [cq+64*15] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6, \ + m8, m9, m10, m11, m12, m13, m14, m15 + paddd m7, [cq] + REPX {psrad x, 13}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp tx2q +.pass2: + call m(idct_16x16_internal_10bpc).transpose + + mova [cq+32*0], m15 + mova [cq+32*1], m0 + vpbroadcastd m15, [pw_1697x16] + + REPX {IDTX16 x, 0, 15}, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14 + mova m0, [cq+32*1] + mova [cq+32*1], m1 + IDTX16 0, 1, 15 + mova m1, [cq+32*0] + pmulhrsw m15, m1 + paddsw m1, m1 + paddsw m15, m1 + mova m1, [cq+32*1] + jmp m(idct_16x16_internal_10bpc).end + +INV_TXFM_16X16_FN dct, dct, 0, 12 +INV_TXFM_16X16_FN dct, identity, 28, 12 +INV_TXFM_16X16_FN dct, adst, 0, 12 +INV_TXFM_16X16_FN dct, flipadst, 0, 12 + +cglobal idct_16x16_internal_12bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + jmp m(idct_16x16_internal_10bpc).pass1 +.pass2: + mova [cq+32* 8], m8 + mova [cq+32* 9], m9 + mova [cq+32*10], m10 + mova [cq+32*11], m11 + mova [cq+32*12], m12 + mova [cq+32*13], m13 + mova [cq+32*14], m14 + mova [cq+32*15], m15 + call .pass2_main + packssdw m0, m1 + packssdw m1, m2, m3 + packssdw m2, m4, m5 + packssdw m3, m6, m7 + packssdw m4, m8, m9 + packssdw m5, m10, m11 + packssdw m6, m12, m13 + packssdw m7, m14, m15 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6-32*2], m2 + mova [r6-32*1], m3 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + mova m0, [cq+32* 8] + mova m1, [cq+32* 9] + mova m2, [cq+32*10] + mova m3, [cq+32*11] + mova m4, [cq+32*12] + mova m5, [cq+32*13] + mova m6, [cq+32*14] + mova m7, [cq+32*15] + mov r5, r6 + add r6, 32*16 + call .pass2_main + jmp m(iadst_16x16_internal_12bpc).end +ALIGN function_align +.write_16x16: + mova [rsp+gprsize+32*0], m8 + mova [rsp+gprsize+32*1], m9 + mova [rsp+gprsize+32*2], m12 + vpbroadcastd m12, [pw_16384] + pmulhrsw m0, m12 + pmulhrsw m1, m12 + pmulhrsw m2, m12 + pmulhrsw m3, m12 + call m(idct_16x8_internal_12bpc).write_16x4_start + call m(idct_16x8_internal_10bpc).write_16x4_zero + jmp m(idct_16x16_internal_10bpc).write_16x16_2 +ALIGN function_align +.pass2_main: + call m(idct_8x8_internal_12bpc).transpose_8x8 + mova [cq+32* 0], m0 + mova [cq+32* 1], m2 + mova [cq+32* 2], m4 + mova [cq+32* 3], m6 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + pmaxsd m0, m12, m1 + pmaxsd m1, m12, m3 + pmaxsd m2, m12, m5 + pmaxsd m3, m12, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3 + test eobd, eobd + jge .pass2_slow + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + jmp .pass2_fast +.pass2_slow: + sub r6, 32*8 + mova m8, [r6-32*4] + mova m4, [r6-32*3] + mova m10, [r6-32*2] + mova m5, [r6-32*1] + mova m12, [r6+32*0] + mova m6, [r6+32*1] + mova m14, [r6+32*2] + mova m7, [r6+32*3] + TRANSPOSE_8X8_DWORD 8, 4, 10, 5, 12, 6, 14, 7, 9, 11, 13, 15 + mova [cq+32* 4], m8 + mova [cq+32* 5], m10 + mova [cq+32* 6], m12 + mova [cq+32* 7], m14 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + REPX {pmaxsd x, m12}, m4, m5, m6, m7 + REPX {pminsd x, m13}, m4, m5, m6, m7 +.pass2_fast: + vpbroadcastd m11, [pd_2048] + vpbroadcastd m14, [pd_2896] + call m(idct_8x16_internal_10bpc).main_oddhalf + pmaxsd m0, m12, [cq+32* 0] + pmaxsd m1, m12, [cq+32* 1] + pmaxsd m2, m12, [cq+32* 2] + pmaxsd m3, m12, [cq+32* 3] + REPX {pminsd x, m13}, m0, m1, m2, m3 + test eobd, eobd + jge .pass2_slow2 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + jmp .pass2_fast2 +.pass2_slow2: + pmaxsd m4, m12, [cq+32* 4] + pmaxsd m5, m12, [cq+32* 5] + pmaxsd m6, m12, [cq+32* 6] + pmaxsd m7, m12, [cq+32* 7] + REPX {pminsd x, m13}, m4, m5, m6, m7 +.pass2_fast2: + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + psrad m11, 8 ; pd_8 + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_16x8_internal_10bpc).pass1_rotations + REPX {psrad x, 4}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + ret + +INV_TXFM_16X16_FN adst, dct, 0, 12 +INV_TXFM_16X16_FN adst, adst, 0, 12 +INV_TXFM_16X16_FN adst, flipadst, 0, 12 + +cglobal iadst_16x16_internal_12bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_20b_min] + vpbroadcastd m14, [clip_20b_max] + jmp m(iadst_16x16_internal_10bpc).pass1 +.pass2: + call .pass2_part1 + call m(iadst_16x8_internal_10bpc).pass1_rotations + call .pass2_part2 + call m(iadst_16x8_internal_10bpc).pass1_rotations +.pass2_part3: + REPX {psrad x, 4 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 15}, m4, m5, m6, m7, m8, m9, m10, m11 +.end: + packssdw m15, m14 + packssdw m14, m13, m12 + packssdw m13, m11, m10 + packssdw m12, m9, m8 + packssdw m11, m7, m6 + packssdw m10, m5, m4 + packssdw m7, m3, m2 + packssdw m6, m1, m0 + vpblendd m0, m6, [r5-32*4], 0x33 + vpblendd m1, m6, [r5-32*4], 0xcc + vpblendd m2, m7, [r5-32*3], 0x33 + vpblendd m3, m7, [r5-32*3], 0xcc + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + call m(idct_16x8_internal_12bpc).write_16x4_start + call m(idct_16x8_internal_10bpc).write_16x4_zero + vpblendd m0, m10, [r5-32*2], 0x33 + vpblendd m1, m10, [r5-32*2], 0xcc + vpblendd m2, m11, [r5-32*1], 0x33 + vpblendd m3, m11, [r5-32*1], 0xcc + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + call m(idct_16x8_internal_10bpc).write_16x4_zero + vpblendd m0, m12, [r5+32*0], 0x33 + vpblendd m1, m12, [r5+32*0], 0xcc + vpblendd m2, m13, [r5+32*1], 0x33 + vpblendd m3, m13, [r5+32*1], 0xcc + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + call m(idct_16x8_internal_10bpc).write_16x4_zero + vpblendd m0, m14, [r5+32*2], 0x33 + vpblendd m1, m14, [r5+32*2], 0xcc + vpblendd m2, m15, [r5+32*3], 0x33 + vpblendd m3, m15, [r5+32*3], 0xcc + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + call m(idct_16x8_internal_10bpc).write_16x4_zero + RET +ALIGN function_align +.pass2_part1: + mova [cq+32* 8], m8 + mova [cq+32* 9], m9 + mova [cq+32*10], m10 + mova [cq+32*11], m11 + mova [cq+32*12], m12 + mova [cq+32*13], m13 + mova [cq+32*14], m14 + mova [cq+32*15], m15 +.pass2_main: + call m(idct_8x8_internal_12bpc).transpose_8x8 + mova [cq+32* 0], m0 + mova [cq+32* 1], m3 + mova [cq+32* 2], m4 + mova [cq+32* 3], m7 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] + pmaxsd m0, m13, m2 + pmaxsd m2, m13, m6 + pmaxsd m5, m13, m5 + pmaxsd m7, m13, m1 + REPX {pminsd x, m14}, m0, m2, m5, m7 + test eobd, eobd + jge .pass2_slow + pxor m1, m1 + REPX {mova x, m1}, m3, m4, m6 + jmp .pass2_fast +.pass2_slow: + sub r6, 32*8 + mova m8, [r6-32*4] + mova m3, [r6-32*3] + mova m4, [r6-32*2] + mova m11, [r6-32*1] + mova m12, [r6+32*0] + mova m1, [r6+32*1] + mova m6, [r6+32*2] + mova m15, [r6+32*3] + TRANSPOSE_8X8_DWORD 8, 3, 4, 11, 12, 1, 6, 15, 13, 9, 10, 14 + mova [cq+32* 4], m8 + mova [cq+32* 5], m11 + mova [cq+32* 6], m12 + mova [cq+32* 7], m15 + vpbroadcastd m13, [clip_18b_min] + vpbroadcastd m14, [clip_18b_max] + REPX {pmaxsd x, m13}, m1, m3, m4, m6 + REPX {pminsd x, m14}, m1, m3, m4, m6 +.pass2_fast: + vpbroadcastd m12, [pd_2048] + vpbroadcastd m15, [pd_2896] + call m(iadst_16x8_internal_10bpc).main_part1 + pmaxsd m0, m13, [cq+32* 0] ; 0 + pmaxsd m7, m13, [cq+32* 1] ; 3 + pmaxsd m2, m13, [cq+32* 2] ; 4 + pmaxsd m5, m13, [cq+32* 3] ; 7 + REPX {pminsd x, m14}, m0, m2, m5, m7 + test eobd, eobd + jge .pass2_slow2 + pxor m1, m1 + REPX {mova x, m1}, m3, m4, m6 + jmp .pass2_fast2 +.pass2_slow2: + pmaxsd m4, m13, [cq+32* 4] ; 8 + pmaxsd m3, m13, [cq+32* 5] ; 11 + pmaxsd m6, m13, [cq+32* 6] ; 12 + pmaxsd m1, m13, [cq+32* 7] ; 15 + REPX {pminsd x, m14}, m1, m3, m4, m6 +.pass2_fast2: + call m(iadst_16x8_internal_10bpc).main_part2 + vpbroadcastd m14, [pd_17408] + psrld m15, 11 ; pd_1 + psubd m13, m14, m15 ; pd_17407 + pslld m15, 3 ; pd_8 + ret +ALIGN function_align +.pass2_part2: + REPX {psrad x, 4 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 15}, m4, m5, m6, m7, m8, m9, m10, m11 + packssdw m0, m1 + packssdw m1, m2, m3 + packssdw m2, m4, m5 + packssdw m3, m6, m7 + packssdw m4, m8, m9 + packssdw m5, m10, m11 + packssdw m6, m12, m13 + packssdw m7, m14, m15 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6-32*2], m2 + mova [r6-32*1], m3 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + mova m0, [cq+32* 8] + mova m1, [cq+32* 9] + mova m2, [cq+32*10] + mova m3, [cq+32*11] + mova m4, [cq+32*12] + mova m5, [cq+32*13] + mova m6, [cq+32*14] + mova m7, [cq+32*15] + mov r5, r6 + add r6, 32*16 + jmp .pass2_main + +INV_TXFM_16X16_FN flipadst, dct, 0, 12 +INV_TXFM_16X16_FN flipadst, adst, 0, 12 +INV_TXFM_16X16_FN flipadst, flipadst, 0, 12 + +cglobal iflipadst_16x16_internal_12bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m13, [clip_20b_min] + vpbroadcastd m14, [clip_20b_max] + jmp m(iflipadst_16x16_internal_10bpc).pass1 +.pass2: + call m(iadst_16x16_internal_12bpc).pass2_part1 + call m(iflipadst_16x8_internal_10bpc).pass1_rotations + call m(iadst_16x16_internal_12bpc).pass2_part2 + call m(iflipadst_16x8_internal_10bpc).pass1_rotations + jmp m(iadst_16x16_internal_12bpc).pass2_part3 + +INV_TXFM_16X16_FN identity, dct, -92, 12 +INV_TXFM_16X16_FN identity, identity, 0, 12 + +%macro IDTX16_12BPC 1 ; src + pmulld m6, m7, m%1 + paddd m6, m15 + psrad m6, 12 + paddd m6, m%1 + psrad m%1, m6, 1 +%endmacro + +cglobal iidentity_16x16_internal_12bpc, 0, 7, 16, 32*24, dst, stride, c, eob, tx2 + vpbroadcastd m7, [pd_1697] + vpbroadcastd m15, [pd_5120] + lea r6, [rsp+32*4] + sub eobd, 36 + jl .fast + mov r3, -32*8*4 +.righthalf: + mova m10, [cq+r3+32*33] + mova m11, [cq+r3+32*35] + mova m12, [cq+r3+32*37] + mova m13, [cq+r3+32*39] + add r6, 32*4 + pmulld m0, m7, m10 + pmulld m1, m7, m11 + pmulld m2, m7, m12 + pmulld m3, m7, m13 + REPX {paddd x, m15}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 + paddd m0, m10 + paddd m1, m11 + paddd m2, m12 + paddd m3, m13 + REPX {psrad x, 1 }, m0, m1, m2, m3 + mova [r6+32*0], m0 + mova [r6+32*1], m1 + mova [r6+32*2], m2 + mova [r6+32*3], m3 + add r3, 32*8 + jl .righthalf +.fast: + mova m0, [cq+64* 0] + mova m1, [cq+64* 1] + mova m2, [cq+64* 2] + mova m3, [cq+64* 3] + mova m4, [cq+64* 4] + mova m5, [cq+64* 5] + mova m8, [cq+64* 6] + mova m9, [cq+64* 7] + REPX {IDTX16_12BPC x}, 0, 1, 2, 3, 4, 5, 8, 9 + mova [cq+64*0], m8 + mova [cq+64*1], m9 + mova m8, [cq+64* 8] + mova m9, [cq+64* 9] + mova m10, [cq+64*10] + mova m11, [cq+64*11] + mova m12, [cq+64*12] + mova m13, [cq+64*13] + mova m14, [cq+64*14] + REPX {IDTX16_12BPC x}, 8, 9, 10, 11, 12, 13, 14 + mova m6, [cq+64*15] + pmulld m7, m6 + paddd m7, m15 + psrad m7, 12 + paddd m7, m6 + mova m6, [cq+64*0] + psrad m15, m7, 1 + mova m7, [cq+64*1] + jmp tx2q +.pass2: + call m(iidentity_8x16_internal_12bpc).pass2_main + call m(idct_16x16_internal_10bpc).transpose_fast + test eobd, eobd + jl .pass2_fast + mova [cq+32* 8], m0 + mova [cq+32* 9], m1 + mova [cq+32*10], m2 + mova [cq+32*11], m3 + mova [cq+32*12], m4 + mova [cq+32*13], m5 + mova [cq+32*14], m6 + mova [cq+32*15], m7 + mova m8, [r6-32*4] + mova m9, [r6-32*3] + mova m10, [r6-32*2] + mova m11, [r6-32*1] + mova m12, [r6+32*0] + mova m13, [r6+32*1] + mova m14, [r6+32*2] + mova m15, [r6+32*3] + sub r6, 32*8 + mova m0, [r6-32*4] + mova m1, [r6-32*3] + mova m2, [r6-32*2] + mova m3, [r6-32*1] + mova m4, [r6+32*0] + mova m5, [r6+32*1] + mova m6, [r6+32*2] + mova m7, [r6+32*3] + call m(iidentity_8x16_internal_12bpc).pass2_main + call m(idct_16x8_internal_10bpc).transpose2 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 + mova m12, m4 + mova m13, m5 + mova m14, m6 + mova m15, m7 + mova m0, [cq+32* 8] + mova m1, [cq+32* 9] + mova m2, [cq+32*10] + mova m3, [cq+32*11] + mova m4, [cq+32*12] + mova m5, [cq+32*13] + mova m6, [cq+32*14] + mova m7, [cq+32*15] +.pass2_fast: + call m(idct_16x16_internal_12bpc).write_16x16 + RET + +%macro IDCT32_END 6-7 1 ; in/out1, out2, tmp[1-3], shift, pack + mova m%4, [r6+32*(%1-4)] + mova m%2, [r5+32*(3-%1)] + mova m%5, [r4+32*(%1-4)] + psubd m%3, m%1, m%4 ; idct16 out15 - n + paddd m%1, m%4 ; idct16 out0 + n + pmaxsd m%1, m12 + pmaxsd m%3, m12 + pminsd m%1, m13 + pminsd m%3, m13 + paddd m%1, m11 + paddd m%3, m11 + psubd m%4, m%1, m%2 ; out31 - n + paddd m%1, m%2 ; out0 + n + paddd m%2, m%3, m%5 ; out15 - n + psubd m%3, m%5 ; out16 + n + REPX {psrad x, %6}, m%1, m%3, m%2, m%4 +%if %7 & 1 + packssdw m%1, m%3 ; out0 + n, out16 + n + packssdw m%2, m%4 ; out15 - n, out31 - n +%endif +%endmacro + +cglobal inv_txfm_add_dct_dct_8x32_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 7, 16, 32*12, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vbroadcasti128 m14, [idct32_shuf] + mov r4, cq + call .pass1_main + mova [rsp+32*0], m2 + mova [rsp+32*1], m3 + cmp eobd, 43 + jge .eob43 + pxor m4, m4 + REPX {mova x, m4}, [rsp+32*2], m2, m3, m11 + jmp .pass1_end_fast +.eob43: + lea r6, [rsp+32*8] + mova [r6-32*4], m0 + mova [r6-32*3], m1 + call .pass1_main + mova [rsp+32*2], m2 + cmp eobd, 107 + jge .eob107 + mova m11, m3 + mova m2, m0 + mova m3, m1 + mova m0, [r6-32*4] + mova m1, [r6-32*3] + pxor m4, m4 +.pass1_end_fast: + vpbroadcastd m10, [pw_2048] + lea r6, [deint_shuf+128] + REPX {mova x, m4}, m5, m6, m7 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_fast + jmp .end +.eob107: + mova [rsp+32*3], m3 + mova [r6-32*2], m0 + mova [r6-32*1], m1 + call .pass1_main + cmp eobd, 171 + jge .eob171 + pshufd m12, m2, q1032 + pshufd m13, m3, q1032 + mova m4, m0 + mova m5, m1 + pxor m6, m6 + REPX {mova x, m6}, m7, m14, m15 + jmp .pass1_end +.eob171: + mova [r6+32*0], m0 + mova [r6+32*1], m1 + mova [r6+32*2], m2 + mova [r6+32*3], m3 + call .pass1_main + pshufd m12, [r6+32*2], q1032 ; out19 out17 + pshufd m13, [r6+32*3], q1032 ; out23 out21 + mova m4, [r6+32*0] ; out16 out18 + mova m5, [r6+32*1] ; out20 out22 + pshufd m14, m2, q1032 ; out27 out25 + pshufd m15, m3, q1032 ; out31 out29 + mova m6, m0 ; out24 out26 + mova m7, m1 ; out28 out30 +.pass1_end: + mova m0, [r6-32*4] ; out0 out2 + mova m1, [r6-32*3] ; out4 out6 + mova m2, [r6-32*2] ; out8 out10 + mova m3, [r6-32*1] ; out12 out14 + lea r6, [deint_shuf+128] + mova m11, [rsp+32*3] ; out13 out15 + vpbroadcastd m10, [pw_2048] + call m(inv_txfm_add_dct_dct_8x32_8bpc).main +.end: ; [rsp+0*32] = m12 + vpbroadcastd m12, [pw_2048] + mov cq, r4 + mova [rsp+32*1], m8 + mova [rsp+32*2], m9 + mova [rsp+32*3], m10 + mova [rsp+32*4], m11 + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4_start + vpermq m0, m2, q3120 + vpermq m1, m3, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m4, q3120 + vpermq m1, m5, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m6, q3120 + vpermq m1, m7, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [rsp+32*1], q3120 + vpermq m1, [rsp+32*2], q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [rsp+32*3], q3120 + vpermq m1, [rsp+32*4], q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [rsp+32*0], q3120 + vpermq m1, m13, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m14, q3120 + vpermq m1, m15, q2031 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m2, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 32 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly3 +ALIGN function_align +.pass1_main_part1: + mova m0, [cq+128*0] + mova m1, [cq+128*1] + mova m2, [cq+128*2] + mova m3, [cq+128*3] + mova m4, [cq+128*4] + mova m5, [cq+128*5] + mova m6, [cq+128*6] + mova m7, [cq+128*7] + call m(idct_8x8_internal_10bpc).main + psrld m1, m11, 10 ; pd_2 + REPX {paddd x, m1}, m0, m6, m5, m3 + paddd m1, m6, m7 ; out1 + psubd m6, m7 ; out6 + psubd m7, m0, m9 ; out7 + paddd m0, m9 ; out0 + paddd m2, m5, m4 ; out2 + psubd m5, m4 ; out5 + psubd m4, m3, m8 ; out4 + paddd m3, m8 ; out3 + REPX {psrad x, 2 }, m0, m1, m2, m3, m4, m5, m6, m7 + ret +ALIGN function_align +.pass1_main: + call .pass1_main_part1 + add cq, 32 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + pshufb m0, m14 + pshufb m2, m14 + pshufb m4, m14 + pshufb m6, m14 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + vperm2i128 m1, m0, m2, 0x31 ; 4 6 + vinserti128 m0, xm2, 1 ; 0 2 + vinserti128 m2, m3, xm4, 1 ; 1 3 + vperm2i128 m3, m4, 0x31 ; 5 7 + ret +.main_oddhalf_part1_fast_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_oddhalf_part1_fast: ; lower half zero + vpbroadcastd m7, [pd_4091] + vpbroadcastd m8, [pd_201] + vpbroadcastd m6, [pd_m1380] + vpbroadcastd m9, [pd_3857] + vpbroadcastd m5, [pd_3703] + vpbroadcastd m10, [pd_1751] + vpbroadcastd m4, [pd_m2751] + vpbroadcastd m15, [pd_3035] + pmulld m7, m0 + pmulld m0, m8 + pmulld m6, m1 + pmulld m1, m9 + pmulld m5, m2 + pmulld m2, m10 + pmulld m4, m3 + pmulld m3, m15 + jmp .main_oddhalf_part1_fast2 +.main_oddhalf_part1_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 +.main_oddhalf_part1: ; in1, in7, in9, in15, in17, in23, in25, in31 + ITX_MULSUB_2D 0, 7, 8, 9, 10, _, 201, 4091 ; t16a, t31a + ITX_MULSUB_2D 6, 1, 8, 9, 10, _, 3857, 1380 ; t19a, t28a + ITX_MULSUB_2D 2, 5, 8, 9, 10, _, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2D 4, 3, 8, 9, 10, _, 3035, 2751 ; t17a, t30a +.main_oddhalf_part1_fast2: + REPX {paddd x, m11}, m0, m7, m6, m1, m2, m5, m4, m3 + REPX {psrad x, 12 }, m0, m4, m6, m2, m1, m5, m7, m3 + psubd m8, m0, m4 ; t17 + paddd m0, m4 ; t16 + psubd m4, m6, m2 ; t18 + paddd m6, m2 ; t19 + psubd m2, m1, m5 ; t29 + paddd m1, m5 ; t28 + psubd m5, m7, m3 ; t30 + paddd m7, m3 ; t31 + REPX {pmaxsd x, m12}, m8, m5, m4, m2, m0, m6, m1, m7 + REPX {pminsd x, m13}, m8, m5, m4, m2, m0, m6, m1, m7 + vpbroadcastd m15, [pd_4017] + vpbroadcastd m10, [pd_799] + ITX_MULSUB_2D 5, 8, 3, 9, _, 11, 10, 15 ; t17a, t30a + ITX_MULSUB_2D 2, 4, 3, 9, _, 11, 10, 15, 2 ; t29a, t18a + psubd m3, m0, m6 ; t19a + paddd m0, m6 ; t16a + psubd m6, m7, m1 ; t28a + paddd m7, m1 ; t31a + psubd m1, m5, m4 ; t18 + paddd m5, m4 ; t17 + psubd m4, m8, m2 ; t29 + paddd m8, m2 ; t30 + REPX {pmaxsd x, m12}, m3, m6, m1, m4, m0, m7, m5, m8 + REPX {pminsd x, m13}, m3, m6, m1, m4, m0, m7, m5, m8 + vpbroadcastd m15, [pd_3784] + vpbroadcastd m10, [pd_1567] + ITX_MULSUB_2D 4, 1, 2, 9, _, 11, 10, 15 ; t18a, t29a + ITX_MULSUB_2D 6, 3, 2, 9, _, 11, 10, 15 ; t19, t28 + mova [r6-32*4], m0 + mova [r6-32*3], m5 + mova [r6-32*2], m4 + mova [r6-32*1], m6 + mova [r6+32*0], m3 + mova [r6+32*1], m1 + mova [r6+32*2], m8 + mova [r6+32*3], m7 + ret +.main_oddhalf_part2_fast_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_oddhalf_part2_fast: ; lower half zero + vpbroadcastd m7, [pd_m601] + vpbroadcastd m8, [pd_4052] + vpbroadcastd m6, [pd_3973] + vpbroadcastd m9, [pd_995] + vpbroadcastd m5, [pd_m2106] + vpbroadcastd m10, [pd_3513] + vpbroadcastd m4, [pd_3290] + vpbroadcastd m15, [pd_2440] + pmulld m7, m0 + pmulld m0, m8 + pmulld m6, m1 + pmulld m1, m9 + pmulld m5, m2 + pmulld m2, m10 + pmulld m4, m3 + pmulld m3, m15 + jmp .main_oddhalf_part2_fast2 +.main_oddhalf_part2_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 +.main_oddhalf_part2: ; in3, in5, in11, in13, in19, in21, in27, in29 + ITX_MULSUB_2D 7, 0, 8, 9, 10, _, 4052, 601 ; t23a, t24a + ITX_MULSUB_2D 1, 6, 8, 9, 10, _, 995, 3973 ; t20a, t27a + ITX_MULSUB_2D 5, 2, 8, 9, 10, _, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2D 3, 4, 8, 9, 10, _, 2440, 3290 ; t22a, t25a +.main_oddhalf_part2_fast2: + REPX {paddd x, m11}, m0, m7, m6, m1, m2, m5, m4, m3 + REPX {psrad x, 12 }, m0, m4, m6, m2, m1, m5, m7, m3 + psubd m8, m0, m4 ; t25 + paddd m0, m4 ; t24 + psubd m4, m6, m2 ; t26 + paddd m6, m2 ; t27 + psubd m2, m1, m5 ; t21 + paddd m1, m5 ; t20 + psubd m5, m7, m3 ; t22 + paddd m7, m3 ; t23 + REPX {pmaxsd x, m12}, m8, m5, m4, m2, m0, m6, m1, m7 + REPX {pminsd x, m13}, m8, m5, m4, m2, m0, m6, m1, m7 + vpbroadcastd m15, [pd_2276] + vpbroadcastd m10, [pd_3406] + ITX_MULSUB_2D 4, 2, 3, 9, _, 11, 10, 15 ; t21a, t26a + ITX_MULSUB_2D 8, 5, 3, 9, _, 11, 10, 15, 2 ; t25a, t22a + psubd m3, m0, m6 ; t27a + paddd m0, m6 ; t24a + psubd m6, m7, m1 ; t20a + paddd m7, m1 ; t23a + psubd m1, m5, m4 ; t21 + paddd m5, m4 ; t22 + psubd m4, m8, m2 ; t26 + paddd m8, m2 ; t25 + REPX {pmaxsd x, m12}, m3, m6, m1, m4, m0, m7, m5, m8 + REPX {pminsd x, m13}, m3, m6, m1, m4, m0, m7, m5, m8 + vpbroadcastd m15, [pd_3784] + vpbroadcastd m10, [pd_1567] + ITX_MULSUB_2D 4, 1, 2, 9, _, 11, 10, 15, 2 ; t26a, t21a + ITX_MULSUB_2D 3, 6, 2, 9, _, 11, 10, 15, 2 ; t27, t20 + mova m9, [r6-32*4] ; t16a + mova m10, [r6-32*3] ; t17 + psubd m2, m9, m7 ; t23 + paddd m9, m7 ; t16 + psubd m7, m10, m5 ; t22a + paddd m10, m5 ; t17a + REPX {pmaxsd x, m12}, m9, m10, m2, m7 + REPX {pminsd x, m13}, m9, m10, m2, m7 + mova [r6-32*4], m9 + mova [r6-32*3], m10 + mova m9, [r6-32*2] ; t18a + mova m10, [r6-32*1] ; t19 + psubd m5, m9, m1 ; t21 + paddd m9, m1 ; t18 + psubd m1, m10, m6 ; t20a + paddd m10, m6 ; t19a + REPX {pmaxsd x, m12}, m9, m10, m5, m1 + REPX {pminsd x, m13}, m9, m10, m5, m1 + mova [r6-32*2], m9 + mova [r6-32*1], m10 + mova m9, [r6+32*0] ; t28 + mova m10, [r6+32*1] ; t29a + psubd m6, m9, m3 ; t27a + paddd m9, m3 ; t28a + psubd m3, m10, m4 ; t26 + paddd m10, m4 ; t29 + REPX {pmaxsd x, m12}, m9, m10, m6, m3 + REPX {pminsd x, m13}, m9, m10, m6, m3 + REPX {pmulld x, m14}, m6, m3, m1, m5 + paddd m6, m11 + paddd m3, m11 + psubd m4, m6, m1 ; t20 + paddd m6, m1 ; t27 + psubd m1, m3, m5 ; t21a + paddd m3, m5 ; t26a + REPX {psrad x, 12 }, m4, m1, m3, m6 + mova [r6+32*0], m4 + mova [r6+32*1], m1 + mova m4, [r6+32*2] ; t30 + mova m1, [r6+32*3] ; t31a + psubd m5, m4, m8 ; t25a + paddd m4, m8 ; t30a + psubd m8, m1, m0 ; t24 + paddd m1, m0 ; t31 + REPX {pmaxsd x, m12}, m8, m5, m4, m1 + REPX {pminsd x, m13}, m8, m5, m4, m1 + REPX {pmulld x, m14}, m5, m8, m7, m2 + paddd m5, m11 + paddd m8, m11 + psubd m0, m5, m7 ; t22 + paddd m5, m7 ; t25 + psubd m7, m8, m2 ; t23a + paddd m2, m8 ; t24a + REPX {psrad x, 12 }, m0, m7, m2, m5 + mova [r6+32*2], m0 + mova [r6+32*3], m7 + mov r4, r6 + add r6, 32*8 + mova [r6-32*4], m2 + mova [r6-32*3], m5 + mova [r6-32*2], m3 + mova [r6-32*1], m6 + mova [r6+32*0], m9 + mova [r6+32*1], m10 + mova [r6+32*2], m4 + mova [r6+32*3], m1 + mov r5, r6 + add r6, 32*8 + ret +ALIGN function_align +.main_end: + psrld m11, 10 ; pd_2 + IDCT32_END 0, 15, 8, 9, 10, 2 + IDCT32_END 1, 14, 8, 9, 10, 2 + punpckhwd m8, m0, m1 ; 16 17 + punpcklwd m0, m1 ; 0 1 + punpcklwd m1, m14, m15 ; 14 15 + punpckhwd m14, m15 ; 30 31 + mova [r5+32*3], m8 + mova [r5+32*2], m14 + IDCT32_END 2, 15, 8, 9, 10, 2 + IDCT32_END 3, 14, 8, 9, 10, 2 + punpckhwd m8, m2, m3 ; 18 19 + punpcklwd m2, m3 ; 2 3 + punpcklwd m3, m14, m15 ; 12 13 + punpckhwd m14, m15 ; 28 29 + mova [r5+32*1], m8 + mova [r5+32*0], m14 + IDCT32_END 4, 15, 8, 9, 10, 2 + IDCT32_END 5, 14, 8, 9, 10, 2 + punpckhwd m8, m4, m5 ; 20 21 + punpcklwd m4, m5 ; 4 5 + punpcklwd m5, m14, m15 ; 10 11 + punpckhwd m14, m15 ; 26 27 + mova [r5-32*1], m8 + mova [r5-32*2], m14 + IDCT32_END 6, 15, 8, 9, 10, 2 + IDCT32_END 7, 14, 8, 9, 10, 2 + punpckhwd m8, m6, m7 ; 22 23 + punpcklwd m6, m7 ; 6 7 + punpcklwd m7, m14, m15 ; 8 9 + punpckhwd m14, m15 ; 24 25 + mova [r5-32*3], m8 + mova [r5-32*4], m14 +.transpose: + punpckhdq m15, m3, m1 + punpckldq m3, m1 + punpckhdq m1, m4, m6 + punpckldq m4, m6 + punpckhdq m6, m0, m2 + punpckldq m0, m2 + punpckhdq m2, m7, m5 + punpckldq m7, m5 + punpcklqdq m5, m2, m15 + punpckhqdq m2, m15 + punpckhqdq m15, m7, m3 + punpcklqdq m7, m3 + punpckhqdq m3, m6, m1 + punpcklqdq m6, m1 + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + vperm2i128 m4, m0, m7, 0x31 + vinserti128 m0, xm7, 1 + vperm2i128 m7, m3, m2, 0x31 + vinserti128 m3, xm2, 1 + vinserti128 m2, m6, xm5, 1 + vperm2i128 m6, m5, 0x31 + vperm2i128 m5, m1, m15, 0x31 + vinserti128 m1, xm15, 1 + ret + +cglobal inv_txfm_add_identity_identity_8x32_10bpc, 4, 7, 8, dst, stride, c, eob + vpbroadcastd m7, [pixel_10bpc_max] +.pass1: + vpbroadcastd m5, [pw_5] + pxor m6, m6 + mov r6d, eobd + add eobb, 21 + cmovc eobd, r6d ; 43, 107, 171 -> 64, 128, 192 + lea r6, [strideq*3] + lea r5, [strideq*5] + lea r4, [strideq+r6*2] ; strideq*7 +.loop: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + REPX {paddsw x, m5}, m0, m1, m2, m3 + REPX {psraw x, 3 }, m0, m1, m2, m3 + call .main_zero + add cq, 32 + lea dstq, [dstq+strideq*8] + sub eobd, 64 + jge .loop + RET +ALIGN function_align +.main_zero: + REPX {mova [cq+128*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 +.main: + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m4 + punpcklwd m0, m4 + punpckhwd m4, m2, m1 + punpcklwd m2, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + mova xm4, [dstq+strideq*0] + vinserti128 m4, [dstq+strideq*4], 1 + paddw m0, m4 + mova xm4, [dstq+strideq*1] + vinserti128 m4, [dstq+r5 ], 1 + paddw m1, m4 + mova xm4, [dstq+strideq*2] + vinserti128 m4, [dstq+r6*2 ], 1 + paddw m2, m4 + mova xm4, [dstq+r6 ] + vinserti128 m4, [dstq+r4 ], 1 + paddw m3, m4 + REPX {pmaxsw x, m6}, m0, m1, m2, m3 + REPX {pminsw x, m7}, m0, m1, m2, m3 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*4], m0, 1 + mova [dstq+strideq*1], xm1 + vextracti128 [dstq+r5 ], m1, 1 + mova [dstq+strideq*2], xm2 + vextracti128 [dstq+r6*2 ], m2, 1 + mova [dstq+r6 ], xm3 + vextracti128 [dstq+r4 ], m3, 1 + ret + +cglobal inv_txfm_add_dct_dct_8x32_12bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 7, 16, 32*24, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + mov r4, cq + lea r6, [rsp+32*4] + call .pass1_main + cmp eobd, 43 + jge .eob43 + jmp .pass2_fast +.eob43: + call .pass1_main + cmp eobd, 107 + jge .eob107 +.pass2_fast: + mov cq, r4 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + pmaxsd m0, m12, [cq+128*1+ 0] + pmaxsd m1, m12, [cq+128*7+ 0] + pmaxsd m2, m12, [cq+128*1+32] + pmaxsd m3, m12, [cq+128*7+32] + REPX {pminsd x, m13}, m0, m1, m2, m3 + vpbroadcastd m14, [pd_2896] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_fast + pmaxsd m0, m12, [cq+128*3+ 0] + pmaxsd m1, m12, [cq+128*5+ 0] + pmaxsd m2, m12, [cq+128*3+32] + pmaxsd m3, m12, [cq+128*5+32] + REPX {pminsd x, m13}, m0, m1, m2, m3 + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_fast + pmaxsd m0, m12, [cq+128*2+ 0] + pmaxsd m1, m12, [cq+128*6+ 0] + pmaxsd m2, m12, [cq+128*2+32] + pmaxsd m3, m12, [cq+128*6+32] + REPX {pminsd x, m13}, m0, m1, m2, m3 + call m(idct_8x16_internal_10bpc).main_oddhalf_fast + pmaxsd m0, m12, [cq+128*0+ 0] + pmaxsd m1, m12, [cq+128*4+ 0] + pmaxsd m2, m12, [cq+128*0+32] + pmaxsd m3, m12, [cq+128*4+32] + REPX {pminsd x, m13}, m0, m1, m2, m3 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + jmp .pass2_end +.eob107: + call .pass1_main + cmp eobd, 171 + jge .eob171 + jmp .pass2 +.eob171: + call .pass1_main +.pass2: + mov cq, r4 + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + pmaxsd m0, m12, [cq+128*1+ 0] + pmaxsd m1, m12, [cq+128*7+ 0] + pmaxsd m2, m12, [cq+128*1+32] + pmaxsd m3, m12, [cq+128*7+32] + pmaxsd m4, m12, [cq+128*1+64] + pmaxsd m5, m12, [cq+128*7+64] + pmaxsd m6, m12, [cq+128*1+96] + pmaxsd m7, m12, [cq+128*7+96] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + vpbroadcastd m14, [pd_2896] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1 + pmaxsd m0, m12, [cq+128*3+ 0] + pmaxsd m1, m12, [cq+128*5+ 0] + pmaxsd m2, m12, [cq+128*3+32] + pmaxsd m3, m12, [cq+128*5+32] + pmaxsd m4, m12, [cq+128*3+64] + pmaxsd m5, m12, [cq+128*5+64] + pmaxsd m6, m12, [cq+128*3+96] + pmaxsd m7, m12, [cq+128*5+96] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2 + pmaxsd m0, m12, [cq+128*2+ 0] + pmaxsd m1, m12, [cq+128*6+ 0] + pmaxsd m2, m12, [cq+128*2+32] + pmaxsd m3, m12, [cq+128*6+32] + pmaxsd m4, m12, [cq+128*2+64] + pmaxsd m5, m12, [cq+128*6+64] + pmaxsd m6, m12, [cq+128*2+96] + pmaxsd m7, m12, [cq+128*6+96] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x16_internal_10bpc).main_oddhalf + pmaxsd m0, m12, [cq+128*0+ 0] + pmaxsd m1, m12, [cq+128*4+ 0] + pmaxsd m2, m12, [cq+128*0+32] + pmaxsd m3, m12, [cq+128*4+32] + pmaxsd m4, m12, [cq+128*0+64] + pmaxsd m5, m12, [cq+128*4+64] + pmaxsd m6, m12, [cq+128*0+96] + pmaxsd m7, m12, [cq+128*4+96] + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf +.pass2_end: + psrld m11, 8 ; pd_8 + IDCT32_END 0, 15, 8, 9, 10, 4 + IDCT32_END 1, 14, 8, 9, 10, 4 + punpckhqdq m8, m0, m1 ; 16 17 (interleaved) + punpcklqdq m0, m1 ; 0 1 (interleaved) + punpcklqdq m1, m14, m15 ; 14 15 (interleaved) + punpckhqdq m14, m15 ; 30 31 (interleaved) + mova [r5+32*3], m8 + mova [r5+32*2], m14 + IDCT32_END 2, 15, 8, 9, 10, 4 + IDCT32_END 3, 14, 8, 9, 10, 4 + punpckhqdq m8, m2, m3 ; 18 19 (interleaved) + punpcklqdq m2, m3 ; 2 3 (interleaved) + punpcklqdq m3, m14, m15 ; 12 13 (interleaved) + punpckhqdq m14, m15 ; 28 29 (interleaved) + mova [r5+32*1], m8 + mova [r5+32*0], m14 + IDCT32_END 4, 15, 8, 9, 10, 4 + IDCT32_END 5, 14, 8, 9, 10, 4 + punpckhqdq m8, m4, m5 ; 20 21 (interleaved) + punpcklqdq m4, m5 ; 4 5 (interleaved) + punpcklqdq m5, m14, m15 ; 10 11 (interleaved) + punpckhqdq m14, m15 ; 26 27 (interleaved) + mova [r5-32*1], m8 + mova [r5-32*2], m14 + IDCT32_END 6, 15, 8, 9, 10, 4 + IDCT32_END 7, 14, 8, 9, 10, 4 + punpckhqdq m8, m6, m7 ; 22 23 (interleaved) + punpcklqdq m6, m7 ; 6 7 (interleaved) + punpcklqdq m7, m14, m15 ; 8 9 (interleaved) + punpckhqdq m14, m15 ; 24 25 (interleaved) + mova [r5-32*3], m8 + mova [r5-32*4], m14 + mova m15, m1 +.end: + vpermq m0, m0, q3120 + vpermq m1, m2, q3120 + call m(idct_8x8_internal_12bpc).write_8x4_start + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m4, q3120 + vpermq m1, m6, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m7, q3120 + vpermq m1, m5, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, m3, q3120 + vpermq m1, m15, q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [r5+32*3], q3120 + vpermq m1, [r5+32*1], q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [r5-32*1], q3120 + vpermq m1, [r5-32*3], q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [r5-32*4], q3120 + vpermq m1, [r5-32*2], q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + vpermq m0, [r5+32*0], q3120 + vpermq m1, [r5+32*2], q3120 + call m(idct_8x8_internal_10bpc).write_8x4 + RET +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m2, [dconly_12bpc] + mov [cq], eobd ; 0 + or r3d, 32 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly3 +ALIGN function_align +.pass1_main: + call m(inv_txfm_add_dct_dct_8x32_10bpc).pass1_main_part1 + TRANSPOSE_8X8_DWORD 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15 + mova [cq+128*0], m0 + mova [cq+128*1], m1 + mova [cq+128*2], m2 + mova [cq+128*3], m3 + mova [cq+128*4], m4 + mova [cq+128*5], m5 + mova [cq+128*6], m6 + mova [cq+128*7], m7 + add cq, 32 + ret +ALIGN function_align +.main_end: + psrld m11, 10 ; pd_2 + IDCT32_END 0, 15, 8, 9, 10, 2, 0 + mova [cq+32*16], m8 + mova [cq+32*31], m9 + IDCT32_END 1, 14, 8, 9, 10, 2, 0 + mova [cq+32*17], m8 + mova [cq+32*30], m9 + mova [cq+32*14], m14 + IDCT32_END 2, 14, 8, 9, 10, 2, 0 + mova [cq+32*18], m8 + mova [cq+32*29], m9 + mova [cq+32*13], m14 + IDCT32_END 3, 14, 8, 9, 10, 2, 0 + mova [cq+32*19], m8 + mova [cq+32*28], m9 + mova [cq+32*12], m14 + IDCT32_END 4, 14, 8, 9, 10, 2, 0 + mova [cq+32*20], m8 + mova [cq+32*27], m9 + mova [cq+32* 0], m0 + mova [cq+32* 1], m1 + mova [cq+32* 2], m2 + IDCT32_END 5, 10, 0, 1, 2, 2, 0 + mova [cq+32*21], m0 + mova [cq+32*26], m1 + IDCT32_END 6, 9, 0, 1, 2, 2, 0 + mova [cq+32*22], m0 + mova [cq+32*25], m1 + IDCT32_END 7, 8, 0, 1, 2, 2, 0 + mova [cq+32*23], m0 + mova [cq+32*24], m1 + mova m0, [cq+32* 0] + mova m1, [cq+32* 1] + mova m2, [cq+32* 2] + mova m11, m14 + mova m12, [cq+32*12] + mova m13, [cq+32*13] + mova m14, [cq+32*14] + ret + +cglobal inv_txfm_add_identity_identity_8x32_12bpc, 4, 7, 8, dst, stride, c, eob + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(inv_txfm_add_identity_identity_8x32_10bpc).pass1 + +cglobal inv_txfm_add_dct_dct_32x8_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jnz .full + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 8 +.dconly: + add r6d, 640 + sar r6d, 10 +.dconly2: + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + movd xm0, r6d + paddsw xm0, xm3 + vpbroadcastw m0, xm0 +.dconly_loop: + paddsw m1, m0, [dstq+32*0] + paddsw m2, m0, [dstq+32*1] + psubusw m1, m3 + psubusw m2, m3 + mova [dstq+32*0], m1 + mova [dstq+32*1], m2 + add dstq, strideq + dec r3d + jg .dconly_loop + RET +.full: + PROLOGUE 0, 7, 16, 32*24, dst, stride, c, eob + lea r6, [rsp+32*4] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + call .pass1 + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_end + lea r6, [deint_shuf+128] + vpbroadcastd m11, [pw_2048] + mov r4, dstq + call .pass2 + mova m0, [r5+32*3] ; 16 17 + mova m1, [r5+32*2] ; 30 31 + mova m2, [r5+32*1] ; 18 19 + mova m3, [r5+32*0] ; 28 29 + mova m4, [r5-32*1] ; 20 21 + mova m5, [r5-32*2] ; 26 27 + mova m6, [r5-32*3] ; 22 23 + mova m7, [r5-32*4] ; 24 25 + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + lea dstq, [r4+32] + call .pass2 + RET +ALIGN function_align +.pass2: + call m(idct_16x8_internal_8bpc).main + REPX {pmulhrsw x, m11}, m0, m1, m2, m3 + call m(idct_16x8_internal_10bpc).write_16x4_start + pmulhrsw m0, m11, m4 + pmulhrsw m1, m11, m5 + pmulhrsw m2, m11, m6 + pmulhrsw m3, m11, m7 + jmp m(idct_16x8_internal_10bpc).write_16x4_zero +ALIGN function_align +.pass1: + mova m0, [cq+32* 1] + mova m1, [cq+32* 7] + mova m2, [cq+32* 9] + mova m3, [cq+32*15] + mova m4, [cq+32*17] + mova m5, [cq+32*23] + mova m6, [cq+32*25] + mova m7, [cq+32*31] + vpbroadcastd m11, [pd_2048] + vpbroadcastd m14, [pd_2896] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1 + mova m0, [cq+32* 3] + mova m1, [cq+32* 5] + mova m2, [cq+32*11] + mova m3, [cq+32*13] + mova m4, [cq+32*19] + mova m5, [cq+32*21] + mova m6, [cq+32*27] + mova m7, [cq+32*29] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2 + mova m0, [cq+32* 2] + mova m1, [cq+32* 6] + mova m2, [cq+32*10] + mova m3, [cq+32*14] + mova m4, [cq+32*18] + mova m5, [cq+32*22] + mova m6, [cq+32*26] + mova m7, [cq+32*30] + call m(idct_8x16_internal_10bpc).main_oddhalf + mova m0, [cq+32* 0] + mova m1, [cq+32* 4] + mova m2, [cq+32* 8] + mova m3, [cq+32*12] + mova m4, [cq+32*16] + mova m5, [cq+32*20] + mova m6, [cq+32*24] + mova m7, [cq+32*28] + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + ret + +cglobal inv_txfm_add_identity_identity_32x8_10bpc, 4, 7, 8, dst, stride, c, eob + vpbroadcastd m7, [pixel_10bpc_max] +.pass1: + vpbroadcastd m5, [pw_4096] + pxor m6, m6 + mov r6d, eobd + add eobb, 21 + cmovc eobd, r6d + lea r6, [strideq*3] + lea r5, [strideq*5] + lea r4, [strideq+r6*2] ; strideq*7 +.loop: + mova m0, [cq+32*0] + packssdw m0, [cq+32*1] + mova m1, [cq+32*2] + packssdw m1, [cq+32*3] + REPX {mova [cq+32*x], m6}, 0, 1, 2, 3 + add cq, 32*8 + mova m2, [cq-32*4] + packssdw m2, [cq-32*3] + mova m3, [cq-32*2] + packssdw m3, [cq-32*1] + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {mova [cq+32*x], m6}, -4, -3, -2, -1 + call m(inv_txfm_add_identity_identity_8x32_10bpc).main + add dstq, 16 + sub eobd, 64 + jge .loop + RET + +cglobal inv_txfm_add_dct_dct_32x8_12bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jnz .full + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_12bpc] + mov [cq], eobd ; 0 + or r3d, 8 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).dconly +.full: + PROLOGUE 0, 7, 16, 32*24, dst, stride, c, eob + lea r6, [rsp+32*4] + vpbroadcastd m12, [clip_20b_min] + vpbroadcastd m13, [clip_20b_max] + call m(inv_txfm_add_dct_dct_32x8_10bpc).pass1 + call m(inv_txfm_add_dct_dct_8x32_12bpc).main_end + mov r4, dstq + call m(idct_16x8_internal_12bpc).pass2_main + mova m0, [cq+32* 0] ; 16 + mova m1, [cq+32* 1] ; 17 + mova m2, [cq+32* 2] ; 18 + mova m3, [cq+32* 3] ; 19 + mova m4, [cq+32* 4] ; 20 + mova m5, [cq+32* 5] ; 21 + mova m6, [cq+32* 6] ; 22 + mova m7, [cq+32* 7] ; 23 + mova m8, [cq+32* 8] ; 24 + mova m9, [cq+32* 9] ; 25 + mova m10, [cq+32*10] ; 26 + mova m11, [cq+32*11] ; 27 + mova m12, [cq+32*12] ; 28 + mova m13, [cq+32*13] ; 29 + mova m14, [cq+32*14] ; 30 + mova m15, [cq+32*15] ; 31 + lea dstq, [r4+32] + call m(idct_16x8_internal_12bpc).pass2_main + RET + +cglobal inv_txfm_add_identity_identity_32x8_12bpc, 4, 7, 8, dst, stride, c, eob + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(inv_txfm_add_identity_identity_32x8_10bpc).pass1 + +%macro IDCT32_PASS2_END 6 ; coefs[1-2], tmp[1-2], offset[1-2] + mova m%4, [%2] + paddsw m%3, m%1, m%4 + psubsw m%1, m%4 +%if %1 == 0 + pxor m6, m6 +%endif + pmulhrsw m%3, m15 + pmulhrsw m%1, m15 + paddw m%3, [dstq+%5] + paddw m%1, [r2+%6] + pmaxsw m%3, m6 + pmaxsw m%1, m6 + pminsw m%3, m7 + pminsw m%1, m7 + mova [dstq+%5], m%3 + mova [r2+%6], m%1 +%endmacro + +cglobal inv_txfm_add_dct_dct_16x32_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 8, 16, 32*36, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*16] + lea r4, [r6+32*8] + lea r5, [r6+32*16] + call .main + sub eobd, 44 + jge .eob44 + vperm2i128 m2, m0, m3, 0x31 ; 5 + vinserti128 m0, xm3, 1 ; 1 + vperm2i128 m3, m1, m4, 0x31 ; 7 + vinserti128 m1, xm4, 1 ; 3 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + REPX {mova [r6+32*x], m4}, 0, 1, 2, 3 + jmp .fast +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 32 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + jmp m(inv_txfm_add_dct_dct_16x4_10bpc).dconly2 +.eob44: + mova [r4+16*0], xm0 + mova [r4+16*1], xm3 + mova [r4+16*2], xm1 + mova [r4+16*3], xm4 + vextracti128 [r4+16*4], m0, 1 + vextracti128 [r4+16*5], m3, 1 + vextracti128 [r4+16*6], m1, 1 + vextracti128 [r4+16*7], m4, 1 + call .main + sub eobd, 107 + jge .eob151 + vperm2i128 m7, m1, m4, 0x31 ; 15 + vinserti128 m5, m1, xm4, 1 ; 11 + vperm2i128 m6, m0, m3, 0x31 ; 13 + vinserti128 m4, m0, xm3, 1 ; 9 + mova m0, [r4+32*0] + mova m1, [r4+32*1] + mova m2, [r4+32*2] + mova m3, [r4+32*3] +.fast: + lea r6, [pw_5+128] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + jmp .idct16 +.eob151: + mova [r4-16*8], xm0 + mova [r4-16*7], xm3 + mova [r4-16*6], xm1 + mova [r4-16*5], xm4 + vextracti128 [r4-16*4], m0, 1 + vextracti128 [r4-16*3], m3, 1 + vextracti128 [r4-16*2], m1, 1 + vextracti128 [r4-16*1], m4, 1 + call .main + sub eobd, 128 + jge .eob279 + vperm2i128 m10, m0, m3, 0x31 ; 21 + vinserti128 m8, m0, xm3, 1 ; 17 + vperm2i128 m11, m1, m4, 0x31 ; 23 + vinserti128 m9, m1, xm4, 1 ; 19 + pxor m12, m12 + REPX {mova x, m12}, m13, m14, m15 + REPX {mova [r6+32*x], m12}, 0, 1, 2, 3 + jmp .full +.eob279: + mova [r5+16*0], xm0 + mova [r5+16*1], xm3 + mova [r5+16*2], xm1 + mova [r5+16*3], xm4 + vextracti128 [r5+16*4], m0, 1 + vextracti128 [r5+16*5], m3, 1 + vextracti128 [r5+16*6], m1, 1 + vextracti128 [r5+16*7], m4, 1 + call .main + vperm2i128 m14, m0, m3, 0x31 ; 29 + vinserti128 m12, m0, xm3, 1 ; 25 + vperm2i128 m15, m1, m4, 0x31 ; 31 + vinserti128 m13, m1, xm4, 1 ; 27 + mova m8, [r5+32*0] + mova m9, [r5+32*1] + mova m10, [r5+32*2] + mova m11, [r5+32*3] +.full: + mova m0, [r4+32*0] + mova m1, [r4+32*1] + mova m2, [r4+32*2] + mova m3, [r4+32*3] + mova m4, [r4-32*4] + mova m5, [r4-32*3] + mova m6, [r4-32*2] + mova m7, [r4-32*1] + lea r6, [pw_5 + 128] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + lea r3, [rsp+32*8] + mova m8, [r3+32*0] + mova m9, [r3+32*1] + mova m10, [r3+32*2] + mova m11, [r3+32*3] + mova m12, [r3-32*4] + mova m13, [r3-32*3] + mova m14, [r3-32*2] + mova m15, [r3-32*1] +.idct16: + lea r3, [rsp+32*16] + mova m0, [r3+32*0] + mova m1, [r3+32*1] + mova m2, [r3+32*2] + mova m3, [r3+32*3] + mova m4, [r3-32*4] + mova m5, [r3-32*3] + mova m6, [r3-32*2] + mova m7, [r3-32*1] + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq + call .pass2_end + RET +ALIGN function_align +.main: + pmulld m0, m14, [cq+128* 1] + pmulld m1, m14, [cq+128* 3] + pmulld m2, m14, [cq+128* 5] + pmulld m3, m14, [cq+128* 7] + pmulld m4, m14, [cq+128* 9] + pmulld m5, m14, [cq+128*11] + pmulld m6, m14, [cq+128*13] + pmulld m7, m14, [cq+128*15] + call m(idct_8x16_internal_10bpc).main_oddhalf_rect2 + pmulld m0, m14, [cq+128* 0] + pmulld m1, m14, [cq+128* 2] + pmulld m2, m14, [cq+128* 4] + pmulld m3, m14, [cq+128* 6] + pmulld m4, m14, [cq+128* 8] + pmulld m5, m14, [cq+128*10] + pmulld m6, m14, [cq+128*12] + pmulld m7, m14, [cq+128*14] + call m(idct_8x8_internal_10bpc).main_rect2 + call m(idct_8x16_internal_10bpc).main_evenhalf + psrld m15, m11, 11 ; pd_1 + mova m8, [r6-32*4] + mova m9, [r6-32*3] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m10, m0, m8 ; out15 + paddd m0, m8 ; out0 + mova m8, [r6-32*2] + paddd m15, m1, m9 ; out1 + psubd m1, m9 ; out14 + mova m9, [r6-32*1] + REPX {psrad x, 1}, m0, m15, m10, m1 + packssdw m0, m15 + packssdw m1, m10 + psubd m10, m2, m8 ; out13 + paddd m2, m8 ; out2 + mova m8, [r6+32*0] + paddd m15, m3, m9 ; out3 + psubd m3, m9 ; out12 + mova m9, [r6+32*1] + REPX {psrad x, 1}, m2, m15, m10, m3 + packssdw m2, m15 + packssdw m3, m10 + psubd m10, m4, m8 ; out11 + paddd m4, m8 ; out4 + mova m8, [r6+32*2] + paddd m15, m5, m9 ; out5 + psubd m5, m9 ; out10 + mova m9, [r6+32*3] + REPX {psrad x, 1}, m4, m10, m15, m5 + packssdw m4, m15 + packssdw m5, m10 + psubd m10, m6, m8 ; out9 + paddd m6, m8 ; out6 + paddd m15, m7, m9 ; out7 + psubd m7, m9 ; out8 + REPX {psrad x, 1}, m6, m10, m15, m7 + packssdw m6, m15 + packssdw m7, m10 + punpckhwd m8, m0, m2 + punpcklwd m0, m2 + punpckhwd m2, m3, m1 + punpcklwd m3, m1 + punpckhwd m1, m4, m6 + punpcklwd m4, m6 + punpcklwd m6, m7, m5 + punpckhwd m7, m5 + pxor m5, m5 + mov r7d, 128*13 +.main_zero_loop: + mova [cq+r7-128*1], m5 + mova [cq+r7+128*0], m5 + mova [cq+r7+128*1], m5 + mova [cq+r7+128*2], m5 + sub r7d, 128*4 + jg .main_zero_loop + add cq, 32 + punpcklwd m5, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m1 + punpckhwd m4, m1 + punpckhwd m1, m0, m8 + punpcklwd m0, m8 + punpckhwd m8, m6, m7 + punpcklwd m6, m7 + punpcklqdq m7, m1, m4 + punpckhqdq m1, m4 + punpckhqdq m4, m8, m3 + punpcklqdq m8, m3 + punpckhqdq m3, m6, m5 + punpcklqdq m6, m5 + punpcklqdq m5, m0, m2 + punpckhqdq m0, m2 + mova [r6+16*0], xm5 + mova [r6+16*1], xm6 + mova [r6+16*2], xm7 + mova [r6+16*3], xm8 + vextracti128 [r6+16*4], m5, 1 + vextracti128 [r6+16*5], m6, 1 + vextracti128 [r6+16*6], m7, 1 + vextracti128 [r6+16*7], m8, 1 + sub r6, 32*4 + ret +ALIGN function_align +.pass2_end: + mova [rsp+gprsize+32*0], m6 + mova [rsp+gprsize+32*2], m7 + mova [rsp+gprsize+32*3], m15 + vpbroadcastd m15, [pw_2048] + vpbroadcastd m7, [pixel_10bpc_max] + IDCT32_PASS2_END 0, r5+32*3, 1, 6, strideq*0, r3*4 + IDCT32_PASS2_END 4, r5-32*1, 0, 1, strideq*4, strideq*8 + IDCT32_PASS2_END 8, r4+32*3, 0, 4, strideq*8, strideq*4 + IDCT32_PASS2_END 12, r4-32*1, 0, 4, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + mova m1, [rsp+gprsize+32*1] + IDCT32_PASS2_END 1, r5+32*2, 0, 4, strideq*0, r3*4 + IDCT32_PASS2_END 5, r5-32*2, 0, 4, strideq*4, strideq*8 + IDCT32_PASS2_END 9, r4+32*2, 0, 4, strideq*8, strideq*4 + IDCT32_PASS2_END 13, r4-32*2, 0, 4, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + mova m1, [rsp+gprsize+32*0] + IDCT32_PASS2_END 2, r5+32*1, 0, 4, strideq*0, r3*4 + IDCT32_PASS2_END 1, r5-32*3, 0, 4, strideq*4, strideq*8 + IDCT32_PASS2_END 10, r4+32*1, 0, 4, strideq*8, strideq*4 + IDCT32_PASS2_END 14, r4-32*3, 0, 4, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + mova m1, [rsp+gprsize+32*2] + mova m2, [rsp+gprsize+32*3] + IDCT32_PASS2_END 3, r5+32*0, 0, 4, strideq*0, r3*4 + IDCT32_PASS2_END 1, r5-32*4, 0, 4, strideq*4, strideq*8 + IDCT32_PASS2_END 11, r4+32*0, 0, 4, strideq*8, strideq*4 + IDCT32_PASS2_END 2, r4-32*4, 0, 4, r3*4, strideq*0 + ret + +cglobal inv_txfm_add_identity_identity_16x32_10bpc, 4, 7, 12, dst, stride, c, eob + vpbroadcastd m7, [pixel_10bpc_max] +.pass1: + vpbroadcastd m8, [pw_2896x8] + vpbroadcastd m9, [pw_1697x16] + vpbroadcastd m11, [pw_8192] + lea r6, [strideq*5] + pxor m6, m6 + paddw m10, m11, m11 ; pw_16384 + mov r5, dstq + call .main + sub eobd, 36 + jl .ret + add cq, 128*8 + lea dstq, [r5+16] + call .main + sub cq, 128*8-32 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 107 ; eob < 143 + jl .ret + add cq, 128*8 + lea dstq, [r5+16] + call .main + sub cq, 128*8-32 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 128 ; eob < 271 + jl .ret + add cq, 128*8 + lea dstq, [r5+16] + call .main + sub cq, 128*8-32 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 128 ; eob < 399 + jl .ret + add cq, 128*8 + lea dstq, [r5+16] + call .main +.ret: + RET +ALIGN function_align +.main: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + REPX {pmulhrsw x, m8 }, m0, m1, m2, m3 + REPX {IDTX16 x, 4, 9, 10}, 0, 1, 2, 3 + REPX {pmulhrsw x, m11}, m0, m1, m2, m3 + REPX {mova [cq+128*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 +.main2: + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m4 + punpcklwd m0, m4 + punpcklwd m4, m2, m1 + punpckhwd m2, m1 + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + call m(iidentity_8x8_internal_10bpc).write_2x8x2 + punpcklqdq m0, m3, m2 + punpckhqdq m1, m3, m2 + jmp m(iidentity_8x8_internal_10bpc).write_2x8x2 + +cglobal inv_txfm_add_identity_identity_16x32_12bpc, 4, 7, 12, dst, stride, c, eob + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(inv_txfm_add_identity_identity_16x32_10bpc).pass1 + +cglobal inv_txfm_add_dct_dct_32x16_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 8, 16, 32*40, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + lea r6, [rsp+32*4] + call .main + cmp eobd, 36 + jge .full + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, [rsp] + lea r6, [pw_5+128] + mov r7, dstq + call m(idct_16x16_internal_8bpc).main + call .write_16x16 + mova m0, [r5+32*3] + mova m1, [r5+32*2] + mova m2, [r5+32*1] + mova m3, [r5+32*0] + mova m4, [r5-32*1] + mova m5, [r5-32*2] + mova m6, [r5-32*3] + mova m7, [r5-32*4] + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, [rsp] + jmp .end +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).dconly2 +.full: + add cq, 32 + mova [r4+32*3], m0 + mova [r4+32*2], m1 + mova [r4+32*1], m2 + mova [r4+32*0], m3 + mova [r4-32*1], m4 + mova [r4-32*2], m5 + mova [r4-32*3], m6 + mova [r4-32*4], m7 + call .main + sub r4, 32*16 ; topleft 16x8 + call .transpose_16x16 + lea r6, [pw_5+128] + mov r7, dstq + call m(idct_16x16_internal_8bpc).main + call .write_16x16 + mova m0, [r5+32*3] + mova m1, [r5+32*2] + mova m2, [r5+32*1] + mova m3, [r5+32*0] + mova m4, [r5-32*1] + mova m5, [r5-32*2] + mova m6, [r5-32*3] + mova m7, [r5-32*4] + add r4, 32*8 ; bottomleft 16x8 + call .transpose_16x16 +.end: + lea dstq, [r7+32] + call m(idct_16x16_internal_8bpc).main + call .write_16x16 + RET +ALIGN function_align +.transpose_16x16: + punpckhdq m8, m3, m1 + punpckldq m3, m1 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckhdq m2, m7, m5 + punpckldq m7, m5 + punpckhdq m5, m4, m6 + punpckldq m4, m6 + punpckhqdq m6, m0, m4 + punpcklqdq m0, m4 + punpckhqdq m4, m1, m5 + punpcklqdq m1, m5 + punpckhqdq m5, m7, m3 + punpcklqdq m7, m3 + punpckhqdq m3, m2, m8 + punpcklqdq m2, m8 + vinserti128 m8, m0, xm7, 1 + vperm2i128 m12, m0, m7, 0x31 + vinserti128 m9, m6, xm5, 1 + vperm2i128 m13, m6, m5, 0x31 + vinserti128 m10, m1, xm2, 1 + vperm2i128 m14, m1, m2, 0x31 + vinserti128 m11, m4, xm3, 1 + vperm2i128 m15, m4, m3, 0x31 + mova m0, [r4+32*3] + mova m1, [r4+32*2] + mova m2, [r4+32*1] + mova m3, [r4+32*0] + mova m4, [r4-32*1] + mova m5, [r4-32*2] + mova m6, [r4-32*3] + mova m7, [r4-32*4] + mova [rsp+gprsize], m15 + jmp m(inv_txfm_add_dct_dct_8x32_10bpc).transpose +ALIGN function_align +.main: + vpbroadcastd m14, [pd_2896] + vpbroadcastd m11, [pd_2048] + pmulld m0, m14, [cq+64* 1] + pmulld m1, m14, [cq+64* 7] + pmulld m2, m14, [cq+64* 9] + pmulld m3, m14, [cq+64*15] + pmulld m4, m14, [cq+64*17] + pmulld m5, m14, [cq+64*23] + pmulld m6, m14, [cq+64*25] + pmulld m7, m14, [cq+64*31] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_rect2 + pmulld m0, m14, [cq+64* 3] + pmulld m1, m14, [cq+64* 5] + pmulld m2, m14, [cq+64*11] + pmulld m3, m14, [cq+64*13] + pmulld m4, m14, [cq+64*19] + pmulld m5, m14, [cq+64*21] + pmulld m6, m14, [cq+64*27] + pmulld m7, m14, [cq+64*29] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_rect2 + pmulld m0, m14, [cq+64* 2] + pmulld m1, m14, [cq+64* 6] + pmulld m2, m14, [cq+64*10] + pmulld m3, m14, [cq+64*14] + pmulld m4, m14, [cq+64*18] + pmulld m5, m14, [cq+64*22] + pmulld m6, m14, [cq+64*26] + pmulld m7, m14, [cq+64*30] + call m(idct_8x16_internal_10bpc).main_oddhalf_rect2 + pmulld m0, m14, [cq+64* 0] + pmulld m1, m14, [cq+64* 4] + pmulld m2, m14, [cq+64* 8] + pmulld m3, m14, [cq+64*12] + pmulld m4, m14, [cq+64*16] + pmulld m5, m14, [cq+64*20] + pmulld m6, m14, [cq+64*24] + pmulld m7, m14, [cq+64*28] + call m(idct_8x8_internal_10bpc).main_rect2 + call m(idct_8x16_internal_10bpc).main_evenhalf + pxor m8, m8 + mov r7d, 64*30 +.main_zero_loop: + mova [cq+r7-64*2], m8 + mova [cq+r7-64*1], m8 + mova [cq+r7+64*0], m8 + mova [cq+r7+64*1], m8 + sub r7d, 64*4 + jg .main_zero_loop +.main_end: + psrld m11, 11 ; pd_1 + IDCT32_END 0, 15, 8, 9, 10, 1 + IDCT32_END 1, 14, 8, 9, 10, 1 + punpckhwd m8, m0, m1 ; 16 17 + punpcklwd m0, m1 ; 0 1 + punpcklwd m1, m14, m15 ; 14 15 + punpckhwd m14, m15 ; 30 31 + mova [r5+32*3], m8 + mova [r5+32*2], m14 + IDCT32_END 2, 15, 8, 9, 10, 1 + IDCT32_END 3, 14, 8, 9, 10, 1 + punpckhwd m8, m2, m3 ; 18 19 + punpcklwd m2, m3 ; 2 3 + punpcklwd m3, m14, m15 ; 12 13 + punpckhwd m14, m15 ; 28 29 + mova [r5+32*1], m8 + mova [r5+32*0], m14 + IDCT32_END 4, 15, 8, 9, 10, 1 + IDCT32_END 5, 14, 8, 9, 10, 1 + punpckhwd m8, m4, m5 ; 20 21 + punpcklwd m4, m5 ; 4 5 + punpcklwd m5, m14, m15 ; 10 11 + punpckhwd m14, m15 ; 26 27 + mova [r5-32*1], m8 + mova [r5-32*2], m14 + IDCT32_END 6, 15, 8, 9, 10, 1 + IDCT32_END 7, 14, 8, 9, 10, 1 + punpckhwd m8, m6, m7 ; 22 23 + punpcklwd m6, m7 ; 6 7 + punpcklwd m7, m14, m15 ; 8 9 + punpckhwd m14, m15 ; 24 25 + mova [r5-32*3], m8 + mova [r5-32*4], m14 + ret +ALIGN function_align +.write_16x16: + mova m1, [rsp+gprsize+32*1] + mova [rsp+gprsize+32*0], m8 + mova [rsp+gprsize+32*1], m9 + mova [rsp+gprsize+32*2], m12 + vpbroadcastd m12, [pw_2048] + vpbroadcastd m9, [pixel_10bpc_max] + lea r3, [strideq*3] + pxor m8, m8 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + pmulhrsw m2, m12 + pmulhrsw m3, m12 + call m(idct_16x8_internal_10bpc).write_16x4 + pmulhrsw m0, m12, m4 + pmulhrsw m1, m12, m5 + pmulhrsw m2, m12, m6 + pmulhrsw m3, m12, m7 + call m(idct_16x8_internal_10bpc).write_16x4 + pmulhrsw m0, m12, [rsp+gprsize+32*0] + pmulhrsw m1, m12, [rsp+gprsize+32*1] + pmulhrsw m2, m12, m10 + pmulhrsw m3, m12, m11 + call m(idct_16x8_internal_10bpc).write_16x4 + pmulhrsw m0, m12, [rsp+gprsize+32*2] + pmulhrsw m1, m12, m13 + pmulhrsw m2, m12, m14 + pmulhrsw m3, m12, m15 + jmp m(idct_16x8_internal_10bpc).write_16x4 + +cglobal inv_txfm_add_identity_identity_32x16_10bpc, 4, 7, 11, dst, stride, c, eob + vpbroadcastd m7, [pixel_10bpc_max] +.pass1: + vpbroadcastd m8, [pw_2896x8] + vpbroadcastd m9, [pw_1697x16] + vpbroadcastd m10, [pw_4096] + lea r6, [strideq*5] + pxor m6, m6 + mov r5, dstq + call .main + sub eobd, 36 + jl .ret + add cq, 32 + lea dstq, [dstq+strideq*4] + call .main + add cq, 64*8-32 + lea dstq, [r5+16*1] + call .main + sub eobd, 107 ; eob < 143 + jl .ret + add cq, 32 + lea dstq, [dstq+strideq*4] + call .main + add cq, 64*8-32 + lea dstq, [r5+16*2] + call .main + sub eobd, 128 ; eob < 271 + jl .ret + add cq, 32 + lea dstq, [dstq+strideq*4] + call .main + add cq, 64*8-32 + lea dstq, [r5+16*3] + call .main + sub eobd, 128 ; eob < 399 + jl .ret + add cq, 32 + lea dstq, [dstq+strideq*4] + call .main +.ret: + RET +ALIGN function_align +.main: + mova m0, [cq+64*0] + packssdw m0, [cq+64*1] + mova m1, [cq+64*2] + packssdw m1, [cq+64*3] + mova m2, [cq+64*4] + packssdw m2, [cq+64*5] + mova m3, [cq+64*6] + packssdw m3, [cq+64*7] + REPX {pmulhrsw x, m8 }, m0, m1, m2, m3 + REPX {paddsw x, x }, m0, m1, m2, m3 + REPX {IDTX16 x, 4, 9, _ }, 0, 1, 2, 3 + REPX {pmulhrsw x, m10}, m0, m1, m2, m3 + REPX {mova [cq+64*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + jmp m(inv_txfm_add_identity_identity_16x32_10bpc).main2 + +cglobal inv_txfm_add_identity_identity_32x16_12bpc, 4, 7, 11, dst, stride, c, eob + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(inv_txfm_add_identity_identity_32x16_10bpc).pass1 + +cglobal inv_txfm_add_dct_dct_32x32_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 8, 16, 32*83, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + lea r6, [rsp+32*7] + call .main + cmp eobd, 36 + jl .fast + call .main + cmp eobd, 136 + jl .fast + call .main + cmp eobd, 300 + jl .fast + call .main + jmp .pass2 +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).dconly +.fast: + lea r4, [rsp+32*71] + pxor m0, m0 +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + cmp r6, r4 + jl .fast_loop +.pass2: + lea r3, [rsp+32*3] + mov r4, r6 + lea r5, [r6+32*8] + lea r6, [pw_5+128] + call .pass2_oddhalf + call .pass2_evenhalf + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq + call m(inv_txfm_add_dct_dct_16x32_10bpc).pass2_end + sub dstq, r3 + lea r2, [r2+r3+32] + add dstq, 32 + lea r3, [rsp+32*11] + call .pass2_oddhalf + call .pass2_evenhalf + lea r3, [strideq*3] + call m(inv_txfm_add_dct_dct_16x32_10bpc).pass2_end + RET +ALIGN function_align +.main: + mova m0, [cq+128* 1] + mova m1, [cq+128* 7] + mova m2, [cq+128* 9] + mova m3, [cq+128*15] + mova m4, [cq+128*17] + mova m5, [cq+128*23] + mova m6, [cq+128*25] + mova m7, [cq+128*31] + vpbroadcastd m11, [pd_2048] + vpbroadcastd m14, [pd_2896] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1 + mova m0, [cq+128* 3] + mova m1, [cq+128* 5] + mova m2, [cq+128*11] + mova m3, [cq+128*13] + mova m4, [cq+128*19] + mova m5, [cq+128*21] + mova m6, [cq+128*27] + mova m7, [cq+128*29] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2 + mova m0, [cq+128* 2] + mova m1, [cq+128* 6] + mova m2, [cq+128*10] + mova m3, [cq+128*14] + mova m4, [cq+128*18] + mova m5, [cq+128*22] + mova m6, [cq+128*26] + mova m7, [cq+128*30] + call m(idct_8x16_internal_10bpc).main_oddhalf + mova m0, [cq+128* 0] + mova m1, [cq+128* 4] + mova m2, [cq+128* 8] + mova m3, [cq+128*12] + mova m4, [cq+128*16] + mova m5, [cq+128*20] + mova m6, [cq+128*24] + mova m7, [cq+128*28] + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_end + pxor m15, m15 + mov r7d, 128*29 +.main_zero_loop: + mova [cq+r7-128*1], m15 + mova [cq+r7+128*0], m15 + mova [cq+r7+128*1], m15 + mova [cq+r7+128*2], m15 + sub r7d, 128*4 + jg .main_zero_loop + add cq, 32 + mova [r4-32*4], m0 + mova [r4-32*3], m1 + mova [r4-32*2], m2 + mova [r4-32*1], m3 + mova [r4+32*0], m4 + mova [r4+32*1], m5 + mova [r4+32*2], m6 + mova [r4+32*3], m7 + mova m0, [r5+32*3] + mova m1, [r5+32*2] + mova m2, [r5+32*1] + mova m3, [r5+32*0] + mova m4, [r5-32*1] + mova m5, [r5-32*2] + mova m6, [r5-32*3] + mova m7, [r5-32*4] + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + mova [r5-32*4], m0 + mova [r5-32*3], m1 + mova [r5-32*2], m2 + mova [r5-32*1], m3 + mova [r5+32*0], m4 + mova [r5+32*1], m5 + mova [r5+32*2], m6 + mova [r5+32*3], m7 + ret +ALIGN function_align +.pass2_oddhalf: + mova m0, [r3+32* 1] ; 1 + mova m1, [r3+32* 3] ; 3 + mova m2, [r3+32* 5] ; 5 + mova m3, [r3+32* 7] ; 7 + mova m4, [r3+32*17] ; 9 + mova m5, [r3+32*19] ; 11 + mova m6, [r3+32*21] ; 13 + mova m7, [r3+32*23] ; 15 + mova m8, [r3+32*33] ; 17 + mova m9, [r3+32*35] ; 19 + mova m10, [r3+32*37] ; 21 + mova m11, [r3+32*39] ; 23 + mova m12, [r3+32*49] ; 25 + mova m13, [r3+32*51] ; 27 + mova m14, [r3+32*53] ; 29 + mova m15, [r3+32*55] ; 31 + jmp m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf +ALIGN function_align +.pass2_evenhalf: + mova m0, [r3+32* 0] ; 0 + mova m1, [r3+32* 2] ; 2 + mova m2, [r3+32* 4] ; 4 + mova m3, [r3+32* 6] ; 6 + mova m4, [r3+32*16] ; 8 + mova m5, [r3+32*18] ; 10 + mova m6, [r3+32*20] ; 12 + mova m7, [r3+32*22] ; 14 + mova m8, [r3+32*32] ; 16 + mova m9, [r3+32*34] ; 18 + mova m10, [r3+32*36] ; 20 + mova m11, [r3+32*38] ; 22 + mova m12, [r3+32*48] ; 24 + mova m13, [r3+32*50] ; 26 + mova m14, [r3+32*52] ; 28 + mova m15, [r3+32*54] ; 30 + mova [rsp+gprsize], m15 + jmp m(idct_16x16_internal_8bpc).main + +cglobal inv_txfm_add_identity_identity_32x32_10bpc, 4, 8, 8, dst, stride, c, eob +%undef cmp + vpbroadcastd m7, [pixel_10bpc_max] +.pass1: + vpbroadcastd m5, [pw_8192] + pxor m6, m6 + lea r6, [strideq*3] + lea r5, [strideq*5] + lea r4, [strideq+r6*2] ; strideq*7 + call .main ; 0 + cmp eobd, 36 + jl .ret + add cq, 128*8 ; 0 1 + mov r7, dstq ; 1 + add dstq, 16 + call .main + call .main2 + cmp eobd, 136 + jl .ret + add cq, 128*16-32 ; 0 1 2 + lea dstq, [r7+16*2] ; 1 2 + call .main ; 2 + call .main2 + call .main2 + cmp eobd, 300 + jl .ret + add cq, 128*24-64 ; 0 1 2 3 + add r7, 16*3 ; 1 2 3 + mov dstq, r7 ; 2 3 + call .main ; 3 + call .main2 + call .main2 + call .main2 + cmp eobd, 535 + jl .ret + add cq, 128*24-64 ; 0 1 2 3 + lea dstq, [r7+strideq*8] ; 1 2 3 4 + mov r7, dstq ; 2 3 4 + call .main ; 3 4 + call .main2 + call .main2 + cmp eobd, 755 + jl .ret + add cq, 128*16-32 ; 0 1 2 3 + lea dstq, [r7+strideq*8] ; 1 2 3 4 + call .main ; 2 3 4 5 + call .main2 ; 3 4 5 + cmp eobd, 911 + jl .ret + add cq, 128*8 ; 0 1 2 3 + add dstq, 16 ; 1 2 3 4 + call .main ; 2 3 4 5 +.ret: ; 3 4 5 6 + RET +ALIGN function_align +.main2: + sub cq, 128*8-32 + lea dstq, [dstq+strideq*8-16] +.main: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + jmp m(inv_txfm_add_identity_identity_8x32_10bpc).main_zero + +cglobal inv_txfm_add_identity_identity_32x32_12bpc, 4, 8, 8, dst, stride, c, eob + vpbroadcastd m7, [pixel_12bpc_max] + jmp m(inv_txfm_add_identity_identity_32x32_10bpc).pass1 + +%macro IDCT64_PART2_END 6-10 ; out, src[1-2], tmp[1-3], (offset[1-4]) +%if %1 & 1 + mova m%5, [r5-32*(51-%1)] ; idct16 out 0+n + mova m%4, [r4-32*(14+%1)] ; idct32 out31-n +%else + mova m%5, [r4-32*(45-%1)] + mova m%4, [r5-32*(20+%1)] +%endif + paddsw m%6, m%5, m%4 ; idct32 out 0+n + psubsw m%5, m%4 ; idct32 out31-n + paddsw m%4, m%5, m%3 ; out31-n + psubsw m%5, m%3 ; out32+n + paddsw m%3, m%6, m%2 ; out 0+n + psubsw m%6, m%2 ; out63-n + REPX {pmulhrsw x, m14}, m%5, m%6, m%4, m%3 +%if %1 & 1 + %define %%d0 r2 + %define %%d1 dstq +%else + %define %%d0 dstq + %define %%d1 r2 +%endif + paddw m%3, [%%d0+%7 ] + paddw m%4, [%%d1+%8 ] + paddw m%5, [%%d0+%9 ] + paddw m%6, [%%d1+%10] + pxor m%2, m%2 + REPX {pmaxsw x, m%2}, m%3, m%4, m%5, m%6 + vpbroadcastd m%2, [pixel_10bpc_max] + REPX {pminsw x, m%2}, m%3, m%4, m%5, m%6 + mova [%%d0+%7 ], m%3 + mova [%%d1+%8 ], m%4 + mova [%%d0+%9 ], m%5 + mova [%%d1+%10], m%6 +%endmacro + +cglobal inv_txfm_add_dct_dct_16x64_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 10, 16, 32*98, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*6] + call .main + sub eobd, 44 + jl .fast + call .main + sub eobd, 107 + jl .fast + call .main + sub eobd, 128 + jl .fast + call .main + jmp .pass2 +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 64 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_16x4_10bpc).dconly3 +.fast: + lea r4, [rsp+32*38] + pxor m0, m0 +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + cmp r6, r4 + jl .fast_loop +.pass2: + lea r6, [pw_5+128] + mova m0, [rsp+32* 2] ; in0 + mova m1, [rsp+32* 6] ; in4 + mova m2, [rsp+32*10] ; in8 + mova m3, [rsp+32*14] ; in12 + mova m4, [rsp+32*18] ; in16 + mova m5, [rsp+32*22] ; in20 + mova m6, [rsp+32*26] ; in24 + mova m7, [rsp+32*30] ; in28 + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + lea r4, [rsp+32*38] + mova [r4-32*4], m0 + mova [r4-32*3], m1 + mova [r4-32*2], m2 + mova [r4-32*1], m3 + mova [r4+32*0], m4 + mova [r4+32*1], m5 + mova [r4+32*2], m6 + mova [r4+32*3], m7 + add r4, 32*8 + mova [r4-32*4], m8 + mova [r4-32*3], m9 + mova [r4-32*2], m10 + mova [r4-32*1], m11 + mova [r4+32*0], m12 + mova [r4+32*1], m13 + mova [r4+32*2], m14 + mova [r4+32*3], m15 + mova m0, [rsp+32* 4] ; in2 + mova m1, [rsp+32* 8] ; in6 + mova m2, [rsp+32*12] ; in10 + mova m3, [rsp+32*16] ; in14 + mova m4, [rsp+32*20] ; in18 + mova m5, [rsp+32*24] ; in22 + mova m6, [rsp+32*28] ; in26 + mova m7, [rsp+32*32] ; in30 + lea r5, [r4+32*16] + add r4, 32*8 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova m0, [rsp+32* 3] ; in1 + mova m1, [rsp+32*33] ; in31 + mova m2, [rsp+32*19] ; in17 + mova m3, [rsp+32*17] ; in15 + mova m4, [rsp+32*11] ; in9 + mova m5, [rsp+32*25] ; in23 + mova m6, [rsp+32*27] ; in25 + mova m7, [rsp+32* 9] ; in7 + lea r6, [idct64_mul - 8] + add r4, 32*16 + add r5, 32*32 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + mova m0, [rsp+32* 7] ; in5 + mova m1, [rsp+32*29] ; in27 + mova m2, [rsp+32*23] ; in21 + mova m3, [rsp+32*13] ; in11 + mova m4, [rsp+32*15] ; in13 + mova m5, [rsp+32*21] ; in19 + mova m6, [rsp+32*31] ; in29 + mova m7, [rsp+32* 5] ; in3 + add r6, 8 + add r4, 32*8 + sub r5, 32*8 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + lea r8, [strideq*4] + lea r9, [strideq*5] + lea r3, [r9+strideq*1] ; stride*6 + lea r7, [r9+strideq*2] ; stride*7 + call .main_part2_pass2 + RET +ALIGN function_align +.main: + mova m0, [cq+128* 1] + mova m1, [cq+128* 3] + mova m2, [cq+128* 5] + mova m3, [cq+128* 7] + mova m4, [cq+128* 9] + mova m5, [cq+128*11] + mova m6, [cq+128*13] + mova m7, [cq+128*15] + call m(idct_8x16_internal_10bpc).main_oddhalf + mova m0, [cq+128* 0] + mova m1, [cq+128* 2] + mova m2, [cq+128* 4] + mova m3, [cq+128* 6] + mova m4, [cq+128* 8] + mova m5, [cq+128*10] + mova m6, [cq+128*12] + mova m7, [cq+128*14] + call m(idct_8x8_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_evenhalf + pxor m15, m15 + mov r7d, 128*13 +.main_zero_loop: + mova [cq+r7-128*1], m15 + mova [cq+r7+128*0], m15 + mova [cq+r7+128*1], m15 + mova [cq+r7+128*2], m15 + sub r7d, 128*4 + jg .main_zero_loop + add cq, 32 + psrld m15, m11, 10 ; pd_2 + mova m8, [r6-32*4] + mova m9, [r6+32*3] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m10, m0, m8 ; out15 + paddd m0, m8 ; out0 + mova m8, [r6-32*3] + psubd m15, m7, m9 ; out8 + paddd m7, m9 ; out7 + mova m9, [r6+32*2] + REPX {psrad x, 2}, m0, m15, m10, m7 + packssdw m0, m15 + packssdw m7, m10 + psubd m10, m1, m8 ; out14 + paddd m1, m8 ; out1 + mova m8, [r6-32*2] + psubd m15, m6, m9 ; out9 + paddd m6, m9 ; out6 + mova m9, [r6+32*1] + REPX {psrad x, 2}, m1, m15, m10, m6 + packssdw m1, m15 + packssdw m6, m10 + psubd m10, m2, m8 ; out13 + paddd m2, m8 ; out2 + mova m8, [r6-32*1] + psubd m15, m5, m9 ; out10 + paddd m5, m9 ; out5 + mova m9, [r6+32*0] + REPX {psrad x, 2}, m2, m15, m10, m5 + packssdw m2, m15 + packssdw m5, m10 + psubd m10, m3, m8 ; out12 + paddd m3, m8 ; out3 + psubd m15, m4, m9 ; out11 + paddd m4, m9 ; out4 + REPX {psrad x, 2}, m3, m15, m10, m4 + packssdw m3, m15 + packssdw m4, m10 + call m(idct_16x8_internal_10bpc).transpose3 + mova [r6-32*4], m0 + mova [r6-32*3], m1 + mova [r6-32*2], m2 + mova [r6-32*1], m3 + mova [r6+32*0], m4 + mova [r6+32*1], m5 + mova [r6+32*2], m6 + mova [r6+32*3], m7 + add r6, 32*8 + ret +.main_part2_pass2: + vpbroadcastd m11, [pw_1567_3784] + vpbroadcastd m12, [pw_m3784_1567] + vpbroadcastd m13, [pw_2896_2896] + lea r6, [pw_5+128] + lea r2, [dstq+r7] +.main_part2_pass2_loop: + vpbroadcastd m14, [pw_m2896_2896] + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_internal + vpbroadcastd m14, [pw_2048] + IDCT64_PART2_END 0, 7, 0, 6, 9, 10, strideq*0, r3*4, r8*8, r7*8 + IDCT64_PART2_END 7, 8, 5, 0, 6, 7, strideq*0, r3*4, r8*8, r7*8 + IDCT64_PART2_END 8, 2, 1, 0, 6, 7, strideq*8, r8*4, r9*8, r3*8 + IDCT64_PART2_END 15, 3, 4, 0, 6, 7, strideq*8, r8*4, r9*8, r3*8 + add dstq, strideq + sub r2, strideq + cmp r4, r5 + jne .main_part2_pass2_loop + ret +ALIGN function_align +.main_part1_rect2: + REPX {paddd x, m11}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_part1: ; idct64 steps 1-5 + ; in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + ; in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + ; in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + ; in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + vpbroadcastd m7, [r5+4*0] + vpbroadcastd m8, [r5+4*1] + vpbroadcastd m6, [r5+4*2] + vpbroadcastd m9, [r5+4*3] + vpbroadcastd m5, [r5+4*4] + vpbroadcastd m10, [r5+4*5] + vpbroadcastd m4, [r5+4*6] + vpbroadcastd m15, [r5+4*7] + pmulld m7, m0 ; t63a + pmulld m0, m8 ; t32a + pmulld m6, m1 ; t62a + pmulld m1, m9 ; t33a + pmulld m5, m2 ; t61a + pmulld m2, m10 ; t34a + pmulld m4, m3 ; t60a + pmulld m3, m15 ; t35a + vpbroadcastd m10, [r5+4*8] + vpbroadcastd m15, [r5+4*9] + REPX {paddd x, m11}, m7, m0, m6, m1, m5, m2, m4, m3 + REPX {psrad x, 12 }, m0, m1, m7, m6, m2, m3, m5, m4 + psubd m8, m0, m1 ; t33 + paddd m0, m1 ; t32 + psubd m1, m7, m6 ; t62 + paddd m7, m6 ; t63 + psubd m6, m3, m2 ; t34 + paddd m3, m2 ; t35 + psubd m2, m4, m5 ; t61 + paddd m4, m5 ; t60 + REPX {pmaxsd x, m12}, m8, m1, m6, m2 + REPX {pminsd x, m13}, m8, m1, m6, m2 + ITX_MULSUB_2D 1, 8, 5, 9, _, 11, 10, 15 ; t33a, t62a + ITX_MULSUB_2D 2, 6, 5, 9, _, 11, 10, 15, 2 ; t61a, t34a + REPX {pmaxsd x, m12}, m0, m3, m7, m4 + REPX {pminsd x, m13}, m0, m3, m7, m4 + vpbroadcastd m10, [r5+4*10] + vpbroadcastd m15, [r5+4*11] + psubd m5, m0, m3 ; t35a + paddd m0, m3 ; t32a + psubd m3, m7, m4 ; t60a + paddd m7, m4 ; t63a + psubd m4, m1, m6 ; t34 + paddd m1, m6 ; t33 + psubd m6, m8, m2 ; t61 + paddd m8, m2 ; t62 + REPX {pmaxsd x, m12}, m5, m3, m4, m6 + REPX {pminsd x, m13}, m5, m3, m4, m6 + ITX_MULSUB_2D 3, 5, 2, 9, _, 11, 10, 15 ; t35, t60 + ITX_MULSUB_2D 6, 4, 2, 9, _, 11, 10, 15 ; t34a, t61a + REPX {pmaxsd x, m12}, m0, m7, m1, m8 + REPX {pminsd x, m13}, m0, m7, m1, m8 + add r5, 4*12 + mova [r6-32*4], m0 + mova [r6+32*3], m7 + mova [r6-32*3], m1 + mova [r6+32*2], m8 + mova [r6-32*2], m6 + mova [r6+32*1], m4 + mova [r6-32*1], m3 + mova [r6+32*0], m5 + add r6, 32*8 + ret +.main_part2: ; idct64 steps 6-9 + lea r5, [r6+32*3] + sub r6, 32*4 + vpbroadcastd m10, [pd_1567] + vpbroadcastd m15, [pd_3784] +.main_part2_loop: + mova m0, [r6-32*32] ; t32a + mova m1, [r5-32*24] ; t39a + mova m2, [r5-32*32] ; t63a + mova m3, [r6-32*24] ; t56a + mova m4, [r6-32*16] ; t40a + mova m5, [r5-32* 8] ; t47a + mova m6, [r5-32*16] ; t55a + mova m7, [r6-32* 8] ; t48a + psubd m8, m0, m1 ; t39 + paddd m0, m1 ; t32 + psubd m1, m2, m3 ; t56 + paddd m2, m3 ; t63 + psubd m3, m5, m4 ; t40 + paddd m5, m4 ; t47 + psubd m4, m7, m6 ; t55 + paddd m7, m6 ; t48 + REPX {pmaxsd x, m12}, m8, m1, m3, m4 + REPX {pminsd x, m13}, m8, m1, m3, m4 + ITX_MULSUB_2D 1, 8, 6, 9, _, 11, 10, 15 ; t39a, t56a + ITX_MULSUB_2D 4, 3, 6, 9, _, 11, 10, 15, 2 ; t55a, t40a + REPX {pmaxsd x, m12}, m0, m2, m5, m7 + REPX {pminsd x, m13}, m0, m5, m2, m7 + psubd m6, m2, m7 ; t48a + paddd m2, m7 ; t63a + psubd m7, m0, m5 ; t47a + paddd m0, m5 ; t32a + psubd m5, m8, m4 ; t55 + paddd m8, m4 ; t56 + psubd m4, m1, m3 ; t40 + paddd m1, m3 ; t39 + REPX {pmaxsd x, m12}, m6, m7, m5, m4 + REPX {pminsd x, m13}, m6, m7, m5, m4 + REPX {pmulld x, m14}, m6, m7, m5, m4 + REPX {pmaxsd x, m12}, m2, m0, m8, m1 + REPX {pminsd x, m13}, m2, m0, m8, m1 + paddd m6, m11 + paddd m5, m11 + psubd m3, m6, m7 ; t47 + paddd m6, m7 ; t48 + psubd m7, m5, m4 ; t40a + paddd m5, m4 ; t55a + REPX {psrad x, 12}, m3, m6, m7, m5 + mova [r5-32* 8], m2 + mova [r6-32*32], m0 + mova [r6-32* 8], m8 + mova [r5-32*32], m1 + mova [r5-32*24], m3 + mova [r6-32*16], m6 + mova [r6-32*24], m7 + mova [r5-32*16], m5 + add r6, 32 + sub r5, 32 + cmp r6, r5 + jl .main_part2_loop + ret + +cglobal inv_txfm_add_dct_dct_32x64_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 11, 16, 32*134, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + lea r6, [rsp+32*6] + call .main + cmp eobd, 36 + jl .fast + call .main + cmp eobd, 136 + jl .fast + call .main + cmp eobd, 300 + jl .fast + call .main + jmp .pass2 +.dconly: + imul r6d, [cq], 181 + vpbroadcastd m3, [dconly_10bpc] + mov [cq], eobd ; 0 + or r3d, 64 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).dconly2 +.fast: + lea r4, [rsp+32*70] + pxor m0, m0 +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + cmp r6, r4 + jl .fast_loop +.pass2: + lea r6, [pw_5 + 128] + mov r10, rsp + lea r8, [strideq*4] + lea r9, [strideq*5] + lea r3, [r9+strideq*1] ; stride*6 + lea r7, [r9+strideq*2] ; stride*7 +.pass2_loop: + mova m0, [r10+32* 2] ; in0 + mova m1, [r10+32* 6] ; in4 + mova m2, [r10+32*18] ; in8 + mova m3, [r10+32*22] ; in12 + mova m4, [r10+32*34] ; in16 + mova m5, [r10+32*38] ; in20 + mova m6, [r10+32*50] ; in24 + mova m7, [r10+32*54] ; in28 + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + lea r4, [rsp+32*70] + mova [r4-32*4], m0 + mova [r4-32*3], m1 + mova [r4-32*2], m2 + mova [r4-32*1], m3 + mova [r4+32*0], m4 + mova [r4+32*1], m5 + mova [r4+32*2], m6 + mova [r4+32*3], m7 + add r4, 32*8 + mova [r4-32*4], m8 + mova [r4-32*3], m9 + mova [r4-32*2], m10 + mova [r4-32*1], m11 + mova [r4+32*0], m12 + mova [r4+32*1], m13 + mova [r4+32*2], m14 + mova [r4+32*3], m15 + mova m0, [r10+32* 4] ; in2 + mova m1, [r10+32* 8] ; in6 + mova m2, [r10+32*20] ; in10 + mova m3, [r10+32*24] ; in14 + mova m4, [r10+32*36] ; in18 + mova m5, [r10+32*40] ; in22 + mova m6, [r10+32*52] ; in26 + mova m7, [r10+32*56] ; in30 + lea r5, [r4+32*16] + add r4, 32*8 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova m0, [r10+32* 3] ; in1 + mova m1, [r10+32*57] ; in31 + mova m2, [r10+32*35] ; in17 + mova m3, [r10+32*25] ; in15 + mova m4, [r10+32*19] ; in9 + mova m5, [r10+32*41] ; in23 + mova m6, [r10+32*51] ; in25 + mova m7, [r10+32* 9] ; in7 + lea r6, [idct64_mul - 8] + add r4, 32*16 + add r5, 32*32 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + mova m0, [r10+32* 7] ; in5 + mova m1, [r10+32*53] ; in27 + mova m2, [r10+32*39] ; in21 + mova m3, [r10+32*21] ; in11 + mova m4, [r10+32*23] ; in13 + mova m5, [r10+32*37] ; in19 + mova m6, [r10+32*55] ; in29 + mova m7, [r10+32* 5] ; in3 + add r6, 8 + add r4, 32*8 + sub r5, 32*8 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part2_pass2 + add r10, 32*8 + sub r4, 32*98 ; rsp+32*16 + sub dstq, r8 + add dstq, 32 + cmp r10, r4 + jl .pass2_loop + RET +ALIGN function_align +.main: + vpbroadcastd m14, [pd_2896] + vpbroadcastd m11, [pd_2048] + pmulld m0, m14, [cq+128* 1] + pmulld m1, m14, [cq+128* 7] + pmulld m2, m14, [cq+128* 9] + pmulld m3, m14, [cq+128*15] + pmulld m4, m14, [cq+128*17] + pmulld m5, m14, [cq+128*23] + pmulld m6, m14, [cq+128*25] + pmulld m7, m14, [cq+128*31] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_rect2 + pmulld m0, m14, [cq+128* 3] + pmulld m1, m14, [cq+128* 5] + pmulld m2, m14, [cq+128*11] + pmulld m3, m14, [cq+128*13] + pmulld m4, m14, [cq+128*19] + pmulld m5, m14, [cq+128*21] + pmulld m6, m14, [cq+128*27] + pmulld m7, m14, [cq+128*29] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_rect2 + pmulld m0, m14, [cq+128* 2] + pmulld m1, m14, [cq+128* 6] + pmulld m2, m14, [cq+128*10] + pmulld m3, m14, [cq+128*14] + pmulld m4, m14, [cq+128*18] + pmulld m5, m14, [cq+128*22] + pmulld m6, m14, [cq+128*26] + pmulld m7, m14, [cq+128*30] + call m(idct_8x16_internal_10bpc).main_oddhalf_rect2 + pmulld m0, m14, [cq+128* 0] + pmulld m1, m14, [cq+128* 4] + pmulld m2, m14, [cq+128* 8] + pmulld m3, m14, [cq+128*12] + pmulld m4, m14, [cq+128*16] + pmulld m5, m14, [cq+128*20] + pmulld m6, m14, [cq+128*24] + pmulld m7, m14, [cq+128*28] + pxor m15, m15 + mov r7d, 128*29 +.main_zero_loop: + mova [cq+r7-128*1], m15 + mova [cq+r7+128*0], m15 + mova [cq+r7+128*1], m15 + mova [cq+r7+128*2], m15 + sub r7d, 128*4 + jg .main_zero_loop + add cq, 32 + call m(idct_8x8_internal_10bpc).main_rect2 + call m(idct_8x16_internal_10bpc).main_evenhalf + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_end + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + mova [r4-32*4], m0 + mova [r4-32*3], m1 + mova [r4-32*2], m2 + mova [r4-32*1], m3 + mova [r4+32*0], m4 + mova [r4+32*1], m5 + mova [r4+32*2], m6 + mova [r4+32*3], m7 + mova m0, [r5+32*3] + mova m1, [r5+32*2] + mova m2, [r5+32*1] + mova m3, [r5+32*0] + mova m4, [r5-32*1] + mova m5, [r5-32*2] + mova m6, [r5-32*3] + mova m7, [r5-32*4] + call m(inv_txfm_add_dct_dct_8x32_10bpc).transpose + mova [r5-32*4], m0 + mova [r5-32*3], m1 + mova [r5-32*2], m2 + mova [r5-32*1], m3 + mova [r5+32*0], m4 + mova [r5+32*1], m5 + mova [r5+32*2], m6 + mova [r5+32*3], m7 + ret + +cglobal inv_txfm_add_dct_dct_64x16_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jnz .normal + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 16 +.dconly: + add r6d, 640 + sar r6d, 10 +.dconly2: + vpbroadcastd m5, [dconly_10bpc] + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + movd xm0, r6d + paddsw xm0, xm5 + vpbroadcastw m0, xm0 +.dconly_loop: + paddsw m1, m0, [dstq+32*0] + paddsw m2, m0, [dstq+32*1] + paddsw m3, m0, [dstq+32*2] + paddsw m4, m0, [dstq+32*3] + REPX {psubusw x, m5}, m1, m2, m3, m4 + mova [dstq+32*0], m1 + mova [dstq+32*1], m2 + mova [dstq+32*2], m3 + mova [dstq+32*3], m4 + add dstq, strideq + dec r3d + jg .dconly_loop + RET +.normal: + PROLOGUE 0, 8, 16, 32*96, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*4] + call .main + call .shift_transpose + cmp eobd, 36 + jl .fast + call .main + call .shift_transpose + jmp .pass2 +.fast: + pxor m0, m0 + mov r3d, 4 +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + dec r3d + jg .fast_loop +.pass2: + lea r7, [r6-32*64] + lea r4, [r6-32*32] + lea r6, [pw_5+128] + mov r5, dstq +.pass2_loop: + mova m0, [r7-32*4] + mova m1, [r7-32*3] + mova m2, [r7-32*2] + mova m3, [r7-32*1] + mova m4, [r7+32*0] + mova m5, [r7+32*1] + mova m6, [r7+32*2] + mova m7, [r7+32*3] + add r7, 32*32 + mova m8, [r7-32*4] + mova m9, [r7-32*3] + mova m10, [r7-32*2] + mova m11, [r7-32*1] + mova m12, [r7+32*0] + mova m13, [r7+32*1] + mova m14, [r7+32*2] + mova m15, [r7+32*3] + sub r7, 32*24 + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + call m(inv_txfm_add_dct_dct_32x16_10bpc).write_16x16 + add r5, 32 + mov dstq, r5 + cmp r7, r4 + jl .pass2_loop + RET +ALIGN function_align +.main: + lea r5, [idct64_mul_16bpc] + mova m0, [cq+64* 1] + mova m1, [cq+64*31] + mova m2, [cq+64*17] + mova m3, [cq+64*15] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+64* 7] + mova m1, [cq+64*25] + mova m2, [cq+64*23] + mova m3, [cq+64* 9] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+64* 5] + mova m1, [cq+64*27] + mova m2, [cq+64*21] + mova m3, [cq+64*11] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+64* 3] + mova m1, [cq+64*29] + mova m2, [cq+64*19] + mova m3, [cq+64*13] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part2 + mova m0, [cq+64* 2] + mova m1, [cq+64*14] + mova m2, [cq+64*18] + mova m3, [cq+64*30] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_fast + mova m0, [cq+64* 6] + mova m1, [cq+64*10] + mova m2, [cq+64*22] + mova m3, [cq+64*26] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_fast + mova m0, [cq+64* 4] + mova m1, [cq+64*12] + mova m2, [cq+64*20] + mova m3, [cq+64*28] + call m(idct_8x16_internal_10bpc).main_oddhalf_fast + mova m0, [cq+64* 0] + mova m1, [cq+64* 8] + mova m2, [cq+64*16] + mova m3, [cq+64*24] + pxor m15, m15 + mov r7d, 64*30 +.main_zero_loop: + mova [cq+r7-64*2], m15 + mova [cq+r7-64*1], m15 + mova [cq+r7+64*0], m15 + mova [cq+r7+64*1], m15 + sub r7d, 64*4 + jg .main_zero_loop +.main_end: + psrld m15, m11, 10 ; pd_2 +.main_end2: + add cq, 32 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_10bpc).main + add r6, 32*8 + call m(idct_8x16_internal_10bpc).main_evenhalf + mova [r6+32*2], m1 + mova [r6+32*1], m2 + mova [r6+32*0], m3 + mova [r6-32*1], m4 + mova [r6-32*2], m5 + mova [r6-32*3], m6 + mova [r6-32*4], m7 + jmp .main_end_loop_start +.main_end_loop: + mova m0, [r6+32* 3] ; idct8 0 + n +.main_end_loop_start: + mova m1, [r5+32* 4] ; idct16 15 - n + mova m2, [r5-32*12] ; idct32 16 + n + mova m3, [r6-32*13] ; idct32 31 - n + mova m4, [r6-32*29] ; idct64 63 - n + mova m5, [r5-32*28] ; idct64 48 + n + mova m6, [r6-32*45] ; idct64 47 - n + mova m7, [r5-32*44] ; idct64 32 + n + paddd m8, m0, m1 ; idct16 out0 + n + psubd m0, m1 ; idct16 out15 - n + REPX {pmaxsd x, m12}, m8, m0 + REPX {pminsd x, m13}, m8, m0 + paddd m1, m8, m3 ; idct32 out0 + n + psubd m8, m3 ; idct32 out31 - n + paddd m3, m0, m2 ; idct32 out15 - n + psubd m0, m2 ; idct32 out16 + n + REPX {pmaxsd x, m12}, m1, m8, m3, m0 + REPX {pminsd x, m13}, m1, m3, m8, m0 + REPX {paddd x, m15}, m1, m3, m0, m8 + paddd m2, m1, m4 ; idct64 out0 + n (unshifted) + psubd m1, m4 ; idct64 out63 - n (unshifted) + paddd m4, m3, m5 ; idct64 out15 - n (unshifted) + psubd m3, m5 ; idct64 out48 + n (unshifted) + paddd m5, m0, m6 ; idct64 out16 + n (unshifted) + psubd m0, m6 ; idct64 out47 - n (unshifted) + paddd m6, m8, m7 ; idct64 out31 - n (unshifted) + psubd m8, m7 ; idct64 out32 + n (unshifted) + mova [r5-32*44], m2 + mova [r6+32* 3], m1 + mova [r6-32*45], m4 + mova [r5+32* 4], m3 + mova [r5-32*28], m5 + mova [r6-32*13], m0 + mova [r6-32*29], m6 + mova [r5-32*12], m8 + add r5, 32 + sub r6, 32 + cmp r5, r6 + jl .main_end_loop + ret +.shift_transpose: +%macro IDCT64_SHIFT_TRANSPOSE 1 ; shift + sub r6, 32*48 + mov r5, r6 +%%loop: + mova m0, [r6-32* 4] + mova m4, [r6+32* 4] + mova m1, [r6-32* 3] + mova m5, [r6+32* 5] + mova m2, [r6-32* 2] + mova m6, [r6+32* 6] + mova m3, [r6-32* 1] + mova m7, [r6+32* 7] + REPX {psrad x, %1}, m0, m4, m1, m5, m2, m6, m3, m7 + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + mova m4, [r6+32* 0] + mova m6, [r6+32* 8] + mova m5, [r6+32* 1] + mova m7, [r6+32* 9] + REPX {psrad x, %1}, m4, m6, m5, m7 + packssdw m4, m6 + packssdw m5, m7 + mova m6, [r6+32* 2] + mova m8, [r6+32*10] + mova m7, [r6+32* 3] + mova m9, [r6+32*11] + REPX {psrad x, %1}, m6, m8, m7, m9 + packssdw m6, m8 + packssdw m7, m9 + call m(idct_16x8_internal_10bpc).transpose3 + mova [r5-32*4], m0 + mova [r5-32*3], m1 + mova [r5-32*2], m2 + mova [r5-32*1], m3 + mova [r5+32*0], m4 + mova [r5+32*1], m5 + mova [r5+32*2], m6 + mova [r5+32*3], m7 + add r6, 32*16 + add r5, 32*8 + cmp r5, r4 + jl %%loop + mov r6, r4 +%endmacro + IDCT64_SHIFT_TRANSPOSE 2 + ret + +cglobal inv_txfm_add_dct_dct_64x32_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 8, 16, 32*163, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*7] + call .main + cmp eobd, 36 + jl .fast + call .main + cmp eobd, 136 + jl .fast + call .main + cmp eobd, 300 + jl .fast + call .main + jmp .pass2 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 32 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 + jmp m(inv_txfm_add_dct_dct_64x16_10bpc).dconly2 +.fast: + pxor m0, m0 + lea r4, [rsp+32*135] +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + cmp r6, r4 + jl .fast_loop +.pass2: + lea r7, [r6-32*32] + lea r5, [r6+32*8] + lea r6, [pw_5+128] + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq +.pass2_loop: + mova m0, [r7-32*99] + mova m1, [r7-32*97] + mova m2, [r7-32*95] + mova m3, [r7-32*93] + mova m4, [r7-32*67] + mova m5, [r7-32*65] + mova m6, [r7-32*63] + mova m7, [r7-32*61] + mova m8, [r7-32*35] + mova m9, [r7-32*33] + mova m10, [r7-32*31] + mova m11, [r7-32*29] + mova m12, [r7-32* 3] + mova m13, [r7-32* 1] + mova m14, [r7+32* 1] + mova m15, [r7+32* 3] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + mova m0, [r7-32*100] + mova m1, [r7-32*98] + mova m2, [r7-32*96] + mova m3, [r7-32*94] + mova m4, [r7-32*68] + mova m5, [r7-32*66] + mova m6, [r7-32*64] + mova m7, [r7-32*62] + mova m8, [r7-32*36] + mova m9, [r7-32*34] + mova m10, [r7-32*32] + mova m11, [r7-32*30] + mova m12, [r7-32* 4] + mova m13, [r7-32* 2] + mova m14, [r7+32* 0] + mova m15, [r7+32* 2] + add r7, 32*8 + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_16x32_10bpc).pass2_end + sub dstq, r3 + lea r2, [r2+r3+32] + add dstq, 32 + cmp r7, r4 + jl .pass2_loop + RET +ALIGN function_align +.main: + lea r5, [idct64_mul_16bpc] + pmulld m0, m14, [cq+128* 1] + pmulld m1, m14, [cq+128*31] + pmulld m2, m14, [cq+128*17] + pmulld m3, m14, [cq+128*15] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1_rect2 + pmulld m0, m14, [cq+128* 7] + pmulld m1, m14, [cq+128*25] + pmulld m2, m14, [cq+128*23] + pmulld m3, m14, [cq+128* 9] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1_rect2 + pmulld m0, m14, [cq+128* 5] + pmulld m1, m14, [cq+128*27] + pmulld m2, m14, [cq+128*21] + pmulld m3, m14, [cq+128*11] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1_rect2 + pmulld m0, m14, [cq+128* 3] + pmulld m1, m14, [cq+128*29] + pmulld m2, m14, [cq+128*19] + pmulld m3, m14, [cq+128*13] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1_rect2 + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part2 + pmulld m0, m14, [cq+128* 2] + pmulld m1, m14, [cq+128*14] + pmulld m2, m14, [cq+128*18] + pmulld m3, m14, [cq+128*30] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_fast_rect2 + pmulld m0, m14, [cq+128* 6] + pmulld m1, m14, [cq+128*10] + pmulld m2, m14, [cq+128*22] + pmulld m3, m14, [cq+128*26] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_fast_rect2 + pmulld m0, m14, [cq+128* 4] + pmulld m1, m14, [cq+128*12] + pmulld m2, m14, [cq+128*20] + pmulld m3, m14, [cq+128*28] + call m(idct_8x16_internal_10bpc).main_oddhalf_fast_rect2 + pmulld m0, m14, [cq+128* 0] + pmulld m1, m14, [cq+128* 8] + pmulld m2, m14, [cq+128*16] + pmulld m3, m14, [cq+128*24] + pxor m15, m15 + mov r7d, 128*29 +.main_zero_loop: + mova [cq+r7-128*1], m15 + mova [cq+r7+128*0], m15 + mova [cq+r7+128*1], m15 + mova [cq+r7+128*2], m15 + sub r7d, 128*4 + jg .main_zero_loop + psrld m15, m11, 11 ; pd_1 + REPX {paddd x, m11}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_end2 + IDCT64_SHIFT_TRANSPOSE 1 + ret + +cglobal inv_txfm_add_dct_dct_64x64_10bpc, 4, 7, 0, dst, stride, c, eob + test eobd, eobd + jz .dconly + PROLOGUE 0, 11, 16, 32*195, dst, stride, c, eob +%undef cmp + vpbroadcastd m11, [pd_2048] + vpbroadcastd m12, [clip_18b_min] + vpbroadcastd m13, [clip_18b_max] + vpbroadcastd m14, [pd_2896] + lea r6, [rsp+32*7] + call .main + cmp eobd, 36 + jl .fast + call .main + cmp eobd, 136 + jl .fast + call .main + cmp eobd, 300 + jl .fast + call .main + jmp .pass2 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_64x16_10bpc).dconly +.fast: + pxor m0, m0 + lea r4, [rsp+32*135] +.fast_loop: + REPX {mova [r6+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 + add r6, 32*8 + cmp r6, r4 + jl .fast_loop +.pass2: + lea r10, [r6-32*32] + lea r6, [pw_5+128] + lea r8, [strideq*4] + lea r9, [strideq*5] + lea r3, [r9+strideq*1] ; stride*6 + lea r7, [r9+strideq*2] ; stride*7 +.pass2_loop: + mova m0, [r10-32*100] ; in0 + mova m1, [r10-32*96] ; in4 + mova m2, [r10-32*68] ; in8 + mova m3, [r10-32*64] ; in12 + mova m4, [r10-32*36] ; in16 + mova m5, [r10-32*32] ; in20 + mova m6, [r10-32* 4] ; in24 + mova m7, [r10+32* 0] ; in28 + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [r4-32*4], m0 + mova [r4-32*3], m1 + mova [r4-32*2], m2 + mova [r4-32*1], m3 + mova [r4+32*0], m4 + mova [r4+32*1], m5 + mova [r4+32*2], m6 + mova [r4+32*3], m7 + add r4, 32*8 + mova [r4-32*4], m8 + mova [r4-32*3], m9 + mova [r4-32*2], m10 + mova [r4-32*1], m11 + mova [r4+32*0], m12 + mova [r4+32*1], m13 + mova [r4+32*2], m14 + mova [r4+32*3], m15 + mova m0, [r10-32*98] ; in2 + mova m1, [r10-32*94] ; in6 + mova m2, [r10-32*66] ; in10 + mova m3, [r10-32*62] ; in14 + mova m4, [r10-32*34] ; in18 + mova m5, [r10-32*30] ; in22 + mova m6, [r10-32* 2] ; in26 + mova m7, [r10+32* 2] ; in30 + lea r5, [r4+32*16] + add r4, 32*8 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova m0, [r10-32*99] ; in1 + mova m1, [r10+32* 3] ; in31 + mova m2, [r10-32*35] ; in17 + mova m3, [r10-32*61] ; in15 + mova m4, [r10-32*67] ; in9 + mova m5, [r10-32*29] ; in23 + mova m6, [r10-32* 3] ; in25 + mova m7, [r10-32*93] ; in7 + lea r6, [idct64_mul - 8] + add r4, 32*16 + add r5, 32*32 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + mova m0, [r10-32*95] ; in5 + mova m1, [r10-32* 1] ; in27 + mova m2, [r10-32*31] ; in21 + mova m3, [r10-32*65] ; in11 + mova m4, [r10-32*63] ; in13 + mova m5, [r10-32*33] ; in19 + mova m6, [r10+32* 1] ; in29 + mova m7, [r10-32*97] ; in3 + add r6, 8 + add r4, 32*8 + sub r5, 32*8 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part2_pass2 + add r10, 32*8 + sub dstq, r8 + sub r4, 32*44 + add dstq, 32 + cmp r10, r4 + jl .pass2_loop + RET +ALIGN function_align +.main: + lea r5, [idct64_mul_16bpc] + mova m0, [cq+128* 1] + mova m1, [cq+128*31] + mova m2, [cq+128*17] + mova m3, [cq+128*15] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+128* 7] + mova m1, [cq+128*25] + mova m2, [cq+128*23] + mova m3, [cq+128* 9] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+128* 5] + mova m1, [cq+128*27] + mova m2, [cq+128*21] + mova m3, [cq+128*11] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + mova m0, [cq+128* 3] + mova m1, [cq+128*29] + mova m2, [cq+128*19] + mova m3, [cq+128*13] + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_10bpc).main_part2 + mova m0, [cq+128* 2] + mova m1, [cq+128*14] + mova m2, [cq+128*18] + mova m3, [cq+128*30] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part1_fast + mova m0, [cq+128* 6] + mova m1, [cq+128*10] + mova m2, [cq+128*22] + mova m3, [cq+128*26] + call m(inv_txfm_add_dct_dct_8x32_10bpc).main_oddhalf_part2_fast + mova m0, [cq+128* 4] + mova m1, [cq+128*12] + mova m2, [cq+128*20] + mova m3, [cq+128*28] + call m(idct_8x16_internal_10bpc).main_oddhalf_fast + mova m0, [cq+128* 0] + mova m1, [cq+128* 8] + mova m2, [cq+128*16] + mova m3, [cq+128*24] + pxor m15, m15 + mov r7d, 128*29 +.main_zero_loop: + mova [cq+r7-128*1], m15 + mova [cq+r7+128*0], m15 + mova [cq+r7+128*1], m15 + mova [cq+r7+128*2], m15 + sub r7d, 128*4 + jg .main_zero_loop + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_end + jmp m(inv_txfm_add_dct_dct_64x16_10bpc).shift_transpose + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6056 @@ +; Copyright © 2022-2023, VideoLAN and dav1d authors +; Copyright © 2022-2023, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +idct8x8p: db 0, 1, 4, 5, 2, 3, 6, 7, 16, 17, 20, 21, 18, 19, 22, 23 + db 8, 9, 12, 13, 10, 11, 14, 15, 24, 25, 28, 29, 26, 27, 30, 31 + db 32, 33, 36, 37, 34, 35, 38, 39, 48, 49, 52, 53, 50, 51, 54, 55 + db 40, 41, 44, 45, 42, 43, 46, 47, 56, 57, 60, 61, 58, 59, 62, 63 +idtx8x8p: db 0, 1, 32, 33, 2, 3, 34, 35, 4, 5, 36, 37, 6, 7, 38, 39 + db 8, 9, 40, 41, 10, 11, 42, 43, 12, 13, 44, 45, 14, 15, 46, 47 + db 16, 17, 48, 49, 18, 19, 50, 51, 20, 21, 52, 53, 22, 23, 54, 55 + db 24, 25, 56, 57, 26, 27, 58, 59, 28, 29, 60, 61, 30, 31, 62, 63 +idct8x16p: db 54, 55, 2, 3, 22, 23, 34, 35, 38, 39, 18, 19, 6, 7, 50, 51 + db 62, 63, 10, 11, 30, 31, 42, 43, 46, 47, 26, 27, 14, 15, 58, 59 + db 52, 53, 4, 5, 20, 21, 36, 37, 32, 33, 0, 1, 48, 49, 16, 17 + db 60, 61, 12, 13, 28, 29, 44, 45, 40, 41, 8, 9, 56, 57, 24, 25 +iadst8x16p: db 0, 1, 54, 55, 48, 49, 6, 7, 16, 17, 38, 39, 32, 33, 22, 23 + db 8, 9, 62, 63, 56, 57, 14, 15, 24, 25, 46, 47, 40, 41, 30, 31 + db 4, 5, 50, 51, 52, 53, 2, 3, 20, 21, 34, 35, 36, 37, 18, 19 + db 12, 13, 58, 59, 60, 61, 10, 11, 28, 29, 42, 43, 44, 45, 26, 27 +permA: db 0, 1, 0, 8, 4, 5, 1, 9, 8, 9, 4, 12, 12, 13, 5, 13 + db 16, 17, 16, 24, 20, 21, 17, 25, 24, 25, 20, 28, 28, 29, 21, 29 + db 2, 3, 2, 10, 6, 7, 3, 11, 10, 11, 6, 14, 14, 15, 7, 15 + db 18, 19, 18, 26, 22, 23, 19, 27, 26, 27, 22, 30, 30, 31, 23, 31 +permB: db 4, 2, 1, 8, 0, 0, 1, 0, 12, 3, 3, 10, 8, 1, 3, 2 + db 5, 10, 5, 12, 1, 8, 5, 4, 13, 11, 7, 14, 9, 9, 7, 6 + db 6, 6, 13, 4, 2, 4, 4, 5, 14, 7, 15, 6, 10, 5, 6, 7 + db 7, 14, 9, 0, 3, 12, 0, 1, 15, 15, 11, 2, 11, 13, 2, 3 +permC: db 0, 9, 0, 0, 0, 1, 4, 4, 2, 11, 2, 2, 2, 3, 6, 6 + db 1, 8, 1, 8, 4, 5, 5, 12, 3, 10, 3, 10, 6, 7, 7, 14 + db 9, 1, 8, 1, 1, 0, 12, 5, 11, 3, 10, 3, 3, 2, 14, 7 + db 8, 0, 9, 9, 5, 4, 13, 13, 10, 2, 11, 11, 7, 6, 15, 15 +idct8x32p: db 0, 1, 4, 5, 16, 17, 20, 21, 32, 33, 36, 37, 48, 49, 52, 53 + db 8, 9, 12, 13, 24, 25, 28, 29, 40, 41, 44, 45, 56, 57, 60, 61 + db 2, 3, 6, 7, 18, 19, 22, 23, 34, 35, 38, 39, 50, 51, 54, 55 + db 10, 11, 14, 15, 26, 27, 30, 31, 42, 43, 46, 47, 58, 59, 62, 63 +idct32x8p: db 2, 18, 0, 16, 3, 19, 1, 17, 10, 26, 8, 24, 11, 27, 9, 25 + db 34, 50, 32, 48, 35, 51, 33, 49, 42, 58, 40, 56, 43, 59, 41, 57 + db 6, 22, 4, 20, 7, 23, 5, 21, 14, 30, 12, 28, 15, 31, 13, 29 + db 38, 54, 36, 52, 39, 55, 37, 53, 46, 62, 44, 60, 47, 63, 45, 61 +idtx32x8p: db 0, 8, 16, 24, 4, 12, 20, 28, 2, 10, 18, 26, 6, 14, 22, 30 + db 32, 40, 48, 56, 36, 44, 52, 60, 34, 42, 50, 58, 38, 46, 54, 62 + db 1, 9, 17, 25, 5, 13, 21, 29, 3, 11, 19, 27, 7, 15, 23, 31 + db 33, 41, 49, 57, 37, 45, 53, 61, 35, 43, 51, 59, 39, 47, 55, 63 + +pw_2048_m2048: times 16 dw 2048 +pw_m2048_2048: times 16 dw -2048 +pw_2048: times 16 dw 2048 + +; flags: 0 = ++, 1 = +-, 2 = -+, 3 = ++-, 4=-- +%macro COEF_PAIR 2-3 0 ; a, b, flags +%if %3 == 1 +pd_%1_m%2: dd %1, %1, -%2, -%2 +%define pd_%1 (pd_%1_m%2 + 4*0) +%define pd_m%2 (pd_%1_m%2 + 4*2) +%elif %3 == 2 +pd_m%1_%2: dd -%1, -%1, %2, %2 +%define pd_m%1 (pd_m%1_%2 + 4*0) +%define pd_%2 (pd_m%1_%2 + 4*2) +%elif %3 == 4 +pd_m%1_m%2: dd -%1, -%1, -%2, -%2 +%define pd_m%1 (pd_m%1_m%2 + 4*0) +%define pd_m%2 (pd_m%1_m%2 + 4*2) +%else +pd_%1_%2: dd %1, %1, %2, %2 +%define pd_%1 (pd_%1_%2 + 4*0) +%define pd_%2 (pd_%1_%2 + 4*2) +%if %3 == 3 +%define pd_%2_m%2 pd_%2 +dd -%2, -%2 +%endif +%endif +%endmacro + +COEF_PAIR 101, 501 +COEF_PAIR 201, 601, 1 +COEF_PAIR 201, 995 +COEF_PAIR 401, 1189, 1 +COEF_PAIR 401, 1931 +COEF_PAIR 401, 3920 +COEF_PAIR 401, 4076 +COEF_PAIR 700, 301, 4 +COEF_PAIR 799, 2276, 1 +COEF_PAIR 799, 3406 +COEF_PAIR 799, 4017 +COEF_PAIR 1380, 601 +COEF_PAIR 1751, 2440 +COEF_PAIR 2598, 1189 +COEF_PAIR 2598, 1931, 2 +COEF_PAIR 2598, 3612 +COEF_PAIR 2751, 2106 +COEF_PAIR 2896, 1567, 3 +COEF_PAIR 2896, 3784, 3 +COEF_PAIR 3035, 3513 +COEF_PAIR 3166, 1931 +COEF_PAIR 3166, 3612 +COEF_PAIR 3166, 3920 +COEF_PAIR 3703, 3290 +COEF_PAIR 3857, 4052 +COEF_PAIR 4017, 2276 +COEF_PAIR 4017, 3406 +COEF_PAIR 4036, 4085 +COEF_PAIR 4076, 1189 +COEF_PAIR 4076, 3612 +COEF_PAIR 4076, 3920 +COEF_PAIR 4091, 3973 +COEF_PAIR 4091, 4052 +COEF_PAIR 4095, 4065 + +pb_32: times 4 db 32 +pw_5: times 2 dw 5 +pw_4096: times 2 dw 4096 +pw_8192: times 2 dw 8192 +pw_1697x16: times 2 dw 1697*16 +pw_2896x8: times 2 dw 2896*8 +pixel_10bpc_max: times 2 dw 0x03ff +dconly_10bpc: times 2 dw 0x7c00 +clip_18b_min: dd -0x20000 +clip_18b_max: dd 0x1ffff +pd_1: dd 1 +pd_2: dd 2 +pd_1448: dd 1448 +pd_2048: dd 2048 +pd_3071: dd 3071 ; 1024 + 2048 - 1 +pd_3072: dd 3072 ; 1024 + 2048 +pd_5119: dd 5119 ; 1024 + 4096 - 1 +pd_5120: dd 5120 ; 1024 + 4096 +pd_5793: dd 5793 + +cextern dup16_perm +cextern int8_permA +cextern idct64_mul_16bpc +cextern idct_8x8_internal_8bpc_avx512icl.main +cextern iadst_8x8_internal_8bpc_avx512icl.main_pass2 +cextern idct_8x16_internal_8bpc_avx512icl.main +cextern idct_8x16_internal_8bpc_avx512icl.main2 +cextern idct_8x16_internal_8bpc_avx512icl.main_fast +cextern idct_8x16_internal_8bpc_avx512icl.main_fast2 +cextern iadst_8x16_internal_8bpc_avx512icl.main2 +cextern idct_16x8_internal_8bpc_avx512icl.main +cextern iadst_16x8_internal_8bpc_avx512icl.main_pass2 +cextern idct_16x16_internal_8bpc_avx512icl.main +cextern idct_16x16_internal_8bpc_avx512icl.main2 +cextern idct_16x16_internal_8bpc_avx512icl.main_fast +cextern idct_16x16_internal_8bpc_avx512icl.main_fast2 +cextern iadst_16x16_internal_8bpc_avx512icl.main_pass2b +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx512icl.main +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx512icl.main_fast +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx512icl.main_fast2 +cextern inv_txfm_add_dct_dct_8x32_8bpc_avx512icl.main_end +cextern inv_txfm_add_dct_dct_16x32_8bpc_avx512icl.main_oddhalf +cextern inv_txfm_add_dct_dct_16x32_8bpc_avx512icl.main_oddhalf_fast +cextern inv_txfm_add_dct_dct_16x32_8bpc_avx512icl.main_oddhalf_fast2 +cextern inv_txfm_add_dct_dct_32x8_8bpc_avx512icl.main +cextern inv_txfm_add_dct_dct_32x16_8bpc_avx512icl.main_oddhalf +cextern inv_txfm_add_dct_dct_32x16_8bpc_avx512icl.main_oddhalf_fast +cextern inv_txfm_add_dct_dct_32x16_8bpc_avx512icl.main_oddhalf_fast2 +cextern inv_txfm_add_dct_dct_32x16_8bpc_avx512icl.main_oddhalf_fast3 +cextern inv_txfm_add_dct_dct_32x32_8bpc_avx512icl.main_oddhalf +cextern inv_txfm_add_dct_dct_32x32_8bpc_avx512icl.main_oddhalf_fast +cextern inv_txfm_add_dct_dct_32x32_8bpc_avx512icl.main_oddhalf_fast2 +cextern inv_txfm_add_dct_dct_32x32_8bpc_avx512icl.main_oddhalf_fast3 +cextern inv_txfm_add_dct_dct_16x64_8bpc_avx512icl.main_oddhalf +cextern inv_txfm_add_dct_dct_16x64_8bpc_avx512icl.main_oddhalf_fast +cextern inv_txfm_add_dct_dct_32x64_8bpc_avx512icl.main_part1 +cextern inv_txfm_add_dct_dct_32x64_8bpc_avx512icl.main_part1_fast +cextern inv_txfm_add_dct_dct_32x64_8bpc_avx512icl.main_part1_fast2 +cextern inv_txfm_add_dct_dct_32x64_8bpc_avx512icl.main_part2 + +SECTION .text + +%define o_base (pw_2048+4*128) +%define o_base_8bpc (int8_permA+64*18) +%define o(x) (r5 - o_base + (x)) +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +INIT_ZMM avx512icl + +; dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +; dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +; flags: 1 = inv_dst1, 2 = inv_dst2 +; skip round/shift if rnd is not a number +%macro ITX_MULSUB_2D 8-9 0 ; dst/src[1-2], tmp[1-3], rnd, coef[1-2], flags +%if %8 < 32 + pmulld m%4, m%1, m%8 + pmulld m%3, m%2, m%8 +%else +%if %8 < 4096 + vpbroadcastd m%3, [o(pd_%8)] +%else + vbroadcasti32x4 m%3, [o(pd_%8)] +%endif + pmulld m%4, m%1, m%3 + pmulld m%3, m%2 +%endif +%if %7 < 32 + pmulld m%1, m%7 + pmulld m%2, m%7 +%else +%if %7 < 4096 + vpbroadcastd m%5, [o(pd_%7)] +%else + vbroadcasti32x4 m%5, [o(pd_%7)] +%endif + pmulld m%1, m%5 + pmulld m%2, m%5 +%endif +%if %9 & 2 + psubd m%4, m%6, m%4 + psubd m%2, m%4, m%2 +%else +%ifnum %6 + paddd m%4, m%6 +%endif + paddd m%2, m%4 +%endif +%ifnum %6 + paddd m%1, m%6 +%endif +%if %9 & 1 + psubd m%1, m%3, m%1 +%else + psubd m%1, m%3 +%endif +%ifnum %6 + psrad m%2, 12 + psrad m%1, 12 +%endif +%endmacro + +%macro INV_TXFM_FN 4 ; type1, type2, eob_offset, size +cglobal inv_txfm_add_%1_%2_%4_10bpc, 4, 7, 0, dst, stride, c, eob, tx2 + %define %%p1 m(i%1_%4_internal_10bpc) + lea r5, [o_base] + ; Jump to the 1st txfm function if we're not taking the fast path, which + ; in turn performs an indirect jump to the 2nd txfm function. + lea tx2q, [m(i%2_%4_internal_10bpc).pass2] +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else +%if %3 + add eobd, %3 +%endif + ; jump to the 1st txfm function unless it's located directly after this + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endmacro + +%macro INV_TXFM_8X8_FN 2-3 0 ; type1, type2, eob_offset + INV_TXFM_FN %1, %2, %3, 8x8 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 8 +.dconly: + add r6d, 384 + sar r6d, 9 +.dconly2: + vpbroadcastd ym2, [o(dconly_10bpc)] + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + vpbroadcastw ym1, r6d + paddsw ym1, ym2 +.dconly_loop: + mova xm0, [dstq+strideq*0] + vinserti32x4 ym0, [dstq+strideq*1], 1 + paddsw ym0, ym1 + psubusw ym0, ym2 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%endif +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst +INV_TXFM_8X8_FN dct, identity + +cglobal idct_8x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call .load + vpermi2q m1, m0, m2 ; 1 5 + vpermi2q m3, m6, m4 ; 7 3 + vpermt2q m0, m5, m4 ; 0 2 + vpermt2q m2, m5, m6 ; 4 6 + call .main + call .main_end + mova m4, [o(idct8x8p)] + packssdw m0, m2 ; 0 1 4 5 + packssdw m1, m3 ; 3 2 7 6 + vpermb m0, m4, m0 + vprolq m1, 32 + vpermb m2, m4, m1 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + jmp tx2q +.pass2: + lea r5, [o_base_8bpc] + vextracti32x8 ym2, m0, 1 + vextracti32x8 ym3, m1, 1 + call m(idct_8x8_internal_8bpc).main + mova m10, [permC] + vpbroadcastd m12, [pw_2048] +.end: + vpermt2q m0, m10, m1 + vpermt2q m2, m10, m3 +.end2: + vpbroadcastd m11, [pixel_10bpc_max] + lea r6, [strideq*3] + pxor m10, m10 + pmulhrsw m8, m12, m0 + call .write_8x4_start + pmulhrsw m8, m12, m2 +.write_8x4: + lea dstq, [dstq+strideq*4] + add cq, 64*2 +.write_8x4_start: + mova xm9, [dstq+strideq*0] + vinserti32x4 ym9, [dstq+strideq*1], 1 + vinserti32x4 m9, [dstq+strideq*2], 2 + vinserti32x4 m9, [dstq+r6 ], 3 + mova [cq+64*0], m10 + mova [cq+64*1], m10 + paddw m9, m8 + pmaxsw m9, m10 + pminsw m9, m11 + mova [dstq+strideq*0], xm9 + vextracti32x4 [dstq+strideq*1], ym9, 1 + vextracti32x4 [dstq+strideq*2], m9, 2 + vextracti32x4 [dstq+r6 ], m9, 3 + ret +ALIGN function_align +.load: + mova m0, [cq+64*0] ; 0 1 + mova m4, [cq+64*1] ; 2 3 + mova m1, [o(permB)] + mova m2, [cq+64*2] ; 4 5 + mova m6, [cq+64*3] ; 6 7 + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + psrlq m5, m1, 32 + vpbroadcastd m12, [o(pd_2896)] + mova m3, m1 + vpbroadcastd m11, [o(pd_1)] + ret +ALIGN function_align +.main_fast: ; bottom half is zero + vbroadcasti32x4 m3, [o(pd_4017_3406)] + vbroadcasti32x4 m8, [o(pd_799_m2276)] + vbroadcasti32x4 m2, [o(pd_2896_3784)] + vbroadcasti32x4 m9, [o(pd_2896_1567)] + pmulld m3, m1 ; t4a t5a + pmulld m1, m8 ; t7a t6a + pmulld m2, m0 ; t0 t3 + pmulld m0, m9 ; t1 t2 + jmp .main2 +.main: + ITX_MULSUB_2D 1, 3, 8, 9, 10, _, 799_3406, 4017_2276 + ITX_MULSUB_2D 0, 2, 8, 9, 10, _, 2896_1567, 2896_3784 +.main2: + REPX {paddd x, m13}, m1, m3, m0, m2 + REPX {psrad x, 12 }, m1, m3, m0, m2 + punpcklqdq m8, m1, m3 ; t4a t7a + punpckhqdq m1, m3 ; t5a t6a + psubd m3, m8, m1 ; t5a t6a + paddd m8, m1 ; t4 t7 + pmaxsd m3, m14 + punpckhqdq m1, m2, m0 ; t3 t2 + pminsd m3, m15 + punpcklqdq m2, m0 ; t0 t1 + pmulld m3, m12 + paddd m0, m2, m1 ; dct4 out0 out1 + psubd m2, m1 ; dct4 out3 out2 + REPX {pmaxsd x, m14}, m8, m0, m2 + REPX {pminsd x, m15}, m8, m0, m2 +.main3: + pshufd m1, m3, q1032 + paddd m3, m13 + psubd m9, m3, m1 + paddd m3, m1 + psrad m9, 12 + psrad m3, 12 + punpckhqdq m1, m8, m3 ; t7 t6 + shufpd m8, m9, 0xaa ; t4 t5 + ret +.main_end: + paddd m0, m11 + paddd m2, m11 + psubd m3, m0, m1 ; out7 out6 + paddd m0, m1 ; out0 out1 + paddd m1, m2, m8 ; out3 out2 + psubd m2, m8 ; out4 out5 + REPX {vpsravd x, m11}, m0, m2, m3, m1 + ret + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity +INV_TXFM_8X8_FN adst, adst + +cglobal iadst_8x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call m(idct_8x8_internal_10bpc).load + vpermi2q m1, m6, m2 ; 7 5 + vpermi2q m3, m4, m0 ; 3 1 + vpermt2q m0, m5, m4 ; 0 2 + vpermt2q m2, m5, m6 ; 4 6 + call .main + punpckldq m1, m2, m4 ; out4 out6 + punpckhdq m2, m0 ; -out5 -out7 + punpckldq m0, m3 ; out0 out2 + punpckhdq m4, m3 ; -out1 -out3 + paddd m1, m11 + psubd m3, m11, m2 + paddd m0, m11 + psubd m4, m11, m4 +.pass1_end: + REPX {psrad x, 1}, m1, m0, m3, m4 + packssdw m0, m1 ; 0 2 4 6 + packssdw m4, m3 ; 1 3 5 7 + psrlq m1, [o(permB)], 8 + punpckhwd m3, m0, m4 + punpcklwd m0, m4 + psrlq m2, m1, 32 + vpermi2q m1, m0, m3 + vpermt2q m0, m2, m3 + jmp tx2q +.pass2: + call .main_pass2 + movu m10, [permC+2] + vbroadcasti32x8 m12, [pw_2048_m2048+16] + jmp m(idct_8x8_internal_10bpc).end +.main_pass2: + vextracti32x8 ym2, m0, 1 + vextracti32x8 ym3, m1, 1 + lea r5, [o_base_8bpc] + pshufd ym4, ym0, q1032 + pshufd ym5, ym1, q1032 + jmp m(iadst_8x8_internal_8bpc).main_pass2 +ALIGN function_align +.main: + ITX_MULSUB_2D 1, 0, 4, 5, 6, 13, 401_1931, 4076_3612 + ITX_MULSUB_2D 3, 2, 4, 5, 6, 13, 3166_3920, 2598_1189 + psubd m4, m0, m2 ; t4 t6 + paddd m0, m2 ; t0 t2 + psubd m2, m1, m3 ; t5 t7 + paddd m1, m3 ; t1 t3 + REPX {pmaxsd x, m14}, m4, m2, m0, m1 + REPX {pminsd x, m15}, m4, m2, m0, m1 + pxor m5, m5 + psubd m5, m4 + shufpd m4, m2, 0xaa ; t4 t7 + shufpd m2, m5, 0xaa ; t5 -t6 + ITX_MULSUB_2D 4, 2, 3, 5, 6, 13, 1567, 3784 + punpckhqdq m3, m0, m1 + punpcklqdq m0, m1 + psubd m1, m0, m3 ; t2 t3 + paddd m0, m3 ; out0 -out7 + punpckhqdq m3, m4, m2 ; t7a t6a + punpcklqdq m4, m2 ; t5a t4a + psubd m2, m4, m3 ; t7 t6 + paddd m4, m3 ; out6 -out1 + REPX {pmaxsd x, m14}, m1, m2 + REPX {pminsd x, m15}, m1, m2 + shufpd m3, m1, m2, 0xaa + shufpd m1, m2, 0x55 + pmulld m3, m12 + pmulld m1, m12 + paddd m3, m13 + psubd m2, m3, m1 + paddd m3, m1 + psrad m2, 12 ; out4 -out5 + pshufd m3, m3, q1032 + psrad m3, 12 ; out2 -out3 + ret + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, identity +INV_TXFM_8X8_FN flipadst, flipadst + +cglobal iflipadst_8x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call m(idct_8x8_internal_10bpc).load + vpermi2q m1, m6, m2 ; 7 5 + vpermi2q m3, m4, m0 ; 3 1 + vpermt2q m0, m5, m4 ; 0 2 + vpermt2q m2, m5, m6 ; 4 6 + call m(iadst_8x8_internal_10bpc).main + punpckhdq m1, m3, m4 ; -out3 -out1 + punpckldq m3, m0 ; out2 out0 + punpckhdq m0, m2 ; -out7 -out5 + punpckldq m4, m2 ; out6 out4 + psubd m1, m11, m1 + paddd m3, m11 + psubd m0, m11, m0 + paddd m4, m11 + jmp m(iadst_8x8_internal_10bpc).pass1_end +.pass2: + call m(iadst_8x8_internal_10bpc).main_pass2 + movu m10, [permC+1] + vbroadcasti32x8 m12, [pw_m2048_2048+16] + lea r6, [strideq*3] + vpermt2q m0, m10, m1 ; 7 6 5 4 + vpbroadcastd m11, [pixel_10bpc_max] + vpermt2q m2, m10, m3 ; 3 2 1 0 + pxor m10, m10 + pmulhrsw m8, m12, m2 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m8, m12, m0 + jmp m(idct_8x8_internal_10bpc).write_8x4 + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + mova m1, [cq+64*0] + packssdw m1, [cq+64*2] ; 0 4 1 5 + mova m2, [cq+64*1] ; 2 6 3 7 + packssdw m2, [cq+64*3] + mova m0, [o(idtx8x8p)] + vpermb m1, m0, m1 + vpermb m2, m0, m2 + punpckldq m0, m1, m2 ; 0 1 4 5 + punpckhdq m1, m2 ; 2 3 6 7 + jmp tx2q +.pass2: + movu m3, [o(permC+2)] + vpbroadcastd m12, [o(pw_4096)] + psrlq m2, m3, 32 + vpermi2q m2, m0, m1 + vpermt2q m0, m3, m1 + jmp m(idct_8x8_internal_10bpc).end2 + +%macro INV_TXFM_8X16_FN 2-3 0 ; type1, type2, eob_offset + INV_TXFM_FN %1, %2, %3, 8x16 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly +%endif +%endmacro + +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, identity, 35 +INV_TXFM_8X16_FN dct, flipadst +INV_TXFM_8X16_FN dct, adst + +cglobal idct_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + cmp eobd, 43 + jl .fast + call .load + call .main + call .main_end +.pass1_end: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + jmp tx2q +.pass2: + mova m8, [o(idct8x16p)] + REPX {vpermb x, m8, x}, m0, m1, m2, m3 + punpckhdq m5, m0, m1 + punpckldq m0, m1 + punpckhdq m4, m2, m3 + punpckldq m2, m3 + punpcklqdq m8, m0, m2 ; 15 1 + punpckhqdq m0, m2 ; 7 9 + punpckhqdq m1, m5, m4 ; 3 13 + punpcklqdq m5, m4 ; 11 5 + lea r5, [o_base_8bpc] + vextracti32x8 ym7, m8, 1 ; 14 2 + vextracti32x8 ym3, m0, 1 ; 6 10 + vextracti32x8 ym6, m1, 1 ; 12 4 + vextracti32x8 ym9, m5, 1 ; 8 0 + call m(idct_8x16_internal_8bpc).main2 + mova m8, [permC] + vpbroadcastd m12, [pw_2048] + vpermt2q m0, m8, m1 + lea r6, [strideq*3] + vpermt2q m2, m8, m3 + vpbroadcastd m11, [pixel_10bpc_max] + vpermt2q m4, m8, m5 + pxor m10, m10 + vpermt2q m6, m8, m7 + pmulhrsw m8, m12, m0 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m8, m12, m2 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m8, m12, m4 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m8, m12, m6 + jmp m(idct_8x8_internal_10bpc).write_8x4 +.fast: + mova ym0, [cq+64*0] + mova ym4, [cq+64*2] + mova ym1, [cq+64*1] + mova ym5, [cq+64*5] + mova ym2, [cq+64*4] + mova ym6, [cq+64*6] + mova ym3, [cq+64*7] + mova ym7, [cq+64*3] + call .round_input_fast + call m(idct_8x8_internal_10bpc).main + call m(idct_8x8_internal_10bpc).main_end + movu m6, [o(permC+3)] + packssdw m3, m1, m3 + packssdw m1, m0, m2 + vprolq m3, 32 + vpermd m1, m6, m1 + vpermd m3, m6, m3 + mova ym0, ym1 ; 0 4 + vextracti32x8 ym1, m1, 1 ; 1 5 + mova ym2, ym3 ; 2 6 + vextracti32x8 ym3, m3, 1 ; 3 7 + jmp tx2q +ALIGN function_align +.round_input_fast: + movshdup m8, [o(permB)] + vpbroadcastd m12, [o(pd_2896)] + vpermt2q m0, m8, m4 + vpermt2q m1, m8, m5 + vpermt2q m2, m8, m6 + vpermt2q m3, m8, m7 + vpbroadcastd m13, [o(pd_2048)] + REPX {pmulld x, m12}, m0, m1, m2, m3 + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + REPX {paddd x, m13}, m0, m1, m2, m3 + vpbroadcastd m11, [o(pd_1)] + REPX {psrad x, 12 }, m0, m1, m2, m3 + ret +ALIGN function_align +.load: + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] +.load2: + vpbroadcastd m12, [o(pd_2896)] + pmulld m0, m12, [cq+64*0] + pmulld m1, m12, [cq+64*1] + pmulld m2, m12, [cq+64*2] + pmulld m3, m12, [cq+64*3] + vpbroadcastd m13, [o(pd_2048)] + pmulld m4, m12, [cq+64*4] + pmulld m5, m12, [cq+64*5] + pmulld m6, m12, [cq+64*6] + pmulld m7, m12, [cq+64*7] +.round: + REPX {paddd x, m13}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 + REPX {paddd x, m13}, m4, m5, m6, m7 + REPX {psrad x, 12 }, m4, m5, m6, m7 + ret +ALIGN function_align +.main_fast2_rect2: + REPX {paddd x, m13}, m0, m1 + REPX {psrad x, 12 }, m0, m1 +.main_fast2: + pmulld m0, m12 + pmulld m6, m1, [o(pd_4017)] {1to16} ; t7a + pmulld m8, m1, [o(pd_799)] {1to16} ; t4a + REPX {paddd x, m13}, m0, m6, m8 + REPX {psrad x, 12 }, m0, m6, m8 + pmulld m5, m6, m12 + pmulld m1, m8, m12 + paddd m5, m13 + psubd m4, m5, m1 + paddd m5, m1 + REPX {psrad x, 12 }, m4, m5 + REPX {mova x, m0 }, m1, m2, m3 + ret +.main_fast_rect2: + REPX {paddd x, m13}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_fast: + pmulld m0, m12 + pmulld m5, m3, [o(pd_2276)] {1to16} ; t5a + pmulld m3, [o(pd_3406)] {1to16} ; t6a + pmulld m7, m1, [o(pd_4017)] {1to16} ; t7a + pmulld m1, [o(pd_799)] {1to16} ; t4a + pmulld m6, m2, [o(pd_3784)] {1to16} ; t3 + pmulld m2, [o(pd_1567)] {1to16} ; t2 + paddd m0, m13 + psubd m5, m13, m5 + psrad m0, 12 ; t0 + mova m9, m0 ; t1 + jmp .main2 +.main_rect2: + call .round +.main: + pmulld m0, m12 + ITX_MULSUB_2D 5, 3, 8, 9, 10, _, 3406, 2276 ; t5a t6a + ITX_MULSUB_2D 1, 7, 8, 9, 10, _, 799, 4017 ; t4a t7a + ITX_MULSUB_2D 2, 6, 8, 9, 10, _, 1567, 3784 ; t2 t3 + pmulld m4, m12 + paddd m0, m13 + paddd m5, m13 + psubd m9, m0, m4 ; t1 + paddd m0, m4 ; t0 + psrad m9, 12 + psrad m0, 12 +.main2: + REPX {paddd x, m13}, m3, m1, m7 + REPX {psrad x, 12 }, m5, m1, m3, m7 + paddd m8, m1, m5 ; t4 + psubd m1, m5 ; t5a + psubd m5, m7, m3 ; t6a + paddd m7, m3 ; t7 + pmaxsd m5, m14 + pmaxsd m1, m14 + paddd m2, m13 + paddd m6, m13 + pminsd m5, m15 + pminsd m1, m15 + pmulld m5, m12 + pmulld m1, m12 + pmaxsd m8, m14 + pmaxsd m7, m14 + pminsd m8, m15 + paddd m5, m13 + psubd m4, m5, m1 + paddd m5, m1 + REPX {psrad x, 12 }, m2, m6, m5, m4 + paddd m1, m9, m2 ; dct4 out1 + psubd m2, m9, m2 ; dct4 out2 + psubd m3, m0, m6 ; dct4 out3 + paddd m0, m6 ; dct4 out0 + pminsd m6, m15, m7 + REPX {pmaxsd x, m14}, m0, m1, m2, m3 + REPX {pminsd x, m15}, m0, m1, m2, m3 + ret +.main_end: + vpbroadcastd m11, [o(pd_1)] +.main_end2: + REPX {paddd x, m11}, m0, m1, m2, m3 + psubd m7, m0, m6 ; out7 + paddd m0, m6 ; out0 + psubd m6, m1, m5 ; out6 + paddd m1, m5 ; out1 + psubd m5, m2, m4 ; out5 + paddd m2, m4 ; out2 + psubd m4, m3, m8 ; out4 + paddd m3, m8 ; out3 + REPX {vpsravd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + ret + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, identity, 35 +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, adst + +cglobal iadst_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + cmp eobd, 43 + jl .fast + call m(idct_8x16_internal_10bpc).load + call .main + psrad m0, 1 + psrad m1, 1 + psrad m6, m10, 1 + psrad m7, m11, 1 + psrad m2, 12 + psrad m3, 12 + psrad m4, m8, 12 + psrad m5, m9, 12 + jmp m(idct_8x16_internal_10bpc).pass1_end +.fast: + call .fast_main + punpcklqdq m1, m2, m4 ; out4 out6 + punpckhqdq m2, m0 ; -out5 -out7 + punpcklqdq m0, m3 ; out0 out2 + punpckhqdq m4, m3 ; -out1 -out3 + paddd m1, m11 + psubd m3, m11, m2 + paddd m0, m11 + psubd m4, m11, m4 +.fast_end: + movu m5, [o(permC+3)] + REPX {psrad x, 1}, m1, m0, m3, m4 + packssdw m2, m0, m1 ; 0 2 4 6 + packssdw m3, m4, m3 ; 1 3 5 7 + vpermd m2, m5, m2 + vpermd m3, m5, m3 + mova ym0, ym2 + vextracti32x8 ym2, m2, 1 + mova ym1, ym3 + vextracti32x8 ym3, m3, 1 + jmp tx2q +.pass2: + call .pass2_main + movu m4, [permB+2] + vbroadcasti32x8 m12, [pw_2048_m2048+16] + psrlq m7, m4, 8 + vpermi2q m4, m0, m3 ; 0 1 2 3 + psrlq m5, m7, 24 + vpermi2q m7, m0, m3 ; 12 13 14 15 + psrlq m6, m5, 8 + vpermq m5, m5, m1 ; 4 5 6 7 + vpermq m6, m6, m2 ; 8 9 10 11 +.pass2_end: + vpbroadcastd m11, [pixel_10bpc_max] + pxor m10, m10 + lea r6, [strideq*3] + pmulhrsw m8, m12, m4 + call m(idct_8x8_internal_10bpc).write_8x4_start + pmulhrsw m8, m12, m5 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m8, m12, m6 + call m(idct_8x8_internal_10bpc).write_8x4 + pmulhrsw m8, m12, m7 + jmp m(idct_8x8_internal_10bpc).write_8x4 +ALIGN function_align +.main: + ITX_MULSUB_2D 7, 0, 8, 9, 10, 13, 401, 4076 ; t1a, t0a + ITX_MULSUB_2D 1, 6, 8, 9, 10, 13, 3920, 1189 ; t7a, t6a + ITX_MULSUB_2D 5, 2, 8, 9, 10, 13, 1931, 3612 ; t3a, t2a + ITX_MULSUB_2D 3, 4, 8, 9, 10, 13, 3166, 2598 ; t5a, t4a + psubd m8, m2, m6 ; t6 + paddd m2, m6 ; t2 + psubd m6, m0, m4 ; t4 + paddd m0, m4 ; t0 + psubd m4, m5, m1 ; t7 + paddd m5, m1 ; t3 + psubd m1, m7, m3 ; t5 + paddd m7, m3 ; t1 + REPX {pmaxsd x, m14}, m6, m1, m8, m4, m2, m0, m5, m7 + REPX {pminsd x, m15}, m6, m1, m8, m4, m2, m0, m5, m7 + vpbroadcastd m10, [o(pd_1567)] + vpbroadcastd m11, [o(pd_3784)] + ITX_MULSUB_2D 6, 1, 3, 9, _, 13, 10, 11 ; t5a, t4a + ITX_MULSUB_2D 4, 8, 3, 9, _, 13, 11, 10 ; t6a, t7a + vpbroadcastd m12, [o(pd_1448)] + psubd m9, m6, m8 ; t7 + paddd m6, m8 ; out6 + psubd m3, m7, m5 ; t3 + paddd m7, m5 ; -out7 + psubd m5, m0, m2 ; t2 + paddd m0, m2 ; out0 + psubd m2, m1, m4 ; t6 + paddd m1, m4 ; -out1 + REPX {pmaxsd x, m14}, m5, m3, m2, m9 + REPX {pminsd x, m15}, m5, m3, m2, m9 + REPX {pmulld x, m12}, m5, m3, m2, m9 + vpbroadcastd m4, [o(pd_1)] + psubd m8, m5, m3 ; (t2 - t3) * 1448 + paddd m3, m5 ; (t2 + t3) * 1448 + psubd m5, m2, m9 ; (t6 - t7) * 1448 + paddd m2, m9 ; (t6 + t7) * 1448 + vpbroadcastd m9, [o(pd_3072)] + paddd m0, m4 + psubd m1, m4, m1 + paddd m10, m6, m4 + psubd m11, m4, m7 + paddd m2, m9 + paddd m8, m9 + vpbroadcastd m9, [o(pd_3071)] + psubd m3, m9, m3 + psubd m9, m5 + ret +ALIGN function_align +.fast_main: + mova ym0, [cq+64*0] + mova ym4, [cq+64*2] + mova ym1, [cq+64*7] + mova ym5, [cq+64*5] + mova ym2, [cq+64*4] + mova ym6, [cq+64*6] + mova ym3, [cq+64*3] + mova ym7, [cq+64*1] + call m(idct_8x16_internal_10bpc).round_input_fast + jmp m(iadst_8x8_internal_10bpc).main +ALIGN function_align +.pass2_main: + mova m8, [o(iadst8x16p)] + REPX {vpermb x, m8, x}, m0, m1, m2, m3 + vpbroadcastd m10, [o(pw_2896x8)] + punpckhdq m5, m0, m1 + punpckldq m0, m1 + punpckhdq m1, m2, m3 + punpckldq m2, m3 + lea r5, [o_base_8bpc] + punpckhqdq m4, m0, m2 ; 12 3 14 1 + punpcklqdq m0, m2 ; 0 15 2 13 + punpckhqdq m6, m5, m1 ; 8 7 10 5 + punpcklqdq m5, m1 ; 4 11 6 9 + call m(iadst_8x16_internal_8bpc).main2 + paddsw m1, m2, m4 + psubsw m2, m4 + pmulhrsw m1, m10 ; -out7 out4 out6 -out5 + pmulhrsw m2, m10 ; out8 -out11 -out9 out10 + ret + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, identity, 35 +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst + +cglobal iflipadst_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + cmp eobd, 43 + jl .fast + call m(idct_8x16_internal_10bpc).load + call m(iadst_8x16_internal_10bpc).main + psrad m7, m0, 1 + psrad m0, m11, 1 + psrad m6, m1, 1 + psrad m1, m10, 1 + psrad m5, m2, 12 + psrad m2, m9, 12 + psrad m4, m3, 12 + psrad m3, m8, 12 + jmp m(idct_8x16_internal_10bpc).pass1_end +.fast: + call m(iadst_8x16_internal_10bpc).fast_main + punpckhqdq m1, m3, m4 ; -out3 -out1 + punpcklqdq m3, m0 ; out2 out0 + punpckhqdq m0, m2 ; -out7 -out5 + punpcklqdq m4, m2 ; out6 out4 + psubd m1, m11, m1 + paddd m3, m11 + psubd m0, m11, m0 + paddd m4, m11 + jmp m(iadst_8x16_internal_10bpc).fast_end +.pass2: + call m(iadst_8x16_internal_10bpc).pass2_main + movu m7, [permB+2] + vbroadcasti32x8 m12, [pw_m2048_2048+16] + psrlq m4, m7, 8 + vpermi2q m7, m3, m0 ; 3 2 1 0 + psrlq m5, m4, 24 + vpermi2q m4, m3, m0 ; 15 14 13 12 + psrlq m6, m5, 8 + vpermq m5, m5, m2 ; 11 10 9 8 + vpermq m6, m6, m1 ; 7 6 5 4 + jmp m(iadst_8x16_internal_10bpc).pass2_end + +INV_TXFM_8X16_FN identity, dct +INV_TXFM_8X16_FN identity, adst +INV_TXFM_8X16_FN identity, flipadst +INV_TXFM_8X16_FN identity, identity + +cglobal iidentity_8x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call m(idct_8x16_internal_10bpc).load2 + jmp m(idct_8x16_internal_10bpc).pass1_end +.pass2: + vpbroadcastd m8, [o(pw_1697x16)] + pmulhrsw m4, m8, m0 + pmulhrsw m5, m8, m1 + pmulhrsw m6, m8, m2 + pmulhrsw m7, m8, m3 + REPX {paddsw x, x}, m0, m1, m2, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + vpbroadcastd m7, [o(pw_2048)] + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + vpbroadcastd m6, [o(pixel_10bpc_max)] + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m1 + punpckhdq m4, m1 + pxor m5, m5 + punpckhqdq m1, m0, m2 ; 1 5 9 13 + punpcklqdq m0, m2 ; 0 4 8 12 + punpcklqdq m2, m3, m4 ; 2 6 10 14 + punpckhqdq m3, m4 ; 3 7 11 15 + lea r6, [strideq*3] + pmulhrsw m0, m7 + call .write_8x4_start + pmulhrsw m0, m7, m1 + call .write_8x4 + pmulhrsw m0, m7, m2 + call .write_8x4 + pmulhrsw m0, m7, m3 +.write_8x4: + add dstq, strideq + add cq, 64*2 +.write_8x4_start: + mova xm4, [dstq+strideq*0] + vinserti32x4 ym4, [dstq+strideq*4], 1 + vinserti32x4 m4, [dstq+strideq*8], 2 + vinserti32x4 m4, [dstq+r6*4 ], 3 + mova [cq+64*0], m5 + mova [cq+64*1], m5 + paddw m4, m0 + pmaxsw m4, m5 + pminsw m4, m6 + mova [dstq+strideq*0], xm4 + vextracti32x4 [dstq+strideq*4], ym4, 1 + vextracti32x4 [dstq+strideq*8], m4, 2 + vextracti32x4 [dstq+r6*4 ], m4, 3 + ret + +%macro INV_TXFM_16X8_FN 2-3 0 ; type1, type2, eob_offset + INV_TXFM_FN %1, %2, %3, 16x8 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 8 +.dconly: + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 +.dconly2: + vpbroadcastd m2, [o(dconly_10bpc)] + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + vpbroadcastw m1, r6d + paddsw m1, m2 +.dconly_loop: + mova ym0, [dstq+strideq*0] + vinserti32x8 m0, [dstq+strideq*1], 1 + paddsw m0, m1 + psubusw m0, m2 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%endif +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, identity, -21 +INV_TXFM_16X8_FN dct, flipadst +INV_TXFM_16X8_FN dct, adst + +cglobal idct_16x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + pmulld m4, m12, [cq+64*0] ; 0 1 + pmulld m9, m12, [cq+64*1] ; 2 3 + pmulld m8, m12, [cq+64*2] ; 4 5 + pmulld m7, m12, [cq+64*3] ; 6 7 + vpbroadcastd m13, [o(pd_2048)] + pxor m2, m2 + mova m15, [o(permB)] + REPX {mova [cq+64*x], m2}, 0, 1, 2, 3 + psrlq m0, m15, 32 + REPX {paddd x, m13}, m4, m9, m8, m7 + vpbroadcastd m14, [o(clip_18b_min)] + REPX {psrad x, 12 }, m4, m8, m9, m7 + mova m1, m0 + vpermi2q m0, m4, m8 ; 0 4 + cmp eobd, 43 + jl .fast + pmulld m5, m12, [cq+64*4] ; 8 9 + pmulld m10, m12, [cq+64*5] ; 10 11 + pmulld m11, m12, [cq+64*6] ; 12 13 + pmulld m6, m12, [cq+64*7] ; 14 15 + REPX {mova [cq+64*x], m2}, 4, 5, 6, 7 + REPX {paddd x, m13}, m5, m10, m11, m6 + REPX {psrad x, 12 }, m10, m5, m11, m6 + mova m2, m1 + vpermi2q m1, m9, m10 ; 2 10 + mova m3, m2 + vpermi2q m2, m5, m11 ; 8 12 + vpermi2q m3, m6, m7 ; 14 6 + vpermt2q m4, m15, m11 ; 1 13 + vpermt2q m6, m15, m9 ; 15 3 + vpermt2q m5, m15, m8 ; 9 5 + vpermt2q m7, m15, m10 ; 7 11 + vpbroadcastd m15, [o(clip_18b_max)] + call m(idct_8x8_internal_10bpc).main + call .main + jmp .pass1_end +.fast: + vpermi2q m1, m9, m7 ; 2 6 + vpermt2q m4, m15, m9 ; 1 3 + vpermt2q m7, m15, m8 ; 7 5 + vpbroadcastd m15, [o(clip_18b_max)] + call m(idct_8x8_internal_10bpc).main_fast + call .main_fast +.pass1_end: + call m(idct_8x16_internal_10bpc).main_end + mova m8, [o(permA)] + psrlq m9, m8, 8 +.pass1_end2: + mova m10, m9 + mova m11, m8 + call .transpose_16x8 + jmp tx2q +.pass2: + lea r5, [o_base_8bpc] + call m(idct_16x8_internal_8bpc).main + movshdup m4, [permC] + vpbroadcastd m11, [pw_2048] + psrlq m5, m4, 8 +.end: + vpbroadcastd m13, [pixel_10bpc_max] + pxor m12, m12 + vpermq m8, m4, m0 + vpermq m9, m5, m1 + lea r6, [strideq*3] + call .write_16x4 + vpermq m8, m4, m2 + vpermq m9, m5, m3 +.write_16x4: + pmulhrsw m8, m11 + pmulhrsw m9, m11 +.write_16x4_noround: + mova ym10, [dstq+strideq*0] + vinserti32x8 m10, [dstq+strideq*1], 1 + paddw m8, m10 + mova ym10, [dstq+strideq*2] + vinserti32x8 m10, [dstq+r6 ], 1 + paddw m9, m10 + pmaxsw m8, m12 + pmaxsw m9, m12 + pminsw m8, m13 + pminsw m9, m13 + mova [dstq+strideq*0], ym8 + vextracti32x8 [dstq+strideq*1], m8, 1 + mova [dstq+strideq*2], ym9 + vextracti32x8 [dstq+r6 ], m9, 1 + lea dstq, [dstq+strideq*4] + ret +ALIGN function_align +.main_fast: ; bottom half is zero + vbroadcasti32x4 m6, [o(pd_4076_3920)] + vbroadcasti32x4 m3, [o(pd_401_m1189)] + vbroadcasti32x4 m5, [o(pd_m2598_1931)] + vbroadcasti32x4 m9, [o(pd_3166_3612)] + pmulld m6, m4 ; t15a t12a + pmulld m4, m3 ; t8a t11a + pmulld m5, m7 ; t9a t10a + pmulld m7, m9 ; t14a t13a + jmp .main2 +.main: + ITX_MULSUB_2D 4, 6, 3, 9, 10, _, 401_3920, 4076_1189 + ITX_MULSUB_2D 5, 7, 3, 9, 10, _, 3166_1931, 2598_3612 +.main2: + REPX {paddd x, m13}, m4, m6, m5, m7 + REPX {psrad x, 12 }, m4, m5, m6, m7 + paddd m9, m4, m5 ; t8 t11 + psubd m4, m5 ; t9 t10 + psubd m5, m6, m7 ; t14 t13 + paddd m6, m7 ; t15 t12 + REPX {pmaxsd x, m14}, m5, m4, m9, m6 + REPX {pminsd x, m15}, m5, m4, m9, m6 +.main3: + psubd m3, m0, m1 ; dct8 out7 out6 + paddd m0, m1 ; dct8 out0 out1 + vbroadcasti32x4 m7, [o(pd_3784_m3784)] + pmulld m7, m5 + vpmulld m5, [o(pd_1567)] {1to16} + paddd m1, m2, m8 ; dct8 out3 out2 + psubd m2, m8 ; dct8 out4 out5 + vbroadcasti32x4 m8, [o(pd_1567_m1567)] + pmulld m8, m4 + vpmulld m4, [o(pd_3784)] {1to16} + REPX {pmaxsd x, m14}, m0, m1 + REPX {pminsd x, m15}, m0, m1 + paddd m7, m13 + paddd m5, m13 + paddd m7, m8 + psubd m5, m4 + psrad m7, 12 ; t14a t10a + psrad m5, 12 ; t9a t13a + punpckhqdq m4, m9, m7 + punpcklqdq m8, m9, m5 + punpckhqdq m5, m6, m5 + punpcklqdq m6, m7 + psubd m7, m8, m4 ; t11a t10 + paddd m8, m4 ; t8a t9 + psubd m4, m6, m5 ; t12a t13 + paddd m6, m5 ; t15a t14 + REPX {pmaxsd x, m14}, m4, m7 + REPX {pminsd x, m15}, m4, m7 + pmulld m4, m12 + pmulld m7, m12 + REPX {pmaxsd x, m14}, m2, m3, m6, m8 + REPX {pminsd x, m15}, m2, m3, m6, m8 + paddd m4, m13 + paddd m5, m4, m7 + psubd m4, m7 + psrad m4, 12 ; t11 t10a + psrad m5, 12 ; t12 t13a + ret +ALIGN function_align +.transpose_16x8: + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + vpermi2d m8, m0, m2 + vpermt2d m0, m9, m2 + vpermi2d m10, m1, m3 + vpermi2d m11, m1, m3 + punpckhwd m3, m8, m0 + punpcklwd m1, m8, m0 + punpckhwd m4, m10, m11 + punpcklwd m2, m10, m11 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + ret + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, identity, -21 +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, adst + +cglobal iadst_16x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + call .main_pass1 + vpbroadcastd m9, [o(pd_1)] + paddd m0, m9 + psubd m1, m9, m1 + paddd m2, m9 + psubd m3, m9, m3 + paddd m4, m9, m5 + psubd m5, m9, m6 + paddd m6, m9, m7 + psubd m7, m9, m8 +.pass1_end: + mova m9, [o(permA)] + psrlq m8, m9, 8 + REPX {psrad x, 1}, m0, m4, m1, m5, m2, m6, m3, m7 + jmp m(idct_16x8_internal_10bpc).pass1_end2 +.pass2: + call .main_pass2 + vpermq m8, m11, m0 + vpermq m9, m11, m1 + call m(idct_16x8_internal_10bpc).write_16x4_noround + vpermq m8, m11, m2 + vpermq m9, m11, m3 + jmp m(idct_16x8_internal_10bpc).write_16x4_noround +ALIGN function_align +.main_pass1: + vpbroadcastd m12, [o(pd_2896)] + pmulld m2, m12, [cq+64*0] + pmulld m7, m12, [cq+64*1] + pmulld m1, m12, [cq+64*2] + pmulld m5, m12, [cq+64*3] + vpbroadcastd m13, [o(pd_2048)] + pxor m4, m4 + mova m10, [o(permB)] + REPX {mova [cq+64*x], m4}, 0, 1, 2, 3 + REPX {paddd x, m13}, m2, m7, m1, m5 + psrlq m6, m10, 32 + REPX {psrad x, 12 }, m2, m7, m1, m5 + mova m0, m6 + vpermi2q m0, m2, m7 ; 0 2 + vpermt2q m7, m10, m2 ; 3 1 + mova m2, m6 + vpermi2q m2, m1, m5 ; 4 6 + vpermt2q m5, m10, m1 ; 7 5 + cmp eobd, 43 + jl .main_fast + pmulld m8, m12, [cq+64*4] + pmulld m3, m12, [cq+64*5] + pmulld m9, m12, [cq+64*6] + pmulld m1, m12, [cq+64*7] + REPX {mova [cq+64*x], m4}, 4, 5, 6, 7 + REPX {paddd x, m13}, m8, m3, m9, m1 + REPX {psrad x, 12 }, m8, m3, m9, m1 + mova m4, m6 + vpermi2q m4, m8, m3 ; 8 10 + vpermt2q m3, m10, m8 ; 11 9 + vpermi2q m6, m9, m1 ; 12 14 + vpermt2q m1, m10, m9 ; 15 13 +.main: + ITX_MULSUB_2D 1, 0, 8, 9, 10, _, 201_995, 4091_3973, 1 + ITX_MULSUB_2D 3, 2, 8, 9, 10, _, 1751_2440, 3703_3290, 1 + ITX_MULSUB_2D 5, 4, 8, 9, 10, _, 3035_3513, 2751_2106 + ITX_MULSUB_2D 7, 6, 8, 9, 10, _, 3857_4052, 1380_601 + jmp .main2 +.main_fast: + vbroadcasti32x4 m1, [o(pd_4091_3973)] + vbroadcasti32x4 m8, [o(pd_201_995)] + vbroadcasti32x4 m3, [o(pd_3703_3290)] + vbroadcasti32x4 m9, [o(pd_1751_2440)] + vbroadcasti32x4 m4, [o(pd_2751_2106)] + vbroadcasti32x4 m10, [o(pd_3035_3513)] + vbroadcasti32x4 m6, [o(pd_1380_601)] + vbroadcasti32x4 m11, [o(pd_3857_4052)] + pmulld m1, m0 + pmulld m0, m8 + pmulld m3, m2 + pmulld m2, m9 + pmulld m4, m5 + pmulld m5, m10 + pmulld m6, m7 + pmulld m7, m11 +.main2: + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + REPX {psubd x, m13, x}, m1, m3 + REPX {paddd x, m13 }, m0, m2, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m4, m1, m5, m2, m6, m3, m7 + psubd m8, m0, m4 ; t8a t10a + paddd m0, m4 ; t0a t2a + psubd m4, m1, m5 ; t9a t11a + paddd m1, m5 ; t1a t3a + psubd m5, m2, m6 ; t12a t14a + paddd m2, m6 ; t4a t6a + psubd m6, m3, m7 ; t13a t15a + paddd m3, m7 ; t5a t7a + REPX {pmaxsd x, m14}, m8, m4, m5, m6 + REPX {pminsd x, m15}, m8, m4, m5, m6 + vbroadcasti32x4 m11, [o(pd_4017_2276)] + vbroadcasti32x4 m10, [o(pd_799_3406)] + ITX_MULSUB_2D 8, 4, 7, 9, _, 13, 10, 11 + ITX_MULSUB_2D 6, 5, 7, 9, _, 13, 11, 10 + REPX {pmaxsd x, m14}, m0, m2, m1, m3 + REPX {pminsd x, m15}, m0, m2, m1, m3 + psubd m7, m0, m2 ; t4 t6 + paddd m0, m2 ; t0 t2 + psubd m2, m1, m3 ; t5 t7 + paddd m1, m3 ; t1 t3 + psubd m3, m4, m6 ; t12a t14a + paddd m4, m6 ; t8a t10a + psubd m6, m8, m5 ; t13a t15a + paddd m8, m5 ; t9a t11a + REPX {pmaxsd x, m14}, m7, m3, m2, m6 + REPX {pminsd x, m15}, m7, m3, m2, m6 + punpcklqdq m5, m3, m7 ; t12a t4 + punpckhqdq m3, m7 ; t14a t6 + punpckhqdq m7, m6, m2 ; t15a t7 + punpcklqdq m6, m2 ; t13a t5 + vpbroadcastd m11, [o(pd_1567)] + vpbroadcastd m10, [o(pd_3784)] + ITX_MULSUB_2D 7, 3, 2, 9, 10, 13, 10, 11 + ITX_MULSUB_2D 5, 6, 2, 9, 10, 13, 11, 10 + REPX {pmaxsd x, m14}, m0, m4, m1, m8 + REPX {pminsd x, m15}, m0, m4, m1, m8 + punpckhqdq m2, m4, m0 ; t10a t2 + punpcklqdq m4, m0 ; t8a t0 + punpckhqdq m0, m8, m1 ; t11a t3 + punpcklqdq m8, m1 ; t9a t1 + paddd m1, m6, m7 ; out2 -out3 + psubd m6, m7 ; t14a t6 + paddd m7, m5, m3 ; -out13 out12 + psubd m5, m3 ; t15a t7 + psubd m3, m8, m0 ; t11 t3a + paddd m8, m0 ; out14 -out15 + paddd m0, m4, m2 ; -out1 out0 + psubd m4, m2 ; t10 t2a + REPX {pmaxsd x, m14}, m6, m5, m3, m4 + mov r6d, 0x3333 + REPX {pminsd x, m15}, m6, m5, m3, m4 + kmovw k1, r6d + REPX {pmulld x, m12}, m6, m5, m3, m4 + pxor m9, m9 + REPX {vpsubd x{k1}, m9, x}, m0, m1, m7, m8 + paddd m6, m13 + paddd m4, m13 + paddd m2, m6, m5 ; -out5 out4 + psubd m6, m5 ; out10 -out11 + psubd m5, m4, m3 ; -out9 out8 + paddd m3, m4 ; out6 -out7 + REPX {psrad x, 12}, m2, m3, m5, m6 + REPX {vpsubd x{k1}, m9, x}, m2, m3, m5, m6 + ret +ALIGN function_align +.main_pass2: + lea r5, [o_base_8bpc] + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call m(iadst_16x8_internal_8bpc).main_pass2 + movshdup m11, [permC] + pmulhrsw m0, m6 + pmulhrsw m1, m6 + vpbroadcastd m13, [pixel_10bpc_max] + pxor m12, m12 + lea r6, [strideq*3] + ret + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, identity, -21 +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst + +cglobal iflipadst_16x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call m(iadst_16x8_internal_10bpc).main_pass1 + vpbroadcastd m9, [o(pd_1)] + psubd m4, m9, m3 + paddd m3, m9, m5 + paddd m5, m9, m2 + psubd m2, m9, m6 + psubd m6, m9, m1 + paddd m1, m9, m7 + paddd m7, m9, m0 + psubd m0, m9, m8 + jmp m(iadst_16x8_internal_10bpc).pass1_end +.pass2: + call m(iadst_16x8_internal_10bpc).main_pass2 + psrlq m11, 8 + vpermq m8, m11, m3 + vpermq m9, m11, m2 + call m(idct_16x8_internal_10bpc).write_16x4_noround + vpermq m8, m11, m1 + vpermq m9, m11, m0 + jmp m(idct_16x8_internal_10bpc).write_16x4_noround + +INV_TXFM_16X8_FN identity, dct +INV_TXFM_16X8_FN identity, adst +INV_TXFM_16X8_FN identity, flipadst +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 + call m(idct_8x16_internal_10bpc).load2 + vpbroadcastd m8, [o(pd_5793)] + vpbroadcastd m13, [o(pd_3072)] + pxor m10, m10 + REPX {pmulld x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {mova [cq+64*x], m10}, 0, 1, 2, 3, 4, 5, 6, 7 + call m(idct_8x16_internal_10bpc).round + psrlq m8, [o(permA)], 16 + psrlq m9, m8, 8 + mova m10, m8 + mova m11, m9 + call m(idct_16x8_internal_10bpc).transpose_16x8 + jmp tx2q +.pass2: + movshdup m4, [o(permC)] + vpbroadcastd m11, [o(pw_4096)] + mova m5, m4 + jmp m(idct_16x8_internal_10bpc).end + +%macro INV_TXFM_16X16_FN 2-3 0 ; type1, type2, eob_offset + INV_TXFM_FN %1, %2, %3, 16x16 +%ifidn %1_%2, dct_dct + imul r6d, [cq], 181 + mov [cq], eobd ; 0 + or r3d, 16 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_16x8_10bpc).dconly2 +%endif +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, identity, 28 +INV_TXFM_16X16_FN dct, flipadst +INV_TXFM_16X16_FN dct, adst + +cglobal idct_16x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 36 + jl .fast + mova m0, [cq+64* 0] + mova m1, [cq+64* 2] + mova m2, [cq+64* 4] + mova m3, [cq+64* 6] + mova m4, [cq+64* 8] + mova m5, [cq+64*10] + mova m6, [cq+64*12] + mova m7, [cq+64*14] +%if WIN64 + movaps [cq+16*0], xmm6 + movaps [cq+16*1], xmm7 +%endif + call m(idct_8x16_internal_10bpc).main + mova m16, [cq+64* 1] + mova m17, [cq+64* 3] + mova m18, [cq+64* 5] + mova m19, [cq+64* 7] + mova m20, [cq+64* 9] + mova m21, [cq+64*11] + mova m22, [cq+64*13] + mova m23, [cq+64*15] + call .main + call .main_end +.pass1_end: +%if WIN64 + movaps xmm6, [cq+16*0] + movaps xmm7, [cq+16*1] +%endif + vzeroupper +.pass1_end2: + call .main_end3 +.pass1_end3: + mov r6d, 64*12 + pxor m8, m8 +.zero_loop: + mova [cq+r6+64*3], m8 + mova [cq+r6+64*2], m8 + mova [cq+r6+64*1], m8 + mova [cq+r6+64*0], m8 + sub r6d, 64*4 + jge .zero_loop + jmp tx2q +.pass2: + lea r5, [o_base_8bpc] + call m(idct_16x16_internal_8bpc).main + movshdup m12, [permC] + vpbroadcastd m11, [pw_2048] + psrlq m13, m12, 8 + vpermq m8, m12, m0 + vpermq m0, m13, m7 + vpermq m7, m13, m1 + vpermq m1, m12, m6 + vpermq m6, m12, m2 + vpermq m2, m13, m5 + vpermq m5, m13, m3 + vpermq m3, m12, m4 +.pass2_end: + lea r6, [strideq*3] + vpbroadcastd m13, [pixel_10bpc_max] + pxor m12, m12 + pmulhrsw m8, m11, m8 + pmulhrsw m9, m11, m7 + call m(idct_16x8_internal_10bpc).write_16x4_noround + pmulhrsw m8, m11, m6 + pmulhrsw m9, m11, m5 + call m(idct_16x8_internal_10bpc).write_16x4_noround + pmulhrsw m8, m11, m3 + pmulhrsw m9, m11, m2 + call m(idct_16x8_internal_10bpc).write_16x4_noround + pmulhrsw m8, m11, m1 + pmulhrsw m9, m11, m0 + jmp m(idct_16x8_internal_10bpc).write_16x4_noround +.fast: + mova ym0, [cq+64*0] + mova ym2, [cq+64*4] + movshdup m8, [o(permB)] + mova ym1, [cq+64*2] + mova ym3, [cq+64*6] + mova ym4, [cq+64*1] + mova ym5, [cq+64*3] + mova ym6, [cq+64*5] + mova ym7, [cq+64*7] + vpermt2q m0, m8, m2 ; 0 4 + vpermt2q m1, m8, m3 ; 2 6 + vpermt2q m4, m8, m5 ; 1 3 + vpermt2q m7, m8, m6 ; 7 5 + call m(idct_8x8_internal_10bpc).main_fast + call m(idct_16x8_internal_10bpc).main_fast + vpbroadcastd m11, [o(pd_2)] + call m(idct_8x16_internal_10bpc).main_end2 + mova m8, [o(permA)] + psrlq m9, m8, 8 + jmp m(iadst_16x16_internal_10bpc).pass1_fast_end2 +ALIGN function_align +.main_fast2_rect2: + REPX {paddd x, m13}, m16, m17 + REPX {psrad x, 12 }, m16, m17 +.main_fast2: + pmulld m22, m16, [o(pd_4076)] {1to16} ; t15a + pmulld m9, m16, [o(pd_401)] {1to16} ; t8a + pmulld m18, m17, [o(pd_1189)] {1to16} ; t11a + pmulld m17, [o(pd_3920)] {1to16} ; t12a + psubd m18, m13, m18 + REPX {paddd x, m13}, m22, m9, m17 + REPX {psrad x, 12 }, m18, m22, m9, m17 + + mova m20, m9 + mova m16, m18 + mova m23, m22 + mova m19, m17 + jmp .main3 +.main_fast_rect2: + REPX {paddd x, m13}, m16, m17, m18, m19 + REPX {psrad x, 12 }, m16, m17, m18, m19 +.main_fast: + pmulld m23, m16, [o(pd_4076)] {1to16} ; t15a + pmulld m16, [o(pd_401)] {1to16} ; t8a + pmulld m20, m19, [o(pd_2598)] {1to16} ; t9a + pmulld m19, [o(pd_3166)] {1to16} ; t14a + pmulld m22, m17, [o(pd_1189)] {1to16} ; t11a + pmulld m17, [o(pd_3920)] {1to16} ; t12a + pmulld m21, m18, [o(pd_3612)] {1to16} ; t13a + pmulld m18, [o(pd_1931)] {1to16} ; t10a + psubd m20, m13, m20 + psubd m22, m13, m22 + call .round2 + jmp .main2 +.main_rect2: + call .round +.main: + ITX_MULSUB_2D 16, 23, 7, 9, 10, _, 401, 4076 ; t8a, t15a + ITX_MULSUB_2D 20, 19, 7, 9, 10, _, 3166, 2598 ; t9a, t14a + ITX_MULSUB_2D 22, 17, 7, 9, 10, _, 3920, 1189 ; t11a, t12a + ITX_MULSUB_2D 18, 21, 7, 9, 10, _, 1931, 3612 ; t10a, t13a + call .round +.main2: + paddd m9, m20, m16 ; t8 + psubd m20, m16, m20 ; t9 + psubd m16, m22, m18 ; t10 + paddd m18, m22 ; t11 + paddd m22, m23, m19 ; t15 + psubd m23, m19 ; t14 + psubd m19, m17, m21 ; t13 + paddd m17, m21 ; t12 + REPX {pmaxsd x, m14}, m20, m23, m16, m19 + REPX {pminsd x, m15}, m20, m23, m16, m19 + REPX {pmaxsd x, m14}, m9, m18, m22, m17 + REPX {pminsd x, m15}, m9, m18, m22, m17 +.main3: + vpbroadcastd m11, [o(pd_3784)] + vpbroadcastd m10, [o(pd_1567)] + ITX_MULSUB_2D 23, 20, 21, 7, _, 13, 10, 11 + ITX_MULSUB_2D 19, 16, 21, 7, _, 13, 10, 11, 2 + paddd m21, m20, m19 ; t14 + psubd m20, m19 ; t13 + psubd m19, m9, m18 ; t11a + paddd m9, m18 ; t8a + psubd m18, m23, m16 ; t10 + paddd m16, m23 ; t9 + psubd m23, m22, m17 ; t12a + paddd m22, m17 ; t15a + REPX {pmaxsd x, m14}, m20, m23, m18, m19 + REPX {pminsd x, m15}, m20, m23, m18, m19 + REPX {pmulld x, m12}, m20, m23, m18, m19 + psubd m7, m0, m6 ; dct8 out7 + paddd m0, m6 ; dct8 out0 + psubd m6, m1, m5 ; dct8 out6 + paddd m1, m5 ; dct8 out1 + REPX {pmaxsd x, m14}, m7, m0, m6, m1 + psubd m5, m2, m4 ; dct8 out5 + paddd m2, m4 ; dct8 out2 + REPX {pminsd x, m15}, m7, m0, m6, m1 + psubd m4, m3, m8 ; dct8 out4 + paddd m3, m8 ; dct8 out3 + REPX {pmaxsd x, m14}, m5, m2, m4, m3 + paddd m20, m13 + paddd m23, m13 + REPX {pminsd x, m15}, m5, m2, m4, m3 + psubd m17, m20, m18 ; t10a + paddd m20, m18 ; t13a + REPX {pmaxsd x, m14}, m22, m21, m16, m9 + psubd m18, m23, m19 ; t11 + paddd m19, m23 ; t12 + REPX {pminsd x, m15}, m22, m21, m16, m9 + REPX {psrad x, 12 }, m20, m19, m18, m17 + ret +.main_end: + vpbroadcastd m11, [o(pd_2)] +.main_end2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m23, m0, m22 ; out15 + paddd m0, m22 ; out0 + psubd m22, m1, m21 ; out14 + paddd m1, m21 ; out1 + psubd m21, m2, m20 ; out13 + paddd m2, m20 ; out2 + psubd m20, m3, m19 ; out12 + paddd m3, m19 ; out3 + psubd m19, m4, m18 ; out11 + paddd m4, m18 ; out4 + psubd m18, m5, m17 ; out10 + paddd m5, m17 ; out5 + psubd m17, m6, m16 ; out9 + paddd m6, m16 ; out6 + psubd m16, m7, m9 ; out8 + paddd m7, m9 ; out7 + REPX {vpsravd x, m11}, m0, m16, m1, m17, m2, m18, m3, m19, \ + m4, m20, m5, m21, m6, m22, m7, m23 + packssdw m0, m16 + packssdw m1, m17 + packssdw m2, m18 + packssdw m3, m19 + packssdw m4, m20 + packssdw m5, m21 + packssdw m6, m22 + packssdw m7, m23 + ret +.main_end3: + punpckhwd m8, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m4, m5 + punpcklwd m4, m5 + punpcklwd m5, m6, m7 + punpckhwd m6, m7 + punpckhdq m7, m0, m2 + punpckldq m0, m2 + punpckhdq m2, m8, m1 + punpckldq m8, m1 + punpckhdq m1, m4, m5 + punpckldq m4, m5 + punpckhdq m5, m3, m6 + punpckldq m3, m6 + vshufi32x4 m6, m0, m4, q3232 + vinserti32x8 m0, ym4, 1 + vinserti32x8 m4, m8, ym3, 1 + vshufi32x4 m8, m3, q3232 + vinserti32x8 m3, m7, ym1, 1 + vshufi32x4 m7, m1, q3232 + vshufi32x4 m1, m2, m5, q3232 + vinserti32x8 m2, ym5, 1 + vshufi32x4 m5, m7, m1, q2020 ; 10 11 + vshufi32x4 m7, m1, q3131 ; 14 15 + vshufi32x4 m1, m3, m2, q2020 ; 2 3 + vshufi32x4 m3, m2, q3131 ; 6 7 + vshufi32x4 m2, m0, m4, q3131 ; 4 5 + vshufi32x4 m0, m4, q2020 ; 0 1 + vshufi32x4 m4, m6, m8, q2020 ; 8 9 + vshufi32x4 m6, m8, q3131 ; 12 13 + ret +ALIGN function_align +.round: + paddd m20, m13 + paddd m22, m13 +.round2: + paddd m16, m13 + paddd m18, m13 +.round3: + REPX {psrad x, 12 }, m16, m18, m20, m22 + REPX {paddd x, m13}, m17, m19, m21, m23 + REPX {psrad x, 12 }, m17, m19, m21, m23 + ret + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, flipadst +INV_TXFM_16X16_FN adst, adst + +cglobal iadst_16x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + cmp eobd, 36 + jl .fast + call .main_pass1 + packssdw m0, m16 + packssdw m1, m17 + packssdw m2, m18 + packssdw m3, m19 + packssdw m4, m5, m20 + packssdw m5, m6, m21 + packssdw m6, m7, m22 + packssdw m7, m8, m23 + jmp m(idct_16x16_internal_10bpc).pass1_end +.fast: + call .main_pass1_fast + vpbroadcastd m9, [o(pd_2)] + paddd m0, m9 + psubd m1, m9, m1 + paddd m2, m9 + psubd m3, m9, m3 + paddd m4, m9, m5 + psubd m5, m9, m6 + paddd m6, m9, m7 + psubd m7, m9, m8 +.pass1_fast_end: + mova m9, [o(permA)] + psrlq m8, m9, 8 + REPX {psrad x, 2}, m0, m1, m2, m3, m4, m5, m6, m7 +.pass1_fast_end2: + mova m10, m9 + mova m11, m8 + call m(idct_16x8_internal_10bpc).transpose_16x8 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + REPX {mova [cq+64*x], ym4}, 0, 1, 2, 3, 4, 5, 6, 7 + jmp tx2q +.pass2: + lea r5, [o_base_8bpc] + call m(iadst_16x16_internal_8bpc).main_pass2b + movshdup m12, [permC] + mova m11, [pw_2048_m2048] + psrlq m13, m12, 8 + vpermq m8, m13, m0 + vpermq m0, m12, m7 + vpermq m7, m13, m1 + vpermq m1, m12, m6 + vpermq m6, m13, m2 + vpermq m2, m12, m5 + vpermq m5, m13, m3 + vpermq m3, m12, m4 + jmp m(idct_16x16_internal_10bpc).pass2_end +ALIGN function_align +.main_pass1: + mova m0, [cq+64* 0] +%if WIN64 + movaps [cq+16*0], xmm6 + movaps [cq+16*1], xmm7 +%endif + mova m23, [cq+64*15] + vpbroadcastd m13, [o(pd_2048)] + ITX_MULSUB_2D 23, 0, 8, 9, 10, 13, 201, 4091 ; t1 t0 + mova m7, [cq+64* 7] + mova m16, [cq+64* 8] + ITX_MULSUB_2D 7, 16, 8, 9, 10, 13, 3035, 2751 ; t9 t8 + mova m2, [cq+64* 2] + mova m21, [cq+64*13] + ITX_MULSUB_2D 21, 2, 8, 9, 10, 13, 995, 3973 ; t3 t2 + mova m5, [cq+64* 5] + mova m18, [cq+64*10] + ITX_MULSUB_2D 5, 18, 8, 9, 10, 13, 3513, 2106 ; t11 t10 + mova m4, [cq+64* 4] + mova m19, [cq+64*11] + ITX_MULSUB_2D 19, 4, 8, 9, 10, 13, 1751, 3703 ; t5 t4 + mova m3, [cq+64* 3] + mova m20, [cq+64*12] + ITX_MULSUB_2D 3, 20, 8, 9, 10, 13, 3857, 1380 ; t13 t12 + mova m6, [cq+64* 6] + mova m17, [cq+64* 9] + ITX_MULSUB_2D 17, 6, 8, 9, 10, 13, 2440, 3290 ; t7 t6 + mova m1, [cq+64* 1] + mova m22, [cq+64*14] + ITX_MULSUB_2D 1, 22, 8, 9, 10, 13, 4052, 601 ; t15 t14 + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + psubd m9, m23, m7 ; t9a + paddd m23, m7 ; t1a + psubd m7, m2, m18 ; t10a + paddd m18, m2 ; t2a + REPX {pmaxsd x, m14}, m9, m23, m7, m18 + psubd m2, m17, m1 ; t15a + paddd m17, m1 ; t7a + REPX {pminsd x, m15}, m9, m23, m7, m18 + psubd m1, m21, m5 ; t11a + paddd m21, m5 ; t3a + REPX {pmaxsd x, m14}, m2, m17, m1, m21 + psubd m5, m4, m20 ; t12a + paddd m4, m20 ; t4a + REPX {pminsd x, m15}, m2, m17, m1, m21 + psubd m20, m19, m3 ; t13a + paddd m19, m3 ; t5a + REPX {pmaxsd x, m14}, m5, m4, m20, m19 + psubd m8, m6, m22 ; t14a + paddd m6, m22 ; t6a + REPX {pminsd x, m15}, m5, m4, m20, m19 + psubd m22, m0, m16 ; t8a + paddd m16, m0 ; t0a + REPX {pmaxsd x, m14}, m8, m6, m22, m16 + vpbroadcastd m11, [o(pd_4017)] + vpbroadcastd m10, [o(pd_799)] + REPX {pminsd x, m15}, m8, m6, m22, m16 + ITX_MULSUB_2D 22, 9, 0, 3, _, 13, 10, 11 ; t9 t8 + ITX_MULSUB_2D 20, 5, 0, 3, _, 13, 11, 10 ; t12 t13 + vpbroadcastd m11, [o(pd_2276)] + vpbroadcastd m10, [o(pd_3406)] + ITX_MULSUB_2D 7, 1, 0, 3, _, 13, 10, 11 ; t11 t10 + ITX_MULSUB_2D 2, 8, 0, 3, _, 13, 11, 10 ; t14 t15 + paddd m0, m16, m4 ; t0 + psubd m16, m4 ; t4 + psubd m3, m23, m19 ; t5 + paddd m23, m19 ; t1 + REPX {pmaxsd x, m14}, m0, m16, m3, m23 + psubd m19, m18, m6 ; t6 + paddd m18, m6 ; t2 + REPX {pminsd x, m15}, m0, m16, m3, m23 + psubd m6, m21, m17 ; t7 + paddd m21, m17 ; t3 + REPX {pmaxsd x, m14}, m19, m18, m6, m21 + paddd m17, m9, m20 ; t8a + psubd m9, m20 ; t12a + REPX {pminsd x, m15}, m19, m18, m6, m21 + psubd m20, m22, m5 ; t13a + paddd m22, m5 ; t9a + REPX {pmaxsd x, m14}, m17, m9, m20, m22 + psubd m5, m1, m2 ; t14a + paddd m1, m2 ; t10a + REPX {pminsd x, m15}, m17, m9, m20, m22 + psubd m2, m7, m8 ; t15a + paddd m7, m8 ; t11a + REPX {pmaxsd x, m14}, m5, m1, m2, m7 + vpbroadcastd m11, [o(pd_3784)] + vpbroadcastd m10, [o(pd_1567)] + REPX {pminsd x, m15}, m5, m1, m2, m7 + ITX_MULSUB_2D 16, 3, 4, 8, _, 13, 10, 11 ; t5a t4a + ITX_MULSUB_2D 6, 19, 4, 8, _, 13, 11, 10 ; t6a t7a + ITX_MULSUB_2D 9, 20, 4, 8, _, 13, 10, 11 ; t13 t12 + ITX_MULSUB_2D 2, 5, 4, 8, _, 13, 11, 10 ; t14 t15 + psubd m8, m0, m18 ; t2a + paddd m0, m18 ; out0 + psubd m18, m23, m21 ; t3a + paddd m23, m21 ; -out15 + paddd m21, m9, m5 ; -out13 + psubd m9, m5 ; t15a + psubd m5, m3, m6 ; t6 + paddd m3, m6 ; -out3 + REPX {pmaxsd x, m14}, m8, m18, m9, m5 + psubd m6, m20, m2 ; t14a + paddd m2, m20 ; out2 + paddd m20, m16, m19 ; out12 + psubd m16, m19 ; t7 + REPX {pminsd x, m15}, m8, m18, m9, m5 + psubd m19, m22, m7 ; t11 + paddd m22, m7 ; out14 + psubd m7, m17, m1 ; t10 + paddd m1, m17 ; -out1 + REPX {pmaxsd x, m14}, m6, m16, m19, m7 + vpbroadcastd m12, [o(pd_1448)] + vpbroadcastd m4, [o(pd_2)] + vpbroadcastd m10, [o(pd_5120)] + vpbroadcastd m11, [o(pd_5119)] + REPX {pminsd x, m15}, m6, m16, m19, m7 + psubd m17, m7, m19 ; -out9 + paddd m7, m19 ; out6 + psubd m19, m5, m16 ; -out11 + paddd m5, m16 ; out4 + REPX {pmulld x, m12}, m17, m7, m19, m5 + psubd m16, m8, m18 ; out8 + paddd m8, m18 ; -out7 + psubd m18, m6, m9 ; out10 + paddd m6, m9 ; -out5 + REPX {pmulld x, m12}, m16, m8, m18, m6 + REPX {paddd x, m4 }, m0, m2, m20, m22 + REPX {psubd x, m4, x}, m1, m3, m21, m23 + REPX {paddd x, m10 }, m7, m5, m16, m18 + REPX {psubd x, m11, x}, m17, m19, m8, m6 + REPX {psrad x, 2 }, m20, m22, m0, m2, m21, m23, m1, m3 + REPX {psrad x, 13}, m17, m19, m5, m7, m16, m18, m6, m8 + ret +ALIGN function_align +.main_pass1_fast: + mova ym0, [cq+64*0] + mova ym1, [cq+64*2] + movshdup m8, [o(permB)] + mova ym6, [cq+64*1] + mova ym7, [cq+64*3] + mova ym2, [cq+64*4] + mova ym3, [cq+64*6] + mova ym4, [cq+64*5] + mova ym5, [cq+64*7] + vpermt2q m0, m8, m1 ; 0 2 + vpermt2q m7, m8, m6 ; 3 1 + vpermt2q m2, m8, m3 ; 4 6 + vpermt2q m5, m8, m4 ; 7 5 + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m12, [o(pd_2896)] + jmp m(iadst_16x8_internal_10bpc).main_fast + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + cmp eobd, 36 + jl .fast + call m(iadst_16x16_internal_10bpc).main_pass1 + packssdw m4, m19, m3 + packssdw m3, m20, m5 + packssdw m5, m18, m2 + packssdw m2, m21, m6 + packssdw m6, m17, m1 + packssdw m1, m22, m7 + packssdw m7, m16, m0 + packssdw m0, m23, m8 + jmp m(idct_16x16_internal_10bpc).pass1_end +.fast: + call m(iadst_16x16_internal_10bpc).main_pass1_fast + vpbroadcastd m9, [o(pd_2)] + psubd m4, m9, m3 + paddd m3, m9, m5 + paddd m5, m9, m2 + psubd m2, m9, m6 + psubd m6, m9, m1 + paddd m1, m9, m7 + paddd m7, m9, m0 + psubd m0, m9, m8 + jmp m(iadst_16x16_internal_10bpc).pass1_fast_end +.pass2: + lea r5, [o_base_8bpc] + call m(iadst_16x16_internal_8bpc).main_pass2b + movshdup m12, [permC] + movu m11, [pw_m2048_2048] + psrlq m13, m12, 8 + vpermq m8, m13, m7 + vpermq m7, m13, m6 + vpermq m6, m13, m5 + vpermq m5, m13, m4 + vpermq m3, m12, m3 + vpermq m2, m12, m2 + vpermq m1, m12, m1 + vpermq m0, m12, m0 + jmp m(idct_16x16_internal_10bpc).pass2_end + +INV_TXFM_16X16_FN identity, dct, -92 +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_10bpc, 0, 7, 16, dst, stride, c, eob, tx2 +%undef cmp + vpbroadcastd m10, [o(pd_5793)] + vpbroadcastd m11, [o(pd_5120)] + mov r6, cq + cmp eobd, 36 + jl .fast + call .pass1_main + packssdw m0, m6, m8 + packssdw m1, m7, m9 + call .pass1_main + packssdw m2, m6, m8 + packssdw m3, m7, m9 + call .pass1_main + packssdw m4, m6, m8 + packssdw m5, m7, m9 + call .pass1_main + packssdw m6, m8 + packssdw m7, m9 + jmp m(idct_16x16_internal_10bpc).pass1_end2 +.fast: + call .pass1_main_fast + packssdw m0, m6, m7 + call .pass1_main_fast + packssdw m1, m6, m7 + call .pass1_main_fast + packssdw m2, m6, m7 + call .pass1_main_fast + packssdw m3, m6, m7 + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckldq m3, m4, m1 + punpckhdq m4, m1 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + pxor m7, m7 + vshufi32x4 m2, m0, m3, q3131 + vshufi32x4 m0, m3, q2020 + vshufi32x4 m3, m1, m4, q3131 + vshufi32x4 m1, m4, q2020 + REPX {mova x, m7}, m4, m5, m6 + jmp m(idct_16x16_internal_10bpc).pass1_end3 +.pass2: + movshdup m14, [o(permC)] + vpbroadcastd m15, [o(pw_1697x16)] + lea r6, [strideq*3] + vpbroadcastd m11, [o(pw_2048)] + pxor m12, m12 + vpbroadcastd m13, [pixel_10bpc_max] + vpermq m8, m14, m0 + vpermq m9, m14, m1 + call .pass2_main + vpermq m8, m14, m2 + vpermq m9, m14, m3 + call .pass2_main + vpermq m8, m14, m4 + vpermq m9, m14, m5 + call .pass2_main + vpermq m8, m14, m6 + vpermq m9, m14, m7 +.pass2_main: + pmulhrsw m0, m15, m8 + pmulhrsw m1, m15, m9 + paddsw m8, m8 + paddsw m9, m9 + paddsw m8, m0 + paddsw m9, m1 + jmp m(idct_16x8_internal_10bpc).write_16x4 +ALIGN function_align +.pass1_main: + pmulld m6, m10, [r6+64*0] + pmulld m7, m10, [r6+64*1] + pmulld m8, m10, [r6+64*8] + pmulld m9, m10, [r6+64*9] + add r6, 64*2 + REPX {paddd x, m11}, m6, m7, m8, m9 + REPX {psrad x, 13 }, m6, m8, m7, m9 + ret +ALIGN function_align +.pass1_main_fast: + mova ym6, [r6+64* 0] + vinserti32x8 m6, [r6+64* 4], 1 + mova ym7, [r6+64* 8] + vinserti32x8 m7, [r6+64*12], 1 + add r6, 64 + REPX {pmulld x, m10}, m6, m7 + REPX {paddd x, m11}, m6, m7 + REPX {psrad x, 13 }, m6, m7 + ret + +cglobal inv_txfm_add_dct_dct_8x32_10bpc, 4, 7, 22, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + vpbroadcastd m11, [o(pd_2)] + mova m20, [o(idct8x32p)] + pxor m21, m21 + cmp eobd, 43 + jl .fast + call .pass1_main + punpcklwd m16, m0, m1 + punpcklwd m17, m2, m3 + punpckhwd m18, m0, m1 + punpckhwd m19, m2, m3 + cmp eobd, 107 + jge .full + punpckldq m0, m16, m17 ; 0 2 + punpckhdq m1, m16, m17 ; 4 6 + punpckldq m2, m18, m19 ; 8 10 + punpckhdq m3, m18, m19 ; 12 14 + lea r5, [o_base_8bpc] + vextracti32x8 ym14, m0, 1 + vextracti32x8 ym15, m1, 1 + vextracti32x8 ym16, m2, 1 + vextracti32x8 ym17, m3, 1 + call m(idct_8x16_internal_8bpc).main_fast + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_fast + jmp .end +.full: + add cq, 64 + call .pass1_main + punpcklwd m5, m0, m1 + punpcklwd m6, m2, m3 + punpckhwd m7, m0, m1 + punpckhwd m8, m2, m3 + punpckldq m0, m16, m17 ; 0 2 + punpckhdq m1, m16, m17 ; 4 6 + punpckldq m2, m18, m19 ; 8 10 + punpckhdq m3, m18, m19 ; 12 14 + punpckldq m4, m5, m6 ; 16 18 + punpckhdq m5, m6 ; 20 22 + punpckldq m6, m7, m8 ; 24 26 + punpckhdq m7, m8 ; 28 30 + lea r5, [o_base_8bpc] + vextracti32x8 ym14, m0, 1 + vextracti32x8 ym15, m1, 1 + vextracti32x8 ym16, m2, 1 + vextracti32x8 ym17, m3, 1 + vextracti32x8 ym18, m4, 1 + vextracti32x8 ym19, m5, 1 + vextracti32x8 ym20, m6, 1 + vextracti32x8 ym21, m7, 1 + call m(idct_8x16_internal_8bpc).main + REPX {pshufd x, x, q1032}, ym18, ym19, ym20, ym21 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main + jmp .end +.fast: + movshdup m8, [o(permB)] + mova ym1, [cq+128*1] + mova ym5, [cq+128*5] + mova ym7, [cq+128*3] + mova ym3, [cq+128*7] + mova ym0, [cq+128*0] + mova ym4, [cq+128*2] + mova ym2, [cq+128*4] + mova ym6, [cq+128*6] + vpermt2q m1, m8, m5 ; 1 5 + vpermt2q m3, m8, m7 ; 7 3 + vpermt2q m0, m8, m4 ; 0 2 + vpermt2q m2, m8, m6 ; 4 6 + mova [cq+128*0], ym21 + REPX {vmovdqa32 [cq+128*x], ym21}, 1, 2, 3, 4, 5, 6, 7 + call m(idct_8x8_internal_10bpc).main + call m(idct_8x8_internal_10bpc).main_end + packssdw m0, m2 + packssdw m1, m3 + vpermb m0, m20, m0 + vprold m20, 16 + vpermb m2, m20, m1 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + lea r5, [o_base_8bpc] + vextracti32x8 ym14, m0, 1 + vextracti32x8 ym15, m1, 1 + call m(idct_8x16_internal_8bpc).main_fast2 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_fast2 +.end: + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_end ; performs vzeroupper + lea r3, [strideq*2] + vpbroadcastd m12, [pixel_10bpc_max] + lea r6, [strideq*3] + pxor m11, m11 + lea r3, [dstq+r3*8] + pmulhrsw m0, m10 + pmulhrsw m1, m10 + call .write_8x4x2 + pmulhrsw m0, m10, m2 + pmulhrsw m1, m10, m3 + call .write_8x4x2 + pmulhrsw m0, m10, m4 + pmulhrsw m1, m10, m5 + call .write_8x4x2 + pmulhrsw m0, m10, m6 + pmulhrsw m1, m10, m7 +.write_8x4x2: + mova xm8, [dstq+strideq*0] + vinserti32x4 ym8, [dstq+strideq*1], 1 + vinserti32x4 m8, [dstq+strideq*2], 2 + vinserti32x4 m8, [dstq+r6 ], 3 + mova xm9, [r3 +r6 ] + vinserti32x4 ym9, [r3 +strideq*2], 1 + vinserti32x4 m9, [r3 +strideq*1], 2 + vinserti32x4 m9, [r3 +strideq*0], 3 + paddw m8, m0 + paddw m9, m1 + pmaxsw m8, m11 + pmaxsw m9, m11 + pminsw m8, m12 + pminsw m9, m12 + mova [dstq+strideq*0], xm8 + vextracti32x4 [dstq+strideq*1], ym8, 1 + vextracti32x4 [dstq+strideq*2], m8, 2 + vextracti32x4 [dstq+r6 ], m8, 3 + lea dstq, [dstq+strideq*4] + vextracti32x4 [r3 +strideq*0], m9, 3 + vextracti32x4 [r3 +strideq*1], m9, 2 + vextracti32x4 [r3 +strideq*2], ym9, 1 + mova [r3 +r6 ], xm9 + lea r3, [r3+strideq*4] + ret +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 32 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_8x8_10bpc).dconly2 +ALIGN function_align +.pass1_main: + mova m0, [cq+128*0] + mova m1, [cq+128*1] + mova m2, [cq+128*2] + mova m3, [cq+128*3] + mova m4, [cq+128*4] + mova m5, [cq+128*5] + mova m6, [cq+128*6] + mova m7, [cq+128*7] + REPX {mova [cq+128*x], m21}, 0, 1, 2, 3, 4, 5, 6, 7 + call m(idct_8x16_internal_10bpc).main + call m(idct_8x16_internal_10bpc).main_end2 + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + REPX {vpermb x, m20, x}, m0, m1, m2, m3 + ret + +cglobal inv_txfm_add_identity_identity_8x32_10bpc, 4, 8, 12, dst, stride, c, eob + vpbroadcastd m9, [pw_5] + lea r4, [strideq*3] + pxor m10, m10 + lea r5, [strideq*5] + vpbroadcastd m11, [pixel_10bpc_max] + sub eobd, 107 + lea r6, [strideq+r4*2] +.loop: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + lea r7, [dstq+strideq*8] + REPX {mova [cq+128*x], m10}, 0, 1, 2, 3 + REPX {paddsw x, m9}, m0, m1, m2, m3 + REPX {mova [cq+128*x], m10}, 4, 5, 6, 7 + REPX {psraw x, 3 }, m0, m1, m2, m3 + add cq, 64 + mova xm4, [dstq+strideq*0] + mova xm5, [dstq+strideq*1] + mova xm6, [dstq+strideq*2] + mova xm7, [dstq+r4 *1] + punpckhwd m8, m0, m1 + vinserti32x4 ym4, [dstq+strideq*4], 1 + punpcklwd m0, m1 + vinserti32x4 ym5, [dstq+r5 *1], 1 + punpckhwd m1, m2, m3 + vinserti32x4 ym6, [dstq+r4 *2], 1 + punpcklwd m2, m3 + vinserti32x4 ym7, [dstq+r6 *1], 1 + punpckhwd m3, m0, m8 + vinserti32x4 m4, [r7 +strideq*0], 2 + punpcklwd m0, m8 + vinserti32x4 m5, [r7 +strideq*1], 2 + punpckhwd m8, m2, m1 + vinserti32x4 m6, [r7 +strideq*2], 2 + punpcklwd m2, m1 + vinserti32x4 m7, [r7 +r4 *1], 2 + punpckhqdq m1, m0, m2 + vinserti32x4 m4, [r7 +strideq*4], 3 + punpcklqdq m0, m2 + vinserti32x4 m5, [r7 +r5 *1], 3 + punpcklqdq m2, m3, m8 + vinserti32x4 m6, [r7 +r4 *2], 3 + punpckhqdq m3, m8 + vinserti32x4 m7, [r7 +r6 *1], 3 + paddw m0, m4 + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + REPX {pmaxsw x, m10}, m0, m1, m2, m3 + REPX {pminsw x, m11}, m0, m1, m2, m3 + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + mova [dstq+strideq*2], xm2 + mova [dstq+r4 *1], xm3 + vextracti32x4 [dstq+strideq*4], ym0, 1 + vextracti32x4 [dstq+r5 *1], ym1, 1 + vextracti32x4 [dstq+r4 *2], ym2, 1 + vextracti32x4 [dstq+r6 *1], ym3, 1 + lea dstq, [r7+strideq*8] + vextracti32x4 [r7 +strideq*0], m0, 2 + vextracti32x4 [r7 +strideq*1], m1, 2 + vextracti32x4 [r7 +strideq*2], m2, 2 + vextracti32x4 [r7 +r4 *1], m3, 2 + vextracti32x4 [r7 +strideq*4], m0, 3 + vextracti32x4 [r7 +r5 *1], m1, 3 + vextracti32x4 [r7 +r4 *2], m2, 3 + vextracti32x4 [r7 +r6 *1], m3, 3 + add eobd, 0x80000000 + jnc .loop + RET + +cglobal inv_txfm_add_dct_dct_32x8_10bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + mova m11, [o(permB)] + mova m0, [cq+64* 0] ; 0 1 + mova m4, [cq+64* 1] ; 2 3 + mova m1, [cq+64* 2] ; 4 5 + mova m8, [cq+64* 3] ; 6 7 + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + psrlq m10, m11, 32 +%if WIN64 + movaps [cq+16*0], xmm6 + movaps [cq+16*1], xmm7 +%endif + mova m16, m11 + vpermi2q m16, m0, m1 ; 1 5 + mova m17, m11 + vpermi2q m17, m8, m4 ; 7 3 + cmp eobd, 43 + jl .fast + mova m18, [cq+64* 4] ; 8 9 + mova m20, [cq+64* 5] ; 10 11 + mova m6, [cq+64* 6] ; 12 13 + mova m7, [cq+64* 7] ; 14 15 + vpermt2q m0, m10, m18 ; 0 8 + vpermt2q m18, m11, m6 ; 9 13 + mova m19, m11 + vpermi2q m19, m7, m20 ; 15 11 + cmp eobd, 107 + jge .full + vpermt2q m1, m10, m6 ; 4 12 + vpermt2q m4, m10, m8 ; 2 6 + vpermt2q m7, m10, m20 ; 14 10 + mov r6d, 64*1 + call m(idct_8x8_internal_10bpc).main_fast + call m(idct_16x8_internal_10bpc).main_fast + call .main_fast + call m(idct_16x16_internal_10bpc).main_end + jmp .end +.full: + mova m2, [cq+64* 8] ; 16 17 + mova m5, [cq+64* 9] ; 18 19 + mova m9, [cq+64*10] ; 20 21 + mova m21, [cq+64*11] ; 22 23 + vpermt2q m1, m10, m9 ; 4 20 + vpermt2q m7, m10, m21 ; 14 22 + vpermt2q m21, m11, m5 ; 23 19 + vpermt2q m5, m10, m20 ; 18 10 + mova m20, m11 + vpermi2q m20, m2, m9 ; 17 21 + mova m22, [cq+64*12] ; 24 25 + mova m9, [cq+64*13] ; 26 27 + mova m3, [cq+64*14] ; 28 29 + mova m23, [cq+64*15] ; 30 31 + vpermt2q m2, m10, m22 ; 16 24 + vpermt2q m22, m11, m3 ; 25 29 + vpermt2q m3, m10, m6 ; 28 12 + vpermt2q m4, m10, m9 ; 2 26 + mova m6, m10 + vpermi2q m6, m23, m8 ; 30 6 + vpermt2q m23, m11, m9 ; 31 27 + mov r6d, 64*3 + call m(idct_8x8_internal_10bpc).main + call m(idct_16x8_internal_10bpc).main + call .main + call m(idct_16x16_internal_10bpc).main_end + jmp .end +.fast: + vpermq m0, m10, m0 ; 0 0 + vpermq m1, m10, m1 ; 4 4 + vpermt2q m4, m10, m8 ; 2 6 + xor r6d, r6d + call .main_fast2 + call m(idct_16x16_internal_10bpc).main_end +.end: +%if WIN64 + movaps xmm6, [cq+16*0] + movaps xmm7, [cq+16*1] +%endif + vzeroupper + call .transpose_8x32 + pxor m14, m14 +.zero_loop: + mova [cq+r6*4+64*3], m14 + mova [cq+r6*4+64*2], m14 + mova [cq+r6*4+64*1], m14 + mova [cq+r6*4+64*0], m14 + sub r6d, 64 + jge .zero_loop + lea r5, [o_base_8bpc] + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m8 + punpcklqdq m6, m8 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + pxor m12, m12 +.write_32x8_start: + vpbroadcastd m11, [pw_2048] + vpbroadcastd m13, [pixel_10bpc_max] + lea r3, [strideq*3] +.write_32x8: + pmulhrsw m0, m11 + pmulhrsw m1, m11 + pmulhrsw m2, m11 + pmulhrsw m3, m11 + call .write_32x4 + pmulhrsw m0, m11, m4 + pmulhrsw m1, m11, m5 + pmulhrsw m2, m11, m6 + pmulhrsw m3, m11, m7 +.write_32x4: + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] + paddw m2, [dstq+strideq*2] + paddw m3, [dstq+r3 ] + REPX {pmaxsw x, m12}, m0, m1, m2, m3 + REPX {pminsw x, m13}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r3 ], m3 + lea dstq, [dstq+strideq*4] + ret +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 8 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_32x16_10bpc).dconly2 +ALIGN function_align +.main_fast3: + ; assuming m0=in0 in0, m4=in2 in2, and m16=in1 in3 + vbroadcasti32x4 m5, [o(pd_401_4076)] + pmulld m3, m0, m12 + pmulld m4, m5 + REPX {paddd x, m13}, m3, m4 + REPX {psrad x, 12 }, m3, m4 ; m3=idct8:t0-7, m4=t8a t15a + + ; t8a t15a -> t8/9 t14/15 + + vbroadcasti32x4 m5, [o(pd_3784_m3784)] + pshufd m7, m4, q1032 + pmulld m6, m4, [o(pd_1567)]{bcstd} + pmulld m5, m7 + paddd m6, m13 + paddd m5, m6 + psrad m5, 12 ; m5=t9a t14a + + ; t14a t9a -> t13/14 t9/10 [m5] & t8 15 -> t8/11a t12/15a [m4] + + shufps m6, m4, m5, q1032 ; t12 t13 + shufps m8, m4, m5, q3210 ; t11a t10 + pmulld m9, m6, m12 + pmulld m7, m8, m12 + paddd m9, m13 + paddd m5, m9, m7 ; t12 t13a + psubd m4, m9, m7 ; t11 t10a + REPX {psrad x, 12 }, m5, m4 + + psubd m7, m3, m6 ; dct16 out15 out14 + paddd m0, m3, m6 ; dct16 out0 out1 + psubd m6, m3, m5 ; dct16 out12 out13 + paddd m1, m3, m5 ; dct16 out3 out2 + psubd m5, m3, m4 ; dct16 out11 out10 + paddd m2, m3, m4 ; dct16 out4 out5 + psubd m4, m3, m8 ; dct16 out8 out9 + paddd m3, m8 ; dct16 out7 out6 + REPX {pmaxsd x, m14}, m7, m0, m6, m1, m5, m2, m4, m3 + REPX {pminsd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7 + + ; idct32_bottomhalf + vbroadcasti32x4 m18, [o(pd_201_m601)] + vbroadcasti32x4 m19, [o(pd_4091_4052)] + pmulld m17, m16, m19 + pmulld m16, m18 + REPX {paddd x, m13}, m17, m16 + REPX {psrad x, 12 }, m17, m16 + + ; m17: t31a t24a -> t30/31 t24/25, m16: t16a t23a -> t16/17 t22/23 [step2] + + vbroadcasti32x4 m10, [o(pd_799_m2276)] + vbroadcasti32x4 m11, [o(pd_4017_3406)] + pmulld m18, m17, m10 + pmulld m19, m17, m11 + pmulld m8, m16, m11 + pmulld m9, m16, m10 + REPX {paddd x, m13}, m18, m19 + psubd m18, m8 + paddd m19, m9 + REPX {psrad x, 12 }, m18, m19 + + ; m17=t31 t24 -> t28/31a t24/27a, m16=t16 t23 -> t16/19a t20/23a + ; m18=t17a t22a -> t17/18 t21/22, m19=t30a t25a -> t29/30 t25/26 + + punpckhqdq m23, m17, m19 ; t24a t25 [or t27a t26] + punpcklqdq m20, m16, m18 ; t16a t17 [or t19a t18] + punpckhqdq m22, m16, m18 ; t23a t22 [or t20a t21] + punpcklqdq m16, m17, m19 ; t28a t29 [or t31a t30] + mova m21, m23 + mova m18, m20 + mova m17, m22 + mova m19, m16 + + jmp .main4 +.main_fast2: ; bottom three-quarters are zero + vbroadcasti32x4 m8, [o(pd_799_4017)] + pmulld m8, m1 ; t4 t7 + vpmulld m0, [o(pd_2896)] {1to16} ; t0 t1 + REPX {paddd x, m13}, m8, m0 + REPX {psrad x, 12 }, m8, m0 + pmulld m3, m8, m12 + mova m2, m0 ; t3 t2 + call m(idct_8x8_internal_10bpc).main3 + vbroadcasti32x4 m6, [o(pd_4076_3920)] + vbroadcasti32x4 m3, [o(pd_401_m1189)] + pmulld m6, m4 ; t15 t12 + pmulld m4, m3 ; t9 t10 + REPX {paddd x, m13}, m6, m4 + REPX {psrad x, 12 }, m6, m4 + mova m5, m6 ; t14 t13 + mova m9, m4 ; t8 t11 + call m(idct_16x8_internal_10bpc).main3 + vbroadcasti32x4 m23, [o(pd_4091_3973)] + vbroadcasti32x4 m7, [o(pd_201_995)] + vbroadcasti32x4 m22, [o(pd_1380_601)] + vbroadcasti32x4 m9, [o(pd_3857_4052)] + pmulld m23, m16 ; t16 t20 + pmulld m16, m7 ; t31 t27 + pmulld m22, m17 ; -t19 -t25 + pmulld m17, m9 ; t28 t24 + REPX {paddd x, m13}, m23, m16, m17 + psubd m22, m13, m22 + REPX {psrad x, 12 }, m23, m16, m22, m17 + mova m20, m23 ; t30 t26 + mova m9, m16 ; t17 t21 + mova m19, m22 ; t18 t22 + mova m18, m17 ; t29 t25 + jmp .main3 +.main_fast: ; bottom half is zero + vbroadcasti32x4 m23, [o(pd_4091_3973)] + vbroadcasti32x4 m7, [o(pd_201_995)] + vbroadcasti32x4 m20, [o(pd_2751_2106)] + vbroadcasti32x4 m9, [o(pd_3035_3513)] + vbroadcasti32x4 m21, [o(pd_3703_3290)] + vbroadcasti32x4 m10, [o(pd_1751_2440)] + vbroadcasti32x4 m22, [o(pd_1380_601)] + vbroadcasti32x4 m11, [o(pd_3857_4052)] + pmulld m23, m16 ; t16a t20a + pmulld m16, m7 ; t31a t27a + pmulld m20, m19 ; -t17a -t21a + pmulld m19, m9 ; t30a t26a + pmulld m21, m18 ; t18a t22a + pmulld m18, m10 ; t29a t25a + pmulld m22, m17 ; -t19a -t25a + pmulld m17, m11 ; t28a t24a + psubd m20, m13, m20 + psubd m22, m13, m22 + jmp .main2 +.main: + ITX_MULSUB_2D 16, 23, 7, 9, 10, _, 201_995, 4091_3973 + ITX_MULSUB_2D 20, 19, 7, 9, 10, _, 3035_3513, 2751_2106 + ITX_MULSUB_2D 18, 21, 7, 9, 10, _, 1751_2440, 3703_3290 + ITX_MULSUB_2D 22, 17, 7, 9, 10, _, 3857_4052, 1380_601 + paddd m20, m13 + paddd m22, m13 +.main2: + REPX {paddd x, m13}, m16, m23, m19 + REPX {psrad x, 12 }, m16, m20, m23, m19 + psubd m9, m16, m20 ; t17 t21 + paddd m16, m20 ; t16 t20 + psubd m20, m23, m19 ; t30 t26 + paddd m23, m19 ; t31 t27 + REPX {pmaxsd x, m14}, m9, m16, m20, m23 + REPX {paddd x, m13}, m21, m18, m17 + REPX {psrad x, 12 }, m18, m22, m21, m17 + psubd m19, m22, m18 ; t18 t22 + paddd m22, m18 ; t19 t23 + psubd m18, m17, m21 ; t29 t25 + paddd m17, m21 ; t28 t24 + REPX {pmaxsd x, m14}, m19, m22, m18, m17 + REPX {pminsd x, m15}, m20, m9, m18, m19, m16, m23, m22, m17 +.main3: + vbroadcasti32x4 m11, [o(pd_4017_2276)] + vbroadcasti32x4 m10, [o(pd_799_3406)] + psubd m7, m0, m6 ; dct16 out15 out14 + paddd m0, m6 ; dct16 out0 out1 + psubd m6, m1, m5 ; dct16 out12 out13 + paddd m1, m5 ; dct16 out3 out2 + psubd m5, m2, m4 ; dct16 out11 out10 + paddd m2, m4 ; dct16 out4 out5 + psubd m4, m3, m8 ; dct16 out8 out9 + paddd m3, m8 ; dct16 out7 out6 + ITX_MULSUB_2D 20, 9, 8, 21, _, 13, 10, 11 + ITX_MULSUB_2D 18, 19, 8, 21, _, 13, 10, 11, 2 + REPX {pmaxsd x, m14}, m7, m0, m6, m1, m5, m2, m4, m3 + punpckhqdq m21, m16, m20 ; t20 t21a + punpcklqdq m16, m20 ; t16 t17a + punpcklqdq m20, m22, m19 ; t19 t18a + punpckhqdq m22, m19 ; t23 t22a + REPX {pminsd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7 + punpcklqdq m19, m23, m9 ; t31 t30a + punpckhqdq m23, m9 ; t27 t26a + punpckhqdq m9, m17, m18 ; t24 t25a + punpcklqdq m17, m18 ; t28 t29a + psubd m18, m16, m20 ; t19a t18 + paddd m20, m16 ; t16a t17 + psubd m16, m19, m17 ; t28a t29 + paddd m19, m17 ; t31a t30 + psubd m17, m22, m21 ; t20a t21 + paddd m22, m21 ; t23a t22 + psubd m21, m9, m23 ; t27a t26 + paddd m23, m9 ; t24a t25 + REPX {pmaxsd x, m14}, m18, m16, m17, m21 + REPX {pminsd x, m15}, m16, m18, m21, m17 + REPX {pmaxsd x, m14}, m20, m22, m19, m23 + REPX {pminsd x, m15}, m20, m22, m19, m23 +.main4: + vpbroadcastd m11, [o(pd_3784)] + vpbroadcastd m10, [o(pd_1567)] + ITX_MULSUB_2D 16, 18, 8, 9, _, 13, 10, 11 + ITX_MULSUB_2D 21, 17, 8, 9, _, 13, 10, 11, 2 + paddd m9, m20, m22 ; t16 t17a + psubd m20, m22 ; t23 t22a + paddd m22, m19, m23 ; t31 t30a + psubd m19, m23 ; t24 t25a + psubd m23, m16, m17 ; t20a t21 + paddd m16, m17 ; t19a t18 + psubd m17, m18, m21 ; t27a t26 + paddd m21, m18 ; t28a t29 + REPX {pmaxsd x, m14}, m20, m19, m23, m17 + REPX {pminsd x, m15}, m19, m20, m17, m23 + REPX {pmulld x, m12}, m19, m20, m17, m23 + REPX {pmaxsd x, m14}, m22, m21, m16, m9 + paddd m19, m13 + paddd m17, m13 + REPX {pminsd x, m15}, m22, m21, m16, m9 + psubd m18, m19, m20 ; t23a t22 + paddd m19, m20 ; t24a t25 + paddd m20, m17, m23 ; t27 t26a + psubd m17, m23 ; t20 t21a + REPX {psrad x, 12 }, m20, m19, m18, m17 + ret +.transpose_8x32: + mova m10, [o(idct32x8p)] + psrlw m8, m10, 8 + mova m9, m8 + vpermi2w m8, m1, m5 + vpermt2w m1, m10, m5 + vprold m5, m9, 16 + vpermi2w m9, m3, m7 + vpermt2w m3, m10, m7 + vprold m10, 16 + mova m7, m5 + vpermi2w m5, m0, m4 + vpermt2w m0, m10, m4 + vpermi2w m7, m2, m6 + vpermt2w m2, m10, m6 + punpckhdq m6, m5, m8 + punpckldq m5, m8 + punpckhdq m8, m7, m9 + punpckldq m7, m9 + punpckhdq m4, m2, m3 + punpckldq m2, m3 + punpckhdq m3, m0, m1 + punpckldq m0, m1 + ret + +cglobal inv_txfm_add_identity_identity_32x8_10bpc, 4, 7, 10, dst, stride, c, eob + vpbroadcastd m5, [pw_4096] + lea r4, [strideq*3] + mova m6, [idtx32x8p] + lea r5, [strideq*5] + vpbroadcastd m9, [pixel_10bpc_max] + lea r6, [strideq+r4*2] + pxor m8, m8 + sub eobd, 107 + psrlw m7, m6, 8 +.loop: + mova m0, [cq+64*0] + packssdw m0, [cq+64*1] ; 02 13 + mova m1, [cq+64*2] + packssdw m1, [cq+64*3] ; 46 57 + mova m2, [cq+64*4] + packssdw m2, [cq+64*5] ; 8a 9b + mova m3, [cq+64*6] + packssdw m3, [cq+64*7] ; ce df + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + REPX {mova [cq+64*x], m8}, 0, 1, 2, 3 + mova m4, m6 + vpermi2w m4, m1, m3 + vpermt2w m1, m7, m3 + REPX {mova [cq+64*x], m8}, 4, 5, 6, 7 + mova m3, m7 + vpermi2w m3, m0, m2 + vpermt2w m0, m6, m2 + add cq, 64*8 + punpcklqdq m2, m3, m1 ; 4 5 + punpckhqdq m3, m1 ; 6 7 + punpckhqdq m1, m0, m4 ; 2 3 + punpcklqdq m0, m4 ; 0 1 + mova ym4, [dstq+strideq*0] + vinserti32x8 m4, [dstq+strideq*1], 1 + paddw m0, m4 + mova ym4, [dstq+strideq*2] + vinserti32x8 m4, [dstq+r4 *1], 1 + paddw m1, m4 + mova ym4, [dstq+strideq*4] + vinserti32x8 m4, [dstq+r5 *1], 1 + paddw m2, m4 + mova ym4, [dstq+r4 *2] + vinserti32x8 m4, [dstq+r6 *1], 1 + paddw m3, m4 + REPX {pmaxsw x, m8}, m0, m1, m2, m3 + REPX {pminsw x, m9}, m0, m1, m2, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+r4 *1], m1, 1 + mova [dstq+strideq*4], ym2 + vextracti32x8 [dstq+r5 *1], m2, 1 + mova [dstq+r4 *2], ym3 + vextracti32x8 [dstq+r6 *1], m3, 1 + add dstq, 32 + add eobd, 0x80000000 + jnc .loop + RET + +cglobal inv_txfm_add_dct_dct_16x32_10bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] +%if WIN64 + movaps [rsp+ 8], xmm6 + movaps [rsp+24], xmm7 +%endif + cmp eobd, 36 + jl .fast + call .pass1 + cmp eobd, 151 + jge .full + lea r5, [o_base_8bpc] + pxor m9, m9 + punpcklwd m8, m1, m1 ; 2 + punpckhwd m14, m1, m1 ; 3 + punpcklwd m1, m3, m3 ; 6 + punpckhwd m15, m3, m3 ; 7 + punpcklwd m3, m6, m6 ; 12 + punpckhwd m19, m6, m6 ; 13 + punpcklwd m6, m9, m4 ; __ 8 + punpckhwd m20, m4, m4 ; 9 + punpckhwd m16, m5, m5 ; 11 + punpcklwd m5, m5 ; 10 + punpcklwd m9, m0 ; __ 0 + punpckhwd m21, m0, m0 ; 1 + punpcklwd m0, m7, m7 ; 14 + punpckhwd m17, m7, m7 ; 15 + punpcklwd m7, m2, m2 ; 4 + punpckhwd m18, m2, m2 ; 5 + call m(idct_16x16_internal_8bpc).main_fast + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mov r6d, 64*3 + pxor m8, m8 +.zero_loop: + REPX {mova [cq+r6*8+128*x], m8}, 3, 2, 1, 0 + sub r6d, 64 + jge .zero_loop + jmp .pass2_end +.full: + mova [cq+128*0], m0 + mova [cq+128*1], m1 + mova [cq+128*2], m2 + mova [cq+128*3], m3 + mova [cq+128*4], m4 + mova [cq+128*5], m5 + mova [cq+128*6], m6 + mova [cq+128*7], m7 + add cq, 64 + call .pass1 + mova m9, [cq-64* 1] ; 0 1 + mova m14, [cq+64* 1] ; 2 3 + mova m18, [cq+64* 3] ; 4 5 + mova m15, [cq+64* 5] ; 6 7 + mova m20, [cq+64* 7] ; 8 9 + mova m16, [cq+64* 9] ; 10 11 + mova m22, [cq+64*11] ; 12 13 + mova m19, [cq+64*13] ; 14 15 + lea r5, [o_base_8bpc] + punpcklwd m8, m7, m14 ; 30 2 + punpckhwd m21, m7, m9 ; 31 1 + punpcklwd m7, m6, m18 ; 28 4 + punpckhwd m14, m6 ; 3 29 + punpcklwd m9, m0, m9 ; 16 0 + punpckhwd m17, m19, m0 ; 15 17 + punpcklwd m0, m19, m1 ; 14 18 + punpckhwd m19, m1, m22 ; 19 13 + punpcklwd m1, m15, m5 ; 6 26 + punpckhwd m18, m5, m18 ; 27 5 + punpcklwd m6, m4, m20 ; 24 8 + punpckhwd m15, m4 ; 7 25 + punpcklwd m5, m3, m16 ; 22 10 + punpckhwd m20, m3, m20 ; 23 9 + punpcklwd m3, m22, m2 ; 12 20 + punpckhwd m16, m2 ; 11 21 + call m(idct_16x16_internal_8bpc).main2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + mov r6d, 32*7 + pxor m8, m8 +.full_zero_loop: + REPX {mova [cq+r6*8+64*x], m8}, 2, 1, 0, -1 + sub r6d, 32 + jge .full_zero_loop + jmp .pass2_end +.fast: + mova ym0, [cq+128*0] + mova ym2, [cq+128*4] + movshdup m8, [o(permB)] + mova ym1, [cq+128*2] + mova ym3, [cq+128*6] + mova ym4, [cq+128*1] + mova ym5, [cq+128*3] + mova ym6, [cq+128*5] + mova ym7, [cq+128*7] + vpermt2q m0, m8, m2 ; 0 4 + vpermt2q m1, m8, m3 ; 2 6 + vpermt2q m4, m8, m5 ; 1 3 + vpermt2q m7, m8, m6 ; 7 5 + REPX {pmulld x, m12}, m0, m1, m4, m7 + pxor ym16, ym16 + mova [cq+128*0], ym16 + REPX {vmovdqa32 [cq+128*x], ym16}, 1, 2, 3, 4, 5, 6, 7 + REPX {paddd x, m13}, m0, m1, m4, m7 + REPX {psrad x, 12 }, m0, m1, m4, m7 + call m(idct_8x8_internal_10bpc).main_fast + call m(idct_16x8_internal_10bpc).main_fast + vpbroadcastd m11, [o(pd_1)] + call m(idct_8x16_internal_10bpc).main_end2 + mova m8, [o(idct8x32p)] + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + mova m6, [dup16_perm] + vpermb m0, m8, m0 + vpermb m2, m8, m2 + vprold m8, 16 + vpermb m1, m8, m1 + vpermb m3, m8, m3 + punpckldq m4, m0, m2 + punpckhdq m0, m2 + punpckldq m2, m1, m3 + punpckhdq m1, m3 + punpckldq m21, m4, m2 + punpckhdq m14, m4, m2 + punpckldq m18, m0, m1 + punpckhdq m15, m0, m1 + vpermb m8, m6, m14 ; 2 + vpermb m1, m6, m15 ; 6 + vpermb m7, m6, m18 ; 4 + pmovzxwd m9, ym21 ; 0 + vpord m6, [o(pb_32)] {1to16} + lea r5, [o_base_8bpc] + vpermb m21, m6, m21 ; 1 + vpermb m15, m6, m15 ; 7 + vpermb m18, m6, m18 ; 5 + vpermb m14, m6, m14 ; 3 + pslld m9, 16 + call m(idct_16x16_internal_8bpc).main_fast2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 +.pass2_end: + movshdup m22, [permC] + vpbroadcastd m11, [pw_2048] + vpbroadcastd m13, [pixel_10bpc_max] + lea r6, [strideq*3] + pxor m12, m12 + psrlq m23, m22, 8 + vpermq m8, m22, m0 + vpermq m9, m23, m1 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m2 + vpermq m9, m23, m3 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m4 + vpermq m9, m23, m5 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m6 + vpermq m9, m23, m7 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m14 + vpermq m9, m23, m15 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m16 + vpermq m9, m23, m17 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m18 + vpermq m9, m23, m19 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m22, m20 + vpermq m9, m23, m21 +%if WIN64 + movaps xmm6, [rsp+ 8] + movaps xmm7, [rsp+24] +%endif + vzeroupper + jmp m(idct_16x8_internal_10bpc).write_16x4 +.pass1: + pmulld m0, m12, [cq+128* 0] + pmulld m1, m12, [cq+128* 2] + pmulld m2, m12, [cq+128* 4] + pmulld m3, m12, [cq+128* 6] + pmulld m4, m12, [cq+128* 8] + pmulld m5, m12, [cq+128*10] + pmulld m6, m12, [cq+128*12] + pmulld m7, m12, [cq+128*14] + call m(idct_8x16_internal_10bpc).main_rect2 + pmulld m16, m12, [cq+128* 1] + pmulld m17, m12, [cq+128* 3] + pmulld m18, m12, [cq+128* 5] + pmulld m19, m12, [cq+128* 7] + pmulld m20, m12, [cq+128* 9] + pmulld m21, m12, [cq+128*11] + pmulld m22, m12, [cq+128*13] + pmulld m23, m12, [cq+128*15] + call m(idct_16x16_internal_10bpc).main_rect2 + vpbroadcastd m11, [o(pd_1)] + call m(idct_16x16_internal_10bpc).main_end2 + jmp m(idct_16x16_internal_10bpc).main_end3 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_16x8_10bpc).dconly + +cglobal inv_txfm_add_identity_identity_16x32_10bpc, 4, 7, 16, dst, stride, c, eob +%undef cmp + vpbroadcastd m10, [pw_2896x8] + vpbroadcastd m11, [pw_1697x16] + vpbroadcastd m13, [pw_8192] + vpbroadcastd m15, [pixel_10bpc_max] + lea r6, [strideq*9] + pxor m14, m14 + paddw m12, m13, m13 ; pw_16384 + cmp eobd, 151 + jl .main + call .main + add cq, 64-128*4 + lea dstq, [dstq+strideq*8] +.main: + call .main_internal + add cq, 128*4 + pmulhrsw m1, m13, m2 + pmulhrsw m3, m13, m4 + pmulhrsw m5, m13, m6 + pmulhrsw m7, m13, m8 + call .main_internal +.main2: + pmulhrsw m2, m13 + pmulhrsw m4, m13 + pmulhrsw m6, m13 + pmulhrsw m8, m13 + punpcklqdq m0, m1, m2 ; 0 8 + punpckhqdq m1, m2 ; 1 9 + call .write_16x2x2 + punpcklqdq m0, m3, m4 ; 2 10 + punpckhqdq m1, m3, m4 ; 3 11 + call .write_16x2x2 + punpcklqdq m0, m5, m6 ; 4 12 + punpckhqdq m1, m5, m6 ; 5 13 + call .write_16x2x2 + punpcklqdq m0, m7, m8 ; 6 14 + punpckhqdq m1, m7, m8 ; 7 15 +.write_16x2x2: + mova ym2, [dstq+strideq*0] + vinserti32x8 m2, [dstq+strideq*8], 1 + mova ym9, [dstq+strideq*1] + vinserti32x8 m9, [dstq+r6 ], 1 + paddw m0, m2 + paddw m1, m9 + pmaxsw m0, m14 + pmaxsw m1, m14 + pminsw m0, m15 + pminsw m1, m15 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*8], m0, 1 + mova [dstq+strideq*1], ym1 + vextracti32x8 [dstq+r6 ], m1, 1 + lea dstq, [dstq+strideq*2] + ret +.main_internal: + mova m8, [cq+128* 0] + packssdw m8, [cq+128* 8] + mova m6, [cq+128* 1] + packssdw m6, [cq+128* 9] + mova m0, [cq+128* 2] + packssdw m0, [cq+128*10] + mova m2, [cq+128* 3] + packssdw m2, [cq+128*11] + REPX {pmulhrsw x, m10}, m8, m6, m0, m2 + REPX {vpermq x, x, q3120}, m8, m6, m0, m2 + pmulhrsw m4, m11, m8 + pmulhrsw m9, m11, m6 + REPX {mova [cq+128*x], m14}, 0, 1, 2, 3 + pmulhrsw m4, m12 + pmulhrsw m9, m12 + paddsw m8, m4 + paddsw m6, m9 + pmulhrsw m4, m11, m0 + pmulhrsw m9, m11, m2 + REPX {mova [cq+128*x], m14}, 8, 9, 10, 11 + pmulhrsw m4, m12 + pmulhrsw m9, m12 + paddsw m0, m4 + paddsw m2, m9 + punpcklwd m4, m8, m6 + punpckhwd m8, m6 + punpcklwd m6, m0, m2 + punpckhwd m0, m2 + punpckldq m2, m4, m6 ; 0 1 + punpckhdq m4, m6 ; 2 3 + punpckldq m6, m8, m0 ; 4 5 + punpckhdq m8, m0 ; 6 7 + ret + +cglobal inv_txfm_add_dct_dct_32x16_10bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] +%if WIN64 + movaps [rsp+ 8], xmm6 + movaps [rsp+24], xmm7 +%endif + mov r6d, 8*12 + cmp eobd, 36 + jl .fast + pmulld m0, m12, [cq+64* 0] + pmulld m1, m12, [cq+64* 4] + pmulld m2, m12, [cq+64* 8] + pmulld m3, m12, [cq+64*12] + pmulld m16, m12, [cq+64* 2] + pmulld m17, m12, [cq+64* 6] + pmulld m18, m12, [cq+64*10] + pmulld m19, m12, [cq+64*14] + cmp eobd, 151 + jge .full + call m(idct_8x16_internal_10bpc).main_fast_rect2 + call m(idct_16x16_internal_10bpc).main_fast_rect2 + call .idct16_sumsub + call .pass1_load_spill + call .main_fast_rect2 + jmp .pass1_end +.full: + pmulld m4, m12, [cq+64*16] + pmulld m5, m12, [cq+64*20] + pmulld m6, m12, [cq+64*24] + pmulld m7, m12, [cq+64*28] + pmulld m20, m12, [cq+64*18] + pmulld m21, m12, [cq+64*22] + pmulld m22, m12, [cq+64*26] + pmulld m23, m12, [cq+64*30] + add r6d, 8*16 + call m(idct_8x16_internal_10bpc).main_rect2 + call m(idct_16x16_internal_10bpc).main_rect2 + call .idct16_sumsub + call .pass1_load_spill + pmulld m16, m12, [cq+64*17] + pmulld m17, m12, [cq+64*19] + pmulld m18, m12, [cq+64*21] + pmulld m19, m12, [cq+64*23] + pmulld m20, m12, [cq+64*25] + pmulld m21, m12, [cq+64*27] + pmulld m22, m12, [cq+64*29] + pmulld m23, m12, [cq+64*31] + call .main_rect2 +.pass1_end: + vpbroadcastd m11, [o(pd_1)] + lea r4, [cq+64] + call .idct32_pass1_end + lea r5, [o_base_8bpc] + punpckhqdq m19, m5, m16 ; 11 + punpcklqdq m5, m16 ; 10 + punpckhqdq m16, m2, m1 ; 5 + punpcklqdq m2, m1 ; 4 + punpcklqdq m1, m15, m4 ; 2 + punpckhqdq m15, m4 ; 3 + punpcklqdq m4, m14, m18 ; 8 + punpckhqdq m18, m14, m18 ; 9 + punpckhqdq m14, m0, m20 ; 1 + punpcklqdq m0, m20 ; 0 + punpckhqdq m20, m6, m17 ; 13 + punpcklqdq m6, m17 ; 12 + punpckhqdq m17, m3, m21 ; 7 + punpcklqdq m3, m21 ; 6 + punpckhqdq m21, m7, m8 ; 15 + punpcklqdq m7, m8 ; 14 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + jmp .end +.fast: + pmulld ym0, ym12, [cq+64*0] + pmulld ym1, ym12, [cq+64*4] + movshdup m7, [o(permB)] + mova ym4, [cq+64*2] + mova ym5, [cq+64*6] + mova ym16, [cq+64*1] + mova ym2, [cq+64*5] + mova ym3, [cq+64*3] + mova ym17, [cq+64*7] + vpermt2q m4, m7, m5 ; 2 6 + vpermt2q m16, m7, m2 ; 1 5 + vpermt2q m17, m7, m3 ; 7 3 + paddd ym0, ym13 + paddd ym1, ym13 + psrad ym0, 12 + psrad ym1, 12 + vpermq m0, m7, m0 ; 0 0 + vpermq m1, m7, m1 ; 4 4 + REPX {pmulld x, m12}, m4, m16, m17 + REPX {paddd x, m13}, m4, m16, m17 + REPX {psrad x, 12 }, m4, m16, m17 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast2 + vpbroadcastd m11, [o(pd_1)] + call m(idct_16x16_internal_10bpc).main_end2 + call m(inv_txfm_add_dct_dct_32x8_10bpc).transpose_8x32 + lea r5, [o_base_8bpc] + punpckhqdq m14, m0, m2 ; 1 + punpcklqdq m0, m2 ; 0 + punpcklqdq m1, m3, m4 ; 2 + punpckhqdq m15, m3, m4 ; 3 + punpcklqdq m2, m5, m7 ; 4 + punpckhqdq m16, m5, m7 ; 5 + punpcklqdq m3, m6, m8 ; 6 + punpckhqdq m17, m6, m8 ; 7 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast +.end: +%if WIN64 + movaps xmm6, [rsp+ 8] + movaps xmm7, [rsp+24] +%endif + pxor m12, m12 +.zero_loop: + mova [cq+r6*8+64*3], m12 + mova [cq+r6*8+64*2], m12 + mova [cq+r6*8+64*1], m12 + mova [cq+r6*8+64*0], m12 + sub r6d, 8*4 + jge .zero_loop + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x8_start + pmulhrsw m0, m11, m14 + pmulhrsw m1, m11, m15 + pmulhrsw m2, m11, m16 + pmulhrsw m3, m11, m17 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 + pmulhrsw m0, m11, m18 + pmulhrsw m1, m11, m19 + pmulhrsw m2, m11, m20 + pmulhrsw m3, m11, m21 + vzeroupper + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 16 +.dconly3: + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 +.dconly2: + vpbroadcastd m3, [o(dconly_10bpc)] + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + vpbroadcastw m2, r6d + paddsw m2, m3 +.dconly_loop: + paddsw m0, m2, [dstq+strideq*0] + paddsw m1, m2, [dstq+strideq*1] + psubusw m0, m3 + psubusw m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +ALIGN function_align +.idct16_sumsub: + psubd m23, m0, m22 ; t15 + paddd m0, m22 ; t0 + psubd m22, m1, m21 ; t14 + paddd m1, m21 ; t1 + REPX {pmaxsd x, m14}, m23, m0, m22, m1 + psubd m21, m2, m20 ; t13 + paddd m2, m20 ; t2 + REPX {pminsd x, m15}, m23, m0, m22, m1 + psubd m20, m3, m19 ; t12 + paddd m3, m19 ; t3 + REPX {pmaxsd x, m14}, m21, m2, m20, m3 + psubd m19, m4, m18 ; t11 + paddd m4, m18 ; t4 + REPX {pminsd x, m15}, m21, m2, m20, m3 + psubd m18, m5, m17 ; t10 + paddd m5, m17 ; t5 + REPX {pmaxsd x, m14}, m19, m4, m18, m5 + psubd m17, m6, m16 ; t9 + paddd m6, m16 ; t6 + REPX {pminsd x, m15}, m19, m4, m18, m5 + psubd m16, m7, m9 ; t8 + paddd m7, m9 ; t7 + REPX {pmaxsd x, m14}, m17, m6, m16, m7 + REPX {pminsd x, m15}, m17, m6, m16, m7 + ret +.idct32_pass1_end: + psrlq m12, [o(permC)], 24 ; 0 2 8 10 1 3 9 11 + psrlq m13, m12, 32 ; 4 6 12 14 5 7 13 15 +%macro IDCT32_PASS1_END 2 ; low, high + paddd m8, m11, [r4+128*%1] + paddd m9, m11, [cq+128*%1] + psubd m10, m8, m%1 ; out 16+n + paddd m8, m%1 ; out 15-n + paddd m%1, m9, m%2 ; out 0+n + psubd m9, m%2 ; out 31-n + REPX {vpsravd x, m11}, m10, m%1, m8, m9 + packssdw m%1, m10 ; 0+n 16+n + packssdw m%2, m8, m9 ; 15-n 31-n +%endmacro + IDCT32_PASS1_END 0, 23 ; 0 16, 15 31 + IDCT32_PASS1_END 7, 16 ; 7 23, 8 24 + IDCT32_PASS1_END 1, 22 ; 1 17, 14 30 + IDCT32_PASS1_END 6, 17 ; 6 22, 9 25 + IDCT32_PASS1_END 2, 21 ; 2 18, 13 29 + IDCT32_PASS1_END 5, 18 ; 5 21, 10 26 + IDCT32_PASS1_END 3, 20 ; 3 19, 12 28 + IDCT32_PASS1_END 4, 19 ; 4 20, 11 27 +.transpose_16x32: + mova m14, m13 + vpermi2q m14, m0, m16 + vpermt2q m0, m12, m16 + mova m15, m13 + vpermi2q m15, m1, m17 + vpermt2q m1, m12, m17 + mova m16, m13 + vpermi2q m16, m2, m18 + vpermt2q m2, m12, m18 + mova m17, m13 + vpermi2q m17, m3, m19 + vpermt2q m3, m12, m19 + mova m18, m13 + vpermi2q m18, m4, m20 + vpermt2q m4, m12, m20 + mova m19, m13 + vpermi2q m19, m5, m21 + vpermt2q m5, m12, m21 + mova m20, m13 + vpermi2q m20, m6, m22 + vpermt2q m6, m12, m22 + mova m21, m13 + vpermi2q m21, m7, m23 + vpermt2q m7, m12, m23 + punpckhwd m8, m2, m3 ; c04 d04 c05 d05 c06 d06 c07 d07 + punpcklwd m2, m3 ; c00 d00 c01 d01 c02 d02 c03 d03 + punpckhwd m3, m0, m1 ; a04 b04 a05 b05 a06 b06 a07 b07 + punpcklwd m0, m1 ; a00 b00 a01 b01 a02 b02 a03 b03 + punpckhwd m1, m4, m5 ; e04 f04 e05 f05 e06 f06 e07 f07 + punpcklwd m4, m5 ; e00 f00 e01 f01 e02 f02 e03 f03 + punpckhwd m5, m6, m7 ; g04 h04 g05 h05 g06 h06 g07 h07 + punpcklwd m6, m7 ; g00 h00 g01 h01 g02 h02 g03 h03 + punpckhwd m7, m14, m15 ; a12 b12 a13 b13 a14 b14 a15 b15 + punpcklwd m14, m15 ; a08 b08 a09 b09 a10 b10 a11 b11 + punpckhwd m15, m16, m17 ; c12 d12 c13 d13 c14 d14 c15 d15 + punpcklwd m16, m17 ; c08 d08 c09 d09 c10 d10 c11 d11 + punpckhwd m17, m18, m19 ; e12 f12 e13 f13 e14 f14 e15 f15 + punpcklwd m18, m19 ; e08 f08 e09 f09 e10 f10 e11 f11 + punpckhwd m19, m20, m21 ; g12 h12 g13 h13 g14 h14 g15 h15 + punpcklwd m20, m21 ; g08 h08 g09 h09 g10 h10 g11 h11 + punpckhdq m21, m1, m5 ; e06 f06 g06 h06 e07 f07 g07 h07 + punpckldq m1, m5 ; e04 f04 g04 h04 e05 f05 g05 h05 + punpckhdq m5, m14, m16 ; a10 b10 c10 d10 a11 b11 c11 d11 + punpckldq m14, m16 ; a08 b08 c08 d08 a09 b09 c09 d09 + punpckhdq m16, m18, m20 ; e10 f10 g10 h10 e11 f11 g11 h11 + punpckldq m18, m20 ; e08 f08 g08 h08 e09 f09 g09 h09 + punpckldq m20, m4, m6 ; e00 f00 g00 h00 e01 f01 g01 h01 + punpckhdq m4, m6 ; e02 f02 g02 h02 e03 f03 g03 h03 + punpckldq m6, m7, m15 ; a12 b12 c12 d12 a13 b13 c13 d13 + punpckhdq m7, m15 ; a14 b14 c14 d14 a15 b15 c15 d15 + punpckhdq m15, m0, m2 ; a02 b02 c02 d02 a03 b03 c03 d03 + punpckldq m0, m2 ; a00 b00 c00 d00 a01 b01 c01 d01 + punpckldq m2, m3, m8 ; a04 b04 c04 d04 a05 b05 c05 d05 + punpckhdq m3, m8 ; a06 b06 c06 d06 a07 b07 c07 d07 + punpckhdq m8, m17, m19 ; e14 f14 g14 h14 e15 f15 g15 h15 + punpckldq m17, m19 ; e12 f12 g12 h12 e13 f13 g13 h13 + ret +.pass1_load_spill: + mova [cq+64* 0], m0 + mova [cq+64* 2], m1 + mova [cq+64* 4], m2 + mova [cq+64* 6], m3 + mova [cq+64* 8], m4 + mova [cq+64*10], m5 + mova [cq+64*12], m6 + mova [cq+64*14], m7 + pmulld m0, m12, [cq+64* 1] + pmulld m1, m12, [cq+64* 3] + pmulld m2, m12, [cq+64* 5] + pmulld m3, m12, [cq+64* 7] + pmulld m4, m12, [cq+64* 9] + pmulld m5, m12, [cq+64*11] + pmulld m6, m12, [cq+64*13] + pmulld m7, m12, [cq+64*15] + mova [cq+64* 1], m23 + mova [cq+64* 3], m22 + mova [cq+64* 5], m21 + mova [cq+64* 7], m20 + mova [cq+64* 9], m19 + mova [cq+64*11], m18 + mova [cq+64*13], m17 + mova [cq+64*15], m16 + ret +.main_fast2_rect2: + REPX {paddd x, m13}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_fast2: ; bottom 3/4 is zero + pmulld m23, m0, [o(pd_4091)] {1to16} ; t31a + pmulld m0, [o(pd_201)] {1to16} ; t16a + pmulld m20, m3, [o(pd_1380)] {1to16} ; t19a + pmulld m3, [o(pd_3857)] {1to16} ; t28a + pmulld m21, m2, [o(pd_3973)] {1to16} ; t27a + pmulld m2, [o(pd_995)] {1to16} ; t20a + pmulld m6, m1, [o(pd_601)] {1to16} ; t23a + pmulld m17, m1, [o(pd_4052)] {1to16} ; t24a + REPX {psubd x, m13, x}, m20, m6 + REPX {paddd x, m13}, m23, m0, m3, m21, m2, m17 + REPX {psrad x, 12 }, m20, m6, m23, m0, m3, m21, m2, m17 + mova m8, m0 + mova m16, m23 + mova m7, m20 + mova m4, m3 + mova m19, m2 + mova m18, m21 + mova m5, m6 + mova m22, m17 + jmp .main3 +.main_fast_rect2: + call m(idct_8x16_internal_10bpc).round +.main_fast: ; bottom half is zero + pmulld m23, m0, [o(pd_4091)] {1to16} ; t31a + pmulld m0, [o(pd_201)] {1to16} ; t16a + pmulld m16, m7, [o(pd_2751)] {1to16} ; t17a + pmulld m7, [o(pd_3035)] {1to16} ; t30a + pmulld m19, m4, [o(pd_3703)] {1to16} ; t29a + pmulld m4, [o(pd_1751)] {1to16} ; t18a + pmulld m20, m3, [o(pd_1380)] {1to16} ; t19a + pmulld m3, [o(pd_3857)] {1to16} ; t28a + pmulld m21, m2, [o(pd_3973)] {1to16} ; t27a + pmulld m2, [o(pd_995)] {1to16} ; t20a + pmulld m18, m5, [o(pd_2106)] {1to16} ; t21a + pmulld m5, [o(pd_3513)] {1to16} ; t26a + pmulld m17, m6, [o(pd_3290)] {1to16} ; t25a + pmulld m6, [o(pd_2440)] {1to16} ; t22a + pmulld m22, m1, [o(pd_601)] {1to16} ; t23a + pmulld m1, [o(pd_4052)] {1to16} ; t24a + REPX {psubd x, m13, x}, m16, m20, m18, m22 + call m(idct_16x16_internal_10bpc).round3 + jmp .main2 +.main_rect2: + call m(idct_8x16_internal_10bpc).round + call m(idct_16x16_internal_10bpc).round +.main: + ITX_MULSUB_2D 0, 23, 8, 9, 10, _, 201, 4091 ; t16a, t31a + ITX_MULSUB_2D 16, 7, 8, 9, 10, _, 3035, 2751 ; t17a, t30a + ITX_MULSUB_2D 4, 19, 8, 9, 10, _, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2D 20, 3, 8, 9, 10, _, 3857, 1380 ; t19a, t28a + ITX_MULSUB_2D 2, 21, 8, 9, 10, _, 995, 3973 ; t20a, t27a + ITX_MULSUB_2D 18, 5, 8, 9, 10, _, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2D 6, 17, 8, 9, 10, _, 2440, 3290 ; t22a, t25a + ITX_MULSUB_2D 22, 1, 8, 9, 10, _, 4052, 601 ; t23a, t24a + call m(idct_16x16_internal_10bpc).round +.main2: + call m(idct_8x16_internal_10bpc).round + psubd m8, m0, m16 ; t17 + paddd m0, m16 ; t16 + psubd m16, m23, m7 ; t30 + paddd m23, m7 ; t31 + REPX {pmaxsd x, m14}, m8, m0, m16, m23 + paddd m7, m20, m4 ; t19 + psubd m20, m4 ; t18 + REPX {pminsd x, m15}, m8, m0, m16, m23 + paddd m4, m3, m19 ; t28 + psubd m3, m19 ; t29 + REPX {pmaxsd x, m14}, m7, m20, m4, m3 + psubd m19, m2, m18 ; t21 + paddd m2, m18 ; t20 + REPX {pminsd x, m15}, m7, m20, m4, m3 + psubd m18, m21, m5 ; t26 + paddd m21, m5 ; t27 + REPX {pmaxsd x, m14}, m19, m2, m18, m21 + psubd m5, m22, m6 ; t22 + paddd m6, m22 ; t23 + REPX {pminsd x, m15}, m19, m2, m18, m21 + psubd m22, m1, m17 ; t25 + paddd m17, m1 ; t24 + REPX {pmaxsd x, m14}, m5, m6, m22, m17 + REPX {pminsd x, m15}, m5, m6, m22, m17 +.main3: + vpbroadcastd m11, [o(pd_4017)] + vpbroadcastd m10, [o(pd_799)] + ITX_MULSUB_2D 16, 8, 9, 1, _, 13, 10, 11 ; t17a, t30a + ITX_MULSUB_2D 3, 20, 9, 1, _, 13, 10, 11, 2 ; t29a, t18a + vpbroadcastd m11, [o(pd_2276)] + vpbroadcastd m10, [o(pd_3406)] + ITX_MULSUB_2D 18, 19, 9, 1, _, 13, 10, 11 ; t21a, t26a + ITX_MULSUB_2D 22, 5, 9, 1, _, 13, 10, 11, 2 ; t25a, t22a + paddd m1, m6, m2 ; t23a + psubd m6, m2 ; t20a + psubd m2, m17, m21 ; t27a + paddd m17, m21 ; t24a + REPX {pmaxsd x, m14}, m1, m6, m2, m17 + psubd m21, m23, m4 ; t28a + paddd m23, m4 ; t31a + REPX {pminsd x, m15}, m1, m6, m2, m17 + psubd m4, m16, m20 ; t18 + paddd m16, m20 ; t17 + REPX {pmaxsd x, m14}, m21, m23, m4, m16 + psubd m20, m0, m7 ; t19a + paddd m0, m7 ; t16a + REPX {pminsd x, m15}, m21, m23, m4, m16 + psubd m7, m8, m3 ; t29 + paddd m3, m8 ; t30 + REPX {pmaxsd x, m14}, m20, m0, m7, m3 + paddd m8, m5, m18 ; t22 + psubd m5, m18 ; t21 + REPX {pminsd x, m15}, m20, m0, m7, m3 + psubd m18, m22, m19 ; t26 + paddd m22, m19 ; t25 + REPX {pmaxsd x, m14}, m8, m5, m18, m22 + vpbroadcastd m11, [o(pd_3784)] + vpbroadcastd m10, [o(pd_1567)] + REPX {pminsd x, m15}, m8, m5, m18, m22 + ITX_MULSUB_2D 21, 20, 9, 19, _, 13, 10, 11 ; t19, t28 + ITX_MULSUB_2D 2, 6, 9, 19, _, 13, 10, 11, 2 ; t27, t20 + ITX_MULSUB_2D 7, 4, 9, 19, _, 13, 10, 11 ; t18a, t29a + ITX_MULSUB_2D 18, 5, 9, 19, _, 13, 10, 11, 2 ; t26a, t21a + psubd m19, m0, m1 ; t23 + paddd m0, m1 ; t16 + paddd m1, m8, m16 ; t17a + psubd m8, m16, m8 ; t22a + REPX {pmaxsd x, m14}, m19, m0, m1, m8 + psubd m16, m23, m17 ; t24 + paddd m23, m17 ; t31 + REPX {pminsd x, m15}, m19, m0, m1, m8 + psubd m17, m3, m22 ; t25a + paddd m22, m3 ; t30a + REPX {pmaxsd x, m14}, m16, m23, m17, m22 + paddd m3, m6, m21 ; t19a + psubd m6, m21, m6 ; t20a + REPX {pminsd x, m15}, m16, m23, m17, m22 + paddd m21, m18, m4 ; t29 + psubd m18, m4, m18 ; t26 + REPX {pmaxsd x, m14}, m3, m6, m21, m18 + psubd m4, m20, m2 ; t27a + paddd m20, m2 ; t28a + REPX {pminsd x, m15}, m3, m6, m21, m18 + paddd m2, m7, m5 ; t18 + psubd m7, m5 ; t21 + REPX {pmaxsd x, m14}, m4, m20, m2, m7 + REPX {pminsd x, m15}, m4, m20, m2, m7 + REPX {pmulld x, m12}, m18, m16, m4, m17, m7, m19, m6, m8 + REPX {paddd x, m13}, m18, m16, m4, m17 + psubd m5, m18, m7 ; t21a + paddd m18, m7 ; t26a + psubd m7, m16, m19 ; t23a + paddd m16, m19 ; t24a + REPX {psrad x, 12 }, m5, m18, m7, m16 + paddd m19, m4, m6 ; t27 + psubd m4, m6 ; t20 + psubd m6, m17, m8 ; t22 + paddd m17, m8 ; t25 + REPX {psrad x, 12 }, m19, m4, m6, m17 + ret + +cglobal inv_txfm_add_identity_identity_32x16_10bpc, 4, 7, 16, dst, stride, c, eob +%undef cmp + vpbroadcastd m10, [pw_2896x8] + vpbroadcastd m11, [pw_1697x16] + vpbroadcastd m13, [pw_2048] + vpbroadcastd m15, [pixel_10bpc_max] + lea r6, [strideq*9] + pxor m14, m14 + cmp eobd, 151 + jl .main + mov r4, dstq + call .main + add cq, 64*12 + lea dstq, [r4+32] +.main: + call .main_internal + add cq, 64*4 + pmulhrsw m1, m13, m2 + pmulhrsw m3, m13, m4 + pmulhrsw m5, m13, m6 + pmulhrsw m7, m13, m8 + call .main_internal + jmp m(inv_txfm_add_identity_identity_16x32_10bpc).main2 +.main_internal: + mova m8, [cq+64* 0] + packssdw m8, [cq+64* 8] + mova m6, [cq+64* 1] + packssdw m6, [cq+64* 9] + mova m0, [cq+64* 2] + packssdw m0, [cq+64*10] + mova m2, [cq+64* 3] + packssdw m2, [cq+64*11] + REPX {pmulhrsw x, m10}, m8, m6, m0, m2 + REPX {paddsw x, x }, m8, m6, m0, m2 + REPX {vpermq x, x, q3120}, m8, m6, m0, m2 + pmulhrsw m4, m11, m8 + pmulhrsw m9, m11, m6 + paddsw m8, m8 + paddsw m6, m6 + REPX {mova [cq+64*x], m14}, 0, 1, 2, 3 + paddsw m8, m4 + paddsw m6, m9 + pmulhrsw m4, m11, m0 + pmulhrsw m9, m11, m2 + paddsw m0, m0 + paddsw m2, m2 + REPX {mova [cq+64*x], m14}, 8, 9, 10, 11 + paddsw m0, m4 + paddsw m2, m9 + punpcklwd m4, m8, m6 + punpckhwd m8, m6 + punpcklwd m6, m0, m2 + punpckhwd m0, m2 + punpckldq m2, m4, m6 ; 0 1 + punpckhdq m4, m6 ; 2 3 + punpckldq m6, m8, m0 ; 4 5 + punpckhdq m8, m0 ; 6 7 + ret + +cglobal inv_txfm_add_dct_dct_32x32_10bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + WIN64_SPILL_XMM 30 + cmp eobd, 136 + jl .fast + add cq, 64 + cmp eobd, 543 + jge .full + call .pass1_fast ; bottomright 16x16 zero + mov r6d, 16*12 + jmp .lefthalf +.full: + call .pass1 + mov r6d, 16*28 +.lefthalf: + mova [cq+128* 0], m0 + mova [cq+128* 1], m1 + mova [cq+128* 2], m2 + mova [cq+128* 3], m3 + mova [cq+128* 4], m14 + mova [cq+128* 5], m15 + mova [cq+128* 6], m16 + mova [cq+128* 7], m17 + mova [cq+128* 8], m22 + mova [cq+128* 9], m23 + mova [cq+128*10], m24 + mova [cq+128*11], m25 + mova [cq+128*12], m26 + mova [cq+128*13], m27 + mova [cq+128*14], m28 + mova [cq+128*15], m29 + sub cq, 64 + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + call .pass1 + lea r5, [o_base_8bpc] + call .pass2_start + pxor m12, m12 +.right_zero_loop: + mova [cq+r6*8+64+128*3], m12 + mova [cq+r6*8+64+128*2], m12 + mova [cq+r6*8+64+128*1], m12 + mova [cq+r6*8+64+128*0], m12 + sub r6d, 16*4 + jge .right_zero_loop + mov r6d, 16*28 + jmp .end2 +.pass2_start: + mova m4, [cq+64+128* 0] + mova m5, [cq+64+128* 1] + mova m6, [cq+64+128* 2] + mova m7, [cq+64+128* 3] + mova m18, [cq+64+128* 4] + mova m19, [cq+64+128* 5] + mova m20, [cq+64+128* 6] + mova m21, [cq+64+128* 7] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova [cq+128*0], m14 + mova [cq+128*1], m15 + mova [cq+128*2], m16 + mova [cq+128*3], m17 + mova [cq+128*4], m18 + mova [cq+128*5], m19 + mova [cq+128*6], m20 + mova [cq+128*7], m21 + mova m14, [cq+64+128* 8] + mova m15, [cq+64+128* 9] + mova m16, [cq+64+128*10] + mova m17, [cq+64+128*11] + mova m18, [cq+64+128*12] + mova m19, [cq+64+128*13] + mova m20, [cq+64+128*14] + mova m21, [cq+64+128*15] + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf +.fast: ; topleft 16x16 nonzero + cmp eobd, 36 + jl .fast2 + call .pass1_fast + lea r5, [o_base_8bpc] + call .pass2_fast_start + jmp .end +.pass2_fast_start: + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + mova [cq+128*0], m14 + mova [cq+128*1], m15 + mova [cq+128*2], m16 + mova [cq+128*3], m17 + mova [cq+128*4], m18 + mova [cq+128*5], m19 + mova [cq+128*6], m20 + mova [cq+128*7], m21 + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast +.fast2: ; topleft 8x8 nonzero + movshdup m7, [o(permB)] + mova ym0, [cq+128*0] + mova ym1, [cq+128*4] + mova ym4, [cq+128*2] + mova ym5, [cq+128*6] + mova ym16, [cq+128*1] + mova ym2, [cq+128*5] + mova ym3, [cq+128*3] + mova ym17, [cq+128*7] + mov r6d, 16*4 + vpermq m0, m7, m0 ; 0 0 + vpermq m1, m7, m1 ; 4 4 + vpermt2q m4, m7, m5 ; 2 6 + vpermt2q m16, m7, m2 ; 1 5 + vpermt2q m17, m7, m3 ; 7 3 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast2 + call m(idct_16x16_internal_10bpc).main_end + call .pass2_fast2_start +.end: + pxor m12, m12 +.end2: + call .pass2_end +.zero_loop: + mova [cq+r6*8+128*3], m12 + mova [cq+r6*8+128*2], m12 + mova [cq+r6*8+128*1], m12 + mova [cq+r6*8+128*0], m12 + sub r6d, 16*4 + jge .zero_loop + WIN64_RESTORE_XMM + vzeroupper + ret +.pass2_fast2_start: + call m(inv_txfm_add_dct_dct_32x8_10bpc).transpose_8x32 + lea r5, [o_base_8bpc] + punpckhqdq m22, m0, m2 ; 1 + punpcklqdq m0, m2 ; 0 + punpcklqdq m1, m5, m7 ; 4 + punpckhqdq m24, m5, m7 ; 5 + punpcklqdq m14, m3, m4 ; 2 + punpckhqdq m23, m3, m4 ; 3 + punpcklqdq m15, m6, m8 ; 6 + punpckhqdq m25, m6, m8 ; 7 + mova m10, m13 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast2 + mova [cq+128*0], m14 + mova [cq+128*1], m15 + mova [cq+128*2], m16 + mova [cq+128*3], m17 + mova [cq+128*4], m18 + mova [cq+128*5], m19 + mova [cq+128*6], m20 + mova [cq+128*7], m21 + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast2 +.pass2_end: + psubsw m9, m0, m29 ; out31 + paddsw m0, m29 ; out0 + psubsw m29, m1, m28 ; out30 + paddsw m1, m28 ; out1 + psubsw m28, m2, m27 ; out29 + paddsw m2, m27 ; out2 + psubsw m27, m3, m26 ; out28 + paddsw m3, m26 ; out3 + psubsw m26, m4, m25 ; out27 + paddsw m4, m25 ; out4 + psubsw m25, m5, m24 ; out26 + paddsw m5, m24 ; out5 + psubsw m24, m6, m23 ; out25 + paddsw m6, m23 ; out6 + psubsw m23, m7, m22 ; out24 + paddsw m7, m22 ; out7 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x8_start + mova m0, [cq+128*0] + mova m1, [cq+128*1] + mova m2, [cq+128*2] + mova m3, [cq+128*3] + mova m4, [cq+128*4] + mova m5, [cq+128*5] + mova m6, [cq+128*6] + mova m7, [cq+128*7] + psubsw m22, m0, m21 ; out23 + paddsw m0, m21 ; out8 + psubsw m21, m1, m20 ; out22 + paddsw m1, m20 ; out9 + psubsw m20, m2, m19 ; out21 + paddsw m2, m19 ; out10 + psubsw m19, m3, m18 ; out20 + paddsw m3, m18 ; out11 + psubsw m18, m4, m17 ; out19 + paddsw m4, m17 ; out12 + psubsw m17, m5, m16 ; out18 + paddsw m5, m16 ; out13 + psubsw m16, m6, m15 ; out17 + paddsw m6, m15 ; out14 + psubsw m15, m7, m14 ; out16 + paddsw m7, m14 ; out15 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x8 + pmulhrsw m0, m11, m15 + pmulhrsw m1, m11, m16 + pmulhrsw m2, m11, m17 + pmulhrsw m3, m11, m18 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 + pmulhrsw m0, m11, m19 + pmulhrsw m1, m11, m20 + pmulhrsw m2, m11, m21 + pmulhrsw m3, m11, m22 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 + pmulhrsw m0, m11, m23 + pmulhrsw m1, m11, m24 + pmulhrsw m2, m11, m25 + pmulhrsw m3, m11, m26 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 + pmulhrsw m0, m11, m27 + pmulhrsw m1, m11, m28 + pmulhrsw m2, m11, m29 + pmulhrsw m3, m11, m9 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 32 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_32x16_10bpc).dconly2 +.pass1_fast: + mova m0, [cq+128* 0] + mova m1, [cq+128* 4] + mova m2, [cq+128* 8] + mova m3, [cq+128*12] + mov r6d, 16*12 + call m(idct_8x16_internal_10bpc).main_fast + mova m16, [cq+128* 2] + mova m17, [cq+128* 6] + mova m18, [cq+128*10] + mova m19, [cq+128*14] + call m(idct_16x16_internal_10bpc).main_fast + call .pass1_load_spill + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast + jmp .pass1_end +.pass1: + mova m0, [cq+128* 0] + mova m1, [cq+128* 4] + mova m2, [cq+128* 8] + mova m3, [cq+128*12] + mova m4, [cq+128*16] + mova m5, [cq+128*20] + mova m6, [cq+128*24] + mova m7, [cq+128*28] + call m(idct_8x16_internal_10bpc).main + mova m16, [cq+128* 2] + mova m17, [cq+128* 6] + mova m18, [cq+128*10] + mova m19, [cq+128*14] + mova m20, [cq+128*18] + mova m21, [cq+128*22] + mova m22, [cq+128*26] + mova m23, [cq+128*30] + call m(idct_16x16_internal_10bpc).main + call .pass1_load_spill + mova m16, [cq+128*17] + mova m17, [cq+128*19] + mova m18, [cq+128*21] + mova m19, [cq+128*23] + mova m20, [cq+128*25] + mova m21, [cq+128*27] + mova m22, [cq+128*29] + mova m23, [cq+128*31] + call m(inv_txfm_add_dct_dct_32x16_10bpc).main +.pass1_end: + vpbroadcastd m11, [o(pd_2)] + lea r4, [cq+128*8] + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct32_pass1_end + punpckhqdq m22, m0, m20 ; 1 + punpcklqdq m0, m20 ; 0 + punpckhqdq m24, m2, m1 ; 5 + punpcklqdq m1, m2, m1 ; 4 + punpcklqdq m2, m14, m18 ; 8 + punpckhqdq m26, m14, m18 ; 9 + punpcklqdq m14, m15, m4 ; 2 + punpckhqdq m23, m15, m4 ; 3 + punpckhqdq m25, m3, m21 ; 7 + punpcklqdq m15, m3, m21 ; 6 + punpckhqdq m28, m6, m17 ; 13 + punpcklqdq m3, m6, m17 ; 12 + punpckhqdq m27, m5, m16 ; 11 + punpcklqdq m16, m5, m16 ; 10 + punpckhqdq m29, m7, m8 ; 15 + punpcklqdq m17, m7, m8 ; 14 + ret +.pass1_load_spill: + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + mova [cq+128* 0], m0 + mova m0, [cq+128* 1] + mova [cq+128* 1], m1 + mova [cq+128* 2], m2 + mova m1, [cq+128* 3] + mova m2, [cq+128* 5] + mova [cq+128* 3], m3 + mova [cq+128* 4], m4 + mova m3, [cq+128* 7] + mova m4, [cq+128* 9] + mova [cq+128* 5], m5 + mova [cq+128* 6], m6 + mova [cq+128* 7], m7 + mova m5, [cq+128*11] + mova m6, [cq+128*13] + mova m7, [cq+128*15] + mova [cq+128* 8], m23 + mova [cq+128* 9], m22 + mova [cq+128*10], m21 + mova [cq+128*11], m20 + mova [cq+128*12], m19 + mova [cq+128*13], m18 + mova [cq+128*14], m17 + mova [cq+128*15], m16 + ret + +cglobal inv_txfm_add_identity_identity_32x32_10bpc, 4, 7, 16, dst, stride, c, eob +%undef cmp + vpbroadcastd m13, [pw_8192] + vpbroadcastd m15, [pixel_10bpc_max] + pxor m14, m14 + lea r6, [strideq*9] + cmp eobd, 136 + jl .main + mov r4, dstq + call .main + add cq, 64-128*4 + lea dstq, [dstq+strideq*8] + call .main + add cq, 128*12-64 + lea dstq, [r4+32] + cmp eobd, 543 + jl .main + call .main + add cq, 64-128*4 + lea dstq, [dstq+strideq*8] +.main: + call .main_internal + add cq, 128*4 + pmulhrsw m1, m13, m2 + pmulhrsw m3, m13, m4 + pmulhrsw m5, m13, m6 + pmulhrsw m7, m13, m8 + call .main_internal + jmp m(inv_txfm_add_identity_identity_16x32_10bpc).main2 +.main_internal: + mova m8, [cq+128* 0] + packssdw m8, [cq+128* 8] + mova m6, [cq+128* 1] + packssdw m6, [cq+128* 9] + mova m0, [cq+128* 2] + packssdw m0, [cq+128*10] + mova m2, [cq+128* 3] + packssdw m2, [cq+128*11] + REPX {vpermq x, x, q3120}, m8, m6, m0, m2 + REPX {mova [cq+128*x], m14}, 0, 1, 2, 3 + punpcklwd m4, m8, m6 + punpckhwd m8, m6 + punpcklwd m6, m0, m2 + punpckhwd m0, m2 + REPX {mova [cq+128*x], m14}, 8, 9, 10, 11 + punpckldq m2, m4, m6 ; 0 1 + punpckhdq m4, m6 ; 2 3 + punpckldq m6, m8, m0 ; 4 5 + punpckhdq m8, m0 ; 6 7 + ret + +cglobal inv_txfm_add_dct_dct_16x64_10bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + + PROLOGUE 4, 7, 32, -8*mmsize, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 36 + jl .fast + call .pass1 + cmp eobd, 151 + jge .full + lea r5, [o_base_8bpc] + + punpckhwd m22, m0, m0 + punpckhwd m23, m1, m1 + punpckhwd m24, m2, m2 + punpckhwd m25, m3, m3 + punpckhwd m26, m4, m4 + punpckhwd m27, m5, m5 + punpckhwd m28, m6, m6 + punpckhwd m29, m7, m7 + punpcklwd m21, m1, m1 + punpcklwd m14, m3, m3 + punpcklwd m18, m5, m5 + punpcklwd m15, m7, m7 + pxor m9, m9 + punpcklwd m9, m9, m0 + punpcklwd m8, m2, m2 + punpcklwd m7, m4, m4 + punpcklwd m1, m6, m6 + call m(idct_16x16_internal_8bpc).main_fast2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + mova [rsp+mmsize*0], m14 + mova [rsp+mmsize*1], m15 + mova [rsp+mmsize*2], m16 + mova [rsp+mmsize*3], m17 + mova [rsp+mmsize*4], m18 + mova [rsp+mmsize*5], m19 + mova [rsp+mmsize*6], m20 + mova [rsp+mmsize*7], m21 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf_fast + + pxor m12, m12 + mov r3d, 64*3 +.zero_loop: + REPX {mova [cq+r3*8+128*x], m12}, 0, 1, 2, 3 + sub r3d, 64 + jge .zero_loop + + jmp .pass2_end +.full: + mova [cq+128*0], m0 + mova [cq+128*1], m1 + mova [cq+128*2], m2 + mova [cq+128*3], m3 + mova [cq+128*4], m4 + mova [cq+128*5], m5 + mova [cq+128*6], m6 + mova [cq+128*7], m7 + add cq, 64 + call .pass1 + sub cq, 64 + mova m22, [cq+128*0] ; 0 1 + mova m23, [cq+128*1] ; 2 3 + mova m24, [cq+128*2] ; 4 5 + mova m25, [cq+128*3] ; 6 7 + mova m26, [cq+128*4] ; 8 9 + mova m27, [cq+128*5] ; 10 11 + mova m28, [cq+128*6] ; 12 13 + mova m29, [cq+128*7] ; 14 15 + mova [cq+64* 8], m0 + mova [cq+64* 9], m1 + mova [cq+64*10], m2 + mova [cq+64*11], m3 + mova [cq+64*12], m4 + mova [cq+64*13], m5 + mova [cq+64*14], m6 + mova [cq+64*15], m7 + lea r5, [o_base_8bpc] + + punpcklwd m20, m1, m1 + punpcklwd m16, m3, m3 + punpcklwd m19, m5, m5 + punpcklwd m17, m7, m7 + punpcklwd m8, m24, m24 ; 4 + punpcklwd m5, m2, m2 ; 20 + punpcklwd m1, m28, m28 ; 12 + punpcklwd m7, m26, m26 ; 8 + punpcklwd m3, m4, m4 ; 24 + punpcklwd m4, m6, m6 ; 28 + pxor m9, m9 + punpcklwd m6, m9, m0 ; __ 16 + mova m0, m4 + punpcklwd m9, m9, m22 ; __ 0 + call m(idct_16x16_internal_8bpc).main_fast + punpcklwd m21, m23, m23 ; 2 + punpcklwd m15, m29, m29 ; 14 + punpcklwd m18, m27, m27 ; 10 + punpcklwd m14, m25, m25 ; 6 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova [rsp+mmsize*0], m14 + mova [rsp+mmsize*1], m15 + mova [rsp+mmsize*2], m16 + mova [rsp+mmsize*3], m17 + mova [rsp+mmsize*4], m18 + mova [rsp+mmsize*5], m19 + mova [rsp+mmsize*6], m20 + mova [rsp+mmsize*7], m21 + mova m21, [cq+64*15] + mova m14, [cq+64* 8] + mova m17, [cq+64*11] + mova m18, [cq+64*12] + mova m19, [cq+64*13] + mova m16, [cq+64*10] + mova m15, [cq+64* 9] + mova m20, [cq+64*14] + REPX {punpckhwd x, x}, m22, m21, m14, m29, m26, m17, m18, m25, \ + m24, m19, m16, m27, m28, m15, m20, m23 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf + + pxor m12, m12 + mov r3d, 32*7 +.full_zero_loop: + REPX {mova [cq+r3*8+64*x], m12}, 0, 1, 2, 3 + sub r3d, 32 + jge .full_zero_loop + + jmp .pass2_end +.fast: + mova ym0, [cq+128*0] + mova ym2, [cq+128*4] + movshdup m8, [o(permB)] + mova ym1, [cq+128*2] + mova ym3, [cq+128*6] + mova ym4, [cq+128*1] + mova ym5, [cq+128*3] + mova ym6, [cq+128*5] + mova ym7, [cq+128*7] + vpermt2q m0, m8, m2 ; 0 4 + vpermt2q m1, m8, m3 ; 2 6 + vpermt2q m4, m8, m5 ; 1 3 + vpermt2q m7, m8, m6 ; 7 5 + call m(idct_8x8_internal_10bpc).main_fast + call m(idct_16x8_internal_10bpc).main_fast + vpbroadcastd m11, [o(pd_2)] + call m(idct_8x16_internal_10bpc).main_end2 + mova m8, [o(idct8x32p)] + packssdw m0, m4 + packssdw m1, m5 + packssdw m2, m6 + packssdw m3, m7 + mova m6, [dup16_perm] + vpermb m0, m8, m0 + vpermb m2, m8, m2 + vprold m8, 16 + vpermb m1, m8, m1 + vpermb m3, m8, m3 + punpckldq m4, m0, m2 + punpckhdq m0, m2 + punpckldq m2, m1, m3 + punpckhdq m1, m3 + punpckldq m21, m4, m2 + punpckhdq m14, m4, m2 + punpckldq m18, m0, m1 + punpckhdq m15, m0, m1 + vpord m7, m6, [o(pb_32)] {1to16} + vpermb m22, m7, m21 ; 1 + pmovzxwd m9, ym21 ; 0 + vpermb m8, m6, m18 ; 4 + vpermb m24, m7, m18 ; 5 + vpermb m21, m6, m14 ; 2 + vpermb m23, m7, m14 ; 3 + vpermb m14, m6, m15 ; 6 + vpermb m25, m7, m15 ; 7 + lea r5, [o_base_8bpc] + pslld m9, 16 + + pxor m7, m7 + REPX {mova x, m7}, m1, m18, m15, m26, m27, m28, m29 + + call m(idct_16x16_internal_8bpc).main_fast2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + mova [rsp+mmsize*0], m14 + mova [rsp+mmsize*1], m15 + mova [rsp+mmsize*2], m16 + mova [rsp+mmsize*3], m17 + mova [rsp+mmsize*4], m18 + mova [rsp+mmsize*5], m19 + mova [rsp+mmsize*6], m20 + mova [rsp+mmsize*7], m21 + + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf_fast + + pxor m12, m12 + REPX {mova [cq+128*x], ym12}, 0, 1, 2, 3, 4, 5, 6, 7 +.pass2_end: + movshdup m30, [permC] + vpbroadcastd m11, [pw_2048] + vpbroadcastd m13, [pixel_10bpc_max] + lea r6, [strideq*3] + psrlq m31, m30, 8 + vpermq m8, m30, m0 + vpermq m9, m31, m1 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m2 + vpermq m9, m31, m3 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m4 + vpermq m9, m31, m5 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m6 + vpermq m9, m31, m7 + call m(idct_16x8_internal_10bpc).write_16x4 + + mova m1, [rsp+mmsize*0] + mova m2, [rsp+mmsize*1] + mova m3, [rsp+mmsize*2] + mova m4, [rsp+mmsize*3] + mova m5, [rsp+mmsize*4] + mova m6, [rsp+mmsize*5] + mova m7, [rsp+mmsize*6] + mova m8, [rsp+mmsize*7] + + paddsw m0, m1, m21 + psubsw m21, m1, m21 + paddsw m1, m2, m20 + psubsw m20, m2, m20 + paddsw m2, m3, m19 + psubsw m19, m3, m19 + paddsw m3, m4, m18 + psubsw m18, m4, m18 + paddsw m4, m5, m17 + psubsw m17, m5, m17 + paddsw m5, m6, m16 + psubsw m16, m6, m16 + paddsw m6, m7, m15 + psubsw m15, m7, m15 + paddsw m7, m8, m14 + psubsw m14, m8, m14 + + vpermq m8, m30, m0 + vpermq m9, m31, m1 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m2 + vpermq m9, m31, m3 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m4 + vpermq m9, m31, m5 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m6 + vpermq m9, m31, m7 + call m(idct_16x8_internal_10bpc).write_16x4 + + vpermq m8, m30, m14 + vpermq m9, m31, m15 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m16 + vpermq m9, m31, m17 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m18 + vpermq m9, m31, m19 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m20 + vpermq m9, m31, m21 + call m(idct_16x8_internal_10bpc).write_16x4 + + vpermq m8, m30, m22 + vpermq m9, m31, m23 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m24 + vpermq m9, m31, m25 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m26 + vpermq m9, m31, m27 + call m(idct_16x8_internal_10bpc).write_16x4 + vpermq m8, m30, m28 + vpermq m9, m31, m29 + call m(idct_16x8_internal_10bpc).write_16x4 + RET +.pass1: + mova m0, [cq+128* 0] + mova m1, [cq+128* 2] + mova m2, [cq+128* 4] + mova m3, [cq+128* 6] + mova m4, [cq+128* 8] + mova m5, [cq+128*10] + mova m6, [cq+128*12] + mova m7, [cq+128*14] + call m(idct_8x16_internal_10bpc).main + mova m16, [cq+128* 1] + mova m17, [cq+128* 3] + mova m18, [cq+128* 5] + mova m19, [cq+128* 7] + mova m20, [cq+128* 9] + mova m21, [cq+128*11] + mova m22, [cq+128*13] + mova m23, [cq+128*15] + call m(idct_16x16_internal_10bpc).main + call m(idct_16x16_internal_10bpc).main_end + jmp m(idct_16x16_internal_10bpc).main_end3 +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 64 + add r6d, 640 + sar r6d, 10 + jmp m(inv_txfm_add_dct_dct_16x8_10bpc).dconly2 + +cglobal inv_txfm_add_dct_dct_32x64_10bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 4, 7, 32, -64*40, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 136 + jl .fast + add cq, 64 + cmp eobd, 543 + jge .full + call .pass1_fast ; bottomright 16x16 zero + jmp .lefthalf +.full: + call .pass1 + mov r3d, 16*28 +.lefthalf: + mova [cq+128* 0], m27 + mova [cq+128* 1], m14 + mova [cq+128* 2], m28 + mova [cq+128* 3], m15 + mova [cq+128* 4], m22 + mova [cq+128* 5], m23 + mova [cq+128* 6], m24 + mova [cq+128* 7], m25 + mova [cq+128* 8], m0 + mova [cq+128* 9], m26 + mova [cq+128*10], m20 + mova [cq+128*11], m21 + mova [cq+128*12], m18 + mova [cq+128*13], m16 + mova [cq+128*14], m17 + mova [cq+128*15], m3 + sub cq, 64 + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + call .pass1 + call .pass2_start + + pxor m31, m31 +.right_zero_loop: + REPX {mova [cq+r3*8+64+128*x], m31}, 0, 1, 2, 3 + sub r3d, 16*4 + jge .right_zero_loop + mov r3d, 16*28 + jmp .left_zero_loop +.pass2_start: + vpbroadcastd m10, [o(pd_2048)] + lea r5, [o_base_8bpc] + + lea r4, [rsp+gprsize] + mova m1, [cq+128*15+64] + mova m2, [cq+128* 8+64] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, m21 + mova m1, [cq+128*12+64] + mova m2, [cq+128*11+64] + mova m3, m18 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, m20 + mova m1, [cq+128*13+64] + mova m2, [cq+128*10+64] + mova m3, m16 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, m26 + mova m1, [cq+128*14+64] + mova m2, [cq+128* 9+64] + mova m3, m17 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + + mova m0, m27 + mova m1, m28 + mova m2, [cq+128* 0+64] + mova m3, [cq+128* 2+64] + mova m16, [cq+128* 1+64] + mova m17, [cq+128* 3+64] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + mova m26, [cq+128* 4+64] + mova m27, [cq+128* 5+64] + mova m28, [cq+128* 6+64] + mova m29, [cq+128* 7+64] + mova [rsp+64*32+gprsize], m14 + mova [rsp+64*33+gprsize], m15 + mova [rsp+64*34+gprsize], m16 + mova [rsp+64*35+gprsize], m17 + mova [rsp+64*36+gprsize], m18 + mova [rsp+64*37+gprsize], m19 + mova [rsp+64*38+gprsize], m20 + mova [rsp+64*39+gprsize], m21 + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast +.fast: ; topleft 16x16 nonzero + cmp eobd, 36 + jl .fast2 + call .pass1_fast + vpbroadcastd m10, [o(pd_2048)] + call .pass2_fast_start + jmp .end +.fast2: ; topleft 8x8 nonzero + movshdup m7, [o(permB)] + mova ym0, [cq+128*0] + mova ym1, [cq+128*4] + mova ym4, [cq+128*2] + mova ym5, [cq+128*6] + mova ym16, [cq+128*1] + mova ym2, [cq+128*5] + mova ym3, [cq+128*3] + mova ym17, [cq+128*7] + mov r3d, 16*4 + vpermq m0, m7, m0 ; 0 0 + vpermq m1, m7, m1 ; 4 4 + vpermt2q m4, m7, m5 ; 2 6 + vpermt2q m16, m7, m2 ; 1 5 + vpermt2q m17, m7, m3 ; 7 3 + REPX {pmulld x, m12}, m0, m1, m4, m16, m17 + REPX {paddd x, m13}, m0, m1, m4, m16, m17 + REPX {psrad x, 12 }, m0, m1, m4, m16, m17 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast2 + vpbroadcastd m11, [o(pd_1)] + call m(idct_16x16_internal_10bpc).main_end2 + + call m(inv_txfm_add_dct_dct_32x8_10bpc).transpose_8x32 + punpcklqdq m27, m0, m2 ; 0 + punpckhqdq m0, m2 ; 1 + punpcklqdq m22, m3, m4 ; 2 + punpckhqdq m26, m3, m4 ; 3 + punpcklqdq m14, m5, m7 ; 4 + punpckhqdq m20, m5, m7 ; 5 + punpcklqdq m23, m6, m8 ; 6 + punpckhqdq m21, m6, m8 ; 7 + + mova m10, m13 + call .pass2_fast2_start +.end: + + pxor m31, m31 + +.left_zero_loop: + REPX {mova [cq+r3*8+128*x], m31}, 0, 1, 2, 3 + sub r3d, 16*4 + jge .left_zero_loop + + call .pass2_end + RET +.pass2_end: + DEFINE_ARGS dst, stride, _, dst2, stride32, stklo, stkhi + vpbroadcastd m30, [pixel_10bpc_max] + vpbroadcastd m13, [pw_2048] + + mov stride32q, strideq + shl stride32q, 5 + lea stkhiq, [rsp+31*mmsize+gprsize] + lea dst2q, [dstq+stride32q] + lea stkloq, [rsp+gprsize] + sub dst2q, strideq ; dst31 + + paddsw m8, m0, m29 ; t0[idct32] + psubsw m9, m0, m29 ; t31[idct32] + call .end_sumsub_write + paddsw m8, m1, m28 ; t1[idct32] + psubsw m9, m1, m28 ; t30[idct32] + call .end_sumsub_write + paddsw m8, m2, m27 ; t2[idct32] + psubsw m9, m2, m27 ; t29[idct32] + call .end_sumsub_write + paddsw m8, m3, m26 ; t3[idct32] + psubsw m9, m3, m26 ; t28[idct32] + call .end_sumsub_write + paddsw m8, m4, m25 ; t4[idct32] + psubsw m9, m4, m25 ; t27[idct32] + call .end_sumsub_write + paddsw m8, m5, m24 ; t5[idct32] + psubsw m9, m5, m24 ; t26[idct32] + call .end_sumsub_write + paddsw m8, m6, m23 ; t6[idct32] + psubsw m9, m6, m23 ; t25[idct32] + call .end_sumsub_write + paddsw m8, m7, m22 ; t7[idct32] + psubsw m9, m7, m22 ; t24[idct32] + call .end_sumsub_write + mova m0, [rsp+64*32+gprsize] + mova m1, [rsp+64*33+gprsize] + mova m2, [rsp+64*34+gprsize] + mova m3, [rsp+64*35+gprsize] + mova m4, [rsp+64*36+gprsize] + mova m5, [rsp+64*37+gprsize] + mova m6, [rsp+64*38+gprsize] + mova m7, [rsp+64*39+gprsize] + paddsw m8, m0, m21 ; t8[idct32] + psubsw m9, m0, m21 ; t23[idct32] + call .end_sumsub_write + paddsw m8, m1, m20 ; t9[idct32] + psubsw m9, m1, m20 ; t22[idct32] + call .end_sumsub_write + paddsw m8, m2, m19 ; t10[idct32] + psubsw m9, m2, m19 ; t21[idct32] + call .end_sumsub_write + paddsw m8, m3, m18 ; t11[idct32] + psubsw m9, m3, m18 ; t20[idct32] + call .end_sumsub_write + paddsw m8, m4, m17 ; t12[idct32] + psubsw m9, m4, m17 ; t19[idct32] + call .end_sumsub_write + paddsw m8, m5, m16 ; t13[idct32] + psubsw m9, m5, m16 ; t18[idct32] + call .end_sumsub_write + paddsw m8, m6, m15 ; t14[idct32] + psubsw m9, m6, m15 ; t17[idct32] + call .end_sumsub_write + paddsw m8, m7, m14 ; t15[idct32] + psubsw m9, m7, m14 ; t16[idct32] + ; fall-through +.end_sumsub_write: + mova m10, [stkhiq] ; t63-n + mova m12, [stkloq] ; t32+n + psubsw m11, m8, m10 ; out63-n + paddsw m8, m10 ; out0 +n + psubsw m10, m9, m12 ; out32+n + paddsw m9, m12 ; out32-n + REPX {pmulhrsw x, m13}, m11, m8, m10, m9 + paddw m8, [dstq] + paddw m9, [dst2q] + paddw m10, [dstq+stride32q] + paddw m11, [dst2q+stride32q] + REPX {pminsw x, m30}, m11, m8, m10, m9 + REPX {pmaxsw x, m31}, m11, m8, m10, m9 + mova [dstq ], m8 + mova [dst2q ], m9 + mova [dstq +stride32q], m10 + mova [dst2q+stride32q], m11 + add stkloq, mmsize + sub stkhiq, mmsize + add dstq, strideq + sub dst2q, strideq + ret +.pass2_fast_start: + lea r5, [o_base_8bpc] + lea r4, [rsp+gprsize] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m21 + mova m3, m18 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m20 + mova m3, m16 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m26 + mova m3, m17 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + + mova m0, m27 + mova m1, m28 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast2 + mova [rsp+64*32+gprsize], m14 + mova [rsp+64*33+gprsize], m15 + mova [rsp+64*34+gprsize], m16 + mova [rsp+64*35+gprsize], m17 + mova [rsp+64*36+gprsize], m18 + mova [rsp+64*37+gprsize], m19 + mova [rsp+64*38+gprsize], m20 + mova [rsp+64*39+gprsize], m21 + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast2 +.pass2_fast2_start: + lea r5, [o_base_8bpc] + lea r4, [rsp+gprsize] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast2 + mova m0, m21 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast2 + mova m0, m20 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast2 + mova m0, m26 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast2 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + + mova m0, m27 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast3 + mova [rsp+64*32+gprsize], m14 + mova [rsp+64*33+gprsize], m15 + mova [rsp+64*34+gprsize], m16 + mova [rsp+64*35+gprsize], m17 + mova [rsp+64*36+gprsize], m18 + mova [rsp+64*37+gprsize], m19 + mova [rsp+64*38+gprsize], m20 + mova [rsp+64*39+gprsize], m21 + jmp m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast3 +.dconly: + DEFINE_ARGS dst, stride, c, eob + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_32x16_10bpc).dconly3 +.pass1_fast: + pmulld m0, m12, [cq+128* 0] + pmulld m1, m12, [cq+128* 4] + pmulld m2, m12, [cq+128* 8] + pmulld m3, m12, [cq+128*12] + mov r3d, 16*12 + call m(idct_8x16_internal_10bpc).main_fast_rect2 + pmulld m16, m12, [cq+128* 2] + pmulld m17, m12, [cq+128* 6] + pmulld m18, m12, [cq+128*10] + pmulld m19, m12, [cq+128*14] + call m(idct_16x16_internal_10bpc).main_fast_rect2 + call .pass1_load_spill + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast_rect2 + jmp .pass1_end +.pass1: + pmulld m0, m12, [cq+128* 0] + pmulld m1, m12, [cq+128* 4] + pmulld m2, m12, [cq+128* 8] + pmulld m3, m12, [cq+128*12] + pmulld m4, m12, [cq+128*16] + pmulld m5, m12, [cq+128*20] + pmulld m6, m12, [cq+128*24] + pmulld m7, m12, [cq+128*28] + call m(idct_8x16_internal_10bpc).main_rect2 + pmulld m16, m12, [cq+128* 2] + pmulld m17, m12, [cq+128* 6] + pmulld m18, m12, [cq+128*10] + pmulld m19, m12, [cq+128*14] + pmulld m20, m12, [cq+128*18] + pmulld m21, m12, [cq+128*22] + pmulld m22, m12, [cq+128*26] + pmulld m23, m12, [cq+128*30] + call m(idct_16x16_internal_10bpc).main_rect2 + call .pass1_load_spill + pmulld m16, m12, [cq+128*17] + pmulld m17, m12, [cq+128*19] + pmulld m18, m12, [cq+128*21] + pmulld m19, m12, [cq+128*23] + pmulld m20, m12, [cq+128*25] + pmulld m21, m12, [cq+128*27] + pmulld m22, m12, [cq+128*29] + pmulld m23, m12, [cq+128*31] + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_rect2 +.pass1_end: + vpbroadcastd m11, [o(pd_1)] + lea r4, [cq+128*8] + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct32_pass1_end + punpcklqdq m27, m0, m20 ; 0 + punpckhqdq m0, m20 ; 1 + punpcklqdq m24, m5, m16 ; 10 + punpckhqdq m16, m5, m16 ; 11 + punpcklqdq m23, m3, m21 ; 6 + punpckhqdq m21, m3, m21 ; 7 + punpcklqdq m25, m7, m8 ; 14 + punpckhqdq m3, m7, m8 ; 15 + punpcklqdq m22, m15, m4 ; 2 + punpckhqdq m26, m15, m4 ; 3 + punpcklqdq m15, m6, m17 ; 12 + punpckhqdq m17, m6, m17 ; 13 + punpcklqdq m28, m14, m18 ; 8 + punpckhqdq m18, m14, m18 ; 9 + punpcklqdq m14, m2, m1 ; 4 + punpckhqdq m20, m2, m1 ; 5 + ret +.pass1_load_spill: + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + mova [cq+128* 0], m0 + pmulld m0, m12, [cq+128* 1] + mova [cq+128* 1], m1 + mova [cq+128* 2], m2 + pmulld m1, m12, [cq+128* 3] + pmulld m2, m12, [cq+128* 5] + mova [cq+128* 3], m3 + mova [cq+128* 4], m4 + pmulld m3, m12, [cq+128* 7] + pmulld m4, m12, [cq+128* 9] + mova [cq+128* 5], m5 + mova [cq+128* 6], m6 + mova [cq+128* 7], m7 + pmulld m5, m12, [cq+128*11] + pmulld m6, m12, [cq+128*13] + pmulld m7, m12, [cq+128*15] + mova [cq+128* 8], m23 + mova [cq+128* 9], m22 + mova [cq+128*10], m21 + mova [cq+128*11], m20 + mova [cq+128*12], m19 + mova [cq+128*13], m18 + mova [cq+128*14], m17 + mova [cq+128*15], m16 + ret + +cglobal inv_txfm_add_dct_dct_64x16_10bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + + PROLOGUE 4, 7, 32, -64*32, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 36 + jl .fast ; 8x8 + cmp eobd, 151 + jge .full ; 16x16 + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64] + mova m0, [cq+64* 1] + mova m3, [cq+64*15] + call .main_part1_fast + mova m0, [cq+64* 7] + mova m3, [cq+64* 9] + call .main_part1_fast + mova m0, [cq+64* 5] + mova m3, [cq+64*11] + call .main_part1_fast + mova m0, [cq+64* 3] + mova m3, [cq+64*13] + call .main_part1_fast + call .main_part2 + mova m0, [cq+64* 0] + mova m1, [cq+64* 8] + mova m16, [cq+64* 4] + mova m17, [cq+64*12] + call m(idct_8x16_internal_10bpc).main_fast2 + call m(idct_16x16_internal_10bpc).main_fast2 + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + call .pass1_load_spill + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast2 + mov r6d, 12*8 + jmp .idct64_end +.full: + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64] + mova m0, [cq+64* 1] + mova m1, [cq+64*31] + mova m2, [cq+64*17] + mova m3, [cq+64*15] + call .main_part1 + mova m0, [cq+64* 7] + mova m1, [cq+64*25] + mova m2, [cq+64*23] + mova m3, [cq+64* 9] + call .main_part1 + mova m0, [cq+64* 5] + mova m1, [cq+64*27] + mova m2, [cq+64*21] + mova m3, [cq+64*11] + call .main_part1 + mova m0, [cq+64* 3] + mova m1, [cq+64*29] + mova m2, [cq+64*19] + mova m3, [cq+64*13] + call .main_part1 + call .main_part2 + mova m0, [cq+64* 0] + mova m1, [cq+64* 8] + mova m2, [cq+64*16] + mova m3, [cq+64*24] + mova m16, [cq+64* 4] + mova m17, [cq+64*12] + mova m18, [cq+64*20] + mova m19, [cq+64*28] + call m(idct_8x16_internal_10bpc).main_fast + call m(idct_16x16_internal_10bpc).main_fast + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + call .pass1_load_spill + mova m4, [cq+64*18] + mova m5, [cq+64*22] + mova m6, [cq+64*26] + mova m7, [cq+64*30] + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast + mov r6d, 28*8 + jmp .idct64_end +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 16 +.dconly1: + add r6d, 640 + sar r6d, 10 +.dconly2: + vpbroadcastd m3, [o(dconly_10bpc)] + imul r6d, 181 + add r6d, 2176 + sar r6d, 12 + vpbroadcastw m2, r6d + paddsw m2, m3 +.dconly_loop: + paddsw m0, m2, [dstq+64*0] + paddsw m1, m2, [dstq+64*1] + psubusw m0, m3 + psubusw m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + dec r3d + jg .dconly_loop + ret +.pass1_load_spill: + mova [cq+64* 0], m0 + mova m0, [cq+64* 2] + mova [cq+64* 2], m1 + mova m1, [cq+64* 6] + mova [cq+64* 4], m2 + mova [cq+64* 6], m3 + mova m2, [cq+64*10] + mova m3, [cq+64*14] + mova [cq+64* 8], m4 + mova [cq+64*10], m5 + mova [cq+64*12], m6 + mova [cq+64*14], m7 + mova [cq+64* 1], m23 + mova [cq+64* 3], m22 + mova [cq+64* 5], m21 + mova [cq+64* 7], m20 + mova [cq+64* 9], m19 + mova [cq+64*11], m18 + mova [cq+64*13], m17 + mova [cq+64*15], m16 + ret +ALIGN function_align +.main_part1_fast_rect2: + REPX {paddd x, m13}, m0, m3 + REPX {psrad x, 12 }, m0, m3 +.main_part1_fast: + pmulld m7, m0, [r4+4*0]{bcstd} ; t63a + pmulld m0, [r4+4*1]{bcstd} ; t32a + pmulld m4, m3, [r4+4*6]{bcstd} ; t60a + pmulld m3, [r4+4*7]{bcstd} ; t35a + vpbroadcastd m10, [r4+4*8] + vpbroadcastd m11, [r4+4*9] + REPX {paddd x, m13}, m7, m0, m4, m3 + REPX {psrad x, 12 }, m7, m0, m4, m3 + mova m8, m0 + mova m1, m7 + mova m6, m3 + mova m2, m4 + jmp .main_part1b +.main_part1_rect2: + REPX {paddd x, m13}, m0, m1, m2, m3 + REPX {psrad x, 12 }, m0, m1, m2, m3 +.main_part1: ; idct64 steps 1-5 + ; in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + ; in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + ; in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + ; in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + pmulld m7, m0, [r4+4*0]{bcstd} ; t63a + pmulld m0, [r4+4*1]{bcstd} ; t32a + pmulld m6, m1, [r4+4*2]{bcstd} ; t62a + pmulld m1, [r4+4*3]{bcstd} ; t33a + pmulld m5, m2, [r4+4*4]{bcstd} ; t61a + pmulld m2, [r4+4*5]{bcstd} ; t34a + pmulld m4, m3, [r4+4*6]{bcstd} ; t60a + pmulld m3, [r4+4*7]{bcstd} ; t35a + vpbroadcastd m10, [r4+4*8] + vpbroadcastd m11, [r4+4*9] + REPX {paddd x, m13}, m7, m0, m6, m1, m5, m2, m4, m3 + REPX {psrad x, 12 }, m0, m1, m7, m6, m2, m3, m5, m4 + psubd m8, m0, m1 ; t33 + paddd m0, m1 ; t32 + psubd m1, m7, m6 ; t62 + paddd m7, m6 ; t63 + psubd m6, m3, m2 ; t34 + paddd m3, m2 ; t35 + psubd m2, m4, m5 ; t61 + paddd m4, m5 ; t60 +.main_part1b: + REPX {pmaxsd x, m14}, m8, m1, m6, m2 + REPX {pminsd x, m15}, m8, m1, m6, m2 + ITX_MULSUB_2D 1, 8, 5, 9, _, 13, 10, 11 ; t33a, t62a + ITX_MULSUB_2D 2, 6, 5, 9, _, 13, 10, 11, 2 ; t61a, t34a + REPX {pmaxsd x, m14}, m0, m3, m7, m4 + REPX {pminsd x, m15}, m0, m3, m7, m4 + vpbroadcastd m10, [r4+4*10] + vpbroadcastd m11, [r4+4*11] + psubd m5, m0, m3 ; t35a + paddd m0, m3 ; t32a + psubd m3, m7, m4 ; t60a + paddd m7, m4 ; t63a + psubd m4, m1, m6 ; t34 + paddd m1, m6 ; t33 + psubd m6, m8, m2 ; t61 + paddd m8, m2 ; t62 + REPX {pmaxsd x, m14}, m5, m3, m4, m6 + REPX {pminsd x, m15}, m5, m3, m4, m6 + ITX_MULSUB_2D 3, 5, 2, 9, _, 13, 10, 11 ; t35, t60 + ITX_MULSUB_2D 6, 4, 2, 9, _, 13, 10, 11 ; t34a, t61a + REPX {pmaxsd x, m14}, m0, m7, m1, m8 + REPX {pminsd x, m15}, m0, m7, m1, m8 + add r4, 4*12 + mova [r6-64*4], m0 + mova [r6+64*3], m7 + mova [r6-64*3], m1 + mova [r6+64*2], m8 + mova [r6-64*2], m6 + mova [r6+64*1], m4 + mova [r6-64*1], m3 + mova [r6+64*0], m5 + add r6, 64*8 + ret +.main_part2: ; idct64 steps 6-9 + lea r4, [r6+64*3] + sub r6, 64*4 + vpbroadcastd m10, [pd_1567] + vpbroadcastd m11, [pd_3784] +.main_part2_loop: + mova m0, [r6-64*32] ; t32a + mova m1, [r4-64*24] ; t39a + mova m2, [r4-64*32] ; t63a + mova m3, [r6-64*24] ; t56a + mova m4, [r6-64*16] ; t40a + mova m5, [r4-64* 8] ; t47a + mova m6, [r4-64*16] ; t55a + mova m7, [r6-64* 8] ; t48a + psubd m8, m0, m1 ; t39 + paddd m0, m1 ; t32 + psubd m1, m2, m3 ; t56 + paddd m2, m3 ; t63 + psubd m3, m5, m4 ; t40 + paddd m5, m4 ; t47 + psubd m4, m7, m6 ; t55 + paddd m7, m6 ; t48 + REPX {pmaxsd x, m14}, m8, m1, m3, m4 + REPX {pminsd x, m15}, m8, m1, m3, m4 + ITX_MULSUB_2D 1, 8, 6, 9, _, 13, 10, 11 ; t39a, t56a + ITX_MULSUB_2D 4, 3, 6, 9, _, 13, 10, 11, 2 ; t55a, t40a + REPX {pmaxsd x, m14}, m0, m2, m5, m7 + REPX {pminsd x, m15}, m0, m5, m2, m7 + psubd m6, m2, m7 ; t48a + paddd m2, m7 ; t63a + psubd m7, m0, m5 ; t47a + paddd m0, m5 ; t32a + psubd m5, m8, m4 ; t55 + paddd m8, m4 ; t56 + psubd m4, m1, m3 ; t40 + paddd m1, m3 ; t39 + REPX {pmaxsd x, m14}, m6, m7, m5, m4 + REPX {pminsd x, m15}, m6, m7, m5, m4 + REPX {pmulld x, m12}, m6, m7, m5, m4 + REPX {pmaxsd x, m14}, m2, m0, m8, m1 + REPX {pminsd x, m15}, m2, m0, m8, m1 + paddd m6, m13 + paddd m5, m13 + psubd m3, m6, m7 ; t47 + paddd m6, m7 ; t48 + psubd m7, m5, m4 ; t40a + paddd m5, m4 ; t55a + REPX {psrad x, 12}, m3, m6, m7, m5 + mova [r4-64* 8], m2 + mova [r6-64*32], m0 + mova [r6-64* 8], m8 + mova [r4-64*32], m1 + mova [r4-64*24], m3 + mova [r6-64*16], m6 + mova [r6-64*24], m7 + mova [r4-64*16], m5 + add r6, 64 + sub r4, 64 + cmp r6, r4 + jl .main_part2_loop + ret +.idct64_main_end: +%macro IDCT64_PASS1_END 9 + mova m%5, [%9+%1*128] ; t0+n [idct32] + idct64 rounding + psubd m%6, m%5, m%2 ; out31-n [idct32] = t31-n [idct64] + paddd m%5, m%2 ; out0+n [idct32] = t0+n [idct64] + REPX {pmaxsd x, m14}, m%6, m%5 + REPX {pminsd x, m15}, m%6, m%5 + REPX {paddd x, m11}, m%6, m%5 + mova m%2, [r3+%3*64] ; t32+n [idct64] + mova m%7, [r3+%4*64] ; t63-n [idct64] + psubd m%8, m%5, m%7 ; out63-n + paddd m%5, m%7 ; out0+n + psubd m%7, m%6, m%2 ; out32+n + paddd m%6, m%2 ; out31-n + REPX {vpsravd x, m11}, m%8, m%5, m%7, m%6 +%endmacro + +%macro IDCT64_PASS1_ENDx4 1 +%assign %%m1 %1 ; t32+n +%assign %%m2 (7-%1) ; t39-n +%assign %%m3 (8+%1) ; t40+n +%assign %%m4 (15-%1) ; t47-n +%assign %%m5 (16+%1) ; t48+n +%assign %%m6 (23-%1) ; t55-n +%assign %%m7 (24+%1) ; t56+n +%assign %%m8 (31-%1) ; t63-n + +%assign %%r1 %1 ; t16+n +%assign %%r2 (7-%1) ; t23-n +%assign %%r3 (16+%1) ; t24-n +%assign %%r4 (23-%1) ; t31-n + +%assign %%c1 (%1) ; t0/8+n +%assign %%c2 (7-%1) ; t7/15-n + + IDCT64_PASS1_END %%c1, %%r4, %%m1, %%m8, 24, 25, 26, 27, cq ; out0/31/32/63 + IDCT64_PASS1_END %%c1, %%r1, %%m4, %%m5, 28, 29, 30, 31, r4 ; out15/16/47/48 + packssdw m %+ %%r1, m24, m29 + packssdw m %+ %%r4, m28, m25 + packssdw m26, m31 + packssdw m30, m27 + mova [r3+%%m5*mmsize], m26 + mova [r3+%%m8*mmsize], m30 + IDCT64_PASS1_END %%c2, %%r3, %%m2, %%m7, 24, 25, 26, 27, cq ; out7/24/39/56 + IDCT64_PASS1_END %%c2, %%r2, %%m3, %%m6, 28, 29, 30, 31, r4 ; out8/23/40/55 + packssdw m %+ %%r2, m24, m29 + packssdw m %+ %%r3, m28, m25 + packssdw m26, m31 + packssdw m30, m27 + mova [r3+%%m6*mmsize], m26 + mova [r3+%%m7*mmsize], m30 +%endmacro + IDCT64_PASS1_ENDx4 0 + IDCT64_PASS1_ENDx4 1 + IDCT64_PASS1_ENDx4 2 + IDCT64_PASS1_ENDx4 3 + ret +.idct64_end: + vpbroadcastd m11, [o(pd_2)] + lea r4, [cq+64] + mov r3, rsp + lea r5, [o_base_8bpc] + call .idct64_main_end + + pxor m12, m12 +.zero_loop: + REPX {mova [cq+r6*8+64*x], m12}, 0, 1, 2, 3 + sub r6d, 8*4 + jge .zero_loop + + lea r3, [strideq*3] + mov r4, dstq + call .pass2 + mova m0, [rsp+16*mmsize] + mova m1, [rsp+17*mmsize] + mova m2, [rsp+18*mmsize] + mova m3, [rsp+19*mmsize] + mova m4, [rsp+20*mmsize] + mova m5, [rsp+21*mmsize] + mova m6, [rsp+22*mmsize] + mova m7, [rsp+23*mmsize] + mova m16, [rsp+24*mmsize] + mova m17, [rsp+25*mmsize] + mova m18, [rsp+26*mmsize] + mova m19, [rsp+27*mmsize] + mova m20, [rsp+28*mmsize] + mova m21, [rsp+29*mmsize] + mova m22, [rsp+30*mmsize] + mova m23, [rsp+31*mmsize] + lea dstq, [r4+64] + call .pass2 + RET +.pass2: + psrlq m12, [permC], 24 ; 0 2 8 10 1 3 9 11 + psrlq m13, m12, 32 ; 4 6 12 14 5 7 13 15 + call m(inv_txfm_add_dct_dct_32x16_10bpc).transpose_16x32 + + punpckhqdq m19, m5, m16 ; 11 + punpcklqdq m5, m16 ; 10 + punpckhqdq m16, m2, m1 ; 5 + punpcklqdq m2, m1 ; 4 + punpcklqdq m1, m15, m4 ; 2 + punpckhqdq m15, m4 ; 3 + punpcklqdq m4, m14, m18 ; 8 + punpckhqdq m18, m14, m18 ; 9 + punpckhqdq m14, m0, m20 ; 1 + punpcklqdq m0, m20 ; 0 + punpckhqdq m20, m6, m17 ; 13 + punpcklqdq m6, m17 ; 12 + punpckhqdq m17, m3, m21 ; 7 + punpcklqdq m3, m21 ; 6 + punpckhqdq m21, m7, m8 ; 15 + punpcklqdq m7, m8 ; 14 + + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf +.write: + vpbroadcastd m11, [pw_2048] + pxor m12, m12 + vpbroadcastd m13, [pixel_10bpc_max] + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x8 + pmulhrsw m0, m11, m14 + pmulhrsw m1, m11, m15 + pmulhrsw m2, m11, m16 + pmulhrsw m3, m11, m17 + call m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 + pmulhrsw m0, m11, m18 + pmulhrsw m1, m11, m19 + pmulhrsw m2, m11, m20 + pmulhrsw m3, m11, m21 + jmp m(inv_txfm_add_dct_dct_32x8_10bpc).write_32x4 +.fast: ; 8x8 packed + movshdup m7, [o(permB)] + mova ym0, [cq+64*1] + mova ym2, [cq+64*5] + mova ym3, [cq+64*3] + mova ym1, [cq+64*7] + vpermt2q m0, m7, m2 ; 1 5 + vpermt2q m1, m7, m3 ; 7 3 + call .main_oddhalf_packed + mova [rsp+ 0*mmsize], m0 + mova [rsp+ 1*mmsize], m1 + mova [rsp+ 2*mmsize], m2 + mova [rsp+ 3*mmsize], m3 + mova [rsp+ 4*mmsize], m4 + mova [rsp+ 5*mmsize], m5 + mova [rsp+ 6*mmsize], m6 + mova [rsp+ 7*mmsize], m7 + mova [rsp+ 8*mmsize], m16 + mova [rsp+ 9*mmsize], m17 + mova [rsp+10*mmsize], m18 + mova [rsp+11*mmsize], m19 + mova [rsp+12*mmsize], m20 + mova [rsp+13*mmsize], m21 + mova [rsp+14*mmsize], m22 + mova [rsp+15*mmsize], m23 + + movshdup m7, [o(permB)] + mova ym0, [cq+64*0] + mova ym4, [cq+64*4] + mova ym16, [cq+64*2] + mova ym5, [cq+64*6] + vpermt2q m16, m7, m5 ; 2 6 + vpermq m0, m7, m0 ; 0 0 + vpermq m4, m7, m4 ; 4 4 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast3 + ; m0-7,9,16-22 contain un-sumsub'ed dct32 output data + + ; zero input coefs + pxor m12, m12 + REPX {mova [cq+x*64], ym12}, 0, 1, 2, 3, 4, 5, 6, 7 + + vpbroadcastd m11, [o(pd_2)] + call .main_end + lea r3, [strideq*3] + mov r4, dstq + call .pass2_fast + mova m0, m24 + mova m1, m25 + mova m2, m26 + mova m3, m27 + mova m4, m28 + mova m5, m29 + mova m6, m30 + mova m7, m31 + lea dstq, [r4+64] + lea r5, [o_base] + call .pass2_fast + RET +.pass2_fast: + call m(inv_txfm_add_dct_dct_32x8_10bpc).transpose_8x32 + lea r5, [o_base_8bpc] + punpckhqdq m14, m0, m2 ; 1 + punpcklqdq m0, m2 ; 0 + punpcklqdq m1, m3, m4 ; 2 + punpckhqdq m15, m3, m4 ; 3 + punpcklqdq m2, m5, m7 ; 4 + punpckhqdq m16, m5, m7 ; 5 + punpcklqdq m3, m6, m8 ; 6 + punpckhqdq m17, m6, m8 ; 7 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + jmp .write +.main_end: + +%macro IDCT64_PASS1_PACKED_END 7 + psubd m%5, m%1, m%2 ; out31-n [idct32] = t31-n [idct64] + paddd m%1, m%2 ; out0+n [idct32] = t0+n [idct64] + REPX {pmaxsd x, m14}, m%5, m%1 + REPX {pminsd x, m15}, m%5, m%1 + REPX {paddd x, m11}, m%5, m%1 + mova m%2, [rsp+%6*64+gprsize] ; t32+n [idct64] + mova m%3, [rsp+%7*64+gprsize] ; t63-n [idct64] + psubd m%4, m%1, m%3 ; out63-n + paddd m%1, m%3 ; out0+n + psubd m%3, m%5, m%2 ; out32+n + paddd m%2, m%5 ; out31-n + REPX {vpsravd x, m11}, m%4, m%1, m%3, m%2 +%endmacro + + IDCT64_PASS1_PACKED_END 0, 22, 24, 10, 12, 0, 15 ; out0/1,31/30,32/33,63/62 + IDCT64_PASS1_PACKED_END 7, 9, 31, 13, 12, 7, 8 ; out15/14,16/17,47/46,48/49 + packssdw m0, m9 + packssdw m7, m22 + packssdw m24, m13 + packssdw m31, m10 + IDCT64_PASS1_PACKED_END 1, 21, 25, 10, 12, 1, 14 ; out3/2,28/29,35/34,60/61 + IDCT64_PASS1_PACKED_END 6, 16, 30, 13, 12, 6, 9 ; out12/13,19/18,44/45,51/50 + packssdw m1, m16 + packssdw m6, m21 + packssdw m25, m13 + packssdw m30, m10 + IDCT64_PASS1_PACKED_END 2, 20, 26, 10, 12, 2, 13 ; out4/5,27/26,36/37,59/58 + IDCT64_PASS1_PACKED_END 5, 17, 29, 13, 12, 5, 10 ; out11/10,20/21,43/42,52/53 + packssdw m2, m17 + packssdw m5, m20 + packssdw m26, m13 + packssdw m29, m10 + IDCT64_PASS1_PACKED_END 3, 19, 27, 10, 12, 3, 12 ; out7/6,24/25,39/38,56/57 + IDCT64_PASS1_PACKED_END 4, 18, 28, 13, 12, 4, 11 ; out8/9,23/22,40/41,55/54 + packssdw m3, m18 + packssdw m4, m19 + packssdw m27, m13 + packssdw m28, m10 + ret +.main_oddhalf_packed_rect2: + REPX {paddd x, m13}, m0, m1 + REPX {psrad x, 12 }, m0, m1 +.main_oddhalf_packed: + ; m0=in1 in5, m1=in7 in3 + vbroadcasti32x4 m2, [o(pd_101_501)] + vbroadcasti32x4 m3, [o(pd_m700_m301)] + vbroadcasti32x4 m4, [o(pd_4095_4065)] + vbroadcasti32x4 m5, [o(pd_4036_4085)] + pmulld m2, m0 + pmulld m3, m1 + pmulld m0, m4 + pmulld m1, m5 + REPX {paddd x, m13}, m2, m3, m0, m1 + REPX {psrad x, 12 }, m2, m3, m0, m1 + + ; m2=t32a t40a -> t32/33 t40/41, m3=t39a t47a -> t38/39 t46/47 + ; m0=t63a t55a -> t62/63 t54/55, m1=t56a t48a -> t56/57 t48/49 + ; end of step 1-2 + + vbroadcasti32x4 m10, [o(pd_401_1931)] + vbroadcasti32x4 m11, [o(pd_4076_3612)] + mova m4, m0 + mova m5, m2 + ITX_MULSUB_2D 4, 5, 8, 9, _, 13, 10, 11 + vbroadcasti32x4 m10, [o(pd_3166_3920)] + vbroadcasti32x4 m11, [o(pd_2598_1189)] + mova m6, m3 + mova m7, m1 + ITX_MULSUB_2D 7, 6, 8, 9, _, 13, 10, 11, 2 + + ; m4=t33a t41a -> t41/42 t33/34, m5=t63a t54a -> t61/62 t53/54 + ; m6=t38a t46a -> t37/38 t45/46, m7=t57a t49a -> t57/58 t49/50 + ; and from earlier: + ; m0=t63 t55 -> t60/63a t52/55a, m1=t56 t48 -> t56/59a t48/51a + ; m2=t32 t40 -> t32/35a t40/43a, m3=t39 t47 -> t36/39a t44/47a + ; end of step 3-4 + + punpcklqdq m22, m2, m4 ; t32a/33 or t35a/34 + punpcklqdq m21, m3, m6 ; t36a/37 or t39a/38 + punpckhqdq m18, m2, m4 ; t40a/41 or t43a/42 + punpckhqdq m17, m3, m6 ; t44a/45 or t47a/46 + punpckhqdq m6, m1, m7 ; t48a/49 or t51a/50 + punpckhqdq m19, m0, m5 ; t52a/53 or t55a/54 + punpcklqdq m8, m1, m7 ; t56a/57 or t59a/58 + punpcklqdq m23, m0, m5 ; t60a/61 or t63a/62 + mova m0, m22 + mova m7, m21 + mova m3, m18 + mova m16, m17 + mova m5, m6 + mova m4, m19 + mova m2, m8 + mova m1, m23 + ; m0/22/7/21,18/3/17/16,6/5/19/4,2/8/1/23: t32-63[a] + + ; step5 + vpbroadcastd m10, [o(pd_799)] + vpbroadcastd m11, [o(pd_4017)] + ITX_MULSUB_2D 1, 22, 20, 9, _, 13, 10, 11 ; t35/34a, t60/61a + ITX_MULSUB_2D 8, 7, 20, 9, _, 13, 10, 11, 2 ; t59/58a, t36/37a + vpbroadcastd m10, [o(pd_3406)] + vpbroadcastd m11, [o(pd_2276)] + ITX_MULSUB_2D 19, 3, 20, 9, _, 13, 10, 11 ; t43/42a, t52/53a + ITX_MULSUB_2D 5, 17, 20, 9, _, 13, 10, 11, 2 ; t51/50a, t44/45a + ; m0-1/7/21: t32-39[a], m18-19/17-16: t40-47[a] + ; m6-5/3-4: t48-55[a], m2/8/22-23: t56-63[a] + + ; step6 + psubd m20, m0, m21 ; t39/38a + paddd m0, m21 ; t32/33a + psubd m21, m1, m7 ; t36a/37 + paddd m1, m7 ; t35a/34 + REPX {pmaxsd x, m14}, m20, m0, m21, m1 + psubd m7, m16, m18 ; t40/41a + paddd m16, m18 ; t47/46a + REPX {pminsd x, m15}, m20, m0, m21, m1 + psubd m18, m17, m19 ; t43a/42 + paddd m17, m19 ; t44a/45 + REPX {pmaxsd x, m14}, m7, m16, m18, m17 + psubd m19, m6, m4 ; t55/54a + paddd m6, m4 ; t48/49a + REPX {pminsd x, m15}, m7, m16, m18, m17 + psubd m4, m5, m3 ; t52a/53 + paddd m5, m3 ; t51a/50 + REPX {pmaxsd x, m14}, m19, m6, m4, m5 + psubd m3, m23, m2 ; t56/57a + paddd m23, m2 ; t63/62a + REPX {pminsd x, m15}, m19, m6, m4, m5 + psubd m2, m22, m8 ; t59a/58 + paddd m22, m8 ; t60a/61 + REPX {pmaxsd x, m14}, m3, m23, m2, m22 + REPX {pminsd x, m15}, m3, m23, m2, m22 + ; m0-1: t32-35[a], m17-16: t44-47[a], m6-5: t48-51[a], m22-23: t60-63[a] + ; m21-20: t36-39[a], m7/18: t40-43[a], m4/19: t52-55[a], m3-2: t56-59[a] + + ; step7 + vpbroadcastd m10, [o(pd_1567)] + vpbroadcastd m11, [o(pd_3784)] + ITX_MULSUB_2D 2, 21, 8, 9, _, 13, 10, 11 ; t36/37a, t59/58a + ITX_MULSUB_2D 3, 20, 8, 9, _, 13, 10, 11 ; t39a/38, t56a/57 + ITX_MULSUB_2D 19, 7, 8, 9, _, 13, 10, 11, 2 ; t55a/54, t40a/41 + ITX_MULSUB_2D 4, 18, 8, 9, _, 13, 10, 11, 2 ; t52/53a, t43/42a + ; m0-3: t32-39[a], m7,18-16: t40-47[a], m6-4,19: t48-55[a], m20-23: t56-63[a] + + ; step8 + psubd m8, m0, m16 ; t47a/46 + paddd m0, m16 ; t32a/33 + psubd m16, m1, m17 ; t44/45a + paddd m1, m17 ; t35/34a + REPX {pmaxsd x, m14}, m8, m0, m16, m1 + psubd m17, m2, m18 ; t43a/42 + paddd m2, m18 ; t36a/37 + REPX {pminsd x, m15}, m8, m0, m16, m1 + psubd m18, m3, m7 ; t40/41a + paddd m3, m7 ; t39/38a + REPX {pmaxsd x, m14}, m17, m2, m18, m3 + psubd m7, m23, m6 ; t48a/49 + paddd m23, m6 ; t63a/62 + REPX {pminsd x, m15}, m17, m2, m18, m3 + psubd m6, m22, m5 ; t51/50a + paddd m22, m5 ; t60/61a + REPX {pmaxsd x, m14}, m7, m23, m6, m22 + psubd m5, m21, m4 ; t52a/53 + paddd m21, m4 ; t59a/58 + REPX {pminsd x, m15}, m7, m23, m6, m22 + psubd m4, m20, m19 ; t55/54a + paddd m20, m19 ; t56/57a + REPX {pmaxsd x, m14}, m5, m21, m4, m20 + REPX {pminsd x, m15}, m5, m21, m4, m20 + ; m0-3=t32-39[a], m18-16,8: t40-47[a], m7-4=t48-55[a], m20-23=t56-63[a] + + ; step9 + REPX {pmulld x, m12}, m4, m18, m5, m17, m6, m16, m7, m8 + REPX {paddd x, m13}, m4, m5, m6, m7 + paddd m19, m4, m18 ; t55a/54 + psubd m4, m18 ; t40a/41 + paddd m18, m5, m17 ; t52/53a + psubd m5, m17 ; t43/42a + paddd m17, m6, m16 ; t51a/50 + psubd m6, m16 ; t44a/45 + paddd m16, m7, m8 ; t48/49a + psubd m7, m8 ; t47/46a + REPX {psrad x, 12 }, m19, m4, m18, m5, m17, m6, m16, m7 + ; m4-7=t40-47[a], m16-19=t48-55[a] + ret + +cglobal inv_txfm_add_dct_dct_64x32_10bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + + PROLOGUE 4, 8, 32, -64*32, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 136 + jl .fast + add cq, 64 + cmp eobd, 543 + jge .full + call .pass1_fast ; bottomright 16x16 zero + mov r7d, 16*12 + jmp .lefthalf +.full: + call .pass1 + mov r7d, 16*28 +.lefthalf: + mova [cq+128* 0], m0 + mova [cq+128* 1], m1 + mova [cq+128* 2], m2 + mova [cq+128* 3], m3 + mova [cq+128* 4], m14 + mova [cq+128* 5], m15 + mova [cq+128* 6], m16 + mova [cq+128* 7], m17 + mova [cq+128* 8], m22 + mova [cq+128* 9], m23 + mova [cq+128*10], m24 + mova [cq+128*11], m25 + mova [cq+128*12], m26 + mova [cq+128*13], m27 + mova [cq+128*14], m28 + mova [cq+128*15], m29 + sub cq, 64 + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + sub rsp, 16*64 + call .pass1 + add rsp, 16*64 + lea r5, [o_base_8bpc] + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_start + mov r4, dstq + pxor m12, m12 + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_end + lea dstq, [r4+64] + mova m0, [rsp+16*mmsize] + mova m1, [rsp+17*mmsize] + mova m2, [rsp+18*mmsize] + mova m3, [rsp+19*mmsize] + mova m4, [rsp+20*mmsize] + mova m5, [rsp+21*mmsize] + mova m6, [rsp+22*mmsize] + mova m7, [rsp+23*mmsize] + mova m16, [rsp+24*mmsize] + mova m17, [rsp+25*mmsize] + mova m18, [rsp+26*mmsize] + mova m19, [rsp+27*mmsize] + mova m20, [rsp+28*mmsize] + mova m21, [rsp+29*mmsize] + mova m22, [rsp+30*mmsize] + mova m23, [rsp+31*mmsize] + call .transpose + mova [cq+128* 0+64], m0 + mova [cq+128* 1+64], m1 + mova [cq+128* 2+64], m2 + mova [cq+128* 3+64], m3 + mova [cq+128* 4+64], m14 + mova [cq+128* 5+64], m15 + mova [cq+128* 6+64], m16 + mova [cq+128* 7+64], m17 + mova [cq+128* 8+64], m22 + mova [cq+128* 9+64], m23 + mova [cq+128*10+64], m24 + mova [cq+128*11+64], m25 + mova [cq+128*12+64], m26 + mova [cq+128*13+64], m27 + mova [cq+128*14+64], m28 + mova [cq+128*15+64], m29 + mova m0, [rsp+ 0*mmsize] + mova m1, [rsp+ 1*mmsize] + mova m2, [rsp+ 2*mmsize] + mova m3, [rsp+ 3*mmsize] + mova m4, [rsp+ 4*mmsize] + mova m5, [rsp+ 5*mmsize] + mova m6, [rsp+ 6*mmsize] + mova m7, [rsp+ 7*mmsize] + mova m16, [rsp+ 8*mmsize] + mova m17, [rsp+ 9*mmsize] + mova m18, [rsp+10*mmsize] + mova m19, [rsp+11*mmsize] + mova m20, [rsp+12*mmsize] + mova m21, [rsp+13*mmsize] + mova m22, [rsp+14*mmsize] + mova m23, [rsp+15*mmsize] + call .transpose + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_start + pxor m12, m12 +.right_zero_loop: + mova [cq+r7*8+64+128*3], m12 + mova [cq+r7*8+64+128*2], m12 + mova [cq+r7*8+64+128*1], m12 + mova [cq+r7*8+64+128*0], m12 + sub r7d, 16*4 + jge .right_zero_loop + mov r7d, 16*28 + jmp .end +.fast: ; topleft 16x16 nonzero + cmp eobd, 36 + jl .fast2 + call .pass1_fast + lea r5, [o_base_8bpc] + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_fast_start + mov r4, dstq + pxor m12, m12 + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_end + lea dstq, [r4+64] + mova m0, [rsp+16*mmsize] + mova m1, [rsp+17*mmsize] + mova m2, [rsp+18*mmsize] + mova m3, [rsp+19*mmsize] + mova m4, [rsp+20*mmsize] + mova m5, [rsp+21*mmsize] + mova m6, [rsp+22*mmsize] + mova m7, [rsp+23*mmsize] + mova m16, [rsp+24*mmsize] + mova m17, [rsp+25*mmsize] + mova m18, [rsp+26*mmsize] + mova m19, [rsp+27*mmsize] + mova m20, [rsp+28*mmsize] + mova m21, [rsp+29*mmsize] + mova m22, [rsp+30*mmsize] + mova m23, [rsp+31*mmsize] + call .transpose + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_fast_start + mov r7d, 16*12 + pxor m12, m12 + jmp .end +.fast2: ; topleft 8x8 nonzero + movshdup m7, [o(permB)] + mova ym0, [cq+128*1] + mova ym2, [cq+128*5] + mova ym3, [cq+128*3] + mova ym1, [cq+128*7] + vpermt2q m0, m7, m2 ; 1 5 + vpermt2q m1, m7, m3 ; 7 3 + REPX {pmulld x, m12}, m0, m1 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_oddhalf_packed_rect2 + mova [rsp+ 0*mmsize], m0 + mova [rsp+ 1*mmsize], m1 + mova [rsp+ 2*mmsize], m2 + mova [rsp+ 3*mmsize], m3 + mova [rsp+ 4*mmsize], m4 + mova [rsp+ 5*mmsize], m5 + mova [rsp+ 6*mmsize], m6 + mova [rsp+ 7*mmsize], m7 + mova [rsp+ 8*mmsize], m16 + mova [rsp+ 9*mmsize], m17 + mova [rsp+10*mmsize], m18 + mova [rsp+11*mmsize], m19 + mova [rsp+12*mmsize], m20 + mova [rsp+13*mmsize], m21 + mova [rsp+14*mmsize], m22 + mova [rsp+15*mmsize], m23 + + movshdup m7, [o(permB)] + pmulld ym0, ym12, [cq+128*0] + pmulld ym4, ym12, [cq+128*4] + mova ym16, [cq+128*2] + mova ym5, [cq+128*6] + REPX {paddd x, ym13}, ym0, ym4 + REPX {psrad x, 12 }, ym0, ym4 + vpermt2q m16, m7, m5 ; 2 6 + vpermq m0, m7, m0 ; 0 0 + vpermq m4, m7, m4 ; 4 4 + pmulld m16, m12 + paddd m16, m13 + psrad m16, 12 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast3 + + vpbroadcastd m11, [o(pd_1)] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_end + mova [rsp+16*mmsize], m24 + mova [rsp+17*mmsize], m25 + mova [rsp+18*mmsize], m26 + mova [rsp+19*mmsize], m27 + mova [rsp+20*mmsize], m28 + mova [rsp+21*mmsize], m29 + mova [rsp+22*mmsize], m30 + mova [rsp+23*mmsize], m31 + vpbroadcastd m13, [o(pd_2048)] + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_fast2_start + mov r7d, 16*4 + mov r4, dstq + pxor m12, m12 + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_end + lea dstq, [r4+64] + mova m0, [rsp+16*mmsize] + mova m1, [rsp+17*mmsize] + mova m2, [rsp+18*mmsize] + mova m3, [rsp+19*mmsize] + mova m4, [rsp+20*mmsize] + mova m5, [rsp+21*mmsize] + mova m6, [rsp+22*mmsize] + mova m7, [rsp+23*mmsize] + lea r5, [o_base] + vpbroadcastd m13, [o(pd_2048)] + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_fast2_start + pxor m12, m12 +.end: + call m(inv_txfm_add_dct_dct_32x32_10bpc).pass2_end +.zero_loop: + mova [cq+r7*8+128*3], m12 + mova [cq+r7*8+128*2], m12 + mova [cq+r7*8+128*1], m12 + mova [cq+r7*8+128*0], m12 + sub r7d, 16*4 + jge .zero_loop + RET +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 32 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 384 + sar r6d, 9 + jmp m(inv_txfm_add_dct_dct_64x16_10bpc).dconly2 +.pass1_fast: + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64+gprsize] + pmulld m0, m12, [cq+128* 1] + pmulld m3, m12, [cq+128*15] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast_rect2 + pmulld m0, m12, [cq+128* 7] + pmulld m3, m12, [cq+128* 9] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast_rect2 + pmulld m0, m12, [cq+128* 5] + pmulld m3, m12, [cq+128*11] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast_rect2 + pmulld m0, m12, [cq+128* 3] + pmulld m3, m12, [cq+128*13] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast_rect2 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part2 + pmulld m0, m12, [cq+128* 0] + pmulld m1, m12, [cq+128* 8] + pmulld m16, m12, [cq+128* 4] + pmulld m17, m12, [cq+128*12] + call m(idct_8x16_internal_10bpc).main_fast2_rect2 + call m(idct_16x16_internal_10bpc).main_fast2_rect2 + call .pass1_load_spill + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast2_rect2 + jmp .pass1_end +.pass1: + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64+gprsize] + pmulld m0, m12, [cq+128* 1] + pmulld m1, m12, [cq+128*31] + pmulld m2, m12, [cq+128*17] + pmulld m3, m12, [cq+128*15] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_rect2 + pmulld m0, m12, [cq+128* 7] + pmulld m1, m12, [cq+128*25] + pmulld m2, m12, [cq+128*23] + pmulld m3, m12, [cq+128* 9] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_rect2 + pmulld m0, m12, [cq+128* 5] + pmulld m1, m12, [cq+128*27] + pmulld m2, m12, [cq+128*21] + pmulld m3, m12, [cq+128*11] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_rect2 + pmulld m0, m12, [cq+128* 3] + pmulld m1, m12, [cq+128*29] + pmulld m2, m12, [cq+128*19] + pmulld m3, m12, [cq+128*13] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_rect2 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part2 + pmulld m0, m12, [cq+128* 0] + pmulld m1, m12, [cq+128* 8] + pmulld m2, m12, [cq+128*16] + pmulld m3, m12, [cq+128*24] + pmulld m16, m12, [cq+128* 4] + pmulld m17, m12, [cq+128*12] + pmulld m18, m12, [cq+128*20] + pmulld m19, m12, [cq+128*28] + call m(idct_8x16_internal_10bpc).main_fast_rect2 + call m(idct_16x16_internal_10bpc).main_fast_rect2 + call .pass1_load_spill + pmulld m4, m12, [cq+128*18] + pmulld m5, m12, [cq+128*22] + pmulld m6, m12, [cq+128*26] + pmulld m7, m12, [cq+128*30] + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast_rect2 +.pass1_end: + vpbroadcastd m11, [o(pd_1)] + lea r3, [rsp+gprsize] + lea r4, [cq+8*128] + call m(inv_txfm_add_dct_dct_64x16_10bpc).idct64_main_end + ; transpose one half immediately, we can transpose lower half later +.transpose: + ; transpose m0-7,16-23 + psrlq m12, [permC], 24 ; 0 2 8 10 1 3 9 11 + psrlq m13, m12, 32 ; 4 6 12 14 5 7 13 15 + call m(inv_txfm_add_dct_dct_32x16_10bpc).transpose_16x32 + punpckhqdq m22, m0, m20 ; 1 + punpcklqdq m0, m20 ; 0 + punpckhqdq m24, m2, m1 ; 5 + punpcklqdq m1, m2, m1 ; 4 + punpcklqdq m2, m14, m18 ; 8 + punpckhqdq m26, m14, m18 ; 9 + punpcklqdq m14, m15, m4 ; 2 + punpckhqdq m23, m15, m4 ; 3 + punpckhqdq m25, m3, m21 ; 7 + punpcklqdq m15, m3, m21 ; 6 + punpckhqdq m28, m6, m17 ; 13 + punpcklqdq m3, m6, m17 ; 12 + punpckhqdq m27, m5, m16 ; 11 + punpcklqdq m16, m5, m16 ; 10 + punpckhqdq m29, m7, m8 ; 15 + punpcklqdq m17, m7, m8 ; 14 + ret +.pass1_load_spill: + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + mova [cq+128* 0], m0 + mova [cq+128* 1], m1 + pmulld m0, m12, [cq+128* 2] + pmulld m1, m12, [cq+128* 6] + mova [cq+128* 2], m2 + mova [cq+128* 3], m3 + pmulld m2, m12, [cq+128*10] + pmulld m3, m12, [cq+128*14] + mova [cq+128* 4], m4 + mova [cq+128* 5], m5 + mova [cq+128* 6], m6 + mova [cq+128* 7], m7 + mova [cq+128* 8], m23 + mova [cq+128* 9], m22 + mova [cq+128*10], m21 + mova [cq+128*11], m20 + mova [cq+128*12], m19 + mova [cq+128*13], m18 + mova [cq+128*14], m17 + mova [cq+128*15], m16 + ret + +cglobal inv_txfm_add_dct_dct_64x64_10bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + + PROLOGUE 4, 9, 32, -64*32, dst, stride, c, eob +%undef cmp + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + cmp eobd, 136 + jl .fast + add cq, 64 + cmp eobd, 543 + jge .full + call .pass1_fast ; bottomright 16x16 zero + mov r7d, 16*12 + jmp .lefthalf +.full: + call .pass1 + mov r7d, 16*28 +.lefthalf: + mova [cq+128* 0], m27 + mova [cq+128* 1], m14 + mova [cq+128* 2], m28 + mova [cq+128* 3], m15 + mova [cq+128* 4], m22 + mova [cq+128* 5], m23 + mova [cq+128* 6], m24 + mova [cq+128* 7], m25 + mova [cq+128* 8], m0 + mova [cq+128* 9], m26 + mova [cq+128*10], m20 + mova [cq+128*11], m21 + mova [cq+128*12], m18 + mova [cq+128*13], m16 + mova [cq+128*14], m17 + mova [cq+128*15], m3 + sub cq, 64 + vpbroadcastd m12, [o(pd_2896)] + vpbroadcastd m13, [o(pd_2048)] + vpbroadcastd m14, [o(clip_18b_min)] + vpbroadcastd m15, [o(clip_18b_max)] + sub rsp, 16*64 + call .pass1 + sub rsp, 24*64 + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_start + mov r8, dstq + pxor m31, m31 + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_end + lea dstq, [r8+64] + mova m0, [rsp+56*mmsize] + mova m1, [rsp+57*mmsize] + mova m2, [rsp+58*mmsize] + mova m3, [rsp+59*mmsize] + mova m4, [rsp+60*mmsize] + mova m5, [rsp+61*mmsize] + mova m6, [rsp+62*mmsize] + mova m7, [rsp+63*mmsize] + mova m16, [rsp+64*mmsize] + mova m17, [rsp+65*mmsize] + mova m18, [rsp+66*mmsize] + mova m19, [rsp+67*mmsize] + mova m20, [rsp+68*mmsize] + mova m21, [rsp+69*mmsize] + mova m22, [rsp+70*mmsize] + mova m23, [rsp+71*mmsize] + call .transpose + mova [cq+128* 0+64], m27 + mova [cq+128* 1+64], m14 + mova [cq+128* 2+64], m28 + mova [cq+128* 3+64], m15 + mova [cq+128* 4+64], m22 + mova [cq+128* 5+64], m23 + mova [cq+128* 6+64], m24 + mova [cq+128* 7+64], m25 + mova [cq+128* 8+64], m0 + mova [cq+128* 9+64], m26 + mova [cq+128*10+64], m20 + mova [cq+128*11+64], m21 + mova [cq+128*12+64], m18 + mova [cq+128*13+64], m16 + mova [cq+128*14+64], m17 + mova [cq+128*15+64], m3 + mova m0, [rsp+40*mmsize] + mova m1, [rsp+41*mmsize] + mova m2, [rsp+42*mmsize] + mova m3, [rsp+43*mmsize] + mova m4, [rsp+44*mmsize] + mova m5, [rsp+45*mmsize] + mova m6, [rsp+46*mmsize] + mova m7, [rsp+47*mmsize] + mova m16, [rsp+48*mmsize] + mova m17, [rsp+49*mmsize] + mova m18, [rsp+50*mmsize] + mova m19, [rsp+51*mmsize] + mova m20, [rsp+52*mmsize] + mova m21, [rsp+53*mmsize] + mova m22, [rsp+54*mmsize] + mova m23, [rsp+55*mmsize] + add rsp, 32*64 + call .transpose + lea r5, [o_base] + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_start +.right_zero_loop: + REPX {mova [cq+r7*8+64+128*x], m31}, 0, 1, 2, 3 + sub r7d, 16*4 + jge .right_zero_loop + mov r7d, 16*28 + jmp .end +.fast: ; topleft 16x16 nonzero + cmp eobd, 36 + jl .fast2 + call .pass1_fast + sub rsp, 24*64 + vpbroadcastd m10, [o(pd_2048)] + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_fast_start + mov r8, dstq + pxor m31, m31 + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_end + lea dstq, [r8+64] + mova m0, [rsp+40*mmsize] + mova m1, [rsp+41*mmsize] + mova m2, [rsp+42*mmsize] + mova m3, [rsp+43*mmsize] + mova m4, [rsp+44*mmsize] + mova m5, [rsp+45*mmsize] + mova m6, [rsp+46*mmsize] + mova m7, [rsp+47*mmsize] + mova m16, [rsp+48*mmsize] + mova m17, [rsp+49*mmsize] + mova m18, [rsp+50*mmsize] + mova m19, [rsp+51*mmsize] + mova m20, [rsp+52*mmsize] + mova m21, [rsp+53*mmsize] + mova m22, [rsp+54*mmsize] + mova m23, [rsp+55*mmsize] + add rsp, 16*64 + call .transpose + lea r5, [o_base] + vpbroadcastd m10, [o(pd_2048)] + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_fast_start + mov r7d, 16*12 + jmp .end +.fast2: ; topleft 8x8 nonzero + movshdup m7, [o(permB)] + mova ym0, [cq+128*1] + mova ym2, [cq+128*5] + mova ym3, [cq+128*3] + mova ym1, [cq+128*7] + vpermt2q m0, m7, m2 ; 1 5 + vpermt2q m1, m7, m3 ; 7 3 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_oddhalf_packed + mova [rsp+ 0*mmsize], m0 + mova [rsp+ 1*mmsize], m1 + mova [rsp+ 2*mmsize], m2 + mova [rsp+ 3*mmsize], m3 + mova [rsp+ 4*mmsize], m4 + mova [rsp+ 5*mmsize], m5 + mova [rsp+ 6*mmsize], m6 + mova [rsp+ 7*mmsize], m7 + mova [rsp+ 8*mmsize], m16 + mova [rsp+ 9*mmsize], m17 + mova [rsp+10*mmsize], m18 + mova [rsp+11*mmsize], m19 + mova [rsp+12*mmsize], m20 + mova [rsp+13*mmsize], m21 + mova [rsp+14*mmsize], m22 + mova [rsp+15*mmsize], m23 + + movshdup m7, [o(permB)] + mova ym0, [cq+128*0] + mova ym4, [cq+128*4] + mova ym16, [cq+128*2] + mova ym5, [cq+128*6] + vpermt2q m16, m7, m5 ; 2 6 + vpermq m0, m7, m0 ; 0 0 + vpermq m4, m7, m4 ; 4 4 + call m(inv_txfm_add_dct_dct_32x8_10bpc).main_fast3 + + vpbroadcastd m11, [o(pd_2)] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_end + sub rsp, 16*64 + mova [rsp+40*mmsize], m24 + mova [rsp+41*mmsize], m25 + mova [rsp+42*mmsize], m26 + mova [rsp+43*mmsize], m27 + mova [rsp+44*mmsize], m28 + mova [rsp+45*mmsize], m29 + mova [rsp+46*mmsize], m30 + mova [rsp+47*mmsize], m31 + call .pass2_fast2_start + mov r7d, 16*4 + mov r8, dstq + pxor m31, m31 + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_end + lea dstq, [r8+64] + mova m0, [rsp+40*mmsize] + mova m1, [rsp+41*mmsize] + mova m2, [rsp+42*mmsize] + mova m3, [rsp+43*mmsize] + mova m4, [rsp+44*mmsize] + mova m5, [rsp+45*mmsize] + mova m6, [rsp+46*mmsize] + mova m7, [rsp+47*mmsize] + add rsp, 8*64 + lea r5, [o_base] + call .pass2_fast2_start +.end: + pxor m31, m31 +.zero_loop: + REPX {mova [cq+r7*8+128*x], m31}, 0, 1, 2, 3 + sub r7d, 16*4 + jge .zero_loop + call m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_end + add rsp, 8*64 ; FIXME adjust stack_size_padded instead? + RET +.pass2_fast2_start: + call m(inv_txfm_add_dct_dct_32x8_10bpc).transpose_8x32 + punpcklqdq m27, m0, m2 ; 0 + punpckhqdq m0, m2 ; 1 + punpcklqdq m22, m3, m4 ; 2 + punpckhqdq m26, m3, m4 ; 3 + punpcklqdq m14, m5, m7 ; 4 + punpckhqdq m20, m5, m7 ; 5 + punpcklqdq m23, m6, m8 ; 6 + punpckhqdq m21, m6, m8 ; 7 + vpbroadcastd m10, [o(pd_2048)] + jmp m(inv_txfm_add_dct_dct_32x64_10bpc).pass2_fast2_start +.dconly: + imul r6d, [cq], 181 + mov [cq], eobd + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_64x16_10bpc).dconly1 +.pass1_fast: + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64+gprsize] + mova m0, [cq+128* 1] + mova m3, [cq+128*15] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast + mova m0, [cq+128* 7] + mova m3, [cq+128* 9] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast + mova m0, [cq+128* 5] + mova m3, [cq+128*11] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast + mova m0, [cq+128* 3] + mova m3, [cq+128*13] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1_fast + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part2 + mova m0, [cq+128* 0] + mova m1, [cq+128* 8] + mova m16, [cq+128* 4] + mova m17, [cq+128*12] + call m(idct_8x16_internal_10bpc).main_fast2 + call m(idct_16x16_internal_10bpc).main_fast2 + call .pass1_load_spill + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast2 + jmp .pass1_end +.pass1: + lea r4, [idct64_mul_16bpc] + lea r6, [rsp+4*64+gprsize] + mova m0, [cq+128* 1] + mova m1, [cq+128*31] + mova m2, [cq+128*17] + mova m3, [cq+128*15] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1 + mova m0, [cq+128* 7] + mova m1, [cq+128*25] + mova m2, [cq+128*23] + mova m3, [cq+128* 9] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1 + mova m0, [cq+128* 5] + mova m1, [cq+128*27] + mova m2, [cq+128*21] + mova m3, [cq+128*11] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1 + mova m0, [cq+128* 3] + mova m1, [cq+128*29] + mova m2, [cq+128*19] + mova m3, [cq+128*13] + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part1 + call m(inv_txfm_add_dct_dct_64x16_10bpc).main_part2 + mova m0, [cq+128* 0] + mova m1, [cq+128* 8] + mova m2, [cq+128*16] + mova m3, [cq+128*24] + mova m16, [cq+128* 4] + mova m17, [cq+128*12] + mova m18, [cq+128*20] + mova m19, [cq+128*28] + call m(idct_8x16_internal_10bpc).main_fast + call m(idct_16x16_internal_10bpc).main_fast + call .pass1_load_spill + mova m4, [cq+128*18] + mova m5, [cq+128*22] + mova m6, [cq+128*26] + mova m7, [cq+128*30] + call m(inv_txfm_add_dct_dct_32x16_10bpc).main_fast +.pass1_end: + vpbroadcastd m11, [o(pd_2)] + lea r3, [rsp+gprsize] + lea r4, [cq+8*128] + call m(inv_txfm_add_dct_dct_64x16_10bpc).idct64_main_end + ; transpose one half immediately, we can transpose lower half later +.transpose: + ; transpose m0-7,16-23 + psrlq m12, [permC], 24 ; 0 2 8 10 1 3 9 11 + psrlq m13, m12, 32 ; 4 6 12 14 5 7 13 15 + call m(inv_txfm_add_dct_dct_32x16_10bpc).transpose_16x32 + punpcklqdq m27, m0, m20 ; 0 + punpckhqdq m0, m20 ; 1 + punpcklqdq m24, m5, m16 ; 10 + punpckhqdq m16, m5, m16 ; 11 + punpcklqdq m23, m3, m21 ; 6 + punpckhqdq m21, m3, m21 ; 7 + punpcklqdq m25, m7, m8 ; 14 + punpckhqdq m3, m7, m8 ; 15 + punpcklqdq m22, m15, m4 ; 2 + punpckhqdq m26, m15, m4 ; 3 + punpcklqdq m15, m6, m17 ; 12 + punpckhqdq m17, m6, m17 ; 13 + punpcklqdq m28, m14, m18 ; 8 + punpckhqdq m18, m14, m18 ; 9 + punpcklqdq m14, m2, m1 ; 4 + punpckhqdq m20, m2, m1 ; 5 + ret +.pass1_load_spill: + call m(inv_txfm_add_dct_dct_32x16_10bpc).idct16_sumsub + mova [cq+128* 0], m0 + mova [cq+128* 1], m1 + mova m0, [cq+128* 2] + mova m1, [cq+128* 6] + mova [cq+128* 2], m2 + mova [cq+128* 3], m3 + mova m2, [cq+128*10] + mova m3, [cq+128*14] + mova [cq+128* 4], m4 + mova [cq+128* 5], m5 + mova [cq+128* 6], m6 + mova [cq+128* 7], m7 + mova [cq+128* 8], m23 + mova [cq+128* 9], m22 + mova [cq+128*10], m21 + mova [cq+128*11], m20 + mova [cq+128*12], m19 + mova [cq+128*13], m18 + mova [cq+128*14], m17 + mova [cq+128*15], m16 + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8135 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; Copyright © 2017-2021, The rav1e contributors +; Copyright © 2020, Nathan Egge +; Copyright © 2021, Matthias Dressel +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA +%macro COEF 1-2 +pd_%1: times 4 dd %1 +%if %0 == 2 +pd_m%1: times 4 dd -%1 +%endif +%endmacro + +COEF 201 +COEF 401 +COEF 601, 1 +COEF 799 +COEF 995 +COEF 1189, 1 +COEF 1380, 1 +COEF 1567 +COEF 1751 +COEF 1931 +COEF 2106, 1 +COEF 2276, 1 +COEF 2440 +COEF 2598, 1 +COEF 2751, 1 +COEF 2896 +COEF 3035 +COEF 3166 +COEF 3290 +COEF 3406 +COEF 3513 +COEF 3612 +COEF 3703 +COEF 3784 +COEF 3857 +COEF 3920 +COEF 3973 +COEF 4017 +COEF 4052 +COEF 4076 +COEF 4091 + +deint_shuf: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 + +%if ARCH_X86_32 +pd_1: times 4 dd 1 +%endif +pd_2: times 4 dd 2 +pw_5: times 8 dw 5 +pd_1321: times 4 dd 1321 +pd_2482: times 4 dd 2482 +pd_m3344: times 4 dd -3344 +pd_2048: times 4 dd 2048 +pw_4x2048_4xm2048: times 4 dw 2048 + times 4 dw -2048 +pw_4xm2048_4x2048: times 4 dw -2048 + times 4 dw 2048 +pw_2048: times 8 dw 2048 +pw_m2048: times 8 dw -2048 +pd_3803: times 4 dd 3803 +pw_4096: times 8 dw 4096 +pd_5793: times 4 dd 5793 +pd_6144: times 4 dd 6144 +pw_8192: times 8 dw 8192 +pd_10240: times 4 dd 10240 +pd_11586: times 4 dd 11586 +pw_1697x8: times 8 dw 1697*8 +pw_2896x8: times 8 dw 2896*8 +pw_1697x16: times 8 dw 1697*16 +pw_16384: times 8 dw 16384 +pixel_10bpc_max: times 8 dw 0x03ff + +pw_1567_3784: times 4 dw 1567, 3784 +pw_m3784_1567: times 4 dw -3784, 1567 +pw_2896_2896: times 4 dw 2896, 2896 +pw_m2896_2896: times 4 dw -2896, 2896 + +clip_18b_min: times 4 dd -0x20000 +clip_18b_max: times 4 dd 0x1ffff + +idct64_mul_16bpc: +dd 4095, 101, 2967, -2824, 3745, 1660, 3822, -1474, 401, 4076, 799, 4017 +dd -700, 4036, 2359, 3349, -2191, 3461, 897, 3996, -2598, -3166, -4017, -799 +dd 4065, 501, 3229, -2520, 3564, 2019, 3948, -1092, 1931, 3612, 3406, 2276 +dd -301, 4085, 2675, 3102, -1842, 3659, 1285, 3889, -1189, -3920, -2276, -3406 + +cextern inv_txfm_add_dct_dct_4x4_8bpc_ssse3 +cextern iadst_4x4_internal_8bpc_ssse3.main +cextern idct_4x8_internal_8bpc_ssse3.main +cextern iadst_4x8_internal_8bpc_ssse3.main +cextern idct_16x4_internal_8bpc_ssse3.main +cextern iadst_16x4_internal_8bpc_ssse3.main +cextern iadst_16x4_internal_8bpc_ssse3.main_pass2_end +cextern idct_8x4_internal_8bpc_ssse3.main +cextern iadst_8x4_internal_8bpc_ssse3.main +cextern idct_8x8_internal_8bpc_ssse3.main +cextern idct_8x8_internal_8bpc_ssse3.pass1_end3 +cextern iadst_8x8_internal_8bpc_ssse3.main +cextern iadst_8x8_internal_8bpc_ssse3.main_pass2_end +cextern idct_16x8_internal_8bpc_ssse3.main +cextern iadst_16x8_internal_8bpc_ssse3.main +cextern iadst_16x8_internal_8bpc_ssse3.main_pass2_end +cextern idct_8x32_internal_8bpc_ssse3.main +cextern idct_8x32_internal_8bpc_ssse3.main_fast +cextern idct_8x32_internal_8bpc_ssse3.main_veryfast +cextern idct_16x64_internal_8bpc_ssse3.main +cextern idct_16x64_internal_8bpc_ssse3.main_fast + +tbl_4x16_2d: db 0, 13, 29, 45 +tbl_4x16_h: db 0, 16, 32, 48 +tbl_4x16_v: db 0, 4, 8, 12 + +tbl_8x16_2d: db 0, 14, 30, 46 +tbl_8x16_v: db 0, 4, 8, 12 +tbl_8x16_h: db 0, 32, 64, 96 + +tbl_16x16_2d: db 0, 10, 36, 78 +tbl_16x16_v: db 0, 4, 8, 12 +tbl_16x16_h: db 0, 64, 128, 192 + +tbl_8x32_2d: dw 0, 14, 43, 75, 107, 139, 171, 203 + +tbl_16x32_2d: dw 0, 14, 44, 90, 151, 215, 279, 343 + +tbl_32x16_2d: ; first 4 entries of 32x32 are identical to this one +tbl_32x32_2d: dw 0, 10, 36, 78, 136, 210, 300, 406 + +tbl_Nx32_odd_offset: db 2*16, 2*23 + db 2*20, 2*19 + db 2*18, 2*21 + db 2*22, 2*17 + db 2*30, 2*25 + db 2*26, 2*29 + db 2*28, 2*27 + db 2*24, 2*31 + +tbl_Nx64_offset: db 2* 0, 2*32, 2*16, 2*46 + db 2* 8, 2*40, 2*23, 2*38 + db 2* 1, 2*36, 2*20, 2*42 + db 2* 9, 2*44, 2*19, 2*34 + db 2* 2, 2*60, 2*18, 2*50 + db 2*10, 2*52, 2*21, 2*58 + db 2* 3, 2*56, 2*22, 2*54 + db 2*11, 2*48, 2*17, 2*62 + +SECTION .text + +%define m_suffix(x, sfx) mangle(private_prefix %+ _ %+ x %+ sfx) +%define m(x) m_suffix(x, SUFFIX) + +; This refers to the first function in itx_sse i.e. the start of the text section +; which is needed as a base pointer for constants. +%define itx8_start m_suffix(inv_txfm_add_dct_dct_4x4_8bpc, _ssse3) + +%if ARCH_X86_64 +%define o(x) x +%else +%define o(x) r6-$$+x ; PIC +%endif + +%macro IWHT4_1D 0 + ; m0 = in0, m1 = in1, m2 = in2, m3 = in3 + paddd m0, m1 ; in0 += in1 + psubd m4, m2, m3 ; tmp0 = in2 - in3 + psubd m5, m0, m4 ; tmp1 = (in0 - tmp0) >> 1 + psrad m5, 1 + psubd m2, m5, m1 ; in2 = tmp1 - in1 + psubd m5, m3 ; in1 = tmp1 - in3 + psubd m0, m5 ; in0 -= in1 + paddd m4, m2 ; in3 = tmp0 + in2 + ; m0 = out0, m1 = in1, m2 = out2, m3 = in3 + ; m4 = out3, m5 = out1 +%endmacro + +INIT_XMM sse2 +cglobal inv_txfm_add_wht_wht_4x4_16bpc, 3, 3, 6, dst, stride, c, eob, bdmax + mova m0, [cq+16*0] + mova m1, [cq+16*1] + mova m2, [cq+16*2] + mova m3, [cq+16*3] + REPX {psrad x, 2}, m0, m1, m2, m3 + IWHT4_1D + punpckldq m1, m0, m5 + punpckhdq m3, m0, m5 + punpckldq m5, m2, m4 + punpckhdq m2, m4 + punpcklqdq m0, m1, m5 + punpckhqdq m1, m5 + punpcklqdq m4, m3, m2 + punpckhqdq m3, m2 + mova m2, m4 + IWHT4_1D + packssdw m0, m4 ; low: out3, high: out0 + packssdw m2, m5 ; low: out2, high: out1 + pxor m4, m4 + mova [cq+16*0], m4 + mova [cq+16*1], m4 + mova [cq+16*2], m4 + mova [cq+16*3], m4 + lea r2, [dstq+strideq*2] + movq m1, [dstq+strideq*0] + movhps m1, [r2 +strideq*1] + movq m3, [r2 +strideq*0] + movhps m3, [dstq+strideq*1] + movd m5, bdmaxm + pshuflw m5, m5, q0000 ; broadcast + punpcklqdq m5, m5 ; broadcast + paddsw m0, m1 + paddsw m2, m3 + pmaxsw m0, m4 + pmaxsw m2, m4 + pminsw m0, m5 + pminsw m2, m5 + movhps [r2 +strideq*1], m0 ; write out0 + movhps [dstq+strideq*1], m2 ; write out1 + movq [r2 +strideq*0], m2 ; write out2 + movq [dstq+strideq*0], m0 ; write out3 + RET + +; dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +; dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +; flags: 2 = inv_dst1, 4 = inv_dst2 +; skip round/shift if rnd is not a number +%macro ITX_MULSUB_2D 8-9 0 ; dst/src[1-2], tmp[1-3], rnd, coef[1-2], flags +; %1 dst/src[1] +; %2 dst/src[2] +; %3 tmp[1] +; %4 tmp[2] +; %5 tmp[3] +; %6 rnd +; %7 coef[1] +; %8 coef[2] +; %9 flags +%ifnidn %7,%8 ; optimize when coef1 == coef2 +%if %8 < 32 + pmulld m%4, m%1, m%8 + pmulld m%3, m%2, m%8 +%else + mova m%3, [o(pd_%8)] + pmulld m%4, m%1, m%3 + pmulld m%3, m%2 +%endif +%endif +%if %7 < 32 + pmulld m%1, m%7 + pmulld m%2, m%7 +%else + mova m%5, [o(pd_%7)] + pmulld m%1, m%5 + pmulld m%2, m%5 +%endif +%if %9 & 4 ; invert dst2 + paddd m%4, m%2 + psubd m%2, m%6, m%4 +%else +%ifnum %6 +%ifnidn %7,%8 + paddd m%4, m%6 +%else + paddd m%1, m%6 +%endif +%endif +%ifnidn %7,%8 + paddd m%2, m%4 +%else + mova m%3, m%2 + paddd m%2, m%1 +%endif +%endif +%if %9 & 2 ; invert dst1 + psubd m%3, m%1 + paddd m%1, m%3, m%6 +%else +%ifnum %6 +%ifnidn %7,%8 + paddd m%1, m%6 +%endif +%endif + psubd m%1, m%3 +%endif +%ifnum %6 + psrad m%2, 12 + psrad m%1, 12 +%endif +%endmacro + +%macro INV_TXFM_FN 4-5+ 8 ; type1, type2, eob_offset, size, mmsize/stack +cglobal inv_txfm_add_%1_%2_%4_16bpc, 4, 7, %5, dst, stride, c, eob, tx2 + %define %%p1 m(i%1_%4_internal_16bpc) +%if ARCH_X86_32 + LEA r6, $$ +%endif +%if has_epilogue +%ifidn %1_%2, dct_dct + test eobd, eobd + jz %%end +%endif + lea tx2q, [o(m(i%2_%4_internal_16bpc).pass2)] +%ifnum %3 +%if %3 + add eobd, %3 +%endif +%else + lea r5, [o(%3)] +%endif + call %%p1 + RET +%%end: +%else + ; Jump to the 1st txfm function if we're not taking the fast path, which + ; in turn performs an indirect jump to the 2nd txfm function. + lea tx2q, [o(m(i%2_%4_internal_16bpc).pass2)] +%ifnum %3 +%if %3 + add eobd, %3 +%endif +%else + lea r5, [o(%3)] +%endif +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else + ; jump to the 1st txfm function unless it's located directly after this + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endif +%endmacro + +%macro INV_TXFM_4X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 0, 4x4 +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 4 +.dconly: + add r5d, 128 + sar r5d, 8 +.dconly2: + imul r5d, 2896 + mova m2, [o(pixel_10bpc_max)] + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + pxor m3, m3 + punpcklqdq m0, m0 +.dconly_loop: + movq m1, [dstq+strideq*0] + movhps m1, [dstq+strideq*1] + paddw m1, m0 + pminsw m1, m2 + pmaxsw m1, m3 + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%endif +%endmacro + +%macro IDCT4_1D 8 ; src[1-4], tmp[1-3], rnd + ; butterfly rotation + ITX_MULSUB_2D %1, %3, %5, %6, %7, %8, 2896, 2896 ; %1 out1 %3 out0 + ITX_MULSUB_2D %2, %4, %5, %6, %7, %8, 1567, 3784 ; %2 out2 %4 out3 + ; Hadamard rotation + psubd m%5, m%1, m%2 + paddd m%2, m%1 + paddd m%1, m%3, m%4 + psubd m%3, m%4 + ; %1 (src1) = out0 + ; %2 (src2) = out1 + ; %3 (src3) = out3 + ; $5 (tmp1) = out2 +%endmacro + +INIT_XMM sse4 + +INV_TXFM_4X4_FN dct, dct +INV_TXFM_4X4_FN dct, identity +INV_TXFM_4X4_FN dct, adst +INV_TXFM_4X4_FN dct, flipadst + +cglobal idct_4x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + mova m2, [cq+16*2] + mova m3, [cq+16*3] + mova m5, [o(pd_2048)] + call .pass1_main + packssdw m0, m1 ; out0 out1 + packssdw m4, m2 ; out2 out3 + ; transpose + punpckhwd m2, m0, m4 + punpcklwd m0, m4 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + ; m0 = out0 out1 + ; m1 = out2 out3 + ; m5 = pd_2048 + jmp tx2q +.pass1_main: + IDCT4_1D 0, 1, 2, 3, 4, 6, 7, 5 + ret +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 + ; m5 = pd_2048 + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + pmaddwd m4, m2, [o(pw_m3784_1567)] + pmaddwd m2, [o(pw_1567_3784)] + pmaddwd m0, m1, [o(pw_m2896_2896)] + pmaddwd m1, [o(pw_2896_2896)] + REPX {paddd x, m5}, m4, m2, m0, m1 + packssdw m5, m5 ; pw_2048 + REPX {psrad x, 12}, m4, m2, m0, m1 + packssdw m2, m4 ; t3 t2 + packssdw m1, m0 ; t0 t1 + paddsw m0, m1, m2 ; out0 out1 + psubsw m1, m2 ; out3 out2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + movq m2, [dstq+strideq*0] + movhps m2, [dstq+strideq*1] + lea r5, [dstq+strideq*2] + movq m3, [r5 +strideq*1] + movhps m3, [r5 +strideq*0] + mova m5, [o(pixel_10bpc_max)] + pxor m4, m4 + mova [cq+16*0], m4 + mova [cq+16*1], m4 + mova [cq+16*2], m4 + mova [cq+16*3], m4 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m5 + pminsw m1, m5 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movhps [r5 +strideq*0], m1 + movq [r5 +strideq*1], m1 + RET + +INV_TXFM_4X4_FN adst, dct +INV_TXFM_4X4_FN adst, adst +INV_TXFM_4X4_FN adst, flipadst +INV_TXFM_4X4_FN adst, identity + +cglobal iadst_4x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + call .main + packssdw m0, m2 ; out0 out1 + packssdw m1, m4 ; out2 out3 + ; transpose + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + ; m0 = out0 out1 + ; m1 = out2 out3 + ; m5 = pd_2048 + jmp tx2q +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_4x4_internal_8bpc, _ssse3).main +.end: + mova m4, [o(pw_2048)] + movq m2, [dstq+strideq*0] + movhps m2, [dstq+strideq*1] + lea r5, [dstq+strideq*2] + movq m3, [r5 +strideq*0] + movhps m3, [r5 +strideq*1] + mova m5, [o(pixel_10bpc_max)] + pmulhrsw m0, m4 + pmulhrsw m1, m4 + pxor m4, m4 + mova [cq+16*0], m4 + mova [cq+16*1], m4 + mova [cq+16*2], m4 + mova [cq+16*3], m4 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m5 + pminsw m1, m5 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [r5 +strideq*0], m1 + movhps [r5 +strideq*1], m1 + RET +ALIGN function_align +.main: + mova m1, [cq+16*2] + mova m3, [cq+16*3] + mova m5, [cq+16*0] + lea r3, [cq+16*1] +.main2: + mova m0, [o(pd_1321)] ; SINPI_1_9 + mova m2, [o(pd_2482)] ; SINPI_2_9 + mova m6, [o(pd_3803)] ; SINPI_4_9 + pmulld m4, m0, m1 ; s[4] = SINPI_1_9 * T[2] + pmulld m7, m3, m6 ; s[6] = SINPI_4_9 * T[3] + pmulld m6, m1 ; s[3] = SINPI_4_9 * T[2] + pmulld m0, m5 ; s[0] = SINPI_1_9 * T[0] + psubd m1, m3 ; T[2] - T[3] + pmulld m3, m2 ; s[5] = SINPI_2_9 * T[3] + pmulld m2, m5 ; s[1] = SINPI_2_9 * T[0] + paddd m0, m6 ; s[0] += s[3] + paddd m0, m3 ; s[0] += s[5] + mova m3, [o(pd_m3344)] ; -SINPI_3_9 + psubd m2, m4 ; s[1] -= s[4] + psubd m2, m7 ; s[1] -= s[6] + psubd m1, m5 ; -b7 = (T[2] -T[3]) - T[0] + pmulld m1, m3 ; s[2] = -SINPI_3_9 * -b7 + pmulld m3, [r3] ; -s[3] = -SINPI_3_9 * T[1] + mova m5, [o(pd_2048)] + REPX {paddd x, m5}, m0, m1 ; {s[0], s[2]} + 2048 + paddd m4, m0, m2 ; x[3] = s[0] + s[1] + psubd m2, m3 ; x[1] = s[1] + s[3] + psubd m0, m3 ; x[0] = s[0] + s[3] + paddd m4, m3 ; x[3] -= s[3] + paddd m2, m5 ; x[1] + 2048 + REPX {psrad x, 12}, m0, m2, m1, m4 + ret + + +INV_TXFM_4X4_FN flipadst, dct +INV_TXFM_4X4_FN flipadst, adst +INV_TXFM_4X4_FN flipadst, flipadst +INV_TXFM_4X4_FN flipadst, identity + +cglobal iflipadst_4x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + call m(iadst_4x4_internal_16bpc).main + packssdw m0, m2 ; out0 out1 + packssdw m1, m4 ; out2 out3 + ; transpose + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + ; m0 = out0 out1 + ; m1 = out2 out3 + ; m5 = pd_2048 + jmp tx2q +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_4x4_internal_8bpc, _ssse3).main + mova m4, [o(pw_2048)] + movq m3, [dstq+strideq*1] + movhps m3, [dstq+strideq*0] + lea r5, [dstq+strideq*2] + movq m2, [r5 +strideq*1] + movhps m2, [r5 +strideq*0] + mova m5, [o(pixel_10bpc_max)] + pmulhrsw m0, m4 + pmulhrsw m1, m4 + pxor m4, m4 + mova [cq+16*0], m4 + mova [cq+16*1], m4 + mova [cq+16*2], m4 + mova [cq+16*3], m4 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m5 + pminsw m1, m5 + movhps [dstq+strideq*0], m1 + movq [dstq+strideq*1], m1 + movhps [r5 +strideq*0], m0 + movq [r5 +strideq*1], m0 + RET + +INV_TXFM_4X4_FN identity, dct +INV_TXFM_4X4_FN identity, adst +INV_TXFM_4X4_FN identity, flipadst +INV_TXFM_4X4_FN identity, identity + +cglobal iidentity_4x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + mova m3, [o(pd_5793)] + pmulld m0, m3, [cq+16*0] + pmulld m1, m3, [cq+16*1] + pmulld m2, m3, [cq+16*2] + pmulld m3, [cq+16*3] + mova m5, [o(pd_2048)] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + packssdw m0, m1 + packssdw m2, m3 + ; transpose + punpckhwd m3, m0, m2 + punpcklwd m0, m2 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + ; m0 = out0 out1 + ; m1 = out2 out3 + ; m5 = pd_2048 + jmp tx2q +.pass2: + ; m0 = in0 in1 + ; m1 = in2 in3 + ; m5 = pd_2048 + mova m4, [o(pw_1697x8)] + movq m2, [dstq+strideq*0] + movhps m2, [dstq+strideq*1] + lea r5, [dstq+strideq*2] + pmulhrsw m3, m4, m0 + pmulhrsw m4, m1 + paddsw m0, m3 + paddsw m1, m4 + movq m3, [r5 +strideq*0] + movhps m3, [r5 +strideq*1] + mova m4, [o(pixel_10bpc_max)] + packssdw m5, m5 ; pw_2048 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + pxor m5, m5 + mova [cq+16*0], m5 + mova [cq+16*1], m5 + mova [cq+16*2], m5 + mova [cq+16*3], m5 + paddw m0, m2 + paddw m1, m3 + pmaxsw m0, m5 + pmaxsw m1, m5 + pminsw m0, m4 + pminsw m1, m4 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [r5 +strideq*0], m1 + movhps [r5 +strideq*1], m1 + RET + +%macro INV_TXFM_4X8_FN 2-3 0 ; type1, type2, eob_offset + INV_TXFM_FN %1, %2, %3, 4x8 +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 8 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + jmp m(inv_txfm_add_dct_dct_4x4_16bpc).dconly +%endif +%endmacro + +INV_TXFM_4X8_FN dct, dct +INV_TXFM_4X8_FN dct, identity, 9 +INV_TXFM_4X8_FN dct, adst +INV_TXFM_4X8_FN dct, flipadst + +cglobal idct_4x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp + mova m5, [o(pd_2048)] +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 13 + setge r5b +%else + mov r5d, 1 + cmp eobd, 13 + sbb r5d, 0 +%endif + shl r5d, 4 +.loop_pass1: + mova m3, [o(pd_2896)] + pmulld m0, m3, [cq+32*0+r5] + pmulld m1, m3, [cq+32*1+r5] + pmulld m2, m3, [cq+32*2+r5] + pmulld m3, [cq+32*3+r5] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + call m(idct_4x4_internal_16bpc).pass1_main + packssdw m0, m1 ; out0 out1 + packssdw m4, m2 ; out2 out3 + test r5d, r5d + jz .end_pass1 + mova [cq+32*0+16], m0 + mova [cq+32*1+16], m4 + xor r5d, r5d + jmp .loop_pass1 +.end_pass1: + punpckhwd m2, m0, m4 + punpcklwd m0, m4 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + mova m2, [cq+32*0+16] + mova m6, [cq+32*1+16] + punpckhwd m4, m2, m6 + punpcklwd m2, m6 + punpckhwd m3, m2, m4 + punpcklwd m2, m4 + ; m0-3 = packed & transposed output + jmp tx2q +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(idct_4x8_internal_8bpc, _ssse3).main + ; m0-3 is now out0/1,3/2,4/5,7/6 + mova m4, [o(pw_2048)] + shufps m1, m1, q1032 + shufps m3, m3, q1032 +.end: + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + pxor m4, m4 + REPX {mova [cq+16*x], m4}, 0, 1, 2, 3, 4, 5, 6, 7 + mova m7, [o(pixel_10bpc_max)] + lea r2, [strideq*3] + movq m5, [dstq+strideq*0] + movq m6, [dstq+strideq*2] + movhps m5, [dstq+strideq*1] + movhps m6, [dstq+r2] + lea r4, [dstq+strideq*4] + paddw m0, m5 + paddw m1, m6 + movq m5, [r4+strideq*0] + movq m6, [r4+strideq*2] + movhps m5, [r4+strideq*1] + movhps m6, [r4+r2] + paddw m2, m5 + paddw m3, m6 + REPX {pminsw x, m7}, m0, m1, m2, m3 + REPX {pmaxsw x, m4}, m0, m1, m2, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r2 ], m1 + movq [r4 +strideq*0], m2 + movhps [r4 +strideq*1], m2 + movq [r4 +strideq*2], m3 + movhps [r4 +r2 ], m3 + RET + +INV_TXFM_4X8_FN adst, dct +INV_TXFM_4X8_FN adst, adst +INV_TXFM_4X8_FN adst, flipadst +INV_TXFM_4X8_FN adst, identity, 9 + +cglobal iadst_4x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + call .pass1_main + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + mova m2, [cq+32*2+16] + mova m6, [cq+32*3+16] + punpckhwd m4, m2, m6 + punpcklwd m2, m6 + punpckhwd m3, m2, m4 + punpcklwd m2, m4 + ; m0-3 = packed & transposed output + jmp tx2q +.pass1_main: +%undef cmp +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 13 + setge r5b +%else + mov r5d, 1 + cmp eobd, 13 + sbb r5d, 0 +%endif + shl r5d, 4 + lea r3, [cq+32*1+16] +.loop_pass1: + mova m0, [o(pd_2048)] + mova m3, [o(pd_2896)] + pmulld m5, m3, [cq+32*0+r5] + pmulld m2, m3, [cq+32*1+r5] + pmulld m1, m3, [cq+32*2+r5] + pmulld m3, [cq+32*3+r5] + REPX {paddd x, m0}, m5, m2, m1, m3 + REPX {psrad x, 12}, m5, m2, m1, m3 + mova [r3], m2 + call m(iadst_4x4_internal_16bpc).main2 + packssdw m0, m2 ; out0 out1 + packssdw m1, m4 ; out2 out3 + test r5d, r5d + jz .end_pass1 + mova [cq+32*2+16], m0 + mova [cq+32*3+16], m1 + xor r5d, r5d + jmp .loop_pass1 +.end_pass1: + ret +.pass2: + shufps m0, m0, q1032 + shufps m1, m1, q1032 +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_4x8_internal_8bpc, _ssse3).main + mova m4, [o(pw_4x2048_4xm2048)] + jmp m(idct_4x8_internal_16bpc).end + +INV_TXFM_4X8_FN flipadst, dct +INV_TXFM_4X8_FN flipadst, adst +INV_TXFM_4X8_FN flipadst, flipadst +INV_TXFM_4X8_FN flipadst, identity, 9 + +cglobal iflipadst_4x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + call m(iadst_4x8_internal_16bpc).pass1_main + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + mova m6, [cq+32*2+16] + mova m2, [cq+32*3+16] + punpcklwd m4, m2, m6 + punpckhwd m2, m6 + punpckhwd m3, m2, m4 + punpcklwd m2, m4 + ; m0-3 = packed & transposed output + jmp tx2q +.pass2: + shufps m0, m0, q1032 + shufps m1, m1, q1032 +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_4x8_internal_8bpc, _ssse3).main + mova m4, m0 + mova m5, m1 + pshufd m0, m3, q1032 + pshufd m1, m2, q1032 + pshufd m2, m5, q1032 + pshufd m3, m4, q1032 + mova m4, [o(pw_4xm2048_4x2048)] + jmp m(idct_4x8_internal_16bpc).end + +INV_TXFM_4X8_FN identity, dct +INV_TXFM_4X8_FN identity, adst +INV_TXFM_4X8_FN identity, flipadst +INV_TXFM_4X8_FN identity, identity, 3 + +cglobal iidentity_4x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp + mova m5, [o(pd_2048)] + mova m4, [o(pd_2896)] + mova m6, [o(pd_5793)] + ; clear m7 in case we skip the bottom square + pxor m7, m7 +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 16 + setge r5b +%else + mov r5d, 1 + cmp eobd, 16 + sbb r5d, 0 +%endif + shl r5d, 4 +.loop_pass1: + pmulld m0, m4, [cq+32*0+r5] + pmulld m1, m4, [cq+32*1+r5] + pmulld m2, m4, [cq+32*2+r5] + pmulld m3, m4, [cq+32*3+r5] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + REPX {pmulld x, m6}, m0, m1, m2, m3 + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 12}, m0, m1, m2, m3 + packssdw m0, m1 + packssdw m2, m3 + test r5d, r5d + jz .end_pass1 + mova [cq+32*0+16], m0 + mova m7, m2 + xor r5d, r5d + jmp .loop_pass1 +.end_pass1: + punpckhwd m4, m0, m2 + punpcklwd m0, m2 + punpckhwd m1, m0, m4 + punpcklwd m0, m4 + mova m2, [cq+32*0+16] + punpckhwd m4, m2, m7 + punpcklwd m2, m7 + punpckhwd m3, m2, m4 + punpcklwd m2, m4 + ; m0-3 = packed & transposed output + jmp tx2q +.pass2: + mova m4, [o(pw_4096)] + jmp m(idct_4x8_internal_16bpc).end + +%macro INV_TXFM_4X16_FN 2-3 2d ; type1, type2, eob_tbl_suffix + INV_TXFM_FN %1, %2, tbl_4x16_%3, 4x16 +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 16 + add r5d, 384 + sar r5d, 9 + jmp m(inv_txfm_add_dct_dct_4x4_16bpc).dconly2 +%endif +%endmacro + +INV_TXFM_4X16_FN dct, dct +INV_TXFM_4X16_FN dct, identity, v +INV_TXFM_4X16_FN dct, adst +INV_TXFM_4X16_FN dct, flipadst + +cglobal idct_4x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp +%if ARCH_X86_32 + mov r5m, r6d +%endif + mov r6d, 4 +.zero_loop: + dec r6d + cmp eobb, byte [r5+r6] + jl .zero_loop + mov r5d, r6d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, r5m +%endif + mova m5, [o(pd_2048)] +.loop_pass1: + mova m0, [cq+64*0+r5] + mova m1, [cq+64*1+r5] + mova m2, [cq+64*2+r5] + mova m3, [cq+64*3+r5] + call m(idct_4x4_internal_16bpc).pass1_main + pcmpeqd m3, m3 + REPX {psubd x, m3}, m0, m1, m4, m2 + REPX {psrad x, 1}, m0, m1, m4, m2 + packssdw m0, m1 ; out0 out1 + packssdw m4, m2 ; out2 out3 + punpckhwd m2, m0, m4 + punpcklwd m0, m4 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + test r5d, r5d + jz .end_pass1 + mova [cq+64*0+r5], m0 + mova [cq+64*1+r5], m1 + sub r5d, 16 + jmp .loop_pass1 +.end_pass1: + mova m2, [cq+64*0+16] + mova m3, [cq+64*1+16] + mova m4, [cq+64*0+32] + mova m5, [cq+64*1+32] + mova m6, [cq+64*0+48] + mova m7, [cq+64*1+48] + ; m0-7 = packed & transposed output + jmp tx2q +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(idct_16x4_internal_8bpc, _ssse3).main + ; m0-6 is out0-13 [with odd registers having inversed output] + ; [coeffq+16*7] has out15/14 + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [cq+16*7] + REPX {shufps x, x, q1032}, m1, m3, m5, m7 + mova [cq+16*0], m4 + mova [cq+16*1], m5 + mova [cq+16*2], m6 + mova [cq+16*3], m7 +.end: + pxor m4, m4 + REPX {mova [cq+16*x], m4}, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + mova m7, [o(pixel_10bpc_max)] + mov r5d, 2 + lea r3, [strideq*3] +.loop: + movq m5, [dstq+strideq*0] + movq m6, [dstq+strideq*2] + movhps m5, [dstq+strideq*1] + movhps m6, [dstq+r3] + lea r4, [dstq+strideq*4] + paddw m0, m5 + paddw m1, m6 + movq m5, [r4+strideq*0] + movq m6, [r4+strideq*2] + movhps m5, [r4+strideq*1] + movhps m6, [r4+r3] + paddw m2, m5 + paddw m3, m6 + REPX {pminsw x, m7}, m0, m1, m2, m3 + REPX {pmaxsw x, m4}, m0, m1, m2, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+r3 ], m1 + movq [r4 +strideq*0], m2 + movhps [r4 +strideq*1], m2 + movq [r4 +strideq*2], m3 + movhps [r4 +r3 ], m3 + dec r5d + jz .end2 + lea dstq, [dstq+strideq*8] + mova m0, [cq+0*16] + mova m1, [cq+1*16] + mova m2, [cq+2*16] + mova m3, [cq+3*16] + REPX {mova [cq+x*16], m4}, 0, 1, 2, 3 + jmp .loop +.end2: + RET + +INV_TXFM_4X16_FN adst, dct +INV_TXFM_4X16_FN adst, adst +INV_TXFM_4X16_FN adst, flipadst +INV_TXFM_4X16_FN adst, identity, v + +cglobal iadst_4x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp +%if ARCH_X86_32 + mov r5m, r6d +%endif + mov r6d, 4 +.zero_loop: + dec r6d + cmp eobb, byte [r6+r5] + jl .zero_loop + mov r5d, r6d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, r5m +%endif +.loop_pass1: + mova m5, [cq+64*0+r5] + lea r3, [cq+64*1+r5] + mova m1, [cq+64*2+r5] + mova m3, [cq+64*3+r5] + call m(iadst_4x4_internal_16bpc).main2 + pcmpeqd m3, m3 + REPX {psubd x, m3}, m0, m2, m1, m4 + REPX {psrad x, 1}, m0, m2, m1, m4 + packssdw m0, m2 ; out0 out1 + packssdw m1, m4 ; out2 out3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + test r5d, r5d + jz m(idct_4x16_internal_16bpc).end_pass1 + mova [cq+64*0+r5], m0 + mova [cq+64*1+r5], m1 + sub r5d, 16 + jmp .loop_pass1 +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_16x4_internal_8bpc, _ssse3).main + call m_suffix(iadst_16x4_internal_8bpc, _ssse3).main_pass2_end + ; m7/5/2/4 = out4/-11,-5/10,6/-9,-7/8 + ; m0/3 & cq6/7 = out0/-15,-3/12,-1/14,2/-13 + mova m1, [o(pw_4x2048_4xm2048)] + REPX {pmulhrsw x, m1}, m7, m2, m0 + pshufd m6, m1, q1032 ; 4x-2048,4x2048 + pmulhrsw m1, [cq+16*7] + REPX {pmulhrsw x, m6}, m5, m4, m3 + pmulhrsw m6, [cq+16*6] + ; m7/5/2/4 = out4/11,5/10,6/9,7/8 + ; m0/3/6/1 = out0/15,3/12,1/14,2/13 + ; output should be as 0-3 for out0-7, and cq+0-3*16 for out8-15 + movhps [cq+0*8], m4 + movhps [cq+1*8], m2 + movhps [cq+2*8], m5 + movhps [cq+3*8], m7 + movhps [cq+4*8], m3 + movhps [cq+5*8], m1 + movhps [cq+6*8], m6 + movhps [cq+7*8], m0 + punpcklqdq m0, m6 + punpcklqdq m1, m3 + punpcklqdq m3, m2, m4 + punpcklqdq m2, m7, m5 + jmp m(idct_4x16_internal_16bpc).end + +INV_TXFM_4X16_FN flipadst, dct +INV_TXFM_4X16_FN flipadst, adst +INV_TXFM_4X16_FN flipadst, flipadst +INV_TXFM_4X16_FN flipadst, identity, v + +cglobal iflipadst_4x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp +%if ARCH_X86_32 + mov r5m, r6d +%endif + mov r6d, 4 +.zero_loop: + dec r6d + cmp eobb, byte [r5+r6] + jl .zero_loop + mov r5d, r6d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, r5m +%endif +.loop_pass1: + mova m5, [cq+64*0+r5] + lea r3, [cq+64*1+r5] + mova m1, [cq+64*2+r5] + mova m3, [cq+64*3+r5] + call m(iadst_4x4_internal_16bpc).main2 + pcmpeqd m3, m3 + REPX {psubd x, m3}, m0, m2, m1, m4 + REPX {psrad x, 1}, m0, m2, m1, m4 + packssdw m0, m2 ; out3 out2 + packssdw m1, m4 ; out1 out0 + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + test r5d, r5d + jz m(idct_4x16_internal_16bpc).end_pass1 + mova [cq+64*0+r5], m0 + mova [cq+64*1+r5], m1 + sub r5d, 16 + jmp .loop_pass1 +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_16x4_internal_8bpc, _ssse3).main + call m_suffix(iadst_16x4_internal_8bpc, _ssse3).main_pass2_end + ; m7/5/2/4 = out11/-4,-10/5,9/-6,-8/7 + ; m0/3 & cq6/7 = out15/-0,-12/3,-14/1,13/-2 + mova m1, [o(pw_4x2048_4xm2048)] + REPX {pmulhrsw x, m1}, m7, m2, m0 + pshufd m6, m1, q1032 ; 4x-2048,4x2048 + pmulhrsw m1, [cq+16*7] + REPX {pmulhrsw x, m6}, m5, m4, m3 + pmulhrsw m6, [cq+16*6] + ; m7/5/2/4 = out11/4,10/5,9/6,8/7 + ; m0/3/6/1 = out15/0,12/3,14/1,13/2 + ; output should be as 0-3 for out0-7, and cq+0-3*16 for out8-15 + movq [cq+0*8], m4 + movq [cq+1*8], m2 + movq [cq+2*8], m5 + movq [cq+3*8], m7 + movq [cq+4*8], m3 + movq [cq+5*8], m1 + movq [cq+6*8], m6 + movq [cq+7*8], m0 + punpckhqdq m0, m6 + punpckhqdq m1, m3 + punpckhqdq m3, m2, m4 + punpckhqdq m2, m7, m5 + jmp m(idct_4x16_internal_16bpc).end + +INV_TXFM_4X16_FN identity, dct, h +INV_TXFM_4X16_FN identity, adst, h +INV_TXFM_4X16_FN identity, flipadst, h +INV_TXFM_4X16_FN identity, identity + +cglobal iidentity_4x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%undef cmp +%if ARCH_X86_32 + mov r5m, r6d +%endif + mov r6d, 4 +.zero_loop: + dec r6d + cmp eobb, byte [r5+r6] + jl .zero_loop + mov r5d, r6d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, r5m +%endif + mova m5, [o(pd_6144)] + mova m4, [o(pd_5793)] +.loop_pass1: + pmulld m0, m4, [cq+64*0+r5] + pmulld m1, m4, [cq+64*1+r5] + pmulld m2, m4, [cq+64*2+r5] + pmulld m3, m4, [cq+64*3+r5] + REPX {paddd x, m5}, m0, m1, m2, m3 + REPX {psrad x, 13}, m0, m1, m2, m3 + packssdw m0, m1 + packssdw m2, m3 + punpckhwd m3, m0, m2 + punpcklwd m0, m2 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + test r5d, r5d + jz m(idct_4x16_internal_16bpc).end_pass1 + mova [cq+64*0+r5], m0 + mova [cq+64*1+r5], m1 + sub r5d, 16 + jmp .loop_pass1 +.pass2: + mova [cq+16*4], m0 + mova [cq+16*5], m1 + mova [cq+16*6], m2 + mova [cq+16*7], m7 + mova m0, [o(pw_1697x16)] + mova m7, [o(pw_2048)] + pmulhrsw m1, m0, m4 + pmulhrsw m2, m0, m5 + REPX {paddsw x, x}, m4, m5 + paddsw m4, m1 + paddsw m5, m2 + REPX {pmulhrsw x, m7}, m4, m5 + mova [cq+16*0], m4 + mova [cq+16*1], m5 + mova m4, [cq+16*7] + pmulhrsw m1, m0, m6 + pmulhrsw m2, m0, m4 + REPX {paddsw x, x}, m6, m4 + paddsw m6, m1 + paddsw m4, m2 + REPX {pmulhrsw x, m7}, m6, m4 + mova [cq+16*2], m6 + mova [cq+16*3], m4 + mova m4, [cq+16*4] + mova m1, [cq+16*5] + mova m2, [cq+16*6] + pmulhrsw m5, m0, m2 + pmulhrsw m6, m0, m3 + REPX {paddsw x, x}, m2, m3 + paddsw m2, m5 + paddsw m3, m6 + pmulhrsw m6, m0, m1 + pmulhrsw m0, m4 + REPX {paddsw x, x}, m1, m4 + paddsw m1, m6 + paddsw m0, m4 + REPX {pmulhrsw x, m7}, m2, m3, m1, m0 + jmp m(idct_4x16_internal_16bpc).end + +%macro INV_TXFM_8X4_FN 2 ; type1, type2 +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, 0, 8x4, 15 +%else + INV_TXFM_FN %1, %2, 0, 8x4, 8, 0-4*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + add r5d, 128 + sar r5d, 8 + imul r5d, 2896 + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + punpcklqdq m0, m0 + mova m6, [o(pixel_10bpc_max)] + pxor m5, m5 + lea r2, [strideq*3] + mova m1, [dstq+strideq*0] + mova m2, [dstq+strideq*1] + mova m3, [dstq+strideq*2] + mova m4, [dstq+r2] + REPX {paddw x, m0}, m1, m2, m3, m4 + REPX {pmaxsw x, m5}, m1, m2, m3, m4 + REPX {pminsw x, m6}, m1, m2, m3, m4 + mova [dstq+strideq*0], m1 + mova [dstq+strideq*1], m2 + mova [dstq+strideq*2], m3 + mova [dstq+r2 ], m4 + RET +%endif +%endmacro + +INV_TXFM_8X4_FN dct, dct +INV_TXFM_8X4_FN dct, identity +INV_TXFM_8X4_FN dct, adst +INV_TXFM_8X4_FN dct, flipadst + +cglobal idct_8x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + lea r5, [o(.main)] +.pass1_entry: +%if ARCH_X86_32 + lea r3, [rsp+gprsize] +%else + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+0*16] + mova m1, [cq+1*16] + mova m2, [cq+2*16] + mova m3, [cq+3*16] + mova m4, [cq+4*16] + mova m5, [cq+5*16] + mova m6, [cq+6*16] + mova m7, [cq+7*16] + call .rect2_mul + call r5 + call .transpose4x8packed + ; m0-3 = packed & transposed output + jmp tx2q +.transpose4x8packed: + ; transpose + punpcklwd m1, m2, m6 + punpckhwd m2, m6 + punpckhwd m6, m0, m4 + punpcklwd m0, m4 + + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhwd m4, m6, m2 + punpcklwd m6, m2 + + punpcklwd m2, m3, m4 + punpckhwd m3, m4 + punpckhwd m1, m0, m6 + punpcklwd m0, m6 + ret +.main: + call .main_pass1 + call .round + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + ret +.rect2_mul: +%if ARCH_X86_64 + REPX {pmulld x, m14}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 +%else + mova [r3], m7 + mova m7, [o(pd_2896)] + REPX {pmulld x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulld m7, [r3] + mova [r3], m7 + mova m7, [o(pd_2048)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3] +%endif + REPX {psrad x, 12}, m0, m1, m2, m3, m4, m5, m6, m7 + ret +%if ARCH_X86_64 +.main_pass1_fast: + pmulld m5, m3, [o(pd_m2276)] + pmulld m3, [o(pd_3406)] + pmulld m7, m1, [o(pd_4017)] + pmulld m1, [o(pd_799)] + pmulld m6, m2, [o(pd_3784)] + pmulld m2, [o(pd_1567)] + pmulld m0, m14 + pxor m4, m4 + jmp .main_pass1_fast2 +.main_pass1: + ITX_MULSUB_2D 5, 3, 8, 9, 10, _, 3406, 2276 ; t5a t6a + ITX_MULSUB_2D 1, 7, 8, 9, 10, _, 799, 4017 ; t4a t7a + ITX_MULSUB_2D 2, 6, 8, 9, 10, _, 1567, 3784 ; t2 t3 + REPX {pmulld x, m14}, m0, m4 +.main_pass1_fast2: + REPX {paddd x, m11}, m1, m2, m3, m5, m6, m7 + REPX {psrad x, 12 }, m1, m2, m3, m5, m6, m7 + paddd m8, m1, m5 ; t4 + psubd m1, m5 ; t5a + paddd m9, m7, m3 ; t7 + psubd m7, m3 ; t6a + REPX {pmaxsd x, m12}, m1, m8, m7, m9 + REPX {pminsd x, m13}, m1, m8, m7, m9 + REPX {pmulld x, m14}, m7, m1 + paddd m0, m11 + paddd m7, m11 + psubd m5, m0, m4 + paddd m0, m4 + psubd m4, m7, m1 + paddd m7, m1 + REPX {psrad x, 12 }, m5, m0, m4, m7 + psubd m3, m0, m6 ; dct4 out3 + paddd m0, m6 ; dct4 out0 + paddd m6, m5, m2 ; dct4 out1 + psubd m5, m2 ; dct4 out2 + REPX {pmaxsd x, m12}, m0, m6, m5, m3 + REPX {pminsd x, m13}, m0, m6, m5, m3 + ret +.round: + paddd m1, m6, m7 ; out1 + psubd m6, m7 ; out6 + psubd m7, m0, m9 ; out7 + paddd m0, m9 ; out0 + paddd m2, m5, m4 ; out2 + psubd m5, m4 ; out5 + psubd m4, m3, m8 ; out4 + paddd m3, m8 ; out3 +%else +.main_pass1_fast: + pmulld m5, m3, [o(pd_m2276)] + pmulld m3, [o(pd_3406)] + pmulld m7, m1, [o(pd_4017)] + pmulld m1, [o(pd_799)] + pmulld m6, m2, [o(pd_3784)] + pmulld m2, [o(pd_1567)] + mova m4, [o(pd_2048)] + mova [r3+0*16], m2 + REPX {paddd x, m4}, m5, m3, m7, m1 + REPX {psrad x, 12}, m5, m3, m7, m1 + paddd m2, m1, m5 ; t4 + psubd m1, m5 ; t5a + pmulld m5, m0, [o(pd_2896)] + mova m0, m4 + paddd m4, m7, m3 ; t7 + psubd m7, m3 ; t6a + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3 }, m1, m2, m7, m4 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3 }, m1, m2, m7, m4 + mova [r3+3*16], m2 + mova [r3+1*16], m4 + pxor m4, m4 + mova m2, [r3+0*16] + mova m3, [o(pd_2896)] + jmp .main_pass1_fast2 +.main_pass1: + mova [r3+0*16], m0 + mova [r3+1*16], m2 + mova [r3+2*16], m4 + mova [r3+3*16], m6 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 5, 3, 2, 4, 6, 0, 3406, 2276 ; t5a t6a + ITX_MULSUB_2D 1, 7, 2, 4, 6, 0, 799, 4017 ; t4a t7a + paddd m2, m1, m5 ; t4 + psubd m1, m5 ; t5a + paddd m4, m7, m3 ; t7 + psubd m7, m3 ; t6a + mova m6, [o(clip_18b_min)] + REPX {pmaxsd x, m6 }, m1, m2, m7, m4 + mova m6, [o(clip_18b_max)] + REPX {pminsd x, m6 }, m1, m2, m7, m4 + mova m6, [r3+3*16] + mova [r3+3*16], m2 + mova m2, [r3+1*16] + mova [r3+1*16], m4 + + ITX_MULSUB_2D 2, 6, 4, 3, 5, _, 1567, 3784 ; t2 t3 + mova m3, [o(pd_2896)] + mova m5, [r3+0*16] + mova m4, [r3+2*16] + REPX {pmulld x, m3 }, m5, m4 +.main_pass1_fast2: + REPX {paddd x, m0 }, m2, m6 + REPX {psrad x, 12 }, m2, m6 + REPX {pmulld x, m3 }, m7, m1 + paddd m7, m0 + paddd m0, m5 + + psubd m5, m0, m4 + paddd m0, m4 + psubd m4, m7, m1 + paddd m7, m1 + REPX {psrad x, 12 }, m5, m0, m4, m7 + psubd m3, m0, m6 ; dct4 out3 + paddd m0, m6 ; dct4 out0 + paddd m6, m5, m2 ; dct4 out1 + psubd m5, m2 ; dct4 out2 + + mova m1, [o(clip_18b_min)] + REPX {pmaxsd x, m1 }, m0, m6, m5, m3 + mova m1, [o(clip_18b_max)] + REPX {pminsd x, m1 }, m0, m6, m5, m3 + ret +.round: + paddd m1, m6, m7 ; out1 + psubd m6, m7 ; out6 + mova [r3+0*16], m6 + mova m6, [r3+1*16] + psubd m7, m0, m6 ; out7 + paddd m0, m6 ; out0 + paddd m2, m5, m4 ; out2 + psubd m5, m4 ; out5 + mova m6, [r3+3*16] + psubd m4, m3, m6 ; out4 + paddd m3, m6 ; out3 + mova m6, [r3+0*16] +%endif + ret + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(idct_8x4_internal_8bpc, _ssse3).main +.end: + lea r3, [strideq*3] + call .round2_and_write_8x4 + REPX {mova [cq+16*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + RET +.round2_and_write_8x4: + pxor m6, m6 + mova m5, [o(pixel_10bpc_max)] + mova m4, [o(pw_2048)] +.round1_and_write_8x4: + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 +.write_8x4: + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] + paddw m2, [dstq+strideq*2] + paddw m3, [dstq+r3] + REPX {pminsw x, m5}, m0, m1, m2, m3 + REPX {pmaxsw x, m6}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r3 ], m3 + ret + +INV_TXFM_8X4_FN adst, dct +INV_TXFM_8X4_FN adst, adst +INV_TXFM_8X4_FN adst, flipadst +INV_TXFM_8X4_FN adst, identity + +cglobal iadst_8x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + lea r5, [o(.main)] + jmp m(idct_8x4_internal_16bpc).pass1_entry +.main: + call .main_pass1 + call .round + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + ret +.main_pass1: +%if ARCH_X86_64 + ITX_MULSUB_2D 7, 0, 8, 9, 10, 11, 401, 4076 ; t1a, t0a + ITX_MULSUB_2D 1, 6, 8, 9, 10, 11, 3920, 1189 ; t7a, t6a + ITX_MULSUB_2D 5, 2, 8, 9, 10, 11, 1931, 3612 ; t3a, t2a + ITX_MULSUB_2D 3, 4, 8, 9, 10, 11, 3166, 2598 ; t5a, t4a + psubd m8, m2, m6 ; t6 + paddd m2, m6 ; t2 + psubd m6, m0, m4 ; t4 + paddd m0, m4 ; t0 + psubd m4, m5, m1 ; t7 + paddd m5, m1 ; t3 + psubd m1, m7, m3 ; t5 + paddd m7, m3 ; t1 + REPX {pmaxsd x, m12}, m6, m1, m8, m4, m2, m0, m5, m7 + REPX {pminsd x, m13}, m6, m1, m8, m4, m2, m0, m5, m7 + ITX_MULSUB_2D 6, 1, 3, 9, 10, 11, 1567, 3784 ; t5a, t4a + ITX_MULSUB_2D 4, 8, 3, 9, 10, 11, 3784, 10 ; t6a, t7a + psubd m9, m6, m8 ; t7 + paddd m6, m8 ; out6 + mova m8, [o(pd_2896)] + psubd m3, m7, m5 ; t3 + paddd m7, m5 ; -out7 + psubd m5, m0, m2 ; t2 + paddd m0, m2 ; out0 + psubd m2, m1, m4 ; t6 + paddd m1, m4 ; -out1 + REPX {pmaxsd x, m12}, m5, m3, m2, m9 + REPX {pminsd x, m13}, m5, m3, m2, m9 + REPX {pmulld x, m14}, m5, m3, m2, m9 + psubd m4, m5, m3 ; (t2 - t3) * 2896 + paddd m3, m5 ; (t2 + t3) * 2896 + psubd m5, m2, m9 ; (t6 - t7) * 2896 + paddd m2, m9 ; (t6 + t7) * 2896 + ret +.round: + + ; m0=out0,m1=-out1,m6=out6,m7=-out7 + + pcmpeqd m8, m8 + REPX {pxor x, m8 }, m1, m7, m3, m5 + REPX {psubd x, m8 }, m1, m7 + REPX {paddd x, m11}, m2, m3, m4, m5 + REPX {psrad x, 12 }, m2, m3, m4, m5 +%else + mova [r3+0*16], m2 + mova [r3+1*16], m3 + mova [r3+2*16], m4 + mova [r3+3*16], m5 + mova m5, [o(pd_2048)] + + ITX_MULSUB_2D 7, 0, 2, 3, 4, 5, 401, 4076 ; t1a, t0a + ITX_MULSUB_2D 1, 6, 2, 3, 4, 5, 3920, 1189 ; t7a, t6a + mova m2, [r3+0*16] + mova m3, [r3+1*16] + mova m4, [r3+2*16] + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova [r3+2*16], m6 + mova m1, [r3+3*16] + mova [r3+3*16], m7 + ITX_MULSUB_2D 1, 2, 0, 6, 7, 5, 1931, 3612 ; t3a, t2a + ITX_MULSUB_2D 3, 4, 0, 6, 7, 5, 3166, 2598 ; t5a, t4a + mova m0, [r3+0*16] + mova m6, [r3+2*16] + psubd m7, m2, m6 ; t6 + paddd m2, m6 ; t2 + psubd m6, m0, m4 ; t4 + paddd m0, m4 ; t0 + mova [r3+0*16], m7 + mova m5, [r3+1*16] + mova m7, [r3+3*16] + psubd m4, m1, m5 ; t7 + paddd m5, m1 ; t3 + psubd m1, m7, m3 ; t5 + paddd m7, m3 ; t1 + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3 }, m6, m1, m4, m2, m0, m5, m7 + mova [r3+1*16], m7 + mova m7, [o(clip_18b_max)] + pmaxsd m3, [r3+0*16] + REPX {pminsd x, m7 }, m6, m1, m3, m4, m2, m0, m5 + pminsd m7, [r3+1*16] + mova [r3+0*16], m0 + mova [r3+1*16], m2 + mova [r3+2*16], m5 + mova [r3+3*16], m7 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 6, 1, 2, 5, 7, 0, 1567, 3784 ; t5a, t4a + ITX_MULSUB_2D 4, 3, 2, 5, 7, 0, 3784, 7 ; t6a, t7a + mova m5, [r3+2*16] + mova m7, [r3+3*16] + psubd m2, m6, m3 ; t7 + paddd m6, m3 ; out6 + mova [r3+3*16], m6 + mova m0, [r3+0*16] + mova m6, [r3+1*16] + psubd m3, m7, m5 ; t3 + paddd m7, m5 ; -out7 + psubd m5, m0, m6 ; t2 + paddd m0, m6 ; out0 + psubd m6, m1, m4 ; t6 + paddd m1, m4 ; -out1 + mova m4, [o(clip_18b_min)] + REPX {pmaxsd x, m4 }, m5, m3, m6, m2 + mova m4, [o(clip_18b_max)] + REPX {pminsd x, m4 }, m5, m3, m6, m2 + mova m4, [o(pd_2896)] + REPX {pmulld x, m4 }, m5, m3, m6, m2 + psubd m4, m5, m3 ; (t2 - t3) * 2896 + paddd m3, m5 ; (t2 + t3) * 2896 + psubd m5, m6, m2 ; (t6 - t7) * 2896 + paddd m2, m6 ; (t6 + t7) * 2896 + ret +.round: + mova [r3+2*16], m0 + + pcmpeqd m0, m0 + mova m6, [o(pd_2048)] + REPX {pxor x, m0 }, m1, m7, m3, m5 + REPX {psubd x, m0 }, m1, m7 + REPX {paddd x, m6 }, m2, m3, m4, m5 + REPX {psrad x, 12 }, m2, m3, m4, m5 + + mova m6, [r3+3*16] + mova m0, [r3+2*16] +%endif + ret + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_8x4_internal_8bpc, _ssse3).main + jmp m(idct_8x4_internal_16bpc).end + +INV_TXFM_8X4_FN flipadst, dct +INV_TXFM_8X4_FN flipadst, adst +INV_TXFM_8X4_FN flipadst, flipadst +INV_TXFM_8X4_FN flipadst, identity + +cglobal iflipadst_8x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + lea r5, [o(.main)] + jmp m(idct_8x4_internal_16bpc).pass1_entry +.main: + call m(iadst_8x4_internal_16bpc).main_pass1 + call m(iadst_8x4_internal_16bpc).round + packssdw m7, m6 + packssdw m5, m4 + packssdw m3, m2 + packssdw m1, m0 + mova m0, m7 + mova m2, m5 + mova m4, m3 + mova m6, m1 + ret +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_8x4_internal_8bpc, _ssse3).main + lea r3, [strideq*3] + add dstq, r3 + neg strideq + jmp m(idct_8x4_internal_16bpc).end + +INV_TXFM_8X4_FN identity, dct +INV_TXFM_8X4_FN identity, adst +INV_TXFM_8X4_FN identity, flipadst +INV_TXFM_8X4_FN identity, identity + +cglobal iidentity_8x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + lea r5, [o(.main)] + jmp m(idct_8x4_internal_16bpc).pass1_entry +.main: + REPX {paddd x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + ret +.pass2: + mova m7, [o(pw_1697x8)] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(idct_8x4_internal_16bpc).end + +%macro INV_TXFM_8X8_FN 2-3 0 ; type1, type2, eob_offset +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, %3, 8x8, 15, 0-3*16 +%else + INV_TXFM_FN %1, %2, %3, 8x8, 8, 0-5*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 2 +.end: + add r5d, 384 + sar r5d, 9 +.end2: + imul r5d, 2896 + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + punpcklqdq m0, m0 + mova m6, [o(pixel_10bpc_max)] + pxor m5, m5 + lea r2, [strideq*3] +.loop: + mova m1, [dstq+strideq*0] + mova m2, [dstq+strideq*1] + mova m3, [dstq+strideq*2] + mova m4, [dstq+r2] + REPX {paddw x, m0}, m1, m2, m3, m4 + REPX {pmaxsw x, m5}, m1, m2, m3, m4 + REPX {pminsw x, m6}, m1, m2, m3, m4 + mova [dstq+strideq*0], m1 + mova [dstq+strideq*1], m2 + mova [dstq+strideq*2], m3 + mova [dstq+r2 ], m4 + lea dstq, [dstq+strideq*4] + dec r3d + jg .loop + RET +%endif +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, identity, 6 +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst + +cglobal idct_8x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + DECLARE_REG_TMP 1 + mov [rsp+4*16+1*gprsize], r1 +%else + DECLARE_REG_TMP 6 +%endif + lea t0, [o(.pass1_main)] + +.pass1_full: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif +%undef cmp +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 10 + setge r5b +%else + mov r5d, 1 + cmp eobd, 10 + sbb r5d, 0 +%endif + shl r5d, 4 +%if ARCH_X86_32 + lea r3, [rsp+gprsize] +%endif +.loop_pass1: + mova m0, [cq+0*32+r5] + mova m1, [cq+1*32+r5] + mova m2, [cq+2*32+r5] + mova m3, [cq+3*32+r5] + mova m4, [cq+4*32+r5] + mova m5, [cq+5*32+r5] + mova m6, [cq+6*32+r5] + mova m7, [cq+7*32+r5] + call t0 + + test r5d, r5d + jz .end_pass1 + + mova [cq+0*32+16], m0 + mova [cq+1*32+16], m1 + mova [cq+2*32+16], m2 + mova [cq+3*32+16], m3 + + sub r5d, 16 + jmp .loop_pass1 +.end_pass1: + mova m4, [cq+0*32+16] + mova m5, [cq+1*32+16] + mova m6, [cq+2*32+16] + mova m7, [cq+3*32+16] +%if ARCH_X86_32 + mov r1, [rsp+4*16+1*gprsize] +%endif + jmp tx2q +.pass1_main: + call m(idct_8x4_internal_16bpc).main_pass1 + pcmpeqd m1, m1 + REPX {psubd x, m1}, m0, m6, m5, m3 + call m(idct_8x4_internal_16bpc).round + REPX {psrad x, 1 }, m0, m1, m2, m3, m4, m5, m6, m7 +.pack_and_transpose: + packssdw m2, m3 + packssdw m6, m7 + packssdw m0, m1 + packssdw m4, m5 + jmp m(idct_8x4_internal_16bpc).transpose4x8packed + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + lea r3, [strideq*3] +%if ARCH_X86_64 + mova m10, [o(pixel_10bpc_max)] + pxor m9, m9 +%endif + call .round3_and_write_8x8 +.zero: +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+16*x], mzero}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +%undef mzero + RET + + ; round (rounded right-shift by 5) before writing + ; data in m0-7 + ; on x86-64, pw_2048 is in m8 + ; .round1 is for m0-7 + ; .round2 is for m0-6 & [rsp+gprsize*2] + ; .round3 is same, but without using m8 on x86-64 (.round2/3 are identical on x86-32) + ; .round4 is x86-32-only, it is similar to .round2 but with constant already in m7 +%if ARCH_X86_32 +.round1_and_write_8x8: + mova [rsp+gprsize*2], m7 +.round2_and_write_8x8: +%endif +.round3_and_write_8x8: + mova m7, [o(pw_2048)] +%if ARCH_X86_32 +.round4_and_write_8x8: +%endif + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [rsp+gprsize*2] +%if ARCH_X86_64 + jmp .write_8x8 +.round2_and_write_8x8: + mova m7, [rsp+gprsize*2] +.round1_and_write_8x8: + REPX {pmulhrsw x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 +%endif + + ; m0-7 have to-be-written data [pre-rounded] + ; on x86-64, m9-10 contain a zero/pixel_max + ; on x86-32, these are runtime-generated, and [rsp+gprsize*2] is scratch + ; r0,1,3 contain dstq/strideq/stride3q + ; r5 is a scratch register +.write_8x8: + lea r5, [dstq+strideq*4] + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] + paddw m2, [dstq+strideq*2] + paddw m3, [dstq+r3] + paddw m4, [r5 +strideq*0] + paddw m5, [r5 +strideq*1] + paddw m6, [r5 +strideq*2] + paddw m7, [r5 +r3] +%if ARCH_X86_64 + REPX {pmaxsw x, m9 }, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsw x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 +%else + mova [rsp+gprsize*2], m7 + pxor m7, m7 + REPX {pmaxsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmaxsw m7, [rsp+gprsize*2] + mova [rsp+gprsize*2], m7 + mova m7, [o(pixel_10bpc_max)] + REPX {pminsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pminsw m7, [rsp+gprsize*2] +%endif + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r3 ], m3 + mova [r5 +strideq*0], m4 + mova [r5 +strideq*1], m5 + mova [r5 +strideq*2], m6 + mova [r5 +r3 ], m7 + ret + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, adst +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity, 6 + +cglobal iadst_8x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + mov [rsp+4*16+1*gprsize], r1 +%endif + lea t0, [o(.pass1_main)] + jmp m(idct_8x8_internal_16bpc).pass1_full +.pass1_main: + call m(iadst_8x4_internal_16bpc).main_pass1 + call .round + jmp m(idct_8x8_internal_16bpc).pack_and_transpose +.round: +%if ARCH_X86_64 + pcmpeqd m8, m8 ; -1 + REPX {psubd x, m8 }, m0, m6 + REPX {pxor x, m8 }, m1, m7, m3, m5 + REPX {psrad x, 1 }, m0, m1, m6, m7 + REPX {psubd x, m8 }, m1, m7 + mova m8, [o(pd_6144)] + REPX {paddd x, m8 }, m2, m3, m4, m5 + REPX {psrad x, 13 }, m2, m3, m4, m5 +%else + mova [r3+2*16], m0 + + pcmpeqd m0, m0 ; -1 + mova m6, [o(pd_6144)] + REPX {pxor x, m0 }, m1, m7, m3, m5 + REPX {psrad x, 1 }, m1, m7 + REPX {psubd x, m0 }, m1, m7 + REPX {paddd x, m6 }, m2, m3, m4, m5 + REPX {psrad x, 13 }, m2, m3, m4, m5 + + mova m0, [r3+2*16] + psrld m6, 12 ; +1 + paddd m0, m6 + paddd m6, [r3+3*16] + REPX {psrad x, 1 }, m0, m6 +%endif + ret + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_8x8_internal_8bpc, _ssse3).main + call m_suffix(iadst_8x8_internal_8bpc, _ssse3).main_pass2_end + lea r3, [strideq*3] +%if ARCH_X86_64 + mova m10, [o(pixel_10bpc_max)] + pxor m9, m9 +%endif + call .round3_and_write_8x8 + jmp m(idct_8x8_internal_16bpc).zero + + ; round (rounded right-shift by 5) before writing; odd registers are negated + ; data in m0-7 + ; on x86-64, pw_2048 is in m8 and pw_m2048 is in m11 + ; .round1 is for m0-7 + ; .round2 is for m0-6 & [rsp+gprsize*2] + ; .round3 is same, but without using m8 on x86-64 (.round2/3 are identical on x86-32) +%if ARCH_X86_64 +.round2_and_write_8x8: + mova m7, [rsp+gprsize*2] +.round1_and_write_8x8: + REPX {pmulhrsw x, m8 }, m0, m2, m4, m6 + REPX {pmulhrsw x, m11}, m1, m3, m5, m7 + jmp m(idct_8x8_internal_16bpc).write_8x8 +%else +.round1_and_write_8x8: + mova [rsp+gprsize*2], m7 +.round2_and_write_8x8: +%endif +.round3_and_write_8x8: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova m7, [o(pw_m2048)] + REPX {pmulhrsw x, m7}, m1, m3, m5 + pmulhrsw m7, [rsp+gprsize*2] + jmp m(idct_8x8_internal_16bpc).write_8x8 + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, flipadst +INV_TXFM_8X8_FN flipadst, identity, 6 + +cglobal iflipadst_8x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + mov [rsp+4*16+1*gprsize], r1 +%endif + lea t0, [o(.pass1_main)] + jmp m(idct_8x8_internal_16bpc).pass1_full +.pass1_main: + call m(iadst_8x4_internal_16bpc).main_pass1 + call m(iadst_8x8_internal_16bpc).round + ; invert registers + packssdw m7, m6 + packssdw m5, m4 + packssdw m3, m2 + packssdw m1, m0 + mova m0, m7 + mova m2, m5 + mova m4, m3 + mova m6, m1 + jmp m(idct_8x4_internal_16bpc).transpose4x8packed + +.pass2: + lea dstq, [dstq+strideq*8] + sub dstq, strideq + neg strideq + jmp m(iadst_8x8_internal_16bpc).pass2 + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + mova m0, [cq+0*32] + mova m1, [cq+1*32] + mova m2, [cq+2*32] + mova m3, [cq+3*32] + mova m4, [cq+4*32] + mova m5, [cq+5*32] + mova m6, [cq+6*32] + mova m7, [cq+7*32] + packssdw m0, [cq+0*32+16] + packssdw m1, [cq+1*32+16] + packssdw m2, [cq+2*32+16] + packssdw m3, [cq+3*32+16] + packssdw m4, [cq+4*32+16] + packssdw m5, [cq+5*32+16] + packssdw m6, [cq+6*32+16] + packssdw m7, [cq+7*32+16] + mova [rsp+gprsize+16*1], m6 + jmp m_suffix(idct_8x8_internal_8bpc, _ssse3).pass1_end3 + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + lea r3, [strideq*3] +%if ARCH_X86_64 + mova m10, [o(pixel_10bpc_max)] + pxor m9, m9 + mova m8, [o(pw_4096)] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 +%else + mova [rsp+gprsize], m7 + mova m7, [o(pw_4096)] + call m(idct_8x8_internal_16bpc).round4_and_write_8x8 +%endif + jmp m(idct_8x8_internal_16bpc).zero + +%macro INV_TXFM_8X16_FN 2-3 2d ; type1, type2, eob_tbl_suffix +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, tbl_8x16_%3, 8x16, 15, 0-16*16 +%else + INV_TXFM_FN %1, %2, tbl_8x16_%3, 8x16, 8, 0-17*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + mov r3d, 4 +%if stack_size_padded > 0 + ; adjust to caller's stack allocation + add rsp, (12+ARCH_X86_64)*16 +%endif + jmp m(inv_txfm_add_dct_dct_8x8_16bpc).end +%endif +%endmacro + +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, identity, v +INV_TXFM_8X16_FN dct, adst +INV_TXFM_8X16_FN dct, flipadst + +%if ARCH_X86_64 +DECLARE_REG_TMP 7 +%endif + +cglobal idct_8x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + PUSH r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(m(idct_8x8_internal_16bpc).pass1_main)] +.pass1_full: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif +%undef cmp + mov r6d, 4 +.zero_loop: + dec r6d + cmp eobb, byte [r5+r6] + jl .zero_loop + mov r5d, r6d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, [rsp+16*16+2*gprsize] + ; setup stack pointer + lea r3, [rsp+gprsize] +%endif +.loop_pass1: + mova m0, [cq+0*64+r5] + mova m1, [cq+1*64+r5] + mova m2, [cq+2*64+r5] + mova m3, [cq+3*64+r5] + mova m4, [cq+4*64+r5] + mova m5, [cq+5*64+r5] + mova m6, [cq+6*64+r5] + mova m7, [cq+7*64+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + call t0 + + mova [cq+0*64+r5], m0 + mova [cq+1*64+r5], m1 + mova [cq+2*64+r5], m2 + mova [cq+3*64+r5], m3 + sub r5d, 16 + jge .loop_pass1 +%if WIN64 + POP r7 +%elif ARCH_X86_32 + mov r1, [rsp+16*16+1*gprsize] +%endif + jmp tx2q + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + + ; input is in cqN*16, where N=0/4/8/12/1/5/9/13/2/6/10/14/3/7/11/15 + ; some are still pre-loaded from the final loop iteration in pass=1 + + mova m1, m2 + mova m2, [cq+ 1*16] + mova m3, [cq+ 9*16] + mova m4, [cq+ 2*16] + mova m5, [cq+10*16] + mova m6, [cq+ 3*16] + mova m7, [cq+11*16] + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + mova [rsp+gprsize+3*16], m0 + mova [rsp+gprsize+4*16], m1 + mova [rsp+gprsize+5*16], m2 + mova [rsp+gprsize+6*16], m3 + mova [rsp+gprsize+7*16], m4 + mova [rsp+gprsize+8*16], m5 + mova [rsp+gprsize+9*16], m6 + ; m7 is already stored in [rsp+gprsize+0*16] + mova m0, [cq+ 4*16] + mova m1, [cq+12*16] + mova m2, [cq+ 5*16] + mova m3, [cq+13*16] + mova m4, [cq+ 6*16] + mova m5, [cq+14*16] + mova m6, [cq+ 7*16] + mova m7, [cq+15*16] + call m_suffix(idct_16x8_internal_8bpc, _ssse3).main + + ; out0-7 is in rsp+gprsize+3-10*mmsize + ; out8-14 is in m0-6, and out15 is in m7 as well as rsp+gprsize+0*mmsize + +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + mova m10, [o(pixel_10bpc_max)] + pxor m9, m9 + mov r6, dstq +%else + mov [rsp+16*16+gprsize*1], dstq +%endif + lea r3, [strideq*3] + lea dstq, [dstq+strideq*8] + call m(idct_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +%undef mzero + mova m0, [rsp+gprsize+ 3*16] + mova m1, [rsp+gprsize+ 4*16] + mova m2, [rsp+gprsize+ 5*16] + mova m3, [rsp+gprsize+ 6*16] + mova m4, [rsp+gprsize+ 7*16] + mova m5, [rsp+gprsize+ 8*16] + mova m6, [rsp+gprsize+ 9*16] + mova m7, [rsp+gprsize+10*16] +%if ARCH_X86_64 + mov dstq, r6 +%else + mov dstq, [rsp+16*16+gprsize*1] +%endif + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + RET + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, adst +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, identity, v + +cglobal iadst_8x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + PUSH r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(m(iadst_8x8_internal_16bpc).pass1_main)] + jmp m(idct_8x16_internal_16bpc).pass1_full + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + mova m4, [cq+ 9*16] + mova m5, [cq+13*16] + mova [rsp+gprsize+7*16], m0 + mova [rsp+gprsize+8*16], m1 + mova [rsp+gprsize+5*16], m4 + mova [rsp+gprsize+6*16], m5 + mova m0, m2 + mova m1, m3 + mova m2, [cq+ 1*16] + mova m3, [cq+ 5*16] + mova m4, [cq+ 2*16] + mova m5, [cq+ 6*16] + mova m6, [cq+11*16] + mova m7, [cq+15*16] + mova [rsp+gprsize+ 3*16], m4 + mova [rsp+gprsize+ 4*16], m5 + mova [rsp+gprsize+ 9*16], m6 + mova [rsp+gprsize+10*16], m7 + mova m4, [cq+10*16] + mova m5, [cq+14*16] + mova m6, [cq+ 3*16] + mova m7, [cq+ 7*16] + call m_suffix(iadst_16x8_internal_8bpc, _ssse3).main + call m_suffix(iadst_16x8_internal_8bpc, _ssse3).main_pass2_end + +%if ARCH_X86_64 + mova m11, [o(pw_m2048)] + mova m8, [o(pw_2048)] + mova m10, [o(pixel_10bpc_max)] + pxor m9, m9 + mov r6, dstq +%else + mov [rsp+16*16+gprsize*1], dstq +%endif + lea r3, [strideq*3] + lea dstq, [dstq+strideq*8] + call m(iadst_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +%undef mzero + mova m0, [rsp+gprsize+ 3*16] + mova m1, [rsp+gprsize+ 4*16] + mova m2, [rsp+gprsize+ 5*16] + mova m3, [rsp+gprsize+ 6*16] + mova m4, [rsp+gprsize+ 7*16] + mova m5, [rsp+gprsize+ 8*16] + mova m6, [rsp+gprsize+ 9*16] + mova m7, [rsp+gprsize+10*16] +%if ARCH_X86_64 + mov dstq, r6 +%else + mov dstq, [rsp+16*16+gprsize*1] +%endif + call m(iadst_8x8_internal_16bpc).round1_and_write_8x8 + RET + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst +INV_TXFM_8X16_FN flipadst, identity, v + +cglobal iflipadst_8x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + PUSH r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(m(iflipadst_8x8_internal_16bpc).pass1_main)] + jmp m(idct_8x16_internal_16bpc).pass1_full + +.pass2: + lea r3, [strideq*3] + lea r3, [r3*5] + add dstq, r3 + neg strideq + jmp m(iadst_8x16_internal_16bpc).pass2 + +INV_TXFM_8X16_FN identity, dct, h +INV_TXFM_8X16_FN identity, adst, h +INV_TXFM_8X16_FN identity, flipadst, h +INV_TXFM_8X16_FN identity, identity + +cglobal iidentity_8x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + PUSH r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(m(idct_8x8_internal_16bpc).pack_and_transpose)] + jmp m(idct_8x16_internal_16bpc).pass1_full + +.pass2: +%if ARCH_X86_64 + mova m4, [o(pw_2048)] + mova m5, [o(pixel_10bpc_max)] + pxor m6, m6 + mova m7, [o(pw_1697x16)] +%endif + mov r5d, 4 + lea r3, [strideq*3] +.pass2_loop: + call .main +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).round1_and_write_8x4 +%else + call m(idct_8x4_internal_16bpc).round2_and_write_8x4 +%endif + REPX {mova [cq+x*16], m6}, 0, 4, 8, 12, 16, 20, 24, 28 + dec r5d + jle .end + add cq, 16 + lea dstq, [dstq+strideq*4] + mova m0, [cq+ 0*16] + mova m1, [cq+ 4*16] + mova m2, [cq+ 8*16] + mova m3, [cq+12*16] + jmp .pass2_loop +.end: + RET +.main: + ; y = pmulhrsw(x, pw_1697x16); x = paddsw(x, x); x = paddsw(x, y) +%if ARCH_X86_32 + mova m7, [o(pw_1697x16)] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 +%else + pmulhrsw m8, m7, m0 + pmulhrsw m9, m7, m1 + pmulhrsw m10, m7, m2 + pmulhrsw m11, m7, m3 +%endif + REPX {paddsw x, x}, m0, m1, m2, m3 +%if ARCH_X86_64 + paddsw m0, m8 + paddsw m1, m9 + paddsw m2, m10 + paddsw m3, m11 +%else + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 +%endif + ret + +%macro INV_TXFM_16X4_FN 2 ; type1, type2 +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, 0, 16x4, 16, 0-8*16 +%else + INV_TXFM_FN %1, %2, 0, 16x4, 8, 0-12*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 4 +.dconly: + add r5d, 384 + sar r5d, 9 +.dconly2: + imul r5d, 2896 + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + punpcklqdq m0, m0 + mova m3, [o(pixel_10bpc_max)] + pxor m4, m4 +.loop: + mova m1, [dstq+ 0] + mova m2, [dstq+16] + REPX {paddw x, m0}, m1, m2 + REPX {pminsw x, m3}, m1, m2 + REPX {pmaxsw x, m4}, m1, m2 + mova [dstq+ 0], m1 + mova [dstq+16], m2 + add dstq, strideq + dec r3d + jg .loop + RET +%endif +%endmacro + +INV_TXFM_16X4_FN dct, dct +INV_TXFM_16X4_FN dct, identity +INV_TXFM_16X4_FN dct, adst +INV_TXFM_16X4_FN dct, flipadst + +cglobal idct_16x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + ; setup stack pointer + lea r3, [rsp+gprsize] + + mova m0, [cq+ 1*16] + mova m1, [cq+ 3*16] + mova m2, [cq+ 5*16] + mova m3, [cq+ 7*16] + mova m4, [cq+ 9*16] + mova m5, [cq+11*16] + mova m6, [cq+13*16] + mova m7, [cq+15*16] + call .main_oddhalf + mova m0, [cq+ 0*16] + mova m1, [cq+ 2*16] + mova m2, [cq+ 4*16] + mova m3, [cq+ 6*16] + mova m4, [cq+ 8*16] + mova m5, [cq+10*16] + mova m6, [cq+12*16] + mova m7, [cq+14*16] + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + ; t0-7 is in m0-7 + + call .round + +%if ARCH_X86_64 +.pack_transpose: + ; transpose in two parts + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +.transpose: + call m(idct_8x4_internal_16bpc).transpose4x8packed + call .transpose4x8packed_hi +%else + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova [r3+2*16], m2 + mova [r3+3*16], m3 + mova m0, [r3+ 8*16] + mova m2, [r3+ 9*16] + mova m4, [r3+10*16] + mova m6, [r3+11*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + jmp tx2q +%if ARCH_X86_64 +.transpose4x8packed_hi: + punpcklwd m9, m10, m14 + punpckhwd m10, m14 + punpckhwd m14, m8, m12 + punpcklwd m8, m12 + + punpckhwd m11, m8, m9 + punpcklwd m8, m9 + punpckhwd m12, m14, m10 + punpcklwd m14, m10 + + punpcklwd m10, m11, m12 + punpckhwd m11, m12 + punpckhwd m9, m8, m14 + punpcklwd m8, m14 + ret +%endif +.main_oddhalf_fast: ; lower half zero + pmulld m7, m0, [o(pd_4076)] + pmulld m0, [o(pd_401)] + pmulld m6, m1, [o(pd_m1189)] + pmulld m1, [o(pd_3920)] +%if ARCH_X86_32 + mova m4, [o(pd_2048)] + REPX {paddd x, m4}, m1, m6 + REPX {psrad x, 12}, m1, m6 + mova [r3+1*16], m1 +%endif + pmulld m5, m2, [o(pd_3612)] + pmulld m2, [o(pd_1931)] +%if ARCH_X86_32 + pmulld m1, m3, [o(pd_m2598)] +%else + pmulld m4, m3, [o(pd_m2598)] +%endif + pmulld m3, [o(pd_3166)] + jmp .main_oddhalf_fast2 +.main_oddhalf: +%if ARCH_X86_64 + ITX_MULSUB_2D 0, 7, 8, 9, 10, _, 401, 4076 ; t8a, t15a + ITX_MULSUB_2D 6, 1, 8, 9, 10, _, 3920, 1189 ; t11a, t12a + ITX_MULSUB_2D 2, 5, 8, 9, 10, _, 1931, 3612 ; t10a, t13a + ITX_MULSUB_2D 4, 3, 8, 9, 10, _, 3166, 2598 ; t9a, t14a +.main_oddhalf_fast2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m8, m0, m4 ; t9 + paddd m0, m4 ; t8 + psubd m4, m6, m2 ; t10 + paddd m2, m6 ; t11 + psubd m6, m1, m5 ; t13 + paddd m5, m1 ; t12 + psubd m1, m7, m3 ; t14 + paddd m7, m3 ; t15 + REPX {pmaxsd x, m12}, m8, m1, m4, m6, m0, m2, m5, m7 + REPX {pminsd x, m13}, m8, m1, m4, m6, m0, m2, m5, m7 + mova m15, [o(pd_3784)] + mova m10, [o(pd_1567)] + ITX_MULSUB_2D 1, 8, 3, 9, _, 11, 10, 15 + ITX_MULSUB_2D 6, 4, 3, 9, _, 11, 10, 15, 4 + psubd m3, m1, m4 ; t10 + paddd m1, m4 ; t9 + psubd m4, m0, m2 ; t11a + paddd m0, m2 ; t8a + psubd m2, m8, m6 ; t13 + paddd m6, m8 ; t14 + psubd m8, m7, m5 ; t12a + paddd m7, m5 ; t15a + REPX {pmaxsd x, m12}, m2, m8, m3, m4, m0, m1, m6, m7 + REPX {pminsd x, m13}, m2, m8, m3, m4, m0, m1, m6, m7 + REPX {pmulld x, m14}, m2, m8, m3, m4 + paddd m2, m11 + paddd m8, m11 + paddd m5, m2, m3 ; t13a + psubd m2, m3 ; t10a + psubd m3, m8, m4 ; t11 + paddd m4, m8 ; t12 + REPX {psrad x, 12}, m5, m2, m3, m4 + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova [r3+2*16], m2 + mova [r3+3*16], m3 + mova [r3+4*16], m4 + mova [r3+5*16], m5 + mova [r3+6*16], m6 + mova [r3+7*16], m7 +%else + mova [r3+0*16], m2 + mova [r3+1*16], m3 + mova [r3+2*16], m4 + mova [r3+3*16], m5 + mova m4, [o(pd_2048)] + + ITX_MULSUB_2D 0, 7, 2, 3, 5, _, 401, 4076 ; t8a, t15a + ITX_MULSUB_2D 6, 1, 2, 3, 5, 4, 3920, 1189 ; t11a, t12a + + mova m2, [r3+0*16] + mova m3, [r3+1*16] + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova m1, [r3+2*16] + mova m5, [r3+3*16] + mova [r3+2*16], m6 + mova [r3+3*16], m7 + + ITX_MULSUB_2D 2, 5, 0, 6, 7, _, 1931, 3612 ; t10a, t13a + ITX_MULSUB_2D 1, 3, 0, 6, 7, _, 3166, 2598 ; t9a, t14a + + mova m0, [r3+0*16] + mova m6, [r3+2*16] + mova m7, [r3+3*16] +.main_oddhalf_fast2: + REPX {paddd x, m4}, m0, m7, m2, m5, m1, m3 + REPX {psrad x, 12}, m0, m7, m2, m5, m1, m3 + psubd m4, m0, m1 ; t9 + paddd m0, m1 ; t8 + mova m1, [r3+1*16] + mova [r3+0*16], m4 + psubd m4, m6, m2 ; t10 + paddd m2, m6 ; t11 + psubd m6, m1, m5 ; t13 + paddd m5, m1 ; t12 + psubd m1, m7, m3 ; t14 + paddd m7, m3 ; t15 + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m1, m4, m6, m0, m2, m5, m7 + pmaxsd m3, [r3+0*16] + mova [r3+0*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m1, m4, m6, m0, m2, m5, m7 + pminsd m3, [r3+0*16] + mova [r3+0*16], m0 + mova [r3+1*16], m2 + mova [r3+2*16], m5 + mova [r3+3*16], m7 + mova m7, [o(pd_2048)] + ITX_MULSUB_2D 1, 3, 0, 2, 5, 7, 1567, 3784 + ITX_MULSUB_2D 6, 4, 0, 2, _, 7, 5, 3784, 4 + mova m0, [r3+0*16] + mova m2, [r3+1*16] + psubd m5, m1, m4 ; t10 + mova [r3+1*16], m5 + paddd m1, m4 ; t9 + psubd m4, m0, m2 ; t11a + paddd m0, m2 ; t8a + mova m5, [r3+2*16] + mova m7, [r3+3*16] + psubd m2, m3, m6 ; t13 + paddd m6, m3 ; t14 + paddd m3, m7, m5 ; t15a + psubd m7, m5 ; t12a + mova [r3+0*16], m3 + mova m3, [r3+1*16] + mova m5, [o(clip_18b_min)] + REPX {pmaxsd x, m5}, m2, m7, m3, m4, m0, m1, m6 + pmaxsd m5, [r3+0*16] + mova [r3+0*16], m5 + mova m5, [o(clip_18b_max)] + REPX {pminsd x, m5}, m2, m7, m3, m4, m0, m1, m6 + pminsd m5, [r3+0*16] + mova [r3+0*16], m5 + mova m5, [o(pd_2896)] + REPX {pmulld x, m5}, m2, m7, m3, m4 + mova m5, [o(pd_2048)] + REPX {paddd x, m5}, m2, m7 + paddd m5, m2, m3 ; t13a + psubd m2, m3 ; t10a + psubd m3, m7, m4 ; t11 + paddd m4, m7 ; t12 + REPX {psrad x, 12}, m5, m2, m3, m4 + mova m7, [r3+0*16] + mova [r3+11*16], m0 + mova [r3+10*16], m1 + mova [r3+9*16], m2 + mova [r3+8*16], m3 + mova [r3+7*16], m4 + mova [r3+6*16], m5 + mova [r3+5*16], m6 + mova [r3+4*16], m7 +%endif + ret +.round: +%if ARCH_X86_64 + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + pcmpeqd m8, m8 + REPX {psubd x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + mova m8, [r3+1*16] + mova m9, [r3+2*16] + mova m10, [r3+3*16] + mova m11, [r3+4*16] + mova m12, [r3+5*16] + mova m13, [r3+6*16] + mova m14, [r3+7*16] + psubd m15, m0, m14 ; out15 + paddd m0, m14 ; out0 + psubd m14, m1, m13 ; out14 + paddd m1, m13 ; out1 + psubd m13, m2, m12 ; out13 + paddd m2, m12 ; out2 + psubd m12, m3, m11 ; out12 + paddd m3, m11 ; out3 + psubd m11, m4, m10 ; out11 + paddd m4, m10 ; out4 + psubd m10, m5, m9 ; out10 + paddd m5, m9 ; out5 + psubd m9, m6, m8 ; out9 + paddd m6, m8 ; out6 + psubd m8, m7, [r3+0*16] ; out8 + paddd m7, [r3+0*16] ; out7 + REPX {psrad x, 1}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + ; and out0-15 is now in m0-15 +%else + mova [r3+ 0*16], m0 + mova m0, [o(clip_18b_min)] + REPX {pmaxsd x, m0}, m1, m2, m3, m4, m5, m6, m7 + pmaxsd m0, [r3+ 0*16] + mova [r3+ 0*16], m7 + mova m7, [o(clip_18b_max)] + REPX {pminsd x, m7}, m0, m1, m2, m3, m4, m5, m6 + pminsd m7, [r3+ 0*16] + mova [r3+ 0*16], m0 + pcmpeqd m0, m0 + REPX {psubd x, m0}, m1, m2, m3, m4, m5, m6, m7 + mova [r3+ 1*16], m1 + mova [r3+ 2*16], m2 + mova m1, [r3+ 0*16] + psubd m1, m0 + mova [r3+ 0*16], m1 + mova m1, [r3+11*16] + mova m2, [r3+10*16] + psubd m0, m7, m1 + paddd m7, m1 + psubd m1, m6, m2 + paddd m6, m2 + REPX {psrad x, 1}, m0, m1, m6, m7 + packssdw m0, m1 ; out8-9 + packssdw m6, m7 ; out6-7 + mova [r3+11*16], m6 + mova m1, [r3+9*16] + mova m7, [r3+8*16] + psubd m2, m5, m1 + paddd m5, m1 + psubd m1, m4, m7 + paddd m4, m7 + REPX {psrad x, 1}, m2, m1, m4, m5 + packssdw m2, m1 ; out10-11 + packssdw m4, m5 ; out4-5 + mova m1, [r3+2*16] + mova [r3+10*16], m4 + mova m6, [r3+7*16] + mova m7, [r3+6*16] + psubd m4, m3, m6 + paddd m3, m6 + psubd m6, m1, m7 + paddd m1, m7 + REPX {psrad x, 1}, m4, m6, m1, m3 + packssdw m4, m6 ; out12-13 + packssdw m1, m3 ; out2-3 + mova m3, [r3+1*16] + mova [r3+9*16], m1 + mova m1, [r3+0*16] + mova m5, [r3+5*16] + mova m7, [r3+4*16] + psubd m6, m3, m5 + paddd m3, m5 + psubd m5, m1, m7 + paddd m1, m7 + REPX {psrad x, 1}, m6, m5, m1, m3 + packssdw m6, m5 ; out14-15 + packssdw m1, m3 ; out0-1 + mova [r3+8*16], m1 +%endif + ret + +.pass2: + lea r4, [o(m_suffix(idct_8x4_internal_8bpc, _ssse3).main)] +.pass2_loop: + lea r3, [strideq*3] +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call r4 + call m(idct_8x4_internal_16bpc).round2_and_write_8x4 + REPX {mova [cq+x*16], m6}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +%if ARCH_X86_64 + mova m0, m8 + mova m1, m9 + mova m2, m10 + mova m3, m11 +%else + mova m0, [rsp+gprsize+0*16] + mova m1, [rsp+gprsize+1*16] + mova m2, [rsp+gprsize+2*16] + mova m3, [rsp+gprsize+3*16] +%endif + add dstq, 16 +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call r4 + call m(idct_8x4_internal_16bpc).round2_and_write_8x4 + RET + +INV_TXFM_16X4_FN adst, dct +INV_TXFM_16X4_FN adst, adst +INV_TXFM_16X4_FN adst, flipadst +INV_TXFM_16X4_FN adst, identity + +cglobal iadst_16x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + ; setup stack pointer + lea r3, [rsp+gprsize] + call .main +%if ARCH_X86_64 + jmp m(idct_16x4_internal_16bpc).pack_transpose +%else + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+gprsize+0*16], m0 + mova [rsp+gprsize+1*16], m1 + mova [rsp+gprsize+2*16], m2 + mova [rsp+gprsize+3*16], m3 + mova m0, [rsp+gprsize+ 8*16] + mova m2, [rsp+gprsize+ 9*16] + mova m4, [rsp+gprsize+10*16] + mova m6, [rsp+gprsize+11*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + jmp tx2q +%endif + +.main: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 2*16] + mova m1, [cq+13*16] + mova m2, [cq+ 6*16] + mova m3, [cq+ 9*16] + mova m4, [cq+10*16] + mova m5, [cq+ 5*16] + mova m6, [cq+14*16] + mova m7, [cq+ 1*16] + call .main_part1 + mova m0, [cq+ 0*16] + mova m1, [cq+15*16] + mova m2, [cq+ 4*16] + mova m3, [cq+11*16] + mova m4, [cq+ 8*16] + mova m5, [cq+ 7*16] + mova m6, [cq+12*16] + mova m7, [cq+ 3*16] + call .main_part2 +.round: +%if ARCH_X86_64 + mova m15, [o(pd_6144)] + psrld m14, 11 ; pd_1 + pcmpeqd m8, m8 ; -1 + psubd m13, m15, m14 ; pd_6143 + REPX {paddd x, m14}, m0, m2 + REPX {paddd x, m15}, m4, m6 + REPX {pxor x, m8 }, m1, m3, m5, m7 + REPX {psrad x, 1 }, m1, m3 + REPX {paddd x, m15}, m5, m7 + REPX {psubd x, m8 }, m1, m3 + paddd m8, m15, m9 + psubd m9, m13, m10 + paddd m10, m15, m11 + psubd m11, m13, m12 + paddd m12, m14, [r3+3*16] + psubd m13, m14, [r3+2*16] + psubd m15, m14, [r3+0*16] + paddd m14, [r3+1*16] + REPX {psrad x, 1 }, m0, m2, m12, m13, m14, m15 + REPX {psrad x, 13}, m4, m5, m6, m7, m8, m9, m10, m11 +%else + mova [r3+8*16], m1 + mova [r3+9*16], m3 + mova m3, [o(pd_6144)] + pcmpeqd m1, m1 + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m4, m5, m6, m7 + REPX {psrad x, 13}, m4, m5, m6, m7 + packssdw m4, m5 + packssdw m6, m7 + mova [r3+10*16], m4 + mova [r3+11*16], m6 + mova m4, [r3+4*16] + mova m5, [r3+5*16] + mova m6, [r3+6*16] + mova m7, [r3+7*16] + REPX {pxor x, m1}, m5, m7 + REPX {psubd x, m1}, m4, m6 + REPX {psrad x, 1 }, m4, m5, m6, m7 + REPX {psubd x, m1}, m5, m7 + packssdw m4, m5 + packssdw m6, m7 + mova m5, [r3+8*16] + mova m7, [r3+9*16] + mova [r3+8*16], m4 + mova [r3+9*16], m6 + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m0, m5, m2, m7 + REPX {psrad x, 13}, m0, m5, m2, m7 + packssdw m0, m5 + packssdw m2, m7 + mova m4, [r3+0*16] + mova m5, [r3+1*16] + mova m6, [r3+2*16] + mova m7, [r3+3*16] + REPX {psubd x, m1}, m4, m6 + REPX {pxor x, m1}, m5, m7 + REPX {psrad x, 1 }, m4, m5, m6, m7 + REPX {psubd x, m1}, m5, m7 + packssdw m4, m5 + packssdw m6, m7 +%endif + ret + +.main_part2: +%if ARCH_X86_64 + ITX_MULSUB_2D 1, 0, 8, 9, 10, 11, 201, 4091 + ITX_MULSUB_2D 3, 2, 8, 9, 10, 11, 1751, 3703 + ITX_MULSUB_2D 5, 4, 8, 9, 10, 11, 3035, 2751 + ITX_MULSUB_2D 7, 6, 8, 9, 10, 11, 3857, 1380 + psubd m8, m0, m4 ; t8a + paddd m0, m4 ; t0a + psubd m4, m1, m5 ; t9a + paddd m1, m5 ; t1a + psubd m5, m2, m6 ; t12a + paddd m2, m6 ; t4a + psubd m6, m3, m7 ; t13a + paddd m7, m3 ; t5a + REPX {pmaxsd x, m12}, m8, m4, m5, m6, m0, m1, m2, m7 + REPX {pminsd x, m13}, m8, m4, m5, m6, m0, m1, m2, m7 + mova m15, [o(pd_4017)] + mova m10, [o(pd_799)] + ITX_MULSUB_2D 8, 4, 3, 9, _, 11, 10, 15 + ITX_MULSUB_2D 6, 5, 3, 9, _, 11, 15, 10 + psubd m3, m0, m2 ; t4 + paddd m0, m2 ; t0 + psubd m2, m1, m7 ; t5 + paddd m1, m7 ; t1 + psubd m7, m4, m6 ; t12a + paddd m4, m6 ; t8a + psubd m6, m8, m5 ; t13a + paddd m5, m8 ; t9a + REPX {pmaxsd x, m12}, m3, m2, m7, m6, m0, m1, m4, m5 + REPX {pminsd x, m13}, m3, m2, m7, m6, m0, m1, m4, m5 + mova m15, [o(pd_3784)] + mova m10, [o(pd_1567)] + ITX_MULSUB_2D 3, 2, 8, 9, _, 11, 10, 15 + ITX_MULSUB_2D 7, 6, 8, 9, _, 11, 10, 15 + mova m10, [r3+0*16] ; t2 + mova m8, [r3+1*16] ; t3 + psubd m9, m0, m10 ; t2a + paddd m0, m10 ; out0 + psubd m10, m1, m8 ; t3a + paddd m1, m8 ; -out15 + mova [r3+0*16], m1 + mova m15, [r3+3*16] ; t7a + mova m1, [r3+2*16] ; t6a + psubd m8, m3, m15 ; t7 + paddd m15, m3 ; out12 + paddd m3, m2, m1 ; -out3 + psubd m2, m1 ; t6 + mova [r3+3*16], m15 + mova [r3+1*16], m2 + mova m1, [r3+7*16] ; t15 + mova m2, [r3+6*16] ; t14 + paddd m15, m7, m1 ; -out13 + psubd m7, m1 ; t15a + psubd m11, m6, m2 ; t14a + paddd m2, m6 ; out2 + mova [r3+2*16], m15 + mova m1, [r3+4*16] ; t10a + mova m15, [r3+5*16] ; t11a + psubd m6, m4, m1 ; t10 + paddd m1, m4 ; -out1 + psubd m4, m5, m15 ; t11 + paddd m5, m15 ; out14 + REPX {pmaxsd x, m12}, m11, m7, m9, m10, m6, m4, m8 + pmaxsd m12, [r3+1*16] ; t6 + mova [r3+1*16], m5 + REPX {pminsd x, m13}, m11, m7, m9, m10, m6, m4, m12, m8 + REPX {pmulld x, m14}, m11, m7, m9, m10, m6, m4, m12, m8 + paddd m5, m11, m7 ; -out5 (unshifted) + psubd m11, m7 ; out10 (unshifted) + paddd m7, m9, m10 ; -out7 (unshifted) + psubd m9, m10 ; out8 (unshifted) + psubd m10, m6, m4 ; -out9 (unshifted) + paddd m6, m4 ; out6 (unshifted) + paddd m4, m12, m8 ; out4 (unshifted) + psubd m12, m8 ; -out11 (unshifted) +%else + mova [r3+8*16], m0 + mova [r3+9*16], m1 + mova [r3+10*16], m2 + mova [r3+11*16], m3 + mova m3, [o(pd_2048)] + ITX_MULSUB_2D 5, 4, 0, 1, 2, 3, 3035, 2751 + ITX_MULSUB_2D 7, 6, 0, 1, 2, 3, 3857, 1380 + mova m0, [r3+8*16] + mova m1, [r3+9*16] + mova [r3+8*16], m4 + mova m4, [r3+10*16] + mova [r3+9*16], m5 + mova [r3+10*16], m6 + mova m5, [r3+11*16] + mova [r3+11*16], m7 + ITX_MULSUB_2D 1, 0, 2, 6, 7, 3, 201, 4091 + ITX_MULSUB_2D 5, 4, 2, 6, 7, 3, 1751, 3703 + mova m2, [r3+8*16] + mova m6, [r3+9*16] + psubd m3, m0, m2 ; t8a + paddd m0, m2 ; t0a + mova [r3+8*16], m3 + psubd m2, m1, m6 ; t9a + paddd m1, m6 ; t1a + mova m3, [r3+10*16] + psubd m6, m4, m3 ; t12a + paddd m4, m3 ; t4a + mova m3, [r3+11*16] + psubd m7, m5, m3 ; t13a + paddd m5, m3 ; t5a + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m2, m6, m7, m0, m1, m4, m5 + pmaxsd m3, [r3+8*16] + mova [r3+8*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m2, m6, m7, m0, m1, m4, m5 + pminsd m3, [r3+8*16] + mova [r3+8*16], m3 + psubd m3, m0, m4 ; t4 + paddd m0, m4 ; t0 + psubd m4, m1, m5 ; t5 + paddd m1, m5 ; t1 + mova m5, [o(pd_2048)] + mova [r3+9*16], m1 + mova [r3+10*16], m4 + mova [r3+11*16], m3 + mova m3, [r3+8*16] + mova [r3+8*16], m0 + ITX_MULSUB_2D 3, 2, 0, 1, 4, 5, 799, 4017 + ITX_MULSUB_2D 7, 6, 0, 1, 4, 5, 4017, 4 + psubd m5, m2, m7 ; t12a + paddd m2, m7 ; t8a + psubd m7, m3, m6 ; t13a + paddd m6, m3 ; t9a + mova m0, [r3+8*16] + mova m1, [r3+9*16] + mova m4, [r3+10*16] + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m4, m5, m7, m0, m1, m2, m6 + pmaxsd m3, [r3+11*16] + mova [r3+8*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m4, m5, m7, m0, m1, m2, m6 + pminsd m3, [r3+8*16] + mova [r3+8*16], m0 + mova [r3+9*16], m1 + mova [r3+10*16], m2 + mova [r3+11*16], m6 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 3, 4, 1, 2, 6, 0, 1567, 3784 + ITX_MULSUB_2D 5, 7, 1, 2, 6, 0, 6, 3784 + mova m0, [r3+7*16] ; t7a + mova m2, [r3+6*16] ; t6a + psubd m1, m3, m0 ; t7 + paddd m0, m3 ; out12 + paddd m3, m4, m2 ; -out3 + psubd m4, m2 ; t6 + mova [r3+7*16], m3 + mova m3, [r3+3*16] ; t15 + mova m2, [r3+2*16] ; t14 + paddd m6, m5, m3 ; -out13 + psubd m5, m3 ; t15a + psubd m3, m7, m2 ; t14a + paddd m2, m7 ; out2 + mova [r3+6*16], m2 + mova m7, [r3+0*16] ; t10a + mova m2, [r3+1*16] ; t11a + mova [r3+0*16], m0 + mova [r3+1*16], m6 + mova m6, [r3+11*16] + psubd m0, m6, m2 ; t11 + paddd m6, m2 ; out14 + mova [r3+2*16], m6 + mova m2, [r3+10*16] + psubd m6, m2, m7 ; t10 + paddd m2, m7 ; -out1 + mova m7, [r3+5*16] ; t3 + mova [r3+5*16], m2 + mova [r3+10*16], m1 + mova m1, [r3+9*16] + psubd m2, m1, m7 ; t3a + paddd m1, m7 ; -out15 + mova [r3+3*16], m1 + mova m1, [r3+4*16] ; t2 + mova m7, [r3+8*16] + psubd m7, m1 ; t2a + paddd m1, [r3+8*16] ; out0 + mova [r3+4*16], m1 + mova m1, [o(clip_18b_min)] + REPX {pmaxsd x, m1}, m0, m2, m3, m4, m5, m6, m7 + pmaxsd m1, [r3+10*16] + mova [r3+10*16], m1 + mova m1, [o(clip_18b_max)] + REPX {pminsd x, m1}, m0, m2, m3, m4, m5, m6, m7 + pminsd m1, [r3+10*16] + mova [r3+10*16], m1 + mova m1, [o(pd_2896)] + REPX {pmulld x, m1}, m0, m2, m3, m4, m5, m6, m7 + pmulld m1, [r3+10*16] + mova [r3+11*16], m3 + psubd m3, m4, m1 ; -out11 (unshifted) + paddd m4, m1 ; out4 (unshifted) + psubd m1, m6, m0 ; -out9 (unshifted) + paddd m6, m0 ; out6 (unshifted) + psubd m0, m7, m2 ; out8 (unshifted) + paddd m7, m2 ; -out7 (unshifted) + mova m2, [r3+11*16] + mova [r3+11*16], m5 + paddd m5, m2 ; -out5 (unshifted) + psubd m2, [r3+11*16] ; out10 (unshifted) + ; m0-3 contain out8-11 (unshifted), m4-7 contain out4-7 (unshifted) + ; r[-4,3] contain out0-3 and out12-15 +%endif + ret +.main_part1: +%if ARCH_X86_64 + ITX_MULSUB_2D 1, 0, 8, 9, 10, 11, 995, 3973 + ITX_MULSUB_2D 3, 2, 8, 9, 10, 11, 2440, 3290 + ITX_MULSUB_2D 5, 4, 8, 9, 10, 11, 3513, 2106 + ITX_MULSUB_2D 7, 6, 8, 9, 10, 11, 4052, 601 + psubd m8, m0, m4 ; t10a + paddd m0, m4 ; t2a + psubd m4, m1, m5 ; t11a + paddd m1, m5 ; t3a + psubd m5, m2, m6 ; t14a + paddd m2, m6 ; t6a + psubd m6, m3, m7 ; t15a + paddd m7, m3 ; t7a + REPX {pmaxsd x, m12}, m8, m4, m5, m6, m0, m1, m2, m7 + REPX {pminsd x, m13}, m8, m4, m5, m6, m0, m1, m2, m7 + mova m15, [o(pd_2276)] + mova m10, [o(pd_3406)] + ITX_MULSUB_2D 8, 4, 3, 9, _, 11, 10, 15 + ITX_MULSUB_2D 6, 5, 3, 9, _, 11, 15, 10 + psubd m3, m0, m2 ; t6 + paddd m0, m2 ; t2 + psubd m2, m1, m7 ; t7 + paddd m1, m7 ; t3 + psubd m7, m4, m6 ; t14a + paddd m4, m6 ; t10a + psubd m6, m8, m5 ; t15a + paddd m5, m8 ; t11a + REPX {pmaxsd x, m12}, m3, m2, m7, m6, m0, m1, m4, m5 + REPX {pminsd x, m13}, m3, m2, m7, m6, m0, m1, m4, m5 + mova m15, [o(pd_1567)] + mova m10, [o(pd_3784)] + ITX_MULSUB_2D 2, 3, 8, 9, _, 11, 10, 15 + ITX_MULSUB_2D 6, 7, 8, 9, _, 11, 10, 15 + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova [r3+4*16], m4 + mova [r3+5*16], m5 + mova [r3+2*16], m2 + mova [r3+3*16], m3 + mova [r3+6*16], m6 + mova [r3+7*16], m7 +%else + mova [r3+4*16], m0 + mova [r3+5*16], m1 + mova [r3+6*16], m2 + mova [r3+7*16], m3 + mova m3, [o(pd_2048)] + ITX_MULSUB_2D 5, 4, 0, 1, 2, 3, 3513, 2106 + ITX_MULSUB_2D 7, 6, 0, 1, 2, 3, 4052, 601 + mova [r3+0*16], m4 + mova [r3+1*16], m5 + mova [r3+2*16], m6 + mova [r3+3*16], m7 + mova m0, [r3+4*16] + mova m1, [r3+5*16] + mova m2, [r3+6*16] + mova m7, [r3+7*16] + ITX_MULSUB_2D 1, 0, 4, 5, 6, 3, 995, 3973 + ITX_MULSUB_2D 7, 2, 4, 5, 6, 3, 2440, 3290 + mova m4, [r3+0*16] + mova m5, [r3+1*16] + psubd m6, m0, m4 ; t10a + paddd m0, m4 ; t2a + mova [r3+4*16], m6 + mova m6, [r3+2*16] + mova m3, [r3+3*16] + psubd m4, m1, m5 ; t11a + paddd m1, m5 ; t3a + psubd m5, m2, m6 ; t14a + paddd m2, m6 ; t6a + psubd m6, m7, m3 ; t15a + paddd m7, m3 ; t7a + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m4, m5, m6, m0, m1, m2, m7 + pmaxsd m3, [r3+4*16] + mova [r3+4*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m4, m5, m6, m0, m1, m2, m7 + pminsd m3, [r3+4*16] + mova [r3+4*16], m3 + psubd m3, m0, m2 ; t6 + paddd m0, m2 ; t2 + psubd m2, m1, m7 ; t7 + paddd m1, m7 ; t3 + mova [r3+5*16], m1 + mova [r3+6*16], m3 + mova [r3+7*16], m2 + mova m1, [r3+4*16] + mova [r3+4*16], m0 + mova m3, [o(pd_2048)] + ITX_MULSUB_2D 1, 4, 0, 7, 2, 3, 3406, 2276 + ITX_MULSUB_2D 6, 5, 0, 7, 2, 3, 2276, 2 + psubd m7, m4, m6 ; t14a + paddd m4, m6 ; t10a + psubd m6, m1, m5 ; t15a + paddd m5, m1 ; t11a + mova m1, [r3+5*16] + mova m3, [r3+6*16] + mova m2, [r3+7*16] + mova m0, [o(clip_18b_min)] + REPX {pmaxsd x, m0}, m3, m2, m7, m6, m1, m4, m5 + pmaxsd m0, [r3+4*16] + mova [r3+4*16], m0 + mova m0, [o(clip_18b_max)] + REPX {pminsd x, m0}, m3, m2, m7, m6, m1, m4, m5 + pminsd m0, [r3+4*16] + mova [r3+4*16], m0 + mova [r3+5*16], m1 + mova [r3+0*16], m4 + mova [r3+1*16], m5 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 2, 3, 1, 4, 5, 0, 3784, 1567 + ITX_MULSUB_2D 6, 7, 1, 4, 5, 0, 5, 1567 + mova [r3+6*16], m2 + mova [r3+7*16], m3 + mova [r3+2*16], m6 + mova [r3+3*16], m7 +%endif + ret + +.pass2: + lea r4, [o(m_suffix(iadst_8x4_internal_8bpc, _ssse3).main)] + jmp m(idct_16x4_internal_16bpc).pass2_loop + +INV_TXFM_16X4_FN flipadst, dct +INV_TXFM_16X4_FN flipadst, adst +INV_TXFM_16X4_FN flipadst, flipadst +INV_TXFM_16X4_FN flipadst, identity + +cglobal iflipadst_16x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 + lea r3, [rsp+gprsize] + call m(iadst_16x4_internal_16bpc).main +%if ARCH_X86_64 + packssdw m1, m0 + packssdw m3, m2 + packssdw m5, m4 + packssdw m7, m6 + packssdw m9, m8 + packssdw m11, m10 + packssdw m13, m12 + packssdw m15, m14 + mova m0, m15 + mova m2, m13 + mova m4, m11 + mova m6, m9 + mova m8, m7 + mova m10, m5 + mova m12, m3 + mova m14, m1 + jmp m(idct_16x4_internal_16bpc).transpose +%else + mova [rsp+gprsize+4*16], m0 + mova [rsp+gprsize+5*16], m2 + mova [rsp+gprsize+6*16], m4 + mova [rsp+gprsize+7*16], m6 + pshufd m6, [rsp+gprsize+ 8*16], q1032 + pshufd m4, [rsp+gprsize+ 9*16], q1032 + pshufd m2, [rsp+gprsize+10*16], q1032 + pshufd m0, [rsp+gprsize+11*16], q1032 + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+gprsize+0*16], m0 + mova [rsp+gprsize+1*16], m1 + mova [rsp+gprsize+2*16], m2 + mova [rsp+gprsize+3*16], m3 + pshufd m6, [rsp+gprsize+ 4*16], q1032 + pshufd m4, [rsp+gprsize+ 5*16], q1032 + pshufd m2, [rsp+gprsize+ 6*16], q1032 + pshufd m0, [rsp+gprsize+ 7*16], q1032 + call m(idct_8x4_internal_16bpc).transpose4x8packed + jmp tx2q +%endif + +.pass2: + lea r3, [strideq*3] + lea dstq, [dstq+r3] + neg strideq + lea r4, [o(m_suffix(iadst_8x4_internal_8bpc, _ssse3).main)] + jmp m(idct_16x4_internal_16bpc).pass2_loop + +INV_TXFM_16X4_FN identity, dct +INV_TXFM_16X4_FN identity, adst +INV_TXFM_16X4_FN identity, flipadst +INV_TXFM_16X4_FN identity, identity + +cglobal iidentity_16x4_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_64 + mova m15, [o(pd_11586)] + pmulld m0, m15, [cq+ 0*16] + pmulld m1, m15, [cq+ 1*16] + pmulld m2, m15, [cq+ 2*16] + pmulld m3, m15, [cq+ 3*16] + pmulld m4, m15, [cq+ 4*16] + pmulld m5, m15, [cq+ 5*16] + pmulld m6, m15, [cq+ 6*16] + pmulld m7, m15, [cq+ 7*16] + pmulld m8, m15, [cq+ 8*16] + pmulld m9, m15, [cq+ 9*16] + pmulld m10, m15, [cq+10*16] + pmulld m11, m15, [cq+11*16] + pmulld m12, m15, [cq+12*16] + pmulld m13, m15, [cq+13*16] + pmulld m14, m15, [cq+14*16] + pmulld m15, [cq+15*16] + mova [cq+ 0*16], m15 + mova m15, [o(pd_6144)] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + paddd m15, [cq+ 0*16] + REPX {psrad x, 13 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + jmp m(idct_16x4_internal_16bpc).pack_transpose +%else + add cq, 8*16 + mov r5d, 2 +.loop_pass1: + mova m7, [o(pd_11586)] + pmulld m0, m7, [cq+0*16] + pmulld m1, m7, [cq+1*16] + pmulld m2, m7, [cq+2*16] + pmulld m3, m7, [cq+3*16] + pmulld m4, m7, [cq+4*16] + pmulld m5, m7, [cq+5*16] + pmulld m6, m7, [cq+6*16] + pmulld m7, [cq+7*16] + mova [cq+7*16], m7 + mova m7, [o(pd_6144)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [cq+7*16] + REPX {psrad x, 13}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + call m(idct_8x4_internal_16bpc).transpose4x8packed + dec r5d + jz .end_pass1 + mova [rsp+gprsize+0*16], m0 + mova [rsp+gprsize+1*16], m1 + mova [rsp+gprsize+2*16], m2 + mova [rsp+gprsize+3*16], m3 + sub cq, 8*16 + jmp .loop_pass1 +.end_pass1: + jmp tx2q +%endif + +.pass2: +%if ARCH_X86_64 + mova m12, [o(pw_1697x8)] +%endif + lea r4, [o(.main)] + jmp m(idct_16x4_internal_16bpc).pass2_loop +.main: +%if ARCH_X86_64 + pmulhrsw m4, m0, m12 + pmulhrsw m5, m1, m12 + pmulhrsw m6, m2, m12 + pmulhrsw m7, m3, m12 +%else + mova m7, [o(pw_1697x8)] + pmulhrsw m4, m0, m7 + pmulhrsw m5, m1, m7 + pmulhrsw m6, m2, m7 + pmulhrsw m7, m3 +%endif + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + ret + +%macro INV_TXFM_16X8_FN 2-3 0 ; type1, type2, eob_offset +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, %3, 16x8, 16, 0-8*16 +%else + INV_TXFM_FN %1, %2, %3, 16x8, 8, 0-13*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 8 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 +%if ARCH_X86_32 + add rsp, 1*16 +%endif + jmp m(inv_txfm_add_dct_dct_16x4_16bpc).dconly +%endif +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, identity, 6 +INV_TXFM_16X8_FN dct, adst +INV_TXFM_16X8_FN dct, flipadst + +cglobal idct_16x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_64 + DECLARE_REG_TMP 6, 4, 6 +%else + mov [rsp+gprsize+12*16], r1 + DECLARE_REG_TMP 1, 4, 3 +%endif + lea t0, [o(.main)] +.loop_main: +%undef cmp +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 10 + setge r5b +%else + mov r5d, 1 + cmp eobd, 10 + sbb r5d, 0 +%endif + shl r5d, 4 + + lea r3, [rsp+gprsize] +.loop_pass1: + call t0 +%if ARCH_X86_64 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+4*32+r5], m8 + mova [cq+5*32+r5], m9 + mova [cq+6*32+r5], m10 + mova [cq+7*32+r5], m11 +%else + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+4*32+r5], m0 + mova [cq+5*32+r5], m1 + mova [cq+6*32+r5], m2 + mova [cq+7*32+r5], m3 + mova m0, [rsp+gprsize+ 8*16] + mova m2, [rsp+gprsize+ 9*16] + mova m4, [rsp+gprsize+10*16] + mova m6, [rsp+gprsize+11*16] +%endif + call m(idct_8x4_internal_16bpc).transpose4x8packed + pxor m7, m7 + REPX {mova [cq+x*32+r5], m7}, 8, 9, 10, 11, 12, 13, 14, 15 + test r5d, r5d + jz .end + mova [cq+0*32+r5], m0 + mova [cq+1*32+r5], m1 + mova [cq+2*32+r5], m2 + mova [cq+3*32+r5], m3 + xor r5d, r5d + jmp .loop_pass1 +.end: + + jmp tx2q +.main: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 1*32+r5] + mova m1, [cq+ 3*32+r5] + mova m2, [cq+ 5*32+r5] + mova m3, [cq+ 7*32+r5] + mova m4, [cq+ 9*32+r5] + mova m5, [cq+11*32+r5] + mova m6, [cq+13*32+r5] + mova m7, [cq+15*32+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+ 0*32+r5] + mova m1, [cq+ 2*32+r5] + mova m2, [cq+ 4*32+r5] + mova m3, [cq+ 6*32+r5] + mova m4, [cq+ 8*32+r5] + mova m5, [cq+10*32+r5] + mova m6, [cq+12*32+r5] + mova m7, [cq+14*32+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + call m(idct_16x4_internal_16bpc).round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + ret + +.pass2: +%if ARCH_X86_32 + mov strideq, [rsp+gprsize+12*16] +%endif + mov r4d, 2 +.pass2_main: +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%endif + lea r3, [strideq*3] + jmp .loop_pass2_entry +.loop_pass2: + mova m0, [cq+0*32+ 0] + mova m1, [cq+1*32+ 0] + mova m2, [cq+2*32+ 0] + mova m3, [cq+3*32+ 0] +.loop_pass2_entry: + mova m4, [cq+0*32+16] + mova m5, [cq+1*32+16] + mova m6, [cq+2*32+16] + mova m7, [cq+3*32+16] +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + call m(idct_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7 + add dstq, 16 + add cq, 4*32 + dec r4d + jg .loop_pass2 + RET + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, adst +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, identity, 6 + +cglobal iadst_16x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + mov [rsp+gprsize+12*16], r1 +%endif + lea t0, [o(.main)] + jmp m(idct_16x8_internal_16bpc).loop_main + +.main: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 2*32+r5] + mova m1, [cq+13*32+r5] + mova m2, [cq+ 6*32+r5] + mova m3, [cq+ 9*32+r5] + mova m4, [cq+10*32+r5] + mova m5, [cq+ 5*32+r5] + mova m6, [cq+14*32+r5] + mova m7, [cq+ 1*32+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(iadst_16x4_internal_16bpc).main_part1 + mova m0, [cq+ 0*32+r5] + mova m1, [cq+15*32+r5] + mova m2, [cq+ 4*32+r5] + mova m3, [cq+11*32+r5] + mova m4, [cq+ 8*32+r5] + mova m5, [cq+ 7*32+r5] + mova m6, [cq+12*32+r5] + mova m7, [cq+ 3*32+r5] +%if ARCH_X86_32 + add r3, 8*16 +%endif + call m(idct_8x4_internal_16bpc).rect2_mul +%if ARCH_X86_32 + sub r3, 8*16 +%endif + call m(iadst_16x4_internal_16bpc).main_part2 + call m(iadst_16x4_internal_16bpc).round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + ret + +.pass2: +%if ARCH_X86_32 + mov strideq, [rsp+gprsize+12*16] +%endif + mov r4d, 2 +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] + mova m11, [o(pw_m2048)] +%endif + lea r3, [strideq*3] + jmp .loop_pass2_entry +.loop_pass2: + mova m0, [cq+0*32+ 0] + mova m1, [cq+1*32+ 0] + mova m2, [cq+2*32+ 0] + mova m3, [cq+3*32+ 0] +.loop_pass2_entry: + mova m4, [cq+0*32+16] + mova m5, [cq+1*32+16] + mova m6, [cq+2*32+16] + mova m7, [cq+3*32+16] +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + call m_suffix(iadst_8x8_internal_8bpc, _ssse3).main + call m_suffix(iadst_8x8_internal_8bpc, _ssse3).main_pass2_end + call m(iadst_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7 + add dstq, 16 + add cq, 4*32 + dec r4d + jg .loop_pass2 + RET + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst +INV_TXFM_16X8_FN flipadst, identity, 6 + +cglobal iflipadst_16x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + mov [rsp+gprsize+12*16], r1 +%endif + lea t0, [o(.main)] + jmp m(idct_16x8_internal_16bpc).loop_main +.main: + call m(iadst_16x8_internal_16bpc).main +%if ARCH_X86_64 + pshufd m1, m0, q1032 + pshufd m3, m2, q1032 + pshufd m5, m4, q1032 + pshufd m7, m6, q1032 + pshufd m0, m14, q1032 + pshufd m2, m12, q1032 + pshufd m4, m10, q1032 + pshufd m6, m8, q1032 + mova m14, m1 + mova m12, m3 + mova m10, m5 + mova m8, m7 +%else + pshufd m1, m0, q1032 + pshufd m3, m2, q1032 + pshufd m5, m4, q1032 + pshufd m7, m6, q1032 + pshufd m0, [r3+11*16], q1032 + pshufd m2, [r3+10*16], q1032 + pshufd m4, [r3+9*16], q1032 + pshufd m6, [r3+8*16], q1032 + mova [r3+8*16], m7 + mova [r3+9*16], m5 + mova [r3+10*16], m3 + mova [r3+11*16], m1 +%endif + ret + +.pass2: +%if ARCH_X86_32 + mov strideq, [rsp+gprsize+12*16] +%endif + lea dstq, [dstq+strideq*8] + neg strideq + add dstq, strideq +%if ARCH_X86_32 + mov [rsp+gprsize+12*16], strideq +%endif + jmp m(iadst_16x8_internal_16bpc).pass2 + +INV_TXFM_16X8_FN identity, dct, -54 +INV_TXFM_16X8_FN identity, adst, -54 +INV_TXFM_16X8_FN identity, flipadst, -54 +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_32 + mov [rsp+gprsize+12*16], r1 +%endif + lea t0, [o(.main)] + jmp m(idct_16x8_internal_16bpc).loop_main +.main: +%if ARCH_X86_64 + mova m15, [o(pd_2896)] + pmulld m0, m15, [cq+ 0*32+r5] + pmulld m1, m15, [cq+ 1*32+r5] + pmulld m2, m15, [cq+ 2*32+r5] + pmulld m3, m15, [cq+ 3*32+r5] + pmulld m4, m15, [cq+ 4*32+r5] + pmulld m5, m15, [cq+ 5*32+r5] + pmulld m6, m15, [cq+ 6*32+r5] + pmulld m7, m15, [cq+ 7*32+r5] + pmulld m8, m15, [cq+ 8*32+r5] + pmulld m9, m15, [cq+ 9*32+r5] + pmulld m10, m15, [cq+10*32+r5] + pmulld m11, m15, [cq+11*32+r5] + pmulld m12, m15, [cq+12*32+r5] + pmulld m13, m15, [cq+13*32+r5] + pmulld m14, m15, [cq+14*32+r5] + pmulld m15, [cq+15*32+r5] + mova [r3], m15 + mova m15, [o(pd_2048)] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + paddd m15, [r3] + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + mova [r3], m15 + mova m15, [o(pd_11586)] + REPX {pmulld x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + pmulld m15, [r3] + mova [r3], m15 + mova m15, [o(pd_6144)] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + paddd m15, [r3] + REPX {psrad x, 13 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%else + mova m0, [cq+ 0*32+r5] + mova m1, [cq+ 1*32+r5] + mova m2, [cq+ 2*32+r5] + mova m3, [cq+ 3*32+r5] + mova m4, [cq+ 4*32+r5] + mova m5, [cq+ 5*32+r5] + mova m6, [cq+ 6*32+r5] + mova m7, [cq+ 7*32+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + mova [r3], m7 + mova m7, [o(pd_11586)] + REPX {pmulld x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulld m7, [r3] + mova [r3], m7 + mova m7, [o(pd_6144)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3] + REPX {psrad x, 13}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + mova [r3+ 8*16], m0 + mova [r3+ 9*16], m2 + mova [r3+10*16], m4 + mova [r3+11*16], m6 + mova m0, [cq+ 8*32+r5] + mova m1, [cq+ 9*32+r5] + mova m2, [cq+10*32+r5] + mova m3, [cq+11*32+r5] + mova m4, [cq+12*32+r5] + mova m5, [cq+13*32+r5] + mova m6, [cq+14*32+r5] + mova m7, [cq+15*32+r5] + call m(idct_8x4_internal_16bpc).rect2_mul + mova [r3], m7 + mova m7, [o(pd_11586)] + REPX {pmulld x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulld m7, [r3] + mova [r3], m7 + mova m7, [o(pd_6144)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3] + REPX {psrad x, 13}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 +%endif + ret +.pass2: +%if ARCH_X86_32 + mov strideq, [rsp+gprsize+12*16] +%endif + mov r4d, 2 +%if ARCH_X86_64 + mova m8, [o(pw_4096)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%endif + lea r3, [strideq*3] + jmp .loop_pass2_entry +.loop_pass2: + mova m0, [cq+0*32+ 0] + mova m1, [cq+1*32+ 0] + mova m2, [cq+2*32+ 0] + mova m3, [cq+3*32+ 0] +.loop_pass2_entry: + mova m4, [cq+0*32+16] + mova m5, [cq+1*32+16] + mova m6, [cq+2*32+16] + mova m7, [cq+3*32+16] +%if ARCH_X86_64 + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 +%else + mova [rsp+gprsize], m7 + mova m7, [o(pw_4096)] + call m(idct_8x8_internal_16bpc).round4_and_write_8x8 +%endif +%if ARCH_X86_64 +%define mzero m9 +%else +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7 + add dstq, 16 + add cq, 4*32 + dec r4d + jg .loop_pass2 + RET + +%macro INV_TXFM_16X16_FN 2-3 2d ; type1, type2, eob_tbl_suffix +%if ARCH_X86_64 + INV_TXFM_FN %1, %2, tbl_16x16_%3, 16x16, 16, 0-(16+WIN64)*16 +%else + INV_TXFM_FN %1, %2, tbl_16x16_%3, 16x16, 8, 0-17*16 +%endif +%ifidn %1_%2, dct_dct + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 16 + add r5d, 640 + sar r5d, 10 + add rsp, (5+ARCH_X86_64*3+WIN64)*16 + jmp m(inv_txfm_add_dct_dct_16x4_16bpc).dconly2 +%endif +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, identity, v +INV_TXFM_16X16_FN dct, adst +INV_TXFM_16X16_FN dct, flipadst + +cglobal idct_16x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if ARCH_X86_64 + DECLARE_REG_TMP 6, 7 +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%endif +%elif ARCH_X86_32 + DECLARE_REG_TMP 1, 6 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(.main)] +.pass1_full: +%undef cmp + mov t1d, 4 +.zero_loop: + dec t1d + cmp eobb, byte [r5+t1] + jb .zero_loop + mov r5d, t1d + shl r5d, 4 +%if ARCH_X86_32 + ; restore pic-ptr + mov r6, [rsp+16*16+2*gprsize] +%endif + ; setup stack pointer + lea r3, [rsp+gprsize] +.loop_pass1: + call t0 +%if ARCH_X86_64 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+4*64+r5], m8 + mova [cq+5*64+r5], m9 + mova [cq+6*64+r5], m10 + mova [cq+7*64+r5], m11 +%else + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+4*64+r5], m0 + mova [cq+5*64+r5], m1 + mova [cq+6*64+r5], m2 + mova [cq+7*64+r5], m3 + mova m0, [rsp+gprsize+ 8*16] + mova m2, [rsp+gprsize+ 9*16] + mova m4, [rsp+gprsize+10*16] + mova m6, [rsp+gprsize+11*16] +%endif + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+0*64+r5], m0 + mova [cq+1*64+r5], m1 + mova [cq+2*64+r5], m2 + mova [cq+3*64+r5], m3 + pxor m0, m0 + REPX {mova [cq+x*64+r5], m0}, 8, 9, 10, 11, 12, 13, 14, 15 + sub r5d, 16 + jge .loop_pass1 + +%if ARCH_X86_32 + ; restore pic-ptr + mov r1, [rsp+16*16+1*gprsize] +%endif + jmp tx2q +.main: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + + mova m0, [cq+ 1*64+r5] + mova m1, [cq+ 3*64+r5] + mova m2, [cq+ 5*64+r5] + mova m3, [cq+ 7*64+r5] + mova m4, [cq+ 9*64+r5] + mova m5, [cq+11*64+r5] + mova m6, [cq+13*64+r5] + mova m7, [cq+15*64+r5] + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+ 0*64+r5] + mova m1, [cq+ 2*64+r5] + mova m2, [cq+ 4*64+r5] + mova m3, [cq+ 6*64+r5] + mova m4, [cq+ 8*64+r5] + mova m5, [cq+10*64+r5] + mova m6, [cq+12*64+r5] + mova m7, [cq+14*64+r5] + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + call .round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + ret +.round: +%if ARCH_X86_64 + REPX {pmaxsd x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {pminsd x, m13}, m0, m1, m2, m3, m4, m5, m6, m7 + psrld m8, m11, 10 ; 2 + REPX {paddd x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + mova m8, [r3+1*16] + mova m9, [r3+2*16] + mova m10, [r3+3*16] + mova m11, [r3+4*16] + mova m12, [r3+5*16] + mova m13, [r3+6*16] + mova m14, [r3+7*16] + psubd m15, m0, m14 ; out15 + paddd m0, m14 ; out0 + psubd m14, m1, m13 ; out14 + paddd m1, m13 ; out1 + psubd m13, m2, m12 ; out13 + paddd m2, m12 ; out2 + psubd m12, m3, m11 ; out12 + paddd m3, m11 ; out3 + psubd m11, m4, m10 ; out11 + paddd m4, m10 ; out4 + psubd m10, m5, m9 ; out10 + paddd m5, m9 ; out5 + psubd m9, m6, m8 ; out9 + paddd m6, m8 ; out6 + psubd m8, m7, [r3+0*16] ; out8 + paddd m7, [r3+0*16] ; out7 + REPX {psrad x, 2}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + ; and out0-15 is now in m0-15 +%else + mova [r3+ 0*16], m0 + mova m0, [o(clip_18b_min)] + REPX {pmaxsd x, m0}, m1, m2, m3, m4, m5, m6, m7 + pmaxsd m0, [r3+ 0*16] + mova [r3+ 0*16], m7 + mova m7, [o(clip_18b_max)] + REPX {pminsd x, m7}, m0, m1, m2, m3, m4, m5, m6 + pminsd m7, [r3+ 0*16] + mova [r3+ 0*16], m0 + mova m0, [o(pd_2)] + REPX {paddd x, m0}, m1, m2, m3, m4, m5, m6, m7 + paddd m0, [r3+ 0*16] + mova [r3+ 0*16], m0 + mova [r3+ 1*16], m1 + mova [r3+ 2*16], m2 + mova m1, [r3+11*16] + mova m2, [r3+10*16] + psubd m0, m7, m1 + paddd m7, m1 + psubd m1, m6, m2 + paddd m6, m2 + REPX {psrad x, 2}, m0, m1, m6, m7 + packssdw m0, m1 ; out8-9 + packssdw m6, m7 ; out6-7 + mova [r3+11*16], m6 + mova m1, [r3+9*16] + mova m7, [r3+8*16] + psubd m2, m5, m1 + paddd m5, m1 + psubd m1, m4, m7 + paddd m4, m7 + REPX {psrad x, 2}, m2, m1, m4, m5 + packssdw m2, m1 ; out10-11 + packssdw m4, m5 ; out4-5 + mova m1, [r3+2*16] + mova [r3+10*16], m4 + mova m6, [r3+7*16] + mova m7, [r3+6*16] + psubd m4, m3, m6 + paddd m3, m6 + psubd m6, m1, m7 + paddd m1, m7 + REPX {psrad x, 2}, m4, m6, m1, m3 + packssdw m4, m6 ; out12-13 + packssdw m1, m3 ; out2-3 + mova m3, [r3+1*16] + mova [r3+9*16], m1 + mova m1, [r3+0*16] + mova m5, [r3+5*16] + mova m7, [r3+4*16] + psubd m6, m3, m5 + paddd m3, m5 + psubd m5, m1, m7 + paddd m1, m7 + REPX {psrad x, 2}, m6, m5, m1, m3 + packssdw m6, m5 ; out14-15 + packssdw m1, m3 ; out0-1 + mova [r3+8*16], m1 +%endif + ret + +.pass2: +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] + mov r7, dstq +%else + mov [rsp+2*gprsize+16*16], dstq +%endif + lea r3, [strideq*3] + mov r4d, 2 +.loop_pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + mova m0, [cq+0*64+ 0] + mova m1, [cq+2*64+ 0] + mova m2, [cq+0*64+16] + mova m3, [cq+2*64+16] + mova m4, [cq+0*64+32] + mova m5, [cq+2*64+32] + mova m6, [cq+0*64+48] + mova m7, [cq+2*64+48] + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + mova [rsp+gprsize+3*16], m0 + mova [rsp+gprsize+4*16], m1 + mova [rsp+gprsize+5*16], m2 + mova [rsp+gprsize+6*16], m3 + mova [rsp+gprsize+7*16], m4 + mova [rsp+gprsize+8*16], m5 + mova [rsp+gprsize+9*16], m6 + ; m7 is already stored in [rsp+gprsize+0*16] + mova m0, [cq+1*64+ 0] + mova m1, [cq+3*64+ 0] + mova m2, [cq+1*64+16] + mova m3, [cq+3*64+16] + mova m4, [cq+1*64+32] + mova m5, [cq+3*64+32] + mova m6, [cq+1*64+48] + mova m7, [cq+3*64+48] + call m_suffix(idct_16x8_internal_8bpc, _ssse3).main + + ; out0-7 is in rsp+gprsize+3-10*mmsize + ; out8-14 is in m0-6, and out15 is in m7 as well as rsp+gprsize+0*mmsize + +%if ARCH_X86_64 + lea dstq, [r7+strideq*8] +%else + mov dstq, [rsp+2*gprsize+16*16] + lea dstq, [dstq+strideq*8] +%endif + call m(idct_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 + mov dstq, r7 +%else + mov dstq, [rsp+2*gprsize+16*16] +%endif + mova m0, [rsp+gprsize+ 3*16] + mova m1, [rsp+gprsize+ 4*16] + mova m2, [rsp+gprsize+ 5*16] + mova m3, [rsp+gprsize+ 6*16] + mova m4, [rsp+gprsize+ 7*16] + mova m5, [rsp+gprsize+ 8*16] + mova m6, [rsp+gprsize+ 9*16] + mova m7, [rsp+gprsize+10*16] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 +%if ARCH_X86_64 + add r7, 16 +%define mzero m9 +%else + add dword [rsp+2*gprsize+16*16], 16 +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7 + add cq, 64*4 + REPX {mova [cq+x*16], mzero}, -8, -7, -6, -5, -4, -3, -2, -1 +%undef mzero + dec r4d + jg .loop_pass2 +%if WIN64 + mov r7, [rsp+16*16+gprsize] +%endif + RET + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, adst +INV_TXFM_16X16_FN adst, flipadst + +cglobal iadst_16x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(.main)] + jmp m(idct_16x16_internal_16bpc).pass1_full + +.main: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 2*64+r5] + mova m1, [cq+13*64+r5] + mova m2, [cq+ 6*64+r5] + mova m3, [cq+ 9*64+r5] + mova m4, [cq+10*64+r5] + mova m5, [cq+ 5*64+r5] + mova m6, [cq+14*64+r5] + mova m7, [cq+ 1*64+r5] + call m(iadst_16x4_internal_16bpc).main_part1 + mova m0, [cq+ 0*64+r5] + mova m1, [cq+15*64+r5] + mova m2, [cq+ 4*64+r5] + mova m3, [cq+11*64+r5] + mova m4, [cq+ 8*64+r5] + mova m5, [cq+ 7*64+r5] + mova m6, [cq+12*64+r5] + mova m7, [cq+ 3*64+r5] + call m(iadst_16x4_internal_16bpc).main_part2 + call .round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + ret +.round: +%if ARCH_X86_64 + pcmpeqd m8, m8 ; -1 + mova m15, [o(pd_10240)] + psrld m14, 10 ; +2 + psubd m13, m14, m8 ; +3 + REPX {pxor x, m8 }, m1, m3, m5, m7 + REPX {paddd x, m14}, m0, m2 + REPX {paddd x, m13}, m1, m3 + REPX {paddd x, m15}, m4, m5, m6, m7 + paddd m13, m15, m8 ; +10239 + paddd m8, m15, m9 + psubd m9, m13, m10 + paddd m10, m15, m11 + psubd m11, m13, m12 + paddd m12, m14, [r3+3*16] + psubd m13, m14, [r3+2*16] + psubd m15, m14, [r3+0*16] + paddd m14, [r3+1*16] + REPX {psrad x, 2 }, m0, m1, m2, m3, m12, m13, m14, m15 + REPX {psrad x, 14}, m4, m5, m6, m7, m8, m9, m10, m11 +%else + mova [r3+8*16], m1 + mova [r3+9*16], m3 + mova m3, [o(pd_10240)] + pcmpeqd m1, m1 + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m4, m5, m6, m7 + REPX {psrad x, 14}, m4, m5, m6, m7 + packssdw m4, m5 + packssdw m6, m7 + mova [r3+10*16], m4 + mova [r3+11*16], m6 + mova m4, [r3+4*16] + mova m5, [r3+5*16] + mova m6, [r3+6*16] + mova m7, [r3+7*16] + mova m3, [o(pd_2)] + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m4, m6 + psubd m3, m1 + REPX {paddd x, m3}, m5, m7 + REPX {psrad x, 2 }, m4, m5, m6, m7 + packssdw m4, m5 + packssdw m6, m7 + mova m5, [r3+8*16] + mova m7, [r3+9*16] + mova [r3+8*16], m4 + mova [r3+9*16], m6 + mova m3, [o(pd_10240)] + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m0, m5, m2, m7 + REPX {psrad x, 14}, m0, m5, m2, m7 + packssdw m0, m5 + packssdw m2, m7 + mova m4, [r3+0*16] + mova m5, [r3+1*16] + mova m6, [r3+2*16] + mova m7, [r3+3*16] + mova m3, [o(pd_2)] + REPX {pxor x, m1}, m5, m7 + REPX {paddd x, m3}, m4, m6 + psubd m3, m1 + REPX {paddd x, m3}, m5, m7 + REPX {psrad x, 2 }, m4, m5, m6, m7 + packssdw m4, m5 + packssdw m6, m7 +%endif + ret +.pass2: +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + mova m11, [o(pw_m2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] + mov r7, dstq +%else + mov [rsp+2*gprsize+16*16], dstq +%endif + lea r3, [strideq*3] + mov r4d, 2 +.loop_pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + mova m0, [cq+0*64+32] + mova m1, [cq+1*64+32] + mova m2, [cq+2*64+16] + mova m3, [cq+3*64+16] + mova m4, [cq+0*64+ 0] + mova m5, [cq+1*64+ 0] + mova m6, [cq+2*64+48] + mova m7, [cq+3*64+48] + mova [rsp+gprsize+3*16], m0 + mova [rsp+gprsize+4*16], m1 + mova [rsp+gprsize+5*16], m2 + mova [rsp+gprsize+6*16], m3 + mova [rsp+gprsize+7*16], m4 + mova [rsp+gprsize+8*16], m5 + mova [rsp+gprsize+9*16], m6 + mova [rsp+gprsize+10*16], m7 + mova m0, [cq+2*64+ 0] + mova m1, [cq+3*64+ 0] + mova m2, [cq+0*64+16] + mova m3, [cq+1*64+16] + mova m4, [cq+2*64+32] + mova m5, [cq+3*64+32] + mova m6, [cq+0*64+48] + mova m7, [cq+1*64+48] + call m_suffix(iadst_16x8_internal_8bpc, _ssse3).main + call m_suffix(iadst_16x8_internal_8bpc, _ssse3).main_pass2_end + + ; out0-7 is in rsp+gprsize+3-10*mmsize + ; out8-14 is in m0-6, and out15 is in m7 as well as rsp+gprsize+0*mmsize + +%if ARCH_X86_64 + lea dstq, [r7+strideq*8] +%else + mov dstq, [rsp+2*gprsize+16*16] + lea dstq, [dstq+strideq*8] +%endif + call m(iadst_8x8_internal_16bpc).round2_and_write_8x8 +%if ARCH_X86_64 + mov dstq, r7 +%else + mov dstq, [rsp+2*gprsize+16*16] +%endif + mova m0, [rsp+gprsize+ 3*16] + mova m1, [rsp+gprsize+ 4*16] + mova m2, [rsp+gprsize+ 5*16] + mova m3, [rsp+gprsize+ 6*16] + mova m4, [rsp+gprsize+ 7*16] + mova m5, [rsp+gprsize+ 8*16] + mova m6, [rsp+gprsize+ 9*16] + mova m7, [rsp+gprsize+10*16] + call m(iadst_8x8_internal_16bpc).round1_and_write_8x8 +%if ARCH_X86_64 + add r7, 16 +%define mzero m9 +%else + add dword [rsp+2*gprsize+16*16], 16 +%define mzero m7 + pxor m7, m7 +%endif + REPX {mova [cq+x*16], mzero}, 0, 1, 2, 3, 4, 5, 6, 7 + add cq, 64*4 + REPX {mova [cq+x*16], mzero}, -8, -7, -6, -5, -4, -3, -2, -1 +%undef mzero + dec r4d + jg .loop_pass2 +%if WIN64 + mov r7, [rsp+16*16+gprsize] +%endif + RET + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(.main)] + jmp m(idct_16x16_internal_16bpc).pass1_full + +.main: + call m(iadst_16x16_internal_16bpc).main +%if ARCH_X86_64 + mova m1, m0 + mova m3, m2 + mova m5, m4 + mova m7, m6 + pshufd m0, m14, q1032 + pshufd m2, m12, q1032 + pshufd m4, m10, q1032 + pshufd m6, m8, q1032 + pshufd m8, m7, q1032 + pshufd m10, m5, q1032 + pshufd m12, m3, q1032 + pshufd m14, m1, q1032 +%else + pshufd m1, m0, q1032 + pshufd m3, m2, q1032 + pshufd m5, m4, q1032 + pshufd m7, m6, q1032 + pshufd m0, [r3+11*16], q1032 + pshufd m2, [r3+10*16], q1032 + pshufd m4, [r3+9*16], q1032 + pshufd m6, [r3+8*16], q1032 + mova [r3+11*16], m1 + mova [r3+10*16], m3 + mova [r3+ 9*16], m5 + mova [r3+ 8*16], m7 +%endif + ret + +.pass2: + lea r3, [strideq*3] + lea r3, [r3*5] + add dstq, r3 + neg strideq + jmp m(iadst_16x16_internal_16bpc).pass2 + +INV_TXFM_16X16_FN identity, dct, h +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_16bpc, 0, 0, 0, dst, stride, c, eob, tx2 +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%elif ARCH_X86_32 + mov [rsp+16*16+gprsize*1], r1 + mov [rsp+16*16+gprsize*2], r6 +%endif + lea t0, [o(.main)] + jmp m(idct_16x16_internal_16bpc).pass1_full + +.main: +%if ARCH_X86_64 + mova m15, [o(pd_11586)] + pmulld m0, m15, [cq+ 0*64+r5] + pmulld m1, m15, [cq+ 1*64+r5] + pmulld m2, m15, [cq+ 2*64+r5] + pmulld m3, m15, [cq+ 3*64+r5] + pmulld m4, m15, [cq+ 4*64+r5] + pmulld m5, m15, [cq+ 5*64+r5] + pmulld m6, m15, [cq+ 6*64+r5] + pmulld m7, m15, [cq+ 7*64+r5] + pmulld m8, m15, [cq+ 8*64+r5] + pmulld m9, m15, [cq+ 9*64+r5] + pmulld m10, m15, [cq+10*64+r5] + pmulld m11, m15, [cq+11*64+r5] + pmulld m12, m15, [cq+12*64+r5] + pmulld m13, m15, [cq+13*64+r5] + pmulld m14, m15, [cq+14*64+r5] + pmulld m15, [cq+15*64+r5] + mova [r3], m15 + mova m15, [o(pd_10240)] + REPX {paddd x, m15}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14 + paddd m15, [r3] + REPX {psrad x, 14 }, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m12, m13, m14, m15 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%else + mova m7, [o(pd_11586)] + pmulld m0, m7, [cq+ 0*64+r5] + pmulld m1, m7, [cq+ 1*64+r5] + pmulld m2, m7, [cq+ 2*64+r5] + pmulld m3, m7, [cq+ 3*64+r5] + pmulld m4, m7, [cq+ 4*64+r5] + pmulld m5, m7, [cq+ 5*64+r5] + pmulld m6, m7, [cq+ 6*64+r5] + pmulld m7, [cq+ 7*64+r5] + mova [r3], m7 + mova m7, [o(pd_10240)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3] + REPX {psrad x, 14}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + mova [r3+8*16], m0 + mova [r3+9*16], m2 + mova [r3+10*16], m4 + mova [r3+11*16], m6 + mova m7, [o(pd_11586)] + pmulld m0, m7, [cq+ 8*64+r5] + pmulld m1, m7, [cq+ 9*64+r5] + pmulld m2, m7, [cq+10*64+r5] + pmulld m3, m7, [cq+11*64+r5] + pmulld m4, m7, [cq+12*64+r5] + pmulld m5, m7, [cq+13*64+r5] + pmulld m6, m7, [cq+14*64+r5] + pmulld m7, [cq+15*64+r5] + mova [r3], m7 + mova m7, [o(pd_10240)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3] + REPX {psrad x, 14}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 +%endif + ret + +.pass2: +%if ARCH_X86_64 + mova m4, [o(pw_2048)] + mova m5, [o(pixel_10bpc_max)] + pxor m6, m6 + mova m7, [o(pw_1697x16)] + mov r7, dstq +%else + mov [rsp+2*gprsize+16*16], dstq +%endif + mov r5d, 4 + lea r3, [strideq*3] +.pass2_loop: + mova m0, [cq+0*64+0] + mova m1, [cq+1*64+0] + mova m2, [cq+2*64+0] + mova m3, [cq+3*64+0] + call m(iidentity_8x16_internal_16bpc).main +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).round1_and_write_8x4 +%else + call m(idct_8x4_internal_16bpc).round2_and_write_8x4 +%endif + REPX {mova [cq+x*16], m6}, 0, 4, 8, 12 + add cq, 16 + lea dstq, [dstq+strideq*4] + dec r5w + jg .pass2_loop + add cq, 64*3 + btc r5d, 16 + jc .end +%if ARCH_X86_64 + lea dstq, [r7+16] +%else + mov dstq, [rsp+2*gprsize+16*16] + add dstq, 16 +%endif + add r5d, 4 + jmp .pass2_loop +.end: +%if WIN64 + mov r7, [rsp+16*16+gprsize] +%endif + RET + +cglobal inv_txfm_add_identity_identity_8x32_16bpc, 4, 7, 8, dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%endif + mova m5, [o(pw_5)] + mova m7, [o(pixel_10bpc_max)] + pxor m6, m6 + mov r5d, eobd + add eobb, 21 + cmovc eobd, r5d ; 43, 107, 171 -> 64, 128, 192 + lea r4, [strideq*3] +.loop: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + REPX {paddsw x, m5}, m0, m1, m2, m3 + REPX {psraw x, 3 }, m0, m1, m2, m3 + call .main_zero + add cq, 16 + lea dstq, [dstq+strideq*4] + btc eobd, 16 + jnc .loop + sub eobd, 64 + jge .loop + RET +ALIGN function_align +.main_zero: + REPX {mova [cq+128*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 +.main: + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m4 + punpcklwd m0, m4 + punpckhwd m4, m2, m1 + punpcklwd m2, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + paddw m0, [dstq+strideq*0] + paddw m1, [dstq+strideq*1] + paddw m2, [dstq+strideq*2] + paddw m3, [dstq+r4 ] + REPX {pmaxsw x, m6}, m0, m1, m2, m3 + REPX {pminsw x, m7}, m0, m1, m2, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+r4 ], m3 + ret + +cglobal inv_txfm_add_identity_identity_32x8_16bpc, 4, 7, 8, dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%endif + mova m5, [o(pw_4096)] + mova m7, [o(pixel_10bpc_max)] + pxor m6, m6 + mov r4d, eobd + add eobb, 21 + cmovc eobd, r4d + lea r4, [strideq*3] + mov r5, dstq +.loop: + mova m0, [cq+32*0] + packssdw m0, [cq+32*1] + mova m1, [cq+32*2] + packssdw m1, [cq+32*3] + mova m2, [cq+32*4] + packssdw m2, [cq+32*5] + mova m3, [cq+32*6] + packssdw m3, [cq+32*7] + REPX {mova [cq+32*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + call m(inv_txfm_add_identity_identity_8x32_16bpc).main + lea dstq, [dstq+strideq*4] + add cq, 16 + btc eobd, 16 + jnc .loop + add cq, 32*8-32 + add r5, 16 + mov dstq, r5 + sub eobd, 64 + jge .loop + RET + +cglobal inv_txfm_add_identity_identity_16x32_16bpc, 4, 7, 12, dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%else + mova m8, [o(pw_2896x8)] + mova m9, [o(pw_1697x16)] + mova m11, [o(pw_8192)] +%endif + mova m7, [o(pixel_10bpc_max)] + lea r4, [strideq*3] + pxor m6, m6 +%if ARCH_X86_64 + paddw m10, m11, m11 ; pw_16384 +%endif + mov r5, dstq + call .main + sub eobd, 36 + jl .ret + add cq, 128*8-32 + lea dstq, [r5+16] + call .main + sub cq, 128*8 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 107 ; eob < 143 + jl .ret + add cq, 128*8-32 + lea dstq, [r5+16] + call .main + sub cq, 128*8 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 128 ; eob < 271 + jl .ret + add cq, 128*8-32 + lea dstq, [r5+16] + call .main + sub cq, 128*8 + lea dstq, [r5+strideq*8] + mov r5, dstq + call .main + sub eobd, 128 ; eob < 399 + jl .ret + add cq, 128*8-32 + lea dstq, [r5+16] + call .main +.ret: + RET +ALIGN function_align +.main: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] +%if ARCH_X86_64 + REPX {pmulhrsw x, m8 }, m0, m1, m2, m3 + pmulhrsw m4, m9, m0 + pmulhrsw m5, m9, m1 + REPX {pmulhrsw x, m10}, m4, m5 +%else + mova m6, [o(pw_2896x8)] + REPX {pmulhrsw x, m6 }, m0, m1, m2, m3 + mova m5, [o(pw_1697x16)] + pmulhrsw m4, m5, m0 + pmulhrsw m5, m1 + mova m6, [o(pw_16384)] + REPX {pmulhrsw x, m6 }, m4, m5 +%endif + paddsw m0, m4 + paddsw m1, m5 +%if ARCH_X86_64 + pmulhrsw m4, m9, m2 + pmulhrsw m5, m9, m3 + REPX {pmulhrsw x, m10}, m4, m5 +%else + mova m5, [o(pw_1697x16)] + pmulhrsw m4, m5, m2 + pmulhrsw m5, m3 + REPX {pmulhrsw x, m6 }, m4, m5 +%endif + paddsw m2, m4 + paddsw m3, m5 +%if ARCH_X86_64 + REPX {pmulhrsw x, m11}, m0, m1, m2, m3 +%else + psrlw m6, 1 ; pw_8192 + REPX {pmulhrsw x, m6 }, m0, m1, m2, m3 + pxor m6, m6 +%endif + call m(inv_txfm_add_identity_identity_8x32_16bpc).main_zero + lea dstq, [dstq+strideq*4] + add cq, 16 + btc eobd, 16 + jnc .main + ret + +cglobal inv_txfm_add_identity_identity_32x16_16bpc, 4, 7, 11, dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%else + mova m8, [o(pw_2896x8)] + mova m9, [o(pw_1697x16)] + mova m10, [o(pw_2048)] +%endif + mova m7, [o(pixel_10bpc_max)] + lea r4, [strideq*3] + pxor m6, m6 + mov r5, dstq + call .main + sub eobd, 36 + jl .ret + call .main + add cq, 64*8-64 + lea dstq, [r5+16*1] + call .main + sub eobd, 107 ; eob < 143 + jl .ret + call .main + add cq, 64*8-64 + lea dstq, [r5+16*2] + call .main + sub eobd, 128 ; eob < 271 + jl .ret + call .main + add cq, 64*8-64 + lea dstq, [r5+16*3] + call .main + sub eobd, 128 ; eob < 399 + jl .ret + call .main +.ret: + RET +ALIGN function_align +.main: + mova m0, [cq+64*0] + packssdw m0, [cq+64*1] + mova m1, [cq+64*2] + packssdw m1, [cq+64*3] + mova m2, [cq+64*4] + packssdw m2, [cq+64*5] + mova m3, [cq+64*6] + packssdw m3, [cq+64*7] +%if ARCH_X86_64 + REPX {pmulhrsw x, m8 }, m0, m1, m2, m3 +%else + mova m6, [o(pw_2896x8)] + REPX {pmulhrsw x, m6 }, m0, m1, m2, m3 +%endif + REPX {paddsw x, x }, m0, m1, m2, m3 +%if ARCH_X86_64 + pmulhrsw m4, m9, m0 + pmulhrsw m5, m9, m1 +%else + mova m6, [o(pw_1697x16)] + pmulhrsw m4, m6, m0 + pmulhrsw m5, m6, m1 +%endif + REPX {paddsw x, x }, m0, m1 + paddsw m0, m4 + paddsw m1, m5 +%if ARCH_X86_64 + pmulhrsw m4, m9, m2 + pmulhrsw m5, m9, m3 +%else + pmulhrsw m4, m6, m2 + pmulhrsw m6, m3 +%endif + REPX {paddsw x, x }, m2, m3 + paddsw m2, m4 +%if ARCH_X86_64 + paddsw m3, m5 + REPX {pmulhrsw x, m10}, m0, m1, m2, m3 +%else + paddsw m3, m6 + mova m6, [o(pw_2048)] + REPX {pmulhrsw x, m6 }, m0, m1, m2, m3 + pxor m6, m6 +%endif + REPX {mova [cq+64*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + call m(inv_txfm_add_identity_identity_8x32_16bpc).main + lea dstq, [dstq+strideq*4] + add cq, 16 + btc eobd, 16 + jnc .main + ret + +cglobal inv_txfm_add_identity_identity_32x32_16bpc, 4, 7, 8, dst, stride, c, eob +%undef cmp +%if ARCH_X86_32 + LEA r6, $$ +%endif + mova m5, [o(pw_8192)] + mova m7, [o(pixel_10bpc_max)] + pxor m6, m6 + lea r4, [strideq*3] + mov r5, dstq + call .main ; 0 + cmp eobd, 36 + jl .ret + add cq, 128*8-32 ; 0 1 + lea dstq, [r5+16] ; 1 + call .main + call .main2 + cmp eobd, 136 + jl .ret + add cq, 128*16-64 ; 0 1 2 + lea dstq, [r5+16*2] ; 1 2 + call .main ; 2 + call .main2 + call .main2 + cmp eobd, 300 + jl .ret + add cq, 128*24-96 ; 0 1 2 3 + add r5, 16*3 ; 1 2 3 + mov dstq, r5 ; 2 3 + call .main ; 3 + call .main2 + call .main2 + call .main2 + cmp eobd, 535 + jl .ret + add cq, 128*24-96 ; 0 1 2 3 + lea dstq, [r5+strideq*8] ; 1 2 3 4 + mov r5, dstq ; 2 3 4 + call .main ; 3 4 + call .main2 + call .main2 + cmp eobd, 755 + jl .ret + add cq, 128*16-64 ; 0 1 2 3 + lea dstq, [r5+strideq*8] ; 1 2 3 4 + mov r5, dstq ; 2 3 4 5 + call .main ; 3 4 5 + call .main2 + cmp eobd, 911 + jl .ret + add cq, 128*8-32 ; 0 1 2 3 + lea dstq, [r5+strideq*8] ; 1 2 3 4 + call .main ; 2 3 4 5 +.ret: ; 3 4 5 6 + RET +ALIGN function_align +.main2: + sub cq, 128*8 + sub dstq, 16 +.main: + mova m0, [cq+128*0] + packssdw m0, [cq+128*1] + mova m1, [cq+128*2] + packssdw m1, [cq+128*3] + mova m2, [cq+128*4] + packssdw m2, [cq+128*5] + mova m3, [cq+128*6] + packssdw m3, [cq+128*7] + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + call m(inv_txfm_add_identity_identity_8x32_16bpc).main_zero + lea dstq, [dstq+strideq*4] + add cq, 16 + btc eobd, 16 + jnc .main + ret + +cglobal inv_txfm_add_dct_dct_8x32_16bpc, 4, 7, 15, 0-36*16, \ + dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%define base $$ + DECLARE_REG_TMP 0, 4 +%else + lea r6, [tbl_Nx32_odd_offset] +%define base tbl_Nx32_odd_offset + DECLARE_REG_TMP 4, 7 +%if WIN64 + mov [rsp+gprsize*1+35*16], r7 +%endif +%endif +%define o2(x) r6-base+x + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + mov [rsp+gprsize*1+35*16], r0 +%endif +%undef cmp + ; remove entirely-zero iterations + mov r5d, 7*2 + cmp eobw, word [o2(tbl_8x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + mova [rsp+ 3*16+r5*8], m0 + mova [rsp+11*16+r5*8], m0 + mova [rsp+ 3*16+t0*8], m0 + mova [rsp+ 3*16+t1*8], m0 + sub r5d, 2 + cmp eobw, word [o2(tbl_8x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + ; actual first pass after skipping all-zero data + mov [rsp+gprsize*0+35*16], eobd + mov r3, rsp +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+0*128+r5*8] + mova m1, [cq+1*128+r5*8] + mova m2, [cq+2*128+r5*8] + mova m3, [cq+3*128+r5*8] + mova m4, [cq+4*128+r5*8] + mova m5, [cq+5*128+r5*8] + mova m6, [cq+6*128+r5*8] + mova m7, [cq+7*128+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1 + mova m1, [o(pd_2)] + REPX {paddd x, m1}, m0, m6, m5, m3 + call m(idct_8x4_internal_16bpc).round + REPX {psrad x, 2 }, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + call m(idct_8x4_internal_16bpc).transpose4x8packed + + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + mova [r3+ 3*16+r5*8], m0 + mova [r3+11*16+r5*8], m2 + mova [r3+ 3*16+t1*8], m1 + mova [r3+ 3*16+t0*8], m3 + pxor m7, m7 + REPX {mova [cq+x*128+r5*8], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + sub r5d, 2 + jge .loop_pass1 + + ; pass 2 code starts here + ; m0 is already loaded from last iteration of first pass +%if ARCH_X86_32 + mov r0, [rsp+gprsize*1+35*16] +%endif + mov eobd, [rsp+gprsize*0+35*16] + cmp eobd, 43 + jl .load_veryfast + cmp eobd, 107 + jl .load_fast + ; load normal + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main)] + jmp .run +.load_fast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + jmp .run +.load_veryfast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + ; fall-through +.run: + call .pass2 +%if WIN64 + mov r7, [rsp+gprsize*1+35*16] +%endif + RET + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + mova m1, [rsp+gprsize+16* 4] + mova m2, [rsp+gprsize+16* 5] + mova m3, [rsp+gprsize+16* 6] + mova m4, [rsp+gprsize+16* 7] + mova m5, [rsp+gprsize+16* 8] + mova m6, [rsp+gprsize+16* 9] + mova m7, [rsp+gprsize+16*10] + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + mova [rsp+gprsize+ 3*16], m0 + mova [rsp+gprsize+ 4*16], m1 + mova [rsp+gprsize+ 5*16], m2 + mova [rsp+gprsize+ 6*16], m3 + mova [rsp+gprsize+ 7*16], m4 + mova [rsp+gprsize+ 8*16], m5 + mova [rsp+gprsize+ 9*16], m6 + mova m0, [rsp+gprsize+11*16] + mova m1, [rsp+gprsize+12*16] + mova m2, [rsp+gprsize+13*16] + mova m3, [rsp+gprsize+14*16] + mova m4, [rsp+gprsize+15*16] + mova m5, [rsp+gprsize+16*16] + mova m6, [rsp+gprsize+17*16] + mova m7, [rsp+gprsize+18*16] + call m_suffix(idct_16x8_internal_8bpc, _ssse3).main + mova m7, [rsp+gprsize+ 0*16] + mova [rsp+gprsize+11*16], m0 + mova [rsp+gprsize+12*16], m1 + mova [rsp+gprsize+13*16], m2 + mova [rsp+gprsize+14*16], m3 + mova [rsp+gprsize+15*16], m4 + mova [rsp+gprsize+16*16], m5 + mova [rsp+gprsize+17*16], m6 + mova [rsp+gprsize+18*16], m7 + call r4 +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%endif + lea r3, [strideq*3] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + lea dstq, [dstq+strideq*8] + mova m0, [rsp+gprsize+11*16] + mova m1, [rsp+gprsize+12*16] + mova m2, [rsp+gprsize+13*16] + mova m3, [rsp+gprsize+14*16] + mova m4, [rsp+gprsize+15*16] + mova m5, [rsp+gprsize+16*16] + mova m6, [rsp+gprsize+17*16] + mova m7, [rsp+gprsize+18*16] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + lea dstq, [dstq+strideq*8] + mova m0, [rsp+gprsize+19*16] + mova m1, [rsp+gprsize+20*16] + mova m2, [rsp+gprsize+21*16] + mova m3, [rsp+gprsize+22*16] + mova m4, [rsp+gprsize+23*16] + mova m5, [rsp+gprsize+24*16] + mova m6, [rsp+gprsize+25*16] + mova m7, [rsp+gprsize+26*16] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + lea dstq, [dstq+strideq*8] + mova m0, [rsp+gprsize+27*16] + mova m1, [rsp+gprsize+28*16] + mova m2, [rsp+gprsize+29*16] + mova m3, [rsp+gprsize+30*16] + mova m4, [rsp+gprsize+31*16] + mova m5, [rsp+gprsize+32*16] + mova m6, [rsp+gprsize+33*16] + mova m7, [rsp+gprsize+34*16] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + ret +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 8 + add r5d, 640 + sar r5d, 10 + add rsp, (31+2*ARCH_X86_64)*16 + jmp m(inv_txfm_add_dct_dct_8x8_16bpc).end2 + +cglobal inv_txfm_add_dct_dct_16x32_16bpc, 4, 7, 16, 0-77*16, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + mov [rsp+gprsize*1+76*16], r0 +%elif WIN64 + mov [rsp+gprsize*1+76*16], r7 +%endif +%undef cmp + ; remove entirely-zero iterations + mov r5d, 7*2 + cmp eobw, word [o2(tbl_16x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + mova [rsp+12*16+r5*8], m0 + mova [rsp+20*16+r5*8], m0 + mova [rsp+12*16+t0*8], m0 + mova [rsp+12*16+t1*8], m0 + mova [rsp+44*16+r5*8], m0 + mova [rsp+52*16+r5*8], m0 + mova [rsp+44*16+t0*8], m0 + mova [rsp+44*16+t1*8], m0 + sub r5d, 2 + cmp eobw, word [o2(tbl_16x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + ; actual first pass after skipping all-zero data + mov [rsp+gprsize*0+76*16], eobd + mov r3, rsp +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 1*128+r5*8] + mova m1, [cq+ 3*128+r5*8] + mova m2, [cq+ 5*128+r5*8] + mova m3, [cq+ 7*128+r5*8] + mova m4, [cq+ 9*128+r5*8] + mova m5, [cq+11*128+r5*8] + mova m6, [cq+13*128+r5*8] + mova m7, [cq+15*128+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+ 0*128+r5*8] + mova m1, [cq+ 2*128+r5*8] + mova m2, [cq+ 4*128+r5*8] + mova m3, [cq+ 6*128+r5*8] + mova m4, [cq+ 8*128+r5*8] + mova m5, [cq+10*128+r5*8] + mova m6, [cq+12*128+r5*8] + mova m7, [cq+14*128+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + call m(idct_16x4_internal_16bpc).round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + call m(idct_8x4_internal_16bpc).transpose4x8packed + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 +%if ARCH_X86_64 + mova [rsp+12*16+r5*8], m0 + mova [rsp+20*16+r5*8], m2 + mova [rsp+12*16+t1*8], m1 + mova [rsp+12*16+t0*8], m3 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+44*16+r5*8], m8 + mova [rsp+52*16+r5*8], m10 + mova [rsp+44*16+t1*8], m9 + mova [rsp+44*16+t0*8], m11 +%else + mova [rsp+44*16+r5*8], m0 + mova [rsp+52*16+r5*8], m2 + mova [rsp+44*16+t1*8], m1 + mova [rsp+44*16+t0*8], m3 + mova m0, [r3+ 8*16] + mova m2, [r3+ 9*16] + mova m4, [r3+10*16] + mova m6, [r3+11*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+12*16+r5*8], m0 + mova [rsp+20*16+r5*8], m2 + mova [rsp+12*16+t1*8], m1 + mova [rsp+12*16+t0*8], m3 +%endif + pxor m7, m7 + REPX {mova [cq+x*128+r5*8], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 + add rsp, 9*16 +%if ARCH_X86_64 + mov r6, dstq +%else + mov dstq, [rsp+gprsize*1+67*16] +%endif + mov eobd, [rsp+gprsize*0+67*16] + cmp eobd, 44 + jl .load_veryfast + cmp eobd, 151 + jl .load_fast + ; load normal + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main)] + jmp .run +.load_fast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + jmp .run +.load_veryfast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + ; fall-through +.run: +%if ARCH_X86_64 + lea r2, [dstq+32] + mov r7, -4 +%else + lea r2, [rsp+67*16] + mov dword [r2+0*gprsize], 2 +%endif + jmp .loop_pass2_entry +.loop_pass2: + mova m0, [rsp+16* 3] +.loop_pass2_entry: +%if ARCH_X86_32 + mov dstq, [r2+1*gprsize] +%endif + call m(inv_txfm_add_dct_dct_8x32_16bpc).pass2 + add rsp, 32*16 +%if ARCH_X86_64 + add r7, 2 + lea dstq, [r2+r7*8] + jl .loop_pass2 +%if WIN64 + mov r7, [rsp+gprsize*1+3*16] +%endif +%else + add dword [r2+1*gprsize], 16 + dec dword [r2+0*gprsize] + jg .loop_pass2 +%endif +%assign stack_size (stack_size-73*16) +%if STACK_ALIGNMENT >= 16 +%assign stack_size_padded (stack_size_padded-73*16) +%assign stack_offset (stack_offset-73*16) +%else +%xdefine rstkm [rsp + stack_size] +%endif + RET +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 32 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + add rsp, (65+4*ARCH_X86_64)*16 + jmp m(inv_txfm_add_dct_dct_16x4_16bpc).dconly + +cglobal inv_txfm_add_dct_dct_32x8_16bpc, 4, 7, 16, 0-(24+8*ARCH_X86_32)*16, \ + dst, stride, c, eob +%if ARCH_X86_32 + LEA r6, $$ +%endif + test eobd, eobd + jz .dconly + + ; remove entirely-zero iterations +%undef cmp +%if ARCH_X86_64 + xor r5d, r5d + cmp eobd, 10 + setge r5b +%else + mov r5d, 1 + cmp eobd, 10 + sbb r5d, 0 +%endif + add r5d, r5d + + ; actual first pass after skipping all-zero data +.loop_pass1: + mova m0, [cq+32* 1+r5*8] + mova m1, [cq+32* 7+r5*8] + mova m2, [cq+32* 9+r5*8] + mova m3, [cq+32*15+r5*8] + mova m4, [cq+32*17+r5*8] + mova m5, [cq+32*23+r5*8] + mova m6, [cq+32*25+r5*8] + mova m7, [cq+32*31+r5*8] +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mov r3, rsp + call .main_oddhalf_part1 + mova m0, [cq+32* 3+r5*8] + mova m1, [cq+32* 5+r5*8] + mova m2, [cq+32*11+r5*8] + mova m3, [cq+32*13+r5*8] + mova m4, [cq+32*19+r5*8] + mova m5, [cq+32*21+r5*8] + mova m6, [cq+32*27+r5*8] + mova m7, [cq+32*29+r5*8] + call .main_oddhalf_part2 + mova m0, [cq+32* 2+r5*8] + mova m1, [cq+32* 6+r5*8] + mova m2, [cq+32*10+r5*8] + mova m3, [cq+32*14+r5*8] + mova m4, [cq+32*18+r5*8] + mova m5, [cq+32*22+r5*8] + mova m6, [cq+32*26+r5*8] + mova m7, [cq+32*30+r5*8] + add r3, 16*(16+4*ARCH_X86_32) + call m(idct_16x4_internal_16bpc).main_oddhalf + mova m0, [cq+32* 0+r5*8] + mova m1, [cq+32* 4+r5*8] + mova m2, [cq+32* 8+r5*8] + mova m3, [cq+32*12+r5*8] + mova m4, [cq+32*16+r5*8] + mova m5, [cq+32*20+r5*8] + mova m6, [cq+32*24+r5*8] + mova m7, [cq+32*28+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + sub r3, 16*(16+4*ARCH_X86_32) + call .round_dct32 +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).transpose4x8packed + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+32* 8+r5*8], m8 + mova [cq+32* 9+r5*8], m9 + mova [cq+32*10+r5*8], m10 + mova [cq+32*11+r5*8], m11 + mova m8, [r3+16* 9] ; 8 9 + mova m10, [r3+16*11] ; 10 11 + mova m12, [r3+16*13] ; 12 13 + mova m14, [r3+16*15] ; 14 15 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+32* 4+r5*8], m8 + mova [cq+32* 5+r5*8], m9 + mova [cq+32* 6+r5*8], m10 + mova [cq+32* 7+r5*8], m11 + mova m8, [r3+16* 8] ; 24 25 + mova m10, [r3+16*10] ; 26 27 + mova m12, [r3+16*12] ; 28 29 + mova m14, [r3+16*14] ; 30 31 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+32*12+r5*8], m8 + mova [cq+32*13+r5*8], m9 + mova [cq+32*14+r5*8], m10 + mova [cq+32*15+r5*8], m11 +%else + sub r3, 8*16 + mova m0, [r3+ 8*16] + mova m2, [r3+10*16] + mova m4, [r3+12*16] + mova m6, [r3+14*16] + packssdw m0, [r3+ 9*16] + packssdw m2, [r3+11*16] + packssdw m4, [r3+13*16] + packssdw m6, [r3+15*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+32* 4+r5*8], m0 + mova [cq+32* 5+r5*8], m1 + mova [cq+32* 6+r5*8], m2 + mova [cq+32* 7+r5*8], m3 + mova m0, [r3+16*16] + mova m2, [r3+18*16] + mova m4, [r3+20*16] + mova m6, [r3+22*16] + packssdw m0, [r3+17*16] + packssdw m2, [r3+19*16] + packssdw m4, [r3+21*16] + packssdw m6, [r3+23*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+32* 8+r5*8], m0 + mova [cq+32* 9+r5*8], m1 + mova [cq+32*10+r5*8], m2 + mova [cq+32*11+r5*8], m3 + mova m0, [r3+31*16] + mova m2, [r3+29*16] + mova m4, [r3+27*16] + mova m6, [r3+25*16] + packssdw m0, [r3+30*16] + packssdw m2, [r3+28*16] + packssdw m4, [r3+26*16] + packssdw m6, [r3+24*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+32*12+r5*8], m0 + mova [cq+32*13+r5*8], m1 + mova [cq+32*14+r5*8], m2 + mova [cq+32*15+r5*8], m3 + mova m0, [r3+ 0*16] + mova m2, [r3+ 2*16] + mova m4, [r3+ 4*16] + mova m6, [r3+ 6*16] + packssdw m0, [r3+ 1*16] + packssdw m2, [r3+ 3*16] + packssdw m4, [r3+ 5*16] + packssdw m6, [r3+ 7*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + pxor m7, m7 + ; clear lower half of [cq] + REPX {mova [cq+x*32+r5*8], m7}, 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + test r5d, r5d + jz .end_pass1 + mova [cq+32* 0+r5*8], m0 + mova [cq+32* 1+r5*8], m1 + mova [cq+32* 2+r5*8], m2 + mova [cq+32* 3+r5*8], m3 + sub r5d, 2 + jmp .loop_pass1 +.end_pass1: + + ; pass=2, we need to call this otherwise the stack pointer has + ; the wrong offset in the 8-bit code + mov r4d, 4 + call m(idct_16x8_internal_16bpc).pass2_main + RET + +.main_oddhalf_part1_fast: ; lower half zero + pmulld m7, m0, [o(pd_4091)] + pmulld m0, [o(pd_201)] + pmulld m4, m3, [o(pd_m2751)] +%if ARCH_X86_32 + pmulld m3, [o(pd_3035)] + mova m5, [o(pd_2048)] + REPX {paddd x, m5}, m0, m7 + REPX {psrad x, 12}, m0, m7 + mova [r3+3*16], m7 + mova m7, m3 + mova m3, m5 +%else + pmulld m3, [o(pd_3035)] +%endif + pmulld m6, m1, [o(pd_m1380)] + pmulld m1, [o(pd_3857)] + pmulld m5, m2, [o(pd_3703)] + pmulld m2, [o(pd_1751)] + jmp .main_oddhalf_part1_fast2 +.main_oddhalf_part1: ; in1, in7, in9, in15, in17, in23, in25, in31 +%if ARCH_X86_64 + ITX_MULSUB_2D 0, 7, 8, 9, 10, _, 201, 4091 ; t16a, t31a + ITX_MULSUB_2D 6, 1, 8, 9, 10, _, 3857, 1380 ; t19a, t28a + ITX_MULSUB_2D 2, 5, 8, 9, 10, _, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2D 4, 3, 8, 9, 10, _, 3035, 2751 ; t17a, t30a +.main_oddhalf_part1_fast2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m8, m0, m4 ; t17 + paddd m0, m4 ; t16 + psubd m4, m6, m2 ; t18 + paddd m6, m2 ; t19 + psubd m2, m1, m5 ; t29 + paddd m1, m5 ; t28 + psubd m5, m7, m3 ; t30 + paddd m7, m3 ; t31 + REPX {pmaxsd x, m12}, m8, m5, m4, m2, m0, m6, m1, m7 + REPX {pminsd x, m13}, m8, m5, m4, m2, m0, m6, m1, m7 + mova m15, [o(pd_4017)] + mova m10, [o(pd_799)] + ITX_MULSUB_2D 5, 8, 3, 9, _, 11, 10, 15 ; t17a, t30a + ITX_MULSUB_2D 2, 4, 3, 9, _, 11, 10, 15, 4 ; t29a, t18a + psubd m3, m0, m6 ; t19a + paddd m0, m6 ; t16a + psubd m6, m7, m1 ; t28a + paddd m7, m1 ; t31a + psubd m1, m5, m4 ; t18 + paddd m5, m4 ; t17 + psubd m4, m8, m2 ; t29 + paddd m8, m2 ; t30 + REPX {pmaxsd x, m12}, m3, m6, m1, m4, m0, m7, m5, m8 + REPX {pminsd x, m13}, m3, m6, m1, m4, m0, m7, m5, m8 + mova m15, [o(pd_3784)] + mova m10, [o(pd_1567)] + ITX_MULSUB_2D 4, 1, 2, 9, _, 11, 10, 15 ; t18a, t29a + ITX_MULSUB_2D 6, 3, 2, 9, _, 11, 10, 15 ; t19, t28 + mova [r3+16*0], m0 + mova [r3+16*1], m5 + mova [r3+16*2], m4 + mova [r3+16*3], m6 + mova [r3+16*4], m3 + mova [r3+16*5], m1 + mova [r3+16*6], m8 + mova [r3+16*7], m7 +%else + mova [r3+0*16], m2 + mova [r3+1*16], m3 + mova [r3+2*16], m4 + mova [r3+3*16], m5 + mova m3, [o(pd_2048)] + ITX_MULSUB_2D 0, 7, 2, 4, 5, 3, 201, 4091 ; t16a, t31a + ITX_MULSUB_2D 6, 1, 2, 4, 5, _, 3857, 1380 ; t19a, t28a + mova m4, [r3+2*16] + mova m5, [r3+3*16] + mova [r3+2*16], m6 + mova [r3+3*16], m7 + mova m2, [r3+0*16] + mova m7, [r3+1*16] + mova [r3+0*16], m0 + mova [r3+1*16], m1 + ITX_MULSUB_2D 2, 5, 0, 1, 6, _, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2D 4, 7, 0, 1, 6, _, 3035, 2751 ; t17a, t30a + mova m0, [r3+0*16] + mova m1, [r3+1*16] + mova m6, [r3+2*16] +.main_oddhalf_part1_fast2: + REPX {paddd x, m3}, m1, m2, m4, m5, m6, m7 + REPX {psrad x, 12}, m1, m2, m4, m5, m6, m7 + psubd m3, m0, m4 ; t17 + mova [r3+0*16], m3 + mova m3, [r3+3*16] + paddd m0, m4 ; t16 + psubd m4, m6, m2 ; t18 + paddd m6, m2 ; t19 + psubd m2, m1, m5 ; t29 + paddd m1, m5 ; t28 + psubd m5, m3, m7 ; t30 + paddd m7, m3 ; t31 + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m5, m4, m2, m0, m6, m1, m7 + pmaxsd m3, [r3+0*16] + mova [r3+0*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m5, m4, m2, m0, m6, m1, m7 + pminsd m3, [r3+0*16] + mova [r3+0*16], m0 + mova [r3+1*16], m1 + mova [r3+2*16], m6 + mova [r3+3*16], m7 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 5, 3, 1, 6, 7, 0, 799, 4017 ; t17a, t30a + ITX_MULSUB_2D 2, 4, 1, 6, _, 0, 7, 4017, 4 ; t29a, t18a + psubd m1, m5, m4 ; t18 + paddd m5, m4 ; t17 + psubd m4, m3, m2 ; t29 + paddd m3, m2 ; t30 + mova m0, [r3+0*16] + mova m2, [r3+1*16] + mova m6, [r3+2*16] + mova m7, [r3+3*16] + mova [r3+0*16], m3 + psubd m3, m0, m6 ; t19a + paddd m0, m6 ; t16a + psubd m6, m7, m2 ; t28a + paddd m7, m2 ; t31a + mova m2, [o(clip_18b_min)] + REPX {pmaxsd x, m2}, m3, m6, m1, m4, m0, m7, m5 + pmaxsd m2, [r3+0*16] + mova [r3+0*16], m2 + mova m2, [o(clip_18b_max)] + REPX {pminsd x, m2}, m3, m6, m1, m4, m0, m7, m5 + pminsd m2, [r3+0*16] + mova [r3+16*0], m0 + mova [r3+16*1], m5 + mova [r3+16*6], m2 + mova [r3+16*7], m7 + mova m7, [o(pd_2048)] + ITX_MULSUB_2D 4, 1, 0, 5, 2, 7, 1567, 3784 ; t18a, t29a + ITX_MULSUB_2D 6, 3, 0, 5, 2, 7, 2, 3784 ; t19, t28 + mova [r3+16*2], m4 + mova [r3+16*3], m6 + mova [r3+16*4], m3 + mova [r3+16*5], m1 +%endif + ret +.main_oddhalf_part2_fast: ; lower half zero + pmulld m7, m0, [o(pd_m601)] + pmulld m0, [o(pd_4052)] + pmulld m4, m3, [o(pd_3290)] +%if ARCH_X86_32 + pmulld m3, [o(pd_2440)] + mova m5, [o(pd_2048)] + REPX {paddd x, m5}, m0, m7 + REPX {psrad x, 12}, m0, m7 + mova [r3+11*16], m7 + mova m7, m3 + mova m3, m5 +%else + pmulld m3, [o(pd_2440)] +%endif + pmulld m6, m1, [o(pd_3973)] + pmulld m1, [o(pd_995)] + pmulld m5, m2, [o(pd_m2106)] + pmulld m2, [o(pd_3513)] + jmp .main_oddhalf_part2_fast2 +.main_oddhalf_part2: ; in3, in5, in11, in13, in19, in21, in27, in29 +%if ARCH_X86_64 + ITX_MULSUB_2D 7, 0, 8, 9, 10, _, 4052, 601 ; t23a, t24a + ITX_MULSUB_2D 1, 6, 8, 9, 10, _, 995, 3973 ; t20a, t27a + ITX_MULSUB_2D 5, 2, 8, 9, 10, _, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2D 3, 4, 8, 9, 10, _, 2440, 3290 ; t22a, t25a +.main_oddhalf_part2_fast2: + REPX {paddd x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {psrad x, 12 }, m0, m1, m2, m3, m4, m5, m6, m7 + psubd m8, m0, m4 ; t25 + paddd m0, m4 ; t24 + psubd m4, m6, m2 ; t26 + paddd m6, m2 ; t27 + psubd m2, m1, m5 ; t21 + paddd m1, m5 ; t20 + psubd m5, m7, m3 ; t22 + paddd m7, m3 ; t23 + REPX {pmaxsd x, m12}, m8, m5, m4, m2, m0, m6, m1, m7 + REPX {pminsd x, m13}, m8, m5, m4, m2, m0, m6, m1, m7 + mova m15, [o(pd_2276)] + mova m10, [o(pd_3406)] + ITX_MULSUB_2D 4, 2, 3, 9, _, 11, 10, 15 ; t21a, t26a + ITX_MULSUB_2D 8, 5, 3, 9, _, 11, 10, 15, 4 ; t25a, t22a + psubd m3, m0, m6 ; t27a + paddd m0, m6 ; t24a + psubd m6, m7, m1 ; t20a + paddd m7, m1 ; t23a + psubd m1, m5, m4 ; t21 + paddd m5, m4 ; t22 + psubd m4, m8, m2 ; t26 + paddd m8, m2 ; t25 + REPX {pmaxsd x, m12}, m3, m6, m1, m4, m0, m7, m5, m8 + REPX {pminsd x, m13}, m3, m6, m1, m4, m0, m7, m5, m8 + mova m15, [o(pd_3784)] + mova m10, [o(pd_1567)] + ITX_MULSUB_2D 4, 1, 2, 9, _, 11, 10, 15, 4 ; t26a, t21a + ITX_MULSUB_2D 3, 6, 2, 9, _, 11, 10, 15, 4 ; t27, t20 + mova m9, [r3+16*0] ; t16a + mova m10, [r3+16*1] ; t17 + psubd m2, m9, m7 ; t23 + paddd m9, m7 ; t16 + psubd m7, m10, m5 ; t22a + paddd m10, m5 ; t17a + REPX {pmaxsd x, m12}, m9, m10, m2, m7 + REPX {pminsd x, m13}, m9, m10, m2, m7 + mova [r3+16*0], m9 + mova [r3+16*1], m10 + mova m9, [r3+16*2] ; t18a + mova m10, [r3+16*3] ; t19 + psubd m5, m9, m1 ; t21 + paddd m9, m1 ; t18 + psubd m1, m10, m6 ; t20a + paddd m10, m6 ; t19a + REPX {pmaxsd x, m12}, m9, m10, m5, m1 + REPX {pminsd x, m13}, m9, m10, m5, m1 + mova [r3+16*2], m9 + mova [r3+16*3], m10 + mova m9, [r3+16*4] ; t28 + mova m10, [r3+16*5] ; t29a + psubd m6, m9, m3 ; t27a + paddd m9, m3 ; t28a + psubd m3, m10, m4 ; t26 + paddd m10, m4 ; t29 + REPX {pmaxsd x, m12}, m9, m10, m6, m3 + REPX {pminsd x, m13}, m9, m10, m6, m3 + REPX {pmulld x, m14}, m6, m3, m1, m5 + paddd m6, m11 + paddd m3, m11 + psubd m4, m6, m1 ; t20 + paddd m6, m1 ; t27 + psubd m1, m3, m5 ; t21a + paddd m3, m5 ; t26a + REPX {psrad x, 12 }, m4, m1, m3, m6 + mova [r3+16*4], m4 + mova [r3+16*5], m1 + mova m4, [r3+16*6] ; t30 + mova m1, [r3+16*7] ; t31a + psubd m5, m4, m8 ; t25a + paddd m4, m8 ; t30a + psubd m8, m1, m0 ; t24 + paddd m1, m0 ; t31 + REPX {pmaxsd x, m12}, m8, m5, m4, m1 + REPX {pminsd x, m13}, m8, m5, m4, m1 + REPX {pmulld x, m14}, m5, m8, m7, m2 + paddd m5, m11 + paddd m8, m11 + psubd m0, m5, m7 ; t22 + paddd m5, m7 ; t25 + psubd m7, m8, m2 ; t23a + paddd m2, m8 ; t24a + REPX {psrad x, 12 }, m0, m7, m2, m5 + mova [r3+16*6], m0 + mova [r3+16*7], m7 + mova [r3+16*8], m2 + mova [r3+16*9], m5 + mova [r3+16*10], m3 + mova [r3+16*11], m6 + mova [r3+16*12], m9 + mova [r3+16*13], m10 + mova [r3+16*14], m4 + mova [r3+16*15], m1 +%else + mova [r3+ 8*16], m2 + mova [r3+ 9*16], m3 + mova [r3+10*16], m4 + mova [r3+11*16], m5 + mova m3, [o(pd_2048)] + ITX_MULSUB_2D 7, 0, 2, 4, 5, 3, 4052, 601 ; t23a, t24a + ITX_MULSUB_2D 1, 6, 2, 4, 5, _, 995, 3973 ; t20a, t27a + mova m2, [r3+ 8*16] + mova m4, [r3+10*16] + mova m5, [r3+11*16] + mova [r3+ 8*16], m0 + mova [r3+10*16], m6 + mova [r3+11*16], m7 + mova m7, [r3+ 9*16] + mova [r3+ 9*16], m1 + ITX_MULSUB_2D 5, 2, 0, 6, 1, _, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2D 7, 4, 0, 6, 1, _, 2440, 3290 ; t22a, t25a + mova m0, [r3+ 8*16] + mova m1, [r3+ 9*16] + mova m6, [r3+10*16] +.main_oddhalf_part2_fast2: + REPX {paddd x, m3}, m1, m2, m7, m4, m5, m6 + REPX {psrad x, 12}, m1, m2, m7, m4, m5, m6 + psubd m3, m0, m4 ; t25 + mova [r3+ 8*16], m3 + mova m3, [r3+11*16] + paddd m0, m4 ; t24 + psubd m4, m6, m2 ; t26 + paddd m6, m2 ; t27 + psubd m2, m1, m5 ; t21 + paddd m1, m5 ; t20 + psubd m5, m3, m7 ; t22 + paddd m7, m3 ; t23 + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m5, m4, m2, m0, m6, m1, m7 + pmaxsd m3, [r3+ 8*16] + mova [r3+ 8*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m5, m4, m2, m0, m6, m1, m7 + pminsd m3, [r3+ 8*16] + mova [r3+ 8*16], m0 + mova [r3+ 9*16], m1 + mova [r3+10*16], m6 + mova [r3+11*16], m7 + mova m7, [o(pd_2048)] + ITX_MULSUB_2D 4, 2, 0, 1, 6, 7, 3406, 2276 ; t21a, t26a + ITX_MULSUB_2D 3, 5, 0, 1, _, 7, 6, 2276, 4 ; t25a, t22a + psubd m1, m5, m4 ; t21 + paddd m5, m4 ; t22 + psubd m4, m3, m2 ; t26 + paddd m3, m2 ; t25 + mova m0, [r3+ 8*16] + mova m2, [r3+ 9*16] + mova m6, [r3+10*16] + mova m7, [r3+11*16] + mova [r3+ 8*16], m3 + psubd m3, m0, m6 ; t27a + paddd m0, m6 ; t24a + psubd m6, m7, m2 ; t20a + paddd m7, m2 ; t23a + mova m2, [o(clip_18b_min)] + REPX {pmaxsd x, m2}, m3, m6, m1, m4, m0, m7, m5 + pmaxsd m2, [r3+ 8*16] + mova [r3+ 8*16], m2 + mova m2, [o(clip_18b_max)] + REPX {pminsd x, m2}, m3, m6, m1, m4, m0, m7, m5 + pminsd m2, [r3+ 8*16] + mova [r3+ 8*16], m0 + mova [r3+ 9*16], m2 + mova [r3+14*16], m5 + mova [r3+15*16], m7 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 4, 1, 2, 5, 7, 0, 1567, 3784, 4 ; t26a, t21a + ITX_MULSUB_2D 3, 6, 2, 5, _, 0, 7, 3784, 4 ; t27, t20 + mova [r3+10*16], m3 + mova m0, [o(clip_18b_min)] + mova m2, [o(clip_18b_max)] + mova m5, [r3+16*2] ; t18a + mova m7, [r3+16*3] ; t19 + psubd m3, m5, m1 ; t21 + paddd m5, m1 ; t18 + psubd m1, m7, m6 ; t20a + paddd m7, m6 ; t19a + REPX {pmaxsd x, m0}, m5, m7, m3, m1 + REPX {pminsd x, m2}, m5, m7, m3, m1 + mova [r3+16*2], m5 + mova [r3+16*3], m7 + mova [r3+11*16], m3 + mova m3, [r3+10*16] + mova m5, [r3+16*4] ; t28 + mova m7, [r3+16*5] ; t29a + psubd m6, m5, m3 ; t27a + paddd m5, m3 ; t28a + psubd m3, m7, m4 ; t26 + paddd m7, m4 ; t29 + REPX {pmaxsd x, m0}, m5, m7, m6, m3 + REPX {pminsd x, m2}, m5, m7, m6, m3 + mova [r3+16*12], m5 + mova [r3+16*13], m7 + mova m5, [o(pd_2048)] + mova m7, [o(pd_2896)] + mova m4, [r3+11*16] + REPX {pmulld x, m7}, m6, m3, m1, m4 + paddd m6, m5 + paddd m3, m5 + psubd m5, m6, m1 ; t20 + paddd m6, m1 ; t27 + psubd m1, m3, m4 ; t21a + paddd m3, m4 ; t26a + REPX {psrad x, 12}, m5, m1, m3, m6 + mova [r3+16*4], m5 + mova [r3+16*5], m1 + mova [r3+16*10], m3 + mova [r3+16*11], m6 + + mova m5, [r3+14*16] + mova m6, [r3+15*16] + mova m3, [r3+16*0] ; t16a + mova m4, [r3+16*1] ; t17 + psubd m1, m3, m6 ; t23 + paddd m3, m6 ; t16 + psubd m6, m4, m5 ; t22a + paddd m4, m5 ; t17a + REPX {pmaxsd x, m0}, m3, m4, m1, m6 + REPX {pminsd x, m2}, m3, m4, m1, m6 + mova [r3+16*0], m3 + mova [r3+16*1], m4 + mova m5, [r3+ 8*16] + mova m3, [r3+ 9*16] + mova [r3+ 8*16], m1 + mova [r3+ 9*16], m6 + mova m4, [r3+16*6] ; t30 + mova m1, [r3+16*7] ; t31a + psubd m6, m1, m5 ; t24 + paddd m1, m5 ; t31 + psubd m5, m4, m3 ; t25a + paddd m4, m3 ; t30a + REPX {pmaxsd x, m0}, m6, m5, m4, m1 + REPX {pminsd x, m2}, m6, m5, m4, m1 + mova [r3+16*14], m4 + mova [r3+16*15], m1 + mova m4, [o(pd_2048)] + mova m1, [r3+ 9*16] + mova m2, [r3+ 8*16] + REPX {pmulld x, m7}, m5, m6, m1, m2 + paddd m5, m4 + paddd m6, m4 + psubd m0, m5, m1 ; t22 + paddd m5, m1 ; t25 + psubd m1, m6, m2 ; t23a + paddd m2, m6 ; t24a + REPX {psrad x, 12}, m0, m1, m2, m5 + mova [r3+16*6], m0 + mova [r3+16*7], m1 + mova [r3+16*8], m2 + mova [r3+16*9], m5 +%endif + ret + + ; final sumsub for idct16 as well as idct32, plus final downshift +%macro IDCT32_END 6 ; in/out1, out2-4, tmp, shift, idx + mova m%4, [r3+16*(23-%1)] + pmaxsd m%1, m12 + pminsd m%1, m13 + psubd m%3, m%1, m%4 ; idct16 out15 - n + paddd m%1, m%4 ; idct16 out0 + n + pmaxsd m%1, m12 + pmaxsd m%3, m12 + pminsd m%1, m13 + pminsd m%3, m13 + paddd m%1, m11 + paddd m%3, m11 + mova m%5, [r3+16*( 0+%1)] + mova m%2, [r3+16*(15-%1)] + psubd m%4, m%1, m%2 ; out31 - n + paddd m%1, m%2 ; out0 + n + paddd m%2, m%3, m%5 ; out15 - n + psubd m%3, m%5 ; out16 + n + REPX {psrad x, %6}, m%1, m%3, m%2, m%4 +%endmacro + +.round_dct32: +%if ARCH_X86_64 + psrld m11, 10 ; pd_2 + IDCT32_END 0, 15, 8, 9, 10, 2 ; 0 15 16 31 + mova [r3+ 0*16], m6 + mova [r3+23*16], m7 + IDCT32_END 1, 14, 6, 7, 10, 2 ; 1 14 17 30 + packssdw m0, m1 ; 0 1 + packssdw m14, m15 ; 14 15 + packssdw m8, m6 ; 16 17 + packssdw m7, m9 ; 30 31 + mova [r3+16*15], m14 + mova [r3+16*14], m7 + IDCT32_END 2, 15, 10, 7, 6, 2 ; 2 13 18 29 + IDCT32_END 3, 14, 1, 9, 6, 2 ; 3 12 19 28 + packssdw m2, m3 ; 2 3 + packssdw m14, m15 ; 12 13 + packssdw m10, m1 ; 18 19 + packssdw m9, m7 ; 28 29 + mova [r3+16*13], m14 + mova [r3+16*12], m9 + IDCT32_END 4, 15, 1, 7, 6, 2 ; 4 11 20 27 + IDCT32_END 5, 14, 3, 9, 6, 2 ; 5 10 21 26 + packssdw m4, m5 ; 4 5 + packssdw m14, m15 ; 10 11 + packssdw m1, m3 ; 20 21 + packssdw m9, m7 ; 26 27 + mova [r3+16*11], m14 + mova [r3+16*10], m9 + mova m6, [r3+ 0*16] + mova m7, [r3+23*16] + IDCT32_END 6, 15, 14, 5, 3, 2 ; 6 9 22 25 + IDCT32_END 7, 11, 3, 9, 13, 2 ; 7 8 23 24 + packssdw m6, m7 ; 6 7 + packssdw m11, m15 ; 8 9 + packssdw m14, m3 ; 22 23 + packssdw m9, m5 ; 24 25 + mova [r3+16*9], m11 + mova [r3+16*8], m9 + mova m12, m1 + ret +%else + mova [r3+16*16], m0 + mova [r3+17*16], m1 + mova [r3+18*16], m2 + mova [r3+19*16], m3 + mova [r3+20*16], m4 + mova [r3+21*16], m5 + mova [r3+22*16], m6 + mova [r3+23*16], m7 + mova m1, [o(pd_2)] + mova m2, [o(clip_18b_min)] + mova m3, [o(clip_18b_max)] + + mov r4, 15*16 +.loop_dct32_end: + mova m0, [r3+16*16] + mova m6, [r3+16*24] + pmaxsd m0, m2 + pminsd m0, m3 + psubd m5, m0, m6 ; idct16 out15 - n + paddd m0, m6 ; idct16 out0 + n + pmaxsd m0, m2 + pmaxsd m5, m2 + pminsd m0, m3 + pminsd m5, m3 + paddd m0, m1 + paddd m5, m1 + mova m7, [r3] + mova m4, [r3+r4] + psubd m6, m0, m4 ; out31 - n + paddd m0, m4 ; out0 + n + paddd m4, m5, m7 ; out15 - n + psubd m5, m7 ; out16 + n + REPX {psrad x, 2}, m0, m5, m4, m6 + mova [r3], m0 + mova [r3+r4], m4 + mova [r3+16*16], m5 + mova [r3+24*16], m6 + add r3, 16 + sub r4, 32 + jg .loop_dct32_end + ret +%endif + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 8 +.dconly1: + add r5d, 640 + sar r5d, 10 +.dconly2: + imul r5d, 2896 + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + punpcklqdq m0, m0 + mova m6, [o(pixel_10bpc_max)] + pxor m5, m5 +.dconly_loop: + mova m1, [dstq+16*0] + mova m2, [dstq+16*1] + mova m3, [dstq+16*2] + mova m4, [dstq+16*3] + REPX {paddw x, m0}, m1, m2, m3, m4 + REPX {pminsw x, m6}, m1, m2, m3, m4 + REPX {pmaxsw x, m5}, m1, m2, m3, m4 + mova [dstq+16*0], m1 + mova [dstq+16*1], m2 + mova [dstq+16*2], m3 + mova [dstq+16*3], m4 + add dstq, strideq + dec r3d + jg .dconly_loop + RET + +cglobal inv_txfm_add_dct_dct_32x16_16bpc, 4, 7, 16, 0-(24+8*ARCH_X86_32)*16, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + + ; remove entirely-zero iterations +%undef cmp + mov r5d, 8 +.zero_loop: + sub r5d, 2 + cmp eobw, word [o2(tbl_32x16_2d)+r5] + jl .zero_loop + + ; actual first pass after skipping all-zero data +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+64* 1+r5*8] + mova m1, [cq+64* 7+r5*8] + mova m2, [cq+64* 9+r5*8] + mova m3, [cq+64*15+r5*8] + mova m4, [cq+64*17+r5*8] + mova m5, [cq+64*23+r5*8] + mova m6, [cq+64*25+r5*8] + mova m7, [cq+64*31+r5*8] + mov r3, rsp + call m(idct_8x4_internal_16bpc).rect2_mul + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1 + + mova m0, [cq+64* 3+r5*8] + mova m1, [cq+64* 5+r5*8] + mova m2, [cq+64*11+r5*8] + mova m3, [cq+64*13+r5*8] + mova m4, [cq+64*19+r5*8] + mova m5, [cq+64*21+r5*8] + mova m6, [cq+64*27+r5*8] + mova m7, [cq+64*29+r5*8] +%if ARCH_X86_32 + add r3, 16*8 +%endif + call m(idct_8x4_internal_16bpc).rect2_mul +%if ARCH_X86_32 + sub r3, 16*8 +%endif + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2 + add r3, 16*(16+4*ARCH_X86_32) + + mova m0, [cq+64* 2+r5*8] + mova m1, [cq+64* 6+r5*8] + mova m2, [cq+64*10+r5*8] + mova m3, [cq+64*14+r5*8] + mova m4, [cq+64*18+r5*8] + mova m5, [cq+64*22+r5*8] + mova m6, [cq+64*26+r5*8] + mova m7, [cq+64*30+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+64* 0+r5*8] + mova m1, [cq+64* 4+r5*8] + mova m2, [cq+64* 8+r5*8] + mova m3, [cq+64*12+r5*8] + mova m4, [cq+64*16+r5*8] + mova m5, [cq+64*20+r5*8] + mova m6, [cq+64*24+r5*8] + mova m7, [cq+64*28+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + sub r3, 16*(16+4*ARCH_X86_32) + call .round_dct32 + +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).transpose4x8packed + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+64* 8+r5*8], m8 + mova [cq+64* 9+r5*8], m9 + mova [cq+64*10+r5*8], m10 + mova [cq+64*11+r5*8], m11 + mova m8, [r3+16* 9] ; 8 9 + mova m10, [r3+16*11] ; 10 11 + mova m12, [r3+16*13] ; 12 13 + mova m14, [r3+16*15] ; 14 15 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+64* 4+r5*8], m8 + mova [cq+64* 5+r5*8], m9 + mova [cq+64* 6+r5*8], m10 + mova [cq+64* 7+r5*8], m11 + mova m8, [r3+16* 8] ; 24 25 + mova m10, [r3+16*10] ; 26 27 + mova m12, [r3+16*12] ; 28 29 + mova m14, [r3+16*14] ; 30 31 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [cq+64*12+r5*8], m8 + mova [cq+64*13+r5*8], m9 + mova [cq+64*14+r5*8], m10 + mova [cq+64*15+r5*8], m11 +%else + sub r3, 8*16 + mova m0, [r3+ 8*16] + mova m2, [r3+10*16] + mova m4, [r3+12*16] + mova m6, [r3+14*16] + packssdw m0, [r3+ 9*16] + packssdw m2, [r3+11*16] + packssdw m4, [r3+13*16] + packssdw m6, [r3+15*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+64* 4+r5*8], m0 + mova [cq+64* 5+r5*8], m1 + mova [cq+64* 6+r5*8], m2 + mova [cq+64* 7+r5*8], m3 + mova m0, [r3+16*16] + mova m2, [r3+18*16] + mova m4, [r3+20*16] + mova m6, [r3+22*16] + packssdw m0, [r3+17*16] + packssdw m2, [r3+19*16] + packssdw m4, [r3+21*16] + packssdw m6, [r3+23*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+64* 8+r5*8], m0 + mova [cq+64* 9+r5*8], m1 + mova [cq+64*10+r5*8], m2 + mova [cq+64*11+r5*8], m3 + mova m0, [r3+31*16] + mova m2, [r3+29*16] + mova m4, [r3+27*16] + mova m6, [r3+25*16] + packssdw m0, [r3+30*16] + packssdw m2, [r3+28*16] + packssdw m4, [r3+26*16] + packssdw m6, [r3+24*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [cq+64*12+r5*8], m0 + mova [cq+64*13+r5*8], m1 + mova [cq+64*14+r5*8], m2 + mova [cq+64*15+r5*8], m3 + mova m0, [r3+ 0*16] + mova m2, [r3+ 2*16] + mova m4, [r3+ 4*16] + mova m6, [r3+ 6*16] + packssdw m0, [r3+ 1*16] + packssdw m2, [r3+ 3*16] + packssdw m4, [r3+ 5*16] + packssdw m6, [r3+ 7*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + mova [cq+64* 0+r5*8], m0 + mova [cq+64* 1+r5*8], m1 + mova [cq+64* 2+r5*8], m2 + mova [cq+64* 3+r5*8], m3 + pxor m0, m0 + REPX {mova [cq+x*64+r5*8], m0}, 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + sub r5d, 2 + jge .loop_pass1 + + ; pass=2, we need to call this otherwise the stack pointer has + ; the wrong offset in the 8-bit code + call .pass2 + RET + +.pass2: +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%endif + mov r7, dstq +%else + mov [rsp+2*gprsize+16*16], dstq +%endif + lea r3, [strideq*3] + mov r4d, 4 + jmp m(idct_16x16_internal_16bpc).loop_pass2 + +.round_dct32: +%if ARCH_X86_64 + psrld m11, 11 ; pd_1 + IDCT32_END 0, 15, 8, 9, 10, 1 ; 0 15 16 31 + mova [r3+ 0*16], m6 + mova [r3+23*16], m7 + IDCT32_END 1, 14, 6, 7, 10, 1 ; 1 14 17 30 + packssdw m0, m1 ; 0 1 + packssdw m14, m15 ; 14 15 + packssdw m8, m6 ; 16 17 + packssdw m7, m9 ; 30 31 + mova [r3+16*15], m14 + mova [r3+16*14], m7 + IDCT32_END 2, 15, 10, 7, 6, 1 ; 2 13 18 29 + IDCT32_END 3, 14, 1, 9, 6, 1 ; 3 12 19 28 + packssdw m2, m3 ; 2 3 + packssdw m14, m15 ; 12 13 + packssdw m10, m1 ; 18 19 + packssdw m9, m7 ; 28 29 + mova [r3+16*13], m14 + mova [r3+16*12], m9 + IDCT32_END 4, 15, 1, 7, 6, 1 ; 4 11 20 27 + IDCT32_END 5, 14, 3, 9, 6, 1 ; 5 10 21 26 + packssdw m4, m5 ; 4 5 + packssdw m14, m15 ; 10 11 + packssdw m1, m3 ; 20 21 + packssdw m9, m7 ; 26 27 + mova [r3+16*11], m14 + mova [r3+16*10], m9 + mova m6, [r3+ 0*16] + mova m7, [r3+23*16] + IDCT32_END 6, 15, 14, 5, 3, 1 ; 6 9 22 25 + IDCT32_END 7, 11, 3, 9, 13, 1 ; 7 8 23 24 + packssdw m6, m7 ; 6 7 + packssdw m11, m15 ; 8 9 + packssdw m14, m3 ; 22 23 + packssdw m9, m5 ; 24 25 + mova [r3+16*9], m11 + mova [r3+16*8], m9 + mova m12, m1 + ret +%else + mova [r3+16*16], m0 + mova [r3+17*16], m1 + mova [r3+18*16], m2 + mova [r3+19*16], m3 + mova [r3+20*16], m4 + mova [r3+21*16], m5 + mova [r3+22*16], m6 + mova [r3+23*16], m7 + pcmpeqd m1, m1 ; -1 + mova m2, [o(clip_18b_min)] + mova m3, [o(clip_18b_max)] + + mov r4, 15*16 +.loop_dct32_end: + mova m0, [r3+16*16] + mova m6, [r3+16*24] + psubd m5, m0, m6 ; idct16 out15 - n + paddd m0, m6 ; idct16 out0 + n + pmaxsd m0, m2 + pmaxsd m5, m2 + pminsd m0, m3 + pminsd m5, m3 + psubd m0, m1 + psubd m5, m1 + mova m7, [r3] + mova m4, [r3+r4] + psubd m6, m0, m4 ; out31 - n + paddd m0, m4 ; out0 + n + paddd m4, m5, m7 ; out15 - n + psubd m5, m7 ; out16 + n + REPX {psrad x, 1}, m0, m5, m4, m6 + mova [r3], m0 + mova [r3+r4], m4 + mova [r3+16*16], m5 + mova [r3+24*16], m6 + add r3, 16 + sub r4, 32 + jg .loop_dct32_end + ret +%endif + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 16 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + add r5d, 384 + sar r5d, 9 + jmp m(inv_txfm_add_dct_dct_32x8_16bpc).dconly2 + +cglobal inv_txfm_add_dct_dct_32x32_16bpc, 4, 7, 16, 0-(5*32+1)*16, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + + ; remove entirely-zero iterations +%if ARCH_X86_32 + mov [rsp+5*32*16+1*gprsize], dstq +%elif WIN64 + mov [rsp+5*32*16+1*gprsize], r7 +%endif +%undef cmp + mov r5d, 14 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + mova [rsp+32*16+r5*8+0*32*16], m0 + mova [rsp+40*16+r5*8+0*32*16], m0 + mova [rsp+32*16+t0*8+0*32*16], m0 + mova [rsp+32*16+t1*8+0*32*16], m0 + mova [rsp+32*16+r5*8+1*32*16], m0 + mova [rsp+40*16+r5*8+1*32*16], m0 + mova [rsp+32*16+t0*8+1*32*16], m0 + mova [rsp+32*16+t1*8+1*32*16], m0 + mova [rsp+32*16+r5*8+2*32*16], m0 + mova [rsp+40*16+r5*8+2*32*16], m0 + mova [rsp+32*16+t0*8+2*32*16], m0 + mova [rsp+32*16+t1*8+2*32*16], m0 + mova [rsp+32*16+r5*8+3*32*16], m0 + mova [rsp+40*16+r5*8+3*32*16], m0 + mova [rsp+32*16+t0*8+3*32*16], m0 + mova [rsp+32*16+t1*8+3*32*16], m0 + sub r5d, 2 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + + ; actual first pass after skipping all-zero data + mov [rsp+gprsize*0+5*32*16], eobd +.loop_pass1: + mova m0, [cq+128* 1+r5*8] + mova m1, [cq+128* 7+r5*8] + mova m2, [cq+128* 9+r5*8] + mova m3, [cq+128*15+r5*8] + mova m4, [cq+128*17+r5*8] + mova m5, [cq+128*23+r5*8] + mova m6, [cq+128*25+r5*8] + mova m7, [cq+128*31+r5*8] +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mov r3, rsp + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1 + mova m0, [cq+128* 3+r5*8] + mova m1, [cq+128* 5+r5*8] + mova m2, [cq+128*11+r5*8] + mova m3, [cq+128*13+r5*8] + mova m4, [cq+128*19+r5*8] + mova m5, [cq+128*21+r5*8] + mova m6, [cq+128*27+r5*8] + mova m7, [cq+128*29+r5*8] + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2 + mova m0, [cq+128* 2+r5*8] + mova m1, [cq+128* 6+r5*8] + mova m2, [cq+128*10+r5*8] + mova m3, [cq+128*14+r5*8] + mova m4, [cq+128*18+r5*8] + mova m5, [cq+128*22+r5*8] + mova m6, [cq+128*26+r5*8] + mova m7, [cq+128*30+r5*8] + add r3, 16*(16+4*ARCH_X86_32) + call m(idct_16x4_internal_16bpc).main_oddhalf + mova m0, [cq+128* 0+r5*8] + mova m1, [cq+128* 4+r5*8] + mova m2, [cq+128* 8+r5*8] + mova m3, [cq+128*12+r5*8] + mova m4, [cq+128*16+r5*8] + mova m5, [cq+128*20+r5*8] + mova m6, [cq+128*24+r5*8] + mova m7, [cq+128*28+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + sub r3, 16*(16+4*ARCH_X86_32) + call m(inv_txfm_add_dct_dct_32x8_16bpc).round_dct32 + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).transpose4x8packed + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+32*16+r5*8+2*32*16], m8 + mova [rsp+40*16+r5*8+2*32*16], m10 + mova [rsp+32*16+t1*8+2*32*16], m9 + mova [rsp+32*16+t0*8+2*32*16], m11 + mova m8, [r3+16* 9] ; 8 9 + mova m10, [r3+16*11] ; 10 11 + mova m12, [r3+16*13] ; 12 13 + mova m14, [r3+16*15] ; 14 15 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+32*16+r5*8+1*32*16], m8 + mova [rsp+40*16+r5*8+1*32*16], m10 + mova [rsp+32*16+t1*8+1*32*16], m9 + mova [rsp+32*16+t0*8+1*32*16], m11 + mova m8, [r3+16* 8] ; 24 25 + mova m10, [r3+16*10] ; 26 27 + mova m12, [r3+16*12] ; 28 29 + mova m14, [r3+16*14] ; 30 31 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+32*16+r5*8+3*32*16], m8 + mova [rsp+40*16+r5*8+3*32*16], m10 + mova [rsp+32*16+t1*8+3*32*16], m9 + mova [rsp+32*16+t0*8+3*32*16], m11 +%else + sub r3, 8*16 + mova m0, [r3+ 8*16] + mova m2, [r3+10*16] + mova m4, [r3+12*16] + mova m6, [r3+14*16] + packssdw m0, [r3+ 9*16] + packssdw m2, [r3+11*16] + packssdw m4, [r3+13*16] + packssdw m6, [r3+15*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+32*16+r5*8+1*32*16], m0 + mova [rsp+40*16+r5*8+1*32*16], m2 + mova [rsp+32*16+t1*8+1*32*16], m1 + mova [rsp+32*16+t0*8+1*32*16], m3 + mova m0, [r3+16*16] + mova m2, [r3+18*16] + mova m4, [r3+20*16] + mova m6, [r3+22*16] + packssdw m0, [r3+17*16] + packssdw m2, [r3+19*16] + packssdw m4, [r3+21*16] + packssdw m6, [r3+23*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+32*16+r5*8+2*32*16], m0 + mova [rsp+40*16+r5*8+2*32*16], m2 + mova [rsp+32*16+t1*8+2*32*16], m1 + mova [rsp+32*16+t0*8+2*32*16], m3 + mova m0, [r3+31*16] + mova m2, [r3+29*16] + mova m4, [r3+27*16] + mova m6, [r3+25*16] + packssdw m0, [r3+30*16] + packssdw m2, [r3+28*16] + packssdw m4, [r3+26*16] + packssdw m6, [r3+24*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+32*16+r5*8+3*32*16], m0 + mova [rsp+40*16+r5*8+3*32*16], m2 + mova [rsp+32*16+t1*8+3*32*16], m1 + mova [rsp+32*16+t0*8+3*32*16], m3 + mova m0, [r3+ 0*16] + mova m2, [r3+ 2*16] + mova m4, [r3+ 4*16] + mova m6, [r3+ 6*16] + packssdw m0, [r3+ 1*16] + packssdw m2, [r3+ 3*16] + packssdw m4, [r3+ 5*16] + packssdw m6, [r3+ 7*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + pxor m7, m7 + ; clear lower half of [cq] + REPX {mova [cq+x*128+r5*8], m7}, 0, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + mova [rsp+32*16+r5*8+0*32*16], m0 + mova [rsp+40*16+r5*8+0*32*16], m2 + mova [rsp+32*16+t1*8+0*32*16], m1 + mova [rsp+32*16+t0*8+0*32*16], m3 + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 code starts here + mov eobd, [rsp+gprsize*0+5*32*16] + add rsp, 29*16 + cmp eobd, 36 + jl .load_veryfast + cmp eobd, 136 + jl .load_fast + ; load normal + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main)] + jmp .run +.load_fast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + jmp .run +.load_veryfast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + ; fall-through +.run: +%if ARCH_X86_64 + lea r2, [dstq+64] + mov r7, -8 +%else + lea r2, [rsp+(4*32+3)*16] + mov dword [r2+0*gprsize], 4 +%endif + jmp m(inv_txfm_add_dct_dct_16x32_16bpc).loop_pass2_entry + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 32 + add rsp, (5*32+1-(24+8*ARCH_X86_32))*16 + jmp m(inv_txfm_add_dct_dct_32x8_16bpc).dconly1 + +cglobal inv_txfm_add_dct_dct_16x64_16bpc, 4, 7, 16, \ + 0-(12+2*64)*16-(4+4*ARCH_X86_32)*gprsize, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 2, 0 + mov [rsp+gprsize*1+(64*2+12)*16], r0 + mov [rsp+gprsize*2+(64*2+12)*16], r1 + mov [rsp+gprsize*3+(64*2+12)*16], r2 +%else + DECLARE_REG_TMP 8, 9, 4, 7 + mov [rsp+gprsize*1+(64*2+12)*16], r9 +%if WIN64 + mov [rsp+gprsize*2+(64*2+12)*16], r7 + mov [rsp+gprsize*3+(64*2+12)*16], r8 +%endif +%endif +%undef cmp + ; remove entirely-zero iterations + mov r5d, 7*2 + cmp eobw, word [o2(tbl_16x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 + mova [rsp+12*16+t0*8], m0 + mova [rsp+12*16+t1*8], m0 + mova [rsp+12*16+t2*8], m0 + mova [rsp+12*16+t3*8], m0 + mova [rsp+76*16+t0*8], m0 + mova [rsp+76*16+t1*8], m0 + mova [rsp+76*16+t2*8], m0 + mova [rsp+76*16+t3*8], m0 + sub r5d, 2 + cmp eobw, word [o2(tbl_16x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + ; actual first pass after skipping all-zero data + mov [rsp+gprsize*0+(64*2+12)*16], eobd + mov r3, rsp +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 6, 0 + mov r2, [rsp+gprsize*3+(64*2+12)*16] + mov [rsp+gprsize*3+(64*2+12)*16], r6 +%endif +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+ 1*128+r5*8] + mova m1, [cq+ 3*128+r5*8] + mova m2, [cq+ 5*128+r5*8] + mova m3, [cq+ 7*128+r5*8] + mova m4, [cq+ 9*128+r5*8] + mova m5, [cq+11*128+r5*8] + mova m6, [cq+13*128+r5*8] + mova m7, [cq+15*128+r5*8] + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+ 0*128+r5*8] + mova m1, [cq+ 2*128+r5*8] + mova m2, [cq+ 4*128+r5*8] + mova m3, [cq+ 6*128+r5*8] + mova m4, [cq+ 8*128+r5*8] + mova m5, [cq+10*128+r5*8] + mova m6, [cq+12*128+r5*8] + mova m7, [cq+14*128+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + call m(idct_16x16_internal_16bpc).round +%if ARCH_X86_64 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + packssdw m8, m9 + packssdw m10, m11 + packssdw m12, m13 + packssdw m14, m15 +%endif + call m(idct_8x4_internal_16bpc).transpose4x8packed + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 +%if ARCH_X86_64 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+76*16+t0*8], m8 + mova [rsp+76*16+t1*8], m9 + mova [rsp+76*16+t2*8], m10 + mova [rsp+76*16+t3*8], m11 +%else + mova [rsp+76*16+t0*8], m0 + mova [rsp+76*16+t1*8], m1 + mova [rsp+76*16+t2*8], m2 + mova [rsp+76*16+t3*8], m3 + mova m0, [rsp+ 8*16] + mova m2, [rsp+ 9*16] + mova m4, [rsp+10*16] + mova m6, [rsp+11*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + mova [rsp+12*16+t0*8], m0 + mova [rsp+12*16+t1*8], m1 + mova [rsp+12*16+t2*8], m2 + mova [rsp+12*16+t3*8], m3 +%if ARCH_X86_32 + mov r6, [rsp+gprsize*3+(64*2+12)*16] +%endif + pxor m7, m7 + REPX {mova [cq+x*128+r5*8], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 + mov eobd, [rsp+gprsize*0+(64*2+12)*16] + cmp eobd, 151 + jl .fast + ; fall-through +%if ARCH_X86_64 + DECLARE_REG_TMP 8, 9 +%else + DECLARE_REG_TMP 1, 5 +%endif + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main)] + jmp .run +.fast: + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main_fast)] +.run: + add rsp, 9*16 + +%if ARCH_X86_64 + lea r2, [dstq+32] + mov r7, -4 +%else + lea r2, [rsp+(64*2+3)*16] + mov [r2+4*gprsize], t0 + mov [r2+5*gprsize], t1 + mov r1, [r2+2*gprsize] + mov dword [r2+0*gprsize], 2 +%endif +.loop_pass2: +%if ARCH_X86_32 + mov dstq, [r2+1*gprsize] +%endif + call .pass2 + add rsp, 64*16 +%if ARCH_X86_64 + add r7, 2 + lea dstq, [r2+r7*8] + jl .loop_pass2 +%else + add dword [r2+1*gprsize], 16 + dec dword [r2+0*gprsize] + jg .loop_pass2 +%endif +%assign stack_size (stack_size-(64*2+9)*16) +%if STACK_ALIGNMENT >= 16 +%assign stack_size_padded (stack_size_padded-(64*2+9)*16) +%assign stack_offset (stack_offset-(64*2+9)*16) +%else +%xdefine rstkm [rsp + stack_size] +%endif +%if ARCH_X86_64 + mov r9, [rsp+gprsize*1+3*16] +%if WIN64 + mov r7, [rsp+gprsize*2+3*16] + mov r8, [rsp+gprsize*3+3*16] +%endif +%endif + RET + +.pass2: +%if ARCH_X86_32 + lea r5, [o(itx8_start)] +%endif + mova m0, [rsp+gprsize+16* 3] + mova m1, [rsp+gprsize+16* 4] + mova m2, [rsp+gprsize+16* 5] + mova m3, [rsp+gprsize+16* 6] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m_suffix(idct_8x8_internal_8bpc, _ssse3).main + mova [rsp+gprsize+ 3*16], m0 + mova [rsp+gprsize+ 4*16], m1 + mova [rsp+gprsize+ 5*16], m2 + mova [rsp+gprsize+ 6*16], m3 + mova [rsp+gprsize+ 7*16], m4 + mova [rsp+gprsize+ 8*16], m5 + mova [rsp+gprsize+ 9*16], m6 + mova [rsp+gprsize+10*16], m7 + mova m0, [rsp+gprsize+16*11] + mova m1, [rsp+gprsize+16*12] + mova m2, [rsp+gprsize+16*13] + mova m3, [rsp+gprsize+16*14] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m_suffix(idct_16x8_internal_8bpc, _ssse3).main + mova m7, [rsp+gprsize+ 0*16] + mova [rsp+gprsize+11*16], m0 + mova [rsp+gprsize+12*16], m1 + mova [rsp+gprsize+13*16], m2 + mova [rsp+gprsize+14*16], m3 + mova [rsp+gprsize+15*16], m4 + mova [rsp+gprsize+16*16], m5 + mova [rsp+gprsize+17*16], m6 + mova [rsp+gprsize+18*16], m7 +%if ARCH_X86_64 + call r8 +%else + call [r2+4*gprsize] +%endif + mova [rsp+gprsize+ 3*16], m0 + mova [rsp+gprsize+ 5*16], m2 + mova [rsp+gprsize+ 8*16], m5 + mova [rsp+gprsize+10*16], m7 +%if ARCH_X86_64 + call r9 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%else + call [r2+5*gprsize] +%endif + lea r3, [strideq*3] + lea r4, [rsp+gprsize+ 3*16] +%if ARCH_X86_64 + mov r6d, 8 +%else + mov dword [r2+2*gprsize], 8 +%endif +.loop_write: + mova m0, [r4+0*16] + mova m1, [r4+1*16] + mova m2, [r4+2*16] + mova m3, [r4+3*16] + mova m4, [r4+4*16] + mova m5, [r4+5*16] + mova m6, [r4+6*16] + mova m7, [r4+7*16] + call m(idct_8x8_internal_16bpc).round1_and_write_8x8 + lea dstq, [dstq+strideq*8] + add r4, 8*16 +%if ARCH_X86_64 + dec r6d +%else + dec dword [r2+2*gprsize] +%endif + jg .loop_write + ret + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 64 + add r5d, 640 + sar r5d, 10 + add rsp, (12+2*64)*16+(4+4*ARCH_X86_32)*gprsize-(8+4*ARCH_X86_32)*16 + jmp m(inv_txfm_add_dct_dct_16x4_16bpc).dconly2 + +cglobal inv_txfm_add_dct_dct_32x64_16bpc, 4, 7, 16, \ + 0-(32+4*64)*16-(4+4*ARCH_X86_32)*gprsize, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 2, 0 + mov [rsp+gprsize*1+(64*4+32)*16], r0 + mov [rsp+gprsize*2+(64*4+32)*16], r1 + mov [rsp+gprsize*3+(64*4+32)*16], r2 +%else + DECLARE_REG_TMP 8, 9, 4, 7 + mov [rsp+gprsize*1+(64*4+32)*16], r9 +%if WIN64 + mov [rsp+gprsize*2+(64*4+32)*16], r7 + mov [rsp+gprsize*3+(64*4+32)*16], r8 +%endif +%endif +%undef cmp + ; remove entirely-zero iterations + mov r5d, 7*2 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 + mova [rsp+ 32*16+t0*8], m0 + mova [rsp+ 32*16+t1*8], m0 + mova [rsp+ 32*16+t2*8], m0 + mova [rsp+ 32*16+t3*8], m0 + mova [rsp+ 96*16+t0*8], m0 + mova [rsp+ 96*16+t1*8], m0 + mova [rsp+ 96*16+t2*8], m0 + mova [rsp+ 96*16+t3*8], m0 + mova [rsp+160*16+t0*8], m0 + mova [rsp+160*16+t1*8], m0 + mova [rsp+160*16+t2*8], m0 + mova [rsp+160*16+t3*8], m0 + mova [rsp+224*16+t0*8], m0 + mova [rsp+224*16+t1*8], m0 + mova [rsp+224*16+t2*8], m0 + mova [rsp+224*16+t3*8], m0 + sub r5d, 2 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + ; actual first pass after skipping all-zero data + mov [rsp+gprsize*0+(64*4+32)*16], eobd + mov r3, rsp +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 6, 0 + mov r2, [rsp+gprsize*3+(64*4+32)*16] + mov [rsp+gprsize*3+(64*4+32)*16], r6 +%endif +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + mova m0, [cq+128* 1+r5*8] + mova m1, [cq+128* 7+r5*8] + mova m2, [cq+128* 9+r5*8] + mova m3, [cq+128*15+r5*8] + mova m4, [cq+128*17+r5*8] + mova m5, [cq+128*23+r5*8] + mova m6, [cq+128*25+r5*8] + mova m7, [cq+128*31+r5*8] + mov r3, rsp + call m(idct_8x4_internal_16bpc).rect2_mul + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1 + + mova m0, [cq+128* 3+r5*8] + mova m1, [cq+128* 5+r5*8] + mova m2, [cq+128*11+r5*8] + mova m3, [cq+128*13+r5*8] + mova m4, [cq+128*19+r5*8] + mova m5, [cq+128*21+r5*8] + mova m6, [cq+128*27+r5*8] + mova m7, [cq+128*29+r5*8] +%if ARCH_X86_32 + add r3, 16*8 +%endif + call m(idct_8x4_internal_16bpc).rect2_mul +%if ARCH_X86_32 + sub r3, 16*8 +%endif + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2 + add r3, 16*(16+4*ARCH_X86_32) + + mova m0, [cq+128* 2+r5*8] + mova m1, [cq+128* 6+r5*8] + mova m2, [cq+128*10+r5*8] + mova m3, [cq+128*14+r5*8] + mova m4, [cq+128*18+r5*8] + mova m5, [cq+128*22+r5*8] + mova m6, [cq+128*26+r5*8] + mova m7, [cq+128*30+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_16x4_internal_16bpc).main_oddhalf + + mova m0, [cq+128* 0+r5*8] + mova m1, [cq+128* 4+r5*8] + mova m2, [cq+128* 8+r5*8] + mova m3, [cq+128*12+r5*8] + mova m4, [cq+128*16+r5*8] + mova m5, [cq+128*20+r5*8] + mova m6, [cq+128*24+r5*8] + mova m7, [cq+128*28+r5*8] + call m(idct_8x4_internal_16bpc).rect2_mul + call m(idct_8x4_internal_16bpc).main_pass1 + call m(idct_8x4_internal_16bpc).round + sub r3, 16*(16+4*ARCH_X86_32) + call m(inv_txfm_add_dct_dct_32x16_16bpc).round_dct32 + + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 +%if ARCH_X86_64 + call m(idct_8x4_internal_16bpc).transpose4x8packed + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+160*16+t0*8], m8 + mova [rsp+160*16+t1*8], m9 + mova [rsp+160*16+t2*8], m10 + mova [rsp+160*16+t3*8], m11 + mova m8, [r3+16* 9] ; 8 9 + mova m10, [r3+16*11] ; 10 11 + mova m12, [r3+16*13] ; 12 13 + mova m14, [r3+16*15] ; 14 15 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+ 96*16+t0*8], m8 + mova [rsp+ 96*16+t1*8], m9 + mova [rsp+ 96*16+t2*8], m10 + mova [rsp+ 96*16+t3*8], m11 + mova m8, [r3+16* 8] ; 24 25 + mova m10, [r3+16*10] ; 26 27 + mova m12, [r3+16*12] ; 28 29 + mova m14, [r3+16*14] ; 30 31 + call m(idct_16x4_internal_16bpc).transpose4x8packed_hi + mova [rsp+224*16+t0*8], m8 + mova [rsp+224*16+t1*8], m9 + mova [rsp+224*16+t2*8], m10 + mova [rsp+224*16+t3*8], m11 +%else + sub r3, 8*16 + mova m0, [r3+ 8*16] + mova m2, [r3+10*16] + mova m4, [r3+12*16] + mova m6, [r3+14*16] + packssdw m0, [r3+ 9*16] + packssdw m2, [r3+11*16] + packssdw m4, [r3+13*16] + packssdw m6, [r3+15*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+ 96*16+t0*8], m0 + mova [rsp+ 96*16+t1*8], m1 + mova [rsp+ 96*16+t2*8], m2 + mova [rsp+ 96*16+t3*8], m3 + mova m0, [r3+16*16] + mova m2, [r3+18*16] + mova m4, [r3+20*16] + mova m6, [r3+22*16] + packssdw m0, [r3+17*16] + packssdw m2, [r3+19*16] + packssdw m4, [r3+21*16] + packssdw m6, [r3+23*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+160*16+t0*8], m0 + mova [rsp+160*16+t1*8], m1 + mova [rsp+160*16+t2*8], m2 + mova [rsp+160*16+t3*8], m3 + mova m0, [r3+31*16] + mova m2, [r3+29*16] + mova m4, [r3+27*16] + mova m6, [r3+25*16] + packssdw m0, [r3+30*16] + packssdw m2, [r3+28*16] + packssdw m4, [r3+26*16] + packssdw m6, [r3+24*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [rsp+224*16+t0*8], m0 + mova [rsp+224*16+t1*8], m1 + mova [rsp+224*16+t2*8], m2 + mova [rsp+224*16+t3*8], m3 + mova m0, [r3+ 0*16] + mova m2, [r3+ 2*16] + mova m4, [r3+ 4*16] + mova m6, [r3+ 6*16] + packssdw m0, [r3+ 1*16] + packssdw m2, [r3+ 3*16] + packssdw m4, [r3+ 5*16] + packssdw m6, [r3+ 7*16] + call m(idct_8x4_internal_16bpc).transpose4x8packed +%endif + mova [rsp+ 32*16+t0*8], m0 + mova [rsp+ 32*16+t1*8], m1 + mova [rsp+ 32*16+t2*8], m2 + mova [rsp+ 32*16+t3*8], m3 + pxor m0, m0 + REPX {mova [cq+x*128+r5*8], m0}, 0, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 +%if ARCH_X86_32 + mov r6, [rsp+gprsize*3+(64*4+32)*16] +%endif + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 + mov eobd, [rsp+gprsize*0+(64*4+32)*16] + cmp eobd, 136 + jl .fast + ; fall-through +%if ARCH_X86_64 + DECLARE_REG_TMP 8, 9 +%else + DECLARE_REG_TMP 1, 5 +%endif + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main)] + jmp .run +.fast: + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main_fast)] +.run: + add rsp, 29*16 + +%if ARCH_X86_64 + lea r2, [dstq+64] + mov r7, -8 +%else + lea r2, [rsp+(64*4+3)*16] + mov [r2+4*gprsize], t0 + mov [r2+5*gprsize], t1 + mov r1, [r2+2*gprsize] + mov dword [r2+0*gprsize], 4 +%endif + jmp m(inv_txfm_add_dct_dct_16x64_16bpc).loop_pass2 + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 64 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + add r5d, 384 + sar r5d, 9 + add rsp, (32+4*64)*16+(4+4*ARCH_X86_32)*gprsize-(24+8*ARCH_X86_32)*16 + jmp m(inv_txfm_add_dct_dct_32x8_16bpc).dconly2 + +cglobal inv_txfm_add_dct_dct_64x16_16bpc, 4, 7, 16, 0-(64+8*ARCH_X86_32)*16, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + + ; remove entirely-zero iterations +%undef cmp + mov r5d, 8 +.zero_loop: + sub r5d, 2 + cmp eobw, word [o2(tbl_32x16_2d)+r5] + jl .zero_loop + + ; actual first pass after skipping all-zero data +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + + mov r3, rsp + lea r4, [o(idct64_mul_16bpc)] + mova m0, [cq+64* 1+r5*8] + mova m1, [cq+64*31+r5*8] + mova m2, [cq+64*17+r5*8] + mova m3, [cq+64*15+r5*8] + call .main_part1 + mova m0, [cq+64* 7+r5*8] + mova m1, [cq+64*25+r5*8] + mova m2, [cq+64*23+r5*8] + mova m3, [cq+64* 9+r5*8] + call .main_part1 + mova m0, [cq+64* 5+r5*8] + mova m1, [cq+64*27+r5*8] + mova m2, [cq+64*21+r5*8] + mova m3, [cq+64*11+r5*8] + call .main_part1 + mova m0, [cq+64* 3+r5*8] + mova m1, [cq+64*29+r5*8] + mova m2, [cq+64*19+r5*8] + mova m3, [cq+64*13+r5*8] + call .main_part1 + call .main_part2 + + mova m0, [cq+64* 2+r5*8] + mova m1, [cq+64*14+r5*8] + mova m2, [cq+64*18+r5*8] + mova m3, [cq+64*30+r5*8] + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1_fast + + mova m0, [cq+64* 6+r5*8] + mova m1, [cq+64*10+r5*8] + mova m2, [cq+64*22+r5*8] + mova m3, [cq+64*26+r5*8] + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2_fast + add r3, 16*(24+4*ARCH_X86_32) + + mova m0, [cq+64* 4+r5*8] + mova m1, [cq+64*12+r5*8] + mova m2, [cq+64*20+r5*8] + mova m3, [cq+64*28+r5*8] + call m(idct_16x4_internal_16bpc).main_oddhalf_fast + + mova m0, [cq+64* 0+r5*8] + mova m1, [cq+64* 8+r5*8] + mova m2, [cq+64*16+r5*8] + mova m3, [cq+64*24+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1_fast + call m(idct_8x4_internal_16bpc).round + mova [r3-(7+4*ARCH_X86_32)*16], m1 + mova [r3-(6+4*ARCH_X86_32)*16], m2 + mova [r3-(5+4*ARCH_X86_32)*16], m3 + mova [r3-(4+4*ARCH_X86_32)*16], m4 + mova [r3-(3+4*ARCH_X86_32)*16], m5 + mova [r3-(2+4*ARCH_X86_32)*16], m6 + mova [r3-(1+4*ARCH_X86_32)*16], m7 + sub r3, 16*(40+4*ARCH_X86_32-4) + +%if ARCH_X86_64 + psrld m15, m11, 10 ; pd_2 +%else + mova m7, [o(pd_2)] +%endif + call .main_end_loop_start + + lea r3, [rsp+56*16] + lea r4, [cq+r5*8+64*28] + call .shift_transpose + sub r5d, 2 + jge .loop_pass1 + + ; pass=2, we need to call this otherwise the stack pointer has + ; the wrong offset in the 8-bit code + call .pass2 + RET + +.pass2: +%if ARCH_X86_64 + mova m8, [o(pw_2048)] + pxor m9, m9 + mova m10, [o(pixel_10bpc_max)] +%if WIN64 + mov [rsp+16*16+gprsize], r7 +%endif + mov r7, dstq +%else + mov [rsp+2*gprsize+16*16], dstq +%endif + lea r3, [strideq*3] + mov r4d, 8 + jmp m(idct_16x16_internal_16bpc).loop_pass2 + +.main_part1: ; idct64 steps 1-5 + ; in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + ; in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + ; in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + ; in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a +%if ARCH_X86_64 + movd m7, [r4+4*0] + movd m8, [r4+4*1] + movd m6, [r4+4*2] + movd m9, [r4+4*3] + movd m5, [r4+4*4] + movd m10, [r4+4*5] + movd m4, [r4+4*6] + movd m15, [r4+4*7] + REPX {pshufd x, x, q0000}, m7, m8, m6, m9, m5, m10, m4, m15 + pmulld m7, m0 ; t63a + pmulld m0, m8 ; t32a + pmulld m6, m1 ; t62a + pmulld m1, m9 ; t33a + pmulld m5, m2 ; t61a + pmulld m2, m10 ; t34a + pmulld m4, m3 ; t60a + pmulld m3, m15 ; t35a + movd m10, [r4+4*8] + movd m15, [r4+4*9] + REPX {pshufd x, x, q0000}, m10, m15 + REPX {paddd x, m11}, m7, m0, m6, m1, m5, m2, m4, m3 + REPX {psrad x, 12 }, m0, m1, m7, m6, m2, m3, m5, m4 + psubd m8, m0, m1 ; t33 + paddd m0, m1 ; t32 + psubd m1, m7, m6 ; t62 + paddd m7, m6 ; t63 + psubd m6, m3, m2 ; t34 + paddd m3, m2 ; t35 + psubd m2, m4, m5 ; t61 + paddd m4, m5 ; t60 + REPX {pmaxsd x, m12}, m8, m1, m6, m2 + REPX {pminsd x, m13}, m8, m1, m6, m2 + ITX_MULSUB_2D 1, 8, 5, 9, _, 11, 10, 15 ; t33a, t62a + ITX_MULSUB_2D 2, 6, 5, 9, _, 11, 10, 15, 4 ; t61a, t34a + REPX {pmaxsd x, m12}, m0, m3, m7, m4 + REPX {pminsd x, m13}, m0, m3, m7, m4 + movd m10, [r4+4*10] + movd m15, [r4+4*11] + REPX {pshufd x, x, q0000}, m10, m15 + psubd m5, m0, m3 ; t35a + paddd m0, m3 ; t32a + psubd m3, m7, m4 ; t60a + paddd m7, m4 ; t63a + psubd m4, m1, m6 ; t34 + paddd m1, m6 ; t33 + psubd m6, m8, m2 ; t61 + paddd m8, m2 ; t62 + REPX {pmaxsd x, m12}, m5, m3, m4, m6 + REPX {pminsd x, m13}, m5, m3, m4, m6 + ITX_MULSUB_2D 3, 5, 2, 9, _, 11, 10, 15 ; t35, t60 + ITX_MULSUB_2D 6, 4, 2, 9, _, 11, 10, 15 ; t34a, t61a + REPX {pmaxsd x, m12}, m0, m7, m1, m8 + REPX {pminsd x, m13}, m0, m7, m1, m8 + add r4, 4*12 + mova [r3+16*0], m0 + mova [r3+16*7], m7 + mova [r3+16*1], m1 + mova [r3+16*6], m8 + mova [r3+16*2], m6 + mova [r3+16*5], m4 + mova [r3+16*3], m3 + mova [r3+16*4], m5 +%else + movd m7, [r4+4*0] + movd m6, [r4+4*2] + movd m5, [r4+4*4] + movd m4, [r4+4*6] + REPX {pshufd x, x, q0000}, m7, m6, m5, m4 + pmulld m7, m0 ; t63a + pmulld m6, m1 ; t62a + pmulld m5, m2 ; t61a + pmulld m4, m3 ; t60a + mova [r3+0*16], m6 + mova [r3+1*16], m7 + movd m6, [r4+4*1] + movd m7, [r4+4*3] + REPX {pshufd x, x, q0000}, m7, m6 + pmulld m0, m6 ; t32a + pmulld m1, m7 ; t33a + movd m6, [r4+4*5] + movd m7, [r4+4*7] + REPX {pshufd x, x, q0000}, m7, m6 + pmulld m2, m6 ; t34a + pmulld m3, m7 ; t35a + mova m6, [r3+0*16] + mova m7, [o(pd_2048)] + REPX {paddd x, m7}, m0, m1, m2, m3, m4, m5, m6 + paddd m7, [r3+1*16] + REPX {psrad x, 12}, m0, m1, m7, m6, m2, m3, m5, m4 + mova [r3+0*16], m5 + psubd m5, m0, m1 ; t33 + paddd m0, m1 ; t32 + mova [r3+1*16], m0 + mova m0, [r3+0*16] + psubd m1, m7, m6 ; t62 + paddd m7, m6 ; t63 + psubd m6, m3, m2 ; t34 + paddd m3, m2 ; t35 + psubd m2, m4, m0 ; t61 + paddd m4, m0 ; t60 + mova m0, [o(clip_18b_min)] + REPX {pmaxsd x, m0}, m5, m1, m7, m6, m3, m2, m4 + pmaxsd m0, [r3+1*16] + mova [r3+0*16], m0 + mova m0, [o(clip_18b_max)] + REPX {pminsd x, m0}, m5, m1, m7, m6, m3, m2, m4 + pminsd m0, [r3+0*16] + mova [r3+0*16], m0 + mova [r3+1*16], m3 + mova [r3+2*16], m4 + mova [r3+3*16], m7 + mova m0, [o(pd_2048)] + movd m3, [r4+4*8] + movd m4, [r4+4*9] + REPX {pshufd x, x, q0000}, m3, m4 + mova [r3+4*16], m2 + ITX_MULSUB_2D 1, 5, 2, 7, _, 0, 3, 4 ; t33a, t62a + mova m2, [r3+4*16] + mova [r3+4*16], m5 + ITX_MULSUB_2D 2, 6, 5, 7, _, 0, 3, 4, 4 ; t61a, t34a + mova m0, [r3+0*16] + mova m3, [r3+1*16] + mova m4, [r3+2*16] + mova m7, [r3+3*16] + psubd m5, m0, m3 ; t35a + paddd m0, m3 ; t32a + mova [r3+0*16], m5 + mova m5, [r3+4*16] + psubd m3, m7, m4 ; t60a + paddd m7, m4 ; t63a + psubd m4, m1, m6 ; t34 + paddd m1, m6 ; t33 + psubd m6, m5, m2 ; t61 + paddd m2, m5 ; t62 + mova m5, [o(clip_18b_min)] + REPX {pmaxsd x, m5}, m0, m3, m7, m4, m1, m6, m2 + pmaxsd m5, [r3+0*16] + mova [r3+0*16], m5 + mova m5, [o(clip_18b_max)] + REPX {pminsd x, m5}, m0, m3, m7, m4, m1, m6, m2 + pminsd m5, [r3+0*16] + mova [r3+16*0], m0 + mova [r3+16*7], m7 + mova [r3+16*1], m1 + mova [r3+16*6], m2 + mova [r3+16*2], m4 + mova m7, [o(pd_2048)] + movd m0, [r4+4*10] + movd m1, [r4+4*11] + REPX {pshufd x, x, q0000}, m0, m1 + ITX_MULSUB_2D 3, 5, 2, 4, _, 7, 0, 1 ; t35, t60 + mova [r3+16*3], m3 + mova [r3+16*4], m5 + mova m4, [r3+2*16] + ITX_MULSUB_2D 6, 4, 2, 3, _, 7, 0, 1 ; t34a, t61a + add r4, 4*12 + mova [r3+16*2], m6 + mova [r3+16*5], m4 +%endif + add r3, 16*8 + ret + +.main_part2: ; idct64 steps 6-9 + lea r4, [r3+16*7] +%if ARCH_X86_64 + mova m10, [o(pd_1567)] + mova m15, [o(pd_3784)] +.main_part2_loop: + mova m0, [r3-16*32] ; t32a + mova m1, [r4-16*24] ; t39a + mova m2, [r4-16*32] ; t63a + mova m3, [r3-16*24] ; t56a + mova m4, [r3-16*16] ; t40a + mova m5, [r4-16* 8] ; t47a + mova m6, [r4-16*16] ; t55a + mova m7, [r3-16* 8] ; t48a + psubd m8, m0, m1 ; t39 + paddd m0, m1 ; t32 + psubd m1, m2, m3 ; t56 + paddd m2, m3 ; t63 + psubd m3, m5, m4 ; t40 + paddd m5, m4 ; t47 + psubd m4, m7, m6 ; t55 + paddd m7, m6 ; t48 + REPX {pmaxsd x, m12}, m8, m1, m3, m4 + REPX {pminsd x, m13}, m8, m1, m3, m4 + ITX_MULSUB_2D 1, 8, 6, 9, _, 11, 10, 15 ; t39a, t56a + ITX_MULSUB_2D 4, 3, 6, 9, _, 11, 10, 15, 4 ; t55a, t40a + REPX {pmaxsd x, m12}, m0, m2, m5, m7 + REPX {pminsd x, m13}, m0, m5, m2, m7 + psubd m6, m2, m7 ; t48a + paddd m2, m7 ; t63a + psubd m7, m0, m5 ; t47a + paddd m0, m5 ; t32a + psubd m5, m8, m4 ; t55 + paddd m8, m4 ; t56 + psubd m4, m1, m3 ; t40 + paddd m1, m3 ; t39 + REPX {pmaxsd x, m12}, m6, m7, m5, m4 + REPX {pminsd x, m13}, m6, m7, m5, m4 + REPX {pmulld x, m14}, m6, m7, m5, m4 + REPX {pmaxsd x, m12}, m2, m0, m8, m1 + REPX {pminsd x, m13}, m2, m0, m8, m1 + paddd m6, m11 + paddd m5, m11 + psubd m3, m6, m7 ; t47 + paddd m6, m7 ; t48 + psubd m7, m5, m4 ; t40a + paddd m5, m4 ; t55a + REPX {psrad x, 12}, m3, m6, m7, m5 + mova [r4-16* 8], m2 + mova [r3-16*32], m0 + mova [r3-16* 8], m8 + mova [r4-16*32], m1 + mova [r4-16*24], m3 + mova [r3-16*16], m6 + mova [r3-16*24], m7 + mova [r4-16*16], m5 +%else +.main_part2_loop: + mova m0, [r3-16*32] ; t32a + mova m1, [r4-16*24] ; t39a + mova m2, [r4-16*32] ; t63a + mova m3, [r3-16*24] ; t56a + mova m4, [r3-16*16] ; t40a + mova m5, [r4-16* 8] ; t47a + mova m6, [r4-16*16] ; t55a + psubd m7, m0, m1 ; t39 + paddd m0, m1 ; t32 + mova [r3+0*16], m7 + mova m7, [r3-16* 8] ; t48a + psubd m1, m2, m3 ; t56 + paddd m2, m3 ; t63 + psubd m3, m5, m4 ; t40 + paddd m5, m4 ; t47 + psubd m4, m7, m6 ; t55 + paddd m7, m6 ; t48 + mova m6, [o(clip_18b_min)] + REPX {pmaxsd x, m6}, m0, m1, m2, m3, m5, m4, m7 + pmaxsd m6, [r3+0*16] + mova [r3+0*16], m6 + mova m6, [o(clip_18b_max)] + REPX {pminsd x, m6}, m0, m1, m2, m3, m5, m4, m7 + pminsd m6, [r3+0*16] + mova [r3+0*16], m0 + mova [r3+1*16], m2 + mova [r3+2*16], m5 + mova [r3+3*16], m7 + mova m0, [o(pd_2048)] + ITX_MULSUB_2D 1, 6, 2, 5, 7, 0, 1567, 3784 ; t39a, t56a + ITX_MULSUB_2D 4, 3, 2, 5, _, 0, 7, 3784, 4 ; t55a, t40a + mova m2, [r3+1*16] + mova m7, [r3+3*16] + psubd m5, m2, m7 ; t48a + paddd m2, m7 ; t63a + mova [r3+1*16], m5 + mova m0, [r3+0*16] + mova m5, [r3+2*16] + psubd m7, m0, m5 ; t47a + paddd m0, m5 ; t32a + psubd m5, m6, m4 ; t55 + paddd m6, m4 ; t56 + psubd m4, m1, m3 ; t40 + paddd m1, m3 ; t39 + mova m3, [o(clip_18b_min)] + REPX {pmaxsd x, m3}, m2, m7, m0, m5, m6, m4, m1 + pmaxsd m3, [r3+1*16] + mova [r3+0*16], m3 + mova m3, [o(clip_18b_max)] + REPX {pminsd x, m3}, m2, m7, m0, m5, m6, m4, m1 + pminsd m3, [r3+0*16] + mova [r4-16* 8], m2 + mova [r3-16*32], m0 + mova [r3-16* 8], m6 + mova [r4-16*32], m1 + mova m0, [o(pd_2896)] + mova m1, [o(pd_2048)] + REPX {pmulld x, m0}, m3, m7, m5, m4 + REPX {paddd x, m1}, m3, m5 + psubd m6, m3, m7 ; t47 + paddd m3, m7 ; t48 + psubd m7, m5, m4 ; t40a + paddd m5, m4 ; t55a + REPX {psrad x, 12}, m6, m3, m7, m5 + mova [r4-16*24], m6 + mova [r3-16*16], m3 + mova [r3-16*24], m7 + mova [r4-16*16], m5 +%endif + add r3, 16 + sub r4, 16 + cmp r3, r4 + jl .main_part2_loop + sub r3, 4*16 + ret + +.main_end_loop: + mova m0, [r3+16*28] ; idct8 0 + n +.main_end_loop_start: + mova m2, [r3+16*12] ; idct32 16 + n + mova m3, [r4+16*12] ; idct32 31 - n +%if ARCH_X86_64 + mova m1, [r4+16*28] ; idct16 15 - n + mova m4, [r4-16* 4] ; idct64 63 - n + mova m5, [r3-16* 4] ; idct64 48 + n + mova m6, [r4-16*20] ; idct64 47 - n + mova m7, [r3-16*20] ; idct64 32 + n + pmaxsd m0, m12 + pminsd m0, m13 + paddd m8, m0, m1 ; idct16 out0 + n + psubd m0, m1 ; idct16 out15 - n + REPX {pmaxsd x, m12}, m8, m0 + REPX {pminsd x, m13}, m8, m0 + paddd m1, m8, m3 ; idct32 out0 + n + psubd m8, m3 ; idct32 out31 - n + paddd m3, m0, m2 ; idct32 out15 - n + psubd m0, m2 ; idct32 out16 + n + REPX {pmaxsd x, m12}, m1, m8, m3, m0 + REPX {pminsd x, m13}, m1, m3, m8, m0 + REPX {paddd x, m15}, m1, m3, m0, m8 + paddd m2, m1, m4 ; idct64 out0 + n (unshifted) + psubd m1, m4 ; idct64 out63 - n (unshifted) + paddd m4, m3, m5 ; idct64 out15 - n (unshifted) + psubd m3, m5 ; idct64 out48 + n (unshifted) + paddd m5, m0, m6 ; idct64 out16 + n (unshifted) + psubd m0, m6 ; idct64 out47 - n (unshifted) + paddd m6, m8, m7 ; idct64 out31 - n (unshifted) + psubd m8, m7 ; idct64 out32 + n (unshifted) + mova [r3-16*20], m2 + mova [r4+16*28], m1 + mova [r4-16*20], m4 + mova [r3+16*28], m3 + mova [r3-16* 4], m5 + mova [r4+16*12], m0 + mova [r4-16* 4], m6 + mova [r3+16*12], m8 +%else + mova m5, [o(clip_18b_min)] + mova m6, [o(clip_18b_max)] + mova m1, [r3+16*44] ; idct16 15 - n + pmaxsd m0, m5 + pminsd m0, m6 + paddd m4, m0, m1 ; idct16 out0 + n + psubd m0, m1 ; idct16 out15 - n + REPX {pmaxsd x, m5}, m4, m0 + REPX {pminsd x, m6}, m4, m0 + paddd m1, m4, m3 ; idct32 out0 + n + psubd m4, m3 ; idct32 out31 - n + paddd m3, m0, m2 ; idct32 out15 - n + psubd m0, m2 ; idct32 out16 + n + REPX {pmaxsd x, m5}, m1, m4, m3, m0 + REPX {pminsd x, m6}, m1, m3, m4, m0 + REPX {paddd x, m7}, m1, m3, m0, m4 + mova m5, [r4-16* 4] ; idct64 63 - n + mova m6, [r3-16* 4] ; idct64 48 + n + paddd m2, m1, m5 ; idct64 out0 + n (unshifted) + psubd m1, m5 ; idct64 out63 - n (unshifted) + paddd m5, m3, m6 ; idct64 out15 - n (unshifted) + psubd m3, m6 ; idct64 out48 + n (unshifted) + mova [r4+16*28], m1 + mova [r3+16*28], m3 + mova m6, [r4-16*20] ; idct64 47 - n + mova m1, [r3-16*20] ; idct64 32 + n + mova [r3-16*20], m2 + mova [r4-16*20], m5 + paddd m5, m0, m6 ; idct64 out16 + n (unshifted) + psubd m0, m6 ; idct64 out47 - n (unshifted) + paddd m6, m4, m1 ; idct64 out31 - n (unshifted) + psubd m4, m1 ; idct64 out32 + n (unshifted) + mova [r3-16* 4], m5 + mova [r4+16*12], m0 + mova [r4-16* 4], m6 + mova [r3+16*12], m4 +%endif + sub r4, 16 + add r3, 16 + cmp r3, r4 + jl .main_end_loop + ret + +.shift_transpose: + mova m0, [r3+0*16] + mova m1, [r3+1*16] + mova m2, [r3+2*16] + mova m3, [r3+3*16] + mova m4, [r3+4*16] + mova m5, [r3+5*16] + mova m6, [r3+6*16] + mova m7, [r3+7*16] + REPX {psrad x, 2}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [r4+0*64], m0 + mova [r4+1*64], m1 + mova [r4+2*64], m2 + mova [r4+3*64], m3 + sub r4, 4*64 + sub r3, 8*16 + cmp r3, rsp + jg .shift_transpose + ret + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 16 +.dconly1: + add r5d, 640 + sar r5d, 10 +.dconly2: + imul r5d, 2896 + add r5d, 34816 + movd m0, r5d + pshuflw m0, m0, q1111 + punpcklqdq m0, m0 + mova m6, [o(pixel_10bpc_max)] + pxor m5, m5 +.dconly_loop: + paddw m1, m0, [dstq+16*0] + paddw m2, m0, [dstq+16*1] + paddw m3, m0, [dstq+16*2] + paddw m4, m0, [dstq+16*3] + REPX {pmaxsw x, m5}, m1, m2, m3, m4 + REPX {pminsw x, m6}, m1, m2, m3, m4 + mova [dstq+16*0], m1 + mova [dstq+16*1], m2 + mova [dstq+16*2], m3 + mova [dstq+16*3], m4 + add dstq, 64 + btc r3d, 16 + jnc .dconly_loop + lea dstq, [dstq+strideq-128] + dec r3d + jg .dconly_loop + RET + +cglobal inv_txfm_add_dct_dct_64x32_16bpc, 4, 7, 16, \ + 0-(1+64+8*ARCH_X86_32+8*32+1*WIN64)*16, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + DECLARE_REG_TMP 0, 4, 1 + mov [rsp+(8*32+64+8)*16+1*gprsize], dstq + mov [rsp+(8*32+64+8)*16+2*gprsize], strideq +%else + DECLARE_REG_TMP 4, 7, 8 +%if WIN64 + mov [rsp+(8*32+64+1)*16+1*gprsize], r7 + mov [rsp+64*16+0*gprsize], r8 +%endif +%endif +%undef cmp + ; remove entirely-zero iterations + mov r5d, 14 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + lea t2, [rsp+7*32*16] +.zero_loop_inner: + mova [t2+(64+8*ARCH_X86_32+1*WIN64)*16+r5*8], m0 + mova [t2+(72+8*ARCH_X86_32+1*WIN64)*16+r5*8], m0 + mova [t2+(64+8*ARCH_X86_32+1*WIN64)*16+t0*8], m0 + mova [t2+(64+8*ARCH_X86_32+1*WIN64)*16+t1*8], m0 + sub t2, 32*16 + cmp t2, rsp + jge .zero_loop_inner + sub r5d, 2 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + mov [rsp+(8*32+64+8*ARCH_X86_32+1*WIN64)*16+0*gprsize], eobd + ; actual first pass after skipping all-zero data +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + + mov r3, rsp + lea r4, [o(idct64_mul_16bpc)] + mova m0, [cq+128* 1+r5*8] + mova m1, [cq+128*31+r5*8] + mova m2, [cq+128*17+r5*8] + mova m3, [cq+128*15+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 7+r5*8] + mova m1, [cq+128*25+r5*8] + mova m2, [cq+128*23+r5*8] + mova m3, [cq+128* 9+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 5+r5*8] + mova m1, [cq+128*27+r5*8] + mova m2, [cq+128*21+r5*8] + mova m3, [cq+128*11+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 3+r5*8] + mova m1, [cq+128*29+r5*8] + mova m2, [cq+128*19+r5*8] + mova m3, [cq+128*13+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part2 + + mova m0, [cq+128* 2+r5*8] + mova m1, [cq+128*14+r5*8] + mova m2, [cq+128*18+r5*8] + mova m3, [cq+128*30+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1_fast + + mova m0, [cq+128* 6+r5*8] + mova m1, [cq+128*10+r5*8] + mova m2, [cq+128*22+r5*8] + mova m3, [cq+128*26+r5*8] + call .rect2_mul_fast + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2_fast + add r3, 16*(24+4*ARCH_X86_32) + + mova m0, [cq+128* 4+r5*8] + mova m1, [cq+128*12+r5*8] + mova m2, [cq+128*20+r5*8] + mova m3, [cq+128*28+r5*8] + call .rect2_mul_fast + call m(idct_16x4_internal_16bpc).main_oddhalf_fast + + mova m0, [cq+128* 0+r5*8] + mova m1, [cq+128* 8+r5*8] + mova m2, [cq+128*16+r5*8] + mova m3, [cq+128*24+r5*8] + call .rect2_mul_fast + call m(idct_8x4_internal_16bpc).main_pass1_fast + call m(idct_8x4_internal_16bpc).round + mova [r3-(7+4*ARCH_X86_32)*16], m1 + mova [r3-(6+4*ARCH_X86_32)*16], m2 + mova [r3-(5+4*ARCH_X86_32)*16], m3 + mova [r3-(4+4*ARCH_X86_32)*16], m4 + mova [r3-(3+4*ARCH_X86_32)*16], m5 + mova [r3-(2+4*ARCH_X86_32)*16], m6 + mova [r3-(1+4*ARCH_X86_32)*16], m7 + sub r3, 16*(40+4*ARCH_X86_32-4) + +%if ARCH_X86_64 + psrld m15, m11, 11 ; pd_1 +%else + mova m7, [o(pd_1)] +%endif + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_end_loop_start + + lea r3, [rsp+56*16] + lea t2, [rsp+7*32*16+(64+8*ARCH_X86_32+1*WIN64)*16] + movzx t0d, word [o2(tbl_Nx32_odd_offset)+r5] + movzx t1d, t0b + shr t0d, 8 + call .shift_transpose + ; zero cq + pxor m7, m7 + lea r4, [cq+30*128+r5*8] +.zero_cq_loop: + REPX {mova [r4+x*128], m7}, -2, -1, 0, 1 + sub r4, 4*128 + cmp r4, cq + jg .zero_cq_loop + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 code starts here + mov eobd, [rsp+gprsize*0+(8*32+64+8*ARCH_X86_32+1*WIN64)*16] +%if ARCH_X86_32 + mov strideq, [rsp+gprsize*2+(8*32+64+8)*16] +%elif WIN64 + mov r8, [rsp+gprsize*0+64*16] +%endif + add rsp, (64+8*ARCH_X86_32+1*WIN64-3)*16 + cmp eobd, 36 + jl .load_veryfast + cmp eobd, 136 + jl .load_fast + ; load normal + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main)] + jmp .run +.load_fast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + jmp .run +.load_veryfast: + lea r4, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + ; fall-through +.run: +%if ARCH_X86_64 + lea r2, [dstq+128] + mov r7, -16 +%else + lea r2, [rsp+(8*32+3)*16] + mov dword [r2+0*gprsize], 8 +%endif + jmp m(inv_txfm_add_dct_dct_16x32_16bpc).loop_pass2_entry + +.rect2_mul_fast: +%if ARCH_X86_64 + REPX {pmulld x, m14}, m0, m1, m2, m3 + REPX {paddd x, m11}, m0, m1, m2, m3 +%else + mova m4, [o(pd_2896)] + mova m5, [o(pd_2048)] + REPX {pmulld x, m4 }, m0, m1, m2, m3 + REPX {paddd x, m5 }, m0, m1, m2, m3 +%endif + REPX {psrad x, 12 }, m0, m1, m2, m3 + ret + +.shift_transpose: + mova m0, [r3+0*16] + mova m1, [r3+1*16] + mova m2, [r3+2*16] + mova m3, [r3+3*16] + mova m4, [r3+4*16] + mova m5, [r3+5*16] + mova m6, [r3+6*16] + mova m7, [r3+7*16] + REPX {psrad x, 1}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [t2+0*16+r5*8], m0 + mova [t2+8*16+r5*8], m2 + mova [t2+0*16+t0*8], m3 + mova [t2+0*16+t1*8], m1 + sub t2, 16*32 + sub r3, 8*16 + cmp r3, rsp + jg .shift_transpose + ret + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 32 + add r5d, 128 + sar r5d, 8 + imul r5d, 181 + add r5d, 384 + sar r5d, 9 + add rsp, (1+8*32+1*WIN64)*16 + jmp m(inv_txfm_add_dct_dct_64x16_16bpc).dconly2 + +cglobal inv_txfm_add_dct_dct_64x64_16bpc, 4, 7, 16, \ + 0-(64+8*ARCH_X86_32+8*64+1*ARCH_X86_64)*16-(4+4*ARCH_X86_32)*gprsize, \ + dst, stride, c, eob + LEA r6, base + test eobd, eobd + jz .dconly + +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 2, 0, 6 + mov [rsp+gprsize*1+(64*9+8)*16], r0 + mov [rsp+gprsize*2+(64*9+8)*16], r1 + mov [rsp+gprsize*3+(64*9+8)*16], r2 + mov [rsp+gprsize*4+(64*9+8)*16], r6 +%else + DECLARE_REG_TMP 8, 9, 4, 7, 0 + mov [rsp+gprsize*1+(64*9+1)*16], r9 + mov [rsp+gprsize*0+64*16], r0 +%if WIN64 + mov [rsp+gprsize*2+(64*9+1)*16], r7 + mov [rsp+gprsize*3+(64*9+1)*16], r8 +%endif +%endif +%undef cmp + + ; remove entirely-zero iterations + mov r5d, 14 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jge .end_zero_loop + pxor m0, m0 +.zero_loop: + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 + lea t4, [rsp+7*64*16] +.zero_loop_inner: + mova [t4+(64+8*ARCH_X86_32+1*ARCH_X86_64)*16+t0*8], m0 + mova [t4+(64+8*ARCH_X86_32+1*ARCH_X86_64)*16+t1*8], m0 + mova [t4+(64+8*ARCH_X86_32+1*ARCH_X86_64)*16+t2*8], m0 + mova [t4+(64+8*ARCH_X86_32+1*ARCH_X86_64)*16+t3*8], m0 + sub t4, 64*16 + cmp t4, rsp + jge .zero_loop_inner +%if ARCH_X86_32 + mov r6, [rsp+gprsize*4+(64*9+8)*16] +%endif + sub r5d, 2 + cmp eobw, word [o2(tbl_32x32_2d)+r5] + jl .zero_loop +.end_zero_loop: + mov [rsp+gprsize*0+(9*64+8*ARCH_X86_32+1*ARCH_X86_64)*16], eobd +%if ARCH_X86_32 + mov cq, [rsp+gprsize*3+(64*9+8)*16] +%endif + ; actual first pass after skipping all-zero data +.loop_pass1: +%if ARCH_X86_64 + mova m11, [o(pd_2048)] + mova m12, [o(clip_18b_min)] + mova m13, [o(clip_18b_max)] + mova m14, [o(pd_2896)] +%endif + + mov r3, rsp + lea r4, [o(idct64_mul_16bpc)] + mova m0, [cq+128* 1+r5*8] + mova m1, [cq+128*31+r5*8] + mova m2, [cq+128*17+r5*8] + mova m3, [cq+128*15+r5*8] + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 7+r5*8] + mova m1, [cq+128*25+r5*8] + mova m2, [cq+128*23+r5*8] + mova m3, [cq+128* 9+r5*8] + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 5+r5*8] + mova m1, [cq+128*27+r5*8] + mova m2, [cq+128*21+r5*8] + mova m3, [cq+128*11+r5*8] + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + mova m0, [cq+128* 3+r5*8] + mova m1, [cq+128*29+r5*8] + mova m2, [cq+128*19+r5*8] + mova m3, [cq+128*13+r5*8] + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part1 + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_part2 + + mova m0, [cq+128* 2+r5*8] + mova m1, [cq+128*14+r5*8] + mova m2, [cq+128*18+r5*8] + mova m3, [cq+128*30+r5*8] + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part1_fast + + mova m0, [cq+128* 6+r5*8] + mova m1, [cq+128*10+r5*8] + mova m2, [cq+128*22+r5*8] + mova m3, [cq+128*26+r5*8] + call m(inv_txfm_add_dct_dct_32x8_16bpc).main_oddhalf_part2_fast + add r3, 16*(24+4*ARCH_X86_32) + + mova m0, [cq+128* 4+r5*8] + mova m1, [cq+128*12+r5*8] + mova m2, [cq+128*20+r5*8] + mova m3, [cq+128*28+r5*8] + call m(idct_16x4_internal_16bpc).main_oddhalf_fast + + mova m0, [cq+128* 0+r5*8] + mova m1, [cq+128* 8+r5*8] + mova m2, [cq+128*16+r5*8] + mova m3, [cq+128*24+r5*8] + call m(idct_8x4_internal_16bpc).main_pass1_fast + call m(idct_8x4_internal_16bpc).round + mova [r3-(7+4*ARCH_X86_32)*16], m1 + mova [r3-(6+4*ARCH_X86_32)*16], m2 + mova [r3-(5+4*ARCH_X86_32)*16], m3 + mova [r3-(4+4*ARCH_X86_32)*16], m4 + mova [r3-(3+4*ARCH_X86_32)*16], m5 + mova [r3-(2+4*ARCH_X86_32)*16], m6 + mova [r3-(1+4*ARCH_X86_32)*16], m7 + sub r3, 16*(40+4*ARCH_X86_32-4) + +%if ARCH_X86_64 + psrld m15, m11, 10 ; pd_2 +%else + mova m7, [o(pd_2)] +%endif + call m(inv_txfm_add_dct_dct_64x16_16bpc).main_end_loop_start + + lea r3, [rsp+56*16] + movzx t1d, word [o2(tbl_Nx64_offset)+r5*2+0] + movzx t3d, word [o2(tbl_Nx64_offset)+r5*2+2] + movzx t0d, t1b + movzx t2d, t3b + shr t1d, 8 + shr t3d, 8 + lea t4, [rsp+7*64*16+(64+8*ARCH_X86_32+1*ARCH_X86_64)*16] + call .shift_transpose + ; zero cq + pxor m7, m7 +%if ARCH_X86_32 + mov cq, [rsp+gprsize*3+(64*9+8)*16] +%endif + lea r4, [cq+30*128+r5*8] +.zero_cq_loop: + REPX {mova [r4+x*128], m7}, -2, -1, 0, 1 + sub r4, 4*128 + cmp r4, cq + jg .zero_cq_loop +%if ARCH_X86_32 + mov r6, [rsp+gprsize*4+(64*9+8)*16] +%endif + sub r5d, 2 + jge .loop_pass1 + + ; pass=2 code starts here + mov eobd, [rsp+gprsize*0+(9*64+8*ARCH_X86_32+1*ARCH_X86_64)*16] +%if ARCH_X86_32 + mov strideq, [rsp+gprsize*2+(9*64+8)*16] +%else + mov r0, [rsp+gprsize*0+64*16] +%endif + add rsp, (64+8*ARCH_X86_32+1*ARCH_X86_64-3)*16 + cmp eobd, 151 + jl .fast + ; fall-through +%if ARCH_X86_64 + DECLARE_REG_TMP 8, 9 +%else + DECLARE_REG_TMP 1, 5 +%endif + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_fast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main)] + jmp .run +.fast: + lea t0, [o(m_suffix(idct_8x32_internal_8bpc, _ssse3).main_veryfast)] + lea t1, [o(m_suffix(idct_16x64_internal_8bpc, _ssse3).main_fast)] +.run: + +%if ARCH_X86_64 + lea r2, [dstq+128] + mov r7, -16 +%else + lea r2, [rsp+(64*8+3)*16] + mov [r2+4*gprsize], t0 + mov [r2+5*gprsize], t1 + mov r1, [r2+2*gprsize] + mov dword [r2+0*gprsize], 8 +%endif + jmp m(inv_txfm_add_dct_dct_16x64_16bpc).loop_pass2 + + ; copy of pass=1 tmp-regs +%if ARCH_X86_32 + DECLARE_REG_TMP 4, 1, 2, 0, 6 +%else + DECLARE_REG_TMP 8, 9, 4, 7, 0 +%endif + +.shift_transpose: + mova m0, [r3+0*16] + mova m1, [r3+1*16] + mova m2, [r3+2*16] + mova m3, [r3+3*16] + mova m4, [r3+4*16] + mova m5, [r3+5*16] + mova m6, [r3+6*16] + mova m7, [r3+7*16] + REPX {psrad x, 2}, m0, m1, m2, m3, m4, m5, m6, m7 + packssdw m0, m1 + packssdw m2, m3 + packssdw m4, m5 + packssdw m6, m7 + call m(idct_8x4_internal_16bpc).transpose4x8packed + mova [t4+t0*8], m0 + mova [t4+t1*8], m1 + mova [t4+t2*8], m2 + mova [t4+t3*8], m3 + sub t4, 16*64 + sub r3, 8*16 + cmp r3, rsp + jg .shift_transpose + ret + +.dconly: + imul r5d, [cq], 181 + mov [cq], eobd ; 0 + mov r3d, 64 + add rsp, (64+8*ARCH_X86_32+8*64+1*ARCH_X86_64)*16 + \ + (4+4*ARCH_X86_32)*gprsize - (64+8*ARCH_X86_32)*16 + jmp m(inv_txfm_add_dct_dct_64x16_16bpc).dconly1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5542 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 16 + +; Note: The order of (at least some of) those constants matter! + +const deint_shuf, db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 + +%macro COEF_PAIR 2 +pw_%1_%2: dw %1, %2 +pw_m%2_%1: dw -%2, %1 +%endmacro + +; ADST-only +pw_3803_1321: dw 3803, 1321 +pw_m1321_2482: dw -1321, 2482 +pw_2482_3344: dw 2482, 3344 +pw_m3344_3344: dw -3344, 3344 +pw_m3803_3344: dw -3803, 3344 +pw_m3803_m6688: dw -3803, -6688 +pw_2896_m2896: dw 2896, -2896 + +const pw_5, times 2 dw 5 +const pw_2048, times 2 dw 2048 +const pw_4096, times 2 dw 4096 +const pw_8192, times 2 dw 8192 +const pw_16384, times 2 dw 16384 +const pw_1697x16, times 2 dw 1697*16 +const pw_1697x8, times 2 dw 1697*8 +const pw_2896x8, times 2 dw 2896*8 +const pd_2048, dd 2048 + +const pw_2896_2896, dw 2896, 2896 +const pw_m2896_2896, dw -2896, 2896 +const pw_1567_3784, dw 1567, 3784 +const pw_m3784_1567, dw -3784, 1567 +COEF_PAIR 3784, 1567 +COEF_PAIR 201, 4091 +COEF_PAIR 995, 3973 +COEF_PAIR 1751, 3703 +COEF_PAIR 2440, 3290 +COEF_PAIR 3035, 2751 +COEF_PAIR 3513, 2106 +COEF_PAIR 3857, 1380 +COEF_PAIR 4052, 601 +COEF_PAIR 401, 4076 +COEF_PAIR 1931, 3612 +COEF_PAIR 3166, 2598 +COEF_PAIR 3920, 1189 +COEF_PAIR 799, 4017 +COEF_PAIR 3406, 2276 +pw_m799_m4017: dw -799, -4017 +const pw_m1567_m3784, dw -1567, -3784 +pw_m3406_m2276: dw -3406, -2276 +pw_m401_m4076: dw -401, -4076 +pw_m3166_m2598: dw -3166, -2598 +pw_m1931_m3612: dw -1931, -3612 +pw_m3920_m1189: dw -3920, -1189 +COEF_PAIR 2276, 3406 +COEF_PAIR 4017, 799 + +%macro COEF_X8 1-* +%rep %0 + dw %1*8, %1*8 + %rotate 1 +%endrep +%endmacro + +pw_3703x8: COEF_X8 3703 +pw_1751x8: COEF_X8 1751 +pw_m1380x8: COEF_X8 -1380 +pw_3857x8: COEF_X8 3857 +pw_3973x8: COEF_X8 3973 +pw_995x8: COEF_X8 995 +pw_m2106x8: COEF_X8 -2106 +pw_3513x8: COEF_X8 3513 +pw_3290x8: COEF_X8 3290 +pw_2440x8: COEF_X8 2440 +pw_m601x8: COEF_X8 -601 +pw_4052x8: COEF_X8 4052 + +const idct64_mul +COEF_X8 4095, 101, 4065, 501, 2967, -2824, 3229, -2520 +COEF_X8 3745, 1660, 3564, 2019, 3822, -1474, 3948, -1092 +COEF_X8 3996, 897, 3889, 1285, 3461, -2191, 3659, -1842 +COEF_X8 3349, 2359, 3102, 2675, 4036, -700, 4085, -301 + +pw_201_4091x8: dw 201*8, 4091*8 +pw_m601_4052x8: dw -601*8, 4052*8 +pw_995_3973x8: dw 995*8, 3973*8 +pw_m1380_3857x8: dw -1380*8, 3857*8 +pw_1751_3703x8: dw 1751*8, 3703*8 +pw_m2106_3513x8: dw -2106*8, 3513*8 +pw_2440_3290x8: dw 2440*8, 3290*8 +pw_m2751_3035x8: dw -2751*8, 3035*8 + +%define o_idct64_offset idct64_mul - (o_base) - 8 + +SECTION .text + +; Code size reduction trickery: Instead of using rip-relative loads with +; mandatory 4-byte offsets everywhere, we can set up a base pointer with a +; single rip-relative lea and then address things relative from that with +; 1-byte offsets as long as data is within +-128 bytes of the base pointer. +%define o_base deint_shuf + 128 +%define o(x) (r6 - (o_base) + (x)) +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +; flags: 1 = swap, 2 = interleave, 4: coef_regs +%macro ITX_MUL2X_PACK 6-7 0 ; dst/src, tmp[1-2], rnd, coef[1-2], flags +%if %7 & 4 + pmaddwd m%2, m%5, m%1 + pmaddwd m%1, m%6 +%else +%if %7 & 1 + vpbroadcastd m%2, [o(pw_%5_%6)] + vpbroadcastd m%3, [o(pw_m%6_%5)] +%else + vpbroadcastd m%2, [o(pw_m%6_%5)] + vpbroadcastd m%3, [o(pw_%5_%6)] +%endif + pmaddwd m%2, m%1 + pmaddwd m%1, m%3 +%endif + paddd m%2, m%4 + paddd m%1, m%4 +%if %7 & 2 + pslld m%2, 4 + psrld m%1, 12 + pblendw m%1, m%2, 0xaa +%else + psrad m%2, 12 + psrad m%1, 12 + packssdw m%1, m%2 +%endif +%endmacro + +; flags: 1 = swap, 2 = interleave, 4 = coef_regs +%macro ITX_MUL4X_PACK 9-10 0 ; dst/src, tmp[1-3], rnd, coef[1-4], flags +%if %10 & 1 + vpbroadcastd m%3, [o(pw_%8_%9)] + vpbroadcastd m%4, [o(pw_m%9_%8)] + vpbroadcastd xm%2, [o(pw_%6_%7)] + vpblendd m%2, m%3, 0xf0 + vpbroadcastd xm%3, [o(pw_m%7_%6)] +%else + vpbroadcastd m%3, [o(pw_m%9_%8)] + vpbroadcastd m%4, [o(pw_%8_%9)] + vpbroadcastd xm%2, [o(pw_m%7_%6)] + vpblendd m%2, m%3, 0xf0 + vpbroadcastd xm%3, [o(pw_%6_%7)] +%endif + vpblendd m%3, m%4, 0xf0 + ITX_MUL2X_PACK %1, %4, _, %5, %2, %3, (4|%10) +%endmacro + +; dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +; dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +%macro ITX_MULSUB_2W 7-8 ; dst/src[1-2], tmp[1-2], rnd, coef[1-2], dst2 + punpckhwd m%3, m%2, m%1 + punpcklwd m%2, m%1 +%if %7 < 32 + pmaddwd m%1, m%7, m%2 + pmaddwd m%4, m%7, m%3 +%else + vpbroadcastd m%1, [o(pw_m%7_%6)] + pmaddwd m%4, m%3, m%1 + pmaddwd m%1, m%2 +%endif + paddd m%4, m%5 + paddd m%1, m%5 + psrad m%4, 12 + psrad m%1, 12 + packssdw m%1, m%4 +%if %7 < 32 + pmaddwd m%3, m%6 + pmaddwd m%2, m%6 +%else + vpbroadcastd m%4, [o(pw_%6_%7)] + pmaddwd m%3, m%4 + pmaddwd m%2, m%4 +%endif + paddd m%3, m%5 + paddd m%2, m%5 + psrad m%3, 12 + psrad m%2, 12 +%if %0 == 8 + packssdw m%8, m%2, m%3 +%else + packssdw m%2, m%3 +%endif +%endmacro + +%macro IDCT4_1D 7 ; src[1-4], tmp[1-2], pd_2048 + ITX_MULSUB_2W %2, %4, %5, %6, %7, 1567, 3784, %5 ; t2, t3 + ITX_MULSUB_2W %1, %3, %4, %6, %7, 2896, 2896, %4 ; t1, t0 + psubsw m%3, m%1, m%2 + paddsw m%2, m%1 + paddsw m%1, m%4, m%5 + psubsw m%4, m%5 +%endmacro + +%macro IDCT8_1D 11 ; src[1-8], tmp[1-2], pd_2048 + ITX_MULSUB_2W %6, %4, %9, %10, %11, 3406, 2276 ; t5a, t6a + ITX_MULSUB_2W %2, %8, %9, %10, %11, 799, 4017 ; t4a, t7a + ITX_MULSUB_2W %3, %7, %9, %10, %11, 1567, 3784 ; t2, t3 + paddsw m%9, m%2, m%6 ; t4 + psubsw m%2, m%6 ; t5a + paddsw m%10, m%8, m%4 ; t7 + psubsw m%8, m%4 ; t6a + ITX_MULSUB_2W %1, %5, %4, %6, %11, 2896, 2896 ; t1, t0 + ITX_MULSUB_2W %8, %2, %4, %6, %11, 2896, 2896 ; t5, t6 + psubsw m%6, m%1, m%3 ; dct4 out2 + paddsw m%3, m%1 ; dct4 out1 + paddsw m%1, m%5, m%7 ; dct4 out0 + psubsw m%5, m%7 ; dct4 out3 + psubsw m%7, m%3, m%2 ; out6 + paddsw m%2, m%3 ; out1 + paddsw m%3, m%6, m%8 ; out2 + psubsw m%6, m%8 ; out5 + psubsw m%8, m%1, m%10 ; out7 + paddsw m%1, m%10 ; out0 + paddsw m%4, m%5, m%9 ; out3 + psubsw m%5, m%9 ; out4 +%endmacro + +; in1 = %1, in3 = %2, in5 = %3, in7 = %4 +; in9 = %5, in11 = %6, in13 = %7, in15 = %8 +%macro IDCT16_1D_ODDHALF 11 ; src[1-8], tmp[1-2], pd_2048 + ITX_MULSUB_2W %1, %8, %9, %10, %11, 401, 4076 ; t8a, t15a + ITX_MULSUB_2W %5, %4, %9, %10, %11, 3166, 2598 ; t9a, t14a + ITX_MULSUB_2W %3, %6, %9, %10, %11, 1931, 3612 ; t10a, t13a + ITX_MULSUB_2W %7, %2, %9, %10, %11, 3920, 1189 ; t11a, t12a + psubsw m%9, m%2, m%6 ; t13 + paddsw m%6, m%2 ; t12 + psubsw m%2, m%8, m%4 ; t14 + paddsw m%8, m%4 ; t15 + psubsw m%4, m%7, m%3 ; t10 + paddsw m%3, m%7 ; t11 + psubsw m%7, m%1, m%5 ; t9 + paddsw m%1, m%5 ; t8 + ITX_MULSUB_2W %2, %7, %5, %10, %11, 1567, 3784 ; t9a, t14a + ITX_MULSUB_2W %9, %4, %5, %10, %11, m3784, 1567 ; t10a, t13a + psubsw m%5, m%1, m%3 ; t11a + paddsw m%1, m%3 ; t8a + psubsw m%3, m%7, m%4 ; t13 + paddsw m%7, m%4 ; t14 + psubsw m%4, m%8, m%6 ; t12a + paddsw m%8, m%6 ; t15a + psubsw m%6, m%2, m%9 ; t10 + paddsw m%2, m%9 ; t9 + ITX_MULSUB_2W %3, %6, %9, %10, %11, 2896, 2896 ; t10a, t13a + ITX_MULSUB_2W %4, %5, %9, %10, %11, 2896, 2896 ; t11, t12 +%endmacro + +%macro WRAP_XMM 1+ + INIT_XMM cpuname + %1 + INIT_YMM cpuname +%endmacro + +%macro ITX4_END 4-5 2048 ; row[1-4], rnd +%if %5 + vpbroadcastd m2, [o(pw_%5)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 +%endif + lea r2, [dstq+strideq*2] +%assign %%i 1 +%rep 4 + %if %1 & 2 + CAT_XDEFINE %%row_adr, %%i, r2 + strideq*(%1&1) + %else + CAT_XDEFINE %%row_adr, %%i, dstq + strideq*(%1&1) + %endif + %assign %%i %%i + 1 + %rotate 1 +%endrep + movd m2, [%%row_adr1] + pinsrd m2, [%%row_adr2], 1 + movd m3, [%%row_adr3] + pinsrd m3, [%%row_adr4], 1 + pmovzxbw m2, m2 + pmovzxbw m3, m3 + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + movd [%%row_adr1], m0 + pextrd [%%row_adr2], m0, 1 + pextrd [%%row_adr3], m0, 2 + pextrd [%%row_adr4], m0, 3 + ret +%endmacro + +%macro IWHT4_1D_PACKED 0 + punpckhqdq m3, m0, m1 ; in1 in3 + punpcklqdq m0, m1 ; in0 in2 + psubw m2, m0, m3 + paddw m0, m3 + punpckhqdq m2, m2 ; t2 t2 + punpcklqdq m0, m0 ; t0 t0 + psubw m1, m0, m2 + psraw m1, 1 + psubw m1, m3 ; t1 t3 + psubw m0, m1 ; ____ out0 + paddw m2, m1 ; out3 ____ +%endmacro + +INIT_XMM avx2 +cglobal inv_txfm_add_wht_wht_4x4_8bpc, 3, 3, 4, dst, stride, c + mova m0, [cq+16*0] + mova m1, [cq+16*1] + pxor m2, m2 + mova [cq+16*0], m2 + mova [cq+16*1], m2 + psraw m0, 2 + psraw m1, 2 + IWHT4_1D_PACKED + punpckhwd m0, m1 + punpcklwd m3, m1, m2 + punpckhdq m1, m0, m3 + punpckldq m0, m3 + IWHT4_1D_PACKED + vpblendd m0, m2, 0x03 + ITX4_END 3, 0, 2, 1, 0 + +%macro INV_TXFM_FN 3 ; type1, type2, size +cglobal inv_txfm_add_%1_%2_%3_8bpc, 4, 5, 0, dst, stride, c, eob, tx2 + %define %%p1 m(i%1_%3_internal_8bpc) + lea r6, [o_base] + ; Jump to the 1st txfm function if we're not taking the fast path, which + ; in turn performs an indirect jump to the 2nd txfm function. + lea tx2q, [m(i%2_%3_internal_8bpc).pass2] +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else + ; jump to the 1st txfm function unless it's located directly after this + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endmacro + +%macro INV_TXFM_4X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x4 +%ifidn %1_%2, dct_dct + vpbroadcastw m0, [cq] + vpbroadcastd m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mov [cq], eobd ; 0 + pmulhrsw m0, m1 + mova m1, m0 + jmp m(iadst_4x4_internal_8bpc).end2 +%endif +%endmacro + +%macro IDCT4_1D_PACKED 0 + vpbroadcastd m4, [o(pd_2048)] + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + ITX_MUL2X_PACK 2, 0, 3, 4, 1567, 3784 + ITX_MUL2X_PACK 1, 0, 3, 4, 2896, 2896 + paddsw m0, m1, m2 ; out0 out1 + psubsw m1, m2 ; out3 out2 +%endmacro + +%macro IADST4_1D_PACKED 0 + punpcklwd m2, m1, m0 + punpckhwd m3, m1, m0 + vpbroadcastd m5, [o(pw_m3344_3344)] + vpbroadcastd m0, [o(pw_3803_1321)] + vpbroadcastd m4, [o(pw_m1321_2482)] + pmaddwd m1, m5, m2 ; 3344*in3 - 3344*in2 + psrld m5, 16 + pmaddwd m0, m2 + pmaddwd m2, m4 + pmaddwd m5, m3 ; 3344*in0 + paddd m1, m5 ; 3344*in0 - 3344*in2 + 3344*in3 + vpbroadcastd m4, [o(pw_2482_3344)] + vpbroadcastd m5, [o(pw_m3803_3344)] + pmaddwd m4, m3 + pmaddwd m5, m3 + paddd m4, m0 ; 1321*in0 + 3344*in1 + 3803*in2 + 2482*in3 + vpbroadcastd m0, [o(pw_m3803_m6688)] + pmaddwd m3, m0 + vpbroadcastd m0, [o(pd_2048)] + paddd m2, m0 + paddd m1, m0 + paddd m0, m4 + paddd m5, m2 ; 2482*in0 + 3344*in1 - 1321*in2 - 3803*in3 + paddd m2, m4 + paddd m2, m3 + REPX {psrad x, 12}, m1, m2, m0, m5 + packssdw m0, m5 ; out0 out1 + packssdw m1, m2 ; out2 out3 +%endmacro + +INV_TXFM_4X4_FN dct, dct +INV_TXFM_4X4_FN dct, adst +INV_TXFM_4X4_FN dct, flipadst +INV_TXFM_4X4_FN dct, identity + +cglobal idct_4x4_internal_8bpc, 0, 5, 6, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + IDCT4_1D_PACKED + mova m2, [o(deint_shuf)] + shufps m3, m0, m1, q1331 + shufps m0, m1, q0220 + pshufb m0, m2 + pshufb m1, m3, m2 + jmp tx2q +.pass2: + IDCT4_1D_PACKED + pxor m2, m2 + mova [cq+16*0], m2 + mova [cq+16*1], m2 + ITX4_END 0, 1, 3, 2 + +INV_TXFM_4X4_FN adst, dct +INV_TXFM_4X4_FN adst, adst +INV_TXFM_4X4_FN adst, flipadst +INV_TXFM_4X4_FN adst, identity + +cglobal iadst_4x4_internal_8bpc, 0, 5, 6, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + call .main + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call .main +.end: + pxor m2, m2 + mova [cq+16*0], m2 + mova [cq+16*1], m2 +.end2: + ITX4_END 0, 1, 2, 3 +ALIGN function_align +cglobal_label .main + IADST4_1D_PACKED + ret + +INV_TXFM_4X4_FN flipadst, dct +INV_TXFM_4X4_FN flipadst, adst +INV_TXFM_4X4_FN flipadst, flipadst +INV_TXFM_4X4_FN flipadst, identity + +cglobal iflipadst_4x4_internal_8bpc, 0, 5, 6, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + call m(iadst_4x4_internal_8bpc).main + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + jmp tx2q +.pass2: + call m(iadst_4x4_internal_8bpc).main +.end: + pxor m2, m2 + mova [cq+16*0], m2 + mova [cq+16*1], m2 +.end2: + ITX4_END 3, 2, 1, 0 + +INV_TXFM_4X4_FN identity, dct +INV_TXFM_4X4_FN identity, adst +INV_TXFM_4X4_FN identity, flipadst +INV_TXFM_4X4_FN identity, identity + +cglobal iidentity_4x4_internal_8bpc, 0, 5, 6, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_4x4_internal_8bpc).end + +%macro WRITE_4X8 2 ; coefs[1-2] + movd xm4, [dstq+strideq*0] + pinsrd xm4, [dstq+strideq*1], 1 + movd xm5, [dstq+strideq*2] + pinsrd xm5, [dstq+r3 ], 1 + pinsrd xm4, [r2 +strideq*0], 2 + pinsrd xm4, [r2 +strideq*1], 3 + pinsrd xm5, [r2 +strideq*2], 2 + pinsrd xm5, [r2 +r3 ], 3 + pmovzxbw m4, xm4 + pmovzxbw m5, xm5 + paddw m4, m%1 + paddw m5, m%2 + packuswb m4, m5 + vextracti128 xm5, m4, 1 + movd [dstq+strideq*0], xm4 + pextrd [dstq+strideq*1], xm4, 1 + pextrd [dstq+strideq*2], xm4, 2 + pextrd [dstq+r3 ], xm4, 3 + movd [r2 +strideq*0], xm5 + pextrd [r2 +strideq*1], xm5, 1 + pextrd [r2 +strideq*2], xm5, 2 + pextrd [r2 +r3 ], xm5, 3 +%endmacro + +%macro INV_TXFM_4X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x8 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_2048)] + mov [cq], eobd + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 + mova m1, m0 + jmp m(iadst_4x8_internal_8bpc).end3 +%endif +%endmacro + +%macro IDCT8_1D_PACKED 0 + vpbroadcastd m6, [o(pd_2048)] + punpckhwd m5, m3, m0 ; in7 in1 + punpckhwd m4, m1, m2 ; in3 in5 + punpcklwd m3, m1 ; in6 in2 + punpcklwd m2, m0 ; in4 in0 + ITX_MUL2X_PACK 5, 0, 1, 6, 799, 4017, 3 ; t4a t7a + ITX_MUL2X_PACK 4, 0, 1, 6, 3406, 2276, 3 ; t5a t6a + ITX_MUL2X_PACK 3, 0, 1, 6, 1567, 3784 ; t3 t2 + psubsw m0, m5, m4 ; t5a t6a (interleaved) + paddsw m4, m5 ; t4 t7 (interleaved) + ITX_MUL2X_PACK 2, 1, 5, 6, 2896, 2896 ; t0 t1 + vpbroadcastd m1, [o(pw_m2896_2896)] + ITX_MUL2X_PACK 0, 1, _, 6, 1, 5, 4 ; t6 t5 +%if mmsize > 16 + vbroadcasti128 m1, [o(deint_shuf)] + pshufb m4, m1 +%else + pshufb m4, [o(deint_shuf)] +%endif + psubsw m1, m2, m3 ; tmp3 tmp2 + paddsw m3, m2 ; tmp0 tmp1 + shufps m2, m4, m0, q1032 ; t7 t6 + vpblendd m4, m0, 0xcc ; t4 t5 + paddsw m0, m3, m2 ; out0 out1 + psubsw m3, m2 ; out7 out6 + psubsw m2, m1, m4 ; out4 out5 + paddsw m1, m4 ; out3 out2 +%endmacro + +%macro IADST8_1D_PACKED 1 ; pass + vpbroadcastd m6, [o(pd_2048)] + punpckhwd m0, m4, m3 ; 0 7 + punpckhwd m1, m5, m2 ; 2 5 + punpcklwd m2, m5 ; 4 3 + punpcklwd m3, m4 ; 6 1 +%if %1 == 1 + ITX_MUL2X_PACK 0, 4, 5, 6, 401, 4076, 3 ; t1a t0a + ITX_MUL2X_PACK 1, 4, 5, 6, 1931, 3612, 2 ; t2a t3a + ITX_MUL2X_PACK 2, 4, 5, 6, 3166, 2598, 3 ; t5a t4a + ITX_MUL2X_PACK 3, 4, 5, 6, 3920, 1189, 2 ; t6a t7a + psubsw m4, m0, m2 ; t5 t4 + paddsw m0, m2 ; t1 t0 + psubsw m5, m1, m3 ; t6 t7 + paddsw m1, m3 ; t2 t3 + ITX_MUL2X_PACK 4, 2, 3, 6, 1567, 3784, 3 ; t5a t4a + ITX_MUL2X_PACK 5, 2, 3, 6, 3784, 1567, 2 ; t7a t6a +%if mmsize > 16 + vbroadcasti128 m2, [o(deint_shuf)] +%else + mova m2, [o(deint_shuf)] +%endif + pshuflw m1, m1, q2301 + pshufhw m1, m1, q2301 + psubsw m3, m0, m1 ; t3 t2 + paddsw m0, m1 ; -out7 out0 + psubsw m1, m4, m5 ; t7 t6 + paddsw m4, m5 ; out6 -out1 + pshufb m0, m2 + pshufb m4, m2 + vpbroadcastd m5, [o(pw_m2896_2896)] + pmaddwd m2, m5, m3 + pmaddwd m5, m1 + paddd m2, m6 + paddd m5, m6 + psrad m2, 12 + psrad m5, 12 + packssdw m2, m5 ; out4 -out5 + vpbroadcastd m5, [o(pw_2896_2896)] + pmaddwd m3, m5 + pmaddwd m1, m5 + paddd m3, m6 + paddd m1, m6 + psrad m3, 12 + psrad m1, 12 + packssdw m1, m3 ; out2 -out3 + punpcklqdq m3, m4, m0 ; out6 -out7 + punpckhqdq m0, m4 ; out0 -out1 +%else + ITX_MUL2X_PACK 0, 4, 5, 6, 401, 4076 ; t0a t1a + ITX_MUL2X_PACK 1, 4, 5, 6, 1931, 3612 ; t2a t3a + ITX_MUL2X_PACK 2, 4, 5, 6, 3166, 2598 ; t4a t5a + ITX_MUL2X_PACK 3, 4, 5, 6, 3920, 1189 ; t6a t7a + psubsw m4, m0, m2 ; t4 t5 + paddsw m0, m2 ; t0 t1 + psubsw m5, m1, m3 ; t6 t7 + paddsw m1, m3 ; t2 t3 + shufps m2, m5, m4, q1032 + punpckhwd m4, m2 + punpcklwd m5, m2 + ITX_MUL2X_PACK 4, 2, 3, 6, 1567, 3784, 1 ; t5a t4a + ITX_MUL2X_PACK 5, 2, 3, 6, 3784, 1567 ; t7a t6a + psubsw m2, m0, m1 ; t2 t3 + paddsw m0, m1 ; out0 -out7 + psubsw m1, m4, m5 ; t7 t6 + paddsw m4, m5 ; out6 -out1 + vpbroadcastd m5, [o(pw_2896x8)] + vpblendd m3, m0, m4, 0x33 ; out6 -out7 + vpblendd m0, m4, 0xcc ; out0 -out1 + shufps m4, m2, m1, q1032 ; t3 t7 + vpblendd m1, m2, 0x33 ; t2 t6 + psubsw m2, m1, m4 ; t2-t3 t6-t7 + paddsw m1, m4 ; t2+t3 t6+t7 + pmulhrsw m2, m5 ; out4 -out5 + pshufd m1, m1, q1032 + pmulhrsw m1, m5 ; out2 -out3 +%endif +%endmacro + +INIT_YMM avx2 +INV_TXFM_4X8_FN dct, dct +INV_TXFM_4X8_FN dct, adst +INV_TXFM_4X8_FN dct, flipadst +INV_TXFM_4X8_FN dct, identity + +cglobal idct_4x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + IDCT4_1D_PACKED + vbroadcasti128 m2, [o(deint_shuf)] + shufps m3, m0, m1, q1331 + shufps m0, m1, q0220 + pshufb m0, m2 + pshufb m1, m3, m2 + jmp tx2q +.pass2: + vextracti128 xm2, m0, 1 + vextracti128 xm3, m1, 1 + call .main + vpbroadcastd m4, [o(pw_2048)] + vinserti128 m0, xm2, 1 + vinserti128 m1, xm3, 1 + pshufd m1, m1, q1032 + jmp m(iadst_4x8_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + WRAP_XMM IDCT8_1D_PACKED + ret + +INV_TXFM_4X8_FN adst, dct +INV_TXFM_4X8_FN adst, adst +INV_TXFM_4X8_FN adst, flipadst +INV_TXFM_4X8_FN adst, identity + +cglobal iadst_4x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + call m(iadst_8x4_internal_8bpc).main + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + vextracti128 xm2, m0, 1 + vextracti128 xm3, m1, 1 + pshufd xm4, xm0, q1032 + pshufd xm5, xm1, q1032 + call .main_pass2 + vpbroadcastd m4, [o(pw_2048)] + vinserti128 m0, xm2, 1 + vinserti128 m1, xm3, 1 + pxor m5, m5 + psubw m5, m4 +.end: + vpblendd m4, m5, 0xcc +.end2: + pmulhrsw m0, m4 + pmulhrsw m1, m4 + WIN64_RESTORE_XMM + pxor m2, m2 + mova [cq+32*0], m2 + mova [cq+32*1], m2 +.end3: + lea r2, [dstq+strideq*4] + lea r3, [strideq*3] + WRITE_4X8 0, 1 + RET +ALIGN function_align +.main_pass1: + WRAP_XMM IADST8_1D_PACKED 1 + ret +ALIGN function_align +cglobal_label .main_pass2 + WRAP_XMM IADST8_1D_PACKED 2 + ret + +INV_TXFM_4X8_FN flipadst, dct +INV_TXFM_4X8_FN flipadst, adst +INV_TXFM_4X8_FN flipadst, flipadst +INV_TXFM_4X8_FN flipadst, identity + +cglobal iflipadst_4x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + call m(iadst_8x4_internal_8bpc).main + punpcklwd m3, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m3 + punpckhwd m1, m3 + jmp tx2q +.pass2: + vextracti128 xm2, m0, 1 + vextracti128 xm3, m1, 1 + pshufd xm4, xm0, q1032 + pshufd xm5, xm1, q1032 + call m(iadst_4x8_internal_8bpc).main_pass2 + vpbroadcastd m5, [o(pw_2048)] + vinserti128 m3, xm1, 1 + vinserti128 m2, xm0, 1 + pxor m4, m4 + psubw m4, m5 + pshufd m0, m3, q1032 + pshufd m1, m2, q1032 + jmp m(iadst_4x8_internal_8bpc).end + +INV_TXFM_4X8_FN identity, dct +INV_TXFM_4X8_FN identity, adst +INV_TXFM_4X8_FN identity, flipadst +INV_TXFM_4X8_FN identity, identity + +cglobal iidentity_4x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m2, [cq+32*0], q3120 + vpermq m0, [cq+32*1], q3120 + vpbroadcastd m3, [o(pw_2896x8)] + vpbroadcastd m4, [o(pw_1697x8)] + punpcklwd m1, m2, m0 + punpckhwd m2, m0 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + pmulhrsw m2, m4, m0 + pmulhrsw m4, m1 + paddsw m0, m2 + paddsw m1, m4 + jmp tx2q +.pass2: + vpbroadcastd m4, [o(pw_4096)] + jmp m(iadst_4x8_internal_8bpc).end2 + +%macro INV_TXFM_4X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x16 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + movd xm3, [o(pw_2048)] + mov [cq], eobd + pmulhrsw xm0, xm2 + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm3 + vpbroadcastw m0, xm0 + mova m1, m0 + mova m2, m0 + mova m3, m0 + jmp m(iadst_4x16_internal_8bpc).end3 +%endif +%endmacro + +%macro IDCT16_1D_PACKED 0 + vpbroadcastd m10, [o(pd_2048)] +.main2: + punpckhwd m8, m7, m0 ; dct16 in15 in1 + punpcklwd m9, m4, m0 ; dct4 in2 in0 + punpckhwd m0, m3, m4 ; dct16 in7 in9 + punpcklwd m7, m1 ; dct8 in7 in1 + punpckhwd m1, m6 ; dct16 in3 in13 + punpcklwd m3, m5 ; dct8 in3 in5 + punpckhwd m5, m2 ; dct16 in11 in5 + punpcklwd m6, m2 ; dct4 in3 in1 + ITX_MUL2X_PACK 8, 2, 4, 10, 401, 4076, 3 ; t8a t15a + ITX_MUL2X_PACK 0, 2, 4, 10, 3166, 2598, 3 ; t9a t14a + ITX_MUL2X_PACK 1, 2, 4, 10, 3920, 1189, 3 ; t11a t12a + ITX_MUL2X_PACK 5, 2, 4, 10, 1931, 3612, 3 ; t10a t13a + ITX_MUL2X_PACK 7, 2, 4, 10, 799, 4017, 3 ; t4a t7a + ITX_MUL2X_PACK 3, 2, 4, 10, 3406, 2276, 3 ; t5a t6a + ITX_MUL2X_PACK 6, 2, 4, 10, 1567, 3784 ; t3 t2 + psubsw m2, m8, m0 ; t9 t14 + paddsw m8, m0 ; t8 t15 + psubsw m0, m1, m5 ; t10 t13 + paddsw m1, m5 ; t11 t12 + vpbroadcastd m5, [o(pw_m3784_1567)] ; reuse pw_1567_3784 + ITX_MUL2X_PACK 2, 4, _, 10, 4, 5, 6 ; t9a t14a + vpbroadcastd m4, [o(pw_m1567_m3784)] ; reuse pw_m3784_1567 + ITX_MUL2X_PACK 0, 5, _, 10, 5, 4, 6 ; t10a t13a + psubsw m4, m8, m1 ; t11a t12a + paddsw m8, m1 ; t8a t15a + psubsw m1, m7, m3 ; t5a t6a + paddsw m7, m3 ; t4 t7 + paddsw m3, m2, m0 ; t9 t14 + psubsw m2, m0 ; t10 t13 +%if mmsize > 16 + vbroadcasti128 m0, [o(deint_shuf)] +%else + mova m0, [o(deint_shuf)] +%endif + pshufb m8, m0 + pshufb m7, m0 + pshufb m3, m0 + ITX_MUL2X_PACK 9, 0, 5, 10, 2896, 2896 ; t0 t1 + vpbroadcastd m0, [o(pw_m2896_2896)] + ITX_MUL2X_PACK 4, 5, _, 10, 5, 0, 4 ; t11 t12 + vpbroadcastd m5, [o(pw_2896_2896)] + ITX_MUL2X_PACK 1, 0, _, 10, 0, 5, 4 ; t6 t5 + vpbroadcastd m0, [o(pw_m2896_2896)] + ITX_MUL2X_PACK 2, 0, _, 10, 0, 5, 4 ; t13a t10a + punpckhqdq m0, m8, m3 ; t15a t14 + punpcklqdq m8, m3 ; t8a t9 + shufps m5, m4, m2, q1032 ; t12 t13a + vpblendd m4, m2, 0xcc ; t11 t10a + shufps m2, m7, m1, q1032 ; t7 t6 + vpblendd m7, m1, 0xcc ; t4 t5 + psubsw m1, m9, m6 ; dct4 out3 out2 + paddsw m9, m6 ; dct4 out0 out1 + psubsw m3, m9, m2 ; dct8 out7 out6 + paddsw m9, m2 ; dct8 out0 out1 + psubsw m2, m1, m7 ; dct8 out4 out5 + paddsw m1, m7 ; dct8 out3 out2 + psubsw m7, m9, m0 ; out15 out14 + paddsw m0, m9 ; out0 out1 + psubsw m6, m1, m5 ; out12 out13 + paddsw m1, m5 ; out3 out2 + psubsw m5, m2, m4 ; out11 out10 + paddsw m2, m4 ; out4 out5 + psubsw m4, m3, m8 ; out8 out9 + paddsw m3, m8 ; out7 out6 +%endmacro + +INV_TXFM_4X16_FN dct, dct +INV_TXFM_4X16_FN dct, adst +INV_TXFM_4X16_FN dct, flipadst +INV_TXFM_4X16_FN dct, identity + +cglobal idct_4x16_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + call m(idct_16x4_internal_8bpc).main + vpbroadcastd m5, [o(pw_16384)] + punpckhwd m4, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + REPX {pmulhrsw x, m5}, m0, m4, m2, m3 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + vextracti128 xm4, m0, 1 + vextracti128 xm5, m1, 1 + vextracti128 xm6, m2, 1 + vextracti128 xm7, m3, 1 + call .main + vinserti128 m0, xm4, 1 + vinserti128 m1, xm5, 1 + vpbroadcastd m5, [o(pw_2048)] + vinserti128 m2, xm6, 1 + vinserti128 m3, xm7, 1 + pshufd m1, m1, q1032 + pshufd m3, m3, q1032 + jmp m(iadst_4x16_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + WRAP_XMM IDCT16_1D_PACKED + ret + +INV_TXFM_4X16_FN adst, dct +INV_TXFM_4X16_FN adst, adst +INV_TXFM_4X16_FN adst, flipadst +INV_TXFM_4X16_FN adst, identity + +cglobal iadst_4x16_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m5, [o(pw_16384)] + punpckhwd m4, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + REPX {pmulhrsw x, m5}, m4, m2, m3, m0 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + call .main + vpbroadcastd m5, [o(pw_2896x8)] + paddsw m1, m2, m4 + psubsw m2, m4 + pmulhrsw m1, m5 ; -out7 out4 out6 -out5 + pmulhrsw m2, m5 ; out8 -out11 -out9 out10 + vpbroadcastd m5, [o(pw_2048)] + pshufd m1, m1, q1032 + vpblendd m4, m1, m0, 0x33 + vpblendd m0, m2, 0x33 + vpblendd m2, m3, 0x33 + vpblendd m3, m1, 0x33 + vpermq m0, m0, q2031 + vpermq m1, m2, q1302 + vpermq m2, m3, q3120 + vpermq m3, m4, q0213 + psubw m6, m7, m5 +.end: + vpblendd m5, m6, 0xcc +.end2: + REPX {pmulhrsw x, m5}, m0, m1, m2, m3 + WIN64_RESTORE_XMM + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + mova [cq+32*2], m4 + mova [cq+32*3], m4 +.end3: + lea r2, [dstq+strideq*8] + lea r3, [strideq*3] + WRITE_4X8 0, 1 + lea dstq, [dstq+strideq*4] + lea r2, [r2 +strideq*4] + WRITE_4X8 2, 3 + RET +ALIGN function_align +.main: + vpblendd m4, m1, m0, 0xcc + vpblendd m1, m0, 0x33 + vpblendd m5, m2, m3, 0xcc + vpblendd m2, m3, 0x33 + vperm2i128 m3, m5, m2, 0x31 + vinserti128 m0, m1, xm4, 1 ; in0 in3 in2 in1 + vperm2i128 m4, m1, m4, 0x31 + vinserti128 m1, m5, xm2, 1 ; in4 in7 in6 in5 + pshufd m3, m3, q1032 ; in15 in12 in13 in14 + pshufd m2, m4, q1032 ; in11 in8 in9 in10 +cglobal_label .main2 + vpbroadcastd m8, [o(pd_2048)] + pxor m7, m7 + punpckhwd m4, m3, m0 ; in12 in3 in14 in1 + punpcklwd m0, m3 ; in0 in15 in2 in13 + punpckhwd m3, m2, m1 ; in8 in7 in10 in5 + punpcklwd m1, m2 ; in4 in11 in6 in9 + ITX_MUL4X_PACK 0, 2, 5, 6, 8, 201, 4091, 995, 3973, 3 + ITX_MUL4X_PACK 1, 2, 5, 6, 8, 1751, 3703, 2440, 3290, 3 + ITX_MUL4X_PACK 3, 2, 5, 6, 8, 3035, 2751, 3513, 2106, 3 + ITX_MUL4X_PACK 4, 2, 5, 6, 8, 3857, 1380, 4052, 601, 3 + psubsw m2, m0, m3 ; t9a t8a t11a t10a + paddsw m0, m3 ; t1a t0a t3a t2a + psubsw m3, m1, m4 ; t13a t12a t15a t14a + paddsw m1, m4 ; t5a t4a t7a t6a + ITX_MUL4X_PACK 2, 4, 5, 6, 8, 799, 4017, 3406, 2276, 3 + psubw m6, m7, m5 + ITX_MUL2X_PACK 3, 5, _, 8, 6, 4, 6 + vpbroadcastd m6, [o(pw_m3784_1567)] + vpbroadcastd m5, [o(pw_1567_3784)] + psubsw m4, m0, m1 ; t5 t4 t7 t6 + paddsw m0, m1 ; t1 t0 t3 t2 + psubsw m1, m2, m3 ; t13a t12a t15a t14a + paddsw m2, m3 ; t9a t8a t11a t10a + psubw m3, m7, m6 ; pw_3784_m1567 + vpblendd m6, m3, 0xf0 + ITX_MUL2X_PACK 4, 3, _, 8, 6, 5, 4 ; t4a t5a t7a t6a + ITX_MUL2X_PACK 1, 3, _, 8, 6, 5, 4 ; t12 t13 t15 t14 + vbroadcasti128 m5, [o(deint_shuf)] + pshufb m0, m5 + pshufb m2, m5 + vperm2i128 m3, m0, m2, 0x31 ; t3 t2 t11a t10a + vinserti128 m0, xm2, 1 ; t1 t0 t9a t8a + vperm2i128 m2, m4, m1, 0x31 ; t7a t6a t15 t14 + vinserti128 m4, xm1, 1 ; t4a t5a t12 t13 + pshufd m2, m2, q1032 ; t6a t7a t14 t15 + psubsw m1, m0, m3 ; t3a t2a t11 t10 + paddsw m0, m3 ; -out15 out0 out14 -out1 + paddsw m3, m4, m2 ; -out3 out12 out2 -out13 + psubsw m4, m2 ; t6 t7 t14a t15a + shufps m2, m1, m4, q1032 ; t2a t6 t10 t14a + vpblendd m4, m1, 0x33 ; t3a t7 t11 t15a + ret +ALIGN function_align +.main_pass1_end: + vpbroadcastd m5, [o(pw_m2896_2896)] + vpbroadcastd m6, [o(pw_2896_2896)] + punpcklwd m1, m4, m2 + punpckhwd m4, m2 + pmaddwd m2, m5, m4 + pmaddwd m4, m6 + pmaddwd m5, m1 + pmaddwd m1, m6 + REPX {paddd x, m8}, m5, m1, m2, m4 + REPX {psrad x, 12}, m5, m2, m1, m4 + packssdw m2, m5 ; -out11 out8 out10 -out9 + packssdw m1, m4 ; -out7 out4 out6 -out5 + ret + +INV_TXFM_4X16_FN flipadst, dct +INV_TXFM_4X16_FN flipadst, adst +INV_TXFM_4X16_FN flipadst, flipadst +INV_TXFM_4X16_FN flipadst, identity + +cglobal iflipadst_4x16_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m5, [o(pw_16384)] + punpcklwd m4, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m3, m2 + punpckhwd m3, m2 + REPX {pmulhrsw x, m5}, m4, m1, m0, m3 + punpckldq m2, m3, m1 + punpckhdq m3, m1 + punpckhdq m1, m0, m4 + punpckldq m0, m4 + jmp tx2q +.pass2: + call m(iadst_4x16_internal_8bpc).main + vpbroadcastd m5, [o(pw_2896x8)] + paddsw m1, m2, m4 + psubsw m2, m4 + pmulhrsw m1, m5 ; -out7 out4 out6 -out5 + pmulhrsw m2, m5 ; out8 -out11 -out9 out10 + vpbroadcastd m6, [o(pw_2048)] + pshufd m1, m1, q1032 + vpblendd m4, m0, m2, 0x33 + vpblendd m0, m1, 0xcc + vpblendd m1, m3, 0xcc + vpblendd m2, m3, 0x33 + vpermq m0, m0, q3120 + vpermq m1, m1, q0213 + vpermq m2, m2, q2031 + vpermq m3, m4, q1302 + psubw m5, m7, m6 + jmp m(iadst_4x16_internal_8bpc).end + +INV_TXFM_4X16_FN identity, dct +INV_TXFM_4X16_FN identity, adst +INV_TXFM_4X16_FN identity, flipadst +INV_TXFM_4X16_FN identity, identity + +cglobal iidentity_4x16_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova m3, [cq+32*0] + mova m2, [cq+32*1] + mova m4, [cq+32*2] + mova m5, [cq+32*3] + vpbroadcastd m8, [o(pw_1697x8)] + pcmpeqw m0, m0 ; -1 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m5 + punpckhwd m4, m5 + pmulhrsw m5, m8, m1 + pmulhrsw m6, m8, m2 + pmulhrsw m7, m8, m3 + pmulhrsw m8, m4 + pcmpeqw m9, m0, m1 ; we want to do a signed avg, but pavgw is + pxor m1, m9 ; unsigned. as long as both signs are equal + pcmpeqw m9, m0, m2 ; it still works, but if the input is -1 the + pxor m2, m9 ; pmulhrsw result will become 0 which causes + pcmpeqw m9, m0, m3 ; pavgw to output -32768 instead of 0 unless + pxor m3, m9 ; we explicitly deal with that case here. + pcmpeqw m0, m4 + pxor m4, m0 + pavgw m1, m5 + pavgw m2, m6 + pavgw m3, m7 + pavgw m4, m8 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + vpbroadcastd m8, [o(pw_1697x16)] + vpbroadcastd m5, [o(pw_2048)] + pmulhrsw m4, m8, m0 + pmulhrsw m6, m8, m1 + pmulhrsw m7, m8, m2 + pmulhrsw m8, m3 + REPX {paddsw x, x}, m0, m1, m2, m3 + paddsw m0, m4 + paddsw m1, m6 + paddsw m2, m7 + paddsw m3, m8 + jmp m(iadst_4x16_internal_8bpc).end2 + +%macro WRITE_8X4 4-7 strideq*1, strideq*2, r3 ; coefs[1-2], tmp[1-2], off[1-3] + movq xm%3, [dstq ] + movhps xm%3, [dstq+%5] + movq xm%4, [dstq+%6] + movhps xm%4, [dstq+%7] + pmovzxbw m%3, xm%3 + pmovzxbw m%4, xm%4 +%ifnum %1 + paddw m%3, m%1 +%else + paddw m%3, %1 +%endif +%ifnum %2 + paddw m%4, m%2 +%else + paddw m%4, %2 +%endif + packuswb m%3, m%4 + vextracti128 xm%4, m%3, 1 + movq [dstq ], xm%3 + movhps [dstq+%6], xm%3 + movq [dstq+%5], xm%4 + movhps [dstq+%7], xm%4 +%endmacro + +%macro INV_TXFM_8X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x4 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + mov [cq], eobd + pmulhrsw xm0, xm1 + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).dconly2 +%endif +%endmacro + +INV_TXFM_8X4_FN dct, dct +INV_TXFM_8X4_FN dct, adst +INV_TXFM_8X4_FN dct, flipadst +INV_TXFM_8X4_FN dct, identity + +cglobal idct_8x4_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpbroadcastd xm3, [o(pw_2896x8)] + pmulhrsw xm0, xm3, [cq+16*0] + pmulhrsw xm1, xm3, [cq+16*1] + pmulhrsw xm2, xm3, [cq+16*2] + pmulhrsw xm3, [cq+16*3] + call m(idct_4x8_internal_8bpc).main + vbroadcasti128 m4, [o(deint_shuf)] + vinserti128 m3, m1, xm3, 1 + vinserti128 m1, m0, xm2, 1 + shufps m0, m1, m3, q0220 + shufps m1, m3, q1331 + pshufb m0, m4 + pshufb m1, m4 + jmp tx2q +.pass2: + IDCT4_1D_PACKED + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + jmp m(iadst_8x4_internal_8bpc).end2 + +INV_TXFM_8X4_FN adst, dct +INV_TXFM_8X4_FN adst, adst +INV_TXFM_8X4_FN adst, flipadst +INV_TXFM_8X4_FN adst, identity + +cglobal iadst_8x4_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpbroadcastd xm0, [o(pw_2896x8)] + pshufd xm4, [cq+16*0], q1032 + pmulhrsw xm3, xm0, [cq+16*3] + pshufd xm5, [cq+16*1], q1032 + pmulhrsw xm2, xm0, [cq+16*2] + pmulhrsw xm4, xm0 + pmulhrsw xm5, xm0 + call m(iadst_4x8_internal_8bpc).main_pass1 + vinserti128 m0, xm2, 1 + vinserti128 m1, xm3, 1 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pxor m3, m3 + psubsw m3, m2 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call .main +.end: + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 +.end2: + vpbroadcastd m2, [o(pw_2048)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + WIN64_RESTORE_XMM +.end3: + pxor m2, m2 + mova [cq+32*0], m2 + mova [cq+32*1], m2 + lea r3, [strideq*3] + WRITE_8X4 0, 1, 4, 5 + RET +ALIGN function_align +cglobal_label .main + IADST4_1D_PACKED + ret + +INV_TXFM_8X4_FN flipadst, dct +INV_TXFM_8X4_FN flipadst, adst +INV_TXFM_8X4_FN flipadst, flipadst +INV_TXFM_8X4_FN flipadst, identity + +cglobal iflipadst_8x4_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpbroadcastd xm0, [o(pw_2896x8)] + pshufd xm4, [cq+16*0], q1032 + pmulhrsw xm3, xm0, [cq+16*3] + pshufd xm5, [cq+16*1], q1032 + pmulhrsw xm2, xm0, [cq+16*2] + pmulhrsw xm4, xm0 + pmulhrsw xm5, xm0 + call m(iadst_4x8_internal_8bpc).main_pass1 + vinserti128 m3, xm1, 1 + vinserti128 m2, xm0, 1 + punpckhwd m1, m3, m2 + punpcklwd m3, m2 + pxor m0, m0 + psubsw m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call m(iadst_8x4_internal_8bpc).main + mova m2, m1 + vpermq m1, m0, q2031 + vpermq m0, m2, q2031 + jmp m(iadst_8x4_internal_8bpc).end2 + +INV_TXFM_8X4_FN identity, dct +INV_TXFM_8X4_FN identity, adst +INV_TXFM_8X4_FN identity, flipadst +INV_TXFM_8X4_FN identity, identity + +cglobal iidentity_8x4_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + mova xm2, [cq+16*0] + mova xm0, [cq+16*1] + vinserti128 m2, [cq+16*2], 1 + vinserti128 m0, [cq+16*3], 1 + vpbroadcastd m3, [o(pw_2896x8)] + punpcklwd m1, m2, m0 + punpckhwd m2, m0 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + paddsw m0, m0 + paddsw m1, m1 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_8x4_internal_8bpc).end + +%macro INV_TXFM_8X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x8 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + or r3d, 8 +.dconly: + pmulhrsw xm0, xm2 +.dconly2: + movd xm2, [pw_2048] + pmulhrsw xm0, xm1 + lea r2, [strideq*3] + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 +.dconly_loop: + WRITE_8X4 0, 0, 1, 2, strideq*1, strideq*2, r2 + lea dstq, [dstq+strideq*4] + sub r3d, 4 + jg .dconly_loop + RET +%endif +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst +INV_TXFM_8X8_FN dct, identity + +cglobal idct_8x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 ; 0 1 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m2, [cq+32*2], q3120 ; 4 5 + vpermq m1, [cq+32*1], q3120 ; 2 3 + call .main + shufps m4, m0, m1, q0220 + shufps m5, m0, m1, q1331 + shufps m1, m2, m3, q0220 + shufps m3, m2, m3, q1331 + vbroadcasti128 m0, [o(deint_shuf)] + vpbroadcastd m2, [o(pw_16384)] + REPX {pshufb x, m0}, m4, m5, m1, m3 + REPX {pmulhrsw x, m2}, m4, m5, m1, m3 + vinserti128 m0, m4, xm1, 1 + vperm2i128 m2, m4, m1, 0x31 + vinserti128 m1, m5, xm3, 1 + vperm2i128 m3, m5, m3, 0x31 + jmp tx2q +.pass2: + call .main + vpbroadcastd m4, [o(pw_2048)] + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + jmp m(iadst_8x8_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + IDCT8_1D_PACKED + ret + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, adst +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity + +cglobal iadst_8x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m4, [cq+32*0], q1302 ; 1 0 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m5, [cq+32*1], q1302 ; 3 2 + vpermq m2, [cq+32*2], q3120 ; 4 5 + call .main_pass1 + vpbroadcastd m5, [o(pw_16384)] + punpcklwd m4, m0, m1 + punpckhwd m0, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + pxor m3, m3 + psubw m3, m5 ; negate odd elements during rounding + pmulhrsw m4, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m5 + pmulhrsw m2, m3 + punpcklwd m3, m4, m0 + punpckhwd m4, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + vperm2i128 m2, m3, m0, 0x31 + vinserti128 m0, m3, xm0, 1 + vperm2i128 m3, m4, m1, 0x31 + vinserti128 m1, m4, xm1, 1 + jmp tx2q +.pass2: + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call .main_pass2 + vpbroadcastd m5, [o(pw_2048)] + vpbroadcastd xm4, [o(pw_4096)] + psubw m4, m5 ; lower half = 2048, upper half = -2048 +.end: + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 +.end2: + pmulhrsw m0, m4 + pmulhrsw m1, m4 +.end3: + pmulhrsw m2, m4 + pmulhrsw m3, m4 + WIN64_RESTORE_XMM +.end4: + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + mova [cq+32*2], m4 + mova [cq+32*3], m4 + lea r3, [strideq*3] + WRITE_8X4 0, 1, 4, 5 + lea dstq, [dstq+strideq*4] + WRITE_8X4 2, 3, 4, 5 + RET +ALIGN function_align +.main_pass1: + IADST8_1D_PACKED 1 + ret +ALIGN function_align +cglobal_label .main_pass2 + IADST8_1D_PACKED 2 + ret + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, flipadst +INV_TXFM_8X8_FN flipadst, identity + +cglobal iflipadst_8x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + vpermq m4, [cq+32*0], q1302 ; 1 0 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m5, [cq+32*1], q1302 ; 3 2 + vpermq m2, [cq+32*2], q3120 ; 4 5 + call m(iadst_8x8_internal_8bpc).main_pass1 + vpbroadcastd m5, [o(pw_16384)] + punpckhwd m4, m3, m2 + punpcklwd m3, m2 + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + pxor m0, m0 + psubw m0, m5 + pmulhrsw m4, m0 + pmulhrsw m3, m5 + pmulhrsw m2, m0 + pmulhrsw m1, m5 + punpckhwd m0, m4, m3 + punpcklwd m4, m3 + punpckhwd m3, m2, m1 + punpcklwd m2, m1 + vinserti128 m1, m0, xm3, 1 + vperm2i128 m3, m0, m3, 0x31 + vinserti128 m0, m4, xm2, 1 + vperm2i128 m2, m4, m2, 0x31 + jmp tx2q +.pass2: + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call m(iadst_8x8_internal_8bpc).main_pass2 + vpbroadcastd m4, [o(pw_2048)] + vpbroadcastd xm5, [o(pw_4096)] + psubw m4, m5 ; lower half = -2048, upper half = 2048 + vpermq m5, m3, q2031 + vpermq m3, m0, q2031 + vpermq m0, m2, q2031 + vpermq m2, m1, q2031 + pmulhrsw m1, m0, m4 + pmulhrsw m0, m5, m4 + jmp m(iadst_8x8_internal_8bpc).end3 + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_8bpc, 0, 5, 7, dst, stride, c, eob, tx2 + mova xm3, [cq+16*0] + mova xm2, [cq+16*1] + vinserti128 m3, [cq+16*4], 1 + vinserti128 m2, [cq+16*5], 1 + mova xm4, [cq+16*2] + mova xm0, [cq+16*3] + vinserti128 m4, [cq+16*6], 1 + vinserti128 m0, [cq+16*7], 1 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + vpbroadcastd m4, [o(pw_4096)] + jmp m(iadst_8x8_internal_8bpc).end + +%macro INV_TXFM_8X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x16 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 16 + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).dconly +%endif +%endmacro + +%macro ITX_8X16_LOAD_COEFS 0 + vpbroadcastd m4, [o(pw_2896x8)] + pmulhrsw m0, m4, [cq+32*0] + add cq, 32*4 + pmulhrsw m7, m4, [cq+32*3] + pmulhrsw m1, m4, [cq-32*3] + pmulhrsw m6, m4, [cq+32*2] + pmulhrsw m2, m4, [cq-32*2] + pmulhrsw m5, m4, [cq+32*1] + pmulhrsw m3, m4, [cq-32*1] + pmulhrsw m4, [cq+32*0] +%endmacro + +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, adst +INV_TXFM_8X16_FN dct, flipadst +INV_TXFM_8X16_FN dct, identity + +cglobal idct_8x16_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_8X16_LOAD_COEFS + call m(idct_16x8_internal_8bpc).main + vpbroadcastd m10, [o(pw_16384)] +.pass1_end: + vperm2i128 m9, m3, m7, 0x31 + vinserti128 m3, xm7, 1 + vperm2i128 m8, m2, m6, 0x31 + vinserti128 m2, xm6, 1 + vperm2i128 m6, m1, m5, 0x31 + vinserti128 m1, xm5, 1 + vperm2i128 m5, m0, m4, 0x31 + vinserti128 m0, xm4, 1 + punpckhwd m4, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m1 + punpcklwd m0, m1 +.pass1_end2: + punpckhwd m7, m5, m6 + punpcklwd m5, m6 + punpcklwd m6, m8, m9 + punpckhwd m8, m9 + REPX {pmulhrsw x, m10}, m2, m0, m4, m3, m5, m6, m7, m8 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + punpckldq m4, m5, m6 + punpckhdq m5, m6 + punpckldq m6, m7, m8 + punpckhdq m7, m8 + jmp tx2q +.pass2: + call .main + REPX {vpermq x, x, q3120}, m0, m2, m4, m6 + REPX {vpermq x, x, q2031}, m1, m3, m5, m7 +.end: + vpbroadcastd m8, [o(pw_2048)] +.end2: + REPX {pmulhrsw x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 +.end3: + pxor m8, m8 + REPX {mova [cq+32*x], m8}, -4, -3, -2, -1, 0, 1, 2, 3 + lea r3, [strideq*3] + WRITE_8X4 0, 1, 8, 9 + lea dstq, [dstq+strideq*4] + WRITE_8X4 2, 3, 0, 1 + lea dstq, [dstq+strideq*4] + WRITE_8X4 4, 5, 0, 1 + lea dstq, [dstq+strideq*4] + WRITE_8X4 6, 7, 0, 1 + RET +ALIGN function_align +cglobal_label .main + IDCT16_1D_PACKED + ret + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, adst +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, identity + +cglobal iadst_8x16_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_8X16_LOAD_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + vpbroadcastd m10, [o(pw_16384)] + pslld m9, m10, 17 + psubw m10, m9 ; 16384, -16384 + jmp m(idct_8x16_internal_8bpc).pass1_end +ALIGN function_align +.pass2: + call .main + call .main_pass2_end + vpbroadcastd m9, [o(pw_2048)] + vpbroadcastd xm8, [o(pw_4096)] + psubw m8, m9 + REPX {vpermq x, x, q2031}, m0, m1, m2, m3 + REPX {vpermq x, x, q3120}, m4, m5, m6, m7 + jmp m(idct_8x16_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + REPX {pshufd x, x, q1032}, m7, m1, m5, m3 +.main2: + vpbroadcastd m10, [o(pd_2048)] + punpckhwd m8, m7, m0 ; in14 in1 + punpcklwd m0, m7 ; in0 in15 + punpcklwd m7, m6, m1 ; in12 in3 + punpckhwd m1, m6 ; in2 in13 + punpckhwd m6, m5, m2 ; in10 in5 + punpcklwd m2, m5 ; in4 in11 + punpcklwd m5, m4, m3 ; in8 in7 + punpckhwd m3, m4 ; in6 in9 + ITX_MUL2X_PACK 0, 4, 9, 10, 201, 4091, 3 ; t0 t1 + ITX_MUL2X_PACK 1, 4, 9, 10, 995, 3973, 3 ; t2 t3 + ITX_MUL2X_PACK 2, 4, 9, 10, 1751, 3703, 3 ; t4 t5 + ITX_MUL2X_PACK 3, 4, 9, 10, 2440, 3290, 3 ; t6 t7 + ITX_MUL2X_PACK 5, 4, 9, 10, 3035, 2751, 3 ; t8 t9 + ITX_MUL2X_PACK 6, 4, 9, 10, 3513, 2106, 3 ; t10 t11 + ITX_MUL2X_PACK 7, 4, 9, 10, 3857, 1380, 3 ; t12 t13 + ITX_MUL2X_PACK 8, 4, 9, 10, 4052, 601, 3 ; t14 t15 + psubsw m4, m0, m5 ; t9a t8a + paddsw m0, m5 ; t1a t0a + psubsw m5, m1, m6 ; t11a t10a + paddsw m1, m6 ; t3a t2a + psubsw m6, m2, m7 ; t13a t12a + paddsw m2, m7 ; t5a t4a + psubsw m7, m3, m8 ; t15a t14a + paddsw m3, m8 ; t7a t6a + vpbroadcastd m11, [o(pw_m4017_799)] + vpbroadcastd m12, [o(pw_799_4017)] + pxor m9, m9 + ITX_MUL2X_PACK 4, 8, _, 10, 11, 12, 6 ; t8 t9 + psubw m8, m9, m11 ; pw_4017_m799 + ITX_MUL2X_PACK 6, 12, _, 10, 12, 8, 6 ; t12 t13 + vpbroadcastd m11, [o(pw_m2276_3406)] + vpbroadcastd m12, [o(pw_3406_2276)] + ITX_MUL2X_PACK 5, 8, _, 10, 11, 12, 6 ; t10 t11 + psubw m8, m9, m11 ; pw_2276_m3406 + ITX_MUL2X_PACK 7, 12, _, 10, 12, 8, 6 ; t14 t15 + psubsw m8, m1, m3 ; t7 t6 + paddsw m1, m3 ; t3 t2 + psubsw m3, m0, m2 ; t5 t4 + paddsw m0, m2 ; t1 t0 + psubsw m2, m5, m7 ; t14a t15a + paddsw m7, m5 ; t10a t11a + psubsw m5, m4, m6 ; t12a t13a + paddsw m4, m6 ; t8a t9a + vpbroadcastd m11, [o(pw_m3784_1567)] + vpbroadcastd m12, [o(pw_1567_3784)] + ITX_MUL2X_PACK 3, 6, _, 10, 12, 11, 6 ; t5a t4a + psubw m6, m9, m11 ; pw_3784_m1567 + ITX_MUL2X_PACK 8, 6, _, 10, 6, 12, 6 ; t7a t6a + vpbroadcastd m11, [o(pw_m1567_3784)] + vpbroadcastd m12, [o(pw_3784_1567)] + ITX_MUL2X_PACK 2, 6, _, 10, 11, 12, 6 ; t15 t14 + psubw m6, m9, m11 ; pw_1567_m3784 + ITX_MUL2X_PACK 5, 12, _, 10, 12, 6, 6 ; t13 t12 + vbroadcasti128 m12, [o(deint_shuf)] + paddsw m6, m4, m7 ; -out1 out14 + psubsw m4, m7 ; t10 t11 + psubsw m11, m3, m8 ; t7 t6 + paddsw m8, m3 ; out12 -out3 + psubsw m3, m0, m1 ; t3a t2a + paddsw m0, m1 ; -out15 out0 + paddsw m1, m2, m5 ; -out13 out2 + psubsw m5, m2 ; t15a t14a + pshufb m0, m12 + pshufb m6, m12 + pshufb m8, m12 + pshufb m1, m12 + shufps m7, m6, m0, q1032 ; out14 -out15 + vpblendd m0, m6, 0x33 ; -out1 out0 + punpcklqdq m6, m8, m1 ; out12 -out13 + punpckhqdq m1, m8, m1 ; -out3 out2 + ret +ALIGN function_align +.main_pass1_end: + vpbroadcastd m8, [o(pw_m2896_2896)] + vpbroadcastd m12, [o(pw_2896_2896)] + pmaddwd m9, m8, m11 ; -out11 + pmaddwd m2, m12, m5 ; -out5 + pmaddwd m5, m8 ; out10 + pmaddwd m11, m12 ; out4 + REPX {paddd x, m10}, m9, m5, m2, m11 + REPX {psrad x, 12 }, m9, m5, m2, m11 + packssdw m5, m9 ; out10 -out11 + packssdw m2, m11 ; -out5 out4 + pmaddwd m11, m8, m3 ; out8 + vpbroadcastd m8, [o(pw_2896_m2896)] + pmaddwd m3, m12 ; -out7 + pmaddwd m8, m4 ; -out9 + pmaddwd m4, m12 ; out6 + REPX {paddd x, m10}, m11, m3, m8, m4 + REPX {psrad x, 12 }, m11, m3, m8, m4 + packssdw m3, m4 ; -out7 out6 + packssdw m4, m11, m8 ; out8 -out9 + vpbroadcastd m10, [o(pw_16384)] + pxor m9, m9 + ret +ALIGN function_align +cglobal_label .main_pass2_end + vpbroadcastd m8, [o(pw_2896x8)] + pshufb m2, m11, m12 + pshufb m5, m12 + pshufb m3, m12 + pshufb m4, m12 + punpcklqdq m11, m5, m2 ; t15a t7 + punpckhqdq m5, m2 ; t14a t6 + shufps m2, m3, m4, q1032 ; t2a t10 + vpblendd m3, m4, 0xcc ; t3a t11 + psubsw m4, m2, m3 ; out8 -out9 + paddsw m3, m2 ; -out7 out6 + paddsw m2, m5, m11 ; -out5 out4 + psubsw m5, m11 ; out10 -out11 + REPX {pmulhrsw x, m8}, m2, m3, m4, m5 + ret + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst +INV_TXFM_8X16_FN flipadst, identity + +cglobal iflipadst_8x16_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_8X16_LOAD_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + vpbroadcastd m9, [o(pw_16384)] + pslld m10, m9, 17 + psubw m10, m9 ; -16384, 16384 + vperm2i128 m9, m4, m0, 0x31 + vinserti128 m0, m4, xm0, 1 + vperm2i128 m8, m5, m1, 0x31 + vinserti128 m4, m5, xm1, 1 + vperm2i128 m5, m7, m3, 0x31 + vinserti128 m3, m7, xm3, 1 + vinserti128 m1, m6, xm2, 1 + vperm2i128 m6, m6, m2, 0x31 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 + punpcklwd m0, m3, m1 + punpckhwd m3, m1 + jmp m(idct_8x16_internal_8bpc).pass1_end2 +.pass2: + call m(iadst_8x16_internal_8bpc).main + call m(iadst_8x16_internal_8bpc).main_pass2_end + vpbroadcastd m8, [o(pw_2048)] + vpbroadcastd xm9, [o(pw_4096)] + psubw m8, m9 + vpermq m9, m0, q3120 + vpermq m0, m7, q2031 + vpermq m7, m1, q3120 + vpermq m1, m6, q2031 + vpermq m6, m2, q3120 + vpermq m2, m5, q2031 + vpermq m5, m3, q3120 + vpermq m3, m4, q2031 + pmulhrsw m0, m8 + pmulhrsw m1, m8 + pmulhrsw m2, m8 + pmulhrsw m3, m8 + pmulhrsw m4, m5, m8 + pmulhrsw m5, m6, m8 + pmulhrsw m6, m7, m8 + pmulhrsw m7, m9, m8 + jmp m(idct_8x16_internal_8bpc).end3 + +INV_TXFM_8X16_FN identity, dct +INV_TXFM_8X16_FN identity, adst +INV_TXFM_8X16_FN identity, flipadst +INV_TXFM_8X16_FN identity, identity + +%macro IDTX16 3-4 ; src/dst, tmp, pw_1697x16, [pw_16394] + pmulhrsw m%2, m%3, m%1 +%if %0 == 4 ; if downshifting by 1 + pmulhrsw m%2, m%4 +%else + paddsw m%1, m%1 +%endif + paddsw m%1, m%2 +%endmacro + +cglobal iidentity_8x16_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + mova xm3, [cq+16*0] + mova xm2, [cq+16*2] + add cq, 16*8 + vinserti128 m3, [cq+16*0], 1 + vinserti128 m2, [cq+16*2], 1 + vpbroadcastd m9, [o(pw_2896x8)] + mova xm4, [cq-16*4] + mova xm5, [cq-16*2] + vinserti128 m4, [cq+16*4], 1 + vinserti128 m5, [cq+16*6], 1 + mova xm7, [cq-16*7] + mova xm6, [cq-16*5] + vinserti128 m7, [cq+16*1], 1 + vinserti128 m6, [cq+16*3], 1 + mova xm8, [cq-16*3] + mova xm0, [cq-16*1] + vinserti128 m8, [cq+16*5], 1 + vinserti128 m0, [cq+16*7], 1 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m5 + punpckhwd m4, m5 + punpcklwd m5, m7, m6 + punpckhwd m7, m6 + punpcklwd m6, m8, m0 + punpckhwd m8, m0 + REPX {pmulhrsw x, m9}, m1, m2, m3, m4, m5, m6, m7, m8 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + punpckldq m4, m5, m6 + punpckhdq m5, m6 + punpckldq m6, m7, m8 + punpckhdq m7, m8 + jmp tx2q +.pass2: + vpbroadcastd m8, [o(pw_1697x16)] + REPX {vpermq x, x, q3120}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {IDTX16 x, 9, 8}, 0, 1, 2, 3, 4, 5, 6, 7 + jmp m(idct_8x16_internal_8bpc).end + +%macro WRITE_16X2 6 ; coefs[1-2], tmp[1-2], offset[1-2] + pmovzxbw m%3, [dstq+%5] +%ifnum %1 + paddw m%3, m%1 +%else + paddw m%3, %1 +%endif + pmovzxbw m%4, [dstq+%6] +%ifnum %2 + paddw m%4, m%2 +%else + paddw m%4, %2 +%endif + packuswb m%3, m%4 + vpermq m%3, m%3, q3120 + mova [dstq+%5], xm%3 + vextracti128 [dstq+%6], m%3, 1 +%endmacro + +%macro INV_TXFM_16X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x4 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + or r3d, 4 +.dconly: + pmulhrsw xm0, xm2 + movd xm2, [pw_2048] ; intentionally rip-relative + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 + pxor m3, m3 +.dconly_loop: + mova xm1, [dstq+strideq*0] + vinserti128 m1, [dstq+strideq*1], 1 + punpckhbw m2, m1, m3 + punpcklbw m1, m3 + paddw m2, m0 + paddw m1, m0 + packuswb m1, m2 + mova [dstq+strideq*0], xm1 + vextracti128 [dstq+strideq*1], m1, 1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +%endif +%endmacro + +INV_TXFM_16X4_FN dct, dct +INV_TXFM_16X4_FN dct, adst +INV_TXFM_16X4_FN dct, flipadst +INV_TXFM_16X4_FN dct, identity + +cglobal idct_16x4_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova xm0, [cq+16*0] + mova xm1, [cq+16*1] + mova xm2, [cq+16*2] + mova xm3, [cq+16*3] + mova xm4, [cq+16*4] + mova xm5, [cq+16*5] + mova xm6, [cq+16*6] + mova xm7, [cq+16*7] + call m(idct_4x16_internal_8bpc).main + vinserti128 m6, m2, xm6, 1 + vinserti128 m2, m0, xm4, 1 + vinserti128 m0, m1, xm5, 1 + vinserti128 m1, m3, xm7, 1 + punpcklwd m3, m2, m6 + punpckhwd m2, m6 + vpbroadcastd m6, [o(pw_16384)] + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + mova m1, m6 + jmp m(iadst_16x4_internal_8bpc).pass1_end +.pass2: + call .main + jmp m(iadst_16x4_internal_8bpc).end +ALIGN function_align +cglobal_label .main + vpbroadcastd m6, [o(pd_2048)] + IDCT4_1D 0, 1, 2, 3, 4, 5, 6 + ret + +INV_TXFM_16X4_FN adst, dct +INV_TXFM_16X4_FN adst, adst +INV_TXFM_16X4_FN adst, flipadst +INV_TXFM_16X4_FN adst, identity + +cglobal iadst_16x4_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q1230 + vpermq m3, [cq+32*3], q2103 + vpermq m1, [cq+32*1], q1230 + vpermq m2, [cq+32*2], q2103 + call m(iadst_4x16_internal_8bpc).main2 + call m(iadst_4x16_internal_8bpc).main_pass1_end + punpcklwd m4, m3, m1 + punpcklwd m5, m2, m0 + punpckhwd m0, m1 + punpckhwd m2, m3 + vpbroadcastd m1, [o(pw_16384)] + vinserti128 m3, m0, xm2, 1 + vperm2i128 m2, m0, m2, 0x31 + vinserti128 m0, m4, xm5, 1 + vperm2i128 m4, m4, m5, 0x31 + psubw m6, m7, m1 +.pass1_end: + pmulhrsw m3, m1 + pmulhrsw m2, m6 + pmulhrsw m4, m1 + pmulhrsw m0, m6 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + call .main +.end: + vpbroadcastd m4, [o(pw_2048)] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + WIN64_RESTORE_XMM +.end2: + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + mova [cq+32*2], m4 + mova [cq+32*3], m4 +.end3: + WRITE_16X2 0, 1, 4, 5, strideq*0, strideq*1 + lea dstq, [dstq+strideq*2] + WRITE_16X2 2, 3, 4, 5, strideq*0, strideq*1 + RET +ALIGN function_align +cglobal_label .main + vpbroadcastd m6, [o(pw_m3344_3344)] + vpbroadcastd m7, [o(pw_3803_1321)] + vpbroadcastd m8, [o(pw_m1321_2482)] + vpbroadcastd m9, [o(pw_2482_3344)] + punpcklwd m4, m2, m0 ; in2 in0 l + punpckhwd m2, m0 ; in2 in0 h + psrld m5, m6, 16 + pmaddwd m10, m6, m4 ; t2:02 l + pmaddwd m6, m2 ; t2:02 h + pmaddwd m0, m7, m4 ; t0:02 l + pmaddwd m7, m2 ; t0:02 h + pmaddwd m4, m8 ; t1:02 l + pmaddwd m8, m2 ; t1:02 h + punpckhwd m2, m3, m1 ; in3 in1 h + punpcklwd m3, m1 ; in3 in1 l + pmaddwd m1, m5, m2 ; t2:3 h + pmaddwd m5, m3 ; t2:3 l + paddd m6, m1 + vpbroadcastd m1, [o(pd_2048)] + paddd m10, m5 + pmaddwd m5, m9, m3 + pmaddwd m9, m2 + paddd m0, m1 + paddd m7, m1 + paddd m0, m5 ; t0 + t3 + 2048 l + paddd m7, m9 ; t0 + t3 + 2048 h + vpbroadcastd m9, [o(pw_m3803_3344)] + pmaddwd m5, m9, m2 + pmaddwd m9, m3 + paddd m10, m1 ; t2 + 2048 l + paddd m6, m1 ; t2 + 2048 h + paddd m5, m1 ; t1:13 + 2048 h + paddd m1, m9 ; t1:13 + 2048 l + vpbroadcastd m9, [o(pw_m3803_m6688)] + pmaddwd m2, m9 + pmaddwd m3, m9 + paddd m5, m8 ; t1 + t3 + 2048 h + paddd m1, m4 ; t1 + t3 + 2048 l + paddd m8, m7 + paddd m4, m0 + paddd m2, m8 ; t0 + t1 - t3 + 2048 h + paddd m3, m4 ; t0 + t1 - t3 + 2048 l + REPX {psrad x, 12}, m10, m6, m0, m7, m5, m1, m2, m3 + packssdw m0, m7 + packssdw m1, m5 + packssdw m3, m2 + packssdw m2, m10, m6 + ret + +INV_TXFM_16X4_FN flipadst, dct +INV_TXFM_16X4_FN flipadst, adst +INV_TXFM_16X4_FN flipadst, flipadst +INV_TXFM_16X4_FN flipadst, identity + +cglobal iflipadst_16x4_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q1230 + vpermq m3, [cq+32*3], q2103 + vpermq m1, [cq+32*1], q1230 + vpermq m2, [cq+32*2], q2103 + call m(iadst_4x16_internal_8bpc).main2 + call m(iadst_4x16_internal_8bpc).main_pass1_end + punpckhwd m4, m3, m2 + punpckhwd m5, m1, m0 + punpcklwd m0, m2 + punpcklwd m1, m3 + vpbroadcastd m6, [o(pw_16384)] + vinserti128 m3, m0, xm1, 1 + vperm2i128 m2, m0, m1, 0x31 + vinserti128 m0, m4, xm5, 1 + vperm2i128 m4, m4, m5, 0x31 + psubw m1, m7, m6 + jmp m(iadst_16x4_internal_8bpc).pass1_end +ALIGN function_align +.pass2: + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m4, [o(pw_2048)] + REPX {pmulhrsw x, m4}, m3, m2, m1, m0 + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + mova [cq+32*2], m4 + mova [cq+32*3], m4 + WRITE_16X2 3, 2, 4, 5, strideq*0, strideq*1 + lea dstq, [dstq+strideq*2] + WRITE_16X2 1, 0, 4, 5, strideq*0, strideq*1 + RET + +INV_TXFM_16X4_FN identity, dct +INV_TXFM_16X4_FN identity, adst +INV_TXFM_16X4_FN identity, flipadst +INV_TXFM_16X4_FN identity, identity + +cglobal iidentity_16x4_internal_8bpc, 0, 5, 11, dst, stride, c, eob, tx2 + mova xm2, [cq+16*0] + mova xm4, [cq+16*1] + vinserti128 m2, [cq+16*4], 1 + vinserti128 m4, [cq+16*5], 1 + mova xm0, [cq+16*2] + mova xm1, [cq+16*3] + vinserti128 m0, [cq+16*6], 1 + vinserti128 m1, [cq+16*7], 1 + vpbroadcastd m7, [o(pw_1697x16)] + vpbroadcastd m8, [o(pw_16384)] + punpcklwd m3, m2, m4 + punpckhwd m2, m4 + punpcklwd m4, m0, m1 + punpckhwd m0, m1 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 + pmulhrsw m0, m7, m1 + pmulhrsw m5, m7, m2 + pmulhrsw m6, m7, m3 + pmulhrsw m7, m4 + REPX {pmulhrsw x, m8}, m0, m5, m6, m7 + paddsw m1, m0 + paddsw m2, m5 + paddsw m3, m6 + paddsw m4, m7 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + jmp tx2q +.pass2: + vpbroadcastd m7, [o(pw_1697x8)] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(iadst_16x4_internal_8bpc).end + +%macro INV_TXFM_16X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x8 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 8 + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +%endif +%endmacro + +%macro ITX_16X8_LOAD_COEFS 1 ; shuf_odd + vpbroadcastd m8, [o(pw_2896x8)] + vpermq m0, [cq+32*0], q3120 + add cq, 32*4 + vpermq m7, [cq+32*3], q%1 + vpermq m1, [cq-32*3], q%1 + vpermq m6, [cq+32*2], q3120 + vpermq m2, [cq-32*2], q3120 + vpermq m5, [cq+32*1], q%1 + vpermq m3, [cq-32*1], q%1 + vpermq m4, [cq+32*0], q3120 + REPX {pmulhrsw x, m8}, m0, m7, m1, m6, m2, m5, m3, m4 +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, adst +INV_TXFM_16X8_FN dct, flipadst +INV_TXFM_16X8_FN dct, identity + +cglobal idct_16x8_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_16X8_LOAD_COEFS 3120 + call m(idct_8x16_internal_8bpc).main + vpbroadcastd m10, [o(pw_16384)] + punpckhwd m8, m0, m2 + punpcklwd m0, m2 + punpckhwd m2, m1, m3 + punpcklwd m1, m3 + punpcklwd m9, m4, m6 + punpckhwd m4, m6 + punpcklwd m6, m5, m7 + punpckhwd m5, m7 + REPX {pmulhrsw x, m10}, m8, m1, m4, m6 +.pass1_end: + REPX {pmulhrsw x, m10}, m0, m2, m9, m5 + punpckhwd m3, m0, m8 + punpcklwd m0, m8 + punpckhwd m8, m2, m1 + punpcklwd m2, m1 + punpcklwd m7, m9, m4 + punpckhwd m9, m4 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m8 + punpckhdq m3, m8 + punpckldq m6, m7, m4 + punpckhdq m7, m4 + punpckldq m8, m9, m5 + punpckhdq m9, m5 + vperm2i128 m4, m0, m6, 0x31 + vinserti128 m0, xm6, 1 + vperm2i128 m5, m1, m7, 0x31 + vinserti128 m1, xm7, 1 + vperm2i128 m6, m2, m8, 0x31 + vinserti128 m2, xm8, 1 + vperm2i128 m7, m3, m9, 0x31 + vinserti128 m3, xm9, 1 + jmp tx2q +.pass2: + call .main + vpbroadcastd m8, [o(pw_2048)] +.end: + REPX {pmulhrsw x, m8}, m0, m2, m4, m6 +.end2: + REPX {pmulhrsw x, m8}, m1, m3, m5, m7 + lea r3, [strideq*3] + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r3 +.end3: + pxor m0, m0 + REPX {mova [cq+32*x], m0}, -4, -3, -2, -1, 0, 1, 2, 3 +.end4: + lea dstq, [dstq+strideq*4] + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r3 + RET +ALIGN function_align +cglobal_label .main + vpbroadcastd m10, [o(pd_2048)] +.main2: + IDCT8_1D 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + ret + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, adst +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, identity + +cglobal iadst_16x8_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_16X8_LOAD_COEFS 1302 + call m(iadst_8x16_internal_8bpc).main2 + call m(iadst_8x16_internal_8bpc).main_pass1_end + psubw m11, m9, m10 + punpcklwd m8, m0, m2 + punpckhwd m0, m2 + punpckhwd m2, m1, m3 + punpcklwd m1, m3 + punpcklwd m9, m4, m6 + punpckhwd m4, m6 + punpckhwd m6, m5, m7 + punpcklwd m5, m7 + REPX {pmulhrsw x, m11}, m8, m1, m4, m6 + jmp m(idct_16x8_internal_8bpc).pass1_end +ALIGN function_align +.pass2: + call .main + call .main_pass2_end + pxor m8, m8 + psubw m8, m9 + REPX {pmulhrsw x, m9}, m0, m2, m4, m6 + jmp m(idct_16x8_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + vpbroadcastd m10, [o(pd_2048)] + ITX_MULSUB_2W 7, 0, 8, 9, 10, 401, 4076 ; t1a, t0a + ITX_MULSUB_2W 3, 4, 8, 9, 10, 3166, 2598 ; t5a, t4a + ITX_MULSUB_2W 1, 6, 8, 9, 10, 3920, 1189 ; t7a, t6a + ITX_MULSUB_2W 5, 2, 8, 9, 10, 1931, 3612 ; t3a, t2a + psubsw m8, m2, m6 ; t6 + paddsw m2, m6 ; t2 + psubsw m6, m0, m4 ; t4 + paddsw m0, m4 ; t0 + psubsw m4, m5, m1 ; t7 + paddsw m5, m1 ; t3 + psubsw m1, m7, m3 ; t5 + paddsw m7, m3 ; t1 + ITX_MULSUB_2W 6, 1, 3, 9, 10, 1567, 3784 ; t5a, t4a + ITX_MULSUB_2W 4, 8, 3, 9, 10, 3784, 1567 ; t6a, t7a + psubsw m9, m6, m8 ; t7 + paddsw m6, m8 ; out6 + psubsw m3, m7, m5 ; t3 + paddsw m7, m5 ; -out7 + psubsw m5, m0, m2 ; t2 + paddsw m0, m2 ; out0 + psubsw m2, m1, m4 ; t6 + paddsw m1, m4 ; -out1 + ret +ALIGN function_align +.main_pass1_end: + vpbroadcastd m11, [o(pw_m2896_2896)] + vpbroadcastd m12, [o(pw_2896_2896)] + punpckhwd m4, m3, m5 + punpcklwd m3, m5 + pmaddwd m5, m11, m4 + pmaddwd m4, m12 + pmaddwd m8, m11, m3 + pmaddwd m3, m12 + REPX {paddd x, m10}, m5, m4, m8, m3 + REPX {psrad x, 12 }, m5, m8, m4, m3 + packssdw m3, m4 ; -out3 + packssdw m4, m8, m5 ; out4 + punpcklwd m5, m9, m2 + punpckhwd m9, m2 + pmaddwd m2, m12, m5 + pmaddwd m5, m11 + pmaddwd m12, m9 + pmaddwd m11, m9 + REPX {paddd x, m10}, m2, m5, m12, m11 + REPX {psrad x, 12 }, m2, m12, m5, m11 + packssdw m2, m12 ; out2 + packssdw m5, m11 ; -out5 + ret +ALIGN function_align +cglobal_label .main_pass2_end + vpbroadcastd m8, [o(pw_2896x8)] + psubsw m4, m5, m3 + paddsw m3, m5 + psubsw m5, m2, m9 + paddsw m2, m9 + pmulhrsw m2, m8 ; out2 + pmulhrsw m3, m8 ; -out3 + pmulhrsw m4, m8 ; out4 + pmulhrsw m5, m8 ; -out5 + vpbroadcastd m9, [o(pw_2048)] + ret + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst +INV_TXFM_16X8_FN flipadst, identity + +cglobal iflipadst_16x8_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + ITX_16X8_LOAD_COEFS 1302 + call m(iadst_8x16_internal_8bpc).main2 + call m(iadst_8x16_internal_8bpc).main_pass1_end + psubw m9, m10 + punpcklwd m8, m6, m4 + punpckhwd m6, m4 + punpcklwd m4, m7, m5 + punpckhwd m7, m5 + punpckhwd m5, m3, m1 + punpcklwd m3, m1 + punpckhwd m1, m2, m0 + punpcklwd m2, m0 + REPX {pmulhrsw x, m10}, m8, m4, m5, m1 + REPX {pmulhrsw x, m9 }, m6, m7, m3, m2 + punpcklwd m0, m7, m4 + punpckhwd m7, m4 + punpckhwd m4, m6, m8 + punpcklwd m6, m8 + punpckhwd m8, m3, m5 + punpcklwd m3, m5 + punpcklwd m5, m2, m1 + punpckhwd m2, m1 + punpckhdq m1, m0, m6 + punpckldq m0, m6 + punpckldq m6, m7, m4 + punpckhdq m7, m4 + punpckhdq m4, m3, m5 + punpckldq m3, m5 + punpckldq m5, m8, m2 + punpckhdq m8, m2 + vinserti128 m2, m6, xm5, 1 + vperm2i128 m6, m5, 0x31 + vperm2i128 m5, m1, m4, 0x31 + vinserti128 m1, xm4, 1 + vperm2i128 m4, m0, m3, 0x31 + vinserti128 m0, xm3, 1 + vinserti128 m3, m7, xm8, 1 + vperm2i128 m7, m8, 0x31 + jmp tx2q +.pass2: + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass2_end + pxor m8, m8 + psubw m8, m9 + pmulhrsw m10, m7, m8 + pmulhrsw m7, m0, m9 + pmulhrsw m0, m6, m9 + pmulhrsw m6, m1, m8 + pmulhrsw m1, m5, m8 + pmulhrsw m5, m2, m9 + pmulhrsw m2, m4, m9 + pmulhrsw m4, m3, m8 + lea r3, [strideq*3] + WRITE_16X2 10, 0, 8, 9, strideq*0, strideq*1 + WRITE_16X2 1, 2, 0, 1, strideq*2, r3 + jmp m(idct_16x8_internal_8bpc).end3 + +INV_TXFM_16X8_FN identity, dct +INV_TXFM_16X8_FN identity, adst +INV_TXFM_16X8_FN identity, flipadst +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_8bpc, 0, 5, 13, dst, stride, c, eob, tx2 + mova xm7, [cq+16*0] + mova xm2, [cq+16*1] + add cq, 16*8 + vpbroadcastd m3, [o(pw_2896x8)] + vinserti128 m7, [cq+16*0], 1 + vinserti128 m2, [cq+16*1], 1 + mova xm6, [cq-16*6] + mova xm4, [cq-16*5] + vinserti128 m6, [cq+16*2], 1 + vinserti128 m4, [cq+16*3], 1 + mova xm8, [cq-16*4] + mova xm5, [cq-16*3] + vinserti128 m8, [cq+16*4], 1 + vinserti128 m5, [cq+16*5], 1 + mova xm0, [cq-16*2] + mova xm1, [cq-16*1] + vinserti128 m0, [cq+16*6], 1 + vinserti128 m1, [cq+16*7], 1 + vpbroadcastd m10, [o(pw_1697x16)] + vpbroadcastd m11, [o(pw_16384)] + REPX {pmulhrsw x, m3}, m7, m2, m6, m4, m8, m5, m0, m1 + punpcklwd m3, m7, m2 + punpckhwd m7, m2 + punpcklwd m2, m6, m4 + punpckhwd m6, m4 + punpcklwd m4, m8, m5 + punpckhwd m8, m5 + punpcklwd m5, m0, m1 + punpckhwd m0, m1 + punpckldq m1, m3, m2 + punpckhdq m3, m2 + punpckldq m2, m4, m5 + punpckhdq m4, m5 + punpckldq m5, m7, m6 + punpckhdq m7, m6 + punpckldq m6, m8, m0 + punpckhdq m8, m0 + REPX {IDTX16 x, 0, 10, 11}, 1, 3, 2, 4, 5, 7, 6, 8 + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m6 + punpckhqdq m5, m6 + punpcklqdq m6, m7, m8 + punpckhqdq m7, m8 + jmp tx2q +.pass2: + vpbroadcastd m8, [o(pw_4096)] + jmp m(idct_16x8_internal_8bpc).end + +%define o_base pw_5 + 128 + +%macro INV_TXFM_16X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x16 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 16 + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +%endif +%endmacro + +%macro ITX_16X16_LOAD_COEFS 0 + mova m0, [cq+32*0] + mova m1, [cq+32*1] + mova m2, [cq+32*2] + mova m3, [cq+32*3] + add cq, 32*8 + mova m4, [cq-32*4] + mova m5, [cq-32*3] + mova m6, [cq-32*2] + mova m7, [cq-32*1] + mova m8, [cq+32*0] + mova m9, [cq+32*1] + mova m10, [cq+32*2] + mova m11, [cq+32*3] + mova m12, [cq+32*4] + mova m13, [cq+32*5] + mova m14, [cq+32*6] + mova m15, [cq+32*7] + mova [rsp], m15 +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, adst +INV_TXFM_16X16_FN dct, flipadst +INV_TXFM_16X16_FN dct, identity + +cglobal idct_16x16_internal_8bpc, 0, 5, 16, 32*3, dst, stride, c, eob, tx2 + ITX_16X16_LOAD_COEFS + call .main +.pass1_end: + vpbroadcastd m1, [o(pw_8192)] + REPX {pmulhrsw x, m1}, m0, m2, m4, m6, m8, m10, m12, m14 + vextracti128 [rsp+16*5], m8, 1 + mova [rsp+16*1], xm8 +.pass1_end2: + vextracti128 [rsp+16*4], m0, 1 + mova [rsp+16*0], xm0 + REPX {pmulhrsw x, m1}, m3, m5, m7, m9, m11, m13, m15 + pmulhrsw m1, [rsp+32*1] + vperm2i128 m8, m1, m9, 0x31 + vinserti128 m1, xm9, 1 + vperm2i128 m9, m2, m10, 0x31 + vinserti128 m2, xm10, 1 + vperm2i128 m10, m3, m11, 0x31 + vinserti128 m3, xm11, 1 + vperm2i128 m11, m4, m12, 0x31 + vinserti128 m4, xm12, 1 + vperm2i128 m12, m5, m13, 0x31 + vinserti128 m5, xm13, 1 + vperm2i128 m13, m6, m14, 0x31 + vinserti128 m6, xm14, 1 + vperm2i128 m14, m7, m15, 0x31 + vinserti128 m7, xm15, 1 + mova m15, [rsp+32*2] +.pass1_end3: + punpcklwd m0, m9, m10 + punpckhwd m9, m10 + punpcklwd m10, m15, m8 + punpckhwd m15, m8 + punpckhwd m8, m11, m12 + punpcklwd m11, m12 + punpckhwd m12, m13, m14 + punpcklwd m13, m14 + punpckhdq m14, m11, m13 + punpckldq m11, m13 + punpckldq m13, m15, m9 + punpckhdq m15, m9 + punpckldq m9, m10, m0 + punpckhdq m10, m0 + punpckhdq m0, m8, m12 + punpckldq m8, m12 + punpcklqdq m12, m13, m8 + punpckhqdq m13, m8 + punpcklqdq m8, m9, m11 + punpckhqdq m9, m11 + punpckhqdq m11, m10, m14 + punpcklqdq m10, m14 + punpcklqdq m14, m15, m0 + punpckhqdq m15, m0 + mova m0, [rsp] + mova [rsp], m15 + punpckhwd m15, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m7 + punpcklwd m6, m7 + punpckhwd m7, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckhdq m6, m5, m7 + punpckldq m5, m7 + punpckldq m7, m15, m1 + punpckhdq m15, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m15 + punpcklqdq m6, m15 + jmp tx2q +.pass2: + call .main +.end: + vpbroadcastd m1, [o(pw_2048)] + REPX {pmulhrsw x, m1}, m0, m2, m4, m6, m8, m10, m12, m14 + mova [rsp], m6 +.end2: + REPX {pmulhrsw x, m1}, m3, m5, m7, m9, m11, m13, m15 + pmulhrsw m1, [rsp+32*1] + lea r3, [strideq*3] + WRITE_16X2 0, 1, 6, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 [rsp], 7, 0, 1, strideq*2, r3 +.end3: + pxor m2, m2 + REPX {mova [cq+32*x], m2}, -8, -7, -6, -5, -4, -3, -2, -1 + lea dstq, [dstq+strideq*4] + WRITE_16X2 8, 9, 0, 1, strideq*0, strideq*1 + WRITE_16X2 10, 11, 0, 1, strideq*2, r3 + REPX {mova [cq+32*x], m2}, 0, 1, 2, 3, 4, 5, 6, 7 + lea dstq, [dstq+strideq*4] + WRITE_16X2 12, 13, 0, 1, strideq*0, strideq*1 + WRITE_16X2 14, 15, 0, 1, strideq*2, r3 + RET +ALIGN function_align +cglobal_label .main + vpbroadcastd m15, [o(pd_2048)] + mova [rsp+gprsize+32*1], m1 + mova [rsp+gprsize+32*2], m9 + IDCT8_1D 0, 2, 4, 6, 8, 10, 12, 14, 1, 9, 15 + mova m1, [rsp+gprsize+32*2] ; in9 + mova [rsp+gprsize+32*2], m14 ; tmp7 + mova m9, [rsp+gprsize+32*1] ; in1 + mova [rsp+gprsize+32*1], m10 ; tmp5 + mova m14, [rsp+gprsize+32*0] ; in15 + mova [rsp+gprsize+32*0], m6 ; tmp3 + IDCT16_1D_ODDHALF 9, 3, 5, 7, 1, 11, 13, 14, 6, 10, 15 + mova m6, [rsp+gprsize+32*1] ; tmp5 + psubsw m15, m0, m14 ; out15 + paddsw m0, m14 ; out0 + psubsw m14, m2, m13 ; out14 + paddsw m2, m13 ; out1 + mova [rsp+gprsize+32*1], m2 + psubsw m13, m4, m11 ; out13 + paddsw m2, m4, m11 ; out2 + psubsw m11, m8, m7 ; out11 + paddsw m4, m8, m7 ; out4 + mova m7, [rsp+gprsize+32*2] ; tmp7 + psubsw m10, m6, m5 ; out10 + paddsw m5, m6 ; out5 + psubsw m8, m7, m9 ; out8 + paddsw m7, m9 ; out7 + psubsw m9, m12, m3 ; out9 + paddsw m6, m12, m3 ; out6 + mova m3, [rsp+gprsize+32*0] ; tmp3 + psubsw m12, m3, m1 ; out12 + paddsw m3, m1 ; out3 + ret + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, adst +INV_TXFM_16X16_FN adst, flipadst + +cglobal iadst_16x16_internal_8bpc, 0, 5, 16, 32*3, dst, stride, c, eob, tx2 + ITX_16X16_LOAD_COEFS + call .main + call .main_pass1_end + pmulhrsw m0, m1, [cq+32*0] + pmulhrsw m2, m1, [cq+32*1] + REPX {pmulhrsw x, m1}, m4, m6, m8, m10 + pmulhrsw m12, m1, [cq+32*2] + pmulhrsw m14, m1, [cq+32*3] + vextracti128 [rsp+16*5], m8, 1 + mova [rsp+16*1], xm8 + pxor m8, m8 + psubw m1, m8, m1 + jmp m(idct_16x16_internal_8bpc).pass1_end2 +ALIGN function_align +.pass2: + call .main + call .main_pass2_end + REPX {pmulhrsw x, m1}, m0, m2, m4, m6, m8, m10, m12, m14 + mova [rsp+32*0], m6 + pxor m6, m6 + psubw m1, m6, m1 + jmp m(idct_16x16_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + vpbroadcastd m15, [o(pd_2048)] + mova [rsp+gprsize+32*1], m0 + mova [rsp+gprsize+32*2], m4 + ITX_MULSUB_2W 13, 2, 0, 4, 15, 995, 3973 ; t3, t2 + ITX_MULSUB_2W 9, 6, 0, 4, 15, 2440, 3290 ; t7, t6 + ITX_MULSUB_2W 5, 10, 0, 4, 15, 3513, 2106 ; t11, t10 + ITX_MULSUB_2W 1, 14, 0, 4, 15, 4052, 601 ; t15, t14 + psubsw m0, m2, m10 ; t10a + paddsw m2, m10 ; t2a + psubsw m10, m13, m5 ; t11a + paddsw m13, m5 ; t3a + psubsw m5, m6, m14 ; t14a + paddsw m6, m14 ; t6a + psubsw m14, m9, m1 ; t15a + paddsw m9, m1 ; t7a + ITX_MULSUB_2W 0, 10, 1, 4, 15, 3406, 2276 ; t11, t10 + ITX_MULSUB_2W 14, 5, 1, 4, 15, 2276, 3406 ; t14, t15 + psubsw m1, m10, m14 ; t14a + paddsw m10, m14 ; t10a + psubsw m14, m0, m5 ; t15a + paddsw m0, m5 ; t11a + psubsw m5, m2, m6 ; t6 + paddsw m2, m6 ; t2 + psubsw m6, m13, m9 ; t7 + paddsw m13, m9 ; t3 + ITX_MULSUB_2W 6, 5, 4, 9, 15, 3784, 1567 ; t6a, t7a + ITX_MULSUB_2W 14, 1, 4, 9, 15, 3784, 1567 ; t14, t15 + mova m9, [rsp+gprsize+32*0] ; in15 + mova [rsp+gprsize+32*0], m10 ; t10a + mova m4, [rsp+gprsize+32*1] ; in0 + mova [rsp+gprsize+32*1], m6 ; t6a + mova m6, [rsp+gprsize+32*2] ; in4 + mova [rsp+gprsize+32*2], m2 ; t2 + ITX_MULSUB_2W 9, 4, 2, 10, 15, 201, 4091 ; t1, t0 + ITX_MULSUB_2W 11, 6, 2, 10, 15, 1751, 3703 ; t5, t4 + ITX_MULSUB_2W 7, 8, 2, 10, 15, 3035, 2751 ; t9, t8 + ITX_MULSUB_2W 3, 12, 2, 10, 15, 3857, 1380 ; t13, t12 + psubsw m10, m4, m8 ; t8a + paddsw m8, m4 ; t0a + psubsw m4, m9, m7 ; t9a + paddsw m9, m7 ; t1a + psubsw m7, m6, m12 ; t12a + paddsw m6, m12 ; t4a + psubsw m12, m11, m3 ; t13a + paddsw m11, m3 ; t5a + ITX_MULSUB_2W 10, 4, 2, 3, 15, 799, 4017 ; t9, t8 + ITX_MULSUB_2W 12, 7, 2, 3, 15, 4017, 799 ; t12, t13 + psubsw m3, m9, m11 ; t5 + paddsw m9, m11 ; t1 + psubsw m11, m4, m12 ; t12a + paddsw m4, m12 ; t8a + paddsw m12, m8, m6 ; t0 + psubsw m8, m6 ; t4 + paddsw m6, m10, m7 ; t9a + psubsw m10, m7 ; t13a + ITX_MULSUB_2W 8, 3, 2, 7, 15, 1567, 3784 ; t5a, t4a + ITX_MULSUB_2W 11, 10, 2, 7, 15, 1567, 3784 ; t13, t12 + mova m7, [rsp+gprsize+32*0] ; t10a + mova m2, [rsp+gprsize+32*1] ; t6a + paddsw m15, m9, m13 ; -out15 + psubsw m9, m13 ; t3a + paddsw m13, m11, m1 ; -out13 + psubsw m11, m1 ; t15a + psubsw m1, m4, m7 ; t10 + paddsw m7, m4 ; -out1 + psubsw m4, m3, m2 ; t6 + paddsw m3, m2 ; -out3 + paddsw m2, m10, m14 ; out2 + psubsw m10, m14 ; t14a + paddsw m14, m6, m0 ; out14 + psubsw m6, m0 ; t11 + mova m0, [rsp+gprsize+32*2] ; t2 + mova [rsp+gprsize+32*1], m7 + psubsw m7, m12, m0 ; t2a + paddsw m0, m12 ; out0 + paddsw m12, m8, m5 ; out12 + psubsw m8, m5 ; t7 + ret +ALIGN function_align +.main_pass1_end: + mova [cq+32*0], m0 + mova [cq+32*1], m2 + mova [cq+32*2], m12 + mova [cq+32*3], m14 + vpbroadcastd m14, [pw_m2896_2896] + vpbroadcastd m12, [pw_2896_2896] + vpbroadcastd m2, [pd_2048] + punpcklwd m5, m11, m10 + punpckhwd m11, m10 + pmaddwd m10, m14, m5 + pmaddwd m0, m14, m11 + pmaddwd m5, m12 + pmaddwd m11, m12 + REPX {paddd x, m2}, m10, m0, m5, m11 + REPX {psrad x, 12}, m10, m0, m5, m11 + packssdw m10, m0 ; out10 + packssdw m5, m11 ; -out5 + punpcklwd m11, m8, m4 + punpckhwd m8, m4 + pmaddwd m4, m12, m11 + pmaddwd m0, m12, m8 + pmaddwd m11, m14 + pmaddwd m8, m14 + REPX {paddd x, m2}, m4, m0, m11, m8 + REPX {psrad x, 12}, m4, m0, m11, m8 + packssdw m4, m0 ; out4 + packssdw m11, m8 ; -out11 + punpcklwd m8, m9, m7 + punpckhwd m9, m7 + pmaddwd m7, m12, m8 + pmaddwd m0, m12, m9 + pmaddwd m8, m14 + pmaddwd m9, m14 + REPX {paddd x, m2}, m7, m0, m8, m9 + REPX {psrad x, 12}, m7, m0, m8, m9 + packssdw m7, m0 ; -out7 + packssdw m8, m9 ; out8 + punpckhwd m0, m6, m1 + punpcklwd m6, m1 + pmaddwd m1, m14, m0 + pmaddwd m9, m14, m6 + pmaddwd m0, m12 + pmaddwd m6, m12 + REPX {paddd x, m2}, m1, m9, m0, m6 + REPX {psrad x, 12}, m1, m9, m0, m6 + packssdw m9, m1 ; -out7 + packssdw m6, m0 ; out8 + vpbroadcastd m1, [o(pw_8192)] + ret +ALIGN function_align +cglobal_label .main_pass2_end + ; In pass 2 we're going to clip to pixels afterwards anyway, so clipping to + ; 16-bit here will produce the same result as using 32-bit intermediates. + paddsw m5, m10, m11 ; -out5 + psubsw m10, m11 ; out10 + psubsw m11, m4, m8 ; -out11 + paddsw m4, m8 ; out4 + psubsw m8, m7, m9 ; out8 + paddsw m7, m9 ; -out7 + psubsw m9, m1, m6 ; -out9 + paddsw m6, m1 ; out6 + vpbroadcastd m1, [o(pw_2896x8)] + REPX {pmulhrsw x, m1}, m4, m5, m6, m7, m8, m9, m10, m11 + vpbroadcastd m1, [o(pw_2048)] + ret + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_8bpc, 0, 5, 16, 32*3, dst, stride, c, eob, tx2 + ITX_16X16_LOAD_COEFS + call m(iadst_16x16_internal_8bpc).main + call m(iadst_16x16_internal_8bpc).main_pass1_end + pmulhrsw m6, m1 + pmulhrsw m2, m1, m8 + mova [rsp+32*2], m6 + pmulhrsw m6, m1, m4 + pmulhrsw m4, m1, m10 + pmulhrsw m8, m1, [cq+32*3] + pmulhrsw m10, m1, [cq+32*2] + pmulhrsw m12, m1, [cq+32*1] + pmulhrsw m14, m1, [cq+32*0] + pxor m0, m0 + psubw m0, m1 + REPX {pmulhrsw x, m0}, m3, m5, m7, m11, m15 + pmulhrsw m1, m0, m9 + pmulhrsw m9, m0, m13 + pmulhrsw m0, [rsp+32*1] + mova [rsp+16*0], xm15 + mova [rsp+16*1], xm7 + vperm2i128 m15, m15, m7, 0x31 + vinserti128 m7, m2, xm14, 1 + vperm2i128 m14, m2, m14, 0x31 + vinserti128 m2, m9, xm5, 1 + vperm2i128 m9, m9, m5, 0x31 + vinserti128 m5, m4, xm12, 1 + vperm2i128 m12, m4, m12, 0x31 + vinserti128 m4, m11, xm3, 1 + vperm2i128 m11, m11, m3, 0x31 + vinserti128 m3, m10, xm6, 1 + vperm2i128 m10, m10, m6, 0x31 + vinserti128 m6, m1, xm0, 1 + vperm2i128 m13, m1, m0, 0x31 + vinserti128 m1, m8, [rsp+32*2], 1 + vperm2i128 m8, m8, [rsp+32*2], 0x31 + jmp m(idct_16x16_internal_8bpc).pass1_end3 +.pass2: + call m(iadst_16x16_internal_8bpc).main + call m(iadst_16x16_internal_8bpc).main_pass2_end + pmulhrsw m0, m1 + pmulhrsw m8, m1 + mova [rsp+32*0], m0 + mova [rsp+32*2], m8 + pxor m0, m0 + psubw m0, m1 + pmulhrsw m8, m0, m7 + pmulhrsw m7, m0, m9 + pmulhrsw m9, m1, m6 + pmulhrsw m6, m1, m10 + pmulhrsw m10, m0, m5 + pmulhrsw m5, m0, m11 + pmulhrsw m11, m1, m4 + pmulhrsw m4, m1, m12 + pmulhrsw m12, m0, m3 + pmulhrsw m3, m0, m13 + pmulhrsw m13, m1, m2 + pmulhrsw m1, m14 + pmulhrsw m14, m0, [rsp+32*1] + pmulhrsw m0, m15 + lea r3, [strideq*3] + WRITE_16X2 0, 1, 2, 0, strideq*0, strideq*1 + mova m15, [rsp+32*0] + WRITE_16X2 3, 4, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + WRITE_16X2 5, 6, 0, 1, strideq*0, strideq*1 + WRITE_16X2 7, [rsp+32*2], 0, 1, strideq*2, r3 + jmp m(idct_16x16_internal_8bpc).end3 + +%macro IDTX16B 3 ; src/dst, tmp, pw_1697x16 + pmulhrsw m%2, m%3, m%1 + psraw m%2, 1 + pavgw m%1, m%2 ; signs are guaranteed to be equal +%endmacro + +INV_TXFM_16X16_FN identity, dct +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_8bpc, 0, 5, 16, 32*3, dst, stride, c, eob, tx2 + vpbroadcastd m7, [o(pw_1697x16)] + mova xm0, [cq+16* 0] + vinserti128 m0, [cq+16*16], 1 + mova xm15, [cq+16* 1] + vinserti128 m15, [cq+16*17], 1 + mova xm1, [cq+16* 2] + vinserti128 m1, [cq+16*18], 1 + mova xm8, [cq+16* 3] + vinserti128 m8, [cq+16*19], 1 + mova xm2, [cq+16* 4] + vinserti128 m2, [cq+16*20], 1 + mova xm9, [cq+16* 5] + vinserti128 m9, [cq+16*21], 1 + mova xm3, [cq+16* 6] + vinserti128 m3, [cq+16*22], 1 + mova xm10, [cq+16* 7] + add cq, 16*16 + vinserti128 m10, [cq+16* 7], 1 + mova xm4, [cq-16* 8] + vinserti128 m4, [cq+16* 8], 1 + mova xm11, [cq-16* 7] + vinserti128 m11, [cq+16* 9], 1 + mova xm5, [cq-16* 6] + vinserti128 m5, [cq+16*10], 1 + mova xm12, [cq-16* 5] + vinserti128 m12, [cq+16*11], 1 + mova xm13, [cq-16* 3] + vinserti128 m13, [cq+16*13], 1 + mova xm14, [cq-16* 1] + vinserti128 m14, [cq+16*15], 1 + REPX {IDTX16B x, 6, 7}, 0, 15, 1, 8, 2, 9, 3, \ + 10, 4, 11, 5, 12, 13, 14 + mova xm6, [cq-16* 4] + vinserti128 m6, [cq+16*12], 1 + mova [rsp], m0 + IDTX16B 6, 0, 7 + mova xm0, [cq-16* 2] + vinserti128 m0, [cq+16*14], 1 + pmulhrsw m7, m0 + psraw m7, 1 + pavgw m7, m0 + jmp m(idct_16x16_internal_8bpc).pass1_end3 +ALIGN function_align +.pass2: + vpbroadcastd m15, [o(pw_1697x16)] + mova [rsp+32*1], m0 + REPX {IDTX16 x, 0, 15}, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14 + mova m0, [rsp+32*1] + mova [rsp+32*1], m1 + IDTX16 0, 1, 15 + mova m1, [rsp+32*0] + pmulhrsw m15, m1 + paddsw m1, m1 + paddsw m15, m1 + jmp m(idct_16x16_internal_8bpc).end + +%define o_base deint_shuf + 128 + +%macro LOAD_8ROWS 2-3 0 ; src, stride, is_rect2 +%if %3 + vpbroadcastd m15, [o(pw_2896x8)] + pmulhrsw m0, m15, [%1+%2*0] + pmulhrsw m1, m15, [%1+%2*1] + pmulhrsw m2, m15, [%1+%2*2] + pmulhrsw m3, m15, [%1+%2*3] + pmulhrsw m4, m15, [%1+%2*4] + pmulhrsw m5, m15, [%1+%2*5] + pmulhrsw m6, m15, [%1+%2*6] + pmulhrsw m7, m15, [%1+%2*7] +%else + mova m0, [%1+%2*0] + mova m1, [%1+%2*1] + mova m2, [%1+%2*2] + mova m3, [%1+%2*3] + mova m4, [%1+%2*4] + mova m5, [%1+%2*5] + mova m6, [%1+%2*6] + mova m7, [%1+%2*7] +%endif +%endmacro + +%macro LOAD_8ROWS_H 2-3 0 ; src, stride, is_rect2 +%if %3 +%if %3 == 1 + vpbroadcastd m15, [o(pw_2896x8)] +%endif + pmulhrsw m8, m15, [%1+%2*0] + pmulhrsw m9, m15, [%1+%2*1] + pmulhrsw m10, m15, [%1+%2*2] + pmulhrsw m11, m15, [%1+%2*3] + pmulhrsw m12, m15, [%1+%2*4] + pmulhrsw m13, m15, [%1+%2*5] + pmulhrsw m14, m15, [%1+%2*6] + pmulhrsw m15, [%1+%2*7] +%else + mova m8, [%1+%2*0] + mova m9, [%1+%2*1] + mova m10, [%1+%2*2] + mova m11, [%1+%2*3] + mova m12, [%1+%2*4] + mova m13, [%1+%2*5] + mova m14, [%1+%2*6] + mova m15, [%1+%2*7] +%endif +%endmacro + +%macro ITX_UNPACK_MULHRSW 7 ; dst1, dst2/src, tmp, coef[1-4] + vpbroadcastd m%3, [r5-pw_201_4091x8+pw_%4_%5x8] + punpcklwd m%1, m%2, m%2 + pmulhrsw m%1, m%3 + vpbroadcastd m%3, [r5-pw_201_4091x8+pw_%6_%7x8] + punpckhwd m%2, m%2 + pmulhrsw m%2, m%3 +%endmacro + +cglobal inv_txfm_add_dct_dct_8x32_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 0, 4, 16, 32*3, dst, stride, c, eob + %undef cmp + cmp eobd, 106 + jle .fast + LOAD_8ROWS cq+32*1, 32*2 + call m(idct_16x8_internal_8bpc).main + vperm2i128 m11, m0, m4, 0x31 + vinserti128 m0, xm4, 1 + vperm2i128 m4, m1, m5, 0x31 + vinserti128 m1, xm5, 1 + vperm2i128 m5, m2, m6, 0x31 + vinserti128 m2, xm6, 1 + vperm2i128 m6, m3, m7, 0x31 + vinserti128 m3, xm7, 1 + pxor m7, m7 + REPX {mova [cq+32*x], m7}, 1, 3, 5, 7, 9, 11, 13, 15 + punpckhwd m7, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpcklwd m3, m11, m4 + punpckhwd m11, m4 + punpckhwd m4, m5, m6 + punpcklwd m5, m6 + punpckhdq m6, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m5 + punpckhdq m3, m5 + punpckhdq m5, m11, m4 + punpckldq m11, m4 + punpckldq m4, m7, m1 + punpckhdq m7, m1 + punpckhqdq m12, m6, m0 + punpcklqdq m0, m6 ; out4 + punpckhqdq m13, m7, m4 + punpcklqdq m4, m7 ; out5 + punpckhqdq m14, m3, m2 + punpcklqdq m2, m3 ; out6 + punpckhqdq m15, m5, m11 + punpcklqdq m11, m5 ; out7 + mova [rsp+32*0], m0 + mova [rsp+32*1], m4 + mova [rsp+32*2], m2 +.fast: + LOAD_8ROWS cq+32*0, 32*2 + call m(idct_16x8_internal_8bpc).main + vperm2i128 m8, m0, m4, 0x31 + vinserti128 m0, xm4, 1 + vperm2i128 m4, m1, m5, 0x31 + vinserti128 m1, xm5, 1 + vperm2i128 m5, m2, m6, 0x31 + vinserti128 m2, xm6, 1 + vperm2i128 m6, m3, m7, 0x31 + vinserti128 m3, xm7, 1 + vpbroadcastd m9, [o(pw_8192)] + pxor m7, m7 + REPX {mova [cq+32*x], m7}, 0, 2, 4, 6, 8, 10, 12, 14 + punpckhwd m7, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m8, m4 + punpcklwd m8, m4 + punpckhwd m4, m5, m6 + punpcklwd m5, m6 + punpckhdq m6, m0, m2 + punpckldq m0, m2 + punpckldq m2, m8, m5 + punpckhdq m8, m5 + punpckhdq m5, m3, m4 + punpckldq m3, m4 + punpckhdq m4, m7, m1 + punpckldq m7, m1 + punpcklqdq m1, m7, m4 + punpckhqdq m7, m4 ; out9 + punpckhqdq m4, m2, m8 ; out10 + punpcklqdq m2, m8 + punpckhqdq m8, m3, m5 + punpcklqdq m3, m5 + punpckhqdq m5, m0, m6 ; out8 + punpcklqdq m0, m6 + REPX {pmulhrsw x, m9}, m0, m1, m2, m3, m4, m5, m7 + cmp eobd, 106 + jg .full + mova [rsp+32*0], m5 + mova [rsp+32*1], m7 + mova [rsp+32*2], m4 + pmulhrsw m11, m9, m8 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call .main_fast + jmp .pass2 +.dconly: + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).dconly +.full: + REPX {pmulhrsw x, m9}, m12, m13, m14, m15 + pmulhrsw m6, m9, [rsp+32*2] + mova [rsp+32*2], m4 + pmulhrsw m4, m9, [rsp+32*0] + mova [rsp+32*0], m5 + pmulhrsw m5, m9, [rsp+32*1] + mova [rsp+32*1], m7 + pmulhrsw m7, m9, m11 + pmulhrsw m11, m9, m8 + call .main +.pass2: + vpbroadcastd m12, [o(pw_2048)] + REPX {pmulhrsw x, m12}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m8, m9, m10, m11, m13, m14, m15 + pmulhrsw m12, [rsp] + REPX {vpermq x, x, q3120}, m0, m2, m4, m6, m8, m10, m12, m14 + REPX {vpermq x, x, q2031}, m1, m3, m5, m7, m9, m11, m13, m15 + mova [rsp+32*0], m4 + mova [rsp+32*1], m6 + lea r3, [strideq*3] + WRITE_8X4 0, 1, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 2, 3, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 [rsp+32*0], 5, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 [rsp+32*1], 7, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 8, 9, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 10, 11, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 12, 13, 4, 6 + lea dstq, [dstq+strideq*4] + WRITE_8X4 14, 15, 4, 6 + RET +ALIGN function_align +cglobal_label .main_fast ; bottom half is zero + call m(idct_8x16_internal_8bpc).main + mova m8, [rsp+gprsize+0*32] + mova [rsp+gprsize+0*32], m0 + mova m9, [rsp+gprsize+1*32] + mova [rsp+gprsize+1*32], m1 + mova m0, [rsp+gprsize+2*32] + mova [rsp+gprsize+2*32], m6 + lea r5, [r6-(o_base)+pw_201_4091x8] + ITX_UNPACK_MULHRSW 1, 8, 6, 201, 4091, m601, 4052 ; t16a, t31a, t23a, t24a + ITX_UNPACK_MULHRSW 15, 9, 6, 995, 3973, m1380, 3857 ; t20a, t27a, t19a, t28a + ITX_UNPACK_MULHRSW 14, 0, 6, 1751, 3703, m2106, 3513 ; t18a, t29a, t21a, t26a + ITX_UNPACK_MULHRSW 13, 11, 6, 2440, 3290, m2751, 3035 ; t22a, t25a, t17a, t30a + jmp .main2 +ALIGN function_align +cglobal_label .main + call m(idct_8x16_internal_8bpc).main + mova m8, [rsp+gprsize+0*32] + mova [rsp+gprsize+0*32], m0 + mova m9, [rsp+gprsize+1*32] + mova [rsp+gprsize+1*32], m1 + mova m0, [rsp+gprsize+2*32] + mova [rsp+gprsize+2*32], m6 + punpcklwd m1, m15, m8 ; in31 in1 + punpckhwd m8, m15 ; in3 in29 + punpcklwd m15, m14, m9 ; in27 in5 + punpckhwd m9, m14 ; in7 in25 + punpcklwd m14, m13, m0 ; in23 in9 + punpckhwd m0, m13 ; in11 in21 + punpcklwd m13, m12, m11 ; in19 in13 + punpckhwd m11, m12 ; in15 in17 + ITX_MUL2X_PACK 1, 6, 12, 10, 201, 4091, 3 ; t16a, t31a + ITX_MUL2X_PACK 8, 6, 12, 10, 4052, 601, 3 ; t23a, t24a + ITX_MUL2X_PACK 15, 6, 12, 10, 995, 3973, 3 ; t20a, t27a + ITX_MUL2X_PACK 9, 6, 12, 10, 3857, 1380, 3 ; t19a, t28a + ITX_MUL2X_PACK 14, 6, 12, 10, 1751, 3703, 3 ; t18a, t29a + ITX_MUL2X_PACK 0, 6, 12, 10, 3513, 2106, 3 ; t21a, t26a + ITX_MUL2X_PACK 13, 6, 12, 10, 2440, 3290, 3 ; t22a, t25a + ITX_MUL2X_PACK 11, 6, 12, 10, 3035, 2751, 3 ; t17a, t30a +.main2: + psubsw m6, m1, m11 ; t17 t30 + paddsw m1, m11 ; t16 t31 + psubsw m11, m9, m14 ; t18 t29 + paddsw m9, m14 ; t19 t28 + psubsw m14, m15, m0 ; t21 t26 + paddsw m15, m0 ; t20 t27 + psubsw m0, m8, m13 ; t22 t25 + paddsw m8, m13 ; t23 t24 + ITX_MUL2X_PACK 6, 12, 13, 10, 799, 4017, 3 ; t17a t30a + ITX_MUL2X_PACK 11, 12, 13, 10, m4017, 799, 3 ; t18a t29a + ITX_MUL2X_PACK 14, 12, 13, 10, 3406, 2276, 3 ; t21a t26a + ITX_MUL2X_PACK 0, 12, 13, 10, m2276, 3406, 3 ; t22a t25a + psubsw m13, m1, m9 ; t19a t28a + paddsw m1, m9 ; t16a t31a + psubsw m9, m8, m15 ; t20a t27a + paddsw m8, m15 ; t23a t24a + psubsw m15, m6, m11 ; t18 t29 + paddsw m6, m11 ; t17 t30 + psubsw m11, m0, m14 ; t21 t26 + paddsw m0, m14 ; t22 t25 + ITX_MUL2X_PACK 15, 12, 14, 10, 1567, 3784, 3 ; t18a t29a + ITX_MUL2X_PACK 13, 12, 14, 10, 1567, 3784, 3 ; t19 t28 + ITX_MUL2X_PACK 9, 12, 14, 10, m3784, 1567, 3 ; t20 t27 + ITX_MUL2X_PACK 11, 12, 14, 10, m3784, 1567, 3 ; t21a t26a + vbroadcasti128 m12, [o(deint_shuf)] + psubsw m14, m1, m8 ; t23 t24 + paddsw m1, m8 ; t16 t31 + psubsw m8, m6, m0 ; t22a t25a + paddsw m6, m0 ; t17a t30a + psubsw m0, m15, m11 ; t21 t26 + paddsw m15, m11 ; t18 t29 + psubsw m11, m13, m9 ; t20a t27a + paddsw m13, m9 ; t19a t28a + REPX {pshufb x, m12}, m1, m6, m15, m13 + ITX_MUL2X_PACK 14, 9, 12, 10, 2896, 2896 ; t24a t23a + vpbroadcastd m9, [o(pw_m2896_2896)] + ITX_MUL2X_PACK 8, 12, _, 10, 12, 9, 4 ; t22 t25 + vpbroadcastd m12, [o(pw_2896_2896)] + ITX_MUL2X_PACK 0, 12, _, 10, 12, 9, 4 ; t21a t26a + vpbroadcastd m12, [o(pw_2896_2896)] + ITX_MUL2X_PACK 11, 9, _, 10, 9, 12, 4 ; t27 t20 + shufps m9, m14, m8, q1032 ; t23a t22 + vpblendd m14, m8, 0xcc ; t24a t25 + shufps m8, m11, m0, q1032 ; t20 t21a + vpblendd m11, m0, 0xcc ; t27 t26a + punpcklqdq m0, m1, m6 ; t16 t17a + punpckhqdq m1, m6 ; t31 t30a + psubsw m10, m5, m8 ; out20 out21 + paddsw m5, m8 ; out11 out10 + psubsw m6, m3, m14 ; out24 out25 + paddsw m3, m14 ; out7 out6 + psubsw m8, m7, m0 ; out16 out17 + paddsw m7, m0 ; out15 out14 + mova m0, [rsp+gprsize+0*32] + punpcklqdq m12, m13, m15 ; t19a t18 + punpckhqdq m13, m15 ; t28a t29 + psubsw m15, m0, m1 ; out31 out30 + paddsw m0, m1 ; out0 out1 + mova m1, [rsp+gprsize+1*32] + mova [rsp+gprsize+0*32], m6 + mova m6, [rsp+gprsize+2*32] + psubsw m14, m1, m13 ; out28 out29 + paddsw m1, m13 ; out3 out2 + psubsw m13, m2, m11 ; out27 out26 + paddsw m2, m11 ; out4 out5 + psubsw m11, m4, m9 ; out23 out22 + paddsw m4, m9 ; out8 out9 + psubsw m9, m6, m12 ; out19 out18 + paddsw m6, m12 ; out12 out13 + ret + +%macro LOAD_PACKED_16X2 4 ; dst, tmp, row[1-2] + vbroadcasti128 m%1, [cq+16*%3] + vbroadcasti128 m%2, [cq+16*%4] + shufpd m%1, m%2, 0x0c +%endmacro + +cglobal inv_txfm_add_dct_dct_32x8_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 8 +.dconly: + pmulhrsw xm0, xm2 + movd xm2, [pw_2048] ; intentionally rip-relative + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 + pxor m3, m3 +.dconly_loop: + mova m1, [dstq] + punpckhbw m2, m1, m3 + punpcklbw m1, m3 + paddw m2, m0 + paddw m1, m0 + packuswb m1, m2 + mova [dstq], m1 + add dstq, strideq + dec r3d + jg .dconly_loop + RET +.normal: + PROLOGUE 0, 4, 16, 32*3, dst, stride, c, eob + %undef cmp + LOAD_PACKED_16X2 0, 7, 0, 2 ; in0 in2 + LOAD_PACKED_16X2 4, 7, 1, 3 ; in1 in3 + LOAD_PACKED_16X2 1, 7, 4, 6 ; in4 in6 + LOAD_PACKED_16X2 5, 7, 5, 7 ; in5 in7 + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 0, 1, 2, 3 + add cq, 16*16 + LOAD_PACKED_16X2 2, 7, -8, -6 ; in8 in10 + LOAD_PACKED_16X2 6, 7, -7, -5 ; in9 in11 + LOAD_PACKED_16X2 3, 7, -4, -2 ; in12 in14 + LOAD_PACKED_16X2 11, 7, -3, -1 ; in13 in15 + REPX {mova [cq+32*x], m8}, -4, -3, -2, -1 + mova [rsp+32*0], m4 + mova [rsp+32*1], m5 + mova [rsp+32*2], m6 + cmp eobd, 106 + jg .full + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_fast + jmp .pass2 +.full: + LOAD_PACKED_16X2 4, 7, 0, 2 ; in16 in18 + LOAD_PACKED_16X2 12, 7, 3, 1 ; in19 in17 + LOAD_PACKED_16X2 5, 7, 4, 6 ; in20 in22 + LOAD_PACKED_16X2 13, 7, 7, 5 ; in23 in21 + REPX {mova [cq+32*x], m8}, 0, 1, 2, 3 + add cq, 16*8 + LOAD_PACKED_16X2 6, 7, 0, 2 ; in24 in26 + LOAD_PACKED_16X2 14, 7, 3, 1 ; in27 in25 + LOAD_PACKED_16X2 7, 8, 4, 6 ; in28 in30 + LOAD_PACKED_16X2 15, 8, 7, 5 ; in31 in29 + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 0, 1, 2, 3 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main +.pass2: + vpbroadcastd m12, [o(pw_8192)] + REPX {pmulhrsw x, m12}, m8, m9, m10, m11, m13, m14, m15 + mova [rsp+32*1], m9 + mova [rsp+32*2], m10 + punpckhwd m9, m0, m2 + punpcklwd m0, m2 + punpckhwd m2, m1, m3 + punpcklwd m1, m3 + punpcklwd m10, m4, m6 + punpckhwd m4, m6 + punpcklwd m6, m5, m7 + punpckhwd m5, m7 + punpckhwd m3, m0, m9 + punpcklwd m0, m9 + punpckhwd m9, m2, m1 + punpcklwd m2, m1 + punpcklwd m7, m10, m4 + punpckhwd m10, m4 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m9 + punpckhdq m3, m9 + punpckldq m6, m7, m4 + punpckhdq m7, m4 + punpckldq m9, m10, m5 + punpckhdq m10, m5 + REPX {pmulhrsw x, m12}, m0, m1, m2, m3, m6, m7, m9, m10 + pmulhrsw m12, [rsp+32*0] + mova [rsp+32*0], m8 + vperm2i128 m4, m0, m6, 0x31 + vinserti128 m0, xm6, 1 + vperm2i128 m5, m1, m7, 0x31 + vinserti128 m1, xm7, 1 + vperm2i128 m6, m2, m9, 0x31 + vinserti128 m2, xm9, 1 + vperm2i128 m7, m3, m10, 0x31 + vinserti128 m3, xm10, 1 + call m(idct_16x8_internal_8bpc).main + vpbroadcastd m8, [o(pw_2048)] + REPX {pmulhrsw x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + lea r2, [strideq*3] + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r2 + lea r3, [dstq+strideq*4] + %define dstq r3 + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r2 + mova m0, [rsp+32*0] + mova m1, [rsp+32*1] + mova m2, [rsp+32*2] + punpckhwd m7, m0, m2 + punpcklwd m0, m2 + punpckhwd m2, m1, m11 + punpcklwd m1, m11 + punpckhwd m4, m12, m14 + punpcklwd m12, m14 + punpckhwd m5, m13, m15 + punpcklwd m13, m15 + punpckhwd m3, m0, m7 + punpcklwd m0, m7 + punpckhwd m9, m2, m1 + punpcklwd m2, m1 + punpcklwd m7, m12, m4 + punpckhwd m12, m4 + punpcklwd m4, m5, m13 + punpckhwd m5, m13 + punpckhdq m1, m0, m2 + punpckldq m0, m2 + punpckldq m2, m3, m9 + punpckhdq m3, m9 + punpckldq m6, m7, m4 + punpckhdq m7, m4 + punpckldq m9, m12, m5 + punpckhdq m12, m5 + vperm2i128 m4, m0, m6, 0x31 + vinserti128 m0, xm6, 1 + vperm2i128 m5, m1, m7, 0x31 + vinserti128 m1, xm7, 1 + vperm2i128 m6, m2, m9, 0x31 + vinserti128 m2, xm9, 1 + vperm2i128 m7, m3, m12, 0x31 + vinserti128 m3, xm12, 1 + call m(idct_16x8_internal_8bpc).main2 + vpbroadcastd m8, [o(pw_2048)] + REPX {pmulhrsw x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + add r0, 16 + add r3, 16 + %define dstq r0 + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r2 + %define dstq r3 + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r2 + RET + +cglobal inv_txfm_add_identity_identity_8x32_8bpc, 4, 5, 11, dst, stride, c, eob + vpbroadcastd m9, [pw_5] + lea r4, [strideq*3] + sub eobd, 107 ; loop_iterations = 1 + (eobd >= 107) +.loop: + mova xm0,[cq+16* 0] + mova xm1, [cq+16* 4] + vinserti128 m0, [cq+16* 1], 1 + vinserti128 m1, [cq+16* 5], 1 + pxor m8, m8 + mova [cq+32*0], m8 + mova [cq+32*2], m8 + add cq, 16*16 + mova xm2, [cq-16* 8] + mova xm3, [cq-16* 4] + vinserti128 m2, [cq-16* 7], 1 + vinserti128 m3, [cq-16* 3], 1 + mova xm4, [cq+16* 0] + mova xm5, [cq+16* 4] + vinserti128 m4, [cq+16* 1], 1 + vinserti128 m5, [cq+16* 5], 1 + mova xm6, [cq+16* 8] + mova xm7, [cq+16*12] + vinserti128 m6, [cq+16* 9], 1 + vinserti128 m7, [cq+16*13], 1 + REPX {mova [cq+32*x], m8}, -4, -2, 0, 2, 4, 6 + REPX {paddsw x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + call .transpose8x8 + REPX {psraw x, 3 }, m0, m1, m2, m3, m4, m5, m6, m7 + WRITE_8X4 0, 4, 8, 10, strideq*8, strideq*4, r4*4 + add dstq, strideq + WRITE_8X4 1, 5, 0, 4, strideq*8, strideq*4, r4*4 + add dstq, strideq + WRITE_8X4 2, 6, 0, 4, strideq*8, strideq*4, r4*4 + add dstq, strideq + WRITE_8X4 3, 7, 0, 4, strideq*8, strideq*4, r4*4 + add dstq, strideq + sub cq, 16*16-32 + lea dstq, [dstq+r4*4] + add eobd, 0x80000000 + jnc .loop + RET +ALIGN function_align +.transpose8x8: + punpckhwd m8, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m7 + punpcklwd m6, m7 + punpckhwd m7, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckhdq m6, m5, m7 + punpckldq m5, m7 + punpckldq m7, m8, m1 + punpckhdq m8, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m8 + punpcklqdq m6, m8 + ret + +cglobal inv_txfm_add_identity_identity_32x8_8bpc, 4, 6, 10, dst, stride, c, eob + add cq, 16*8 + vpbroadcastd m9, [pw_4096] + lea r4, [strideq*3] + lea r5, [dstq+strideq*4] + sub eobd, 107 +.loop: + mova xm0, [cq-16*8] + mova xm1, [cq-16*7] + vinserti128 m0, [cq+16*0], 1 + vinserti128 m1, [cq+16*1], 1 + mova xm2, [cq-16*6] + mova xm3, [cq-16*5] + vinserti128 m2, [cq+16*2], 1 + vinserti128 m3, [cq+16*3], 1 + mova xm4, [cq-16*4] + mova xm5, [cq-16*3] + vinserti128 m4, [cq+16*4], 1 + vinserti128 m5, [cq+16*5], 1 + mova xm6, [cq-16*2] + mova xm7, [cq-16*1] + vinserti128 m6, [cq+16*6], 1 + vinserti128 m7, [cq+16*7], 1 + pxor m8, m8 + REPX {mova [cq+32*x], m8}, -4, -3, -2, -1, 0, 1, 2, 3 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + REPX {pmulhrsw x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r4 + %define dstq r5 + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r4 + add cq, 16*16 + add r0, 16 + add r5, 16 + add eobd, 0x80000000 + jnc .loop + RET + +%define o_base pw_5 + 128 + +%macro LOAD_16ROWS 2-4 0, 1 ; src, stride, is_rect2, zero_coefs +%if %3 + vpbroadcastd m15, [o(pw_2896x8)] + pmulhrsw m0, m15, [%1+%2* 0] + pmulhrsw m1, m15, [%1+%2* 1] + pmulhrsw m2, m15, [%1+%2* 2] + pmulhrsw m3, m15, [%1+%2* 3] + pmulhrsw m4, m15, [%1+%2* 4] + pmulhrsw m5, m15, [%1+%2* 5] + pmulhrsw m6, m15, [%1+%2* 6] + pmulhrsw m7, m15, [%1+%2* 7] + pmulhrsw m8, m15, [%1+%2* 8] + pmulhrsw m9, m15, [%1+%2* 9] + pmulhrsw m10, m15, [%1+%2*10] + pmulhrsw m11, m15, [%1+%2*11] + pmulhrsw m12, m15, [%1+%2*12] + pmulhrsw m13, m15, [%1+%2*13] + pmulhrsw m14, m15, [%1+%2*14] + pmulhrsw m15, [%1+%2*15] +%else + mova m0, [%1+%2* 0] + mova m1, [%1+%2* 1] + mova m2, [%1+%2* 2] + mova m3, [%1+%2* 3] + mova m4, [%1+%2* 4] + mova m5, [%1+%2* 5] + mova m6, [%1+%2* 6] + mova m7, [%1+%2* 7] + mova m8, [%1+%2* 8] + mova m9, [%1+%2* 9] + mova m10, [%1+%2*10] + mova m11, [%1+%2*11] + mova m12, [%1+%2*12] + mova m13, [%1+%2*13] + mova m14, [%1+%2*14] + mova m15, [%1+%2*15] +%endif + mova [rsp], m15 +%if %4 + pxor m15, m15 + REPX {mova [%1+%2*x], m15}, 0, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14, 15 +%endif +%endmacro + +%macro IDCT32_PASS2_END 7 ; coefs[1-2], tmp[1-2], rnd, offset[1-2] + mova m%4, [%2] + paddsw m%3, m%1, m%4 + psubsw m%1, m%4 + pmovzxbw m%4, [dstq+%6] + pmulhrsw m%3, m%5 + pmulhrsw m%1, m%5 + paddw m%3, m%4 + pmovzxbw m%4, [r2+%7] + paddw m%1, m%4 + packuswb m%3, m%1 + vpermq m%3, m%3, q3120 + mova [dstq+%6], xm%3 + vextracti128 [r2+%7], m%3, 1 +%endmacro + +cglobal inv_txfm_add_dct_dct_16x32_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 0, 8, 16, 32*35, dst, stride, c, eob, tmp1, tmp2, \ + base, tmp3 + %undef cmp + LOAD_16ROWS cq, 64, 1 + call m(idct_16x16_internal_8bpc).main + lea tmp1q, [rsp+32*7] + lea tmp2q, [tmp1q+32*8] + lea tmp3q, [tmp1q+32*16] + mova m1, [rsp+32*1] + mova [rsp+32*0], m6 + mova [rsp+32*1], m7 + vpbroadcastd m7, [o(pw_16384)] + call .transpose_2x8x8_round + mova m15, [rsp+32*0] + mova [tmp3q-32*4+ 0], xm0 + vextracti128 [tmp3q+32*0+ 0], m0, 1 + mova [tmp3q-32*3+ 0], xm2 + vextracti128 [tmp3q+32*1+ 0], m2, 1 + mova [tmp3q-32*2+ 0], xm4 + vextracti128 [tmp3q+32*2+ 0], m4, 1 + mova [tmp3q-32*1+ 0], xm6 + vextracti128 [tmp3q+32*3+ 0], m6, 1 + mova [tmp3q-32*4+16], xm8 + vextracti128 [tmp3q+32*0+16], m8, 1 + mova [tmp3q-32*3+16], xm10 + vextracti128 [tmp3q+32*1+16], m10, 1 + mova [tmp3q-32*2+16], xm12 + vextracti128 [tmp3q+32*2+16], m12, 1 + mova [tmp3q-32*1+16], xm14 + vextracti128 [tmp3q+32*3+16], m14, 1 + cmp eobd, 150 + jg .full + vinserti128 m0, m1, xm9, 1 + vperm2i128 m4, m1, m9, 0x31 + vinserti128 m2, m5, xm13, 1 + vperm2i128 m6, m5, m13, 0x31 + vinserti128 m1, m3, xm11, 1 + vperm2i128 m5, m3, m11, 0x31 + vinserti128 m3, m7, xm15, 1 + vperm2i128 m7, m7, m15, 0x31 + call .main_oddhalf_fast + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 + jmp .idct16 +.dconly: + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +.full: + mova [tmp1q-32*4], m1 + mova [tmp1q-32*3], m3 + mova [tmp1q-32*2], m5 + mova [tmp1q-32*1], m7 + mova [tmp1q+32*0], m9 + mova [tmp1q+32*1], m11 + mova [tmp1q+32*2], m13 + mova [tmp1q+32*3], m15 + LOAD_16ROWS cq+32, 64, 1 + call m(idct_16x16_internal_8bpc).main + lea r2, [tmp3q+32*8] + mova m1, [rsp+32*1] + mova [rsp+32*0], m6 + mova [rsp+32*1], m7 + vpbroadcastd m7, [o(pw_16384)] + call .transpose_2x8x8_round + mova m15, [rsp+32*0] + mova [r2-32*4+ 0], xm0 + vextracti128 [r2+32*0+ 0], m0, 1 + mova [r2-32*3+ 0], xm2 + vextracti128 [r2+32*1+ 0], m2, 1 + mova [r2-32*2+ 0], xm4 + vextracti128 [r2+32*2+ 0], m4, 1 + mova [r2-32*1+ 0], xm6 + vextracti128 [r2+32*3+ 0], m6, 1 + mova [r2-32*4+16], xm8 + vextracti128 [r2+32*0+16], m8, 1 + mova [r2-32*3+16], xm10 + vextracti128 [r2+32*1+16], m10, 1 + mova [r2-32*2+16], xm12 + vextracti128 [r2+32*2+16], m12, 1 + mova [r2-32*1+16], xm14 + vextracti128 [r2+32*3+16], m14, 1 + vinserti128 m8, m1, xm9, 1 + vperm2i128 m12, m1, m9, 0x31 + mova xm0, [tmp1q-32*4] + mova xm1, [tmp1q-32*3] + vinserti128 m0, [tmp1q+32*0], 1 + vinserti128 m1, [tmp1q+32*1], 1 + vinserti128 m10, m5, xm13, 1 + vperm2i128 m14, m5, m13, 0x31 + mova xm4, [tmp1q-32*4+16] + mova xm5, [tmp1q-32*3+16] + vinserti128 m4, [tmp1q+32*0+16], 1 + vinserti128 m5, [tmp1q+32*1+16], 1 + vinserti128 m9, m3, xm11, 1 + vperm2i128 m13, m3, m11, 0x31 + mova xm2, [tmp1q-32*2] + mova xm3, [tmp1q-32*1] + vinserti128 m2, [tmp1q+32*2], 1 + vinserti128 m3, [tmp1q+32*3], 1 + vinserti128 m11, m7, xm15, 1 + vperm2i128 m15, m7, m15, 0x31 + mova xm6, [tmp1q-32*2+16] + mova xm7, [tmp1q-32*1+16] + vinserti128 m6, [tmp1q+32*2+16], 1 + vinserti128 m7, [tmp1q+32*3+16], 1 + call .main_oddhalf + LOAD_8ROWS_H r2-32*4, 32 +.idct16: + LOAD_8ROWS tmp3q-32*4, 32 + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq + call .pass2_end + RET +ALIGN function_align +cglobal_label .main_oddhalf_fast ; lower half is zero + mova [rsp+gprsize+32*1], m7 + pxor m7, m7 + mova [rsp+gprsize+32*0], m7 + mova [rsp+gprsize+32*2], m7 + vpbroadcastd m11, [o(pw_3703x8)] + vpbroadcastd m7, [o(pw_1751x8)] + vpbroadcastd m12, [o(pw_m1380x8)] + vpbroadcastd m8, [o(pw_3857x8)] + vpbroadcastd m13, [o(pw_3973x8)] + vpbroadcastd m15, [o(pw_995x8)] + pmulhrsw m11, m4 ; t29a + pmulhrsw m4, m7 ; t18a + pmulhrsw m12, m3 ; t19a + pmulhrsw m3, m8 ; t28a + pmulhrsw m13, m2 ; t27a + pmulhrsw m2, m15 ; t20a + vpbroadcastd m10, [o(pw_m2106x8)] + vpbroadcastd m7, [o(pw_3513x8)] + vpbroadcastd m9, [o(pw_3290x8)] + vpbroadcastd m8, [o(pw_2440x8)] + vpbroadcastd m14, [o(pw_m601x8)] + vpbroadcastd m15, [o(pw_4052x8)] + pmulhrsw m10, m5 ; t21a + pmulhrsw m5, m7 ; t26a + pmulhrsw m9, m6 ; t25a + pmulhrsw m6, m8 ; t22a + pmulhrsw m14, m1 ; t23a + pmulhrsw m1, m15 ; t24a + vpbroadcastd m15, [o(pd_2048)] + jmp .main2 +ALIGN function_align +cglobal_label .main_oddhalf + mova [rsp+gprsize+32*0], m15 + mova [rsp+gprsize+32*1], m7 + mova [rsp+gprsize+32*2], m8 + vpbroadcastd m15, [o(pd_2048)] + ITX_MULSUB_2W 4, 11, 7, 8, 15, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2W 12, 3, 7, 8, 15, 3857, 1380 ; t19a, t28a + ITX_MULSUB_2W 2, 13, 7, 8, 15, 995, 3973 ; t20a, t27a + ITX_MULSUB_2W 10, 5, 7, 8, 15, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2W 6, 9, 7, 8, 15, 2440, 3290 ; t22a, t25a + ITX_MULSUB_2W 14, 1, 7, 8, 15, 4052, 601 ; t23a, t24a +.main2: + psubsw m7, m12, m4 ; t18 + paddsw m12, m4 ; t19 + psubsw m4, m2, m10 ; t21 + paddsw m2, m10 ; t20 + psubsw m10, m14, m6 ; t22 + paddsw m14, m6 ; t23 + psubsw m6, m1, m9 ; t25 + paddsw m1, m9 ; t24 + psubsw m9, m13, m5 ; t26 + paddsw m13, m5 ; t27 + psubsw m5, m3, m11 ; t29 + paddsw m3, m11 ; t28 + ITX_MULSUB_2W 5, 7, 8, 11, 15, m4017, 799 ; t18a, t29a + ITX_MULSUB_2W 9, 4, 8, 11, 15, 3406, 2276 ; t21a, t26a + ITX_MULSUB_2W 6, 10, 8, 11, 15, m2276, 3406 ; t22a, t25a + psubsw m8, m14, m2 ; t20a + paddsw m14, m2 ; t23a + psubsw m2, m1, m13 ; t27a + paddsw m1, m13 ; t24a + psubsw m13, m6, m9 ; t21 + paddsw m6, m9 ; t22 + psubsw m9, m10, m4 ; t26 + paddsw m10, m4 ; t25 + ITX_MULSUB_2W 2, 8, 4, 11, 15, m3784, 1567 ; t20, t27 + ITX_MULSUB_2W 9, 13, 4, 11, 15, m3784, 1567 ; t21a, t26a + mova m4, [rsp+gprsize+32*0] ; in31 + mova [rsp+gprsize+32*0], m6 ; t22 + mova m6, [rsp+gprsize+32*1] ; in15 + mova [rsp+gprsize+32*1], m14 ; t23a + mova m14, [rsp+gprsize+32*2] ; in17 + mova [rsp+gprsize+32*2], m1 ; t24a + ITX_MULSUB_2W 0, 4, 1, 11, 15, 201, 4091 ; t16a, t31a + ITX_MULSUB_2W 14, 6, 1, 11, 15, 3035, 2751 ; t17a, t30a + psubsw m1, m0, m14 ; t17 + paddsw m0, m14 ; t16 + psubsw m14, m4, m6 ; t30 + paddsw m4, m6 ; t31 + ITX_MULSUB_2W 14, 1, 6, 11, 15, 799, 4017 ; t17a, t30a + psubsw m6, m0, m12 ; t19a + paddsw m0, m12 ; t16a + psubsw m12, m4, m3 ; t28a + paddsw m4, m3 ; t31a + psubsw m3, m14, m5 ; t18 + paddsw m14, m5 ; t17 + psubsw m5, m1, m7 ; t29 + paddsw m1, m7 ; t30 + ITX_MULSUB_2W 5, 3, 7, 11, 15, 1567, 3784 ; t18a, t29a + ITX_MULSUB_2W 12, 6, 7, 11, 15, 1567, 3784 ; t19, t28 + psubsw m7, m1, m10 ; t25a + paddsw m1, m10 ; t30a + psubsw m10, m5, m9 ; t21 + paddsw m5, m9 ; t18 + psubsw m9, m12, m2 ; t20a + paddsw m12, m2 ; t19a + psubsw m2, m3, m13 ; t26 + paddsw m3, m13 ; t29 + psubsw m13, m6, m8 ; t27a + paddsw m6, m8 ; t28a + mova [tmp1q-32*2], m5 + mova [tmp1q-32*1], m12 + mova [tmp2q+32*0], m6 + mova [tmp2q+32*1], m3 + mova [tmp2q+32*2], m1 + mova m5, [rsp+gprsize+32*0] ; t22 + mova m6, [rsp+gprsize+32*1] ; t23 + mova m3, [rsp+gprsize+32*2] ; t24a + psubsw m1, m14, m5 ; t22a + paddsw m14, m5 ; t17a + psubsw m5, m0, m6 ; t23 + paddsw m0, m6 ; t16 + psubsw m6, m4, m3 ; t24 + paddsw m4, m3 ; t31 + vpbroadcastd m8, [o(pw_m2896_2896)] + vpbroadcastd m3, [o(pw_2896_2896)] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m14 + mova [tmp2q+32*3], m4 + ITX_MULSUB_2W 13, 9, 0, 4, 15, 3, 8 ; t20, t27 + ITX_MULSUB_2W 2, 10, 0, 4, 15, 3, 8 ; t21a, t26a + ITX_MULSUB_2W 7, 1, 0, 4, 15, 3, 8 ; t22, t25 + ITX_MULSUB_2W 6, 5, 0, 4, 15, 3, 8 ; t23a, t24a + mova [tmp1q+32*0], m13 + mova [tmp1q+32*1], m2 + mova [tmp1q+32*2], m7 + mova [tmp1q+32*3], m6 + mova [tmp2q-32*4], m5 + mova [tmp2q-32*3], m1 + mova [tmp2q-32*2], m10 + mova [tmp2q-32*1], m9 + ret +ALIGN function_align +.transpose_2x8x8_round: + punpckhwd m6, m12, m13 + punpcklwd m12, m13 + punpckhwd m13, m8, m9 + punpcklwd m8, m9 + punpckhwd m9, m14, m15 + punpcklwd m14, m15 + punpckhwd m15, m10, m11 + punpcklwd m10, m11 + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5 + punpckhdq m11, m8, m10 + punpckldq m8, m10 + punpckldq m10, m12, m14 + punpckhdq m12, m14 + punpckhdq m14, m13, m15 + punpckldq m13, m15 + punpckldq m15, m6, m9 + punpckhdq m6, m9 + punpckhqdq m9, m8, m10 + punpcklqdq m8, m10 + punpcklqdq m10, m11, m12 + punpckhqdq m11, m12 + punpcklqdq m12, m13, m15 + punpckhqdq m13, m15 + punpckhqdq m15, m14, m6 + punpcklqdq m14, m6 + pmulhrsw m6, m7, [rsp+gprsize+32*0] + REPX {pmulhrsw x, m7}, m8, m9, m10, m11, m12, m13, m14, m15 + pmulhrsw m7, [rsp+gprsize+32*1] + mova [rsp+gprsize+32*0], m15 + punpckhwd m15, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m7 + punpcklwd m6, m7 + punpckhwd m7, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckhdq m6, m5, m7 + punpckldq m5, m7 + punpckldq m7, m15, m1 + punpckhdq m15, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m15 + punpcklqdq m6, m15 + ret +ALIGN function_align +.pass2_end: + mova [rsp+gprsize+32*0], m7 + mova [rsp+gprsize+32*2], m15 + vpbroadcastd m15, [o(pw_2048)] + IDCT32_PASS2_END 0, tmp2q+32*3, 1, 7, 15, strideq*0, r3*4 + IDCT32_PASS2_END 4, tmp2q-32*1, 0, 7, 15, strideq*4, strideq*8 + IDCT32_PASS2_END 8, tmp1q+32*3, 0, 4, 15, strideq*8, strideq*4 + IDCT32_PASS2_END 12, tmp1q-32*1, 0, 4, 15, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + mova m1, [rsp+gprsize+32*1] + IDCT32_PASS2_END 1, tmp2q+32*2, 0, 4, 15, strideq*0, r3*4 + IDCT32_PASS2_END 5, tmp2q-32*2, 0, 4, 15, strideq*4, strideq*8 + IDCT32_PASS2_END 9, tmp1q+32*2, 0, 4, 15, strideq*8, strideq*4 + IDCT32_PASS2_END 13, tmp1q-32*2, 0, 4, 15, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + IDCT32_PASS2_END 2, tmp2q+32*1, 0, 4, 15, strideq*0, r3*4 + IDCT32_PASS2_END 6, tmp2q-32*3, 0, 4, 15, strideq*4, strideq*8 + IDCT32_PASS2_END 10, tmp1q+32*1, 0, 4, 15, strideq*8, strideq*4 + IDCT32_PASS2_END 14, tmp1q-32*3, 0, 4, 15, r3*4, strideq*0 + add dstq, strideq + sub r2, strideq + mova m7, [rsp+gprsize+32*0] + mova m1, [rsp+gprsize+32*2] + IDCT32_PASS2_END 3, tmp2q+32*0, 0, 4, 15, strideq*0, r3*4 + IDCT32_PASS2_END 7, tmp2q-32*4, 0, 4, 15, strideq*4, strideq*8 + IDCT32_PASS2_END 11, tmp1q+32*0, 0, 4, 15, strideq*8, strideq*4 + IDCT32_PASS2_END 1, tmp1q-32*4, 0, 4, 15, r3*4, strideq*0 + ret + +; Perform the final sumsub step and YMM lane shuffling +%macro IDCT32_PASS1_END 4 ; row[1-2], tmp[1-2] + mova m%3, [tmp2q+32*( 3-%1)] + psubsw m%4, m%1, m%3 + paddsw m%1, m%3 + mova m%3, [tmp1q+32*(11-%2)] + mova [tmp1q+32*(11-%2)+16], xm%4 + vextracti128 [tmp2q+32*( 3-%1)+16], m%4, 1 + paddsw m%4, m%2, m%3 + psubsw m%2, m%3 + mova [tmp1q+32*(11-%2)], xm%2 + vextracti128 [tmp2q+32*( 3-%1)], m%2, 1 + vperm2i128 m%2, m%1, m%4, 0x31 + vinserti128 m%1, xm%4, 1 +%endmacro + +cglobal inv_txfm_add_dct_dct_32x16_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 16 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly +.normal: + PROLOGUE 0, 6, 16, 32*19, dst, stride, c, eob, tmp1, tmp2 + vpbroadcastd m15, [o(pw_2896x8)] + pmulhrsw m0, m15, [cq+32* 1] + pmulhrsw m1, m15, [cq+32* 3] + pmulhrsw m2, m15, [cq+32* 5] + pmulhrsw m3, m15, [cq+32* 7] + pmulhrsw m4, m15, [cq+32* 9] + pmulhrsw m5, m15, [cq+32*11] + pmulhrsw m6, m15, [cq+32*13] + pmulhrsw m7, m15, [cq+32*15] + pmulhrsw m8, m15, [cq+32*17] + pmulhrsw m9, m15, [cq+32*19] + pmulhrsw m10, m15, [cq+32*21] + pmulhrsw m11, m15, [cq+32*23] + pmulhrsw m12, m15, [cq+32*25] + pmulhrsw m13, m15, [cq+32*27] + pmulhrsw m14, m15, [cq+32*29] + pmulhrsw m15, [cq+32*31] + lea tmp1q, [rsp+32*7] + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + LOAD_16ROWS cq+32*0, 32*2, 1, 0 + pxor m15, m15 + mov r3d, 8 +.zero_loop: + mova [cq+32*0], m15 + mova [cq+32*1], m15 + mova [cq+32*2], m15 + mova [cq+32*3], m15 + add cq, 32*4 + dec r3d + jg .zero_loop + call m(idct_16x16_internal_8bpc).main + call .pass1_end + lea r2, [strideq*3] + mov r3, dstq +.pass2: + vpbroadcastd m7, [o(pw_16384)] + call m(inv_txfm_add_dct_dct_16x32_8bpc).transpose_2x8x8_round + call m(idct_16x16_internal_8bpc).main + mova [rsp+32*2], m15 + vpbroadcastd m15, [o(pw_2048)] + REPX {pmulhrsw x, m15}, m2, m3, m0 + WRITE_16X2 2, 3, 1, 2, strideq*2, r2 + pmulhrsw m1, m15, [rsp+32*1] + WRITE_16X2 0, 1, 2, 3, strideq*0, strideq*1 + lea dstq, [dstq+strideq*4] + REPX {pmulhrsw x, m15}, m4, m5, m6, m7 + WRITE_16X2 4, 5, 2, 3, strideq*0, strideq*1 + WRITE_16X2 6, 7, 2, 3, strideq*2, r2 + lea dstq, [dstq+strideq*4] + REPX {pmulhrsw x, m15}, m8, m9, m10, m11 + WRITE_16X2 8, 9, 2, 3, strideq*0, strideq*1 + WRITE_16X2 10, 11, 2, 3, strideq*2, r2 + lea dstq, [dstq+strideq*4] + REPX {pmulhrsw x, m15}, m11, m12, m13, m14 + pmulhrsw m15, [rsp+32*2] + WRITE_16X2 12, 13, 2, 3, strideq*0, strideq*1 + WRITE_16X2 14, 15, 2, 3, strideq*2, r2 + test r3, r3 + jnz .right_half + RET +.right_half: + LOAD_8ROWS tmp1q-32*4, 32 + LOAD_8ROWS_H tmp2q-32*4, 32 + lea dstq, [r3+16] + xor r3d, r3d + mova [rsp+32*0], m6 + mova [rsp+32*1], m7 + jmp .pass2 +ALIGN function_align +.pass1_end: + mova [rsp+gprsize+32*0], m9 + IDCT32_PASS1_END 0, 8, 1, 9 + IDCT32_PASS1_END 2, 10, 1, 9 + IDCT32_PASS1_END 3, 11, 1, 9 + IDCT32_PASS1_END 4, 12, 1, 9 + IDCT32_PASS1_END 5, 13, 1, 9 + IDCT32_PASS1_END 6, 14, 1, 9 + IDCT32_PASS1_END 7, 15, 1, 9 + mova m1, [rsp+gprsize+32*1] + mova m9, [rsp+gprsize+32*0] + mova [rsp+gprsize+32*0], m6 + mova [rsp+gprsize+32*1], m7 + IDCT32_PASS1_END 1, 9, 6, 7 + ret + +cglobal inv_txfm_add_identity_identity_16x32_8bpc, 4, 5, 13, dst, stride, c, eob +%undef cmp + lea r6, [o_base] + vpbroadcastd m9, [o(pw_2896x8)] + vpbroadcastd m10, [o(pw_1697x16)] + vpbroadcastd m12, [o(pw_8192)] + cmp eobd, 43 ; if (eob > 43) + setg r4b ; iteration_count++ + cmp eobd, 150 ; if (eob > 150) + setg al ; iteration_count++ + add eobd, -279 ; if (eob > 278) + adc r4b, al ; iteration_count++ + lea r3, [strideq*3] + mov r6, cq + paddw m11, m12, m12 ; pw_16384 +.loop: + mova xm0, [cq+64* 0] + mova xm1, [cq+64* 1] + vinserti128 m0, [cq+64* 8], 1 + vinserti128 m1, [cq+64* 9], 1 + mova xm2, [cq+64* 2] + mova xm3, [cq+64* 3] + vinserti128 m2, [cq+64*10], 1 + vinserti128 m3, [cq+64*11], 1 + mova xm4, [cq+64* 4] + mova xm5, [cq+64* 5] + vinserti128 m4, [cq+64*12], 1 + vinserti128 m5, [cq+64*13], 1 + mova xm6, [cq+64* 6] + mova xm7, [cq+64* 7] + vinserti128 m6, [cq+64*14], 1 + vinserti128 m7, [cq+64*15], 1 + REPX {pmulhrsw x, m9 }, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {IDTX16 x, 8, 10, 11}, 0, 1, 2, 3, 4, 5, 6, 7 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + REPX {pmulhrsw x, m12}, m0, m1, m2, m3, m4, m5, m6, m7 + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + add cq, 16 + dec r4b + jge .loop + sub cq, 32 + pxor m0, m0 + mov r0d, 8 + cmp cq, r6 + ja .zero_loop +.zero_loop_half: + mova [r6+64*0], m0 + mova [r6+64*1], m0 + add r6, 64*4 + mova [r6-64*2], m0 + mova [r6-64*1], m0 + sub r0d, 2 + jg .zero_loop_half + RET +.zero_loop: + mova [r6+32*0], m0 + mova [r6+32*1], m0 + mova [r6+32*2], m0 + mova [r6+32*3], m0 + add r6, 32*4 + dec r0d + jg .zero_loop + RET + +cglobal inv_txfm_add_identity_identity_32x16_8bpc, 4, 6, 12, dst, stride, c, eob +%undef cmp + lea r6, [o_base] + vpbroadcastd m9, [o(pw_2896x8)] + vpbroadcastd m10, [o(pw_1697x16)] + vpbroadcastd m11, [o(pw_2048)] + cmp eobd, 35 ; if (eob > 35) + setg r4b ; iteration_count++ + cmp eobd, 150 ; if (eob > 150) + setg r3b ; iteration_count += 2 + lea r4d, [r4+r3*2] + lea r3, [strideq*3] + mov r5, dstq + mov r6, cq +.loop: + mova xm0, [cq+32* 0] + mova xm1, [cq+32* 1] + vinserti128 m0, [cq+32* 8], 1 + vinserti128 m1, [cq+32* 9], 1 + mova xm2, [cq+32* 2] + mova xm3, [cq+32* 3] + vinserti128 m2, [cq+32*10], 1 + vinserti128 m3, [cq+32*11], 1 + mova xm4, [cq+32* 4] + mova xm5, [cq+32* 5] + vinserti128 m4, [cq+32*12], 1 + vinserti128 m5, [cq+32*13], 1 + mova xm6, [cq+32* 6] + mova xm7, [cq+32* 7] + vinserti128 m6, [cq+32*14], 1 + vinserti128 m7, [cq+32*15], 1 + REPX {pmulhrsw x, m9 }, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {paddsw x, x }, m0, m1, m2, m3, m4, m5, m6, m7 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + REPX {IDTX16 x, 8, 10}, 0, 1, 2, 3, 4, 5, 6, 7 + REPX {pmulhrsw x, m11}, m0, m1, m2, m3, m4, m5, m6, m7 + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r3 + lea dstq, [dstq+strideq*4] + add cq, 16 + dec r4b + jl .ret + test r4b, 1 + jz .loop + add cq, 32*15 + lea dstq, [r5+16] + jmp .loop +.ret: + sub cd, eax + pxor m0, m0 + add cd, 384 +.zero_loop: + mova [r6+32*0], m0 + mova [r6+32*1], m0 + mova [r6+32*2], m0 + mova [r6+32*3], m0 + add r6, 32*4 + sub cd, 128 + jge .zero_loop + RET + +cglobal inv_txfm_add_dct_dct_32x32_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly +.normal: + PROLOGUE 0, 9, 16, 32*67, dst, stride, c, eob, tmp1, tmp2, \ + base, tmp3, tmp4 + %undef cmp + lea tmp1q, [rsp+32*7] + lea tmp2q, [tmp1q+32*8] + sub eobd, 136 + mov tmp4d, eobd +.pass1_loop: + LOAD_8ROWS cq+64*1, 64*2 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 1, 3, 5, 7, 9, 11, 13, 15 + test tmp4d, tmp4d + jl .fast + LOAD_8ROWS_H cq+64*17, 64*2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + LOAD_8ROWS_H cq+64*16, 64*2 + pxor m0, m0 + REPX {mova [cq+64*x], m0}, 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + mova [rsp], m15 + jmp .idct16 +.fast: + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 +.idct16: + LOAD_8ROWS cq+64*0, 64*2 + pxor m15, m15 + REPX {mova [cq+64*x], m15}, 0, 2, 4, 6, 8, 10, 12, 14 + call m(idct_16x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_32x16_8bpc).pass1_end + vpbroadcastd m7, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_16x32_8bpc).transpose_2x8x8_round + lea tmp3q, [tmp1q+32*32] + mova m15, [rsp] + mova [tmp3q-32*4], m0 + mova [tmp3q-32*3], m2 + mova [tmp3q-32*2], m4 + mova [tmp3q-32*1], m6 + mova [tmp3q+32*0], m8 + mova [tmp3q+32*1], m10 + mova [tmp3q+32*2], m12 + mova [tmp3q+32*3], m14 + add tmp3q, 32*8 + mova [tmp3q-32*4], m1 + mova [tmp3q-32*3], m3 + mova [tmp3q-32*2], m5 + mova [tmp3q-32*1], m7 + mova [tmp3q+32*0], m9 + mova [tmp3q+32*1], m11 + mova [tmp3q+32*2], m13 + mova [tmp3q+32*3], m15 + vpbroadcastd m9, [o(pw_8192)] + pmulhrsw m0, m9, [tmp1q-32*4] + pmulhrsw m1, m9, [tmp1q-32*3] + pmulhrsw m2, m9, [tmp1q-32*2] + pmulhrsw m3, m9, [tmp1q-32*1] + pmulhrsw m4, m9, [tmp1q+32*0] + pmulhrsw m5, m9, [tmp1q+32*1] + pmulhrsw m6, m9, [tmp1q+32*2] + pmulhrsw m7, m9, [tmp1q+32*3] + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova [tmp1q-32*4], m0 + pmulhrsw m0, m9, [tmp2q-32*4] + mova [tmp2q-32*4], m1 + pmulhrsw m1, m9, [tmp2q-32*3] + mova [tmp1q-32*3], m2 + pmulhrsw m2, m9, [tmp2q-32*2] + mova [tmp2q-32*3], m3 + pmulhrsw m3, m9, [tmp2q-32*1] + mova [tmp1q-32*2], m4 + pmulhrsw m4, m9, [tmp2q+32*0] + mova [tmp2q-32*2], m5 + pmulhrsw m5, m9, [tmp2q+32*1] + mova [tmp1q-32*1], m6 + pmulhrsw m6, m9, [tmp2q+32*2] + mova [tmp2q-32*1], m7 + pmulhrsw m7, m9, [tmp2q+32*3] + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova [tmp1q+32*0], m0 + mova [tmp2q+32*0], m1 + mova [tmp1q+32*1], m2 + mova [tmp2q+32*1], m3 + mova [tmp1q+32*2], m4 + mova [tmp2q+32*2], m5 + mova [tmp1q+32*3], m6 + mova [tmp2q+32*3], m7 + add cq, 32 + add tmp1q, 32*16 + add tmp2q, 32*16 + add eobd, 0x80000000 + jnc .pass1_loop + add tmp1q, 32*24 + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq + test tmp4d, tmp4d + jge .pass2_loop + add tmp1q, 32*16 + add tmp2q, 32*16 + add tmp3q, 32*16 +.pass2_loop: + LOAD_8ROWS tmp2q-32*4, 32 + test tmp4d, tmp4d + jl .fast2 + LOAD_8ROWS_H tmp3q-32*4, 32 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + sub tmp3q, 32*8 + LOAD_8ROWS_H tmp3q-32*4, 32 + sub tmp3q, 32*16 + jmp .pass2_loop_end +.fast2: + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + sub tmp3q, 32*24 + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14, m15 +.pass2_loop_end: + LOAD_8ROWS tmp3q-32*4, 32 + mova [rsp], m15 + call m(idct_16x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_16x32_8bpc).pass2_end + lea tmp3q, [tmp1q-32*32] + cmp tmp2q, tmp3q + jb .ret + sub tmp2q, 32*32 + sub dstq, r3 + lea r2, [r2+r3+16] + add dstq, 16 + jmp .pass2_loop +.ret: + RET + +cglobal inv_txfm_add_identity_identity_32x32_8bpc, 4, 6, 10, dst, stride, c, eob + %undef cmp + vpbroadcastd m9, [pw_8192] + sub eobd, 136 ; if (eob < 136) + shr eobd, 30 ; topleft 16x16 only + lea eobd, [eobq*2-8] + lea r4, [strideq*3] + mov r5, dstq + lea r6, [cq+32] +.loop: + mova xm0, [cq+64* 0] + mova xm1, [cq+64* 1] + vinserti128 m0, [cq+64* 8], 1 + vinserti128 m1, [cq+64* 9], 1 + mova xm2, [cq+64* 2] + mova xm3, [cq+64* 3] + vinserti128 m2, [cq+64*10], 1 + vinserti128 m3, [cq+64*11], 1 + mova xm4, [cq+64* 4] + mova xm5, [cq+64* 5] + vinserti128 m4, [cq+64*12], 1 + vinserti128 m5, [cq+64*13], 1 + mova xm6, [cq+64* 6] + mova xm7, [cq+64* 7] + vinserti128 m6, [cq+64*14], 1 + vinserti128 m7, [cq+64*15], 1 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + REPX {pmulhrsw x, m9}, m0, m1, m2, m3, m4, m5, m6, m7 + WRITE_16X2 0, 1, 8, 0, strideq*0, strideq*1 + WRITE_16X2 2, 3, 0, 1, strideq*2, r4 + lea dstq, [dstq+strideq*4] + WRITE_16X2 4, 5, 0, 1, strideq*0, strideq*1 + WRITE_16X2 6, 7, 0, 1, strideq*2, r4 + lea dstq, [dstq+strideq*4] + add cq, 16 + inc eobd + jz .ret + test eobd, 3 + jnz .loop + add cq, 64*15 + lea dstq, [r5+16] + jmp .loop +.ret: + pxor m0, m0 + mov r0d, 16 + cmp cq, r6 + jne .zero_loop +.zero_loop_topleft: + mova [r6-32*1], m0 + mova [r6+32*1], m0 + mova [r6+32*3], m0 + mova [r6+32*5], m0 + add r6, 64*4 + sub r0d, 4 + jg .zero_loop_topleft + RET +.zero_loop: + mova [r6-32*1], m0 + mova [r6+32*0], m0 + mova [r6+32*1], m0 + mova [r6+32*2], m0 + add r6, 32*4 + dec r0d + jg .zero_loop + RET + +%macro IDCT64_PART2_END 6-10 ; out, src[1-2], tmp[1-3], (offset[1-4]) +%if %1 & 1 + mova m%5, [tmp2q-32*(51-%1)] ; idct16 out 0+n + mova m%4, [tmp1q-32*(14+%1)] ; idct32 out31-n +%else + mova m%5, [tmp1q-32*(45-%1)] + mova m%4, [tmp2q-32*(20+%1)] +%endif + psubsw m%6, m%5, m%4 ; idct32 out31-n + paddsw m%5, m%4 ; idct32 out 0+n + psubsw m%4, m%6, m%3 ; out32+n + paddsw m%6, m%3 ; out31-n + psubsw m%3, m%5, m%2 ; out63-n + paddsw m%5, m%2 ; out 0+n +%if %0 == 6 ; pass 1 +%if %1 & 1 + mova [tmp2q-32*(19-%1)], m%4 + mova [tmp1q-32*(14+%1)], m%6 + mova [tmp1q+32*(18-%1)], m%3 + mova [tmp2q-32*(51-%1)], m%5 +%else + mova [tmp1q-32*(13-%1)], m%4 + mova [tmp2q-32*(20+%1)], m%6 + mova [tmp2q+32*(12-%1)], m%3 + mova [tmp1q-32*(45-%1)], m%5 +%endif +%else ; pass 2 + REPX {pmulhrsw x, m14}, m%4, m%6, m%3, m%5 +%if %1 & 1 + %define %%d0 r2 + %define %%d1 dstq +%else + %define %%d0 dstq + %define %%d1 r2 +%endif + pmovzxbw m%2, [%%d0+%9 ] + paddw m%2, m%4 + pmovzxbw m%4, [%%d1+%8 ] + paddw m%4, m%6 + pmovzxbw m%6, [%%d1+%10] + paddw m%3, m%6 + pmovzxbw m%6, [%%d0+%7 ] + paddw m%5, m%6 + packuswb m%2, m%4 + packuswb m%3, m%5 + vpermq m%2, m%2, q3120 + vpermq m%3, m%3, q3120 + mova [%%d0+%9 ], xm%2 + vextracti128 [%%d1+%8 ], m%2, 1 + mova [%%d1+%10], xm%3 + vextracti128 [%%d0+%7 ], m%3, 1 +%endif +%endmacro + +cglobal inv_txfm_add_dct_dct_16x64_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +.normal: + PROLOGUE 0, 10, 16, 32*67, dst, stride, c, eob, tmp1, tmp2 + %undef cmp + lea tmp1q, [rsp+32*23] + lea tmp2q, [tmp1q+32*24] + sub eobd, 151 + mov r7d, eobd +.pass1_loop: + LOAD_16ROWS cq, 64 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [rsp+32*0], m6 + mova [rsp+32*1], m7 + vpbroadcastd m7, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_16x32_8bpc).transpose_2x8x8_round + mova m15, [rsp+32*0] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m2 + mova [tmp1q-32*2], m4 + mova [tmp1q-32*1], m6 + mova [tmp1q+32*0], m8 + mova [tmp1q+32*1], m10 + mova [tmp1q+32*2], m12 + mova [tmp1q+32*3], m14 + mova [tmp2q-32*4], m1 + mova [tmp2q-32*3], m3 + mova [tmp2q-32*2], m5 + mova [tmp2q-32*1], m7 + mova [tmp2q+32*0], m9 + mova [tmp2q+32*1], m11 + mova [tmp2q+32*2], m13 + mova [tmp2q+32*3], m15 + add cq, 32 + add tmp1q, 32*8 + add tmp2q, 32*8 + add eobd, 0x80000000 + jnc .pass1_loop + lea r2, [rsp+32*23] + mova xm0, [r2-32*4+ 0] + mova xm1, [r2-32*2+ 0] + vinserti128 m0, [r2+32*0+ 0], 1 + vinserti128 m1, [r2+32*2+ 0], 1 + mova xm2, [r2-32*4+16] + mova xm3, [r2-32*2+16] + vinserti128 m2, [r2+32*0+16], 1 + vinserti128 m3, [r2+32*2+16], 1 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14 + test r7d, r7d + jl .fast + lea r3, [r2+32*8] + mova xm4, [r3-32*4+ 0] + mova xm5, [r3-32*2+ 0] + vinserti128 m4, [r3+32*0+ 0], 1 + vinserti128 m5, [r3+32*2+ 0], 1 + mova xm6, [r3-32*4+16] + mova xm7, [r3-32*2+16] + vinserti128 m6, [r3+32*0+16], 1 + vinserti128 m7, [r3+32*2+16], 1 +.fast: + mova [rsp], m8 + lea tmp1q, [rsp+32*7] + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + mova xm0, [r2-32*3+ 0] + mova xm1, [r2-32*1+ 0] + vinserti128 m0, [r2+32*1+ 0], 1 + vinserti128 m1, [r2+32*3+ 0], 1 + mova xm2, [r2-32*3+16] + mova xm3, [r2-32*1+16] + vinserti128 m2, [r2+32*1+16], 1 + vinserti128 m3, [r2+32*3+16], 1 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + test r7d, r7d + jl .fast2 + mova xm4, [r3-32*3+ 0] + mova xm5, [r3-32*1+ 0] + vinserti128 m4, [r3+32*1+ 0], 1 + vinserti128 m5, [r3+32*3+ 0], 1 + mova xm6, [r3-32*3+16] + mova xm7, [r3-32*1+16] + vinserti128 m6, [r3+32*1+16], 1 + vinserti128 m7, [r3+32*3+16], 1 +.fast2: + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + add r2, 32*24 + vpbroadcastd m15, [o(pd_2048)] + add tmp1q, 32*16 + add tmp2q, 32*32 + mova xm0, [r2-32*4+ 0] + mova xm3, [r2-32*1+16] + vinserti128 m0, [r2+32*0+ 0], 1 + vinserti128 m3, [r2+32*3+16], 1 + mova xm4, [r2-32*4+16] + mova xm7, [r2-32*1+ 0] + vinserti128 m4, [r2+32*0+16], 1 + vinserti128 m7, [r2+32*3+ 0], 1 + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r7d, r7d + jl .fast3 + add r3, 32*24 + mova xm1, [r3-32*1+16] + mova xm2, [r3-32*4+ 0] + vinserti128 m1, [r3+32*3+16], 1 + vinserti128 m2, [r3+32*0+ 0], 1 + mova xm5, [r3-32*1+ 0] + mova xm6, [r3-32*4+16] + vinserti128 m5, [r3+32*3+ 0], 1 + vinserti128 m6, [r3+32*0+16], 1 +.fast3: + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + mova xm0, [r2-32*2+ 0] + mova xm3, [r2-32*3+16] + vinserti128 m0, [r2+32*2+ 0], 1 + vinserti128 m3, [r2+32*1+16], 1 + mova xm4, [r2-32*2+16] + mova xm7, [r2-32*3+ 0] + vinserti128 m4, [r2+32*2+16], 1 + vinserti128 m7, [r2+32*1+ 0], 1 + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r7d, r7d + jl .fast4 + mova xm1, [r3-32*3+16] + mova xm2, [r3-32*2+ 0] + vinserti128 m1, [r3+32*1+16], 1 + vinserti128 m2, [r3+32*2+ 0], 1 + mova xm5, [r3-32*3+ 0] + mova xm6, [r3-32*2+16] + vinserti128 m5, [r3+32*1+ 0], 1 + vinserti128 m6, [r3+32*2+16], 1 +.fast4: + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass2 + RET +ALIGN function_align +%define o_base idct64_mul - 8 +cglobal_label .main_part1 + ; idct64 steps 1-5: + ; in1/31/17/15/ 9/23/25/ 7 -> + ; t32a/33/34a/35/36/37a/38/39a/56a/57/58a/59/60/61a/62/63a + ; in5/27/21/11/13/19/29/ 3 -> + ; t40a/41/42a/43/44/45a/46/47a/48a/49/50a/51/52/53a/54/55a + vpbroadcastd m11, [o(idct64_mul+4* 0)] + vpbroadcastd m13, [o(idct64_mul+4* 1)] + vpbroadcastd m10, [o(idct64_mul+4* 4)] + vpbroadcastd m12, [o(idct64_mul+4* 5)] + pmulhrsw m11, m0 ; t63a + pmulhrsw m0, m13 ; t32a + pmulhrsw m10, m1 ; t62a + pmulhrsw m1, m12 ; t33a + vpbroadcastd m9, [o(idct64_mul+4* 8)] + vpbroadcastd m13, [o(idct64_mul+4* 9)] + vpbroadcastd m8, [o(idct64_mul+4*12)] + vpbroadcastd m12, [o(idct64_mul+4*13)] + pmulhrsw m9, m2 ; t61a + pmulhrsw m2, m13 ; t34a + pmulhrsw m8, m3 ; t60a + pmulhrsw m3, m12 ; t35a + psubsw m12, m0, m1 ; t33 + paddsw m0, m1 ; t32 + psubsw m1, m3, m2 ; t34 + paddsw m3, m2 ; t35 + psubsw m2, m8, m9 ; t61 + paddsw m8, m9 ; t60 + psubsw m9, m11, m10 ; t62 + paddsw m11, m10 ; t63 + ITX_MULSUB_2W 2, 1, 10, 13, 15, m4076, 401 ; t34a, t61a + vpbroadcastd m14, [o(pw_401_4076)] + ITX_MULSUB_2W 9, 12, 10, 13, 15, 14, 13 ; t33a, t62a + psubsw m10, m0, m3 ; t35a + paddsw m0, m3 ; t32a + psubsw m3, m11, m8 ; t60a + paddsw m11, m8 ; t63a + psubsw m8, m9, m2 ; t34 + paddsw m9, m2 ; t33 + psubsw m2, m12, m1 ; t61 + paddsw m12, m1 ; t62 + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m9 + mova [tmp2q+32*2], m12 + mova [tmp2q+32*3], m11 + vpbroadcastd m13, [o(pw_m4017_799)] + vpbroadcastd m14, [o(pw_799_4017)] + ITX_MULSUB_2W 2, 8, 0, 1, 15, 14, 13 ; t34a, t61a + ITX_MULSUB_2W 3, 10, 0, 1, 15, 14, 13 ; t35, t60 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp2q+32*0], m10 + mova [tmp2q+32*1], m8 + vpbroadcastd m3, [o(idct64_mul+4*16)] + vpbroadcastd m11, [o(idct64_mul+4*17)] + vpbroadcastd m2, [o(idct64_mul+4*20)] + vpbroadcastd m10, [o(idct64_mul+4*21)] + vpbroadcastd m1, [o(idct64_mul+4*24)] + vpbroadcastd m9, [o(idct64_mul+4*25)] + vpbroadcastd m0, [o(idct64_mul+4*28)] + vpbroadcastd m8, [o(idct64_mul+4*29)] + pmulhrsw m3, m4 ; t59a + pmulhrsw m4, m11 ; t36a + pmulhrsw m2, m5 ; t58a + pmulhrsw m5, m10 ; t37a + pmulhrsw m1, m6 ; t57a + pmulhrsw m6, m9 ; t38a + pmulhrsw m0, m7 ; t56a + pmulhrsw m7, m8 ; t39a + psubsw m8, m4, m5 ; t37 + paddsw m4, m5 ; t36 + psubsw m5, m7, m6 ; t38 + paddsw m7, m6 ; t39 + psubsw m6, m0, m1 ; t57 + paddsw m0, m1 ; t56 + psubsw m1, m3, m2 ; t58 + paddsw m3, m2 ; t59 + ITX_MULSUB_2W 6, 5, 2, 9, 15, m2598, 3166 ; t38a, t57a + vpbroadcastd m10, [o(pw_3166_2598)] + ITX_MULSUB_2W 1, 8, 2, 9, 15, 10, 9 ; t37a, t58a + psubsw m2, m7, m4 ; t36a + paddsw m7, m4 ; t39a + psubsw m4, m0, m3 ; t59a + paddsw m0, m3 ; t56a + psubsw m3, m6, m1 ; t37 + paddsw m6, m1 ; t38 + psubsw m1, m5, m8 ; t58 + paddsw m5, m8 ; t57 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + mova [tmp2q-32*4], m0 + mova [tmp2q-32*3], m5 + vpbroadcastd m6, [o(pw_m799_m4017)] + vpbroadcastd m7, [o(pw_m4017_799)] + ITX_MULSUB_2W 4, 2, 0, 5, 15, 7, 6 ; t36, t59 + ITX_MULSUB_2W 1, 3, 0, 5, 15, 7, 6 ; t37a, t58a + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m1 + mova [tmp2q-32*2], m3 + mova [tmp2q-32*1], m2 + ret +%define o_base pw_5 + 128 +.main_part2_pass1: ; idct64 steps 6-9 + idct16/32/64 sumsub + sub r6, o_idct64_offset + 8 + vpbroadcastd m11, [o(pw_1567_3784)] + vpbroadcastd m12, [o(pw_m3784_1567)] + vpbroadcastd m13, [o(pw_2896_2896)] + vpbroadcastd m14, [o(pw_m2896_2896)] +.main_part2_pass1_loop: + call .main_part2_internal + IDCT64_PART2_END 0, 7, 0, 6, 9, 10 + IDCT64_PART2_END 7, 8, 5, 0, 6, 7 + IDCT64_PART2_END 8, 2, 1, 0, 6, 7 + IDCT64_PART2_END 15, 3, 4, 0, 6, 7 + cmp tmp1q, tmp2q + jne .main_part2_pass1_loop + ret +cglobal_label .main_part2_internal + mova m0, [tmp1q-32*12] ; t32a + mova m6, [tmp2q-32*13] ; t39a + mova m1, [tmp1q-32* 4] ; t40a + mova m5, [tmp2q+32* 3] ; t55a + add tmp1q, 32 + sub tmp2q, 32 + mova m2, [tmp1q+32* 3] ; t48a + mova m4, [tmp2q-32* 4] ; t47a + mova m3, [tmp1q+32*11] ; t56a + mova m7, [tmp2q+32*12] ; t63a + psubsw m8, m0, m6 ; t39 + paddsw m0, m6 ; t32 + psubsw m6, m4, m1 ; t40 + paddsw m4, m1 ; t47 + psubsw m1, m2, m5 ; t55 + paddsw m2, m5 ; t48 + psubsw m5, m7, m3 ; t56 + paddsw m7, m3 ; t63 + ITX_MULSUB_2W 5, 8, 3, 9, 15, 11, 12 ; t39a, t56a + vpbroadcastd m9, [o(pw_m1567_m3784)] + ITX_MULSUB_2W 1, 6, 3, 9, 15, 12, 9 ; t40a, t55a + psubsw m3, m0, m4 ; t47a + paddsw m0, m4 ; t32a + psubsw m4, m7, m2 ; t48a + paddsw m7, m2 ; t63a + psubsw m2, m5, m1 ; t40 + paddsw m5, m1 ; t39 + psubsw m1, m8, m6 ; t55 + paddsw m8, m6 ; t56 + ITX_MULSUB_2W 4, 3, 6, 9, 15, 13, 14 ; t47, t48 + ITX_MULSUB_2W 1, 2, 6, 9, 15, 13, 14 ; t40a, t55a + ret +.main_part2_pass2: + sub r6, o_idct64_offset + 8 + vpbroadcastd m11, [o(pw_1567_3784)] + vpbroadcastd m12, [o(pw_m3784_1567)] + vpbroadcastd m13, [o(pw_2896_2896)] + lea r9, [strideq*5] ; stride*5 + lea r3, [r9+strideq*1] ; stride*6 + lea r7, [r9+strideq*2] ; stride*7 + lea r8, [r3+strideq*2] ; stride*8 + lea r2, [dstq+r7] +.main_part2_pass2_loop: + vpbroadcastd m14, [o(pw_m2896_2896)] + call .main_part2_internal + vpbroadcastd m14, [o(pw_2048)] + IDCT64_PART2_END 0, 7, 0, 6, 9, 10, strideq*0, r3*4, r8*4, r7*8 + IDCT64_PART2_END 7, 8, 5, 0, 6, 7, strideq*0, r3*4, r8*4, r7*8 + IDCT64_PART2_END 8, 2, 1, 0, 6, 7, strideq*8, r8*2, r9*8, r3*8 + IDCT64_PART2_END 15, 3, 4, 0, 6, 7, strideq*8, r8*2, r9*8, r3*8 + add dstq, strideq + sub r2, strideq + cmp tmp1q, tmp2q + jne .main_part2_pass2_loop + ret + +cglobal inv_txfm_add_dct_dct_64x16_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 16 +.dconly: + pmulhrsw xm0, xm2 + movd xm2, [o(pw_2048)] + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 + pxor m1, m1 +.dconly_loop: + mova m2, [dstq+32*0] + mova m3, [dstq+32*1] + punpckhbw m4, m2, m1 + punpcklbw m2, m1 + punpckhbw m5, m3, m1 + punpcklbw m3, m1 + paddw m4, m0 + paddw m2, m0 + paddw m5, m0 + paddw m3, m0 + packuswb m2, m4 + packuswb m3, m5 + mova [dstq+32*0], m2 + mova [dstq+32*1], m3 + add dstq, strideq + dec r3d + jg .dconly_loop + RET +.normal: + PROLOGUE 0, 7, 16, 32*67, dst, stride, c, eob, tmp1, tmp2 + LOAD_8ROWS cq+32*0, 32*4 + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 0, 4, 8, 12, 16, 20, 24, 28 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + lea tmp1q, [rsp+32*7] + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + LOAD_8ROWS cq+32*2, 32*4 + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 2, 6, 10, 14, 18, 22, 26, 30 + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m15, [o(pd_2048)] + add tmp1q, 32*16 + add tmp2q, 32*32 + mova m0, [cq+32* 1] + mova m1, [cq+32*31] + mova m2, [cq+32*17] + mova m3, [cq+32*15] + mova m4, [cq+32* 9] + mova m5, [cq+32*23] + mova m6, [cq+32*25] + mova m7, [cq+32* 7] + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 1, 31, 17, 15, 9, 23, 25, 7 + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + mova m0, [cq+32* 5] + mova m1, [cq+32*27] + mova m2, [cq+32*21] + mova m3, [cq+32*11] + mova m4, [cq+32*13] + mova m5, [cq+32*19] + mova m6, [cq+32*29] + mova m7, [cq+32* 3] + pxor m8, m8 + REPX {mova [cq+32*x], m8}, 5, 27, 21, 11, 13, 19, 29, 3 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass1 + sub tmp1q, 32*36 + lea r2, [strideq*3] + mov tmp2d, 4 +.pass2_loop: + lea r3, [tmp1q-32*8] + mova xm0, [r3 -32*4] + mova xm1, [r3 -32*3] + vinserti128 m0, [tmp1q-32*4], 1 + vinserti128 m1, [tmp1q-32*3], 1 + mova xm2, [r3 -32*2] + mova xm3, [r3 -32*1] + vinserti128 m2, [tmp1q-32*2], 1 + vinserti128 m3, [tmp1q-32*1], 1 + mova xm4, [r3 +32*0] + mova xm5, [r3 +32*1] + vinserti128 m4, [tmp1q+32*0], 1 + vinserti128 m5, [tmp1q+32*1], 1 + mova xm6, [r3 +32*2] + mova xm7, [r3 +32*3] + vinserti128 m6, [tmp1q+32*2], 1 + vinserti128 m7, [tmp1q+32*3], 1 + mova xm8, [r3 -32*4+16] + mova xm9, [r3 -32*3+16] + vinserti128 m8, [tmp1q-32*4+16], 1 + vinserti128 m9, [tmp1q-32*3+16], 1 + mova xm10, [r3 -32*2+16] + mova xm11, [r3 -32*1+16] + vinserti128 m10, [tmp1q-32*2+16], 1 + vinserti128 m11, [tmp1q-32*1+16], 1 + mova xm12, [r3 +32*0+16] + mova xm13, [r3 +32*1+16] + vinserti128 m12, [tmp1q+32*0+16], 1 + vinserti128 m13, [tmp1q+32*1+16], 1 + mova xm14, [r3 +32*2+16] + mova xm15, [r3 +32*3+16] + vinserti128 m14, [tmp1q+32*2+16], 1 + vinserti128 m15, [tmp1q+32*3+16], 1 + mova [rsp+32*0], m6 + mova [rsp+32*1], m7 + vpbroadcastd m7, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_16x32_8bpc).transpose_2x8x8_round + call m(idct_16x16_internal_8bpc).main + mova [rsp+32*0], m15 + vpbroadcastd m15, [o(pw_2048)] + REPX {pmulhrsw x, m15}, m0, m2, m3, m4, m5, m6, m7 + WRITE_16X2 2, 3, 1, 2, strideq*2, r2 + pmulhrsw m1, m15, [rsp+32*1] + WRITE_16X2 0, 1, 2, 3, strideq*0, strideq*1 + lea r3, [dstq+strideq*4] + %define dstq r3 + WRITE_16X2 4, 5, 2, 3, strideq*0, strideq*1 + WRITE_16X2 6, 7, 2, 3, strideq*2, r2 + REPX {pmulhrsw x, m15}, m8, m9, m10, m11, m12, m13, m14 + lea r3, [r3+strideq*4] + WRITE_16X2 8, 9, 2, 3, strideq*0, strideq*1 + WRITE_16X2 10, 11, 2, 3, strideq*2, r2 + pmulhrsw m15, [rsp+32*0] + lea r3, [r3+strideq*4] + WRITE_16X2 12, 13, 2, 3, strideq*0, strideq*1 + WRITE_16X2 14, 15, 2, 3, strideq*2, r2 + add tmp1q, 32*16 + add r0, 16 + dec tmp2d + jg .pass2_loop + RET + +cglobal inv_txfm_add_dct_dct_32x64_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly +.normal: + PROLOGUE 0, 11, 16, 32*99, dst, stride, c, eob, tmp1, tmp2 + lea tmp1q, [rsp+32*7] + lea r10d, [eobq-136] + sar r10d, 31 +.pass1_loop: + lea tmp2q, [tmp1q+32*16] + LOAD_8ROWS cq+64*1, 64*2, 1 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 1, 3, 5, 7, 9, 11, 13, 15 + test r10b, r10b + jnz .fast + LOAD_8ROWS_H cq+64*17, 64*2, 2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + LOAD_8ROWS_H cq+64*16, 64*2, 1 + mova [rsp], m15 + pxor m15, m15 + REPX {mova [cq+64*x], m15}, 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + jmp .idct16 +.fast: + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 +.idct16: + LOAD_8ROWS cq+64*0, 64*2, 1 + pxor m15, m15 + REPX {mova [cq+64*x], m15}, 0, 2, 4, 6, 8, 10, 12, 14 + call m(idct_16x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_32x16_8bpc).pass1_end + vpbroadcastd m7, [o(pw_16384)] + call m(inv_txfm_add_dct_dct_16x32_8bpc).transpose_2x8x8_round + lea r3, [tmp1q+32*48] + mova m15, [rsp] + mova [r3-32*4], m0 + mova [r3-32*3], m2 + mova [r3-32*2], m4 + mova [r3-32*1], m6 + mova [r3+32*0], m8 + mova [r3+32*1], m10 + mova [r3+32*2], m12 + mova [r3+32*3], m14 + add r3, 32*24 + mova [r3-32*4], m1 + mova [r3-32*3], m3 + mova [r3-32*2], m5 + mova [r3-32*1], m7 + mova [r3+32*0], m9 + mova [r3+32*1], m11 + mova [r3+32*2], m13 + mova [r3+32*3], m15 + vpbroadcastd m9, [o(pw_16384)] + pmulhrsw m0, m9, [tmp1q-32*4] + pmulhrsw m1, m9, [tmp1q-32*3] + pmulhrsw m2, m9, [tmp1q-32*2] + pmulhrsw m3, m9, [tmp1q-32*1] + pmulhrsw m4, m9, [tmp1q+32*0] + pmulhrsw m5, m9, [tmp1q+32*1] + pmulhrsw m6, m9, [tmp1q+32*2] + pmulhrsw m7, m9, [tmp1q+32*3] + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova [tmp1q-32*4], m0 + pmulhrsw m0, m9, [tmp2q-32*4] + mova [tmp2q-32*4], m1 + pmulhrsw m1, m9, [tmp2q-32*3] + mova [tmp1q-32*3], m2 + pmulhrsw m2, m9, [tmp2q-32*2] + mova [tmp2q-32*3], m3 + pmulhrsw m3, m9, [tmp2q-32*1] + mova [tmp1q-32*2], m4 + pmulhrsw m4, m9, [tmp2q+32*0] + mova [tmp2q-32*2], m5 + pmulhrsw m5, m9, [tmp2q+32*1] + mova [tmp1q-32*1], m6 + pmulhrsw m6, m9, [tmp2q+32*2] + mova [tmp2q-32*1], m7 + pmulhrsw m7, m9, [tmp2q+32*3] + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova [tmp1q+32*0], m0 + mova [tmp2q+32*0], m1 + mova [tmp1q+32*1], m2 + mova [tmp2q+32*1], m3 + mova [tmp1q+32*2], m4 + mova [tmp2q+32*2], m5 + mova [tmp1q+32*3], m6 + mova [tmp2q+32*3], m7 + add cq, 32 + add tmp1q, 32*8 + add r10d, 0x80000000 + jnc .pass1_loop + lea r2, [rsp+32*55] + lea r7, [r2+32*24] +.pass2_loop: + lea r3, [r2+32*8] + lea r8, [r7+32*8] + mova m0, [r2-32*4] + mova m1, [r2-32*2] + mova m2, [r2+32*0] + mova m3, [r2+32*2] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14 + test r10b, r10b + jnz .fast2 + mova m4, [r3-32*4] + mova m5, [r3-32*2] + mova m6, [r3+32*0] + mova m7, [r3+32*2] +.fast2: + mova [rsp], m8 + lea tmp1q, [rsp+32*39] + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + mova m0, [r2-32*3] + mova m1, [r2-32*1] + mova m2, [r2+32*1] + mova m3, [r2+32*3] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + test r10b, r10b + jnz .fast3 + mova m4, [r3-32*3] + mova m5, [r3-32*1] + mova m6, [r3+32*1] + mova m7, [r3+32*3] +.fast3: + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m15, [o(pd_2048)] + add tmp1q, 32*16 + add tmp2q, 32*32 + mova m0, [r7-32*4] + mova m3, [r7+32*3] + mova m4, [r7+32*0] + mova m7, [r7-32*1] + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r10b, r10b + jnz .fast4 + mova m1, [r8+32*3] + mova m2, [r8-32*4] + mova m5, [r8-32*1] + mova m6, [r8+32*0] +.fast4: + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + mova m0, [r7-32*2] + mova m3, [r7+32*1] + mova m4, [r7+32*2] + mova m7, [r7-32*3] + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r10b, r10b + jnz .fast5 + mova m1, [r8+32*1] + mova m2, [r8-32*2] + mova m5, [r8-32*3] + mova m6, [r8+32*2] +.fast5: + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass2 + add r10d, 0x80000000 + jc .ret + lea r2, [rsp+32*7] + lea r7, [r2+32*16] + sub dstq, r8 + lea dstq, [dstq+strideq*4+16] + jmp .pass2_loop +.ret: + RET + +cglobal inv_txfm_add_dct_dct_64x32_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_16384)] + mov [cq], eobd + pmulhrsw xm0, xm1 + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).dconly +.normal: + PROLOGUE 0, 9, 16, 32*131, dst, stride, c, eob, tmp1, tmp2, \ + base, tmp3, tmp4 + lea tmp1q, [rsp+32*7] + lea tmp4d, [eobq-136] +.pass1_loop: + LOAD_8ROWS cq+64*0, 64*4, 1 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 0, 4, 8, 12, 16, 20, 24, 28 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + LOAD_8ROWS cq+64*2, 64*4, 1 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 2, 6, 10, 14, 18, 22, 26, 30 + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m15, [o(pd_2048)] + add tmp1q, 32*16 + add tmp2q, 32*32 + vpbroadcastd m7, [o(pw_2896x8)] + pmulhrsw m0, m7, [cq+64* 1] + pmulhrsw m1, m7, [cq+64*31] + pmulhrsw m2, m7, [cq+64*17] + pmulhrsw m3, m7, [cq+64*15] + pmulhrsw m4, m7, [cq+64* 9] + pmulhrsw m5, m7, [cq+64*23] + pmulhrsw m6, m7, [cq+64*25] + pmulhrsw m7, [cq+64* 7] + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 1, 31, 17, 15, 9, 23, 25, 7 + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + vpbroadcastd m7, [o(pw_2896x8-(o_idct64_offset))] + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + pmulhrsw m0, m7, [cq+64* 5] + pmulhrsw m1, m7, [cq+64*27] + pmulhrsw m2, m7, [cq+64*21] + pmulhrsw m3, m7, [cq+64*11] + pmulhrsw m4, m7, [cq+64*13] + pmulhrsw m5, m7, [cq+64*19] + pmulhrsw m6, m7, [cq+64*29] + pmulhrsw m7, [cq+64* 3] + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 5, 27, 21, 11, 13, 19, 29, 3 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass1 + sub tmp1q, 32*44 + vpbroadcastd m10, [o(pw_16384)] + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_round_interleave + add cq, 32 + add tmp4d, 0x80000000 + jnc .pass1_loop + lea tmp1q, [rsp+32*15] + imul r2, strideq, 19 + lea r3, [strideq*3] + add r2, dstq + mov tmp4b, 4 +.pass2_loop: + lea tmp2q, [tmp1q+32*64] + LOAD_8ROWS tmp1q-32*4, 32 + test tmp4d, 0x40000000 + jnz .fast + LOAD_8ROWS_H tmp2q-32*4, 32 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + lea tmp3q, [tmp2q-32*8] + LOAD_8ROWS_H tmp3q-32*4, 32 + mova [rsp], m15 + jmp .idct16 +.fast: + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + pxor m8, m8 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 +.idct16: + lea tmp3q, [tmp1q-32*8] + LOAD_8ROWS tmp3q-32*4, 32 + call m(idct_16x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_16x32_8bpc).pass2_end + add tmp1q, 32*16 + sub dstq, r3 + lea r2, [r2+r3+16] + add dstq, 16 + dec tmp4b + jg .pass2_loop + RET +ALIGN function_align +.transpose_round_interleave: + mov tmp3d, 4 +.loop: + lea tmp2q, [tmp1q+32*8] + mova xm0, [tmp1q-32*4] + mova xm1, [tmp1q-32*3] + vinserti128 m0, [tmp2q-32*4], 1 + vinserti128 m1, [tmp2q-32*3], 1 + mova xm2, [tmp1q-32*2] + mova xm3, [tmp1q-32*1] + vinserti128 m2, [tmp2q-32*2], 1 + vinserti128 m3, [tmp2q-32*1], 1 + mova xm4, [tmp1q+32*0] + mova xm5, [tmp1q+32*1] + vinserti128 m4, [tmp2q+32*0], 1 + vinserti128 m5, [tmp2q+32*1], 1 + mova xm6, [tmp1q+32*2] + mova xm7, [tmp1q+32*3] + vinserti128 m6, [tmp2q+32*2], 1 + vinserti128 m7, [tmp2q+32*3], 1 + REPX {pmulhrsw x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova xm8, [tmp1q-32*4+16] + mova xm9, [tmp1q-32*3+16] + vinserti128 m8, [tmp2q-32*4+16], 1 + vinserti128 m9, [tmp2q-32*3+16], 1 + mova [tmp1q-32*4], m0 + mova [tmp2q-32*4], m1 + mova [tmp1q-32*3], m2 + mova [tmp2q-32*3], m3 + mova xm2, [tmp1q-32*2+16] + mova xm3, [tmp1q-32*1+16] + vinserti128 m2, [tmp2q-32*2+16], 1 + vinserti128 m3, [tmp2q-32*1+16], 1 + mova [tmp1q-32*2], m4 + mova [tmp2q-32*2], m5 + mova [tmp1q-32*1], m6 + mova [tmp2q-32*1], m7 + mova xm4, [tmp1q+32*0+16] + mova xm5, [tmp1q+32*1+16] + vinserti128 m4, [tmp2q+32*0+16], 1 + vinserti128 m5, [tmp2q+32*1+16], 1 + mova xm6, [tmp1q+32*2+16] + mova xm7, [tmp1q+32*3+16] + vinserti128 m6, [tmp2q+32*2+16], 1 + vinserti128 m7, [tmp2q+32*3+16], 1 + pmulhrsw m0, m8, m10 + pmulhrsw m1, m9, m10 + REPX {pmulhrsw x, m10}, m2, m3, m4, m5, m6, m7 + call m(inv_txfm_add_identity_identity_8x32_8bpc).transpose8x8 + mova [tmp1q+32*0], m0 + mova [tmp2q+32*0], m1 + mova [tmp1q+32*1], m2 + mova [tmp2q+32*1], m3 + mova [tmp1q+32*2], m4 + mova [tmp2q+32*2], m5 + mova [tmp1q+32*3], m6 + mova [tmp2q+32*3], m7 + add tmp1q, 32*16 + dec tmp3d + jg .loop + ret + +cglobal inv_txfm_add_dct_dct_64x64_8bpc, 4, 4, 0, dst, stride, c, eob + lea r6, [o_base] + test eobd, eobd + jnz .normal + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_8192)] + mov [cq], eobd + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).dconly +.normal: + PROLOGUE 0, 11, 16, 32*199, dst, stride, c, eob, tmp1, tmp2 + lea tmp1q, [rsp+32*71] + lea r10d, [eobq-136] +.pass1_loop: + LOAD_8ROWS cq+64*0, 64*4 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 0, 4, 8, 12, 16, 20, 24, 28 + REPX {mova x, m8}, m9, m10, m11, m12, m13, m14 + mova [rsp], m8 + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + LOAD_8ROWS cq+64*2, 64*4 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 2, 6, 10, 14, 18, 22, 26, 30 + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m15, [o(pd_2048)] + add tmp1q, 32*16 + add tmp2q, 32*32 + mova m0, [cq+64* 1] + mova m1, [cq+64*31] + mova m2, [cq+64*17] + mova m3, [cq+64*15] + mova m4, [cq+64* 9] + mova m5, [cq+64*23] + mova m6, [cq+64*25] + mova m7, [cq+64* 7] + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 1, 31, 17, 15, 9, 23, 25, 7 + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + mova m0, [cq+64* 5] + mova m1, [cq+64*27] + mova m2, [cq+64*21] + mova m3, [cq+64*11] + mova m4, [cq+64*13] + mova m5, [cq+64*19] + mova m6, [cq+64*29] + mova m7, [cq+64* 3] + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 5, 27, 21, 11, 13, 19, 29, 3 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass1 + sub tmp1q, 32*44 + vpbroadcastd m10, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_round_interleave + add cq, 32 + add r10d, 0x80000000 + jnc .pass1_loop + lea tmp1q, [rsp+32*7] + mov r10b, 4 +.pass2_loop: + lea r2, [tmp1q+32*64] + mova m0, [r2-32*4] + mova m1, [r2-32*2] + mova m2, [r2+32*0] + mova m3, [r2+32*2] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14 + mova [rsp], m4 + test r10d, 0x40000000 + jnz .fast + lea r3, [r2+32*64] + mova m4, [r3-32*4] + mova m5, [r3-32*2] + mova m6, [r3+32*0] + mova m7, [r3+32*2] +.fast: + call m(idct_16x16_internal_8bpc).main + mova m1, [rsp+32*1] + mova [tmp1q-32*4], m0 + mova [tmp1q-32*3], m1 + mova [tmp1q-32*2], m2 + mova [tmp1q-32*1], m3 + mova [tmp1q+32*0], m4 + mova [tmp1q+32*1], m5 + mova [tmp1q+32*2], m6 + mova [tmp1q+32*3], m7 + add tmp1q, 32*8 + mova [tmp1q-32*4], m8 + mova [tmp1q-32*3], m9 + mova [tmp1q-32*2], m10 + mova [tmp1q-32*1], m11 + mova [tmp1q+32*0], m12 + mova [tmp1q+32*1], m13 + mova [tmp1q+32*2], m14 + mova [tmp1q+32*3], m15 + mova m0, [r2-32*3] + mova m1, [r2-32*1] + mova m2, [r2+32*1] + mova m3, [r2+32*3] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + test r10d, 0x40000000 + jnz .fast2 + mova m4, [r3-32*3] + mova m5, [r3-32*1] + mova m6, [r3+32*1] + mova m7, [r3+32*3] +.fast2: + add tmp1q, 32*8 + lea tmp2q, [tmp1q+32*8] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m15, [o(pd_2048)] + add r2, 32*8 + add r3, 32*8 + add tmp1q, 32*16 + add tmp2q, 32*32 + mova m0, [r2-32*4] ; 1 + mova m3, [r2+32*3] ; 15 + mova m4, [r2+32*0] ; 9 + mova m7, [r2-32*1] ; 7 + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r10d, 0x40000000 + jnz .fast3 + mova m1, [r3+32*3] ; 31 + mova m2, [r3-32*4] ; 17 + mova m5, [r3-32*1] ; 23 + mova m6, [r3+32*0] ; 25 +.fast3: + add r6, o_idct64_offset + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + add r6, 8 + add tmp1q, 32*8 + sub tmp2q, 32*8 + mova m0, [r2-32*2] ; 5 + mova m3, [r2+32*1] ; 11 + mova m4, [r2+32*2] ; 13 + mova m7, [r2-32*3] ; 3 + pxor m1, m1 + REPX {mova x, m1}, m2, m5, m6 + test r10d, 0x40000000 + jnz .fast4 + mova m1, [r3+32*1] ; 27 + mova m2, [r3-32*2] ; 21 + mova m5, [r3-32*3] ; 19 + mova m6, [r3+32*2] ; 29 +.fast4: + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_part2_pass2 + sub tmp1q, 32*28 + sub dstq, r8 + lea dstq, [dstq+strideq*4+16] + dec r10b + jg .pass2_loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7507 @@ +; Copyright © 2020-2023, VideoLAN and dav1d authors +; Copyright © 2020-2023, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 +const \ +dup16_perm, db 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7 + db 8, 9, 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 14, 15 + db 16, 17, 16, 17, 18, 19, 18, 19, 20, 21, 20, 21, 22, 23, 22, 23 + db 24, 25, 24, 25, 26, 27, 26, 27, 28, 29, 28, 29, 30, 31, 30, 31 +const \ +int8_permA, db 0, 1, 16, 17, 32, 33, 48, 49, 2, 3, 18, 19, 34, 35, 50, 51 + db 4, 5, 20, 21, 36, 37, 52, 53, 6, 7, 22, 23, 38, 39, 54, 55 + db 8, 9, 24, 25, 40, 41, 56, 57, 10, 11, 26, 27, 42, 43, 58, 59 + db 12, 13, 28, 29, 44, 45, 60, 61, 14, 15, 30, 31, 46, 47, 62, 63 +int8_permB: db 0, 1, 16, 17, 32, 33, 48, 49, 2, 3, 18, 19, 34, 35, 50, 51 + db 8, 9, 24, 25, 40, 41, 56, 57, 10, 11, 26, 27, 42, 43, 58, 59 + db 4, 5, 20, 21, 36, 37, 52, 53, 6, 7, 22, 23, 38, 39, 54, 55 + db 12, 13, 28, 29, 44, 45, 60, 61, 14, 15, 30, 31, 46, 47, 62, 63 +int16_perm: db 0, 1, 32, 33, 2, 3, 34, 35, 4, 5, 36, 37, 6, 7, 38, 39 + db 8, 9, 40, 41, 10, 11, 42, 43, 12, 13, 44, 45, 14, 15, 46, 47 + db 16, 17, 48, 49, 18, 19, 50, 51, 20, 21, 52, 53, 22, 23, 54, 55 + db 24, 25, 56, 57, 26, 27, 58, 59, 28, 29, 60, 61, 30, 31, 62, 63 +idtx_16x4p: db 0, 1, 4, 5, 16, 17, 20, 21, 2, 3, 6, 7, 18, 19, 22, 23 + db 32, 33, 36, 37, 48, 49, 52, 53, 34, 35, 38, 39, 50, 51, 54, 55 + db 8, 9, 12, 13, 24, 25, 28, 29, 10, 11, 14, 15, 26, 27, 30, 31 + db 40, 41, 44, 45, 56, 57, 60, 61, 42, 43, 46, 47, 58, 59, 62, 63 +idct_8x32p: db 60, 61, 4, 5, 32, 33, 0, 1, 28, 29, 36, 37, 56, 57, 8, 9 + db 12, 13, 52, 53, 24, 25, 40, 41, 44, 45, 20, 21, 48, 49, 16, 17 + db 62, 63, 2, 3, 6, 7, 58, 59, 54, 55, 10, 11, 14, 15, 50, 51 + db 46, 47, 18, 19, 22, 23, 42, 43, 38, 39, 26, 27, 30, 31, 34, 35 +idct_16x32p: db 6, 7, 58, 59, 38, 39, 26, 27, 32, 33, 0, 1, 30, 31, 34, 35 + db 46, 47, 18, 19, 22, 23, 42, 43, 24, 25, 40, 41, 44, 45, 20, 21 + db 62, 63, 2, 3, 48, 49, 16, 17, 56, 57, 8, 9, 14, 15, 50, 51 + db 54, 55, 10, 11, 60, 61, 4, 5, 12, 13, 52, 53, 28, 29, 36, 37 +end_16x32p: db 0, 32, 1, 48, 2, 36, 3, 52, 16, 40, 17, 56, 18, 44, 19, 60 + db 4, 33, 5, 49, 6, 37, 7, 53, 20, 41, 21, 57, 22, 45, 23, 61 + db 8, 35, 9, 51, 10, 39, 11, 55, 24, 43, 25, 59, 26, 47, 27, 63 + db 12, 34, 13, 50, 14, 38, 15, 54, 28, 42, 29, 58, 30, 46, 31, 62 + +; packed 4-bit qword shuffle indices +permA: dq 0x1c0d0d1ce0d94040, 0x5849495868fb6262 + dq 0x3e2f2f3ef1c85151, 0x7a6b6b7a79ea7373 + dq 0x94858594a451c8d9, 0xd0c1c1d02c73eafb + dq 0xb6a7a7b6b540d9c8, 0xf2e3e3f23d62fbea +permB: dq 0x40acbd0fcadb0f40, 0x518e9f3ce8f99604 + dq 0xc824352d56128751, 0xd906171e74301e15 + dq 0x6271604b03472d62, 0x735342782165b426 + dq 0xeaf9e8699f8ea573, 0xfbdbca5abdac3c37 +permC: dq 0x9d409d041551c2e0, 0xbf62bf263773a486 + dq 0xc88c8c15409dd3f1, 0xeaaeae3762bfb597 + dq 0x04d9158c8cc84a68, 0x26fb37aeaeea2c0e + dq 0x5115049dd9045b79, 0x733726bffb263d1f +permD: dq 0x0cda098800041504, 0x0edb09b2028c3726 + dq 0x0f11fa9c01150415, 0x0988f326039d2637 + dq 0x05640f1108269d8c, 0x05290edb0aaebfae + dq 0x0005000509378c9d, 0xffffffff0bbfaebf + +pd_0to15: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +gather8a: dd 0, 2, 1, 3, 8, 10, 9, 11 +gather8b: dd 0, 1, 4, 5, 8, 9, 12, 13 +gather8c: dd 0, 4, 2, 6, 12, 8, 14, 10 +gather8d: dd 0, 19, 1, 18, 2, 17, 3, 16 + +int_shuf1: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +int_shuf2: db 8, 9, 0, 1, 10, 11, 2, 3, 12, 13, 4, 5, 14, 15, 6, 7 +int_shuf3: db 0, 1, 8, 9, 4, 5, 12, 13, 2, 3, 10, 11, 6, 7, 14, 15 +int_shuf4: db 8, 9, 0, 1, 12, 13, 4, 5, 10, 11, 2, 3, 14, 15, 6, 7 +deint_shuf: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +int_mshift: db 12, 20, 0, 0, 44, 52, 0, 0 + +pb_32: times 4 db 32 +pw_2048: times 2 dw 2048 +pw_4096: times 2 dw 4096 +pw_8192: times 2 dw 8192 +pw_16384: times 2 dw 16384 +pw_1697x16: times 2 dw 1697*16 +pw_1697x8: times 2 dw 1697*8 +pw_2896x8: times 2 dw 2896*8 +pd_2048: dd 2048 + +%define pw_5 (permD+52) +%define pd_m1 (permD+60) +%define pw_3803_1321 (permD+44) +%define pw_2482_3803 (permD+12) +%define pw_2440_3290 (permD+ 4) +%define pw_m3290_2440 (permD+28) +%define pw_3857_1380 (permD+36) +%define pw_m1380_3857 (permD+20) + +pw_8192_m8192: dw 8192, -8192 +pw_m8192_8192: dw -8192, 8192 +pw_16384_m16384: dw 16384, -16384 +pw_m16384_16384: dw -16384, 16384 + +pw_m1321_2482: dw -1321, 2482 +pw_m3344_3344: dw -3344, 3344 +pw_2482_3344: dw 2482, 3344 +pw_m3803_3344: dw -3803, 3344 +pd_3344: dd 3344 +pw_m1321_m3344: dw -1321, -3344 +pw_2896_m2896: dw 2896, -2896 + +pw_1567_m3784: dw 1567, -3784 +pw_3784_m1567: dw 3784, -1567 +pw_4017_m799: dw 4017, -799 +pw_2276_m3406: dw 2276, -3406 +pw_m799_m4017: dw -799, -4017 +pw_m3406_m2276: dw -3406, -2276 + +%macro COEF_PAIR 2-3 0 +pw_%1_%2: dw %1, %2 +pw_m%2_%1: dw -%2, %1 +%if %3 +pw_m%1_m%2: dw -%1, -%2 +%endif +%endmacro + +COEF_PAIR 2896, 2896 +COEF_PAIR 1567, 3784, 1 +COEF_PAIR 3784, 1567 +COEF_PAIR 201, 4091 +COEF_PAIR 995, 3973 +COEF_PAIR 1751, 3703 +COEF_PAIR 3035, 2751 +COEF_PAIR 3513, 2106 +COEF_PAIR 4052, 601 +COEF_PAIR 3166, 2598, 1 +COEF_PAIR 3920, 1189, 1 +COEF_PAIR 2276, 3406 +COEF_PAIR 4017, 799 + +%macro COEF_X8 1-* +%rep %0 + dw %1*8, %1*8 + %rotate 1 +%endrep +%endmacro + +pw_m2276x8: COEF_X8 -2276 +pw_3406x8: COEF_X8 3406 +pw_4017x8: COEF_X8 4017 +pw_799x8: COEF_X8 799 +pw_3784x8: COEF_X8 3784 +pw_1567x8: COEF_X8 1567 + +pw_4076x8: COEF_X8 4076 +pw_401x8: COEF_X8 401 +pw_m2598x8: COEF_X8 -2598 +pw_3166x8: COEF_X8 3166 +pw_3612x8: COEF_X8 3612 +pw_1931x8: COEF_X8 1931 +pw_m1189x8: COEF_X8 -1189 +pw_3920x8: COEF_X8 3920 + +pw_4091x8: COEF_X8 4091 +pw_201x8: COEF_X8 201 +pw_m2751x8: COEF_X8 -2751 +pw_3035x8: COEF_X8 3035 +pw_3703x8: COEF_X8 3703 +pw_1751x8: COEF_X8 1751 +pw_m1380x8: COEF_X8 -1380 +pw_3857x8: COEF_X8 3857 +pw_3973x8: COEF_X8 3973 +pw_995x8: COEF_X8 995 +pw_m2106x8: COEF_X8 -2106 +pw_3513x8: COEF_X8 3513 +pw_3290x8: COEF_X8 3290 +pw_2440x8: COEF_X8 2440 +pw_m601x8: COEF_X8 -601 +pw_4052x8: COEF_X8 4052 + +pw_401_4076x8: dw 401*8, 4076*8 +pw_m2598_3166x8: dw -2598*8, 3166*8 +pw_1931_3612x8: dw 1931*8, 3612*8 +pw_m1189_3920x8: dw -1189*8, 3920*8 +pw_799_4017x8: dw 799*8, 4017*8 +pw_m2276_3406x8: dw -2276*8, 3406*8 + +pw_201_4091x8: dw 201*8, 4091*8 +pw_m601_4052x8: dw -601*8, 4052*8 +pw_995_3973x8: dw 995*8, 3973*8 +pw_m1380_3857x8: dw -1380*8, 3857*8 +pw_1751_3703x8: dw 1751*8, 3703*8 +pw_m2106_3513x8: dw -2106*8, 3513*8 +pw_2440_3290x8: dw 2440*8, 3290*8 +pw_m2751_3035x8: dw -2751*8, 3035*8 + +pw_101_4095x8: dw 101*8, 4095*8 +pw_m2824_2967x8: dw -2824*8, 2967*8 +pw_1660_3745x8: dw 1660*8, 3745*8 +pw_m1474_3822x8: dw -1474*8, 3822*8 +pw_897_3996x8: dw 897*8, 3996*8 +pw_m2191_3461x8: dw -2191*8, 3461*8 +pw_2359_3349x8: dw 2359*8, 3349*8 +pw_m700_4036x8: dw -700*8, 4036*8 +pw_501_4065x8: dw 501*8, 4065*8 +pw_m2520_3229x8: dw -2520*8, 3229*8 +pw_2019_3564x8: dw 2019*8, 3564*8 +pw_m1092_3948x8: dw -1092*8, 3948*8 +pw_1285_3889x8: dw 1285*8, 3889*8 +pw_m1842_3659x8: dw -1842*8, 3659*8 +pw_2675_3102x8: dw 2675*8, 3102*8 +pw_m301_4085x8: dw -301*8, 4085*8 + +idct64_mul: COEF_X8 4095, 101, 2967, -2824, 3745, 1660, 3822, -1474 +COEF_PAIR 401, 4076, 1 +COEF_PAIR 799, 4017 + COEF_X8 -700, 4036, 2359, 3349, -2191, 3461, 897, 3996 +dw -2598, -3166, 3166, -2598, 2598, 3166, -4017, -799, 799, -4017 + COEF_X8 4065, 501, 3229, -2520, 3564, 2019, 3948, -1092 +COEF_PAIR 1931, 3612, 1 +COEF_PAIR 3406, 2276 + COEF_X8 -301, 4085, 2675, 3102, -1842, 3659, 1285, 3889 +dw -1189, -3920, 3920, -1189, 1189, 3920, -2276, -3406, 3406, -2276 + +SECTION .text + +%define o_base int8_permA+64*18 +%define o(x) (r5 - (o_base) + (x)) +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +; flags: 1 = swap, 2 = interleave (l), 4 = interleave (t), 8 = no_pack, +; 16 = special_mul1, 32 = special_mul2 +%macro ITX_MUL2X_PACK 6-7 0 ; dst/src, tmp[1-2], rnd, coef[1-2], flags + mova m%2, m%4 +%if %7 & 16 + vpdpwssd m%2, m%1, [o(pw_%5)] {bcstd} + mova m%3, m%4 +%if %7 & 32 + vpdpwssd m%3, m%1, [o(pw_%6)] {bcstd} +%else + vpdpwssd m%3, m%1, m%6 +%endif +%elif %7 & 32 + vpdpwssd m%2, m%1, m%5 + mova m%3, m%4 + vpdpwssd m%3, m%1, [o(pw_%6)] {bcstd} +%elif %6 < 32 + vpdpwssd m%2, m%1, m%5 + mova m%3, m%4 + vpdpwssd m%3, m%1, m%6 +%elif %7 & 1 + vpdpwssd m%2, m%1, [o(pw_%5_%6)] {bcstd} + mova m%3, m%4 + vpdpwssd m%3, m%1, [o(pw_m%6_%5)] {bcstd} +%else + vpdpwssd m%2, m%1, [o(pw_m%6_%5)] {bcstd} + mova m%3, m%4 + vpdpwssd m%3, m%1, [o(pw_%5_%6)] {bcstd} +%endif +%if %7 & 2 + psrld m%2, 12 + pslld m%3, 4 + vpshrdd m%1, m%3, m%2, 16 +%elif %7 & 4 + ; compared to using shifts (as above) this has better throughput, + ; but worse latency and requires setting up the opmask/index + ; registers, so only use this method for the larger transforms + pslld m%1, m%2, 4 + vpmultishiftqb m%1{k7}, m13, m%3 +%else + psrad m%2, 12 + psrad m%3, 12 +%if %7 & 8 == 0 + packssdw m%1, m%3, m%2 +%endif +%endif +%endmacro + +; flags: same as ITX_MUL2X_PACK +%macro ITX_MUL4X_PACK 10-11 0 ; dst/src, tmp[1-2], coef_tmp[1-2], rnd, coef[1-4], flags +%if %11 & 1 + vpbroadcastd m%4, [o(pw_%9_%10)] + vpbroadcastd m%4{k1}, [o(pw_%7_%8)] + vpbroadcastd m%5, [o(pw_m%10_%9)] + vpbroadcastd m%5{k1}, [o(pw_m%8_%7)] +%else + vpbroadcastd m%4, [o(pw_m%10_%9)] + vpbroadcastd m%4{k1}, [o(pw_m%8_%7)] + vpbroadcastd m%5, [o(pw_%9_%10)] + vpbroadcastd m%5{k1}, [o(pw_%7_%8)] +%endif + ITX_MUL2X_PACK %1, %2, %3, %6, %4, %5, %11 +%endmacro + +; dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +; dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +%macro ITX_MULSUB_2W 7-8 ; dst/src[1-2], tmp[1-2], rnd, coef[1-2], dst2 + punpcklwd m%3, m%2, m%1 + punpckhwd m%2, m%1 +%if %7 < 32 + mova m%1, m%5 + vpdpwssd m%1, m%3, m%7 + mova m%4, m%5 + vpdpwssd m%4, m%2, m%7 +%else + mova m%1, m%5 + vpdpwssd m%1, m%3, [o(pw_m%7_%6)] {bcstd} + mova m%4, m%5 + vpdpwssd m%4, m%2, [o(pw_m%7_%6)] {bcstd} +%endif + psrad m%1, 12 + psrad m%4, 12 + packssdw m%1, m%4 + mova m%4, m%5 +%if %7 < 32 + vpdpwssd m%4, m%2, m%6 + mova m%2, m%5 + vpdpwssd m%2, m%3, m%6 +%else + vpdpwssd m%4, m%2, [o(pw_%6_%7)] {bcstd} + mova m%2, m%5 + vpdpwssd m%2, m%3, [o(pw_%6_%7)] {bcstd} +%endif + psrad m%4, 12 + psrad m%2, 12 +%if %0 == 8 + packssdw m%8, m%2, m%4 +%else + packssdw m%2, m%4 +%endif +%endmacro + +%macro WRAP_XMM 1+ + %xdefine %%reset RESET_MM_PERMUTATION + INIT_XMM cpuname + DEFINE_MMREGS xmm + AVX512_MM_PERMUTATION + %1 + %%reset +%endmacro + +%macro WRAP_YMM 1+ + INIT_YMM cpuname + %1 + INIT_ZMM cpuname +%endmacro + +%macro ITX4_END 4-5 2048 ; row[1-4], rnd +%if %5 + vpbroadcastd m2, [o(pw_%5)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 +%endif + lea r2, [dstq+strideq*2] +%assign %%i 1 +%rep 4 + %if %1 & 2 + CAT_XDEFINE %%row_adr, %%i, r2 + strideq*(%1&1) + %else + CAT_XDEFINE %%row_adr, %%i, dstq + strideq*(%1&1) + %endif + %assign %%i %%i + 1 + %rotate 1 +%endrep + movd m2, [%%row_adr1] + pinsrd m2, [%%row_adr2], 1 + movd m3, [%%row_adr3] + pinsrd m3, [%%row_adr4], 1 + pmovzxbw m2, m2 + pmovzxbw m3, m3 + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + movd [%%row_adr1], m0 + pextrd [%%row_adr2], m0, 1 + pextrd [%%row_adr3], m0, 2 + pextrd [%%row_adr4], m0, 3 + ret +%endmacro + +%macro INV_TXFM_FN 3 ; type1, type2, size +cglobal inv_txfm_add_%1_%2_%3_8bpc, 4, 6, 0, dst, stride, c, eob, tx2, base + %define %%p1 m(i%1_%3_internal_8bpc) + lea baseq, [o_base] + ; Jump to the 1st txfm function if we're not taking the fast path, which + ; in turn performs an indirect jump to the 2nd txfm function. + lea tx2q, [m(i%2_%3_internal_8bpc).pass2] +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else + ; jump to the 1st txfm function unless it's located directly after this + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endmacro + +%macro INV_TXFM_4X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x4 +%ifidn %1_%2, dct_dct + vpbroadcastw m0, [cq] + vpbroadcastd m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mov [cq], eobd + pmulhrsw m0, m1 + mova m1, m0 + jmp m(iadst_4x4_internal_8bpc).end2 +%endif +%endmacro + +%macro IDCT4_1D_PACKED 0 + vpbroadcastd m4, [o(pd_2048)] + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + ITX_MUL2X_PACK 2, 0, 3, 4, 1567, 3784 + ITX_MUL2X_PACK 1, 0, 3, 4, 2896, 2896 + paddsw m0, m1, m2 ; out0 out1 + psubsw m1, m2 ; out3 out2 +%endmacro + +%macro IADST4_1D_PACKED 0 + punpcklwd m4, m1, m0 ; in2 in0 + punpckhwd m5, m1, m0 ; in3 in1 +.main2: + vpbroadcastd m3, [o(pd_2048)] + mova m0, m3 + vpdpwssd m0, m4, [o(pw_3803_1321)] {bcstd} + mova m2, m3 + vpdpwssd m2, m4, [o(pw_m1321_2482)] {bcstd} + mova m1, m3 + vpdpwssd m1, m4, [o(pw_m3344_3344)] {bcstd} + vpdpwssd m3, m4, [o(pw_2482_3803)] {bcstd} + vpdpwssd m0, m5, [o(pw_2482_3344)] {bcstd} + vpdpwssd m2, m5, [o(pw_m3803_3344)] {bcstd} + vpdpwssd m1, m5, [o(pd_3344)] {bcstd} + vpdpwssd m3, m5, [o(pw_m1321_m3344)] {bcstd} + REPX {psrad x, 12}, m0, m2, m1, m3 + packssdw m0, m2 ; out0 out1 + packssdw m1, m3 ; out2 out3 +%endmacro + +INIT_XMM avx512icl +INV_TXFM_4X4_FN dct, dct +INV_TXFM_4X4_FN dct, adst +INV_TXFM_4X4_FN dct, flipadst +INV_TXFM_4X4_FN dct, identity + +cglobal idct_4x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + IDCT4_1D_PACKED + mova m2, [o(deint_shuf)] + shufps m3, m0, m1, q1331 + shufps m0, m0, m1, q0220 + pshufb m0, m2 + pshufb m1, m3, m2 + jmp tx2q +.pass2: + IDCT4_1D_PACKED + pxor ymm16, ymm16 + mova [cq], ymm16 + ITX4_END 0, 1, 3, 2 + +INV_TXFM_4X4_FN adst, dct +INV_TXFM_4X4_FN adst, adst +INV_TXFM_4X4_FN adst, flipadst +INV_TXFM_4X4_FN adst, identity + +cglobal iadst_4x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + call .main + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call .main +.end: + pxor ymm16, ymm16 + mova [cq], ymm16 +.end2: + ITX4_END 0, 1, 2, 3 +ALIGN function_align +.main: + IADST4_1D_PACKED + ret + +INV_TXFM_4X4_FN flipadst, dct +INV_TXFM_4X4_FN flipadst, adst +INV_TXFM_4X4_FN flipadst, flipadst +INV_TXFM_4X4_FN flipadst, identity + +cglobal iflipadst_4x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + call m(iadst_4x4_internal_8bpc).main + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + jmp tx2q +.pass2: + call m(iadst_4x4_internal_8bpc).main +.end: + pxor ymm16, ymm16 + mova [cq], ymm16 +.end2: + ITX4_END 3, 2, 1, 0 + +INV_TXFM_4X4_FN identity, dct +INV_TXFM_4X4_FN identity, adst +INV_TXFM_4X4_FN identity, flipadst +INV_TXFM_4X4_FN identity, identity + +cglobal iidentity_4x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+16*0] + mova m1, [cq+16*1] + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_4x4_internal_8bpc).end + +%macro INV_TXFM_4X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x8 +%ifidn %1_%2, dct_dct + movd xmm1, [o(pw_2896x8)] + pmulhrsw xmm0, xmm1, [cq] + movd xmm2, [o(pw_2048)] + pmulhrsw xmm0, xmm1 + pmulhrsw xmm0, xmm1 + pmulhrsw xmm0, xmm2 + vpbroadcastw ym0, xmm0 + mova ym1, ym0 + jmp m(iadst_4x8_internal_8bpc).end3 +%endif +%endmacro + +%macro IDCT8_1D_PACKED 0 + punpckhwd m5, m3, m0 ; in7 in1 + punpckhwd m4, m1, m2 ; in3 in5 + punpcklwd m3, m1 ; in6 in2 + punpcklwd m2, m0 ; in4 in0 +.main2: + vpbroadcastd m6, [o(pd_2048)] + ITX_MUL2X_PACK 5, 0, 1, 6, 799, 4017, 3 ; t4a t7a + ITX_MUL2X_PACK 4, 0, 1, 6, 3406, 2276, 3 ; t5a t6a + ITX_MUL2X_PACK 3, 0, 1, 6, 1567, 3784 ; t3 t2 + psubsw m0, m5, m4 ; t5a t6a (interleaved) + paddsw m4, m5 ; t4 t7 (interleaved) + ITX_MUL2X_PACK 2, 1, 5, 6, 2896, 2896 ; t0 t1 + ITX_MUL2X_PACK 0, 1, 5, 6, 2896, 2896, 1 ; t6 t5 +%if mmsize > 16 + vbroadcasti32x4 m1, [o(deint_shuf)] + pshufb m4, m1 +%else + pshufb m4, [o(deint_shuf)] +%endif + psubsw m1, m2, m3 ; tmp3 tmp2 + paddsw m3, m2 ; tmp0 tmp1 + punpckhqdq m2, m4, m0 ; t7 t6 + punpcklqdq m4, m0 ; t4 t5 + paddsw m0, m3, m2 ; out0 out1 + psubsw m3, m2 ; out7 out6 + psubsw m2, m1, m4 ; out4 out5 + paddsw m1, m4 ; out3 out2 +%endmacro + +%macro IADST8_1D_PACKED 1 ; pass + vpbroadcastd m6, [o(pd_2048)] +%if %1 == 1 + ITX_MUL2X_PACK 0, 4, 5, 6, 401, 4076, 3 ; t1a t0a + ITX_MUL2X_PACK 1, 4, 5, 6, 1931, 3612, 2 ; t2a t3a + ITX_MUL2X_PACK 2, 4, 5, 6, 3166, 2598, 3 ; t5a t4a + ITX_MUL2X_PACK 3, 4, 5, 6, 3920, 1189, 2 ; t6a t7a + psubsw m4, m0, m2 ; t5 t4 + paddsw m0, m2 ; t1 t0 + psubsw m5, m1, m3 ; t6 t7 + paddsw m1, m3 ; t2 t3 + ITX_MUL2X_PACK 4, 2, 3, 6, 1567, 3784, 3 ; t5a t4a + ITX_MUL2X_PACK 5, 2, 3, 6, 3784, 1567, 2 ; t7a t6a +%if mmsize > 16 + vbroadcasti32x4 m2, [o(deint_shuf)] +%else + mova m2, [o(deint_shuf)] +%endif + vprord m1, 16 + psubsw m3, m0, m1 ; t3 t2 + paddsw m0, m1 ; -out7 out0 + psubsw m1, m4, m5 ; t7 t6 + paddsw m4, m5 ; out6 -out1 + pshufb m0, m2 + pshufb m4, m2 + mova m2, m6 + vpdpwssd m2, m3, [o(pw_m2896_2896)] {bcstd} + mova m5, m6 + vpdpwssd m5, m1, [o(pw_m2896_2896)] {bcstd} + psrad m2, 12 + psrad m5, 12 + packssdw m2, m5 ; out4 -out5 + mova m5, m6 + vpdpwssd m5, m3, [o(pw_2896_2896)] {bcstd} + mova m3, m6 + vpdpwssd m3, m1, [o(pw_2896_2896)] {bcstd} + psrad m5, 12 + psrad m3, 12 + packssdw m1, m3, m5 ; out2 -out3 +%else + punpckhwd m0, m4, m3 ; 0 7 + punpckhwd m1, m5, m2 ; 2 5 + punpcklwd m2, m5 ; 4 3 + punpcklwd m3, m4 ; 6 1 + ITX_MUL2X_PACK 0, 4, 5, 6, 401, 4076 ; t0a t1a + ITX_MUL2X_PACK 1, 4, 5, 6, 1931, 3612 ; t2a t3a + ITX_MUL2X_PACK 2, 4, 5, 6, 3166, 2598 ; t4a t5a + ITX_MUL2X_PACK 3, 4, 5, 6, 3920, 1189 ; t6a t7a + psubsw m4, m0, m2 ; t4 t5 + paddsw m0, m2 ; t0 t1 + psubsw m5, m1, m3 ; t6 t7 + paddsw m1, m3 ; t2 t3 + shufps m2, m5, m4, q1032 + punpckhwd m4, m2 + punpcklwd m5, m2 + ITX_MUL2X_PACK 4, 2, 3, 6, 1567, 3784 ; t4a t5a + ITX_MUL2X_PACK 5, 2, 3, 6, 3784, 1567, 1 ; t6a t7a + psubsw m2, m0, m1 ; t2 t3 + paddsw m0, m1 ; out0 -out7 + psubsw m1, m4, m5 ; t6 t7 + paddsw m4, m5 ; -out1 out6 + vpbroadcastd m5, [o(pw_2896x8)] + punpckhqdq m3, m2, m1 ; t3 t7 + punpcklqdq m2, m1 ; t2 t6 + paddsw m1, m2, m3 ; t2+t3 t6+t7 + psubsw m2, m3 ; t2-t3 t6-t7 + punpckhqdq m3, m4, m0 ; out6 -out7 + punpcklqdq m0, m4 ; out0 -out1 + pmulhrsw m2, m5 ; out4 -out5 + pshufd m1, m1, q1032 + pmulhrsw m1, m5 ; out2 -out3 +%endif +%endmacro + +INIT_YMM avx512icl +INV_TXFM_4X8_FN dct, dct +INV_TXFM_4X8_FN dct, identity +INV_TXFM_4X8_FN dct, adst +INV_TXFM_4X8_FN dct, flipadst + +cglobal idct_4x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + IDCT4_1D_PACKED + vbroadcasti32x4 m2, [o(deint_shuf)] + shufps m3, m0, m1, q1331 + shufps m0, m0, m1, q0220 + pshufb m0, m2 + pshufb m1, m3, m2 + jmp tx2q +.pass2: + vextracti32x4 xm2, m0, 1 + vextracti32x4 xm3, m1, 1 + call .main + vpbroadcastd m4, [o(pw_2048)] + vinserti32x4 m0, m0, xm2, 1 + vinserti32x4 m1, m1, xm3, 1 + pshufd m1, m1, q1032 + jmp m(iadst_4x8_internal_8bpc).end2 +ALIGN function_align +.main: + WRAP_XMM IDCT8_1D_PACKED + ret + +INV_TXFM_4X8_FN adst, dct +INV_TXFM_4X8_FN adst, adst +INV_TXFM_4X8_FN adst, flipadst +INV_TXFM_4X8_FN adst, identity + +cglobal iadst_4x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + call m(iadst_8x4_internal_8bpc).main + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + vextracti32x4 xm2, m0, 1 + vextracti32x4 xm3, m1, 1 + pshufd xm4, xm0, q1032 + pshufd xm5, xm1, q1032 + call .main_pass2 + vpbroadcastd m4, [o(pw_2048)] + vinserti32x4 m0, xm2, 1 + vinserti32x4 m1, xm3, 1 + pxor m5, m5 + psubw m5, m4 +.end: + punpcklqdq m4, m5 +.end2: + pmulhrsw m0, m4 + pmulhrsw m1, m4 +.end3: + vpbroadcastd m3, strided + pmulld m5, m3, [o(pd_0to15)] + kxnorb k1, k1, k1 + kmovb k2, k1 + vpgatherdd m3{k1}, [dstq+m5] + pxor m4, m4 + mova [cq], zmm20 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + vpscatterdd [dstq+m5]{k2}, m0 + RET +ALIGN function_align +.main_pass1: + punpckhwd xm0, xm4, xm3 ; 0 7 + punpckhwd xm1, xm5, xm2 ; 2 5 + punpcklwd xm2, xm5 ; 4 3 + punpcklwd xm3, xm4 ; 6 1 + WRAP_XMM IADST8_1D_PACKED 1 + punpcklqdq xm3, xm4, xm0 ; out6 -out7 + punpckhqdq xm0, xm4 ; out0 -out1 + ret +ALIGN function_align +.main_pass2: + WRAP_XMM IADST8_1D_PACKED 2 + ret + +INV_TXFM_4X8_FN flipadst, dct +INV_TXFM_4X8_FN flipadst, adst +INV_TXFM_4X8_FN flipadst, flipadst +INV_TXFM_4X8_FN flipadst, identity + +cglobal iflipadst_4x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 + vpermq m1, [cq+32*1], q3120 + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + call m(iadst_8x4_internal_8bpc).main + punpcklwd m3, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m3 + punpckhwd m1, m3 + jmp tx2q +.pass2: + vextracti32x4 xm2, m0, 1 + vextracti32x4 xm3, m1, 1 + pshufd xm4, xm0, q1032 + pshufd xm5, xm1, q1032 + call m(iadst_4x8_internal_8bpc).main_pass2 + vpbroadcastd m5, [o(pw_2048)] + vinserti32x4 m3, xm1, 1 + vinserti32x4 m2, xm0, 1 + pxor m4, m4 + psubw m4, m5 + pshufd m0, m3, q1032 + pshufd m1, m2, q1032 + jmp m(iadst_4x8_internal_8bpc).end + +INIT_ZMM avx512icl +INV_TXFM_4X8_FN identity, dct +INV_TXFM_4X8_FN identity, adst +INV_TXFM_4X8_FN identity, flipadst +INV_TXFM_4X8_FN identity, identity + +cglobal iidentity_4x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd m0, [o(pw_2896x8)] + pmulhrsw m0, [cq] + mova m1, [o(int8_permB)] + vpbroadcastd m2, [o(pw_1697x8)] + vpermb m0, m1, m0 + pmulhrsw m2, m0 + paddsw m0, m2 + vextracti32x8 ym1, m0, 1 + jmp tx2q +.pass2: + vpbroadcastd ym4, [o(pw_4096)] + jmp m(iadst_4x8_internal_8bpc).end2 + +%macro INV_TXFM_4X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x16 +%ifidn %1_%2, dct_dct + movsx r6d, word [cq] + mov [cq], eobd + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 + imul r6d, 181 + add r6d, 128+2048 + sar r6d, 8+4 + vpbroadcastw m0, r6d + mova m1, m0 + jmp m(iadst_4x16_internal_8bpc).end3 +%endif +%endmacro + +%macro IDCT16_1D_PACKED 0 + punpckhwd m8, m7, m0 ; dct16 in15 in1 + punpcklwd m9, m4, m0 ; dct4 in2 in0 + punpckhwd m0, m3, m4 ; dct16 in7 in9 + punpcklwd m7, m1 ; dct8 in7 in1 + punpckhwd m1, m6 ; dct16 in3 in13 + punpcklwd m3, m5 ; dct8 in3 in5 + punpckhwd m5, m2 ; dct16 in11 in5 + punpcklwd m6, m2 ; dct4 in3 in1 +cglobal_label .main2 + vpbroadcastd m10, [o(pd_2048)] +.main3: + vpbroadcastq m13, [o(int_mshift)] + vpcmpub k7, m13, m10, 6 ; 0x33... + ITX_MUL2X_PACK 8, 2, 4, 10, 401, 4076, 5 ; t8a t15a + ITX_MUL2X_PACK 0, 2, 4, 10, 3166, 2598, 5 ; t9a t14a + ITX_MUL2X_PACK 5, 2, 4, 10, 1931, 3612, 5 ; t10a t13a + ITX_MUL2X_PACK 1, 2, 4, 10, 3920, 1189, 5 ; t11a t12a + ITX_MUL2X_PACK 7, 2, 4, 10, 799, 4017, 5 ; t4a t7a + ITX_MUL2X_PACK 3, 2, 4, 10, 3406, 2276, 5 ; t5a t6a +.main4: + psubsw m2, m8, m0 ; t9 t14 + paddsw m8, m0 ; t8 t15 + psubsw m4, m1, m5 ; t10 t13 + paddsw m1, m5 ; t11 t12 + ITX_MUL2X_PACK 6, 0, 5, 10, 1567, 3784 ; t3 t2 + psubsw m0, m8, m1 ; t11a t12a + paddsw m8, m1 ; t8a t15a + psubsw m1, m7, m3 ; t5a t6a + paddsw m7, m3 ; t4 t7 +.main5: + ITX_MUL2X_PACK 2, 3, 5, 10, 1567, 3784, 5 ; t9a t14a + ITX_MUL2X_PACK 4, 3, 5, 10, m3784, 1567, 5 ; t10a t13a +%if mmsize > 16 + vbroadcasti32x4 m5, [o(deint_shuf)] +%else + mova m5, [o(deint_shuf)] +%endif + vpbroadcastd m11, [o(pw_m2896_2896)] + vpbroadcastd m12, [o(pw_2896_2896)] + paddsw m3, m2, m4 ; t9 t14 + psubsw m2, m4 ; t10 t13 + pshufb m8, m5 + pshufb m7, m5 + pshufb m3, m5 + ITX_MUL2X_PACK 9, 4, 5, 10, 11, 12 ; t0 t1 + ITX_MUL2X_PACK 1, 4, 5, 10, 12, 11 ; t5 t6 + ITX_MUL2X_PACK 0, 4, 5, 10, 11, 12, 8 ; t11 t12 + ITX_MUL2X_PACK 2, 0, 11, 10, 11, 12, 8 ; t10a t13a + punpckhqdq m2, m7, m1 ; t7 t6 + punpcklqdq m7, m1 ; t4 t5 + psubsw m1, m9, m6 ; dct4 out3 out2 + paddsw m9, m6 ; dct4 out0 out1 + packssdw m5, m11 ; t12 t13a + packssdw m4, m0 ; t11 t10a + punpckhqdq m0, m8, m3 ; t15a t14 + punpcklqdq m8, m3 ; t8a t9 + psubsw m3, m9, m2 ; dct8 out7 out6 + paddsw m9, m2 ; dct8 out0 out1 + psubsw m2, m1, m7 ; dct8 out4 out5 + paddsw m1, m7 ; dct8 out3 out2 + psubsw m7, m9, m0 ; out15 out14 + paddsw m0, m9 ; out0 out1 + psubsw m6, m1, m5 ; out12 out13 + paddsw m1, m5 ; out3 out2 + psubsw m5, m2, m4 ; out11 out10 + paddsw m2, m4 ; out4 out5 + psubsw m4, m3, m8 ; out8 out9 + paddsw m3, m8 ; out7 out6 +%endmacro + +INV_TXFM_4X16_FN dct, dct +INV_TXFM_4X16_FN dct, identity +INV_TXFM_4X16_FN dct, adst +INV_TXFM_4X16_FN dct, flipadst + +cglobal idct_4x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova ym1, [cq+32*2] + vinserti32x8 m1, [cq+32*0], 1 + mova m0, [o(int16_perm)] + mova ym2, [cq+32*3] + vinserti32x8 m2, [cq+32*1], 1 + vpbroadcastd m4, [o(pd_2048)] + vpermb m1, m0, m1 ; c0 a0 c1 a1 c2 a2 c3 a3 + vpermb m2, m0, m2 ; d0 b0 d1 b1 d2 b2 d3 b3 + ITX_MUL2X_PACK 1, 0, 3, 4, 2896, 2896, 2 + ITX_MUL2X_PACK 2, 0, 3, 4, 1567, 3784, 2 + vpbroadcastd m4, [o(pw_16384)] + psubsw m3, m1, m2 + paddsw m1, m2 ; out0 out1 + vprord m3, 16 ; out2 out3 + punpckldq m0, m1, m3 + punpckhdq m1, m3 + pmulhrsw m0, m4 + pmulhrsw m1, m4 + jmp tx2q +.pass2: + vextracti32x4 xm2, ym0, 1 + vextracti32x4 xm3, ym1, 1 + vextracti32x4 xm4, m0, 2 + vextracti32x4 xm5, m1, 2 + vextracti32x4 xm6, m0, 3 + vextracti32x4 xm7, m1, 3 + call .main + vinserti32x4 ym0, xm2, 1 + vinserti32x4 ym1, xm3, 1 + vinserti32x4 ym4, xm6, 1 + vinserti32x4 ym5, xm7, 1 + vinserti32x8 m0, ym4, 1 + vinserti32x8 m1, ym5, 1 + vpbroadcastd m5, [o(pw_2048)] + pshufd m1, m1, q1032 + jmp m(iadst_4x16_internal_8bpc).end2 +ALIGN function_align +.main: + WRAP_XMM IDCT16_1D_PACKED + ret + +INV_TXFM_4X16_FN adst, dct +INV_TXFM_4X16_FN adst, adst +INV_TXFM_4X16_FN adst, flipadst +INV_TXFM_4X16_FN adst, identity + +cglobal iadst_4x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m1, [o(permB)] + vpermq m0, m1, [cq+64*0] + vpermq m1, m1, [cq+64*1] + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m3, [o(pw_16384)] + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + pmulhrsw m2, m3 + pmulhrsw m0, m3 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + jmp tx2q +.pass2: + call .main + vpbroadcastd m5, [o(pw_2048)] + psrlq m10, 4 + psubw m6, m8, m5 +.end: + vpbroadcastd m7, [o(pw_2896x8)] + paddsw ym1, ym2, ym4 + psubsw ym2, ym4 + vinserti32x8 m1, ym2, 1 + pmulhrsw m1, m7 ; -out7 out4 out6 -out5 out8 -out11 -out9 out10 + psrlq m0, m10, 4 + vpermi2q m0, m1, m3 ; 0 1 4 5 8 9 c d + vpermt2q m1, m10, m3 ; 2 3 6 7 a b e f + punpcklqdq m5, m6 +.end2: + pmulhrsw m0, m5 + pmulhrsw m1, m5 +.end3: + vpbroadcastd m3, strided + pmulld m5, m3, [o(pd_0to15)] + kxnorw k1, k1, k1 + kmovw k2, k1 + vpgatherdd m3{k1}, [dstq+m5] + pxor m4, m4 + mova [cq+64*0], m4 + mova [cq+64*1], m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + vpscatterdd [dstq+m5]{k2}, m0 + RET +ALIGN function_align +.main: + movu m3, [o(permB+1)] + psrlq m10, m3, 4 +.main2: + vpermi2q m3, m0, m1 ; in15 in12 in13 in14 in11 in8 in9 in10 + vpermt2q m0, m10, m1 ; in0 in3 in2 in1 in4 in7 in6 in5 + vpbroadcastd m9, [o(pd_2048)] + vpbroadcastq ym13, [o(int_mshift)] + kxnorb k1, k1, k1 + punpckhwd m4, m3, m0 ; in12 in3 in14 in1 + punpcklwd m0, m3 ; in0 in15 in2 in13 + kshiftrb k1, k1, 4 + vextracti32x8 ym3, m4, 1 ; in8 in7 in10 in5 + vextracti32x8 ym1, m0, 1 ; in4 in11 in6 in9 +INIT_YMM avx512icl + vpcmpub k7, m13, m9, 6 ; 0x33... + pxor m8, m8 + ITX_MUL4X_PACK 0, 2, 5, 6, 7, 9, 201, 4091, 995, 3973, 5 + ITX_MUL4X_PACK 1, 2, 5, 6, 7, 9, 1751, 3703, 2440, 3290, 5 + ITX_MUL4X_PACK 3, 2, 5, 6, 7, 9, 3035, 2751, 3513, 2106, 5 + ITX_MUL4X_PACK 4, 2, 5, 6, 7, 9, 3857, 1380, 4052, 601, 5 + psubsw m2, m0, m3 ; t9a t8a t11a t10a + paddsw m0, m3 ; t1a t0a t3a t2a + psubsw m3, m1, m4 ; t13a t12a t15a t14a + paddsw m4, m1 ; t5a t4a t7a t6a + ITX_MUL4X_PACK 2, 1, 5, 6, 7, 9, 799, 4017, 3406, 2276, 5 + psubw m7, m8, m7 + ITX_MUL2X_PACK 3, 1, 5, 9, 7, 6, 4 + vpbroadcastd m6, [o(pw_3784_m1567)] + vpbroadcastd m6{k1}, [o(pw_m3784_1567)] + psubsw m1, m0, m4 ; t5 t4 t7 t6 + paddsw m0, m4 ; t1 t0 t3 t2 + psubsw m4, m2, m3 ; t13a t12a t15a t14a + paddsw m2, m3 ; t9a t8a t11a t10a + ITX_MUL2X_PACK 1, 3, 5, 9, 1567_3784, 6, 16 ; t4a t5a t7a t6a + ITX_MUL2X_PACK 4, 3, 5, 9, 1567_3784, 6, 16 ; t12 t13 t15 t14 + vbroadcasti32x4 m5, [o(deint_shuf)] + pshufb m0, m5 + pshufb m2, m5 + vshufi32x4 m3, m0, m2, 0x03 ; t3 t2 t11a t10a + vinserti32x4 m0, xm2, 1 ; t1 t0 t9a t8a + vshufi32x4 m2, m1, m4, 0x03 ; t7a t6a t15 t14 + vinserti32x4 m1, xm4, 1 ; t4a t5a t12 t13 + pshufd m2, m2, q1032 ; t6a t7a t14 t15 + psubsw m4, m0, m3 ; t3a t2a t11 t10 + paddsw m0, m3 ; -out15 out0 out14 -out1 + paddsw m3, m1, m2 ; out12 -out3 -out13 out2 + psubsw m1, m2 ; t7 t6 t15a t14a + punpckhqdq m2, m4, m1 ; t2a t6 t10 t14a + punpcklqdq m4, m1 ; t3a t7 t11 t15a +INIT_ZMM avx512icl + vinserti32x8 m3, ym0, 1 ; out12 -out3 -out13 out2 -out15 out0 out14 -out1 + ret + +INV_TXFM_4X16_FN flipadst, dct +INV_TXFM_4X16_FN flipadst, adst +INV_TXFM_4X16_FN flipadst, flipadst +INV_TXFM_4X16_FN flipadst, identity + +cglobal iflipadst_4x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m1, [o(permB)] + vpermq m0, m1, [cq+64*0] + vpermq m1, m1, [cq+64*1] + call m(iadst_16x4_internal_8bpc).main + vpbroadcastd m3, [o(pw_16384)] + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + pmulhrsw m2, m3 + pmulhrsw m1, m3 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + jmp tx2q +.pass2: + call m(iadst_4x16_internal_8bpc).main + vpbroadcastd m6, [o(pw_2048)] + psrlq m10, 12 + psubw m5, m8, m6 + jmp m(iadst_4x16_internal_8bpc).end + +INV_TXFM_4X16_FN identity, dct +INV_TXFM_4X16_FN identity, adst +INV_TXFM_4X16_FN identity, flipadst +INV_TXFM_4X16_FN identity, identity + +cglobal iidentity_4x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m2, [o(int16_perm)] + vpermb m1, m2, [cq+64*0] + vpermb m2, m2, [cq+64*1] + vpbroadcastd m4, [o(pw_1697x8)] + vpbroadcastd m0, [o(pd_m1)] + pmulhrsw m3, m4, m1 ; we want to do a signed avg, but pavgw is + vpcmpw k1, m1, m0, 4 ; unsigned. as long as both signs are equal + pmulhrsw m4, m2 ; it still works, but if the input is -1 the + vpcmpw k2, m2, m0, 4 ; pmulhrsw result will become 0 which causes + vpavgw m1{k1}{z}, m3 ; pavgw to output -32768 instead of 0 unless + vpavgw m2{k2}{z}, m4 ; we explicitly deal with that case here. + punpckldq m0, m1, m2 + punpckhdq m1, m2 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x16)] + vpbroadcastd m5, [o(pw_2048)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m0 + paddsw m1, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_4x16_internal_8bpc).end2 + +%macro WRITE_8X4 4-7 strideq*1, strideq*2, r6 ; coefs[1-2], tmp[1-2], off[1-3] + movq xm%3, [dstq ] + movhps xm%3, [dstq+%5] + movq xm%4, [dstq+%6] + movhps xm%4, [dstq+%7] + pmovzxbw m%3, xm%3 + pmovzxbw m%4, xm%4 +%ifnum %1 + paddw m%3, m%1 +%else + paddw m%3, %1 +%endif +%ifnum %2 + paddw m%4, m%2 +%else + paddw m%4, %2 +%endif + packuswb m%3, m%4 + vextracti32x4 xm%4, m%3, 1 + movq [dstq ], xm%3 + movhps [dstq+%6], xm%3 + movq [dstq+%5], xm%4 + movhps [dstq+%7], xm%4 +%endmacro + +%macro INV_TXFM_8X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x4 +%ifidn %1_%2, dct_dct + movd xm1, [o(pw_2896x8)] + pmulhrsw xm0, xm1, [cq] + movd xm2, [o(pw_2048)] + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm1 + pmulhrsw xm0, xm2 + vpbroadcastw m0, xm0 + mova m1, m0 + jmp m(iadst_8x4_internal_8bpc).end3 +%endif +%endmacro + +INIT_YMM avx512icl +INV_TXFM_8X4_FN dct, dct +INV_TXFM_8X4_FN dct, adst +INV_TXFM_8X4_FN dct, flipadst +INV_TXFM_8X4_FN dct, identity + +cglobal idct_8x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd xm3, [o(pw_2896x8)] + pmulhrsw xm0, xm3, [cq+16*0] + pmulhrsw xm1, xm3, [cq+16*1] + pmulhrsw xm2, xm3, [cq+16*2] + pmulhrsw xm3, [cq+16*3] + call m(idct_4x8_internal_8bpc).main + vbroadcasti32x4 m4, [o(deint_shuf)] + vinserti32x4 m3, m1, xm3, 1 + vinserti32x4 m1, m0, xm2, 1 + shufps m0, m1, m3, q0220 + shufps m1, m3, q1331 + pshufb m0, m4 + pshufb m1, m4 + jmp tx2q +.pass2: + IDCT4_1D_PACKED + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + jmp m(iadst_8x4_internal_8bpc).end2 + +INV_TXFM_8X4_FN adst, dct +INV_TXFM_8X4_FN adst, adst +INV_TXFM_8X4_FN adst, flipadst +INV_TXFM_8X4_FN adst, identity + +cglobal iadst_8x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd xm0, [o(pw_2896x8)] + pshufd xm4, [cq+16*0], q1032 + pmulhrsw xm3, xm0, [cq+16*3] + pshufd xm5, [cq+16*1], q1032 + pmulhrsw xm2, xm0, [cq+16*2] + pmulhrsw xm4, xm0 + pmulhrsw xm5, xm0 + call m(iadst_4x8_internal_8bpc).main_pass1 + vinserti32x4 m0, xm2, 1 + vinserti32x4 m1, xm3, 1 + pxor m3, m3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + psubsw m3, m2 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call .main +.end: + vpermq m0, m0, q3120 + vpermq m1, m1, q3120 +.end2: + vpbroadcastd m2, [o(pw_2048)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 +.end3: + pxor m2, m2 + mova [cq], zmm18 + lea r6, [strideq*3] + WRITE_8X4 0, 1, 4, 5 + RET +ALIGN function_align +.main: + IADST4_1D_PACKED + ret + +INV_TXFM_8X4_FN flipadst, dct +INV_TXFM_8X4_FN flipadst, adst +INV_TXFM_8X4_FN flipadst, flipadst +INV_TXFM_8X4_FN flipadst, identity + +cglobal iflipadst_8x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd xm0, [o(pw_2896x8)] + pshufd xm4, [cq+16*0], q1032 + pmulhrsw xm3, xm0, [cq+16*3] + pshufd xm5, [cq+16*1], q1032 + pmulhrsw xm2, xm0, [cq+16*2] + pmulhrsw xm4, xm0 + pmulhrsw xm5, xm0 + call m(iadst_4x8_internal_8bpc).main_pass1 + vinserti32x4 m3, m3, xm1, 1 + vinserti32x4 m2, m2, xm0, 1 + punpckhwd m1, m3, m2 + punpcklwd m3, m2 + pxor m0, m0 + psubsw m0, m1 + punpckhwd m1, m0, m3 + punpcklwd m0, m3 + jmp tx2q +.pass2: + call m(iadst_8x4_internal_8bpc).main + mova m2, m1 + vpermq m1, m0, q2031 + vpermq m0, m2, q2031 + jmp m(iadst_8x4_internal_8bpc).end2 + +INV_TXFM_8X4_FN identity, dct +INV_TXFM_8X4_FN identity, adst +INV_TXFM_8X4_FN identity, flipadst +INV_TXFM_8X4_FN identity, identity + +cglobal iidentity_8x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova xm2, [cq+16*0] + mova xm0, [cq+16*1] + vinserti32x4 m2, [cq+16*2], 1 + vinserti32x4 m0, [cq+16*3], 1 + vpbroadcastd m3, [o(pw_2896x8)] + punpcklwd m1, m2, m0 + punpckhwd m2, m0 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + paddsw m0, m0 + paddsw m1, m1 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_8x4_internal_8bpc).end + +%macro INV_TXFM_8X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x8 +%ifidn %1_%2, dct_dct +INIT_ZMM avx512icl + movsx r6d, word [cq] + mov [cq], eobd +.dconly: + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 +.dconly2: + vpbroadcastd ym2, strided + imul r6d, 181 + pmulld ym5, ym2, [o(pd_0to15)] + kxnorb k1, k1, k1 + add r6d, 128+2048 + sar r6d, 8+4 + pxor m3, m3 + vpbroadcastw m4, r6d +.dconly_loop: + kmovb k2, k1 + vpgatherdq m2{k1}, [dstq+ym5] + punpcklbw m0, m2, m3 + punpckhbw m1, m2, m3 + paddw m0, m4 + paddw m1, m4 + packuswb m0, m1 + kmovb k1, k2 + vpscatterdq [dstq+ym5]{k2}, m0 + lea dstq, [dstq+strideq*8] + sub r3d, 8 + jg .dconly_loop + RET +INIT_YMM avx512icl +%endif +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, identity +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst + +cglobal idct_8x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m0, [cq+32*0], q3120 ; 0 1 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m2, [cq+32*2], q3120 ; 4 5 + vpermq m1, [cq+32*1], q3120 ; 2 3 + call .main + shufps m4, m0, m1, q0220 + shufps m5, m0, m1, q1331 + shufps m1, m2, m3, q0220 + shufps m3, m2, m3, q1331 + vbroadcasti32x4 m0, [o(deint_shuf)] + vpbroadcastd m2, [o(pw_16384)] + REPX {pshufb x, m0}, m4, m5, m1, m3 + REPX {pmulhrsw x, m2}, m4, m5, m1, m3 + vinserti32x4 m0, m4, xm1, 1 + vshufi32x4 m2, m4, m1, 0x03 + vinserti32x4 m1, m5, xm3, 1 + vshufi32x4 m3, m5, m3, 0x03 + jmp tx2q +.pass2: + call .main + vpbroadcastd m4, [o(pw_2048)] + vpermq m0, m0, q3120 + vpermq m1, m1, q2031 + vpermq m2, m2, q3120 + vpermq m3, m3, q2031 + jmp m(iadst_8x8_internal_8bpc).end2 +ALIGN function_align +cglobal_label .main + IDCT8_1D_PACKED + ret + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, adst +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity + +cglobal iadst_8x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m4, [cq+32*0], q1302 ; 1 0 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m5, [cq+32*1], q1302 ; 3 2 + vpermq m2, [cq+32*2], q3120 ; 4 5 + call .main_pass1 + vpbroadcastd m5, [o(pw_16384_m16384)] + punpcklwd m4, m0, m1 + punpckhwd m0, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + punpcklwd m3, m4, m0 + punpckhwd m4, m0 + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + REPX {pmulhrsw x, m5}, m3, m4, m0, m1 + vshufi32x4 m2, m3, m0, 0x03 + vinserti32x4 m0, m3, xm0, 1 + vshufi32x4 m3, m4, m1, 0x03 + vinserti32x4 m1, m4, xm1, 1 + jmp tx2q +.pass2: + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call .main_pass2 + vpbroadcastd m5, [o(pw_2048)] + vpbroadcastd xm4, [o(pw_4096)] + psubw m4, m5 ; lower half = 2048, upper half = -2048 +.end: + REPX {vpermq x, x, q3120}, m0, m1, m2, m3 +.end2: + pmulhrsw m0, m4 + pmulhrsw m1, m4 +.end3: + pmulhrsw m2, m4 + pmulhrsw m3, m4 +.end4: + pxor m4, m4 + mova [cq+32*0], m4 + mova [cq+32*1], m4 + mova [cq+32*2], m4 + mova [cq+32*3], m4 + lea r6, [strideq*3] + WRITE_8X4 0, 1, 4, 5 + lea dstq, [dstq+strideq*4] + WRITE_8X4 2, 3, 4, 5 + RET +ALIGN function_align +.main_pass1: + punpckhwd m0, m4, m3 ; 0 7 + punpckhwd m1, m5, m2 ; 2 5 + punpcklwd m2, m5 ; 4 3 + punpcklwd m3, m4 ; 6 1 + IADST8_1D_PACKED 1 + punpcklqdq m3, m4, m0 ; out6 -out7 + punpckhqdq m0, m4 ; out0 -out1 + ret +ALIGN function_align +cglobal_label .main_pass2 + IADST8_1D_PACKED 2 + ret + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, flipadst +INV_TXFM_8X8_FN flipadst, identity + +cglobal iflipadst_8x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpermq m4, [cq+32*0], q1302 ; 1 0 + vpermq m3, [cq+32*3], q3120 ; 6 7 + vpermq m5, [cq+32*1], q1302 ; 3 2 + vpermq m2, [cq+32*2], q3120 ; 4 5 + call m(iadst_8x8_internal_8bpc).main_pass1 + vpbroadcastd m5, [o(pw_m16384_16384)] + punpckhwd m4, m3, m2 + punpcklwd m3, m2 + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + punpckhwd m0, m4, m3 + punpcklwd m4, m3 + punpckhwd m3, m2, m1 + punpcklwd m2, m1 + REPX {pmulhrsw x, m5}, m0, m4, m3, m2 + vinserti32x4 m1, m0, xm3, 1 + vshufi32x4 m3, m0, m3, 0x03 + vinserti32x4 m0, m4, xm2, 1 + vshufi32x4 m2, m4, m2, 0x03 + jmp tx2q +.pass2: + pshufd m4, m0, q1032 + pshufd m5, m1, q1032 + call m(iadst_8x8_internal_8bpc).main_pass2 + vpbroadcastd m4, [o(pw_2048)] + vpbroadcastd xm5, [o(pw_4096)] + psubw m4, m5 ; lower half = -2048, upper half = 2048 + vpermq m5, m3, q2031 + vpermq m3, m0, q2031 + vpermq m0, m2, q2031 + vpermq m2, m1, q2031 + pmulhrsw m1, m0, m4 + pmulhrsw m0, m5, m4 + jmp m(iadst_8x8_internal_8bpc).end3 + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova xm3, [cq+16*0] + mova xm2, [cq+16*1] + vinserti32x4 m3, [cq+16*4], 1 + vinserti32x4 m2, [cq+16*5], 1 + mova xm4, [cq+16*2] + mova xm0, [cq+16*3] + vinserti32x4 m4, [cq+16*6], 1 + vinserti32x4 m0, [cq+16*7], 1 + punpcklwd m1, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m4, m0 + punpckhwd m4, m0 + punpckldq m0, m1, m2 + punpckhdq m1, m2 + punpckldq m2, m3, m4 + punpckhdq m3, m4 + jmp tx2q +.pass2: + vpbroadcastd m4, [o(pw_4096)] + jmp m(iadst_8x8_internal_8bpc).end + +%macro INV_TXFM_8X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x16 +%ifidn %1_%2, dct_dct + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 16 + imul r6d, 181 + add r6d, 128 + sar r6d, 8 + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).dconly +%endif +%endmacro + +%macro ITX_8X16_LOAD_COEFS 0 + vpbroadcastd m4, [o(pw_2896x8)] + pmulhrsw m0, m4, [cq+32*0] + add cq, 32*4 + pmulhrsw m7, m4, [cq+32*3] + pmulhrsw m1, m4, [cq-32*3] + pmulhrsw m6, m4, [cq+32*2] + pmulhrsw m2, m4, [cq-32*2] + pmulhrsw m5, m4, [cq+32*1] + pmulhrsw m3, m4, [cq-32*1] + pmulhrsw m4, [cq+32*0] +%endmacro + +INIT_ZMM avx512icl +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, identity +INV_TXFM_8X16_FN dct, adst +INV_TXFM_8X16_FN dct, flipadst + +cglobal idct_8x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m3, [o(permB)] + vpermq m0, m3, [cq+64*0] + vpbroadcastd m4, [o(pw_2896x8)] + vpermq m1, m3, [cq+64*1] + vpermq m2, m3, [cq+64*2] + vpermq m3, m3, [cq+64*3] + REPX {pmulhrsw x, m4}, m0, m1, m2, m3 + call m(idct_16x8_internal_8bpc).main + vpbroadcastd m5, [o(pw_16384)] + punpckhwd m4, m0, m2 ; b0 f0 b1 f1 b2 f2 b3 f3 + punpcklwd m0, m2 ; a0 e0 a1 e1 a2 e2 a3 e3 + punpckhwd m2, m1, m3 ; c0 g0 c1 g1 c2 g2 c3 g3 + punpcklwd m1, m3 ; d0 h0 d1 h1 d2 h2 d3 h3 + REPX {pmulhrsw x, m5}, m4, m0, m2, m1 + punpckhwd m3, m0, m4 ; a2 b2 e2 f2 a3 b3 e3 f3 + punpcklwd m0, m4 ; a0 b0 e0 f0 a1 b1 e1 f1 + punpckhwd m4, m2, m1 ; c2 d2 g2 h2 c3 d3 g3 h3 + punpcklwd m2, m1 ; c0 d0 g0 h0 c1 d1 g1 h1 + punpckhdq m1, m0, m2 ; 1 5 9 13 + punpckldq m0, m2 ; 0 4 8 12 + punpckldq m2, m3, m4 ; 2 6 10 14 + punpckhdq m3, m4 ; 3 7 11 15 + jmp tx2q +.pass2: + vprord m5, [o(int16_perm)], 16 + vshufi32x4 m2, m2, q1320 ; 2 10 14 6 + vshufi32x4 m4, m1, m3, q2310 ; 1 5 15 11 + vshufi32x4 m1, m3, q0132 ; 9 13 7 3 + vpermb m9, m5, m0 + vpermb m7, m5, m2 + vpermb m8, m5, m4 + vpermb m0, m5, m1 + vextracti32x8 ym6, m9, 1 + vextracti32x8 ym3, m7, 1 + vextracti32x8 ym5, m8, 1 + vextracti32x8 ym1, m0, 1 + call .main2 + mova ym8, [o(gather8a)] + lea r3, [dstq+strideq*4] + pmovzxdq m9, ym8 + pshufd ym8, ym8, q1230 + vpermt2q m0, m9, m4 + vpermt2q m1, m9, m5 + vpermt2q m2, m9, m6 + vpermt2q m3, m9, m7 +.end: + vpbroadcastd m7, [o(pw_2048)] +.end2: + pmulhrsw m0, m7 + pmulhrsw m1, m7 +.end3: + pmulhrsw m2, m7 + pmulhrsw m3, m7 +.end4: + vpbroadcastd ym6, strided + kxnorb k1, k1, k1 + pxor m4, m4 + pmulld ym8, ym6 + kmovb k2, k1 + vpgatherdq m6{k1}, [dstq+ym8] + kmovb k1, k2 + vpgatherdq m7{k2}, [r3+ym8] + mova [cq+64*0], m4 + mova [cq+64*1], m4 + kmovb k2, k1 + mova [cq+64*2], m4 + mova [cq+64*3], m4 + punpcklbw m5, m6, m4 + punpckhbw m6, m4 + paddw m0, m5 + paddw m1, m6 + packuswb m0, m1 + vpscatterdq [dstq+ym8]{k1}, m0 + punpcklbw m6, m7, m4 + punpckhbw m7, m4 + paddw m2, m6 + paddw m3, m7 + packuswb m2, m3 + vpscatterdq [r3+ym8]{k2}, m2 + RET +ALIGN function_align +cglobal_label .main_fast2 ; bottom three-quarters are zero + vpbroadcastd ym10, [o(pd_2048)] + vpbroadcastq ym13, [o(int_mshift)] + vpbroadcastd ym3, [o(pw_401_4076x8)] + vpbroadcastd ym5, [o(pw_799_4017x8)] + vpbroadcastd ym4, [o(pw_m1189_3920x8)] + pxor ym6, ym6 + punpckhwd ym2, ym0, ym0 + pmulhrsw ym2, ym3 ; t8a t15a + punpcklwd ym7, ym1, ym1 + pmulhrsw ym7, ym5 ; t4a t7a + punpckhwd ym1, ym1 + pmulhrsw ym4, ym1 ; t11a t12a + vpcmpub k7, ym13, ym10, 6 + punpcklwd ym9, ym6, ym0 + psubsw ym0, ym2, ym4 ; t11a t12a + paddsw ym8, ym2, ym4 ; t8a t15a + mova ym1, ym7 + jmp .main5 +ALIGN function_align +cglobal_label .main_fast ; bottom half is zero + vpbroadcastd ym10, [o(pd_2048)] + vpbroadcastq ym13, [o(int_mshift)] + pxor ym6, ym6 + punpckhwd ym8, ym0, ym0 + punpckhwd ym4, ym3, ym3 + punpckhwd ym5, ym2, ym2 + punpcklwd ym7, ym1, ym1 + punpckhwd ym1, ym1 + punpcklwd ym3, ym3 + punpcklwd ym9, ym6, ym0 + punpcklwd ym6, ym2 + vpbroadcastd ym2, [o(pw_401_4076x8)] + vpbroadcastd ym0, [o(pw_m2598_3166x8)] + vpbroadcastd ym11, [o(pw_1931_3612x8)] + vpbroadcastd ym12, [o(pw_m1189_3920x8)] + pmulhrsw ym8, ym2 ; t8a t15a + vpbroadcastd ym2, [o(pw_799_4017x8)] + pmulhrsw ym0, ym4 ; t9a t14a + vpbroadcastd ym4, [o(pw_m2276_3406x8)] + pmulhrsw ym5, ym11 ; t10a t13a + pmulhrsw ym1, ym12 ; t11a t12a + pmulhrsw ym7, ym2 ; t4a t7a + pmulhrsw ym3, ym4 ; t5a t6a + vpcmpub k7, ym13, ym10, 6 + jmp .main4 +ALIGN function_align +cglobal_label .main + WRAP_YMM IDCT16_1D_PACKED + ret + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, adst +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, identity + +cglobal iadst_8x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call m(iadst_16x8_internal_8bpc).main_pass1 + vbroadcasti32x4 m6, [o(int_shuf1)] + vpbroadcastd m7, [o(pw_16384_m16384)] + punpckhwd m3, m0, m4 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpcklwd m4, m0 ; g0 h0 g1 h1 g2 h2 g3 h3 + pshufb m5, m1, m6 ; c0 d0 c1 d1 c2 d2 c3 d3 + pshufb m2, m6 ; e0 f0 e1 f1 e2 f2 e3 f3 +.pass1_end: + REPX {pmulhrsw x, m7}, m3, m5, m4, m2 + punpckldq m0, m3, m5 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m3, m5 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckhdq m5, m2, m4 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpckldq m2, m4 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m5 + punpckhqdq m3, m5 + jmp tx2q +.pass2: + call .main_pass2 + vpbroadcastd m6, [o(pw_2048)] + psrlq m10, 4 + psubw m7, m8, m6 +.pass2_end: + vpbroadcastd m5, [o(pw_2896x8)] + paddsw m1, m2, m4 + psubsw m2, m4 + pmulhrsw m1, m5 ; -out7 out4 out6 -out5 + pmulhrsw m5, m2 ; out8 -out11 -out9 out10 + mova ym8, [o(gather8c)] + lea r3, [dstq+strideq] + psrlq m2, m10, 4 + vpermi2q m2, m0, m3 ; 1 3 13 15 + vpermt2q m0, m10, m3 ; 0 2 12 14 + psrlq m3, m10, 8 + vpermi2q m3, m1, m5 ; 5 7 9 11 + psrlq m10, 12 + vpermt2q m1, m10, m5 ; 4 6 8 10 + pmulhrsw m0, m6 + pmulhrsw m1, m6 + jmp m(idct_8x16_internal_8bpc).end3 +ALIGN function_align +.main_pass1: + vpbroadcastd m2, [o(pw_2896x8)] + pmulhrsw m5, m2, [cq+64*0] + pmulhrsw m3, m2, [cq+64*3] + pmulhrsw m1, m2, [cq+64*1] + pmulhrsw m2, [cq+64*2] + movu m4, [o(permA+3)] + psrlq m10, m4, 4 + mova m6, m4 + vpermi2q m4, m5, m3 ; in0 in12 in2 in14 + vpermt2q m5, m10, m3 ; in15 in3 in13 in1 + vpermi2q m6, m1, m2 ; in4 in8 in6 in10 + vpermt2q m1, m10, m2 ; in11 in7 in9 in5 + jmp .main +ALIGN function_align +.main_pass2: + mova m4, [o(permC)] + psrlq m5, m4, 4 + vpermi2q m4, m0, m2 ; in0 in12 in2 in14 + psrlq m6, m5, 4 + vpermi2q m5, m1, m3 ; in15 in3 in13 in1 + psrlq m10, m6, 4 + vpermi2q m6, m0, m2 ; in4 in8 in6 in10 + vpermt2q m1, m10, m3 ; in11 in7 in9 in5 +.main: + punpcklwd m0, m4, m5 ; in0 in15 in2 in13 + punpckhwd m4, m5 ; in12 in3 in14 in1 + punpcklwd m5, m6, m1 ; in4 in11 in6 in9 + punpckhwd m6, m1 ; in8 in7 in10 in5 +cglobal_label .main2 + vpbroadcastd m9, [o(pd_2048)] + vpbroadcastq m13, [o(int_mshift)] + kxnorb k1, k1, k1 + vpcmpub k7, m13, m9, 6 ; 0x33... + pxor m8, m8 + ITX_MUL4X_PACK 0, 1, 2, 3, 7, 9, 201, 4091, 995, 3973, 5 + ITX_MUL4X_PACK 6, 1, 2, 3, 7, 9, 3035, 2751, 3513, 2106, 5 + ITX_MUL4X_PACK 4, 1, 2, 3, 7, 9, 3857, 1380, 4052, 601, 5 + ITX_MUL4X_PACK 5, 1, 2, 3, 7, 9, 1751, 3703, 2440, 3290, 5 + psubsw m2, m0, m6 ; t9a t8a t11a t10a + paddsw m0, m6 ; t1a t0a t3a t2a + psubsw m3, m5, m4 ; t13a t12a t15a t14a + paddsw m5, m4 ; t5a t4a t7a t6a + ITX_MUL4X_PACK 2, 4, 1, 6, 7, 9, 799, 4017, 3406, 2276, 5 + psubw m7, m8, m7 + ITX_MUL2X_PACK 3, 4, 1, 9, 7, 6, 4 + vpbroadcastd m6, [o(pw_3784_m1567)] + vpbroadcastd m6{k1}, [o(pw_m3784_1567)] + psubsw m1, m0, m5 ; t5 t4 t7 t6 + paddsw m0, m5 ; t1 t0 t3 t2 + psubsw m4, m2, m3 ; t13a t12a t15a t14a + paddsw m2, m3 ; t9a t8a t11a t10a + ITX_MUL2X_PACK 1, 3, 5, 9, 1567_3784, 6, 16 ; t5a t4a t6a t7a + ITX_MUL2X_PACK 4, 3, 5, 9, 1567_3784, 6, 16 ; t13 t12 t14 t15 + vbroadcasti32x4 m5, [o(deint_shuf)] + pshufb m0, m5 + pshufb m2, m5 + vshufi32x4 m3, m0, m2, q3232 ; t3 t2 t11a t10a + vinserti32x8 m0, ym2, 1 ; t1 t0 t9a t8a + vshufi32x4 m2, m1, m4, q3232 ; t6a t7a t14 t15 + vinserti32x8 m1, ym4, 1 ; t5a t4a t13 t12 + pshufd m2, m2, q1032 ; t7a t6a t15 t14 + psubsw m4, m0, m3 ; t3a t2a t11 t10 + paddsw m0, m3 ; -out15 out0 out14 -out1 + paddsw m3, m1, m2 ; out12 -out3 -out13 out2 + psubsw m1, m2 ; t7 t6 t15a t14a + punpckhqdq m2, m4, m1 ; t2a t6 t10 t14a + punpcklqdq m4, m1 ; t3a t7 t11 t15a + ret + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst +INV_TXFM_8X16_FN flipadst, identity + +cglobal iflipadst_8x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call m(iadst_16x8_internal_8bpc).main_pass1 + vbroadcasti32x4 m6, [o(int_shuf2)] + vpbroadcastd m7, [o(pw_m16384_16384)] + punpcklwd m3, m0, m4 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpckhwd m4, m0 ; g0 h0 g1 h1 g2 h2 g3 h3 + pshufb m5, m2, m6 ; c0 d0 c1 d1 c2 d2 c3 d3 + pshufb m2, m1, m6 ; e0 f0 e1 f1 e2 f2 e3 f3 + jmp m(iadst_8x16_internal_8bpc).pass1_end +.pass2: + call m(iadst_8x16_internal_8bpc).main_pass2 + vpbroadcastd m7, [o(pw_2048)] + psrlq m10, 36 + psubw m6, m8, m7 + jmp m(iadst_8x16_internal_8bpc).pass2_end + +INV_TXFM_8X16_FN identity, dct +INV_TXFM_8X16_FN identity, adst +INV_TXFM_8X16_FN identity, flipadst +INV_TXFM_8X16_FN identity, identity + +cglobal iidentity_8x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [o(int16_perm)] + vpermb m3, m0, [cq+64*0] ; a0 b0 a1 b1 a2 b2 a3 b3 + vpermb m2, m0, [cq+64*1] ; c0 d0 c1 d1 c2 d2 c3 d3 + vpermb m4, m0, [cq+64*2] ; e0 f0 e1 f1 e2 f2 e3 f3 + vpermb m0, m0, [cq+64*3] ; g0 h0 g1 h1 g2 h2 g3 h3 + vpbroadcastd m5, [o(pw_2896x8)] + punpckldq m1, m3, m2 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m3, m2 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m2, m4, m0 ; e0 f0 g0 h0 a1 f1 g1 h1 + punpckhdq m4, m0 ; e2 f2 g2 h2 e3 f3 g3 h3 + REPX {pmulhrsw x, m5}, m1, m2, m3, m4 + punpcklqdq m0, m1, m2 ; a0 b0 c0 d0 e0 f0 g0 h0 + punpckhqdq m1, m2 ; a1 b1 c1 d1 e1 f1 g1 h1 + punpcklqdq m2, m3, m4 ; a2 b2 c2 d2 e2 f2 g2 h2 + punpckhqdq m3, m4 ; a3 b3 c3 d3 e3 f3 g3 h3 + jmp tx2q +.pass2: + vpbroadcastd m7, [o(pw_1697x16)] + mova ym8, [o(gather8b)] + lea r3, [dstq+strideq*2] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + REPX {paddsw x, x}, m0, m1, m2, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(idct_8x16_internal_8bpc).end + +%macro WRITE_16X2 6 ; coefs[1-2], tmp[1-2], offset[1-2] + pmovzxbw m%3, [dstq+%5] +%ifnum %1 + paddw m%3, m%1 +%else + paddw m%3, %1 +%endif + pmovzxbw m%4, [dstq+%6] +%ifnum %2 + paddw m%4, m%2 +%else + paddw m%4, %2 +%endif + packuswb m%3, m%4 + vpermq m%3, m%3, q3120 + mova [dstq+%5], xm%3 + vextracti32x4 [dstq+%6], m%3, 1 +%endmacro + +%macro INV_TXFM_16X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x4 +%ifidn %1_%2, dct_dct + movsx r6d, word [cq] + mov [cq], eobd + jmp m(inv_txfm_add_dct_dct_16x8_8bpc).dconly2 +%endif +%endmacro + +INIT_ZMM avx512icl +INV_TXFM_16X4_FN dct, dct +INV_TXFM_16X4_FN dct, adst +INV_TXFM_16X4_FN dct, flipadst +INV_TXFM_16X4_FN dct, identity + +cglobal idct_16x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova xm0, [cq+16*0] + mova xm1, [cq+16*1] + mova xm2, [cq+16*2] + mova xm3, [cq+16*3] + mova xm4, [cq+16*4] + mova xm5, [cq+16*5] + mova xm6, [cq+16*6] + mova xm7, [cq+16*7] + call m(idct_4x16_internal_8bpc).main + vpbroadcastd m8, [o(pw_16384)] + vinserti32x4 ym1, xm3, 1 ; 3 2 7 6 + vinserti32x4 ym5, xm7, 1 ; b a f e + vinserti32x4 ym0, xm2, 1 ; 0 1 4 5 + vinserti32x4 ym4, xm6, 1 ; 8 9 c d + vinserti32x8 m1, ym5, 1 ; 3 2 7 6 b a f e + vinserti32x8 m0, ym4, 1 ; 0 1 4 5 8 9 c d + pmulhrsw m1, m8 + pmulhrsw m0, m8 + pshufd m1, m1, q1032 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + jmp tx2q +.pass2: + IDCT4_1D_PACKED + mova m2, [o(permA)] + jmp m(iadst_16x4_internal_8bpc).end + +INV_TXFM_16X4_FN adst, dct +INV_TXFM_16X4_FN adst, adst +INV_TXFM_16X4_FN adst, flipadst +INV_TXFM_16X4_FN adst, identity + +cglobal iadst_16x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+64*0] + mova m1, [cq+64*1] + movshdup m3, [o(permB)] + psrlq m10, m3, 4 + call m(iadst_4x16_internal_8bpc).main2 + vpbroadcastd m6, [o(pw_16384_m16384)] + psrlq m0, m10, 4 + psrlq m10, 8 +.pass1_end: + punpcklwd ym5, ym4, ym2 + punpckhwd ym4, ym2 + vinserti32x8 m5, ym4, 1 + mova m1, m9 + vpdpwssd m1, m5, [o(pw_m2896_2896)] {1to16} + mova m4, m9 + vpdpwssd m4, m5, [o(pw_2896_2896)] {1to16} + psrad m1, 12 + psrad m4, 12 + packssdw m1, m4 ; out8 -out7 -out9 out6 -out11 out4 out10 -out5 + vpermi2q m0, m1, m3 ; 0 1 4 5 8 9 c d + vpermt2q m1, m10, m3 ; 2 3 6 7 a b e f + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 + punpcklwd m0, m2 + pmulhrsw m0, m6 + pmulhrsw m1, m6 + jmp tx2q +.pass2: + call .main + movu m2, [o(permA+1)] +.end: + vpbroadcastd m3, [o(pw_2048)] + pmulhrsw m0, m3 + pmulhrsw m1, m3 +.end2: + psrlq m3, m2, 4 + vpermi2q m2, m0, m1 + vpermi2q m3, m0, m1 +.end3: + lea r3, [dstq+strideq*2] + mova xm1, [dstq+strideq*0] + vinserti32x4 ym1, [dstq+strideq*1], 1 + vinserti32x4 m1, [r3 +strideq*0], 2 + vinserti32x4 m1, [r3 +strideq*1], 3 + pxor m4, m4 + mova [cq+64*0], m4 + mova [cq+64*1], m4 + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + paddw m0, m2 + paddw m1, m3 + packuswb m0, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [r3 +strideq*0], m0, 2 + vextracti32x4 [r3 +strideq*1], m0, 3 + RET +ALIGN function_align +.main: + IADST4_1D_PACKED + ret + +INV_TXFM_16X4_FN flipadst, dct +INV_TXFM_16X4_FN flipadst, adst +INV_TXFM_16X4_FN flipadst, flipadst +INV_TXFM_16X4_FN flipadst, identity + +cglobal iflipadst_16x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m0, [cq+64*0] + mova m1, [cq+64*1] + movshdup m3, [o(permB)] + psrlq m10, m3, 4 + call m(iadst_4x16_internal_8bpc).main2 + vpbroadcastd m6, [o(pw_m16384_16384)] + psrlq m0, m10, 12 + psrlq m10, 16 + jmp m(iadst_16x4_internal_8bpc).pass1_end +.pass2: + call m(iadst_16x4_internal_8bpc).main + movu m2, [o(permA+2)] + jmp m(iadst_16x4_internal_8bpc).end + +INV_TXFM_16X4_FN identity, dct +INV_TXFM_16X4_FN identity, adst +INV_TXFM_16X4_FN identity, flipadst +INV_TXFM_16X4_FN identity, identity + +cglobal iidentity_16x4_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m1, [cq+64*0] + mova m2, [cq+64*1] + vpbroadcastd m3, [o(pw_1697x16)] + vpbroadcastd m4, [o(pw_16384)] + mova m5, [o(idtx_16x4p)] + shufps m0, m1, m2, q2020 + shufps m1, m2, q3131 + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddsw m0, m2 + paddsw m1, m3 + vpermb m0, m5, m0 + vpermb m1, m5, m1 + jmp tx2q +.pass2: + vpbroadcastd m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + movu m2, [o(permA+1)] + jmp m(iadst_16x4_internal_8bpc).end + +%macro INV_TXFM_16X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x8 +%ifidn %1_%2, dct_dct + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 8 +.dconly: + imul r6d, 181 + add r6d, 128 + sar r6d, 8 +.dconly2: + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 +.dconly3: + imul r6d, 181 + lea r2, [strideq*3] + add r6d, 128+2048 + sar r6d, 8+4 + pxor m2, m2 + vpbroadcastw m3, r6d +.dconly_loop: + mova xm1, [dstq+strideq*0] + vinserti32x4 ym1, [dstq+strideq*1], 1 + vinserti32x4 m1, [dstq+strideq*2], 2 + vinserti32x4 m1, [dstq+r2 ], 3 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + paddw m0, m3 + paddw m1, m3 + packuswb m0, m1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+r2 ], m0, 3 + lea dstq, [dstq+strideq*4] + sub r3d, 4 + jg .dconly_loop + RET +%endif +%endmacro + +%macro ITX_16X8_LOAD_COEFS 1 ; shuf_odd + vpbroadcastd m8, [o(pw_2896x8)] + vpermq m0, [cq+32*0], q3120 + add cq, 32*4 + vpermq m7, [cq+32*3], q%1 + vpermq m1, [cq-32*3], q%1 + vpermq m6, [cq+32*2], q3120 + vpermq m2, [cq-32*2], q3120 + vpermq m5, [cq+32*1], q%1 + vpermq m3, [cq-32*1], q%1 + vpermq m4, [cq+32*0], q3120 + REPX {pmulhrsw x, m8}, m0, m7, m1, m6, m2, m5, m3, m4 +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, identity +INV_TXFM_16X8_FN dct, adst +INV_TXFM_16X8_FN dct, flipadst + +cglobal idct_16x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd m1, [o(pw_2896x8)] + vpermq m0, [cq+64*0], q3120 + vpermq m2, [cq+64*1], q3120 + vpermq m4, [cq+64*2], q3120 + vpermq m6, [cq+64*3], q3120 + REPX {pmulhrsw x, m1}, m0, m2, m4, m6 + vextracti32x8 ym1, m0, 1 + vextracti32x8 ym3, m2, 1 + vextracti32x8 ym5, m4, 1 + vextracti32x8 ym7, m6, 1 + call m(idct_8x16_internal_8bpc).main + vbroadcasti32x4 m8, [o(int_shuf1)] + vbroadcasti32x4 m9, [o(int_shuf2)] + vinserti32x8 m0, ym2, 1 ; a0 a1 a2 a3 b0 b1 b2 b3 + vinserti32x8 m1, ym3, 1 ; d0 d1 d2 d3 c0 c1 c2 c3 + vinserti32x8 m4, ym6, 1 ; i0 i1 i2 i3 j0 j1 j2 j3 + vinserti32x8 m5, ym7, 1 ; l0 l1 l2 l3 k0 k1 k2 k3 + vpbroadcastd m2, [o(pw_16384)] + pshufb m0, m8 ; a0 b0 a1 b1 a2 b2 a3 b3 + pshufb m1, m9 ; c0 d0 c1 d1 c2 d2 c3 d3 + pshufb m6, m4, m8 ; i0 j0 i1 j1 i2 j2 i3 j3 + pshufb m7, m5, m9 ; m0 n0 m1 n1 m2 n2 m3 n3 + REPX {pmulhrsw x, m2}, m0, m1, m6, m7 + punpckldq m2, m0, m1 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m3, m0, m1 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m4, m6, m7 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhdq m5, m6, m7 ; i2 j2 k2 l2 i3 j3 k3 l3 + jmp tx2q +.pass2: + vshufi32x4 m0, m2, m4, q2020 ; 0 1 + vshufi32x4 m2, m4, q3131 ; 4 5 + vshufi32x4 m1, m3, m5, q2020 ; 2 3 + vshufi32x4 m3, m5, q3131 ; 6 7 + call .main + movshdup m4, [o(permC)] + psrlq m6, m4, 4 + vpermq m5, m4, q1032 + vpermi2q m4, m0, m2 ; a2 a3 b2 b3 e2 e3 f2 f3 + vpermt2q m0, m6, m2 ; a0 a1 b0 b1 e0 e1 f0 f1 + psrlq m6, m5, 4 + vpermi2q m5, m1, m3 ; c2 c3 d2 d3 g2 g3 h2 h3 + vpermt2q m1, m6, m3 ; c0 c1 d0 d1 g0 g1 h0 h1 + vpbroadcastd m6, [o(pw_2048)] +.end: + REPX {pmulhrsw x, m6}, m0, m4, m1, m5 +.end2: + lea r3, [dstq+strideq*4] + lea r4, [strideq*3] + mova xm3, [dstq+strideq*0] + mova xm6, [dstq+strideq*2] + vinserti32x4 ym3, [dstq+strideq*1], 1 + vinserti32x4 ym6, [dstq+r4 ], 1 + vinserti32x4 m3, [r3 +strideq*0], 2 + vinserti32x4 m6, [r3 +strideq*2], 2 + vinserti32x4 m3, [r3 +strideq*1], 3 + vinserti32x4 m6, [r3 +r4 ], 3 + pxor m7, m7 + mova [cq+64*0], m7 + mova [cq+64*1], m7 + mova [cq+64*2], m7 + mova [cq+64*3], m7 + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + paddw m0, m2 + paddw m4, m3 + packuswb m0, m4 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [r3 +strideq*0], m0, 2 + vextracti32x4 [r3 +strideq*1], m0, 3 + punpcklbw m3, m6, m7 + punpckhbw m6, m7 + paddw m1, m3 + paddw m5, m6 + packuswb m1, m5 + mova [dstq+strideq*2], xm1 + vextracti32x4 [dstq+r4 ], ym1, 1 + vextracti32x4 [r3 +strideq*2], m1, 2 + vextracti32x4 [r3 +r4 ], m1, 3 + RET +ALIGN function_align +cglobal_label .main + IDCT8_1D_PACKED + ret + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, adst +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, identity + +cglobal iadst_16x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call m(iadst_8x16_internal_8bpc).main_pass1 + vpbroadcastd m7, [o(pw_16384_m16384)] + psrlq m10, 4 +.pass1_end: + punpcklwd m5, m4, m2 + punpckhwd m4, m2 + mova m1, m9 + vpdpwssd m1, m5, [o(pw_m2896_2896)] {1to16} + mova m6, m9 + vpdpwssd m6, m5, [o(pw_2896_2896)] {1to16} + mova m2, m9 + vpdpwssd m2, m4, [o(pw_m2896_2896)] {1to16} + vpdpwssd m9, m4, [o(pw_2896_2896)] {1to16} + psrad m1, 12 + psrad m6, 12 + packssdw m1, m6 ; out8 -out7 -out9 out6 + psrad m2, 12 + psrad m9, 12 + packssdw m2, m9 ; -out11 out4 out10 -out5 + psrlq m4, m10, 4 + vpermi2q m4, m0, m2 + vpermt2q m0, m10, m2 + psrlq m5, m10, 8 + vpermi2q m5, m1, m3 + psrlq m10, 12 + vpermt2q m1, m10, m3 + punpcklwd m3, m4, m5 ; a0 c0 a1 c1 a2 c2 a3 c3 + punpckhwd m4, m5 ; b0 d0 b1 d1 b2 d2 b3 d3 + punpcklwd m5, m1, m0 ; i0 k0 i1 k1 2i k2 i3 k3 + punpckhwd m1, m0 ; j0 l0 j1 l1 j2 l2 j3 l3 + punpcklwd m2, m3, m4 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhwd m3, m4 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpcklwd m4, m5, m1 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhwd m5, m1 ; i2 j2 k2 l2 i3 j3 k3 l3 + REPX {pmulhrsw x, m7}, m2, m3, m4, m5 + jmp tx2q +.pass2: + vshufi32x4 m0, m2, m4, q2020 + vshufi32x4 m2, m4, q3131 ; 4 5 + vshufi32x4 m1, m3, m5, q2020 + vshufi32x4 m3, m5, q3131 ; 6 7 + pshufd m4, m0, q1032 ; 1 0 + pshufd m5, m1, q1032 ; 3 2 + call .main_pass2 + movshdup m4, [o(permC)] + pmulhrsw m0, m6 + pmulhrsw m1, m6 + psrlq m6, m4, 4 + mova m5, m4 + vpermi2q m4, m0, m2 + vpermt2q m0, m6, m2 + vpermi2q m5, m1, m3 + vpermt2q m1, m6, m3 + jmp m(idct_16x8_internal_8bpc).end2 +ALIGN function_align +.main_pass1: + vpbroadcastd m4, [o(pw_2896x8)] + pmulhrsw m3, m4, [cq+64*0] + pmulhrsw m1, m4, [cq+64*3] + pmulhrsw m2, m4, [cq+64*1] + pmulhrsw m4, [cq+64*2] + mova m5, [o(int16_perm)] + kxnorb k1, k1, k1 + vpblendmd m0{k1}, m1, m3 ; 0 7 + vmovdqa32 m3{k1}, m1 ; 6 1 + vpblendmd m1{k1}, m4, m2 ; 2 5 + vmovdqa32 m2{k1}, m4 ; 4 3 + REPX {vpermb x, m5, x}, m0, m1, m2, m3 + IADST8_1D_PACKED 1 + ret +ALIGN function_align +cglobal_label .main_pass2 + IADST8_1D_PACKED 2 + pxor m5, m5 + psubd m5, m6 + packssdw m6, m5 + pmulhrsw m2, m6 + pmulhrsw m3, m6 + ret + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst +INV_TXFM_16X8_FN flipadst, identity + +cglobal iflipadst_16x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call m(iadst_8x16_internal_8bpc).main_pass1 + vpbroadcastd m7, [o(pw_m16384_16384)] + psrlq m10, 20 + jmp m(iadst_16x8_internal_8bpc).pass1_end +.pass2: + vshufi32x4 m0, m2, m4, q2020 + vshufi32x4 m2, m4, q3131 ; 4 5 + vshufi32x4 m1, m3, m5, q2020 + vshufi32x4 m3, m5, q3131 ; 6 7 + pshufd m4, m0, q1032 ; 1 0 + pshufd m5, m1, q1032 ; 3 2 + call m(iadst_16x8_internal_8bpc).main_pass2 + movshdup m4, [o(permC)] + pmulhrsw m5, m6, m0 + pmulhrsw m0, m6, m1 + psrlq m1, m4, 12 + psrlq m4, 8 + mova m7, m4 + vpermi2q m4, m0, m3 + vpermt2q m0, m1, m3 + vpermi2q m1, m5, m2 + vpermt2q m5, m7, m2 + jmp m(idct_16x8_internal_8bpc).end2 + +INV_TXFM_16X8_FN identity, dct +INV_TXFM_16X8_FN identity, adst +INV_TXFM_16X8_FN identity, flipadst +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + vpbroadcastd m0, [o(pw_2896x8)] + pmulhrsw m3, m0, [cq+64*0] + pmulhrsw m4, m0, [cq+64*1] + pmulhrsw m5, m0, [cq+64*2] + pmulhrsw m0, [cq+64*3] + vpbroadcastd m7, [o(pw_1697x16)] + vpbroadcastd m8, [o(pw_16384)] + shufps m2, m3, m4, q2020 ; a0 a1 a4 a5 e0 e1 e4 e5 + shufps m3, m4, q3131 ; a2 a3 a6 a7 e2 e3 e6 e7 + shufps m4, m5, m0, q2020 ; i0 i1 i4 i5 m0 m1 m4 m5 + shufps m5, m0, q3131 ; i2 i3 i6 i7 m2 m3 m6 m7 + mova m9, [o(int8_permA)] + pmulhrsw m0, m7, m2 + pmulhrsw m1, m7, m3 + pmulhrsw m6, m7, m4 + pmulhrsw m7, m5 + REPX {pmulhrsw x, m8}, m0, m1, m6, m7 + paddsw m2, m0 + paddsw m3, m1 + paddsw m4, m6 + paddsw m5, m7 + REPX {vpermb x, m9, x}, m2, m3, m4, m5 + jmp tx2q +.pass2: + mova m7, [o(permB)] + vpbroadcastd m6, [o(pw_4096)] + vpermq m0, m7, m2 + vpermq m4, m7, m4 + vpermq m1, m7, m3 + vpermq m5, m7, m5 + jmp m(idct_16x8_internal_8bpc).end + +%macro INV_TXFM_16X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x16 +%ifidn %1_%2, dct_dct + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 16 + imul r6d, 181 + add r6d, 128+512 + sar r6d, 8+2 + jmp m(inv_txfm_add_dct_dct_16x8_8bpc).dconly3 +%endif +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, identity +INV_TXFM_16X16_FN dct, adst +INV_TXFM_16X16_FN dct, flipadst + +cglobal idct_16x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m7, [o(permB)] + vpermq m0, m7, [cq+64*0] + vpermq m1, m7, [cq+64*1] + vpermq m2, m7, [cq+64*2] + vpermq m3, m7, [cq+64*3] + vpermq m4, m7, [cq+64*4] + vpermq m5, m7, [cq+64*5] + vpermq m6, m7, [cq+64*6] + vpermq m7, m7, [cq+64*7] + call .main + vbroadcasti32x4 m12, [o(int_shuf1)] + vbroadcasti32x4 m11, [o(int_shuf2)] + vpbroadcastd m13, [o(pw_8192)] + pshufb m0, m12 + pshufb m8, m1, m11 + pshufb m2, m12 + pshufb m9, m3, m11 + pshufb m4, m12 + pshufb m10, m5, m11 + pshufb m6, m12 + pshufb m11, m7, m11 + REPX {pmulhrsw x, m13}, m0, m8, m2, m9, m4, m10, m6, m11 + punpckhdq m1, m0, m8 + punpckldq m0, m8 + punpckhdq m3, m2, m9 + punpckldq m2, m9 + punpckhdq m5, m4, m10 + punpckldq m4, m10 + punpckhdq m7, m6, m11 + punpckldq m6, m11 + jmp tx2q +.pass2: + vshufi32x4 m8, m4, m6, q3232 ; i8 ic m8 mc + vinserti32x8 m4, ym6, 1 ; i0 i4 m0 m4 + vshufi32x4 m6, m0, m2, q3232 ; a8 ac e8 ec + vinserti32x8 m0, ym2, 1 ; a0 a4 e0 e4 + vshufi32x4 m9, m5, m7, q3232 ; ia ie ma me + vinserti32x8 m5, ym7, 1 ; i2 i6 m2 m6 + vshufi32x4 m7, m1, m3, q3232 ; aa ae ea ee + vinserti32x8 m1, ym3, 1 ; a2 a6 e2 e6 + vshufi32x4 m2, m0, m4, q3131 ; 4 5 + vshufi32x4 m0, m4, q2020 ; 0 1 + vshufi32x4 m4, m6, m8, q2020 ; 8 9 + vshufi32x4 m6, m8, q3131 ; 12 13 + vshufi32x4 m3, m1, m5, q3131 ; 6 7 + vshufi32x4 m1, m5, q2020 ; 2 3 + vshufi32x4 m5, m7, m9, q2020 ; 10 11 + vshufi32x4 m7, m9, q3131 ; 14 15 + call .main + mova m8, [o(permD)] + psrlq m12, m8, 4 + psrlq m9, m8, 8 + psrlq m13, m8, 12 + mova m10, m8 + vpermi2q m8, m0, m2 ; 0 1 4 5 + vpermt2q m0, m12, m2 + mova m11, m9 + vpermi2q m9, m1, m3 ; 2 3 6 7 + vpermt2q m1, m13, m3 + vpermi2q m10, m4, m6 ; 8 9 12 13 + vpermt2q m4, m12, m6 + vpermi2q m11, m5, m7 ; 10 11 14 15 + vpermt2q m5, m13, m7 +.end: + vpbroadcastd m12, [o(pw_2048)] +.end2: + REPX {pmulhrsw x, m12}, m0, m1, m4, m5 +.end3: + REPX {pmulhrsw x, m12}, m8, m9, m10, m11 + lea r3, [strideq*3] + lea r4, [dstq+strideq*4] + lea r5, [dstq+strideq*8] + lea r6, [r4 +strideq*8] + mova xm3, [dstq+strideq*0] + mova xm6, [dstq+strideq*2] + vinserti32x4 ym3, [dstq+strideq*1], 1 + vinserti32x4 ym6, [dstq+r3 ], 1 + vinserti32x4 m3, [r4+strideq*0], 2 + vinserti32x4 m6, [r4+strideq*2], 2 + vinserti32x4 m3, [r4+strideq*1], 3 + vinserti32x4 m6, [r4+r3 ], 3 + mova xm12, [r5+strideq*0] + mova xm13, [r5+strideq*2] + vinserti32x4 ym12, [r5+strideq*1], 1 + vinserti32x4 ym13, [r5+r3 ], 1 + vinserti32x4 m12, [r6+strideq*0], 2 + vinserti32x4 m13, [r6+strideq*2], 2 + vinserti32x4 m12, [r6+strideq*1], 3 + vinserti32x4 m13, [r6+r3 ], 3 + pxor m7, m7 + REPX {mova [cq+64*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + punpcklbw m2, m3, m7 + punpckhbw m3, m7 + paddw m0, m2 + paddw m8, m3 + packuswb m0, m8 + punpcklbw m2, m6, m7 + punpckhbw m6, m7 + paddw m1, m2 + paddw m9, m6 + packuswb m1, m9 + punpcklbw m2, m12, m7 + punpckhbw m12, m7 + paddw m2, m4 + paddw m10, m12 + packuswb m2, m10 + punpcklbw m3, m13, m7 + punpckhbw m13, m7 + paddw m3, m5 + paddw m11, m13 + packuswb m3, m11 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + mova [dstq+strideq*2], xm1 + vextracti32x4 [dstq+r3 ], ym1, 1 + vextracti32x4 [r4+strideq*0], m0, 2 + vextracti32x4 [r4+strideq*1], m0, 3 + vextracti32x4 [r4+strideq*2], m1, 2 + vextracti32x4 [r4+r3 ], m1, 3 + mova [r5+strideq*0], xm2 + vextracti32x4 [r5+strideq*1], ym2, 1 + mova [r5+strideq*2], xm3 + vextracti32x4 [r5+r3 ], ym3, 1 + vextracti32x4 [r6+strideq*0], m2, 2 + vextracti32x4 [r6+strideq*1], m2, 3 + vextracti32x4 [r6+strideq*2], m3, 2 + vextracti32x4 [r6+r3 ], m3, 3 + RET +ALIGN function_align +cglobal_label .main_fast2 ; bottom three-quarters are zero + vpbroadcastd m10, [o(pd_2048)] + vpbroadcastq m13, [o(int_mshift)] + vpcmpub k7, m13, m10, 6 +.main_fast4: + vpbroadcastd m2, [o(pw_401_4076x8)] + vpbroadcastd m4, [o(pw_m1189_3920x8)] + vpbroadcastd m3, [o(pw_799_4017x8)] + pmulhrsw m2, m8 ; t8a t15a + pmulhrsw m4, m1 ; t11a t12a + pmulhrsw m7, m3 ; t4a t7a + pxor m6, m6 + psubsw m0, m2, m4 ; t11a t12a + paddsw m8, m2, m4 ; t8a t15a + mova m1, m7 + jmp .main5 +ALIGN function_align +cglobal_label .main_fast ; bottom half is zero + vpbroadcastd m10, [o(pd_2048)] +.main_fast3: + vpbroadcastq m13, [o(int_mshift)] + vpcmpub k7, m13, m10, 6 +.main_fast5: + vpbroadcastd m2, [o(pw_401_4076x8)] + vpbroadcastd m4, [o(pw_m2598_3166x8)] + vpbroadcastd m11, [o(pw_1931_3612x8)] + vpbroadcastd m12, [o(pw_m1189_3920x8)] + pmulhrsw m8, m2 ; t8a t15a + vpbroadcastd m2, [o(pw_799_4017x8)] + pmulhrsw m0, m4 ; t9a t14a + vpbroadcastd m4, [o(pw_m2276_3406x8)] + pmulhrsw m5, m11 ; t10a t13a + pmulhrsw m1, m12 ; t11a t12a + pmulhrsw m7, m2 ; t4a t7a + pmulhrsw m3, m4 ; t5a t6a + jmp .main4 +ALIGN function_align +cglobal_label .main + IDCT16_1D_PACKED + ret + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, adst +INV_TXFM_16X16_FN adst, flipadst + +cglobal iadst_16x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call .main_pass1 + vpbroadcastd m10, [o(pw_8192_m8192)] + punpcklwd m8, m0, m1 ; b0 d0 b1 d1 b2 d2 b3 d3 + punpckhwd m0, m1 ; a0 c0 a1 c1 a2 c2 a3 c3 + punpckhwd m1, m0, m8 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpcklwd m0, m8 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpcklwd m8, m2, m3 ; f0 h0 f1 h1 f2 h2 f3 h3 + punpckhwd m2, m3 ; e0 g0 e1 g1 e2 g2 e3 g3 + punpckhwd m3, m2, m8 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpcklwd m2, m8 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhwd m8, m4, m5 ; i0 k0 i1 k1 i2 k2 i3 k3 + punpcklwd m4, m5 ; j0 l0 j1 l1 j2 l2 j3 l3 + punpckhwd m5, m4, m8 ; i2 j2 k2 l2 i3 j3 k3 l3 + punpcklwd m4, m8 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhwd m8, m6, m7 ; m0 o0 m1 o1 m2 o2 m3 o3 + punpcklwd m6, m7 ; n0 p0 n1 p1 n2 p2 n3 p3 + punpckhwd m7, m6, m8 ; m2 n2 o2 p2 m3 n3 o3 p3 + punpcklwd m6, m8 ; m0 n0 o0 p0 m1 n1 o1 p1 +.pass1_end: + REPX {pmulhrsw x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 + jmp tx2q +.pass2: + call .main_pass2 + mova m10, [o(permD)] + psrlq m8, m10, 8 + psrlq m12, m10, 12 + psrlq m13, m10, 4 + mova m9, m8 + vpermi2q m8, m0, m2 ; 0 1 4 5 + vpermt2q m0, m12, m2 + vpermi2q m9, m1, m3 ; 2 3 6 7 + vpermt2q m1, m12, m3 + vpbroadcastd m12, [o(pw_2048)] + mov r3d, 0xff00ff00 + mova m11, m10 + vpermi2q m10, m4, m6 ; 8 9 12 13 + vpermt2q m4, m13, m6 + kmovd k1, r3d + vpermi2q m11, m5, m7 ; 10 11 14 15 + vpermt2q m5, m13, m7 + pxor m7, m7 + vpsubw m12{k1}, m7, m12 + jmp m(idct_16x16_internal_8bpc).end2 +ALIGN function_align +.main_pass1: + mova m4, [o(permB)] + psrlq m3, m4, 4 + vpermq m0, m4, [cq+64*0] + vpermq m7, m3, [cq+64*7] + vpermq m6, m4, [cq+64*6] + vpermq m1, m3, [cq+64*1] + vpermq m2, m4, [cq+64*2] + vpermq m5, m3, [cq+64*5] + vpermq m4, m4, [cq+64*4] + vpermq m3, m3, [cq+64*3] + call .main + vpbroadcastd m13, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + mova m2, m10 + vpdpwssd m2, m5, m13 ; -out5 + mova m8, m10 + vpdpwssd m8, m11, m13 ; out4 + mova m9, m10 + vpdpwssd m9, m5, m12 ; out10 + mova m5, m10 + vpdpwssd m5, m11, m12 ; -out11 + mova m11, m10 + vpdpwssd m11, m3, m13 ; -out7 + mova m14, m10 + vpdpwssd m14, m4, m13 ; out6 + mova m13, m10 + vpdpwssd m13, m3, m12 ; out8 + vpdpwssd m10, m4, [o(pw_2896_m2896)] {1to16} ; -out9 + REPX {psrad x, 12}, m2, m8, m9, m5, m11, m14, m13, m10 + packssdw m2, m8 ; -out5 out4 + packssdw m5, m9, m5 ; out10 -out11 + packssdw m3, m11, m14 ; -out7 out6 + packssdw m4, m13, m10 ; out8 -out9 + ret +ALIGN function_align +.main_pass2: + vshufi32x4 m8, m4, m6, q3232 ; i8 ic m8 mc + vinserti32x8 m4, ym6, 1 ; i0 i4 m0 m4 + vshufi32x4 m6, m0, m2, q3232 ; a8 ac e8 ec + vinserti32x8 m0, ym2, 1 ; a0 a4 e0 e4 + vshufi32x4 m9, m5, m7, q3232 ; ia ie ma me + vinserti32x8 m5, ym7, 1 ; i2 i6 m2 m6 + vshufi32x4 m7, m1, m3, q3232 ; aa ae ea ee + vinserti32x8 m1, ym3, 1 ; a2 a6 e2 e6 + vshufi32x4 m2, m0, m4, q3131 ; 4 5 + vshufi32x4 m0, m4, q2020 ; 0 1 + vshufi32x4 m4, m6, m8, q2020 ; 8 9 + vshufi32x4 m6, m8, q3131 ; 12 13 + vshufi32x4 m3, m1, m5, q3131 ; 6 7 + vshufi32x4 m1, m5, q2020 ; 2 3 + vshufi32x4 m5, m7, m9, q2020 ; 10 11 + vshufi32x4 m7, m9, q3131 ; 14 15 +cglobal_label .main_pass2b + REPX {pshufd x, x, q1032}, m1, m3, m5, m7 + call .main + vpbroadcastd m8, [o(pw_2896x8)] + pshufb m2, m11, m12 + pshufb m5, m12 + pshufb m3, m12 + pshufb m4, m12 + punpcklqdq m9, m5, m2 ; t15a t7 + punpckhqdq m5, m2 ; t14a t6 + shufps m2, m3, m4, q1032 ; t2a t10 + shufps m3, m4, q3210 ; t3a t11 + psubsw m4, m2, m3 ; out8 -out9 + paddsw m3, m2 ; -out7 out6 + paddsw m2, m5, m9 ; -out5 out4 + psubsw m5, m9 ; out10 -out11 + REPX {pmulhrsw x, m8}, m2, m3, m4, m5 + ret +ALIGN function_align +.main: + vpbroadcastd m10, [o(pd_2048)] + vpbroadcastq m13, [o(int_mshift)] + punpckhwd m8, m7, m0 ; in14 in1 + punpcklwd m0, m7 ; in0 in15 + punpcklwd m7, m6, m1 ; in12 in3 + punpckhwd m1, m6 ; in2 in13 + punpckhwd m6, m5, m2 ; in10 in5 + punpcklwd m2, m5 ; in4 in11 + punpcklwd m5, m4, m3 ; in8 in7 + punpckhwd m3, m4 ; in6 in9 + vpcmpub k7, m13, m10, 6 ; 0x33... + ITX_MUL2X_PACK 0, 4, 9, 10, 201, 4091, 5 ; t0 t1 + ITX_MUL2X_PACK 1, 4, 9, 10, 995, 3973, 5 ; t2 t3 + ITX_MUL2X_PACK 2, 4, 9, 10, 1751, 3703, 5 ; t4 t5 + ITX_MUL2X_PACK 3, 4, 9, 10, 2440, 3290, 5 ; t6 t7 + ITX_MUL2X_PACK 5, 4, 9, 10, 3035, 2751, 5 ; t8 t9 + ITX_MUL2X_PACK 6, 4, 9, 10, 3513, 2106, 5 ; t10 t11 + ITX_MUL2X_PACK 7, 4, 9, 10, 3857, 1380, 5 ; t12 t13 + ITX_MUL2X_PACK 8, 4, 9, 10, 4052, 601, 5 ; t14 t15 + psubsw m4, m0, m5 ; t9a t8a + paddsw m0, m5 ; t1a t0a + psubsw m5, m1, m6 ; t11a t10a + paddsw m1, m6 ; t3a t2a + psubsw m6, m2, m7 ; t13a t12a + paddsw m2, m7 ; t5a t4a + psubsw m7, m3, m8 ; t15a t14a + paddsw m3, m8 ; t7a t6a + ITX_MUL2X_PACK 4, 8, 9, 10, 799, 4017, 4 ; t8 t9 + ITX_MUL2X_PACK 6, 8, 9, 10, 799_4017, 4017_m799, 52 ; t12 t13 + ITX_MUL2X_PACK 5, 8, 9, 10, 3406, 2276, 4 ; t10 t11 + ITX_MUL2X_PACK 7, 8, 9, 10, 3406_2276, 2276_m3406, 52 ; t14 t15 + psubsw m8, m1, m3 ; t7 t6 + paddsw m1, m3 ; t3 t2 + psubsw m3, m0, m2 ; t5 t4 + paddsw m0, m2 ; t1 t0 + psubsw m2, m5, m7 ; t14a t15a + paddsw m7, m5 ; t10a t11a + psubsw m5, m4, m6 ; t12a t13a + paddsw m4, m6 ; t8a t9a + ITX_MUL2X_PACK 3, 6, 9, 10, 1567, 3784, 5 ; t5a t4a + ITX_MUL2X_PACK 8, 6, 9, 10, 3784_m1567, 1567_3784, 52 ; t7a t6a + ITX_MUL2X_PACK 2, 6, 9, 10, 3784, 1567, 4 ; t15 t14 + ITX_MUL2X_PACK 5, 6, 9, 10, 3784_1567, 1567_m3784, 52 ; t13 t12 + vbroadcasti32x4 m12, [o(deint_shuf)] + paddsw m6, m4, m7 ; -out1 out14 + psubsw m4, m7 ; t10 t11 + psubsw m11, m3, m8 ; t7 t6 + paddsw m8, m3 ; out12 -out3 + psubsw m3, m0, m1 ; t3a t2a + paddsw m0, m1 ; -out15 out0 + paddsw m1, m2, m5 ; -out13 out2 + psubsw m5, m2 ; t15a t14a + pshufb m0, m12 + pshufb m6, m12 + pshufb m8, m12 + pshufb m1, m12 + shufps m7, m6, m0, q1032 ; out14 -out15 + shufps m0, m6, m0, q3210 ; -out1 out0 + punpcklqdq m6, m8, m1 ; out12 -out13 + punpckhqdq m1, m8, m1 ; -out3 out2 + ret + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + call m(iadst_16x16_internal_8bpc).main_pass1 + vpbroadcastd m10, [o(pw_m8192_8192)] + punpcklwd m8, m1, m0 ; m0 o0 m1 o1 m2 o2 m3 o3 + punpckhwd m9, m1, m0 ; n0 p0 n1 p1 n2 p2 n3 p3 + punpckhwd m1, m7, m6 ; a0 c0 a1 c1 a2 c2 a3 c3 + punpcklwd m7, m6 ; b0 d0 b1 d1 b2 d2 b3 d3 + punpcklwd m0, m1, m7 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhwd m1, m7 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpcklwd m6, m8, m9 ; m0 n0 o0 p0 m1 n1 o1 p1 + punpckhwd m7, m8, m9 ; m2 n2 o2 p2 m3 n3 o3 p3 + punpcklwd m8, m3, m2 ; i0 k0 i1 k1 i2 k2 i3 k3 + punpckhwd m9, m3, m2 ; j0 l0 j1 l1 j2 l2 j3 l3 + punpckhwd m3, m5, m4 ; e0 g0 e1 g1 e2 g2 e3 g3 + punpcklwd m5, m4 ; f0 h0 f1 h1 f2 h2 f3 h3 + punpcklwd m2, m3, m5 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhwd m3, m5 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpcklwd m4, m8, m9 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhwd m5, m8, m9 ; i2 j2 k2 l2 i3 j3 k3 l3 + jmp m(iadst_16x16_internal_8bpc).pass1_end +.pass2: + call m(iadst_16x16_internal_8bpc).main_pass2 + mova m10, [o(permD)] + psrlq m8, m10, 8 + psrlq m12, m10, 12 + psrlq m13, m10, 4 + mova m9, m8 + vpermi2q m8, m7, m5 ; 0 1 4 5 + vpermt2q m7, m12, m5 + vpermi2q m9, m6, m4 ; 2 3 6 7 + vpermt2q m6, m12, m4 + vpbroadcastd m12, [o(pw_2048)] + mov r3d, 0x00ff00ff + mova m11, m10 + vpermi2q m10, m3, m1 ; 8 9 12 13 + vpermt2q m3, m13, m1 + kmovd k1, r3d + vpermi2q m11, m2, m0 ; 10 11 14 15 + vpermt2q m2, m13, m0 + pxor m0, m0 + vpsubw m12{k1}, m0, m12 + pmulhrsw m0, m7, m12 + pmulhrsw m1, m6, m12 + pmulhrsw m4, m3, m12 + pmulhrsw m5, m2, m12 + jmp m(idct_16x16_internal_8bpc).end3 + +INV_TXFM_16X16_FN identity, dct +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_8bpc, 0, 6, 0, dst, stride, c, eob, tx2 + mova m8, [o(int16_perm)] + vpermb m1, m8, [cq+64*0] ; a0 b0 a1 b1 a2 b2 a3 b3 + vpermb m2, m8, [cq+64*1] ; c0 d0 c1 d1 c2 d2 c3 d3 + vpbroadcastd m0, [o(pw_1697x16)] + vpermb m3, m8, [cq+64*2] ; e0 f0 e1 f1 e2 f2 e3 f3 + vpermb m4, m8, [cq+64*3] ; g0 h0 g1 h1 g2 h2 g3 h3 + vpermb m5, m8, [cq+64*4] ; i0 j0 i1 j1 i2 j2 i3 j3 + vpermb m6, m8, [cq+64*5] ; k0 l0 k1 l1 k2 l2 k3 l3 + vpermb m7, m8, [cq+64*6] ; m0 n0 m1 n1 m2 n2 m3 n3 + vpermb m8, m8, [cq+64*7] ; o0 p0 o1 p1 o2 p2 o3 p3 + pmulhrsw m9, m0, m1 + pmulhrsw m10, m0, m2 + pmulhrsw m11, m0, m3 + pmulhrsw m12, m0, m4 + pmulhrsw m13, m0, m5 + pmulhrsw m14, m0, m6 + pmulhrsw m15, m0, m7 + pmulhrsw m0, m8 + REPX {psraw x, 1}, m9, m10, m11, m12 + pavgw m1, m9 + pavgw m2, m10 + pavgw m3, m11 + pavgw m4, m12 + REPX {psraw x, 1}, m13, m14, m15, m0 + pavgw m5, m13 + pavgw m6, m14 + pavgw m7, m15 + pavgw m8, m0 + punpckldq m0, m1, m2 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m1, m2 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m2, m3, m4 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m3, m4 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpckldq m4, m5, m6 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhdq m5, m6 ; i2 j2 k2 l2 i3 j3 k3 l3 + punpckldq m6, m7, m8 ; m0 n0 o0 p0 m1 n1 o1 p1 + punpckhdq m7, m8 ; m2 n2 o2 p2 m3 n3 o3 p3 + jmp tx2q +ALIGN function_align +.pass2: + vpbroadcastd m11, [o(pw_1697x16)] + pmulhrsw m12, m11, m0 + pmulhrsw m13, m11, m1 + pmulhrsw m14, m11, m2 + pmulhrsw m15, m11, m3 + pmulhrsw m8, m11, m4 + pmulhrsw m9, m11, m5 + pmulhrsw m10, m11, m6 + pmulhrsw m11, m7 + REPX {paddsw x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + paddsw m0, m12 + paddsw m1, m13 + paddsw m2, m14 + paddsw m3, m15 + paddsw m8, m4 + movu m4, [o(permD+2)] + paddsw m9, m5 + paddsw m6, m10 + paddsw m7, m11 + psrlq m12, m4, 4 + mova m5, m4 + mova m10, m4 + mova m11, m4 + vpermi2q m4, m0, m2 ; 8 9 12 13 + vpermt2q m0, m12, m2 ; 0 1 4 5 + vpermi2q m5, m1, m3 ; 10 11 14 15 + vpermt2q m1, m12, m3 ; 2 3 6 7 + vpermi2q m10, m8, m6 + vpermt2q m8, m12, m6 + vpermi2q m11, m9, m7 + vpermt2q m9, m12, m7 + jmp m(idct_16x16_internal_8bpc).end + +%macro ITX_UNPACK_MULHRSW 8 ; dst[1-2], src, tmp, coef[1-4] + vpbroadcastd m%4, [o(pw_%5_%6x8)] + punpcklwd m%1, m%3, m%3 + pmulhrsw m%1, m%4 + vpbroadcastd m%4, [o(pw_%7_%8x8)] + punpckhwd m%2, m%3, m%3 + pmulhrsw m%2, m%4 +%endmacro + +cglobal inv_txfm_add_dct_dct_8x32_8bpc, 4, 4, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + cmp eobd, 107 + jb .fast + mova m5, [cq+64*5] + mova m3, [cq+64*3] + mova m1, [cq+64*1] + mova m7, [cq+64*7] + mova m2, [cq+64*2] + mova m6, [cq+64*6] + mova m0, [cq+64*0] + mova m4, [cq+64*4] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + mova m8, [o(idct_8x32p)] + vpbroadcastd m9, [o(pw_8192)] + REPX {vpermb x, m8, x}, m0, m1, m2, m3, m4, m5, m6, m7 + punpckldq m8, m0, m1 ; ab + punpckhdq m0, m1 + punpckldq m1, m2, m3 ; cd + punpckhdq m2, m3 + punpckldq m3, m4, m5 ; ef + punpckhdq m4, m5 + punpckldq m5, m6, m7 ; gh + punpckhdq m6, m7 + REPX {pmulhrsw x, m9}, m8, m0, m1, m2, m3, m4, m5, m6 + punpcklqdq m18, m8, m1 ; 30 2 6 26 31 1 23 9 + punpckhqdq m14, m8, m1 ; 16 0 12 20 3 29 11 21 + punpcklqdq m21, m0, m2 ; 14 18 22 10 27 5 19 13 + punpckhqdq m15, m0, m2 ; 18 4 24 8 7 25 15 17 + punpcklqdq m20, m3, m5 + punpckhqdq m16, m3, m5 + punpcklqdq m19, m4, m6 + punpckhqdq m17, m4, m6 + vinserti32x4 ym8, ym18, xm20, 1 + vshufi32x4 ym1, ym18, ym20, 0x03 + vinserti32x4 ym9, ym14, xm16, 1 + vshufi32x4 ym3, ym14, ym16, 0x03 + vinserti32x4 ym0, ym21, xm19, 1 + vshufi32x4 ym5, ym21, ym19, 0x03 + vinserti32x4 ym7, ym15, xm17, 1 + vshufi32x4 ym6, ym15, ym17, 0x03 + call m(idct_8x16_internal_8bpc).main2 + psrlq m12, [o(permB)], 60 + vpermt2q m14, m12, m16 + vpermt2q m21, m12, m19 + vpermt2q m15, m12, m17 + vpermi2q m12, m18, m20 + vextracti32x8 ym16, m14, 1 + vextracti32x8 ym19, m21, 1 + vextracti32x8 ym17, m15, 1 + vextracti32x8 ym20, m12, 1 + call .main2 + jmp .end +.fast: ; right half is zero + mova m0, [o(int16_perm)] + mova ym2, [cq+64*4] + vinserti32x8 m2, [cq+64*0], 1 + mova ym3, [cq+64*6] + vinserti32x8 m3, [cq+64*2], 1 + mova ym4, [cq+64*3] + vinserti32x8 m4, [cq+64*5], 1 + mova ym5, [cq+64*7] + vinserti32x8 m5, [cq+64*1], 1 + REPX {vpermb x, m0, x}, m2, m3, m4, m5 + call m(idct_16x8_internal_8bpc).main2 + vbroadcasti32x4 m4, [o(int_shuf3)] + vbroadcasti32x4 m5, [o(int_shuf4)] + pshufb m2, m4 ; e0 f0 e2 f2 e1 f1 e3 f3 + pshufb m3, m5 ; g0 h0 g2 h2 g1 h1 g3 h3 + pshufb m0, m4 ; a0 b0 a2 b2 a1 b1 a3 b3 + pshufb m1, m5 ; c0 d0 c2 d2 c1 d1 c3 d3 + vpbroadcastd m4, [o(pw_8192)] + psrlq m5, [o(permB)], 60 + punpckldq m6, m2, m3 ; e0 f0 g0 h0 e2 f2 g2 h2 + punpckhdq m17, m2, m3 ; e1 f1 g1 h1 e3 f3 g3 h3 + punpckldq m2, m0, m1 ; a0 b0 c0 d0 a2 b2 c2 d2 + punpckhdq m16, m0, m1 ; a1 b1 c1 d1 a3 b3 c3 d3 + REPX {pmulhrsw x, m4}, m6, m17, m2, m16 + vinserti32x4 ym0, ym2, xm6, 1 ; 0 2 + vshufi32x4 ym1, ym2, ym6, 0x03 ; 4 6 + vinserti32x4 ym14, ym16, xm17, 1 ; 1 3 + vshufi32x4 ym15, ym16, ym17, 0x03 ; 5 7 + vpermt2q m2, m5, m6 ; 8 10 + vpermt2q m16, m5, m17 ; 9 11 + vextracti32x8 ym3, m2, 1 ; 12 14 + vextracti32x8 ym17, m16, 1 ; 13 15 + call m(idct_8x16_internal_8bpc).main_fast + call .main_fast +.end: + vpbroadcastd ym8, strided + pmulld ym8, [o(gather8d)] + call .main_end + lea r3, [dstq+strideq*4] + kxnorb k1, k1, k1 + lea r4, [dstq+strideq*8] + pxor m9, m9 + lea r1, [r3+strideq*8] + kmovb k2, k1 + vpgatherdq m12{k1}, [r0+ym8] + kmovb k1, k2 + vpgatherdq m13{k2}, [r3+ym8] + kmovb k2, k1 + vpgatherdq m14{k1}, [r4+ym8] + kmovb k1, k2 + vpgatherdq m15{k2}, [r1+ym8] + REPX {pmulhrsw x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 + REPX {mova [cq+64*x], m9}, 0, 1, 2, 3, 4, 5, 6, 7 + punpcklbw m11, m12, m9 + punpckhbw m12, m9 + paddw m0, m11 + paddw m1, m12 + packuswb m0, m1 + kmovb k2, k1 + vpscatterdq [r0+ym8]{k1}, m0 + punpcklbw m12, m13, m9 + punpckhbw m13, m9 + paddw m2, m12 + paddw m3, m13 + packuswb m2, m3 + kmovb k1, k2 + vpscatterdq [r3+ym8]{k2}, m2 + punpcklbw m13, m14, m9 + punpckhbw m14, m9 + paddw m4, m13 + paddw m5, m14 + packuswb m4, m5 + kmovb k2, k1 + vpscatterdq [r4+ym8]{k1}, m4 + punpcklbw m14, m15, m9 + punpckhbw m15, m9 + paddw m6, m14 + paddw m7, m15 + packuswb m6, m7 + vpscatterdq [r1+ym8]{k2}, m6 + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 32 + imul r6d, 181 + add r6d, 128+512 + sar r6d, 8+2 + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).dconly2 +INIT_YMM avx512icl +ALIGN function_align +cglobal_label .main_fast2 ; bottom three-quarters are zero + ITX_UNPACK_MULHRSW 12, 14, 14, 8, 201, 4091, m601, 4052 ; t16a, t31a, t23a, t24a + ITX_UNPACK_MULHRSW 21, 20, 15, 8, 995, 3973, m1380, 3857 ; t20a, t27a, t19a, t28a + mova m11, m12 + mova m17, m20 + mova m15, m21 + mova m16, m14 + jmp .main4 +ALIGN function_align +cglobal_label .main_fast ; bottom half is zero + ITX_UNPACK_MULHRSW 12, 14, 14, 8, 201, 4091, m601, 4052 ; t16a, t31a, t23a, t24a + ITX_UNPACK_MULHRSW 21, 15, 15, 8, 995, 3973, m1380, 3857 ; t20a, t27a, t19a, t28a + ITX_UNPACK_MULHRSW 20, 16, 16, 8, 1751, 3703, m2106, 3513 ; t18a, t29a, t21a, t26a + ITX_UNPACK_MULHRSW 19, 17, 17, 8, 2440, 3290, m2751, 3035 ; t22a, t25a, t17a, t30a + jmp .main3 +ALIGN function_align +cglobal_label .main + punpcklwd m12, m21, m14 ; in31 in1 + punpckhwd m14, m21 ; in3 in29 + punpcklwd m21, m20, m15 ; in27 in5 + punpckhwd m15, m20 ; in7 in25 + punpcklwd m20, m19, m16 ; in23 in9 + punpckhwd m16, m19 ; in11 in21 + punpcklwd m19, m18, m17 ; in19 in13 + punpckhwd m17, m18 ; in15 in17 +.main2: + ITX_MUL2X_PACK 12, 8, 9, 10, 201, 4091, 5 ; t16a, t31a + ITX_MUL2X_PACK 14, 8, 9, 10, 4052, 601, 5 ; t23a, t24a + ITX_MUL2X_PACK 21, 8, 9, 10, 995, 3973, 5 ; t20a, t27a + ITX_MUL2X_PACK 15, 8, 9, 10, 3857, 1380, 5 ; t19a, t28a + ITX_MUL2X_PACK 20, 8, 9, 10, 1751, 3703, 5 ; t18a, t29a + ITX_MUL2X_PACK 16, 8, 9, 10, 3513, 2106, 5 ; t21a, t26a + ITX_MUL2X_PACK 19, 8, 9, 10, 2440, 3290, 5 ; t22a, t25a + ITX_MUL2X_PACK 17, 8, 9, 10, 3035, 2751, 5 ; t17a, t30a +.main3: + psubsw m11, m12, m17 ; t17 t30 + paddsw m12, m17 ; t16 t31 + psubsw m17, m15, m20 ; t18 t29 + paddsw m20, m15 ; t19 t28 + psubsw m15, m21, m16 ; t21 t26 + paddsw m21, m16 ; t20 t27 + psubsw m16, m14, m19 ; t22 t25 + paddsw m14, m19 ; t23 t24 +.main4: + ITX_MUL2X_PACK 11, 18, 19, 10, 799, 4017, 5 ; t17a t30a + ITX_MUL2X_PACK 17, 18, 19, 10, m4017, 799, 5 ; t18a t29a + ITX_MUL2X_PACK 15, 18, 19, 10, 3406, 2276, 5 ; t21a t26a + ITX_MUL2X_PACK 16, 18, 19, 10, m2276, 3406, 5 ; t22a t25a + vpbroadcastd m8, [o(pw_m3784_1567)] + psubsw m19, m12, m20 ; t19a t28a + paddsw m20, m12 ; t16a t31a + psubsw m12, m14, m21 ; t20a t27a + paddsw m14, m21 ; t23a t24a + psubsw m21, m11, m17 ; t18 t29 + paddsw m11, m17 ; t17 t30 + psubsw m17, m16, m15 ; t21 t26 + paddsw m16, m15 ; t22 t25 + ITX_MUL2X_PACK 21, 18, 15, 10, 1567_3784, 8, 20 ; t18a t29a + ITX_MUL2X_PACK 19, 18, 15, 10, 1567_3784, 8, 20 ; t19 t28 + ITX_MUL2X_PACK 12, 18, 15, 10, 8, m1567_m3784, 36 ; t20 t27 + ITX_MUL2X_PACK 17, 18, 15, 10, 8, m1567_m3784, 36 ; t21a t26a + vbroadcasti32x4 m18, [o(deint_shuf)] + vpbroadcastd m8, [o(pw_m2896_2896)] + vpbroadcastd m9, [o(pw_2896_2896)] + psubsw m15, m20, m14 ; t23 t24 + paddsw m20, m14 ; t16 t31 + psubsw m14, m11, m16 ; t22a t25a + paddsw m11, m16 ; t17a t30a + psubsw m16, m21, m17 ; t21 t26 + paddsw m21, m17 ; t18 t29 + psubsw m17, m19, m12 ; t20a t27a + paddsw m19, m12 ; t19a t28a + REPX {pshufb x, m18}, m20, m11, m21, m19 + ITX_MUL2X_PACK 15, 18, 12, 10, 8, 9, 8 ; t23a t22a + ITX_MUL2X_PACK 14, 13, 15, 10, 8, 9, 8 ; t22 t25 + packssdw m18, m13 ; t23a t22 + packssdw m12, m15 ; t24a t25 + ITX_MUL2X_PACK 16, 13, 15, 10, 8, 9, 8 ; t21a t26a + ITX_MUL2X_PACK 17, 16, 14, 10, 8, 9, 8 ; t20 t27 + packssdw m16, m13 ; t20 t21a + packssdw m14, m15 ; t27 t26a + punpcklqdq m13, m19, m21 ; t19a t18 + punpckhqdq m19, m21 ; t28a t29 + punpcklqdq m21, m20, m11 ; t16 t17a + punpckhqdq m20, m11 ; t31 t30a +INIT_ZMM avx512icl + mova m15, [o(permA)] + ret +cglobal_label .main_end + vpbroadcastd m10, [o(pw_2048)] + vpermt2q m0, m15, m1 ; t0 t1 t2 t3 + vpermt2q m20, m15, m19 ; t31 t30a t29 t28a + vpermt2q m2, m15, m3 ; t4 t5 t6 t7 + vpermt2q m14, m15, m12 ; t27 t26a t25 t24a + vpermt2q m4, m15, m5 ; t8 t9 t10 t11 + vpermt2q m18, m15, m16 ; t23a t22 t21a t20 + vpermt2q m6, m15, m7 ; t12 t13 t14 t15 + vpermt2q m13, m15, m21 ; t19a t18 t17a t16 + psubsw m7, m0, m20 ; out31 out30 out29 out28 + paddsw m0, m20 ; out0 out1 out2 out3 + psubsw m5, m2, m14 ; out27 out26 out25 out24 + paddsw m2, m14 ; out4 out5 out6 out7 + psubsw m3, m4, m18 ; out23 out22 out21 out20 + paddsw m4, m18 ; out8 out9 out10 out11 + psubsw m1, m6, m13 ; out19 out18 out17 out16 + paddsw m6, m13 ; out12 out13 out14 out15 + vzeroupper + ret + +%macro LOAD_PACKED_16X2 3 ; dst, row[1-2] + vbroadcasti32x4 ym%1, [cq+16*%2] + vbroadcasti32x4 ym8, [cq+16*%3] + shufpd ym%1, ym8, 0x0c +%endmacro + +cglobal inv_txfm_add_dct_dct_32x8_8bpc, 4, 4, 0, dst, stride, c, eob +%undef cmp + test eobd, eobd + jz .dconly + lea r5, [o_base] + LOAD_PACKED_16X2 0, 0, 2 ; in0 in2 + LOAD_PACKED_16X2 1, 4, 6 ; in4 in6 + LOAD_PACKED_16X2 2, 8, 10 ; in8 in10 + LOAD_PACKED_16X2 3, 12, 14 ; in12 in14 + LOAD_PACKED_16X2 14, 1, 3 ; in1 in3 + LOAD_PACKED_16X2 15, 5, 7 ; in5 in7 + LOAD_PACKED_16X2 16, 9, 11 ; in9 in11 + LOAD_PACKED_16X2 17, 13, 15 ; in13 in15 + pxor m4, m4 + REPX {mova [cq+64*x], m4}, 0, 1, 2, 3 + cmp eobd, 107 + jb .fast + LOAD_PACKED_16X2 4, 16, 18 ; in16 in18 + LOAD_PACKED_16X2 5, 20, 22 ; in20 in22 + LOAD_PACKED_16X2 6, 24, 26 ; in24 in26 + LOAD_PACKED_16X2 7, 28, 30 ; in28 in30 + call m(idct_8x16_internal_8bpc).main + LOAD_PACKED_16X2 18, 19, 17 ; in19 in17 + LOAD_PACKED_16X2 19, 23, 21 ; in23 in21 + LOAD_PACKED_16X2 20, 27, 25 ; in27 in25 + LOAD_PACKED_16X2 21, 31, 29 ; in31 in29 + pxor m8, m8 + REPX {mova [cq+64*x], m8}, 4, 5, 6, 7 + call m(inv_txfm_add_dct_dct_8x32_8bpc).main + jmp .pass2 +.fast: ; bottom half is zero + mova ym5, ym4 + mova ym6, ym4 + mova ym7, ym4 + call m(idct_8x16_internal_8bpc).main + call m(inv_txfm_add_dct_dct_8x32_8bpc).main_fast +.pass2: + vpbroadcastd m10, [o(pw_8192)] + vpermt2q m0, m15, m4 ; t0 t1 t9 t8 + vpermt2q m20, m15, m18 ; t31 t30a t23a t22 + vpermt2q m3, m15, m7 ; t7 t6 t14 t15 + vpermt2q m12, m15, m21 ; t25 t24a t17a t16 + vpermt2q m2, m15, m6 ; t4 t5 t13 t12 + vpermt2q m14, m15, m13 ; t23a t22 t21a t20 + vpermt2q m1, m15, m5 ; t3 t2 t10 t11 + vpermt2q m19, m15, m16 ; t27 t26a t19a t18 + psubsw m8, m0, m20 ; out31 out30 out22 out23 + paddsw m0, m20 ; out0 out1 out9 out8 + paddsw m6, m3, m12 ; out7 out6 out14 out15 + psubsw m3, m12 ; out24 out25 out17 out16 + psubsw m5, m2, m14 ; out27 out26 out18 out19 + paddsw m4, m2, m14 ; out4 out5 out13 out12 + psubsw m7, m1, m19 ; out28 out29 out21 out20 + paddsw m2, m1, m19 ; out3 out2 out10 out11 + vzeroupper + vshufi32x4 m1, m0, m3, q1221 ; out1 out9 out17 out25 + vshufi32x4 m0, m3, q0330 ; out0 out8 out16 out24 + vshufi32x4 m3, m2, m5, q0330 ; out3 out11 out19 out27 + vshufi32x4 m2, m5, q1221 ; out2 out10 out18 out26 + vshufi32x4 m5, m4, m7, q1221 ; out5 out13 out21 out29 + vshufi32x4 m4, m7, q0330 ; out4 out12 out20 out28 + vshufi32x4 m7, m6, m8, q0330 ; out7 out15 out23 out31 + vshufi32x4 m6, m8, q1221 ; out6 out14 out22 out30 + REPX {pmulhrsw x, m10}, m0, m1, m2, m3, m4, m5, m6, m7 + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_8x8 + call .main + vpbroadcastd m8, [o(pw_2048)] + REPX {pmulhrsw x, m8}, m0, m1, m2, m3, m4, m5, m6, m7 + lea r2, [strideq*3] + lea r3, [dstq+strideq*4] + movshdup m12, [o(permD)] + pmovzxbw m8, [dstq+strideq*0] + pmovzxbw m9, [dstq+strideq*1] + pmovzxbw m10, [dstq+strideq*2] + pmovzxbw m11, [dstq+r2 ] + paddw m0, m8 + paddw m1, m9 + paddw m2, m10 + paddw m3, m11 + pmovzxbw m8, [r3+strideq*0] + pmovzxbw m9, [r3+strideq*1] + pmovzxbw m10, [r3+strideq*2] + pmovzxbw m11, [r3+r2 ] + paddw m4, m8 + paddw m5, m9 + paddw m6, m10 + paddw m7, m11 + packuswb m0, m1 + packuswb m2, m3 + vpermq m0, m12, m0 + vpermq m2, m12, m2 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym2 + vextracti32x8 [dstq+r2 ], m2, 1 + packuswb m4, m5 + packuswb m6, m7 + vpermq m4, m12, m4 + vpermq m6, m12, m6 + mova [r3+strideq*0], ym4 + vextracti32x8 [r3+strideq*1], m4, 1 + mova [r3+strideq*2], ym6 + vextracti32x8 [r3+r2 ], m6, 1 + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 8 +.dconly2: + imul r6d, 181 + add r6d, 128+512 + sar r6d, 8+2 +.dconly3: + imul r6d, 181 + add r6d, 128+2048 + sar r6d, 8+4 + pxor m2, m2 + vpbroadcastw m3, r6d +.dconly_loop: + mova ym1, [dstq+strideq*0] + vinserti32x8 m1, [dstq+strideq*1], 1 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + paddw m0, m3 + paddw m1, m3 + packuswb m0, m1 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub r3d, 2 + jg .dconly_loop + RET +ALIGN function_align +cglobal_label .main + vpbroadcastd m10, [o(pd_2048)] +.main2: + ITX_MULSUB_2W 5, 3, 8, 9, 10, 3406, 2276 ; t5a, t6a + ITX_MULSUB_2W 1, 7, 8, 9, 10, 799, 4017 ; t4a, t7a + ITX_MULSUB_2W 2, 6, 8, 9, 10, 1567, 3784 ; t2, t3 + vpbroadcastd m11, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + ITX_MULSUB_2W 0, 4, 8, 9, 10, 11, 12 ; t1, t0 +.main3: + paddsw m8, m1, m5 ; t4 + psubsw m1, m5 ; t5a + paddsw m9, m7, m3 ; t7 + psubsw m7, m3 ; t6a + ITX_MULSUB_2W 7, 1, 3, 5, 10, 11, 12 ; t5, t6 + psubsw m5, m0, m2 ; dct4 out2 + paddsw m2, m0 ; dct4 out1 + paddsw m0, m4, m6 ; dct4 out0 + psubsw m4, m6 ; dct4 out3 + psubsw m6, m2, m1 ; out6 + paddsw m1, m2 ; out1 + paddsw m2, m5, m7 ; out2 + psubsw m5, m7 ; out5 + psubsw m7, m0, m9 ; out7 + paddsw m0, m9 ; out0 + paddsw m3, m4, m8 ; out3 + psubsw m4, m8 ; out4 + ret + +cglobal inv_txfm_add_identity_identity_8x32_8bpc, 3, 5, 0, dst, stride, c + vpbroadcastd m7, [pw_5] + paddsw m0, m7, [cq+64*0] + paddsw m1, m7, [cq+64*1] + vpbroadcastd ym9, strided + paddsw m2, m7, [cq+64*2] + paddsw m3, m7, [cq+64*3] + paddsw m4, m7, [cq+64*4] + paddsw m5, m7, [cq+64*5] + paddsw m6, m7, [cq+64*6] + paddsw m7, [cq+64*7] + pmulld ym14, ym9, [pd_0to15] + lea r3, [dstq+strideq*1] + lea r4, [dstq+strideq*2] + kxnorb k1, k1, k1 + pxor m13, m13 + add r1, r4 ; dstq+strideq*3 + kmovb k2, k1 + vpgatherdq m9{k1}, [r0+ym14*4] + kmovb k1, k2 + vpgatherdq m10{k2}, [r3+ym14*4] + kmovb k2, k1 + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_8x8 + REPX {psraw x, 3}, m0, m1, m2, m3, m4, m5, m6, m7 + vpgatherdq m11{k1}, [r4+ym14*4] + kmovb k1, k2 + vpgatherdq m12{k2}, [r1+ym14*4] + REPX {mova [cq+64*x], m13}, 0, 1, 2, 3, 4, 5, 6, 7 + punpcklbw m8, m9, m13 ; 0 8 16 24 + punpckhbw m9, m13 ; 4 12 20 28 + paddw m0, m8 + paddw m4, m9 + packuswb m0, m4 + kmovb k2, k1 + vpscatterdq [r0+ym14*4]{k1}, m0 + punpcklbw m8, m10, m13 ; 1 9 17 25 + punpckhbw m10, m13 ; 5 13 21 29 + paddw m1, m8 + paddw m5, m10 + packuswb m1, m5 + kmovb k1, k2 + vpscatterdq [r3+ym14*4]{k2}, m1 + punpcklbw m8, m11, m13 ; 2 10 18 26 + punpckhbw m11, m13 ; 6 14 22 30 + paddw m2, m8 + paddw m6, m11 + packuswb m2, m6 + kmovb k2, k1 + vpscatterdq [r4+ym14*4]{k1}, m2 + punpcklbw m8, m12, m13 ; 3 11 19 27 + punpckhbw m12, m13 ; 7 15 23 31 + paddw m3, m8 + paddw m7, m12 + packuswb m3, m7 + vpscatterdq [r1+ym14*4]{k2}, m3 + RET + +cglobal inv_txfm_add_identity_identity_32x8_8bpc, 3, 5, 0, dst, stride, c + vpbroadcastd m0, [pw_4096] + pmulhrsw m3, m0, [cq+64*0] + pmulhrsw m4, m0, [cq+64*4] + pmulhrsw m6, m0, [cq+64*1] + pmulhrsw m5, m0, [cq+64*5] + pmulhrsw m7, m0, [cq+64*2] + pmulhrsw m2, m0, [cq+64*6] + pmulhrsw m8, m0, [cq+64*3] + pmulhrsw m0, [cq+64*7] + mova m13, [int8_permA] + lea r3, [strideq*3] + lea r4, [dstq+strideq*4] + punpckldq m1, m3, m4 + punpckhdq m3, m4 + punpckldq m4, m6, m5 + punpckhdq m6, m5 + punpckldq m5, m7, m2 + punpckhdq m7, m2 + punpckldq m2, m8, m0 + punpckhdq m8, m0 + mova ym9, [dstq+strideq*0] + vinserti32x8 m9, [dstq+strideq*2], 1 + mova ym10, [dstq+strideq*1] + vinserti32x8 m10, [dstq+r3 ], 1 + mova ym11, [r4+strideq*0] + vinserti32x8 m11, [r4+strideq*2], 1 + mova ym12, [r4+strideq*1] + vinserti32x8 m12, [r4+r3 ], 1 + REPX {vpermb x, m13, x}, m1, m4, m5, m2, m3, m6, m7, m8 + pxor m13, m13 + REPX {mova [cq+64*x], m13}, 0, 1, 2, 3, 4, 5, 6, 7 + punpcklqdq m0, m1, m4 ; a0 a2 c0 c2 + punpckhqdq m1, m4 ; b0 b2 d0 d2 + punpcklqdq m4, m5, m2 ; a1 a3 c1 c3 + punpckhqdq m5, m2 ; b1 b3 d1 d3 + punpcklqdq m2, m3, m6 ; e0 e2 g0 g2 + punpckhqdq m3, m6 ; f0 f2 h0 h2 + punpcklqdq m6, m7, m8 ; e1 e3 g1 g3 + punpckhqdq m7, m8 ; f1 f3 h1 h3 + punpcklbw m8, m9, m13 + punpckhbw m9, m13 + paddw m0, m8 + paddw m4, m9 + packuswb m0, m4 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*2], m0, 1 + punpcklbw m8, m10, m13 + punpckhbw m10, m13 + paddw m1, m8 + paddw m5, m10 + packuswb m1, m5 + mova [dstq+strideq*1], ym1 + vextracti32x8 [dstq+r3 ], m1, 1 + punpcklbw m8, m11, m13 + punpckhbw m11, m13 + paddw m2, m8 + paddw m6, m11 + packuswb m2, m6 + mova [r4+strideq*0], ym2 + vextracti32x8 [r4+strideq*2], m2, 1 + punpcklbw m8, m12, m13 + punpckhbw m12, m13 + paddw m3, m8 + paddw m7, m12 + packuswb m3, m7 + mova [r4+strideq*1], ym3 + vextracti32x8 [r4+r3 ], m3, 1 + RET + +%macro IDCT_16x32_END 3 ; src[1-2], row + mova xm8, [dstq+strideq*0] + vinserti32x4 ym8, [dstq+strideq*1], 1 + mova xm9, [dstq+r3 ] + vinserti32x4 ym9, [dstq+strideq*2], 1 + pmulhrsw m%1, m10 + pmulhrsw m%2, m10 + vpermb m8, m11, m8 + vpermb m9, m11, m9 + mova [cq+64*(%3*2+0)], m13 + mova [cq+64*(%3*2+1)], m13 + paddw m8, m%1 + paddw m9, m%2 + packuswb m8, m9 + vpermd m8, m12, m8 + mova [dstq+strideq*0], xm8 + vextracti32x4 [dstq+strideq*1], ym8, 1 + vextracti32x4 [dstq+strideq*2], m8, 2 + vextracti32x4 [dstq+r3 ], m8, 3 +%if %1 != 20 + lea dstq, [dstq+strideq*4] +%endif +%endmacro + +cglobal inv_txfm_add_dct_dct_16x32_8bpc, 4, 4, 22, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + vpbroadcastd m15, [o(pw_2896x8)] + cmp eobd, 151 + jb .fast + pmulhrsw m5, m15, [cq+64*10] + pmulhrsw m3, m15, [cq+64* 6] + pmulhrsw m1, m15, [cq+64* 2] + pmulhrsw m7, m15, [cq+64*14] + pmulhrsw m2, m15, [cq+64* 4] + pmulhrsw m6, m15, [cq+64*12] + pmulhrsw m0, m15, [cq+64* 0] + pmulhrsw m4, m15, [cq+64* 8] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + pmulhrsw m14, m15, [cq+64* 1] + pmulhrsw m21, m15, [cq+64*15] + pmulhrsw m18, m15, [cq+64* 9] + pmulhrsw m17, m15, [cq+64* 7] + pmulhrsw m16, m15, [cq+64* 5] + pmulhrsw m19, m15, [cq+64*11] + pmulhrsw m20, m15, [cq+64*13] + pmulhrsw m15, [cq+64* 3] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova m8, [o(idct_16x32p)] + vpbroadcastd m9, [o(pw_16384)] + REPX {vpermb x, m8, x}, m0, m1, m2, m3, m4, m5, m6, m7, \ + m14, m15, m16, m17, m18, m19, m20, m21 + punpckldq m8, m0, m1 + punpckhdq m0, m1 + punpckldq m1, m2, m3 + punpckhdq m2, m3 + REPX {pmulhrsw x, m9}, m8, m0, m1, m2 + punpckldq m3, m4, m5 + punpckhdq m4, m5 + punpckldq m5, m6, m7 + punpckhdq m6, m7 + REPX {pmulhrsw x, m9}, m3, m4, m5, m6 + punpckldq m7, m14, m15 + punpckhdq m14, m15 + punpckldq m15, m16, m17 + punpckhdq m16, m17 + REPX {pmulhrsw x, m9}, m7, m14, m15, m16 + punpckldq m17, m18, m19 + punpckhdq m18, m19 + punpckldq m19, m20, m21 + punpckhdq m20, m21 + REPX {pmulhrsw x, m9}, m17, m18, m19, m20 + punpcklqdq m21, m8, m1 + punpckhqdq m8, m1 + punpcklqdq m1, m0, m2 + punpckhqdq m0, m2 + punpcklqdq m2, m3, m5 + punpckhqdq m3, m5 + punpcklqdq m5, m4, m6 + punpckhqdq m4, m6 + punpcklqdq m6, m7, m15 + punpckhqdq m7, m15 + punpcklqdq m15, m14, m16 + punpckhqdq m14, m16 + punpcklqdq m16, m17, m19 + punpckhqdq m17, m19 + punpcklqdq m19, m18, m20 + punpckhqdq m18, m20 + vinserti32x8 m20, m21, ym2, 1 + vshufi32x4 m21, m2, q3232 + vinserti32x8 m2, m8, ym3, 1 + vshufi32x4 m8, m3, q3232 + vinserti32x8 m3, m1, ym5, 1 + vshufi32x4 m1, m5, q3232 + vinserti32x8 m5, m0, ym4, 1 + vshufi32x4 m0, m4, q3232 + vinserti32x8 m4, m6, ym16, 1 + vshufi32x4 m6, m16, q3232 + vinserti32x8 m16, m7, ym17, 1 + vshufi32x4 m7, m17, q3232 + vinserti32x8 m17, m15, ym19, 1 + vshufi32x4 m15, m19, q3232 + vinserti32x8 m19, m14, ym18, 1 + vshufi32x4 m14, m18, q3232 + vshufi32x4 m18, m21, m6, q3131 ; 27 5 + vshufi32x4 m21, m6, q2020 ; 31 1 + vshufi32x4 m6, m8, m7, q2020 ; 24 8 + vshufi32x4 m8, m7, q3131 ; 30 2 + vshufi32x4 m7, m1, m15, q2020 ; 28 4 + vshufi32x4 m1, m15, q3131 ; 6 26 + vshufi32x4 m15, m0, m14, q2020 ; 7 25 + vshufi32x4 m0, m14, q3131 ; 14 18 + vshufi32x4 m14, m20, m4, q2020 ; 3 29 + vshufi32x4 m20, m4, q3131 ; 23 9 + vshufi32x4 m9, m3, m17, q2020 ; 16 0 + vshufi32x4 m3, m17, q3131 ; 12 20 + vshufi32x4 m17, m5, m19, q2020 ; 15 17 + vshufi32x4 m5, m19, q3131 ; 22 10 + vshufi32x4 m19, m2, m16, q2020 ; 19 13 + vshufi32x4 m16, m2, m16, q3131 ; 11 21 + call m(idct_16x16_internal_8bpc).main3 + call .main_oddhalf + jmp .pass2 +.fast: ; right half is zero + mova ym8, [cq+64*15] + vinserti32x8 m8, [cq+64* 1], 1 + mova m2, [o(int16_perm)] + mova ym9, [cq+64* 8] + vinserti32x8 m9, [cq+64* 0], 1 + mova ym0, [cq+64* 7] + vinserti32x8 m0, [cq+64* 9], 1 + mova ym7, [cq+64*14] + vinserti32x8 m7, [cq+64* 2], 1 + mova ym1, [cq+64* 3] + vinserti32x8 m1, [cq+64*13], 1 + mova ym3, [cq+64* 6] + vinserti32x8 m3, [cq+64*10], 1 + mova ym5, [cq+64*11] + vinserti32x8 m5, [cq+64* 5], 1 + mova ym6, [cq+64*12] + vinserti32x8 m6, [cq+64* 4], 1 + REPX {pmulhrsw x, m15}, m8, m9, m0, m7, m1, m3, m5, m6 + REPX {vpermb x, m2, x}, m8, m9, m0, m7, m1, m3, m5, m6 + call m(idct_16x16_internal_8bpc).main2 + vbroadcasti32x4 m8, [o(int_shuf3)] + vbroadcasti32x4 m9, [o(int_shuf4)] + vpbroadcastd m11, [o(pw_16384)] + pshufb m0, m8 + pshufb m1, m9 + pshufb m2, m8 + pshufb m3, m9 + REPX {pmulhrsw x, m11}, m0, m1, m2, m3 + pshufb m4, m8 + pshufb m5, m9 + pshufb m6, m8 + pshufb m7, m9 + REPX {pmulhrsw x, m11}, m4, m5, m6, m7 + punpckhdq m17, m0, m1 + punpckldq m0, m1 + punpckhdq m16, m2, m3 + punpckldq m2, m3 + punpckhdq m18, m4, m5 + punpckldq m4, m5 + punpckhdq m5, m6, m7 + punpckldq m6, m7 + vinserti32x8 m1, m0, ym2, 1 + vshufi32x4 m3, m0, m2, q3232 + vinserti32x8 m2, m4, ym6, 1 + vshufi32x4 m4, m6, q3232 + vinserti32x8 m15, m17, ym16, 1 + vshufi32x4 m17, m16, q3232 + vinserti32x8 m16, m18, ym5, 1 + vshufi32x4 m18, m5, q3232 + vshufi32x4 m0, m1, m2, q2020 ; 0 2 + vshufi32x4 m1, m2, q3131 ; 4 6 + vshufi32x4 m2, m3, m4, q2020 ; 8 10 + vshufi32x4 m3, m4, q3131 ; 12 14 + vshufi32x4 m14, m15, m16, q2020 ; 1 3 + vshufi32x4 m15, m16, q3131 ; 5 7 + vshufi32x4 m16, m17, m18, q2020 ; 9 11 + vshufi32x4 m17, m18, q3131 ; 13 15 + pxor m6, m6 + punpckhwd m8, m0, m0 + punpcklwd m9, m6, m0 + punpckhwd m0, m3, m3 + punpckhwd m5, m2, m2 + punpcklwd m7, m1, m1 + punpckhwd m1, m1 + punpcklwd m3, m3 + punpcklwd m6, m2 + call m(idct_16x16_internal_8bpc).main_fast5 + punpcklwd m21, m14, m14 + punpckhwd m14, m14 + punpcklwd m18, m15, m15 + punpckhwd m15, m15 + punpcklwd m20, m16, m16 + punpckhwd m16, m16 + punpcklwd m19, m17, m17 + punpckhwd m17, m17 + call .main_oddhalf_fast +.pass2: + vpbroadcastd m10, [o(pw_2048)] + mova m11, [o(end_16x32p)] + lea r3, [strideq*3] + pxor m13, m13 + psrld m12, m11, 8 + IDCT_16x32_END 0, 1, 0 + IDCT_16x32_END 2, 3, 1 + IDCT_16x32_END 4, 5, 2 + IDCT_16x32_END 6, 7, 3 + IDCT_16x32_END 14, 15, 4 + IDCT_16x32_END 16, 17, 5 + IDCT_16x32_END 18, 19, 6 + IDCT_16x32_END 20, 21, 7 + RET +ALIGN function_align +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_16x8_8bpc).dconly +ALIGN function_align +cglobal_label .main_oddhalf_fast2 ; bottom three-quarters are zero + vpbroadcastd m8, [o(pw_201_4091x8)] + vpbroadcastd m20, [o(pw_m1380_3857x8)] + vpbroadcastd m9, [o(pw_995_3973x8)] + vpbroadcastd m16, [o(pw_m601_4052x8)] + pmulhrsw m21, m8 ; t16a, t31a + pmulhrsw m20, m15 ; t19a, t28a + pmulhrsw m18, m9 ; t20a, t27a + pmulhrsw m14, m16 ; t23a, t24a + mova m8, m21 + mova m17, m20 + mova m15, m18 + mova m16, m14 + jmp .main3 +ALIGN function_align +cglobal_label .main_oddhalf_fast ; bottom half is zero + vpbroadcastd m8, [o(pw_201_4091x8)] + vpbroadcastd m9, [o(pw_m2751_3035x8)] + vpbroadcastd m11, [o(pw_1751_3703x8)] + vpbroadcastd m12, [o(pw_m1380_3857x8)] + pmulhrsw m21, m8 ; t16a, t31a + vpbroadcastd m8, [o(pw_995_3973x8)] + pmulhrsw m17, m9 ; t17a, t30a + vpbroadcastd m9, [o(pw_m2106_3513x8)] + pmulhrsw m20, m11 ; t18a, t29a + vpbroadcastd m11, [o(pw_2440_3290x8)] + pmulhrsw m15, m12 ; t19a, t28a + vpbroadcastd m12, [o(pw_m601_4052x8)] + pmulhrsw m18, m8 ; t20a, t27a + pmulhrsw m16, m9 ; t21a, t26a + pmulhrsw m19, m11 ; t22a, t25a + pmulhrsw m14, m12 ; t23a, t24a + jmp .main2 +ALIGN function_align +cglobal_label .main_oddhalf + ITX_MUL2X_PACK 21, 8, 9, 10, 201, 4091, 5 ; t16a, t31a + ITX_MUL2X_PACK 17, 8, 9, 10, 3035, 2751, 5 ; t17a, t30a + ITX_MUL2X_PACK 20, 8, 9, 10, 1751, 3703, 5 ; t18a, t29a + ITX_MUL2X_PACK 15, 8, 9, 10, 3857, 1380, 5 ; t19a, t28a + ITX_MUL2X_PACK 18, 8, 9, 10, 995, 3973, 5 ; t20a, t27a + ITX_MUL2X_PACK 16, 8, 9, 10, 3513, 2106, 5 ; t21a, t26a + ITX_MUL2X_PACK 19, 8, 9, 10, 2440, 3290, 5 ; t22a, t25a + ITX_MUL2X_PACK 14, 8, 9, 10, 4052, 601, 5 ; t23a, t24a +.main2: + psubsw m8, m21, m17 ; t17 t30 + paddsw m21, m17 ; t16 t31 + psubsw m17, m15, m20 ; t18 t29 + paddsw m20, m15 ; t19 t28 + psubsw m15, m18, m16 ; t21 t26 + paddsw m18, m16 ; t20 t27 + psubsw m16, m14, m19 ; t22 t25 + paddsw m14, m19 ; t23 t24 +.main3: + ITX_MUL2X_PACK 8, 9, 19, 10, 799, 4017, 5 ; t17a t30a + ITX_MUL2X_PACK 17, 9, 19, 10, m4017, 799, 5 ; t18a t29a + ITX_MUL2X_PACK 15, 9, 19, 10, 3406, 2276, 5 ; t21a t26a + ITX_MUL2X_PACK 16, 9, 19, 10, m2276, 3406, 5 ; t22a t25a + vpbroadcastd m11, [o(pw_m3784_1567)] + psubsw m19, m21, m20 ; t19a t28a + paddsw m21, m20 ; t16a t31a + psubsw m20, m14, m18 ; t20a t27a + paddsw m14, m18 ; t23a t24a + psubsw m18, m8, m17 ; t18 t29 + paddsw m8, m17 ; t17 t30 + psubsw m17, m16, m15 ; t21 t26 + paddsw m15, m16 ; t22 t25 + ITX_MUL2X_PACK 18, 9, 16, 10, 1567_3784, 11, 20 ; t18a t29a + ITX_MUL2X_PACK 19, 9, 16, 10, 1567_3784, 11, 20 ; t19 t28 + ITX_MUL2X_PACK 20, 9, 16, 10, 11, m1567_m3784, 36 ; t20 t27 + ITX_MUL2X_PACK 17, 9, 16, 10, 11, m1567_m3784, 36 ; t21a t26a + vbroadcasti32x4 m9, [o(deint_shuf)] + psubsw m16, m21, m14 ; t23 t24 + paddsw m14, m21 ; t16 t31 + psubsw m21, m8, m15 ; t22a t25a + paddsw m15, m8 ; t17a t30a + psubsw m8, m18, m17 ; t21 t26 + paddsw m18, m17 ; t18 t29 + paddsw m17, m19, m20 ; t19a t28a + psubsw m19, m20 ; t20a t27a + vpbroadcastd m11, [o(pw_m2896_2896)] + vpbroadcastd m12, [o(pw_2896_2896)] + REPX {pshufb x, m9}, m14, m15, m18, m17 + mova m9, m10 + vpdpwssd m9, m16, m11 + mova m20, m10 + vpdpwssd m20, m21, m11 + psrad m9, 12 + psrad m20, 12 + packssdw m9, m20 ; t23a t22 + mova m20, m10 + vpdpwssd m20, m16, m12 + mova m16, m10 + vpdpwssd m16, m21, m12 + psrad m20, 12 + psrad m16, 12 + packssdw m16, m20, m16 ; t24a t25 + ITX_MUL2X_PACK 8, 21, 20, 10, 11, 12, 8 ; t21a t26a + ITX_MUL2X_PACK 19, 8, 11, 10, 11, 12, 8 ; t20 t27 + packssdw m11, m20 ; t27 t26a + packssdw m8, m21 ; t20 t21a + punpcklqdq m20, m14, m15 ; t16 t17a + punpckhqdq m14, m15 ; t31 t30a + punpckhqdq m15, m17, m18 ; t28a t29 + punpcklqdq m17, m18 ; t19a t18 + psubsw m21, m0, m14 ; out31 out30 + paddsw m0, m14 ; out0 out1 + psubsw m14, m7, m20 ; out16 out17 + paddsw m7, m20 ; out15 out14 + psubsw m20, m1, m15 ; out28 out29 + paddsw m1, m15 ; out3 out2 + psubsw m15, m6, m17 ; out19 out18 + paddsw m6, m17 ; out12 out13 + psubsw m17, m4, m9 ; out23 out22 + paddsw m4, m9 ; out8 out9 + psubsw m18, m3, m16 ; out24 out25 + paddsw m3, m16 ; out7 out6 + psubsw m16, m5, m8 ; out20 out21 + paddsw m5, m8 ; out11 out10 + psubsw m19, m2, m11 ; out27 out26 + paddsw m2, m11 ; out4 out5 + ret + +cglobal inv_txfm_add_dct_dct_32x16_8bpc, 4, 6, 22, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + mova m21, [o(permB)] + vpermq m1, m21, [cq+64* 0] ; 0 1 + vpermq m14, m21, [cq+64* 1] ; 2 3 + vpermq m20, m21, [cq+64* 2] ; 4 5 + vpermq m15, m21, [cq+64* 3] ; 6 7 + vpbroadcastd m8, [o(pw_2896x8)] + vpermq m2, m21, [cq+64* 4] ; 8 9 + vpermq m16, m21, [cq+64* 5] ; 10 11 + vpermq m3, m21, [cq+64* 6] ; 12 13 + vpermq m17, m21, [cq+64* 7] ; 14 15 + REPX {pmulhrsw x, m8}, m1, m14, m20, m15, m2, m16, m3, m17 + pxor m12, m12 + REPX {mova [cq+64*x], m12}, 0, 1, 2, 3, 4, 5, 6, 7 + cmp eobd, 151 + jb .fast + vpermq m9, m21, [cq+64* 8] ; 16 17 + vpermq m19, m21, [cq+64* 9] ; 18 19 + vpermq m4, m21, [cq+64*10] ; 20 21 + vpermq m5, m21, [cq+64*11] ; 22 23 + vpermq m6, m21, [cq+64*12] ; 24 25 + vpermq m18, m21, [cq+64*13] ; 26 27 + vpermq m7, m21, [cq+64*14] ; 28 29 + vpermq m21, m21, [cq+64*15] ; 30 31 + REPX {pmulhrsw x, m8}, m9, m19, m4, m5, m6, m18, m7, m21 + REPX {mova [cq+64*x], m12}, 8, 9, 10, 11, 12, 13, 14, 15 + punpcklwd m8, m21, m14 ; 30 2 + punpckhwd m21, m1 ; 31 1 + punpcklwd m0, m17, m19 ; 14 18 + punpckhwd m17, m9 ; 15 17 + punpcklwd m9, m1 ; 16 0 + punpckhwd m14, m7 ; 3 29 + punpcklwd m1, m15, m18 ; 6 26 + punpckhwd m15, m6 ; 7 25 + punpcklwd m6, m2 ; 24 8 + punpckhwd m19, m3 ; 19 13 + punpcklwd m3, m4 ; 12 20 + punpckhwd m18, m20 ; 27 5 + punpcklwd m7, m20 ; 28 4 + punpckhwd m20, m5, m2 ; 23 9 + punpcklwd m5, m16 ; 22 10 + punpckhwd m16, m4 ; 11 21 + call m(idct_16x16_internal_8bpc).main2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf + jmp .pass2 +.fast: ; bottom half zero + punpcklwd m8, m14, m14 ; 2 + punpcklwd m0, m17, m17 ; 14 + punpcklwd m5, m16, m16 ; 10 + punpcklwd m9, m12, m1 ; __ 0 + punpckhwd m21, m1, m1 ; 1 + punpcklwd m1, m15, m15 ; 6 + punpcklwd m7, m20, m20 ; 4 + punpckhwd m19, m3, m3 ; 13 + punpcklwd m3, m3 ; 12 + punpcklwd m6, m12, m2 ; __ 8 + punpckhwd m18, m20, m20 ; 5 + punpckhwd m20, m2, m2 ; 9 + call m(idct_16x16_internal_8bpc).main_fast + punpckhwd m15, m15 ; 7 + punpckhwd m14, m14 ; 3 + punpckhwd m16, m16 ; 11 + punpckhwd m17, m17 ; 15 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast +.pass2: + vpbroadcastd m9, [o(pw_16384)] + call .transpose_round + vshufi32x4 m16, m14, m2, q3131 ; 5 + vshufi32x4 m14, m2, q2020 ; 1 + vshufi32x4 m2, m0, m3, q3131 ; 4 + vshufi32x4 m0, m3, q2020 ; 0 + vshufi32x4 m3, m1, m18, q3131 ; 6 + vshufi32x4 m1, m18, q2020 ; 2 + vshufi32x4 m18, m20, m6, q2020 ; 9 + vshufi32x4 m20, m6, q3131 ; 13 + vshufi32x4 m6, m21, m4, q3131 ; 12 + vshufi32x4 m4, m21, m4, q2020 ; 8 + vshufi32x4 m21, m19, m7, q3131 ; 15 + vshufi32x4 m19, m7, q2020 ; 11 + vshufi32x4 m7, m5, m15, q3131 ; 14 + vshufi32x4 m5, m15, q2020 ; 10 + vshufi32x4 m15, m17, m9, q2020 ; 3 + vshufi32x4 m17, m9, q3131 ; 7 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main2 + call .main_oddhalf + vpbroadcastd m12, [o(pw_2048)] + movshdup m13, [o(permD)] + lea r2, [strideq*3] + pmovzxbw m8, [dstq+strideq*0] + pmovzxbw m9, [dstq+strideq*1] + pmovzxbw m10, [dstq+strideq*2] + pmovzxbw m11, [dstq+r2 ] + REPX {pmulhrsw x, m12}, m0, m1, m2, m3 + lea r3, [dstq+strideq*4] + paddw m0, m8 + paddw m1, m9 + paddw m2, m10 + paddw m3, m11 + pmovzxbw m8, [r3+strideq*0] + pmovzxbw m9, [r3+strideq*1] + pmovzxbw m10, [r3+strideq*2] + pmovzxbw m11, [r3+r2 ] + REPX {pmulhrsw x, m12}, m4, m5, m6, m7 + lea r4, [dstq+strideq*8] + packuswb m0, m1 + paddw m4, m8 + paddw m5, m9 + packuswb m2, m3 + paddw m6, m10 + paddw m7, m11 + pmovzxbw m8, [r4+strideq*0] + pmovzxbw m9, [r4+strideq*1] + pmovzxbw m10, [r4+strideq*2] + pmovzxbw m11, [r4+r2 ] + REPX {pmulhrsw x, m12}, m14, m15, m16, m17 + lea r5, [r3+strideq*8] + packuswb m4, m5 + paddw m14, m8 + paddw m15, m9 + packuswb m6, m7 + paddw m16, m10 + paddw m17, m11 + pmovzxbw m8, [r5+strideq*0] + pmovzxbw m9, [r5+strideq*1] + pmovzxbw m10, [r5+strideq*2] + pmovzxbw m11, [r5+r2 ] + REPX {pmulhrsw x, m12}, m18, m19, m20, m21 + packuswb m14, m15 + paddw m18, m8 + paddw m19, m9 + packuswb m16, m17 + paddw m20, m10 + paddw m21, m11 + packuswb m18, m19 + packuswb m20, m21 + REPX {vpermq x, m13, x}, m0, m2, m4, m6, m14, m16, m18, m20 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym2 + vextracti32x8 [dstq+r2 ], m2, 1 + mova [r3+strideq*0], ym4 + vextracti32x8 [r3+strideq*1], m4, 1 + mova [r3+strideq*2], ym6 + vextracti32x8 [r3+r2 ], m6, 1 + mova [r4+strideq*0], ym14 + vextracti32x8 [r4+strideq*1], m14, 1 + mova [r4+strideq*2], ym16 + vextracti32x8 [r4+r2 ], m16, 1 + mova [r5+strideq*0], ym18 + vextracti32x8 [r5+strideq*1], m18, 1 + mova [r5+strideq*2], ym20 + vextracti32x8 [r5+r2 ], m20, 1 + RET +ALIGN function_align +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 16 + imul r6d, 181 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly3 +ALIGN function_align +cglobal_label .main_oddhalf_fast3 ; bottom seven-eights are zero + vpbroadcastd m8, [o(pw_2896x8)] + vpbroadcastd m4, [o(pw_4076x8)] + vpbroadcastd m3, [o(pw_401x8)] + pmulhrsw m8, m0 ; t0 + pmulhrsw m4, m14 ; t15a + pmulhrsw m3, m14 ; t8a + punpcklwd m9, m3, m4 + punpckhwd m5, m3, m4 + mova m2, m10 + vpdpwssd m2, m9, [o(pw_m3784_1567)] {bcstd} + mova m1, m10 + vpdpwssd m1, m5, [o(pw_m3784_1567)] {bcstd} + mova m6, m10 + vpdpwssd m6, m5, [o(pw_1567_3784)] {bcstd} + mova m5, m10 + vpdpwssd m5, m9, [o(pw_1567_3784)] {bcstd} + vpbroadcastd m11, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + psubsw m21, m8, m4 ; out15 + paddsw m0, m8, m4 ; out0 + psubsw m14, m8, m3 ; out8 + paddsw m7, m8, m3 ; out7 + REPX {psrad x, 12}, m2, m1, m6, m5 + packssdw m2, m1 ; t9a + packssdw m5, m6 ; t14a + ITX_MULSUB_2W 4, 3, 16, 17, 10, 11, 12 ; t11, t12 + psubsw m20, m8, m5 ; out14 + paddsw m1, m8, m5 ; out1 + psubsw m15, m8, m2 ; out9 + paddsw m6, m8, m2 ; out6 + ITX_MULSUB_2W 5, 2, 16, 17, 10, 11, 12 ; t10a, t13a + psubsw m18, m8, m3 ; out12 + paddsw m3, m8 ; out3 + psubsw m17, m8, m4 ; out11 + paddsw m4, m8 ; out4 + psubsw m19, m8, m2 ; out13 + paddsw m2, m8 ; out2 + psubsw m16, m8, m5 ; out10 + paddsw m5, m8 ; out5 + ret +cglobal_label .main_oddhalf_fast2 ; bottom three-quarters are zero + vpbroadcastd m9, [o(pw_2896x8)] + vpbroadcastd m2, [o(pw_4017x8)] + vpbroadcastd m3, [o(pw_799x8)] + vpbroadcastd m18, [o(pw_4076x8)] + vpbroadcastd m19, [o(pw_401x8)] + vpbroadcastd m20, [o(pw_m1189x8)] + vpbroadcastd m16, [o(pw_3920x8)] + pmulhrsw m9, m0 ; t0 + pmulhrsw m2, m1 ; t7a + pmulhrsw m1, m3 ; t4a + pmulhrsw m18, m14 ; t15a + pmulhrsw m14, m19 ; t8a + pmulhrsw m20, m15 ; t11a + pmulhrsw m15, m16 ; t12a + psubsw m7, m9, m2 ; idct8 out7 + paddsw m0, m9, m2 ; idct8 out0 + psubsw m4, m9, m1 ; idct8 out4 + paddsw m3, m9, m1 ; idct8 out3 + ITX_MULSUB_2W 2, 1, 5, 6, 10, 2896, 2896 ; t5, t6 + mova m21, m18 + mova m19, m14 + mova m16, m15 + mova m8, m20 + psubsw m6, m9, m1 ; idct8 out6 + paddsw m1, m9 ; idct8 out1 + psubsw m5, m9, m2 ; idct8 out5 + paddsw m2, m9 ; idct8 out2 + jmp .main3 +ALIGN function_align +cglobal_label .main_oddhalf_fast ; bottom half is zero + vpbroadcastd m5, [o(pw_m2276x8)] + vpbroadcastd m11, [o(pw_3406x8)] + vpbroadcastd m7, [o(pw_4017x8)] + vpbroadcastd m12, [o(pw_799x8)] + vpbroadcastd m6, [o(pw_3784x8)] + vpbroadcastd m10, [o(pw_1567x8)] + vpbroadcastd m4, [o(pw_2896x8)] + pmulhrsw m5, m3 ; t5a + pmulhrsw m3, m11 ; t6a + pmulhrsw m7, m1 ; t7a + pmulhrsw m1, m12 ; t4a + pmulhrsw m6, m2 ; t3 + pmulhrsw m2, m10 ; t2 + pmulhrsw m4, m0 ; t0 + vpbroadcastd m11, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + vpbroadcastd m10, [o(pd_2048)] + mova m0, m4 ; t1 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main3 + vpbroadcastd m21, [o(pw_4076x8)] + vpbroadcastd m8, [o(pw_401x8)] + vpbroadcastd m18, [o(pw_m2598x8)] + vpbroadcastd m9, [o(pw_3166x8)] + vpbroadcastd m19, [o(pw_3612x8)] + vpbroadcastd m11, [o(pw_1931x8)] + vpbroadcastd m20, [o(pw_m1189x8)] + vpbroadcastd m12, [o(pw_3920x8)] + pmulhrsw m21, m14 ; t15a + pmulhrsw m14, m8 ; t8a + pmulhrsw m18, m17 ; t9a + pmulhrsw m17, m9 ; t14a + pmulhrsw m19, m16 ; t13a + pmulhrsw m16, m11 ; t10a + pmulhrsw m20, m15 ; t11a + pmulhrsw m15, m12 ; t12a + jmp .main2 +ALIGN function_align +cglobal_label .main_oddhalf + ITX_MULSUB_2W 14, 21, 8, 9, 10, 401, 4076 ; t8a, t15a + ITX_MULSUB_2W 18, 17, 8, 9, 10, 3166, 2598 ; t9a, t14a + ITX_MULSUB_2W 16, 19, 8, 9, 10, 1931, 3612 ; t10a, t13a + ITX_MULSUB_2W 20, 15, 8, 9, 10, 3920, 1189 ; t11a, t12a +.main2: + paddsw m8, m20, m16 ; t11 + psubsw m20, m16 ; t10 + paddsw m16, m15, m19 ; t12 + psubsw m15, m19 ; t13 + psubsw m19, m14, m18 ; t9 + paddsw m14, m18 ; t8 + psubsw m18, m21, m17 ; t14 + paddsw m21, m17 ; t15 +.main3: + vpbroadcastd m11, [o(pw_1567_3784)] + vpbroadcastd m12, [o(pw_m3784_1567)] + ITX_MULSUB_2W 18, 19, 9, 17, 10, 11, 12 ; t9a, t14a + vpbroadcastd m11, [o(pw_m1567_m3784)] + ITX_MULSUB_2W 15, 20, 9, 17, 10, 12, 11 ; t10a, t13a + vpbroadcastd m11, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + psubsw m17, m14, m8 ; t11a + paddsw m8, m14 ; t8a + paddsw m14, m18, m15 ; t9 + psubsw m18, m15 ; t10 + psubsw m15, m19, m20 ; t13 + paddsw m19, m20 ; t14 + paddsw m20, m21, m16 ; t15a + psubsw m16, m21, m16 ; t12a + ITX_MULSUB_2W 15, 18, 9, 21, 10, 11, 12 ; t10a, t13a + ITX_MULSUB_2W 16, 17, 9, 21, 10, 11, 12 ; t11, t12 + psubsw m21, m0, m20 ; out15 + paddsw m0, m20 ; out0 + psubsw m20, m1, m19 ; out14 + paddsw m1, m19 ; out1 + psubsw m19, m2, m18 ; out13 + paddsw m2, m18 ; out2 + psubsw m18, m3, m17 ; out12 + paddsw m3, m17 ; out3 + psubsw m17, m4, m16 ; out11 + paddsw m4, m16 ; out4 + psubsw m16, m5, m15 ; out10 + paddsw m5, m15 ; out5 + psubsw m15, m6, m14 ; out9 + paddsw m6, m14 ; out6 + psubsw m14, m7, m8 ; out8 + paddsw m7, m8 ; out7 + ret +.transpose_round: + punpcklwd m8, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m1, m3 + punpckhwd m1, m3 + punpcklwd m3, m4, m6 + punpckhwd m4, m6 + punpcklwd m6, m5, m7 + punpckhwd m5, m7 + punpcklwd m7, m14, m16 + punpckhwd m14, m16 + punpcklwd m16, m15, m17 + punpckhwd m15, m17 + punpcklwd m17, m19, m21 + punpckhwd m19, m21 + punpckhwd m21, m18, m20 + punpcklwd m18, m20 + punpcklwd m20, m8, m1 + punpckhwd m8, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + REPX {pmulhrsw x, m9}, m20, m8, m1, m0 + punpcklwd m6, m7, m15 + punpckhwd m7, m15 + punpcklwd m15, m14, m16 + punpckhwd m14, m16 + REPX {pmulhrsw x, m9}, m2, m3, m5, m4 + punpckhwd m16, m18, m19 + punpcklwd m18, m19 + punpcklwd m19, m21, m17 + punpckhwd m21, m17 + REPX {pmulhrsw x, m9}, m6, m7, m15, m14 + punpcklwd m17, m8, m0 ; a2 a6 aa ae + punpckhwd m8, m0 ; a3 a7 ab af + punpcklwd m0, m20, m1 ; a0 a4 a8 ac + punpckhwd m20, m1 ; a1 a5 a9 ad + REPX {pmulhrsw x, m9}, m16, m18, m19, m21 + punpcklwd m1, m2, m5 ; b0 b4 b8 bc + punpckhwd m2, m5 ; b1 b5 b9 bd + punpcklwd m5, m3, m4 ; b2 b6 ba be + punpckhwd m3, m4 ; b3 b7 bb bf + punpcklwd m4, m6, m15 ; c0 c4 c8 cc + punpckhwd m6, m15 ; c1 c5 c9 cd + punpcklwd m15, m7, m14 ; c2 c6 ca ce + punpckhwd m7, m14 ; c3 c7 cb cf + punpcklwd m14, m18, m19 ; d0 d4 d8 dc + punpckhwd m18, m19 ; d1 d5 d9 dd + punpcklwd m9, m16, m21 ; d2 d6 da de + punpckhwd m16, m21 ; d3 d7 db df + vshufi32x4 m21, m0, m1, q3232 ; a8 ac b8 bc + vinserti32x8 m0, ym1, 1 ; a0 a4 b0 b4 + vinserti32x8 m1, m17, ym5, 1 ; a2 a6 b2 b6 + vshufi32x4 m5, m17, m5, q3232 ; aa ae ba be + vinserti32x8 m17, m8, ym3, 1 ; a3 a7 b3 b7 + vshufi32x4 m19, m8, m3, q3232 ; ab af bb bf + vinserti32x8 m3, m4, ym14, 1 ; c0 c4 d0 d4 + vshufi32x4 m4, m14, q3232 ; c8 cc d8 dc + vinserti32x8 m14, m20, ym2, 1 ; a1 a5 b1 b5 + vshufi32x4 m20, m2, q3232 ; a9 ad b9 bd + vinserti32x8 m2, m6, ym18, 1 ; c1 c5 d1 d5 + vshufi32x4 m6, m18, q3232 ; c9 cd d9 dd + vinserti32x8 m18, m15, ym9, 1 ; c2 c6 d2 d6 + vshufi32x4 m15, m9, q3232 ; ca ce da de + vinserti32x8 m9, m7, ym16, 1 ; c3 c7 d3 d7 + vshufi32x4 m7, m16, q3232 ; cb cf db df + ret + +%macro IDTX_16x32 4 ; src/dst[1-4] + pmulhrsw m%1, m15, [cq+64*%1] + pmulhrsw m%2, m15, [cq+64*%2] + pmulhrsw m%3, m15, [cq+64*%3] + pmulhrsw m%4, m15, [cq+64*%4] + pmulhrsw m18, m16, m%1 + pmulhrsw m19, m16, m%2 + pmulhrsw m20, m16, m%3 + pmulhrsw m21, m16, m%4 + REPX {pmulhrsw x, m17}, m18, m19, m20, m21 + paddsw m%1, m18 + paddsw m%2, m19 + paddsw m%3, m20 + paddsw m%4, m21 +%endmacro + +%macro IDTX_16x32_STORE 2 ; src[1-2] + mova xm17, [dstq+r3*0] + vinserti128 ym17, [dstq+r3*4], 1 + vinserti32x4 m17, [dstq+r3*8], 2 + vinserti32x4 m17, [dstq+r4*8], 3 + mova [cq+64*(%1*2+0)], m18 + mova [cq+64*(%1*2+1)], m18 + punpcklbw m16, m17, m18 + punpckhbw m17, m18 + paddw m16, m%1 + paddw m17, m%2 + packuswb m16, m17 + mova [dstq+r3*0], xm16 + vextracti128 [dstq+r3*4], ym16, 1 + vextracti32x4 [dstq+r3*8], m16, 2 + vextracti32x4 [dstq+r4*8], m16, 3 +%if %1 != 7 + add dstq, strideq +%endif +%endmacro + +cglobal inv_txfm_add_identity_identity_16x32_8bpc, 3, 5, 22, dst, stride, c + vpbroadcastd m15, [pw_2896x8] + vpbroadcastd m16, [pw_1697x16] + vpbroadcastd m17, [pw_16384] + IDTX_16x32 0, 1, 2, 3 + IDTX_16x32 4, 5, 6, 7 + IDTX_16x32 8, 9, 10, 11 + IDTX_16x32 12, 13, 14, 15 + vpbroadcastd m16, [pw_8192] + call .transpose_2x8x8_round + lea r3, [strideq*2] + lea r4, [strideq*3] + pxor m18, m18 + IDTX_16x32_STORE 0, 8 + IDTX_16x32_STORE 1, 9 + IDTX_16x32_STORE 2, 10 + IDTX_16x32_STORE 3, 11 + IDTX_16x32_STORE 4, 12 + IDTX_16x32_STORE 5, 13 + IDTX_16x32_STORE 6, 14 + IDTX_16x32_STORE 7, 15 + RET +ALIGN function_align +.transpose_2x8x8_round: + punpckhwd m17, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m7 + punpcklwd m6, m7 + punpckhwd m7, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckhdq m6, m5, m7 + punpckldq m5, m7 + punpckldq m7, m17, m1 + punpckhdq m17, m1 + REPX {pmulhrsw x, m16}, m0, m2, m3, m4, m5, m7, m6, m17 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m17 + punpcklqdq m6, m17 + punpckhwd m17, m12, m13 + punpcklwd m12, m13 + punpckhwd m13, m8, m9 + punpcklwd m8, m9 + punpckhwd m9, m14, m15 + punpcklwd m14, m15 + punpckhwd m15, m10, m11 + punpcklwd m10, m11 + punpckhdq m11, m8, m10 + punpckldq m8, m10 + punpckldq m10, m12, m14 + punpckhdq m12, m14 + punpckhdq m14, m13, m15 + punpckldq m13, m15 + punpckldq m15, m17, m9 + punpckhdq m17, m9 + REPX {pmulhrsw x, m16}, m8, m10, m11, m12, m13, m15, m14, m17 + punpckhqdq m9, m8, m10 + punpcklqdq m8, m10 + punpcklqdq m10, m11, m12 + punpckhqdq m11, m12 + punpcklqdq m12, m13, m15 + punpckhqdq m13, m15 + punpckhqdq m15, m14, m17 + punpcklqdq m14, m17 + ret + +%macro IDTX_32x16 4 ; dst[1-4] + pmulhrsw m%2, m12, [cq+32*(%1+ 0)] + pmulhrsw m18, m12, [cq+32*(%1+16)] + pmulhrsw m%4, m12, [cq+32*(%3+ 0)] + pmulhrsw m19, m12, [cq+32*(%3+16)] + REPX {paddsw x, x}, m%2, m18, m%4, m19 + mova m%1, m14 + vpermi2q m%1, m%2, m18 + vpermt2q m%2, m16, m18 +%if %3 != 14 + mova m%3, m14 +%endif + vpermi2q m%3, m%4, m19 + vpermt2q m%4, m16, m19 + pmulhrsw m18, m17, m%1 + pmulhrsw m19, m17, m%2 + pmulhrsw m20, m17, m%3 + pmulhrsw m21, m17, m%4 + REPX {paddsw x, x}, m%1, m%2, m%3, m%4 + paddsw m%1, m18 + paddsw m%2, m19 + paddsw m%3, m20 + paddsw m%4, m21 +%endmacro + +%macro IDTX_32x16_STORE 2-3 0 ; src[1-2], 32x32 + mova ym19, [dstq+strideq*0] + vinserti32x8 m19, [dstq+strideq*8], 1 +%if %3 == 0 + mova [cq+64*(%1*2+0)], m20 + mova [cq+64*(%1*2+1)], m20 +%endif + punpcklbw m18, m19, m20 + punpckhbw m19, m20 + paddw m18, m%1 + paddw m19, m%2 + packuswb m18, m19 + mova [dstq+strideq*0], ym18 + vextracti32x8 [dstq+strideq*8], m18, 1 +%if %3 || %1 != 7 + add dstq, strideq +%endif +%endmacro + +cglobal inv_txfm_add_identity_identity_32x16_8bpc, 3, 3, 22, dst, stride, c + vpbroadcastd m12, [pw_2896x8] + movu m14, [permB+7] + vpbroadcastd m17, [pw_1697x16] + psrlq m16, m14, 4 + IDTX_32x16 0, 1, 2, 3 + IDTX_32x16 4, 5, 6, 7 + IDTX_32x16 8, 9, 10, 11 + IDTX_32x16 12, 13, 14, 15 + vpbroadcastd m16, [pw_2048] + call m(inv_txfm_add_identity_identity_16x32_8bpc).transpose_2x8x8_round + pxor m20, m20 + IDTX_32x16_STORE 0, 8 + IDTX_32x16_STORE 1, 9 + IDTX_32x16_STORE 2, 10 + IDTX_32x16_STORE 3, 11 + IDTX_32x16_STORE 4, 12 + IDTX_32x16_STORE 5, 13 + IDTX_32x16_STORE 6, 14 + IDTX_32x16_STORE 7, 15 + RET + +%macro IDCT_32x32_END 4 ; src, mem, stride[1-2] + pmovzxbw m10, [dstq+%3] + pmovzxbw m11, [r3 +%4] +%if %2 < 8 + paddsw m8, m%2, m%1 + psubsw m9, m%2, m%1 +%else + mova m9, [cq+64*(%2*2-16)] + paddsw m8, m9, m%1 + psubsw m9, m%1 +%endif + pmulhrsw m8, m12 + pmulhrsw m9, m12 +%if %2 >= 8 +%if %2 == 8 + pxor m0, m0 +%endif + mova [cq+64*(%2*2-16)], m0 + mova [cq+64*(%2*2-15)], m0 +%endif + paddw m8, m10 + paddw m9, m11 + packuswb m8, m9 + vpermq m8, m13, m8 + mova [dstq+%3], ym8 + vextracti32x8 [r3 +%4], m8, 1 +%if %2 == 3 || %2 == 7 || %2 == 11 + add dstq, r5 + sub r3, r5 +%endif +%endmacro + +cglobal inv_txfm_add_dct_dct_32x32_8bpc, 4, 6, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + WIN64_SPILL_XMM 30 + cmp eobd, 136 + jb .fast + mova m5, [cq+64*20] + mova m3, [cq+64*12] + mova m1, [cq+64* 4] + mova m7, [cq+64*28] + mova m2, [cq+64* 8] + mova m6, [cq+64*24] + mova m0, [cq+64* 0] + mova m4, [cq+64*16] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + mova m14, [cq+64* 2] + mova m21, [cq+64*30] + mova m18, [cq+64*18] + mova m17, [cq+64*14] + mova m16, [cq+64*10] + mova m19, [cq+64*22] + mova m20, [cq+64*26] + mova m15, [cq+64* 6] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova [cq+64* 0], m14 + mova [cq+64* 2], m15 + mova [cq+64* 4], m16 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64*12], m20 + mova [cq+64*14], m21 + mova m22, [cq+64* 1] + mova m21, [cq+64*31] + mova m14, [cq+64*17] + mova m29, [cq+64*15] + mova m26, [cq+64* 9] + mova m17, [cq+64*23] + mova m18, [cq+64*25] + mova m25, [cq+64* 7] + mova m24, [cq+64* 5] + mova m19, [cq+64*27] + mova m16, [cq+64*21] + mova m27, [cq+64*11] + mova m28, [cq+64*13] + mova m15, [cq+64*19] + mova m20, [cq+64*29] + mova m23, [cq+64* 3] + call .main_oddhalf + vpbroadcastd m10, [o(pw_8192)] + psubsw m13, m0, m29 ; 31 + paddsw m0, m29 ; 0 + psubsw m29, m1, m28 ; 30 + paddsw m1, m28 ; 1 + psubsw m28, m2, m27 ; 29 + paddsw m2, m27 ; 2 + psubsw m27, m3, m26 ; 28 + paddsw m3, m26 ; 3 + psubsw m26, m4, m25 ; 27 + paddsw m4, m25 ; 4 + psubsw m25, m5, m24 ; 26 + paddsw m5, m24 ; 5 + psubsw m24, m6, m23 ; 25 + paddsw m6, m23 ; 6 + psubsw m23, m7, m22 ; 24 + paddsw m7, m22 ; 7 + pxor m9, m9 + punpckhwd m8, m0, m1 ; a4 b4 a5 b5 a6 b6 a7 b7 + punpcklwd m0, m1 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpckhwd m1, m2, m3 ; c4 d4 c5 d5 c6 d6 c7 d7 + punpcklwd m2, m3 ; c0 d0 c1 d1 c2 d2 c3 d3 + REPX {mova [cq+64*x], m9}, 16, 17, 18, 19 + punpckhwd m22, m4, m5 ; e4 f4 e5 f5 e6 f6 e7 f7 + punpcklwd m4, m5 ; e0 f0 e1 f1 e2 f2 e3 f3 + punpckhwd m5, m6, m7 ; g4 h4 g5 h5 g6 h6 g7 h7 + punpcklwd m6, m7 ; g0 h0 g1 h1 g2 h2 g3 h3 + REPX {mova [cq+64*x], m9}, 20, 21, 22, 23 + punpckhwd m3, m23, m24 + punpcklwd m23, m24 + punpckhwd m24, m25, m26 + punpcklwd m25, m26 + REPX {mova [cq+64*x], m9}, 24, 25, 26, 27 + punpckhwd m26, m27, m28 + punpcklwd m27, m28 + punpckhwd m28, m29, m13 + punpcklwd m29, m13 + REPX {mova [cq+64*x], m9}, 28, 29, 30, 31 + punpckhdq m7, m0, m2 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m0, m2 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m2, m4, m6 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpckldq m4, m6 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m6, m8, m1 ; a6 b6 c6 d6 a7 b7 c7 d7 + punpckldq m8, m1 ; a4 b4 c4 d4 a5 b5 c5 d5 + punpckhdq m1, m22, m5 ; e6 f6 g6 h6 e7 f7 g7 h7 + punpckldq m22, m5 ; e4 f4 g4 h5 e5 f5 g5 h5 + REPX {pmulhrsw x, m10}, m0, m4, m8, m22 + punpckhdq m13, m23, m25 + punpckldq m23, m25 + punpckhdq m25, m27, m29 + punpckldq m27, m29 + REPX {pmulhrsw x, m10}, m13, m23, m25, m27 + punpckhdq m9, m3, m24 + punpckldq m3, m24 + punpckhdq m24, m26, m28 + punpckldq m26, m28 + punpcklqdq m5, m23, m27 ; d00 d08 d16 d24 + punpckhqdq m23, m27 ; d01 d09 d17 d25 + punpckhqdq m27, m13, m25 ; d03 d11 d19 d27 + punpcklqdq m13, m25 ; d02 d10 d18 d26 + punpckhqdq m25, m3, m26 ; d05 d13 d21 d29 + punpcklqdq m3, m26 ; d04 d12 d20 d28 + punpckhqdq m26, m9, m24 ; d07 d15 d23 d31 + punpcklqdq m9, m24 ; d06 d14 d22 d30 + REPX {pmulhrsw x, m10}, m25, m3, m26 + mova [cq+64* 9], m23 + mova [cq+64*11], m27 + mova [cq+64*13], m25 + mova [cq+64*15], m26 + punpckhqdq m24, m8, m22 ; a05 a13 a21 a29 + punpcklqdq m8, m22 ; a04 a12 a20 a28 + punpckhqdq m22, m0, m4 ; a01 a09 a17 a25 + punpcklqdq m0, m4 ; a00 a08 a16 a24 + punpckhqdq m23, m7, m2 ; a03 a11 a19 a27 + punpcklqdq m7, m2 ; a02 a10 a18 a26 + punpckhqdq m25, m6, m1 ; a07 a15 a23 a31 + punpcklqdq m6, m1 ; a06 a14 a22 a30 + mova m2, [cq+64* 0] + mova m11, [cq+64* 2] + mova m12, [cq+64* 4] + mova m29, [cq+64* 6] + mova m27, [cq+64* 8] + mova m26, [cq+64*10] + mova m4, [cq+64*12] + mova m28, [cq+64*14] + psubsw m1, m2, m21 ; 23 + paddsw m2, m21 ; 8 + psubsw m21, m11, m20 ; 22 + paddsw m11, m20 ; 9 + psubsw m20, m12, m19 ; 21 + paddsw m12, m19 ; 10 + psubsw m19, m29, m18 ; 20 + paddsw m29, m18 ; 11 + psubsw m18, m27, m17 ; 19 + paddsw m27, m17 ; 12 + psubsw m17, m26, m16 ; 18 + paddsw m26, m16 ; 13 + paddsw m16, m4, m15 ; 14 + psubsw m4, m15 ; 17 + pmulhrsw m15, m6, m10 + psubsw m6, m28, m14 ; 16 + paddsw m28, m14 ; 15 + pmulhrsw m14, m7, m10 + punpcklwd m7, m6, m4 + punpckhwd m6, m4 + punpckhwd m4, m17, m18 + punpcklwd m17, m18 + punpckhwd m18, m19, m20 + punpcklwd m19, m20 + punpckhwd m20, m21, m1 + punpcklwd m21, m1 + punpckhwd m1, m2, m11 ; i4 j4 i5 j5 i6 j6 i7 j7 + punpcklwd m2, m11 ; i0 j1 i1 j1 i2 j2 i3 j3 + punpckhwd m11, m12, m29 ; k4 l4 k5 l5 k6 l6 k7 l7 + punpcklwd m12, m29 ; k0 l0 k1 l1 k2 l2 k3 l3 + punpckhwd m29, m27, m26 ; m4 n4 m5 n5 m6 n6 m7 n7 + punpcklwd m27, m26 ; m0 n0 m1 n1 m2 n2 m3 n3 + punpckhwd m26, m16, m28 ; o4 p4 o5 p5 o6 p6 o7 p7 + punpcklwd m16, m28 ; o0 p0 o1 p1 o2 p2 o3 p3 + pmulhrsw m23, m10 + pmulhrsw m25, m10 + punpckhdq m28, m2, m12 ; i2 j2 k2 l2 i3 j3 k3 l3 + punpckldq m2, m12 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhdq m12, m27, m16 ; m2 n2 o2 p2 m3 n3 o3 p3 + punpckldq m27, m16 ; m0 n0 o0 p0 m1 n1 o1 p1 + REPX {pmulhrsw x, m10}, m28, m2, m12, m27 + punpckhdq m16, m1, m11 ; i6 j6 k6 l6 i7 j7 k7 l7 + punpckldq m1, m11 ; i4 j4 k4 l4 i5 j5 k5 l5 + punpckhdq m11, m29, m26 ; m6 n6 o6 p6 m7 n7 o7 p7 + punpckldq m29, m26 ; m4 n4 o4 p4 m5 n5 o5 p5 + REPX {pmulhrsw x, m10}, m16, m1, m11, m29 + punpckhdq m26, m19, m21 + punpckldq m19, m21 + punpckhdq m21, m6, m4 + punpckldq m6, m4 + REPX {pmulhrsw x, m10}, m26, m19, m21, m6 + punpckhdq m4, m18, m20 + punpckldq m18, m20 + punpckhdq m20, m7, m17 + punpckldq m7, m17 + REPX {pmulhrsw x, m10}, m4, m18, m20, m7 + punpcklqdq m17, m28, m12 ; b02 b10 b18 b26 + punpckhqdq m28, m12 ; b03 b11 b19 b27 + punpckhqdq m12, m2, m27 ; b01 b09 b17 b25 + punpcklqdq m2, m27 ; b00 b08 b16 b24 + punpckhqdq m27, m1, m29 ; b05 b13 b21 b29 + punpcklqdq m1, m29 ; b04 b12 b20 b28 + punpckhqdq m29, m16, m11 ; b07 b15 b23 b31 + punpcklqdq m16, m11 ; b06 b14 b22 b30 + mova [cq+64* 1], m12 + mova [cq+64* 3], m28 + mova [cq+64* 5], m27 + mova [cq+64* 7], m29 + punpckhqdq m27, m20, m26 ; c03 c11 c19 c27 + punpcklqdq m20, m26 ; c02 c10 c18 c26 + punpckhqdq m26, m7, m19 ; c01 c09 c17 c25 + punpcklqdq m7, m19 ; c00 c08 c16 c24 + punpckhqdq m28, m6, m18 ; c05 c13 c21 c29 + punpcklqdq m6, m18 ; c04 c12 c20 c28 + punpckhqdq m29, m21, m4 ; c07 c15 c23 c31 + punpcklqdq m21, m4 ; c06 c14 c22 c30 + pmulhrsw m19, m9, m10 + vshufi32x4 m4, m0, m2, q3232 ; a16 a24 b16 b24 + vinserti32x8 m0, ym2, 1 ; a00 a08 b00 b08 + vshufi32x4 m2, m7, m5, q3232 ; c16 c24 d16 d24 + vinserti32x8 m7, ym5, 1 ; c00 c08 d00 d08 + vshufi32x4 m5, m8, m1, q3232 ; a20 a28 b20 b28 + vinserti32x8 m1, m8, ym1, 1 ; a04 a12 b04 b12 + vshufi32x4 m8, m6, m3, q3232 ; c20 c28 d20 d28 + vinserti32x8 m6, ym3, 1 ; c04 c12 d04 d12 + vshufi32x4 m3, m1, m6, q3131 ; 12 + vshufi32x4 m1, m6, q2020 ; 4 + vshufi32x4 m6, m4, m2, q3131 ; 24 + vshufi32x4 m4, m2, q2020 ; 16 + vshufi32x4 m2, m0, m7, q3131 ; 8 + vshufi32x4 m0, m7, q2020 ; 0 + vshufi32x4 m7, m5, m8, q3131 ; 28 + vshufi32x4 m5, m8, q2020 ; 20 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + vshufi32x4 m18, m14, m17, q3232 ; a18 a26 b18 b26 + vinserti32x8 m14, ym17, 1 ; a02 a10 b02 b10 + vshufi32x4 m17, m20, m13, q3232 ; c18 c26 d18 d26 + vinserti32x8 m20, ym13, 1 ; c02 c10 d02 d10 + vshufi32x4 m13, m21, m19, q3232 ; c22 c30 d22 d30 + vinserti32x8 m21, ym19, 1 ; c06 c14 d06 d14 + vshufi32x4 m19, m15, m16, q3232 ; a22 a30 b22 b30 + vinserti32x8 m15, ym16, 1 ; a06 a14 b06 b14 + vshufi32x4 m16, m14, m20, q3131 ; 10 + vshufi32x4 m14, m20, q2020 ; 2 + vshufi32x4 m20, m18, m17, q3131 ; 26 + vshufi32x4 m18, m17, q2020 ; 18 + vshufi32x4 m17, m15, m21, q3131 ; 14 + vshufi32x4 m15, m21, q2020 ; 6 + vshufi32x4 m21, m19, m13, q3131 ; 30 + vshufi32x4 m19, m13, q2020 ; 22 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova [cq+64* 0], m14 + mova [cq+64* 2], m15 + mova [cq+64* 4], m16 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64*12], m20 + mova [cq+64*14], m21 + mova m15, [cq+64* 1] + mova m16, [cq+64* 3] + mova m17, [cq+64* 5] + mova m19, [cq+64* 7] + mova m20, [cq+64* 9] + mova m21, [cq+64*11] + mova m13, [cq+64*13] + mova m18, [cq+64*15] + vshufi32x4 m14, m22, m15, q3232 ; a17 a25 b17 b25 + vinserti32x8 m22, ym15, 1 ; a01 a09 b01 b09 + vshufi32x4 m15, m23, m16, q3232 ; a19 a27 b19 b27 + vinserti32x8 m23, ym16, 1 ; a03 a11 b03 b11 + vshufi32x4 m16, m24, m17, q3232 ; a21 a29 b21 b29 + vinserti32x8 m24, ym17, 1 ; a05 a13 b05 b13 + vshufi32x4 m17, m25, m19, q3232 ; a23 a31 b23 b31 + vinserti32x8 m25, ym19, 1 ; a07 a15 b07 b15 + vinserti32x8 m8, m26, ym20, 1 ; c01 c09 d01 d09 + vshufi32x4 m26, m20, q3232 ; c17 c25 d17 d25 + vinserti32x8 m9, m27, ym21, 1 ; c03 c11 d03 d11 + vshufi32x4 m27, m21, q3232 ; c19 c27 d19 d27 + vinserti32x8 m11, m28, ym13, 1 ; c05 c13 d05 d13 + vshufi32x4 m28, m13, q3232 ; c21 c29 d21 d29 + vinserti32x8 m12, m29, ym18, 1 ; c07 c15 d07 d15 + vshufi32x4 m29, m18, q3232 ; c23 c31 d23 d31 + vshufi32x4 m18, m14, m26, q3131 ; 25 + vshufi32x4 m14, m26, q2020 ; 17 + vshufi32x4 m19, m15, m27, q3131 ; 27 + vshufi32x4 m15, m27, q2020 ; 19 + vshufi32x4 m20, m16, m28, q3131 ; 29 + vshufi32x4 m16, m28, q2020 ; 21 + vshufi32x4 m21, m17, m29, q3131 ; 31 + vshufi32x4 m17, m29, q2020 ; 23 + vshufi32x4 m26, m22, m8, q3131 ; 9 + vshufi32x4 m22, m8, q2020 ; 1 + vshufi32x4 m27, m23, m9, q3131 ; 11 + vshufi32x4 m23, m9, q2020 ; 3 + vshufi32x4 m28, m24, m11, q3131 ; 13 + vshufi32x4 m24, m11, q2020 ; 5 + vshufi32x4 m29, m25, m12, q3131 ; 15 + vshufi32x4 m25, m12, q2020 ; 7 + call .main_oddhalf + jmp .end +.fast: ; bottom/right halves are zero + mova m14, [o(dup16_perm)] + pmovzxwd m9, [cq+64* 0] + pmovzxwd m6, [cq+64* 8] + vpermb m8, m14, [cq+64* 2] + vpermb ym0, ym14, [cq+64*14] + vpermb ym5, ym14, [cq+64*10] + vpermb m1, m14, [cq+64* 6] + vpermb m7, m14, [cq+64* 4] + vpermb ym3, ym14, [cq+64*12] + pslld m9, 16 + pslld m6, 16 + call m(idct_16x16_internal_8bpc).main_fast + vpermb m21, m14, [cq+64* 1] + vpermb ym17, ym14, [cq+64*15] + vpermb ym20, ym14, [cq+64* 9] + vpermb m15, m14, [cq+64* 7] + vpermb m18, m14, [cq+64* 5] + vpermb ym16, ym14, [cq+64*11] + vpermb ym19, ym14, [cq+64*13] + vpermb m14, m14, [cq+64* 3] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m9, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_32x16_8bpc).transpose_round + vshufi32x4 m22, m14, m2, q2020 ; 1 + vshufi32x4 m24, m14, m2, q3131 ; 5 + vshufi32x4 m23, m17, m9, q2020 ; 3 + vshufi32x4 m25, m17, m9, q3131 ; 7 + vshufi32x4 m16, m5, m15, q2020 ; 10 + vshufi32x4 m17, m5, m15, q3131 ; 14 + vshufi32x4 m14, m1, m18, q2020 ; 2 + vshufi32x4 m15, m1, m18, q3131 ; 6 + vshufi32x4 m1, m0, m3, q3131 ; 4 + vshufi32x4 m0, m3, q2020 ; 0 + vshufi32x4 m3, m21, m4, q3131 ; 12 + vshufi32x4 m2, m21, m4, q2020 ; 8 + vshufi32x4 m26, m20, m6, q2020 ; 9 + vshufi32x4 m28, m20, m6, q3131 ; 13 + vshufi32x4 m27, m19, m7, q2020 ; 11 + vshufi32x4 m29, m19, m7, q3131 ; 15 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + mova [cq+64* 0], m14 + mova [cq+64* 2], m15 + mova [cq+64* 4], m16 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64*12], m20 + mova [cq+64*14], m21 + call .main_oddhalf_fast +.end: + lea r4, [strideq*3] + vpbroadcastd m12, [o(pw_2048)] + movshdup m13, [o(permD)] + lea r3, [dstq+r4*8] + lea r5, [strideq+r4] ; stride*4 + add r3, r5 ; dst+stride*28 + IDCT_32x32_END 29, 0, strideq*0, r4 + IDCT_32x32_END 28, 1, strideq*1, strideq*2 + IDCT_32x32_END 27, 2, strideq*2, strideq*1 + IDCT_32x32_END 26, 3, r4 , strideq*0 + IDCT_32x32_END 25, 4, strideq*0, r4 + IDCT_32x32_END 24, 5, strideq*1, strideq*2 + IDCT_32x32_END 23, 6, strideq*2, strideq*1 + IDCT_32x32_END 22, 7, r4 , strideq*0 + IDCT_32x32_END 21, 8, strideq*0, r4 + IDCT_32x32_END 20, 9, strideq*1, strideq*2 + IDCT_32x32_END 19, 10, strideq*2, strideq*1 + IDCT_32x32_END 18, 11, r4 , strideq*0 + IDCT_32x32_END 17, 12, strideq*0, r4 + IDCT_32x32_END 16, 13, strideq*1, strideq*2 + IDCT_32x32_END 15, 14, strideq*2, strideq*1 + IDCT_32x32_END 14, 15, r4 , strideq*0 + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 32 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly2 +ALIGN function_align +cglobal_label .main_oddhalf_fast3 ; bottom seven-eights are zero + vpbroadcastd m21, [o(pw_4091x8)] + vpbroadcastd m8, [o(pw_201x8)] + vpbroadcastd m24, [o(pw_m601x8)] + vpbroadcastd m12, [o(pw_4052x8)] + pmulhrsw m21, m22 ; t31a + pmulhrsw m22, m8 ; t16a + pmulhrsw m24, m23 ; t23a + pmulhrsw m23, m12 ; t24a + + punpcklwd m9, m22, m21 + punpckhwd m8, m22, m21 + mova m15, m10 + vpdpwssd m15, m9, [o(pw_m4017_799)] {bcstd} + mova m17, m10 + vpdpwssd m17, m8, [o(pw_m4017_799)] {bcstd} + REPX {psrad x, 12}, m15, m17 + packssdw m15, m17 + mova m17, m10 + vpdpwssd m17, m8, [o(pw_799_4017)] {bcstd} + mova m8, m10 + vpdpwssd m8, m9, [o(pw_799_4017)] {bcstd} + REPX {psrad x, 12}, m17, m8 + packssdw m8, m17 + + punpcklwd m9, m24, m23 + punpckhwd m16, m24, m23 + mova m20, m10 + vpdpwssd m20, m9, [o(pw_m3406_m2276)] {bcstd} + mova m17, m10 + vpdpwssd m17, m16, [o(pw_m3406_m2276)] {bcstd} + REPX {psrad x, 12}, m20, m17 + packssdw m20, m17 + mova m17, m10 + vpdpwssd m17, m16, [o(pw_m2276_3406)] {bcstd} + mova m16, m10 + vpdpwssd m16, m9, [o(pw_m2276_3406)] {bcstd} + REPX {psrad x, 12}, m17, m16 + packssdw m16, m17 + + mova m17, m21 + mova m27, m15 + mova m25, m20 + mova m29, m8 + mova m18, m22 + mova m14, m24 + mova m28, m16 + mova m26, m23 + jmp .main4 +cglobal_label .main_oddhalf_fast2 ; bottom three-quarters are zero + vpbroadcastd m21, [o(pw_4091x8)] + vpbroadcastd m8, [o(pw_201x8)] + vpbroadcastd m18, [o(pw_m1380x8)] + vpbroadcastd m9, [o(pw_3857x8)] + vpbroadcastd m19, [o(pw_3973x8)] + vpbroadcastd m11, [o(pw_995x8)] + vpbroadcastd m28, [o(pw_m601x8)] + vpbroadcastd m12, [o(pw_4052x8)] + pmulhrsw m21, m22 ; t31a + pmulhrsw m22, m8 ; t16a + pmulhrsw m18, m25 ; t19a + pmulhrsw m25, m9 ; t28a + pmulhrsw m19, m24 ; t27a + pmulhrsw m24, m11 ; t20a + pmulhrsw m28, m23 ; t23a + pmulhrsw m23, m12 ; t24a + mova m15, m21 + mova m8, m22 + mova m14, m18 + mova m27, m25 + mova m29, m19 + mova m26, m24 + mova m16, m28 + mova m20, m23 + jmp .main3 +ALIGN function_align +cglobal_label .main_oddhalf_fast ; bottom half is zero + vpbroadcastd m21, [o(pw_4091x8)] + vpbroadcastd m8, [o(pw_201x8)] + vpbroadcastd m14, [o(pw_m2751x8)] + vpbroadcastd m9, [o(pw_3035x8)] + vpbroadcastd m17, [o(pw_3703x8)] + vpbroadcastd m11, [o(pw_1751x8)] + vpbroadcastd m18, [o(pw_m1380x8)] + vpbroadcastd m12, [o(pw_3857x8)] + pmulhrsw m21, m22 ; t31a + vpbroadcastd m19, [o(pw_3973x8)] + pmulhrsw m22, m8 ; t16a + vpbroadcastd m8, [o(pw_995x8)] + pmulhrsw m14, m29 ; t30a + vpbroadcastd m16, [o(pw_m2106x8)] + pmulhrsw m29, m9 ; t17a + vpbroadcastd m9, [o(pw_3513x8)] + pmulhrsw m17, m26 ; t29a + vpbroadcastd m15, [o(pw_3290x8)] + pmulhrsw m26, m11 ; t18a + vpbroadcastd m11, [o(pw_2440x8)] + pmulhrsw m18, m25 ; t19a + vpbroadcastd m20, [o(pw_m601x8)] + pmulhrsw m25, m12 ; t28a + vpbroadcastd m12, [o(pw_4052x8)] + pmulhrsw m19, m24 ; t27a + pmulhrsw m24, m8 ; t20a + pmulhrsw m16, m27 ; t21a + pmulhrsw m27, m9 ; t26a + pmulhrsw m15, m28 ; t25a + pmulhrsw m28, m11 ; t22a + pmulhrsw m20, m23 ; t23a + pmulhrsw m23, m12 ; t24a + jmp .main2 +ALIGN function_align +cglobal_label .main_oddhalf + ITX_MULSUB_2W 22, 21, 8, 9, 10, 201, 4091 ; t16a, t31a + ITX_MULSUB_2W 14, 29, 8, 9, 10, 3035, 2751 ; t17a, t30a + ITX_MULSUB_2W 26, 17, 8, 9, 10, 1751, 3703 ; t18a, t29a + ITX_MULSUB_2W 18, 25, 8, 9, 10, 3857, 1380 ; t19a, t28a + ITX_MULSUB_2W 24, 19, 8, 9, 10, 995, 3973 ; t20a, t27a + ITX_MULSUB_2W 16, 27, 8, 9, 10, 3513, 2106 ; t21a, t26a + ITX_MULSUB_2W 28, 15, 8, 9, 10, 2440, 3290 ; t22a, t25a + ITX_MULSUB_2W 20, 23, 8, 9, 10, 4052, 601 ; t23a, t24a +.main2: + psubsw m8, m22, m14 ; t17 + paddsw m22, m14 ; t16 + paddsw m14, m18, m26 ; t19 + psubsw m18, m26 ; t18 + psubsw m26, m24, m16 ; t21 + paddsw m24, m16 ; t20 + psubsw m16, m20, m28 ; t22 + paddsw m28, m20 ; t23 + psubsw m20, m23, m15 ; t25 + paddsw m23, m15 ; t24 + psubsw m15, m21, m29 ; t30 + paddsw m21, m29 ; t31 + psubsw m29, m19, m27 ; t26 + paddsw m19, m27 ; t27 + paddsw m27, m25, m17 ; t28 + psubsw m25, m17 ; t29 +.main3: + ITX_MULSUB_2W 15, 8, 9, 17, 10, 799, 4017 ; t17a, t30a + ITX_MULSUB_2W 25, 18, 9, 17, 10, m4017, 799 ; t18a, t29a + ITX_MULSUB_2W 29, 26, 9, 17, 10, 3406, 2276 ; t21a, t26a + ITX_MULSUB_2W 20, 16, 9, 17, 10, m2276, 3406 ; t22a, t25a + psubsw m17, m21, m27 ; t28a + paddsw m21, m27 ; t31a + psubsw m27, m15, m25 ; t18 + paddsw m15, m25 ; t17 + psubsw m25, m20, m29 ; t21 + paddsw m20, m29 ; t22 + psubsw m29, m8, m18 ; t29 + paddsw m8, m18 ; t30 + psubsw m18, m22, m14 ; t19a + paddsw m22, m14 ; t16a + psubsw m14, m28, m24 ; t20a + paddsw m24, m28 ; t23a + paddsw m28, m16, m26 ; t25 + psubsw m16, m26 ; t26 + psubsw m26, m23, m19 ; t27a + paddsw m23, m19 ; t24a +.main4: + vpbroadcastd m12, [o(pw_m3784_1567)] + vpbroadcastd m11, [o(pw_1567_3784)] + ITX_MULSUB_2W 29, 27, 9, 19, 10, 11, 12 ; t18a, t29a + ITX_MULSUB_2W 17, 18, 9, 19, 10, 11, 12 ; t19, t28 + vpbroadcastd m11, [o(pw_m1567_m3784)] + ITX_MULSUB_2W 16, 25, 9, 19, 10, 12, 11 ; t21a, t26a + ITX_MULSUB_2W 26, 14, 9, 19, 10, 12, 11 ; t20, t27 + vpbroadcastd m12, [o(pw_m2896_2896)] + vpbroadcastd m11, [o(pw_2896_2896)] + psubsw m19, m27, m25 ; t26 + paddsw m27, m25 ; t29 + psubsw m25, m17, m26 ; t20a + paddsw m17, m26 ; t19a + paddsw m26, m18, m14 ; t28a + psubsw m18, m14 ; t27a + paddsw m14, m22, m24 ; t16 + psubsw m22, m24 ; t23 + psubsw m24, m29, m16 ; t21 + paddsw m16, m29 ; t18 + paddsw m29, m21, m23 ; t31 + psubsw m21, m23 ; t24 + psubsw m23, m15, m20 ; t22a + paddsw m15, m20 ; t17a + psubsw m20, m8, m28 ; t25a + paddsw m28, m8 ; t30a + ITX_MULSUB_2W 18, 25, 8, 9, 10, 11, 12 ; t20, t27 + ITX_MULSUB_2W 19, 24, 8, 9, 10, 11, 12 ; t21a, t26a + ITX_MULSUB_2W 21, 22, 8, 9, 10, 11, 12 ; t23a, t24a + ITX_MULSUB_2W 20, 23, 8, 9, 10, 11, 12 ; t22, t25 + ret + +%macro IDTX_32x32 2 ; dst[1-2] + vmovdqa32 ym%1, [cq+64*(%1+ 0)] ; force EVEX encoding, which + vmovdqa32 ym17, [cq+64*(%1+16)] ; reduces code size due to + vmovdqa32 ym%2, [cq+64*(%2+ 0)] ; compressed displacements + vmovdqa32 ym18, [cq+64*(%2+16)] + vpermt2q m%1, m21, m17 + vpermt2q m%2, m21, m18 +%endmacro + +cglobal inv_txfm_add_identity_identity_32x32_8bpc, 3, 3, 22, dst, stride, c + movu m21, [permB+7] + vpbroadcastd m16, [pw_8192] + pxor m20, m20 +.loop: + IDTX_32x32 0, 1 + IDTX_32x32 2, 3 + IDTX_32x32 4, 5 + IDTX_32x32 6, 7 + IDTX_32x32 8, 9 + IDTX_32x32 10, 11 + IDTX_32x32 12, 13 + IDTX_32x32 14, 15 + call m(inv_txfm_add_identity_identity_16x32_8bpc).transpose_2x8x8_round + IDTX_32x16_STORE 0, 8, 1 + IDTX_32x16_STORE 1, 9, 1 + IDTX_32x16_STORE 2, 10, 1 + IDTX_32x16_STORE 3, 11, 1 + IDTX_32x16_STORE 4, 12, 1 + IDTX_32x16_STORE 5, 13, 1 + IDTX_32x16_STORE 6, 14, 1 + IDTX_32x16_STORE 7, 15, 1 + lea dstq, [dstq+strideq*8] + btc cq, 5 + jnc .loop + mov r0d, 8 +.zero_loop: + mova [cq+64*0], m20 + mova [cq+64*1], m20 + mova [cq+64*2], m20 + mova [cq+64*3], m20 + add cq, 64*4 + dec r0d + jg .zero_loop + RET + +cglobal inv_txfm_add_dct_dct_16x64_8bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jz .dconly + WIN64_SPILL_XMM 30 + cmp eobd, 151 + jb .fast + mova m5, [cq+64*10] + mova m3, [cq+64* 6] + mova m1, [cq+64* 2] + mova m7, [cq+64*14] + mova m2, [cq+64* 4] + mova m6, [cq+64*12] + mova m0, [cq+64* 0] + mova m4, [cq+64* 8] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + mova m14, [cq+64* 1] + mova m21, [cq+64*15] + mova m18, [cq+64* 9] + mova m17, [cq+64* 7] + mova m16, [cq+64* 5] + mova m19, [cq+64*11] + mova m20, [cq+64*13] + mova m15, [cq+64* 3] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + vpbroadcastd m9, [o(pw_8192)] +%macro TRANSPOSE_8x4_ROUND 4 + punpckhwd m8, m%3, m%4 ; c4 d4 c5 d5 c6 d6 c7 d7 + punpcklwd m%3, m%4 ; c0 d0 c1 d1 c2 d2 c3 d3 + punpckhwd m%4, m%1, m%2 ; a4 b4 a5 b5 a6 b6 a7 b7 + punpcklwd m%1, m%2 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpckhdq m%2, m%1, m%3 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m%1, m%3 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckldq m%3, m%4, m8 ; a4 b4 c4 d4 a5 b5 c5 d5 + punpckhdq m%4, m8 ; a6 b6 c6 d6 a7 b7 c7 d7 + REPX {pmulhrsw x, m9}, m%2, m%1, m%3, m%4 +%endmacro + TRANSPOSE_8x4_ROUND 0, 1, 2, 3 + TRANSPOSE_8x4_ROUND 4, 5, 6, 7 + TRANSPOSE_8x4_ROUND 14, 15, 16, 17 + TRANSPOSE_8x4_ROUND 18, 19, 20, 21 + vinserti32x8 m26, m0, ym4, 1 ; a0 a4 b0 b4 + vshufi32x4 m0, m4, q3232 ; a8 a12 b8 b12 + vinserti32x8 m27, m1, ym5, 1 ; a1 a5 b1 b5 + vshufi32x4 m1, m5, q3232 ; a9 a13 b9 b13 + vinserti32x8 m28, m2, ym6, 1 ; a2 a6 b2 b6 + vshufi32x4 m2, m6, q3232 ; a10 a14 b10 b14 + vinserti32x8 m29, m3, ym7, 1 ; a3 a7 b3 b7 + vshufi32x4 m8, m3, m7, q3232 ; a11 a15 b11 b15 + vinserti32x8 m4, m14, ym18, 1 ; c0 c4 d0 d4 + vshufi32x4 m14, m18, q3232 ; c8 c12 d8 d12 + vinserti32x8 m5, m15, ym19, 1 ; c1 c5 d1 d5 + vshufi32x4 m15, m19, q3232 ; c9 c13 d9 d13 + vinserti32x8 m6, m16, ym20, 1 ; c2 c6 d2 d6 + vshufi32x4 m16, m20, q3232 ; c10 c14 d10 d14 + vinserti32x8 m7, m17, ym21, 1 ; c3 c7 d3 d7 + vshufi32x4 m17, m21, q3232 ; c11 c15 d11 d15 + vshufi32x4 m22, m26, m4, q2020 ; 0 1 + vshufi32x4 m26, m4, q3131 ; 8 9 + vshufi32x4 m23, m27, m5, q2020 ; 2 3 + vshufi32x4 m27, m5, q3131 ; 10 11 + vshufi32x4 m24, m28, m6, q2020 ; 4 5 + vshufi32x4 m28, m6, q3131 ; 12 13 + vshufi32x4 m25, m29, m7, q2020 ; 6 7 + vshufi32x4 m29, m7, q3131 ; 14 15 + vshufi32x4 m4, m0, m14, q2020 ; 16 17 + vshufi32x4 m3, m0, m14, q3131 ; 24 25 + vshufi32x4 m20, m1, m15, q2020 ; 18 19 + vshufi32x4 m19, m1, m15, q3131 ; 26 27 + vshufi32x4 m5, m2, m16, q2020 ; 20 21 + vshufi32x4 m0, m2, m16, q3131 ; 28 29 + vshufi32x4 m16, m8, m17, q2020 ; 22 23 + vshufi32x4 m17, m8, m17, q3131 ; 30 31 + pxor m6, m6 + mova [cq+64* 0], m4 + mova [cq+64* 2], m5 + mova [cq+64* 4], m3 + mova [cq+64* 6], m0 + punpcklwd m8, m24, m24 ; 4 + punpcklwd m0, m0 ; 28 + punpcklwd m5, m5 ; 20 + punpcklwd m1, m28, m28 ; 12 + punpcklwd m7, m26, m26 ; 8 + punpcklwd m3, m3 ; 24 + punpcklwd m9, m6, m22 ; __ 0 + punpcklwd m6, m4 ; __ 16 + call m(idct_16x16_internal_8bpc).main_fast3 + mova [cq+64* 1], m20 + mova [cq+64* 3], m16 + mova [cq+64* 5], m19 + mova [cq+64* 7], m17 + punpcklwd m21, m23, m23 ; 2 + punpcklwd m17, m17 ; 30 + punpcklwd m20, m20 ; 18 + punpcklwd m15, m29, m29 ; 14 + punpcklwd m18, m27, m27 ; 10 + punpcklwd m16, m16 ; 22 + punpcklwd m19, m19 ; 26 + punpcklwd m14, m25, m25 ; 6 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova [cq+64* 8], m14 + mova [cq+64* 9], m15 + mova [cq+64*10], m16 + mova [cq+64*11], m17 + mova [cq+64*12], m18 + mova [cq+64*13], m19 + mova [cq+64*14], m20 + mova [cq+64*15], m21 + mova m21, [cq+64* 7] + mova m14, [cq+64* 0] + mova m17, [cq+64* 3] + mova m18, [cq+64* 4] + mova m19, [cq+64* 5] + mova m16, [cq+64* 2] + mova m15, [cq+64* 1] + mova m20, [cq+64* 6] + REPX {punpckhwd x, x}, m22, m21, m14, m29, m26, m17, m18, m25, \ + m24, m19, m16, m27, m28, m15, m20, m23 + call .main_oddhalf + jmp .end +.fast: ; right half is zero + mova ym8, [cq+64*15] + vinserti32x8 m8, [cq+64* 1], 1 + mova m2, [o(int16_perm)] + mova ym9, [cq+64* 8] + vinserti32x8 m9, [cq+64* 0], 1 + mova ym0, [cq+64* 7] + vinserti32x8 m0, [cq+64* 9], 1 + mova ym7, [cq+64*14] + vinserti32x8 m7, [cq+64* 2], 1 + mova ym1, [cq+64* 3] + vinserti32x8 m1, [cq+64*13], 1 + mova ym3, [cq+64* 6] + vinserti32x8 m3, [cq+64*10], 1 + mova ym5, [cq+64*11] + vinserti32x8 m5, [cq+64* 5], 1 + mova ym6, [cq+64*12] + vinserti32x8 m6, [cq+64* 4], 1 + REPX {vpermb x, m2, x}, m8, m9, m0, m7, m1, m3, m5, m6 + call m(idct_16x16_internal_8bpc).main2 + vbroadcasti32x4 m8, [o(int_shuf3)] + vbroadcasti32x4 m9, [o(int_shuf4)] + vpbroadcastd m11, [o(pw_8192)] + pshufb m0, m8 + pshufb m1, m9 + pshufb m2, m8 + pshufb m3, m9 + REPX {pmulhrsw x, m11}, m0, m1, m2, m3 + pshufb m4, m8 + pshufb m5, m9 + pshufb m6, m8 + pshufb m7, m9 + REPX {pmulhrsw x, m11}, m4, m5, m6, m7 + punpckhdq m28, m0, m1 + punpckldq m0, m1 + punpckhdq m27, m2, m3 + punpckldq m2, m3 + punpckhdq m22, m4, m5 + punpckldq m4, m5 + punpckhdq m23, m6, m7 + punpckldq m6, m7 + vinserti32x8 m14, m0, ym2, 1 + vshufi32x4 m15, m0, m2, q3232 + vinserti32x8 m2, m4, ym6, 1 + vshufi32x4 m4, m6, q3232 + vshufi32x4 m21, m14, m2, q2020 ; 0 2 + vshufi32x4 m14, m2, q3131 ; 4 6 + vshufi32x4 m18, m15, m4, q2020 ; 8 10 + vshufi32x4 m15, m4, q3131 ; 12 14 + pxor m9, m9 + punpcklwd m8, m14, m14 ; 4 + punpcklwd m1, m15, m15 ; 12 + punpcklwd m7, m18, m18 ; 8 + punpcklwd m9, m21 ; __ 0 + call m(idct_16x16_internal_8bpc).main_fast4 + punpckhwd m21, m21 ; 2 + punpckhwd m15, m15 ; 14 + punpckhwd m18, m18 ; 10 + punpckhwd m14, m14 ; 6 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + vinserti32x8 m24, m28, ym27, 1 + vshufi32x4 m28, m27, q3232 + vinserti32x8 m27, m22, ym23, 1 + vshufi32x4 m22, m23, q3232 + vshufi32x4 m23, m24, m27, q2020 ; 1 3 + vshufi32x4 m24, m27, q3131 ; 5 7 + vshufi32x4 m27, m28, m22, q2020 ; 9 11 + vshufi32x4 m28, m22, q3131 ; 13 15 + punpcklwd m22, m23, m23 ; 1 + punpckhwd m29, m28, m28 ; 15 + punpcklwd m26, m27, m27 ; 9 + punpckhwd m25, m24, m24 ; 7 + mova [cq+64* 8], m14 + mova [cq+64* 9], m15 + mova [cq+64*10], m16 + mova [cq+64*11], m17 + punpcklwd m24, m24 ; 5 + punpckhwd m27, m27 ; 11 + punpcklwd m28, m28 ; 13 + punpckhwd m23, m23 ; 3 + mova [cq+64*12], m18 + mova [cq+64*13], m19 + mova [cq+64*14], m20 + mova [cq+64*15], m21 + call .main_oddhalf_fast +.end: + imul r6, strideq, 60 + mova m10, [o(end_16x32p)] + vpbroadcastd m11, [o(pw_2048)] + lea r3, [strideq*3] + pxor m12, m12 + add r6, dstq ; dst+stride*60 + psrldq m13, m10, 1 + lea r4, [strideq+r3] ; stride*4 +%macro IDCT_16x64_END 3 ; idct32, idct64, tmp +%if %1 & 1 + %define %%s0 r3 + %define %%s1 strideq*2 + %define %%s2 strideq*1 + %define %%s3 strideq*0 +%else + %define %%s0 strideq*0 + %define %%s1 strideq*1 + %define %%s2 strideq*2 + %define %%s3 r3 +%if %1 + add dstq, r4 + sub r6, r4 +%endif +%endif +%if %1 < 8 + pmulhrsw m8, m11, m%1 + pmulhrsw m9, m11, m%2 +%else + mova m9, [cq+64*%1] + paddsw m8, m9, m%2 ; out 0+n, 1+n + psubsw m9, m%2 ; out 63-n, 62-n + pmulhrsw m8, m11 + pmulhrsw m9, m11 +%endif + mova xm29, [dstq+%%s0] + vinserti128 ym29, [dstq+%%s1], 1 + mova xm%3, [r6 +%%s3] + vinserti128 ym%3, [r6 +%%s2], 1 + vpermb m29, m10, m29 + vpermb m%3, m10, m%3 + mova [cq+64*%1], m12 + paddw m29, m8 + paddw m%3, m9 + packuswb m29, m%3 + vpermd m29, m13, m29 + mova [dstq+%%s0], xm29 + vextracti128 [dstq+%%s1], ym29, 1 + vextracti32x4 [r6 +%%s2], m29, 2 + vextracti32x4 [r6 +%%s3], m29, 3 +%endmacro + IDCT_16x64_END 0, 29, 0 + IDCT_16x64_END 1, 28, 28 + IDCT_16x64_END 2, 27, 28 + IDCT_16x64_END 3, 26, 28 + IDCT_16x64_END 4, 25, 28 + IDCT_16x64_END 5, 24, 28 + IDCT_16x64_END 6, 23, 28 + IDCT_16x64_END 7, 22, 28 + IDCT_16x64_END 8, 21, 28 + IDCT_16x64_END 9, 20, 28 + IDCT_16x64_END 10, 19, 28 + IDCT_16x64_END 11, 18, 28 + IDCT_16x64_END 12, 17, 28 + IDCT_16x64_END 13, 16, 28 + IDCT_16x64_END 14, 15, 28 + IDCT_16x64_END 15, 14, 28 + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 64 + imul r6d, 181 + add r6d, 128+512 + sar r6d, 8+2 + jmp m(inv_txfm_add_dct_dct_16x8_8bpc).dconly3 +ALIGN function_align +cglobal_label .main_oddhalf_fast ; bottom three-quarters are zero + vpbroadcastd m8, [o(pw_101_4095x8)] + vpbroadcastd m21, [o(pw_m1474_3822x8)] + vpbroadcastd m14, [o(pw_897_3996x8)] + vpbroadcastd m17, [o(pw_m700_4036x8)] + vpbroadcastd m18, [o(pw_501_4065x8)] + vpbroadcastd m19, [o(pw_m1092_3948x8)] + vpbroadcastd m16, [o(pw_1285_3889x8)] + vpbroadcastd m15, [o(pw_m301_4085x8)] + pmulhrsw m8, m22 ; t32a t63a + pmulhrsw m21, m29 ; t35a t60a + pmulhrsw m14, m26 ; t36a t59a + pmulhrsw m17, m25 ; t39a t56 + pmulhrsw m18, m24 ; t40a t55a + pmulhrsw m19, m27 ; t43a t52a + pmulhrsw m16, m28 ; t44a t51a + pmulhrsw m15, m23 ; t47a t48a + mova m22, m8 + mova m29, m21 + mova m26, m14 + mova m25, m17 + mova m24, m18 + mova m27, m19 + mova m28, m16 + mova m20, m15 + jmp .main_oddhalf2 +ALIGN function_align +cglobal_label .main_oddhalf + vpbroadcastd m8, [o(pw_101_4095x8)] + vpbroadcastd m9, [o(pw_m2824_2967x8)] + vpbroadcastd m11, [o(pw_1660_3745x8)] + vpbroadcastd m12, [o(pw_m1474_3822x8)] + pmulhrsw m22, m8 ; t32a t63a + vpbroadcastd m8, [o(pw_897_3996x8)] + pmulhrsw m21, m9 ; t33a t62a + vpbroadcastd m9, [o(pw_m2191_3461x8)] + pmulhrsw m14, m11 ; t34a t61a + vpbroadcastd m11, [o(pw_2359_3349x8)] + pmulhrsw m29, m12 ; t35a t60a + vpbroadcastd m12, [o(pw_m700_4036x8)] + pmulhrsw m26, m8 ; t36a t59a + vpbroadcastd m8, [o(pw_501_4065x8)] + pmulhrsw m17, m9 ; t37a t58a + vpbroadcastd m9, [o(pw_m2520_3229x8)] + pmulhrsw m18, m11 ; t38a t57a + vpbroadcastd m11, [o(pw_2019_3564x8)] + pmulhrsw m25, m12 ; t39a t56a + vpbroadcastd m12, [o(pw_m1092_3948x8)] + pmulhrsw m24, m8 ; t40a t55a + vpbroadcastd m8, [o(pw_1285_3889x8)] + pmulhrsw m19, m9 ; t41a t54a + vpbroadcastd m9, [o(pw_m1842_3659x8)] + pmulhrsw m16, m11 ; t42a t53a + vpbroadcastd m11, [o(pw_2675_3102x8)] + pmulhrsw m27, m12 ; t43a t52a + vpbroadcastd m12, [o(pw_m301_4085x8)] + pmulhrsw m28, m8 ; t44a t51a + pmulhrsw m15, m9 ; t45a t50a + pmulhrsw m20, m11 ; t46a t49a + pmulhrsw m23, m12 ; t47a t48a + psubsw m8, m22, m21 ; t33 t62 + paddsw m22, m21 ; t32 t63 + psubsw m21, m29, m14 ; t34 t61 + paddsw m29, m14 ; t35 t60 + psubsw m14, m26, m17 ; t37 t58 + paddsw m26, m17 ; t36 t59 + psubsw m17, m25, m18 ; t38 t57 + paddsw m25, m18 ; t39 t56 + psubsw m18, m24, m19 ; t41 t54 + paddsw m24, m19 ; t40 t55 + psubsw m19, m27, m16 ; t42 t53 + paddsw m27, m16 ; t43 t52 + psubsw m16, m28, m15 ; t45 t50 + paddsw m28, m15 ; t44 t51 + psubsw m15, m23, m20 ; t46 t49 + paddsw m20, m23 ; t47 t48 +.main_oddhalf2: + ITX_MUL2X_PACK 8, 9, 23, 10, 401, 4076, 5 ; t33a t62a + ITX_MUL2X_PACK 21, 9, 23, 10, m4076, 401, 5 ; t34a t61a + ITX_MUL2X_PACK 14, 9, 23, 10, 3166, 2598, 5 ; t37a t58a + ITX_MUL2X_PACK 17, 9, 23, 10, m2598, 3166, 5 ; t38a t57a + ITX_MUL2X_PACK 18, 9, 23, 10, 1931, 3612, 5 ; t41a t54a + ITX_MUL2X_PACK 19, 9, 23, 10, m3612, 1931, 5 ; t42a t53a + ITX_MUL2X_PACK 16, 9, 23, 10, 3920, 1189, 5 ; t45a t50a + ITX_MUL2X_PACK 15, 9, 23, 10, m1189, 3920, 5 ; t46a t49a + vpbroadcastd m11, [o(pw_m4017_799)] + psubsw m23, m25, m26 ; t36a t59a + paddsw m25, m26 ; t39a t56a + psubsw m26, m24, m27 ; t43a t52a + paddsw m27, m24 ; t40a t55a + psubsw m24, m20, m28 ; t44a t51a + paddsw m20, m28 ; t47a t48a + psubsw m28, m8, m21 ; t34 t61 + paddsw m8, m21 ; t33 t62 + psubsw m21, m17, m14 ; t37 t58 + paddsw m17, m14 ; t38 t57 + psubsw m14, m18, m19 ; t42 t53 + paddsw m18, m19 ; t41 t54 + psubsw m19, m15, m16 ; t45 t50 + paddsw m15, m16 ; t46 t49 + psubsw m16, m22, m29 ; t35a t60a + paddsw m22, m29 ; t32a t63a + ITX_MUL2X_PACK 16, 9, 29, 10, 799_4017, 11, 20 ; t35 t60 + ITX_MUL2X_PACK 28, 9, 29, 10, 799_4017, 11, 20 ; t34a t61a + ITX_MUL2X_PACK 23, 9, 29, 10, 11, m799_m4017, 36 ; t36 t59 + ITX_MUL2X_PACK 21, 9, 29, 10, 11, m799_m4017, 36 ; t37a t58a + vpbroadcastd m11, [o(pw_m2276_3406)] + ITX_MUL2X_PACK 26, 9, 29, 10, 3406_2276, 11, 20 ; t43 t52 + ITX_MUL2X_PACK 14, 9, 29, 10, 3406_2276, 11, 20 ; t42a t53a + ITX_MUL2X_PACK 24, 9, 29, 10, 11, m3406_m2276, 36 ; t44 t51 + ITX_MUL2X_PACK 19, 9, 29, 10, 11, m3406_m2276, 36 ; t45a t50a + vpbroadcastd m11, [o(pw_1567_3784)] + vpbroadcastd m12, [o(pw_m3784_1567)] + psubsw m29, m22, m25 ; t39 t56 + paddsw m22, m25 ; t32 t63 + psubsw m25, m20, m27 ; t40 t55 + paddsw m20, m27 ; t47 t48 + psubsw m27, m8, m17 ; t38a t57a + paddsw m8, m17 ; t33a t62a + psubsw m17, m15, m18 ; t41a t54a + paddsw m15, m18 ; t46a t49a + paddsw m18, m16, m23 ; t35a t60a + psubsw m16, m23 ; t36a t59a + psubsw m23, m24, m26 ; t43a t52a + paddsw m24, m26 ; t44a t51a + paddsw m26, m28, m21 ; t34 t61 + psubsw m28, m21 ; t37 t58 + psubsw m21, m19, m14 ; t42 t53 + paddsw m19, m14 ; t45 t50 + ITX_MUL2X_PACK 29, 9, 14, 10, 11, 12, 4 ; t39a t56a + ITX_MUL2X_PACK 27, 9, 14, 10, 11, 12, 4 ; t38 t57 + ITX_MUL2X_PACK 16, 9, 14, 10, 11, 12, 4 ; t36 t59 + ITX_MUL2X_PACK 28, 9, 14, 10, 11, 12, 4 ; t37a t58a + vpbroadcastd m11, [o(pw_m1567_m3784)] + ITX_MUL2X_PACK 25, 9, 14, 10, 12, 11, 4 ; t40a t55a + ITX_MUL2X_PACK 17, 9, 14, 10, 12, 11, 4 ; t41 t54 + ITX_MUL2X_PACK 23, 9, 14, 10, 12, 11, 4 ; t43 t52 + ITX_MUL2X_PACK 21, 9, 14, 10, 12, 11, 4 ; t42a t53a + vbroadcasti32x4 m13, [o(deint_shuf)] + vpbroadcastd m11, [o(pw_2896_2896)] + vpbroadcastd m12, [o(pw_m2896_2896)] + paddsw m14, m22, m20 ; t32a t63a + psubsw m22, m20 ; t47a t48a + psubsw m20, m8, m15 ; t46 t49 + paddsw m8, m15 ; t33 t62 + paddsw m15, m18, m24 ; t35 t60 + psubsw m18, m24 ; t44 t51 + psubsw m24, m26, m19 ; t45a t50a + paddsw m26, m19 ; t34a t61a + REPX {pshufb x, m13}, m14, m8, m15, m26 + psubsw m19, m29, m25 ; t40 t55 + paddsw m25, m29 ; t39 t56 + psubsw m29, m27, m17 ; t41a t54a + paddsw m27, m17 ; t38a t57a + psubsw m17, m16, m23 ; t43a t52a + paddsw m16, m23 ; t36a t59a + psubsw m9, m28, m21 ; t42 t53 + paddsw m28, m21 ; t37 t58 + REPX {pshufb x, m13}, m25, m27, m16, m28 + ITX_MUL2X_PACK 22, 13, 21, 10, 11, 12, 8 ; t47 t48 + ITX_MUL2X_PACK 20, 23, 22, 10, 11, 12, 8 ; t46a t49a + packssdw m21, m22 ; t47 t46a + packssdw m13, m23 ; t48 t49a + ITX_MUL2X_PACK 18, 22, 20, 10, 11, 12, 8 ; t44a t51a + ITX_MUL2X_PACK 24, 23, 18, 10, 11, 12, 8 ; t45 t50 + packssdw m20, m18 ; t44a t45 + packssdw m22, m23 ; t51a t50 + ITX_MUL2X_PACK 19, 24, 18, 10, 11, 12, 8 ; t40a t55a + ITX_MUL2X_PACK 29, 23, 19, 10, 11, 12, 8 ; t41 t54 + packssdw m18, m19 ; t40a t41 + packssdw m24, m23 ; t55a t54 + ITX_MUL2X_PACK 17, 23, 19, 10, 11, 12, 8 ; t43 t52 + ITX_MUL2X_PACK 9, 29, 17, 10, 11, 12, 8 ; t42a t53a + packssdw m19, m17 ; t43 t42a + packssdw m23, m29 ; t52 t53a + punpcklqdq m17, m25, m27 ; t39 t38a + punpckhqdq m25, m27 ; t56 t57a + punpckhqdq m27, m15, m26 ; t60 t61a + punpcklqdq m15, m26 ; t35 t34a + punpckhqdq m26, m16, m28 ; t59a t58 + punpcklqdq m16, m28 ; t36a t37 + punpckhqdq m28, m14, m8 ; t63a t62 + punpcklqdq m14, m8 ; t32a t33 + psubsw m29, m0, m28 ; out63 out62 + paddsw m0, m28 ; out0 out1 + psubsw m28, m1, m27 ; out60 out61 + paddsw m1, m27 ; out3 out2 + psubsw m27, m2, m26 ; out59 out58 + paddsw m2, m26 ; out4 out5 + psubsw m26, m3, m25 ; out56 out57 + paddsw m3, m25 ; out7 out6 + psubsw m25, m4, m24 ; out55 out54 + paddsw m4, m24 ; out8 out9 + psubsw m24, m5, m23 ; out52 out53 + paddsw m5, m23 ; out11 out10 + psubsw m23, m6, m22 ; out51 out50 + paddsw m6, m22 ; out12 out13 + psubsw m22, m7, m13 ; out48 out49 + paddsw m7, m13 ; out15 out14 + ret + +cglobal inv_txfm_add_dct_dct_64x16_8bpc, 4, 7, 0, dst, stride, c, eob +%undef cmp + lea r5, [o_base] + test eobd, eobd + jnz .normal + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 16 +.dconly: + imul r6d, 181 + add r6d, 128+512 + sar r6d, 8+2 +.dconly2: + imul r6d, 181 + add r6d, 128+2048 + sar r6d, 8+4 + pxor m2, m2 + vpbroadcastw m3, r6d +.dconly_loop: + mova m1, [dstq] + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + paddw m0, m3 + paddw m1, m3 + packuswb m0, m1 + mova [dstq], m0 + add dstq, strideq + dec r3d + jg .dconly_loop + RET +.normal: + WIN64_SPILL_XMM 31 + mova m19, [o(dup16_perm)] + mova m24, [cq+64* 2] + mova m28, [cq+64* 6] + mova m26, [cq+64* 4] + mova m22, [cq+64* 0] + mova m23, [cq+64* 1] + mova m29, [cq+64* 7] + mova m27, [cq+64* 5] + mova m25, [cq+64* 3] + vpermb m8, m19, m24 ; 4 + vpermb m1, m19, m28 ; 12 + vpermb m7, m19, m26 ; 8 + vpermb m9, m19, m22 ; __ 0 + vpermb m21, m19, m23 ; 2 + vpermb m15, m19, m29 ; 14 + vpermb m18, m19, m27 ; 10 + vpermb m14, m19, m25 ; 6 + pslld m9, 16 + vpord m30, m19, [o(pb_32)] {1to16} + REPX {vpermb x, m30, x}, m22, m29, m26, m25, m24, m27, m28, m23 + cmp eobd, 151 + jb .fast + vpermb m0, m19, [cq+64*14] ; 28 + vpermb m5, m19, [cq+64*10] ; 20 + vpermb m3, m19, [cq+64*12] ; 24 + vpermb m6, m19, [cq+64* 8] ; __ 16 + pslld m6, 16 + call m(idct_16x16_internal_8bpc).main_fast + vpermb m17, m19, [cq+64*15] ; 30 + vpermb m20, m19, [cq+64* 9] ; 18 + vpermb m16, m19, [cq+64*11] ; 22 + vpermb m19, m19, [cq+64*13] ; 26 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + vpermb m21, m30, [cq+64*15] + vpermb m14, m30, [cq+64* 8] + vpermb m17, m30, [cq+64*11] + vpermb m18, m30, [cq+64*12] + vpermb m19, m30, [cq+64*13] + vpermb m16, m30, [cq+64*10] + vpermb m15, m30, [cq+64* 9] + vpermb m20, m30, [cq+64*14] + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf + jmp .end +.fast: ; bottom half is zero + call m(idct_16x16_internal_8bpc).main_fast2 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf_fast +.end: + mova [cq+64* 8], m4 + mova [cq+64* 9], m5 + mova [cq+64*10], m6 + mova [cq+64*11], m7 + mova [cq+64*12], m26 + mova [cq+64*13], m27 + mova [cq+64*14], m28 + mova [cq+64*15], m29 + vpbroadcastd m13, [o(pw_8192)] + call .pass1_end + call .pass2 + mova [cq+64* 0], m0 + mova [cq+64* 1], m1 + mova [cq+64* 2], m2 + mova [cq+64* 3], m3 + mova [cq+64* 4], m4 + mova [cq+64* 5], m5 + mova [cq+64* 6], m6 + mova [cq+64* 7], m7 + pmulhrsw m0, m13, [cq+64* 8] + pmulhrsw m1, m13, [cq+64* 9] + pmulhrsw m2, m13, [cq+64*10] + pmulhrsw m3, m13, [cq+64*11] + vpbroadcastd m30, [o(pw_2048)] + pmulhrsw m4, m13, m22 + pmulhrsw m5, m13, m23 + pmulhrsw m6, m13, m24 + pmulhrsw m7, m13, m25 + pmulhrsw m22, m30, m14 + pmulhrsw m14, m13, m26 + pmulhrsw m23, m30, m15 + pmulhrsw m15, m13, m27 + pmulhrsw m24, m30, m16 + pmulhrsw m16, m13, m28 + pmulhrsw m25, m30, m17 + pmulhrsw m17, m13, m29 + pmulhrsw m26, m30, m18 + pmulhrsw m18, m13, [cq+64*12] + pmulhrsw m27, m30, m19 + pmulhrsw m19, m13, [cq+64*13] + pmulhrsw m28, m30, m20 + pmulhrsw m20, m13, [cq+64*14] + pmulhrsw m29, m30, m21 + pmulhrsw m21, m13, [cq+64*15] + call .transpose_round + call .pass2 + pxor m10, m10 + lea r3, [strideq*3] +%macro IDCT_64x16_END 4 + mova m9, [dstq+%4] +%if %1 < 8 + pmulhrsw m%3, m30, [cq+64*%1] +%endif + pmulhrsw m%2, m30 + mova [cq+64*%1], m10 + punpcklbw m8, m9, m10 + punpckhbw m9, m10 + paddw m8, m%3 + paddw m9, m%2 + packuswb m8, m9 + mova [dstq+%4], m8 +%if %1 == 3 || %1 == 7 || %1 == 11 + lea dstq, [dstq+strideq*4] +%endif +%endmacro + IDCT_64x16_END 0, 0, 11, strideq*0 + IDCT_64x16_END 1, 1, 11, strideq*1 + IDCT_64x16_END 2, 2, 11, strideq*2 + IDCT_64x16_END 3, 3, 11, r3 + IDCT_64x16_END 4, 4, 11, strideq*0 + IDCT_64x16_END 5, 5, 11, strideq*1 + IDCT_64x16_END 6, 6, 11, strideq*2 + IDCT_64x16_END 7, 7, 11, r3 + IDCT_64x16_END 8, 14, 22, strideq*0 + IDCT_64x16_END 9, 15, 23, strideq*1 + IDCT_64x16_END 10, 16, 24, strideq*2 + IDCT_64x16_END 11, 17, 25, r3 + IDCT_64x16_END 12, 18, 26, strideq*0 + IDCT_64x16_END 13, 19, 27, strideq*1 + IDCT_64x16_END 14, 20, 28, strideq*2 + IDCT_64x16_END 15, 21, 29, r3 + RET +ALIGN function_align +.pass1_end: + mova m4, [cq+64* 0] + mova m5, [cq+64* 1] + mova m6, [cq+64* 2] + mova m7, [cq+64* 3] + mova m8, [cq+64* 4] + mova m9, [cq+64* 5] + mova m11, [cq+64* 6] + mova m12, [cq+64* 7] + psubsw m29, m4, m21 ; out47 out46 + paddsw m4, m21 ; out16 out17 + psubsw m28, m5, m20 ; out44 out45 + paddsw m5, m20 ; out19 out18 + REPX {pmulhrsw x, m13}, m0, m1, m2, m3 + psubsw m27, m6, m19 ; out43 out42 + paddsw m6, m19 ; out20 out21 + psubsw m26, m7, m18 ; out40 out41 + paddsw m7, m18 ; out23 out22 + pmulhrsw m18, m13, m22 + pmulhrsw m19, m13, m23 + pmulhrsw m20, m13, m24 + pmulhrsw m21, m13, m25 + paddsw m25, m12, m14 ; out31 out30 + psubsw m14, m12, m14 ; out32 out33 + paddsw m24, m11, m15 ; out28 out29 + psubsw m15, m11, m15 ; out35 out34 + REPX {pmulhrsw x, m13}, m4, m5, m6, m7 + paddsw m23, m9, m16 ; out27 out26 + psubsw m16, m9, m16 ; out36 out37 + paddsw m22, m8, m17 ; out24 out25 + psubsw m17, m8, m17 ; out39 out38 + REPX {pmulhrsw x, m13}, m14, m15, m16, m17 +.transpose_round: +%macro TRANSPOSE_8x4_PACKED 4 + punpckhwd m8, m%1, m%3 ; b0 f0 b1 f1 b2 f2 b3 f3 + punpcklwd m%1, m%3 ; a0 e0 a1 e1 a2 e2 a3 e3 + punpcklwd m%3, m%2, m%4 ; d0 h0 d1 h1 d2 h2 d3 h3 + punpckhwd m%2, m%4 ; c0 g0 c1 g1 c2 g2 c3 g3 + punpckhwd m%4, m%1, m%2 ; a2 c2 e2 g2 a3 c3 e3 g3 + punpcklwd m%1, m%2 ; a0 c0 e0 g0 a1 c1 e1 g1 + punpckhwd m%2, m8, m%3 ; b2 d2 f2 h2 b3 d3 f3 h3 + punpcklwd m8, m%3 ; b0 d0 f0 h0 b1 d1 f1 h1 + punpcklwd m%3, m%4, m%2 ; 2 + punpckhwd m%4, m%2 ; 3 + punpckhwd m%2, m%1, m8 ; 1 + punpcklwd m%1, m8 ; 0 +%endmacro + TRANSPOSE_8x4_PACKED 0, 1, 2, 3 + TRANSPOSE_8x4_PACKED 18, 19, 20, 21 + TRANSPOSE_8x4_PACKED 4, 5, 6, 7 + TRANSPOSE_8x4_PACKED 14, 15, 16, 17 + vshufi32x4 m8, m0, m4, q3232 ; a02 a03 b02 b03 + vinserti32x8 m0, ym4, 1 ; a00 a01 b00 b01 + vshufi32x4 m4, m1, m5, q3232 ; a12 a13 b12 b13 + vinserti32x8 m9, m1, ym5, 1 ; a10 a11 b10 b11 + vshufi32x4 m5, m2, m6, q3232 ; a22 a23 b22 b23 + vinserti32x8 m1, m2, ym6, 1 ; a20 a21 b20 b21 + vshufi32x4 m6, m3, m7, q3232 ; a32 a33 b32 b33 + vinserti32x8 m11, m3, ym7, 1 ; a30 a31 b30 b31 + vshufi32x4 m2, m14, m18, q3232 ; c02 c03 d02 d03 + vinserti32x8 m3, m14, ym18, 1 ; c00 c01 d00 d01 + vshufi32x4 m18, m15, m19, q3232 ; c12 c13 d12 d13 + vinserti32x8 m15, ym19, 1 ; c10 c11 d10 d11 + vshufi32x4 m19, m16, m20, q3232 ; c22 c23 d22 d23 + vinserti32x8 m16, ym20, 1 ; c20 c21 d20 d21 + vshufi32x4 m20, m17, m21, q3232 ; c32 c33 d32 d33 + vinserti32x8 m17, ym21, 1 ; c30 c31 d30 d31 + ret +.pass2: + vshufi32x4 m7, m5, m19, q3131 ; 14 + vshufi32x4 m5, m19, q2020 ; 10 + vshufi32x4 m21, m6, m20, q3131 ; 15 + vshufi32x4 m19, m6, m20, q2020 ; 11 + vshufi32x4 m20, m4, m18, q3131 ; 13 + vshufi32x4 m18, m4, m18, q2020 ; 9 + vshufi32x4 m6, m8, m2, q3131 ; 12 + vshufi32x4 m4, m8, m2, q2020 ; 8 + vshufi32x4 m2, m0, m3, q3131 ; 4 + vshufi32x4 m0, m3, q2020 ; 0 + vshufi32x4 m3, m1, m16, q3131 ; 6 + vshufi32x4 m1, m16, q2020 ; 2 + vshufi32x4 m16, m9, m15, q3131 ; 5 + vshufi32x4 m14, m9, m15, q2020 ; 1 + vshufi32x4 m15, m11, m17, q2020 ; 3 + vshufi32x4 m17, m11, m17, q3131 ; 7 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main2 + jmp m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + +cglobal inv_txfm_add_dct_dct_32x64_8bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 0, 9, 30, 64*32, dst, stride, c, eob + vpbroadcastd m23, [o(pw_2896x8)] +%undef cmp + cmp eobd, 136 + jb .fast + pmulhrsw m5, m23, [cq+64*20] + pmulhrsw m3, m23, [cq+64*12] + pmulhrsw m1, m23, [cq+64* 4] + pmulhrsw m7, m23, [cq+64*28] + pmulhrsw m2, m23, [cq+64* 8] + pmulhrsw m6, m23, [cq+64*24] + pmulhrsw m0, m23, [cq+64* 0] + pmulhrsw m4, m23, [cq+64*16] + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + pmulhrsw m14, m23, [cq+64* 2] + pmulhrsw m21, m23, [cq+64*30] + pmulhrsw m18, m23, [cq+64*18] + pmulhrsw m17, m23, [cq+64*14] + pmulhrsw m16, m23, [cq+64*10] + pmulhrsw m19, m23, [cq+64*22] + pmulhrsw m20, m23, [cq+64*26] + pmulhrsw m15, m23, [cq+64* 6] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova [cq+64* 0], m14 + mova [cq+64* 2], m15 + mova [cq+64* 4], m16 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64*12], m20 + mova [cq+64*14], m21 + pmulhrsw m22, m23, [cq+64* 1] + pmulhrsw m21, m23, [cq+64*31] + pmulhrsw m14, m23, [cq+64*17] + pmulhrsw m29, m23, [cq+64*15] + pmulhrsw m26, m23, [cq+64* 9] + pmulhrsw m17, m23, [cq+64*23] + pmulhrsw m18, m23, [cq+64*25] + pmulhrsw m25, m23, [cq+64* 7] + pmulhrsw m24, m23, [cq+64* 5] + pmulhrsw m19, m23, [cq+64*27] + pmulhrsw m16, m23, [cq+64*21] + pmulhrsw m27, m23, [cq+64*11] + pmulhrsw m28, m23, [cq+64*13] + pmulhrsw m15, m23, [cq+64*19] + pmulhrsw m20, m23, [cq+64*29] + pmulhrsw m23, [cq+64* 3] + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf + vpbroadcastd m12, [o(pw_16384)] + psubsw m13, m0, m29 ; 31 + paddsw m0, m29 ; 0 + psubsw m29, m1, m28 ; 30 + paddsw m1, m28 ; 1 + psubsw m28, m2, m27 ; 29 + paddsw m2, m27 ; 2 + psubsw m27, m3, m26 ; 28 + paddsw m3, m26 ; 3 + psubsw m26, m4, m25 ; 27 + paddsw m4, m25 ; 4 + psubsw m25, m5, m24 ; 26 + paddsw m5, m24 ; 5 + psubsw m24, m6, m23 ; 25 + paddsw m6, m23 ; 6 + psubsw m23, m7, m22 ; 24 + paddsw m7, m22 ; 7 + pxor m9, m9 + punpckhwd m8, m0, m1 ; a4 b4 a5 b5 a6 b6 a7 b7 + punpcklwd m0, m1 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpckhwd m1, m2, m3 ; c4 d4 c5 d5 c6 d6 c7 d7 + punpcklwd m2, m3 ; c0 d0 c1 d1 c2 d2 c3 d3 + REPX {mova [cq+64*x], m9}, 16, 17, 18, 19 + punpckhwd m22, m4, m5 ; e4 f4 e5 f5 e6 f6 e7 f7 + punpcklwd m4, m5 ; e0 f0 e1 f1 e2 f2 e3 f3 + punpckhwd m5, m6, m7 ; g4 h4 g5 h5 g6 h6 g7 h7 + punpcklwd m6, m7 ; g0 h0 g1 h1 g2 h2 g3 h3 + REPX {mova [cq+64*x], m9}, 20, 21, 22, 23 + punpckhwd m3, m23, m24 + punpcklwd m23, m24 + punpckhwd m24, m25, m26 + punpcklwd m25, m26 + REPX {mova [cq+64*x], m9}, 24, 25, 26, 27 + punpckhwd m26, m27, m28 + punpcklwd m27, m28 + punpckhwd m28, m29, m13 + punpcklwd m29, m13 + REPX {mova [cq+64*x], m9}, 28, 29, 30, 31 + punpckhdq m7, m0, m2 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m0, m2 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckhdq m2, m4, m6 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpckldq m4, m6 ; e0 f0 g0 h0 e1 f1 g1 h1 + REPX {pmulhrsw x, m12}, m7, m0, m2, m4 + punpckhdq m6, m8, m1 ; a6 b6 c6 d6 a7 b7 c7 d7 + punpckldq m8, m1 ; a4 b4 c4 d4 a5 b5 c5 d5 + punpckhdq m1, m22, m5 ; e6 f6 g6 h6 e7 f7 g7 h7 + punpckldq m22, m5 ; e4 f4 g4 h5 e5 f5 g5 h5 + REPX {pmulhrsw x, m12}, m6, m8, m1, m22 + punpckhdq m13, m23, m25 + punpckldq m23, m25 + punpckhdq m25, m27, m29 + punpckldq m27, m29 + REPX {pmulhrsw x, m12}, m13, m23, m25, m27 + punpckhdq m9, m3, m24 + punpckldq m3, m24 + punpckhdq m24, m26, m28 + punpckldq m26, m28 + REPX {pmulhrsw x, m12}, m9, m3, m24, m26 + punpckhqdq m5, m23, m27 ; d01 d09 d17 d25 + punpcklqdq m23, m27 ; d00 d08 d16 d24 + punpcklqdq m27, m13, m25 ; d02 d10 d18 d26 + punpckhqdq m13, m25 ; d03 d11 d19 d27 + punpcklqdq m25, m3, m26 ; d04 d12 d20 d28 + punpckhqdq m3, m26 ; d05 d13 d21 d29 + punpcklqdq m26, m9, m24 ; d06 d14 d22 d30 + punpckhqdq m9, m24 ; d07 d15 d23 d31 + mova [cq+64* 3], m23 + mova [cq+64*13], m27 + mova [cq+64* 7], m25 + mova [cq+64*15], m26 + punpckhqdq m24, m8, m22 ; a05 a13 a21 a29 + punpcklqdq m8, m22 ; a04 a12 a20 a28 + punpckhqdq m22, m0, m4 ; a01 a09 a17 a25 + punpcklqdq m0, m4 ; a00 a08 a16 a24 + punpckhqdq m23, m7, m2 ; a03 a11 a19 a27 + punpcklqdq m7, m2 ; a02 a10 a18 a26 + punpckhqdq m25, m6, m1 ; a07 a15 a23 a31 + punpcklqdq m6, m1 ; a06 a14 a22 a30 + mova [cq+64* 1], m0 + mova [cq+64* 9], m7 + mova [cq+64* 5], m8 + mova [cq+64*11], m6 + mova m2, [cq+64* 0] + mova m11, [cq+64* 2] + mova m8, [cq+64* 4] + mova m29, [cq+64* 6] + mova m27, [cq+64* 8] + mova m26, [cq+64*10] + mova m4, [cq+64*12] + mova m28, [cq+64*14] + psubsw m1, m2, m21 ; 23 + paddsw m2, m21 ; 8 + psubsw m21, m11, m20 ; 22 + paddsw m11, m20 ; 9 + psubsw m20, m8, m19 ; 21 + paddsw m8, m19 ; 10 + psubsw m19, m29, m18 ; 20 + paddsw m29, m18 ; 11 + psubsw m18, m27, m17 ; 19 + paddsw m27, m17 ; 12 + psubsw m17, m26, m16 ; 18 + paddsw m26, m16 ; 13 + psubsw m16, m4, m15 ; 17 + paddsw m4, m15 ; 14 + psubsw m15, m28, m14 ; 16 + paddsw m28, m14 ; 15 + punpcklwd m14, m15, m16 + punpckhwd m15, m16 + punpckhwd m16, m17, m18 + punpcklwd m17, m18 + punpckhwd m18, m19, m20 + punpcklwd m19, m20 + punpckhwd m20, m21, m1 + punpcklwd m21, m1 + punpckhwd m1, m2, m11 ; i4 j4 i5 j5 i6 j6 i7 j7 + punpcklwd m2, m11 ; i0 j1 i1 j1 i2 j2 i3 j3 + punpckhwd m11, m8, m29 ; k4 l4 k5 l5 k6 l6 k7 l7 + punpcklwd m8, m29 ; k0 l0 k1 l1 k2 l2 k3 l3 + punpckhwd m29, m27, m26 ; m4 n4 m5 n5 m6 n6 m7 n7 + punpcklwd m27, m26 ; m0 n0 m1 n1 m2 n2 m3 n3 + punpckhwd m26, m4, m28 ; o4 p4 o5 p5 o6 p6 o7 p7 + punpcklwd m4, m28 ; o0 p0 o1 p1 o2 p2 o3 p3 + punpckhdq m28, m2, m8 ; i2 j2 k2 l2 i3 j3 k3 l3 + punpckldq m2, m8 ; i0 j0 k0 l0 i1 j1 k1 l1 + punpckhdq m8, m27, m4 ; m2 n2 o2 p2 m3 n3 o3 p3 + punpckldq m27, m4 ; m0 n0 o0 p0 m1 n1 o1 p1 + REPX {pmulhrsw x, m12}, m28, m2, m8, m27 + punpckhdq m4, m1, m11 ; i6 j6 k6 l6 i7 j7 k7 l7 + punpckldq m1, m11 ; i4 j4 k4 l4 i5 j5 k5 l5 + punpckhdq m11, m29, m26 ; m6 n6 o6 p6 m7 n7 o7 p7 + punpckldq m29, m26 ; m4 n4 o4 p4 m5 n5 o5 p5 + REPX {pmulhrsw x, m12}, m4, m1, m11, m29 + punpckhdq m26, m19, m21 + punpckldq m19, m21 + punpckhdq m21, m15, m16 + punpckldq m15, m16 + REPX {pmulhrsw x, m12}, m26, m19, m21, m15 + punpckhdq m16, m18, m20 + punpckldq m18, m20 + punpckhdq m20, m14, m17 + punpckldq m14, m17 + REPX {pmulhrsw x, m12}, m16, m18, m20, m14 + punpckhqdq m17, m28, m8 ; b03 b11 b19 b27 + punpcklqdq m28, m8 ; b02 b10 b18 b26 + punpckhqdq m8, m2, m27 ; b01 b09 b17 b25 + punpcklqdq m2, m27 ; b00 b08 b16 b24 + punpcklqdq m27, m1, m29 ; b04 b12 b20 b28 + punpckhqdq m1, m29 ; b05 b13 b21 b29 + punpcklqdq m29, m4, m11 ; b06 b14 b22 b30 + punpckhqdq m4, m11 ; b07 b15 b23 b31 + mova [cq+64* 0], m2 + mova [cq+64* 8], m28 + mova [cq+64* 4], m27 + mova [cq+64*10], m29 + punpckhqdq m27, m20, m26 ; c03 c11 c19 c27 + punpcklqdq m20, m26 ; c02 c10 c18 c26 + punpckhqdq m26, m14, m19 ; c01 c09 c17 c25 + punpcklqdq m14, m19 ; c00 c08 c16 c24 + punpckhqdq m28, m15, m18 ; c05 c13 c21 c29 + punpcklqdq m15, m18 ; c04 c12 c20 c28 + punpckhqdq m29, m21, m16 ; c07 c15 c23 c31 + punpcklqdq m21, m16 ; c06 c14 c22 c30 + mova [cq+64* 2], m14 + mova [cq+64*12], m20 + mova [cq+64* 6], m15 + mova [cq+64*14], m21 + vshufi32x4 m14, m22, m8, q3232 ; a17 a25 b17 b25 + vinserti32x8 m22, ym8, 1 ; a01 a09 b01 b09 + vshufi32x4 m15, m23, m17, q3232 ; a19 a27 b19 b27 + vinserti32x8 m23, ym17, 1 ; a03 a11 b03 b11 + vshufi32x4 m16, m24, m1, q3232 ; a21 a29 b21 b29 + vinserti32x8 m24, ym1, 1 ; a05 a13 b05 b13 + vshufi32x4 m17, m25, m4, q3232 ; a23 a31 b23 b31 + vinserti32x8 m25, ym4, 1 ; a07 a15 b07 b15 + vinserti32x8 m19, m26, ym5, 1 ; c01 c09 d01 d09 + vshufi32x4 m26, m5, q3232 ; c17 c25 d17 d25 + vinserti32x8 m20, m27, ym13, 1 ; c03 c11 d03 d11 + vshufi32x4 m27, m13, q3232 ; c19 c27 d19 d27 + vinserti32x8 m21, m28, ym3, 1 ; c05 c13 d05 d13 + vshufi32x4 m28, m3, q3232 ; c21 c29 d21 d29 + vinserti32x8 m18, m29, ym9, 1 ; c07 c15 d07 d15 + vshufi32x4 m29, m9, q3232 ; c23 c31 d23 d31 + mov r4, rsp + vshufi32x4 m0, m22, m19, q2020 ; 1 + vshufi32x4 m1, m17, m29, q3131 ; 31 + vshufi32x4 m2, m14, m26, q2020 ; 17 + vshufi32x4 m3, m25, m18, q3131 ; 15 + call .main_part1 + vshufi32x4 m0, m25, m18, q2020 ; 7 + vshufi32x4 m1, m14, m26, q3131 ; 25 + vshufi32x4 m2, m17, m29, q2020 ; 23 + vshufi32x4 m3, m22, m19, q3131 ; 9 + call .main_part1 + vshufi32x4 m0, m24, m21, q2020 ; 5 + vshufi32x4 m1, m15, m27, q3131 ; 27 + vshufi32x4 m2, m16, m28, q2020 ; 21 + vshufi32x4 m3, m23, m20, q3131 ; 11 + call .main_part1 + vshufi32x4 m0, m23, m20, q2020 ; 3 + vshufi32x4 m1, m16, m28, q3131 ; 29 + vshufi32x4 m2, m15, m27, q2020 ; 19 + vshufi32x4 m3, m24, m21, q3131 ; 13 + call .main_part1 + call .main_part2 + mova m0, [cq+64* 1] ; a0 + mova m15, [cq+64* 0] ; b0 + mova m3, [cq+64* 2] ; c0 + mova m16, [cq+64* 3] ; d0 + mova m14, [cq+64* 5] ; a4 + mova m8, [cq+64* 4] ; b4 + mova m17, [cq+64* 6] ; c4 + mova m1, [cq+64* 7] ; d4 + vshufi32x4 m2, m0, m15, q3232 ; a16 a24 b16 b24 + vinserti32x8 m0, ym15, 1 ; a00 a08 b00 b08 + vshufi32x4 m15, m3, m16, q3232 ; c16 c24 d16 d24 + vinserti32x8 m3, ym16, 1 ; c00 c08 d00 d08 + vshufi32x4 m16, m14, m8, q3232 ; a20 a28 b20 b28 + vinserti32x8 m14, ym8, 1 ; a04 a12 b04 b12 + vshufi32x4 m8, m17, m1, q3232 ; c20 c28 d20 d28 + vinserti32x8 m17, ym1, 1 ; c04 c12 d04 d12 + vshufi32x4 m1, m0, m3, q3131 ; 8 + vshufi32x4 m0, m3, q2020 ; 0 + vshufi32x4 m3, m2, m15, q3131 ; 24 + vshufi32x4 m2, m15, q2020 ; 16 + vshufi32x4 m15, m14, m17, q3131 ; 12 + vshufi32x4 m14, m17, q2020 ; 4 + vshufi32x4 m17, m16, m8, q3131 ; 28 + vshufi32x4 m16, m8, q2020 ; 20 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + mova m8, [cq+64* 8] + mova m9, [cq+64*12] + mova m11, [cq+64*10] + mova m12, [cq+64*14] + mova [cq+64* 0], m14 + mova [cq+64* 2], m15 + mova [cq+64* 4], m16 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64*12], m20 + mova [cq+64*14], m21 + mova m22, [cq+64* 9] + mova m27, [cq+64*13] + mova m23, [cq+64*11] + mova m24, [cq+64*15] + vshufi32x4 m26, m22, m8, q3232 ; a18 a26 b18 b26 + vinserti32x8 m22, ym8, 1 ; a02 a10 b02 b10 + vshufi32x4 m8, m9, m27, q3232 ; c18 c26 d18 d26 + vinserti32x8 m9, ym27, 1 ; c02 c10 d02 d10 + vshufi32x4 m27, m23, m11, q3232 ; a22 a30 b22 b30 + vinserti32x8 m23, ym11, 1 ; a06 a14 b06 b14 + vshufi32x4 m11, m12, m24, q3232 ; c22 c30 d22 d30 + vinserti32x8 m12, ym24, 1 ; c06 c14 d06 d14 + vshufi32x4 m28, m26, m8, q3131 ; 26 + vshufi32x4 m26, m8, q2020 ; 18 + vshufi32x4 m24, m22, m9, q3131 ; 10 + vshufi32x4 m22, m9, q2020 ; 2 + vshufi32x4 m29, m27, m11, q3131 ; 30 + vshufi32x4 m27, m11, q2020 ; 22 + vshufi32x4 m25, m23, m12, q3131 ; 14 + vshufi32x4 m23, m12, q2020 ; 6 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast + jmp .end +.fast: ; bottom/right halves are zero + pmulhrsw ym9, ym23, [cq+64* 0] + pmulhrsw ym6, ym23, [cq+64* 8] + mova m14, [o(dup16_perm)] + pmulhrsw ym8, ym23, [cq+64* 2] + pmulhrsw xm0, xm23, [cq+64*14] + pmulhrsw xm5, xm23, [cq+64*10] + pmulhrsw ym1, ym23, [cq+64* 6] + pmulhrsw ym7, ym23, [cq+64* 4] + pmulhrsw xm3, xm23, [cq+64*12] + pmovzxwd m9, ym9 + pmovzxwd m6, ym6 + vpermb m8, m14, m8 + punpcklwd xm0, xm0 + vpermb ym5, ym14, ym5 + vpermb m1, m14, m1 + vpermb m7, m14, m7 + punpcklwd xm3, xm3 + pslld m9, 16 + pslld m6, 16 + call m(idct_16x16_internal_8bpc).main_fast + vpmulhrsw ym21, ym23, [cq+64* 1] + {evex}vpmulhrsw xm17, xm23, [cq+64*15] ; force EVEX encoding, which + {evex}vpmulhrsw xm20, xm23, [cq+64* 9] ; reduces code size due to + {evex}vpmulhrsw ym15, ym23, [cq+64* 7] ; compressed displacements + {evex}vpmulhrsw ym18, ym23, [cq+64* 5] + {evex}vpmulhrsw xm16, xm23, [cq+64*11] + {evex}vpmulhrsw xm19, xm23, [cq+64*13] + {evex}vpmulhrsw ym23, [cq+64* 3] + vpermb m21, m14, m21 + punpcklwd xm17, xm17 + vpermb ym20, ym14, ym20 + vpermb m15, m14, m15 + vpermb m18, m14, m18 + vpermb ym16, ym14, ym16 + punpcklwd xm19, xm19 + vpermb m14, m14, m23 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast + vpbroadcastd m9, [o(pw_16384)] + call m(inv_txfm_add_dct_dct_32x16_8bpc).transpose_round + vshufi32x4 m16, m0, m3, q2020 ; 0 + vshufi32x4 m26, m0, m3, q3131 ; 4 + vshufi32x4 m0, m14, m2, q2020 ; 1 + vshufi32x4 m14, m2, q3131 ; 5 + vshufi32x4 m3, m19, m7, q3131 ; 15 + vshufi32x4 m19, m7, q2020 ; 11 + vshufi32x4 m27, m17, m9, q2020 ; 3 + vshufi32x4 m17, m9, q3131 ; 7 + vshufi32x4 m28, m20, m6, q2020 ; 9 + vshufi32x4 m20, m6, q3131 ; 13 + vshufi32x4 m22, m1, m18, q2020 ; 2 + vshufi32x4 m23, m1, m18, q3131 ; 6 + vshufi32x4 m24, m5, m15, q2020 ; 10 + vshufi32x4 m25, m5, m15, q3131 ; 14 + vshufi32x4 m15, m21, m4, q3131 ; 12 + vshufi32x4 m21, m21, m4, q2020 ; 8 + mov r4, rsp + call .main_part1_fast + mova m0, m17 + mova m3, m28 + call .main_part1_fast + mova m0, m14 + mova m3, m19 + call .main_part1_fast + mova m0, m27 + mova m3, m20 + call .main_part1_fast + call .main_part2 + mova m0, m16 + mova m1, m21 + mova m14, m26 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast2 + mova [cq+64*14], m21 + mova [cq+64* 0], m14 + mova [cq+64* 6], m17 + mova [cq+64* 8], m18 + mova [cq+64*10], m19 + mova [cq+64* 4], m16 + mova [cq+64* 2], m15 + mova [cq+64*12], m20 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast2 +.end: + lea r4, [strideq*3] + vpbroadcastd m12, [o(pw_2048)] + movshdup m13, [o(permD)] + lea r5, [r4+strideq] ; stride*4 + lea r3, [dstq+r4*8] + lea r6, [strideq+r5*8] ; stride*33 + lea r8, [r4+r5*8] ; stride*35 + add r3, r5 ; dst+stride*28 + lea r7, [r6+strideq] ; stride*34 +%macro IDCT_32x64_END 6 ; src, mem, stride[1-4] +%if %2 < 8 + paddsw m10, m%2, m%1 + psubsw m11, m%2, m%1 +%else + mova m11, [cq+64*(%2*2-16)] + paddsw m10, m11, m%1 + psubsw m11, m%1 +%endif + mova m9, [rsp+64*(31-%2)] + mova m%1, [rsp+64*%2] + paddsw m8, m10, m9 + psubsw m10, m9 + paddsw m9, m11, m%1 + pmovzxbw m0, [dstq+%3] + psubsw m11, m%1 + pmovzxbw m%1, [r3 +%4] + REPX {pmulhrsw x, m12}, m8, m10, m9, m11 + paddw m8, m0 + pmovzxbw m0, [r3 +%5] + paddw m10, m%1 + pmovzxbw m%1, [dstq+%6] + paddw m9, m0 + paddw m11, m%1 +%if %2 >= 8 +%if %2 == 8 + pxor m1, m1 +%endif + mova [cq+64*(%2*2-16)], m1 + mova [cq+64*(%2*2-15)], m1 +%endif + packuswb m8, m10 + packuswb m9, m11 + vpermq m8, m13, m8 + vpermq m9, m13, m9 + mova [dstq+%3], ym8 + vextracti32x8 [r3 +%4], m8, 1 + mova [r3 +%5], ym9 + vextracti32x8 [dstq+%6], m9, 1 +%if %2 == 3 || %2 == 7 || %2 == 11 + add dstq, r5 + sub r3, r5 +%endif +%endmacro + IDCT_32x64_END 29, 0, strideq*0, r8, r4 , r5*8 + IDCT_32x64_END 28, 1, strideq*1, r7, strideq*2, r6 + IDCT_32x64_END 27, 2, strideq*2, r6, strideq*1, r7 + IDCT_32x64_END 26, 3, r4 , r5*8, strideq*0, r8 + IDCT_32x64_END 25, 4, strideq*0, r8, r4 , r5*8 + IDCT_32x64_END 24, 5, strideq*1, r7, strideq*2, r6 + IDCT_32x64_END 23, 6, strideq*2, r6, strideq*1, r7 + IDCT_32x64_END 22, 7, r4 , r5*8, strideq*0, r8 + IDCT_32x64_END 21, 8, strideq*0, r8, r4 , r5*8 + IDCT_32x64_END 20, 9, strideq*1, r7, strideq*2, r6 + IDCT_32x64_END 19, 10, strideq*2, r6, strideq*1, r7 + IDCT_32x64_END 18, 11, r4 , r5*8, strideq*0, r8 + IDCT_32x64_END 17, 12, strideq*0, r8, r4 , r5*8 + IDCT_32x64_END 16, 13, strideq*1, r7, strideq*2, r6 + IDCT_32x64_END 15, 14, strideq*2, r6, strideq*1, r7 + IDCT_32x64_END 14, 15, r4 , r5*8, strideq*0, r8 + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 64 + imul r6d, 181 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).dconly3 +ALIGN function_align ; bottom three-quarters are zero +cglobal_label .main_part1_fast2 + vpbroadcastd m7, [o(idct64_mul+4*0)] + vpbroadcastd m8, [o(idct64_mul+4*1)] + pmulhrsw m7, m0 ; t63a + pmulhrsw m0, m8 ; t32a + + punpcklwd m4, m0, m7 + punpckhwd m6, m0, m7 + mova m1, m10 + vpdpwssd m1, m4, [o(idct64_mul+4*9)] {bcstd} + mova m9, m10 + vpdpwssd m9, m6, [o(idct64_mul+4*9)] {bcstd} + REPX {psrad x, 12}, m1, m9 + packssdw m1, m9 + mova m9, m10 + vpdpwssd m9, m6, [o(idct64_mul+4*8)] {bcstd} + mova m6, m10 + vpdpwssd m6, m4, [o(idct64_mul+4*8)] {bcstd} + REPX {psrad x, 12}, m9, m6 + packssdw m6, m9 + + mova m4, m0 + mova m3, m7 + mova m5, m1 + mova m2, m6 + jmp .main_part1c +cglobal_label .main_part1_fast + vpbroadcastd m1, [o(idct64_mul+4*0)] + vpbroadcastd m8, [o(idct64_mul+4*1)] + vpbroadcastd m2, [o(idct64_mul+4*6)] + vpbroadcastd m9, [o(idct64_mul+4*7)] + pmulhrsw m1, m0 ; t63a + pmulhrsw m0, m8 ; t32a + pmulhrsw m2, m3 ; t60a + pmulhrsw m3, m9 ; t35a + mova m8, m0 + mova m7, m1 + mova m6, m3 + mova m5, m2 + jmp .main_part1b +cglobal_label .main_part1 + ; idct64 steps 1-5: + ; in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a + ; in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a + ; in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a + ; in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a + vpbroadcastd m7, [o(idct64_mul+4*0)] + vpbroadcastd m8, [o(idct64_mul+4*1)] + vpbroadcastd m6, [o(idct64_mul+4*2)] + vpbroadcastd m9, [o(idct64_mul+4*3)] + pmulhrsw m7, m0 ; t63a + vpbroadcastd m5, [o(idct64_mul+4*4)] + pmulhrsw m0, m8 ; t32a + vpbroadcastd m8, [o(idct64_mul+4*5)] + pmulhrsw m6, m1 ; t62a + vpbroadcastd m4, [o(idct64_mul+4*6)] + pmulhrsw m1, m9 ; t33a + vpbroadcastd m9, [o(idct64_mul+4*7)] + pmulhrsw m5, m2 ; t61a + pmulhrsw m2, m8 ; t34a + pmulhrsw m4, m3 ; t60a + pmulhrsw m3, m9 ; t35a + psubsw m8, m0, m1 ; t33 + paddsw m0, m1 ; t32 + psubsw m1, m7, m6 ; t62 + paddsw m7, m6 ; t63 + psubsw m6, m3, m2 ; t34 + paddsw m3, m2 ; t35 + psubsw m2, m4, m5 ; t61 + paddsw m5, m4 ; t60 +.main_part1b: + vpbroadcastd m11, [o(idct64_mul+4*8)] + vpbroadcastd m12, [o(idct64_mul+4*9)] + ITX_MULSUB_2W 1, 8, 4, 9, 10, 11, 12 ; t33a, t62a + vpbroadcastd m11, [o(idct64_mul+4*10)] + ITX_MULSUB_2W 2, 6, 4, 9, 10, 12, 11 ; t34a, t61a + psubsw m4, m0, m3 ; t35a + paddsw m0, m3 ; t32a + psubsw m3, m7, m5 ; t60a + paddsw m7, m5 ; t63a + psubsw m5, m1, m2 ; t34 + paddsw m1, m2 ; t33 + psubsw m2, m8, m6 ; t61 + paddsw m6, m8 ; t62 +.main_part1c: + vpbroadcastd m11, [o(idct64_mul+4*11)] + vpbroadcastd m12, [o(idct64_mul+4*12)] + add r5, 4*13 + ITX_MULSUB_2W 3, 4, 8, 9, 10, 11, 12 ; t35, t60 + ITX_MULSUB_2W 2, 5, 8, 9, 10, 11, 12 ; t34a, t61a + mova [r4+64*0], m0 + mova [r4+64*7], m7 + mova [r4+64*1], m1 + mova [r4+64*6], m6 + mova [r4+64*3], m3 + mova [r4+64*4], m4 + mova [r4+64*2], m2 + mova [r4+64*5], m5 + add r4, 64*8 + ret +cglobal_label .main_part2 + vpbroadcastd m11, [o(pw_1567_3784 -16*13)] + vpbroadcastd m12, [o(pw_m3784_1567 -16*13)] + lea r6, [r4+64*7] + vpbroadcastd m17, [o(pw_m1567_m3784-16*13)] + vpbroadcastd m18, [o(pw_2896_2896 -16*13)] + vpbroadcastd m19, [o(pw_m2896_2896 -16*13)] + sub r5, 16*13 +.main_part2_loop: + mova m0, [r4-64*32] ; t32a + mova m1, [r6-64*24] ; t39a + mova m2, [r6-64*32] ; t63a + mova m3, [r4-64*24] ; t56a + mova m4, [r4-64*16] ; t40a + mova m5, [r6-64* 8] ; t47a + mova m6, [r6-64*16] ; t55a + mova m7, [r4-64* 8] ; t48a + psubsw m8, m0, m1 ; t39 + paddsw m0, m1 ; t32 + psubsw m1, m2, m3 ; t56 + paddsw m2, m3 ; t63 + psubsw m3, m5, m4 ; t40 + paddsw m5, m4 ; t47 + psubsw m4, m7, m6 ; t55 + paddsw m7, m6 ; t48 + ITX_MULSUB_2W 1, 8, 6, 9, 10, 11, 12 ; t39a, t56a + ITX_MULSUB_2W 4, 3, 6, 9, 10, 12, 17 ; t40a, t55a + psubsw m6, m2, m7 ; t48a + paddsw m2, m7 ; t63a + psubsw m7, m0, m5 ; t47a + paddsw m0, m5 ; t32a + psubsw m5, m8, m3 ; t55 + paddsw m8, m3 ; t56 + psubsw m3, m1, m4 ; t40 + paddsw m1, m4 ; t39 + ITX_MULSUB_2W 6, 7, 4, 9, 10, 18, 19 ; t47, t48 + ITX_MULSUB_2W 5, 3, 4, 9, 10, 18, 19 ; t40a, t55a + mova [r6-64* 8], m2 + mova [r4-64*32], m0 + mova [r4-64* 8], m8 + mova [r6-64*32], m1 + mova [r6-64*24], m6 + mova [r4-64*16], m7 + mova [r4-64*24], m5 + mova [r6-64*16], m3 + add r4, 64 + sub r6, 64 + cmp r4, r6 + jb .main_part2_loop + ret + +cglobal inv_txfm_add_dct_dct_64x32_8bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 0, 7, 30, 64*32, dst, stride, c, eob + vpbroadcastd m23, [o(pw_2896x8)] +%undef cmp + cmp eobd, 136 + jb .fast + pmulhrsw m0, m23, [cq+64* 1] + pmulhrsw m1, m23, [cq+64*31] + pmulhrsw m2, m23, [cq+64*17] + pmulhrsw m3, m23, [cq+64*15] + vpbroadcastd m10, [o(pd_2048)] + mov r4, rsp + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + pmulhrsw m0, m23, [cq+64* 7] + pmulhrsw m1, m23, [cq+64*25] + pmulhrsw m2, m23, [cq+64*23] + pmulhrsw m3, m23, [cq+64* 9] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + pmulhrsw m0, m23, [cq+64* 5] + pmulhrsw m1, m23, [cq+64*27] + pmulhrsw m2, m23, [cq+64*21] + pmulhrsw m3, m23, [cq+64*11] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + pmulhrsw m0, m23, [cq+64* 3] + pmulhrsw m1, m23, [cq+64*29] + pmulhrsw m2, m23, [cq+64*19] + pmulhrsw m3, m23, [cq+64*13] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + pmulhrsw m3, m23, [cq+64*24] + pmulhrsw m1, m23, [cq+64* 8] + pmulhrsw m2, m23, [cq+64*16] + pmulhrsw m0, m23, [cq+64* 0] + pmulhrsw m14, m23, [cq+64* 4] + pmulhrsw m17, m23, [cq+64*28] + pmulhrsw m16, m23, [cq+64*20] + pmulhrsw m15, m23, [cq+64*12] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + pmulhrsw m22, m23, [cq+64* 2] + pmulhrsw m29, m23, [cq+64*30] + pmulhrsw m26, m23, [cq+64*18] + pmulhrsw m25, m23, [cq+64*14] + pmulhrsw m24, m23, [cq+64*10] + pmulhrsw m27, m23, [cq+64*22] + pmulhrsw m28, m23, [cq+64*26] + pmulhrsw m23, [cq+64* 6] + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast + vpbroadcastd m13, [o(pw_16384)] + call .pass1_end_part1 + mova [cq+64*16], m1 + mova [cq+64*17], m3 + mova [cq+64*18], m5 + mova [cq+64*19], m7 + mova [cq+64*24], m23 + mova [cq+64*25], m25 + mova [cq+64*26], m27 + mova [cq+64*27], m29 + pmulhrsw m23, m13, m0 ; a0 + pmulhrsw m25, m13, m2 ; a2 + pmulhrsw m27, m13, m4 ; a4 + pmulhrsw m29, m13, m6 ; a6 + REPX {pmulhrsw x, m13}, m22, m24, m26, m28 ; e0 e2 e4 e6 + call .pass1_end_part2 + mova [cq+64*20], m15 + mova [cq+64*21], m17 + mova [cq+64*22], m19 + mova [cq+64*23], m21 + mova [cq+64*28], m1 + mova [cq+64*29], m3 + mova [cq+64*30], m5 + mova [cq+64*31], m7 + REPX {pmulhrsw x, m13}, m14, m16, m18, m20 ; c0 c2 c4 c6 + REPX {pmulhrsw x, m13}, m0, m2, m4, m6 ; g0 g2 g4 g6 + vinserti32x8 m3, m23, ym14, 1 ; a00 a01 c00 c01 + vshufi32x4 m23, m14, q3232 ; a02 a03 c02 c03 + vinserti32x8 m15, m22, ym0, 1 ; e00 e01 g00 g01 + vshufi32x4 m22, m0, q3232 ; e02 e03 g02 g03 + vinserti32x8 m1, m27, ym18, 1 ; a40 a41 c40 c41 + vshufi32x4 m27, m18, q3232 ; a42 a43 c42 c43 + vinserti32x8 m18, m26, ym4, 1 ; e40 e41 g40 g41 + vshufi32x4 m26, m4, q3232 ; e42 e43 g42 g43 + vinserti32x8 m14, m25, ym16, 1 ; a20 a21 c20 c21 + vshufi32x4 m25, m16, q3232 ; a22 a23 c22 c23 + vinserti32x8 m17, m24, ym2, 1 ; e20 e21 g20 g21 + vshufi32x4 m24, m2, q3232 ; e22 e23 g22 g23 + vinserti32x8 m19, m29, ym20, 1 ; a60 a61 c60 c61 + vshufi32x4 m29, m20, q3232 ; a62 a63 c62 c63 + vinserti32x8 m20, m28, ym6, 1 ; e60 e61 g60 g61 + vshufi32x4 m28, m6, q3232 ; e62 e63 g62 g63 + vshufi32x4 m2, m3, m15, q3131 ; 8 + vshufi32x4 m0, m3, m15, q2020 ; 0 + vshufi32x4 m6, m23, m22, q3131 ; 24 + vshufi32x4 m4, m23, m22, q2020 ; 16 + vshufi32x4 m3, m1, m18, q3131 ; 12 + vshufi32x4 m1, m18, q2020 ; 4 + vshufi32x4 m7, m27, m26, q3131 ; 28 + vshufi32x4 m5, m27, m26, q2020 ; 20 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + vshufi32x4 m16, m14, m17, q3131 ; 10 + vshufi32x4 m14, m17, q2020 ; 2 + vshufi32x4 m17, m19, m20, q3131 ; 14 + vshufi32x4 m15, m19, m20, q2020 ; 6 + vshufi32x4 m20, m25, m24, q3131 ; 26 + vshufi32x4 m18, m25, m24, q2020 ; 18 + vshufi32x4 m21, m29, m28, q3131 ; 30 + vshufi32x4 m19, m29, m28, q2020 ; 22 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + pmulhrsw m22, m13, [cq+64*16] ; a1 + pmulhrsw m23, m13, [cq+64*20] ; c1 + pmulhrsw m24, m13, [cq+64*24] ; e1 + pmulhrsw m25, m13, [cq+64*28] ; g1 + pmulhrsw m26, m13, [cq+64*17] ; a3 + pmulhrsw m27, m13, [cq+64*21] ; c3 + pmulhrsw m28, m13, [cq+64*25] ; e3 + pmulhrsw m29, m13, [cq+64*29] ; g3 + mova [cq+64* 8], m14 + mova [cq+64* 9], m15 + mova [cq+64*10], m16 + mova [cq+64*11], m17 + mova [cq+64*12], m18 + mova [cq+64*13], m19 + mova [cq+64*14], m20 + mova [cq+64*15], m21 + pmulhrsw m14, m13, [cq+64*18] ; a5 + pmulhrsw m15, m13, [cq+64*22] ; c5 + pmulhrsw m16, m13, [cq+64*26] ; e5 + pmulhrsw m17, m13, [cq+64*30] ; g5 + pmulhrsw m18, m13, [cq+64*19] ; a7 + pmulhrsw m19, m13, [cq+64*23] ; c7 + pmulhrsw m20, m13, [cq+64*27] ; e7 + pmulhrsw m21, m13, [cq+64*31] ; g7 + vinserti32x8 m8, m22, ym23, 1 ; a10 a11 c10 c11 + vshufi32x4 m22, m23, q3232 ; a12 a13 c12 c13 + vinserti32x8 m9, m24, ym25, 1 ; e10 e11 g10 g11 + vshufi32x4 m24, m25, q3232 ; e12 e13 g12 g13 + vinserti32x8 m23, m26, ym27, 1 ; a30 a31 c30 c31 + vshufi32x4 m26, m27, q3232 ; a32 a33 c32 c33 + vinserti32x8 m11, m28, ym29, 1 ; e30 e31 g30 g31 + vshufi32x4 m28, m29, q3232 ; e32 e33 g32 g33 + mova [cq+64* 0], m0 + mova [cq+64* 1], m1 + mova [cq+64* 2], m2 + mova [cq+64* 3], m3 + mova [cq+64* 4], m4 + mova [cq+64* 5], m5 + mova [cq+64* 6], m6 + mova [cq+64* 7], m7 + vinserti32x8 m12, m14, ym15, 1 ; a50 a51 c50 c51 + vshufi32x4 m14, m15, q3232 ; a52 a53 c52 c53 + vinserti32x8 m13, m16, ym17, 1 ; e50 e51 g50 g51 + vshufi32x4 m16, m17, q3232 ; e52 e53 g52 g53 + vinserti32x8 m25, m18, ym19, 1 ; a70 a71 c70 c71 + vshufi32x4 m18, m19, q3232 ; a72 a73 c72 c73 + vinserti32x8 m17, m20, ym21, 1 ; e70 e71 g70 g71 + vshufi32x4 m20, m21, q3232 ; e72 e73 g72 g73 + vshufi32x4 m27, m23, m11, q3131 ; 11 m27 + vshufi32x4 m23, m11, q2020 ; 3 m23 + vshufi32x4 m19, m26, m28, q3131 ; 27 m19 + vshufi32x4 m15, m26, m28, q2020 ; 19 m15 + vshufi32x4 m29, m25, m17, q3131 ; 15 m29 + vshufi32x4 m25, m17, q2020 ; 7 m25 + vshufi32x4 m21, m18, m20, q3131 ; 31 m21 + vshufi32x4 m17, m18, m20, q2020 ; 23 m17 + vshufi32x4 m20, m14, m16, q3131 ; 29 m20 + vshufi32x4 m16, m14, m16, q2020 ; 21 m16 + vshufi32x4 m18, m22, m24, q3131 ; 25 m18 + vshufi32x4 m14, m22, m24, q2020 ; 17 m14 + vshufi32x4 m26, m8, m9, q3131 ; 9 m26 + vshufi32x4 m22, m8, m9, q2020 ; 1 m22 + vshufi32x4 m28, m12, m13, q3131 ; 13 m28 + vshufi32x4 m24, m12, m13, q2020 ; 5 m24 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf + vpbroadcastd m13, [o(pw_16384)] + pmulhrsw m0, m13, [r4-64*21] + pmulhrsw m1, m13, [r4-64*22] + pmulhrsw m2, m13, [r4-64*23] + pmulhrsw m3, m13, [r4-64*24] + pmulhrsw m4, m13, [r4-64*25] + pmulhrsw m5, m13, [r4-64*26] + pmulhrsw m6, m13, [r4-64*27] + pmulhrsw m7, m13, [r4-64*28] + mova [cq+64*16], m14 + mova [cq+64*17], m15 + mova [cq+64*18], m16 + mova [cq+64*19], m17 + mova [cq+64*20], m18 + mova [cq+64*21], m19 + mova [cq+64*22], m20 + mova [cq+64*23], m21 + pmulhrsw m14, m13, [r4-64*12] + pmulhrsw m15, m13, [r4-64*11] + pmulhrsw m16, m13, [r4-64*10] + pmulhrsw m17, m13, [r4-64* 9] + pmulhrsw m18, m13, [r4-64* 8] + pmulhrsw m19, m13, [r4-64* 7] + pmulhrsw m20, m13, [r4-64* 6] + pmulhrsw m21, m13, [r4-64* 5] + mova [cq+64*24], m22 + mova [cq+64*25], m23 + mova [cq+64*26], m24 + mova [cq+64*27], m25 + mova [cq+64*28], m26 + mova [cq+64*29], m27 + mova [cq+64*30], m28 + mova [cq+64*31], m29 + call .transpose_2x8x8_lo + mova [r4-64*12], m1 + mova [r4-64*11], m3 + mova [r4-64*10], m5 + mova [r4-64* 9], m7 + mova [r4-64* 8], m15 + mova [r4-64* 7], m17 + mova [r4-64* 6], m19 + mova [r4-64* 5], m21 + vinserti32x8 m22, m0, ym14, 1 ; f00 f01 h00 h01 + vshufi32x4 m23, m0, m14, q3232 ; f02 f03 h02 h03 + vinserti32x8 m24, m2, ym16, 1 ; f20 f21 h20 h21 + vshufi32x4 m25, m2, m16, q3232 ; f22 f23 h22 h23 + vinserti32x8 m26, m4, ym18, 1 ; f40 f41 h40 h41 + vshufi32x4 m27, m4, m18, q3232 ; f42 f43 h42 h43 + vinserti32x8 m28, m6, ym20, 1 ; f60 f61 h60 h61 + vshufi32x4 m29, m6, m20, q3232 ; f62 f63 h62 h63 + pmulhrsw m0, m13, [r4-64*20] + pmulhrsw m1, m13, [r4-64*19] + pmulhrsw m2, m13, [r4-64*18] + pmulhrsw m3, m13, [r4-64*17] + pmulhrsw m4, m13, [r4-64*16] + pmulhrsw m5, m13, [r4-64*15] + pmulhrsw m6, m13, [r4-64*14] + pmulhrsw m7, m13, [r4-64*13] + pmulhrsw m14, m13, [r4-64*29] + pmulhrsw m15, m13, [r4-64*30] + pmulhrsw m16, m13, [r4-64*31] + pmulhrsw m17, m13, [r4-64*32] + pmulhrsw m18, m13, [r4-64*33] + pmulhrsw m19, m13, [r4-64*34] + pmulhrsw m20, m13, [r4-64*35] + pmulhrsw m21, m13, [r4-64*36] + call .transpose_2x8x8_lo + mova [r4-64*20], m1 + mova [r4-64*19], m3 + mova [r4-64*18], m5 + mova [r4-64*17], m7 + mova [r4-64*16], m15 + mova [r4-64*15], m17 + mova [r4-64*14], m19 + mova [r4-64*13], m21 + vinserti32x8 m1, m4, ym18, 1 ; b40 b41 d40 d41 + vshufi32x4 m5, m4, m18, q3232 ; b42 b43 d42 d43 + vshufi32x4 m4, m0, m14, q3232 ; b02 b03 d02 d03 + vinserti32x8 m0, ym14, 1 ; b00 b01 d00 d01 + vinserti32x8 m14, m2, ym16, 1 ; b20 b21 d20 d21 + vshufi32x4 m18, m2, m16, q3232 ; b22 b23 d22 d23 + vinserti32x8 m15, m6, ym20, 1 ; b60 b61 d60 d61 + vshufi32x4 m19, m6, m20, q3232 ; b62 b63 d62 d63 + vshufi32x4 m2, m0, m22, q3131 ; 8 + vshufi32x4 m0, m22, q2020 ; 0 + vshufi32x4 m3, m1, m26, q3131 ; 12 + vshufi32x4 m1, m26, q2020 ; 4 + vshufi32x4 m6, m4, m23, q3131 ; 24 + vshufi32x4 m4, m23, q2020 ; 16 + vshufi32x4 m7, m5, m27, q3131 ; 28 + vshufi32x4 m5, m27, q2020 ; 20 + call m(inv_txfm_add_dct_dct_32x8_8bpc).main + vshufi32x4 m16, m14, m24, q3131 ; 10 + vshufi32x4 m14, m24, q2020 ; 2 + vshufi32x4 m17, m15, m28, q3131 ; 14 + vshufi32x4 m15, m28, q2020 ; 6 + vshufi32x4 m20, m18, m25, q3131 ; 26 + vshufi32x4 m18, m25, q2020 ; 18 + vshufi32x4 m21, m19, m29, q3131 ; 30 + vshufi32x4 m19, m29, q2020 ; 22 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf + mova m22, [r4-64*20] + mova m26, [r4-64*16] + mova m23, [r4-64*19] + mova m27, [r4-64*15] + mova m24, [r4-64*18] + mova m28, [r4-64*14] + mova m25, [r4-64*17] + mova m29, [r4-64*13] + mova [r4-64*20], m14 + mova [r4-64*19], m15 + mova [r4-64*18], m16 + mova [r4-64*17], m17 + mova [r4-64*16], m18 + mova [r4-64*15], m19 + mova [r4-64*14], m20 + mova [r4-64*13], m21 + mova m19, [r4-64*12] + mova m11, [r4-64* 8] + mova m20, [r4-64*11] + mova m12, [r4-64* 7] + mova m21, [r4-64*10] + mova m8, [r4-64* 6] + mova m9, [r4-64* 9] + mova m18, [r4-64* 5] + vshufi32x4 m14, m22, m26, q3232 ; b12 b13 d12 d13 + vinserti32x8 m22, ym26, 1 ; b10 b11 d10 d11 + vshufi32x4 m15, m23, m27, q3232 ; b32 b33 d32 d33 + vinserti32x8 m23, ym27, 1 ; b30 b31 d30 d31 + vshufi32x4 m16, m24, m28, q3232 ; b52 b53 d52 d53 + vinserti32x8 m24, ym28, 1 ; b50 b51 d50 d51 + vshufi32x4 m17, m25, m29, q3232 ; b72 b73 d72 d73 + vinserti32x8 m25, ym29, 1 ; b70 b71 d70 d71 + vinserti32x8 m27, m19, ym11, 1 ; f10 f11 h10 h11 + vshufi32x4 m19, m11, q3232 ; f12 f13 h12 h13 + vinserti32x8 m28, m20, ym12, 1 ; f30 f31 h30 h31 + vshufi32x4 m20, m12, q3232 ; f32 f33 h32 h33 + vinserti32x8 m29, m21, ym8, 1 ; f50 f51 h50 h51 + vshufi32x4 m21, m8, q3232 ; f52 f53 h52 h53 + vinserti32x8 m8, m9, ym18, 1 ; f70 f71 h70 h71 + vshufi32x4 m9, m18, q3232 ; f72 f73 h72 h73 + vshufi32x4 m26, m22, m27, q3131 ; 9 + vshufi32x4 m22, m27, q2020 ; 1 + vshufi32x4 m27, m23, m28, q3131 ; 11 + vshufi32x4 m23, m28, q2020 ; 3 + vshufi32x4 m28, m24, m29, q3131 ; 13 + vshufi32x4 m24, m29, q2020 ; 5 + vshufi32x4 m29, m25, m8, q3131 ; 15 + vshufi32x4 m25, m8, q2020 ; 7 + vshufi32x4 m18, m14, m19, q3131 ; 25 + vshufi32x4 m14, m19, q2020 ; 17 + vshufi32x4 m19, m15, m20, q3131 ; 27 + vshufi32x4 m15, m20, q2020 ; 19 + vshufi32x4 m20, m16, m21, q3131 ; 29 + vshufi32x4 m16, m21, q2020 ; 21 + vshufi32x4 m21, m17, m9, q3131 ; 31 + vshufi32x4 m17, m9, q2020 ; 23 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf + jmp .end +.fast: ; bottom/right halves are zero + {evex}vpmulhrsw ym8, ym23, [cq+64* 4] + {evex}vpmulhrsw xm1, xm23, [cq+64*12] + mova m28, [o(dup16_perm)] + {evex}vpmulhrsw ym7, ym23, [cq+64* 8] + vpmulhrsw ym22, ym23, [cq+64* 0] + vpermb m8, m28, m8 + vpermb ym1, ym28, ym1 + vpermb m7, m28, m7 + pmovzxwd m9, ym22 + pslld m9, 16 + call m(idct_16x16_internal_8bpc).main_fast2 + {evex}vpmulhrsw ym21, ym23, [cq+64* 2] + {evex}vpmulhrsw xm15, xm23, [cq+64*14] + {evex}vpmulhrsw xm18, xm23, [cq+64*10] + {evex}vpmulhrsw ym14, ym23, [cq+64* 6] + vpermb m21, m28, m21 + punpcklwd xm15, xm15 + vpermb ym18, ym28, ym18 + vpermb m14, m28, m14 + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + vpmulhrsw ym22, ym23, [cq+64* 1] + {evex}vpmulhrsw xm29, xm23, [cq+64*15] + {evex}vpmulhrsw xm26, xm23, [cq+64* 9] + {evex}vpmulhrsw ym25, ym23, [cq+64* 7] + {evex}vpmulhrsw ym24, ym23, [cq+64* 5] + {evex}vpmulhrsw xm27, xm23, [cq+64*11] + {evex}vpmulhrsw xm8, xm23, [cq+64*13] + {evex}vpmulhrsw ym23, [cq+64* 3] + vpermb m22, m28, m22 + punpcklwd xm29, xm29 + vpermb ym26, ym28, ym26 + vpermb m25, m28, m25 + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + REPX {vpermb x, m28, x}, m24, m27, m23 + punpcklwd xm28, xm8, xm8 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf_fast + mov r4, rsp + vpbroadcastd m13, [o(pw_16384)] + mova [r4+64*16], m4 + mova [r4+64*17], m5 + mova [r4+64*18], m6 + mova [r4+64*19], m7 + mova [r4+64*28], m26 + mova [r4+64*29], m27 + mova [r4+64*30], m28 + mova [r4+64*31], m29 + call m(inv_txfm_add_dct_dct_64x16_8bpc).pass1_end + mova [r4+64*20], m22 + mova [r4+64*21], m23 + mova [r4+64*22], m24 + mova [r4+64*23], m25 + mova [r4+64*24], m26 + mova [r4+64*25], m27 + mova [r4+64*26], m28 + mova [r4+64*27], m29 + call .pass2_fast + mova [cq+64* 8], m14 + mova [cq+64* 9], m15 + mova [cq+64*10], m16 + mova [cq+64*11], m17 + mova [cq+64*12], m18 + mova [cq+64*13], m19 + mova [cq+64*14], m20 + mova [cq+64*15], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast + mova [cq+64* 0], m0 + mova [cq+64* 1], m1 + mova [cq+64* 2], m2 + mova [cq+64* 3], m3 + mova [cq+64* 4], m4 + mova [cq+64* 5], m5 + mova [cq+64* 6], m6 + mova [cq+64* 7], m7 + pmulhrsw m0, m13, [r4+64*16] + pmulhrsw m1, m13, [r4+64*17] + pmulhrsw m2, m13, [r4+64*18] + pmulhrsw m3, m13, [r4+64*19] + pmulhrsw m4, m13, [r4+64*20] + pmulhrsw m5, m13, [r4+64*21] + pmulhrsw m6, m13, [r4+64*22] + pmulhrsw m7, m13, [r4+64*23] + mova [cq+64*16], m14 + mova [cq+64*17], m15 + mova [cq+64*18], m16 + mova [cq+64*19], m17 + mova [cq+64*20], m18 + mova [cq+64*21], m19 + mova [cq+64*22], m20 + mova [cq+64*23], m21 + pmulhrsw m14, m13, [r4+64*24] + pmulhrsw m15, m13, [r4+64*25] + pmulhrsw m16, m13, [r4+64*26] + pmulhrsw m17, m13, [r4+64*27] + pmulhrsw m18, m13, [r4+64*28] + pmulhrsw m19, m13, [r4+64*29] + pmulhrsw m20, m13, [r4+64*30] + pmulhrsw m21, m13, [r4+64*31] + mova [cq+64*24], m22 + mova [cq+64*25], m23 + mova [cq+64*26], m24 + mova [cq+64*27], m25 + mova [cq+64*28], m26 + mova [cq+64*29], m27 + mova [cq+64*30], m28 + mova [cq+64*31], m29 + call m(inv_txfm_add_dct_dct_64x16_8bpc).transpose_round + call .pass2_fast + mova [r4+64*16], m14 + mova [r4+64*17], m15 + mova [r4+64*18], m16 + mova [r4+64*19], m17 + mova [r4+64*20], m18 + mova [r4+64*21], m19 + mova [r4+64*22], m20 + mova [r4+64*23], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast +.end: + vpbroadcastd m13, [o(pw_2048)] + lea r5, [strideq*3] + pxor m12, m12 + lea r3, [dstq+r5*8] + lea r6, [strideq+r5] ; stride*4 + add r3, r6 ; dst+stride*28 +%macro IDCT_64x32_END 5 ; src16, src32, mem, off_lo, off_hi + mova m11, [cq+64*( %3)] ; 0 + mova m9, [cq+64*(31-%3)] ; 31 +%if %3 >= 8 + mova m%1, [rsp+64*(%1+16)] +%endif + mova m10, [dstq+%4] + paddsw m8, m11, m9 + psubsw m11, m9 + paddsw m9, m%1, m%2 + psubsw m%1, m%2 + punpcklbw m%2, m10, m12 + punpckhbw m10, m12 + pmulhrsw m8, m13 + pmulhrsw m9, m13 + paddw m8, m%2 + paddw m9, m10 + mova m10, [r3+%5] + pmulhrsw m11, m13 + pmulhrsw m%1, m13 + mova [cq+64*( %3)], m12 + mova [cq+64*(31-%3)], m12 + punpcklbw m%2, m10, m12 + punpckhbw m10, m12 + packuswb m8, m9 + paddw m11, m%2 + paddw m%1, m10 + packuswb m11, m%1 + mova [dstq+%4], m8 + mova [r3 +%5], m11 +%if %3 == 3 || %3 == 7 || %3 == 11 + add dstq, r6 + sub r3, r6 +%endif +%endmacro + IDCT_64x32_END 0, 29, 0, strideq*0, r5 + IDCT_64x32_END 1, 28, 1, strideq*1, strideq*2 + IDCT_64x32_END 2, 27, 2, strideq*2, strideq*1 + IDCT_64x32_END 3, 26, 3, r5 , strideq*0 + IDCT_64x32_END 4, 25, 4, strideq*0, r5 + IDCT_64x32_END 5, 24, 5, strideq*1, strideq*2 + IDCT_64x32_END 6, 23, 6, strideq*2, strideq*1 + IDCT_64x32_END 7, 22, 7, r5 , strideq*0 + IDCT_64x32_END 0, 21, 8, strideq*0, r5 + IDCT_64x32_END 1, 20, 9, strideq*1, strideq*2 + IDCT_64x32_END 2, 19, 10, strideq*2, strideq*1 + IDCT_64x32_END 3, 18, 11, r5 , strideq*0 + IDCT_64x32_END 4, 17, 12, strideq*0, r5 + IDCT_64x32_END 5, 16, 13, strideq*1, strideq*2 + IDCT_64x32_END 6, 15, 14, strideq*2, strideq*1 + IDCT_64x32_END 7, 14, 15, r5 , strideq*0 + RET +ALIGN function_align +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 32 + imul r6d, 181 + add r6d, 128 + sar r6d, 8 + imul r6d, 181 + add r6d, 128+256 + sar r6d, 8+1 + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).dconly2 +ALIGN function_align +.pass1_end_part1: +%macro IDCT_64x32_PASS1_END 3 ; src16, src32, src64 +%if %1 != %3 + mova m%1, [cq+64*%1] +%endif + mova m9, [r4+64*(%3-36)] ; idct64 32+n + mova m11, [r4+64*(-5-%3)] ; idct64 63-n + psubsw m8, m%1, m%2 ; idct32 31-n + paddsw m%1, m%2 ; idct32 0+n +%if %1 == %3 + psubsw m%2, m8, m9 ; out 32+n e + paddsw m8, m9 ; out 31-n d + psubsw m9, m%1, m11 ; out 63-n h + paddsw m%1, m11 ; out 0+n a +%else + paddsw m%2, m8, m9 ; out 23-n c + psubsw m8, m9 ; out 40+n f + paddsw m9, m%1, m11 ; out 8+n b + psubsw m%1, m11 ; out 55-n g +%endif + mova [r4+64*(%3-36)], m8 + mova [r4+64*(-5-%3)], m9 +%endmacro + IDCT_64x32_PASS1_END 0, 29, 0 + IDCT_64x32_PASS1_END 1, 28, 1 + IDCT_64x32_PASS1_END 2, 27, 2 + IDCT_64x32_PASS1_END 3, 26, 3 + IDCT_64x32_PASS1_END 4, 25, 4 + IDCT_64x32_PASS1_END 5, 24, 5 + IDCT_64x32_PASS1_END 6, 23, 6 + IDCT_64x32_PASS1_END 7, 22, 7 +.transpose_2x8x8_hi: ; m0-m7 + m22-m29 (inverted) + punpcklwd m8, m25, m24 ; e0 f0 e1 f1 e2 f2 e3 f3 + punpckhwd m25, m24 ; e4 f4 e5 f5 e6 f6 e7 f7 + punpcklwd m24, m23, m22 ; g0 h0 g1 h1 g2 h2 g3 h3 + punpckhwd m23, m22 ; g4 h4 g5 h5 g6 h6 g7 h7 + punpcklwd m22, m29, m28 ; a0 b0 a1 b1 a2 b2 a3 b3 + punpckhwd m29, m28 ; a4 b4 a5 b5 a6 b6 a7 b7 + punpcklwd m28, m27, m26 ; c0 d0 c1 d1 c2 d2 c3 d3 + punpckhwd m27, m26 ; c4 d4 c5 d5 c6 d6 c7 d7 + punpckldq m26, m29, m27 ; a4 b4 c4 d4 a5 b5 c5 d5 + punpckhdq m29, m27 ; a6 b6 c6 d6 a7 b7 c7 d7 + punpckldq m27, m8, m24 ; e0 f0 g0 h0 e1 f1 g1 h1 + punpckhdq m8, m24 ; e2 f2 g2 h2 e3 f3 g3 h3 + punpckhdq m24, m22, m28 ; a2 b2 c2 d2 a3 b3 c3 d3 + punpckldq m22, m28 ; a0 b0 c0 d0 a1 b1 c1 d1 + punpckldq m28, m25, m23 ; e4 f4 g4 h4 e5 f5 g5 h5 + punpckhdq m25, m23 ; e6 f6 g6 h6 e7 f7 g7 h7 + punpckhqdq m23, m22, m27 ; 1 23 + punpcklqdq m22, m27 ; 0 22 + punpckhqdq m27, m26, m28 ; 5 27 + punpcklqdq m26, m28 ; 4 26 + punpcklqdq m28, m29, m25 ; 6 28 + punpckhqdq m29, m25 ; 7 29 + punpckhqdq m25, m24, m8 ; 3 25 + punpcklqdq m24, m8 ; 2 24 +.transpose_8x8: + punpckhwd m8, m4, m5 + punpcklwd m4, m5 + punpckhwd m5, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m6, m7 + punpcklwd m6, m7 + punpckhwd m7, m2, m3 + punpcklwd m2, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckldq m2, m4, m6 + punpckhdq m4, m6 + punpckhdq m6, m5, m7 + punpckldq m5, m7 + punpckldq m7, m8, m1 + punpckhdq m8, m1 + punpckhqdq m1, m0, m2 + punpcklqdq m0, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + punpcklqdq m4, m5, m7 + punpckhqdq m5, m7 + punpckhqdq m7, m6, m8 + punpcklqdq m6, m8 + ret +.pass1_end_part2: + IDCT_64x32_PASS1_END 0, 21, 8 + IDCT_64x32_PASS1_END 1, 20, 9 + IDCT_64x32_PASS1_END 2, 19, 10 + IDCT_64x32_PASS1_END 3, 18, 11 + IDCT_64x32_PASS1_END 4, 17, 12 + IDCT_64x32_PASS1_END 5, 16, 13 + IDCT_64x32_PASS1_END 6, 15, 14 + IDCT_64x32_PASS1_END 7, 14, 15 +.transpose_2x8x8_lo: ; m0-m7 (inverted) + m14-m21 + punpcklwd m8, m3, m2 + punpckhwd m3, m2 + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m7, m6 + punpckhwd m7, m6 + punpcklwd m6, m5, m4 + punpckhwd m5, m4 + punpckldq m4, m7, m5 + punpckhdq m7, m5 + punpckldq m5, m8, m2 + punpckhdq m8, m2 + punpckhdq m2, m0, m6 + punpckldq m0, m6 + punpckldq m6, m3, m1 + punpckhdq m3, m1 + punpckhqdq m1, m0, m5 + punpcklqdq m0, m5 + punpckhqdq m5, m4, m6 + punpcklqdq m4, m6 + punpcklqdq m6, m7, m3 + punpckhqdq m7, m3 + punpckhqdq m3, m2, m8 + punpcklqdq m2, m8 + punpckhwd m8, m18, m19 + punpcklwd m18, m19 + punpckhwd m19, m14, m15 + punpcklwd m14, m15 + punpckhwd m15, m20, m21 + punpcklwd m20, m21 + punpckhwd m21, m16, m17 + punpcklwd m16, m17 + punpckhdq m17, m14, m16 + punpckldq m14, m16 + punpckldq m16, m18, m20 + punpckhdq m18, m20 + punpckhdq m20, m19, m21 + punpckldq m19, m21 + punpckldq m21, m8, m15 + punpckhdq m8, m15 + punpckhqdq m15, m14, m16 + punpcklqdq m14, m16 + punpcklqdq m16, m17, m18 + punpckhqdq m17, m18 + punpcklqdq m18, m19, m21 + punpckhqdq m19, m21 + punpckhqdq m21, m20, m8 + punpcklqdq m20, m8 + ret +.pass2_fast: + vshufi32x4 m24, m9, m15, q3131 ; 5 + vshufi32x4 m22, m9, m15, q2020 ; 1 + vshufi32x4 m15, m1, m16, q3131 ; 6 + vshufi32x4 m14, m1, m16, q2020 ; 2 + vshufi32x4 m1, m0, m3, q3131 ; 4 + vshufi32x4 m0, m3, q2020 ; 0 + vshufi32x4 m3, m8, m2, q3131 ; 12 + vshufi32x4 m2, m8, m2, q2020 ; 8 + vshufi32x4 m25, m11, m17, q3131 ; 7 + vshufi32x4 m23, m11, m17, q2020 ; 3 + vshufi32x4 m17, m5, m19, q3131 ; 14 + vshufi32x4 m16, m5, m19, q2020 ; 10 + vshufi32x4 m29, m6, m20, q3131 ; 15 + vshufi32x4 m27, m6, m20, q2020 ; 11 + vshufi32x4 m28, m4, m18, q3131 ; 13 + vshufi32x4 m26, m4, m18, q2020 ; 9 + jmp m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + +cglobal inv_txfm_add_dct_dct_64x64_8bpc, 4, 7, 0, dst, stride, c, eob + lea r5, [o_base] + test eobd, eobd + jz .dconly + PROLOGUE 0, 7, 30, 64*96, dst, stride, c, eob +%undef cmp + cmp eobd, 136 + jb .fast + mova m0, [cq+64* 1] + mova m1, [cq+64*31] + mova m2, [cq+64*17] + mova m3, [cq+64*15] + vpbroadcastd m10, [o(pd_2048)] + mov r4, rsp + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, [cq+64* 7] + mova m1, [cq+64*25] + mova m2, [cq+64*23] + mova m3, [cq+64* 9] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, [cq+64* 5] + mova m1, [cq+64*27] + mova m2, [cq+64*21] + mova m3, [cq+64*11] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + mova m0, [cq+64* 3] + mova m1, [cq+64*29] + mova m2, [cq+64*19] + mova m3, [cq+64*13] + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + mova m0, [cq+64* 0] + mova m1, [cq+64* 8] + mova m2, [cq+64*16] + mova m3, [cq+64*24] + mova m14, [cq+64* 4] + mova m15, [cq+64*12] + mova m16, [cq+64*20] + mova m17, [cq+64*28] + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + mova m22, [cq+64* 2] + mova m29, [cq+64*30] + mova m26, [cq+64*18] + mova m25, [cq+64*14] + mova m24, [cq+64*10] + mova m27, [cq+64*22] + mova m28, [cq+64*26] + mova m23, [cq+64* 6] + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast + vpbroadcastd m13, [o(pw_8192)] + call m(inv_txfm_add_dct_dct_64x32_8bpc).pass1_end_part1 + mova [r4+64*36], m1 + mova [r4+64*37], m3 + mova [r4+64*38], m5 + mova [r4+64*39], m7 + mova [r4+64*44], m23 + mova [r4+64*45], m25 + mova [r4+64*46], m27 + mova [r4+64*47], m29 + pmulhrsw m23, m13, m0 ; a0 + pmulhrsw m25, m13, m2 ; a2 + pmulhrsw m27, m13, m4 ; a4 + pmulhrsw m29, m13, m6 ; a6 + call m(inv_txfm_add_dct_dct_64x32_8bpc).pass1_end_part2 + lea r6, [r4-64*4] + add r4, 64*28 + call .pass2_end + mov r4, rsp + mova m0, [r4+64*23] + mova m1, [r4+64*22] + mova m2, [r4+64*21] + mova m3, [r4+64*20] + mova m4, [r4+64*19] + mova m5, [r4+64*18] + mova m6, [r4+64*17] + mova m7, [r4+64*16] + mova m22, [r4+64*15] + mova m23, [r4+64*14] + mova m24, [r4+64*13] + mova m25, [r4+64*12] + mova m26, [r4+64*11] + mova m27, [r4+64*10] + mova m28, [r4+64* 9] + mova m29, [r4+64* 8] + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_2x8x8_hi + vpbroadcastd m13, [o(pw_8192)] + mova [r4+64* 8], m1 + mova [r4+64* 9], m3 + mova [r4+64*10], m5 + mova [r4+64*11], m7 + mova [r4+64*16], m23 + mova [r4+64*17], m25 + mova [r4+64*18], m27 + mova [r4+64*19], m29 + pmulhrsw m23, m13, m0 ; b0 + pmulhrsw m25, m13, m2 ; b2 + pmulhrsw m27, m13, m4 ; b4 + pmulhrsw m29, m13, m6 ; b6 + mova m0, [r4+64*31] + mova m1, [r4+64*30] + mova m2, [r4+64*29] + mova m3, [r4+64*28] + mova m4, [r4+64*27] + mova m5, [r4+64*26] + mova m6, [r4+64*25] + mova m7, [r4+64*24] + mova m14, [r4+64* 7] + mova m15, [r4+64* 6] + mova m16, [r4+64* 5] + mova m17, [r4+64* 4] + mova m18, [r4+64* 3] + mova m19, [r4+64* 2] + mova m20, [r4+64* 1] + mova m21, [r4+64* 0] + call m(inv_txfm_add_dct_dct_64x32_8bpc).transpose_2x8x8_lo + mov r6, cq + call .pass2_end + jmp .end +.fast: ; bottom/right halves are zero + mova m28, [o(dup16_perm)] + pmovzxwd m9, [cq+64* 0] + vpermb m8, m28, [cq+64* 4] + vpermb ym1, ym28, [cq+64*12] + vpermb m7, m28, [cq+64* 8] + pslld m9, 16 + call m(idct_16x16_internal_8bpc).main_fast2 + vpermb m21, m28, [cq+64* 2] + vpermb ym15, ym28, [cq+64*14] + vpermb ym18, ym28, [cq+64*10] + vpermb m14, m28, [cq+64* 6] + call m(inv_txfm_add_dct_dct_16x32_8bpc).main_oddhalf_fast2 + vpermb m22, m28, [cq+64* 1] + vpermb ym29, ym28, [cq+64*15] + vpermb ym26, ym28, [cq+64* 9] + vpermb m25, m28, [cq+64* 7] + vpermb m24, m28, [cq+64* 5] + vpermb ym27, ym28, [cq+64*11] + vpermb m23, m28, [cq+64* 3] + vpermb ym28, ym28, [cq+64*13] + mova [cq+64* 0], m14 + mova [cq+64* 1], m15 + mova [cq+64* 2], m16 + mova [cq+64* 3], m17 + mova [cq+64* 4], m18 + mova [cq+64* 5], m19 + mova [cq+64* 6], m20 + mova [cq+64* 7], m21 + call m(inv_txfm_add_dct_dct_16x64_8bpc).main_oddhalf_fast + vpbroadcastd m13, [o(pw_8192)] + mova [cq+64*16], m4 + mova [cq+64*17], m5 + mova [cq+64*18], m6 + mova [cq+64*19], m7 + mova [cq+64*28], m26 + mova [cq+64*29], m27 + mova [cq+64*30], m28 + mova [cq+64*31], m29 + call m(inv_txfm_add_dct_dct_64x16_8bpc).pass1_end + mova [cq+64*20], m22 + mova [cq+64*21], m23 + mova [cq+64*22], m24 + mova [cq+64*23], m25 + mova [cq+64*24], m26 + mova [cq+64*25], m27 + mova [cq+64*26], m28 + mova [cq+64*27], m29 + lea r4, [rsp+64*64] + lea r3, [rsp+64*32] + call .pass2_fast + pmulhrsw m0, m13, [cq+64*16] + pmulhrsw m1, m13, [cq+64*17] + pmulhrsw m2, m13, [cq+64*18] + pmulhrsw m3, m13, [cq+64*19] + pmulhrsw m4, m13, [cq+64*20] + pmulhrsw m5, m13, [cq+64*21] + pmulhrsw m6, m13, [cq+64*22] + pmulhrsw m7, m13, [cq+64*23] + pmulhrsw m14, m13, [cq+64*24] + pmulhrsw m15, m13, [cq+64*25] + pmulhrsw m16, m13, [cq+64*26] + pmulhrsw m17, m13, [cq+64*27] + pmulhrsw m18, m13, [cq+64*28] + pmulhrsw m19, m13, [cq+64*29] + pmulhrsw m20, m13, [cq+64*30] + pmulhrsw m21, m13, [cq+64*31] + call m(inv_txfm_add_dct_dct_64x16_8bpc).transpose_round + mov r4, rsp + mov r3, cq + call .pass2_fast +.end: + vpbroadcastd m17, [o(pw_2048)] + lea r5, [strideq*8] + mov r3, dstq + pxor m16, m16 + sub r4, 64*5 ; rsp+64*31 + mov r6, rsp +.end_loop: + mova m2, [r6+64*32] ; idct16 0+n lo + mova m7, [r6+64*48] ; idct32 31-n lo + mova m6, [cq+64* 0] ; idct16 0+n hi + mova m0, [cq+64*16] ; idct32 31-n hi + mova m4, [r4+64*64] ; idct64 63-n lo + mova m1, [r4+64* 0] ; idct64 63-n hi + mova m5, [r6+64*64] ; idct64 32+n lo + mova m8, [r6+64* 0] ; idct64 32+n hi + sub r3, strideq + paddsw m3, m2, m7 ; idct32 0+n lo + mova m12, [dstq+r5*0] + psubsw m2, m7 ; idct32 31-n lo + mova m15, [r3 +r5*8] + paddsw m7, m6, m0 ; idct32 0+n hi + mova m13, [r3 +r5*4] + psubsw m6, m0 ; idct32 31-n hi + mova m14, [dstq+r5*4] + paddsw m0, m3, m4 ; out 0+n lo + add r6, 64 + psubsw m3, m4 ; out 63-n lo + sub r4, 64 + paddsw m4, m7, m1 ; out 0+n hi + mova [cq+64* 0], m16 + psubsw m7, m1 ; out 63-n hi + mova [cq+64*16], m16 + paddsw m1, m2, m5 ; out 31-n lo + add cq, 64 + psubsw m2, m5 ; out 32+n lo + paddsw m5, m6, m8 ; out 31-n hi + psubsw m6, m8 ; out 32+n hi + pmulhrsw m0, m17 + punpcklbw m8, m12, m16 + pmulhrsw m4, m17 + punpckhbw m12, m16 + pmulhrsw m3, m17 + punpcklbw m11, m15, m16 + pmulhrsw m7, m17 + punpckhbw m15, m16 + pmulhrsw m1, m17 + punpcklbw m9, m13, m16 + pmulhrsw m5, m17 + punpckhbw m13, m16 + pmulhrsw m2, m17 + punpcklbw m10, m14, m16 + pmulhrsw m6, m17 + punpckhbw m14, m16 + paddw m0, m8 + paddw m4, m12 + packuswb m0, m4 + paddw m3, m11 + paddw m7, m15 + packuswb m3, m7 + paddw m1, m9 + paddw m5, m13 + packuswb m1, m5 + paddw m2, m10 + paddw m6, m14 + packuswb m2, m6 + mova [dstq+r5*0], m0 + mova [r3 +r5*8], m3 + mova [r3 +r5*4], m1 + mova [dstq+r5*4], m2 + add dstq, strideq + cmp r6, r4 + jb .end_loop + RET +.dconly: + movsx r6d, word [cq] + mov [cq], eobd + or r3d, 64 + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).dconly +ALIGN function_align +.pass2_end: + REPX {pmulhrsw x, m13}, m22, m24, m26, m28, m14, m16, m18, m20, m0, m2, m4, m6 + mova [r4+64*20], m1 + mova [r4+64*21], m3 + mova [r4+64*22], m5 + mova [r4+64*23], m7 + vinserti32x8 m1, m23, ym14, 1 ; a00 a01 c00 c01 + vshufi32x4 m3, m23, m14, q3232 ; a02 a03 c02 c03 + vinserti32x8 m5, m22, ym0, 1 ; e00 e01 g00 g01 + vshufi32x4 m14, m22, m0, q3232 ; e02 e03 g02 g03 + mova [r4+64*12], m15 + mova [r4+64*13], m17 + mova [r4+64*14], m19 + mova [r4+64*15], m21 + vinserti32x8 m15, m27, ym18, 1 ; a40 a41 c40 c41 + vshufi32x4 m17, m27, m18, q3232 ; a42 a43 c42 c43 + vinserti32x8 m18, m26, ym4, 1 ; e40 e41 g40 g41 + vshufi32x4 m19, m26, m4, q3232 ; e42 e43 g42 g43 + vinserti32x8 m22, m25, ym16, 1 ; a20 a21 c20 c21 + vshufi32x4 m26, m25, m16, q3232 ; a22 a23 c22 c23 + vinserti32x8 m25, m24, ym2, 1 ; e20 e21 g20 g21 + vshufi32x4 m27, m24, m2, q3232 ; e22 e23 g22 g23 + vinserti32x8 m23, m29, ym20, 1 ; a60 a61 c60 c61 + vshufi32x4 m29, m20, q3232 ; a62 a63 c62 c63 + vshufi32x4 m13, m28, m6, q3232 ; e62 e63 g62 g63 + vinserti32x8 m28, ym6, 1 ; e60 e61 g60 g61 + vshufi32x4 m0, m1, m5, q2020 ; 0 + vshufi32x4 m1, m5, q3131 ; 8 + vshufi32x4 m2, m3, m14, q2020 ; 16 + vshufi32x4 m3, m14, q3131 ; 24 + vshufi32x4 m14, m15, m18, q2020 ; 4 + vshufi32x4 m15, m18, q3131 ; 12 + vshufi32x4 m16, m17, m19, q2020 ; 20 + vshufi32x4 m17, m19, q3131 ; 28 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast + vshufi32x4 m24, m22, m25, q3131 ; 10 + vshufi32x4 m22, m25, q2020 ; 2 + vshufi32x4 m25, m23, m28, q3131 ; 14 + vshufi32x4 m23, m28, q2020 ; 6 + vshufi32x4 m28, m26, m27, q3131 ; 26 + vshufi32x4 m26, m27, q2020 ; 18 + vshufi32x4 m27, m29, m13, q2020 ; 22 + vshufi32x4 m29, m13, q3131 ; 30 + mova [r6+64* 0], m0 + mova [r6+64* 1], m1 + mova [r6+64* 2], m2 + mova [r6+64* 3], m3 + mova [r6+64* 4], m4 + mova [r6+64* 5], m5 + mova [r6+64* 6], m6 + mova [r6+64* 7], m7 + mova [r6+64* 8], m14 + mova [r6+64* 9], m15 + mova [r6+64*10], m16 + mova [r6+64*11], m17 + mova [r6+64*12], m18 + mova [r6+64*13], m19 + mova [r6+64*14], m20 + mova [r6+64*15], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast + vpbroadcastd m13, [o(pw_8192)] + mova [r6+64*16], m29 + mova [r6+64*17], m28 + mova [r6+64*18], m27 + mova [r6+64*19], m26 + mova [r6+64*20], m25 + mova [r6+64*21], m24 + mova [r6+64*22], m23 + mova [r6+64*23], m22 + mova [r6+64*24], m21 + mova [r6+64*25], m20 + mova [r6+64*26], m19 + mova [r6+64*27], m18 + mova [r6+64*28], m17 + mova [r6+64*29], m16 + mova [r6+64*30], m15 + mova [r6+64*31], m14 + pmulhrsw m15, m13, [r4+64* 8] ; 1 9 17 25 + pmulhrsw m16, m13, [r4+64*12] + pmulhrsw m17, m13, [r4+64*16] + pmulhrsw m18, m13, [r4+64*20] + pmulhrsw m19, m13, [r4+64*11] ; 7 15 23 31 + pmulhrsw m20, m13, [r4+64*15] + pmulhrsw m21, m13, [r4+64*19] + pmulhrsw m22, m13, [r4+64*23] + vinserti32x8 m14, m15, ym16, 1 ; a1 a9 c1 c9 + vshufi32x4 m15, m16, q3232 ; a17 a25 c17 c25 + vinserti32x8 m16, m17, ym18, 1 ; e1 e9 g1 g9 + vshufi32x4 m17, m18, q3232 ; e17 e25 g17 g25 + pmulhrsw m23, m13, [r4+64*10] ; 5 13 21 29 + pmulhrsw m24, m13, [r4+64*14] + pmulhrsw m25, m13, [r4+64*18] + pmulhrsw m26, m13, [r4+64*22] + vinserti32x8 m18, m19, ym20, 1 ; a7 a15 c7 c15 + vshufi32x4 m19, m20, q3232 ; a23 a31 c23 c31 + vinserti32x8 m20, m21, ym22, 1 ; e7 e15 g7 g15 + vshufi32x4 m21, m22, q3232 ; e23 e31 g23 g31 + pmulhrsw m27, m13, [r4+64* 9] ; 3 11 19 27 + pmulhrsw m28, m13, [r4+64*13] + pmulhrsw m29, m13, [r4+64*17] + pmulhrsw m13, [r4+64*21] + vshufi32x4 m0, m14, m16, q2020 ; 1 + vshufi32x4 m1, m19, m21, q3131 ; 31 + vshufi32x4 m2, m15, m17, q2020 ; 17 + vshufi32x4 m3, m18, m20, q3131 ; 15 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + vshufi32x4 m0, m18, m20, q2020 ; 7 + vshufi32x4 m1, m15, m17, q3131 ; 25 + vshufi32x4 m2, m19, m21, q2020 ; 23 + vshufi32x4 m3, m14, m16, q3131 ; 9 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + vinserti32x8 m22, m23, ym24, 1 ; a5 a13 c5 c13 + vshufi32x4 m23, m24, q3232 ; a21 a29 c21 c29 + vinserti32x8 m24, m25, ym26, 1 ; e5 e13 g5 g13 + vshufi32x4 m25, m26, q3232 ; e21 e29 g21 g29 + vinserti32x8 m26, m27, ym28, 1 ; a3 a11 c3 c11 + vshufi32x4 m27, m28, q3232 ; a19 a27 c19 c27 + vinserti32x8 m28, m29, ym13, 1 ; e3 e11 g3 g11 + vshufi32x4 m29, m13, q3232 ; e19 e17 g19 g27 + vshufi32x4 m0, m22, m24, q2020 ; 5 + vshufi32x4 m1, m27, m29, q3131 ; 27 + vshufi32x4 m2, m23, m25, q2020 ; 21 + vshufi32x4 m3, m26, m28, q3131 ; 11 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + vshufi32x4 m0, m26, m28, q2020 ; 3 + vshufi32x4 m1, m23, m25, q3131 ; 29 + vshufi32x4 m2, m27, m29, q2020 ; 19 + vshufi32x4 m3, m22, m24, q3131 ; 13 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1 + jmp m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 +ALIGN function_align +.pass2_fast: + vshufi32x4 m23, m1, m16, q3131 ; 6 + vshufi32x4 m22, m1, m16, q2020 ; 2 + vshufi32x4 m14, m0, m3, q3131 ; 4 + vshufi32x4 m26, m0, m3, q2020 ; 0 + vshufi32x4 m28, m9, m15, q3131 ; 5 + vshufi32x4 m0, m9, m15, q2020 ; 1 + vshufi32x4 m16, m11, m17, q3131 ; 7 + vshufi32x4 m29, m11, m17, q2020 ; 3 + vshufi32x4 m15, m8, m2, q3131 ; 12 + vshufi32x4 m27, m8, m2, q2020 ; 8 + vshufi32x4 m25, m5, m19, q3131 ; 14 + vshufi32x4 m24, m5, m19, q2020 ; 10 + vshufi32x4 m3, m6, m20, q3131 ; 15 + vshufi32x4 m19, m6, m20, q2020 ; 11 + vshufi32x4 m17, m4, m18, q3131 ; 13 + vshufi32x4 m18, m4, m18, q2020 ; 9 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m16 + mova m3, m18 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m28 + mova m3, m19 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + mova m0, m29 + mova m3, m17 + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part1_fast + call m(inv_txfm_add_dct_dct_32x64_8bpc).main_part2 + mova m0, m26 + mova m1, m27 + call m(inv_txfm_add_dct_dct_32x16_8bpc).main_oddhalf_fast2 + mova [r3+64* 0], m0 + mova [r3+64* 1], m1 + mova [r3+64* 2], m2 + mova [r3+64* 3], m3 + mova [r3+64* 4], m4 + mova [r3+64* 5], m5 + mova [r3+64* 6], m6 + mova [r3+64* 7], m7 + mova [r3+64* 8], m14 + mova [r3+64* 9], m15 + mova [r3+64*10], m16 + mova [r3+64*11], m17 + mova [r3+64*12], m18 + mova [r3+64*13], m19 + mova [r3+64*14], m20 + mova [r3+64*15], m21 + call m(inv_txfm_add_dct_dct_32x32_8bpc).main_oddhalf_fast2 + mova [r3+64*16], m29 + mova [r3+64*17], m28 + mova [r3+64*18], m27 + mova [r3+64*19], m26 + mova [r3+64*20], m25 + mova [r3+64*21], m24 + mova [r3+64*22], m23 + mova [r3+64*23], m22 + mova [r3+64*24], m21 + mova [r3+64*25], m20 + mova [r3+64*26], m19 + mova [r3+64*27], m18 + mova [r3+64*28], m17 + mova [r3+64*29], m16 + mova [r3+64*30], m15 + mova [r3+64*31], m14 + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/itx_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/itx_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6533 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + + +SECTION_RODATA 16 + +deint_shuf: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 + +deint_shuf1: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +deint_shuf2: db 8, 9, 0, 1, 10, 11, 2, 3, 12, 13, 4, 5, 14, 15, 6, 7 + +%macro COEF_PAIR 2-3 0 ; !0 = m%1_m%2, 2 = no %2_%1 +pw_%1_m%2: times 4 dw %1, -%2 +%if %3 != 2 +pw_%2_%1: times 4 dw %2, %1 +%endif +%if %3 +pw_m%1_m%2: times 4 dw -%1, -%2 +%endif +%endmacro + +;adst4 +pw_1321_3803: times 4 dw 1321, 3803 +pw_2482_m1321: times 4 dw 2482, -1321 +pw_3344_2482: times 4 dw 3344, 2482 +pw_3344_m3803: times 4 dw 3344, -3803 +pw_3344_m3344: times 4 dw 3344, -3344 +pw_0_3344 times 4 dw 0, 3344 +pw_m6688_m3803: times 4 dw -6688, -3803 + +COEF_PAIR 2896, 2896 +COEF_PAIR 1567, 3784 +COEF_PAIR 799, 4017 +COEF_PAIR 3406, 2276 +COEF_PAIR 401, 4076 +COEF_PAIR 1931, 3612 +COEF_PAIR 3166, 2598 +COEF_PAIR 3920, 1189 +COEF_PAIR 3784, 1567, 1 +COEF_PAIR 995, 3973 +COEF_PAIR 1751, 3703 +COEF_PAIR 3513, 2106 +COEF_PAIR 3857, 1380 +COEF_PAIR 4017, 799, 1 +COEF_PAIR 201, 4091 +COEF_PAIR 2440, 3290 +COEF_PAIR 3035, 2751 +COEF_PAIR 4052, 601 +COEF_PAIR 2276, 3406, 1 +COEF_PAIR 4076, 401, 2 +COEF_PAIR 2598, 3166, 2 +COEF_PAIR 3612, 1931, 2 +COEF_PAIR 1189, 3920, 2 + +pd_2048: times 4 dd 2048 +pw_2048: times 8 dw 2048 +pw_m2048: times 8 dw -2048 +pw_4096: times 8 dw 4096 +pw_16384: times 8 dw 16384 +pw_m16384: times 8 dw -16384 +pw_1697x16: times 8 dw 1697*16 +pw_1697x8: times 8 dw 1697*8 +pw_2896x8: times 8 dw 2896*8 +pw_3344x8: times 8 dw 3344*8 +pw_8192: times 8 dw 8192 +pw_m8192: times 8 dw -8192 +pw_5: times 8 dw 5 +pw_201x8: times 8 dw 201*8 +pw_4091x8: times 8 dw 4091*8 +pw_m2751x8: times 8 dw -2751*8 +pw_3035x8: times 8 dw 3035*8 +pw_1751x8: times 8 dw 1751*8 +pw_3703x8: times 8 dw 3703*8 +pw_m1380x8: times 8 dw -1380*8 +pw_3857x8: times 8 dw 3857*8 +pw_995x8: times 8 dw 995*8 +pw_3973x8: times 8 dw 3973*8 +pw_m2106x8: times 8 dw -2106*8 +pw_3513x8: times 8 dw 3513*8 +pw_2440x8: times 8 dw 2440*8 +pw_3290x8: times 8 dw 3290*8 +pw_m601x8: times 8 dw -601*8 +pw_4052x8: times 8 dw 4052*8 + +pw_4095x8: times 8 dw 4095*8 +pw_101x8: times 8 dw 101*8 +pw_2967x8: times 8 dw 2967*8 +pw_m2824x8: times 8 dw -2824*8 +pw_3745x8: times 8 dw 3745*8 +pw_1660x8: times 8 dw 1660*8 +pw_3822x8: times 8 dw 3822*8 +pw_m1474x8: times 8 dw -1474*8 +pw_3996x8: times 8 dw 3996*8 +pw_897x8: times 8 dw 897*8 +pw_3461x8: times 8 dw 3461*8 +pw_m2191x8: times 8 dw -2191*8 +pw_3349x8: times 8 dw 3349*8 +pw_2359x8: times 8 dw 2359*8 +pw_4036x8: times 8 dw 4036*8 +pw_m700x8: times 8 dw -700*8 +pw_4065x8: times 8 dw 4065*8 +pw_501x8: times 8 dw 501*8 +pw_3229x8: times 8 dw 3229*8 +pw_m2520x8: times 8 dw -2520*8 +pw_3564x8: times 8 dw 3564*8 +pw_2019x8: times 8 dw 2019*8 +pw_3948x8: times 8 dw 3948*8 +pw_m1092x8: times 8 dw -1092*8 +pw_3889x8: times 8 dw 3889*8 +pw_1285x8: times 8 dw 1285*8 +pw_3659x8: times 8 dw 3659*8 +pw_m1842x8: times 8 dw -1842*8 +pw_3102x8: times 8 dw 3102*8 +pw_2675x8: times 8 dw 2675*8 +pw_4085x8: times 8 dw 4085*8 +pw_m301x8: times 8 dw -301*8 + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +%if ARCH_X86_64 +%define o(x) x +%else +%define o(x) r5-$$+x ; PIC +%endif + +%macro WRITE_4X4 9 ;src[1-2], tmp[1-3], row[1-4] + lea r2, [dstq+strideq*2] +%assign %%i 1 +%rotate 5 +%rep 4 + %if %1 & 2 + CAT_XDEFINE %%row_adr, %%i, r2 + strideq*(%1&1) + %else + CAT_XDEFINE %%row_adr, %%i, dstq + strideq*(%1&1) + %endif + %assign %%i %%i + 1 + %rotate 1 +%endrep + + movd m%3, [%%row_adr1] ;dst0 + movd m%5, [%%row_adr2] ;dst1 + punpckldq m%3, m%5 ;high: dst1 :low: dst0 + movd m%4, [%%row_adr3] ;dst2 + movd m%5, [%%row_adr4] ;dst3 + punpckldq m%4, m%5 ;high: dst3 :low: dst2 + + pxor m%5, m%5 + punpcklbw m%3, m%5 ;extend byte to word + punpcklbw m%4, m%5 ;extend byte to word + + paddw m%3, m%1 ;high: dst1 + out1 ;low: dst0 + out0 + paddw m%4, m%2 ;high: dst3 + out3 ;low: dst2 + out2 + + packuswb m%3, m%4 ;high->low: dst3 + out3, dst2 + out2, dst1 + out1, dst0 + out0 + + movd [%%row_adr1], m%3 ;store dst0 + out0 + pshuflw m%4, m%3, q1032 + movd [%%row_adr2], m%4 ;store dst1 + out1 + punpckhqdq m%3, m%3 + movd [%%row_adr3], m%3 ;store dst2 + out2 + psrlq m%3, 32 + movd [%%row_adr4], m%3 ;store dst3 + out3 +%endmacro + +%macro ITX4_END 4-5 2048 ; row[1-4], rnd +%if %5 + mova m2, [o(pw_%5)] + pmulhrsw m0, m2 + pmulhrsw m1, m2 +%endif + + WRITE_4X4 0, 1, 2, 3, 4, %1, %2, %3, %4 + ret +%endmacro + +; flags: 1 = swap, 2: coef_regs, 4: no_pack +%macro ITX_MUL2X_PACK 5-6 0 ; dst/src, tmp[1], rnd, coef[1-2], flags +%if %6 & 2 + pmaddwd m%2, m%4, m%1 + pmaddwd m%1, m%5 +%elif %6 & 1 + pmaddwd m%2, m%1, [o(pw_%5_%4)] + pmaddwd m%1, [o(pw_%4_m%5)] +%else + pmaddwd m%2, m%1, [o(pw_%4_m%5)] + pmaddwd m%1, [o(pw_%5_%4)] +%endif + paddd m%2, m%3 + paddd m%1, m%3 + psrad m%2, 12 + psrad m%1, 12 +%if %6 & 4 == 0 + packssdw m%1, m%2 +%endif +%endmacro + +%macro IDCT4_1D_PACKED 0-1 ;pw_2896x8 + mova m3, [o(pd_2048)] + punpckhwd m2, m0, m1 ;unpacked in1 in3 + punpcklwd m0, m1 ;unpacked in0 in2 + ITX_MUL2X_PACK 2, 1, 3, 1567, 3784 + ITX_MUL2X_PACK 0, 1, 3, 2896, 2896 + psubsw m1, m0, m2 ;high: out2 ;low: out3 + paddsw m0, m2 ;high: out1 ;low: out0 +%endmacro + +%macro INV_TXFM_FN 4+ ; type1, type2, size, xmm/stack +cglobal inv_txfm_add_%1_%2_%3_8bpc, 4, 6, %4, dst, stride, coeff, eob, tx2 + %define %%p1 m(i%1_%3_internal_8bpc) +%if ARCH_X86_32 + LEA r5, $$ +%endif +%if has_epilogue +%ifidn %1_%2, dct_dct + test eobd, eobd + jz %%end +%endif + lea tx2q, [o(m(i%2_%3_internal_8bpc).pass2)] + call %%p1 + RET +%%end: +%else + lea tx2q, [o(m(i%2_%3_internal_8bpc).pass2)] +%ifidn %1_%2, dct_dct + test eobd, eobd + jnz %%p1 +%else + times ((%%end - %%p1) >> 31) & 1 jmp %%p1 +ALIGN function_align +%%end: +%endif +%endif +%endmacro + +%macro INV_TXFM_4X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x4, 6 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklqdq m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mov [coeffq], eobd ;0 + pmulhrsw m0, m1 + mova m1, m0 + TAIL_CALL m(iadst_4x4_internal_8bpc).end2 +%endif +%endmacro + +INIT_XMM ssse3 +; itx16 relies on dct_dct being the first function. If you change the order, adjust `itx8_start` in itx16. + +INV_TXFM_4X4_FN dct, dct +INV_TXFM_4X4_FN dct, adst +INV_TXFM_4X4_FN dct, flipadst +INV_TXFM_4X4_FN dct, identity + +cglobal idct_4x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m0, [coeffq+16*0] ;high: in1 ;low: in0 + mova m1, [coeffq+16*1] ;high: in3 ;low in2 + + IDCT4_1D_PACKED + + mova m2, [o(deint_shuf)] + shufps m3, m0, m1, q1331 + shufps m0, m1, q0220 + pshufb m0, m2 ;high: in1 ;low: in0 + pshufb m1, m3, m2 ;high: in3 ;low :in2 + jmp tx2q + +.pass2: + IDCT4_1D_PACKED + + pxor m2, m2 + mova [coeffq+16*0], m2 + mova [coeffq+16*1], m2 ;memset(coeff, 0, sizeof(*coeff) * sh * sw); + + ITX4_END 0, 1, 3, 2 + +INV_TXFM_4X4_FN adst, dct +INV_TXFM_4X4_FN adst, adst +INV_TXFM_4X4_FN adst, flipadst +INV_TXFM_4X4_FN adst, identity + +cglobal iadst_4x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + call .main + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 ;high: in3 ;low :in2 + punpcklwd m0, m2 ;high: in1 ;low: in0 + jmp tx2q + +.pass2: + call .main + +.end: + pxor m2, m2 + mova [coeffq+16*0], m2 + mova [coeffq+16*1], m2 + +.end2: + ITX4_END 0, 1, 2, 3 + +ALIGN function_align +cglobal_label .main + punpcklwd m2, m0, m1 ;unpacked in0 in2 + punpckhwd m0, m1 ;unpacked in1 in3 + mova m3, m0 + pmaddwd m1, m2, [o(pw_3344_m3344)];3344 * in0 - 3344 * in2 + pmaddwd m0, [o(pw_0_3344)] ;3344 * in3 + paddd m1, m0 ;t2 + pmaddwd m0, m2, [o(pw_1321_3803)] ;1321 * in0 + 3803 * in2 + pmaddwd m2, [o(pw_2482_m1321)] ;2482 * in0 - 1321 * in2 + pmaddwd m4, m3, [o(pw_3344_2482)] ;3344 * in1 + 2482 * in3 + pmaddwd m5, m3, [o(pw_3344_m3803)];3344 * in1 - 3803 * in3 + paddd m4, m0 ;t0 + t3 + pmaddwd m3, [o(pw_m6688_m3803)] ;-2 * 3344 * in1 - 3803 * in3 + mova m0, [o(pd_2048)] + paddd m1, m0 ;t2 + 2048 + paddd m2, m0 + paddd m0, m4 ;t0 + t3 + 2048 + paddd m5, m2 ;t1 + t3 + 2048 + paddd m2, m4 + paddd m2, m3 ;t0 + t1 - t3 + 2048 + REPX {psrad x, 12}, m1, m0, m5, m2 + packssdw m0, m5 ;high: out1 ;low: out0 + packssdw m1, m2 ;high: out3 ;low: out3 + ret + +INV_TXFM_4X4_FN flipadst, dct +INV_TXFM_4X4_FN flipadst, adst +INV_TXFM_4X4_FN flipadst, flipadst +INV_TXFM_4X4_FN flipadst, identity + +cglobal iflipadst_4x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + call m(iadst_4x4_internal_8bpc).main + punpcklwd m2, m1, m0 + punpckhwd m1, m0 + punpcklwd m0, m1, m2 ;high: in3 ;low :in2 + punpckhwd m1, m2 ;high: in1 ;low: in0 + jmp tx2q + +.pass2: + call m(iadst_4x4_internal_8bpc).main + +.end: + pxor m2, m2 + mova [coeffq+16*0], m2 + mova [coeffq+16*1], m2 + +.end2: + ITX4_END 3, 2, 1, 0 + +INV_TXFM_4X4_FN identity, dct +INV_TXFM_4X4_FN identity, adst +INV_TXFM_4X4_FN identity, flipadst +INV_TXFM_4X4_FN identity, identity + +cglobal iidentity_4x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + mova m3, [o(pw_1697x8)] + pmulhrsw m2, m0, m3 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + punpckhwd m2, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m0, m2 ;high: in3 ;low :in2 + punpcklwd m0, m2 ;high: in1 ;low: in0 + jmp tx2q + +.pass2: + mova m3, [o(pw_1697x8)] + pmulhrsw m2, m3, m0 + pmulhrsw m3, m1 + paddsw m0, m2 + paddsw m1, m3 + jmp m(iadst_4x4_internal_8bpc).end + +%macro IWHT4_1D_PACKED 0 + punpckhqdq m3, m0, m1 ;low: in1 high: in3 + punpcklqdq m0, m1 ;low: in0 high: in2 + psubw m2, m0, m3 ;low: in0 - in1 high: in2 - in3 + paddw m0, m3 ;low: in0 + in1 high: in2 + in3 + punpckhqdq m2, m2 ;t2 t2 + punpcklqdq m0, m0 ;t0 t0 + psubw m1, m0, m2 + psraw m1, 1 ;t4 t4 + psubw m1, m3 ;low: t1/out2 high: t3/out1 + psubw m0, m1 ;high: out0 + paddw m2, m1 ;low: out3 +%endmacro + +INIT_XMM sse2 +cglobal inv_txfm_add_wht_wht_4x4_8bpc, 3, 3, 4, dst, stride, coeff + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + pxor m2, m2 + mova [coeffq+16*0], m2 + mova [coeffq+16*1], m2 + psraw m0, 2 + psraw m1, 2 + IWHT4_1D_PACKED + punpckhwd m0, m1 + punpcklwd m3, m1, m2 + punpckhdq m1, m0, m3 + punpckldq m0, m3 + IWHT4_1D_PACKED + shufpd m0, m2, 0x01 + ITX4_END 0, 3, 2, 1, 0 + +%macro IDCT8_1D_PACKED 0 + mova m6, [o(pd_2048)] + punpckhwd m4, m0, m3 ;unpacked in1 in7 + punpcklwd m0, m2 ;unpacked in0 in4 + punpckhwd m2, m1 ;unpacked in5 in3 + punpcklwd m1, m3 ;unpacked in2 in6 + ITX_MUL2X_PACK 4, 3, 6, 799, 4017 ;low: t7a high: t4a + ITX_MUL2X_PACK 2, 3, 6, 3406, 2276 ;low: t6a high: t5a + ITX_MUL2X_PACK 1, 3, 6, 1567, 3784 ;low: t3 high: t2 + psubsw m3, m4, m2 ;low: t6a high: t5a + paddsw m4, m2 ;low: t7 high: t4 + pshufb m3, [o(deint_shuf1)] + ITX_MUL2X_PACK 0, 2, 6, 2896, 2896 ;low: t0 high: t1 + ITX_MUL2X_PACK 3, 2, 6, 2896, 2896 ;low: t6 high: t5 + psubsw m2, m0, m1 ;low: tmp3 high: tmp2 + paddsw m0, m1 ;low: tmp0 high: tmp1 + punpcklqdq m1, m4, m3 ;low: t7 high: t6 + punpckhqdq m4, m3 ;low: t4 high: t5 + psubsw m3, m0, m1 ;low: out7 high: out6 + paddsw m0, m1 ;low: out0 high: out1 + paddsw m1, m2, m4 ;low: out3 high: out2 + psubsw m2, m4 ;low: out4 high: out5 +%endmacro + +;dst1 = (src1 * coef1 - src2 * coef2 + rnd) >> 12 +;dst2 = (src1 * coef2 + src2 * coef1 + rnd) >> 12 +%macro ITX_MULSUB_2W 7-8 0 ; dst/src[1-2], tmp[1-2], rnd, coef[1-2], dst2_in_tmp1 + punpckhwd m%4, m%1, m%2 + punpcklwd m%1, m%2 +%if %7 < 8 + pmaddwd m%2, m%7, m%1 + pmaddwd m%3, m%7, m%4 +%else + mova m%2, [o(pw_%7_%6)] +%if %8 + pmaddwd m%3, m%1, m%2 + pmaddwd m%2, m%4 +%else + pmaddwd m%3, m%4, m%2 + pmaddwd m%2, m%1 +%endif +%endif + paddd m%3, m%5 + paddd m%2, m%5 + psrad m%3, 12 + psrad m%2, 12 +%if %8 + packssdw m%3, m%2 +%else + packssdw m%2, m%3 ;dst2 +%endif +%if %7 < 8 + pmaddwd m%4, m%6 + pmaddwd m%1, m%6 +%elif %8 + mova m%2, [o(pw_%6_m%7)] + pmaddwd m%4, m%2 + pmaddwd m%1, m%2 +%else + mova m%3, [o(pw_%6_m%7)] + pmaddwd m%4, m%3 + pmaddwd m%1, m%3 +%endif + paddd m%4, m%5 + paddd m%1, m%5 + psrad m%4, 12 + psrad m%1, 12 + packssdw m%1, m%4 ;dst1 +%endmacro + +%macro IDCT4_1D 7 ; src[1-4], tmp[1-2], pd_2048 + ITX_MULSUB_2W %2, %4, %5, %6, %7, 1567, 3784, 1 ;t2, t3 + ITX_MULSUB_2W %1, %3, %4, %6, %7, 2896, 2896, 1 ;t1, t0 + psubsw m%3, m%1, m%2 ;out2 + paddsw m%2, m%1 ;out1 + paddsw m%1, m%5, m%4 ;out0 + psubsw m%4, m%5 ;out3 +%endmacro + +%macro WRITE_4X8 4 ;row[1-4] + WRITE_4X4 0, 1, 4, 5, 6, %1, %2, %3, %4 + lea dstq, [dstq+strideq*4] + WRITE_4X4 2, 3, 4, 5, 6, %1, %2, %3, %4 +%endmacro + +%macro INV_4X8 0 + punpckhwd m4, m2, m3 + punpcklwd m2, m3 + punpckhwd m3, m0, m1 + punpcklwd m0, m1 + punpckhdq m1, m0, m2 ;low: in2 high: in3 + punpckldq m0, m2 ;low: in0 high: in1 + punpckldq m2, m3, m4 ;low: in4 high: in5 + punpckhdq m3, m4 ;low: in6 high: in7 +%endmacro + +%macro INV_TXFM_4X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x8, 8 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklqdq m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mov [coeffq], eobd + pmulhrsw m0, m1 + pmulhrsw m0, m1 + pmulhrsw m0, [o(pw_2048)] + mova m1, m0 + mova m2, m0 + mova m3, m0 + TAIL_CALL m(iadst_4x8_internal_8bpc).end3 +%endif +%endmacro + +INIT_XMM ssse3 +INV_TXFM_4X8_FN dct, dct +INV_TXFM_4X8_FN dct, adst +INV_TXFM_4X8_FN dct, flipadst +INV_TXFM_4X8_FN dct, identity + +cglobal idct_4x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + +.pass1: + call m(idct_8x4_internal_8bpc).main + jmp m(iadst_4x8_internal_8bpc).pass1_end + +.pass2: + call .main + shufps m1, m1, q1032 + shufps m3, m3, q1032 + mova m4, [o(pw_2048)] + jmp m(iadst_4x8_internal_8bpc).end2 + +ALIGN function_align +cglobal_label .main + IDCT8_1D_PACKED + ret + + +INV_TXFM_4X8_FN adst, dct +INV_TXFM_4X8_FN adst, adst +INV_TXFM_4X8_FN adst, flipadst +INV_TXFM_4X8_FN adst, identity + +cglobal iadst_4x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + +.pass1: + call m(iadst_8x4_internal_8bpc).main + +.pass1_end: + INV_4X8 + jmp tx2q + +.pass2: + shufps m0, m0, q1032 + shufps m1, m1, q1032 + call .main + mova m4, [o(pw_2048)] + pxor m5, m5 + psubw m5, m4 + +.end: + punpcklqdq m4, m5 + +.end2: + pmulhrsw m0, m4 + pmulhrsw m1, m4 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + pxor m5, m5 + mova [coeffq+16*0], m5 + mova [coeffq+16*1], m5 + mova [coeffq+16*2], m5 + mova [coeffq+16*3], m5 + +.end3: + WRITE_4X8 0, 1, 2, 3 + RET + +ALIGN function_align +cglobal_label .main + mova m6, [o(pd_2048)] + punpckhwd m4, m3, m0 ;unpacked in7 in0 + punpckhwd m5, m2, m1 ;unpacked in5 in2 + punpcklwd m1, m2 ;unpacked in3 in4 + punpcklwd m0, m3 ;unpacked in1 in6 + ITX_MUL2X_PACK 4, 2, 6, 401, 4076 ;low: t0a high: t1a + ITX_MUL2X_PACK 5, 2, 6, 1931, 3612 ;low: t2a high: t3a + ITX_MUL2X_PACK 1, 2, 6, 3166, 2598 ;low: t4a high: t5a + ITX_MUL2X_PACK 0, 2, 6, 3920, 1189 ;low: t6a high: t7a + + psubsw m3, m4, m1 ;low: t4 high: t5 + paddsw m4, m1 ;low: t0 high: t1 + psubsw m2, m5, m0 ;low: t6 high: t7 + paddsw m5, m0 ;low: t2 high: t3 + + shufps m1, m3, m2, q1032 + punpckhwd m2, m1 + punpcklwd m3, m1 + ITX_MUL2X_PACK 3, 0, 6, 1567, 3784, 1 ;low: t5a high: t4a + ITX_MUL2X_PACK 2, 0, 6, 3784, 1567 ;low: t7a high: t6a + + psubsw m1, m4, m5 ;low: t2 high: t3 + paddsw m4, m5 ;low: out0 high: -out7 + psubsw m5, m3, m2 ;low: t7 high: t6 + paddsw m3, m2 ;low: out6 high: -out1 + shufps m0, m4, m3, q3210 ;low: out0 high: -out1 + shufps m3, m4, q3210 ;low: out6 high: -out7 + + mova m2, [o(pw_2896_m2896)] + mova m7, [o(pw_2896_2896)] + shufps m4, m1, m5, q1032 ;low: t3 high: t7 + shufps m1, m5, q3210 ;low: t2 high: t6 + punpcklwd m5, m1, m4 + punpckhwd m1, m4 + pmaddwd m4, m2, m1 ;-out5 + pmaddwd m2, m5 ; out4 + pmaddwd m1, m7 ; out2 + pmaddwd m5, m7 ;-out3 + REPX {paddd x, m6}, m4, m2, m1, m5 + REPX {psrad x, 12}, m4, m2, m1, m5 + packssdw m1, m5 ;low: out2 high: -out3 + packssdw m2, m4 ;low: out4 high: -out5 + ret + +INV_TXFM_4X8_FN flipadst, dct +INV_TXFM_4X8_FN flipadst, adst +INV_TXFM_4X8_FN flipadst, flipadst +INV_TXFM_4X8_FN flipadst, identity + +cglobal iflipadst_4x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + +.pass1: + call m(iadst_8x4_internal_8bpc).main + + punpcklwd m4, m3, m2 + punpckhwd m3, m2 + punpcklwd m5, m1, m0 + punpckhwd m1, m0 + punpckldq m2, m3, m1 ;low: in4 high: in5 + punpckhdq m3, m1 ;low: in6 high: in7 + punpckldq m0, m4, m5 ;low: in0 high: in1 + punpckhdq m1, m4, m5 ;low: in2 high: in3 + jmp tx2q + +.pass2: + shufps m0, m0, q1032 + shufps m1, m1, q1032 + call m(iadst_4x8_internal_8bpc).main + + mova m4, m0 + mova m5, m1 + pshufd m0, m3, q1032 + pshufd m1, m2, q1032 + pshufd m2, m5, q1032 + pshufd m3, m4, q1032 + mova m5, [o(pw_2048)] + pxor m4, m4 + psubw m4, m5 + jmp m(iadst_4x8_internal_8bpc).end + +INV_TXFM_4X8_FN identity, dct +INV_TXFM_4X8_FN identity, adst +INV_TXFM_4X8_FN identity, flipadst +INV_TXFM_4X8_FN identity, identity + +cglobal iidentity_4x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + +.pass1: + mova m7, [o(pw_1697x8)] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(iadst_4x8_internal_8bpc).pass1_end + +.pass2: + mova m4, [o(pw_4096)] + jmp m(iadst_4x8_internal_8bpc).end2 + + +%macro WRITE_8X2 5 ;coefs[1-2], tmp[1-3] + movq m%3, [dstq ] + movq m%4, [dstq+strideq] + pxor m%5, m%5 + punpcklbw m%3, m%5 ;extend byte to word + punpcklbw m%4, m%5 ;extend byte to word +%ifnum %1 + paddw m%3, m%1 +%else + paddw m%3, %1 +%endif +%ifnum %2 + paddw m%4, m%2 +%else + paddw m%4, %2 +%endif + packuswb m%3, m%4 + movq [dstq ], m%3 + punpckhqdq m%3, m%3 + movq [dstq+strideq], m%3 +%endmacro + +%macro WRITE_8X4 7 ;coefs[1-4], tmp[1-3] + WRITE_8X2 %1, %2, %5, %6, %7 + lea dstq, [dstq+strideq*2] + WRITE_8X2 %3, %4, %5, %6, %7 +%endmacro + +%macro INV_TXFM_8X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x4, 8 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklqdq m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + pmulhrsw m0, m1 + mova m2, [o(pw_2048)] + pmulhrsw m0, m1 + pmulhrsw m0, m2 + mova m1, m0 + mova m2, m0 + mova m3, m0 + TAIL_CALL m(iadst_8x4_internal_8bpc).end2 +%endif +%endmacro + +INV_TXFM_8X4_FN dct, dct +INV_TXFM_8X4_FN dct, adst +INV_TXFM_8X4_FN dct, flipadst +INV_TXFM_8X4_FN dct, identity + +cglobal idct_8x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + + call m(idct_4x8_internal_8bpc).main + + mova m4, [o(deint_shuf1)] + mova m5, [o(deint_shuf2)] + pshufb m0, m4 + pshufb m1, m5 + pshufb m2, m4 + pshufb m3, m5 + punpckhdq m4, m0, m1 + punpckldq m0, m1 + punpckhdq m5, m2, m3 + punpckldq m2, m3 + punpckhqdq m1, m0, m2 ;in1 + punpcklqdq m0, m2 ;in0 + punpckhqdq m3, m4, m5 ;in3 + punpcklqdq m2 ,m4, m5 ;in2 + jmp tx2q + +.pass2: + call .main + jmp m(iadst_8x4_internal_8bpc).end + +ALIGN function_align +cglobal_label .main + mova m6, [o(pd_2048)] + IDCT4_1D 0, 1, 2, 3, 4, 5, 6 + ret + +INV_TXFM_8X4_FN adst, dct +INV_TXFM_8X4_FN adst, adst +INV_TXFM_8X4_FN adst, flipadst +INV_TXFM_8X4_FN adst, identity + +cglobal iadst_8x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + + shufps m0, m0, q1032 + shufps m1, m1, q1032 + call m(iadst_4x8_internal_8bpc).main + + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + pxor m5, m5 + psubsw m3, m5, m1 + psubsw m5, m4 + punpckhdq m4, m5, m3 + punpckldq m5, m3 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckhwd m1, m0, m5 ;in1 + punpcklwd m0, m5 ;in0 + punpcklwd m2, m3, m4 ;in2 + punpckhwd m3, m4 ;in3 + jmp tx2q + +.pass2: + call .main + +.end: + mova m4, [o(pw_2048)] + pmulhrsw m0, m4 + pmulhrsw m1, m4 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + +.end2: + pxor m6, m6 + mova [coeffq+16*0], m6 + mova [coeffq+16*1], m6 + mova [coeffq+16*2], m6 + mova [coeffq+16*3], m6 +.end3: + WRITE_8X4 0, 1, 2, 3, 4, 5, 6 + RET + +ALIGN function_align +cglobal_label .main + punpckhwd m6, m0, m2 ;unpacked in0 in2 + punpcklwd m0, m2 ;unpacked in0 in2 + punpckhwd m7, m1, m3 ;unpacked in1 in3 + punpcklwd m1, m3 ;unpacked in1 in3 + + mova m2, [o(pw_3344_m3344)] + mova m4, [o(pw_0_3344)] + pmaddwd m3, m2, m6 ;3344 * in0 - 3344 * in2 + pmaddwd m5, m4, m7 ;3344 * in3 + pmaddwd m2, m0 + pmaddwd m4, m1 + paddd m3, m5 + paddd m2, m4 + mova m4, [o(pd_2048)] + paddd m3, m4 ;t2 + 2048 + paddd m2, m4 + psrad m3, 12 + psrad m2, 12 + packssdw m2, m3 ;out2 + + pmaddwd m4, m0, [o(pw_1321_3803)] ;1321 * in0 + 3803 * in2 + pmaddwd m0, [o(pw_2482_m1321)] ;2482 * in0 - 1321 * in2 + pmaddwd m3, m1, [o(pw_3344_2482)] ;3344 * in1 + 2482 * in3 + pmaddwd m5, m1, [o(pw_3344_m3803)] ;3344 * in1 - 3803 * in3 + paddd m3, m4 ;t0 + t3 + + pmaddwd m1, [o(pw_m6688_m3803)] ;-2 * 3344 * in1 - 3803 * in3 + mova m4, [o(pd_2048)] + paddd m0, m4 + paddd m4, m3 ;t0 + t3 + 2048 + paddd m5, m0 ;t1 + t3 + 2048 + paddd m3, m0 + paddd m3, m1 ;t0 + t1 - t3 + 2048 + + psrad m4, 12 ;out0 + psrad m5, 12 ;out1 + psrad m3, 12 ;out3 + packssdw m0, m4, m5 ;low: out0 high: out1 + + pmaddwd m4, m6, [o(pw_1321_3803)] ;1321 * in0 + 3803 * in2 + pmaddwd m6, [o(pw_2482_m1321)] ;2482 * in0 - 1321 * in2 + pmaddwd m1, m7, [o(pw_3344_2482)] ;3344 * in1 + 2482 * in3 + pmaddwd m5, m7, [o(pw_3344_m3803)] ;3344 * in1 - 3803 * in3 + paddd m1, m4 ;t0 + t3 + pmaddwd m7, [o(pw_m6688_m3803)] ;-2 * 3344 * in1 - 3803 * in3 + + mova m4, [o(pd_2048)] + paddd m6, m4 + paddd m4, m1 ;t0 + t3 + 2048 + paddd m5, m6 ;t1 + t3 + 2048 + paddd m1, m6 + paddd m1, m7 ;t0 + t1 - t3 + 2048 + + psrad m4, 12 ;out0 + psrad m5, 12 ;out1 + psrad m1, 12 ;out3 + packssdw m3, m1 ;out3 + packssdw m4, m5 ;low: out0 high: out1 + + punpckhqdq m1, m0, m4 ;out1 + punpcklqdq m0, m4 ;out0 + ret + +INV_TXFM_8X4_FN flipadst, dct +INV_TXFM_8X4_FN flipadst, adst +INV_TXFM_8X4_FN flipadst, flipadst +INV_TXFM_8X4_FN flipadst, identity + +cglobal iflipadst_8x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + + shufps m0, m0, q1032 + shufps m1, m1, q1032 + call m(iadst_4x8_internal_8bpc).main + + punpckhwd m5, m3, m2 + punpcklwd m3, m2 + punpckhwd m2, m1, m0 + punpcklwd m1, m0 + + pxor m0, m0 + psubsw m4, m0, m2 + psubsw m0, m5 + punpckhdq m2, m0, m4 + punpckldq m0, m4 + punpckhdq m4, m3, m1 + punpckldq m3, m1 + punpckhwd m1, m0, m3 ;in1 + punpcklwd m0, m3 ;in0 + punpckhwd m3, m2, m4 ;in3 + punpcklwd m2, m4 ;in2 + jmp tx2q + +.pass2: + call m(iadst_8x4_internal_8bpc).main + mova m4, m0 + mova m5, m1 + mova m0, m3 + mova m1, m2 + mova m2, m5 + mova m3, m4 + jmp m(iadst_8x4_internal_8bpc).end + +INV_TXFM_8X4_FN identity, dct +INV_TXFM_8X4_FN identity, adst +INV_TXFM_8X4_FN identity, flipadst +INV_TXFM_8X4_FN identity, identity + +cglobal iidentity_8x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [coeffq+16*0] + pmulhrsw m1, m3, [coeffq+16*1] + pmulhrsw m2, m3, [coeffq+16*2] + pmulhrsw m3, [coeffq+16*3] + paddsw m0, m0 + paddsw m1, m1 + paddsw m2, m2 + paddsw m3, m3 + + punpckhwd m4, m0, m1 + punpcklwd m0, m1 + punpckhwd m1, m2, m3 + punpcklwd m2, m3 + punpckhdq m5, m4, m1 + punpckldq m4, m1 + punpckhdq m3, m0, m2 + punpckldq m0, m2 + punpckhwd m1, m0, m4 ;in1 + punpcklwd m0, m4 ;in0 + punpcklwd m2, m3, m5 ;in2 + punpckhwd m3, m5 ;in3 + jmp tx2q + +.pass2: + mova m7, [o(pw_1697x8)] + pmulhrsw m4, m7, m0 + pmulhrsw m5, m7, m1 + pmulhrsw m6, m7, m2 + pmulhrsw m7, m3 + paddsw m0, m4 + paddsw m1, m5 + paddsw m2, m6 + paddsw m3, m7 + jmp m(iadst_8x4_internal_8bpc).end + +%macro INV_TXFM_8X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x8, 8, 16*4 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklwd m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mova m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m2 + psrlw m2, 3 + pmulhrsw m0, m1 + pmulhrsw m0, m2 +.end: + mov r3d, 2 + lea tx2q, [o(m(inv_txfm_add_dct_dct_8x8_8bpc).end3)] +.loop: + WRITE_8X4 0, 0, 0, 0, 1, 2, 3 + lea dstq, [dstq+strideq*2] + dec r3d + jg .loop + jmp tx2q +.end3: + RET +%endif +%endmacro + +%macro LOAD_8ROWS 2-3 0 ; src, stride, is_rect2 +%if %3 + mova m7, [o(pw_2896x8)] + pmulhrsw m0, m7, [%1+%2*0] + pmulhrsw m1, m7, [%1+%2*1] + pmulhrsw m2, m7, [%1+%2*2] + pmulhrsw m3, m7, [%1+%2*3] + pmulhrsw m4, m7, [%1+%2*4] + pmulhrsw m5, m7, [%1+%2*5] + pmulhrsw m6, m7, [%1+%2*6] + pmulhrsw m7, [%1+%2*7] +%else + mova m0, [%1+%2*0] + mova m1, [%1+%2*1] + mova m2, [%1+%2*2] + mova m3, [%1+%2*3] + mova m4, [%1+%2*4] + mova m5, [%1+%2*5] + mova m6, [%1+%2*6] + mova m7, [%1+%2*7] +%endif +%endmacro + +%macro IDCT8_1D_ODDHALF 7 ; src[1-4], tmp[1-2], pd_2048 + ITX_MULSUB_2W %1, %4, %5, %6, %7, 799, 4017 ;t4a, t7a + ITX_MULSUB_2W %3, %2, %5, %6, %7, 3406, 2276, 1 ;t5a, t6a + psubsw m%2, m%4, m%5 ;t6a + paddsw m%4, m%5 ;t7 + psubsw m%5, m%1, m%3 ;t5a + paddsw m%1, m%3 ;t4 + ITX_MULSUB_2W %2, %5, %3, %6, %7, 2896, 2896, 1 ;t5, t6 +%endmacro + +INV_TXFM_8X8_FN dct, dct +INV_TXFM_8X8_FN dct, adst +INV_TXFM_8X8_FN dct, flipadst +INV_TXFM_8X8_FN dct, identity + +cglobal idct_8x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq, 16 + +.pass1: + call .main + +.pass1_end: + mova m7, [o(pw_16384)] + +.pass1_end1: + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova [rsp+gprsize+16*1], m6 + +.pass1_end2: + REPX {pmulhrsw x, m7}, m1, m3, m5 + pmulhrsw m7, [rsp+gprsize+16*0] + +cglobal_label .pass1_end3 + punpcklwd m6, m1, m5 ;10 50 11 51 12 52 13 53 + punpckhwd m1, m5 ;14 54 15 55 16 56 17 57 + punpckhwd m5, m0, m4 ;04 44 05 45 06 46 07 47 + punpcklwd m0, m4 ;00 40 01 41 02 42 03 43 + punpckhwd m4, m3, m7 ;34 74 35 75 36 76 37 77 + punpcklwd m3, m7 ;30 70 31 71 32 72 33 73 + punpckhwd m7, m1, m4 ;16 36 56 76 17 37 57 77 + punpcklwd m1, m4 ;14 34 54 74 15 35 55 75 + punpckhwd m4, m6, m3 ;12 32 52 72 13 33 53 73 + punpcklwd m6, m3 ;10 30 50 70 11 31 51 71 + mova [rsp+gprsize+16*2], m6 + mova m6, [rsp+gprsize+16*1] + punpckhwd m3, m2, m6 ;24 64 25 65 26 66 27 67 + punpcklwd m2, m6 ;20 60 21 61 22 62 23 63 + punpckhwd m6, m5, m3 ;06 26 46 66 07 27 47 67 + punpcklwd m5, m3 ;04 24 44 64 05 25 45 65 + punpckhwd m3, m0, m2 ;02 22 42 62 03 23 43 63 + punpcklwd m0, m2 ;00 20 40 60 01 21 41 61 + + punpckhwd m2, m6, m7 ;07 17 27 37 47 57 67 77 + punpcklwd m6, m7 ;06 16 26 36 46 56 66 76 + mova [rsp+gprsize+16*0], m2 + punpcklwd m2, m3, m4 ;02 12 22 32 42 52 62 72 + punpckhwd m3, m4 ;03 13 23 33 43 53 63 73 + punpcklwd m4, m5, m1 ;04 14 24 34 44 54 64 74 + punpckhwd m5, m1 ;05 15 25 35 45 55 65 75 + mova m7, [rsp+gprsize+16*2] + punpckhwd m1, m0, m7 ;01 11 21 31 41 51 61 71 + punpcklwd m0, m7 ;00 10 20 30 40 50 60 70 + mova m7, [rsp+gprsize+16*0] + jmp tx2q + +.pass2: + lea tx2q, [o(m(idct_8x8_internal_8bpc).end4)] + +.pass2_main: + call .main + +.end: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova [rsp+gprsize+16*1], m6 + +.end2: + REPX {pmulhrsw x, m7}, m1, m3, m5 + pmulhrsw m7, [rsp+gprsize+16*0] + mova [rsp+gprsize+16*2], m5 + mova [rsp+gprsize+16*0], m7 + +.end3: + WRITE_8X4 0, 1, 2, 3, 5, 6, 7 + lea dstq, [dstq+strideq*2] + WRITE_8X4 4, [rsp+gprsize+16*2], [rsp+gprsize+16*1], [rsp+gprsize+16*0], 5, 6, 7 + jmp tx2q + +.end4: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + ret + +ALIGN function_align +cglobal_label .main + mova [rsp+gprsize*2+16*0], m7 + mova [rsp+gprsize*2+16*1], m3 + mova [rsp+gprsize*2+16*2], m1 + mova m7, [o(pd_2048)] + IDCT4_1D 0, 2, 4, 6, 1, 3, 7 + mova m3, [rsp+gprsize*2+16*2] + mova [rsp+gprsize*2+16*2], m2 + mova m2, [rsp+gprsize*2+16*1] + mova [rsp+gprsize*2+16*1], m4 + mova m4, [rsp+gprsize*2+16*0] + mova [rsp+gprsize*2+16*0], m6 + IDCT8_1D_ODDHALF 3, 2, 5, 4, 1, 6, 7 + mova m6, [rsp+gprsize*2+16*0] + psubsw m7, m0, m4 ;out7 + paddsw m0, m4 ;out0 + mova [rsp+gprsize*2+16*0], m7 + mova m1, [rsp+gprsize*2+16*2] + psubsw m4, m6, m3 ;out4 + paddsw m3, m6 ;out3 + mova m7, [rsp+gprsize*2+16*1] + psubsw m6, m1, m5 ;out6 + paddsw m1, m5 ;out1 + psubsw m5, m7, m2 ;out5 + paddsw m2, m7 ;out2 + ret + + +INV_TXFM_8X8_FN adst, dct +INV_TXFM_8X8_FN adst, adst +INV_TXFM_8X8_FN adst, flipadst +INV_TXFM_8X8_FN adst, identity + +cglobal iadst_8x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq, 16 + +.pass1: + call .main + call .main_pass1_end + +.pass1_end: + mova m7, [o(pw_16384)] + +.pass1_end1: + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova [rsp+gprsize+16*1], m6 + pxor m6, m6 + psubw m6, m7 + mova m7, m6 + jmp m(idct_8x8_internal_8bpc).pass1_end2 + +ALIGN function_align +.pass2: + lea tx2q, [o(m(idct_8x8_internal_8bpc).end4)] + +.pass2_main: + call .main + call .main_pass2_end + +.end: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova [rsp+gprsize+16*1], m6 + pxor m6, m6 + psubw m6, m7 + mova m7, m6 + jmp m(idct_8x8_internal_8bpc).end2 + +ALIGN function_align +cglobal_label .main + mova [rsp+gprsize*2+16*0], m7 + mova [rsp+gprsize*2+16*1], m3 + mova [rsp+gprsize*2+16*2], m4 + mova m7, [o(pd_2048)] + ITX_MULSUB_2W 5, 2, 3, 4, 7, 1931, 3612 ;t3a, t2a + ITX_MULSUB_2W 1, 6, 3, 4, 7, 3920, 1189 ;t7a, t6a + paddsw m3, m2, m6 ;t2 + psubsw m2, m6 ;t6 + paddsw m4, m5, m1 ;t3 + psubsw m5, m1 ;t7 + ITX_MULSUB_2W 5, 2, 1, 6, 7, 3784, 1567 ;t6a, t7a + + mova m6, [rsp+gprsize*2+16*2] + mova [rsp+gprsize*2+16*2], m5 + mova m1, [rsp+gprsize*2+16*1] + mova [rsp+gprsize*2+16*1], m2 + mova m5, [rsp+gprsize*2+16*0] + mova [rsp+gprsize*2+16*0], m3 + ITX_MULSUB_2W 5, 0, 2, 3, 7, 401, 4076 ;t1a, t0a + ITX_MULSUB_2W 1, 6, 2, 3, 7, 3166, 2598 ;t5a, t4a + psubsw m2, m0, m6 ;t4 + paddsw m0, m6 ;t0 + paddsw m3, m5, m1 ;t1 + psubsw m5, m1 ;t5 + ITX_MULSUB_2W 2, 5, 1, 6, 7, 1567, 3784 ;t5a, t4a + + mova m7, [rsp+gprsize*2+16*0] + paddsw m1, m3, m4 ;-out7 + psubsw m3, m4 ;t3 + mova [rsp+gprsize*2+16*0], m1 + psubsw m4, m0, m7 ;t2 + paddsw m0, m7 ;out0 + mova m6, [rsp+gprsize*2+16*2] + mova m7, [rsp+gprsize*2+16*1] + paddsw m1, m5, m6 ;-out1 + psubsw m5, m6 ;t6 + paddsw m6, m2, m7 ;out6 + psubsw m2, m7 ;t7 + ret +ALIGN function_align +.main_pass1_end: + mova [rsp+gprsize*2+16*1], m1 + mova [rsp+gprsize*2+16*2], m6 + punpckhwd m1, m4, m3 + punpcklwd m4, m3 + punpckhwd m7, m5, m2 + punpcklwd m5, m2 + mova m2, [o(pw_2896_2896)] + mova m6, [o(pd_2048)] + pmaddwd m3, m2, m7 + pmaddwd m2, m5 + paddd m3, m6 + paddd m2, m6 + psrad m3, 12 + psrad m2, 12 + packssdw m2, m3 ;out2 + mova m3, [o(pw_2896_m2896)] + pmaddwd m7, m3 + pmaddwd m5, m3 + paddd m7, m6 + paddd m5, m6 + psrad m7, 12 + psrad m5, 12 + packssdw m5, m7 ;-out5 + mova m3, [o(pw_2896_2896)] + pmaddwd m7, m3, m1 + pmaddwd m3, m4 + paddd m7, m6 + paddd m3, m6 + psrad m7, 12 + psrad m3, 12 + packssdw m3, m7 ;-out3 + mova m7, [o(pw_2896_m2896)] + pmaddwd m1, m7 + pmaddwd m4, m7 + paddd m1, m6 + paddd m4, m6 + psrad m1, 12 + psrad m4, 12 + packssdw m4, m1 ;-out5 + mova m1, [rsp+gprsize*2+16*1] + mova m6, [rsp+gprsize*2+16*2] + ret +ALIGN function_align +cglobal_label .main_pass2_end + paddsw m7, m4, m3 ;t2 + t3 + psubsw m4, m3 ;t2 - t3 + paddsw m3, m5, m2 ;t6 + t7 + psubsw m5, m2 ;t6 - t7 + mova m2, [o(pw_2896x8)] + pmulhrsw m4, m2 ;out4 + pmulhrsw m5, m2 ;-out5 + pmulhrsw m7, m2 ;-out3 + pmulhrsw m2, m3 ;out2 + mova m3, m7 + ret + +INV_TXFM_8X8_FN flipadst, dct +INV_TXFM_8X8_FN flipadst, adst +INV_TXFM_8X8_FN flipadst, flipadst +INV_TXFM_8X8_FN flipadst, identity + +cglobal iflipadst_8x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq, 16 + +.pass1: + call m(iadst_8x8_internal_8bpc).main + call m(iadst_8x8_internal_8bpc).main_pass1_end + +.pass1_end: + mova m7, [o(pw_m16384)] + +.pass1_end1: + pmulhrsw m1, m7 + mova [rsp+gprsize+16*1], m1 + mova m1, m6 + mova m6, m2 + pmulhrsw m2, m5, m7 + mova m5, m6 + mova m6, m4 + pmulhrsw m4, m3, m7 + mova m3, m6 + mova m6, m0 + mova m0, m7 + pxor m7, m7 + psubw m7, m0 + pmulhrsw m0, [rsp+gprsize+16*0] + REPX {pmulhrsw x, m7}, m1, m3, m5 + pmulhrsw m7, m6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +ALIGN function_align +.pass2: + lea tx2q, [o(m(idct_8x8_internal_8bpc).end4)] + +.pass2_main: + call m(iadst_8x8_internal_8bpc).main + call m(iadst_8x8_internal_8bpc).main_pass2_end + +.end: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m2, m4, m6 + mova [rsp+gprsize+16*2], m2 + mova m2, m0 + pxor m0, m0 + psubw m0, m7 + mova m7, m2 + pmulhrsw m1, m0 + pmulhrsw m2, m5, m0 + mova [rsp+gprsize+16*1], m1 + mova m5, m4 + mova m1, m6 + pmulhrsw m4, m3, m0 + pmulhrsw m0, [rsp+gprsize+16*0] + mova m3, m5 + mova [rsp+gprsize+16*0], m7 + jmp m(idct_8x8_internal_8bpc).end3 + +INV_TXFM_8X8_FN identity, dct +INV_TXFM_8X8_FN identity, adst +INV_TXFM_8X8_FN identity, flipadst +INV_TXFM_8X8_FN identity, identity + +cglobal iidentity_8x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq, 16 + mova [rsp+gprsize+16*1], m6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +ALIGN function_align +.pass2: + lea tx2q, [o(m(idct_8x8_internal_8bpc).end4)] + +.end: + pmulhrsw m7, [o(pw_4096)] + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_4096)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + mova [rsp+gprsize+16*2], m5 + mova [rsp+gprsize+16*1], m6 + jmp m(idct_8x8_internal_8bpc).end3 + + +%macro INV_TXFM_4X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 4x16, 8 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklwd m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mov [coeffq], eobd + pmulhrsw m0, [o(pw_16384)] + pmulhrsw m0, m1 + pmulhrsw m0, [o(pw_2048)] +.end: + WRITE_4X4 0, 0, 1, 2, 3, 0, 1, 2, 3 + lea dstq, [dstq+strideq*4] + WRITE_4X4 0, 0, 1, 2, 3, 0, 1, 2, 3 + lea dstq, [dstq+strideq*4] + WRITE_4X4 0, 0, 1, 2, 3, 0, 1, 2, 3 + lea dstq, [dstq+strideq*4] + WRITE_4X4 0, 0, 1, 2, 3, 0, 1, 2, 3 + RET +%endif +%endmacro + +INV_TXFM_4X16_FN dct, dct +INV_TXFM_4X16_FN dct, adst +INV_TXFM_4X16_FN dct, flipadst +INV_TXFM_4X16_FN dct, identity + +cglobal idct_4x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(idct_4x8_internal_8bpc).pass1)] + +.pass1: + mova m0, [coeffq+16*1] + mova m1, [coeffq+16*3] + mova m2, [coeffq+16*5] + mova m3, [coeffq+16*7] + push tx2q + lea tx2q, [o(m(idct_4x16_internal_8bpc).pass1_2)] + jmp r3 + +.pass1_2: + mova [coeffq+16*1], m0 + mova [coeffq+16*3], m1 + mova [coeffq+16*5], m2 + mova [coeffq+16*7], m3 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*2] + mova m2, [coeffq+16*4] + mova m3, [coeffq+16*6] + lea tx2q, [o(m(idct_4x16_internal_8bpc).pass1_end)] + jmp r3 + +.pass1_end: + pop tx2q + + mova m4, [coeffq+16*1] + mova m5, [coeffq+16*3] + mova m6, [coeffq+16*5] + mova m7, [o(pw_16384)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + + pmulhrsw m7, [coeffq+16*7] + mova [coeffq+16*7], m7 + jmp tx2q + +.pass2: + call m(idct_16x4_internal_8bpc).main + +.end: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [coeffq+16*7] + mova [coeffq+16*4], m4 + +.end1: + mova [coeffq+16*5], m5 + mova [coeffq+16*6], m6 + mov r3, coeffq + WRITE_4X8 0, 1, 3, 2 + + mova m0, [r3+16*4] + mova m1, [r3+16*5] + mova m2, [r3+16*6] + mova m3, m7 + lea dstq, [dstq+strideq*4] + WRITE_4X8 0, 1, 3, 2 + +.end2: + pxor m7, m7 + REPX {mova [r3+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + ret + +INV_TXFM_4X16_FN adst, dct +INV_TXFM_4X16_FN adst, adst +INV_TXFM_4X16_FN adst, flipadst +INV_TXFM_4X16_FN adst, identity + +cglobal iadst_4x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(iadst_4x8_internal_8bpc).pass1)] + jmp m(idct_4x16_internal_8bpc).pass1 + +.pass2: + call m(iadst_16x4_internal_8bpc).main + call m(iadst_16x4_internal_8bpc).main_pass2_end + + punpcklqdq m6, m5, m4 ;low: -out5 high: -out7 + punpckhqdq m4, m5 ;low: out8 high: out10 + punpcklqdq m5, m7, m2 ;low: out4 high: out6 + punpckhqdq m2, m7 ;low: -out9 high: -out11 + mova [coeffq+16*4], m2 + mova [coeffq+16*5], m6 + mova m2, [coeffq+16*6] + mova m6, [coeffq+16*7] + punpckhqdq m1, m6, m0 ;low: -out13 high: -out15 + punpcklqdq m0, m6 ;low: out0 high: out2 + punpckhqdq m6, m3, m2 ;low: out12 high: out14 + punpcklqdq m2, m3 ;low: -out1 high: -out3 + + mova m7, [o(pw_2048)] + +.end1: + REPX {pmulhrsw x, m7}, m0, m5, m4, m6 + pxor m3, m3 + psubw m3, m7 + mova m7, [coeffq+16*4] + REPX {pmulhrsw x, m3}, m2, m7, m1 + pmulhrsw m3, [coeffq+16*5] + mova [coeffq+16*7], m5 + + punpckhqdq m5, m4, m7 ;low: out10 high: out11 + punpcklqdq m4, m7 ;low: out8 high: out9 + punpckhqdq m7, m6, m1 ;low: out14 high: out15 + punpcklqdq m6, m1 ;low: out12 high: out13 + punpckhqdq m1, m0, m2 ;low: out2 high: out3 + punpcklqdq m0, m2 ;low: out0 high: out1 + mova [coeffq+16*4], m4 + mova m4, [coeffq+16*7] + punpcklqdq m2, m4, m3 ;low: out4 high: out5 + punpckhqdq m4, m3 ;low: out6 high: out7 + mova m3, m4 + +.end2: + mova [coeffq+16*5], m5 + mova [coeffq+16*6], m6 + mov r3, coeffq + WRITE_4X8 0, 1, 2, 3 + + mova m0, [r3+16*4] + mova m1, [r3+16*5] + mova m2, [r3+16*6] + mova m3, m7 + lea dstq, [dstq+strideq*4] + WRITE_4X8 0, 1, 2, 3 + +.end3: + pxor m7, m7 + REPX {mova [r3+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + ret + + +INV_TXFM_4X16_FN flipadst, dct +INV_TXFM_4X16_FN flipadst, adst +INV_TXFM_4X16_FN flipadst, flipadst +INV_TXFM_4X16_FN flipadst, identity + +cglobal iflipadst_4x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(iflipadst_4x8_internal_8bpc).pass1)] + jmp m(idct_4x16_internal_8bpc).pass1 + +.pass2: + call m(iadst_16x4_internal_8bpc).main + call m(iadst_16x4_internal_8bpc).main_pass2_end + + punpckhqdq m6, m5, m4 ;low: out5 high: out7 + punpcklqdq m4, m5 ;low: -out8 high: -out10 + punpckhqdq m5, m7, m2 ;low: -out4 high: -out6 + punpcklqdq m2, m7 ;low: out9 high: out11 + mova [coeffq+16*4], m2 + mova [coeffq+16*5], m6 + mova m2, [coeffq+16*6] + mova m6, [coeffq+16*7] + punpcklqdq m1, m6, m0 ;low: out13 high: out15 + punpckhqdq m0, m6 ;low: -out0 high: -out2 + punpcklqdq m6, m3, m2 ;low: -out12 high: -out14 + punpckhqdq m2, m3 ;low: out1 high: out3 + + mova m7, [o(pw_m2048)] + jmp m(iadst_4x16_internal_8bpc).end1 + + +INV_TXFM_4X16_FN identity, dct +INV_TXFM_4X16_FN identity, adst +INV_TXFM_4X16_FN identity, flipadst +INV_TXFM_4X16_FN identity, identity + +%macro IDTX16 3-4 ; src/dst, tmp, pw_1697x16, [pw_16394] + pmulhrsw m%2, m%3, m%1 +%if %0 == 4 ; if downshifting by 1 + pmulhrsw m%2, m%4 +%else + paddsw m%1, m%1 +%endif + paddsw m%1, m%2 +%endmacro + +cglobal iidentity_4x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m0, [coeffq+16*1] + mova m6, [o(pw_1697x8)] + mova m1, [coeffq+16*3] + mova m2, [coeffq+16*5] + mova m3, [coeffq+16*7] + pcmpeqw m7, m7 + mov r3, tx2q + lea tx2q, [o(.pass1_2)] +.pass1: + pmulhrsw m4, m6, m0 + pmulhrsw m5, m6, m1 + pavgw m4, m0 + pcmpeqw m0, m7 + pavgw m5, m1 + pcmpeqw m1, m7 + pandn m0, m4 + pmulhrsw m4, m6, m2 + pandn m1, m5 + pmulhrsw m5, m6, m3 + pavgw m4, m2 + pcmpeqw m2, m7 + pavgw m5, m3 + pcmpeqw m3, m7 + pandn m2, m4 + pandn m3, m5 + jmp m(iadst_4x8_internal_8bpc).pass1_end +.pass1_2: + mova [coeffq+16*1], m0 + mova [coeffq+16*3], m1 + mova [coeffq+16*5], m2 + mova [coeffq+16*7], m3 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*2] + mova m2, [coeffq+16*4] + mova m3, [coeffq+16*6] + lea tx2q, [o(.pass1_end)] + jmp .pass1 +.pass1_end: + mova m4, [coeffq+16*1] + mova m5, [coeffq+16*3] + mova m6, [coeffq+16*5] + jmp r3 +.pass2: + mova m7, [o(pw_1697x16)] + mova [coeffq+16*6], m6 + REPX {IDTX16 x, 6, 7}, 0, 1, 2, 3, 4, 5 + mova m6, [coeffq+16*7] + IDTX16 6, 7, 7 + mova [coeffq+16*7], m6 + mova m6, [coeffq+16*6] + pmulhrsw m7, m6, [o(pw_1697x16)] + paddsw m6, m6 + paddsw m6, m7 + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [coeffq+16*7] + mova [coeffq+16*4], m4 + jmp m(iadst_4x16_internal_8bpc).end2 + + +%macro INV_TXFM_16X4_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x4, 8 +%ifidn %1_%2, dct_dct + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + mov [coeffq], eobd + mov r2d, 2 + lea tx2q, [o(m(inv_txfm_add_dct_dct_16x4_8bpc).end)] +.dconly: + pmulhrsw m0, m2 + movd m2, [o(pw_2048)] ;intentionally rip-relative + pmulhrsw m0, m1 + pmulhrsw m0, m2 + pshuflw m0, m0, q0000 + punpcklwd m0, m0 + pxor m5, m5 +.dconly_loop: + mova m1, [dstq] + mova m3, [dstq+strideq] + punpckhbw m2, m1, m5 + punpcklbw m1, m5 + punpckhbw m4, m3, m5 + punpcklbw m3, m5 + paddw m2, m0 + paddw m1, m0 + paddw m4, m0 + paddw m3, m0 + packuswb m1, m2 + packuswb m3, m4 + mova [dstq], m1 + mova [dstq+strideq], m3 + lea dstq, [dstq+strideq*2] + dec r2d + jg .dconly_loop + jmp tx2q +.end: + RET +%endif +%endmacro + +%macro LOAD_7ROWS 2 ;src, stride + mova m0, [%1+%2*0] + mova m1, [%1+%2*1] + mova m2, [%1+%2*2] + mova m3, [%1+%2*3] + mova m4, [%1+%2*4] + mova m5, [%1+%2*5] + mova m6, [%1+%2*6] +%endmacro + +%macro SAVE_7ROWS 2 ;src, stride + mova [%1+%2*0], m0 + mova [%1+%2*1], m1 + mova [%1+%2*2], m2 + mova [%1+%2*3], m3 + mova [%1+%2*4], m4 + mova [%1+%2*5], m5 + mova [%1+%2*6], m6 +%endmacro + +%macro IDCT16_1D_PACKED_ODDHALF 7 ;src[1-4], tmp[1-3] + punpckhwd m%5, m%4, m%1 ;packed in13 in3 + punpcklwd m%1, m%4 ;packed in1 in15 + punpcklwd m%4, m%3, m%2 ;packed in9 in7 + punpckhwd m%2, m%3 ;packed in5 in11 + mova m%7, [o(pd_2048)] + ITX_MUL2X_PACK %1, %6, %7, 401, 4076, 1 ;low: t8a high: t15a + ITX_MUL2X_PACK %4, %6, %7, 3166, 2598, 1 ;low: t9a high: t14a + ITX_MUL2X_PACK %2, %6, %7, 1931, 3612, 1 ;low: t10a high: t13a + ITX_MUL2X_PACK %5, %6, %7, 3920, 1189, 1 ;low: t11a high: t12a + psubsw m%6, m%1, m%4 ;low: t9 high: t14 + paddsw m%1, m%4 ;low: t8 high: t15 + psubsw m%4, m%5, m%2 ;low: t10 high: t13 + paddsw m%5, m%2 ;low: t11 high: t12 + mova m%2, [o(deint_shuf2)] + pshufb m%6, m%2 + pshufb m%4, m%2 + ITX_MUL2X_PACK %6, %3, %7, 1567, 3784, 1 ;low: t9a high: t14a + ITX_MUL2X_PACK %4, %3, %7, m3784, 1567, 1 ;low: t10a high: t13a + psubsw m%3, m%1, m%5 ;low: t11a high: t12a + paddsw m%1, m%5 ;low: t8a high: t15a + psubsw m%5, m%6, m%4 ;low: t10 high: t13 + paddsw m%6, m%4 ;low: t9 high: t14 + pshufb m%3, m%2 + pshufb m%5, m%2 + ITX_MUL2X_PACK %3, %2, %7, 2896, 2896, 4 ;t12, t11 + ITX_MUL2X_PACK %5, %4, %7, 2896, 2896, 4 ;t13a, t10a + packssdw m%2, m%4 ;low: t11 high: t10a + packssdw m%3, m%5 ;low: t12 high: t13a + punpckhqdq m%4, m%1, m%6 ;low: t15a high: t14 + punpcklqdq m%1, m%6 ;low: t8a high: t9 +%endmacro + +INV_TXFM_16X4_FN dct, dct +INV_TXFM_16X4_FN dct, adst +INV_TXFM_16X4_FN dct, flipadst +INV_TXFM_16X4_FN dct, identity + +cglobal idct_16x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_7ROWS coeffq, 16 + call .main + +.pass1_end: + punpckhwd m7, m0, m2 ;packed out1, out5 + punpcklwd m0, m2 ;packed out0, out4 + punpcklwd m2, m1, m3 ;packed out3, out7 + punpckhwd m1, m3 ;packed out2, out6 + mova [coeffq+16*6], m7 + mova m7, [coeffq+16*7] + punpckhwd m3, m4, m6 ;packed out9, out13 + punpcklwd m4, m6 ;packed out8, out12 + punpcklwd m6, m5, m7 ;packed out11, out15 + punpckhwd m5, m7 ;packed out10, out14 + +.pass1_end2: + mova m7, [o(pw_16384)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [coeffq+16*6] + mova [coeffq+16*6], m7 + +.pass1_end3: + punpckhwd m7, m3, m6 ;packed 9, 11, 13, 15 high + punpcklwd m3, m6 ;packed 9, 10, 13, 15 low + punpckhwd m6, m4, m5 ;packed 8, 10, 12, 14 high + punpcklwd m4, m5 ;packed 8, 10, 12, 14 low + punpckhwd m5, m4, m3 ;8, 9, 10, 11, 12, 13, 14, 15(1) + punpcklwd m4, m3 ;8, 9, 10, 11, 12, 13, 14, 15(0) + punpckhwd m3, m6, m7 ;8, 9, 10, 11, 12, 13, 14, 15(3) + punpcklwd m6, m7 ;8, 9, 10, 11, 12, 13, 14, 15(2) + mova [coeffq+16*7], m3 + mova m3, [coeffq+16*6] + punpckhwd m7, m3, m2 ;packed 1, 3, 5, 7 high + punpcklwd m3, m2 ;packed 1, 3, 5, 7 low + punpckhwd m2, m0, m1 ;packed 0, 2, 4, 6 high + punpcklwd m0, m1 ;packed 0, 2, 4, 6 low + punpckhwd m1, m0, m3 ;0, 1, 2, 3, 4, 5, 6, 7(1) + punpcklwd m0, m3 ;0, 1, 2, 3, 4, 5, 6, 7(0) + punpckhwd m3, m2, m7 ;0, 1, 2, 3, 4, 5, 6, 7(3) + punpcklwd m2, m7 ;0, 1, 2, 3, 4, 5, 6, 7(2) + jmp tx2q + +.pass2: + lea tx2q, [o(m(idct_8x4_internal_8bpc).pass2)] + +.pass2_end: + mova [coeffq+16*4], m4 + mova [coeffq+16*5], m5 + mova [coeffq+16*6], m6 + lea r3, [dstq+8] + call tx2q + + add coeffq, 16*4 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + mova m2, [coeffq+16*2] + mova m3, [coeffq+16*3] + mov dstq, r3 + jmp tx2q + +ALIGN function_align +cglobal_label .main + punpckhqdq m7, m0, m1 ;low:in1 high:in3 + punpcklqdq m0, m1 + punpcklqdq m1, m2, m3 + punpckhqdq m3, m2 ;low:in7 high:in5 + mova [coeffq+16*4], m7 + mova [coeffq+16*5], m3 + mova m7, [coeffq+16*7] + punpcklqdq m2, m4, m5 + punpckhqdq m4, m5 ;low:in9 high:in11 + punpcklqdq m3, m6, m7 + punpckhqdq m7, m6 ;low:in15 high:in13 + mova [coeffq+16*6], m4 + IDCT8_1D_PACKED + mova m6, [coeffq+16*4] + mova m4, [coeffq+16*5] + mova m5, [coeffq+16*6] + mova [coeffq+16*4], m1 + mova [coeffq+16*5], m2 + mova [coeffq+16*6], m3 + + IDCT16_1D_PACKED_ODDHALF 6, 4, 5, 7, 1, 2, 3 + + mova m1, [coeffq+16*4] + psubsw m3, m0, m7 ;low:out15 high:out14 + paddsw m0, m7 ;low:out0 high:out1 + psubsw m7, m1, m5 ;low:out12 high:out13 + paddsw m1, m5 ;low:out3 high:out2 + mova [coeffq+16*7], m3 + mova m2, [coeffq+16*5] + mova m3, [coeffq+16*6] + psubsw m5, m2, m4 ;low:out11 high:out10 + paddsw m2, m4 ;low:out4 high:out5 + psubsw m4, m3, m6 ;low:out8 high:out9 + paddsw m3, m6 ;low:out7 high:out6 + mova m6, m7 + ret + +INV_TXFM_16X4_FN adst, dct +INV_TXFM_16X4_FN adst, adst +INV_TXFM_16X4_FN adst, flipadst +INV_TXFM_16X4_FN adst, identity + +cglobal iadst_16x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_7ROWS coeffq, 16 + call .main + call .main_pass1_end + + punpckhwd m6, m7, m0 ;packed -out11, -out15 + punpcklwd m0, m7 ;packed out0, out4 + punpcklwd m7, m3, m4 ;packed -out3, -out7 + punpckhwd m4, m3 ;packed out8, out12 + mova m1, [coeffq+16*6] + punpcklwd m3, m1, m5 ;packed -out1, -out5 + punpckhwd m5, m1 ;packed out10, out14 + mova m1, [coeffq+16*7] + mova [coeffq+16*6], m3 + mova [coeffq+16*7], m7 + punpckhwd m3, m2, m1 ;packed -out9, -out13 + punpcklwd m1, m2 ;packed out2, out6 + + mova m7, [o(pw_16384)] + +.pass1_end: + REPX {pmulhrsw x, m7}, m0, m1, m4, m5 + pxor m2, m2 + psubw m2, m7 + mova m7, [coeffq+16*6] + REPX {pmulhrsw x, m2}, m7, m3, m6 + pmulhrsw m2, [coeffq+16*7] + mova [coeffq+16*6], m7 + jmp m(idct_16x4_internal_8bpc).pass1_end3 + +.pass2: + lea tx2q, [o(m(iadst_8x4_internal_8bpc).pass2)] + jmp m(idct_16x4_internal_8bpc).pass2_end + +ALIGN function_align +cglobal_label .main + mova [coeffq+16*6], m0 + pshufd m0, m1, q1032 + pshufd m2, m2, q1032 + punpckhwd m1, m6, m0 ;packed in13, in2 + punpcklwd m0, m6 ;packed in3, in12 + punpckhwd m7, m5, m2 ;packed in11, in4 + punpcklwd m2, m5 ;packed in5, in10 + mova m6, [o(pd_2048)] + ITX_MUL2X_PACK 1, 5, 6, 995, 3973 ;low:t2 high:t3 + ITX_MUL2X_PACK 7, 5, 6, 1751, 3703 ;low:t4 high:t5 + ITX_MUL2X_PACK 2, 5, 6, 3513, 2106 ;low:t10 high:t11 + ITX_MUL2X_PACK 0, 5, 6, 3857, 1380 ;low:t12 high:t13 + psubsw m5, m1, m2 ;low:t10a high:t11a + paddsw m1, m2 ;low:t2a high:t3a + psubsw m2, m7, m0 ;low:t12a high:t13a + paddsw m7, m0 ;low:t4a high:t5a + punpcklqdq m0, m5 + punpckhwd m0, m5 ;packed t10a, t11a + punpcklqdq m5, m2 + punpckhwd m2, m5 ;packed t13a, t12a + ITX_MUL2X_PACK 0, 5, 6, 3406, 2276 ;low:t10 high:t11 + ITX_MUL2X_PACK 2, 5, 6, 4017, 799, 1 ;low:t12 high:t13 + mova [coeffq+16*4], m1 + mova [coeffq+16*5], m7 + mova m1, [coeffq+16*6] + mova m7, [coeffq+16*7] + pshufd m1, m1, q1032 + pshufd m3, m3, q1032 + punpckhwd m5, m7, m1 ;packed in15, in0 + punpcklwd m1, m7 ;packed in1, in14 + punpckhwd m7, m4, m3 ;packed in9, in6 + punpcklwd m3, m4 ;packed in7, in8 + ITX_MUL2X_PACK 5, 4, 6, 201, 4091 ;low:t0 high:t1 + ITX_MUL2X_PACK 7, 4, 6, 2440, 3290 ;low:t6 high:t7 + ITX_MUL2X_PACK 3, 4, 6, 3035, 2751 ;low:t8 high:t9 + ITX_MUL2X_PACK 1, 4, 6, 4052, 601 ;low:t14 high:t15 + psubsw m4, m5, m3 ;low:t8a high:t9a + paddsw m5, m3 ;low:t0a high:t1a + psubsw m3, m7, m1 ;low:t14a high:t15a + paddsw m7, m1 ;low:t6a high:t7a + punpcklqdq m1, m4 + punpckhwd m1, m4 ;packed t8a, t9a + punpcklqdq m4, m3 + punpckhwd m3, m4 ;packed t15a, t14a + ITX_MUL2X_PACK 1, 4, 6, 799, 4017 ;low:t8 high:t9 + ITX_MUL2X_PACK 3, 4, 6, 2276, 3406, 1 ;low:t14 high:t15 + paddsw m4, m1, m2 ;low:t12a high:t13a + psubsw m1, m2 ;low:t8a high:t9a + psubsw m2, m0, m3 ;low:t14a high:t15a + paddsw m0, m3 ;low:t10a high:t11a + punpcklqdq m3, m1 + punpckhwd m3, m1 ;packed t12a, t13a + punpcklqdq m1, m2 + punpckhwd m2, m1 ;packed t15a, t14a + ITX_MUL2X_PACK 3, 1, 6, 1567, 3784 ;low:t12 high:t13 + ITX_MUL2X_PACK 2, 1, 6, 3784, 1567, 1 ;low:t14 high:t15 + psubsw m1, m3, m2 ;low:t14a high:t15a + paddsw m3, m2 ;low:out2 high:-out13 + psubsw m2, m4, m0 ;low:t10 high:t11 + paddsw m0, m4 ;low:-out1 high:out14 + mova [coeffq+16*6], m0 + mova [coeffq+16*7], m3 + mova m0, [coeffq+16*4] + mova m3, [coeffq+16*5] + psubsw m4, m5, m3 ;low:t4 high:t5 + paddsw m5, m3 ;low:t0 high:t1 + psubsw m3, m0, m7 ;low:t6 high:t7 + paddsw m0, m7 ;low:t2 high:t3 + punpcklqdq m7, m4 + punpckhwd m7, m4 ;packed t4, t5 + punpcklqdq m4, m3 + punpckhwd m3, m4 ;packed t7, t6 + ITX_MUL2X_PACK 7, 4, 6, 1567, 3784 ;low:t4a high:t5a + ITX_MUL2X_PACK 3, 4, 6, 3784, 1567, 1 ;low:t6a high:t7a + psubsw m4, m5, m0 ;low:t2a high:t3a + paddsw m0, m5 ;low:out0 high:-out15 + psubsw m5, m7, m3 ;low:t6 high:t7 + paddsw m3, m7 ;low:-out3 high:out12 + ret +ALIGN function_align +.main_pass1_end: + mova m7, [o(deint_shuf1)] + mova [coeffq+16*4], m0 + mova [coeffq+16*5], m3 + mova m0, [o(pw_2896_m2896)] + mova m3, [o(pw_2896_2896)] + pshufb m1, m7 ;t14a t15a + pshufb m2, m7 ;t10 t11 + pshufb m4, m7 ;t2a t3a + pshufb m5, m7 ;t6 t7 + pmaddwd m7, m0, m2 + pmaddwd m2, m3 + paddd m7, m6 + paddd m2, m6 + psrad m7, 12 + psrad m2, 12 + packssdw m2, m7 ;low:out6 high:-out9 + pmaddwd m7, m0, m4 + pmaddwd m4, m3 + paddd m7, m6 + paddd m4, m6 + psrad m7, 12 + psrad m4, 12 + packssdw m4, m7 ;low:-out7 high:out8 + pmaddwd m7, m3, m5 + pmaddwd m5, m0 + paddd m7, m6 + paddd m5, m6 + psrad m7, 12 + psrad m5, 12 + packssdw m7, m5 ;low:out4 high:-out11 + pmaddwd m5, m3, m1 + pmaddwd m1, m0 + paddd m5, m6 + paddd m1, m6 + psrad m5, 12 + psrad m1, 12 + packssdw m5, m1 ;low:-out5 high:out10 + mova m0, [coeffq+16*4] + mova m3, [coeffq+16*5] + ret +ALIGN function_align +cglobal_label .main_pass2_end + mova m7, [o(pw_2896x8)] + punpckhqdq m6, m2, m1 ;low:t11 high:t15a + punpcklqdq m2, m1 ;low:t10 high:t14a + psubsw m1, m2, m6 + paddsw m2, m6 + punpckhqdq m6, m4, m5 ;low:t3a high:t7 + punpcklqdq m4, m5 ;low:t2a high:t6 + psubsw m5, m4, m6 + paddsw m4, m6 + pmulhrsw m1, m7 ;low:-out9 high:out10 + pmulhrsw m2, m7 ;low:out6 high:-out5 + pmulhrsw m5, m7 ;low:out8 high:-out11 + pmulhrsw m4, m7 ;low:-out7 high:out4 + punpckhqdq m7, m4, m5 ;low:out4 high:-out11 + punpcklqdq m4, m5 ;low:-out7 high:out8 + punpckhqdq m5, m2, m1 ;low:-out5 high:out10 + punpcklqdq m2, m1 ;low:out6 high:-out9 + ret + + +INV_TXFM_16X4_FN flipadst, dct +INV_TXFM_16X4_FN flipadst, adst +INV_TXFM_16X4_FN flipadst, flipadst +INV_TXFM_16X4_FN flipadst, identity + +cglobal iflipadst_16x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_7ROWS coeffq, 16 + call m(iadst_16x4_internal_8bpc).main + call m(iadst_16x4_internal_8bpc).main_pass1_end + + punpcklwd m6, m7, m0 ;packed out11, out15 + punpckhwd m0, m7 ;packed -out0, -out4 + punpckhwd m7, m3, m4 ;packed out3, out7 + punpcklwd m4, m3 ;packed -out8, -out12 + mova m1, [coeffq+16*6] + punpckhwd m3, m1, m5 ;packed out1, out5 + punpcklwd m5, m1 ;packed -out10, -out14 + mova m1, [coeffq+16*7] + mova [coeffq+16*6], m3 + mova [coeffq+16*7], m7 + punpcklwd m3, m2, m1 ;packed out9, out13 + punpckhwd m1, m2 ;packed -out2, -out6 + + mova m7, [o(pw_m16384)] + jmp m(iadst_16x4_internal_8bpc).pass1_end + +.pass2: + lea tx2q, [o(m(iflipadst_8x4_internal_8bpc).pass2)] + jmp m(idct_16x4_internal_8bpc).pass2_end + + +INV_TXFM_16X4_FN identity, dct +INV_TXFM_16X4_FN identity, adst +INV_TXFM_16X4_FN identity, flipadst +INV_TXFM_16X4_FN identity, identity + +cglobal iidentity_16x4_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m1, [coeffq+16*6] + mova m0, [coeffq+16*5] + mova m2, [coeffq+16*7] + mova m6, [o(pw_1697x16)] + mova m7, [o(pw_16384)] + pmulhrsw m4, m6, m1 + pmulhrsw m3, m6, m0 + pmulhrsw m5, m6, m2 + pmulhrsw m4, m7 + pmulhrsw m3, m7 + pmulhrsw m5, m7 + paddsw m1, m4 + paddsw m0, m3 + paddsw m5, m2 + mova m2, [coeffq+16*2] + mova m3, [coeffq+16*3] + mova m4, [coeffq+16*4] + mova [coeffq+16*6], m1 + mova [coeffq+16*5], m0 + mova [coeffq+16*7], m5 + pmulhrsw m0, m6, m2 + pmulhrsw m1, m6, m3 + pmulhrsw m5, m6, m4 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + pmulhrsw m5, m7 + paddsw m2, m0 + paddsw m3, m1 + paddsw m4, m5 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + pmulhrsw m5, m6, m0 + pmulhrsw m6, m1 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + paddsw m0, m5 + paddsw m1, m6 + mova m6, [coeffq+16*6] + mova m5, [coeffq+16*5] + punpckhwd m7, m0, m2 ;packed out1, out5 + punpcklwd m0, m2 ;packed out0, out4 + punpckhwd m2, m1, m3 ;packed out3, out7 + punpcklwd m1, m3 ;packed out2, out6 + mova [coeffq+16*6], m7 + mova m7, [coeffq+16*7] + punpckhwd m3, m4, m6 ;packed out9, out13 + punpcklwd m4, m6 ;packed out8, out12 + punpckhwd m6, m5, m7 ;packed out11, out15 + punpcklwd m5, m7 ;packed out10, out14 + jmp m(idct_16x4_internal_8bpc).pass1_end3 + +.pass2: + lea tx2q, [o(m(iidentity_8x4_internal_8bpc).pass2)] + jmp m(idct_16x4_internal_8bpc).pass2_end + + +%macro SAVE_8ROWS 2 ;src, stride + mova [%1+%2*0], m0 + mova [%1+%2*1], m1 + mova [%1+%2*2], m2 + mova [%1+%2*3], m3 + mova [%1+%2*4], m4 + mova [%1+%2*5], m5 + mova [%1+%2*6], m6 + mova [%1+%2*7], m7 +%endmacro + +%macro INV_TXFM_8X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 8x16, 8, 16*16 +%ifidn %1_%2, dct_dct + pshuflw m0, [coeffq], q0000 + punpcklwd m0, m0 + mova m1, [o(pw_2896x8)] + pmulhrsw m0, m1 + mova m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m1 + pmulhrsw m0, m2 + psrlw m2, 3 ; pw_2048 + pmulhrsw m0, m1 + pmulhrsw m0, m2 + mov r3d, 4 + lea tx2q, [o(m(inv_txfm_add_dct_dct_8x16_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).loop +.end: + RET +%endif +%endmacro + +INV_TXFM_8X16_FN dct, dct +INV_TXFM_8X16_FN dct, adst +INV_TXFM_8X16_FN dct, flipadst +INV_TXFM_8X16_FN dct, identity + +cglobal idct_8x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(idct_8x8_internal_8bpc).pass1)] + +.pass1: + LOAD_8ROWS coeffq+16*1, 32, 1 + mov [rsp+gprsize+16*11], tx2q + lea tx2q, [o(m(idct_8x16_internal_8bpc).pass1_end)] + jmp r3 + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS coeffq+16*0, 32, 1 + mov tx2q, [rsp+gprsize+16*11] + jmp r3 + +.pass2: + lea tx2q, [o(m(idct_8x16_internal_8bpc).end)] + +.pass2_pre: + mova [coeffq+16*2 ], m1 + mova [coeffq+16*6 ], m3 + mova [coeffq+16*10], m5 + mova [coeffq+16*14], m7 + mova m1, m2 + mova m2, m4 + mova m3, m6 + mova m4, [coeffq+16*1 ] + mova m5, [coeffq+16*5 ] + mova m6, [coeffq+16*9 ] + mova m7, [coeffq+16*13] + +.pass2_main: + call m(idct_8x8_internal_8bpc).main + + SAVE_7ROWS rsp+gprsize+16*3, 16 + mova m0, [coeffq+16*2 ] + mova m1, [coeffq+16*6 ] + mova m2, [coeffq+16*10] + mova m3, [coeffq+16*14] + mova m4, [coeffq+16*3 ] + mova m5, [coeffq+16*7 ] + mova m6, [coeffq+16*11] + mova m7, [coeffq+16*15] + call m(idct_16x8_internal_8bpc).main + + mov r3, dstq + lea dstq, [dstq+strideq*8] + jmp m(idct_8x8_internal_8bpc).end + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(idct_8x8_internal_8bpc).end + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ret + +INV_TXFM_8X16_FN adst, dct +INV_TXFM_8X16_FN adst, adst +INV_TXFM_8X16_FN adst, flipadst +INV_TXFM_8X16_FN adst, identity + +cglobal iadst_8x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(iadst_8x8_internal_8bpc).pass1)] + jmp m(idct_8x16_internal_8bpc).pass1 + +.pass2: + lea tx2q, [o(m(iadst_8x16_internal_8bpc).end)] + +.pass2_pre: + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*5], m6 + mova [rsp+gprsize+16*6], m7 + mova m0, m2 + mova m1, m3 + mova m2, m4 + mova m3, m5 + +.pass2_main: + mova m4, [coeffq+16*1 ] + mova m5, [coeffq+16*3 ] + mova m6, [coeffq+16*13] + mova m7, [coeffq+16*15] + mova [rsp+gprsize+16*3], m4 + mova [rsp+gprsize+16*4], m5 + mova [rsp+gprsize+16*9], m6 + mova [rsp+gprsize+32*5], m7 + mova m4, [coeffq+16*5 ] + mova m5, [coeffq+16*7 ] + mova m6, [coeffq+16*9 ] + mova m7, [coeffq+16*11] + + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass2_end + + mov r3, dstq + lea dstq, [dstq+strideq*8] + jmp m(iadst_8x8_internal_8bpc).end + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(iadst_8x8_internal_8bpc).end + + +INV_TXFM_8X16_FN flipadst, dct +INV_TXFM_8X16_FN flipadst, adst +INV_TXFM_8X16_FN flipadst, flipadst +INV_TXFM_8X16_FN flipadst, identity + +cglobal iflipadst_8x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + lea r3, [o(m(iflipadst_8x8_internal_8bpc).pass1)] + jmp m(idct_8x16_internal_8bpc).pass1 + +.pass2: + lea tx2q, [o(m(iflipadst_8x16_internal_8bpc).end)] + lea r3, [dstq+strideq*8] + +.pass2_pre: + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*5], m6 + mova [rsp+gprsize+16*6], m7 + mova m0, m2 + mova m1, m3 + mova m2, m4 + mova m3, m5 + +.pass2_main: + mova m4, [coeffq+16*1 ] + mova m5, [coeffq+16*3 ] + mova m6, [coeffq+16*13] + mova m7, [coeffq+16*15] + mova [rsp+gprsize+16*3], m4 + mova [rsp+gprsize+16*4], m5 + mova [rsp+gprsize+16*9], m6 + mova [rsp+gprsize+32*5], m7 + mova m4, [coeffq+16*5 ] + mova m5, [coeffq+16*7 ] + mova m6, [coeffq+16*9 ] + mova m7, [coeffq+16*11] + + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass2_end + jmp m(iflipadst_8x8_internal_8bpc).end + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(iflipadst_8x8_internal_8bpc).end + + +INV_TXFM_8X16_FN identity, dct +INV_TXFM_8X16_FN identity, adst +INV_TXFM_8X16_FN identity, flipadst +INV_TXFM_8X16_FN identity, identity + +cglobal iidentity_8x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq+16*1, 32, 1 + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + mova [rsp+gprsize+16*1], m6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS coeffq+16*0, 32, 1 + mov tx2q, r3 + mova [rsp+gprsize+16*1], m6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +.pass2: + lea tx2q, [o(.end1)] + +.end: + mova [rsp+gprsize+16*0], m7 + mova [rsp+gprsize+16*1], m6 + mova m7, [o(pw_1697x16)] + REPX {IDTX16 x, 6, 7}, 0, 1, 2, 3, 4, 5 + mova m6, [rsp+gprsize+16*1] + mova [rsp+gprsize+16*2], m5 + IDTX16 6, 5, 7 + mova m5, [rsp+gprsize+16*0] + IDTX16 5, 7, 7 + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [rsp+gprsize+16*2] + mova [rsp+gprsize+16*0], m5 + mova [rsp+gprsize+16*1], m6 + mova [rsp+gprsize+16*2], m7 + jmp m(idct_8x8_internal_8bpc).end3 + +.end1: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + lea dstq, [dstq+strideq*2] + jmp .end + + +%macro INV_TXFM_16X8_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x8, 8, 16*16 +%ifidn %1_%2, dct_dct + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m1 + mov r2d, 4 + lea tx2q, [o(m(inv_txfm_add_dct_dct_16x8_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +.end: + RET +%endif +%endmacro + +INV_TXFM_16X8_FN dct, dct +INV_TXFM_16X8_FN dct, adst +INV_TXFM_16X8_FN dct, flipadst +INV_TXFM_16X8_FN dct, identity + +cglobal idct_16x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq+16*0, 32, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+16*1, 32, 1 + call .main + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass2: + lea tx2q, [o(.end)] + lea r3, [dstq+8] + jmp m(idct_8x8_internal_8bpc).pass2_main + +.end: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(idct_8x8_internal_8bpc).pass2_main + + +ALIGN function_align +cglobal_label .main + mova [rsp+gprsize*2+16*1], m2 + mova [rsp+gprsize*2+16*2], m6 + mova [rsp+gprsize*2+32*5], m5 + + mova m6, [o(pd_2048)] + ITX_MULSUB_2W 0, 7, 2, 5, 6, 401, 4076 ;t8a, t15a + ITX_MULSUB_2W 4, 3, 2, 5, 6, 3166, 2598 ;t9a, t14a + psubsw m2, m0, m4 ;t9 + paddsw m0, m4 ;t8 + psubsw m4, m7, m3 ;t14 + paddsw m7, m3 ;t15 + ITX_MULSUB_2W 4, 2, 3, 5, 6, 1567, 3784 ;t9a, t14a + mova m3, [rsp+gprsize*2+16*1] + mova m5, [rsp+gprsize*2+32*5] + mova [rsp+gprsize*2+16*1], m2 + mova [rsp+gprsize*2+32*5], m4 + mova m2, [rsp+gprsize*2+16*2] + mova [rsp+gprsize*2+16*2], m7 + ITX_MULSUB_2W 3, 5, 7, 4, 6, 1931, 3612 ;t10a, t13a + ITX_MULSUB_2W 2, 1, 7, 4, 6, 3920, 1189 ;t11a, t12a + psubsw m4, m2, m3 ;t10 + paddsw m2, m3 ;t11 + psubsw m3, m1, m5 ;t13 + paddsw m1, m5 ;t12 + ITX_MULSUB_2W 3, 4, 7, 5, 6, m3784, 1567 ;t10a, t13a + mova m7, [rsp+gprsize*2+32*5] + psubsw m6, m0, m2 ;t11a + paddsw m0, m2 ;t8a + paddsw m2, m7, m3 ;t9 + psubsw m7, m3 ;t10 + mova m5, [rsp+gprsize*2+16*0] + psubsw m3, m5, m0 ;out8 + paddsw m0, m5 ;out7 + mova [rsp+gprsize*2+32*5], m0 + mova m5, [rsp+gprsize*2+16*9] + psubsw m0, m5, m2 ;out9 + paddsw m2, m5 ;out6 + mova [rsp+gprsize*2+16*0], m0 + mova [rsp+gprsize*2+16*9], m2 + mova m0, [rsp+gprsize*2+16*1] + mova m2, [rsp+gprsize*2+16*2] + mova [rsp+gprsize*2+16*1], m3 + psubsw m5, m0, m4 ;t13 + paddsw m0, m4 ;t14 + mova m3, [o(pd_2048)] + psubsw m4, m2, m1 ;t12a + paddsw m1, m2 ;t15a + mova [rsp+gprsize*2+16*2], m1 + ITX_MULSUB_2W 5, 7, 1, 2, 3, 2896, 2896 ;t10a, t13a + ITX_MULSUB_2W 4, 6, 1, 2, 3, 2896, 2896 ;t11, t12 + mova m3, [rsp+gprsize*2+16*8] + psubsw m2, m3, m5 ;out10 + paddsw m3, m5 ;out5 + mova m5, [rsp+gprsize*2+16*7] + mova [rsp+gprsize*2+16*8], m3 + psubsw m3, m5, m4 ;out11 + paddsw m5, m4 ;out4 + mova m4, [rsp+gprsize*2+16*6] + mova [rsp+gprsize*2+16*7], m5 + paddsw m5, m4, m6 ;out3 + psubsw m4, m6 ;out12 + mova m6, [rsp+gprsize*2+16*5] + mova [rsp+gprsize*2+16*6], m5 + psubsw m5, m6, m7 ;out13 + paddsw m6, m7 ;out2 + mova m7, [rsp+gprsize*2+16*4] + mova [rsp+gprsize*2+16*5], m6 + psubsw m6, m7, m0 ;out14 + paddsw m7, m0 ;out1 + mova m1, [rsp+gprsize*2+16*2] + mova m0, [rsp+gprsize*2+16*3] + mova [rsp+gprsize*2+16*4], m7 + psubsw m7, m0, m1 ;out15 + paddsw m0, m1 ;out0 + mova [rsp+gprsize*2+16*3], m0 + mova m1, [rsp+gprsize*2+16*0] + mova m0, [rsp+gprsize*2+16*1] + mova [rsp+gprsize*2+16*0], m7 + ret + +INV_TXFM_16X8_FN adst, dct +INV_TXFM_16X8_FN adst, adst +INV_TXFM_16X8_FN adst, flipadst +INV_TXFM_16X8_FN adst, identity + +cglobal iadst_16x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m7, [o(pw_2896x8)] + pmulhrsw m0, m7, [coeffq+16*0 ] + pmulhrsw m1, m7, [coeffq+16*1 ] + pmulhrsw m2, m7, [coeffq+16*14] + pmulhrsw m3, m7, [coeffq+16*15] + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*9], m2 + mova [rsp+gprsize+32*5], m3 + pmulhrsw m0, m7, [coeffq+16*6 ] + pmulhrsw m1, m7, [coeffq+16*7 ] + pmulhrsw m2, m7, [coeffq+16*8 ] + pmulhrsw m3, m7, [coeffq+16*9 ] + mova [rsp+gprsize+16*3], m2 + mova [rsp+gprsize+16*4], m3 + mova [rsp+gprsize+16*5], m0 + mova [rsp+gprsize+16*6], m1 + pmulhrsw m0, m7, [coeffq+16*2 ] + pmulhrsw m1, m7, [coeffq+16*3 ] + pmulhrsw m2, m7, [coeffq+16*4 ] + pmulhrsw m3, m7, [coeffq+16*5 ] + pmulhrsw m4, m7, [coeffq+16*10] + pmulhrsw m5, m7, [coeffq+16*11] + pmulhrsw m6, m7, [coeffq+16*12] + pmulhrsw m7, [coeffq+16*13] + + call .main + call .main_pass1_end + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + jmp m(iadst_8x8_internal_8bpc).pass1_end + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + jmp m(iadst_8x8_internal_8bpc).pass1_end + +.pass2: + lea tx2q, [o(.end)] + lea r3, [dstq+8] + jmp m(iadst_8x8_internal_8bpc).pass2_main + +.end: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(iadst_8x8_internal_8bpc).pass2_main + +ALIGN function_align +cglobal_label .main + mova [rsp+gprsize*2+16*0], m1 + mova [rsp+gprsize*2+16*1], m2 + mova [rsp+gprsize*2+16*2], m6 + + mova m6, [o(pd_2048)] + ITX_MULSUB_2W 7, 0, 1, 2, 6, 995, 3973 ;t3, t2 + ITX_MULSUB_2W 3, 4, 1, 2, 6, 3513, 2106 ;t11, t10 + psubsw m1, m0, m4 ;t10a + paddsw m0, m4 ;t2a + psubsw m4, m7, m3 ;t11a + paddsw m3, m7 ;t3a + ITX_MULSUB_2W 1, 4, 7, 2, 6, 3406, 2276 ;t11, t10 + mova m2, [rsp+gprsize*2+16*0] ;in3 + mova m7, [rsp+gprsize*2+16*1] ;in4 + mova [rsp+gprsize*2+16*0], m1 ;t11 + mova [rsp+gprsize*2+16*1], m4 ;t10 + mova m1, [rsp+gprsize*2+16*2] ;in12 + mova [rsp+gprsize*2+16*2], m0 ;t2a + ITX_MULSUB_2W 5, 7, 0, 4, 6, 1751, 3703 ;t5, t4 + ITX_MULSUB_2W 2, 1, 0, 4, 6, 3857, 1380 ;t13, t12 + psubsw m0, m7, m1 ;t12a + paddsw m1, m7 ;t4a + psubsw m4, m5, m2 ;t13a + paddsw m5, m2 ;t5a + ITX_MULSUB_2W 4, 0, 7, 2, 6, 4017, 799 ;t12, t13 + mova m2, [rsp+gprsize*2+16*8] ;in1 + mova m7, [rsp+gprsize*2+16*9] ;in14 + mova [rsp+gprsize*2+16*8], m4 ;t12 + mova [rsp+gprsize*2+16*9], m0 ;t13 + mova m4, [rsp+gprsize*2+16*4] ;in9 + mova m0, [rsp+gprsize*2+16*5] ;in6 + mova [rsp+gprsize*2+16*4], m1 ;t4a + mova [rsp+gprsize*2+16*5], m5 ;t5a + ITX_MULSUB_2W 2, 7, 1, 5, 6, 4052, 601 ;t15, t14 + ITX_MULSUB_2W 4, 0, 1, 5, 6, 2440, 3290 ;t7, t6 + psubsw m1, m0, m7 ;t14a + paddsw m0, m7 ;t6a + psubsw m5, m4, m2 ;t15a + paddsw m4, m2 ;t7a + ITX_MULSUB_2W 5, 1, 7, 2, 6, 2276, 3406 ;t14, t15 + mova m2, [rsp+gprsize*2+16*2] ;t2a + mova [rsp+gprsize*2+16*2], m5 ;t14 + psubsw m7, m2, m0 ;t6 + paddsw m2, m0 ;t2 + psubsw m0, m3, m4 ;t7 + paddsw m3, m4 ;t3 + ITX_MULSUB_2W 0, 7, 4, 5, 6, 3784, 1567 ;t6a, t7a + mova m4, [rsp+gprsize*2+16*7] ;in0 + mova m5, [rsp+gprsize*2+32*5] ;in15 + mova [rsp+gprsize*2+16*7], m3 ;t3 + mova [rsp+gprsize*2+32*5], m1 ;t15 + mova m1, [rsp+gprsize*2+16*6] ;in7 + mova m3, [rsp+gprsize*2+16*3] ;in8 + mova [rsp+gprsize*2+16*6], m7 ;t7a + mova [rsp+gprsize*2+16*3], m0 ;t6a + ITX_MULSUB_2W 5, 4, 0, 7, 6, 201, 4091 ;t1, t0 + ITX_MULSUB_2W 1, 3, 0, 7, 6, 3035, 2751 ;t9, t8 + psubsw m0, m4, m3 ;t8a + paddsw m4, m3 ;t0a + psubsw m3, m5, m1 ;t9a + paddsw m5, m1 ;t1a + ITX_MULSUB_2W 0, 3, 1, 7, 6, 799, 4017 ;t9, t8 + mova m1, [rsp+gprsize*2+16*4] ;t4a + mova m7, [rsp+gprsize*2+16*5] ;t5a + mova [rsp+gprsize*2+16*4], m3 ;t8 + mova [rsp+gprsize*2+16*5], m0 ;t9 + psubsw m0, m4, m1 ;t4 + paddsw m4, m1 ;t0 + psubsw m3, m5, m7 ;t5 + paddsw m5, m7 ;t1 + ITX_MULSUB_2W 0, 3, 1, 7, 6, 1567, 3784 ;t5a, t4a + mova m7, [rsp+gprsize*2+16*3] ;t6a + psubsw m1, m4, m2 ;t2a + paddsw m4, m2 ;out0 + mova [rsp+gprsize*2+16*3], m4 ;out0 + mova m4, [rsp+gprsize*2+16*6] ;t7a + psubsw m2, m3, m7 ;t6 + paddsw m3, m7 ;-out3 + mova [rsp+gprsize*2+16*6], m3 ;-out3 + psubsw m3, m0, m4 ;t7 + paddsw m0, m4 ;out12 + mova [rsp+gprsize*2+16*12], m3 + mova m3, [rsp+gprsize*2+16*7] ;t3 + mova [rsp+gprsize*2+16* 7], m2 ;out4 + psubsw m2, m5, m3 ;t3a + paddsw m5, m3 ;-out15 + mova [rsp+gprsize*2+16*11], m2 + mova m2, [rsp+gprsize*2+32*5] ;t15 + mova [rsp+gprsize*2+16*10], m1 ;-out7 + mova m1, [rsp+gprsize*2+16*0] ;t11 + mova [rsp+gprsize*2+16*0 ], m5 ;-out15 + mova m3, [rsp+gprsize*2+16*1] ;t10 + mova [rsp+gprsize*2+16*1 ], m4 ;-out11 + mova m4, [rsp+gprsize*2+16*2] ;t14 + mova [rsp+gprsize*2+16*2 ], m0 ;out12 + psubsw m0, m3, m4 ;t14a + paddsw m3, m4 ;t10a + psubsw m5, m1, m2 ;t15a + paddsw m1, m2 ;t11a + ITX_MULSUB_2W 5, 0, 2, 4, 6, 3784, 1567 ;t14, t15 + mova m2, [rsp+gprsize*2+16*4] ;t8 + mova m4, [rsp+gprsize*2+16*5] ;t9 + mova [rsp+gprsize*2+16*4], m3 ;t10a + mova [rsp+gprsize*2+16*5], m1 ;t11a + mova m3, [rsp+gprsize*2+16*8] ;t12 + mova m1, [rsp+gprsize*2+16*9] ;t13 + mova [rsp+gprsize*2+16*8], m5 ;t14 + mova [rsp+gprsize*2+16*9], m0 ;t15 + psubsw m5, m2, m3 ;t12a + paddsw m2, m3 ;t8a + psubsw m0, m4, m1 ;t13a + paddsw m4, m1 ;t9a + ITX_MULSUB_2W 5, 0, 1, 3, 6, 1567, 3784 ;t13, t12 + mova m6, [rsp+gprsize*2+16*4] ;t10a + mova m1, [rsp+gprsize*2+16*5] ;t11a + psubsw m3, m2, m6 ;t10 + paddsw m2, m6 ;-out1 + paddsw m6, m4, m1 ;out14 + psubsw m4, m1 ;t11 + mova [rsp+gprsize*2+16*14], m4 + mova [rsp+gprsize*2+16* 4], m2 ;-out1 + mova m4, [rsp+gprsize*2+16*8] ;t14 + mova m2, [rsp+gprsize*2+16*9] ;t15 + mova [rsp+gprsize*2+16* 9], m3 ;out6 + psubsw m3, m0, m4 ;t14a + paddsw m0, m4 ;out2 + psubsw m4, m5, m2 ;t15a + paddsw m5, m2 ;-out13 + mova [rsp+gprsize*2+16* 5], m0 ;out2 + ret +ALIGN function_align +.main_pass1_end: + mova m0, [rsp+gprsize*2+16*14] + mova [rsp+gprsize*2+16*14], m5 + mova [rsp+gprsize*2+16*15], m6 + mova m5, [o(pw_2896_2896)] + mova m6, [o(pw_2896_m2896)] + mova m7, [o(pd_2048)] + punpcklwd m2, m3, m4 + punpckhwd m3, m4 + pmaddwd m4, m5, m2 + pmaddwd m2, m6 + pmaddwd m1, m5, m3 + pmaddwd m3, m6 + REPX {paddd x, m7}, m4, m2, m1, m3 + REPX {psrad x, 12}, m4, m1, m2, m3 + packssdw m4, m1 ;-out5 + packssdw m2, m3 ;out10 + mova [rsp+gprsize*2+16* 8], m4 + mova m3, [rsp+gprsize*2+16* 9] + punpcklwd m1, m3, m0 + punpckhwd m3, m0 + pmaddwd m0, m5, m1 + pmaddwd m1, m6 + pmaddwd m4, m5, m3 + pmaddwd m3, m6 + REPX {paddd x, m7}, m0, m1, m4, m3 + REPX {psrad x, 12}, m0, m4, m1, m3 + packssdw m0, m4 ;out6 + packssdw m1, m3 ;-out9 + mova [rsp+gprsize*2+16* 9], m0 + mova m0, [rsp+gprsize*2+16* 7] + mova m4, [rsp+gprsize*2+16*12] + punpcklwd m3, m0, m4 + punpckhwd m0, m4 + pmaddwd m4, m5, m3 + pmaddwd m3, m6 + pmaddwd m5, m0 + pmaddwd m0, m6 + REPX {paddd x, m7}, m4, m3, m5, m0 + REPX {psrad x, 12}, m4, m5, m3, m0 + packssdw m4, m5 ;out4 + packssdw m3, m0 ;-out11 + mova [rsp+gprsize*2+16* 7], m4 + mova m4, [rsp+gprsize*2+16*10] + mova m5, [rsp+gprsize*2+16*11] + punpcklwd m0, m4, m5 + punpckhwd m4, m5 + pmaddwd m5, m0, [o(pw_2896_2896)] + pmaddwd m0, m6 + pmaddwd m6, m4 + pmaddwd m4, [o(pw_2896_2896)] + REPX {paddd x, m7}, m5, m0, m6, m4 + REPX {psrad x, 12}, m0, m6, m5, m4 + packssdw m0, m6 ;out8 + packssdw m5, m4 ;-out7 + mova [rsp+gprsize*2+16*10], m5 + mova m4, [rsp+gprsize*2+16* 2] ;out12 + mova m5, [rsp+gprsize*2+16*14] ;-out13 + mova m6, [rsp+gprsize*2+16*15] ;out14 + ret +ALIGN function_align +cglobal_label .main_pass2_end + mova m7, [o(pw_2896x8)] + mova m1, [rsp+gprsize*2+16* 9] + mova m2, [rsp+gprsize*2+16*14] + paddsw m0, m1, m2 + psubsw m1, m2 + pmulhrsw m0, m7 ;out6 + pmulhrsw m1, m7 ;-out9 + mova [rsp+gprsize*2+16* 9], m0 + psubsw m2, m3, m4 + paddsw m3, m4 + pmulhrsw m2, m7 ;out10 + pmulhrsw m3, m7 ;-out5 + mova [rsp+gprsize*2+16* 8], m3 + mova m3, [rsp+gprsize*2+16* 7] + mova m4, [rsp+gprsize*2+16*12] + paddsw m0, m3, m4 + psubsw m3, m4 + pmulhrsw m0, m7 ;out4 + pmulhrsw m3, m7 ;-out11 + mova [rsp+gprsize*2+16* 7], m0 + mova m0, [rsp+gprsize*2+16*10] + paddsw m4, m0, [rsp+gprsize*2+16*11] + psubsw m0, [rsp+gprsize*2+16*11] + pmulhrsw m4, m7 ;-out7 + pmulhrsw m0, m7 ;out8 + mova [rsp+gprsize*2+16*10], m4 + mova m4, [rsp+gprsize*2+16*2 ] ;out12 + ret + +INV_TXFM_16X8_FN flipadst, dct +INV_TXFM_16X8_FN flipadst, adst +INV_TXFM_16X8_FN flipadst, flipadst +INV_TXFM_16X8_FN flipadst, identity + +cglobal iflipadst_16x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mova m7, [o(pw_2896x8)] + pmulhrsw m0, m7, [coeffq+16*0 ] + pmulhrsw m1, m7, [coeffq+16*1 ] + pmulhrsw m2, m7, [coeffq+16*14] + pmulhrsw m3, m7, [coeffq+16*15] + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*9], m2 + mova [rsp+gprsize+32*5], m3 + pmulhrsw m0, m7, [coeffq+16*6 ] + pmulhrsw m1, m7, [coeffq+16*7 ] + pmulhrsw m2, m7, [coeffq+16*8 ] + pmulhrsw m3, m7, [coeffq+16*9 ] + mova [rsp+gprsize+16*3], m2 + mova [rsp+gprsize+16*4], m3 + mova [rsp+gprsize+16*5], m0 + mova [rsp+gprsize+16*6], m1 + pmulhrsw m0, m7, [coeffq+16*2 ] + pmulhrsw m1, m7, [coeffq+16*3 ] + pmulhrsw m2, m7, [coeffq+16*4 ] + pmulhrsw m3, m7, [coeffq+16*5 ] + pmulhrsw m4, m7, [coeffq+16*10] + pmulhrsw m5, m7, [coeffq+16*11] + pmulhrsw m6, m7, [coeffq+16*12] + pmulhrsw m7, [coeffq+16*13] + + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS coeffq+16*0, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + jmp m(iflipadst_8x8_internal_8bpc).pass1_end + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS coeffq+16*0, 32 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + jmp m(iflipadst_8x8_internal_8bpc).pass1_end + +.pass2: + lea tx2q, [o(.end)] + lea r3, [dstq+8] + jmp m(iflipadst_8x8_internal_8bpc).pass2_main + +.end: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(iflipadst_8x8_internal_8bpc).pass2_main + + +INV_TXFM_16X8_FN identity, dct +INV_TXFM_16X8_FN identity, adst +INV_TXFM_16X8_FN identity, flipadst +INV_TXFM_16X8_FN identity, identity + +cglobal iidentity_16x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + add coeffq, 16*16 + mova m4, [coeffq-16*7] + mova m5, [coeffq-16*5] + mova m6, [coeffq-16*3] + mova m7, [coeffq-16*1] + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + +.pass1: + mova m0, [o(pw_2896x8)] + mova m2, [o(pw_1697x16)] + mova m3, [o(pw_16384)] + sub coeffq, 8*16 + REPX {pmulhrsw x, m0}, m4, m5, m6, m7 + pmulhrsw m1, m2, m4 + pmulhrsw m1, m3 + paddsw m1, m4 ; 1 + pmulhrsw m4, m2, m5 + pmulhrsw m4, m3 + paddsw m4, m5 ; 3 + pmulhrsw m5, m2, m6 + pmulhrsw m5, m3 + paddsw m5, m6 ; 5 + pmulhrsw m6, m2, m7 + pmulhrsw m6, m3 + paddsw m7, m6 ; 7 + pmulhrsw m6, m0, [coeffq+16*6] + mova [rsp+gprsize+16*0], m4 + pmulhrsw m4, m2, m6 + pmulhrsw m4, m3 + paddsw m6, m4 ; 6 + pmulhrsw m4, m0, [coeffq+16*4] + mova [rsp+gprsize+16*1], m6 + pmulhrsw m6, m2, m4 + pmulhrsw m6, m3 + paddsw m4, m6 ; 4 + pmulhrsw m6, m0, [coeffq+16*2] + pmulhrsw m0, [coeffq+16*0] + pmulhrsw m2, m6 + pmulhrsw m2, m3 + paddsw m2, m6 ; 2 + pmulhrsw m6, m0, [o(pw_1697x16)] + pmulhrsw m6, m3 + mova m3, [rsp+gprsize+16*0] + paddsw m0, m6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +.pass1_end: + mova [coeffq+16*1], m4 + mova [coeffq+16*3], m5 + mova [coeffq+16*5], m6 + mova [coeffq+16*7], m7 + mova m4, [coeffq-16*7] + mova m5, [coeffq-16*5] + mova m6, [coeffq-16*3] + mova m7, [coeffq-16*1] + mova [coeffq-16*7], m0 + mova [coeffq-16*5], m1 + mova [coeffq-16*3], m2 + mova [coeffq-16*1], m3 + mov tx2q, r3 + jmp .pass1 + +.pass2: + lea tx2q, [o(.end)] + lea r3, [dstq+8] + jmp m(iidentity_8x8_internal_8bpc).end + +.end: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + mov dstq, r3 + jmp m(iidentity_8x8_internal_8bpc).end + + +%macro INV_TXFM_16X16_FN 2 ; type1, type2 + INV_TXFM_FN %1, %2, 16x16, 8, 16*16 +%ifidn %1_%2, dct_dct + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r2d, 8 + lea tx2q, [o(m(inv_txfm_add_dct_dct_16x16_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly +.end: + RET +%endif +%endmacro + +INV_TXFM_16X16_FN dct, dct +INV_TXFM_16X16_FN dct, adst +INV_TXFM_16X16_FN dct, flipadst +INV_TXFM_16X16_FN dct, identity + +cglobal idct_16x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq+16*1, 64 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*3, 64 + call m(idct_16x8_internal_8bpc).main + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + mova m7, [o(pw_8192)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+16*17, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + mova m7, [o(pw_8192)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS coeffq+16*0, 64 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*2, 64 + call m(idct_16x8_internal_8bpc).main + lea tx2q, [o(.pass1_end2)] + mova m7, [o(pw_8192)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+16*16, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + mova m7, [o(pw_8192)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass2: + lea tx2q, [o(.end)] + jmp m(idct_8x16_internal_8bpc).pass2_pre + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.end1)] + mov dstq, r3 + lea r3, [dstq+8] + jmp m(idct_8x8_internal_8bpc).end + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + + add coeffq, 32*8 + mov dstq, r3 + + mova m0, [coeffq+16*0 ] + mova m1, [coeffq+16*4 ] + mova m2, [coeffq+16*8 ] + mova m3, [coeffq+16*12] + mova m4, [coeffq+16*1 ] + mova m5, [coeffq+16*5 ] + mova m6, [coeffq+16*9 ] + mova m7, [coeffq+16*13] + lea tx2q, [o(m(idct_8x16_internal_8bpc).end)] + jmp m(idct_8x16_internal_8bpc).pass2_main + + +%macro ITX_16X16_ADST_LOAD_ODD_COEFS 0 + mova m0, [coeffq+16*1 ] + mova m1, [coeffq+16*3 ] + mova m2, [coeffq+16*29] + mova m3, [coeffq+16*31] + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*9], m2 + mova [rsp+gprsize+32*5], m3 + mova m0, [coeffq+16*13] + mova m1, [coeffq+16*15] + mova m2, [coeffq+16*17] + mova m3, [coeffq+16*19] + mova [rsp+gprsize+16*3], m2 + mova [rsp+gprsize+16*4], m3 + mova [rsp+gprsize+16*5], m0 + mova [rsp+gprsize+16*6], m1 + mova m0, [coeffq+16*5 ] + mova m1, [coeffq+16*7 ] + mova m2, [coeffq+16*9 ] + mova m3, [coeffq+16*11] + mova m4, [coeffq+16*21] + mova m5, [coeffq+16*23] + mova m6, [coeffq+16*25] + mova m7, [coeffq+16*27] +%endmacro + +%macro ITX_16X16_ADST_LOAD_EVEN_COEFS 0 + mova m0, [coeffq+16*0 ] + mova m1, [coeffq+16*2 ] + mova m2, [coeffq+16*28] + mova m3, [coeffq+16*30] + mova [rsp+gprsize+16*7], m0 + mova [rsp+gprsize+16*8], m1 + mova [rsp+gprsize+16*9], m2 + mova [rsp+gprsize+32*5], m3 + mova m0, [coeffq+16*12] + mova m1, [coeffq+16*14] + mova m2, [coeffq+16*16] + mova m3, [coeffq+16*18] + mova [rsp+gprsize+16*3], m2 + mova [rsp+gprsize+16*4], m3 + mova [rsp+gprsize+16*5], m0 + mova [rsp+gprsize+16*6], m1 + mova m0, [coeffq+16*4 ] + mova m1, [coeffq+16*6 ] + mova m2, [coeffq+16*8 ] + mova m3, [coeffq+16*10] + mova m4, [coeffq+16*20] + mova m5, [coeffq+16*22] + mova m6, [coeffq+16*24] + mova m7, [coeffq+16*26] +%endmacro + +INV_TXFM_16X16_FN adst, dct +INV_TXFM_16X16_FN adst, adst +INV_TXFM_16X16_FN adst, flipadst + +cglobal iadst_16x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + ITX_16X16_ADST_LOAD_ODD_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + mova m7, [o(pw_8192)] + jmp m(iadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+16*17, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + mova m7, [o(pw_8192)] + jmp m(iadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+16*1, 32 + ITX_16X16_ADST_LOAD_EVEN_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + + lea tx2q, [o(.pass1_end2)] + mova m7, [o(pw_8192)] + jmp m(iadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+16*16, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + mova m7, [o(pw_8192)] + jmp m(iadst_8x8_internal_8bpc).pass1_end1 + +.pass2: + lea tx2q, [o(.end)] + jmp m(iadst_8x16_internal_8bpc).pass2_pre + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.end1)] + mov dstq, r3 + lea r3, [dstq+8] + jmp m(iadst_8x8_internal_8bpc).end + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + + add coeffq, 32*8 + mov dstq, r3 + + mova m4, [coeffq+16*0 ] + mova m5, [coeffq+16*2 ] + mova m0, [coeffq+16*4 ] + mova m1, [coeffq+16*6 ] + mova m2, [coeffq+16*8 ] + mova m3, [coeffq+16*10] + mova m6, [coeffq+16*12] + mova m7, [coeffq+16*14] + mova [rsp+gprsize+16*7], m4 + mova [rsp+gprsize+16*8], m5 + mova [rsp+gprsize+16*5], m6 + mova [rsp+gprsize+16*6], m7 + lea tx2q, [o(m(iadst_8x16_internal_8bpc).end)] + jmp m(iadst_8x16_internal_8bpc).pass2_main + + +INV_TXFM_16X16_FN flipadst, dct +INV_TXFM_16X16_FN flipadst, adst +INV_TXFM_16X16_FN flipadst, flipadst + +cglobal iflipadst_16x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + ITX_16X16_ADST_LOAD_ODD_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + mova m7, [o(pw_m8192)] + jmp m(iflipadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+16*1, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + mova m7, [o(pw_m8192)] + jmp m(iflipadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+16*17, 32 + ITX_16X16_ADST_LOAD_EVEN_COEFS + call m(iadst_16x8_internal_8bpc).main + call m(iadst_16x8_internal_8bpc).main_pass1_end + + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS coeffq+16*0, 32 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end2)] + mova m7, [o(pw_m8192)] + jmp m(iflipadst_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+16*16, 32 + LOAD_8ROWS coeffq+16* 0, 32 + mova [rsp+gprsize+16*0], m7 + mov tx2q, r3 + mova m7, [o(pw_m8192)] + jmp m(iflipadst_8x8_internal_8bpc).pass1_end1 + +.pass2: + lea tx2q, [o(.end)] + lea r3, [dstq+8] + jmp m(iflipadst_8x16_internal_8bpc).pass2_pre + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.end1)] + lea dstq, [dstq+strideq*2] + jmp m(iflipadst_8x8_internal_8bpc).end + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + + add coeffq, 32*8 + + mova m4, [coeffq+16*0 ] + mova m5, [coeffq+16*2 ] + mova m0, [coeffq+16*4 ] + mova m1, [coeffq+16*6 ] + mova m2, [coeffq+16*8 ] + mova m3, [coeffq+16*10] + mova m6, [coeffq+16*12] + mova m7, [coeffq+16*14] + mova [rsp+gprsize+16*7], m4 + mova [rsp+gprsize+16*8], m5 + mova [rsp+gprsize+16*5], m6 + mova [rsp+gprsize+16*6], m7 + + lea tx2q, [o(.end2)] + mov dstq, r3 + jmp m(iflipadst_8x16_internal_8bpc).pass2_main + +.end2: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + lea dstq, [dstq+strideq*2] + jmp m(iflipadst_8x8_internal_8bpc).end + + +%macro IDTX16B 3 ; src/dst, tmp, pw_1697x16 + pmulhrsw m%2, m%3, m%1 + psraw m%2, 1 + pavgw m%1, m%2 +%endmacro + +INV_TXFM_16X16_FN identity, dct +INV_TXFM_16X16_FN identity, identity + +cglobal iidentity_16x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + add coeffq, 16*17 + mov r3, tx2q + lea tx2q, [o(.pass1_end)] + +.pass1: + mova m6, [o(pw_1697x16)] + mova m7, [coeffq+32*6] + mova m0, [coeffq+32*0] + mova m1, [coeffq+32*1] + mova m2, [coeffq+32*2] + mova m3, [coeffq+32*3] + mova m4, [coeffq+32*4] + REPX {IDTX16B x, 5, 6}, 7, 0, 1, 2, 3, 4 + mova m5, [coeffq+32*5] + mova [rsp+gprsize+16*1], m7 + IDTX16B 5, 7, 6 + mova m7, [coeffq+32*7] + IDTX16B 7, 6, 6 + jmp m(idct_8x8_internal_8bpc).pass1_end3 + +.pass1_end: + SAVE_8ROWS coeffq, 32 + sub coeffq, 16 + lea tx2q, [o(.pass1_end1)] + jmp .pass1 + +.pass1_end1: + SAVE_8ROWS coeffq, 32 + sub coeffq, 15*16 + lea tx2q, [o(.pass1_end2)] + jmp .pass1 + +.pass1_end2: + SAVE_8ROWS coeffq, 32 + sub coeffq, 16 + mov tx2q, r3 + jmp .pass1 + +.pass2: + lea r3, [dstq+8] + lea tx2q, [o(.end1)] + +.end: + mova [rsp+gprsize+16*0], m7 + mova [rsp+gprsize+16*1], m4 + mova m7, [o(pw_1697x16)] + REPX {IDTX16 x, 4, 7}, 5, 6, 0, 1, 2, 3 + mova m4, [o(pw_2048)] + pmulhrsw m5, m4 + pmulhrsw m6, m4 + mova [rsp+gprsize+16*2], m5 + mova m5, [rsp+gprsize+16*1] + mova [rsp+gprsize+16*1], m6 + IDTX16 5, 6, 7 + mova m6, [rsp+gprsize+16*0] + IDTX16 6, 7, 7 + REPX {pmulhrsw x, m4}, m0, m1, m2, m3, m6 + pmulhrsw m4, m5 + mova [rsp+gprsize+16*0], m6 + jmp m(idct_8x8_internal_8bpc).end3 + +.end1: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(.end2)] + lea dstq, [dstq+strideq*2] + jmp .end + +.end2: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + + add coeffq, 32*8 + LOAD_8ROWS coeffq, 32 + lea tx2q, [o(.end3)] + mov dstq, r3 + jmp .end + +.end3: + LOAD_8ROWS coeffq+16*1, 32 + lea tx2q, [o(m(idct_8x16_internal_8bpc).end1)] + lea dstq, [dstq+strideq*2] + jmp .end + + +cglobal inv_txfm_add_dct_dct_8x32_8bpc, 4, 6, 8, 16*36, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_8x32_internal_8bpc) + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + pmulhrsw m0, m2 + psrlw m2, 2 ;pw_2048 + pmulhrsw m0, m1 + pmulhrsw m0, m2 + pshuflw m0, m0, q0000 + punpcklwd m0, m0 + mov r3d, 8 + lea tx2q, [o(.end)] + jmp m(inv_txfm_add_dct_dct_8x8_8bpc).loop + +.end: + RET + + + +cglobal idct_8x32_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + cmp eobd, 106 + jle .fast + + LOAD_8ROWS coeffq+16*3, 64 + call m(idct_8x8_internal_8bpc).main + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1: + mova [rsp+gprsize+16*9 ], m0 ;in24 + mova [rsp+gprsize+16*10], m4 ;in28 + mova [rsp+gprsize+16*17], m2 ;in26 + mova [rsp+gprsize+16*18], m6 ;in30 + mova [rsp+gprsize+16*31], m1 ;in25 + mova [rsp+gprsize+16*30], m3 ;in27 + mova [rsp+gprsize+16*27], m5 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + LOAD_8ROWS coeffq+16*2, 64 + call m(idct_8x8_internal_8bpc).main + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_1: + mova [rsp+gprsize+16*7 ], m0 ;in16 + mova [rsp+gprsize+16*8 ], m4 ;in20 + mova [rsp+gprsize+16*15], m2 ;in18 + mova [rsp+gprsize+16*16], m6 ;in22 + mova [rsp+gprsize+16*33], m1 ;in17 + mova [rsp+gprsize+16*28], m3 ;in19 + mova [rsp+gprsize+16*29], m5 ;in21 + mova [rsp+gprsize+16*32], m7 ;in23 + +.fast: + LOAD_8ROWS coeffq+16*1, 64 + call m(idct_8x8_internal_8bpc).main + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + mova [rsp+gprsize+16*5 ], m0 ;in8 + mova [rsp+gprsize+16*6 ], m4 ;in12 + mova [rsp+gprsize+16*13], m2 ;in10 + mova [rsp+gprsize+16*14], m6 ;in14 + mova [rsp+gprsize+16*21], m1 ;in9 + mova [rsp+gprsize+16*24], m3 ;in11 + mova [rsp+gprsize+16*25], m5 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + LOAD_8ROWS coeffq+16*0, 64 + call m(idct_8x8_internal_8bpc).main + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + mova [rsp+gprsize+16*11], m2 ;in2 + mova [rsp+gprsize+16*12], m6 ;in6 + mova [rsp+gprsize+16*19], m1 ;in1 + mova [rsp+gprsize+16*26], m3 ;in3 + mova [rsp+gprsize+16*23], m5 ;in5 + mova [rsp+gprsize+16*22], m7 ;in7 + mova m1, m4 ;in4 + mova m2, [rsp+gprsize+16*5 ] ;in8 + mova m3, [rsp+gprsize+16*6 ] ;in12 + + cmp eobd, 106 + jg .full + + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3 , 16 + mova m0, [rsp+gprsize+16*11] + mova m1, [rsp+gprsize+16*12] + mova m2, [rsp+gprsize+16*13] + mova m3, [rsp+gprsize+16*14] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call .main_fast + jmp .pass2 + +.full: + mova m4, [rsp+gprsize+16*7 ] ;in16 + mova m5, [rsp+gprsize+16*8 ] ;in20 + mova m6, [rsp+gprsize+16*9 ] ;in24 + mova m7, [rsp+gprsize+16*10] ;in28 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3 , 16 + LOAD_8ROWS rsp+gprsize+16*11, 16 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + call .main + +.pass2: + lea r3, [o(.end6)] + +.end: + mova [rsp+gprsize+16*0 ], m7 + lea tx2q, [o(.end2)] + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31 + + jmp tx2q + +.end2: + lea tx2q, [o(.end3)] + jmp m(idct_8x8_internal_8bpc).end + +.end3: + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0 ], m7 + lea dstq, [dstq+strideq*2] + lea tx2q, [o(.end4)] + jmp m(idct_8x8_internal_8bpc).end + +.end4: + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0 ], m7 + lea dstq, [dstq+strideq*2] + lea tx2q, [o(.end5)] + jmp m(idct_8x8_internal_8bpc).end + +.end5: + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0 ], m7 + lea dstq, [dstq+strideq*2] + mov tx2q, r3 + jmp m(idct_8x8_internal_8bpc).end + +.end6: + ret + +ALIGN function_align +cglobal_label .main_veryfast + mova m0, [rsp+gprsize*2+16*19] ;in1 + pmulhrsw m3, m0, [o(pw_4091x8)] ;t30,t31 + pmulhrsw m0, [o(pw_201x8)] ;t16,t17 + mova m7, [o(pd_2048)] + mova [rsp+gprsize*2+16*19], m0 ;t16 + mova [rsp+gprsize*2+16*34], m3 ;t31 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 799, 4017 ;t17a, t30a + mova [rsp+gprsize*2+16*20], m3 ;t17a + mova [rsp+gprsize*2+16*33], m0 ;t30a + mova m1, [rsp+gprsize*2+16*22] ;in7 + pmulhrsw m2, m1, [o(pw_3857x8)] ;t28,t29 + pmulhrsw m1, [o(pw_m1380x8)] ;t18,t19 + mova [rsp+gprsize*2+16*22], m1 ;t19 + mova [rsp+gprsize*2+16*31], m2 ;t28 + ITX_MULSUB_2W 2, 1, 0, 3, 7, m4017, 799 ;t18a, t29a + mova [rsp+gprsize*2+16*21], m2 ;t18a + mova [rsp+gprsize*2+16*32], m1 ;t29a + mova m0, [rsp+gprsize*2+16*23] ;in5 + pmulhrsw m3, m0, [o(pw_3973x8)] ;t26, t27 + pmulhrsw m0, [o(pw_995x8)] ;t20, t21 + mova [rsp+gprsize*2+16*23], m0 ;t20 + mova [rsp+gprsize*2+16*30], m3 ;t27 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 3406, 2276 ;t21a, t26a + mova [rsp+gprsize*2+16*24], m3 ;t21a + mova [rsp+gprsize*2+16*29], m0 ;t26a + mova m2, [rsp+gprsize*2+16*26] ;in3 + pxor m0, m0 + mova m3, m0 + pmulhrsw m1, m2, [o(pw_4052x8)] + pmulhrsw m2, [o(pw_m601x8)] + jmp .main2 + +ALIGN function_align +cglobal_label .main_fast ;bottom half is zero + mova m0, [rsp+gprsize*2+16*19] ;in1 + mova m1, [rsp+gprsize*2+16*20] ;in15 + pmulhrsw m3, m0, [o(pw_4091x8)] ;t31a + pmulhrsw m0, [o(pw_201x8)] ;t16a + pmulhrsw m2, m1, [o(pw_3035x8)] ;t30a + pmulhrsw m1, [o(pw_m2751x8)] ;t17a + mova m7, [o(pd_2048)] + psubsw m4, m0, m1 ;t17 + paddsw m0, m1 ;t16 + psubsw m5, m3, m2 ;t30 + paddsw m3, m2 ;t31 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 799, 4017 ;t17a, t30a + mova [rsp+gprsize*2+16*19], m0 ;t16 + mova [rsp+gprsize*2+16*20], m5 ;t17a + mova [rsp+gprsize*2+16*33], m4 ;t30a + mova [rsp+gprsize*2+16*34], m3 ;t31 + mova m0, [rsp+gprsize*2+16*21] ;in9 + mova m1, [rsp+gprsize*2+16*22] ;in7 + pmulhrsw m3, m0, [o(pw_3703x8)] + pmulhrsw m0, [o(pw_1751x8)] + pmulhrsw m2, m1, [o(pw_3857x8)] + pmulhrsw m1, [o(pw_m1380x8)] + psubsw m4, m1, m0 ;t18 + paddsw m0, m1 ;t19 + psubsw m5, m2, m3 ;t29 + paddsw m3, m2 ;t28 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m4017, 799 ;t18a, t29a + mova [rsp+gprsize*2+16*21], m5 ;t18a + mova [rsp+gprsize*2+16*22], m0 ;t19 + mova [rsp+gprsize*2+16*31], m3 ;t28 + mova [rsp+gprsize*2+16*32], m4 ;t29a + mova m0, [rsp+gprsize*2+16*23] ;in5 + mova m1, [rsp+gprsize*2+16*24] ;in11 + pmulhrsw m3, m0, [o(pw_3973x8)] + pmulhrsw m0, [o(pw_995x8)] + pmulhrsw m2, m1, [o(pw_3513x8)] + pmulhrsw m1, [o(pw_m2106x8)] + psubsw m4, m0, m1 ;t21 + paddsw m0, m1 ;t20 + psubsw m5, m3, m2 ;t26 + paddsw m3, m2 ;t27 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 3406, 2276 ;t21a, t26a + mova [rsp+gprsize*2+16*23], m0 ;t20 + mova [rsp+gprsize*2+16*24], m5 ;t21a + mova [rsp+gprsize*2+16*29], m4 ;t26a + mova [rsp+gprsize*2+16*30], m3 ;t27 + mova m0, [rsp+gprsize*2+16*25] ;in13 + mova m2, [rsp+gprsize*2+16*26] ;in3 + pmulhrsw m3, m0, [o(pw_3290x8)] + pmulhrsw m0, [o(pw_2440x8)] + pmulhrsw m1, m2, [o(pw_4052x8)] + pmulhrsw m2, [o(pw_m601x8)] + jmp .main2 + +ALIGN function_align +cglobal_label .main + mova m7, [o(pd_2048)] + mova m0, [rsp+gprsize*2+16*19] ;in1 + mova m1, [rsp+gprsize*2+16*20] ;in15 + mova m2, [rsp+gprsize*2+16*33] ;in17 + mova m3, [rsp+gprsize*2+16*34] ;in31 + ITX_MULSUB_2W 0, 3, 4, 5, 7, 201, 4091 ;t16a, t31a + ITX_MULSUB_2W 2, 1, 4, 5, 7, 3035, 2751 ;t17a, t30a + psubsw m4, m0, m2 ;t17 + paddsw m0, m2 ;t16 + psubsw m5, m3, m1 ;t30 + paddsw m3, m1 ;t31 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 799, 4017 ;t17a, t30a + mova [rsp+gprsize*2+16*19], m0 ;t16 + mova [rsp+gprsize*2+16*20], m5 ;t17a + mova [rsp+gprsize*2+16*33], m4 ;t30a + mova [rsp+gprsize*2+16*34], m3 ;t31 + mova m0, [rsp+gprsize*2+16*21] ;in9 + mova m1, [rsp+gprsize*2+16*22] ;in7 + mova m2, [rsp+gprsize*2+16*31] ;in25 + mova m3, [rsp+gprsize*2+16*32] ;in23 + ITX_MULSUB_2W 0, 3, 4, 5, 7, 1751, 3703 ;t18a, t29a + ITX_MULSUB_2W 2, 1, 4, 5, 7, 3857, 1380 ;t19a, t28a + psubsw m4, m2, m0 ;t18 + paddsw m0, m2 ;t19 + psubsw m5, m1, m3 ;t29 + paddsw m3, m1 ;t28 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m4017, 799 ;t18a, t29a + mova [rsp+gprsize*2+16*21], m5 ;t18a + mova [rsp+gprsize*2+16*22], m0 ;t19 + mova [rsp+gprsize*2+16*31], m3 ;t28 + mova [rsp+gprsize*2+16*32], m4 ;t29a + mova m0, [rsp+gprsize*2+16*23] ;in5 + mova m1, [rsp+gprsize*2+16*24] ;in11 + mova m2, [rsp+gprsize*2+16*29] ;in21 + mova m3, [rsp+gprsize*2+16*30] ;in27 + ITX_MULSUB_2W 0, 3, 4, 5, 7, 995, 3973 ;t20a, t27a + ITX_MULSUB_2W 2, 1, 4, 5, 7, 3513, 2106 ;t21a, t26a + psubsw m4, m0, m2 ;t21 + paddsw m0, m2 ;t20 + psubsw m5, m3, m1 ;t26 + paddsw m3, m1 ;t27 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 3406, 2276 ;t21a, t26a + mova [rsp+gprsize*2+16*23], m0 ;t20 + mova [rsp+gprsize*2+16*24], m5 ;t21a + mova [rsp+gprsize*2+16*29], m4 ;t26a + mova [rsp+gprsize*2+16*30], m3 ;t27 + mova m0, [rsp+gprsize*2+16*25] ;in13 + mova m1, [rsp+gprsize*2+16*26] ;in3 + mova m2, [rsp+gprsize*2+16*27] ;in29 + mova m3, [rsp+gprsize*2+16*28] ;in19 + ITX_MULSUB_2W 0, 3, 4, 5, 7, 2440, 3290 ;t22a, t25a + ITX_MULSUB_2W 2, 1, 4, 5, 7, 4052, 601 ;t23a, t24a + +.main2: + psubsw m4, m2, m0 ;t22 + paddsw m0, m2 ;t23 + psubsw m5, m1, m3 ;t25 + paddsw m3, m1 ;t24 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m2276, 3406 ;t22a, t25a + mova m2, [rsp+gprsize*2+16*24] ;t21a + psubsw m1, m5, m2 ;t21 + paddsw m5, m2 ;t22 + mova [rsp+gprsize*2+16*25], m5 ;t22 + mova m2, [rsp+gprsize*2+16*29] ;t26a + psubsw m5, m4, m2 ;t26 + paddsw m4, m2 ;t25 + mova [rsp+gprsize*2+16*28], m4 ;t25 + ITX_MULSUB_2W 5, 1, 2, 4, 7, m3784, 1567 ;t21a, t26a + mova [rsp+gprsize*2+16*24], m5 ;t21a + mova [rsp+gprsize*2+16*29], m1 ;t26a + + mova m1, [rsp+gprsize*2+16*23] ;t20 + mova m5, [rsp+gprsize*2+16*30] ;t27 + psubsw m2, m0, m1 ;t20a + paddsw m0, m1 ;t23a + psubsw m6, m3, m5 ;t27a + paddsw m3, m5 ;t24a + ITX_MULSUB_2W 6, 2, 1, 5, 7, m3784, 1567 ;t20, t27 + mova [rsp+gprsize*2+16*26], m0 ;t23a + mova [rsp+gprsize*2+16*27], m3 ;t24a + mova [rsp+gprsize*2+16*30], m2 ;t27 + + mova m0, [rsp+gprsize*2+16*20] ;t17a + mova m1, [rsp+gprsize*2+16*21] ;t18a + mova m2, [rsp+gprsize*2+16*32] ;t29a + mova m3, [rsp+gprsize*2+16*33] ;t30a + psubsw m4, m0, m1 ;t18 + paddsw m0, m1 ;t17 + psubsw m5, m3, m2 ;t29 + paddsw m3, m2 ;t30 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 1567, 3784 ;t18a, t29a + mova [rsp+gprsize*2+16*20], m0 ;t17 + mova [rsp+gprsize*2+16*21], m5 ;t18a + mova [rsp+gprsize*2+16*32], m4 ;t29a + mova [rsp+gprsize*2+16*33], m3 ;t30 + mova m0, [rsp+gprsize*2+16*19] ;t16 + mova m1, [rsp+gprsize*2+16*22] ;t19 + mova m2, [rsp+gprsize*2+16*31] ;t28 + mova m3, [rsp+gprsize*2+16*34] ;t31 + psubsw m4, m0, m1 ;t19a + paddsw m0, m1 ;t16a + psubsw m5, m3, m2 ;t28a + paddsw m3, m2 ;t31a + ITX_MULSUB_2W 5, 4, 1, 2, 7, 1567, 3784 ;t19, t28 + mova m2, [rsp+gprsize*2+16*15] ;tmp12 + psubsw m1, m5, m6 ;t20a + paddsw m5, m6 ;t19a + psubsw m6, m2, m5 ;out19 + paddsw m2, m5 ;out12 + mova m5, [rsp+gprsize*2+16*30] ;t27 + mova [rsp+gprsize*2+16*22], m6 ;out19 + mova [rsp+gprsize*2+16*15], m2 ;out12 + psubsw m6, m4, m5 ;t27a + paddsw m4, m5 ;t28a + ITX_MULSUB_2W 6, 1, 2, 5, 7, 2896, 2896 ;t20, t27 + mova m2, [rsp+gprsize*2+16*6 ] ;tmp3 + psubsw m5, m2, m4 ;out28 + paddsw m2, m4 ;out3 + mova m4, [rsp+gprsize*2+16*14] ;tmp11 + mova [rsp+gprsize*2+16*31], m5 ;out28 + mova [rsp+gprsize*2+16*6 ], m2 ;out3 + psubsw m5, m4, m6 ;out20 + paddsw m4, m6 ;out11 + mova m2, [rsp+gprsize*2+16*7 ] ;tmp4 + mova [rsp+gprsize*2+16*23], m5 ;out20 + mova [rsp+gprsize*2+16*14], m4 ;out11 + psubsw m5, m2, m1 ;out27 + paddsw m2, m1 ;out4 + mova m1, [rsp+gprsize*2+16*26] ;t23a + mova m4, [rsp+gprsize*2+16*27] ;t24a + mova [rsp+gprsize*2+16*30], m5 ;out27 + mova [rsp+gprsize*2+16*7 ], m2 ;out4 + psubsw m5, m0, m1 ;t23 + paddsw m0, m1 ;t16 + psubsw m2, m3, m4 ;t24 + paddsw m3, m4 ;t31 + ITX_MULSUB_2W 2, 5, 4, 6, 7, 2896, 2896 ;t23a, t24a + mova m6, [rsp+gprsize*2+16*18] ;tmp15 + psubsw m4, m6, m0 ;out16 + paddsw m6, m0 ;out15 + mova m0, [rsp+gprsize*2+16*3 ] ;tmp0 + mova m1, [rsp+gprsize*2+16*11] ;tmp8 + mova [rsp+gprsize*2+16*18], m6 ;out15 + mova [rsp+gprsize*2+16*19], m4 ;out16 + psubsw m6, m0, m3 ;out31 + paddsw m0, m3 ;out0 + psubsw m4, m1, m2 ;out23 + paddsw m1, m2 ;out8 + mova m3, [rsp+gprsize*2+16*10] ;tmp7 + mova [rsp+gprsize*2+16*34], m6 ;out31 + mova [rsp+gprsize*2+16*11], m1 ;out8 + mova [rsp+gprsize*2+16*26], m4 ;out23 + paddsw m6, m3, m5 ;out7 + psubsw m3, m5 ;out24 + mova m1, [rsp+gprsize*2+16*20] ;t17 + mova m5, [rsp+gprsize*2+16*25] ;t22 + mova m2, [rsp+gprsize*2+16*17] ;tmp14 + mova [rsp+gprsize*2+16*27], m3 ;out24 + psubsw m4, m1, m5 ;t22a + paddsw m1, m5 ;t17a + psubsw m3, m2, m1 ;out17 + paddsw m2, m1 ;out14 + mova m5, [rsp+gprsize*2+16*28] ;t25 + mova m1, [rsp+gprsize*2+16*33] ;t30 + mova [rsp+gprsize*2+16*17], m2 ;out14 + mova [rsp+gprsize*2+16*20], m3 ;out17 + psubsw m2, m1, m5 ;t25a + paddsw m1, m5 ;t30a + ITX_MULSUB_2W 2, 4, 3, 5, 7, 2896, 2896 ;t22, t25 + mova m5, [rsp+gprsize*2+16*4 ] ;tmp1 + psubsw m3, m5, m1 ;out30 + paddsw m5, m1 ;out1 + mova m1, [rsp+gprsize*2+16*12] ;tmp9 + mova [rsp+gprsize*2+16*33], m3 ;out30 + mova [rsp+gprsize*2+16*4 ], m5 ;out1 + psubsw m3, m1, m2 ;out22 + paddsw m1, m2 ;out9 + mova m5, [rsp+gprsize*2+16*9 ] ;tmp6 + mova [rsp+gprsize*2+16*25], m3 ;out22 + mova [rsp+gprsize*2+16*12], m1 ;out9 + psubsw m3, m5, m4 ;out25 + paddsw m5, m4 ;out6 + mova m4, [rsp+gprsize*2+16*21] ;t18a + mova m1, [rsp+gprsize*2+16*24] ;t21a + mova m2, [rsp+gprsize*2+16*16] ;tmp13 + mova [rsp+gprsize*2+16*28], m3 ;out25 + mova [rsp+gprsize*2+16*9 ], m5 ;out6 + paddsw m3, m4, m1 ;t18 + psubsw m4, m1 ;t21 + psubsw m5, m2, m3 ;out18 + paddsw m2, m3 ;out13 + mova m1, [rsp+gprsize*2+16*29] ;t26a + mova m3, [rsp+gprsize*2+16*32] ;t29a + mova [rsp+gprsize*2+16*21], m5 ;out18 + mova [rsp+gprsize*2+16*16], m2 ;out13 + psubsw m5, m3, m1 ;t26 + paddsw m3, m1 ;t29 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 2896, 2896 ;t21a, t26a + mova m2, [rsp+gprsize*2+16*5 ] ;tmp2 + psubsw m1, m2, m3 ;out29 + paddsw m2, m3 ;out2 + mova m3, [rsp+gprsize*2+16*13] ;tmp10 + mova [rsp+gprsize*2+16*32], m1 ;out29 + psubsw m7, m3, m5 ;out21 + paddsw m3, m5 ;out10 + mova m5, [rsp+gprsize*2+16*8 ] ;tmp5 + mova [rsp+gprsize*2+16*24], m7 ;out21 + mova [rsp+gprsize*2+16*13], m3 ;out10 + psubsw m1, m5, m4 ;out26 + paddsw m5, m4 ;out5 + mova m7, m6 ;out7 + mova m3, [rsp+gprsize*2+16*6 ] ;out3 + mova m4, [rsp+gprsize*2+16*7 ] ;out4 + mova [rsp+gprsize*2+16*29], m1 ;out26 + mova m6, [rsp+gprsize*2+16*9 ] ;out6 + mova m1, [rsp+gprsize*2+16*4 ] ;out1 + ret + + +cglobal inv_txfm_add_dct_dct_32x8_8bpc, 4, 6, 8, 16*36, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_32x8_internal_8bpc) + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r3d, 8 + lea tx2q, [o(.end)] + +.body: + pmulhrsw m0, m2 + movd m2, [o(pw_2048)] ;intentionally rip-relative + pmulhrsw m0, m1 + pmulhrsw m0, m2 + pshuflw m0, m0, q0000 + punpcklwd m0, m0 + pxor m5, m5 + +.loop: + mova m1, [dstq+16*0] + mova m3, [dstq+16*1] + punpckhbw m2, m1, m5 + punpcklbw m1, m5 + punpckhbw m4, m3, m5 + punpcklbw m3, m5 + paddw m2, m0 + paddw m1, m0 + paddw m4, m0 + paddw m3, m0 + packuswb m1, m2 + packuswb m3, m4 + mova [dstq+16*0], m1 + mova [dstq+16*1], m3 + add dstq, strideq + dec r3d + jg .loop + jmp tx2q + +.end: + RET + + +cglobal idct_32x8_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq+16*0, 64 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+16*2, 64 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+16*1, 32 + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + cmp eobd, 106 + jg .full + call m(idct_8x32_internal_8bpc).main_fast + jmp .pass2 + +.full: + LOAD_8ROWS coeffq+16*17, 32 + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + call m(idct_8x32_internal_8bpc).main + +.pass2: + mova [rsp+gprsize+16*0 ], m7 + lea tx2q, [o(.end)] + jmp m(idct_8x32_internal_8bpc).end1 + +.end: + mova m7, [o(pw_8192)] + lea tx2q, [o(.end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.end1: + lea r3, [dstq+8] + lea tx2q, [o(.end2)] + jmp m(idct_8x8_internal_8bpc).pass2_main + +.end2: + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0 ], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.end3: + mov dstq, r3 + add r3, 8 + lea tx2q, [o(.end4)] + jmp m(idct_8x8_internal_8bpc).pass2_main + +.end4: + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0 ], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.end5)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.end5: + mov dstq, r3 + add r3, 8 + lea tx2q, [o(.end6)] + jmp m(idct_8x8_internal_8bpc).pass2_main + +.end6: + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0 ], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.end7)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.end7: + mov dstq, r3 + lea tx2q, [o(.end8)] + jmp m(idct_8x8_internal_8bpc).pass2_main + +.end8: + ret + + +cglobal inv_txfm_add_identity_identity_8x32_8bpc, 4, 6, 8, 16*4, dst, stride, coeff, eob, tx2 + mov r5d, 4 + mov tx2d, 2 + cmp eobd, 107 + cmovns tx2d, r5d + mov r3d, tx2d +%if ARCH_X86_32 + LEA r5, $$ +%endif + lea tx2q, [o(m(idct_32x8_internal_8bpc).end8)] +.loop: + LOAD_8ROWS coeffq+16*0, 64 + paddsw m6, [o(pw_5)] + mova [rsp+16*1], m6 + mova m6, [o(pw_5)] + REPX {paddsw x, m6}, m0, m1, m2, m3, m4, m5, m7 + call m(idct_8x8_internal_8bpc).pass1_end3 + REPX {psraw x, 3 }, m0, m1, m2, m3, m4, m5, m6, m7 + mova [rsp+16*2], m5 + mova [rsp+16*1], m6 + mova [rsp+16*0], m7 + call m(idct_8x8_internal_8bpc).end3 + lea dstq, [dstq+strideq*2] + pxor m7, m7 + REPX {mova [coeffq+64*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + add coeffq, 16 + dec r3d + jg .loop + RET + +cglobal inv_txfm_add_identity_identity_32x8_8bpc, 4, 6, 8, 16*4, dst, stride, coeff, eob, tx2 + mov r5d, 4 + mov tx2d, 2 + cmp eobd, 107 + cmovns tx2d, r5d + mov r3d, tx2d +%if ARCH_X86_32 + LEA r5, $$ +%endif + +.loop: + LOAD_8ROWS coeffq+16*0, 16 + pmulhrsw m6, [o(pw_4096)] + mova [rsp+16*1], m6 + mova m6, [o(pw_4096)] + REPX {pmulhrsw x, m6}, m0, m1, m2, m3, m4, m5, m7 + lea tx2q, [o(m(idct_32x8_internal_8bpc).end8)] + call m(idct_8x8_internal_8bpc).pass1_end3 + + mov [rsp+16*3], dstq + mova [rsp+16*2], m5 + mova [rsp+16*1], m6 + mova [rsp+16*0], m7 + lea tx2q, [o(m(idct_8x8_internal_8bpc).end4)] + call m(idct_8x8_internal_8bpc).end3 + + add coeffq, 16*8 + mov dstq, [rsp+16*3] + lea dstq, [dstq+8] + dec r3d + jg .loop + jnc .loop + RET + + +cglobal inv_txfm_add_dct_dct_16x32_8bpc, 4, 6, 8, 16*36, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_16x32_internal_8bpc) +.end: + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m1 + mov r2d, 16 + lea tx2q, [o(.end)] + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly + + +cglobal idct_16x32_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + LOAD_8ROWS coeffq+16*1, 128, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*5, 128, 1 + call m(idct_16x8_internal_8bpc).main + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end: + SAVE_8ROWS coeffq+16*33, 64 ;in8~in15 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end1: + mova [coeffq+16*1 ], m0 ;in8 + mova [coeffq+16*5 ], m4 ;in12 + mova [rsp+gprsize+16*13], m2 ;in10 + mova [rsp+gprsize+16*14], m6 ;in14 + mova [rsp+gprsize+16*21], m1 ;in9 + mova [rsp+gprsize+16*24], m3 ;in11 + mova [rsp+gprsize+16*25], m5 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + LOAD_8ROWS coeffq+16*0, 128, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*4, 128, 1 + call m(idct_16x8_internal_8bpc).main + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end2: + SAVE_8ROWS coeffq+16*32, 64 ;in0~in7 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end3: + mova [rsp+gprsize+16*11], m2 ;in2 + mova [rsp+gprsize+16*12], m6 ;in6 + mova [rsp+gprsize+16*19], m1 ;in1 + mova [rsp+gprsize+16*26], m3 ;in3 + mova [rsp+gprsize+16*23], m5 ;in5 + mova [rsp+gprsize+16*22], m7 ;in7 + + cmp eobd, 150 + jg .full + + mova m1, m4 ;in4 + mova m2, [coeffq+16*1 ] ;in8 + mova m3, [coeffq+16*5 ] ;in12 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + mova m0, [rsp+gprsize+16*11] ;in2 + mova m1, [rsp+gprsize+16*12] ;in6 + mova m2, [rsp+gprsize+16*13] ;in10 + mova m3, [rsp+gprsize+16*14] ;in14 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main_fast + jmp .pass2 + +.full: + mova [coeffq+16*0 ], m0 ;in0 + mova [coeffq+16*4 ], m4 ;in4 + + LOAD_8ROWS coeffq+16*2, 128, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*6, 128, 1 + call m(idct_16x8_internal_8bpc).main + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end4: + SAVE_8ROWS coeffq+16*34, 64 ;in16~in23 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end5)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end5: + mova [coeffq+16*2 ], m0 ;in16 + mova [coeffq+16*6 ], m4 ;in20 + mova [rsp+gprsize+16*15], m2 ;in18 + mova [rsp+gprsize+16*16], m6 ;in22 + mova [rsp+gprsize+16*33], m1 ;in17 + mova [rsp+gprsize+16*28], m3 ;in19 + mova [rsp+gprsize+16*29], m5 ;in21 + mova [rsp+gprsize+16*32], m7 ;in23 + + LOAD_8ROWS coeffq+16*3, 128, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+16*7, 128, 1 + call m(idct_16x8_internal_8bpc).main + lea tx2q, [o(.pass1_end6)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end6: + SAVE_8ROWS coeffq+16*35, 64 ;in24~in31 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end7)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end7: + mova [rsp+gprsize+16*17], m2 ;in26 + mova [rsp+gprsize+16*18], m6 ;in30 + mova [rsp+gprsize+16*31], m1 ;in25 + mova [rsp+gprsize+16*30], m3 ;in27 + mova [rsp+gprsize+16*27], m5 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + + mova m6, m0 ;in24 + mova m7, m4 ;in28 + mova m0, [coeffq+16*0 ] ;in0 + mova m1, [coeffq+16*4 ] ;in4 + mova m2, [coeffq+16*1 ] ;in8 + mova m3, [coeffq+16*5 ] ;in12 + mova m4, [coeffq+16*2 ] ;in16 + mova m5, [coeffq+16*6 ] ;in20 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3 , 16 + LOAD_8ROWS rsp+gprsize+16*11, 16 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main + +.pass2: + mov [rsp+gprsize*1+16*35], eobd + lea r3, [dstq+8] + mov [rsp+gprsize*2+16*35], r3 + lea r3, [o(.end)] + jmp m(idct_8x32_internal_8bpc).end + +.end: + mov dstq, [rsp+gprsize*2+16*35] + mov eobd, [rsp+gprsize*1+16*35] + add coeffq, 16*32 + + mova m0, [coeffq+16*4 ] ;in1 + mova m1, [coeffq+16*12] ;in3 + mova m2, [coeffq+16*20] ;in5 + mova m3, [coeffq+16*28] ;in7 + mova m4, [coeffq+16*5 ] ;in9 + mova m5, [coeffq+16*13] ;in11 + mova m6, [coeffq+16*21] ;in13 + mova m7, [coeffq+16*29] ;in15 + + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + mova m0, [coeffq+16*0 ] ;in0 + mova m1, [coeffq+16*16] ;in4 + mova m2, [coeffq+16*1 ] ;in8 + mova m3, [coeffq+16*17] ;in12 + + cmp eobd, 150 + jg .full1 + + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + mova m0, [coeffq+16*8 ] ;in2 + mova m1, [coeffq+16*24] ;in6 + mova m2, [coeffq+16*9 ] ;in10 + mova m3, [coeffq+16*25] ;in14 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main_fast + jmp m(idct_8x32_internal_8bpc).pass2 + +.full1: + mova m4, [coeffq+16*2 ] ;in16 + mova m5, [coeffq+16*18] ;in20 + mova m6, [coeffq+16*3 ] ;in24 + mova m7, [coeffq+16*19] ;in26 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + mova m0, [coeffq+16*8 ] ;in2 + mova m1, [coeffq+16*24] ;in6 + mova m2, [coeffq+16*9 ] ;in10 + mova m3, [coeffq+16*25] ;in14 + mova m4, [coeffq+16*10] ;in18 + mova m5, [coeffq+16*26] ;in22 + mova m6, [coeffq+16*11] ;in26 + mova m7, [coeffq+16*27] ;in30 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + mova m0, [coeffq+16*6 ] ;in17 + mova m1, [coeffq+16*14] ;in19 + mova m2, [coeffq+16*22] ;in21 + mova m3, [coeffq+16*30] ;in23 + mova m4, [coeffq+16*7 ] ;in25 + mova m5, [coeffq+16*15] ;in27 + mova m6, [coeffq+16*23] ;in29 + mova m7, [coeffq+16*31] ;in31 + + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + + call m(idct_8x32_internal_8bpc).main + jmp m(idct_8x32_internal_8bpc).pass2 + + +cglobal inv_txfm_add_dct_dct_32x16_8bpc, 4, 6, 8, 16*36, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + + call m(idct_32x16_internal_8bpc) + call m(idct_8x16_internal_8bpc).pass2 + + add coeffq, 16*16 + lea dstq, [r3+8] + LOAD_8ROWS rsp+16*11, 16 + mova [rsp+16*0], m7 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end + call m(idct_8x16_internal_8bpc).pass2 + + add coeffq, 16*16 + lea dstq, [r3+8] + LOAD_8ROWS rsp+16*19, 16 + mova [rsp+16*0], m7 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end + call m(idct_8x16_internal_8bpc).pass2 + + add coeffq, 16*16 + lea dstq, [r3+8] + LOAD_8ROWS rsp+16*27, 16 + mova [rsp+16*0], m7 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end + call m(idct_8x16_internal_8bpc).pass2 + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m1 + mov r3d, 16 + lea tx2q, [o(m(inv_txfm_add_dct_dct_32x8_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).body + + +cglobal idct_32x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + add coeffq, 16 + lea r3, [o(.pass1_end1)] +.pass1: + LOAD_8ROWS coeffq+16*0, 128, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+16*4, 128, 1 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+16*2, 64, 1 + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + LOAD_8ROWS coeffq+16*34, 64, 1 + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + call m(idct_8x32_internal_8bpc).main + +.pass1_end: + mova [rsp+gprsize+16*0 ], m7 + mov tx2q, r3 + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end1: + SAVE_8ROWS coeffq+16*0, 32 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0 ], m7 + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end2: + SAVE_8ROWS coeffq+16*16, 32 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0 ], m7 + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end3: + SAVE_8ROWS coeffq+16*32, 32 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0 ], m7 + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end4: + SAVE_8ROWS coeffq+16*48, 32 + + sub coeffq, 16 + lea r3, [o(.end)] + jmp .pass1 + +.end: + ret + + +cglobal inv_txfm_add_identity_identity_16x32_8bpc, 4, 6, 8, 16*4, dst, stride, coeff, eob, tx2 + mov r4d, eobd + cmp eobd, 43 ;if (eob > 43) + sbb r3d, r3d ; iteration_count++ + cmp r4d, 150 ;if (eob > 150) + sbb r3d, 0 ; iteration_count++ + cmp r4d, 278 ;if (eob > 278) + sbb r3d, -4 ; iteration_count++ + +%if ARCH_X86_32 + LEA r5, $$ +%endif + lea r4, [dstq+8] + mov [rsp+16*3], r4 + mov [rsp+gprsize+16*3], r3d + mov [rsp+gprsize*2+16*3], coeffq + +.loop: + LOAD_8ROWS coeffq, 64, 1 + mova [rsp+16*1], m6 + pxor m6, m6 + REPX {mova [coeffq+64*x], m6}, 0, 1, 2, 3, 4, 5, 6, 7 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end3 + mova [rsp+16*0], m2 + mova [rsp+16*1], m3 + mova [rsp+16*2], m4 + mova m3, [o(pw_1697x16)] + mova m4, [o(pw_16384)] + REPX {IDTX16 x, 2, 3, 4}, 5, 6, 7, 0, 1 + mova m2, [o(pw_8192)] + REPX {pmulhrsw x, m2}, m5, m6, m7, m0, m1 + mova m2, [rsp+16*0] + mova [rsp+16*0], m7 + IDTX16 2, 7, 3, 4 + mova m7, [rsp+16*2] + mova [rsp+16*2], m5 + IDTX16 7, 5, 3, 4 + mova m5, [rsp+16*1] + mova [rsp+16*1], m6 + pmulhrsw m3, m5 + pmulhrsw m3, m4 + psrlw m4, 1 ; pw_8192 + paddsw m3, m5 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + pmulhrsw m4, m7 + call m(idct_8x8_internal_8bpc).end3 + lea dstq, [dstq+strideq*2] + add coeffq, 16 + dec r3d + jg .loop + mov coeffq, [rsp+gprsize*2+16*3] + add coeffq, 64*8 + mov r3d, [rsp+gprsize+16*3] + xor dstq, dstq + mov [rsp+gprsize+16*3], dstq + mov dstq, [rsp+16*3] + test r3d, r3d + jnz .loop + RET + + +cglobal inv_txfm_add_identity_identity_32x16_8bpc, 4, 6, 8, 16*4, dst, stride, coeff, eob, tx2 + mov r4d, 12 ;0100b + mov r5d, 136 ;1000 1000b + cmp eobd, 44 ;if (eob > 43) + cmovns r4d, r5d ; iteration_count+2 + cmp eobd, 151 ;if (eob > 150) + mov r3d, 34952 ;1000 1000 1000 1000b + cmovs r3d, r4d ; iteration_count += 4 + +%if ARCH_X86_32 + LEA r5, $$ +%endif + lea r4, [dstq+8] + mov [rsp+16*3], r4 + +.loop: + LOAD_8ROWS coeffq, 32, 1 + REPX {paddsw x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + mova [rsp+16*1], m6 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end3 + mova [rsp+16*1], m5 + mova [rsp+16*2], m6 + mova m6, [o(pw_1697x16)] + REPX {IDTX16 x, 5, 6}, 7, 0, 1, 2, 3, 4 + pmulhrsw m7, [o(pw_2048)] + mova m5, [rsp+16*1] + mova [rsp+16*0], m7 + IDTX16 5, 7, 6 + mova m7, [rsp+16*2] + IDTX16 7, 6, 6 + mova m6, [o(pw_2048)] + REPX {pmulhrsw x, m6}, m0, m1, m2, m3, m4, m5, m7 + mova [rsp+16*2], m5 + mova [rsp+16*1], m7 + call m(idct_8x8_internal_8bpc).end3 + lea dstq, [dstq+strideq*2] + pxor m7, m7 + REPX {mova [coeffq+32*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + +.loop_end: + add coeffq, 16 + shr r3d, 2 + jz .ret + test r3d, 2 + jnz .loop + mov r4d, r3d + and r4d, 1 + lea coeffq, [coeffq+r4*8+32*7] + mov dstq, [rsp+16*3] + lea r4, [dstq+8] + mov [rsp+16*3], r4 + jmp .loop + +.ret: + RET + + +cglobal inv_txfm_add_dct_dct_32x32_8bpc, 4, 6, 8, 16*36, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + + call m(idct_32x32_internal_8bpc) + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r3d, 32 + lea tx2q, [o(m(inv_txfm_add_dct_dct_32x8_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).body + + +cglobal idct_32x32_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r4d, 2 + sub eobd, 136 + mov [rsp+gprsize*1+16*35], eobd + mov r3d, 4 + cmovs r3d, r4d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + mov [rsp+gprsize*2+16*35], coeffq + +.pass1_loop: + LOAD_8ROWS coeffq+64*1, 64*2 + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + mov tx2d, [rsp+gprsize*1+16*35] + test tx2d, tx2d + jl .fast + +.full: + LOAD_8ROWS coeffq+64*0, 64*4 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+64*2, 64*4 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+64*17, 64*2 + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + + call m(idct_8x32_internal_8bpc).main + jmp .pass1_end + +.fast: + mova m0, [coeffq+256*0] + mova m1, [coeffq+256*1] + mova m2, [coeffq+256*2] + mova m3, [coeffq+256*3] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + + SAVE_7ROWS rsp+gprsize+16*3, 16 + mova m0, [coeffq+128*1] + mova m1, [coeffq+128*3] + mova m2, [coeffq+128*5] + mova m3, [coeffq+128*7] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main_fast + +.pass1_end: + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end3: + SAVE_8ROWS coeffq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end4: + SAVE_8ROWS coeffq+64*24, 64 + + add coeffq, 16 + dec r3d + jg .pass1_loop + + +.pass2: + mov coeffq, [rsp+gprsize*2+16*35] + mov r3d, 4 + lea tx2q, [o(.pass2_end)] + +.pass2_loop: + mov [rsp+gprsize*3+16*35], r3d + lea r3, [dstq+8] + mov [rsp+gprsize*2+16*35], r3 + + mova m0, [coeffq+16*4 ] + mova m1, [coeffq+16*12] + mova m2, [coeffq+16*20] + mova m3, [coeffq+16*28] + mova m4, [coeffq+16*5 ] + mova m5, [coeffq+16*13] + mova m6, [coeffq+16*21] + mova m7, [coeffq+16*29] + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + mov eobd, [rsp+gprsize*1+16*35] + test eobd, eobd + jl .fast1 + +.full1: + mova m0, [coeffq+16*0 ] + mova m1, [coeffq+16*16] + mova m2, [coeffq+16*1 ] + mova m3, [coeffq+16*17] + mova m4, [coeffq+16*2 ] + mova m5, [coeffq+16*18] + mova m6, [coeffq+16*3 ] + mova m7, [coeffq+16*19] + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + mova m0, [coeffq+16*8 ] + mova m1, [coeffq+16*24] + mova m2, [coeffq+16*9 ] + mova m3, [coeffq+16*25] + mova m4, [coeffq+16*10] + mova m5, [coeffq+16*26] + mova m6, [coeffq+16*11] + mova m7, [coeffq+16*27] + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + mova m0, [coeffq+16*6 ] + mova m1, [coeffq+16*14] + mova m2, [coeffq+16*22] + mova m3, [coeffq+16*30] + mova m4, [coeffq+16*7 ] + mova m5, [coeffq+16*15] + mova m6, [coeffq+16*23] + mova m7, [coeffq+16*31] + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + + call m(idct_8x32_internal_8bpc).main + jmp tx2q + +.fast1: + mova m0, [coeffq+16*0 ] + mova m1, [coeffq+16*16] + mova m2, [coeffq+16*1 ] + mova m3, [coeffq+16*17] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + mova m0, [coeffq+16*8 ] + mova m1, [coeffq+16*24] + mova m2, [coeffq+16*9 ] + mova m3, [coeffq+16*25] + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main_fast + jmp tx2q + +.pass2_end: + lea r3, [o(.pass2_end1)] + jmp m(idct_8x32_internal_8bpc).end + +.pass2_end1: + lea tx2q, [o(.pass2_end)] + add coeffq, 16*32 + mov dstq, [rsp+gprsize*2+16*35] + mov r3d, [rsp+gprsize*3+16*35] + dec r3d + jg .pass2_loop + + ret + + +cglobal inv_txfm_add_identity_identity_32x32_8bpc, 4, 6, 8, 16*5, dst, stride, coeff, eob, tx2 + mov r4d, 2 + cmp eobd, 136 + mov r3d, 4 + cmovs r3d, r4d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + lea r4, [dstq+8] + mov [rsp+gprsize*0+16*3], r4 + mov [rsp+gprsize*1+16*3], r3d + mov [rsp+gprsize*2+16*3], r3d + mov [rsp+gprsize*3+16*3], coeffq + +.loop: + LOAD_8ROWS coeffq, 64 + mova [rsp+16*1], m6 + lea tx2q, [o(m(idct_32x16_internal_8bpc).end)] + call m(idct_8x8_internal_8bpc).pass1_end3 + pmulhrsw m7, [o(pw_8192)] + mova [rsp+16*0], m7 + mova m7, [o(pw_8192)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + mova [rsp+16*1], m6 + mova [rsp+16*2], m5 + call m(idct_8x8_internal_8bpc).end3 + lea dstq, [dstq+strideq*2] + + pxor m7, m7 + REPX {mova [coeffq+64*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7 + + add coeffq, 16 + dec r3d + jg .loop + + mov r4d, [rsp+gprsize*2+16*3] + dec r4d + jle .ret + + mov dstq, [rsp+gprsize*0+16*3] + mov coeffq, [rsp+gprsize*3+16*3] + mov [rsp+gprsize*2+16*3], r4 + lea r3, [dstq+8] + add coeffq, 64*8 + mov [rsp+gprsize*0+16*3], r3 + mov r3d, [rsp+gprsize*1+16*3] + mov [rsp+gprsize*3+16*3], coeffq + jmp .loop + +.ret: + RET + + +cglobal inv_txfm_add_dct_dct_16x64_8bpc, 4, 6, 8, 16*68, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_16x64_internal_8bpc) +.end: + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r2d, 32 + lea tx2q, [o(.end)] + jmp m(inv_txfm_add_dct_dct_16x4_8bpc).dconly + + +cglobal idct_16x64_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r4d, 2 + sub eobd, 151 + mov [rsp+gprsize*1+16*67], eobd + mov r3d, 4 + cmovs r3d, r4d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + mov [rsp+gprsize*2+16*67], coeffq + +.pass1_loop: + LOAD_8ROWS coeffq+64*0, 64*2 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+64*1, 64*2 + call m(idct_16x8_internal_8bpc).main + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+64*0, 64 + + add coeffq, 16 + dec r3d + jg .pass1_loop + + mov coeffq, [rsp+gprsize*2+16*67] + mov r3d, 2 + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(.end1)] + +.pass2_loop: + mov [rsp+gprsize*3+16*67], r3d + mov eobd, [rsp+gprsize*1+16*67] + + mova m0, [coeffq+16*4 ] ;in1 + mova m1, [coeffq+16*12] ;in3 + mova m2, [coeffq+16*20] ;in5 + mova m3, [coeffq+16*28] ;in7 + mova m4, [coeffq+16*5 ] ;in9 + mova m5, [coeffq+16*13] ;in11 + mova m6, [coeffq+16*21] ;in13 + mova m7, [coeffq+16*29] ;in15 + mova [rsp+gprsize+16*35], m0 ;in1 + mova [rsp+gprsize+16*49], m1 ;in3 + mova [rsp+gprsize+16*43], m2 ;in5 + mova [rsp+gprsize+16*41], m3 ;in7 + mova [rsp+gprsize+16*39], m4 ;in9 + mova [rsp+gprsize+16*45], m5 ;in11 + mova [rsp+gprsize+16*47], m6 ;in13 + mova [rsp+gprsize+16*37], m7 ;in15 + + pxor m4, m4 + mova m0, [coeffq+16*0] + mova m1, [coeffq+16*1] + + test eobd, eobd + jl .fast + +.full: + mova m2, [coeffq+16*2] + mova m3, [coeffq+16*3] + + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + pxor m4, m4 + mova m0, [coeffq+16*16] + mova m1, [coeffq+16*17] + mova m2, [coeffq+16*18] + mova m3, [coeffq+16*19] + + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + mova m0, [coeffq+16*8 ] + mova m1, [coeffq+16*24] + mova m2, [coeffq+16*9 ] + mova m3, [coeffq+16*25] + mova m4, [coeffq+16*10] + mova m5, [coeffq+16*26] + mova m6, [coeffq+16*11] + mova m7, [coeffq+16*27] + mova [rsp+gprsize+16*19], m0 + mova [rsp+gprsize+16*26], m1 + mova [rsp+gprsize+16*23], m2 + mova [rsp+gprsize+16*22], m3 + mova [rsp+gprsize+16*21], m4 + mova [rsp+gprsize+16*24], m5 + mova [rsp+gprsize+16*25], m6 + mova [rsp+gprsize+16*20], m7 + + call m(idct_8x32_internal_8bpc).main_fast + SAVE_8ROWS rsp+gprsize+16*3, 16 + + mova m0, [coeffq+16*6 ] ;in17 + mova m1, [coeffq+16*14] ;in19 + mova m2, [coeffq+16*22] ;in21 + mova m3, [coeffq+16*30] ;in23 + mova m4, [coeffq+16*7 ] ;in25 + mova m5, [coeffq+16*15] ;in27 + mova m6, [coeffq+16*23] ;in29 + mova m7, [coeffq+16*31] ;in31 + mova [rsp+gprsize+16*63], m0 ;in17 + mova [rsp+gprsize+16*53], m1 ;in19 + mova [rsp+gprsize+16*55], m2 ;in21 + mova [rsp+gprsize+16*61], m3 ;in23 + mova [rsp+gprsize+16*59], m4 ;in25 + mova [rsp+gprsize+16*57], m5 ;in27 + mova [rsp+gprsize+16*51], m6 ;in29 + mova [rsp+gprsize+16*65], m7 ;in31 + + call .main + jmp .end + +.fast: + REPX {mova x, m4}, m2, m3, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + pxor m4, m4 + mova m0, [coeffq+16*16] + mova m1, [coeffq+16*17] + + REPX {mova x, m4}, m2, m3, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + mova m0, [coeffq+16*8 ] + mova m1, [coeffq+16*24] + mova m2, [coeffq+16*9 ] + mova m3, [coeffq+16*25] + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + + call m(idct_8x32_internal_8bpc).main_veryfast + SAVE_8ROWS rsp+gprsize+16*3, 16 + + call .main_fast + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mov r3, r4 + jmp m(idct_8x32_internal_8bpc).end2 + +.end1: + LOAD_8ROWS rsp+gprsize+16*35, 16 + lea dstq, [dstq+strideq*2] + lea r3, [rsp+16*32+gprsize] + call .write + mov dstq, [rsp+gprsize*2+16*67] + mov r3d, [rsp+gprsize*3+16*67] + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(.end1)] + + dec r3d + jg .pass2_loop + ret +.write: + mova [r3+16*0], m7 + mov r4, -16*32 + pxor m7, m7 + sub coeffq, r4 +.zero_loop: + mova [coeffq+r4+16*0], m7 + mova [coeffq+r4+16*1], m7 + add r4, 16*2 + jl .zero_loop + call .write_main2 + LOAD_8ROWS r3+16*11, 16 + call .write_main + LOAD_8ROWS r3+16*19, 16 + call .write_main + LOAD_8ROWS r3+16*27, 16 +.write_main: + mova [r3+16*0], m7 +.write_main2: + mova m7, [o(pw_2048)] + REPX {pmulhrsw x, m7}, m0, m1, m2, m3, m4, m5, m6 + pmulhrsw m7, [r3+16*0] + mova [r3+16*2], m5 + mova [r3+16*1], m6 + mova [r3+16*0], m7 + WRITE_8X4 0, 1, 2, 3, 5, 6, 7 + lea dstq, [dstq+strideq*2] + WRITE_8X4 4, [r3+16*2], [r3+16*1], [r3+16*0], 5, 6, 7 + lea dstq, [dstq+strideq*2] + ret + + +ALIGN function_align +cglobal_label .main_fast + mova m0, [rsp+gprsize*2+16*35] ;in1 + pmulhrsw m3, m0, [o(pw_4095x8)] ;t62,t63 + pmulhrsw m0, [o(pw_101x8)] ;t32,t33 + mova m7, [o(pd_2048)] + mova [rsp+gprsize*2+16*35], m0 ;t32 + mova [rsp+gprsize*2+16*66], m3 ;t63 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 401, 4076 ;t33a, t62a + mova [rsp+gprsize*2+16*36], m3 ;t33a + mova [rsp+gprsize*2+16*65], m0 ;t62a + + mova m1, [rsp+gprsize*2+16*37] ;in15 + pmulhrsw m2, m1, [o(pw_3822x8)] ;t60,t61 + pmulhrsw m1, [o(pw_m1474x8)] ;t34,t35 + mova [rsp+gprsize*2+16*38], m1 ;t35 + mova [rsp+gprsize*2+16*63], m2 ;t60 + ITX_MULSUB_2W 2, 1, 0, 3, 7, m4076, 401 ;t34a, t61a + mova [rsp+gprsize*2+16*37], m2 ;t34a + mova [rsp+gprsize*2+16*64], m1 ;t61a + + mova m0, [rsp+gprsize*2+16*39] ;in9 + pmulhrsw m3, m0, [o(pw_3996x8)] ;t58,t59 + pmulhrsw m0, [o(pw_897x8)] ;t36,t37 + mova [rsp+gprsize*2+16*39], m0 ;t36 + mova [rsp+gprsize*2+16*62], m3 ;t59 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 3166, 2598 ;t37a, t58a + mova [rsp+gprsize*2+16*40], m3 ;t37a + mova [rsp+gprsize*2+16*61], m0 ;t58a + + mova m1, [rsp+gprsize*2+16*41] ;in7 + pmulhrsw m2, m1, [o(pw_4036x8)] ;t56,t57 + pmulhrsw m1, [o(pw_m700x8)] ;t38,t39 + mova [rsp+gprsize*2+16*42], m1 ;t39 + mova [rsp+gprsize*2+16*59], m2 ;t56 + ITX_MULSUB_2W 2, 1, 0, 3, 7, m2598, 3166 ;t38a, t57a + mova [rsp+gprsize*2+16*41], m2 ;t38a + mova [rsp+gprsize*2+16*60], m1 ;t57a + + mova m0, [rsp+gprsize*2+16*43] ;in5 + pmulhrsw m3, m0, [o(pw_4065x8)] ;t54,t55 + pmulhrsw m0, [o(pw_501x8)] ;t40,t41 + mova [rsp+gprsize*2+16*43], m0 ;t40 + mova [rsp+gprsize*2+16*58], m3 ;t55 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 1931, 3612 ;t41a, t54a + mova [rsp+gprsize*2+16*44], m3 ;t41a + mova [rsp+gprsize*2+16*57], m0 ;t54a + + mova m1, [rsp+gprsize*2+16*45] ;in11 + pmulhrsw m2, m1, [o(pw_3948x8)] ;t52,t53 + pmulhrsw m1, [o(pw_m1092x8)] ;t42,t43 + mova [rsp+gprsize*2+16*46], m1 ;t43 + mova [rsp+gprsize*2+16*55], m2 ;t52 + ITX_MULSUB_2W 2, 1, 0, 3, 7, m3612, 1931 ;t42a, t53a + mova [rsp+gprsize*2+16*45], m2 ;t42a + mova [rsp+gprsize*2+16*56], m1 ;t53a + + mova m0, [rsp+gprsize*2+16*47] ;in13 + pmulhrsw m3, m0, [o(pw_3889x8)] ;t50,t51 + pmulhrsw m0, [o(pw_1285x8)] ;t44,t45 + mova m6, m0 + mova [rsp+gprsize*2+16*54], m3 ;t51 + ITX_MULSUB_2W 3, 0, 1, 2, 7, 3920, 1189 ;t45a, t50a + mova [rsp+gprsize*2+16*48], m3 ;t45a + mova [rsp+gprsize*2+16*53], m0 ;t50a + + mova m0, [rsp+gprsize*2+16*49] ;in3 + pmulhrsw m3, m0, [o(pw_4085x8)] ;t48,t49 + pmulhrsw m0, [o(pw_m301x8)] ;t46,t47 + mova m4, m3 + mova m5, m0 + + jmp .main2 + +ALIGN function_align +cglobal_label .main + mova m0, [rsp+gprsize*2+16*35] ;in1 + mova m1, [rsp+gprsize*2+16*65] ;in31 + pmulhrsw m3, m0, [o(pw_4095x8)] ;t63a + pmulhrsw m0, [o(pw_101x8)] ;t32a + pmulhrsw m2, m1, [o(pw_2967x8)] ;t62a + pmulhrsw m1, [o(pw_m2824x8)] ;t33a + mova m7, [o(pd_2048)] + psubsw m4, m0, m1 ;t33 + paddsw m0, m1 ;t32 + psubsw m5, m3, m2 ;t62 + paddsw m3, m2 ;t63 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 401, 4076 ;t33a, t62a + mova [rsp+gprsize*2+16*35], m0 ;t32 + mova [rsp+gprsize*2+16*36], m5 ;t33a + mova [rsp+gprsize*2+16*65], m4 ;t62a + mova [rsp+gprsize*2+16*66], m3 ;t63 + + mova m0, [rsp+gprsize*2+16*63] ;in17 + mova m1, [rsp+gprsize*2+16*37] ;in15 + pmulhrsw m3, m0, [o(pw_3745x8)] ;t61a + pmulhrsw m0, [o(pw_1660x8)] ;t34a + pmulhrsw m2, m1, [o(pw_3822x8)] ;t60a + pmulhrsw m1, [o(pw_m1474x8)] ;t35a + psubsw m4, m1, m0 ;t34 + paddsw m0, m1 ;t35 + psubsw m5, m2, m3 ;t61 + paddsw m3, m2 ;t60 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m4076, 401 ;t34a, t61a + mova [rsp+gprsize*2+16*37], m5 ;t34a + mova [rsp+gprsize*2+16*38], m0 ;t35 + mova [rsp+gprsize*2+16*63], m3 ;t60 + mova [rsp+gprsize*2+16*64], m4 ;t61a + + mova m0, [rsp+gprsize*2+16*39] ;in9 + mova m1, [rsp+gprsize*2+16*61] ;in23 + pmulhrsw m3, m0, [o(pw_3996x8)] ;t59a + pmulhrsw m0, [o(pw_897x8)] ;t36a + pmulhrsw m2, m1, [o(pw_3461x8)] ;t58a + pmulhrsw m1, [o(pw_m2191x8)] ;t37a + psubsw m4, m0, m1 ;t37 + paddsw m0, m1 ;t36 + psubsw m5, m3, m2 ;t58 + paddsw m3, m2 ;t59 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 3166, 2598 ;t37a, t58a + mova [rsp+gprsize*2+16*39], m0 ;t36 + mova [rsp+gprsize*2+16*40], m5 ;t37a + mova [rsp+gprsize*2+16*61], m4 ;t58a + mova [rsp+gprsize*2+16*62], m3 ;t59 + + mova m0, [rsp+gprsize*2+16*59] ;in25 + mova m1, [rsp+gprsize*2+16*41] ;in7 + pmulhrsw m3, m0, [o(pw_3349x8)] ;t57a + pmulhrsw m0, [o(pw_2359x8)] ;t38a + pmulhrsw m2, m1, [o(pw_4036x8)] ;t56a + pmulhrsw m1, [o(pw_m700x8)] ;t39a + psubsw m4, m1, m0 ;t38 + paddsw m0, m1 ;t39 + psubsw m5, m2, m3 ;t57 + paddsw m3, m2 ;t56 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m2598, 3166 ;t38a, t57a + mova [rsp+gprsize*2+16*41], m5 ;t38a + mova [rsp+gprsize*2+16*42], m0 ;t39 + mova [rsp+gprsize*2+16*59], m3 ;t56 + mova [rsp+gprsize*2+16*60], m4 ;t57a + + mova m0, [rsp+gprsize*2+16*43] ;in5 + mova m1, [rsp+gprsize*2+16*57] ;in27 + pmulhrsw m3, m0, [o(pw_4065x8)] ;t55a + pmulhrsw m0, [o(pw_501x8)] ;t40a + pmulhrsw m2, m1, [o(pw_3229x8)] ;t54a + pmulhrsw m1, [o(pw_m2520x8)] ;t41a + psubsw m4, m0, m1 ;t41 + paddsw m0, m1 ;t40 + psubsw m5, m3, m2 ;t54 + paddsw m3, m2 ;t55 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 1931, 3612 ;t41a, t54a + mova [rsp+gprsize*2+16*43], m0 ;t40 + mova [rsp+gprsize*2+16*44], m5 ;t41a + mova [rsp+gprsize*2+16*57], m4 ;t54a + mova [rsp+gprsize*2+16*58], m3 ;t55 + + mova m0, [rsp+gprsize*2+16*55] ;in21 + mova m1, [rsp+gprsize*2+16*45] ;in11 + pmulhrsw m3, m0, [o(pw_3564x8)] ;t53a + pmulhrsw m0, [o(pw_2019x8)] ;t42a + pmulhrsw m2, m1, [o(pw_3948x8)] ;t52a + pmulhrsw m1, [o(pw_m1092x8)] ;t43a + psubsw m4, m1, m0 ;t42 + paddsw m0, m1 ;t43 + psubsw m5, m2, m3 ;t53 + paddsw m3, m2 ;t52 + ITX_MULSUB_2W 5, 4, 1, 2, 7, m3612, 1931 ;t42a, t53a + mova [rsp+gprsize*2+16*45], m5 ;t42a + mova [rsp+gprsize*2+16*46], m0 ;t43 + mova [rsp+gprsize*2+16*55], m3 ;t52 + mova [rsp+gprsize*2+16*56], m4 ;t53a + + mova m0, [rsp+gprsize*2+16*47] ;in13 + mova m1, [rsp+gprsize*2+16*53] ;in19 + pmulhrsw m3, m0, [o(pw_3889x8)] ;t51a + pmulhrsw m0, [o(pw_1285x8)] ;t44a + pmulhrsw m2, m1, [o(pw_3659x8)] ;t50a + pmulhrsw m1, [o(pw_m1842x8)] ;t45a + psubsw m4, m0, m1 ;t45 + paddsw m0, m1 ;t44 + psubsw m5, m3, m2 ;t50 + paddsw m3, m2 ;t51 + ITX_MULSUB_2W 5, 4, 1, 2, 7, 3920, 1189 ;t45a, t50a + mova m6, m0 + mova [rsp+gprsize*2+16*48], m5 ;t45a + mova [rsp+gprsize*2+16*53], m4 ;t50a + mova [rsp+gprsize*2+16*54], m3 ;t51 + + mova m0, [rsp+gprsize*2+16*51] ;in29 + mova m1, [rsp+gprsize*2+16*49] ;in3 + pmulhrsw m3, m0, [o(pw_3102x8)] ;t49a + pmulhrsw m0, [o(pw_2675x8)] ;t46a + pmulhrsw m2, m1, [o(pw_4085x8)] ;t48a + pmulhrsw m1, [o(pw_m301x8)] ;t47a + psubsw m5, m1, m0 ;t46 + paddsw m0, m1 ;t47 + psubsw m4, m2, m3 ;t49 + paddsw m3, m2 ;t48 + +ALIGN function_align +.main2: + ITX_MULSUB_2W 4, 5, 1, 2, 7, m1189, 3920 ;t46a, t49a + mova m1, [rsp+gprsize*2+16*54] ;t51 + psubsw m2, m0, m6 ;t44a + paddsw m0, m6 ;t47a + psubsw m6, m3, m1 ;t51a + paddsw m3, m1 ;t48a + mova [rsp+gprsize*2+16*50], m0 ;t47a + mova [rsp+gprsize*2+16*51], m3 ;t48a + ITX_MULSUB_2W 6, 2, 0, 3, 7, m2276, 3406 ;t44, t51 + mova [rsp+gprsize*2+16*47], m6 ;t44 + mova [rsp+gprsize*2+16*54], m2 ;t51 + + mova m0, [rsp+gprsize*2+16*48] ;t45a + mova m3, [rsp+gprsize*2+16*53] ;t50a + psubsw m2, m4, m0 ;t45 + paddsw m4, m0 ;t46 + psubsw m6, m5, m3 ;t50 + paddsw m5, m3 ;t49 + ITX_MULSUB_2W 6, 2, 0, 3, 7, m2276, 3406 ;t45a, t50a + mova [rsp+gprsize*2+16*48], m6 ;t45a + mova [rsp+gprsize*2+16*49], m4 ;t46 + mova [rsp+gprsize*2+16*52], m5 ;t49 + mova [rsp+gprsize*2+16*53], m2 ;t50a + + mova m0, [rsp+gprsize*2+16*43] ;t40 + mova m2, [rsp+gprsize*2+16*46] ;t43 + mova m3, [rsp+gprsize*2+16*55] ;t52 + mova m1, [rsp+gprsize*2+16*58] ;t55 + psubsw m4, m0, m2 ;t43a + paddsw m0, m2 ;t40a + psubsw m5, m1, m3 ;t52a + paddsw m1, m3 ;t55a + ITX_MULSUB_2W 5, 4, 2, 3, 7, 3406, 2276 ;t43, t52 + mova [rsp+gprsize*2+16*43], m0 ;t40a + mova [rsp+gprsize*2+16*46], m5 ;t43 + mova [rsp+gprsize*2+16*55], m4 ;t52 + mova [rsp+gprsize*2+16*58], m1 ;t55a + + mova m0, [rsp+gprsize*2+16*44] ;t41a + mova m2, [rsp+gprsize*2+16*45] ;t42a + mova m3, [rsp+gprsize*2+16*56] ;t53a + mova m1, [rsp+gprsize*2+16*57] ;t54a + psubsw m4, m0, m2 ;t42 + paddsw m0, m2 ;t41 + psubsw m5, m1, m3 ;t53 + paddsw m1, m3 ;t54 + ITX_MULSUB_2W 5, 4, 2, 3, 7, 3406, 2276 ;t42a, t53a + mova [rsp+gprsize*2+16*44], m0 ;t41 + mova [rsp+gprsize*2+16*45], m5 ;t42a + mova [rsp+gprsize*2+16*56], m4 ;t53a + mova [rsp+gprsize*2+16*57], m1 ;t54 + + mova m0, [rsp+gprsize*2+16*41] ;t38a + mova m2, [rsp+gprsize*2+16*40] ;t37a + mova m3, [rsp+gprsize*2+16*61] ;t58a + mova m1, [rsp+gprsize*2+16*60] ;t57a + psubsw m4, m0, m2 ;t37 + paddsw m0, m2 ;t38 + psubsw m5, m1, m3 ;t58 + paddsw m1, m3 ;t57 + ITX_MULSUB_2W 5, 4, 2, 3, 7, m4017, 799 ;t37a, t58a + mova [rsp+gprsize*2+16*41], m0 ;t38 + mova [rsp+gprsize*2+16*40], m5 ;t37a + mova [rsp+gprsize*2+16*61], m4 ;t58a + mova [rsp+gprsize*2+16*60], m1 ;t57 + + mova m0, [rsp+gprsize*2+16*42] ;t39 + mova m2, [rsp+gprsize*2+16*39] ;t36 + mova m3, [rsp+gprsize*2+16*62] ;t59 + mova m1, [rsp+gprsize*2+16*59] ;t56 + psubsw m4, m0, m2 ;t36a + paddsw m0, m2 ;t39a + psubsw m5, m1, m3 ;t59a + paddsw m1, m3 ;t56a + ITX_MULSUB_2W 5, 4, 2, 3, 7, m4017, 799 ;t36, t59 + mova [rsp+gprsize*2+16*42], m0 ;t39a + mova [rsp+gprsize*2+16*39], m5 ;t36 + mova [rsp+gprsize*2+16*62], m4 ;t59 + mova [rsp+gprsize*2+16*59], m1 ;t56a + + mova m0, [rsp+gprsize*2+16*35] ;t32 + mova m2, [rsp+gprsize*2+16*38] ;t35 + mova m3, [rsp+gprsize*2+16*63] ;t60 + mova m1, [rsp+gprsize*2+16*66] ;t63 + psubsw m4, m0, m2 ;t35a + paddsw m0, m2 ;t32a + psubsw m5, m1, m3 ;t60a + paddsw m1, m3 ;t63a + ITX_MULSUB_2W 5, 4, 2, 3, 7, 799, 4017 ;t35, t60 + mova [rsp+gprsize*2+16*35], m0 ;t32a + mova [rsp+gprsize*2+16*38], m5 ;t35 + mova [rsp+gprsize*2+16*63], m4 ;t60 + mova [rsp+gprsize*2+16*66], m1 ;t63a + + mova m0, [rsp+gprsize*2+16*36] ;t33a + mova m2, [rsp+gprsize*2+16*37] ;t34a + mova m3, [rsp+gprsize*2+16*64] ;t61a + mova m1, [rsp+gprsize*2+16*65] ;t62a + psubsw m4, m0, m2 ;t34 + paddsw m0, m2 ;t33 + psubsw m5, m1, m3 ;t61 + paddsw m1, m3 ;t62 + ITX_MULSUB_2W 5, 4, 2, 3, 7, 799, 4017 ;t34a, t61a + + mova m2, [rsp+gprsize*2+16*41] ;t38 + mova m3, [rsp+gprsize*2+16*60] ;t57 + psubsw m6, m0, m2 ;t38a + paddsw m0, m2 ;t33a + psubsw m2, m1, m3 ;t57a + paddsw m1, m3 ;t62a + mova [rsp+gprsize*2+16*36], m0 ;t33a + mova [rsp+gprsize*2+16*65], m1 ;t62a + ITX_MULSUB_2W 2, 6, 0, 3, 7, 1567, 3784 ;t38, t57 + mova [rsp+gprsize*2+16*41], m2 ;t38 + mova [rsp+gprsize*2+16*60], m6 ;t57 + + mova m2, [rsp+gprsize*2+16*40] ;t37 + mova m3, [rsp+gprsize*2+16*61] ;t58 + psubsw m0, m5, m2 ;t37 + paddsw m5, m2 ;t34 + psubsw m1, m4, m3 ;t58 + paddsw m4, m3 ;t61 + ITX_MULSUB_2W 1, 0, 2, 3, 7, 1567, 3784 ;t37a, t58a + mova [rsp+gprsize*2+16*37], m5 ;t34 + mova [rsp+gprsize*2+16*64], m4 ;t61 + mova [rsp+gprsize*2+16*40], m1 ;t37a + mova [rsp+gprsize*2+16*61], m0 ;t58a + + mova m0, [rsp+gprsize*2+16*38] ;t35 + mova m2, [rsp+gprsize*2+16*39] ;t36 + mova m3, [rsp+gprsize*2+16*62] ;t59 + mova m1, [rsp+gprsize*2+16*63] ;t60 + psubsw m4, m0, m2 ;t36a + paddsw m0, m2 ;t35a + psubsw m5, m1, m3 ;t59a + paddsw m1, m3 ;t60a + ITX_MULSUB_2W 5, 4, 2, 3, 7, 1567, 3784 ;t36, t59 + mova [rsp+gprsize*2+16*38], m0 ;t35a + mova [rsp+gprsize*2+16*39], m5 ;t36 + mova [rsp+gprsize*2+16*62], m4 ;t59 + mova [rsp+gprsize*2+16*63], m1 ;t60a + + mova m0, [rsp+gprsize*2+16*35] ;t32a + mova m2, [rsp+gprsize*2+16*42] ;t39a + mova m3, [rsp+gprsize*2+16*59] ;t56a + mova m1, [rsp+gprsize*2+16*66] ;t63a + psubsw m4, m0, m2 ;t39 + paddsw m0, m2 ;t32 + psubsw m5, m1, m3 ;t56 + paddsw m1, m3 ;t63 + ITX_MULSUB_2W 5, 4, 2, 3, 7, 1567, 3784 ;t39a, t56a + mova [rsp+gprsize*2+16*35], m0 ;t32 + mova [rsp+gprsize*2+16*42], m5 ;t39a + mova [rsp+gprsize*2+16*59], m4 ;t56a + mova [rsp+gprsize*2+16*66], m1 ;t63 + + mova m0, [rsp+gprsize*2+16*50] ;t47a + mova m2, [rsp+gprsize*2+16*43] ;t40a + mova m3, [rsp+gprsize*2+16*58] ;t55a + mova m1, [rsp+gprsize*2+16*51] ;t48a + psubsw m4, m0, m2 ;t40 + paddsw m0, m2 ;t47 + psubsw m5, m1, m3 ;t55 + paddsw m1, m3 ;t48 + ITX_MULSUB_2W 5, 4, 2, 3, 7, m3784, 1567 ;t40a, t55a + mova [rsp+gprsize*2+16*50], m0 ;t47 + mova [rsp+gprsize*2+16*43], m5 ;t40a + mova [rsp+gprsize*2+16*58], m4 ;t55a + mova [rsp+gprsize*2+16*51], m1 ;t48 + + mova m0, [rsp+gprsize*2+16*49] ;t46 + mova m2, [rsp+gprsize*2+16*44] ;t41 + mova m3, [rsp+gprsize*2+16*57] ;t54 + mova m1, [rsp+gprsize*2+16*52] ;t49 + psubsw m4, m0, m2 ;t41a + paddsw m0, m2 ;t46a + psubsw m5, m1, m3 ;t54a + paddsw m1, m3 ;t49a + ITX_MULSUB_2W 5, 4, 2, 3, 7, m3784, 1567 ;t41, t54 + mova [rsp+gprsize*2+16*49], m0 ;t46a + mova [rsp+gprsize*2+16*44], m5 ;t41 + mova [rsp+gprsize*2+16*57], m4 ;t54 + mova [rsp+gprsize*2+16*52], m1 ;t49a + + mova m0, [rsp+gprsize*2+16*48] ;t45a + mova m2, [rsp+gprsize*2+16*45] ;t42a + mova m3, [rsp+gprsize*2+16*56] ;t53a + mova m1, [rsp+gprsize*2+16*53] ;t50a + psubsw m4, m0, m2 ;t42 + paddsw m0, m2 ;t45 + psubsw m5, m1, m3 ;t53 + paddsw m1, m3 ;t50 + ITX_MULSUB_2W 5, 4, 2, 3, 7, m3784, 1567 ;t42a, t53a + mova [rsp+gprsize*2+16*48], m0 ;t45 + mova [rsp+gprsize*2+16*45], m5 ;t42a + mova [rsp+gprsize*2+16*56], m4 ;t53a + mova [rsp+gprsize*2+16*53], m1 ;t50 + + mova m0, [rsp+gprsize*2+16*47] ;t44 + mova m2, [rsp+gprsize*2+16*46] ;t43 + mova m3, [rsp+gprsize*2+16*55] ;t52 + mova m1, [rsp+gprsize*2+16*54] ;t51 + psubsw m4, m0, m2 ;t43a + paddsw m0, m2 ;t44a + psubsw m5, m1, m3 ;t52a + paddsw m1, m3 ;t51a + ITX_MULSUB_2W 5, 4, 2, 3, 7, m3784, 1567 ;t43, t52 + + mova m2, [rsp+gprsize*2+16*38] ;t35a + mova m3, [rsp+gprsize*2+16*31] ;tmp[28] + psubsw m6, m2, m0 ;t44 + paddsw m2, m0 ;t35 + psubsw m0, m3, m2 ;out35 + paddsw m2, m3 ;out28 + mova m3, [rsp+gprsize*2+16*63] ;t60a + mova [rsp+gprsize*2+16*38], m0 ;out35 + mova [rsp+gprsize*2+16*31], m2 ;out28 + psubsw m0, m3, m1 ;t51 + paddsw m3, m1 ;t60 + ITX_MULSUB_2W 0, 6, 1, 2, 7, 2896, 2896 ;t44a, t51a + mova m2, [rsp+gprsize*2+16*6 ] ;tmp[3] + psubsw m1, m2, m3 ;out60 + paddsw m2, m3 ;out3 + mova m3, [rsp+gprsize*2+16*22] ;tmp[19] + mova [rsp+gprsize*2+16*63], m1 ;out60 + mova [rsp+gprsize*2+16*6 ], m2 ;out3 + psubsw m1, m3, m0 ;out44 + paddsw m3, m0 ;out19 + mova m2, [rsp+gprsize*2+16*15] ;tmp[12] + + mova m0, [rsp+gprsize*2+16*39] ;t36 + mova [rsp+gprsize*2+16*47], m1 ;out44 + mova [rsp+gprsize*2+16*22], m3 ;out19 + mova m1, [rsp+gprsize*2+16*62] ;t59 + psubsw m3, m2, m6 ;out51 + paddsw m2, m6 ;out12 + mova [rsp+gprsize*2+16*54], m3 ;out51 + mova [rsp+gprsize*2+16*15], m2 ;out12 + psubsw m2, m0, m5 ;t43a + paddsw m0, m5 ;t36a + mova m5, [rsp+gprsize*2+16*30] ;tmp[27] + psubsw m3, m1, m4 ;t52a + paddsw m1, m4 ;t59a + ITX_MULSUB_2W 3, 2, 4, 6, 7, 2896, 2896 ;t43, t52 + mova m4, [rsp+gprsize*2+16*7 ] ;tmp[4 ] + psubsw m6, m5, m0 ;out36 + paddsw m5, m0 ;out27 + psubsw m0, m4, m1 ;out59 + paddsw m4, m1 ;out4 + mova [rsp+gprsize*2+16*39], m6 ;out36 + mova [rsp+gprsize*2+16*30], m5 ;out27 + mova [rsp+gprsize*2+16*62], m0 ;out59 + mova [rsp+gprsize*2+16*7 ], m4 ;out4 + mova m0, [rsp+gprsize*2+16*23] ;tmp[20] + mova m5, [rsp+gprsize*2+16*14] ;tmp[11] + psubsw m4, m0, m3 ;out43 + paddsw m0, m3 ;out20 + psubsw m6, m5, m2 ;out52 + paddsw m5, m2 ;out11 + mova [rsp+gprsize*2+16*46], m4 ;out43 + mova [rsp+gprsize*2+16*23], m0 ;out20 + mova [rsp+gprsize*2+16*55], m6 ;out52 + mova [rsp+gprsize*2+16*14], m5 ;out11 + + mova m0, [rsp+gprsize*2+16*40] ;t37a + mova m5, [rsp+gprsize*2+16*45] ;t42a + mova m3, [rsp+gprsize*2+16*56] ;t53a + mova m1, [rsp+gprsize*2+16*61] ;t58a + mova m2, [rsp+gprsize*2+16*29] ;tmp[26] + psubsw m4, m0, m5 ;t42 + paddsw m0, m5 ;t37 + psubsw m5, m1, m3 ;t53 + paddsw m1, m3 ;t58 + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t43, t52 + mova m3, [rsp+gprsize*2+16*8 ] ;tmp[5 ] + psubsw m6, m2, m0 ;out37 + paddsw m2, m0 ;out26 + psubsw m0, m3, m1 ;out58 + paddsw m3, m1 ;out5 + mova [rsp+gprsize*2+16*40], m6 ;out37 + mova [rsp+gprsize*2+16*29], m2 ;out26 + mova [rsp+gprsize*2+16*61], m0 ;out58 + mova [rsp+gprsize*2+16*8 ], m3 ;out5 + mova m0, [rsp+gprsize*2+16*24] ;tmp[21] + mova m1, [rsp+gprsize*2+16*13] ;tmp[10] + psubsw m2, m0, m5 ;out42 + paddsw m0, m5 ;out21 + psubsw m3, m1, m4 ;out53 + paddsw m1, m4 ;out10 + mova [rsp+gprsize*2+16*45], m2 ;out42 + mova [rsp+gprsize*2+16*24], m0 ;out21 + mova [rsp+gprsize*2+16*56], m3 ;out53 + mova [rsp+gprsize*2+16*13], m1 ;out10 + + mova m0, [rsp+gprsize*2+16*41] ;t38 + mova m5, [rsp+gprsize*2+16*44] ;t41 + mova m3, [rsp+gprsize*2+16*57] ;t54 + mova m1, [rsp+gprsize*2+16*60] ;t57 + mova m2, [rsp+gprsize*2+16*28] ;tmp[25] + psubsw m4, m0, m5 ;t41a + paddsw m0, m5 ;t38a + psubsw m5, m1, m3 ;t54a + paddsw m1, m3 ;t57a + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t41a, t54a + mova m3, [rsp+gprsize*2+16*9 ] ;tmp[6 ] + psubsw m6, m2, m0 ;out38 + paddsw m2, m0 ;out25 + psubsw m0, m3, m1 ;out57 + paddsw m3, m1 ;out6 + mova [rsp+gprsize*2+16*41], m6 ;out38 + mova [rsp+gprsize*2+16*28], m2 ;out25 + mova [rsp+gprsize*2+16*60], m0 ;out57 + mova [rsp+gprsize*2+16*9 ], m3 ;out6 + mova m0, [rsp+gprsize*2+16*25] ;tmp[22] + mova m1, [rsp+gprsize*2+16*12] ;tmp[9 ] + psubsw m2, m0, m5 ;out41 + paddsw m0, m5 ;out22 + psubsw m3, m1, m4 ;out54 + paddsw m1, m4 ;out9 + mova [rsp+gprsize*2+16*44], m2 ;out41 + mova [rsp+gprsize*2+16*25], m0 ;out22 + mova [rsp+gprsize*2+16*57], m3 ;out54 + mova [rsp+gprsize*2+16*12], m1 ;out9 + + mova m0, [rsp+gprsize*2+16*42] ;t39a + mova m5, [rsp+gprsize*2+16*43] ;t40a + mova m3, [rsp+gprsize*2+16*58] ;t55a + mova m1, [rsp+gprsize*2+16*59] ;t56a + mova m2, [rsp+gprsize*2+16*27] ;tmp[24] + psubsw m4, m0, m5 ;t40 + paddsw m0, m5 ;t39 + psubsw m5, m1, m3 ;t55 + paddsw m1, m3 ;t56 + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t40a, t55a + mova m3, [rsp+gprsize*2+16*10] ;tmp[7 ] + psubsw m6, m2, m0 ;out39 + paddsw m2, m0 ;out24 + psubsw m0, m3, m1 ;out56 + paddsw m3, m1 ;out7 + mova [rsp+gprsize*2+16*42], m6 ;out39 + mova [rsp+gprsize*2+16*27], m2 ;out24 + mova [rsp+gprsize*2+16*59], m0 ;out56 + mova [rsp+gprsize*2+16*10], m3 ;out7 + mova m0, [rsp+gprsize*2+16*26] ;tmp[23] + mova m1, [rsp+gprsize*2+16*11] ;tmp[8 ] + psubsw m2, m0, m5 ;out40 + paddsw m0, m5 ;out23 + psubsw m3, m1, m4 ;out55 + paddsw m1, m4 ;out8 + mova [rsp+gprsize*2+16*43], m2 ;out40 + mova [rsp+gprsize*2+16*26], m0 ;out23 + mova [rsp+gprsize*2+16*58], m3 ;out55 + mova [rsp+gprsize*2+16*11], m1 ;out8 + + mova m0, [rsp+gprsize*2+16*37] ;t34 + mova m5, [rsp+gprsize*2+16*48] ;t45 + mova m3, [rsp+gprsize*2+16*53] ;t50 + mova m1, [rsp+gprsize*2+16*64] ;t61 + mova m2, [rsp+gprsize*2+16*32] ;tmp[29] + psubsw m4, m0, m5 ;t45a + paddsw m0, m5 ;t34a + psubsw m5, m1, m3 ;t50a + paddsw m1, m3 ;t61a + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t45, t50 + mova m3, [rsp+gprsize*2+16*5 ] ;tmp[2 ] + psubsw m6, m2, m0 ;out34 + paddsw m2, m0 ;out29 + psubsw m0, m3, m1 ;out61 + paddsw m3, m1 ;out2 + mova [rsp+gprsize*2+16*37], m6 ;out34 + mova [rsp+gprsize*2+16*32], m2 ;out29 + mova [rsp+gprsize*2+16*64], m0 ;out61 + mova [rsp+gprsize*2+16*5 ], m3 ;out2 + mova m0, [rsp+gprsize*2+16*21] ;tmp[18] + mova m1, [rsp+gprsize*2+16*16] ;tmp[13] + psubsw m2, m0, m5 ;out45 + paddsw m0, m5 ;out18 + psubsw m3, m1, m4 ;out50 + paddsw m1, m4 ;out13 + mova [rsp+gprsize*2+16*48], m2 ;out45 + mova [rsp+gprsize*2+16*21], m0 ;out18 + mova [rsp+gprsize*2+16*53], m3 ;out50 + mova [rsp+gprsize*2+16*16], m1 ;out13 + + mova m0, [rsp+gprsize*2+16*36] ;t33a + mova m5, [rsp+gprsize*2+16*49] ;t46a + mova m3, [rsp+gprsize*2+16*52] ;t49a + mova m1, [rsp+gprsize*2+16*65] ;t62a + mova m2, [rsp+gprsize*2+16*33] ;tmp[30] + psubsw m4, m0, m5 ;t46 + paddsw m0, m5 ;t33 + psubsw m5, m1, m3 ;t49 + paddsw m1, m3 ;t62 + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t45, t50 + mova m3, [rsp+gprsize*2+16*4 ] ;tmp[1 ] + psubsw m6, m2, m0 ;out33 + paddsw m2, m0 ;out30 + psubsw m0, m3, m1 ;out62 + paddsw m3, m1 ;out1 + mova [rsp+gprsize*2+16*36], m6 ;out33 + mova [rsp+gprsize*2+16*33], m2 ;out30 + mova [rsp+gprsize*2+16*65], m0 ;out62 + mova [rsp+gprsize*2+16*4 ], m3 ;out1 + mova m0, [rsp+gprsize*2+16*20] ;tmp[17] + mova m1, [rsp+gprsize*2+16*17] ;tmp[14] + psubsw m2, m0, m5 ;out46 + paddsw m0, m5 ;out17 + psubsw m3, m1, m4 ;out49 + paddsw m1, m4 ;out14 + mova [rsp+gprsize*2+16*49], m2 ;out46 + mova [rsp+gprsize*2+16*20], m0 ;out17 + mova [rsp+gprsize*2+16*52], m3 ;out49 + mova [rsp+gprsize*2+16*17], m1 ;out14 + + mova m0, [rsp+gprsize*2+16*35] ;t32 + mova m5, [rsp+gprsize*2+16*50] ;t47 + mova m3, [rsp+gprsize*2+16*51] ;t48 + mova m1, [rsp+gprsize*2+16*66] ;t63 + mova m2, [rsp+gprsize*2+16*34] ;tmp[31] + psubsw m4, m0, m5 ;t47a + paddsw m0, m5 ;t32a + psubsw m5, m1, m3 ;t48a + paddsw m1, m3 ;t63a + ITX_MULSUB_2W 5, 4, 3, 6, 7, 2896, 2896 ;t47, t48 + mova m3, [rsp+gprsize*2+16*3 ] ;tmp[0 ] + psubsw m6, m2, m0 ;out32 + paddsw m2, m0 ;out31 + psubsw m0, m3, m1 ;out63 + paddsw m3, m1 ;out0 + mova [rsp+gprsize*2+16*35], m6 ;out32 + mova [rsp+gprsize*2+16*34], m2 ;out31 + mova [rsp+gprsize*2+16*66], m0 ;out63 + mova [rsp+gprsize*2+16*3 ], m3 ;out0 + mova m0, [rsp+gprsize*2+16*19] ;tmp[16] + mova m1, [rsp+gprsize*2+16*18] ;tmp[15] + psubsw m2, m0, m5 ;out47 + paddsw m0, m5 ;out16 + psubsw m3, m1, m4 ;out48 + paddsw m1, m4 ;out15 + mova [rsp+gprsize*2+16*50], m2 ;out47 + mova [rsp+gprsize*2+16*19], m0 ;out16 + mova [rsp+gprsize*2+16*51], m3 ;out48 + mova [rsp+gprsize*2+16*18], m1 ;out15 + ret + + +cglobal inv_txfm_add_dct_dct_64x16_8bpc, 4, 6, 8, 16*132, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + + call m(idct_64x16_internal_8bpc) + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r3d, 16 + lea tx2q, [o(.end)] + +.body: + pmulhrsw m0, m2 + movd m2, [o(pw_2048)] ;intentionally rip-relative + pmulhrsw m0, m1 + pmulhrsw m0, m2 + pshuflw m0, m0, q0000 + punpcklwd m0, m0 + pxor m7, m7 + +.loop: + mova m1, [dstq+16*0] + mova m3, [dstq+16*1] + mova m5, [dstq+16*2] + mova m6, [dstq+16*3] + punpckhbw m2, m1, m7 + punpcklbw m1, m7 + punpckhbw m4, m3, m7 + punpcklbw m3, m7 + paddw m2, m0 + paddw m1, m0 + paddw m4, m0 + paddw m3, m0 + packuswb m1, m2 + packuswb m3, m4 + punpckhbw m2, m5, m7 + punpcklbw m5, m7 + punpckhbw m4, m6, m7 + punpcklbw m6, m7 + paddw m2, m0 + paddw m5, m0 + paddw m4, m0 + paddw m6, m0 + packuswb m5, m2 + packuswb m6, m4 + mova [dstq+16*0], m1 + mova [dstq+16*1], m3 + mova [dstq+16*2], m5 + mova [dstq+16*3], m6 + add dstq, strideq + dec r3d + jg .loop + jmp tx2q + +.end: + RET + + +%macro LOAD_4ROWS 2-3 0 ;src, stride, is_rect2 + +%if %3 + mova m3, [o(pw_2896x8)] + pmulhrsw m0, m3, [%1+%2*0] + pmulhrsw m1, m3, [%1+%2*1] + pmulhrsw m2, m3, [%1+%2*2] + pmulhrsw m3, [%1+%2*3] +%else + mova m0, [%1+%2*0] + mova m1, [%1+%2*1] + mova m2, [%1+%2*2] + mova m3, [%1+%2*3] +%endif +%endmacro + +%macro LOAD_4ROWS_H 2 ;src, stride + mova m4, [%1+%2*0] + mova m5, [%1+%2*1] + mova m6, [%1+%2*2] + mova m7, [%1+%2*3] +%endmacro + +cglobal idct_64x16_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r3d, 2 + mov [rsp+gprsize*2+16*67], dstq + lea dstq, [rsp+gprsize+16*68] + +.pass1_loop: + LOAD_4ROWS coeffq+32*0, 32*8 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + pxor m4, m4 + LOAD_4ROWS coeffq+32*4, 32*8 + + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+32*2, 32*4 + mova [rsp+gprsize+16*19], m0 + mova [rsp+gprsize+16*26], m1 + mova [rsp+gprsize+16*23], m2 + mova [rsp+gprsize+16*22], m3 + mova [rsp+gprsize+16*21], m4 + mova [rsp+gprsize+16*24], m5 + mova [rsp+gprsize+16*25], m6 + mova [rsp+gprsize+16*20], m7 + + call m(idct_8x32_internal_8bpc).main_fast + SAVE_8ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+32*1, 32*2 + mova [rsp+gprsize+16*35], m0 ;in1 + mova [rsp+gprsize+16*49], m1 ;in3 + mova [rsp+gprsize+16*43], m2 ;in5 + mova [rsp+gprsize+16*41], m3 ;in7 + mova [rsp+gprsize+16*39], m4 ;in9 + mova [rsp+gprsize+16*45], m5 ;in11 + mova [rsp+gprsize+16*47], m6 ;in13 + mova [rsp+gprsize+16*37], m7 ;in15 + + LOAD_8ROWS coeffq+32*17, 32*2 + mova [rsp+gprsize+16*63], m0 ;in17 + mova [rsp+gprsize+16*53], m1 ;in19 + mova [rsp+gprsize+16*55], m2 ;in21 + mova [rsp+gprsize+16*61], m3 ;in23 + mova [rsp+gprsize+16*59], m4 ;in25 + mova [rsp+gprsize+16*57], m5 ;in27 + mova [rsp+gprsize+16*51], m6 ;in29 + mova [rsp+gprsize+16*65], m7 ;in31 + + call m(idct_16x64_internal_8bpc).main + + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+32*0, 32 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+32*8, 32 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+32*16, 32 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end3: + SAVE_8ROWS coeffq+32*24, 32 + LOAD_8ROWS rsp+gprsize+16*35, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end4: + SAVE_8ROWS dstq+32*0, 32 + LOAD_8ROWS rsp+gprsize+16*43, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end5)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end5: + SAVE_8ROWS dstq+32*8, 32 + LOAD_8ROWS rsp+gprsize+16*51, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end6)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end6: + SAVE_8ROWS dstq+32*16, 32 + LOAD_8ROWS rsp+gprsize+16*59, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end7)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end7: + SAVE_8ROWS dstq+32*24, 32 + + add coeffq, 16 + add dstq, 16 + dec r3d + jg .pass1_loop + +.pass2: + mov dstq, [rsp+gprsize*2+16*67] + sub coeffq, 32 + mov r3d, 4 + +.pass2_loop: + mov [rsp+gprsize*1+16*67], r3d + + LOAD_4ROWS coeffq+16*0, 32*2 + LOAD_4ROWS_H coeffq+16*1, 32*2 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_4ROWS coeffq+16*2, 32*2 + LOAD_4ROWS_H coeffq+16*3, 32*2 + call m(idct_16x8_internal_8bpc).main + + mov r3, dstq + lea tx2q, [o(.end)] + lea dstq, [dstq+strideq*8] + jmp m(idct_8x8_internal_8bpc).end + +.end: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.end1)] + mov dstq, r3 + jmp m(idct_8x8_internal_8bpc).end + +.end1: + pxor m7, m7 + REPX {mova [coeffq+16*x], m7}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + + add coeffq, 16*16 + mov r3d, [rsp+gprsize*1+16*67] + mov dstq, [rsp+gprsize*2+16*67] + add dstq, 8 + mov [rsp+gprsize*2+16*67], dstq + dec r3d + jg .pass2_loop + + mov r3d, 4 + lea coeffq, [rsp+gprsize+16*68] +.pass2_loop2: + mov [rsp+gprsize*1+16*67], r3d + + LOAD_4ROWS coeffq+16*0, 32*2 + LOAD_4ROWS_H coeffq+16*1, 32*2 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_4ROWS coeffq+16*2, 32*2 + LOAD_4ROWS_H coeffq+16*3, 32*2 + call m(idct_16x8_internal_8bpc).main + + mov r3, dstq + lea tx2q, [o(.end2)] + lea dstq, [dstq+strideq*8] + jmp m(idct_8x8_internal_8bpc).end + +.end2: + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.end3)] + mov dstq, r3 + jmp m(idct_8x8_internal_8bpc).end + +.end3: + + add coeffq, 16*16 + mov r3d, [rsp+gprsize*1+16*67] + mov dstq, [rsp+gprsize*2+16*67] + add dstq, 8 + mov [rsp+gprsize*2+16*67], dstq + dec r3d + jg .pass2_loop2 + ret + + +cglobal inv_txfm_add_dct_dct_32x64_8bpc, 4, 6, 8, 16*68, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_32x64_internal_8bpc) +.end: + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + mov [coeffq], eobd + pmulhrsw m0, m1 + mov r3d, 64 + lea tx2q, [o(.end)] + jmp m(inv_txfm_add_dct_dct_32x8_8bpc).body + + +cglobal idct_32x64_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r4d, 2 + sub eobd, 136 + mov [rsp+gprsize*1+16*67], eobd + mov r3d, 4 + cmovs r3d, r4d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + mov [rsp+gprsize*2+16*67], coeffq + +.pass1_loop: + LOAD_8ROWS coeffq+64*1, 64*2, 1 + mova [rsp+gprsize+16*19], m0 ;in1 + mova [rsp+gprsize+16*26], m1 ;in3 + mova [rsp+gprsize+16*23], m2 ;in5 + mova [rsp+gprsize+16*22], m3 ;in7 + mova [rsp+gprsize+16*21], m4 ;in9 + mova [rsp+gprsize+16*24], m5 ;in11 + mova [rsp+gprsize+16*25], m6 ;in13 + mova [rsp+gprsize+16*20], m7 ;in15 + + mov tx2d, [rsp+gprsize*1+16*67] + test tx2d, tx2d + jl .fast + +.full: + LOAD_8ROWS coeffq+64*0, 64*4, 1 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_8ROWS coeffq+64*2, 64*4, 1 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+64*17, 64*2, 1 + mova [rsp+gprsize+16*33], m0 ;in17 + mova [rsp+gprsize+16*28], m1 ;in19 + mova [rsp+gprsize+16*29], m2 ;in21 + mova [rsp+gprsize+16*32], m3 ;in23 + mova [rsp+gprsize+16*31], m4 ;in25 + mova [rsp+gprsize+16*30], m5 ;in27 + mova [rsp+gprsize+16*27], m6 ;in29 + mova [rsp+gprsize+16*34], m7 ;in31 + + call m(idct_8x32_internal_8bpc).main + jmp .pass1_end + +.fast: + LOAD_4ROWS coeffq, 256, 1 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + + SAVE_7ROWS rsp+gprsize+16*3, 16 + LOAD_4ROWS coeffq+128*1, 256, 1 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + call m(idct_8x32_internal_8bpc).main_fast + +.pass1_end: + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end1: + SAVE_8ROWS coeffq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end2: + SAVE_8ROWS coeffq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end3: + SAVE_8ROWS coeffq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end4: + SAVE_8ROWS coeffq+64*24, 64 + + add coeffq, 16 + dec r3d + jg .pass1_loop + +.pass2: + mov coeffq, [rsp+gprsize*2+16*67] + mov r3d, 4 + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(m(idct_16x64_internal_8bpc).end1)] + jmp m(idct_16x64_internal_8bpc).pass2_loop + + +cglobal inv_txfm_add_dct_dct_64x32_8bpc, 4, 6, 8, 16*197, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + call m(idct_64x32_internal_8bpc) +.end: + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_16384)] + pmulhrsw m0, m1 + mov [coeffq], eobd + mov r3d, 32 + lea tx2q, [o(.end)] + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).body + + +cglobal idct_64x32_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r4d, 2 + sub eobd, 136 + mov [rsp+gprsize*1+16*67], eobd + mov r3d, 4 + cmovs r3d, r4d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + mov [rsp+gprsize*2+16*67], coeffq + mov [rsp+gprsize*3+16*67], dstq + lea dstq, [rsp+gprsize+16*69] + mov [rsp+gprsize*4+16*67], dstq + +.pass1_loop: + LOAD_4ROWS coeffq+64*0, 64*8, 1 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + pxor m4, m4 + LOAD_4ROWS coeffq+64*4, 64*8, 1 + + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+64*2, 64*4, 1 + mova [rsp+gprsize+16*19], m0 + mova [rsp+gprsize+16*26], m1 + mova [rsp+gprsize+16*23], m2 + mova [rsp+gprsize+16*22], m3 + mova [rsp+gprsize+16*21], m4 + mova [rsp+gprsize+16*24], m5 + mova [rsp+gprsize+16*25], m6 + mova [rsp+gprsize+16*20], m7 + + call m(idct_8x32_internal_8bpc).main_fast + SAVE_8ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+64*1, 64*2, 1 + mova [rsp+gprsize+16*35], m0 ;in1 + mova [rsp+gprsize+16*49], m1 ;in3 + mova [rsp+gprsize+16*43], m2 ;in5 + mova [rsp+gprsize+16*41], m3 ;in7 + mova [rsp+gprsize+16*39], m4 ;in9 + mova [rsp+gprsize+16*45], m5 ;in11 + mova [rsp+gprsize+16*47], m6 ;in13 + mova [rsp+gprsize+16*37], m7 ;in15 + + LOAD_8ROWS coeffq+64*17, 64*2, 1 + mova [rsp+gprsize+16*63], m0 ;in17 + mova [rsp+gprsize+16*53], m1 ;in19 + mova [rsp+gprsize+16*55], m2 ;in21 + mova [rsp+gprsize+16*61], m3 ;in23 + mova [rsp+gprsize+16*59], m4 ;in25 + mova [rsp+gprsize+16*57], m5 ;in27 + mova [rsp+gprsize+16*51], m6 ;in29 + mova [rsp+gprsize+16*65], m7 ;in31 + + call m(idct_16x64_internal_8bpc).main + + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end: + SAVE_8ROWS coeffq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end1: + SAVE_8ROWS coeffq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end2: + SAVE_8ROWS coeffq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end3: + SAVE_8ROWS coeffq+64*24, 64 + LOAD_8ROWS rsp+gprsize+16*35, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end4: + SAVE_8ROWS dstq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*43, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end5)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end5: + SAVE_8ROWS dstq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*51, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end6)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end6: + SAVE_8ROWS dstq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*59, 16 + mova [rsp+gprsize+16*0], m7 + lea tx2q, [o(.pass1_end7)] + jmp m(idct_8x8_internal_8bpc).pass1_end + +.pass1_end7: + SAVE_8ROWS dstq+64*24, 64 + + add coeffq, 16 + add dstq, 16 + dec r3d + jg .pass1_loop + +.pass2: + mov coeffq, [rsp+gprsize*4+16*67] + mov dstq, [rsp+gprsize*3+16*67] + mov eobd, [rsp+gprsize*1+16*67] + lea dstq, [dstq+32] + mov [rsp+gprsize*1+16*35], eobd + lea tx2q, [o(.pass2_end)] + mov r3d, 4 + jmp m(idct_32x32_internal_8bpc).pass2_loop + +.pass2_end: + mova [rsp+gprsize+16*0], m7 + lea r3, [o(.pass2_end1)] + jmp m(idct_8x32_internal_8bpc).end2 + +.pass2_end1: + lea tx2q, [o(.pass2_end)] + add coeffq, 16*32 + mov dstq, [rsp+gprsize*2+16*35] + mov r3d, [rsp+gprsize*3+16*35] + dec r3d + jg m(idct_32x32_internal_8bpc).pass2_loop + +.pass2_end2: + mov dstq, [rsp+gprsize*3+16*67] + mov coeffq, [rsp+gprsize*2+16*67] + lea tx2q, [o(m(idct_32x32_internal_8bpc).pass2_end)] + mov r3d, 4 + jmp m(idct_32x32_internal_8bpc).pass2_loop + + +cglobal inv_txfm_add_dct_dct_64x64_8bpc, 4, 6, 8, 16*197, dst, stride, coeff, eob, tx2 +%if ARCH_X86_32 + LEA r5, $$ +%endif + test eobd, eobd + jz .dconly + + call m(idct_64x64_internal_8bpc) + RET + +.dconly: + movd m1, [o(pw_2896x8)] + pmulhrsw m0, m1, [coeffq] + movd m2, [o(pw_8192)] + mov [coeffq], eobd + mov r3d, 64 + lea tx2q, [o(m(inv_txfm_add_dct_dct_64x32_8bpc).end)] + jmp m(inv_txfm_add_dct_dct_64x16_8bpc).body + +cglobal idct_64x64_internal_8bpc, 0, 0, 0, dst, stride, coeff, eob, tx2 + mov r5d, 4 + mov r4d, 2 + sub eobd, 136 + cmovns r4d, r5d + +%if ARCH_X86_32 + LEA r5, $$ +%endif + + mov [rsp+gprsize*1+16*67], eobd + mov r3d, r4d + mov [rsp+gprsize*4+16*67], coeffq + mov [rsp+gprsize*3+16*67], dstq + lea dstq, [rsp+gprsize+16*69] + mov [rsp+gprsize*2+16*67], dstq + +.pass1_loop: + LOAD_4ROWS coeffq+64*0, 64*8 + pxor m4, m4 + REPX {mova x, m4}, m5, m6, m7 + call m(idct_8x8_internal_8bpc).main + SAVE_7ROWS rsp+gprsize+16*3, 16 + + pxor m4, m4 + LOAD_4ROWS coeffq+64*4, 64*8 + + REPX {mova x, m4}, m5, m6, m7 + call m(idct_16x8_internal_8bpc).main + mova m7, [rsp+gprsize+16*0] + SAVE_8ROWS rsp+gprsize+16*11, 16 + + LOAD_8ROWS coeffq+64*2, 64*4 + mova [rsp+gprsize+16*19], m0 + mova [rsp+gprsize+16*26], m1 + mova [rsp+gprsize+16*23], m2 + mova [rsp+gprsize+16*22], m3 + mova [rsp+gprsize+16*21], m4 + mova [rsp+gprsize+16*24], m5 + mova [rsp+gprsize+16*25], m6 + mova [rsp+gprsize+16*20], m7 + + call m(idct_8x32_internal_8bpc).main_fast + SAVE_8ROWS rsp+gprsize+16*3, 16 + + LOAD_8ROWS coeffq+64*1, 64*2 + mova [rsp+gprsize+16*35], m0 ;in1 + mova [rsp+gprsize+16*49], m1 ;in3 + mova [rsp+gprsize+16*43], m2 ;in5 + mova [rsp+gprsize+16*41], m3 ;in7 + mova [rsp+gprsize+16*39], m4 ;in9 + mova [rsp+gprsize+16*45], m5 ;in11 + mova [rsp+gprsize+16*47], m6 ;in13 + mova [rsp+gprsize+16*37], m7 ;in15 + + LOAD_8ROWS coeffq+64*17, 64*2 + mova [rsp+gprsize+16*63], m0 ;in17 + mova [rsp+gprsize+16*53], m1 ;in19 + mova [rsp+gprsize+16*55], m2 ;in21 + mova [rsp+gprsize+16*61], m3 ;in23 + mova [rsp+gprsize+16*59], m4 ;in25 + mova [rsp+gprsize+16*57], m5 ;in27 + mova [rsp+gprsize+16*51], m6 ;in29 + mova [rsp+gprsize+16*65], m7 ;in31 + + call m(idct_16x64_internal_8bpc).main + + LOAD_8ROWS rsp+gprsize+16*3, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end: + SAVE_8ROWS coeffq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*11, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end1)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end1: + SAVE_8ROWS coeffq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*19, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end2)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end2: + SAVE_8ROWS coeffq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*27, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end3)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end3: + SAVE_8ROWS coeffq+64*24, 64 + LOAD_8ROWS rsp+gprsize+16*35, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end4)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end4: + SAVE_8ROWS dstq+64*0, 64 + LOAD_8ROWS rsp+gprsize+16*43, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end5)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end5: + SAVE_8ROWS dstq+64*8, 64 + LOAD_8ROWS rsp+gprsize+16*51, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end6)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end6: + SAVE_8ROWS dstq+64*16, 64 + LOAD_8ROWS rsp+gprsize+16*59, 16 + mova [rsp+gprsize+16*0], m7 + mova m7, [o(pw_8192)] + lea tx2q, [o(.pass1_end7)] + jmp m(idct_8x8_internal_8bpc).pass1_end1 + +.pass1_end7: + SAVE_8ROWS dstq+64*24, 64 + + add coeffq, 16 + add dstq, 16 + dec r3d + jg .pass1_loop + +.pass2: + mov dstq, [rsp+gprsize*3+16*67] + mov coeffq, [rsp+gprsize*2+16*67] + lea dstq, [dstq+32] + mov r3d, 4 + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(.pass2_end)] + jmp m(idct_16x64_internal_8bpc).pass2_loop + +.pass2_end: + LOAD_8ROWS rsp+gprsize+16*35, 16 + lea dstq, [dstq+strideq*2] + lea r3, [rsp+16*32+gprsize] + mova [rsp+gprsize+16*0], m7 + call m(idct_16x64_internal_8bpc).write + mov dstq, [rsp+gprsize*2+16*67] + mov r3d, [rsp+gprsize*3+16*67] + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(.pass2_end)] + + dec r3d + jg m(idct_16x64_internal_8bpc).pass2_loop + +.pass2_end2: + mov coeffq, [rsp+gprsize*4+16*67] + mov dstq, [rsp+gprsize*2+16*67] + mov r3d, 4 + sub dstq, 72 + lea r4, [dstq+8] + mov [rsp+gprsize*2+16*67], r4 + lea r4, [o(m(idct_16x64_internal_8bpc).end1)] + jmp m(idct_16x64_internal_8bpc).pass2_loop diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1161 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +pb_mask: dd 1, 1, 2, 2, 4, 4, 8, 8 +pb_4x1_4x5_4x9_4x13: times 4 db 0, 1 + times 4 db 8, 9 + times 4 db 0, 1 + times 4 db 8, 9 + +pw_1: times 16 dw 1 +pw_2: times 16 dw 2 +pw_3: times 16 dw 3 +pw_4096: times 2 dw 4096 + +; 10bpc/12bpc: +pw_4: times 2 dw 4 + times 2 dw 16 +clip_max: times 2 dw 511 + times 2 dw 2047 +clip_min: times 2 dw -512 + times 2 dw -2048 + +SECTION .text + +; in: out: +; mm%1 a b c d a e i m +; mm%2 e f g h b f j n +; mm%3 i j k l -> c g k o +; mm%4 m n o p d h l p +%macro TRANSPOSE4X4W 5 + punpcklwd m%5, m%1, m%2 + punpckhwd m%1, m%2 + punpcklwd m%2, m%3, m%4 + punpckhwd m%3, m%4 + punpckldq m%4, m%5, m%2 + punpckhdq m%5, m%2 + punpckldq m%2, m%1, m%3 + punpckhdq m%1, m%3 + + SWAP %1, %4 + SWAP %2, %5, %3 +%endmacro + +; in: out: +; xmm%1 a b c d e f g h a i q y 6 E M U +; xmm%2 i j k l m n o p b j r z 7 F N V +; xmm%3 q r s t u v w x c k s 0 8 G O W +; xmm%4 y z 0 1 2 3 4 5 d l t 1 9 H P X +; xmm%5 6 7 8 9 A B C D -> e m u 2 A I Q Y +; xmm%6 E F G H I J K L f n v 3 B J R Z +; xmm%7 M N O P Q R S T g o w 4 C K S + +; xmm%8 U V W X Y Z + = h p x 5 D L T = +%macro TRANSPOSE8X8W 9 + ; xmm%1 a b c d e f g h a i q y b j r z + ; xmm%2 i j k l m n o p c k s 0 d l t 1 + ; xmm%3 q r s t u v w x -> e m u 2 f n v 3 + ; xmm%4 y z 0 1 2 3 4 5 g o w 4 h p x 5 + TRANSPOSE4X4W %1, %2, %3, %4, %9 + + ; xmm%5 6 7 8 9 A B C D 6 E M U 7 F N V + ; xmm%6 E F G H I J K L 8 G O W 9 H P X + ; xmm%7 M N O P Q R S T -> A I Q Y B J R Z + ; xmm%8 U V W X Y Z + = C K S + D L T = + TRANSPOSE4X4W %5, %6, %7, %8, %9 + + ; xmm%1 a i q y b j r z a i q y 6 E M U + ; xmm%2 c k s 0 d l t 1 b j r z 7 F N V + ; xmm%3 e m u 2 f n v 3 c k s 0 8 G O W + ; xmm%4 g o w 4 h p x 5 d l t 1 9 H P X + ; xmm%5 6 E M U 7 F N V -> e m u 2 A I Q Y + ; xmm%6 8 G O W 9 H P X f n v 3 B J R Z + ; xmm%7 A I Q Y B J R Z g o w 4 C K S + + ; xmm%8 C K S + D L T = h p x 5 D L T = + punpckhqdq m%9, m%1, m%5 + punpcklqdq m%1, m%5 + punpckhqdq m%5, m%2, m%6 + punpcklqdq m%2, m%6 + punpckhqdq m%6, m%3, m%7 + punpcklqdq m%3, m%7 + punpckhqdq m%7, m%4, m%8 + punpcklqdq m%4, m%8 + + SWAP %8, %7, %4, %5, %3, %2, %9 +%endmacro + +; transpose and write m3-6, everything else is scratch +%macro TRANSPOSE_8x4_AND_WRITE_4x16 0 + ; transpose 8x4 + punpcklwd m0, m3, m4 + punpckhwd m3, m4 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpckldq m6, m0, m4 + punpckhdq m0, m4 + punpckldq m4, m3, m5 + punpckhdq m3, m5 + + ; write out + movq [dstq+strideq*0-4], xm6 + movhps [dstq+strideq*1-4], xm6 + movq [dstq+strideq*2-4], xm0 + movhps [dstq+stride3q -4], xm0 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm4 + movhps [dstq+strideq*1-4], xm4 + movq [dstq+strideq*2-4], xm3 + movhps [dstq+stride3q -4], xm3 + lea dstq, [dstq+strideq*4] + + vextracti128 xm6, m6, 1 + vextracti128 xm0, m0, 1 + vextracti128 xm4, m4, 1 + vextracti128 xm3, m3, 1 + + movq [dstq+strideq*0-4], xm6 + movhps [dstq+strideq*1-4], xm6 + movq [dstq+strideq*2-4], xm0 + movhps [dstq+stride3q -4], xm0 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm4 + movhps [dstq+strideq*1-4], xm4 + movq [dstq+strideq*2-4], xm3 + movhps [dstq+stride3q -4], xm3 + lea dstq, [dstq+strideq*4] +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] + ; load data +%ifidn %2, v +%if %1 == 4 + lea tmpq, [dstq+mstrideq*2] + mova m3, [tmpq+strideq*0] ; p1 + mova m4, [tmpq+strideq*1] ; p0 + mova m5, [tmpq+strideq*2] ; q0 + mova m6, [tmpq+stride3q] ; q1 +%else + ; load 6-8 pixels, remainder (for wd=16) will be read inline + lea tmpq, [dstq+mstrideq*4] + ; we load p3 later + mova m13, [tmpq+strideq*1] + mova m3, [tmpq+strideq*2] + mova m4, [tmpq+stride3q] + mova m5, [dstq+strideq*0] + mova m6, [dstq+strideq*1] + mova m14, [dstq+strideq*2] +%if %1 != 6 + mova m15, [dstq+stride3q] +%endif +%endif +%else + ; load lines +%if %1 == 4 + movq xm3, [dstq+strideq*0-4] + movq xm4, [dstq+strideq*1-4] + movq xm5, [dstq+strideq*2-4] + movq xm6, [dstq+stride3q -4] + lea tmpq, [dstq+strideq*4] + movq xm11, [tmpq+strideq*0-4] + movq xm13, [tmpq+strideq*1-4] + movq xm14, [tmpq+strideq*2-4] + movq xm15, [tmpq+stride3q -4] + lea tmpq, [tmpq+strideq*4] + ; this overreads by 8 bytes but the buffers are padded + ; so that should be ok + vinserti128 m3, [tmpq+strideq*0-4], 1 + vinserti128 m4, [tmpq+strideq*1-4], 1 + vinserti128 m5, [tmpq+strideq*2-4], 1 + vinserti128 m6, [tmpq+stride3q -4], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m11, [tmpq+strideq*0-4], 1 + vinserti128 m13, [tmpq+strideq*1-4], 1 + vinserti128 m14, [tmpq+strideq*2-4], 1 + vinserti128 m15, [tmpq+stride3q -4], 1 + + ; transpose 4x8 + ; xm3: A-D0,A-D4 + ; xm4: A-D1,A-D5 + ; xm5: A-D2,A-D6 + ; xm6: A-D3,A-D7 + punpcklwd m7, m3, m4 + punpcklwd m3, m11, m13 + punpcklwd m4, m5, m6 + punpcklwd m5, m14, m15 + ; xm7: A0-1,B0-1,C0-1,D0-1 + ; xm3: A4-5,B4-5,C4-5,D4-5 + ; xm4: A2-3,B2-3,C2-3,D2-3 + ; xm5: A6-7,B6-7,C6-7,D6-7 + punpckldq m6, m7, m4 + punpckhdq m7, m4 + punpckldq m8, m3, m5 + punpckhdq m5, m3, m5 + ; xm6: A0-3,B0-3 + ; xm7: C0-3,D0-3 + ; xm8: A4-7,B4-7 + ; xm5: C4-7,D4-7 + punpcklqdq m3, m6, m8 + punpckhqdq m4, m6, m8 + punpckhqdq m6, m7, m5 + punpcklqdq m5, m7, m5 + ; xm3: A0-7 + ; xm4: B0-7 + ; xm5: C0-7 + ; xm6: D0-7 +%elif %1 == 6 || %1 == 8 + movu xm3, [dstq+strideq*0-8] + movu xm4, [dstq+strideq*1-8] + movu xm5, [dstq+strideq*2-8] + movu xm6, [dstq+stride3q -8] + lea tmpq, [dstq+strideq*4] + movu xm11, [tmpq+strideq*0-8] + movu xm13, [tmpq+strideq*1-8] + movu xm14, [tmpq+strideq*2-8] + movu xm15, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + vinserti128 m3, [tmpq+strideq*0-8], 1 + vinserti128 m4, [tmpq+strideq*1-8], 1 + vinserti128 m5, [tmpq+strideq*2-8], 1 + vinserti128 m6, [tmpq+stride3q -8], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m11, [tmpq+strideq*0-8], 1 + vinserti128 m13, [tmpq+strideq*1-8], 1 + vinserti128 m14, [tmpq+strideq*2-8], 1 + vinserti128 m15, [tmpq+stride3q -8], 1 + + ; transpose 8x16 + ; xm3: A-H0,A-H8 + ; xm4: A-H1,A-H9 + ; xm5: A-H2,A-H10 + ; xm6: A-H3,A-H11 + ; xm11: A-H4,A-H12 + ; xm13: A-H5,A-H13 + ; xm14: A-H6,A-H14 + ; xm15: A-H7,A-H15 + punpcklwd m7, m3, m4 + punpckhwd m3, m4 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpcklwd m6, m11, m13 + punpckhwd m11, m13 + punpcklwd m13, m14, m15 + punpckhwd m14, m15 + ; xm7: A0-1,B0-1,C0-1,D0-1 + ; xm3: E0-1,F0-1,G0-1,H0-1 + ; xm4: A2-3,B2-3,C2-3,D2-3 + ; xm5: E2-3,F2-3,G2-3,H2-3 + ; xm6: A4-5,B4-5,C4-5,D4-5 + ; xm11: E4-5,F4-5,G4-5,H4-5 + ; xm13: A6-7,B6-7,C6-7,D6-7 + ; xm14: E6-7,F6-7,G6-7,H6-7 + punpckldq m15, m7, m4 + punpckhdq m7, m4 + punpckldq m9, m3, m5 + punpckhdq m8, m3, m5 + punpckldq m3, m6, m13 + punpckhdq m6, m13 + punpckldq m10, m11, m14 + punpckhdq m11, m14 + ; xm15: A0-3,B0-3 + ; xm7: C0-3,D0-3 + ; xm9: E0-3,F0-3 + ; xm8: G0-3,H0-3 + ; xm3: A4-7,B4-7 + ; xm6: C4-7,D4-7 + ; xm10: E4-7,F4-7 + ; xm11: G4-7,H4-7 +%if %1 != 6 + punpcklqdq m0, m15, m3 +%endif + punpckhqdq m13, m15, m3 + punpcklqdq m3, m7, m6 + punpckhqdq m4, m7, m6 + punpcklqdq m5, m9, m10 + punpckhqdq m6, m9, m10 + punpcklqdq m14, m8, m11 +%if %1 != 6 + punpckhqdq m15, m8, m11 + mova [rsp+5*32], m0 +%endif +%else + ; We only use 14 pixels but we'll need the remainder at the end for + ; the second transpose + mova xm0, [dstq+strideq*0-16] + mova xm1, [dstq+strideq*1-16] + mova xm2, [dstq+strideq*2-16] + mova xm3, [dstq+stride3q -16] + lea tmpq, [dstq+strideq*4] + mova xm4, [tmpq+strideq*0-16] + mova xm5, [tmpq+strideq*1-16] + mova xm6, [tmpq+strideq*2-16] + mova xm7, [tmpq+stride3q -16] + lea tmpq, [tmpq+strideq*4] + vinserti128 m0, m0, [tmpq+strideq*0-16], 1 + vinserti128 m1, m1, [tmpq+strideq*1-16], 1 + vinserti128 m2, m2, [tmpq+strideq*2-16], 1 + vinserti128 m3, m3, [tmpq+stride3q -16], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m4, m4, [tmpq+strideq*0-16], 1 + vinserti128 m5, m5, [tmpq+strideq*1-16], 1 + vinserti128 m6, m6, [tmpq+strideq*2-16], 1 + vinserti128 m7, m7, [tmpq+stride3q -16], 1 + + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 7, 8 + + mova [rsp+6*32], m0 + mova [rsp+7*32], m1 + mova [rsp+8*32], m2 + mova [rsp+9*32], m3 + mova [rsp+5*32], m4 + + mova xm0, [dstq+strideq*0] + mova xm1, [dstq+strideq*1] + mova xm2, [dstq+strideq*2] + mova xm3, [dstq+stride3q ] + lea tmpq, [dstq+strideq*4] + mova xm8, [tmpq+strideq*0] + mova xm9, [tmpq+strideq*1] + mova xm10, [tmpq+strideq*2] + mova xm11, [tmpq+stride3q ] + lea tmpq, [tmpq+strideq*4] + vinserti128 m0, m0, [tmpq+strideq*0], 1 + vinserti128 m1, m1, [tmpq+strideq*1], 1 + vinserti128 m2, m2, [tmpq+strideq*2], 1 + vinserti128 m3, m3, [tmpq+stride3q ], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m8, m8, [tmpq+strideq*0], 1 + vinserti128 m9, m9, [tmpq+strideq*1], 1 + vinserti128 m10, m10, [tmpq+strideq*2], 1 + vinserti128 m11, m11, [tmpq+stride3q ], 1 + + TRANSPOSE8X8W 0, 1, 2, 3, 8, 9, 10, 11, 4 + + mova [rsp+10*32], m8 + mova [rsp+11*32], m9 + mova [rsp+12*32], m10 + mova [rsp+13*32], m11 + + ; 5,6,7,0,1,2,3 -> 13,3,4,5,6,14,15 + SWAP 13, 5, 0 + SWAP 3, 6, 1, 15 + SWAP 4, 7 + SWAP 2, 14 +%endif +%endif + + ; load L/E/I/H +%ifidn %2, v + pmovzxbw m1, [lq] + pmovzxbw m0, [lq+l_strideq] + pxor m2, m2 +%else + vpbroadcastq m0, [lq] ; l0, l1 + vpbroadcastq m1, [lq+l_strideq] ; l2, l3 + vpbroadcastq m2, [lq+l_strideq*2] ; l4, l5 + vpbroadcastq m10, [lq+l_stride3q] ; l6, l7 + punpckldq m0, m1 ; l0, l2, l1, l3 [2x] + punpckldq m2, m10 ; l4, l6, l5, l7 [2x] + vpblendd m0, m0, m2, 11110000b ; l0, l2, l1, l3, l4, l6, l5, l7 + pxor m2, m2 + punpcklbw m1, m0, m2 ; l0, l2, l4, l6 + punpckhbw m0, m2 ; l1, l3, l5, l7 +%endif + pcmpeqw m10, m2, m0 + pand m1, m10 + por m0, m1 ; l[x][] ? l[x][] : l[x-stride][] + pshufb m0, [pb_4x1_4x5_4x9_4x13] ; l[x][1] + pcmpeqw m10, m2, m0 ; !L + psrlw m10, 1 + psrlw m2, m0, [lutq+128] + vpbroadcastw m1, [lutq+136] + pminuw m2, m1 + pmaxuw m2, [pw_1] ; I + psrlw m1, m0, 4 ; H + paddw m0, [pw_2] + vpbroadcastd m8, [r11] + paddw m0, m0 + paddw m0, m2 ; E + REPX {pmullw x, m8}, m0, m1, m2 + + psubw m8, m3, m4 ; p1-p0 + psubw m9, m5, m6 ; q1-q0 + REPX {pabsw x, x}, m8, m9 + pmaxuw m8, m10 + pmaxuw m8, m9 + pcmpgtw m7, m8, m1 ; hev +%if %1 != 4 + psubw m9, m13, m4 ; p2-p0 + pabsw m9, m9 + pmaxuw m9, m8 +%if %1 != 6 +%ifidn %2, v + mova m11, [tmpq+strideq*0] ; p3 +%else + mova m11, [rsp+5*32] ; p3 +%endif + psubw m10, m11, m4 ; p3-p0 + pabsw m10, m10 + pmaxuw m9, m10 +%endif + psubw m10, m5, m14 ; q2-q0 + pabsw m10, m10 + pmaxuw m9, m10 +%if %1 != 6 + psubw m10, m5, m15 ; q3-q0 + pabsw m10, m10 + pmaxuw m9, m10 +%endif + vpbroadcastd m10, [r11] + pcmpgtw m9, m10 ; !flat8in + + psubw m10, m13, m3 ; p2-p1 + pabsw m10, m10 +%if %1 != 6 + psubw m11, m13 ; p3-p2 + pabsw m11, m11 + pmaxuw m10, m11 + psubw m11, m14, m15 ; q3-q2 + pabsw m11, m11 + pmaxuw m10, m11 +%endif + psubw m11, m14, m6 ; q2-q1 + pabsw m11, m11 + pmaxuw m10, m11 + +%if %1 == 16 + vpbroadcastd m11, [maskq+8] + vpbroadcastd m1, [maskq+4] + por m11, m1 + pand m11, m12 + pcmpeqd m11, m12 + pand m10, m11 +%else + vpbroadcastd m11, [maskq+4] + pand m11, m12 + pcmpeqd m11, m12 + pand m10, m11 ; only apply fm-wide to wd>4 blocks +%endif + pmaxuw m8, m10 +%endif + pcmpgtw m8, m2 + + psubw m10, m3, m6 ; p1-q1 + psubw m11, m4, m5 ; p0-q0 + REPX {pabsw x, x}, m10, m11 + paddw m11, m11 + psrlw m10, 1 + paddw m10, m11 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + pcmpgtw m10, m0 ; abs(p0-q0)*2+(abs(p1-q1)>>1) > E + por m8, m10 + +%if %1 == 16 + +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] + mova m1, [tmpq+strideq*2] + mova m2, [tmpq+stride3q] +%else + mova m0, [rsp+7*32] + mova m1, [rsp+8*32] + mova m2, [rsp+9*32] +%endif + REPX {psubw x, m4}, m0, m1, m2 + REPX {pabsw x, x}, m0, m1, m2 + pmaxuw m1, m0 + pmaxuw m1, m2 +%ifidn %2, v + lea tmpq, [dstq+strideq*4] + mova m0, [tmpq+strideq*0] + mova m2, [tmpq+strideq*1] + mova m10, [tmpq+strideq*2] +%else + mova m0, [rsp+10*32] + mova m2, [rsp+11*32] + mova m10, [rsp+12*32] +%endif + REPX {psubw x, m5}, m0, m2, m10 + REPX {pabsw x, x}, m0, m2, m10 + pmaxuw m0, m2 + pmaxuw m1, m10 + pmaxuw m1, m0 + vpbroadcastd m0, [r11] + pcmpgtw m1, m0 ; !flat8out + por m1, m9 ; !flat8in | !flat8out + vpbroadcastd m2, [maskq+8] + pand m10, m2, m12 + pcmpeqd m10, m12 + pandn m1, m10 ; flat16 + pandn m1, m8, m1 ; flat16 & fm + + vpbroadcastd m10, [maskq+4] + por m10, m2 + pand m2, m10, m12 + pcmpeqd m2, m12 + pandn m9, m2 ; flat8in + pandn m9, m8, m9 + vpbroadcastd m2, [maskq+0] + por m2, m10 + pand m2, m12 + pcmpeqd m2, m12 + pandn m8, m2 + pandn m8, m9, m8 ; fm & !flat8 & !flat16 + pandn m9, m1, m9 ; flat8 & !flat16 +%elif %1 != 4 + vpbroadcastd m0, [maskq+4] + pand m2, m0, m12 + pcmpeqd m2, m12 + pandn m9, m2 + pandn m9, m8, m9 ; flat8 & fm + vpbroadcastd m2, [maskq+0] + por m0, m2 + pand m0, m12 + pcmpeqd m0, m12 + pandn m8, m0 + pandn m8, m9, m8 ; fm & !flat8 +%else + vpbroadcastd m0, [maskq+0] + pand m0, m12 + pcmpeqd m0, m12 + pandn m8, m0 ; fm +%endif + + ; short filter + vpbroadcastd m0, [r11+8*1] ; 511 or 2047 + vpbroadcastd m2, [r11+8*2] ; -512 or -2048 + psubw m10, m5, m4 + paddw m11, m10, m10 + paddw m11, m10 + psubw m10, m3, m6 ; iclip_diff(p1-q1) + pminsw m10, m0 + pmaxsw m10, m2 + pand m10, m7 ; f=iclip_diff(p1-q1)&hev + paddw m10, m11 ; f=iclip_diff(3*(q0-p0)+f) + pminsw m10, m0 + pmaxsw m10, m2 + pand m8, m10 ; f&=fm + vpbroadcastd m10, [pw_4] + paddw m10, m8 + paddw m8, [pw_3] + REPX {pminsw x, m0}, m10, m8 + psraw m10, 3 ; f2 + psraw m8, 3 ; f1 + psubw m5, m10 + paddw m4, m8 + + paddw m10, [pw_1] + psraw m10, 1 ; f=(f1+1)>>1 + pandn m8, m7, m10 ; f&=!hev + paddw m3, m8 + psubw m6, m8 + pxor m8, m8 + psubw m0, m2 ; 1023 or 4095 + REPX {pminsw x, m0}, m3, m4, m5, m6 + REPX {pmaxsw x, m8}, m3, m4, m5, m6 + +%if %1 == 16 + +; m3-6 = p1/p0/q0/q1, m9=flat8, m1=flat16 +; m12=filter bits mask +; m13-15=p2/q2/q3 +; m0,2,7-8,10-11 = free + + ; flat16 filter +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] ; p6 + mova m2, [tmpq+strideq*2] ; p5 + mova m7, [tmpq+stride3q] ; p4 + mova m11, [tmpq+strideq*4] ; p3 +%else + mova m0, [rsp+7*32] + mova m2, [rsp+8*32] + mova m7, [rsp+9*32] + mova m11, [rsp+5*32] +%endif + + mova [rsp+ 0*32], m9 + + ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + paddw m8, m0, [pw_1] + psllw m8, 3 ; p6*8+8 + paddw m10, m2, m7 ; p5+p4 + psubw m8, m0 + paddw m10, m10 ; (p5+p4)*2 + paddw m8, m11 ; p6*7+p3 + paddw m10, m13 ; (p5+p4)*2+p2 + paddw m8, m3 ; p6*7+p3+p1 + paddw m10, m4 ; (p5+p4)*2+p2+p0 + paddw m8, m5 ; p6*7+p3+p1+q0 + paddw m8, m10 ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + psrlw m10, m8, 4 + vpblendvb m10, m2, m10, m1 +%ifidn %2, v + mova [tmpq+strideq*2], m10 ; p5 +%else + mova [rsp+8*32], m10 +%endif + + ; sub p6*2, add p3/q1 + paddw m8, m11 + paddw m10, m0, m0 + paddw m8, m6 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m7, m10, m1 +%ifidn %2, v + mova [tmpq+stride3q], m10 ; p4 +%else + mova [rsp+9*32], m10 +%endif + + ; sub p6/p5, add p2/q2 + psubw m8, m0 + paddw m10, m13, m14 + psubw m8, m2 + paddw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m11, m10, m1 +%ifidn %2, v + mova [tmpq+strideq*4], m10 ; p3 + lea tmpq, [dstq+strideq*4] +%else + mova [rsp+5*32], m10 +%endif + + ; sub p6/p4, add p1/q3 + paddw m8, m3 + paddw m10, m0, m7 + paddw m8, m15 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m13, m10, m1 + mova [rsp+1*32], m10 ; don't clobber p2/m13 + + ; sub p6/p3, add p0/q4 + paddw m8, m4 + paddw m10, m0, m11 +%ifidn %2, v + paddw m8, [tmpq+strideq*0] +%else + paddw m8, [rsp+10*32] +%endif + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m3, m10, m1 + mova [rsp+2*32], m10 ; don't clobber p1/m3 + + ; sub p6/p2, add q0/q5 + paddw m8, m5 + paddw m10, m0, m13 +%ifidn %2, v + paddw m8, [tmpq+strideq*1] +%else + paddw m8, [rsp+11*32] +%endif + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m4, m10, m1 + mova [rsp+3*32], m10 ; don't clobber p0/m4 + + ; sub p6/p1, add q1/q6 + paddw m8, m6 + paddw m10, m0, m3 +%ifidn %2, v + mova m0, [tmpq+strideq*2] ; q6 +%else + mova m0, [rsp+12*32] ; q6 +%endif + paddw m8, m0 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m5, m10, m1 + mova [rsp+4*32], m10 ; don't clobber q0/m5 + + ; sub p5/p0, add q2/q6 + paddw m8, m14 + paddw m10, m2, m4 + paddw m8, m0 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m2, m6, m10, m1 ; don't clobber q1/m6 + + ; sub p4/q0, add q3/q6 + paddw m8, m15 + paddw m10, m7, m5 + paddw m8, m0 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m7, m14, m10, m1 ; don't clobber q2/m14 + + ; sub p3/q1, add q4/q6 +%ifidn %2, v + paddw m8, [tmpq+strideq*0] +%else + paddw m8, [rsp+10*32] +%endif + paddw m10, m11, m6 + paddw m8, m0 + psubw m8, m10 + psrlw m10, m8, 4 + vpblendvb m10, m15, m10, m1 +%ifidn %2, v + mova [tmpq+mstrideq], m10 ; q3 +%else + mova [rsp+14*32], m10 +%endif + + ; sub p2/q2, add q5/q6 +%ifidn %2, v + paddw m8, [tmpq+strideq*1] +%else + paddw m8, [rsp+11*32] +%endif + paddw m10, m13, m14 + paddw m8, m0 + psubw m8, m10 + psrlw m10, m8, 4 +%ifidn %2, v + mova m9, [tmpq+strideq*0] +%else + mova m9, [rsp+10*32] +%endif + vpblendvb m10, m9, m10, m1 +%ifidn %2, v + mova [tmpq+strideq*0], m10 ; q4 +%else + mova [rsp+10*32], m10 +%endif + + ; sub p1/q3, add q6*2 + psubw m8, m3 + paddw m0, m0 + psubw m8, m15 + paddw m8, m0 + psrlw m10, m8, 4 +%ifidn %2, v + mova m9, [tmpq+strideq*1] +%else + mova m9, [rsp+11*32] +%endif + vpblendvb m10, m9, m10, m1 +%ifidn %2, v + mova [tmpq+strideq*1], m10 ; q5 +%else + mova [rsp+11*32], m10 +%endif + + mova m9, [rsp+0*32] + mova m13, [rsp+1*32] + mova m3, [rsp+2*32] + mova m4, [rsp+3*32] + mova m5, [rsp+4*32] + SWAP 2, 6 + SWAP 7, 14 +%ifidn %2, v + lea tmpq, [dstq+mstrideq*4] +%else + mova m15, [rsp+14*32] +%endif +%endif + +%if %1 >= 8 + ; flat8 filter + vpbroadcastd m7, [pw_4096] +%ifidn %2, v + mova m0, [tmpq+strideq*0] ; p3 +%else + mova m0, [rsp+5*32] ; p3 +%endif + paddw m1, m0, m13 ; p3+p2 + paddw m2, m3, m4 ; p1+p0 + paddw m8, m1, m1 ; 2*(p3+p2) + paddw m2, m0 ; p1+p0+p3 + paddw m8, m5 ; 2*(p3+p2)+q0 + paddw m2, m8 ; 3*p3+2*p2+p1+p0+q0 + pmulhrsw m10, m2, m7 + + paddw m8, m3, m6 + psubw m2, m1 + paddw m2, m8 + pmulhrsw m8, m2, m7 + + paddw m11, m0, m3 + paddw m1, m4, m14 + psubw m2, m11 + paddw m2, m1 + pmulhrsw m1, m2, m7 + + paddw m11, m0, m4 + pblendvb m4, m1, m9 + paddw m1, m5, m15 + psubw m2, m11 + paddw m2, m1 + pmulhrsw m11, m2, m7 + + paddw m2, m6 + paddw m2, m15 + paddw m1, m13, m5 + pblendvb m5, m11, m9 + pblendvb m13, m10, m9 + psubw m2, m1 + pmulhrsw m1, m2, m7 + + psubw m2, m3 + pblendvb m3, m8, m9 + psubw m2, m6 + pblendvb m6, m1, m9 + paddw m1, m15, m14 + paddw m2, m1 + pmulhrsw m2, m7 + + pblendvb m14, m2, m9 + +%ifidn %2, v + mova [tmpq+strideq*1], m13 ; p2 + mova [tmpq+strideq*2], m3 ; p1 + mova [tmpq+stride3q ], m4 ; p0 + mova [dstq+strideq*0], m5 ; q0 + mova [dstq+strideq*1], m6 ; q1 + mova [dstq+strideq*2], m14 ; q2 +%elif %1 == 8 + TRANSPOSE8X8W 0, 13, 3, 4, 5, 6, 14, 15, 1 + + ; write 8x16 + movu [dstq+strideq*0-8], xm0 + movu [dstq+strideq*1-8], xm13 + movu [dstq+strideq*2-8], xm3 + movu [dstq+stride3q -8], xm4 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm5 + movu [dstq+strideq*1-8], xm6 + movu [dstq+strideq*2-8], xm14 + movu [dstq+stride3q -8], xm15 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m0, 1 + vextracti128 [dstq+strideq*1-8], m13, 1 + vextracti128 [dstq+strideq*2-8], m3, 1 + vextracti128 [dstq+stride3q -8], m4, 1 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m5, 1 + vextracti128 [dstq+strideq*1-8], m6, 1 + vextracti128 [dstq+strideq*2-8], m14, 1 + vextracti128 [dstq+stride3q -8], m15, 1 + lea dstq, [dstq+strideq*4] +%else + mova m8, [rsp+6*32] + mova m1, [rsp+7*32] + mova m2, [rsp+8*32] + mova m7, [rsp+9*32] + TRANSPOSE8X8W 8, 1, 2, 7, 0, 13, 3, 4, 9 + + mova [dstq+strideq*0-16], xm8 + mova [dstq+strideq*1-16], xm1 + mova [dstq+strideq*2-16], xm2 + mova [dstq+stride3q -16], xm7 + lea tmpq, [dstq+strideq*4] + mova [tmpq+strideq*0-16], xm0 + mova [tmpq+strideq*1-16], xm13 + mova [tmpq+strideq*2-16], xm3 + mova [tmpq+stride3q -16], xm4 + lea tmpq, [tmpq+strideq*4] + vextracti128 [tmpq+strideq*0-16], m8, 1 + vextracti128 [tmpq+strideq*1-16], m1, 1 + vextracti128 [tmpq+strideq*2-16], m2, 1 + vextracti128 [tmpq+stride3q -16], m7, 1 + lea tmpq, [tmpq+strideq*4] + vextracti128 [tmpq+strideq*0-16], m0, 1 + vextracti128 [tmpq+strideq*1-16], m13, 1 + vextracti128 [tmpq+strideq*2-16], m3, 1 + vextracti128 [tmpq+stride3q -16], m4, 1 + + mova m0, [rsp+10*32] + mova m1, [rsp+11*32] + mova m2, [rsp+12*32] + mova m3, [rsp+13*32] + TRANSPOSE8X8W 5, 6, 14, 15, 0, 1, 2, 3, 4 + mova [dstq+strideq*0], xm5 + mova [dstq+strideq*1], xm6 + mova [dstq+strideq*2], xm14 + mova [dstq+stride3q ], xm15 + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm0 + mova [dstq+strideq*1], xm1 + mova [dstq+strideq*2], xm2 + mova [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0], m5, 1 + vextracti128 [dstq+strideq*1], m6, 1 + vextracti128 [dstq+strideq*2], m14, 1 + vextracti128 [dstq+stride3q ], m15, 1 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0], m0, 1 + vextracti128 [dstq+strideq*1], m1, 1 + vextracti128 [dstq+strideq*2], m2, 1 + vextracti128 [dstq+stride3q ], m3, 1 + lea dstq, [dstq+strideq*4] +%endif +%elif %1 == 6 + ; flat6 filter + vpbroadcastd m7, [pw_4096] + paddw m8, m3, m4 + paddw m8, m13 ; p2+p1+p0 + paddw m11, m13, m5 + paddw m8, m8 + paddw m8, m11 ; p2+2*(p2+p1+p0)+q0 + pmulhrsw m2, m8, m7 + + paddw m8, m5 + paddw m11, m13, m13 + paddw m8, m6 + psubw m8, m11 + pmulhrsw m10, m8, m7 + + paddw m8, m6 + paddw m11, m13, m3 + paddw m8, m14 + psubw m8, m11 + pmulhrsw m11, m8, m7 + + psubw m8, m3 + paddw m14, m14 + psubw m8, m4 + paddw m8, m14 + pmulhrsw m8, m7 + + pblendvb m3, m2, m9 + pblendvb m4, m10, m9 + pblendvb m5, m11, m9 + pblendvb m6, m8, m9 + +%ifidn %2, v + mova [tmpq+strideq*2], m3 ; p1 + mova [tmpq+stride3q ], m4 ; p0 + mova [dstq+strideq*0], m5 ; q0 + mova [dstq+strideq*1], m6 ; q1 +%else + TRANSPOSE_8x4_AND_WRITE_4x16 +%endif +%else +%ifidn %2, v + mova [tmpq+strideq*0], m3 ; p1 + mova [tmpq+strideq*1], m4 ; p0 + mova [tmpq+strideq*2], m5 ; q0 + mova [tmpq+stride3q ], m6 ; q1 +%else + TRANSPOSE_8x4_AND_WRITE_4x16 +%endif +%endif +%endmacro + +INIT_YMM avx2 +cglobal lpf_v_sb_y_16bpc, 6, 12, 16, 32 * 5, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits + mov r6d, r7m + lea r11, [pw_4] + shr r6d, 11 ; is_12bpc + lea r11, [r11+r6*4] + mov wd, wm + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + mov mask_bitsd, 0xf + mova m12, [pb_mask] + +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + jz .no_flat16 + + FILTER 16, v + jmp .end + +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + + FILTER 8, v + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .end + + call .v4 + +.end: + pslld m12, 4 + add lq, 16 + add dstq, 32 + shl mask_bitsd, 4 + sub wd, 4 + jg .loop + RET +ALIGN function_align +.v4: + FILTER 4, v + ret + +INIT_YMM avx2 +cglobal lpf_h_sb_y_16bpc, 6, 12, 16, 32 * 15, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp, mask_bits + mov r6d, r7m + lea r11, [pw_4] + shr r6d, 11 ; is_12bpc + lea r11, [r11+r6*4] + mov hd, hm + shl l_strideq, 2 + sub lq, 4 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] + mov mask_bitsd, 0xf + mova m12, [pb_mask] + +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + jz .no_flat16 + + FILTER 16, h + jmp .end + +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + + FILTER 8, h + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .no_filter + + call .h4 + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] + lea dstq, [dstq+strideq*8] +.end: + pslld m12, 4 + lea lq, [lq+l_strideq*4] + shl mask_bitsd, 4 + sub hd, 4 + jg .loop + RET +ALIGN function_align +.h4: + FILTER 4, h + ret + +INIT_YMM avx2 +cglobal lpf_v_sb_uv_16bpc, 6, 12, 16, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits + mov r6d, r7m + lea r11, [pw_4] + shr r6d, 11 ; is_12bpc + lea r11, [r11+r6*4] + mov wd, wm + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + mov mask_bitsd, 0xf + mova m12, [pb_mask] + +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + + FILTER 6, v + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .end + + call mangle(private_prefix %+ _lpf_v_sb_y_16bpc_avx2).v4 + +.end: + pslld m12, 4 + add lq, 16 + add dstq, 32 + shl mask_bitsd, 4 + sub wd, 4 + jg .loop + RET + +INIT_YMM avx2 +cglobal lpf_h_sb_uv_16bpc, 6, 12, 16, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp, mask_bits + mov r6d, r7m + lea r11, [pw_4] + shr r6d, 11 ; is_12bpc + lea r11, [r11+r6*4] + mov hd, hm + shl l_strideq, 2 + sub lq, 4 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] + mov mask_bitsd, 0xf + mova m12, [pb_mask] + +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + + FILTER 6, h + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .no_filter + + call mangle(private_prefix %+ _lpf_h_sb_y_16bpc_avx2).h4 + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] + lea dstq, [dstq+strideq*8] +.end: + pslld m12, 4 + lea lq, [lq+l_strideq*4] + shl mask_bitsd, 4 + sub hd, 4 + jg .loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,912 @@ +; Copyright © 2022, VideoLAN and dav1d authors +; Copyright © 2022, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +l_shuf_v: times 2 db 0, 32 +pw_1: times 2 dw 1 + times 2 db 4, 36 +pw_3: times 2 dw 3 + times 2 db 8, 40 +pw_4: times 2 dw 4 + times 2 db 12, 44 +pw_16: times 2 dw 16 + times 2 db 16, 48 +pw_4096: times 2 dw 4096 + times 2 db 20, 52 +pw_16384: times 2 dw 16384 + times 2 db 24, 56 +pw_32767: times 2 dw 32767 + times 2 db 28, 60 + times 2 dw 0 +filter_mask: dd 1, 2, 4, 8, 16, 32, 64,128 +stride_mul: dd 0, 1, 8, 9, 16, 17, 24, 25 +l_shuf_h: db 4, -1, 4, -1, 4, -1, 4, -1, 12, -1, 12, -1, 12, -1, 12, -1 +clip_max: dw 511, 511, 2047, 2047 +clip_min: dw -512, -512, -2048, -2048 + +SECTION .text + +%macro TRANSPOSE8X8W 9 ; src/dst[1-8], tmp + punpckhwd m%9, m%5, m%6 + punpcklwd m%5, m%6 + punpckhwd m%6, m%1, m%2 + punpcklwd m%1, m%2 + punpckhwd m%2, m%7, m%8 + punpcklwd m%7, m%8 + punpckhwd m%8, m%3, m%4 + punpcklwd m%3, m%4 + punpckhdq m%4, m%1, m%3 + punpckldq m%1, m%3 + punpckldq m%3, m%5, m%7 + punpckhdq m%5, m%7 + punpckhdq m%7, m%6, m%8 + punpckldq m%6, m%8 + punpckldq m%8, m%9, m%2 + punpckhdq m%9, m%2 + punpckhqdq m%2, m%1, m%3 + punpcklqdq m%1, m%3 + punpcklqdq m%3, m%4, m%5 + punpckhqdq m%4, m%5 + punpcklqdq m%5, m%6, m%8 + punpckhqdq m%6, m%8 + punpckhqdq m%8, m%7, m%9 + punpcklqdq m%7, m%9 +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] +%ifidn %2, v +%if %1 == 16 + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1 ] + mova m1, [tmpq+strideq*2 ] ; p5 + mova m2, [tmpq+stride3q ] ; p4 + mova m3, [tmpq+strideq*4 ] ; p3 + mova m4, [tmpq+stride5q ] ; p2 +%elif %1 == 6 || %1 == 8 + lea tmpq, [dstq+mstrideq*4] +%if %1 == 8 + mova m3, [tmpq+strideq*0 ] +%endif + mova m4, [tmpq+strideq*1 ] +%endif + mova m5, [dstq+mstrideq*2] ; p1 + mova m6, [dstq+mstrideq*1] ; p0 + mova m7, [dstq+strideq*0 ] ; q0 + mova m8, [dstq+strideq*1 ] ; q1 +%if %1 != 4 + mova m9, [dstq+strideq*2 ] ; q2 +%endif +%if %1 == 8 || %1 == 16 + mova m10, [dstq+stride3q ] ; q3 +%endif +%if %1 == 16 + mova m11, [dstq+strideq*4 ] ; q4 + mova m22, [dstq+stride5q ] ; q5 + mova m23, [dstq+stride3q*2] +%endif +%else ; h +%if %1 == 16 + movu ym16, [dstq+strideq*0 -16] + movu ym17, [dstq+strideq*1 -16] + movu ym18, [dstq+strideq*2 -16] + movu ym19, [dstq+stride3q -16] + movu ym20, [dstq+strideq*4 -16] + movu ym22, [dstq+stride5q -16] + movu ym23, [dstq+stride3q*2-16] + movu ym28, [dstq+stride7q -16] + lea tmpq, [dstq+strideq*8 -16] + vinserti32x8 m7, m16, [tmpq+strideq*0 ], 1 + vinserti32x8 m8, m17, [tmpq+strideq*1 ], 1 + vinserti32x8 m9, m18, [tmpq+strideq*2 ], 1 + vinserti32x8 m10, m19, [tmpq+stride3q ], 1 + vinserti32x8 m11, m20, [tmpq+strideq*4 ], 1 + vinserti32x8 m22, m22, [tmpq+stride5q ], 1 + vinserti32x8 m23, m23, [tmpq+stride3q*2], 1 + vinserti32x8 m28, m28, [tmpq+stride7q ], 1 + lea tmpq, [tmpq+strideq*8] + TRANSPOSE8X8W 7, 8, 9, 10, 11, 22, 23, 28, 27 + movu ym16, [tmpq+strideq*0 ] + movu ym17, [tmpq+strideq*1 ] + movu ym18, [tmpq+strideq*2 ] + movu ym19, [tmpq+stride3q ] + movu ym24, [tmpq+strideq*4 ] + movu ym25, [tmpq+stride5q ] + movu ym26, [tmpq+stride3q*2] + movu ym20, [tmpq+stride7q ] + lea tmpq, [tmpq+strideq*8] + vinserti32x8 m0, m16, [tmpq+strideq*0 ], 1 + vinserti32x8 m1, m17, [tmpq+strideq*1 ], 1 + vinserti32x8 m2, m18, [tmpq+strideq*2 ], 1 + vinserti32x8 m3, m19, [tmpq+stride3q ], 1 + vinserti32x8 m4, m24, [tmpq+strideq*4 ], 1 + vinserti32x8 m5, m25, [tmpq+stride5q ], 1 + vinserti32x8 m6, m26, [tmpq+stride3q*2], 1 + vinserti32x8 m20, m20, [tmpq+stride7q ], 1 + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 20, 27 + vshufi32x4 m27, m7, m0, q2020 + vshufi32x4 m7, m0, q3131 + vshufi32x4 m0, m8, m1, q2020 + vshufi32x4 m8, m1, q3131 + vshufi32x4 m1, m9, m2, q2020 + vshufi32x4 m9, m2, q3131 + vshufi32x4 m2, m10, m3, q2020 + vshufi32x4 m10, m3, q3131 + vshufi32x4 m3, m11, m4, q2020 + vshufi32x4 m11, m4, q3131 + vshufi32x4 m4, m22, m5, q2020 + vshufi32x4 m22, m5, q3131 + vshufi32x4 m5, m23, m6, q2020 + vshufi32x4 m23, m6, q3131 + vshufi32x4 m6, m28, m20, q2020 + vshufi32x4 m28, m20, q3131 +%elif %1 == 6 || %1 == 8 +%if %1 == 8 + sub dstq, 8 + movu xm16, [dstq+strideq*0 ] + movu xm17, [dstq+strideq*1 ] + movu xm18, [dstq+strideq*2 ] + movu xm19, [dstq+stride3q ] + movu xm24, [dstq+strideq*4 ] + movu xm25, [dstq+stride5q ] + movu xm26, [dstq+stride3q*2] + movu xm27, [dstq+stride7q ] + lea tmpq, [dstq+strideq*8 ] + vinserti128 ym16, [tmpq+strideq*0 ], 1 + vinserti128 ym17, [tmpq+strideq*1 ], 1 + vinserti128 ym18, [tmpq+strideq*2 ], 1 + vinserti128 ym19, [tmpq+stride3q ], 1 + vinserti128 ym24, [tmpq+strideq*4 ], 1 + vinserti128 ym25, [tmpq+stride5q ], 1 + vinserti128 ym26, [tmpq+stride3q*2], 1 + vinserti128 ym27, [tmpq+stride7q ], 1 + lea tmpq, [tmpq+strideq*8 ] + vinserti32x4 m10, m16, [tmpq+strideq*0 ], 2 + vinserti32x4 m8, m17, [tmpq+strideq*1 ], 2 + vinserti32x4 m5, m18, [tmpq+strideq*2 ], 2 + vinserti32x4 m7, m19, [tmpq+stride3q ], 2 + vinserti32x4 m2, m24, [tmpq+strideq*4 ], 2 + vinserti32x4 m9, m25, [tmpq+stride5q ], 2 + vinserti32x4 m3, m26, [tmpq+stride3q*2], 2 + vinserti32x4 m4, m27, [tmpq+stride7q ], 2 + lea tmpq, [tmpq+strideq*8 ] + vinserti32x4 m10, [tmpq+strideq*0 ], 3 + vinserti32x4 m8, [tmpq+strideq*1 ], 3 + vinserti32x4 m5, [tmpq+strideq*2 ], 3 + vinserti32x4 m7, [tmpq+stride3q ], 3 + vinserti32x4 m2, [tmpq+strideq*4 ], 3 + vinserti32x4 m9, [tmpq+stride5q ], 3 + vinserti32x4 m3, [tmpq+stride3q*2], 3 + vinserti32x4 m4, [tmpq+stride7q ], 3 +%else ; %1 == 6 + movu xm16, [dstq+strideq*0-8] + movu xm17, [dstq+strideq*1-8] + movu xm18, [dstq+strideq*2-8] + movu xm19, [dstq+stride3q -8] + lea tmpq, [dstq+strideq*4-8] + movu xm2, [tmpq+strideq*0] + movu xm9, [tmpq+strideq*1] + movu xm3, [tmpq+strideq*2] + movu xm4, [tmpq+stride3q ] + lea tmpq, [tmpq+strideq*4] + vinserti128 ym16, [tmpq+strideq*0], 1 + vinserti128 ym17, [tmpq+strideq*1], 1 + vinserti128 ym18, [tmpq+strideq*2], 1 + vinserti128 ym19, [tmpq+stride3q ], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 ym2, [tmpq+strideq*0], 1 + vinserti128 ym9, [tmpq+strideq*1], 1 + vinserti128 ym3, [tmpq+strideq*2], 1 + vinserti128 ym4, [tmpq+stride3q ], 1 + lea tmpq, [tmpq+strideq*4] + vinserti32x4 m10, m16, [tmpq+strideq*0], 2 + vinserti32x4 m8, m17, [tmpq+strideq*1], 2 + vinserti32x4 m5, m18, [tmpq+strideq*2], 2 + vinserti32x4 m7, m19, [tmpq+stride3q ], 2 + lea tmpq, [tmpq+strideq*4] + vinserti32x4 m2, [tmpq+strideq*0], 2 + vinserti32x4 m9, [tmpq+strideq*1], 2 + vinserti32x4 m3, [tmpq+strideq*2], 2 + vinserti32x4 m4, [tmpq+stride3q ], 2 + lea tmpq, [tmpq+strideq*4] + vinserti32x4 m10, [tmpq+strideq*0], 3 + vinserti32x4 m8, [tmpq+strideq*1], 3 + vinserti32x4 m5, [tmpq+strideq*2], 3 + vinserti32x4 m7, [tmpq+stride3q ], 3 + lea tmpq, [tmpq+strideq*4] + vinserti32x4 m2, [tmpq+strideq*0], 3 + vinserti32x4 m9, [tmpq+strideq*1], 3 + vinserti32x4 m3, [tmpq+strideq*2], 3 + vinserti32x4 m4, [tmpq+stride3q ], 3 +%endif + punpcklwd m6, m10, m8 + punpckhwd m10, m8 + punpcklwd m8, m5, m7 + punpckhwd m5, m7 + punpcklwd m7, m2, m9 + punpckhwd m2, m9 + punpcklwd m9, m3, m4 + punpckhwd m3, m4 + punpckldq m4, m6, m8 + punpckhdq m6, m8 + punpckldq m8, m10, m5 + punpckhdq m10, m5 + punpckldq m5, m7, m9 + punpckhdq m7, m9 + punpckldq m9, m2, m3 + punpckhdq m2, m3 +%if %1 == 8 + punpcklqdq m3, m4, m5 +%endif + punpckhqdq m4, m5 + punpcklqdq m5, m6, m7 + punpckhqdq m6, m7 + punpcklqdq m7, m8, m9 + punpckhqdq m8, m9 + punpcklqdq m9, m10, m2 +%if %1 == 8 + punpckhqdq m10, m2 +%endif +%else ; %1 == 4 + kxnorb k1, k1, k1 + kmovb k2, k1 + vpgatherdq m7{k1}, [dstq+ym12-4] + lea tmpq, [dstq+strideq*2-4] + kmovb k1, k2 + vpgatherdq m4{k2}, [tmpq+ym12] + lea tmpq, [tmpq+strideq*2] + kmovb k2, k1 + vpgatherdq m5{k1}, [tmpq+ym12] + lea tmpq, [tmpq+strideq*2] + vpgatherdq m6{k2}, [tmpq+ym12] + punpcklwd m8, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpcklwd m6, m8, m7 + punpckhwd m8, m7 + punpcklwd m7, m4, m5 + punpckhwd m4, m5 + punpcklqdq m5, m6, m7 + punpckhqdq m6, m7 + punpcklqdq m7, m8, m4 + punpckhqdq m8, m4 +%endif +%endif + + ; load L/E/I/H +%ifidn %2, v + movu ym16, [lq+l_strideq*1] + movsldup m17, [l_shuf_v] + vptestnmb k1, ym16, ym16 + vmovdqu8 ym16{k1}, [lq+l_strideq*0] ; l[x][] ? l[x][] : l[x-stride][] + vpermb m16, m17, m16 ; l[x][1] +%else + movq xm16, [lq+l_strideq*0] + movq xm17, [lq+l_strideq*1] + vinserti128 ym16, [lq+l_strideq*2], 1 + vinserti128 ym17, [lq+l_stride3q ], 1 + lea tmpq, [lq+l_strideq*4] + vinserti32x4 m16, [tmpq+l_strideq*0], 2 + vinserti32x4 m17, [tmpq+l_strideq*1], 2 + vinserti32x4 m16, [tmpq+l_strideq*2], 3 + vinserti32x4 m17, [tmpq+l_stride3q ], 3 + punpcklqdq m16, m17 + vbroadcasti32x4 m17, [l_shuf_h] + vptestnmb k1, m16, m16 + vpalignr m16{k1}, m16, 12 + pshufb m16, m17 ; l[x][1] +%endif + vpbroadcastd m20, [pw_32767] + psubw m17, m5, m6 ; p1-p0 + psubw m18, m7, m8 ; q1-q0 + vptestmw k1, m16, m16 ; L + pabsw m17, m17 + pabsw m18, m18 + vpmaxuw m20{k1}, m17, m18 + vpbroadcastw m17, [lutq+136] + psrlw m18, m16, [lutq+128] + vpbroadcastd m19, [pw_1] + pminuw m18, m17 + psrlw m17, m16, 4 ; H + paddw m16, m16 + pmaxuw m18, m19 ; I + vpaddd m16, [pw_4] {1to16} + paddw m16, m18 ; E + REPX {pmullw x, m13}, m17, m18, m16 + vpcmpw k4, m20, m17, 6 ; hev +%if %1 != 4 + psubw m19, m4, m5 ; p2-p1 + pabsw m19, m19 +%if %1 == 8 || %1 == 16 + psubw m17, m3, m4 ; p3-p2 + pabsw m17, m17 + pmaxuw m19, m17 + psubw m17, m9, m10 ; q3-q2 + pabsw m17, m17 + pmaxuw m19, m17 +%endif + psubw m17, m9, m8 ; q2-q1 + pabsw m17, m17 + pmaxuw m19, m17 +%if %1 == 16 + vpbroadcastd ym17, [maskq+4] + vpord ym17, [maskq+8] {1to8} + vptestmd k1, ym17, ym21 +%else + vptestmd k1, ym21, [maskq+4] {1to8} +%endif + pmaxuw m19, m20 + psubw m17, m4, m6 ; p2-p0 + pabsw m17, m17 + pmaxuw m17, m20 + vmovdqa64 m20{k1}, m19 ; only apply fm-wide to wd>4 blocks +%if %1 == 8 || %1 == 16 + psubw m19, m3, m6 ; p3-p0 + pabsw m19, m19 + pmaxuw m17, m19 + psubw m19, m7, m10 ; q3-q0 + pabsw m19, m19 + pmaxuw m17, m19 +%endif + psubw m19, m7, m9 ; q2-q0 + pabsw m19, m19 + pmaxuw m17, m19 +%endif + vpcmpw k1, m20, m18, 2 + psubw m18, m5, m8 ; p1-q1 + psubw m19, m6, m7 ; p0-q0 + pabsw m18, m18 + pabsw m19, m19 + psrlw m18, 1 + paddw m19, m19 + paddw m18, m19 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + vpcmpw k1{k1}, m18, m16, 2 ; abs(p0-q0)*2+(abs(p1-q1)>>1) <= E +%if %1 != 4 + vpcmpw k2{k1}, m17, m13, 2 ; flat8in +%endif +%if %1 == 16 + psubw m20, m0, m6 + psubw m16, m1, m6 + pabsw m20, m20 + psubw m17, m2, m6 + pabsw m16, m16 + psubw m18, m11, m7 + pabsw m17, m17 + psubw m19, m22, m7 + pabsw m18, m18 + pmaxuw m20, m16 + psubw m16, m23, m7 + pabsw m19, m19 + pmaxuw m17, m18 + pabsw m16, m16 + vpandd ym18, ym21, [maskq+8] {1to8} + pmaxuw m20, m17 + pmaxuw m19, m16 + pcmpeqd ym16, ym21, ym18 + vpternlogd ym18, ym21, [maskq+4] {1to8}, 0xc8 + pmaxuw m20, m19 + pcmpeqd ym17, ym21, ym18 + vpternlogd ym18, ym21, [maskq+0] {1to8}, 0xc8 + vpcmpw k3{k2}, m20, m13, 2 ; flat8in & flat8out + pcmpeqd ym18, ym21 + vptestmb k3{k3}, ym16, ym16 ; flat8 & fm + vptestmb k2{k2}, ym17, ym17 ; flat8in + vptestmb k1{k1}, ym18, ym18 + kandnd k1, k2, k1 ; fm & !flat8 & !flat16 + kandnd k2, k3, k2 ; flat8 & !flat16 +%elif %1 == 6 || %1 == 8 + vpandd ym17, ym21, [maskq+4] {1to8} + pcmpeqd ym16, ym21, ym17 + vpternlogd ym17, ym21, [maskq+0] {1to8}, 0xc8 + pcmpeqd ym17, ym21 + vptestmb k2{k2}, ym16, ym16 ; flat8 & fm + vptestmb k1{k1}, ym17, ym17 + kandnd k1, k2, k1 ; fm & !flat8 +%else ; %1 == 4 + vpandd ym16, ym21, [maskq+0] {1to8} + pcmpeqd ym16, ym21 + vptestmb k1{k1}, ym16, ym16 +%endif + + ; short filter + psubw m16, m7, m6 + vpbroadcastd m17, [pw_3] + paddw m18, m16, m16 + paddw m18, m16 + psubw m16, m5, m8 ; iclip_diff(p1-q1) + pminsw m16, m14 + vpmaxsw m16{k4}{z}, m15 ; f=iclip_diff(p1-q1)&hev + knotd k4, k4 ; !hev + paddw m16, m18 ; f=iclip_diff(3*(q0-p0)+f) + vpbroadcastd m18, [pw_4] + pminsw m16, m14 + vpmaxsw m16{k1}{z}, m15 ; f&=fm + paddw m17, m16 + paddw m16, m18 + vpbroadcastd m18, [pw_16384] + pminsw m17, m14 + pminsw m16, m14 + psraw m17, 3 ; f2 + psraw m16, 3 ; f1 + paddw m6, m17 + psubw m7, m16 + vpmulhrsw m16{k4}{z}, m18 ; (f=(f1+1)>>1) & !hev + psubw m17, m14, m15 ; 1023 or 4095 + pxor m18, m18 + paddw m5, m16 + psubw m8, m16 + REPX {pminsw x, m17}, m6, m7, m5, m8 + REPX {pmaxsw x, m18}, m6, m7, m5, m8 + +%if %1 == 16 ; flat16 filter + vpaddd m19, m0, [pw_1] {1to16} + paddw m16, m1, m2 ; p5+p4 + paddw m26, m1, m6 ; p5+p0 + paddw m24, m2, m7 ; p4+q0 + paddw m16, m4 ; p5+p4+p3 + paddw m17, m3, m5 ; p2+p1 + psllw m19, 3 + paddw m16, m26 ; p5*2+p4+p3+p0 + paddw m17, m24 ; p4+p2+p1+q0 + psubw m19, m0 ; p6*7+8 + paddw m16, m17 ; p5*2+p4*2+p3+p2+p1+q0 + paddw m18, m3, m8 + paddw m19, m16 ; p6*7+p5+p4*2+p3+p2+p1+p0+q0 + paddw m25, m1, m0 + paddw m16, m0, m0 + psrlw m1{k3}, m19, 4 + paddw m19, m18 + psubw m19, m16 ; +p3+q1-p6*2 + paddw m16, m2, m0 + psrlw m2{k3}, m19, 4 + psubw m19, m25 + paddw m25, m4, m9 + paddw m20, m10, m5 + paddw m19, m25 ; +p2+q2-p6-p5 + paddw m17, m0, m3 + psubw m16, m20, m16 + psrlw m3{k3}, m19, 4 + paddw m19, m16 ; +p1+q3-p6-p4 + paddw m16, m11, m6 + psubw m16, m17 + paddw m17, m0, m4 + psrlw m4{k3}, m19, 4 + paddw m19, m16 ; +p0+q4-p6-p3 + paddw m16, m22, m7 + psubw m16, m17 + paddw m17, m0, m5 + psrlw m5{k3}, m19, 4 + paddw m19, m16 ; +q0+q5-p6-p2 + paddw m16, m23, m8 + psrlw m6{k3}, m19, 4 + psubw m16, m17 + paddw m19, m16 ; +q1+q6-p6-p1 + paddw m16, m23, m9 + psrlw m7{k3}, m19, 4 + psubw m16, m26 + paddw m19, m16 ; +q2+q6-p5-p0 + paddw m16, m23, m10 + psrlw m8{k3}, m19, 4 + psubw m16, m24 + paddw m19, m16 ; +q3+q6-p4-p0 + paddw m16, m23, m11 + psrlw m9{k3}, m19, 4 + psubw m16, m18 + paddw m19, m16 ; +q4+q6-p3-q1 + paddw m16, m23, m22 + psrlw m10{k3}, m19, 4 + psubw m16, m25 + paddw m19, m16 ; +q5+q6-p2-q2 + paddw m16, m23, m23 + psrlw m11{k3}, m19, 4 + psubw m16, m20 + paddw m19, m16 ; +q6*2-p1-q3 + psrlw m22{k3}, m19, 4 +%endif +%if %1 == 8 || %1 == 16 ; flat8 filter + vpbroadcastd m20, [pw_4096] + paddw m16, m3, m4 ; p3+p2 + paddw m19, m5, m6 ; p1+p0 + paddw m17, m16, m16 ; 2*(p3+p2) + paddw m19, m3 ; p1+p0+p3 + paddw m17, m7 ; 2*(p3+p2)+q0 + paddw m19, m17 ; 3*p3+2*p2+p1+p0+q0 + paddw m18, m4, m7 + pmulhrsw m4{k2}, m19, m20 + psubw m19, m16 + paddw m17, m5, m8 + paddw m16, m3, m5 + paddw m19, m17 + pmulhrsw m5{k2}, m19, m20 + psubw m19, m16 + paddw m16, m6, m9 + paddw m19, m16 + paddw m16, m3, m6 + pmulhrsw m6{k2}, m19, m20 + paddw m19, m10 + psubw m16, m7, m16 + paddw m19, m16 + psubw m16, m10, m18 + pmulhrsw m7{k2}, m19, m20 + paddw m16, m8 + paddw m19, m16 + psubw m16, m10, m17 + pmulhrsw m8{k2}, m19, m20 + paddw m16, m9 + paddw m19, m16 + pmulhrsw m9{k2}, m19, m20 +%elif %1 == 6 ; flat6 filter + vpbroadcastd m10, [pw_4096] + paddw m2, m5, m6 + paddw m0, m4, m7 + paddw m1, m2, m4 ; p2+p1+p0 + paddw m3, m4, m4 + paddw m1, m1 + paddw m4, m5 + paddw m1, m0 ; p2+2*(p2+p1+p0)+q0 + psubw m3, m7, m3 + pmulhrsw m5{k2}, m1, m10 + paddw m3, m8 + psubw m4, m8, m4 + paddw m1, m3 + pmulhrsw m6{k2}, m1, m10 + paddw m4, m9 + paddw m9, m9 + paddw m1, m4 + pmulhrsw m7{k2}, m1, m10 + psubw m9, m2 + paddw m1, m9 + pmulhrsw m8{k2}, m1, m10 +%endif + +%ifidn %2, v +%if %1 == 16 + mova [tmpq+strideq*2 ], m1 ; p5 + mova [tmpq+stride3q ], m2 ; p4 + mova [tmpq+strideq*4 ], m3 ; p3 + mova [tmpq+stride5q ], m4 ; p2 +%elif %1 == 8 + mova [tmpq+strideq*1 ], m4 ; p2 +%endif + mova [dstq+mstrideq*2], m5 ; p1 + mova [dstq+mstrideq ], m6 ; p0 + mova [dstq+strideq*0 ], m7 ; q0 + mova [dstq+strideq*1 ], m8 ; q1 +%if %1 == 8 || %1 == 16 + mova [dstq+strideq*2 ], m9 ; q2 +%endif +%if %1 == 16 + mova [dstq+stride3q ], m10 ; q3 + mova [dstq+strideq*4 ], m11 ; q4 + mova [dstq+stride5q ], m22 ; q5 +%endif +%else +%if %1 == 16 + TRANSPOSE8X8W 27, 0, 1, 2, 3, 4, 5, 6, 20 + TRANSPOSE8X8W 7, 8, 9, 10, 11, 22, 23, 28, 20 + mova [dstq+strideq*0 -16], xm27 + mova [dstq+strideq*0 ], xm7 + mova [dstq+strideq*1 -16], xm0 + mova [dstq+strideq*1 ], xm8 + mova [dstq+strideq*2 -16], xm1 + mova [dstq+strideq*2 ], xm9 + mova [dstq+stride3q -16], xm2 + mova [dstq+stride3q ], xm10 + mova [dstq+strideq*4 -16], xm3 + mova [dstq+strideq*4 ], xm11 + mova [dstq+stride5q -16], xm4 + mova [dstq+stride5q ], xm22 + mova [dstq+stride3q*2-16], xm5 + mova [dstq+stride3q*2 ], xm23 + mova [dstq+stride7q -16], xm6 + mova [dstq+stride7q ], xm28 + lea dstq, [dstq+strideq*8] + vextracti128 [dstq+strideq*0 -16], ym27, 1 + vextracti128 [dstq+strideq*0 ], ym7, 1 + vextracti128 [dstq+strideq*1 -16], ym0, 1 + vextracti128 [dstq+strideq*1 ], ym8, 1 + vextracti128 [dstq+strideq*2 -16], ym1, 1 + vextracti128 [dstq+strideq*2 ], ym9, 1 + vextracti128 [dstq+stride3q -16], ym2, 1 + vextracti128 [dstq+stride3q ], ym10, 1 + vextracti128 [dstq+strideq*4 -16], ym3, 1 + vextracti128 [dstq+strideq*4 ], ym11, 1 + vextracti128 [dstq+stride5q -16], ym4, 1 + vextracti128 [dstq+stride5q ], ym22, 1 + vextracti128 [dstq+stride3q*2-16], ym5, 1 + vextracti128 [dstq+stride3q*2 ], ym23, 1 + vextracti128 [dstq+stride7q -16], ym6, 1 + vextracti128 [dstq+stride7q ], ym28, 1 + lea dstq, [dstq+strideq*8] + vextracti32x4 [dstq+strideq*0 -16], m27, 2 + vextracti32x4 [dstq+strideq*0 ], m7, 2 + vextracti32x4 [dstq+strideq*1 -16], m0, 2 + vextracti32x4 [dstq+strideq*1 ], m8, 2 + vextracti32x4 [dstq+strideq*2 -16], m1, 2 + vextracti32x4 [dstq+strideq*2 ], m9, 2 + vextracti32x4 [dstq+stride3q -16], m2, 2 + vextracti32x4 [dstq+stride3q ], m10, 2 + vextracti32x4 [dstq+strideq*4 -16], m3, 2 + vextracti32x4 [dstq+strideq*4 ], m11, 2 + vextracti32x4 [dstq+stride5q -16], m4, 2 + vextracti32x4 [dstq+stride5q ], m22, 2 + vextracti32x4 [dstq+stride3q*2-16], m5, 2 + vextracti32x4 [dstq+stride3q*2 ], m23, 2 + vextracti32x4 [dstq+stride7q -16], m6, 2 + vextracti32x4 [dstq+stride7q ], m28, 2 + lea dstq, [dstq+strideq*8] + vextracti32x4 [dstq+strideq*0 -16], m27, 3 + vextracti32x4 [dstq+strideq*0 ], m7, 3 + vextracti32x4 [dstq+strideq*1 -16], m0, 3 + vextracti32x4 [dstq+strideq*1 ], m8, 3 + vextracti32x4 [dstq+strideq*2 -16], m1, 3 + vextracti32x4 [dstq+strideq*2 ], m9, 3 + vextracti32x4 [dstq+stride3q -16], m2, 3 + vextracti32x4 [dstq+stride3q ], m10, 3 + vextracti32x4 [dstq+strideq*4 -16], m3, 3 + vextracti32x4 [dstq+strideq*4 ], m11, 3 + vextracti32x4 [dstq+stride5q -16], m4, 3 + vextracti32x4 [dstq+stride5q ], m22, 3 + vextracti32x4 [dstq+stride3q*2-16], m5, 3 + vextracti32x4 [dstq+stride3q*2 ], m23, 3 + vextracti32x4 [dstq+stride7q -16], m6, 3 + vextracti32x4 [dstq+stride7q ], m28, 3 +%elif %1 == 8 + TRANSPOSE8X8W 3, 4, 5, 6, 7, 8, 9, 10, 2 + movu [dstq+strideq*0 ], xm3 + movu [dstq+strideq*1 ], xm4 + movu [dstq+strideq*2 ], xm5 + movu [dstq+stride3q ], xm6 + movu [dstq+strideq*4 ], xm7 + movu [dstq+stride5q ], xm8 + movu [dstq+stride3q*2], xm9 + movu [dstq+stride7q ], xm10 + lea dstq, [dstq+strideq*8] + vextracti128 [dstq+strideq*0 ], ym3, 1 + vextracti128 [dstq+strideq*1 ], ym4, 1 + vextracti128 [dstq+strideq*2 ], ym5, 1 + vextracti128 [dstq+stride3q ], ym6, 1 + vextracti128 [dstq+strideq*4 ], ym7, 1 + vextracti128 [dstq+stride5q ], ym8, 1 + vextracti128 [dstq+stride3q*2], ym9, 1 + vextracti128 [dstq+stride7q ], ym10, 1 + lea dstq, [dstq+strideq*8] + vextracti32x4 [dstq+strideq*0 ], m3, 2 + vextracti32x4 [dstq+strideq*1 ], m4, 2 + vextracti32x4 [dstq+strideq*2 ], m5, 2 + vextracti32x4 [dstq+stride3q ], m6, 2 + vextracti32x4 [dstq+strideq*4 ], m7, 2 + vextracti32x4 [dstq+stride5q ], m8, 2 + vextracti32x4 [dstq+stride3q*2], m9, 2 + vextracti32x4 [dstq+stride7q ], m10, 2 + lea dstq, [dstq+strideq*8] + vextracti32x4 [dstq+strideq*0 ], m3, 3 + vextracti32x4 [dstq+strideq*1 ], m4, 3 + vextracti32x4 [dstq+strideq*2 ], m5, 3 + vextracti32x4 [dstq+stride3q ], m6, 3 + vextracti32x4 [dstq+strideq*4 ], m7, 3 + vextracti32x4 [dstq+stride5q ], m8, 3 + vextracti32x4 [dstq+stride3q*2], m9, 3 + vextracti32x4 [dstq+stride7q ], m10, 3 + lea dstq, [dstq+strideq*8+8] +%else ; %1 == 4 || %1 == 6 + punpcklwd m9, m5, m6 + punpckhwd m5, m6 + kxnorb k1, k1, k1 + punpcklwd m6, m7, m8 + punpckhwd m7, m8 + kmovb k2, k1 + punpckldq m8, m9, m6 + vpscatterdq [dstq+ym12-4]{k1}, m8 + punpckhdq m9, m6 + lea tmpq, [dstq+strideq*2-4] + kmovb k1, k2 + vpscatterdq [tmpq+ym12]{k2}, m9 + punpckldq m6, m5, m7 + lea tmpq, [tmpq+strideq*2] + kmovb k2, k1 + vpscatterdq [tmpq+ym12]{k1}, m6 + punpckhdq m5, m7 + lea tmpq, [tmpq+strideq*2] + vpscatterdq [tmpq+ym12]{k2}, m5 +%endif +%endif +%endmacro + +INIT_ZMM avx512icl +cglobal lpf_v_sb_y_16bpc, 6, 12, 26, dst, stride, mask, l, l_stride, \ + lut, w, stride3, mstride, tmp, \ + mask_bits, stride5 +%define base tmpq-filter_mask + SWAP 12, 26 ; avoids clobbering xmm10 on WIN64 + lea tmpq, [filter_mask] + mov r6d, r7m ; bitdepth_max + lea stride3q, [strideq*3] + shl l_strideq, 2 + lea stride5q, [strideq*5] + shr r6d, 11 ; is_12bpc + mova ym21, [base+filter_mask] + mov mstrideq, strideq + vpbroadcastd m13, [base+pw_4+r6*8] + mov mask_bitsd, 0xff + vpbroadcastd m14, [base+clip_max+r6*4] + sub lq, l_strideq + vpbroadcastd m15, [base+clip_min+r6*4] + neg mstrideq + mov wd, wm +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + jz .no_flat16 + FILTER 16, v + jmp .end +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + FILTER 8, v + jmp .end +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .end + call .v4 +.end: + shl mask_bitsd, 8 + add dstq, 64 + pslld ym21, 8 + add lq, 32 + sub wd, 8 + jg .loop + RET +ALIGN function_align +.v4: ; called by both luma and chroma + FILTER 4, v + ret + +cglobal lpf_h_sb_y_16bpc, 6, 13, 29, dst, stride, mask, l, l_stride, \ + lut, h, stride3, l_stride3, tmp, \ + mask_bits, stride5, stride7 + lea tmpq, [filter_mask] + mov r6d, r7m ; bitdepth_max + lea stride3q, [strideq*3] + vpbroadcastd ym12, strided + shl l_strideq, 2 + lea stride5q, [strideq*5] + shr r6d, 11 ; is_12bpc + pmulld ym12, [base+stride_mul] + lea stride7q, [strideq+stride3q*2] + mova ym21, [base+filter_mask] + mov mask_bitsd, 0xff + vpbroadcastd m13, [base+pw_4+r6*8] + sub lq, 4 + vpbroadcastd m14, [base+clip_max+r6*4] + lea l_stride3q, [l_strideq*3] + vpbroadcastd m15, [base+clip_min+r6*4] + mov hd, hm +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + jz .no_flat16 + FILTER 16, h + jmp .end +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + FILTER 8, h + jmp .end2 +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .no_filter + call .h4 +.no_filter: + lea dstq, [dstq+stride3q*8] +.end: + lea dstq, [dstq+strideq*8] +.end2: + shl mask_bitsd, 8 + pslld ym21, 8 + lea lq, [lq+l_strideq*8] + sub hd, 8 + jg .loop + RET +ALIGN function_align +.h4: ; called by both luma and chroma + FILTER 4, h + ret + +cglobal lpf_v_sb_uv_16bpc, 6, 11, 22, dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits + lea tmpq, [filter_mask] + mov r6d, r7m ; bitdepth_max + shl l_strideq, 2 + lea stride3q, [strideq*3] + shr r6d, 11 ; is_12bpc + mova ym21, [base+filter_mask] + mov mstrideq, strideq + vpbroadcastd m13, [base+pw_4+r6*8] + mov mask_bitsd, 0xff + vpbroadcastd m14, [base+clip_max+r6*4] + sub lq, l_strideq + vpbroadcastd m15, [base+clip_min+r6*4] + neg mstrideq + mov wd, wm +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + FILTER 6, v + jmp .end +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .end + call mangle(private_prefix %+ _lpf_v_sb_y_16bpc_avx512icl).v4 +.end: + shl mask_bitsd, 8 + add dstq, 64 + pslld ym21, 8 + add lq, 32 + sub wd, 8 + jg .loop + RET + +cglobal lpf_h_sb_uv_16bpc, 6, 11, 22, dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp, mask_bits + lea tmpq, [filter_mask] + mov r6d, r7m ; bitdepth_max + vpbroadcastd ym12, strided + shl l_strideq, 2 + shr r6d, 11 ; is_12bpc + pmulld ym12, [base+stride_mul] + lea stride3q, [strideq*3] + mova ym21, [base+filter_mask] + mov mask_bitsd, 0xff + vpbroadcastd m13, [base+pw_4+r6*8] + sub lq, 4 + vpbroadcastd m14, [base+clip_max+r6*4] + lea l_stride3q, [l_strideq*3] + vpbroadcastd m15, [base+clip_min+r6*4] + mov hd, hm +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + jz .no_flat + FILTER 6, h + jmp .end +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + jz .end + call mangle(private_prefix %+ _lpf_h_sb_y_16bpc_avx512icl).h4 +.end: + lea tmpq, [strideq+stride3q] + shl mask_bitsd, 8 + pslld ym21, 8 + lea dstq, [dstq+tmpq*8] + lea lq, [lq+l_strideq*8] + sub hd, 8 + jg .loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1793 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +%if ARCH_X86_64 +%define PIC_sym(a) a +%else +%define PIC_base $$ +%define PIC_sym(a) pic_regq+a-PIC_base +%endif + +pb_4x1_4x5_4x9_4x13: times 4 db 0, 1 + times 4 db 8, 9 + +pw_1: times 8 dw 1 +pw_2: times 8 dw 2 +pw_3: times 8 dw 3 +; 4 and 16 need to be next to each other since they are used as alternates +; depending on whether bitdepth is 10 or 12 +pw_4: times 8 dw 4 +pw_16: times 8 dw 16 +pw_8: times 8 dw 8 +pw_4096: times 8 dw 4096 + +pb_mask: dd 1, 1, 2, 2 + +SECTION .text + +%if ARCH_X86_32 +%if STACK_ALIGNMENT < 16 +%define extra_stack 2 +%else +%define extra_stack 0 +%endif +%endif + +%macro RELOC_ARGS 2 ; h/v, off +ASSERT ARCH_X86_32 +%if STACK_ALIGNMENT < 16 + mov r5d, [rstk + stack_offset + 4*4 + 4] +%define lstridem [esp+%2+0*gprsize] + mov lstridem, r5d + mov r5d, [rstk + stack_offset + 4*5 + 4] +%define lutm [esp+%2+1*gprsize] + mov lutm, r5d + mov r5d, [rstk + stack_offset + 4*6 + 4] +%ifidn %1, v +%define wm [esp+%2+2*gprsize] + mov wm, r5d + mov r5d, [rstk + stack_offset + 4*3 + 4] +%define lm [esp+%2+3*gprsize] + mov lm, r5d +%else ; %1 == h +%define hm [esp+%2+2*gprsize] + mov hm, r5d +%endif ; %1==v + mov r5d, r7m +%define bdmulm [esp+%2+4*gprsize] + mov bdmulm, r5d +%else +%define lstridem r4m +%define lutm r5m +%ifidn %1, v +%define wm r6m +%define lm r3m +%else +%define hm r6m +%endif +%define bdmulm r7m +%endif ; STACK_ALIGNMENT +%endmacro + +%macro UNRELOC_ARGS 0 +%if ARCH_X86_32 +%undef lm +%undef lstridem +%undef wm +%undef hm +%undef lutm +%endif +%endmacro + +%macro SPLATD 2 + movd %1, %2 + pshufd %1, %1, q0000 +%endmacro + +%macro SPLATW 2 + movd %1, %2 + pshuflw %1, %1, q0000 + punpcklqdq %1, %1 +%endmacro + +; in: out: +; mm%1 a b c d a e i m +; mm%2 e f g h b f j n +; mm%3 i j k l -> c g k o +; mm%4 m n o p d h l p +%macro TRANSPOSE4X4W 5 + punpcklwd m%5, m%1, m%2 + punpckhwd m%1, m%2 + punpcklwd m%2, m%3, m%4 + punpckhwd m%3, m%4 + punpckldq m%4, m%5, m%2 + punpckhdq m%5, m%2 + punpckldq m%2, m%1, m%3 + punpckhdq m%1, m%3 + + SWAP %1, %4 + SWAP %2, %5, %3 +%endmacro + +; in: out: +; m%1 a b c d e f g h a i q y 6 E M U +; m%2 i j k l m n o p b j r z 7 F N V +; m%3 q r s t u v w x c k s 0 8 G O W +; m%4 y z 0 1 2 3 4 5 d l t 1 9 H P X +; m%5 6 7 8 9 A B C D -> e m u 2 A I Q Y +; m%6 E F G H I J K L f n v 3 B J R Z +; m%7 M N O P Q R S T g o w 4 C K S + +; m%8 U V W X Y Z + = h p x 5 D L T = +%if ARCH_X86_64 +%macro TRANSPOSE8X8W 9 + ; m%1 a b c d e f g h a i q y b j r z + ; m%2 i j k l m n o p c k s 0 d l t 1 + ; m%3 q r s t u v w x -> e m u 2 f n v 3 + ; m%4 y z 0 1 2 3 4 5 g o w 4 h p x 5 + TRANSPOSE4X4W %1, %2, %3, %4, %9 + + ; m%5 6 7 8 9 A B C D 6 E M U 7 F N V + ; m%6 E F G H I J K L 8 G O W 9 H P X + ; m%7 M N O P Q R S T -> A I Q Y B J R Z + ; m%8 U V W X Y Z + = C K S + D L T = + TRANSPOSE4X4W %5, %6, %7, %8, %9 + + ; m%1 a i q y b j r z a i q y 6 E M U + ; m%2 c k s 0 d l t 1 b j r z 7 F N V + ; m%3 e m u 2 f n v 3 c k s 0 8 G O W + ; m%4 g o w 4 h p x 5 d l t 1 9 H P X + ; m%5 6 E M U 7 F N V -> e m u 2 A I Q Y + ; m%6 8 G O W 9 H P X f n v 3 B J R Z + ; m%7 A I Q Y B J R Z g o w 4 C K S + + ; m%8 C K S + D L T = h p x 5 D L T = + punpckhqdq m%9, m%1, m%5 + punpcklqdq m%1, m%5 + punpckhqdq m%5, m%2, m%6 + punpcklqdq m%2, m%6 + punpckhqdq m%6, m%3, m%7 + punpcklqdq m%3, m%7 + punpckhqdq m%7, m%4, m%8 + punpcklqdq m%4, m%8 + + SWAP %8, %7, %4, %5, %3, %2, %9 +%endmacro +%else ; x86-32 +; input: 1-7 in registers, 8 in first memory [read-only] +; second memory is scratch, and may overlap with first or third memory +; output: 1-5,7-8 in registers, 6 in third memory [write-only] +%macro TRANSPOSE8X8W 13 ; regs [8x], mem [3x], a/u [in/out alignment [2x] + TRANSPOSE4X4W %1, %2, %3, %4, %8 +%ifnidn %9, "" + mov%12 m%8, %9 +%else + mova m%8, %10 +%endif + mova %10, m%4 + TRANSPOSE4X4W %5, %6, %7, %8, %4 + punpckhqdq m%4, m%1, m%5 + punpcklqdq m%1, m%5 + punpckhqdq m%5, m%2, m%6 + punpcklqdq m%2, m%6 + punpckhqdq m%6, m%3, m%7 + punpcklqdq m%3, m%7 + mova m%7, %10 +%ifnidn %11, "" + mov%13 %11, m%6 +%else + mova %10, m%6 +%endif + punpckhqdq m%6, m%7, m%8 + punpcklqdq m%7, m%8 + + ; 1,4,2,5,3,8,7,6 -> 1,2,3,4,5,6,7,8 + SWAP %2, %4, %5, %3 + SWAP %6, %8 +%endmacro +%endif ; x86-32/64 + +; transpose and write m8-11, everything else is scratch +%macro TRANSPOSE_8x4_AND_WRITE_4x8 5 ; p1, p0, q0, q1, tmp + ; transpose 8x4 + punpcklwd %5, %1, %2 + punpckhwd %1, %2 + punpcklwd %2, %3, %4 + punpckhwd %3, %4 + punpckldq %4, %5, %2 + punpckhdq %5, %2 + punpckldq %2, %1, %3 + punpckhdq %1, %3 + + ; write out + movq [dstq+strideq*0-4], %4 + movhps [dstq+strideq*1-4], %4 + movq [dstq+strideq*2-4], %5 + movhps [dstq+stride3q -4], %5 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], %2 + movhps [dstq+strideq*1-4], %2 + movq [dstq+strideq*2-4], %1 + movhps [dstq+stride3q -4], %1 + lea dstq, [dstq+strideq*4] +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] + ; load data +%ifidn %2, v +%if %1 == 4 +%if ARCH_X86_64 +%define P1 m8 +%define P0 m9 +%define Q0 m10 +%define Q1 m11 + mova P1, [dstq+mstrideq*2] ; p1 + mova P0, [dstq+mstrideq*1] ; p0 + mova Q0, [dstq+strideq*0] ; q0 + mova Q1, [dstq+strideq*1] ; q1 +%else ; x86-32 +%define P1 [dstq+mstrideq*2] +%define P0 [dstq+mstrideq*1] +%define Q0 [dstq+strideq*0] +%define Q1 [dstq+strideq*1] +%endif ; x86-32/64 +%else ; %1 != 4 + ; load 6-8 pixels, remainder (for wd=16) will be read inline + lea tmpq, [dstq+mstrideq*4] +%if ARCH_X86_64 + ; we load p3 later +%define P2 m13 +%define P1 m8 +%define P0 m9 +%define Q0 m10 +%define Q1 m11 +%define Q2 m14 + mova P2, [tmpq+strideq*1] + mova P1, [tmpq+strideq*2] + mova P0, [tmpq+stride3q] + mova Q0, [dstq+strideq*0] + mova Q1, [dstq+strideq*1] + mova Q2, [dstq+strideq*2] +%if %1 != 6 +%define P3 [tmpq+strideq*0] +%define Q3 m15 + mova Q3, [dstq+stride3q] +%endif ; %1 != 6 +%else ; x86-32 +%define P2 [tmpq+strideq*1] +%define P1 [dstq+mstrideq*2] +%define P0 [dstq+mstrideq*1] +%define Q0 [dstq+strideq*0] +%define Q1 [dstq+strideq*1] +%define Q2 [dstq+strideq*2] +%if %1 != 6 +%define P3 [dstq+mstrideq*4] +%define Q3 [dstq+stride3q] +%endif ; %1 != 6 +%endif ; x86-32/64 +%endif ; %1 ==/!= 4 +%else ; %2 != v + ; load lines +%if %1 == 4 + movq m0, [dstq+strideq*0-4] + movq m2, [dstq+strideq*1-4] + movq m4, [dstq+strideq*2-4] + movq m5, [dstq+stride3q -4] + lea tmpq, [dstq+strideq*4] + movq m3, [tmpq+strideq*0-4] + movq m6, [tmpq+strideq*1-4] + movq m1, [tmpq+strideq*2-4] + movq m7, [tmpq+stride3q -4] + + ; transpose 4x8 + ; m0: A-D0 + ; m2: A-D1 + ; m4: A-D2 + ; m5: A-D3 + ; m3: A-D4 + ; m6: A-D5 + ; m1: A-D6 + ; m7: A-D7 + punpcklwd m0, m2 + punpcklwd m4, m5 + punpcklwd m3, m6 + punpcklwd m1, m7 + ; m0: A0-1,B0-1,C0-1,D0-1 + ; m4: A2-3,B2-3,C2-3,D2-3 + ; m3: A4-5,B4-5,C4-5,D4-5 + ; m1: A6-7,B6-7,C6-7,D6-7 + punpckhdq m2, m0, m4 + punpckldq m0, m4 + punpckhdq m4, m3, m1 + punpckldq m3, m1 + ; m0: A0-3,B0-3 + ; m2: C0-3,D0-3 + ; m3: A4-7,B4-7 + ; m4: C4-7,D4-7 + punpckhqdq m1, m0, m3 + punpcklqdq m0, m3 + punpckhqdq m3, m2, m4 + punpcklqdq m2, m4 + ; m0: A0-7 + ; m1: B0-7 + ; m2: C0-7 + ; m3: D0-7 +%if ARCH_X86_64 + SWAP 0, 8 + SWAP 1, 9 + SWAP 2, 10 + SWAP 3, 11 +%define P1 m8 +%define P0 m9 +%define Q0 m10 +%define Q1 m11 +%else +%define P1 [esp+3*mmsize] +%define P0 [esp+4*mmsize] +%define Q0 [esp+5*mmsize] +%define Q1 [esp+6*mmsize] + mova P1, m0 + mova P0, m1 + mova Q0, m2 + mova Q1, m3 +%endif +%elif %1 == 6 || %1 == 8 + movu m0, [dstq+strideq*0-8] + movu m1, [dstq+strideq*1-8] + movu m2, [dstq+strideq*2-8] + movu m3, [dstq+stride3q -8] + lea tmpq, [dstq+strideq*4] + movu m4, [tmpq+strideq*0-8] + movu m5, [tmpq+strideq*1-8] + movu m6, [tmpq+strideq*2-8] +%if ARCH_X86_64 + movu m7, [tmpq+stride3q -8] +%endif + + ; transpose 8x16 + ; m0: A-H0,A-H8 + ; m1: A-H1,A-H9 + ; m2: A-H2,A-H10 + ; m3: A-H3,A-H11 + ; m4: A-H4,A-H12 + ; m5: A-H5,A-H13 + ; m6: A-H6,A-H14 + ; m7: A-H7,A-H15 +%if ARCH_X86_64 + punpcklwd m8, m0, m1 +%else + punpcklwd m7, m0, m1 +%endif + punpckhwd m0, m1 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 + punpcklwd m3, m4, m5 + punpckhwd m4, m5 +%if ARCH_X86_64 + punpcklwd m5, m6, m7 + punpckhwd m6, m7 +%else + mova [rsp+3*16], m4 + movu m4, [tmpq+stride3q -8] + punpcklwd m5, m6, m4 + punpckhwd m6, m4 +%endif + ; m8: A0-1,B0-1,C0-1,D0-1 [m7 on x86-32] + ; m0: E0-1,F0-1,G0-1,H0-1 + ; m1: A2-3,B2-3,C2-3,D2-3 + ; m2: E2-3,F2-3,G2-3,H2-3 + ; m3: A4-5,B4-5,C4-5,D4-5 + ; m4: E4-5,F4-5,G4-5,H4-5 [r3 on x86-32] + ; m5: A6-7,B6-7,C6-7,D6-7 + ; m6: E6-7,F6-7,G6-7,H6-7 +%if ARCH_X86_64 + punpckldq m7, m8, m1 + punpckhdq m8, m1 +%else + punpckldq m4, m7, m1 + punpckhdq m7, m1 +%endif + punpckldq m1, m0, m2 + punpckhdq m0, m2 + punpckldq m2, m3, m5 + punpckhdq m3, m5 +%if ARCH_X86_64 + punpckldq m5, m4, m6 + punpckhdq m4, m6 +%else + mova [rsp+4*16], m3 + mova m3, [rsp+3*16] + punpckldq m5, m3, m6 + punpckhdq m3, m6 +%endif + ; m7: A0-3,B0-3 [m4 on x86-32] + ; m8: C0-3,D0-3 [m7 on x86-32] + ; m1: E0-3,F0-3 + ; m0: G0-3,H0-3 + ; m2: A4-7,B4-7 + ; m3: C4-7,D4-7 [r4 on x86-32] + ; m5: E4-7,F4-7 + ; m4: G4-7,H4-7 [m3 on x86-32] +%if ARCH_X86_64 +%if %1 != 6 + punpcklqdq m6, m7, m2 +%endif + punpckhqdq m7, m2 + punpcklqdq m2, m8, m3 + punpckhqdq m8, m3 + punpcklqdq m3, m1, m5 + punpckhqdq m1, m5 +%if %1 != 6 + punpckhqdq m5, m0, m4 +%endif + punpcklqdq m0, m4 +%if %1 == 8 + mova [rsp+1*16], m6 +%define P3 [rsp+1*16] +%endif + ; 7,2,8,3,1,0,5 -> 13,8,9,10,11,14,15 + SWAP 7, 13 + SWAP 8, 2, 9 + SWAP 3, 10 + SWAP 1, 11 + SWAP 0, 14 + SWAP 5, 15 +%define P2 m13 +%define P1 m8 +%define P0 m9 +%define Q0 m10 +%define Q1 m11 +%define Q2 m14 +%if %1 == 8 +%define Q3 m15 +%endif +%else ; x86-32 +%if %1 == 8 +%define P3 [rsp+ 6*16] + punpcklqdq m6, m4, m2 + mova P3, m6 +%endif + mova m6, [rsp+4*16] + punpckhqdq m4, m2 + punpcklqdq m2, m7, m6 + punpckhqdq m7, m6 + punpcklqdq m6, m1, m5 + punpckhqdq m1, m5 +%if %1 == 8 +%define Q3 [rsp+24*16] + punpckhqdq m5, m0, m3 + mova Q3, m5 +%endif + punpcklqdq m0, m3 +%if %1 == 8 +%define P2 [rsp+18*16] +%define P1 [rsp+19*16] +%define P0 [rsp+20*16] +%define Q0 [rsp+21*16] +%define Q1 [rsp+22*16] +%define Q2 [rsp+23*16] +%else +%define P2 [rsp+3*16] +%define P1 [rsp+4*16] +%define P0 [rsp+5*16] +%define Q0 [rsp+6*16] +%define Q1 [rsp+7*16] +%define Q2 [rsp+8*16] +%endif + mova P2, m4 + mova P1, m2 + mova P0, m7 + mova Q0, m6 + mova Q1, m1 + mova Q2, m0 +%endif ; x86-32/64 +%else ; %1 == 16 + ; We only use 14 pixels but we'll need the remainder at the end for + ; the second transpose + mova m0, [dstq+strideq*0-16] + mova m1, [dstq+strideq*1-16] + mova m2, [dstq+strideq*2-16] + mova m3, [dstq+stride3q -16] + lea tmpq, [dstq+strideq*4] + mova m4, [tmpq+strideq*0-16] + mova m5, [tmpq+strideq*1-16] + mova m6, [tmpq+strideq*2-16] +%if ARCH_X86_64 + mova m7, [tmpq+stride3q -16] + + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 7, 8 + SWAP 5, 13 + SWAP 6, 8 + SWAP 7, 9 +%define P2 m13 +%define P1 m8 +%define P0 m9 +%else ; x86-32 +%define P2 [esp+18*16] +%define P1 [esp+19*16] +%define P0 [esp+20*16] + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 7, \ + [tmpq+stride3q -16], P2, "", a, a + mova P1, m6 + mova P0, m7 +%endif ; x86-32/64 + mova [rsp+ 7*16], m0 + mova [rsp+ 8*16], m1 + mova [rsp+ 9*16], m2 + mova [rsp+10*16], m3 +%define P3 [rsp+6*16] + mova P3, m4 + + mova m0, [dstq+strideq*0] + mova m1, [dstq+strideq*1] + mova m2, [dstq+strideq*2] + mova m3, [dstq+stride3q ] + lea tmpq, [dstq+strideq*4] + mova m4, [tmpq+strideq*0] + mova m5, [tmpq+strideq*1] + mova m6, [tmpq+strideq*2] +%if ARCH_X86_64 + mova m7, [tmpq+stride3q ] + + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 7, 10 + SWAP 0, 10 + SWAP 1, 11 + SWAP 2, 14 + SWAP 3, 15 +%define Q0 m10 +%define Q1 m11 +%define Q2 m14 +%define Q3 m15 +%else ; x86-32 + TRANSPOSE8X8W 0, 1, 2, 3, 4, 5, 6, 7, \ + [tmpq+stride3q ], [rsp+12*16], "", a, a +%define Q0 [esp+21*16] +%define Q1 [esp+22*16] +%define Q2 [esp+23*16] +%define Q3 [esp+24*16] + mova Q0, m0 + mova Q1, m1 + mova Q2, m2 + mova Q3, m3 +%endif ; x86-32/64 + + mova [rsp+11*16], m4 +%if ARCH_X86_64 + mova [rsp+12*16], m5 +%endif + mova [rsp+13*16], m6 + mova [rsp+14*16], m7 +%endif ; %1 == 4/6/8/16 +%endif ; %2 ==/!= v + + ; load L/E/I/H +%if ARCH_X86_32 +%define l_strideq r5 + mov l_strideq, dword lstridem +%ifidn %2, v +%define lq r3 + mov lq, dword lm +%endif +%endif +%ifidn %2, v +%if cpuflag(sse4) + pmovzxbw m1, [lq] + pmovzxbw m0, [lq+l_strideq] + pxor m2, m2 +%else ; ssse3 + movq m1, [lq] + movq m0, [lq+l_strideq] + pxor m2, m2 + REPX {punpcklbw x, m2}, m1, m0 +%endif ; ssse3/sse4 +%else ; %2 != v + movq m0, [lq] ; l0, l1 + movq m1, [lq+l_strideq] ; l2, l3 + punpckldq m0, m1 ; l0, l2, l1, l3 + pxor m2, m2 + punpcklbw m1, m0, m2 ; l0, l2 + punpckhbw m0, m2 ; l1, l3 +%endif ; %2==/!=v +%if ARCH_X86_32 +%ifidn %2, v +%undef lq + mov mstrideq, mstridem +%endif +%endif + pcmpeqw m5, m2, m0 + pand m1, m5 + por m0, m1 ; l[x][] ? l[x][] : l[x-stride][] + pshufb m0, [PIC_sym(pb_4x1_4x5_4x9_4x13)] ; l[x][1] + pcmpeqw m5, m2, m0 ; !L + psrlw m5, 1 +%if ARCH_X86_64 + psrlw m2, m0, [lutq+128] + SPLATW m1, [lutq+136] +%else ; x86-32 + mov r5, lutm + psrlw m2, m0, [r5+128] + SPLATW m1, [r5+136] +%endif ; x86-32/64 + pminsw m2, m1 + pmaxsw m2, [PIC_sym(pw_1)] ; I + psrlw m1, m0, 4 ; H + paddw m0, [PIC_sym(pw_2)] + paddw m0, m0 + paddw m0, m2 ; E + REPX {pmullw x, [bdmulq]}, m0, m1, m2 +%if ARCH_X86_32 +%undef l_strideq + lea stride3q, [strideq*3] +%endif + + psubw m3, P1, P0 ; p1-p0 + psubw m4, Q0, Q1 ; q0-q1 + REPX {pabsw x, x}, m3, m4 + pmaxsw m3, m5 + pmaxsw m3, m4 + pcmpgtw m7, m3, m1 ; hev +%if %1 != 4 + psubw m4, P2, P0 ; p2-p0 + pabsw m4, m4 + pmaxsw m4, m3 +%if %1 != 6 + mova m6, P3 ; p3 + psubw m5, m6, P0 ; p3-p0 + pabsw m5, m5 + pmaxsw m4, m5 +%endif ; %1 != 6 + psubw m5, Q0, Q2 ; q0-q2 + pabsw m5, m5 + pmaxsw m4, m5 +%if %1 != 6 + psubw m5, Q0, Q3 ; q0-q3 + pabsw m5, m5 + pmaxsw m4, m5 +%endif ; %1 != 6 + pcmpgtw m4, [bdmulq] ; !flat8in + + psubw m5, P2, P1 ; p2-p1 + pabsw m5, m5 +%if %1 != 6 + psubw m6, P2 ; p3-p2 + pabsw m6, m6 + pmaxsw m5, m6 + psubw m6, Q2, Q3 ; q2-q3 + pabsw m6, m6 + pmaxsw m5, m6 +%endif ; %1 != 6 + psubw m6, Q2, Q1 ; q2-q1 + pabsw m6, m6 + pmaxsw m5, m6 + +%if %1 == 16 + SPLATD m6, [maskq+8] + SPLATD m1, [maskq+4] + por m6, m1 + pand m6, m12 + pcmpeqd m6, m12 + pand m5, m6 +%else ; %1 != 16 + SPLATD m6, [maskq+4] + pand m6, m12 + pcmpeqd m6, m12 + pand m5, m6 ; only apply fm-wide to wd>4 blocks +%endif ; %1==/!=16 + pmaxsw m3, m5 +%endif ; %1 != 4 + pcmpgtw m3, m2 + + psubw m5, P1, Q1 ; p1-q1 + psubw m6, P0, Q0 ; p0-q0 + REPX {pabsw x, x}, m5, m6 + paddw m6, m6 + psrlw m5, 1 + paddw m5, m6 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + pcmpgtw m5, m0 ; abs(p0-q0)*2+(abs(p1-q1)>>1) > E + por m3, m5 + +%if %1 == 16 + +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] + mova m1, [tmpq+strideq*2] + mova m2, [tmpq+stride3q] +%else ; %2 != v + mova m0, [rsp+ 8*16] + mova m1, [rsp+ 9*16] + mova m2, [rsp+10*16] +%endif ; %2==/!=v + REPX {psubw x, P0}, m0, m1, m2 + REPX {pabsw x, x}, m0, m1, m2 + pmaxsw m1, m0 + pmaxsw m1, m2 +%ifidn %2, v + lea tmpq, [dstq+strideq*4] + mova m0, [tmpq+strideq*0] + mova m2, [tmpq+strideq*1] + mova m5, [tmpq+strideq*2] +%else ; %2 != v + mova m0, [rsp+11*16] + mova m2, [rsp+12*16] + mova m5, [rsp+13*16] +%endif ; %2==/!=v + REPX {psubw x, Q0}, m0, m2, m5 + REPX {pabsw x, x}, m0, m2, m5 + pmaxsw m0, m2 + pmaxsw m1, m5 + pmaxsw m1, m0 + pcmpgtw m1, [bdmulq] ; !flat8out + por m1, m4 ; !flat8in | !flat8out + SPLATD m2, [maskq+8] + pand m5, m2, m12 + pcmpeqd m5, m12 + pandn m1, m5 ; flat16 + pandn m5, m3, m1 ; flat16 & fm + SWAP 1, 5 + + SPLATD m5, [maskq+4] + por m5, m2 + pand m2, m5, m12 + pcmpeqd m2, m12 + pandn m4, m2 ; flat8in + pandn m2, m3, m4 + SWAP 2, 4 + SPLATD m2, [maskq+0] + por m2, m5 + pand m2, m12 + pcmpeqd m2, m12 + pandn m3, m2 + pandn m0, m4, m3 ; fm & !flat8 & !flat16 + SWAP 0, 3 + pandn m0, m1, m4 ; flat8 & !flat16 + SWAP 0, 4 +%elif %1 != 4 + SPLATD m0, [maskq+4] + pand m2, m0, m12 + pcmpeqd m2, m12 + pandn m4, m2 + pandn m2, m3, m4 ; flat8 & fm + SWAP 2, 4 + SPLATD m2, [maskq+0] + por m0, m2 + pand m0, m12 + pcmpeqd m0, m12 + pandn m3, m0 + pandn m0, m4, m3 ; fm & !flat8 + SWAP 0, 3 +%else ; %1 == 4 + SPLATD m0, [maskq+0] + pand m0, m12 + pcmpeqd m0, m12 + pandn m3, m0 ; fm +%endif ; %1==/!=4 + + ; short filter +%if ARCH_X86_64 + SPLATW m0, r7m +%else + SPLATW m0, bdmulm +%endif + pcmpeqw m2, m2 + psrlw m0, 1 ; 511 or 2047 + pxor m2, m0 ; -512 or -2048 + + psubw m5, Q0, P0 ; q0-p0 + paddw m6, m5, m5 + paddw m6, m5 ; 3*(q0-p0) + psubw m5, P1, Q1 ; iclip_diff(p1-q1) + pminsw m5, m0 + pmaxsw m5, m2 + pand m5, m7 ; f=iclip_diff(p1-q1)&hev + paddw m5, m6 ; f=iclip_diff(3*(q0-p0)+f) + pminsw m5, m0 + pmaxsw m5, m2 + pand m3, m5 ; f&=fm + paddw m5, m3, [PIC_sym(pw_3)] + paddw m3, [PIC_sym(pw_4)] + REPX {pminsw x, m0}, m5, m3 + psraw m5, 3 ; f2 + psraw m3, 3 ; f1 + psubw m0, m2 ; 1023 or 4095 + pxor m2, m2 +%if ARCH_X86_64 + paddw P0, m5 + psubw Q0, m3 +%else + paddw m5, P0 + psubw m6, Q0, m3 + REPX {pminsw x, m0}, m5, m6 + REPX {pmaxsw x, m2}, m5, m6 +%endif + + paddw m3, [PIC_sym(pw_1)] + psraw m3, 1 ; f=(f1+1)>>1 + pandn m7, m3 ; f&=!hev + SWAP 7, 3 +%if ARCH_X86_64 + paddw P1, m3 + psubw Q1, m3 + REPX {pminsw x, m0}, P1, P0, Q0, Q1 + REPX {pmaxsw x, m2}, P1, P0, Q0, Q1 +%else + psubw m7, Q1, m3 + paddw m3, P1 + REPX {pminsw x, m0}, m7, m3 + REPX {pmaxsw x, m2}, m7, m3 +%if %1 > 4 + mova P1, m3 + mova P0, m5 + mova Q0, m6 + mova Q1, m7 +%endif +%endif + +%if %1 == 16 + +; m8-11 = p1/p0/q0/q1, m4=flat8, m1=flat16 +; m12=filter bits mask +; m13-15=p2/q2/q3 +; m0,2-3,5-7 = free + + ; flat16 filter +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] ; p6 + mova m2, [tmpq+strideq*2] ; p5 + mova m7, [tmpq+stride3q] ; p4 + mova m6, [tmpq+strideq*4] ; p3 + lea tmpq, [dstq+mstrideq*4] +%else ; %2 != v + mova m0, [rsp+ 8*16] + mova m2, [rsp+ 9*16] + mova m7, [rsp+10*16] + mova m6, [rsp+ 6*16] +%endif ; %2==/!=v + + mova [rsp+ 0*16], m4 + + ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + psllw m3, m0, 3 ; p6*8 + paddw m3, [PIC_sym(pw_8)] + paddw m5, m2, m7 ; p5+p4 + psubw m3, m0 + paddw m5, m5 ; (p5+p4)*2 + paddw m3, m6 ; p6*7+p3 + paddw m5, P2 ; (p5+p4)*2+p2 + paddw m3, P1 ; p6*7+p3+p1 + paddw m5, P0 ; (p5+p4)*2+p2+p0 + paddw m3, Q0 ; p6*7+p3+p1+q0 + paddw m3, m5 ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, m2 + por m5, m4 +%ifidn %2, v + mova [tmpq+mstrideq*2], m5 ; p5 +%else ; %2 != v + mova [rsp+9*16], m5 +%endif ; %2==/!=v + + ; sub p6*2, add p3/q1 + paddw m3, m6 + paddw m5, m0, m0 + paddw m3, Q1 + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, m7 + por m5, m4 +%ifidn %2, v + mova [tmpq+mstrideq*1], m5 ; p4 +%else ; %2 != v + mova [rsp+10*16], m5 +%endif ; %2==/!=v + + ; sub p6/p5, add p2/q2 + psubw m3, m0 + paddw m5, P2, Q2 + psubw m3, m2 + paddw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, m6 + por m5, m4 +%ifidn %2, v + mova [tmpq+strideq*0], m5 ; p3 +%else ; %2 != v + mova [rsp+6*16], m5 +%endif ; %2==/!=v + +%define WRITE_IN_PLACE 0 +%ifidn %2, v +%if ARCH_X86_64 +%define WRITE_IN_PLACE 1 +%endif +%endif + + ; sub p6/p4, add p1/q3 + paddw m3, P1 + paddw m5, m0, m7 + paddw m3, Q3 + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, P2 + por m5, m4 +%if WRITE_IN_PLACE + mova [tmpq+strideq*1], m5 +%else + mova [rsp+1*16], m5 ; don't clobber p2/m13 +%endif + + ; sub p6/p3, add p0/q4 + paddw m3, P0 + paddw m5, m0, m6 +%ifidn %2, v + paddw m3, [dstq+strideq*4] +%else ; %2 != v + paddw m3, [rsp+11*16] +%endif ; %2==/!=v + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, P1 + por m5, m4 +%if WRITE_IN_PLACE + mova [dstq+mstrideq*2], m5 +%else + mova [rsp+2*16], m5 ; don't clobber p1/m3 +%endif + + ; sub p6/p2, add q0/q5 + paddw m3, Q0 + paddw m5, m0, P2 +%ifidn %2, v +%if ARCH_X86_32 + lea r4, P2 +%endif + lea tmpq, [dstq+strideq*4] + paddw m3, [tmpq+strideq*1] +%else ; %2 != v + paddw m3, [rsp+12*16] +%endif ; %2==/!=v + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, P0 + por m5, m4 +%if WRITE_IN_PLACE + mova [dstq+mstrideq*1], m5 +%else + mova [rsp+3*16], m5 ; don't clobber p0/m4 +%endif + + ; sub p6/p1, add q1/q6 + paddw m3, Q1 + paddw m5, m0, P1 +%ifidn %2, v + mova m0, [tmpq+strideq*2] ; q6 +%else ; %2 != v + mova m0, [rsp+13*16] ; q6 +%endif ; %2==/!=v + paddw m3, m0 + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, Q0 + por m5, m4 +%if WRITE_IN_PLACE + mova [dstq], m5 +%else + mova [rsp+4*16], m5 ; don't clobber q0/m5 +%endif + + ; sub p5/p0, add q2/q6 + paddw m3, Q2 + paddw m5, m2, P0 + paddw m3, m0 + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 + pandn m4, m1, Q1 + por m2, m5, m4 ; don't clobber q1/m6 + + ; sub p4/q0, add q3/q6 + paddw m3, Q3 + paddw m7, Q0 + paddw m3, m0 + psubw m3, m7 + psrlw m7, m3, 4 + pand m7, m1 + pandn m4, m1, Q2 + por m7, m4 ; don't clobber q2/m14 + + ; sub p3/q1, add q4/q6 +%ifidn %2, v + paddw m3, [tmpq+strideq*0] +%else ; %2 != v + paddw m3, [rsp+11*16] +%endif ; %2==/!=v + paddw m6, Q1 + paddw m3, m0 + psubw m3, m6 + psrlw m6, m3, 4 + pand m6, m1 + pandn m4, m1, Q3 + por m6, m4 +%if WRITE_IN_PLACE + mova [tmpq+mstrideq], m6 ; q3 +%else ; %2 != v + mova [rsp+5*16], m6 +%endif ; %2==/!=v + + ; sub p2/q2, add q5/q6 +%ifidn %2, v + paddw m3, [tmpq+strideq*1] +%if ARCH_X86_64 + paddw m5, P2, Q2 +%else + ; because tmpq is clobbered, so we use a backup pointer for P2 instead + paddw m5, [r4], Q2 + mov pic_regq, pic_regm +%endif +%else ; %2 != v + paddw m3, [rsp+12*16] + paddw m5, P2, Q2 +%endif ; %2==/!=v + paddw m3, m0 + psubw m3, m5 + psrlw m5, m3, 4 + pand m5, m1 +%ifidn %2, v + pandn m4, m1, [tmpq+strideq*0] +%else ; %2 != v + pandn m4, m1, [rsp+11*16] +%endif ; %2==/!=v + por m5, m4 +%ifidn %2, v + mova [tmpq+strideq*0], m5 ; q4 +%else ; %2 != v + mova [rsp+11*16], m5 +%endif ; %2==/!=v + + ; sub p1/q3, add q6*2 + psubw m3, P1 + paddw m0, m0 + psubw m3, Q3 + paddw m3, m0 + psrlw m5, m3, 4 + pand m5, m1 +%ifidn %2, v + pandn m4, m1, [tmpq+strideq*1] +%else ; %2 != v + pandn m4, m1, [rsp+12*16] +%endif ; %2==/!=v + por m5, m4 +%ifidn %2, v + mova [tmpq+strideq*1], m5 ; q5 +%else ; %2 != v + mova [rsp+12*16], m5 +%endif ; %2==/!=v + + mova m4, [rsp+0*16] +%ifidn %2, v + lea tmpq, [dstq+mstrideq*4] +%endif +%if ARCH_X86_64 + SWAP 2, 11 + SWAP 7, 14 + SWAP 6, 15 +%else ; x86-32 + mova Q1, m2 + mova Q2, m7 +%endif ; x86-32/64 +%if WRITE_IN_PLACE + mova P2, [tmpq+strideq*1] + mova P1, [tmpq+strideq*2] + mova P0, [tmpq+stride3q] + mova Q0, [dstq] +%elif ARCH_X86_64 + mova P2, [rsp+1*16] + mova P1, [rsp+2*16] + mova P0, [rsp+3*16] + mova Q0, [rsp+4*16] +%else ; !WRITE_IN_PLACE & x86-32 + mova m0, [rsp+1*16] + mova m1, [rsp+2*16] + mova m2, [rsp+3*16] + mova m3, [rsp+4*16] + mova m7, [rsp+5*16] + mova P2, m0 + mova P1, m1 + mova P0, m2 + mova Q0, m3 + mova Q3, m7 +%endif ; WRITE_IN_PLACE / x86-32/64 +%undef WRITE_IN_PLACE +%endif ; %1 == 16 + +%if %1 >= 8 + + ; flat8 filter + mova m0, P3 ; p3 + paddw m1, m0, P2 ; p3+p2 + paddw m2, P1, P0 ; p1+p0 + paddw m3, m1, m1 ; 2*(p3+p2) + paddw m2, m0 ; p1+p0+p3 + paddw m3, Q0 ; 2*(p3+p2)+q0 + paddw m2, m3 ; 3*p3+2*p2+p1+p0+q0 + pmulhrsw m7, m2, [PIC_sym(pw_4096)] + psubw m7, P2 + pand m7, m4 + + paddw m3, P1, Q1 ; p1+q1 + psubw m2, m1 ; 2*p3+p2+p1+p0+q0 + paddw m2, m3 ; 2*p3+p2+2*p1+p0+q0+q1 + pmulhrsw m3, m2, [PIC_sym(pw_4096)] + psubw m3, P1 + pand m3, m4 + + paddw m5, m0, P1 ; p3+p1 + paddw m6, P0, Q2 ; p0+q2 + psubw m2, m5 ; p3+p2+p1+p0+q0+q1 + paddw m2, m6 ; p3+p2+p1+2*p0+q0+q1+q2 + pmulhrsw m5, m2, [PIC_sym(pw_4096)] + psubw m5, P0 + pand m5, m4 + + paddw m6, m0, P0 ; p3+p0 + paddw m1, Q0, Q3 ; q0+q3 + psubw m2, m6 ; p2+p1+p0+q0+q1+q2 + paddw m2, m1 ; p2+p1+p0+2*q0+q1+q2+q3 + pmulhrsw m6, m2, [PIC_sym(pw_4096)] + psubw m6, Q0 + pand m6, m4 + + paddw m2, Q1 ; p2+p1+p0+2*q0+2*q1+q2+q3 + paddw m2, Q3 ; p2+p1+p0+2*q0+2*q1+q2+2*q3 + paddw m1, P2, Q0 ; p2+q0 + psubw m2, m1 ; p1+p0+q0+2*q1+q2+2*q3 + pmulhrsw m1, m2, [PIC_sym(pw_4096)] + psubw m1, Q1 + pand m1, m4 + + psubw m2, P1 ; p0+q0+2*q1+q2+2*q3 + psubw m2, Q1 ; p0+q0+q1+q2+2*q3 + paddw m0, Q3, Q2 ; q3+q2 + paddw m2, m0 ; p0+q0+q1+2*q2+3*q3 + pmulhrsw m2, [PIC_sym(pw_4096)] + psubw m2, Q2 + pand m2, m4 + + paddw m7, P2 + paddw m3, P1 + paddw m5, P0 + paddw m6, Q0 + paddw m1, Q1 + paddw m2, Q2 + +%ifidn %2, v + mova [tmpq+strideq*1], m7 ; p2 + mova [tmpq+strideq*2], m3 ; p1 + mova [tmpq+stride3q ], m5 ; p0 + mova [dstq+strideq*0], m6 ; q0 + mova [dstq+strideq*1], m1 ; q1 + mova [dstq+strideq*2], m2 ; q2 +%else ; %2 != v + mova m0, P3 + +%if %1 == 8 + lea tmpq, [dstq+strideq*4] +%if ARCH_X86_64 + SWAP 4, 15 + TRANSPOSE8X8W 0, 7, 3, 5, 6, 1, 2, 4, 8 +%else + TRANSPOSE8X8W 0, 7, 3, 5, 6, 1, 2, 4, "", \ + Q3, [tmpq+strideq*1-8], a, u +%endif + + ; write 8x8 + movu [dstq+strideq*0-8], m0 + movu [dstq+strideq*1-8], m7 + movu [dstq+strideq*2-8], m3 + movu [dstq+stride3q -8], m5 + movu [tmpq+strideq*0-8], m6 +%if ARCH_X86_64 + movu [tmpq+strideq*1-8], m1 +%endif + movu [tmpq+strideq*2-8], m2 + movu [tmpq+stride3q -8], m4 + lea dstq, [dstq+strideq*8] +%else ; %1 != 8 +%if ARCH_X86_64 + SWAP 6, 8 + SWAP 1, 9 + SWAP 2, 10 +%else + mova [rsp+1*16], m6 + mova [rsp+2*16], m1 + mova [rsp+3*16], m2 +%endif + + mova m1, [rsp+ 7*16] + mova m2, [rsp+ 8*16] + mova m4, [rsp+ 9*16] + mova m6, [rsp+10*16] + lea tmpq, [dstq+strideq*4] +%if ARCH_X86_64 + TRANSPOSE8X8W 1, 2, 4, 6, 0, 7, 3, 5, 11 +%else + mova [rsp+7*16], m5 + TRANSPOSE8X8W 1, 2, 4, 6, 0, 7, 3, 5, "", \ + [rsp+7*16], [tmpq+strideq*1-16], a, a +%endif + + mova [dstq+strideq*0-16], m1 + mova [dstq+strideq*1-16], m2 + mova [dstq+strideq*2-16], m4 + mova [dstq+stride3q -16], m6 + mova [tmpq+strideq*0-16], m0 +%if ARCH_X86_64 + mova [tmpq+strideq*1-16], m7 +%endif + mova [tmpq+strideq*2-16], m3 + mova [tmpq+stride3q -16], m5 + +%if ARCH_X86_64 + SWAP 6, 8 + SWAP 1, 9 + SWAP 2, 10 + SWAP 4, 15 +%else + mova m6, [rsp+1*16] + mova m1, [rsp+2*16] + mova m2, [rsp+3*16] + mova m4, Q3 +%endif + mova m0, [rsp+11*16] + mova m3, [rsp+12*16] + mova m5, [rsp+13*16] +%if ARCH_X86_64 + mova m7, [rsp+14*16] + TRANSPOSE8X8W 6, 1, 2, 4, 0, 3, 5, 7, 8 +%else + TRANSPOSE8X8W 6, 1, 2, 4, 0, 3, 5, 7, "", \ + [rsp+14*16], [tmpq+strideq*1], a, a +%endif + mova [dstq+strideq*0], m6 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m4 + mova [tmpq+strideq*0], m0 +%if ARCH_X86_64 + mova [tmpq+strideq*1], m3 +%endif + mova [tmpq+strideq*2], m5 + mova [tmpq+stride3q ], m7 + lea dstq, [dstq+strideq*8] +%endif ; %1==/!=8 +%endif ; %2==/!=v +%elif %1 == 6 + ; flat6 filter + paddw m3, P1, P0 ; p1+p0 + paddw m3, P2 ; p2+p1+p0 + paddw m6, P2, Q0 ; p2+q0 + paddw m3, m3 ; 2*(p2+p1+p0) + paddw m3, m6 ; p2+2*(p2+p1+p0)+q0 + pmulhrsw m2, m3, [PIC_sym(pw_4096)] + psubw m2, P1 + pand m2, m4 + + paddw m3, Q0 ; p2+2*(p2+p1+p0+q0) + paddw m6, P2, P2 ; 2*p2 + paddw m3, Q1 ; p2+2*(p2+p1+p0+q0)+q1 + psubw m3, m6 ; p2+2*(p1+p0+q0)+q1 + pmulhrsw m5, m3, [PIC_sym(pw_4096)] + psubw m5, P0 + pand m5, m4 + + paddw m3, Q1 ; p2+2*(p1+p0+q0+q1) + paddw m6, P2, P1 ; p2+p1 + paddw m3, Q2 ; p2+2*(p1+p0+q0+q1)+q2 + psubw m3, m6 ; p1+2*(p0+q0+q1)+q2 + pmulhrsw m6, m3, [PIC_sym(pw_4096)] + psubw m6, Q0 + pand m6, m4 + + psubw m3, P1 ; 2*(p0+q0+q1)+q2 +%if ARCH_X86_64 + paddw Q2, Q2 ; q2*2 +%else + mova m0, Q2 + paddw m0, m0 +%endif + psubw m3, P0 ; p0+2*(q0+q1)+q2 +%if ARCH_X86_64 + paddw m3, Q2 ; p0+q*(q0+q1+q2)+q2 +%else + paddw m3, m0 +%endif + pmulhrsw m3, [PIC_sym(pw_4096)] + psubw m3, Q1 + pand m3, m4 + + paddw m2, P1 + paddw m5, P0 + paddw m6, Q0 + paddw m3, Q1 + +%ifidn %2, v + mova [dstq+mstrideq*2], m2 ; p1 + mova [dstq+mstrideq*1], m5 ; p0 + mova [dstq+strideq*0], m6 ; q0 + mova [dstq+strideq*1], m3 ; q1 +%else ; %2 != v + TRANSPOSE_8x4_AND_WRITE_4x8 m2, m5, m6, m3, m0 +%endif ; %2==/!=v +%else ; %1 == 4 +%if ARCH_X86_64 +%ifidn %2, v + mova [dstq+mstrideq*2], P1 ; p1 + mova [dstq+mstrideq*1], P0 ; p0 + mova [dstq+strideq*0], Q0 ; q0 + mova [dstq+strideq*1], Q1 ; q1 +%else ; %2 != v + TRANSPOSE_8x4_AND_WRITE_4x8 P1, P0, Q0, Q1, m0 +%endif ; %2==/!=v +%else ; x86-32 +%ifidn %2, v + mova [dstq+mstrideq*2], m3 + mova [dstq+mstrideq*1], m5 + mova [dstq+strideq*0], m6 + mova [dstq+strideq*1], m7 +%else ; %2 != v + TRANSPOSE_8x4_AND_WRITE_4x8 m3, m5, m6, m7, m0 +%endif ; %2==/!=v +%endif ; x86-32/64 +%endif ; %1 +%undef P3 +%undef P2 +%undef P1 +%undef P0 +%undef Q0 +%undef Q1 +%undef Q2 +%undef Q3 +%endmacro + +INIT_XMM ssse3 +; stack layout: +; r0 - flat8 backup inside flat16 code +%if ARCH_X86_64 +cglobal lpf_v_sb_y_16bpc, 6, 12, 16, -16 * 1, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits, bdmul + mov r6d, r7m + sar r6d, 7 + and r6d, 16 ; 0 for 10bpc, 16 for 12bpc + lea bdmulq, [pw_4] + add bdmulq, r6 + mov wd, wm + shl l_strideq, 2 + sub lq, l_strideq +%else +; stack layout [32bit only]: +; r1-4 - p2-q0 post-filter16 +; r5 - p3 +; r6 - q3 post-filter16 +; r7 - GPRs [mask_bitsm, mstridem] +; r8 - m12/pb_mask +; r9 - bdmulq +cglobal lpf_v_sb_y_16bpc, 4, 7, 8, -16 * (10 + extra_stack), \ + dst, stride, mask, mstride, pic_reg, stride3, tmp + RELOC_ARGS v, 10*16 +%if STACK_ALIGNMENT >= 16 + mov r5d, r7m +%endif + sar r5d, 7 + and r5d, 16 ; 0 for 10bpc, 16 for 12bpc + LEA pic_regq, PIC_base +%define pic_regm dword [esp+7*16+2*gprsize] + mov pic_regm, pic_regq + mova m0, [PIC_sym(pw_4)+r5] +%define bdmulq esp+9*16 + mova [bdmulq], m0 + shl dword lstridem, 2 + sub r3, dword lstridem + mov dword lm, r3 +%endif + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] +%if ARCH_X86_64 + mov mask_bitsd, 0x3 + mova m12, [pb_mask] +%else +%define mstridem dword [esp+7*16+1*gprsize] + mov mstridem, mstrideq +%define mask_bitsm dword [esp+7*16+0*gprsize] + mov mask_bitsm, 0x3 + mova m0, [PIC_sym(pb_mask)] +%define m12 [esp+8*16] + mova m12, m0 +%endif + +.loop: +%if ARCH_X86_64 + test [maskq+8], mask_bitsd ; vmask[2] +%else + mov r6d, mask_bitsm + test [maskq+8], r6d +%endif + jz .no_flat16 + + FILTER 16, v + jmp .end + +.no_flat16: +%if ARCH_X86_64 + test [maskq+4], mask_bitsd ; vmask[1] +%else + test [maskq+4], r6d +%endif + jz .no_flat + + FILTER 8, v + jmp .end + +.no_flat: +%if ARCH_X86_64 + test [maskq+0], mask_bitsd ; vmask[0] +%else + test [maskq+0], r6d +%endif + jz .end + + FILTER 4, v + +.end: +%if ARCH_X86_64 + pslld m12, 2 + add lq, 8 +%else + mova m0, m12 + pslld m0, 2 + mova m12, m0 + add dword lm, 8 +%endif + add dstq, 16 +%if ARCH_X86_64 + shl mask_bitsd, 2 + sub wd, 2 +%else + shl mask_bitsm, 2 + sub dword wm, 2 +%endif + jg .loop +%undef mask_bitsm +%undef bdmulq + UNRELOC_ARGS + RET + +INIT_XMM ssse3 +; stack layout: +; r0 - flat8 backup inside flat16 +; r1-4 - p2-q0 post-filter16 backup +; r5 - q3 post-filter16 backup +; r6 - p3 +; r7-10 - p7-4 +; r11-14 - q4-7 +%if ARCH_X86_64 +cglobal lpf_h_sb_y_16bpc, 6, 11, 16, -16 * 15, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, tmp, mask_bits, bdmul + mov r6d, r7m + sar r6d, 7 + and r6d, 16 ; 0 for 10bpc, 16 for 12bpc + lea bdmulq, [pw_4] + add bdmulq, r6 + mov hd, hm + shl l_strideq, 2 +%else +; stack layout [32bit only]: +; r15 - GPRs [mask_bitsm] +; r16 - m12/pb_mask +; r17 - bdmulq +; r18-24 - p2-q3 +cglobal lpf_h_sb_y_16bpc, 4, 7, 8, -16 * (25 + extra_stack), \ + dst, stride, mask, l, pic_reg, stride3, tmp + RELOC_ARGS h, 25*16 +%if STACK_ALIGNMENT >= 16 + mov r5d, r7m +%endif + sar r5d, 7 + and r5d, 16 ; 0 for 10bpc, 16 for 12bpc + LEA pic_regq, PIC_base + mova m0, [PIC_sym(pw_4)+r5] +%define bdmulq esp+17*16 + mova [bdmulq], m0 + shl dword lstridem, 2 +%endif + sub lq, 4 + lea stride3q, [strideq*3] +%if ARCH_X86_64 + mov mask_bitsd, 0x3 + mova m12, [pb_mask] +%else +%define mask_bitsm dword [esp+15*16+0*gprsize] + mov mask_bitsm, 0x3 + mova m0, [PIC_sym(pb_mask)] +%define m12 [esp+16*16] + mova m12, m0 +%endif + +.loop: +%if ARCH_X86_64 + test [maskq+8], mask_bitsd ; vmask[2] +%else + mov r6d, mask_bitsm + test [maskq+8], r6d +%endif + jz .no_flat16 + + FILTER 16, h + jmp .end + +.no_flat16: +%if ARCH_X86_64 + test [maskq+4], mask_bitsd ; vmask[1] +%else + test [maskq+4], r6d +%endif + jz .no_flat + + FILTER 8, h + jmp .end + +.no_flat: +%if ARCH_X86_64 + test [maskq+0], mask_bitsd ; vmask[0] +%else + test [maskq+0], r6d +%endif + jz .no_filter + + FILTER 4, h + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] +.end: +%if ARCH_X86_64 + pslld m12, 2 + lea lq, [lq+l_strideq*2] + shl mask_bitsd, 2 + sub hd, 2 +%else + mova m0, m12 + pslld m0, 2 + mova m12, m0 + add lq, dword lstridem + add lq, dword lstridem + shl mask_bitsm, 2 + sub dword hm, 2 +%endif + jg .loop +%undef mask_bitsm +%undef bdmulq + UNRELOC_ARGS + RET + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_v_sb_uv_16bpc, 6, 12, 16, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits, bdmul + mov r6d, r7m + sar r6d, 7 + and r6d, 16 ; 0 for 10bpc, 16 for 12bpc + lea bdmulq, [pw_4] + add bdmulq, r6 + mov wd, wm + shl l_strideq, 2 + sub lq, l_strideq +%else +; stack layout [32bit only]: +; r0 - GPRs [mask_bitsm, mstridem] +; r1 - m12/pb_mask +; r2 - bdmulq +cglobal lpf_v_sb_uv_16bpc, 4, 7, 8, -16 * (3 + extra_stack), \ + dst, stride, mask, mstride, pic_reg, stride3, tmp + RELOC_ARGS v, 3*16 +%if STACK_ALIGNMENT >= 16 + mov r5d, r7m +%endif + sar r5d, 7 + and r5d, 16 ; 0 for 10bpc, 16 for 12bpc + LEA pic_regq, PIC_base + mova m0, [PIC_sym(pw_4)+r5] +%define bdmulq esp+2*16 + mova [bdmulq], m0 + shl dword lstridem, 2 + sub r3, dword lstridem + mov dword lm, r3 +%endif + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] +%if ARCH_X86_64 + mov mask_bitsd, 0x3 + mova m12, [pb_mask] +%else +%define mask_bitsm dword [esp+0*gprsize] +%define mstridem dword [esp+1*gprsize] + mov mask_bitsm, 0x3 + mov mstridem, mstrideq + mova m0, [PIC_sym(pb_mask)] +%define m12 [esp+1*16] + mova m12, m0 +%endif + +.loop: +%if ARCH_X86_64 + test [maskq+4], mask_bitsd ; vmask[1] +%else + mov r6d, mask_bitsm + test [maskq+4], r6d +%endif + jz .no_flat + + FILTER 6, v + jmp .end + +.no_flat: +%if ARCH_X86_64 + test [maskq+0], mask_bitsd ; vmask[0] +%else + test [maskq+0], r6d +%endif + jz .end + + FILTER 4, v + +.end: +%if ARCH_X86_64 + pslld m12, 2 + add lq, 8 +%else + mova m0, m12 + pslld m0, 2 + mova m12, m0 + add dword lm, 8 +%endif + add dstq, 16 +%if ARCH_X86_64 + shl mask_bitsd, 2 + sub wd, 2 +%else + shl mask_bitsm, 2 + sub dword wm, 2 +%endif + jg .loop +%undef mask_bitsm +%undef bdmulq + UNRELOC_ARGS + RET + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_h_sb_uv_16bpc, 6, 11, 16, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, tmp, mask_bits, bdmul + mov r6d, r7m + sar r6d, 7 + and r6d, 16 ; 0 for 10bpc, 16 for 12bpc + lea bdmulq, [pw_4] + add bdmulq, r6 + mov hd, hm + shl l_strideq, 2 +%else +; stack layout [32bit only]: +; r0 - GPRs [mask_bitsm] +; r1 - m12/pb_mask +; r2 - bdmulq +; r3-8 - p2-q2 +cglobal lpf_h_sb_uv_16bpc, 4, 7, 8, -16 * (9 + extra_stack), \ + dst, stride, mask, l, pic_reg, stride3, tmp + RELOC_ARGS h, 9*16 +%if STACK_ALIGNMENT >= 16 + mov r5d, r7m +%endif + sar r5d, 7 + and r5d, 16 ; 0 for 10bpc, 16 for 12bpc + LEA pic_regq, PIC_base + mova m0, [PIC_sym(pw_4)+r5] +%define bdmulq esp+2*16 + mova [bdmulq], m0 + shl dword lstridem, 2 +%endif + sub lq, 4 + lea stride3q, [strideq*3] +%if ARCH_X86_64 + mov mask_bitsd, 0x3 + mova m12, [pb_mask] +%else +%define mask_bitsm dword [esp+0*gprsize] + mov mask_bitsm, 0x3 + mova m0, [PIC_sym(pb_mask)] +%define m12 [esp+1*16] + mova m12, m0 +%endif + +.loop: +%if ARCH_X86_64 + test [maskq+4], mask_bitsd ; vmask[1] +%else + mov r6d, mask_bitsm + test [maskq+4], r6d +%endif + jz .no_flat + + FILTER 6, h + jmp .end + +.no_flat: +%if ARCH_X86_64 + test [maskq+0], mask_bitsd ; vmask[0] +%else + test [maskq+0], r6d +%endif + jz .no_filter + + FILTER 4, h + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] +.end: +%if ARCH_X86_64 + pslld m12, 2 + lea lq, [lq+l_strideq*2] + shl mask_bitsd, 2 + sub hd, 2 +%else + mova m0, m12 + pslld m0, 2 + mova m12, m0 + add lq, dword lstridem + add lq, dword lstridem + shl mask_bitsm, 2 + sub dword hm, 2 +%endif + jg .loop +%undef mask_bitsm +%undef bdmulq + UNRELOC_ARGS + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1569 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +pb_4x1_4x5_4x9_4x13: times 2 db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12 +pb_7_1: times 16 db 7, 1 +pb_3_1: times 16 db 3, 1 +pb_2_1: times 16 db 2, 1 +pb_m1_0: times 16 db -1, 0 +pb_m1_1: times 16 db -1, 1 +pb_m1_2: times 16 db -1, 2 +pb_1: times 32 db 1 +pb_2: times 32 db 2 +pb_3: times 32 db 3 +pb_4: times 32 db 4 +pb_16: times 32 db 16 +pb_63: times 32 db 63 +pb_64: times 32 db 64 +pb_128: times 32 db 0x80 +pb_129: times 32 db 0x81 +pb_240: times 32 db 0xf0 +pb_248: times 32 db 0xf8 +pb_254: times 32 db 0xfe + +pw_2048: times 16 dw 2048 +pw_4096: times 16 dw 4096 + +pb_mask: dd 1, 2, 4, 8, 16, 32, 64, 128 + +SECTION .text + +%macro ABSSUB 4 ; dst, a, b, tmp + psubusb %1, %2, %3 + psubusb %4, %3, %2 + por %1, %4 +%endmacro + +%macro TRANSPOSE_16x4_AND_WRITE_4x32 5 + ; transpose 16x4 + punpcklbw m%5, m%1, m%2 + punpckhbw m%1, m%2 + punpcklbw m%2, m%3, m%4 + punpckhbw m%3, m%4 + punpcklwd m%4, m%5, m%2 + punpckhwd m%5, m%2 + punpcklwd m%2, m%1, m%3 + punpckhwd m%1, m%3 + + ; write out + movd [dstq+strideq*0-2], xm%4 + pextrd [dstq+strideq*1-2], xm%4, 1 + pextrd [dstq+strideq*2-2], xm%4, 2 + pextrd [dstq+stride3q-2], xm%4, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%5 + pextrd [dstq+strideq*1-2], xm%5, 1 + pextrd [dstq+strideq*2-2], xm%5, 2 + pextrd [dstq+stride3q-2], xm%5, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%2 + pextrd [dstq+strideq*1-2], xm%2, 1 + pextrd [dstq+strideq*2-2], xm%2, 2 + pextrd [dstq+stride3q-2], xm%2, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%1 + pextrd [dstq+strideq*1-2], xm%1, 1 + pextrd [dstq+strideq*2-2], xm%1, 2 + pextrd [dstq+stride3q-2], xm%1, 3 + lea dstq, [dstq+strideq*4] + + vextracti128 xm%4, m%4, 1 + vextracti128 xm%5, m%5, 1 + vextracti128 xm%2, m%2, 1 + vextracti128 xm%1, m%1, 1 + + movd [dstq+strideq*0-2], xm%4 + pextrd [dstq+strideq*1-2], xm%4, 1 + pextrd [dstq+strideq*2-2], xm%4, 2 + pextrd [dstq+stride3q-2], xm%4, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%5 + pextrd [dstq+strideq*1-2], xm%5, 1 + pextrd [dstq+strideq*2-2], xm%5, 2 + pextrd [dstq+stride3q-2], xm%5, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%2 + pextrd [dstq+strideq*1-2], xm%2, 1 + pextrd [dstq+strideq*2-2], xm%2, 2 + pextrd [dstq+stride3q-2], xm%2, 3 + lea dstq, [dstq+strideq*4] + movd [dstq+strideq*0-2], xm%1 + pextrd [dstq+strideq*1-2], xm%1, 1 + pextrd [dstq+strideq*2-2], xm%1, 2 + pextrd [dstq+stride3q-2], xm%1, 3 + lea dstq, [dstq+strideq*4] +%endmacro + +%macro TRANSPOSE_16X16B 3 ; in_load_15_from_mem, out_store_0_in_mem, mem +%if %1 == 0 + mova %3, m15 +%endif + + ; input in m0-15 + punpcklbw m15, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklbw m7, m8, m9 + punpckhbw m8, m9 + punpcklbw m9, m10, m11 + punpckhbw m10, m11 + punpcklbw m11, m12, m13 + punpckhbw m12, m13 + mova m13, %3 + mova %3, m12 + punpcklbw m12, m14, m13 + punpckhbw m13, m14, m13 + + ; interleaved in m15,0,1,2,3,4,5,6,7,8,9,10,11,rsp%3,12,13 + punpcklwd m14, m15, m1 + punpckhwd m15, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpcklwd m6, m7, m9 + punpckhwd m7, m9 + punpcklwd m9, m8, m10 + punpckhwd m8, m10 + punpcklwd m10, m11, m12 + punpckhwd m11, m12 + mova m12, %3 + mova %3, m11 + punpcklwd m11, m12, m13 + punpckhwd m12, m13 + + ; interleaved in m14,15,1,0,2,3,5,4,6,7,9,8,10,rsp%3,11,12 + punpckldq m13, m14, m2 + punpckhdq m14, m2 + punpckldq m2, m15, m3 + punpckhdq m15, m3 + punpckldq m3, m1, m5 + punpckhdq m1, m5 + punpckldq m5, m0, m4 + punpckhdq m0, m4 + punpckldq m4, m6, m10 + punpckhdq m6, m10 + punpckldq m10, m9, m11 + punpckhdq m9, m11 + punpckldq m11, m8, m12 + punpckhdq m8, m12 + mova m12, %3 + mova %3, m8 + punpckldq m8, m7, m12 + punpckhdq m7, m12 + + ; interleaved in m13,14,2,15,3,1,5,0,4,6,8,7,10,9,11,rsp%3 + punpcklqdq m12, m13, m4 + punpckhqdq m13, m4 + punpcklqdq m4, m14, m6 + punpckhqdq m14, m6 + punpcklqdq m6, m2, m8 + punpckhqdq m2, m8 + punpcklqdq m8, m15, m7 + punpckhqdq m15, m7 + punpcklqdq m7, m3, m10 + punpckhqdq m3, m10 + punpcklqdq m10, m1, m9 + punpckhqdq m1, m9 + punpcklqdq m9, m5, m11 + punpckhqdq m5, m11 + mova m11, %3 + mova %3, m12 + punpcklqdq m12, m0, m11 + punpckhqdq m0, m11 +%if %2 == 0 + mova m11, %3 +%endif + + ; interleaved m11,13,4,14,6,2,8,15,7,3,10,1,9,5,12,0 + SWAP 0, 11, 1, 13, 5, 2, 4, 6, 8, 7, 15 + SWAP 3, 14, 12, 9 +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] + ; load data +%ifidn %2, v +%if %1 == 4 + lea tmpq, [dstq+mstrideq*2] + mova m3, [tmpq+strideq*0] ; p1 + mova m4, [tmpq+strideq*1] ; p0 + mova m5, [tmpq+strideq*2] ; q0 + mova m6, [tmpq+stride3q] ; q1 +%else + ; load 6-8 pixels, remainder (for wd=16) will be read inline + lea tmpq, [dstq+mstrideq*4] +%if %1 != 6 + mova m12, [tmpq+strideq*0] +%endif + mova m13, [tmpq+strideq*1] + mova m3, [tmpq+strideq*2] + mova m4, [tmpq+stride3q] + mova m5, [dstq+strideq*0] + mova m6, [dstq+strideq*1] + mova m14, [dstq+strideq*2] +%if %1 != 6 + mova m15, [dstq+stride3q] +%endif +%endif +%else + ; load lines +%if %1 == 4 + movd xm3, [dstq+strideq*0-2] + movd xm4, [dstq+strideq*1-2] + movd xm5, [dstq+strideq*2-2] + movd xm6, [dstq+stride3q -2] + lea tmpq, [dstq+strideq*4] + pinsrd xm3, [tmpq+strideq*0-2], 2 + pinsrd xm4, [tmpq+strideq*1-2], 2 + pinsrd xm5, [tmpq+strideq*2-2], 2 + pinsrd xm6, [tmpq+stride3q -2], 2 + lea tmpq, [tmpq+strideq*4] + pinsrd xm3, [tmpq+strideq*0-2], 1 + pinsrd xm4, [tmpq+strideq*1-2], 1 + pinsrd xm5, [tmpq+strideq*2-2], 1 + pinsrd xm6, [tmpq+stride3q -2], 1 + lea tmpq, [tmpq+strideq*4] + pinsrd xm3, [tmpq+strideq*0-2], 3 + pinsrd xm4, [tmpq+strideq*1-2], 3 + pinsrd xm5, [tmpq+strideq*2-2], 3 + pinsrd xm6, [tmpq+stride3q -2], 3 + lea tmpq, [tmpq+strideq*4] + movd xm12, [tmpq+strideq*0-2] + movd xm13, [tmpq+strideq*1-2] + movd xm14, [tmpq+strideq*2-2] + movd xm15, [tmpq+stride3q -2] + lea tmpq, [tmpq+strideq*4] + pinsrd xm12, [tmpq+strideq*0-2], 2 + pinsrd xm13, [tmpq+strideq*1-2], 2 + pinsrd xm14, [tmpq+strideq*2-2], 2 + pinsrd xm15, [tmpq+stride3q -2], 2 + lea tmpq, [tmpq+strideq*4] + pinsrd xm12, [tmpq+strideq*0-2], 1 + pinsrd xm13, [tmpq+strideq*1-2], 1 + pinsrd xm14, [tmpq+strideq*2-2], 1 + pinsrd xm15, [tmpq+stride3q -2], 1 + lea tmpq, [tmpq+strideq*4] + pinsrd xm12, [tmpq+strideq*0-2], 3 + pinsrd xm13, [tmpq+strideq*1-2], 3 + pinsrd xm14, [tmpq+strideq*2-2], 3 + pinsrd xm15, [tmpq+stride3q -2], 3 + vinserti128 m3, xm12, 1 + vinserti128 m4, xm13, 1 + vinserti128 m5, xm14, 1 + vinserti128 m6, xm15, 1 + + ; transpose 4x16 + ; xm3: A-D0,A-D8,A-D4,A-D12 + ; xm4: A-D1,A-D9,A-D5,A-D13 + ; xm5: A-D2,A-D10,A-D6,A-D14 + ; xm6: A-D3,A-D11,A-D7,A-D15 + punpcklbw m7, m3, m4 + punpckhbw m3, m4 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + ; xm7: A0-1,B0-1,C0-1,D0-1,A8-9,B8-9,C8-9,D8-9 + ; xm3: A4-5,B4-5,C4-5,D4-5,A12-13,B12-13,C12-13,D12-13 + ; xm4: A2-3,B2-3,C2-3,D2-3,A10-11,B10-11,C10-11,D10-11 + ; xm5: A6-7,B6-7,C6-7,D6-7,A14-15,B14-15,C14-15,D14-15 + punpcklwd m6, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m3, m5 + punpckhwd m3, m5 + ; xm6: A0-3,B0-3,C0-3,D0-3 + ; xm7: A8-11,B8-11,C8-11,D8-11 + ; xm4: A4-7,B4-7,C4-7,D4-7 + ; xm3: A12-15,B12-15,C12-15,D12-15 + punpckldq m5, m6, m4 + punpckhdq m6, m4 + punpckldq m4, m7, m3 + punpckhdq m7, m3 + ; xm5: A0-7,B0-7 + ; xm6: C0-7,D0-7 + ; xm4: A8-15,B8-15 + ; xm7: C8-15,D8-15 + punpcklqdq m3, m5, m4 + punpckhqdq m4, m5, m4 + punpcklqdq m5, m6, m7 + punpckhqdq m6, m7 + ; xm3: A0-15 + ; xm5: B0-15 + ; xm4: C0-15 + ; xm6: D0-15 +%elif %1 == 6 || %1 == 8 + movq xm3, [dstq+strideq*0-%1/2] + movq xm4, [dstq+strideq*1-%1/2] + movq xm5, [dstq+strideq*2-%1/2] + movq xm6, [dstq+stride3q -%1/2] + lea tmpq, [dstq+strideq*8] + movhps xm3, [tmpq+strideq*0-%1/2] + movhps xm4, [tmpq+strideq*1-%1/2] + movhps xm5, [tmpq+strideq*2-%1/2] + movhps xm6, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + movq xm7, [tmpq+strideq*0-%1/2] + movq xm8, [tmpq+strideq*1-%1/2] + movq xm9, [tmpq+strideq*2-%1/2] + movq xm11, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + movhps xm7, [tmpq+strideq*0-%1/2] + movhps xm8, [tmpq+strideq*1-%1/2] + movhps xm9, [tmpq+strideq*2-%1/2] + movhps xm11, [tmpq+stride3q -%1/2] + vinserti128 m3, xm7, 1 + vinserti128 m4, xm8, 1 + vinserti128 m5, xm9, 1 + vinserti128 m6, xm11, 1 + lea tmpq, [dstq+strideq*4] + movq xm12, [tmpq+strideq*0-%1/2] + movq xm13, [tmpq+strideq*1-%1/2] + movq xm14, [tmpq+strideq*2-%1/2] + movq xm15, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + movhps xm12, [tmpq+strideq*0-%1/2] + movhps xm13, [tmpq+strideq*1-%1/2] + movhps xm14, [tmpq+strideq*2-%1/2] + movhps xm15, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + movq xm7, [tmpq+strideq*0-%1/2] + movq xm8, [tmpq+strideq*1-%1/2] + movq xm9, [tmpq+strideq*2-%1/2] + movq xm11, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + movhps xm7, [tmpq+strideq*0-%1/2] + movhps xm8, [tmpq+strideq*1-%1/2] + movhps xm9, [tmpq+strideq*2-%1/2] + movhps xm11, [tmpq+stride3q -%1/2] + vinserti128 m12, xm7, 1 + vinserti128 m13, xm8, 1 + vinserti128 m14, xm9, 1 + vinserti128 m15, xm11, 1 + + ; transpose 8x16 + ; xm3: A-H0,A-H8 + ; xm4: A-H1,A-H9 + ; xm5: A-H2,A-H10 + ; xm6: A-H3,A-H11 + ; xm12: A-H4,A-H12 + ; xm13: A-H5,A-H13 + ; xm14: A-H6,A-H14 + ; xm15: A-H7,A-H15 + punpcklbw m7, m3, m4 + punpckhbw m3, m4 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + punpcklbw m6, m12, m13 + punpckhbw m12, m13 + punpcklbw m13, m14, m15 + punpckhbw m14, m15 + ; xm7: A0-1,B0-1,C0-1,D0-1,E0-1,F0-1,G0-1,H0-1 + ; xm3: A8-9,B8-9,C8-9,D8-9,E8-9,F8-9,G8-9,H8-9 + ; xm4: A2-3,B2-3,C2-3,D2-3,E2-3,F2-3,G2-3,H2-3 + ; xm5: A10-11,B10-11,C10-11,D10-11,E10-11,F10-11,G10-11,H10-11 + ; xm6: A4-5,B4-5,C4-5,D4-5,E4-5,F4-5,G4-5,H4-5 + ; xm12: A12-13,B12-13,C12-13,D12-13,E12-13,F12-13,G12-13,H12-13 + ; xm13: A6-7,B6-7,C6-7,D6-7,E6-7,F6-7,G6-7,H6-7 + ; xm14: A14-15,B14-15,C14-15,D14-15,E14-15,F14-15,G14-15,H14-15 + punpcklwd m15, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m6, m13 + punpckhwd m6, m13 + punpcklwd m13, m12, m14 + punpckhwd m12, m14 + ; xm15: A0-3,B0-3,C0-3,D0-3 + ; xm7: E0-3,F0-3,G0-3,H0-3 + ; xm4: A8-11,B8-11,C8-11,D8-11 + ; xm3: E8-11,F8-11,G8-11,H8-11 + ; xm5: A4-7,B4-7,C4-7,D4-7 + ; xm6: E4-7,F4-7,G4-7,H4-7 + ; xm13: A12-15,B12-15,C12-15,D12-15 + ; xm12: E12-15,F12-15,G12-15,H12-15 + punpckldq m14, m15, m5 + punpckhdq m15, m5 + punpckldq m5, m7, m6 +%if %1 != 6 + punpckhdq m7, m6 +%endif + punpckldq m6, m4, m13 + punpckhdq m4, m13 + punpckldq m13, m3, m12 +%if %1 != 6 + punpckhdq m12, m3, m12 +%endif + ; xm14: A0-7,B0-7 + ; xm15: C0-7,D0-7 + ; xm5: E0-7,F0-7 + ; xm7: G0-7,H0-7 + ; xm6: A8-15,B8-15 + ; xm4: C8-15,D8-15 + ; xm13: E8-15,F8-15 + ; xm12: G8-15,H8-15 + punpcklqdq m3, m14, m6 + punpckhqdq m14, m6 + punpckhqdq m6, m15, m4 + punpcklqdq m15, m4 + punpcklqdq m4, m5, m13 + punpckhqdq m13, m5, m13 +%if %1 == 8 + punpcklqdq m5, m7, m12 + punpckhqdq m12, m7, m12 + ; xm3: A0-15 + ; xm14: B0-15 + ; xm15: C0-15 + ; xm6: D0-15 + ; xm4: E0-15 + ; xm13: F0-15 + ; xm5: G0-15 + ; xm12: H0-15 + SWAP 12, 3, 15 + SWAP 13, 14, 5, 4, 6 + ; 3,14,15,6,4,13,5,12 -> 12,13,3,4,5,6,14,15 +%else + SWAP 13, 3, 14 + SWAP 6, 4, 15, 5 + ; 3,14,15,6,4,13 -> 13,3,4,5,6,14 +%endif +%else + ; load and 16x16 transpose. We only use 14 pixels but we'll need the + ; remainder at the end for the second transpose + movu xm0, [dstq+strideq*0-8] + movu xm1, [dstq+strideq*1-8] + movu xm2, [dstq+strideq*2-8] + movu xm3, [dstq+stride3q -8] + lea tmpq, [dstq+strideq*4] + movu xm4, [tmpq+strideq*0-8] + movu xm5, [tmpq+strideq*1-8] + movu xm6, [tmpq+strideq*2-8] + movu xm7, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + movu xm8, [tmpq+strideq*0-8] + movu xm9, [tmpq+strideq*1-8] + movu xm10, [tmpq+strideq*2-8] + movu xm11, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + movu xm12, [tmpq+strideq*0-8] + movu xm13, [tmpq+strideq*1-8] + movu xm14, [tmpq+strideq*2-8] + movu xm15, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + vinserti128 m0, [tmpq+strideq*0-8], 1 + vinserti128 m1, [tmpq+strideq*1-8], 1 + vinserti128 m2, [tmpq+strideq*2-8], 1 + vinserti128 m3, [tmpq+stride3q -8], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m4, [tmpq+strideq*0-8], 1 + vinserti128 m5, [tmpq+strideq*1-8], 1 + vinserti128 m6, [tmpq+strideq*2-8], 1 + vinserti128 m7, [tmpq+stride3q -8], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m8, [tmpq+strideq*0-8], 1 + vinserti128 m9, [tmpq+strideq*1-8], 1 + vinserti128 m10, [tmpq+strideq*2-8], 1 + vinserti128 m11, [tmpq+stride3q -8], 1 + lea tmpq, [tmpq+strideq*4] + vinserti128 m12, [tmpq+strideq*0-8], 1 + vinserti128 m13, [tmpq+strideq*1-8], 1 + vinserti128 m14, [tmpq+strideq*2-8], 1 + vinserti128 m15, [tmpq+stride3q -8], 1 + + TRANSPOSE_16X16B 0, 1, [rsp+11*32] + mova [rsp+12*32], m1 + mova [rsp+13*32], m2 + mova [rsp+14*32], m3 + mova [rsp+15*32], m12 + mova [rsp+16*32], m13 + mova [rsp+17*32], m14 + mova [rsp+18*32], m15 + ; 4,5,6,7,8,9,10,11 -> 12,13,3,4,5,6,14,15 + SWAP 12, 4, 7 + SWAP 13, 5, 8 + SWAP 3, 6, 9 + SWAP 10, 14 + SWAP 11, 15 +%endif +%endif + + ; load L/E/I/H +%ifidn %2, v + movu m1, [lq] + movu m0, [lq+l_strideq] +%else + movq xm1, [lq] + movq xm2, [lq+l_strideq*2] + movhps xm1, [lq+l_strideq] + movhps xm2, [lq+l_stride3q] + lea lq, [lq+l_strideq*4] + movq xm10, [lq] + movq xm0, [lq+l_strideq*2] + movhps xm10, [lq+l_strideq] + movhps xm0, [lq+l_stride3q] + lea lq, [lq+l_strideq*4] + vinserti128 m1, xm10, 1 + vinserti128 m2, xm0, 1 + shufps m0, m1, m2, q3131 + shufps m1, m2, q2020 +%endif + pxor m2, m2 + pcmpeqb m10, m2, m0 + pand m1, m10 + por m0, m1 ; l[x][] ? l[x][] : l[x-stride][] + pshufb m0, [pb_4x1_4x5_4x9_4x13] ; l[x][1] + pcmpeqb m10, m2, m0 ; !L + psrlq m2, m0, [lutq+128] + pand m2, [pb_63] + vpbroadcastb m1, [lutq+136] + pminub m2, m1 + pmaxub m2, [pb_1] ; I + pand m1, m0, [pb_240] + psrlq m1, 4 ; H + paddb m0, [pb_2] + paddb m0, m0 + paddb m0, m2 ; E + pxor m1, [pb_128] + pxor m2, [pb_128] + pxor m0, [pb_128] + + ABSSUB m8, m3, m4, m9 ; abs(p1-p0) + pmaxub m8, m10 + ABSSUB m9, m5, m6, m10 ; abs(q1-q0) + pmaxub m8, m9 +%if %1 == 4 + pxor m8, [pb_128] + pcmpgtb m7, m8, m1 ; hev +%else + pxor m7, m8, [pb_128] + pcmpgtb m7, m1 ; hev + +%if %1 == 6 + ABSSUB m9, m13, m4, m10 ; abs(p2-p0) + pmaxub m9, m8 +%else + ABSSUB m9, m12, m4, m10 ; abs(p3-p0) + pmaxub m9, m8 + ABSSUB m10, m13, m4, m11 ; abs(p2-p0) + pmaxub m9, m10 +%endif + ABSSUB m10, m5, m14, m11 ; abs(q2-q0) + pmaxub m9, m10 +%if %1 != 6 + ABSSUB m10, m5, m15, m11 ; abs(q3-q0) + pmaxub m9, m10 +%endif + pxor m9, [pb_128] + pcmpgtb m9, [pb_129] ; !flat8in + +%if %1 == 6 + ABSSUB m10, m13, m3, m1 ; abs(p2-p1) +%else + ABSSUB m10, m12, m13, m11 ; abs(p3-p2) + ABSSUB m11, m13, m3, m1 ; abs(p2-p1) + pmaxub m10, m11 + ABSSUB m11, m14, m15, m1 ; abs(q3-q2) + pmaxub m10, m11 +%endif + ABSSUB m11, m14, m6, m1 ; abs(q2-q1) + pmaxub m10, m11 +%if %1 == 16 + vpbroadcastd m11, [maskq+8] + vpbroadcastd m1, [maskq+4] + por m11, m1 + pand m11, [pb_mask] + pcmpeqd m11, [pb_mask] + pand m10, m11 +%else + vpbroadcastd m11, [maskq+4] + pand m11, [pb_mask] + pcmpeqd m11, [pb_mask] + pand m10, m11 ; only apply fm-wide to wd>4 blocks +%endif + pmaxub m8, m10 + + pxor m8, [pb_128] +%endif + pcmpgtb m8, m2 + + ABSSUB m10, m3, m6, m11 ; abs(p1-q1) + ABSSUB m11, m4, m5, m2 ; abs(p0-q0) + paddusb m11, m11 + pand m10, [pb_254] + psrlq m10, 1 + paddusb m10, m11 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + pxor m10, [pb_128] + pcmpgtb m10, m0 ; abs(p0-q0)*2+(abs(p1-q1)>>1) > E + por m8, m10 + +%if %1 == 16 +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] +%else + mova m0, [rsp+12*32] +%endif + ABSSUB m1, m0, m4, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*2] +%else + mova m0, [rsp+13*32] +%endif + ABSSUB m2, m0, m4, m10 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+stride3q] +%else + mova m0, [rsp+14*32] +%endif + ABSSUB m2, m0, m4, m10 + pmaxub m1, m2 +%ifidn %2, v + lea tmpq, [dstq+strideq*4] + mova m0, [tmpq+strideq*0] +%else + mova m0, [rsp+15*32] +%endif + ABSSUB m2, m0, m5, m10 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*1] +%else + mova m0, [rsp+16*32] +%endif + ABSSUB m2, m0, m5, m10 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*2] +%else + mova m0, [rsp+17*32] +%endif + ABSSUB m2, m0, m5, m10 + pmaxub m1, m2 + pxor m1, [pb_128] + pcmpgtb m1, [pb_129] ; !flat8out + por m1, m9 ; !flat8in | !flat8out + vpbroadcastd m2, [maskq+8] + pand m10, m2, [pb_mask] + pcmpeqd m10, [pb_mask] + pandn m1, m10 ; flat16 + pandn m1, m8, m1 ; flat16 & fm + + vpbroadcastd m10, [maskq+4] + por m10, m2 + pand m2, m10, [pb_mask] + pcmpeqd m2, [pb_mask] + pandn m9, m2 ; flat8in + pandn m9, m8, m9 + vpbroadcastd m2, [maskq+0] + por m2, m10 + pand m2, [pb_mask] + pcmpeqd m2, [pb_mask] + pandn m8, m2 + pandn m8, m9, m8 ; fm & !flat8 & !flat16 + pandn m9, m1, m9 ; flat8 & !flat16 +%elif %1 != 4 + vpbroadcastd m0, [maskq+4] + pand m2, m0, [pb_mask] + pcmpeqd m2, [pb_mask] + pandn m9, m2 + pandn m9, m8, m9 ; flat8 & fm + vpbroadcastd m2, [maskq+0] + por m0, m2 + pand m0, [pb_mask] + pcmpeqd m0, [pb_mask] + pandn m8, m0 + pandn m8, m9, m8 ; fm & !flat8 +%else + vpbroadcastd m0, [maskq+0] + pand m0, [pb_mask] + pcmpeqd m0, [pb_mask] + pandn m8, m0 ; fm +%endif + + ; short filter + + pxor m3, [pb_128] + pxor m6, [pb_128] + psubsb m10, m3, m6 ; iclip_diff(p1-q1) + pand m10, m7 ; f=iclip_diff(p1-q1)&hev + pxor m4, [pb_128] + pxor m5, [pb_128] + psubsb m11, m5, m4 + paddsb m10, m11 + paddsb m10, m11 + paddsb m10, m11 ; f=iclip_diff(3*(q0-p0)+f) + pand m8, m10 ; f&=fm + paddsb m10, m8, [pb_3] + paddsb m8, [pb_4] + pand m10, [pb_248] + pand m8, [pb_248] + psrlq m10, 3 + psrlq m8, 3 + pxor m10, [pb_16] + pxor m8, [pb_16] + psubb m10, [pb_16] ; f2 + psubb m8, [pb_16] ; f1 + paddsb m4, m10 + psubsb m5, m8 + pxor m4, [pb_128] + pxor m5, [pb_128] + + pxor m8, [pb_128] + pxor m10, m10 + pavgb m8, m10 ; f=(f1+1)>>1 + psubb m8, [pb_64] + pandn m8, m7, m8 ; f&=!hev + paddsb m3, m8 + psubsb m6, m8 + pxor m3, [pb_128] + pxor m6, [pb_128] + +%if %1 == 16 + ; flat16 filter +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] ; p6 + mova m2, [tmpq+strideq*2] ; p5 + mova m7, [tmpq+stride3q] ; p4 +%else + mova m0, [rsp+12*32] + mova m2, [rsp+13*32] + mova m7, [rsp+14*32] +%endif + + mova [rsp+0*32], m9 + mova [rsp+1*32], m14 + mova [rsp+2*32], m15 + + ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 [p5/p4/p2/p1/p0/q0][p6/p3] A + ; write -6 + punpcklbw m14, m0, m12 + punpckhbw m15, m0, m12 + pmaddubsw m10, m14, [pb_7_1] + pmaddubsw m11, m15, [pb_7_1] ; p6*7+p3 + punpcklbw m8, m2, m7 + punpckhbw m9, m2, m7 + pmaddubsw m8, [pb_2] + pmaddubsw m9, [pb_2] + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3 + punpcklbw m8, m13, m3 + punpckhbw m9, m13, m3 + pmaddubsw m8, [pb_1] + pmaddubsw m9, [pb_1] + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3+p2+p1 + punpcklbw m8, m4, m5 + punpckhbw m9, m4, m5 + pmaddubsw m8, [pb_1] + pmaddubsw m9, [pb_1] + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + pand m8, m1 + pandn m9, m1, m2 + por m8, m9 +%ifidn %2, v + mova [tmpq+strideq*2], m8 ; p5 +%else + mova [rsp+13*32], m8 +%endif + + ; sub p6*2, add p3/q1 [reuse p6/p3 from A][-p6,+q1|save] B + ; write -5 + pmaddubsw m14, [pb_m1_1] + pmaddubsw m15, [pb_m1_1] + paddw m10, m14 + paddw m11, m15 ; p6*6+p5*2+p4*2+p3*2+p2+p1+p0+q0 + punpcklbw m8, m0, m6 + punpckhbw m9, m0, m6 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + mova [rsp+3*32], m8 + mova [rsp+4*32], m9 + paddw m10, m8 + paddw m11, m9 ; p6*5+p5*2+p4*2+p3*2+p2+p1+p0+q0+q1 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m7, m8, m1 +%ifidn %2, v + mova [tmpq+stride3q], m8 ; p4 +%else + mova [rsp+14*32], m8 +%endif + + ; sub p6/p5, add p2/q2 [-p6,+p2][-p5,+q2|save] C + ; write -4 + mova m14, [rsp+1*32] + punpcklbw m8, m0, m13 + punpckhbw m9, m0, m13 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p6*4+p5*2+p4*2+p3*2+p2*2+p1+p0+q0+q1 + punpcklbw m8, m2, m14 + punpckhbw m2, m14 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m2, [pb_m1_1] + mova [rsp+1*32], m8 + paddw m10, m8 + paddw m11, m2 ; p6*4+p5+p4*2+p3*2+p2*2+p1+p0+q0+q1+q2 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m12, m8, m1 +%ifidn %2, v + mova [tmpq+strideq*4], m8 ; p3 +%else + mova [rsp+19*32], m8 +%endif + + ; sub p6/p4, add p1/q3 [-p6,+p1][-p4,+q3|save] D + ; write -3 + mova m15, [rsp+2*32] + punpcklbw m8, m0, m3 + punpckhbw m9, m0, m3 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p6*3+p5+p4*2+p3*2+p2*2+p1*2+p0+q0+q1+q2 + punpcklbw m8, m7, m15 + punpckhbw m7, m15 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m7, [pb_m1_1] + mova [rsp+2*32], m8 + paddw m10, m8 + paddw m11, m7 ; p6*3+p5+p4+p3*2+p2*2+p1*2+p0+q0+q1+q2+q3 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m13, m8, m1 + mova [rsp+6*32], m8 ; don't clobber p2/m13 since we need it in F + + ; sub p6/p3, add p0/q4 [-p6,+p0][-p3,+q4|save] E + ; write -2 +%ifidn %2, v + lea tmpq, [dstq+strideq*4] +%endif + punpcklbw m8, m0, m4 + punpckhbw m9, m0, m4 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p6*2+p5+p4+p3*2+p2*2+p1*2+p0*2+q0+q1+q2+q3 +%ifidn %2, v + mova m9, [tmpq+strideq*0] ; q4 +%else + mova m9, [rsp+15*32] +%endif + punpcklbw m8, m12, m9 + punpckhbw m9, m12, m9 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + mova [rsp+7*32], m8 + mova [rsp+5*32], m9 + paddw m10, m8 + paddw m11, m9 ; p6*2+p5+p4+p3+p2*2+p1*2+p0*2+q0+q1+q2+q3+q4 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m3, m8, m1 + mova [rsp+8*32], m8 ; don't clobber p1/m3 since we need it in G + + ; sub p6/p2, add q0/q5 [-p6,+q0][-p2,+q5|save] F + ; write -1 +%ifidn %2, v + mova m9, [tmpq+strideq*1] ; q5 +%else + mova m9, [rsp+16*32] +%endif + punpcklbw m8, m0, m5 + punpckhbw m0, m5 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m0, [pb_m1_1] + paddw m10, m8 + paddw m11, m0 ; p6+p5+p4+p3+p2*2+p1*2+p0*2+q0*2+q1+q2+q3+q4 + punpcklbw m0, m13, m9 + punpckhbw m9, m13, m9 + mova m13, [rsp+6*32] + pmaddubsw m0, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + mova [rsp+ 9*32], m0 + mova [rsp+10*32], m9 + paddw m10, m0 + paddw m11, m9 ; p6+p5+p4+p3+p2+p1*2+p0*2+q0*2+q1+q2+q3+q4+q5 + pmulhrsw m0, m10, [pw_2048] + pmulhrsw m8, m11, [pw_2048] + packuswb m0, m8 + vpblendvb m0, m4, m0, m1 + mova [rsp+6*32], m0 ; don't clobber p0/m4 since we need it in H + + ; sub p6/p1, add q1/q6 [reuse -p6,+q1 from B][-p1,+q6|save] G + ; write +0 +%ifidn %2, v + mova m0, [tmpq+strideq*2] ; q6 +%else + mova m0, [rsp+17*32] +%endif + paddw m10, [rsp+3*32] + paddw m11, [rsp+4*32] ; p5+p4+p3+p2+p1*2+p0*2+q0*2+q1*2+q2+q3+q4+q5 + punpcklbw m8, m3, m0 + punpckhbw m9, m3, m0 + mova m3, [rsp+8*32] + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + mova [rsp+3*32], m8 + mova [rsp+4*32], m9 + paddw m10, m8 + paddw m11, m9 ; p5+p4+p3+p2+p1+p0*2+q0*2+q1*2+q2+q3+q4+q5+q6 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m5, m8, m1 + mova [rsp+8*32], m8 ; don't clobber q0/m5 since we need it in I + + ; sub p5/p0, add q2/q6 [reuse -p5,+q2 from C][-p0,+q6] H + ; write +1 + paddw m10, [rsp+1*32] + paddw m11, m2 ; p4+p3+p2+p1+p0*2+q0*2+q1*2+q2*2+q3+q4+q5+q6 + punpcklbw m8, m4, m0 + punpckhbw m2, m4, m0 + mova m4, [rsp+6*32] + pmaddubsw m8, [pb_m1_1] + pmaddubsw m2, [pb_m1_1] + paddw m10, m8 + paddw m11, m2 ; p4+p3+p2+p1+p0+q0*2+q1*2+q2*2+q3+q4+q5+q6*2 + pmulhrsw m2, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m2, m9 + vpblendvb m2, m6, m2, m1 ; don't clobber q1/m6 since we need it in K + + ; sub p4/q0, add q3/q6 [reuse -p4,+q3 from D][-q0,+q6] I + ; write +2 + paddw m10, [rsp+2*32] + paddw m11, m7 ; p3+p2+p1+p0+q0*2+q1*2+q2*2+q3*2+q4+q5+q6*2 + punpcklbw m8, m5, m0 + punpckhbw m9, m5, m0 + mova m5, [rsp+8*32] + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p3+p2+p1+p0+q0+q1*2+q2*2+q3*2+q4+q5+q6*3 + pmulhrsw m7, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m7, m9 + vpblendvb m7, m14, m7, m1 ; don't clobber q2/m14 since we need it in K + + ; sub p3/q1, add q4/q6 [reuse -p3,+q4 from E][-q1,+q6] J + ; write +3 + paddw m10, [rsp+7*32] + paddw m11, [rsp+5*32] ; p2+p1+p0+q0+q1*2+q2*2+q3*2+q4*2+q5+q6*3 + punpcklbw m8, m6, m0 + punpckhbw m9, m6, m0 + SWAP 2, 6 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p2+p1+p0+q0+q1+q2*2+q3*2+q4*2+q5+q6*4 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 + vpblendvb m8, m15, m8, m1 +%ifidn %2, v + mova [tmpq+mstrideq], m8 ; q3 +%else + mova [rsp+20*32], m8 +%endif + + ; sub p2/q2, add q5/q6 [reuse -p2,+q5 from F][-q2,+q6] K + ; write +4 + paddw m10, [rsp+ 9*32] + paddw m11, [rsp+10*32] ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + punpcklbw m8, m14, m0 + punpckhbw m9, m14, m0 + SWAP 14, 7 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m8, m10, [pw_2048] + pmulhrsw m9, m11, [pw_2048] + packuswb m8, m9 +%ifidn %2, v + mova m9, [tmpq+strideq*0] +%else + mova m9, [rsp+15*32] +%endif + vpblendvb m8, m9, m8, m1 +%ifidn %2, v + mova [tmpq+strideq*0], m8 ; q4 +%else + mova [rsp+15*32], m8 +%endif + + ; sub p1/q3, add q6*2 [reuse -p1,+q6 from G][-q3,+q6] L + ; write +5 + paddw m10, [rsp+3*32] + paddw m11, [rsp+4*32] ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + punpcklbw m8, m15, m0 + punpckhbw m9, m15, m0 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m9, [pb_m1_1] + paddw m10, m8 + paddw m11, m9 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m10, [pw_2048] + pmulhrsw m11, [pw_2048] + packuswb m10, m11 +%ifidn %2, v + mova m11, [tmpq+strideq*1] +%else + mova m11, [rsp+16*32] +%endif + vpblendvb m10, m11, m10, m1 +%ifidn %2, v + mova [tmpq+strideq*1], m10 ; q5 +%else + mova [rsp+16*32], m10 +%endif + + mova m9, [rsp+0*32] +%ifidn %2, v + lea tmpq, [dstq+mstrideq*4] +%endif +%endif +%if %1 >= 8 + ; flat8 filter + punpcklbw m0, m12, m3 + punpckhbw m1, m12, m3 + pmaddubsw m2, m0, [pb_3_1] + pmaddubsw m7, m1, [pb_3_1] ; 3 * p3 + p1 + punpcklbw m8, m13, m4 + punpckhbw m11, m13, m4 + pmaddubsw m8, [pb_2_1] + pmaddubsw m11, [pb_2_1] + paddw m2, m8 + paddw m7, m11 ; 3 * p3 + 2 * p2 + p1 + p0 + punpcklbw m8, m5, [pb_4] + punpckhbw m11, m5, [pb_4] + pmaddubsw m8, [pb_1] + pmaddubsw m11, [pb_1] + paddw m2, m8 + paddw m7, m11 ; 3 * p3 + 2 * p2 + p1 + p0 + q0 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendvb m10, m13, m8, m9 ; p2 +%ifidn %2, v + mova [tmpq+strideq*1], m10 ; p2 +%endif + + pmaddubsw m8, m0, [pb_m1_1] + pmaddubsw m11, m1, [pb_m1_1] + paddw m2, m8 + paddw m7, m11 + punpcklbw m8, m13, m6 + punpckhbw m11, m13, m6 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m11, [pb_m1_1] + paddw m2, m8 + paddw m7, m11 ; 2 * p3 + p2 + 2 * p1 + p0 + q0 + q1 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendvb m8, m3, m8, m9 ; p1 +%ifidn %2, v + mova [tmpq+strideq*2], m8 ; p1 +%else + mova [rsp+0*32], m8 +%endif + + pmaddubsw m0, [pb_1] + pmaddubsw m1, [pb_1] + psubw m2, m0 + psubw m7, m1 + punpcklbw m8, m4, m14 + punpckhbw m11, m4, m14 + pmaddubsw m8, [pb_1] + pmaddubsw m11, [pb_1] + paddw m2, m8 + paddw m7, m11 ; p3 + p2 + p1 + 2 * p0 + q0 + q1 + q2 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendvb m8, m4, m8, m9 ; p0 +%ifidn %2, v + mova [tmpq+stride3q ], m8 ; p0 +%else + mova [rsp+1*32], m8 +%endif + + punpcklbw m0, m5, m15 + punpckhbw m1, m5, m15 + pmaddubsw m8, m0, [pb_1] + pmaddubsw m11, m1, [pb_1] + paddw m2, m8 + paddw m7, m11 + punpcklbw m8, m4, m12 + punpckhbw m11, m4, m12 + pmaddubsw m8, [pb_1] + pmaddubsw m11, [pb_1] + psubw m2, m8 + psubw m7, m11 ; p2 + p1 + p0 + 2 * q0 + q1 + q2 + q3 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendvb m11, m5, m8, m9 ; q0 +%ifidn %2, v + mova [dstq+strideq*0], m11 ; q0 +%endif + + pmaddubsw m0, [pb_m1_1] + pmaddubsw m1, [pb_m1_1] + paddw m2, m0 + paddw m7, m1 + punpcklbw m8, m13, m6 + punpckhbw m13, m6 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m13, [pb_m1_1] + paddw m2, m8 + paddw m7, m13 ; p1 + p0 + q0 + 2 * q1 + q2 + 2 * q3 + 4 + psrlw m8, m2, 3 + psrlw m13, m7, 3 + packuswb m8, m13 + vpblendvb m13, m6, m8, m9 ; q1 +%ifidn %2, v + mova [dstq+strideq*1], m13 ; q1 +%endif + + punpcklbw m0, m3, m6 + punpckhbw m1, m3, m6 + pmaddubsw m0, [pb_1] + pmaddubsw m1, [pb_1] + psubw m2, m0 + psubw m7, m1 + punpcklbw m0, m14, m15 + punpckhbw m1, m14, m15 + pmaddubsw m0, [pb_1] + pmaddubsw m1, [pb_1] + paddw m2, m0 + paddw m7, m1 ; p0 + q0 + q1 + q2 + 2 * q2 + 3 * q3 + 4 + psrlw m2, 3 + psrlw m7, 3 + packuswb m2, m7 + vpblendvb m2, m14, m2, m9 ; q2 +%ifidn %2, v + mova [dstq+strideq*2], m2 ; q2 +%else + mova m0, [rsp+0*32] + mova m1, [rsp+1*32] +%if %1 == 8 + ; 16x8 transpose + punpcklbw m3, m12, m10 + punpckhbw m12, m10 + punpcklbw m10, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m11, m13 + punpckhbw m11, m13 + punpcklbw m13, m2, m15 + punpckhbw m2, m15 + + punpcklwd m15, m3, m10 + punpckhwd m3, m10 + punpcklwd m10, m12, m0 + punpckhwd m12, m0 + punpcklwd m0, m1, m13 + punpckhwd m1, m13 + punpcklwd m13, m11, m2 + punpckhwd m11, m2 + + punpckldq m2, m15, m0 + punpckhdq m15, m0 + punpckldq m0, m3, m1 + punpckhdq m3, m1 + punpckldq m1, m10, m13 + punpckhdq m10, m13 + punpckldq m13, m12, m11 + punpckhdq m12, m11 + + ; write 8x32 + movq [dstq+strideq*0-4], xm2 + movhps [dstq+strideq*1-4], xm2 + movq [dstq+strideq*2-4], xm15 + movhps [dstq+stride3q -4], xm15 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm0 + movhps [dstq+strideq*1-4], xm0 + movq [dstq+strideq*2-4], xm3 + movhps [dstq+stride3q -4], xm3 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm1 + movhps [dstq+strideq*1-4], xm1 + movq [dstq+strideq*2-4], xm10 + movhps [dstq+stride3q -4], xm10 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm13 + movhps [dstq+strideq*1-4], xm13 + movq [dstq+strideq*2-4], xm12 + movhps [dstq+stride3q -4], xm12 + lea dstq, [dstq+strideq*4] + + vextracti128 xm2, m2, 1 + vextracti128 xm15, m15, 1 + vextracti128 xm0, m0, 1 + vextracti128 xm3, m3, 1 + vextracti128 xm1, m1, 1 + vextracti128 xm10, m10, 1 + vextracti128 xm13, m13, 1 + vextracti128 xm12, m12, 1 + + movq [dstq+strideq*0-4], xm2 + movhps [dstq+strideq*1-4], xm2 + movq [dstq+strideq*2-4], xm15 + movhps [dstq+stride3q -4], xm15 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm0 + movhps [dstq+strideq*1-4], xm0 + movq [dstq+strideq*2-4], xm3 + movhps [dstq+stride3q -4], xm3 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm1 + movhps [dstq+strideq*1-4], xm1 + movq [dstq+strideq*2-4], xm10 + movhps [dstq+stride3q -4], xm10 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm13 + movhps [dstq+strideq*1-4], xm13 + movq [dstq+strideq*2-4], xm12 + movhps [dstq+stride3q -4], xm12 + lea dstq, [dstq+strideq*4] +%else + ; 16x16 transpose and store + SWAP 5, 10, 2 + SWAP 6, 0 + SWAP 7, 1 + SWAP 8, 11 + SWAP 9, 13 + mova m0, [rsp+11*32] + mova m1, [rsp+12*32] + mova m2, [rsp+13*32] + mova m3, [rsp+14*32] + mova m4, [rsp+19*32] + mova m11, [rsp+20*32] + mova m12, [rsp+15*32] + mova m13, [rsp+16*32] + mova m14, [rsp+17*32] + TRANSPOSE_16X16B 1, 0, [rsp+18*32] + movu [dstq+strideq*0-8], xm0 + movu [dstq+strideq*1-8], xm1 + movu [dstq+strideq*2-8], xm2 + movu [dstq+stride3q -8], xm3 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm4 + movu [dstq+strideq*1-8], xm5 + movu [dstq+strideq*2-8], xm6 + movu [dstq+stride3q -8], xm7 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm8 + movu [dstq+strideq*1-8], xm9 + movu [dstq+strideq*2-8], xm10 + movu [dstq+stride3q -8], xm11 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm12 + movu [dstq+strideq*1-8], xm13 + movu [dstq+strideq*2-8], xm14 + movu [dstq+stride3q -8], xm15 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m0, 1 + vextracti128 [dstq+strideq*1-8], m1, 1 + vextracti128 [dstq+strideq*2-8], m2, 1 + vextracti128 [dstq+stride3q -8], m3, 1 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m4, 1 + vextracti128 [dstq+strideq*1-8], m5, 1 + vextracti128 [dstq+strideq*2-8], m6, 1 + vextracti128 [dstq+stride3q -8], m7, 1 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m8, 1 + vextracti128 [dstq+strideq*1-8], m9, 1 + vextracti128 [dstq+strideq*2-8], m10, 1 + vextracti128 [dstq+stride3q -8], m11, 1 + lea dstq, [dstq+strideq*4] + vextracti128 [dstq+strideq*0-8], m12, 1 + vextracti128 [dstq+strideq*1-8], m13, 1 + vextracti128 [dstq+strideq*2-8], m14, 1 + vextracti128 [dstq+stride3q -8], m15, 1 + lea dstq, [dstq+strideq*4] +%endif +%endif +%elif %1 == 6 + ; flat6 filter + + punpcklbw m8, m13, m5 + punpckhbw m11, m13, m5 + pmaddubsw m0, m8, [pb_3_1] + pmaddubsw m1, m11, [pb_3_1] + punpcklbw m7, m4, m3 + punpckhbw m10, m4, m3 + pmaddubsw m2, m7, [pb_2] + pmaddubsw m12, m10, [pb_2] + paddw m0, m2 + paddw m1, m12 + pmulhrsw m2, m0, [pw_4096] + pmulhrsw m12, m1, [pw_4096] + packuswb m2, m12 + vpblendvb m2, m3, m2, m9 +%ifidn %2, v + mova [tmpq+strideq*2], m2 ; p1 +%endif + + pmaddubsw m8, [pb_m1_1] + pmaddubsw m11, [pb_m1_1] + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m13, m6 + punpckhbw m11, m13, m6 + pmaddubsw m8, [pb_m1_1] + pmaddubsw m11, [pb_m1_1] + paddw m0, m8 + paddw m1, m11 + pmulhrsw m12, m0, [pw_4096] + pmulhrsw m13, m1, [pw_4096] + packuswb m12, m13 + vpblendvb m12, m4, m12, m9 +%ifidn %2, v + mova [tmpq+stride3q], m12 ; p0 +%endif + + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m3, m14 + punpckhbw m11, m3, m14 + pmaddubsw m14, m8, [pb_m1_1] + pmaddubsw m13, m11, [pb_m1_1] + paddw m0, m14 + paddw m1, m13 + pmulhrsw m14, m0, [pw_4096] + pmulhrsw m13, m1, [pw_4096] + packuswb m14, m13 + vpblendvb m14, m5, m14, m9 +%ifidn %2, v + mova [dstq+strideq*0], m14 ; q0 +%endif + + pmaddubsw m8, [pb_m1_2] + pmaddubsw m11, [pb_m1_2] + paddw m0, m8 + paddw m1, m11 + pmaddubsw m7, [pb_m1_0] + pmaddubsw m10, [pb_m1_0] + paddw m0, m7 + paddw m1, m10 + pmulhrsw m0, [pw_4096] + pmulhrsw m1, [pw_4096] + packuswb m0, m1 + vpblendvb m0, m6, m0, m9 +%ifidn %2, v + mova [dstq+strideq*1], m0 ; q1 +%else + TRANSPOSE_16x4_AND_WRITE_4x32 2, 12, 14, 0, 1 +%endif +%else +%ifidn %2, v + mova [tmpq+strideq*0], m3 ; p1 + mova [tmpq+strideq*1], m4 ; p0 + mova [tmpq+strideq*2], m5 ; q0 + mova [tmpq+stride3q ], m6 ; q1 +%else + TRANSPOSE_16x4_AND_WRITE_4x32 3, 4, 5, 6, 7 +%endif +%endif +%endmacro + +INIT_YMM avx2 +cglobal lpf_v_sb_y_8bpc, 7, 10, 16, 32 * 11, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + +.loop: + cmp byte [maskq+8], 0 ; vmask[2] + je .no_flat16 + + FILTER 16, v + jmp .end + +.no_flat16: + cmp byte [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 8, v + jmp .end + +.no_flat: + cmp byte [maskq+0], 0 ; vmask[0] + je .end + + call .v4 + +.end: + add lq, 32 + add dstq, 32 + add maskq, 1 + sub wd, 8 + jg .loop + RET +ALIGN function_align +.v4: + FILTER 4, v + ret + +INIT_YMM avx2 +cglobal lpf_h_sb_y_8bpc, 7, 10, 16, 32 * 21, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp + shl l_strideq, 2 + sub lq, 4 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] + +.loop: + cmp byte [maskq+8], 0 ; vmask[2] + je .no_flat16 + + FILTER 16, h + jmp .end + +.no_flat16: + cmp byte [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 8, h + jmp .end + +.no_flat: + cmp byte [maskq+0], 0 ; vmask[0] + je .no_filter + + call .h4 + jmp .end + +.no_filter: + lea dstq, [dstq+stride3q*8] + lea lq, [lq+l_strideq*8] + lea dstq, [dstq+strideq*8] +.end: + add maskq, 1 + sub hd, 8 + jg .loop + RET +ALIGN function_align +.h4: + FILTER 4, h + ret + +INIT_YMM avx2 +cglobal lpf_v_sb_uv_8bpc, 7, 10, 16, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + +.loop: + cmp byte [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 6, v + jmp .end + +.no_flat: + cmp byte [maskq+0], 0 ; vmask[0] + je .end + + call mangle(private_prefix %+ _lpf_v_sb_y_8bpc_avx2).v4 + +.end: + add lq, 32 + add dstq, 32 + add maskq, 1 + sub wd, 8 + jg .loop + RET + +INIT_YMM avx2 +cglobal lpf_h_sb_uv_8bpc, 7, 10, 16, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp + shl l_strideq, 2 + sub lq, 4 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] + +.loop: + cmp byte [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 6, h + jmp .end + +.no_flat: + cmp byte [maskq+0], 0 ; vmask[0] + je .no_filter + + call mangle(private_prefix %+ _lpf_h_sb_y_8bpc_avx2).h4 + jmp .end + +.no_filter: + lea dstq, [dstq+stride3q*8] + lea lq, [lq+l_strideq*8] + lea dstq, [dstq+strideq*8] +.end: + add maskq, 1 + sub hd, 8 + jg .loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1534 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +pb_4x0_4x4_4x8_4x12: times 4 db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12 + +pb_mask: dd 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080 + dd 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 + +hmulA: dd 0, 8, 16, 24, 32, 40, 48, 56, 4, 12, 20, 28, 36, 44, 52, 60 +hmulB: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +hmulC: dd 0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51 +hmulD: dd 0, 1, 16, 17, 32, 33, 48, 49 +hshuf4:db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 + +pb_1: times 4 db 1 +pb_2: times 4 db 2 +pb_3: times 4 db 3 +pb_4: times 4 db 4 +pb_16: times 4 db 16 +pb_63: times 4 db 63 +pb_64: times 4 db 64 +pb_128: times 4 db 0x80 +pb_240: times 4 db 0xf0 +pb_248: times 4 db 0xf8 +pb_254: times 4 db 0xfe +pb_2_1: times 2 db 2, 1 +pb_3_1: times 2 db 3, 1 +pb_7_1: times 2 db 7, 1 +pb_m1_0: times 2 db -1, 0 +pb_m1_1: times 2 db -1, 1 +pb_m1_2: times 2 db -1, 2 +pw_2048: times 2 dw 2048 +pw_4096: times 2 dw 4096 + +SECTION .text + +%macro ABSSUB 4 ; dst, a, b, tmp + psubusb %1, %2, %3 + psubusb %4, %3, %2 + por %1, %4 +%endmacro + +%macro TRANSPOSE_16x4_AND_WRITE_4x32 5 + punpcklbw m%5, m%1, m%2 + punpckhbw m%1, m%2 + punpcklbw m%2, m%3, m%4 + punpckhbw m%3, m%4 + punpcklwd m%4, m%5, m%2 + punpckhwd m%5, m%2 + punpcklwd m%2, m%1, m%3 + punpckhwd m%1, m%3 + kmovw k1, k6 + lea t0, [dstq+strideq*4] + vpscatterdd [dstq+m19-2]{k1}, m%4 + kmovw k1, k6 + lea t1, [dstq+strideq*8] + vpscatterdd [t0 +m19-2]{k1}, m%5 + kmovw k1, k6 + lea t2, [t0 +strideq*8] + vpscatterdd [t1 +m19-2]{k1}, m%2 + kmovw k1, k6 + vpscatterdd [t2 +m19-2]{k1}, m%1 +%endmacro + +%macro TRANSPOSE_16X16B 3 ; in_load_15_from_mem, out_store_0_in_mem, mem +%if %1 == 0 + SWAP m16, m22 +%endif + punpcklbw m22, m24, m26 + punpckhbw m24, m26 + punpcklbw m26, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + punpcklbw m7, m8, m9 + punpckhbw m8, m9 + punpcklbw m9, m10, m11 + punpckhbw m10, m11 + punpcklbw m11, m25, m13 + punpckhbw m25, m13 +%if %1 == 0 + SWAP m13, m16 +%else + mova m13, %3 +%endif + SWAP m16, m25 + punpcklbw m25, m14, m13 + punpckhbw m13, m14, m13 + ; interleaved in m22,24,26,2,3,4,5,6,7,8,9,10,11,rsp%3,25,13 + punpcklwd m14, m22, m26 + punpckhwd m22, m26 + punpcklwd m26, m24, m2 + punpckhwd m24, m2 + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + punpcklwd m6, m7, m9 + punpckhwd m7, m9 + punpcklwd m9, m8, m10 + punpckhwd m8, m10 + punpcklwd m10, m11, m25 + punpckhwd m11, m25 + SWAP m25, m16, m11 + punpcklwd m11, m25, m13 + punpckhwd m25, m13 + ; interleaved in m14,15,26,24,2,3,5,4,6,7,9,8,10,rsp%3,11,25 + punpckldq m13, m14, m2 + punpckhdq m14, m2 + punpckldq m2, m22, m3 + punpckhdq m22, m3 + punpckldq m3, m26, m5 + punpckhdq m26, m5 + punpckldq m5, m24, m4 + punpckhdq m24, m4 + punpckldq m4, m6, m10 + punpckhdq m6, m10 + punpckldq m10, m9, m11 + punpckhdq m9, m11 + punpckldq m11, m8, m25 + punpckhdq m8, m25 + SWAP m25, m16, m8 + punpckldq m8, m7, m25 + punpckhdq m7, m25 + ; interleaved in m13,14,2,15,3,26,5,24,4,6,8,7,10,9,11,rsp%3 + punpcklqdq m25, m13, m4 + punpckhqdq m13, m4 + punpcklqdq m4, m14, m6 + punpckhqdq m14, m6 + punpcklqdq m6, m2, m8 + punpckhqdq m2, m8 + punpcklqdq m8, m22, m7 + punpckhqdq m22, m7 + punpcklqdq m7, m3, m10 + punpckhqdq m3, m10 + punpcklqdq m10, m26, m9 + punpckhqdq m26, m9 + punpcklqdq m9, m5, m11 + punpckhqdq m5, m11 + SWAP m11, m16 +%if %2 == 0 + SWAP m16, m25 +%else + mova %3, m25 +%endif + punpcklqdq m25, m24, m11 + punpckhqdq m24, m11 +%if %2 == 0 + SWAP m11, m16 +%endif + ; interleaved m11,13,4,14,6,2,8,15,7,3,10,26,9,5,25,24 + SWAP 24, 11, 26, 13, 5, 2, 4, 6, 8, 7, 22 + SWAP 3, 14, 25, 9 +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] + ; load data +%ifidn %2, v +%define is_h 0 +%if %1 == 4 + lea t0, [dstq+mstrideq*2] + mova m3, [t0 +strideq*0] ; p1 + mova m4, [t0 +strideq*1] ; p0 + mova m5, [t0 +strideq*2] ; q0 + mova m6, [t0 +stride3q ] ; q1 +%else + ; load 6-8 pixels, remainder (for wd=16) will be read inline +%if %1 == 16 + lea t0, [dstq+mstrideq*8] + mova m16, [t0 +strideq*1] + mova m17, [t0 +strideq*2] + mova m18, [t0 +stride3q ] +%endif + lea t0, [dstq+mstrideq*4] +%if %1 != 6 + mova m25, [t0 +strideq*0] +%endif + mova m13, [t0 +strideq*1] + mova m3, [t0 +strideq*2] + mova m4, [t0 +stride3q ] + mova m5, [dstq+strideq*0] + mova m6, [dstq+strideq*1] + mova m14, [dstq+strideq*2] +%if %1 != 6 + mova m22, [dstq+stride3q ] +%endif +%if %1 == 16 + lea t0, [dstq+strideq*4] + mova m29, [t0 +strideq*0] + mova m30, [t0 +strideq*1] + mova m31, [t0 +strideq*2] +%endif +%endif +%else ; h +%define is_h 1 + ; load lines +%if %1 == 4 + vbroadcasti32x4 m0, [hshuf4] + kmovw k1, k6 + lea t0, [dstq+strideq*4] + vpgatherdd m3{k1}, [dstq+m19-2] + kmovw k1, k6 + lea t1, [dstq+strideq*8] + vpgatherdd m4{k1}, [t0 +m19-2] + kmovw k1, k6 + lea t2, [t0 +strideq*8] + vpgatherdd m5{k1}, [t1 +m19-2] + kmovw k1, k6 + vpgatherdd m6{k1}, [t2 +m19-2] + pshufb m3, m0 + pshufb m4, m0 + pshufb m5, m0 + pshufb m6, m0 + punpckldq m7, m3, m4 + punpckhdq m3, m4 + punpckldq m4, m5, m6 + punpckhdq m5, m6 + punpcklqdq m6, m7, m4 + punpckhqdq m7, m4 + punpcklqdq m4, m3, m5 + punpckhqdq m3, m5 + SWAP 3, 6 + SWAP 5, 4, 7 + ; 6,7,4,3 -> 3,4,5,6 +%elif %1 == 6 || %1 == 8 + kmovb k1, k7 + lea t0, [dstq+strideq*1] + vpgatherdq m3{k1}, [dstq+ym21-%1/2] + kmovb k1, k7 + lea t1, [dstq+strideq*2] + vpgatherdq m4{k1}, [t0 +ym21-%1/2] + kmovb k1, k7 + lea t2, [dstq+stride3q ] + vpgatherdq m5{k1}, [t1 +ym21-%1/2] + kmovb k1, k7 + vextracti32x8 ym0, m21, 1 + vpgatherdq m6{k1}, [t2 +ym21-%1/2] + kmovb k1, k7 + vpgatherdq m12{k1}, [dstq+ym0 -%1/2] + kmovb k1, k7 + vpgatherdq m13{k1}, [t0 +ym0 -%1/2] + kmovb k1, k7 + vpgatherdq m14{k1}, [t1 +ym0 -%1/2] + kmovb k1, k7 + vpgatherdq m15{k1}, [t2 +ym0 -%1/2] + ; transpose 8x16 + ; xm3: A-H0,A-H8 + ; xm4: A-H1,A-H9 + ; xm5: A-H2,A-H10 + ; xm6: A-H3,A-H11 + ; xm12: A-H4,A-H12 + ; xm13: A-H5,A-H13 + ; xm14: A-H6,A-H14 + ; xm15: A-H7,A-H15 + punpcklbw m7, m3, m4 + punpckhbw m3, m4 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + punpcklbw m6, m12, m13 + punpckhbw m12, m13 + punpcklbw m13, m14, m15 + punpckhbw m14, m15 + ; xm7: A0-1,B0-1,C0-1,D0-1,E0-1,F0-1,G0-1,H0-1 + ; xm3: A8-9,B8-9,C8-9,D8-9,E8-9,F8-9,G8-9,H8-9 + ; xm4: A2-3,B2-3,C2-3,D2-3,E2-3,F2-3,G2-3,H2-3 + ; xm5: A10-11,B10-11,C10-11,D10-11,E10-11,F10-11,G10-11,H10-11 + ; xm6: A4-5,B4-5,C4-5,D4-5,E4-5,F4-5,G4-5,H4-5 + ; xm12: A12-13,B12-13,C12-13,D12-13,E12-13,F12-13,G12-13,H12-13 + ; xm13: A6-7,B6-7,C6-7,D6-7,E6-7,F6-7,G6-7,H6-7 + ; xm14: A14-15,B14-15,C14-15,D14-15,E14-15,F14-15,G14-15,H14-15 + punpcklwd m15, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m6, m13 + punpckhwd m6, m13 + punpcklwd m13, m12, m14 + punpckhwd m12, m14 + ; xm15: A0-3,B0-3,C0-3,D0-3 + ; xm7: E0-3,F0-3,G0-3,H0-3 + ; xm4: A8-11,B8-11,C8-11,D8-11 + ; xm3: E8-11,F8-11,G8-11,H8-11 + ; xm5: A4-7,B4-7,C4-7,D4-7 + ; xm6: E4-7,F4-7,G4-7,H4-7 + ; xm13: A12-15,B12-15,C12-15,D12-15 + ; xm12: E12-15,F12-15,G12-15,H12-15 + punpckldq m14, m15, m5 + punpckhdq m15, m5 + punpckldq m5, m7, m6 + %if %1 != 6 + punpckhdq m7, m6 + %endif + punpckldq m6, m4, m13 + punpckhdq m4, m13 + punpckldq m13, m3, m12 + %if %1 != 6 + punpckhdq m12, m3, m12 + %endif + ; xm14: A0-7,B0-7 + ; xm15: C0-7,D0-7 + ; xm5: E0-7,F0-7 + ; xm7: G0-7,H0-7 + ; xm6: A8-15,B8-15 + ; xm4: C8-15,D8-15 + ; xm13: E8-15,F8-15 + ; xm12: G8-15,H8-15 + punpcklqdq m3, m14, m6 + punpckhqdq m14, m6 + punpckhqdq m6, m15, m4 + punpcklqdq m15, m4 + punpcklqdq m4, m5, m13 + punpckhqdq m13, m5, m13 + %if %1 == 8 + punpcklqdq m5, m7, m12 + punpckhqdq m25, m7, m12 + ; xm3: A0-15 + ; xm14: B0-15 + ; xm15: C0-15 + ; xm6: D0-15 + ; xm4: E0-15 + ; xm13: F0-15 + ; xm5: G0-15 + ; xm25: H0-15 + SWAP 25, 3, 15 + SWAP 13, 14, 5, 4, 6 + SWAP 15, 22 + ; 3,14,15,6,4,13,5,12 -> 12,13,3,4,5,6,14,22 + %else + SWAP 13, 3, 14 + SWAP 6, 4, 15, 5 + ; 3,14,15,6,4,13 -> 13,3,4,5,6,14 + %endif +%else ; 16, h + ; load and 16x16 transpose. We only use 14 pixels but we'll need the + ; remainder at the end for the second transpose + movu xm24, [dstq+strideq*0-8] + movu xm26, [dstq+strideq*1-8] + movu xm2, [dstq+strideq*2-8] + movu xm3, [dstq+stride3q -8] + lea t0, [dstq+strideq*4] + movu xm4, [t0 +strideq*0-8] + movu xm5, [t0 +strideq*1-8] + movu xm6, [t0 +strideq*2-8] + movu xm7, [t0 +stride3q -8] + lea t0, [t0 +strideq*4] + movu xm8, [t0 +strideq*0-8] + movu xm9, [t0 +strideq*1-8] + movu xm10, [t0 +strideq*2-8] + movu xm11, [t0 +stride3q -8] + lea t0, [t0 +strideq*4] + movu xm25, [t0 +strideq*0-8] + movu xm13, [t0 +strideq*1-8] + movu xm14, [t0 +strideq*2-8] + movu xm22, [t0 +stride3q -8] + lea t0, [t0 +strideq*4] + vinserti32x4 ym24, [t0 +strideq*0-8], 1 + vinserti32x4 ym26, [t0 +strideq*1-8], 1 + vinserti32x4 ym2, [t0 +strideq*2-8], 1 + vinserti32x4 ym3, [t0 +stride3q -8], 1 + lea t0, [t0 +strideq*4] + vinserti32x4 ym4, [t0 +strideq*0-8], 1 + vinserti32x4 ym5, [t0 +strideq*1-8], 1 + vinserti32x4 ym6, [t0 +strideq*2-8], 1 + vinserti32x4 ym7, [t0 +stride3q -8], 1 + lea t0, [t0 +strideq*4] + vinserti32x4 ym8, [t0 +strideq*0-8], 1 + vinserti32x4 ym9, [t0 +strideq*1-8], 1 + vinserti32x4 ym10, [t0 +strideq*2-8], 1 + vinserti32x4 ym11, [t0 +stride3q -8], 1 + lea t0, [t0 +strideq*4] + vinserti32x4 ym25, [t0 +strideq*0-8], 1 + vinserti32x4 ym13, [t0 +strideq*1-8], 1 + vinserti32x4 ym14, [t0 +strideq*2-8], 1 + vinserti32x4 ym22, [t0 +stride3q -8], 1 + lea t0, [t0 +strideq*4] + vinserti32x4 m24, [t0 +strideq*0-8], 2 + vinserti32x4 m26, [t0 +strideq*1-8], 2 + vinserti32x4 m2, [t0 +strideq*2-8], 2 + vinserti32x4 m3, [t0 +stride3q -8], 2 + lea t0, [t0 +strideq*4] + vinserti32x4 m4, [t0 +strideq*0-8], 2 + vinserti32x4 m5, [t0 +strideq*1-8], 2 + vinserti32x4 m6, [t0 +strideq*2-8], 2 + vinserti32x4 m7, [t0 +stride3q -8], 2 + lea t0, [t0 +strideq*4] + vinserti32x4 m8, [t0 +strideq*0-8], 2 + vinserti32x4 m9, [t0 +strideq*1-8], 2 + vinserti32x4 m10, [t0 +strideq*2-8], 2 + vinserti32x4 m11, [t0 +stride3q -8], 2 + lea t0, [t0 +strideq*4] + vinserti32x4 m25, [t0 +strideq*0-8], 2 + vinserti32x4 m13, [t0 +strideq*1-8], 2 + vinserti32x4 m14, [t0 +strideq*2-8], 2 + vinserti32x4 m22, [t0 +stride3q -8], 2 + lea t0, [t0 +strideq*4] + vinserti32x4 m24, [t0 +strideq*0-8], 3 + vinserti32x4 m26, [t0 +strideq*1-8], 3 + vinserti32x4 m2, [t0 +strideq*2-8], 3 + vinserti32x4 m3, [t0 +stride3q -8], 3 + lea t0, [t0 +strideq*4] + vinserti32x4 m4, [t0 +strideq*0-8], 3 + vinserti32x4 m5, [t0 +strideq*1-8], 3 + vinserti32x4 m6, [t0 +strideq*2-8], 3 + vinserti32x4 m7, [t0 +stride3q -8], 3 + lea t0, [t0 +strideq*4] + vinserti32x4 m8, [t0 +strideq*0-8], 3 + vinserti32x4 m9, [t0 +strideq*1-8], 3 + vinserti32x4 m10, [t0 +strideq*2-8], 3 + vinserti32x4 m11, [t0 +stride3q -8], 3 + lea t0, [t0 +strideq*4] + vinserti32x4 m25, [t0 +strideq*0-8], 3 + vinserti32x4 m13, [t0 +strideq*1-8], 3 + vinserti32x4 m14, [t0 +strideq*2-8], 3 + vinserti32x4 m22, [t0 +stride3q -8], 3 + ; + TRANSPOSE_16X16B 0, 1, [rsp+0*64] + SWAP m16, m26 + SWAP m17, m2 + SWAP m18, m3 + SWAP m29, m25 + SWAP m30, m13 + SWAP m31, m14 + mova [rsp+4*64], m22 + ; 4,5,6,7,8,9,10,11 -> 25,13,3,4,5,6,14,22 + SWAP 25, 4, 7 + SWAP 13, 5, 8 + SWAP 3, 6, 9 + SWAP 10, 14 + SWAP 11, 22 +%endif +%endif + + ; load L/E/I/H + vpbroadcastd m15, [pb_1] +%ifidn %2, v + movu m1, [lq] + movu m0, [lq+l_strideq] +%else + kmovw k1, k6 + vpgatherdd m0{k1}, [lq+m20+4] + kmovw k1, k6 + vpgatherdd m1{k1}, [lq+m20+0] +%endif + pxor m2, m2 + pcmpeqb k1, m0, m2 + vmovdqu8 m0{k1}, m1 ; l[x][] ? l[x][] : l[x-stride][] + pshufb m0, pbshuf ; l[x][0] + vpcmpub k3, m0, m2, 4 ; neq ; L + psrlq m2, m0, [lutq+128] + pand m2, [pb_63]{bcstd} + vpbroadcastb m1, [lutq+136] + pminub m2, m1 + pmaxub m2, m15 ; I + pand m1, m0, [pb_240]{bcstd} + psrlq m1, 4 ; H + paddd m0, [pb_2]{bcstd} + paddb m0, m0 + paddb m0, m2 ; E + + ABSSUB m8, m3, m4, m9 ; abs(p1-p0) + ABSSUB m9, m5, m6, m10 ; abs(q1-q0) + pmaxub m8, m9 + vpcmpub k1, m8, m1, 6 ; gt ; hev +%if %1 != 4 + %if %1 == 6 + ABSSUB m9, m13, m4, m10 ; abs(p2-p0) + pmaxub m9, m8 + %else + ABSSUB m9, m25, m4, m10 ; abs(p3-p0) + pmaxub m9, m8 + ABSSUB m10, m13, m4, m11 ; abs(p2-p0) + pmaxub m9, m10 + %endif + ABSSUB m10, m5, m14, m11 ; abs(q2-q0) + pmaxub m9, m10 + %if %1 != 6 + ABSSUB m10, m5, m22, m11 ; abs(q3-q0) + pmaxub m9, m10 + %endif + vpcmpub k2{k3}, m9, m15, 2 ; le ; flat8in + %if %1 == 6 + ABSSUB m10, m13, m3, m1 ; abs(p2-p1) + %else + ABSSUB m10, m25, m13, m11 ; abs(p3-p2) + ABSSUB m11, m13, m3, m1 ; abs(p2-p1) + pmaxub m10, m11 + ABSSUB m11, m14, m22, m1 ; abs(q3-q2) + pmaxub m10, m11 + %endif + ABSSUB m11, m14, m6, m1 ; abs(q2-q1) + pmaxub m10, m11 + %if %1 == 16 + vpbroadcastd m11, [maskq+8] + por m11, [maskq+4]{bcstd} + %else + vpbroadcastd m11, [maskq+4] + %endif + vptestmd k4, m11, pbmask + vmovdqa32 m10{k4}{z}, m10 ; only apply fm-wide to wd>4 blocks + pmaxub m8, m10 +%endif + vpcmpub k3{k3}, m8, m2, 2 ; le + ABSSUB m10, m3, m6, m11 ; abs(p1-q1) + ABSSUB m11, m4, m5, m2 ; abs(p0-q0) + paddusb m11, m11 + pand m10, [pb_254]{bcstd} + psrlq m10, 1 + paddusb m10, m11 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + vpcmpub k3{k3}, m10, m0, 2 ; abs(p0-q0)*2+(abs(p1-q1)>>1) <= E + +%if %1 == 16 + ABSSUB m1, m16, m4, m2 + ABSSUB m2, m17, m4, m10 + pmaxub m1, m2 + ABSSUB m2, m18, m4, m10 + pmaxub m1, m2 + ABSSUB m2, m29, m5, m10 + pmaxub m1, m2 + ABSSUB m2, m30, m5, m10 + pmaxub m1, m2 + ABSSUB m2, m31, m5, m10 + pmaxub m1, m2 + kandq k2, k2, k3 + vpcmpub k4{k2}, m1, m15, 2 ; flat8in & flat8out + vpbroadcastd m2, [maskq+8] + vptestmd k5, m2, pbmask + vpmovm2d m7, k5 + vptestmb k4{k4}, m7, m7 ; flat16 & fm + por m10, m2, [maskq+4]{bcstd} + vptestmd k5, m10, pbmask + vpmovm2d m7, k5 + vptestmb k2{k2}, m7, m7 ; flat8in + por m2, m10, [maskq+0]{bcstd} + vptestmd k5, m2, pbmask + vpmovm2d m7, k5 + vptestmb k3{k3}, m7, m7 + kandnq k3, k2, k3 ; fm & !flat8 & !flat16 + kandnq k2, k4, k2 ; flat8 & !flat16 +%elif %1 != 4 + vpbroadcastd m0, [maskq+4] + vptestmd k4, m0, pbmask + vpmovm2d m7, k4 + vptestmb k2{k2}, m7, m7 + kandq k2, k2, k3 ; flat8 & fm + por m0, [maskq+0]{bcstd} + vptestmd k4, m0, pbmask + vpmovm2d m7, k4 + vptestmb k3{k3}, m7, m7 + kandnq k3, k2, k3 ; fm & !flat8 +%else + %ifidn %2, v + vptestmd k4, pbmask, [maskq+0]{bcstd} + %else + vpbroadcastd m0, [maskq+0] + vptestmd k4, m0, pbmask + %endif + vpmovm2d m7, k4 + vptestmb k3{k3}, m7, m7 ; fm +%endif + + ; short filter +%if %1 >= 8 + SWAP m23, m15 +%endif + vpbroadcastd m15, [pb_3] + vpbroadcastd m0, [pb_4] + vpbroadcastd m12, [pb_16] + vpbroadcastd m1, [pb_64] + pxor m3, pb128 + pxor m6, pb128 + psubsb m10{k1}{z}, m3, m6 ; f=iclip_diff(p1-q1)&hev + pxor m4, pb128 + pxor m5, pb128 + psubsb m11, m5, m4 + paddsb m10, m11 + paddsb m10, m11 + paddsb m10{k3}{z}, m10, m11 ; f=iclip_diff(3*(q0-p0)+f)&fm + paddsb m8, m10, m15 + paddsb m10, m0 + pand m8, [pb_248]{bcstd} + pand m10, [pb_248]{bcstd} + psrlq m8, 3 + psrlq m10, 3 + pxor m8, m12 + pxor m10, m12 + psubb m8, m12 ; f2 + psubb m10, m12 ; f1 + paddsb m4, m8 + psubsb m5, m10 + pxor m4, pb128 + pxor m5, pb128 + ; + pxor m10, pb128 + pxor m8, m8 + pavgb m8, m10 ; f=(f1+1)>>1 + psubb m8, m1 + knotq k1, k1 + paddsb m3{k1}, m3, m8 + psubsb m6{k1}, m6, m8 + pxor m3, pb128 + pxor m6, pb128 + +%if %1 == 16 + ; flat16 filter +%ifidn %2, v + lea t0, [dstq+mstrideq*8] +%endif + SWAP m24, m16, m14 + SWAP m2, m17, m22 + SWAP m7, m18 + + ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 [p5/p4/p2/p1/p0/q0][p6/p3] A + ; write -6 + vpbroadcastd m1, [pb_7_1] + vpbroadcastd m12, [pb_2] + punpcklbw m14, m24, m25 + punpckhbw m22, m24, m25 + pmaddubsw m10, m14, m1 + pmaddubsw m11, m22, m1 ; p6*7+p3 + punpcklbw m8, m2, m7 + punpckhbw m9, m2, m7 + pmaddubsw m8, m12 + pmaddubsw m9, m12 + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3 +%ifidn %2, h + vpbroadcastd m27, [pw_2048] + vpbroadcastd m1, [pb_m1_1] + %define pw2048 m27 + %define pbm1_1 m1 +%endif + punpcklbw m8, m13, m3 + punpckhbw m9, m13, m3 + pmaddubsw m8, m23 + pmaddubsw m9, m23 + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3+p2+p1 + punpcklbw m8, m4, m5 + punpckhbw m9, m4, m5 + pmaddubsw m8, m23 + pmaddubsw m9, m23 + paddw m10, m8 + paddw m11, m9 ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 +%ifidn %2, v + vmovdqu8 [t0+strideq*2]{k4}, m8 ; p5 +%else + vpblendmb m8{k4}, m2, m8 + mova [rsp+1*64], m8 +%endif + + ; sub p6*2, add p3/q1 [reuse p6/p3 from A][-p6,+q1|save] B + ; write -5 + pmaddubsw m14, pbm1_1 + pmaddubsw m22, pbm1_1 + paddw m10, m14 + paddw m11, m22 ; p6*6+p5*2+p4*2+p3*2+p2+p1+p0+q0 + punpcklbw m8, m24, m6 + punpckhbw m9, m24, m6 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p6*5+p5*2+p4*2+p3*2+p2+p1+p0+q0+q1 + SWAP m18, m8 + SWAP m23, m9 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 +%ifidn %2, v + vmovdqu8 [t0+stride3q]{k4}, m8 ; p4 +%else + vpblendmb m8{k4}, m7, m8 + mova [rsp+2*64], m8 +%endif + + ; sub p6/p5, add p2/q2 [-p6,+p2][-p5,+q2|save] C + ; write -4 + SWAP m14, m16 + punpcklbw m8, m24, m13 + punpckhbw m9, m24, m13 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p6*4+p5*2+p4*2+p3*2+p2*2+p1+p0+q0+q1 + punpcklbw m8, m2, m14 + punpckhbw m2, m14 + pmaddubsw m8, pbm1_1 + pmaddubsw m2, pbm1_1 + paddw m10, m8 + paddw m11, m2 ; p6*4+p5+p4*2+p3*2+p2*2+p1+p0+q0+q1+q2 + SWAP m16, m8 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 +%ifidn %2, v + vmovdqu8 [t0+strideq*4]{k4}, m8 ; p3 +%else + vpblendmb m8{k4}, m25, m8 + mova [rsp+3*64], m8 +%endif + + ; sub p6/p4, add p1/q3 [-p6,+p1][-p4,+q3|save] D + ; write -3 + SWAP m22, m17 + punpcklbw m8, m24, m3 + punpckhbw m9, m24, m3 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p6*3+p5+p4*2+p3*2+p2*2+p1*2+p0+q0+q1+q2 + punpcklbw m8, m7, m22 + punpckhbw m7, m22 + pmaddubsw m8, pbm1_1 + pmaddubsw m7, pbm1_1 + paddw m10, m8 + paddw m11, m7 ; p6*3+p5+p4+p3*2+p2*2+p1*2+p0+q0+q1+q2+q3 + SWAP m17, m8 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 + vpblendmb m15{k4}, m13, m8 ; don't clobber p2/m13 since we need it in F + + ; sub p6/p3, add p0/q4 [-p6,+p0][-p3,+q4|save] E + ; write -2 +%ifidn %2, v + lea t0, [dstq+strideq*4] +%endif + punpcklbw m8, m24, m4 + punpckhbw m9, m24, m4 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p6*2+p5+p4+p3*2+p2*2+p1*2+p0*2+q0+q1+q2+q3 + punpcklbw m8, m25, m29 + punpckhbw m9, m25, m29 + SWAP m26, m29 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p6*2+p5+p4+p3+p2*2+p1*2+p0*2+q0+q1+q2+q3+q4 + SWAP m29, m8 + SWAP m0, m9 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 + vpblendmb m12{k4}, m3, m8 ; don't clobber p1/m3 since we need it in G + + ; sub p6/p2, add q0/q5 [-p6,+q0][-p2,+q5|save] F + ; write -1 +%ifidn %2, h + SWAP m28, m24 + punpcklbw m8, m28, m5 + punpckhbw m24, m28, m5 +%else + punpcklbw m8, m24, m5 + punpckhbw m24, m5 +%endif + pmaddubsw m8, pbm1_1 + pmaddubsw m24, pbm1_1 + paddw m10, m8 + paddw m11, m24 ; p6+p5+p4+p3+p2*2+p1*2+p0*2+q0*2+q1+q2+q3+q4 + punpcklbw m24, m13, m30 + punpckhbw m9, m13, m30 +%ifidn %2, h + SWAP m27, m30 +%endif + SWAP m13, m15 + pmaddubsw m24, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m24 + paddw m11, m9 ; p6+p5+p4+p3+p2+p1*2+p0*2+q0*2+q1+q2+q3+q4+q5 + SWAP m30, m24 + SWAP m15, m9 +%ifidn %2, h + SWAP m9, m24 + %define pw2048 m9 +%endif + pmulhrsw m24, m10, pw2048 + pmulhrsw m8, m11, pw2048 + paddw m10, m18 ; p5+p4+p3+p2+p1*2+p0*2+q0*2+q1*2+q2+q3+q4+q5 + paddw m11, m23 + packuswb m24, m8 + punpcklbw m8, m3, m31 + pmaddubsw m8, pbm1_1 + paddw m10, m8 ; p5+p4+p3+p2+p1+p0*2+q0*2+q1*2+q2+q3+q4+q5+q6 + SWAP m18, m8 + pmulhrsw m8, m10, pw2048 + paddw m10, m16 ; p4+p3+p2+p1+p0*2+q0*2+q1*2+q2*2+q3+q4+q5+q6 +%ifidn %2, h + SWAP m16, m9 + %define pw2048 m16 +%endif + punpckhbw m9, m3, m31 + SWAP m3, m12 + pmaddubsw m9, pbm1_1 + paddw m11, m9 ; p5+p4+p3+p2+p1+p0*2+q0*2+q1*2+q2+q3+q4+q5+q6 + SWAP m23, m9 + pmulhrsw m9, m11, pw2048 + paddw m11, m2 ; p4+p3+p2+p1+p0*2+q0*2+q1*2+q2*2+q3+q4+q5+q6 +%ifidn %2, h + SWAP m2, m1 + %define pbm1_1 m2 +%endif + vpblendmb m1{k4}, m4, m24 ; don't clobber p0/m4 since we need it in H + + ; sub p6/p1, add q1/q6 [reuse -p6,+q1 from B][-p1,+q6|save] G + ; write +0 + SWAP m24, m31 ; q6 + packuswb m8, m9 +%ifidn %2, h + SWAP m31, m2 + %define pbm1_1 m31 +%endif + vpblendmb m12{k4}, m5, m8 ; don't clobber q0/m5 since we need it in I + + ; sub p5/p0, add q2/q6 [reuse -p5,+q2 from C][-p0,+q6] H + ; write +1 + punpcklbw m8, m4, m24 + punpckhbw m2, m4, m24 + SWAP m4, m1 + pmaddubsw m8, pbm1_1 + pmaddubsw m2, pbm1_1 + paddw m10, m8 + paddw m11, m2 ; p4+p3+p2+p1+p0+q0*2+q1*2+q2*2+q3+q4+q5+q6*2 + pmulhrsw m2, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m2, m9 + vpblendmb m2{k4}, m6, m2 ; don't clobber q1/m6 since we need it in K + + ; sub p4/q0, add q3/q6 [reuse -p4,+q3 from D][-q0,+q6] I + ; write +2 + paddw m10, m17 ; p3+p2+p1+p0+q0*2+q1*2+q2*2+q3*2+q4+q5+q6*2 + paddw m11, m7 + punpcklbw m8, m5, m24 + punpckhbw m9, m5, m24 + SWAP m5, m12 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p3+p2+p1+p0+q0+q1*2+q2*2+q3*2+q4+q5+q6*3 + pmulhrsw m7, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m7, m9 + vpblendmb m7{k4}, m14, m7 ; don't clobber q2/m14 since we need it in K + + ; sub p3/q1, add q4/q6 [reuse -p3,+q4 from E][-q1,+q6] J + ; write +3 + paddw m10, m29 ; p2+p1+p0+q0+q1*2+q2*2+q3*2+q4*2+q5+q6*3 + paddw m11, m0 + punpcklbw m8, m6, m24 + punpckhbw m9, m6, m24 + SWAP 2, 6 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p2+p1+p0+q0+q1+q2*2+q3*2+q4*2+q5+q6*4 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 +%ifidn %2, v + vmovdqu8 [t0+mstrideq]{k4}, m8 +%else + SWAP m29, m16 + %define pw2048 m29 + vpblendmb m16{k4}, m22, m8 +%endif + + ; sub p2/q2, add q5/q6 [reuse -p2,+q5 from F][-q2,+q6] K + ; write +4 + paddw m10, m30 ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + paddw m11, m15 +%ifidn %2, h + SWAP m15, m8 +%endif + punpcklbw m8, m14, m24 + punpckhbw m9, m14, m24 + SWAP 14, 7 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m8, m10, pw2048 + pmulhrsw m9, m11, pw2048 + packuswb m8, m9 +%ifidn %2, v + vmovdqu8 [t0+strideq*0]{k4}, m8 ; q4 +%else + vpblendmb m17{k4}, m26, m8 +%endif + + ; sub p1/q3, add q6*2 [reuse -p1,+q6 from G][-q3,+q6] L + ; write +5 + paddw m10, m18 ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + paddw m11, m23 + punpcklbw m8, m22, m24 + punpckhbw m9, m22, m24 + SWAP m30, m24 + pmaddubsw m8, pbm1_1 + pmaddubsw m9, pbm1_1 + paddw m10, m8 + paddw m11, m9 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m10, pw2048 + pmulhrsw m11, pw2048 + packuswb m10, m11 +%ifidn %2, v + vmovdqu8 [t0+strideq*1]{k4}, m10 ; q5 +%else + vmovdqu8 m27{k4}, m10 +%endif + +%ifidn %2, v + lea t0, [dstq+mstrideq*4] +%endif +%endif + +%if %1 >= 8 + ; flat8 filter + vpbroadcastd m9, [pb_3_1] + vpbroadcastd m10, [pb_2_1] +%if %1 == 16 + vpbroadcastd m23, [pb_1] + vpbroadcastd m0, [pb_4] +%elifidn %2, h + vpbroadcastd m31, [pb_m1_1] + %define pbm1_1 m31 +%endif + punpcklbw m24, m25, m3 + punpckhbw m26, m25, m3 + pmaddubsw m2, m24, m9 + pmaddubsw m7, m26, m9 ; 3 * p3 + p1 + punpcklbw m8, m13, m4 + punpckhbw m11, m13, m4 + pmaddubsw m8, m10 + pmaddubsw m11, m10 + paddw m2, m8 + paddw m7, m11 ; 3 * p3 + 2 * p2 + p1 + p0 + punpcklbw m8, m5, m0 + punpckhbw m11, m5, m0 + pmaddubsw m8, m23 + pmaddubsw m11, m23 + paddw m2, m8 + paddw m7, m11 ; 3 * p3 + 2 * p2 + p1 + p0 + q0 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 +%if is_h || %1 == 16 + vpblendmb m10{k2}, m13, m8 ; p2 +%endif +%ifidn %2, v + %if %1 == 8 + vmovdqu8 [t0+strideq*1]{k2}, m8 + %else + mova [t0+strideq*1], m10 + %endif +%endif + + pmaddubsw m8, m24, pbm1_1 + pmaddubsw m11, m26, pbm1_1 + paddw m2, m8 + paddw m7, m11 + punpcklbw m8, m13, m6 + punpckhbw m11, m13, m6 + pmaddubsw m8, pbm1_1 + pmaddubsw m11, pbm1_1 + paddw m2, m8 + paddw m7, m11 ; 2 * p3 + p2 + 2 * p1 + p0 + q0 + q1 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendmb m8{k2}, m3, m8 ; p1 +%ifidn %2, v + mova [t0+strideq*2], m8 +%else + SWAP m18, m8 +%endif + + pmaddubsw m24, m23 + pmaddubsw m26, m23 + psubw m2, m24 + psubw m7, m26 + punpcklbw m8, m4, m14 + punpckhbw m11, m4, m14 + pmaddubsw m8, m23 + pmaddubsw m11, m23 + paddw m2, m8 + paddw m7, m11 ; p3 + p2 + p1 + 2 * p0 + q0 + q1 + q2 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendmb m8{k2}, m4, m8 ; p0 +%ifidn %2, v + mova [t0+stride3q], m8 +%else + SWAP m29, m8 +%endif + + punpcklbw m24, m5, m22 + punpckhbw m26, m5, m22 + pmaddubsw m8, m24, m23 + pmaddubsw m11, m26, m23 + paddw m2, m8 + paddw m7, m11 + punpcklbw m8, m4, m25 + punpckhbw m11, m4, m25 + pmaddubsw m8, m23 + pmaddubsw m11, m23 + psubw m2, m8 + psubw m7, m11 ; p2 + p1 + p0 + 2 * q0 + q1 + q2 + q3 + 4 + psrlw m8, m2, 3 + psrlw m11, m7, 3 + packuswb m8, m11 + vpblendmb m11{k2}, m5, m8 ; q0 +%ifidn %2, v + mova [dstq+strideq*0], m11 +%endif + + pmaddubsw m24, pbm1_1 + pmaddubsw m26, pbm1_1 + paddw m2, m24 + paddw m7, m26 + punpcklbw m8, m13, m6 + punpckhbw m13, m6 + pmaddubsw m8, pbm1_1 + pmaddubsw m13, pbm1_1 + paddw m2, m8 + paddw m7, m13 ; p1 + p0 + q0 + 2 * q1 + q2 + 2 * q3 + 4 + psrlw m8, m2, 3 + psrlw m13, m7, 3 + packuswb m8, m13 + vpblendmb m13{k2}, m6, m8 ; q1 +%ifidn %2, v + mova [dstq+strideq*1], m13 +%endif + + punpcklbw m24, m3, m6 + punpckhbw m26, m3, m6 + pmaddubsw m24, m23 + pmaddubsw m26, m23 + psubw m2, m24 + psubw m7, m26 + punpcklbw m24, m14, m22 + punpckhbw m26, m14, m22 + pmaddubsw m24, m23 + pmaddubsw m26, m23 + paddw m2, m24 + paddw m7, m26 ; p0 + q0 + q1 + q2 + 2 * q2 + 3 * q3 + 4 + psrlw m2, 3 + psrlw m7, 3 + packuswb m2, m7 +%if is_h || %1 == 16 + vpblendmb m2{k2}, m14, m2 ; q2 +%endif +%ifidn %2, v + %if %1 == 8 + vmovdqu8 [dstq+strideq*2]{k2}, m2 + %else + mova [dstq+strideq*2], m2 + %endif +%endif + +%ifidn %2, h + SWAP m24, m18 + SWAP m26, m29 +%if %1 == 8 + ; 16x8 transpose + punpcklbw m3, m25, m10 + punpckhbw m25, m10 + punpcklbw m10, m24, m26 + punpckhbw m24, m26 + punpcklbw m26, m11, m13 + punpckhbw m11, m13 + punpcklbw m13, m2, m22 + punpckhbw m2, m22 + ; + punpcklwd m22, m3, m10 + punpckhwd m3, m10 + punpcklwd m10, m25, m24 + punpckhwd m25, m24 + punpcklwd m24, m26, m13 + punpckhwd m26, m13 + punpcklwd m13, m11, m2 + punpckhwd m11, m2 + ; + punpckldq m2, m22, m24 + punpckhdq m22, m24 + punpckldq m24, m3, m26 + punpckhdq m3, m26 + punpckldq m26, m10, m13 + punpckhdq m10, m13 + punpckldq m13, m25, m11 + punpckhdq m25, m11 + ; write 8x32 + vpbroadcastd ym16, strided + pmulld ym16, [hmulD] + lea t1, [dstq+strideq*2] + lea t2, [dstq+strideq*4] + lea t3, [t1 +strideq*4] + lea t0, [dstq+strideq*8] + kmovb k1, k6 + kmovb k2, k6 + kmovb k3, k6 + kmovb k4, k6 + vpscatterdq [dstq+ym16-4]{k1}, m2 + vpscatterdq [t1 +ym16-4]{k2}, m22 + vpscatterdq [t2 +ym16-4]{k3}, m24 + vpscatterdq [t3 +ym16-4]{k4}, m3 + lea t1, [t0+strideq*2] + lea t2, [t0+strideq*4] + lea t3, [t1+strideq*4] + kmovb k1, k6 + kmovb k2, k6 + kmovb k3, k6 + kmovb k4, k6 + vpscatterdq [t0+ym16-4]{k1}, m26 + vpscatterdq [t1+ym16-4]{k2}, m10 + vpscatterdq [t2+ym16-4]{k3}, m13 + vpscatterdq [t3+ym16-4]{k4}, m25 +%else + ; 16x16 transpose and store + SWAP 5, 10, 2 + SWAP 6, 24 + SWAP 7, 26 + SWAP 8, 11 + SWAP 9, 13 + mova m24, [rsp+0*64] + SWAP m26, m28 + mova m2, [rsp+1*64] + mova m3, [rsp+2*64] + mova m4, [rsp+3*64] + SWAP m11, m16 + SWAP m25, m17 + SWAP m13, m27 + SWAP m14, m30 + TRANSPOSE_16X16B 1, 0, [rsp+4*64] + movu [dstq+strideq*0-8], xm24 + movu [dstq+strideq*1-8], xm26 + movu [dstq+strideq*2-8], xm2 + movu [dstq+stride3q -8], xm3 + lea t0, [dstq+strideq*4] + movu [t0+strideq*0-8], xm4 + movu [t0+strideq*1-8], xm5 + movu [t0+strideq*2-8], xm6 + movu [t0+stride3q -8], xm7 + lea t0, [t0+strideq*4] + movu [t0+strideq*0-8], xm8 + movu [t0+strideq*1-8], xm9 + movu [t0+strideq*2-8], xm10 + movu [t0+stride3q -8], xm11 + lea t0, [t0+strideq*4] + movu [t0+strideq*0-8], xm25 + movu [t0+strideq*1-8], xm13 + movu [t0+strideq*2-8], xm14 + movu [t0+stride3q -8], xm22 + lea t0, [t0+strideq*4] + vextracti128 [t0+strideq*0-8], ym24, 1 + vextracti128 [t0+strideq*1-8], ym26, 1 + vextracti128 [t0+strideq*2-8], ym2, 1 + vextracti128 [t0+stride3q -8], ym3, 1 + lea t0, [t0+strideq*4] + vextracti128 [t0+strideq*0-8], ym4, 1 + vextracti128 [t0+strideq*1-8], ym5, 1 + vextracti128 [t0+strideq*2-8], ym6, 1 + vextracti128 [t0+stride3q -8], ym7, 1 + lea t0, [t0+strideq*4] + vextracti128 [t0+strideq*0-8], ym8, 1 + vextracti128 [t0+strideq*1-8], ym9, 1 + vextracti128 [t0+strideq*2-8], ym10, 1 + vextracti128 [t0+stride3q -8], ym11, 1 + lea t0, [t0+strideq*4] + vextracti128 [t0+strideq*0-8], ym25, 1 + vextracti128 [t0+strideq*1-8], ym13, 1 + vextracti128 [t0+strideq*2-8], ym14, 1 + vextracti128 [t0+stride3q -8], ym22, 1 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m24, 2 + vextracti32x4 [t0+strideq*1-8], m26, 2 + vextracti32x4 [t0+strideq*2-8], m2, 2 + vextracti32x4 [t0+stride3q -8], m3, 2 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m4, 2 + vextracti32x4 [t0+strideq*1-8], m5, 2 + vextracti32x4 [t0+strideq*2-8], m6, 2 + vextracti32x4 [t0+stride3q -8], m7, 2 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m8, 2 + vextracti32x4 [t0+strideq*1-8], m9, 2 + vextracti32x4 [t0+strideq*2-8], m10, 2 + vextracti32x4 [t0+stride3q -8], m11, 2 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m25, 2 + vextracti32x4 [t0+strideq*1-8], m13, 2 + vextracti32x4 [t0+strideq*2-8], m14, 2 + vextracti32x4 [t0+stride3q -8], m22, 2 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m24, 3 + vextracti32x4 [t0+strideq*1-8], m26, 3 + vextracti32x4 [t0+strideq*2-8], m2, 3 + vextracti32x4 [t0+stride3q -8], m3, 3 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m4, 3 + vextracti32x4 [t0+strideq*1-8], m5, 3 + vextracti32x4 [t0+strideq*2-8], m6, 3 + vextracti32x4 [t0+stride3q -8], m7, 3 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m8, 3 + vextracti32x4 [t0+strideq*1-8], m9, 3 + vextracti32x4 [t0+strideq*2-8], m10, 3 + vextracti32x4 [t0+stride3q -8], m11, 3 + lea t0, [t0+strideq*4] + vextracti32x4 [t0+strideq*0-8], m25, 3 + vextracti32x4 [t0+strideq*1-8], m13, 3 + vextracti32x4 [t0+strideq*2-8], m14, 3 + vextracti32x4 [t0+stride3q -8], m22, 3 +%endif +%endif + +%elif %1 == 6 + ; flat6 filter + vpbroadcastd m15, [pb_3_1] + vpbroadcastd m12, [pb_2] + punpcklbw m8, m13, m5 + punpckhbw m11, m13, m5 + pmaddubsw m0, m8, m15 + pmaddubsw m1, m11, m15 + punpcklbw m7, m4, m3 + punpckhbw m10, m4, m3 + pmaddubsw m2, m7, m12 + pmaddubsw m12, m10, m12 +%ifidn %2, h + vpbroadcastd m15, [pb_m1_1] + %define pbm1_1 m15 +%endif + paddw m0, m2 + paddw m1, m12 + pmulhrsw m2, m0, m16 + pmulhrsw m12, m1, m16 + packuswb m2, m12 + vpblendmb m2{k2}, m3, m2 ; p1 +%ifidn %2, v + mova [t0+strideq*2], m2 +%endif + + pmaddubsw m8, pbm1_1 + pmaddubsw m11, pbm1_1 + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m13, m6 + punpckhbw m11, m13, m6 + pmaddubsw m8, pbm1_1 + pmaddubsw m11, pbm1_1 + paddw m0, m8 + paddw m1, m11 + pmulhrsw m12, m0, m16 + pmulhrsw m13, m1, m16 + packuswb m12, m13 + vpblendmb m12{k2}, m4, m12 ; p0 +%ifidn %2, v + mova [t0+stride3q], m12 +%endif + + vpbroadcastd m9, [pb_m1_2] + vpbroadcastd m4, [pb_m1_0] + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m3, m14 + punpckhbw m11, m3, m14 + pmaddubsw m14, m8, pbm1_1 + pmaddubsw m13, m11, pbm1_1 + paddw m0, m14 + paddw m1, m13 + pmulhrsw m14, m0, m16 + pmulhrsw m13, m1, m16 + packuswb m14, m13 + vpblendmb m14{k2}, m5, m14 ; q0 +%ifidn %2, v + mova [dstq+strideq*0], m14 +%endif + + pmaddubsw m8, m9 + pmaddubsw m11, m9 + paddw m0, m8 + paddw m1, m11 + pmaddubsw m7, m4 + pmaddubsw m10, m4 + paddw m0, m7 + paddw m1, m10 + pmulhrsw m0, m16 + pmulhrsw m1, m16 + packuswb m0, m1 + vpblendmb m0{k2}, m6, m0 ; q1 +%ifidn %2, v + mova [dstq+strideq*1], m0 +%else + TRANSPOSE_16x4_AND_WRITE_4x32 2, 12, 14, 0, 1 +%endif +%else ; %1 == 4 +%ifidn %2, v + mova [t0+strideq*0], m3 ; p1 + mova [t0+strideq*1], m4 ; p0 + mova [t0+strideq*2], m5 ; q0 + mova [t0+stride3q ], m6 ; q1 +%else + TRANSPOSE_16x4_AND_WRITE_4x32 3, 4, 5, 6, 7 +%endif +%endif +%endmacro + +%define k7 k6 + +INIT_ZMM avx512icl +cglobal lpf_v_sb_y_8bpc, 7, 10, 32, dst, stride, mask, l, l_stride, \ + lut, w, stride3, mstride + DECLARE_REG_TMP 9 + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + mova m21, [pb_4x0_4x4_4x8_4x12] + mova m20, [pb_mask] + vpbroadcastd m19, [pb_128] + vpbroadcastd m28, [pb_m1_1] + vpbroadcastd m27, [pw_2048] + %define pbshuf m21 + %define pbmask m20 + %define pb128 m19 + %define pbm1_1 m28 + %define pw2048 m27 + +.loop: + cmp word [maskq+8], 0 ; vmask[2] + je .no_flat16 + + FILTER 16, v + jmp .end + +.no_flat16: + cmp word [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 8, v + jmp .end + +.no_flat: + cmp word [maskq+0], 0 ; vmask[0] + je .end + + call .v4 + +.end: + add lq, 64 + add dstq, 64 + add maskq, 2 + sub wd, 16 + jg .loop + RET +ALIGN function_align +RESET_MM_PERMUTATION +.v4: + FILTER 4, v + ret + +cglobal lpf_h_sb_y_8bpc, 7, 13, 32, 5*64, dst, stride, mask, l, l_stride, \ + lut, h, stride3, stride8 + DECLARE_REG_TMP 9, 10, 11, 12 + shl l_strideq, 2 + sub lq, 4 + lea stride3q, [strideq*3] + lea stride8q, [strideq*8] + kxnorw k6, k6, k6 + vpbroadcastd m19, strided + vpbroadcastd m20, l_strided + pmulld m21, m19, [hmulA] + pmulld m20, [hmulB] + pmulld m19, [hmulC] + %define pbshuf [pb_4x0_4x4_4x8_4x12] + %define pbmask [pb_mask] + %define pb128 [pb_128]{bcstd} + shl l_strideq, 1 + +.loop: + cmp word [maskq+8], 0 ; vmask[2] + je .no_flat16 + + FILTER 16, h + jmp .end + +.no_flat16: + cmp word [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 8, h + jmp .end + +.no_flat: + cmp word [maskq+0], 0 ; vmask[0] + je .end + + call .h4 + +.end: + lea lq, [lq+l_strideq*8] + lea dstq, [dstq+stride8q*8] + add maskq, 2 + sub hd, 16 + jg .loop + RET +ALIGN function_align +RESET_MM_PERMUTATION +.h4: + FILTER 4, h + ret + +cglobal lpf_v_sb_uv_8bpc, 7, 10, 22, dst, stride, mask, l, l_stride, \ + lut, w, stride3, mstride + DECLARE_REG_TMP 9 + shl l_strideq, 2 + sub lq, l_strideq + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] + mova m21, [pb_4x0_4x4_4x8_4x12] + mova m20, [pb_mask] + vpbroadcastd m19, [pb_128] + vpbroadcastd m17, [pb_m1_1] + vpbroadcastd m16, [pw_4096] + %define pbshuf m21 + %define pbmask m20 + %define pb128 m19 + %define pbm1_1 m17 + +.loop: + cmp word [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 6, v + jmp .end + +.no_flat: + cmp word [maskq+0], 0 ; vmask[0] + je .end + + call mangle(private_prefix %+ _lpf_v_sb_y_8bpc_avx512icl).v4 + +.end: + add lq, 64 + add dstq, 64 + add maskq, 2 + sub wd, 16 + jg .loop + RET + +%undef k7 +cglobal lpf_h_sb_uv_8bpc, 7, 12, 22, dst, stride, mask, l, l_stride, \ + lut, h, stride3, stride8 + DECLARE_REG_TMP 9, 10, 11 + mov r7d, 0xffff + movzx r8d, r7b + cmp hd, 9 + cmovb r7d, r8d + kmovw k6, r7d ; h > 8 ? 0xffff : 0x00ff + shl l_strideq, 2 + sub lq, 4 + kshiftrw k7, k6, 4 ; h > 8 ? 0xff : 0xf0 + lea stride3q, [strideq*3] + lea stride8q, [strideq*8] + vpbroadcastd m19, strided + vpbroadcastd m20, l_strided + pmulld m21, m19, [hmulA] + pmulld m20, [hmulB] + pmulld m19, [hmulC] + mova m18, [pb_mask] + vpbroadcastd m17, [pb_128] + vpbroadcastd m16, [pw_4096] + %define pbshuf [pb_4x0_4x4_4x8_4x12] + %define pbmask m18 + %define pb128 m17 + add l_strideq, l_strideq + +.loop: + cmp word [maskq+4], 0 ; vmask[1] + je .no_flat + + FILTER 6, h + jmp .end + +.no_flat: + cmp word [maskq+0], 0 ; vmask[0] + je .end + + call mangle(private_prefix %+ _lpf_h_sb_y_8bpc_avx512icl).h4 + +.end: + lea lq, [lq+l_strideq*8] + lea dstq, [dstq+stride8q*8] + add maskq, 2 + sub hd, 16 + jg .loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/loopfilter_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2348 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +pb_4x0_4x4_4x8_4x12: db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12 +pb_7_1: times 8 db 7, 1 +pb_3_1: times 8 db 3, 1 +pb_2_1: times 8 db 2, 1 +pb_m1_0: times 8 db -1, 0 +pb_m1_1: times 8 db -1, 1 +pb_m1_2: times 8 db -1, 2 +pb_1: times 16 db 1 +pb_2: times 16 db 2 +pb_3: times 16 db 3 +pb_4: times 16 db 4 +pb_16: times 16 db 16 +pb_63: times 16 db 63 +pb_64: times 16 db 64 +pb_128: times 16 db 0x80 +pb_129: times 16 db 0x81 +pb_240: times 16 db 0xf0 +pb_248: times 16 db 0xf8 +pb_254: times 16 db 0xfe + +pw_2048: times 8 dw 2048 +pw_4096: times 8 dw 4096 + +pd_mask: dd 1, 2, 4, 8 + +SECTION .text + +%macro ABSSUB 4 ; dst, a, b, tmp + psubusb %1, %2, %3 + psubusb %4, %3, %2 + por %1, %4 +%endmacro + +%macro TRANSPOSE_16x4_AND_WRITE_4x16 5 + ; transpose 16x4 + punpcklbw m%5, m%1, m%2 + punpckhbw m%1, m%2 + punpcklbw m%2, m%3, m%4 + punpckhbw m%3, m%4 + punpcklwd m%4, m%5, m%2 + punpckhwd m%5, m%2 + punpcklwd m%2, m%1, m%3 + punpckhwd m%1, m%3 + + ; write out +%assign %%n 0 +%rep 4 + movd [dstq+strideq *0-2], xm%4 + movd [dstq+strideq *4-2], xm%5 + movd [dstq+strideq *8-2], xm%2 + movd [dstq+stride3q*4-2], xm%1 + add dstq, strideq +%if %%n < 3 + psrldq xm%4, 4 + psrldq xm%5, 4 + psrldq xm%2, 4 + psrldq xm%1, 4 +%endif +%assign %%n (%%n+1) +%endrep + lea dstq, [dstq+stride3q*4] +%endmacro + +%macro TRANSPOSE_16X16B 2 ; output_transpose, mem +%if %1 == 0 + mova %2, m15 ; m7 in 32-bit +%endif + + ; input in m0-7 + punpcklbw m15, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + punpcklbw m3, m4, m5 + punpckhbw m4, m5 +%if ARCH_X86_64 + SWAP 4, 5, 7 +%else + %if %1 == 0 + mova m5, %2 + %else + mova m5, [esp+1*16] + %endif + mova %2, m4 +%endif + punpcklbw m4, m6, m5 + punpckhbw m6, m5 + + ; interleaved in m15,0,1,2,3,7,4,6 + punpcklwd m5, m15, m1 + punpckhwd m15, m1 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + punpcklwd m2, m3, m4 + punpckhwd m3, m4 +%if ARCH_X86_64 + SWAP 3, 4, 7 +%else + mova m4, %2 + mova %2, m3 +%endif + punpcklwd m3, m4, m6 + punpckhwd m4, m6 + + ; interleaved in m5,15,1,0,2,7,3,4 + punpckldq m6, m5, m2 + punpckhdq m5, m2 +%if ARCH_X86_64 + SWAP 2, 7, 5 +%else + mova m2, %2 + mova [esp+1*16], m5 +%endif + punpckldq m5, m15, m2 + punpckhdq m15, m2 + punpckldq m2, m1, m3 + punpckhdq m1, m3 + punpckldq m3, m0, m4 + punpckhdq m0, m4 + +%if ARCH_X86_32 + mova [esp+0*16], m6 + mova [esp+2*16], m5 + mova [esp+3*16], m15 + mova [esp+4*16], m2 + mova [esp+5*16], m1 + mova [esp+6*16], m3 + mova [esp+7*16], m0 + mova m8, [esp+ 8*16] + mova m9, [esp+ 9*16] + mova m10, [esp+10*16] + %if %1 == 0 + mova m11, [esp+11*16] + mova m12, [esp+12*16] + mova m13, [esp+13*16] + mova m14, [esp+14*16] + %else + mova m11, [esp+20*16] + mova m12, [esp+15*16] + mova m13, [esp+16*16] + mova m14, [esp+17*16] + %endif +%endif + + ; input in m8-m15 +%if ARCH_X86_64 + SWAP 7, 4 +%endif + punpcklbw m7, m8, m9 + punpckhbw m8, m9 + punpcklbw m9, m10, m11 + punpckhbw m10, m11 + punpcklbw m11, m12, m13 + punpckhbw m12, m13 +%if ARCH_X86_64 + mova m13, %2 +%else + %if %1 == 0 + mova m13, [esp+15*16] + %else + mova m13, [esp+18*16] + %endif +%endif + mova %2, m12 + punpcklbw m12, m14, m13 + punpckhbw m14, m14, m13 + + ; interleaved in m7,8,9,10,11,rsp%2,12,14 + punpcklwd m13, m7, m9 + punpckhwd m7, m9 + punpcklwd m9, m8, m10 + punpckhwd m8, m10 + punpcklwd m10, m11, m12 + punpckhwd m11, m12 + mova m12, %2 + mova %2, m11 + punpcklwd m11, m12, m14 + punpckhwd m12, m14 + + ; interleaved in m13,7,9,8,10,rsp%2,11,12 + punpckldq m14, m13, m10 + punpckhdq m13, m10 + punpckldq m10, m9, m11 + punpckhdq m9, m11 + punpckldq m11, m8, m12 + punpckhdq m8, m12 + mova m12, %2 + mova %2, m8 + punpckldq m8, m7, m12 + punpckhdq m7, m12 + +%if ARCH_X86_32 + mova [esp+ 8*16], m10 + mova [esp+ 9*16], m9 + mova [esp+10*16], m11 + SWAP 6, 1 + SWAP 4, 2 + SWAP 5, 3 + mova m6, [esp+0*16] + mova m4, [esp+1*16] + mova m5, [esp+2*16] +%endif + + ; interleaved in m6,7,5,15,2,1,3,0,14,13,10,9,11,rsp%2,8,7 + punpcklqdq m12, m6, m14 + punpckhqdq m6, m14 + punpcklqdq m14, m4, m13 + punpckhqdq m4, m13 + punpcklqdq m13, m5, m8 + punpckhqdq m5, m8 +%if ARCH_X86_64 + SWAP 8, 5 +%else + mova m8, [esp+3*16] + mova [esp+27*16], m5 + %define m15 m8 +%endif + punpcklqdq m5, m15, m7 + punpckhqdq m15, m7 + +%if ARCH_X86_32 + mova [esp+11*16], m12 + mova [esp+12*16], m6 + mova [esp+13*16], m14 + mova [esp+14*16], m4 + mova [esp+26*16], m13 + mova [esp+ 0*16], m5 + mova [esp+ 1*16], m15 + mova m2, [esp+ 4*16] + mova m10, [esp+ 8*16] + mova m1, [esp+ 5*16] + mova m9, [esp+ 9*16] + mova m3, [esp+ 6*16] + mova m11, [esp+10*16] + mova m0, [esp+ 7*16] +%endif + + punpcklqdq m7, m2, m10 + punpckhqdq m2, m10 + punpcklqdq m10, m1, m9 + punpckhqdq m1, m9 + punpcklqdq m9, m3, m11 + punpckhqdq m3, m11 + mova m11, %2 +%if ARCH_X86_32 + %define m12 m3 +%endif + mova %2, m12 + punpcklqdq m12, m0, m11 + punpckhqdq m0, m11 +%if %1 == 1 + mova m11, %2 +%endif + +%if ARCH_X86_64 + ; interleaved m11,6,14,4,13,8,5,15,7,2,10,1,9,3,12,0 + SWAP 0, 11, 1, 6, 5, 8, 7, 15 + SWAP 2, 14, 12, 9 + SWAP 3, 4, 13 +%else + %if %1 == 0 + mova [esp+15*16], m9 + mova [esp+17*16], m12 + mova [esp+18*16], m0 + mova [esp+28*16], m10 + mova [esp+29*16], m1 + mova m3, [esp+0*16] + mova m4, [esp+1*16] + SWAP m5, m7 + SWAP m6, m2 + %else + SWAP 0, 7 + SWAP 3, 1, 2, 4, 6 + %endif +%endif +%endmacro + +%macro FILTER 2 ; width [4/6/8/16], dir [h/v] +%if ARCH_X86_64 + %define %%flat8mem [rsp+0*16] + %define %%q2mem [rsp+1*16] + %define %%q3mem [rsp+2*16] +%else + %if %1 == 4 || %1 == 6 + %define %%p2mem [esp+ 8*16] + %define %%q2mem [esp+ 9*16] + %define %%flat8mem [esp+10*16] + %else + %ifidn %2, v + %define %%p2mem [esp+16*16] + %define %%q2mem [esp+ 1*16] + %define %%q3mem [esp+18*16] + %define %%flat8mem [esp+ 0*16] + %define %%flat16mem [esp+20*16] + %else + %define %%p2mem [esp+27*16] + %define %%q2mem [esp+28*16] + %define %%q3mem [esp+29*16] + %define %%flat8mem [esp+21*16] + %define %%flat16mem [esp+30*16] + %endif + %endif + %xdefine m12reg m12 +%endif + +%if ARCH_X86_32 + lea stride3q, [strideq*3] +%endif + ; load data +%ifidn %2, v +%if ARCH_X86_32 + mov mstrideq, strideq + neg mstrideq +%endif +%if %1 == 4 + lea tmpq, [dstq+mstrideq*2] + mova m3, [tmpq+strideq*0] ; p1 + mova m4, [tmpq+strideq*1] ; p0 + mova m5, [tmpq+strideq*2] ; q0 + mova m6, [tmpq+stride3q] ; q1 +%else + ; load 6-8 pixels, remainder (for wd=16) will be read inline + lea tmpq, [dstq+mstrideq*4] + ; we load p3 later +%define %%p3mem [dstq+mstrideq*4] + %if ARCH_X86_32 + %define m13 m0 + %define m14 m1 + %define m15 m2 + %endif + mova m13, [tmpq+strideq*1] + mova m3, [tmpq+strideq*2] + mova m4, [tmpq+stride3q] + mova m5, [dstq+strideq*0] + mova m6, [dstq+strideq*1] + mova m14, [dstq+strideq*2] +%if %1 != 6 + mova m15, [dstq+stride3q] +%endif + %if ARCH_X86_32 + mova %%p2mem, m13 + mova %%q2mem, m14 + %define m13 %%p2mem + %define m14 %%q2mem + %if %1 != 6 + mova %%q3mem, m15 + %define m15 %%q3mem + %endif + %endif +%endif +%else ; %2 == h + ; load lines +%if %1 == 4 + ; transpose 4x16 + movd m7, [dstq+strideq*0-2] + movd m3, [dstq+strideq*1-2] + movd m4, [dstq+strideq*2-2] + movd m5, [dstq+stride3q -2] + lea tmpq, [dstq+strideq*4] + punpcklbw m7, m3 + punpcklbw m4, m5 + movd m3, [tmpq+strideq*0-2] + movd m1, [tmpq+strideq*1-2] + movd m5, [tmpq+strideq*2-2] + movd m6, [tmpq+stride3q -2] + lea tmpq, [tmpq+strideq*4] + punpcklbw m3, m1 + punpcklbw m5, m6 + movd m0, [tmpq+strideq*0-2] + movd m1, [tmpq+strideq*1-2] + punpcklbw m0, m1 + movd m1, [tmpq+strideq*2-2] + movd m2, [tmpq+stride3q -2] + punpcklbw m1, m2 + punpcklqdq m7, m0 + punpcklqdq m4, m1 + lea tmpq, [tmpq+strideq*4] + movd m0, [tmpq+strideq*0-2] + movd m1, [tmpq+strideq*1-2] + punpcklbw m0, m1 + movd m1, [tmpq+strideq*2-2] + movd m2, [tmpq+stride3q -2] + punpcklbw m1, m2 + punpcklqdq m3, m0 + punpcklqdq m5, m1 + ; xm7: A0-1,B0-1,C0-1,D0-1,A8-9,B8-9,C8-9,D8-9 + ; xm3: A4-5,B4-5,C4-5,D4-5,A12-13,B12-13,C12-13,D12-13 + ; xm4: A2-3,B2-3,C2-3,D2-3,A10-11,B10-11,C10-11,D10-11 + ; xm5: A6-7,B6-7,C6-7,D6-7,A14-15,B14-15,C14-15,D14-15 + punpcklwd m6, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m3, m5 + punpckhwd m3, m5 + ; xm6: A0-3,B0-3,C0-3,D0-3 + ; xm7: A8-11,B8-11,C8-11,D8-11 + ; xm4: A4-7,B4-7,C4-7,D4-7 + ; xm3: A12-15,B12-15,C12-15,D12-15 + punpckldq m5, m6, m4 + punpckhdq m6, m4 + punpckldq m4, m7, m3 + punpckhdq m7, m3 + ; xm5: A0-7,B0-7 + ; xm6: C0-7,D0-7 + ; xm4: A8-15,B8-15 + ; xm7: C8-15,D8-15 + punpcklqdq m3, m5, m4 + punpckhqdq m5, m5, m4 + punpcklqdq m4, m6, m7 + punpckhqdq m6, m7 + ; xm3: A0-15 + ; xm5: B0-15 + ; xm4: C0-15 + ; xm6: D0-15 + SWAP 4, 5 +%elif %1 == 6 || %1 == 8 + ; transpose 8x16 + movq m7, [dstq+strideq*0-%1/2] + movq m3, [dstq+strideq*1-%1/2] + movq m4, [dstq+strideq*2-%1/2] + movq m5, [dstq+stride3q -%1/2] + lea tmpq, [dstq+strideq*8] + punpcklbw m7, m3 + punpcklbw m4, m5 + movq m3, [tmpq+strideq*0-%1/2] + movq m1, [tmpq+strideq*1-%1/2] + movq m5, [tmpq+strideq*2-%1/2] + movq m6, [tmpq+stride3q -%1/2] + lea tmpq, [dstq+strideq*4] + punpcklbw m3, m1 + punpcklbw m5, m6 + movq m6, [tmpq+strideq*0-%1/2] + movq m0, [tmpq+strideq*1-%1/2] + movq m1, [tmpq+strideq*2-%1/2] + movq m2, [tmpq+stride3q -%1/2] + lea tmpq, [tmpq+strideq*8] + punpcklbw m6, m0 + punpcklbw m1, m2 + movq m2, [tmpq+strideq*2-%1/2] + movq m0, [tmpq+stride3q -%1/2] + punpcklbw m2, m0 +%if ARCH_X86_64 + SWAP m15, m2 +%else + %define m15 [esp+3*16] + mova m15, m2 +%endif + movq m0, [tmpq+strideq*0-%1/2] + movq m2, [tmpq+strideq*1-%1/2] + punpcklbw m0, m2 + ; xm7: A0-1,B0-1,C0-1,D0-1,E0-1,F0-1,G0-1,H0-1 + ; xm3: A8-9,B8-9,C8-9,D8-9,E8-9,F8-9,G8-9,H8-9 + ; xm4: A2-3,B2-3,C2-3,D2-3,E2-3,F2-3,G2-3,H2-3 + ; xm5: A10-11,B10-11,C10-11,D10-11,E10-11,F10-11,G10-11,H10-11 + ; xm6: A4-5,B4-5,C4-5,D4-5,E4-5,F4-5,G4-5,H4-5 + ; xm0: A12-13,B12-13,C12-13,D12-13,E12-13,F12-13,G12-13,H12-13 + ; xm1: A6-7,B6-7,C6-7,D6-7,E6-7,F6-7,G6-7,H6-7 + ; xm2: A14-15,B14-15,C14-15,D14-15,E14-15,F14-15,G14-15,H14-15 + punpcklwd m2, m7, m4 + punpckhwd m7, m4 + punpcklwd m4, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m6, m1 + punpckhwd m6, m1 + punpcklwd m1, m0, m15 + punpckhwd m0, m15 +%if ARCH_X86_64 + SWAP m15, m0 +%else + mova m15, m0 +%endif + ; xm2: A0-3,B0-3,C0-3,D0-3 + ; xm7: E0-3,F0-3,G0-3,H0-3 + ; xm4: A8-11,B8-11,C8-11,D8-11 + ; xm3: E8-11,F8-11,G8-11,H8-11 + ; xm5: A4-7,B4-7,C4-7,D4-7 + ; xm6: E4-7,F4-7,G4-7,H4-7 + ; xm1: A12-15,B12-15,C12-15,D12-15 + ; xm0: E12-15,F12-15,G12-15,H12-15 + punpckldq m0, m2, m5 + punpckhdq m2, m5 + punpckldq m5, m7, m6 +%if %1 != 6 + punpckhdq m7, m6 +%endif + punpckldq m6, m4, m1 + punpckhdq m4, m1 + punpckldq m1, m3, m15 +%if %1 != 6 + punpckhdq m3, m15 + %if ARCH_X86_64 + SWAP m15, m3 + %else + mova m15, m3 + %endif +%endif + ; xm0: A0-7,B0-7 + ; xm2: C0-7,D0-7 + ; xm5: E0-7,F0-7 + ; xm7: G0-7,H0-7 + ; xm6: A8-15,B8-15 + ; xm4: C8-15,D8-15 + ; xm1: E8-15,F8-15 + ; xm3: G8-15,H8-15 + punpcklqdq m3, m0, m6 + punpckhqdq m0, m6 + punpckhqdq m6, m2, m4 + punpcklqdq m2, m4 + punpcklqdq m4, m5, m1 + punpckhqdq m5, m1 +%if %1 == 8 + punpcklqdq m1, m7, m15 + punpckhqdq m7, m15 + ; xm3: A0-15 + ; xm0: B0-15 + ; xm2: C0-15 + ; xm6: D0-15 + ; xm4: E0-15 + ; xm5: F0-15 + ; xm1: G0-15 + ; xm7: H0-15 +%if ARCH_X86_64 + SWAP 11, 3, 2 + SWAP 13, 0 + SWAP 6, 5, 4 + SWAP 14, 1 + SWAP 15, 7 + ; 3,0,2,6,4,5,1,7 -> 11,13,3,4,5,6,14,15 + mova [rsp+21*16], m11 + %define %%p3mem [rsp+21*16] +%else + %define m11 [esp+26*16] + %define m13 [esp+27*16] + %define m14 [esp+28*16] + %define m15 [esp+29*16] + mova m11, m3 + mova m13, m0 + SWAP 3, 2 + SWAP 6, 5, 4 + mova m14, m1 + mova m15, m7 + %define %%p3mem [esp+26*16] +%endif +%else + %if ARCH_X86_64 + SWAP 13, 3, 0 + SWAP 14, 5, 6, 4, 2 + ; 3,0,2,6,4,5 -> 13,3,4,5,6,14 + %else + %define m13 %%p2mem + %define m14 %%q2mem + mova m13, m3 + mova m14, m5 + SWAP 3, 0 + SWAP 5, 6, 4, 2 + ; 0,2,6,4 -> 3,4,5,6 + %endif +%endif +%else +%if ARCH_X86_64 + mova [rsp+20*16], m12 +%endif + ; load and 16x16 transpose. We only use 14 pixels but we'll need the + ; remainder at the end for the second transpose +%if ARCH_X86_32 + %xdefine m8 m0 + %xdefine m9 m1 + %xdefine m10 m2 + %xdefine m11 m3 + %xdefine m12 m4 + %xdefine m13 m5 + %xdefine m14 m6 + %xdefine m15 m7 + lea tmpq, [dstq+strideq*8] + movu m8, [tmpq+strideq*0-8] + movu m9, [tmpq+strideq*1-8] + movu m10, [tmpq+strideq*2-8] + movu m11, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + movu m12, [tmpq+strideq*0-8] + movu m13, [tmpq+strideq*1-8] + movu m14, [tmpq+strideq*2-8] + movu m15, [tmpq+stride3q -8] + mova [esp+ 8*16], m8 + mova [esp+ 9*16], m9 + mova [esp+10*16], m10 + mova [esp+11*16], m11 + mova [esp+12*16], m12 + mova [esp+13*16], m13 + mova [esp+14*16], m14 + mova [esp+15*16], m15 +%endif + movu m0, [dstq+strideq*0-8] + movu m1, [dstq+strideq*1-8] + movu m2, [dstq+strideq*2-8] + movu m3, [dstq+stride3q -8] + lea tmpq, [dstq+strideq*4] + movu m4, [tmpq+strideq*0-8] + movu m5, [tmpq+strideq*1-8] + movu m6, [tmpq+strideq*2-8] + movu m7, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] +%if ARCH_X86_64 + movu m8, [tmpq+strideq*0-8] + movu m9, [tmpq+strideq*1-8] + movu m10, [tmpq+strideq*2-8] + movu m11, [tmpq+stride3q -8] + lea tmpq, [tmpq+strideq*4] + movu m12, [tmpq+strideq*0-8] + movu m13, [tmpq+strideq*1-8] + movu m14, [tmpq+strideq*2-8] + movu m15, [tmpq+stride3q -8] +%endif + +%if ARCH_X86_64 + TRANSPOSE_16X16B 0, [rsp+11*16] + mova [rsp+12*16], m1 + mova [rsp+13*16], m2 + mova [rsp+14*16], m3 + mova [rsp+15*16], m12 + mova [rsp+16*16], m13 + mova [rsp+17*16], m14 + mova [rsp+18*16], m15 + ; 4,5,6,7,8,9,10,11 -> 12,13,3,4,5,6,14,15 + SWAP 12, 4, 7 + SWAP 13, 5, 8 + SWAP 3, 6, 9 + SWAP 10, 14 + SWAP 11, 15 + mova [rsp+21*16], m12 + %define %%p3mem [rsp+21*16] + mova m12, [rsp+20*16] +%else + TRANSPOSE_16X16B 0, [esp+16*16] + %define %%p3mem [esp+26*16] + %define m11 %%p3mem + %define m13 %%p2mem + %define m14 %%q2mem + %define m15 %%q3mem +%endif +%endif ; if 4 elif 6 or 8 else 16 +%endif ; if v else h + + ; load L/E/I/H +%if ARCH_X86_32 + mov l_strideq, l_stridem +%endif +%ifidn %2, v + movu m1, [lq] + movu m0, [lq+l_strideq] +%else + %if ARCH_X86_32 + lea l_stride3q, [l_strideq*3] + %endif + movq xm1, [lq] + movq xm2, [lq+l_strideq*2] + movhps xm1, [lq+l_strideq] + movhps xm2, [lq+l_stride3q] + shufps m0, m1, m2, q3131 + shufps m1, m2, q2020 + %if ARCH_X86_32 + lea stride3q, [strideq*3] + %endif +%endif + +%if ARCH_X86_32 + %ifidn %2, v + mov lutd, lutm + %endif +%endif + pxor m2, m2 + pcmpeqb m7, m2, m0 + pand m1, m7 + por m0, m1 ; l[x][] ? l[x][] : l[x-stride][] + pshufb m0, [PIC_sym(pb_4x0_4x4_4x8_4x12)] ; l[x][1] + pcmpeqb m2, m0 ; !L + psrlq m7, m0, [lutq+128] + pand m7, [PIC_sym(pb_63)] + pminub m7, minlvl + pmaxub m7, [PIC_sym(pb_1)] ; I + pand m1, m0, [PIC_sym(pb_240)] + psrlq m1, 4 ; H + paddb m0, [PIC_sym(pb_2)] + paddb m0, m0 + paddb m0, m7 ; E + pxor m1, [PIC_sym(pb_128)] + pxor m7, [PIC_sym(pb_128)] + pxor m0, [PIC_sym(pb_128)] + SWAP 2, 7 + +%if ARCH_X86_64 + SWAP 0, 8 + SWAP 2, 10 +%else + %ifidn %2, v + mov mstrideq, strideq + neg mstrideq + %if %1 == 4 + lea tmpq, [dstq+mstrideq*2] + %elif %1 == 6 || %1 == 8 + lea tmpq, [dstq+mstrideq*4] + %endif + %endif + mova [esp+3*16], m0 + mova [esp+4*16], m2 +%endif + + ABSSUB m0, m3, m4, m2 ; abs(p1-p0) + pmaxub m0, m7 + ABSSUB m2, m5, m6, m7 ; abs(q1-q0) + pmaxub m0, m2 +%if %1 == 4 + pxor m0, [PIC_sym(pb_128)] + pcmpgtb m7, m0, m1 ; hev + %if ARCH_X86_64 + SWAP 7, 11 + %else + mova [esp+5*16], m7 + %endif +%else + pxor m7, m0, [PIC_sym(pb_128)] + pcmpgtb m7, m1 ; hev +%if ARCH_X86_64 + SWAP 7, 11 +%else + mova [esp+5*16], m7 +%endif + +%if %1 == 6 + ABSSUB m1, m13, m4, m7 ; abs(p2-p0) + pmaxub m1, m0 +%else + mova m2, %%p3mem + ABSSUB m1, m2, m4, m7 ; abs(p3-p0) + pmaxub m1, m0 + ABSSUB m7, m13, m4, m2 ; abs(p2-p0) + pmaxub m1, m7 +%endif + ABSSUB m7, m5, m14, m2 ; abs(p2-p0) + pmaxub m1, m7 +%if %1 != 6 + ABSSUB m7, m5, m15, m2 ; abs(q3-q0) + pmaxub m1, m7 +%endif + pxor m1, [PIC_sym(pb_128)] + pcmpgtb m1, [PIC_sym(pb_129)] ; !flat8in +%if ARCH_X86_64 + SWAP 1, 9 +%else + mova [esp+6*16], m1 +%endif + +%if %1 == 6 + ABSSUB m7, m13, m3, m1 ; abs(p2-p1) +%else + mova m2, %%p3mem + ABSSUB m7, m2, m13, m1 ; abs(p3-p2) + ABSSUB m2, m13, m3, m1 ; abs(p2-p1) + pmaxub m7, m2 + ABSSUB m2, m14, m15, m1 ; abs(q3-q2) + pmaxub m7, m2 +%endif + ABSSUB m2, m14, m6, m1 ; abs(q2-q1) + pmaxub m7, m2 +%if ARCH_X86_32 + %define m12 m1 + mova m12, maskmem +%endif + pand m2, m12, mask1 + pcmpeqd m2, m12 + pand m7, m2 ; only apply fm-wide to wd>4 blocks + pmaxub m0, m7 + + pxor m0, [PIC_sym(pb_128)] +%endif ; %if %1 == 4 else +%if ARCH_X86_64 + SWAP 2, 10 + pcmpgtb m0, m2 +%else + pcmpgtb m0, [esp+4*16] +%endif + + ABSSUB m1, m3, m6, m7 ; abs(p1-q1) + ABSSUB m7, m4, m5, m2 ; abs(p0-q0) + paddusb m7, m7 + pand m1, [PIC_sym(pb_254)] + psrlq m1, 1 + paddusb m1, m7 ; abs(p0-q0)*2+(abs(p1-q1)>>1) + pxor m1, [PIC_sym(pb_128)] +%if ARCH_X86_64 + pcmpgtb m1, m8 ; abs(p0-q0)*2+(abs(p1-q1)>>1) > E +%else + pcmpgtb m1, [esp+3*16] +%endif + por m0, m1 + +%if %1 == 16 +%if ARCH_X86_64 + SWAP 0, 8 +%else + mova [esp+3*16], m0 +%endif +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] +%else + mova m0, [rsp+12*16] +%endif + ABSSUB m1, m0, m4, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*2] +%else + mova m0, [rsp+13*16] +%endif + ABSSUB m2, m0, m4, m7 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+stride3q] +%else + mova m0, [rsp+14*16] +%endif + ABSSUB m2, m0, m4, m7 + pmaxub m1, m2 +%ifidn %2, v + lea tmpq, [dstq+strideq*4] + mova m0, [tmpq+strideq*0] +%else + mova m0, [rsp+15*16] +%endif + ABSSUB m2, m0, m5, m7 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*1] +%else + mova m0, [rsp+16*16] +%endif + ABSSUB m2, m0, m5, m7 + pmaxub m1, m2 +%ifidn %2, v + mova m0, [tmpq+strideq*2] +%else + mova m0, [rsp+17*16] +%endif + ABSSUB m2, m0, m5, m7 + pmaxub m1, m2 + pxor m1, [PIC_sym(pb_128)] + pcmpgtb m1, [PIC_sym(pb_129)] ; !flat8out +%if ARCH_X86_64 + por m1, m9 ; !flat8in | !flat8out +%else + por m1, [esp+6*16] + %define m12 m7 + mova m12, maskmem +%endif + pand m2, m12, mask2 + pcmpeqd m2, m12 + pandn m1, m2 ; flat16 +%if ARCH_X86_64 + pandn m2, m8, m1 ; flat16 & fm +%else + pandn m2, [esp+3*16], m1 ; flat16 & fm + mova %%flat16mem, m2 +%endif + SWAP 1, 2 + + pand m2, m12, mask1 + pcmpeqd m2, m12 +%if ARCH_X86_64 + pandn m9, m2 ; flat8in + pandn m2, m8, m9 + SWAP 2, 9 +%else + pandn m0, [esp+6*16], m2 + pandn m2, [esp+3*16], m0 + mova [esp+6*16], m2 +%endif + pand m2, m12, mask0 + pcmpeqd m2, m12 +%if ARCH_X86_64 + pandn m8, m2 + pandn m2, m9, m8 ; fm & !flat8 & !flat16 + SWAP 2, 8 + pandn m2, m1, m9 ; flat8 & !flat16 + SWAP 2, 9 + SWAP 0, 8 + SWAP 1, 10 +%else + pandn m0, [esp+3*16], m2 + pandn m2, [esp+6*16], m0 + SWAP 2, 0 + pandn m2, m1, [esp+6*16] + mova %%flat8mem, m2 +%endif +%elif %1 != 4 + %if ARCH_X86_64 + SWAP 1, 9 + %else + %define m12 m7 + mova m12, maskmem + mova m1, [esp+6*16] + %endif + pand m2, m12, mask1 + pcmpeqd m2, m12 + pandn m1, m2 + pandn m2, m0, m1 ; flat8 & fm + pand m1, m12, mask0 + pcmpeqd m1, m12 + pandn m0, m1 + pandn m1, m2, m0 ; fm & !flat8 + SWAP 1, 2, 0 + %if ARCH_X86_64 + SWAP 1, 9 + %else + mova %%flat8mem, m1 + %endif +%else +%if ARCH_X86_32 + %define m12 m1 + mova m12, maskmem +%endif + pand m2, m12, mask0 + pcmpeqd m2, m12 + pandn m0, m2 ; fm +%endif + + ; short filter + + mova m1, [PIC_sym(pb_128)] +%if ARCH_X86_64 + SWAP 7, 11 +%else + mova m7, [esp+5*16] +%endif + pxor m3, m1 + pxor m6, m1 + pxor m4, m1 + pxor m5, m1 + psubsb m1, m3, m6 ; iclip_diff(p1-q1) + pand m1, m7 ; f=iclip_diff(p1-q1)&hev + psubsb m2, m5, m4 + paddsb m1, m2 + paddsb m1, m2 + paddsb m1, m2 ; f=iclip_diff(3*(q0-p0)+f) + mova m2, [PIC_sym(pb_16)] + pand m0, m1 ; f&=fm + paddsb m1, m0, [PIC_sym(pb_3)] + paddsb m0, [PIC_sym(pb_4)] + pand m1, [PIC_sym(pb_248)] + pand m0, [PIC_sym(pb_248)] + psrlq m1, 3 + psrlq m0, 3 + pxor m1, m2 + pxor m0, m2 + psubb m1, m2 ; f2 + psubb m0, m2 ; f1 + mova m2, [PIC_sym(pb_128)] + paddsb m4, m1 + psubsb m5, m0 + pxor m4, m2 + pxor m5, m2 + + pxor m0, m2 + pxor m1, m1 + pavgb m0, m1 ; f=(f1+1)>>1 + psubb m0, [PIC_sym(pb_64)] + pandn m7, m0 ; f&=!hev + paddsb m3, m7 + psubsb m6, m7 + pxor m3, m2 + pxor m6, m2 + +%if %1 == 16 + ; flat16 filter +%ifidn %2, v + lea tmpq, [dstq+mstrideq*8] + mova m0, [tmpq+strideq*1] ; p6 + mova m2, [tmpq+strideq*2] ; p5 + mova m7, [tmpq+stride3q] ; p4 +%else + mova m0, [rsp+12*16] + mova m2, [rsp+13*16] + mova m7, [rsp+14*16] +%endif + +%if ARCH_X86_64 + SWAP 1, 10 + mova %%flat8mem, m9 + mova %%q2mem, m14 + mova %%q3mem, m15 + SWAP 0, 8 + SWAP 1, 9 +%else + %ifidn %2, v + mova [esp+17*16], m0 + mova [esp+19*16], m3 + mova [esp+21*16], m4 + mova [esp+22*16], m5 + mova [esp+23*16], m6 + %xdefine m11 m3 + %xdefine m14 m4 + %xdefine m15 m5 + %xdefine m10 m6 + %define m13 %%p2mem + %define m8 [esp+17*16] + %define m9 %%flat16mem + %define m3 [esp+19*16] + %define m4 [esp+21*16] + %define m5 [esp+22*16] + %define m6 [esp+23*16] + %else + mova [esp+31*16], m0 + mova [esp+32*16], m3 + mova [esp+33*16], m4 + mova [esp+34*16], m5 + mova [esp+35*16], m6 + %xdefine m11 m3 + %xdefine m14 m4 + %xdefine m15 m5 + %xdefine m10 m6 + %define m13 %%p2mem + %define m8 [esp+31*16] + %define m9 %%flat16mem + %define m3 [esp+32*16] + %define m4 [esp+33*16] + %define m5 [esp+34*16] + %define m6 [esp+35*16] + %endif +%endif + + ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 [p5/p4/p2/p1/p0/q0][p6/p3] A + ; write -6 + mova m11, %%p3mem +%if ARCH_X86_64 + punpcklbw m14, m8, m11 + punpckhbw m15, m8, m11 +%else + punpcklbw m14, m0, m11 + punpckhbw m15, m0, m11 +%endif +%ifidn %2, v + mova [rsp+5*16], m11 +%endif + pmaddubsw m10, m14, [PIC_sym(pb_7_1)] + pmaddubsw m11, m15, [PIC_sym(pb_7_1)] ; p6*7+p3 + punpcklbw m0, m2, m7 + punpckhbw m1, m2, m7 + pmaddubsw m0, [PIC_sym(pb_2)] + pmaddubsw m1, [PIC_sym(pb_2)] + paddw m10, m0 + paddw m11, m1 ; p6*7+p5*2+p4*2+p3 + punpcklbw m0, m13, m3 + punpckhbw m1, m13, m3 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + paddw m10, m0 + paddw m11, m1 ; p6*7+p5*2+p4*2+p3+p2+p1 + punpcklbw m0, m4, m5 + punpckhbw m1, m4, m5 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + paddw m10, m0 + paddw m11, m1 ; p6*7+p5*2+p4*2+p3+p2+p1+p0+q0 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m2 + por m0, m1 +%ifidn %2, v + mova [tmpq+strideq*2], m0 ; p5 +%else + mova [rsp+13*16], m0 +%endif + + ; sub p6*2, add p3/q1 [reuse p6/p3 from A][-p6,+q1|save] B + ; write -5 + pmaddubsw m14, [PIC_sym(pb_m1_1)] + pmaddubsw m15, [PIC_sym(pb_m1_1)] + paddw m10, m14 + paddw m11, m15 ; p6*6+p5*2+p4*2+p3*2+p2+p1+p0+q0 + punpcklbw m0, m8, m6 + punpckhbw m1, m8, m6 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + mova [rsp+3*16], m0 + mova [rsp+4*16], m1 + paddw m10, m0 + paddw m11, m1 ; p6*5+p5*2+p4*2+p3*2+p2+p1+p0+q0+q1 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m7 + por m0, m1 +%ifidn %2, v + mova [tmpq+stride3q], m0 ; p4 +%else + mova [rsp+14*16], m0 +%endif + + ; sub p6/p5, add p2/q2 [-p6,+p2][-p5,+q2|save] C + ; write -4 + mova m14, %%q2mem + punpcklbw m0, m8, m13 + punpckhbw m1, m8, m13 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p6*4+p5*2+p4*2+p3*2+p2*2+p1+p0+q0+q1 + punpcklbw m0, m2, m14 + punpckhbw m2, m14 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m2, [PIC_sym(pb_m1_1)] + mova [rsp+1*16], m0 + paddw m10, m0 + paddw m11, m2 ; p6*4+p5+p4*2+p3*2+p2*2+p1+p0+q0+q1+q2 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, %%p3mem + por m0, m1 +%ifidn %2, v + mova [tmpq+strideq*4], m0 ; p3 +%else + mova [rsp+19*16], m0 +%endif + + ; sub p6/p4, add p1/q3 [-p6,+p1][-p4,+q3|save] D + ; write -3 + mova m15, %%q3mem + punpcklbw m0, m8, m3 + punpckhbw m1, m8, m3 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p6*3+p5+p4*2+p3*2+p2*2+p1*2+p0+q0+q1+q2 + punpcklbw m0, m7, m15 + punpckhbw m7, m15 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m7, [PIC_sym(pb_m1_1)] + mova [rsp+2*16], m0 +%if ARCH_X86_32 + %ifidn %2, v + mova [esp+24*16], m7 + %else + mova [esp+36*16], m7 + %endif +%endif + paddw m10, m0 + paddw m11, m7 ; p6*3+p5+p4+p3*2+p2*2+p1*2+p0+q0+q1+q2+q3 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m13 + por m0, m1 + mova [rsp+6*16], m0 ; don't clobber p2/m13 since we need it in F + + ; sub p6/p3, add p0/q4 [-p6,+p0][-p3,+q4|save] E + ; write -2 + punpcklbw m0, m8, m4 + punpckhbw m1, m8, m4 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p6*2+p5+p4+p3*2+p2*2+p1*2+p0*2+q0+q1+q2+q3 +%if ARCH_X86_64 + SWAP 7, 8 +%endif +%ifidn %2, v + mova m1, [dstq+strideq*4] ; q4 + mova m7, [rsp+5*16] ; (pre-filter) p3 +%else + mova m1, [rsp+15*16] + mova m7, %%p3mem ; (pre-filter) p3 +%endif + punpcklbw m0, m1, m7 + punpckhbw m1, m1, m7 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + mova [rsp+7*16], m0 + mova [rsp+5*16], m1 + psubw m10, m0 + psubw m11, m1 ; p6*2+p5+p4+p3+p2*2+p1*2+p0*2+q0+q1+q2+q3+q4 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m3 + por m0, m1 + mova [rsp+8*16], m0 ; don't clobber p1/m3 since we need it in G + + ; sub p6/p2, add q0/q5 [-p6,+q0][-p2,+q5|save] F + ; write -1 +%ifidn %2, v + mova m7, [tmpq+strideq*1] ; p6 + lea tmpq, [dstq+strideq*4] + mova m1, [tmpq+strideq*1] ; q5 +%else + mova m7, [rsp+12*16] ; p6 + mova m1, [rsp+16*16] +%endif + punpcklbw m0, m7, m5 + punpckhbw m7, m5 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m7, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m7 ; p6+p5+p4+p3+p2*2+p1*2+p0*2+q0*2+q1+q2+q3+q4 + punpcklbw m7, m13, m1 + pmaddubsw m7, [PIC_sym(pb_m1_1)] + mova [rsp+9*16], m7 + paddw m10, m7 +%if ARCH_X86_64 + punpckhbw m13, m1 + mova m1, [rsp+6*16] + SWAP 1, 13 +%else + punpckhbw m7, m13, m1 + mova m1, [esp+6*16] + mova m13, m1 + SWAP 1, 7 +%endif + pmaddubsw m1, [PIC_sym(pb_m1_1)] + mova [rsp+10*16], m1 + paddw m11, m1 ; p6+p5+p4+p3+p2+p1*2+p0*2+q0*2+q1+q2+q3+q4+q5 + pmulhrsw m7, m10, [PIC_sym(pw_2048)] + pmulhrsw m0, m11, [PIC_sym(pw_2048)] + packuswb m7, m0 + pand m7, m9 + pandn m0, m9, m4 + por m7, m0 + mova [rsp+6*16], m7 ; don't clobber p0/m4 since we need it in H + + ; sub p6/p1, add q1/q6 [reuse -p6,+q1 from B][-p1,+q6|save] G + ; write +0 +%ifidn %2, v + mova m7, [tmpq+strideq*2] ; q6 +%else + mova m7, [rsp+17*16] +%endif + paddw m10, [rsp+3*16] + paddw m11, [rsp+4*16] ; p5+p4+p3+p2+p1*2+p0*2+q0*2+q1*2+q2+q3+q4+q5 + punpcklbw m0, m3, m7 + punpckhbw m1, m3, m7 +%if ARCH_X86_64 + mova m3, [rsp+8*16] +%endif + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + mova [rsp+3*16], m0 + mova [rsp+4*16], m1 + paddw m10, m0 + paddw m11, m1 ; p5+p4+p3+p2+p1+p0*2+q0*2+q1*2+q2+q3+q4+q5+q6 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m5 + por m0, m1 +%if ARCH_X86_32 + mova m1, [esp+8*16] + mova m3, m1 +%endif + mova [rsp+8*16], m0 ; don't clobber q0/m5 since we need it in I + + ; sub p5/p0, add q2/q6 [reuse -p5,+q2 from C][-p0,+q6] H + ; write +1 + paddw m10, [rsp+1*16] + paddw m11, m2 ; p4+p3+p2+p1+p0*2+q0*2+q1*2+q2*2+q3+q4+q5+q6 + punpcklbw m0, m4, m7 + punpckhbw m2, m4, m7 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m2, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m2 ; p4+p3+p2+p1+p0+q0*2+q1*2+q2*2+q3+q4+q5+q6*2 +%if ARCH_X86_64 + mova m4, [rsp+6*16] +%else + %define m4 [esp+6*16] +%endif + pmulhrsw m2, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m2, m1 + pand m2, m9 + pandn m1, m9, m6 + por m2, m1 ; don't clobber q1/m6 since we need it in K + + ; sub p4/q0, add q3/q6 [reuse -p4,+q3 from D][-q0,+q6] I + ; write +2 + paddw m10, [rsp+2*16] +%if ARCH_X86_64 + SWAP 7, 8 + paddw m11, m7 +%else + mova m8, m7 + %ifidn %2, v + paddw m11, [esp+24*16] ; p3+p2+p1+p0+q0*2+q1*2+q2*2+q3*2+q4+q5+q6*2 + %else + paddw m11, [esp+36*16] ; p3+p2+p1+p0+q0*2+q1*2+q2*2+q3*2+q4+q5+q6*2 + %endif +%endif + punpcklbw m0, m5, m8 + punpckhbw m1, m5, m8 +%if ARCH_X86_64 + mova m5, [rsp+8*16] +%else + %define m5 [esp+8*16] +%endif + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p3+p2+p1+p0+q0+q1*2+q2*2+q3*2+q4+q5+q6*3 + pmulhrsw m7, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m7, m1 + pand m7, m9 + pandn m1, m9, m14 + por m7, m1 ; don't clobber q2/m14 since we need it in K + + ; sub p3/q1, add q4/q6 [reuse -p3,+q4 from E][-q1,+q6] J + ; write +3 + psubw m10, [rsp+7*16] + psubw m11, [rsp+5*16] ; p2+p1+p0+q0+q1*2+q2*2+q3*2+q4*2+q5+q6*3 + punpcklbw m0, m6, m8 + punpckhbw m1, m6, m8 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p2+p1+p0+q0+q1+q2*2+q3*2+q4*2+q5+q6*4 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m15 + por m0, m1 +%ifidn %2, v + mova [tmpq+mstrideq], m0 ; q3 +%else + mova [rsp+20*16], m0 +%endif + + ; sub p2/q2, add q5/q6 [reuse -p2,+q5 from F][-q2,+q6] K + ; write +4 + paddw m10, [rsp+ 9*16] + paddw m11, [rsp+10*16] ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + punpcklbw m0, m14, m8 + punpckhbw m1, m14, m8 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m0, m10, [PIC_sym(pw_2048)] + pmulhrsw m1, m11, [PIC_sym(pw_2048)] + packuswb m0, m1 + pand m0, m9 +%ifidn %2, v + pandn m1, m9, [tmpq+strideq*0] +%else + pandn m1, m9, [rsp+15*16] +%endif + por m0, m1 +%ifidn %2, v + mova [tmpq+strideq*0], m0 ; q4 +%else + mova [rsp+15*16], m0 +%endif + + ; sub p1/q3, add q6*2 [reuse -p1,+q6 from G][-q3,+q6] L + ; write +5 + paddw m10, [rsp+3*16] + paddw m11, [rsp+4*16] ; p1+p0+q0+q1+q2*2+q3*2+q4*2+q5*2+q6*4 + punpcklbw m0, m15, m8 + punpckhbw m1, m15, m8 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m10, m0 + paddw m11, m1 ; p1+p0+q0+q1+q2+q3*2+q4*2+q5*2+q6*5 + pmulhrsw m10, [PIC_sym(pw_2048)] + pmulhrsw m11, [PIC_sym(pw_2048)] + packuswb m10, m11 + pand m10, m9 +%ifidn %2, v + pandn m11, m9, [tmpq+strideq*1] +%else + pandn m11, m9, [rsp+16*16] +%endif + por m10, m11 +%ifidn %2, v + mova [tmpq+strideq*1], m10 ; q5 +%else + mova [rsp+16*16], m10 +%endif + +%if ARCH_X86_64 + SWAP 0, 8 + SWAP 1, 9 + SWAP 14, 7 +%else + %xdefine m3 m11 + %xdefine m4 m14 + %xdefine m5 m15 + %xdefine m6 m10 + mova %%q2mem, m7 + %ifidn %2, v + mova m3, [esp+19*16] + %else + mova m3, [esp+32*16] + %endif + mova m4, [esp+ 6*16] + mova m5, [esp+ 8*16] +%endif + SWAP m6, m2 + +%if ARCH_X86_64 + mova m9, %%flat8mem +%endif +%ifidn %2, v + lea tmpq, [dstq+mstrideq*4] +%endif +%endif ; if %1 == 16 +%if %1 >= 8 + ; flat8 filter +%if ARCH_X86_32 + %define m9 %%flat8mem + %define m11 m1 + %define m13 %%p2mem + %define m14 %%q2mem + %define m15 %%q3mem +%endif + mova m11, %%p3mem + punpcklbw m0, m11, m3 + punpcklbw m7, m13, m4 + pmaddubsw m2, m0, [PIC_sym(pb_3_1)] ; 3 * p3 + p1 + pmaddubsw m7, [PIC_sym(pb_2_1)] + paddw m2, m7 ; 3 * p3 + 2 * p2 + p1 + p0 + punpcklbw m7, m5, [PIC_sym(pb_4)] + pmaddubsw m7, [PIC_sym(pb_1)] + paddw m2, m7 ; 3 * p3 + 2 * p2 + p1 + p0 + q0 + 4 + punpckhbw m1, m11, m3 + pmaddubsw m7, m1, [PIC_sym(pb_3_1)] ; 3 * p3 + p1 + punpckhbw m0, m13, m4 + pmaddubsw m0, [PIC_sym(pb_2_1)] + paddw m7, m0 ; 3 * p3 + 2 * p2 + p1 + p0 + punpckhbw m0, m5, [PIC_sym(pb_4)] + pmaddubsw m0, [PIC_sym(pb_1)] + paddw m7, m0 ; 3 * p3 + 2 * p2 + p1 + p0 + q0 + 4 + psrlw m0, m2, 3 + psrlw m1, m7, 3 + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m13 + por m0, m1 ; p2 +%ifidn %2, v + mova [tmpq+strideq*1], m0 +%else + %if ARCH_X86_64 + SWAP 0, 10 + %else + mova [esp+2*16], m0 + %endif +%endif + +%if ARCH_X86_32 + mova m11, %%p3mem +%endif + punpcklbw m0, m11, m3 + punpckhbw m1, m11, m3 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m2, m0 + paddw m7, m1 + punpcklbw m0, m13, m6 + punpckhbw m1, m13, m6 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m2, m0 + paddw m7, m1 ; 2 * p3 + p2 + 2 * p1 + p0 + q0 + q1 + 4 + psrlw m0, m2, 3 + psrlw m1, m7, 3 + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m3 + por m0, m1 ; p1 +%ifidn %2, v + mova [tmpq+strideq*2], m0 +%else + mova [rsp+0*16], m0 +%endif + +%if ARCH_X86_32 + mova m11, %%p3mem +%endif + punpcklbw m0, m11, m3 + punpckhbw m1, m11, m3 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + psubw m2, m0 + psubw m7, m1 + punpcklbw m0, m4, m14 + punpckhbw m1, m4, m14 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + paddw m2, m0 + paddw m7, m1 ; p3 + p2 + p1 + 2 * p0 + q0 + q1 + q2 + 4 + psrlw m0, m2, 3 + psrlw m1, m7, 3 + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m4 + por m0, m1 ; p0 +%ifidn %2, v + mova [tmpq+stride3q], m0 +%else + mova [rsp+1*16], m0 +%endif + + punpcklbw m0, m5, m15 + punpckhbw m1, m5, m15 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + paddw m2, m0 + paddw m7, m1 +%if ARCH_X86_32 + mova m11, %%p3mem +%endif + punpcklbw m0, m11, m4 + punpckhbw m11, m11, m4 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m11, [PIC_sym(pb_1)] + psubw m2, m0 + psubw m7, m11 ; p2 + p1 + p0 + 2 * q0 + q1 + q2 + q3 + 4 + psrlw m0, m2, 3 + psrlw m11, m7, 3 + packuswb m0, m11 + pand m0, m9 + pandn m11, m9, m5 + por m11, m0 ; q0 +%ifidn %2, v + mova [dstq+strideq*0], m11 +%elif ARCH_X86_32 + mova [esp+8*16], m11 +%endif + + punpcklbw m0, m5, m15 + punpckhbw m1, m5, m15 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m2, m0 + paddw m7, m1 + punpcklbw m0, m13, m6 + punpckhbw m1, m13, m6 + pmaddubsw m0, [PIC_sym(pb_m1_1)] + pmaddubsw m1, [PIC_sym(pb_m1_1)] + paddw m2, m0 + paddw m7, m1 ; p1 + p0 + q0 + 2 * q1 + q2 + 2 * q3 + 4 + psrlw m0, m2, 3 + psrlw m1, m7, 3 + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m6 + por m0, m1 ; q1 +%ifidn %2, v + mova [dstq+strideq*1], m0 +%else + %if ARCH_X86_64 + SWAP 0, 13 + %else + mova [esp+9*16], m0 + %endif +%endif + + punpcklbw m0, m3, m6 + punpckhbw m1, m3, m6 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + psubw m2, m0 + psubw m7, m1 + punpcklbw m0, m14, m15 + punpckhbw m1, m14, m15 + pmaddubsw m0, [PIC_sym(pb_1)] + pmaddubsw m1, [PIC_sym(pb_1)] + paddw m2, m0 + paddw m7, m1 ; p0 + q0 + q1 + q2 + 2 * q2 + 3 * q3 + 4 + psrlw m2, 3 + psrlw m7, 3 + packuswb m2, m7 + pand m2, m9 + pandn m7, m9, m14 + por m2, m7 ; q2 +%ifidn %2, v + mova [dstq+strideq*2], m2 +%else + mova m0, [rsp+0*16] +%if %1 == 8 + mova m1, [rsp+1*16] + mova m4, %%p3mem + +%if ARCH_X86_32 + %define m10 [esp+2*16] + %define m11 [esp+8*16] + %define m13 [esp+9*16] +%endif + + ; 16x8 transpose + punpcklbw m3, m4, m10 + punpckhbw m4, m10 + punpcklbw m5, m0, m1 + punpckhbw m0, m1 + punpcklbw m1, m11, m13 + punpckhbw m6, m11, m13 + punpcklbw m7, m2, m15 + punpckhbw m2, m15 +%if ARCH_X86_64 + SWAP 2, 15 +%else + mova m15, m2 +%endif + + punpcklwd m2, m3, m5 + punpckhwd m3, m5 + punpcklwd m5, m4, m0 + punpckhwd m4, m0 + punpcklwd m0, m1, m7 + punpckhwd m1, m7 + punpcklwd m7, m6, m15 + punpckhwd m6, m15 +%if ARCH_X86_64 + SWAP 6, 15 +%else + mova m15, m6 +%endif + + punpckldq m6, m2, m0 + punpckhdq m2, m0 + punpckldq m0, m3, m1 + punpckhdq m3, m1 + punpckldq m1, m5, m7 + punpckhdq m5, m7 + punpckldq m7, m4, m15 + punpckhdq m4, m15 + + ; write 8x16 + movq [dstq+strideq*0-4], xm6 + movhps [dstq+strideq*1-4], xm6 + movq [dstq+strideq*2-4], xm2 + movhps [dstq+stride3q -4], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm0 + movhps [dstq+strideq*1-4], xm0 + movq [dstq+strideq*2-4], xm3 + movhps [dstq+stride3q -4], xm3 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm1 + movhps [dstq+strideq*1-4], xm1 + movq [dstq+strideq*2-4], xm5 + movhps [dstq+stride3q -4], xm5 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0-4], xm7 + movhps [dstq+strideq*1-4], xm7 + movq [dstq+strideq*2-4], xm4 + movhps [dstq+stride3q -4], xm4 + lea dstq, [dstq+strideq*4] +%else + ; 16x16 transpose and store + SWAP 6, 0 + SWAP 7, 1 + %if ARCH_X86_64 + SWAP 5, 10, 2 + SWAP 8, 11 + SWAP 9, 13 + mova [rsp+21*16], m12 + %else + mova [esp+10*16], m2 + %xdefine m8 m0 + %xdefine m9 m1 + %xdefine m10 m2 + %xdefine m11 m3 + %xdefine m12 m4 + %xdefine m13 m5 + %xdefine m14 m6 + %xdefine m15 m7 + %endif + mova m0, [rsp+11*16] + mova m1, [rsp+12*16] + mova m2, [rsp+13*16] + mova m3, [rsp+14*16] + mova m4, [rsp+19*16] +%if ARCH_X86_64 + mova m7, [rsp+ 1*16] + mova m11, [rsp+20*16] + mova m12, [rsp+15*16] + mova m13, [rsp+16*16] + mova m14, [rsp+17*16] + TRANSPOSE_16X16B 1, [rsp+18*16] +%else + mova m5, [esp+ 2*16] + TRANSPOSE_16X16B 1, [esp+32*16] + mov tmpq, dstq + lea dstq, [dstq+strideq*8] +%endif + movu [dstq+strideq*0-8], xm0 + movu [dstq+strideq*1-8], xm1 + movu [dstq+strideq*2-8], xm2 + movu [dstq+stride3q -8], xm3 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm4 + movu [dstq+strideq*1-8], xm5 + movu [dstq+strideq*2-8], xm6 + movu [dstq+stride3q -8], xm7 +%if ARCH_X86_64 + lea dstq, [dstq+strideq*4] +%else + %xdefine m8 m0 + %xdefine m9 m1 + %xdefine m10 m2 + %xdefine m11 m3 + %xdefine m12 m4 + %xdefine m13 m5 + %xdefine m14 m6 + %xdefine m15 m7 + mova m8, [esp+11*16] + mova m9, [esp+12*16] + mova m10, [esp+13*16] + mova m11, [esp+14*16] + mova m12, [esp+26*16] + mova m13, [esp+27*16] + mova m14, [esp+ 0*16] + mova m15, [esp+ 1*16] + mov dstq, tmpq +%endif + movu [dstq+strideq*0-8], xm8 + movu [dstq+strideq*1-8], xm9 + movu [dstq+strideq*2-8], xm10 + movu [dstq+stride3q -8], xm11 + lea dstq, [dstq+strideq*4] + movu [dstq+strideq*0-8], xm12 + movu [dstq+strideq*1-8], xm13 + movu [dstq+strideq*2-8], xm14 + movu [dstq+stride3q -8], xm15 + lea dstq, [dstq+strideq*4] +%if ARCH_X86_32 + lea dstq, [dstq+strideq*8] +%else + mova m12, [rsp+21*16] +%endif + +%endif ; if %1 == 8 +%endif ; ifidn %2, v +%elif %1 == 6 + ; flat6 filter +%if ARCH_X86_32 + mova [esp+3*16], m3 + mova [esp+4*16], m4 + mova [esp+5*16], m5 + mova [esp+6*16], m6 + %xdefine m8 m3 + %xdefine m10 m4 + %xdefine m11 m5 + %xdefine m15 m6 + %define m3 [esp+3*16] + %define m4 [esp+4*16] + %define m5 [esp+5*16] + %define m6 [esp+6*16] + %define m9 %%flat8mem + %define m13 %%p2mem + %define m14 %%q2mem +%endif + + punpcklbw m8, m13, m5 + punpckhbw m11, m13, m5 + pmaddubsw m0, m8, [PIC_sym(pb_3_1)] + pmaddubsw m1, m11, [PIC_sym(pb_3_1)] + punpcklbw m7, m4, m3 + punpckhbw m10, m4, m3 + pmaddubsw m2, m7, [PIC_sym(pb_2)] + pmaddubsw m15, m10, [PIC_sym(pb_2)] + paddw m0, m2 + paddw m1, m15 + pmulhrsw m2, m0, [PIC_sym(pw_4096)] + pmulhrsw m15, m1, [PIC_sym(pw_4096)] + packuswb m2, m15 + pand m2, m9 + pandn m15, m9, m3 + por m2, m15 +%ifidn %2, v + mova [tmpq+strideq*2], m2 ; p1 +%elif ARCH_X86_32 + mova [esp+11*16], m2 +%endif + + pmaddubsw m8, [PIC_sym(pb_m1_1)] + pmaddubsw m11, [PIC_sym(pb_m1_1)] + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m13, m6 + punpckhbw m11, m13, m6 +%if ARCH_X86_64 + SWAP 2, 13 +%endif + pmaddubsw m8, [PIC_sym(pb_m1_1)] + pmaddubsw m11, [PIC_sym(pb_m1_1)] + paddw m0, m8 + paddw m1, m11 + pmulhrsw m2, m0, [PIC_sym(pw_4096)] + pmulhrsw m15, m1, [PIC_sym(pw_4096)] + packuswb m2, m15 + pand m2, m9 + pandn m15, m9, m4 + por m2, m15 +%ifidn %2, v + mova [tmpq+stride3q], m2 ; p0 +%elif ARCH_X86_32 + mova [esp+8*16], m2 +%endif + + paddw m0, m8 + paddw m1, m11 + punpcklbw m8, m3, m14 + punpckhbw m11, m3, m14 +%if ARCH_X86_64 + SWAP 2, 14 +%endif + pmaddubsw m2, m8, [PIC_sym(pb_m1_1)] + pmaddubsw m15, m11, [PIC_sym(pb_m1_1)] + paddw m0, m2 + paddw m1, m15 + pmulhrsw m2, m0, [PIC_sym(pw_4096)] + pmulhrsw m15, m1, [PIC_sym(pw_4096)] + packuswb m2, m15 + pand m2, m9 + pandn m15, m9, m5 + por m2, m15 +%ifidn %2, v + mova [dstq+strideq*0], m2 ; q0 +%endif + + pmaddubsw m8, [PIC_sym(pb_m1_2)] + pmaddubsw m11, [PIC_sym(pb_m1_2)] + paddw m0, m8 + paddw m1, m11 + pmaddubsw m7, [PIC_sym(pb_m1_0)] + pmaddubsw m10, [PIC_sym(pb_m1_0)] + paddw m0, m7 + paddw m1, m10 + pmulhrsw m0, [PIC_sym(pw_4096)] + pmulhrsw m1, [PIC_sym(pw_4096)] + packuswb m0, m1 + pand m0, m9 + pandn m1, m9, m6 + por m0, m1 +%if ARCH_X86_32 + %xdefine m3 m8 + %xdefine m4 m10 + %xdefine m5 m11 + %xdefine m6 m15 +%endif +%ifidn %2, v + mova [dstq+strideq*1], m0 ; q1 +%else + %if ARCH_X86_64 + SWAP 3, 13 + SWAP 4, 14 + %else + mova m3, [esp+11*16] + mova m4, [esp+ 8*16] + %endif + SWAP 5, 2 + SWAP 6, 0 + TRANSPOSE_16x4_AND_WRITE_4x16 3, 4, 5, 6, 7 +%endif +%else ; if %1 == 4 +%ifidn %2, v + mova [tmpq+strideq*0], m3 ; p1 + mova [tmpq+strideq*1], m4 ; p0 + mova [tmpq+strideq*2], m5 ; q0 + mova [tmpq+stride3q ], m6 ; q1 +%else + TRANSPOSE_16x4_AND_WRITE_4x16 3, 4, 5, 6, 7 +%endif +%endif +%if ARCH_X86_32 + %define m12 m12reg +%endif +%endmacro + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 32-bit PIC helpers ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%if ARCH_X86_32 + %define PIC_base_offset $$ + + %macro SETUP_PIC 0 ; PIC_reg + %define PIC_reg r2 + %assign PIC_reg_stk_offset stack_size-gprsize*(1+copy_args*4) + LEA PIC_reg, $$ + %endmacro + + %macro XCHG_PIC_REG 1 ; 0=mask 1=PIC_base + %if %1 == 0 + mov [esp+PIC_reg_stk_offset], PIC_reg + mov PIC_reg, maskm + %else + mov PIC_reg, [esp+PIC_reg_stk_offset] + %endif + %endmacro + + %define PIC_sym(sym) (PIC_reg+(sym)-PIC_base_offset) + +%else + %macro XCHG_PIC_REG 1 + %endmacro + %define PIC_sym(sym) (sym) +%endif + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < required_stack_alignment + %assign copy_args 1 + %else + %assign copy_args 0 + %endif +%endif + +%macro RELOC_ARGS 1 + %if copy_args + %define maskm [esp+stack_size-gprsize*1] + %define l_stridem [esp+stack_size-gprsize*2] + %define lutm [esp+stack_size-gprsize*3] + %define %1m [esp+stack_size-gprsize*4] + mov r6d, r6m + mov maskm, maskd + mov lutm, lutd + mov %1m, r6d + %else + %define %1m r6m + %endif +%endmacro + +%if ARCH_X86_32 + %define tmpq r4 + %define mstrideq r5 + %define stride3q r6 + %define l_stride3q r6 +%endif + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_v_sb_y_8bpc, 7, 11, 16, 16 * 15, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits +%else +cglobal lpf_v_sb_y_8bpc, 6, 7, 8, -16 * (26 + copy_args), \ + dst, stride, mask, l, l_stride, lut, mask_bits + RELOC_ARGS w + SETUP_PIC + %define m12 m5 +%endif + shl l_strideq, 2 + sub lq, l_strideq +%if ARCH_X86_64 + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] +%else + mov l_stridem, l_strided +%endif + mov mask_bitsd, 0xf + mova m12, [PIC_sym(pd_mask)] + XCHG_PIC_REG 0 + movu m0, [maskq] + pxor m4, m4 + movd m3, [lutq+136] + pshufb m3, m4 + pshufd m2, m0, q2222 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + por m1, m2 + por m0, m1 + mova [rsp+11*16], m0 + mova [rsp+12*16], m1 + mova [rsp+13*16], m2 + mova [rsp+14*16], m3 + +%define maskmem [esp+15*16] +%define mask0 [rsp+11*16] +%define mask1 [rsp+12*16] +%define mask2 [rsp+13*16] +%define minlvl [rsp+14*16] + +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + je .no_flat16 + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+25*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 16, v + jmp .end + +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + je .no_flat + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+25*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 8, v + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + XCHG_PIC_REG 1 + je .no_filter + +%if ARCH_X86_32 + mov [esp+25*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 4, v + +.end: +%if ARCH_X86_32 + mova m12, maskmem + mov mask_bitsd, [esp+25*16] +%endif +.no_filter: + pslld m12, 4 + shl mask_bitsd, 4 + add lq, 16 + add dstq, 16 +%if ARCH_X86_64 + sub wd, 4 +%else + sub dword wm, 4 +%endif + XCHG_PIC_REG 0 + jg .loop + RET + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_h_sb_y_8bpc, 7, 11, 16, 16 * 26, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp, mask_bits +%else +cglobal lpf_h_sb_y_8bpc, 6, 7, 8, -16 * (39 + copy_args), \ + dst, stride, mask, l, l_stride, lut, mask_bits + RELOC_ARGS h + SETUP_PIC + %define m12 m5 +%endif + sub lq, 4 + shl l_strideq, 2 +%if ARCH_X86_64 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] +%else + mov l_stridem, l_strided +%endif + mov mask_bitsd, 0xf + mova m12, [PIC_sym(pd_mask)] + XCHG_PIC_REG 0 + movu m0, [maskq] + pxor m4, m4 + movd m3, [lutq+136] + pshufb m3, m4 + pshufd m2, m0, q2222 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + por m1, m2 + por m0, m1 + mova [rsp+22*16], m0 + mova [rsp+23*16], m1 + mova [rsp+24*16], m2 + mova [rsp+25*16], m3 + +%define maskmem [esp+37*16] +%define mask0 [rsp+22*16] +%define mask1 [rsp+23*16] +%define mask2 [rsp+24*16] +%define minlvl [rsp+25*16] + +.loop: + test [maskq+8], mask_bitsd ; vmask[2] + je .no_flat16 + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+38*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 16, h + jmp .end + +.no_flat16: + test [maskq+4], mask_bitsd ; vmask[1] + je .no_flat + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+38*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 8, h + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[0] + XCHG_PIC_REG 1 + je .no_filter + +%if ARCH_X86_32 + mov [esp+38*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 4, h + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] + lea dstq, [dstq+strideq*8] +%if ARCH_X86_32 + jmp .end_noload +.end: + mova m12, maskmem + mov l_strideq, l_stridem + mov mask_bitsd, [esp+38*16] +.end_noload: +%else +.end: +%endif + lea lq, [lq+l_strideq*4] + pslld m12, 4 + shl mask_bitsd, 4 +%if ARCH_X86_64 + sub hd, 4 +%else + sub dword hm, 4 +%endif + XCHG_PIC_REG 0 + jg .loop + RET + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_v_sb_uv_8bpc, 7, 11, 16, 3 * 16, \ + dst, stride, mask, l, l_stride, lut, \ + w, stride3, mstride, tmp, mask_bits +%else +cglobal lpf_v_sb_uv_8bpc, 6, 7, 8, -16 * (12 + copy_args), \ + dst, stride, mask, l, l_stride, lut, mask_bits + RELOC_ARGS w + SETUP_PIC + %define m12 m4 +%endif + shl l_strideq, 2 + sub lq, l_strideq +%if ARCH_X86_64 + mov mstrideq, strideq + neg mstrideq + lea stride3q, [strideq*3] +%else + mov l_stridem, l_strided +%endif + mov mask_bitsd, 0xf + mova m12, [PIC_sym(pd_mask)] + XCHG_PIC_REG 0 + movq m0, [maskq] + pxor m3, m3 + movd m2, [lutq+136] + pshufb m2, m3 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + por m0, m1 + mova [rsp+0*16], m0 + mova [rsp+1*16], m1 + mova [rsp+2*16], m2 + +%define maskmem [esp+7*16] +%define mask0 [rsp+0*16] +%define mask1 [rsp+1*16] +%define minlvl [rsp+2*16] + +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + je .no_flat + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+11*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 6, v + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[1] + XCHG_PIC_REG 1 + je .no_filter + +%if ARCH_X86_32 + mov [esp+11*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 4, v + +.end: +%if ARCH_X86_32 + mova m12, maskmem + mov mask_bitsd, [esp+11*16] +%endif +.no_filter: + pslld m12, 4 + shl mask_bitsd, 4 + add lq, 16 + add dstq, 16 +%if ARCH_X86_64 + sub wd, 4 +%else + sub dword wm, 4 +%endif + XCHG_PIC_REG 0 + jg .loop + RET + +INIT_XMM ssse3 +%if ARCH_X86_64 +cglobal lpf_h_sb_uv_8bpc, 7, 11, 16, 16 * 3, \ + dst, stride, mask, l, l_stride, lut, \ + h, stride3, l_stride3, tmp, mask_bits +%else +cglobal lpf_h_sb_uv_8bpc, 6, 7, 8, -16 * (13 + copy_args), \ + dst, stride, mask, l, l_stride, lut, mask_bits + RELOC_ARGS h + SETUP_PIC + %define m12 m4 +%endif + sub lq, 4 + shl l_strideq, 2 +%if ARCH_X86_64 + lea stride3q, [strideq*3] + lea l_stride3q, [l_strideq*3] +%else + mov l_stridem, l_strided +%endif + mov mask_bitsd, 0xf + mova m12, [PIC_sym(pd_mask)] + XCHG_PIC_REG 0 + movq m0, [maskq] + pxor m3, m3 + movd m2, [lutq+136] + pshufb m2, m3 + pshufd m1, m0, q1111 + pshufd m0, m0, q0000 + por m0, m1 + mova [rsp+0*16], m0 + mova [rsp+1*16], m1 + mova [rsp+2*16], m2 + +%define maskmem [esp+7*16] +%define mask0 [rsp+0*16] +%define mask1 [rsp+1*16] +%define minlvl [rsp+2*16] + +.loop: + test [maskq+4], mask_bitsd ; vmask[1] + je .no_flat + +%if ARCH_X86_32 + XCHG_PIC_REG 1 + mov [esp+12*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 6, h + jmp .end + +.no_flat: + test [maskq+0], mask_bitsd ; vmask[1] + XCHG_PIC_REG 1 + je .no_filter + +%if ARCH_X86_32 + mov [esp+12*16], mask_bitsd + mova maskmem, m12 +%endif + FILTER 4, h + jmp .end + +.no_filter: + lea dstq, [dstq+strideq*8] + lea dstq, [dstq+strideq*8] +%if ARCH_X86_32 + jmp .end_noload +.end: + mova m12, maskmem + mov l_strided, l_stridem + mov mask_bitsd, [esp+12*16] +.end_noload: +%else +.end: +%endif + lea lq, [lq+l_strideq*4] + pslld m12, 4 + shl mask_bitsd, 4 +%if ARCH_X86_64 + sub hd, 4 +%else + sub dword hm, 4 +%endif + XCHG_PIC_REG 0 + jg .loop + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2540 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +sgr_lshuf3: db 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +sgr_lshuf5: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +wiener_shufA: db 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11 +wiener_shufB: db 6, 7, 4, 5, 8, 9, 6, 7, 10, 11, 8, 9, 12, 13, 10, 11 +wiener_shufC: db 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15 +wiener_shufD: db 2, 3, -1, -1, 4, 5, -1, -1, 6, 7, -1, -1, 8, 9, -1, -1 +wiener_shufE: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +wiener_lshuf5: db 4, 5, 4, 5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +wiener_lshuf7: db 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 10, 11, 12, 13, 14, 15 +pb_0to31: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + db 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + +wiener_hshift: dw 4, 4, 1, 1 +wiener_vshift: dw 1024, 1024, 4096, 4096 +wiener_round: dd 1049600, 1048832 + +pb_m10_m9: times 2 db -10, -9 +pb_m6_m5: times 2 db -6, -5 +pb_m2_m1: times 2 db -2, -1 +pb_2_3: times 2 db 2, 3 +pb_6_7: times 2 db 6, 7 +pw_1023: times 2 dw 1023 +pd_8: dd 8 +pd_25: dd 25 +pd_4096: dd 4096 +pd_34816: dd 34816 +pd_m262128: dd -262128 +pd_0xf00800a4: dd 0xf00800a4 +pd_0xf00801c7: dd 0xf00801c7 + +%define pw_256 sgr_lshuf5 + +cextern sgr_x_by_x_avx2 + +SECTION .text + +DECLARE_REG_TMP 8, 7, 9, 11, 12, 13, 14 ; wiener ring buffer pointers + +INIT_YMM avx2 +cglobal wiener_filter7_16bpc, 4, 15, 16, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt +%define base t4-wiener_hshift + mov fltq, r6mp + movifnidn wd, wm + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + vbroadcasti128 m6, [wiener_shufA] + vpbroadcastd m12, [fltq+ 0] ; x0 x1 + lea t4, [wiener_hshift] + vbroadcasti128 m7, [wiener_shufB] + add wd, wd + vpbroadcastd m13, [fltq+ 4] ; x2 x3 + shr t3d, 11 + vpbroadcastd m14, [fltq+16] ; y0 y1 + add lpfq, wq + vpbroadcastd m15, [fltq+20] ; y2 y3 + add dstq, wq + vbroadcasti128 m8, [wiener_shufC] + lea t1, [rsp+wq+16] + vbroadcasti128 m9, [wiener_shufD] + neg wq + vpbroadcastd m0, [base+wiener_hshift+t3*4] + vpbroadcastd m10, [base+wiener_round+t3*4] + vpbroadcastd m11, [base+wiener_vshift+t3*4] + pmullw m12, m0 ; upshift filter coefs to make the + pmullw m13, m0 ; horizontal downshift constant + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call .v + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call .v +.v2: + call .v + jmp .v1 +.extend_right: + movd xm1, r10d + vpbroadcastd m0, [pb_6_7] + movu m2, [pb_0to31] + vpbroadcastb m1, xm1 + psubb m0, m1 + pminub m0, m2 + pshufb m3, m0 + vpbroadcastd m0, [pb_m2_m1] + psubb m0, m1 + pminub m0, m2 + pshufb m4, m0 + vpbroadcastd m0, [pb_m10_m9] + psubb m0, m1 + pminub m0, m2 + pshufb m5, m0 + ret +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movq xm3, [leftq] + vpblendd m3, [lpfq+r10-8], 0xfc + add leftq, 8 + jmp .h_main +.h_extend_left: + vbroadcasti128 m3, [lpfq+r10] ; avoid accessing memory located + mova m4, [lpfq+r10] ; before the start of the buffer + shufpd m3, m4, 0x05 + pshufb m3, [wiener_lshuf7] + jmp .h_main2 +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+r10-8] +.h_main: + mova m4, [lpfq+r10+0] +.h_main2: + movu m5, [lpfq+r10+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -36 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m0, m3, m6 + pshufb m1, m4, m7 + paddw m0, m1 + pshufb m3, m8 + pmaddwd m0, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + pmaddwd m3, m13 + pshufb m2, m5, m7 + paddw m1, m2 + vpbroadcastd m2, [pd_m262128] ; (1 << 4) - (1 << 18) + pshufb m4, m8 + pmaddwd m1, m12 + pshufb m5, m9 + paddw m4, m5 + pmaddwd m4, m13 + paddd m0, m2 + paddd m1, m2 + paddd m0, m3 + paddd m1, m4 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+r10], m0 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movq xm3, [leftq] + vpblendd m3, [lpfq+r10-8], 0xfc + add leftq, 8 + jmp .hv_main +.hv_extend_left: + movu m3, [lpfq+r10-8] + pshufb m3, [wiener_lshuf7] + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+r10-8] +.hv_main: + mova m4, [lpfq+r10+0] + movu m5, [lpfq+r10+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -36 + jl .hv_have_right + call .extend_right +.hv_have_right: + pshufb m0, m3, m6 + pshufb m1, m4, m7 + paddw m0, m1 + pshufb m3, m8 + pmaddwd m0, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + pmaddwd m3, m13 + pshufb m2, m5, m7 + paddw m1, m2 + vpbroadcastd m2, [pd_m262128] + pshufb m4, m8 + pmaddwd m1, m12 + pshufb m5, m9 + paddw m4, m5 + pmaddwd m4, m13 + paddd m0, m2 + paddd m1, m2 + mova m2, [t4+r10] + paddw m2, [t2+r10] + mova m5, [t3+r10] + paddd m0, m3 + paddd m1, m4 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova m4, [t5+r10] + paddw m4, [t1+r10] + psraw m0, 1 + paddw m3, m0, [t6+r10] + mova [t0+r10], m0 + punpcklwd m0, m2, m5 + pmaddwd m0, m15 + punpckhwd m2, m5 + pmaddwd m2, m15 + punpcklwd m1, m3, m4 + pmaddwd m1, m14 + punpckhwd m3, m4 + pmaddwd m3, m14 + paddd m0, m10 + paddd m2, m10 + paddd m0, m1 + paddd m2, m3 + psrad m0, 5 + psrad m2, 5 + packusdw m0, m2 + pmulhuw m0, m11 + mova [dstq+r10], m0 + add r10, 32 + jl .hv_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m1, [t4+r10] + paddw m1, [t2+r10] + mova m2, [t3+r10] + mova m4, [t1+r10] + paddw m3, m4, [t6+r10] + paddw m4, [t5+r10] + punpcklwd m0, m1, m2 + pmaddwd m0, m15 + punpckhwd m1, m2 + pmaddwd m1, m15 + punpcklwd m2, m3, m4 + pmaddwd m2, m14 + punpckhwd m3, m4 + pmaddwd m3, m14 + paddd m0, m10 + paddd m1, m10 + paddd m0, m2 + paddd m1, m3 + psrad m0, 5 + psrad m1, 5 + packusdw m0, m1 + pmulhuw m0, m11 + mova [dstq+r10], m0 + add r10, 32 + jl .v_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq + ret + +cglobal wiener_filter5_16bpc, 4, 13, 16, 384*8+16, dst, stride, left, lpf, \ + w, h, edge, flt +%define base t4-wiener_hshift + mov fltq, r6mp + movifnidn wd, wm + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + vbroadcasti128 m5, [wiener_shufE] + vpbroadcastw m11, [fltq+ 2] ; x1 + vbroadcasti128 m6, [wiener_shufB] + lea t4, [wiener_hshift] + vbroadcasti128 m7, [wiener_shufD] + add wd, wd + vpbroadcastd m12, [fltq+ 4] ; x2 x3 + shr t3d, 11 + vpbroadcastd m8, [pd_m262128] ; (1 << 4) - (1 << 18) + add lpfq, wq + vpbroadcastw m13, [fltq+18] ; y1 + add dstq, wq + vpbroadcastd m14, [fltq+20] ; y2 y3 + lea t1, [rsp+wq+16] + neg wq + vpbroadcastd m0, [base+wiener_hshift+t3*4] + vpbroadcastd m9, [base+wiener_round+t3*4] + vpbroadcastd m10, [base+wiener_vshift+t3*4] + movu xm15, [wiener_lshuf5] + pmullw m11, m0 + vinserti128 m15, [pb_0to31], 1 + pmullw m12, m0 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t4, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t3, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 +.main: + mov t0, t4 +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v2 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.end: + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v2 + add t0, 384*6 + call .hv + dec hd + jnz .main +.v2: + call .v + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq +.v1: + call .v + jmp .end +.extend_right: + movd xm2, r10d + vpbroadcastd m0, [pb_2_3] + vpbroadcastd m1, [pb_m6_m5] + vpbroadcastb m2, xm2 + psubb m0, m2 + psubb m1, m2 + movu m2, [pb_0to31] + pminub m0, m2 + pminub m1, m2 + pshufb m3, m0 + pshufb m4, m1 + ret +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm3, [leftq+4] + vpblendd m3, [lpfq+r10-4], 0xfe + add leftq, 8 + jmp .h_main +.h_extend_left: + vbroadcasti128 m4, [lpfq+r10] ; avoid accessing memory located + mova m3, [lpfq+r10] ; before the start of the buffer + palignr m3, m4, 12 + pshufb m3, m15 + jmp .h_main +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+r10-4] +.h_main: + movu m4, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -34 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m0, m3, m5 + pmaddwd m0, m11 + pshufb m1, m4, m5 + pmaddwd m1, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + pmaddwd m2, m12 + pshufb m4, m7 + paddw m3, m4 + pmaddwd m3, m12 + paddd m0, m8 + paddd m1, m8 + paddd m0, m2 + paddd m1, m3 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+r10], m0 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm3, [leftq+4] + vpblendd m3, [lpfq+r10-4], 0xfe + add leftq, 8 + jmp .hv_main +.hv_extend_left: + movu m3, [lpfq+r10-4] + pshufb m3, m15 + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+r10-4] +.hv_main: + movu m4, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -34 + jl .hv_have_right + call .extend_right +.hv_have_right: + pshufb m0, m3, m5 + pmaddwd m0, m11 + pshufb m1, m4, m5 + pmaddwd m1, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + pmaddwd m2, m12 + pshufb m4, m7 + paddw m3, m4 + pmaddwd m3, m12 + paddd m0, m8 + paddd m1, m8 + paddd m0, m2 + mova m2, [t3+r10] + paddw m2, [t1+r10] + paddd m1, m3 + mova m4, [t2+r10] + punpckhwd m3, m2, m4 + pmaddwd m3, m14 + punpcklwd m2, m4 + mova m4, [t4+r10] + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + pmaddwd m2, m14 + psraw m0, 1 + mova [t0+r10], m0 + punpckhwd m1, m0, m4 + pmaddwd m1, m13 + punpcklwd m0, m4 + pmaddwd m0, m13 + paddd m3, m9 + paddd m2, m9 + paddd m1, m3 + paddd m0, m2 + psrad m1, 5 + psrad m0, 5 + packusdw m0, m1 + pmulhuw m0, m10 + mova [dstq+r10], m0 + add r10, 32 + jl .hv_loop + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t4 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m0, [t1+r10] + paddw m2, m0, [t3+r10] + mova m1, [t2+r10] + mova m4, [t4+r10] + punpckhwd m3, m2, m1 + pmaddwd m3, m14 + punpcklwd m2, m1 + pmaddwd m2, m14 + punpckhwd m1, m0, m4 + pmaddwd m1, m13 + punpcklwd m0, m4 + pmaddwd m0, m13 + paddd m3, m9 + paddd m2, m9 + paddd m1, m3 + paddd m0, m2 + psrad m1, 5 + psrad m0, 5 + packusdw m0, m1 + pmulhuw m0, m10 + mova [dstq+r10], m0 + add r10, 32 + jl .v_loop + ret + +cglobal sgr_filter_5x5_16bpc, 4, 14, 15, 400*24+16, dst, stride, left, lpf, \ + w, h, edge, params + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [sgr_x_by_x_avx2+256*4] + movifnidn hd, hm + mov edged, r7m + add wd, wd + vpbroadcastw m7, [paramsq+8] ; w0 + add lpfq, wq + vpbroadcastd m8, [pd_8] + add dstq, wq + vpbroadcastd m9, [pd_25] + lea t3, [rsp+wq*2+400*12+16] + vpbroadcastd m10, [paramsq+0] ; s0 + lea t4, [rsp+wq+400*20+16] + vpbroadcastd m11, [pd_0xf00800a4] + lea t1, [rsp+wq+20] + mova xm12, [sgr_lshuf5] + neg wq + vpbroadcastd m13, [pd_34816] ; (1 << 11) + (1 << 15) + pxor m6, m6 + vpbroadcastd m14, [pw_1023] + psllw m7, 4 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call .top_fixup + add t1, 400*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, strideq + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + test hd, hd + jz .odd_height + call .h + add lpfq, strideq + call .hv + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .h_top + add lpfq, strideq + call .hv_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + call .n0 + call .n1 +.odd_height_end: + call .v + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+400*6] + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + jmp .main +.no_top_height1: + call .v + call .prep_n + jmp .odd_height_end +.extend_right: + vpbroadcastw m0, [lpfq-2] + movu m1, [r13+r10+ 0] + movu m2, [r13+r10+16] + vpblendvb m4, m0, m1 + vpblendvb m5, m0, m2 + ret +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 10 + jmp .h_main +.h_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, xm12 + vinserti128 m4, [lpfq+wq+10], 1 + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+r10- 2] +.h_main: + movu m5, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -36 + jl .h_have_right + call .extend_right +.h_have_right: + palignr m2, m5, m4, 2 + paddw m0, m4, m2 + palignr m3, m5, m4, 6 + paddw m0, m3 + punpcklwd m1, m2, m3 + pmaddwd m1, m1 + punpckhwd m2, m3 + pmaddwd m2, m2 + shufpd m5, m4, m5, 0x05 + paddw m0, m5 + punpcklwd m3, m4, m5 + pmaddwd m3, m3 + paddd m1, m3 + punpckhwd m3, m4, m5 + pmaddwd m3, m3 + shufps m4, m5, q2121 + paddw m0, m4 ; sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m2, m3 + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+r10+400*0] + paddd m1, [t1+r10+400*2] + paddd m2, [t1+r10+400*4] +.h_loop_end: + paddd m1, m5 ; sumsq + paddd m2, m4 + mova [t1+r10+400*0], m0 + mova [t1+r10+400*2], m1 + mova [t1+r10+400*4], m2 + add r10, 32 + jl .h_loop + ret +.top_fixup: + lea r10, [wq-4] +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+r10+400*0] + mova m1, [t1+r10+400*2] + mova m2, [t1+r10+400*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m1 + mova [t2+r10+400*4], m2 + add r10, 32 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 10 + jmp .hv_main +.hv_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, xm12 + vinserti128 m4, [lpfq+wq+10], 1 + jmp .hv_main +.hv_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m4, [lpfq+r10- 2] +.hv_main: + movu m5, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -36 + jl .hv_have_right + call .extend_right +.hv_have_right: + palignr m3, m5, m4, 2 + paddw m0, m4, m3 + palignr m1, m5, m4, 6 + paddw m0, m1 + punpcklwd m2, m3, m1 + pmaddwd m2, m2 + punpckhwd m3, m1 + pmaddwd m3, m3 + shufpd m5, m4, m5, 0x05 + paddw m0, m5 + punpcklwd m1, m4, m5 + pmaddwd m1, m1 + paddd m2, m1 + punpckhwd m1, m4, m5 + pmaddwd m1, m1 + shufps m4, m5, q2121 + paddw m0, m4 ; h sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m3, m1 + paddd m2, m5 ; h sumsq + paddd m3, m4 + paddw m1, m0, [t1+r10+400*0] + paddd m4, m2, [t1+r10+400*2] + paddd m5, m3, [t1+r10+400*4] + test hd, hd + jz .hv_last_row +.hv_main2: + paddw m1, [t2+r10+400*0] ; hv sum + paddd m4, [t2+r10+400*2] ; hv sumsq + paddd m5, [t2+r10+400*4] + mova [t0+r10+400*0], m0 + mova [t0+r10+400*2], m2 + mova [t0+r10+400*4], m3 + psrlw m3, m1, 1 + paddd m4, m8 + pavgw m3, m6 ; (b + 2) >> 2 + paddd m5, m8 + psrld m4, 4 ; (a + 8) >> 4 + punpcklwd m2, m3, m6 + psrld m5, 4 + punpckhwd m3, m6 + pmulld m4, m9 ; a * 25 + pmulld m5, m9 + pmaddwd m2, m2 ; b * b + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + pmaxud m5, m3 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m10 ; p * s + pmulld m5, m10 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m13 + mova [t4+r10+4], m2 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+r10*2+ 8], xm0 + vextracti128 [t3+r10*2+40], m0, 1 + mova [t3+r10*2+24], xm1 + vextracti128 [t3+r10*2+56], m1, 1 + add r10, 32 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+r10+400*0], m1 + paddw m1, m0 + mova [t1+r10+400*2], m4 + paddd m4, m2 + mova [t1+r10+400*4], m5 + paddd m5, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab + lea r10, [wq-4] +.v_loop: + mova m0, [t1+r10+400*0] + mova m2, [t1+r10+400*2] + mova m3, [t1+r10+400*4] + paddw m1, m0, [t2+r10+400*0] + paddd m4, m2, [t2+r10+400*2] + paddd m5, m3, [t2+r10+400*4] + paddw m0, m0 + paddd m2, m2 + paddd m3, m3 + paddw m1, m0 ; hv sum + paddd m4, m2 ; hv sumsq + paddd m5, m3 + psrlw m3, m1, 1 + paddd m4, m8 + pavgw m3, m6 ; (b + 2) >> 2 + paddd m5, m8 + psrld m4, 4 ; (a + 8) >> 4 + punpcklwd m2, m3, m6 + psrld m5, 4 + punpckhwd m3, m6 + pmulld m4, m9 ; a * 25 + pmulld m5, m9 + pmaddwd m2, m2 ; b * b + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + pmaxud m5, m3 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m10 ; p * s + pmulld m5, m10 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m13 + mova [t4+r10+4], m2 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+r10*2+ 8], xm0 + vextracti128 [t3+r10*2+40], m0, 1 + mova [t3+r10*2+24], xm1 + vextracti128 [t3+r10*2+56], m1, 1 + add r10, 32 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t4+r10*1+ 2] + movu m1, [t3+r10*2+ 4] + movu m2, [t3+r10*2+36] + paddw m3, m0, [t4+r10*1+ 0] + paddd m4, m1, [t3+r10*2+ 0] + paddd m5, m2, [t3+r10*2+32] + paddw m3, [t4+r10*1+ 4] + paddd m4, [t3+r10*2+ 8] + paddd m5, [t3+r10*2+40] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + mova [t4+r10*1+400*2+ 0], m0 + mova [t3+r10*2+400*4+ 0], m1 + mova [t3+r10*2+400*4+32], m2 + add r10, 32 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m0, [t4+r10*1+ 2] + movu m1, [t3+r10*2+ 4] + movu m2, [t3+r10*2+36] + paddw m3, m0, [t4+r10*1+ 0] + paddd m4, m1, [t3+r10*2+ 0] + paddd m5, m2, [t3+r10*2+32] + paddw m3, [t4+r10*1+ 4] + paddd m4, [t3+r10*2+ 8] + paddd m5, [t3+r10*2+40] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + paddw m3, m0, [t4+r10*1+400*2+ 0] + paddd m4, m1, [t3+r10*2+400*4+ 0] + paddd m5, m2, [t3+r10*2+400*4+32] + mova [t4+r10*1+400*2+ 0], m0 + mova [t3+r10*2+400*4+ 0], m1 + mova [t3+r10*2+400*4+32], m2 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vinserti128 m1, m4, xm5, 1 + vperm2i128 m4, m5, 0x31 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m4, m3 + psrad m1, 9 + psrad m4, 9 + packssdw m1, m4 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 32 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m0, [dstq+r10] + mova m3, [t4+r10*1+400*2+ 0] + mova m4, [t3+r10*2+400*4+ 0] + mova m5, [t3+r10*2+400*4+32] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vinserti128 m1, m4, xm5, 1 + vperm2i128 m4, m5, 0x31 + psubd m1, m2 ; b - a * src + (1 << 7) + psubd m4, m3 + psrad m1, 8 + psrad m4, 8 + packssdw m1, m4 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 32 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_3x3_16bpc, 4, 14, 14, 400*42+8, dst, stride, left, lpf, \ + w, h, edge, params + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [sgr_x_by_x_avx2+256*4] + add wd, wd + movifnidn hd, hm + mov edged, r7m + add lpfq, wq + vpbroadcastw m7, [paramsq+10] ; w1 + add dstq, wq + vpbroadcastd m9, [paramsq+ 4] ; s1 + lea t3, [rsp+wq*2+400*12+8] + vpbroadcastd m8, [pd_8] + lea t4, [rsp+wq+400*32+8] + vpbroadcastd m10, [pd_0xf00801c7] + lea t1, [rsp+wq+12] + vpbroadcastd m11, [pd_34816] + neg wq + mova xm12, [sgr_lshuf3] + pxor m6, m6 + vpbroadcastd m13, [pw_1023] + psllw m7, 4 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + add t1, 400*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea r10, [wq-4] + lea t2, [t1+400*6] +.top_fixup_loop: + mova m0, [t1+r10+400*0] + mova m1, [t1+r10+400*2] + mova m2, [t1+r10+400*4] + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m1 + mova [t2+r10+400*4], m2 + add r10, 32 + jl .top_fixup_loop + call .v0 + jmp .main +.extend_right: + vpbroadcastw m0, [lpfq-2] + movu m1, [r13+r10+ 2] + movu m2, [r13+r10+18] + vpblendvb m4, m0, m1 + vpblendvb m5, m0, m2 + ret +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 12 + jmp .h_main +.h_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, xm12 + vinserti128 m4, [lpfq+wq+12], 1 + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+r10+ 0] +.h_main: + movu m5, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -34 + jl .h_have_right + call .extend_right +.h_have_right: + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + mova [t1+r10+400*0], m1 + mova [t1+r10+400*2], m2 + mova [t1+r10+400*4], m3 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab (even rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 12 + jmp .hv0_main +.hv0_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, xm12 + vinserti128 m4, [lpfq+wq+12], 1 + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu m4, [lpfq+r10+ 0] +.hv0_main: + movu m5, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -34 + jl .hv0_have_right + call .extend_right +.hv0_have_right: + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + paddw m0, m1, [t1+r10+400*0] + paddd m4, m2, [t1+r10+400*2] + paddd m5, m3, [t1+r10+400*4] + mova [t1+r10+400*0], m1 + mova [t1+r10+400*2], m2 + mova [t1+r10+400*4], m3 + paddw m1, m0, [t2+r10+400*0] + paddd m2, m4, [t2+r10+400*2] + paddd m3, m5, [t2+r10+400*4] + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m4 + mova [t2+r10+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + psubd m4, m2 ; p + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m9 ; p * s + pmulld m5, m9 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*0+ 4], m2 + mova [t3+r10*2+400*0+ 8], xm0 + vextracti128 [t3+r10*2+400*0+40], m0, 1 + mova [t3+r10*2+400*0+24], xm1 + vextracti128 [t3+r10*2+400*0+56], m1, 1 + add r10, 32 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 12 + jmp .hv1_main +.hv1_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, xm12 + vinserti128 m4, [lpfq+wq+12], 1 + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu m4, [lpfq+r10+ 0] +.hv1_main: + movu m5, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -34 + jl .hv1_have_right + call .extend_right +.hv1_have_right: + palignr m1, m5, m4, 2 + paddw m0, m4, m1 + punpcklwd m2, m4, m1 + pmaddwd m2, m2 + punpckhwd m3, m4, m1 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m0, m5 ; h sum + punpcklwd m1, m5, m6 + pmaddwd m1, m1 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m1 ; h sumsq + paddd m3, m5 + paddw m1, m0, [t2+r10+400*0] + paddd m4, m2, [t2+r10+400*2] + paddd m5, m3, [t2+r10+400*4] + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m2 + mova [t2+r10+400*4], m3 + paddd m4, m8 + paddd m5, m8 + psrld m4, 4 ; (a + 8) >> 4 + psrld m5, 4 + pslld m2, m4, 3 + pslld m3, m5, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + psubd m4, m2 ; p + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m9 ; p * s + pmulld m5, m9 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*2 +4], m2 + mova [t3+r10*2+400*4+ 8], xm0 + vextracti128 [t3+r10*2+400*4+40], m0, 1 + mova [t3+r10*2+400*4+24], xm1 + vextracti128 [t3+r10*2+400*4+56], m1, 1 + add r10, 32 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab (even rows) + lea r10, [wq-4] +.v0_loop: + mova m0, [t1+r10+400*0] + mova m4, [t1+r10+400*2] + mova m5, [t1+r10+400*4] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+r10+400*0] + paddd m2, m4, [t2+r10+400*2] + paddd m3, m5, [t2+r10+400*4] + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m4 + mova [t2+r10+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + psubd m4, m2 ; p + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m9 ; p * s + pmulld m5, m9 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*0+ 4], m2 + mova [t3+r10*2+400*0+ 8], xm0 + vextracti128 [t3+r10*2+400*0+40], m0, 1 + mova [t3+r10*2+400*0+24], xm1 + vextracti128 [t3+r10*2+400*0+56], m1, 1 + add r10, 32 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-4] +.v1_loop: + mova m0, [t1+r10+400*0] + mova m4, [t1+r10+400*2] + mova m5, [t1+r10+400*4] + paddw m1, m0, [t2+r10+400*0] + paddd m2, m4, [t2+r10+400*2] + paddd m3, m5, [t2+r10+400*4] + mova [t2+r10+400*0], m0 + mova [t2+r10+400*2], m4 + mova [t2+r10+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaxud m4, m2 + psubd m4, m2 ; p + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m9 ; p * s + pmulld m5, m9 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*2+ 4], m2 + mova [t3+r10*2+400*4+ 8], xm0 + vextracti128 [t3+r10*2+400*4+40], m0, 1 + mova [t3+r10*2+400*4+24], xm1 + vextracti128 [t3+r10*2+400*4+56], m1, 1 + add r10, 32 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + mova xm0, [t4+r10*1+400*0+0] + paddw xm0, [t4+r10*1+400*0+4] + paddw xm2, xm0, [t4+r10*1+400*0+2] + mova m1, [t3+r10*2+400*0+0] + paddd m1, [t3+r10*2+400*0+8] + paddd m3, m1, [t3+r10*2+400*0+4] + psllw xm2, 2 ; a[-1] 444 + pslld m3, 2 ; b[-1] 444 + psubw xm2, xm0 ; a[-1] 343 + psubd m3, m1 ; b[-1] 343 + mova [t4+r10*1+400* 4], xm2 + mova [t3+r10*2+400* 8], m3 + mova xm0, [t4+r10*1+400*2+0] + paddw xm0, [t4+r10*1+400*2+4] + paddw xm2, xm0, [t4+r10*1+400*2+2] + mova m1, [t3+r10*2+400*4+0] + paddd m1, [t3+r10*2+400*4+8] + paddd m3, m1, [t3+r10*2+400*4+4] + psllw xm2, 2 ; a[ 0] 444 + pslld m3, 2 ; b[ 0] 444 + mova [t4+r10*1+400* 6], xm2 + mova [t3+r10*2+400*12], m3 + psubw xm2, xm0 ; a[ 0] 343 + psubd m3, m1 ; b[ 0] 343 + mova [t4+r10*1+400* 8], xm2 + mova [t3+r10*2+400*16], m3 + add r10, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + mova m3, [t4+r10*1+400*0+0] + paddw m3, [t4+r10*1+400*0+4] + paddw m1, m3, [t4+r10*1+400*0+2] + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+r10*1+400*4] + paddw m3, [t4+r10*1+400*6] + mova [t4+r10*1+400*4], m2 + mova [t4+r10*1+400*6], m1 + mova m4, [t3+r10*2+400*0+0] + paddd m4, [t3+r10*2+400*0+8] + paddd m1, m4, [t3+r10*2+400*0+4] + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+r10*2+400* 8+ 0] + paddd m4, [t3+r10*2+400*12+ 0] + mova [t3+r10*2+400* 8+ 0], m2 + mova [t3+r10*2+400*12+ 0], m1 + mova m5, [t3+r10*2+400*0+32] + paddd m5, [t3+r10*2+400*0+40] + paddd m1, m5, [t3+r10*2+400*0+36] + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+r10*2+400* 8+32] + paddd m5, [t3+r10*2+400*12+32] + mova [t3+r10*2+400* 8+32], m2 + mova [t3+r10*2+400*12+32], m1 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vinserti128 m1, m4, xm5, 1 + vperm2i128 m4, m5, 0x31 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m4, m3 + psrad m1, 9 + psrad m4, 9 + packssdw m1, m4 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m13 + mova [dstq+r10], m0 + add r10, 32 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m3, [t4+r10*1+400*2+0] + paddw m3, [t4+r10*1+400*2+4] + paddw m1, m3, [t4+r10*1+400*2+2] + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+r10*1+400*6] + paddw m3, [t4+r10*1+400*8] + mova [t4+r10*1+400*6], m1 + mova [t4+r10*1+400*8], m2 + mova m4, [t3+r10*2+400*4+0] + paddd m4, [t3+r10*2+400*4+8] + paddd m1, m4, [t3+r10*2+400*4+4] + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+r10*2+400*12+ 0] + paddd m4, [t3+r10*2+400*16+ 0] + mova [t3+r10*2+400*12+ 0], m1 + mova [t3+r10*2+400*16+ 0], m2 + mova m5, [t3+r10*2+400*4+32] + paddd m5, [t3+r10*2+400*4+40] + paddd m1, m5, [t3+r10*2+400*4+36] + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+r10*2+400*12+32] + paddd m5, [t3+r10*2+400*16+32] + mova [t3+r10*2+400*12+32], m1 + mova [t3+r10*2+400*16+32], m2 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vinserti128 m1, m4, xm5, 1 + vperm2i128 m4, m5, 0x31 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m4, m3 + psrad m1, 9 + psrad m4, 9 + packssdw m1, m4 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m13 + mova [dstq+r10], m0 + add r10, 32 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_mix_16bpc, 4, 14, 16, 400*66+8, dst, stride, left, lpf, \ + w, h, edge, params + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [sgr_x_by_x_avx2+256*4] + add wd, wd + movifnidn hd, hm + mov edged, r7m + add lpfq, wq + vpbroadcastd m15, [paramsq+8] ; w0 w1 + add dstq, wq + vpbroadcastd m13, [paramsq+0] ; s0 + lea t3, [rsp+wq*2+400*24+8] + vpbroadcastd m14, [paramsq+4] ; s1 + lea t4, [rsp+wq+400*52+8] + vpbroadcastd m9, [pd_8] + lea t1, [rsp+wq+12] + vpbroadcastd m10, [pd_34816] + neg wq + vpbroadcastd m11, [pd_4096] + pxor m7, m7 + vpbroadcastd m12, [pd_0xf00801c7] + psllw m15, 2 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_avx2).top_fixup + add t1, 400*12 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea r10, [wq-4] + lea t2, [t1+400*12] +.top_fixup_loop: + mova m0, [t1+r10+400* 0] + mova m1, [t1+r10+400* 2] + mova m2, [t1+r10+400* 4] + paddw m0, m0 + mova m3, [t1+r10+400* 6] + paddd m1, m1 + mova m4, [t1+r10+400* 8] + paddd m2, m2 + mova m5, [t1+r10+400*10] + mova [t2+r10+400* 0], m0 + mova [t2+r10+400* 2], m1 + mova [t2+r10+400* 4], m2 + mova [t2+r10+400* 6], m3 + mova [t2+r10+400* 8], m4 + mova [t2+r10+400*10], m5 + add r10, 32 + jl .top_fixup_loop + call .v0 + jmp .main +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 10 + jmp .h_main +.h_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, [sgr_lshuf5] + vinserti128 m4, [lpfq+wq+10], 1 + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+r10- 2] +.h_main: + movu m5, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -36 + jl .h_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_avx2).extend_right +.h_have_right: + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; sum3 + punpcklwd m6, m0, m7 + pmaddwd m6, m6 + punpckhwd m0, m7 + pmaddwd m0, m0 + paddd m2, m6 ; sumsq3 + shufpd m6, m4, m5, 0x05 + punpcklwd m5, m6, m4 + paddw m8, m4, m6 + pmaddwd m5, m5 + punpckhwd m6, m4 + pmaddwd m6, m6 + paddd m3, m0 + mova [t1+r10+400* 6], m1 + mova [t1+r10+400* 8], m2 + mova [t1+r10+400*10], m3 + paddw m8, m1 ; sum5 + paddd m5, m2 ; sumsq5 + paddd m6, m3 + mova [t1+r10+400* 0], m8 + mova [t1+r10+400* 2], m5 + mova [t1+r10+400* 4], m6 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab3 (even rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 10 + jmp .hv0_main +.hv0_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, [sgr_lshuf5] + vinserti128 m4, [lpfq+wq+10], 1 + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu m4, [lpfq+r10- 2] +.hv0_main: + movu m5, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -36 + jl .hv0_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_avx2).extend_right +.hv0_have_right: + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; h sum3 + punpcklwd m6, m0, m7 + pmaddwd m6, m6 + punpckhwd m0, m7 + pmaddwd m0, m0 + paddd m2, m6 ; h sumsq3 + shufpd m6, m4, m5, 0x05 + punpcklwd m5, m6, m4 + paddw m8, m4, m6 + pmaddwd m5, m5 + punpckhwd m6, m4 + pmaddwd m6, m6 + paddd m3, m0 + paddw m8, m1 ; h sum5 + paddd m5, m2 ; h sumsq5 + paddd m6, m3 + mova [t3+r10*2+400*8+ 8], m8 ; we need a clean copy of the last row TODO: t4? + mova [t3+r10*2+400*0+ 8], m5 ; in case height is odd + mova [t3+r10*2+400*0+40], m6 + paddw m8, [t1+r10+400* 0] + paddd m5, [t1+r10+400* 2] + paddd m6, [t1+r10+400* 4] + mova [t1+r10+400* 0], m8 + mova [t1+r10+400* 2], m5 + mova [t1+r10+400* 4], m6 + paddw m0, m1, [t1+r10+400* 6] + paddd m4, m2, [t1+r10+400* 8] + paddd m5, m3, [t1+r10+400*10] + mova [t1+r10+400* 6], m1 + mova [t1+r10+400* 8], m2 + mova [t1+r10+400*10], m3 + paddw m1, m0, [t2+r10+400* 6] + paddd m2, m4, [t2+r10+400* 8] + paddd m3, m5, [t2+r10+400*10] + mova [t2+r10+400* 6], m0 + mova [t2+r10+400* 8], m4 + mova [t2+r10+400*10], m5 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pmaxud m4, m2 + psubd m4, m2 ; p3 + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m12 ; b3 * 455 + pmaddwd m1, m12 + paddusw m4, m12 + paddusw m5, m12 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x3 + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*2+ 4], m2 + mova [t3+r10*2+400*4+ 8], xm0 + vextracti128 [t3+r10*2+400*4+40], m0, 1 + mova [t3+r10*2+400*4+24], xm1 + vextracti128 [t3+r10*2+400*4+56], m1, 1 + add r10, 32 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + vpbroadcastq xm5, [leftq] + vinserti128 m5, [lpfq+wq], 1 + mova m4, [lpfq+wq] + add leftq, 8 + palignr m4, m5, 10 + jmp .hv1_main +.hv1_extend_left: + mova xm4, [lpfq+wq] + pshufb xm4, [sgr_lshuf5] + vinserti128 m4, [lpfq+wq+10], 1 + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu m4, [lpfq+r10- 2] +.hv1_main: + movu m5, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -36 + jl .hv1_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_avx2).extend_right +.hv1_have_right: + palignr m6, m5, m4, 2 + palignr m3, m5, m4, 4 + paddw m2, m6, m3 + punpcklwd m0, m6, m3 + pmaddwd m0, m0 + punpckhwd m6, m3 + pmaddwd m6, m6 + palignr m3, m5, m4, 6 + paddw m2, m3 ; h sum3 + punpcklwd m1, m3, m7 + pmaddwd m1, m1 + punpckhwd m3, m7 + pmaddwd m3, m3 + paddd m0, m1 ; h sumsq3 + shufpd m1, m4, m5, 0x05 + punpckhwd m5, m4, m1 + paddw m8, m4, m1 + pmaddwd m5, m5 + punpcklwd m4, m1 + pmaddwd m4, m4 + paddd m6, m3 + paddw m1, m2, [t2+r10+400* 6] + mova [t2+r10+400* 6], m2 + paddw m8, m2 ; h sum5 + paddd m2, m0, [t2+r10+400* 8] + paddd m3, m6, [t2+r10+400*10] + mova [t2+r10+400* 8], m0 + mova [t2+r10+400*10], m6 + paddd m4, m0 ; h sumsq5 + paddd m5, m6 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pslld m0, m2, 3 + pslld m6, m3, 3 + paddd m2, m0 ; ((a3 + 8) >> 4) * 9 + paddd m3, m6 + psrlw m6, m1, 1 + pavgw m6, m7 ; (b3 + 2) >> 2 + punpcklwd m0, m6, m7 + pmaddwd m0, m0 + punpckhwd m6, m7 + pmaddwd m6, m6 + pmaxud m2, m0 + psubd m2, m0 ; p3 + pmaxud m3, m6 + psubd m3, m6 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pmulld m2, m14 ; p3 * s1 + pmulld m3, m14 + pmaddwd m0, m12 ; b3 * 455 + pmaddwd m1, m12 + paddusw m2, m12 + paddusw m3, m12 + psrad m7, m2, 20 ; min(z3, 255) - 256 + vpgatherdd m6, [r13+m7*4], m2 ; x3 + psrad m2, m3, 20 + vpgatherdd m7, [r13+m2*4], m3 + pmulld m0, m6 + packssdw m6, m7 + pmulld m7, m1 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m7, m10 + psrld m0, 12 + psrld m7, 12 + paddw m1, m8, [t2+r10+400*0] + paddd m2, m4, [t2+r10+400*2] + paddd m3, m5, [t2+r10+400*4] + paddw m1, [t1+r10+400*0] + paddd m2, [t1+r10+400*2] + paddd m3, [t1+r10+400*4] + mova [t2+r10+400*0], m8 + mova [t2+r10+400*2], m4 + mova [t2+r10+400*4], m5 + mova [t4+r10*1+400*4 +4], m6 + mova [t3+r10*2+400*8+ 8], xm0 + vextracti128 [t3+r10*2+400*8+40], m0, 1 + mova [t3+r10*2+400*8+24], xm7 + vextracti128 [t3+r10*2+400*8+56], m7, 1 + vpbroadcastd m4, [pd_25] + pxor m7, m7 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + pmulld m2, m4 ; ((a5 + 8) >> 4) * 25 + pmulld m3, m4 + psrlw m5, m1, 1 + pavgw m5, m7 ; (b5 + 2) >> 2 + punpcklwd m4, m5, m7 + pmaddwd m4, m4 + punpckhwd m5, m7 + pmaddwd m5, m5 + punpcklwd m0, m1, m7 ; b5 + punpckhwd m1, m7 + pmaxud m2, m4 + psubd m2, m4 ; p5 + vpbroadcastd m4, [pd_0xf00800a4] + pmaxud m3, m5 + psubd m3, m5 + pmulld m2, m13 ; p5 * s0 + pmulld m3, m13 + pmaddwd m0, m4 ; b5 * 164 + pmaddwd m1, m4 + paddusw m2, m4 + paddusw m3, m4 + psrad m5, m2, 20 ; min(z5, 255) - 256 + vpgatherdd m4, [r13+m5*4], m2 ; x5 + psrad m2, m3, 20 + vpgatherdd m5, [r13+m2*4], m3 + pmulld m0, m4 + pmulld m1, m5 + packssdw m4, m5 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m10 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*0+ 4], m4 + mova [t3+r10*2+400*0+ 8], xm0 + vextracti128 [t3+r10*2+400*0+40], m0, 1 + mova [t3+r10*2+400*0+24], xm1 + vextracti128 [t3+r10*2+400*0+56], m1, 1 + add r10, 32 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) + lea r10, [wq-4] +.v0_loop: + mova m0, [t1+r10+400* 6] + mova m4, [t1+r10+400* 8] + mova m5, [t1+r10+400*10] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+r10+400* 6] + paddd m2, m4, [t2+r10+400* 8] + paddd m3, m5, [t2+r10+400*10] + mova [t2+r10+400* 6], m0 + mova [t2+r10+400* 8], m4 + mova [t2+r10+400*10], m5 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pmaxud m4, m2 + psubd m4, m2 ; p3 + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m12 ; b3 * 455 + pmaddwd m1, m12 + paddusw m4, m12 + paddusw m5, m12 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x3 + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + psrld m0, 12 + psrld m1, 12 + mova m3, [t1+r10+400*0] + mova m4, [t1+r10+400*2] + mova m5, [t1+r10+400*4] + mova [t3+r10*2+400*8+ 8], m3 + mova [t3+r10*2+400*0+ 8], m4 + mova [t3+r10*2+400*0+40], m5 + paddw m3, m3 ; cc5 + paddd m4, m4 + paddd m5, m5 + mova [t1+r10+400*0], m3 + mova [t1+r10+400*2], m4 + mova [t1+r10+400*4], m5 + mova [t4+r10*1+400*2+ 4], m2 + mova [t3+r10*2+400*4+ 8], xm0 + vextracti128 [t3+r10*2+400*4+40], m0, 1 + mova [t3+r10*2+400*4+24], xm1 + vextracti128 [t3+r10*2+400*4+56], m1, 1 + add r10, 32 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-4] +.v1_loop: + mova m4, [t1+r10+400* 6] + mova m5, [t1+r10+400* 8] + mova m6, [t1+r10+400*10] + paddw m1, m4, [t2+r10+400* 6] + paddd m2, m5, [t2+r10+400* 8] + paddd m3, m6, [t2+r10+400*10] + mova [t2+r10+400* 6], m4 + mova [t2+r10+400* 8], m5 + mova [t2+r10+400*10], m6 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pmaxud m4, m2 + psubd m4, m2 ; p3 + pmaxud m5, m3 + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m12 ; b3 * 455 + pmaddwd m1, m12 + paddusw m4, m12 + paddusw m5, m12 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r13+m3*4], m4 ; x3 + psrad m4, m5, 20 + vpgatherdd m3, [r13+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + packssdw m2, m3 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + psrld m0, 12 + psrld m8, m1, 12 + mova [t4+r10*1+400*4+4], m2 + mova m4, [t3+r10*2+400*8+ 8] + mova m5, [t3+r10*2+400*0+ 8] + mova m6, [t3+r10*2+400*0+40] + paddw m1, m4, [t2+r10+400*0] + paddd m2, m5, [t2+r10+400*2] + paddd m3, m6, [t2+r10+400*4] + paddw m1, [t1+r10+400*0] + paddd m2, [t1+r10+400*2] + paddd m3, [t1+r10+400*4] + mova [t2+r10+400*0], m4 + mova [t2+r10+400*2], m5 + mova [t2+r10+400*4], m6 + vpbroadcastd m4, [pd_25] + mova [t3+r10*2+400*8+ 8], xm0 + vextracti128 [t3+r10*2+400*8+40], m0, 1 + mova [t3+r10*2+400*8+24], xm8 + vextracti128 [t3+r10*2+400*8+56], m8, 1 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + pmulld m2, m4 ; ((a5 + 8) >> 4) * 25 + pmulld m3, m4 + psrlw m5, m1, 1 + pavgw m5, m7 ; (b5 + 2) >> 2 + punpcklwd m4, m5, m7 + pmaddwd m4, m4 + punpckhwd m5, m7 + pmaddwd m5, m5 + punpcklwd m0, m1, m7 ; b5 + punpckhwd m1, m7 + pmaxud m2, m4 + psubd m2, m4 ; p5 + vpbroadcastd m4, [pd_0xf00800a4] + pmaxud m3, m5 + psubd m3, m5 + pmulld m2, m13 ; p5 * s0 + pmulld m3, m13 + pmaddwd m0, m4 ; b5 * 164 + pmaddwd m1, m4 + paddusw m2, m4 + paddusw m3, m4 + psrad m5, m2, 20 ; min(z5, 255) - 256 + vpgatherdd m4, [r13+m5*4], m2 ; x5 + psrad m2, m3, 20 + vpgatherdd m5, [r13+m2*4], m3 + pmulld m0, m4 + pmulld m1, m5 + packssdw m4, m5 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m10 + psrld m0, 12 + psrld m1, 12 + mova [t4+r10*1+400*0+ 4], m4 + mova [t3+r10*2+400*0+ 8], xm0 + vextracti128 [t3+r10*2+400*0+40], m0, 1 + mova [t3+r10*2+400*0+24], xm1 + vextracti128 [t3+r10*2+400*0+56], m1, 1 + add r10, 32 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu xm0, [t4+r10*1+400*0+2] + paddw xm2, xm0, [t4+r10*1+400*0+0] + paddw xm2, [t4+r10*1+400*0+4] + movu m1, [t3+r10*2+400*0+4] + paddd m3, m1, [t3+r10*2+400*0+0] + paddd m3, [t3+r10*2+400*0+8] + paddw xm0, xm2 + paddd m1, m3 + psllw xm2, 2 + pslld m3, 2 + paddw xm0, xm2 ; a5 565 + paddd m1, m3 ; b5 565 + mova [t4+r10*1+400* 6], xm0 + mova [t3+r10*2+400*12], m1 + mova xm0, [t4+r10*1+400*2+0] + paddw xm0, [t4+r10*1+400*2+4] + paddw xm2, xm0, [t4+r10*1+400*2+2] + mova m1, [t3+r10*2+400*4+0] + paddd m1, [t3+r10*2+400*4+8] + paddd m3, m1, [t3+r10*2+400*4+4] + psllw xm2, 2 ; a3[-1] 444 + pslld m3, 2 ; b3[-1] 444 + psubw xm2, xm0 ; a3[-1] 343 + psubd m3, m1 ; b3[-1] 343 + mova [t4+r10*1+400* 8], xm2 + mova [t3+r10*2+400*16], m3 + mova xm0, [t4+r10*1+400*4+0] + paddw xm0, [t4+r10*1+400*4+4] + paddw xm2, xm0, [t4+r10*1+400*4+2] + mova m1, [t3+r10*2+400*8+0] + paddd m1, [t3+r10*2+400*8+8] + paddd m3, m1, [t3+r10*2+400*8+4] + psllw xm2, 2 ; a3[ 0] 444 + pslld m3, 2 ; b3[ 0] 444 + mova [t4+r10*1+400*10], xm2 + mova [t3+r10*2+400*20], m3 + psubw xm2, xm0 ; a3[ 0] 343 + psubd m3, m1 ; b3[ 0] 343 + mova [t4+r10*1+400*12], xm2 + mova [t3+r10*2+400*24], m3 + add r10, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu xm2, [t4+r10*1+2] + paddw xm0, xm2, [t4+r10*1+0] + paddw xm0, [t4+r10*1+4] + paddw xm2, xm0 + psllw xm0, 2 + paddw xm0, xm2 ; a5 + movu m1, [t3+r10*2+4] + paddd m4, m1, [t3+r10*2+0] + paddd m4, [t3+r10*2+8] + paddd m1, m4 + pslld m4, 2 + paddd m4, m1 ; b5 + paddw xm2, xm0, [t4+r10*1+400* 6] + mova [t4+r10*1+400* 6], xm0 + paddd m0, m4, [t3+r10*2+400*12] + mova [t3+r10*2+400*12], m4 + mova xm3, [t4+r10*1+400*2+0] + paddw xm3, [t4+r10*1+400*2+4] + paddw xm5, xm3, [t4+r10*1+400*2+2] + psllw xm5, 2 ; a3[ 1] 444 + psubw xm4, xm5, xm3 ; a3[ 1] 343 + paddw xm3, xm4, [t4+r10*1+400* 8] + paddw xm3, [t4+r10*1+400*10] + mova [t4+r10*1+400* 8], xm4 + mova [t4+r10*1+400*10], xm5 + mova m1, [t3+r10*2+400*4+0] + paddd m1, [t3+r10*2+400*4+8] + paddd m5, m1, [t3+r10*2+400*4+4] + pslld m5, 2 ; b3[ 1] 444 + psubd m4, m5, m1 ; b3[ 1] 343 + paddd m1, m4, [t3+r10*2+400*16] + paddd m1, [t3+r10*2+400*20] + mova [t3+r10*2+400*16], m4 + mova [t3+r10*2+400*20], m5 + pmovzxwd m4, [dstq+r10] + pmovzxwd m2, xm2 ; a5 + pmovzxwd m3, xm3 ; a3 + pmaddwd m2, m4 ; a5 * src + pmaddwd m3, m4 ; a3 * src + pslld m4, 13 + psubd m0, m2 ; b5 - a5 * src + (1 << 8) + psubd m1, m3 ; b3 - a3 * src + (1 << 8) + psrld m0, 9 + pslld m1, 7 + pblendw m0, m1, 0xaa + pmaddwd m0, m15 + paddd m4, m11 + paddd m0, m4 + psrad m0, 7 + vextracti128 xm1, m0, 1 + packusdw xm0, xm1 ; clip + psrlw xm0, 6 + mova [dstq+r10], xm0 + add r10, 16 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova xm3, [t4+r10*1+400*4+0] + paddw xm3, [t4+r10*1+400*4+4] + paddw xm5, xm3, [t4+r10*1+400*4+2] + psllw xm5, 2 ; a3[ 1] 444 + psubw xm4, xm5, xm3 ; a3[ 1] 343 + paddw xm3, xm4, [t4+r10*1+400*12] + paddw xm3, [t4+r10*1+400*10] + mova [t4+r10*1+400*10], xm5 + mova [t4+r10*1+400*12], xm4 + mova m1, [t3+r10*2+400*8+0] + paddd m1, [t3+r10*2+400*8+8] + paddd m5, m1, [t3+r10*2+400*8+4] + pslld m5, 2 ; b3[ 1] 444 + psubd m4, m5, m1 ; b3[ 1] 343 + paddd m1, m4, [t3+r10*2+400*24] + paddd m1, [t3+r10*2+400*20] + mova [t3+r10*2+400*20], m5 + mova [t3+r10*2+400*24], m4 + pmovzxwd m4, [dstq+r10] + pmovzxwd m2, [t4+r10*1+400* 6] + pmovzxwd m3, xm3 + mova m0, [t3+r10*2+400*12] + pmaddwd m2, m4 ; a5 * src + pmaddwd m3, m4 ; a3 * src + pslld m4, 13 + psubd m0, m2 ; b5 - a5 * src + (1 << 8) + psubd m1, m3 ; b3 - a3 * src + (1 << 8) + psrld m0, 8 + pslld m1, 7 + pblendw m0, m1, 0xaa + pmaddwd m0, m15 + paddd m4, m11 + paddd m0, m4 + psrad m0, 7 + vextracti128 xm1, m0, 1 + packusdw xm0, xm1 ; clip + psrlw xm0, 6 + mova [dstq+r10], xm0 + add r10, 16 + jl .n1_loop + add dstq, strideq + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2524 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 16 + +wiener_shufA: db 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11 +wiener_shufB: db 6, 7, 4, 5, 8, 9, 6, 7, 10, 11, 8, 9, 12, 13, 10, 11 +wiener_shufC: db 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15 +wiener_shufD: db 2, 3, -1, -1, 4, 5, -1, -1, 6, 7, -1, -1, 8, 9, -1, -1 +wiener_shufE: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +r_ext_mask: times 72 db -1 + times 8 db 0 +wiener_hshift: dw 4, 4, 1, 1 +wiener_vshift: dw 1024, 1024, 4096, 4096 +wiener_round: dd 1049600, 1048832 + +pw_164_455: dw 164, 455 +pw_1023: times 2 dw 1023 +pw_61448: times 2 dw 61448 +pd_m262128: dd -262128 +pd_m34816: dd -34816 +pd_m25: dd -25 +pd_m9: dd -9 +pd_8: dd 8 +pd_2147483648: dd 2147483648 + +cextern sgr_x_by_x + +SECTION .text + +DECLARE_REG_TMP 8, 7, 9, 11, 12, 13, 14 ; ring buffer pointers + +INIT_ZMM avx512icl +cglobal wiener_filter7_16bpc, 4, 15, 17, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt +%define base t4-wiener_hshift + mov fltq, r6mp + movifnidn wd, wm + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + vbroadcasti128 m6, [wiener_shufA] + vpbroadcastd m12, [fltq+ 0] ; x0 x1 + lea t4, [wiener_hshift] + vbroadcasti128 m7, [wiener_shufB] + add wd, wd + vpbroadcastd m13, [fltq+ 4] ; x2 x3 + shr t3d, 11 + vpbroadcastd m14, [fltq+16] ; y0 y1 + add lpfq, wq + vpbroadcastd m15, [fltq+20] ; y2 y3 + add dstq, wq + vbroadcasti128 m8, [wiener_shufC] + lea t1, [rsp+wq+16] + vbroadcasti128 m9, [wiener_shufD] + neg wq + vpbroadcastd m0, [base+wiener_hshift+t3*4] + mov r10d, 0xfe + vpbroadcastd m10, [base+wiener_round+t3*4] + kmovb k1, r10d + vpbroadcastd m11, [base+wiener_vshift+t3*4] + pmullw m12, m0 ; upshift filter coefs to make the + vpbroadcastd m16, [pd_m262128] + pmullw m13, m0 ; horizontal downshift constant + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call .v + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call .v +.v2: + call .v + jmp .v1 +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movq xm3, [leftq] + vmovdqu64 m3{k1}, [lpfq+r10-8] + add leftq, 8 + jmp .h_main +.h_extend_left: + mova m4, [lpfq+r10+0] + vpbroadcastw xm3, xm4 + vmovdqu64 m3{k1}, [lpfq+r10-8] + jmp .h_main2 +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+r10-8] +.h_main: + mova m4, [lpfq+r10+0] +.h_main2: + movu m5, [lpfq+r10+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -68 + jl .h_have_right + push r0 + lea r0, [r_ext_mask+66] + vpbroadcastw m0, [lpfq-2] + vpternlogd m3, m0, [r0+r10+ 0], 0xe4 ; c ? a : b + vpternlogd m4, m0, [r0+r10+ 8], 0xe4 + vpternlogd m5, m0, [r0+r10+16], 0xe4 + pop r0 +.h_have_right: + pshufb m2, m3, m6 + pshufb m1, m4, m7 + paddw m2, m1 + pshufb m3, m8 + mova m0, m16 + vpdpwssd m0, m2, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + vpdpwssd m0, m3, m13 + pshufb m2, m5, m7 + paddw m2, m1 + mova m1, m16 + pshufb m4, m8 + vpdpwssd m1, m2, m12 + pshufb m5, m9 + paddw m4, m5 + vpdpwssd m1, m4, m13 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+r10], m0 + add r10, 64 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movq xm3, [leftq] + vmovdqu64 m3{k1}, [lpfq+r10-8] + add leftq, 8 + jmp .hv_main +.hv_extend_left: + mova m4, [lpfq+r10+0] + vpbroadcastw xm3, xm4 + vmovdqu64 m3{k1}, [lpfq+r10-8] + jmp .hv_main2 +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+r10-8] +.hv_main: + mova m4, [lpfq+r10+0] +.hv_main2: + movu m5, [lpfq+r10+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -68 + jl .hv_have_right + push r0 + lea r0, [r_ext_mask+66] + vpbroadcastw m0, [lpfq-2] + vpternlogd m3, m0, [r0+r10+ 0], 0xe4 + vpternlogd m4, m0, [r0+r10+ 8], 0xe4 + vpternlogd m5, m0, [r0+r10+16], 0xe4 + pop r0 +.hv_have_right: + pshufb m2, m3, m6 + pshufb m1, m4, m7 + paddw m2, m1 + pshufb m3, m8 + mova m0, m16 + vpdpwssd m0, m2, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + vpdpwssd m0, m3, m13 + pshufb m2, m5, m7 + paddw m2, m1 + pshufb m4, m8 + mova m1, m16 + vpdpwssd m1, m2, m12 + pshufb m5, m9 + paddw m4, m5 + vpdpwssd m1, m4, m13 + mova m2, [t4+r10] + paddw m2, [t2+r10] + mova m5, [t3+r10] + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova m4, [t5+r10] + paddw m4, [t1+r10] + psraw m0, 1 + paddw m3, m0, [t6+r10] + mova [t0+r10], m0 + punpcklwd m1, m2, m5 + mova m0, m10 + vpdpwssd m0, m1, m15 + punpckhwd m2, m5 + mova m1, m10 + vpdpwssd m1, m2, m15 + punpcklwd m2, m3, m4 + vpdpwssd m0, m2, m14 + punpckhwd m3, m4 + vpdpwssd m1, m3, m14 + psrad m0, 5 + psrad m1, 5 + packusdw m0, m1 + pmulhuw m0, m11 + mova [dstq+r10], m0 + add r10, 64 + jl .hv_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m2, [t4+r10] + paddw m2, [t2+r10] + mova m3, [t3+r10] + punpcklwd m1, m2, m3 + mova m0, m10 + vpdpwssd m0, m1, m15 + punpckhwd m2, m3 + mova m1, m10 + vpdpwssd m1, m2, m15 + mova m4, [t1+r10] + paddw m3, m4, [t6+r10] + paddw m4, [t5+r10] + punpcklwd m2, m3, m4 + vpdpwssd m0, m2, m14 + punpckhwd m3, m4 + vpdpwssd m1, m3, m14 + psrad m0, 5 + psrad m1, 5 + packusdw m0, m1 + pmulhuw m0, m11 + mova [dstq+r10], m0 + add r10, 64 + jl .v_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq + ret + +cglobal wiener_filter5_16bpc, 4, 14, 15, 384*8+16, dst, stride, left, lpf, \ + w, h, edge, flt +%define base r13-r_ext_mask-70 + mov fltq, r6mp + movifnidn wd, wm + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + vbroadcasti128 m5, [wiener_shufE] + vpbroadcastw m11, [fltq+ 2] ; x1 + vbroadcasti128 m6, [wiener_shufB] + lea r13, [r_ext_mask+70] + vbroadcasti128 m7, [wiener_shufD] + add wd, wd + vpbroadcastd m12, [fltq+ 4] ; x2 x3 + shr t3d, 11 + vpbroadcastd m8, [pd_m262128] ; (1 << 4) - (1 << 18) + add lpfq, wq + vpbroadcastw m13, [fltq+18] ; y1 + add dstq, wq + vpbroadcastd m14, [fltq+20] ; y2 y3 + lea t1, [rsp+wq+16] + vpbroadcastd m0, [base+wiener_hshift+t3*4] + neg wq + vpbroadcastd m9, [base+wiener_round+t3*4] + mov r10d, 0xfffe + vpbroadcastd m10, [base+wiener_vshift+t3*4] + kmovw k1, r10d + pmullw m11, m0 + pmullw m12, m0 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t4, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t3, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 +.main: + mov t0, t4 +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v2 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.end: + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v2 + add t0, 384*6 + call .hv + dec hd + jnz .main +.v2: + call .v + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq +.v1: + call .v + jmp .end +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm3, [leftq+4] + vmovdqu32 m3{k1}, [lpfq+r10-4] + add leftq, 8 + jmp .h_main +.h_extend_left: + vpbroadcastw xm3, [lpfq+r10] + vmovdqu32 m3{k1}, [lpfq+r10-4] + jmp .h_main +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+r10-4] +.h_main: + movu m4, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -66 + jl .h_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m3, m0, [r13+r10+0], 0xe4 ; c ? a : b + vpternlogd m4, m0, [r13+r10+8], 0xe4 +.h_have_right: + pshufb m1, m3, m5 + mova m0, m8 + vpdpwssd m0, m1, m11 + pshufb m2, m4, m5 + mova m1, m8 + vpdpwssd m1, m2, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + vpdpwssd m0, m2, m12 + pshufb m4, m7 + paddw m3, m4 + vpdpwssd m1, m3, m12 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+r10], m0 + add r10, 64 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm3, [leftq+4] + vmovdqu32 m3{k1}, [lpfq+r10-4] + add leftq, 8 + jmp .hv_main +.hv_extend_left: + vpbroadcastw xm3, [lpfq+r10] + vmovdqu32 m3{k1}, [lpfq+r10-4] + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+r10-4] +.hv_main: + movu m4, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -66 + jl .hv_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m3, m0, [r13+r10+0], 0xe4 + vpternlogd m4, m0, [r13+r10+8], 0xe4 +.hv_have_right: + pshufb m1, m3, m5 + mova m0, m8 + vpdpwssd m0, m1, m11 + pshufb m2, m4, m5 + mova m1, m8 + vpdpwssd m1, m2, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + vpdpwssd m0, m2, m12 + pshufb m4, m7 + paddw m4, m3 + vpdpwssd m1, m4, m12 + mova m2, [t3+r10] + paddw m2, [t1+r10] + mova m3, [t2+r10] + punpcklwd m4, m2, m3 + punpckhwd m2, m3 + mova m3, m9 + vpdpwssd m3, m2, m14 + mova m2, m9 + vpdpwssd m2, m4, m14 + mova m4, [t4+r10] + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t0+r10], m0 + punpcklwd m1, m0, m4 + vpdpwssd m2, m1, m13 + punpckhwd m0, m4 + vpdpwssd m3, m0, m13 + psrad m2, 5 + psrad m3, 5 + packusdw m2, m3 + pmulhuw m2, m10 + mova [dstq+r10], m2 + add r10, 64 + jl .hv_loop + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t4 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m0, [t1+r10] + paddw m2, m0, [t3+r10] + mova m1, [t2+r10] + mova m4, [t4+r10] + punpckhwd m3, m2, m1 + pmaddwd m3, m14 + punpcklwd m2, m1 + pmaddwd m2, m14 + punpckhwd m1, m0, m4 + pmaddwd m1, m13 + punpcklwd m0, m4 + pmaddwd m0, m13 + paddd m3, m9 + paddd m2, m9 + paddd m1, m3 + paddd m0, m2 + psrad m1, 5 + psrad m0, 5 + packusdw m0, m1 + pmulhuw m0, m10 + mova [dstq+r10], m0 + add r10, 64 + jl .v_loop + ret + +cglobal sgr_filter_5x5_16bpc, 4, 14, 22, 416*24+8, dst, stride, left, lpf, \ + w, h, edge, params +%define base r13-r_ext_mask-72 + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [r_ext_mask+72] + mov edged, r7m + movifnidn hd, hm + pxor m6, m6 + vpbroadcastw m7, [paramsq+8] ; w0 + add wd, wd + vpbroadcastd m8, [base+pd_8] + add lpfq, wq + vpbroadcastd m9, [base+pd_m25] + add dstq, wq + vpsubd m10, m6, [paramsq+0] {1to16} ; -s0 + lea t3, [rsp+wq*2+416*12+8] + vpbroadcastd m11, [base+pw_164_455] + lea t4, [rsp+wq+416*20+8] + vpbroadcastd m12, [base+pw_61448] ; (15 << 12) + (1 << 3) + lea t1, [rsp+wq+12] + vpbroadcastd m13, [base+pd_m34816] ; -((1 << 11) + (1 << 15)) + neg wq + vpbroadcastd m14, [base+pw_1023] + psllw m7, 4 + mova m18, [sgr_x_by_x+64*0] + mov r10d, 0xfffffff8 + mova m19, [sgr_x_by_x+64*1] + kmovd k1, r10d + mova m20, [sgr_x_by_x+64*2] + mov r10, 0x3333333333333333 + mova m21, [sgr_x_by_x+64*3] + kmovq k2, r10 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call .top_fixup + add t1, 416*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, strideq + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + test hd, hd + jz .odd_height + call .h + add lpfq, strideq + call .hv + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .h_top + add lpfq, strideq + call .hv_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + call .n0 + call .n1 +.odd_height_end: + call .v + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+416*6] + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + jmp .main +.no_top_height1: + call .v + call .prep_n + jmp .odd_height_end +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movq xm16, [leftq+2] + vmovdqu16 m16{k1}, [lpfq+wq-6] + add leftq, 8 + jmp .h_main +.h_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-6] + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m16, [lpfq+r10- 2] +.h_main: + movu m17, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -68 + jl .h_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 ; c ? a : b + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.h_have_right: + palignr m2, m17, m16, 2 + paddw m0, m16, m2 + palignr m3, m17, m16, 6 + paddw m0, m3 + punpcklwd m1, m2, m3 + pmaddwd m1, m1 + punpckhwd m2, m3 + pmaddwd m2, m2 + shufpd m17, m16, m17, 0x55 + paddw m0, m17 + punpcklwd m3, m16, m17 + vpdpwssd m1, m3, m3 + punpckhwd m3, m16, m17 + vpdpwssd m2, m3, m3 + shufps m16, m17, q2121 + paddw m0, m16 ; sum + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+r10+416*0] + paddd m1, [t1+r10+416*2] + paddd m2, [t1+r10+416*4] +.h_loop_end: + punpcklwd m17, m16, m6 + vpdpwssd m1, m17, m17 ; sumsq + punpckhwd m16, m6 + vpdpwssd m2, m16, m16 + mova [t1+r10+416*0], m0 + mova [t1+r10+416*2], m1 + mova [t1+r10+416*4], m2 + add r10, 64 + jl .h_loop + ret +.top_fixup: + lea r10, [wq-4] +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+r10+416*0] + mova m1, [t1+r10+416*2] + mova m2, [t1+r10+416*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m1 + mova [t2+r10+416*4], m2 + add r10, 64 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movq xm16, [leftq+2] + vmovdqu16 m16{k1}, [lpfq+wq-6] + add leftq, 8 + jmp .hv_main +.hv_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-6] + jmp .hv_main +.hv_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m16, [lpfq+r10- 2] +.hv_main: + movu m17, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -68 + jl .hv_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.hv_have_right: + palignr m3, m17, m16, 2 + paddw m0, m16, m3 + palignr m1, m17, m16, 6 + paddw m0, m1 + punpcklwd m2, m3, m1 + pmaddwd m2, m2 + punpckhwd m3, m1 + pmaddwd m3, m3 + shufpd m17, m16, m17, 0x55 + paddw m0, m17 + punpcklwd m1, m16, m17 + vpdpwssd m2, m1, m1 + punpckhwd m1, m16, m17 + vpdpwssd m3, m1, m1 + shufps m16, m17, q2121 + paddw m0, m16 ; h sum + punpcklwd m17, m16, m6 + vpdpwssd m2, m17, m17 ; h sumsq + punpckhwd m16, m6 + vpdpwssd m3, m16, m16 + paddw m1, m0, [t1+r10+416*0] + paddd m16, m2, [t1+r10+416*2] + paddd m17, m3, [t1+r10+416*4] + test hd, hd + jz .hv_last_row +.hv_main2: + paddw m1, [t2+r10+416*0] ; hv sum + paddd m16, [t2+r10+416*2] ; hv sumsq + paddd m17, [t2+r10+416*4] + mova [t0+r10+416*0], m0 + mova [t0+r10+416*2], m2 + mova [t0+r10+416*4], m3 + psrlw m3, m1, 1 + paddd m16, m8 + pavgw m3, m6 ; (b + 2) >> 2 + paddd m17, m8 + psrld m16, 4 ; (a + 8) >> 4 + psrld m17, 4 + pmulld m16, m9 ; -a * 25 + pmulld m17, m9 + punpcklwd m2, m3, m6 + vpdpwssd m16, m2, m2 ; -p + punpckhwd m3, m6 + vpdpwssd m17, m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmulld m16, m10 ; p * s + pmulld m17, m10 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + pmaxsw m17, m6 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + packssdw m16, m17 + psubd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + psubd m1, m13 + mova [t4+r10+4], m16 + psrld m16, m0, 12 ; b + psrld m17, m1, 12 + mova [t3+r10*2+ 8], xm16 + mova [t3+r10*2+ 24], xm17 + vextracti128 [t3+r10*2+ 40], ym16, 1 + vextracti128 [t3+r10*2+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+ 72], m16, 2 + vextracti32x4 [t3+r10*2+ 88], m17, 2 + vextracti32x4 [t3+r10*2+104], m16, 3 + vextracti32x4 [t3+r10*2+120], m17, 3 + add r10, 64 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+r10+416*0], m1 + paddw m1, m0 + mova [t1+r10+416*2], m16 + paddd m16, m2 + mova [t1+r10+416*4], m17 + paddd m17, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab + lea r10, [wq-4] +.v_loop: + mova m2, [t1+r10+416*2] + mova m3, [t1+r10+416*4] + mova m0, [t1+r10+416*0] + paddd m16, m2, [t2+r10+416*2] + paddd m17, m3, [t2+r10+416*4] + paddw m1, m0, [t2+r10+416*0] + paddd m2, m2 + paddd m3, m3 + paddd m16, m2 ; hv sumsq + paddd m17, m3 + paddd m16, m8 + paddd m17, m8 + psrld m16, 4 ; (a + 8) >> 4 + psrld m17, 4 + pmulld m16, m9 ; -a * 25 + pmulld m17, m9 + paddw m0, m0 + paddw m1, m0 ; hv sum + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + vpdpwssd m16, m2, m2 ; -p + punpckhwd m3, m6 + vpdpwssd m17, m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmulld m16, m10 ; p * s + pmulld m17, m10 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + pmaxsw m17, m6 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + packssdw m16, m17 + psubd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + psubd m1, m13 + mova [t4+r10+4], m16 + psrld m16, m0, 12 ; b + psrld m17, m1, 12 + mova [t3+r10*2+ 8], xm16 + mova [t3+r10*2+ 24], xm17 + vextracti128 [t3+r10*2+ 40], ym16, 1 + vextracti128 [t3+r10*2+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+ 72], m16, 2 + vextracti32x4 [t3+r10*2+ 88], m17, 2 + vextracti32x4 [t3+r10*2+104], m16, 3 + vextracti32x4 [t3+r10*2+120], m17, 3 + add r10, 64 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t4+r10*1+ 2] + movu m1, [t3+r10*2+ 4] + movu m2, [t3+r10*2+68] + paddw m3, m0, [t4+r10*1+ 0] + paddd m16, m1, [t3+r10*2+ 0] + paddd m17, m2, [t3+r10*2+64] + paddw m3, [t4+r10*1+ 4] + paddd m16, [t3+r10*2+ 8] + paddd m17, [t3+r10*2+72] + paddw m0, m3 + psllw m3, 2 + paddd m1, m16 + pslld m16, 2 + paddd m2, m17 + pslld m17, 2 + paddw m0, m3 ; a 565 + paddd m1, m16 ; b 565 + paddd m2, m17 + mova [t4+r10*1+416*2+ 0], m0 + mova [t3+r10*2+416*4+ 0], m1 + mova [t3+r10*2+416*4+64], m2 + add r10, 64 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m0, [t4+r10*1+ 2] + movu m1, [t3+r10*2+ 4] + movu m2, [t3+r10*2+68] + paddw m3, m0, [t4+r10*1+ 0] + paddd m16, m1, [t3+r10*2+ 0] + paddd m17, m2, [t3+r10*2+64] + paddw m3, [t4+r10*1+ 4] + paddd m16, [t3+r10*2+ 8] + paddd m17, [t3+r10*2+72] + paddw m0, m3 + psllw m3, 2 + paddd m1, m16 + pslld m16, 2 + paddd m2, m17 + pslld m17, 2 + paddw m0, m3 ; a 565 + paddd m1, m16 ; b 565 + paddd m2, m17 + paddw m3, m0, [t4+r10*1+416*2+ 0] + paddd m16, m1, [t3+r10*2+416*4+ 0] + paddd m17, m2, [t3+r10*2+416*4+64] + mova [t4+r10*1+416*2+ 0], m0 + mova [t3+r10*2+416*4+ 0], m1 + mova [t3+r10*2+416*4+64], m2 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vshufi32x4 m1, m16, m17, q2020 + vshufi32x4 m16, m17, q3131 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m16, m3 + psrad m1, 9 + psrad m16, 9 + packssdw m1, m16 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 64 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m0, [dstq+r10] + mova m3, [t4+r10*1+416*2+ 0] + mova m16, [t3+r10*2+416*4+ 0] + mova m17, [t3+r10*2+416*4+64] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vshufi32x4 m1, m16, m17, q2020 + vshufi32x4 m16, m17, q3131 + psubd m1, m2 ; b - a * src + (1 << 7) + psubd m16, m3 + psrad m1, 8 + psrad m16, 8 + packssdw m1, m16 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 64 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_3x3_16bpc, 4, 14, 22, 416*42+8, dst, stride, left, lpf, \ + w, h, edge, params + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [r_ext_mask+72] + mov edged, r7m + movifnidn hd, hm + pxor m6, m6 + vpbroadcastw m7, [paramsq+10] ; w1 + add wd, wd + vpbroadcastd m8, [base+pd_8] + add lpfq, wq + vpbroadcastd m9, [base+pd_m9] + add dstq, wq + vpsubd m10, m6, [paramsq+4] {1to16} ; -s1 + lea t3, [rsp+wq*2+416*12+8] + vpbroadcastd m11, [base+pw_164_455] + lea t4, [rsp+wq+416*32+8] + vpbroadcastd m12, [base+pw_61448] + lea t1, [rsp+wq+12] + vpbroadcastd m13, [base+pd_m34816] + neg wq + vpbroadcastd m14, [base+pw_1023] + psllw m7, 4 + mova m18, [sgr_x_by_x+64*0] + mov r10d, 0xfffffffc + mova m19, [sgr_x_by_x+64*1] + kmovd k1, r10d + mova m20, [sgr_x_by_x+64*2] + mov r10, 0x3333333333333333 + mova m21, [sgr_x_by_x+64*3] + kmovq k2, r10 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + add t1, 416*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea r10, [wq-4] + lea t2, [t1+416*6] +.top_fixup_loop: + mova m0, [t1+r10+416*0] + mova m1, [t1+r10+416*2] + mova m2, [t1+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m1 + mova [t2+r10+416*4], m2 + add r10, 64 + jl .top_fixup_loop + call .v0 + jmp .main +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm16, [leftq+4] + vmovdqu16 m16{k1}, [lpfq+wq-4] + add leftq, 8 + jmp .h_main +.h_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-4] + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m16, [lpfq+r10+ 0] +.h_main: + movu m17, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -66 + jl .h_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.h_have_right: + palignr m0, m17, m16, 2 + paddw m1, m16, m0 + punpcklwd m2, m16, m0 + pmaddwd m2, m2 + punpckhwd m3, m16, m0 + pmaddwd m3, m3 + palignr m17, m16, 4 + paddw m1, m17 ; sum + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; sumsq + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + mova [t1+r10+416*0], m1 + mova [t1+r10+416*2], m2 + mova [t1+r10+416*4], m3 + add r10, 64 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab (even rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movd xm16, [leftq+4] + vmovdqu16 m16{k1}, [lpfq+wq-4] + add leftq, 8 + jmp .hv0_main +.hv0_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-4] + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu m16, [lpfq+r10+ 0] +.hv0_main: + movu m17, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -66 + jl .hv0_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.hv0_have_right: + palignr m0, m17, m16, 2 + paddw m1, m16, m0 + punpcklwd m2, m16, m0 + pmaddwd m2, m2 + punpckhwd m3, m16, m0 + pmaddwd m3, m3 + palignr m17, m16, 4 + paddw m1, m17 ; sum + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; sumsq + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + paddw m0, m1, [t1+r10+416*0] + paddd m16, m2, [t1+r10+416*2] + paddd m17, m3, [t1+r10+416*4] + mova [t1+r10+416*0], m1 + mova [t1+r10+416*2], m2 + mova [t1+r10+416*4], m3 + paddw m1, m0, [t2+r10+416*0] + paddd m2, m16, [t2+r10+416*2] + paddd m3, m17, [t2+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m16 + mova [t2+r10+416*4], m17 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pmulld m2, m9 ; -((a + 8) >> 4) * 9 + pmulld m3, m9 + psrlw m17, m1, 1 + pavgw m17, m6 ; (b + 2) >> 2 + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; -p + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + punpcklwd m16, m6, m1 ; b + punpckhwd m17, m6, m1 + pminsd m2, m6 + pminsd m3, m6 + pmulld m2, m10 ; p * s + pmulld m3, m10 + pmaddwd m16, m11 ; b * 455 + pmaddwd m17, m11 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + paddusw m3, m12 + psraw m3, 4 ; min(z, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x + pandn m2, m13, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + psubd m16, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + psubd m17, m13 + mova [t4+r10*1+416*0+4], m2 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*0+ 8], xm16 + mova [t3+r10*2+416*0+ 24], xm17 + vextracti128 [t3+r10*2+416*0+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*0+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*0+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*0+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*0+104], m16, 3 + vextracti32x4 [t3+r10*2+416*0+120], m17, 3 + add r10, 64 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movd xm16, [leftq+4] + vmovdqu16 m16{k1}, [lpfq+wq-4] + add leftq, 8 + jmp .hv1_main +.hv1_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-4] + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu m16, [lpfq+r10+ 0] +.hv1_main: + movu m17, [lpfq+r10+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -66 + jl .hv1_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.hv1_have_right: + palignr m1, m17, m16, 2 + paddw m0, m16, m1 + punpcklwd m2, m16, m1 + pmaddwd m2, m2 + punpckhwd m3, m16, m1 + pmaddwd m3, m3 + palignr m17, m16, 4 + paddw m0, m17 ; h sum + punpcklwd m1, m17, m6 + vpdpwssd m2, m1, m1 ; h sumsq + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + paddw m1, m0, [t2+r10+416*0] + paddd m16, m2, [t2+r10+416*2] + paddd m17, m3, [t2+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m2 + mova [t2+r10+416*4], m3 + paddd m16, m8 + paddd m17, m8 + psrld m16, 4 ; (a + 8) >> 4 + psrld m17, 4 + pmulld m16, m9 ; -((a + 8) >> 4) * 9 + pmulld m17, m9 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + vpdpwssd m16, m2, m2 ; -p + punpckhwd m3, m6 + vpdpwssd m17, m3, m3 + punpcklwd m0, m6, m1 ; b + punpckhwd m1, m6, m1 + pminsd m16, m6 + pminsd m17, m6 + pmulld m16, m10 ; p * s + pmulld m17, m10 + pmaddwd m0, m11 ; b * 455 + pmaddwd m1, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + packssdw m16, m17 + psubd m0, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + psubd m1, m13 + mova [t4+r10*1+416*2+4], m16 + psrld m16, m0, 12 + psrld m17, m1, 12 + mova [t3+r10*2+416*4+ 8], xm16 + mova [t3+r10*2+416*4+ 24], xm17 + vextracti128 [t3+r10*2+416*4+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*4+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*4+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*4+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*4+104], m16, 3 + vextracti32x4 [t3+r10*2+416*4+120], m17, 3 + add r10, 64 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab (even rows) + lea r10, [wq-4] +.v0_loop: + mova m0, [t1+r10+416*0] + mova m16, [t1+r10+416*2] + mova m17, [t1+r10+416*4] + paddw m0, m0 + paddd m16, m16 + paddd m17, m17 + paddw m1, m0, [t2+r10+416*0] + paddd m2, m16, [t2+r10+416*2] + paddd m3, m17, [t2+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m16 + mova [t2+r10+416*4], m17 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pmulld m2, m9 ; -((a + 8) >> 4) * 9 + pmulld m3, m9 + psrlw m17, m1, 1 + pavgw m17, m6 ; (b + 2) >> 2 + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; -p + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + punpcklwd m16, m6, m1 ; b + punpckhwd m17, m6, m1 + pminsd m2, m6 + pminsd m3, m6 + pmulld m2, m10 ; p * s + pmulld m3, m10 + pmaddwd m16, m11 ; b * 455 + pmaddwd m17, m11 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + paddusw m3, m12 + psraw m3, 4 ; min(z, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x + pandn m2, m13, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + psubd m16, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + psubd m17, m13 + mova [t4+r10*1+416*0+4], m2 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*0+ 8], xm16 + mova [t3+r10*2+416*0+ 24], xm17 + vextracti128 [t3+r10*2+416*0+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*0+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*0+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*0+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*0+104], m16, 3 + vextracti32x4 [t3+r10*2+416*0+120], m17, 3 + add r10, 64 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-4] +.v1_loop: + mova m0, [t1+r10+416*0] + mova m16, [t1+r10+416*2] + mova m17, [t1+r10+416*4] + paddw m1, m0, [t2+r10+416*0] + paddd m2, m16, [t2+r10+416*2] + paddd m3, m17, [t2+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m16 + mova [t2+r10+416*4], m17 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pmulld m2, m9 ; -((a + 8) >> 4) * 9 + pmulld m3, m9 + psrlw m17, m1, 1 + pavgw m17, m6 ; (b + 2) >> 2 + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; -p + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + punpcklwd m16, m6, m1 ; b + punpckhwd m17, m6, m1 + pminsd m2, m6 + pminsd m3, m6 + pmulld m2, m10 ; p * s + pmulld m3, m10 + pmaddwd m16, m11 ; b * 455 + pmaddwd m17, m11 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + paddusw m3, m12 + psraw m3, 4 ; min(z, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x + pandn m2, m13, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + psubd m16, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + psubd m17, m13 + mova [t4+r10*1+416*2+4], m2 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*4+ 8], xm16 + mova [t3+r10*2+416*4+ 24], xm17 + vextracti128 [t3+r10*2+416*4+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*4+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*4+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*4+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*4+104], m16, 3 + vextracti32x4 [t3+r10*2+416*4+120], m17, 3 + add r10, 64 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + mova ym16, [t4+r10*1+416*0+0] + paddw ym16, [t4+r10*1+416*0+4] + paddw ym17, ym16, [t4+r10*1+416*0+2] + mova m0, [t3+r10*2+416*0+0] + paddd m0, [t3+r10*2+416*0+8] + paddd m1, m0, [t3+r10*2+416*0+4] + psllw ym17, 2 ; a[-1] 444 + pslld m1, 2 ; b[-1] 444 + psubw ym17, ym16 ; a[-1] 343 + psubd m1, m0 ; b[-1] 343 + vmovdqa32 [t4+r10*1+416* 4], ym17 + vmovdqa32 [t3+r10*2+416* 8], m1 + mova ym16, [t4+r10*1+416*2+0] + paddw ym16, [t4+r10*1+416*2+4] + paddw ym17, ym16, [t4+r10*1+416*2+2] + mova m0, [t3+r10*2+416*4+0] + paddd m0, [t3+r10*2+416*4+8] + paddd m1, m0, [t3+r10*2+416*4+4] + psllw ym17, 2 ; a[ 0] 444 + pslld m1, 2 ; b[ 0] 444 + vmovdqa32 [t4+r10*1+416* 6], ym17 + vmovdqa32 [t3+r10*2+416*12], m1 + psubw ym17, ym16 ; a[ 0] 343 + psubd m1, m0 ; b[ 0] 343 + vmovdqa32 [t4+r10*1+416* 8], ym17 + vmovdqa32 [t3+r10*2+416*16], m1 + add r10, 32 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + mova m3, [t4+r10*1+416*0+0] + paddw m3, [t4+r10*1+416*0+4] + paddw m1, m3, [t4+r10*1+416*0+2] + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+r10*1+416*4] + paddw m3, [t4+r10*1+416*6] + mova [t4+r10*1+416*4], m2 + mova [t4+r10*1+416*6], m1 + mova m16, [t3+r10*2+416*0+0] + paddd m16, [t3+r10*2+416*0+8] + paddd m1, m16, [t3+r10*2+416*0+4] + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m16 ; b[ 1] 343 + paddd m16, m2, [t3+r10*2+416* 8+ 0] + paddd m16, [t3+r10*2+416*12+ 0] + mova [t3+r10*2+416* 8+ 0], m2 + mova [t3+r10*2+416*12+ 0], m1 + mova m17, [t3+r10*2+416*0+64] + paddd m17, [t3+r10*2+416*0+72] + paddd m1, m17, [t3+r10*2+416*0+68] + pslld m1, 2 + psubd m2, m1, m17 + paddd m17, m2, [t3+r10*2+416* 8+64] + paddd m17, [t3+r10*2+416*12+64] + mova [t3+r10*2+416* 8+64], m2 + mova [t3+r10*2+416*12+64], m1 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vshufi32x4 m1, m16, m17, q2020 + vshufi32x4 m16, m17, q3131 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m16, m3 + psrad m1, 9 + psrad m16, 9 + packssdw m1, m16 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 64 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m3, [t4+r10*1+416*2+0] + paddw m3, [t4+r10*1+416*2+4] + paddw m1, m3, [t4+r10*1+416*2+2] + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+r10*1+416*6] + paddw m3, [t4+r10*1+416*8] + mova [t4+r10*1+416*6], m1 + mova [t4+r10*1+416*8], m2 + mova m16, [t3+r10*2+416*4+0] + paddd m16, [t3+r10*2+416*4+8] + paddd m1, m16, [t3+r10*2+416*4+4] + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m16 ; b[ 1] 343 + paddd m16, m2, [t3+r10*2+416*12+ 0] + paddd m16, [t3+r10*2+416*16+ 0] + mova [t3+r10*2+416*12+ 0], m1 + mova [t3+r10*2+416*16+ 0], m2 + mova m17, [t3+r10*2+416*4+64] + paddd m17, [t3+r10*2+416*4+72] + paddd m1, m17, [t3+r10*2+416*4+68] + pslld m1, 2 + psubd m2, m1, m17 + paddd m17, m2, [t3+r10*2+416*12+64] + paddd m17, [t3+r10*2+416*16+64] + mova [t3+r10*2+416*12+64], m1 + mova [t3+r10*2+416*16+64], m2 + mova m0, [dstq+r10] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + vshufi32x4 m1, m16, m17, q2020 + vshufi32x4 m16, m17, q3131 + psubd m1, m2 ; b - a * src + (1 << 8) + psubd m16, m3 + psrad m1, 9 + psrad m16, 9 + packssdw m1, m16 + pmulhrsw m1, m7 + paddw m0, m1 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+r10], m0 + add r10, 64 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_mix_16bpc, 4, 14, 23, 416*66+8, dst, stride, left, lpf, \ + w, h, edge, params + movifnidn wd, wm + mov paramsq, r6mp + lea r13, [r_ext_mask+72] + mov edged, r7m + movifnidn hd, hm + vpbroadcastd m7, [paramsq+8] ; w0 w1 + pxor m6, m6 + vpbroadcastd m8, [base+pd_8] + add wd, wd + vpbroadcastd m9, [base+pd_m9] + add lpfq, wq + vpbroadcastd m10, [base+pd_m25] + add dstq, wq + vpsubd m11, m6, [paramsq+0] {1to16} ; -s0 + lea t3, [rsp+wq*2+416*24+8] + vpsubd m12, m6, [paramsq+4] {1to16} ; -s1 + lea t4, [rsp+wq+416*52+8] + vpbroadcastd m13, [base+pw_164_455] + lea t1, [rsp+wq+12] + vpbroadcastd m14, [base+pw_61448] + neg wq + vpbroadcastd m15, [base+pd_m34816] + psllw m7, 2 + vpbroadcastd m22, [base+pd_2147483648] + mov r10d, 0xfffffff8 + mova m18, [sgr_x_by_x+64*0] + kmovd k1, r10d + mova m19, [sgr_x_by_x+64*1] + mov r10, 0x3333333333333333 + mova m20, [sgr_x_by_x+64*2] + kmovq k2, r10 + mova m21, [sgr_x_by_x+64*3] + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_avx512icl).top_fixup + add t1, 416*12 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea r10, [wq-4] + lea t2, [t1+416*12] +.top_fixup_loop: + mova m0, [t1+r10+416* 0] + mova m1, [t1+r10+416* 2] + mova m2, [t1+r10+416* 4] + paddw m0, m0 + mova m3, [t1+r10+416* 6] + paddd m1, m1 + mova m4, [t1+r10+416* 8] + paddd m2, m2 + mova m5, [t1+r10+416*10] + mova [t2+r10+416* 0], m0 + mova [t2+r10+416* 2], m1 + mova [t2+r10+416* 4], m2 + mova [t2+r10+416* 6], m3 + mova [t2+r10+416* 8], m4 + mova [t2+r10+416*10], m5 + add r10, 64 + jl .top_fixup_loop + call .v0 + jmp .main +.h: ; horizontal boxsum + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movq xm16, [leftq+2] + vmovdqu16 m16{k1}, [lpfq+wq-6] + add leftq, 8 + jmp .h_main +.h_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-6] + jmp .h_main +.h_top: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m16, [lpfq+r10- 2] +.h_main: + movu m17, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -68 + jl .h_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.h_have_right: + palignr m3, m17, m16, 2 + palignr m0, m17, m16, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m17, m16, 6 + paddw m1, m0 ; sum3 + punpcklwd m4, m0, m6 + vpdpwssd m2, m4, m4 ; sumsq3 + punpckhwd m0, m6 + vpdpwssd m3, m0, m0 + shufpd m4, m16, m17, 0x55 + punpcklwd m17, m4, m16 + paddw m0, m16, m4 + punpckhwd m4, m16 + mova [t1+r10+416* 6], m1 + mova [t1+r10+416* 8], m2 + mova [t1+r10+416*10], m3 + paddw m1, m0 ; sum5 + vpdpwssd m2, m17, m17 ; sumsq5 + vpdpwssd m3, m4, m4 + mova [t1+r10+416* 0], m1 + mova [t1+r10+416* 2], m2 + mova [t1+r10+416* 4], m3 + add r10, 64 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab3 (even rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movq xm16, [leftq+2] + vmovdqu16 m16{k1}, [lpfq+wq-6] + add leftq, 8 + jmp .hv0_main +.hv0_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-6] + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu m16, [lpfq+r10- 2] +.hv0_main: + movu m17, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -68 + jl .hv0_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.hv0_have_right: + palignr m3, m17, m16, 2 + palignr m0, m17, m16, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m17, m16, 6 + paddw m1, m0 ; h sum3 + punpcklwd m4, m0, m6 + vpdpwssd m2, m4, m4 ; h sumsq3 + punpckhwd m0, m6 + vpdpwssd m3, m0, m0 + shufpd m17, m16, m17, 0x55 + paddw m4, m1, [t1+r10+416* 6] + paddd m5, m2, [t1+r10+416* 8] + mova [t1+r10+416* 6], m1 + mova [t1+r10+416* 8], m2 + paddw m1, m16 + paddw m1, m17 ; h sum5 + punpcklwd m0, m17, m16 + vpdpwssd m2, m0, m0 ; h sumsq5 + paddd m0, m3, [t1+r10+416*10] + mova [t1+r10+416*10], m3 + punpckhwd m17, m16 + vpdpwssd m3, m17, m17 + mova [t3+r10*2+416*8+ 8], m1 ; we need a clean copy of the last row + mova [t3+r10*2+416*0+ 8], m2 ; in case height is odd + mova [t3+r10*2+416*0+72], m3 + paddw m1, [t1+r10+416* 0] + paddd m2, [t1+r10+416* 2] + paddd m3, [t1+r10+416* 4] + mova [t1+r10+416* 0], m1 + mova [t1+r10+416* 2], m2 + mova [t1+r10+416* 4], m3 + paddw m17, m4, [t2+r10+416* 6] + paddd m2, m5, [t2+r10+416* 8] + paddd m3, m0, [t2+r10+416*10] + mova [t2+r10+416* 6], m4 + mova [t2+r10+416* 8], m5 + mova [t2+r10+416*10], m0 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pmulld m2, m9 ; -((a3 + 8) >> 4) * 9 + pmulld m3, m9 + psrlw m5, m17, 1 + pavgw m5, m6 ; (b3 + 2) >> 2 + punpcklwd m4, m5, m6 + vpdpwssd m2, m4, m4 ; -p3 + punpckhwd m5, m6 + vpdpwssd m3, m5, m5 + punpcklwd m16, m6, m17 ; b3 + punpckhwd m17, m6, m17 + pminsd m2, m6 + pminsd m3, m6 + pmulld m2, m12 ; p3 * s1 + pmulld m3, m12 + pmaddwd m16, m13 ; b3 * 455 + pmaddwd m17, m13 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + paddusw m3, m14 + psraw m3, 4 ; min(z3, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x3 + pandn m2, m15, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + mova [t4+r10*1+416*2+4], m2 + psubd m16, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*4+ 8], xm16 + mova [t3+r10*2+416*4+ 24], xm17 + vextracti128 [t3+r10*2+416*4+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*4+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*4+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*4+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*4+104], m16, 3 + vextracti32x4 [t3+r10*2+416*4+120], m17, 3 + add r10, 64 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movq xm16, [leftq+2] + vmovdqu16 m16{k1}, [lpfq+wq-6] + add leftq, 8 + jmp .hv1_main +.hv1_extend_left: + vpbroadcastw xm16, [lpfq+wq] + vmovdqu16 m16{k1}, [lpfq+wq-6] + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-4] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu m16, [lpfq+r10- 2] +.hv1_main: + movu m17, [lpfq+r10+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -68 + jl .hv1_have_right + vpbroadcastw m0, [lpfq-2] + vpternlogd m16, m0, [r13+r10+ 0], 0xe4 + vpternlogd m17, m0, [r13+r10+16], 0xe4 +.hv1_have_right: + palignr m1, m17, m16, 2 + palignr m3, m17, m16, 4 + paddw m2, m1, m3 + punpcklwd m0, m1, m3 + pmaddwd m0, m0 + punpckhwd m1, m3 + pmaddwd m1, m1 + palignr m3, m17, m16, 6 + paddw m2, m3 ; h sum3 + punpcklwd m5, m3, m6 + vpdpwssd m0, m5, m5 ; h sumsq3 + punpckhwd m3, m6 + vpdpwssd m1, m3, m3 + shufpd m3, m16, m17, 0x55 + punpcklwd m5, m16, m3 + paddw m4, m16, m3 + punpckhwd m16, m3 + paddw m17, m2, [t2+r10+416* 6] + mova [t2+r10+416* 6], m2 + paddw m4, m2 ; h sum5 + paddd m2, m0, [t2+r10+416* 8] + paddd m3, m1, [t2+r10+416*10] + mova [t2+r10+416* 8], m0 + mova [t2+r10+416*10], m1 + vpdpwssd m0, m5, m5 ; h sumsq5 + vpdpwssd m1, m16, m16 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pmulld m2, m9 ; -((a3 + 8) >> 4) * 9 + pmulld m3, m9 + psrlw m16, m17, 1 + pavgw m16, m6 ; (b3 + 2) >> 2 + punpcklwd m5, m16, m6 + vpdpwssd m2, m5, m5 ; -p3 + punpckhwd m16, m6 + vpdpwssd m3, m16, m16 + punpcklwd m16, m6, m17 ; b3 + punpckhwd m17, m6, m17 + pminsd m2, m6 + pminsd m3, m6 + pmulld m2, m12 ; p3 * s1 + pmulld m3, m12 + pmaddwd m16, m13 ; b3 * 455 + pmaddwd m17, m13 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + paddusw m3, m14 + psraw m3, 4 ; min(z3, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x3 + pandn m2, m15, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + mova [t4+r10*1+416*4+4], m2 + psubd m16, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + paddw m5, m4, [t2+r10+416*0] + paddd m2, m0, [t2+r10+416*2] + paddd m3, m1, [t2+r10+416*4] + paddw m5, [t1+r10+416*0] + paddd m2, [t1+r10+416*2] + paddd m3, [t1+r10+416*4] + mova [t2+r10+416*0], m4 + mova [t2+r10+416*2], m0 + mova [t2+r10+416*4], m1 + mova [t3+r10*2+416*8+ 8], xm16 + mova [t3+r10*2+416*8+ 24], xm17 + vextracti128 [t3+r10*2+416*8+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*8+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*8+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*8+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*8+104], m16, 3 + vextracti32x4 [t3+r10*2+416*8+120], m17, 3 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + pmulld m2, m10 ; -((a5 + 8) >> 4) * 25 + pmulld m3, m10 + psrlw m17, m5, 1 + pavgw m17, m6 ; (b5 + 2) >> 2 + punpcklwd m16, m17, m6 + vpdpwssd m2, m16, m16 ; -p5 + punpckhwd m17, m6 + vpdpwssd m3, m17, m17 + punpcklwd m16, m5, m6 ; b5 + punpckhwd m17, m5, m6 + pmulld m2, m11 ; p5 * s0 + pmulld m3, m11 + pmaddwd m16, m13 ; b5 * 164 + pmaddwd m17, m13 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + pmaxsw m3, m6 + paddusw m3, m14 + psraw m3, 4 ; min(z5, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x5 + pandn m2, m15, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + mova [t4+r10*1+416*0+4], m2 + psubd m16, m15 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*0+ 8], xm16 + mova [t3+r10*2+416*0+ 24], xm17 + vextracti128 [t3+r10*2+416*0+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*0+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*0+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*0+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*0+104], m16, 3 + vextracti32x4 [t3+r10*2+416*0+120], m17, 3 + add r10, 64 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) + lea r10, [wq-4] +.v0_loop: + mova m16, [t1+r10+416* 6] + mova m2, [t1+r10+416* 8] + mova m3, [t1+r10+416*10] + paddw m16, m16 + paddd m2, m2 + paddd m3, m3 + paddw m17, m16, [t2+r10+416* 6] + paddd m4, m2, [t2+r10+416* 8] + paddd m5, m3, [t2+r10+416*10] + mova [t2+r10+416* 6], m16 + mova [t2+r10+416* 8], m2 + mova [t2+r10+416*10], m3 + paddd m4, m8 + paddd m5, m8 + psrld m4, 4 ; (a3 + 8) >> 4 + psrld m5, 4 + pmulld m4, m9 ; -((a3 + 8) >> 4) * 9 + pmulld m5, m9 + psrlw m3, m17, 1 + pavgw m3, m6 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m6 + vpdpwssd m4, m2, m2 ; -p3 + punpckhwd m3, m6 + vpdpwssd m5, m3, m3 + punpcklwd m16, m6, m17 ; b3 + punpckhwd m17, m6, m17 + pminsd m4, m6 + pminsd m5, m6 + pmulld m4, m12 ; p3 * s1 + pmulld m5, m12 + pmaddwd m16, m13 ; b3 * 455 + pmaddwd m17, m13 + vpalignr m5{k2}, m4, m4, 2 + mova m4, m20 + paddusw m5, m14 + psraw m5, 4 ; min(z3, 255) - 256 + vpermt2b m4, m5, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m5 + vpermi2b m5, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m5{k3}, m4 ; x3 + pandn m4, m15, m5 + psrld m5, 16 + pmulld m16, m4 + pmulld m17, m5 + packssdw m4, m5 + mova [t4+r10*1+416*2+4], m4 + psubd m16, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + mova m3, [t1+r10+416*0] + mova m4, [t1+r10+416*2] + mova m5, [t1+r10+416*4] + mova [t3+r10*2+416*8+ 8], m3 + mova [t3+r10*2+416*0+ 8], m4 + mova [t3+r10*2+416*0+72], m5 + paddw m3, m3 ; cc5 + paddd m4, m4 + paddd m5, m5 + mova [t1+r10+416*0], m3 + mova [t1+r10+416*2], m4 + mova [t1+r10+416*4], m5 + mova [t3+r10*2+416*4+ 8], xm16 + mova [t3+r10*2+416*4+ 24], xm17 + vextracti128 [t3+r10*2+416*4+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*4+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*4+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*4+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*4+104], m16, 3 + vextracti32x4 [t3+r10*2+416*4+120], m17, 3 + add r10, 64 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-4] +.v1_loop: + mova m16, [t1+r10+416* 6] + mova m2, [t1+r10+416* 8] + mova m3, [t1+r10+416*10] + paddw m17, m16, [t2+r10+416* 6] + paddd m4, m2, [t2+r10+416* 8] + paddd m5, m3, [t2+r10+416*10] + mova [t2+r10+416* 6], m16 + mova [t2+r10+416* 8], m2 + mova [t2+r10+416*10], m3 + paddd m4, m8 + paddd m5, m8 + psrld m4, 4 ; (a3 + 8) >> 4 + psrld m5, 4 + pmulld m4, m9 ; -((a3 + 8) >> 4) * 9 + pmulld m5, m9 + psrlw m3, m17, 1 + pavgw m3, m6 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m6 + vpdpwssd m4, m2, m2 ; -p3 + punpckhwd m3, m6 + vpdpwssd m5, m3, m3 + punpcklwd m16, m6, m17 ; b3 + punpckhwd m17, m6, m17 + pminsd m4, m6 + pminsd m5, m6 + pmulld m4, m12 ; p3 * s1 + pmulld m5, m12 + pmaddwd m16, m13 ; b3 * 455 + pmaddwd m17, m13 + vpalignr m5{k2}, m4, m4, 2 + mova m4, m20 + paddusw m5, m14 + psraw m5, 4 ; min(z3, 255) - 256 + vpermt2b m4, m5, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m5 + vpermi2b m5, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m5{k3}, m4 ; x3 + pandn m4, m15, m5 + psrld m5, 16 + pmulld m16, m4 + pmulld m17, m5 + packssdw m4, m5 + mova [t4+r10*1+416*4+4], m4 + psubd m16, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + mova m0, [t3+r10*2+416*8+ 8] + mova m4, [t3+r10*2+416*0+ 8] + mova m5, [t3+r10*2+416*0+72] + paddw m1, m0, [t2+r10+416*0] + paddd m2, m4, [t2+r10+416*2] + paddd m3, m5, [t2+r10+416*4] + paddw m1, [t1+r10+416*0] + paddd m2, [t1+r10+416*2] + paddd m3, [t1+r10+416*4] + mova [t2+r10+416*0], m0 + mova [t2+r10+416*2], m4 + mova [t2+r10+416*4], m5 + mova [t3+r10*2+416*8+ 8], xm16 + mova [t3+r10*2+416*8+ 24], xm17 + vextracti128 [t3+r10*2+416*8+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*8+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*8+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*8+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*8+104], m16, 3 + vextracti32x4 [t3+r10*2+416*8+120], m17, 3 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + pmulld m2, m10 ; -((a5 + 8) >> 4) * 25 + pmulld m3, m10 + psrlw m5, m1, 1 + pavgw m5, m6 ; (b5 + 2) >> 2 + punpcklwd m4, m5, m6 + vpdpwssd m2, m4, m4 ; -p5 + punpckhwd m5, m6 + vpdpwssd m3, m5, m5 + punpcklwd m16, m1, m6 ; b5 + punpckhwd m17, m1, m6 + pmulld m2, m11 ; p5 * s0 + pmulld m3, m11 + pmaddwd m16, m13 ; b5 * 164 + pmaddwd m17, m13 + vpalignr m3{k2}, m2, m2, 2 + mova m2, m20 + pmaxsw m3, m6 + paddusw m3, m14 + psraw m3, 4 ; min(z5, 255) - 256 + vpermt2b m2, m3, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m3 + vpermi2b m3, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m3{k3}, m2 ; x5 + pandn m2, m15, m3 + psrld m3, 16 + pmulld m16, m2 + pmulld m17, m3 + packssdw m2, m3 + mova [t4+r10*1+416*0+4], m2 + psubd m16, m15 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + psubd m17, m15 + psrld m16, 12 + psrld m17, 12 + mova [t3+r10*2+416*0+ 8], xm16 + mova [t3+r10*2+416*0+ 24], xm17 + vextracti128 [t3+r10*2+416*0+ 40], ym16, 1 + vextracti128 [t3+r10*2+416*0+ 56], ym17, 1 + vextracti32x4 [t3+r10*2+416*0+ 72], m16, 2 + vextracti32x4 [t3+r10*2+416*0+ 88], m17, 2 + vextracti32x4 [t3+r10*2+416*0+104], m16, 3 + vextracti32x4 [t3+r10*2+416*0+120], m17, 3 + add r10, 64 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu ym0, [t4+r10*1+416*0+2] + paddw ym2, ym0, [t4+r10*1+416*0+0] + paddw ym2, [t4+r10*1+416*0+4] + movu m1, [t3+r10*2+416*0+4] + paddd m3, m1, [t3+r10*2+416*0+0] + paddd m3, [t3+r10*2+416*0+8] + paddw ym0, ym2 + paddd m1, m3 + psllw ym2, 2 + pslld m3, 2 + paddw ym0, ym2 ; a5 565 + paddd m1, m3 ; b5 565 + mova [t4+r10*1+416* 6], ym0 + mova [t3+r10*2+416*12], m1 + mova ym0, [t4+r10*1+416*2+0] + paddw ym0, [t4+r10*1+416*2+4] + paddw ym2, ym0, [t4+r10*1+416*2+2] + mova m1, [t3+r10*2+416*4+0] + paddd m1, [t3+r10*2+416*4+8] + paddd m3, m1, [t3+r10*2+416*4+4] + psllw ym2, 2 ; a3[-1] 444 + pslld m3, 2 ; b3[-1] 444 + psubw ym2, ym0 ; a3[-1] 343 + psubd m3, m1 ; b3[-1] 343 + mova [t4+r10*1+416* 8], ym2 + mova [t3+r10*2+416*16], m3 + mova ym0, [t4+r10*1+416*4+0] + paddw ym0, [t4+r10*1+416*4+4] + paddw ym2, ym0, [t4+r10*1+416*4+2] + mova m1, [t3+r10*2+416*8+0] + paddd m1, [t3+r10*2+416*8+8] + paddd m3, m1, [t3+r10*2+416*8+4] + psllw ym2, 2 ; a3[ 0] 444 + pslld m3, 2 ; b3[ 0] 444 + mova [t4+r10*1+416*10], ym2 + mova [t3+r10*2+416*20], m3 + psubw ym2, ym0 ; a3[ 0] 343 + psubd m3, m1 ; b3[ 0] 343 + mova [t4+r10*1+416*12], ym2 + mova [t3+r10*2+416*24], m3 + add r10, 32 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu ym2, [t4+r10*1+2] + paddw ym0, ym2, [t4+r10*1+0] + paddw ym0, [t4+r10*1+4] + paddw ym2, ym0 + psllw ym0, 2 + paddw ym0, ym2 ; a5 + movu m1, [t3+r10*2+4] + paddd m4, m1, [t3+r10*2+0] + paddd m4, [t3+r10*2+8] + paddd m1, m4 + pslld m4, 2 + paddd m4, m1 ; b5 + paddw ym2, ym0, [t4+r10*1+416* 6] + mova [t4+r10*1+416* 6], ym0 + paddd m0, m4, [t3+r10*2+416*12] + mova [t3+r10*2+416*12], m4 + mova ym3, [t4+r10*1+416*2+0] + paddw ym3, [t4+r10*1+416*2+4] + paddw ym5, ym3, [t4+r10*1+416*2+2] + psllw ym5, 2 ; a3[ 1] 444 + psubw ym4, ym5, ym3 ; a3[ 1] 343 + paddw ym3, ym4, [t4+r10*1+416* 8] + paddw ym3, [t4+r10*1+416*10] + mova [t4+r10*1+416* 8], ym4 + mova [t4+r10*1+416*10], ym5 + mova m1, [t3+r10*2+416*4+0] + paddd m1, [t3+r10*2+416*4+8] + paddd m5, m1, [t3+r10*2+416*4+4] + pslld m5, 2 ; b3[ 1] 444 + psubd m4, m5, m1 ; b3[ 1] 343 + paddd m1, m4, [t3+r10*2+416*16] + paddd m1, [t3+r10*2+416*20] + mova [t3+r10*2+416*16], m4 + mova [t3+r10*2+416*20], m5 + pmovzxwd m4, [dstq+r10] + pmovzxwd m2, ym2 ; a5 + pmovzxwd m3, ym3 ; a3 + pmaddwd m2, m4 ; a5 * src + pmaddwd m3, m4 ; a3 * src + vpshldd m4, m22, 13 + psubd m0, m2 ; b5 - a5 * src + (1 << 8) + psubd m1, m3 ; b3 - a3 * src + (1 << 8) + psrld m0, 9 + pslld m1, 7 + vpblendmb m0{k2}, m1, m0 + vpdpwssd m4, m0, m7 + psrad m4, 7 + pmaxsd m4, m6 + vpmovusdw ym16, m4 ; clip + psrlw ym16, 6 + mova [dstq+r10], ym16 + add r10, 32 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova ym3, [t4+r10*1+416*4+0] + paddw ym3, [t4+r10*1+416*4+4] + paddw ym5, ym3, [t4+r10*1+416*4+2] + psllw ym5, 2 ; a3[ 1] 444 + psubw ym4, ym5, ym3 ; a3[ 1] 343 + paddw ym3, ym4, [t4+r10*1+416*12] + paddw ym3, [t4+r10*1+416*10] + mova [t4+r10*1+416*10], ym5 + mova [t4+r10*1+416*12], ym4 + mova m0, [t3+r10*2+416*8+0] + paddd m0, [t3+r10*2+416*8+8] + paddd m5, m0, [t3+r10*2+416*8+4] + pslld m5, 2 ; b3[ 1] 444 + psubd m4, m5, m0 ; b3[ 1] 343 + paddd m0, m4, [t3+r10*2+416*24] + paddd m0, [t3+r10*2+416*20] + mova [t3+r10*2+416*20], m5 + mova [t3+r10*2+416*24], m4 + pmovzxwd m4, [dstq+r10] + pmovzxwd m2, [t4+r10*1+416* 6] + pmovzxwd m3, ym3 + mova m1, [t3+r10*2+416*12] + pmaddwd m2, m4 ; a5 * src + pmaddwd m3, m4 ; a3 * src + vpshldd m4, m22, 13 + psubd m1, m2 ; b5 - a5 * src + (1 << 8) + psubd m0, m3 ; b3 - a3 * src + (1 << 8) + pslld m0, 7 + vpalignr m0{k2}, m1, m1, 1 + vpdpwssd m4, m0, m7 + psrad m4, 7 + pmaxsd m4, m6 + vpmovusdw ym16, m4 ; clip + psrlw ym16, 6 + mova [dstq+r10], ym16 + add r10, 32 + jl .n1_loop + add dstq, strideq + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3723 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA + +wiener_shufA: db 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11 +wiener_shufB: db 6, 7, 4, 5, 8, 9, 6, 7, 10, 11, 8, 9, 12, 13, 10, 11 +wiener_shufC: db 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15 +wiener_shufD: db 2, 3, -1, -1, 4, 5, -1, -1, 6, 7, -1, -1, 8, 9, -1, -1 +wiener_shufE: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +wiener_lshuf5: db 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +wiener_lshuf7: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 +sgr_lshuf3: db 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +sgr_lshuf5: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +pb_0to15: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + +pb_m14_m13: times 8 db -14,-13 +pb_m10_m9: times 8 db -10, -9 +pb_m6_m5: times 8 db -6, -5 +pb_m2_m1: times 8 db -2, -1 +pb_2_3: times 8 db 2, 3 +pb_6_7: times 8 db 6, 7 +pw_256: times 8 dw 256 +pw_1023: times 8 dw 1023 +pd_8: times 4 dd 8 +pd_4096: times 4 dd 4096 +pd_34816: times 4 dd 34816 +pd_m262128: times 4 dd -262128 +pd_0xffff: times 4 dd 0xffff +pd_0xf00800a4: times 4 dd 0xf00800a4 +pd_0xf00801c7: times 4 dd 0xf00801c7 +pd_0xfffffff0: times 4 dd 0xfffffff0 + +wiener_shifts: dw 4, 4, 2048, 2048, 1, 1, 8192, 8192 +wiener_round: dd 1049600, 1048832 + +cextern sgr_x_by_x + +SECTION .text + +%macro movif64 2 ; dst, src + %if ARCH_X86_64 + mov %1, %2 + %endif +%endmacro + +%macro movif32 2 ; dst, src + %if ARCH_X86_32 + mov %1, %2 + %endif +%endmacro + +INIT_XMM ssse3 +%if ARCH_X86_32 +DECLARE_REG_TMP 5, 6 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 13*16 + %else + %assign extra_stack 12*16 + %endif +cglobal wiener_filter7_16bpc, 4, 7, 8, -384*12-16-extra_stack, \ + dst, stride, left, lpf, w, flt + %if STACK_ALIGNMENT < 16 + %define lpfm dword [esp+calloff+16*12+ 0] + %define wm dword [esp+calloff+16*12+ 4] + %define hd dword [esp+calloff+16*12+ 8] + %define edgeb byte [esp+calloff+16*12+12] + %define edged dword [esp+calloff+16*12+12] + %else + %define hd dword r5m + %define edgeb byte r7m + %endif + %define PICmem dword [esp+calloff+4*0] + %define t0m dword [esp+calloff+4*1] ; wiener ring buffer pointers + %define t1m dword [esp+calloff+4*2] + %define t2m dword [esp+calloff+4*3] + %define t3m dword [esp+calloff+4*4] + %define t4m dword [esp+calloff+4*5] + %define t5m dword [esp+calloff+4*6] + %define t6m dword [esp+calloff+4*7] + %define t2 t2m + %define t3 t3m + %define t4 t4m + %define t5 t5m + %define t6 t6m + %define m8 [esp+calloff+16*2] + %define m9 [esp+calloff+16*3] + %define m10 [esp+calloff+16*4] + %define m11 [esp+calloff+16*5] + %define m12 [esp+calloff+16*6] + %define m13 [esp+calloff+16*7] + %define m14 [esp+calloff+16*8] + %define m15 [esp+calloff+16*9] + %define r10 r4 + %define base t0-wiener_shifts + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov wd, [rstk+stack_offset+20] + mov wm, wd + mov r5, [rstk+stack_offset+24] + mov hd, r5 + mov r5, [rstk+stack_offset+32] + mov edged, r5 ; edge + %endif +%else +DECLARE_REG_TMP 8, 7, 9, 11, 12, 13, 14 ; wiener ring buffer pointers +cglobal wiener_filter7_16bpc, 4, 15, 16, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt + %define base +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + movifnidn wd, wm +%endif +%if ARCH_X86_64 + mov fltq, r6mp + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + movq m13, [fltq] + movq m15, [fltq+16] +%else + %if STACK_ALIGNMENT < 16 + mov t0, [rstk+stack_offset+28] + mov t1, [rstk+stack_offset+36] ; pixel_max + movq m1, [t0] ; fx + movq m3, [t0+16] ; fy + LEA t0, wiener_shifts + %else + mov fltq, r6m + movq m1, [fltq] + movq m3, [fltq+16] + LEA t0, wiener_shifts + mov t1, r8m ; pixel_max + %endif + mov PICmem, t0 +%endif + mova m6, [base+wiener_shufA] + mova m7, [base+wiener_shufB] +%if ARCH_X86_64 + lea t4, [wiener_shifts] + add wd, wd + pshufd m12, m13, q0000 ; x0 x1 + pshufd m13, m13, q1111 ; x2 x3 + pshufd m14, m15, q0000 ; y0 y1 + pshufd m15, m15, q1111 ; y2 y3 + mova m8, [wiener_shufC] + mova m9, [wiener_shufD] + add lpfq, wq + lea t1, [rsp+wq+16] + add dstq, wq + neg wq + shr t3d, 11 + %define base t4-wiener_shifts + movd m10, [base+wiener_round+t3*4] + movq m11, [base+wiener_shifts+t3*8] + pshufd m10, m10, q0000 + pshufd m0, m11, q0000 + pshufd m11, m11, q1111 + pmullw m12, m0 ; upshift filter coefs to make the + pmullw m13, m0 ; horizontal downshift constant + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] + %define base + %define wiener_lshuf7_mem [wiener_lshuf7] + %define pd_m262128_mem [pd_m262128] +%else + add wd, wd + mova m4, [base+wiener_shufC] + mova m5, [base+wiener_shufD] + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + pshufd m2, m3, q0000 + pshufd m3, m3, q1111 + mova m8, m4 + mova m9, m5 + mova m14, m2 + mova m15, m3 + shr t1, 11 + add lpfq, wq + mova m3, [base+pd_m262128] + movd m4, [base+wiener_round+t1*4] + movq m5, [base+wiener_shifts+t1*8] + lea t1, [esp+extra_stack+wq+16] + add dstq, wq + neg wq + pshufd m4, m4, q0000 + pshufd m2, m5, q0000 + pshufd m5, m5, q1111 + mov wm, wq + pmullw m0, m2 + pmullw m1, m2 + mova m2, [base+wiener_lshuf7] + %define pd_m262128_mem [esp+calloff+16*10] + mova pd_m262128_mem, m3 + mova m10, m4 + mova m11, m5 + mova m12, m0 + mova m13, m1 + %define wiener_lshuf7_mem [esp+calloff+16*11] + mova wiener_lshuf7_mem, m2 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 384*2 + add r10, strideq + mov lpfm, r10 ; below + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, lpfm + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call .v + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call .v + movif32 wq, wm +.v2: + call .v + movif32 wq, wm + jmp .v1 +.extend_right: +%assign stack_offset stack_offset+8 +%assign calloff 8 + movif32 t0, PICmem + pxor m0, m0 + movd m1, wd + mova m2, [base+pb_0to15] + pshufb m1, m0 + mova m0, [base+pb_6_7] + psubb m0, m1 + pminub m0, m2 + pshufb m3, m0 + mova m0, [base+pb_m2_m1] + psubb m0, m1 + pminub m0, m2 + pshufb m4, m0 + mova m0, [base+pb_m10_m9] + psubb m0, m1 + pminub m0, m2 + pshufb m5, m0 + movif32 t0, t0m + ret +%assign stack_offset stack_offset-4 +%assign calloff 4 +.h: + movif64 wq, r4 + movif32 wq, wm + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movq m3, [leftq] + movhps m3, [lpfq+wq] + add leftq, 8 + jmp .h_main +.h_extend_left: + mova m3, [lpfq+wq] ; avoid accessing memory located + pshufb m3, wiener_lshuf7_mem ; before the start of the buffer + jmp .h_main +.h_top: + movif64 wq, r4 + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+wq-8] +.h_main: + mova m4, [lpfq+wq+0] + movu m5, [lpfq+wq+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -20 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m0, m3, m6 + pshufb m1, m4, m7 + paddw m0, m1 + pshufb m3, m8 + pmaddwd m0, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + pmaddwd m3, m13 + pshufb m2, m5, m7 + paddw m1, m2 + mova m2, pd_m262128_mem ; (1 << 4) - (1 << 18) + pshufb m4, m8 + pmaddwd m1, m12 + pshufb m5, m9 + paddw m4, m5 + pmaddwd m4, m13 + paddd m0, m2 + paddd m1, m2 + paddd m0, m3 + paddd m1, m4 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+wq], m0 + add wq, 16 + jl .h_loop + movif32 wq, wm + ret +ALIGN function_align +.hv: + add lpfq, strideq + movif64 wq, r4 + movif32 t0m, t0 + movif32 t1m, t1 + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movq m3, [leftq] + movhps m3, [lpfq+wq] + add leftq, 8 + jmp .hv_main +.hv_extend_left: + mova m3, [lpfq+wq] + pshufb m3, wiener_lshuf7_mem + jmp .hv_main +.hv_bottom: + movif64 wq, r4 + movif32 t0m, t0 + movif32 t1m, t1 + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+wq-8] +.hv_main: + mova m4, [lpfq+wq+0] + movu m5, [lpfq+wq+8] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp wd, -20 + jl .hv_have_right + call .extend_right +.hv_have_right: + movif32 t1, t4m + movif32 t0, t2m + pshufb m0, m3, m6 + pshufb m1, m4, m7 + paddw m0, m1 + pshufb m3, m8 + pmaddwd m0, m12 + pshufb m1, m4, m9 + paddw m3, m1 + pshufb m1, m4, m6 + pmaddwd m3, m13 + pshufb m2, m5, m7 + paddw m1, m2 + mova m2, pd_m262128_mem + pshufb m4, m8 + pmaddwd m1, m12 + pshufb m5, m9 + paddw m4, m5 + pmaddwd m4, m13 + paddd m0, m2 + paddd m1, m2 +%if ARCH_X86_64 + mova m2, [t4+wq] + paddw m2, [t2+wq] + mova m5, [t3+wq] +%else + mova m2, [t1+wq] + paddw m2, [t0+wq] + mov t1, t3m + mov t0, t5m + mova m5, [t1+wq] + mov t1, t1m +%endif + paddd m0, m3 + paddd m1, m4 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 +%if ARCH_X86_64 + mova m4, [t5+wq] + paddw m4, [t1+wq] + psraw m0, 1 + paddw m3, m0, [t6+wq] +%else + mova m4, [t0+wq] + paddw m4, [t1+wq] + mov t0, t0m + mov t1, t6m + psraw m0, 1 + paddw m3, m0, [t1+wq] +%endif + mova [t0+wq], m0 + punpcklwd m0, m2, m5 + pmaddwd m0, m15 + punpckhwd m2, m5 + pmaddwd m2, m15 + punpcklwd m1, m3, m4 + pmaddwd m1, m14 + punpckhwd m3, m4 + pmaddwd m3, m14 + paddd m0, m10 + paddd m2, m10 + paddd m0, m1 + paddd m2, m3 + psrad m0, 6 + psrad m2, 6 + packssdw m0, m2 + pmulhw m0, m11 + pxor m1, m1 + pmaxsw m0, m1 + mova [dstq+wq], m0 + add wq, 16 + jl .hv_loop +%if ARCH_X86_64 + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 +%else + mov r4, t5m + mov t1, t4m + mov t6m, r4 + mov t5m, t1 + mov r4, t3m + mov t1, t2m + mov t4m, r4 + mov t3m, t1 + mov r4, t1m + mov t1, t0 + mov t2m, r4 + mov t0, t6m + mov wq, wm +%endif + add dstq, strideq + ret +.v: + movif64 wq, r4 + movif32 t0m, t0 + movif32 t1m, t1 +.v_loop: +%if ARCH_X86_64 + mova m1, [t4+wq] + paddw m1, [t2+wq] + mova m2, [t3+wq] + mova m4, [t1+wq] + paddw m3, m4, [t6+wq] + paddw m4, [t5+wq] +%else + mov t0, t4m + mov t1, t2m + mova m1, [t0+wq] + paddw m1, [t1+wq] + mov t0, t3m + mov t1, t1m + mova m2, [t0+wq] + mova m4, [t1+wq] + mov t0, t6m + mov t1, t5m + paddw m3, m4, [t0+wq] + paddw m4, [t1+wq] +%endif + punpcklwd m0, m1, m2 + pmaddwd m0, m15 + punpckhwd m1, m2 + pmaddwd m1, m15 + punpcklwd m2, m3, m4 + pmaddwd m2, m14 + punpckhwd m3, m4 + pmaddwd m3, m14 + paddd m0, m10 + paddd m1, m10 + paddd m0, m2 + paddd m1, m3 + psrad m0, 6 + psrad m1, 6 + packssdw m0, m1 + pmulhw m0, m11 + pxor m1, m1 + pmaxsw m0, m1 + mova [dstq+wq], m0 + add wq, 16 + jl .v_loop +%if ARCH_X86_64 + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 +%else + mov t0, t5m + mov t1, t4m + mov r4, t3m + mov t6m, t0 + mov t5m, t1 + mov t4m, r4 + mov r4, t2m + mov t1, t1m + mov t0, t0m + mov t3m, r4 + mov t2m, t1 +%endif + add dstq, strideq + ret + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < 16 + %assign stack_size 12*16+384*8 + %else + %assign stack_size 11*16+384*8 + %endif +cglobal wiener_filter5_16bpc, 4, 7, 8, -stack_size, dst, stride, left, \ + lpf, w, flt + %if STACK_ALIGNMENT < 16 + %define lpfm dword [esp+calloff+4*6] + %define wm dword [esp+calloff+4*7] + %define hd dword [esp+calloff+16*10+0] + %define edgeb byte [esp+calloff+16*10+4] + %define edged dword [esp+calloff+16*10+4] + %else + %define hd dword r5m + %define edgeb byte r7m + %endif + %define PICmem dword [esp+calloff+4*0] + %define t0m dword [esp+calloff+4*1] ; wiener ring buffer pointers + %define t1m dword [esp+calloff+4*2] + %define t2m dword [esp+calloff+4*3] + %define t3m dword [esp+calloff+4*4] + %define t4m dword [esp+calloff+4*5] + %define t2 t2m + %define t3 t3m + %define t4 t4m + %define m8 [esp+calloff+16*2] + %define m9 [esp+calloff+16*3] + %define m10 [esp+calloff+16*4] + %define m11 [esp+calloff+16*5] + %define m12 [esp+calloff+16*6] + %define m13 [esp+calloff+16*7] + %define m14 [esp+calloff+16*8] + %define m15 [esp+calloff+16*9] + %define base t0-wiener_shifts + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov wd, [rstk+stack_offset+20] + mov wm, wd + mov r5, [rstk+stack_offset+24] + mov hd, r5 + mov r5, [rstk+stack_offset+32] + mov edged, r5 ; edge + %endif +%else +cglobal wiener_filter5_16bpc, 4, 14, 16, 384*8+16, dst, stride, left, lpf, \ + w, h, edge, flt + %define base +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + movifnidn wd, wm +%endif +%if ARCH_X86_64 + mov fltq, r6mp + movifnidn hd, hm + mov edged, r7m + mov t3d, r8m ; pixel_max + movq m12, [fltq] + movq m14, [fltq+16] +%else + %if STACK_ALIGNMENT < 16 + mov t0, [rstk+stack_offset+28] + mov t1, [rstk+stack_offset+36] ; pixel_max + movq m1, [t0] ; fx + movq m3, [t0+16] ; fy + LEA t0, wiener_shifts + %else + mov fltq, r6m + movq m1, [fltq] + movq m3, [fltq+16] + LEA t0, wiener_shifts + mov t1, r8m ; pixel_max + %endif + mov PICmem, t0 +%endif + mova m5, [base+wiener_shufE] + mova m6, [base+wiener_shufB] + mova m7, [base+wiener_shufD] +%if ARCH_X86_64 + lea t4, [wiener_shifts] + add wd, wd + punpcklwd m11, m12, m12 + pshufd m11, m11, q1111 ; x1 + pshufd m12, m12, q1111 ; x2 x3 + punpcklwd m13, m14, m14 + pshufd m13, m13, q1111 ; y1 + pshufd m14, m14, q1111 ; y2 y3 + shr t3d, 11 + mova m8, [pd_m262128] ; (1 << 4) - (1 << 18) + add lpfq, wq + lea t1, [rsp+wq+16] + add dstq, wq + neg wq + %define base t4-wiener_shifts + movd m9, [base+wiener_round+t3*4] + movq m10, [base+wiener_shifts+t3*8] + pshufd m9, m9, q0000 + pshufd m0, m10, q0000 + pshufd m10, m10, q1111 + mova m15, [wiener_lshuf5] + pmullw m11, m0 + pmullw m12, m0 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] + %define base +%else + add wd, wd + punpcklwd m0, m1, m1 + pshufd m0, m0, q1111 ; x1 + pshufd m1, m1, q1111 ; x2 x3 + punpcklwd m2, m3, m3 + pshufd m2, m2, q1111 ; y1 + pshufd m3, m3, q1111 ; y2 y3 + mova m4, [base+pd_m262128] ; (1 << 4) - (1 << 18) + mova m13, m2 + mova m14, m3 + mova m8, m4 + shr t1, 11 + add lpfq, wq + movd m2, [base+wiener_round+t1*4] + movq m3, [base+wiener_shifts+t1*8] + %if STACK_ALIGNMENT < 16 + lea t1, [esp+16*11+wq+16] + %else + lea t1, [esp+16*10+wq+16] + %endif + add dstq, wq + neg wq + pshufd m2, m2, q0000 + pshufd m4, m3, q0000 + pshufd m3, m3, q1111 + mov wm, wq + pmullw m0, m4 + pmullw m1, m4 + mova m4, [base+wiener_lshuf5] + mova m9, m2 + mova m10, m3 + mova m11, m0 + mova m12, m1 + mova m15, m4 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t4, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t3, t1 + add t1, 384*2 + add r10, strideq + mov lpfm, r10 ; below + call .h + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 +.main: + mov t0, t4 +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v2 + mov lpfq, lpfm + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.end: + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v2 + add t0, 384*6 + call .hv + dec hd + jnz .main +.v2: + call .v +%if ARCH_X86_64 + mov t4, t3 + mov t3, t2 + mov t2, t1 +%else + mov t0, t3m + mov r4, t2m + mov t1, t1m + mov t4m, t0 + mov t3m, r4 + mov t2m, t1 + mov wq, wm +%endif + add dstq, strideq +.v1: + call .v + jmp .end +.extend_right: +%assign stack_offset stack_offset+8 +%assign calloff 8 + movif32 t0, PICmem + pxor m1, m1 + movd m2, wd + mova m0, [base+pb_2_3] + pshufb m2, m1 + mova m1, [base+pb_m6_m5] + psubb m0, m2 + psubb m1, m2 + mova m2, [base+pb_0to15] + pminub m0, m2 + pminub m1, m2 + pshufb m3, m0 + pshufb m4, m1 + ret +%assign stack_offset stack_offset-4 +%assign calloff 4 +.h: + movif64 wq, r4 + movif32 wq, wm + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + mova m4, [lpfq+wq] + movd m3, [leftq+4] + pslldq m4, 4 + por m3, m4 + add leftq, 8 + jmp .h_main +.h_extend_left: + mova m3, [lpfq+wq] ; avoid accessing memory located + pshufb m3, m15 ; before the start of the buffer + jmp .h_main +.h_top: + movif64 wq, r4 + movif32 wq, wm + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m3, [lpfq+wq-4] +.h_main: + movu m4, [lpfq+wq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -18 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m0, m3, m5 + pmaddwd m0, m11 + pshufb m1, m4, m5 + pmaddwd m1, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + pmaddwd m2, m12 + pshufb m4, m7 + paddw m3, m4 + pmaddwd m3, m12 + paddd m0, m8 + paddd m1, m8 + paddd m0, m2 + paddd m1, m3 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + psraw m0, 1 + mova [t1+wq], m0 + add wq, 16 + jl .h_loop + movif32 wq, wm + ret +ALIGN function_align +.hv: + add lpfq, strideq + movif64 wq, r4 + movif32 t0m, t0 + movif32 t1m, t1 + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + mova m4, [lpfq+wq] + movd m3, [leftq+4] + pslldq m4, 4 + por m3, m4 + add leftq, 8 + jmp .hv_main +.hv_extend_left: + mova m3, [lpfq+wq] + pshufb m3, m15 + jmp .hv_main +.hv_bottom: + movif64 wq, r4 + movif32 t0m, t0 + movif32 t1m, t1 + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m3, [lpfq+wq-4] +.hv_main: + movu m4, [lpfq+wq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp wd, -18 + jl .hv_have_right + call .extend_right +.hv_have_right: + movif32 t1, t1m + movif32 t0, t3m + pshufb m0, m3, m5 + pmaddwd m0, m11 + pshufb m1, m4, m5 + pmaddwd m1, m11 + pshufb m2, m3, m6 + pshufb m3, m7 + paddw m2, m3 + pshufb m3, m4, m6 + pmaddwd m2, m12 + pshufb m4, m7 + paddw m3, m4 + pmaddwd m3, m12 + paddd m0, m8 + paddd m1, m8 + paddd m0, m2 +%if ARCH_X86_64 + mova m2, [t3+wq] + paddw m2, [t1+wq] + paddd m1, m3 + mova m4, [t2+wq] +%else + mova m2, [t0+wq] + mov t0, t2m + paddw m2, [t1+wq] + mov t1, t4m + paddd m1, m3 + mova m4, [t0+wq] + mov t0, t0m +%endif + punpckhwd m3, m2, m4 + pmaddwd m3, m14 + punpcklwd m2, m4 +%if ARCH_X86_64 + mova m4, [t4+wq] +%else + mova m4, [t1+wq] +%endif + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + pmaddwd m2, m14 + psraw m0, 1 + mova [t0+wq], m0 + punpckhwd m1, m0, m4 + pmaddwd m1, m13 + punpcklwd m0, m4 + pmaddwd m0, m13 + paddd m3, m9 + paddd m2, m9 + paddd m1, m3 + paddd m0, m2 + psrad m1, 6 + psrad m0, 6 + packssdw m0, m1 + pmulhw m0, m10 + pxor m1, m1 + pmaxsw m0, m1 + mova [dstq+wq], m0 + add wq, 16 + jl .hv_loop +%if ARCH_X86_64 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t4 +%else + mov r4, t3m + mov t1, t2m + mov t4m, r4 + mov t3m, t1 + mov r4, t1m + mov t1, t0 + mov t2m, r4 + mov t0, t4m + mov wq, wm +%endif + add dstq, strideq + ret +.v: + movif64 wq, r4 + movif32 t1m, t1 +.v_loop: +%if ARCH_X86_64 + mova m0, [t1+wq] + paddw m2, m0, [t3+wq] + mova m1, [t2+wq] + mova m4, [t4+wq] +%else + mov t0, t3m + mova m0, [t1+wq] + mov t1, t2m + paddw m2, m0, [t0+wq] + mov t0, t4m + mova m1, [t1+wq] + mova m4, [t0+wq] +%endif + punpckhwd m3, m2, m1 + pmaddwd m3, m14 + punpcklwd m2, m1 + pmaddwd m2, m14 + punpckhwd m1, m0, m4 + pmaddwd m1, m13 + punpcklwd m0, m4 + pmaddwd m0, m13 + paddd m3, m9 + paddd m2, m9 + paddd m1, m3 + paddd m0, m2 + psrad m1, 6 + psrad m0, 6 + packssdw m0, m1 + pmulhw m0, m10 + pxor m1, m1 + pmaxsw m0, m1 + mova [dstq+wq], m0 + add wq, 16 +%if ARCH_X86_64 + jl .v_loop +%else + jge .v_end + mov t1, t1m + jmp .v_loop +.v_end: +%endif + ret + +%macro GATHERDD 3 ; dst, src, tmp + movd %3d, %2 + %if ARCH_X86_64 + movd %1, [r13+%3] + pextrw %3d, %2, 2 + pinsrw %1, [r13+%3+2], 3 + pextrw %3d, %2, 4 + pinsrw %1, [r13+%3+2], 5 + pextrw %3d, %2, 6 + pinsrw %1, [r13+%3+2], 7 + %else + movd %1, [base+sgr_x_by_x-0xf03+%3] + pextrw %3, %2, 2 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 3 + pextrw %3, %2, 4 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 5 + pextrw %3, %2, 6 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 7 + %endif +%endmacro + +%macro GATHER_X_BY_X 5 ; dst, src0, src1, tmp32, tmp32_restore + %if ARCH_X86_64 + %define tmp r14 + %else + %define tmp %4 + %endif + GATHERDD %1, %2, tmp + GATHERDD %2, %3, tmp + movif32 %4, %5 + psrld %1, 24 + psrld %2, 24 + packssdw %1, %2 +%endmacro + +%macro MAXSD 3-4 0 ; dst, src, restore_tmp + pcmpgtd %3, %1, %2 + pand %1, %3 + pandn %3, %2 + por %1, %3 + %if %4 == 1 + pxor %3, %3 + %endif +%endmacro + +%macro MULLD 3 ; dst, src, tmp + pmulhuw %3, %1, %2 + pmullw %1, %2 + pslld %3, 16 + paddd %1, %3 +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 0, 1, 2, 3, 5 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 5*16 + %else + %assign extra_stack 3*16 + %endif +cglobal sgr_filter_5x5_16bpc, 1, 7, 8, -400*24-16-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*0+4*6] + %define stridemp dword [esp+calloff+16*0+4*7] + %define leftm dword [esp+calloff+16*3+4*0] + %define lpfm dword [esp+calloff+16*3+4*1] + %define w0m dword [esp+calloff+16*3+4*2] + %define hd dword [esp+calloff+16*3+4*3] + %define edgeb byte [esp+calloff+16*3+4*4] + %define edged dword [esp+calloff+16*3+4*4] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t0m dword [esp+calloff+4*2] + %define t2m dword [esp+calloff+4*3] + %define t3m dword [esp+calloff+4*4] + %define t4m dword [esp+calloff+4*5] + %define m8 [base+pd_8] + %define m9 [base+pd_0xfffffff0] + %define m10 [esp+calloff+16*2] + %define m11 [base+pd_0xf00800a4] + %define m12 [base+sgr_lshuf5] + %define m13 [base+pd_34816] + %define m14 [base+pw_1023] + %define r10 r4 + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +cglobal sgr_filter_5x5_16bpc, 4, 15, 15, -400*24-16, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + movifnidn wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + movifnidn hd, hm + add wd, wd + mov edged, r7m + movu m10, [paramsq] + mova m12, [sgr_lshuf5] + add lpfq, wq + mova m8, [pd_8] + lea t1, [rsp+wq+20] + mova m9, [pd_0xfffffff0] + add dstq, wq + lea t3, [rsp+wq*2+400*12+16] + mova m11, [pd_0xf00800a4] + lea t4, [rsp+wq+400*20+16] + pshufhw m7, m10, q0000 + pshufb m10, [pw_256] ; s0 + punpckhqdq m7, m7 ; w0 + neg wq + mova m13, [pd_34816] ; (1 << 11) + (1 << 15) + pxor m6, m6 + mova m14, [pw_1023] + psllw m7, 4 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + add wd, wd + movu m1, [r1] + add lpfm, wq + lea t1, [rsp+extra_stack+wq+20] + add dstq, wq + lea t3, [rsp+extra_stack+wq*2+400*12+16] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq+400*20+16] + mov t3m, t3 + pshufhw m7, m1, q0000 + mov t4m, t4 + pshufb m1, [base+pw_256] ; s0 + punpckhqdq m7, m7 ; w0 + psllw m7, 4 + neg wq + mova m10, m1 + pxor m6, m6 + mov w1m, wd + sub wd, 4 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + movif32 t2m, t1 + mov t2, t1 + call .top_fixup + add t1, 400*6 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t0m, t2 + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, stridemp + movif32 t4, t4m + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp +%if ARCH_X86_64 + test hb, hb +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + call .h + add lpfq, stridemp + call .hv + movif32 dstq, dstm + call .n0 + call .n1 + sub hd, 2 + movif32 t0, t0m + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .h_top + add lpfq, stridemp + call .hv_bottom +.end: + movif32 dstq, dstm + call .n0 + call .n1 +.end2: + RET +.height1: + movif32 t4, t4m + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + movif32 dstq, dstm + call .n0 + call .n1 +.odd_height_end: + call .v + movif32 dstq, dstm + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h + lea t2, [t1+400*6] + movif32 t2m, t2 + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + movif32 t0m, t0 + jmp .main +.no_top_height1: + movif32 t3, t3m + movif32 t4, t4m + call .v + call .prep_n + jmp .odd_height_end +.extend_right: + movd m0, wd + movd m1, [lpfq-2] + mova m2, [base+pw_256] + mova m3, [base+pb_m14_m13] + pshufb m0, m6 + pshufb m1, m2 + psubb m2, m0 + psubb m3, m0 + mova m0, [base+pb_0to15] + pcmpgtb m2, m0 + pcmpgtb m3, m0 + pand m4, m2 + pand m5, m3 + pandn m2, m1 + pandn m3, m1 + por m4, m2 + por m5, m3 + ret +%assign stack_offset stack_offset+4 +%assign calloff 4 +.h: ; horizontal boxsum +%if ARCH_X86_64 + lea wq, [r4-4] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 10 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, m12 + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-4] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m4, [lpfq+wq- 2] +.h_main: + movu m5, [lpfq+wq+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -20 + jl .h_have_right + call .extend_right +.h_have_right: + palignr m2, m5, m4, 2 + paddw m0, m4, m2 + palignr m3, m5, m4, 6 + paddw m0, m3 + punpcklwd m1, m2, m3 + pmaddwd m1, m1 + punpckhwd m2, m3 + pmaddwd m2, m2 + palignr m5, m4, 8 + paddw m0, m5 + punpcklwd m3, m4, m5 + pmaddwd m3, m3 + paddd m1, m3 + punpckhwd m3, m4, m5 + pmaddwd m3, m3 + shufps m4, m5, q2121 + paddw m0, m4 ; sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m2, m3 + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+wq+400*0] + paddd m1, [t1+wq+400*2] + paddd m2, [t1+wq+400*4] +.h_loop_end: + paddd m1, m5 ; sumsq + paddd m2, m4 + mova [t1+wq+400*0], m0 + mova [t1+wq+400*2], m1 + mova [t1+wq+400*4], m2 + add wq, 16 + jl .h_loop + ret +.top_fixup: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+wq+400*0] + mova m1, [t1+wq+400*2] + mova m2, [t1+wq+400*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m1 + mova [t2+wq+400*4], m2 + add wq, 16 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 10 + jmp .hv_main +.hv_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, m12 + jmp .hv_main +.hv_bottom: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv_loop_start +%endif +.hv_loop: + movif32 lpfq, hvsrcm +.hv_loop_start: + movu m4, [lpfq+wq- 2] +.hv_main: + movu m5, [lpfq+wq+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp wd, -20 + jl .hv_have_right + call .extend_right +.hv_have_right: + movif32 t3, hd + palignr m3, m5, m4, 2 + paddw m0, m4, m3 + palignr m1, m5, m4, 6 + paddw m0, m1 + punpcklwd m2, m3, m1 + pmaddwd m2, m2 + punpckhwd m3, m1 + pmaddwd m3, m3 + palignr m5, m4, 8 + paddw m0, m5 + punpcklwd m1, m4, m5 + pmaddwd m1, m1 + paddd m2, m1 + punpckhwd m1, m4, m5 + pmaddwd m1, m1 + shufps m4, m5, q2121 + paddw m0, m4 ; h sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m3, m1 + paddd m2, m5 ; h sumsq + paddd m3, m4 + paddw m1, m0, [t1+wq+400*0] + paddd m4, m2, [t1+wq+400*2] + paddd m5, m3, [t1+wq+400*4] +%if ARCH_X86_64 + test hd, hd +%else + test t3, t3 +%endif + jz .hv_last_row +.hv_main2: + paddw m1, [t2+wq+400*0] ; hv sum + paddd m4, [t2+wq+400*2] ; hv sumsq + paddd m5, [t2+wq+400*4] + mova [t0+wq+400*0], m0 + mova [t0+wq+400*2], m2 + mova [t0+wq+400*4], m3 + psrlw m3, m1, 1 + paddd m4, m8 + pavgw m3, m6 ; (b + 2) >> 2 + paddd m5, m8 + pand m4, m9 ; ((a + 8) >> 4) << 4 + pand m5, m9 + psrld m2, m4, 4 + psrld m0, m5, 4 + paddd m2, m4 + psrld m4, 1 + paddd m0, m5 + psrld m5, 1 + paddd m4, m2 ; a * 25 + paddd m5, m0 + punpcklwd m2, m3, m6 + punpckhwd m3, m6 + pmaddwd m2, m2 ; b * b + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m6 + MAXSD m5, m3, m6, 1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m10, m2 ; p * s + MULLD m5, m10, m2 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, t2, t2m + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m2 + MULLD m1, m5, m2 + paddd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m13 + mova [t4+wq+4], m3 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+wq*2+ 8], m0 + mova [t3+wq*2+24], m1 + add wq, 16 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + movif32 t2m, t2 + movif32 t0m, t0 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+wq+400*0], m1 + paddw m1, m0 + mova [t1+wq+400*2], m4 + paddd m4, m2 + mova [t1+wq+400*4], m5 + paddd m5, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.v_loop: + mova m0, [t1+wq+400*0] + mova m2, [t1+wq+400*2] + mova m3, [t1+wq+400*4] + paddw m1, m0, [t2+wq+400*0] + paddd m4, m2, [t2+wq+400*2] + paddd m5, m3, [t2+wq+400*4] + paddw m0, m0 + paddd m2, m2 + paddd m3, m3 + paddw m1, m0 ; hv sum + paddd m4, m2 ; hv sumsq + paddd m5, m3 + psrlw m3, m1, 1 + paddd m4, m8 + pavgw m3, m6 ; (b + 2) >> 2 + paddd m5, m8 + pand m4, m9 ; ((a + 8) >> 4) << 4 + pand m5, m9 + psrld m2, m4, 4 + psrld m0, m5, 4 + paddd m2, m4 + psrld m4, 1 + paddd m0, m5 + psrld m5, 1 + paddd m4, m2 ; a * 25 + paddd m5, m0 + punpcklwd m2, m3, m6 + punpckhwd m3, m6 + pmaddwd m2, m2 ; b * b + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m6 + MAXSD m5, m3, m6, 1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m10, m2 ; p * s + MULLD m5, m10, m2 + pmaddwd m0, m11 ; b * 164 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, t2, t2m + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m2 + MULLD m1, m5, m2 + paddd m0, m13 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m13 + mova [t4+wq+4], m3 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+wq*2+ 8], m0 + mova [t3+wq*2+24], m1 + add wq, 16 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*1+ 2] + movu m3, [t4+wq*1+ 4] + movu m1, [t3+wq*2+ 4] + movu m4, [t3+wq*2+ 8] + movu m2, [t3+wq*2+20] + movu m5, [t3+wq*2+24] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + paddw m3, [t4+wq*1+ 0] + paddd m4, [t3+wq*2+ 0] + paddd m5, [t3+wq*2+16] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + mova [t4+wq*1+400*2+ 0], m0 + mova [t3+wq*2+400*4+ 0], m1 + mova [t3+wq*2+400*4+16], m2 + add wq, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m0, [t4+wq*1+ 2] + movu m3, [t4+wq*1+ 4] + movu m1, [t3+wq*2+ 4] + movu m4, [t3+wq*2+ 8] + movu m2, [t3+wq*2+20] + movu m5, [t3+wq*2+24] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + paddw m3, [t4+wq*1+ 0] + paddd m4, [t3+wq*2+ 0] + paddd m5, [t3+wq*2+16] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + paddw m3, m0, [t4+wq*1+400*2+ 0] + paddd m4, m1, [t3+wq*2+400*4+ 0] + paddd m5, m2, [t3+wq*2+400*4+16] + mova [t4+wq*1+400*2+ 0], m0 + mova [t3+wq*2+400*4+ 0], m1 + mova [t3+wq*2+400*4+16], m2 + mova m0, [dstq+wq] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+wq], m0 + add wq, 16 + jl .n0_loop + add dstq, stridemp + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + mova m0, [dstq+wq] + mova m3, [t4+wq*1+400*2+ 0] + mova m4, [t3+wq*2+400*4+ 0] + mova m5, [t3+wq*2+400*4+16] + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 7) + psubd m5, m3 + psrad m4, 8 + psrad m5, 8 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + pmaxsw m0, m6 + pminsw m0, m14 + mova [dstq+wq], m0 + add wq, 16 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 4*16 + %else + %assign extra_stack 2*16 + %endif +cglobal sgr_filter_3x3_16bpc, 1, 7, 8, -400*42-16-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*2+4*0] + %define stridemp dword [esp+calloff+16*2+4*1] + %define leftm dword [esp+calloff+16*2+4*2] + %define lpfm dword [esp+calloff+16*2+4*3] + %define w0m dword [esp+calloff+16*2+4*4] + %define hd dword [esp+calloff+16*2+4*5] + %define edgeb byte [esp+calloff+16*2+4*6] + %define edged dword [esp+calloff+16*2+4*6] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t3m dword [esp+calloff+4*2] + %define t4m dword [esp+calloff+4*3] + %define m8 [base+pd_8] + %define m9 [esp+calloff+16*1] + %define m10 [base+pd_0xf00801c7] + %define m11 [base+pd_34816] + %define m12 [base+sgr_lshuf3] + %define m13 [base+pw_1023] + %define m14 m6 + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +cglobal sgr_filter_3x3_16bpc, 4, 15, 15, -400*42-8, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + movifnidn wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + movifnidn hd, hm + add wd, wd + mov edged, r7m + movq m9, [paramsq+4] + add lpfq, wq + lea t1, [rsp+wq+12] + mova m8, [pd_8] + add dstq, wq + lea t3, [rsp+wq*2+400*12+8] + mova m10, [pd_0xf00801c7] + lea t4, [rsp+wq+400*32+8] + mova m11, [pd_34816] + pshuflw m7, m9, q3333 + pshufb m9, [pw_256] ; s1 + punpcklqdq m7, m7 ; w1 + neg wq + pxor m6, m6 + mova m13, [pw_1023] + psllw m7, 4 + mova m12, [sgr_lshuf3] + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + add wd, wd + movq m1, [r1+4] + add lpfm, wq + lea t1, [rsp+extra_stack+wq+20] + add dstq, wq + lea t3, [rsp+extra_stack+wq*2+400*12+16] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq+400*32+16] + mov t3m, t3 + pshuflw m7, m1, q3333 + mov t4m, t4 + pshufb m1, [base+pw_256] ; s1 + punpcklqdq m7, m7 ; w1 + psllw m7, 4 + neg wq + mova m9, m1 + pxor m6, m6 + mov w1m, wd + sub wd, 4 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + mov t2, t1 + add t1, 400*6 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t4, t4m + call .hv0 +.main: + dec hd + jz .height1 + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv0 +%if ARCH_X86_64 + test hb, hb +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .hv0_bottom + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wq, w0m + mov hvsrcm, lpfq +%endif + lea t2, [t1+400*6] +.top_fixup_loop: + mova m0, [t1+wq+400*0] + mova m1, [t1+wq+400*2] + mova m2, [t1+wq+400*4] + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m1 + mova [t2+wq+400*4], m2 + add wq, 16 + jl .top_fixup_loop + movif32 t3, t3m + movif32 t4, t4m + call .v0 + jmp .main +.extend_right: + movd m1, wd + movd m5, [lpfq-2] + mova m2, [base+pw_256] + mova m3, [base+pb_0to15] + pshufb m1, m6 + pshufb m5, m2 + psubb m2, m1 + pcmpgtb m2, m3 + pand m4, m2 + pandn m2, m5 + por m4, m2 + ret +%assign stack_offset stack_offset+4 +%assign calloff 4 +.h: ; horizontal boxsum +%if ARCH_X86_64 + lea wq, [r4-4] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 12 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, m12 + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-4] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m4, [lpfq+wq+ 0] +.h_main: + movu m5, [lpfq+wq+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -18 + jl .h_have_right + call .extend_right +.h_have_right: + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + mova [t1+wq+400*0], m1 + mova [t1+wq+400*2], m2 + mova [t1+wq+400*4], m3 + add wq, 16 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab (even rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 12 + jmp .hv0_main +.hv0_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, m12 + jmp .hv0_main +.hv0_bottom: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv0_loop_start +%endif +.hv0_loop: + movif32 lpfq, hvsrcm +.hv0_loop_start: + movu m4, [lpfq+wq+ 0] +.hv0_main: + movu m5, [lpfq+wq+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp wd, -18 + jl .hv0_have_right + call .extend_right +.hv0_have_right: + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + paddw m0, m1, [t1+wq+400*0] + paddd m4, m2, [t1+wq+400*2] + paddd m5, m3, [t1+wq+400*4] + mova [t1+wq+400*0], m1 + mova [t1+wq+400*2], m2 + mova [t1+wq+400*4], m3 + paddw m1, m0, [t2+wq+400*0] + paddd m2, m4, [t2+wq+400*2] + paddd m3, m5, [t2+wq+400*4] + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m4 + mova [t2+wq+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m14 + MAXSD m5, m3, m14 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m14 ; p * s + MULLD m5, m9, m14 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m14 + MULLD m1, m5, m14 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq+4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+ 8], m0 + mova [t3+wq*2+24], m1 + add wq, 16 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 12 + jmp .hv1_main +.hv1_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, m12 + jmp .hv1_main +.hv1_bottom: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv1_loop_start +%endif +.hv1_loop: + movif32 lpfq, hvsrcm +.hv1_loop_start: + movu m4, [lpfq+wq+ 0] +.hv1_main: + movu m5, [lpfq+wq+16] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp wd, -18 + jl .hv1_have_right + call .extend_right +.hv1_have_right: + palignr m1, m5, m4, 2 + paddw m0, m4, m1 + punpcklwd m2, m4, m1 + pmaddwd m2, m2 + punpckhwd m3, m4, m1 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m0, m5 ; h sum + punpcklwd m1, m5, m6 + pmaddwd m1, m1 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m1 ; h sumsq + paddd m3, m5 + paddw m1, m0, [t2+wq+400*0] + paddd m4, m2, [t2+wq+400*2] + paddd m5, m3, [t2+wq+400*4] + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m2 + mova [t2+wq+400*4], m3 + paddd m4, m8 + paddd m5, m8 + psrld m4, 4 ; (a + 8) >> 4 + psrld m5, 4 + pslld m2, m4, 3 + pslld m3, m5, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m14 + MAXSD m5, m3, m14 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m14 ; p * s + MULLD m5, m9, m14 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m14 + MULLD m1, m5, m14 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*1+400*2 +4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+400*4+ 8], m0 + mova [t3+wq*2+400*4+24], m1 + add wq, 16 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab (even rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.v0_loop: + mova m0, [t1+wq+400*0] + mova m4, [t1+wq+400*2] + mova m5, [t1+wq+400*4] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+wq+400*0] + paddd m2, m4, [t2+wq+400*2] + paddd m3, m5, [t2+wq+400*4] + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m4 + mova [t2+wq+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m14 + MAXSD m5, m3, m14 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m14 ; p * s + MULLD m5, m9, m14 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m14 + MULLD m1, m5, m14 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*1+400*0+ 4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+400*0+ 8], m0 + mova [t3+wq*2+400*0+24], m1 + add wq, 16 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.v1_loop: + mova m0, [t1+wq+400*0] + mova m4, [t1+wq+400*2] + mova m5, [t1+wq+400*4] + paddw m1, m0, [t2+wq+400*0] + paddd m2, m4, [t2+wq+400*2] + paddd m3, m5, [t2+wq+400*4] + mova [t2+wq+400*0], m0 + mova [t2+wq+400*2], m4 + mova [t2+wq+400*4], m5 + paddd m2, m8 + paddd m3, m8 + psrld m2, 4 ; (a + 8) >> 4 + psrld m3, 4 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m6 ; (b + 2) >> 2 + punpcklwd m2, m3, m6 + pmaddwd m2, m2 + punpckhwd m3, m6 + pmaddwd m3, m3 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + MAXSD m4, m2, m14 + MAXSD m5, m3, m14 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m14 ; p * s + MULLD m5, m9, m14 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m14 + MULLD m1, m5, m14 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*1+400*2+ 4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+400*4+ 8], m0 + mova [t3+wq*2+400*4+24], m1 + add wq, 16 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*1+400*0+ 4] + movu m1, [t3+wq*2+400*0+ 8] + movu m2, [t3+wq*2+400*0+24] + movu m3, [t4+wq*1+400*0+ 2] + movu m4, [t3+wq*2+400*0+ 4] + movu m5, [t3+wq*2+400*0+20] + paddw m0, [t4+wq*1+400*0+ 0] + paddd m1, [t3+wq*2+400*0+ 0] + paddd m2, [t3+wq*2+400*0+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a[-1] 444 + pslld m4, 2 ; b[-1] 444 + pslld m5, 2 + psubw m3, m0 ; a[-1] 343 + psubd m4, m1 ; b[-1] 343 + psubd m5, m2 + mova [t4+wq*1+400*4], m3 + mova [t3+wq*2+400*8+ 0], m4 + mova [t3+wq*2+400*8+16], m5 + movu m0, [t4+wq*1+400*2+ 4] + movu m1, [t3+wq*2+400*4+ 8] + movu m2, [t3+wq*2+400*4+24] + movu m3, [t4+wq*1+400*2+ 2] + movu m4, [t3+wq*2+400*4+ 4] + movu m5, [t3+wq*2+400*4+20] + paddw m0, [t4+wq*1+400*2+ 0] + paddd m1, [t3+wq*2+400*4+ 0] + paddd m2, [t3+wq*2+400*4+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a[ 0] 444 + pslld m4, 2 ; b[ 0] 444 + pslld m5, 2 + mova [t4+wq*1+400* 6], m3 + mova [t3+wq*2+400*12+ 0], m4 + mova [t3+wq*2+400*12+16], m5 + psubw m3, m0 ; a[ 0] 343 + psubd m4, m1 ; b[ 0] 343 + psubd m5, m2 + mova [t4+wq*1+400* 8], m3 + mova [t3+wq*2+400*16+ 0], m4 + mova [t3+wq*2+400*16+16], m5 + add wq, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m3, [t4+wq*1+400*0+4] + movu m1, [t4+wq*1+400*0+2] + paddw m3, [t4+wq*1+400*0+0] + paddw m1, m3 + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+wq*1+400*4] + paddw m3, [t4+wq*1+400*6] + mova [t4+wq*1+400*4], m2 + mova [t4+wq*1+400*6], m1 + movu m4, [t3+wq*2+400*0+8] + movu m1, [t3+wq*2+400*0+4] + paddd m4, [t3+wq*2+400*0+0] + paddd m1, m4 + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+wq*2+400* 8+ 0] + paddd m4, [t3+wq*2+400*12+ 0] + mova [t3+wq*2+400* 8+ 0], m2 + mova [t3+wq*2+400*12+ 0], m1 + movu m5, [t3+wq*2+400*0+24] + movu m1, [t3+wq*2+400*0+20] + paddd m5, [t3+wq*2+400*0+16] + paddd m1, m5 + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+wq*2+400* 8+16] + paddd m5, [t3+wq*2+400*12+16] + mova [t3+wq*2+400* 8+16], m2 + mova [t3+wq*2+400*12+16], m1 + mova m0, [dstq+wq] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + pmaxsw m0, m6 + pminsw m0, m13 + mova [dstq+wq], m0 + add wq, 16 + jl .n0_loop + add dstq, stridemp + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + movu m3, [t4+wq*1+400*2+4] + movu m1, [t4+wq*1+400*2+2] + paddw m3, [t4+wq*1+400*2+0] + paddw m1, m3 + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+wq*1+400*6] + paddw m3, [t4+wq*1+400*8] + mova [t4+wq*1+400*6], m1 + mova [t4+wq*1+400*8], m2 + movu m4, [t3+wq*2+400*4+8] + movu m1, [t3+wq*2+400*4+4] + paddd m4, [t3+wq*2+400*4+0] + paddd m1, m4 + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+wq*2+400*12+ 0] + paddd m4, [t3+wq*2+400*16+ 0] + mova [t3+wq*2+400*12+ 0], m1 + mova [t3+wq*2+400*16+ 0], m2 + movu m5, [t3+wq*2+400*4+24] + movu m1, [t3+wq*2+400*4+20] + paddd m5, [t3+wq*2+400*4+16] + paddd m1, m5 + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+wq*2+400*12+16] + paddd m5, [t3+wq*2+400*16+16] + mova [t3+wq*2+400*12+16], m1 + mova [t3+wq*2+400*16+16], m2 + mova m0, [dstq+wq] + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + pmaxsw m0, m6 + pminsw m0, m13 + mova [dstq+wq], m0 + add wq, 16 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 10*16 + %else + %assign extra_stack 8*16 + %endif +cglobal sgr_filter_mix_16bpc, 1, 7, 8, -400*66-48-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*8+4*0] + %define stridemp dword [esp+calloff+16*8+4*1] + %define leftm dword [esp+calloff+16*8+4*2] + %define lpfm dword [esp+calloff+16*8+4*3] + %define w0m dword [esp+calloff+16*8+4*4] + %define hd dword [esp+calloff+16*8+4*5] + %define edgeb byte [esp+calloff+16*8+4*6] + %define edged dword [esp+calloff+16*8+4*6] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t3m dword [esp+calloff+4*2] + %define t4m dword [esp+calloff+4*3] + %xdefine m8 m6 + %define m9 [base+pd_8] + %define m10 [base+pd_34816] + %define m11 [base+pd_0xf00801c7] + %define m12 [base+pd_0xf00800a4] + %define m13 [esp+calloff+16*4] + %define m14 [esp+calloff+16*5] + %define m15 [esp+calloff+16*6] + %define m6 [esp+calloff+16*7] + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +cglobal sgr_filter_mix_16bpc, 4, 15, 16, -400*66-40, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + movifnidn wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + movifnidn hd, hm + add wd, wd + mov edged, r7m + mova m14, [paramsq] + add lpfq, wq + mova m9, [pd_8] + lea t1, [rsp+wq+44] + mova m10, [pd_34816] + add dstq, wq + mova m11, [pd_0xf00801c7] + lea t3, [rsp+wq*2+400*24+40] + mova m12, [pd_0xf00800a4] + lea t4, [rsp+wq+400*52+40] + neg wq + pshufd m15, m14, q2222 ; w0 w1 + punpcklwd m14, m14 + pshufd m13, m14, q0000 ; s0 + pshufd m14, m14, q2222 ; s1 + pxor m6, m6 + psllw m15, 2 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + add wd, wd + mova m2, [r1] + add lpfm, wq + lea t1, [rsp+extra_stack+wq+52] + add dstq, wq + lea t3, [rsp+extra_stack+wq*2+400*24+48] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq+400*52+48] + mov t3m, t3 + mov t4m, t4 + neg wq + pshuflw m0, m2, q0000 + pshuflw m1, m2, q2222 + pshufhw m2, m2, q1010 + punpcklqdq m0, m0 ; s0 + punpcklqdq m1, m1 ; s1 + punpckhqdq m2, m2 ; w0 w1 + mov w1m, wd + pxor m3, m3 + psllw m2, 2 + mova m13, m0 + mova m14, m1 + sub wd, 4 + mova m15, m2 + mova m6, m3 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + mov t2, t1 +%if ARCH_X86_64 + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_ssse3).top_fixup +%else + mov wq, w0m + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_ssse3).top_fixup_loop +%endif + add t1, 400*12 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t4, t4m + call .hv0 +.main: + dec hd + jz .height1 + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv0 +%if ARCH_X86_64 + test hd, hd +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .hv0_bottom + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wq, w0m + mov hvsrcm, lpfq +%endif + lea t2, [t1+400*12] +.top_fixup_loop: + mova m0, [t1+wq+400* 0] + mova m1, [t1+wq+400* 2] + mova m2, [t1+wq+400* 4] + paddw m0, m0 + mova m3, [t1+wq+400* 6] + paddd m1, m1 + mova m4, [t1+wq+400* 8] + paddd m2, m2 + mova m5, [t1+wq+400*10] + mova [t2+wq+400* 0], m0 + mova [t2+wq+400* 2], m1 + mova [t2+wq+400* 4], m2 + mova [t2+wq+400* 6], m3 + mova [t2+wq+400* 8], m4 + mova [t2+wq+400*10], m5 + add wq, 16 + jl .top_fixup_loop + movif32 t3, t3m + movif32 t4, t4m + call .v0 + jmp .main +.h: ; horizontal boxsum +%assign stack_offset stack_offset+4 +%assign calloff 4 +%if ARCH_X86_64 + lea wq, [r4-4] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 10 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, [base+sgr_lshuf5] + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-4] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m4, [lpfq+wq- 2] +.h_main: + movu m5, [lpfq+wq+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -20 + jl .h_have_right +%if ARCH_X86_32 + pxor m8, m8 +%endif + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_ssse3).extend_right +.h_have_right: + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; sum3 + punpcklwd m7, m0, m6 + pmaddwd m7, m7 + punpckhwd m0, m6 + pmaddwd m0, m0 + paddd m2, m7 ; sumsq3 + palignr m5, m4, 8 + punpcklwd m7, m5, m4 + paddw m8, m4, m5 + pmaddwd m7, m7 + punpckhwd m5, m4 + pmaddwd m5, m5 + paddd m3, m0 + mova [t1+wq+400* 6], m1 + mova [t1+wq+400* 8], m2 + mova [t1+wq+400*10], m3 + paddw m8, m1 ; sum5 + paddd m7, m2 ; sumsq5 + paddd m5, m3 + mova [t1+wq+400* 0], m8 + mova [t1+wq+400* 2], m7 + mova [t1+wq+400* 4], m5 + add wq, 16 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab3 (even rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 10 + jmp .hv0_main +.hv0_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, [base+sgr_lshuf5] + jmp .hv0_main +.hv0_bottom: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv0_loop_start +%endif +.hv0_loop: + movif32 lpfq, hvsrcm +.hv0_loop_start: + movu m4, [lpfq+wq- 2] +.hv0_main: + movu m5, [lpfq+wq+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp wd, -20 + jl .hv0_have_right +%if ARCH_X86_32 + pxor m8, m8 +%endif + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_ssse3).extend_right +.hv0_have_right: + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + movif32 t3, t3m + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; h sum3 + punpcklwd m7, m0, m6 + pmaddwd m7, m7 + punpckhwd m0, m6 + pmaddwd m0, m0 + paddd m2, m7 ; h sumsq3 + palignr m5, m4, 8 + punpcklwd m7, m5, m4 + paddw m8, m4, m5 + pmaddwd m7, m7 + punpckhwd m5, m4 + pmaddwd m5, m5 + paddd m3, m0 + paddw m8, m1 ; h sum5 + paddd m7, m2 ; h sumsq5 + paddd m5, m3 + mova [t3+wq*2+400*8+ 8], m8 + mova [t3+wq*2+400*0+ 8], m7 + mova [t3+wq*2+400*0+24], m5 + paddw m8, [t1+wq+400* 0] + paddd m7, [t1+wq+400* 2] + paddd m5, [t1+wq+400* 4] + mova [t1+wq+400* 0], m8 + mova [t1+wq+400* 2], m7 + mova [t1+wq+400* 4], m5 + paddw m0, m1, [t1+wq+400* 6] + paddd m4, m2, [t1+wq+400* 8] + paddd m5, m3, [t1+wq+400*10] + mova [t1+wq+400* 6], m1 + mova [t1+wq+400* 8], m2 + mova [t1+wq+400*10], m3 + paddw m1, m0, [t2+wq+400* 6] + paddd m2, m4, [t2+wq+400* 8] + paddd m3, m5, [t2+wq+400*10] + mova [t2+wq+400* 6], m0 + mova [t2+wq+400* 8], m4 + mova [t2+wq+400*10], m5 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MAXSD m4, m2, m7 + MAXSD m5, m3, m7 + psubd m4, m2 ; p3 + psubd m5, m3 + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*1+400*2+ 4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+400*4+ 8], m0 + mova [t3+wq*2+400*4+24], m1 + add wq, 16 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 leftq, leftm + movddup m5, [leftq] + movif32 wq, w0m + mova m4, [lpfq+wq+4] + add leftmp, 8 + palignr m4, m5, 10 + jmp .hv1_main +.hv1_extend_left: + movif32 wq, w0m + mova m4, [lpfq+wq+4] + pshufb m4, [base+sgr_lshuf5] + jmp .hv1_main +.hv1_bottom: +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv1_loop_start +%endif +.hv1_loop: + movif32 lpfq, hvsrcm +.hv1_loop_start: + movu m4, [lpfq+wq- 2] +.hv1_main: + movu m5, [lpfq+wq+14] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp wd, -20 + jl .hv1_have_right +%if ARCH_X86_32 + pxor m8, m8 +%endif + call mangle(private_prefix %+ _sgr_filter_5x5_16bpc_ssse3).extend_right +.hv1_have_right: + palignr m7, m5, m4, 2 + palignr m3, m5, m4, 4 + paddw m2, m7, m3 + punpcklwd m0, m7, m3 + pmaddwd m0, m0 + punpckhwd m7, m3 + pmaddwd m7, m7 + palignr m3, m5, m4, 6 + paddw m2, m3 ; h sum3 + punpcklwd m1, m3, m6 + pmaddwd m1, m1 + punpckhwd m3, m6 + pmaddwd m3, m3 + paddd m0, m1 ; h sumsq3 + palignr m5, m4, 8 + punpckhwd m1, m4, m5 + paddw m8, m4, m5 + pmaddwd m1, m1 + punpcklwd m4, m5 + pmaddwd m4, m4 + paddd m7, m3 + paddw m5, m2, [t2+wq+400* 6] + mova [t2+wq+400* 6], m2 + paddw m8, m2 ; h sum5 + paddd m2, m0, [t2+wq+400* 8] + paddd m3, m7, [t2+wq+400*10] + mova [t2+wq+400* 8], m0 + mova [t2+wq+400*10], m7 + paddd m4, m0 ; h sumsq5 + paddd m1, m7 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 + pslld m0, m2, 3 + pslld m7, m3, 3 + paddd m2, m0 ; ((a3 + 8) >> 4) * 9 + paddd m3, m7 + psrlw m7, m5, 1 + pavgw m7, m6 ; (b3 + 2) >> 2 + punpcklwd m0, m7, m6 + pmaddwd m0, m0 + punpckhwd m7, m6 + pmaddwd m7, m7 +%if ARCH_X86_32 + mova [esp+20], m8 +%else + SWAP m8, m6 +%endif + MAXSD m2, m0, m8 + MAXSD m3, m7, m8 + pxor m8, m8 + psubd m2, m0 ; p3 + psubd m3, m7 + punpcklwd m0, m5, m8 ; b3 + punpckhwd m5, m8 + MULLD m2, m14, m8 ; p3 * s1 + MULLD m3, m14, m8 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m5, m11 + paddusw m2, m11 + paddusw m3, m11 + psrld m2, 20 ; min(z3, 255) + movif32 t3, t3m + psrld m3, 20 + GATHER_X_BY_X m8, m2, m3, r0, dstm + punpcklwd m2, m8, m8 + punpckhwd m3, m8, m8 + MULLD m0, m2, m7 + MULLD m5, m3, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m5, m10 + psrld m0, 12 + psrld m5, 12 + mova [t4+wq*1+400*4+4], m8 + mova [t3+wq*2+400*8+ 8], m0 + mova [t3+wq*2+400*8+24], m5 +%if ARCH_X86_32 + mova m8, [esp+20] +%else + SWAP m6, m8 + pxor m6, m6 +%endif + paddw m5, m8, [t2+wq+400*0] + paddd m2, m4, [t2+wq+400*2] + paddd m3, m1, [t2+wq+400*4] + paddw m5, [t1+wq+400*0] + paddd m2, [t1+wq+400*2] + paddd m3, [t1+wq+400*4] + mova [t2+wq+400*0], m8 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + mova [t2+wq+400*2], m4 + pslld m8, m2, 4 + mova [t2+wq+400*4], m1 + pslld m4, m3, 4 + paddd m8, m2 + pslld m2, 3 + paddd m4, m3 + pslld m3, 3 + paddd m2, m8 ; ((a5 + 8) >> 4) * 25 + paddd m3, m4 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + psrlw m1, m5, 1 + pavgw m1, m7 ; (b5 + 2) >> 2 + punpcklwd m4, m1, m7 + pmaddwd m4, m4 + punpckhwd m1, m7 + pmaddwd m1, m1 + punpcklwd m0, m5, m7 ; b5 + punpckhwd m5, m7 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MAXSD m2, m4, m7 + psubd m2, m4 ; p5 + MAXSD m3, m1, m7 + psubd m3, m1 + MULLD m2, m13, m7 ; p5 * s0 + MULLD m3, m13, m7 + pmaddwd m0, m12 ; b5 * 164 + pmaddwd m5, m12 + paddusw m2, m12 + paddusw m3, m12 + psrld m2, 20 ; min(z5, 255) + psrld m3, 20 + GATHER_X_BY_X m1, m2, m3, r0, dstm + punpcklwd m2, m1, m1 + punpckhwd m3, m1, m1 + MULLD m0, m2, m7 + MULLD m5, m3, m7 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m5, m10 + mova [t4+wq*1+400*0+ 4], m1 + psrld m0, 12 + psrld m5, 12 + mova [t3+wq*2+400*0+ 8], m0 + mova [t3+wq*2+400*0+24], m5 + add wq, 16 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.v0_loop: + mova m0, [t1+wq+400* 6] + mova m4, [t1+wq+400* 8] + mova m5, [t1+wq+400*10] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+wq+400* 6] + paddd m2, m4, [t2+wq+400* 8] + paddd m3, m5, [t2+wq+400*10] + mova [t2+wq+400* 6], m0 + mova [t2+wq+400* 8], m4 + mova [t2+wq+400*10], m5 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MAXSD m4, m2, m7 + MAXSD m5, m3, m7 + psubd m4, m2 ; p3 + psubd m5, m3 + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*1+400*2+4], m3 + psrld m0, 12 + psrld m1, 12 + mova m3, [t1+wq+400*0] + mova m4, [t1+wq+400*2] + mova m5, [t1+wq+400*4] + mova [t3+wq*2+400*8+ 8], m3 + mova [t3+wq*2+400*0+ 8], m4 + mova [t3+wq*2+400*0+24], m5 + paddw m3, m3 ; cc5 + paddd m4, m4 + paddd m5, m5 + mova [t1+wq+400*0], m3 + mova [t1+wq+400*2], m4 + mova [t1+wq+400*4], m5 + mova [t3+wq*2+400*4+ 8], m0 + mova [t3+wq*2+400*4+24], m1 + add wq, 16 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-4] +%else + mov wd, w0m +%endif +.v1_loop: + mova m4, [t1+wq+400* 6] + mova m5, [t1+wq+400* 8] + mova m7, [t1+wq+400*10] + paddw m1, m4, [t2+wq+400* 6] + paddd m2, m5, [t2+wq+400* 8] + paddd m3, m7, [t2+wq+400*10] + mova [t2+wq+400* 6], m4 + mova [t2+wq+400* 8], m5 + mova [t2+wq+400*10], m7 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a3 + 8) >> 4 + psrld m3, 4 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + psrlw m3, m1, 1 + pavgw m3, m7 ; (b3 + 2) >> 2 + punpcklwd m2, m3, m7 + pmaddwd m2, m2 + punpckhwd m3, m7 + pmaddwd m3, m3 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MAXSD m4, m2, m7 + MAXSD m5, m3, m7 + psubd m4, m2 ; p3 + psubd m5, m3 + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*1+400*4+4], m3 + psrld m0, 12 + psrld m8, m1, 12 + mova m4, [t3+wq*2+400*8+ 8] + mova m5, [t3+wq*2+400*0+ 8] + mova m7, [t3+wq*2+400*0+24] + paddw m1, m4, [t2+wq+400*0] + paddd m2, m5, [t2+wq+400*2] + paddd m3, m7, [t2+wq+400*4] + paddw m1, [t1+wq+400*0] + paddd m2, [t1+wq+400*2] + paddd m3, [t1+wq+400*4] + mova [t2+wq+400*0], m4 + mova [t2+wq+400*2], m5 + mova [t2+wq+400*4], m7 + paddd m2, m9 + paddd m3, m9 + psrld m2, 4 ; (a5 + 8) >> 4 + psrld m3, 4 + mova [t3+wq*2+400*8+ 8], m0 + pslld m4, m2, 4 + mova [t3+wq*2+400*8+24], m8 + pslld m5, m3, 4 + paddd m4, m2 + pslld m2, 3 + paddd m5, m3 + pslld m3, 3 + paddd m2, m4 + paddd m3, m5 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + psrlw m5, m1, 1 + pavgw m5, m7 ; (b5 + 2) >> 2 + punpcklwd m4, m5, m7 + pmaddwd m4, m4 + punpckhwd m5, m7 + pmaddwd m5, m5 + punpcklwd m0, m1, m7 ; b5 + punpckhwd m1, m7 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MAXSD m2, m4, m7 + psubd m2, m4 ; p5 + MAXSD m3, m5, m7 + psubd m3, m5 + MULLD m2, m13, m7 ; p5 * s0 + MULLD m3, m13, m7 + pmaddwd m0, m12 ; b5 * 164 + pmaddwd m1, m12 + paddusw m2, m12 + paddusw m3, m12 + psrld m2, 20 ; min(z5, 255) + psrld m3, 20 + GATHER_X_BY_X m4, m2, m3, r0, dstm + punpcklwd m2, m4, m4 + punpckhwd m3, m4, m4 + MULLD m0, m2, m7 + MULLD m1, m3, m7 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*1+400*0+ 4], m4 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*2+400*0+ 8], m0 + mova [t3+wq*2+400*0+24], m1 + add wq, 16 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*1+400*0+ 2] + movu m1, [t3+wq*2+400*0+ 4] + movu m2, [t3+wq*2+400*0+20] + movu m7, [t4+wq*1+400*0+ 4] + movu m8, [t3+wq*2+400*0+ 8] + paddw m3, m0, [t4+wq*1+400*0+ 0] + paddd m4, m1, [t3+wq*2+400*0+ 0] + paddd m5, m2, [t3+wq*2+400*0+16] + paddw m3, m7 + paddd m4, m8 + movu m7, [t3+wq*2+400*0+24] + paddw m0, m3 + paddd m1, m4 + psllw m3, 2 + pslld m4, 2 + paddd m5, m7 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a5 565 + paddd m1, m4 ; b5 565 + paddd m2, m5 + mova [t4+wq*1+400* 6+ 0], m0 + mova [t3+wq*2+400*12+ 0], m1 + mova [t3+wq*2+400*12+16], m2 + movu m0, [t4+wq*1+400*2+ 4] + movu m1, [t3+wq*2+400*4+ 8] + movu m2, [t3+wq*2+400*4+24] + movu m3, [t4+wq*1+400*2+ 2] + movu m4, [t3+wq*2+400*4+ 4] + movu m5, [t3+wq*2+400*4+20] + paddw m0, [t4+wq*1+400*2+ 0] + paddd m1, [t3+wq*2+400*4+ 0] + paddd m2, [t3+wq*2+400*4+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a3[-1] 444 + pslld m4, 2 ; b3[-1] 444 + pslld m5, 2 + psubw m3, m0 ; a3[-1] 343 + psubd m4, m1 ; b3[-1] 343 + psubd m5, m2 + mova [t4+wq*1+400* 8+ 0], m3 + mova [t3+wq*2+400*16+ 0], m4 + mova [t3+wq*2+400*16+16], m5 + movu m0, [t4+wq*1+400*4+ 4] + movu m1, [t3+wq*2+400*8+ 8] + movu m2, [t3+wq*2+400*8+24] + movu m3, [t4+wq*1+400*4+ 2] + movu m4, [t3+wq*2+400*8+ 4] + movu m5, [t3+wq*2+400*8+20] + paddw m0, [t4+wq*1+400*4+ 0] + paddd m1, [t3+wq*2+400*8+ 0] + paddd m2, [t3+wq*2+400*8+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a3[ 0] 444 + pslld m4, 2 ; b3[ 0] 444 + pslld m5, 2 + mova [t4+wq*1+400*10+ 0], m3 + mova [t3+wq*2+400*20+ 0], m4 + mova [t3+wq*2+400*20+16], m5 + psubw m3, m0 ; a3[ 0] 343 + psubd m4, m1 ; b3[ 0] 343 + psubd m5, m2 + mova [t4+wq*1+400*12+ 0], m3 + mova [t3+wq*2+400*24+ 0], m4 + mova [t3+wq*2+400*24+16], m5 + add wq, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m0, [t4+wq*1+ 4] + movu m2, [t4+wq*1+ 2] + paddw m0, [t4+wq*1+ 0] + paddw m0, m2 + paddw m2, m0 + psllw m0, 2 + paddw m0, m2 ; a5 + movu m4, [t3+wq*2+ 8] + movu m5, [t3+wq*2+24] + movu m1, [t3+wq*2+ 4] + movu m3, [t3+wq*2+20] + paddd m4, [t3+wq*2+ 0] + paddd m5, [t3+wq*2+16] + paddd m4, m1 + paddd m5, m3 + paddd m1, m4 + paddd m3, m5 + pslld m4, 2 + pslld m5, 2 + paddd m4, m1 ; b5 + paddd m5, m3 + movu m2, [t4+wq*1+400* 6] + paddw m2, m0 + mova [t4+wq*1+400* 6], m0 + paddd m0, m4, [t3+wq*2+400*12+ 0] + paddd m1, m5, [t3+wq*2+400*12+16] + mova [t3+wq*2+400*12+ 0], m4 + mova [t3+wq*2+400*12+16], m5 + mova [rsp+16+ARCH_X86_32*4], m1 + movu m3, [t4+wq*1+400*2+4] + movu m5, [t4+wq*1+400*2+2] + paddw m3, [t4+wq*1+400*2+0] + paddw m5, m3 + psllw m5, 2 ; a3[ 1] 444 + psubw m4, m5, m3 ; a3[ 1] 343 + movu m3, [t4+wq*1+400* 8] + paddw m3, [t4+wq*1+400*10] + paddw m3, m4 + mova [t4+wq*1+400* 8], m4 + mova [t4+wq*1+400*10], m5 + movu m1, [t3+wq*2+400*4+ 8] + movu m5, [t3+wq*2+400*4+ 4] + movu m7, [t3+wq*2+400*4+24] + movu m8, [t3+wq*2+400*4+20] + paddd m1, [t3+wq*2+400*4+ 0] + paddd m7, [t3+wq*2+400*4+16] + paddd m5, m1 + paddd m8, m7 + pslld m5, 2 ; b3[ 1] 444 + pslld m8, 2 + psubd m4, m5, m1 ; b3[ 1] 343 +%if ARCH_X86_32 + mova [esp+52], m8 + psubd m8, m7 +%else + psubd m6, m8, m7 + SWAP m8, m6 +%endif + paddd m1, m4, [t3+wq*2+400*16+ 0] + paddd m7, m8, [t3+wq*2+400*16+16] + paddd m1, [t3+wq*2+400*20+ 0] + paddd m7, [t3+wq*2+400*20+16] + mova [t3+wq*2+400*16+ 0], m4 + mova [t3+wq*2+400*16+16], m8 + mova [t3+wq*2+400*20+ 0], m5 +%if ARCH_X86_32 + mova m8, [esp+52] +%else + SWAP m8, m6 + pxor m6, m6 +%endif + mova [t3+wq*2+400*20+16], m8 + mova [rsp+32+ARCH_X86_32*4], m7 + movu m5, [dstq+wq] + punpcklwd m4, m5, m6 + punpcklwd m7, m2, m6 + pmaddwd m7, m4 ; a5 * src + punpcklwd m8, m3, m6 + pmaddwd m8, m4 ; a3 * src + punpckhwd m5, m6 + punpckhwd m2, m6 + pmaddwd m2, m5 + punpckhwd m3, m6 + pmaddwd m3, m5 + pslld m4, 13 + pslld m5, 13 + psubd m0, m7 ; b5 - a5 * src + (1 << 8) + psubd m1, m8 ; b3 - a3 * src + (1 << 8) + mova m7, [base+pd_0xffff] + psrld m0, 9 + pslld m1, 7 + pand m0, m7 + pandn m8, m7, m1 + por m0, m8 + mova m1, [rsp+16+ARCH_X86_32*4] + mova m8, [rsp+32+ARCH_X86_32*4] + psubd m1, m2 + psubd m8, m3 + mova m2, [base+pd_4096] + psrld m1, 9 + pslld m8, 7 + pand m1, m7 + pandn m7, m8 + por m1, m7 + pmaddwd m0, m15 + pmaddwd m1, m15 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + paddd m4, m2 + paddd m5, m2 + paddd m0, m4 + paddd m1, m5 + psrad m0, 8 + psrad m1, 8 + packssdw m0, m1 ; clip + pmaxsw m0, m7 + psrlw m0, 5 + mova [dstq+wq], m0 + add wq, 16 + jl .n0_loop + add dstq, stridemp + ret +%if ARCH_X86_64 + SWAP m6, m7 +%endif +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + movu m3, [t4+wq*1+400*4+4] + movu m5, [t4+wq*1+400*4+2] + paddw m3, [t4+wq*1+400*4+0] + paddw m5, m3 + psllw m5, 2 ; a3[ 1] 444 + psubw m4, m5, m3 ; a3[ 1] 343 + paddw m3, m4, [t4+wq*1+400*12] + paddw m3, [t4+wq*1+400*10] + mova [t4+wq*1+400*10], m5 + mova [t4+wq*1+400*12], m4 + movu m1, [t3+wq*2+400*8+ 8] + movu m5, [t3+wq*2+400*8+ 4] + movu m7, [t3+wq*2+400*8+24] + movu m8, [t3+wq*2+400*8+20] + paddd m1, [t3+wq*2+400*8+ 0] + paddd m7, [t3+wq*2+400*8+16] + paddd m5, m1 + paddd m8, m7 + pslld m5, 2 ; b3[ 1] 444 + pslld m8, 2 + psubd m4, m5, m1 ; b3[ 1] 343 + psubd m0, m8, m7 + paddd m1, m4, [t3+wq*2+400*24+ 0] + paddd m7, m0, [t3+wq*2+400*24+16] + paddd m1, [t3+wq*2+400*20+ 0] + paddd m7, [t3+wq*2+400*20+16] + mova [t3+wq*2+400*20+ 0], m5 + mova [t3+wq*2+400*20+16], m8 + mova [t3+wq*2+400*24+ 0], m4 + mova [t3+wq*2+400*24+16], m0 + mova m5, [dstq+wq] + mova m2, [t4+wq*1+400* 6] + punpcklwd m4, m5, m6 + punpcklwd m8, m2, m6 + pmaddwd m8, m4 ; a5 * src + punpcklwd m0, m3, m6 + pmaddwd m0, m4 ; a3 * src + punpckhwd m5, m6 + punpckhwd m2, m6 + pmaddwd m2, m5 + punpckhwd m3, m6 + pmaddwd m3, m5 + psubd m1, m0 ; b3 - a3 * src + (1 << 8) + pslld m4, 13 + pslld m5, 13 + mova m0, [t3+wq*2+400*12+ 0] + psubd m0, m8 ; b5 - a5 * src + (1 << 8) + mova m8, [t3+wq*2+400*12+16] + psubd m8, m2 + psubd m7, m3 + mova m2, [base+pd_0xffff] + pslld m1, 7 + psrld m0, 8 + psrld m8, 8 + pslld m7, 7 + pand m0, m2 + pandn m3, m2, m1 + por m0, m3 + pand m8, m2 + pandn m2, m7 + por m2, m8 + mova m1, [base+pd_4096] + pmaddwd m0, m15 + pmaddwd m2, m15 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + pxor m7, m7 + paddd m4, m1 + paddd m5, m1 + paddd m0, m4 + paddd m2, m5 + psrad m0, 8 + psrad m2, 8 + packssdw m0, m2 ; clip + pmaxsw m0, m7 + psrlw m0, 5 + mova [dstq+wq], m0 + add wq, 16 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2237 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +wiener_l_shuf: db 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +pb_0to31: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + db 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +wiener_shufA: db 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14 +wiener_shufB: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 +wiener_shufC: db 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 10, 12, 11, 13, 12 +sgr_r_ext: times 16 db 1 + times 16 db 9 + +; dword version of dav1d_sgr_x_by_x[] for use with gathers, wastes a bit of +; cache but eliminates some shifts in the inner sgr loop which is overall a win +const sgr_x_by_x_avx2 + dd 255,128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17, 16 + dd 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8 + dd 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5 + dd 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 + dd 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3 + dd 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + dd 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + dd 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + dd 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + dd 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + dd 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 + dd 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + dd 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + dd 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + dd 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + dd 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 + + times 4 db -1 ; needed for 16-bit sgr +pb_m5: times 4 db -5 +pb_3: times 4 db 3 +pw_5_6: dw 5, 6 + +sgr_l_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +sgr_shuf: db 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7, -1, 8, -1 + db 9, -1, 10, -1, 11, -1, 12, -1 + +pw_256: times 2 dw 256 +pw_2056: times 2 dw 2056 +pw_m16380: times 2 dw -16380 +pd_25: dd 25 +pd_34816: dd 34816 +pd_m4096: dd -4096 +pd_0xf00801c7: dd 0xf00801c7 +pd_0xf00800a4: dd 0xf00800a4 + +SECTION .text + +DECLARE_REG_TMP 8, 7, 9, 11, 12, 13, 14 ; ring buffer pointers + +INIT_YMM avx2 +cglobal wiener_filter7_8bpc, 4, 15, 16, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt + mov fltq, r6mp + movifnidn hd, hm + mov edged, r7m + mov wd, wm + vbroadcasti128 m6, [wiener_shufA] + vpbroadcastb m11, [fltq+ 0] ; x0 x0 + vbroadcasti128 m7, [wiener_shufB] + vpbroadcastd m12, [fltq+ 2] + vbroadcasti128 m8, [wiener_shufC] + packsswb m12, m12 ; x1 x2 + vpbroadcastw m13, [fltq+ 6] ; x3 + vbroadcasti128 m9, [sgr_shuf+6] + add lpfq, wq + vpbroadcastd m10, [pw_m16380] + vpbroadcastd m14, [fltq+16] ; y0 y1 + add dstq, wq + vpbroadcastd m15, [fltq+20] ; y2 y3 + lea t1, [rsp+wq*2+16] + psllw m14, 5 + neg wq + psllw m15, 5 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call .v + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call .v +.v2: + call .v + jmp .v1 +.extend_right: + movd xm2, r10d + vpbroadcastd m0, [pb_3] + vpbroadcastd m1, [pb_m5] + vpbroadcastb m2, xm2 + movu m3, [pb_0to31] + psubb m0, m2 + psubb m1, m2 + pminub m0, m3 + pminub m1, m3 + pshufb m4, m0 + pshufb m5, m1 + ret +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm4, [leftq] + vpblendd m4, [lpfq+r10-4], 0xfe + add leftq, 4 + jmp .h_main +.h_extend_left: + vbroadcasti128 m5, [lpfq+r10] ; avoid accessing memory located + mova m4, [lpfq+r10] ; before the start of the buffer + palignr m4, m5, 12 + pshufb m4, [wiener_l_shuf] + jmp .h_main +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+r10-4] +.h_main: + movu m5, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -34 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m0, m4, m6 + pmaddubsw m0, m11 + pshufb m1, m5, m6 + pmaddubsw m1, m11 + pshufb m2, m4, m7 + pmaddubsw m2, m12 + pshufb m3, m5, m7 + pmaddubsw m3, m12 + paddw m0, m2 + pshufb m2, m4, m8 + pmaddubsw m2, m12 + paddw m1, m3 + pshufb m3, m5, m8 + pmaddubsw m3, m12 + pshufb m4, m9 + paddw m0, m2 + pmullw m2, m4, m13 + pshufb m5, m9 + paddw m1, m3 + pmullw m3, m5, m13 + psllw m4, 7 + psllw m5, 7 + paddw m4, m10 + paddw m5, m10 + paddw m0, m2 + vpbroadcastd m2, [pw_2056] + paddw m1, m3 + paddsw m0, m4 + paddsw m1, m5 + psraw m0, 3 + psraw m1, 3 + paddw m0, m2 + paddw m1, m2 + mova [t1+r10*2+ 0], m0 + mova [t1+r10*2+32], m1 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm4, [leftq] + vpblendd m4, [lpfq+r10-4], 0xfe + add leftq, 4 + jmp .hv_main +.hv_extend_left: + movu m4, [lpfq+r10-4] + pshufb m4, [wiener_l_shuf] + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m4, [lpfq+r10-4] +.hv_main: + movu m5, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -34 + jl .hv_have_right + call .extend_right +.hv_have_right: + pshufb m0, m4, m6 + pmaddubsw m0, m11 + pshufb m1, m5, m6 + pmaddubsw m1, m11 + pshufb m2, m4, m7 + pmaddubsw m2, m12 + pshufb m3, m5, m7 + pmaddubsw m3, m12 + paddw m0, m2 + pshufb m2, m4, m8 + pmaddubsw m2, m12 + paddw m1, m3 + pshufb m3, m5, m8 + pmaddubsw m3, m12 + pshufb m4, m9 + paddw m0, m2 + pmullw m2, m4, m13 + pshufb m5, m9 + paddw m1, m3 + pmullw m3, m5, m13 + psllw m4, 7 + psllw m5, 7 + paddw m4, m10 + paddw m5, m10 + paddw m0, m2 + paddw m1, m3 + mova m2, [t4+r10*2] + paddw m2, [t2+r10*2] + mova m3, [t3+r10*2] + paddsw m0, m4 + vpbroadcastd m4, [pw_2056] + paddsw m1, m5 + mova m5, [t5+r10*2] + paddw m5, [t1+r10*2] + psraw m0, 3 + psraw m1, 3 + paddw m0, m4 + paddw m1, m4 + paddw m4, m0, [t6+r10*2] + mova [t0+r10*2], m0 + punpcklwd m0, m2, m3 + pmaddwd m0, m15 + punpckhwd m2, m3 + pmaddwd m2, m15 + punpcklwd m3, m4, m5 + pmaddwd m3, m14 + punpckhwd m4, m5 + pmaddwd m4, m14 + paddd m0, m3 + paddd m4, m2 + mova m2, [t4+r10*2+32] + paddw m2, [t2+r10*2+32] + mova m3, [t3+r10*2+32] + mova m5, [t5+r10*2+32] + paddw m5, [t1+r10*2+32] + packuswb m0, m4 + paddw m4, m1, [t6+r10*2+32] + mova [t0+r10*2+32], m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m15 + punpckhwd m2, m3 + pmaddwd m2, m15 + punpcklwd m3, m4, m5 + pmaddwd m3, m14 + punpckhwd m4, m5 + pmaddwd m4, m14 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+r10], m0 + add r10, 32 + jl .hv_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m2, [t4+r10*2+ 0] + paddw m2, [t2+r10*2+ 0] + mova m4, [t3+r10*2+ 0] + mova m6, [t1+r10*2+ 0] + paddw m8, m6, [t6+r10*2+ 0] + paddw m6, [t5+r10*2+ 0] + mova m3, [t4+r10*2+32] + paddw m3, [t2+r10*2+32] + mova m5, [t3+r10*2+32] + mova m7, [t1+r10*2+32] + paddw m9, m7, [t6+r10*2+32] + paddw m7, [t5+r10*2+32] + punpcklwd m0, m2, m4 + pmaddwd m0, m15 + punpckhwd m2, m4 + pmaddwd m2, m15 + punpcklwd m4, m8, m6 + pmaddwd m4, m14 + punpckhwd m6, m8, m6 + pmaddwd m6, m14 + punpcklwd m1, m3, m5 + pmaddwd m1, m15 + punpckhwd m3, m5 + pmaddwd m3, m15 + punpcklwd m5, m9, m7 + pmaddwd m5, m14 + punpckhwd m7, m9, m7 + pmaddwd m7, m14 + paddd m0, m4 + paddd m2, m6 + paddd m1, m5 + paddd m3, m7 + packuswb m0, m2 + packuswb m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+r10], m0 + add r10, 32 + jl .v_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq + ret + +cglobal wiener_filter5_8bpc, 4, 13, 16, 384*8+16, dst, stride, left, lpf, \ + w, h, edge, flt + mov fltq, r6mp + movifnidn hd, hm + mov edged, r7m + mov wd, wm + vbroadcasti128 m6, [wiener_shufB] + vpbroadcastd m12, [fltq+ 2] + vbroadcasti128 m7, [wiener_shufC] + packsswb m12, m12 ; x1 x2 + vpbroadcastw m13, [fltq+ 6] ; x3 + vbroadcasti128 m8, [sgr_shuf+6] + add lpfq, wq + vpbroadcastd m9, [pw_m16380] + vpbroadcastd m10, [pw_2056] + mova m11, [wiener_l_shuf] + vpbroadcastd m14, [fltq+16] ; __ y1 + add dstq, wq + vpbroadcastd m15, [fltq+20] ; y2 y3 + lea t1, [rsp+wq*2+16] + psllw m14, 5 + neg wq + psllw m15, 5 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t4, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t3, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 +.main: + mov t0, t4 +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v2 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.end: + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v2 + add t0, 384*6 + call .hv + dec hd + jnz .main +.v2: + call .v + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq +.v1: + call .v + jmp .end +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm4, [leftq] + vpblendd m4, [lpfq+r10-4], 0xfe + add leftq, 4 + jmp .h_main +.h_extend_left: + vbroadcasti128 m5, [lpfq+r10] ; avoid accessing memory located + mova m4, [lpfq+r10] ; before the start of the buffer + palignr m4, m5, 12 + pshufb m4, m11 + jmp .h_main +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+r10-4] +.h_main: + movu m5, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -33 + jl .h_have_right + call mangle(private_prefix %+ _wiener_filter7_8bpc_avx2).extend_right +.h_have_right: + pshufb m0, m4, m6 + pmaddubsw m0, m12 + pshufb m1, m5, m6 + pmaddubsw m1, m12 + pshufb m2, m4, m7 + pmaddubsw m2, m12 + pshufb m3, m5, m7 + pmaddubsw m3, m12 + pshufb m4, m8 + paddw m0, m2 + pmullw m2, m4, m13 + pshufb m5, m8 + paddw m1, m3 + pmullw m3, m5, m13 + psllw m4, 7 + psllw m5, 7 + paddw m4, m9 + paddw m5, m9 + paddw m0, m2 + paddw m1, m3 + paddsw m0, m4 + paddsw m1, m5 + psraw m0, 3 + psraw m1, 3 + paddw m0, m10 + paddw m1, m10 + mova [t1+r10*2+ 0], m0 + mova [t1+r10*2+32], m1 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm4, [leftq] + vpblendd m4, [lpfq+r10-4], 0xfe + add leftq, 4 + jmp .hv_main +.hv_extend_left: + movu m4, [lpfq+r10-4] + pshufb m4, m11 + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m4, [lpfq+r10-4] +.hv_main: + movu m5, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -33 + jl .hv_have_right + call mangle(private_prefix %+ _wiener_filter7_8bpc_avx2).extend_right +.hv_have_right: + pshufb m0, m4, m6 + pmaddubsw m0, m12 + pshufb m1, m5, m6 + pmaddubsw m1, m12 + pshufb m2, m4, m7 + pmaddubsw m2, m12 + pshufb m3, m5, m7 + pmaddubsw m3, m12 + pshufb m4, m8 + paddw m0, m2 + pmullw m2, m4, m13 + pshufb m5, m8 + paddw m1, m3 + pmullw m3, m5, m13 + psllw m4, 7 + psllw m5, 7 + paddw m4, m9 + paddw m5, m9 + paddw m0, m2 + paddw m1, m3 + mova m2, [t3+r10*2] + paddw m2, [t1+r10*2] + mova m3, [t2+r10*2] + paddsw m0, m4 + paddsw m1, m5 + psraw m0, 3 + psraw m1, 3 + paddw m0, m10 + paddw m1, m10 + paddw m4, m0, [t4+r10*2] + mova [t0+r10*2], m0 + punpcklwd m0, m2, m3 + pmaddwd m0, m15 + punpckhwd m2, m3 + pmaddwd m2, m15 + punpcklwd m3, m4, m4 + pmaddwd m3, m14 + punpckhwd m4, m4 + pmaddwd m4, m14 + paddd m0, m3 + paddd m4, m2 + mova m2, [t3+r10*2+32] + paddw m2, [t1+r10*2+32] + mova m3, [t2+r10*2+32] + packuswb m0, m4 + paddw m4, m1, [t4+r10*2+32] + mova [t0+r10*2+32], m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m15 + punpckhwd m2, m3 + pmaddwd m2, m15 + punpcklwd m3, m4, m4 + pmaddwd m3, m14 + punpckhwd m4, m4 + pmaddwd m4, m14 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+r10], m0 + add r10, 32 + jl .hv_loop + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t4 + add dstq, strideq + ret +.v: + mov r10, wq + psrld m13, m14, 16 ; y1 __ +.v_loop: + mova m6, [t1+r10*2+ 0] + paddw m2, m6, [t3+r10*2+ 0] + mova m4, [t2+r10*2+ 0] + mova m7, [t1+r10*2+32] + paddw m3, m7, [t3+r10*2+32] + mova m5, [t2+r10*2+32] + paddw m6, [t4+r10*2+ 0] + paddw m7, [t4+r10*2+32] + punpcklwd m0, m2, m4 + pmaddwd m0, m15 + punpckhwd m2, m4 + pmaddwd m2, m15 + punpcklwd m1, m3, m5 + pmaddwd m1, m15 + punpckhwd m3, m5 + pmaddwd m3, m15 + punpcklwd m5, m7, m6 + pmaddwd m4, m5, m14 + punpckhwd m7, m6 + pmaddwd m6, m7, m14 + pmaddwd m5, m13 + pmaddwd m7, m13 + paddd m0, m4 + paddd m2, m6 + paddd m1, m5 + paddd m3, m7 + packuswb m0, m2 + packuswb m1, m3 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+r10], m0 + add r10, 32 + jl .v_loop + ret + +cglobal sgr_filter_5x5_8bpc, 4, 13, 16, 400*24+16, dst, stride, left, lpf, \ + w, h, edge, params +%define base r12-sgr_x_by_x_avx2-256*4 + lea r12, [sgr_x_by_x_avx2+256*4] + mov paramsq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + vbroadcasti128 m8, [base+sgr_shuf+0] + vbroadcasti128 m9, [base+sgr_shuf+8] + add lpfq, wq + vbroadcasti128 m10, [base+sgr_shuf+2] + add dstq, wq + vbroadcasti128 m11, [base+sgr_shuf+6] + lea t3, [rsp+wq*4+16+400*12] + vpbroadcastd m12, [paramsq+0] ; s0 + pxor m6, m6 + vpbroadcastw m7, [paramsq+8] ; w0 + lea t1, [rsp+wq*2+20] + vpbroadcastd m13, [base+pd_0xf00800a4] + neg wq + vpbroadcastd m14, [base+pd_34816] ; (1 << 11) + (1 << 15) + psllw m7, 4 + vpbroadcastd m15, [base+pd_m4096] + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call .top_fixup + add t1, 400*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, strideq + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + test hd, hd + jz .odd_height + call .h + add lpfq, strideq + call .hv + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .h_top + add lpfq, strideq + call .hv_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + call .n0 + call .n1 +.odd_height_end: + call .v + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+400*6] + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + jmp .main +.no_top_height1: + call .v + call .prep_n + jmp .odd_height_end +.extend_right: + movd xm2, r10d + mova m0, [sgr_r_ext] + vpbroadcastb m2, xm2 + psubb m0, m2 + pminub m0, [pb_0to31] + pshufb m5, m0 + ret +.h: ; horizontal boxsum + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .h_main +.h_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu xm5, [lpfq+r10-2] +.h_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -18 + jl .h_have_right + call .extend_right +.h_have_right: + pshufb m3, m5, m8 + pmullw m4, m3, m3 + pshufb m2, m5, m9 + paddw m0, m3, m2 + shufps m3, m2, q2121 + paddw m0, m3 + punpcklwd m1, m2, m3 + pmaddwd m1, m1 + punpckhwd m2, m3 + pmaddwd m2, m2 + punpcklwd m3, m4, m6 + paddd m1, m3 + punpckhwd m4, m6 + paddd m2, m4 + pshufb m4, m5, m10 + paddw m0, m4 + pshufb m5, m11 + paddw m0, m5 ; sum + punpcklwd m3, m4, m5 + pmaddwd m3, m3 + punpckhwd m4, m5 + pmaddwd m4, m4 + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+r10*2+400*0] + paddd m1, [t1+r10*2+400*2] + paddd m2, [t1+r10*2+400*4] +.h_loop_end: + paddd m1, m3 ; sumsq + paddd m2, m4 + mova [t1+r10*2+400*0], m0 + mova [t1+r10*2+400*2], m1 + mova [t1+r10*2+400*4], m2 + add r10, 16 + jl .h_loop + ret +.top_fixup: + lea r10, [wq-2] +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+r10*2+400*0] + mova m1, [t1+r10*2+400*2] + mova m2, [t1+r10*2+400*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+r10*2+400*0], m0 + mova [t2+r10*2+400*2], m1 + mova [t2+r10*2+400*4], m2 + add r10, 16 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .hv_main +.hv_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .hv_main +.hv_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu xm5, [lpfq+r10-2] +.hv_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -18 + jl .hv_have_right + call .extend_right +.hv_have_right: + pshufb m1, m5, m8 + pmullw m4, m1, m1 + pshufb m3, m5, m9 + paddw m0, m1, m3 + shufps m1, m3, q2121 + paddw m0, m1 + punpcklwd m2, m3, m1 + pmaddwd m2, m2 + punpckhwd m3, m1 + pmaddwd m3, m3 + punpcklwd m1, m4, m6 + paddd m2, m1 + punpckhwd m4, m6 + paddd m3, m4 + pshufb m1, m5, m10 + paddw m0, m1 + pshufb m5, m11 + paddw m0, m5 ; h sum + punpcklwd m4, m5, m1 + pmaddwd m4, m4 + punpckhwd m5, m1 + pmaddwd m5, m5 + paddw m1, m0, [t1+r10*2+400*0] + paddd m2, m4 ; h sumsq + paddd m3, m5 + paddd m4, m2, [t1+r10*2+400*2] + paddd m5, m3, [t1+r10*2+400*4] + test hd, hd + jz .hv_last_row +.hv_main2: + paddw m1, [t2+r10*2+400*0] ; hv sum + paddd m4, [t2+r10*2+400*2] ; hv sumsq + paddd m5, [t2+r10*2+400*4] + mova [t0+r10*2+400*0], m0 + mova [t0+r10*2+400*2], m2 + mova [t0+r10*2+400*4], m3 + vpbroadcastd m2, [pd_25] + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmulld m4, m2 ; a * 25 + pmulld m5, m2 + pmaddwd m2, m0, m0 ; b * b + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m12 ; p * s + pmulld m5, m12 + pmaddwd m0, m13 ; b * 164 + pmaddwd m1, m13 + paddusw m4, m13 + paddusw m5, m13 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r12+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r12+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + paddd m0, m14 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m14 + pand m0, m15 + pand m1, m15 + por m0, m2 ; a | (b << 12) + por m1, m3 + mova [t3+r10*4+ 8], xm0 ; The neighbor calculations requires + vextracti128 [t3+r10*4+40], m0, 1 ; 13 bits for a and 21 bits for b. + mova [t3+r10*4+24], xm1 ; Packing them allows for 12+20, but + vextracti128 [t3+r10*4+56], m1, 1 ; that gets us most of the way. + add r10, 16 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+r10*2+400*0], m1 + paddw m1, m0 + mova [t1+r10*2+400*2], m4 + paddd m4, m2 + mova [t1+r10*2+400*4], m5 + paddd m5, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab + lea r10, [wq-2] +.v_loop: + mova m0, [t1+r10*2+400*0] + mova m2, [t1+r10*2+400*2] + mova m3, [t1+r10*2+400*4] + paddw m1, m0, [t2+r10*2+400*0] + paddd m4, m2, [t2+r10*2+400*2] + paddd m5, m3, [t2+r10*2+400*4] + paddw m0, m0 + paddd m2, m2 + paddd m3, m3 + paddw m1, m0 ; hv sum + paddd m4, m2 ; hv sumsq + paddd m5, m3 + vpbroadcastd m2, [pd_25] + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmulld m4, m2 ; a * 25 + pmulld m5, m2 + pmaddwd m2, m0, m0 ; b * b + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m12 ; p * s + pmulld m5, m12 + pmaddwd m0, m13 ; b * 164 + pmaddwd m1, m13 + paddusw m4, m13 + paddusw m5, m13 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r12+m3*4], m4 ; x + psrad m4, m5, 20 + vpgatherdd m3, [r12+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + paddd m0, m14 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m14 + pand m0, m15 + pand m1, m15 + por m0, m2 ; a | (b << 12) + por m1, m3 + mova [t3+r10*4+ 8], xm0 + vextracti128 [t3+r10*4+40], m0, 1 + mova [t3+r10*4+24], xm1 + vextracti128 [t3+r10*4+56], m1, 1 + add r10, 16 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t3+r10*4+ 4] + movu m1, [t3+r10*4+36] + paddd m2, m0, [t3+r10*4+ 0] + paddd m3, m1, [t3+r10*4+32] + paddd m2, [t3+r10*4+ 8] + paddd m3, [t3+r10*4+40] + paddd m0, m2 + pslld m2, 2 + paddd m1, m3 + pslld m3, 2 + paddd m2, m0 ; ab 565 + paddd m3, m1 + pandn m0, m15, m2 ; a + psrld m2, 12 ; b + pandn m1, m15, m3 + psrld m3, 12 + mova [t3+r10*4+400*4+ 0], m0 + mova [t3+r10*4+400*8+ 0], m2 + mova [t3+r10*4+400*4+32], m1 + mova [t3+r10*4+400*8+32], m3 + add r10, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m0, [t3+r10*4+ 4] + movu m1, [t3+r10*4+36] + paddd m2, m0, [t3+r10*4+ 0] + paddd m3, m1, [t3+r10*4+32] + paddd m2, [t3+r10*4+ 8] + paddd m3, [t3+r10*4+40] + paddd m0, m2 + pslld m2, 2 + paddd m1, m3 + pslld m3, 2 + paddd m2, m0 + paddd m3, m1 + pandn m0, m15, m2 + psrld m2, 12 + pandn m1, m15, m3 + psrld m3, 12 + paddd m4, m0, [t3+r10*4+400*4+ 0] ; a + paddd m5, m1, [t3+r10*4+400*4+32] + mova [t3+r10*4+400*4+ 0], m0 + mova [t3+r10*4+400*4+32], m1 + paddd m0, m2, [t3+r10*4+400*8+ 0] ; b + paddd m1, m3, [t3+r10*4+400*8+32] + mova [t3+r10*4+400*8+ 0], m2 + mova [t3+r10*4+400*8+32], m3 + pmovzxbd m2, [dstq+r10+0] + pmovzxbd m3, [dstq+r10+8] + pmaddwd m4, m2 ; a * src + pmaddwd m5, m3 + packssdw m2, m3 + psubd m0, m4 ; b - a * src + (1 << 8) + psubd m1, m5 + psrad m0, 9 + psrad m1, 9 + packssdw m0, m1 + pmulhrsw m0, m7 + paddw m0, m2 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + pshufd xm0, xm0, q3120 + mova [dstq+r10], xm0 + add r10, 16 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + pmovzxbd m2, [dstq+r10+0] + pmovzxbd m3, [dstq+r10+8] + pmaddwd m4, m2, [t3+r10*4+400*4+ 0] ; a * src + pmaddwd m5, m3, [t3+r10*4+400*4+32] + mova m0, [t3+r10*4+400*8+ 0] ; b + mova m1, [t3+r10*4+400*8+32] + packssdw m2, m3 + psubd m0, m4 ; b - a * src + (1 << 7) + psubd m1, m5 + psrad m0, 8 + psrad m1, 8 + packssdw m0, m1 + pmulhrsw m0, m7 + paddw m0, m2 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + pshufd xm0, xm0, q3120 + mova [dstq+r10], xm0 + add r10, 16 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_3x3_8bpc, 4, 15, 15, -400*28-16, dst, stride, left, lpf, \ + w, h, edge, params +%define base r14-sgr_x_by_x_avx2-256*4 + mov paramsq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + lea r14, [sgr_x_by_x_avx2+256*4] + vbroadcasti128 m8, [base+sgr_shuf+2] + add lpfq, wq + vbroadcasti128 m9, [base+sgr_shuf+4] + add dstq, wq + vbroadcasti128 m10, [base+sgr_shuf+6] + lea t3, [rsp+wq*4+16+400*12] + vpbroadcastd m11, [paramsq+ 4] ; s1 + pxor m6, m6 + vpbroadcastw m7, [paramsq+10] ; w1 + lea t1, [rsp+wq*2+20] + vpbroadcastd m12, [base+pd_0xf00801c7] + neg wq + vpbroadcastd m13, [base+pd_34816] ; (1 << 11) + (1 << 15) + psllw m7, 4 + vpbroadcastd m14, [base+pd_m4096] + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + add t1, 400*6 + call .h_top + lea t4, [lpfq+strideq*4] + mov lpfq, dstq + add t4, strideq + mov [rsp], t4 ; below + mov t0, t2 + call .hv +.main: + mov t5, t3 + add t3, 400*4 + dec hd + jz .height1 + add lpfq, strideq + call .hv + call .prep_n + dec hd + jz .extend_bottom +.main_loop: + add lpfq, strideq + call .hv + call .n + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv_bottom + call .n + add lpfq, strideq + call .hv_bottom +.end: + call .n + RET +.height1: + call .v + call .prep_n + mov t2, t1 + call .v + jmp .end +.extend_bottom: + call .v + call .n + mov t2, t1 + call .v + jmp .end +.no_top: + lea t4, [lpfq+strideq*4] + mov lpfq, dstq + lea t4, [t4+strideq*2] + mov [rsp], t4 + call .h + lea t0, [t1+400*6] + mov t2, t1 + call .v + jmp .main +.h: ; horizontal boxsum + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .h_main +.h_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu xm5, [lpfq+r10-2] +.h_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -17 + jl .h_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).extend_right +.h_have_right: + pshufb m0, m5, m8 + pmullw m2, m0, m0 + pshufb m4, m5, m9 + paddw m0, m4 + pshufb m5, m10 + paddw m0, m5 ; sum + punpcklwd m3, m4, m5 + pmaddwd m3, m3 + punpckhwd m4, m5 + pmaddwd m4, m4 + punpcklwd m1, m2, m6 + punpckhwd m2, m6 + mova [t1+r10*2+400*0], m0 + paddd m1, m3 ; sumsq + paddd m2, m4 + mova [t1+r10*2+400*2], m1 + mova [t1+r10*2+400*4], m2 + add r10, 16 + jl .h_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .hv_main +.hv_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .hv_main +.hv_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu xm5, [lpfq+r10-2] +.hv_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -17 + jl .hv_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).extend_right +.hv_have_right: + pshufb m0, m5, m8 + pmullw m3, m0, m0 + pshufb m1, m5, m9 + paddw m0, m1 + pshufb m5, m10 + paddw m0, m5 ; h sum + punpcklwd m4, m5, m1 + pmaddwd m4, m4 + punpckhwd m5, m1 + pmaddwd m5, m5 + paddw m1, m0, [t2+r10*2+400*0] + paddw m1, [t1+r10*2+400*0] ; hv sum + punpcklwd m2, m3, m6 + punpckhwd m3, m6 + paddd m4, m2 ; h sumsq + paddd m5, m3 + paddd m2, m4, [t2+r10*2+400*2] + paddd m3, m5, [t2+r10*2+400*4] + paddd m2, [t1+r10*2+400*2] ; hv sumsq + paddd m3, [t1+r10*2+400*4] + mova [t0+r10*2+400*0], m0 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + mova [t0+r10*2+400*2], m4 + pslld m4, m2, 3 + mova [t0+r10*2+400*4], m5 + pslld m5, m3, 3 + paddd m4, m2 ; a * 9 + pmaddwd m2, m0, m0 ; b * b + paddd m5, m3 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m11 ; p * s + pmulld m5, m11 + pmaddwd m0, m12 ; b * 455 + pmaddwd m1, m12 + paddusw m4, m12 + paddusw m5, m12 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r14+m3*4], m4 + psrad m4, m5, 20 + vpgatherdd m3, [r14+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + paddd m0, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m13 + pand m0, m14 + pand m1, m14 + por m0, m2 ; a | (b << 12) + por m1, m3 + mova [t3+r10*4+ 8], xm0 + vextracti128 [t3+r10*4+40], m0, 1 + mova [t3+r10*4+24], xm1 + vextracti128 [t3+r10*4+56], m1, 1 + add r10, 16 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.v: ; vertical boxsum + ab + lea r10, [wq-2] +.v_loop: + mova m1, [t1+r10*2+400*0] + paddw m1, m1 + paddw m1, [t2+r10*2+400*0] ; hv sum + mova m2, [t1+r10*2+400*2] + mova m3, [t1+r10*2+400*4] + paddd m2, m2 + paddd m3, m3 + paddd m2, [t2+r10*2+400*2] ; hv sumsq + paddd m3, [t2+r10*2+400*4] + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a * 9 + pmaddwd m2, m0, m0 ; b * b + paddd m5, m3 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + pmulld m4, m11 ; p * s + pmulld m5, m11 + pmaddwd m0, m12 ; b * 455 + pmaddwd m1, m12 + paddusw m4, m12 + paddusw m5, m12 + psrad m3, m4, 20 ; min(z, 255) - 256 + vpgatherdd m2, [r14+m3*4], m4 + psrad m4, m5, 20 + vpgatherdd m3, [r14+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + paddd m0, m13 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m13 + pand m0, m14 + pand m1, m14 + por m0, m2 ; a | (b << 12) + por m1, m3 + mova [t3+r10*4+ 8], xm0 + vextracti128 [t3+r10*4+40], m0, 1 + mova [t3+r10*4+24], xm1 + vextracti128 [t3+r10*4+56], m1, 1 + add r10, 16 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq + mov t4, t3 + add t3, 400*4 +.prep_n_loop: + mova m2, [t5+r10*4+0] + mova m3, [t4+r10*4+0] + paddd m2, [t5+r10*4+8] + paddd m3, [t4+r10*4+8] + paddd m0, m2, [t5+r10*4+4] + paddd m1, m3, [t4+r10*4+4] + pslld m0, 2 + paddd m1, m1 ; ab[ 0] 222 + psubd m0, m2 ; ab[-1] 343 + mova [t3+r10*4+400*4], m1 + paddd m1, m1 + mova [t5+r10*4], m0 + psubd m1, m3 ; ab[ 0] 343 + mova [t4+r10*4], m1 + add r10, 8 + jl .prep_n_loop + ret +; a+b are packed together in a single dword, but we can't do the +; full neighbor calculations before splitting them since we don't +; have sufficient precision. The solution is to do the calculations +; in two equal halves and split a and b before doing the final sum. +ALIGN function_align +.n: ; neighbor + output + mov r10, wq +.n_loop: + mova m4, [t3+r10*4+ 0] + paddd m4, [t3+r10*4+ 8] + paddd m5, m4, [t3+r10*4+ 4] + paddd m5, m5 ; ab[+1] 222 + mova m2, [t3+r10*4+400*4+ 0] + paddd m0, m2, [t5+r10*4+ 0] ; ab[ 0] 222 + ab[-1] 343 + mova m3, [t3+r10*4+400*4+32] + paddd m1, m3, [t5+r10*4+32] + mova [t3+r10*4+400*4+ 0], m5 + paddd m5, m5 + psubd m5, m4 ; ab[+1] 343 + mova [t5+r10*4+ 0], m5 + paddd m2, m5 ; ab[ 0] 222 + ab[+1] 343 + mova m4, [t3+r10*4+32] + paddd m4, [t3+r10*4+40] + paddd m5, m4, [t3+r10*4+36] + paddd m5, m5 + mova [t3+r10*4+400*4+32], m5 + paddd m5, m5 + psubd m5, m4 + mova [t5+r10*4+32], m5 + pandn m4, m14, m0 + psrld m0, 12 + paddd m3, m5 + pandn m5, m14, m2 + psrld m2, 12 + paddd m4, m5 ; a + pandn m5, m14, m1 + psrld m1, 12 + paddd m0, m2 ; b + (1 << 8) + pandn m2, m14, m3 + psrld m3, 12 + paddd m5, m2 + pmovzxbd m2, [dstq+r10+0] + paddd m1, m3 + pmovzxbd m3, [dstq+r10+8] + pmaddwd m4, m2 ; a * src + pmaddwd m5, m3 + packssdw m2, m3 + psubd m0, m4 ; b - a * src + (1 << 8) + psubd m1, m5 + psrad m0, 9 + psrad m1, 9 + packssdw m0, m1 + pmulhrsw m0, m7 + paddw m0, m2 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + pshufd xm0, xm0, q3120 + mova [dstq+r10], xm0 + add r10, 16 + jl .n_loop + mov r10, t5 + mov t5, t4 + mov t4, r10 + add dstq, strideq + ret + +cglobal sgr_filter_mix_8bpc, 4, 13, 16, 400*56+8, dst, stride, left, lpf, \ + w, h, edge, params +%define base r12-sgr_x_by_x_avx2-256*4 + lea r12, [sgr_x_by_x_avx2+256*4] + mov paramsq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + vbroadcasti128 m9, [base+sgr_shuf+0] + vbroadcasti128 m10, [base+sgr_shuf+8] + add lpfq, wq + vbroadcasti128 m11, [base+sgr_shuf+2] + vbroadcasti128 m12, [base+sgr_shuf+6] + add dstq, wq + vpbroadcastd m15, [paramsq+8] ; w0 w1 + lea t3, [rsp+wq*4+400*24+8] + vpbroadcastd m13, [paramsq+0] ; s0 + pxor m7, m7 + vpbroadcastd m14, [paramsq+4] ; s1 + lea t1, [rsp+wq*2+12] + neg wq + psllw m15, 2 ; to reuse existing pd_m4096 register for rounding + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).top_fixup + add t1, 400*12 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+400*12] + lea r10, [wq-2] +.top_fixup_loop: + mova m0, [t1+r10*2+400* 0] + mova m1, [t1+r10*2+400* 2] + mova m2, [t1+r10*2+400* 4] + paddw m0, m0 + mova m3, [t1+r10*2+400* 6] + paddd m1, m1 + mova m4, [t1+r10*2+400* 8] + paddd m2, m2 + mova m5, [t1+r10*2+400*10] + mova [t2+r10*2+400* 0], m0 + mova [t2+r10*2+400* 2], m1 + mova [t2+r10*2+400* 4], m2 + mova [t2+r10*2+400* 6], m3 + mova [t2+r10*2+400* 8], m4 + mova [t2+r10*2+400*10], m5 + add r10, 16 + jl .top_fixup_loop + call .v0 + jmp .main +.h: ; horizontal boxsums + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .h_main +.h_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu xm5, [lpfq+r10-2] +.h_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -18 + jl .h_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).extend_right +.h_have_right: + pshufb m6, m5, m9 + pshufb m4, m5, m10 + paddw m8, m6, m4 + shufps m0, m6, m4, q2121 + pmullw m3, m0, m0 + pshufb m2, m5, m11 + paddw m0, m2 + pshufb m5, m12 + paddw m0, m5 ; sum3 + punpcklwd m1, m2, m5 + pmaddwd m1, m1 + punpckhwd m2, m5 + pmaddwd m2, m2 + punpcklwd m5, m6, m4 + pmaddwd m5, m5 + punpckhwd m6, m4 + pmaddwd m6, m6 + punpcklwd m4, m3, m7 + paddd m1, m4 ; sumsq3 + punpckhwd m3, m7 + paddd m2, m3 + mova [t1+r10*2+400* 6], m0 + mova [t1+r10*2+400* 8], m1 + mova [t1+r10*2+400*10], m2 + paddw m8, m0 ; sum5 + paddd m5, m1 ; sumsq5 + paddd m6, m2 + mova [t1+r10*2+400* 0], m8 + mova [t1+r10*2+400* 2], m5 + mova [t1+r10*2+400* 4], m6 + add r10, 16 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsums + vertical boxsum3 + ab3 (even rows) + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .hv0_main +.hv0_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu xm5, [lpfq+r10-2] +.hv0_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -18 + jl .hv0_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).extend_right +.hv0_have_right: + pshufb m6, m5, m9 + pshufb m4, m5, m10 + paddw m8, m6, m4 + shufps m1, m6, m4, q2121 + pmullw m0, m1, m1 + pshufb m3, m5, m11 + paddw m1, m3 + pshufb m5, m12 + paddw m1, m5 ; sum3 + punpcklwd m2, m3, m5 + pmaddwd m2, m2 + punpckhwd m3, m5 + pmaddwd m3, m3 + punpcklwd m5, m6, m4 + pmaddwd m5, m5 + punpckhwd m6, m4 + pmaddwd m6, m6 + punpcklwd m4, m0, m7 + paddd m2, m4 ; sumsq3 + punpckhwd m0, m7 + paddd m3, m0 + paddw m8, m1 ; sum5 + paddd m5, m2 ; sumsq5 + paddd m6, m3 + mova [t3+r10*4+400*8+ 8], m8 ; we need a clean copy of the last row + mova [t3+r10*4+400*0+ 8], m5 ; in case height is odd + mova [t3+r10*4+400*0+40], m6 + paddw m8, [t1+r10*2+400* 0] + paddd m5, [t1+r10*2+400* 2] + paddd m6, [t1+r10*2+400* 4] + mova [t1+r10*2+400* 0], m8 + mova [t1+r10*2+400* 2], m5 + mova [t1+r10*2+400* 4], m6 + paddw m0, m1, [t1+r10*2+400* 6] + paddd m4, m2, [t1+r10*2+400* 8] + paddd m5, m3, [t1+r10*2+400*10] + mova [t1+r10*2+400* 6], m1 + mova [t1+r10*2+400* 8], m2 + mova [t1+r10*2+400*10], m3 + paddw m1, m0, [t2+r10*2+400* 6] + paddd m2, m4, [t2+r10*2+400* 8] + paddd m3, m5, [t2+r10*2+400*10] + mova [t2+r10*2+400* 6], m0 + mova [t2+r10*2+400* 8], m4 + mova [t2+r10*2+400*10], m5 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a3 * 9 + pmaddwd m2, m0, m0 ; b3 * b + paddd m5, m3 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p3 + vpbroadcastd m2, [base+pd_0xf00801c7] + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m2 ; b3 * 455 + pmaddwd m1, m2 + paddusw m4, m2 + paddusw m5, m2 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r12+m3*4], m4 + psrad m4, m5, 20 + vpgatherdd m3, [r12+m4*4], m5 + vpbroadcastd m4, [base+pd_34816] + pmulld m0, m2 + vpbroadcastd m5, [base+pd_m4096] + pmulld m1, m3 + paddd m0, m4 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m4 + pand m0, m5 + pand m1, m5 + por m0, m2 ; a3 | (b3 << 12) + por m1, m3 + mova [t3+r10*4+400*4+ 8], xm0 + vextracti128 [t3+r10*4+400*4+40], m0, 1 + mova [t3+r10*4+400*4+24], xm1 + vextracti128 [t3+r10*4+400*4+56], m1, 1 + add r10, 16 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + vpbroadcastd xm0, [leftq] + mova xm5, [lpfq+wq] + palignr xm5, xm0, 12 + add leftq, 4 + jmp .hv1_main +.hv1_extend_left: + mova xm5, [lpfq+wq] + pshufb xm5, [base+sgr_l_shuf] + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu xm5, [lpfq+r10-2] +.hv1_main: + vinserti128 m5, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -18 + jl .hv1_have_right + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx2).extend_right +.hv1_have_right: + pshufb m6, m5, m9 + pshufb m3, m5, m10 + paddw m8, m6, m3 + shufps m2, m6, m3, q2121 + pmullw m1, m2, m2 + pshufb m0, m5, m11 + paddw m2, m0 + pshufb m5, m12 + paddw m2, m5 ; sum3 + punpcklwd m4, m5, m0 + pmaddwd m4, m4 + punpckhwd m5, m0 + pmaddwd m5, m5 + punpcklwd m0, m6, m3 + pmaddwd m0, m0 + punpckhwd m6, m3 + pmaddwd m6, m6 + punpcklwd m3, m1, m7 + paddd m4, m3 ; sumsq3 + punpckhwd m1, m7 + paddd m5, m1 + paddw m1, m2, [t2+r10*2+400* 6] + mova [t2+r10*2+400* 6], m2 + paddw m8, m2 ; sum5 + paddd m2, m4, [t2+r10*2+400* 8] + paddd m3, m5, [t2+r10*2+400*10] + mova [t2+r10*2+400* 8], m4 + mova [t2+r10*2+400*10], m5 + paddd m4, m0 ; sumsq5 + paddd m5, m6 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pslld m6, m2, 3 + pslld m7, m3, 3 + paddd m6, m2 ; a3 * 9 + pmaddwd m2, m0, m0 ; b3 * b3 + paddd m7, m3 + pmaddwd m3, m1, m1 + psubd m6, m2 ; p3 + vpbroadcastd m2, [base+pd_0xf00801c7] + psubd m7, m3 + pmulld m6, m14 ; p3 * s1 + pmulld m7, m14 + pmaddwd m0, m2 ; b3 * 455 + pmaddwd m1, m2 + paddusw m6, m2 + paddusw m7, m2 + psrad m3, m6, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r12+m3*4], m6 + psrad m6, m7, 20 + vpgatherdd m3, [r12+m6*4], m7 + vpbroadcastd m6, [base+pd_34816] ; x3 + pmulld m0, m2 + vpbroadcastd m7, [base+pd_m4096] + pmulld m1, m3 + paddd m0, m6 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m6 + pand m0, m7 + pand m7, m1 + por m0, m2 ; a3 | (b3 << 12) + por m7, m3 + paddw m1, m8, [t2+r10*2+400*0] + paddd m2, m4, [t2+r10*2+400*2] + paddd m3, m5, [t2+r10*2+400*4] + paddw m1, [t1+r10*2+400*0] + paddd m2, [t1+r10*2+400*2] + paddd m3, [t1+r10*2+400*4] + mova [t2+r10*2+400*0], m8 + mova [t2+r10*2+400*2], m4 + mova [t2+r10*2+400*4], m5 + mova [t3+r10*4+400*8+ 8], xm0 + vextracti128 [t3+r10*4+400*8+40], m0, 1 + mova [t3+r10*4+400*8+24], xm7 + vextracti128 [t3+r10*4+400*8+56], m7, 1 + vpbroadcastd m4, [base+pd_25] + pxor m7, m7 + punpcklwd m0, m1, m7 ; b5 + punpckhwd m1, m7 + pmulld m2, m4 ; a5 * 25 + pmulld m3, m4 + pmaddwd m4, m0, m0 ; b5 * b5 + pmaddwd m5, m1, m1 + psubd m2, m4 ; p5 + vpbroadcastd m4, [base+pd_0xf00800a4] + psubd m3, m5 + pmulld m2, m13 ; p5 * s0 + pmulld m3, m13 + pmaddwd m0, m4 ; b5 * 164 + pmaddwd m1, m4 + paddusw m2, m4 + paddusw m3, m4 + psrad m5, m2, 20 ; min(z5, 255) - 256 + vpgatherdd m4, [r12+m5*4], m2 ; x5 + psrad m2, m3, 20 + vpgatherdd m5, [r12+m2*4], m3 + pmulld m0, m4 + pmulld m1, m5 + paddd m0, m6 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m6 + vpbroadcastd m6, [base+pd_m4096] + pand m0, m6 + pand m1, m6 + por m0, m4 ; a5 | (b5 << 12) + por m1, m5 + mova [t3+r10*4+400*0+ 8], xm0 + vextracti128 [t3+r10*4+400*0+40], m0, 1 + mova [t3+r10*4+400*0+24], xm1 + vextracti128 [t3+r10*4+400*0+56], m1, 1 + add r10, 16 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) + lea r10, [wq-2] + vpbroadcastd m6, [base+pd_34816] + vpbroadcastd m8, [base+pd_m4096] +.v0_loop: + mova m0, [t1+r10*2+400* 6] + mova m4, [t1+r10*2+400* 8] + mova m5, [t1+r10*2+400*10] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+r10*2+400* 6] + paddd m2, m4, [t2+r10*2+400* 8] + paddd m3, m5, [t2+r10*2+400*10] + mova [t2+r10*2+400* 6], m0 + mova [t2+r10*2+400* 8], m4 + mova [t2+r10*2+400*10], m5 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a3 * 9 + pmaddwd m2, m0, m0 ; b3 * b3 + paddd m5, m3 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p3 + vpbroadcastd m2, [base+pd_0xf00801c7] + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m2 ; b3 * 455 + pmaddwd m1, m2 + paddusw m4, m2 + paddusw m5, m2 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r12+m3*4], m4 ; x3 + psrad m4, m5, 20 + vpgatherdd m3, [r12+m4*4], m5 + pmulld m0, m2 + pmulld m1, m3 + paddd m0, m6 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m6 + pand m0, m8 + pand m1, m8 + por m0, m2 ; a3 | (b3 << 12) + por m1, m3 + mova m2, [t1+r10*2+400*0] + mova m3, [t1+r10*2+400*2] + mova m4, [t1+r10*2+400*4] + mova [t3+r10*4+400*8+ 8], m2 + mova [t3+r10*4+400*0+ 8], m3 + mova [t3+r10*4+400*0+40], m4 + paddw m2, m2 ; cc5 + paddd m3, m3 + paddd m4, m4 + mova [t1+r10*2+400*0], m2 + mova [t1+r10*2+400*2], m3 + mova [t1+r10*2+400*4], m4 + mova [t3+r10*4+400*4+ 8], xm0 + vextracti128 [t3+r10*4+400*4+40], m0, 1 + mova [t3+r10*4+400*4+24], xm1 + vextracti128 [t3+r10*4+400*4+56], m1, 1 + add r10, 16 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-2] +.v1_loop: + mova m4, [t1+r10*2+400* 6] + mova m5, [t1+r10*2+400* 8] + mova m6, [t1+r10*2+400*10] + paddw m1, m4, [t2+r10*2+400* 6] + paddd m2, m5, [t2+r10*2+400* 8] + paddd m3, m6, [t2+r10*2+400*10] + mova [t2+r10*2+400* 6], m4 + mova [t2+r10*2+400* 8], m5 + mova [t2+r10*2+400*10], m6 + punpcklwd m0, m1, m7 ; b3 + punpckhwd m1, m7 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a3 * 9 + pmaddwd m2, m0, m0 ; b3 * b3 + paddd m5, m3 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p3 + vpbroadcastd m2, [base+pd_0xf00801c7] + psubd m5, m3 + pmulld m4, m14 ; p3 * s1 + pmulld m5, m14 + pmaddwd m0, m2 ; b3 * 455 + pmaddwd m1, m2 + paddusw m4, m2 + paddusw m5, m2 + psrad m3, m4, 20 ; min(z3, 255) - 256 + vpgatherdd m2, [r12+m3*4], m4 ; x3 + psrad m4, m5, 20 + vpgatherdd m3, [r12+m4*4], m5 + vpbroadcastd m4, [base+pd_34816] + pmulld m0, m2 + vpbroadcastd m8, [base+pd_m4096] + pmulld m1, m3 + paddd m0, m4 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m4 + pand m0, m8 + pand m8, m1 + por m0, m2 ; a3 | (b3 << 12) + por m8, m3 + mova m4, [t3+r10*4+400*8+ 8] + mova m5, [t3+r10*4+400*0+ 8] + mova m6, [t3+r10*4+400*0+40] + paddw m1, m4, [t2+r10*2+400*0] + paddd m2, m5, [t2+r10*2+400*2] + paddd m3, m6, [t2+r10*2+400*4] + paddw m1, [t1+r10*2+400*0] + paddd m2, [t1+r10*2+400*2] + paddd m3, [t1+r10*2+400*4] + mova [t2+r10*2+400*0], m4 + mova [t2+r10*2+400*2], m5 + mova [t2+r10*2+400*4], m6 + vpbroadcastd m4, [base+pd_25] + mova [t3+r10*4+400*8+ 8], xm0 + vextracti128 [t3+r10*4+400*8+40], m0, 1 + mova [t3+r10*4+400*8+24], xm8 + vextracti128 [t3+r10*4+400*8+56], m8, 1 + punpcklwd m0, m1, m7 ; b5 + punpckhwd m1, m7 + pmulld m2, m4 ; a5 * 25 + pmulld m3, m4 + pmaddwd m4, m0, m0 ; b5 * b5 + pmaddwd m5, m1, m1 + psubd m2, m4 ; p5 + vpbroadcastd m4, [base+pd_0xf00800a4] + psubd m3, m5 + pmulld m2, m13 ; p5 * s0 + pmulld m3, m13 + pmaddwd m0, m4 ; b5 * 164 + pmaddwd m1, m4 + paddusw m2, m4 + paddusw m3, m4 + psrad m5, m2, 20 ; min(z5, 255) - 256 + vpgatherdd m4, [r12+m5*4], m2 ; x5 + psrad m2, m3, 20 + vpgatherdd m5, [r12+m2*4], m3 + pmulld m0, m4 + vpbroadcastd m6, [base+pd_34816] + pmulld m1, m5 + paddd m0, m6 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m6 + vpbroadcastd m6, [base+pd_m4096] + pand m0, m6 + pand m1, m6 + por m0, m4 ; a5 | (b5 << 12) + por m1, m5 + mova [t3+r10*4+400*0+ 8], xm0 + vextracti128 [t3+r10*4+400*0+40], m0, 1 + mova [t3+r10*4+400*0+24], xm1 + vextracti128 [t3+r10*4+400*0+56], m1, 1 + add r10, 16 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t3+r10*4+400*0+4] + paddd m1, m0, [t3+r10*4+400*0+0] + mova m4, [t3+r10*4+400*4+0] + paddd m1, [t3+r10*4+400*0+8] + mova m5, [t3+r10*4+400*8+0] + paddd m4, [t3+r10*4+400*4+8] + paddd m5, [t3+r10*4+400*8+8] + paddd m2, m4, [t3+r10*4+400*4+4] + paddd m3, m5, [t3+r10*4+400*8+4] + paddd m0, m1 + pslld m1, 2 + pslld m2, 2 + paddd m1, m0 ; ab5 565 + paddd m3, m3 ; ab3[ 0] 222 + psubd m2, m4 ; ab3[-1] 343 + mova [t3+r10*4+400*20], m3 + pandn m0, m6, m1 ; a5 565 + mova [t3+r10*4+400*24], m2 + psrld m1, 12 ; b5 565 + mova [t3+r10*4+400*12], m0 + paddd m3, m3 + mova [t3+r10*4+400*16], m1 + psubd m3, m5 ; ab3[ 0] 343 + mova [t3+r10*4+400*28], m3 + add r10, 8 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m0, [t3+r10*4+4] + paddd m4, m0, [t3+r10*4+0] + paddd m4, [t3+r10*4+8] + paddd m0, m4 + pslld m4, 2 + paddd m4, m0 + pandn m0, m6, m4 + psrld m4, 12 + paddd m2, m0, [t3+r10*4+400*12] ; a5 + mova [t3+r10*4+400*12], m0 + paddd m0, m4, [t3+r10*4+400*16] ; b5 + (1 << 8) + mova [t3+r10*4+400*16], m4 + mova m3, [t3+r10*4+400*4+0] + paddd m3, [t3+r10*4+400*4+8] + paddd m5, m3, [t3+r10*4+400*4+4] + paddd m5, m5 ; ab3[ 1] 222 + mova m4, [t3+r10*4+400*20] + paddd m1, m4, [t3+r10*4+400*24] ; ab3[ 0] 222 + ab3[-1] 343 + mova [t3+r10*4+400*20], m5 + paddd m5, m5 + psubd m5, m3 ; ab3[ 1] 343 + mova [t3+r10*4+400*24], m5 + paddd m4, m5 ; ab3[ 0] 222 + ab3[ 1] 343 + pandn m3, m6, m1 + psrld m1, 12 + pandn m5, m6, m4 + psrld m4, 12 + paddd m3, m5 ; a3 + paddd m1, m4 ; b3 + (1 << 8) + pmovzxbd m4, [dstq+r10] + pmaddwd m2, m4 ; a5 * src + pmaddwd m3, m4 ; a3 * src + psubd m0, m2 ; b5 - a5 * src + (1 << 8) + psubd m1, m3 ; b3 - a3 * src + (1 << 8) + psrld m0, 9 + pslld m1, 7 + pblendw m0, m1, 0xaa + pmaddwd m0, m15 + psubd m0, m6 + psrad m0, 13 + paddd m0, m4 + vextracti128 xm1, m0, 1 + packssdw xm0, xm1 + packuswb xm0, xm0 + movq [dstq+r10], xm0 + add r10, 8 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m3, [t3+r10*4+400*8+0] + paddd m3, [t3+r10*4+400*8+8] + paddd m5, m3, [t3+r10*4+400*8+4] + paddd m5, m5 ; ab3[ 1] 222 + mova m4, [t3+r10*4+400*20] + paddd m1, m4, [t3+r10*4+400*28] ; ab3[ 0] 222 + ab3[-1] 343 + mova [t3+r10*4+400*20], m5 + paddd m5, m5 + psubd m5, m3 ; ab3[ 1] 343 + mova [t3+r10*4+400*28], m5 + paddd m4, m5 ; ab3[ 0] 222 + ab3[ 1] 343 + pandn m3, m6, m1 + psrld m1, 12 + pandn m5, m6, m4 + psrld m4, 12 + paddd m3, m5 ; -a3 + paddd m1, m4 ; b3 + (1 << 8) + pmovzxbd m4, [dstq+r10] + pmaddwd m2, m4, [t3+r10*4+400*12] ; -a5 * src + mova m0, [t3+r10*4+400*16] ; b5 + (1 << 7) + pmaddwd m3, m4 ; -a3 * src + psubd m0, m2 ; a5 * src + b5 + (1 << 7) + psubd m1, m3 ; a3 * src + b3 + (1 << 8) + psrld m0, 8 + pslld m1, 7 + pblendw m0, m1, 0xaa + pmaddwd m0, m15 + psubd m0, m6 + psrad m0, 13 + paddd m0, m4 + vextracti128 xm1, m0, 1 + packssdw xm0, xm1 + packuswb xm0, xm0 + movq [dstq+r10], xm0 + add r10, 8 + jl .n1_loop + add dstq, strideq + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2122 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +wiener_shufA: db 1, 2, 7, 6, 3, 4, 9, 8, 5, 6, 11, 10, 7, 8, 13, 12 +wiener_shufB: db 2, 3, 8, 7, 4, 5, 10, 9, 6, 7, 12, 11, 8, 9, 14, 13 +wiener_shufC: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11 +wiener_shufD: db 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12 +wiener_perm32: db 1, 9, 3, 11, 5, 13, 7, 15, 33, 41, 35, 43, 37, 45, 39, 47 + db 17, 25, 19, 27, 21, 29, 23, 31, 49, 57, 51, 59, 53, 61, 55, 63 +sgr_shuf: db 128, 1, -1, 2,132, 3, -1, 4,136, 5, -1, 6,140, 7, -1, 8 + db 129, 9, -1, 10,133, 11, -1, 12,137, -1, -1, -1,141, -1, 0,128 +sgr_mix_perm: db 1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, 49, 51, 53, 55 +r_ext_mask: times 68 db -1 + times 4 db 0 +wiener_x_shuf: db 0, 2, -1, 0 +wiener_x_add: db 0, 1,127, 0 + +pw_61448: times 2 dw 61448 +pw_164_455: dw 164, 455 +pd_m16380: dd -16380 +pd_m4096: dd -4096 +pd_m25 dd -25 +pd_m9: dd -9 +pd_34816: dd 34816 +pd_8421376: dd 8421376 + +cextern sgr_x_by_x + +SECTION .text + +DECLARE_REG_TMP 8, 7, 9, 11, 12, 13, 14 ; ring buffer pointers + +INIT_ZMM avx512icl +cglobal wiener_filter7_8bpc, 4, 15, 20, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt + mov fltq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + vbroadcasti32x4 m6, [wiener_shufA] + vbroadcasti32x4 m7, [wiener_shufB] + mov r10d, 0xfffe + vbroadcasti32x4 m8, [wiener_shufC] + vbroadcasti32x4 m9, [wiener_shufD] + kmovw k1, r10d + vpbroadcastd m0, [wiener_x_shuf] + vpbroadcastd m1, [wiener_x_add] + mov r10, 0xaaaaaaaaaaaaaaaa + vpbroadcastd m11, [fltq+ 0] + vpbroadcastd m12, [fltq+ 4] + kmovq k2, r10 + vpbroadcastd m10, [pd_m16380] + packsswb m11, m11 ; x0 x1 x0 x1 + vpbroadcastd m14, [fltq+16] + pshufb m12, m0 + vpbroadcastd m15, [fltq+20] + paddb m12, m1 ; x2 x3+1 x2 127 + vpbroadcastd m13, [pd_8421376] + psllw m14, 5 ; y0 y1 + psllw m15, 5 ; y2 y3 + cmp wd, 32 ; the minimum lr unit size for chroma in 4:2:0 is 32 + jle .w32 ; pixels, so we need a special case for small widths + lea t1, [rsp+wq*2+16] + add lpfq, wq + add dstq, wq + neg wq + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 384*2 + add r10, strideq + mov [rsp], r10 ; below + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call .v + RET +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call .v +.v2: + call .v + jmp .v1 +.h: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm16, [leftq] + vmovdqu32 m16{k1}, [lpfq+r10-4] + add leftq, 4 + jmp .h_main +.h_extend_left: + vpbroadcastb xm16, [lpfq+r10] ; the masked load ensures that no exception + vmovdqu32 m16{k1}, [lpfq+r10-4] ; gets raised from accessing invalid memory + jmp .h_main +.h_top: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m16, [lpfq+r10-4] +.h_main: + movu m17, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -66 + jl .h_have_right + push r0 + lea r0, [r_ext_mask+65] + vpbroadcastb m0, [lpfq-1] + vpternlogd m16, m0, [r0+r10+0], 0xe4 ; c ? a : b + vpternlogd m17, m0, [r0+r10+8], 0xe4 + pop r0 +.h_have_right: + pshufb m4, m16, m6 + mova m0, m10 + vpdpbusd m0, m4, m11 + pshufb m4, m16, m7 + mova m2, m10 + vpdpbusd m2, m4, m11 + pshufb m4, m17, m6 + mova m1, m10 + vpdpbusd m1, m4, m11 + pshufb m4, m17, m7 + mova m3, m10 + vpdpbusd m3, m4, m11 + pshufb m4, m16, m8 + vpdpbusd m0, m4, m12 + pshufb m16, m9 + vpdpbusd m2, m16, m12 + pshufb m4, m17, m8 + vpdpbusd m1, m4, m12 + pshufb m17, m9 + vpdpbusd m3, m17, m12 + packssdw m0, m2 + packssdw m1, m3 + psraw m0, 3 + psraw m1, 3 + mova [t1+r10*2+ 0], m0 + mova [t1+r10*2+64], m1 + add r10, 64 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm16, [leftq] + vmovdqu32 m16{k1}, [lpfq+r10-4] + add leftq, 4 + jmp .hv_main +.hv_extend_left: + vpbroadcastb xm16, [lpfq+r10] + vmovdqu32 m16{k1}, [lpfq+r10-4] + jmp .hv_main +.hv_bottom: + mov r10, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m16, [lpfq+r10-4] +.hv_main: + movu m17, [lpfq+r10+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -66 + jl .hv_have_right + push r0 + lea r0, [r_ext_mask+65] + vpbroadcastb m0, [lpfq-1] + vpternlogd m16, m0, [r0+r10+0], 0xe4 ; c ? a : b + vpternlogd m17, m0, [r0+r10+8], 0xe4 + pop r0 +.hv_have_right: + pshufb m4, m16, m6 + mova m0, m10 + vpdpbusd m0, m4, m11 + pshufb m4, m16, m7 + mova m2, m10 + vpdpbusd m2, m4, m11 + pshufb m4, m17, m6 + mova m1, m10 + vpdpbusd m1, m4, m11 + pshufb m4, m17, m7 + mova m3, m10 + vpdpbusd m3, m4, m11 + pshufb m4, m16, m8 + vpdpbusd m0, m4, m12 + pshufb m16, m9 + vpdpbusd m2, m16, m12 + pshufb m4, m17, m8 + vpdpbusd m1, m4, m12 + pshufb m17, m9 + vpdpbusd m3, m17, m12 + packssdw m0, m2 + packssdw m1, m3 + psraw m0, 3 + psraw m1, 3 + mova m16, [t4+r10*2] + paddw m16, [t2+r10*2] + mova m3, [t3+r10*2] + mova m17, [t4+r10*2+64] + paddw m17, [t2+r10*2+64] + mova m5, [t3+r10*2+64] + punpcklwd m4, m16, m3 + mova m2, m13 + vpdpwssd m2, m4, m15 + punpcklwd m18, m17, m5 + mova m4, m13 + vpdpwssd m4, m18, m15 + punpckhwd m16, m3 + mova m3, m13 + vpdpwssd m3, m16, m15 + punpckhwd m17, m5 + mova m5, m13 + vpdpwssd m5, m17, m15 + mova m17, [t5+r10*2] + paddw m17, [t1+r10*2] + paddw m16, m0, [t6+r10*2] + mova m19, [t5+r10*2+64] + paddw m19, [t1+r10*2+64] + paddw m18, m1, [t6+r10*2+64] + mova [t0+r10*2+ 0], m0 + mova [t0+r10*2+64], m1 + punpcklwd m0, m16, m17 + vpdpwssd m2, m0, m14 + punpcklwd m1, m18, m19 + vpdpwssd m4, m1, m14 + punpckhwd m16, m17 + vpdpwssd m3, m16, m14 + punpckhwd m18, m19 + vpdpwssd m5, m18, m14 + packuswb m2, m4 + psrlw m2, 8 + vpackuswb m2{k2}, m3, m5 + movu [dstq+r10], m2 ; We don't have a separate 5-tap version so the 7-tap + add r10, 64 ; function is used for chroma as well, and in some + jl .hv_loop ; esoteric edge cases chroma dst pointers may only + mov t6, t5 ; have a 32-byte alignment despite having a width + mov t5, t4 ; larger than 32, so use an unaligned store here. + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 + add dstq, strideq + ret +.v: + mov r10, wq +.v_loop: + mova m4, [t4+r10*2+ 0] + paddw m4, [t2+r10*2+ 0] + mova m1, [t3+r10*2+ 0] + mova m5, [t4+r10*2+64] + paddw m5, [t2+r10*2+64] + mova m3, [t3+r10*2+64] + punpcklwd m6, m4, m1 + mova m0, m13 + vpdpwssd m0, m6, m15 + punpcklwd m6, m5, m3 + mova m2, m13 + vpdpwssd m2, m6, m15 + punpckhwd m4, m1 + mova m1, m13 + vpdpwssd m1, m4, m15 + punpckhwd m5, m3 + mova m3, m13 + vpdpwssd m3, m5, m15 + mova m5, [t1+r10*2+ 0] + paddw m4, m5, [t6+r10*2+ 0] + paddw m5, [t5+r10*2+ 0] + mova m7, [t1+r10*2+64] + paddw m6, m7, [t6+r10*2+64] + paddw m7, [t5+r10*2+64] + punpcklwd m8, m4, m5 + vpdpwssd m0, m8, m14 + punpcklwd m8, m6, m7 + vpdpwssd m2, m8, m14 + punpckhwd m4, m5 + vpdpwssd m1, m4, m14 + punpckhwd m6, m7 + vpdpwssd m3, m6, m14 + packuswb m0, m2 + psrlw m0, 8 + vpackuswb m0{k2}, m1, m3 + movu [dstq+r10], m0 + add r10, 64 + jl .v_loop + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq + ret +.w32: + lea r10, [r_ext_mask+73] + mova ym18, [wiener_perm32] + lea t1, [rsp+16] + sub r10, wq + test edgeb, 4 ; LR_HAVE_TOP + jz .w32_no_top + call .w32_h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 32*2 + call .w32_h_top + lea r9, [lpfq+strideq*4] + mov lpfq, dstq + mov t4, t1 + add t1, 32*2 + add r9, strideq + mov [rsp], r9 ; below + call .w32_h + mov t3, t1 + mov t2, t1 + dec hd + jz .w32_v1 + add lpfq, strideq + add t1, 32*2 + call .w32_h + mov t2, t1 + dec hd + jz .w32_v2 + add lpfq, strideq + add t1, 32*2 + call .w32_h + dec hd + jz .w32_v3 +.w32_main: + lea t0, [t1+32*2] +.w32_main_loop: + call .w32_hv + dec hd + jnz .w32_main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .w32_v3 + mov lpfq, [rsp] + call .w32_hv_bottom + add lpfq, strideq + call .w32_hv_bottom +.w32_v1: + call .w32_v + RET +.w32_no_top: + lea r9, [lpfq+strideq*4] + mov lpfq, dstq + lea r9, [r9+strideq*2] + mov [rsp], r9 + call .w32_h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .w32_v1 + add lpfq, strideq + add t1, 32*2 + call .w32_h + mov t2, t1 + dec hd + jz .w32_v2 + add lpfq, strideq + add t1, 32*2 + call .w32_h + dec hd + jz .w32_v3 + lea t0, [t1+32*2] + call .w32_hv + dec hd + jz .w32_v3 + add t0, 32*8 + call .w32_hv + dec hd + jnz .w32_main +.w32_v3: + call .w32_v +.w32_v2: + call .w32_v + jmp .w32_v1 +.w32_h: + test edgeb, 1 ; LR_HAVE_LEFT + jz .w32_h_extend_left + movd xm16, [leftq] + vmovdqu32 ym16{k1}, [lpfq-4] + add leftq, 4 + jmp .w32_h_main +.w32_h_extend_left: + vpbroadcastb xm16, [lpfq] ; the masked load ensures that no exception + vmovdqu32 ym16{k1}, [lpfq-4] ; gets raised from accessing invalid memory + jmp .w32_h_main +.w32_h_top: + test edgeb, 1 ; LR_HAVE_LEFT + jz .w32_h_extend_left + movu ym16, [lpfq-4] +.w32_h_main: + vinserti32x8 m16, [lpfq+4], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .w32_h_have_right + vpbroadcastb m0, [lpfq+wq-1] + movu ym17, [r10-8] + vinserti32x8 m17, [r10+0], 1 + vpternlogd m16, m0, m17, 0xe4 ; c ? a : b +.w32_h_have_right: + pshufb m2, m16, m6 + mova m0, m10 + vpdpbusd m0, m2, m11 + pshufb m2, m16, m7 + mova m1, m10 + vpdpbusd m1, m2, m11 + pshufb m2, m16, m8 + vpdpbusd m0, m2, m12 + pshufb m16, m9 + vpdpbusd m1, m16, m12 + packssdw m0, m1 + psraw m0, 3 + mova [t1], m0 + ret +.w32_hv: + add lpfq, strideq + test edgeb, 1 ; LR_HAVE_LEFT + jz .w32_hv_extend_left + movd xm16, [leftq] + vmovdqu32 ym16{k1}, [lpfq-4] + add leftq, 4 + jmp .w32_hv_main +.w32_hv_extend_left: + vpbroadcastb xm16, [lpfq] + vmovdqu32 ym16{k1}, [lpfq-4] + jmp .w32_hv_main +.w32_hv_bottom: + test edgeb, 1 ; LR_HAVE_LEFT + jz .w32_hv_extend_left + movu ym16, [lpfq-4] +.w32_hv_main: + vinserti32x8 m16, [lpfq+4], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .w32_hv_have_right + vpbroadcastb m0, [lpfq+wq-1] + movu ym17, [r10-8] + vinserti32x8 m17, [r10+0], 1 + vpternlogd m16, m0, m17, 0xe4 +.w32_hv_have_right: + mova m3, [t4] + paddw m3, [t2] + mova m2, [t3] + pshufb m4, m16, m6 + mova m0, m10 + vpdpbusd m0, m4, m11 + pshufb m4, m16, m7 + mova m5, m10 + vpdpbusd m5, m4, m11 + punpcklwd m4, m3, m2 + mova m1, m13 + vpdpwssd m1, m4, m15 + punpckhwd m3, m2 + mova m2, m13 + vpdpwssd m2, m3, m15 + pshufb m4, m16, m8 + vpdpbusd m0, m4, m12 + pshufb m16, m9 + vpdpbusd m5, m16, m12 + packssdw m0, m5 + psraw m0, 3 + mova m4, [t5] + paddw m4, [t1] + paddw m3, m0, [t6] + mova [t0], m0 + punpcklwd m0, m3, m4 + vpdpwssd m1, m0, m14 + punpckhwd m3, m4 + vpdpwssd m2, m3, m14 + packuswb m1, m2 + vpermb m16, m18, m1 + mova [dstq], ym16 + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 + add dstq, strideq + ret +.w32_v: + mova m2, [t4] + paddw m2, [t2] + mova m1, [t3] + mova m4, [t1] + paddw m3, m4, [t6] + paddw m4, [t5] + punpcklwd m5, m2, m1 + mova m0, m13 + vpdpwssd m0, m5, m15 + punpckhwd m2, m1 + mova m1, m13 + vpdpwssd m1, m2, m15 + punpcklwd m2, m3, m4 + vpdpwssd m0, m2, m14 + punpckhwd m3, m4 + vpdpwssd m1, m3, m14 + packuswb m0, m1 + vpermb m16, m18, m0 + mova [dstq], ym16 + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + add dstq, strideq + ret + +cglobal sgr_filter_5x5_8bpc, 4, 13, 23, 416*24+16, dst, stride, left, lpf, \ + w, h, edge, params + mov paramsq, r6mp + mov wd, wm + mov hd, hm + mov edged, r7m + vbroadcasti32x4 m5, [sgr_shuf+1] + add lpfq, wq + vbroadcasti32x4 m6, [sgr_shuf+9] + add dstq, wq + vbroadcasti32x4 m7, [sgr_shuf+3] + lea t3, [rsp+wq*4+16+416*12] + vbroadcasti32x4 m8, [sgr_shuf+7] + pxor m4, m4 + vpbroadcastd m9, [pd_m25] + vpsubd m11, m4, [paramsq+0] {1to16} ; -s0 + vpbroadcastw m15, [paramsq+8] ; w0 + lea t1, [rsp+wq*2+20] + vpbroadcastd m10, [pw_164_455] + neg wq + vpbroadcastd m12, [pw_61448] ; (15 << 12) + (1 << 3) + mov r10d, 0xfe + vpbroadcastd m13, [pd_m4096] + kmovb k1, r10d + vpbroadcastd m14, [pd_34816] ; (1 << 11) + (1 << 15) + mov r10, 0x3333333333333333 + mova m18, [sgr_x_by_x+64*0] + kmovq k2, r10 + mova m19, [sgr_x_by_x+64*1] + lea r12, [r_ext_mask+75] + mova m20, [sgr_x_by_x+64*2] + psllw m15, 4 + mova m21, [sgr_x_by_x+64*3] + lea r10, [lpfq+strideq*4] + mova ym22, [sgr_shuf] + add r10, strideq + mov [rsp], r10 ; below + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call .top_fixup + add t1, 416*6 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, strideq + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + test hd, hd + jz .odd_height + call .h + add lpfq, strideq + call .hv + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .h_top + add lpfq, strideq + call .hv_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + call .n0 + call .n1 +.odd_height_end: + call .v + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+416*6] + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + jmp .main +.no_top_height1: + call .v + call .prep_n + jmp .odd_height_end +.h: ; horizontal boxsum + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .h_main +.h_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu ym17, [lpfq+r10-2] +.h_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -34 + jl .h_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r12+r10-8] + vinserti32x8 m16, [r12+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.h_have_right: + pshufb m3, m17, m5 + pmullw m2, m3, m3 + pshufb m1, m17, m6 + paddw m0, m3, m1 + shufps m3, m1, q2121 + paddw m0, m3 + punpcklwd m16, m3, m1 + punpckhwd m3, m1 + punpcklwd m1, m2, m4 + vpdpwssd m1, m16, m16 + punpckhwd m2, m4 + vpdpwssd m2, m3, m3 + pshufb m16, m17, m7 + paddw m0, m16 + pshufb m17, m8 + paddw m0, m17 ; sum + punpcklwd m3, m16, m17 + vpdpwssd m1, m3, m3 ; sumsq + punpckhwd m16, m17 + vpdpwssd m2, m16, m16 + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+r10*2+416*0] + paddd m1, [t1+r10*2+416*2] + paddd m2, [t1+r10*2+416*4] +.h_loop_end: + mova [t1+r10*2+416*0], m0 + mova [t1+r10*2+416*2], m1 + mova [t1+r10*2+416*4], m2 + add r10, 32 + jl .h_loop + ret +.top_fixup: + lea r10, [wq-2] +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+r10*2+416*0] + mova m1, [t1+r10*2+416*2] + mova m2, [t1+r10*2+416*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+r10*2+416*0], m0 + mova [t2+r10*2+416*2], m1 + mova [t2+r10*2+416*4], m2 + add r10, 32 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .hv_main +.hv_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .hv_main +.hv_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu ym17, [lpfq+r10-2] +.hv_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -34 + jl .hv_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r12+r10-8] + vinserti32x8 m16, [r12+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.hv_have_right: + pshufb m1, m17, m5 + pmullw m3, m1, m1 + pshufb m2, m17, m6 + paddw m0, m1, m2 + shufps m1, m2, q2121 + paddw m0, m1 + punpcklwd m16, m1, m2 + punpckhwd m1, m2 + punpcklwd m2, m3, m4 + vpdpwssd m2, m16, m16 + punpckhwd m3, m4 + vpdpwssd m3, m1, m1 + pshufb m16, m17, m7 + paddw m0, m16 + pshufb m17, m8 + paddw m0, m17 ; h sum + punpcklwd m1, m16, m17 + vpdpwssd m2, m1, m1 ; h sumsq + punpckhwd m16, m17 + vpdpwssd m3, m16, m16 + paddw m1, m0, [t1+r10*2+416*0] + paddd m16, m2, [t1+r10*2+416*2] + paddd m17, m3, [t1+r10*2+416*4] + test hd, hd + jz .hv_last_row +.hv_main2: + paddd m16, [t2+r10*2+416*2] ; hv sumsq + paddd m17, [t2+r10*2+416*4] + paddw m1, [t2+r10*2+416*0] ; hv sum + mova [t0+r10*2+416*2], m2 + mova [t0+r10*2+416*4], m3 + mova [t0+r10*2+416*0], m0 + pmulld m16, m9 ; -a * 25 + pmulld m17, m9 + punpcklwd m0, m1, m4 ; b + vpdpwssd m16, m0, m0 ; -p + punpckhwd m1, m4 + vpdpwssd m17, m1, m1 + pmaddwd m0, m10 ; b * 164 + pmaddwd m1, m10 + pmulld m16, m11 ; p * s + pmulld m17, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddd m0, m14 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m14 + vpternlogd m16, m0, m13, 0xd8 ; a | (b << 12) + vpternlogd m17, m1, m13, 0xd8 + mova [t3+r10*4+ 8], m16 ; The neighbor calculations requires + mova [t3+r10*4+ 24], xm17 ; 13 bits for a and 21 bits for b. + vextracti32x4 [t3+r10*4+ 56], m17, 2 ; Packing them allows for 12+20, but + mova [t3+r10*4+ 72], m17 ; that gets us most of the way. + vextracti128 [t3+r10*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+104], m16, 3 + add r10, 32 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+r10*2+416*0], m1 + paddw m1, m0 + mova [t1+r10*2+416*2], m16 + paddd m16, m2 + mova [t1+r10*2+416*4], m17 + paddd m17, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab + lea r10, [wq-2] +.v_loop: + mova m2, [t1+r10*2+416*2] + paddd m16, m2, [t2+r10*2+416*2] + mova m3, [t1+r10*2+416*4] + paddd m17, m3, [t2+r10*2+416*4] + paddd m2, m2 + paddd m3, m3 + paddd m16, m2 ; hv sumsq + paddd m17, m3 + pmulld m16, m9 ; -a * 25 + pmulld m17, m9 + mova m0, [t1+r10*2+416*0] + paddw m1, m0, [t2+r10*2+416*0] + paddw m0, m0 + paddw m1, m0 ; hv sum + punpcklwd m0, m1, m4 ; b + vpdpwssd m16, m0, m0 ; -p + punpckhwd m1, m4 + vpdpwssd m17, m1, m1 + pmaddwd m0, m10 ; b * 164 + pmaddwd m1, m10 + pmulld m16, m11 ; p * s + pmulld m17, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddd m0, m14 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m14 + vpternlogd m16, m0, m13, 0xd8 ; a | (b << 12) + vpternlogd m17, m1, m13, 0xd8 + mova [t3+r10*4+ 8], m16 + mova [t3+r10*4+ 24], xm17 + vextracti32x4 [t3+r10*4+ 56], m17, 2 + mova [t3+r10*4+ 72], m17 + vextracti128 [t3+r10*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+104], m16, 3 + add r10, 32 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t3+r10*4+ 4] + movu m1, [t3+r10*4+68] + paddd m2, m0, [t3+r10*4+ 0] + paddd m3, m1, [t3+r10*4+64] + paddd m2, [t3+r10*4+ 8] + paddd m3, [t3+r10*4+72] + paddd m0, m2 + pslld m2, 2 + paddd m1, m3 + pslld m3, 2 + paddd m2, m0 ; ab 565 + paddd m3, m1 + pandn m0, m13, m2 ; a + psrld m2, 12 ; b + pandn m1, m13, m3 + psrld m3, 12 + mova [t3+r10*4+416*4+ 0], m0 + mova [t3+r10*4+416*8+ 0], m2 + mova [t3+r10*4+416*4+64], m1 + mova [t3+r10*4+416*8+64], m3 + add r10, 32 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m16, [t3+r10*4+ 4] + movu m17, [t3+r10*4+68] + paddd m0, m16, [t3+r10*4+ 0] + paddd m1, m17, [t3+r10*4+64] + paddd m0, [t3+r10*4+ 8] + paddd m1, [t3+r10*4+72] + paddd m16, m0 + pslld m0, 2 + paddd m17, m1 + pslld m1, 2 + paddd m0, m16 + paddd m1, m17 + pandn m16, m13, m0 + psrld m0, 12 + pandn m17, m13, m1 + psrld m1, 12 + paddd m2, m16, [t3+r10*4+416*4+ 0] ; a + paddd m3, m17, [t3+r10*4+416*4+64] + mova [t3+r10*4+416*4+ 0], m16 + mova [t3+r10*4+416*4+64], m17 + paddd m16, m0, [t3+r10*4+416*8+ 0] ; b + (1 << 8) + paddd m17, m1, [t3+r10*4+416*8+64] + mova [t3+r10*4+416*8+ 0], m0 + mova [t3+r10*4+416*8+64], m1 + pmovzxbd m0, [dstq+r10+ 0] + pmovzxbd m1, [dstq+r10+16] + pmaddwd m2, m0 ; a * src + pmaddwd m3, m1 + packssdw m0, m1 + psubd m16, m2 ; b - a * src + (1 << 8) + psubd m17, m3 + psrad m16, 9 + psrad m17, 9 + packssdw m16, m17 + pmulhrsw m16, m15 + paddw m16, m0 + packuswb m16, m16 + vpermd m16, m22, m16 + mova [dstq+r10], ym16 + add r10, 32 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + pmovzxbd m0, [dstq+r10+ 0] + pmovzxbd m1, [dstq+r10+16] + pmaddwd m2, m0, [t3+r10*4+416*4+ 0] ; a * src + pmaddwd m3, m1, [t3+r10*4+416*4+64] + mova m16, [t3+r10*4+416*8+ 0] ; b + (1 << 7) + mova m17, [t3+r10*4+416*8+64] + packssdw m0, m1 + psubd m16, m2 ; b - a * src + (1 << 7) + psubd m17, m3 + psrad m16, 8 + psrad m17, 8 + packssdw m16, m17 + pmulhrsw m16, m15 + paddw m16, m0 + packuswb m16, m16 + vpermd m16, m22, m16 + mova [dstq+r10], ym16 + add r10, 32 + jl .n1_loop + add dstq, strideq + ret + +cglobal sgr_filter_3x3_8bpc, 4, 15, 22, -416*28-16, dst, stride, left, lpf, \ + w, h, edge, params + mov paramsq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + vbroadcasti32x4 m5, [sgr_shuf+3] + add lpfq, wq + vbroadcasti32x4 m6, [sgr_shuf+5] + add dstq, wq + vbroadcasti32x4 m7, [sgr_shuf+7] + pxor m4, m4 + vpbroadcastd m8, [pd_m9] + vpsubd m11, m4, [paramsq+4] {1to16} ; -s1 + vpbroadcastw m15, [paramsq+10] ; w1 + lea t1, [rsp+wq*2+20] + vpbroadcastd m10, [pw_164_455] + lea t3, [rsp+wq*4+16+416*12] + vpbroadcastd m12, [pw_61448] ; (15 << 12) + (1 << 3) + neg wq + vpbroadcastd m13, [pd_m4096] + mov r10d, 0xfe + vpbroadcastd m14, [pd_34816] ; (1 << 11) + (1 << 15) + kmovb k1, r10d + mova m18, [sgr_x_by_x+64*0] + mov r10, 0x3333333333333333 + mova m19, [sgr_x_by_x+64*1] + kmovq k2, r10 + mova m20, [sgr_x_by_x+64*2] + psllw m15, 4 + mova m21, [sgr_x_by_x+64*3] + lea r14, [r_ext_mask+75] + mova ym9, [sgr_shuf] + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + add t1, 416*6 + call .h_top + lea t4, [lpfq+strideq*4] + mov lpfq, dstq + add t4, strideq + mov [rsp], t4 ; below + mov t0, t2 + call .hv +.main: + mov t5, t3 + add t3, 416*4 + dec hd + jz .height1 + add lpfq, strideq + call .hv + call .prep_n + dec hd + jz .extend_bottom +.main_loop: + add lpfq, strideq + call .hv + call .n + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv_bottom + call .n + add lpfq, strideq + call .hv_bottom +.end: + call .n + RET +.height1: + call .v + call .prep_n + mov t2, t1 + call .v + jmp .end +.extend_bottom: + call .v + call .n + mov t2, t1 + call .v + jmp .end +.no_top: + lea t4, [lpfq+strideq*4] + mov lpfq, dstq + lea t4, [t4+strideq*2] + mov [rsp], t4 + call .h + lea t0, [t1+416*6] + mov t2, t1 + call .v + jmp .main +.h: ; horizontal boxsum + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .h_main +.h_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu ym17, [lpfq+r10-2] +.h_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -33 + jl .h_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r14+r10-8] + vinserti32x8 m16, [r14+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.h_have_right: + pshufb m0, m17, m5 + pmullw m2, m0, m0 + pshufb m16, m17, m6 + paddw m0, m16 + pshufb m17, m7 + paddw m0, m17 ; sum + punpcklwd m3, m16, m17 + punpcklwd m1, m2, m4 + vpdpwssd m1, m3, m3 ; sumsq + punpckhwd m16, m17 + punpckhwd m2, m4 + vpdpwssd m2, m16, m16 + mova [t1+r10*2+416*0], m0 + mova [t1+r10*2+416*2], m1 + mova [t1+r10*2+416*4], m2 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .hv_main +.hv_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .hv_main +.hv_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu ym17, [lpfq+r10-2] +.hv_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp r10d, -33 + jl .hv_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r14+r10-8] + vinserti32x8 m16, [r14+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.hv_have_right: + pshufb m0, m17, m5 + pmullw m3, m0, m0 + pshufb m1, m17, m6 + paddw m0, m1 + pshufb m17, m7 + paddw m0, m17 ; h sum + punpcklwd m16, m17, m1 + punpcklwd m2, m3, m4 + vpdpwssd m2, m16, m16 ; h sumsq + punpckhwd m17, m1 + punpckhwd m3, m4 + vpdpwssd m3, m17, m17 + paddw m1, m0, [t2+r10*2+416*0] + paddw m1, [t1+r10*2+416*0] ; hv sum + paddd m16, m2, [t2+r10*2+416*2] + paddd m17, m3, [t2+r10*2+416*4] + paddd m16, [t1+r10*2+416*2] ; hv sumsq + paddd m17, [t1+r10*2+416*4] + mova [t0+r10*2+416*0], m0 + mova [t0+r10*2+416*2], m2 + mova [t0+r10*2+416*4], m3 + pmulld m16, m8 ; -a * 9 + pmulld m17, m8 + punpcklwd m0, m4, m1 ; b + vpdpwssd m16, m0, m0 ; -p + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + pmulld m16, m11 ; p * s + pmulld m17, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddd m0, m14 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m14 + vpternlogd m16, m0, m13, 0xd8 ; a | (b << 12) + vpternlogd m17, m1, m13, 0xd8 + mova [t3+r10*4+ 8], m16 + mova [t3+r10*4+ 24], xm17 + vextracti32x4 [t3+r10*4+ 56], m17, 2 + mova [t3+r10*4+ 72], m17 + vextracti128 [t3+r10*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+104], m16, 3 + add r10, 32 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + ret +.v: ; vertical boxsum + ab + lea r10, [wq-2] +.v_loop: + mova m16, [t1+r10*2+416*2] + mova m17, [t1+r10*2+416*4] + paddd m16, m16 + paddd m17, m17 + paddd m16, [t2+r10*2+416*2] ; hv sumsq + paddd m17, [t2+r10*2+416*4] + pmulld m16, m8 ; -a * 9 + pmulld m17, m8 + mova m1, [t1+r10*2+416*0] + paddw m1, m1 + paddw m1, [t2+r10*2+416*0] ; hv sum + punpcklwd m0, m4, m1 ; b + vpdpwssd m16, m0, m0 ; -p + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + pmulld m16, m11 ; p * s + pmulld m17, m11 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m20 + paddusw m17, m12 + psraw m17, 4 ; min(z, 255) - 256 + vpermt2b m16, m17, m21 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m18, m19 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x + pandn m16, m13, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddd m0, m14 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m14 + vpternlogd m16, m0, m13, 0xd8 ; a | (b << 12) + vpternlogd m17, m1, m13, 0xd8 + mova [t3+r10*4+ 8], m16 + mova [t3+r10*4+ 24], xm17 + vextracti32x4 [t3+r10*4+ 56], m17, 2 + mova [t3+r10*4+ 72], m17 + vextracti128 [t3+r10*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+104], m16, 3 + add r10, 32 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + mov r10, wq + mov t4, t3 + add t3, 416*4 +.prep_n_loop: + mova m2, [t5+r10*4+0] + mova m3, [t4+r10*4+0] + paddd m2, [t5+r10*4+8] + paddd m3, [t4+r10*4+8] + paddd m0, m2, [t5+r10*4+4] + paddd m1, m3, [t4+r10*4+4] + pslld m0, 2 + paddd m1, m1 ; ab[ 0] 222 + psubd m0, m2 ; ab[-1] 343 + mova [t3+r10*4+416*4], m1 + paddd m1, m1 + mova [t5+r10*4], m0 + psubd m1, m3 ; ab[ 0] 343 + mova [t4+r10*4], m1 + add r10, 16 + jl .prep_n_loop + ret +; a+b are packed together in a single dword, but we can't do the +; full neighbor calculations before splitting them since we don't +; have sufficient precision. The solution is to do the calculations +; in two equal halves and split a and b before doing the final sum. +ALIGN function_align +.n: ; neighbor + output + mov r10, wq +.n_loop: + mova m16, [t3+r10*4+ 0] + paddd m16, [t3+r10*4+ 8] + paddd m17, m16, [t3+r10*4+ 4] + paddd m17, m17 ; ab[+1] 222 + mova m2, [t3+r10*4+416*4+ 0] + paddd m0, m2, [t5+r10*4+ 0] ; ab[ 0] 222 + ab[-1] 343 + mova m3, [t3+r10*4+416*4+64] + paddd m1, m3, [t5+r10*4+64] + mova [t3+r10*4+416*4+ 0], m17 + paddd m17, m17 + psubd m17, m16 ; ab[+1] 343 + mova [t5+r10*4+ 0], m17 + paddd m2, m17 ; ab[ 0] 222 + ab[+1] 343 + mova m16, [t3+r10*4+64] + paddd m16, [t3+r10*4+72] + paddd m17, m16, [t3+r10*4+68] + paddd m17, m17 + mova [t3+r10*4+416*4+64], m17 + paddd m17, m17 + psubd m17, m16 + mova [t5+r10*4+64], m17 + pandn m16, m13, m0 + psrld m0, 12 + paddd m3, m17 + pandn m17, m13, m2 + psrld m2, 12 + paddd m16, m17 ; a + pandn m17, m13, m1 + psrld m1, 12 + paddd m0, m2 ; b + (1 << 8) + pandn m2, m13, m3 + psrld m3, 12 + paddd m17, m2 + pmovzxbd m2, [dstq+r10+ 0] + paddd m1, m3 + pmovzxbd m3, [dstq+r10+16] + pmaddwd m16, m2 ; a * src + pmaddwd m17, m3 + packssdw m2, m3 + psubd m0, m16 ; b - a * src + (1 << 8) + psubd m1, m17 + psrad m0, 9 + psrad m1, 9 + packssdw m0, m1 + pmulhrsw m0, m15 + paddw m0, m2 + packuswb m0, m0 + vpermd m16, m9, m0 + mova [dstq+r10], ym16 + add r10, 32 + jl .n_loop + mov r10, t5 + mov t5, t4 + mov t4, r10 + add dstq, strideq + ret + +cglobal sgr_filter_mix_8bpc, 4, 13, 28, 416*56+8, dst, stride, left, lpf, \ + w, h, edge, params + mov paramsq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + vbroadcasti128 m5, [sgr_shuf+1] + add lpfq, wq + vbroadcasti128 m6, [sgr_shuf+9] + add dstq, wq + vbroadcasti128 m7, [sgr_shuf+3] + lea t3, [rsp+wq*4+416*24+8] + vbroadcasti128 m8, [sgr_shuf+7] + pxor m4, m4 + vpbroadcastd m9, [pd_m9] + vpsubd m11, m4, [paramsq+0] {1to16} ; -s0 + vpbroadcastd m14, [pw_61448] + vpsubd m12, m4, [paramsq+4] {1to16} ; -s1 + vpbroadcastd m26, [paramsq+8] ; w0 w1 + lea t1, [rsp+wq*2+12] + vpbroadcastd m10, [pd_m25] + neg wq + vpbroadcastd m13, [pw_164_455] + mov r10d, 0xfe + vpbroadcastd m15, [pd_34816] + kmovb k1, r10d + mova m20, [sgr_x_by_x+64*0] + mov r10, 0x3333333333333333 + mova m21, [sgr_x_by_x+64*1] + kmovq k2, r10 + mova m22, [sgr_x_by_x+64*2] + lea r12, [r_ext_mask+75] + mova m23, [sgr_x_by_x+64*3] + vpbroadcastd m24, [pd_m4096] + vpbroadcastd m25, [sgr_shuf+28] ; 0x8000____ + psllw m26, 5 + mova xm27, [sgr_mix_perm] + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t2, t1 + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_avx512icl).top_fixup + add t1, 416*12 + call .h_top + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov [rsp], r10 ; below + call .hv0 +.main: + dec hd + jz .height1 + add lpfq, strideq + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + add lpfq, strideq + call .hv0 + test hd, hd + jz .odd_height + add lpfq, strideq + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, [rsp] + call .hv0_bottom + add lpfq, strideq + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov [rsp], r10 + call .h + lea t2, [t1+416*12] + lea r10, [wq-2] +.top_fixup_loop: + mova m0, [t1+r10*2+416* 0] + mova m1, [t1+r10*2+416* 2] + mova m2, [t1+r10*2+416* 4] + paddw m0, m0 + mova m3, [t1+r10*2+416* 6] + paddd m1, m1 + mova m16, [t1+r10*2+416* 8] + paddd m2, m2 + mova m17, [t1+r10*2+416*10] + mova [t2+r10*2+416* 0], m0 + mova [t2+r10*2+416* 2], m1 + mova [t2+r10*2+416* 4], m2 + mova [t2+r10*2+416* 6], m3 + mova [t2+r10*2+416* 8], m16 + mova [t2+r10*2+416*10], m17 + add r10, 32 + jl .top_fixup_loop + call .v0 + jmp .main +.h: ; horizontal boxsums + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .h_main +.h_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .h_main +.h_top: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu ym17, [lpfq+r10-2] +.h_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp r10d, -34 + jl .h_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r12+r10-8] + vinserti32x8 m16, [r12+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.h_have_right: + pshufb m3, m17, m5 + pshufb m18, m17, m6 + shufps m0, m3, m18, q2121 + pmullw m2, m0, m0 + pshufb m19, m17, m7 + paddw m0, m19 + pshufb m17, m8 + paddw m0, m17 ; sum3 + punpcklwd m16, m19, m17 + punpcklwd m1, m2, m4 + vpdpwssd m1, m16, m16 ; sumsq3 + punpckhwd m19, m17 + punpckhwd m2, m4 + vpdpwssd m2, m19, m19 + mova [t1+r10*2+416* 6], m0 + mova [t1+r10*2+416* 8], m1 + mova [t1+r10*2+416*10], m2 + punpcklwd m19, m3, m18 + paddw m0, m3 + vpdpwssd m1, m19, m19 ; sumsq5 + punpckhwd m3, m18 + paddw m0, m18 ; sum5 + vpdpwssd m2, m3, m3 + mova [t1+r10*2+416* 0], m0 + mova [t1+r10*2+416* 2], m1 + mova [t1+r10*2+416* 4], m2 + add r10, 32 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsums + vertical boxsum3 + ab3 (even rows) + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .hv0_main +.hv0_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .hv0_main +.hv0_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left +.hv0_loop: + movu ym17, [lpfq+r10-2] +.hv0_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp r10d, -34 + jl .hv0_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r12+r10-8] + vinserti32x8 m16, [r12+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.hv0_have_right: + pshufb m18, m17, m5 + pshufb m19, m17, m6 + shufps m1, m18, m19, q2121 + pmullw m3, m1, m1 + pshufb m0, m17, m7 + paddw m1, m0 + pshufb m17, m8 + paddw m1, m17 ; sum3 + punpcklwd m16, m0, m17 + punpcklwd m2, m3, m4 + vpdpwssd m2, m16, m16 ; sumsq3 + punpckhwd m0, m17 + punpckhwd m3, m4 + vpdpwssd m3, m0, m0 + paddw m0, m1, [t1+r10*2+416* 6] + paddd m16, m2, [t1+r10*2+416* 8] + paddd m17, m3, [t1+r10*2+416*10] + mova [t1+r10*2+416* 6], m1 + mova [t1+r10*2+416* 8], m2 + mova [t1+r10*2+416*10], m3 + paddw m1, m18 + paddw m1, m19 ; sum5 + mova [t3+r10*4+416*8+ 8], m1 + paddw m1, [t1+r10*2+416* 0] + mova [t1+r10*2+416* 0], m1 + punpcklwd m1, m18, m19 + vpdpwssd m2, m1, m1 ; sumsq5 + punpckhwd m18, m19 + vpdpwssd m3, m18, m18 + mova [t3+r10*4+416*0+ 8], m2 ; we need a clean copy of the last row + mova [t3+r10*4+416*0+72], m3 ; in case height is odd + paddd m2, [t1+r10*2+416* 2] + paddd m3, [t1+r10*2+416* 4] + mova [t1+r10*2+416* 2], m2 + mova [t1+r10*2+416* 4], m3 + paddw m1, m0, [t2+r10*2+416* 6] + paddd m2, m16, [t2+r10*2+416* 8] + paddd m3, m17, [t2+r10*2+416*10] + mova [t2+r10*2+416* 6], m0 + mova [t2+r10*2+416* 8], m16 + mova [t2+r10*2+416*10], m17 + pmulld m16, m2, m9 ; -a3 * 9 + pmulld m17, m3, m9 + punpcklwd m0, m4, m1 ; b3 + vpdpwssd m16, m0, m0 ; -p3 + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + pmulld m16, m12 ; p3 * s1 + pmulld m17, m12 + pmaddwd m0, m13 ; b3 * 455 + pmaddwd m1, m13 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m22 + paddusw m17, m14 + psraw m17, 4 ; min(z3, 255) - 256 + vpermt2b m16, m17, m23 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m20, m21 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x3 + pandn m16, m24, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddd m0, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m15 + vpternlogd m16, m0, m24, 0xd8 ; a3 | (b3 << 12) + vpternlogd m17, m1, m24, 0xd8 + mova [t3+r10*4+416*4+ 8], m16 + mova [t3+r10*4+416*4+ 24], xm17 + vextracti32x4 [t3+r10*4+416*4+ 56], m17, 2 + mova [t3+r10*4+416*4+ 72], m17 + vextracti128 [t3+r10*4+416*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+416*4+104], m16, 3 + add r10, 32 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movd xm17, [leftq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + add leftq, 4 + jmp .hv1_main +.hv1_extend_left: + vpbroadcastb xm17, [lpfq+wq] + vmovdqu32 ym17{k1}, [lpfq+wq-4] + jmp .hv1_main +.hv1_bottom: + lea r10, [wq-2] + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left +.hv1_loop: + movu ym17, [lpfq+r10-2] +.hv1_main: + vinserti32x8 m17, [lpfq+r10+6], 1 + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp r10d, -34 + jl .hv1_have_right + vpbroadcastb m0, [lpfq-1] + movu ym16, [r12+r10-8] + vinserti32x8 m16, [r12+r10+0], 1 + vpternlogd m17, m0, m16, 0xe4 +.hv1_have_right: + pshufb m3, m17, m5 + pshufb m19, m17, m6 + shufps m2, m3, m19, q2121 + pmullw m1, m2, m2 + pshufb m18, m17, m7 + paddw m2, m18 + pshufb m17, m8 + paddw m2, m17 ; sum3 + punpcklwd m16, m17, m18 + punpcklwd m0, m1, m4 + vpdpwssd m0, m16, m16 ; sumsq3 + punpckhwd m17, m18 + punpckhwd m1, m4 + vpdpwssd m1, m17, m17 + paddd m16, m0, [t2+r10*2+416* 8] + paddd m17, m1, [t2+r10*2+416*10] + mova [t2+r10*2+416* 8], m0 + mova [t2+r10*2+416*10], m1 + punpcklwd m18, m3, m19 + vpdpwssd m0, m18, m18 ; sumsq5 + punpckhwd m18, m3, m19 + vpdpwssd m1, m18, m18 + paddw m3, m19 + pmulld m16, m9 ; -a3 * 9 + pmulld m17, m9 + paddd m18, m0, [t2+r10*2+416*2] + paddd m19, m1, [t2+r10*2+416*4] + paddd m18, [t1+r10*2+416*2] + paddd m19, [t1+r10*2+416*4] + mova [t2+r10*2+416*2], m0 + mova [t2+r10*2+416*4], m1 + pmulld m18, m10 ; -a5 * 25 + pmulld m19, m10 + paddw m1, m2, [t2+r10*2+416* 6] + mova [t2+r10*2+416* 6], m2 + paddw m2, m3 ; sum5 + paddw m3, m2, [t2+r10*2+416*0] + paddw m3, [t1+r10*2+416*0] + mova [t2+r10*2+416*0], m2 + punpcklwd m0, m4, m1 ; b3 + vpdpwssd m16, m0, m0 ; -p3 + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + punpcklwd m2, m3, m4 ; b5 + vpdpwssd m18, m2, m2 ; -p5 + punpckhwd m3, m4 + vpdpwssd m19, m3, m3 + pmulld m16, m12 ; p3 * s1 + pmulld m17, m12 + pmulld m18, m11 ; p5 * s0 + pmulld m19, m11 + pmaddwd m0, m13 ; b3 * 455 + pmaddwd m1, m13 + pmaddwd m2, m13 ; b5 * 164 + pmaddwd m3, m13 + vpalignr m17{k2}, m16, m16, 2 + vpalignr m19{k2}, m18, m18, 2 + paddusw m17, m14 + mova m16, m22 + psraw m17, 4 ; min(z3, 255) - 256 + vpermt2b m16, m17, m23 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m20, m21 ; sgr_x_by_x[ 0..127] + paddusw m19, m14 + mova m18, m22 + psraw m19, 4 ; min(z5, 255) - 256 + vpermt2b m18, m19, m23 ; sgr_x_by_x[128..255] + vpmovb2m k4, m19 + vpermi2b m19, m20, m21 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x3 + vmovdqu8 m19{k4}, m18 ; x5 + pandn m16, m24, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + pandn m18, m24, m19 + psrld m19, 16 + pmulld m2, m18 + pmulld m3, m19 + paddd m0, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m15 + vpternlogd m16, m0, m24, 0xd8 ; a3 | (b3 << 12) + vpternlogd m17, m1, m24, 0xd8 + mova [t3+r10*4+416*8+ 8], m16 + mova [t3+r10*4+416*8+ 24], xm17 + vextracti32x4 [t3+r10*4+416*8+ 56], m17, 2 + paddd m2, m15 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m3, m15 + mova [t3+r10*4+416*8+ 72], m17 + vextracti128 [t3+r10*4+416*8+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+416*8+104], m16, 3 + vpternlogd m18, m2, m24, 0xd8 ; a5 | (b5 << 12) + vpternlogd m19, m3, m24, 0xd8 + mova [t3+r10*4+416*0+ 8], m18 + mova [t3+r10*4+416*0+ 24], xm19 + vextracti32x4 [t3+r10*4+416*0+ 56], m19, 2 + mova [t3+r10*4+416*0+ 72], m19 + vextracti128 [t3+r10*4+416*0+ 72], ym18, 1 + vextracti32x4 [t3+r10*4+416*0+104], m18, 3 + add r10, 32 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) + lea r10, [wq-2] +.v0_loop: + mova m2, [t1+r10*2+416* 8] + mova m3, [t1+r10*2+416*10] + paddd m2, m2 + paddd m3, m3 + paddd m16, m2, [t2+r10*2+416* 8] + paddd m17, m3, [t2+r10*2+416*10] + mova m0, [t1+r10*2+416* 6] + paddw m0, m0 + paddw m1, m0, [t2+r10*2+416* 6] + pmulld m16, m9 ; -a3 * 9 + pmulld m17, m9 + mova [t2+r10*2+416* 6], m0 + mova [t2+r10*2+416* 8], m2 + mova [t2+r10*2+416*10], m3 + mova m2, [t1+r10*2+416*0] + mova m3, [t1+r10*2+416*2] + mova m18, [t1+r10*2+416*4] + punpcklwd m0, m4, m1 ; b3 + vpdpwssd m16, m0, m0 ; -p3 + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + pmulld m16, m12 ; p3 * s1 + pmulld m17, m12 + pmaddwd m0, m13 ; b3 * 455 + pmaddwd m1, m13 + mova [t3+r10*4+416*8+ 8], m2 + mova [t3+r10*4+416*0+ 8], m3 + mova [t3+r10*4+416*0+72], m18 + vpalignr m17{k2}, m16, m16, 2 + mova m16, m22 + paddusw m17, m14 + psraw m17, 4 ; min(z3, 255) - 256 + vpermt2b m16, m17, m23 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m20, m21 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x3 + pandn m16, m24, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + paddw m2, m2 ; cc5 + paddd m3, m3 + paddd m18, m18 + mova [t1+r10*2+416*0], m2 + mova [t1+r10*2+416*2], m3 + mova [t1+r10*2+416*4], m18 + paddd m0, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m15 + vpternlogd m16, m0, m24, 0xd8 ; a3 | (b3 << 12) + vpternlogd m17, m1, m24, 0xd8 + mova [t3+r10*4+416*4+ 8], m16 + mova [t3+r10*4+416*4+ 24], xm17 + vextracti32x4 [t3+r10*4+416*4+ 56], m17, 2 + mova [t3+r10*4+416*4+ 72], m17 + vextracti128 [t3+r10*4+416*4+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+416*4+104], m16, 3 + add r10, 32 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) + lea r10, [wq-2] +.v1_loop: + mova m0, [t1+r10*2+416* 8] + paddd m16, m0, [t2+r10*2+416* 8] + mova m1, [t1+r10*2+416*10] + paddd m17, m1, [t2+r10*2+416*10] + mova m2, [t3+r10*4+416*0+ 8] + paddd m18, m2, [t2+r10*2+416* 2] + mova m3, [t3+r10*4+416*0+72] + paddd m19, m3, [t2+r10*2+416* 4] + paddd m18, [t1+r10*2+416* 2] + paddd m19, [t1+r10*2+416* 4] + mova [t2+r10*2+416* 8], m0 + mova [t2+r10*2+416*10], m1 + mova [t2+r10*2+416* 2], m2 + mova [t2+r10*2+416* 4], m3 + pmulld m16, m9 ; -a3 * 9 + pmulld m17, m9 + pmulld m18, m10 ; -a5 * 25 + pmulld m19, m10 + mova m0, [t1+r10*2+416* 6] + paddw m1, m0, [t2+r10*2+416* 6] + mova m2, [t3+r10*4+416*8+ 8] + paddw m3, m2, [t2+r10*2+416*0] + paddw m3, [t1+r10*2+416*0] + mova [t2+r10*2+416* 6], m0 + mova [t2+r10*2+416*0], m2 + punpcklwd m0, m4, m1 ; b3 + vpdpwssd m16, m0, m0 ; -p3 + punpckhwd m1, m4, m1 + vpdpwssd m17, m1, m1 + punpcklwd m2, m3, m4 ; b5 + vpdpwssd m18, m2, m2 ; -p5 + punpckhwd m3, m4 + vpdpwssd m19, m3, m3 + pmulld m16, m12 ; p3 * s1 + pmulld m17, m12 + pmulld m18, m11 ; p5 * s0 + pmulld m19, m11 + pmaddwd m0, m13 ; b3 * 455 + pmaddwd m1, m13 + pmaddwd m2, m13 ; b5 * 164 + pmaddwd m3, m13 + vpalignr m17{k2}, m16, m16, 2 + vpalignr m19{k2}, m18, m18, 2 + paddusw m17, m14 + mova m16, m22 + psraw m17, 4 ; min(z3, 255) - 256 + vpermt2b m16, m17, m23 ; sgr_x_by_x[128..255] + vpmovb2m k3, m17 + vpermi2b m17, m20, m21 ; sgr_x_by_x[ 0..127] + paddusw m19, m14 + mova m18, m22 + psraw m19, 4 ; min(z5, 255) - 256 + vpermt2b m18, m19, m23 ; sgr_x_by_x[128..255] + vpmovb2m k4, m19 + vpermi2b m19, m20, m21 ; sgr_x_by_x[ 0..127] + vmovdqu8 m17{k3}, m16 ; x3 + vmovdqu8 m19{k4}, m18 ; x5 + pandn m16, m24, m17 + psrld m17, 16 + pmulld m0, m16 + pmulld m1, m17 + pandn m18, m24, m19 + psrld m19, m19, 16 + pmulld m2, m18 + pmulld m3, m19 + paddd m0, m15 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m15 + vpternlogd m16, m0, m24, 0xd8 ; a3 | (b3 << 12) + vpternlogd m17, m1, m24, 0xd8 + mova [t3+r10*4+416*8+ 8], m16 + mova [t3+r10*4+416*8+ 24], xm17 + vextracti32x4 [t3+r10*4+416*8+ 56], m17, 2 + paddd m2, m15 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m3, m15 + mova [t3+r10*4+416*8+ 72], m17 + vextracti128 [t3+r10*4+416*8+ 72], ym16, 1 + vextracti32x4 [t3+r10*4+416*8+104], m16, 3 + vpternlogd m18, m2, m24, 0xd8 ; a5 | (b5 << 12) + vpternlogd m19, m3, m24, 0xd8 + mova [t3+r10*4+416*0+ 8], m18 + mova [t3+r10*4+416*0+ 24], xm19 + vextracti32x4 [t3+r10*4+416*0+ 56], m19, 2 + mova [t3+r10*4+416*0+ 72], m19 + vextracti128 [t3+r10*4+416*0+ 72], ym18, 1 + vextracti32x4 [t3+r10*4+416*0+104], m18, 3 + add r10, 32 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + mov r10, wq +.prep_n_loop: + movu m0, [t3+r10*4+416*0+4] + paddd m1, m0, [t3+r10*4+416*0+0] + mova m16, [t3+r10*4+416*4+0] + paddd m1, [t3+r10*4+416*0+8] + mova m17, [t3+r10*4+416*8+0] + paddd m16, [t3+r10*4+416*4+8] + paddd m17, [t3+r10*4+416*8+8] + paddd m2, m16, [t3+r10*4+416*4+4] + paddd m3, m17, [t3+r10*4+416*8+4] + paddd m0, m1 + pslld m1, 2 + pslld m2, 2 + paddd m1, m0 ; ab5 565 + paddd m3, m3 ; ab3[ 0] 222 + psubd m2, m16 ; ab3[-1] 343 + mova [t3+r10*4+416*20], m3 + pandn m0, m24, m1 ; a5 565 + mova [t3+r10*4+416*24], m2 + psrld m1, 12 ; b5 565 + mova [t3+r10*4+416*12], m0 + paddd m3, m3 + mova [t3+r10*4+416*16], m1 + psubd m3, m17 ; ab3[ 0] 343 + mova [t3+r10*4+416*28], m3 + add r10, 16 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + mov r10, wq +.n0_loop: + movu m2, [t3+r10*4+4] + paddd m3, m2, [t3+r10*4+0] + paddd m3, [t3+r10*4+8] + mova m1, [t3+r10*4+416*4+0] + paddd m2, m3 + pslld m3, 2 + paddd m1, [t3+r10*4+416*4+8] + paddd m3, m2 + pandn m2, m24, m3 + psrld m3, 12 + paddd m0, m2, [t3+r10*4+416*12] ; a5 + paddd m16, m3, [t3+r10*4+416*16] ; b5 + (1 << 8) + mova [t3+r10*4+416*12], m2 + mova [t3+r10*4+416*16], m3 + paddd m2, m1, [t3+r10*4+416*4+4] + paddd m2, m2 ; ab3[ 1] 222 + mova m3, [t3+r10*4+416*20] + paddd m17, m3, [t3+r10*4+416*24] ; ab3[ 0] 222 + ab3[-1] 343 + mova [t3+r10*4+416*20], m2 + paddd m2, m2 + psubd m2, m1 ; ab3[ 1] 343 + mova [t3+r10*4+416*24], m2 + paddd m2, m3 ; ab3[ 0] 222 + ab3[ 1] 343 + pandn m1, m24, m17 + psrld m17, 12 + pandn m3, m24, m2 + psrld m2, 12 + paddd m1, m3 ; a3 + pmovzxbd m3, [dstq+r10] + paddd m17, m2 ; b3 + (1 << 8) + pmaddwd m0, m3 ; a5 * src + pmaddwd m1, m3 ; a3 * src + vpshldd m3, m25, 16 ; (dst << 16) + (1 << 15) + psubd m16, m0 ; b5 - a5 * src + (1 << 8) + psubd m17, m1 ; b3 - a3 * src + (1 << 8) + psrld m16, 9 + pslld m17, 7 + vmovdqu8 m17{k2}, m16 + vpdpwssd m3, m17, m26 + packuswb m3, m2 + vpermb m16, m27, m3 + mova [dstq+r10], xm16 + add r10, 16 + jl .n0_loop + add dstq, strideq + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + mov r10, wq +.n1_loop: + mova m1, [t3+r10*4+416*8+0] + paddd m1, [t3+r10*4+416*8+8] + paddd m2, m1, [t3+r10*4+416*8+4] + paddd m2, m2 ; ab3[ 1] 222 + mova m0, [t3+r10*4+416*20] + paddd m17, m0, [t3+r10*4+416*28] ; ab3[ 0] 222 + ab3[-1] 343 + pmovzxbd m3, [dstq+r10] + mova [t3+r10*4+416*20], m2 + paddd m2, m2 + psubd m2, m1 ; ab3[ 1] 343 + mova [t3+r10*4+416*28], m2 + paddd m0, m2 ; ab3[ 0] 222 + ab3[ 1] 343 + pandn m1, m24, m17 + psrld m17, 12 + pandn m2, m24, m0 + psrld m0, 12 + paddd m1, m2 ; a3 + paddd m17, m0 ; b3 + (1 << 8) + mova m16, [t3+r10*4+416*16] ; b5 + (1 << 7) + pmaddwd m1, m3 ; a3 * src + pmaddwd m0, m3, [t3+r10*4+416*12] ; a5 * src + vpshldd m3, m25, 16 ; (dst << 16) + (1 << 15) + psubd m17, m1 ; b3 - a3 * src + (1 << 8) + psubd m16, m0 ; b5 - a5 * src + (1 << 7) + pslld m17, 7 + palignr m17{k2}, m16, m16, 1 + vpdpwssd m3, m17, m26 + packuswb m3, m3 + vpermb m16, m27, m3 + mova [dstq+r10], xm16 + add r10, 16 + jl .n1_loop + add dstq, strideq + ret + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/looprestoration_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3681 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; Copyright © 2018, VideoLabs +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +wiener_init: db 6, 7, 6, 7, 6, 7, 6, 7, 0, 0, 0, 0, 2, 4, 2, 4 +wiener_shufA: db 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14 +wiener_shufB: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 +wiener_shufC: db 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 10, 12, 11, 13, 12 +wiener_shufD: db 4, -1, 5, -1, 6, -1, 7, -1, 8, -1, 9, -1, 10, -1, 11, -1 +wiener_l_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +sgr_lshuf3: db 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 +sgr_lshuf5: db 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 +pb_0to15: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + +pb_right_ext_mask: times 24 db 0xff + times 8 db 0 +pb_1: times 16 db 1 +pb_3: times 16 db 3 +pw_256: times 8 dw 256 +pw_2056: times 8 dw 2056 +pw_m16380: times 8 dw -16380 +pd_4096: times 4 dd 4096 +pd_34816: times 4 dd 34816 +pd_0xffff: times 4 dd 0xffff +pd_0xf00800a4: times 4 dd 0xf00800a4 +pd_0xf00801c7: times 4 dd 0xf00801c7 + +cextern sgr_x_by_x + +SECTION .text + +%macro movif64 2 ; dst, src + %if ARCH_X86_64 + mov %1, %2 + %endif +%endmacro + +%macro movif32 2 ; dst, src + %if ARCH_X86_32 + mov %1, %2 + %endif +%endmacro + +%if ARCH_X86_32 + %define PIC_base_offset $$ + + %macro SETUP_PIC 1-3 1,0 ; PIC_reg, save_PIC_reg, restore_PIC_reg + %assign pic_reg_stk_off 4 + %xdefine PIC_reg %1 + %if %2 == 1 + mov [esp], %1 + %endif + LEA PIC_reg, PIC_base_offset + %if %3 == 1 + XCHG_PIC_REG + %endif + %endmacro + + %macro XCHG_PIC_REG 0 + mov [esp+pic_reg_stk_off], PIC_reg + %assign pic_reg_stk_off (pic_reg_stk_off+4) % 8 + mov PIC_reg, [esp+pic_reg_stk_off] + %endmacro + + %define PIC_sym(sym) (PIC_reg+(sym)-PIC_base_offset) + +%else + %macro XCHG_PIC_REG 0 + %endmacro + + %define PIC_sym(sym) (sym) +%endif + +%macro WIENER 0 +%if ARCH_X86_64 +DECLARE_REG_TMP 9, 7, 10, 11, 12, 13, 14 ; ring buffer pointers +cglobal wiener_filter7_8bpc, 4, 15, 16, -384*12-16, dst, stride, left, lpf, \ + w, h, edge, flt, x + %define tmpstrideq strideq + %define base 0 + mov fltq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + movq m14, [fltq] + add lpfq, wq + movq m7, [fltq+16] + add dstq, wq + lea t1, [rsp+wq*2+16] + mova m15, [pw_2056] + neg wq +%if cpuflag(ssse3) + pshufb m14, [wiener_init] + mova m8, [wiener_shufA] + pshufd m12, m14, q2222 ; x0 x0 + mova m9, [wiener_shufB] + pshufd m13, m14, q3333 ; x1 x2 + mova m10, [wiener_shufC] + punpcklqdq m14, m14 ; x3 + mova m11, [wiener_shufD] +%else + mova m10, [pw_m16380] + punpcklwd m14, m14 + pshufd m11, m14, q0000 ; x0 + pshufd m12, m14, q1111 ; x1 + pshufd m13, m14, q2222 ; x2 + pshufd m14, m14, q3333 ; x3 +%endif +%else +DECLARE_REG_TMP 4, 0, _, 5 +%if cpuflag(ssse3) + %define m10 [base+wiener_shufC] + %define m11 [base+wiener_shufD] + %define stk_off 96 +%else + %define m10 [base+pw_m16380] + %define m11 [stk+96] + %define stk_off 112 +%endif +cglobal wiener_filter7_8bpc, 0, 7, 8, -384*12-stk_off, _, x, left, lpf, tmpstride + %define base r6-pb_right_ext_mask-21 + %define stk esp + %define dstq leftq + %define edgeb byte edged + %define edged [stk+ 8] + %define dstmp [stk+12] + %define hd dword [stk+16] + %define wq [stk+20] + %define strideq [stk+24] + %define leftmp [stk+28] + %define t2 [stk+32] + %define t4 [stk+36] + %define t5 [stk+40] + %define t6 [stk+44] + %define m8 [base+wiener_shufA] + %define m9 [base+wiener_shufB] + %define m12 [stk+48] + %define m13 [stk+64] + %define m14 [stk+80] + %define m15 [base+pw_2056] + mov r1, r6m ; flt + mov r0, r0m ; dst + mov r4, r4m ; w + mov lpfq, lpfm + mov r2, r7m ; edge + mov r5, r5m ; h + movq m3, [r1+ 0] + movq m7, [r1+16] + add r0, r4 + mov r1, r1m ; stride + add lpfq, r4 + mov edged, r2 + mov r2, r2m ; left + mov dstmp, r0 + lea t1, [rsp+r4*2+stk_off] + mov hd, r5 + neg r4 + LEA r6, pb_right_ext_mask+21 + mov wq, r4 + mov strideq, r1 + mov leftmp, r2 + mov r4, r1 +%if cpuflag(ssse3) + pshufb m3, [base+wiener_init] + pshufd m1, m3, q2222 + pshufd m2, m3, q3333 + punpcklqdq m3, m3 +%else + punpcklwd m3, m3 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m11, m0 +%endif + mova m12, m1 + mova m13, m2 + mova m14, m3 +%endif + psllw m7, 5 + pshufd m6, m7, q0000 ; y0 y1 + pshufd m7, m7, q1111 ; y2 y3 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t6, t1 + mov t5, t1 + add t1, 384*2 + call .h_top + lea t3, [lpfq+tmpstrideq*4] + mov lpfq, dstmp + add t3, tmpstrideq + mov [rsp], t3 ; below + mov t4, t1 + add t1, 384*2 + call .h + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 +.main: + lea t0, [t1+384*2] +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v3 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.v1: + call mangle(private_prefix %+ _wiener_filter7_8bpc_ssse3).v + RET +.no_top: + lea t3, [lpfq+tmpstrideq*4] + mov lpfq, dstmp + lea t3, [t3+tmpstrideq*2] + mov [rsp], t3 + call .h + mov t6, t1 + mov t5, t1 + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + mov t2, t1 + dec hd + jz .v2 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v3 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v3 + add t0, 384*8 + call .hv + dec hd + jnz .main +.v3: + call mangle(private_prefix %+ _wiener_filter7_8bpc_ssse3).v +.v2: + call mangle(private_prefix %+ _wiener_filter7_8bpc_ssse3).v + jmp .v1 +.extend_right: + movd m2, [lpfq-4] +%if ARCH_X86_64 + push r0 + lea r0, [pb_right_ext_mask+21] + movu m0, [r0+xq+0] + movu m1, [r0+xq+8] + pop r0 +%else + movu m0, [r6+xq+0] + movu m1, [r6+xq+8] +%endif +%if cpuflag(ssse3) + pshufb m2, [base+pb_3] +%else + punpcklbw m2, m2 + pshuflw m2, m2, q3333 + punpcklqdq m2, m2 +%endif + pand m4, m0 + pand m5, m1 + pandn m0, m2 + pandn m1, m2 + por m4, m0 + por m5, m1 + ret +.h: + %define stk esp+4 ; offset due to call + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movifnidn leftq, leftmp + mova m4, [lpfq+xq] + movd m5, [leftq] + add leftq, 4 + pslldq m4, 4 + por m4, m5 + movifnidn leftmp, leftq + jmp .h_main +.h_extend_left: +%if cpuflag(ssse3) + mova m4, [lpfq+xq] + pshufb m4, [base+wiener_l_shuf] +%else + mova m5, [lpfq+xq] + pshufd m4, m5, q2103 + punpcklbw m5, m5 + punpcklwd m5, m5 + movss m4, m5 +%endif + jmp .h_main +.h_top: + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+xq-4] +.h_main: + movu m5, [lpfq+xq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp xd, -18 + jl .h_have_right + call .extend_right +.h_have_right: +%macro %%h7 0 +%if cpuflag(ssse3) + pshufb m0, m4, m8 + pmaddubsw m0, m12 + pshufb m1, m5, m8 + pmaddubsw m1, m12 + pshufb m2, m4, m9 + pmaddubsw m2, m13 + pshufb m3, m5, m9 + pmaddubsw m3, m13 + paddw m0, m2 + pshufb m2, m4, m10 + pmaddubsw m2, m13 + paddw m1, m3 + pshufb m3, m5, m10 + pmaddubsw m3, m13 + pshufb m4, m11 + paddw m0, m2 + pmullw m2, m14, m4 + pshufb m5, m11 + paddw m1, m3 + pmullw m3, m14, m5 + psllw m4, 7 + psllw m5, 7 + paddw m0, m2 + mova m2, [base+pw_m16380] + paddw m1, m3 + paddw m4, m2 + paddw m5, m2 + paddsw m0, m4 + paddsw m1, m5 +%else + psrldq m0, m4, 1 + pslldq m1, m4, 1 + pxor m3, m3 + punpcklbw m0, m3 + punpckhbw m1, m3 + paddw m0, m1 + pmullw m0, m11 + psrldq m1, m4, 2 + pslldq m2, m4, 2 + punpcklbw m1, m3 + punpckhbw m2, m3 + paddw m1, m2 + pmullw m1, m12 + paddw m0, m1 + pshufd m2, m4, q0321 + punpcklbw m2, m3 + pmullw m1, m14, m2 + paddw m0, m1 + psrldq m1, m4, 3 + pslldq m4, 3 + punpcklbw m1, m3 + punpckhbw m4, m3 + paddw m1, m4 + pmullw m1, m13 + paddw m0, m1 + psllw m2, 7 + paddw m2, m10 + paddsw m0, m2 + psrldq m1, m5, 1 + pslldq m2, m5, 1 + punpcklbw m1, m3 + punpckhbw m2, m3 + paddw m1, m2 + pmullw m1, m11 + psrldq m2, m5, 2 + pslldq m4, m5, 2 + punpcklbw m2, m3 + punpckhbw m4, m3 + paddw m2, m4 + pmullw m2, m12 + paddw m1, m2 + pshufd m4, m5, q0321 + punpcklbw m4, m3 + pmullw m2, m14, m4 + paddw m1, m2 + psrldq m2, m5, 3 + pslldq m5, 3 + punpcklbw m2, m3 + punpckhbw m5, m3 + paddw m2, m5 + pmullw m2, m13 + paddw m1, m2 + psllw m4, 7 + paddw m4, m10 + paddsw m1, m4 +%endif +%endmacro + %%h7 + psraw m0, 3 + psraw m1, 3 + paddw m0, m15 + paddw m1, m15 + mova [t1+xq*2+ 0], m0 + mova [t1+xq*2+16], m1 + add xq, 16 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movifnidn leftq, leftmp + mova m4, [lpfq+xq] + movd m5, [leftq] + add leftq, 4 + pslldq m4, 4 + por m4, m5 + movifnidn leftmp, leftq + jmp .hv_main +.hv_extend_left: +%if cpuflag(ssse3) + mova m4, [lpfq+xq] + pshufb m4, [base+wiener_l_shuf] +%else + mova m5, [lpfq+xq] + pshufd m4, m5, q2103 + punpcklbw m5, m5 + punpcklwd m5, m5 + movss m4, m5 +%endif + jmp .hv_main +.hv_bottom: + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m4, [lpfq+xq-4] +.hv_main: + movu m5, [lpfq+xq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp xd, -18 + jl .hv_have_right + call .extend_right +.hv_have_right: + %%h7 +%if ARCH_X86_64 + mova m2, [t4+xq*2] + paddw m2, [t2+xq*2] +%else + mov r2, t4 + mova m2, [r2+xq*2] + mov r2, t2 + paddw m2, [r2+xq*2] + mov r2, t5 +%endif + mova m3, [t3+xq*2] +%if ARCH_X86_64 + mova m5, [t5+xq*2] +%else + mova m5, [r2+xq*2] + mov r2, t6 +%endif + paddw m5, [t1+xq*2] + psraw m0, 3 + psraw m1, 3 + paddw m0, m15 + paddw m1, m15 +%if ARCH_X86_64 + paddw m4, m0, [t6+xq*2] +%else + paddw m4, m0, [r2+xq*2] + mov r2, t4 +%endif + mova [t0+xq*2], m0 + punpcklwd m0, m2, m3 + pmaddwd m0, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4, m5 + pmaddwd m3, m6 + punpckhwd m4, m5 + pmaddwd m4, m6 + paddd m0, m3 + mova m3, [t3+xq*2+16] + paddd m4, m2 +%if ARCH_X86_64 + mova m2, [t4+xq*2+16] + paddw m2, [t2+xq*2+16] + mova m5, [t5+xq*2+16] +%else + mova m2, [r2+xq*2+16] + mov r2, t2 + paddw m2, [r2+xq*2+16] + mov r2, t5 + mova m5, [r2+xq*2+16] + mov r2, t6 +%endif + paddw m5, [t1+xq*2+16] + packuswb m0, m4 +%if ARCH_X86_64 + paddw m4, m1, [t6+xq*2+16] +%else + paddw m4, m1, [r2+xq*2+16] + mov dstq, dstmp +%endif + mova [t0+xq*2+16], m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4, m5 + pmaddwd m3, m6 + punpckhwd m4, m5 + pmaddwd m4, m6 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+xq], m0 + add xq, 16 + jl .hv_loop + add dstq, strideq +%if ARCH_X86_64 + mov t6, t5 + mov t5, t4 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t6 +%else + mov dstmp, dstq + mov r1, t5 + mov r2, t4 + mov t6, r1 + mov t5, r2 + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, r1 +%endif + ret +%if cpuflag(ssse3) ; identical in sse2 and ssse3, so share code +.v: + mov xq, wq +.v_loop: +%if ARCH_X86_64 + mova m1, [t4+xq*2] + paddw m1, [t2+xq*2] +%else + mov r2, t4 + mova m1, [r2+xq*2] + mov r2, t2 + paddw m1, [r2+xq*2] + mov r2, t6 +%endif + mova m2, [t3+xq*2] + mova m4, [t1+xq*2] +%if ARCH_X86_64 + paddw m3, m4, [t6+xq*2] + paddw m4, [t5+xq*2] +%else + paddw m3, m4, [r2+xq*2] + mov r2, t5 + paddw m4, [r2+xq*2] + mov r2, t4 +%endif + punpcklwd m0, m1, m2 + pmaddwd m0, m7 + punpckhwd m1, m2 + pmaddwd m1, m7 + punpcklwd m2, m3, m4 + pmaddwd m2, m6 + punpckhwd m3, m4 + pmaddwd m3, m6 + paddd m0, m2 + paddd m1, m3 +%if ARCH_X86_64 + mova m2, [t4+xq*2+16] + paddw m2, [t2+xq*2+16] +%else + mova m2, [r2+xq*2+16] + mov r2, t2 + paddw m2, [r2+xq*2+16] + mov r2, t6 +%endif + mova m3, [t3+xq*2+16] + mova m5, [t1+xq*2+16] +%if ARCH_X86_64 + paddw m4, m5, [t6+xq*2+16] + paddw m5, [t5+xq*2+16] +%else + paddw m4, m5, [r2+xq*2+16] + mov r2, t5 + paddw m5, [r2+xq*2+16] + movifnidn dstq, dstmp +%endif + packuswb m0, m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4, m5 + pmaddwd m3, m6 + punpckhwd m4, m5 + pmaddwd m4, m6 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+xq], m0 + add xq, 16 + jl .v_loop + add dstq, strideq +%if ARCH_X86_64 + mov t6, t5 + mov t5, t4 +%else + mov dstmp, dstq + mov r1, t5 + mov r2, t4 + mov t6, r1 + mov t5, r2 +%endif + mov t4, t3 + mov t3, t2 + mov t2, t1 + ret +%endif + +%if ARCH_X86_64 +cglobal wiener_filter5_8bpc, 4, 13, 16, 384*8+16, dst, stride, left, lpf, \ + w, h, edge, flt, x + mov fltq, r6mp + mov wd, wm + movifnidn hd, hm + mov edged, r7m + movq m14, [fltq] + add lpfq, wq + movq m7, [fltq+16] + add dstq, wq + mova m8, [pw_m16380] + lea t1, [rsp+wq*2+16] + mova m15, [pw_2056] + neg wq +%if cpuflag(ssse3) + pshufb m14, [wiener_init] + mova m9, [wiener_shufB] + pshufd m13, m14, q3333 ; x1 x2 + mova m10, [wiener_shufC] + punpcklqdq m14, m14 ; x3 + mova m11, [wiener_shufD] + mova m12, [wiener_l_shuf] +%else + punpcklwd m14, m14 + pshufd m11, m14, q1111 ; x1 + pshufd m13, m14, q2222 ; x2 + pshufd m14, m14, q3333 ; x3 +%endif +%else +%if cpuflag(ssse3) + %define stk_off 80 +%else + %define m11 [stk+80] + %define stk_off 96 +%endif +cglobal wiener_filter5_8bpc, 0, 7, 8, -384*8-stk_off, _, x, left, lpf, tmpstride + %define stk esp + %define leftmp [stk+28] + %define m8 [base+pw_m16380] + %define m12 [base+wiener_l_shuf] + %define m14 [stk+48] + mov r1, r6m ; flt + mov r0, r0m ; dst + mov r4, r4m ; w + mov lpfq, lpfm + mov r2, r7m ; edge + mov r5, r5m ; h + movq m2, [r1+ 0] + movq m7, [r1+16] + add r0, r4 + mov r1, r1m ; stride + add lpfq, r4 + mov edged, r2 + mov r2, r2m ; left + mov dstmp, r0 + lea t1, [rsp+r4*2+stk_off] + mov hd, r5 + neg r4 + LEA r6, pb_right_ext_mask+21 + mov wq, r4 + mov strideq, r1 + mov leftmp, r2 + mov r4, r1 +%if cpuflag(ssse3) + pshufb m2, [base+wiener_init] + pshufd m1, m2, q3333 + punpcklqdq m2, m2 +%else + punpcklwd m2, m2 + pshufd m0, m2, q1111 + pshufd m1, m2, q2222 + pshufd m2, m2, q3333 + mova m11, m0 +%endif + mova m13, m1 + mova m14, m2 +%endif + psllw m7, 5 + pshufd m6, m7, q0000 ; __ y1 + pshufd m7, m7, q1111 ; y2 y3 + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, strideq + mov t4, t1 + add t1, 384*2 + call .h_top + lea xq, [lpfq+tmpstrideq*4] + mov lpfq, dstmp + mov t3, t1 + add t1, 384*2 + add xq, tmpstrideq + mov [rsp], xq ; below + call .h + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 +.main: + mov t0, t4 +.main_loop: + call .hv + dec hd + jnz .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .v2 + mov lpfq, [rsp] + call .hv_bottom + add lpfq, strideq + call .hv_bottom +.end: + RET +.no_top: + lea t3, [lpfq+tmpstrideq*4] + mov lpfq, dstmp + lea t3, [t3+tmpstrideq*2] + mov [rsp], t3 + call .h + mov t4, t1 + mov t3, t1 + mov t2, t1 + dec hd + jz .v1 + add lpfq, strideq + add t1, 384*2 + call .h + dec hd + jz .v2 + lea t0, [t1+384*2] + call .hv + dec hd + jz .v2 + add t0, 384*6 + call .hv + dec hd + jnz .main +.v2: + call mangle(private_prefix %+ _wiener_filter5_8bpc_ssse3).v + add dstq, strideq + mov t4, t3 + mov t3, t2 + mov t2, t1 + movifnidn dstmp, dstq +.v1: + call mangle(private_prefix %+ _wiener_filter5_8bpc_ssse3).v + jmp .end +.h: + %define stk esp+4 + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movifnidn leftq, leftmp + mova m4, [lpfq+xq] + movd m5, [leftq] + add leftq, 4 + pslldq m4, 4 + por m4, m5 + movifnidn leftmp, leftq + jmp .h_main +.h_extend_left: +%if cpuflag(ssse3) + mova m4, [lpfq+xq] + pshufb m4, m12 +%else + mova m5, [lpfq+xq] + pshufd m4, m5, q2103 + punpcklbw m5, m5 + punpcklwd m5, m5 + movss m4, m5 +%endif + jmp .h_main +.h_top: + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left +.h_loop: + movu m4, [lpfq+xq-4] +.h_main: + movu m5, [lpfq+xq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp xd, -17 + jl .h_have_right + call mangle(private_prefix %+ _wiener_filter7_8bpc %+ SUFFIX).extend_right +.h_have_right: +%macro %%h5 0 +%if cpuflag(ssse3) + pshufb m0, m4, m9 + pmaddubsw m0, m13 + pshufb m1, m5, m9 + pmaddubsw m1, m13 + pshufb m2, m4, m10 + pmaddubsw m2, m13 + pshufb m3, m5, m10 + pmaddubsw m3, m13 + pshufb m4, m11 + paddw m0, m2 + pmullw m2, m14, m4 + pshufb m5, m11 + paddw m1, m3 + pmullw m3, m14, m5 + psllw m4, 7 + psllw m5, 7 + paddw m4, m8 + paddw m5, m8 + paddw m0, m2 + paddw m1, m3 + paddsw m0, m4 + paddsw m1, m5 +%else + psrldq m0, m4, 2 + pslldq m1, m4, 2 + pxor m3, m3 + punpcklbw m0, m3 + punpckhbw m1, m3 + paddw m0, m1 + pmullw m0, m11 + pshufd m2, m4, q0321 + punpcklbw m2, m3 + pmullw m1, m14, m2 + paddw m0, m1 + psrldq m1, m4, 3 + pslldq m4, 3 + punpcklbw m1, m3 + punpckhbw m4, m3 + paddw m1, m4 + pmullw m1, m13 + paddw m0, m1 + psllw m2, 7 + paddw m2, m8 + paddsw m0, m2 + psrldq m1, m5, 2 + pslldq m4, m5, 2 + punpcklbw m1, m3 + punpckhbw m4, m3 + paddw m1, m4 + pmullw m1, m11 + pshufd m4, m5, q0321 + punpcklbw m4, m3 + pmullw m2, m14, m4 + paddw m1, m2 + psrldq m2, m5, 3 + pslldq m5, 3 + punpcklbw m2, m3 + punpckhbw m5, m3 + paddw m2, m5 + pmullw m2, m13 + paddw m1, m2 + psllw m4, 7 + paddw m4, m8 + paddsw m1, m4 +%endif +%endmacro + %%h5 + psraw m0, 3 + psraw m1, 3 + paddw m0, m15 + paddw m1, m15 + mova [t1+xq*2+ 0], m0 + mova [t1+xq*2+16], m1 + add xq, 16 + jl .h_loop + ret +ALIGN function_align +.hv: + add lpfq, strideq + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movifnidn leftq, leftmp + mova m4, [lpfq+xq] + movd m5, [leftq] + add leftq, 4 + pslldq m4, 4 + por m4, m5 + movifnidn leftmp, leftq + jmp .hv_main +.hv_extend_left: +%if cpuflag(ssse3) + mova m4, [lpfq+xq] + pshufb m4, m12 +%else + mova m5, [lpfq+xq] + pshufd m4, m5, q2103 + punpcklbw m5, m5 + punpcklwd m5, m5 + movss m4, m5 +%endif + jmp .hv_main +.hv_bottom: + mov xq, wq + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left +.hv_loop: + movu m4, [lpfq+xq-4] +.hv_main: + movu m5, [lpfq+xq+4] + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp xd, -17 + jl .hv_have_right + call mangle(private_prefix %+ _wiener_filter7_8bpc %+ SUFFIX).extend_right +.hv_have_right: + %%h5 + mova m2, [t3+xq*2] + paddw m2, [t1+xq*2] + psraw m0, 3 + psraw m1, 3 + paddw m0, m15 + paddw m1, m15 +%if ARCH_X86_64 + mova m3, [t2+xq*2] + paddw m4, m0, [t4+xq*2] +%else + mov r2, t2 + mova m3, [r2+xq*2] + mov r2, t4 + paddw m4, m0, [r2+xq*2] +%endif + mova [t0+xq*2], m0 + punpcklwd m0, m2, m3 + pmaddwd m0, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4, m4 + pmaddwd m3, m6 + punpckhwd m4, m4 + pmaddwd m4, m6 + paddd m0, m3 + paddd m4, m2 + mova m2, [t3+xq*2+16] + paddw m2, [t1+xq*2+16] + packuswb m0, m4 +%if ARCH_X86_64 + mova m3, [t2+xq*2+16] + paddw m4, m1, [t4+xq*2+16] +%else + paddw m4, m1, [r2+xq*2+16] + mov r2, t2 + mova m3, [r2+xq*2+16] + mov dstq, dstmp +%endif + mova [t0+xq*2+16], m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4, m4 + pmaddwd m3, m6 + punpckhwd m4, m4 + pmaddwd m4, m6 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+xq], m0 + add xq, 16 + jl .hv_loop + add dstq, strideq + mov t4, t3 + mov t3, t2 + mov t2, t1 + mov t1, t0 + mov t0, t4 + movifnidn dstmp, dstq + ret +%if cpuflag(ssse3) +.v: + mov xq, wq +.v_loop: + mova m3, [t1+xq*2] + paddw m1, m3, [t3+xq*2] +%if ARCH_X86_64 + mova m2, [t2+xq*2] + paddw m3, [t4+xq*2] +%else + mov r2, t2 + mova m2, [r2+xq*2] + mov r2, t4 + paddw m3, [r2+xq*2] +%endif + punpcklwd m0, m1, m2 + pmaddwd m0, m7 + punpckhwd m1, m2 + pmaddwd m1, m7 + punpcklwd m2, m3 + pmaddwd m2, m6 + punpckhwd m3, m3 + pmaddwd m3, m6 + paddd m0, m2 + paddd m1, m3 + mova m4, [t1+xq*2+16] + paddw m2, m4, [t3+xq*2+16] +%if ARCH_X86_64 + mova m3, [t2+xq*2+16] + paddw m4, [t4+xq*2+16] +%else + paddw m4, [r2+xq*2+16] + mov r2, t2 + mova m3, [r2+xq*2+16] + mov dstq, dstmp +%endif + packuswb m0, m1 + punpcklwd m1, m2, m3 + pmaddwd m1, m7 + punpckhwd m2, m3 + pmaddwd m2, m7 + punpcklwd m3, m4 + pmaddwd m3, m6 + punpckhwd m4, m4 + pmaddwd m4, m6 + paddd m1, m3 + paddd m2, m4 + packuswb m1, m2 + psrlw m0, 8 + psrlw m1, 8 + packuswb m0, m1 + mova [dstq+xq], m0 + add xq, 16 + jl .v_loop + ret +%endif +%endmacro + +INIT_XMM sse2 +WIENER + +INIT_XMM ssse3 +WIENER + +;;;;;;;;;;;;;;;;;;;;;;;;;; +;; self-guided ;; +;;;;;;;;;;;;;;;;;;;;;;;;;; + +%macro GATHERDD 3 ; dst, src, tmp + movd %3d, %2 + %if ARCH_X86_64 + movd %1, [r13+%3] + pextrw %3d, %2, 2 + pinsrw %1, [r13+%3+2], 3 + pextrw %3d, %2, 4 + pinsrw %1, [r13+%3+2], 5 + pextrw %3d, %2, 6 + pinsrw %1, [r13+%3+2], 7 + %else + movd %1, [base+sgr_x_by_x-0xf03+%3] + pextrw %3, %2, 2 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 3 + pextrw %3, %2, 4 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 5 + pextrw %3, %2, 6 + pinsrw %1, [base+sgr_x_by_x-0xf03+%3+2], 7 + %endif +%endmacro + +%macro GATHER_X_BY_X 5 ; dst, src0, src1, tmp32, tmp32_restore + %if ARCH_X86_64 + %define tmp r14 + %else + %define tmp %4 + %endif + GATHERDD %1, %2, tmp + GATHERDD %2, %3, tmp + movif32 %4, %5 + psrld %1, 24 + psrld %2, 24 + packssdw %1, %2 +%endmacro + +%macro MULLD 3 ; dst, src, tmp + pmulhuw %3, %1, %2 + pmullw %1, %2 + pslld %3, 16 + paddd %1, %3 +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 0, 1, 2, 3, 5 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 5*16 + %else + %assign extra_stack 3*16 + %endif +cglobal sgr_filter_5x5_8bpc, 1, 7, 8, -400*24-16-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*0+4*6] + %define stridemp dword [esp+calloff+16*0+4*7] + %define leftm dword [esp+calloff+16*3+4*0] + %define lpfm dword [esp+calloff+16*3+4*1] + %define w0m dword [esp+calloff+16*3+4*2] + %define hd dword [esp+calloff+16*3+4*3] + %define edgeb byte [esp+calloff+16*3+4*4] + %define edged dword [esp+calloff+16*3+4*4] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t0m dword [esp+calloff+4*2] + %define t2m dword [esp+calloff+4*3] + %define t3m dword [esp+calloff+4*4] + %define t4m dword [esp+calloff+4*5] + %define m8 [base+pb_1] + %define m9 [esp+calloff+16*2] + %define m10 [base+pd_0xf00800a4] + %define m11 [base+sgr_lshuf5] + %define m12 [base+pd_34816] + %define m13 [base+pb_0to15] + %define r10 r4 + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +DECLARE_REG_TMP 8, 7, 9, 11, 12 +cglobal sgr_filter_5x5_8bpc, 4, 15, 14, -400*24-16, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + mov wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + movifnidn hd, hm + mov edged, r7m + movu m9, [paramsq] + add lpfq, wq + mova m8, [pb_1] + lea t1, [rsp+wq*2+20] + mova m10, [pd_0xf00800a4] + add dstq, wq + lea t3, [rsp+wq*4+400*12+16] + mova m12, [pd_34816] ; (1 << 11) + (1 << 15) + lea t4, [rsp+wq*2+400*20+16] + pshufhw m7, m9, q0000 + pshufb m9, [pw_256] ; s0 + punpckhqdq m7, m7 ; w0 + neg wq + mova m13, [pb_0to15] + pxor m6, m6 + mova m11, [sgr_lshuf5] + psllw m7, 4 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + movu m1, [r1] + add lpfm, wq + lea t1, [rsp+extra_stack+wq*2+20] + add dstq, wq + lea t3, [rsp+extra_stack+wq*4+400*12+16] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq*2+400*20+16] + mov t3m, t3 + pshufhw m7, m1, q0000 + mov t4m, t4 + pshufb m1, [base+pw_256] ; s0 + punpckhqdq m7, m7 ; w0 + psllw m7, 4 + neg wq + mova m9, m1 + pxor m6, m6 + mov w1m, wd + sub wd, 2 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + movif32 t2m, t1 + mov t2, t1 + call .top_fixup + add t1, 400*6 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t0m, t2 + mov t0, t2 + dec hd + jz .height1 + or edged, 16 + call .h +.main: + add lpfq, stridemp + movif32 t4, t4m + call .hv + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp +%if ARCH_X86_64 + test hb, hb +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + call .h + add lpfq, stridemp + call .hv + movif32 dstq, dstm + call .n0 + call .n1 + sub hd, 2 + movif32 t0, t0m + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .h_top + add lpfq, stridemp + call .hv_bottom +.end: + movif32 dstq, dstm + call .n0 + call .n1 +.end2: + RET +.height1: + movif32 t4, t4m + call .hv + call .prep_n + jmp .odd_height_end +.odd_height: + call .hv + movif32 dstq, dstm + call .n0 + call .n1 +.odd_height_end: + call .v + movif32 dstq, dstm + call .n0 + jmp .end2 +.extend_bottom: + call .v + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h + lea t2, [t1+400*6] + movif32 t2m, t2 + call .top_fixup + dec hd + jz .no_top_height1 + or edged, 16 + mov t0, t1 + mov t1, t2 + movif32 t0m, t0 + jmp .main +.no_top_height1: + movif32 t3, t3m + movif32 t4, t4m + call .v + call .prep_n + jmp .odd_height_end +.extend_right: +%assign stack_offset stack_offset+8 +%assign calloff 8 + movd m1, wd + movd m3, [lpfq-1] + pshufb m1, m6 + pshufb m3, m6 + psubb m2, m8, m1 + pcmpgtb m2, m13 + pand m5, m2 + pandn m2, m3 + por m5, m2 + ret +%assign stack_offset stack_offset-4 +%assign calloff 4 +.h: ; horizontal boxsum +%if ARCH_X86_64 + lea wq, [r4-2] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 13 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, m11 + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-2] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m5, [lpfq+wq-1] +.h_main: + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -10 + jl .h_have_right + call .extend_right +.h_have_right: + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + palignr m2, m5, m4, 2 + paddw m0, m4, m2 + palignr m3, m5, m4, 6 + paddw m0, m3 + punpcklwd m1, m2, m3 + pmaddwd m1, m1 + punpckhwd m2, m3 + pmaddwd m2, m2 + palignr m5, m4, 8 + paddw m0, m5 + punpcklwd m3, m4, m5 + pmaddwd m3, m3 + paddd m1, m3 + punpckhwd m3, m4, m5 + pmaddwd m3, m3 + shufps m4, m5, q2121 + paddw m0, m4 ; sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m2, m3 + test edgeb, 16 ; y > 0 + jz .h_loop_end + paddw m0, [t1+wq*2+400*0] + paddd m1, [t1+wq*2+400*2] + paddd m2, [t1+wq*2+400*4] +.h_loop_end: + paddd m1, m5 ; sumsq + paddd m2, m4 + mova [t1+wq*2+400*0], m0 + mova [t1+wq*2+400*2], m1 + mova [t1+wq*2+400*4], m2 + add wq, 8 + jl .h_loop + ret +.top_fixup: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.top_fixup_loop: ; the sums of the first row needs to be doubled + mova m0, [t1+wq*2+400*0] + mova m1, [t1+wq*2+400*2] + mova m2, [t1+wq*2+400*4] + paddw m0, m0 + paddd m1, m1 + paddd m2, m2 + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m1 + mova [t2+wq*2+400*4], m2 + add wq, 8 + jl .top_fixup_loop + ret +ALIGN function_align +.hv: ; horizontal boxsum + vertical boxsum + ab +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 13 + jmp .hv_main +.hv_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, m11 + jmp .hv_main +.hv_bottom: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv_loop_start +%endif +.hv_loop: + movif32 lpfq, hvsrcm +.hv_loop_start: + movu m5, [lpfq+wq-1] +.hv_main: + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv_have_right + cmp wd, -10 + jl .hv_have_right + call .extend_right +.hv_have_right: + movif32 t3, hd + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + palignr m3, m5, m4, 2 + paddw m0, m4, m3 + palignr m1, m5, m4, 6 + paddw m0, m1 + punpcklwd m2, m3, m1 + pmaddwd m2, m2 + punpckhwd m3, m1 + pmaddwd m3, m3 + palignr m5, m4, 8 + paddw m0, m5 + punpcklwd m1, m4, m5 + pmaddwd m1, m1 + paddd m2, m1 + punpckhwd m1, m4, m5 + pmaddwd m1, m1 + shufps m4, m5, q2121 + paddw m0, m4 ; h sum + punpcklwd m5, m4, m6 + pmaddwd m5, m5 + punpckhwd m4, m6 + pmaddwd m4, m4 + paddd m3, m1 + paddd m2, m5 ; h sumsq + paddd m3, m4 + paddw m1, m0, [t1+wq*2+400*0] + paddd m4, m2, [t1+wq*2+400*2] + paddd m5, m3, [t1+wq*2+400*4] +%if ARCH_X86_64 + test hd, hd +%else + test t3, t3 +%endif + jz .hv_last_row +.hv_main2: + paddw m1, [t2+wq*2+400*0] ; hv sum + paddd m4, [t2+wq*2+400*2] ; hv sumsq + paddd m5, [t2+wq*2+400*4] + mova [t0+wq*2+400*0], m0 + pslld m0, m4, 4 + mova [t0+wq*2+400*2], m2 + mova [t0+wq*2+400*4], m3 + pslld m2, m4, 3 + paddd m4, m0 + pslld m0, m5, 4 + paddd m4, m2 ; a * 25 + pslld m2, m5, 3 + paddd m5, m0 + paddd m5, m2 + punpcklwd m0, m1, m6 ; b + punpckhwd m1, m6 + pmaddwd m2, m0, m0 ; b * b + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m2 ; p * s + MULLD m5, m9, m2 + pmaddwd m0, m10 ; b * 164 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, t2, t2m + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m2 + MULLD m1, m5, m2 + paddd m0, m12 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m12 + mova [t4+wq*2+4], m3 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m1 + add wq, 8 + jl .hv_loop + mov t2, t1 + mov t1, t0 + mov t0, t2 + movif32 t2m, t2 + movif32 t0m, t0 + ret +.hv_last_row: ; esoteric edge case for odd heights + mova [t1+wq*2+400*0], m1 + paddw m1, m0 + mova [t1+wq*2+400*2], m4 + paddd m4, m2 + mova [t1+wq*2+400*4], m5 + paddd m5, m3 + jmp .hv_main2 +.v: ; vertical boxsum + ab +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.v_loop: + mova m0, [t1+wq*2+400*0] + mova m2, [t1+wq*2+400*2] + mova m3, [t1+wq*2+400*4] + paddw m1, m0, [t2+wq*2+400*0] + paddd m4, m2, [t2+wq*2+400*2] + paddd m5, m3, [t2+wq*2+400*4] + paddw m0, m0 + paddd m2, m2 + paddd m3, m3 + paddw m1, m0 ; hv sum + paddd m4, m2 ; hv sumsq + pslld m0, m4, 4 + paddd m5, m3 + pslld m2, m4, 3 + paddd m4, m0 + pslld m0, m5, 4 + paddd m4, m2 ; a * 25 + pslld m2, m5, 3 + paddd m5, m0 + paddd m5, m2 + punpcklwd m0, m1, m6 + punpckhwd m1, m6 + pmaddwd m2, m0, m0 ; b * b + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m2 ; p * s + MULLD m5, m9, m2 + pmaddwd m0, m10 ; b * 164 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, t2, t2m + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m2 + MULLD m1, m5, m2 + paddd m0, m12 ; x * b * 164 + (1 << 11) + (1 << 15) + paddd m1, m12 + mova [t4+wq*2+4], m3 + psrld m0, 12 ; b + psrld m1, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m1 + add wq, 8 + jl .v_loop + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*2+ 2] + movu m3, [t4+wq*2+ 4] + movu m1, [t3+wq*4+ 4] + movu m4, [t3+wq*4+ 8] + movu m2, [t3+wq*4+20] + movu m5, [t3+wq*4+24] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + paddw m3, [t4+wq*2+ 0] + paddd m4, [t3+wq*4+ 0] + paddd m5, [t3+wq*4+16] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + mova [t4+wq*2+400*2+ 0], m0 + mova [t3+wq*4+400*4+ 0], m1 + mova [t3+wq*4+400*4+16], m2 + add wq, 8 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m0, [t4+wq*2+ 2] + movu m3, [t4+wq*2+ 4] + movu m1, [t3+wq*4+ 4] + movu m4, [t3+wq*4+ 8] + movu m2, [t3+wq*4+20] + movu m5, [t3+wq*4+24] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + paddw m3, [t4+wq*2+ 0] + paddd m4, [t3+wq*4+ 0] + paddd m5, [t3+wq*4+16] + paddw m0, m3 + psllw m3, 2 + paddd m1, m4 + pslld m4, 2 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a 565 + paddd m1, m4 ; b 565 + paddd m2, m5 + paddw m3, m0, [t4+wq*2+400*2+ 0] + paddd m4, m1, [t3+wq*4+400*4+ 0] + paddd m5, m2, [t3+wq*4+400*4+16] + mova [t4+wq*2+400*2+ 0], m0 + mova [t3+wq*4+400*4+ 0], m1 + mova [t3+wq*4+400*4+16], m2 + movq m0, [dstq+wq] + punpcklbw m0, m6 + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n0_loop + add dstq, stridemp + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + movq m0, [dstq+wq] + mova m3, [t4+wq*2+400*2+ 0] + mova m4, [t3+wq*4+400*4+ 0] + mova m5, [t3+wq*4+400*4+16] + punpcklbw m0, m6 + punpcklwd m1, m0, m6 ; src + punpcklwd m2, m3, m6 ; a + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 7) + psubd m5, m3 + psrad m4, 8 + psrad m5, 8 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 4*16 + %else + %assign extra_stack 2*16 + %endif +cglobal sgr_filter_3x3_8bpc, 1, 7, 8, -400*42-16-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*2+4*0] + %define stridemp dword [esp+calloff+16*2+4*1] + %define leftm dword [esp+calloff+16*2+4*2] + %define lpfm dword [esp+calloff+16*2+4*3] + %define w0m dword [esp+calloff+16*2+4*4] + %define hd dword [esp+calloff+16*2+4*5] + %define edgeb byte [esp+calloff+16*2+4*6] + %define edged dword [esp+calloff+16*2+4*6] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t3m dword [esp+calloff+4*2] + %define t4m dword [esp+calloff+4*3] + %define m8 [base+pb_0to15] + %define m9 [esp+calloff+16*1] + %define m10 [base+pd_0xf00801c7] + %define m11 [base+pd_34816] + %define m12 m6 + %define m13 [base+sgr_lshuf3] + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +cglobal sgr_filter_3x3_8bpc, 4, 15, 14, -400*42-8, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + mov wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + mov hd, hm + mov edged, r7m + movq m9, [paramsq+4] + add lpfq, wq + lea t1, [rsp+wq*2+12] + mova m8, [pb_0to15] + add dstq, wq + lea t3, [rsp+wq*4+400*12+8] + mova m10, [pd_0xf00801c7] + lea t4, [rsp+wq*2+400*32+8] + mova m11, [pd_34816] + pshuflw m7, m9, q3333 + pshufb m9, [pw_256] ; s1 + punpcklqdq m7, m7 ; w1 + neg wq + pxor m6, m6 + mova m13, [sgr_lshuf3] + psllw m7, 4 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + movq m1, [r1+4] + add lpfm, wq + lea t1, [rsp+extra_stack+wq*2+20] + add dstq, wq + lea t3, [rsp+extra_stack+wq*4+400*12+16] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq*2+400*32+16] + mov t3m, t3 + pshuflw m7, m1, q3333 + mov t4m, t4 + pshufb m1, [base+pw_256] ; s1 + punpcklqdq m7, m7 ; w1 + psllw m7, 4 + neg wq + mova m9, m1 + pxor m6, m6 + mov w1m, wd + sub wd, 2 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + mov t2, t1 + add t1, 400*6 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t4, t4m + call .hv0 +.main: + dec hd + jz .height1 + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv0 +%if ARCH_X86_64 + test hb, hb +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .hv0_bottom + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wq, w0m + mov hvsrcm, lpfq +%endif + lea t2, [t1+400*6] +.top_fixup_loop: + mova m0, [t1+wq*2+400*0] + mova m1, [t1+wq*2+400*2] + mova m2, [t1+wq*2+400*4] + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m1 + mova [t2+wq*2+400*4], m2 + add wq, 8 + jl .top_fixup_loop + movif32 t3, t3m + movif32 t4, t4m + call .v0 + jmp .main +.extend_right: +%assign stack_offset stack_offset+8 +%assign calloff 8 + movd m0, [lpfq-1] + movd m1, wd + mova m3, m8 + pshufb m0, m6 + pshufb m1, m6 + mova m2, m6 + psubb m2, m1 + pcmpgtb m2, m3 + pand m5, m2 + pandn m2, m0 + por m5, m2 + ret +%assign stack_offset stack_offset-4 +%assign calloff 4 +.h: ; horizontal boxsum +%if ARCH_X86_64 + lea wq, [r4-2] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 14 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, m13 + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-2] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m5, [lpfq+wq] +.h_main: + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .h_have_right + cmp wd, -9 + jl .h_have_right + call .extend_right +.h_have_right: + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + mova [t1+wq*2+400*0], m1 + mova [t1+wq*2+400*2], m2 + mova [t1+wq*2+400*4], m3 + add wq, 8 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab (even rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 14 + jmp .hv0_main +.hv0_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, m13 + jmp .hv0_main +.hv0_bottom: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv0_loop_start +%endif +.hv0_loop: + movif32 lpfq, hvsrcm +.hv0_loop_start: + movu m5, [lpfq+wq] +.hv0_main: + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv0_have_right + cmp wd, -9 + jl .hv0_have_right + call .extend_right +.hv0_have_right: + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + palignr m0, m5, m4, 2 + paddw m1, m4, m0 + punpcklwd m2, m4, m0 + pmaddwd m2, m2 + punpckhwd m3, m4, m0 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m1, m5 ; sum + punpcklwd m4, m5, m6 + pmaddwd m4, m4 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m4 ; sumsq + paddd m3, m5 + paddw m0, m1, [t1+wq*2+400*0] + paddd m4, m2, [t1+wq*2+400*2] + paddd m5, m3, [t1+wq*2+400*4] + mova [t1+wq*2+400*0], m1 + mova [t1+wq*2+400*2], m2 + mova [t1+wq*2+400*4], m3 + paddw m1, m0, [t2+wq*2+400*0] + paddd m2, m4, [t2+wq*2+400*2] + paddd m3, m5, [t2+wq*2+400*4] + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m4 + mova [t2+wq*2+400*4], m5 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a * 9 + paddd m5, m3 + punpcklwd m0, m1, m6 ; b + pmaddwd m2, m0, m0 ; b * b + punpckhwd m1, m6 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m12 ; p * s + MULLD m5, m9, m12 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m12 + MULLD m1, m5, m12 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*2+4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m1 + add wq, 8 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 14 + jmp .hv1_main +.hv1_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, m13 + jmp .hv1_main +.hv1_bottom: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv1_loop_start +%endif +.hv1_loop: + movif32 lpfq, hvsrcm +.hv1_loop_start: + movu m5, [lpfq+wq] +.hv1_main: + test edgeb, 2 ; LR_HAVE_RIGHT + jnz .hv1_have_right + cmp wd, -9 + jl .hv1_have_right + call .extend_right +.hv1_have_right: + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + palignr m1, m5, m4, 2 + paddw m0, m4, m1 + punpcklwd m2, m4, m1 + pmaddwd m2, m2 + punpckhwd m3, m4, m1 + pmaddwd m3, m3 + palignr m5, m4, 4 + paddw m0, m5 ; h sum + punpcklwd m1, m5, m6 + pmaddwd m1, m1 + punpckhwd m5, m6 + pmaddwd m5, m5 + paddd m2, m1 ; h sumsq + paddd m3, m5 + paddw m1, m0, [t2+wq*2+400*0] + paddd m4, m2, [t2+wq*2+400*2] + paddd m5, m3, [t2+wq*2+400*4] + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m2 + mova [t2+wq*2+400*4], m3 + pslld m2, m4, 3 + pslld m3, m5, 3 + paddd m4, m2 ; a * 9 + paddd m5, m3 + punpcklwd m0, m1, m6 ; b + pmaddwd m2, m0, m0 ; b * b + punpckhwd m1, m6 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m12 ; p * s + MULLD m5, m9, m12 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + movif32 t3, t3m + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m12 + MULLD m1, m5, m12 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*2+400*2 +4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+400*4+ 8], m0 + mova [t3+wq*4+400*4+24], m1 + add wq, 8 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab (even rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.v0_loop: + mova m0, [t1+wq*2+400*0] + mova m4, [t1+wq*2+400*2] + mova m5, [t1+wq*2+400*4] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+wq*2+400*0] + paddd m2, m4, [t2+wq*2+400*2] + paddd m3, m5, [t2+wq*2+400*4] + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m4 + mova [t2+wq*2+400*4], m5 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a * 9 + paddd m5, m3 + punpcklwd m0, m1, m6 ; b + pmaddwd m2, m0, m0 ; b * b + punpckhwd m1, m6 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m12 ; p * s + MULLD m5, m9, m12 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m12 + MULLD m1, m5, m12 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*2+4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m1 + add wq, 8 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.v1_loop: + mova m0, [t1+wq*2+400*0] + mova m4, [t1+wq*2+400*2] + mova m5, [t1+wq*2+400*4] + paddw m1, m0, [t2+wq*2+400*0] + paddd m2, m4, [t2+wq*2+400*2] + paddd m3, m5, [t2+wq*2+400*4] + mova [t2+wq*2+400*0], m0 + mova [t2+wq*2+400*2], m4 + mova [t2+wq*2+400*4], m5 + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a * 9 + paddd m5, m3 + punpcklwd m0, m1, m6 ; b + pmaddwd m2, m0, m0 ; b * b + punpckhwd m1, m6 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p + psubd m5, m3 + MULLD m4, m9, m12 ; p * s + MULLD m5, m9, m12 + pmaddwd m0, m10 ; b * 455 + pmaddwd m1, m10 + paddusw m4, m10 + paddusw m5, m10 + psrld m4, 20 ; min(z, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m12 + MULLD m1, m5, m12 +%if ARCH_X86_32 + pxor m6, m6 +%endif + paddd m0, m11 ; x * b * 455 + (1 << 11) + (1 << 15) + paddd m1, m11 + mova [t4+wq*2+400*2+ 4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+400*4+ 8], m0 + mova [t3+wq*4+400*4+24], m1 + add wq, 8 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*2+400*0+ 4] + movu m1, [t3+wq*4+400*0+ 8] + movu m2, [t3+wq*4+400*0+24] + movu m3, [t4+wq*2+400*0+ 2] + movu m4, [t3+wq*4+400*0+ 4] + movu m5, [t3+wq*4+400*0+20] + paddw m0, [t4+wq*2+400*0+ 0] + paddd m1, [t3+wq*4+400*0+ 0] + paddd m2, [t3+wq*4+400*0+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a[-1] 444 + pslld m4, 2 ; b[-1] 444 + pslld m5, 2 + psubw m3, m0 ; a[-1] 343 + psubd m4, m1 ; b[-1] 343 + psubd m5, m2 + mova [t4+wq*2+400*4], m3 + mova [t3+wq*4+400*8+ 0], m4 + mova [t3+wq*4+400*8+16], m5 + movu m0, [t4+wq*2+400*2+ 4] + movu m1, [t3+wq*4+400*4+ 8] + movu m2, [t3+wq*4+400*4+24] + movu m3, [t4+wq*2+400*2+ 2] + movu m4, [t3+wq*4+400*4+ 4] + movu m5, [t3+wq*4+400*4+20] + paddw m0, [t4+wq*2+400*2+ 0] + paddd m1, [t3+wq*4+400*4+ 0] + paddd m2, [t3+wq*4+400*4+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a[ 0] 444 + pslld m4, 2 ; b[ 0] 444 + pslld m5, 2 + mova [t4+wq*2+400* 6], m3 + mova [t3+wq*4+400*12+ 0], m4 + mova [t3+wq*4+400*12+16], m5 + psubw m3, m0 ; a[ 0] 343 + psubd m4, m1 ; b[ 0] 343 + psubd m5, m2 + mova [t4+wq*2+400* 8], m3 + mova [t3+wq*4+400*16+ 0], m4 + mova [t3+wq*4+400*16+16], m5 + add wq, 8 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m3, [t4+wq*2+400*0+4] + movu m1, [t4+wq*2+400*0+2] + paddw m3, [t4+wq*2+400*0+0] + paddw m1, m3 + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+wq*2+400*4] + paddw m3, [t4+wq*2+400*6] + mova [t4+wq*2+400*4], m2 + mova [t4+wq*2+400*6], m1 + movu m4, [t3+wq*4+400*0+8] + movu m1, [t3+wq*4+400*0+4] + paddd m4, [t3+wq*4+400*0+0] + paddd m1, m4 + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+wq*4+400* 8+ 0] + paddd m4, [t3+wq*4+400*12+ 0] + mova [t3+wq*4+400* 8+ 0], m2 + mova [t3+wq*4+400*12+ 0], m1 + movu m5, [t3+wq*4+400*0+24] + movu m1, [t3+wq*4+400*0+20] + paddd m5, [t3+wq*4+400*0+16] + paddd m1, m5 + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+wq*4+400* 8+16] + paddd m5, [t3+wq*4+400*12+16] + mova [t3+wq*4+400* 8+16], m2 + mova [t3+wq*4+400*12+16], m1 + movq m0, [dstq+wq] + punpcklbw m0, m6 + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n0_loop + add dstq, stridemp + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + movu m3, [t4+wq*2+400*2+4] + movu m1, [t4+wq*2+400*2+2] + paddw m3, [t4+wq*2+400*2+0] + paddw m1, m3 + psllw m1, 2 ; a[ 1] 444 + psubw m2, m1, m3 ; a[ 1] 343 + paddw m3, m2, [t4+wq*2+400*6] + paddw m3, [t4+wq*2+400*8] + mova [t4+wq*2+400*6], m1 + mova [t4+wq*2+400*8], m2 + movu m4, [t3+wq*4+400*4+8] + movu m1, [t3+wq*4+400*4+4] + paddd m4, [t3+wq*4+400*4+0] + paddd m1, m4 + pslld m1, 2 ; b[ 1] 444 + psubd m2, m1, m4 ; b[ 1] 343 + paddd m4, m2, [t3+wq*4+400*12+ 0] + paddd m4, [t3+wq*4+400*16+ 0] + mova [t3+wq*4+400*12+ 0], m1 + mova [t3+wq*4+400*16+ 0], m2 + movu m5, [t3+wq*4+400*4+24] + movu m1, [t3+wq*4+400*4+20] + paddd m5, [t3+wq*4+400*4+16] + paddd m1, m5 + pslld m1, 2 + psubd m2, m1, m5 + paddd m5, m2, [t3+wq*4+400*12+16] + paddd m5, [t3+wq*4+400*16+16] + mova [t3+wq*4+400*12+16], m1 + mova [t3+wq*4+400*16+16], m2 + movq m0, [dstq+wq] + punpcklbw m0, m6 + punpcklwd m1, m0, m6 + punpcklwd m2, m3, m6 + pmaddwd m2, m1 ; a * src + punpckhwd m1, m0, m6 + punpckhwd m3, m6 + pmaddwd m3, m1 + psubd m4, m2 ; b - a * src + (1 << 8) + psubd m5, m3 + psrad m4, 9 + psrad m5, 9 + packssdw m4, m5 + pmulhrsw m4, m7 + paddw m0, m4 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < 16 + %assign extra_stack 10*16 + %else + %assign extra_stack 8*16 + %endif +cglobal sgr_filter_mix_8bpc, 1, 7, 8, -400*66-48-extra_stack, \ + dst, stride, left, lpf, w + %if STACK_ALIGNMENT < 16 + %define dstm dword [esp+calloff+16*8+4*0] + %define stridemp dword [esp+calloff+16*8+4*1] + %define leftm dword [esp+calloff+16*8+4*2] + %define lpfm dword [esp+calloff+16*8+4*3] + %define w0m dword [esp+calloff+16*8+4*4] + %define hd dword [esp+calloff+16*8+4*5] + %define edgeb byte [esp+calloff+16*8+4*6] + %define edged dword [esp+calloff+16*8+4*6] + %define leftmp leftm + %else + %define w0m wm + %define hd dword r5m + %define edgeb byte r7m + %define edged dword r7m + %endif + %define hvsrcm dword [esp+calloff+4*0] + %define w1m dword [esp+calloff+4*1] + %define t3m dword [esp+calloff+4*2] + %define t4m dword [esp+calloff+4*3] + %xdefine m8 m6 + %define m9 [base+pd_0xffff] + %define m10 [base+pd_34816] + %define m11 [base+pd_0xf00801c7] + %define m12 [base+pd_0xf00800a4] + %define m13 [esp+calloff+16*4] + %define m14 [esp+calloff+16*5] + %define m15 [esp+calloff+16*6] + %define m6 [esp+calloff+16*7] + %define base r6-$$ + %assign calloff 0 + %if STACK_ALIGNMENT < 16 + mov strideq, [rstk+stack_offset+ 8] + mov leftq, [rstk+stack_offset+12] + mov lpfq, [rstk+stack_offset+16] + mov wd, [rstk+stack_offset+20] + mov dstm, dstq + mov stridemp, strideq + mov leftm, leftq + mov r1, [rstk+stack_offset+24] + mov r2, [rstk+stack_offset+32] + mov lpfm, lpfq + mov hd, r1 + mov edged, r2 + %endif +%else +cglobal sgr_filter_mix_8bpc, 4, 15, 16, -400*66-40, dst, stride, left, lpf, \ + w, h, edge, params +%endif +%if ARCH_X86_64 || STACK_ALIGNMENT >= 16 + mov wd, wm +%endif +%if ARCH_X86_64 + mov paramsq, r6mp + lea r13, [sgr_x_by_x-0xf03] + movifnidn hd, hm + mov edged, r7m + mova m15, [paramsq] + add lpfq, wq + mova m9, [pd_0xffff] + lea t1, [rsp+wq*2+44] + mova m10, [pd_34816] + add dstq, wq + lea t3, [rsp+wq*4+400*24+40] + mova m11, [pd_0xf00801c7] + lea t4, [rsp+wq*2+400*52+40] + mova m12, [base+pd_0xf00800a4] + neg wq + pshuflw m13, m15, q0000 + pshuflw m14, m15, q2222 + pshufhw m15, m15, q1010 + punpcklqdq m13, m13 ; s0 + punpcklqdq m14, m14 ; s1 + punpckhqdq m15, m15 ; w0 w1 + pxor m6, m6 + psllw m15, 2 + DEFINE_ARGS dst, stride, left, lpf, _, h, edge, _, _, _, w + %define lpfm [rsp] +%else + mov r1, [rstk+stack_offset+28] ; params + LEA r6, $$ + mova m2, [r1] + add lpfm, wq + lea t1, [rsp+extra_stack+wq*2+52] + add dstq, wq + lea t3, [rsp+extra_stack+wq*4+400*24+48] + mov dstm, dstq + lea t4, [rsp+extra_stack+wq*2+400*52+48] + mov t3m, t3 + mov t4m, t4 + neg wq + pshuflw m0, m2, q0000 + pshuflw m1, m2, q2222 + pshufhw m2, m2, q1010 + punpcklqdq m0, m0 ; s0 + punpcklqdq m1, m1 ; s1 + punpckhqdq m2, m2 ; w0 w1 + mov w1m, wd + pxor m3, m3 + psllw m2, 2 + mova m13, m0 + mova m14, m1 + sub wd, 2 + mova m15, m2 + mova m6, m3 + mov lpfq, lpfm + mov w0m, wd + %define strideq r5 +%endif + test edgeb, 4 ; LR_HAVE_TOP + jz .no_top + call .h_top + add lpfq, stridemp + mov t2, t1 +%if ARCH_X86_64 + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_ssse3).top_fixup +%else + mov wq, w0m + call mangle(private_prefix %+ _sgr_filter_5x5_8bpc_ssse3).top_fixup_loop +%endif + add t1, 400*12 + call .h_top + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + add r10, strideq + mov lpfm, r10 ; below + movif32 t4, t4m + call .hv0 +.main: + dec hd + jz .height1 + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .prep_n + sub hd, 2 + jl .extend_bottom +.main_loop: + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv0 +%if ARCH_X86_64 + test hd, hd +%else + mov r4, hd + test r4, r4 +%endif + jz .odd_height + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1 + call .n0 + call .n1 + sub hd, 2 + jge .main_loop + test edgeb, 8 ; LR_HAVE_BOTTOM + jz .extend_bottom + mov lpfq, lpfm + call .hv0_bottom + movif32 lpfq, hvsrcm + add lpfq, stridemp + call .hv1_bottom +.end: + call .n0 + call .n1 +.end2: + RET +.height1: + call .v1 + call .prep_n + jmp .odd_height_end +.odd_height: + call .v1 + call .n0 + call .n1 +.odd_height_end: + call .v0 + call .v1 + call .n0 + jmp .end2 +.extend_bottom: + call .v0 + call .v1 + jmp .end +.no_top: + movif32 strideq, stridemp + lea r10, [lpfq+strideq*4] + mov lpfq, dstq + lea r10, [r10+strideq*2] + mov lpfm, r10 + call .h +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wq, w0m + mov hvsrcm, lpfq +%endif + lea t2, [t1+400*12] +.top_fixup_loop: + mova m0, [t1+wq*2+400* 0] + mova m1, [t1+wq*2+400* 2] + mova m2, [t1+wq*2+400* 4] + paddw m0, m0 + mova m3, [t1+wq*2+400* 6] + paddd m1, m1 + mova m4, [t1+wq*2+400* 8] + paddd m2, m2 + mova m5, [t1+wq*2+400*10] + mova [t2+wq*2+400* 0], m0 + mova [t2+wq*2+400* 2], m1 + mova [t2+wq*2+400* 4], m2 + mova [t2+wq*2+400* 6], m3 + mova [t2+wq*2+400* 8], m4 + mova [t2+wq*2+400*10], m5 + add wq, 8 + jl .top_fixup_loop + movif32 t3, t3m + movif32 t4, t4m + call .v0 + jmp .main +.extend_right: +%assign stack_offset stack_offset+8 +%assign calloff 8 +%if ARCH_X86_64 + SWAP m8, m6 +%endif + movd m1, wd + movd m3, [lpfq-1] + pshufb m1, m8 + pshufb m3, m8 + psubb m2, [base+pb_1], m1 + pcmpgtb m2, [base+pb_0to15] + pand m5, m2 + pandn m2, m3 + por m5, m2 +%if ARCH_X86_64 + SWAP m6, m8 +%endif + ret +%assign stack_offset stack_offset-4 +%assign calloff 4 +.h: ; horizontal boxsum +%if ARCH_X86_64 + lea wq, [r4-2] +%else + %define leftq r4 +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 13 + jmp .h_main +.h_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, [base+sgr_lshuf5] + jmp .h_main +.h_top: +%if ARCH_X86_64 + lea wq, [r4-2] +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .h_extend_left + movif32 wq, w0m +.h_loop: + movu m5, [lpfq+wq-1] +.h_main: + test edgeb, 2 ; LR_HAVE_RIGHT +%if ARCH_X86_32 + pxor m8, m8 +%else + SWAP m8, m6 +%endif + jnz .h_have_right + cmp wd, -10 + jl .h_have_right + call .extend_right +.h_have_right: + punpcklbw m4, m5, m8 + punpckhbw m5, m8 + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; sum3 + punpcklwd m7, m0, m8 + pmaddwd m7, m7 + punpckhwd m0, m8 + pmaddwd m0, m0 +%if ARCH_X86_64 + SWAP m6, m8 +%endif + paddd m2, m7 ; sumsq3 + palignr m5, m4, 8 + punpcklwd m7, m5, m4 + paddw m8, m4, m5 + pmaddwd m7, m7 + punpckhwd m5, m4 + pmaddwd m5, m5 + paddd m3, m0 + mova [t1+wq*2+400* 6], m1 + mova [t1+wq*2+400* 8], m2 + mova [t1+wq*2+400*10], m3 + paddw m8, m1 ; sum5 + paddd m7, m2 ; sumsq5 + paddd m5, m3 + mova [t1+wq*2+400* 0], m8 + mova [t1+wq*2+400* 2], m7 + mova [t1+wq*2+400* 4], m5 + add wq, 8 + jl .h_loop + ret +ALIGN function_align +.hv0: ; horizontal boxsum + vertical boxsum + ab3 (even rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 13 + jmp .hv0_main +.hv0_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, [base+sgr_lshuf5] + jmp .hv0_main +.hv0_bottom: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv0_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv0_loop_start +%endif +.hv0_loop: + movif32 lpfq, hvsrcm +.hv0_loop_start: + movu m5, [lpfq+wq-1] +.hv0_main: + test edgeb, 2 ; LR_HAVE_RIGHT +%if ARCH_X86_32 + pxor m8, m8 +%else + SWAP m8, m6 +%endif + jnz .hv0_have_right + cmp wd, -10 + jl .hv0_have_right + call .extend_right +.hv0_have_right: + punpcklbw m4, m5, m8 + punpckhbw m5, m8 + palignr m3, m5, m4, 2 + palignr m0, m5, m4, 4 + movif32 t3, t3m + paddw m1, m3, m0 + punpcklwd m2, m3, m0 + pmaddwd m2, m2 + punpckhwd m3, m0 + pmaddwd m3, m3 + palignr m0, m5, m4, 6 + paddw m1, m0 ; h sum3 + punpcklwd m7, m0, m8 + pmaddwd m7, m7 + punpckhwd m0, m8 +%if ARCH_X86_64 + SWAP m6, m8 +%endif + pmaddwd m0, m0 + paddd m2, m7 ; h sumsq3 + palignr m5, m4, 8 + punpcklwd m7, m5, m4 + paddw m8, m4, m5 + pmaddwd m7, m7 + punpckhwd m5, m4 + pmaddwd m5, m5 + paddd m3, m0 + paddw m8, m1 ; h sum5 + paddd m7, m2 ; h sumsq5 + paddd m5, m3 + mova [t3+wq*4+400*8+ 8], m8 + mova [t3+wq*4+400*0+ 8], m7 + mova [t3+wq*4+400*0+24], m5 + paddw m8, [t1+wq*2+400* 0] + paddd m7, [t1+wq*2+400* 2] + paddd m5, [t1+wq*2+400* 4] + mova [t1+wq*2+400* 0], m8 + mova [t1+wq*2+400* 2], m7 + mova [t1+wq*2+400* 4], m5 + paddw m0, m1, [t1+wq*2+400* 6] + paddd m4, m2, [t1+wq*2+400* 8] + paddd m5, m3, [t1+wq*2+400*10] + mova [t1+wq*2+400* 6], m1 + mova [t1+wq*2+400* 8], m2 + mova [t1+wq*2+400*10], m3 + paddw m1, m0, [t2+wq*2+400* 6] + paddd m2, m4, [t2+wq*2+400* 8] + paddd m3, m5, [t2+wq*2+400*10] + mova [t2+wq*2+400* 6], m0 + mova [t2+wq*2+400* 8], m4 + mova [t2+wq*2+400*10], m5 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a3 * 9 + paddd m5, m3 + punpcklwd m0, m1, m7 ; b3 + pmaddwd m2, m0, m0 + punpckhwd m1, m7 + pmaddwd m3, m1, m1 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + psubd m4, m2 ; p3 + psubd m5, m3 + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*2+400*2+ 4], m3 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+400*4+ 8], m0 + mova [t3+wq*4+400*4+24], m1 + add wq, 8 + jl .hv0_loop + ret +ALIGN function_align +.hv1: ; horizontal boxsums + vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 leftq, leftm + movddup m4, [leftq-4] + movif32 wq, w0m + mova m5, [lpfq+wq+2] + add leftmp, 4 + palignr m5, m4, 13 + jmp .hv1_main +.hv1_extend_left: + movif32 wq, w0m + mova m5, [lpfq+wq+2] + pshufb m5, [base+sgr_lshuf5] + jmp .hv1_main +.hv1_bottom: +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov hvsrcm, lpfq +%endif + test edgeb, 1 ; LR_HAVE_LEFT + jz .hv1_extend_left + movif32 wq, w0m +%if ARCH_X86_32 + jmp .hv1_loop_start +%endif +.hv1_loop: + movif32 lpfq, hvsrcm +.hv1_loop_start: + movu m5, [lpfq+wq-1] +.hv1_main: + test edgeb, 2 ; LR_HAVE_RIGHT +%if ARCH_X86_32 + pxor m8, m8 +%else + SWAP m8, m6 +%endif + jnz .hv1_have_right + cmp wd, -10 + jl .hv1_have_right + call .extend_right +.hv1_have_right: + punpcklbw m4, m5, m8 + punpckhbw m5, m8 + palignr m7, m5, m4, 2 + palignr m3, m5, m4, 4 + paddw m2, m7, m3 + punpcklwd m0, m7, m3 + pmaddwd m0, m0 + punpckhwd m7, m3 + pmaddwd m7, m7 + palignr m3, m5, m4, 6 + paddw m2, m3 ; h sum3 + punpcklwd m1, m3, m8 + pmaddwd m1, m1 + punpckhwd m3, m8 +%if ARCH_X86_64 + SWAP m6, m8 +%endif + pmaddwd m3, m3 + paddd m0, m1 ; h sumsq3 + palignr m5, m4, 8 + punpckhwd m1, m4, m5 + paddw m8, m4, m5 + pmaddwd m1, m1 + punpcklwd m4, m5 + pmaddwd m4, m4 + paddd m7, m3 + paddw m5, m2, [t2+wq*2+400* 6] + mova [t2+wq*2+400* 6], m2 + paddw m8, m2 ; h sum5 + paddd m2, m0, [t2+wq*2+400* 8] + paddd m3, m7, [t2+wq*2+400*10] + mova [t2+wq*2+400* 8], m0 + mova [t2+wq*2+400*10], m7 + paddd m4, m0 ; h sumsq5 + paddd m1, m7 + pslld m0, m2, 3 + pslld m7, m3, 3 + paddd m2, m0 ; a3 * 9 + paddd m3, m7 +%if ARCH_X86_32 + mova [esp+20], m8 + pxor m8, m8 +%else + SWAP m8, m6 +%endif + punpcklwd m0, m5, m8 ; b3 + pmaddwd m7, m0, m0 + punpckhwd m5, m8 + pmaddwd m8, m5, m5 + psubd m2, m7 ; p3 + psubd m3, m8 + MULLD m2, m14, m8 ; p3 * s1 + MULLD m3, m14, m8 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m5, m11 + paddusw m2, m11 + paddusw m3, m11 + psrld m2, 20 ; min(z3, 255) + movif32 t3, t3m + psrld m3, 20 + GATHER_X_BY_X m8, m2, m3, r0, dstm + punpcklwd m2, m8, m8 + punpckhwd m3, m8, m8 + MULLD m0, m2, m7 + MULLD m5, m3, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m5, m10 + psrld m0, 12 + psrld m5, 12 + mova [t4+wq*2+400*4+ 4], m8 + mova [t3+wq*4+400*8+ 8], m0 + mova [t3+wq*4+400*8+24], m5 +%if ARCH_X86_32 + mova m8, [esp+20] +%else + SWAP m6, m8 + pxor m6, m6 +%endif + paddw m5, m8, [t2+wq*2+400*0] + paddd m2, m4, [t2+wq*2+400*2] + paddd m3, m1, [t2+wq*2+400*4] + paddw m5, [t1+wq*2+400*0] + paddd m2, [t1+wq*2+400*2] + paddd m3, [t1+wq*2+400*4] + mova [t2+wq*2+400*0], m8 + pslld m0, m2, 4 + mova [t2+wq*2+400*2], m4 + pslld m8, m3, 4 + mova [t2+wq*2+400*4], m1 + pslld m4, m2, 3 + paddd m2, m0 + pslld m7, m3, 3 + paddd m3, m8 + paddd m2, m4 ; a5 * 25 + paddd m3, m7 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + punpcklwd m0, m5, m7 ; b5 + pmaddwd m4, m0, m0 + punpckhwd m5, m7 + pmaddwd m1, m5, m5 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + psubd m2, m4 ; p5 + psubd m3, m1 + MULLD m2, m13, m7 ; p5 * s0 + MULLD m3, m13, m7 + pmaddwd m0, m12 ; b5 * 164 + pmaddwd m5, m12 + paddusw m2, m12 + paddusw m3, m12 + psrld m2, 20 ; min(z5, 255) + psrld m3, 20 + GATHER_X_BY_X m1, m2, m3, r0, dstm + punpcklwd m2, m1, m1 + punpckhwd m3, m1, m1 + MULLD m0, m2, m7 + MULLD m5, m3, m7 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m5, m10 + mova [t4+wq*2+4], m1 + psrld m0, 12 + psrld m5, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m5 + add wq, 8 + jl .hv1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.v0: ; vertical boxsums + ab3 (even rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.v0_loop: + mova m0, [t1+wq*2+400* 6] + mova m4, [t1+wq*2+400* 8] + mova m5, [t1+wq*2+400*10] + paddw m0, m0 + paddd m4, m4 + paddd m5, m5 + paddw m1, m0, [t2+wq*2+400* 6] + paddd m2, m4, [t2+wq*2+400* 8] + paddd m3, m5, [t2+wq*2+400*10] + mova [t2+wq*2+400* 6], m0 + mova [t2+wq*2+400* 8], m4 + mova [t2+wq*2+400*10], m5 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; a3 * 9 + paddd m5, m3 + punpcklwd m0, m1, m7 ; b3 + pmaddwd m2, m0, m0 + punpckhwd m1, m7 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p3 + psubd m5, m3 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*2+400*2+4], m3 + psrld m0, 12 + psrld m1, 12 + mova m3, [t1+wq*2+400*0] + mova m4, [t1+wq*2+400*2] + mova m5, [t1+wq*2+400*4] + mova [t3+wq*4+400*8+ 8], m3 + mova [t3+wq*4+400*0+ 8], m4 + mova [t3+wq*4+400*0+24], m5 + paddw m3, m3 ; cc5 + paddd m4, m4 + paddd m5, m5 + mova [t1+wq*2+400*0], m3 + mova [t1+wq*2+400*2], m4 + mova [t1+wq*2+400*4], m5 + mova [t3+wq*4+400*4+ 8], m0 + mova [t3+wq*4+400*4+24], m1 + add wq, 8 + jl .v0_loop + ret +.v1: ; vertical boxsums + ab (odd rows) +%if ARCH_X86_64 + lea wq, [r4-2] +%else + mov wd, w0m +%endif +.v1_loop: + mova m4, [t1+wq*2+400* 6] + mova m5, [t1+wq*2+400* 8] + mova m7, [t1+wq*2+400*10] + paddw m1, m4, [t2+wq*2+400* 6] + paddd m2, m5, [t2+wq*2+400* 8] + paddd m3, m7, [t2+wq*2+400*10] + mova [t2+wq*2+400* 6], m4 + mova [t2+wq*2+400* 8], m5 + mova [t2+wq*2+400*10], m7 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + pslld m4, m2, 3 + pslld m5, m3, 3 + paddd m4, m2 ; ((a3 + 8) >> 4) * 9 + paddd m5, m3 + punpcklwd m0, m1, m7 ; b3 + pmaddwd m2, m0, m0 + punpckhwd m1, m7 + pmaddwd m3, m1, m1 + psubd m4, m2 ; p3 + psubd m5, m3 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MULLD m4, m14, m7 ; p3 * s1 + MULLD m5, m14, m7 + pmaddwd m0, m11 ; b3 * 455 + pmaddwd m1, m11 + paddusw m4, m11 + paddusw m5, m11 + psrld m4, 20 ; min(z3, 255) + psrld m5, 20 + GATHER_X_BY_X m3, m4, m5, r0, dstm + punpcklwd m4, m3, m3 + punpckhwd m5, m3, m3 + MULLD m0, m4, m7 + MULLD m1, m5, m7 + paddd m0, m10 ; x3 * b3 * 455 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*2+400*4+4], m3 + psrld m0, 12 + psrld m8, m1, 12 + mova m4, [t3+wq*4+400*8+ 8] + mova m5, [t3+wq*4+400*0+ 8] + mova m7, [t3+wq*4+400*0+24] + paddw m1, m4, [t2+wq*2+400*0] + paddd m2, m5, [t2+wq*2+400*2] + paddd m3, m7, [t2+wq*2+400*4] + paddw m1, [t1+wq*2+400*0] + paddd m2, [t1+wq*2+400*2] + paddd m3, [t1+wq*2+400*4] + mova [t2+wq*2+400*0], m4 + mova [t2+wq*2+400*2], m5 + mova [t2+wq*2+400*4], m7 + pslld m4, m2, 4 + mova [t3+wq*4+400*8+ 8], m0 + pslld m5, m3, 4 + mova [t3+wq*4+400*8+24], m8 + pslld m7, m2, 3 + paddd m2, m4 + pslld m8, m3, 3 + paddd m3, m5 + paddd m2, m7 ; a5 * 25 + paddd m3, m8 +%if ARCH_X86_32 + pxor m7, m7 +%else + SWAP m7, m6 +%endif + punpcklwd m0, m1, m7 ; b5 + pmaddwd m4, m0, m0 + punpckhwd m1, m7 + pmaddwd m5, m1, m1 + psubd m2, m4 ; p5 + psubd m3, m5 +%if ARCH_X86_64 + SWAP m7, m6 +%endif + MULLD m2, m13, m7 ; p5 * s0 + MULLD m3, m13, m7 + pmaddwd m0, m12 ; b5 * 164 + pmaddwd m1, m12 + paddusw m2, m12 + paddusw m3, m12 + psrld m2, 20 ; min(z5, 255) + psrld m3, 20 + GATHER_X_BY_X m4, m2, m3, r0, dstm + punpcklwd m2, m4, m4 + punpckhwd m3, m4, m4 + MULLD m0, m2, m7 + MULLD m1, m3, m7 + paddd m0, m10 ; x5 * b5 * 164 + (1 << 11) + (1 << 15) + paddd m1, m10 + mova [t4+wq*2+4], m4 + psrld m0, 12 + psrld m1, 12 + mova [t3+wq*4+ 8], m0 + mova [t3+wq*4+24], m1 + add wq, 8 + jl .v1_loop + mov r10, t2 + mov t2, t1 + mov t1, r10 + ret +.prep_n: ; initial neighbor setup + movif64 wq, r4 + movif32 wd, w1m +.prep_n_loop: + movu m0, [t4+wq*2+400*0+ 2] + movu m1, [t3+wq*4+400*0+ 4] + movu m2, [t3+wq*4+400*0+20] + movu m7, [t4+wq*2+400*0+ 4] + movu m8, [t3+wq*4+400*0+ 8] + paddw m3, m0, [t4+wq*2+400*0+ 0] + paddd m4, m1, [t3+wq*4+400*0+ 0] + paddd m5, m2, [t3+wq*4+400*0+16] + paddw m3, m7 + paddd m4, m8 + movu m7, [t3+wq*4+400*0+24] + paddw m0, m3 + paddd m1, m4 + psllw m3, 2 + pslld m4, 2 + paddd m5, m7 + paddd m2, m5 + pslld m5, 2 + paddw m0, m3 ; a5 565 + paddd m1, m4 ; b5 565 + paddd m2, m5 + mova [t4+wq*2+400* 6+ 0], m0 + mova [t3+wq*4+400*12+ 0], m1 + mova [t3+wq*4+400*12+16], m2 + movu m0, [t4+wq*2+400*2+ 4] + movu m1, [t3+wq*4+400*4+ 8] + movu m2, [t3+wq*4+400*4+24] + movu m3, [t4+wq*2+400*2+ 2] + movu m4, [t3+wq*4+400*4+ 4] + movu m5, [t3+wq*4+400*4+20] + paddw m0, [t4+wq*2+400*2+ 0] + paddd m1, [t3+wq*4+400*4+ 0] + paddd m2, [t3+wq*4+400*4+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a3[-1] 444 + pslld m4, 2 ; b3[-1] 444 + pslld m5, 2 + psubw m3, m0 ; a3[-1] 343 + psubd m4, m1 ; b3[-1] 343 + psubd m5, m2 + mova [t4+wq*2+400* 8+ 0], m3 + mova [t3+wq*4+400*16+ 0], m4 + mova [t3+wq*4+400*16+16], m5 + movu m0, [t4+wq*2+400*4+ 4] + movu m1, [t3+wq*4+400*8+ 8] + movu m2, [t3+wq*4+400*8+24] + movu m3, [t4+wq*2+400*4+ 2] + movu m4, [t3+wq*4+400*8+ 4] + movu m5, [t3+wq*4+400*8+20] + paddw m0, [t4+wq*2+400*4+ 0] + paddd m1, [t3+wq*4+400*8+ 0] + paddd m2, [t3+wq*4+400*8+16] + paddw m3, m0 + paddd m4, m1 + paddd m5, m2 + psllw m3, 2 ; a3[ 0] 444 + pslld m4, 2 ; b3[ 0] 444 + pslld m5, 2 + mova [t4+wq*2+400*10+ 0], m3 + mova [t3+wq*4+400*20+ 0], m4 + mova [t3+wq*4+400*20+16], m5 + psubw m3, m0 ; a3[ 0] 343 + psubd m4, m1 ; b3[ 0] 343 + psubd m5, m2 + mova [t4+wq*2+400*12+ 0], m3 + mova [t3+wq*4+400*24+ 0], m4 + mova [t3+wq*4+400*24+16], m5 + add wq, 8 + jl .prep_n_loop + ret +ALIGN function_align +.n0: ; neighbor + output (even rows) + movif64 wq, r4 + movif32 wd, w1m +.n0_loop: + movu m0, [t4+wq*2+ 4] + movu m2, [t4+wq*2+ 2] + paddw m0, [t4+wq*2+ 0] + paddw m0, m2 + paddw m2, m0 + psllw m0, 2 + paddw m0, m2 ; a5 + movu m4, [t3+wq*4+ 8] + movu m5, [t3+wq*4+24] + movu m1, [t3+wq*4+ 4] + movu m3, [t3+wq*4+20] + paddd m4, [t3+wq*4+ 0] + paddd m5, [t3+wq*4+16] + paddd m4, m1 + paddd m5, m3 + paddd m1, m4 + paddd m3, m5 + pslld m4, 2 + pslld m5, 2 + paddd m4, m1 ; b5 + paddd m5, m3 + movu m2, [t4+wq*2+400* 6] + paddw m2, m0 + mova [t4+wq*2+400* 6], m0 + paddd m0, m4, [t3+wq*4+400*12+ 0] + paddd m1, m5, [t3+wq*4+400*12+16] + mova [t3+wq*4+400*12+ 0], m4 + mova [t3+wq*4+400*12+16], m5 + mova [rsp+16+ARCH_X86_32*4], m1 + movu m3, [t4+wq*2+400*2+4] + movu m5, [t4+wq*2+400*2+2] + paddw m3, [t4+wq*2+400*2+0] + paddw m5, m3 + psllw m5, 2 ; a3[ 1] 444 + psubw m4, m5, m3 ; a3[ 1] 343 + movu m3, [t4+wq*2+400* 8] + paddw m3, [t4+wq*2+400*10] + paddw m3, m4 + mova [t4+wq*2+400* 8], m4 + mova [t4+wq*2+400*10], m5 + movu m1, [t3+wq*4+400*4+ 8] + movu m5, [t3+wq*4+400*4+ 4] + movu m7, [t3+wq*4+400*4+24] + movu m8, [t3+wq*4+400*4+20] + paddd m1, [t3+wq*4+400*4+ 0] + paddd m7, [t3+wq*4+400*4+16] + paddd m5, m1 + paddd m8, m7 + pslld m5, 2 ; b3[ 1] 444 + pslld m8, 2 + psubd m4, m5, m1 ; b3[ 1] 343 +%if ARCH_X86_32 + mova [esp+52], m8 + psubd m8, m7 +%else + psubd m6, m8, m7 + SWAP m8, m6 +%endif + paddd m1, m4, [t3+wq*4+400*16+ 0] + paddd m7, m8, [t3+wq*4+400*16+16] + paddd m1, [t3+wq*4+400*20+ 0] + paddd m7, [t3+wq*4+400*20+16] + mova [t3+wq*4+400*16+ 0], m4 + mova [t3+wq*4+400*16+16], m8 + mova [t3+wq*4+400*20+ 0], m5 +%if ARCH_X86_32 + mova m8, [esp+52] +%else + SWAP m8, m6 + pxor m6, m6 +%endif + mova [t3+wq*4+400*20+16], m8 + mova [rsp+32+ARCH_X86_32*4], m7 + movq m4, [dstq+wq] + punpcklbw m4, m6 + punpcklwd m5, m4, m6 + punpcklwd m7, m2, m6 + pmaddwd m7, m5 ; a5 * src + punpcklwd m8, m3, m6 + pmaddwd m8, m5 ; a3 * src + punpckhwd m5, m4, m6 + punpckhwd m2, m6 + pmaddwd m2, m5 + punpckhwd m3, m6 + pmaddwd m3, m5 + psubd m0, m7 ; b5 - a5 * src + (1 << 8) - (src << 13) + psubd m1, m8 ; b3 - a3 * src + (1 << 8) - (src << 13) + psrld m0, 9 + pslld m1, 7 + pand m0, m9 + pandn m8, m9, m1 + por m0, m8 + mova m1, [rsp+16+ARCH_X86_32*4] + psubd m1, m2 + mova m2, [rsp+32+ARCH_X86_32*4] + psubd m2, m3 + mova m3, [base+pd_4096] + psrld m1, 9 + pslld m2, 7 + pand m1, m9 + pandn m5, m9, m2 + por m1, m5 + pmaddwd m0, m15 + pmaddwd m1, m15 + paddd m0, m3 + paddd m1, m3 + psrad m0, 13 + psrad m1, 13 + packssdw m0, m1 + paddw m0, m4 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n0_loop + add dstq, stridemp + ret +ALIGN function_align +.n1: ; neighbor + output (odd rows) + movif64 wq, r4 + movif32 wd, w1m +.n1_loop: + movu m3, [t4+wq*2+400*4+4] + movu m5, [t4+wq*2+400*4+2] + paddw m3, [t4+wq*2+400*4+0] + paddw m5, m3 + psllw m5, 2 ; a3[ 1] 444 + psubw m4, m5, m3 ; a3[ 1] 343 + paddw m3, m4, [t4+wq*2+400*12] + paddw m3, [t4+wq*2+400*10] + mova [t4+wq*2+400*10], m5 + mova [t4+wq*2+400*12], m4 + movu m1, [t3+wq*4+400*8+ 8] + movu m5, [t3+wq*4+400*8+ 4] + movu m7, [t3+wq*4+400*8+24] + movu m8, [t3+wq*4+400*8+20] + paddd m1, [t3+wq*4+400*8+ 0] + paddd m7, [t3+wq*4+400*8+16] + paddd m5, m1 + paddd m8, m7 + pslld m5, 2 ; b3[ 1] 444 + pslld m8, 2 + psubd m4, m5, m1 ; b3[ 1] 343 + psubd m0, m8, m7 + paddd m1, m4, [t3+wq*4+400*24+ 0] + paddd m7, m0, [t3+wq*4+400*24+16] + paddd m1, [t3+wq*4+400*20+ 0] + paddd m7, [t3+wq*4+400*20+16] + mova [t3+wq*4+400*20+ 0], m5 + mova [t3+wq*4+400*20+16], m8 + mova [t3+wq*4+400*24+ 0], m4 + mova [t3+wq*4+400*24+16], m0 + movq m5, [dstq+wq] + mova m2, [t4+wq*2+400* 6] + punpcklbw m5, m6 + punpcklwd m4, m5, m6 + punpcklwd m8, m2, m6 + pmaddwd m8, m4 ; a5 * src + punpcklwd m0, m3, m6 + pmaddwd m0, m4 ; a3 * src + punpckhwd m4, m5, m6 + punpckhwd m2, m6 + pmaddwd m2, m4 + punpckhwd m3, m6 + pmaddwd m3, m4 + psubd m1, m0 ; b3 - a3 * src + (1 << 8) - (src << 13) + mova m0, [t3+wq*4+400*12+ 0] + psubd m0, m8 ; b5 - a5 * src + (1 << 8) - (src << 13) + mova m4, [t3+wq*4+400*12+16] + psubd m4, m2 + psubd m7, m3 + pslld m1, 7 + psrld m0, 8 + psrld m4, 8 + pslld m7, 7 + pandn m3, m9, m1 + pand m0, m9 + por m0, m3 + pand m4, m9 + pandn m2, m9, m7 + por m2, m4 + mova m1, [base+pd_4096] + pmaddwd m0, m15 + pmaddwd m2, m15 + paddd m0, m1 + paddd m2, m1 + psrad m0, 13 + psrad m2, 13 + packssdw m0, m2 + paddw m0, m5 + packuswb m0, m0 + movq [dstq+wq], m0 + add wq, 8 + jl .n1_loop + add dstq, stridemp + movif32 dstm, dstq + ret diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5879 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +; dav1d_obmc_masks[] * -512 +const obmc_masks_avx2 + dw 0, 0, -9728, 0, -12800, -7168, -2560, 0 + dw -14336, -11264, -8192, -5632, -3584, -1536, 0, 0 + dw -15360, -13824, -12288, -10752, -9216, -7680, -6144, -5120 + dw -4096, -3072, -2048, -1536, 0, 0, 0, 0 + dw -15872, -14848, -14336, -13312, -12288, -11776, -10752, -10240 + dw -9728, -8704, -8192, -7168, -6656, -6144, -5632, -4608 + dw -4096, -3584, -3072, -2560, -2048, -2048, -1536, -1024 + dw 0, 0, 0, 0, 0, 0, 0, 0 + +deint_shuf: dd 0, 4, 1, 5, 2, 6, 3, 7 +subpel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +subpel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +subpel_h_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +subpel_s_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7 +rescale_mul2: dd 0, 1, 4, 5, 2, 3, 6, 7 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +wswap: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 +bdct_lb_q: times 8 db 0 + times 8 db 4 + times 8 db 8 + times 8 db 12 + +prep_mul: dw 16, 16, 4, 4 +put_bilin_h_rnd: dw 8, 8, 10, 10 +put_8tap_h_rnd: dd 34, 40 +s_8tap_h_rnd: dd 2, 8 +s_8tap_h_sh: dd 2, 4 +put_s_8tap_v_rnd: dd 512, 128 +put_s_8tap_v_sh: dd 10, 8 +prep_8tap_1d_rnd: dd 8 - (8192 << 4) +prep_8tap_2d_rnd: dd 32 - (8192 << 5) +warp8x8t_rnd: dd 16384 - (8192 << 15) +warp8x8_shift: dd 5, 3 +warp8x8_rnd: dw 4096, 4096, 16384, 16384 +bidir_rnd: dw -16400, -16400, -16388, -16388 +bidir_mul: dw 2048, 2048, 8192, 8192 + +%define pw_16 prep_mul +%define pd_512 put_s_8tap_v_rnd + +pw_2: times 2 dw 2 +pw_64: times 2 dw 64 +pw_2048: times 2 dw 2048 +pw_8192: times 2 dw 8192 +pw_27615: times 2 dw 27615 +pw_32766: times 2 dw 32766 +pw_m512: times 2 dw -512 +pd_32: dd 32 +pd_63: dd 63 +pd_64: dd 64 +pd_32768: dd 32768 +pd_65538: dd 65538 +pd_m524256: dd -524256 ; -8192 << 6 + 32 +pd_0x3ff: dd 0x3ff +pq_0x40000000: dq 0x40000000 + dd 0 + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx2, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx2, 2, 4, 8, 16, 32, 64, 128 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx2 mangle(private_prefix %+ _put_bilin_16bpc_avx2.put) +%xdefine prep_avx2 mangle(private_prefix %+ _prep_bilin_16bpc_avx2.prep) + +BASE_JMP_TABLE put, avx2, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx2, 4, 8, 16, 32, 64, 128 + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_16bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +HV_JMP_TABLE put, bilin, avx2, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx2, 7, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_16bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 + %%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 + %%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, avx2, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, avx2, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern resize_filter + +SECTION .text + +INIT_XMM avx2 +cglobal put_bilin_16bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + mov mxyd, r6m ; mx + lea r7, [put_avx2] +%if UNIX64 + DECLARE_REG_TMP 8 + %define org_w r8d + mov r8d, wd +%else + DECLARE_REG_TMP 7 + %define org_w wm +%endif + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +INIT_YMM avx2 +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*0+32*1], m1 + mova [dstq+dsq*1+32*0], m2 + mova [dstq+dsq*1+32*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + add srcq, ssq + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + movu m0, [srcq+32*4] + movu m1, [srcq+32*5] + movu m2, [srcq+32*6] + movu m3, [srcq+32*7] + add srcq, ssq + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + movd xm5, mxyd + mov mxyd, r7m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + mov r6d, r8m ; bitdepth_max + add wq, r7 + shr r6d, 11 + vpbroadcastd m3, [r7-put_avx2+put_bilin_h_rnd+r6*4] + jmp wq +.h_w2: + movq xm1, [srcq+ssq*0] + movhps xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw xm0, xm4, xm1 + psrlq xm1, 16 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 4 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + movq xm1, [srcq+ssq*0+2] + movhps xm1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw xm0, xm4 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 4 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti128 m0, [srcq+ssq*1], 1 + movu xm1, [srcq+ssq*0+2] + vinserti128 m1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + pmullw m0, m4, [srcq+ssq*0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+ssq*1] + pmullw m2, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m5, [srcq+32*0+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+32*1] + pmullw m2, m5, [srcq+32*1+2] + add srcq, ssq + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: +.h_w128: + movifnidn t0d, org_w +.h_w64_loop0: + mov r6d, t0d +.h_w64_loop: + pmullw m0, m4, [srcq+r6*2-32*1] + pmullw m1, m5, [srcq+r6*2-32*1+2] + paddw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+r6*2-32*2] + pmullw m2, m5, [srcq+r6*2-32*2+2] + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+r6*2-32*1], m0 + mova [dstq+r6*2-32*2], m1 + sub r6d, 32 + jg .h_w64_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w64_loop0 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + shl mxyd, 11 + movd xm5, mxyd + add wq, r7 + vpbroadcastw m5, xm5 + jmp wq +.v_w2: + movd xm0, [srcq+ssq*0] +.v_w2_loop: + movd xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq xm2, xm0, xm1 + movd xm0, [srcq+ssq*0] + punpckldq xm1, xm0 + psubw xm1, xm2 + pmulhrsw xm1, xm5 + paddw xm1, xm2 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xm0, [srcq+ssq*0] +.v_w4_loop: + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq xm2, xm0, xm1 + movq xm0, [srcq+ssq*0] + punpcklqdq xm1, xm0 + psubw xm1, xm2 + pmulhrsw xm1, xm5 + paddw xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu xm0, [srcq+ssq*0] +.v_w8_loop: + vbroadcasti128 m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m2, m0, m1, 0xf0 + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m1, m0, 0xf0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w32: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] +.v_w32_loop: + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + psubw m4, m2, m0 + pmulhrsw m4, m5 + paddw m4, m0 + movu m0, [srcq+ssq*0+32*0] + mova [dstq+dsq*0+32*0], m4 + psubw m4, m3, m1 + pmulhrsw m4, m5 + paddw m4, m1 + movu m1, [srcq+ssq*0+32*1] + mova [dstq+dsq*0+32*1], m4 + psubw m4, m0, m2 + pmulhrsw m4, m5 + paddw m4, m2 + mova [dstq+dsq*1+32*0], m4 + psubw m4, m1, m3 + pmulhrsw m4, m5 + paddw m4, m3 + mova [dstq+dsq*1+32*1], m4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w16: +.v_w64: +.v_w128: + movifnidn t0d, org_w + add t0d, t0d + mov r4, srcq + lea r6d, [hq+t0*8-256] + mov r7, dstq +.v_w16_loop0: + movu m0, [srcq+ssq*0] +.v_w16_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m5 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m5 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 + vpbroadcastd m3, [pw_2] + movd xm6, mxyd + vpbroadcastd m7, [pw_8192] + add wq, r7 + vpbroadcastw m6, xm6 + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + vpbroadcastd m7, [pw_2048] +.hv_12bpc: + jmp wq +.hv_w2: + vpbroadcastq xm1, [srcq+ssq*0] + pmullw xm0, xm4, xm1 + psrlq xm1, 16 + pmullw xm1, xm5 + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 +.hv_w2_loop: + movq xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm2, [srcq+ssq*0] + pmullw xm1, xm4, xm2 + psrlq xm2, 16 + pmullw xm2, xm5 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 ; 1 _ 2 _ + shufpd xm2, xm0, xm1, 0x01 ; 0 _ 1 _ + mova xm0, xm1 + psubw xm1, xm2 + paddw xm1, xm1 + pmulhw xm1, xm6 + paddw xm1, xm2 + pmulhrsw xm1, xm7 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + pmullw xm0, xm4, [srcq+ssq*0-8] + pmullw xm1, xm5, [srcq+ssq*0-6] + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 +.hv_w4_loop: + movq xm1, [srcq+ssq*1] + movq xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps xm1, [srcq+ssq*0] + movhps xm2, [srcq+ssq*0+2] + pmullw xm1, xm4 + pmullw xm2, xm5 + paddw xm1, xm3 + paddw xm1, xm2 + psrlw xm1, 2 ; 1 2 + shufpd xm2, xm0, xm1, 0x01 ; 0 1 + mova xm0, xm1 + psubw xm1, xm2 + paddw xm1, xm1 + pmulhw xm1, xm6 + paddw xm1, xm2 + pmulhrsw xm1, xm7 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xm0, xm4, [srcq+ssq*0] + pmullw xm1, xm5, [srcq+ssq*0+2] + paddw xm0, xm3 + paddw xm0, xm1 + psrlw xm0, 2 + vinserti128 m0, xm0, 1 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti128 m1, [srcq+ssq*0], 1 + vinserti128 m2, [srcq+ssq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +.hv_w32: +.hv_w64: +.hv_w128: +%if UNIX64 + lea r6d, [r8*2-32] +%else + mov r6d, wm + lea r6d, [r6*2-32] +%endif + mov r4, srcq + lea r6d, [hq+r6*8] + mov r7, dstq +.hv_w16_loop0: + pmullw m0, m4, [srcq+ssq*0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w16_loop: + pmullw m1, m4, [srcq+ssq*1] + pmullw m2, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 + psubw m2, m1, m0 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m0 + pmulhrsw m2, m7 + mova [dstq+dsq*0], m2 + pmullw m0, m4, [srcq+ssq*0] + pmullw m2, m5, [srcq+ssq*0+2] + paddw m0, m3 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m1 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m1 + pmulhrsw m2, m7 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w16_loop0 + RET + +cglobal prep_bilin_16bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep_avx2] +%if UNIX64 + DECLARE_REG_TMP 7 + %define org_w r7d +%else + DECLARE_REG_TMP 6 + %define org_w r5m +%endif + mov org_w, wd + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [r6-prep_avx2+pw_8192] + add wq, r6 + shr r5d, 11 + vpbroadcastd m4, [r6-prep_avx2+prep_mul+r5*4] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + vpbroadcastq m1, [srcq+strideq*2] + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + pmullw m0, m4 + psubw m0, m5 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*2] + vinserti128 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m4, [srcq+strideq*2] + pmullw m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmullw m0, m4, [srcq+strideq*0+32*0] + pmullw m1, m4, [srcq+strideq*0+32*1] + pmullw m2, m4, [srcq+strideq*1+32*0] + pmullw m3, m4, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .prep_w32 + RET +.prep_w64: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m4, [srcq+32*1] + pmullw m2, m4, [srcq+32*2] + pmullw m3, m4, [srcq+32*3] + add srcq, strideq + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .prep_w64 + RET +.prep_w128: + pmullw m0, m4, [srcq+32*0] + pmullw m1, m4, [srcq+32*1] + pmullw m2, m4, [srcq+32*2] + pmullw m3, m4, [srcq+32*3] + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + pmullw m0, m4, [srcq+32*4] + pmullw m1, m4, [srcq+32*5] + pmullw m2, m4, [srcq+32*6] + pmullw m3, m4, [srcq+32*7] + add tmpq, 32*8 + add srcq, strideq + psubw m0, m5 + psubw m1, m5 + psubw m2, m5 + psubw m3, m5 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .prep_w128 + RET +.h: + movd xm5, mxyd + mov mxyd, r6m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + vpbroadcastd m3, [pw_32766] + psubw m4, m5 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m4, 2 + psllw m5, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti128 m2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq m0, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + pmullw m0, m4 + vpblendd m1, m2, 0xcc + pmullw m1, m5 + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*0+2] + vinserti128 m1, [srcq+strideq*1+2], 1 + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m5, [srcq+strideq*0+2] + psubw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m1, m3 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 2 + jg .h_w16 + RET +.h_w32: +.h_w64: +.h_w128: + movifnidn t0d, org_w +.h_w32_loop0: + mov r3d, t0d +.h_w32_loop: + pmullw m0, m4, [srcq+r3*2-32*1] + pmullw m1, m5, [srcq+r3*2-32*1+2] + psubw m0, m3 + paddw m0, m1 + pmullw m1, m4, [srcq+r3*2-32*2] + pmullw m2, m5, [srcq+r3*2-32*2+2] + psubw m1, m3 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+r3*2-32*1], m0 + mova [tmpq+r3*2-32*2], m1 + sub r3d, 32 + jg .h_w32_loop + add srcq, strideq + lea tmpq, [tmpq+t0*2] + dec hd + jg .h_w32_loop0 + RET +.v: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + movd xm5, mxyd + vpbroadcastd m4, [pw_16] + vpbroadcastw m5, xm5 + vpbroadcastd m3, [pw_32766] + add wq, r6 + lea stride3q, [strideq*3] + psubw m4, m5 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m4, 2 + psllw m5, 2 +.v_12bpc: + jmp wq +.v_w4: + movq xm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq xm1, [srcq+strideq*1] + vpblendd m2, m0, 0x03 ; 0 2 2 2 + vpbroadcastq m0, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0xf0 ; 1 1 3 3 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m1, m2, 0x33 ; 0 1 2 3 + vpblendd m0, m2, 0x0c ; 4 2 4 4 + punpckhqdq m2, m1, m0 ; 1 2 3 4 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movu xm0, [srcq+strideq*0] +.v_w8_loop: + vbroadcasti128 m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m1, m0, m2, 0xf0 ; 0 1 + vbroadcasti128 m0, [srcq+strideq*0] + vpblendd m2, m0, 0xf0 ; 1 2 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5, m2 + psubw m0, m3 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m4 + mova [tmpq+32*0], m1 + pmullw m1, m5, m0 + psubw m2, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + PUSH r7 +%endif + movifnidn r7d, org_w + add r7d, r7d + mov r3, srcq + lea r6d, [hq+r7*8-256] + mov r5, tmpq +.v_w32_loop0: + movu m0, [srcq+strideq*0] +.v_w32_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5, m2 + psubw m0, m3 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m4 + mova [tmpq+r7*0], m1 + pmullw m1, m5, m0 + psubw m2, m3 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+r7*1], m1 + lea tmpq, [tmpq+r7*2] + sub hd, 2 + jg .v_w32_loop + add r3, 32 + add r5, 32 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .v_w32_loop0 +%if WIN64 + POP r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + movd xm6, mxyd + add wq, r6 + lea stride3q, [strideq*3] + vpbroadcastw m6, xm6 + jmp wq +.hv_w4: + movu xm1, [srcq+strideq*0] +%if WIN64 + movaps [rsp+24], xmm7 +%endif + pmullw xm0, xm4, xm1 + psrldq xm1, 2 + pmullw xm1, xm5 + psubw xm0, xm3 + paddw xm0, xm1 + psraw xm0, 2 + vpbroadcastq m0, xm0 +.hv_w4_loop: + movu xm1, [srcq+strideq*1] + vinserti128 m1, [srcq+stride3q ], 1 + movu xm2, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vinserti128 m2, [srcq+strideq*0], 1 + punpcklqdq m7, m1, m2 + psrldq m1, 2 + pslldq m2, 6 + pmullw m7, m4 + vpblendd m1, m2, 0xcc + pmullw m1, m5 + psubw m7, m3 + paddw m1, m7 + psraw m1, 2 ; 1 2 3 4 + vpblendd m0, m1, 0x3f + vpermq m2, m0, q2103 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop +%if WIN64 + movaps xmm7, [rsp+24] +%endif + RET +.hv_w8: + pmullw xm0, xm4, [srcq+strideq*0] + pmullw xm1, xm5, [srcq+strideq*0+2] + psubw xm0, xm3 + paddw xm0, xm1 + psraw xm0, 2 + vinserti128 m0, xm0, 1 +.hv_w8_loop: + movu xm1, [srcq+strideq*1] + movu xm2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + vinserti128 m1, [srcq+strideq*0], 1 + vinserti128 m2, [srcq+strideq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +.hv_w32: +.hv_w64: +.hv_w128: +%if WIN64 + PUSH r7 +%endif + movifnidn r7d, org_w + add r7d, r7d + mov r3, srcq + lea r6d, [hq+r7*8-256] + mov r5, tmpq +.hv_w16_loop0: + pmullw m0, m4, [srcq] + pmullw m1, m5, [srcq+2] + psubw m0, m3 + paddw m0, m1 + psraw m0, 2 +.hv_w16_loop: + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m1, m3 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+r7*0], m2 + pmullw m0, m4, [srcq+strideq*0] + pmullw m2, m5, [srcq+strideq*0+2] + psubw m0, m3 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+r7*1], m2 + lea tmpq, [tmpq+r7*2] + sub hd, 2 + jg .hv_w16_loop + add r3, 32 + add r5, 32 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .hv_w16_loop0 +%if WIN64 + POP r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_16bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my +%define base r8-put_avx2 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx2] + movifnidn wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 +%if WIN64 + pop r8 +%endif + jmp wq +.h_w2: + movzx mxd, mxb + sub srcq, 2 + mova xm2, [subpel_h_shuf2] + vpbroadcastd xm3, [base+subpel_filters+mxq*8+2] + pmovsxbw xm3, xm3 +.h_w2_loop: + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm2 + pshufb xm1, xm2 + pmaddwd xm0, xm3 + pmaddwd xm1, xm3 + phaddd xm0, xm1 + paddd xm0, xm4 + psrad xm0, 6 + packusdw xm0, xm0 + pminsw xm0, xm5 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xm3, [base+subpel_filters+mxq*8] + WIN64_SPILL_XMM 8 + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + pshufd xm3, xm3, q2211 + vpbroadcastq m2, xm3 + vpermq m3, m3, q1111 +.h_w4_loop: + movu xm1, [srcq+ssq*0] + vinserti128 m1, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m1, m6 ; 0 1 1 2 2 3 3 4 + pshufb m1, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m2 + pmaddwd m1, m3 + paddd m0, m4 + paddd m0, m1 + psrad m0, 6 + vextracti128 xm1, m0, 1 + packusdw xm0, xm1 + pminsw xm0, xm5 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + mov r7d, r8m + vpbroadcastw m5, r8m + shr r7d, 11 + vpbroadcastd m4, [base+put_8tap_h_rnd+r7*4] + cmp wd, 4 + je .h_w4 + jl .h_w2 + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 13 + shr mxd, 16 + sub srcq, 6 + vpbroadcastq m0, [base+subpel_filters+mxq*8] + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 8 + jg .h_w16 +.h_w8: +%macro PUT_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2] + pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m6 ; 0 1 1 2 2 3 3 4 + pmaddwd m%5, m9, m%4 ; abcd1 + pmaddwd m%1, m8 ; abcd0 + pshufb m%2, m7 ; 6 7 7 8 8 9 9 a + shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m%5, m4 + paddd m%1, m%5 + pmaddwd m%5, m11, m%2 ; abcd3 + paddd m%1, m%5 + pmaddwd m%5, m10, m%4 ; abcd2 + pshufb m%3, m7 ; a b b c c d d e + pmaddwd m%4, m8 ; efgh0 + paddd m%1, m%5 + pmaddwd m%5, m9, m%2 ; efgh1 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m11 ; efgh3 + pmaddwd m%2, m10 ; efgh2 + paddd m%4, m4 + paddd m%4, m%5 + paddd m%3, m%4 + paddd m%2, m%3 + psrad m%1, 6 + psrad m%2, 6 + packusdw m%1, m%2 + pminsw m%1, m5 +%endmacro + movu xm0, [srcq+ssq*0+ 0] + vinserti128 m0, [srcq+ssq*1+ 0], 1 + movu xm2, [srcq+ssq*0+16] + vinserti128 m2, [srcq+ssq*1+16], 1 + lea srcq, [srcq+ssq*2] + shufpd m1, m0, m2, 0x05 + PUT_8TAP_H 0, 1, 2, 3, 12 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mov r6d, wd +.h_w16_loop: + movu m0, [srcq+r6*2-32] + movu m1, [srcq+r6*2-24] + movu m2, [srcq+r6*2-16] + PUT_8TAP_H 0, 1, 2, 3, 12 + mova [dstq+r6*2-32], m0 + sub r6d, 16 + jg .h_w16_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w16 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m0, [base+subpel_filters+myq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastd m6, [pd_32] + vpbroadcastw m7, r8m + lea r6, [ssq*3] + sub srcq, r6 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 4 + jg .v_w8 + je .v_w4 +.v_w2: + movd xm2, [srcq+ssq*0] + pinsrd xm2, [srcq+ssq*1], 1 + pinsrd xm2, [srcq+ssq*2], 2 + pinsrd xm2, [srcq+r6 ], 3 ; 0 1 2 3 + lea srcq, [srcq+ssq*4] + movd xm3, [srcq+ssq*0] + vpbroadcastd xm1, [srcq+ssq*1] + vpbroadcastd xm0, [srcq+ssq*2] + add srcq, r6 + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklwd xm3, xm1 ; 45 56 + punpcklwd xm1, xm2, xm4 ; 01 12 + punpckhwd xm2, xm4 ; 23 34 +.v_w2_loop: + vpbroadcastd xm4, [srcq+ssq*0] + pmaddwd xm5, xm8, xm1 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm9 ; a1 b1 + paddd xm5, xm6 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm10 ; a2 b2 + paddd xm5, xm3 + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklwd xm3, xm4 ; 67 78 + pmaddwd xm4, xm11, xm3 ; a3 b3 + paddd xm5, xm4 + psrad xm5, 6 + packusdw xm5, xm5 + pminsw xm5, xm7 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xm1, [srcq+ssq*0] + vpbroadcastq m0, [srcq+ssq*1] + vpbroadcastq m2, [srcq+ssq*2] + vpbroadcastq m4, [srcq+r6 ] + lea srcq, [srcq+ssq*4] + vpbroadcastq m3, [srcq+ssq*0] + vpbroadcastq m5, [srcq+ssq*1] + vpblendd m1, m0, 0x30 + vpblendd m0, m2, 0x30 + punpcklwd m1, m0 ; 01 12 + vpbroadcastq m0, [srcq+ssq*2] + add srcq, r6 + vpblendd m2, m4, 0x30 + vpblendd m4, m3, 0x30 + punpcklwd m2, m4 ; 23 34 + vpblendd m3, m5, 0x30 + vpblendd m5, m0, 0x30 + punpcklwd m3, m5 ; 45 56 +.v_w4_loop: + vpbroadcastq m4, [srcq+ssq*0] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m6 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m4, m0, 0x30 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 6 + vextracti128 xm4, m5, 1 + packusdw xm5, xm4 + pminsw xm5, xm7 + movq [dstq+dsq*0], xm5 + movhps [dstq+dsq*1], xm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + shl wd, 5 + mov r7, srcq + mov r8, dstq + lea wd, [hq+wq-256] +.v_w8_loop0: + vbroadcasti128 m4, [srcq+ssq*0] + vbroadcasti128 m5, [srcq+ssq*1] + vbroadcasti128 m0, [srcq+r6 ] + vbroadcasti128 m6, [srcq+ssq*2] + lea srcq, [srcq+ssq*4] + vbroadcasti128 m1, [srcq+ssq*0] + vbroadcasti128 m2, [srcq+ssq*1] + vbroadcasti128 m3, [srcq+ssq*2] + add srcq, r6 + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklwd m3, m6, m0 ; 23 + punpckhwd m6, m0 ; 56 +.v_w8_loop: + vbroadcasti128 m14, [srcq+ssq*0] + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + vbroadcasti128 m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + paddd m13, m6 + shufpd m6, m0, m14, 0x0d + shufpd m0, m14, m5, 0x0c + punpcklwd m5, m6, m0 ; 67 + punpckhwd m6, m0 ; 78 + pmaddwd m14, m11, m5 ; a3 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 5 + psrad m13, 5 + packusdw m12, m13 + pxor m13, m13 + pavgw m12, m13 + pminsw m12, m7 + vpermq m12, m12, q3120 + mova [dstq+dsq*0], xm12 + vextracti128 [dstq+dsq*1], m12, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + add r7, 16 + add r8, 16 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .v_w8_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vpbroadcastw m15, r8m + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + vpbroadcastd m0, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m1, [base+subpel_filters+myq*8] + vpbroadcastd m6, [pd_512] + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m1, m1 + psraw m1, 8 ; sign-extend + test dword r8m, 0x800 + jz .hv_10bit + psraw m7, 2 + psllw m1, 2 +.hv_10bit: + pshufd m11, m1, q0000 + pshufd m12, m1, q1111 + pshufd m13, m1, q2222 + pshufd m14, m1, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 m9, [subpel_h_shuf2] + vbroadcasti128 m1, [srcq+r6 ] ; 3 3 + movu xm3, [srcq+ssq*2] + movu xm0, [srcq+ssq*0] + movu xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*4] + vinserti128 m3, [srcq+ssq*0], 1 ; 2 4 + vinserti128 m0, [srcq+ssq*1], 1 ; 0 5 + vinserti128 m2, [srcq+ssq*2], 1 ; 1 6 + add srcq, r6 + pshufb m1, m9 + pshufb m3, m9 + pshufb m0, m9 + pshufb m2, m9 + pmaddwd m1, m7 + pmaddwd m3, m7 + pmaddwd m0, m7 + pmaddwd m2, m7 + phaddd m1, m3 + phaddd m0, m2 + paddd m1, m6 + paddd m0, m6 + psrad m1, 10 + psrad m0, 10 + packssdw m1, m0 ; 3 2 0 1 + vextracti128 xm0, m1, 1 ; 3 4 5 6 + pshufd xm2, xm1, q1301 ; 2 3 1 2 + pshufd xm3, xm0, q2121 ; 4 5 4 5 + punpckhwd xm1, xm2 ; 01 12 + punpcklwd xm2, xm0 ; 23 34 + punpckhwd xm3, xm0 ; 45 56 +.hv_w2_loop: + movu xm4, [srcq+ssq*0] + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm4, xm9 + pshufb xm5, xm9 + pmaddwd xm4, xm7 + pmaddwd xm5, xm7 + phaddd xm4, xm5 + pmaddwd xm5, xm11, xm1 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm12 ; a1 b1 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm13 ; a2 b2 + paddd xm5, xm3 + paddd xm4, xm6 + psrad xm4, 10 + packssdw xm4, xm4 + palignr xm3, xm4, xm0, 12 + mova xm0, xm4 + punpcklwd xm3, xm0 ; 67 78 + pmaddwd xm4, xm14, xm3 ; a3 b3 + paddd xm5, xm6 + paddd xm5, xm4 + psrad xm5, 10 + packusdw xm5, xm5 + pminsw xm5, xm15 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + vbroadcasti128 m9, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + pshufd m8, m7, q1111 + pshufd m7, m7, q0000 + movu xm1, [srcq+ssq*0] + vinserti128 m1, [srcq+ssq*1], 1 ; 0 1 + vbroadcasti128 m0, [srcq+r6 ] + vinserti128 m2, m0, [srcq+ssq*2], 0 ; 2 3 + lea srcq, [srcq+ssq*4] + vinserti128 m0, [srcq+ssq*0], 1 ; 3 4 + movu xm3, [srcq+ssq*1] + vinserti128 m3, [srcq+ssq*2], 1 ; 5 6 + add srcq, r6 + pshufb m4, m1, m9 + pshufb m1, m10 + pmaddwd m4, m7 + pmaddwd m1, m8 + pshufb m5, m2, m9 + pshufb m2, m10 + pmaddwd m5, m7 + pmaddwd m2, m8 + paddd m4, m6 + paddd m1, m4 + pshufb m4, m0, m9 + pshufb m0, m10 + pmaddwd m4, m7 + pmaddwd m0, m8 + paddd m5, m6 + paddd m2, m5 + pshufb m5, m3, m9 + pshufb m3, m10 + pmaddwd m5, m7 + pmaddwd m3, m8 + paddd m4, m6 + paddd m4, m0 + paddd m5, m6 + paddd m5, m3 + vperm2i128 m0, m1, m2, 0x21 + psrld m1, 10 + psrld m2, 10 + vperm2i128 m3, m4, m5, 0x21 + pslld m4, 6 + pslld m5, 6 + pblendw m2, m4, 0xaa ; 23 34 + pslld m0, 6 + pblendw m1, m0, 0xaa ; 01 12 + psrld m3, 10 + pblendw m3, m5, 0xaa ; 45 56 + psrad m0, m5, 16 +.hv_w4_loop: + movu xm4, [srcq+ssq*0] + vinserti128 m4, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m6 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + pshufb m3, m4, m9 + pshufb m4, m10 + pmaddwd m3, m7 + pmaddwd m4, m8 + paddd m3, m6 + paddd m4, m3 + psrad m4, 10 + packssdw m0, m4 ; _ 7 6 8 + vpermq m3, m0, q1122 ; _ 6 _ 7 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m4, m5 + psrad m4, 10 + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, xm15 + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + vpbroadcastq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + pmovsxbw xm1, [base+subpel_filters+myq*8] + shl wd, 5 + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + pxor m0, m0 + punpcklbw m0, m2 + mov r7, srcq + mov r8, dstq + lea wd, [hq+wq-256] + test dword r8m, 0x800 + jz .hv_w8_10bit + psraw m0, 2 + psllw xm1, 2 +.hv_w8_10bit: + pshufd m11, m0, q0000 + pshufd m12, m0, q1111 + pshufd m13, m0, q2222 + pshufd m14, m0, q3333 +%if WIN64 + %define v_mul (rsp+stack_offset+40) ; r4m +%else + %define v_mul (rsp-24) ; red zone +%endif + mova [v_mul], xm1 +.hv_w8_loop0: +%macro PUT_8TAP_HV_H 3 ; dst/src+0, src+8, src+16 + pshufb m2, m%1, m9 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m8 ; 0 1 1 2 2 3 3 4 + pmaddwd m3, m12, m2 + pmaddwd m%1, m11 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + shufpd m2, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m3, m10 + paddd m%1, m3 + pmaddwd m3, m14, m%2 + paddd m%1, m3 + pmaddwd m3, m13, m2 + pshufb m%3, m9 ; a b b c c d d e + pmaddwd m2, m11 + paddd m%1, m3 + pmaddwd m3, m12, m%2 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m14 + pmaddwd m%2, m13 + paddd m2, m10 + paddd m2, m3 + paddd m%3, m2 + paddd m%2, m%3 + psrad m%1, 10 + psrad m%2, 10 + packssdw m%1, m%2 +%endmacro + movu xm4, [srcq+r6 *1+ 0] + vbroadcasti128 m8, [subpel_h_shufA] + movu xm6, [srcq+r6 *1+ 8] + vbroadcasti128 m9, [subpel_h_shufB] + movu xm0, [srcq+r6 *1+16] + vpbroadcastd m10, [pd_512] + movu xm5, [srcq+ssq*0+ 0] + vinserti128 m5, [srcq+ssq*4+ 0], 1 + movu xm1, [srcq+ssq*0+16] + vinserti128 m1, [srcq+ssq*4+16], 1 + shufpd m7, m5, m1, 0x05 + INIT_XMM avx2 + PUT_8TAP_HV_H 4, 6, 0 ; 3 + INIT_YMM avx2 + PUT_8TAP_HV_H 5, 7, 1 ; 0 4 + movu xm0, [srcq+ssq*2+ 0] + vinserti128 m0, [srcq+r6 *2+ 0], 1 + movu xm1, [srcq+ssq*2+16] + vinserti128 m1, [srcq+r6 *2+16], 1 + shufpd m7, m0, m1, 0x05 + PUT_8TAP_HV_H 0, 7, 1 ; 2 6 + movu xm6, [srcq+ssq*1+ 0] + movu xm1, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*4] + vinserti128 m6, [srcq+ssq*1+ 0], 1 + vinserti128 m1, [srcq+ssq*1+16], 1 + add srcq, r6 + shufpd m7, m6, m1, 0x05 + PUT_8TAP_HV_H 6, 7, 1 ; 1 5 + vpermq m4, m4, q1100 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + vpermq m7, m0, q3120 + punpcklwd m3, m7, m4 ; 23 + punpckhwd m4, m5 ; 34 + punpcklwd m1, m5, m6 ; 01 + punpckhwd m5, m6 ; 45 + punpcklwd m2, m6, m7 ; 12 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vpbroadcastd m9, [v_mul+4*0] + vpbroadcastd m7, [v_mul+4*1] + vpbroadcastd m10, [v_mul+4*2] + pmaddwd m8, m9, m1 ; a0 + pmaddwd m9, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m7 ; a1 + pmaddwd m4, m7 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m8, m5 + paddd m9, m6 + movu xm5, [srcq+ssq*0] + vinserti128 m5, [srcq+ssq*1], 1 + vbroadcasti128 m7, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + movu xm6, [srcq+ssq*0+16] + vinserti128 m6, [srcq+ssq*1+16], 1 + vextracti128 [dstq], m0, 1 + pshufb m0, m5, m7 ; 01 + pshufb m5, m10 ; 23 + pmaddwd m0, m11 + pmaddwd m5, m12 + paddd m0, m5 + pshufb m5, m6, m7 ; 89 + pshufb m6, m10 ; ab + pmaddwd m5, m13 + pmaddwd m6, m14 + paddd m6, m5 + movu xm5, [srcq+ssq*0+8] + vinserti128 m5, [srcq+ssq*1+8], 1 + lea srcq, [srcq+ssq*2] + pshufb m7, m5, m7 + pshufb m5, m10 + pmaddwd m10, m13, m7 + pmaddwd m7, m11 + paddd m0, m10 + vpbroadcastd m10, [pd_512] + paddd m6, m7 + pmaddwd m7, m14, m5 + pmaddwd m5, m12 + paddd m0, m7 + paddd m5, m6 + vbroadcasti128 m6, [dstq] + paddd m8, m10 + paddd m9, m10 + paddd m0, m10 + paddd m5, m10 + vpbroadcastd m10, [v_mul+4*3] + psrad m0, 10 + psrad m5, 10 + packssdw m0, m5 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m10, m5 ; a3 + pmaddwd m10, m6 ; b3 + paddd m7, m8 + paddd m9, m10 + psrad m7, 10 + psrad m9, 10 + packusdw m7, m9 + pminsw m7, m15 + vpermq m7, m7, q3120 + mova [dstq+dsq*0], xm7 + vextracti128 [dstq+dsq*1], m7, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + add r7, 16 + add r8, 16 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .hv_w8_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, stride, w, h, mx, my +%define base r7-prep_avx2 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx2] + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov r6d, r7m ; bitdepth_max + movzx wd, word [r7+wq*2+table_offset(prep,)] + vpbroadcastd m5, [r7-prep_avx2+pw_8192] + shr r6d, 11 + add wq, r7 + vpbroadcastd m4, [base+prep_mul+r6*4] + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xm0, [base+subpel_filters+mxq*8] + vbroadcasti128 m3, [subpel_h_shufA] + vbroadcasti128 m4, [subpel_h_shufB] + WIN64_SPILL_XMM 8 + pshufd xm0, xm0, q2211 + test dword r7m, 0x800 + jnz .h_w4_12bpc + psllw xm0, 2 +.h_w4_12bpc: + vpbroadcastq m6, xm0 + vpermq m7, m0, q1111 +.h_w4_loop: + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti128 m2, [srcq+r6 ], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m1, m3 ; 0 1 1 2 2 3 3 4 + pshufb m1, m4 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m6 + pmaddwd m1, m7 + paddd m0, m5 + paddd m0, m1 + pshufb m1, m2, m3 + pshufb m2, m4 + pmaddwd m1, m6 + pmaddwd m2, m7 + paddd m1, m5 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [prep_8tap_1d_rnd] ; 8 - (8192 << 4) + lea r6, [strideq*3] + cmp wd, 4 + je .h_w4 + shr mxd, 16 + sub srcq, 6 + vpbroadcastq m0, [base+subpel_filters+mxq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 + vbroadcasti128 m6, [subpel_h_shufA] + vbroadcasti128 m7, [subpel_h_shufB] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + test dword r7m, 0x800 + jnz .h_12bpc + psllw m0, 2 +.h_12bpc: + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 8 + jg .h_w16 +.h_w8: +%macro PREP_8TAP_H 5 ; dst/src+0, src+8, src+16, tmp[1-2] + pshufb m%4, m%1, m7 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m6 ; 0 1 1 2 2 3 3 4 + pmaddwd m%5, m9, m%4 ; abcd1 + pmaddwd m%1, m8 ; abcd0 + pshufb m%2, m7 ; 6 7 7 8 8 9 9 a + shufpd m%4, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m%5, m5 + paddd m%1, m%5 + pmaddwd m%5, m11, m%2 ; abcd3 + paddd m%1, m%5 + pmaddwd m%5, m10, m%4 ; abcd2 + pshufb m%3, m7 ; a b b c c d d e + pmaddwd m%4, m8 ; efgh0 + paddd m%1, m%5 + pmaddwd m%5, m9, m%2 ; efgh1 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m11 ; efgh3 + pmaddwd m%2, m10 ; efgh2 + paddd m%4, m5 + paddd m%4, m%5 + paddd m%3, m%4 + paddd m%2, m%3 + psrad m%1, 4 + psrad m%2, 4 + packssdw m%1, m%2 +%endmacro + movu xm0, [srcq+strideq*0+ 0] + vinserti128 m0, [srcq+strideq*1+ 0], 1 + movu xm2, [srcq+strideq*0+16] + vinserti128 m2, [srcq+strideq*1+16], 1 + lea srcq, [srcq+strideq*2] + shufpd m1, m0, m2, 0x05 + PREP_8TAP_H 0, 1, 2, 3, 4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + add wd, wd +.h_w16_loop0: + mov r6d, wd +.h_w16_loop: + movu m0, [srcq+r6-32] + movu m1, [srcq+r6-24] + movu m2, [srcq+r6-16] + PREP_8TAP_H 0, 1, 2, 3, 4 + mova [tmpq+r6-32], m0 + sub r6d, 32 + jg .h_w16_loop + add srcq, strideq + add tmpq, wq + dec hd + jg .h_w16_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m0, [base+subpel_filters+myq*8] + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 15 + vpbroadcastd m7, [prep_8tap_1d_rnd] + lea r6, [strideq*3] + sub srcq, r6 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + test dword r7m, 0x800 + jnz .v_12bpc + psllw m0, 2 +.v_12bpc: + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + cmp wd, 4 + jg .v_w8 +.v_w4: + movq xm1, [srcq+strideq*0] + vpbroadcastq m0, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m4, [srcq+r6 ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + vpblendd m1, m0, 0x30 + vpblendd m0, m2, 0x30 + punpcklwd m1, m0 ; 01 12 + vpbroadcastq m0, [srcq+strideq*2] + add srcq, r6 + vpblendd m2, m4, 0x30 + vpblendd m4, m3, 0x30 + punpcklwd m2, m4 ; 23 34 + vpblendd m3, m5, 0x30 + vpblendd m5, m0, 0x30 + punpcklwd m3, m5 ; 45 56 +.v_w4_loop: + vpbroadcastq m4, [srcq+strideq*0] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m7 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m4, m0, 0x30 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 4 + vextracti128 xm4, m5, 1 + packssdw xm5, xm4 + mova [tmpq], xm5 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: +%if WIN64 + push r8 +%endif + mov r8d, wd + shl wd, 5 + mov r5, srcq + mov r7, tmpq + lea wd, [hq+wq-256] +.v_w8_loop0: + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + vbroadcasti128 m0, [srcq+r6 ] + vbroadcasti128 m6, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m1, [srcq+strideq*0] + vbroadcasti128 m2, [srcq+strideq*1] + vbroadcasti128 m3, [srcq+strideq*2] + add srcq, r6 + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklwd m3, m6, m0 ; 23 + punpckhwd m6, m0 ; 56 +.v_w8_loop: + vbroadcasti128 m14, [srcq+strideq*0] + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m7 + paddd m13, m7 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + vbroadcasti128 m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + paddd m13, m6 + shufpd m6, m0, m14, 0x0d + shufpd m0, m14, m5, 0x0c + punpcklwd m5, m6, m0 ; 67 + punpckhwd m6, m0 ; 78 + pmaddwd m14, m11, m5 ; a3 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 4 + psrad m13, 4 + packssdw m12, m13 + vpermq m12, m12, q3120 + mova [tmpq+r8*0], xm12 + vextracti128 [tmpq+r8*2], m12, 1 + lea tmpq, [tmpq+r8*4] + sub hd, 2 + jg .v_w8_loop + add r5, 16 + add r7, 16 + movzx hd, wb + mov srcq, r5 + mov tmpq, r7 + sub wd, 1<<8 + jg .v_w8_loop0 +%if WIN64 + pop r8 +%endif + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + vpbroadcastd m15, [prep_8tap_2d_rnd] + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + vpbroadcastd m0, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + vpbroadcastq m1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 2 + sub srcq, r6 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m1, m1 + psraw m7, 4 + psraw m1, 8 + test dword r7m, 0x800 + jz .hv_w4_10bit + psraw m7, 2 +.hv_w4_10bit: + pshufd m11, m1, q0000 + pshufd m12, m1, q1111 + pshufd m13, m1, q2222 + pshufd m14, m1, q3333 +.hv_w4: + vbroadcasti128 m9, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + pshufd m8, m7, q1111 + pshufd m7, m7, q0000 + movu xm1, [srcq+strideq*0] + vinserti128 m1, [srcq+strideq*1], 1 ; 0 1 + vbroadcasti128 m0, [srcq+r6 ] + vinserti128 m2, m0, [srcq+strideq*2], 0 ; 2 3 + lea srcq, [srcq+strideq*4] + vinserti128 m0, [srcq+strideq*0], 1 ; 3 4 + movu xm3, [srcq+strideq*1] + vinserti128 m3, [srcq+strideq*2], 1 ; 5 6 + add srcq, r6 + pshufb m4, m1, m9 + pshufb m1, m10 + pmaddwd m4, m7 + pmaddwd m1, m8 + pshufb m5, m2, m9 + pshufb m2, m10 + pmaddwd m5, m7 + pmaddwd m2, m8 + paddd m4, m15 + paddd m1, m4 + pshufb m4, m0, m9 + pshufb m0, m10 + pmaddwd m4, m7 + pmaddwd m0, m8 + paddd m5, m15 + paddd m2, m5 + pshufb m5, m3, m9 + pshufb m3, m10 + pmaddwd m5, m7 + pmaddwd m3, m8 + paddd m4, m15 + paddd m4, m0 + paddd m5, m15 + paddd m5, m3 + vperm2i128 m0, m1, m2, 0x21 + psrld m1, 6 + psrld m2, 6 + vperm2i128 m3, m4, m5, 0x21 + pslld m4, 10 + pslld m5, 10 + pblendw m2, m4, 0xaa ; 23 34 + pslld m0, 10 + pblendw m1, m0, 0xaa ; 01 12 + psrld m3, 6 + pblendw m3, m5, 0xaa ; 45 56 + psrad m0, m5, 16 +.hv_w4_loop: + movu xm4, [srcq+strideq*0] + vinserti128 m4, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m15 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + pshufb m3, m4, m9 + pshufb m4, m10 + pmaddwd m3, m7 + pmaddwd m4, m8 + paddd m3, m15 + paddd m4, m3 + psrad m4, 6 + packssdw m0, m4 ; _ 7 6 8 + vpermq m3, m0, q1122 ; _ 6 _ 7 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m4, m5 + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + vpbroadcastq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmovle myd, mxd + pmovsxbw xm1, [base+subpel_filters+myq*8] +%if WIN64 + PUSH r8 +%endif + mov r8d, wd + shl wd, 5 + lea r6, [strideq*3] + sub srcq, 6 + sub srcq, r6 + mov r5, srcq + mov r7, tmpq + lea wd, [hq+wq-256] + pxor m0, m0 + punpcklbw m0, m2 + mova [v_mul], xm1 + psraw m0, 4 + test dword r7m, 0x800 + jz .hv_w8_10bit + psraw m0, 2 +.hv_w8_10bit: + pshufd m11, m0, q0000 + pshufd m12, m0, q1111 + pshufd m13, m0, q2222 + pshufd m14, m0, q3333 +.hv_w8_loop0: +%macro PREP_8TAP_HV_H 3 ; dst/src+0, src+8, src+16 + pshufb m2, m%1, m9 ; 2 3 3 4 4 5 5 6 + pshufb m%1, m8 ; 0 1 1 2 2 3 3 4 + pmaddwd m3, m12, m2 + pmaddwd m%1, m11 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + shufpd m2, m%2, 0x05 ; 4 5 5 6 6 7 7 8 + paddd m3, m15 + paddd m%1, m3 + pmaddwd m3, m14, m%2 + paddd m%1, m3 + pmaddwd m3, m13, m2 + pshufb m%3, m9 ; a b b c c d d e + pmaddwd m2, m11 + paddd m%1, m3 + pmaddwd m3, m12, m%2 + shufpd m%2, m%3, 0x05 ; 8 9 9 a a b b c + pmaddwd m%3, m14 + pmaddwd m%2, m13 + paddd m2, m15 + paddd m2, m3 + paddd m2, m%3 + paddd m2, m%2 + psrad m%1, 6 + psrad m2, 6 + packssdw m%1, m2 +%endmacro + movu xm4, [srcq+r6 + 0] + vbroadcasti128 m8, [subpel_h_shufA] + movu xm6, [srcq+r6 + 8] + vbroadcasti128 m9, [subpel_h_shufB] + movu xm0, [srcq+r6 +16] + movu xm5, [srcq+strideq*0+ 0] + vinserti128 m5, [srcq+strideq*4+ 0], 1 + movu xm1, [srcq+strideq*0+16] + vinserti128 m1, [srcq+strideq*4+16], 1 + shufpd m7, m5, m1, 0x05 + INIT_XMM avx2 + PREP_8TAP_HV_H 4, 6, 0 ; 3 + INIT_YMM avx2 + PREP_8TAP_HV_H 5, 7, 1 ; 0 4 + movu xm0, [srcq+strideq*2+ 0] + vinserti128 m0, [srcq+r6 *2+ 0], 1 + movu xm1, [srcq+strideq*2+16] + vinserti128 m1, [srcq+r6 *2+16], 1 + shufpd m7, m0, m1, 0x05 + PREP_8TAP_HV_H 0, 7, 1 ; 2 6 + movu xm6, [srcq+strideq*1+ 0] + movu xm1, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*4] + vinserti128 m6, [srcq+strideq*1+ 0], 1 + vinserti128 m1, [srcq+strideq*1+16], 1 + add srcq, r6 + shufpd m7, m6, m1, 0x05 + PREP_8TAP_HV_H 6, 7, 1 ; 1 5 + vpermq m4, m4, q1100 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + vpermq m7, m0, q3120 + punpcklwd m3, m7, m4 ; 23 + punpckhwd m4, m5 ; 34 + punpcklwd m1, m5, m6 ; 01 + punpckhwd m5, m6 ; 45 + punpcklwd m2, m6, m7 ; 12 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vpbroadcastd m9, [v_mul+4*0] + vpbroadcastd m7, [v_mul+4*1] + vpbroadcastd m10, [v_mul+4*2] + pmaddwd m8, m9, m1 ; a0 + pmaddwd m9, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m7 ; a1 + pmaddwd m4, m7 ; b1 + paddd m8, m15 + paddd m9, m15 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m8, m5 + paddd m9, m6 + movu xm5, [srcq+strideq*0] + vinserti128 m5, [srcq+strideq*1], 1 + vbroadcasti128 m7, [subpel_h_shufA] + vbroadcasti128 m10, [subpel_h_shufB] + movu xm6, [srcq+strideq*0+16] + vinserti128 m6, [srcq+strideq*1+16], 1 + vextracti128 [tmpq], m0, 1 + pshufb m0, m5, m7 ; 01 + pshufb m5, m10 ; 23 + pmaddwd m0, m11 + pmaddwd m5, m12 + paddd m0, m15 + paddd m0, m5 + pshufb m5, m6, m7 ; 89 + pshufb m6, m10 ; ab + pmaddwd m5, m13 + pmaddwd m6, m14 + paddd m5, m15 + paddd m6, m5 + movu xm5, [srcq+strideq*0+8] + vinserti128 m5, [srcq+strideq*1+8], 1 + lea srcq, [srcq+strideq*2] + pshufb m7, m5, m7 + pshufb m5, m10 + pmaddwd m10, m13, m7 + pmaddwd m7, m11 + paddd m0, m10 + paddd m6, m7 + pmaddwd m7, m14, m5 + pmaddwd m5, m12 + paddd m0, m7 + paddd m5, m6 + vbroadcasti128 m6, [tmpq] + vpbroadcastd m10, [v_mul+4*3] + psrad m0, 6 + psrad m5, 6 + packssdw m0, m5 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m10, m5 ; a3 + pmaddwd m10, m6 ; b3 + paddd m7, m8 + paddd m9, m10 + psrad m7, 6 + psrad m9, 6 + packssdw m7, m9 + vpermq m7, m7, q3120 + mova [tmpq+r8*0], xm7 + vextracti128 [tmpq+r8*2], m7, 1 + lea tmpq, [tmpq+r8*4] + sub hd, 2 + jg .hv_w8_loop + add r5, 16 + add r7, 16 + movzx hd, wb + mov srcq, r5 + mov tmpq, r7 + sub wd, 1<<8 + jg .hv_w8_loop0 +%if WIN64 + POP r8 +%endif + RET + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro REMAP_REG 2 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %xdefine r14_save r14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + %xdefine r14 r14_save + %undef r14_save + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%macro MC_8TAP_SCALED_H 8-9 0 ; dst, tmp[0-6], load_hrnd + movu xm%1, [srcq+ r4*2] + movu xm%2, [srcq+ r6*2] + movu xm%3, [srcq+ r7*2] + movu xm%4, [srcq+ r9*2] + vinserti128 m%1, [srcq+r10*2], 1 + vinserti128 m%2, [srcq+r11*2], 1 + vinserti128 m%3, [srcq+r13*2], 1 + vinserti128 m%4, [srcq+ rX*2], 1 + add srcq, ssq + movu xm%5, [srcq+ r4*2] + movu xm%6, [srcq+ r6*2] + movu xm%7, [srcq+ r7*2] + movu xm%8, [srcq+ r9*2] + vinserti128 m%5, [srcq+r10*2], 1 + vinserti128 m%6, [srcq+r11*2], 1 + vinserti128 m%7, [srcq+r13*2], 1 + vinserti128 m%8, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m%1, m12 + pmaddwd m%2, m13 + pmaddwd m%3, m14 + pmaddwd m%4, m15 + pmaddwd m%5, m12 + pmaddwd m%6, m13 + pmaddwd m%7, m14 + pmaddwd m%8, m15 + phaddd m%1, m%2 + %if %9 + mova m10, [rsp+0x00] + %endif + phaddd m%3, m%4 + phaddd m%5, m%6 + phaddd m%7, m%8 + phaddd m%1, m%3 + phaddd m%5, m%7 + paddd m%1, m10 + paddd m%5, m10 + psrad m%1, xm11 + psrad m%5, xm11 + packssdw m%1, m%5 +%endmacro + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isput 1 + %assign isprep 0 +cglobal put_8tap_scaled_16bpc, 4, 14, 16, 0xe0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %xdefine base_reg r12 + mov r7d, pxmaxm +%else + %assign isput 0 + %assign isprep 1 +cglobal prep_8tap_scaled_16bpc, 4, 14, 16, 0xe0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %define tmp_stridem qword [rsp+0xd0] + %xdefine base_reg r11 +%endif + lea base_reg, [%1_8tap_scaled_16bpc_avx2] +%define base base_reg-%1_8tap_scaled_16bpc_avx2 + tzcnt wd, wm + vpbroadcastd m8, dxm +%if isprep && UNIX64 + movd xm10, mxd + vpbroadcastd m10, xm10 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 + mov r6d, pxmaxm +%else + vpbroadcastd m10, mxm + %if isput + vpbroadcastw m11, pxmaxm + %else + mov r6d, pxmaxm + %endif +%endif + mov dyd, dym +%if isput + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %else + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %define dsm [rsp+0x98] + %define rX r1 + %define rXd r1d +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %else + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+0x98] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define rX r14 + %define rXd r14d +%endif + shr r7d, 11 + vpbroadcastd m6, [base+pd_0x3ff] + vpbroadcastd m12, [base+s_8tap_h_rnd+r7*4] + movd xm7, [base+s_8tap_h_sh+r7*4] +%if isput + vpbroadcastd m13, [base+put_s_8tap_v_rnd+r7*4] + pinsrd xm7, [base+put_s_8tap_v_sh+r7*4], 2 +%else + vpbroadcastd m13, [base+pd_m524256] +%endif + pxor m9, m9 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_avx2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0,1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd xm4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*2] + movu xm3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*0], 1 ; 0 4 + vinserti128 m1, [srcq+ssq*1], 1 ; 1 5 + vinserti128 m2, [srcq+ssq*2], 1 ; 2 6 + vinserti128 m3, [srcq+ss3q ], 1 ; 3 7 + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m10}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + phaddd m0, m1 + phaddd m2, m3 + paddd m0, m12 + paddd m2, m12 + psrad m0, xm7 + psrad m2, xm7 + packssdw m0, m2 ; 0 1 2 3 4 5 6 7 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 ; 1 2 3 4 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + pshufd xm4, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm4 ; 45 56 + punpckhwd xm4, xm1, xm4 ; 67 __ +.w2_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm14, r6q + pmovsxbw xm14, xm14 + pshufd xm8, xm14, q0000 + pshufd xm9, xm14, q1111 + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pshufd xm8, xm14, q2222 + pshufd xm14, xm14, q3333 + paddd xm5, xm6 + pmaddwd xm6, xm2, xm8 + pmaddwd xm8, xm4, xm14 + psrldq xm9, xm7, 8 + paddd xm5, xm6 + paddd xm5, xm13 + paddd xm5, xm8 + psrad xm5, xm9 + packusdw xm5, xm5 + pminsw xm5, xm11 + movd [dstq], xm5 + add dstq, dsq + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w2_loop + movu xm5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps xm3, xm0, q1032 ; 01 12 + shufps xm0, xm2, q1032 ; 23 34 + shufps xm2, xm4, q1032 ; 45 56 + pshufb xm5, xm10 + pmaddwd xm5, xm15 + phaddd xm5, xm5 + paddd xm5, xm12 + psrad xm5, xm7 + packssdw xm5, xm5 + palignr xm1, xm5, xm1, 12 + punpcklqdq xm1, xm1 ; 6 7 6 7 + punpcklwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +.w2_skip_line: + movu xm6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xm3, xm0 ; 01 12 + mova xm0, xm2 ; 23 34 + pshufb xm5, xm10 + pshufb xm6, xm10 + pmaddwd xm5, xm15 + pmaddwd xm6, xm15 + phaddd xm5, xm6 + paddd xm5, xm12 + psrad xm5, xm7 + packssdw xm5, xm5 ; 6 7 6 7 + palignr xm1, xm5, xm1, 8 ; 4 5 6 7 + pshufd xm5, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm5 ; 45 56 + punpckhwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +%endif +.w4: + mov myd, mym + mova [rsp+0x00], m12 +%if isput + mova [rsp+0x20], xm13 +%else + SWAP m11, m13 +%endif + mova [rsp+0x30], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m0, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + pcmpeqd m6, m9 + punpckldq m10, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pblendvb m14, m2, m10 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu xm7, [srcq+ssq*0] + movu xm9, [srcq+ssq*1] + movu xm8, [srcq+ssq*2] + movu xm10, [srcq+ss3q ] + movu xm1, [srcq+r4 ] + movu xm3, [srcq+r6 ] + movu xm2, [srcq+r11 ] + movu xm4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + vinserti128 m7, [srcq+ssq*0], 1 + vinserti128 m9, [srcq+ssq*1], 1 + vinserti128 m8, [srcq+ssq*2], 1 + vinserti128 m10, [srcq+ss3q ], 1 + vinserti128 m1, [srcq+r4 ], 1 + vinserti128 m3, [srcq+r6 ], 1 + vinserti128 m2, [srcq+r11 ], 1 + vinserti128 m4, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m0 + paddb m13, m0 + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m14}, m7, m9, m8, m10 + REPX {pshufb x, m13}, m1, m2, m3, m4 + REPX {pmaddwd x, m15}, m1, m2, m3, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x30] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 4 5 + packssdw m8, m10 ; 2 3 6 7 + vextracti128 xm9, m7, 1 ; 4 5 + vextracti128 xm3, m8, 1 ; 6 7 + shufps xm4, xm7, xm8, q1032 ; 1 2 + shufps xm5, xm8, xm9, q1032 ; 3 4 + shufps xm6, xm9, xm3, q1032 ; 5 6 + psrldq xm10, xm3, 8 ; 7 _ + punpcklwd xm0, xm7, xm4 ; 01 + punpckhwd xm7, xm4 ; 12 + punpcklwd xm1, xm8, xm5 ; 23 + punpckhwd xm8, xm5 ; 34 + punpcklwd xm2, xm9, xm6 ; 45 + punpckhwd xm9, xm6 ; 56 + punpcklwd xm3, xm10 ; 67 + mova [rsp+0x40], xm7 + mova [rsp+0x50], xm8 + mova [rsp+0x60], xm9 +.w4_loop: + and myd, 0x3ff + mov r11d, 64 << 24 + mov r13d, myd + shr r13d, 6 + lea r13d, [t1+r13] + cmovnz r11q, [base+subpel_filters+r13*8] + movq xm9, r11q + pmovsxbw xm9, xm9 + pshufd xm7, xm9, q0000 + pshufd xm8, xm9, q1111 + pmaddwd xm4, xm0, xm7 + pmaddwd xm5, xm1, xm8 + pshufd xm7, xm9, q2222 + pshufd xm9, xm9, q3333 + pmaddwd xm6, xm2, xm7 + pmaddwd xm8, xm3, xm9 +%if isput + mova xm7, [rsp+0x20] + movd xm9, [rsp+0x38] +%else + SWAP m7, m11 +%endif + paddd xm4, xm5 + paddd xm6, xm8 + paddd xm4, xm6 + paddd xm4, xm7 +%if isput + psrad xm4, xm9 + packusdw xm4, xm4 + pminuw xm4, xm11 + movq [dstq], xm4 + add dstq, dsq +%else + SWAP m11, m7 + psrad xm4, 6 + packssdw xm4, xm4 + movq [tmpq], xm4 + add tmpq, 8 +%endif + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + mova xm8, [rsp+0x00] + movd xm9, [rsp+0x30] + movu xm4, [srcq] + movu xm5, [srcq+r4] + test myd, 0x400 + jz .w4_skip_line + mova xm0, [rsp+0x40] + mova [rsp+0x40], xm1 + mova xm1, [rsp+0x50] + mova [rsp+0x50], xm2 + mova xm2, [rsp+0x60] + mova [rsp+0x60], xm3 + pshufb xm4, xm12 + pshufb xm5, xm13 + pmaddwd xm4, xm14 + pmaddwd xm5, xm15 + phaddd xm4, xm5 + paddd xm4, xm8 + psrad xm4, xm9 + packssdw xm4, xm4 + punpcklwd xm3, xm10, xm4 + mova xm10, xm4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu xm6, [srcq+ssq*1] + movu xm7, [srcq+r6] + movu m0, [rsp+0x50] + pshufb xm4, xm12 + pshufb xm6, xm12 + pshufb xm5, xm13 + pshufb xm7, xm13 + pmaddwd xm4, xm14 + pmaddwd xm6, xm14 + pmaddwd xm5, xm15 + pmaddwd xm7, xm15 + mova [rsp+0x40], m0 + phaddd xm4, xm5 + phaddd xm6, xm7 + paddd xm4, xm8 + paddd xm6, xm8 + psrad xm4, xm9 + psrad xm6, xm9 + packssdw xm4, xm6 + punpcklwd xm9, xm10, xm4 + mova [rsp+0x60], xm9 + psrldq xm10, xm4, 8 + mova xm0, xm1 + mova xm1, xm2 + mova xm2, xm3 + punpcklwd xm3, xm4, xm10 + lea srcq, [srcq+ssq*2] + jmp .w4_loop + SWAP m10, m13 +%if isprep + SWAP m13, m11 +%endif +.w8: + mov dword [rsp+0x80], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+0x80], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+0x80], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+0x80], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+0x80], 16 + movifprep tmp_stridem, 256 +.w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free +%if isput + movifnidn dsm, dsq + mova [rsp+0xb0], xm7 +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + shr t0d, 16 + sub srcq, 6 + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0x84], t0d + mov [rsp+0x88], srcq + mov [rsp+0x90], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + jmp .hloop +.hloop_prep: + dec dword [rsp+0x80] + jz .ret + add qword [rsp+0x90], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x40] + vpbroadcastd m15, [rsp+0x84] + pxor m9, m9 + mov srcq, [rsp+0x88] + mov r0q, [rsp+0x90] ; dstq / tmpq +.hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x40], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq [rsp+0xa0], xm1 + movq [rsp+0xa8], xm7 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x60], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x60] + vbroadcasti128 m9, [base+subpel_s_shuf8] + mov myd, mym + mov dyd, dym + pshufb m0, m9 ; 01a 01b + pshufb m1, m9 ; 23a 23b + pshufb m2, m9 ; 45a 45b + pshufb m3, m9 ; 67a 67b +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm9, r6q + punpcklqdq xm9, xm9 + pmovsxbw m9, xm9 + pshufd m8, m9, q0000 + pshufd m7, m9, q1111 + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m7 + pshufd m8, m9, q2222 + pshufd m9, m9, q3333 + pmaddwd m6, m2, m8 + pmaddwd m7, m3, m9 +%if isput + psrldq xm8, xm11, 8 +%endif + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, xm8 + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xb0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+0x60], myd + mov r4d, [rsp+0xa0] + mov r6d, [rsp+0xa4] + mov r7d, [rsp+0xa8] + mov r9d, [rsp+0xac] + jz .skip_line + vbroadcasti128 m9, [base+wswap] + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + mov myd, [rsp+0x60] + mov dyd, dym + pshufb m0, m9 + pshufb m1, m9 + pshufb m2, m9 + pshufb m3, m9 + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + phaddd m4, m6 + paddd m4, m10 + psrad m4, xm11 + pslld m4, 16 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .vloop +.skip_line: + mova m0, m1 + mova m1, m2 + mova m2, m3 + MC_8TAP_SCALED_H 3, 10, 4, 5, 6, 7, 8, 9, 1 + vbroadcasti128 m9, [base+subpel_s_shuf8] + mov myd, [rsp+0x60] + mov dyd, dym + pshufb m3, m9 + jmp .vloop + SWAP m1, m12, m10 + SWAP m7, m11 +.dy1: + movzx wd, word [base+%1_8tap_scaled_avx2_dy1_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy1_w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0-1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + movu xm2, [srcq+ssq*2] + movu xm3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*1], 1 + vinserti128 m2, [srcq+ssq*2], 1 + add srcq, ss3q + movq xm6, r4q + pmovsxbw xm6, xm6 + pshufd xm8, xm6, q0000 + pshufd xm9, xm6, q1111 + pshufd xm14, xm6, q2222 + pshufd xm6, xm6, q3333 + REPX {pshufb x, m10}, m0, m1, m2 + pshufb xm3, xm10 + REPX {pmaddwd x, m15}, m0, m1, m2 + pmaddwd xm3, xm15 + phaddd m0, m1 + phaddd m2, m3 + paddd m0, m12 + paddd m2, m12 + psrad m0, xm7 + psrad m2, xm7 + packssdw m0, m2 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 + pshufd xm4, xm1, q2121 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + punpcklwd xm2, xm1, xm4 ; 45 56 +.dy1_w2_loop: + movu xm1, [srcq+ssq*0] + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm1, xm10 + pshufb xm5, xm10 + pmaddwd xm1, xm15 + pmaddwd xm5, xm15 + phaddd xm1, xm5 + pmaddwd xm5, xm3, xm8 + mova xm3, xm0 + pmaddwd xm0, xm9 + paddd xm1, xm12 + psrad xm1, xm7 + packssdw xm1, xm1 + paddd xm5, xm0 + mova xm0, xm2 + pmaddwd xm2, xm14 + paddd xm5, xm2 + palignr xm2, xm1, xm4, 12 + punpcklwd xm2, xm1 ; 67 78 + pmaddwd xm4, xm2, xm6 + paddd xm5, xm13 + paddd xm5, xm4 + mova xm4, xm1 + psrldq xm1, xm7, 8 + psrad xm5, xm1 + packusdw xm5, xm5 + pminsw xm5, xm11 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +.dy1_w4: + mov myd, mym +%if isput + mova [rsp+0x50], xm11 +%endif + mova [rsp+0x00], m12 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m4, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + pcmpeqd m6, m9 + punpckldq m10, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pblendvb m14, m2, m10 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*2] + lea r11, [r4+ssq*1] + lea r13, [r4+ss3q ] + movu xm0, [srcq+ssq*0] + movu xm7, [srcq+r4 ] + movu xm1, [srcq+ssq*2] + movu xm8, [srcq+r6 ] + vinserti128 m0, [srcq+ssq*1], 1 ; 0 1 + vinserti128 m7, [srcq+r11 ], 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 2 3 + vinserti128 m8, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + movu xm2, [srcq+ssq*0] + movu xm9, [srcq+r4 ] + movu xm3, [srcq+ssq*2] ; 6 _ + movu xm10, [srcq+r6 ] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + vinserti128 m9, [srcq+r11 ], 1 + lea srcq, [srcq+ss3q ] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m4 + paddb m13, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x40] + pshufb m0, m12 + pshufb m1, m12 + pmaddwd m0, m14 + pmaddwd m1, m14 + pshufb m7, m13 + pshufb m8, m13 + pmaddwd m7, m15 + pmaddwd m8, m15 + pshufb m2, m12 + pshufb xm3, xm12 + pmaddwd m2, m14 + pmaddwd xm3, xm14 + pshufb m9, m13 + pshufb xm10, xm13 + pmaddwd m9, m15 + pmaddwd xm10, xm15 + phaddd m0, m7 + phaddd m1, m8 + phaddd m2, m9 + phaddd xm3, xm10 + paddd m0, m5 + paddd m1, m5 + paddd m2, m5 + paddd xm3, xm5 + psrad m0, xm6 + psrad m1, xm6 + psrad m2, xm6 + psrad xm3, xm6 + vperm2i128 m4, m0, m1, 0x21 ; 1 2 + vperm2i128 m5, m1, m2, 0x21 ; 3 4 + vperm2i128 m6, m2, m3, 0x21 ; 5 6 + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + pslld m4, 16 + pslld m5, 16 + pslld m6, 16 + pblendw m0, m4, 0xaa ; 01 12 + pblendw m1, m5, 0xaa ; 23 34 + pblendw m2, m6, 0xaa ; 45 56 + movq xm10, r13q + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 +.dy1_w4_loop: + movu xm11, [srcq+ssq*0] + movu xm6, [srcq+r4 ] + vinserti128 m11, [srcq+ssq*1], 1 + vinserti128 m6, [srcq+r11 ], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pshufb m11, m12 + pshufb m6, m13 + pmaddwd m11, m14 + pmaddwd m6, m15 + paddd m4, [rsp+0x20] + phaddd m11, m6 + pmaddwd m6, m2, m9 + paddd m11, [rsp+0x00] + psrad m11, [rsp+0x40] + mova m0, m1 + mova m1, m2 + paddd m5, m6 + paddd m4, m5 + vinserti128 m2, m3, xm11, 1 + pslld m3, m11, 16 + pblendw m2, m3, 0xaa ; 67 78 + pmaddwd m5, m2, m10 + vextracti128 xm3, m11, 1 + paddd m4, m5 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0x50] + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET + SWAP m10, m13 +.dy1_w8: + mov dword [rsp+0xa0], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+0xa0], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+0xa0], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+0xa0], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+0xa0], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free + mov myd, mym +%if isput + %define dsm [rsp+0xb8] + movifnidn dsm, dsq + mova [rsp+0xc0], xm7 +%else + %if UNIX64 + %define hm [rsp+0xb8] + %endif +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm11 + shr t0d, 16 + sub srcq, 6 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0xa4], t0d + mov [rsp+0xa8], srcq + mov [rsp+0xb0], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+0xa0] + jz .ret + add qword [rsp+0xb0], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x60] + vpbroadcastd m15, [rsp+0xa4] + pxor m9, m9 + mov srcq, [rsp+0xa8] + mov r0q, [rsp+0xb0] ; dstq / tmpq + mova m10, [rsp+0x00] + mova xm11, [rsp+0x40] +.dy1_hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x60], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x80], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x80] + vbroadcasti128 m7, [base+subpel_s_shuf8] + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m10, [rsp+0x58] + vpbroadcastd m11, [rsp+0x5c] + pshufb m0, m7 ; 01a 01b + pshufb m1, m7 ; 23a 23b + pshufb m2, m7 ; 45a 45b + pshufb m3, m7 ; 67a 67b +.dy1_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xc0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep + vbroadcasti128 m7, [base+wswap] + pshufb m0, m7 + pshufb m1, m7 + pshufb m2, m7 + pshufb m3, m7 + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + phaddd m4, m6 + paddd m4, [rsp+0x00] + psrad m4, [rsp+0x40] + pslld m4, 16 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .dy1_vloop + SWAP m1, m12, m10 + SWAP m7, m11 +.dy2: + movzx wd, word [base+%1_8tap_scaled_avx2_dy2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy2_w2: + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m10, m8 ; mx+dx*[0-1] + vpbroadcastd xm14, [base+pq_0x40000000+2] + vpbroadcastd xm15, xm15 + pand xm8, xm10, xm6 + psrld xm8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_q] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd xm4, [base+subpel_filters+r6*8+2] + pcmpeqd xm8, xm9 + psrld m10, 10 + paddd m10, m10 + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*2] + movu xm2, [srcq+ssq*4] + pshufb m10, m5 + paddb m10, m6 + vpblendd xm15, xm4, 0xa + pblendvb xm15, xm14, xm8 + pmovsxbw m15, xm15 + vinserti128 m0, [srcq+ssq*1], 1 ; 0 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 2 3 + lea srcq, [srcq+ssq*4] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m0, m10 + pshufb m1, m10 + pshufb m2, m10 + pmaddwd m0, m15 + pmaddwd m1, m15 + pmaddwd m2, m15 + movq xm6, r4q + pmovsxbw xm6, xm6 + phaddd m0, m1 + phaddd m1, m2 + paddd m0, m12 + paddd m1, m12 + psrad m0, xm7 + psrad m1, xm7 + packssdw m0, m1 ; 0 2 2 4 1 3 3 5 + vextracti128 xm1, m0, 1 + pshufd xm8, xm6, q0000 + pshufd xm9, xm6, q1111 + pshufd xm14, xm6, q2222 + pshufd xm6, xm6, q3333 + punpcklwd xm2, xm0, xm1 ; 01 23 + punpckhwd xm1, xm0, xm1 ; 23 45 +.dy2_w2_loop: + movu xm3, [srcq+ssq*0] + movu xm5, [srcq+ssq*2] + vinserti128 m3, [srcq+ssq*1], 1 ; 6 7 + vinserti128 m5, [srcq+ss3q ], 1 ; 8 9 + lea srcq, [srcq+ssq*4] + pmaddwd xm4, xm2, xm8 + pmaddwd xm1, xm9 + pshufb m3, m10 + pshufb m5, m10 + pmaddwd m3, m15 + pmaddwd m5, m15 + phaddd m3, m5 + paddd xm4, xm1 + paddd m3, m12 + psrad m3, xm7 + packssdw m3, m3 + pshufd m3, m3, q2100 + palignr m0, m3, m0, 12 ; 4 6 6 8 5 7 7 9 + vextracti128 xm1, m0, 1 + punpcklwd xm2, xm0, xm1 ; 45 67 + punpckhwd xm1, xm0, xm1 ; 67 89 + pmaddwd xm3, xm2, xm14 + pmaddwd xm5, xm1, xm6 + paddd xm4, xm13 + paddd xm4, xm3 + psrldq xm3, xm7, 8 + paddd xm4, xm5 + psrad xm4, xm3 + packusdw xm4, xm4 + pminsw xm4, xm11 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +.dy2_w4: + mov myd, mym +%if isput + mova [rsp+0x50], xm11 +%endif + mova [rsp+0x00], m12 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm7 + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + sub srcq, 2 + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastq m2, [base+pq_0x40000000+1] + vpbroadcastd xm15, xm15 + SWAP m13, m10 + paddd m13, m8 ; mx+dx*[0-3] + pand m6, m13 + psrld m6, 6 + paddd xm15, xm6 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + vbroadcasti128 m5, [base+bdct_lb_q+ 0] + vbroadcasti128 m1, [base+bdct_lb_q+16] + vbroadcasti128 m4, [base+subpel_s_shuf2] + vpbroadcastd xm14, [base+subpel_filters+r4*8+2] + vpbroadcastd xm7, [base+subpel_filters+r6*8+2] + vpbroadcastd xm15, [base+subpel_filters+r11*8+2] + vpbroadcastd xm8, [base+subpel_filters+r13*8+2] + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + pcmpeqd m6, m9 + punpckldq m11, m6, m6 + punpckhdq m6, m6 + psrld m13, 10 + paddd m13, m13 + vpblendd xm14, xm7, 0xa + vpblendd xm15, xm8, 0xa + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + movq xm10, r13q + pblendvb m14, m2, m11 + pblendvb m15, m2, m6 + pextrd r4, xm13, 2 + pshufb m12, m13, m5 + pshufb m13, m1 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu xm0, [srcq+ssq*0] + movu xm7, [srcq+r4 ] + movu xm1, [srcq+ssq*1] + movu xm8, [srcq+r6 ] + vinserti128 m0, [srcq+ssq*2], 1 ; 0 2 + vinserti128 m7, [srcq+r11 ], 1 + vinserti128 m1, [srcq+ss3q ], 1 ; 1 3 + vinserti128 m8, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + movu xm2, [srcq+ssq*0] + movu xm9, [srcq+r4 ] + vinserti128 m2, [srcq+ssq*1], 1 ; 4 5 + vinserti128 m9, [srcq+r6 ], 1 + lea srcq, [srcq+ssq*2] + vpbroadcastb m5, xm13 + psubb m13, m5 + paddb m12, m4 + paddb m13, m4 + mova m5, [rsp+0x00] + movd xm6, [rsp+0x40] + pshufb m0, m12 + pshufb m1, m12 + pshufb m2, m12 + pmaddwd m0, m14 + pmaddwd m1, m14 + pmaddwd m2, m14 + pshufb m7, m13 + pshufb m8, m13 + pshufb m9, m13 + pmaddwd m7, m15 + pmaddwd m8, m15 + pmaddwd m9, m15 + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + phaddd m0, m7 + phaddd m1, m8 + phaddd m2, m9 + paddd m0, m5 + paddd m1, m5 + paddd m2, m5 + psrad m0, xm6 + psrad m1, xm6 + psrad m2, xm6 + vperm2i128 m3, m0, m2, 0x21 ; 2 4 + vperm2i128 m2, m1, 0x13 ; 3 5 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + packssdw m0, m3 ; 0 2 2 4 + packssdw m1, m2 ; 1 3 3 5 + punpckhwd m2, m0, m1 ; 23 45 + punpcklwd m0, m1 ; 01 23 +.dy2_w4_loop: + movu xm1, [srcq+ssq*0] + movu xm6, [srcq+r4 ] + movu xm3, [srcq+ssq*1] + movu xm11, [srcq+r6 ] + vinserti128 m1, [srcq+ssq*2], 1 ; 6 8 + vinserti128 m6, [srcq+r11 ], 1 + vinserti128 m3, [srcq+ss3q ], 1 ; 7 9 + vinserti128 m11, [srcq+r13 ], 1 + lea srcq, [srcq+ssq*4] + pmaddwd m4, m0, m7 + pmaddwd m5, m2, m8 + pshufb m1, m12 + pshufb m3, m12 + pmaddwd m1, m14 + pmaddwd m3, m14 + mova m0, [rsp+0x00] + pshufb m6, m13 + pshufb m11, m13 + pmaddwd m6, m15 + pmaddwd m11, m15 + paddd m4, m5 + movd xm5, [rsp+0x40] + phaddd m1, m6 + phaddd m3, m11 + paddd m1, m0 + paddd m3, m0 + psrad m1, xm5 + psrad m3, xm5 + pslld m3, 16 + pblendw m1, m3, 0xaa ; 67 89 + vperm2i128 m0, m2, m1, 0x21 ; 45 67 + paddd m4, [rsp+0x20] + mova m2, m1 + pmaddwd m5, m0, m9 + pmaddwd m6, m2, m10 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0x50] + movq [dstq+dsq*0], xm4 + movhps [dstq+dsq*1], xm4 + lea dstq, [dstq+dsq*2] +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET + SWAP m10, m13 +.dy2_w8: + mov dword [rsp+0xa0], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+0xa0], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+0xa0], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+0xa0], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+0xa0], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + SWAP m10, m12, m1 + SWAP m11, m7 + ; m1=mx, m7=pxmax, m10=h_rnd, m11=h_sh, m12=free + mov myd, mym +%if isput + movifnidn dsm, dsq + mova [rsp+0xc0], xm7 +%endif + mova [rsp+0x00], m10 + mova [rsp+0x20], m13 + mova [rsp+0x40], xm11 + shr t0d, 16 + sub srcq, 6 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul2] + movd xm15, t0d + mov [rsp+0xa4], t0d + mov [rsp+0xa8], srcq + mov [rsp+0xb0], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m1, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+0xa0] + jz .ret + add qword [rsp+0xb0], 16 + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m6, [base+pd_0x3ff] + paddd m1, m8, [rsp+0x60] + vpbroadcastd m15, [rsp+0xa4] + pxor m9, m9 + mov srcq, [rsp+0xa8] + mov r0q, [rsp+0xb0] ; dstq / tmpq + mova m10, [rsp+0x00] + mova xm11, [rsp+0x40] +.dy2_hloop: + vpbroadcastq xm2, [base+pq_0x40000000] + pand m5, m1, m6 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + vextracti128 xm7, m15, 1 + movq r6, xm15 + pextrq r9, xm15, 1 + movq r11, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r7d, r9d + shr r9, 32 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mova [rsp+0x60], m1 + movq xm12, [base+subpel_filters+ r4*8] + movq xm13, [base+subpel_filters+ r6*8] + movhps xm12, [base+subpel_filters+ r7*8] + movhps xm13, [base+subpel_filters+ r9*8] + movq xm14, [base+subpel_filters+r10*8] + movq xm15, [base+subpel_filters+r11*8] + movhps xm14, [base+subpel_filters+r13*8] + movhps xm15, [base+subpel_filters+ rX*8] + psrld m1, 10 + vextracti128 xm7, m1, 1 + vextracti128 xm6, m5, 1 + movq r6, xm1 + pextrq r11, xm1, 1 + movq r9, xm7 + pextrq rX, xm7, 1 + mov r4d, r6d + shr r6, 32 + mov r10d, r11d + shr r11, 32 + mov r7d, r9d + shr r9, 32 + mov r13d, rXd + shr rX, 32 + pshufd xm4, xm5, q2200 + pshufd xm5, xm5, q3311 + pshufd xm7, xm6, q2200 + pshufd xm6, xm6, q3311 + pblendvb xm12, xm2, xm4 + pblendvb xm13, xm2, xm5 + pblendvb xm14, xm2, xm7 + pblendvb xm15, xm2, xm6 + pmovsxbw m12, xm12 + pmovsxbw m13, xm13 + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + mova [rsp+0x80], m0 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 0 ; 6a 7a 6b 7b + mova m0, [rsp+0x80] + vbroadcasti128 m7, [base+subpel_s_shuf8] + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m10, [rsp+0x58] + vpbroadcastd m11, [rsp+0x5c] + pshufb m0, m7 ; 01a 01b + pshufb m1, m7 ; 23a 23b + pshufb m2, m7 ; 45a 45b + pshufb m3, m7 ; 67a 67b +.dy2_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, [rsp+0x20] + paddd m6, m7 + paddd m4, m5 + paddd m4, m6 +%if isput + psrad m4, [rsp+0x48] + vextracti128 xm5, m4, 1 + packusdw xm4, xm5 + pminsw xm4, [rsp+0xc0] + mova [dstq], xm4 + add dstq, dsm +%else + psrad m4, 6 + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep + mova m0, m1 + mova m1, m2 + mova m2, m3 + movu xm3, [srcq+ r4*2] + movu xm4, [srcq+ r6*2] + movu xm5, [srcq+ r7*2] + movu xm6, [srcq+ r9*2] + vinserti128 m3, [srcq+r10*2], 1 + vinserti128 m4, [srcq+r11*2], 1 + vinserti128 m5, [srcq+r13*2], 1 + vinserti128 m6, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m3, m12 + pmaddwd m4, m13 + pmaddwd m5, m14 + pmaddwd m6, m15 + phaddd m3, m4 + phaddd m5, m6 + phaddd m3, m5 + movu xm4, [srcq+ r4*2] + movu xm5, [srcq+ r6*2] + movu xm6, [srcq+ r7*2] + movu xm7, [srcq+ r9*2] + vinserti128 m4, [srcq+r10*2], 1 + vinserti128 m5, [srcq+r11*2], 1 + vinserti128 m6, [srcq+r13*2], 1 + vinserti128 m7, [srcq+ rX*2], 1 + add srcq, ssq + pmaddwd m4, m12 + pmaddwd m5, m13 + pmaddwd m6, m14 + pmaddwd m7, m15 + phaddd m4, m5 + phaddd m6, m7 + mova m5, [rsp+0x00] + movd xm7, [rsp+0x40] + phaddd m4, m6 + paddd m3, m5 + paddd m4, m5 + psrad m3, xm7 + psrad m4, xm7 + pslld m4, 16 + pblendw m3, m4, 0xaa + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%undef isput +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_16bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, t0d + jmp mangle(private_prefix %+ _%1_8tap_scaled_16bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%else +DECLARE_REG_TMP 6, 8 +%endif + +%define PUT_8TAP_SCALED_FN FN put_8tap_scaled, +BILIN_SCALED_FN put +PUT_8TAP_SCALED_FN sharp, SHARP, SHARP +PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled, +BILIN_SCALED_FN prep +PREP_8TAP_SCALED_FN sharp, SHARP, SHARP +PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%macro WARP_V 5 ; dst, 01, 23, 45, 67 + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm8, [filterq+myq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 ; a e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; b f + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm9, [filterq+myq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 ; c g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + punpcklwd m8, m0 + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; d h + punpcklwd m0, m9, m0 + punpckldq m9, m8, m0 + punpckhdq m0, m8, m0 + punpcklbw m8, m11, m9 ; a0 a1 b0 b1 c0 c1 d0 d1 << 8 + punpckhbw m9, m11, m9 ; a2 a3 b2 b3 c2 c3 d2 d3 << 8 + pmaddwd m%2, m8 + pmaddwd m9, m%3 + punpcklbw m8, m11, m0 ; a4 a5 b4 b5 c4 c5 d4 d5 << 8 + punpckhbw m0, m11, m0 ; a6 a7 b6 b7 c6 c7 d6 d7 << 8 + pmaddwd m8, m%4 + pmaddwd m0, m%5 + paddd m9, m%2 + mova m%2, m%3 + paddd m0, m8 + mova m%3, m%4 + mova m%4, m%5 + paddd m%1, m0, m9 +%endmacro + +cglobal warp_affine_8x8t_16bpc, 4, 14, 16, tmp, ts + mov r6d, r7m + lea r9, [$$] + shr r6d, 11 + vpbroadcastd m13, [r9-$$+warp8x8_shift+r6*4] + vpbroadcastd m14, [warp8x8t_rnd] + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx2).main + jmp .start +.loop: + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx2).main2 + lea tmpq, [tmpq+tsq*4] +.start: + paddd m7, m14 + paddd m0, m14 + psrad m7, 15 + psrad m0, 15 + packssdw m7, m0 + vpermq m7, m7, q3120 + mova [tmpq+tsq*0], xm7 + vextracti128 [tmpq+tsq*2], m7, 1 + dec r4d + jg .loop +.end: + RET + +cglobal warp_affine_8x8_16bpc, 4, 14, 16, dst, ds, src, ss, abcd, mx, tmp2, \ + alpha, beta, filter, tmp1, delta, \ + my, gamma + mov r6d, r7m + lea filterq, [$$] + shr r6d, 11 + vpbroadcastd m13, [filterq-$$+warp8x8_shift+r6*4] + vpbroadcastd m14, [filterq-$$+warp8x8_rnd +r6*4] + vpbroadcastw m15, r7m ; pixel_max + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m7, 16 + psrad m0, 16 + packusdw m7, m0 + pmulhrsw m7, m14 + pminsw m7, m15 + vpermq m7, m7, q3120 + mova [dstq+dsq*0], xm7 + vextracti128 [dstq+dsq*1], m7, 1 + dec r4d + jg .loop +.end: + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov abcdq, r5m + mov mxd, r6m +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + vpbroadcastd m12, [pd_32768] + pxor m11, m11 + add filterq, mc_warp_filter-$$ + lea tmp1q, [ssq*3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + sub betad, tmp2d ; beta -= alpha*3 + mov myd, r7m + call .h + psrld m1, m0, 16 + call .h + pblendw m1, m0, 0xaa ; 01 + psrld m2, m0, 16 + call .h + pblendw m2, m0, 0xaa ; 12 + psrld m3, m0, 16 + call .h + pblendw m3, m0, 0xaa ; 23 + psrld m4, m0, 16 + call .h + pblendw m4, m0, 0xaa ; 34 + psrld m5, m0, 16 + call .h + pblendw m5, m0, 0xaa ; 45 + psrld m6, m0, 16 + call .h + pblendw m6, m0, 0xaa ; 56 + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + add myd, 512+(64<<10) + mov r4d, 4 + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 +.main2: + call .h + psrld m7, m6, 16 + pblendw m7, m0, 0xaa ; 67 + WARP_V 7, 1, 3, 5, 7 + call .h + psrld m10, m5, 16 + pblendw m10, m0, 0xaa ; 78 + WARP_V 0, 2, 4, 6, 10 + ret +ALIGN function_align +.h: + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + movu xm10, [srcq-6] + vinserti128 m10, [srcq+2], 1 + shr mxd, 10 ; 0 + shr tmp1d, 10 ; 4 + movq xm0, [filterq+mxq *8] + vinserti128 m0, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + movu xm8, [srcq-4] + vinserti128 m8, [srcq+4], 1 + shr tmp2d, 10 ; 1 + shr tmp1d, 10 ; 5 + movq xm9, [filterq+tmp2q*8] + vinserti128 m9, [filterq+tmp1q*8], 1 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 ; 2 + shr tmp1d, 10 ; 6 + punpcklbw m0, m11, m0 + pmaddwd m0, m10 + movu xm10, [srcq-2] + vinserti128 m10, [srcq+6], 1 + punpcklbw m9, m11, m9 + pmaddwd m9, m8 + movq xm8, [filterq+mxq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + phaddd m0, m9 ; 0 1 4 5 + movu xm9, [srcq+0] + vinserti128 m9, [srcq+8], 1 + shr tmp2d, 10 ; 3 + shr tmp1d, 10 ; 7 + punpcklbw m8, m11, m8 + pmaddwd m8, m10 + movq xm10, [filterq+tmp2q*8] + vinserti128 m10, [filterq+tmp1q*8], 1 + punpcklbw m10, m11, m10 + pmaddwd m9, m10 + add srcq, ssq + phaddd m8, m9 ; 2 3 6 7 + phaddd m0, m8 ; 0 1 2 3 4 5 6 7 + vpsllvd m0, m13 + paddd m0, m12 ; rounded 14-bit result in upper 16 bits of dword + ret + +%macro BIDIR_FN 0 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + movq [dstq ], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + cmp hd, 8 + je .ret + lea dstq, [dstq+strideq*4] + movq [dstq ], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.ret: + RET +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + cmp hd, 4 + jne .w8_loop_start + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 +.w8_loop_start: + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + dec hd + jg .w128_loop + RET +%endmacro + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal avg_16bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx2_table + lea r6, [avg_avx2_table] + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + vpbroadcastd m4, [base+bidir_rnd+t0*4] + vpbroadcastd m5, [base+bidir_mul+t0*4] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+32*0] + paddsw m0, [tmp2q+32*0] + mova m1, [tmp1q+32*1] + paddsw m1, [tmp2q+32*1] + mova m2, [tmp1q+32*2] + paddsw m2, [tmp2q+32*2] + mova m3, [tmp1q+32*3] + paddsw m3, [tmp2q+32*3] + add tmp1q, 32*4 + add tmp2q, 32*4 + pmaxsw m0, m4 + pmaxsw m1, m4 + pmaxsw m2, m4 + pmaxsw m3, m4 + psubsw m0, m4 + psubsw m1, m4 + psubsw m2, m4 + psubsw m3, m4 + pmulhw m0, m5 + pmulhw m1, m5 + pmulhw m2, m5 + pmulhw m3, m5 + ret + +cglobal w_avg_16bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, stride3 + lea r6, [w_avg_avx2_table] + tzcnt wd, wm + mov t0d, r6m ; weight + vpbroadcastw m8, r7m ; pixel_max + vpbroadcastd m7, [r6-w_avg_avx2_table+pd_65538] + movsxd wq, [r6+wq*4] + paddw m7, m8 + add wq, r6 + lea r6d, [t0-16] + shl t0d, 16 + sub t0d, r6d ; 16-weight, weight + pslld m7, 7 + rorx r6d, t0d, 30 ; << 2 + test dword r7m, 0x800 + cmovz r6d, t0d + movifnidn hd, hm + movd xm6, r6d + vpbroadcastd m6, xm6 + BIDIR_FN +ALIGN function_align +.main: + mova m4, [tmp1q+32*0] + mova m0, [tmp2q+32*0] + punpckhwd m5, m0, m4 + punpcklwd m0, m4 + mova m4, [tmp1q+32*1] + mova m1, [tmp2q+32*1] + pmaddwd m5, m6 + pmaddwd m0, m6 + paddd m5, m7 + paddd m0, m7 + psrad m5, 8 + psrad m0, 8 + packusdw m0, m5 + punpckhwd m5, m1, m4 + punpcklwd m1, m4 + mova m4, [tmp1q+32*2] + mova m2, [tmp2q+32*2] + pmaddwd m5, m6 + pmaddwd m1, m6 + paddd m5, m7 + paddd m1, m7 + psrad m5, 8 + psrad m1, 8 + packusdw m1, m5 + punpckhwd m5, m2, m4 + punpcklwd m2, m4 + mova m4, [tmp1q+32*3] + mova m3, [tmp2q+32*3] + add tmp1q, 32*4 + add tmp2q, 32*4 + pmaddwd m5, m6 + pmaddwd m2, m6 + paddd m5, m7 + paddd m2, m7 + psrad m5, 8 + psrad m2, 8 + packusdw m2, m5 + punpckhwd m5, m3, m4 + punpcklwd m3, m4 + pmaddwd m5, m6 + pmaddwd m3, m6 + paddd m5, m7 + paddd m3, m7 + psrad m5, 8 + psrad m3, 8 + packusdw m3, m5 + pminsw m0, m8 + pminsw m1, m8 + pminsw m2, m8 + pminsw m3, m8 + ret + +cglobal mask_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx2_table + lea r7, [mask_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_64] + vpbroadcastd m9, [base+bidir_rnd+r6*4] + vpbroadcastd m10, [base+bidir_mul+r6*4] + mov maskq, maskmp + add wq, r7 + BIDIR_FN +ALIGN function_align +.main: +%macro MASK 1 + pmovzxbw m5, [maskq+16*%1] + mova m%1, [tmp1q+32*%1] + mova m6, [tmp2q+32*%1] + punpckhwd m4, m%1, m6 + punpcklwd m%1, m6 + psubw m7, m8, m5 + punpckhwd m6, m5, m7 ; m, 64-m + punpcklwd m5, m7 + pmaddwd m4, m6 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m%1, m5 + psrad m4, 5 + psrad m%1, 5 + packssdw m%1, m4 + pmaxsw m%1, m9 + psubsw m%1, m9 + pmulhw m%1, m10 +%endmacro + MASK 0 + MASK 1 + MASK 2 + MASK 3 + add maskq, 16*4 + add tmp1q, 32*4 + add tmp2q, 32*4 + ret + +cglobal w_mask_420_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx2_table + lea r7, [w_mask_420_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd xm0, r7m ; sign + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+bidir_rnd+r6*4] + vpbroadcastd m13, [base+bidir_mul+r6*4] + movd xm14, [base+pw_2] + mov maskq, maskmp + psubw xm14, xm0 + vpbroadcastw m14, xm14 + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + phaddd m4, m5 + paddw m4, m14 + psrlw m4, 2 + packuswb m4, m4 + vextracti128 xm5, m4, 1 + punpcklwd xm4, xm5 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + mova [maskq], xm4 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8: + vperm2i128 m6, m4, m5, 0x21 + vpblendd m4, m5, 0xf0 + paddw m4, m14 + paddw m4, m6 + psrlw m4, 2 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + mova [maskq], xm4 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16: + punpcklqdq m6, m4, m5 + punpckhqdq m4, m5 + paddw m6, m14 + paddw m4, m6 + psrlw m4, 2 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + pshufd xm4, xm4, q3120 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + mova [maskq], xm4 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w32: + paddw m4, m14 + paddw m4, m5 + psrlw m15, m4, 2 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + call .main + mova m6, [deint_shuf] + paddw m4, m14 + paddw m4, m5 + psrlw m4, 2 + packuswb m15, m4 + vpermd m4, m6, m15 + mova [dstq+strideq*2+32*0], m0 + mova [dstq+strideq*2+32*1], m1 + mova [dstq+stride3q +32*0], m2 + mova [dstq+stride3q +32*1], m3 + mova [maskq], m4 + sub hd, 4 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w64: + paddw m4, m14 + paddw m15, m14, m5 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [maskq], m4 ; no available registers + call .main + paddw m4, [maskq] + mova m6, [deint_shuf] + paddw m5, m15 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 ; 0 2 4 6 1 3 5 7 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + mova [maskq], m4 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 64 +.w128: + paddw m4, m14 + paddw m5, m14 + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*0+32*2], m2 + mova [dstq+strideq*0+32*3], m3 + mova [maskq+32*0], m4 + mova [dstq+strideq], m5 + call .main + paddw m4, m14 + paddw m15, m14, m5 + mova [dstq+strideq*0+32*4], m0 + mova [dstq+strideq*0+32*5], m1 + mova [dstq+strideq*0+32*6], m2 + mova [dstq+strideq*0+32*7], m3 + mova [maskq+32*1], m4 + call .main + paddw m4, [maskq+32*0] + paddw m5, [dstq+strideq] + mova m6, [deint_shuf] + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*0], m0 + mova [dstq+strideq*1+32*1], m1 + mova [dstq+strideq*1+32*2], m2 + mova [dstq+strideq*1+32*3], m3 + mova [maskq+32*0], m4 + call .main + paddw m4, [maskq+32*1] + mova m6, [deint_shuf] + paddw m5, m15 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m6, m4 + mova [dstq+strideq*1+32*4], m0 + mova [dstq+strideq*1+32*5], m1 + mova [dstq+strideq*1+32*6], m2 + mova [dstq+strideq*1+32*7], m3 + mova [maskq+32*1], m4 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: +%macro W_MASK 2-6 11, 12, 13 ; dst/src1, mask/src2, pw_64, rnd, mul + mova m%1, [tmp1q+32*%1] + mova m%2, [tmp2q+32*%1] + punpcklwd m8, m%2, m%1 + punpckhwd m9, m%2, m%1 + psubsw m%1, m%2 + pabsw m%1, m%1 + psubusw m7, m10, m%1 + psrlw m7, 10 ; 64-m + psubw m%2, m%3, m7 ; m + punpcklwd m%1, m7, m%2 + punpckhwd m7, m%2 + pmaddwd m%1, m8 + pmaddwd m7, m9 + psrad m%1, 5 + psrad m7, 5 + packssdw m%1, m7 + pmaxsw m%1, m%4 + psubsw m%1, m%4 + pmulhw m%1, m%5 +%endmacro + W_MASK 0, 4 + W_MASK 1, 5 + phaddw m4, m5 + W_MASK 2, 5 + W_MASK 3, 6 + phaddw m5, m6 + add tmp1q, 32*4 + add tmp2q, 32*4 + ret + +cglobal w_mask_422_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx2_table + lea r7, [w_mask_422_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + vpbroadcastb m14, r7m ; sign + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+bidir_rnd+r6*4] + vpbroadcastd m13, [base+bidir_mul+r6*4] + mova m15, [base+deint_shuf] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti128 xm2, m2, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm3 + movhps [dstq+strideq*1], xm3 + vextracti128 xm3, m3, 1 + movq [dstq+strideq*2], xm3 + movhps [dstq+stride3q ], xm3 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm2 + vextracti128 [dstq+strideq*1], m2, 1 + mova [dstq+strideq*2], xm3 + vextracti128 [dstq+stride3q ], m3, 1 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + mova [dstq+strideq*2], m2 + mova [dstq+stride3q ], m3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0+32*0], m0 + mova [dstq+strideq*0+32*1], m1 + mova [dstq+strideq*1+32*0], m2 + mova [dstq+strideq*1+32*1], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + mova [dstq+32*6], m2 + mova [dstq+32*7], m3 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 4 + W_MASK 1, 5 + phaddw m4, m5 + W_MASK 2, 5 + W_MASK 3, 6 + phaddw m5, m6 + add tmp1q, 32*4 + add tmp2q, 32*4 + packuswb m4, m5 + pxor m5, m5 + psubb m4, m14 + pavgb m4, m5 + vpermd m4, m15, m4 + mova [maskq], m4 + add maskq, 32 + ret + +cglobal w_mask_444_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx2_table + lea r7, [w_mask_444_avx2_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] + vpbroadcastd m4, [base+pw_64] + vpbroadcastd m5, [base+bidir_rnd+r6*4] + vpbroadcastd m6, [base+bidir_mul+r6*4] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 + je .w4_end + call .main + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti128 xm0, m0, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti128 xm1, m1, 1 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], xm1 + vextracti128 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + call .main + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + call .main + mova [dstq+32*2], m0 + mova [dstq+32*3], m1 + call .main + mova [dstq+32*4], m0 + mova [dstq+32*5], m1 + call .main + mova [dstq+32*6], m0 + mova [dstq+32*7], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2, 4, 5, 6 + W_MASK 1, 3, 4, 5, 6 + packuswb m2, m3 + vpermq m2, m2, q3120 + add tmp1q, 32*2 + add tmp2q, 32*2 + mova [maskq], m2 + add maskq, 32 + ret + +; (a * (64 - m) + b * m + 32) >> 6 +; = (((b - a) * m + 32) >> 6) + a +; = (((b - a) * (m << 9) + 16384) >> 15) + a +; except m << 9 overflows int16_t when m == 64 (which is possible), +; but if we negate m it works out (-64 << 9 == -32768). +; = (((a - b) * (m * -512) + 16384) >> 15) + a +cglobal blend_16bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx2_table + lea r6, [blend_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + vpbroadcastd m6, [base+pw_m512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + pmovzxbw m3, [maskq] + movq xm0, [dstq+dsq*0] + movhps xm0, [dstq+dsq*1] + vpbroadcastq m1, [dstq+dsq*2] + vpbroadcastq m2, [dstq+r6 ] + vpblendd m0, m1, 0x30 + vpblendd m0, m2, 0xc0 + psubw m1, m0, [tmpq] + add maskq, 16 + add tmpq, 32 + pmullw m3, m6 + pmulhrsw m1, m3 + paddw m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + movq [dstq+dsq*2], xm1 + movhps [dstq+r6 ], xm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +.w8: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + mova xm1, [dstq+dsq*2] + vinserti128 m1, [dstq+r6 ], 1 + psubw m2, m0, [tmpq+32*0] + psubw m3, m1, [tmpq+32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + mova [dstq+dsq*2], xm1 + vextracti128 [dstq+r6 ], m1, 1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16 + RET +.w32: + pmovzxbw m4, [maskq+16*0] + pmovzxbw m5, [maskq+16*1] + mova m0, [dstq+32*0] + psubw m2, m0, [tmpq+32*0] + mova m1, [dstq+32*1] + psubw m3, m1, [tmpq+32*1] + add maskq, 16*2 + add tmpq, 32*2 + pmullw m4, m6 + pmullw m5, m6 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .w32 + RET + +INIT_XMM avx2 +cglobal blend_v_16bpc, 3, 6, 6, dst, ds, tmp, w, h +%define base r5-blend_v_avx2_table + lea r5, [blend_v_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + vpbroadcastd m2, [base+obmc_masks_avx2+2*2] +.w2_loop: + movd m0, [dstq+dsq*0] + pinsrd m0, [dstq+dsq*1], 1 + movq m1, [tmpq] + add tmpq, 4*2 + psubw m1, m0, m1 + pmulhrsw m1, m2 + paddw m0, m1 + movd [dstq+dsq*0], m0 + pextrd [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + vpbroadcastq m2, [base+obmc_masks_avx2+4*2] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + psubw m1, m0, [tmpq] + add tmpq, 8*2 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +INIT_YMM avx2 +.w8: + vbroadcasti128 m2, [base+obmc_masks_avx2+8*2] +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + psubw m1, m0, [tmpq] + add tmpq, 16*2 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + mova m4, [base+obmc_masks_avx2+16*2] +.w16_loop: + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add tmpq, 32*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: +%if WIN64 + movaps [rsp+ 8], xmm6 + movaps [rsp+24], xmm7 +%endif + mova m6, [base+obmc_masks_avx2+32*2] + vbroadcasti128 m7, [base+obmc_masks_avx2+32*3] +.w32_loop: + mova m0, [dstq+dsq*0+32*0] + psubw m3, m0, [tmpq +32*0] + mova xm2, [dstq+dsq*0+32*1] + mova xm5, [tmpq +32*1] + mova m1, [dstq+dsq*1+32*0] + psubw m4, m1, [tmpq +32*2] + vinserti128 m2, [dstq+dsq*1+32*1], 1 + vinserti128 m5, [tmpq +32*3], 1 + add tmpq, 32*4 + psubw m5, m2, m5 + pmulhrsw m3, m6 + pmulhrsw m4, m6 + pmulhrsw m5, m7 + paddw m0, m3 + paddw m1, m4 + paddw m2, m5 + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*1+32*0], m1 + mova [dstq+dsq*0+32*1], xm2 + vextracti128 [dstq+dsq*1+32*1], m2, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop +%if WIN64 + movaps xmm6, [rsp+ 8] + movaps xmm7, [rsp+24] +%endif + RET + +%macro BLEND_H_ROW 2-3 0; dst_off, tmp_off, inc_tmp + mova m0, [dstq+32*(%1+0)] + psubw m2, m0, [tmpq+32*(%2+0)] + mova m1, [dstq+32*(%1+1)] + psubw m3, m1, [tmpq+32*(%2+1)] +%if %3 + add tmpq, 32*%3 +%endif + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+32*(%1+0)], m0 + mova [dstq+32*(%1+1)], m1 +%endmacro + +INIT_XMM avx2 +cglobal blend_h_16bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_h_avx2_table + lea r5, [blend_h_avx2_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + lea maskq, [base+obmc_masks_avx2+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + pinsrd m0, [dstq+dsq*1], 1 + movd m2, [maskq+hq*2] + movq m1, [tmpq] + add tmpq, 4*2 + punpcklwd m2, m2 + psubw m1, m0, m1 + pmulhrsw m1, m2 + paddw m0, m1 + movd [dstq+dsq*0], m0 + pextrd [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova m3, [blend_shuf] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + movd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 8*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +INIT_YMM avx2 +.w8: + vbroadcasti128 m3, [blend_shuf] + shufpd m3, m3, 0x0c +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti128 m0, [dstq+dsq*1], 1 + vpbroadcastd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 16*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +.w16: + vpbroadcastw m4, [maskq+hq*2] + vpbroadcastw m5, [maskq+hq*2+2] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 32*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 32*1] + add tmpq, 32*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16 + RET +.w32: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0, 2 + add dstq, dsq + inc hq + jl .w32 + RET +.w64: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 4 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m4, [maskq+hq*2] + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 8 + BLEND_H_ROW 4, -4 + BLEND_H_ROW 6, -2 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal emu_edge_16bpc, 10, 13, 1, bw, bh, iw, ih, x, y, dst, dstride, src, sstride, \ + bottomext, rightext + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor r12d, r12d + lea r10, [ihq-1] + cmp yq, ihq + cmovs r10, yq + test yq, yq + cmovs r10, r12 + imul r10, sstrideq + add srcq, r10 + + ; ref += iclip(x, 0, iw - 1) + lea r10, [iwq-1] + cmp xq, iwq + cmovs r10, xq + test xq, xq + cmovs r10, r12 + lea srcq, [srcq+r10*2] + + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) + lea bottomextq, [yq+bhq] + sub bottomextq, ihq + lea r3, [bhq-1] + cmovs bottomextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, x, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, r12 + cmp bottomextq, bhq + cmovns bottomextq, r3 + cmp topextq, bhq + cmovg topextq, r3 + + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + lea rightextq, [xq+bwq] + sub rightextq, iwq + lea r2, [bwq-1] + cmovs rightextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, leftext, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, r12 + cmp rightextq, bwq + cmovns rightextq, r2 + cmp leftextq, bwq + cmovns leftextq, r2 + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, topext, \ + dst, dstride, src, sstride, bottomext, rightext + + ; center_h = bh - top_ext - bottom_ext + lea r3, [bottomextq+topextq] + sub centerhq, r3 + + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq + imul r2, dstrideq + add dstq, r2 + mov r9m, dstq + + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq + lea r3, [rightextq+leftextq] + sub centerwq, r3 + +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix +.v_loop_%3: +%if %1 + ; left extension + xor r3, r3 + vpbroadcastw m0, [srcq] +.left_loop_%3: + mova [dstq+r3*2], m0 + add r3, 16 + cmp r3, leftextq + jl .left_loop_%3 + + ; body + lea r12, [dstq+leftextq*2] +%endif + xor r3, r3 +.body_loop_%3: + movu m0, [srcq+r3*2] +%if %1 + movu [r12+r3*2], m0 +%else + movu [dstq+r3*2], m0 +%endif + add r3, 16 + cmp r3, centerwq + jl .body_loop_%3 + +%if %2 + ; right extension +%if %1 + lea r12, [r12+centerwq*2] +%else + lea r12, [dstq+centerwq*2] +%endif + xor r3, r3 + vpbroadcastw m0, [srcq+centerwq*2-2] +.right_loop_%3: + movu [r12+r3*2], m0 + add r3, 16 + cmp r3, rightextq + jl .right_loop_%3 + +%endif + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 +%endmacro + + test leftextq, leftextq + jnz .need_left_ext + test rightextq, rightextq + jnz .need_right_ext + v_loop 0, 0, 0 + jmp .body_done + +.need_left_ext: + test rightextq, rightextq + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: + ; bottom edge extension + test bottomextq, bottomextq + jz .top + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 +.bottom_x_loop: + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, bottomextq +.bottom_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .bottom_y_loop + add r1, 16 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end + mov srcq, r9m + mov dstq, dstm + xor r1, r1 +.top_x_loop: + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, topextq +.top_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .top_y_loop + add r1, 16 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +cglobal resize_16bpc, 6, 12, 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x, _, _, pxmax + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pd_64] + vpbroadcastw xm7, pxmaxm + pmaddwd m2, m5, [base+rescale_mul] ; dx*[0,1,2,3,4,5,6,7] + pslld m5, 3 ; dx*8 + pslld m6, 14 + paddd m8, m2 ; mx+[0..7]*dx +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + vpbroadcastd m10, [base+pd_63] + pxor m2, m2 + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + pand m9, m10 ; filter offset (masked) + ; load source pixels + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vextracti128 xm0, m0, 1 + movu xm10, [srcq+r8*2] + movu xm11, [srcq+r9*2] + movu xm12, [srcq+r10*2] + movu xm13, [srcq+r11*2] + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vinserti128 m10, [srcq+r8*2], 1 + vinserti128 m11, [srcq+r9*2], 1 + vinserti128 m12, [srcq+r10*2], 1 + vinserti128 m13, [srcq+r11*2], 1 + ptest m1, m1 + jz .filter + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vextracti128 xm1, m1, 1 + movu xm14, [base+resize_shuf+8+r8*2] + movu xm15, [base+resize_shuf+8+r9*2] + movu xm0, [base+resize_shuf+8+r10*2] + movu xm2, [base+resize_shuf+8+r11*2] + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vinserti128 m14, [base+resize_shuf+8+r8*2], 1 + vinserti128 m15, [base+resize_shuf+8+r9*2], 1 + vinserti128 m0, [base+resize_shuf+8+r10*2], 1 + vinserti128 m2, [base+resize_shuf+8+r11*2], 1 + pshufb m10, m14 + pshufb m11, m15 + pshufb m12, m0 + pshufb m13, m2 +.filter: + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vextracti128 xm9, m9, 1 + movq xm14, [base+resize_filter+r8*8] + movq xm15, [base+resize_filter+r9*8] + movq xm0, [base+resize_filter+r10*8] + movq xm2, [base+resize_filter+r11*8] + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + movhps xm14, [base+resize_filter+r8*8] + movhps xm15, [base+resize_filter+r9*8] + movhps xm0, [base+resize_filter+r10*8] + movhps xm2, [base+resize_filter+r11*8] + pmovsxbw m14, xm14 + pmovsxbw m15, xm15 + pmovsxbw m0, xm0 + pmovsxbw m2, xm2 + pmaddwd m10, m14 + pmaddwd m11, m15 + pmaddwd m12, m0 + pmaddwd m13, m2 + phaddd m10, m11 + phaddd m12, m13 + phaddd m10, m12 + psubd m10, m3, m10 + psrad m10, 7 + vextracti128 xm0, m10, 1 + packusdw xm10, xm0 + pminsw xm10, xm7 + mova [dstq+xq*2], xm10 + paddd m4, m5 + add xd, 8 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4858 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +spel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 + db 32, 33, 34, 35, 34, 35, 36, 37, 36, 37, 38, 39, 38, 39, 40, 41 +spel_h_shufC: db 8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 14, 15, 16, 17 + db 40, 41, 42, 43, 42, 43, 44, 45, 44, 45, 46, 47, 46, 47, 48, 49 + db 16, 17, 18, 19, 18, 19, 20, 21, 20, 21, 22, 23, 22, 23, 24, 25 + db 48, 49, 50, 51, 50, 51, 52, 53, 52, 53, 54, 55, 54, 55, 56, 57 +spel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 + db 36, 37, 38, 39, 38, 39, 40, 41, 40, 41, 42, 43, 42, 43, 44, 45 +spel_h_shufD: db 12, 13, 14, 15, 14, 15, 16, 17, 16, 17, 18, 19, 18, 19, 20, 21 + db 44, 45, 46, 47, 46, 47, 48, 49, 48, 49, 50, 51, 50, 51, 52, 53 + db 20, 21, 22, 23, 22, 23, 24, 25, 24, 25, 26, 27, 26, 27, 28, 29 + db 52, 53, 54, 55, 54, 55, 56, 57, 56, 57, 58, 59, 58, 59, 60, 61 +spel_v_shuf8: db 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 + db 16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39 + db 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 + db 24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47 +spel_v_shuf16: db 0, 1, 32, 33, 2, 3, 34, 35, 4, 5, 36, 37, 6, 7, 38, 39 + db 8, 9, 40, 41, 10, 11, 42, 43, 12, 13, 44, 45, 14, 15, 46, 47 + db 16, 17, 48, 49, 18, 19, 50, 51, 20, 21, 52, 53, 22, 23, 54, 55 + db 24, 25, 56, 57, 26, 27, 58, 59, 28, 29, 60, 61, 30, 31, 62, 63 +prep_endA: db 1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30 + db 33, 34, 37, 38, 41, 42, 45, 46, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 81, 82, 85, 86, 89, 90, 93, 94 + db 97, 98,101,102,105,106,109,110,113,114,117,118,121,122,125,126 +prep_endB: db 1, 2, 5, 6, 9, 10, 13, 14, 33, 34, 37, 38, 41, 42, 45, 46 + db 17, 18, 21, 22, 25, 26, 29, 30, 49, 50, 53, 54, 57, 58, 61, 62 + db 65, 66, 69, 70, 73, 74, 77, 78, 97, 98,101,102,105,106,109,110 + db 81, 82, 85, 86, 89, 90, 93, 94,113,114,117,118,121,122,125,126 +prep_endC: db 1, 2, 5, 6, 9, 10, 13, 14, 65, 66, 69, 70, 73, 74, 77, 78 + db 17, 18, 21, 22, 25, 26, 29, 30, 81, 82, 85, 86, 89, 90, 93, 94 + db 33, 34, 37, 38, 41, 42, 45, 46, 97, 98,101,102,105,106,109,110 + db 49, 50, 53, 54, 57, 58, 61, 62,113,114,117,118,121,122,125,126 +spel_shuf4a: db 1, 2, 17, 18, 5, 6, 21, 22, 9, 10, 25, 26, 13, 14, 29, 30 + db 17, 18, 33, 34, 21, 22, 37, 38, 25, 26, 41, 42, 29, 30, 45, 46 +spel_shuf4b: db 18, 19, 33, 34, 22, 23, 37, 38, 26, 27, 41, 42, 30, 31, 45, 46 + db 33, 34, 49, 50, 37, 38, 53, 54, 41, 42, 57, 58, 45, 46, 61, 62 +spel_shuf8a: db 1, 2, 17, 18, 5, 6, 21, 22, 9, 10, 25, 26, 13, 14, 29, 30 + db 17, 18, 65, 66, 21, 22, 69, 70, 25, 26, 73, 74, 29, 30, 77, 78 + db 33, 34, 49, 50, 37, 38, 53, 54, 41, 42, 57, 58, 45, 46, 61, 62 + db 49, 50, 97, 98, 53, 54,101,102, 57, 58,105,106, 61, 62,109,110 +spel_shuf8b: db 18, 19, 65, 66, 22, 23, 69, 70, 26, 27, 73, 74, 30, 31, 77, 78 + db 65, 66, 81, 82, 69, 70, 85, 86, 73, 74, 89, 90, 77, 78, 93, 94 + db 50, 51, 97, 98, 54, 55,101,102, 58, 59,105,106, 62, 63,109,110 + db 97, 98,113,114,101,102,117,118,105,106,121,122,109,110,125,126 +spel_shuf16: db 1, 2, 33, 34, 5, 6, 37, 38, 9, 10, 41, 42, 13, 14, 45, 46 + db 17, 18, 49, 50, 21, 22, 53, 54, 25, 26, 57, 58, 29, 30, 61, 62 + db 65, 66, 97, 98, 69, 70,101,102, 73, 74,105,106, 77, 78,109,110 + db 81, 82,113,114, 85, 86,117,118, 89, 90,121,122, 93, 94,125,126 +spel_shuf32: db 1, 2, 65, 66, 5, 6, 69, 70, 9, 10, 73, 74, 13, 14, 77, 78 + db 17, 18, 81, 82, 21, 22, 85, 86, 25, 26, 89, 90, 29, 30, 93, 94 + db 33, 34, 97, 98, 37, 38,101,102, 41, 42,105,106, 45, 46,109,110 + db 49, 50,113,114, 53, 54,117,118, 57, 58,121,122, 61, 62,125,126 +spel_h_shuf2b: db 1, 2, 17, 18, 5, 6, 21, 22, 17, 18, 33, 34, 21, 22, 37, 38 + db 33, 34, 49, 50, 37, 38, 53, 54, 49, 50, 9, 10, 53, 54, 13, 14 + db 9, 10, 25, 26, 13, 14, 29, 30, 25, 26, 41, 42, 29, 30, 45, 46 +spel_shuf2: db 10, 11, 17, 18, 14, 15, 21, 22, 17, 18, 25, 26, 21, 22, 29, 30 +spel_h_shuf2a: db 0, 1, 2, 3, 2, 3, 4, 5, 16, 17, 18, 19, 18, 19, 20, 21 + db 4, 5, 6, 7, 6, 7, 8, 9, 20, 21, 22, 23, 22, 23, 24, 25 +w_mask_end42x: db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +w_mask_end444: db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 + db 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94 + db 96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126 +w_mask_shuf4: db 0, 2, 8, 10, 4, 6, 12, 14, 16, 18, 24, 26, 20, 22, 28, 30 + db 32, 34, 40, 42, 36, 38, 44, 46, 48, 50, 56, 58, 52, 54, 60, 62 + db 64, 66, 72, 74, 68, 70, 76, 78, 80, 82, 88, 90, 84, 86, 92, 94 + db 96, 98,104,106,100,102,108,110,112,114,120,122,116,118,124,126 +w_mask_shuf8: db 0, 2, 16, 18, 4, 6, 20, 22, 8, 10, 24, 26, 12, 14, 28, 30 + db 32, 34, 48, 50, 36, 38, 52, 54, 40, 42, 56, 58, 44, 46, 60, 62 + db 64, 66, 80, 82, 68, 70, 84, 86, 72, 74, 88, 90, 76, 78, 92, 94 + db 96, 98,112,114,100,102,116,118,104,106,120,122,108,110,124,126 +w_mask_shuf16: db 0, 2, 32, 34, 4, 6, 36, 38, 8, 10, 40, 42, 12, 14, 44, 46 + db 16, 18, 48, 50, 20, 22, 52, 54, 24, 26, 56, 58, 28, 30, 60, 62 + db 64, 66, 96, 98, 68, 70,100,102, 72, 74,104,106, 76, 78,108,110 + db 80, 82,112,114, 84, 86,116,118, 88, 90,120,122, 92, 94,124,126 +warp8x8_permA: db 0, 1, 2, 3, 32, 33, 34, 35, 2, 3, 4, 5, 34, 35, 36, 37 + db 4, 5, 6, 7, 36, 37, 38, 39, 6, 7, 8, 9, 38, 39, 40, 41 + db 8, 9, 10, 11, 40, 41, 42, 43, 10, 11, 12, 13, 42, 43, 44, 45 + db 12, 13, 14, 15, 44, 45, 46, 47, 14, 15, 16, 17, 46, 47, 48, 49 +warp8x8_permB: db 12, 13, 14, 15, 44, 45, 46, 47, 14, 15, 16, 17, 46, 47, 48, 49 + db 16, 17, 18, 19, 48, 49, 50, 51, 18, 19, 20, 21, 50, 51, 52, 53 + db 20, 21, 22, 23, 52, 53, 54, 55, 22, 23, 24, 25, 54, 55, 56, 57 + db 24, 25, 26, 27, 56, 57, 58, 59, 26, 27, 28, 29, 58, 59, 60, 61 +warp8x8_end: db 0, 1, 4, 5, 16, 17, 20, 21, 32, 33, 36, 37, 48, 49, 52, 53 + db 2, 3, 6, 7, 18, 19, 22, 23, 34, 35, 38, 39, 50, 51, 54, 55 + db 8, 9, 12, 13, 24, 25, 28, 29, 40, 41, 44, 45, 56, 57, 60, 61 + db 10, 11, 14, 15, 26, 27, 30, 31, 42, 43, 46, 47, 58, 59, 62, 63 +deint_q_shuf: ;dq 0, 2, 4, 6, 1, 3, 5, 7 +pd_0to7: dd 0, 1, 2, 3, 4, 5, 6, 7 + dd 1 +pw_2048: times 2 dw 2048 + dd 3 +pw_8192: times 2 dw 8192 +avg_shift: dw 5, 5, 3, 3 +pw_27615: times 2 dw 27615 +pw_32766: times 2 dw 32766 +warp8x8_permC: db -1, 0, -1, 1, -1, 8, -1, 9, -1, 4, -1, 5, -1, 12, -1, 13 +warp8x8_permD: db -1, 2, -1, 3, -1, 10, -1, 11, -1, 6, -1, 7, -1, 14, -1, 15 +warp_shift_h: db 11, 19, 11, 19, 43, 51, 43, 51, 13, 21, 13, 21, 45, 53, 45, 53 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +resize_permA: dd 0, 4, 8, 12, 1, 5, 9, 13, 16, 20, 24, 28, 17, 21, 25, 29 +resize_permB: dd 2, 6, 10, 14, 3, 7, 11, 15, 18, 22, 26, 30, 19, 23, 27, 31 +resize_permC: dq 0, 1, 4, 5, 8, 9, 12, 13 +resize_permD: dq 2, 3, 6, 7, 10, 11, 14, 15 +resize_permE: dq 0, 2, 4, 6 +resize_shufA: db -1, 0, -1, 1, -1, 4, -1, 5, -1, 8, -1, 9, -1, 12, -1, 13 +resize_shufB: db -1, 2, -1, 3, -1, 6, -1, 7, -1, 10, -1, 11, -1, 14, -1, 15 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 + +prep_hv_shift: dq 6, 4 +put_bilin_h_rnd: dw 8, 8, 10, 10 +prep_mul: dw 16, 16, 4, 4 +put_8tap_h_rnd: dd 34, 40 +prep_8tap_rnd: dd 128 - (8192 << 8) +warp_8x8_rnd_h: dd 512, 2048 +warp_8x8_rnd_v: dd 262144, 65536 +warp_8x8t_rnd_v: dd 16384 - (8192 << 15) +avg_round: dw -16400, -16400, -16388, -16388 +w_avg_round: dd 128 + (8192 << 4), 32 + (8192 << 4) +mask_round: dd 512 + (8192 << 6), 128 + (8192 << 6) +w_mask_round: dd 128, 64 +bidir_shift: dw 6, 6, 4, 4 + +pb_64: times 4 db 64 +pw_m512: times 2 dw -512 +pw_2: times 2 dw 2 +pw_64: times 2 dw 64 +pd_32: dd 32 +pd_63: dd 63 +pd_128: dd 128 +pd_640: dd 640 +pd_2176: dd 2176 +pd_16384: dd 16384 +pd_0_4: dd 0, 4 + +%define pw_16 prep_mul +%define pd_512 warp_8x8_rnd_h + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_16bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx512icl mangle(private_prefix %+ _put_bilin_16bpc_avx512icl.put) +%xdefine prep_avx512icl mangle(private_prefix %+ _prep_bilin_16bpc_avx512icl.prep) + +BIDIR_JMP_TABLE avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx512icl, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx512icl, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE put, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx512icl, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx512icl, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx512icl, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx512icl, 2, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx512icl, 2, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern obmc_masks_avx2 +cextern resize_filter + +SECTION .text + +%if WIN64 +DECLARE_REG_TMP 4 +%else +DECLARE_REG_TMP 8 +%endif + +INIT_ZMM avx512icl +cglobal put_bilin_16bpc, 4, 8, 13, dst, ds, src, ss, w, h, mxy + mov mxyd, r6m ; mx + lea r7, [put_avx512icl] + tzcnt t0d, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx t0d, word [r7+t0*2+table_offset(put,)] + add t0, r7 + jmp t0 +.put_w2: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu xmm0, [srcq+ssq*0] + movu xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], xmm0 + mova [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu ym0, [srcq+ssq*0] + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], ym0 + mova [dstq+dsq*1], ym1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+64*0], m0 + mova [dstq+dsq*0+64*1], m1 + mova [dstq+dsq*1+64*0], m2 + mova [dstq+dsq*1+64*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] + movu m2, [srcq+64*2] + movu m3, [srcq+64*3] + add srcq, ssq + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + vpbroadcastw m5, mxyd + mov mxyd, r7m ; my + vpbroadcastd m4, [pw_16] + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_h)] + mov r6d, r8m ; bitdepth_max + add t0, r7 + shr r6d, 11 + vpbroadcastd m6, [r7-put_avx512icl+put_bilin_h_rnd+r6*4] + jmp t0 +.h_w2: + movq xmm1, [srcq+ssq*0] + movhps xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw xmm0, xmm1, xm4 + psrlq xmm1, 16 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 4 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq xmm0, [srcq+ssq*0+0] + movhps xmm0, [srcq+ssq*1+0] + movq xmm1, [srcq+ssq*0+2] + movhps xmm1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw xmm0, xm4 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 4 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+ssq*0+0] + vinserti32x4 ym0, [srcq+ssq*1+0], 1 + movu xm1, [srcq+ssq*0+2] + vinserti32x4 ym1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw ym0, ym4 + pmullw ym1, ym5 + paddw ym0, ym6 + paddw ym0, ym1 + psrlw ym0, 4 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu ym0, [srcq+ssq*0+0] + vinserti32x8 m0, [srcq+ssq*1+0], 1 + movu ym1, [srcq+ssq*0+2] + vinserti32x8 m1, [srcq+ssq*1+2], 1 + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m6 + paddw m0, m1 + psrlw m0, 4 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m2, m5, [srcq+ssq*0+2] + pmullw m1, m4, [srcq+ssq*1+0] + pmullw m3, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m0, m6 + paddw m1, m6 + paddw m0, m2 + paddw m1, m3 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + pmullw m0, m4, [srcq+64*0+0] + pmullw m2, m5, [srcq+64*0+2] + pmullw m1, m4, [srcq+64*1+0] + pmullw m3, m5, [srcq+64*1+2] + add srcq, ssq + paddw m0, m6 + paddw m1, m6 + paddw m0, m2 + paddw m1, m3 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + pmullw m0, m4, [srcq+64*0+0] + pmullw m7, m5, [srcq+64*0+2] + pmullw m1, m4, [srcq+64*1+0] + pmullw m8, m5, [srcq+64*1+2] + pmullw m2, m4, [srcq+64*2+0] + pmullw m9, m5, [srcq+64*2+2] + pmullw m3, m4, [srcq+64*3+0] + pmullw m10, m5, [srcq+64*3+2] + add srcq, ssq + REPX {paddw x, m6}, m0, m1, m2, m3 + paddw m0, m7 + paddw m1, m8 + paddw m2, m9 + paddw m3, m10 + REPX {psrlw x, 4}, m0, m1, m2, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_v)] + shl mxyd, 11 + vpbroadcastw m8, mxyd + add t0, r7 + jmp t0 +.v_w2: + movd xmm0, [srcq+ssq*0] +.v_w2_loop: + movd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq xmm2, xmm0, xmm1 + movd xmm0, [srcq+ssq*0] + punpckldq xmm1, xmm0 + psubw xmm1, xmm2 + pmulhrsw xmm1, xm8 + paddw xmm1, xmm2 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xmm0, [srcq+ssq*0] +.v_w4_loop: + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq xmm2, xmm0, xmm1 + movq xmm0, [srcq+ssq*0] + punpcklqdq xmm1, xmm0 + psubw xmm1, xmm2 + pmulhrsw xmm1, xm8 + paddw xmm1, xmm2 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu xmm0, [srcq+ssq*0] +.v_w8_loop: + vbroadcasti128 ymm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd ymm2, ymm0, ymm1, 0xf0 + vbroadcasti128 ymm0, [srcq+ssq*0] + vpblendd ymm1, ymm0, 0xf0 + psubw ymm1, ymm2 + pmulhrsw ymm1, ym8 + paddw ymm1, ymm2 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + vzeroupper + RET +.v_w16: + movu ym0, [srcq+ssq*0] +.v_w16_loop: + movu ym3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw ym1, ym3, ym0 + pmulhrsw ym1, ym8 + paddw ym1, ym0 + movu ym0, [srcq+ssq*0] + psubw ym2, ym0, ym3 + pmulhrsw ym2, ym8 + paddw ym2, ym3 + mova [dstq+dsq*0], ym1 + mova [dstq+dsq*1], ym2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: + movu m0, [srcq+ssq*0] +.v_w32_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m8 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m8 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] +.v_w64_loop: + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + psubw m4, m2, m0 + pmulhrsw m4, m8 + paddw m4, m0 + movu m0, [srcq+ssq*0+64*0] + psubw m5, m3, m1 + pmulhrsw m5, m8 + paddw m5, m1 + movu m1, [srcq+ssq*0+64*1] + psubw m6, m0, m2 + pmulhrsw m6, m8 + psubw m7, m1, m3 + pmulhrsw m7, m8 + mova [dstq+dsq*0+64*0], m4 + mova [dstq+dsq*0+64*1], m5 + paddw m6, m2 + paddw m7, m3 + mova [dstq+dsq*1+64*0], m6 + mova [dstq+dsq*1+64*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*0+64*2] + movu m3, [srcq+ssq*0+64*3] +.v_w128_loop: + movu m4, [srcq+ssq*1+64*0] + movu m5, [srcq+ssq*1+64*1] + movu m6, [srcq+ssq*1+64*2] + movu m7, [srcq+ssq*1+64*3] + lea srcq, [srcq+ssq*2] + psubw m9, m4, m0 + pmulhrsw m9, m8 + paddw m9, m0 + movu m0, [srcq+ssq*0+64*0] + psubw m10, m5, m1 + pmulhrsw m10, m8 + paddw m10, m1 + movu m1, [srcq+ssq*0+64*1] + psubw m11, m6, m2 + pmulhrsw m11, m8 + paddw m11, m2 + movu m2, [srcq+ssq*0+64*2] + psubw m12, m7, m3 + pmulhrsw m12, m8 + paddw m12, m3 + movu m3, [srcq+ssq*0+64*3] + mova [dstq+dsq*0+64*0], m9 + psubw m9, m0, m4 + pmulhrsw m9, m8 + mova [dstq+dsq*0+64*1], m10 + psubw m10, m1, m5 + pmulhrsw m10, m8 + mova [dstq+dsq*0+64*2], m11 + psubw m11, m2, m6 + pmulhrsw m11, m8 + mova [dstq+dsq*0+64*3], m12 + psubw m12, m3, m7 + pmulhrsw m12, m8 + paddw m9, m4 + paddw m10, m5 + mova [dstq+dsq*1+64*0], m9 + mova [dstq+dsq*1+64*1], m10 + paddw m11, m6 + paddw m12, m7 + mova [dstq+dsq*1+64*2], m11 + mova [dstq+dsq*1+64*3], m12 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w128_loop + RET +.hv: + movzx t0d, word [r7+t0*2+table_offset(put, _bilin_hv)] + shl mxyd, 11 + vpbroadcastd m6, [pw_2] + vpbroadcastw m7, mxyd + vpbroadcastd m8, [pw_8192] + add t0, r7 + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + vpbroadcastd m8, [pw_2048] +.hv_12bpc: + jmp t0 +.hv_w2: + vpbroadcastq xmm1, [srcq+ssq*0] + pmullw xmm0, xmm1, xm4 + psrlq xmm1, 16 + pmullw xmm1, xm5 + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 +.hv_w2_loop: + movq xmm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm2, [srcq+ssq*0] + pmullw xmm1, xmm2, xm4 + psrlq xmm2, 16 + pmullw xmm2, xm5 + paddw xmm1, xm6 + paddw xmm1, xmm2 + psrlw xmm1, 2 ; 1 _ 2 _ + shufpd xmm2, xmm0, xmm1, 0x01 ; 0 _ 1 _ + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm7 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm8 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + pmullw xmm0, xm4, [srcq+ssq*0-8] + pmullw xmm1, xm5, [srcq+ssq*0-6] + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 +.hv_w4_loop: + movq xmm1, [srcq+ssq*1+0] + movq xmm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps xmm1, [srcq+ssq*0+0] + movhps xmm2, [srcq+ssq*0+2] + pmullw xmm1, xm4 + pmullw xmm2, xm5 + paddw xmm1, xm6 + paddw xmm1, xmm2 + psrlw xmm1, 2 ; 1 2 + shufpd xmm2, xmm0, xmm1, 0x01 ; 0 1 + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm7 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm8 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xmm0, xm4, [srcq+ssq*0+0] + pmullw xmm1, xm5, [srcq+ssq*0+2] + paddw xmm0, xm6 + paddw xmm0, xmm1 + psrlw xmm0, 2 + vinserti32x4 ym0, xmm0, 1 +.hv_w8_loop: + movu xm1, [srcq+ssq*1+0] + movu xm2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym1, [srcq+ssq*0+0], 1 + vinserti32x4 ym2, [srcq+ssq*0+2], 1 + pmullw ym1, ym4 + pmullw ym2, ym5 + paddw ym1, ym6 + paddw ym1, ym2 + psrlw ym1, 2 ; 1 2 + vshufi32x4 ym2, ym0, ym1, 0x01 ; 0 1 + mova ym0, ym1 + psubw ym1, ym2 + paddw ym1, ym1 + pmulhw ym1, ym7 + paddw ym1, ym2 + pmulhrsw ym1, ym8 + mova [dstq+dsq*0], xm1 + vextracti32x4 [dstq+dsq*1], ym1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + pmullw ym0, ym4, [srcq+ssq*0+0] + pmullw ym1, ym5, [srcq+ssq*0+2] + paddw ym0, ym6 + paddw ym0, ym1 + psrlw ym0, 2 + vinserti32x8 m0, ym0, 1 +.hv_w16_loop: + movu ym1, [srcq+ssq*1+0] + movu ym2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + vinserti32x8 m1, [srcq+ssq*0+0], 1 + vinserti32x8 m2, [srcq+ssq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m6 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + vshufi32x4 m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m7 + paddw m1, m2 + pmulhrsw m1, m8 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: +.hv_w64: +.hv_w128: + movifnidn wd, wm + lea r6d, [hq+wq*8-256] + mov r4, srcq + mov r7, dstq +.hv_w32_loop0: + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m1, m5, [srcq+ssq*0+2] + paddw m0, m6 + paddw m0, m1 + psrlw m0, 2 +.hv_w32_loop: + pmullw m3, m4, [srcq+ssq*1+0] + pmullw m1, m5, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + paddw m3, m6 + paddw m3, m1 + psrlw m3, 2 + psubw m1, m3, m0 + paddw m1, m1 + pmulhw m1, m7 + paddw m1, m0 + pmullw m0, m4, [srcq+ssq*0+0] + pmullw m2, m5, [srcq+ssq*0+2] + paddw m0, m6 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m3 + paddw m2, m2 + pmulhw m2, m7 + paddw m2, m3 + pmulhrsw m1, m8 + pmulhrsw m2, m8 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + add r4, 64 + add r7, 64 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w32_loop0 + RET + +cglobal prep_bilin_16bpc, 3, 7, 16, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [r6-prep_avx512icl+pw_8192] + add wq, r6 + shr r5d, 11 + vpbroadcastd m4, [r6-prep_avx512icl+prep_mul+r5*4] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq xmm0, [srcq+strideq*0] + movhps xmm0, [srcq+strideq*1] + vpbroadcastq ymm1, [srcq+strideq*2] + vpbroadcastq ymm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm0, ymm1, 0x30 + vpblendd ymm0, ymm2, 0xc0 + pmullw ymm0, ym4 + psubw ymm0, ym5 + mova [tmpq], ymm0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + vzeroupper + RET +.prep_w8: + movu xm0, [srcq+strideq*0] + vinserti32x4 ym0, [srcq+strideq*1], 1 + vinserti32x4 m0, [srcq+strideq*2], 2 + vinserti32x4 m0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + psubw m0, m5 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + movu ym1, [srcq+strideq*2] + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmullw m0, m4, [srcq+strideq*0] + pmullw m1, m4, [srcq+strideq*1] + pmullw m2, m4, [srcq+strideq*2] + pmullw m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .prep_w32 + RET +.prep_w64: + pmullw m0, m4, [srcq+strideq*0+64*0] + pmullw m1, m4, [srcq+strideq*0+64*1] + pmullw m2, m4, [srcq+strideq*1+64*0] + pmullw m3, m4, [srcq+strideq*1+64*1] + lea srcq, [srcq+strideq*2] + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .prep_w64 + RET +.prep_w128: + pmullw m0, m4, [srcq+64*0] + pmullw m1, m4, [srcq+64*1] + pmullw m2, m4, [srcq+64*2] + pmullw m3, m4, [srcq+64*3] + add srcq, strideq + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + dec hd + jg .prep_w128 + RET +.h: + vpbroadcastw m5, mxyd + mov mxyd, r6m ; my + vpbroadcastd m4, [pw_16] + vpbroadcastd m6, [pw_32766] + psubw m4, m5 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m4, 2 + psllw m5, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + movu xm1, [srcq+strideq*0] + vinserti32x4 ym1, [srcq+strideq*2], 1 + movu xm2, [srcq+strideq*1] + vinserti32x4 ym2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1, ym2 + psrldq ym1, 2 + psrldq ym2, 2 + pmullw ym0, ym4 + punpcklqdq ym1, ym2 + pmullw ym1, ym5 + psubw ym0, ym6 + paddw ym0, ym1 + psraw ym0, 2 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4 + RET +.h_w8: + movu xm0, [srcq+strideq*0+0] + movu xm1, [srcq+strideq*0+2] + vinserti32x4 ym0, [srcq+strideq*1+0], 1 + vinserti32x4 ym1, [srcq+strideq*1+2], 1 + vinserti32x4 m0, [srcq+strideq*2+0], 2 + vinserti32x4 m1, [srcq+strideq*2+2], 2 + vinserti32x4 m0, [srcq+stride3q +0], 3 + vinserti32x4 m1, [srcq+stride3q +2], 3 + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8 + RET +.h_w16: + movu ym0, [srcq+strideq*0+0] + vinserti32x8 m0, [srcq+strideq*1+0], 1 + movu ym1, [srcq+strideq*0+2] + vinserti32x8 m1, [srcq+strideq*1+2], 1 + lea srcq, [srcq+strideq*2] + pmullw m0, m4 + pmullw m1, m5 + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 2 + jg .h_w16 + RET +.h_w32: + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m2, m5, [srcq+strideq*0+2] + pmullw m1, m4, [srcq+strideq*1+0] + pmullw m3, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 2 + jg .h_w32 + RET +.h_w64: + pmullw m0, m4, [srcq+ 0] + pmullw m2, m5, [srcq+ 2] + pmullw m1, m4, [srcq+64] + pmullw m3, m5, [srcq+66] + add srcq, strideq + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + dec hd + jg .h_w64 + RET +.h_w128: + pmullw m0, m4, [srcq+ 0] + pmullw m7, m5, [srcq+ 2] + pmullw m1, m4, [srcq+ 64] + pmullw m8, m5, [srcq+ 66] + pmullw m2, m4, [srcq+128] + pmullw m9, m5, [srcq+130] + pmullw m3, m4, [srcq+192] + pmullw m10, m5, [srcq+194] + add srcq, strideq + REPX {psubw x, m6}, m0, m1, m2, m3 + paddw m0, m7 + paddw m1, m8 + paddw m2, m9 + paddw m3, m10 + REPX {psraw x, 2}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + vpbroadcastw m9, mxyd + vpbroadcastd m8, [pw_16] + vpbroadcastd m10, [pw_32766] + add wq, r6 + lea stride3q, [strideq*3] + psubw m8, m9 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m8, 2 + psllw m9, 2 +.v_12bpc: + jmp wq +.v_w4: + movq xmm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastq xmm2, [srcq+strideq*1] + vpbroadcastq ymm1, [srcq+strideq*2] + vpbroadcastq ymm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm2, ymm1, 0x30 + vpblendd ymm2, ymm3, 0xc0 + vpblendd ymm1, ymm2, ymm0, 0x03 ; 0 1 2 3 + movq xmm0, [srcq+strideq*0] + valignq ymm2, ymm0, ymm2, 1 ; 1 2 3 4 + pmullw ymm1, ym8 + pmullw ymm2, ym9 + psubw ymm1, ym10 + paddw ymm1, ymm2 + psraw ymm1, 2 + mova [tmpq], ymm1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + movu xm0, [srcq+strideq*0] +.v_w8_loop: + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vinserti32x4 m1, [srcq+strideq*2], 2 + vinserti32x4 m1, [srcq+stride3q ], 3 ; 0 1 2 3 + lea srcq, [srcq+strideq*4] + movu xm0, [srcq+strideq*0] + valignq m2, m0, m1, 2 ; 1 2 3 4 + pmullw m1, m8 + pmullw m2, m9 + psubw m1, m10 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + movu ym0, [srcq+strideq*0] +.v_w16_loop: + vinserti32x8 m1, m0, [srcq+strideq*1], 1 ; 0 1 + movu ym3, [srcq+strideq*2] + vinserti32x8 m2, m3, [srcq+stride3q ], 1 ; 2 3 + lea srcq, [srcq+strideq*4] + movu ym0, [srcq+strideq*0] + vshufi32x4 m3, m1, m3, q1032 ; 1 2 + vshufi32x4 m4, m2, m0, q1032 ; 3 4 + pmullw m1, m8 + pmullw m2, m8 + pmullw m3, m9 + pmullw m4, m9 + psubw m1, m10 + psubw m2, m10 + paddw m1, m3 + paddw m2, m4 + psraw m1, 2 + psraw m2, 2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + movu m0, [srcq+strideq*0] +.v_w32_loop: + movu m3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m1, m8, m0 + movu m0, [srcq+strideq*0] + pmullw m2, m8, m3 + pmullw m3, m9 + pmullw m4, m9, m0 + psubw m1, m10 + psubw m2, m10 + paddw m1, m3 + paddw m2, m4 + psraw m1, 2 + psraw m2, 2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] +.v_w64_loop: + add srcq, strideq + pmullw m2, m8, m0 + movu m0, [srcq+64*0] + pmullw m3, m8, m1 + movu m1, [srcq+64*1] + pmullw m4, m9, m0 + pmullw m5, m9, m1 + psubw m2, m10 + psubw m3, m10 + paddw m2, m4 + paddw m3, m5 + psraw m2, 2 + psraw m3, 2 + mova [tmpq+64*0], m2 + mova [tmpq+64*1], m3 + add tmpq, 64*2 + dec hd + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] + movu m2, [srcq+64*2] + movu m3, [srcq+64*3] +.v_w128_loop: + add srcq, strideq + pmullw m4, m8, m0 + movu m0, [srcq+64*0] + pmullw m5, m8, m1 + movu m1, [srcq+64*1] + pmullw m6, m8, m2 + movu m2, [srcq+64*2] + pmullw m7, m8, m3 + movu m3, [srcq+64*3] + pmullw m11, m9, m0 + pmullw m12, m9, m1 + pmullw m13, m9, m2 + pmullw m14, m9, m3 + REPX {psubw x, m10}, m4, m5, m6, m7 + paddw m4, m11 + paddw m5, m12 + paddw m6, m13 + paddw m7, m14 + REPX {psraw x, 2}, m4, m5, m6, m7 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m5 + mova [tmpq+64*2], m6 + mova [tmpq+64*3], m7 + add tmpq, 64*4 + dec hd + jg .v_w128_loop + RET +.hv: + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + vpbroadcastw m7, mxyd + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + movq xmm0, [srcq+strideq*0+0] + movq xmm1, [srcq+strideq*0+2] + pmullw xmm0, xm4 + pmullw xmm1, xm5 + psubw xmm0, xm6 + paddw xmm0, xmm1 + psraw xmm0, 2 + vpbroadcastq ym0, xmm0 +.hv_w4_loop: + movu xm1, [srcq+strideq*1] + vinserti128 ym1, [srcq+stride3q ], 1 + movu xm2, [srcq+strideq*2] + lea srcq, [srcq+strideq*4] + vinserti128 ym2, [srcq+strideq*0], 1 + punpcklqdq ym3, ym1, ym2 + psrldq ym1, 2 + psrldq ym2, 2 + pmullw ym3, ym4 + punpcklqdq ym1, ym2 + pmullw ym1, ym5 + psubw ym3, ym6 + paddw ym1, ym3 + psraw ym1, 2 ; 1 2 3 4 + valignq ym2, ym1, ym0, 3 ; 0 1 2 3 + mova ym0, ym1 + psubw ym1, ym2 + pmulhrsw ym1, ym7 + paddw ym1, ym2 + mova [tmpq], ym1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + pmullw xm0, xm4, [srcq+strideq*0+0] + pmullw xm1, xm5, [srcq+strideq*0+2] + psubw xm0, xm6 + paddw xm0, xm1 + psraw xm0, 2 + vinserti32x4 m0, xm0, 3 +.hv_w8_loop: + movu xm1, [srcq+strideq*1+0] + movu xm2, [srcq+strideq*1+2] + vinserti32x4 ym1, [srcq+strideq*2+0], 1 + vinserti32x4 ym2, [srcq+strideq*2+2], 1 + vinserti32x4 m1, [srcq+stride3q +0], 2 + vinserti32x4 m2, [srcq+stride3q +2], 2 + lea srcq, [srcq+strideq*4] + vinserti32x4 m1, [srcq+strideq*0+0], 3 + vinserti32x4 m2, [srcq+strideq*0+2], 3 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m6 + paddw m1, m2 + psraw m1, 2 ; 1 2 3 4 + valignq m2, m1, m0, 6 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m7 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + pmullw ym0, ym4, [srcq+strideq*0+0] + pmullw ym1, ym5, [srcq+strideq*0+2] + psubw ym0, ym6 + paddw ym0, ym1 + psraw ym0, 2 + vinserti32x8 m0, ym0, 1 +.hv_w16_loop: + movu ym1, [srcq+strideq*1+0] + movu ym2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + vinserti32x8 m1, [srcq+strideq*0+0], 1 + vinserti32x8 m2, [srcq+strideq*0+2], 1 + pmullw m1, m4 + pmullw m2, m5 + psubw m1, m6 + paddw m1, m2 + psraw m1, 2 ; 1 2 + vshufi32x4 m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m7 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m1, m5, [srcq+strideq*0+2] + psubw m0, m6 + paddw m0, m1 + psraw m0, 2 +.hv_w32_loop: + pmullw m3, m4, [srcq+strideq*1+0] + pmullw m1, m5, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + psubw m3, m6 + paddw m3, m1 + psraw m3, 2 + psubw m1, m3, m0 + pmulhrsw m1, m7 + paddw m1, m0 + pmullw m0, m4, [srcq+strideq*0+0] + pmullw m2, m5, [srcq+strideq*0+2] + psubw m0, m6 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m3 + pmulhrsw m2, m7 + paddw m2, m3 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + pmullw m0, m4, [srcq+ 0] + pmullw m2, m5, [srcq+ 2] + pmullw m1, m4, [srcq+64] + pmullw m3, m5, [srcq+66] + psubw m0, m6 + psubw m1, m6 + paddw m0, m2 + paddw m1, m3 + psraw m0, 2 + psraw m1, 2 +.hv_w64_loop: + add srcq, strideq + pmullw m2, m4, [srcq+ 0] + pmullw m8, m5, [srcq+ 2] + pmullw m3, m4, [srcq+64] + pmullw m9, m5, [srcq+66] + psubw m2, m6 + psubw m3, m6 + paddw m2, m8 + paddw m3, m9 + psraw m2, 2 + psraw m3, 2 + psubw m8, m2, m0 + psubw m9, m3, m1 + pmulhrsw m8, m7 + pmulhrsw m9, m7 + paddw m8, m0 + mova m0, m2 + paddw m9, m1 + mova m1, m3 + mova [tmpq+64*0], m8 + mova [tmpq+64*1], m9 + add tmpq, 64*2 + dec hd + jg .hv_w64_loop + RET +.hv_w128: + pmullw m0, m4, [srcq+ 0] + pmullw m8, m5, [srcq+ 2] + pmullw m1, m4, [srcq+ 64] + pmullw m9, m5, [srcq+ 66] + pmullw m2, m4, [srcq+128] + pmullw m10, m5, [srcq+130] + pmullw m3, m4, [srcq+192] + pmullw m11, m5, [srcq+194] + REPX {psubw x, m6}, m0, m1, m2, m3 + paddw m0, m8 + paddw m1, m9 + paddw m2, m10 + paddw m3, m11 + REPX {psraw x, 2}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, strideq + pmullw m8, m4, [srcq+ 0] + pmullw m12, m5, [srcq+ 2] + pmullw m9, m4, [srcq+ 64] + pmullw m13, m5, [srcq+ 66] + pmullw m10, m4, [srcq+128] + pmullw m14, m5, [srcq+130] + pmullw m11, m4, [srcq+192] + pmullw m15, m5, [srcq+194] + REPX {psubw x, m6}, m8, m9, m10, m11 + paddw m8, m12 + paddw m9, m13 + paddw m10, m14 + paddw m11, m15 + REPX {psraw x, 2}, m8, m9, m10, m11 + psubw m12, m8, m0 + psubw m13, m9, m1 + psubw m14, m10, m2 + psubw m15, m11, m3 + REPX {pmulhrsw x, m7}, m12, m13, m14, m15 + paddw m12, m0 + mova m0, m8 + paddw m13, m1 + mova m1, m9 + mova [tmpq+64*0], m12 + mova [tmpq+64*1], m13 + paddw m14, m2 + mova m2, m10 + paddw m15, m3 + mova m3, m11 + mova [tmpq+64*2], m14 + mova [tmpq+64*3], m15 + add tmpq, 64*4 + dec hd + jg .hv_w128_loop + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro MC_8TAP_FN 4 ; prefix, type, type_h, type_v +cglobal %1_8tap_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8tap_16bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%define buf rsp+stack_offset+8 ; shadow space +%else +DECLARE_REG_TMP 7, 8 +%define buf rsp-40 ; red zone +%endif + +MC_8TAP_FN put, sharp, SHARP, SHARP +MC_8TAP_FN put, sharp_smooth, SHARP, SMOOTH +MC_8TAP_FN put, smooth_sharp, SMOOTH, SHARP +MC_8TAP_FN put, smooth, SMOOTH, SMOOTH +MC_8TAP_FN put, sharp_regular, SHARP, REGULAR +MC_8TAP_FN put, regular_sharp, REGULAR, SHARP +MC_8TAP_FN put, smooth_regular, SMOOTH, REGULAR +MC_8TAP_FN put, regular_smooth, REGULAR, SMOOTH +MC_8TAP_FN put, regular, REGULAR, REGULAR + +cglobal put_8tap_16bpc, 4, 9, 16, dst, ds, src, ss, w, h, mx, my +%define base r8-put_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx512icl] + movifnidn wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 +%if WIN64 + pop r8 +%endif + jmp wq +.h_w2: + movzx mxd, mxb + sub srcq, 2 + mova ym2, [spel_h_shuf2a] + pmovsxbw xmm4, [base+subpel_filters+mxq*8] + pshufd xmm3, xmm4, q1111 + pshufd xmm4, xmm4, q2222 +.h_w2_loop: + movu xm1, [srcq+ssq*0] + vinserti32x4 ym1, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova xmm0, xm8 + vpermb ym1, ym2, ym1 + vpdpwssd xmm0, xmm3, xm1 + vextracti32x4 xm1, ym1, 1 + vpdpwssd xmm0, xmm4, xm1 + psrad xmm0, 6 + packusdw xmm0, xmm0 + pminsw xmm0, xm9 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + vbroadcasti32x4 ym4, [spel_h_shufA] + vbroadcasti32x4 ym5, [spel_h_shufB] + pshufd xmm0, xmm0, q2211 + vpbroadcastq ym6, xmm0 + vpermq ym7, ymm0, q1111 +.h_w4_loop: + movu xm2, [srcq+ssq*0] + vinserti32x4 ym2, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova ym0, ym8 + pshufb ym1, ym2, ym4 + vpdpwssd ym0, ym6, ym1 + pshufb ym2, ym5 + vpdpwssd ym0, ym7, ym2 + psrad ym0, 6 + vextracti32x4 xm1, ym0, 1 + packusdw xm0, xm1 + pminsw xmm0, xm0, xm9 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + mov r7d, r8m + vpbroadcastw m9, r8m + shr r7d, 11 + vpbroadcastd m8, [base+put_8tap_h_rnd+r7*4] + cmp wd, 4 + je .h_w4 + jl .h_w2 + shr mxd, 16 + sub srcq, 6 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mova [buf], xmm0 + vpbroadcastd m10, xmm0 + vpbroadcastd m11, [buf+ 4] + vpbroadcastd m12, [buf+ 8] + vpbroadcastd m13, [buf+12] + sub wd, 16 + je .h_w16 + jg .h_w32 +.h_w8: + mova m4, [spel_h_shufA] + movu m5, [spel_h_shufB] + movu m6, [spel_h_shufC] + mova m7, [spel_h_shufD] +.h_w8_loop: + movu ym2, [srcq+ssq*0] + vinserti32x8 m2, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + mova m0, m8 + vpermb m1, m4, m2 + vpdpwssd m0, m10, m1 + vpermb m1, m5, m2 + vpdpwssd m0, m11, m1 + vpermb m1, m6, m2 + vpdpwssd m0, m12, m1 + vpermb m1, m7, m2 + vpdpwssd m0, m13, m1 + psrad m0, 6 + vextracti32x8 ym1, m0, 1 + packusdw ym0, ym1 + pminsw ym0, ym9 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8_loop + RET +.h_w16: + vbroadcasti32x4 m6, [spel_h_shufA] + vbroadcasti32x4 m7, [spel_h_shufB] +.h_w16_loop: + movu ym2, [srcq+ssq*0+ 0] + vinserti32x8 m2, [srcq+ssq*1+ 0], 1 + movu ym3, [srcq+ssq*0+16] + vinserti32x8 m3, [srcq+ssq*1+16], 1 + lea srcq, [srcq+ssq*2] + mova m0, m8 + mova m1, m8 + pshufb m4, m2, m6 + vpdpwssd m0, m10, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m12, m4 ; b2 + pshufb m4, m2, m7 + vpdpwssd m0, m11, m4 ; a1 + pshufb m4, m3, m7 + vpdpwssd m1, m13, m4 ; b3 + shufpd m2, m3, 0x55 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a2 + vpdpwssd m1, m10, m4 ; b0 + pshufb m2, m7 + vpdpwssd m0, m13, m2 ; a3 + vpdpwssd m1, m11, m2 ; b1 + psrad m0, 6 + psrad m1, 6 + packusdw m0, m1 + pminsw m0, m9 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + lea srcq, [srcq+wq*2] + vbroadcasti32x4 m6, [spel_h_shufA] + lea dstq, [dstq+wq*2] + vbroadcasti32x4 m7, [spel_h_shufB] + neg wq +.h_w32_loop0: + mov r6, wq +.h_w32_loop: + movu m2, [srcq+r6*2+ 0] + movu m3, [srcq+r6*2+ 8] + mova m0, m8 + mova m1, m8 + pshufb m4, m2, m6 + vpdpwssd m0, m10, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m10, m4 ; b0 + vpdpwssd m0, m12, m4 ; a2 + movu m4, [srcq+r6*2+16] + pshufb m3, m7 + vpdpwssd m1, m11, m3 ; b1 + vpdpwssd m0, m13, m3 ; a3 + pshufb m3, m4, m6 + vpdpwssd m1, m12, m3 ; b2 + pshufb m2, m7 + vpdpwssd m0, m11, m2 ; a1 + pshufb m4, m7 + vpdpwssd m1, m13, m4 ; b3 + psrad m0, 6 + psrad m1, 6 + packusdw m0, m1 + pminsw m0, m9 + mova [dstq+r6*2], m0 + add r6, 32 + jl .h_w32_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w32_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m10, [pd_32] + pmovsxbw xmm0, [base+subpel_filters+myq*8] + tzcnt r7d, wd + vpbroadcastw m11, r8m + lea r6, [ssq*3] + movzx r7d, word [r8+r7*2+table_offset(put, _8tap_v)] + sub srcq, r6 + mova [rsp+stack_offset+8], xmm0 + vpbroadcastd m12, xmm0 + add r7, r8 + vpbroadcastd m13, [rsp+stack_offset+12] + vpbroadcastd m14, [rsp+stack_offset+16] + vpbroadcastd m15, [rsp+stack_offset+20] + jmp r7 +.v_w2: + movd xmm2, [srcq+ssq*0] + pinsrd xmm2, [srcq+ssq*1], 1 + pinsrd xmm2, [srcq+ssq*2], 2 + add srcq, r6 + pinsrd xmm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, r6 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklwd xmm3, xmm1 ; 45 56 + punpcklwd xmm1, xmm2, xmm4 ; 01 12 + punpckhwd xmm2, xmm4 ; 23 34 +.v_w2_loop: + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xmm5, xm10 + vpdpwssd xmm5, xm12, xmm1 ; a0 b0 + mova xmm1, xmm2 + vpdpwssd xmm5, xm13, xmm2 ; a1 b1 + mova xmm2, xmm3 + vpdpwssd xmm5, xm14, xmm3 ; a2 b2 + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm0, 0x02 ; 7 8 + punpcklwd xmm3, xmm4 ; 67 78 + vpdpwssd xmm5, xm15, xmm3 ; a3 b3 + psrad xmm5, 6 + packusdw xmm5, xmm5 + pminsw xmm5, xm11 + movd [dstq+dsq*0], xmm5 + pextrd [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq xmm1, [srcq+ssq*0] + vpbroadcastq ymm0, [srcq+ssq*1] + vpbroadcastq ymm2, [srcq+ssq*2] + add srcq, r6 + vpbroadcastq ymm4, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm5, [srcq+ssq*2] + add srcq, r6 + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklwd ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm4, 0x30 + vpblendd ymm4, ymm3, 0x30 + punpcklwd ymm2, ymm4 ; 23 34 + vpblendd ymm3, ymm5, 0x30 + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 45 56 +.v_w4_loop: + vpbroadcastq ymm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova ymm4, ym10 + vpdpwssd ymm4, ym12, ymm1 ; a0 b0 + mova ymm1, ymm2 + vpdpwssd ymm4, ym13, ymm2 ; a1 b1 + mova ymm2, ymm3 + vpdpwssd ymm4, ym14, ymm3 ; a2 b2 + vpblendd ymm3, ymm0, ymm5, 0x30 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 67 78 + vpdpwssd ymm4, ym15, ymm3 ; a3 b3 + psrad ymm4, 6 + vextracti128 xmm5, ymm4, 1 + packusdw xmm4, xmm5 + pminsw xmm4, xm11 + movq [dstq+dsq*0], xmm4 + movhps [dstq+dsq*1], xmm4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + vbroadcasti32x4 m2, [srcq+ssq*2] + vinserti32x4 m1, m2, [srcq+ssq*0], 0 + vinserti32x4 m1, [srcq+ssq*1], 1 ; 0 1 2 + add srcq, r6 + vinserti32x4 ym2, [srcq+ssq*0], 1 + vinserti32x4 m2, [srcq+ssq*1], 2 ; 2 3 4 + mova m6, [spel_v_shuf8] + movu xm0, [srcq+ssq*1] + vinserti32x4 ym0, [srcq+ssq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+ssq*0], 2 ; 4 5 6 + vpermb m1, m6, m1 ; 01 12 + vpermb m2, m6, m2 ; 23 34 + vpermb m3, m6, m0 ; 45 56 +.v_w8_loop: + vinserti32x4 m0, [srcq+ssq*1], 3 + lea srcq, [srcq+ssq*2] + movu xm5, [srcq+ssq*0] + mova m4, m10 + vpdpwssd m4, m12, m1 ; a0 b0 + mova m1, m2 + vshufi32x4 m0, m5, q1032 ; 6 7 8 + vpdpwssd m4, m13, m2 ; a1 b1 + mova m2, m3 + vpdpwssd m4, m14, m3 ; a2 b2 + vpermb m3, m6, m0 ; 67 78 + vpdpwssd m4, m15, m3 ; a3 b3 + psrad m4, 6 + vextracti32x8 ym5, m4, 1 + packusdw ym4, ym5 + pminsw ym4, ym11 + mova [dstq+dsq*0], xm4 + vextracti32x4 [dstq+dsq*1], ym4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti32x8 m1, [srcq+ssq*1] + vinserti32x8 m0, m1, [srcq+ssq*0], 0 + vinserti32x8 m1, [srcq+ssq*2], 1 + mova m8, [spel_v_shuf16] + add srcq, r6 + movu ym3, [srcq+ssq*0] + vinserti32x8 m3, [srcq+ssq*1], 1 + movu ym5, [srcq+ssq*2] + add srcq, r6 + vinserti32x8 m5, [srcq+ssq*0], 1 + vpermb m0, m8, m0 ; 01 + vpermb m1, m8, m1 ; 12 + vpermb m3, m8, m3 ; 34 + vpermb m5, m8, m5 ; 56 + mova m9, [deint_q_shuf] + vpshrdd m2, m1, m3, 16 ; 23 + vpshrdd m4, m3, m5, 16 ; 45 +.v_w16_loop: + mova m6, m10 + mova m7, m10 + vpdpwssd m6, m12, m0 ; a0 + mova m0, m2 + vpdpwssd m7, m12, m1 ; b0 + mova m1, m3 + vpdpwssd m6, m13, m2 ; a1 + mova m2, m4 + vpdpwssd m7, m13, m3 ; b1 + mova m3, m5 + vpdpwssd m6, m14, m4 ; a2 + mova m4, m5 + vpdpwssd m7, m14, m5 ; b2 + movu ym5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m5, [srcq+ssq*0], 1 + vpermb m5, m8, m5 ; 78 + vpshrdd m4, m5, 16 ; 67 + vpdpwssd m6, m15, m4 ; a3 + vpdpwssd m7, m15, m5 ; b3 + psrad m6, 6 + psrad m7, 6 + packusdw m6, m7 + pminsw m6, m11 + vpermq m6, m9, m6 + mova [dstq+dsq*0], ym6 + vextracti32x8 [dstq+dsq*1], m6, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + movaps [rsp+stack_offset+8], xmm6 +%endif + lea wd, [hq+wq*8-256] + mov r7, srcq + mov r8, dstq +.v_w32_loop0: + movu m16, [srcq+ssq*0] + movu m17, [srcq+ssq*1] + movu m18, [srcq+ssq*2] + add srcq, r6 + movu m19, [srcq+ssq*0] + movu m20, [srcq+ssq*1] + movu m21, [srcq+ssq*2] + add srcq, r6 + movu m22, [srcq+ssq*0] + punpcklwd m0, m16, m17 ; 01l + punpckhwd m16, m17 ; 01h + punpcklwd m1, m17, m18 ; 12l + punpckhwd m17, m18 ; 12h + punpcklwd m2, m18, m19 ; 23l + punpckhwd m18, m19 ; 23h + punpcklwd m3, m19, m20 ; 34l + punpckhwd m19, m20 ; 34h + punpcklwd m4, m20, m21 ; 45l + punpckhwd m20, m21 ; 45h + punpcklwd m5, m21, m22 ; 56l + punpckhwd m21, m22 ; 56h +.v_w32_loop: + mova m6, m10 + vpdpwssd m6, m12, m0 ; a0l + mova m8, m10 + vpdpwssd m8, m12, m16 ; a0h + mova m7, m10 + vpdpwssd m7, m12, m1 ; b0l + mova m9, m10 + vpdpwssd m9, m12, m17 ; b0h + mova m0, m2 + vpdpwssd m6, m13, m2 ; a1l + mova m16, m18 + vpdpwssd m8, m13, m18 ; a1h + mova m1, m3 + vpdpwssd m7, m13, m3 ; b1l + mova m17, m19 + vpdpwssd m9, m13, m19 ; b1h + mova m2, m4 + vpdpwssd m6, m14, m4 ; a2l + mova m18, m20 + vpdpwssd m8, m14, m20 ; a2h + mova m3, m5 + vpdpwssd m7, m14, m5 ; b2l + mova m19, m21 + vpdpwssd m9, m14, m21 ; b2h + movu m21, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m4, m22, m21 ; 67l + punpckhwd m20, m22, m21 ; 67h + movu m22, [srcq+ssq*0] + vpdpwssd m6, m15, m4 ; a3l + vpdpwssd m8, m15, m20 ; a3h + punpcklwd m5, m21, m22 ; 78l + punpckhwd m21, m22 ; 78h + vpdpwssd m7, m15, m5 ; b3l + vpdpwssd m9, m15, m21 ; b3h + REPX {psrad x, 6}, m6, m8, m7, m9 + packusdw m6, m8 + packusdw m7, m9 + pminsw m6, m11 + pminsw m7, m11 + mova [dstq+dsq*0], m6 + mova [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + add r7, 64 + add r8, 64 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .v_w32_loop0 +%if WIN64 + movaps xmm6, [rsp+stack_offset+8] +%endif + vzeroupper + RET +.hv: + vpbroadcastw m11, r8m + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 + test dword r8m, 0x800 + jnz .hv_12bit + vpbroadcastd m10, [pd_2176] + psllw xmm0, 6 + jmp .hv_main +.hv_12bit: + vpbroadcastd m10, [pd_640] + psllw xmm0, 4 + psllw xmm1, 2 +.hv_main: + mova [buf+ 0], xmm0 + mova [buf+16], xmm1 + vpbroadcastd m8, [buf+ 4] + vpbroadcastd m9, [buf+ 8] + vpbroadcastd ym12, xmm1 + vpbroadcastd ym13, [buf+20] + vpbroadcastd ym14, [buf+24] + vpbroadcastd ym15, [buf+28] + movu xm4, [srcq+ssq*0] + vinserti32x4 ym4, [srcq+ssq*1], 1 + vinserti32x4 m4, [srcq+ssq*2], 2 + add srcq, r6 + vinserti32x4 m4, [srcq+ssq*0], 3 ; 0 1 2 3 + movu xm0, [srcq+ssq*1] + vinserti32x4 ym0, [srcq+ssq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+ssq*0], 2 ; 4 5 6 + cmp wd, 4 + je .hv_w4 + vbroadcasti32x4 m2, [spel_h_shufA] + mova m3, [spel_h_shuf2b] + mova ym6, [spel_h_shuf2a] + mova xm7, [spel_shuf2] + mova m1, m10 + pshufb m4, m2 + pshufb m0, m2 + punpcklqdq m2, m4, m0 + vpdpwssd m1, m8, m2 ; 04 15 26 3_ + punpckhqdq m4, m0 + vpdpwssd m1, m9, m4 + vpermb m1, m3, m1 ; 01 12 + vextracti32x4 xm2, ym1, 1 ; 23 34 + vextracti32x4 xm3, m1, 2 ; 45 56 +.hv_w2_loop: + movu xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym5, [srcq+ssq*0], 1 + mova xm4, xm10 + vpermb ym5, ym6, ym5 + pmaddwd xmm0, xm12, xm1 ; a0 b0 + vpdpwssd xm4, xm8, xm5 + vextracti32x4 xm5, ym5, 1 + mova xm1, xm2 + vpdpwssd xmm0, xm13, xm2 ; a1 b1 + vpdpwssd xm4, xm9, xm5 ; 7 8 + mova xm2, xm3 + vpdpwssd xmm0, xm14, xm3 ; a2 b2 + vpermt2b xm3, xm7, xm4 ; 67 78 + vpdpwssd xmm0, xm15, xm3 ; a3 b3 + psrad xmm0, 10 + packusdw xmm0, xmm0 + pminsw xmm0, xm11 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + vbroadcasti32x4 m19, [spel_h_shufA] + vbroadcasti32x4 m20, [spel_h_shufB] + mova ym6, [spel_shuf4a] + mova ym7, [spel_shuf4b] + mova m2, m10 + mova m3, m10 + pshufb m1, m4, m19 + vpdpwssd m2, m8, m1 + pshufb m1, m0, m19 + vpdpwssd m3, m8, m1 + pshufb m4, m20 + vpdpwssd m2, m9, m4 + pshufb m0, m20 + vpdpwssd m3, m9, m0 + vpermb m1, m6, m2 ; 01 12 + vshufi32x4 m2, m3, q1032 + vpermb m3, m6, m3 ; 45 56 + vpermb m2, m6, m2 ; 23 34 +.hv_w4_loop: + movu xm18, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 ym18, [srcq+ssq*0], 1 + mova ym4, ym10 + pshufb ym17, ym18, ym19 + pmaddwd ym16, ym12, ym1 ; a0 b0 + vpdpwssd ym4, ym8, ym17 + pshufb ym18, ym20 + mova ym1, ym2 + vpdpwssd ym16, ym13, ym2 ; a1 b1 + vpdpwssd ym4, ym9, ym18 ; 7 8 + mova ym2, ym3 + vpdpwssd ym16, ym14, ym3 ; a2 b2 + vpermt2b ym3, ym7, ym4 ; 67 78 + vpdpwssd ym16, ym15, ym3 ; a3 b3 + psrad ym16, 10 + vextracti128 xm17, ym16, 1 + packusdw xm16, xm17 + pminsw xm16, xm11 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + test dword r8m, 0x800 + jnz .hv_w8_12bit + vpbroadcastd m10, [pd_2176] + psllw xmm0, 6 + jmp .hv_w8_main +.hv_w8_12bit: + vpbroadcastd m10, [pd_640] + psllw xmm0, 4 + psllw xmm1, 2 +.hv_w8_main: + mova [buf+ 0], xmm0 + mova [buf+16], xmm1 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [buf+ 4] + vpbroadcastd m14, [buf+ 8] + vpbroadcastd m15, [buf+12] + vpbroadcastd m16, xmm1 + vpbroadcastd m17, [buf+20] + vpbroadcastd m18, [buf+24] + vpbroadcastd m19, [buf+28] + cmp wd, 16 + je .hv_w16 + jg .hv_w32 + mova m5, [spel_h_shufA] + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 ; 0 1 + movu ym9, [srcq+ssq*2] + add srcq, r6 + vinserti32x8 m9, [srcq+ssq*0], 1 ; 2 3 + movu ym20, [srcq+ssq*1] + vinserti32x8 m20, [srcq+ssq*2], 1 ; 4 5 + add srcq, r6 + movu ym21, [srcq+ssq*0] ; 6 + movu m6, [spel_h_shufB] + movu m7, [spel_h_shufC] + vpermb m8, m5, m0 + mova m1, m10 + vpdpwssd m1, m12, m8 ; a0 b0 + vpermb m8, m5, m9 + mova m2, m10 + vpdpwssd m2, m12, m8 ; c0 d0 + vpermb m8, m5, m20 + mova m3, m10 + vpdpwssd m3, m12, m8 ; e0 f0 + vpermb m8, m5, m21 + mova m4, m10 + vpdpwssd m4, m12, m8 ; g0 + vpermb m8, m6, m0 + vpdpwssd m1, m13, m8 ; a1 b1 + vpermb m8, m6, m9 + vpdpwssd m2, m13, m8 ; c1 d1 + vpermb m8, m6, m20 + vpdpwssd m3, m13, m8 ; e1 f1 + vpermb m8, m6, m21 + vpdpwssd m4, m13, m8 ; g1 + vpermb m8, m7, m0 + vpdpwssd m1, m14, m8 ; a2 b2 + vpermb m8, m7, m9 + vpdpwssd m2, m14, m8 ; c2 d2 + vpermb m8, m7, m20 + vpdpwssd m3, m14, m8 ; e2 f2 + vpermb m8, m7, m21 + vpdpwssd m4, m14, m8 ; g2 + mova m8, [spel_h_shufD] + vpermb m0, m8, m0 + vpdpwssd m1, m15, m0 ; a3 b3 + mova m0, [spel_shuf8a] + vpermb m9, m8, m9 + vpdpwssd m2, m15, m9 ; c3 d3 + mova m9, [spel_shuf8b] + vpermb m20, m8, m20 + vpdpwssd m3, m15, m20 ; e3 f3 + vpermb m21, m8, m21 + vpdpwssd m4, m15, m21 ; g3 + vpermt2b m1, m0, m2 ; 01 12 + vpermt2b m2, m0, m3 ; 23 34 + vpermt2b m3, m0, m4 ; 45 56 +.hv_w8_loop: + movu ym0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m0, [srcq+ssq*0], 1 + mova m4, m10 + vpermb m21, m5, m0 + vpdpwssd m4, m12, m21 ; h0 i0 + vpermb m21, m6, m0 + pmaddwd m20, m16, m1 ; A0 B0 + vpdpwssd m4, m13, m21 ; h1 i1 + vpermb m21, m7, m0 + mova m1, m2 + vpdpwssd m20, m17, m2 ; A1 B1 + vpdpwssd m4, m14, m21 ; h2 i2 + vpermb m21, m8, m0 + mova m2, m3 + vpdpwssd m20, m18, m3 ; A2 B2 + vpdpwssd m4, m15, m21 ; h3 i3 + vpermt2b m3, m9, m4 ; 67 78 + vpdpwssd m20, m19, m3 ; A3 B3 + psrad m20, 10 + vextracti32x8 ym21, m20, 1 + packusdw ym20, ym21 + pminsw ym20, ym11 + mova [dstq+dsq*0], xm20 + vextracti128 [dstq+dsq*1], ym20, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + vzeroupper + RET +.hv_w16: + WIN64_SPILL_XMM 26 + vbroadcasti32x8 m5, [srcq+ssq*0+ 8] + vinserti32x8 m4, m5, [srcq+ssq*0+ 0], 0 + vinserti32x8 m5, [srcq+ssq*0+16], 1 ; 0 + movu ym6, [srcq+ssq*1+ 0] + movu ym7, [srcq+ssq*1+16] + vinserti32x8 m6, [srcq+ssq*2+ 0], 1 + vinserti32x8 m7, [srcq+ssq*2+16], 1 ; 1 2 + add srcq, r6 + movu ym22, [srcq+ssq*0+ 0] + movu ym23, [srcq+ssq*0+16] + vinserti32x8 m22, [srcq+ssq*1+ 0], 1 + vinserti32x8 m23, [srcq+ssq*1+16], 1 ; 3 4 + movu ym24, [srcq+ssq*2+ 0] + movu ym25, [srcq+ssq*2+16] + add srcq, r6 + vinserti32x8 m24, [srcq+ssq*0+ 0], 1 + vinserti32x8 m25, [srcq+ssq*0+16], 1 ; 5 6 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m9, [spel_shuf16] + pshufb m0, m4, m20 + mova m1, m10 + vpdpwssd m1, m12, m0 ; a0 + pshufb m0, m6, m20 + mova m2, m10 + vpdpwssd m2, m12, m0 ; b0 + pshufb m0, m7, m20 + mova m3, m10 + vpdpwssd m3, m14, m0 ; c2 + pshufb m0, m4, m21 + vpdpwssd m1, m13, m0 ; a1 + pshufb m0, m6, m21 + vpdpwssd m2, m13, m0 ; b1 + pshufb m0, m7, m21 + vpdpwssd m3, m15, m0 ; c3 + pshufb m0, m5, m20 + vpdpwssd m1, m14, m0 ; a2 + shufpd m6, m7, 0x55 + pshufb m7, m6, m20 + vpdpwssd m2, m14, m7 ; b2 + vpdpwssd m3, m12, m7 ; c0 + pshufb m5, m21 + vpdpwssd m1, m15, m5 ; a3 + pshufb m6, m21 + vpdpwssd m2, m15, m6 ; b3 + vpdpwssd m3, m13, m6 ; c1 + pshufb m0, m22, m20 + mova m4, m10 + vpdpwssd m4, m12, m0 ; d0 + pshufb m0, m23, m20 + mova m5, m10 + vpdpwssd m5, m14, m0 ; e2 + pshufb m0, m24, m20 + mova m6, m10 + vpdpwssd m6, m12, m0 ; f0 + pshufb m0, m25, m20 + mova m7, m10 + vpdpwssd m7, m14, m0 ; g2 + pshufb m0, m22, m21 + vpdpwssd m4, m13, m0 ; d1 + pshufb m0, m23, m21 + vpdpwssd m5, m15, m0 ; e3 + pshufb m0, m24, m21 + vpdpwssd m6, m13, m0 ; f1 + pshufb m0, m25, m21 + vpdpwssd m7, m15, m0 ; g3 + shufpd m22, m23, 0x55 + pshufb m23, m22, m20 + vpdpwssd m4, m14, m23 ; d2 + vpdpwssd m5, m12, m23 ; e0 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m6, m14, m25 ; f2 + vpdpwssd m7, m12, m25 ; g0 + pshufb m22, m21 + vpdpwssd m4, m15, m22 ; d3 + vpdpwssd m5, m13, m22 ; e1 + pshufb m24, m21 + vpdpwssd m6, m15, m24 ; f3 + vpdpwssd m7, m13, m24 ; g1 + pslldq m1, 1 + vpermt2b m2, m9, m3 ; 12 + vpermt2b m4, m9, m5 ; 34 + vpermt2b m6, m9, m7 ; 56 + vpshrdd m1, m2, 16 ; 01 + vpshrdd m3, m2, m4, 16 ; 23 + vpshrdd m5, m4, m6, 16 ; 45 +.hv_w16_loop: + movu ym24, [srcq+ssq*1+ 0] + movu ym25, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*2] + vinserti32x8 m24, [srcq+ssq*0+ 0], 1 + vinserti32x8 m25, [srcq+ssq*0+16], 1 + mova m7, m10 + mova m8, m10 + pshufb m0, m24, m20 + vpdpwssd m7, m12, m0 ; h0 + pshufb m0, m25, m20 + vpdpwssd m8, m14, m0 ; i2 + pmaddwd m22, m16, m1 ; A0 + mova m1, m3 + pmaddwd m23, m16, m2 ; B0 + mova m2, m4 + pshufb m0, m24, m21 + vpdpwssd m7, m13, m0 ; h1 + pshufb m0, m25, m21 + vpdpwssd m8, m15, m0 ; i3 + vpdpwssd m22, m17, m3 ; A1 + mova m3, m5 + vpdpwssd m23, m17, m4 ; B1 + mova m4, m6 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m7, m14, m25 ; h2 + vpdpwssd m8, m12, m25 ; i0 + vpdpwssd m22, m18, m5 ; A2 + vpdpwssd m23, m18, m6 ; B2 + pshufb m24, m21 + vpdpwssd m7, m15, m24 ; h3 + vpdpwssd m8, m13, m24 ; i1 + vpermt2b m7, m9, m8 ; 78 + vpshrdd m5, m6, m7, 16 ; 67 + vpdpwssd m22, m19, m5 ; A3 + vpdpwssd m23, m19, m7 ; B3 + mova m6, m7 + psrad m22, 10 + psrad m23, 10 + vshufi32x4 m0, m22, m23, q3232 + vinserti32x8 m22, ym23, 1 + packusdw m22, m0 + pminsw m22, m11 + mova [dstq+dsq*0], ym22 + vextracti32x8 [dstq+dsq*1], m22, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 32 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m22, [spel_shuf32] + lea wd, [hq+wq*8-256] + mov r7, srcq + mov r8, dstq +.hv_w32_loop0: + movu m6, [srcq+ssq*0+ 0] + movu m7, [srcq+ssq*0+ 8] + movu m8, [srcq+ssq*0+16] + mova m0, m10 + mova m23, m10 + pshufb m9, m6, m20 + vpdpwssd m0, m12, m9 ; a0l + pshufb m9, m7, m20 + vpdpwssd m23, m12, m9 ; a0h + vpdpwssd m0, m14, m9 ; a2l + pshufb m7, m21 + vpdpwssd m23, m13, m7 ; a1h + vpdpwssd m0, m15, m7 ; a3l + pshufb m7, m8, m20 + vpdpwssd m23, m14, m7 ; a2h + pshufb m6, m21 + vpdpwssd m0, m13, m6 ; a1l + pshufb m8, m21 + vpdpwssd m23, m15, m8 ; a3h +%macro PUT_8TAP_HV_W32 5 ; dst_lo, dst_hi, stride_name, stride[1-2] + movu m6, [srcq+%3*%4+ 0] + movu m7, [srcq+%3*%4+ 8] + movu m8, [srcq+%3*%4+16] +%if %4 == 2 + add srcq, r6 +%endif + movu m29, [srcq+%3*%5+ 0] + movu m30, [srcq+%3*%5+ 8] + movu m31, [srcq+%3*%5+16] +%if %5 == 2 + add srcq, r6 +%endif + mova m%1, m10 + mova m9, m10 + pshufb m%2, m6, m20 + vpdpwssd m%1, m12, m%2 ; x0l + pshufb m%2, m29, m20 + vpdpwssd m9, m12, m%2 ; y0l + pshufb m6, m21 + vpdpwssd m%1, m13, m6 ; x1l + pshufb m29, m21 + vpdpwssd m9, m13, m29 ; y1l + pshufb m6, m7, m20 + mova m%2, m10 + vpdpwssd m%2, m12, m6 ; x0h + pshufb m29, m30, m20 + vpdpwssd m%1, m14, m6 ; y2l + mova m6, m10 + vpdpwssd m6, m12, m29 ; x0h + pshufb m7, m21 + vpdpwssd m9, m14, m29 ; y2l + pshufb m30, m21 + vpdpwssd m%2, m13, m7 ; x1h + vpdpwssd m%1, m15, m7 ; x3l + pshufb m7, m8, m20 + vpdpwssd m6, m13, m30 ; y1h + vpdpwssd m9, m15, m30 ; y3l + pshufb m30, m31, m20 + vpdpwssd m%2, m14, m7 ; x2h + pshufb m8, m21 + vpdpwssd m6, m14, m30 ; y2h + pshufb m31, m21 + vpdpwssd m%2, m15, m8 ; x3h + vpdpwssd m6, m15, m31 ; y3h +%if %1 == 1 + vpermt2b m0, m22, m%1 ; 01l + vpermt2b m23, m22, m%2 ; 01h +%endif + vpermt2b m%1, m22, m9 ; xyl + vpermt2b m%2, m22, m6 ; xyh +%endmacro + PUT_8TAP_HV_W32 1, 24, ssq, 1, 2 ; 12 + PUT_8TAP_HV_W32 3, 26, ssq, 0, 1 ; 34 + PUT_8TAP_HV_W32 5, 28, ssq, 2, 0 ; 56 + vpshrdd m2, m1, m3, 16 ; 23l + vpshrdd m25, m24, m26, 16 ; 23h + vpshrdd m4, m3, m5, 16 ; 45l + vpshrdd m27, m26, m28, 16 ; 45h +.hv_w32_loop: + movu m7, [srcq+ssq*1+ 0] + movu m9, [srcq+ssq*2+ 0] + movu m6, [srcq+ssq*1+ 8] + movu m8, [srcq+ssq*2+ 8] + mova m29, m10 + mova m31, m10 + pshufb m30, m7, m20 + vpdpwssd m29, m12, m30 ; h0l + pshufb m30, m9, m20 + vpdpwssd m31, m12, m30 ; i0l + pshufb m7, m21 + vpdpwssd m29, m13, m7 ; h1l + pshufb m9, m21 + vpdpwssd m31, m13, m9 ; i1l + pshufb m7, m6, m20 + vpdpwssd m29, m14, m7 ; h2l + pshufb m9, m8, m20 + vpdpwssd m31, m14, m9 ; i2l + pshufb m6, m21 + vpdpwssd m29, m15, m6 ; h3l + pshufb m8, m21 + vpdpwssd m31, m15, m8 ; i3l + mova m30, m10 + vpdpwssd m30, m12, m7 ; h0h + movu m7, [srcq+ssq*1+16] + lea srcq, [srcq+ssq*2] + vpermt2b m29, m22, m31 ; 78l + mova m31, m10 + vpdpwssd m31, m12, m9 ; i0h + movu m9, [srcq+ssq*0+16] + vpdpwssd m30, m13, m6 ; h1h + pshufb m6, m7, m20 + vpdpwssd m31, m13, m8 ; i1h + pshufb m8, m9, m20 + vpdpwssd m30, m14, m6 ; h2h + pmaddwd m6, m16, m0 ; A0l + pshufb m7, m21 + vpdpwssd m31, m14, m8 ; i2h + pmaddwd m8, m16, m23 ; A0h + pshufb m9, m21 + vpdpwssd m30, m15, m7 ; h3h + pmaddwd m7, m16, m1 ; B0l + vpdpwssd m31, m15, m9 ; i3h + pmaddwd m9, m16, m24 ; B0h + mova m0, m2 + vpdpwssd m6, m17, m2 ; A1l + mova m23, m25 + vpdpwssd m8, m17, m25 ; A1h + mova m1, m3 + vpdpwssd m7, m17, m3 ; B1l + mova m24, m26 + vpdpwssd m9, m17, m26 ; B1h + vpermt2b m30, m22, m31 ; 78h + vpdpwssd m6, m18, m4 ; A2l + mova m2, m4 + vpdpwssd m8, m18, m27 ; A2h + mova m25, m27 + vpdpwssd m7, m18, m5 ; B2l + mova m3, m5 + vpdpwssd m9, m18, m28 ; B2h + mova m26, m28 + vpshrdd m4, m5, m29, 16 ; 67l + vpdpwssd m6, m19, m4 ; A3l + vpshrdd m27, m28, m30, 16 ; 67h + vpdpwssd m8, m19, m27 ; A3h + mova m5, m29 + vpdpwssd m7, m19, m29 ; B3l + mova m28, m30 + vpdpwssd m9, m19, m30 ; B3h + REPX {psrad x, 10}, m6, m8, m7, m9 + packusdw m6, m8 + packusdw m7, m9 + pminsw m6, m11 + pminsw m7, m11 + mova [dstq+dsq*0], m6 + mova [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + add r7, 64 + add r8, 64 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 + jg .hv_w32_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +MC_8TAP_FN prep, sharp, SHARP, SHARP +MC_8TAP_FN prep, sharp_smooth, SHARP, SMOOTH +MC_8TAP_FN prep, smooth_sharp, SMOOTH, SHARP +MC_8TAP_FN prep, smooth, SMOOTH, SMOOTH +MC_8TAP_FN prep, sharp_regular, SHARP, REGULAR +MC_8TAP_FN prep, regular_sharp, REGULAR, SHARP +MC_8TAP_FN prep, smooth_regular, SMOOTH, REGULAR +MC_8TAP_FN prep, regular_smooth, REGULAR, SMOOTH +MC_8TAP_FN prep, regular, REGULAR, REGULAR + +cglobal prep_8tap_16bpc, 3, 8, 16, tmp, src, stride, w, h, mx, my, stride3 +%define base r7-prep_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx512icl] + mov wd, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov r5d, r7m ; bitdepth_max + vpbroadcastd m5, [pw_8192] + movzx wd, word [r7+wq*2+table_offset(prep,)] + shr r5d, 11 + vpbroadcastd m4, [r7-prep_avx512icl+prep_mul+r5*4] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h_w4: + movzx mxd, mxb + sub srcq, 2 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mov r5d, r7m + vbroadcasti32x4 m4, [spel_h_shufA] + vbroadcasti32x4 m5, [spel_h_shufB] + shr r5d, 11 + mova ym9, [prep_endA] + psllw xmm0, [base+prep_hv_shift+r5*8] + mova [tmpq], xmm0 + vpbroadcastd m6, [tmpq+4] + vpbroadcastd m7, [tmpq+8] +.h_w4_loop: + movu xm2, [srcq+strideq*0] + vinserti32x4 ym2, [srcq+strideq*1], 1 + vinserti32x4 m2, [srcq+strideq*2], 2 + vinserti32x4 m2, [srcq+r6 ], 3 + lea srcq, [srcq+strideq*4] + mova m0, m10 + pshufb m1, m2, m4 + vpdpwssd m0, m6, m1 + pshufb m2, m5 + vpdpwssd m0, m7, m2 + vpermb m0, m9, m0 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m10, [prep_8tap_rnd] + lea r6, [strideq*3] + cmp wd, 4 + je .h_w4 + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + mov r5d, r7m + sub srcq, 6 + shr r5d, 11 + psllw xmm0, [base+prep_hv_shift+r5*8] + mova [tmpq], xmm0 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + cmp wd, 16 + je .h_w16 + jg .h_w32 +.h_w8: + mova m6, [spel_h_shufA] + movu m7, [spel_h_shufB] + movu m8, [spel_h_shufC] + mova m9, [spel_h_shufD] + mova m11, [prep_endB] +.h_w8_loop: + movu ym4, [srcq+strideq*0] + vinserti32x8 m4, [srcq+strideq*1], 1 + movu ym5, [srcq+strideq*2] + vinserti32x8 m5, [srcq+r6 ], 1 + lea srcq, [srcq+strideq*4] + mova m0, m10 + mova m1, m10 + vpermb m2, m6, m4 + vpermb m3, m6, m5 + vpdpwssd m0, m12, m2 + vpdpwssd m1, m12, m3 + vpermb m2, m7, m4 + vpermb m3, m7, m5 + vpdpwssd m0, m13, m2 + vpdpwssd m1, m13, m3 + vpermb m2, m8, m4 + vpermb m3, m8, m5 + vpdpwssd m0, m14, m2 + vpdpwssd m1, m14, m3 + vpermb m2, m9, m4 + vpermb m3, m9, m5 + vpdpwssd m0, m15, m2 + vpdpwssd m1, m15, m3 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + vbroadcasti32x4 m6, [spel_h_shufA] + vbroadcasti32x4 m7, [spel_h_shufB] + mova m11, [prep_endC] +.h_w16_loop: + movu ym2, [srcq+strideq*0+ 0] + vinserti32x8 m2, [srcq+strideq*1+ 0], 1 + movu ym3, [srcq+strideq*0+16] + vinserti32x8 m3, [srcq+strideq*1+16], 1 + lea srcq, [srcq+strideq*2] + mova m0, m10 + mova m1, m10 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m14, m4 ; b2 + pshufb m4, m2, m7 + vpdpwssd m0, m13, m4 ; a1 + pshufb m4, m3, m7 + vpdpwssd m1, m15, m4 ; b3 + shufpd m2, m3, 0x55 + pshufb m4, m2, m6 + vpdpwssd m0, m14, m4 ; a2 + vpdpwssd m1, m12, m4 ; b0 + pshufb m2, m7 + vpdpwssd m0, m15, m2 ; a3 + vpdpwssd m1, m13, m2 ; b1 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + vbroadcasti32x4 m6, [spel_h_shufA] + lea srcq, [srcq+wq*2] + vbroadcasti32x4 m7, [spel_h_shufB] + neg wq + mova m11, [prep_endC] +.h_w32_loop0: + mov r6, wq +.h_w32_loop: + movu m2, [srcq+r6*2+ 0] + movu m3, [srcq+r6*2+ 8] + mova m0, m10 + mova m1, m10 + pshufb m4, m2, m6 + vpdpwssd m0, m12, m4 ; a0 + pshufb m4, m3, m6 + vpdpwssd m1, m12, m4 ; b0 + vpdpwssd m0, m14, m4 ; a2 + movu m4, [srcq+r6*2+16] + pshufb m3, m7 + vpdpwssd m1, m13, m3 ; b1 + vpdpwssd m0, m15, m3 ; a3 + pshufb m3, m4, m6 + vpdpwssd m1, m14, m3 ; b2 + pshufb m2, m7 + vpdpwssd m0, m13, m2 ; a1 + pshufb m4, m7 + vpdpwssd m1, m15, m4 ; b3 + vpermt2b m0, m11, m1 + mova [tmpq], m0 + add tmpq, 64 + add r6, 32 + jl .h_w32_loop + add srcq, strideq + dec hd + jg .h_w32_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + mov r5d, r7m + vpbroadcastd m10, [prep_8tap_rnd] + pmovsxbw xmm0, [base+subpel_filters+myq*8] + tzcnt r6d, wd + shr r5d, 11 + movzx r6d, word [r7+r6*2+table_offset(prep, _8tap_v)] + psllw xmm0, [base+prep_hv_shift+r5*8] + add r7, r6 + lea r6, [strideq*3] + sub srcq, r6 + mova [tmpq], xmm0 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + jmp r7 +.v_w4: + movq xmm1, [srcq+strideq*0] + vpbroadcastq ymm0, [srcq+strideq*1] + vpbroadcastq ymm2, [srcq+strideq*2] + add srcq, r6 + vpbroadcastq ymm4, [srcq+strideq*0] + vpbroadcastq ymm3, [srcq+strideq*1] + vpbroadcastq ymm5, [srcq+strideq*2] + mova xm11, [prep_endA] + add srcq, r6 + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklwd ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+strideq*0] + vpblendd ymm2, ymm4, 0x30 + vpblendd ymm4, ymm3, 0x30 + punpcklwd ymm2, ymm4 ; 23 34 + vpblendd ymm3, ymm5, 0x30 + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 45 56 +.v_w4_loop: + vpbroadcastq ymm5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + mova ymm4, ym10 + vpdpwssd ymm4, ym12, ymm1 ; a0 b0 + mova ymm1, ymm2 + vpdpwssd ymm4, ym13, ymm2 ; a1 b1 + mova ymm2, ymm3 + vpdpwssd ymm4, ym14, ymm3 ; a2 b2 + vpblendd ymm3, ymm0, ymm5, 0x30 + vpbroadcastq ymm0, [srcq+strideq*0] + vpblendd ymm5, ymm0, 0x30 + punpcklwd ymm3, ymm5 ; 67 78 + vpdpwssd ymm4, ym15, ymm3 ; a3 b3 + vpermb ymm4, ym11, ymm4 + mova [tmpq], xmm4 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + vbroadcasti32x4 m2, [srcq+strideq*2] + vinserti32x4 m1, m2, [srcq+strideq*0], 0 + vinserti32x4 m1, [srcq+strideq*1], 1 ; 0 1 2 + add srcq, r6 + vinserti32x4 ym2, [srcq+strideq*0], 1 + vinserti32x4 m2, [srcq+strideq*1], 2 ; 2 3 4 + mova m6, [spel_v_shuf8] + movu xm0, [srcq+strideq*1] + vinserti32x4 ym0, [srcq+strideq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+strideq*0], 2 ; 4 5 6 + mova ym11, [prep_endB] + vpermb m1, m6, m1 ; 01 12 + vpermb m2, m6, m2 ; 23 34 + vpermb m3, m6, m0 ; 45 56 +.v_w8_loop: + vinserti32x4 m0, [srcq+strideq*1], 3 + lea srcq, [srcq+strideq*2] + movu xm5, [srcq+strideq*0] + mova m4, m10 + vpdpwssd m4, m12, m1 ; a0 b0 + mova m1, m2 + vshufi32x4 m0, m5, q1032 ; 6 7 8 + vpdpwssd m4, m13, m2 ; a1 b1 + mova m2, m3 + vpdpwssd m4, m14, m3 ; a2 b2 + vpermb m3, m6, m0 ; 67 78 + vpdpwssd m4, m15, m3 ; a3 b3 + vpermb m4, m11, m4 + mova [tmpq], ym4 + add tmpq, 32 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti32x8 m1, [srcq+strideq*1] + vinserti32x8 m0, m1, [srcq+strideq*0], 0 + vinserti32x8 m1, [srcq+strideq*2], 1 + mova m8, [spel_v_shuf16] + add srcq, r6 + movu ym3, [srcq+strideq*0] + vinserti32x8 m3, [srcq+strideq*1], 1 + movu ym5, [srcq+strideq*2] + add srcq, r6 + vinserti32x8 m5, [srcq+strideq*0], 1 + mova m11, [prep_endA] + vpermb m0, m8, m0 ; 01 + vpermb m1, m8, m1 ; 12 + vpermb m3, m8, m3 ; 34 + vpermb m5, m8, m5 ; 56 + vpshrdd m2, m1, m3, 16 ; 23 + vpshrdd m4, m3, m5, 16 ; 45 +.v_w16_loop: + mova m6, m10 + mova m7, m10 + vpdpwssd m6, m12, m0 ; a0 + mova m0, m2 + vpdpwssd m7, m12, m1 ; b0 + mova m1, m3 + vpdpwssd m6, m13, m2 ; a1 + mova m2, m4 + vpdpwssd m7, m13, m3 ; b1 + mova m3, m5 + vpdpwssd m6, m14, m4 ; a2 + mova m4, m5 + vpdpwssd m7, m14, m5 ; b2 + movu ym5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m5, [srcq+strideq*0], 1 + vpermb m5, m8, m5 ; 78 + vpshrdd m4, m5, 16 ; 67 + vpdpwssd m6, m15, m4 ; a3 + vpdpwssd m7, m15, m5 ; b3 + vpermt2b m6, m11, m7 + mova [tmpq], m6 + add tmpq, 64 + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +.v_w64: +.v_w128: +%if WIN64 + PUSH r8 + movaps [rsp+stack_offset+8], xmm6 +%endif + lea r5, [hq+wq*8-256] + mov r7, srcq + mov r8, tmpq +.v_w32_loop0: + movu m16, [srcq+strideq*0] + movu m17, [srcq+strideq*1] + movu m18, [srcq+strideq*2] + add srcq, r6 + movu m19, [srcq+strideq*0] + movu m20, [srcq+strideq*1] + movu m21, [srcq+strideq*2] + add srcq, r6 + movu m22, [srcq+strideq*0] + mova m11, [prep_endC] + punpcklwd m0, m16, m17 ; 01l + punpckhwd m16, m17 ; 01h + punpcklwd m1, m17, m18 ; 12l + punpckhwd m17, m18 ; 12h + punpcklwd m2, m18, m19 ; 23l + punpckhwd m18, m19 ; 23h + punpcklwd m3, m19, m20 ; 34l + punpckhwd m19, m20 ; 34h + punpcklwd m4, m20, m21 ; 45l + punpckhwd m20, m21 ; 45h + punpcklwd m5, m21, m22 ; 56l + punpckhwd m21, m22 ; 56h +.v_w32_loop: + mova m6, m10 + vpdpwssd m6, m12, m0 ; a0l + mova m8, m10 + vpdpwssd m8, m12, m16 ; a0h + mova m7, m10 + vpdpwssd m7, m12, m1 ; b0l + mova m9, m10 + vpdpwssd m9, m12, m17 ; b0h + mova m0, m2 + vpdpwssd m6, m13, m2 ; a1l + mova m16, m18 + vpdpwssd m8, m13, m18 ; a1h + mova m1, m3 + vpdpwssd m7, m13, m3 ; b1l + mova m17, m19 + vpdpwssd m9, m13, m19 ; b1h + mova m2, m4 + vpdpwssd m6, m14, m4 ; a2l + mova m18, m20 + vpdpwssd m8, m14, m20 ; a2h + mova m3, m5 + vpdpwssd m7, m14, m5 ; b2l + mova m19, m21 + vpdpwssd m9, m14, m21 ; b2h + movu m21, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklwd m4, m22, m21 ; 67l + punpckhwd m20, m22, m21 ; 67h + movu m22, [srcq+strideq*0] + vpdpwssd m6, m15, m4 ; a3l + vpdpwssd m8, m15, m20 ; a3h + punpcklwd m5, m21, m22 ; 78l + punpckhwd m21, m22 ; 78h + vpdpwssd m7, m15, m5 ; b3l + vpdpwssd m9, m15, m21 ; b3h + vpermt2b m6, m11, m8 + vpermt2b m7, m11, m9 + mova [tmpq+wq*0], m6 + mova [tmpq+wq*2], m7 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w32_loop + add r7, 64 + add r8, 64 + movzx hd, r5b + mov srcq, r7 + mov tmpq, r8 + sub r5d, 1<<8 + jg .v_w32_loop0 +%if WIN64 + movaps xmm6, [rsp+stack_offset+8] + POP r8 +%endif + vzeroupper + RET +.hv: + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + mov r5d, r7m + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 2 + shr r5d, 11 + sub srcq, r6 + psllw xmm0, [base+prep_hv_shift+r5*8] + psllw xmm1, 2 + vpbroadcastd m10, [prep_8tap_rnd] + vpbroadcastd ym11, [pd_128] + mova xm21, [prep_endA] + mova [tmpq+ 0], xmm0 + mova [tmpq+16], xmm1 + vpbroadcastd m8, [tmpq+ 4] + vpbroadcastd m9, [tmpq+ 8] + vpbroadcastd ym12, xmm1 + vpbroadcastd ym13, [tmpq+20] + vpbroadcastd ym14, [tmpq+24] + vpbroadcastd ym15, [tmpq+28] + movu xm4, [srcq+strideq*0] + vinserti32x4 ym4, [srcq+strideq*1], 1 + vinserti32x4 m4, [srcq+strideq*2], 2 + add srcq, r6 + vinserti32x4 m4, [srcq+strideq*0], 3 ; 0 1 2 3 + movu xm0, [srcq+strideq*1] + vinserti32x4 ym0, [srcq+strideq*2], 1 + add srcq, r6 + vinserti32x4 m0, [srcq+strideq*0], 2 ; 4 5 6 + vbroadcasti32x4 m19, [spel_h_shufA] + vbroadcasti32x4 m20, [spel_h_shufB] + mova ym6, [spel_shuf4a] + mova ym7, [spel_shuf4b] + mova m2, m10 + mova m3, m10 + pshufb m1, m4, m19 + vpdpwssd m2, m8, m1 + pshufb m1, m0, m19 + vpdpwssd m3, m8, m1 + pshufb m4, m20 + vpdpwssd m2, m9, m4 + pshufb m0, m20 + vpdpwssd m3, m9, m0 + vpermb m1, m6, m2 ; 01 12 + vshufi32x4 m2, m3, q1032 + vpermb m3, m6, m3 ; 45 56 + vpermb m2, m6, m2 ; 23 34 +.hv_w4_loop: + movu xm18, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti128 ym18, [srcq+strideq*0], 1 + mova ym16, ym11 + mova ym4, ym10 + pshufb ym17, ym18, ym19 + vpdpwssd ym16, ym12, ym1 ; a0 b0 + vpdpwssd ym4, ym8, ym17 + pshufb ym18, ym20 + mova ym1, ym2 + vpdpwssd ym16, ym13, ym2 ; a1 b1 + vpdpwssd ym4, ym9, ym18 ; 7 8 + mova ym2, ym3 + vpdpwssd ym16, ym14, ym3 ; a2 b2 + vpermt2b ym3, ym7, ym4 ; 67 78 + vpdpwssd ym16, ym15, ym3 ; a3 b3 + vpermb ym16, ym21, ym16 + mova [tmpq], xm16 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + shr mxd, 16 + pmovsxbw xmm0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + mov r5d, r7m + pmovsxbw xmm1, [base+subpel_filters+myq*8] + lea r6, [strideq*3] + sub srcq, 6 + shr r5d, 11 + sub srcq, r6 + vpbroadcastd m10, [prep_8tap_rnd] + vpbroadcastd m11, [pd_128] + psllw xmm0, [base+prep_hv_shift+r5*8] + psllw xmm1, 2 + mova [tmpq+ 0], xmm0 + mova [tmpq+16], xmm1 + vpbroadcastd m12, xmm0 + vpbroadcastd m13, [tmpq+ 4] + vpbroadcastd m14, [tmpq+ 8] + vpbroadcastd m15, [tmpq+12] + vpbroadcastd m16, xmm1 + vpbroadcastd m17, [tmpq+20] + vpbroadcastd m18, [tmpq+24] + vpbroadcastd m19, [tmpq+28] + cmp wd, 16 + je .hv_w16 + jg .hv_w32 + WIN64_SPILL_XMM 23 + mova m5, [spel_h_shufA] + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 ; 0 1 + movu ym9, [srcq+strideq*2] + add srcq, r6 + vinserti32x8 m9, [srcq+strideq*0], 1 ; 2 3 + movu ym20, [srcq+strideq*1] + vinserti32x8 m20, [srcq+strideq*2], 1 ; 4 5 + add srcq, r6 + movu ym21, [srcq+strideq*0] ; 6 + movu m6, [spel_h_shufB] + movu m7, [spel_h_shufC] + mova ym22, [prep_endB] + vpermb m8, m5, m0 + mova m1, m10 + vpdpwssd m1, m12, m8 ; a0 b0 + vpermb m8, m5, m9 + mova m2, m10 + vpdpwssd m2, m12, m8 ; c0 d0 + vpermb m8, m5, m20 + mova m3, m10 + vpdpwssd m3, m12, m8 ; e0 f0 + vpermb m8, m5, m21 + mova m4, m10 + vpdpwssd m4, m12, m8 ; g0 + vpermb m8, m6, m0 + vpdpwssd m1, m13, m8 ; a1 b1 + vpermb m8, m6, m9 + vpdpwssd m2, m13, m8 ; c1 d1 + vpermb m8, m6, m20 + vpdpwssd m3, m13, m8 ; e1 f1 + vpermb m8, m6, m21 + vpdpwssd m4, m13, m8 ; g1 + vpermb m8, m7, m0 + vpdpwssd m1, m14, m8 ; a2 b2 + vpermb m8, m7, m9 + vpdpwssd m2, m14, m8 ; c2 d2 + vpermb m8, m7, m20 + vpdpwssd m3, m14, m8 ; e2 f2 + vpermb m8, m7, m21 + vpdpwssd m4, m14, m8 ; g2 + mova m8, [spel_h_shufD] + vpermb m0, m8, m0 + vpdpwssd m1, m15, m0 ; a3 b3 + mova m0, [spel_shuf8a] + vpermb m9, m8, m9 + vpdpwssd m2, m15, m9 ; c3 d3 + mova m9, [spel_shuf8b] + vpermb m20, m8, m20 + vpdpwssd m3, m15, m20 ; e3 f3 + vpermb m21, m8, m21 + vpdpwssd m4, m15, m21 ; g3 + vpermt2b m1, m0, m2 ; 01 12 + vpermt2b m2, m0, m3 ; 23 34 + vpermt2b m3, m0, m4 ; 45 56 +.hv_w8_loop: + movu ym0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m0, [srcq+strideq*0], 1 + mova m4, m10 + mova m20, m11 + vpermb m21, m5, m0 + vpdpwssd m4, m12, m21 ; h0 i0 + vpermb m21, m6, m0 + vpdpwssd m20, m16, m1 ; A0 B0 + vpdpwssd m4, m13, m21 ; h1 i1 + vpermb m21, m7, m0 + mova m1, m2 + vpdpwssd m20, m17, m2 ; A1 B1 + vpdpwssd m4, m14, m21 ; h2 i2 + vpermb m21, m8, m0 + mova m2, m3 + vpdpwssd m20, m18, m3 ; A2 B2 + vpdpwssd m4, m15, m21 ; h3 i3 + vpermt2b m3, m9, m4 ; 67 78 + vpdpwssd m20, m19, m3 ; A3 B3 + vpermb m20, m22, m20 + mova [tmpq], ym20 + add tmpq, 32 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 27 + vbroadcasti32x8 m5, [srcq+strideq*0+ 8] + vinserti32x8 m4, m5, [srcq+strideq*0+ 0], 0 + vinserti32x8 m5, [srcq+strideq*0+16], 1 ; 0 + movu ym6, [srcq+strideq*1+ 0] + movu ym7, [srcq+strideq*1+16] + vinserti32x8 m6, [srcq+strideq*2+ 0], 1 + vinserti32x8 m7, [srcq+strideq*2+16], 1 ; 1 2 + add srcq, r6 + movu ym22, [srcq+strideq*0+ 0] + movu ym23, [srcq+strideq*0+16] + vinserti32x8 m22, [srcq+strideq*1+ 0], 1 + vinserti32x8 m23, [srcq+strideq*1+16], 1 ; 3 4 + movu ym24, [srcq+strideq*2+ 0] + movu ym25, [srcq+strideq*2+16] + add srcq, r6 + vinserti32x8 m24, [srcq+strideq*0+ 0], 1 + vinserti32x8 m25, [srcq+strideq*0+16], 1 ; 5 6 + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m9, [spel_shuf16] + mova m26, [prep_endB] + pshufb m0, m4, m20 + mova m1, m10 + vpdpwssd m1, m12, m0 ; a0 + pshufb m0, m6, m20 + mova m2, m10 + vpdpwssd m2, m12, m0 ; b0 + pshufb m0, m7, m20 + mova m3, m10 + vpdpwssd m3, m14, m0 ; c2 + pshufb m0, m4, m21 + vpdpwssd m1, m13, m0 ; a1 + pshufb m0, m6, m21 + vpdpwssd m2, m13, m0 ; b1 + pshufb m0, m7, m21 + vpdpwssd m3, m15, m0 ; c3 + pshufb m0, m5, m20 + vpdpwssd m1, m14, m0 ; a2 + shufpd m6, m7, 0x55 + pshufb m7, m6, m20 + vpdpwssd m2, m14, m7 ; b2 + vpdpwssd m3, m12, m7 ; c0 + pshufb m5, m21 + vpdpwssd m1, m15, m5 ; a3 + pshufb m6, m21 + vpdpwssd m2, m15, m6 ; b3 + vpdpwssd m3, m13, m6 ; c1 + pshufb m0, m22, m20 + mova m4, m10 + vpdpwssd m4, m12, m0 ; d0 + pshufb m0, m23, m20 + mova m5, m10 + vpdpwssd m5, m14, m0 ; e2 + pshufb m0, m24, m20 + mova m6, m10 + vpdpwssd m6, m12, m0 ; f0 + pshufb m0, m25, m20 + mova m7, m10 + vpdpwssd m7, m14, m0 ; g2 + pshufb m0, m22, m21 + vpdpwssd m4, m13, m0 ; d1 + pshufb m0, m23, m21 + vpdpwssd m5, m15, m0 ; e3 + pshufb m0, m24, m21 + vpdpwssd m6, m13, m0 ; f1 + pshufb m0, m25, m21 + vpdpwssd m7, m15, m0 ; g3 + shufpd m22, m23, 0x55 + pshufb m23, m22, m20 + vpdpwssd m4, m14, m23 ; d2 + vpdpwssd m5, m12, m23 ; e0 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m6, m14, m25 ; f2 + vpdpwssd m7, m12, m25 ; g0 + pshufb m22, m21 + vpdpwssd m4, m15, m22 ; d3 + vpdpwssd m5, m13, m22 ; e1 + pshufb m24, m21 + vpdpwssd m6, m15, m24 ; f3 + vpdpwssd m7, m13, m24 ; g1 + pslldq m1, 1 + vpermt2b m2, m9, m3 ; 12 + vpermt2b m4, m9, m5 ; 34 + vpermt2b m6, m9, m7 ; 56 + vpshrdd m1, m2, 16 ; 01 + vpshrdd m3, m2, m4, 16 ; 23 + vpshrdd m5, m4, m6, 16 ; 45 +.hv_w16_loop: + movu ym24, [srcq+strideq*1+ 0] + movu ym25, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*2] + vinserti32x8 m24, [srcq+strideq*0+ 0], 1 + vinserti32x8 m25, [srcq+strideq*0+16], 1 + mova m7, m10 + mova m8, m10 + pshufb m0, m24, m20 + vpdpwssd m7, m12, m0 ; h0 + mova m22, m11 + pshufb m0, m25, m20 + vpdpwssd m8, m14, m0 ; i2 + mova m23, m11 + vpdpwssd m22, m16, m1 ; A0 + mova m1, m3 + vpdpwssd m23, m16, m2 ; B0 + mova m2, m4 + pshufb m0, m24, m21 + vpdpwssd m7, m13, m0 ; h1 + pshufb m0, m25, m21 + vpdpwssd m8, m15, m0 ; i3 + vpdpwssd m22, m17, m3 ; A1 + mova m3, m5 + vpdpwssd m23, m17, m4 ; B1 + mova m4, m6 + shufpd m24, m25, 0x55 + pshufb m25, m24, m20 + vpdpwssd m7, m14, m25 ; h2 + vpdpwssd m8, m12, m25 ; i0 + vpdpwssd m22, m18, m5 ; A2 + vpdpwssd m23, m18, m6 ; B2 + pshufb m24, m21 + vpdpwssd m7, m15, m24 ; h3 + vpdpwssd m8, m13, m24 ; i1 + vpermt2b m7, m9, m8 ; 78 + vpshrdd m5, m6, m7, 16 ; 67 + vpdpwssd m22, m19, m5 ; A3 + vpdpwssd m23, m19, m7 ; B3 + mova m6, m7 + vpermt2b m22, m26, m23 + mova [tmpq], m22 + add tmpq, 64 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + PUSH r8 + %assign regs_used regs_used + 1 + WIN64_SPILL_XMM 32 +%endif + vbroadcasti32x4 m20, [spel_h_shufA] + vbroadcasti32x4 m21, [spel_h_shufB] + mova m22, [spel_shuf32] + lea r5d, [hq+wq*8-256] + mov r7, srcq + mov r8, tmpq +.hv_w32_loop0: + movu m6, [srcq+strideq*0+ 0] + movu m7, [srcq+strideq*0+ 8] + movu m8, [srcq+strideq*0+16] + mova m0, m10 + mova m23, m10 + pshufb m9, m6, m20 + vpdpwssd m0, m12, m9 ; a0l + pshufb m9, m7, m20 + vpdpwssd m23, m12, m9 ; a0h + vpdpwssd m0, m14, m9 ; a2l + pshufb m7, m21 + vpdpwssd m23, m13, m7 ; a1h + vpdpwssd m0, m15, m7 ; a3l + pshufb m7, m8, m20 + vpdpwssd m23, m14, m7 ; a2h + pshufb m6, m21 + vpdpwssd m0, m13, m6 ; a1l + pshufb m8, m21 + vpdpwssd m23, m15, m8 ; a3h + PUT_8TAP_HV_W32 1, 24, strideq, 1, 2 ; 12 + PUT_8TAP_HV_W32 3, 26, strideq, 0, 1 ; 34 + PUT_8TAP_HV_W32 5, 28, strideq, 2, 0 ; 56 + vpshrdd m2, m1, m3, 16 ; 23l + vpshrdd m25, m24, m26, 16 ; 23h + vpshrdd m4, m3, m5, 16 ; 45l + vpshrdd m27, m26, m28, 16 ; 45h +.hv_w32_loop: + movu m7, [srcq+strideq*1+ 0] + movu m9, [srcq+strideq*2+ 0] + movu m6, [srcq+strideq*1+ 8] + movu m8, [srcq+strideq*2+ 8] + mova m29, m10 + mova m31, m10 + pshufb m30, m7, m20 + vpdpwssd m29, m12, m30 ; h0l + pshufb m30, m9, m20 + vpdpwssd m31, m12, m30 ; i0l + pshufb m7, m21 + vpdpwssd m29, m13, m7 ; h1l + pshufb m9, m21 + vpdpwssd m31, m13, m9 ; i1l + pshufb m7, m6, m20 + vpdpwssd m29, m14, m7 ; h2l + pshufb m9, m8, m20 + vpdpwssd m31, m14, m9 ; i2l + pshufb m6, m21 + vpdpwssd m29, m15, m6 ; h3l + pshufb m8, m21 + vpdpwssd m31, m15, m8 ; i3l + mova m30, m10 + vpdpwssd m30, m12, m7 ; h0h + movu m7, [srcq+strideq*1+16] + lea srcq, [srcq+strideq*2] + vpermt2b m29, m22, m31 ; 78l + mova m31, m10 + vpdpwssd m31, m12, m9 ; i0h + movu m9, [srcq+strideq*0+16] + vpdpwssd m30, m13, m6 ; h1h + pshufb m6, m7, m20 + vpdpwssd m31, m13, m8 ; i1h + pshufb m8, m9, m20 + vpdpwssd m30, m14, m6 ; h2h + mova m6, m11 + vpdpwssd m6, m16, m0 ; A0l + pshufb m7, m21 + vpdpwssd m31, m14, m8 ; i2h + mova m8, m11 + vpdpwssd m8, m16, m23 ; A0h + pshufb m9, m21 + vpdpwssd m30, m15, m7 ; h3h + mova m7, m11 + vpdpwssd m7, m16, m1 ; B0l + vpdpwssd m31, m15, m9 ; i3h + mova m9, m11 + vpdpwssd m9, m16, m24 ; B0h + mova m0, m2 + vpdpwssd m6, m17, m2 ; A1l + mova m23, m25 + vpdpwssd m8, m17, m25 ; A1h + mova m1, m3 + vpdpwssd m7, m17, m3 ; B1l + mova m24, m26 + vpdpwssd m9, m17, m26 ; B1h + vpermt2b m30, m22, m31 ; 78h + mova m31, [prep_endC] + vpdpwssd m6, m18, m4 ; A2l + mova m2, m4 + vpdpwssd m8, m18, m27 ; A2h + mova m25, m27 + vpdpwssd m7, m18, m5 ; B2l + mova m3, m5 + vpdpwssd m9, m18, m28 ; B2h + mova m26, m28 + vpshrdd m4, m5, m29, 16 ; 67l + vpdpwssd m6, m19, m4 ; A3l + vpshrdd m27, m28, m30, 16 ; 67h + vpdpwssd m8, m19, m27 ; A3h + mova m5, m29 + vpdpwssd m7, m19, m29 ; B3l + mova m28, m30 + vpdpwssd m9, m19, m30 ; B3h + vpermt2b m6, m31, m8 + vpermt2b m7, m31, m9 + mova [tmpq+wq*0], m6 + mova [tmpq+wq*2], m7 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w32_loop + add r7, 64 + add r8, 64 + movzx hd, r5b + mov srcq, r7 + mov tmpq, r8 + sub r5d, 1<<8 + jg .hv_w32_loop0 + RET + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal warp_affine_8x8t_16bpc, 4, 7, 22, tmp, ts +%define base r6-pd_0to7 + mov t0d, r7m + lea r6, [pd_0to7] + shr t0d, 11 + vpbroadcastd m8, [base+warp_8x8t_rnd_v] + vpbroadcastd m1, [base+warp_8x8_rnd_h+t0*4] + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main + psrad m14, m16, 15 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + psrad m16, 15 + packssdw m14, m16 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + psrad m15, m16, 15 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).main2 + add tsq, tsq + psrad m16, 15 + packssdw m15, m16 + jmp mangle(private_prefix %+ _warp_affine_8x8_16bpc_avx512icl).end + +cglobal warp_affine_8x8_16bpc, 4, 7, 22, dst, ds, src, ss, abcd + mov t0d, r7m ; pixel_max + lea r6, [pd_0to7] + shr t0d, 11 + vpbroadcastd m1, [base+warp_8x8_rnd_h+t0*4] + vpbroadcastd m8, [base+warp_8x8_rnd_v+t0*4] + call .main + psrad m14, m16, 13 + call .main2 + psrad m16, 13 + packusdw m14, m16 + call .main2 + psrad m15, m16, 13 + call .main2 + vpbroadcastd m0, [base+bidir_shift+t0*4] + vpsrlvw m14, m0 + psrad m16, 13 + packusdw m15, m16 + vpsrlvw m15, m0 +.end: + mova m0, [base+warp8x8_end] + vpermb m16, m0, m14 + lea r2, [dsq*3] + mova [dstq+dsq*0], xm16 + vextracti128 [dstq+dsq*1], ym16, 1 + vextracti32x4 [dstq+dsq*2], m16, 2 + vextracti32x4 [dstq+r2 ], m16, 3 + vpermb m16, m0, m15 + lea dstq, [dstq+dsq*4] + mova [dstq+dsq*0], xm16 + vextracti128 [dstq+dsq*1], ym16, 1 + vextracti32x4 [dstq+dsq*2], m16, 2 + vextracti32x4 [dstq+r2 ], m16, 3 + RET +.main: + vpbroadcastd ym3, [base+pd_512] +%if WIN64 + mov abcdq, r5mp + vpaddd ym18, ym3, r6m {1to8} ; mx +%else + add r5d, 512 + vpbroadcastd ym18, r5d +%endif + vpaddd ym20, ym3, r7m {1to8} ; my + mova ym16, [base+pd_0to7] + vpbroadcastd ym19, [abcdq+4*0] ; alpha + vpbroadcastd ym21, [abcdq+4*1] ; gamma + lea r4, [ssq*3+6] + vpdpwssd ym18, ym19, ym16 ; tmx + vpdpwssd ym20, ym21, ym16 ; tmy + sub srcq, r4 + mova m10, [base+warp8x8_permA] + lea r4, [mc_warp_filter+64*8] + vbroadcasti32x4 m12, [base+warp8x8_permC] + kxnorb k1, k1, k1 + vbroadcasti32x4 m13, [base+warp8x8_permD] + movu ym5, [srcq+0] + vinserti32x8 m5, [srcq+8], 1 + psrad ym17, ym18, 10 + mova m11, [base+warp8x8_permB] + kmovb k2, k1 + vpgatherdq m3{k1}, [r4+ym17*8] ; filter_x0 + psrad ym19, 16 ; beta + psrad ym21, 16 ; delta + paddd ym18, ym19 + vpermb m4, m10, m5 + vpbroadcastq m9, [base+warp_shift_h+t0*8] + pshufd m3, m3, q3120 + paddd m7, m1, m1 + pshufb m2, m3, m12 + vpdpwssd m1, m4, m2 + vpermb m5, m11, m5 + vshufi32x4 m4, m5, q1021 + pshufb m3, m13 + vpdpwssd m1, m4, m3 + call .h + psllq m2, m1, 32 + paddd m1, m2 + vpmultishiftqb m1, m9, m1 + vpshrdq m1, m0, 48 ; 01 12 + call .h + vpshrdq m2, m1, m0, 48 ; 23 34 + call .h + vpshrdq m3, m2, m0, 48 ; 45 56 +.main2: + call .h + psrad ym6, ym20, 10 + kmovb k1, k2 + paddd ym17, ym20, ym21 ; my += delta + vpgatherdq m20{k2}, [r4+ym6*8] ; filter_y0 + psrad ym16, ym17, 10 + kmovb k2, k1 + vpgatherdq m6{k1}, [r4+ym16*8] ; filter_y1 + shufps m5, m20, m6, q2020 + mova m16, m8 + pshufb m4, m5, m12 + vpdpwssd m16, m1, m4 ; a0 b0 + pshufb m5, m13 + mova m1, m2 + vpdpwssd m16, m2, m5 ; a1 b1 + shufps m6, m20, m6, q3131 + paddd ym20, ym17, ym21 + pshufb m4, m6, m12 + mova m2, m3 + vpdpwssd m16, m3, m4 ; a2 b2 + vpshrdq m3, m0, 48 ; 67 78 + pshufb m6, m13 + vpdpwssd m16, m3, m6 ; a3 b3 + ret +ALIGN function_align +.h: + movu ym16, [srcq+ssq*1] + psrad ym6, ym18, 10 + lea srcq, [srcq+ssq*2] + vinserti32x8 m5, m16, [srcq+ssq*0], 1 + kmovb k1, k2 + paddd ym17, ym18, ym19 ; mx += beta + vpgatherdq m18{k2}, [r4+ym6*8] ; filter_x1 + psrad ym16, ym17, 10 + kmovb k2, k1 + vpgatherdq m6{k1}, [r4+ym16*8] ; filter_x2 + vpermb m4, m10, m5 + shufps m16, m18, m6, q2020 + shufps m6, m18, m6, q3131 + mova m0, m7 + pshufb m18, m16, m12 + vpdpwssd m0, m4, m18 ; a0 b0 + vpermb m5, m11, m5 + pshufb m18, m6, m13 + vpdpwssd m0, m5, m18 ; a3 b3 + paddd ym18, ym17, ym19 + vshufi32x4 m17, m4, m5, q1021 + pshufb m16, m13 + vpdpwssd m0, m17, m16 ; a1 b1 + vshufi32x4 m4, m5, q2132 + pshufb m6, m12 + vpdpwssd m0, m4, m6 ; a2 b2 + vpmultishiftqb m0, m9, m0 ; a a b b + ret + +%macro BIDIR_FN 0 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq ], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm0, ym1, 1 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + vextracti32x4 xm0, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq ], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +%endmacro + +%if WIN64 +DECLARE_REG_TMP 5 +%else +DECLARE_REG_TMP 7 +%endif + +cglobal avg_16bpc, 4, 7, 4, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx512icl_table + lea r6, [avg_avx512icl_table] + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + vpbroadcastd m2, [base+avg_round+t0*4] + vpbroadcastd m3, [base+avg_shift+t0*4] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+64*0] + paddsw m0, [tmp2q+64*0] + mova m1, [tmp1q+64*1] + paddsw m1, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + pmaxsw m0, m2 + pmaxsw m1, m2 + psubsw m0, m2 + psubsw m1, m2 + vpsrlvw m0, m3 + vpsrlvw m1, m3 + ret + +cglobal w_avg_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg_avx512icl_table + lea r6, [w_avg_avx512icl_table] + tzcnt wd, wm + mov t0d, r7m ; pixel_max + shr t0d, 11 + movsxd wq, [r6+wq*4] + vpbroadcastd m5, [base+w_avg_round+t0*4] + vpbroadcastd m7, [base+bidir_shift+t0*4] + add wq, r6 + mov r6d, r6m ; weight + lea t0d, [r6-16] + shl r6d, 16 + sub r6d, t0d ; 16-weight, weight + movifnidn hd, hm + vpbroadcastd m6, r6d + BIDIR_FN +ALIGN function_align +.main: + mova m3, [tmp1q+64*0] + mova m1, [tmp2q+64*0] + mova m0, [tmp1q+64*1] + mova m4, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + punpcklwd m2, m1, m3 + punpckhwd m1, m3 + punpcklwd m3, m4, m0 + punpckhwd m4, m0 + mova m0, m5 + vpdpwssd m0, m6, m2 + mova m2, m5 + vpdpwssd m2, m6, m1 + mova m1, m5 + vpdpwssd m1, m6, m3 + mova m3, m5 + vpdpwssd m3, m6, m4 + REPX {psrad x, 2}, m0, m2, m1, m3 + packusdw m0, m2 + packusdw m1, m3 + vpsrlvw m0, m7 + vpsrlvw m1, m7 + ret + +cglobal mask_16bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx512icl_table + lea r7, [mask_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_64] + vpbroadcastd m9, [base+mask_round+r6*4] + vpbroadcastd m10, [base+bidir_shift+r6*4] + mov maskq, maskmp + add wq, r7 + BIDIR_FN +ALIGN function_align +.main: + pmovzxbw m1, [maskq+32*0] + mova m4, [tmp1q+64*0] + mova m2, [tmp2q+64*0] + pmovzxbw m6, [maskq+32*1] + mova m5, [tmp1q+64*1] + mova m3, [tmp2q+64*1] + add maskq, 32*2 + add tmp1q, 64*2 + add tmp2q, 64*2 + punpcklwd m7, m4, m2 + punpckhwd m4, m2 + psubw m0, m8, m1 + punpcklwd m2, m1, m0 ; m, 64-m + punpckhwd m1, m0 + mova m0, m9 + vpdpwssd m0, m7, m2 + mova m2, m9 + vpdpwssd m2, m4, m1 ; tmp1 * m + tmp2 * (64-m) + punpcklwd m7, m5, m3 + punpckhwd m5, m3 + psubw m1, m8, m6 + punpcklwd m3, m6, m1 + punpckhwd m6, m1 + mova m1, m9 + vpdpwssd m1, m7, m3 + mova m3, m9 + vpdpwssd m3, m5, m6 + REPX {psrad x, 4}, m0, m2, m1, m3 + packusdw m0, m2 + packusdw m1, m3 + vpsrlvw m0, m10 + vpsrlvw m1, m10 + ret + +cglobal w_mask_420_16bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx512icl_table + lea r7, [w_mask_420_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m10, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m11, [base+pw_64] + vpbroadcastd m12, [base+mask_round+r6*4] + vpbroadcastd m13, [base+bidir_shift+r6*4] + mov r6d, r7m ; sign + vpbroadcastd m14, [base+w_mask_round+r6*4] + mova ym15, [w_mask_end42x] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + mova m4, [w_mask_shuf4] + vpermt2b m2, m4, m3 + mova m3, m14 + vpdpbusd m3, m2, [pb_64] {1to16} + vpermb m3, m15, m3 + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + mova [maskq], xm3 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8: + mova m8, [w_mask_shuf8] + vpbroadcastd m9, [pb_64] + jmp .w8_start +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8_start: + vpermt2b m2, m8, m3 + mova m3, m14 + vpdpbusd m3, m2, m9 + vpermb m3, m15, m3 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + mova [maskq], xm3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16: + mova m8, [w_mask_shuf16] + vpbroadcastd m9, [pb_64] + jmp .w16_start +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16_start: + vpermt2b m2, m8, m3 + mova m3, m14 + vpdpbusd m3, m2, m9 + vpermb m3, m15, m3 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + mova [maskq], xm3 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w32: + paddw m2, m3 + mova m8, m14 + vpdpwssd m8, m11, m2 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + call .main + paddw m2, m3 + mova m3, m14 + vpdpwssd m3, m11, m2 + vpermt2b m8, m15, m3 + mova [dstq+strideq*2], m0 + mova [dstq+stride3q ], m1 + mova [maskq], ym8 + sub hd, 4 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w64: + mova m8, m2 + mova m9, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + call .main + paddw m8, m2 + paddw m9, m3 + mova m2, m14 + vpdpwssd m2, m11, m8 + mova m3, m14 + vpdpwssd m3, m11, m9 + vpermt2b m2, m15, m3 + mova [dstq+strideq*1+64*0], m0 + mova [dstq+strideq*1+64*1], m1 + mova [maskq], ym2 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 64 +.w128: + mova m16, m2 + mova m8, m3 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*0+64*1], m1 + call .main + mova m17, m2 + mova m9, m3 + mova [dstq+strideq*0+64*2], m0 + mova [dstq+strideq*0+64*3], m1 + call .main + paddw m2, m16 + paddw m3, m8 + mova m16, m14 + vpdpwssd m16, m11, m2 + mova m8, m14 + vpdpwssd m8, m11, m3 + mova [dstq+strideq*1+64*0], m0 + mova [dstq+strideq*1+64*1], m1 + call .main + paddw m2, m17 + paddw m3, m9 + mova m17, m14 + vpdpwssd m17, m11, m2 + mova m9, m14 + vpdpwssd m9, m11, m3 + vpermt2b m16, m15, m8 + vpermt2b m17, m15, m9 + mova [dstq+strideq*1+64*2], m0 + mova [dstq+strideq*1+64*3], m1 + mova [maskq+32*0], ym16 + mova [maskq+32*1], ym17 + sub hd, 2 + jg .w128_loop + vzeroupper + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m10, m6 + psrlw m6, 10 ; 64-m + psubw m2, m11, m6 ; m + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m12 + vpdpwssd m0, m5, m1 + mova m1, m12 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m10, m5 + psrlw m5, 10 + psubw m3, m11, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m12 + vpdpwssd m1, m6, m4 + mova m4, m12 + vpdpwssd m4, m7, m5 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpsrlvw m0, m13 + vpsrlvw m1, m13 + ret + +cglobal w_mask_422_16bpc, 4, 8, 15, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx512icl_table + lea r7, [w_mask_422_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m9, [base+pw_64] + vpbroadcastd m10, [base+mask_round+r6*4] + vpbroadcastd m11, [base+bidir_shift+r6*4] + mov r6d, r7m ; sign + vpbroadcastd m12, [base+w_mask_round+r6*4] + mova ym13, [w_mask_end42x] + mov maskq, maskmp + add wq, r7 + paddw m14, m9, m9 ; pw_128 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m8, m6 + psrlw m6, 10 + psubw m2, m9, m6 + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m10 + vpdpwssd m0, m5, m1 + mova m1, m10 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m8, m5 + psrlw m5, 10 + psubw m3, m9, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m10 + vpdpwssd m1, m6, m4 + mova m4, m10 + vpdpwssd m4, m7, m5 + mova m5, m12 + vpdpwssd m5, m14, m2 + mova m2, m12 + vpdpwssd m2, m14, m3 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpermt2b m5, m13, m2 + vpsrlvw m0, m11 + vpsrlvw m1, m11 + mova [maskq], ym5 + add maskq, 32 + ret + +cglobal w_mask_444_16bpc, 4, 8, 13, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx512icl_table + lea r7, [w_mask_444_avx512icl_table] + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movifnidn hd, hm + shr r6d, 11 + movsxd wq, [r7+wq*4] + vpbroadcastd m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + vpbroadcastd m9, [base+pw_64] + vpbroadcastd m10, [base+mask_round+r6*4] + mova m11, [w_mask_end444] + vpbroadcastd m12, [base+bidir_shift+r6*4] + mov maskq, maskmp + add wq, r7 + call .main + lea stride3q, [strideq*3] + jmp wq +.w4: + movq [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm0 + vextracti32x4 xm2, ym0, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + cmp hd, 8 + jl .w4_end + vextracti32x4 xm2, m0, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm0, m0, 3 + movq [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm0 + je .w4_end + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm1 + movhps [dstq+strideq*1], xm1 + vextracti32x4 xm2, ym1, 1 + movq [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm2 + vextracti32x4 xm2, m1, 2 + lea dstq, [dstq+strideq*4] + movq [dstq+strideq*0], xm2 + movhps [dstq+strideq*1], xm2 + vextracti32x4 xm1, m1, 3 + movq [dstq+strideq*2], xm1 + movhps [dstq+stride3q ], xm1 +.w4_end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*4] +.w8: + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], ym0, 1 + vextracti32x4 [dstq+strideq*2], m0, 2 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 8 + jl .w8_end + lea dstq, [dstq+strideq*4] + mova [dstq+strideq*0], xm1 + vextracti32x4 [dstq+strideq*1], ym1, 1 + vextracti32x4 [dstq+strideq*2], m1, 2 + vextracti32x4 [dstq+stride3q ], m1, 3 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*4] +.w16: + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + mova [dstq+strideq*2], ym1 + vextracti32x8 [dstq+stride3q ], m1, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] +.w32: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + call .main + mova [dstq+64*2], m0 + mova [dstq+64*3], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m1, [tmp1q+64*0] + mova m3, [tmp2q+64*0] + mova m4, [tmp1q+64*1] + mova m7, [tmp2q+64*1] + add tmp1q, 64*2 + add tmp2q, 64*2 + psubsw m6, m1, m3 + punpcklwd m5, m3, m1 + pabsw m6, m6 + punpckhwd m3, m1 + psubusw m6, m8, m6 + psrlw m6, 10 + psubw m2, m9, m6 + punpcklwd m1, m6, m2 + punpckhwd m6, m2 + mova m0, m10 + vpdpwssd m0, m5, m1 + mova m1, m10 + vpdpwssd m1, m3, m6 + psubsw m5, m4, m7 + punpcklwd m6, m7, m4 + pabsw m5, m5 + punpckhwd m7, m4 + psubusw m5, m8, m5 + psrlw m5, 10 + psubw m3, m9, m5 + punpcklwd m4, m5, m3 + psrad m0, 4 + punpckhwd m5, m3 + psrad m1, 4 + packusdw m0, m1 + mova m1, m10 + vpdpwssd m1, m6, m4 + mova m4, m10 + vpdpwssd m4, m7, m5 + vpermt2b m2, m11, m3 + psrad m1, 4 + psrad m4, 4 + packusdw m1, m4 + vpsrlvw m0, m12 + vpsrlvw m1, m12 + mova [maskq], m2 + add maskq, 64 + ret + +cglobal blend_16bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx512icl_table + lea r6, [blend_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + vpbroadcastd m6, [base+pw_m512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + pmovzxbw ym19, [maskq] + movq xm16, [dstq+dsq*0] + movhps xm16, [dstq+dsq*1] + vpbroadcastq ym17, [dstq+dsq*2] + vpbroadcastq ym18, [dstq+r6 ] + pmullw ym19, ym6 + vpblendd ym16, ym17, 0x30 + vpblendd ym16, ym18, 0xc0 + psubw ym17, ym16, [tmpq] + add maskq, 16 + add tmpq, 32 + pmulhrsw ym17, ym19 + paddw ym16, ym17 + vextracti128 xm17, ym16, 1 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + movq [dstq+dsq*2], xm17 + movhps [dstq+r6 ], xm17 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + vzeroupper + RET +.w8: + pmovzxbw m2, [maskq] + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + vinserti32x4 m0, [dstq+dsq*2], 2 + vinserti32x4 m0, [dstq+r6 ], 3 + pmullw m2, m6 + psubw m1, m0, [tmpq] + add maskq, 32 + add tmpq, 64 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + vextracti32x4 [dstq+dsq*2], m0, 2 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +.w16: + pmovzxbw m4, [maskq+32*0] + pmovzxbw m5, [maskq+32*1] + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + mova ym1, [dstq+dsq*2] + vinserti32x8 m1, [dstq+r6 ], 1 + pmullw m4, m6 + pmullw m5, m6 + psubw m2, m0, [tmpq+64*0] + psubw m3, m1, [tmpq+64*1] + add maskq, 32*2 + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + mova [dstq+dsq*2], ym1 + vextracti32x8 [dstq+r6 ], m1, 1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w16 + RET +.w32: + pmovzxbw m4, [maskq+32*0] + pmovzxbw m5, [maskq+32*1] + mova m0, [dstq+dsq*0] + mova m1, [dstq+dsq*1] + pmullw m4, m6 + pmullw m5, m6 + psubw m2, m0, [tmpq+ 64*0] + psubw m3, m1, [tmpq+ 64*1] + add maskq, 32*2 + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32 + RET + +cglobal blend_v_16bpc, 3, 6, 5, dst, ds, tmp, w, h + lea r5, [blend_v_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + vpbroadcastd xmm2, [obmc_masks_avx2+2*2] +.w2_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movq xmm1, [tmpq] + add tmpq, 4*2 + psubw xmm1, xmm0, xmm1 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + vpbroadcastq xmm2, [obmc_masks_avx2+4*2] +.w4_loop: + movq xmm0, [dstq+dsq*0] + movhps xmm0, [dstq+dsq*1] + psubw xmm1, xmm0, [tmpq] + add tmpq, 8*2 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + vbroadcasti32x4 ym2, [obmc_masks_avx2+8*2] +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + psubw ym1, ym0, [tmpq] + add tmpq, 16*2 + pmulhrsw ym1, ym2 + paddw ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + vbroadcasti32x8 m2, [obmc_masks_avx2+16*2] +.w16_loop: + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + psubw m1, m0, [tmpq] + add tmpq, 32*2 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + mova m4, [obmc_masks_avx2+32*2] +.w32_loop: + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 64*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop + RET + +cglobal blend_h_16bpc, 3, 7, 9, dst, ds, tmp, w, h, mask +%define base r6-$$ + lea r6, [$$] + tzcnt wd, wm + mov hd, hm + movsxd wq, [base+blend_h_avx512icl_table+wq*4] + lea maskq, [base+obmc_masks_avx2+hq*2] + lea hd, [hq*3] + lea wq, [base+blend_h_avx512icl_table+wq] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movq xmm1, [tmpq] + add tmpq, 4*2 + punpcklwd xmm2, xmm2 + psubw xmm1, xmm0, xmm1 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova xmm3, [blend_shuf] +.w4_loop: + movq xmm0, [dstq+dsq*0] + movhps xmm0, [dstq+dsq*1] + movd xmm2, [maskq+hq*2] + psubw xmm1, xmm0, [tmpq] + add tmpq, 8*2 + pshufb xmm2, xmm3 + pmulhrsw xmm1, xmm2 + paddw xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + vbroadcasti32x4 ym3, [blend_shuf] + shufpd ym3, ym3, 0x0c +.w8_loop: + mova xm0, [dstq+dsq*0] + vinserti32x4 ym0, [dstq+dsq*1], 1 + vpbroadcastd ym2, [maskq+hq*2] + psubw ym1, ym0, [tmpq] + add tmpq, 16*2 + pshufb ym2, ym3 + pmulhrsw ym1, ym2 + paddw ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +.w16: + vbroadcasti32x4 m3, [blend_shuf] + shufpd m3, m3, 0xf0 +.w16_loop: + mova ym0, [dstq+dsq*0] + vinserti32x8 m0, [dstq+dsq*1], 1 + vpbroadcastd m2, [maskq+hq*2] + psubw m1, m0, [tmpq] + add tmpq, 32*2 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +.w32: + vpbroadcastw m4, [maskq+hq*2] + vpbroadcastw m5, [maskq+hq*2+2] + mova m0, [dstq+dsq*0] + psubw m2, m0, [tmpq+ 64*0] + mova m1, [dstq+dsq*1] + psubw m3, m1, [tmpq+ 64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w32 + RET +.w64: + vpbroadcastw m4, [maskq+hq*2] + mova m0, [dstq+64*0] + psubw m2, m0, [tmpq+64*0] + mova m1, [dstq+64*1] + psubw m3, m1, [tmpq+64*1] + add tmpq, 64*2 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m8, [maskq+hq*2] + mova m0, [dstq+64*0] + psubw m4, m0, [tmpq+64*0] + mova m1, [dstq+64*1] + psubw m5, m1, [tmpq+64*1] + mova m2, [dstq+64*2] + psubw m6, m2, [tmpq+64*2] + mova m3, [dstq+64*3] + psubw m7, m3, [tmpq+64*3] + add tmpq, 64*4 + REPX {pmulhrsw x, m8}, m4, m5, m6, m7 + paddw m0, m4 + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + mova [dstq+64*2], m2 + mova [dstq+64*3], m3 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal resize_16bpc, 6, 12, 32, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + mov r6, ~0 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + kmovq k6, r6 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x, _, _, pxmax + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pd_16384] + vpbroadcastd m7, [base+pd_63] + mova m24, [base+resize_permA] + mova m25, [base+resize_permB] + mova m26, [base+resize_permC] + mova m27, [base+resize_permD] + vbroadcasti32x4 m28, [base+resize_shufA] + vbroadcasti32x4 m29, [base+resize_shufB] + mova m30, [base+resize_permE] + vpbroadcastw ym31, pxmaxm + vpdpwssd m8, m5, [base+rescale_mul] ; mx+dx*[0-15] + pslld m5, 4 ; dx*16 + pslld m6, 14 + pxor m2, m2 +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + vptestmd k5, m1, m1 + pand m9, m7 ; filter offset (masked) + ktestw k5, k5 + jz .load + vpbroadcastq m14, [base+pd_0_4] + vpermq m10, m0, q1100 + vpermq m11, m0, q3322 + vpermq m20, m1, q1100 + vpermq m21, m1, q3322 + punpckldq m10, m10 + punpckldq m11, m11 + punpckldq m20, m20 + punpckldq m21, m21 + paddd m10, m14 + paddd m11, m14 + paddd m20, m14 + paddd m21, m14 + vextracti32x8 ym12, m10, 1 + vextracti32x8 ym13, m11, 1 + vextracti32x8 ym22, m20, 1 + vextracti32x8 ym23, m21, 1 + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdq m16{k1}, [srcq+ym10*2] ; 0 1 2 3 + vpgatherdq m17{k2}, [srcq+ym11*2] ; 4 5 6 7 + vpgatherdq m18{k3}, [srcq+ym12*2] ; 8 9 A B + vpgatherdq m19{k4}, [srcq+ym13*2] ; C D E F + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdq m0{k1}, [base+resize_shuf+8+ym20*2] + vpgatherdq m1{k2}, [base+resize_shuf+8+ym21*2] + vpgatherdq m14{k3}, [base+resize_shuf+8+ym22*2] + vpgatherdq m15{k4}, [base+resize_shuf+8+ym23*2] + pshufb m16, m0 + pshufb m17, m1 + pshufb m18, m14 + pshufb m19, m15 + mova m20, m24 + mova m22, m24 + mova m21, m25 + mova m23, m25 + vpermi2d m20, m16, m17 ; 0-3a 0-3b 4-7a 4-7b + vpermi2d m21, m16, m17 ; 0-3c 0-3d 4-7c 4-7d + vpermi2d m22, m18, m19 ; 8-Ba 8-Bb C-Fa C-Fb + vpermi2d m23, m18, m19 ; 8-Bc 8-Bd C-Fc C-Fd + mova m15, m26 + mova m17, m26 + mova m16, m27 + mova m18, m27 + vpermi2q m15, m20, m22 ; 0-3a 4-7a 8-Ba C-Fa + vpermi2q m16, m20, m22 ; 0-3b 4-7b 8-Bb C-Fb + vpermi2q m17, m21, m23 ; 0-3c 4-7c 8-Bc C-Fc + vpermi2q m18, m21, m23 ; 0-3d 4-7d 8-Bd C-Fd + kmovq k1, k6 + kmovq k2, k6 + vpgatherdd m11{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m13{k2}, [base+resize_filter+m9*8+4] + pshufb m10, m11, m28 + pshufb m11, m11, m29 + pshufb m12, m13, m28 + pshufb m13, m13, m29 + jmp .filter +.load: + kmovq k1, k6 + kmovq k2, k6 + kmovq k3, k6 + kmovq k4, k6 + vpgatherdd m11{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m13{k2}, [base+resize_filter+m9*8+4] + pshufb m10, m11, m28 + pshufb m11, m11, m29 + pshufb m12, m13, m28 + pshufb m13, m13, m29 + vpgatherdd m15{k3}, [srcq+m0*2+ 0] + vpgatherdd m16{k4}, [srcq+m0*2+ 4] + kmovq k1, k6 + kmovq k2, k6 + vpgatherdd m17{k1}, [srcq+m0*2+ 8] + vpgatherdd m18{k2}, [srcq+m0*2+12] +.filter: + mova m14, m2 + vpdpwssd m14, m15, m10 + vpdpwssd m14, m16, m11 + vpdpwssd m14, m17, m12 + vpdpwssd m14, m18, m13 + psubd m14, m3, m14 + psrad m14, 15 + packusdw m14, m14 + vpermq m14, m30, m14 + pminsw ym14, ym31 + mova [dstq+xq*2], ym14 + paddd m4, m5 + add xd, 16 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc16_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc16_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8731 @@ +; Copyright © 2021, VideoLAN and dav1d authors +; Copyright © 2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA + +; dav1d_obmc_masks[] << 9 +obmc_masks: dw 0, 0, 9728, 0, 12800, 7168, 2560, 0 + dw 14336, 11264, 8192, 5632, 3584, 1536, 0, 0 + dw 15360, 13824, 12288, 10752, 9216, 7680, 6144, 5120 + dw 4096, 3072, 2048, 1536, 0, 0, 0, 0 + dw 15872, 14848, 14336, 13312, 12288, 11776, 10752, 10240 + dw 9728, 8704, 8192, 7168, 6656, 6144, 5632, 4608 + dw 4096, 3584, 3072, 2560, 2048, 2048, 1536, 1024 + +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +spel_h_shufA: db 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 +spel_h_shufB: db 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 10, 11, 12, 13 +spel_h_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 9 +spel_s_shuf2: db 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 +spel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +unpckw: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +rescale_mul: dd 0, 1, 2, 3 +resize_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7 + db 8, 9, 10, 11, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15 +bdct_lb_q: times 8 db 0 + times 8 db 4 + times 8 db 8 + times 8 db 12 + +pw_2: times 8 dw 2 +pw_16: times 4 dw 16 +prep_mul: times 4 dw 16 + times 8 dw 4 +pw_64: times 8 dw 64 +pw_256: times 8 dw 256 +pw_2048: times 4 dw 2048 +bidir_mul: times 4 dw 2048 +pw_8192: times 8 dw 8192 +pw_27615: times 8 dw 27615 +pw_32766: times 8 dw 32766 +pw_m512: times 8 dw -512 +pd_63: times 4 dd 63 +pd_64: times 4 dd 64 +pd_512: times 4 dd 512 +pd_m524256: times 4 dd -524256 ; -8192 << 6 + 32 +pd_0x3ff: times 4 dd 0x3ff +pd_0x4000: times 4 dd 0x4000 +pq_0x400000: times 2 dq 0x400000 +pq_0x40000000: times 2 dq 0x40000000 +pd_65538: times 2 dd 65538 + +put_bilin_h_rnd: times 4 dw 8 + times 4 dw 10 +s_8tap_h_rnd: times 2 dd 2 + times 2 dd 8 +put_s_8tap_v_rnd: times 2 dd 512 + times 2 dd 128 +s_8tap_h_sh: dd 2, 4 +put_s_8tap_v_sh: dd 10, 8 +bidir_rnd: times 4 dw -16400 + times 4 dw -16388 +put_8tap_h_rnd: dd 34, 34, 40, 40 +prep_8tap_1d_rnd: times 2 dd 8 - (8192 << 4) +prep_8tap_2d_rnd: times 4 dd 32 - (8192 << 5) + +warp8x8_shift: dd 11, 13 +warp8x8_rnd1: dd 1024, 1024, 4096, 4096 +warp8x8_rnd2: times 4 dw 4096 + times 4 dw 16384 +warp8x8t_rnd: times 2 dd 16384 - (8192 << 15) + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_16bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, ssse3, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, ssse3, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, ssse3, 2, 4, 8, 16, 32, 64, 128 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_ssse3 mangle(private_prefix %+ _put_bilin_16bpc_ssse3.put) +%xdefine prep_ssse3 mangle(private_prefix %+ _prep_bilin_16bpc_ssse3.prep) + +BASE_JMP_TABLE put, ssse3, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, ssse3, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_16bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, ssse3, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, ssse3, 4, 8, 16, 32, 64, 128 + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +cextern mc_warp_filter +cextern resize_filter + +SECTION .text + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +INIT_XMM ssse3 +cglobal put_bilin_16bpc, 4, 7, 0, dst, ds, src, ss, w, h, mxy +%define base t0-put_ssse3 + mov mxyd, r6m ; mx + LEA t0, put_ssse3 + movifnidn wd, wm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + tzcnt wd, wd + movzx wd, word [base+put_ssse3_table+wq*2] + add wq, t0 + movifnidn hd, hm + jmp wq +.put_w2: + mov r4d, [srcq+ssq*0] + mov r6d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4d + mov [dstq+dsq*1], r6d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq [dstq+dsq*0], m0 + movq [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0+16*0] + movu m1, [srcq+ssq*0+16*1] + movu m2, [srcq+ssq*1+16*0] + movu m3, [srcq+ssq*1+16*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+16*0], m0 + mova [dstq+dsq*0+16*1], m1 + mova [dstq+dsq*1+16*0], m2 + mova [dstq+dsq*1+16*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, ssq + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + add dstq, dsq + dec hd + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, ssq + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + add srcq, 16*8 + add dstq, 16*8 +.put_w128_loop: + movu m0, [srcq-16*8] + movu m1, [srcq-16*7] + movu m2, [srcq-16*6] + movu m3, [srcq-16*5] + mova [dstq-16*8], m0 + mova [dstq-16*7], m1 + mova [dstq-16*6], m2 + mova [dstq-16*5], m3 + movu m0, [srcq-16*4] + movu m1, [srcq-16*3] + movu m2, [srcq-16*2] + movu m3, [srcq-16*1] + mova [dstq-16*4], m0 + mova [dstq-16*3], m1 + mova [dstq-16*2], m2 + mova [dstq-16*1], m3 + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, ssq + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add dstq, dsq + dec hd + jg .put_w128_loop + RET +.h: + movd m5, mxyd + mov mxyd, r7m ; my + mova m4, [base+pw_16] + pshufb m5, [base+pw_256] + psubw m4, m5 + test mxyd, mxyd + jnz .hv + ; 12-bit is rounded twice so we can't use the same pmulhrsw approach as .v + mov r6d, r8m ; bitdepth_max + shr r6d, 11 + movddup m3, [base+put_bilin_h_rnd+r6*8] + movifnidn hd, hm + sub wd, 8 + jg .h_w16 + je .h_w8 + cmp wd, -4 + je .h_w4 +.h_w2: + movq m1, [srcq+ssq*0] + movhps m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmullw m0, m4, m1 + psrlq m1, 16 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + movd [dstq+dsq*0], m0 + punpckhqdq m0, m0 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + movq m0, [srcq+ssq*0] + movhps m0, [srcq+ssq*1] + movq m1, [srcq+ssq*0+2] + movhps m1, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 4 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + lea srcq, [srcq+wq*2] + lea dstq, [dstq+wq*2] + neg wq +.h_w16_loop0: + mov r6, wq +.h_w16_loop: + movu m0, [srcq+r6*2+ 0] + movu m1, [srcq+r6*2+ 2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + movu m1, [srcq+r6*2+16] + movu m2, [srcq+r6*2+18] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m0, 4 + psrlw m1, 4 + mova [dstq+r6*2+16*0], m0 + mova [dstq+r6*2+16*1], m1 + add r6, 16 + jl .h_w16_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w16_loop0 + RET +.v: + shl mxyd, 11 + movd m5, mxyd + pshufb m5, [base+pw_256] + movifnidn hd, hm + cmp wd, 4 + jg .v_w8 + je .v_w4 +.v_w2: + movd m0, [srcq+ssq*0] +.v_w2_loop: + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq m2, m0, m1 + movd m0, [srcq+ssq*0] + punpcklqdq m1, m0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + movd [dstq+dsq*0], m1 + punpckhqdq m1, m1 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movq m0, [srcq+ssq*0] +.v_w4_loop: + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklqdq m2, m0, m1 + movq m0, [srcq+ssq*0] + punpcklqdq m1, m0 + psubw m1, m2 + pmulhrsw m1, m5 + paddw m1, m2 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: +%if ARCH_X86_64 +%if WIN64 + push r7 +%endif + shl wd, 5 + mov r7, srcq + lea r6d, [wq+hq-256] + mov r4, dstq +%else + mov r6, srcq +%endif +.v_w8_loop0: + movu m0, [srcq+ssq*0] +.v_w8_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + psubw m1, m3, m0 + pmulhrsw m1, m5 + paddw m1, m0 + movu m0, [srcq+ssq*0] + psubw m2, m0, m3 + pmulhrsw m2, m5 + paddw m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop +%if ARCH_X86_64 + add r7, 16 + add r4, 16 + movzx hd, r6b + mov srcq, r7 + mov dstq, r4 + sub r6d, 1<<8 +%else + mov dstq, dstmp + add r6, 16 + mov hd, hm + add dstq, 16 + mov srcq, r6 + mov dstmp, dstq + sub wd, 8 +%endif + jg .v_w8_loop0 +%if WIN64 + pop r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 8 + shl mxyd, 11 + mova m3, [base+pw_2] + movd m6, mxyd + mova m7, [base+pw_8192] + pshufb m6, [base+pw_256] + test dword r8m, 0x800 + jnz .hv_12bpc + psllw m4, 2 + psllw m5, 2 + mova m7, [base+pw_2048] +.hv_12bpc: + movifnidn hd, hm + cmp wd, 4 + jg .hv_w8 + je .hv_w4 +.hv_w2: + movddup m0, [srcq+ssq*0] + pshufhw m1, m0, q0321 + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w2_loop: + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps m2, [srcq+ssq*0] + pmullw m1, m4, m2 + psrlq m2, 16 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 _ 2 _ + shufpd m2, m0, m1, 0x01 ; 0 _ 1 _ + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + movd [dstq+dsq*0], m1 + punpckhqdq m1, m1 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + movddup m0, [srcq+ssq*0] + movddup m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w4_loop: + movq m1, [srcq+ssq*1] + movq m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + movhps m1, [srcq+ssq*0] + movhps m2, [srcq+ssq*0+2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 ; 1 2 + shufpd m2, m0, m1, 0x01 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: +%if ARCH_X86_64 +%if WIN64 + push r7 +%endif + shl wd, 5 + lea r6d, [wq+hq-256] + mov r4, srcq + mov r7, dstq +%else + mov r6, srcq +%endif +.hv_w8_loop0: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m1, m5 + paddw m0, m3 + paddw m0, m1 + psrlw m0, 2 +.hv_w8_loop: + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*1+2] + lea srcq, [srcq+ssq*2] + pmullw m1, m4 + pmullw m2, m5 + paddw m1, m3 + paddw m1, m2 + psrlw m1, 2 + psubw m2, m1, m0 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m0 + pmulhrsw m2, m7 + mova [dstq+dsq*0], m2 + movu m0, [srcq+ssq*0] + movu m2, [srcq+ssq*0+2] + pmullw m0, m4 + pmullw m2, m5 + paddw m0, m3 + paddw m0, m2 + psrlw m0, 2 + psubw m2, m0, m1 + paddw m2, m2 + pmulhw m2, m6 + paddw m2, m1 + pmulhrsw m2, m7 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop +%if ARCH_X86_64 + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 +%else + mov dstq, dstmp + add r6, 16 + mov hd, hm + add dstq, 16 + mov srcq, r6 + mov dstmp, dstq + sub wd, 8 +%endif + jg .hv_w8_loop0 +%if WIN64 + pop r7 +%endif + RET + +cglobal prep_bilin_16bpc, 4, 7, 0, tmp, src, stride, w, h, mxy, stride3 +%define base r6-prep_ssse3 + movifnidn mxyd, r5m ; mx + LEA r6, prep_ssse3 + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + tzcnt wd, wd + movzx wd, word [base+prep_ssse3_table+wq*2] + mov r5d, r7m ; bitdepth_max + mova m5, [base+pw_8192] + add wq, r6 + shr r5d, 11 + movddup m4, [base+prep_mul+r5*8] + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*2] + movhps m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmullw m0, m4 + pmullw m1, m4 + psubw m0, m5 + psubw m1, m5 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu m0, [srcq+strideq*0+16*0] + movu m1, [srcq+strideq*0+16*1] + movu m2, [srcq+strideq*1+16*0] + movu m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .prep_w16 + RET +.prep_w32: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + dec hd + jg .prep_w32 + RET +.prep_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*4], m0 + mova [tmpq+16*5], m1 + mova [tmpq+16*6], m2 + mova [tmpq+16*7], m3 + add tmpq, 16*8 + dec hd + jg .prep_w64 + RET +.prep_w128: + movu m0, [srcq+16* 0] + movu m1, [srcq+16* 1] + movu m2, [srcq+16* 2] + movu m3, [srcq+16* 3] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + movu m0, [srcq+16* 4] + movu m1, [srcq+16* 5] + movu m2, [srcq+16* 6] + movu m3, [srcq+16* 7] + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq+16*4], m0 + mova [tmpq+16*5], m1 + mova [tmpq+16*6], m2 + mova [tmpq+16*7], m3 + movu m0, [srcq+16* 8] + movu m1, [srcq+16* 9] + movu m2, [srcq+16*10] + movu m3, [srcq+16*11] + add tmpq, 16*16 + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq-16*8], m0 + mova [tmpq-16*7], m1 + mova [tmpq-16*6], m2 + mova [tmpq-16*5], m3 + movu m0, [srcq+16*12] + movu m1, [srcq+16*13] + movu m2, [srcq+16*14] + movu m3, [srcq+16*15] + add srcq, strideq + REPX {pmullw x, m4}, m0, m1, m2, m3 + REPX {psubw x, m5}, m0, m1, m2, m3 + mova [tmpq-16*4], m0 + mova [tmpq-16*3], m1 + mova [tmpq-16*2], m2 + mova [tmpq-16*1], m3 + dec hd + jg .prep_w128 + RET +.h: + movd m4, mxyd + mov mxyd, r6m ; my + mova m3, [base+pw_16] + pshufb m4, [base+pw_256] + mova m5, [base+pw_32766] + psubw m3, m4 + test dword r7m, 0x800 + jnz .h_12bpc + psllw m3, 2 + psllw m4, 2 +.h_12bpc: + test mxyd, mxyd + jnz .hv + sub wd, 8 + je .h_w8 + jg .h_w16 +.h_w4: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*0+2] + movhps m1, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 16 + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + lea srcq, [srcq+wq*2] + neg wq +.h_w16_loop0: + mov r6, wq +.h_w16_loop: + movu m0, [srcq+r6*2+ 0] + movu m1, [srcq+r6*2+ 2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + movu m1, [srcq+r6*2+16] + movu m2, [srcq+r6*2+18] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + add r6, 16 + jl .h_w16_loop + add srcq, strideq + dec hd + jg .h_w16_loop0 + RET +.v: + movd m4, mxyd + mova m3, [base+pw_16] + pshufb m4, [base+pw_256] + mova m5, [base+pw_32766] + psubw m3, m4 + test dword r7m, 0x800 + jnz .v_12bpc + psllw m3, 2 + psllw m4, 2 +.v_12bpc: + cmp wd, 8 + je .v_w8 + jg .v_w16 +.v_w4: + movq m0, [srcq+strideq*0] +.v_w4_loop: + movq m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklqdq m1, m0, m2 ; 0 1 + movq m0, [srcq+strideq*0] + punpcklqdq m2, m0 ; 1 2 + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq], m1 + add tmpq, 16 + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movu m0, [srcq+strideq*0] +.v_w8_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4, m2 + psubw m0, m5 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m3 + mova [tmpq+16*0], m1 + pmullw m1, m4, m0 + psubw m2, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+16*1], m1 + add tmpq, 16*2 + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: +%if WIN64 + push r7 +%endif + mov r5, srcq +%if ARCH_X86_64 + lea r6d, [wq*4-32] + mov wd, wd + lea r6d, [hq+r6*8] + mov r7, tmpq +%else + mov r6d, wd +%endif +.v_w16_loop0: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + pmullw m0, m3 + pmullw m1, m4, m2 + psubw m0, m5 + paddw m1, m0 + movu m0, [srcq+strideq*0] + psraw m1, 2 + pmullw m2, m3 + mova [tmpq+wq*0], m1 + pmullw m1, m4, m0 + psubw m2, m5 + paddw m1, m2 + psraw m1, 2 + mova [tmpq+wq*2], m1 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w16_loop +%if ARCH_X86_64 + add r5, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 +%else + mov tmpq, tmpmp + add r5, 16 + mov hd, hm + add tmpq, 16 + mov srcq, r5 + mov tmpmp, tmpq + sub r6d, 8 +%endif + jg .v_w16_loop0 +%if WIN64 + pop r7 +%endif + RET +.hv: + WIN64_SPILL_XMM 7 + shl mxyd, 11 + movd m6, mxyd + pshufb m6, [base+pw_256] + cmp wd, 8 + je .hv_w8 + jg .hv_w16 +.hv_w4: + movddup m0, [srcq+strideq*0] + movddup m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w4_loop: + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + movhps m1, [srcq+strideq*0] + movhps m2, [srcq+strideq*0+2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 ; 1 2 + shufpd m2, m0, m1, 0x01 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 16 + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w8_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+16*0], m2 + movu m0, [srcq+strideq*0] + movu m2, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m2, m4 + psubw m0, m5 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: +%if WIN64 + push r7 +%endif + mov r5, srcq +%if ARCH_X86_64 + lea r6d, [wq*4-32] + mov wd, wd + lea r6d, [hq+r6*8] + mov r7, tmpq +%else + mov r6d, wd +%endif +.hv_w16_loop0: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m1, m4 + psubw m0, m5 + paddw m0, m1 + psraw m0, 2 +.hv_w16_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*1+2] + lea srcq, [srcq+strideq*2] + pmullw m1, m3 + pmullw m2, m4 + psubw m1, m5 + paddw m1, m2 + psraw m1, 2 + psubw m2, m1, m0 + pmulhrsw m2, m6 + paddw m2, m0 + mova [tmpq+wq*0], m2 + movu m0, [srcq+strideq*0] + movu m2, [srcq+strideq*0+2] + pmullw m0, m3 + pmullw m2, m4 + psubw m0, m5 + paddw m0, m2 + psraw m0, 2 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+wq*2], m2 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w16_loop +%if ARCH_X86_64 + add r5, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 +%else + mov tmpq, tmpmp + add r5, 16 + mov hd, hm + add tmpq, 16 + mov srcq, r5 + mov tmpmp, tmpq + sub r6d, 8 +%endif + jg .hv_w16_loop0 +%if WIN64 + pop r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_16bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_16bpc %+ SUFFIX) +%endif +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 1, 2, 6 +%elif WIN64 +DECLARE_REG_TMP 4, 5, 8 +%else +DECLARE_REG_TMP 7, 8, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +%if ARCH_X86_32 +cglobal put_8tap_16bpc, 0, 7, 8, dst, ds, src, ss, w, h, mx, my +%define mxb r0b +%define mxd r0 +%define mxq r0 +%define myb r1b +%define myd r1 +%define myq r1 +%define m8 [esp+16*0] +%define m9 [esp+16*1] +%define m10 [esp+16*2] +%define m11 [esp+16*3] +%define m12 [esp+16*4] +%define m13 [esp+16*5] +%define m14 [esp+16*6] +%define m15 [esp+16*7] +%else +cglobal put_8tap_16bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my +%endif +%define base t2-put_ssse3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + LEA t2, put_ssse3 + movifnidn wd, wm + movifnidn srcq, srcmp + movifnidn ssq, ssmp + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [base+put_ssse3_table+wq*2] + movifnidn dstq, dstmp + movifnidn dsq, dsmp + add wq, t2 +%if WIN64 + pop r8 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + mov myd, r8m + movd m5, r8m + shr myd, 11 + movddup m4, [base+put_8tap_h_rnd+myq*8] + movifnidn dsq, dsmp + pshufb m5, [base+pw_256] + cmp wd, 4 + jg .h_w8 + movzx mxd, mxb + lea srcq, [srcq-2] + movq m3, [base+subpel_filters+mxq*8] + movifnidn dstq, dstmp + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + je .h_w4 +.h_w2: + mova m2, [base+spel_h_shuf2] + pshufd m3, m3, q2121 +.h_w2_loop: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m2 + pshufb m1, m2 + pmaddwd m0, m3 + pmaddwd m1, m3 + phaddd m0, m1 + paddd m0, m4 + psrad m0, 6 + packssdw m0, m0 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + movd [dstq+dsq*0], m0 + pshuflw m0, m0, q3232 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + WIN64_SPILL_XMM 8 + mova m6, [base+spel_h_shufA] + mova m7, [base+spel_h_shufB] + pshufd m2, m3, q1111 + pshufd m3, m3, q2222 +.h_w4_loop: + movu m1, [srcq] + add srcq, ssq + pshufb m0, m1, m6 ; 0 1 1 2 2 3 3 4 + pshufb m1, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m2 + pmaddwd m1, m3 + paddd m0, m4 + paddd m0, m1 + psrad m0, 6 + packssdw m0, m0 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + movq [dstq], m0 + add dstq, dsq + dec hd + jg .h_w4_loop + RET +.h_w8: +%if WIN64 + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 12 +%endif + shr mxd, 16 + movq m3, [base+subpel_filters+mxq*8] + movifnidn dstq, dstmp + mova m6, [base+spel_h_shufA] + mova m7, [base+spel_h_shufB] +%if UNIX64 + mov wd, wd +%endif + lea srcq, [srcq+wq*2] + punpcklbw m3, m3 + lea dstq, [dstq+wq*2] + psraw m3, 8 + neg wq +%if ARCH_X86_32 + ALLOC_STACK -16*4 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif +.h_w8_loop0: + mov r6, wq +.h_w8_loop: + movu m0, [srcq+r6*2- 6] + movu m1, [srcq+r6*2+ 2] + pshufb m2, m0, m6 ; 0 1 1 2 2 3 3 4 + pshufb m0, m7 ; 2 3 3 4 4 5 5 6 + pmaddwd m2, m8 ; abcd0 + pmaddwd m0, m9 ; abcd1 + pshufb m3, m1, m6 ; 4 5 5 6 6 7 7 8 + pshufb m1, m7 ; 6 7 7 8 8 9 9 a + paddd m2, m4 + paddd m0, m2 + pmaddwd m2, m10, m3 ; abcd2 + pmaddwd m3, m8 ; efgh0 + paddd m0, m2 + pmaddwd m2, m11, m1 ; abcd3 + pmaddwd m1, m9 ; efgh1 + paddd m0, m2 + movu m2, [srcq+r6*2+10] + paddd m3, m4 + paddd m1, m3 + pshufb m3, m2, m6 ; 8 9 9 a a b b c + pshufb m2, m7 ; a b b c c d d e + pmaddwd m3, m10 ; efgh2 + pmaddwd m2, m11 ; efgh3 + paddd m1, m3 + paddd m1, m2 + psrad m0, 6 + psrad m1, 6 + packssdw m0, m1 + pxor m1, m1 + pminsw m0, m5 + pmaxsw m0, m1 + mova [dstq+r6*2], m0 + add r6, 8 + jl .h_w8_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w8_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif +%if WIN64 + WIN64_SPILL_XMM 15 +%endif + movd m7, r8m + movifnidn dstq, dstmp + movifnidn dsq, dsmp + punpcklbw m3, m3 + pshufb m7, [base+pw_256] + psraw m3, 8 ; sign-extend +%if ARCH_X86_32 + ALLOC_STACK -16*7 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif + lea r6, [ssq*3] + sub srcq, r6 + cmp wd, 2 + jne .v_w4 +.v_w2: + movd m1, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + movd m2, [srcq+ssq*2] + add srcq, r6 + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m6, [srcq+ssq*2] + add srcq, r6 + movd m0, [srcq+ssq*0] + punpckldq m1, m4 ; 0 1 + punpckldq m4, m2 ; 1 2 + punpckldq m2, m5 ; 2 3 + punpckldq m5, m3 ; 3 4 + punpckldq m3, m6 ; 4 5 + punpckldq m6, m0 ; 5 6 + punpcklwd m1, m4 ; 01 12 + punpcklwd m2, m5 ; 23 34 + punpcklwd m3, m6 ; 45 56 + pxor m6, m6 +.v_w2_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m8, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m9 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m10 ; a2 b2 + paddd m5, m3 + punpckldq m3, m0, m4 ; 6 7 + movd m0, [srcq+ssq*0] + punpckldq m4, m0 ; 7 8 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m11, m3 ; a3 b3 + paddd m5, m4 + psrad m5, 5 + packssdw m5, m5 + pmaxsw m5, m6 + pavgw m5, m6 + pminsw m5, m7 + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q3232 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: +%if ARCH_X86_32 + shl wd, 14 +%if STACK_ALIGNMENT < 16 + mov [esp+4*29], srcq + mov [esp+4*30], dstq +%else + mov srcmp, srcq +%endif + lea wd, [wq+hq-(1<<16)] +%else + shl wd, 6 + mov r7, srcq + mov r8, dstq + lea wd, [wq+hq-(1<<8)] +%endif +.v_w4_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + movq m3, [srcq+ssq*2] + add srcq, r6 + movq m4, [srcq+ssq*0] + movq m5, [srcq+ssq*1] + movq m6, [srcq+ssq*2] + add srcq, r6 + movq m0, [srcq+ssq*0] + punpcklwd m1, m2 ; 01 + punpcklwd m2, m3 ; 12 + punpcklwd m3, m4 ; 23 + punpcklwd m4, m5 ; 34 + punpcklwd m5, m6 ; 45 + punpcklwd m6, m0 ; 56 +%if ARCH_X86_32 + jmp .v_w4_loop_start +.v_w4_loop: + mova m1, m12 + mova m2, m13 + mova m3, m14 +.v_w4_loop_start: + pmaddwd m1, m8 ; a0 + pmaddwd m2, m8 ; b0 + mova m12, m3 + mova m13, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m1, m3 + paddd m2, m4 + mova m14, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m1, m5 + paddd m2, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m3, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m1, m3 + pmaddwd m3, m11, m6 ; b3 + paddd m2, m3 + psrad m1, 5 + psrad m2, 5 + packssdw m1, m2 + pxor m2, m2 + pmaxsw m1, m2 + pavgw m1, m2 + pminsw m1, m7 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop +%if STACK_ALIGNMENT < 16 + mov srcq, [esp+4*29] + mov dstq, [esp+4*30] + movzx hd, ww + add srcq, 8 + add dstq, 8 + mov [esp+4*29], srcq + mov [esp+4*30], dstq +%else + mov srcq, srcmp + mov dstq, dstmp + movzx hd, ww + add srcq, 8 + add dstq, 8 + mov srcmp, srcq + mov dstmp, dstq +%endif + sub wd, 1<<16 +%else +.v_w4_loop: + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + paddd m13, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m14, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m14 + psrad m12, 5 + psrad m13, 5 + packssdw m12, m13 + pxor m13, m13 + pmaxsw m12, m13 + pavgw m12, m13 + pminsw m12, m7 + movq [dstq+dsq*0], m12 + movhps [dstq+dsq*1], m12 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + add r7, 8 + add r8, 8 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 +%endif + jg .v_w4_loop0 + RET +.hv: +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif +%if ARCH_X86_32 + movd m4, r8m + mova m6, [base+pd_512] + pshufb m4, [base+pw_256] +%else +%if WIN64 + ALLOC_STACK 16*6, 16 +%endif + movd m15, r8m + pshufb m15, [base+pw_256] +%endif + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + je .hv_w4 + movq m0, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 + mov dstq, dstmp + mov dsq, dsmp + mova m5, [base+spel_h_shuf2] + ALLOC_STACK -16*8 +%else + mova m6, [base+pd_512] + mova m9, [base+spel_h_shuf2] +%endif + pshuflw m0, m0, q2121 + pxor m7, m7 + punpcklbw m7, m0 + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + test dword r8m, 0x800 + jz .hv_w2_10bpc + psraw m7, 2 + psllw m3, 2 +.hv_w2_10bpc: + lea r6, [ssq*3] + sub srcq, 2 + sub srcq, r6 +%if ARCH_X86_32 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m9, m5 + mova m11, m0 + mova m12, m1 + mova m13, m2 + mova m14, m3 + mova m15, m4 +%else + pshufd m11, m3, q0000 + pshufd m12, m3, q1111 + pshufd m13, m3, q2222 + pshufd m14, m3, q3333 +%endif + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + movu m1, [srcq+ssq*2] + add srcq, r6 + movu m4, [srcq+ssq*0] +%if ARCH_X86_32 + REPX {pshufb x, m5}, m2, m3, m1, m4 +%else + REPX {pshufb x, m9}, m2, m3, m1, m4 +%endif + REPX {pmaddwd x, m7}, m2, m3, m1, m4 + phaddd m2, m3 ; 0 1 + phaddd m1, m4 ; 2 3 + movu m3, [srcq+ssq*1] + movu m4, [srcq+ssq*2] + add srcq, r6 + movu m0, [srcq+ssq*0] +%if ARCH_X86_32 + REPX {pshufb x, m5}, m3, m4, m0 +%else + REPX {pshufb x, m9}, m3, m4, m0 +%endif + REPX {pmaddwd x, m7}, m3, m4, m0 + phaddd m3, m4 ; 4 5 + phaddd m0, m0 ; 6 6 + REPX {paddd x, m6}, m2, m1, m3, m0 + REPX {psrad x, 10}, m2, m1, m3, m0 + packssdw m2, m1 ; 0 1 2 3 + packssdw m3, m0 ; 4 5 6 _ + palignr m4, m3, m2, 4 ; 1 2 3 4 + pshufd m5, m3, q0321 ; 5 6 _ _ + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + punpcklwd m3, m5 ; 45 56 +.hv_w2_loop: + movu m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movu m5, [srcq+ssq*0] + pshufb m4, m9 + pshufb m5, m9 + pmaddwd m4, m7 + pmaddwd m5, m7 + phaddd m4, m5 + pmaddwd m5, m11, m1 ; a0 b0 + mova m1, m2 + pmaddwd m2, m12 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m13 ; a2 b2 + paddd m5, m3 + paddd m4, m6 + psrad m4, 10 ; 7 8 + packssdw m0, m4 + pshufd m3, m0, q2103 + punpckhwd m3, m0 ; 67 78 + mova m0, m4 + pmaddwd m4, m14, m3 ; a3 b3 + paddd m5, m6 + paddd m5, m4 + psrad m5, 10 + packssdw m5, m5 + pxor m4, m4 + pminsw m5, m15 + pmaxsw m5, m4 + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q3232 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w8: + shr mxd, 16 +.hv_w4: + movq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovb myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + mov dstq, dstmp + mov dsq, dsmp + mova m0, [base+spel_h_shufA] + mova m1, [base+spel_h_shufB] + ALLOC_STACK -16*15 + mova m8, m0 + mova m9, m1 + mova m14, m6 +%else + mova m8, [base+spel_h_shufA] + mova m9, [base+spel_h_shufB] +%endif + pxor m0, m0 + punpcklbw m0, m2 + punpcklbw m3, m3 + psraw m3, 8 + test dword r8m, 0x800 + jz .hv_w4_10bpc + psraw m0, 2 + psllw m3, 2 +.hv_w4_10bpc: + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 +%if ARCH_X86_32 + %define tmp esp+16*8 + shl wd, 14 +%if STACK_ALIGNMENT < 16 + mov [esp+4*61], srcq + mov [esp+4*62], dstq +%else + mov srcmp, srcq +%endif + mova [tmp+16*5], m4 + lea wd, [wq+hq-(1<<16)] + pshufd m1, m0, q0000 + pshufd m2, m0, q1111 + pshufd m5, m0, q2222 + pshufd m0, m0, q3333 + mova m10, m1 + mova m11, m2 + mova m12, m5 + mova m13, m0 +%else +%if WIN64 + %define tmp rsp +%else + %define tmp rsp-104 ; red zone +%endif + shl wd, 6 + mov r7, srcq + mov r8, dstq + lea wd, [wq+hq-(1<<8)] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 + mova [tmp+16*5], m15 +%endif + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [tmp+16*1], m0 + mova [tmp+16*2], m1 + mova [tmp+16*3], m2 + mova [tmp+16*4], m3 +%macro PUT_8TAP_HV_H 4-5 m14 ; dst/src+0, src+8, tmp, shift, [pd_512] + pshufb m%3, m%1, m8 ; 0 1 1 2 2 3 3 4 + pshufb m%1, m9 ; 2 3 3 4 4 5 5 6 + pmaddwd m%3, m10 + pmaddwd m%1, m11 + paddd m%3, %5 + paddd m%1, m%3 + pshufb m%3, m%2, m8 ; 4 5 5 6 6 7 7 8 + pshufb m%2, m9 ; 6 7 7 8 8 9 9 a + pmaddwd m%3, m12 + pmaddwd m%2, m13 + paddd m%1, m%3 + paddd m%1, m%2 + psrad m%1, %4 +%endmacro +.hv_w4_loop0: +%if ARCH_X86_64 + mova m14, [pd_512] +%endif + movu m4, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + movu m5, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + movu m6, [srcq+ssq*2+0] + movu m3, [srcq+ssq*2+8] + add srcq, r6 + PUT_8TAP_HV_H 4, 1, 0, 10 + PUT_8TAP_HV_H 5, 2, 0, 10 + PUT_8TAP_HV_H 6, 3, 0, 10 + movu m7, [srcq+ssq*0+0] + movu m2, [srcq+ssq*0+8] + movu m1, [srcq+ssq*1+0] + movu m3, [srcq+ssq*1+8] + PUT_8TAP_HV_H 7, 2, 0, 10 + PUT_8TAP_HV_H 1, 3, 0, 10 + movu m2, [srcq+ssq*2+0] + movu m3, [srcq+ssq*2+8] + add srcq, r6 + PUT_8TAP_HV_H 2, 3, 0, 10 + packssdw m4, m7 ; 0 3 + packssdw m5, m1 ; 1 4 + movu m0, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 1, 3, 10 + packssdw m6, m2 ; 2 5 + packssdw m7, m0 ; 3 6 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +%if ARCH_X86_32 + jmp .hv_w4_loop_start +.hv_w4_loop: + mova m1, [tmp+16*6] + mova m2, m15 +.hv_w4_loop_start: + mova m7, [tmp+16*1] + pmaddwd m1, m7 ; a0 + pmaddwd m2, m7 ; b0 + mova m7, [tmp+16*2] + mova [tmp+16*6], m3 + pmaddwd m3, m7 ; a1 + mova m15, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m1, m3 + paddd m2, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m1, m5 + paddd m2, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 10 + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 10 + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m1, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m2, m7 ; b3 + psrad m1, 9 + psrad m2, 9 + packssdw m1, m2 + pxor m7, m7 + pmaxsw m1, m7 + pavgw m7, m1 + pminsw m7, [tmp+16*5] + movq [dstq+dsq*0], m7 + movhps [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop +%if STACK_ALIGNMENT < 16 + mov srcq, [esp+4*61] + mov dstq, [esp+4*62] + add srcq, 8 + add dstq, 8 + mov [esp+4*61], srcq + mov [esp+4*62], dstq +%else + mov srcq, srcmp + mov dstq, dstmp + add srcq, 8 + add dstq, 8 + mov srcmp, srcq + mov dstmp, dstq +%endif + movzx hd, ww + sub wd, 1<<16 +%else +.hv_w4_loop: + mova m15, [tmp+16*1] + pmaddwd m14, m15, m1 ; a0 + pmaddwd m15, m2 ; b0 + mova m7, [tmp+16*2] + mova m1, m3 + pmaddwd m3, m7 ; a1 + mova m2, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m14, m3 + paddd m15, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m14, m5 + paddd m15, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 10, [pd_512] + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 10, [pd_512] + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m14, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m15, m7 ; b3 + psrad m14, 9 + psrad m15, 9 + packssdw m14, m15 + pxor m7, m7 + pmaxsw m14, m7 + pavgw m7, m14 + pminsw m7, [tmp+16*5] + movq [dstq+dsq*0], m7 + movhps [dstq+dsq*1], m7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + add r7, 8 + add r8, 8 + movzx hd, wb + mov srcq, r7 + mov dstq, r8 + sub wd, 1<<8 +%endif + jg .hv_w4_loop0 + RET +%undef tmp + +%if ARCH_X86_32 +DECLARE_REG_TMP 2, 1, 6, 4 +%elif WIN64 +DECLARE_REG_TMP 6, 4, 7, 4 +%else +DECLARE_REG_TMP 6, 7, 7, 8 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +%if ARCH_X86_32 +cglobal prep_8tap_16bpc, 0, 7, 8, tmp, src, ss, w, h, mx, my +%define mxb r0b +%define mxd r0 +%define mxq r0 +%define myb r2b +%define myd r2 +%define myq r2 +%else +cglobal prep_8tap_16bpc, 4, 8, 0, tmp, src, ss, w, h, mx, my +%endif +%define base t2-prep_ssse3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + LEA t2, prep_ssse3 + movifnidn wd, wm + movifnidn srcq, srcmp + test mxd, 0xf00 + jnz .h + movifnidn hd, hm + test myd, 0xf00 + jnz .v + tzcnt wd, wd + mov myd, r7m ; bitdepth_max + movzx wd, word [base+prep_ssse3_table+wq*2] + mova m5, [base+pw_8192] + shr myd, 11 + add wq, t2 + movddup m4, [base+prep_mul+myq*8] + movifnidn ssq, ssmp + movifnidn tmpq, tmpmp + lea r6, [ssq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + movifnidn ssq, r2mp + movifnidn hd, r4m + movddup m5, [base+prep_8tap_1d_rnd] + cmp wd, 4 + jne .h_w8 + movzx mxd, mxb + movq m0, [base+subpel_filters+mxq*8] + mova m3, [base+spel_h_shufA] + mova m4, [base+spel_h_shufB] + movifnidn tmpq, tmpmp + sub srcq, 2 + WIN64_SPILL_XMM 8 + punpcklbw m0, m0 + psraw m0, 8 + test dword r7m, 0x800 + jnz .h_w4_12bpc + psllw m0, 2 +.h_w4_12bpc: + pshufd m6, m0, q1111 + pshufd m7, m0, q2222 +.h_w4_loop: + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m1, m3 ; 0 1 1 2 2 3 3 4 + pshufb m1, m4 ; 2 3 3 4 4 5 5 6 + pmaddwd m0, m6 + pmaddwd m1, m7 + paddd m0, m5 + paddd m0, m1 + pshufb m1, m2, m3 + pshufb m2, m4 + pmaddwd m1, m6 + pmaddwd m2, m7 + paddd m1, m5 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq], m0 + add tmpq, 16 + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + WIN64_SPILL_XMM 11 + shr mxd, 16 + movq m2, [base+subpel_filters+mxq*8] + mova m4, [base+spel_h_shufA] + mova m6, [base+spel_h_shufB] + movifnidn tmpq, r0mp + add wd, wd + punpcklbw m2, m2 + add srcq, wq + psraw m2, 8 + add tmpq, wq + neg wq + test dword r7m, 0x800 + jnz .h_w8_12bpc + psllw m2, 2 +.h_w8_12bpc: + pshufd m7, m2, q0000 +%if ARCH_X86_32 + ALLOC_STACK -16*3 + pshufd m0, m2, q1111 + pshufd m1, m2, q2222 + pshufd m2, m2, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 +%else + pshufd m8, m2, q1111 + pshufd m9, m2, q2222 + pshufd m10, m2, q3333 +%endif +.h_w8_loop0: + mov r6, wq +.h_w8_loop: + movu m0, [srcq+r6- 6] + movu m1, [srcq+r6+ 2] + pshufb m2, m0, m4 ; 0 1 1 2 2 3 3 4 + pshufb m0, m6 ; 2 3 3 4 4 5 5 6 + pmaddwd m2, m7 ; abcd0 + pmaddwd m0, m8 ; abcd1 + pshufb m3, m1, m4 ; 4 5 5 6 6 7 7 8 + pshufb m1, m6 ; 6 7 7 8 8 9 9 a + paddd m2, m5 + paddd m0, m2 + pmaddwd m2, m9, m3 ; abcd2 + pmaddwd m3, m7 ; efgh0 + paddd m0, m2 + pmaddwd m2, m10, m1 ; abcd3 + pmaddwd m1, m8 ; efgh1 + paddd m0, m2 + movu m2, [srcq+r6+10] + paddd m3, m5 + paddd m1, m3 + pshufb m3, m2, m4 ; a b b c c d d e + pshufb m2, m6 ; 8 9 9 a a b b c + pmaddwd m3, m9 ; efgh2 + pmaddwd m2, m10 ; efgh3 + paddd m1, m3 + paddd m1, m2 + psrad m0, 4 + psrad m1, 4 + packssdw m0, m1 + mova [tmpq+r6], m0 + add r6, 16 + jl .h_w8_loop + add srcq, ssq + sub tmpq, wq + dec hd + jg .h_w8_loop0 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + WIN64_SPILL_XMM 15 + movddup m7, [base+prep_8tap_1d_rnd] + movifnidn ssq, r2mp + movifnidn tmpq, r0mp + punpcklbw m3, m3 + psraw m3, 8 ; sign-extend + test dword r7m, 0x800 + jnz .v_12bpc + psllw m3, 2 +.v_12bpc: +%if ARCH_X86_32 + ALLOC_STACK -16*7 + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova m8, m0 + mova m9, m1 + mova m10, m2 + mova m11, m3 +%else + pshufd m8, m3, q0000 + pshufd m9, m3, q1111 + pshufd m10, m3, q2222 + pshufd m11, m3, q3333 +%endif + lea r6, [ssq*3] + sub srcq, r6 + mov r6d, wd + shl wd, 6 + mov r5, srcq +%if ARCH_X86_64 + mov r7, tmpq +%elif STACK_ALIGNMENT < 16 + mov [esp+4*29], tmpq +%endif + lea wd, [wq+hq-(1<<8)] +.v_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m3, [srcq+ssq*0] + movq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m5, [srcq+ssq*0] + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq m0, [srcq+ssq*0] + punpcklwd m1, m2 ; 01 + punpcklwd m2, m3 ; 12 + punpcklwd m3, m4 ; 23 + punpcklwd m4, m5 ; 34 + punpcklwd m5, m6 ; 45 + punpcklwd m6, m0 ; 56 +%if ARCH_X86_32 + jmp .v_loop_start +.v_loop: + mova m1, m12 + mova m2, m13 + mova m3, m14 +.v_loop_start: + pmaddwd m1, m8 ; a0 + pmaddwd m2, m8 ; b0 + mova m12, m3 + mova m13, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m1, m3 + paddd m2, m4 + mova m14, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m1, m5 + paddd m2, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m3, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m1, m7 + paddd m1, m3 + pmaddwd m3, m11, m6 ; b3 + paddd m2, m7 + paddd m2, m3 + psrad m1, 4 + psrad m2, 4 + packssdw m1, m2 + movq [tmpq+r6*0], m1 + movhps [tmpq+r6*2], m1 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .v_loop +%if STACK_ALIGNMENT < 16 + mov tmpq, [esp+4*29] + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov [esp+4*29], tmpq +%else + mov tmpq, tmpmp + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov tmpmp, tmpq +%endif +%else +.v_loop: + pmaddwd m12, m8, m1 ; a0 + pmaddwd m13, m8, m2 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m9 ; a1 + pmaddwd m4, m9 ; b1 + paddd m12, m3 + paddd m13, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m10 ; a2 + pmaddwd m6, m10 ; b2 + paddd m12, m5 + paddd m13, m6 + movq m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklwd m5, m0, m6 ; 67 + movq m0, [srcq+ssq*0] + pmaddwd m14, m11, m5 ; a3 + punpcklwd m6, m0 ; 78 + paddd m12, m7 + paddd m12, m14 + pmaddwd m14, m11, m6 ; b3 + paddd m13, m7 + paddd m13, m14 + psrad m12, 4 + psrad m13, 4 + packssdw m12, m13 + movq [tmpq+r6*0], m12 + movhps [tmpq+r6*2], m12 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .v_loop + add r5, 8 + add r7, 8 + mov srcq, r5 + mov tmpq, r7 +%endif + movzx hd, wb + sub wd, 1<<8 + jg .v_loop0 + RET +.hv: +%if STACK_ALIGNMENT < 16 + %xdefine rstk rsp +%else + %assign stack_offset stack_offset - stack_size_padded +%endif + movzx t3d, mxb + shr mxd, 16 + cmp wd, 4 + cmove mxd, t3d + movifnidn hd, r4m + movq m2, [base+subpel_filters+mxq*8] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + movq m3, [base+subpel_filters+myq*8] +%if ARCH_X86_32 + mov ssq, r2mp + mov tmpq, r0mp + mova m0, [base+spel_h_shufA] + mova m1, [base+spel_h_shufB] + mova m4, [base+prep_8tap_2d_rnd] + ALLOC_STACK -16*14 + mova m8, m0 + mova m9, m1 + mova m14, m4 +%else +%if WIN64 + ALLOC_STACK 16*6, 16 +%endif + mova m8, [base+spel_h_shufA] + mova m9, [base+spel_h_shufB] +%endif + pxor m0, m0 + punpcklbw m0, m2 + punpcklbw m3, m3 + psraw m0, 4 + psraw m3, 8 + test dword r7m, 0x800 + jz .hv_10bpc + psraw m0, 2 +.hv_10bpc: + lea r6, [ssq*3] + sub srcq, 6 + sub srcq, r6 + mov r6d, wd + shl wd, 6 + mov r5, srcq +%if ARCH_X86_32 + %define tmp esp+16*8 +%if STACK_ALIGNMENT < 16 + mov [esp+4*61], tmpq +%endif + pshufd m1, m0, q0000 + pshufd m2, m0, q1111 + pshufd m5, m0, q2222 + pshufd m0, m0, q3333 + mova m10, m1 + mova m11, m2 + mova m12, m5 + mova m13, m0 +%else +%if WIN64 + %define tmp rsp +%else + %define tmp rsp-88 ; red zone +%endif + mov r7, tmpq + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + lea wd, [wq+hq-(1<<8)] + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [tmp+16*1], m0 + mova [tmp+16*2], m1 + mova [tmp+16*3], m2 + mova [tmp+16*4], m3 +.hv_loop0: +%if ARCH_X86_64 + mova m14, [prep_8tap_2d_rnd] +%endif + movu m4, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + movu m5, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + movu m6, [srcq+ssq*0+0] + movu m3, [srcq+ssq*0+8] + PUT_8TAP_HV_H 4, 1, 0, 6 + PUT_8TAP_HV_H 5, 2, 0, 6 + PUT_8TAP_HV_H 6, 3, 0, 6 + movu m7, [srcq+ssq*1+0] + movu m2, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + movu m1, [srcq+ssq*0+0] + movu m3, [srcq+ssq*0+8] + PUT_8TAP_HV_H 7, 2, 0, 6 + PUT_8TAP_HV_H 1, 3, 0, 6 + movu m2, [srcq+ssq*1+0] + movu m3, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 2, 3, 0, 6 + packssdw m4, m7 ; 0 3 + packssdw m5, m1 ; 1 4 + movu m0, [srcq+ssq*0+0] + movu m1, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 1, 3, 6 + packssdw m6, m2 ; 2 5 + packssdw m7, m0 ; 3 6 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +%if ARCH_X86_32 + jmp .hv_loop_start +.hv_loop: + mova m1, [tmp+16*5] + mova m2, m15 +.hv_loop_start: + mova m7, [tmp+16*1] + pmaddwd m1, m7 ; a0 + pmaddwd m2, m7 ; b0 + mova m7, [tmp+16*2] + mova [tmp+16*5], m3 + pmaddwd m3, m7 ; a1 + mova m15, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m1, m14 + paddd m2, m14 + paddd m1, m3 + paddd m2, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m1, m5 + paddd m2, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 6 + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 6 + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m1, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m2, m7 ; b3 + psrad m1, 6 + psrad m2, 6 + packssdw m1, m2 + movq [tmpq+r6*0], m1 + movhps [tmpq+r6*2], m1 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .hv_loop +%if STACK_ALIGNMENT < 16 + mov tmpq, [esp+4*61] + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov [esp+4*61], tmpq +%else + mov tmpq, tmpmp + add r5, 8 + add tmpq, 8 + mov srcq, r5 + mov tmpmp, tmpq +%endif +%else +.hv_loop: + mova m15, [tmp+16*1] + mova m7, [prep_8tap_2d_rnd] + pmaddwd m14, m15, m1 ; a0 + pmaddwd m15, m2 ; b0 + paddd m14, m7 + paddd m15, m7 + mova m7, [tmp+16*2] + mova m1, m3 + pmaddwd m3, m7 ; a1 + mova m2, m4 + pmaddwd m4, m7 ; b1 + mova m7, [tmp+16*3] + paddd m14, m3 + paddd m15, m4 + mova m3, m5 + pmaddwd m5, m7 ; a2 + mova m4, m6 + pmaddwd m6, m7 ; b2 + paddd m14, m5 + paddd m15, m6 + movu m7, [srcq+ssq*1+0] + movu m5, [srcq+ssq*1+8] + lea srcq, [srcq+ssq*2] + PUT_8TAP_HV_H 7, 5, 6, 6, [prep_8tap_2d_rnd] + packssdw m0, m7 ; 6 7 + mova [tmp+16*0], m0 + movu m0, [srcq+ssq*0+0] + movu m5, [srcq+ssq*0+8] + PUT_8TAP_HV_H 0, 5, 6, 6, [prep_8tap_2d_rnd] + mova m6, [tmp+16*0] + packssdw m7, m0 ; 7 8 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, [tmp+16*4] + paddd m14, m7 ; a3 + pmaddwd m7, m6, [tmp+16*4] + paddd m15, m7 ; b3 + psrad m14, 6 + psrad m15, 6 + packssdw m14, m15 + movq [tmpq+r6*0], m14 + movhps [tmpq+r6*2], m14 + lea tmpq, [tmpq+r6*4] + sub hd, 2 + jg .hv_loop + add r5, 8 + add r7, 8 + mov srcq, r5 + mov tmpq, r7 +%endif + movzx hd, wb + sub wd, 1<<8 + jg .hv_loop0 + RET +%undef tmp + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro SAVE_REG 1 + %xdefine r%1_save r%1 + %xdefine r%1q_save r%1q + %xdefine r%1d_save r%1d + %if ARCH_X86_32 + %define r%1m_save [rstk+stack_offset+(%1+1)*4] + %endif +%endmacro + +%macro LOAD_REG 1 + %xdefine r%1 r%1_save + %xdefine r%1q r%1q_save + %xdefine r%1d r%1d_save + %if ARCH_X86_32 + %define r%1m r%1m_save + %endif + %undef r%1d_save + %undef r%1q_save + %undef r%1_save +%endmacro + +%macro REMAP_REG 2-3 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d + %if ARCH_X86_32 + %if %3 == 0 + %xdefine r%1m r%2m + %else + %define r%1m [rstk+stack_offset+(%1+1)*4] + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %if ARCH_X86_64 + SAVE_REG 14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %else + SAVE_REG 5 + %assign %%i 5 + %rep 5 + %assign %%j %%i-1 + REMAP_REG %%i, %%j, 0 + %assign %%i %%i-1 + %endrep + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %if ARCH_X86_64 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + LOAD_REG 14 + %else + %rep 4 + %assign %%j %%i+1 + REMAP_REG %%i, %%j, 1 + %assign %%i %%i+1 + %endrep + LOAD_REG 5 + %endif + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%if ARCH_X86_32 + %macro MC_4TAP_SCALED_H 1 ; dst_mem + movu m7, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m5, [r4 +ssq*0] + movu m6, [r4 +ssq*1] + lea srcq, [srcq+ssq*2] + lea r4, [r4 +ssq*2] + REPX {pshufb x, m12}, m7, m2 + REPX {pmaddwd x, m13}, m7, m2 + REPX {pshufb x, m14}, m5, m6 + REPX {pmaddwd x, m15}, m5, m6 + phaddd m7, m5 + phaddd m2, m6 + mova m5, [esp+0x00] + movd m6, [esp+0x10] + paddd m7, m5 + paddd m2, m5 + psrad m7, m6 + psrad m2, m6 + packssdw m7, m2 + mova [stk+%1], m7 + %endmacro +%endif + +%if ARCH_X86_64 + %macro MC_8TAP_SCALED_H 8 ; dst, tmp[0-6] + movu m%1, [srcq+ r4*2] + movu m%2, [srcq+ r6*2] + movu m%3, [srcq+ r7*2] + movu m%4, [srcq+ r9*2] + movu m%5, [srcq+r10*2] + movu m%6, [srcq+r11*2] + movu m%7, [srcq+r13*2] + movu m%8, [srcq+ rX*2] + add srcq, ssq + pmaddwd m%1, [stk+0x10] + pmaddwd m%2, [stk+0x20] + pmaddwd m%3, [stk+0x30] + pmaddwd m%4, [stk+0x40] + pmaddwd m%5, [stk+0x50] + pmaddwd m%6, [stk+0x60] + pmaddwd m%7, [stk+0x70] + pmaddwd m%8, [stk+0x80] + phaddd m%1, m%2 + phaddd m%3, m%4 + phaddd m%5, m%6 + phaddd m%7, m%8 + phaddd m%1, m%3 + phaddd m%5, m%7 + paddd m%1, hround + paddd m%5, hround + psrad m%1, m12 + psrad m%5, m12 + packssdw m%1, m%5 + %endmacro +%else + %macro MC_8TAP_SCALED_H 2-3 1 ; weights_mem_start, h_mem, load_fh_offsets + %if %3 == 1 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + %endif + movu m0, [srcq+r0*2] + movu m1, [srcq+rX*2] + movu m2, [srcq+r4*2] + movu m3, [srcq+r5*2] + mov r0, [stk+16] + mov rX, [stk+20] + mov r4, [stk+24] + mov r5, [stk+28] + pmaddwd m0, [stk+%1+0x00] + pmaddwd m1, [stk+%1+0x10] + pmaddwd m2, [stk+%1+0x20] + pmaddwd m3, [stk+%1+0x30] + phaddd m0, m1 + phaddd m2, m3 + movu m4, [srcq+r0*2] + movu m5, [srcq+rX*2] + movu m6, [srcq+r4*2] + movu m7, [srcq+r5*2] + add srcq, ssq + pmaddwd m4, [stk+%1+0xa0] + pmaddwd m5, [stk+%1+0xb0] + pmaddwd m6, [stk+%1+0xc0] + pmaddwd m7, [stk+%1+0xd0] + phaddd m4, m5 + phaddd m6, m7 + phaddd m0, m2 + phaddd m4, m6 + paddd m0, hround + paddd m4, hround + psrad m0, m12 + psrad m4, m12 + packssdw m0, m4 + %if %2 != 0 + mova [stk+%2], m0 + %endif + %endmacro +%endif + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isput 1 + %assign isprep 0 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_16bpc, 2, 15, 16, 0x1c0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal put_8tap_scaled_16bpc, 2, 14, 16, 0x1c0, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_16bpc, 0, 7, 8, 0x200, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal put_8tap_scaled_16bpc, 0, 7, 8, -0x200-0x30, dst, ds, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %endif + %xdefine base_reg r12 +%else ; prep + %assign isput 0 + %assign isprep 1 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_16bpc, 2, 15, 16, 0x1c0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %xdefine tmp_stridem r14q + %else +cglobal prep_8tap_scaled_16bpc, 2, 14, 16, 0x1c0, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %define tmp_stridem qword [stk+0x138] + %endif + %xdefine base_reg r11 + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_16bpc, 0, 7, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %else +cglobal prep_8tap_scaled_16bpc, 0, 6, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy, pxmax + %endif + %define tmp_stridem dword [stk+0x138] + %endif +%endif +%if ARCH_X86_32 + mov [esp+0x1f0], t0d + mov [esp+0x1f4], t1d + %if isput && required_stack_alignment > STACK_ALIGNMENT + mov dstd, dstm + mov dsd, dsm + mov srcd, srcm + mov ssd, ssm + mov hd, hm + mov r4, mxm + %define r0m [esp+0x200] + %define dsm [esp+0x204] + %define dsmp dsm + %define r1m dsm + %define r2m [esp+0x208] + %define ssm [esp+0x20c] + %define r3m ssm + %define hm [esp+0x210] + %define mxm [esp+0x214] + mov r0m, dstd + mov dsm, dsd + mov r2m, srcd + mov ssm, ssd + mov hm, hd + mov r0, mym + mov r1, dxm + mov r2, dym + %define mym [esp+0x218] + %define dxm [esp+0x21c] + %define dym [esp+0x220] + mov mxm, r4 + mov mym, r0 + mov dxm, r1 + mov dym, r2 + tzcnt wd, wm + %endif + %if isput + mov r3, pxmaxm + %define pxmaxm r3 + %else + mov r2, pxmaxm + %endif + %if isprep && required_stack_alignment > STACK_ALIGNMENT + %xdefine base_reg r5 + %else + %xdefine base_reg r6 + %endif +%endif + LEA base_reg, %1_8tap_scaled_16bpc_ssse3 +%xdefine base base_reg-%1_8tap_scaled_16bpc_ssse3 +%if ARCH_X86_64 || isprep || required_stack_alignment <= STACK_ALIGNMENT + tzcnt wd, wm +%endif +%if ARCH_X86_64 + %if isput + mov r7d, pxmaxm + %endif +%else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 +%endif + movd m8, dxm + movd m14, mxm +%if isput + movd m15, pxmaxm +%endif + pshufd m8, m8, q0000 + pshufd m14, m14, q0000 +%if isput + pshuflw m15, m15, q0000 + punpcklqdq m15, m15 +%endif +%if isprep + %if UNIX64 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 + %endif + %if ARCH_X86_64 + mov r6d, pxmaxm + %endif +%endif +%if ARCH_X86_64 + mov dyd, dym +%endif +%if isput + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %elif ARCH_X86_64 + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %else + %endif + %if ARCH_X86_64 + %if required_stack_alignment > STACK_ALIGNMENT + %define dsm [rsp+0x138] + %define rX r1 + %define rXd r1d + %else + %define dsm dsq + %define rX r14 + %define rXd r14d + %endif + %else + %define rX r1 + %endif +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %elif ARCH_X86_64 + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %xdefine hm r7m + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %if ARCH_X86_64 + %define rX r14 + %define rXd r14d + %else + %define rX r3 + %endif +%endif +%if ARCH_X86_64 + shr r7d, 11 + mova m10, [base+pd_0x3ff] + movddup m11, [base+s_8tap_h_rnd+r7*8] + movd m12, [base+s_8tap_h_sh+r7*4] + %if isput + movddup m13, [base+put_s_8tap_v_rnd+r7*8] + movd m7, [base+put_s_8tap_v_sh+r7*4] + %define pxmaxm [rsp] + mova pxmaxm, m15 + punpcklqdq m12, m7 + %endif + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q +%else + %define m10 [base+pd_0x3ff] + %define m11 [esp+0x00] + %define m12 [esp+0x10] + shr r3, 11 + movddup m1, [base+s_8tap_h_rnd+r3*8] + movd m2, [base+s_8tap_h_sh+r3*4] + %if isput + %define m13 [esp+0x20] + %define pxmaxm [esp+0x30] + %define stk esp+0x40 + movddup m5, [base+put_s_8tap_v_rnd+r3*8] + movd m6, [base+put_s_8tap_v_sh+r3*4] + mova pxmaxm, m15 + punpcklqdq m2, m6 + mova m13, m5 + %else + %define m13 [base+pd_m524256] + %endif + mov ssd, ssm + mova m11, m1 + mova m12, m2 + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + mov r1, [esp+0x1f4] + lea r0, [ssd*3] + movzx r2, r1b + shr r1, 16 + cmp dword hm, 6 + cmovs r1, r2 + mov [esp+0x1f4], r1 + %if isprep + mov r1, r1m + %endif + mov r2, r2m + sub srcq, r0 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define ss3q r0 + %define myd r4 + %define dyd dword dym + %define hd dword hm +%endif + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_ssse3_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + movzx r4, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r4 + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6, m7 + REPX {pmaddwd x, m15}, m4, m5, m6, m7 + phaddd m0, m1 + phaddd m2, m3 + phaddd m4, m5 + phaddd m6, m7 + REPX {paddd x, m11}, m0, m2, m4, m6 + REPX {psrad x, m12}, m0, m2, m4, m6 + packssdw m0, m2 ; 0 1 2 3 + packssdw m4, m6 ; 4 5 6 7 + SWAP m1, m4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m2, m3 + movu m1, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m14}, m1, m7, m6, m3 + REPX {pmaddwd x, m15}, m1, m7, m6, m3 + phaddd m1, m7 + phaddd m6, m3 + REPX {paddd x, m11}, m0, m2, m1, m6 + REPX {psrad x, m12}, m0, m2, m1, m6 + packssdw m0, m2 + packssdw m1, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + %endif + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mov myd, mym + mov r0, r0m + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif +.w2_loop: + and myd, 0x3ff + %if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m10, r6q + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pmaddwd m5, m3, m7 + pmaddwd m6, m0, m8 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddwd m7, m2, m9 + pmaddwd m8, m4, m10 + paddd m5, m6 + paddd m7, m8 + %else + mov r1, [esp+0x1f4] + xor r3, r3 + mov r5, myd + shr r5, 6 + lea r1, [r1+r5] + mov r5, 64 << 24 + cmovnz r3, [base+subpel_filters+r1*8+4] + cmovnz r5, [base+subpel_filters+r1*8+0] + movd m6, r3 + movd m7, r5 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m5, m7, q0000 + pshufd m6, m7, q1111 + pmaddwd m3, m5 + pmaddwd m0, m6 + pshufd m5, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m2, m5 + pmaddwd m4, m7 + paddd m3, m0 + paddd m2, m4 + SWAP m5, m3 + SWAP m7, m2 + %define m8 m3 + %endif + paddd m5, m13 + pshufd m6, m12, q1032 + pxor m8, m8 + paddd m5, m7 + psrad m5, m6 + packssdw m5, m5 + pmaxsw m5, m8 + pminsw m5, pxmaxm + movd [dstq], m5 + add dstq, dsmp + dec hd + jz .ret + %if ARCH_X86_64 + add myd, dyd + %else + add myd, dym + %endif + test myd, ~0x3ff + %if ARCH_X86_32 + SWAP m3, m5 + SWAP m2, m7 + mova m3, [stk+0x20] + mova m0, [stk+0x30] + mova m2, [stk+0x40] + mova m4, [stk+0x50] + %endif + jz .w2_loop + %if ARCH_X86_32 + mov r3, r3m + %endif + movu m5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps m3, m0, q1032 ; 01 12 + shufps m0, m2, q1032 ; 23 34 + shufps m2, m4, q1032 ; 45 56 + pshufb m5, m14 + pmaddwd m5, m15 + phaddd m5, m5 + paddd m5, m11 + psrad m5, m12 + packssdw m5, m5 + palignr m4, m5, m1, 12 + punpcklqdq m1, m4, m4 ; 6 7 6 7 + punpcklwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif + jmp .w2_loop +.w2_skip_line: + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m3, m0 ; 01 12 + mova m0, m2 ; 23 34 + pshufb m5, m14 + pshufb m6, m14 + pmaddwd m5, m15 + pmaddwd m6, m15 + phaddd m5, m6 + paddd m5, m11 + psrad m5, m12 + packssdw m5, m5 ; 6 7 6 7 + punpckhqdq m1, m5 ; 4 5 6 7 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + mova [stk+0x40], m2 + mova [stk+0x50], m4 + %endif + jmp .w2_loop +%endif +INIT_XMM ssse3 +.w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + movzx r4, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%else + %define m9 [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd rX, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + movifprep r3, r3m + SWAP m4, m7 + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x20], m13 + mova [stk+0x30], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + movu m1, [srcq+r4 ] + movu m3, [srcq+r6 ] + movu m2, [srcq+r11 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m13}, m7, m9, m8, m10 + REPX {pshufb x, m14}, m1, m2, m3, m4 + REPX {pmaddwd x, m15}, m1, m2, m3, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m4, [srcq+ss3q ] + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 + packssdw m8, m10 ; 2 3 + movu m0, [srcq+r4 ] + movu m9, [srcq+r6 ] + movu m10, [srcq+r11 ] + movu m11, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m1, m2, m3, m4 + REPX {pmaddwd x, m13}, m1, m2, m3, m4 + REPX {pshufb x, m14}, m0, m9, m10, m11 + REPX {pmaddwd x, m15}, m0, m9, m10, m11 + phaddd m1, m0 + phaddd m2, m9 + phaddd m3, m10 + phaddd m4, m11 + REPX {paddd x, m5}, m1, m2, m3, m4 + REPX {psrad x, xm6}, m1, m2, m3, m4 + packssdw m1, m2 ; 4 5 + packssdw m3, m4 ; 6 7 + SWAP m9, m1 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + pshufd m10, m3, q1032 ; 7 _ + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + punpcklwd m3, m10 ; 67 + mova [rsp+0x40], m7 + mova [rsp+0x50], m8 + mova [rsp+0x60], m9 +%else + mova [stk+0x00], m12 + mova [stk+0x10], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x40 ; 0 1 + MC_4TAP_SCALED_H 0x50 ; 2 3 + MC_4TAP_SCALED_H 0x60 ; 4 5 + MC_4TAP_SCALED_H 0x70 ; 6 7 + mova m4, [stk+0x40] + mova m5, [stk+0x50] + mova m6, [stk+0x60] + mova m7, [stk+0x70] + mov [stk+0xc0], r4 + shufps m1, m4, m5, q1032 ; 1 2 + shufps m2, m5, m6, q1032 ; 3 4 + shufps m3, m6, m7, q1032 ; 5 6 + pshufd m0, m7, q1032 ; 7 _ + mova [stk+0xb0], m0 + punpcklwd m0, m4, m1 ; 01 + punpckhwd m4, m1 ; 12 + punpcklwd m1, m5, m2 ; 23 + punpckhwd m5, m2 ; 34 + punpcklwd m2, m6, m3 ; 45 + punpckhwd m6, m3 ; 56 + punpcklwd m3, m7, [stk+0xb0] ; 67 + mov myd, mym + mov r0, r0m + mova [stk+0x40], m0 ; 01 + mova [stk+0x50], m1 ; 23 + mova [stk+0x60], m2 ; 45 + mova [stk+0x70], m3 ; 67 + mova [stk+0x80], m4 ; 12 + mova [stk+0x90], m5 ; 34 + mova [stk+0xa0], m6 ; 56 + %define m12 [stk+0x00] + %define m14 [stk+0x10] + %define m13 [stk+0x20] + %define m15 [stk+0x30] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%endif +.w4_loop: + and myd, 0x3ff +%if ARCH_X86_64 + mov r11d, 64 << 24 + mov r13d, myd + shr r13d, 6 + lea r13d, [t1+r13] + cmovnz r11q, [base+subpel_filters+r13*8] + movq m9, r11q + punpcklbw m9, m9 + psraw m9, 8 + pshufd m7, m9, q0000 + pshufd m8, m9, q1111 + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pshufd m7, m9, q2222 + pshufd m9, m9, q3333 + pmaddwd m6, m2, m7 + pmaddwd m8, m3, m9 + %if isput + movd m9, [rsp+0x28] + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif + paddd m4, m5 + paddd m6, m8 + paddd m4, m6 + paddd m4, vrnd_mem +%else + mov mym, myd + mov r5, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m0, m4 + pmaddwd m1, m5 + pmaddwd m2, m6 + pmaddwd m3, m7 + %if isput + movd m4, [esp+0x18] + %endif + paddd m0, m1 + paddd m2, m3 + paddd m0, vrnd_mem + paddd m0, m2 + SWAP m4, m0 + %define m9 m0 +%endif +%if isput + pxor m5, m5 + psrad m4, m9 + packssdw m4, m4 + pmaxsw m4, m5 + pminsw m4, pxmaxm + movq [dstq], m4 + add dstq, dsmp +%else + psrad m4, 6 + packssdw m4, m4 + movq [tmpq], m4 + add tmpq, 8 +%endif + dec hd + jz .ret +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + mova m8, [rsp+0x10] + movd m9, [rsp+0x20] + movu m4, [srcq] + movu m5, [srcq+r4] + test myd, 0x400 + jz .w4_skip_line + mova m0, [rsp+0x40] + mova [rsp+0x40], m1 + mova m1, [rsp+0x50] + mova [rsp+0x50], m2 + mova m2, [rsp+0x60] + mova [rsp+0x60], m3 + pshufb m4, m12 + pshufb m5, m14 + pmaddwd m4, m13 + pmaddwd m5, m15 + phaddd m4, m5 + paddd m4, m8 + psrad m4, m9 + packssdw m4, m4 + punpcklwd m3, m10, m4 + mova m10, m4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu m6, [srcq+ssq*1] + movu m7, [srcq+r6] + mova m0, [rsp+0x50] + mova m11, [rsp+0x60] + pshufb m4, m12 + pshufb m6, m12 + pshufb m5, m14 + pshufb m7, m14 + pmaddwd m4, m13 + pmaddwd m6, m13 + pmaddwd m5, m15 + pmaddwd m7, m15 + mova [rsp+0x40], m0 + mova [rsp+0x50], m11 + phaddd m4, m5 + phaddd m6, m7 + paddd m4, m8 + paddd m6, m8 + psrad m4, m9 + psrad m6, m9 + packssdw m4, m6 + punpcklwd m9, m10, m4 + mova [rsp+0x60], m9 + pshufd m10, m4, q1032 + mova m0, m1 + mova m1, m2 + mova m2, m3 + punpcklwd m3, m4, m10 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +%else + SWAP m0, m4 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + jnz .w4_next_line + mova m0, [stk+0x40] + mova m1, [stk+0x50] + mova m2, [stk+0x60] + mova m3, [stk+0x70] + jmp .w4_loop +.w4_next_line: + mov r5, [stk+0xc0] + movu m4, [srcq] + movu m5, [r5] + test myd, 0x400 + jz .w4_skip_line + add [stk+0xc0], ssq + mova m0, [stk+0x80] + mova m3, [stk+0x50] + mova [stk+0x40], m0 + mova [stk+0x80], m3 + mova m1, [stk+0x90] + mova m6, [stk+0x60] + mova [stk+0x50], m1 + mova [stk+0x90], m6 + mova m2, [stk+0xa0] + mova m7, [stk+0x70] + mova [stk+0x60], m2 + mova [stk+0xa0], m7 + pshufb m4, m12 + pshufb m5, m14 + pmaddwd m4, m13 + pmaddwd m5, m15 + phaddd m4, m5 + paddd m4, hrnd_mem + psrad m4, hsh_mem + packssdw m4, m4 + punpcklwd m3, [stk+0xb0], m4 + mova [stk+0xb0], m4 + mova [stk+0x70], m3 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu m6, [srcq+ssq*1] + movu m7, [r5 +ssq*1] + lea r5, [r5 +ssq*2] + mov [stk+0xc0], r5 + mova m0, [stk+0x50] + mova m1, [stk+0x60] + mova m2, [stk+0x70] + mova m3, [stk+0x90] + pshufb m4, m12 + pshufb m6, m12 + pshufb m5, m14 + pshufb m7, m14 + pmaddwd m4, m13 + pmaddwd m6, m13 + pmaddwd m5, m15 + pmaddwd m7, m15 + mova [stk+0x40], m0 + mova [stk+0x50], m1 + mova [stk+0x60], m2 + mova [stk+0x80], m3 + phaddd m4, m5 + phaddd m6, m7 + mova m5, [stk+0xa0] + mova m7, [stk+0xb0] + paddd m4, hrnd_mem + paddd m6, hrnd_mem + psrad m4, hsh_mem + psrad m6, hsh_mem + packssdw m4, m6 + punpcklwd m7, m4 + pshufd m6, m4, q1032 + mova [stk+0x90], m5 + mova [stk+0xa0], m7 + mova [stk+0xb0], m6 + punpcklwd m3, m4, m6 + mova [stk+0x70], m3 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +%endif +INIT_XMM ssse3 +%if ARCH_X86_64 + %define stk rsp+0x20 +%endif +.w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.w_start: +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + %define hround m11 + shr t0d, 16 + movd m15, t0d + %if isprep + mova m13, [base+pd_m524256] + %endif +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq ssm + %endif + mov r4, [esp+0x1f0] + shr r4, 16 + movd m15, r4 + mov r0, r0m + mov myd, mym +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + mov r5, hm + mov [stk+0x0f4], myd + mov [stk+0x134], r5 +%endif + jmp .hloop +.hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov myd, [stk+0x0f4] + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov mym, myd + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + mov myd, mym + mov dyd, dym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m5, m11, q0000 + pshufd m7, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m4, m5, m0 + pmaddwd m5, m5, m1 + pmaddwd m6, m7, m2 + pmaddwd m7, m7, m3 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m10 + pmaddwd m7, [stk+0xa0], m10 + pmaddwd m8, [stk+0xb0], m11 + pmaddwd m9, [stk+0xc0], m11 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov myd, mym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.vloop: + mov r0, r0m + mov r5, [esp+0x1f4] + and myd, 0x3ff + mov mym, myd + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [stk+0x140], myd + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + jz .skip_line + mova m14, [base+unpckw] + movu m8, [srcq+r10*2] + movu m9, [srcq+r11*2] + movu m10, [srcq+r13*2] + movu m11, [srcq+ rX*2] + movu m4, [srcq+ r4*2] + movu m5, [srcq+ r6*2] + movu m6, [srcq+ r7*2] + movu m7, [srcq+ r9*2] + add srcq, ssq + mov myd, [stk+0x140] + mov dyd, dym + pshufd m15, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m15 ; 3a 2a + pshufb m3, m15 ; 3b 2b + pmaddwd m8, [stk+0x50] + pmaddwd m9, [stk+0x60] + pmaddwd m10, [stk+0x70] + pmaddwd m11, [stk+0x80] + pmaddwd m4, [stk+0x10] + pmaddwd m5, [stk+0x20] + pmaddwd m6, [stk+0x30] + pmaddwd m7, [stk+0x40] + phaddd m8, m9 + phaddd m10, m11 + mova m11, hround + phaddd m4, m5 + phaddd m6, m7 + phaddd m8, m10 + phaddd m4, m6 + paddd m4, m11 + paddd m8, m11 + psrad m4, m12 + psrad m8, m12 + packssdw m4, m8 + pshufb m5, [stk+0x90], m14 ; 4a 5a + pshufb m6, [stk+0xa0], m14 ; 4b 5b + pshufb m7, [stk+0xb0], m15 ; 7a 6a + pshufb m8, [stk+0xc0], m15 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + punpckhwd m5, m7 ; 56a + punpckhwd m6, m8 ; 56b + punpcklwd m7, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m8, m4 ; 78b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m8 + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 10, 11 + MC_8TAP_SCALED_H 8, 5, 6, 7, 9, 0, 10, 11 + mov myd, [stk+0x140] + mov dyd, dym + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [stk+0x90] ; 23a + mova m3, [stk+0xa0] ; 23b + mova m5, [stk+0xb0] ; 45a + mova m6, [stk+0xc0] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m4 +%else + mov r0m, r0 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + mov mym, myd + jnz .next_line + mova m0, [stk+0x20] + mova m1, [stk+0x30] + mova m2, [stk+0x40] + mova m3, [stk+0x50] + jmp .vloop +.next_line: + test myd, 0x400 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + jz .skip_line + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + mova m7, [base+unpckw] + pshufd m4, m7, q1032 + pshufb m0, [stk+0x20], m7 ; 0a 1a + pshufb m1, [stk+0x30], m7 ; 0b 1b + pshufb m2, [stk+0x40], m4 ; 3a 2a + pshufb m3, [stk+0x50], m4 ; 3b 2b + pshufb m5, [stk+0x60], m7 ; 4a 5a + pshufb m6, [stk+0x70], m7 ; 4b 5b + pshufb m7, [stk+0x80], m4 ; 7a 6a + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + punpckhwd m5, m7 ; 56a + mova [stk+0x60], m5 + pshufb m5, [stk+0x90], m4 ; 7b 6b + punpcklwd m7, [stk+0xe0] ; 78a + punpckhwd m6, m5 ; 56b + mova [stk+0x70], m6 + movq m6, [stk+0xe8] + mova [stk+0x80], m7 + punpcklwd m5, m6 + mov myd, mym + mova [stk+0x90], m5 + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + MC_8TAP_SCALED_H 0xa0, 0 ; 9 + mova m7, [stk+0xe0] + mova m2, [stk+0x60] ; 23a + mova m3, [stk+0x70] ; 23b + mova m4, [stk+0x80] ; 45a + mova m5, [stk+0x90] ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova m0, [stk+0x40] ; 01a + mova m1, [stk+0x50] ; 01b + mov myd, mym + mova [stk+0x40], m2 + mova [stk+0x50], m3 + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova [stk+0x20], m0 + mova [stk+0x30], m1 +%endif + jmp .vloop +INIT_XMM ssse3 +.dy1: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy1_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy1_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + %define m11 [esp+0x00] + %define m12 [esp+0x10] + %define m13 [esp+0x20] + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 + mov r1, r1m + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + mov [stk+0x20], r3 + mov r3, r3m + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2, m3 + REPX {pmaddwd x, m15}, m0, m1, m2, m3 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6 + REPX {pmaddwd x, m15}, m4, m5, m6 + phaddd m0, m1 + phaddd m2, m3 + phaddd m4, m5 + phaddd m6, m6 + REPX {paddd x, m11}, m0, m2, m4, m6 + REPX {psrad x, m12}, m0, m2, m4, m6 + packssdw m0, m2 ; 0 1 2 3 + packssdw m4, m6 ; 4 5 6 + SWAP m1, m4 + movq m10, r4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m2, m3 + movu m1, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + REPX {pshufb x, m14}, m1, m7, m6 + REPX {pmaddwd x, m15}, m1, m7, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + phaddd m1, m7 + phaddd m6, m6 + REPX {paddd x, m11}, m0, m2, m1, m6 + REPX {psrad x, m12}, m0, m2, m1, m6 + packssdw m0, m2 + packssdw m1, m6 + %define m8 m6 + %define m9 m4 + %define m10 m5 + movd m10, r4 + movd m9, [stk+0x20] + punpckldq m10, m9 + %endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + %if ARCH_X86_32 + mova [stk+0x50], m7 + mova [stk+0x60], m8 + mova [stk+0x70], m9 + mova [stk+0x80], m10 + %define m7 [stk+0x50] + %define m8 [stk+0x60] + %define m9 [stk+0x70] + %define m10 [stk+0x80] + %endif + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m4, m1, q2121 ; 5 6 5 6 + punpcklwd m2, m1, m4 ; 45 56 + %if ARCH_X86_32 + mov r0, r0m + %endif +.dy1_w2_loop: + movu m1, [srcq+ssq*0] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m3, m7 + mova m3, m0 + pmaddwd m0, m8 + pshufb m1, m14 + pshufb m6, m14 + pmaddwd m1, m15 + pmaddwd m6, m15 + phaddd m1, m6 + paddd m1, m11 + psrad m1, m12 + packssdw m1, m1 + paddd m5, m0 + mova m0, m2 + pmaddwd m2, m9 + paddd m5, m2 + palignr m2, m1, m4, 12 + punpcklwd m2, m1 ; 67 78 + pmaddwd m4, m2, m10 + paddd m5, m13 + paddd m5, m4 + pxor m6, m6 + mova m4, m1 + pshufd m1, m12, q1032 + psrad m5, m1 + packssdw m5, m5 + pmaxsw m5, m6 + pminsw m5, pxmaxm + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q1032 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy1_w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %define vrnd_mem [rsp+0x30] + %define stk rsp+0x40 + %else + %define vrnd_mem [base+pd_m524256] + %define stk rsp+0x30 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m9 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd rX, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + SWAP m4, m7 + %if isprep + mov r3, r3m + %endif + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x40], m13 + mova [stk+0x50], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + movu m1, [srcq+r4 ] + movu m3, [srcq+r6 ] + movu m2, [srcq+r11 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m7, m9, m8, m10 + REPX {pmaddwd x, m13}, m7, m9, m8, m10 + REPX {pshufb x, m14}, m1, m3, m2, m4 + REPX {pmaddwd x, m15}, m1, m3, m2, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m7, m1 + phaddd m9, m3 + phaddd m8, m2 + phaddd m10, m4 + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + REPX {paddd x, m5}, m7, m9, m8, m10 + REPX {psrad x, xm6}, m7, m9, m8, m10 + packssdw m7, m9 ; 0 1 + packssdw m8, m10 ; 2 3 + movu m0, [srcq+r4 ] + movu m9, [srcq+r6 ] + movu m10, [srcq+r11 ] + add srcq, ss3q + REPX {pshufb x, m12}, m1, m2, m3 + REPX {pmaddwd x, m13}, m1, m2, m3 + REPX {pshufb x, m14}, m0, m9, m10 + REPX {pmaddwd x, m15}, m0, m9, m10 + phaddd m1, m0 + phaddd m2, m9 + phaddd m3, m10 + shr myd, 6 + mov r13d, 64 << 24 + lea myd, [t1+myq] + cmovnz r13q, [base+subpel_filters+myq*8] + REPX {paddd x, m5}, m1, m2, m3 + REPX {psrad x, xm6}, m1, m2, m3 + packssdw m1, m2 ; 4 5 + packssdw m3, m3 ; 6 6 + SWAP m9, m1 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + movq m10, r13 + mova [stk+0x00], m1 + mova [stk+0x10], m8 + mova [stk+0x20], m2 + mova [stk+0x30], m9 + mova [stk+0x40], m3 + %define hrnd_mem [rsp+0x10] + %define hsh_mem [rsp+0x20] + %define vsh_mem [rsp+0x28] + %if isput + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%else + mova [stk+0x20], m12 + mova [stk+0x30], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x60 ; 0 1 + MC_4TAP_SCALED_H 0x70 ; 2 3 + MC_4TAP_SCALED_H 0x80 ; 4 5 + movu m7, [srcq] + movu m2, [r4] + add srcq, ssq + add r4, ssq + mov [stk+0xb0], r4 + pshufb m7, m12 + pshufb m2, m14 + pmaddwd m7, m13 + pmaddwd m2, m15 + phaddd m7, m2 + paddd m7, [esp+0x00] + psrad m7, [esp+0x10] + packssdw m7, m7 ; 6 6 + mova m4, [stk+0x60] + mova m5, [stk+0x70] + mova m6, [stk+0x80] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + shufps m1, m4, m5, q1032 ; 1 2 + shufps m2, m5, m6, q1032 ; 3 4 + shufps m3, m6, m7, q1032 ; 5 6 + mova [stk+0xa0], m7 + punpcklwd m0, m4, m1 ; 01 + punpckhwd m4, m1 ; 12 + punpcklwd m1, m5, m2 ; 23 + punpckhwd m5, m2 ; 34 + punpcklwd m2, m6, m3 ; 45 + punpckhwd m6, m3 ; 56 + movd m7, r4 + movd m3, r5 + mov r0, r0m + %if isput + mov r1, r1m + %endif + mov r4, [stk+0xb0] + mova [stk+0xc0], m4 ; 12 + mova [stk+0x60], m1 ; 23 + mova [stk+0x70], m2 ; 45 + mova [stk+0x80], m5 ; 34 + mova [stk+0x90], m6 ; 56 + %define m12 [stk+0x20] + %define m14 [stk+0x30] + %define m13 [stk+0x40] + %define m15 [stk+0x50] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %define vsh_mem [esp+0x18] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif + %define m10 m7 + punpckldq m10, m3 +%endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m3, m10, q0000 + pshufd m4, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_32 + %xdefine m8 m3 + %xdefine m9 m6 + %xdefine m11 m5 + %xdefine m6 m4 + mova [stk+0x100], m3 + mova [stk+0x110], m4 + mova [stk+0x120], m5 + mova [stk+0x130], m10 + %define m3 [stk+0x100] + %define m4 [stk+0x110] + %define m5 [stk+0x120] + %define m10 [stk+0x130] + mova m7, [stk+0xc0] + mova m8, [stk+0x80] +%endif +.dy1_w4_loop: + movu m11, [srcq+ssq*0] + movu m6, [srcq+ssq*1] + pmaddwd m0, m3 + pmaddwd m7, m3 + pmaddwd m1, m4 + pmaddwd m8, m4 + pmaddwd m2, m5 + pmaddwd m9, m5 + paddd m1, m0 + paddd m8, m7 +%if ARCH_X86_64 + movu m0, [srcq+r4] + movu m7, [srcq+r6] +%else + movu m0, [r4+ssq*0] + movu m7, [r4+ssq*1] + lea r4, [r4+ssq*2] +%endif + lea srcq, [srcq+ssq*2] + paddd m1, m2 + paddd m8, m9 + pshufb m11, m12 + pshufb m6, m12 + pmaddwd m11, m13 + pmaddwd m6, m13 + pshufb m0, m14 + pshufb m7, m14 + pmaddwd m0, m15 + pmaddwd m7, m15 + phaddd m11, m0 + phaddd m6, m7 + paddd m11, hrnd_mem + paddd m6, hrnd_mem + psrad m11, hsh_mem + psrad m6, hsh_mem + packssdw m11, m6 ; 7 8 +%if ARCH_X86_64 + shufps m9, [stk+0x40], m11, q1032 ; 6 7 + mova m0, [stk+0x00] + mova [stk+0x40], m11 +%else + shufps m9, [stk+0xa0], m11, q1032 ; 6 7 + mova m0, [stk+0x60] + mova [stk+0xa0], m11 +%endif + punpcklwd m2, m9, m11 ; 67 + punpckhwd m9, m11 ; 78 + pmaddwd m6, m2, m10 + pmaddwd m7, m9, m10 +%if isput + movd m11, vsh_mem +%endif + paddd m1, vrnd_mem + paddd m8, vrnd_mem + paddd m1, m6 + paddd m8, m7 +%if ARCH_X86_64 + mova m7, [stk+0x10] +%else + mova m7, [stk+0x80] +%endif +%if isput + psrad m1, m11 + psrad m8, m11 +%else + psrad m1, 6 + psrad m8, 6 +%endif + packssdw m1, m8 +%if ARCH_X86_64 + mova m8, [stk+0x30] +%else + mova m8, [stk+0x90] +%endif +%if isput + pxor m6, m6 + pmaxsw m1, m6 + pminsw m1, pxmaxm + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m1 + add tmpq, 16 +%endif +%if ARCH_X86_64 + mova m1, [stk+0x20] + mova [stk+0x10], m8 + mova [stk+0x00], m1 + mova [stk+0x20], m2 + mova [stk+0x30], m9 +%else + mova m1, [stk+0x70] + mova [stk+0x80], m8 + mova [stk+0x60], m1 + mova [stk+0x70], m2 + mova [stk+0x90], m9 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET ; why not jz .ret? +INIT_XMM ssse3 +.dy1_w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %define hround m11 + %if isput + mova [rsp+0x30], m13 + %else + mova m13, [base+pd_m524256] + %endif + shr t0d, 16 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + SWAP m3, m5 +%endif + punpcklbw m3, m3 + psraw m3, 8 + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 +%if ARCH_X86_64 + mova [stk+0x140], m0 + mova [stk+0x150], m1 + mova [stk+0x160], m2 + mova [stk+0x170], m3 + %if UNIX64 + mov hm, hd + %endif +%else + mova [stk+0x180], m0 + mova [stk+0x190], m1 + mova [stk+0x1a0], m2 + mova [stk+0x1b0], m3 + SWAP m5, m3 + mov r5, hm + mov [stk+0x134], r5 +%endif + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy1_hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova m10, [stk+0x140] + mova m11, [stk+0x150] + mova m14, [stk+0x160] + mova m15, [stk+0x170] + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] + %define shift [rsp+0x20] + %if isput + %define vround [rsp+0x30] + %else + %define vround [base+pd_m524256] + %endif +.dy1_vloop: + pmaddwd m4, m0, m10 + pmaddwd m5, m1, m10 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m11 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m14 + pmaddwd m7, [stk+0xa0], m14 + pmaddwd m8, [stk+0xb0], m15 + pmaddwd m9, [stk+0xc0], m15 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov r0, r0m + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.dy1_vloop: + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep +%if ARCH_X86_64 + movu m8, [srcq+r10*2] + movu m9, [srcq+r11*2] + movu m12, [srcq+r13*2] + movu m13, [srcq+ rX*2] + movu m4, [srcq+ r4*2] + movu m5, [srcq+ r6*2] + movu m6, [srcq+ r7*2] + movu m7, [srcq+ r9*2] + add srcq, ssq + pmaddwd m8, [stk+0x50] + pmaddwd m9, [stk+0x60] + pmaddwd m12, [stk+0x70] + pmaddwd m13, [stk+0x80] + pmaddwd m4, [stk+0x10] + pmaddwd m5, [stk+0x20] + pmaddwd m6, [stk+0x30] + pmaddwd m7, [stk+0x40] + phaddd m8, m9 + phaddd m12, m13 + mova m9, [base+unpckw] + mova m13, hround + phaddd m4, m5 + phaddd m6, m7 + phaddd m8, m12 + phaddd m4, m6 + pshufd m5, m9, q1032 + pshufb m0, m9 ; 0a 1a + pshufb m1, m9 ; 0b 1b + pshufb m2, m5 ; 3a 2a + pshufb m3, m5 ; 3b 2b + mova m12, shift + paddd m4, m13 + paddd m8, m13 + psrad m4, m12 + psrad m8, m12 + packssdw m4, m8 + pshufb m6, [stk+0x90], m9 ; 4a 5a + pshufb m7, [stk+0xa0], m9 ; 4b 5b + pshufb m8, [stk+0xb0], m5 ; 7a 6a + pshufb m13, [stk+0xc0], m5 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m6 ; 34a + punpcklwd m3, m7 ; 34b + punpckhwd m6, m8 ; 56a + punpckhwd m7, m13 ; 56b + punpcklwd m8, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m13, m4 ; 78b + mova [stk+0x90], m6 + mova [stk+0xa0], m7 + mova [stk+0xb0], m8 + mova [stk+0xc0], m13 + mova m13, vround +%else + mov r0m, r0 + mov r3, r3m + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + MC_8TAP_SCALED_H 0xa0, 0xe0, 0 ; 8 + mova m7, [base+unpckw] + pshufd m4, m7, q1032 + pshufb m0, [stk+0x20], m7 ; 0a 1a + pshufb m1, [stk+0x30], m7 ; 0b 1b + pshufb m2, [stk+0x40], m4 ; 3a 2a + pshufb m3, [stk+0x50], m4 ; 3b 2b + pshufb m5, [stk+0x60], m7 ; 4a 5a + pshufb m6, [stk+0x70], m7 ; 4b 5b + pshufb m7, [stk+0x80], m4 ; 7a 6a + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + punpckhwd m5, m7 ; 56a + mova [stk+0x60], m5 + pshufb m5, [stk+0x90], m4 ; 7b 6b + punpcklwd m7, [stk+0xe0] ; 78a + mova m4, [stk+0x180] + punpckhwd m6, m5 ; 56b + mova [stk+0x70], m6 + movq m6, [stk+0xe8] + mova [stk+0x80], m7 + mova m7, [stk+0x1b0] + punpcklwd m5, m6 + mova m6, [stk+0x1a0] + mova [stk+0x90], m5 + mova m5, [stk+0x190] + mov r0, r0m +%endif + jmp .dy1_vloop +INIT_XMM ssse3 +%if ARCH_X86_64 + %define stk rsp+0x20 +%endif +.dy2: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy2_table+wq*2] + add wq, base_reg + jmp wq +%if isput +.dy2_w2: + %if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m13 + %define vrnd_mem [rsp+0x10] + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + %define m11 [esp+0x00] + %define m12 [esp+0x10] + %define vrnd_mem [esp+0x20] + mov r1, r1m + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 + %endif + pxor m9, m9 + punpckldq m9, m8 + paddd m14, m9 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m9, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + pshufd m15, m15, q0321 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_q] + mova m6, [base+spel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m2, m2 + pcmpeqd m8, m2 + psrld m14, 10 + paddd m14, m14 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [stk], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m15 m6 + %endif + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*2] + movu m2, [srcq+ssq*4] + punpckldq m15, m7 + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + pand m9, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m9 + movu m4, [srcq+ssq*1] + movu m5, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + %else + pand m7, m5, [base+pd_0x4000] + pandn m5, m15 + por m5, m7 + %define m15 m5 + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + mov [stk+0x20], r3 + mov r3, r3m + %endif + punpcklbw m15, m15 + psraw m15, 8 + REPX {pshufb x, m14}, m0, m1, m2 + REPX {pmaddwd x, m15}, m0, m1, m2 + %if ARCH_X86_64 + REPX {pshufb x, m14}, m4, m5, m6 + REPX {pmaddwd x, m15}, m4, m5, m6 + phaddd m0, m1 + phaddd m1, m2 + phaddd m4, m5 + phaddd m5, m6 + REPX {paddd x, m11}, m0, m1, m4, m5 + REPX {psrad x, m12}, m0, m1, m4, m5 + packssdw m0, m1 ; 0 2 2 4 + packssdw m4, m5 ; 1 3 3 5 + SWAP m2, m4 + movq m10, r4 + %else + mova [stk+0x10], m15 + phaddd m0, m1 + phaddd m1, m2 + movu m2, [srcq+ssq*1] + movu m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m6, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + REPX {pshufb x, m14}, m2, m7, m6 + REPX {pmaddwd x, m15}, m2, m7, m6 + %define m14 [stk+0x00] + %define m15 [stk+0x10] + phaddd m2, m7 + phaddd m7, m6 + REPX {paddd x, m11}, m0, m1, m2, m7 + REPX {psrad x, m12}, m0, m1, m2, m7 + packssdw m0, m1 + packssdw m2, m7 + %define m8 m6 + %define m9 m4 + %define m10 m5 + movd m10, r4 + movd m9, [stk+0x20] + punpckldq m10, m9 + %endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + %if ARCH_X86_32 + mova [stk+0x50], m7 + mova [stk+0x60], m8 + mova [stk+0x70], m9 + mova [stk+0x80], m10 + %xdefine m13 m7 + %define m7 [stk+0x50] + %define m8 [stk+0x60] + %define m9 [stk+0x70] + %define m10 [stk+0x80] + %endif + punpcklwd m1, m0, m2 ; 01 23 + punpckhwd m3, m0, m2 ; 23 45 + %if ARCH_X86_32 + mov r4, r0m + %define dstq r4 + mova [stk+0x20], m3 + mova [stk+0x30], m0 + %endif +.dy2_w2_loop: + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + movu m13, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd m3, m8 + REPX {pshufb x, m14}, m4, m5, m6, m13 + REPX {pmaddwd x, m15}, m4, m5, m6, m13 + phaddd m4, m5 + phaddd m6, m13 + pmaddwd m5, m1, m7 + paddd m4, m11 + paddd m6, m11 + psrad m4, m12 + psrad m6, m12 + packssdw m4, m6 ; 6 7 8 9 + paddd m5, m3 + pshufd m3, m4, q2200 + pshufd m4, m4, q3311 + palignr m3, m0, 12 ; 4 6 6 8 + palignr m4, m2, 12 ; 5 7 7 9 + mova m0, m3 + mova m2, m4 + punpcklwd m1, m3, m4 + punpckhwd m3, m4 + pmaddwd m6, m1, m9 + pmaddwd m4, m3, m10 + paddd m5, vrnd_mem + paddd m6, m4 + paddd m5, m6 + pshufd m4, m12, q1032 + pxor m6, m6 + psrad m5, m4 + packssdw m5, m5 + pmaxsw m5, m6 + pminsw m5, pxmaxm + movd [dstq+dsq*0], m5 + pshuflw m5, m5, q1032 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy2_w4: +%if ARCH_X86_64 + mov myd, mym + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %if isput + mova [rsp+0x30], m13 + %define vrnd_mem [rsp+0x30] + %define stk rsp+0x40 + %else + %define vrnd_mem [base+pd_m524256] + %define stk rsp+0x30 + %endif + movzx t0d, t0b + sub srcq, 2 + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m9 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r5, byte [esp+0x1f0] + sub srcq, 2 + movd m15, r5 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m9, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + pshufd m7, m15, q1032 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r6d, m15 + movd r13d, m7 + mova m10, [base+bdct_lb_q+ 0] + mova m11, [base+bdct_lb_q+16] + movd m13, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+ r6*8+2] + movd m15, [base+subpel_filters+r11*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r1, m15 + movd r4, m7 + pshufd m15, m15, q0321 + pshufd m7, m7, q0321 + movd r3, m15 + movd r5, m7 + mova m5, [base+bdct_lb_q+ 0] + mova m6, [base+bdct_lb_q+16] + movd m1, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + SWAP m4, m7 + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif + %define m10 m5 + %define m11 m6 + %define m12 m1 + %define m13 m1 +%endif + psrld m14, 10 + paddd m14, m14 + punpckldq m13, m2 + punpckldq m15, m4 + punpcklqdq m13, m15 + pxor m2, m2 + pcmpeqd m0, m2 +%if ARCH_X86_64 + pand m9, m0 +%else + pand m2, m9, m0 + %define m9 m2 + SWAP m7, m4 +%endif + pandn m0, m13 +%if ARCH_X86_64 + SWAP m13, m0 +%else + %define m13 m0 +%endif + por m13, m9 + punpckhbw m15, m13, m13 + punpcklbw m13, m13 + psraw m15, 8 + psraw m13, 8 + pshufb m12, m14, m10 + pshufb m14, m11 + mova m10, [base+spel_s_shuf2] + movd r4d, m14 + shr r4d, 24 +%if ARCH_X86_32 + mova [stk+0x40], m13 + mova [stk+0x50], m15 + pxor m2, m2 +%endif + pshufb m7, m14, m2 + psubb m14, m7 + paddb m12, m10 + paddb m14, m10 +%if ARCH_X86_64 + lea r6, [r4+ssq*1] + lea r11, [r4+ssq*2] + lea r13, [r4+ss3q ] + movu m1, [srcq+ssq*0] + movu m8, [srcq+ssq*2] + movu m9, [srcq+ssq*1] + movu m10, [srcq+ss3q ] + movu m7, [srcq+r4 ] + movu m2, [srcq+r11 ] + movu m3, [srcq+r6 ] + movu m4, [srcq+r13 ] + lea srcq, [srcq+ssq*4] + REPX {pshufb x, m12}, m1, m9, m8, m10 + REPX {pmaddwd x, m13}, m1, m9, m8, m10 + REPX {pshufb x, m14}, m7, m3, m2, m4 + REPX {pmaddwd x, m15}, m7, m3, m2, m4 + mova m5, [rsp+0x10] + movd xm6, [rsp+0x20] + phaddd m1, m7 + phaddd m8, m2 + phaddd m9, m3 + phaddd m10, m4 + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + REPX {paddd x, m5}, m1, m9, m8, m10 + REPX {psrad x, xm6}, m1, m9, m8, m10 + packssdw m1, m8 ; 0 2 + packssdw m9, m10 ; 1 3 + movu m0, [srcq+r4 ] + movu m8, [srcq+r6 ] + lea srcq, [srcq+ssq*2] + REPX {pshufb x, m12}, m2, m3 + REPX {pmaddwd x, m13}, m2, m3 + REPX {pshufb x, m14}, m0, m8 + REPX {pmaddwd x, m15}, m0, m8 + phaddd m2, m0 + phaddd m3, m8 + shr myd, 6 + mov r9d, 64 << 24 + lea myd, [t1+myq] + cmovnz r9q, [base+subpel_filters+myq*8] + REPX {paddd x, m5}, m2, m3 + REPX {psrad x, xm6}, m2, m3 + packssdw m2, m3 ; 4 5 + pshufd m3, m2, q1032 ; 5 _ + punpcklwd m0, m1, m9 ; 01 + punpckhwd m1, m9 ; 23 + punpcklwd m2, m3 ; 45 + movq m10, r9 + %define hrnd_mem [rsp+0x10] + %define hsh_mem [rsp+0x20] + %define vsh_mem [rsp+0x28] + %if isput + %define vrnd_mem [rsp+0x30] + %else + %define vrnd_mem [base+pd_m524256] + %endif +%else + mova [stk+0x20], m12 + mova [stk+0x30], m14 + add r4, srcq + MC_4TAP_SCALED_H 0x60 ; 0 1 + MC_4TAP_SCALED_H 0x70 ; 2 3 + MC_4TAP_SCALED_H 0x80 ; 4 5 + mov [stk+0xe0], r4 + mova m3, [base+spel_s_shuf8] + mova m0, [stk+0x60] + mova m1, [stk+0x70] + mova m2, [stk+0x80] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + pshufb m0, m3 ; 01 + pshufb m1, m3 ; 23 + pshufb m2, m3 ; 45 + movd m7, r4 + movd m4, r5 + mov r5, r0m + %if isput + mov r1, r1m + %endif + mov r4, [stk+0xe0] + %define dstq r5 + %define tmpq r5 + %define m12 [stk+0x20] + %define m14 [stk+0x30] + %define m13 [stk+0x40] + %define m15 [stk+0x50] + %define hrnd_mem [esp+0x00] + %define hsh_mem [esp+0x10] + %define vsh_mem [esp+0x18] + %if isput + %define vrnd_mem [esp+0x20] + %else + %define vrnd_mem [base+pd_m524256] + %endif + %define m10 m7 + punpckldq m10, m4 +%endif + punpcklbw m10, m10 + psraw m10, 8 + pshufd m3, m10, q0000 + pshufd m4, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_32 + %xdefine m8 m3 + %xdefine m9 m6 + %xdefine m11 m5 + %xdefine m6 m4 + mova [stk+0x100], m3 + mova [stk+0x110], m4 + mova [stk+0x120], m5 + mova [stk+0x130], m10 + %define m3 [stk+0x100] + %define m4 [stk+0x110] + %define m5 [stk+0x120] + %define m10 [stk+0x130] +%endif +.dy2_w4_loop: + pmaddwd m8, m0, m3 + pmaddwd m9, m1, m3 + mova m0, m2 + pmaddwd m1, m4 + pmaddwd m11, m2, m4 + paddd m8, vrnd_mem + paddd m9, vrnd_mem + pmaddwd m2, m5 + paddd m8, m1 + paddd m9, m11 + paddd m8, m2 + movu m6, [srcq+ssq*0] + movu m1, [srcq+ssq*2] +%if ARCH_X86_64 + movu m11, [srcq+r4 ] + movu m2, [srcq+r11] +%else + movu m11, [r4+ssq*0] + movu m2, [r4+ssq*2] +%endif + pshufb m6, m12 + pshufb m1, m12 + pmaddwd m6, m13 + pmaddwd m1, m13 + pshufb m11, m14 + pshufb m2, m14 + pmaddwd m11, m15 + pmaddwd m2, m15 + phaddd m6, m11 + phaddd m1, m2 + paddd m6, hrnd_mem + paddd m1, hrnd_mem + psrad m6, hsh_mem + psrad m1, hsh_mem + movu m7, [srcq+ssq*1] + movu m11, [srcq+ss3q ] + packssdw m6, m1 ; 6 8 +%if ARCH_X86_64 + movu m2, [srcq+r6 ] + movu m1, [srcq+r13] +%else + movu m2, [r4+ssq*1] + movu m1, [r4+ss3q ] +%endif + pshufb m7, m12 + pshufb m11, m12 + pmaddwd m7, m13 + pmaddwd m11, m13 + pshufb m2, m14 + pshufb m1, m14 + pmaddwd m2, m15 + pmaddwd m1, m15 + phaddd m7, m2 + phaddd m11, m1 + paddd m7, hrnd_mem + paddd m11, hrnd_mem + psrad m7, hsh_mem + psrad m11, hsh_mem + packssdw m7, m11 ; 7 9 +%if ARCH_X86_32 + lea r4, [r4+ssq*4] +%endif + lea srcq, [srcq+ssq*4] + punpcklwd m1, m6, m7 ; 67 + punpckhwd m6, m7 ; 89 + mova m2, m6 + pmaddwd m11, m1, m5 + pmaddwd m7, m1, m10 + pmaddwd m6, m10 + paddd m9, m11 +%if isput + movd m11, vsh_mem +%endif + paddd m8, m7 + paddd m9, m6 +%if isput + psrad m8, m11 + psrad m9, m11 + packssdw m8, m9 + pxor m7, m7 + pmaxsw m8, m7 + pminsw m8, pxmaxm + movq [dstq+dsq*0], m8 + movhps [dstq+dsq*1], m8 + lea dstq, [dstq+dsq*2] +%else + psrad m8, 6 + psrad m9, 6 + packssdw m8, m9 + mova [tmpq], m8 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET ; why not jz .ret? +INIT_XMM ssse3 +.dy2_w8: + mov dword [stk+0xf0], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [stk+0xf0], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [stk+0xf0], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [stk+0xf0], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [stk+0xf0], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%if ARCH_X86_64 + %ifidn %1, put + movifnidn dsm, dsq + %endif + mova [rsp+0x10], m11 + mova [rsp+0x20], m12 + %define hround m11 + %if isput + mova [rsp+0x30], m13 + %else + mova m13, [base+pd_m524256] + %endif + shr t0d, 16 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define hround [esp+0x00] + %define m12 [esp+0x10] + %define m10 [base+pd_0x3ff] + %define m8 m0 + %xdefine m14 m4 + %xdefine m15 m3 + %if isput + %define dstq r0 + %else + %define tmpq r0 + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + sub srcq, 6 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + SWAP m3, m5 +%endif + punpcklbw m3, m3 + psraw m3, 8 + mova [stk+0x100], m7 + mova [stk+0x120], m15 + mov [stk+0x0f8], srcq + mov [stk+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 +%if ARCH_X86_64 + mova [stk+0x140], m0 + mova [stk+0x150], m1 + mova [stk+0x160], m2 + mova [stk+0x170], m3 + %if UNIX64 + mov hm, hd + %endif +%else + mova [stk+0x180], m0 + mova [stk+0x190], m1 + mova [stk+0x1a0], m2 + mova [stk+0x1b0], m3 + SWAP m5, m3 + mov r5, hm + mov [stk+0x134], r5 +%endif + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [stk+0x0f0] + jz .ret +%if ARCH_X86_64 + add qword [stk+0x130], 16 + mov hd, hm +%else + add dword [stk+0x130], 16 + mov r5, [stk+0x134] + mov r0, [stk+0x130] +%endif + mova m7, [stk+0x100] + mova m14, [stk+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m11, [rsp+0x10] +%endif + mova m15, [stk+0x120] + mov srcq, [stk+0x0f8] +%if ARCH_X86_64 + mov r0q, [stk+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy2_hloop: +%if ARCH_X86_64 + mova m9, [base+pq_0x40000000] +%else + %define m9 [base+pq_0x40000000] +%endif + pxor m1, m1 + psrld m2, m14, 10 + mova [stk], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m1 + pshufd m2, m5, q1032 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + pshufd m5, m5, q0321 + pshufd m2, m2, q0321 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pxor m2, m2 + pcmpeqd m5, m2 + mova [stk+0x110], m14 + pshufd m4, m15, q1032 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + movq r11, m14 + punpckhqdq m14, m14 + movq rX, m14 + mov r10d, r11d + shr r11, 32 + mov r13d, rXd + shr rX, 32 + mov r4d, [stk+ 0] + mov r6d, [stk+ 4] + mov r7d, [stk+ 8] + mov r9d, [stk+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m9, m4 + pand m8, m9, m6 + pand m15, m9, m14 + pand m9, m9, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m9, m5 + punpcklbw m0, m7, m7 + punpckhbw m7, m7 + punpcklbw m1, m8, m8 + punpckhbw m8, m8 + psraw m0, 8 + psraw m7, 8 + psraw m1, 8 + psraw m8, 8 + punpcklbw m2, m15, m15 + punpckhbw m15, m15 + punpcklbw m3, m9, m9 + punpckhbw m9, m9 + psraw m2, 8 + psraw m15, 8 + psraw m3, 8 + psraw m9, 8 + mova [stk+0x10], m0 + mova [stk+0x20], m7 + mova [stk+0x30], m1 + mova [stk+0x40], m8 + mova [stk+0x50], m2 + mova [stk+0x60], m15 + mova [stk+0x70], m3 + mova [stk+0x80], m9 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10 ; 0 + mova [stk+0x90], m1 + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 1, 9, 10 ; 1 + mova [stk+0xa0], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10 ; 2 + mova [stk+0xb0], m3 + MC_8TAP_SCALED_H 4, 5, 6, 1, 2, 3, 9, 10 ; 3 + mova [stk+0xc0], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10 ; 4 + mova [stk+0xd0], m5 + MC_8TAP_SCALED_H 6, 1, 2, 3, 4, 5, 9, 10 ; 5 + MC_8TAP_SCALED_H 7, 1, 2, 3, 4, 5, 9, 10 ; 6 + MC_8TAP_SCALED_H 8, 1, 2, 3, 4, 5, 9, 10 ; 7 + mova m5, [stk+0xd0] + mova m1, [stk+0x90] + mova m2, [stk+0xa0] + mova m3, [stk+0xb0] + mova m9, [stk+0xc0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova m10, [stk+0x140] + mova m11, [stk+0x150] + mova m14, [stk+0x160] + mova m15, [stk+0x170] + mova [stk+0x90], m4 + mova [stk+0xa0], m5 + mova [stk+0xb0], m6 + mova [stk+0xc0], m7 + %define hround [rsp+0x10] + %define shift [rsp+0x20] + %if isput + %define vround [rsp+0x30] + %else + %define vround [base+pd_m524256] + %endif +.dy2_vloop: + pmaddwd m4, m0, m10 + pmaddwd m5, m1, m10 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m11 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [stk+0x90], m14 + pmaddwd m7, [stk+0xa0], m14 + pmaddwd m8, [stk+0xb0], m15 + pmaddwd m9, [stk+0xc0], m15 + paddd m4, m6 + paddd m5, m7 + %if isput + pshufd m6, m12, q1032 + %endif + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + pshufd m15, m15, q0321 + pshufd m4, m4, q0321 + movd r4, m15 + movd r5, m4 + mova m14, [stk+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [stk+16], m14 + mov r0, [stk+ 0] + mov rX, [stk+ 4] + mov r4, [stk+ 8] + mov r5, [stk+12] + mova [stk+0x20], m0 + mova [stk+0x30], m1 + mova [stk+0x40], m2 + mova [stk+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m9, m4 + pand m1, m9, m6 + pand m2, m9, m7 + pand m3, m9, m5 + pandn m4, [stk+0x20] + pandn m6, [stk+0x30] + pandn m7, [stk+0x40] + pandn m5, [stk+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + punpcklbw m4, m0, m0 + punpckhbw m0, m0 + punpcklbw m5, m1, m1 + punpckhbw m1, m1 + psraw m4, 8 + psraw m0, 8 + psraw m5, 8 + psraw m1, 8 + punpcklbw m6, m2, m2 + punpckhbw m2, m2 + punpcklbw m7, m3, m3 + punpckhbw m3, m3 + psraw m6, 8 + psraw m2, 8 + psraw m7, 8 + psraw m3, 8 + mova [stk+0x0a0], m4 + mova [stk+0x0b0], m0 + mova [stk+0x0c0], m5 + mova [stk+0x0d0], m1 + mova [stk+0x140], m6 + mova [stk+0x150], m2 + mova [stk+0x160], m7 + mova [stk+0x170], m3 + MC_8TAP_SCALED_H 0xa0, 0x20, 0 ; 0 + MC_8TAP_SCALED_H 0xa0, 0x30 ; 1 + MC_8TAP_SCALED_H 0xa0, 0x40 ; 2 + MC_8TAP_SCALED_H 0xa0, 0x50 ; 3 + MC_8TAP_SCALED_H 0xa0, 0x60 ; 4 + MC_8TAP_SCALED_H 0xa0, 0x70 ; 5 + MC_8TAP_SCALED_H 0xa0, 0x80 ; 6 + MC_8TAP_SCALED_H 0xa0, 0x90 ; 7 + mova m5, [stk+0x60] + mova m6, [stk+0x70] + mova m7, [stk+0x80] + mova m0, [stk+0x90] + mov r0, r0m + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m1, [stk+0x20] + mova m2, [stk+0x30] + mova m3, [stk+0x40] + mova m4, [stk+0x50] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mova [stk+0x40], m2 + mova [stk+0x50], m3 +.dy2_vloop: + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [stk+0x60], m6 + pmaddwd m3, [stk+0x70], m6 + pmaddwd m4, [stk+0x80], m7 + pmaddwd m5, [stk+0x90], m7 + %if isput + movd m6, [esp+0x18] + %endif + paddd m0, m2 + paddd m1, m3 + paddd m0, vrnd_mem + paddd m1, vrnd_mem + paddd m4, m0 + paddd m5, m1 +%endif +%ifidn %1, put + psrad m4, m6 + psrad m5, m6 + packssdw m4, m5 + pxor m7, m7 + pmaxsw m4, m7 + pminsw m4, pxmaxm + mova [dstq], m4 + add dstq, dsm +%else + psrad m4, 6 + psrad m5, 6 + packssdw m4, m5 + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep +%if ARCH_X86_64 + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 0, 1 + mova [stk+0xd0], m4 + MC_8TAP_SCALED_H 8, 5, 6, 7, 9, 4, 0, 1 + mova m4, [stk+0xd0] + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [stk+0x90] ; 23a + mova m3, [stk+0xa0] ; 23b + mova m5, [stk+0xb0] ; 45a + mova m6, [stk+0xc0] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [stk+0x90], m5 + mova [stk+0xa0], m6 + mova [stk+0xb0], m7 + mova [stk+0xc0], m4 +%else + mov r0m, r0 + mov r3, r3m + MC_8TAP_SCALED_H 0xa0, 0xe0 ; 8 + MC_8TAP_SCALED_H 0xa0, 0 ; 9 + mova m7, [stk+0xe0] + mova m2, [stk+0x60] ; 23a + mova m3, [stk+0x70] ; 23b + mova m4, [stk+0x80] ; 45a + mova m5, [stk+0x90] ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova m0, [stk+0x40] ; 01a + mova m1, [stk+0x50] ; 01b + mova [stk+0x40], m2 + mova [stk+0x50], m3 + mova [stk+0x60], m4 + mova [stk+0x70], m5 + mova m4, [stk+0x180] + mova m5, [stk+0x190] + mova [stk+0x80], m6 + mova [stk+0x90], m7 + mova m6, [stk+0x1a0] + mova m7, [stk+0x1b0] + mov r0, r0m +%endif + jmp .dy2_vloop +INIT_XMM ssse3 +.ret: + MC_8TAP_SCALED_RET 0 +%if ARCH_X86_32 && !isprep && required_stack_alignment > STACK_ALIGNMENT + %define r0m [rstk+stack_offset+ 4] + %define r1m [rstk+stack_offset+ 8] + %define r2m [rstk+stack_offset+12] + %define r3m [rstk+stack_offset+16] +%endif +%undef isput +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_16bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, (5*15 << 16) | 5*15 + jmp mangle(private_prefix %+ _%1_8tap_scaled_16bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 8 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN put +FN put_8tap_scaled, sharp, SHARP, SHARP +FN put_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN put_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN put_8tap_scaled, smooth, SMOOTH, SMOOTH +FN put_8tap_scaled, sharp_regular, SHARP, REGULAR +FN put_8tap_scaled, regular_sharp, REGULAR, SHARP +FN put_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN put_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN put_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 7 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN prep +FN prep_8tap_scaled, sharp, SHARP, SHARP +FN prep_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN prep_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN prep_8tap_scaled, smooth, SMOOTH, SMOOTH +FN prep_8tap_scaled, sharp_regular, SHARP, REGULAR +FN prep_8tap_scaled, regular_sharp, REGULAR, SHARP +FN prep_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN prep_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN prep_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%if ARCH_X86_64 +DECLARE_REG_TMP 6 +%else +DECLARE_REG_TMP 2 +%endif + +%if ARCH_X86_64 +; warp8x8t spills one less xmm register than warp8x8 on WIN64, compensate that +; by allocating 16 bytes more stack space so that stack offsets match up. +%if WIN64 && STACK_ALIGNMENT == 16 +%assign stksz 16*14 +%else +%assign stksz 16*13 +%endif +cglobal warp_affine_8x8t_16bpc, 4, 13, 9, stksz, dst, ds, src, ss, delta, \ + mx, tmp, alpha, beta, \ + filter, my, gamma, cnt +%assign stack_size_padded_8x8t stack_size_padded +%else +cglobal warp_affine_8x8t_16bpc, 0, 7, 8, -16*17, alpha, gamma, src, tmp, \ + filter, mx, my +%define m8 [esp+16*13] +%define m9 [esp+16*14] +%define cntd dword [esp+4*63] +%define dstq tmpq +%define dsq 0 +%if STACK_ALIGNMENT < 16 +%define dstm [esp+4*65] +%define dsm [esp+4*66] +%else +%define dstm r0m +%define dsm r1m +%endif +%endif +%define base filterq-$$ + mov t0d, r7m + LEA filterq, $$ + shr t0d, 11 +%if ARCH_X86_64 + movddup m8, [base+warp8x8t_rnd] +%else + movddup m1, [base+warp8x8t_rnd] + mov r1, r1m + add r1, r1 + mova m8, m1 + mov r1m, r1 ; ds *= 2 +%endif + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main + jmp .start +.loop: +%if ARCH_X86_64 + lea dstq, [dstq+dsq*4] +%else + add dstq, dsm + mov dstm, dstq +%endif + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main2 +.start: +%if ARCH_X86_32 + mov dstq, dstm +%endif + paddd m1, m8 + paddd m2, m8 + psrad m1, 15 + psrad m2, 15 + packssdw m1, m2 + mova [dstq+dsq*0], m1 + call mangle(private_prefix %+ _warp_affine_8x8_16bpc_ssse3).main3 +%if ARCH_X86_32 + mov dstq, dstm + add dstq, dsm +%endif + paddd m1, m8 + paddd m2, m8 + psrad m1, 15 + psrad m2, 15 + packssdw m1, m2 + mova [dstq+dsq*2], m1 + dec cntd + jg .loop + RET + +%if ARCH_X86_64 +cglobal warp_affine_8x8_16bpc, 4, 13, 10, 16*13, dst, ds, src, ss, delta, \ + mx, tmp, alpha, beta, \ + filter, my, gamma, cnt +ASSERT stack_size_padded == stack_size_padded_8x8t +%else +cglobal warp_affine_8x8_16bpc, 0, 7, 8, -16*17, alpha, gamma, src, tmp, \ + filter, mx, my +%endif + mov t0d, r7m + LEA filterq, $$ + shr t0d, 11 +%if ARCH_X86_64 + movddup m8, [base+warp8x8_rnd2+t0*8] + movd m9, r7m ; pixel_max + pshufb m9, [base+pw_256] +%else + movddup m1, [base+warp8x8_rnd2+t0*8] + movd m2, r7m ; pixel_max + pshufb m2, [base+pw_256] + mova m8, m1 + mova m9, m2 +%endif + call .main + jmp .start +.loop: +%if ARCH_X86_64 + lea dstq, [dstq+dsq*2] +%else + add dstq, dsm + mov dstm, dstq +%endif + call .main2 +.start: +%if ARCH_X86_32 + mov dstq, dstm +%endif + psrad m1, 16 + psrad m2, 16 + packssdw m1, m2 + pmaxsw m1, m6 + pmulhrsw m1, m8 + pminsw m1, m9 + mova [dstq+dsq*0], m1 + call .main3 +%if ARCH_X86_32 + mov dstq, dstm + add dstq, dsm +%endif + psrad m1, 16 + psrad m2, 16 + packssdw m1, m2 + pmaxsw m1, m6 + pmulhrsw m1, m8 + pminsw m1, m9 + mova [dstq+dsq*1], m1 + dec cntd + jg .loop + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov deltaq, r5m + mov mxd, r6m +%endif + movd m0, [base+warp8x8_shift+t0*4] + movddup m7, [base+warp8x8_rnd1+t0*8] + add filterq, mc_warp_filter-$$ +%if ARCH_X86_64 + movsx alphad, word [deltaq+2*0] + movsx betad, word [deltaq+2*1] + movsx gammad, word [deltaq+2*2] + movsx deltad, word [deltaq+2*3] + lea tmpq, [ssq*3] + add mxd, 512+(64<<10) + sub srcq, tmpq ; src -= ss*3 + imul tmpd, alphad, -7 + mov myd, r7m + add betad, tmpd ; beta -= alpha*7 + imul tmpd, gammad, -7 + add myd, 512+(64<<10) + mov cntd, 4 + add deltad, tmpd ; delta -= gamma*7 +%else +%if STACK_ALIGNMENT < 16 + %assign stack_offset stack_offset - gprsize +%endif + mov r3d, r5m ; abcd +%if STACK_ALIGNMENT < 16 + mov r0, r1m ; dst + mov r1, r2m ; ds + mov [esp+gprsize+4*65], r0 + mov [esp+gprsize+4*66], r1 +%endif + movsx alphad, word [r3+2*0] + movsx r2d, word [r3+2*1] + movsx gammad, word [r3+2*2] + movsx r3d, word [r3+2*3] + imul r5d, alphad, -7 + add r2d, r5d ; beta -= alpha*7 + imul r5d, gammad, -7 + mov [esp+gprsize+4*60], r2d + add r3d, r5d ; delta -= gamma*7 + mov [esp+gprsize+4*61], r3d + mov r3d, r4m ; ss + mov srcq, r3m + mov mxd, r6m + mov myd, r7m + mov dword [esp+gprsize+4*63], 4 ; cnt + mov [esp+gprsize+4*62], r3 + lea r3, [r3*3] + add mxd, 512+(64<<10) + add myd, 512+(64<<10) + sub srcq, r3 ; src -= ss*3 +%if STACK_ALIGNMENT < 16 + %assign stack_offset stack_offset + gprsize +%endif +%endif + mova [rsp+gprsize], m0 + pxor m6, m6 + call .h + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 01 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 1], m1 + mova [rsp+gprsize+16* 4], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 12 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 7], m1 + mova [rsp+gprsize+16*10], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 23 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 2], m1 + mova [rsp+gprsize+16* 5], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 34 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 8], m1 + mova [rsp+gprsize+16*11], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 45 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 3], m1 + mova [rsp+gprsize+16* 6], m5 + mova m5, m0 + call .h + punpcklwd m1, m5, m0 ; 56 + punpckhwd m5, m0 + mova [rsp+gprsize+16* 9], m1 + mova [rsp+gprsize+16*12], m5 + mova m5, m0 +.main2: + call .h +%macro WARP_V 6 ; 01l, 23l, 45l, 01h, 23h, 45h + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m4, [filterq+myq*8] ; a + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m2, [filterq+tmpq*8] ; b + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m3, [filterq+myq*8] ; c + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m1, [filterq+tmpq*8] ; d + lea tmpd, [myq+gammaq] + shr myd, 10 + punpcklwd m4, m2 + punpcklwd m3, m1 + punpckldq m2, m4, m3 + punpckhdq m4, m3 + punpcklbw m1, m6, m2 ; a0 a1 b0 b1 c0 c1 d0 d1 << 8 + pmaddwd m1, [rsp+gprsize+16*%1] + punpckhbw m3, m6, m2 ; a2 a3 b2 b3 c2 c3 d2 d3 << 8 + mova m2, [rsp+gprsize+16*%2] + pmaddwd m3, m2 + mova [rsp+gprsize+16*%1], m2 + paddd m1, m3 + punpcklbw m3, m6, m4 ; a4 a5 b4 b5 c4 c5 d4 d5 << 8 + mova m2, [rsp+gprsize+16*%3] + pmaddwd m3, m2 + mova [rsp+gprsize+16*%2], m2 + paddd m1, m3 + punpcklwd m3, m5, m0 ; 67 + punpckhbw m2, m6, m4 ; a6 a7 b6 b7 c6 c7 d6 d7 << 8 + pmaddwd m2, m3 + mova [rsp+gprsize+16*%3], m3 + paddd m1, m2 + movq m4, [filterq+myq*8] ; e + lea myd, [tmpq+gammaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] ; f + lea tmpd, [myq+gammaq] + shr myd, 10 + movq m2, [filterq+myq*8] ; g +%if ARCH_X86_64 + lea myd, [tmpq+deltaq] ; my += delta +%else + mov myd, [esp+gprsize+4*61] + add myd, tmpd +%endif + shr tmpd, 10 + punpcklwd m4, m3 + movq m3, [filterq+tmpq*8] ; h + punpcklwd m2, m3 + punpckldq m3, m4, m2 + punpckhdq m4, m2 + punpcklbw m2, m6, m3 ; e0 e1 f0 f1 g0 g1 h0 h1 << 8 + pmaddwd m2, [rsp+gprsize+16*%4] + punpckhbw m6, m3 ; e2 e3 f2 f3 g2 g3 h2 h3 << 8 + mova m3, [rsp+gprsize+16*%5] + pmaddwd m6, m3 + mova [rsp+gprsize+16*%4], m3 + pxor m3, m3 + paddd m2, m6 + punpcklbw m3, m4 ; e4 e5 f4 f5 g4 g5 h4 h5 << 8 + mova m6, [rsp+gprsize+16*%6] + pmaddwd m3, m6 + mova [rsp+gprsize+16*%5], m6 + punpckhwd m5, m0 + pxor m6, m6 + paddd m2, m3 + punpckhbw m3, m6, m4 ; e6 e7 f6 f7 g6 g7 h6 h7 << 8 + pmaddwd m3, m5 + mova [rsp+gprsize+16*%6], m5 + mova m5, m0 + paddd m2, m3 +%endmacro + WARP_V 1, 2, 3, 4, 5, 6 + ret +.main3: + call .h + WARP_V 7, 8, 9, 10, 11, 12 + ret +ALIGN function_align +.h: + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + punpcklbw m0, m6, m3 + movu m3, [srcq-6] + pmaddwd m0, m3 ; 0 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m2, m6, m3 + movu m3, [srcq-4] + pmaddwd m2, m3 ; 1 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m0, m2 ; 0 1 + punpcklbw m2, m6, m3 + movu m3, [srcq-2] + pmaddwd m2, m3 ; 2 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m1, m6, m3 + movu m3, [srcq+0] + pmaddwd m1, m3 ; 3 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m2, m1 ; 2 3 + punpcklbw m1, m6, m3 + movu m3, [srcq+2] + pmaddwd m1, m3 ; 4 + lea mxd, [tmpq+alphaq] + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + phaddd m0, m2 ; 0 1 2 3 + punpcklbw m2, m6, m3 + movu m3, [srcq+4] + pmaddwd m2, m3 ; 5 + lea tmpd, [mxq+alphaq] + shr mxd, 10 + movq m3, [filterq+mxq*8] + phaddd m1, m2 ; 4 5 + punpcklbw m2, m6, m3 + movu m3, [srcq+6] + pmaddwd m2, m3 ; 6 +%if ARCH_X86_64 + lea mxd, [tmpq+betaq] ; mx += beta +%else + mov mxd, [esp+gprsize*2+4*60] + add mxd, tmpd +%endif + shr tmpd, 10 + movq m3, [filterq+tmpq*8] + punpcklbw m4, m6, m3 + movu m3, [srcq+8] +%if ARCH_X86_64 + add srcq, ssq +%else + add srcq, [esp+gprsize*2+4*62] +%endif + pmaddwd m3, m4 ; 7 + phaddd m2, m3 ; 6 7 + phaddd m1, m2 ; 4 5 6 7 + paddd m0, m7 + paddd m1, m7 + psrad m0, [rsp+gprsize*2] + psrad m1, [rsp+gprsize*2] + packssdw m0, m1 + ret + +%macro BIDIR_FN 0 + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.ret: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jne .w8_loop + RET +.w16_loop: + call .main + add dstq, strideq +.w16: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + dec hd + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal avg_16bpc, 4, 7, 4, dst, stride, tmp1, tmp2, w, h +%define base r6-avg_ssse3_table + LEA r6, avg_ssse3_table + tzcnt wd, wm + mov t0d, r6m ; pixel_max + movsxd wq, [r6+wq*4] + shr t0d, 11 + movddup m2, [base+bidir_rnd+t0*8] + movddup m3, [base+bidir_mul+t0*8] + movifnidn hd, hm + add wq, r6 + BIDIR_FN +ALIGN function_align +.main: + mova m0, [tmp1q+16*0] + paddsw m0, [tmp2q+16*0] + mova m1, [tmp1q+16*1] + paddsw m1, [tmp2q+16*1] + add tmp1q, 16*2 + add tmp2q, 16*2 + pmaxsw m0, m2 + pmaxsw m1, m2 + psubsw m0, m2 + psubsw m1, m2 + pmulhw m0, m3 + pmulhw m1, m3 + ret + +cglobal w_avg_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, h +%define base r6-w_avg_ssse3_table + LEA r6, w_avg_ssse3_table + tzcnt wd, wm + mov t0d, r6m ; weight + movd m6, r7m ; pixel_max + movddup m5, [base+pd_65538] + movsxd wq, [r6+wq*4] + pshufb m6, [base+pw_256] + add wq, r6 + lea r6d, [t0-16] + shl t0d, 16 + sub t0d, r6d ; 16-weight, weight + paddw m5, m6 + mov r6d, t0d + shl t0d, 2 + test dword r7m, 0x800 + cmovnz r6d, t0d + movifnidn hd, hm + movd m4, r6d + pslld m5, 7 + pxor m7, m7 + pshufd m4, m4, q0000 + BIDIR_FN +ALIGN function_align +.main: + mova m2, [tmp1q+16*0] + mova m0, [tmp2q+16*0] + punpckhwd m3, m0, m2 + punpcklwd m0, m2 + mova m2, [tmp1q+16*1] + mova m1, [tmp2q+16*1] + add tmp1q, 16*2 + add tmp2q, 16*2 + pmaddwd m3, m4 + pmaddwd m0, m4 + paddd m3, m5 + paddd m0, m5 + psrad m3, 8 + psrad m0, 8 + packssdw m0, m3 + punpckhwd m3, m1, m2 + punpcklwd m1, m2 + pmaddwd m3, m4 + pmaddwd m1, m4 + paddd m3, m5 + paddd m1, m5 + psrad m3, 8 + psrad m1, 8 + packssdw m1, m3 + pminsw m0, m6 + pminsw m1, m6 + pmaxsw m0, m7 + pmaxsw m1, m7 + ret + +%if ARCH_X86_64 +cglobal mask_16bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%else +cglobal mask_16bpc, 4, 7, 8, dst, stride, tmp1, tmp2, w, mask +%define hd dword r5m +%define m8 [base+pw_64] +%endif +%define base r6-mask_ssse3_table + LEA r6, mask_ssse3_table + tzcnt wd, wm + mov t0d, r7m ; pixel_max + shr t0d, 11 + movsxd wq, [r6+wq*4] + movddup m6, [base+bidir_rnd+t0*8] + movddup m7, [base+bidir_mul+t0*8] +%if ARCH_X86_64 + mova m8, [base+pw_64] + movifnidn hd, hm +%endif + add wq, r6 + mov maskq, r6mp + BIDIR_FN +ALIGN function_align +.main: + movq m3, [maskq+8*0] + mova m0, [tmp1q+16*0] + mova m4, [tmp2q+16*0] + pxor m5, m5 + punpcklbw m3, m5 + punpckhwd m2, m0, m4 + punpcklwd m0, m4 + psubw m1, m8, m3 + punpckhwd m4, m3, m1 ; m, 64-m + punpcklwd m3, m1 + pmaddwd m2, m4 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m0, m3 + movq m3, [maskq+8*1] + mova m1, [tmp1q+16*1] + mova m4, [tmp2q+16*1] + add maskq, 8*2 + add tmp1q, 16*2 + add tmp2q, 16*2 + psrad m2, 5 + psrad m0, 5 + packssdw m0, m2 + punpcklbw m3, m5 + punpckhwd m2, m1, m4 + punpcklwd m1, m4 + psubw m5, m8, m3 + punpckhwd m4, m3, m5 ; m, 64-m + punpcklwd m3, m5 + pmaddwd m2, m4 ; tmp1 * m + tmp2 * (64-m) + pmaddwd m1, m3 + psrad m2, 5 + psrad m1, 5 + packssdw m1, m2 + pmaxsw m0, m6 + pmaxsw m1, m6 + psubsw m0, m6 + psubsw m1, m6 + pmulhw m0, m7 + pmulhw m1, m7 + ret + +cglobal w_mask_420_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_420_ssse3_table + LEA t0, w_mask_420_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd m0, r7m ; sign + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] ; ((64 - 38) << 10) + 1023 - 32 + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m4, [base+bidir_mul+r6*8] + ALLOC_STACK -16*4 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + mova [rsp+16*3], m4 + %define m8 [rsp+gprsize+16*0] + %define m9 [rsp+gprsize+16*1] + %define m10 [rsp+gprsize+16*2] + %define m11 [rsp+gprsize+16*3] +%endif + movd m7, [base+pw_2] + psubw m7, m0 + pshufb m7, [base+pw_256] + add wq, t0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 4 +.w4: + movq [dstq+strideq*0], m0 + phaddw m2, m3 + movhps [dstq+strideq*1], m0 + phaddd m2, m2 + lea dstq, [dstq+strideq*2] + paddw m2, m7 + movq [dstq+strideq*0], m1 + psrlw m2, 2 + movhps [dstq+strideq*1], m1 + packuswb m2, m2 + movd [maskq], m2 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 4 +.w8: + mova [dstq+strideq*0], m0 + paddw m2, m3 + phaddw m2, m2 + mova [dstq+strideq*1], m1 + paddw m2, m7 + psrlw m2, 2 + packuswb m2, m2 + movd [maskq], m2 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 8 +.w16: + mova [dstq+strideq*1+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*1], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + paddw m2, [dstq+strideq*1+16*0] + paddw m3, [dstq+strideq*1+16*1] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*1], m1 + paddw m2, m7 + psrlw m2, 2 + packuswb m2, m2 + movq [maskq], m2 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16 +.w32: + mova [dstq+strideq*1+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*1], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*0+16*2], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m1 + call .main + paddw m2, [dstq+strideq*1+16*0] + paddw m3, [dstq+strideq*1+16*1] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*1], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*2] + paddw m2, [dstq+strideq*1+16*3] + mova [dstq+strideq*1+16*2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*3], m1 + packuswb m3, m2 + mova [maskq], m3 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16*2 +.w64: + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*1+16*2], m3 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*2], m0 + mova [dstq+strideq*1+16*4], m3 + mova [dstq+strideq*0+16*3], m1 + call .main + mova [dstq+strideq*1+16*5], m2 + mova [dstq+strideq*0+16*4], m0 + mova [dstq+strideq*1+16*6], m3 + mova [dstq+strideq*0+16*5], m1 + call .main + mova [dstq+strideq*0+16*6], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*7], m2 + mova [dstq+strideq*0+16*7], m1 + call .main + paddw m2, [dstq+strideq*1+16*1] + paddw m3, [dstq+strideq*1+16*2] + mova [dstq+strideq*1+16*0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*2], m2 + mova [dstq+strideq*1+16*1], m1 + call .main + paddw m2, [dstq+strideq*1+16*3] + paddw m3, [dstq+strideq*1+16*4] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*2] + mova [dstq+strideq*1+16*2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*3], m1 + packuswb m3, m2 + mova [maskq+16*0], m3 + call .main + paddw m2, [dstq+strideq*1+16*5] + paddw m3, [dstq+strideq*1+16*6] + mova [dstq+strideq*1+16*4], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*6], m2 + mova [dstq+strideq*1+16*5], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*6] + paddw m2, [dstq+strideq*1+16*7] + mova [dstq+strideq*1+16*6], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*7], m1 + packuswb m3, m2 + mova [maskq+16*1], m3 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + lea dstq, [dstq+strideq*2] + add maskq, 16*4 +.w128: + mova [dstq+strideq*1+16* 1], m2 + mova [dstq+strideq*0+16* 0], m0 + mova [dstq+strideq*1+16* 2], m3 + mova [dstq+strideq*0+16* 1], m1 + call .main + mova [dstq+strideq*1+16* 3], m2 + mova [dstq+strideq*0+16* 2], m0 + mova [dstq+strideq*1+16* 4], m3 + mova [dstq+strideq*0+16* 3], m1 + call .main + mova [dstq+strideq*1+16* 5], m2 + mova [dstq+strideq*0+16* 4], m0 + mova [dstq+strideq*1+16* 6], m3 + mova [dstq+strideq*0+16* 5], m1 + call .main + mova [dstq+strideq*1+16* 7], m2 + mova [dstq+strideq*0+16* 6], m0 + mova [dstq+strideq*1+16* 8], m3 + mova [dstq+strideq*0+16* 7], m1 + call .main + mova [dstq+strideq*1+16* 9], m2 + mova [dstq+strideq*0+16* 8], m0 + mova [dstq+strideq*1+16*10], m3 + mova [dstq+strideq*0+16* 9], m1 + call .main + mova [dstq+strideq*1+16*11], m2 + mova [dstq+strideq*0+16*10], m0 + mova [dstq+strideq*1+16*12], m3 + mova [dstq+strideq*0+16*11], m1 + call .main + mova [dstq+strideq*1+16*13], m2 + mova [dstq+strideq*0+16*12], m0 + mova [dstq+strideq*1+16*14], m3 + mova [dstq+strideq*0+16*13], m1 + call .main + mova [dstq+strideq*0+16*14], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*15], m2 + mova [dstq+strideq*0+16*15], m1 + call .main + paddw m2, [dstq+strideq*1+16* 1] + paddw m3, [dstq+strideq*1+16* 2] + mova [dstq+strideq*1+16* 0], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16* 2], m2 + mova [dstq+strideq*1+16* 1], m1 + call .main + paddw m2, [dstq+strideq*1+16* 3] + paddw m3, [dstq+strideq*1+16* 4] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16* 2] + mova [dstq+strideq*1+16* 2], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16* 3], m1 + packuswb m3, m2 + mova [maskq+16*0], m3 + call .main + paddw m2, [dstq+strideq*1+16* 5] + paddw m3, [dstq+strideq*1+16* 6] + mova [dstq+strideq*1+16* 4], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16* 6], m2 + mova [dstq+strideq*1+16* 5], m1 + call .main + paddw m2, [dstq+strideq*1+16* 7] + paddw m3, [dstq+strideq*1+16* 8] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16* 6] + mova [dstq+strideq*1+16* 6], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16* 7], m1 + packuswb m3, m2 + mova [maskq+16*1], m3 + call .main + paddw m2, [dstq+strideq*1+16* 9] + paddw m3, [dstq+strideq*1+16*10] + mova [dstq+strideq*1+16* 8], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*10], m2 + mova [dstq+strideq*1+16* 9], m1 + call .main + paddw m2, [dstq+strideq*1+16*11] + paddw m3, [dstq+strideq*1+16*12] + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*10] + mova [dstq+strideq*1+16*10], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*11], m1 + packuswb m3, m2 + mova [maskq+16*2], m3 + call .main + paddw m2, [dstq+strideq*1+16*13] + paddw m3, [dstq+strideq*1+16*14] + mova [dstq+strideq*1+16*12], m0 + phaddw m2, m3 + mova [dstq+strideq*1+16*14], m2 + mova [dstq+strideq*1+16*13], m1 + call .main + phaddw m2, m3 + paddw m3, m7, [dstq+strideq*1+16*14] + paddw m2, [dstq+strideq*1+16*15] + mova [dstq+strideq*1+16*14], m0 + paddw m2, m7 + psrlw m3, 2 + psrlw m2, 2 + mova [dstq+strideq*1+16*15], m1 + packuswb m3, m2 + mova [maskq+16*3], m3 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: +%macro W_MASK 2 ; dst/tmp_offset, mask + mova m%1, [tmp1q+16*%1] + mova m%2, [tmp2q+16*%1] + punpcklwd m4, m%2, m%1 + punpckhwd m5, m%2, m%1 + psubsw m%1, m%2 + pabsw m%1, m%1 + psubusw m6, m8, m%1 + psrlw m6, 10 ; 64-m + psubw m%2, m9, m6 ; m + punpcklwd m%1, m6, m%2 + punpckhwd m6, m%2 + pmaddwd m%1, m4 + pmaddwd m6, m5 + psrad m%1, 5 + psrad m6, 5 + packssdw m%1, m6 + pmaxsw m%1, m10 + psubsw m%1, m10 + pmulhw m%1, m11 +%endmacro + W_MASK 0, 2 + W_MASK 1, 3 + add tmp1q, 16*2 + add tmp2q, 16*2 + ret + +cglobal w_mask_422_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_422_ssse3_table + LEA t0, w_mask_422_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + movd m7, r7m ; sign + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m4, [base+bidir_mul+r6*8] + ALLOC_STACK -16*4 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + mova [rsp+16*3], m4 +%endif + pxor m0, m0 + add wq, t0 + pshufb m7, m0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2 + W_MASK 1, 3 + phaddw m2, m3 + add tmp1q, 16*2 + add tmp2q, 16*2 + packuswb m2, m2 + pxor m3, m3 + psubb m2, m7 + pavgb m2, m3 + movq [maskq], m2 + add maskq, 8 + ret + +cglobal w_mask_444_16bpc, 4, 7, 12, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_444_ssse3_table + LEA t0, w_mask_444_ssse3_table + tzcnt wd, wm + mov r6d, r8m ; pixel_max + shr r6d, 11 + movsxd wq, [t0+wq*4] +%if ARCH_X86_64 + mova m8, [base+pw_27615] + mova m9, [base+pw_64] + movddup m10, [base+bidir_rnd+r6*8] + movddup m11, [base+bidir_mul+r6*8] +%else + mova m1, [base+pw_27615] + mova m2, [base+pw_64] + movddup m3, [base+bidir_rnd+r6*8] + movddup m7, [base+bidir_mul+r6*8] + ALLOC_STACK -16*3 + mova [rsp+16*0], m1 + mova [rsp+16*1], m2 + mova [rsp+16*2], m3 + %define m11 m7 +%endif + add wq, t0 + movifnidn hd, r5m + mov maskq, r6mp + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + movq [dstq+strideq*0], m1 + movhps [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop +.end: + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + sub hd, 2 + jg .w8_loop +.w8_end: + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0+16*0], m0 + mova [dstq+strideq*0+16*1], m1 + call .main + mova [dstq+strideq*1+16*0], m0 + mova [dstq+strideq*1+16*1], m1 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + call .main + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + call .main + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + call .main + mova [dstq+16*6], m0 + mova [dstq+16*7], m1 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16* 0], m0 + mova [dstq+16* 1], m1 + call .main + mova [dstq+16* 2], m0 + mova [dstq+16* 3], m1 + call .main + mova [dstq+16* 4], m0 + mova [dstq+16* 5], m1 + call .main + mova [dstq+16* 6], m0 + mova [dstq+16* 7], m1 + call .main + mova [dstq+16* 8], m0 + mova [dstq+16* 9], m1 + call .main + mova [dstq+16*10], m0 + mova [dstq+16*11], m1 + call .main + mova [dstq+16*12], m0 + mova [dstq+16*13], m1 + call .main + mova [dstq+16*14], m0 + mova [dstq+16*15], m1 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + W_MASK 0, 2 + W_MASK 1, 3 + packuswb m2, m3 + add tmp1q, 16*2 + add tmp2q, 16*2 + mova [maskq], m2 + add maskq, 16 + ret + +; (a * (64 - m) + b * m + 32) >> 6 +; = (((b - a) * m + 32) >> 6) + a +; = (((b - a) * (m << 9) + 16384) >> 15) + a +; except m << 9 overflows int16_t when m == 64 (which is possible), +; but if we negate m it works out (-64 << 9 == -32768). +; = (((a - b) * (m * -512) + 16384) >> 15) + a +cglobal blend_16bpc, 3, 7, 8, dst, stride, tmp, w, h, mask, stride3 +%define base r6-blend_ssse3_table + LEA r6, blend_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r6+wq*4] + movifnidn maskq, maskmp + mova m7, [base+pw_m512] + add wq, r6 + lea stride3q, [strideq*3] + pxor m6, m6 + jmp wq +.w4: + mova m5, [maskq] + movq m0, [dstq+strideq*0] + movhps m0, [dstq+strideq*1] + movq m1, [dstq+strideq*2] + movhps m1, [dstq+stride3q ] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + movq [dstq+strideq*2], m1 + movhps [dstq+stride3q ], m1 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w4 + RET +.w8: + mova m5, [maskq] + mova m0, [dstq+strideq*0] + mova m1, [dstq+strideq*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8 + RET +.w16: + mova m5, [maskq] + mova m0, [dstq+16*0] + mova m1, [dstq+16*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + add maskq, 16 + add tmpq, 32 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16 + RET +.w32: + mova m5, [maskq+16*0] + mova m0, [dstq+16*0] + mova m1, [dstq+16*1] + psubw m2, m0, [tmpq+16*0] + psubw m3, m1, [tmpq+16*1] + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova m5, [maskq+16*1] + mova m0, [dstq+16*2] + mova m1, [dstq+16*3] + psubw m2, m0, [tmpq+16*2] + psubw m3, m1, [tmpq+16*3] + add maskq, 32 + add tmpq, 64 + punpcklbw m4, m5, m6 + punpckhbw m5, m6 + pmullw m4, m7 + pmullw m5, m7 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*2], m0 + mova [dstq+16*3], m1 + add dstq, strideq + dec hd + jg .w32 + RET + +cglobal blend_v_16bpc, 3, 6, 6, dst, stride, tmp, w, h +%define base r5-blend_v_ssse3_table + LEA r5, blend_v_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + add wq, r5 + jmp wq +.w2: + movd m4, [base+obmc_masks+2*2] +.w2_loop: + movd m0, [dstq+strideq*0] + movd m2, [tmpq+4*0] + movd m1, [dstq+strideq*1] + movd m3, [tmpq+4*1] + add tmpq, 4*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + movd [dstq+strideq*0], m0 + movd [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w2_loop + RET +.w4: + movddup m2, [base+obmc_masks+4*2] +.w4_loop: + movq m0, [dstq+strideq*0] + movhps m0, [dstq+strideq*1] + mova m1, [tmpq] + add tmpq, 8*2 + psubw m1, m0 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova m4, [base+obmc_masks+8*2] +.w8_loop: + mova m0, [dstq+strideq*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+strideq*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m4 + paddw m0, m2 + paddw m1, m3 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + mova m4, [base+obmc_masks+16*2] + movq m5, [base+obmc_masks+16*3] +.w16_loop: + mova m0, [dstq+16*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+16*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, strideq + dec hd + jg .w16_loop + RET +.w32: +%if WIN64 + movaps [rsp+8], m6 +%endif + mova m4, [base+obmc_masks+16*4] + mova m5, [base+obmc_masks+16*5] + mova m6, [base+obmc_masks+16*6] +.w32_loop: + mova m0, [dstq+16*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+16*1] + mova m3, [tmpq+16*1] + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m4 + pmulhrsw m3, m5 + paddw m0, m2 + mova m2, [dstq+16*2] + paddw m1, m3 + mova m3, [tmpq+16*2] + add tmpq, 16*4 + psubw m3, m2 + pmulhrsw m3, m6 + paddw m2, m3 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + add dstq, strideq + dec hd + jg .w32_loop +%if WIN64 + movaps m6, [rsp+8] +%endif + RET + +%macro BLEND_H_ROW 2-3 0; dst_off, tmp_off, inc_tmp + mova m0, [dstq+16*(%1+0)] + mova m2, [tmpq+16*(%2+0)] + mova m1, [dstq+16*(%1+1)] + mova m3, [tmpq+16*(%2+1)] +%if %3 + add tmpq, 16*%3 +%endif + psubw m2, m0 + psubw m3, m1 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + paddw m0, m2 + paddw m1, m3 + mova [dstq+16*(%1+0)], m0 + mova [dstq+16*(%1+1)], m1 +%endmacro + +cglobal blend_h_16bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base r6-blend_h_ssse3_table + LEA r6, blend_h_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + movddup m4, [base+blend_shuf] + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + add wq, r6 + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + movd m2, [dstq+dsq*1] + movd m3, [maskq+hq*2] + movq m1, [tmpq] + add tmpq, 4*2 + punpckldq m0, m2 + punpcklwd m3, m3 + psubw m1, m0 + pmulhrsw m1, m3 + paddw m0, m1 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova m3, [base+blend_shuf] +.w4_loop: + movq m0, [dstq+dsq*0] + movhps m0, [dstq+dsq*1] + movd m2, [maskq+hq*2] + mova m1, [tmpq] + add tmpq, 8*2 + psubw m1, m0 + pshufb m2, m3 + pmulhrsw m1, m2 + paddw m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + movddup m5, [base+blend_shuf+8] +%if WIN64 + movaps [rsp+ 8], m6 + movaps [rsp+24], m7 +%endif +.w8_loop: + movd m7, [maskq+hq*2] + mova m0, [dstq+dsq*0] + mova m2, [tmpq+16*0] + mova m1, [dstq+dsq*1] + mova m3, [tmpq+16*1] + add tmpq, 16*2 + pshufb m6, m7, m4 + psubw m2, m0 + pshufb m7, m5 + psubw m3, m1 + pmulhrsw m2, m6 + pmulhrsw m3, m7 + paddw m0, m2 + paddw m1, m3 + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop +%if WIN64 + movaps m6, [rsp+ 8] + movaps m7, [rsp+24] +%endif + RET +.w16: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0, 2 + add dstq, dsq + inc hq + jl .w16 + RET +.w32: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2, 4 + add dstq, dsq + inc hq + jl .w32 + RET +.w64: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2 + BLEND_H_ROW 4, 4 + BLEND_H_ROW 6, 6, 8 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + movd m5, [maskq+hq*2] + pshufb m5, m4 + BLEND_H_ROW 0, 0 + BLEND_H_ROW 2, 2 + BLEND_H_ROW 4, 4 + BLEND_H_ROW 6, 6, 16 + BLEND_H_ROW 8, -8 + BLEND_H_ROW 10, -6 + BLEND_H_ROW 12, -4 + BLEND_H_ROW 14, -2 + add dstq, dsq + inc hq + jl .w128 + RET + +; emu_edge args: +; const intptr_t bw, const intptr_t bh, const intptr_t iw, const intptr_t ih, +; const intptr_t x, const intptr_t y, pixel *dst, const ptrdiff_t dst_stride, +; const pixel *ref, const ptrdiff_t ref_stride +; +; bw, bh total filled size +; iw, ih, copied block -> fill bottom, right +; x, y, offset in bw/bh -> fill top, left +cglobal emu_edge_16bpc, 10, 13, 1, bw, bh, iw, ih, x, \ + y, dst, dstride, src, sstride, \ + bottomext, rightext, blk + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + +%if ARCH_X86_64 + %define reg_zero r12q + %define reg_tmp r10 + %define reg_src srcq + %define reg_bottomext bottomextq + %define reg_rightext rightextq + %define reg_blkm r9m +%else + %define reg_zero r6 + %define reg_tmp r0 + %define reg_src r1 + %define reg_bottomext r0 + %define reg_rightext r1 + %define reg_blkm r2m +%endif + ; + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor reg_zero, reg_zero + lea reg_tmp, [ihq-1] + cmp yq, ihq + cmovs reg_tmp, yq + test yq, yq + cmovs reg_tmp, reg_zero +%if ARCH_X86_64 + imul reg_tmp, sstrideq + add srcq, reg_tmp +%else + imul reg_tmp, sstridem + mov reg_src, srcm + add reg_src, reg_tmp +%endif + ; + ; ref += iclip(x, 0, iw - 1) + lea reg_tmp, [iwq-1] + cmp xq, iwq + cmovs reg_tmp, xq + test xq, xq + cmovs reg_tmp, reg_zero + lea reg_src, [reg_src+reg_tmp*2] +%if ARCH_X86_32 + mov srcm, reg_src +%endif + ; + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) +%if ARCH_X86_32 + mov r1, r1m ; restore bh +%endif + lea reg_bottomext, [yq+bhq] + sub reg_bottomext, ihq + lea r3, [bhq-1] + cmovs reg_bottomext, reg_zero + ; + + DEFINE_ARGS bw, bh, iw, ih, x, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, reg_zero + cmp reg_bottomext, bhq + cmovns reg_bottomext, r3 + cmp topextq, bhq + cmovg topextq, r3 + %if ARCH_X86_32 + mov r4m, reg_bottomext + ; + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + mov r0, r0m ; restore bw + %endif + lea reg_rightext, [xq+bwq] + sub reg_rightext, iwq + lea r2, [bwq-1] + cmovs reg_rightext, reg_zero + + DEFINE_ARGS bw, bh, iw, ih, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, reg_zero + cmp reg_rightext, bwq + cmovns reg_rightext, r2 + %if ARCH_X86_32 + mov r3m, r1 + %endif + cmp leftextq, bwq + cmovns leftextq, r2 + +%undef reg_zero +%undef reg_tmp +%undef reg_src +%undef reg_bottomext +%undef reg_rightext + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; center_h = bh - top_ext - bottom_ext +%if ARCH_X86_64 + lea r3, [bottomextq+topextq] + sub centerhq, r3 +%else + mov r1, centerhm ; restore r1 + sub centerhq, topextq + sub centerhq, r4m + mov r1m, centerhq +%endif + ; + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq +%if ARCH_X86_64 + imul r2, dstrideq +%else + mov r6, r6m ; restore dstq + imul r2, dstridem +%endif + add dstq, r2 + mov reg_blkm, dstq ; save pointer for ext + ; + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq +%if ARCH_X86_64 + lea r3, [rightextq+leftextq] + sub centerwq, r3 +%else + sub centerwq, r3m + sub centerwq, leftextq +%endif + +; vloop Macro +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix + %if ARCH_X86_64 + %define reg_tmp r12 + %else + %define reg_tmp r0 + %endif +.v_loop_%3: + %if ARCH_X86_32 + mov r0, r0m + mov r1, r1m + %endif +%if %1 + ; left extension + %if ARCH_X86_64 + movd m0, [srcq] + %else + mov r3, srcm + movd m0, [r3] + %endif + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + xor r3, r3 +.left_loop_%3: + mova [dstq+r3*2], m0 + add r3, mmsize/2 + cmp r3, leftextq + jl .left_loop_%3 + ; body + lea reg_tmp, [dstq+leftextq*2] +%endif + xor r3, r3 +.body_loop_%3: + %if ARCH_X86_64 + movu m0, [srcq+r3*2] + %else + mov r1, srcm + movu m0, [r1+r3*2] + %endif +%if %1 + movu [reg_tmp+r3*2], m0 +%else + movu [dstq+r3*2], m0 +%endif + add r3, mmsize/2 + cmp r3, centerwq + jl .body_loop_%3 +%if %2 + ; right extension +%if %1 + lea reg_tmp, [reg_tmp+centerwq*2] +%else + lea reg_tmp, [dstq+centerwq*2] +%endif + %if ARCH_X86_64 + movd m0, [srcq+centerwq*2-2] + %else + mov r3, srcm + movd m0, [r3+centerwq*2-2] + %endif + pshuflw m0, m0, q0000 + punpcklqdq m0, m0 + xor r3, r3 +.right_loop_%3: + movu [reg_tmp+r3*2], m0 + add r3, mmsize/2 + %if ARCH_X86_64 + cmp r3, rightextq + %else + cmp r3, r3m + %endif + jl .right_loop_%3 +%endif + %if ARCH_X86_64 + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 + %else + add dstq, dstridem + mov r0, sstridem + add srcm, r0 + sub dword centerhm, 1 + jg .v_loop_%3 + mov r0, r0m ; restore r0 + %endif +%endmacro ; vloop MACRO + + test leftextq, leftextq + jnz .need_left_ext + %if ARCH_X86_64 + test rightextq, rightextq + jnz .need_right_ext + %else + cmp leftextq, r3m ; leftextq == 0 + jne .need_right_ext + %endif + v_loop 0, 0, 0 + jmp .body_done + + ;left right extensions +.need_left_ext: + %if ARCH_X86_64 + test rightextq, rightextq + %else + mov r3, r3m + test r3, r3 + %endif + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: +; r0 ; bw +; r1 ;; x loop +; r4 ;; y loop +; r5 ; topextq +; r6 ;dstq +; r7 ;dstrideq +; r8 ; srcq +%if ARCH_X86_64 + %define reg_dstride dstrideq +%else + %define reg_dstride r2 +%endif + ; + ; bottom edge extension + %if ARCH_X86_64 + test bottomextq, bottomextq + jz .top + %else + xor r1, r1 + cmp r1, r4m + je .top + %endif + ; + %if ARCH_X86_64 + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 + %else + mov r3, dstq + mov reg_dstride, dstridem + sub r3, reg_dstride + mov srcm, r3 + %endif + ; +.bottom_x_loop: + %if ARCH_X86_64 + mova m0, [srcq+r1*2] + lea r3, [dstq+r1*2] + mov r4, bottomextq + %else + mov r3, srcm + mova m0, [r3+r1*2] + lea r3, [dstq+r1*2] + mov r4, r4m + %endif + ; +.bottom_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .bottom_y_loop + add r1, mmsize/2 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end +%if ARCH_X86_64 + mov srcq, reg_blkm +%else + mov r3, reg_blkm + mov reg_dstride, dstridem +%endif + mov dstq, dstm + xor r1, r1 + ; +.top_x_loop: +%if ARCH_X86_64 + mova m0, [srcq+r1*2] +%else + mov r3, reg_blkm + mova m0, [r3+r1*2] +%endif + lea r3, [dstq+r1*2] + mov r4, topextq + ; +.top_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .top_y_loop + add r1, mmsize/2 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +%undef reg_dstride +%undef reg_blkm +%undef reg_tmp + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +%if ARCH_X86_64 +cglobal resize_16bpc, 0, 12, 16, 1*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%elif STACK_ALIGNMENT >= 16 +cglobal resize_16bpc, 0, 7, 8, 6*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%else +cglobal resize_16bpc, 0, 6, 8, 6*16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0, pxmax +%endif + movifnidn dstq, dstmp + movifnidn srcq, srcmp +%if STACK_ALIGNMENT >= 16 + movifnidn dst_wd, dst_wm +%endif +%if ARCH_X86_64 + movifnidn hd, hm +%endif + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + movd m4, pxmaxm + movd m7, dxm + movd m6, mx0m + movd m5, src_wm + punpcklwd m4, m4 + pshufd m4, m4, q0000 + pshufd m7, m7, q0000 + pshufd m6, m6, q0000 + pshufd m5, m5, q0000 + mova [rsp+16*3*ARCH_X86_32], m4 +%if ARCH_X86_64 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ + %define base r7-$$ +%else + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, x + %define hd dword r5m + %if STACK_ALIGNMENT >= 16 + LEA r6, $$ + %define base r6-$$ + %else + LEA r4, $$ + %define base r4-$$ + %endif +%endif +%if ARCH_X86_64 + mova m12, [base+pd_64] + mova m11, [base+pd_63] +%else + %define m12 [base+pd_64] + %define m11 [base+pd_63] +%endif + pmaddwd m4, m7, [base+rescale_mul] ; dx*[0,1,2,3] + pslld m7, 2 ; dx*4 + pslld m5, 14 + paddd m6, m4 ; mx+[0..3]*dx + SCRATCH 7, 15, 0 + SCRATCH 6, 14, 1 + SCRATCH 5, 13, 2 + pxor m1, m1 +.loop_y: + xor xd, xd + mova m0, m14 ; per-line working version of mx +.loop_x: + pcmpgtd m1, m0 + pandn m1, m0 + psrad m2, m0, 8 ; filter offset (unmasked) + pcmpgtd m3, m13, m1 + pand m1, m3 + pandn m3, m13 + por m1, m3 + psubd m3, m0, m1 ; pshufb offset + psrad m1, 14 ; clipped src_x offset + psrad m3, 14 ; pshufb edge_emu offset + pand m2, m11 ; filter offset (masked) + ; load source pixels +%if ARCH_X86_64 + movd r8d, m1 + pshuflw m1, m1, q3232 + movd r9d, m1 + punpckhqdq m1, m1 + movd r10d, m1 + psrlq m1, 32 + movd r11d, m1 + movu m4, [srcq+r8*2] + movu m5, [srcq+r9*2] + movu m6, [srcq+r10*2] + movu m7, [srcq+r11*2] + ; if no emulation is required, we don't need to shuffle or emulate edges + packssdw m3, m3 + movq r11, m3 + test r11, r11 + jz .filter + movsx r8, r11w + sar r11, 16 + movsx r9, r11w + sar r11, 16 + movsx r10, r11w + sar r11, 16 + movu m1, [base+resize_shuf+8+r8*2] + movu m3, [base+resize_shuf+8+r9*2] + movu m8, [base+resize_shuf+8+r10*2] + movu m9, [base+resize_shuf+8+r11*2] + pshufb m4, m1 + pshufb m5, m3 + pshufb m6, m8 + pshufb m7, m9 +.filter: + movd r8d, m2 + pshuflw m2, m2, q3232 + movd r9d, m2 + punpckhqdq m2, m2 + movd r10d, m2 + psrlq m2, 32 + movd r11d, m2 + movq m8, [base+resize_filter+r8*8] + movq m2, [base+resize_filter+r9*8] + pxor m9, m9 + punpcklbw m1, m9, m8 + punpcklbw m3, m9, m2 + psraw m1, 8 + psraw m3, 8 + movq m10, [base+resize_filter+r10*8] + movq m2, [base+resize_filter+r11*8] + punpcklbw m8, m9, m10 + punpcklbw m9, m2 + psraw m8, 8 + psraw m9, 8 + pmaddwd m4, m1 + pmaddwd m5, m3 + pmaddwd m6, m8 + pmaddwd m7, m9 + phaddd m4, m5 +%else + movd r3, m1 + pshuflw m1, m1, q3232 + movd r1, m1 + punpckhqdq m1, m1 + movu m4, [srcq+r3*2] + movu m5, [srcq+r1*2] + movd r3, m1 + psrlq m1, 32 + movd r1, m1 + movu m6, [srcq+r3*2] + movu m7, [srcq+r1*2] + ; if no emulation is required, we don't need to shuffle or emulate edges + pxor m1, m1 + pcmpeqb m1, m3 + pmovmskb r3d, m1 + cmp r3d, 0xffff + je .filter + movd r3, m3 + movu m1, [base+resize_shuf+8+r3*2] + pshuflw m3, m3, q3232 + movd r1, m3 + pshufb m4, m1 + movu m1, [base+resize_shuf+8+r1*2] + punpckhqdq m3, m3 + movd r3, m3 + pshufb m5, m1 + movu m1, [base+resize_shuf+8+r3*2] + psrlq m3, 32 + movd r1, m3 + pshufb m6, m1 + movu m1, [base+resize_shuf+8+r1*2] + pshufb m7, m1 +.filter: + mova [esp+4*16], m6 + mova [esp+5*16], m7 + movd r3, m2 + pshuflw m2, m2, q3232 + movd r1, m2 + movq m6, [base+resize_filter+r3*8] + movq m7, [base+resize_filter+r1*8] + pxor m3, m3 + punpcklbw m1, m3, m6 + punpcklbw m3, m7 + psraw m1, 8 + psraw m3, 8 + pmaddwd m4, m1 + pmaddwd m5, m3 + punpckhqdq m2, m2 + movd r3, m2 + psrlq m2, 32 + movd r1, m2 + phaddd m4, m5 + movq m2, [base+resize_filter+r3*8] + movq m5, [base+resize_filter+r1*8] + mova m6, [esp+4*16] + mova m7, [esp+5*16] + pxor m3, m3 + punpcklbw m1, m3, m2 + punpcklbw m3, m5 + psraw m1, 8 + psraw m3, 8 + pmaddwd m6, m1 + pmaddwd m7, m3 +%endif + phaddd m6, m7 + phaddd m4, m6 + pxor m1, m1 + psubd m2, m12, m4 + psrad m2, 7 + packssdw m2, m2 + pmaxsw m2, m1 + pminsw m2, [rsp+16*3*ARCH_X86_32] + movq [dstq+xq*2], m2 + paddd m0, m15 + add xd, 4 +%if STACK_ALIGNMENT >= 16 + cmp xd, dst_wd +%else + cmp xd, dst_wm +%endif + jl .loop_x + add dstq, dst_stridemp + add srcq, src_stridemp + dec hd + jg .loop_y + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5669 @@ +; Copyright © 2018-2021, VideoLAN and dav1d authors +; Copyright © 2018-2021, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +; dav1d_obmc_masks[] with 64-x interleaved +obmc_masks: db 0, 0, 0, 0 + ; 2 + db 45, 19, 64, 0 + ; 4 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + db 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0 + +warp_8x8_shufA: db 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 8 + db 4, 6, 8, 10, 5, 7, 9, 11, 5, 7, 9, 11, 6, 8, 10, 12 +warp_8x8_shufB: db 2, 4, 6, 8, 3, 5, 7, 9, 3, 5, 7, 9, 4, 6, 8, 10 + db 6, 8, 10, 12, 7, 9, 11, 13, 7, 9, 11, 13, 8, 10, 12, 14 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_v_shuf4: db 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 +subpel_s_shuf2: db 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +bilin_h_shuf8: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7 +deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +pb_8x0_8x8: db 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 +bdct_lb_dw: db 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12 +wswap: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 + +wm_420_sign: dd 0x01020102, 0x01010101 +wm_422_sign: dd 0x80808080, 0x7f7f7f7f + +pb_64: times 4 db 64 +pw_m256: times 2 dw -256 +pw_15: times 2 dw 15 +pw_32: times 2 dw 32 +pw_34: times 2 dw 34 +pw_258: times 2 dw 258 +pw_512: times 2 dw 512 +pw_1024: times 2 dw 1024 +pw_2048: times 2 dw 2048 +pw_6903: times 2 dw 6903 +pw_8192: times 2 dw 8192 +pd_32: dd 32 +pd_63: dd 63 +pd_512: dd 512 +pd_32768: dd 32768 +pd_0x3ff: dd 0x3ff +pd_0x4000: dd 0x4000 +pq_0x40000000: dq 0x40000000 + +cextern mc_subpel_filters +cextern mc_warp_filter2 +cextern resize_filter + +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx2 mangle(private_prefix %+ _put_bilin_8bpc_avx2.put) +%xdefine prep_avx2 mangle(private_prefix %+ _prep_bilin_8bpc_avx2.prep) + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +BASE_JMP_TABLE put, avx2, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx2, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx2, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx2, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx2, 1, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE put_8tap_scaled, avx2, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx2, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx2, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx2, 2, 4, 8, 16, 32, 32, 32 + +SECTION .text + +INIT_XMM avx2 +cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + lea r7, [put_avx2] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + movzx r6d, word [srcq+ssq*0] + movzx r7d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6w + mov [dstq+dsq*1], r7w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +INIT_YMM avx2 +.put_w32: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0+32*0] + movu m1, [srcq+ssq*0+32*1] + movu m2, [srcq+ssq*1+32*0] + movu m3, [srcq+ssq*1+32*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+32*0], m0 + mova [dstq+dsq*0+32*1], m1 + mova [dstq+dsq*1+32*0], m2 + mova [dstq+dsq*1+32*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] + movu m2, [srcq+32*2] + movu m3, [srcq+32*3] + add srcq, ssq + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + mova [dstq+32*2], m2 + mova [dstq+32*3], m3 + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 255 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 + movd xm5, mxyd + mov mxyd, r7m ; my + vpbroadcastw m5, xm5 + test mxyd, mxyd + jnz .hv + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + vpbroadcastd m3, [pw_2048] + add wq, r7 + jmp wq +.h_w2: + movd xm0, [srcq+ssq*0] + pinsrd xm0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 + pmulhrsw xm0, xm3 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + mova xm4, [bilin_h_shuf4] +.h_w4_loop: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 + pmulhrsw xm0, xm3 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pshufb xm1, xm4 + pmaddubsw xm0, xm5 + pmaddubsw xm1, xm5 + pmulhrsw xm0, xm3 + pmulhrsw xm1, xm3 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*1+8*0], 1 + movu xm1, [srcq+ssq*0+8*1] + vinserti128 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movu m1, [srcq+8*4] + movu m2, [srcq+8*5] + add srcq, ssq + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + packuswb m1, m2 + mova [dstq+32*0], m0 + mova [dstq+32*1], m1 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + mov r6, -32*3 +.h_w128_loop: + movu m0, [srcq+r6+32*3+8*0] + movu m1, [srcq+r6+32*3+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+32*3], m0 + add r6, 32 + jle .h_w128_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 255 + vpbroadcastd m5, [pw_2048] + add mxyd, 16 + add wq, r7 + movd xm4, mxyd + vpbroadcastw m4, xm4 + jmp wq +.v_w2: + movd xm0, [srcq+ssq*0] +.v_w2_loop: + pinsrw xm1, xm0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pinsrw xm0, xm1, [srcq+ssq*0], 0 ; 2 1 + pshuflw xm1, xm1, q2301 ; 1 0 + punpcklbw xm1, xm0 + pmaddubsw xm1, xm4 + pmulhrsw xm1, xm5 + packuswb xm1, xm1 + pextrw [dstq+dsq*0], xm1, 1 + pextrw [dstq+dsq*1], xm1, 0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xm0, [srcq+ssq*0] +.v_w4_loop: + vpbroadcastd xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm1, xm2, xm0, 0x01 ; 0 1 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm2, xm0, 0x02 ; 1 2 + punpcklbw xm1, xm2 + pmaddubsw xm1, xm4 + pmulhrsw xm1, xm5 + packuswb xm1, xm1 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xm0, [srcq+ssq*0] +.v_w8_loop: + movq xm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw xm1, xm0, xm2 + movq xm0, [srcq+ssq*0] + punpcklbw xm2, xm0 + pmaddubsw xm1, xm4 + pmaddubsw xm2, xm4 + pmulhrsw xm1, xm5 + pmulhrsw xm2, xm5 + packuswb xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu xm0, [srcq+ssq*0] +.v_w16_loop: + vbroadcasti128 m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd m2, m3, m0, 0x0f ; 0 1 + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m3, m0, 0xf0 ; 1 2 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: +%macro PUT_BILIN_V_W32 0 + movu m0, [srcq+ssq*0] +%%loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m1, m0, m3 + punpckhbw m2, m0, m3 + movu m0, [srcq+ssq*0] + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + pmaddubsw m2, m4 + pmaddubsw m3, m4 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + packuswb m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg %%loop +%endmacro + PUT_BILIN_V_W32 + RET +.v_w64: + movu m0, [srcq+32*0] + movu m1, [srcq+32*1] +.v_w64_loop: + add srcq, ssq + movu m3, [srcq+32*0] + punpcklbw m2, m0, m3 + punpckhbw m0, m3 + pmaddubsw m2, m4 + pmaddubsw m0, m4 + pmulhrsw m2, m5 + pmulhrsw m0, m5 + packuswb m2, m0 + mova m0, m3 + movu m3, [srcq+32*1] + mova [dstq+32*0], m2 + punpcklbw m2, m1, m3 + punpckhbw m1, m3 + pmaddubsw m2, m4 + pmaddubsw m1, m4 + pmulhrsw m2, m5 + pmulhrsw m1, m5 + packuswb m2, m1 + mova m1, m3 + mova [dstq+32*1], m2 + add dstq, dsq + dec hd + jg .v_w64_loop + RET +.v_w128: + lea r6d, [hq+(3<<8)] + mov r4, srcq + mov r7, dstq +.v_w128_loop: + PUT_BILIN_V_W32 + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + vpbroadcastd m7, [pw_15] + movd xm6, mxyd + add wq, r7 + paddb m5, m5 + vpbroadcastw m6, xm6 + jmp wq +.hv_w2: + vpbroadcastd xm0, [srcq+ssq*0] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 +.hv_w2_loop: + movd xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pinsrd xm1, [srcq+ssq*0], 1 + pshufb xm1, xm4 + pmaddubsw xm1, xm5 ; 1 _ 2 _ + shufps xm2, xm0, xm1, q1032 ; 0 _ 1 _ + mova xm0, xm1 + psubw xm1, xm2 + pmulhw xm1, xm6 + pavgw xm2, xm7 + paddw xm1, xm2 + psrlw xm1, 4 + packuswb xm1, xm1 + pextrw [dstq+dsq*0], xm1, 0 + pextrw [dstq+dsq*1], xm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova xm4, [bilin_h_shuf4] + movddup xm0, [srcq+ssq*0] + pshufb xm0, xm4 + pmaddubsw xm0, xm5 +.hv_w4_loop: + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm1, [srcq+ssq*0] + pshufb xm1, xm4 + pmaddubsw xm1, xm5 ; 1 2 + shufps xm2, xm0, xm1, q1032 ; 0 1 + mova xm0, xm1 + psubw xm1, xm2 + pmulhw xm1, xm6 + pavgw xm2, xm7 + paddw xm1, xm2 + psrlw xm1, 4 + packuswb xm1, xm1 + movd [dstq+dsq*0], xm1 + pextrd [dstq+dsq*1], xm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 m0, [srcq+ssq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 m1, [srcq+ssq*0], 1 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 + vperm2i128 m2, m0, m1, 0x21 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhw m1, m6 + pavgw m2, m7 + paddw m1, m2 + psrlw m1, 4 + vextracti128 xm2, m1, 1 + packuswb xm1, xm2 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + movu m0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w16_loop: + movu xm2, [srcq+ssq*1+8*0] + vinserti128 m2, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + movu xm3, [srcq+ssq*0+8*0] + vinserti128 m3, [srcq+ssq*0+8*1], 1 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + psubw m1, m2, m0 + pmulhw m1, m6 + pavgw m0, m7 + paddw m1, m0 + pmaddubsw m0, m3, m5 + psubw m3, m0, m2 + pmulhw m3, m6 + pavgw m2, m7 + paddw m3, m2 + psrlw m1, 4 + psrlw m3, 4 + packuswb m1, m3 + vpermq m1, m1, q3120 + mova [dstq+dsq*0], xm1 + vextracti128 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w128: + lea r6d, [hq+(3<<16)] + jmp .hv_w32_start +.hv_w64: + lea r6d, [hq+(1<<16)] +.hv_w32_start: + mov r4, srcq + mov r7, dstq +.hv_w32: +%if WIN64 + movaps r4m, xmm8 +%endif +.hv_w32_loop0: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w32_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m8, m2, m0 + pmulhw m8, m6 + pavgw m0, m7 + paddw m8, m0 + mova m0, m2 + psubw m2, m3, m1 + pmulhw m2, m6 + pavgw m1, m7 + paddw m2, m1 + mova m1, m3 + psrlw m8, 4 + psrlw m2, 4 + packuswb m8, m2 + mova [dstq], m8 + add dstq, dsq + dec hd + jg .hv_w32_loop + add r4, 32 + add r7, 32 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<16 + jg .hv_w32_loop0 +%if WIN64 + movaps xmm8, r4m +%endif + RET + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea r6, [prep%+SUFFIX] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [r6+wq*2+table_offset(prep,)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd xm0, [srcq+strideq*0] + pinsrd xm0, [srcq+strideq*1], 1 + pinsrd xm0, [srcq+strideq*2], 2 + pinsrd xm0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmovzxbw m0, xm0 + psllw m0, 4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + movq xm1, [srcq+strideq*2] + movhps xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmovzxbw m0, xm0 + pmovzxbw m1, xm1 + psllw m0, 4 + psllw m1, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + pmovzxbw m0, [srcq+strideq*0] + pmovzxbw m1, [srcq+strideq*1] + pmovzxbw m2, [srcq+strideq*2] + pmovzxbw m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmovzxbw m0, [srcq+strideq*0+16*0] + pmovzxbw m1, [srcq+strideq*0+16*1] + pmovzxbw m2, [srcq+strideq*1+16*0] + pmovzxbw m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .prep_w32 + RET +.prep_w64: + pmovzxbw m0, [srcq+16*0] + pmovzxbw m1, [srcq+16*1] + pmovzxbw m2, [srcq+16*2] + pmovzxbw m3, [srcq+16*3] + add srcq, strideq + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .prep_w64 + RET +.prep_w128: + pmovzxbw m0, [srcq+16*0] + pmovzxbw m1, [srcq+16*1] + pmovzxbw m2, [srcq+16*2] + pmovzxbw m3, [srcq+16*3] + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + pmovzxbw m0, [srcq+16*4] + pmovzxbw m1, [srcq+16*5] + pmovzxbw m2, [srcq+16*6] + pmovzxbw m3, [srcq+16*7] + add tmpq, 32*8 + add srcq, strideq + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .prep_w128 + RET +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] + imul mxyd, 255 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 + movd xm5, mxyd + mov mxyd, r6m ; my + vpbroadcastw m5, xm5 + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + vbroadcasti128 m4, [bilin_h_shuf4] +.h_w4_loop: + movq xm0, [srcq+strideq*0] + movhps xm0, [srcq+strideq*1] + movq xm1, [srcq+strideq*2] + movhps xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 m0, xm1, 1 + pshufb m0, m4 + pmaddubsw m0, m5 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: +.h_w8_loop: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + movu xm1, [srcq+strideq*2] + vinserti128 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + add tmpq, 32*2 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: +.h_w16_loop: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + movu xm2, [srcq+strideq*2+8*0] + vinserti128 m2, [srcq+strideq*2+8*1], 1 + movu xm3, [srcq+stride3q +8*0] + vinserti128 m3, [srcq+stride3q +8*1], 1 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: +.h_w32_loop: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + movu xm1, [srcq+strideq*0+8*2] + vinserti128 m1, [srcq+strideq*0+8*3], 1 + movu xm2, [srcq+strideq*1+8*0] + vinserti128 m2, [srcq+strideq*1+8*1], 1 + movu xm3, [srcq+strideq*1+8*2] + vinserti128 m3, [srcq+strideq*1+8*3], 1 + lea srcq, [srcq+strideq*2] + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + sub hd, 2 + jg .h_w32_loop + RET +.h_w64: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + movu xm2, [srcq+8*4] + vinserti128 m2, [srcq+8*5], 1 + movu xm3, [srcq+8*6] + vinserti128 m3, [srcq+8*7], 1 + add srcq, strideq + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + add tmpq, 32*4 + dec hd + jg .h_w64 + RET +.h_w128: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + movu xm2, [srcq+8*4] + vinserti128 m2, [srcq+8*5], 1 + movu xm3, [srcq+8*6] + vinserti128 m3, [srcq+8*7], 1 + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+32*0], m0 + mova [tmpq+32*1], m1 + mova [tmpq+32*2], m2 + mova [tmpq+32*3], m3 + movu xm0, [srcq+8* 8] + vinserti128 m0, [srcq+8* 9], 1 + movu xm1, [srcq+8*10] + vinserti128 m1, [srcq+8*11], 1 + movu xm2, [srcq+8*12] + vinserti128 m2, [srcq+8*13], 1 + movu xm3, [srcq+8*14] + vinserti128 m3, [srcq+8*15], 1 + add tmpq, 32*8 + add srcq, strideq + pshufb m0, m4 + pshufb m1, m4 + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq-32*4], m0 + mova [tmpq-32*3], m1 + mova [tmpq-32*2], m2 + mova [tmpq-32*1], m3 + dec hd + jg .h_w128 + RET +.v: + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] + imul mxyd, 255 + add mxyd, 16 + add wq, r6 + lea stride3q, [strideq*3] + movd xm6, mxyd + vpbroadcastw m6, xm6 + jmp wq +.v_w4: + movd xm0, [srcq+strideq*0] +.v_w4_loop: + vpbroadcastd m1, [srcq+strideq*2] + vpbroadcastd xm2, [srcq+strideq*1] + vpbroadcastd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0x05 ; 0 2 2 2 + vpbroadcastd m0, [srcq+strideq*0] + vpblendd m3, m2, 0x0f ; 1 1 3 3 + vpblendd m2, m1, m0, 0xa0 ; 0 2 2 4 + vpblendd m1, m3, 0xaa ; 0 1 2 3 + vpblendd m2, m3, 0x55 ; 1 2 3 4 + punpcklbw m1, m2 + pmaddubsw m1, m6 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq xm0, [srcq+strideq*0] +.v_w8_loop: + vpbroadcastq m1, [srcq+strideq*2] + vpbroadcastq m2, [srcq+strideq*1] + vpbroadcastq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m0, 0x03 ; 0 2 2 2 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m2, m3, 0xcc ; 1 3 1 3 + vpblendd m3, m2, m1, 0xf0 ; 1 3 2 2 + vpblendd m2, m1, 0x0f ; 0 2 1 3 + vpblendd m3, m0, 0xc0 ; 1 3 2 4 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m6 + pmaddubsw m2, m6 + mova [tmpq+32*0], m1 + mova [tmpq+32*1], m2 + add tmpq, 32*2 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + vbroadcasti128 m0, [srcq+strideq*0] +.v_w16_loop: + vbroadcasti128 m1, [srcq+strideq*1] + vbroadcasti128 m2, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + shufpd m4, m0, m2, 0x0c ; 0 2 + vbroadcasti128 m0, [srcq+strideq*0] + shufpd m1, m3, 0x0c ; 1 3 + shufpd m2, m0, 0x0c ; 2 4 + punpcklbw m3, m4, m1 + punpcklbw m5, m1, m2 + punpckhbw m4, m1 + punpckhbw m1, m2 + pmaddubsw m3, m6 + pmaddubsw m5, m6 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+32*0], m3 + mova [tmpq+32*1], m5 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m1 + add tmpq, 32*4 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + vpermq m0, [srcq+strideq*0], q3120 +.v_w32_loop: + vpermq m1, [srcq+strideq*1], q3120 + vpermq m2, [srcq+strideq*2], q3120 + vpermq m3, [srcq+stride3q ], q3120 + lea srcq, [srcq+strideq*4] + punpcklbw m4, m0, m1 + punpckhbw m5, m0, m1 + vpermq m0, [srcq+strideq*0], q3120 + pmaddubsw m4, m6 + pmaddubsw m5, m6 + mova [tmpq+32*0], m4 + mova [tmpq+32*1], m5 + punpcklbw m4, m1, m2 + punpckhbw m1, m2 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + punpcklbw m5, m2, m3 + punpckhbw m2, m3 + pmaddubsw m5, m6 + pmaddubsw m2, m6 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m1 + add tmpq, 32*8 + punpcklbw m1, m3, m0 + punpckhbw m3, m0 + pmaddubsw m1, m6 + pmaddubsw m3, m6 + mova [tmpq-32*4], m5 + mova [tmpq-32*3], m2 + mova [tmpq-32*2], m1 + mova [tmpq-32*1], m3 + sub hd, 4 + jg .v_w32_loop + RET +.v_w64: + vpermq m0, [srcq+strideq*0+32*0], q3120 + vpermq m1, [srcq+strideq*0+32*1], q3120 +.v_w64_loop: + vpermq m2, [srcq+strideq*1+32*0], q3120 + vpermq m3, [srcq+strideq*1+32*1], q3120 + lea srcq, [srcq+strideq*2] + punpcklbw m4, m0, m2 + punpckhbw m0, m2 + pmaddubsw m4, m6 + pmaddubsw m0, m6 + mova [tmpq+32*0], m4 + mova [tmpq+32*1], m0 + punpcklbw m4, m1, m3 + punpckhbw m5, m1, m3 + vpermq m0, [srcq+strideq*0+32*0], q3120 + vpermq m1, [srcq+strideq*0+32*1], q3120 + pmaddubsw m4, m6 + pmaddubsw m5, m6 + mova [tmpq+32*2], m4 + mova [tmpq+32*3], m5 + add tmpq, 32*8 + punpcklbw m4, m2, m0 + punpckhbw m2, m0 + punpcklbw m5, m3, m1 + punpckhbw m3, m1 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + pmaddubsw m5, m6 + pmaddubsw m3, m6 + mova [tmpq-32*4], m4 + mova [tmpq-32*3], m2 + mova [tmpq-32*2], m5 + mova [tmpq-32*1], m3 + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + lea r6d, [hq+(3<<8)] + mov r3, srcq + mov r5, tmpq +.v_w128_loop0: + vpermq m0, [srcq+strideq*0], q3120 +.v_w128_loop: + vpermq m1, [srcq+strideq*1], q3120 + lea srcq, [srcq+strideq*2] + punpcklbw m2, m0, m1 + punpckhbw m3, m0, m1 + vpermq m0, [srcq+strideq*0], q3120 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + punpcklbw m4, m1, m0 + punpckhbw m1, m0 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+32*0], m2 + mova [tmpq+32*1], m3 + mova [tmpq+32*8], m4 + mova [tmpq+32*9], m1 + add tmpq, 32*16 + sub hd, 2 + jg .v_w128_loop + add r3, 32 + add r5, 64 + movzx hd, r6b + mov srcq, r3 + mov tmpq, r5 + sub r6d, 1<<8 + jg .v_w128_loop0 + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 7 + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + movd xm6, mxyd + vpbroadcastw m6, xm6 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + vbroadcasti128 m4, [bilin_h_shuf4] + vpbroadcastq m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w4_loop: + movq xm1, [srcq+strideq*1] + movhps xm1, [srcq+strideq*2] + movq xm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + movhps xm2, [srcq+strideq*0] + vinserti128 m1, xm2, 1 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 3 4 + vpblendd m2, m1, m0, 0xc0 + vpermq m2, m2, q2103 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xm1, [srcq+strideq*1] + vinserti128 m1, [srcq+strideq*2], 1 + movu xm2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 m2, [srcq+strideq*0], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 ; 1 2 + vperm2i128 m3, m0, m1, 0x21 ; 0 1 + pmaddubsw m0, m2, m5 ; 3 4 + vperm2i128 m2, m1, m0, 0x21 ; 2 3 + psubw m1, m3 + pmulhrsw m1, m6 + paddw m1, m3 + psubw m3, m0, m2 + pmulhrsw m3, m6 + paddw m3, m2 + mova [tmpq+32*0], m1 + mova [tmpq+32*1], m3 + add tmpq, 32*2 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w16_loop: + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + movu xm2, [srcq+strideq*0+8*0] + vinserti128 m2, [srcq+strideq*0+8*1], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+32*0], m3 + mova [tmpq+32*1], m2 + add tmpq, 32*2 + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + movu xm0, [srcq+8*0] + vinserti128 m0, [srcq+8*1], 1 + movu xm1, [srcq+8*2] + vinserti128 m1, [srcq+8*3], 1 + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w32_loop: + add srcq, strideq + movu xm2, [srcq+8*0] + vinserti128 m2, [srcq+8*1], 1 + pshufb m2, m4 + pmaddubsw m2, m5 + psubw m3, m2, m0 + pmulhrsw m3, m6 + paddw m3, m0 + mova m0, m2 + movu xm2, [srcq+8*2] + vinserti128 m2, [srcq+8*3], 1 + pshufb m2, m4 + pmaddubsw m2, m5 + mova [tmpq+32*0], m3 + psubw m3, m2, m1 + pmulhrsw m3, m6 + paddw m3, m1 + mova m1, m2 + mova [tmpq+32*1], m3 + add tmpq, 32*2 + dec hd + jg .hv_w32_loop + RET +.hv_w128: + lea r3d, [hq+(7<<8)] + mov r6d, 256 + jmp .hv_w64_start +.hv_w64: + lea r3d, [hq+(3<<8)] + mov r6d, 128 +.hv_w64_start: +%if WIN64 + PUSH r7 +%endif + mov r5, srcq + mov r7, tmpq +.hv_w64_loop0: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w64_loop: + movu xm1, [srcq+strideq*1+8*0] + vinserti128 m1, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + movu xm2, [srcq+strideq*0+8*0] + vinserti128 m2, [srcq+strideq*0+8*1], 1 + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+r6*0], m3 + mova [tmpq+r6*1], m2 + lea tmpq, [tmpq+r6*2] + sub hd, 2 + jg .hv_w64_loop + add r5, 16 + add r7, 32 + movzx hd, r3b + mov srcq, r5 + mov tmpq, r7 + sub r3d, 1<<8 + jg .hv_w64_loop0 +%if WIN64 + POP r7 +%endif + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; fn, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx2] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 + lea r6, [ssq*3] + lea r7, [dsq*3] +%if WIN64 + pop r8 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [pw_34] ; 2 + (8 << 2) + WIN64_SPILL_XMM 11 + cmp wd, 4 + jl .h_w2 + vbroadcasti128 m6, [subpel_h_shufA] + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m7, [subpel_h_shufB] + vbroadcasti128 m8, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)] + vpbroadcastd m9, [r8+mxq*8+subpel_filters-put_avx2+0] + vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+4] + add wq, r8 + jmp wq +.h_w2: + movzx mxd, mxb + dec srcq + mova xm4, [subpel_h_shuf4] + vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2] +.h_w2_loop: + movq xm0, [srcq+ssq*0] + movhps xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm4 + pmaddubsw xm0, xm3 + phaddw xm0, xm0 + paddw xm0, xm5 + psraw xm0, 6 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd xm3, [r8+mxq*8+subpel_filters-put_avx2+2] +.h_w4_loop: + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xm0, xm6 + pshufb xm1, xm6 + pmaddubsw xm0, xm3 + pmaddubsw xm1, xm3 + phaddw xm0, xm1 + paddw xm0, xm5 + psraw xm0, 6 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: +%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3] + pshufb m%2, m%1, m7 + pshufb m%3, m%1, m8 + pshufb m%1, m6 + pmaddubsw m%4, m%2, m9 + pmaddubsw m%2, m10 + pmaddubsw m%3, m10 + pmaddubsw m%1, m9 + paddw m%3, m%4 + paddw m%1, m%2 + phaddw m%1, m%3 + paddw m%1, m5 + psraw m%1, 6 +%endmacro + movu xm0, [srcq+ssq*0] + vinserti128 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 1, 2, 3 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+ssq*0+8*0] + vinserti128 m0, [srcq+ssq*1+8*0], 1 + movu xm1, [srcq+ssq*0+8*1] + vinserti128 m1, [srcq+ssq*1+8*1], 1 + PUT_8TAP_H 0, 2, 3, 4 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 1, 2, 3, 4 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16 + RET +.h_w32: + xor r6d, r6d + jmp .h_start +.h_w64: + mov r6, -32*1 + jmp .h_start +.h_w128: + mov r6, -32*3 +.h_start: + sub srcq, r6 + sub dstq, r6 + mov r4, r6 +.h_loop: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 2, 3, 4 + packuswb m0, m1 + mova [dstq+r6], m0 + add r6, 32 + jle .h_loop + add srcq, ssq + add dstq, dsq + mov r6, r4 + dec hd + jg .h_loop + RET +.v: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + tzcnt r6d, wd + movzx r6d, word [r8+r6*2+table_offset(put, _8tap_v)] + vpbroadcastd m7, [pw_512] + lea myq, [r8+myq*8+subpel_filters-put_avx2] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + add r6, r8 + lea ss3q, [ssq*3] + sub srcq, ss3q + jmp r6 +.v_w2: + movd xm2, [srcq+ssq*0] + pinsrw xm2, [srcq+ssq*1], 2 + pinsrw xm2, [srcq+ssq*2], 4 + add srcq, ss3q + pinsrw xm2, [srcq+ssq*0], 6 ; 0 1 2 3 + movd xm3, [srcq+ssq*1] + vpbroadcastd xm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklbw xm3, xm1 ; 45 56 + punpcklbw xm1, xm2, xm4 ; 01 12 + punpckhbw xm2, xm4 ; 23 34 +.v_w2_loop: + pmaddubsw xm5, xm1, xm8 ; a0 b0 + mova xm1, xm2 + pmaddubsw xm2, xm9 ; a1 b1 + paddw xm5, xm2 + mova xm2, xm3 + pmaddubsw xm3, xm10 ; a2 b2 + paddw xm5, xm3 + vpbroadcastd xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklbw xm3, xm4 ; 67 78 + pmaddubsw xm4, xm3, xm11 ; a3 b3 + paddw xm5, xm4 + pmulhrsw xm5, xm7 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xm2, [srcq+ssq*0] + pinsrd xm2, [srcq+ssq*1], 1 + pinsrd xm2, [srcq+ssq*2], 2 + add srcq, ss3q + pinsrd xm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xm3, [srcq+ssq*1] + vpbroadcastd xm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm3, xm1, 0x02 ; 4 5 + vpblendd xm1, xm0, 0x02 ; 5 6 + palignr xm4, xm3, xm2, 4 ; 1 2 3 4 + punpcklbw xm3, xm1 ; 45 56 + punpcklbw xm1, xm2, xm4 ; 01 12 + punpckhbw xm2, xm4 ; 23 34 +.v_w4_loop: + pmaddubsw xm5, xm1, xm8 ; a0 b0 + mova xm1, xm2 + pmaddubsw xm2, xm9 ; a1 b1 + paddw xm5, xm2 + mova xm2, xm3 + pmaddubsw xm3, xm10 ; a2 b2 + paddw xm5, xm3 + vpbroadcastd xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xm3, xm0, xm4, 0x02 ; 6 7 + vpbroadcastd xm0, [srcq+ssq*0] + vpblendd xm4, xm0, 0x02 ; 7 8 + punpcklbw xm3, xm4 ; 67 78 + pmaddubsw xm4, xm3, xm11 ; a3 b3 + paddw xm5, xm4 + pmulhrsw xm5, xm7 + packuswb xm5, xm5 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xm1, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + vpbroadcastq m2, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m5, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpbroadcastq m6, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m0, [srcq+ssq*0] + vpblendd m1, m4, 0x30 + vpblendd m4, m2, 0x30 + punpcklbw m1, m4 ; 01 12 + vpblendd m2, m5, 0x30 + vpblendd m5, m3, 0x30 + punpcklbw m2, m5 ; 23 34 + vpblendd m3, m6, 0x30 + vpblendd m6, m0, 0x30 + punpcklbw m3, m6 ; 45 56 +.v_w8_loop: + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, m8 ; a0 b0 + mova m1, m2 + pmaddubsw m2, m9 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, m10 ; a2 b2 + paddw m5, m3 + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+ssq*0] + vpblendd m4, m0, 0x30 + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, m11 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + vextracti128 xm4, m5, 1 + packuswb xm5, xm4 + movq [dstq+dsq*0], xm5 + movhps [dstq+dsq*1], xm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: +.v_w32: +.v_w64: +.v_w128: + lea r6d, [wq*8-128] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*2] +.v_w16_loop0: + vbroadcasti128 m4, [srcq+ssq*0] + vbroadcasti128 m5, [srcq+ssq*1] + vbroadcasti128 m6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m0, [srcq+ssq*0] + vbroadcasti128 m1, [srcq+ssq*1] + vbroadcasti128 m2, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m3, [srcq+ssq*0] + shufpd m4, m0, 0x0c + shufpd m5, m1, 0x0c + punpcklbw m1, m4, m5 ; 01 + punpckhbw m4, m5 ; 34 + shufpd m6, m2, 0x0c + punpcklbw m2, m5, m6 ; 12 + punpckhbw m5, m6 ; 45 + shufpd m0, m3, 0x0c + punpcklbw m3, m6, m0 ; 23 + punpckhbw m6, m0 ; 56 +.v_w16_loop: + vbroadcasti128 m12, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti128 m13, [srcq+ssq*0] + pmaddubsw m14, m1, m8 ; a0 + pmaddubsw m15, m2, m8 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, m9 ; a1 + pmaddubsw m4, m9 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, m10 ; a2 + pmaddubsw m6, m10 ; b2 + paddw m14, m5 + paddw m15, m6 + shufpd m6, m0, m12, 0x0d + shufpd m0, m12, m13, 0x0c + punpcklbw m5, m6, m0 ; 67 + punpckhbw m6, m0 ; 78 + pmaddubsw m12, m5, m11 ; a3 + pmaddubsw m13, m6, m11 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + packuswb m14, m15 + vpermq m14, m14, q3120 + mova [dstq+dsq*0], xm14 + vextracti128 [dstq+dsq*1], m14, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + dec srcq + vpbroadcastd m7, [r8+mxq*8+subpel_filters-put_avx2+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastq m0, [r8+myq*8+subpel_filters-put_avx2] + lea ss3q, [ssq*3] + sub srcq, ss3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m8, [pw_8192] + vpbroadcastd m9, [pd_512] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 m6, [subpel_h_shuf4] + movq xm2, [srcq+ssq*0] + movhps xm2, [srcq+ssq*1] + movq xm0, [srcq+ssq*2] + add srcq, ss3q + movhps xm0, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpbroadcastq m4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m1, [srcq+ssq*0] + vpblendd m2, m3, 0x30 + vpblendd m0, m1, 0x30 + vpblendd m2, m4, 0xc0 + pshufb m2, m6 + pshufb m0, m6 + pmaddubsw m2, m7 + pmaddubsw m0, m7 + phaddw m2, m0 + pmulhrsw m2, m8 + vextracti128 xm3, m2, 1 + palignr xm4, xm3, xm2, 4 + punpcklwd xm1, xm2, xm4 ; 01 12 + punpckhwd xm2, xm4 ; 23 34 + pshufd xm0, xm3, q2121 + punpcklwd xm3, xm0 ; 45 56 +.hv_w2_loop: + movq xm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xm4, [srcq+ssq*0] + pshufb xm4, xm6 + pmaddubsw xm4, xm7 + pmaddwd xm5, xm1, xm10 ; a0 b0 + mova xm1, xm2 + pmaddwd xm2, xm11 ; a1 b1 + paddd xm5, xm2 + mova xm2, xm3 + pmaddwd xm3, xm12 ; a2 b2 + phaddw xm4, xm4 + pmulhrsw xm4, xm8 + paddd xm5, xm3 + palignr xm3, xm4, xm0, 12 + mova xm0, xm4 + punpcklwd xm3, xm0 ; 67 78 + pmaddwd xm4, xm3, xm13 ; a3 b3 + paddd xm5, xm9 + paddd xm5, xm4 + psrad xm5, 10 + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova m6, [subpel_h_shuf4] + vpbroadcastq m2, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + vpbroadcastq m0, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m5, [srcq+ssq*0] + vpbroadcastq m3, [srcq+ssq*1] + vpblendd m2, m4, 0xcc ; 0 1 + vpbroadcastq m4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq m1, [srcq+ssq*0] + vpblendd m0, m5, 0xcc ; 2 3 + vpblendd m3, m4, 0xcc ; 4 5 + pshufb m2, m6 + pshufb m0, m6 + pshufb m3, m6 + pshufb m1, m6 + pmaddubsw m2, m7 + pmaddubsw m0, m7 + pmaddubsw m3, m7 + pmaddubsw m1, m7 + phaddw m2, m0 + phaddw m3, m1 + pmulhrsw m2, m8 + pmulhrsw m3, m8 + palignr m4, m3, m2, 4 + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + pshufd m0, m3, q2121 + punpcklwd m3, m0 ; 45 56 +.hv_w4_loop: + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m1, m10 ; a0 b0 + mova m1, m2 + pmaddwd m2, m11 ; a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, m12 ; a2 b2 + paddd m5, m3 + vpbroadcastq m3, [srcq+ssq*0] + vpblendd m4, m3, 0xcc ; 7 8 + pshufb m4, m6 + pmaddubsw m4, m7 + phaddw m4, m4 + pmulhrsw m4, m8 + palignr m3, m4, m0, 12 + mova m0, m4 + punpcklwd m3, m0 ; 67 78 + pmaddwd m4, m3, m13 ; a3 b3 + paddd m5, m9 + paddd m5, m4 + psrad m5, 10 + vextracti128 xm4, m5, 1 + packssdw xm5, xm4 + packuswb xm5, xm5 + pshuflw xm5, xm5, q3120 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r8+mxq*8+subpel_filters-put_avx2+0] + vpbroadcastd m11, [r8+mxq*8+subpel_filters-put_avx2+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastq m0, [r8+myq*8+subpel_filters-put_avx2] + lea ss3q, [ssq*3] + sub srcq, ss3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + lea r6d, [wq*8-64] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*4] +.hv_w8_loop0: + vbroadcasti128 m7, [subpel_h_shufA] + movu xm4, [srcq+ssq*0] + vbroadcasti128 m8, [subpel_h_shufB] + movu xm5, [srcq+ssq*1] + vbroadcasti128 m9, [subpel_h_shufC] + movu xm6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti128 m0, [srcq+ssq*0] + vpblendd m4, m0, 0xf0 ; 0 3 + vinserti128 m5, [srcq+ssq*1], 1 ; 1 4 + vinserti128 m6, [srcq+ssq*2], 1 ; 2 5 + add srcq, ss3q + vinserti128 m0, [srcq+ssq*0], 1 ; 3 6 +%macro HV_H_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3] + pshufb %3, %1, %6 + pshufb %4, %1, %7 + pshufb %1, %5 + pmaddubsw %2, %3, m10 + pmaddubsw %4, m11 + pmaddubsw %3, m11 + pmaddubsw %1, m10 + paddw %2, %4 + paddw %1, %3 + phaddw %1, %2 +%endmacro + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 + vpbroadcastd m7, [pw_8192] + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + pmulhrsw m0, m7 + pmulhrsw m4, m7 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + vpermq m7, m0, q3120 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vextracti128 r6m, m0, 1 ; not enough registers + movu xm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 m0, [srcq+ssq*0], 1 ; 7 8 + pmaddwd m8, m1, m12 ; a0 + pmaddwd m9, m2, m12 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m13 ; a1 + pmaddwd m4, m13 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m14 ; a2 + pmaddwd m6, m14 ; b2 + paddd m8, m5 + paddd m9, m6 + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + vbroadcasti128 m5, [subpel_h_shufA] + HV_H_W8 m0, m5, m6, m7, m5, m6, m7 + vpbroadcastd m5, [pw_8192] + vpbroadcastd m7, [pd_512] + vbroadcasti128 m6, r6m + pmulhrsw m0, m5 + paddd m8, m7 + paddd m9, m7 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, m15 ; a3 + paddd m8, m7 + pmaddwd m7, m6, m15 ; b3 + paddd m7, m9 + psrad m8, 10 + psrad m7, 10 + packssdw m8, m7 + vextracti128 xm7, m8, 1 + packuswb xm8, xm7 + pshufd xm7, xm8, q3120 + movq [dstq+dsq*0], xm7 + movhps [dstq+dsq*1], xm7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + add r4, 8 + add r7, 8 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w8_loop0 + RET + +%macro PREP_8TAP_H 0 + pshufb m1, m0, m5 + pshufb m2, m0, m6 + pshufb m3, m0, m7 + pmaddubsw m1, m8 + pmaddubsw m0, m2, m8 + pmaddubsw m2, m9 + pmaddubsw m3, m9 + paddw m1, m2 + paddw m0, m3 + phaddw m0, m1, m0 + pmulhrsw m0, m4 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep%+SUFFIX] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r7+wq*2+table_offset(prep,)] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m4, [pw_8192] + vbroadcasti128 m5, [subpel_h_shufA] + WIN64_SPILL_XMM 10 + cmp wd, 4 + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)] + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0] + vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4] + add wq, r7 + jmp wq +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m6, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2] + lea stride3q, [strideq*3] +.h_w4_loop: + movq xm0, [srcq+strideq*0] + vpbroadcastq m2, [srcq+strideq*2] + movq xm1, [srcq+strideq*1] + vpblendd m0, m2, 0xf0 + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd m1, m2, 0xf0 + pshufb m0, m5 + pshufb m1, m5 + pmaddubsw m0, m6 + pmaddubsw m1, m6 + phaddw m0, m1 + pmulhrsw m0, m4 + mova [tmpq], m0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+strideq*0] + vinserti128 m0, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + mova [tmpq], m0 + add tmpq, 32 + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu xm0, [srcq+strideq*0+8*0] + vinserti128 m0, [srcq+strideq*0+8*1], 1 + PREP_8TAP_H + mova [tmpq+32*0], m0 + movu xm0, [srcq+strideq*1+8*0] + vinserti128 m0, [srcq+strideq*1+8*1], 1 + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + mova [tmpq+32*1], m0 + add tmpq, 32*2 + sub hd, 2 + jg .h_w16 + RET +.h_w32: + xor r6d, r6d + jmp .h_start +.h_w64: + mov r6, -32*1 + jmp .h_start +.h_w128: + mov r6, -32*3 +.h_start: + sub srcq, r6 + mov r5, r6 +.h_loop: + movu xm0, [srcq+r6+8*0] + vinserti128 m0, [srcq+r6+8*1], 1 + PREP_8TAP_H + mova [tmpq+32*0], m0 + movu xm0, [srcq+r6+8*2] + vinserti128 m0, [srcq+r6+8*3], 1 + PREP_8TAP_H + mova [tmpq+32*1], m0 + add tmpq, 32*2 + add r6, 32 + jle .h_loop + add srcq, strideq + mov r6, r5 + dec hd + jg .h_loop + RET +.v: + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 16 + movzx mxd, myb ; Select 4-tap/8-tap filter multipliers. + shr myd, 16 ; Note that the code is 8-tap only, having + cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4 + cmove myd, mxd ; had a negligible effect on performance. + ; TODO: Would a 6-tap code path be worth it? + lea myq, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + vpbroadcastd m7, [pw_8192] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + cmp wd, 8 + jg .v_w16 + je .v_w8 +.v_w4: + movd xm0, [srcq+strideq*0] + vpbroadcastd m1, [srcq+strideq*2] + vpbroadcastd xm2, [srcq+strideq*1] + add srcq, stride3q + vpbroadcastd m3, [srcq+strideq*0] + vpblendd m1, m0, 0x01 ; 0 2 2 _ 2 _ _ _ + vpblendd m3, m2, 0x03 ; 1 1 3 3 3 3 _ _ + vpbroadcastd m0, [srcq+strideq*1] + vpbroadcastd m2, [srcq+strideq*2] + vpblendd m1, m0, 0x68 ; 0 2 2 4 2 4 4 _ + vpbroadcastd m0, [srcq+stride3q ] + vbroadcasti128 m5, [deint_shuf4] + vpblendd m3, m2, 0xc0 ; 1 1 3 3 3 3 5 5 + vpblendd m2, m3, m1, 0x55 ; 0 1 2 3 2 3 4 5 + vpblendd m3, m1, 0xaa ; 1 2 3 4 3 4 5 _ + punpcklbw m1, m2, m3 ; 01 12 23 34 + vpblendd m3, m0, 0x80 ; 1 2 3 4 3 4 5 6 + punpckhbw m2, m3 ; 23 34 45 56 +.v_w4_loop: + lea srcq, [srcq+strideq*4] + pinsrd xm0, [srcq+strideq*0], 1 + vpbroadcastd m3, [srcq+strideq*1] + vpbroadcastd m4, [srcq+strideq*2] + vpblendd m3, m0, 0x03 ; 6 7 8 _ 8 _ _ _ + vpbroadcastd m0, [srcq+stride3q ] + vpblendd m3, m4, 0x20 ; 6 7 8 _ 8 9 _ _ + vpblendd m3, m0, 0x40 ; 6 7 8 _ 8 9 a _ + pshufb m3, m5 ; 67 78 89 9a + pmaddubsw m4, m1, m8 + vperm2i128 m1, m2, m3, 0x21 ; 45 56 67 78 + pmaddubsw m2, m9 + paddw m4, m2 + mova m2, m3 + pmaddubsw m3, m11 + paddw m3, m4 + pmaddubsw m4, m1, m10 + paddw m3, m4 + pmulhrsw m3, m7 + mova [tmpq], m3 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq xm1, [srcq+strideq*0] + vpbroadcastq m4, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m5, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m6, [srcq+strideq*1] + vpbroadcastq m0, [srcq+strideq*2] + vpblendd m1, m4, 0x30 + vpblendd m4, m2, 0x30 + punpcklbw m1, m4 ; 01 12 + vpblendd m2, m5, 0x30 + vpblendd m5, m3, 0x30 + punpcklbw m2, m5 ; 23 34 + vpblendd m3, m6, 0x30 + vpblendd m6, m0, 0x30 + punpcklbw m3, m6 ; 45 56 +.v_w8_loop: + vpbroadcastq m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmaddubsw m5, m2, m9 ; a1 + pmaddubsw m6, m2, m8 ; b0 + vpblendd m2, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*0] + vpblendd m4, m0, 0x30 + punpcklbw m2, m4 ; 67 78 + pmaddubsw m1, m8 ; a0 + pmaddubsw m4, m3, m9 ; b1 + paddw m5, m1 + mova m1, m3 + pmaddubsw m3, m10 ; a2 + paddw m6, m4 + paddw m5, m3 + vpbroadcastq m4, [srcq+strideq*1] + vpblendd m3, m0, m4, 0x30 + vpbroadcastq m0, [srcq+strideq*2] + vpblendd m4, m0, 0x30 + punpcklbw m3, m4 ; 89 9a + pmaddubsw m4, m2, m11 ; a3 + paddw m5, m4 + pmaddubsw m4, m2, m10 ; b2 + paddw m6, m4 + pmaddubsw m4, m3, m11 ; b3 + paddw m6, m4 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + mova [tmpq+32*0], m5 + mova [tmpq+32*1], m6 + add tmpq, 32*2 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + add wd, wd + mov r5, srcq + mov r7, tmpq + lea r6d, [hq+wq*8-256] +.v_w16_loop0: + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m0, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*0] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m1, [srcq+strideq*0] + vbroadcasti128 m2, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+strideq*0] + shufpd m4, m4, m0, 0x0c + shufpd m5, m5, m1, 0x0c + punpcklbw m1, m4, m5 ; 01 + punpckhbw m4, m5 ; 34 + shufpd m6, m6, m2, 0x0c + punpcklbw m2, m5, m6 ; 12 + punpckhbw m5, m6 ; 45 + shufpd m0, m0, m3, 0x0c + punpcklbw m3, m6, m0 ; 23 + punpckhbw m6, m0 ; 56 +.v_w16_loop: + vbroadcasti128 m12, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m13, [srcq+strideq*0] + pmaddubsw m14, m1, m8 ; a0 + pmaddubsw m15, m2, m8 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, m9 ; a1 + pmaddubsw m4, m9 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, m10 ; a2 + pmaddubsw m6, m10 ; b2 + paddw m14, m5 + paddw m15, m6 + shufpd m6, m0, m12, 0x0d + shufpd m0, m12, m13, 0x0c + punpcklbw m5, m6, m0 ; 67 + punpckhbw m6, m0 ; 78 + pmaddubsw m12, m5, m11 ; a3 + pmaddubsw m13, m6, m11 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + mova [tmpq+wq*0], m14 + mova [tmpq+wq*1], m15 + lea tmpq, [tmpq+wq*2] + sub hd, 2 + jg .v_w16_loop + add r5, 16 + add r7, 32 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .v_w16_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + %assign stack_size_padded 0 + WIN64_SPILL_XMM 16 + cmp wd, 4 + je .hv_w4 + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r7+mxq*8+subpel_filters-prep%+SUFFIX+0] + vpbroadcastd m11, [r7+mxq*8+subpel_filters-prep%+SUFFIX+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + jmp .hv_w8 +.hv_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep%+SUFFIX+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep%+SUFFIX] + lea stride3q, [strideq*3] + sub srcq, stride3q + mova m7, [subpel_h_shuf4] + pmovzxbd m9, [deint_shuf4] + vpbroadcastd m10, [pw_8192] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m11, [pd_32] + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + vpbroadcastq m2, [srcq+strideq*0] + vpbroadcastq m4, [srcq+strideq*1] + vpbroadcastq m0, [srcq+strideq*2] + vpbroadcastq m5, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m6, [srcq+strideq*1] + vpbroadcastq m1, [srcq+strideq*2] + vpblendd m2, m4, 0xcc ; 0 1 + vpblendd m0, m5, 0xcc ; 2 3 + vpblendd m3, m6, 0xcc ; 4 5 + pshufb m2, m7 ; 00 01 10 11 02 03 12 13 + pshufb m0, m7 ; 20 21 30 31 22 23 32 33 + pshufb m3, m7 ; 40 41 50 51 42 43 52 53 + pshufb m1, m7 ; 60 61 60 61 62 63 62 63 + pmaddubsw m2, m8 + pmaddubsw m0, m8 + pmaddubsw m3, m8 + pmaddubsw m1, m8 + phaddw m2, m0 ; 0a 1a 2a 3a 0b 1b 2b 3b + phaddw m3, m1 ; 4a 5a 6a __ 4b 5b 6b __ + pmulhrsw m2, m10 + pmulhrsw m3, m10 + palignr m4, m3, m2, 4 ; 1a 2a 3a 4a 1b 2b 3b 4b + punpcklwd m1, m2, m4 ; 01 12 + punpckhwd m2, m4 ; 23 34 + pshufd m0, m3, q2121 + punpcklwd m3, m0 ; 45 56 +.hv_w4_loop: + pmaddwd m5, m1, m12 ; a0 b0 + pmaddwd m6, m2, m12 ; c0 d0 + pmaddwd m2, m13 ; a1 b1 + pmaddwd m4, m3, m13 ; c1 d1 + mova m1, m3 + pmaddwd m3, m14 ; a2 b2 + paddd m5, m2 + vpbroadcastq m2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + paddd m6, m4 + vpbroadcastq m4, [srcq+strideq*0] + paddd m5, m3 + vpbroadcastq m3, [srcq+strideq*1] + vpblendd m2, m4, 0xcc + vpbroadcastq m4, [srcq+strideq*2] + vpblendd m3, m4, 0xcc + pshufb m2, m7 + pshufb m3, m7 + pmaddubsw m2, m8 + pmaddubsw m3, m8 + phaddw m2, m3 + pmulhrsw m2, m10 + palignr m3, m2, m0, 12 + mova m0, m2 + punpcklwd m2, m3, m0 ; 67 78 + punpckhwd m3, m0 ; 89 9a + pmaddwd m4, m2, m14 ; c2 d2 + paddd m6, m11 + paddd m5, m11 + paddd m6, m4 + pmaddwd m4, m2, m15 ; a3 b3 + paddd m5, m4 + pmaddwd m4, m3, m15 ; c3 d3 + paddd m6, m4 + psrad m5, 6 + psrad m6, 6 + packssdw m5, m6 + vpermd m5, m9, m5 + mova [tmpq], m5 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + lea r6d, [wq*8-64] + mov r5, srcq + mov r7, tmpq + lea r6d, [hq+r6*4] +.hv_w8_loop0: + vbroadcasti128 m7, [subpel_h_shufA] + movu xm4, [srcq+strideq*0] + vbroadcasti128 m8, [subpel_h_shufB] + movu xm5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vbroadcasti128 m9, [subpel_h_shufC] + movu xm6, [srcq+strideq*0] + vbroadcasti128 m0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpblendd m4, m0, 0xf0 ; 0 3 + vinserti128 m5, [srcq+strideq*0], 1 ; 1 4 + vinserti128 m6, [srcq+strideq*1], 1 ; 2 5 + lea srcq, [srcq+strideq*2] + vinserti128 m0, [srcq+strideq*0], 1 ; 3 6 + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 + vpbroadcastd m7, [pw_8192] + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + vpermq m6, m6, q3120 + pmulhrsw m0, m7 + pmulhrsw m4, m7 + pmulhrsw m5, m7 + pmulhrsw m6, m7 + vpermq m7, m0, q3120 + punpcklwd m1, m4, m5 ; 01 + punpckhwd m4, m5 ; 34 + punpcklwd m2, m5, m6 ; 12 + punpckhwd m5, m6 ; 45 + punpcklwd m3, m6, m7 ; 23 + punpckhwd m6, m7 ; 56 +.hv_w8_loop: + vextracti128 [tmpq], m0, 1 ; not enough registers + movu xm0, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti128 m0, [srcq+strideq*0], 1 ; 7 8 + pmaddwd m8, m1, m12 ; a0 + pmaddwd m9, m2, m12 ; b0 + mova m1, m3 + mova m2, m4 + pmaddwd m3, m13 ; a1 + pmaddwd m4, m13 ; b1 + paddd m8, m3 + paddd m9, m4 + mova m3, m5 + mova m4, m6 + pmaddwd m5, m14 ; a2 + pmaddwd m6, m14 ; b2 + paddd m8, m5 + paddd m9, m6 + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + vbroadcasti128 m5, [subpel_h_shufA] + HV_H_W8 m0, m5, m6, m7, m5, m6, m7 + vpbroadcastd m5, [pw_8192] + vpbroadcastd m7, [pd_32] + vbroadcasti128 m6, [tmpq] + pmulhrsw m0, m5 + paddd m8, m7 + paddd m9, m7 + vpermq m7, m0, q3120 ; 7 8 + shufpd m6, m6, m7, 0x04 ; 6 7 + punpcklwd m5, m6, m7 ; 67 + punpckhwd m6, m7 ; 78 + pmaddwd m7, m5, m15 ; a3 + paddd m8, m7 + pmaddwd m7, m6, m15 ; b3 + paddd m7, m9 + psrad m8, 6 + psrad m7, 6 + packssdw m8, m7 + vpermq m7, m8, q3120 + mova [tmpq+wq*0], xm7 + vextracti128 [tmpq+wq*2], m7, 1 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .hv_w8_loop + add r5, 8 + add r7, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .hv_w8_loop0 + RET + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro REMAP_REG 2 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %xdefine r14_save r14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + %xdefine r14 r14_save + %undef r14_save + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%macro MC_8TAP_SCALED_H 8 ; dst, tmp[0-6] + movq xm%1, [srcq+ r4] + movq xm%2, [srcq+ r6] + movhps xm%1, [srcq+ r7] + movhps xm%2, [srcq+ r9] + vinserti128 m%1, [srcq+r10], 1 + vinserti128 m%2, [srcq+r11], 1 + vpbroadcastq m%5, [srcq+r13] + vpbroadcastq m%6, [srcq+ rX] + add srcq, ssq + movq xm%3, [srcq+ r4] + movq xm%4, [srcq+ r6] + movhps xm%3, [srcq+ r7] + movhps xm%4, [srcq+ r9] + vinserti128 m%3, [srcq+r10], 1 + vinserti128 m%4, [srcq+r11], 1 + vpbroadcastq m%7, [srcq+r13] + vpbroadcastq m%8, [srcq+ rX] + add srcq, ssq + vpblendd m%1, m%5, 0xc0 + vpblendd m%2, m%6, 0xc0 + vpblendd m%3, m%7, 0xc0 + vpblendd m%4, m%8, 0xc0 + pmaddubsw m%1, m15 + pmaddubsw m%2, m10 + pmaddubsw m%3, m15 + pmaddubsw m%4, m10 + phaddw m%1, m%2 + phaddw m%3, m%4 + phaddw m%1, m%3 + pmulhrsw m%1, m12 +%endmacro + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isprep 0 +cglobal put_8tap_scaled_8bpc, 4, 14, 16, 128, dst, ds, src, ss, w, h, mx, my, dx, dy + %xdefine base_reg r12 + %define rndshift 10 +%else + %assign isprep 1 +cglobal prep_8tap_scaled_8bpc, 4, 14, 16, 128, tmp, src, ss, w, h, mx, my, dx, dy + %define tmp_stridem qword [rsp+120] + %xdefine base_reg r11 + %define rndshift 6 +%endif + lea base_reg, [%1_8tap_scaled_8bpc_avx2] +%define base base_reg-%1_8tap_scaled_8bpc_avx2 + tzcnt wd, wm + vpbroadcastd m8, dxm +%if isprep && UNIX64 + movd xm14, mxd + vpbroadcastd m14, xm14 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 +%else + vpbroadcastd m14, mxm +%endif + mov dyd, dym +%ifidn %1, put + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %else + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %define dsm [rsp+112] + %define rX r1 + %define rXd r1d +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %else + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+112] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define rX r14 + %define rXd r14d +%endif + vpbroadcastd m10, [base+pd_0x3ff] + vpbroadcastd m12, [base+pw_8192] +%ifidn %1, put + vpbroadcastd m13, [base+pd_512] +%else + vpbroadcastd m13, [base+pd_32] +%endif + pxor m9, m9 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_avx2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0,1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*2] + movhps xm0, [srcq+ssq*1] + movhps xm1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*2], 1 + vpbroadcastq m2, [srcq+ssq*1] + vpbroadcastq m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + vpblendd m15, m7, 0xaa + vpblendd m0, m2, 0xc0 ; 0 1 4 5 + vpblendd m1, m3, 0xc0 ; 2 3 6 7 + pblendvb m15, m11, m8 + pshufb m0, m14 + pshufb m1, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + phaddw m0, m1 + pmulhrsw m0, m12 ; 0 1 2 3 4 5 6 7 + vextracti128 xm1, m0, 1 ; 4 5 6 7 + palignr xm2, xm1, xm0, 4 ; 1 2 3 4 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + pshufd xm4, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm4 ; 45 56 + punpckhwd xm4, xm1, xm4 ; 67 __ +.w2_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm11, r6q + pmovsxbw xm11, xm11 + pshufd xm8, xm11, q0000 + pshufd xm9, xm11, q1111 + pshufd xm10, xm11, q2222 + pshufd xm11, xm11, q3333 + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pmaddwd xm7, xm2, xm10 + pmaddwd xm8, xm4, xm11 + paddd xm5, xm6 + paddd xm7, xm8 + paddd xm5, xm13 + paddd xm5, xm7 + psrad xm5, 10 + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq], xm5, 0 + add dstq, dsq + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w2_loop + movq xm5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps xm3, xm0, q1032 ; 01 12 + shufps xm0, xm2, q1032 ; 23 34 + shufps xm2, xm4, q1032 ; 45 56 + pshufb xm5, xm14 + pmaddubsw xm5, xm15 + phaddw xm5, xm5 + pmulhrsw xm5, xm12 + palignr xm1, xm5, xm1, 12 + punpcklqdq xm1, xm1 ; 6 7 6 7 + punpcklwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +.w2_skip_line: + movhps xm5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova xm3, xm0 ; 01 12 + mova xm0, xm2 ; 23 34 + pshufb xm5, xm14 + pmaddubsw xm5, xm15 + phaddw xm5, xm5 + pmulhrsw xm5, xm12 ; 6 7 6 7 + palignr xm1, xm5, xm1, 8 ; 4 5 6 7 + pshufd xm5, xm1, q0321 ; 5 6 7 _ + punpcklwd xm2, xm1, xm5 ; 45 56 + punpckhwd xm4, xm1, xm5 ; 67 __ + jmp .w2_loop +%endif +.w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd xm15, xm0 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pinsrd xm15, [base+subpel_filters+r6*8+2], 1 + pcmpeqd m0, m9 + psrld m14, 10 + movu xm7, [srcq+ssq*0] + movu xm9, [srcq+ssq*1] + pinsrd xm15, [base+subpel_filters+r11*8+2], 2 + movu xm8, [srcq+ssq*2] + movu xm10, [srcq+ss3q ] + pinsrd xm15, [base+subpel_filters+r13*8+2], 3 + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m7, [srcq+ssq*0], 1 + vinserti128 m9, [srcq+ssq*1], 1 + vinserti128 m15, xm15, 1 + vinserti128 m8, [srcq+ssq*2], 1 + vinserti128 m10, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + pblendvb m15, m11, m0 + pshufb m7, m14 + pshufb m9, m14 + pshufb m8, m14 + pshufb m10, m14 + pmaddubsw m7, m15 + pmaddubsw m9, m15 + pmaddubsw m8, m15 + pmaddubsw m10, m15 + phaddw m7, m9 + phaddw m8, m10 + pmulhrsw m7, m12 ; 0 1 4 5 + pmulhrsw m8, m12 ; 2 3 6 7 + vextracti128 xm9, m7, 1 ; 4 5 + vextracti128 xm3, m8, 1 ; 6 7 + shufps xm4, xm7, xm8, q1032 ; 1 2 + shufps xm5, xm8, xm9, q1032 ; 3 4 + shufps xm6, xm9, xm3, q1032 ; 5 6 + psrldq xm11, xm3, 8 ; 7 _ + punpcklwd xm0, xm7, xm4 ; 01 + punpckhwd xm7, xm4 ; 12 + punpcklwd xm1, xm8, xm5 ; 23 + punpckhwd xm8, xm5 ; 34 + punpcklwd xm2, xm9, xm6 ; 45 + punpckhwd xm9, xm6 ; 56 + punpcklwd xm3, xm11 ; 67 + mova [rsp+0x00], xm7 + mova [rsp+0x10], xm8 + mova [rsp+0x20], xm9 +.w4_loop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm10, r6q + pmovsxbw xm10, xm10 + pshufd xm7, xm10, q0000 + pshufd xm8, xm10, q1111 + pshufd xm9, xm10, q2222 + pshufd xm10, xm10, q3333 + pmaddwd xm4, xm0, xm7 + pmaddwd xm5, xm1, xm8 + pmaddwd xm6, xm2, xm9 + pmaddwd xm7, xm3, xm10 + paddd xm4, xm5 + paddd xm6, xm7 + paddd xm4, xm13 + paddd xm4, xm6 + psrad xm4, rndshift + packssdw xm4, xm4 +%ifidn %1, put + packuswb xm4, xm4 + movd [dstq], xm4 + add dstq, dsq +%else + movq [tmpq], xm4 + add tmpq, 8 +%endif + dec hd + jz .ret + add myd, dyd + test myd, ~0x3ff + jz .w4_loop + movu xm4, [srcq] + test myd, 0x400 + jz .w4_skip_line + mova xm0, [rsp+0x00] + mova [rsp+0x00], xm1 + mova xm1, [rsp+0x10] + mova [rsp+0x10], xm2 + mova xm2, [rsp+0x20] + mova [rsp+0x20], xm3 + pshufb xm4, xm14 + pmaddubsw xm4, xm15 + phaddw xm4, xm4 + pmulhrsw xm4, xm12 + punpcklwd xm3, xm11, xm4 + mova xm11, xm4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: + movu xm5, [srcq+ssq*1] + movu m6, [rsp+0x10] + pshufb xm4, xm14 + pshufb xm5, xm14 + pmaddubsw xm4, xm15 + pmaddubsw xm5, xm15 + movu [rsp+0x00], m6 + phaddw xm4, xm5 + pmulhrsw xm4, xm12 + punpcklwd xm9, xm11, xm4 + mova [rsp+0x20], xm9 + psrldq xm11, xm4, 8 + mova xm0, xm1 + mova xm1, xm2 + mova xm2, xm3 + punpcklwd xm3, xm4, xm11 + lea srcq, [srcq+ssq*2] + jmp .w4_loop +.w8: + mov dword [rsp+48], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+48], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+48], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+48], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+48], 16 + movifprep tmp_stridem, 256 +.w_start: +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+72], t0d + mov [rsp+56], srcq + mov [rsp+64], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + jmp .hloop +.hloop_prep: + dec dword [rsp+48] + jz .ret + add qword [rsp+64], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp+16] + vpbroadcastd m15, [rsp+72] + pxor m9, m9 + mov srcq, [rsp+56] + mov r0q, [rsp+64] ; dstq / tmpq +.hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp+16], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + mova [rsp], xm14 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + mov myd, mym + mov dyd, dym + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + vbroadcasti128 m14, [base+wswap] +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq xm11, r6q + punpcklqdq xm11, xm11 + pmovsxbw m11, xm11 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pshufd m8, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m6, m2, m8 + pmaddwd m7, m3, m11 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+52], myd + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + jz .skip_line + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + add srcq, ssq + mov myd, [rsp+52] + mov dyd, dym + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, m10 + phaddw m4, m5 + pslld m5, m4, 16 + paddw m4, m5 + pmulhrsw m4, m12 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .vloop +.skip_line: + mova m0, m1 + mova m1, m2 + mova m2, m3 + vpbroadcastq m7, [srcq+r13] + vpbroadcastq m8, [srcq+ rX] + movq xm3, [srcq+ r4] + movq xm4, [srcq+ r6] + movhps xm3, [srcq+ r7] + movhps xm4, [srcq+ r9] + vinserti128 m3, [srcq+r10], 1 + vinserti128 m4, [srcq+r11], 1 + add srcq, ssq + movq xm5, [srcq+ r4] + movq xm6, [srcq+ r6] + movhps xm5, [srcq+ r7] + movhps xm6, [srcq+ r9] + vinserti128 m5, [srcq+r10], 1 + vinserti128 m6, [srcq+r11], 1 + vpbroadcastq m9, [srcq+r13] + vpbroadcastq m11, [srcq+ rX] + add srcq, ssq + mov myd, [rsp+52] + mov dyd, dym + vpblendd m3, m7, 0xc0 + vpblendd m4, m8, 0xc0 + vpblendd m5, m9, 0xc0 + vpblendd m6, m11, 0xc0 + pmaddubsw m3, m15 + pmaddubsw m4, m10 + pmaddubsw m5, m15 + pmaddubsw m6, m10 + phaddw m3, m4 + phaddw m5, m6 + psrld m4, m3, 16 + pslld m6, m5, 16 + paddw m3, m4 + paddw m5, m6 + pblendw m3, m5, 0xaa + pmulhrsw m3, m12 + jmp .vloop +.dy1: + movzx wd, word [base+%1_8tap_scaled_avx2_dy1_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy1_w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0-1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + movq xm1, [srcq+ssq*2] + movhps xm0, [srcq+ssq*1] + movhps xm1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + vinserti128 m0, [srcq+ssq*0], 1 + vinserti128 m1, [srcq+ssq*2], 1 + vpbroadcastq m2, [srcq+ssq*1] + add srcq, ss3q + movq xm10, r4q + pmovsxbw xm10, xm10 + vpblendd m15, m7, 0xaa + pblendvb m15, m11, m8 + pshufd xm8, xm10, q0000 + pshufd xm9, xm10, q1111 + pshufd xm11, xm10, q3333 + pshufd xm10, xm10, q2222 + vpblendd m0, m2, 0xc0 + pshufb m1, m14 + pshufb m0, m14 + pmaddubsw m1, m15 + pmaddubsw m0, m15 + phaddw m0, m1 + pmulhrsw m0, m12 + vextracti128 xm1, m0, 1 + palignr xm2, xm1, xm0, 4 + pshufd xm4, xm1, q2121 + punpcklwd xm3, xm0, xm2 ; 01 12 + punpckhwd xm0, xm2 ; 23 34 + punpcklwd xm2, xm1, xm4 ; 45 56 +.dy1_w2_loop: + movq xm1, [srcq+ssq*0] + movhps xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd xm5, xm3, xm8 + pmaddwd xm6, xm0, xm9 + pmaddwd xm7, xm2, xm10 + mova xm3, xm0 + mova xm0, xm2 + paddd xm5, xm13 + paddd xm6, xm7 + pshufb xm1, xm14 + pmaddubsw xm1, xm15 + phaddw xm1, xm1 + pmulhrsw xm1, xm12 + palignr xm7, xm1, xm4, 12 + punpcklwd xm2, xm7, xm1 ; 67 78 + pmaddwd xm7, xm2, xm11 + mova xm4, xm1 + paddd xm5, xm6 + paddd xm5, xm7 + psrad xm5, rndshift + packssdw xm5, xm5 + packuswb xm5, xm5 + pextrw [dstq+dsq*0], xm5, 0 + pextrw [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +.dy1_w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + vpermq m8, m8, q3120 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r11d, xm15, 1 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + movu xm2, [srcq+ssq*0] + movu xm3, [srcq+ssq*2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pcmpeqd m8, m9 + psrld m14, 10 + pinsrd xm15, [base+subpel_filters+r11*8+2], 1 + vpblendd m7, [base+subpel_filters+r13*8+2-20], 0x20 + vinserti128 m2, [srcq+ssq*1], 1 + vinserti128 m3, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movu xm4, [srcq+ssq*0] + movu xm5, [srcq+ssq*2] + vinserti128 m4, [srcq+ssq*1], 1 + add srcq, ss3q + vpblendd m15, m7, 0x30 + punpcklqdq m15, m15 + pblendvb m15, m11, m8 + movq xm10, r4q + punpcklqdq xm10, xm10 + pmovsxbw m10, xm10 + pshufb m2, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb xm5, xm14 + vpermq m2, m2, q3120 + vpermq m3, m3, q3120 + vpermq m4, m4, q3120 + vpermq m5, m5, q3120 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m2, m3 + phaddw m4, m5 + pmulhrsw m2, m12 + pmulhrsw m4, m12 + palignr m5, m4, m2, 4 + pshufd m3, m4, q2121 + punpcklwd m0, m2, m5 ; 01 12 + punpckhwd m1, m2, m5 ; 23 34 + punpcklwd m2, m4, m3 ; 45 56 +.dy1_w4_loop: + movu xm11, [srcq+ssq*0] + vinserti128 m11, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + mova m0, m1 + mova m1, m2 + paddd m4, m13 + paddd m5, m6 + pshufb m11, m14 + vpermq m11, m11, q3120 + pmaddubsw m11, m15 + phaddw m11, m11 + pmulhrsw m11, m12 + palignr m6, m11, m3, 12 + punpcklwd m2, m6, m11 ; 67 78 + mova m3, m11 + pmaddwd m6, m2, m10 + paddd m4, m5 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + pshuflw xm4, xm4, q3120 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] +%else + pshufd xm4, xm4, q3120 + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy1_w4_loop + MC_8TAP_SCALED_RET +.dy1_w8: + mov dword [rsp+72], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+72], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+72], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+72], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+72], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+76], t0d + mov [rsp+80], srcq + mov [rsp+88], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+96], xm0 + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+72] + jz .ret + add qword [rsp+88], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp+32] + vpbroadcastd m15, [rsp+76] + pxor m9, m9 + mov srcq, [rsp+80] + mov r0q, [rsp+88] ; dstq / tmpq +.dy1_hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp+32], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + movq [rsp+64], xm14 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + movu [rsp], m10 + vpbroadcastd m8, [rsp+0x60] + vpbroadcastd m9, [rsp+0x64] + vpbroadcastd m10, [rsp+0x68] + vpbroadcastd m11, [rsp+0x6c] + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + vbroadcasti128 m14, [base+wswap] +.dy1_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m10 + pmaddwd m7, m3, m11 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy1_hloop_prep + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + add srcq, ssq + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, [rsp] + phaddw m4, m5 + pslld m5, m4, 16 + paddw m4, m5 + pmulhrsw m4, m12 + pblendw m0, m1, 0xaa + pblendw m1, m2, 0xaa + pblendw m2, m3, 0xaa + pblendw m3, m4, 0xaa + jmp .dy1_vloop +.dy2: + movzx wd, word [base+%1_8tap_scaled_avx2_dy2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy2_w2: + mov myd, mym + movzx t0d, t0b + dec srcq + movd xm15, t0d + punpckldq m8, m9, m8 + paddd m14, m8 ; mx+dx*[0-1] + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + vbroadcasti128 m5, [base+bdct_lb_dw] + vbroadcasti128 m6, [base+subpel_s_shuf2] + vpbroadcastd m15, [base+subpel_filters+r4*8+2] + vpbroadcastd m7, [base+subpel_filters+r6*8+2] + pcmpeqd m8, m9 + psrld m14, 10 + movq xm0, [srcq+ssq*0] + vpbroadcastq m2, [srcq+ssq*1] + movhps xm0, [srcq+ssq*2] + vpbroadcastq m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m14, m5 + paddb m14, m6 + vpblendd m15, m7, 0xaa + pblendvb m15, m11, m8 + movhps xm1, [srcq+ssq*0] + vpbroadcastq m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + vpblendd m0, m2, 0x30 + vpblendd m1, m4, 0xc0 + vpblendd m0, m3, 0xc0 + pshufb m0, m14 + pshufb m1, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + movq xm11, r4q + pmovsxbw xm11, xm11 + phaddw m0, m1 + pmulhrsw m0, m12 ; 0 2 _ 4 1 3 _ 5 + pshufd xm8, xm11, q0000 + pshufd xm9, xm11, q1111 + pshufd xm10, xm11, q2222 + pshufd xm11, xm11, q3333 + pshufd m2, m0, q3110 ; 0 2 2 4 1 3 3 5 + vextracti128 xm1, m2, 1 + punpcklwd xm3, xm2, xm1 ; 01 23 + punpckhwd xm2, xm1 ; 23 45 +.dy2_w2_loop: + movq xm6, [srcq+ssq*0] + vpbroadcastq m7, [srcq+ssq*1] + movhps xm6, [srcq+ssq*2] + vpbroadcastq m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd xm4, xm3, xm8 + pmaddwd xm5, xm2, xm9 + vpblendd m6, m7, 0x30 + vpblendd m6, m1, 0xc0 + pshufb m6, m14 + pmaddubsw m6, m15 + phaddw m6, m6 + pmulhrsw m6, m12 + palignr m0, m6, m0, 8 + pshufd m2, m0, q3221 + vextracti128 xm1, m2, 1 + punpcklwd xm3, xm2, xm1 ; 45 67 + punpckhwd xm2, xm1 ; 67 89 + pmaddwd xm6, xm3, xm10 + pmaddwd xm7, xm2, xm11 + paddd xm4, xm5 + paddd xm4, xm13 + paddd xm6, xm7 + paddd xm4, xm6 + psrad xm4, rndshift + packssdw xm4, xm4 + packuswb xm4, xm4 + pextrw [dstq+dsq*0], xm4, 0 + pextrw [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +.dy2_w4: + mov myd, mym + vbroadcasti128 m7, [base+rescale_mul] + movzx t0d, t0b + dec srcq + movd xm15, t0d + pmaddwd m8, m7 + vpbroadcastd m11, [base+pd_0x4000] + vpbroadcastd xm15, xm15 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd xm15, xm8 + movd r4d, xm15 + pextrd r6d, xm15, 1 + pextrd r11d, xm15, 2 + pextrd r13d, xm15, 3 + movd xm15, [base+subpel_filters+r4*8+2] + vbroadcasti128 m5, [base+bdct_lb_dw] + vpbroadcastq m6, [base+subpel_s_shuf2] + pinsrd xm15, [base+subpel_filters+r6*8+2], 1 + pcmpeqd m8, m9 + psrld m14, 10 + movu xm0, [srcq+ssq*0] + movu xm2, [srcq+ssq*2] + pinsrd xm15, [base+subpel_filters+r11*8+2], 2 + movu xm1, [srcq+ssq*1] + movu xm3, [srcq+ss3q ] + pinsrd xm15, [base+subpel_filters+r13*8+2], 3 + lea srcq, [srcq+ssq*4] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + vinserti128 m15, xm15, 1 + pshufb m14, m5 + paddb m14, m6 + vinserti128 m2, [srcq+ssq*0], 1 + vinserti128 m3, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pblendvb m15, m11, m8 + pshufb xm0, xm14 + pshufb m2, m14 + pshufb xm1, xm14 + pshufb m3, m14 + pmaddubsw xm0, xm15 + pmaddubsw m2, m15 + pmaddubsw xm1, xm15 + pmaddubsw m3, m15 + movq xm11, r4q + punpcklqdq xm11, xm11 + pmovsxbw m11, xm11 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 2 _ 4 + pmulhrsw m1, m12 ; 1 3 _ 5 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + punpcklwd xm2, xm0, xm1 + punpckhwd m1, m0, m1 ; 23 45 + vinserti128 m0, m2, xm1, 1 ; 01 23 +.dy2_w4_loop: + movu xm6, [srcq+ssq*0] + movu xm7, [srcq+ssq*1] + vinserti128 m6, [srcq+ssq*2], 1 + vinserti128 m7, [srcq+ss3q ], 1 + lea srcq, [srcq+ssq*4] + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pshufb m6, m14 + pshufb m7, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + psrld m2, m6, 16 + pslld m3, m7, 16 + paddw m6, m2 + paddw m7, m3 + pblendw m6, m7, 0xaa ; 67 89 + pmulhrsw m6, m12 + paddd m4, m5 + vperm2i128 m0, m1, m6, 0x21 ; 45 67 + mova m1, m6 + pmaddwd m6, m0, m10 + pmaddwd m7, m1, m11 + paddd m4, m13 + paddd m6, m7 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movd [dstq+dsq*0], xm4 + pextrd [dstq+dsq*1], xm4, 1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], xm4 + add tmpq, 16 +%endif + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET +.dy2_w8: + mov dword [rsp+40], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+40], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+40], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+40], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+40], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pmaddwd m8, [base+rescale_mul] + movd xm15, t0d + mov [rsp+64], t0d + mov [rsp+48], srcq + mov [rsp+56], r0q ; dstq / tmpq +%if UNIX64 + mov hm, hd +%endif + shl dword dxm, 3 ; dx*8 + vpbroadcastd m15, xm15 + paddd m14, m8 ; mx+dx*[0-7] + movq xm0, r4q + pmovsxbw xm0, xm0 + mova [rsp+0x50], xm0 + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+40] + jz .ret + add qword [rsp+56], 8*(isprep+1) + mov hd, hm + vpbroadcastd m8, dxm + vpbroadcastd m10, [base+pd_0x3ff] + paddd m14, m8, [rsp] + vpbroadcastd m15, [rsp+64] + pxor m9, m9 + mov srcq, [rsp+48] + mov r0q, [rsp+56] ; dstq / tmpq +.dy2_hloop: + vpbroadcastq m11, [base+pq_0x40000000] + pand m6, m14, m10 + psrld m6, 6 + paddd m15, m6 + pcmpeqd m6, m9 + vextracti128 xm7, m15, 1 + movd r4d, xm15 + pextrd r6d, xm15, 2 + pextrd r7d, xm15, 1 + pextrd r9d, xm15, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + movu [rsp], m14 + movq xm15, [base+subpel_filters+ r4*8] + movq xm10, [base+subpel_filters+ r6*8] + movhps xm15, [base+subpel_filters+ r7*8] + movhps xm10, [base+subpel_filters+ r9*8] + vinserti128 m15, [base+subpel_filters+r10*8], 1 + vinserti128 m10, [base+subpel_filters+r11*8], 1 + vpbroadcastq m9, [base+subpel_filters+r13*8] + vpbroadcastq m8, [base+subpel_filters+ rX*8] + psrld m14, 10 + vextracti128 xm7, m14, 1 + movd r4d, xm14 + pextrd r6d, xm14, 2 + pextrd r7d, xm14, 1 + pextrd r9d, xm14, 3 + movd r10d, xm7 + pextrd r11d, xm7, 2 + pextrd r13d, xm7, 1 + pextrd rXd, xm7, 3 + pshufd m5, m6, q1100 + pshufd m6, m6, q3322 + vpblendd m15, m9, 0xc0 + vpblendd m10, m8, 0xc0 + pblendvb m15, m11, m5 + pblendvb m10, m11, m6 + vbroadcasti128 m14, [base+subpel_s_shuf8] + MC_8TAP_SCALED_H 0, 1, 2, 3, 4, 5, 6, 7 ; 0a 1a 0b 1b + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 8 ; 2a 3a 2b 3b + MC_8TAP_SCALED_H 2, 3, 4, 5, 6, 7, 8, 9 ; 4a 5a 4b 5b + MC_8TAP_SCALED_H 3, 4, 5, 6, 7, 8, 9, 11 ; 6a 7a 6b 7b + vpbroadcastd m8, [rsp+0x50] + vpbroadcastd m9, [rsp+0x54] + vpbroadcastd m11, [rsp+0x58] + vpbroadcastd m4, [rsp+0x5c] + pshufb m0, m14 ; 01a 01b + pshufb m1, m14 ; 23a 23b + pshufb m2, m14 ; 45a 45b + pshufb m3, m14 ; 67a 67b + SWAP m14, m4 +.dy2_vloop: + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m9 + pmaddwd m6, m2, m11 + pmaddwd m7, m3, m14 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 + psrad m4, rndshift + vextracti128 xm5, m4, 1 + packssdw xm4, xm5 +%ifidn %1, put + packuswb xm4, xm4 + movq [dstq], xm4 + add dstq, dsm +%else + mova [tmpq], xm4 + add tmpq, tmp_stridem +%endif + dec hd + jz .dy2_hloop_prep + mova m0, m1 + mova m1, m2 + mova m2, m3 + movq xm3, [srcq+ r4] + movq xm4, [srcq+ r6] + movhps xm3, [srcq+ r7] + movhps xm4, [srcq+ r9] + vinserti128 m3, [srcq+r10], 1 + vinserti128 m4, [srcq+r11], 1 + vpbroadcastq m5, [srcq+r13] + vpbroadcastq m6, [srcq+ rX] + add srcq, ssq + vpblendd m3, m5, 0xc0 + vpblendd m4, m6, 0xc0 + pmaddubsw m3, m15 + pmaddubsw m4, m10 + phaddw m3, m4 + movq xm4, [srcq+ r4] + movq xm5, [srcq+ r6] + movhps xm4, [srcq+ r7] + movhps xm5, [srcq+ r9] + vinserti128 m4, [srcq+r10], 1 + vinserti128 m5, [srcq+r11], 1 + vpbroadcastq m6, [srcq+r13] + vpbroadcastq m7, [srcq+ rX] + add srcq, ssq + vpblendd m4, m6, 0xc0 + vpblendd m5, m7, 0xc0 + pmaddubsw m4, m15 + pmaddubsw m5, m10 + phaddw m4, m5 + psrld m5, m3, 16 + pslld m6, m4, 16 + paddw m3, m5 + paddw m4, m6 + pblendw m3, m4, 0xaa + pmulhrsw m3, m12 + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_8bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, t0d + jmp mangle(private_prefix %+ _%1_8tap_scaled_8bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%else +DECLARE_REG_TMP 6, 8 +%endif + +%define PUT_8TAP_SCALED_FN FN put_8tap_scaled, +%define PREP_8TAP_SCALED_FN FN prep_8tap_scaled, + +BILIN_SCALED_FN put +PUT_8TAP_SCALED_FN sharp, SHARP, SHARP +PUT_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +BILIN_SCALED_FN prep +PREP_8TAP_SCALED_FN sharp, SHARP, SHARP +PREP_8TAP_SCALED_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_SCALED_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_SCALED_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_SCALED_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_SCALED_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_SCALED_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_SCALED_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_SCALED_FN regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%macro WARP_V 5 ; dst, 02, 46, 13, 57 + ; Can be done using gathers, but that's terribly slow on many CPU:s + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm8, [filterq+myq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 ; a e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; b f + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq xm9, [filterq+myq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 ; c g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + shr tmp2d, 10 + shr tmp1d, 10 + punpcklwd m8, m0 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 ; d h + punpcklwd m0, m9, m0 + punpckldq m9, m8, m0 + punpckhdq m0, m8, m0 + punpcklbw m8, m11, m9 ; a0 a2 b0 b2 c0 c2 d0 d2 << 8 + punpckhbw m9, m11, m9 ; a4 a6 b4 b6 c4 c6 d4 d6 << 8 + pmaddwd m%2, m8 + pmaddwd m9, m%3 + punpcklbw m8, m11, m0 ; a1 a3 b1 b3 c1 c3 d1 d3 << 8 + punpckhbw m0, m11, m0 ; a5 a7 b5 b7 c5 c7 d5 d7 << 8 + pmaddwd m8, m%4 + pmaddwd m0, m%5 + paddd m%2, m9 + paddd m0, m8 + paddd m%1, m0, m%2 +%endmacro + +cglobal warp_affine_8x8t_8bpc, 0, 14, 0, tmp, ts +%if WIN64 + sub rsp, 0xa0 +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).main +.loop: + psrad m7, 13 + psrad m0, 13 + packssdw m7, m0 + pmulhrsw m7, m14 ; (x + (1 << 6)) >> 7 + vpermq m7, m7, q3120 + mova [tmpq+tsq*0], xm7 + vextracti128 [tmpq+tsq*2], m7, 1 + dec r4d + jz mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).end + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx2).main2 + lea tmpq, [tmpq+tsq*4] + jmp .loop + +cglobal warp_affine_8x8_8bpc, 0, 14, 0, dst, ds, src, ss, abcd, mx, tmp2, alpha, \ + beta, filter, tmp1, delta, my, gamma +%if WIN64 + sub rsp, 0xa0 + %assign xmm_regs_used 16 + %assign stack_size_padded 0xa0 + %assign stack_offset stack_offset+stack_size_padded +%endif + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m7, 18 + psrad m0, 18 + packusdw m7, m0 + pavgw m7, m11 ; (x + (1 << 10)) >> 11 + vextracti128 xm0, m7, 1 + packuswb xm7, xm0 + pshufd xm7, xm7, q3120 + movq [dstq+dsq*0], xm7 + movhps [dstq+dsq*1], xm7 + dec r4d + jg .loop +.end: + RET +ALIGN function_align +.main: + ; Stack args offset by one (r4m -> r5m etc.) due to call +%if WIN64 + mov abcdq, r5m + mov mxd, r6m + movaps [rsp+stack_offset+0x10], xmm6 + movaps [rsp+stack_offset+0x20], xmm7 + movaps [rsp+0x28], xmm8 + movaps [rsp+0x38], xmm9 + movaps [rsp+0x48], xmm10 + movaps [rsp+0x58], xmm11 + movaps [rsp+0x68], xmm12 + movaps [rsp+0x78], xmm13 + movaps [rsp+0x88], xmm14 + movaps [rsp+0x98], xmm15 +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + mova m12, [warp_8x8_shufA] + mova m13, [warp_8x8_shufB] + vpbroadcastd m14, [pw_8192] + vpbroadcastd m15, [pd_32768] + pxor m11, m11 + lea filterq, [mc_warp_filter2] + lea tmp1q, [ssq*3+3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + 3 + sub betad, tmp2d ; beta -= alpha*3 + mov myd, r7m + call .h + psrld m1, m0, 16 + call .h + psrld m4, m0, 16 + call .h + pblendw m1, m0, 0xaa ; 02 + call .h + pblendw m4, m0, 0xaa ; 13 + call .h + psrld m2, m1, 16 + pblendw m2, m0, 0xaa ; 24 + call .h + psrld m5, m4, 16 + pblendw m5, m0, 0xaa ; 35 + call .h + psrld m3, m2, 16 + pblendw m3, m0, 0xaa ; 46 + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + add myd, 512+(64<<10) + mov r4d, 4 + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 +.main2: + call .h + psrld m6, m5, 16 + pblendw m6, m0, 0xaa ; 57 + WARP_V 7, 1, 3, 4, 6 + call .h + mova m1, m2 + mova m2, m3 + psrld m3, 16 + pblendw m3, m0, 0xaa ; 68 + WARP_V 0, 4, 6, 1, 3 + mova m4, m5 + mova m5, m6 + ret +ALIGN function_align +.h: + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + vbroadcasti128 m10, [srcq] + shr mxd, 10 + shr tmp1d, 10 + movq xm8, [filterq+mxq *8] + vinserti128 m8, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 + shr tmp1d, 10 + movq xm9, [filterq+mxq *8] + vinserti128 m9, [filterq+tmp1q*8], 1 + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + punpcklqdq m8, m0 ; 0 1 4 5 + movq xm0, [filterq+tmp2q*8] + vinserti128 m0, [filterq+tmp1q*8], 1 + punpcklqdq m9, m0 ; 2 3 6 7 + pshufb m0, m10, m12 + pmaddubsw m0, m8 + pshufb m10, m13 + pmaddubsw m10, m9 + add srcq, ssq + phaddw m0, m10 + pmaddwd m0, m14 ; 17-bit intermediate, upshifted by 13 + paddd m0, m15 ; rounded 14-bit result in upper 16 bits of dword + ret + +%macro BIDIR_FN 1 ; op + %1 0 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 4 + je .ret + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + cmp hd, 8 + je .ret + %1 2 + lea dstq, [dstq+strideq*4] + vextracti128 xm1, m0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.ret: + RET +.w8_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*4] +.w8: + vextracti128 xm1, m0, 1 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq*4] +.w16: + vpermq m0, m0, q3120 + mova [dstq ], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq*2] +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + %1_INC_PTR 4 + %1 0 + add dstq, strideq +.w64: + vpermq m0, m0, q3120 + mova [dstq], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+32], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + %1 0 + add dstq, strideq +.w128: + vpermq m0, m0, q3120 + mova [dstq+0*32], m0 + %1 2 + vpermq m0, m0, q3120 + mova [dstq+1*32], m0 + %1_INC_PTR 8 + %1 -4 + vpermq m0, m0, q3120 + mova [dstq+2*32], m0 + %1 -2 + vpermq m0, m0, q3120 + mova [dstq+3*32], m0 + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + mova m0, [tmp1q+(%1+0)*32] + paddw m0, [tmp2q+(%1+0)*32] + mova m1, [tmp1q+(%1+1)*32] + paddw m1, [tmp2q+(%1+1)*32] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + packuswb m0, m1 +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*32 + add tmp2q, %1*32 +%endmacro + +cglobal avg_8bpc, 4, 7, 3, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg %+ SUFFIX %+ _table + lea r6, [avg %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m2, [base+pw_1024] + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m0, [tmp1q+(%1+0)*32] + psubw m2, m0, [tmp2q+(%1+0)*32] + mova m1, [tmp1q+(%1+1)*32] + psubw m3, m1, [tmp2q+(%1+1)*32] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg %+ SUFFIX %+ _table + lea r6, [w_avg %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + vpbroadcastw m4, r6m ; weight + movsxd wq, dword [r6+wq*4] + vpbroadcastd m5, [base+pw_2048] + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + pxor m0, m0 + mov tmp1q, tmp2q + psubw m4, m0, m4 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 + vpermq m3, [maskq+%1*16], q3120 + mova m0, [tmp2q+(%1+0)*32] + psubw m1, m0, [tmp1q+(%1+0)*32] + psubb m3, m4, m3 + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 + punpcklbw m2, m4, m3 ; -m << 9 + pmulhw m1, m2 + paddw m0, m1 + mova m1, [tmp2q+(%1+1)*32] + psubw m2, m1, [tmp1q+(%1+1)*32] + paddw m2, m2 + punpckhbw m3, m4, m3 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*16 + add tmp2q, %1*32 + add tmp1q, %1*32 +%endmacro + +cglobal mask_8bpc, 4, 8, 6, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask %+ SUFFIX %+ _table + lea r7, [mask %+ SUFFIX %+ _table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + vpbroadcastd m5, [base+pw_2048] + pxor m4, m4 + add wq, r7 + BIDIR_FN MASK + +%macro W_MASK 4-5 0 ; dst, mask, tmp_offset[1-2], 4:4:4 + mova m%1, [tmp1q+32*%3] + mova m1, [tmp2q+32*%3] + psubw m1, m%1 + pabsw m%2, m1 + psubusw m%2, m6, m%2 + psrlw m%2, 8 ; 64 - m + psllw m2, m%2, 10 + pmulhw m1, m2 + paddw m%1, m1 + mova m1, [tmp1q+32*%4] + mova m2, [tmp2q+32*%4] + psubw m2, m1 + pabsw m3, m2 + psubusw m3, m6, m3 + psrlw m3, 8 +%if %5 + packuswb m%2, m3 + psubb m%2, m5, m%2 + vpermq m%2, m%2, q3120 +%else + phaddw m%2, m3 +%endif + psllw m3, 10 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m%1, m7 + pmulhrsw m1, m7 + packuswb m%1, m1 +%endmacro + +cglobal blend_8bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_avx2_table + lea r6, [blend_avx2_table] + tzcnt wd, wm + movifnidn maskq, maskmp + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m4, [base+pb_64] + vpbroadcastd m5, [base+pw_512] + sub tmpq, maskq + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + vpbroadcastd xm1, [dstq+dsq*2] + pinsrd xm1, [dstq+r6 ], 3 + mova xm6, [maskq] + psubb xm3, xm4, xm6 + punpcklbw xm2, xm3, xm6 + punpckhbw xm3, xm6 + mova xm6, [maskq+tmpq] + add maskq, 4*4 + punpcklbw xm0, xm6 + punpckhbw xm1, xm6 + pmaddubsw xm0, xm2 + pmaddubsw xm1, xm3 + pmulhrsw xm0, xm5 + pmulhrsw xm1, xm5 + packuswb xm0, xm1 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + pextrd [dstq+dsq*2], xm0, 2 + pextrd [dstq+r6 ], xm0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +ALIGN function_align +.w8: + movq xm1, [dstq+dsq*0] + movhps xm1, [dstq+dsq*1] + vpbroadcastq m2, [dstq+dsq*2] + vpbroadcastq m3, [dstq+r6 ] + mova m0, [maskq] + mova m6, [maskq+tmpq] + add maskq, 8*4 + vpblendd m1, m2, 0x30 + vpblendd m1, m3, 0xc0 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + vextracti128 xm1, m0, 1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + movq [dstq+dsq*2], xm1 + movhps [dstq+r6 ], xm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + RET +ALIGN function_align +.w16: + mova m0, [maskq] + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + mova m6, [maskq+tmpq] + add maskq, 16*2 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16 + RET +ALIGN function_align +.w32: + mova m0, [maskq] + mova m1, [dstq] + mova m6, [maskq+tmpq] + add maskq, 32 + psubb m3, m4, m0 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + punpcklbw m0, m1, m6 + punpckhbw m1, m6 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_avx2_table + lea r5, [blend_v_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_avx2_table + jmp wq +.w2: + vpbroadcastd xm2, [maskq+2*2] +.w2_s0_loop: + movd xm0, [dstq+dsq*0] + pinsrw xm0, [dstq+dsq*1], 1 + movd xm1, [tmpq] + add tmpq, 2*2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_s0_loop + RET +ALIGN function_align +.w4: + vpbroadcastq xm2, [maskq+4*2] +.w4_loop: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + movq xm1, [tmpq] + add tmpq, 4*2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +ALIGN function_align +.w8: + mova xm3, [maskq+8*2] +.w8_loop: + movq xm0, [dstq+dsq*0] + vpbroadcastq xm1, [dstq+dsq*1] + mova xm2, [tmpq] + add tmpq, 8*2 + punpcklbw xm0, xm2 + punpckhbw xm1, xm2 + pmaddubsw xm0, xm3 + pmaddubsw xm1, xm3 + pmulhrsw xm0, xm5 + pmulhrsw xm1, xm5 + packuswb xm0, xm1 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m3, [maskq+16*2] + vbroadcasti128 m4, [maskq+16*3] +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + mova m2, [tmpq] + add tmpq, 16*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +ALIGN function_align +.w32: + mova xm3, [maskq+16*4] + vinserti128 m3, [maskq+16*6], 1 + mova xm4, [maskq+16*5] + vinserti128 m4, [maskq+16*7], 1 +.w32_loop: + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .w32_loop + RET + +cglobal blend_h_8bpc, 4, 7, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_h_avx2_table + lea r5, [blend_h_avx2_table] + mov r6d, wd + tzcnt wd, wd + mov hd, hm + movsxd wq, dword [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xm0, [dstq+dsq*0] + pinsrw xm0, [dstq+dsq*1], 1 + movd xm2, [maskq+hq*2] + movd xm1, [tmpq] + add tmpq, 2*2 + punpcklwd xm2, xm2 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + pextrw [dstq+dsq*0], xm0, 0 + pextrw [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +ALIGN function_align +.w4: + mova xm3, [blend_shuf] +.w4_loop: + movd xm0, [dstq+dsq*0] + pinsrd xm0, [dstq+dsq*1], 1 + movd xm2, [maskq+hq*2] + movq xm1, [tmpq] + add tmpq, 4*2 + pshufb xm2, xm3 + punpcklbw xm0, xm1 + pmaddubsw xm0, xm2 + pmulhrsw xm0, xm5 + packuswb xm0, xm0 + movd [dstq+dsq*0], xm0 + pextrd [dstq+dsq*1], xm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +ALIGN function_align +.w8: + vbroadcasti128 m4, [blend_shuf] + shufpd m4, m4, 0x03 +.w8_loop: + vpbroadcastq m1, [dstq+dsq*0] + movq xm0, [dstq+dsq*1] + vpblendd m0, m1, 0x30 + vpbroadcastd m3, [maskq+hq*2] + movq xm1, [tmpq+8*1] + vinserti128 m1, [tmpq+8*0], 1 + add tmpq, 8*2 + pshufb m3, m4 + punpcklbw m0, m1 + pmaddubsw m0, m3 + pmulhrsw m0, m5 + vextracti128 xm1, m0, 1 + packuswb xm0, xm1 + movhps [dstq+dsq*0], xm0 + movq [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + RET +ALIGN function_align +.w16: + vbroadcasti128 m4, [blend_shuf] + shufpd m4, m4, 0x0c +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti128 m1, [dstq+dsq*1], 1 + vpbroadcastd m3, [maskq+hq*2] + mova m2, [tmpq] + add tmpq, 16*2 + pshufb m3, m4 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +ALIGN function_align +.w32: ; w32/w64/w128 + sub dsq, r6 +.w32_loop0: + vpbroadcastw m3, [maskq+hq*2] + mov wd, r6d +.w32_loop: + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, 32 + sub wd, 32 + jg .w32_loop + add dstq, dsq + inc hq + jl .w32_loop0 + RET + +cglobal emu_edge_8bpc, 10, 13, 1, bw, bh, iw, ih, x, y, dst, dstride, src, sstride, \ + bottomext, rightext + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor r12d, r12d + lea r10, [ihq-1] + cmp yq, ihq + cmovs r10, yq + test yq, yq + cmovs r10, r12 + imul r10, sstrideq + add srcq, r10 + + ; ref += iclip(x, 0, iw - 1) + lea r10, [iwq-1] + cmp xq, iwq + cmovs r10, xq + test xq, xq + cmovs r10, r12 + add srcq, r10 + + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) + lea bottomextq, [yq+bhq] + sub bottomextq, ihq + lea r3, [bhq-1] + cmovs bottomextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, x, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, r12 + cmp bottomextq, bhq + cmovns bottomextq, r3 + cmp topextq, bhq + cmovg topextq, r3 + + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + lea rightextq, [xq+bwq] + sub rightextq, iwq + lea r2, [bwq-1] + cmovs rightextq, r12 + + DEFINE_ARGS bw, bh, iw, ih, leftext, topext, dst, dstride, src, sstride, \ + bottomext, rightext + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, r12 + cmp rightextq, bwq + cmovns rightextq, r2 + cmp leftextq, bwq + cmovns leftextq, r2 + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, topext, \ + dst, dstride, src, sstride, bottomext, rightext + + ; center_h = bh - top_ext - bottom_ext + lea r3, [bottomextq+topextq] + sub centerhq, r3 + + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq + imul r2, dstrideq + add dstq, r2 + mov r9m, dstq + + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq + lea r3, [rightextq+leftextq] + sub centerwq, r3 + +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix +.v_loop_%3: +%if %1 + ; left extension + xor r3, r3 + vpbroadcastb m0, [srcq] +.left_loop_%3: + mova [dstq+r3], m0 + add r3, 32 + cmp r3, leftextq + jl .left_loop_%3 + + ; body + lea r12, [dstq+leftextq] +%endif + xor r3, r3 +.body_loop_%3: + movu m0, [srcq+r3] +%if %1 + movu [r12+r3], m0 +%else + movu [dstq+r3], m0 +%endif + add r3, 32 + cmp r3, centerwq + jl .body_loop_%3 + +%if %2 + ; right extension +%if %1 + add r12, centerwq +%else + lea r12, [dstq+centerwq] +%endif + xor r3, r3 + vpbroadcastb m0, [srcq+centerwq-1] +.right_loop_%3: + movu [r12+r3], m0 + add r3, 32 + cmp r3, rightextq + jl .right_loop_%3 + +%endif + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 +%endmacro + + test leftextq, leftextq + jnz .need_left_ext + test rightextq, rightextq + jnz .need_right_ext + v_loop 0, 0, 0 + jmp .body_done + +.need_left_ext: + test rightextq, rightextq + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: + ; bottom edge extension + test bottomextq, bottomextq + jz .top + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 +.bottom_x_loop: + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, bottomextq +.bottom_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .bottom_y_loop + add r1, 32 + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end + mov srcq, r9m + mov dstq, dstm + xor r1, r1 +.top_x_loop: + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, topextq +.top_y_loop: + mova [r3], m0 + add r3, dstrideq + dec r4 + jg .top_y_loop + add r1, 32 + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +cglobal resize_8bpc, 6, 12, 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ + + vpbroadcastd xm3, [base+pw_m256] + vpbroadcastd m7, [base+pd_63] + vbroadcasti128 m15, [base+pb_8x0_8x8] + pmaddwd m2, m5, [base+rescale_mul] ; dx*[0,1,2,3,4,5,6,7] + pslld m5, 3 ; dx*8 + pslld m6, 14 + paddd m8, m2 ; mx+[0..7]*dx + pxor m2, m2 + + ; m2 = 0, m3 = pmulhrsw constant for x=(x+64)>>7 + ; m8 = mx+[0..7]*dx, m5 = dx*8, m6 = src_w, m7 = 0x3f, m15=0,8 + +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx + +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + pand m9, m7 ; filter offset (masked) + + ; load source pixels - this ugly code is vpgatherdq emulation since + ; directly using vpgatherdq on Haswell is quite a bit slower :( + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vextracti128 xm0, m0, 1 + movq xm12, [srcq+r8] + movq xm13, [srcq+r10] + movhps xm12, [srcq+r9] + movhps xm13, [srcq+r11] + movd r8d, xm0 + pextrd r9d, xm0, 1 + pextrd r10d, xm0, 2 + pextrd r11d, xm0, 3 + vinserti128 m12, [srcq+r8], 1 + vinserti128 m13, [srcq+r10], 1 + vpbroadcastq m10, [srcq+r9] + vpbroadcastq m11, [srcq+r11] + vpblendd m12, m10, 11000000b + vpblendd m13, m11, 11000000b + + ; if no emulation is required, we don't need to shuffle or emulate edges + ; this also saves 2 quasi-vpgatherdqs + vptest m1, m1 + jz .filter + + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vextracti128 xm1, m1, 1 + movq xm14, [base+resize_shuf+4+r8] + movq xm0, [base+resize_shuf+4+r10] + movhps xm14, [base+resize_shuf+4+r9] + movhps xm0, [base+resize_shuf+4+r11] + movq r9, xm1 + pextrq r11, xm1, 1 + movsxd r8, r9d + sar r9, 32 + movsxd r10, r11d + sar r11, 32 + vinserti128 m14, [base+resize_shuf+4+r8], 1 + vinserti128 m0, [base+resize_shuf+4+r10], 1 + vpbroadcastq m10, [base+resize_shuf+4+r9] + vpbroadcastq m11, [base+resize_shuf+4+r11] + vpblendd m14, m10, 11000000b + vpblendd m0, m11, 11000000b + + paddb m14, m15 + paddb m0, m15 + pshufb m12, m14 + pshufb m13, m0 + +.filter: + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vextracti128 xm9, m9, 1 + movq xm10, [base+resize_filter+r8*8] + movq xm11, [base+resize_filter+r10*8] + movhps xm10, [base+resize_filter+r9*8] + movhps xm11, [base+resize_filter+r11*8] + movd r8d, xm9 + pextrd r9d, xm9, 1 + pextrd r10d, xm9, 2 + pextrd r11d, xm9, 3 + vinserti128 m10, [base+resize_filter+r8*8], 1 + vinserti128 m11, [base+resize_filter+r10*8], 1 + vpbroadcastq m14, [base+resize_filter+r9*8] + vpbroadcastq m1, [base+resize_filter+r11*8] + vpblendd m10, m14, 11000000b + vpblendd m11, m1, 11000000b + + pmaddubsw m12, m10 + pmaddubsw m13, m11 + phaddw m12, m13 + vextracti128 xm13, m12, 1 + phaddsw xm12, xm13 + pmulhrsw xm12, xm3 ; x=(x+64)>>7 + packuswb xm12, xm12 + movq [dstq+xq], xm12 + + paddd m4, m5 + add xd, 8 + cmp xd, dst_wd + jl .loop_x + + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +cglobal w_mask_420_8bpc, 4, 8, 14, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx2_table + lea r7, [w_mask_420_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + pmovzxbd m9, [base+deint_shuf4] + vpbroadcastd m8, [base+wm_420_sign+r6*4] ; 258 - sign + add wq, r7 + W_MASK 0, 4, 0, 1 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + jg .w4_h16 +.w4_end: + vextracti128 xm0, m4, 1 + vpblendd xm1, xm4, xm0, 0x05 + vpblendd xm4, xm0, 0x0a + pshufd xm1, xm1, q2301 + psubw xm4, xm8, xm4 + psubw xm4, xm1 + psrlw xm4, 2 + packuswb xm4, xm4 + movq [maskq], xm4 + RET +.w4_h16: + W_MASK 0, 5, 2, 3 + lea dstq, [dstq+strideq*4] + phaddd m4, m5 + vextracti128 xm1, m0, 1 + psubw m4, m8, m4 + psrlw m4, 2 + vpermd m4, m9, m4 + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq], xm4 + RET +.w8_loop: + add tmp1q, 2*32 + add tmp2q, 2*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 8 +.w8: + vextracti128 xm2, m4, 1 + vextracti128 xm1, m0, 1 + psubw xm4, xm8, xm4 + psubw xm4, xm2 + psrlw xm4, 2 + packuswb xm4, xm4 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + movq [maskq], xm4 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + W_MASK 0, 5, 2, 3 + punpckhqdq m1, m4, m5 + punpcklqdq m4, m5 + psubw m1, m8, m1 + psubw m1, m4 + psrlw m1, 2 + vpermq m0, m0, q3120 + packuswb m1, m1 + vpermd m1, m9, m1 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + mova [maskq], xm1 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*2] + add maskq, 16 +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + W_MASK 0, 5, 2, 3 + psubw m4, m8, m4 + psubw m4, m5 + psrlw m4, 2 + vpermq m0, m0, q3120 + packuswb m4, m4 + vpermd m4, m9, m4 + mova [dstq+strideq*1], m0 + mova [maskq], xm4 + sub hd, 2 + jg .w32_loop + RET +.w64_loop_even: + psubw m10, m8, m4 + psubw m11, m8, m5 + dec hd +.w64_loop: + add tmp1q, 4*32 + add tmp2q, 4*32 + W_MASK 0, 4, 0, 1 + add dstq, strideq +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + test hd, 1 + jz .w64_loop_even + psubw m4, m10, m4 + psubw m5, m11, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq], m4 + add maskq, 32 + dec hd + jg .w64_loop + RET +.w128_loop_even: + psubw m12, m8, m4 + psubw m13, m8, m5 + dec hd +.w128_loop: + W_MASK 0, 4, 0, 1 + add dstq, strideq +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + add tmp1q, 8*32 + add tmp2q, 8*32 + test hd, 1 + jz .w128_even + psubw m4, m10, m4 + psubw m5, m11, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq+32*0], m4 + jmp .w128_odd +.w128_even: + psubw m10, m8, m4 + psubw m11, m8, m5 +.w128_odd: + W_MASK 0, 4, -4, -3 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + W_MASK 0, 5, -2, -1 + vpermq m0, m0, q3120 + mova [dstq+32*3], m0 + test hd, 1 + jz .w128_loop_even + psubw m4, m12, m4 + psubw m5, m13, m5 + psrlw m4, 2 + psrlw m5, 2 + packuswb m4, m5 + vpermd m4, m9, m4 + mova [maskq+32*1], m4 + add maskq, 64 + dec hd + jg .w128_loop + RET + +cglobal w_mask_422_8bpc, 4, 8, 11, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx2_table + lea r7, [w_mask_422_avx2_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + pxor m9, m9 + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + pmovzxbd m10, [base+deint_shuf4] + vpbroadcastd m8, [base+wm_422_sign+r6*4] ; 128 - sign + add wq, r7 + mov maskq, maskmp + W_MASK 0, 4, 0, 1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + jg .w4_h16 +.w4_end: + vextracti128 xm5, m4, 1 + packuswb xm4, xm5 + psubb xm5, xm8, xm4 + pavgb xm5, xm9 + pshufd xm5, xm5, q3120 + mova [maskq], xm5 + RET +.w4_h16: + W_MASK 0, 5, 2, 3 + lea dstq, [dstq+strideq*4] + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermd m5, m10, m5 + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq], m5 + RET +.w8_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 16 +.w8: + vextracti128 xm5, m4, 1 + vextracti128 xm1, m0, 1 + packuswb xm4, xm5 + psubb xm5, xm8, xm4 + pavgb xm5, xm9 + pshufd xm5, xm5, q3120 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + mova [maskq], xm5 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+strideq*2], xm0 + vextracti128 [dstq+stride3q ], m0, 1 + mova [maskq], m5 + sub hd, 4 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w32: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+strideq*1], m0 + mova [maskq], m5 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1 + add dstq, strideq + add maskq, 32 +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*1], m0 + mova [maskq], m5 + dec hd + jg .w64_loop + RET +.w128_loop: + add tmp1q, 32*8 + add tmp2q, 32*8 + W_MASK 0, 4, 0, 1 + add dstq, strideq + add maskq, 32*2 +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + W_MASK 0, 5, 2, 3 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*1], m0 + mova [maskq+32*0], m5 + W_MASK 0, 4, 4, 5 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + W_MASK 0, 5, 6, 7 + packuswb m4, m5 + psubb m5, m8, m4 + pavgb m5, m9 + vpermq m0, m0, q3120 + vpermd m5, m10, m5 + mova [dstq+32*3], m0 + mova [maskq+32*1], m5 + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 8, 8, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx2_table + lea r7, [w_mask_444_avx2_table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m5, [base+pb_64] + vpbroadcastd m7, [base+pw_2048] + add wq, r7 + W_MASK 0, 4, 0, 1, 1 + lea stride3q, [strideq*3] + jmp wq +.w4: + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + mova [maskq+32*0], m4 + cmp hd, 8 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + je .w4_end + W_MASK 0, 4, 2, 3, 1 + lea dstq, [dstq+strideq*4] + vextracti128 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 + mova [maskq+32*1], m4 +.w4_end: + RET +.w8_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + lea dstq, [dstq+strideq*4] + add maskq, 32 +.w8: + vextracti128 xm1, m0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + mova [maskq], m4 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + lea dstq, [dstq+strideq*2] + add maskq, 32 +.w16: + vpermq m0, m0, q3120 + mova [dstq+strideq*0], xm0 + vextracti128 [dstq+strideq*1], m0, 1 + mova [maskq], m4 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + add tmp1q, 32*2 + add tmp2q, 32*2 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32 +.w32: + vpermq m0, m0, q3120 + mova [dstq], m0 + mova [maskq], m4 + dec hd + jg .w32_loop + RET +.w64_loop: + add tmp1q, 32*4 + add tmp2q, 32*4 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32*2 +.w64: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + mova [maskq+32*0], m4 + W_MASK 0, 4, 2, 3, 1 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + mova [maskq+32*1], m4 + dec hd + jg .w64_loop + RET +.w128_loop: + add tmp1q, 32*8 + add tmp2q, 32*8 + W_MASK 0, 4, 0, 1, 1 + add dstq, strideq + add maskq, 32*4 +.w128: + vpermq m0, m0, q3120 + mova [dstq+32*0], m0 + mova [maskq+32*0], m4 + W_MASK 0, 4, 2, 3, 1 + vpermq m0, m0, q3120 + mova [dstq+32*1], m0 + mova [maskq+32*1], m4 + W_MASK 0, 4, 4, 5, 1 + vpermq m0, m0, q3120 + mova [dstq+32*2], m0 + mova [maskq+32*2], m4 + W_MASK 0, 4, 6, 7, 1 + vpermq m0, m0, q3120 + mova [dstq+32*3], m0 + mova [maskq+32*3], m4 + dec hd + jg .w128_loop + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx512.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx512.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx512.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_avx512.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4538 @@ +; Copyright © 2020, VideoLAN and dav1d authors +; Copyright © 2020, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 64 + +obmc_masks: +pw_512: times 2 dw 512 + ; 2 + db 45, 19, 64, 0 + ; 4 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + db 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0 + +warp_8x8_permA: db 4, 5, 6, 7, 16, 17, 18, 19, 5, 6, 7, 8, 17, 18, 19, 20 + db 6, 7, 8, 9, 18, 19, 20, 21, 7, 8, 9, 10, 19, 20, 21, 22 + db 8, 9, 10, 11, 20, 21, 22, 23, 9, 10, 11, 12, 21, 22, 23, 24 + db 10, 11, 12, 13, 22, 23, 24, 25, 11, 12, 13, 14, 23, 24, 25, 26 +warp_8x8_permB: db 0, 1, 2, 3, 20, 21, 22, 23, 1, 2, 3, 4, 21, 22, 23, 24 + db 2, 3, 4, 5, 22, 23, 24, 25, 3, 4, 5, 6, 23, 24, 25, 26 + db 4, 5, 6, 7, 24, 25, 26, 27, 5, 6, 7, 8, 25, 26, 27, 28 + db 6, 7, 8, 9, 26, 27, 28, 29, 7, 8, 9, 10, 27, 28, 29, 30 +warp_8x8_permC: db -1, 0, -1, 1, -1, 8, -1, 9, -1, 4, -1, 5, -1, 12, -1, 13 +warp_8x8_permD: db -1, 2, -1, 3, -1, 10, -1, 11, -1, 6, -1, 7, -1, 14, -1, 15 +pd_0to7: dd 0, 1, 2, 3, 4, 5, 6, 7 +warp_8x8_hpack: db 3, 11, 3, 11, 35, 43, 35, 43 +pd_16384: dd 16384 +pd_262144: dd 262144 +warp_8x8_end: db 0, 4, 16, 20, 32, 36, 48, 52, 2, 6, 18, 22, 34, 38, 50, 54 +warp_8x8t_end: db 2, 3, 10, 11, 18, 19, 26, 27, 34, 35, 42, 43, 50, 51, 58, 59 + db 6, 7, 14, 15, 22, 23, 30, 31, 38, 39, 46, 47, 54, 55, 62, 63 +bidir_sctr_w4: dd 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +wm_420_perm4: db 1, 3, 9, 11, 5, 7, 13, 15, 17, 19, 25, 27, 21, 23, 29, 31 + db 33, 35, 41, 43, 37, 39, 45, 47, 49, 51, 57, 59, 53, 55, 61, 63 + db 0, 2, 8, 10, 4, 6, 12, 14, 16, 18, 24, 26, 20, 22, 28, 30 + db 32, 34, 40, 42, 36, 38, 44, 46, 48, 50, 56, 58, 52, 54, 60, 62 +wm_420_perm8: db 1, 3, 17, 19, 5, 7, 21, 23, 9, 11, 25, 27, 13, 15, 29, 31 + db 33, 35, 49, 51, 37, 39, 53, 55, 41, 43, 57, 59, 45, 47, 61, 63 + db 0, 2, 16, 18, 4, 6, 20, 22, 8, 10, 24, 26, 12, 14, 28, 30 + db 32, 34, 48, 50, 36, 38, 52, 54, 40, 42, 56, 58, 44, 46, 60, 62 +wm_420_perm16: db 1, 3, 33, 35, 5, 7, 37, 39, 9, 11, 41, 43, 13, 15, 45, 47 + db 17, 19, 49, 51, 21, 23, 53, 55, 25, 27, 57, 59, 29, 31, 61, 63 + db 0, 2, 32, 34, 4, 6, 36, 38, 8, 10, 40, 42, 12, 14, 44, 46 + db 16, 18, 48, 50, 20, 22, 52, 54, 24, 26, 56, 58, 28, 30, 60, 62 +wm_420_mask: db 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63 + db 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127 + db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +wm_422_mask: db 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62 + db 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61 + db 66, 70, 74, 78, 82, 86, 90, 94, 98,102,106,110,114,118,122,126 + db 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125 +wm_444_mask: db 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + db 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + db 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + db 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 +bilin_h_perm16: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 + db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15 + db 33, 32, 34, 33, 35, 34, 36, 35, 37, 36, 38, 37, 39, 38, 40, 39 + db 41, 40, 42, 41, 43, 42, 44, 43, 45, 44, 46, 45, 47, 46, 48, 47 +bilin_h_perm32: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 + db 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 15, 14, 16, 15 + db 17, 16, 18, 17, 19, 18, 20, 19, 21, 20, 22, 21, 23, 22, 24, 23 + db 25, 24, 26, 25, 27, 26, 28, 27, 29, 28, 30, 29, 31, 30, 32, 31 +bilin_v_perm8: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7 + db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23 + db 32, 80, 33, 81, 34, 82, 35, 83, 36, 84, 37, 85, 38, 86, 39, 87 + db 64, 32, 65, 33, 66, 34, 67, 35, 68, 36, 69, 37, 70, 38, 71, 39 +bilin_v_perm16: db 16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7 + db 24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15 + db 64, 16, 65, 17, 66, 18, 67, 19, 68, 20, 69, 21, 70, 22, 71, 23 + db 72, 24, 73, 25, 74, 26, 75, 27, 76, 28, 77, 29, 78, 30, 79, 31 +bilin_v_perm32: db 64, 0, 65, 1, 66, 2, 67, 3, 68, 4, 69, 5, 70, 6, 71, 7 + db 72, 8, 73, 9, 74, 10, 75, 11, 76, 12, 77, 13, 78, 14, 79, 15 + db 80, 16, 81, 17, 82, 18, 83, 19, 84, 20, 85, 21, 86, 22, 87, 23 + db 88, 24, 89, 25, 90, 26, 91, 27, 92, 28, 93, 29, 94, 30, 95, 31 +bilin_v_perm64: dq 0, 4, 1, 5, 2, 6, 3, 7 +spel_h_perm16a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 + db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38 + db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46 +spel_h_perm16b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 + db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18 + db 36, 37, 38, 39, 37, 38, 39, 40, 38, 39, 40, 41, 39, 40, 41, 42 + db 44, 45, 46, 47, 45, 46, 47, 48, 46, 47, 48, 49, 47, 48, 49, 50 +spel_h_perm16c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 40, 41, 42, 43, 41, 42, 43, 44, 42, 43, 44, 45, 43, 44, 45, 46 + db 48, 49, 50, 51, 49, 50, 51, 52, 50, 51, 52, 53, 51, 52, 53, 54 +spel_h_perm32a: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 + db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30 +spel_h_perm32b: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 + db 12, 13, 14, 15, 13, 14, 15, 16, 14, 15, 16, 17, 15, 16, 17, 18 + db 20, 21, 22, 23, 21, 22, 23, 24, 22, 23, 24, 25, 23, 24, 25, 26 + db 28, 29, 30, 31, 29, 30, 31, 32, 30, 31, 32, 33, 31, 32, 33, 34 +spel_h_perm32c: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 + db 16, 17, 18, 19, 17, 18, 19, 20, 18, 19, 20, 21, 19, 20, 21, 22 + db 24, 25, 26, 27, 25, 26, 27, 28, 26, 27, 28, 29, 27, 28, 29, 30 + db 32, 33, 34, 35, 33, 34, 35, 36, 34, 35, 36, 37, 35, 36, 37, 38 +spel_v_perm16: db 32, 0, 33, 1, 34, 2, 35, 3, 36, 4, 37, 5, 38, 6, 39, 7 + db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 + db 40, 16, 41, 17, 42, 18, 43, 19, 44, 20, 45, 21, 46, 22, 47, 23 + db 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31 +spel_v_perm32: db 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39 + db 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47 + db 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55 + db 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63 +spel_hv_perm4a: db 8, 9, 16, 17, 10, 11, 18, 19, 12, 13, 20, 21, 14, 15, 22, 23 + db 16, 17, 24, 25, 18, 19, 26, 27, 20, 21, 28, 29, 22, 23, 30, 31 +spel_hv_perm4b: db 24, 25, 32, 33, 26, 27, 34, 35, 28, 29, 36, 37, 30, 31, 38, 39 + db 32, 33, 40, 41, 34, 35, 42, 43, 36, 37, 44, 45, 38, 39, 46, 47 +spel_hv_perm4c: db 40, 41, 48, 49, 42, 43, 50, 51, 44, 45, 52, 53, 46, 47, 54, 55 + db 48, 49, 56, 57, 50, 51, 58, 59, 52, 53, 60, 61, 54, 55, 62, 63 +spel_hv_perm4d: db 18, 19, 0, 1, 22, 23, 4, 5, 26, 27, 8, 9, 30, 31, 12, 13 + db 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29 +spel_hv_perm8a: db 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 + db 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 + db 16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39 + db 24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47 +spel_hv_perm8b: db 32, 33, 48, 49, 34, 35, 50, 51, 36, 37, 52, 53, 38, 39, 54, 55 + db 40, 41, 56, 57, 42, 43, 58, 59, 44, 45, 60, 61, 46, 47, 62, 63 + db 48, 49, 64, 65, 50, 51, 66, 67, 52, 53, 68, 69, 54, 55, 70, 71 + db 56, 57, 72, 73, 58, 59, 74, 75, 60, 61, 76, 77, 62, 63, 78, 79 +spel_hv_perm8c: db 34, 35, 0, 1, 38, 39, 4, 5, 42, 43, 8, 9, 46, 47, 12, 13 + db 50, 51, 16, 17, 54, 55, 20, 21, 58, 59, 24, 25, 62, 63, 28, 29 + db 0, 1, 32, 33, 4, 5, 36, 37, 8, 9, 40, 41, 12, 13, 44, 45 + db 16, 17, 48, 49, 20, 21, 52, 53, 24, 25, 56, 57, 28, 29, 60, 61 +spel_hv_end16: db 1, 3, 17, 19, 5, 7, 21, 23, 33, 35, 49, 51, 37, 39, 53, 55 + db 9, 11, 25, 27, 13, 15, 29, 31, 41, 43, 57, 59, 45, 47, 61, 63 +spel_hv_perm16a:db 0, 1, 2, 3, 32, 33, 34, 35, 1, 2, 3, 4, 33, 34, 35, 36 + db 2, 3, 4, 5, 34, 35, 36, 37, 3, 4, 5, 6, 35, 36, 37, 38 +spel_hv_perm16c:db 8, 9, 10, 11, 40, 41, 42, 43, 9, 10, 11, 12, 41, 42, 43, 44 + db 10, 11, 12, 13, 42, 43, 44, 45, 11, 12, 13, 14, 43, 44, 45, 46 + db 16, 17, 18, 19, 48, 49, 50, 51, 17, 18, 19, 20, 49, 50, 51, 52 + db 18, 19, 20, 21, 50, 51, 52, 53, 19, 20, 21, 22, 51, 52, 53, 54 +spel_hv_perm16b:db 4, 5, 6, 7, 36, 37, 38, 39, 5, 6, 7, 8, 37, 38, 39, 40 + db 6, 7, 8, 9, 38, 39, 40, 41, 7, 8, 9, 10, 39, 40, 41, 42 + db 12, 13, 14, 15, 44, 45, 46, 47, 13, 14, 15, 16, 45, 46, 47, 48 + db 14, 15, 16, 17, 46, 47, 48, 49, 15, 16, 17, 18, 47, 48, 49, 50 +spel_hv_perm16d:db 0, 1, 2, 3, 1, 2, 3, 4, 4, 5, 6, 7, 5, 6, 7, 8 + db 2, 3, 4, 5, 3, 4, 5, 6, 6, 7, 8, 9, 7, 8, 9, 10 + db 8, 9, 10, 11, 9, 10, 11, 12, 12, 13, 14, 15, 13, 14, 15, 16 + db 10, 11, 12, 13, 11, 12, 13, 14, 14, 15, 16, 17, 15, 16, 17, 18 +spel_hv_perm16e:db 4, 5, 6, 7, 5, 6, 7, 8, 8, 9, 10, 11, 9, 10, 11, 12 + db 6, 7, 8, 9, 7, 8, 9, 10, 10, 11, 12, 13, 11, 12, 13, 14 + db 12, 13, 14, 15, 13, 14, 15, 16, 16, 17, 18, 19, 17, 18, 19, 20 + db 14, 15, 16, 17, 15, 16, 17, 18, 18, 19, 20, 21, 19, 20, 21, 22 +spel_hv_end: db 1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, 49, 51, 53, 55 +deint_shuf4: db 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +bilin_h_shuf4: db 1, 0, 2, 1, 3, 2, 4, 3, 9, 8, 10, 9, 11, 10, 12, 11 +bilin_h_shuf8: db 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7 +bilin_v_shuf4: db 4, 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +rescale_mul: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 +resize_permA: dd 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 +resize_permB: dd 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 +resize_permC: dd 0, 4, 8, 12 +pb_02461357: db 0, 2, 4, 6, 1, 3, 5, 7 + +wm_420_perm64: dq 0xfedcba9876543210 +wm_sign: dd 0x40804080, 0xc0c0c0c0, 0x40404040 + +pb_8x0_8x8: times 8 db 0 + times 8 db 8 +pb_127: times 4 db 127 +pw_m128 times 2 dw -128 +pw_m256: times 2 dw -256 +pw_1024: times 2 dw 1024 +pw_2048: times 2 dw 2048 +pw_6903: times 2 dw 6903 +pw_8192: times 2 dw 8192 +pd_32: dd 32 +pd_34: dd 34 +pd_63: dd 63 +pd_512: dd 512 +pd_32768: dd 32768 + +%define pb_m64 (wm_sign+4) +%define pb_64 (wm_sign+8) +%define pd_2 (pd_0to7+8) + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) +cextern mc_warp_filter +cextern resize_filter + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +%macro BIDIR_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + %%table: + %rep %0 - 2 + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine put_avx512icl mangle(private_prefix %+ _put_bilin_8bpc_avx512icl.put) +%xdefine prep_avx512icl mangle(private_prefix %+ _prep_bilin_8bpc_avx512icl.prep) + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +BASE_JMP_TABLE put, avx512icl, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, avx512icl, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, avx512icl, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, avx512icl, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, avx512icl, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, avx512icl, 7, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, avx512icl, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, avx512icl, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, avx512icl, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, avx512icl, 2, 4, 8, 16, 32, 64, 128 + +SECTION .text + +%macro WRAP_YMM 1+ +INIT_YMM cpuname + %1 +INIT_ZMM cpuname +%endmacro + +INIT_ZMM avx512icl +cglobal put_bilin_8bpc, 4, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + lea r7, [put_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [r7+wq*2+table_offset(put,)] + add wq, r7 + jmp wq +.put_w2: + movzx r6d, word [srcq+ssq*0] + movzx r7d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6w + mov [dstq+dsq*1], r7w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r6d, [srcq+ssq*0] + mov r7d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6d + mov [dstq+dsq*1], r7d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + mov r6, [srcq+ssq*0] + mov r7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r6 + mov [dstq+dsq*1], r7 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu xmm0, [srcq+ssq*0] + movu xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], xmm0 + mova [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu ym0, [srcq+ssq*0] + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], ym0 + mova [dstq+dsq*1], ym1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+ssq*0+64*0] + movu m1, [srcq+ssq*0+64*1] + movu m2, [srcq+ssq*1+64*0] + movu m3, [srcq+ssq*1+64*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+64*0], m0 + mova [dstq+dsq*0+64*1], m1 + mova [dstq+dsq*1+64*0], m2 + mova [dstq+dsq*1+64*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 0xff01 + vbroadcasti128 m4, [bilin_h_shuf8] + add mxyd, 16 << 8 + vpbroadcastw m5, mxyd + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .hv + movzx wd, word [r7+wq*2+table_offset(put, _bilin_h)] + vpbroadcastd m3, [pw_2048] + add wq, r7 + jmp wq +.h_w2: + movd xmm0, [srcq+ssq*0] + pinsrd xmm0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb xmm0, xm4 + pmaddubsw xmm0, xm5 + pmulhrsw xmm0, xm3 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2 + RET +.h_w4: + mova xmm4, [bilin_h_shuf4] +.h_w4_loop: + movq xmm0, [srcq+ssq*0] + movhps xmm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xmm4 + pmaddubsw xmm0, xm5 + pmulhrsw xmm0, xm3 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti32x4 ym0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 + pmulhrsw ym0, ym3 + vpmovuswb xm0, ym0 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mova m4, [bilin_h_perm16] +.h_w16_loop: + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + vpermb m0, m4, m0 + pmaddubsw m0, m5 + pmulhrsw m0, m3 + vpmovuswb ym0, m0 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + movu ym0, [srcq+ssq*0+8*0] + vinserti32x8 m0, [srcq+ssq*1+8*0], 1 + movu ym1, [srcq+ssq*0+8*1] + vinserti32x8 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + add srcq, ssq + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + movu m0, [srcq+8*0] + movu m2, [srcq+8*1] + movu m1, [srcq+8*8] + movu m6, [srcq+8*9] + add srcq, ssq + REPX {pshufb x, m4}, m0, m2, m1, m6 + REPX {pmaddubsw x, m5}, m0, m2, m1, m6 + REPX {pmulhrsw x, m3}, m0, m2, m1, m6 + packuswb m0, m2 + packuswb m1, m6 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [r7+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 0xff01 + vpbroadcastd m5, [pw_2048] + add mxyd, 16 << 8 + add wq, r7 + vpbroadcastw m4, mxyd + jmp wq +.v_w2: + movd xmm0, [srcq+ssq*0] +.v_w2_loop: + pinsrw xmm1, xmm0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pinsrw xmm0, xmm1, [srcq+ssq*0], 0 ; 2 1 + pshuflw xmm1, xmm1, q2301 ; 1 0 + punpcklbw xmm1, xmm0, xmm1 + pmaddubsw xmm1, xm4 + pmulhrsw xmm1, xm5 + packuswb xmm1, xmm1 + pextrw [dstq+dsq*0], xmm1, 1 + pextrw [dstq+dsq*1], xmm1, 0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xmm0, [srcq+ssq*0] +.v_w4_loop: + vpbroadcastd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xmm2, xmm1, xmm0, 0x01 ; 0 1 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm1, xmm0, 0x02 ; 1 2 + punpcklbw xmm1, xmm2 + pmaddubsw xmm1, xm4 + pmulhrsw xmm1, xm5 + packuswb xmm1, xmm1 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xmm0, [srcq+ssq*0] +.v_w8_loop: + movq xmm3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw xmm1, xmm3, xmm0 + movq xmm0, [srcq+ssq*0] + punpcklbw xmm2, xmm0, xmm3 + pmaddubsw xmm1, xm4 + pmaddubsw xmm2, xm4 + pmulhrsw xmm1, xm5 + pmulhrsw xmm2, xm5 + packuswb xmm1, xmm2 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +.v_w16: + movu xmm0, [srcq+ssq*0] +.v_w16_loop: + vbroadcasti128 ymm2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd ymm3, ymm2, ymm0, 0x0f ; 0 1 + vbroadcasti128 ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm2, ymm0, 0xf0 ; 1 2 + punpcklbw ymm1, ymm2, ymm3 + punpckhbw ymm2, ymm3 + pmaddubsw ymm1, ym4 + pmaddubsw ymm2, ym4 + pmulhrsw ymm1, ym5 + pmulhrsw ymm2, ym5 + packuswb ymm1, ymm2 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + vzeroupper + RET +.v_w32: + movu ym0, [srcq+ssq*0] + kxnorb k1, k1, k1 +.v_w32_loop: + vbroadcasti32x8 m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendmd m3{k1}, m2, m0 ; 0 1 + vbroadcasti32x8 m0, [srcq+ssq*0] + vpblendmd m2{k1}, m0, m2 ; 1 2 + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + RET +.v_w64: + movu m0, [srcq+ssq*0] +.v_w64_loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m1, m3, m0 + punpckhbw m6, m3, m0 + movu m0, [srcq+ssq*0] + pmaddubsw m1, m4 + pmaddubsw m6, m4 + punpcklbw m2, m0, m3 + punpckhbw m7, m0, m3 + pmaddubsw m2, m4 + pmaddubsw m7, m4 + REPX {pmulhrsw x, m5}, m1, m6, m2, m7 + packuswb m1, m6 + packuswb m2, m7 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + movu m0, [srcq+64*0] + movu m1, [srcq+64*1] +.v_w128_loop: + add srcq, ssq + movu m2, [srcq+64*0] + movu m3, [srcq+64*1] + punpcklbw m6, m2, m0 + pmaddubsw m6, m4 + punpckhbw m0, m2, m0 + pmaddubsw m0, m4 + punpcklbw m7, m3, m1 + pmaddubsw m7, m4 + punpckhbw m1, m3, m1 + pmaddubsw m1, m4 + REPX {pmulhrsw x, m5}, m6, m0, m7, m1 + packuswb m6, m0 + mova m0, m2 + packuswb m7, m1 + mova m1, m3 + mova [dstq+64*0], m6 + mova [dstq+64*1], m7 + add dstq, dsq + dec hd + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [r7+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + vpbroadcastd m7, [pw_2048] + add wq, r7 + vpbroadcastw m6, mxyd + jmp wq +.hv_w2: + vpbroadcastd xmm0, [srcq+ssq*0] + pshufb xmm0, xm4 + pmaddubsw xmm0, xm5 +.hv_w2_loop: + movd xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pinsrd xmm1, [srcq+ssq*0], 1 + pshufb xmm1, xm4 + pmaddubsw xmm1, xm5 ; 1 _ 2 _ + shufps xmm2, xmm0, xmm1, q1032 ; 0 _ 1 _ + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm6 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm7 + packuswb xmm1, xmm1 + pextrw [dstq+dsq*0], xmm1, 0 + pextrw [dstq+dsq*1], xmm1, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova xmm4, [bilin_h_shuf4] + movddup xmm0, [srcq+ssq*0] + pshufb xmm0, xmm4 + pmaddubsw xmm0, xm5 +.hv_w4_loop: + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm1, [srcq+ssq*0] + pshufb xmm1, xmm4 + pmaddubsw xmm1, xm5 ; 1 2 + shufps xmm2, xmm0, xmm1, q1032 ; 0 1 + mova xmm0, xmm1 + psubw xmm1, xmm2 + paddw xmm1, xmm1 + pmulhw xmm1, xm6 + paddw xmm1, xmm2 + pmulhrsw xmm1, xm7 + packuswb xmm1, xmm1 + movd [dstq+dsq*0], xmm1 + pextrd [dstq+dsq*1], xmm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti128 ym0, [srcq+ssq*0] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 +.hv_w8_loop: + movu xm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti128 ym1, [srcq+ssq*0], 1 + pshufb ym1, ym4 + pmaddubsw ym1, ym5 ; 1 2 + valignq ym2, ym1, ym0, 2 + mova ym0, ym1 + psubw ym1, ym2 + paddw ym1, ym1 + pmulhw ym1, ym6 + paddw ym1, ym2 + pmulhrsw ym1, ym7 + vpmovuswb xm1, ym1 + movq [dstq+dsq*0], xm1 + movhps [dstq+dsq*1], xm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w16: + vbroadcasti32x8 m0, [srcq+ssq*0] + mova m4, [bilin_h_perm16] + vpermb m0, m4, m0 + pmaddubsw m0, m5 +.hv_w16_loop: + movu ym1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m1, [srcq+ssq*0], 1 + vpermb m1, m4, m1 + pmaddubsw m1, m5 ; 1 2 + valignq m2, m1, m0, 4 ; 0 1 + mova m0, m1 + psubw m1, m2 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m2 + pmulhrsw m1, m7 + vpmovuswb ym1, m1 + mova [dstq+dsq*0], xm1 + vextracti32x4 [dstq+dsq*1], ym1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + RET +.hv_w32: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+ssq*0] + pmovzxbq m8, [pb_02461357] + pmaddubsw m0, m5 +.hv_w32_loop: + vpermb m2, m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpermb m3, m4, [srcq+ssq*0] + pmaddubsw m2, m5 + psubw m1, m2, m0 + paddw m1, m1 + pmulhw m1, m6 + paddw m1, m0 + pmaddubsw m0, m3, m5 + psubw m3, m0, m2 + paddw m3, m3 + pmulhw m3, m6 + paddw m3, m2 + pmulhrsw m1, m7 + pmulhrsw m3, m7 + packuswb m1, m3 + vpermq m1, m8, m1 + mova [dstq+dsq*0], ym1 + vextracti32x8 [dstq+dsq*1], m1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w64_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m8, m2, m0 + psubw m9, m3, m1 + paddw m8, m8 + pmulhw m8, m6 + paddw m9, m9 + pmulhw m9, m6 + paddw m8, m0 + pmulhrsw m8, m7 + paddw m9, m1 + pmulhrsw m9, m7 + mova m0, m2 + mova m1, m3 + packuswb m8, m9 + mova [dstq], m8 + add dstq, dsq + dec hd + jg .hv_w64_loop + RET +.hv_w128: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + movu m2, [srcq+8*8] + movu m3, [srcq+8*9] + REPX {pshufb x, m4}, m0, m1, m2, m3 + REPX {pmaddubsw x, m5}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, ssq + movu m8, [srcq+8*0] + movu m9, [srcq+8*1] + movu m10, [srcq+8*8] + movu m11, [srcq+8*9] + REPX {pshufb x, m4}, m8, m9, m10, m11 + REPX {pmaddubsw x, m5}, m8, m9, m10, m11 + psubw m12, m8, m0 + psubw m13, m9, m1 + psubw m14, m10, m2 + psubw m15, m11, m3 + paddw m12, m12 + pmulhw m12, m6 + paddw m13, m13 + pmulhw m13, m6 + paddw m14, m14 + pmulhw m14, m6 + paddw m15, m15 + pmulhw m15, m6 + paddw m12, m0 + pmulhrsw m12, m7 + paddw m13, m1 + pmulhrsw m13, m7 + paddw m14, m2 + pmulhrsw m14, m7 + paddw m15, m3 + pmulhrsw m15, m7 + mova m0, m8 + mova m1, m9 + mova m2, m10 + mova m3, m11 + packuswb m12, m13 + packuswb m14, m15 + mova [dstq+64*0], m12 + mova [dstq+64*1], m14 + add dstq, dsq + dec hd + jg .hv_w128_loop + RET + +DECLARE_REG_TMP 3, 5, 6 + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + lea t2, [prep_avx512icl] + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: + movzx wd, word [t2+wq*2+table_offset(prep,)] + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd xmm0, [srcq+strideq*0] + pinsrd xmm0, [srcq+strideq*1], 1 + pinsrd xmm0, [srcq+strideq*2], 2 + pinsrd xmm0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pmovzxbw ym0, xmm0 + psllw ym0, 4 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq xmm0, [srcq+strideq*0] + movq xmm1, [srcq+strideq*1] + vinserti128 ym0, ymm0, [srcq+strideq*2], 1 + vinserti128 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1 + pmovzxbw m0, ym0 + psllw m0, 4 + mova [tmpq], m0 + add tmpq, 32*2 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu xmm0, [srcq+strideq*0] + vinserti128 ym0, ymm0, [srcq+strideq*1], 1 + movu xmm1, [srcq+strideq*2] + vinserti128 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + pmovzxbw m0, ym0 + pmovzxbw m1, ym1 + psllw m0, 4 + psllw m1, 4 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 32*4 + sub hd, 4 + jg .prep_w16 + RET +.prep_w32: + pmovzxbw m0, [srcq+strideq*0] + pmovzxbw m1, [srcq+strideq*1] + pmovzxbw m2, [srcq+strideq*2] + pmovzxbw m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .prep_w32 + RET +.prep_w64: + pmovzxbw m0, [srcq+strideq*0+32*0] + pmovzxbw m1, [srcq+strideq*0+32*1] + pmovzxbw m2, [srcq+strideq*1+32*0] + pmovzxbw m3, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .prep_w64 + RET +.prep_w128: + pmovzxbw m0, [srcq+32*0] + pmovzxbw m1, [srcq+32*1] + pmovzxbw m2, [srcq+32*2] + pmovzxbw m3, [srcq+32*3] + REPX {psllw x, 4}, m0, m1, m2, m3 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + add srcq, strideq + dec hd + jg .prep_w128 + RET +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] + imul mxyd, 0xff01 + add mxyd, 16 << 8 + vpbroadcastw m5, mxyd + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .hv + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_h)] + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.h_w4: + vbroadcasti32x4 ym4, [bilin_h_shuf4] +.h_w4_loop: + movq xmm0, [srcq+strideq*0] + movq xmm1, [srcq+strideq*1] + vinserti32x4 ym0, ymm0, [srcq+strideq*2], 1 + vinserti32x4 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + punpcklqdq ym0, ym1 + pshufb ym0, ym4 + pmaddubsw ym0, ym5 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + vbroadcasti32x4 m4, [bilin_h_shuf8] +.h_w8_loop: + movu xmm0, [srcq+strideq*0] + vinserti32x4 ym0, ymm0, [srcq+strideq*1], 1 + vinserti32x4 m0, [srcq+strideq*2], 2 + vinserti32x4 m0, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pshufb m0, m4 + pmaddubsw m0, m5 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + mova m4, [bilin_h_perm16] +.h_w16_loop: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + movu ym1, [srcq+strideq*2] + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vpermb m0, m4, m0 + vpermb m1, m4, m1 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + add tmpq, 64*2 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: + mova m4, [bilin_h_perm32] +.h_w32_loop: + vpermb m0, m4, [srcq+strideq*0] + vpermb m1, m4, [srcq+strideq*1] + vpermb m2, m4, [srcq+strideq*2] + vpermb m3, m4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 4 + jg .h_w32_loop + RET +.h_w64: + mova m4, [bilin_h_perm32] +.h_w64_loop: + vpermb m0, m4, [srcq+strideq*0+32*0] + vpermb m1, m4, [srcq+strideq*0+32*1] + vpermb m2, m4, [srcq+strideq*1+32*0] + vpermb m3, m4, [srcq+strideq*1+32*1] + lea srcq, [srcq+strideq*2] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + sub hd, 2 + jg .h_w64_loop + RET +.h_w128: + mova m4, [bilin_h_perm32] +.h_w128_loop: + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + vpermb m2, m4, [srcq+32*2] + vpermb m3, m4, [srcq+32*3] + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 + mova [tmpq+64*2], m2 + mova [tmpq+64*3], m3 + add tmpq, 64*4 + add srcq, strideq + dec hd + jg .h_w128_loop + RET +.v: + WIN64_SPILL_XMM 7 + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_v)] + imul mxyd, 0xff01 + add mxyd, 16 << 8 + add wq, t2 + lea stride3q, [strideq*3] + vpbroadcastw m6, mxyd + jmp wq +.v_w4: + vpbroadcastd xm0, [srcq+strideq*0] + mov r3d, 0x29 + vbroadcasti32x4 ym3, [bilin_v_shuf4] + kmovb k1, r3d +.v_w4_loop: + vpblendmd xm1{k1}, xm0, [srcq+strideq*1] {1to4} ; __01 ____ + vpbroadcastd ym2, [srcq+strideq*2] + vpbroadcastd ym2{k1}, [srcq+stride3q ] ; __2_ 23__ + lea srcq, [srcq+strideq*4] + vpbroadcastd ym0, [srcq+strideq*0] + punpckhqdq ym2{k1}, ym1, ym0 ; 012_ 234_ + pshufb ym2, ym3 + pmaddubsw ym2, ym6 + mova [tmpq], ym2 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + mova m5, [bilin_v_perm8] + vbroadcasti32x4 ym0, [srcq+strideq*0] +.v_w8_loop: + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vpbroadcastq ym0, [srcq+strideq*2] + vinserti32x4 m1, [srcq+stride3q ], 2 + lea srcq, [srcq+strideq*4] + vinserti32x4 ym0, [srcq+strideq*0], 0 + vpermt2b m1, m5, m0 + pmaddubsw m1, m6 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + mova m5, [bilin_v_perm16] + movu xm0, [srcq+strideq*0] +.v_w16_loop: + movu xm2, [srcq+strideq*2] + vinserti32x4 ym1, ym0, [srcq+strideq*1], 1 + vpermt2b m1, m5, m2 + vinserti32x4 ym2, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + movu xm0, [srcq+strideq*0] + vpermt2b m2, m5, m0 + pmaddubsw m1, m6 + pmaddubsw m2, m6 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + mova m5, [bilin_v_perm32] + movu ym0, [srcq+strideq*0] +.v_w32_loop: + movu ym2, [srcq+strideq*1] + movu ym3, [srcq+strideq*2] + movu ym4, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpermt2b m0, m5, m2 + vpermt2b m2, m5, m3 + vpermt2b m3, m5, m4 + pmaddubsw m1, m0, m6 + movu ym0, [srcq+strideq*0] + vpermt2b m4, m5, m0 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + pmaddubsw m4, m6 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m2 + mova [tmpq+64*2], m3 + mova [tmpq+64*3], m4 + add tmpq, 64*4 + sub hd, 4 + jg .v_w32_loop + RET +.v_w64: + mova m5, [bilin_v_perm64] + vpermq m0, m5, [srcq+strideq*0] +.v_w64_loop: + vpermq m1, m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m1, m0 + punpckhbw m2, m1, m0 + vpermq m0, m5, [srcq+strideq*0] + punpcklbw m3, m0, m1 + punpckhbw m1, m0, m1 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + pmaddubsw m3, m6 + pmaddubsw m1, m6 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m2 + mova [tmpq+64*2], m3 + mova [tmpq+64*3], m1 + add tmpq, 64*4 + sub hd, 2 + jg .v_w64_loop + RET +.v_w128: + mova m5, [bilin_v_perm64] + vpermq m0, m5, [srcq+strideq*0+ 0] + vpermq m1, m5, [srcq+strideq*0+64] +.v_w128_loop: + vpermq m2, m5, [srcq+strideq*1+ 0] + vpermq m3, m5, [srcq+strideq*1+64] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m2, m0 + punpckhbw m0, m2, m0 + pmaddubsw m4, m6 + pmaddubsw m0, m6 + mova [tmpq+64*0], m4 + mova [tmpq+64*1], m0 + punpcklbw m4, m3, m1 + punpckhbw m1, m3, m1 + pmaddubsw m4, m6 + pmaddubsw m1, m6 + mova [tmpq+64*2], m4 + mova [tmpq+64*3], m1 + vpermq m0, m5, [srcq+strideq*0+ 0] + vpermq m1, m5, [srcq+strideq*0+64] + punpcklbw m4, m0, m2 + punpckhbw m2, m0, m2 + pmaddubsw m4, m6 + pmaddubsw m2, m6 + mova [tmpq+64*4], m4 + mova [tmpq+64*5], m2 + punpcklbw m4, m1, m3 + punpckhbw m3, m1, m3 + pmaddubsw m4, m6 + pmaddubsw m3, m6 + mova [tmpq+64*6], m4 + mova [tmpq+64*7], m3 + add tmpq, 64*8 + sub hd, 2 + jg .v_w128_loop + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 7 + movzx wd, word [t2+wq*2+table_offset(prep, _bilin_hv)] + shl mxyd, 11 + vpbroadcastw m6, mxyd + add wq, t2 + lea stride3q, [strideq*3] + jmp wq +.hv_w4: + vbroadcasti32x4 ym4, [bilin_h_shuf4] + vpbroadcastq ym0, [srcq+strideq*0] + pshufb ym0, ym4 + pmaddubsw ym0, ym5 +.hv_w4_loop: + movq xmm1, [srcq+strideq*1] + movq xmm2, [srcq+strideq*2] + vinserti32x4 ym1, ymm1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vinserti32x4 ym2, ymm2, [srcq+strideq*0], 1 + punpcklqdq ym1, ym2 + pshufb ym1, ym4 + pmaddubsw ym1, ym5 ; 1 2 3 4 + valignq ym2, ym1, ym0, 3 ; 0 1 2 3 + mova ym0, ym1 + psubw ym1, ym2 + pmulhrsw ym1, ym6 + paddw ym1, ym2 + mova [tmpq], ym1 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + vbroadcasti32x4 m4, [bilin_h_shuf8] + vbroadcasti32x4 m0, [srcq+strideq*0] + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu xmm1, [srcq+strideq*1] + vinserti128 ym1, ymm1, [srcq+strideq*2], 1 + vinserti128 m1, [srcq+stride3q ], 2 + lea srcq, [srcq+strideq*4] + vinserti128 m1, [srcq+strideq*0], 3 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 3 4 + valignq m2, m1, m0, 6 ; 0 1 2 3 + mova m0, m1 + psubw m1, m2 + pmulhrsw m1, m6 + paddw m1, m2 + mova [tmpq], m1 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + mova m4, [bilin_h_perm16] + vbroadcasti32x8 m0, [srcq+strideq*0] + vpermb m0, m4, m0 + pmaddubsw m0, m5 +.hv_w16_loop: + movu ym1, [srcq+strideq*1] + vinserti32x8 m1, [srcq+strideq*2], 1 + movu ym2, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti32x8 m2, [srcq+strideq*0], 1 + vpermb m1, m4, m1 + vpermb m2, m4, m2 + pmaddubsw m1, m5 ; 1 2 + vshufi32x4 m3, m0, m1, q1032 ; 0 1 + pmaddubsw m0, m2, m5 ; 3 4 + vshufi32x4 m2, m1, m0, q1032 ; 2 3 + psubw m1, m3 + pmulhrsw m1, m6 + paddw m1, m3 + psubw m3, m0, m2 + pmulhrsw m3, m6 + paddw m3, m2 + mova [tmpq+64*0], m1 + mova [tmpq+64*1], m3 + add tmpq, 64*2 + sub hd, 4 + jg .hv_w16_loop + RET +.hv_w32: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+strideq*0] + pmaddubsw m0, m5 +.hv_w32_loop: + vpermb m1, m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermb m2, m4, [srcq+strideq*0] + pmaddubsw m1, m5 + psubw m3, m1, m0 + pmulhrsw m3, m6 + paddw m3, m0 + pmaddubsw m0, m2, m5 + psubw m2, m0, m1 + pmulhrsw m2, m6 + paddw m2, m1 + mova [tmpq+64*0], m3 + mova [tmpq+64*1], m2 + add tmpq, 64*2 + sub hd, 2 + jg .hv_w32_loop + RET +.hv_w64: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w64_loop: + add srcq, strideq + vpermb m2, m4, [srcq+32*0] + vpermb m3, m4, [srcq+32*1] + pmaddubsw m2, m5 + pmaddubsw m3, m5 + psubw m7, m2, m0 + psubw m8, m3, m1 + pmulhrsw m7, m6 + pmulhrsw m8, m6 + paddw m7, m0 + mova m0, m2 + paddw m8, m1 + mova m1, m3 + mova [tmpq+64*0], m7 + mova [tmpq+64*1], m8 + add tmpq, 64*2 + dec hd + jg .hv_w64_loop + RET +.hv_w128: + mova m4, [bilin_h_perm32] + vpermb m0, m4, [srcq+32*0] + vpermb m1, m4, [srcq+32*1] + vpermb m2, m4, [srcq+32*2] + vpermb m3, m4, [srcq+32*3] + REPX {pmaddubsw x, m5}, m0, m1, m2, m3 +.hv_w128_loop: + add srcq, strideq + vpermb m7, m4, [srcq+32*0] + vpermb m8, m4, [srcq+32*1] + vpermb m9, m4, [srcq+32*2] + vpermb m10, m4, [srcq+32*3] + REPX {pmaddubsw x, m5}, m7, m8, m9, m10 + psubw m11, m7, m0 + psubw m12, m8, m1 + psubw m13, m9, m2 + psubw m14, m10, m3 + REPX {pmulhrsw x, m6}, m11, m12, m13, m14 + paddw m11, m0 + mova m0, m7 + paddw m12, m1 + mova m1, m8 + paddw m13, m2 + mova m2, m9 + paddw m14, m3 + mova m3, m10 + mova [tmpq+64*0], m11 + mova [tmpq+64*1], m12 + mova [tmpq+64*2], m13 + mova [tmpq+64*3], m14 + add tmpq, 64*4 + dec hd + jg .hv_w128_loop + RET + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; fn, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%macro PUT_8TAP_H 4-5 0 ; dst/src, tmp[1-3], vpermb +%if %5 + vpermb m%2, m6, m%1 + vpermb m%3, m7, m%1 + vpermb m%4, m8, m%1 +%else +%if %2 < %4 ; reuse a previous value if possible + pshufb m%2, m%1, m6 +%endif + pshufb m%3, m%1, m7 + pshufb m%4, m%1, m8 +%endif + mova m%1, m5 + vpdpbusd m%1, m%2, m9 + mova m%2, m5 + vpdpbusd m%2, m%3, m9 + vpdpbusd m%1, m%3, m10 + vpdpbusd m%2, m%4, m10 + packusdw m%1, m%2 + psrlw m%1, 6 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +%define PUT_8TAP_FN FN put_8tap, + +PUT_8TAP_FN sharp, SHARP, SHARP +PUT_8TAP_FN sharp_smooth, SHARP, SMOOTH +PUT_8TAP_FN smooth_sharp, SMOOTH, SHARP +PUT_8TAP_FN smooth, SMOOTH, SMOOTH +PUT_8TAP_FN sharp_regular, SHARP, REGULAR +PUT_8TAP_FN regular_sharp, REGULAR, SHARP +PUT_8TAP_FN smooth_regular, SMOOTH, REGULAR +PUT_8TAP_FN regular_smooth, REGULAR, SMOOTH +PUT_8TAP_FN regular, REGULAR, REGULAR + +cglobal put_8tap_8bpc, 4, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 +%define base r8-put_avx512icl + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r8, [put_avx512icl] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r8+wq*2+table_offset(put,)] + add wq, r8 + lea r6, [ssq*3] + lea r7, [dsq*3] +%if WIN64 + pop r8 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m5, [pd_34] ; 2 + (8 << 2) + WIN64_SPILL_XMM 11 + cmp wd, 4 + jl .h_w2 + vbroadcasti128 m6, [subpel_h_shufA] + je .h_w4 + tzcnt wd, wd + vbroadcasti128 m7, [subpel_h_shufB] + vbroadcasti128 m8, [subpel_h_shufC] + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r8+wq*2+table_offset(put, _8tap_h)] + vpbroadcastd m9, [base+mxq*8+subpel_filters+0] + vpbroadcastd m10, [base+mxq*8+subpel_filters+4] + add wq, r8 + jmp wq +.h_w2: + movzx mxd, mxb + dec srcq + mova xmm4, [subpel_h_shuf4] + vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2] +.h_w2_loop: + movq xmm0, [srcq+ssq*0] + movhps xmm0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xmm4 + mova xmm1, xm5 + vpdpbusd xmm1, xmm0, xmm3 + packssdw xmm0, xmm1, xmm1 + psraw xmm0, 6 + packuswb xmm0, xm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd xmm3, [base+mxq*8+subpel_filters+2] +.h_w4_loop: + movq xmm0, [srcq+ssq*0] + movq xmm1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb xmm0, xm6 + pshufb xmm1, xm6 + mova xmm2, xm5 + vpdpbusd xmm2, xmm0, xmm3 + mova xmm0, xm5 + vpdpbusd xmm0, xmm1, xmm3 + packssdw xmm0, xmm2, xmm0 + psraw xmm0, 6 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +.h_w8: + movu xm0, [srcq+ssq*0] + vinserti32x4 ym0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + WRAP_YMM PUT_8TAP_H 0, 1, 2, 3 + vpmovuswb xm0, ym0 + movq [dstq+dsq*0], xm0 + movhps [dstq+dsq*1], xm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + mova m6, [spel_h_perm16a] + mova m7, [spel_h_perm16b] + mova m8, [spel_h_perm16c] +.h_w16_loop: + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 1, 2, 3, 1 + vpmovuswb ym0, m0 + mova [dstq+dsq*0], xm0 + vextracti128 [dstq+dsq*1], ym0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w16_loop + RET +.h_w32: + movu ym0, [srcq+ssq*0+8*0] + vinserti32x8 m0, [srcq+ssq*1+8*0], 1 + movu ym1, [srcq+ssq*0+8*1] + vinserti32x8 m1, [srcq+ssq*1+8*1], 1 + lea srcq, [srcq+ssq*2] + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 4, 3, 2 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w32 + RET +.h_w64: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + PUT_8TAP_H 0, 2, 3, 4 + PUT_8TAP_H 1, 4, 3, 2 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + movu m0, [srcq+8*0] + movu m2, [srcq+8*1] + movu m1, [srcq+8*8] + movu m3, [srcq+8*9] + add srcq, ssq + PUT_8TAP_H 0, 4, 11, 12 + PUT_8TAP_H 2, 12, 11, 4 + PUT_8TAP_H 1, 4, 11, 12 + PUT_8TAP_H 3, 12, 11, 4 + packuswb m0, m2 + packuswb m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + tzcnt r6d, wd + movzx r6d, word [r8+r6*2+table_offset(put, _8tap_v)] + vpbroadcastd m7, [pw_512] + lea myq, [base+subpel_filters+myq*8] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + add r6, r8 + lea ss3q, [ssq*3] + sub srcq, ss3q + jmp r6 +.v_w2: + movd xmm2, [srcq+ssq*0] + pinsrw xmm2, [srcq+ssq*1], 2 + pinsrw xmm2, [srcq+ssq*2], 4 + add srcq, ss3q + pinsrw xmm2, [srcq+ssq*0], 6 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklbw xmm3, xmm1 ; 45 56 + punpcklbw xmm1, xmm2, xmm4 ; 01 12 + punpckhbw xmm2, xmm4 ; 23 34 +.v_w2_loop: + pmaddubsw xmm5, xmm1, xm8 ; a0 b0 + mova xmm1, xmm2 + pmaddubsw xmm2, xm9 ; a1 b1 + paddw xmm5, xmm2 + mova xmm2, xmm3 + pmaddubsw xmm3, xm10 ; a2 b2 + paddw xmm5, xmm3 + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm4, xmm0, 0x02 ; 7 8 + punpcklbw xmm3, xmm4 ; 67 78 + pmaddubsw xmm4, xmm3, xm11 ; a3 b3 + paddw xmm5, xmm4 + pmulhrsw xmm5, xm7 + packuswb xmm5, xmm5 + pextrw [dstq+dsq*0], xmm5, 0 + pextrw [dstq+dsq*1], xmm5, 2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd xmm2, [srcq+ssq*0] + pinsrd xmm2, [srcq+ssq*1], 1 + pinsrd xmm2, [srcq+ssq*2], 2 + add srcq, ss3q + pinsrd xmm2, [srcq+ssq*0], 3 ; 0 1 2 3 + movd xmm3, [srcq+ssq*1] + vpbroadcastd xmm1, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm3, xmm3, xmm1, 0x02 ; 4 5 + vpblendd xmm1, xmm1, xmm0, 0x02 ; 5 6 + palignr xmm4, xmm3, xmm2, 4 ; 1 2 3 4 + punpcklbw xmm3, xmm1 ; 45 56 + punpcklbw xmm1, xmm2, xmm4 ; 01 12 + punpckhbw xmm2, xmm4 ; 23 34 +.v_w4_loop: + vpbroadcastd xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw xmm5, xmm1, xm8 ; a0 b0 + mova xmm1, xmm2 + pmaddubsw xmm2, xm9 ; a1 b1 + paddw xmm5, xmm2 + mova xmm2, xmm3 + pmaddubsw xmm3, xm10 ; a2 b2 + paddw xmm5, xmm3 + vpblendd xmm3, xmm0, xmm4, 0x02 ; 6 7 + vpbroadcastd xmm0, [srcq+ssq*0] + vpblendd xmm4, xmm4, xmm0, 0x02 ; 7 8 + punpcklbw xmm3, xmm4 ; 67 78 + pmaddubsw xmm4, xmm3, xm11 ; a3 b3 + paddw xmm5, xmm4 + pmulhrsw xmm5, xm7 + packuswb xmm5, xmm5 + movd [dstq+dsq*0], xmm5 + pextrd [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq xmm1, [srcq+ssq*0] + vpbroadcastq ymm0, [srcq+ssq*1] + vpbroadcastq ymm2, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq ymm5, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm4, [srcq+ssq*2] + add srcq, ss3q + vpblendd ymm1, ymm0, 0x30 + vpblendd ymm0, ymm2, 0x30 + punpcklbw ymm1, ymm0 ; 01 12 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm2, ymm5, 0x30 + vpblendd ymm5, ymm3, 0x30 + punpcklbw ymm2, ymm5 ; 23 34 + vpblendd ymm3, ymm4, 0x30 + vpblendd ymm4, ymm0, 0x30 + punpcklbw ymm3, ymm4 ; 45 56 +.v_w8_loop: + vpbroadcastq ymm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw ymm5, ymm1, ym8 ; a0 b0 + mova ymm1, ymm2 + pmaddubsw ymm2, ym9 ; a1 b1 + paddw ymm5, ymm2 + mova ymm2, ymm3 + pmaddubsw ymm3, ym10 ; a2 b2 + paddw ymm5, ymm3 + vpblendd ymm3, ymm0, ymm4, 0x30 + vpbroadcastq ymm0, [srcq+ssq*0] + vpblendd ymm4, ymm4, ymm0, 0x30 + punpcklbw ymm3, ymm4 ; 67 78 + pmaddubsw ymm4, ymm3, ym11 ; a3 b3 + paddw ymm5, ymm4 + pmulhrsw ymm5, ym7 + vextracti128 xmm4, ymm5, 1 + packuswb xmm5, xmm4 + movq [dstq+dsq*0], xmm5 + movhps [dstq+dsq*1], xmm5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + vzeroupper + RET +.v_w16: + mova m12, [spel_v_perm16] + vbroadcasti32x4 m1, [srcq+ssq*0] + vbroadcasti32x4 ym4, [srcq+ssq*1] + mov r6d, 0x0f + vbroadcasti32x4 m2, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti32x4 ym5, [srcq+ssq*0] + kmovb k1, r6d + vbroadcasti32x4 m3, [srcq+ssq*1] + vbroadcasti32x4 ym6, [srcq+ssq*2] + add srcq, ss3q + vbroadcasti32x4 m0, [srcq+ssq*0] + vshufpd m1{k1}, m4, m2, 0xcc + vshufpd m2{k1}, m5, m3, 0xcc + vshufpd m3{k1}, m6, m0, 0xcc + vpermb m1, m12, m1 ; 01 12 + vpermb m2, m12, m2 ; 23 34 + vpermb m3, m12, m3 ; 45 56 +.v_w16_loop: + pmaddubsw m4, m1, m8 ; a0 b0 + mova m1, m2 + pmaddubsw m5, m2, m9 ; a1 b1 + mova m2, m3 + pmaddubsw m6, m3, m10 ; a2 b2 + mova m3, m0 + paddw m4, m5 + vbroadcasti32x4 ym5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti32x4 m0, [srcq+ssq*0] + vshufpd m3{k1}, m5, m0, 0xcc + vpermb m3, m12, m3 ; 67 78 + pmaddubsw m5, m3, m11 ; a3 b3 + paddw m4, m6 + paddw m4, m5 + pmulhrsw m4, m7 + vextracti32x8 ym5, m4, 1 + packuswb ym4, ym5 + mova [dstq+dsq*0], xm4 + vextracti32x4 [dstq+dsq*1], ym4, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w16_loop + RET +.v_w32: + mova m12, [spel_v_perm32] + pmovzxbq m14, [pb_02461357] + vpshrdw m13, m12, m12, 8 + movu ym0, [srcq+ssq*0] + vinserti32x8 m0, [srcq+ssq*1], 1 + vpermb m1, m12, m0 ; 01 + vinserti32x8 m0, [srcq+ssq*2], 0 + add srcq, ss3q + vpermb m2, m13, m0 ; 12 + vinserti32x8 m0, [srcq+ssq*0], 1 + vpermb m3, m12, m0 ; 23 + vinserti32x8 m0, [srcq+ssq*1], 0 + vpermb m4, m13, m0 ; 34 + vinserti32x8 m0, [srcq+ssq*2], 1 + add srcq, ss3q + vpermb m5, m12, m0 ; 45 + vinserti32x8 m0, [srcq+ssq*0], 0 + vpermb m6, m13, m0 ; 56 +.v_w32_loop: + vinserti32x8 m0, [srcq+ssq*1], 1 + lea srcq, [srcq+ssq*2] + pmaddubsw m15, m1, m8 + mova m1, m3 + pmaddubsw m16, m2, m8 + mova m2, m4 + pmaddubsw m17, m3, m9 + mova m3, m5 + pmaddubsw m18, m4, m9 + mova m4, m6 + pmaddubsw m19, m5, m10 + vpermb m5, m12, m0 ; 67 + vinserti32x8 m0, [srcq+ssq*0], 0 + pmaddubsw m20, m6, m10 + vpermb m6, m13, m0 ; 78 + paddw m15, m17 + pmaddubsw m17, m5, m11 + paddw m16, m18 + pmaddubsw m18, m6, m11 + paddw m15, m19 + paddw m16, m20 + paddw m15, m17 + paddw m16, m18 + pmulhrsw m15, m7 + pmulhrsw m16, m7 + packuswb m15, m16 + vpermq m15, m14, m15 + mova [dstq+dsq*0], ym15 + vextracti32x8 [dstq+dsq*1], m15, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w32_loop + vzeroupper + RET +.v_w64: +.v_w128: + lea r6d, [hq+wq*4-256] + mov r4, srcq + mov r7, dstq +.v_loop0: + movu m2, [srcq+ssq*0] + movu m4, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + movu m13, [srcq+ssq*0] + movu m15, [srcq+ssq*1] + movu m17, [srcq+ssq*2] + add srcq, ss3q + movu m0, [srcq+ssq*0] + punpcklbw m1, m2, m4 ; 01l + punpckhbw m2, m4 ; 01h + punpcklbw m3, m4, m6 ; 12l + punpckhbw m4, m6 ; 12h + punpcklbw m5, m6, m13 ; 23l + punpckhbw m6, m13 ; 23h + punpcklbw m12, m13, m15 ; 34l + punpckhbw m13, m15 ; 34h + punpcklbw m14, m15, m17 ; 45l + punpckhbw m15, m17 ; 45h + punpcklbw m16, m17, m0 ; 56l + punpckhbw m17, m0 ; 56h +.v_loop: + pmaddubsw m18, m1, m8 ; a0l + mova m1, m5 + pmaddubsw m19, m2, m8 ; a0h + mova m2, m6 + pmaddubsw m20, m3, m8 ; b0l + mova m3, m12 + pmaddubsw m21, m4, m8 ; b0h + mova m4, m13 + pmaddubsw m5, m9 ; a1l + pmaddubsw m6, m9 ; a1h + pmaddubsw m12, m9 ; b1l + pmaddubsw m13, m9 ; b1h + paddw m18, m5 + mova m5, m14 + pmaddubsw m14, m10 ; a2l + paddw m19, m6 + mova m6, m15 + pmaddubsw m15, m10 ; a2h + paddw m20, m12 + mova m12, m16 + pmaddubsw m16, m10 ; b2l + paddw m21, m13 + mova m13, m17 + pmaddubsw m17, m10 ; b2h + paddw m18, m14 + paddw m19, m15 + paddw m20, m16 + paddw m21, m17 + movu m17, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m14, m0, m17 ; 67l + punpckhbw m15, m0, m17 ; 67h + pmaddubsw m16, m14, m11 ; a3l + pmaddubsw m0, m15, m11 ; a3h + paddw m18, m16 + paddw m19, m0 + movu m0, [srcq+ssq*0] + punpcklbw m16, m17, m0 ; 78l + punpckhbw m17, m0 ; 78h + pmulhrsw m18, m7 + pmulhrsw m19, m7 + packuswb m18, m19 + mova [dstq+dsq*0], m18 + pmaddubsw m18, m16, m11 ; b3l + pmaddubsw m19, m17, m11 ; b3h + paddw m18, m20 + paddw m19, m21 + pmulhrsw m18, m7 + pmulhrsw m19, m7 + packuswb m18, m19 + mova [dstq+dsq*1], m18 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_loop + add r4, 64 + add r7, 64 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 256 + jg .v_loop0 + vzeroupper + RET +.hv: + cmp wd, 4 + jg .hv_w8 + movzx mxd, mxb + dec srcq + vpbroadcastd m7, [base+subpel_filters+mxq*8+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m8, [pd_2] + vpbroadcastq ym0, [base+subpel_filters+myq*8] + lea ss3q, [ssq*3] + vpbroadcastd ym9, [pd_32768] + mov r6, srcq + punpcklbw ym0, ym8, ym0 + sub r6, ss3q + psraw ym0, 2 ; << 6 + mova xm14, [spel_hv_end] + pshufd ym10, ym0, q0000 + pshufd ym11, ym0, q1111 + pshufd ym12, ym0, q2222 + pshufd ym13, ym0, q3333 + cmp wd, 4 + je .hv_w4 + vbroadcasti128 ym6, [subpel_h_shuf4] + movq xmm2, [r6+ssq*0] + movhps xmm2, [r6+ssq*1] + movq xmm0, [r6+ssq*2] + movhps xmm0, [srcq+ssq*0] + vpbroadcastq ymm3, [srcq+ssq*1] + vpbroadcastq ymm4, [srcq+ssq*2] + add srcq, ss3q + vpbroadcastq ymm1, [srcq+ssq*0] + vpblendd ymm2, ymm3, 0x30 + vpblendd ymm0, ymm1, 0x30 ; 2 3 6 _ + vpblendd ymm2, ymm4, 0xc0 ; 0 1 4 5 + pshufb ymm2, ym6 + pshufb ymm0, ym6 + mova ymm1, ym8 + vpdpbusd ymm1, ymm2, ym7 + mova ymm2, ym8 + vpdpbusd ymm2, ymm0, ym7 + packssdw ymm2, ymm1, ymm2 + psraw ymm2, 2 + vextracti128 xmm3, ymm2, 1 + palignr xmm4, xmm3, xmm2, 4 + punpcklwd xmm1, xmm2, xmm4 ; 01 12 + punpckhwd xmm2, xmm4 ; 23 34 + pshufd xmm0, xmm3, q2121 + punpcklwd xmm3, xmm0 ; 45 56 +.hv_w2_loop: + movq xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps xmm4, [srcq+ssq*0] + mova xmm5, xm9 + vpdpwssd xmm5, xmm1, xm10 ; a0 b0 + mova xmm1, xmm2 + vpdpwssd xmm5, xmm2, xm11 ; a1 b1 + pshufb xmm4, xm6 + mova xmm2, xmm3 + vpdpwssd xmm5, xmm3, xm12 ; a2 b2 + mova xmm3, xm8 + vpdpbusd xmm3, xmm4, xm7 + packssdw xmm4, xmm3, xmm3 + psraw xmm4, 2 + palignr xmm3, xmm4, xmm0, 12 + mova xmm0, xmm4 + punpcklwd xmm3, xmm4 ; 67 78 + vpdpwssd xmm5, xmm3, xm13 ; a3 b3 + packuswb xmm5, xmm5 + pshufb xmm5, xm14 + pextrw [dstq+dsq*0], xmm5, 0 + pextrw [dstq+dsq*1], xmm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + vzeroupper + RET +.hv_w4: + movq xmm1, [r6+ssq*0] + vpbroadcastq ym2, [r6+ssq*1] + vinserti32x4 ym1, ymm1, [r6+ssq*2], 1 + vinserti32x4 m2, [srcq+ssq*0], 2 + vinserti32x4 m1, [srcq+ssq*1], 2 + vinserti32x4 m2, [srcq+ssq*2], 3 ; _ 1 3 5 + vbroadcasti32x4 m6, [subpel_h_shufA] + add srcq, ss3q + vinserti32x4 m1, [srcq+ssq*0], 3 ; 0 2 4 6 + pshufb m2, m6 + pshufb m1, m6 + mova m0, m8 + vpdpbusd m0, m2, m7 + mova m4, m8 + vpdpbusd m4, m1, m7 + mova ym1, [spel_hv_perm4a] + mova ym2, [spel_hv_perm4b] + mova ym3, [spel_hv_perm4c] + packssdw m0, m4 + psraw m0, 2 ; _ 0 1 2 3 4 5 6 + mov r6d, 0x5555 + vpermb ym1, ym1, ym0 ; 01 12 + vpermb m2, m2, m0 ; 23 34 + vpermb m3, m3, m0 ; 45 56 + kmovw k1, r6d + mova ym15, [spel_hv_perm4d] +.hv_w4_loop: + movq xmm4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x4 ym4, ymm4, [srcq+ssq*0], 1 + mova ym5, ym9 + vpdpwssd ym5, ym1, ym10 ; a0 b0 + mova ym1, ym2 + pshufb ym4, ym6 + mova ym0, ym8 + vpdpbusd ym0, ym4, ym7 + vpdpwssd ym5, ym2, ym11 ; a1 b1 + mova ym2, ym3 + vpdpwssd ym5, ym3, ym12 ; a2 b2 + vpsraw ym3{k1}, ym0, 2 ; 7 8 + vpermb ym3, ym15, ym3 ; 67 78 + vpdpwssd ym5, ym3, ym13 ; a3 b3 + packuswb ym5, ym5 + vpermb ym5, ym14, ym5 + movd [dstq+dsq*0], xm5 + pextrd [dstq+dsq*1], xm5, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [base+subpel_filters+mxq*8+0] + vpbroadcastd m11, [base+subpel_filters+mxq*8+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + vpbroadcastd m8, [pd_2] + vpbroadcastq m0, [base+subpel_filters+myq*8] + vpbroadcastd m9, [pd_32768] + punpcklbw m0, m8, m0 + lea ss3q, [ssq*3] + psraw m0, 2 ; << 6 + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + cmp wd, 8 + jne .hv_w16 + mov r6, srcq + sub r6, ss3q + movu xmm1, [r6+ssq*0] + vinserti128 ymm1, [r6+ssq*1], 1 + movu xmm2, [srcq+ssq*1] + vinserti32x4 m6, zmm1, [r6+ssq*2], 2 + vinserti128 ymm2, [srcq+ssq*2], 1 + vinserti32x4 m6, [srcq+ssq*0], 3 ; 0 1 2 3 + add srcq, ss3q + vbroadcasti32x4 m4, [subpel_h_shufA] + vinserti32x4 m0, zmm2, [srcq+ssq*0], 2 ; 4 5 6 _ + vbroadcasti32x4 m7, [subpel_h_shufB] + vbroadcasti32x4 m17, [subpel_h_shufC] + pshufb m1, m6, m4 ; 0 1 2 3 0123 + mova m2, m8 + vpdpbusd m2, m1, m10 + pshufb m5, m6, m7 ; 0 1 2 3 4567 + mova m1, m8 + vpdpbusd m1, m5, m10 + pshufb m4, m0, m4 ; 4 5 6 _ 0123 + mova m3, m8 + vpdpbusd m3, m4, m10 + pshufb m7, m0, m7 ; 4 5 6 _ 4567 + mova m4, m8 + vpdpbusd m4, m7, m10 + pshufb m6, m17 + vpdpbusd m2, m5, m11 + vpdpbusd m1, m6, m11 + pshufb m6, m0, m17 + vpdpbusd m3, m7, m11 + vpdpbusd m4, m6, m11 + mova m5, [spel_hv_perm8a] + mova m0, [spel_hv_perm8b] + mov r6, 0x55555555ff00 + packssdw m2, m1 + packssdw m3, m4 + mova m18, [spel_hv_perm8c] + psraw m2, 2 ; 0 1 2 3 + psraw m3, 2 ; 4 5 6 _ + vpermb m1, m5, m2 ; 01 12 + vbroadcasti32x8 m6, [subpel_h_shufA] + kmovq k1, r6 + vpermt2b m2, m0, m3 ; 23 34 + vbroadcasti32x8 m7, [subpel_h_shufB] + kshiftrq k2, k1, 16 + mova xm16, [spel_hv_end] + vpermb m3, m5, m3 ; 45 56 +.hv_w8_loop: + vbroadcasti32x4 ym4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vbroadcasti32x4 m4{k1}, [srcq+ssq*0] + mova m0, m9 + vpdpwssd m0, m1, m12 ; a0 b0 + pshufb m1, m4, m6 ; 7 8 0123 4567 + mova m5, m8 + vpdpbusd m5, m1, m10 + pshufb m4, m7 ; 7 8 4567 89ab + vpdpwssd m0, m2, m13 ; a1 b1 + mova m1, m2 + vpdpbusd m5, m4, m11 + mova m2, m3 + vpdpwssd m0, m3, m14 ; a2 b2 + psraw m3{k2}, m5, 2 ; 75 86 + vpermb m3, m18, m3 ; 67 78 + vpdpwssd m0, m3, m15 ; a3 b3 + packuswb m0, m0 + vpermb zmm1, m16, m0 + movq [dstq+dsq*0], xmm1 + movhps [dstq+dsq*1], xmm1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + vzeroupper + RET +.hv_w16: + movu m7, [spel_hv_perm16a] + sub srcq, ss3q + mova m20, [spel_hv_perm16b] + lea r6d, [wq*2-32] + mova m21, [spel_hv_perm16c] + mov r4, srcq + mov r7, dstq + mova ym16, [spel_hv_end16] + lea r6d, [hq+r6*8] +.hv_w16_loop0: + movu ym17, [srcq+ssq*0] + vinserti32x8 m17, [srcq+ssq*1], 1 ; 0 1 + movu ym18, [srcq+ssq*2] + add srcq, ss3q + vinserti32x8 m18, [srcq+ssq*0], 1 ; 2 3 + movu ym19, [srcq+ssq*1] + vinserti32x8 m19, [srcq+ssq*2], 1 ; 4 5 + add srcq, ss3q + vpermb m2, m7, m17 ; 0 1 0123 89ab + vpermb m0, m20, m17 ; 0 1 4567 cdef + vpermb m4, m7, m18 ; 2 3 0123 89ab + mova m1, m8 + vpdpbusd m1, m2, m10 + vpermb m5, m20, m18 ; 2 3 4567 cdef + mova m2, m8 + vpdpbusd m2, m0, m10 + vpermb m17, m21, m17 ; 0 1 89ab ghij + mova m3, m8 + vpdpbusd m3, m4, m10 + vpermb m6, m7, m19 ; 4 5 0123 89ab + mova m4, m8 + vpdpbusd m4, m5, m10 + vpermb m18, m21, m18 ; 2 3 89ab ghij + vpdpbusd m1, m0, m11 + movu ym0, [srcq+ssq*0] ; 6 + vpdpbusd m2, m17, m11 + vpermb m17, m20, m19 ; 4 5 4567 cdef + vpdpbusd m3, m5, m11 + mova m5, m8 + vpdpbusd m5, m6, m10 + mova m6, m8 + vpdpbusd m6, m17, m10 + vpdpbusd m4, m18, m11 + mova m18, [spel_hv_perm16d] + vpermb m18, m18, m0 ; 6 0145 2367 89cd abef + vpdpbusd m5, m17, m11 + vpermb m19, m21, m19 ; 4 5 89ab ghij + mova m17, m8 + vpdpbusd m17, m18, m10 + mova m18, [spel_hv_perm16e] + vpermb m0, m18, m0 ; 6 4589 67ab cdgh efij + packssdw m1, m2 ; 01 + vpdpbusd m6, m19, m11 + packssdw m3, m4 ; 23 + vpdpbusd m17, m0, m11 + psraw m1, 2 + packssdw m5, m6 ; 45 + psraw m3, 2 + vpshrdd m2, m1, m3, 16 ; 12 + psraw m5, 2 + vpshrdd m4, m3, m5, 16 ; 34 + psraw m17, 2 + vpshrdd m6, m5, m17, 16 ; 56 +.hv_w16_loop: + movu ym18, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + vinserti32x8 m18, [srcq+ssq*0], 1 + mova m0, m9 + vpdpwssd m0, m1, m12 ; a0 + vpermb m1, m7, m18 ; 7 8 0123 89ab + mova m17, m9 + vpdpwssd m17, m2, m12 ; b0 + vpermb m2, m20, m18 ; 7 8 4567 cdef + mova m19, m8 + vpdpbusd m19, m1, m10 + vpermb m18, m21, m18 + mova m1, m8 + vpdpbusd m1, m2, m10 + vpdpwssd m0, m3, m13 ; a1 + vpdpwssd m17, m4, m13 ; b1 + vpdpbusd m19, m2, m11 + mova m2, m4 + vpdpbusd m1, m18, m11 + mova m4, m6 + vpdpwssd m0, m5, m14 ; a2 + vpdpwssd m17, m6, m14 ; b2 + packssdw m19, m1 + mova m1, m3 + mova m3, m5 + psraw m6, m19, 2 ; 7 8 + vpshrdd m5, m4, m6, 16 ; 6 7 + vpdpwssd m17, m6, m15 ; b3 + vpdpwssd m0, m5, m15 ; a3 + packuswb m0, m17 + vpermb zmm1, m16, m0 + mova [dstq+dsq*0], xmm1 + vextracti128 [dstq+dsq*1], ymm1, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w16_loop + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .hv_w16_loop0 + vzeroupper + RET + +%macro PREP_8TAP_H 0 + vpermb m10, m5, m0 + vpermb m11, m5, m1 + vpermb m12, m6, m0 + vpermb m13, m6, m1 + vpermb m14, m7, m0 + vpermb m15, m7, m1 + mova m0, m4 + vpdpbusd m0, m10, m8 + mova m2, m4 + vpdpbusd m2, m12, m8 + mova m1, m4 + vpdpbusd m1, m11, m8 + mova m3, m4 + vpdpbusd m3, m13, m8 + vpdpbusd m0, m12, m9 + vpdpbusd m2, m14, m9 + vpdpbusd m1, m13, m9 + vpdpbusd m3, m15, m9 + packssdw m0, m2 + packssdw m1, m3 + psraw m0, 2 + psraw m1, 2 + mova [tmpq+64*0], m0 + mova [tmpq+64*1], m1 +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%define PREP_8TAP_FN FN prep_8tap, + +PREP_8TAP_FN sharp, SHARP, SHARP +PREP_8TAP_FN sharp_smooth, SHARP, SMOOTH +PREP_8TAP_FN smooth_sharp, SMOOTH, SHARP +PREP_8TAP_FN smooth, SMOOTH, SMOOTH +PREP_8TAP_FN sharp_regular, SHARP, REGULAR +PREP_8TAP_FN regular_sharp, REGULAR, SHARP +PREP_8TAP_FN smooth_regular, SMOOTH, REGULAR +PREP_8TAP_FN regular_smooth, REGULAR, SMOOTH +PREP_8TAP_FN regular, REGULAR, REGULAR + +cglobal prep_8tap_8bpc, 3, 8, 0, tmp, src, stride, w, h, mx, my, stride3 + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + lea r7, [prep_avx512icl] + movsxd wq, wm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + tzcnt wd, wd + movzx wd, word [r7+wq*2+table_offset(prep,)] + add wq, r7 + lea r6, [strideq*3] +%if WIN64 + pop r7 +%endif + jmp wq +.h: + test myd, 0xf00 + jnz .hv + vpbroadcastd m4, [pd_2] + WIN64_SPILL_XMM 10 + cmp wd, 4 + je .h_w4 + tzcnt wd, wd + shr mxd, 16 + sub srcq, 3 + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_h)] + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+0] + vpbroadcastd m9, [r7+mxq*8+subpel_filters-prep_avx512icl+4] + add wq, r7 + jmp wq +.h_w4: + movzx mxd, mxb + vbroadcasti128 ym5, [subpel_h_shufA] + mov r3d, 0x4 + dec srcq + vpbroadcastd ym6, [r7+mxq*8+subpel_filters-prep_avx512icl+2] + kmovb k1, r3d + lea stride3q, [strideq*3] +.h_w4_loop: + movq xm2, [srcq+strideq*0] + movq xm3, [srcq+strideq*1] + vpbroadcastq ym2{k1}, [srcq+strideq*2] + vpbroadcastq ym3{k1}, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + pshufb ym2, ym5 + pshufb ym3, ym5 + mova ym0, ym4 + vpdpbusd ym0, ym2, ym6 + mova ym1, ym4 + vpdpbusd ym1, ym3, ym6 + packssdw ym0, ym1 + psraw ym0, 2 + mova [tmpq], ym0 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + vbroadcasti128 m5, [subpel_h_shufA] + vbroadcasti128 m6, [subpel_h_shufB] + vbroadcasti128 m7, [subpel_h_shufC] + lea stride3q, [strideq*3] +.h_w8_loop: + movu xmm3, [srcq+strideq*0] + vinserti128 ym3, ymm3, [srcq+strideq*1], 1 + vinserti128 m3, [srcq+strideq*2], 2 + vinserti128 m3, [srcq+stride3q ], 3 + lea srcq, [srcq+strideq*4] + pshufb m1, m3, m5 + pshufb m2, m3, m6 + mova m0, m4 + vpdpbusd m0, m1, m8 + mova m1, m4 + vpdpbusd m1, m2, m8 + pshufb m3, m7 + vpdpbusd m0, m2, m9 + vpdpbusd m1, m3, m9 + packssdw m0, m1 + psraw m0, 2 + mova [tmpq], m0 + add tmpq, 64 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + mova m5, [spel_h_perm16a] + mova m6, [spel_h_perm16b] + mova m7, [spel_h_perm16c] + lea stride3q, [strideq*3] +.h_w16_loop: + movu ym0, [srcq+strideq*0] + movu ym1, [srcq+strideq*2] + vinserti32x8 m0, [srcq+strideq*1], 1 + vinserti32x8 m1, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + PREP_8TAP_H + add tmpq, 64*2 + sub hd, 4 + jg .h_w16_loop + RET +.h_w32: + mova m5, [spel_h_perm32a] + mova m6, [spel_h_perm32b] + mova m7, [spel_h_perm32c] +.h_w32_loop: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + PREP_8TAP_H + add tmpq, 64*2 + sub hd, 2 + jg .h_w32_loop + RET +.h_w64: + xor r6d, r6d + jmp .h_start +.h_w128: + mov r6, -64*1 +.h_start: + mova m5, [spel_h_perm32a] + mova m6, [spel_h_perm32b] + mova m7, [spel_h_perm32c] + sub srcq, r6 + mov r5, r6 +.h_loop: + movu m0, [srcq+r6+32*0] + movu m1, [srcq+r6+32*1] + PREP_8TAP_H + add tmpq, 64*2 + add r6, 64 + jle .h_loop + add srcq, strideq + mov r6, r5 + dec hd + jg .h_loop + RET +.v: + movzx mxd, myb ; Select 4-tap/8-tap filter multipliers. + shr myd, 16 ; Note that the code is 8-tap only, having + tzcnt wd, wd + cmp hd, 4 ; a separate 4-tap code path for (4|8|16)x4 + cmove myd, mxd ; had a negligible effect on performance. + ; TODO: Would a 6-tap code path be worth it? + lea myq, [r7+myq*8+subpel_filters-prep_avx512icl] + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_v)] + add wq, r7 + lea stride3q, [strideq*3] + sub srcq, stride3q + vpbroadcastd m7, [pw_8192] + vpbroadcastw m8, [myq+0] + vpbroadcastw m9, [myq+2] + vpbroadcastw m10, [myq+4] + vpbroadcastw m11, [myq+6] + jmp wq +.v_w4: + movd xmm0, [srcq+strideq*0] + vpbroadcastd ymm1, [srcq+strideq*2] + vpbroadcastd xmm2, [srcq+strideq*1] + vpbroadcastd ymm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpblendd ymm1, ymm0, 0x01 ; 0 2 2 _ 2 _ _ _ + vpblendd ymm3, ymm2, 0x03 ; 1 1 3 3 3 3 _ _ + vpbroadcastd ymm0, [srcq+strideq*0] + vpbroadcastd ymm2, [srcq+strideq*1] + vpblendd ymm1, ymm0, 0x68 ; 0 2 2 4 2 4 4 _ + vpbroadcastd ymm0, [srcq+strideq*2] + vbroadcasti128 ymm5, [deint_shuf4] + vpblendd ymm3, ymm2, 0xc0 ; 1 1 3 3 3 3 5 5 + vpblendd ymm2, ymm3, ymm1, 0x55 ; 0 1 2 3 2 3 4 5 + vpblendd ymm3, ymm1, 0xaa ; 1 2 3 4 3 4 5 _ + punpcklbw ymm1, ymm2, ymm3 ; 01 12 23 34 + vpblendd ymm3, ymm0, 0x80 ; 1 2 3 4 3 4 5 6 + punpckhbw ymm2, ymm3 ; 23 34 45 56 +.v_w4_loop: + pinsrd xmm0, [srcq+stride3q ], 1 + lea srcq, [srcq+strideq*4] + vpbroadcastd ymm3, [srcq+strideq*0] + vpbroadcastd ymm4, [srcq+strideq*1] + vpblendd ymm3, ymm4, 0x20 ; _ _ 8 _ 8 9 _ _ + vpblendd ymm3, ymm0, 0x03 ; 6 7 8 _ 8 9 _ _ + vpbroadcastd ymm0, [srcq+strideq*2] + vpblendd ymm3, ymm0, 0x40 ; 6 7 8 _ 8 9 a _ + pshufb ymm3, ymm5 ; 67 78 89 9a + pmaddubsw ymm4, ymm1, ym8 + vperm2i128 ymm1, ymm2, ymm3, 0x21 ; 45 56 67 78 + pmaddubsw ymm2, ym9 + paddw ymm4, ymm2 + mova ymm2, ymm3 + pmaddubsw ymm3, ym11 + paddw ymm3, ymm4 + pmaddubsw ymm4, ymm1, ym10 + paddw ymm3, ymm4 + pmulhrsw ymm3, ym7 + mova [tmpq], ymm3 + add tmpq, 32 + sub hd, 4 + jg .v_w4_loop + vzeroupper + RET +.v_w8: + mov r3d, 0xf044 + kmovw k1, r3d + kshiftrw k2, k1, 8 + movq xm0, [srcq+strideq*0] + vpbroadcastq ym1, [srcq+strideq*1] + vpbroadcastq m2, [srcq+strideq*2] + vpbroadcastq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m4, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + vpbroadcastq m6, [srcq+strideq*2] + vmovdqa64 ym0{k1}, ym1 + vmovdqa64 ym1{k1}, ym2 + vmovdqa64 m2{k1}, m3 + vmovdqa64 m3{k1}, m4 + vmovdqa64 m4{k1}, m5 + vmovdqa64 m5{k1}, m6 + punpcklbw ym0, ym1 ; 01 12 __ __ + punpcklbw m2, m3 ; 23 34 23 34 + punpcklbw m4, m5 ; 45 56 45 56 + vmovdqa64 m0{k2}, m2 ; 01 12 23 34 + vmovdqa64 m2{k2}, m4 ; 23 34 45 56 +.v_w8_loop: + vpbroadcastq m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3, [srcq+strideq*0] + vpbroadcastq m5, [srcq+strideq*1] + pmaddubsw m14, m0, m8 + pmaddubsw m15, m2, m9 + vpblendmq m0{k1}, m6, m1 + vpblendmq m2{k1}, m1, m3 + vpbroadcastq m6, [srcq+strideq*2] + paddw m14, m15 + punpcklbw m2, m0, m2 ; 67 78 67 78 + vpblendmq m12{k1}, m3, m5 + vpblendmq m13{k1}, m5, m6 + vpblendmq m0{k2}, m4, m2 ; 45 56 67 78 + punpcklbw m4, m12, m13 ; 89 9a 89 9a + vmovdqa64 m2{k2}, m4 ; 67 78 89 9a + pmaddubsw m12, m0, m10 + pmaddubsw m13, m2, m11 + paddw m14, m12 + paddw m14, m13 + pmulhrsw m14, m7 + mova [tmpq], m14 + add tmpq, 64 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + mov r3d, 0xf0 + kmovb k1, r3d + vbroadcasti128 m0, [srcq+strideq*0] + vbroadcasti128 m1, [srcq+strideq*1] + vbroadcasti128 m2, [srcq+strideq*2] + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m4, [srcq+strideq*0] + vbroadcasti128 m5, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*2] + vmovdqa64 m0{k1}, m1 + vmovdqa64 m1{k1}, m2 + vmovdqa64 m2{k1}, m3 + vmovdqa64 m3{k1}, m4 + vmovdqa64 m4{k1}, m5 + vmovdqa64 m5{k1}, m6 + shufpd m0, m2, 0xcc ; 0a_2a 0b_2b 1a_3a 1b_3b + shufpd m1, m3, 0xcc ; 1a_3a 1b_3b 2a_4a 2b_4b + shufpd m4, m4, 0x44 ; 4a_-- 4b_-- 5a_-- 5b_-- + shufpd m5, m5, 0x44 ; 5a_-- 5b_-- 6a_-- 6b_-- + punpckhbw m2, m0, m1 ; 23a 23b 34a 34b + punpcklbw m0, m1 ; 01a 01b 12a 12b + punpcklbw m4, m5 ; 45a 45b 56a 56b +.v_w16_loop: + vbroadcasti128 m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vbroadcasti128 m5, [srcq+strideq*0] + vpblendmq m1{k1}, m6, m3 + vmovdqa64 m3{k1}, m5 + pmaddubsw m12, m0, m8 + pmaddubsw m13, m2, m8 + pmaddubsw m14, m2, m9 + pmaddubsw m15, m4, m9 + pmaddubsw m0, m4, m10 + vbroadcasti128 m2, [srcq+strideq*1] + vbroadcasti128 m6, [srcq+strideq*2] + paddw m12, m14 + paddw m13, m15 + paddw m12, m0 + vmovdqa64 m5{k1}, m2 + vmovdqa64 m2{k1}, m6 + mova m0, m4 + shufpd m1, m5, 0xcc ; 6a_8a 6b_8b 7a_9a 7b_9b + shufpd m3, m2, 0xcc ; 7a_9a 7b_9b 8a_Aa 8b_Ab + punpcklbw m2, m1, m3 ; 67a 67b 78a 78b + punpckhbw m4, m1, m3 ; 89a 89b 9Aa 9Ab + pmaddubsw m14, m2, m10 + pmaddubsw m15, m2, m11 + paddw m13, m14 + paddw m12, m15 + pmaddubsw m14, m4, m11 + paddw m13, m14 + pmulhrsw m12, m7 + pmulhrsw m13, m7 + mova [tmpq+ 0], m12 + mova [tmpq+64], m13 + add tmpq, 64*2 + sub hd, 4 + jg .v_w16_loop + RET +.v_w32: + mova m18, [bilin_v_perm64] + movu ym0, [srcq+strideq*0] + movu ym1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym2, [srcq+strideq*0] + movu ym3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym4, [srcq+strideq*0] + movu ym5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym6, [srcq+strideq*0] + vpermq m0, m18, m0 + vpermq m1, m18, m1 + vpermq m2, m18, m2 + vpermq m3, m18, m3 + vpermq m4, m18, m4 + vpermq m5, m18, m5 + vpermq m6, m18, m6 + punpcklbw m0, m1 + punpcklbw m1, m2 + punpcklbw m2, m3 + punpcklbw m3, m4 + punpcklbw m4, m5 + punpcklbw m5, m6 +.v_w32_loop: + movu ym12, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu ym13, [srcq+strideq*0] + pmaddubsw m14, m0, m8 + pmaddubsw m16, m2, m9 + pmaddubsw m15, m1, m8 + pmaddubsw m17, m3, m9 + mova m0, m2 + mova m1, m3 + vpermq m12, m18, m12 + vpermq m13, m18, m13 + paddw m14, m16 + paddw m15, m17 + pmaddubsw m16, m4, m10 + pmaddubsw m17, m5, m10 + punpcklbw m6, m12 + punpcklbw m12, m13 + mova m2, m4 + mova m3, m5 + paddw m14, m16 + paddw m15, m17 + pmaddubsw m16, m6, m11 + pmaddubsw m17, m12, m11 + mova m4, m6 + mova m5, m12 + paddw m14, m16 + paddw m15, m17 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + mova m6, m13 + mova [tmpq+ 0], m14 + mova [tmpq+64], m15 + add tmpq, 64*2 + sub hd, 2 + jg .v_w32_loop + vzeroupper + RET +.v_w64: + mov wd, 64 + jmp .v_start +.v_w128: + mov wd, 128 +.v_start: + WIN64_SPILL_XMM 27 + mova m26, [bilin_v_perm64] + lea r6d, [hq+wq*2] + mov r5, srcq + mov r7, tmpq +.v_loop0: + vpermq m0, m26, [srcq+strideq*0] + vpermq m1, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m2, m26, [srcq+strideq*0] + vpermq m3, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m4, m26, [srcq+strideq*0] + vpermq m5, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m6, m26, [srcq+strideq*0] + punpckhbw m12, m0, m1 + punpcklbw m0, m1 + punpckhbw m13, m1, m2 + punpcklbw m1, m2 + punpckhbw m14, m2, m3 + punpcklbw m2, m3 + punpckhbw m15, m3, m4 + punpcklbw m3, m4 + punpckhbw m16, m4, m5 + punpcklbw m4, m5 + punpckhbw m17, m5, m6 + punpcklbw m5, m6 +.v_loop: + vpermq m18, m26, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vpermq m19, m26, [srcq+strideq*0] + pmaddubsw m20, m0, m8 + pmaddubsw m21, m12, m8 + pmaddubsw m22, m1, m8 + pmaddubsw m23, m13, m8 + mova m0, m2 + mova m12, m14 + mova m1, m3 + mova m13, m15 + pmaddubsw m2, m9 + pmaddubsw m14, m9 + pmaddubsw m3, m9 + pmaddubsw m15, m9 + punpckhbw m24, m6, m18 + punpcklbw m6, m18 + paddw m20, m2 + paddw m21, m14 + paddw m22, m3 + paddw m23, m15 + mova m2, m4 + mova m14, m16 + mova m3, m5 + mova m15, m17 + pmaddubsw m4, m10 + pmaddubsw m16, m10 + pmaddubsw m5, m10 + pmaddubsw m17, m10 + punpckhbw m25, m18, m19 + punpcklbw m18, m19 + paddw m20, m4 + paddw m21, m16 + paddw m22, m5 + paddw m23, m17 + mova m4, m6 + mova m16, m24 + mova m5, m18 + mova m17, m25 + pmaddubsw m6, m11 + pmaddubsw m24, m11 + pmaddubsw m18, m11 + pmaddubsw m25, m11 + paddw m20, m6 + paddw m21, m24 + paddw m22, m18 + paddw m23, m25 + pmulhrsw m20, m7 + pmulhrsw m21, m7 + pmulhrsw m22, m7 + pmulhrsw m23, m7 + mova m6, m19 + mova [tmpq+wq*0+ 0], m20 + mova [tmpq+wq*0+64], m21 + mova [tmpq+wq*2+ 0], m22 + mova [tmpq+wq*2+64], m23 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_loop + add r5, 64 + add r7, 128 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .v_loop0 + RET +.hv: + %assign stack_offset stack_offset - stack_size_padded + %assign stack_size_padded 0 + WIN64_SPILL_XMM 16 + cmp wd, 4 + je .hv_w4 + shr mxd, 16 + sub srcq, 3 + vpbroadcastd m10, [r7+mxq*8+subpel_filters-prep_avx512icl+0] + vpbroadcastd m11, [r7+mxq*8+subpel_filters-prep_avx512icl+4] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + tzcnt wd, wd + vpbroadcastd m8, [pd_2] + movzx wd, word [r7+wq*2+table_offset(prep, _8tap_hv)] + vpbroadcastd m9, [pd_32] + add wq, r7 + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl] + lea stride3q, [strideq*3] + sub srcq, stride3q + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + jmp wq +.hv_w4: + movzx mxd, mxb + dec srcq + vpbroadcastd m8, [r7+mxq*8+subpel_filters-prep_avx512icl+2] + movzx mxd, myb + shr myd, 16 + cmp hd, 4 + cmove myd, mxd + vpbroadcastq m0, [r7+myq*8+subpel_filters-prep_avx512icl] + lea stride3q, [strideq*3] + sub srcq, stride3q + mov r3d, 0x04 + kmovb k1, r3d + kshiftlb k2, k1, 2 + kshiftlb k3, k1, 4 + vpbroadcastd m10, [pd_2] + vbroadcasti128 m16, [subpel_h_shufA] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + vpbroadcastd m11, [pd_32] + pshufd m12, m0, q0000 + pshufd m13, m0, q1111 + pshufd m14, m0, q2222 + pshufd m15, m0, q3333 + movq xm3, [srcq+strideq*0] + vpbroadcastq ym2, [srcq+strideq*1] + vpbroadcastq ym3{k1}, [srcq+strideq*2] + vpbroadcastq m2{k2}, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vpbroadcastq m3{k2}, [srcq+strideq*0] + vpbroadcastq m2{k3}, [srcq+strideq*1] + vpbroadcastq m3{k3}, [srcq+strideq*2] + mova m17, [spel_hv_perm4a] + movu m18, [spel_hv_perm4b] + mova m0, m10 + mova m1, m10 + pshufb m2, m16 + pshufb m3, m16 + vpdpbusd m0, m2, m8 + vpdpbusd m1, m3, m8 + packssdw m0, m1 ; _ 0 1 2 3 4 5 6 + psraw m0, 2 + vpermb m1, m17, m0 ; 01 12 23 34 + vpermb m2, m18, m0 ; 23 34 45 56 +.hv_w4_loop: + movq xm3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + movq xm4, [srcq+strideq*0] + vpbroadcastq ym3{k1}, [srcq+strideq*1] + vpbroadcastq ym4{k1}, [srcq+strideq*2] + mova ym5, ym10 + mova ym6, ym10 + pshufb ym3, ym16 + pshufb ym4, ym16 + vpdpbusd ym5, ym3, ym8 + vpdpbusd ym6, ym4, ym8 + mova m7, m11 + packssdw ym5, ym6 ; 7 8 9 a _ _ _ _ + psraw ym5, 2 + valignq m0, m5, m0, 4 ; _ 4 5 6 7 8 9 a + vpdpwssd m7, m1, m12 + vpdpwssd m7, m2, m13 + vpermb m1, m17, m0 ; 45 56 67 78 + vpermb m2, m18, m0 ; 67 78 89 9a + vpdpwssd m7, m1, m14 + vpdpwssd m7, m2, m15 + psrad m7, 6 + vpmovdw [tmpq], m7 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + vzeroupper + RET +.hv_w8: + WIN64_SPILL_XMM 24 + vbroadcasti128 m16, [subpel_h_shufA] + vbroadcasti128 m17, [subpel_h_shufB] + vbroadcasti128 m18, [subpel_h_shufC] + vinserti128 ym0, [srcq+strideq*0], 1 + vinserti128 m0, [srcq+strideq*1], 2 + vinserti128 m0, [srcq+strideq*2], 3 + movu xm1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 ym1, [srcq+strideq*0], 1 + vinserti128 m1, [srcq+strideq*1], 2 + vinserti128 m1, [srcq+strideq*2], 3 + mova m2, m8 + mova m4, m8 + mova m3, m8 + mova m5, m8 + pshufb m20, m0, m16 + pshufb m21, m0, m17 + pshufb m22, m0, m18 + pshufb m23, m1, m16 + pshufb m6, m1, m17 + pshufb m7, m1, m18 + vpdpbusd m2, m20, m10 + vpdpbusd m4, m21, m10 + vpdpbusd m2, m21, m11 + vpdpbusd m4, m22, m11 + vpdpbusd m3, m23, m10 + vpdpbusd m5, m6, m10 + vpdpbusd m3, m6, m11 + vpdpbusd m5, m7, m11 + packssdw m2, m4 + packssdw m3, m5 + psraw m2, 2 ; _ 0 1 2 + psraw m3, 2 ; 3 4 5 6 + valignq m0, m3, m2, 2 ; 0 1 2 3 + valignq m1, m3, m2, 4 ; 1 2 3 4 + valignq m2, m3, m2, 6 ; 2 3 4 5 + punpcklwd m4, m0, m1 ; 01a 12a 23a 34a + punpckhwd m5, m0, m1 ; 01b 12b 23b 34b + punpcklwd m6, m2, m3 ; 23a 34a 45a 56a + punpckhwd m7, m2, m3 ; 23b 34b 45b 56b +.hv_w8_loop: + movu xm19, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + vinserti128 ym19, [srcq+strideq*0], 1 + vinserti128 m19, [srcq+strideq*1], 2 + vinserti128 m19, [srcq+strideq*2], 3 + mova m20, m9 + mova m21, m9 + mova m22, m8 + mova m23, m8 + vpdpwssd m20, m4, m12 + vpdpwssd m21, m5, m12 + vpdpwssd m20, m6, m13 + vpdpwssd m21, m7, m13 + pshufb m0, m19, m16 + pshufb m1, m19, m17 + pshufb m2, m19, m18 + vpdpbusd m22, m0, m10 + vpdpbusd m23, m1, m10 + vpdpbusd m22, m1, m11 + vpdpbusd m23, m2, m11 + packssdw m22, m23 + psraw m22, 2 ; 7 8 9 A + valignq m0, m22, m3, 2 ; 4 5 6 7 + valignq m1, m22, m3, 4 ; 5 6 7 8 + valignq m2, m22, m3, 6 ; 6 7 8 9 + mova m3, m22 + punpcklwd m4, m0, m1 ; 45a 56a 67a 78a + punpckhwd m5, m0, m1 ; 45b 56b 67b 78b + punpcklwd m6, m2, m3 ; 67a 78a 89a 9Aa + punpckhwd m7, m2, m3 ; 67b 78b 89b 9Ab + vpdpwssd m20, m4, m14 + vpdpwssd m21, m5, m14 + vpdpwssd m20, m6, m15 + vpdpwssd m21, m7, m15 + psrad m20, 6 + psrad m21, 6 + packssdw m20, m21 + mova [tmpq], m20 + add tmpq, 64 + sub hd, 4 + jg .hv_w8_loop + RET +.hv_w16: + mov wd, 16*2 + jmp .hv_start +.hv_w32: + mov wd, 32*2 + jmp .hv_start +.hv_w64: + mov wd, 64*2 + jmp .hv_start +.hv_w128: + mov wd, 128*2 +.hv_start: + WIN64_SPILL_XMM 31 + mova m16, [spel_h_perm16a] + mova m17, [spel_h_perm16b] + mova m18, [spel_h_perm16c] + lea r6d, [hq+wq*8-256] + mov r5, srcq + mov r7, tmpq +.hv_loop0: + movu ym0, [srcq+strideq*0] + vinserti32x8 m0, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym1, [srcq+strideq*0] + vinserti32x8 m1, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym2, [srcq+strideq*0] + vinserti32x8 m2, [srcq+strideq*1], 1 + lea srcq, [srcq+strideq*2] + movu ym3, [srcq+strideq*0] + mova m4, m8 + mova m5, m8 + mova m6, m8 + mova m7, m8 + vpermb m19, m16, m0 + vpermb m20, m17, m0 + vpermb m21, m18, m0 + vpermb m22, m16, m1 + vpermb m23, m17, m1 + vpermb m24, m18, m1 + vpermb m25, m16, m2 + vpermb m26, m17, m2 + vpermb m27, m18, m2 + vpermb ym28, ym16, ym3 + vpermb ym29, ym17, ym3 + vpermb ym30, ym18, ym3 + mova m0, m8 + mova m1, m8 + mova ym2, ym8 + mova ym3, ym8 + vpdpbusd m4, m19, m10 + vpdpbusd m5, m20, m10 + vpdpbusd m6, m22, m10 + vpdpbusd m7, m23, m10 + vpdpbusd m0, m25, m10 + vpdpbusd m1, m26, m10 + vpdpbusd ym2, ym28, ym10 + vpdpbusd ym3, ym29, ym10 + vpdpbusd m4, m20, m11 + vpdpbusd m5, m21, m11 + vpdpbusd m6, m23, m11 + vpdpbusd m7, m24, m11 + vpdpbusd m0, m26, m11 + vpdpbusd m1, m27, m11 + vpdpbusd ym2, ym29, ym11 + vpdpbusd ym3, ym30, ym11 + packssdw m4, m5 + packssdw m6, m7 + packssdw m0, m1 + packssdw ym2, ym3 + psraw m4, 2 ; 0a 0b 1a 1b + psraw m6, 2 ; 2a 2b 3a 3b + psraw m0, 2 ; 4a 4b 5a 5b + psraw ym2, 2 ; 6a 6b __ __ + vshufi32x4 m5, m4, m6, q1032 ; 1a 1b 2a 2b + vshufi32x4 m7, m6, m0, q1032 ; 3a 3b 4a 4b + vshufi32x4 m1, m0, m2, q1032 ; 5a 5b 6a 6b + punpcklwd m2, m4, m5 ; 01a 01c 12a 12c + punpckhwd m3, m4, m5 ; 01b 01d 12b 12d + punpcklwd m4, m6, m7 ; 23a 23c 34a 34c + punpckhwd m5, m6, m7 ; 23b 23d 34b 34d + punpcklwd m6, m0, m1 ; 45a 45c 56a 56c + punpckhwd m7, m0, m1 ; 45b 45d 56b 56d +.hv_loop: + movu ym19, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + vinserti32x8 m19, [srcq+strideq*0], 1 + mova m20, m9 + mova m21, m9 + mova m22, m8 + mova m23, m8 + vpdpwssd m20, m2, m12 + vpdpwssd m21, m3, m12 + vpdpwssd m20, m4, m13 + vpdpwssd m21, m5, m13 + vpermb m24, m16, m19 + vpermb m25, m17, m19 + vpermb m26, m18, m19 + vpdpbusd m22, m24, m10 + vpdpbusd m23, m25, m10 + vpdpbusd m22, m25, m11 + vpdpbusd m23, m26, m11 + packssdw m22, m23 + psraw m22, 2 ; 7a 7b 8a 8b + vshufi32x4 m0, m1, m22, q1032 ; 6a 6b 7a 7b + mova m2, m4 + mova m3, m5 + mova m1, m22 + mova m4, m6 + mova m5, m7 + punpcklwd m6, m0, m1 ; 67a 67c 78a 78c + punpckhwd m7, m0, m1 ; 67b 67d 78b 78d + vpdpwssd m20, m4, m14 + vpdpwssd m21, m5, m14 + vpdpwssd m20, m6, m15 + vpdpwssd m21, m7, m15 + psrad m20, 6 + psrad m21, 6 + packssdw m20, m21 + mova [tmpq+wq*0], ym20 + vextracti32x8 [tmpq+wq*1], m20, 1 + lea tmpq, [tmpq+wq*2] + sub hd, 2 + jg .hv_loop + add r5, 16 + add r7, 32 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r7 + sub r6d, 1<<8 + jg .hv_loop0 + RET + +cglobal warp_affine_8x8t_8bpc, 4, 7, 22, tmp, ts + vpbroadcastd m9, [pd_16384] + mova ym15, [warp_8x8t_end] + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx512icl).main + jmp .start +.loop: + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_avx512icl).main2 + lea tmpq, [tmpq+tsq*4] +.start: + paddd m16, m16 + vpermb m16, m15, m16 + mova [tmpq+tsq*0], xm16 + vextracti128 [tmpq+tsq*2], ym16, 1 + sub r6d, 0x1800 + jg .loop + RET + +cglobal warp_affine_8x8_8bpc, 4, 7, 22, dst, ds, src, ss, abcd, filter + vpbroadcastd m9, [pd_262144] + mova xm15, [warp_8x8_end] + call .main + jmp .start +.loop: + call .main2 + lea dstq, [dstq+dsq*2] +.start: + psrad m16, 19 + packuswb m16, m16 + vpermb m16, m15, m16 + movq [dstq+dsq*0], xm16 + movhps [dstq+dsq*1], xm16 + sub r6d, 0x1800 + jg .loop + RET +ALIGN function_align +.main: + vpbroadcastd m1, [pd_512] +%if WIN64 + mov abcdq, r5mp + vpaddd ym18, ym1, r6m {1to8} ; mx +%else + add r5d, 512 + vpbroadcastd ym18, r5d +%endif + vpaddd ym20, ym1, r7m {1to8} ; my + mova ym16, [pd_0to7] + vpbroadcastd ym19, [abcdq+4*0] + vpbroadcastd ym21, [abcdq+4*1] + lea r4, [ssq*3+3] + mova m10, [warp_8x8_permA] + mov r6d, 0x5555 + mova m11, [warp_8x8_permB] + lea filterq, [mc_warp_filter+64*8] + vpbroadcastq m12, [warp_8x8_hpack] + sub srcq, r4 ; src -= src_stride*3 + 3 + vbroadcasti32x4 m13, [warp_8x8_permC] + kxnorb k2, k2, k2 + vbroadcasti32x4 m14, [warp_8x8_permD] + vpdpwssd ym18, ym19, ym16 ; alpha + vpdpwssd ym20, ym21, ym16 ; gamma + vbroadcasti32x4 m0, [srcq] + psrad ym19, 16 ; beta + psrad ym21, 16 ; delta + kmovw k1, r6d + psrad ym16, ym18, 10 + kmovb k3, k2 + paddd ym18, ym19 + vpgatherdq m2{k2}, [filterq+ym16*8] ; filter_x0 + psrld m1, 8 ; pd_2 + pshufb m0, m11 + paddd m8, m1, m1 ; pd_4 + vpdpbusd m1, m0, m2 + call .h + psllq m2, m1, 45 + pslld m1, 13 + paddd m1, m2 + vpshrdq m1, m0, 48 ; 01 12 + call .h + vpshrdq m2, m1, m0, 48 ; 23 34 + call .h + vpshrdq m3, m2, m0, 48 ; 45 56 +.main2: + call .h + psrad ym17, ym20, 10 + kmovb k2, k3 + paddd ym20, ym21 + vpgatherdq m7{k3}, [filterq+ym17*8] ; filter_y0 + psrad ym16, ym20, 10 + kmovb k3, k2 + paddd ym20, ym21 + vpgatherdq m17{k2}, [filterq+ym16*8] ; filter_y1 + shufps m5, m7, m17, q2020 ; a0 a1 a2 a3 b0 b1 b2 b3 A0 A1 A2 A3 B0 B1 B2 B3 + mova m16, m9 + pshufb m4, m5, m13 ; a0 a1 A0 A1 b0 b1 B0 B1 + vpdpwssd m16, m1, m4 + pshufb m5, m14 ; a2 a3 A2 A3 b2 b3 B2 B3 + mova m1, m2 + vpdpwssd m16, m2, m5 + shufps m5, m7, m17, q3131 ; a4 a5 a6 a7 b4 b5 b6 b7 A4 A5 A6 A7 B4 B5 B6 B7 + mova m2, m3 + pshufb m4, m5, m13 ; a4 a5 A4 A5 b4 b5 B4 B5 + vpdpwssd m16, m3, m4 + vpshrdq m3, m0, 48 ; 67 78 + pshufb m5, m14 ; a6 a7 A6 A7 b6 b7 B6 B7 + vpdpwssd m16, m3, m5 + ret +ALIGN function_align +.h: + movu xm5, [srcq+ssq*1] + psrad ym16, ym18, 10 + lea srcq, [srcq+ssq*2] + vinserti32x4 ym5, [srcq+ssq*0], 1 + kmovb k2, k3 + paddd ym18, ym19 + vpgatherdq m6{k3}, [filterq+ym16*8] ; filter_x1 + psrad ym17, ym18, 10 + kmovb k3, k2 + paddd ym18, ym19 + vpgatherdq m16{k2}, [filterq+ym17*8] ; filter_x2 + mova m0, m8 + vpermb m4, m10, m5 ; a4 b0 a5 b1 a6 b2 a7 b3 a8 b4 a9 b5 aa b6 ab b7 + vpshldq m17, m16, m6, 32 ; a4 a5 a6 a7 b0 b1 b2 b3 + vpdpbusd m0, m4, m17 + vpermb m5, m11, m5 ; a0 b4 a1 b5 a2 b6 a3 b7 a4 b8 a5 b9 a6 ba a7 bb + vmovdqa32 m16{k1}, m6 ; a0 a1 a2 a3 b4 b5 b6 b7 + vpdpbusd m0, m5, m16 + vpmultishiftqb m0, m12, m0 ; 1 1 2 2 (>> 3) + ret + +%macro BIDIR_FN 1 ; op + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM %1 0 + vextracti32x4 xm1, ym0, 1 + movd [dstq ], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_ret + lea dstq, [dstq+strideq*4] + pextrd [dstq ], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_ret: + RET +.w4_h16: + vpbroadcastd m7, strided + pmulld m7, [bidir_sctr_w4] + %1 0 + kxnorw k1, k1, k1 + vpscatterdd [dstq+m7]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM %1 0 + vextracti32x4 xm1, ym0, 1 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + %1_INC_PTR 2 + lea dstq, [dstq+strideq*4] +.w8_h8: + %1 0 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq ], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq ], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 2 + lea dstq, [dstq+strideq*4] +.w16: + %1 0 + vpermq m0, m0, q3120 + mova [dstq ], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m7, [pb_02461357] +.w32_loop: + %1 0 + %1_INC_PTR 2 + vpermq m0, m7, m0 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m7, [pb_02461357] +.w64_loop: + %1 0 + %1_INC_PTR 2 + vpermq m0, m7, m0 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m7, [pb_02461357] +.w128_loop: + %1 0 + vpermq m6, m7, m0 + %1 2 + mova [dstq+64*0], m6 + %1_INC_PTR 4 + vpermq m6, m7, m0 + mova [dstq+64*1], m6 + add dstq, strideq + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + mova m0, [tmp1q+(%1+0)*mmsize] + paddw m0, [tmp2q+(%1+0)*mmsize] + mova m1, [tmp1q+(%1+1)*mmsize] + paddw m1, [tmp2q+(%1+1)*mmsize] + pmulhrsw m0, m4 + pmulhrsw m1, m4 + packuswb m0, m1 +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +cglobal avg_8bpc, 4, 7, 5, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-avg_avx512icl_table + lea r6, [avg_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r6+wq*4] + vpbroadcastd m4, [base+pw_1024] + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m0, [tmp1q+(%1+0)*mmsize] + psubw m2, m0, [tmp2q+(%1+0)*mmsize] + mova m1, [tmp1q+(%1+1)*mmsize] + psubw m3, m1, [tmp2q+(%1+1)*mmsize] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 +%define base r6-w_avg_avx512icl_table + lea r6, [w_avg_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + vpbroadcastw m4, r6m ; weight + movsxd wq, dword [r6+wq*4] + vpbroadcastd m5, [base+pw_2048] + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + pxor m0, m0 + mov tmp1q, tmp2q + psubw m4, m0, m4 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 +%if mmsize == 64 + vpermq m3, m8, [maskq+%1*32] +%else + vpermq m3, [maskq+%1*16], q3120 +%endif + mova m0, [tmp2q+(%1+0)*mmsize] + psubw m1, m0, [tmp1q+(%1+0)*mmsize] + psubb m3, m4, m3 + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 + punpcklbw m2, m4, m3 ; -m << 9 + pmulhw m1, m2 + paddw m0, m1 + mova m1, [tmp2q+(%1+1)*mmsize] + psubw m2, m1, [tmp1q+(%1+1)*mmsize] + paddw m2, m2 + punpckhbw m3, m4, m3 + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*32 + add tmp2q, %1*64 + add tmp1q, %1*64 +%endmacro + +cglobal mask_8bpc, 4, 8, 6, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-mask_avx512icl_table + lea r7, [mask_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + mov maskq, maskmp + movsxd wq, dword [r7+wq*4] + pxor m4, m4 + mova m8, [base+bilin_v_perm64] + vpbroadcastd m5, [base+pw_2048] + add wq, r7 + BIDIR_FN MASK + +%macro W_MASK 4-5 0 ; dst, mask, tmp_offset[1-2], 4:4:4 + mova m%1, [tmp1q+mmsize*%3] + mova m1, [tmp2q+mmsize*%3] + psubw m1, m%1 + pabsw m%2, m1 + psubusw m%2, m6, m%2 + psrlw m%2, 8 ; 64 - m + psllw m2, m%2, 10 + pmulhw m1, m2 + paddw m%1, m1 + mova m1, [tmp1q+mmsize*%4] + mova m2, [tmp2q+mmsize*%4] + psubw m2, m1 + pabsw m3, m2 + psubusw m3, m6, m3 + vpshldw m%2, m3, 8 + psllw m3, m%2, 10 +%if %5 + psubb m%2, m5, m%2 +%endif + pmulhw m2, m3 + paddw m1, m2 + pmulhrsw m%1, m7 + pmulhrsw m1, m7 + packuswb m%1, m1 +%endmacro + +cglobal w_mask_420_8bpc, 4, 8, 16, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_420_avx512icl_table + lea r7, [w_mask_420_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + vpbroadcastd m9, [base+pb_m64] ; -1 << 6 + mova ym10, [base+wm_420_mask+32] + vpbroadcastd m8, [base+wm_sign+r6*8] ; (258 - sign) << 6 + add wq, r7 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + mova m5, [wm_420_perm4] + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1 + vinserti128 ym5, [wm_420_perm4+32], 1 + vpermb ym4, ym5, ym4 + vpdpbusd ym8, ym4, ym9 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + vpermb ym8, ym10, ym8 + movq [maskq], xm8 + RET +.w4_h16: + vpbroadcastd m11, strided + pmulld m11, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + vpdpbusd m8, m4, m9 + kxnorw k1, k1, k1 + vpermb m8, m10, m8 + mova [maskq], xm8 + vpscatterdd [dstq+m11]{k1}, m0 + RET +.w8: + mova m5, [wm_420_perm8] + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1 + vinserti128 ym5, [wm_420_perm8+32], 1 + vpermb ym4, ym5, ym4 + vpdpbusd ym8, ym4, ym9 + vpermb m8, m10, m8 + mova [maskq], xm8 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 16 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + mova m1, m8 + vpdpbusd m1, m4, m9 + vpermb m1, m10, m1 + mova [maskq], xm1 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16: + mova m5, [wm_420_perm16] +.w16_loop: + W_MASK 0, 4, 0, 1 + vpermb m4, m5, m4 + mova m1, m8 + vpdpbusd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m0, q3120 + mova [maskq], xm1 + add maskq, 16 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + lea dstq, [dstq+strideq*4] + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m5, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpbusd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + mova [maskq], xm1 + add maskq, 16 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m12, [wm_420_perm64] ; 0, 2, 4, 6, 8, 10, 12, 14 + psrlq m13, m12, 4 ; 1, 3, 5, 7, 9, 11, 13, 15 +.w64_loop: + W_MASK 0, 4, 0, 2 + W_MASK 11, 5, 1, 3 + mova m2, m8 + vpdpbusd m2, m4, m9 + mova m3, m8 + vpdpbusd m3, m5, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermt2b m2, m10, m3 + mova m1, m0 + vpermt2q m0, m12, m11 + vpermt2q m1, m13, m11 + mova [maskq], ym2 + add maskq, 32 + mova [dstq+strideq*0], m0 + mova [dstq+strideq*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w64_loop + RET +.w128: + pmovzxbq m14, [wm_420_perm64] + mova m10, [wm_420_mask] + psrlq m15, m14, 4 +.w128_loop: + W_MASK 0, 12, 0, 4 + W_MASK 11, 13, 1, 5 + mova m4, m8 + vpdpbusd m4, m12, m9 + mova m5, m8 + vpdpbusd m5, m13, m9 + mova m1, m0 + vpermt2q m0, m14, m11 + vpermt2q m1, m15, m11 + mova [dstq+strideq*0+64*0], m0 + mova [dstq+strideq*1+64*0], m1 + W_MASK 0, 12, 2, 6 + W_MASK 11, 13, 3, 7 + vprold m4, 16 + vprold m5, 16 + vpdpbusd m4, m12, m9 + vpdpbusd m5, m13, m9 + add tmp1q, 512 + add tmp2q, 512 + vpermt2b m4, m10, m5 + mova m1, m0 + vpermt2q m0, m14, m11 + vpermt2q m1, m15, m11 + mova [maskq], m4 + add maskq, 64 + mova [dstq+strideq*0+64*1], m0 + mova [dstq+strideq*1+64*1], m1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w128_loop + RET + +cglobal w_mask_422_8bpc, 4, 8, 14, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_422_avx512icl_table + lea r7, [w_mask_422_avx512icl_table] + tzcnt wd, wm + mov r6d, r7m ; sign + movifnidn hd, hm + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m7, [base+pw_2048] + vpbroadcastd m9, [base+pw_m128] + mova m10, [base+wm_422_mask] + vpbroadcastd m11, [base+pb_127] + add wq, r7 + vpbroadcastd m8, [base+wm_sign+4+r6*4] + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1 + movhps xm10, [wm_422_mask+16] + vpdpwssd ym8, ym4, ym9 + vpermb ym8, ym10, ym8 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + pand xm8, xm11 + mova [maskq], xm8 + RET +.w4_h16: + vpbroadcastd m5, strided + pmulld m5, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1 + vpdpwssd m8, m4, m9 + kxnorw k1, k1, k1 + vpermb m8, m10, m8 + pand ym8, ym11 + mova [maskq], ym8 + vpscatterdd [dstq+m5]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1 + movhps xm10, [wm_422_mask+16] + vpdpwssd ym8, ym4, ym9 + vpermb ym8, ym10, ym8 + pand xm8, xm11 + mova [maskq], xm8 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 32 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + vpermb m1, m10, m1 + pand ym1, ym11 + mova [maskq], ym1 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 32 + lea dstq, [dstq+strideq*4] +.w16: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + vpermb m1, m10, m1 + vpermq m0, m0, q3120 + pand ym1, ym11 + mova [maskq], ym1 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m5, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + pand ym1, ym11 + mova [maskq], ym1 + add maskq, 32 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m5, [pb_02461357] +.w64_loop: + W_MASK 0, 4, 0, 1 + mova m1, m8 + vpdpwssd m1, m4, m9 + add tmp1q, 128 + add tmp2q, 128 + vpermb m1, m10, m1 + vpermq m0, m5, m0 + pand ym1, ym11 + mova [maskq], ym1 + add maskq, 32 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m13, [pb_02461357] +.w128_loop: + W_MASK 0, 4, 0, 1 + W_MASK 12, 5, 2, 3 + mova m2, m8 + vpdpwssd m2, m4, m9 + mova m3, m8 + vpdpwssd m3, m5, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermt2b m2, m10, m3 + vpermq m0, m13, m0 + vpermq m1, m13, m12 + pand m2, m11 + mova [maskq], m2 + add maskq, 64 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, strideq + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 8, 12, dst, stride, tmp1, tmp2, w, h, mask, stride3 +%define base r7-w_mask_444_avx512icl_table + lea r7, [w_mask_444_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r7+wq*4] + vpbroadcastd m6, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + vpbroadcastd m5, [base+pb_64] + vpbroadcastd m7, [base+pw_2048] + mova m8, [base+wm_444_mask] + add wq, r7 + mov maskq, maskmp + lea stride3q, [strideq*3] + jmp wq +.w4: + cmp hd, 8 + jg .w4_h16 + WRAP_YMM W_MASK 0, 4, 0, 1, 1 + vinserti128 ym8, [wm_444_mask+32], 1 + vpermb ym4, ym8, ym4 + mova [maskq], ym4 + vextracti32x4 xm1, m0, 1 + movd [dstq+strideq*0], xm0 + pextrd [dstq+strideq*1], xm0, 1 + movd [dstq+strideq*2], xm1 + pextrd [dstq+stride3q ], xm1, 1 + jl .w4_end + lea dstq, [dstq+strideq*4] + pextrd [dstq+strideq*0], xm0, 2 + pextrd [dstq+strideq*1], xm0, 3 + pextrd [dstq+strideq*2], xm1, 2 + pextrd [dstq+stride3q ], xm1, 3 +.w4_end: + RET +.w4_h16: + vpbroadcastd m9, strided + pmulld m9, [bidir_sctr_w4] + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + kxnorw k1, k1, k1 + mova [maskq], m4 + vpscatterdd [dstq+m9]{k1}, m0 + RET +.w8: + cmp hd, 4 + jne .w8_h8 + WRAP_YMM W_MASK 0, 4, 0, 1, 1 + vinserti128 ym8, [wm_444_mask+32], 1 + vpermb ym4, ym8, ym4 + mova [maskq], ym4 + vextracti32x4 xm1, ym0, 1 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm0 + movhps [dstq+stride3q ], xm1 + RET +.w8_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 64 + lea dstq, [dstq+strideq*4] +.w8_h8: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + mova [maskq], m4 + vextracti32x4 xm1, ym0, 1 + vextracti32x4 xm2, m0, 2 + vextracti32x4 xm3, m0, 3 + movq [dstq+strideq*0], xm0 + movq [dstq+strideq*1], xm1 + movq [dstq+strideq*2], xm2 + movq [dstq+stride3q ], xm3 + lea dstq, [dstq+strideq*4] + movhps [dstq+strideq*0], xm0 + movhps [dstq+strideq*1], xm1 + movhps [dstq+strideq*2], xm2 + movhps [dstq+stride3q ], xm3 + sub hd, 8 + jg .w8_loop + RET +.w16_loop: + add tmp1q, 128 + add tmp2q, 128 + add maskq, 64 + lea dstq, [dstq+strideq*4] +.w16: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + vpermq m0, m0, q3120 + mova [maskq], m4 + mova [dstq+strideq*0], xm0 + vextracti32x4 [dstq+strideq*1], m0, 2 + vextracti32x4 [dstq+strideq*2], ym0, 1 + vextracti32x4 [dstq+stride3q ], m0, 3 + sub hd, 4 + jg .w16_loop + RET +.w32: + pmovzxbq m9, [pb_02461357] +.w32_loop: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + add tmp1q, 128 + add tmp2q, 128 + vpermq m0, m9, m0 + mova [maskq], m4 + add maskq, 64 + mova [dstq+strideq*0], ym0 + vextracti32x8 [dstq+strideq*1], m0, 1 + lea dstq, [dstq+strideq*2] + sub hd, 2 + jg .w32_loop + RET +.w64: + pmovzxbq m9, [pb_02461357] +.w64_loop: + W_MASK 0, 4, 0, 1, 1 + vpermb m4, m8, m4 + add tmp1q, 128 + add tmp2q, 128 + vpermq m0, m9, m0 + mova [maskq], m4 + add maskq, 64 + mova [dstq], m0 + add dstq, strideq + dec hd + jg .w64_loop + RET +.w128: + pmovzxbq m11, [pb_02461357] +.w128_loop: + W_MASK 0, 4, 0, 1, 1 + W_MASK 10, 9, 2, 3, 1 + vpermb m4, m8, m4 + vpermb m9, m8, m9 + add tmp1q, 256 + add tmp2q, 256 + vpermq m0, m11, m0 + vpermq m10, m11, m10 + mova [maskq+64*0], m4 + mova [maskq+64*1], m9 + add maskq, 128 + mova [dstq+64*0], m0 + mova [dstq+64*1], m10 + add dstq, strideq + dec hd + jg .w128_loop + RET + +cglobal blend_8bpc, 3, 7, 8, dst, ds, tmp, w, h, mask +%define base r6-blend_avx512icl_table + lea r6, [blend_avx512icl_table] + tzcnt wd, wm + movifnidn maskq, maskmp + movifnidn hd, hm + movsxd wq, [r6+wq*4] + vpbroadcastd m6, [base+pb_64] + vpbroadcastd m7, [base+pw_512] + sub tmpq, maskq + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + vpbroadcastd xmm1, [dstq+dsq*2] + pinsrd xmm1, [dstq+r6 ], 3 + mova xmm4, [maskq] + mova xmm5, [maskq+tmpq] + add maskq, 4*4 + psubb xmm3, xm6, xmm4 + punpcklbw xmm0, xmm5 + punpcklbw xmm2, xmm3, xmm4 + punpckhbw xmm1, xmm5 + punpckhbw xmm3, xmm4 + pmaddubsw xmm0, xmm2 + pmaddubsw xmm1, xmm3 + pmulhrsw xmm0, xm7 + pmulhrsw xmm1, xm7 + packuswb xmm0, xmm1 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + pextrd [dstq+dsq*2], xmm0, 2 + pextrd [dstq+r6 ], xmm0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w4 + RET +.w8: + movq xmm0, [dstq+dsq*0] + vpbroadcastq xmm1, [dstq+dsq*1] + vpbroadcastq ymm2, [dstq+dsq*2] + vpbroadcastq ymm3, [dstq+r6 ] + mova ymm4, [maskq] + mova ymm5, [maskq+tmpq] + add maskq, 8*4 + vpblendd ymm0, ymm2, 0x30 + vpblendd ymm1, ymm3, 0xc0 + psubb ymm3, ym6, ymm4 + punpcklbw ymm0, ymm5 + punpcklbw ymm2, ymm3, ymm4 + punpckhbw ymm1, ymm5 + punpckhbw ymm3, ymm4 + pmaddubsw ymm0, ymm2 + pmaddubsw ymm1, ymm3 + pmulhrsw ymm0, ym7 + pmulhrsw ymm1, ym7 + packuswb ymm0, ymm1 + vextracti128 xmm1, ymm0, 1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + movq [dstq+dsq*2], xmm1 + movhps [dstq+r6 ], xmm1 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w8 + vzeroupper + RET +.w16: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + vinserti32x4 m1, [dstq+dsq*2], 2 + mova m4, [maskq] + vinserti32x4 m1, [dstq+r6 ], 3 + mova m5, [maskq+tmpq] + add maskq, 16*4 + psubb m3, m6, m4 + punpcklbw m0, m1, m5 + punpcklbw m2, m3, m4 + punpckhbw m1, m5 + punpckhbw m3, m4 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + packuswb m0, m1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], ym0, 1 + vextracti32x4 [dstq+dsq*2], m0, 2 + vextracti32x4 [dstq+r6 ], m0, 3 + lea dstq, [dstq+dsq*4] + sub hd, 4 + jg .w16 + RET +.w32: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + mova m4, [maskq] + mova m5, [maskq+tmpq] + add maskq, 32*2 + psubb m3, m6, m4 + punpcklbw m0, m1, m5 + punpcklbw m2, m3, m4 + punpckhbw m1, m5 + punpckhbw m3, m4 + pmaddubsw m0, m2 + pmaddubsw m1, m3 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_avx512icl_table + lea r5, [blend_v_avx512icl_table] + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, [r5+wq*4] + vpbroadcastd m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_avx512icl_table + jmp wq +.w2: + vpbroadcastd xmm2, [maskq+2*2] +.w2_s0_loop: + movd xmm0, [dstq+dsq*0] + pinsrw xmm0, [dstq+dsq*1], 1 + movd xmm1, [tmpq] + add tmpq, 2*2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w2_s0_loop + RET +.w4: + vpbroadcastq xmm2, [maskq+4*2] +.w4_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movq xmm1, [tmpq] + add tmpq, 4*2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova xmm3, [maskq+8*2] +.w8_loop: + movq xmm0, [dstq+dsq*0] + vpbroadcastq xmm1, [dstq+dsq*1] + mova xmm2, [tmpq] + add tmpq, 8*2 + punpcklbw xmm0, xmm2 + punpckhbw xmm1, xmm2 + pmaddubsw xmm0, xmm3 + pmaddubsw xmm1, xmm3 + pmulhrsw xmm0, xm5 + pmulhrsw xmm1, xm5 + packuswb xmm0, xmm1 + movq [dstq+dsq*0], xmm0 + movhps [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + vbroadcasti32x4 ym3, [maskq+16*2] + vbroadcasti32x4 ym4, [maskq+16*3] +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + mova ym2, [tmpq] + add tmpq, 16*2 + punpcklbw ym0, ym1, ym2 + punpckhbw ym1, ym2 + pmaddubsw ym0, ym3 + pmaddubsw ym1, ym4 + pmulhrsw ym0, ym5 + pmulhrsw ym1, ym5 + packuswb ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w16_loop + RET +.w32: + mova m4, [maskq+32*2] + vshufi32x4 m3, m4, m4, q2020 + vshufi32x4 m4, m4, q3131 +.w32_loop: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + mova m2, [tmpq] + add tmpq, 32*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m4 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w32_loop + RET + +cglobal blend_h_8bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base r6-blend_h_avx512icl_table + lea r6, [blend_h_avx512icl_table] + tzcnt wd, wm + mov hd, hm + movsxd wq, [r6+wq*4] + lea maskq, [base+obmc_masks+hq*2] + vpbroadcastd m5, [base+pw_512] + lea hd, [hq*3] + add wq, r6 + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd xmm0, [dstq+dsq*0] + pinsrw xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movd xmm1, [tmpq] + add tmpq, 2*2 + punpcklwd xmm2, xmm2 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + pextrw [dstq+dsq*0], xmm0, 0 + pextrw [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w2 + RET +.w4: + mova xmm3, [blend_shuf] +.w4_loop: + movd xmm0, [dstq+dsq*0] + pinsrd xmm0, [dstq+dsq*1], 1 + movd xmm2, [maskq+hq*2] + movq xmm1, [tmpq] + add tmpq, 4*2 + pshufb xmm2, xmm3 + punpcklbw xmm0, xmm1 + pmaddubsw xmm0, xmm2 + pmulhrsw xmm0, xm5 + packuswb xmm0, xmm0 + movd [dstq+dsq*0], xmm0 + pextrd [dstq+dsq*1], xmm0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w4_loop + RET +.w8: + vbroadcasti128 ymm4, [blend_shuf] + shufpd ymm4, ymm4, 0x03 +.w8_loop: + vpbroadcastq ymm1, [dstq+dsq*0] + movq xmm0, [dstq+dsq*1] + vpblendd ymm0, ymm1, 0x30 + vpbroadcastd ymm3, [maskq+hq*2] + movq xmm1, [tmpq+8*1] + vinserti128 ymm1, [tmpq+8*0], 1 + add tmpq, 8*2 + pshufb ymm3, ymm4 + punpcklbw ymm0, ymm1 + pmaddubsw ymm0, ymm3 + pmulhrsw ymm0, ym5 + vextracti128 xmm1, ymm0, 1 + packuswb xmm0, xmm1 + movhps [dstq+dsq*0], xmm0 + movq [dstq+dsq*1], xmm0 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w8_loop + vzeroupper + RET +.w16: + vbroadcasti32x4 ym4, [blend_shuf] + shufpd ym4, ym4, 0x0c +.w16_loop: + mova xm1, [dstq+dsq*0] + vinserti32x4 ym1, [dstq+dsq*1], 1 + vpbroadcastd ym3, [maskq+hq*2] + mova ym2, [tmpq] + add tmpq, 16*2 + pshufb ym3, ym4 + punpcklbw ym0, ym1, ym2 + punpckhbw ym1, ym2 + pmaddubsw ym0, ym3 + pmaddubsw ym1, ym3 + pmulhrsw ym0, ym5 + pmulhrsw ym1, ym5 + packuswb ym0, ym1 + mova [dstq+dsq*0], xm0 + vextracti32x4 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w16_loop + RET +.w32: + vbroadcasti32x4 m4, [blend_shuf] + shufpd m4, m4, 0xf0 +.w32_loop: + mova ym1, [dstq+dsq*0] + vinserti32x8 m1, [dstq+dsq*1], 1 + vpbroadcastd m3, [maskq+hq*2] + mova m2, [tmpq] + add tmpq, 32*2 + pshufb m3, m4 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq+dsq*0], ym0 + vextracti32x8 [dstq+dsq*1], m0, 1 + lea dstq, [dstq+dsq*2] + add hq, 2 + jl .w32_loop + RET +.w64: + vpbroadcastw m3, [maskq+hq*2] + mova m1, [dstq] + mova m2, [tmpq] + add tmpq, 32*2 + punpcklbw m0, m1, m2 + punpckhbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + inc hq + jl .w64 + RET +.w128: + vpbroadcastw m6, [maskq+hq*2] + mova m2, [dstq+64*0] + mova m1, [tmpq+64*0] + mova m3, [dstq+64*1] + mova m4, [tmpq+64*1] + add tmpq, 64*2 + punpcklbw m0, m2, m1 + punpckhbw m2, m1 + pmaddubsw m0, m6 + pmaddubsw m2, m6 + punpcklbw m1, m3, m4 + punpckhbw m3, m4 + pmaddubsw m1, m6 + pmaddubsw m3, m6 + REPX {pmulhrsw x, m5}, m0, m2, m1, m3 + packuswb m0, m2 + packuswb m1, m3 + mova [dstq+64*0], m0 + mova [dstq+64*1], m1 + add dstq, dsq + inc hq + jl .w128 + RET + +cglobal resize_8bpc, 6, 12, 19, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + mov r6, ~0 + vpbroadcastd m5, dxm + vpbroadcastd m8, mx0m + vpbroadcastd m6, src_wm + kmovq k3, r6 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ + vpbroadcastd m3, [base+pw_m256] + vpbroadcastd m7, [base+pd_63] + vbroadcasti32x4 m15, [base+pb_8x0_8x8] + vpdpwssd m8, m5, [base+rescale_mul] ; mx+dx*[0-15] + pslld m5, 4 ; dx*16 + pslld m6, 14 + pxor m2, m2 + mova m16, [base+resize_permA] + mova m17, [base+resize_permB] + mova xm18, [base+resize_permC] +.loop_y: + xor xd, xd + mova m4, m8 ; per-line working version of mx +.loop_x: + pmaxsd m0, m4, m2 + psrad m9, m4, 8 ; filter offset (unmasked) + pminsd m0, m6 ; iclip(mx, 0, src_w-8) + psubd m1, m4, m0 ; pshufb offset + psrad m0, 14 ; clipped src_x offset + psrad m1, 14 ; pshufb edge_emu offset + vptestmd k4, m1, m1 + pand m9, m7 ; filter offset (masked) + ktestw k4, k4 + jz .load + vextracti32x8 ym12, m0, 1 + vextracti32x8 ym13, m1, 1 + kmovq k1, k3 + kmovq k2, k3 + vpgatherdq m10{k1}, [srcq+ym0] + vpgatherdq m11{k2}, [srcq+ym12] + kmovq k1, k3 + kmovq k2, k3 + vpgatherdq m14{k1}, [base+resize_shuf+4+ym1] + vpgatherdq m0{k2}, [base+resize_shuf+4+ym13] + mova m12, m16 + mova m13, m17 + paddb m14, m15 + paddb m0, m15 + pshufb m10, m14 + pshufb m11, m0 + vpermi2d m12, m10, m11 + vpermi2d m13, m10, m11 + jmp .filter +.load: + kmovq k1, k3 + kmovq k2, k3 + vpgatherdd m12{k1}, [srcq+m0+0] + vpgatherdd m13{k2}, [srcq+m0+4] +.filter: + kmovq k1, k3 + kmovq k2, k3 + vpgatherdd m10{k1}, [base+resize_filter+m9*8+0] + vpgatherdd m11{k2}, [base+resize_filter+m9*8+4] + mova m14, m2 + vpdpbusd m14, m12, m10 + vpdpbusd m14, m13, m11 + packssdw m14, m14 + pmulhrsw m14, m3 + packuswb m14, m14 + vpermd m14, m18, m14 + mova [dstq+xq], xm14 + paddd m4, m5 + add xd, 16 + cmp xd, dst_wd + jl .loop_x + add dstq, dst_strideq + add srcq, src_strideq + dec hd + jg .loop_y + RET + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/mc_sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/mc_sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9599 @@ +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; Copyright © 2018, VideoLabs +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +; dav1d_obmc_masks[] with 64-x interleaved +obmc_masks: db 0, 0, 0, 0 + ; 2 @4 + db 45, 19, 64, 0 + ; 4 @8 + db 39, 25, 50, 14, 59, 5, 64, 0 + ; 8 @16 + db 36, 28, 42, 22, 48, 16, 53, 11, 57, 7, 61, 3, 64, 0, 64, 0 + ; 16 @32 + db 34, 30, 37, 27, 40, 24, 43, 21, 46, 18, 49, 15, 52, 12, 54, 10 + db 56, 8, 58, 6, 60, 4, 61, 3, 64, 0, 64, 0, 64, 0, 64, 0 + ; 32 @64 + db 33, 31, 35, 29, 36, 28, 38, 26, 40, 24, 41, 23, 43, 21, 44, 20 + db 45, 19, 47, 17, 48, 16, 50, 14, 51, 13, 52, 12, 53, 11, 55, 9 + db 56, 8, 57, 7, 58, 6, 59, 5, 60, 4, 60, 4, 61, 3, 62, 2 + +warp_8x8_shufA: db 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 8 +warp_8x8_shufB: db 4, 6, 8, 10, 5, 7, 9, 11, 5, 7, 9, 11, 6, 8, 10, 12 +warp_8x8_shufC: db 2, 4, 6, 8, 3, 5, 7, 9, 3, 5, 7, 9, 4, 6, 8, 10 +warp_8x8_shufD: db 6, 8, 10, 12, 7, 9, 11, 13, 7, 9, 11, 13, 8, 10, 12, 14 +blend_shuf: db 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3 +subpel_h_shuf4: db 0, 1, 2, 3, 1, 2, 3, 4, 8, 9, 10, 11, 9, 10, 11, 12 + db 2, 3, 4, 5, 3, 4, 5, 6, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_h_shufA: db 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 +subpel_h_shufB: db 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 7, 8, 9, 10 +subpel_h_shufC: db 8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14 +subpel_s_shuf2: db 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11 +subpel_s_shuf8: db 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 +bilin_h_shuf4: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12 +bilin_h_shuf8: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +unpckw: db 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 +rescale_mul: dd 0, 1, 2, 3 +resize_shuf: db 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7 + +wm_420_sign: times 4 dw 258 + times 4 dw 257 +wm_422_sign: times 8 db 128 + times 8 db 127 + +pb_8x0_8x8: times 8 db 0 + times 8 db 8 +bdct_lb_dw: times 4 db 0 + times 4 db 4 + times 4 db 8 + times 4 db 12 + +pb_64: times 16 db 64 +pw_m256: times 8 dw -256 +pw_1: times 8 dw 1 +pw_2: times 8 dw 2 +pw_8: times 8 dw 8 +pw_15: times 8 dw 15 +pw_26: times 8 dw 26 +pw_34: times 8 dw 34 +pw_512: times 8 dw 512 +pw_1024: times 8 dw 1024 +pw_2048: times 8 dw 2048 +pw_6903: times 8 dw 6903 +pw_8192: times 8 dw 8192 +pd_32: times 4 dd 32 +pd_63: times 4 dd 63 +pd_512: times 4 dd 512 +pd_16384: times 4 dd 16484 +pd_32768: times 4 dd 32768 +pd_262144:times 4 dd 262144 +pd_0x3ff: times 4 dd 0x3ff +pd_0x4000:times 4 dd 0x4000 +pq_0x40000000: times 2 dq 0x40000000 + +const mc_warp_filter2 ; dav1d_mc_warp_filter[] reordered for pmaddubsw usage + ; [-1, 0) + db 0, 127, 0, 0, 0, 1, 0, 0, 0, 127, 0, 0, -1, 2, 0, 0 + db 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, 0 + db 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, 0 + db 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, 0 + db 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, 0 + db 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, 0 + db 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, 0 + db 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, 0 + db 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, 0 + db 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, 0 + db 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, 0 + db 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, 0 + db 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, 0 + db 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, 0 + db 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, 0 + db 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, 0 + db 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, 0 + db 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, 0 + db 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, 0 + db 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, 0 + db 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, 0 + db 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, 0 + db 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, 0 + db 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, 0 + db 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, 0 + db 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, 0 + db 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, 0 + db 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, 0 + db 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, 0 + db 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, 0 + db 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, 0 + db 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, 0 + ; [0, 1) + db 0, 0, 1, 0, 0, 127, 0, 0, 0, -1, 2, 0, 0, 127, 0, 0 + db 0, -3, 4, 1, 1, 127, -2, 0, 0, -5, 6, 1, 1, 127, -2, 0 + db 0, -6, 8, 1, 2, 126, -3, 0, -1, -7, 11, 2, 2, 126, -4, -1 + db -1, -8, 13, 2, 3, 125, -5, -1, -1, -10, 16, 3, 3, 124, -6, -1 + db -1, -11, 18, 3, 4, 123, -7, -1, -1, -12, 20, 3, 4, 122, -7, -1 + db -1, -13, 23, 3, 4, 121, -8, -1, -2, -14, 25, 4, 5, 120, -9, -1 + db -1, -15, 27, 4, 5, 119, -10, -1, -1, -16, 30, 4, 5, 118, -11, -1 + db -2, -17, 33, 5, 6, 116, -12, -1, -2, -17, 35, 5, 6, 114, -12, -1 + db -2, -18, 38, 5, 6, 113, -13, -1, -2, -19, 41, 6, 7, 111, -14, -2 + db -2, -19, 43, 6, 7, 110, -15, -2, -2, -20, 46, 6, 7, 108, -15, -2 + db -2, -20, 49, 6, 7, 106, -16, -2, -2, -21, 51, 7, 7, 104, -16, -2 + db -2, -21, 54, 7, 7, 102, -17, -2, -2, -21, 56, 7, 8, 100, -18, -2 + db -2, -22, 59, 7, 8, 98, -18, -2, -2, -22, 62, 7, 8, 96, -19, -2 + db -2, -22, 64, 7, 8, 94, -19, -2, -2, -22, 67, 8, 8, 91, -20, -2 + db -2, -22, 69, 8, 8, 89, -20, -2, -2, -22, 72, 8, 8, 87, -21, -2 + db -2, -21, 74, 8, 8, 84, -21, -2, -2, -22, 77, 8, 8, 82, -21, -2 + db -2, -21, 79, 8, 8, 79, -21, -2, -2, -21, 82, 8, 8, 77, -22, -2 + db -2, -21, 84, 8, 8, 74, -21, -2, -2, -21, 87, 8, 8, 72, -22, -2 + db -2, -20, 89, 8, 8, 69, -22, -2, -2, -20, 91, 8, 8, 67, -22, -2 + db -2, -19, 94, 8, 7, 64, -22, -2, -2, -19, 96, 8, 7, 62, -22, -2 + db -2, -18, 98, 8, 7, 59, -22, -2, -2, -18, 100, 8, 7, 56, -21, -2 + db -2, -17, 102, 7, 7, 54, -21, -2, -2, -16, 104, 7, 7, 51, -21, -2 + db -2, -16, 106, 7, 6, 49, -20, -2, -2, -15, 108, 7, 6, 46, -20, -2 + db -2, -15, 110, 7, 6, 43, -19, -2, -2, -14, 111, 7, 6, 41, -19, -2 + db -1, -13, 113, 6, 5, 38, -18, -2, -1, -12, 114, 6, 5, 35, -17, -2 + db -1, -12, 116, 6, 5, 33, -17, -2, -1, -11, 118, 5, 4, 30, -16, -1 + db -1, -10, 119, 5, 4, 27, -15, -1, -1, -9, 120, 5, 4, 25, -14, -2 + db -1, -8, 121, 4, 3, 23, -13, -1, -1, -7, 122, 4, 3, 20, -12, -1 + db -1, -7, 123, 4, 3, 18, -11, -1, -1, -6, 124, 3, 3, 16, -10, -1 + db -1, -5, 125, 3, 2, 13, -8, -1, -1, -4, 126, 2, 2, 11, -7, -1 + db 0, -3, 126, 2, 1, 8, -6, 0, 0, -2, 127, 1, 1, 6, -5, 0 + db 0, -2, 127, 1, 1, 4, -3, 0, 0, 0, 127, 0, 0, 2, -1, 0 + ; [1, 2) + db 0, 0, 127, 0, 0, 1, 0, 0, 0, 0, 127, 0, 0, -1, 2, 0 + db 0, 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1 + db 0, 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1 + db 0, 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1 + db 0, 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1 + db 0, 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2 + db 0, 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2 + db 0, 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2 + db 0, 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3 + db 0, 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3 + db 0, 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3 + db 0, 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4 + db 0, 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4 + db 0, 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4 + db 0, 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4 + db 0, 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4 + db 0, 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4 + db 0, 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4 + db 0, 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4 + db 0, 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4 + db 0, 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4 + db 0, 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4 + db 0, 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4 + db 0, 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3 + db 0, 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3 + db 0, 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3 + db 0, 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2 + db 0, 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2 + db 0, 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2 + db 0, 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1 + db 0, 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1 + db 0, 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0 + db 0, 0, 2, -1, 0, 0, 127, 0 + +pw_258: times 2 dw 258 + +cextern mc_subpel_filters +%define subpel_filters (mangle(private_prefix %+ _mc_subpel_filters)-8) + +%macro BIDIR_JMP_TABLE 2-* + ;evaluated at definition time (in loop below) + %xdefine %1_%2_table (%%table - 2*%3) + %xdefine %%base %1_%2_table + %xdefine %%prefix mangle(private_prefix %+ _%1_8bpc_%2) + ; dynamically generated label + %%table: + %rep %0 - 2 ; repeat for num args + dd %%prefix %+ .w%3 - %%base + %rotate 1 + %endrep +%endmacro + +BIDIR_JMP_TABLE avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_avg, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE mask, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_420, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_422, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE w_mask_444, ssse3, 4, 8, 16, 32, 64, 128 +BIDIR_JMP_TABLE blend, ssse3, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_v, ssse3, 2, 4, 8, 16, 32 +BIDIR_JMP_TABLE blend_h, ssse3, 2, 4, 8, 16, 16, 16, 16 + +%macro BASE_JMP_TABLE 3-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base %1_%2 + %%table: + %rep %0 - 2 + dw %%base %+ _w%3 - %%base + %rotate 1 + %endrep +%endmacro + +%xdefine prep_sse2 mangle(private_prefix %+ _prep_bilin_8bpc_sse2.prep) +%xdefine put_ssse3 mangle(private_prefix %+ _put_bilin_8bpc_ssse3.put) +%xdefine prep_ssse3 mangle(private_prefix %+ _prep_bilin_8bpc_ssse3.prep) + +BASE_JMP_TABLE put, ssse3, 2, 4, 8, 16, 32, 64, 128 +BASE_JMP_TABLE prep, ssse3, 4, 8, 16, 32, 64, 128 + +%macro HV_JMP_TABLE 5-* + %xdefine %%prefix mangle(private_prefix %+ _%1_%2_8bpc_%3) + %xdefine %%base %1_%3 + %assign %%types %4 + %if %%types & 1 + %xdefine %1_%2_h_%3_table (%%h - %5) + %%h: + %rep %0 - 4 + dw %%prefix %+ .h_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 2 + %xdefine %1_%2_v_%3_table (%%v - %5) + %%v: + %rep %0 - 4 + dw %%prefix %+ .v_w%5 - %%base + %rotate 1 + %endrep + %rotate 4 + %endif + %if %%types & 4 + %xdefine %1_%2_hv_%3_table (%%hv - %5) + %%hv: + %rep %0 - 4 + dw %%prefix %+ .hv_w%5 - %%base + %rotate 1 + %endrep + %endif +%endmacro + +HV_JMP_TABLE prep, 8tap, sse2, 1, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, sse2, 7, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, 8tap, ssse3, 3, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, 8tap, ssse3, 1, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE put, bilin, ssse3, 7, 2, 4, 8, 16, 32, 64, 128 +HV_JMP_TABLE prep, bilin, ssse3, 7, 4, 8, 16, 32, 64, 128 + +%macro SCALED_JMP_TABLE 2-* + %xdefine %1_%2_table (%%table - %3) + %xdefine %%base mangle(private_prefix %+ _%1_8bpc_%2) +%%table: + %rep %0 - 2 + dw %%base %+ .w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_1024: + %xdefine %1_%2_dy1_table (%%dy_1024 - %3) + %rep %0 - 2 + dw %%base %+ .dy1_w%3 - %%base + %rotate 1 + %endrep + %rotate 2 +%%dy_2048: + %xdefine %1_%2_dy2_table (%%dy_2048 - %3) + %rep %0 - 2 + dw %%base %+ .dy2_w%3 - %%base + %rotate 1 + %endrep +%endmacro + +SCALED_JMP_TABLE put_8tap_scaled, ssse3, 2, 4, 8, 16, 32, 64, 128 +SCALED_JMP_TABLE prep_8tap_scaled, ssse3, 4, 8, 16, 32, 64, 128 + +%define table_offset(type, fn) type %+ fn %+ SUFFIX %+ _table - type %+ SUFFIX + +SECTION .text + +INIT_XMM ssse3 + +%if ARCH_X86_32 + DECLARE_REG_TMP 1 + %define base t0-put_ssse3 +%else + DECLARE_REG_TMP 7 + %define base 0 +%endif + +%macro RESTORE_DSQ_32 1 + %if ARCH_X86_32 + mov %1, dsm ; restore dsq + %endif +%endmacro + +cglobal put_bilin_8bpc, 1, 8, 0, dst, ds, src, ss, w, h, mxy + movifnidn mxyd, r6m ; mx + LEA t0, put_ssse3 + movifnidn srcq, srcmp + movifnidn ssq, ssmp + tzcnt wd, wm + mov hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r7m ; my + test mxyd, mxyd + jnz .v +.put: + movzx wd, word [t0+wq*2+table_offset(put,)] + add wq, t0 + RESTORE_DSQ_32 t0 + jmp wq +.put_w2: + movzx r4d, word [srcq+ssq*0] + movzx r6d, word [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4w + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w2 + RET +.put_w4: + mov r4d, [srcq+ssq*0] + mov r6d, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mov [dstq+dsq*0], r4d + mov [dstq+dsq*1], r6d + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w4 + RET +.put_w8: + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movq [dstq+dsq*0], m0 + movq [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w8 + RET +.put_w16: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0], m0 + mova [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w16 + RET +.put_w32: + movu m0, [srcq+ssq*0+16*0] + movu m1, [srcq+ssq*0+16*1] + movu m2, [srcq+ssq*1+16*0] + movu m3, [srcq+ssq*1+16*1] + lea srcq, [srcq+ssq*2] + mova [dstq+dsq*0+16*0], m0 + mova [dstq+dsq*0+16*1], m1 + mova [dstq+dsq*1+16*0], m2 + mova [dstq+dsq*1+16*1], m3 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .put_w32 + RET +.put_w64: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + add srcq, ssq + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + add dstq, dsq + dec hd + jg .put_w64 + RET +.put_w128: + movu m0, [srcq+16*0] + movu m1, [srcq+16*1] + movu m2, [srcq+16*2] + movu m3, [srcq+16*3] + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + mova [dstq+16*2], m2 + mova [dstq+16*3], m3 + movu m0, [srcq+16*4] + movu m1, [srcq+16*5] + movu m2, [srcq+16*6] + movu m3, [srcq+16*7] + mova [dstq+16*4], m0 + mova [dstq+16*5], m1 + mova [dstq+16*6], m2 + mova [dstq+16*7], m3 + add srcq, ssq + add dstq, dsq + dec hd + jg .put_w128 + RET +.h: + ; (16 * src[x] + (mx * (src[x + 1] - src[x])) + 8) >> 4 + ; = ((16 - mx) * src[x] + mx * src[x + 1] + 8) >> 4 + imul mxyd, 0x00ff00ff + mova m4, [base+bilin_h_shuf8] + mova m0, [base+bilin_h_shuf4] + add mxyd, 0x00100010 + movd m5, mxyd + mov mxyd, r7m ; my + pshufd m5, m5, q0000 + test mxyd, mxyd + jnz .hv + movzx wd, word [t0+wq*2+table_offset(put, _bilin_h)] + mova m3, [base+pw_2048] + add wq, t0 + movifnidn dsq, dsmp + jmp wq +.h_w2: + pshufd m4, m4, q3120 ; m4 = {1, 0, 2, 1, 5, 4, 6, 5} +.h_w2_loop: + movd m0, [srcq+ssq*0] + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpckldq m0, m1 + pshufb m0, m4 + pmaddubsw m0, m5 + pmulhrsw m0, m3 + packuswb m0, m0 + movd r6d, m0 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: + movq m4, [srcq+ssq*0] + movhps m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m4, m0 + pmaddubsw m4, m5 + pmulhrsw m4, m3 + packuswb m4, m4 + movd [dstq+dsq*0], m4 + psrlq m4, 32 + movd [dstq+dsq*1], m4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4 + RET +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w8 + RET +.h_w16: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + add srcq, ssq + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq], m0 + add dstq, dsq + dec hd + jg .h_w16 + RET +.h_w32: + movu m0, [srcq+mmsize*0+8*0] + movu m1, [srcq+mmsize*0+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + movu m1, [srcq+mmsize*1+8*0] + movu m2, [srcq+mmsize*1+8*1] + add srcq, ssq + pshufb m1, m4 + pshufb m2, m4 + pmaddubsw m1, m5 + pmaddubsw m2, m5 + pmulhrsw m1, m3 + pmulhrsw m2, m3 + packuswb m1, m2 + mova [dstq+16*0], m0 + mova [dstq+16*1], m1 + add dstq, dsq + dec hd + jg .h_w32 + RET +.h_w64: + mov r6, -16*3 +.h_w64_loop: + movu m0, [srcq+r6+16*3+8*0] + movu m1, [srcq+r6+16*3+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+16*3], m0 + add r6, 16 + jle .h_w64_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w64 + RET +.h_w128: + mov r6, -16*7 +.h_w128_loop: + movu m0, [srcq+r6+16*7+8*0] + movu m1, [srcq+r6+16*7+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 + pmulhrsw m0, m3 + pmulhrsw m1, m3 + packuswb m0, m1 + mova [dstq+r6+16*7], m0 + add r6, 16 + jle .h_w128_loop + add srcq, ssq + add dstq, dsq + dec hd + jg .h_w128 + RET +.v: + movzx wd, word [t0+wq*2+table_offset(put, _bilin_v)] + imul mxyd, 0x00ff00ff + mova m5, [base+pw_2048] + add mxyd, 0x00100010 + add wq, t0 + movd m4, mxyd + pshufd m4, m4, q0000 + movifnidn dsq, dsmp + jmp wq +.v_w2: + movd m0, [srcq+ssq*0] +.v_w2_loop: + pinsrw m0, [srcq+ssq*1], 1 ; 0 1 + lea srcq, [srcq+ssq*2] + pshuflw m1, m0, q2301 + pinsrw m0, [srcq+ssq*0], 0 ; 2 1 + punpcklbw m1, m0 + pmaddubsw m1, m4 + pmulhrsw m1, m5 + packuswb m1, m1 + movd r6d, m1 + mov [dstq+dsq*1], r6w + shr r6d, 16 + mov [dstq+dsq*0], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: + movd m0, [srcq+ssq*0] +.v_w4_loop: + movd m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + movd m0, [srcq+ssq*0] + punpckldq m1, m2 ; 0 1 + punpckldq m2, m0 ; 1 2 + punpcklbw m1, m2 + pmaddubsw m1, m4 + pmulhrsw m1, m5 + packuswb m1, m1 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + ; + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop + RET +.v_w8: + movq m0, [srcq+ssq*0] +.v_w8_loop: + movq m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + movq m0, [srcq+ssq*0] + punpcklbw m1, m2 + punpcklbw m2, m0 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + RET +%macro PUT_BILIN_V_W16 0 + movu m0, [srcq+ssq*0] +%%loop: + movu m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m1, m0 + mova m2, m0 + movu m0, [srcq+ssq*0] + punpcklbw m1, m3 + punpckhbw m2, m3 + pmaddubsw m1, m4 + pmaddubsw m2, m4 + pmulhrsw m1, m5 + pmulhrsw m2, m5 + packuswb m1, m2 + punpcklbw m2, m3, m0 + punpckhbw m3, m0 + pmaddubsw m2, m4 + pmaddubsw m3, m4 + pmulhrsw m2, m5 + pmulhrsw m3, m5 + packuswb m2, m3 + mova [dstq+dsq*0], m1 + mova [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg %%loop +%endmacro +.v_w16: + PUT_BILIN_V_W16 + RET +.v_w128: + lea r6d, [hq+(7<<16)] + jmp .v_w16gt +.v_w64: + lea r6d, [hq+(3<<16)] + jmp .v_w16gt +.v_w32: + lea r6d, [hq+(1<<16)] +.v_w16gt: + mov r4, srcq +%if ARCH_X86_64 + mov r7, dstq +%endif +.v_w16gt_loop: + PUT_BILIN_V_W16 +%if ARCH_X86_64 + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%else + mov dstq, dstmp + add r4, 16 + movzx hd, r6w + add dstq, 16 + mov srcq, r4 + mov dstmp, dstq +%endif + sub r6d, 1<<16 + jg .v_w16gt + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 128) >> 8 + ; = (src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8) >> 4 + movzx wd, word [t0+wq*2+table_offset(put, _bilin_hv)] + WIN64_SPILL_XMM 8 + shl mxyd, 11 ; can't shift by 12 due to signed overflow + mova m7, [base+pw_15] + movd m6, mxyd + add wq, t0 + pshuflw m6, m6, q0000 + paddb m5, m5 + punpcklqdq m6, m6 + jmp wq +.hv_w2: + RESTORE_DSQ_32 t0 + movd m0, [srcq+ssq*0] + punpckldq m0, m0 + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w2_loop: + movd m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + punpckldq m1, m2 + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 _ 2 _ + shufps m2, m0, m1, q1032 ; 0 _ 1 _ + mova m0, m1 + psubw m1, m2 ; 2 * (src[x + src_stride] - src[x]) + pmulhw m1, m6 ; (my * (src[x + src_stride] - src[x]) >> 4 + pavgw m2, m7 ; src[x] + 8 + paddw m1, m2 ; src[x] + ((my * (src[x + src_stride] - src[x])) >> 4) + 8 + psrlw m1, 4 + packuswb m1, m1 +%if ARCH_X86_64 + movq r6, m1 +%else + pshuflw m1, m1, q2020 + movd r6d, m1 +%endif + mov [dstq+dsq*0], r6w + shr r6, gprsize*4 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +.hv_w4: + mova m4, [base+bilin_h_shuf4] + movddup m0, [srcq+ssq*0] + movifnidn dsq, dsmp + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w4_loop: + movq m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movhps m1, [srcq+ssq*0] + pshufb m1, m4 + pmaddubsw m1, m5 ; 1 2 + shufps m2, m0, m1, q1032 ; 0 1 + mova m0, m1 + psubw m1, m2 + pmulhw m1, m6 + pavgw m2, m7 + paddw m1, m2 + psrlw m1, 4 + packuswb m1, m1 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+ssq*0] + movifnidn dsq, dsmp + pshufb m0, m4 + pmaddubsw m0, m5 +.hv_w8_loop: + movu m2, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m2, m4 + pmaddubsw m2, m5 + psubw m1, m2, m0 + pmulhw m1, m6 + pavgw m0, m7 + paddw m1, m0 + movu m0, [srcq+ssq*0] + pshufb m0, m4 + pmaddubsw m0, m5 + psubw m3, m0, m2 + pmulhw m3, m6 + pavgw m2, m7 + paddw m3, m2 + psrlw m1, 4 + psrlw m3, 4 + packuswb m1, m3 + movq [dstq+dsq*0], m1 + movhps [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w128: + lea r6d, [hq+(7<<16)] + jmp .hv_w16_start +.hv_w64: + lea r6d, [hq+(3<<16)] + jmp .hv_w16_start +.hv_w32: + lea r6d, [hq+(1<<16)] +.hv_w16_start: + mov r4, srcq +%if ARCH_X86_32 + %define m8 [dstq] +%else + mov r7, dstq +%endif +.hv_w16: + movifnidn dsq, dsmp +%if WIN64 + movaps r4m, m8 +%endif +.hv_w16_loop0: + movu m0, [srcq+8*0] + movu m1, [srcq+8*1] + pshufb m0, m4 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m5 +.hv_w16_loop: + add srcq, ssq + movu m2, [srcq+8*0] + movu m3, [srcq+8*1] + pshufb m2, m4 + pshufb m3, m4 + pmaddubsw m2, m5 + pmaddubsw m3, m5 + mova m8, m2 + psubw m2, m0 + pmulhw m2, m6 + pavgw m0, m7 + paddw m2, m0 + mova m0, m3 + psubw m3, m1 + pmulhw m3, m6 + pavgw m1, m7 + paddw m3, m1 + mova m1, m0 + mova m0, m8 + psrlw m2, 4 + psrlw m3, 4 + packuswb m2, m3 + mova [dstq], m2 + add dstq, dsmp + dec hd + jg .hv_w16_loop +%if ARCH_X86_32 + mov dstq, dstm + add r4, 16 + movzx hd, r6w + add dstq, 16 + mov srcq, r4 + mov dstm, dstq +%else + add r4, 16 + add r7, 16 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%endif + sub r6d, 1<<16 + jg .hv_w16_loop0 +%if WIN64 + movaps m8, r4m +%endif + RET + +%macro PSHUFB_BILIN_H8 2 ; dst, src + %if cpuflag(ssse3) + pshufb %1, %2 + %else + psrldq %2, %1, 1 + punpcklbw %1, %2 + %endif +%endmacro + +%macro PSHUFB_BILIN_H4 3 ; dst, src, tmp + %if cpuflag(ssse3) + pshufb %1, %2 + %else + psrldq %2, %1, 1 + punpckhbw %3, %1, %2 + punpcklbw %1, %2 + punpcklqdq %1, %3 + %endif +%endmacro + +%macro PMADDUBSW 5 ; dst/src1, src2, zero, tmp, reset_zero + %if cpuflag(ssse3) + pmaddubsw %1, %2 + %else + %if %5 == 1 + pxor %3, %3 + %endif + punpckhbw %4, %1, %3 + punpcklbw %1, %1, %3 + pmaddwd %4, %2 + pmaddwd %1, %2 + packssdw %1, %4 + %endif +%endmacro + +%macro PMULHRSW 5 ; dst, src, tmp, rndval, shift + %if cpuflag(ssse3) + pmulhrsw %1, %2 + %else + punpckhwd %3, %1, %4 + punpcklwd %1, %4 + pmaddwd %3, %2 + pmaddwd %1, %2 + psrad %3, %5 + psrad %1, %5 + packssdw %1, %3 + %endif +%endmacro + +%macro PREP_BILIN 0 +%if ARCH_X86_32 + %define base r6-prep%+SUFFIX +%else + %define base 0 +%endif + +cglobal prep_bilin_8bpc, 3, 7, 0, tmp, src, stride, w, h, mxy, stride3 + movifnidn mxyd, r5m ; mx + LEA r6, prep%+SUFFIX + tzcnt wd, wm + movifnidn hd, hm + test mxyd, mxyd + jnz .h + mov mxyd, r6m ; my + test mxyd, mxyd + jnz .v +.prep: +%if notcpuflag(ssse3) + add r6, prep_ssse3 - prep_sse2 + jmp prep_ssse3 +%else + movzx wd, word [r6+wq*2+table_offset(prep,)] + pxor m4, m4 + add wq, r6 + lea stride3q, [strideq*3] + jmp wq +.prep_w4: + movd m0, [srcq+strideq*0] + movd m1, [srcq+strideq*1] + movd m2, [srcq+strideq*2] + movd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpckldq m0, m1 + punpckldq m2, m3 + punpcklbw m0, m4 + punpcklbw m2, m4 + psllw m0, 4 + psllw m2, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 4 + jg .prep_w4 + RET +.prep_w8: + movq m0, [srcq+strideq*0] + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*2] + movq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .prep_w8 + RET +.prep_w16: + movu m1, [srcq+strideq*0] + movu m3, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .prep_w16 + RET +.prep_w128: + mov r3, -128 + jmp .prep_w32_start +.prep_w64: + mov r3, -64 + jmp .prep_w32_start +.prep_w32: + mov r3, -32 +.prep_w32_start: + sub srcq, r3 +.prep_w32_vloop: + mov r6, r3 +.prep_w32_hloop: + movu m1, [srcq+r6+16*0] + movu m3, [srcq+r6+16*1] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + psllw m0, 4 + psllw m1, 4 + psllw m2, 4 + psllw m3, 4 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + add r6, 32 + jl .prep_w32_hloop + add srcq, strideq + dec hd + jg .prep_w32_vloop + RET +%endif +.h: + ; 16 * src[x] + (mx * (src[x + 1] - src[x])) + ; = (16 - mx) * src[x] + mx * src[x + 1] +%if cpuflag(ssse3) + imul mxyd, 0x00ff00ff + mova m4, [base+bilin_h_shuf8] + add mxyd, 0x00100010 +%else + imul mxyd, 0xffff + add mxyd, 16 +%endif + movd m5, mxyd + mov mxyd, r6m ; my + pshufd m5, m5, q0000 + test mxyd, mxyd + jnz .hv + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_h)] +%if notcpuflag(ssse3) + WIN64_SPILL_XMM 8 + pxor m6, m6 +%endif + add wq, r6 + jmp wq +.h_w4: +%if cpuflag(ssse3) + mova m4, [base+bilin_h_shuf4] +%endif + lea stride3q, [strideq*3] +.h_w4_loop: + movq m0, [srcq+strideq*0] + movhps m0, [srcq+strideq*1] + movq m1, [srcq+strideq*2] + movhps m1, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + PSHUFB_BILIN_H4 m0, m4, m2 + PMADDUBSW m0, m5, m6, m2, 0 + PSHUFB_BILIN_H4 m1, m4, m2 + PMADDUBSW m1, m5, m6, m2, 0 + mova [tmpq+0 ], m0 + mova [tmpq+16], m1 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: + lea stride3q, [strideq*3] +.h_w8_loop: + movu m0, [srcq+strideq*0] + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .h_w8_loop + RET +.h_w16: + movu m0, [srcq+strideq*0+8*0] + movu m1, [srcq+strideq*0+8*1] + movu m2, [srcq+strideq*1+8*0] + movu m3, [srcq+strideq*1+8*1] + lea srcq, [srcq+strideq*2] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 2 + jg .h_w16 + RET +.h_w128: + mov r3, -128 + jmp .h_w32_start +.h_w64: + mov r3, -64 + jmp .h_w32_start +.h_w32: + mov r3, -32 +.h_w32_start: + sub srcq, r3 +.h_w32_vloop: + mov r6, r3 +.h_w32_hloop: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + movu m2, [srcq+r6+8*2] + movu m3, [srcq+r6+8*3] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + add r6, 32 + jl .h_w32_hloop + add srcq, strideq + dec hd + jg .h_w32_vloop + RET +.v: +%if notcpuflag(ssse3) + %assign stack_offset stack_offset - stack_size_padded + WIN64_SPILL_XMM 8 +%endif + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_v)] +%if cpuflag(ssse3) + imul mxyd, 0x00ff00ff + add mxyd, 0x00100010 +%else + imul mxyd, 0xffff + pxor m6, m6 + add mxyd, 16 +%endif + add wq, r6 + lea stride3q, [strideq*3] + movd m5, mxyd + pshufd m5, m5, q0000 + jmp wq +.v_w4: + movd m0, [srcq+strideq*0] +.v_w4_loop: + movd m1, [srcq+strideq*1] + movd m2, [srcq+strideq*2] + movd m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpckldq m0, m1 + punpckldq m1, m2 + punpcklbw m0, m1 ; 01 12 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + movd m0, [srcq+strideq*0] + punpckldq m2, m3 + punpckldq m3, m0 + punpcklbw m2, m3 ; 23 34 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 4 + jg .v_w4_loop + RET +.v_w8: + movq m0, [srcq+strideq*0] +.v_w8_loop: + movq m1, [srcq+strideq*1] + movq m2, [srcq+strideq*2] + movq m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m0, m1 ; 01 + punpcklbw m1, m2 ; 12 + PMADDUBSW m0, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*0], m0 + movq m0, [srcq+strideq*0] + punpcklbw m2, m3 ; 23 + punpcklbw m3, m0 ; 34 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*1], m1 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*2], m2 + mova [tmpq+16*3], m3 + add tmpq, 16*4 + sub hd, 4 + jg .v_w8_loop + RET +.v_w16: + movu m0, [srcq+strideq*0] +.v_w16_loop: + movu m1, [srcq+strideq*1] + movu m2, [srcq+strideq*2] + movu m3, [srcq+stride3q ] + lea srcq, [srcq+strideq*4] + punpcklbw m4, m0, m1 + punpckhbw m0, m1 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + punpcklbw m4, m1, m2 + punpckhbw m1, m2 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*1], m0 + movu m0, [srcq+strideq*0] + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + punpcklbw m4, m2, m3 + punpckhbw m2, m3 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*3], m1 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*4], m4 + punpcklbw m4, m3, m0 + punpckhbw m3, m0 + PMADDUBSW m4, m5, m6, m7, 0 + mova [tmpq+16*5], m2 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*6], m4 + mova [tmpq+16*7], m3 + add tmpq, 16*8 + sub hd, 4 + jg .v_w16_loop + RET +.v_w128: + lea r3d, [hq+(3<<8)] + mov r6d, 256 + jmp .v_w32_start +.v_w64: + lea r3d, [hq+(1<<8)] + mov r6d, 128 + jmp .v_w32_start +.v_w32: + xor r3d, r3d + mov r6d, 64 +.v_w32_start: +%if ARCH_X86_64 + %if WIN64 + PUSH r7 + %endif + mov r7, tmpq +%endif + mov r5, srcq +.v_w32_hloop: + movu m0, [srcq+strideq*0+16*0] + movu m1, [srcq+strideq*0+16*1] +.v_w32_vloop: + movu m2, [srcq+strideq*1+16*0] + movu m3, [srcq+strideq*1+16*1] + lea srcq, [srcq+strideq*2] + punpcklbw m4, m0, m2 + punpckhbw m0, m2 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m0, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + mova [tmpq+16*1], m0 + movu m0, [srcq+strideq*0+16*0] + punpcklbw m4, m1, m3 + punpckhbw m1, m3 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m1, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + mova [tmpq+16*3], m1 + movu m1, [srcq+strideq*0+16*1] + add tmpq, r6 + punpcklbw m4, m2, m0 + punpckhbw m2, m0 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m2, m5, m6, m7, 0 + mova [tmpq+16*0], m4 + mova [tmpq+16*1], m2 + punpcklbw m4, m3, m1 + punpckhbw m3, m1 + PMADDUBSW m4, m5, m6, m7, 0 + PMADDUBSW m3, m5, m6, m7, 0 + mova [tmpq+16*2], m4 + mova [tmpq+16*3], m3 + add tmpq, r6 + sub hd, 2 + jg .v_w32_vloop + add r5, 32 + movzx hd, r3b + mov srcq, r5 +%if ARCH_X86_64 + add r7, 16*4 + mov tmpq, r7 +%else + mov tmpq, tmpmp + add tmpq, 16*4 + mov tmpmp, tmpq +%endif + sub r3d, 1<<8 + jg .v_w32_hloop +%if WIN64 + POP r7 +%endif + RET +.hv: + ; (16 * src[x] + (my * (src[x + src_stride] - src[x])) + 8) >> 4 + ; = src[x] + (((my * (src[x + src_stride] - src[x])) + 8) >> 4) + movzx wd, word [r6+wq*2+table_offset(prep, _bilin_hv)] +%assign stack_offset stack_offset - stack_size_padded +%if cpuflag(ssse3) + imul mxyd, 0x08000800 + WIN64_SPILL_XMM 8 +%else + or mxyd, 1<<16 + WIN64_SPILL_XMM 9 + %if ARCH_X86_64 + mova m8, [base+pw_8] + %else + %define m8 [base+pw_8] + %endif + pxor m7, m7 +%endif + movd m6, mxyd + add wq, r6 + pshufd m6, m6, q0000 + jmp wq +.hv_w4: +%if cpuflag(ssse3) + mova m4, [base+bilin_h_shuf4] + movddup m0, [srcq+strideq*0] +%else + movhps m0, [srcq+strideq*0] +%endif + lea r3, [strideq*3] + PSHUFB_BILIN_H4 m0, m4, m3 + PMADDUBSW m0, m5, m7, m4, 0 ; _ 0 +.hv_w4_loop: + movq m1, [srcq+strideq*1] + movhps m1, [srcq+strideq*2] + movq m2, [srcq+r3 ] + lea srcq, [srcq+strideq*4] + movhps m2, [srcq+strideq*0] + PSHUFB_BILIN_H4 m1, m4, m3 + PSHUFB_BILIN_H4 m2, m4, m3 + PMADDUBSW m1, m5, m7, m4, 0 ; 1 2 + PMADDUBSW m2, m5, m7, m4, 0 ; 3 4 + shufpd m0, m1, 0x01 ; 0 1 + shufpd m3, m1, m2, 0x01 ; 2 3 + psubw m1, m0 + PMULHRSW m1, m6, m4, m8, 4 + paddw m1, m0 + mova m0, m2 + psubw m2, m3 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m3 + mova [tmpq+16*0], m1 + mova [tmpq+16*1], m2 + add tmpq, 32 + sub hd, 4 + jg .hv_w4_loop + RET +.hv_w8: + movu m0, [srcq+strideq*0] + PSHUFB_BILIN_H8 m0, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 0 +.hv_w8_loop: + movu m1, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movu m2, [srcq+strideq*0] + PSHUFB_BILIN_H8 m1, m4 + PSHUFB_BILIN_H8 m2, m4 + PMADDUBSW m1, m5, m7, m4, 0 ; 1 + PMADDUBSW m2, m5, m7, m4, 0 ; 2 + psubw m3, m1, m0 + PMULHRSW m3, m6, m4, m8, 4 + paddw m3, m0 + mova m0, m2 + psubw m2, m1 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m1 + mova [tmpq+16*0], m3 + mova [tmpq+16*1], m2 + add tmpq, 16*2 + sub hd, 2 + jg .hv_w8_loop + RET +.hv_w128: + lea r3d, [hq+(7<<8)] + mov r5d, 256 + jmp .hv_w16_start +.hv_w64: + lea r3d, [hq+(3<<8)] + mov r5d, 128 + jmp .hv_w16_start +.hv_w32: + lea r3d, [hq+(1<<8)] + mov r5d, 64 + jmp .hv_w16_start +.hv_w16: + xor r3d, r3d + mov r5d, 32 +.hv_w16_start: +%if ARCH_X86_64 || cpuflag(ssse3) + mov r6, srcq +%endif +%if ARCH_X86_64 + %if WIN64 + PUSH r7 + %endif + mov r7, tmpq +%endif +.hv_w16_hloop: + movu m0, [srcq+strideq*0+8*0] + movu m1, [srcq+strideq*0+8*1] + PSHUFB_BILIN_H8 m0, m4 + PSHUFB_BILIN_H8 m1, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 0a + PMADDUBSW m1, m5, m7, m4, 0 ; 0b +.hv_w16_vloop: + movu m2, [srcq+strideq*1+8*0] + PSHUFB_BILIN_H8 m2, m4 + PMADDUBSW m2, m5, m7, m4, 0 ; 1a + psubw m3, m2, m0 + PMULHRSW m3, m6, m4, m8, 4 + paddw m3, m0 + mova [tmpq+16*0], m3 + movu m3, [srcq+strideq*1+8*1] + lea srcq, [srcq+strideq*2] + PSHUFB_BILIN_H8 m3, m4 + PMADDUBSW m3, m5, m7, m4, 0 ; 1b + psubw m0, m3, m1 + PMULHRSW m0, m6, m4, m8, 4 + paddw m0, m1 + mova [tmpq+16*1], m0 + add tmpq, r5 + movu m0, [srcq+strideq*0+8*0] + PSHUFB_BILIN_H8 m0, m4 + PMADDUBSW m0, m5, m7, m4, 0 ; 2a + psubw m1, m0, m2 + PMULHRSW m1, m6, m4, m8, 4 + paddw m1, m2 + mova [tmpq+16*0], m1 + movu m1, [srcq+strideq*0+8*1] + PSHUFB_BILIN_H8 m1, m4 + PMADDUBSW m1, m5, m7, m4, 0 ; 2b + psubw m2, m1, m3 + PMULHRSW m2, m6, m4, m8, 4 + paddw m2, m3 + mova [tmpq+16*1], m2 + add tmpq, r5 + sub hd, 2 + jg .hv_w16_vloop + movzx hd, r3b +%if ARCH_X86_64 + add r6, 16 + add r7, 2*16 + mov srcq, r6 + mov tmpq, r7 +%elif cpuflag(ssse3) + mov tmpq, tmpm + add r6, 16 + add tmpq, 2*16 + mov srcq, r6 + mov tmpm, tmpq +%else + mov srcq, srcm + mov tmpq, tmpm + add srcq, 16 + add tmpq, 2*16 + mov srcm, srcq + mov tmpm, tmpq +%endif + sub r3d, 1<<8 + jg .hv_w16_hloop +%if WIN64 + POP r7 +%endif + RET +%endmacro + +; int8_t subpel_filters[5][15][8] +%assign FILTER_REGULAR (0*15 << 16) | 3*15 +%assign FILTER_SMOOTH (1*15 << 16) | 4*15 +%assign FILTER_SHARP (2*15 << 16) | 3*15 + +%macro FN 4 ; prefix, type, type_h, type_v +cglobal %1_%2_8bpc + mov t0d, FILTER_%3 +%ifidn %3, %4 + mov t1d, t0d +%else + mov t1d, FILTER_%4 +%endif +%ifnidn %2, regular ; skip the jump in the last filter + jmp mangle(private_prefix %+ _%1_8bpc %+ SUFFIX) +%endif +%endmacro + +%if ARCH_X86_32 +DECLARE_REG_TMP 1, 2 +%elif WIN64 +DECLARE_REG_TMP 4, 5 +%else +DECLARE_REG_TMP 7, 8 +%endif + +FN put_8tap, sharp, SHARP, SHARP +FN put_8tap, sharp_smooth, SHARP, SMOOTH +FN put_8tap, smooth_sharp, SMOOTH, SHARP +FN put_8tap, smooth, SMOOTH, SMOOTH +FN put_8tap, sharp_regular, SHARP, REGULAR +FN put_8tap, regular_sharp, REGULAR, SHARP +FN put_8tap, smooth_regular, SMOOTH, REGULAR +FN put_8tap, regular_smooth, REGULAR, SMOOTH +FN put_8tap, regular, REGULAR, REGULAR + +%if ARCH_X86_32 + %define base_reg r1 + %define base base_reg-put_ssse3 +%else + %define base_reg r8 + %define base 0 +%endif + +cglobal put_8tap_8bpc, 1, 9, 0, dst, ds, src, ss, w, h, mx, my, ss3 +%assign org_stack_offset stack_offset + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h +%if ARCH_X86_64 + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v +%else + imul ssd, mym, 0x010101 + add ssd, t1d ; 8tap_v, my, 4tap_v + mov srcq, srcm +%endif + mov wd, wm + movifnidn hd, hm + LEA base_reg, put_ssse3 + test mxd, 0xf00 + jnz .h +%if ARCH_X86_32 + test ssd, 0xf00 +%else + test myd, 0xf00 +%endif + jnz .v + tzcnt wd, wd + movzx wd, word [base_reg+wq*2+table_offset(put,)] + add wq, base_reg +; put_bilin mangling jump +%assign stack_offset org_stack_offset + movifnidn dsq, dsmp + movifnidn ssq, ssmp +%if WIN64 + pop r8 +%endif + lea r6, [ssq*3] + jmp wq +.h: +%if ARCH_X86_32 + test ssd, 0xf00 +%else + test myd, 0xf00 +%endif + jnz .hv + movifnidn ssq, ssmp + WIN64_SPILL_XMM 12 + cmp wd, 4 + jl .h_w2 + je .h_w4 + tzcnt wd, wd +%if ARCH_X86_64 + mova m10, [base+subpel_h_shufA] + mova m11, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] +%endif + shr mxd, 16 + sub srcq, 3 + movzx wd, word [base_reg+wq*2+table_offset(put, _8tap_h)] + movq m6, [base_reg+mxq*8+subpel_filters-put_ssse3] + mova m7, [base+pw_34] ; 2 + (8 << 2) + pshufd m5, m6, q0000 + pshufd m6, m6, q1111 + add wq, base_reg + jmp wq +.h_w2: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + mova m4, [base+subpel_h_shuf4] + movd m3, [base_reg+mxq*8+subpel_filters-put_ssse3+2] + mova m5, [base+pw_34] ; 2 + (8 << 2) + pshufd m3, m3, q0000 + movifnidn dsq, dsmp +.h_w2_loop: + movq m0, [srcq+ssq*0] + movhps m0, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m0, m4 + pmaddubsw m0, m3 + phaddw m0, m0 + paddw m0, m5 ; pw34 + psraw m0, 6 + packuswb m0, m0 + movd r6d, m0 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w2_loop + RET +.h_w4: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m3, [base_reg+mxq*8+subpel_filters-put_ssse3+2] + mova m6, [base+subpel_h_shufA] + mova m5, [base+pw_34] ; 2 + (8 << 2) + pshufd m3, m3, q0000 + movifnidn dsq, dsmp +.h_w4_loop: + movq m0, [srcq+ssq*0] ; 1 + movq m1, [srcq+ssq*1] ; 2 + lea srcq, [srcq+ssq*2] + pshufb m0, m6 ; subpel_h_shufA + pshufb m1, m6 ; subpel_h_shufA + pmaddubsw m0, m3 ; subpel_filters + pmaddubsw m1, m3 ; subpel_filters + phaddw m0, m1 + paddw m0, m5 ; pw34 + psraw m0, 6 + packuswb m0, m0 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .h_w4_loop + RET +%macro PUT_8TAP_H 4 ; dst/src, tmp[1-3] + %if ARCH_X86_32 + pshufb %2, %1, [base+subpel_h_shufB] + pshufb %3, %1, [base+subpel_h_shufC] + pshufb %1, [base+subpel_h_shufA] + %else + pshufb %2, %1, m11; subpel_h_shufB + pshufb %3, %1, m9 ; subpel_h_shufC + pshufb %1, m10 ; subpel_h_shufA + %endif + pmaddubsw %4, %2, m5 ; subpel +0 B0 + pmaddubsw %2, m6 ; subpel +4 B4 + pmaddubsw %3, m6 ; C4 + pmaddubsw %1, m5 ; A0 + paddw %3, %4 ; C4+B0 + paddw %1, %2 ; A0+B4 + phaddw %1, %3 + paddw %1, m7 ; pw34 + psraw %1, 6 +%endmacro +.h_w8: + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + PUT_8TAP_H m0, m2, m3, m4 + PUT_8TAP_H m1, m2, m3, m4 + packuswb m0, m1 +%if ARCH_X86_32 + movq [dstq], m0 + add dstq, dsm + movhps [dstq], m0 + add dstq, dsm +%else + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] +%endif + sub hd, 2 + jg .h_w8 + RET +.h_w128: + mov r4, -16*7 + jmp .h_w16_start +.h_w64: + mov r4, -16*3 + jmp .h_w16_start +.h_w32: + mov r4, -16*1 + jmp .h_w16_start +.h_w16: + xor r4d, r4d +.h_w16_start: + sub srcq, r4 + sub dstq, r4 +.h_w16_loop_v: + mov r6, r4 +.h_w16_loop_h: + movu m0, [srcq+r6+8*0] + movu m1, [srcq+r6+8*1] + PUT_8TAP_H m0, m2, m3, m4 + PUT_8TAP_H m1, m2, m3, m4 + packuswb m0, m1 + mova [dstq+r6], m0 + add r6, 16 + jle .h_w16_loop_h + add srcq, ssq + add dstq, dsmp + dec hd + jg .h_w16_loop_v + RET +.v: +%if ARCH_X86_32 + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m0, [base_reg+ssq*8+subpel_filters-put_ssse3] +%else + %assign stack_offset org_stack_offset + WIN64_SPILL_XMM 16 + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-put_ssse3] +%endif + tzcnt r6d, wd + movzx r6d, word [base_reg+r6*2+table_offset(put, _8tap_v)] + punpcklwd m0, m0 + mova m7, [base+pw_512] + add r6, base_reg +%if ARCH_X86_32 + %define subpel0 [rsp+mmsize*0] + %define subpel1 [rsp+mmsize*1] + %define subpel2 [rsp+mmsize*2] + %define subpel3 [rsp+mmsize*3] +%assign regs_used 2 ; use r1 (ds) as tmp for stack alignment if needed + ALLOC_STACK -16*4 +%assign regs_used 7 + pshufd m1, m0, q0000 + mova subpel0, m1 + pshufd m1, m0, q1111 + mova subpel1, m1 + pshufd m1, m0, q2222 + mova subpel2, m1 + pshufd m1, m0, q3333 + mova subpel3, m1 + mov ssq, [rstk+stack_offset+gprsize*4] + lea ssq, [ssq*3] + sub srcq, ssq + mov ssq, [rstk+stack_offset+gprsize*4] + mov dsq, [rstk+stack_offset+gprsize*2] +%else + %define subpel0 m8 + %define subpel1 m9 + %define subpel2 m10 + %define subpel3 m11 + lea ss3q, [ssq*3] + pshufd m8, m0, q0000 + sub srcq, ss3q + pshufd m9, m0, q1111 + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 +%endif + jmp r6 +.v_w2: + movd m1, [srcq+ssq*0] + movd m0, [srcq+ssq*1] +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + movd m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m3, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] +%else + movd m2, [srcq+ssq*2] + add srcq, ss3q + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m4, [srcq+ssq*2] + add srcq, ss3q +%endif + punpcklwd m1, m0 ; 0 1 + punpcklwd m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+ssq*0] + punpcklwd m2, m5 ; 2 3 + punpcklwd m5, m3 ; 3 4 + punpcklwd m3, m4 ; 4 5 + punpcklwd m4, m0 ; 5 6 + punpcklbw m2, m5 ; 23 34 + punpcklbw m3, m4 ; 45 56 +.v_w2_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, subpel0 ; a0 b0 + mova m1, m2 + pmaddubsw m2, subpel1 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, subpel2 ; a2 b2 + paddw m5, m3 + punpcklwd m3, m0, m4 ; 6 7 + movd m0, [srcq+ssq*0] + punpcklwd m4, m0 ; 7 8 + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, subpel3 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + packuswb m5, m5 + movd r6d, m5 + mov [dstq+dsq*0], r6w + shr r6d, 16 + mov [dstq+dsq*1], r6w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w2_loop + RET +.v_w4: +%if ARCH_X86_32 +.v_w8: +.v_w16: +.v_w32: +.v_w64: +.v_w128: + shl wd, 14 +%if STACK_ALIGNMENT < 16 + %define dstm [rsp+mmsize*4+gprsize] + mov dstm, dstq +%endif + lea r6d, [hq+wq-(1<<16)] + mov r4, srcq +.v_w4_loop0: +%endif + movd m1, [srcq+ssq*0] + movd m0, [srcq+ssq*1] +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movd m2, [srcq+ssq*0] + movd m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + movd m3, [srcq+ssq*0] + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] +%else + movd m2, [srcq+ssq*2] + add srcq, ss3q + movd m5, [srcq+ssq*0] + movd m3, [srcq+ssq*1] + movd m4, [srcq+ssq*2] + add srcq, ss3q +%endif + punpckldq m1, m0 ; 0 1 + punpckldq m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+ssq*0] + punpckldq m2, m5 ; 2 3 + punpckldq m5, m3 ; 3 4 + punpckldq m3, m4 ; 4 5 + punpckldq m4, m0 ; 5 6 + punpcklbw m2, m5 ; 23 34 + punpcklbw m3, m4 ; 45 56 +.v_w4_loop: + movd m4, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m5, m1, subpel0 ; a0 b0 + mova m1, m2 + pmaddubsw m2, subpel1 ; a1 b1 + paddw m5, m2 + mova m2, m3 + pmaddubsw m3, subpel2 ; a2 b2 + paddw m5, m3 + punpckldq m3, m0, m4 ; 6 7 _ _ + movd m0, [srcq+ssq*0] + punpckldq m4, m0 ; 7 8 _ _ + punpcklbw m3, m4 ; 67 78 + pmaddubsw m4, m3, subpel3 ; a3 b3 + paddw m5, m4 + pmulhrsw m5, m7 + packuswb m5, m5 + movd [dstq+dsq*0], m5 + psrlq m5, 32 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w4_loop +%if ARCH_X86_32 + mov dstq, dstm + add r4, 4 + movzx hd, r6w + add dstq, 4 + mov srcq, r4 + mov dstm, dstq + sub r6d, 1<<16 + jg .v_w4_loop0 +%endif + RET +%if ARCH_X86_64 +.v_w8: +.v_w16: +.v_w32: +.v_w64: +.v_w128: + lea r6d, [wq*8-64] + mov r4, srcq + mov r7, dstq + lea r6d, [hq+r6*4] +.v_w8_loop0: + movq m1, [srcq+ssq*0] + movq m2, [srcq+ssq*1] + movq m3, [srcq+ssq*2] + add srcq, ss3q + movq m4, [srcq+ssq*0] + movq m5, [srcq+ssq*1] + movq m6, [srcq+ssq*2] + add srcq, ss3q + movq m0, [srcq+ssq*0] + punpcklbw m1, m2 ; 01 + punpcklbw m2, m3 ; 12 + punpcklbw m3, m4 ; 23 + punpcklbw m4, m5 ; 34 + punpcklbw m5, m6 ; 45 + punpcklbw m6, m0 ; 56 +.v_w8_loop: + movq m13, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddubsw m14, m1, subpel0 ; a0 + mova m1, m3 + pmaddubsw m15, m2, subpel0 ; b0 + mova m2, m4 + pmaddubsw m3, subpel1 ; a1 + mova m12, m0 + pmaddubsw m4, subpel1 ; b1 + movq m0, [srcq+ssq*0] + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + pmaddubsw m5, subpel2 ; a2 + mova m4, m6 + pmaddubsw m6, subpel2 ; b2 + punpcklbw m12, m13 ; 67 + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + pmaddubsw m12, subpel3 ; a3 + paddw m15, m6 + mova m6, m13 + pmaddubsw m13, subpel3 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 + packuswb m14, m15 + movq [dstq+dsq*0], m14 + movhps [dstq+dsq*1], m14 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .v_w8_loop + add r4, 8 + add r7, 8 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 + sub r6d, 1<<8 + jg .v_w8_loop0 + RET +%endif ;ARCH_X86_64 +%undef subpel0 +%undef subpel1 +%undef subpel2 +%undef subpel3 +.hv: + %assign stack_offset org_stack_offset + cmp wd, 4 + jg .hv_w8 +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m1, [base_reg+mxq*8+subpel_filters-put_ssse3+2] +%if ARCH_X86_32 + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m0, [base_reg+ssq*8+subpel_filters-put_ssse3] + mov ssq, ssmp + lea r6, [ssq*3] + sub srcq, r6 + %define base_reg r6 + mov r6, r1; use as new base + %assign regs_used 2 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + mov dsq, [rstk+stack_offset+gprsize*2] + %define subpelv0 [rsp+mmsize*0] + %define subpelv1 [rsp+mmsize*1] + %define subpelv2 [rsp+mmsize*2] + %define subpelv3 [rsp+mmsize*3] + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + pshufd m6, m0, q0000 + mova subpelv0, m6 + pshufd m6, m0, q1111 + mova subpelv1, m6 + pshufd m6, m0, q2222 + mova subpelv2, m6 + pshufd m6, m0, q3333 + mova subpelv3, m6 +%else + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-put_ssse3] + ALLOC_STACK mmsize*14, 14 + lea ss3q, [ssq*3] + sub srcq, ss3q + %define subpelv0 m10 + %define subpelv1 m11 + %define subpelv2 m12 + %define subpelv3 m13 + punpcklbw m0, m0 + psraw m0, 8 ; sign-extend + mova m8, [base+pw_8192] + mova m9, [base+pd_512] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + pshufd m7, m1, q0000 + cmp wd, 4 + je .hv_w4 +.hv_w2: + mova m6, [base+subpel_h_shuf4] + movq m2, [srcq+ssq*0] ; 0 + movhps m2, [srcq+ssq*1] ; 0 _ 1 +%if ARCH_X86_32 + %define w8192reg [base+pw_8192] + %define d512reg [base+pd_512] + lea srcq, [srcq+ssq*2] + movq m0, [srcq+ssq*0] ; 2 + movhps m0, [srcq+ssq*1] ; 2 _ 3 + lea srcq, [srcq+ssq*2] +%else + %define w8192reg m8 + %define d512reg m9 + movq m0, [srcq+ssq*2] ; 2 + add srcq, ss3q + movhps m0, [srcq+ssq*0] ; 2 _ 3 +%endif + pshufb m2, m6 ; 0 ~ 1 ~ + pshufb m0, m6 ; 2 ~ 3 ~ + pmaddubsw m2, m7 ; subpel_filters + pmaddubsw m0, m7 ; subpel_filters + phaddw m2, m0 ; 0 1 2 3 + pmulhrsw m2, w8192reg +%if ARCH_X86_32 + movq m3, [srcq+ssq*0] ; 4 + movhps m3, [srcq+ssq*1] ; 4 _ 5 + lea srcq, [srcq+ssq*2] +%else + movq m3, [srcq+ssq*1] ; 4 + movhps m3, [srcq+ssq*2] ; 4 _ 5 + add srcq, ss3q +%endif + movq m0, [srcq+ssq*0] ; 6 + pshufb m3, m6 ; 4 ~ 5 ~ + pshufb m0, m6 ; 6 ~ + pmaddubsw m3, m7 ; subpel_filters + pmaddubsw m0, m7 ; subpel_filters + phaddw m3, m0 ; 4 5 6 _ + pmulhrsw m3, w8192reg + palignr m4, m3, m2, 4; V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 0 1 1 2 + punpckhwd m2, m4 ; V 23 34 2 3 3 4 + pshufd m0, m3, q2121; V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 4 5 5 6 +.hv_w2_loop: + movq m4, [srcq+ssq*1] ; V 7 + lea srcq, [srcq+ssq*2] ; V + movhps m4, [srcq+ssq*0] ; V 7 8 + pshufb m4, m6 + pmaddubsw m4, m7 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 ; V + pmaddwd m2, subpelv1 ; V a1 b1 + paddd m5, m2 ; V + mova m2, m3 ; V + pmaddwd m3, subpelv2 ; a2 b2 + phaddw m4, m4 + pmulhrsw m4, w8192reg + paddd m5, m3 ; V + palignr m3, m4, m0, 12 + mova m0, m4 + punpcklwd m3, m0 ; V 67 78 + pmaddwd m4, m3, subpelv3 ; V a3 b3 + paddd m5, d512reg + paddd m5, m4 + psrad m5, 10 + packssdw m5, m5 + packuswb m5, m5 + movd r4d, m5 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .hv_w2_loop + RET +%undef w8192reg +%undef d512reg +.hv_w4: +%define hv4_line_0_0 4 +%define hv4_line_0_1 5 +%define hv4_line_0_2 6 +%define hv4_line_0_3 7 +%define hv4_line_0_4 8 +%define hv4_line_0_5 9 +%define hv4_line_1_0 10 +%define hv4_line_1_1 11 +%define hv4_line_1_2 12 +%define hv4_line_1_3 13 +%macro SAVELINE_W4 3 + mova [rsp+mmsize*hv4_line_%3_%2], %1 +%endmacro +%macro RESTORELINE_W4 3 + mova %1, [rsp+mmsize*hv4_line_%3_%2] +%endmacro +%if ARCH_X86_32 + %define w8192reg [base+pw_8192] + %define d512reg [base+pd_512] +%else + %define w8192reg m8 + %define d512reg m9 +%endif + ; lower shuffle 0 1 2 3 4 + mova m6, [base+subpel_h_shuf4] + movq m5, [srcq+ssq*0] ; 0 _ _ _ + movhps m5, [srcq+ssq*1] ; 0 _ 1 _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movq m4, [srcq+ssq*0] ; 2 _ _ _ + movhps m4, [srcq+ssq*1] ; 2 _ 3 _ + lea srcq, [srcq+ssq*2] +%else + movq m4, [srcq+ssq*2] ; 2 _ _ _ + movhps m4, [srcq+ss3q ] ; 2 _ 3 _ + lea srcq, [srcq+ssq*4] +%endif + pshufb m2, m5, m6 ;H subpel_h_shuf4 0 ~ 1 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 2 ~ 3 ~ + pmaddubsw m2, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m2, m0 ;H 0 1 2 3 + pmulhrsw m2, w8192reg ;H pw_8192 + SAVELINE_W4 m2, 2, 0 + ; upper shuffle 2 3 4 5 6 + mova m6, [base+subpel_h_shuf4+16] + pshufb m2, m5, m6 ;H subpel_h_shuf4 0 ~ 1 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 2 ~ 3 ~ + pmaddubsw m2, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m2, m0 ;H 0 1 2 3 + pmulhrsw m2, w8192reg ;H pw_8192 + ; + ; lower shuffle + mova m6, [base+subpel_h_shuf4] + movq m5, [srcq+ssq*0] ; 4 _ _ _ + movhps m5, [srcq+ssq*1] ; 4 _ 5 _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] + movq m4, [srcq+ssq*0] ; 6 _ _ _ + add srcq, ssq +%else + movq m4, [srcq+ssq*2] ; 6 _ _ _ + add srcq, ss3q +%endif + pshufb m3, m5, m6 ;H subpel_h_shuf4 4 ~ 5 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 6 ~ 6 ~ + pmaddubsw m3, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m3, m0 ;H 4 5 6 7 + pmulhrsw m3, w8192reg ;H pw_8192 + SAVELINE_W4 m3, 3, 0 + ; upper shuffle + mova m6, [base+subpel_h_shuf4+16] + pshufb m3, m5, m6 ;H subpel_h_shuf4 4 ~ 5 ~ + pshufb m0, m4, m6 ;H subpel_h_shuf4 6 ~ 6 ~ + pmaddubsw m3, m7 ;H subpel_filters + pmaddubsw m0, m7 ;H subpel_filters + phaddw m3, m0 ;H 4 5 6 7 + pmulhrsw m3, w8192reg ;H pw_8192 + ;process high + palignr m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + ;process low + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + palignr m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 +.hv_w4_loop: + ;process low + pmaddwd m5, m1, subpelv0 ; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 + mova m6, [base+subpel_h_shuf4] + movq m4, [srcq+ssq*0] ; 7 + movhps m4, [srcq+ssq*1] ; 7 _ 8 _ + pshufb m4, m6 ;H subpel_h_shuf4 7 ~ 8 ~ + pmaddubsw m4, m7 ;H subpel_filters + phaddw m4, m4 ;H 7 8 7 8 + pmulhrsw m4, w8192reg ;H pw_8192 + palignr m3, m4, m0, 12 ; 6 7 8 7 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 + paddd m5, d512reg ; pd_512 + paddd m5, m4 + psrad m5, 10 + SAVELINE_W4 m0, 0, 0 + SAVELINE_W4 m1, 1, 0 + SAVELINE_W4 m2, 2, 0 + SAVELINE_W4 m3, 3, 0 + SAVELINE_W4 m5, 5, 0 + ;process high + RESTORELINE_W4 m0, 0, 1 + RESTORELINE_W4 m1, 1, 1 + RESTORELINE_W4 m2, 2, 1 + RESTORELINE_W4 m3, 3, 1 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 + mova m6, [base+subpel_h_shuf4+16] + movq m4, [srcq+ssq*0] ; 7 + movhps m4, [srcq+ssq*1] ; 7 _ 8 _ + lea srcq, [srcq+ssq*2] + pshufb m4, m6 ;H subpel_h_shuf4 7 ~ 8 ~ + pmaddubsw m4, m7 ;H subpel_filters + phaddw m4, m4 ;H 7 8 7 8 + pmulhrsw m4, w8192reg ;H pw_8192 + palignr m3, m4, m0, 12 ; 6 7 8 7 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 + paddd m5, d512reg ; pd_512 + paddd m5, m4 + psrad m4, m5, 10 + RESTORELINE_W4 m5, 5, 0 + packssdw m5, m4 ; d -> w + packuswb m5, m5 ; w -> b + pshuflw m5, m5, q3120 + movd [dstq+dsq*0], m5 + psrlq m5, 32 + movd [dstq+dsq*1], m5 + lea dstq, [dstq+dsq*2] + sub hd, 2 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + RESTORELINE_W4 m0, 0, 0 + RESTORELINE_W4 m1, 1, 0 + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + jg .hv_w4_loop + RET +%undef subpelv0 +%undef subpelv1 +%undef subpelv2 +%undef subpelv3 +.hv_w8: + %assign stack_offset org_stack_offset +%define hv8_line_1 0 +%define hv8_line_2 1 +%define hv8_line_3 2 +%define hv8_line_4 3 +%define hv8_line_6 4 +%macro SAVELINE_W8 2 + mova [rsp+hv8_line_%1*mmsize], %2 +%endmacro +%macro RESTORELINE_W8 2 + mova %2, [rsp+hv8_line_%1*mmsize] +%endmacro + shr mxd, 16 + sub srcq, 3 +%if ARCH_X86_32 + %define base_reg r1 + %define subpelh0 [rsp+mmsize*5] + %define subpelh1 [rsp+mmsize*6] + %define subpelv0 [rsp+mmsize*7] + %define subpelv1 [rsp+mmsize*8] + %define subpelv2 [rsp+mmsize*9] + %define subpelv3 [rsp+mmsize*10] + %define accuv0 [rsp+mmsize*11] + %define accuv1 [rsp+mmsize*12] + movq m1, [base_reg+mxq*8+subpel_filters-put_ssse3] + movzx mxd, ssb + shr ssd, 16 + cmp hd, 6 + cmovs ssd, mxd + movq m5, [base_reg+ssq*8+subpel_filters-put_ssse3] + mov ssq, ssmp + ALLOC_STACK -mmsize*13 +%if STACK_ALIGNMENT < 16 + %define dstm [rsp+mmsize*13+gprsize*1] + %define dsm [rsp+mmsize*13+gprsize*2] + mov r6, [rstk+stack_offset+gprsize*2] + mov dsm, r6 +%endif + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + punpcklbw m5, m5 + psraw m5, 8 ; sign-extend + pshufd m2, m5, q0000 + pshufd m3, m5, q1111 + pshufd m4, m5, q2222 + pshufd m5, m5, q3333 + mova subpelh0, m0 + mova subpelh1, m1 + mova subpelv0, m2 + mova subpelv1, m3 + mova subpelv2, m4 + mova subpelv3, m5 + lea r6, [ssq*3] + mov dstm, dstq + sub srcq, r6 +%else + ALLOC_STACK 16*5, 16 + %define subpelh0 m10 + %define subpelh1 m11 + %define subpelv0 m12 + %define subpelv1 m13 + %define subpelv2 m14 + %define subpelv3 m15 + %define accuv0 m8 + %define accuv1 m9 + movq m0, [base_reg+mxq*8+subpel_filters-put_ssse3] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m1, [base_reg+myq*8+subpel_filters-put_ssse3] + pshufd subpelh0, m0, q0000 + pshufd subpelh1, m0, q1111 + punpcklbw m1, m1 + psraw m1, 8 ; sign-extend + pshufd subpelv0, m1, q0000 + pshufd subpelv1, m1, q1111 + pshufd subpelv2, m1, q2222 + pshufd subpelv3, m1, q3333 + lea ss3q, [ssq*3] + mov r7, dstq + sub srcq, ss3q +%endif + shl wd, 14 + lea r6d, [hq+wq-(1<<16)] + mov r4, srcq +.hv_w8_loop0: + movu m4, [srcq+ssq*0] ; 0 = _ _ + movu m5, [srcq+ssq*1] ; 1 = _ _ +%if ARCH_X86_32 + lea srcq, [srcq+ssq*2] +%endif +%macro HV_H_W8 4-7 ; src/dst, tmp[1-3], shuf[1-3] + %if ARCH_X86_32 + pshufb %3, %1, [base+subpel_h_shufB] + pshufb %4, %1, [base+subpel_h_shufC] + pshufb %1, [base+subpel_h_shufA] + %else + pshufb %3, %1, %6 ; subpel_h_shufB + pshufb %4, %1, %7 ; subpel_h_shufC + pshufb %1, %5 ; subpel_h_shufA + %endif + pmaddubsw %2, %3, subpelh0 ; subpel +0 C0 + pmaddubsw %4, subpelh1; subpel +4 B4 + pmaddubsw %3, subpelh1; C4 + pmaddubsw %1, subpelh0; A0 + paddw %2, %4 ; C0+B4 + paddw %1, %3 ; A0+C4 + phaddw %1, %2 +%endmacro +%if ARCH_X86_64 + mova m7, [base+subpel_h_shufA] + mova m8, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] +%endif + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 ; 0 ~ ~ ~ + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 ; 1 ~ ~ ~ +%if ARCH_X86_32 + movu m6, [srcq+ssq*0] ; 2 = _ _ + movu m0, [srcq+ssq*1] ; 3 = _ _ + lea srcq, [srcq+ssq*2] +%else + movu m6, [srcq+ssq*2] ; 2 = _ _ + add srcq, ss3q + movu m0, [srcq+ssq*0] ; 3 = _ _ +%endif + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 ; 2 ~ ~ ~ + HV_H_W8 m0, m1, m2, m3, m7, m8, m9 ; 3 ~ ~ ~ + mova m7, [base+pw_8192] + pmulhrsw m4, m7 ; H pw_8192 + pmulhrsw m5, m7 ; H pw_8192 + pmulhrsw m6, m7 ; H pw_8192 + pmulhrsw m0, m7 ; H pw_8192 + punpcklwd m1, m4, m5 ; 0 1 ~ + punpcklwd m2, m5, m6 ; 1 2 ~ + punpcklwd m3, m6, m0 ; 2 3 ~ + SAVELINE_W8 1, m1 + SAVELINE_W8 2, m2 + SAVELINE_W8 3, m3 + mova m7, [base+subpel_h_shufA] +%if ARCH_X86_32 + movu m4, [srcq+ssq*0] ; 4 = _ _ + movu m5, [srcq+ssq*1] ; 5 = _ _ + lea srcq, [srcq+ssq*2] +%else + movu m4, [srcq+ssq*1] ; 4 = _ _ + movu m5, [srcq+ssq*2] ; 5 = _ _ + add srcq, ss3q +%endif + movu m6, [srcq+ssq*0] ; 6 = _ _ + HV_H_W8 m4, m1, m2, m3, m7, m8, m9 ; 4 ~ ~ ~ + HV_H_W8 m5, m1, m2, m3, m7, m8, m9 ; 5 ~ ~ ~ + HV_H_W8 m6, m1, m2, m3, m7, m8, m9 ; 6 ~ ~ ~ + mova m7, [base+pw_8192] + pmulhrsw m1, m4, m7 ; H pw_8192 4 ~ + pmulhrsw m2, m5, m7 ; H pw_8192 5 ~ + pmulhrsw m3, m6, m7 ; H pw_8192 6 ~ + punpcklwd m4, m0, m1 ; 3 4 ~ + punpcklwd m5, m1, m2 ; 4 5 ~ + punpcklwd m6, m2, m3 ; 5 6 ~ + SAVELINE_W8 6, m3 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 +.hv_w8_loop: + ; m8 accu for V a + ; m9 accu for V b + SAVELINE_W8 1, m3 + SAVELINE_W8 2, m4 + SAVELINE_W8 3, m5 + SAVELINE_W8 4, m6 +%if ARCH_X86_32 + pmaddwd m0, m1, subpelv0 ; a0 + pmaddwd m7, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m0, m3 + paddd m7, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m0, m5 + paddd m7, m6 + mova m5, [base+pd_512] + paddd m0, m5 ; pd_512 + paddd m7, m5 ; pd_512 + mova accuv0, m0 + mova accuv1, m7 +%else + pmaddwd m8, m1, subpelv0 ; a0 + pmaddwd m9, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m8, m3 + paddd m9, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m8, m5 + paddd m9, m6 + mova m7, [base+pd_512] + paddd m8, m7 ; pd_512 + paddd m9, m7 ; pd_512 + mova m7, [base+subpel_h_shufB] + mova m6, [base+subpel_h_shufC] + mova m5, [base+subpel_h_shufA] +%endif + movu m0, [srcq+ssq*1] ; 7 + movu m4, [srcq+ssq*2] ; 8 + lea srcq, [srcq+ssq*2] + HV_H_W8 m0, m1, m2, m3, m5, m7, m6 + HV_H_W8 m4, m1, m2, m3, m5, m7, m6 + mova m5, [base+pw_8192] + pmulhrsw m0, m5 ; H pw_8192 + pmulhrsw m4, m5 ; H pw_8192 + RESTORELINE_W8 6, m6 + punpcklwd m5, m6, m0 ; 6 7 ~ + punpcklwd m6, m0, m4 ; 7 8 ~ + pmaddwd m1, m5, subpelv3 ; a3 + paddd m2, m1, accuv0 + pmaddwd m1, m6, subpelv3 ; b3 + paddd m1, m1, accuv1 ; H + V + psrad m2, 10 + psrad m1, 10 + packssdw m2, m1 ; d -> w + packuswb m2, m1 ; w -> b + movd [dstq+dsq*0], m2 + psrlq m2, 32 +%if ARCH_X86_32 + add dstq, dsm + movd [dstq+dsq*0], m2 + add dstq, dsm +%else + movd [dstq+dsq*1], m2 + lea dstq, [dstq+dsq*2] +%endif + sub hd, 2 + jle .hv_w8_outer + SAVELINE_W8 6, m4 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 + RESTORELINE_W8 4, m4 + jmp .hv_w8_loop +.hv_w8_outer: +%if ARCH_X86_32 + mov dstq, dstm + add r4, 4 + movzx hd, r6w + add dstq, 4 + mov srcq, r4 + mov dstm, dstq +%else + add r4, 4 + add r7, 4 + movzx hd, r6b + mov srcq, r4 + mov dstq, r7 +%endif + sub r6d, 1<<16 + jg .hv_w8_loop0 + RET + +%macro PSHUFB_SUBPEL_H_4 5 ; dst/src1, src2/mask, tmp1, tmp2, reset_mask + %if cpuflag(ssse3) + pshufb %1, %2 + %else + %if %5 == 1 + pcmpeqd %2, %2 + psrlq %2, 32 + %endif + psrldq %3, %1, 1 + pshufd %3, %3, q2301 + pand %1, %2 + pandn %4, %2, %3 + por %1, %4 + %endif +%endmacro + +%macro PSHUFB_SUBPEL_H_4a 6 ; dst, src1, src2/mask, tmp1, tmp2, reset_mask + %ifnidn %1, %2 + mova %1, %2 + %endif + PSHUFB_SUBPEL_H_4 %1, %3, %4, %5, %6 +%endmacro + +%macro PSHUFB_SUBPEL_H_4b 6 ; dst, src1, src2/mask, tmp1, tmp2, reset_mask + %if notcpuflag(ssse3) + psrlq %1, %2, 16 + %elifnidn %1, %2 + mova %1, %2 + %endif + PSHUFB_SUBPEL_H_4 %1, %3, %4, %5, %6 +%endmacro + +%macro PALIGNR 4-5 ; dst, src1, src2, shift[, tmp] + %if cpuflag(ssse3) + palignr %1, %2, %3, %4 + %else + %if %0 == 4 + %assign %%i regnumof%+%1 + 1 + %define %%tmp m %+ %%i + %else + %define %%tmp %5 + %endif + psrldq %1, %3, %4 + pslldq %%tmp, %2, 16-%4 + por %1, %%tmp + %endif +%endmacro + +%macro PHADDW 4 ; dst, src, pw_1/tmp, load_pw_1 + %if cpuflag(ssse3) + phaddw %1, %2 + %elifnidn %1, %2 + %if %4 == 1 + mova %3, [base+pw_1] + %endif + pmaddwd %1, %3 + pmaddwd %2, %3 + packssdw %1, %2 + %else + %if %4 == 1 + pmaddwd %1, [base+pw_1] + %else + pmaddwd %1, %3 + %endif + packssdw %1, %1 + %endif +%endmacro + +%macro PMULHRSW_POW2 4 ; dst, src1, src2, shift + %if cpuflag(ssse3) + pmulhrsw %1, %2, %3 + %else + paddw %1, %2, %3 + psraw %1, %4 + %endif +%endmacro + +%macro PMULHRSW_8192 3 ; dst, src1, src2 + PMULHRSW_POW2 %1, %2, %3, 2 +%endmacro + +%macro PREP_8TAP_H_LOAD4 5 ; dst, src_memloc, tmp[1-2] + movd %1, [%2+0] + movd %3, [%2+1] + movd %4, [%2+2] + movd %5, [%2+3] + punpckldq %1, %3 + punpckldq %4, %5 + punpcklqdq %1, %4 +%endmacro + +%macro PREP_8TAP_H_LOAD 2 ; dst0, src_memloc + %if cpuflag(ssse3) + movu m%1, [%2] + pshufb m2, m%1, m11 ; subpel_h_shufB + pshufb m3, m%1, m9 ; subpel_h_shufC + pshufb m%1, m10 ; subpel_h_shufA + %else + %if ARCH_X86_64 + SWAP m12, m5 + SWAP m13, m6 + SWAP m14, m7 + %define %%mx0 m%+%%i + %define %%mx1 m%+%%j + %assign %%i 0 + %rep 12 + movd %%mx0, [%2+%%i] + %assign %%i %%i+1 + %endrep + %assign %%i 0 + %rep 6 + %assign %%j %%i+1 + punpckldq %%mx0, %%mx1 + %assign %%i %%i+2 + %endrep + %assign %%i 0 + %rep 3 + %assign %%j %%i+2 + punpcklqdq %%mx0, %%mx1 + %assign %%i %%i+4 + %endrep + SWAP m%1, m0 + SWAP m2, m4 + SWAP m3, m8 + SWAP m5, m12 + SWAP m6, m13 + SWAP m7, m14 + %else + PREP_8TAP_H_LOAD4 m0, %2+0, m1, m4, m7 + PREP_8TAP_H_LOAD4 m2, %2+4, m1, m4, m7 + PREP_8TAP_H_LOAD4 m3, %2+8, m1, m4, m7 + SWAP m%1, m0 + %endif + %endif +%endmacro + +%macro PREP_8TAP_H 2 ; dst, src_memloc + PREP_8TAP_H_LOAD %1, %2 + %if ARCH_X86_64 && notcpuflag(ssse3) + SWAP m8, m1 + SWAP m9, m7 + %endif + %xdefine mX m%+%1 + %assign %%i regnumof%+mX + %define mX m%+%%i + mova m4, m2 + PMADDUBSW m4, m5, m1, m7, 1 ; subpel +0 B0 + PMADDUBSW m2, m6, m1, m7, 0 ; subpel +4 B4 + PMADDUBSW m3, m6, m1, m7, 0 ; subpel +4 C4 + PMADDUBSW mX, m5, m1, m7, 0 ; subpel +0 A0 + %undef mX + %if ARCH_X86_64 && notcpuflag(ssse3) + SWAP m1, m8 + SWAP m7, m9 + %endif + paddw m3, m4 + paddw m%1, m2 + PHADDW m%1, m3, m15, ARCH_X86_32 + %if ARCH_X86_64 || cpuflag(ssse3) + PMULHRSW_8192 m%1, m%1, m7 + %else + PMULHRSW_8192 m%1, m%1, [base+pw_2] + %endif +%endmacro + +%macro PREP_8TAP_HV 4 ; dst, src_memloc, tmp[1-2] + %if cpuflag(ssse3) + movu %1, [%2] + pshufb m2, %1, shufB + pshufb m3, %1, shufC + pshufb %1, shufA + %else + PREP_8TAP_H_LOAD4 %1, %2+0, m1, %3, %4 + PREP_8TAP_H_LOAD4 m2, %2+4, m1, %3, %4 + PREP_8TAP_H_LOAD4 m3, %2+8, m1, %3, %4 + %endif + mova m1, m2 + PMADDUBSW m1, subpelh0, %3, %4, 1 ; subpel +0 C0 + PMADDUBSW m3, subpelh1, %3, %4, 0 ; subpel +4 B4 + PMADDUBSW m2, subpelh1, %3, %4, 0 ; C4 + PMADDUBSW %1, subpelh0, %3, %4, 0 ; A0 + paddw m1, m3 ; C0+B4 + paddw %1, m2 ; A0+C4 + PHADDW %1, m1, %3, 1 +%endmacro + +%macro PREP_8TAP 0 +%if ARCH_X86_32 + DECLARE_REG_TMP 1, 2 +%elif WIN64 + DECLARE_REG_TMP 6, 4 +%else + DECLARE_REG_TMP 6, 7 +%endif + +FN prep_8tap, sharp, SHARP, SHARP +FN prep_8tap, sharp_smooth, SHARP, SMOOTH +FN prep_8tap, smooth_sharp, SMOOTH, SHARP +FN prep_8tap, smooth, SMOOTH, SMOOTH +FN prep_8tap, sharp_regular, SHARP, REGULAR +FN prep_8tap, regular_sharp, REGULAR, SHARP +FN prep_8tap, smooth_regular, SMOOTH, REGULAR +FN prep_8tap, regular_smooth, REGULAR, SMOOTH +FN prep_8tap, regular, REGULAR, REGULAR + +%if ARCH_X86_32 + %define base_reg r2 + %define base base_reg-prep%+SUFFIX +%else + %define base_reg r7 + %define base 0 +%endif +cglobal prep_8tap_8bpc, 1, 9, 0, tmp, src, stride, w, h, mx, my, stride3 +%assign org_stack_offset stack_offset + imul mxd, mxm, 0x010101 + add mxd, t0d ; 8tap_h, mx, 4tap_h + imul myd, mym, 0x010101 + add myd, t1d ; 8tap_v, my, 4tap_v + mov wd, wm + movifnidn srcd, srcm + movifnidn hd, hm + test mxd, 0xf00 + jnz .h + test myd, 0xf00 + jnz .v + LEA base_reg, prep_ssse3 + tzcnt wd, wd + movzx wd, word [base_reg-prep_ssse3+prep_ssse3_table+wq*2] + pxor m4, m4 + add wq, base_reg + movifnidn strided, stridem + lea r6, [strideq*3] + %assign stack_offset org_stack_offset +%if WIN64 + pop r8 + pop r7 +%endif + jmp wq +.h: + LEA base_reg, prep%+SUFFIX + test myd, 0xf00 + jnz .hv +%if cpuflag(ssse3) + WIN64_SPILL_XMM 12 +%else + WIN64_SPILL_XMM 16 +%endif +%if ARCH_X86_32 + %define strideq r6 + mov strideq, stridem +%endif + cmp wd, 4 + je .h_w4 + tzcnt wd, wd +%if cpuflag(ssse3) + %if ARCH_X86_64 + mova m10, [base+subpel_h_shufA] + mova m11, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] + %else + %define m10 [base+subpel_h_shufA] + %define m11 [base+subpel_h_shufB] + %define m9 [base+subpel_h_shufC] + %endif +%endif + shr mxd, 16 + sub srcq, 3 + movzx wd, word [base_reg+wq*2+table_offset(prep, _8tap_h)] + movq m6, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] +%if cpuflag(ssse3) + mova m7, [base+pw_8192] + pshufd m5, m6, q0000 + pshufd m6, m6, q1111 +%else + punpcklbw m6, m6 + psraw m6, 8 + %if ARCH_X86_64 + mova m7, [pw_2] + mova m15, [pw_1] + %else + %define m15 m4 + %endif + pshufd m5, m6, q1010 + punpckhqdq m6, m6 +%endif + add wq, base_reg + jmp wq +.h_w4: +%if ARCH_X86_32 + and mxd, 0x7f +%else + movzx mxd, mxb +%endif + dec srcq + movd m4, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX+2] +%if cpuflag(ssse3) + mova m6, [base+pw_8192] + mova m5, [base+subpel_h_shufA] + pshufd m4, m4, q0000 +%else + mova m6, [base+pw_2] + %if ARCH_X86_64 + mova m14, [pw_1] + %else + %define m14 m7 + %endif + punpcklbw m4, m4 + psraw m4, 8 + punpcklqdq m4, m4 +%endif +%if ARCH_X86_64 + lea stride3q, [strideq*3] +%endif +.h_w4_loop: +%if cpuflag(ssse3) + movq m0, [srcq+strideq*0] ; 0 + movq m1, [srcq+strideq*1] ; 1 + %if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m2, [srcq+strideq*0] ; 2 + movq m3, [srcq+strideq*1] ; 3 + lea srcq, [srcq+strideq*2] + %else + movq m2, [srcq+strideq*2] ; 2 + movq m3, [srcq+stride3q ] ; 3 + lea srcq, [srcq+strideq*4] + %endif + pshufb m0, m5 + pshufb m1, m5 + pshufb m2, m5 + pshufb m3, m5 +%elif ARCH_X86_64 + movd m0, [srcq+strideq*0+0] + movd m12, [srcq+strideq*0+1] + movd m1, [srcq+strideq*1+0] + movd m5, [srcq+strideq*1+1] + movd m2, [srcq+strideq*2+0] + movd m13, [srcq+strideq*2+1] + movd m3, [srcq+stride3q +0] + movd m7, [srcq+stride3q +1] + punpckldq m0, m12 + punpckldq m1, m5 + punpckldq m2, m13 + punpckldq m3, m7 + movd m12, [srcq+strideq*0+2] + movd m8, [srcq+strideq*0+3] + movd m5, [srcq+strideq*1+2] + movd m9, [srcq+strideq*1+3] + movd m13, [srcq+strideq*2+2] + movd m10, [srcq+strideq*2+3] + movd m7, [srcq+stride3q +2] + movd m11, [srcq+stride3q +3] + lea srcq, [srcq+strideq*4] + punpckldq m12, m8 + punpckldq m5, m9 + punpckldq m13, m10 + punpckldq m7, m11 + punpcklqdq m0, m12 ; 0 + punpcklqdq m1, m5 ; 1 + punpcklqdq m2, m13 ; 2 + punpcklqdq m3, m7 ; 3 +%else + movd m0, [srcq+strideq*0+0] + movd m1, [srcq+strideq*0+1] + movd m2, [srcq+strideq*0+2] + movd m3, [srcq+strideq*0+3] + punpckldq m0, m1 + punpckldq m2, m3 + punpcklqdq m0, m2 ; 0 + movd m1, [srcq+strideq*1+0] + movd m2, [srcq+strideq*1+1] + movd m3, [srcq+strideq*1+2] + movd m7, [srcq+strideq*1+3] + lea srcq, [srcq+strideq*2] + punpckldq m1, m2 + punpckldq m3, m7 + punpcklqdq m1, m3 ; 1 + movd m2, [srcq+strideq*0+0] + movd m3, [srcq+strideq*0+1] + movd m7, [srcq+strideq*0+2] + movd m5, [srcq+strideq*0+3] + punpckldq m2, m3 + punpckldq m7, m5 + punpcklqdq m2, m7 ; 2 + movd m3, [srcq+strideq*1+0] + movd m7, [srcq+strideq*1+1] + punpckldq m3, m7 + movd m7, [srcq+strideq*1+2] + movd m5, [srcq+strideq*1+3] + lea srcq, [srcq+strideq*2] + punpckldq m7, m5 + punpcklqdq m3, m7 ; 3 +%endif + PMADDUBSW m0, m4, m5, m7, 1 ; subpel_filters + 2 + PMADDUBSW m1, m4, m5, m7, 0 + PMADDUBSW m2, m4, m5, m7, 0 + PMADDUBSW m3, m4, m5, m7, 0 + PHADDW m0, m1, m14, ARCH_X86_32 + PHADDW m2, m3, m14, 0 + PMULHRSW_8192 m0, m0, m6 + PMULHRSW_8192 m2, m2, m6 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m2 + add tmpq, 32 + sub hd, 4 + jg .h_w4_loop + RET +.h_w8: +%if cpuflag(ssse3) + PREP_8TAP_H 0, srcq+strideq*0 + PREP_8TAP_H 1, srcq+strideq*1 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + lea srcq, [srcq+strideq*2] + add tmpq, 32 + sub hd, 2 +%else + PREP_8TAP_H 0, srcq + mova [tmpq], m0 + add srcq, strideq + add tmpq, 16 + dec hd +%endif + jg .h_w8 + RET +.h_w16: + mov r3, -16*1 + jmp .h_start +.h_w32: + mov r3, -16*2 + jmp .h_start +.h_w64: + mov r3, -16*4 + jmp .h_start +.h_w128: + mov r3, -16*8 +.h_start: + sub srcq, r3 + mov r5, r3 +.h_loop: +%if cpuflag(ssse3) + PREP_8TAP_H 0, srcq+r3+8*0 + PREP_8TAP_H 1, srcq+r3+8*1 + mova [tmpq+16*0], m0 + mova [tmpq+16*1], m1 + add tmpq, 32 + add r3, 16 +%else + PREP_8TAP_H 0, srcq+r3 + mova [tmpq], m0 + add tmpq, 16 + add r3, 8 +%endif + jl .h_loop + add srcq, strideq + mov r3, r5 + dec hd + jg .h_loop + RET +.v: + LEA base_reg, prep%+SUFFIX +%if ARCH_X86_32 + mov mxd, myd + and mxd, 0x7f +%else + %assign stack_offset org_stack_offset + WIN64_SPILL_XMM 16 + movzx mxd, myb +%endif + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] +%if cpuflag(ssse3) + mova m2, [base+pw_512] + mova m7, [base+pw_8192] + punpcklwd m0, m0 +%else + punpcklbw m0, m0 + psraw m0, 8 +%endif +%if ARCH_X86_32 + %define subpel0 [rsp+mmsize*0] + %define subpel1 [rsp+mmsize*1] + %define subpel2 [rsp+mmsize*2] + %define subpel3 [rsp+mmsize*3] +%assign regs_used 6 ; use r5 (mx) as tmp for stack alignment if needed + %if cpuflag(ssse3) + ALLOC_STACK -mmsize*4 + %else + ALLOC_STACK -mmsize*5 + %endif +%assign regs_used 7 + mov strideq, [rstk+stack_offset+gprsize*3] + pshufd m1, m0, q0000 + mova subpel0, m1 + pshufd m1, m0, q1111 + mova subpel1, m1 + lea r5, [strideq*3] + pshufd m1, m0, q2222 + mova subpel2, m1 + pshufd m1, m0, q3333 + mova subpel3, m1 + sub srcq, r5 +%else + %define subpel0 m8 + %define subpel1 m9 + %define subpel2 m10 + %define subpel3 m11 + pshufd m8, m0, q0000 + pshufd m9, m0, q1111 + lea stride3q, [strideq*3] + pshufd m10, m0, q2222 + pshufd m11, m0, q3333 + sub srcq, stride3q + cmp wd, 8 + jns .v_w8 +%endif +.v_w4: +%if notcpuflag(ssse3) + pxor m6, m6 + %if ARCH_X86_64 + mova m7, [base+pw_2] + %endif +%endif +%if ARCH_X86_32 + %if STACK_ALIGNMENT < mmsize + %define srcm [esp+stack_size+gprsize*1] + %define tmpm [esp+stack_size+gprsize*2] + %endif + mov tmpm, tmpq + mov srcm, srcq + lea r5d, [wq - 4] ; horizontal loop + shl r5d, (16 - 2) ; (wq / 4) << 16 + mov r5w, hw +.v_w4_loop0: +%endif + movd m1, [srcq+strideq*0] + movd m0, [srcq+strideq*1] +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movd m2, [srcq+strideq*0] + movd m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + movd m3, [srcq+strideq*0] + movd m5, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] +%else + movd m2, [srcq+strideq*2] + add srcq, stride3q + movd m4, [srcq+strideq*0] + movd m3, [srcq+strideq*1] + movd m5, [srcq+strideq*2] + add srcq, stride3q +%endif + punpckldq m1, m0 ; 0 1 + punpckldq m0, m2 ; 1 2 + punpcklbw m1, m0 ; 01 12 + movd m0, [srcq+strideq*0] + punpckldq m2, m4 ; 2 3 + punpckldq m4, m3 ; 3 4 + punpckldq m3, m5 ; 4 5 + punpckldq m5, m0 ; 5 6 + punpcklbw m2, m4 ; 23 34 + punpcklbw m3, m5 ; 45 56 +.v_w4_loop: +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel0 + %define subpel0 m7 +%endif + mova m5, m1 + PMADDUBSW m5, subpel0, m6, m4, 0 ; a0 b0 +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel1 + %define subpel1 m7 +%endif + mova m1, m2 + PMADDUBSW m2, subpel1, m6, m4, 0 ; a1 b1 + paddw m5, m2 +%if ARCH_X86_32 && notcpuflag(ssse3) + mova m7, subpel2 + %define subpel2 m7 +%endif + mova m2, m3 + PMADDUBSW m3, subpel2, m6, m4, 0 ; a2 b2 + movd m4, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] + paddw m5, m3 + punpckldq m3, m0, m4 ; 6 7 _ _ + movd m0, [srcq+strideq*0] + punpckldq m4, m0 ; 7 8 _ _ + punpcklbw m3, m4 ; 67 78 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m12, m0 + %else + mova [esp+mmsize*4], m0 + mova m7, subpel3 + %define subpel3 m7 + %endif +%endif + mova m4, m3 + PMADDUBSW m4, subpel3, m6, m0, 0 ; a3 b3 + paddw m5, m4 +%if ARCH_X86_64 || cpuflag(ssse3) + %if notcpuflag(ssse3) + SWAP m0, m12 + %endif + PMULHRSW_8192 m5, m5, m7 +%else + mova m0, [esp+mmsize*4] + PMULHRSW_8192 m5, m5, [base+pw_2] +%endif + movq [tmpq+wq*0], m5 + movhps [tmpq+wq*2], m5 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w4_loop +%if ARCH_X86_32 + mov srcq, srcm + mov tmpq, tmpm + movzx hd, r5w + add srcq, 4 + add tmpq, 8 + mov srcm, srcq + mov tmpm, tmpq + sub r5d, 1<<16 ; horizontal-- + jg .v_w4_loop0 +%endif + RET +%if ARCH_X86_64 +.v_w8: + lea r6d, [wq*8-64] + mov r5, srcq + mov r8, tmpq + lea r6d, [hq+r6*4] +.v_w8_loop0: + movq m1, [srcq+strideq*0] + movq m2, [srcq+strideq*1] + movq m3, [srcq+strideq*2] + add srcq, stride3q + movq m4, [srcq+strideq*0] + movq m5, [srcq+strideq*1] + movq m6, [srcq+strideq*2] + add srcq, stride3q + movq m0, [srcq+strideq*0] + punpcklbw m1, m2 ; 01 + punpcklbw m2, m3 ; 12 + punpcklbw m3, m4 ; 23 + punpcklbw m4, m5 ; 34 + punpcklbw m5, m6 ; 45 + punpcklbw m6, m0 ; 56 +.v_w8_loop: + movq m13, [srcq+strideq*1] + lea srcq, [srcq+strideq*2] +%if cpuflag(ssse3) + pmaddubsw m14, m1, subpel0 ; a0 + pmaddubsw m15, m2, subpel0 ; b0 + mova m1, m3 + mova m2, m4 + pmaddubsw m3, subpel1 ; a1 + pmaddubsw m4, subpel1 ; b1 + paddw m14, m3 + paddw m15, m4 + mova m3, m5 + mova m4, m6 + pmaddubsw m5, subpel2 ; a2 + pmaddubsw m6, subpel2 ; b2 + punpcklbw m12, m0, m13 ; 67 + movq m0, [srcq+strideq*0] + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + pmaddubsw m12, subpel3 ; a3 + paddw m15, m6 + mova m6, m13 + pmaddubsw m13, subpel3 ; b3 + paddw m14, m12 + paddw m15, m13 + pmulhrsw m14, m7 + pmulhrsw m15, m7 +%else + mova m14, m1 + PMADDUBSW m14, subpel0, m7, m12, 1 ; a0 + mova m15, m2 + PMADDUBSW m15, subpel0, m7, m12, 0 ; b0 + mova m1, m3 + PMADDUBSW m3, subpel1, m7, m12, 0 ; a1 + mova m2, m4 + PMADDUBSW m4, subpel1, m7, m12, 0 ; b1 + paddw m14, m3 + mova m3, m5 + PMADDUBSW m5, subpel2, m7, m12, 0 ; a2 + paddw m15, m4 + mova m4, m6 + PMADDUBSW m6, subpel2, m7, m12, 0 ; b2 + paddw m15, m6 + punpcklbw m12, m0, m13 ; 67 + movq m0, [srcq+strideq*0] + punpcklbw m13, m0 ; 78 + paddw m14, m5 + mova m5, m12 + PMADDUBSW m12, subpel3, m7, m6, 0 ; a3 + paddw m14, m12 + mova m6, m13 + PMADDUBSW m13, subpel3, m7, m12, 0 ; b3 + paddw m15, m13 + PMULHRSW_8192 m14, m14, [base+pw_2] + PMULHRSW_8192 m15, m15, [base+pw_2] +%endif + movu [tmpq+wq*0], m14 + movu [tmpq+wq*2], m15 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jg .v_w8_loop + add r5, 8 + add r8, 16 + movzx hd, r6b + mov srcq, r5 + mov tmpq, r8 + sub r6d, 1<<8 + jg .v_w8_loop0 + RET +%endif ;ARCH_X86_64 +%undef subpel0 +%undef subpel1 +%undef subpel2 +%undef subpel3 +.hv: + %assign stack_offset org_stack_offset + cmp wd, 4 + jg .hv_w8 + and mxd, 0x7f + movd m1, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX+2] +%if ARCH_X86_32 + mov mxd, myd + shr myd, 16 + and mxd, 0x7f + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + mov strideq, stridem + %assign regs_used 6 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + lea r5, [strideq*3+1] + sub srcq, r5 + %define subpelv0 [rsp+mmsize*0] + %define subpelv1 [rsp+mmsize*1] + %define subpelv2 [rsp+mmsize*2] + %define subpelv3 [rsp+mmsize*3] + punpcklbw m0, m0 + psraw m0, 8 + pshufd m6, m0, q0000 + mova subpelv0, m6 + pshufd m6, m0, q1111 + mova subpelv1, m6 + pshufd m6, m0, q2222 + mova subpelv2, m6 + pshufd m6, m0, q3333 + mova subpelv3, m6 +%else + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m0, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + %if cpuflag(ssse3) + ALLOC_STACK mmsize*14, 14 + %else + ALLOC_STACK mmsize*14, 16 + %endif + lea stride3q, [strideq*3] + sub srcq, stride3q + dec srcq + %define subpelv0 m10 + %define subpelv1 m11 + %define subpelv2 m12 + %define subpelv3 m13 + punpcklbw m0, m0 + psraw m0, 8 + %if cpuflag(ssse3) + mova m8, [base+pw_8192] + %else + mova m8, [base+pw_2] + %endif + mova m9, [base+pd_32] + pshufd m10, m0, q0000 + pshufd m11, m0, q1111 + pshufd m12, m0, q2222 + pshufd m13, m0, q3333 +%endif + pshufd m7, m1, q0000 +%if notcpuflag(ssse3) + punpcklbw m7, m7 + psraw m7, 8 +%endif +%define hv4_line_0_0 4 +%define hv4_line_0_1 5 +%define hv4_line_0_2 6 +%define hv4_line_0_3 7 +%define hv4_line_0_4 8 +%define hv4_line_0_5 9 +%define hv4_line_1_0 10 +%define hv4_line_1_1 11 +%define hv4_line_1_2 12 +%define hv4_line_1_3 13 +%if ARCH_X86_32 + %if cpuflag(ssse3) + %define w8192reg [base+pw_8192] + %else + %define w8192reg [base+pw_2] + %endif + %define d32reg [base+pd_32] +%else + %define w8192reg m8 + %define d32reg m9 +%endif + ; lower shuffle 0 1 2 3 4 +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%else + %if ARCH_X86_64 + mova m15, [pw_1] + %else + %define m15 m1 + %endif +%endif + movq m5, [srcq+strideq*0] ; 0 _ _ _ + movhps m5, [srcq+strideq*1] ; 0 _ 1 _ +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m4, [srcq+strideq*0] ; 2 _ _ _ + movhps m4, [srcq+strideq*1] ; 2 _ 3 _ + lea srcq, [srcq+strideq*2] +%else + movq m4, [srcq+strideq*2] ; 2 _ _ _ + movhps m4, [srcq+stride3q ] ; 2 _ 3 _ + lea srcq, [srcq+strideq*4] +%endif + PSHUFB_SUBPEL_H_4a m2, m5, m6, m1, m3, 1 ;H subpel_h_shuf4 0~1~ + PSHUFB_SUBPEL_H_4a m0, m4, m6, m1, m3, 0 ;H subpel_h_shuf4 2~3~ + PMADDUBSW m2, m7, m1, m3, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m3, 0 ;H subpel_filters + PHADDW m2, m0, m15, ARCH_X86_32 ;H 0 1 2 3 + PMULHRSW_8192 m2, m2, w8192reg + SAVELINE_W4 m2, 2, 0 + ; upper shuffle 2 3 4 5 6 +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + PSHUFB_SUBPEL_H_4b m2, m5, m6, m1, m3, 0 ;H subpel_h_shuf4 0~1~ + PSHUFB_SUBPEL_H_4b m0, m4, m6, m1, m3, 0 ;H subpel_h_shuf4 2~3~ + PMADDUBSW m2, m7, m1, m3, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m3, 0 ;H subpel_filters + PHADDW m2, m0, m15, ARCH_X86_32 ;H 0 1 2 3 + PMULHRSW_8192 m2, m2, w8192reg +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m2 + %else + mova [esp+mmsize*4], m2 + %endif +%endif + ; lower shuffle +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%endif + movq m5, [srcq+strideq*0] ; 4 _ _ _ + movhps m5, [srcq+strideq*1] ; 4 _ 5 _ +%if ARCH_X86_32 + lea srcq, [srcq+strideq*2] + movq m4, [srcq+strideq*0] ; 6 _ _ _ + add srcq, strideq +%else + movq m4, [srcq+strideq*2] ; 6 _ _ _ + add srcq, stride3q +%endif + PSHUFB_SUBPEL_H_4a m3, m5, m6, m1, m2, 0 ;H subpel_h_shuf4 4~5~ + PSHUFB_SUBPEL_H_4a m0, m4, m6, m1, m2, 0 ;H subpel_h_shuf4 6~6~ + PMADDUBSW m3, m7, m1, m2, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m2, 0 ;H subpel_filters + PHADDW m3, m0, m15, ARCH_X86_32 ;H 4 5 6 7 + PMULHRSW_8192 m3, m3, w8192reg + SAVELINE_W4 m3, 3, 0 + ; upper shuffle +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + PSHUFB_SUBPEL_H_4b m3, m5, m6, m1, m2, 0 ;H subpel_h_shuf4 4~5~ + PSHUFB_SUBPEL_H_4b m0, m4, m6, m1, m2, 0 ;H subpel_h_shuf4 6~6~ + PMADDUBSW m3, m7, m1, m2, 1 ;H subpel_filters + PMADDUBSW m0, m7, m1, m2, 0 ;H subpel_filters + PHADDW m3, m0, m15, ARCH_X86_32 ;H 4 5 6 7 + PMULHRSW_8192 m3, m3, w8192reg +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m2, m14 + %else + mova m2, [esp+mmsize*4] + %endif +%endif + ;process high + PALIGNR m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + ;process low + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + PALIGNR m4, m3, m2, 4;V 1 2 3 4 + punpcklwd m1, m2, m4 ; V 01 12 + punpckhwd m2, m4 ; V 23 34 + pshufd m0, m3, q2121;V 5 6 5 6 + punpcklwd m3, m0 ; V 45 56 +.hv_w4_loop: + ;process low + pmaddwd m5, m1, subpelv0 ; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m5 + %else + mova [esp+mmsize*4], m5 + %define m15 m3 + %endif +%endif +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4] +%endif + movq m4, [srcq+strideq*0] ; 7 + movhps m4, [srcq+strideq*1] ; 7 _ 8 _ + PSHUFB_SUBPEL_H_4a m4, m4, m6, m3, m5, 0 ; H subpel_h_shuf4 7~8~ + PMADDUBSW m4, m7, m3, m5, 1 ; H subpel_filters + PHADDW m4, m4, m15, ARCH_X86_32 ; H 7878 + PMULHRSW_8192 m4, m4, w8192reg + PALIGNR m3, m4, m0, 12, m5 ; 6787 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m5, m14 + %else + mova m5, [esp+mmsize*4] + %endif +%endif + paddd m5, d32reg ; pd_32 + paddd m5, m4 + psrad m5, 6 + SAVELINE_W4 m0, 0, 0 + SAVELINE_W4 m1, 1, 0 + SAVELINE_W4 m2, 2, 0 + SAVELINE_W4 m3, 3, 0 + SAVELINE_W4 m5, 5, 0 + ;process high + RESTORELINE_W4 m0, 0, 1 + RESTORELINE_W4 m1, 1, 1 + RESTORELINE_W4 m2, 2, 1 + RESTORELINE_W4 m3, 3, 1 + pmaddwd m5, m1, subpelv0; V a0 b0 + mova m1, m2 + pmaddwd m2, subpelv1; V a1 b1 + paddd m5, m2 + mova m2, m3 + pmaddwd m3, subpelv2; V a2 b2 + paddd m5, m3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m14, m5 + %else + mova [esp+0xA0], m5 + %endif +%endif +%if cpuflag(ssse3) + mova m6, [base+subpel_h_shuf4+16] +%endif + movq m4, [srcq+strideq*0] ; 7 + movhps m4, [srcq+strideq*1] ; 7 _ 8 _ + PSHUFB_SUBPEL_H_4b m4, m4, m6, m3, m5, 0 ; H subpel_h_shuf4 7~8~ + PMADDUBSW m4, m7, m3, m5, 1 ; H subpel_filters + PHADDW m4, m4, m15, ARCH_X86_32 ; H 7878 + PMULHRSW_8192 m4, m4, w8192reg + PALIGNR m3, m4, m0, 12, m5 ; 6787 + mova m0, m4 + punpcklwd m3, m4 ; 67 78 + pmaddwd m4, m3, subpelv3; a3 b3 +%if notcpuflag(ssse3) + %if ARCH_X86_64 + SWAP m5, m14 + %else + mova m5, [esp+0xA0] + %endif +%endif + paddd m5, d32reg ; pd_32 + paddd m5, m4 + psrad m4, m5, 6 + RESTORELINE_W4 m5, 5, 0 + packssdw m5, m4 + pshufd m5, m5, q3120 + movu [tmpq], m5 + lea srcq, [srcq+strideq*2] + add tmpq, 16 + sub hd, 2 + SAVELINE_W4 m0, 0, 1 + SAVELINE_W4 m1, 1, 1 + SAVELINE_W4 m2, 2, 1 + SAVELINE_W4 m3, 3, 1 + RESTORELINE_W4 m0, 0, 0 + RESTORELINE_W4 m1, 1, 0 + RESTORELINE_W4 m2, 2, 0 + RESTORELINE_W4 m3, 3, 0 + jg .hv_w4_loop + RET +%undef subpelv0 +%undef subpelv1 +%undef subpelv2 +%undef subpelv3 +.hv_w8: + %assign stack_offset org_stack_offset +%define hv8_line_1 0 +%define hv8_line_2 1 +%define hv8_line_3 2 +%define hv8_line_4 3 +%define hv8_line_6 4 + shr mxd, 16 +%if ARCH_X86_32 + %define subpelh0 [rsp+mmsize*5] + %define subpelh1 [rsp+mmsize*6] + %define subpelv0 [rsp+mmsize*7] + %define subpelv1 [rsp+mmsize*8] + %define subpelv2 [rsp+mmsize*9] + %define subpelv3 [rsp+mmsize*10] + %define accuv0 [rsp+mmsize*11] + %define accuv1 [rsp+mmsize*12] + movq m1, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] + mov mxd, myd + shr myd, 16 + and mxd, 0x7f + cmp hd, 6 + cmovs myd, mxd + movq m5, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + mov strideq, stridem + %assign regs_used 6 + ALLOC_STACK -mmsize*14 + %assign regs_used 7 + %if STACK_ALIGNMENT < mmsize + %define tmpm [rsp+mmsize*13+gprsize*1] + %define srcm [rsp+mmsize*13+gprsize*2] + %define stridem [rsp+mmsize*13+gprsize*3] + mov tmpm, tmpq + mov stridem, strideq + %endif + %if cpuflag(ssse3) + pshufd m0, m1, q0000 + pshufd m1, m1, q1111 + %else + punpcklbw m1, m1 + psraw m1, 8 + pshufd m0, m1, q1010 + punpckhqdq m1, m1 + %endif + punpcklbw m5, m5 + psraw m5, 8 + pshufd m2, m5, q0000 + pshufd m3, m5, q1111 + pshufd m4, m5, q2222 + pshufd m5, m5, q3333 + mova subpelh0, m0 + mova subpelh1, m1 + mova subpelv0, m2 + mova subpelv1, m3 + mova subpelv2, m4 + mova subpelv3, m5 + lea r5, [strideq*3+3] + sub srcq, r5 + mov srcm, srcq +%else + ALLOC_STACK mmsize*5, 16 + %define subpelh0 m10 + %define subpelh1 m11 + %define subpelv0 m12 + %define subpelv1 m13 + %define subpelv2 m14 + %define subpelv3 m15 + %define accuv0 m8 + %define accuv1 m9 + movq m0, [base_reg+mxq*8+subpel_filters-prep%+SUFFIX] + movzx mxd, myb + shr myd, 16 + cmp hd, 6 + cmovs myd, mxd + movq m1, [base_reg+myq*8+subpel_filters-prep%+SUFFIX] + %if cpuflag(ssse3) + pshufd subpelh0, m0, q0000 + pshufd subpelh1, m0, q1111 + %else + punpcklbw m0, m0 + psraw m0, 8 + pshufd subpelh0, m0, q1010 + pshufd subpelh1, m0, q3232 + mova m7, [base+pw_2] + %endif + punpcklbw m1, m1 + psraw m1, 8 + pshufd subpelv0, m1, q0000 + pshufd subpelv1, m1, q1111 + pshufd subpelv2, m1, q2222 + pshufd subpelv3, m1, q3333 + lea stride3q, [strideq*3] + sub srcq, 3 + sub srcq, stride3q + mov r6, srcq + mov r8, tmpq +%endif + lea r5d, [wq-4] + shl r5d, 14 + add r5d, hd +.hv_w8_loop0: +%if cpuflag(ssse3) + %if ARCH_X86_64 + mova m7, [base+subpel_h_shufA] + mova m8, [base+subpel_h_shufB] + mova m9, [base+subpel_h_shufC] + %define shufA m7 + %define shufB m8 + %define shufC m9 + %else + %define shufA [base+subpel_h_shufA] + %define shufB [base+subpel_h_shufB] + %define shufC [base+subpel_h_shufC] + %endif +%endif + PREP_8TAP_HV m4, srcq+strideq*0, m7, m0 + PREP_8TAP_HV m5, srcq+strideq*1, m7, m0 +%if ARCH_X86_64 + PREP_8TAP_HV m6, srcq+strideq*2, m7, m0 + add srcq, stride3q + PREP_8TAP_HV m0, srcq+strideq*0, m7, m9 +%else + lea srcq, [srcq+strideq*2] + %if notcpuflag(ssse3) + mova [esp], m4 + %endif + PREP_8TAP_HV m6, srcq+strideq*0, m7, m4 + PREP_8TAP_HV m0, srcq+strideq*1, m7, m4 + lea srcq, [srcq+strideq*2] +%endif +%if cpuflag(ssse3) + mova m7, [base+pw_8192] +%else + mova m7, [base+pw_2] + %if ARCH_X86_32 + mova m4, [esp] + %endif +%endif + PMULHRSW_8192 m4, m4, m7 + PMULHRSW_8192 m5, m5, m7 + PMULHRSW_8192 m6, m6, m7 + PMULHRSW_8192 m0, m0, m7 + punpcklwd m1, m4, m5 ; 01 + punpcklwd m2, m5, m6 ; 12 + punpcklwd m3, m6, m0 ; 23 + SAVELINE_W8 1, m1 + SAVELINE_W8 2, m2 + SAVELINE_W8 3, m3 +%if cpuflag(ssse3) + mova m7, [base+subpel_h_shufA] +%endif +%if ARCH_X86_64 + PREP_8TAP_HV m4, srcq+strideq*1, m8, m9 + PREP_8TAP_HV m5, srcq+strideq*2, m8, m9 + add srcq, stride3q + PREP_8TAP_HV m6, srcq+strideq*0, m8, m9 +%else + %if notcpuflag(ssse3) + mova [esp+0x30], m0 + %endif + PREP_8TAP_HV m4, srcq+strideq*0, m7, m0 + PREP_8TAP_HV m5, srcq+strideq*1, m7, m0 + lea srcq, [srcq+strideq*2] + PREP_8TAP_HV m6, srcq+strideq*0, m7, m0 +%endif +%if cpuflag(ssse3) + mova m7, [base+pw_8192] +%elif ARCH_X86_32 + mova m0, [esp+0x30] + mova m7, [base+pw_2] +%endif + PMULHRSW_8192 m1, m4, m7 + PMULHRSW_8192 m2, m5, m7 + PMULHRSW_8192 m3, m6, m7 + punpcklwd m4, m0, m1 ; 34 + punpcklwd m5, m1, m2 ; 45 + punpcklwd m6, m2, m3 ; 56 + SAVELINE_W8 6, m3 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 +.hv_w8_loop: + SAVELINE_W8 1, m3 + SAVELINE_W8 2, m4 + SAVELINE_W8 3, m5 + SAVELINE_W8 4, m6 +%if ARCH_X86_32 + pmaddwd m0, m1, subpelv0 ; a0 + pmaddwd m7, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd m0, m3 + paddd m7, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd m0, m5 + paddd m7, m6 + mova m5, [base+pd_32] + paddd m0, m5 + paddd m7, m5 + mova accuv0, m0 + mova accuv1, m7 +%else + pmaddwd accuv0, m1, subpelv0 ; a0 + pmaddwd accuv1, m2, subpelv0 ; b0 + pmaddwd m3, subpelv1 ; a1 + pmaddwd m4, subpelv1 ; b1 + paddd accuv0, m3 + paddd accuv1, m4 + pmaddwd m5, subpelv2 ; a2 + pmaddwd m6, subpelv2 ; b2 + paddd accuv0, m5 + paddd accuv1, m6 + mova m7, [base+pd_32] + paddd accuv0, m7 + paddd accuv1, m7 + %if cpuflag(ssse3) + mova m7, [base+subpel_h_shufB] + mova m6, [base+subpel_h_shufC] + mova m5, [base+subpel_h_shufA] + %define shufA m5 + %define shufB m7 + %define shufC m6 + %endif +%endif + PREP_8TAP_HV m0, srcq+strideq*1, m5, m6 + lea srcq, [srcq+strideq*2] + PREP_8TAP_HV m4, srcq+strideq*0, m5, m6 +%if cpuflag(ssse3) + mova m5, [base+pw_8192] +%else + mova m5, [base+pw_2] +%endif + PMULHRSW_8192 m0, m0, m5 + PMULHRSW_8192 m4, m4, m5 + RESTORELINE_W8 6, m6 + punpcklwd m5, m6, m0 ; 67 + punpcklwd m6, m0, m4 ; 78 + pmaddwd m1, m5, subpelv3 ; a3 + paddd m2, m1, accuv0 + pmaddwd m1, m6, subpelv3 ; b3 + paddd m1, m1, accuv1 + psrad m2, 6 + psrad m1, 6 + packssdw m2, m1 + movq [tmpq+wq*0], m2 + movhps [tmpq+wq*2], m2 + lea tmpq, [tmpq+wq*4] + sub hd, 2 + jle .hv_w8_outer + SAVELINE_W8 6, m4 + RESTORELINE_W8 1, m1 + RESTORELINE_W8 2, m2 + RESTORELINE_W8 3, m3 + RESTORELINE_W8 4, m4 + jmp .hv_w8_loop +.hv_w8_outer: +%if ARCH_X86_32 + mov srcq, srcm + mov tmpq, tmpm + movzx hd, r5w + add srcq, 4 + add tmpq, 8 + mov srcm, srcq + mov tmpm, tmpq +%else + add r6, 4 + add r8, 8 + movzx hd, r5b + mov srcq, r6 + mov tmpq, r8 +%endif + sub r5d, 1<<16 + jg .hv_w8_loop0 + RET +%endmacro + +%macro movifprep 2 + %if isprep + mov %1, %2 + %endif +%endmacro + +%macro SAVE_REG 1 + %xdefine r%1_save r%1 + %xdefine r%1q_save r%1q + %xdefine r%1d_save r%1d + %if ARCH_X86_32 + %define r%1m_save [rstk+stack_offset+(%1+1)*4] + %endif +%endmacro + +%macro LOAD_REG 1 + %xdefine r%1 r%1_save + %xdefine r%1q r%1q_save + %xdefine r%1d r%1d_save + %if ARCH_X86_32 + %define r%1m r%1m_save + %endif + %undef r%1d_save + %undef r%1q_save + %undef r%1_save +%endmacro + +%macro REMAP_REG 2-3 + %xdefine r%1 r%2 + %xdefine r%1q r%2q + %xdefine r%1d r%2d + %if ARCH_X86_32 + %if %3 == 0 + %xdefine r%1m r%2m + %else + %define r%1m [rstk+stack_offset+(%1+1)*4] + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_PREV 0 + %if isprep + %if ARCH_X86_64 + SAVE_REG 14 + %assign %%i 14 + %rep 14 + %assign %%j %%i-1 + REMAP_REG %%i, %%j + %assign %%i %%i-1 + %endrep + %else + SAVE_REG 5 + %assign %%i 5 + %rep 5 + %assign %%j %%i-1 + REMAP_REG %%i, %%j, 0 + %assign %%i %%i-1 + %endrep + %endif + %endif +%endmacro + +%macro MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT 0 + %if isprep + %assign %%i 1 + %if ARCH_X86_64 + %rep 13 + %assign %%j %%i+1 + REMAP_REG %%i, %%j + %assign %%i %%i+1 + %endrep + LOAD_REG 14 + %else + %rep 4 + %assign %%j %%i+1 + REMAP_REG %%i, %%j, 1 + %assign %%i %%i+1 + %endrep + LOAD_REG 5 + %endif + %endif +%endmacro + +%macro MC_8TAP_SCALED_RET 0-1 1 ; leave_mapping_unchanged + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + RET + %if %1 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %endif +%endmacro + +%if ARCH_X86_64 + %macro MC_8TAP_SCALED_H 12 ; dst[0-1], tmp[0-5], weights[0-3] + SWAP m%2, m%5 + movq m%1, [srcq+ r4] + movq m%2, [srcq+ r6] + movhps m%1, [srcq+ r7] + movhps m%2, [srcq+ r9] + movq m%3, [srcq+r10] + movq m%4, [srcq+r11] + movhps m%3, [srcq+r13] + movhps m%4, [srcq+ rX] + add srcq, ssq + movq m%5, [srcq+ r4] + movq m%6, [srcq+ r6] + movhps m%5, [srcq+ r7] + movhps m%6, [srcq+ r9] + movq m%7, [srcq+r10] + movq m%8, [srcq+r11] + movhps m%7, [srcq+r13] + movhps m%8, [srcq+ rX] + add srcq, ssq + pmaddubsw m%1, m%9 + pmaddubsw m%5, m%9 + pmaddubsw m%2, m%10 + pmaddubsw m%6, m%10 + pmaddubsw m%3, m%11 + pmaddubsw m%7, m%11 + pmaddubsw m%4, m%12 + pmaddubsw m%8, m%12 + phaddw m%1, m%2 + phaddw m%5, m%6 + phaddw m%3, m%4 + phaddw m%7, m%8 + phaddw m%1, m%3 + phaddw m%5, m%7 + pmulhrsw m%1, m12 + pmulhrsw m%5, m12 + SWAP m%2, m%5 + %endmacro +%else + %macro MC_8TAP_SCALED_H 2-3 1 ; weights_mem_start, h_mem_start, load_fh_offsets + %if %3 == 1 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + %endif + movq m0, [srcq+r0] + movq m1, [srcq+rX] + movhps m0, [srcq+r4] + movhps m1, [srcq+r5] + add srcq, ssq + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + sub srcq, ssq + movq m2, [srcq+r0] + movq m3, [srcq+rX] + movhps m2, [srcq+r4] + movhps m3, [srcq+r5] + add srcq, ssq + movq m6, [srcq+r0] + movq m7, [srcq+rX] + movhps m6, [srcq+r4] + movhps m7, [srcq+r5] + add srcq, ssq + pmaddubsw m0, [esp+%1+ 0] + pmaddubsw m4, [esp+%1+ 0] + pmaddubsw m1, [esp+%1+16] + pmaddubsw m5, [esp+%1+16] + pmaddubsw m2, [esp+%1+32] + pmaddubsw m6, [esp+%1+32] + pmaddubsw m3, [esp+%1+48] + pmaddubsw m7, [esp+%1+48] + phaddw m0, m1 + phaddw m4, m5 + phaddw m2, m3 + phaddw m6, m7 + phaddw m0, m2 + phaddw m4, m6 + pmulhrsw m0, m12 + pmulhrsw m4, m12 + %if %2 != 0 + mova [esp+%2+ 0], m0 + mova [esp+%2+16], m4 + %endif + %endmacro +%endif + +%macro MC_8TAP_SCALED 1 +%ifidn %1, put + %assign isprep 0 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_8bpc, 2, 15, 16, 0x180, dst, ds, src, ss, w, h, mx, my, dx, dy + %else +cglobal put_8tap_scaled_8bpc, 2, 14, 16, 0x180, dst, ds, src, ss, w, h, mx, my, dx, dy + %endif + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal put_8tap_scaled_8bpc, 0, 7, 8, 0x200, dst, ds, src, ss, w, h, mx, my, dx, dy + %else +cglobal put_8tap_scaled_8bpc, 0, 7, 8, -0x200-0x20, dst, ds, src, ss, w, h, mx, my, dx, dy + %endif + %endif + %xdefine base_reg r12 + %define rndshift 10 +%else ; prep + %assign isprep 1 + %if ARCH_X86_64 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_8bpc, 2, 15, 16, 0x180, tmp, src, ss, w, h, mx, my, dx, dy + %xdefine tmp_stridem r14q + %else +cglobal prep_8tap_scaled_8bpc, 2, 14, 16, 0x180, tmp, src, ss, w, h, mx, my, dx, dy + %define tmp_stridem qword [rsp+0x138] + %endif + %xdefine base_reg r11 + %else ; ARCH_X86_32 + %if required_stack_alignment <= STACK_ALIGNMENT +cglobal prep_8tap_scaled_8bpc, 0, 7, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy + %else +cglobal prep_8tap_scaled_8bpc, 0, 6, 8, 0x200, tmp, src, ss, w, h, mx, my, dx, dy + %endif + %define tmp_stridem dword [esp+0x138] + %endif + %define rndshift 6 +%endif +%if ARCH_X86_32 + mov [esp+0x1f0], t0d + mov [esp+0x1f4], t1d + %if !isprep && required_stack_alignment > STACK_ALIGNMENT + mov dstd, dstm + mov dsd, dsm + mov srcd, srcm + mov ssd, ssm + mov hd, hm + mov r4, mxm + %define r0m [esp+0x200] + %define dsm [esp+0x204] + %define dsmp dsm + %define r1m dsm + %define r2m [esp+0x208] + %define ssm [esp+0x20c] + %define r3m ssm + %define hm [esp+0x210] + %define mxm [esp+0x214] + mov r0m, dstd + mov dsm, dsd + mov r2m, srcd + mov ssm, ssd + mov hm, hd + mov r0, mym + mov r1, dxm + mov r2, dym + %define mym [esp+0x218] + %define dxm [esp+0x09c] + %define dym [esp+0x21c] + mov mxm, r4 + mov mym, r0 + mov dxm, r1 + mov dym, r2 + tzcnt wd, wm + %endif + %if isprep && required_stack_alignment > STACK_ALIGNMENT + %xdefine base_reg r5 + %else + %xdefine base_reg r6 + %endif + mov ssd, ssm +%endif + LEA base_reg, %1_8tap_scaled_8bpc_ssse3 +%xdefine base base_reg-%1_8tap_scaled_8bpc_ssse3 +%if ARCH_X86_64 || isprep || required_stack_alignment <= STACK_ALIGNMENT + tzcnt wd, wm +%endif +%if ARCH_X86_32 + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 +%endif + movd m8, dxm + movd m14, mxm + pshufd m8, m8, q0000 + pshufd m14, m14, q0000 +%if isprep && UNIX64 + mov r5d, t0d + DECLARE_REG_TMP 5, 7 +%endif +%if ARCH_X86_64 + mov dyd, dym +%endif +%ifidn %1, put + %if WIN64 + mov r8d, hm + DEFINE_ARGS dst, ds, src, ss, w, _, _, my, h, dy, ss3 + %define hm r5m + %define dxm r8m + %elif ARCH_X86_64 + DEFINE_ARGS dst, ds, src, ss, w, h, _, my, dx, dy, ss3 + %define hm r6m + %endif + %if ARCH_X86_64 + %if required_stack_alignment > STACK_ALIGNMENT + %define dsm [rsp+0x138] + %define rX r1 + %define rXd r1d + %else + %define dsm dsq + %define rX r14 + %define rXd r14d + %endif + %else + %define rX r1 + %endif +%else ; prep + %if WIN64 + mov r7d, hm + DEFINE_ARGS tmp, src, ss, w, _, _, my, h, dy, ss3 + %define hm r4m + %define dxm r7m + %elif ARCH_X86_64 + DEFINE_ARGS tmp, src, ss, w, h, _, my, dx, dy, ss3 + %define hm [rsp+0x94] + %endif + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %if ARCH_X86_64 + %define rX r14 + %define rXd r14d + %else + %define rX r3 + %endif +%endif +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] + mova m12, [base+pw_8192] + %ifidn %1, put + mova m13, [base+pd_512] + %else + mova m13, [base+pd_32] + %endif +%else + %define m10 [base+pd_0x3ff] + %define m12 [base+pw_8192] + %ifidn %1, put + %define m13 [base+pd_512] + %else + %define m13 [base+pd_32] + %endif +%endif + pxor m9, m9 +%if ARCH_X86_64 + lea ss3q, [ssq*3] + movzx r7d, t1b + shr t1d, 16 + cmp hd, 6 + cmovs t1d, r7d + sub srcq, ss3q +%else + MCT_8TAP_SCALED_REMAP_REGS_TO_DEFAULT + mov r1, [esp+0x1f4] + lea r0, [ssq*3] + movzx r2, r1b + shr r1, 16 + cmp dword hm, 6 + cmovs r1, r2 + mov [esp+0x1f4], r1 + mov r1, r1m + mov r2, r2m + sub srcq, r0 + MCT_8TAP_SCALED_REMAP_REGS_TO_PREV + %define ss3q r0 + %define myd r4 + %define dyd dword dym + %define hd dword hm +%endif + cmp dyd, 1024 + je .dy1 + cmp dyd, 2048 + je .dy2 + movzx wd, word [base+%1_8tap_scaled_ssse3_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %else + %define m11 [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [rsp+0x180], m14 + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m2, [srcq+ssq*2] + movhps m0, [srcq+ssq*1] + movhps m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + pshufb m14, m5 + paddb m14, m6 + %endif + movq m1, [srcq+ssq*0] + movq m3, [srcq+ssq*2] + movhps m1, [srcq+ssq*1] + movhps m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %else + pand m7, m8, m11 + pandn m8, m15 + %define m8 m6 + %define m15 m5 + por m15, m7 + mova [rsp+0x190], m15 + %endif + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 1 2 3 + pmulhrsw m1, m12 ; 4 5 6 7 + palignr m2, m1, m0, 4 ; 1 2 3 4 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + pshufd m5, m1, q0321 ; 5 6 7 _ + punpcklwd m2, m1, m5 ; 45 56 + punpckhwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mov myd, mym + mov r0, r0m + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif +.w2_loop: + and myd, 0x3ff + %if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m5, m3, m8 + pmaddwd m6, m0, m9 + pmaddwd m7, m2, m10 + pmaddwd m8, m4, m11 + paddd m5, m6 + paddd m7, m8 + %else + mov mym, myd + mov r1, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r1, [r1+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r1*8+0] + cmovnz r3, [base+subpel_filters+r1*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m5, m7, q0000 + pshufd m6, m7, q1111 + pmaddwd m3, m5 + pmaddwd m0, m6 + pshufd m5, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m2, m5 + pmaddwd m4, m7 + paddd m3, m0 + paddd m2, m4 + SWAP m5, m3 + SWAP m7, m2 + %endif + paddd m5, m13 + paddd m5, m7 + psrad m5, 10 + packssdw m5, m5 + packuswb m5, m5 + %if ARCH_X86_64 + pextrw r6d, m5, 0 + mov [dstq], r6w + add dstq, dsq + dec hd + jz .ret + add myd, dyd + %else + pextrw r3d, m5, 0 + mov [dstq], r3w + add dstq, dsm + dec hd + jz .ret + mov myd, mym + add myd, dym + %endif + test myd, ~0x3ff + %if ARCH_X86_32 + SWAP m3, m5 + SWAP m2, m7 + mova m3, [rsp+0x1a0] + mova m0, [rsp+0x1b0] + mova m2, [rsp+0x1c0] + mova m4, [rsp+0x1d0] + %define m14 [esp+0x180] + %define m15 [esp+0x190] + %endif + jz .w2_loop + %if ARCH_X86_32 + mov r3, r3m + %endif + movq m5, [srcq] + test myd, 0x400 + jz .w2_skip_line + add srcq, ssq + shufps m3, m0, q1032 ; 01 12 + shufps m0, m2, q1032 ; 23 34 + shufps m2, m4, q1032 ; 45 56 + pshufb m5, m14 + pmaddubsw m5, m15 + phaddw m5, m5 + pmulhrsw m5, m12 + palignr m4, m5, m1, 12 + punpcklqdq m1, m4, m4 ; 6 7 6 7 + punpcklwd m4, m1, m5 ; 67 __ + %if ARCH_X86_32 + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif + jmp .w2_loop +.w2_skip_line: + movhps m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m3, m0 ; 01 12 + mova m0, m2 ; 23 34 + pshufb m5, m14 + pmaddubsw m5, m15 + phaddw m5, m5 + pmulhrsw m5, m12 ; 6 7 6 7 + palignr m4, m5, m1, 8 ; 4 5 6 7 + pshufd m5, m4, q0321 ; 5 6 7 _ + mova m1, m4 + punpcklwd m2, m4, m5 ; 45 56 + punpckhwd m4, m5 ; 67 __ + %if ARCH_X86_32 + mova [rsp+0x1a0], m3 + mova [rsp+0x1b0], m0 + mova [rsp+0x1c0], m2 + mova [rsp+0x1d0], m4 + %endif + jmp .w2_loop +%endif +INIT_XMM ssse3 +.w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%else + %define m11 [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m0, m14, m10 + psrld m0, 6 + paddd m15, m0 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] +%else + movd r0, m15 + movd rX, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + movd m1, [base+subpel_filters+r0*8+2] + movd m2, [base+subpel_filters+rX*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m7, [base+subpel_filters+r5*8+2] + movifprep r3, r3m + SWAP m4, m7 + %define m15 m1 +%endif + mova m5, [base+bdct_lb_dw] + movq m6, [base+subpel_s_shuf2] + psrld m14, 10 + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 + punpcklqdq m6, m6 + pshufb m14, m5 + paddb m14, m6 +%if ARCH_X86_64 + pcmpeqd m0, m9 + pand m11, m0 +%else + mova [esp+0x180], m14 + SWAP m7, m4 + pxor m3, m3 + pcmpeqd m0, m3 + pand m2, m11, m0 + %define m11 m2 +%endif + pandn m0, m15 +%if ARCH_X86_64 + SWAP m15, m0 +%else + %define m15 m0 +%endif + por m15, m11 +%if ARCH_X86_64 + movu m7, [srcq+ssq*0] + movu m9, [srcq+ssq*1] + movu m8, [srcq+ssq*2] + movu m10, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + movu m2, [srcq+ssq*0] + movu m4, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m5, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m7, m14 + pshufb m9, m14 + pshufb m8, m14 + pshufb m10, m14 + pshufb m2, m14 + pshufb m4, m14 + pshufb m3, m14 + pshufb m5, m14 + pmaddubsw m7, m15 + pmaddubsw m9, m15 + pmaddubsw m8, m15 + pmaddubsw m10, m15 + pmaddubsw m2, m15 + pmaddubsw m4, m15 + pmaddubsw m3, m15 + pmaddubsw m5, m15 + phaddw m7, m9 + phaddw m8, m10 + phaddw m9, m2, m4 + phaddw m3, m5 + pmulhrsw m7, m12 ; 0 1 + pmulhrsw m8, m12 ; 2 3 + pmulhrsw m9, m12 ; 4 5 + pmulhrsw m3, m12 ; 6 7 + shufps m4, m7, m8, q1032 ; 1 2 + shufps m5, m8, m9, q1032 ; 3 4 + shufps m6, m9, m3, q1032 ; 5 6 + psrldq m11, m3, 8 ; 7 _ + punpcklwd m0, m7, m4 ; 01 + punpckhwd m7, m4 ; 12 + punpcklwd m1, m8, m5 ; 23 + punpckhwd m8, m5 ; 34 + punpcklwd m2, m9, m6 ; 45 + punpckhwd m9, m6 ; 56 + punpcklwd m3, m11 ; 67 + mova [rsp+0x00], m7 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 +%else + mova [esp+0x190], m15 + lea ss3q, [ssq*3] + movu m2, [srcq+ssq*0] + movu m3, [srcq+ssq*1] + movu m7, [srcq+ssq*2] + movu m6, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m2, m14 + pshufb m3, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + phaddw m2, m3 + phaddw m7, m6 + movu m1, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m6, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m1, m14 + pshufb m5, m14 + pshufb m3, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m5, m15 + pmaddubsw m3, m15 + pmaddubsw m6, m15 + phaddw m1, m5 + phaddw m3, m6 + pmulhrsw m2, m12 + pmulhrsw m7, m12 + pmulhrsw m1, m12 + pmulhrsw m3, m12 + shufps m4, m2, m7, q1032 ; 1 2 + shufps m5, m7, m1, q1032 ; 3 4 + shufps m6, m1, m3, q1032 ; 5 6 + psrldq m0, m3, 8 ; 7 _ + mova [esp+0x1a0], m0 + %define m11 [esp+0x1a0] + punpcklwd m0, m2, m4 ; 01 + punpckhwd m2, m4 ; 12 + punpcklwd m4, m7, m5 ; 23 + punpckhwd m7, m5 ; 34 + punpcklwd m5, m1, m6 ; 45 + punpckhwd m1, m6 ; 56 + punpcklwd m3, [esp+0x1a0] ; 67 + mov myd, mym + mov r0, r0m + mova [esp+0x1b0], m0 ; 01 + mova [esp+0x1c0], m4 ; 23 + mova [esp+0x1d0], m5 ; 45 + mova [esp+0x1e0], m3 ; 67 + mova [rsp+0x00], m2 ; 12 + mova [rsp+0x10], m7 ; 34 + mova [rsp+0x20], m1 ; 56 + SWAP m1, m4 + SWAP m2, m5 +%endif +.w4_loop: + and myd, 0x3ff +%if ARCH_X86_64 + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m10, r6q + punpcklbw m10, m10 + psraw m10, 8 + pshufd m7, m10, q0000 + pshufd m8, m10, q1111 + pshufd m9, m10, q2222 + pshufd m10, m10, q3333 + pmaddwd m4, m0, m7 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m10 + paddd m4, m5 + paddd m6, m7 + paddd m4, m13 + paddd m4, m6 +%else + mov mym, myd + mov r5, [esp+0x1f4] + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + pmaddwd m0, m4 + pmaddwd m1, m5 + pmaddwd m2, m6 + pmaddwd m3, m7 + paddd m0, m1 + paddd m2, m3 + paddd m0, m13 + paddd m0, m2 + SWAP m4, m0 +%endif + psrad m4, rndshift + packssdw m4, m4 +%ifidn %1, put + packuswb m4, m4 + movd [dstq], m4 + add dstq, dsmp +%else + movq [tmpq], m4 + add tmpq, 8 +%endif + dec hd + jz .ret +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .w4_loop +%else + SWAP m0, m4 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + jnz .w4_next_line + mova m0, [esp+0x1b0] + mova m1, [esp+0x1c0] + mova m2, [esp+0x1d0] + mova m3, [esp+0x1e0] + jmp .w4_loop +.w4_next_line: + %define m14 [esp+0x180] + %define m15 [esp+0x190] +%endif + movu m4, [srcq] + test myd, 0x400 + jz .w4_skip_line +%if ARCH_X86_64 + mova m0, [rsp+0x00] + mova [rsp+0x00], m1 + mova m1, [rsp+0x10] + mova [rsp+0x10], m2 + mova m2, [rsp+0x20] + mova [rsp+0x20], m3 +%else + mova m5, [esp+0x1c0] + mova m0, [rsp+0x000] + mova [rsp+0x00], m5 + mova [esp+0x1b0], m0 + mova m6, [esp+0x1d0] + mova m1, [rsp+0x010] + mova [rsp+0x10], m6 + mova [esp+0x1c0], m1 + mova m7, [esp+0x1e0] + mova m2, [rsp+0x020] + mova [rsp+0x20], m7 + mova [esp+0x1d0], m2 +%endif + pshufb m4, m14 + pmaddubsw m4, m15 + phaddw m4, m4 + pmulhrsw m4, m12 + punpcklwd m3, m11, m4 +%if ARCH_X86_32 + mova [esp+0x1e0], m3 +%endif + mova m11, m4 + add srcq, ssq + jmp .w4_loop +.w4_skip_line: +%if ARCH_X86_32 + mova m0, [esp+0x1c0] + mova m1, [esp+0x1d0] + mova m2, [esp+0x1e0] +%endif + movu m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + mova m6, [rsp+0x10] + mova m7, [rsp+0x20] + pshufb m4, m14 + pshufb m5, m14 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m4, m5 + pmulhrsw m4, m12 + punpcklwd m5, m11, m4 + mova [rsp+0x00], m6 + mova [rsp+0x10], m7 + mova [rsp+0x20], m5 +%if ARCH_X86_64 + psrldq m11, m4, 8 + mova m0, m1 + mova m1, m2 + mova m2, m3 + punpcklwd m3, m4, m11 +%else + psrldq m6, m4, 8 + punpcklwd m3, m4, m6 + mova [esp+0x1a0], m6 + mova [esp+0x1b0], m0 + mova [esp+0x1c0], m1 + mova [esp+0x1d0], m2 + mova [esp+0x1e0], m3 +%endif + jmp .w4_loop +INIT_XMM ssse3 +.w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .w_start +.w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .w_start +.w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .w_start +.w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .w_start +.w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.w_start: +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + movd m15, t0d +%else + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq ssm + %endif + mov r4, [esp+0x1f0] + shr r4, 16 + movd m15, r4 + mov r0, r0m + mov myd, mym +%endif + sub srcq, 3 + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + mov r5, hm + mov [esp+0x094], myd + mov [esp+0x134], r5 +%endif + jmp .hloop +.hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [esp+0x130], 8*(isprep+1) + mov myd, [esp+0x094] + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + pxor m9, m9 + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov mym, myd + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.hloop: +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m14, m5, q1100 + pshufd m5, m5, q3322 + pand m7, m11, m4 + pand m8, m11, m6 + pand m15, m11, m14 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m14, m2 + pandn m5, m3 + por m7, m4 + por m8, m6 + por m15, m14 + por m11, m5 + mova [rsp+0x10], m7 + mova [rsp+0x20], m8 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 9, 10, 7, 8, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 9, 10, 7, 8, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 9, 10, 7, 8, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 9, 10, 7, 8, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m9, [rsp+0x80] + mov myd, mym + mov dyd, dym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m9 ; 23a + punpckhwd m3, m9 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 + SWAP m14, m8 +.vloop: + and myd, 0x3ff + mov r6d, 64 << 24 + mov r4d, myd + shr r4d, 6 + lea r4d, [t1+r4] + cmovnz r6q, [base+subpel_filters+r4*8] + movq m11, r6q + punpcklbw m11, m11 + psraw m11, 8 + pshufd m5, m11, q0000 + pshufd m7, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 + pmaddwd m4, m5, m0 + pmaddwd m5, m5, m1 + pmaddwd m6, m7, m2 + pmaddwd m7, m7, m3 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 + pmaddwd m8, [rsp+0x70], m11 + pmaddwd m9, [rsp+0x80], m11 + paddd m4, m6 + paddd m5, m7 + paddd m4, m8 + paddd m5, m9 +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x140, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x160 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x180 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 6-7 + mova m5, [esp+0x180] + mova m6, [esp+0x190] + mova m7, [esp+0x1a0] + mova m0, [esp+0x1b0] + mov myd, mym + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x180], m4 + mova [esp+0x190], m5 + mova [esp+0x1a0], m6 + mova [esp+0x1b0], m7 + mova m1, [esp+0x140] + mova m2, [esp+0x150] + mova m3, [esp+0x160] + mova m4, [esp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova [esp+0x160], m2 + mova [esp+0x170], m3 +.vloop: + mov r0, r0m + mov r5, [esp+0x1f4] + and myd, 0x3ff + mov mym, myd + xor r3, r3 + shr r4, 6 + lea r5, [r5+r4] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + movd m7, r4 + movd m6, r3 + punpckldq m7, m6 + punpcklbw m7, m7 + psraw m7, 8 + pshufd m4, m7, q0000 + pshufd m5, m7, q1111 + pmaddwd m0, m4 + pmaddwd m1, m4 + pmaddwd m2, m5 + pmaddwd m3, m5 + pshufd m6, m7, q2222 + pshufd m7, m7, q3333 + paddd m0, m2 + paddd m1, m3 + pmaddwd m2, [esp+0x180], m6 + pmaddwd m3, [esp+0x190], m6 + pmaddwd m4, [esp+0x1a0], m7 + pmaddwd m5, [esp+0x1b0], m7 + paddd m0, m2 + paddd m1, m3 + paddd m0, m13 + paddd m1, m13 + paddd m4, m0 + paddd m5, m1 +%endif + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif + dec hd + jz .hloop_prep +%if ARCH_X86_64 + add myd, dyd + test myd, ~0x3ff + jz .vloop + test myd, 0x400 + mov [rsp+0x140], myd + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + jz .skip_line + mova m14, [base+unpckw] + movq m6, [srcq+r10] + movq m7, [srcq+r11] + movhps m6, [srcq+r13] + movhps m7, [srcq+ rX] + movq m4, [srcq+ r4] + movq m5, [srcq+ r6] + movhps m4, [srcq+ r7] + movhps m5, [srcq+ r9] + add srcq, ssq + mov myd, [rsp+0x140] + mov dyd, dym + pshufd m9, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m9 ; 3a 2a + pshufb m3, m9 ; 3b 2b + pmaddubsw m6, [rsp+0x30] + pmaddubsw m7, [rsp+0x40] + pmaddubsw m4, [rsp+0x10] + pmaddubsw m5, [rsp+0x20] + phaddw m6, m7 + phaddw m4, m5 + phaddw m4, m6 + pmulhrsw m4, m12 + pshufb m5, [rsp+0x50], m14 ; 4a 5a + pshufb m6, [rsp+0x60], m14 ; 4b 5b + pshufb m7, [rsp+0x70], m9 ; 7a 6a + pshufb m8, [rsp+0x80], m9 ; 7b 6b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m5 ; 34a + punpcklwd m3, m6 ; 34b + punpckhwd m5, m7 ; 56a + punpckhwd m6, m8 ; 56b + punpcklwd m7, m4 ; 78a + punpckhqdq m4, m4 + punpcklwd m8, m4 ; 78b + mova [rsp+0x50], m5 + mova [rsp+0x60], m6 + mova [rsp+0x70], m7 + mova [rsp+0x80], m8 + jmp .vloop +.skip_line: + mova m0, [rsp+0x10] + mova m1, [rsp+0x20] + mova m14, [rsp+0x30] + mova m15, [rsp+0x40] + MC_8TAP_SCALED_H 4, 8, 5, 6, 7, 9, 10, 11, 0, 1, 14, 15 + mov myd, [rsp+0x140] + mov dyd, dym + mova m0, m2 ; 01a + mova m1, m3 ; 01b + mova m2, [rsp+0x50] ; 23a + mova m3, [rsp+0x60] ; 23b + mova m5, [rsp+0x70] ; 45a + mova m6, [rsp+0x80] ; 45b + punpcklwd m7, m4, m8 ; 67a + punpckhwd m4, m8 ; 67b + mova [rsp+0x50], m5 + mova [rsp+0x60], m6 + mova [rsp+0x70], m7 + mova [rsp+0x80], m4 +%else + mov r0m, r0 + mov myd, mym + mov r3, r3m + add myd, dym + test myd, ~0x3ff + mov mym, myd + jnz .next_line + mova m0, [esp+0x140] + mova m1, [esp+0x150] + mova m2, [esp+0x160] + mova m3, [esp+0x170] + jmp .vloop +.next_line: + test myd, 0x400 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + jz .skip_line + mova m6, [base+unpckw] + mova m0, [esp+0x140] + mova m1, [esp+0x150] + mova m7, [esp+0x180] + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + pshufb m0, m6 ; 0a 1a + pshufb m1, m6 ; 0b 1b + pshufb m7, m6 ; 4a 5a + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + movq m3, [srcq+r0] + movq m2, [srcq+rX] + movhps m3, [srcq+r4] + movhps m2, [srcq+r5] + add srcq, ssq + pmaddubsw m4, [esp+0x20] + pmaddubsw m5, [esp+0x30] + pmaddubsw m3, [esp+0x40] + pmaddubsw m2, [esp+0x50] + phaddw m4, m5 + phaddw m3, m2 + mova m5, [esp+0x190] + mova m2, [esp+0x160] + phaddw m4, m3 + mova m3, [esp+0x170] + pmulhrsw m4, m12 ; 8a 8b + mov myd, mym + pshufb m5, m6 ; 4b 5b + pshufd m6, m6, q1032 + pshufb m2, m6 ; 3a 2a + pshufb m3, m6 ; 3b 2b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova m0, [esp+0x1a0] + mova m1, [esp+0x1b0] + punpcklwd m2, m7 ; 34a + punpcklwd m3, m5 ; 34b + mova [esp+0x160], m2 + mova [esp+0x170], m3 + pshufb m0, m6 ; 7a 6a + pshufb m1, m6 ; 7b 6b + punpckhwd m7, m0 ; 56a + punpckhwd m5, m1 ; 56b + punpcklwd m0, m4 + punpckhqdq m4, m4 + punpcklwd m1, m4 + mova [esp+0x180], m7 + mova [esp+0x190], m5 + mova [esp+0x1a0], m0 + mova [esp+0x1b0], m1 + mova m0, [esp+0x140] + mova m1, [esp+0x150] + jmp .vloop +.skip_line: + MC_8TAP_SCALED_H 0x20, 0x1c0, 0 + mov myd, mym + mova m0, [esp+0x160] + mova m1, [esp+0x170] + mova m2, [esp+0x180] + mova m3, [esp+0x190] + mova [esp+0x140], m0 + mova [esp+0x150], m1 + mova m4, [esp+0x1a0] + mova m5, [esp+0x1b0] + mova [esp+0x160], m2 + mova [esp+0x170], m3 + mova m6, [esp+0x1c0] + mova m7, [esp+0x1d0] + mova [esp+0x180], m4 + mova [esp+0x190], m5 + punpcklwd m4, m6, m7 + punpckhwd m6, m7 + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m6 +%endif + jmp .vloop +INIT_XMM ssse3 +.dy1: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy1_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy1_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + movzx r5, byte [esp+0x1f0] + dec srcd + movd m15, r5 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %else + %define m11 [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [esp+0x00], m14 + %define m14 [esp+0x00] + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m2, [srcq+ssq*2] + movhps m0, [srcq+ssq*1] + movhps m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movq m10, r4 + %else + mov myd, mym + mov r5, [esp+0x1f4] + xor r3, r3 + shr myd, 6 + lea r5, [r5+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r5*8+0] + cmovnz r3, [base+subpel_filters+r5*8+4] + %define m10 m4 + movd m10, r4 + movd m3, r3 + mov r3, r3m + punpckldq m10, m3 + %endif + movq m1, [srcq+ssq*0] + movq m3, [srcq+ssq*2] + movhps m1, [srcq+ssq*1] + add srcq, ss3q + punpcklbw m10, m10 + psraw m10, 8 + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + %else + pand m7, m11, m8 + %define m11 m7 + %endif + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %if ARCH_X86_64 + pshufd m8, m10, q0000 + pshufd m9, m10, q1111 + pshufd m11, m10, q3333 + pshufd m10, m10, q2222 + %else + mova [esp+0x10], m15 + %define m15 [esp+0x10] + mov r0, r0m + pshufd m5, m4, q0000 + pshufd m6, m4, q1111 + pshufd m7, m4, q2222 + pshufd m4, m4, q3333 + %define m8 [esp+0x20] + %define m9 [esp+0x30] + %define m10 [esp+0x40] + %define m11 [esp+0x50] + mova m8, m5 + mova m9, m6 + mova m10, m7 + mova m11, m4 + %endif + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 + pmulhrsw m1, m12 + palignr m2, m1, m0, 4 + pshufd m4, m1, q2121 + punpcklwd m3, m0, m2 ; 01 12 + punpckhwd m0, m2 ; 23 34 + punpcklwd m2, m1, m4 ; 45 56 +.dy1_w2_loop: + movq m1, [srcq+ssq*0] + movhps m1, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pmaddwd m5, m3, m8 + pmaddwd m6, m0, m9 + pmaddwd m7, m2, m10 + mova m3, m0 + mova m0, m2 + paddd m5, m13 + paddd m6, m7 + pshufb m1, m14 + pmaddubsw m1, m15 + phaddw m1, m1 + pmulhrsw m1, m12 + palignr m7, m1, m4, 12 + punpcklwd m2, m7, m1 ; 67 78 + pmaddwd m7, m2, m11 + mova m4, m1 + paddd m5, m6 + paddd m5, m7 + psrad m5, rndshift + packssdw m5, m5 + packuswb m5, m5 + movd r4d, m5 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy1_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy1_w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %if isprep + %define ssq r3 + %endif + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] +%else + movd r1, m15 + movd r3, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + %define m15 m5 + SWAP m4, m7 + movd m15, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m4, [base+subpel_filters+r5*8+2] + mov myd, mym + mov rX, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea rX, [rX+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+rX*8+0] + cmovnz r5, [base+subpel_filters+rX*8+4] + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif +%endif + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 + movq m6, [base+subpel_s_shuf2] +%if ARCH_X86_64 + pcmpeqd m8, m9 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m0, [srcq+ssq*0] + movu m1, [srcq+ssq*1] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpcklqdq m6, m6 + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + movu m7, [srcq+ssq*2] + add srcq, ss3q + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + paddb m14, m6 + movq m10, r4q + punpcklbw m10, m10 + psraw m10, 8 + pshufb m0, m14 + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb m5, m14 + pshufb m7, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + pmaddubsw m7, m15 + phaddw m0, m1 + phaddw m2, m3 + phaddw m4, m5 + phaddw m6, m7, m7 + pmulhrsw m0, m12 ; 0 1 + pmulhrsw m2, m12 ; 2 3 + pmulhrsw m4, m12 ; 4 5 + pmulhrsw m6, m12 ; 6 _ + shufps m1, m0, m2, q1032 ; 1 2 + shufps m3, m2, m4, q1032 ; 3 4 + shufps m5, m4, m6, q1032 ; 5 6 + punpcklwd m7, m0, m1 ; 01 + punpckhwd m0, m1 ; 12 + punpcklwd m8, m2, m3 ; 23 + punpckhwd m2, m3 ; 34 + punpcklwd m9, m4, m5 ; 45 + punpckhwd m4, m5 ; 56 +%else + pxor m3, m3 + pcmpeqd m8, m3 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + add srcq, ss3q + punpcklqdq m6, m6 + SWAP m4, m7 + pand m7, m11, m8 + pandn m8, m15 + SWAP m5, m0 + por m15, m7 + paddb m14, m6 + movu m0, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m0, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + mova [esp+0x00], m14 + mova [esp+0x10], m15 + pmaddubsw m0, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + phaddw m1, m2 + movu m2, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + mov r0, r0m + phaddw m3, m0 + pshufb m2, m14 + pmaddubsw m2, m15 + %define m14 [esp+0x00] + %define m15 [esp+0x10] + phaddw m7, m6 + phaddw m2, m2 + movd m6, r4 + movd m0, r5 + punpckldq m6, m0 + punpcklbw m6, m6 + psraw m6, 8 + mova [esp+0x20], m6 + pmulhrsw m1, m12 ; 0 1 + pmulhrsw m3, m12 ; 2 3 + pmulhrsw m7, m12 ; 4 5 + pmulhrsw m2, m12 ; 6 _ + shufps m0, m1, m3, q1032 ; 1 2 + shufps m4, m3, m7, q1032 ; 3 4 + shufps m5, m7, m2, q1032 ; 5 6 + punpcklwd m6, m1, m0 ; 01 + punpckhwd m1, m0 ; 12 + mova [esp+0x30], m1 + punpcklwd m1, m3, m4 ; 23 + punpckhwd m3, m4 ; 34 + mova [esp+0x40], m3 + punpcklwd m3, m7, m5 ; 45 + punpckhwd m7, m5 ; 56 + mova [esp+0x50], m7 + mova [esp+0x60], m2 + mova m0, [esp+0x20] + %xdefine m8 m1 + %xdefine m9 m3 + %xdefine m10 m0 + SWAP m7, m6 + SWAP m1, m4 + SWAP m3, m2 +%endif + pshufd m1, m10, q0000 + pshufd m3, m10, q1111 + pshufd m5, m10, q2222 + pshufd m10, m10, q3333 +%if ARCH_X86_64 + mova [rsp+0x00], m8 + mova [rsp+0x10], m2 + mova [rsp+0x20], m9 + mova [rsp+0x30], m4 +%else + mova [esp+0x70], m8 + mova [esp+0x80], m9 + mova [esp+0x90], m1 + mova [esp+0xa0], m3 + mova [esp+0xb0], m5 + mova [esp+0xc0], m10 + %ifidn %1, put + mov dsd, dsm + %endif + %define m11 m6 +%endif +.dy1_w4_loop: +%if ARCH_X86_64 + movu m11, [srcq+ssq*0] + pmaddwd m7, m1 + pmaddwd m8, m3 + pmaddwd m0, m1 + pmaddwd m2, m3 + pmaddwd m9, m5 + pmaddwd m4, m5 + paddd m7, m8 + paddd m0, m2 + movu m8, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m11, m14 + pmaddubsw m11, m15 + paddd m7, m13 + paddd m0, m13 + paddd m7, m9 + paddd m0, m4 + pshufb m8, m14 + pmaddubsw m8, m15 + phaddw m11, m8 + mova m8, [rsp+0x20] + pmulhrsw m11, m12 + punpcklwd m9, m6, m11 ; 67 + psrldq m6, m11, 8 + punpcklwd m4, m11, m6 ; 78 + pmaddwd m2, m9, m10 + pmaddwd m11, m4, m10 + paddd m7, m2 + mova m2, [rsp+0x30] + paddd m0, m11 +%else + SWAP m7, m6 + SWAP m1, m4 + SWAP m3, m2 + movu m5, [srcq+ssq*0] + mova m0, [esp+0x30] + mova m2, [esp+0x40] + mova m4, [esp+0x50] + pmaddwd m6, [esp+0x90] + pmaddwd m1, [esp+0xa0] + pmaddwd m0, [esp+0x90] + pmaddwd m2, [esp+0xa0] + pmaddwd m3, [esp+0xb0] + pmaddwd m4, [esp+0xb0] + paddd m6, m1 + paddd m0, m2 + movu m7, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pshufb m5, m14 + pmaddubsw m5, m15 + paddd m6, m13 + paddd m0, m13 + paddd m6, m3 + paddd m0, m4 + pshufb m7, m14 + pmaddubsw m7, m15 + phaddw m5, m7 + mova m7, [rsp+0x80] + pmulhrsw m5, m12 + punpcklwd m3, [esp+0x60], m5 ; 67 + psrldq m1, m5, 8 + punpcklwd m4, m5, m1 ; 78 + pmaddwd m2, m3, [esp+0xc0] + pmaddwd m5, m4, [esp+0xc0] + mova [esp+0x60], m1 + paddd m6, m2 + mova m2, [esp+0x50] + paddd m0, m5 + SWAP m7, m6 +%endif + psrad m7, rndshift + psrad m0, rndshift + packssdw m7, m0 +%if ARCH_X86_64 + mova m0, [rsp+0x10] +%else + mova m0, [esp+0x40] +%define m11 m5 +%endif +%ifidn %1, put + packuswb m7, m7 + psrldq m11, m7, 4 + movd [dstq+dsq*0], m7 + movd [dstq+dsq*1], m11 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m7 + add tmpq, 16 +%endif + sub hd, 2 + jz .ret +%if ARCH_X86_64 + mova m7, [rsp+0x00] + mova [rsp+0x00], m8 + mova [rsp+0x10], m2 + mova [rsp+0x20], m9 + mova [rsp+0x30], m4 +%else + mova m7, [esp+0x70] ; 01 + mova m1, [esp+0x80] ; 23 + mova m2, [esp+0x50] ; 34 + mova [esp+0x30], m0 + mova [esp+0x70], m1 + mova [esp+0x40], m2 + mova [esp+0x80], m3 + mova [esp+0x50], m4 +%endif + jmp .dy1_w4_loop +INIT_XMM ssse3 +.dy1_w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .dy1_w_start +.dy1_w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .dy1_w_start +.dy1_w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .dy1_w_start +.dy1_w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .dy1_w_start +.dy1_w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.dy1_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define m8 m0 + %define m9 m1 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define ssq ssm + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + sub srcq, 3 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q + punpcklbw m3, m3 + psraw m3, 8 +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + punpcklbw m5, m5 + psraw m5, 8 + SWAP m3, m5 +%endif + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [rsp+0x140], m0 + mova [rsp+0x150], m1 + mova [rsp+0x160], m2 + mova [rsp+0x170], m3 +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + SWAP m5, m3 + mov r5, hm + mov [esp+0x134], r5 +%endif + jmp .dy1_hloop +.dy1_hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [rsp+0x130], 8*(isprep+1) + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%else + %define m10 [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy1_hloop: + pxor m9, m9 +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m8, m11, m4 + pand m9, m11, m6 + pand m15, m11, m7 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m7, m2 + pandn m5, m3 + por m8, m4 + por m9, m6 + por m15, m7 + por m11, m5 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 10, 8, 9, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 7, 10, 8, 9, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m15, [rsp+0x80] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + SWAP m14, m8 + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m15; 23a + punpckhwd m3, m15 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 + mova m14, [base+unpckw] +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x60, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x180 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1c0 ; 6-7 + mova m5, [esp+0x1a0] + mova m6, [esp+0x1b0] + mova m7, [esp+0x1c0] + mova m0, [esp+0x1d0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 + mova [esp+0x1d0], m7 + mova m1, [esp+0x060] + mova m2, [esp+0x070] + mova m3, [esp+0x180] + mova m4, [esp+0x190] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x060], m0 + mova [esp+0x070], m1 + mova [esp+0x180], m2 + mova [esp+0x190], m3 + %define m8 [esp+0x140] + %define m9 [esp+0x150] + %define m10 [esp+0x160] + %define m11 [esp+0x170] +%endif +.dy1_vloop: +%if ARCH_X86_32 + mov r0, r0m +%endif + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m9 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 +%else + pmaddwd m6, [rsp+0x1a0], m10 + pmaddwd m7, [rsp+0x1b0], m10 +%endif + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x70], m11 + pmaddwd m7, [rsp+0x80], m11 +%else + pmaddwd m6, [rsp+0x1c0], m11 + pmaddwd m7, [rsp+0x1d0], m11 +%endif + paddd m4, m6 + paddd m5, m7 + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif +%if ARCH_X86_32 + mov r0m, r0 +%endif + dec hd + jz .dy1_hloop_prep +%if ARCH_X86_64 + movq m4, [srcq+ r4] + movq m5, [srcq+ r6] + movhps m4, [srcq+ r7] + movhps m5, [srcq+ r9] + movq m6, [srcq+r10] + movq m7, [srcq+r11] + movhps m6, [srcq+r13] + movhps m7, [srcq+ rX] + add srcq, ssq + pshufd m15, m14, q1032 + pshufb m0, m14 ; 0a 1a + pshufb m1, m14 ; 0b 1b + pshufb m2, m15 ; 3a 2a + pshufb m3, m15 ; 3b 2b + pmaddubsw m4, [rsp+0x10] + pmaddubsw m5, [rsp+0x20] + pmaddubsw m6, [rsp+0x30] + pmaddubsw m7, [rsp+0x40] + phaddw m4, m5 + phaddw m6, m7 + phaddw m4, m6 + pmulhrsw m4, m12 + pshufb m5, [rsp+0x70], m15 ; 7a 6a + pshufb m7, [rsp+0x80], m15 ; 7b 6b + pshufb m6, [rsp+0x50], m14 ; 4a 5a + pshufb m15, [rsp+0x60], m14 ; 4b 5b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + punpcklwd m2, m6 ; 34a + punpcklwd m3, m15 ; 34b + punpckhwd m6, m5 ; 56a + punpckhwd m15, m7 ; 56b + punpcklwd m5, m4 ; 78a + psrldq m4, 8 + punpcklwd m7, m4 ; 78b + mova [rsp+0x50], m6 + mova [rsp+0x60], m15 + mova [rsp+0x70], m5 + mova [rsp+0x80], m7 +%else + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova m6, [base+unpckw] + mova m0, [esp+0x060] + mova m1, [esp+0x070] + mova m7, [esp+0x1a0] + movq m4, [srcq+r0] + movq m5, [srcq+rX] + movhps m4, [srcq+r4] + movhps m5, [srcq+r5] + pshufb m0, m6 ; 0a 1a + pshufb m1, m6 ; 0b 1b + pshufb m7, m6 ; 4a 5a + mov r0, [esp+16] + mov rX, [esp+24] + mov r4, [esp+20] + mov r5, [esp+28] + movq m3, [srcq+r0] + movq m2, [srcq+rX] + movhps m3, [srcq+r4] + movhps m2, [srcq+r5] + add srcq, ssq + pmaddubsw m4, [esp+0x20] + pmaddubsw m5, [esp+0x30] + pmaddubsw m3, [esp+0x40] + pmaddubsw m2, [esp+0x50] + phaddw m4, m5 + phaddw m3, m2 + mova m5, [esp+0x1b0] + mova m2, [esp+0x180] + phaddw m4, m3 + mova m3, [esp+0x190] + pmulhrsw m4, m12 ; 8a 8b + pshufb m5, m6 ; 4b 5b + pshufd m6, m6, q1032 + pshufb m2, m6 ; 3a 2a + pshufb m3, m6 ; 3b 2b + punpckhwd m0, m2 ; 12a + punpckhwd m1, m3 ; 12b + mova [esp+0x60], m0 + mova [esp+0x70], m1 + mova m0, [esp+0x1c0] + mova m1, [esp+0x1d0] + punpcklwd m2, m7 ; 34a + punpcklwd m3, m5 ; 34b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + pshufb m0, m6 ; 7a 6a + pshufb m1, m6 ; 7b 6b + punpckhwd m7, m0 ; 56a + punpckhwd m5, m1 ; 56b + punpcklwd m0, m4 + punpckhqdq m4, m4 + punpcklwd m1, m4 + mova [esp+0x1a0], m7 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m0 + mova [esp+0x1d0], m1 + mova m0, [esp+0x60] + mova m1, [esp+0x70] +%endif + jmp .dy1_vloop +INIT_XMM ssse3 +.dy2: + movzx wd, word [base+%1_8tap_scaled_ssse3_dy2_table+wq*2] + add wq, base_reg + jmp wq +%ifidn %1, put +.dy2_w2: + %if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d + %else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %define m9 m1 + %define m14 m4 + %define m15 m3 + movzx r5, byte [esp+0x1f0] + dec srcd + movd m15, r5 + %endif + punpckldq m9, m8 + SWAP m8, m9 + paddd m14, m8 ; mx+dx*[0-1] + %if ARCH_X86_64 + mova m11, [base+pd_0x4000] + %endif + pshufd m15, m15, q0000 + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + movd r4d, m15 + psrldq m15, 4 + %if ARCH_X86_64 + movd r6d, m15 + %else + movd r3d, m15 + %endif + mova m5, [base+bdct_lb_dw] + mova m6, [base+subpel_s_shuf2] + movd m15, [base+subpel_filters+r4*8+2] + %if ARCH_X86_64 + movd m7, [base+subpel_filters+r6*8+2] + %else + movd m7, [base+subpel_filters+r3*8+2] + %endif + pxor m9, m9 + pcmpeqd m8, m9 + psrld m14, 10 + %if ARCH_X86_32 + mov r3, r3m + pshufb m14, m5 + paddb m14, m6 + mova [esp+0x00], m14 + %define m14 [esp+0x00] + SWAP m5, m0 + SWAP m6, m3 + %define m8 m5 + %define m15 m6 + %endif + movq m0, [srcq+ssq*0] + movq m1, [srcq+ssq*1] + movhps m0, [srcq+ssq*2] + movhps m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + %if ARCH_X86_64 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + pshufb m14, m5 + paddb m14, m6 + movq m10, r4q + %else + mov myd, mym + mov r3, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r3, r3m + %define m10 m4 + movd m10, r4 + movd m3, r5 + punpckldq m10, m3 + %endif + movq m3, [srcq+ssq*0] + movhps m3, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + punpcklbw m10, m10 + psraw m10, 8 + punpckldq m15, m7 + punpcklqdq m15, m15 + %if ARCH_X86_64 + pand m11, m8 + %else + pand m7, m11, m8 + %define m11 m7 + %endif + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + %if ARCH_X86_64 + pshufd m8, m10, q0000 + pshufd m9, m10, q1111 + pshufd m11, m10, q3333 + pshufd m10, m10, q2222 + %else + mova [esp+0x10], m15 + %define m15 [esp+0x10] + mov r5, r0m + %define dstq r5 + mov dsd, dsm + pshufd m5, m4, q0000 + pshufd m6, m4, q1111 + pshufd m7, m4, q2222 + pshufd m4, m4, q3333 + %define m8 [esp+0x20] + %define m9 [esp+0x30] + %define m10 [esp+0x40] + %define m11 [esp+0x50] + mova m8, m5 + mova m9, m6 + mova m10, m7 + mova m11, m4 + %endif + pshufb m0, m14 + pshufb m1, m14 + pshufb m3, m14 + pmaddubsw m0, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + pslldq m2, m3, 8 + phaddw m0, m2 + phaddw m1, m3 + pmulhrsw m0, m12 ; 0 2 _ 4 + pmulhrsw m1, m12 ; 1 3 _ 5 + pshufd m2, m0, q3110 ; 0 2 2 4 + pshufd m1, m1, q3110 ; 1 3 3 5 + punpcklwd m3, m2, m1 ; 01 23 + punpckhwd m2, m1 ; 23 45 +.dy2_w2_loop: + movq m6, [srcq+ssq*0] + movq m7, [srcq+ssq*1] + movhps m6, [srcq+ssq*2] + movhps m7, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pmaddwd m4, m3, m8 + pmaddwd m5, m2, m9 + pshufb m6, m14 + pshufb m7, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + phaddw m6, m7 + pmulhrsw m6, m12 + psrldq m7, m6, 8 + palignr m6, m0, 8 + palignr m7, m1, 8 + mova m0, m6 + mova m1, m7 + pshufd m6, m6, q3221 + pshufd m7, m7, q3221 + punpcklwd m3, m6, m7 ; 45 67 + punpckhwd m2, m6, m7 ; 67 89 + pmaddwd m6, m3, m10 + pmaddwd m7, m2, m11 + paddd m4, m5 + paddd m4, m13 + paddd m6, m7 + paddd m4, m6 + psrad m4, rndshift + packssdw m4, m4 + packuswb m4, m4 + movd r4d, m4 + mov [dstq+dsq*0], r4w + shr r4d, 16 + mov [dstq+dsq*1], r4w + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .dy2_w2_loop + RET +%endif +INIT_XMM ssse3 +.dy2_w4: +%if ARCH_X86_64 + mov myd, mym + movzx t0d, t0b + dec srcq + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %xdefine m14 m4 + %define m15 m3 + %define dstq r0 + %if isprep + %define ssq r3 + %endif + movzx r4, byte [esp+0x1f0] + dec srcq + movd m15, r4 +%endif + pmaddwd m8, [base+rescale_mul] +%if ARCH_X86_64 + mova m11, [base+pd_0x4000] +%endif + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] + pand m8, m14, m10 + psrld m8, 6 + paddd m15, m8 + psrldq m7, m15, 8 +%if ARCH_X86_64 + movd r4d, m15 + movd r11d, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r6d, m15 + movd r13d, m7 + movd m15, [base+subpel_filters+ r4*8+2] + movd m2, [base+subpel_filters+r11*8+2] + movd m3, [base+subpel_filters+ r6*8+2] + movd m4, [base+subpel_filters+r13*8+2] + movq m6, [base+subpel_s_shuf2] + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] +%else + movd r1, m15 + movd r3, m7 + psrldq m15, 4 + psrldq m7, 4 + movd r4, m15 + movd r5, m7 + %define m15 m5 + SWAP m4, m7 + movd m15, [base+subpel_filters+r1*8+2] + movd m2, [base+subpel_filters+r3*8+2] + movd m3, [base+subpel_filters+r4*8+2] + movd m4, [base+subpel_filters+r5*8+2] + movq m6, [base+subpel_s_shuf2] + mov myd, mym + mov r3, [esp+0x1f4] + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r3, r3m + %if isprep + lea ss3q, [ssq*3] + %endif +%endif + punpckldq m15, m3 + punpckldq m2, m4 + punpcklqdq m15, m2 +%if ARCH_X86_64 + pcmpeqd m8, m9 + psrld m14, 10 + movu m0, [srcq+ssq*0] + movu m2, [srcq+ssq*2] + movu m1, [srcq+ssq*1] + movu m3, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + punpcklqdq m6, m6 + pshufb m14, [base+bdct_lb_dw] + movu m4, [srcq+ssq*0] + movu m5, [srcq+ssq*1] + lea srcq, [srcq+ssq*2] + pand m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m11 + paddb m14, m6 + movq m11, r4q + punpcklbw m11, m11 + psraw m11, 8 + pshufb m0, m14 + pshufb m2, m14 + pshufb m1, m14 + pshufb m3, m14 + pshufb m4, m14 + pshufb m5, m14 + pmaddubsw m0, m15 + pmaddubsw m2, m15 + pmaddubsw m1, m15 + pmaddubsw m3, m15 + pmaddubsw m4, m15 + pmaddubsw m5, m15 + phaddw m0, m2 + phaddw m1, m3 + phaddw m4, m5 + pmulhrsw m0, m12 ; 0 2 + pmulhrsw m1, m12 ; 1 3 + pmulhrsw m4, m12 ; 4 5 + pshufd m8, m11, q0000 + pshufd m9, m11, q1111 + pshufd m10, m11, q2222 + pshufd m11, m11, q3333 +%else + pxor m3, m3 + pcmpeqd m8, m3 + psrld m14, 10 + pshufb m14, [base+bdct_lb_dw] + movu m1, [srcq+ssq*0] + movu m2, [srcq+ssq*2] + movu m3, [srcq+ssq*1] + add srcq, ss3q + punpcklqdq m6, m6 + SWAP m4, m7 + pand m7, m11, m8 + pandn m8, m15 + SWAP m15, m8 + por m15, m7 + paddb m14, m6 + movu m0, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m6, [srcq+ssq*2] + add srcq, ss3q + pshufb m1, m14 + pshufb m2, m14 + pshufb m3, m14 + pshufb m0, m14 + pshufb m7, m14 + pshufb m6, m14 + pmaddubsw m1, m15 + pmaddubsw m2, m15 + pmaddubsw m3, m15 + mova [esp+0x00], m14 + mova [esp+0x10], m15 + pmaddubsw m0, m15 + pmaddubsw m7, m15 + pmaddubsw m6, m15 + %define m14 [esp+0x00] + %define m15 [esp+0x10] + phaddw m1, m2 + phaddw m3, m0 + phaddw m7, m6 + %ifidn %1, put + mov dsd, dsm + %define dstq r5 + %else + %define tmpq r5 + %endif + movd m6, r4 + movd m0, r5 + punpckldq m6, m0 + punpcklbw m6, m6 + psraw m6, 8 + mov r5, r0m + pmulhrsw m1, m12 ; 0 2 + pmulhrsw m3, m12 ; 1 3 + pmulhrsw m7, m12 ; 4 5 + SWAP m0, m1, m3 + SWAP m4, m7 + pshufd m2, m6, q0000 + pshufd m3, m6, q1111 + pshufd m7, m6, q2222 + pshufd m6, m6, q3333 + mova [esp+0x30], m2 + mova [esp+0x40], m3 + mova [esp+0x50], m7 + mova [esp+0x60], m6 + %define m8 [esp+0x30] + %define m9 [esp+0x40] + %define m10 [esp+0x50] + %define m11 [esp+0x60] +%endif + psrldq m5, m4, 8 ; 5 _ + punpckhwd m2, m0, m1 ; 23 + punpcklwd m0, m1 ; 01 + punpcklwd m4, m5 ; 45 +.dy2_w4_loop: + pmaddwd m0, m8 ; a0 + pmaddwd m5, m2, m8 ; b0 + pmaddwd m2, m9 ; a1 + pmaddwd m7, m4, m9 ; b1 + pmaddwd m3, m4, m10 ; a2 + paddd m0, m13 + paddd m5, m13 + paddd m0, m2 + paddd m5, m7 + paddd m0, m3 + movu m6, [srcq+ssq*0] + movu m7, [srcq+ssq*1] + movu m3, [srcq+ssq*2] + movu m1, [srcq+ss3q ] + lea srcq, [srcq+ssq*4] + pshufb m6, m14 + pshufb m7, m14 + pshufb m3, m14 + pshufb m1, m14 + pmaddubsw m6, m15 + pmaddubsw m7, m15 + pmaddubsw m3, m15 + pmaddubsw m1, m15 + phaddw m6, m7 + phaddw m3, m1 + pmulhrsw m6, m12 ; 6 7 + pmulhrsw m3, m12 ; 8 9 + psrldq m7, m6, 8 + psrldq m1, m3, 8 + punpcklwd m6, m7 ; 67 + punpcklwd m3, m1 ; 89 + mova m2, m6 + pmaddwd m1, m6, m10 ; b2 + pmaddwd m6, m11 ; a3 + pmaddwd m7, m3, m11 ; b3 + paddd m5, m1 + paddd m0, m6 + paddd m5, m7 + psrad m0, rndshift + psrad m5, rndshift + packssdw m0, m5 +%ifidn %1, put + packuswb m0, m0 + psrldq m1, m0, 4 + movd [dstq+dsq*0], m0 + movd [dstq+dsq*1], m1 + lea dstq, [dstq+dsq*2] +%else + mova [tmpq], m0 + add tmpq, 16 +%endif + mova m0, m4 + mova m4, m3 + sub hd, 2 + jg .dy2_w4_loop + MC_8TAP_SCALED_RET +INIT_XMM ssse3 +.dy2_w8: + mov dword [rsp+0x90], 1 + movifprep tmp_stridem, 16 + jmp .dy2_w_start +.dy2_w16: + mov dword [rsp+0x90], 2 + movifprep tmp_stridem, 32 + jmp .dy2_w_start +.dy2_w32: + mov dword [rsp+0x90], 4 + movifprep tmp_stridem, 64 + jmp .dy2_w_start +.dy2_w64: + mov dword [rsp+0x90], 8 + movifprep tmp_stridem, 128 + jmp .dy2_w_start +.dy2_w128: + mov dword [rsp+0x90], 16 + movifprep tmp_stridem, 256 +.dy2_w_start: + mov myd, mym +%ifidn %1, put + movifnidn dsm, dsq +%endif +%if ARCH_X86_64 + shr t0d, 16 + sub srcq, 3 + shr myd, 6 + mov r4d, 64 << 24 + lea myd, [t1+myq] + cmovnz r4q, [base+subpel_filters+myq*8] + movd m15, t0d +%else + %define m10 [base+pd_0x3ff] + %define m11 [base+pd_0x4000] + %define m8 m0 + %define m9 m1 + %xdefine m14 m4 + %xdefine m15 m3 + %if isprep + %define tmpq r0 + %define ssq ssm + %else + %define dstq r0 + %endif + mov r5, [esp+0x1f0] + mov r3, [esp+0x1f4] + shr r5, 16 + sub srcq, 3 + movd m15, r5 + xor r5, r5 + shr myd, 6 + lea r3, [r3+myd] + mov r4, 64 << 24 + cmovnz r4, [base+subpel_filters+r3*8+0] + cmovnz r5, [base+subpel_filters+r3*8+4] + mov r0, r0m + mov r3, r3m +%endif + pslld m7, m8, 2 ; dx*4 + pmaddwd m8, [base+rescale_mul] ; dx*[0-3] + pshufd m15, m15, q0000 + paddd m14, m8 ; mx+dx*[0-3] +%if ARCH_X86_64 + movq m3, r4q + punpcklbw m3, m3 + psraw m3, 8 +%else + movd m5, r4 + movd m6, r5 + punpckldq m5, m6 + punpcklbw m5, m5 + psraw m5, 8 + SWAP m3, m5 +%endif + mova [rsp+0x100], m7 + mova [rsp+0x120], m15 + mov [rsp+0x098], srcq + mov [rsp+0x130], r0q ; dstq / tmpq + pshufd m0, m3, q0000 + pshufd m1, m3, q1111 + pshufd m2, m3, q2222 + pshufd m3, m3, q3333 + mova [rsp+0x140], m0 + mova [rsp+0x150], m1 + mova [rsp+0x160], m2 + mova [rsp+0x170], m3 +%if ARCH_X86_64 && UNIX64 + mov hm, hd +%elif ARCH_X86_32 + SWAP m5, m3 + mov r5, hm + mov [esp+0x134], r5 +%endif + jmp .dy2_hloop +.dy2_hloop_prep: + dec dword [rsp+0x090] + jz .ret +%if ARCH_X86_64 + add qword [rsp+0x130], 8*(isprep+1) + mov hd, hm +%else + add dword [rsp+0x130], 8*(isprep+1) + mov r5, [esp+0x134] + mov r0, [esp+0x130] +%endif + mova m7, [rsp+0x100] + mova m14, [rsp+0x110] +%if ARCH_X86_64 + mova m10, [base+pd_0x3ff] +%else + %define m10 [base+pd_0x3ff] +%endif + mova m15, [rsp+0x120] + mov srcq, [rsp+0x098] +%if ARCH_X86_64 + mov r0q, [rsp+0x130] ; dstq / tmpq +%else + mov hm, r5 + mov r0m, r0 + mov r3, r3m +%endif + paddd m14, m7 +.dy2_hloop: + pxor m9, m9 +%if ARCH_X86_64 + mova m11, [base+pq_0x40000000] +%else + %define m11 [base+pq_0x40000000] +%endif + psrld m2, m14, 10 + mova [rsp], m2 + pand m6, m14, m10 + psrld m6, 6 + paddd m5, m15, m6 + pcmpeqd m6, m9 + psrldq m2, m5, 8 +%if ARCH_X86_64 + movd r4d, m5 + movd r6d, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r7d, m5 + movd r9d, m2 + movq m0, [base+subpel_filters+r4*8] + movq m1, [base+subpel_filters+r6*8] + movhps m0, [base+subpel_filters+r7*8] + movhps m1, [base+subpel_filters+r9*8] +%else + movd r0, m5 + movd rX, m2 + psrldq m5, 4 + psrldq m2, 4 + movd r4, m5 + movd r5, m2 + movq m0, [base+subpel_filters+r0*8] + movq m1, [base+subpel_filters+rX*8] + movhps m0, [base+subpel_filters+r4*8] + movhps m1, [base+subpel_filters+r5*8] + pxor m2, m2 + %define m9 m2 +%endif + paddd m14, m7 ; mx+dx*[4-7] + pand m5, m14, m10 + psrld m5, 6 + paddd m15, m5 + pcmpeqd m5, m9 + mova [rsp+0x110], m14 + psrldq m4, m15, 8 +%if ARCH_X86_64 + movd r10d, m15 + movd r11d, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r13d, m15 + movd rXd, m4 + movq m2, [base+subpel_filters+r10*8] + movq m3, [base+subpel_filters+r11*8] + movhps m2, [base+subpel_filters+r13*8] + movhps m3, [base+subpel_filters+ rX*8] + psrld m14, 10 + psrldq m4, m14, 8 + movd r10d, m14 + movd r11d, m4 + psrldq m14, 4 + psrldq m4, 4 + movd r13d, m14 + movd rXd, m4 + mov r4d, [rsp+ 0] + mov r6d, [rsp+ 8] + mov r7d, [rsp+ 4] + mov r9d, [rsp+12] + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m8, m11, m4 + pand m9, m11, m6 + pand m15, m11, m7 + pand m11, m11, m5 + pandn m4, m0 + pandn m6, m1 + pandn m7, m2 + pandn m5, m3 + por m8, m4 + por m9, m6 + por m15, m7 + por m11, m5 + mova [rsp+0x10], m8 + mova [rsp+0x20], m9 + mova [rsp+0x30], m15 + mova [rsp+0x40], m11 + MC_8TAP_SCALED_H 1, 2, 3, 4, 5, 6, 7, 10, 8, 9, 15, 11 ; 0-1 + mova [rsp+0x50], m1 + mova [rsp+0x60], m2 + MC_8TAP_SCALED_H 3, 4, 5, 6, 1, 2, 7, 10, 8, 9, 15, 11 ; 2-3 + mova [rsp+0x70], m3 + mova [rsp+0x80], m4 + MC_8TAP_SCALED_H 5, 6, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 4-5 + MC_8TAP_SCALED_H 0,14, 1, 2, 3, 4, 7, 10, 8, 9, 15, 11 ; 6-7 + SWAP m7, m0 + SWAP m8, m14 + mova m1, [rsp+0x50] + mova m2, [rsp+0x60] + mova m3, [rsp+0x70] + mova m15, [rsp+0x80] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m8 ; 67a + punpckhwd m7, m8 ; 67b + SWAP m14, m8 + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m15; 23a + punpckhwd m3, m15 ; 23b + mova [rsp+0x50], m4 + mova [rsp+0x60], m5 + mova [rsp+0x70], m6 + mova [rsp+0x80], m7 +%else + movd r0, m15 + movd rX, m4 + psrldq m15, 4 + psrldq m4, 4 + movd r4, m15 + movd r5, m4 + mova m14, [esp+0x110] + movq m2, [base+subpel_filters+r0*8] + movq m3, [base+subpel_filters+rX*8] + movhps m2, [base+subpel_filters+r4*8] + movhps m3, [base+subpel_filters+r5*8] + psrld m14, 10 + mova [esp+16], m14 + mov r0, [esp+ 0] + mov rX, [esp+ 8] + mov r4, [esp+ 4] + mov r5, [esp+12] + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + pshufd m4, m6, q1100 + pshufd m6, m6, q3322 + pshufd m7, m5, q1100 + pshufd m5, m5, q3322 + pand m0, m11, m4 + pand m1, m11, m6 + pand m2, m11, m7 + pand m3, m11, m5 + pandn m4, [esp+0x20] + pandn m6, [esp+0x30] + pandn m7, [esp+0x40] + pandn m5, [esp+0x50] + por m0, m4 + por m1, m6 + por m2, m7 + por m3, m5 + mova [esp+0x20], m0 + mova [esp+0x30], m1 + mova [esp+0x40], m2 + mova [esp+0x50], m3 + MC_8TAP_SCALED_H 0x20, 0x60, 0 ; 0-1 + MC_8TAP_SCALED_H 0x20, 0x180 ; 2-3 + MC_8TAP_SCALED_H 0x20, 0x1a0 ; 4-5 + MC_8TAP_SCALED_H 0x20, 0x1c0 ; 6-7 + mova m5, [esp+0x1a0] + mova m6, [esp+0x1b0] + mova m7, [esp+0x1c0] + mova m0, [esp+0x1d0] + punpcklwd m4, m5, m6 ; 45a + punpckhwd m5, m6 ; 45b + punpcklwd m6, m7, m0 ; 67a + punpckhwd m7, m0 ; 67b + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 + mova [esp+0x1d0], m7 + mova m1, [esp+0x060] + mova m2, [esp+0x070] + mova m3, [esp+0x180] + mova m4, [esp+0x190] + punpcklwd m0, m1, m2 ; 01a + punpckhwd m1, m2 ; 01b + punpcklwd m2, m3, m4 ; 23a + punpckhwd m3, m4 ; 23b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + %define m8 [esp+0x140] + %define m9 [esp+0x150] + %define m10 [esp+0x160] + %define m11 [esp+0x170] +%endif +.dy2_vloop: +%if ARCH_X86_32 + mov r0, r0m +%endif + pmaddwd m4, m0, m8 + pmaddwd m5, m1, m8 + pmaddwd m6, m2, m9 + pmaddwd m7, m3, m9 + paddd m4, m13 + paddd m5, m13 + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x50], m10 + pmaddwd m7, [rsp+0x60], m10 +%else + pmaddwd m6, [esp+0x1a0], m10 + pmaddwd m7, [esp+0x1b0], m10 +%endif + paddd m4, m6 + paddd m5, m7 +%if ARCH_X86_64 + pmaddwd m6, [rsp+0x70], m11 + pmaddwd m7, [rsp+0x80], m11 +%else + pmaddwd m6, [esp+0x1c0], m11 + pmaddwd m7, [esp+0x1d0], m11 +%endif + paddd m4, m6 + paddd m5, m7 + psrad m4, rndshift + psrad m5, rndshift + packssdw m4, m5 +%ifidn %1, put + packuswb m4, m4 + movq [dstq], m4 + add dstq, dsm +%else + mova [tmpq], m4 + add tmpq, tmp_stridem +%endif +%if ARCH_X86_32 + mov r0m, r0 +%endif + dec hd + jz .dy2_hloop_prep +%if ARCH_X86_64 + mova m8, [rsp+0x10] + mova m9, [rsp+0x20] + mova m10, [rsp+0x30] + mova m11, [rsp+0x40] + mova m0, m2 ; 01a + mova m1, m3 ; 01b + MC_8TAP_SCALED_H 2, 6, 3, 4, 5, 7, 14, 15, 8, 9, 10, 11 + mova m3, [rsp+0x50] ; 23a + mova m4, [rsp+0x60] ; 23b + mova m5, [rsp+0x70] ; 45a + mova m7, [rsp+0x80] ; 45b + mova m8, [rsp+0x140] + mova m9, [rsp+0x150] + mova m10, [rsp+0x160] + mova m11, [rsp+0x170] + punpcklwd m14, m2, m6 ; 67a + punpckhwd m2, m6 ; 67b + mova [rsp+0x50], m5 + mova [rsp+0x60], m7 + mova [rsp+0x70], m14 + mova [rsp+0x80], m2 + mova m2, m3 + mova m3, m4 +%else + MC_8TAP_SCALED_H 0x20, 0 + punpcklwd m6, m0, m4 + punpckhwd m7, m0, m4 + mova m0, [esp+0x180] ; 01a + mova m1, [esp+0x190] ; 01b + mova m2, [rsp+0x1a0] ; 23a + mova m3, [esp+0x1b0] ; 23b + mova m4, [esp+0x1c0] ; 45a + mova m5, [esp+0x1d0] ; 45b + mova [esp+0x180], m2 + mova [esp+0x190], m3 + mova [esp+0x1a0], m4 + mova [esp+0x1b0], m5 + mova [esp+0x1c0], m6 ; 67a + mova [esp+0x1d0], m7 ; 67b +%endif + jmp .dy2_vloop +.ret: + MC_8TAP_SCALED_RET 0 +%if ARCH_X86_32 && !isprep && required_stack_alignment > STACK_ALIGNMENT + %define r0m [rstk+stack_offset+ 4] + %define r1m [rstk+stack_offset+ 8] + %define r2m [rstk+stack_offset+12] + %define r3m [rstk+stack_offset+16] +%endif +%undef isprep +%endmacro + +%macro BILIN_SCALED_FN 1 +cglobal %1_bilin_scaled_8bpc + mov t0d, (5*15 << 16) | 5*15 + mov t1d, (5*15 << 16) | 5*15 + jmp mangle(private_prefix %+ _%1_8tap_scaled_8bpc %+ SUFFIX) +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 5 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 8 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN put +FN put_8tap_scaled, sharp, SHARP, SHARP +FN put_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN put_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN put_8tap_scaled, smooth, SMOOTH, SMOOTH +FN put_8tap_scaled, sharp_regular, SHARP, REGULAR +FN put_8tap_scaled, regular_sharp, REGULAR, SHARP +FN put_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN put_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN put_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED put + +%if WIN64 +DECLARE_REG_TMP 5, 4 +%elif ARCH_X86_64 +DECLARE_REG_TMP 6, 7 +%else +DECLARE_REG_TMP 1, 2 +%endif +BILIN_SCALED_FN prep +FN prep_8tap_scaled, sharp, SHARP, SHARP +FN prep_8tap_scaled, sharp_smooth, SHARP, SMOOTH +FN prep_8tap_scaled, smooth_sharp, SMOOTH, SHARP +FN prep_8tap_scaled, smooth, SMOOTH, SMOOTH +FN prep_8tap_scaled, sharp_regular, SHARP, REGULAR +FN prep_8tap_scaled, regular_sharp, REGULAR, SHARP +FN prep_8tap_scaled, smooth_regular, SMOOTH, REGULAR +FN prep_8tap_scaled, regular_smooth, REGULAR, SMOOTH +FN prep_8tap_scaled, regular, REGULAR, REGULAR +MC_8TAP_SCALED prep + +%if ARCH_X86_32 + %macro SAVE_ALPHA_BETA 0 + mov alpham, alphad + mov betam, betad + %endmacro + + %macro SAVE_DELTA_GAMMA 0 + mov deltam, deltad + mov gammam, gammad + %endmacro + + %macro LOAD_ALPHA_BETA_MX 0 + mov mym, myd + mov alphad, alpham + mov betad, betam + mov mxd, mxm + %endmacro + + %macro LOAD_DELTA_GAMMA_MY 0 + mov mxm, mxd + mov deltad, deltam + mov gammad, gammam + mov myd, mym + %endmacro + + %define PIC_reg r2 + %define PIC_base_offset $$ + %define PIC_sym(sym) (PIC_reg+(sym)-PIC_base_offset) +%else + %define SAVE_ALPHA_BETA + %define SAVE_DELTA_GAMMA + %define PIC_sym(sym) sym +%endif + +%if ARCH_X86_32 + %if STACK_ALIGNMENT < required_stack_alignment + %assign copy_args 8*4 + %else + %assign copy_args 0 + %endif +%endif + +%macro RELOC_ARGS 0 + %if copy_args + mov r0, r0m + mov r1, r1m + mov r2, r2m + mov r3, r3m + mov r5, r5m + mov dstm, r0 + mov dsm, r1 + mov srcm, r2 + mov ssm, r3 + mov mxm, r5 + mov r0, r6m + mov mym, r0 + %endif +%endmacro + +%macro BLENDHWDW 2 ; blend high words from dwords, src1, src2 + %if cpuflag(sse4) + pblendw %1, %2, 0xAA + %else + pand %2, m10 + por %1, %2 + %endif +%endmacro + +%macro WARP_V 10 ; dst0, dst1, 0, 2, 4, 6, 1, 3, 5, 7 + %if ARCH_X86_32 + %define m8 m4 + %define m9 m5 + %define m14 m6 + %define m15 m7 + %define m11 m7 + %endif + %if notcpuflag(ssse3) || ARCH_X86_32 + pxor m11, m11 + %endif + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq m2, [filterq+myq *8] ; a + movq m8, [filterq+tmp1q*8] ; e + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+deltaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movq m3, [filterq+tmp2q*8] ; b + movq m0, [filterq+tmp1q*8] ; f + punpcklwd m2, m3 + punpcklwd m8, m0 + lea tmp1d, [myq+deltaq*4] + lea tmp2d, [myq+deltaq*1] + shr myd, 10 + shr tmp1d, 10 + movq m0, [filterq+myq *8] ; c + movq m9, [filterq+tmp1q*8] ; g + lea tmp1d, [tmp2q+deltaq*4] + lea myd, [tmp2q+gammaq] ; my += gamma + shr tmp2d, 10 + shr tmp1d, 10 + movq m3, [filterq+tmp2q*8] ; d + movq m1, [filterq+tmp1q*8] ; h + punpcklwd m0, m3 + punpcklwd m9, m1 + punpckldq m1, m2, m0 + punpckhdq m2, m0 + punpcklbw m0, m11, m1 ; a0 a2 b0 b2 c0 c2 d0 d2 << 8 + punpckhbw m3, m11, m1 ; a4 a6 b4 b6 c4 c6 d4 d6 << 8 + punpcklbw m1, m11, m2 ; a1 a3 b1 b3 c1 c3 d1 d3 << 8 + punpckhbw m14, m11, m2 ; a5 a7 b5 b7 c5 c7 d5 d7 << 8 + pmaddwd m0, %3 + pmaddwd m3, %5 + pmaddwd m1, %7 + pmaddwd m14, %9 + paddd m0, m3 + paddd m1, m14 + paddd m0, m1 + mova %1, m0 + %if ARCH_X86_64 + SWAP m3, m14 + %endif + punpckldq m0, m8, m9 + punpckhdq m8, m9 + punpcklbw m1, m11, m0 ; e0 e2 f0 f2 g0 g2 h0 h2 << 8 + punpckhbw m14, m11, m0 ; e4 e6 f4 f6 g4 g6 h4 h6 << 8 + punpcklbw m2, m11, m8 ; e1 e3 f1 f3 g1 g3 h1 h3 << 8 + punpckhbw m15, m11, m8 ; e5 e7 f5 f7 g5 g7 h5 h7 << 8 + pmaddwd m1, %4 + pmaddwd m14, %6 + pmaddwd m2, %8 + pmaddwd m15, %10 + paddd m1, m14 + paddd m2, m15 + paddd m1, m2 + mova %2, m1 + %if ARCH_X86_64 + SWAP m14, m3 + %endif +%endmacro + +%if ARCH_X86_64 + %define counterd r4d +%else + %if copy_args == 0 + %define counterd dword r4m + %else + %define counterd dword [esp+stack_size-4*7] + %endif +%endif + +%macro WARP_AFFINE_8X8T 0 +%if ARCH_X86_64 +cglobal warp_affine_8x8t_8bpc, 6, 14, 16, 0x90, tmp, ts +%else +cglobal warp_affine_8x8t_8bpc, 0, 7, 16, -0x130-copy_args, tmp, ts + %if copy_args + %define tmpm [esp+stack_size-4*1] + %define tsm [esp+stack_size-4*2] + %endif +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).main +.loop: +%if ARCH_X86_32 + %define m12 m4 + %define m13 m5 + %define m14 m6 + %define m15 m7 + mova m12, [esp+0xC0] + mova m13, [esp+0xD0] + mova m14, [esp+0xE0] + mova m15, [esp+0xF0] +%endif +%if cpuflag(ssse3) + psrad m12, 13 + psrad m13, 13 + psrad m14, 13 + psrad m15, 13 + packssdw m12, m13 + packssdw m14, m15 + mova m13, [PIC_sym(pw_8192)] + pmulhrsw m12, m13 ; (x + (1 << 6)) >> 7 + pmulhrsw m14, m13 +%else + %if ARCH_X86_32 + %define m10 m0 + %endif + mova m10, [PIC_sym(pd_16384)] + paddd m12, m10 + paddd m13, m10 + paddd m14, m10 + paddd m15, m10 + psrad m12, 15 + psrad m13, 15 + psrad m14, 15 + psrad m15, 15 + packssdw m12, m13 + packssdw m14, m15 +%endif + mova [tmpq+tsq*0], m12 + mova [tmpq+tsq*2], m14 + dec counterd + jz mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).end +%if ARCH_X86_32 + mov tmpm, tmpd + mov r0, [esp+0x100] + mov r1, [esp+0x104] +%endif + call mangle(private_prefix %+ _warp_affine_8x8_8bpc_%+cpuname).main2 + lea tmpq, [tmpq+tsq*4] + jmp .loop +%endmacro + +%macro WARP_AFFINE_8X8 0 +%if ARCH_X86_64 +cglobal warp_affine_8x8_8bpc, 6, 14, 16, 0x90, \ + dst, ds, src, ss, abcd, mx, tmp2, alpha, beta, \ + filter, tmp1, delta, my, gamma +%else +cglobal warp_affine_8x8_8bpc, 0, 7, 16, -0x130-copy_args, \ + dst, ds, src, ss, abcd, mx, tmp2, alpha, beta, \ + filter, tmp1, delta, my, gamma + %define alphaq r0 + %define alphad r0 + %define alpham [esp+gprsize+0x100] + %define betaq r1 + %define betad r1 + %define betam [esp+gprsize+0x104] + %define deltaq r0 + %define deltad r0 + %define deltam [esp+gprsize+0x108] + %define gammaq r1 + %define gammad r1 + %define gammam [esp+gprsize+0x10C] + %define filterq r3 + %define tmp1q r4 + %define tmp1d r4 + %define tmp1m [esp+gprsize+0x110] + %define myq r5 + %define myd r5 + %define mym r6m + %if copy_args + %define dstm [esp+stack_size-4*1] + %define dsm [esp+stack_size-4*2] + %define srcm [esp+stack_size-4*3] + %define ssm [esp+stack_size-4*4] + %define mxm [esp+stack_size-4*5] + %define mym [esp+stack_size-4*6] + %endif +%endif + call .main + jmp .start +.loop: +%if ARCH_X86_32 + mov dstm, dstd + mov alphad, [esp+0x100] + mov betad, [esp+0x104] +%endif + call .main2 + lea dstq, [dstq+dsq*2] +.start: +%if notcpuflag(sse4) + %if cpuflag(ssse3) + %define roundval pw_8192 + %else + %define roundval pd_262144 + %endif + %if ARCH_X86_64 + mova m10, [PIC_sym(roundval)] + %else + %define m10 [PIC_sym(roundval)] + %endif +%endif +%if ARCH_X86_32 + %define m12 m5 + %define m13 m6 + mova m12, [esp+0xC0] + mova m13, [esp+0xD0] +%endif +%if cpuflag(sse4) + %if ARCH_X86_32 + %define m11 m4 + pxor m11, m11 + %endif + psrad m12, 18 + psrad m13, 18 + packusdw m12, m13 + pavgw m12, m11 ; (x + (1 << 10)) >> 11 +%else + %if cpuflag(ssse3) + psrad m12, 17 + psrad m13, 17 + packssdw m12, m13 + pmulhrsw m12, m10 + %else + paddd m12, m10 + paddd m13, m10 + psrad m12, 19 + psrad m13, 19 + packssdw m12, m13 + %endif +%endif +%if ARCH_X86_32 + %define m14 m6 + %define m15 m7 + mova m14, [esp+0xE0] + mova m15, [esp+0xF0] +%endif +%if cpuflag(sse4) + psrad m14, 18 + psrad m15, 18 + packusdw m14, m15 + pavgw m14, m11 ; (x + (1 << 10)) >> 11 +%else + %if cpuflag(ssse3) + psrad m14, 17 + psrad m15, 17 + packssdw m14, m15 + pmulhrsw m14, m10 + %else + paddd m14, m10 + paddd m15, m10 + psrad m14, 19 + psrad m15, 19 + packssdw m14, m15 + %endif +%endif + packuswb m12, m14 + movq [dstq+dsq*0], m12 + movhps [dstq+dsq*1], m12 + dec counterd + jg .loop +.end: + RET +ALIGN function_align +.main: +%assign stack_offset stack_offset+gprsize +%if ARCH_X86_32 + %assign stack_size stack_size+4 + %if copy_args + %assign stack_offset stack_offset-4 + %endif + RELOC_ARGS + LEA PIC_reg, $$ + %define PIC_mem [esp+gprsize+0x114] + mov abcdd, abcdm + %if copy_args == 0 + mov ssd, ssm + mov mxd, mxm + %endif + mov PIC_mem, PIC_reg + mov srcd, srcm +%endif + movsx deltad, word [abcdq+2*2] + movsx gammad, word [abcdq+2*3] + lea tmp1d, [deltaq*3] + sub gammad, tmp1d ; gamma -= delta*3 + SAVE_DELTA_GAMMA +%if ARCH_X86_32 + mov abcdd, abcdm +%endif + movsx alphad, word [abcdq+2*0] + movsx betad, word [abcdq+2*1] + lea tmp1q, [ssq*3+3] + add mxd, 512+(64<<10) + lea tmp2d, [alphaq*3] + sub srcq, tmp1q ; src -= src_stride*3 + 3 +%if ARCH_X86_32 + mov srcm, srcd + mov PIC_reg, PIC_mem +%endif + sub betad, tmp2d ; beta -= alpha*3 + lea filterq, [PIC_sym(mc_warp_filter2)] +%if ARCH_X86_64 + mov myd, r6m + %if cpuflag(ssse3) + pxor m11, m11 + %endif +%endif + call .h + psrld m2, m0, 16 + psrld m3, m1, 16 +%if ARCH_X86_32 + %if notcpuflag(ssse3) + mova [esp+gprsize+0x00], m2 + %endif + mova [esp+gprsize+0x10], m3 +%endif + call .h + psrld m4, m0, 16 + psrld m5, m1, 16 +%if ARCH_X86_32 + mova [esp+gprsize+0x20], m4 + mova [esp+gprsize+0x30], m5 +%endif + call .h +%if ARCH_X86_64 + %define blendmask [rsp+gprsize+0x80] +%else + %if notcpuflag(ssse3) + mova m2, [esp+gprsize+0x00] + %endif + mova m3, [esp+gprsize+0x10] + %define blendmask [esp+gprsize+0x120] + %define m10 m7 +%endif + pcmpeqd m10, m10 + pslld m10, 16 + mova blendmask, m10 + BLENDHWDW m2, m0 ; 0 + BLENDHWDW m3, m1 ; 2 + mova [rsp+gprsize+0x00], m2 + mova [rsp+gprsize+0x10], m3 + call .h +%if ARCH_X86_32 + mova m4, [esp+gprsize+0x20] + mova m5, [esp+gprsize+0x30] +%endif + mova m10, blendmask + BLENDHWDW m4, m0 ; 1 + BLENDHWDW m5, m1 ; 3 + mova [rsp+gprsize+0x20], m4 + mova [rsp+gprsize+0x30], m5 + call .h +%if ARCH_X86_32 + %if notcpuflag(ssse3) + mova m2, [esp+gprsize+0x00] + %endif + mova m3, [esp+gprsize+0x10] + %define m10 m5 +%endif + psrld m6, m2, 16 + psrld m7, m3, 16 + mova m10, blendmask + BLENDHWDW m6, m0 ; 2 + BLENDHWDW m7, m1 ; 4 + mova [rsp+gprsize+0x40], m6 + mova [rsp+gprsize+0x50], m7 + call .h +%if ARCH_X86_32 + mova m4, [esp+gprsize+0x20] + mova m5, [esp+gprsize+0x30] +%endif + psrld m2, m4, 16 + psrld m3, m5, 16 + mova m10, blendmask + BLENDHWDW m2, m0 ; 3 + BLENDHWDW m3, m1 ; 5 + mova [rsp+gprsize+0x60], m2 + mova [rsp+gprsize+0x70], m3 + call .h +%if ARCH_X86_32 + mova m6, [esp+gprsize+0x40] + mova m7, [esp+gprsize+0x50] + %define m10 m7 +%endif + psrld m4, m6, 16 + psrld m5, m7, 16 + mova m10, blendmask + BLENDHWDW m4, m0 ; 4 + BLENDHWDW m5, m1 ; 6 +%if ARCH_X86_64 + add myd, 512+(64<<10) + mova m6, m2 + mova m7, m3 +%else + mova [esp+gprsize+0x80], m4 + mova [esp+gprsize+0x90], m5 + add dword mym, 512+(64<<10) +%endif + mov counterd, 4 + SAVE_ALPHA_BETA +.main2: + call .h +%if ARCH_X86_32 + mova m6, [esp+gprsize+0x60] + mova m7, [esp+gprsize+0x70] + %define m10 m5 +%endif + psrld m6, 16 + psrld m7, 16 + mova m10, blendmask + BLENDHWDW m6, m0 ; 5 + BLENDHWDW m7, m1 ; 7 +%if ARCH_X86_64 + WARP_V m12, m13, [rsp+gprsize+0x00], [rsp+gprsize+0x10], \ + m4, m5, \ + [rsp+gprsize+0x20], [rsp+gprsize+0x30], \ + m6, m7 +%else + mova [esp+gprsize+0xA0], m6 + mova [esp+gprsize+0xB0], m7 + LOAD_DELTA_GAMMA_MY + WARP_V [esp+gprsize+0xC0], [esp+gprsize+0xD0], \ + [esp+gprsize+0x00], [esp+gprsize+0x10], \ + [esp+gprsize+0x80], [esp+gprsize+0x90], \ + [esp+gprsize+0x20], [esp+gprsize+0x30], \ + [esp+gprsize+0xA0], [esp+gprsize+0xB0] + LOAD_ALPHA_BETA_MX +%endif + call .h + mova m2, [rsp+gprsize+0x40] + mova m3, [rsp+gprsize+0x50] +%if ARCH_X86_32 + mova m4, [rsp+gprsize+0x80] + mova m5, [rsp+gprsize+0x90] + %define m10 m7 +%endif + mova [rsp+gprsize+0x00], m2 + mova [rsp+gprsize+0x10], m3 + mova [rsp+gprsize+0x40], m4 + mova [rsp+gprsize+0x50], m5 + psrld m4, 16 + psrld m5, 16 + mova m10, blendmask + BLENDHWDW m4, m0 ; 6 + BLENDHWDW m5, m1 ; 8 +%if ARCH_X86_64 + WARP_V m14, m15, [rsp+gprsize+0x20], [rsp+gprsize+0x30], \ + m6, m7, \ + [rsp+gprsize+0x00], [rsp+gprsize+0x10], \ + m4, m5 +%else + mova [esp+gprsize+0x80], m4 + mova [esp+gprsize+0x90], m5 + LOAD_DELTA_GAMMA_MY + WARP_V [esp+gprsize+0xE0], [esp+gprsize+0xF0], \ + [esp+gprsize+0x20], [esp+gprsize+0x30], \ + [esp+gprsize+0xA0], [esp+gprsize+0xB0], \ + [esp+gprsize+0x00], [esp+gprsize+0x10], \ + [esp+gprsize+0x80], [esp+gprsize+0x90] + mov mym, myd + mov dstd, dstm + mov dsd, dsm + mov mxd, mxm +%endif + mova m2, [rsp+gprsize+0x60] + mova m3, [rsp+gprsize+0x70] +%if ARCH_X86_32 + mova m6, [esp+gprsize+0xA0] + mova m7, [esp+gprsize+0xB0] +%endif + mova [rsp+gprsize+0x20], m2 + mova [rsp+gprsize+0x30], m3 + mova [rsp+gprsize+0x60], m6 + mova [rsp+gprsize+0x70], m7 + ret +ALIGN function_align +.h: +%if ARCH_X86_32 + %define m8 m3 + %define m9 m4 + %define m10 m5 + %define m14 m6 + %define m15 m7 +%endif + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] +%if ARCH_X86_32 + %assign stack_offset stack_offset+4 + %assign stack_size stack_size+4 + %define PIC_mem [esp+gprsize*2+0x114] + mov PIC_mem, PIC_reg + mov srcd, srcm +%endif + movu m10, [srcq] +%if ARCH_X86_32 + add srcd, ssm + mov srcm, srcd + mov PIC_reg, PIC_mem +%else + add srcq, ssq +%endif + shr mxd, 10 + shr tmp1d, 10 + movq m1, [filterq+mxq *8] ; 0 X + movq m8, [filterq+tmp1q*8] ; 4 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+alphaq*1] + shr tmp2d, 10 + shr tmp1d, 10 + movhps m1, [filterq+tmp2q*8] ; 0 1 + movhps m8, [filterq+tmp1q*8] ; 4 5 + lea tmp1d, [mxq+alphaq*4] + lea tmp2d, [mxq+alphaq*1] + shr mxd, 10 + shr tmp1d, 10 +%if cpuflag(ssse3) + movq m14, [filterq+mxq *8] ; 2 X + movq m9, [filterq+tmp1q*8] ; 6 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + movhps m14, [filterq+tmp2q*8] ; 2 3 + movhps m9, [filterq+tmp1q*8] ; 6 7 + pshufb m0, m10, [PIC_sym(warp_8x8_shufA)] + pmaddubsw m0, m1 + pshufb m1, m10, [PIC_sym(warp_8x8_shufB)] + pmaddubsw m1, m8 + pshufb m15, m10, [PIC_sym(warp_8x8_shufC)] + pmaddubsw m15, m14 + pshufb m10, m10, [PIC_sym(warp_8x8_shufD)] + pmaddubsw m10, m9 + phaddw m0, m15 + phaddw m1, m10 +%else + %if ARCH_X86_32 + %define m11 m2 + %endif + pcmpeqw m0, m0 + psrlw m14, m0, 8 + psrlw m15, m10, 8 ; 01 03 05 07 09 11 13 15 + pand m14, m10 ; 00 02 04 06 08 10 12 14 + packuswb m14, m15 ; 00 02 04 06 08 10 12 14 01 03 05 07 09 11 13 15 + psrldq m9, m0, 4 + pshufd m0, m14, q0220 + pand m0, m9 + psrldq m14, 1 ; 02 04 06 08 10 12 14 01 03 05 07 09 11 13 15 __ + pslldq m15, m14, 12 + por m0, m15 ; shufA + psrlw m15, m0, 8 + psraw m11, m1, 8 + psllw m0, 8 + psllw m1, 8 + psrlw m0, 8 + psraw m1, 8 + pmullw m15, m11 + pmullw m0, m1 + paddw m0, m15 ; pmaddubsw m0, m1 + pshufd m15, m14, q0220 + pand m15, m9 + psrldq m14, 1 ; 04 06 08 10 12 14 01 03 05 07 09 11 13 15 __ __ + pslldq m1, m14, 12 + por m15, m1 ; shufC + pshufd m1, m14, q0220 + pand m1, m9 + psrldq m14, 1 ; 06 08 10 12 14 01 03 05 07 09 11 13 15 __ __ __ + pslldq m11, m14, 12 + por m1, m11 ; shufB + pshufd m10, m14, q0220 + pand m10, m9 + psrldq m14, 1 ; 08 10 12 14 01 03 05 07 09 11 13 15 __ __ __ __ + pslldq m14, m14, 12 + por m10, m14 ; shufD + psrlw m9, m1, 8 + psraw m11, m8, 8 + psllw m1, 8 + psllw m8, 8 + psrlw m1, 8 + psraw m8, 8 + pmullw m9, m11 + pmullw m1, m8 + paddw m1, m9 ; pmaddubsw m1, m8 + movq m14, [filterq+mxq *8] ; 2 X + movq m9, [filterq+tmp1q*8] ; 6 X + lea tmp1d, [tmp2q+alphaq*4] + lea mxd, [tmp2q+betaq] ; mx += beta + shr tmp2d, 10 + shr tmp1d, 10 + movhps m14, [filterq+tmp2q*8] ; 2 3 + movhps m9, [filterq+tmp1q*8] ; 6 7 + psrlw m8, m15, 8 + psraw m11, m14, 8 + psllw m15, 8 + psllw m14, 8 + psrlw m15, 8 + psraw m14, 8 + pmullw m8, m11 + pmullw m15, m14 + paddw m15, m8 ; pmaddubsw m15, m14 + psrlw m8, m10, 8 + psraw m11, m9, 8 + psllw m10, 8 + psllw m9, 8 + psrlw m10, 8 + psraw m9, 8 + pmullw m8, m11 + pmullw m10, m9 + paddw m10, m8 ; pmaddubsw m10, m9 + pslld m8, m0, 16 + pslld m9, m1, 16 + pslld m14, m15, 16 + pslld m11, m10, 16 + paddw m0, m8 + paddw m1, m9 + paddw m15, m14 + paddw m10, m11 + psrad m0, 16 + psrad m1, 16 + psrad m15, 16 + psrad m10, 16 + packssdw m0, m15 ; phaddw m0, m15 + packssdw m1, m10 ; phaddw m1, m10 +%endif + mova m14, [PIC_sym(pw_8192)] + mova m9, [PIC_sym(pd_32768)] + pmaddwd m0, m14 ; 17-bit intermediate, upshifted by 13 + pmaddwd m1, m14 + paddd m0, m9 ; rounded 14-bit result in upper 16 bits of dword + paddd m1, m9 + ret +%endmacro + +%if WIN64 +DECLARE_REG_TMP 6, 4 +%else +DECLARE_REG_TMP 6, 7 +%endif + +%macro BIDIR_FN 1 ; op + %1 0 + lea stride3q, [strideq*3] + jmp wq +.w4_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*4] +.w4: ; tile 4x + movd [dstq ], m0 ; copy dw[0] + pshuflw m1, m0, q1032 ; swap dw[1] and dw[0] + movd [dstq+strideq*1], m1 ; copy dw[1] + punpckhqdq m0, m0 ; swap dw[3,2] with dw[1,0] + movd [dstq+strideq*2], m0 ; dw[2] + psrlq m0, 32 ; shift right in dw[3] + movd [dstq+stride3q ], m0 ; copy + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq*2] +.w8: + movq [dstq ], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + %1_INC_PTR 2 + %1 0 + lea dstq, [dstq+strideq] +.w16: + mova [dstq ], m0 + dec hd + jg .w16_loop + RET +.w32_loop: + %1_INC_PTR 4 + %1 0 + lea dstq, [dstq+strideq] +.w32: + mova [dstq ], m0 + %1 2 + mova [dstq + 16 ], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + %1_INC_PTR 8 + %1 0 + add dstq, strideq +.w64: + %assign i 0 + %rep 4 + mova [dstq + i*16 ], m0 + %assign i i+1 + %if i < 4 + %1 2*i + %endif + %endrep + dec hd + jg .w64_loop + RET +.w128_loop: + %1_INC_PTR 16 + %1 0 + add dstq, strideq +.w128: + %assign i 0 + %rep 8 + mova [dstq + i*16 ], m0 + %assign i i+1 + %if i < 8 + %1 2*i + %endif + %endrep + dec hd + jg .w128_loop + RET +%endmacro + +%macro AVG 1 ; src_offset + ; writes AVG of tmp1 tmp2 uint16 coeffs into uint8 pixel + mova m0, [tmp1q+(%1+0)*mmsize] ; load 8 coef(2bytes) from tmp1 + paddw m0, [tmp2q+(%1+0)*mmsize] ; load/add 8 coef(2bytes) tmp2 + mova m1, [tmp1q+(%1+1)*mmsize] + paddw m1, [tmp2q+(%1+1)*mmsize] + pmulhrsw m0, m2 + pmulhrsw m1, m2 + packuswb m0, m1 ; pack/trunc 16 bits from m0 & m1 to 8 bit +%endmacro + +%macro AVG_INC_PTR 1 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +cglobal avg_8bpc, 4, 7, 3, dst, stride, tmp1, tmp2, w, h, stride3 + LEA r6, avg_ssse3_table + tzcnt wd, wm ; leading zeros + movifnidn hd, hm ; move h(stack) to h(register) if not already that register + movsxd wq, dword [r6+wq*4] ; push table entry matching the tile width (tzcnt) in widen reg + mova m2, [pw_1024+r6-avg_ssse3_table] ; fill m2 with shift/align + add wq, r6 + BIDIR_FN AVG + +%macro W_AVG 1 ; src_offset + ; (a * weight + b * (16 - weight) + 128) >> 8 + ; = ((a - b) * weight + (b << 4) + 128) >> 8 + ; = ((((a - b) * ((weight-16) << 12)) >> 16) + a + 8) >> 4 + ; = ((((b - a) * (-weight << 12)) >> 16) + b + 8) >> 4 + mova m2, [tmp1q+(%1+0)*mmsize] + mova m0, m2 + psubw m2, [tmp2q+(%1+0)*mmsize] + mova m3, [tmp1q+(%1+1)*mmsize] + mova m1, m3 + psubw m3, [tmp2q+(%1+1)*mmsize] + pmulhw m2, m4 + pmulhw m3, m4 + paddw m0, m2 + paddw m1, m3 + pmulhrsw m0, m5 + pmulhrsw m1, m5 + packuswb m0, m1 +%endmacro + +%define W_AVG_INC_PTR AVG_INC_PTR + +cglobal w_avg_8bpc, 4, 7, 6, dst, stride, tmp1, tmp2, w, h, stride3 + LEA r6, w_avg_ssse3_table + tzcnt wd, wm + movd m4, r6m + movifnidn hd, hm + pxor m0, m0 + movsxd wq, dword [r6+wq*4] + mova m5, [pw_2048+r6-w_avg_ssse3_table] + pshufb m4, m0 + psllw m4, 12 ; (weight-16) << 12 when interpreted as signed + add wq, r6 + cmp dword r6m, 7 + jg .weight_gt7 + mov r6, tmp1q + psubw m0, m4 + mov tmp1q, tmp2q + mova m4, m0 ; -weight + mov tmp2q, r6 +.weight_gt7: + BIDIR_FN W_AVG + +%macro MASK 1 ; src_offset + ; (a * m + b * (64 - m) + 512) >> 10 + ; = ((a - b) * m + (b << 6) + 512) >> 10 + ; = ((((b - a) * (-m << 10)) >> 16) + b + 8) >> 4 + mova m3, [maskq+(%1+0)*(mmsize/2)] + mova m0, [tmp2q+(%1+0)*mmsize] ; b + psubw m1, m0, [tmp1q+(%1+0)*mmsize] ; b - a + mova m6, m3 ; m + psubb m3, m4, m6 ; -m + paddw m1, m1 ; (b - a) << 1 + paddb m3, m3 ; -m << 1 + punpcklbw m2, m4, m3 ; -m << 9 (<< 8 when ext as uint16) + pmulhw m1, m2 ; (-m * (b - a)) << 10 + paddw m0, m1 ; + b + mova m1, [tmp2q+(%1+1)*mmsize] ; b + psubw m2, m1, [tmp1q+(%1+1)*mmsize] ; b - a + paddw m2, m2 ; (b - a) << 1 + mova m6, m3 ; (-m << 1) + punpckhbw m3, m4, m6 ; (-m << 9) + pmulhw m2, m3 ; (-m << 9) + paddw m1, m2 ; (-m * (b - a)) << 10 + pmulhrsw m0, m5 ; round + pmulhrsw m1, m5 ; round + packuswb m0, m1 ; interleave 16 -> 8 +%endmacro + +%macro MASK_INC_PTR 1 + add maskq, %1*mmsize/2 + add tmp1q, %1*mmsize + add tmp2q, %1*mmsize +%endmacro + +%if ARCH_X86_64 +cglobal mask_8bpc, 4, 8, 7, dst, stride, tmp1, tmp2, w, h, mask, stride3 + movifnidn hd, hm +%else +cglobal mask_8bpc, 4, 7, 7, dst, stride, tmp1, tmp2, w, mask, stride3 +%define hd dword r5m +%endif +%define base r6-mask_ssse3_table + LEA r6, mask_ssse3_table + tzcnt wd, wm + movsxd wq, dword [r6+wq*4] + pxor m4, m4 + mova m5, [base+pw_2048] + add wq, r6 + mov maskq, r6m + BIDIR_FN MASK +%undef hd + +%macro W_MASK_420_END 1-* +%rep %0 + call .main + paddw m2, [maskq+16*%1] + mova [maskq+16*%1], m2 + mova [dstq+strideq*1+16*(2*%1+0)], m0 + call .main + psubw m3, m7, m2 + psubw m1, m7, [maskq+16*%1] + psubw m3, [dstq+strideq*1+16*(2*%1+1)] + psrlw m1, 2 + psrlw m3, 2 + packuswb m1, m3 + mova [maskq+16*%1], m1 + mova [dstq+strideq*1+16*(2*%1+1)], m0 + %rotate 1 +%endrep +%endmacro + +%if UNIX64 +DECLARE_REG_TMP 7 +%else +DECLARE_REG_TMP 5 +%endif + +cglobal w_mask_420_8bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_420_ssse3_table + LEA t0, w_mask_420_ssse3_table + tzcnt wd, wm + mov r6d, r7m ; sign + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_2048] + movddup m7, [base+wm_420_sign+r6*8] ; 258 - sign + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pw_6903] ; ((64 - 38) << 8) + 255 - 8 + movifnidn hd, hm +%else + %define m8 [base+pw_6903] + %define hd dword hm +%endif + mov maskq, maskmp + call .main + jmp wq +.w4_loop: + call .main + add maskq, 4 + lea dstq, [dstq+strideq*2] +.w4: + pshufd m3, m2, q2020 + pshufd m2, m2, q3131 + psubw m1, m7, m3 + psubw m1, m2 + psrlw m1, 2 + packuswb m1, m1 + movd [maskq], m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + add maskq, 4 + lea dstq, [dstq+strideq*2] +.w8: + movhlps m3, m2 + psubw m1, m7, m2 + psubw m1, m3 + psrlw m1, 2 + packuswb m1, m1 + movd [maskq], m1 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + add maskq, 8 + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*1], m2 + mova [dstq+strideq*0], m0 + call .main + psubw m1, m7, [dstq+strideq*1] + psubw m1, m2 + psrlw m1, 2 + packuswb m1, m1 + movq [maskq], m1 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w32: + mova [maskq], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + W_MASK_420_END 0 + sub hd, 2 + jg .w32_loop + RET +.w64_loop: + call .main + add maskq, 16*2 + lea dstq, [dstq+strideq*2] +.w64: + mova [maskq+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + call .main + mova [maskq+16*1], m2 + mova [dstq+strideq*0+16*2], m0 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m0 + W_MASK_420_END 0, 1 + sub hd, 2 + jg .w64_loop + RET +.w128_loop: + call .main + add maskq, 16*4 + lea dstq, [dstq+strideq*2] +.w128: + mova [maskq+16*0], m2 + mova [dstq+strideq*0+16*0], m0 + call .main + mova [dstq+strideq*1+16*1], m2 + mova [dstq+strideq*0+16*1], m0 + call .main + mova [maskq+16*1], m2 + mova [dstq+strideq*0+16*2], m0 + call .main + mova [dstq+strideq*1+16*3], m2 + mova [dstq+strideq*0+16*3], m0 + call .main + mova [maskq+16*2], m2 + mova [dstq+strideq*0+16*4], m0 + call .main + mova [dstq+strideq*1+16*5], m2 + mova [dstq+strideq*0+16*5], m0 + call .main + mova [maskq+16*3], m2 + mova [dstq+strideq*0+16*6], m0 + call .main + mova [dstq+strideq*1+16*7], m2 + mova [dstq+strideq*0+16*7], m0 + W_MASK_420_END 0, 1, 2, 3 + sub hd, 2 + jg .w128_loop + RET +ALIGN function_align +.main: + mova m0, [tmp1q +16*0] + mova m3, [tmp1q+tmp2q+16*0] + mova m1, [tmp1q +16*1] + mova m4, [tmp1q+tmp2q+16*1] + add tmp1q, 16*2 + psubw m3, m0 + psubw m4, m1 + pabsw m5, m3 + psubusw m2, m8, m5 + psrlw m2, 8 ; 64 - m + psllw m5, m2, 10 + pmulhw m3, m5 + pabsw m5, m4 + paddw m0, m3 + psubusw m3, m8, m5 + psrlw m3, 8 + phaddw m2, m3 + psllw m3, 10 + pmulhw m4, m3 + paddw m1, m4 + pmulhrsw m0, m6 + pmulhrsw m1, m6 + packuswb m0, m1 + ret + +%macro W_MASK_422_BACKUP 1 ; mask_offset +%if ARCH_X86_64 + mova m10, m2 +%else + mova [maskq+16*%1], m2 +%endif +%endmacro + +%macro W_MASK_422_END 1 ; mask_offset +%if ARCH_X86_64 + packuswb m10, m2 + psubb m1, m7, m10 + pavgb m1, m9 +%else + mova m3, [maskq+16*%1] + packuswb m3, m2 + pxor m2, m2 + psubb m1, m7, m3 + pavgb m1, m2 +%endif + mova [maskq+16*%1], m1 +%endmacro + +cglobal w_mask_422_8bpc, 4, 7, 11, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_422_ssse3_table + LEA t0, w_mask_422_ssse3_table + tzcnt wd, wm + mov r6d, r7m ; sign + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_2048] + movddup m7, [base+wm_422_sign+r6*8] ; 128 - sign + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pw_6903] + pxor m9, m9 + movifnidn hd, hm +%else + add t0, w_mask_420_ssse3_table-w_mask_422_ssse3_table + %define hd dword hm +%endif + mov maskq, maskmp + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + jmp wq +.w4_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 8 + lea dstq, [dstq+strideq*2] +.w4: + packuswb m2, m2 + psubb m1, m7, m2 +%if ARCH_X86_64 + pavgb m1, m9 +%else + pxor m2, m2 + pavgb m1, m2 +%endif + movq [maskq], m1 + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w8: + W_MASK_422_BACKUP 0 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + lea dstq, [dstq+strideq*2] + W_MASK_422_END 0 + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 4 + jg .w8_loop + RET +.w16_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + lea dstq, [dstq+strideq*2] +.w16: + W_MASK_422_BACKUP 0 + mova [dstq+strideq*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16 + add dstq, strideq +.w32: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16*2 + add dstq, strideq +.w64: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 1 + mova [dstq+16*2], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 1 + mova [dstq+16*3], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + add maskq, 16*4 + add dstq, strideq +.w128: + W_MASK_422_BACKUP 0 + mova [dstq+16*0], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 0 + mova [dstq+16*1], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 1 + mova [dstq+16*2], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 1 + mova [dstq+16*3], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 2 + mova [dstq+16*4], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 2 + mova [dstq+16*5], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_BACKUP 3 + mova [dstq+16*6], m0 + call mangle(private_prefix %+ _w_mask_420_8bpc_ssse3).main + W_MASK_422_END 3 + mova [dstq+16*7], m0 + dec hd + jg .w128_loop + RET + +cglobal w_mask_444_8bpc, 4, 7, 9, dst, stride, tmp1, tmp2, w, h, mask +%define base t0-w_mask_444_ssse3_table + LEA t0, w_mask_444_ssse3_table + tzcnt wd, wm + mov maskq, maskmp + sub tmp2q, tmp1q + movsxd wq, [t0+wq*4] + mova m6, [base+pw_6903] + mova m7, [base+pw_2048] + add wq, t0 +%if ARCH_X86_64 + mova m8, [base+pb_64] + movifnidn hd, hm +%else + %define m8 [base+pb_64] + %define hd dword hm +%endif + call .main + jmp wq +.w4_loop: + call .main + lea dstq, [dstq+strideq*2] +.w4: + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + punpckhqdq m0, m0 + lea dstq, [dstq+strideq*2] + movd [dstq+strideq*0], m0 + pshuflw m1, m0, q1032 + movd [dstq+strideq*1], m1 + sub hd, 4 + jg .w4_loop + RET +.w8_loop: + call .main + lea dstq, [dstq+strideq*2] +.w8: + movq [dstq+strideq*0], m0 + movhps [dstq+strideq*1], m0 + sub hd, 2 + jg .w8_loop + RET +.w16_loop: + call .main + lea dstq, [dstq+strideq*2] +.w16: + mova [dstq+strideq*0], m0 + call .main + mova [dstq+strideq*1], m0 + sub hd, 2 + jg .w16_loop + RET +.w32_loop: + call .main + add dstq, strideq +.w32: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + dec hd + jg .w32_loop + RET +.w64_loop: + call .main + add dstq, strideq +.w64: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + call .main + mova [dstq+16*2], m0 + call .main + mova [dstq+16*3], m0 + dec hd + jg .w64_loop + RET +.w128_loop: + call .main + add dstq, strideq +.w128: + mova [dstq+16*0], m0 + call .main + mova [dstq+16*1], m0 + call .main + mova [dstq+16*2], m0 + call .main + mova [dstq+16*3], m0 + call .main + mova [dstq+16*4], m0 + call .main + mova [dstq+16*5], m0 + call .main + mova [dstq+16*6], m0 + call .main + mova [dstq+16*7], m0 + dec hd + jg .w128_loop + RET +ALIGN function_align +.main: + mova m0, [tmp1q +16*0] + mova m3, [tmp1q+tmp2q+16*0] + mova m1, [tmp1q +16*1] + mova m4, [tmp1q+tmp2q+16*1] + add tmp1q, 16*2 + psubw m3, m0 + psubw m4, m1 + pabsw m5, m3 + psubusw m2, m6, m5 + psrlw m2, 8 ; 64 - m + psllw m5, m2, 10 + pmulhw m3, m5 + pabsw m5, m4 + paddw m0, m3 + psubusw m3, m6, m5 + psrlw m3, 8 + packuswb m2, m3 + psllw m3, 10 + pmulhw m4, m3 + psubb m3, m8, m2 + paddw m1, m4 + pmulhrsw m0, m7 + pmulhrsw m1, m7 + mova [maskq], m3 + add maskq, 16 + packuswb m0, m1 + ret + +%macro BLEND_64M 4; a, b, mask1, mask2 + punpcklbw m0, %1, %2; {b;a}[7..0] + punpckhbw %1, %2 ; {b;a}[15..8] + pmaddubsw m0, %3 ; {b*m[0] + (64-m[0])*a}[7..0] u16 + pmaddubsw %1, %4 ; {b*m[1] + (64-m[1])*a}[15..8] u16 + pmulhrsw m0, m5 ; {((b*m[0] + (64-m[0])*a) + 1) / 32}[7..0] u16 + pmulhrsw %1, m5 ; {((b*m[1] + (64-m[0])*a) + 1) / 32}[15..8] u16 + packuswb m0, %1 ; {blendpx}[15..0] u8 +%endmacro + +%macro BLEND 2; a, b + psubb m3, m4, m0 ; m3 = (64 - m) + punpcklbw m2, m3, m0 ; {m;(64-m)}[7..0] + punpckhbw m3, m0 ; {m;(64-m)}[15..8] + BLEND_64M %1, %2, m2, m3 +%endmacro + +cglobal blend_8bpc, 3, 7, 7, dst, ds, tmp, w, h, mask +%define base r6-blend_ssse3_table + LEA r6, blend_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movifnidn maskq, maskmp + movsxd wq, dword [r6+wq*4] + mova m4, [base+pb_64] + mova m5, [base+pw_512] + add wq, r6 + lea r6, [dsq*3] + jmp wq +.w4: + movq m0, [maskq]; m + movd m1, [dstq+dsq*0] ; a + movd m6, [dstq+dsq*1] + punpckldq m1, m6 + movq m6, [tmpq] ; b + psubb m3, m4, m0 ; m3 = (64 - m) + punpcklbw m2, m3, m0 ; {m;(64-m)}[7..0] + punpcklbw m1, m6 ; {b;a}[7..0] + pmaddubsw m1, m2 ; {b*m[0] + (64-m[0])*a}[7..0] u16 + pmulhrsw m1, m5 ; {((b*m[0] + (64-m[0])*a) + 1) / 32}[7..0] u16 + packuswb m1, m0 ; {blendpx}[15..0] u8 + movd [dstq+dsq*0], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + add maskq, 8 + add tmpq, 8 + lea dstq, [dstq+dsq*2] ; dst_stride * 2 + sub hd, 2 + jg .w4 + RET +.w8: + mova m0, [maskq]; m + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m6, [tmpq] ; b + BLEND m1, m6 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + add maskq, 16 + add tmpq, 16 + lea dstq, [dstq+dsq*2] ; dst_stride * 2 + sub hd, 2 + jg .w8 + RET +.w16: + mova m0, [maskq]; m + mova m1, [dstq] ; a + mova m6, [tmpq] ; b + BLEND m1, m6 + mova [dstq], m0 + add maskq, 16 + add tmpq, 16 + add dstq, dsq ; dst_stride + dec hd + jg .w16 + RET +.w32: + %assign i 0 + %rep 2 + mova m0, [maskq+16*i]; m + mova m1, [dstq+16*i] ; a + mova m6, [tmpq+16*i] ; b + BLEND m1, m6 + mova [dstq+i*16], m0 + %assign i i+1 + %endrep + add maskq, 32 + add tmpq, 32 + add dstq, dsq ; dst_stride + dec hd + jg .w32 + RET + +cglobal blend_v_8bpc, 3, 6, 6, dst, ds, tmp, w, h, mask +%define base r5-blend_v_ssse3_table + LEA r5, blend_v_ssse3_table + tzcnt wd, wm + movifnidn hd, hm + movsxd wq, dword [r5+wq*4] + mova m5, [base+pw_512] + add wq, r5 + add maskq, obmc_masks-blend_v_ssse3_table + jmp wq +.w2: + movd m3, [maskq+4] + punpckldq m3, m3 + ; 2 mask blend is provided for 4 pixels / 2 lines +.w2_loop: + movd m1, [dstq+dsq*0] ; a {..;a;a} + pinsrw m1, [dstq+dsq*1], 1 + movd m2, [tmpq] ; b + punpcklbw m0, m1, m2; {b;a}[7..0] + pmaddubsw m0, m3 ; {b*m + (64-m)*a}[7..0] u16 + pmulhrsw m0, m5 ; {((b*m + (64-m)*a) + 1) / 32}[7..0] u16 + packuswb m0, m1 ; {blendpx}[8..0] u8 + movd r3d, m0 + mov [dstq+dsq*0], r3w + shr r3d, 16 + mov [dstq+dsq*1], r3w + add tmpq, 2*2 + lea dstq, [dstq + dsq * 2] + sub hd, 2 + jg .w2_loop + RET +.w4: + movddup m3, [maskq+8] + ; 4 mask blend is provided for 8 pixels / 2 lines +.w4_loop: + movd m1, [dstq+dsq*0] ; a + movd m2, [dstq+dsq*1] ; + punpckldq m1, m2 + movq m2, [tmpq] ; b + punpcklbw m1, m2 ; {b;a}[7..0] + pmaddubsw m1, m3 ; {b*m + (64-m)*a}[7..0] u16 + pmulhrsw m1, m5 ; {((b*m + (64-m)*a) + 1) / 32}[7..0] u16 + packuswb m1, m1 ; {blendpx}[8..0] u8 + movd [dstq], m1 + psrlq m1, 32 + movd [dstq+dsq*1], m1 + add tmpq, 2*4 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w4_loop + RET +.w8: + mova m3, [maskq+16] + ; 8 mask blend is provided for 16 pixels +.w8_loop: + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m2, [tmpq]; b + BLEND_64M m1, m2, m3, m3 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + add tmpq, 16 + lea dstq, [dstq+dsq*2] + sub hd, 2 + jg .w8_loop + RET +.w16: + ; 16 mask blend is provided for 32 pixels + mova m3, [maskq+32] ; obmc_masks_16[0] (64-m[0]) + mova m4, [maskq+48] ; obmc_masks_16[1] (64-m[1]) +.w16_loop: + mova m1, [dstq] ; a + mova m2, [tmpq] ; b + BLEND_64M m1, m2, m3, m4 + mova [dstq], m0 + add tmpq, 16 + add dstq, dsq + dec hd + jg .w16_loop + RET +.w32: +%if WIN64 + mova [rsp+8], xmm6 +%endif + mova m3, [maskq+64] ; obmc_masks_32[0] (64-m[0]) + mova m4, [maskq+80] ; obmc_masks_32[1] (64-m[1]) + mova m6, [maskq+96] ; obmc_masks_32[2] (64-m[2]) + ; 16 mask blend is provided for 64 pixels +.w32_loop: + mova m1, [dstq+16*0] ; a + mova m2, [tmpq+16*0] ; b + BLEND_64M m1, m2, m3, m4 + movq m1, [dstq+16*1] ; a + punpcklbw m1, [tmpq+16*1] ; b + pmaddubsw m1, m6 + pmulhrsw m1, m5 + packuswb m1, m1 + mova [dstq+16*0], m0 + movq [dstq+16*1], m1 + add tmpq, 32 + add dstq, dsq + dec hd + jg .w32_loop +%if WIN64 + mova xmm6, [rsp+8] +%endif + RET + +cglobal blend_h_8bpc, 3, 7, 6, dst, ds, tmp, w, h, mask +%define base t0-blend_h_ssse3_table +%if ARCH_X86_32 + ; We need to keep the PIC pointer for w4, reload wd from stack instead + DECLARE_REG_TMP 6 +%else + DECLARE_REG_TMP 5 + mov r6d, wd +%endif + LEA t0, blend_h_ssse3_table + tzcnt wd, wm + mov hd, hm + movsxd wq, dword [t0+wq*4] + mova m5, [base+pw_512] + add wq, t0 + lea maskq, [base+obmc_masks+hq*2] + lea hd, [hq*3] + shr hd, 2 ; h * 3/4 + lea maskq, [maskq+hq*2] + neg hq + jmp wq +.w2: + movd m0, [dstq+dsq*0] + pinsrw m0, [dstq+dsq*1], 1 + movd m2, [maskq+hq*2] + movd m1, [tmpq] + punpcklwd m2, m2 + punpcklbw m0, m1 + pmaddubsw m0, m2 + pmulhrsw m0, m5 + packuswb m0, m0 + movd r3d, m0 + mov [dstq+dsq*0], r3w + shr r3d, 16 + mov [dstq+dsq*1], r3w + lea dstq, [dstq+dsq*2] + add tmpq, 2*2 + add hq, 2 + jl .w2 + RET +.w4: +%if ARCH_X86_32 + mova m3, [base+blend_shuf] +%else + mova m3, [blend_shuf] +%endif +.w4_loop: + movd m0, [dstq+dsq*0] + movd m2, [dstq+dsq*1] + punpckldq m0, m2 ; a + movq m1, [tmpq] ; b + movq m2, [maskq+hq*2] ; m + pshufb m2, m3 + punpcklbw m0, m1 + pmaddubsw m0, m2 + pmulhrsw m0, m5 + packuswb m0, m0 + movd [dstq+dsq*0], m0 + psrlq m0, 32 + movd [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add tmpq, 4*2 + add hq, 2 + jl .w4_loop + RET +.w8: + movd m4, [maskq+hq*2] + punpcklwd m4, m4 + pshufd m3, m4, q0000 + pshufd m4, m4, q1111 + movq m1, [dstq+dsq*0] ; a + movhps m1, [dstq+dsq*1] + mova m2, [tmpq] + BLEND_64M m1, m2, m3, m4 + movq [dstq+dsq*0], m0 + movhps [dstq+dsq*1], m0 + lea dstq, [dstq+dsq*2] + add tmpq, 8*2 + add hq, 2 + jl .w8 + RET +; w16/w32/w64/w128 +.w16: +%if ARCH_X86_32 + mov r6d, wm +%endif + sub dsq, r6 +.w16_loop0: + movd m3, [maskq+hq*2] + pshuflw m3, m3, q0000 + punpcklqdq m3, m3 + mov wd, r6d +.w16_loop: + mova m1, [dstq] ; a + mova m2, [tmpq] ; b + BLEND_64M m1, m2, m3, m3 + mova [dstq], m0 + add dstq, 16 + add tmpq, 16 + sub wd, 16 + jg .w16_loop + add dstq, dsq + inc hq + jl .w16_loop0 + RET + +; emu_edge args: +; const intptr_t bw, const intptr_t bh, const intptr_t iw, const intptr_t ih, +; const intptr_t x, const intptr_t y, pixel *dst, const ptrdiff_t dst_stride, +; const pixel *ref, const ptrdiff_t ref_stride +; +; bw, bh total filled size +; iw, ih, copied block -> fill bottom, right +; x, y, offset in bw/bh -> fill top, left +cglobal emu_edge_8bpc, 10, 13, 2, bw, bh, iw, ih, x, \ + y, dst, dstride, src, sstride, \ + bottomext, rightext, blk + ; we assume that the buffer (stride) is larger than width, so we can + ; safely overwrite by a few bytes + pxor m1, m1 + +%if ARCH_X86_64 + %define reg_zero r12q + %define reg_tmp r10 + %define reg_src srcq + %define reg_bottomext bottomextq + %define reg_rightext rightextq + %define reg_blkm r9m +%else + %define reg_zero r6 + %define reg_tmp r0 + %define reg_src r1 + %define reg_bottomext r0 + %define reg_rightext r1 + %define reg_blkm r2m +%endif + ; + ; ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride) + xor reg_zero, reg_zero + lea reg_tmp, [ihq-1] + cmp yq, ihq + cmovs reg_tmp, yq + test yq, yq + cmovs reg_tmp, reg_zero +%if ARCH_X86_64 + imul reg_tmp, sstrideq + add srcq, reg_tmp +%else + imul reg_tmp, sstridem + mov reg_src, srcm + add reg_src, reg_tmp +%endif + ; + ; ref += iclip(x, 0, iw - 1) + lea reg_tmp, [iwq-1] + cmp xq, iwq + cmovs reg_tmp, xq + test xq, xq + cmovs reg_tmp, reg_zero + add reg_src, reg_tmp +%if ARCH_X86_32 + mov srcm, reg_src +%endif + ; + ; bottom_ext = iclip(y + bh - ih, 0, bh - 1) +%if ARCH_X86_32 + mov r1, r1m ; restore bh +%endif + lea reg_bottomext, [yq+bhq] + sub reg_bottomext, ihq + lea r3, [bhq-1] + cmovs reg_bottomext, reg_zero + ; + + DEFINE_ARGS bw, bh, iw, ih, x, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; top_ext = iclip(-y, 0, bh - 1) + neg topextq + cmovs topextq, reg_zero + cmp reg_bottomext, bhq + cmovns reg_bottomext, r3 + cmp topextq, bhq + cmovg topextq, r3 + %if ARCH_X86_32 + mov r4m, reg_bottomext + ; + ; right_ext = iclip(x + bw - iw, 0, bw - 1) + mov r0, r0m ; restore bw + %endif + lea reg_rightext, [xq+bwq] + sub reg_rightext, iwq + lea r2, [bwq-1] + cmovs reg_rightext, reg_zero + + DEFINE_ARGS bw, bh, iw, ih, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; left_ext = iclip(-x, 0, bw - 1) + neg leftextq + cmovs leftextq, reg_zero + cmp reg_rightext, bwq + cmovns reg_rightext, r2 + %if ARCH_X86_32 + mov r3m, r1 + %endif + cmp leftextq, bwq + cmovns leftextq, r2 + +%undef reg_zero +%undef reg_tmp +%undef reg_src +%undef reg_bottomext +%undef reg_rightext + + DEFINE_ARGS bw, centerh, centerw, dummy, leftext, \ + topext, dst, dstride, src, sstride, \ + bottomext, rightext, blk + + ; center_h = bh - top_ext - bottom_ext +%if ARCH_X86_64 + lea r3, [bottomextq+topextq] + sub centerhq, r3 +%else + mov r1, centerhm ; restore r1 + sub centerhq, topextq + sub centerhq, r4m + mov r1m, centerhq +%endif + ; + ; blk += top_ext * PXSTRIDE(dst_stride) + mov r2, topextq +%if ARCH_X86_64 + imul r2, dstrideq +%else + mov r6, r6m ; restore dstq + imul r2, dstridem +%endif + add dstq, r2 + mov reg_blkm, dstq ; save pointer for ext + ; + ; center_w = bw - left_ext - right_ext + mov centerwq, bwq +%if ARCH_X86_64 + lea r3, [rightextq+leftextq] + sub centerwq, r3 +%else + sub centerwq, r3m + sub centerwq, leftextq +%endif + +; vloop Macro +%macro v_loop 3 ; need_left_ext, need_right_ext, suffix + %if ARCH_X86_64 + %define reg_tmp r12 + %else + %define reg_tmp r0 + %endif +.v_loop_%3: + %if ARCH_X86_32 + mov r0, r0m + mov r1, r1m + %endif +%if %1 + ; left extension + %if ARCH_X86_64 + movd m0, [srcq] + %else + mov r3, srcm + movd m0, [r3] + %endif + pshufb m0, m1 + xor r3, r3 +.left_loop_%3: + mova [dstq+r3], m0 + add r3, mmsize + cmp r3, leftextq + jl .left_loop_%3 + ; body + lea reg_tmp, [dstq+leftextq] +%endif + xor r3, r3 +.body_loop_%3: + %if ARCH_X86_64 + movu m0, [srcq+r3] + %else + mov r1, srcm + movu m0, [r1+r3] + %endif +%if %1 + movu [reg_tmp+r3], m0 +%else + movu [dstq+r3], m0 +%endif + add r3, mmsize + cmp r3, centerwq + jl .body_loop_%3 +%if %2 + ; right extension +%if %1 + add reg_tmp, centerwq +%else + lea reg_tmp, [dstq+centerwq] +%endif + %if ARCH_X86_64 + movd m0, [srcq+centerwq-1] + %else + mov r3, srcm + movd m0, [r3+centerwq-1] + %endif + pshufb m0, m1 + xor r3, r3 +.right_loop_%3: + movu [reg_tmp+r3], m0 + add r3, mmsize + %if ARCH_X86_64 + cmp r3, rightextq + %else + cmp r3, r3m + %endif + jl .right_loop_%3 +%endif + %if ARCH_X86_64 + add dstq, dstrideq + add srcq, sstrideq + dec centerhq + jg .v_loop_%3 + %else + add dstq, dstridem + mov r0, sstridem + add srcm, r0 + sub dword centerhm, 1 + jg .v_loop_%3 + mov r0, r0m ; restore r0 + %endif +%endmacro ; vloop MACRO + + test leftextq, leftextq + jnz .need_left_ext + %if ARCH_X86_64 + test rightextq, rightextq + jnz .need_right_ext + %else + cmp leftextq, r3m ; leftextq == 0 + jne .need_right_ext + %endif + v_loop 0, 0, 0 + jmp .body_done + + ;left right extensions +.need_left_ext: + %if ARCH_X86_64 + test rightextq, rightextq + %else + mov r3, r3m + test r3, r3 + %endif + jnz .need_left_right_ext + v_loop 1, 0, 1 + jmp .body_done + +.need_left_right_ext: + v_loop 1, 1, 2 + jmp .body_done + +.need_right_ext: + v_loop 0, 1, 3 + +.body_done: +; r0 ; bw +; r1 ;; x loop +; r4 ;; y loop +; r5 ; topextq +; r6 ;dstq +; r7 ;dstrideq +; r8 ; srcq +%if ARCH_X86_64 + %define reg_dstride dstrideq +%else + %define reg_dstride r2 +%endif + ; + ; bottom edge extension + %if ARCH_X86_64 + test bottomextq, bottomextq + jz .top + %else + xor r1, r1 + cmp r1, r4m + je .top + %endif + ; + %if ARCH_X86_64 + mov srcq, dstq + sub srcq, dstrideq + xor r1, r1 + %else + mov r3, dstq + mov reg_dstride, dstridem + sub r3, reg_dstride + mov srcm, r3 + %endif + ; +.bottom_x_loop: + %if ARCH_X86_64 + mova m0, [srcq+r1] + lea r3, [dstq+r1] + mov r4, bottomextq + %else + mov r3, srcm + mova m0, [r3+r1] + lea r3, [dstq+r1] + mov r4, r4m + %endif + ; +.bottom_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .bottom_y_loop + add r1, mmsize + cmp r1, bwq + jl .bottom_x_loop + +.top: + ; top edge extension + test topextq, topextq + jz .end +%if ARCH_X86_64 + mov srcq, reg_blkm +%else + mov r3, reg_blkm + mov reg_dstride, dstridem +%endif + mov dstq, dstm + xor r1, r1 + ; +.top_x_loop: +%if ARCH_X86_64 + mova m0, [srcq+r1] +%else + mov r3, reg_blkm + mova m0, [r3+r1] +%endif + lea r3, [dstq+r1] + mov r4, topextq + ; +.top_y_loop: + mova [r3], m0 + add r3, reg_dstride + dec r4 + jg .top_y_loop + add r1, mmsize + cmp r1, bwq + jl .top_x_loop + +.end: + RET + +%undef reg_dstride +%undef reg_blkm +%undef reg_tmp + +cextern resize_filter + +%macro SCRATCH 3 +%if ARCH_X86_32 + mova [rsp+%3*mmsize], m%1 +%define m%2 [rsp+%3*mmsize] +%else + SWAP %1, %2 +%endif +%endmacro + +%if ARCH_X86_64 +cglobal resize_8bpc, 0, 12, 14, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%elif STACK_ALIGNMENT >= 16 +cglobal resize_8bpc, 0, 7, 8, 3 * 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%else +cglobal resize_8bpc, 0, 6, 8, 3 * 16, dst, dst_stride, src, src_stride, \ + dst_w, h, src_w, dx, mx0 +%endif + movifnidn dstq, dstmp + movifnidn srcq, srcmp +%if STACK_ALIGNMENT >= 16 + movifnidn dst_wd, dst_wm +%endif +%if ARCH_X86_64 + movifnidn hd, hm +%endif + sub dword mx0m, 4<<14 + sub dword src_wm, 8 + movd m7, dxm + movd m6, mx0m + movd m5, src_wm + pshufd m7, m7, q0000 + pshufd m6, m6, q0000 + pshufd m5, m5, q0000 + +%if ARCH_X86_64 + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, h, x + LEA r7, $$ +%define base r7-$$ +%else + DEFINE_ARGS dst, dst_stride, src, src_stride, dst_w, x +%define hd dword r5m +%if STACK_ALIGNMENT >= 16 + LEA r6, $$ +%define base r6-$$ +%else + LEA r4, $$ +%define base r4-$$ +%endif +%endif + +%if ARCH_X86_64 + mova m10, [base+pw_m256] + mova m9, [base+pd_63] + mova m8, [base+pb_8x0_8x8] +%else +%define m10 [base+pw_m256] +%define m9 [base+pd_63] +%define m8 [base+pb_8x0_8x8] +%endif + pmaddwd m4, m7, [base+rescale_mul] ; dx*[0,1,2,3] + pslld m7, 2 ; dx*4 + pslld m5, 14 + paddd m6, m4 ; mx+[0..3]*dx + SCRATCH 7, 13, 0 + SCRATCH 6, 12, 1 + SCRATCH 5, 11, 2 + + ; m10 = pmulhrsw constant for x=(x+64)>>7 + ; m12 = mx+[0..3]*dx, m13 = dx*4, m11 = src_w, m9 = 0x3f, m8=0,8 + +.loop_y: + xor xd, xd + mova m0, m12 ; per-line working version of mx + +.loop_x: + pxor m1, m1 + pcmpgtd m1, m0 + pandn m1, m0 + psrad m2, m0, 8 ; filter offset (unmasked) + pcmpgtd m3, m11, m1 + pand m1, m3 + pandn m3, m11 + por m1, m3 + psubd m3, m0, m1 ; pshufb offset + psrad m1, 14 ; clipped src_x offset + psrad m3, 14 ; pshufb edge_emu offset + pand m2, m9 ; filter offset (masked) + + ; load source pixels +%if ARCH_X86_64 + movd r8d, m1 + pshuflw m1, m1, q3232 + movd r9d, m1 + punpckhqdq m1, m1 + movd r10d, m1 + psrlq m1, 32 + movd r11d, m1 + movq m4, [srcq+r8] + movq m5, [srcq+r10] + movhps m4, [srcq+r9] + movhps m5, [srcq+r11] +%else + movd r3d, m1 + pshufd m1, m1, q3312 + movd r1d, m1 + pshuflw m1, m1, q3232 + movq m4, [srcq+r3] + movq m5, [srcq+r1] + movd r3d, m1 + punpckhqdq m1, m1 + movd r1d, m1 + movhps m4, [srcq+r3] + movhps m5, [srcq+r1] +%endif + + ; if no emulation is required, we don't need to shuffle or emulate edges + ; this also saves 2 quasi-vpgatherdqs + pxor m6, m6 + pcmpeqb m6, m3 +%if ARCH_X86_64 + pmovmskb r8d, m6 + cmp r8d, 0xffff +%else + pmovmskb r3d, m6 + cmp r3d, 0xffff +%endif + je .filter + +%if ARCH_X86_64 + movd r8d, m3 + pshuflw m3, m3, q3232 + movd r9d, m3 + punpckhqdq m3, m3 + movd r10d, m3 + psrlq m3, 32 + movd r11d, m3 + movsxd r8, r8d + movsxd r9, r9d + movsxd r10, r10d + movsxd r11, r11d + movq m6, [base+resize_shuf+4+r8] + movq m7, [base+resize_shuf+4+r10] + movhps m6, [base+resize_shuf+4+r9] + movhps m7, [base+resize_shuf+4+r11] +%else + movd r3d, m3 + pshufd m3, m3, q3312 + movd r1d, m3 + pshuflw m3, m3, q3232 + movq m6, [base+resize_shuf+4+r3] + movq m7, [base+resize_shuf+4+r1] + movd r3d, m3 + punpckhqdq m3, m3 + movd r1d, m3 + movhps m6, [base+resize_shuf+4+r3] + movhps m7, [base+resize_shuf+4+r1] +%endif + + paddb m6, m8 + paddb m7, m8 + pshufb m4, m6 + pshufb m5, m7 + +.filter: +%if ARCH_X86_64 + movd r8d, m2 + pshuflw m2, m2, q3232 + movd r9d, m2 + punpckhqdq m2, m2 + movd r10d, m2 + psrlq m2, 32 + movd r11d, m2 + movq m6, [base+resize_filter+r8*8] + movq m7, [base+resize_filter+r10*8] + movhps m6, [base+resize_filter+r9*8] + movhps m7, [base+resize_filter+r11*8] +%else + movd r3d, m2 + pshufd m2, m2, q3312 + movd r1d, m2 + pshuflw m2, m2, q3232 + movq m6, [base+resize_filter+r3*8] + movq m7, [base+resize_filter+r1*8] + movd r3d, m2 + punpckhqdq m2, m2 + movd r1d, m2 + movhps m6, [base+resize_filter+r3*8] + movhps m7, [base+resize_filter+r1*8] +%endif + + pmaddubsw m4, m6 + pmaddubsw m5, m7 + phaddw m4, m5 + phaddsw m4, m4 + pmulhrsw m4, m10 ; x=(x+64)>>7 + packuswb m4, m4 + movd [dstq+xq], m4 + + paddd m0, m13 + add xd, 4 +%if STACK_ALIGNMENT >= 16 + cmp xd, dst_wd +%else + cmp xd, dst_wm +%endif + jl .loop_x + + add dstq, dst_stridemp + add srcq, src_stridemp + dec hd + jg .loop_y + RET + +INIT_XMM ssse3 +PREP_BILIN +PREP_8TAP +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T + +INIT_XMM sse4 +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T + +INIT_XMM sse2 +PREP_BILIN +PREP_8TAP +WARP_AFFINE_8X8 +WARP_AFFINE_8X8T diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/me.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/me.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/me.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/me.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,98 @@ +; Copyright (c) 2018, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION .text + +%macro W_ABS_DIFF 8 + psubw %1, %5 + psubw %2, %6 + psubw %3, %7 + psubw %4, %8 + pabsw %1, %1 + pabsw %2, %2 + pabsw %3, %3 + pabsw %4, %4 +%endmacro + +INIT_XMM ssse3 +cglobal sad_4x4_hbd, 4, 6, 8, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + movq m0, [srcq] + movq m1, [srcq+src_strideq*1] + movq m2, [srcq+src_strideq*2] + movq m3, [srcq+src_stride3q] + movq m4, [dstq] + movq m5, [dstq+dst_strideq*1] + movq m6, [dstq+dst_strideq*2] + movq m7, [dstq+dst_stride3q] + W_ABS_DIFF m0, m1, m2, m3, m4, m5, m6, m7 +; Don't convert to 32 bit integers: 4*4 abs diffs of 12-bits fits in 16 bits. +; Accumulate onto m0 + %define sum m0 + paddw sum, m1 + paddw m2, m3 + paddw sum, m2 +; Horizontal reduction + pshuflw m1, sum, q2323 + paddw sum, m1 + pshuflw m1, sum, q1111 + paddw sum, m1 + movd eax, sum +; Convert to 16-bits since the upper half of eax is dirty + movzx eax, ax + RET + +%if ARCH_X86_64 + +INIT_XMM ssse3 +cglobal sad_16x16_hbd, 4, 5, 10, src, src_stride, dst, dst_stride, \ + cnt + mov cntd, 8 + %define sum m0 + pxor sum, sum + pxor m9, m9 +.loop: + movu m1, [srcq] + movu m2, [srcq+16] + movu m3, [srcq+src_strideq] + movu m4, [srcq+src_strideq+16] + lea srcq, [srcq+src_strideq*2] + movu m5, [dstq] + movu m6, [dstq+16] + movu m7, [dstq+dst_strideq] + movu m8, [dstq+dst_strideq+16] + lea dstq, [dstq+dst_strideq*2] + W_ABS_DIFF m1, m2, m3, m4, m5, m6, m7, m8 + paddw m1, m2 + paddw m3, m4 +; Convert to 32-bits + punpcklwd m2, m1, m9 + punpcklwd m4, m3, m9 + punpckhwd m1, m9 + punpckhwd m3, m9 + paddd m1, m2 + paddd m3, m4 + paddd sum, m1 + paddd sum, m3 + dec cntd + jg .loop +; Horizontal reduction + movhlps m1, sum + paddd sum, m1 + pshufd m1, sum, q1111 + paddd sum, m1 + movd eax, sum + RET + +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/msac.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/msac.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/msac.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/msac.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,667 @@ +; Copyright © 2019, VideoLAN and dav1d authors +; Copyright © 2019, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 64 ; avoids cacheline splits + +min_prob: dw 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0 +pw_0xff00: times 8 dw 0xff00 +pw_32: times 8 dw 32 + +%if ARCH_X86_64 +%define resp resq +%define movp movq +%define c_shuf q3333 +%macro DECODE_SYMBOL_ADAPT_INIT 0-1 +%endmacro +%else +%define resp resd +%define movp movd +%define c_shuf q1111 +%macro DECODE_SYMBOL_ADAPT_INIT 0-1 0 ; hi_tok + mov t0, r0m + mov t1, r1m +%if %1 == 0 + mov t2, r2m +%endif +%if STACK_ALIGNMENT >= 16 + sub esp, 40-%1*4 +%else + mov eax, esp + and esp, ~15 + sub esp, 40-%1*4 + mov [esp], eax +%endif +%endmacro +%endif + +struc msac + .buf: resp 1 + .end: resp 1 + .dif: resp 1 + .rng: resd 1 + .cnt: resd 1 + .update_cdf: resd 1 +endstruc + +%define m(x, y) mangle(private_prefix %+ _ %+ x %+ y) + +SECTION .text + +%if WIN64 +DECLARE_REG_TMP 0, 1, 2, 3, 4, 5, 7, 3, 8 +%define buf rsp+stack_offset+8 ; shadow space +%elif UNIX64 +DECLARE_REG_TMP 0, 1, 2, 3, 4, 5, 7, 0, 8 +%define buf rsp-40 ; red zone +%else +DECLARE_REG_TMP 2, 3, 4, 1, 5, 6, 5, 2, 3 +%define buf esp+8 +%endif + +INIT_XMM sse2 +cglobal msac_decode_symbol_adapt4, 0, 6, 6 + DECODE_SYMBOL_ADAPT_INIT + LEA rax, pw_0xff00 + movd m2, [t0+msac.rng] + movq m1, [t1] + movp m3, [t0+msac.dif] + mov t3d, [t0+msac.update_cdf] + mov t4d, t2d + not t2 ; -(n_symbols + 1) + pshuflw m2, m2, q0000 + movd [buf+12], m2 + pand m2, [rax] + mova m0, m1 + psrlw m1, 6 + psllw m1, 7 + pmulhuw m1, m2 + movq m2, [rax+t2*2] + pshuflw m3, m3, c_shuf + paddw m1, m2 + mova [buf+16], m1 + psubusw m1, m3 + pxor m2, m2 + pcmpeqw m1, m2 ; c >= v + pmovmskb eax, m1 + test t3d, t3d + jz .renorm ; !allow_update_cdf + +; update_cdf: + movzx t3d, word [t1+t4*2] ; count + pcmpeqw m2, m2 + mov t2d, t3d + shr t3d, 4 + cmp t4d, 3 + sbb t3d, -5 ; (count >> 4) + (n_symbols > 2) + 4 + cmp t2d, 32 + adc t2d, 0 ; count + (count < 32) + movd m3, t3d + pavgw m2, m1 ; i >= val ? -1 : 32768 + psubw m2, m0 ; for (i = 0; i < val; i++) + psubw m0, m1 ; cdf[i] += (32768 - cdf[i]) >> rate; + psraw m2, m3 ; for (; i < n_symbols; i++) + paddw m0, m2 ; cdf[i] += (( -1 - cdf[i]) >> rate) + 1; + movq [t1], m0 + mov [t1+t4*2], t2w + +.renorm: + tzcnt eax, eax + mov t4, [t0+msac.dif] + movzx t1d, word [buf+rax+16] ; v + movzx t2d, word [buf+rax+14] ; u + shr eax, 1 +.renorm2: +%if ARCH_X86_64 == 0 +%if STACK_ALIGNMENT >= 16 + add esp, 40 +%else + mov esp, [esp] +%endif +%endif + not t4 + sub t2d, t1d ; rng + shl t1, gprsize*8-16 + add t4, t1 ; ~dif +.renorm3: + mov t1d, [t0+msac.cnt] + movifnidn t7, t0 +.renorm4: + bsr ecx, t2d + xor ecx, 15 ; d +.renorm5: + shl t2d, cl + shl t4, cl + mov [t7+msac.rng], t2d + not t4 + sub t1d, ecx + jae .end ; no refill required + +; refill: + mov t2, [t7+msac.buf] + mov rcx, [t7+msac.end] +%if ARCH_X86_64 == 0 + push t5 +%endif + lea t5, [t2+gprsize] + cmp t5, rcx + ja .refill_eob + mov t2, [t2] + lea ecx, [t1+23] + add t1d, 16 + shr ecx, 3 ; shift_bytes + bswap t2 + sub t5, rcx + shl ecx, 3 ; shift_bits + shr t2, cl + sub ecx, t1d ; shift_bits - 16 - cnt + mov t1d, gprsize*8-16 + shl t2, cl + mov [t7+msac.buf], t5 + sub t1d, ecx ; cnt + gprsize*8 - shift_bits + xor t4, t2 +%if ARCH_X86_64 == 0 + pop t5 +%endif +.end: + mov [t7+msac.cnt], t1d + mov [t7+msac.dif], t4 + RET +.refill_eob: ; avoid overreading the input buffer + mov t5, rcx + mov ecx, gprsize*8-24 + sub ecx, t1d ; c +.refill_eob_loop: + cmp t2, t5 + jae .refill_eob_end ; eob reached + movzx t1d, byte [t2] + inc t2 + shl t1, cl + xor t4, t1 + sub ecx, 8 + jge .refill_eob_loop +.refill_eob_end: + mov t1d, gprsize*8-24 +%if ARCH_X86_64 == 0 + pop t5 +%endif + sub t1d, ecx + mov [t7+msac.buf], t2 + mov [t7+msac.dif], t4 + mov [t7+msac.cnt], t1d + RET + +cglobal msac_decode_symbol_adapt8, 0, 6, 6 + DECODE_SYMBOL_ADAPT_INIT + LEA rax, pw_0xff00 + movd m2, [t0+msac.rng] + mova m1, [t1] + movp m3, [t0+msac.dif] + mov t3d, [t0+msac.update_cdf] + mov t4d, t2d + not t2 + pshuflw m2, m2, q0000 + movd [buf+12], m2 + punpcklqdq m2, m2 + mova m0, m1 + psrlw m1, 6 + pand m2, [rax] + psllw m1, 7 + pmulhuw m1, m2 + movu m2, [rax+t2*2] + pshuflw m3, m3, c_shuf + paddw m1, m2 + punpcklqdq m3, m3 + mova [buf+16], m1 + psubusw m1, m3 + pxor m2, m2 + pcmpeqw m1, m2 + pmovmskb eax, m1 + test t3d, t3d + jz m(msac_decode_symbol_adapt4, SUFFIX).renorm + movzx t3d, word [t1+t4*2] + pcmpeqw m2, m2 + mov t2d, t3d + shr t3d, 4 + cmp t4d, 3 ; may be called with n_symbols <= 2 + sbb t3d, -5 + cmp t2d, 32 + adc t2d, 0 + movd m3, t3d + pavgw m2, m1 + psubw m2, m0 + psubw m0, m1 + psraw m2, m3 + paddw m0, m2 + mova [t1], m0 + mov [t1+t4*2], t2w + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm + +cglobal msac_decode_symbol_adapt16, 0, 6, 6 + DECODE_SYMBOL_ADAPT_INIT + LEA rax, pw_0xff00 + movd m4, [t0+msac.rng] + mova m2, [t1] + mova m3, [t1+16] + movp m5, [t0+msac.dif] + mov t3d, [t0+msac.update_cdf] + mov t4d, t2d + not t2 +%if WIN64 + sub rsp, 48 ; need 36 bytes, shadow space is only 32 +%endif + pshuflw m4, m4, q0000 + movd [buf-4], m4 + punpcklqdq m4, m4 + mova m0, m2 + psrlw m2, 6 + mova m1, m3 + psrlw m3, 6 + pand m4, [rax] + psllw m2, 7 + psllw m3, 7 + pmulhuw m2, m4 + pmulhuw m3, m4 + movu m4, [rax+t2*2] + pshuflw m5, m5, c_shuf + paddw m2, m4 + psubw m4, [rax-pw_0xff00+pw_32] + punpcklqdq m5, m5 + paddw m3, m4 + mova [buf], m2 + psubusw m2, m5 + mova [buf+16], m3 + psubusw m3, m5 + pxor m4, m4 + pcmpeqw m2, m4 + pcmpeqw m3, m4 + packsswb m5, m2, m3 + pmovmskb eax, m5 + test t3d, t3d + jz .renorm + movzx t3d, word [t1+t4*2] + pcmpeqw m4, m4 + mova m5, m4 + lea t2d, [t3+80] ; only support n_symbols > 2 + shr t2d, 4 + cmp t3d, 32 + adc t3d, 0 + pavgw m4, m2 + pavgw m5, m3 + psubw m4, m0 + psubw m0, m2 + movd m2, t2d + psubw m5, m1 + psubw m1, m3 + psraw m4, m2 + psraw m5, m2 + paddw m0, m4 + paddw m1, m5 + mova [t1], m0 + mova [t1+16], m1 + mov [t1+t4*2], t3w +.renorm: + tzcnt eax, eax + mov t4, [t0+msac.dif] + movzx t1d, word [buf+rax*2] + movzx t2d, word [buf+rax*2-2] +%if WIN64 + add rsp, 48 +%endif + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm2 + +cglobal msac_decode_bool_adapt, 0, 6, 0 + movifnidn t1, r1mp + movifnidn t0, r0mp + movzx eax, word [t1] + movzx t3d, byte [t0+msac.rng+1] + mov t4, [t0+msac.dif] + mov t2d, [t0+msac.rng] +%if ARCH_X86_64 + mov t5d, eax +%endif + and eax, ~63 + imul eax, t3d +%if UNIX64 + mov t6, t4 +%endif + shr eax, 7 + add eax, 4 ; v + mov t3d, eax + shl rax, gprsize*8-16 ; vw + sub t2d, t3d ; r - v + sub t4, rax ; dif - vw + setb al + cmovb t2d, t3d + mov t3d, [t0+msac.update_cdf] +%if UNIX64 + cmovb t4, t6 +%else + cmovb t4, [t0+msac.dif] +%endif +%if ARCH_X86_64 == 0 + movzx eax, al +%endif + not t4 + test t3d, t3d + jz m(msac_decode_symbol_adapt4, SUFFIX).renorm3 +%if UNIX64 == 0 + push t6 +%endif + movzx t6d, word [t1+2] +%if ARCH_X86_64 == 0 + push t5 + movzx t5d, word [t1] +%endif + movifnidn t7, t0 + lea ecx, [t6+64] + cmp t6d, 32 + adc t6d, 0 + mov [t1+2], t6w + imul t6d, eax, -32769 + shr ecx, 4 ; rate + add t6d, t5d ; if (bit) + sub t5d, eax ; cdf[0] -= ((cdf[0] - 32769) >> rate) + 1; + sar t6d, cl ; else + sub t5d, t6d ; cdf[0] -= cdf[0] >> rate; + mov [t1], t5w +%if WIN64 + mov t1d, [t7+msac.cnt] + pop t6 + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm4 +%else +%if ARCH_X86_64 == 0 + pop t5 + pop t6 +%endif + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm3 +%endif + +cglobal msac_decode_bool_equi, 0, 6, 0 + movifnidn t0, r0mp + mov t1d, [t0+msac.rng] + mov t4, [t0+msac.dif] + mov t2d, t1d + mov t1b, 8 + mov t3, t4 + mov eax, t1d + shr t1d, 1 ; v + shl rax, gprsize*8-17 ; vw + sub t2d, t1d ; r - v + sub t4, rax ; dif - vw + cmovb t2d, t1d + mov t1d, [t0+msac.cnt] + cmovb t4, t3 + movifnidn t7, t0 + mov ecx, 0xbfff + setb al ; the upper 32 bits contains garbage but that's OK + sub ecx, t2d + not t4 + ; In this case of this function, (d =) 16 - clz(v) = 2 - (v >> 14) + ; i.e. (0 <= d <= 2) and v < (3 << 14) + shr ecx, 14 ; d +%if ARCH_X86_64 == 0 + movzx eax, al +%endif + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm5 + +cglobal msac_decode_bool, 0, 6, 0 + movifnidn t0, r0mp + movifnidn t1d, r1m + movzx eax, byte [t0+msac.rng+1] ; r >> 8 + mov t4, [t0+msac.dif] + mov t2d, [t0+msac.rng] + and t1d, ~63 + imul eax, t1d + mov t3, t4 + shr eax, 7 + add eax, 4 ; v + mov t1d, eax + shl rax, gprsize*8-16 ; vw + sub t2d, t1d ; r - v + sub t4, rax ; dif - vw + cmovb t2d, t1d + cmovb t4, t3 + setb al + not t4 +%if ARCH_X86_64 == 0 + movzx eax, al +%endif + jmp m(msac_decode_symbol_adapt4, SUFFIX).renorm3 + +%macro HI_TOK 1 ; update_cdf +%if ARCH_X86_64 == 0 + mov eax, -24 +%endif +%%loop: +%if %1 + movzx t2d, word [t1+3*2] +%endif + mova m1, m0 + pshuflw m2, m2, q0000 + psrlw m1, 6 + movd [buf+12], m2 + pand m2, m4 + psllw m1, 7 + pmulhuw m1, m2 +%if ARCH_X86_64 == 0 + add eax, 5 + mov [buf+8], eax +%endif + pshuflw m3, m3, c_shuf + paddw m1, m5 + movq [buf+16], m1 + psubusw m1, m3 + pxor m2, m2 + pcmpeqw m1, m2 + pmovmskb eax, m1 +%if %1 + lea ecx, [t2+80] + pcmpeqw m2, m2 + shr ecx, 4 + cmp t2d, 32 + adc t2d, 0 + movd m3, ecx + pavgw m2, m1 + psubw m2, m0 + psubw m0, m1 + psraw m2, m3 + paddw m0, m2 + movq [t1], m0 + mov [t1+3*2], t2w +%endif + tzcnt eax, eax + movzx ecx, word [buf+rax+16] + movzx t2d, word [buf+rax+14] + not t4 +%if ARCH_X86_64 + add t6d, 5 +%endif + sub eax, 5 ; setup for merging the tok_br and tok branches + sub t2d, ecx + shl rcx, gprsize*8-16 + add t4, rcx + bsr ecx, t2d + xor ecx, 15 + shl t2d, cl + shl t4, cl + movd m2, t2d + mov [t7+msac.rng], t2d + not t4 + sub t5d, ecx + jae %%end + mov t2, [t7+msac.buf] + mov rcx, [t7+msac.end] +%if UNIX64 == 0 + push t8 +%endif + lea t8, [t2+gprsize] + cmp t8, rcx + ja %%refill_eob + mov t2, [t2] + lea ecx, [t5+23] + add t5d, 16 + shr ecx, 3 + bswap t2 + sub t8, rcx + shl ecx, 3 + shr t2, cl + sub ecx, t5d + mov t5d, gprsize*8-16 + shl t2, cl + mov [t7+msac.buf], t8 +%if UNIX64 == 0 + pop t8 +%endif + sub t5d, ecx + xor t4, t2 +%%end: + movp m3, t4 +%if ARCH_X86_64 + add t6d, eax ; CF = tok_br < 3 || tok == 15 + jnc %%loop + lea eax, [t6+30] +%else + add eax, [buf+8] + jnc %%loop + add eax, 30 +%if STACK_ALIGNMENT >= 16 + add esp, 36 +%else + mov esp, [esp] +%endif +%endif + mov [t7+msac.dif], t4 + shr eax, 1 + mov [t7+msac.cnt], t5d + RET +%%refill_eob: + mov t8, rcx + mov ecx, gprsize*8-24 + sub ecx, t5d +%%refill_eob_loop: + cmp t2, t8 + jae %%refill_eob_end + movzx t5d, byte [t2] + inc t2 + shl t5, cl + xor t4, t5 + sub ecx, 8 + jge %%refill_eob_loop +%%refill_eob_end: +%if UNIX64 == 0 + pop t8 +%endif + mov t5d, gprsize*8-24 + mov [t7+msac.buf], t2 + sub t5d, ecx + jmp %%end +%endmacro + +cglobal msac_decode_hi_tok, 0, 7 + ARCH_X86_64, 6 + DECODE_SYMBOL_ADAPT_INIT 1 +%if ARCH_X86_64 == 0 && PIC + LEA t2, min_prob+12*2 + %define base t2-(min_prob+12*2) +%else + %define base 0 +%endif + movq m0, [t1] + movd m2, [t0+msac.rng] + mov eax, [t0+msac.update_cdf] + movq m4, [base+pw_0xff00] + movp m3, [t0+msac.dif] + movq m5, [base+min_prob+12*2] + mov t4, [t0+msac.dif] + mov t5d, [t0+msac.cnt] +%if ARCH_X86_64 + mov t6d, -24 +%endif + movifnidn t7, t0 + test eax, eax + jz .no_update_cdf + HI_TOK 1 +.no_update_cdf: + HI_TOK 0 + +%if ARCH_X86_64 +INIT_YMM avx2 +cglobal msac_decode_symbol_adapt16, 3, 6, 6 + lea rax, [pw_0xff00] + vpbroadcastw m2, [t0+msac.rng] + mova m0, [t1] + vpbroadcastw m3, [t0+msac.dif+6] + vbroadcasti128 m4, [rax] + mov t3d, [t0+msac.update_cdf] + mov t4d, t2d + not t2 + mov r5, rsp +%if WIN64 + and rsp, ~31 + sub rsp, 40 +%else + and r5, ~31 + %define buf r5-32 +%endif + psrlw m1, m0, 6 + movd [buf-4], xm2 + pand m2, m4 + psllw m1, 7 + pmulhuw m1, m2 + paddw m1, [rax+t2*2] + mova [buf], m1 + pmaxuw m1, m3 + pcmpeqw m1, m3 + pmovmskb eax, m1 + test t3d, t3d + jz .renorm + movzx t3d, word [t1+t4*2] + pcmpeqw m2, m2 + lea t2d, [t3+80] + shr t2d, 4 + cmp t3d, 32 + adc t3d, 0 + movd xm3, t2d + pavgw m2, m1 + psubw m2, m0 + psubw m0, m1 + psraw m2, xm3 + paddw m0, m2 + mova [t1], m0 + mov [t1+t4*2], t3w +.renorm: + tzcnt eax, eax + mov t4, [t0+msac.dif] + movzx t1d, word [buf+rax-0] + movzx t2d, word [buf+rax-2] + shr eax, 1 +%if WIN64 + mov rsp, r5 +%endif + vzeroupper + jmp m(msac_decode_symbol_adapt4, _sse2).renorm2 +%endif diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sad_avx.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_avx.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sad_avx.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_avx.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,204 @@ +; +; Copyright (c) 2016, Alliance for Open Media. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. +; + +; + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION .text + +%macro SAD_FN 4 +%if %4 == 0 +%if %3 == 5 +cglobal sad%1x%2, 4, %3, 5, src, src_stride, ref, ref_stride, n_rows +%else ; %3 == 7 +cglobal sad%1x%2, 4, %3, 6, src, src_stride, ref, ref_stride, \ + src_stride3, ref_stride3, n_rows +%endif ; %3 == 5/7 +%else ; avg +%if %3 == 5 +cglobal sad%1x%2_avg, 5, 1 + %3, 5, src, src_stride, ref, ref_stride, \ + second_pred, n_rows +%else ; %3 == 7 +cglobal sad%1x%2_avg, 5, ARCH_X86_64 + %3, 6, src, src_stride, \ + ref, ref_stride, \ + second_pred, \ + src_stride3, ref_stride3 +%if ARCH_X86_64 +%define n_rowsd r7d +%else ; x86-32 +%define n_rowsd dword r0m +%endif ; x86-32/64 +%endif ; %3 == 5/7 +%endif ; avg/sad + movsxdifnidn src_strideq, src_strided + movsxdifnidn ref_strideq, ref_strided +%if %3 == 7 + lea src_stride3q, [src_strideq*3] + lea ref_stride3q, [ref_strideq*3] +%endif ; %3 == 7 +%endmacro + +; unsigned int aom_sad128x128_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD128XN 1-2 0 + SAD_FN 128, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+32] + movu m3, [refq+64] + movu m4, [refq+96] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + vpsadbw m1, [srcq] + vpsadbw m2, [srcq+32] + vpsadbw m3, [srcq+64] + vpsadbw m4, [srcq+96] + + add refq, ref_strideq + add srcq, src_strideq + + vpaddd m1, m2 + vpaddd m3, m4 + vpaddd m0, m1 + vpaddd m0, m3 + + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + + RET +%endmacro + +INIT_YMM avx2 +SAD128XN 128 ; sad128x128_avx2 +SAD128XN 128, 1 ; sad128x128_avg_avx2 +SAD128XN 64 ; sad128x64_avx2 +SAD128XN 64, 1 ; sad128x64_avg_avx2 + + +; unsigned int aom_sad64x64_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD64XN 1-2 0 + SAD_FN 64, %1, 5, %2 + mov n_rowsd, %1/2 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+32] + movu m3, [refq+ref_strideq] + movu m4, [refq+ref_strideq+32] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + vpsadbw m1, [srcq] + vpsadbw m2, [srcq+32] + vpsadbw m3, [srcq+src_strideq] + vpsadbw m4, [srcq+src_strideq+32] + + vpaddd m1, m2 + vpaddd m3, m4 + lea refq, [refq+ref_strideq*2] + vpaddd m0, m1 + lea srcq, [srcq+src_strideq*2] + vpaddd m0, m3 + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + RET +%endmacro + +INIT_YMM avx2 +SAD64XN 128 ; sad64x128_avx2 +SAD64XN 128, 1 ; sad64x128_avg_avx2 +SAD64XN 64 ; sad64x64_avx2 +SAD64XN 32 ; sad64x32_avx2 +SAD64XN 64, 1 ; sad64x64_avg_avx2 +SAD64XN 32, 1 ; sad64x32_avg_avx2 +SAD64XN 16 ; sad64x16_avx2 +SAD64XN 16, 1 ; sad64x16_avg_avx2 + + +; unsigned int aom_sad32x32_avx2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD32XN 1-2 0 + SAD_FN 32, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+ref_strideq] + movu m3, [refq+ref_strideq*2] + movu m4, [refq+ref_stride3q] +%if %2 == 1 + vpavgb m1, [second_predq+mmsize*0] + vpavgb m2, [second_predq+mmsize*1] + vpavgb m3, [second_predq+mmsize*2] + vpavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+src_strideq] + psadbw m3, [srcq+src_strideq*2] + psadbw m4, [srcq+src_stride3q] + + vpaddd m1, m2 + vpaddd m3, m4 + lea refq, [refq+ref_strideq*4] + vpaddd m0, m1 + lea srcq, [srcq+src_strideq*4] + vpaddd m0, m3 + dec n_rowsd + jg .loop + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + + movhlps xm1, xm0 + paddd xm0, xm1 + movd eax, xm0 + RET +%endmacro + +INIT_YMM avx2 +SAD32XN 64 ; sad32x64_avx2 +SAD32XN 32 ; sad32x32_avx2 +SAD32XN 16 ; sad32x16_avx2 +SAD32XN 64, 1 ; sad32x64_avg_avx2 +SAD32XN 32, 1 ; sad32x32_avg_avx2 +SAD32XN 16, 1 ; sad32x16_avg_avx2 +SAD32XN 8 ; sad_32x8_avx2 +SAD32XN 8, 1 ; sad_32x8_avg_avx2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sad_sse2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_sse2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sad_sse2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sad_sse2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,354 @@ +; +; Copyright (c) 2016, Alliance for Open Media. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. +; + +; + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION .text + +%macro SAD_FN 4 +%if %4 == 0 +%if %3 == 5 +cglobal sad%1x%2, 4, %3, 5, src, src_stride, ref, ref_stride, n_rows +%else ; %3 == 7 +cglobal sad%1x%2, 4, %3, 6, src, src_stride, ref, ref_stride, \ + src_stride3, ref_stride3, n_rows +%endif ; %3 == 5/7 +%else ; avg +%if %3 == 5 +cglobal sad%1x%2_avg, 5, 1 + %3, 5, src, src_stride, ref, ref_stride, \ + second_pred, n_rows +%else ; %3 == 7 +cglobal sad%1x%2_avg, 5, ARCH_X86_64 + %3, 6, src, src_stride, \ + ref, ref_stride, \ + second_pred, \ + src_stride3, ref_stride3 +%if ARCH_X86_64 +%define n_rowsd r7d +%else ; x86-32 +%define n_rowsd dword r0m +%endif ; x86-32/64 +%endif ; %3 == 5/7 +%endif ; avg/sad + movsxdifnidn src_strideq, src_strided + movsxdifnidn ref_strideq, ref_strided +%if %3 == 7 + lea src_stride3q, [src_strideq*3] + lea ref_stride3q, [ref_strideq*3] +%endif ; %3 == 7 +%endmacro + +; unsigned int aom_sad128x128_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD128XN 1-2 0 + SAD_FN 128, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+32] + movu m4, [refq+48] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+32] + psadbw m4, [srcq+48] + + paddd m1, m2 + paddd m3, m4 + paddd m0, m1 + paddd m0, m3 + + movu m1, [refq+64] + movu m2, [refq+80] + movu m3, [refq+96] + movu m4, [refq+112] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*4] + pavgb m2, [second_predq+mmsize*5] + pavgb m3, [second_predq+mmsize*6] + pavgb m4, [second_predq+mmsize*7] + lea second_predq, [second_predq+mmsize*8] +%endif + psadbw m1, [srcq+64] + psadbw m2, [srcq+80] + psadbw m3, [srcq+96] + psadbw m4, [srcq+112] + + add refq, ref_strideq + add srcq, src_strideq + + paddd m1, m2 + paddd m3, m4 + paddd m0, m1 + paddd m0, m3 + + sub n_rowsd, 1 + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD128XN 128 ; sad128x128_sse2 +SAD128XN 128, 1 ; sad128x128_avg_sse2 +SAD128XN 64 ; sad128x64_sse2 +SAD128XN 64, 1 ; sad128x64_avg_sse2 + + +; unsigned int aom_sad64x64_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD64XN 1-2 0 + SAD_FN 64, %1, 5, %2 + mov n_rowsd, %1 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+32] + movu m4, [refq+48] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+32] + psadbw m4, [srcq+48] + paddd m1, m2 + paddd m3, m4 + add refq, ref_strideq + paddd m0, m1 + add srcq, src_strideq + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD64XN 128 ; sad64x128_sse2 +SAD64XN 128, 1 ; sad64x128_avg_sse2 +SAD64XN 64 ; sad64x64_sse2 +SAD64XN 32 ; sad64x32_sse2 +SAD64XN 64, 1 ; sad64x64_avg_sse2 +SAD64XN 32, 1 ; sad64x32_avg_sse2 +SAD64XN 16 ; sad64x16_sse2 +SAD64XN 16, 1 ; sad64x16_avg_sse2 + +; unsigned int aom_sad32x32_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD32XN 1-2 0 + SAD_FN 32, %1, 5, %2 + mov n_rowsd, %1/2 + pxor m0, m0 +.loop: + movu m1, [refq] + movu m2, [refq+16] + movu m3, [refq+ref_strideq] + movu m4, [refq+ref_strideq+16] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+16] + psadbw m3, [srcq+src_strideq] + psadbw m4, [srcq+src_strideq+16] + paddd m1, m2 + paddd m3, m4 + lea refq, [refq+ref_strideq*2] + paddd m0, m1 + lea srcq, [srcq+src_strideq*2] + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD32XN 64 ; sad32x64_sse2 +SAD32XN 32 ; sad32x32_sse2 +SAD32XN 16 ; sad32x16_sse2 +SAD32XN 64, 1 ; sad32x64_avg_sse2 +SAD32XN 32, 1 ; sad32x32_avg_sse2 +SAD32XN 16, 1 ; sad32x16_avg_sse2 +SAD32XN 8 ; sad_32x8_sse2 +SAD32XN 8, 1 ; sad_32x8_avg_sse2 + +; unsigned int aom_sad16x{8,16}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD16XN 1-2 0 + SAD_FN 16, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movu m1, [refq] + movu m2, [refq+ref_strideq] + movu m3, [refq+ref_strideq*2] + movu m4, [refq+ref_stride3q] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + pavgb m3, [second_predq+mmsize*2] + pavgb m4, [second_predq+mmsize*3] + lea second_predq, [second_predq+mmsize*4] +%endif + psadbw m1, [srcq] + psadbw m2, [srcq+src_strideq] + psadbw m3, [srcq+src_strideq*2] + psadbw m4, [srcq+src_stride3q] + paddd m1, m2 + paddd m3, m4 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + paddd m0, m3 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD16XN 32 ; sad16x32_sse2 +SAD16XN 16 ; sad16x16_sse2 +SAD16XN 8 ; sad16x8_sse2 +SAD16XN 32, 1 ; sad16x32_avg_sse2 +SAD16XN 16, 1 ; sad16x16_avg_sse2 +SAD16XN 8, 1 ; sad16x8_avg_sse2 +SAD16XN 4 ; sad_16x4_sse2 +SAD16XN 4, 1 ; sad_16x4_avg_sse2 +SAD16XN 64 ; sad_16x64_sse2 +SAD16XN 64, 1 ; sad_16x64_avg_sse2 + +; unsigned int aom_sad8x{8,16}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD8XN 1-2 0 + SAD_FN 8, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movh m1, [refq] + movhps m1, [refq+ref_strideq] + movh m2, [refq+ref_strideq*2] + movhps m2, [refq+ref_stride3q] +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + pavgb m2, [second_predq+mmsize*1] + lea second_predq, [second_predq+mmsize*2] +%endif + movh m3, [srcq] + movhps m3, [srcq+src_strideq] + movh m4, [srcq+src_strideq*2] + movhps m4, [srcq+src_stride3q] + psadbw m1, m3 + psadbw m2, m4 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + paddd m0, m2 + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD8XN 16 ; sad8x16_sse2 +SAD8XN 8 ; sad8x8_sse2 +SAD8XN 4 ; sad8x4_sse2 +SAD8XN 16, 1 ; sad8x16_avg_sse2 +SAD8XN 8, 1 ; sad8x8_avg_sse2 +SAD8XN 4, 1 ; sad8x4_avg_sse2 +SAD8XN 32 ; sad_8x32_sse2 +SAD8XN 32, 1 ; sad_8x32_avg_sse2 + +; unsigned int aom_sad4x{4, 8}_sse2(uint8_t *src, int src_stride, +; uint8_t *ref, int ref_stride); +%macro SAD4XN 1-2 0 + SAD_FN 4, %1, 7, %2 + mov n_rowsd, %1/4 + pxor m0, m0 + +.loop: + movd m1, [refq] + movd m2, [refq+ref_strideq] + movd m3, [refq+ref_strideq*2] + movd m4, [refq+ref_stride3q] + punpckldq m1, m2 + punpckldq m3, m4 + movlhps m1, m3 +%if %2 == 1 + pavgb m1, [second_predq+mmsize*0] + lea second_predq, [second_predq+mmsize*1] +%endif + movd m2, [srcq] + movd m5, [srcq+src_strideq] + movd m4, [srcq+src_strideq*2] + movd m3, [srcq+src_stride3q] + punpckldq m2, m5 + punpckldq m4, m3 + movlhps m2, m4 + psadbw m1, m2 + lea refq, [refq+ref_strideq*4] + paddd m0, m1 + lea srcq, [srcq+src_strideq*4] + dec n_rowsd + jg .loop + + movhlps m1, m0 + paddd m0, m1 + movd eax, m0 + RET +%endmacro + +INIT_XMM sse2 +SAD4XN 8 ; sad4x8_sse +SAD4XN 4 ; sad4x4_sse +SAD4XN 8, 1 ; sad4x8_avg_sse +SAD4XN 4, 1 ; sad4x4_avg_sse +SAD4XN 16 ; sad_4x16_sse2 +SAD4XN 16, 1 ; sad_4x16_avg_sse2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/satd.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/satd.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,979 @@ +; Copyright (c) 2019, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%if ARCH_X86_64 + +SECTION_RODATA 32 +maddubsw_hsub: times 16 db 1, -1 + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +; Perform 4x4 hadamard transform on input with 2 rows per register. +; Rows 0 and 2 are in m0 and rows 1 and 3 are in m1. +; A second set of packed input can also be taken in m2 and m3. +; Ends with sums in every other entry (i.e. already reduced horizontally). +%macro HADAMARD_4x4_PACKED 1 +%if %1 == 1 + %define tmp m2 + ; 2->0, 1->2, 0->2 + %define ROTATE SWAP 2, 1, 0 +%elif %1 == 2 + %define tmp m4 + ; 4->0, 3->2, 2->3, 1->2, 0->1 + %define ROTATE SWAP 4, 3, 2, 1, 0 +%endif + ; m0 d2 c2 b2 a2 d0 c0 b0 a0 + ; m1 d3 c3 b3 a3 d1 c1 b1 a1 + + ; Stage 1 + ; m0 d2+d3 c2+c3 b2+b3 a2+a3 d0+d1 c0+c1 b0+b1 a0+a1 + ; m1 d2-d3 c2-c3 b2-b3 a2-a3 d0-d1 c0-c1 b0-b1 a0-a1 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; Stage 2 + ; m0 d0-d1 d0+d1 c0-c1 c0+c1 b0-b1 b0+b1 a0-a1 a0+a1 + ; m1 d2-d3 d2+d3 c2-c3 c2+c3 b2-b3 b2+b3 a2-a3 a2+a3 + punpcklwd tmp, m0, m1 + punpckhwd m0, m1 +%if %1 == 2 + punpcklwd m1, m2, m3 + punpckhwd m2, m3 +%endif + ROTATE + + ; m0 d0-d1+d2-d3 d0+d1+d2+d3 c0-c1+c2-c3 c0+c1+c2+c3 + ; b0-b1+b2-b3 b0+b1+b2+b3 a0-a1+a2-a3 a0+a1+a2+a3 + ; m1 d0-d2-d2+d3 d0+d1-d2-d3 c0-c1-c2+c3 c0+c1-c2-c3 + ; b0-b1-b2+b3 b0+b1-b2-b3 a0-a1-a2-a3 a0+a1-a2-a3 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; m0 s2 s0 r2 r0 q2 q0 p2 p0 + ; m1 s3 s1 r3 r1 q3 q1 p3 p1 + + ; Stage 1 + ; m0 q3 q1 q2 q0 p3 p1 p2 p0 + ; m1 s3 s1 s2 s0 r3 r1 r2 r0 + punpckldq tmp, m0, m1 + punpckhdq m0, m1 +%if %1 == 2 + punpckldq m1, m2, m3 + punpckhdq m2, m3 +%endif + ROTATE + + ; m0 q3+s3 q1+s1 q2+s2 q0+s0 p3+r3 p1+r1 p2+r2 p0+r0 + ; m1 q3-s3 q1-s1 q2-s2 q0-s0 p3-r3 p1-r1 p2-r2 p0-r0 + paddw tmp, m0, m1 + psubw m0, m1 +%if %1 == 2 + paddw m1, m2, m3 + psubw m2, m3 +%endif + ROTATE + + ; Stage 2 + ; m0 p3-r3 p1-r1 p2-r2 p0-r0 p3+r3 p1+r1 p2+r2 p0+r0 + ; m1 q3-s3 q1-s1 q2-s2 q0-s0 q3+s3 q1+s1 q2+s2 q0+s0 + punpcklqdq tmp, m0, m1 + punpckhqdq m0, m1 +%if %1 == 2 + punpcklqdq m1, m2, m3 + punpckhqdq m2, m3 +%endif + ROTATE + + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw tmp, m0, m1 + pmaxsw m0, m1 + ; m1 is free + ; 0x7FFF + pcmpeqb m1, m1 + psrlw m1, 1 + + paddsw tmp, m1 + psubw m0, tmp +%if %1 == 2 + paddw tmp, m2, m3 + pmaxsw m2, m3 + paddsw tmp, m1 + psubw m2, tmp + + paddw m0, m2 +%endif +%endmacro + +; Load diffs of 4 entries for 2 rows +%macro LOAD_PACK_DIFF_Dx2 7 + movd m%1, %2 + movd m%6, %4 + punpckldq m%1, m%6 + pmovzxbw m%1, m%1 + movd m%6, %3 + movd m%7, %5 + punpckldq m%6, m%7 + pmovzxbw m%6, m%6 + psubw m%1, m%6 +%endmacro + +; Can only use 128-bit vectors +%macro SATD_4x4_FN 0 +cglobal satd_4x4, 4, 6, 4, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + + ; Load rows 0 and 2 to m0 and 1 and 3 to m1 + LOAD_PACK_DIFF_Dx2 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + 2, 3 + LOAD_PACK_DIFF_Dx2 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + 2, 3 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + pshufd m1, m0, q3232 + paddw m0, m1 + pshuflw m1, m0, q3232 + paddw m0, m1 + pshuflw m1, m0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw m0, m1 + movd eax, m0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 4 + RET +%endmacro + +INIT_XMM sse4 +SATD_4x4_FN + +INIT_XMM avx2 +SATD_4x4_FN + +; Load diffs of 8 entries for 2 row +; Each set of 4 columns share an 128-bit lane +%macro LOAD_PACK_DIFF_Qx2 7 + movq xm%1, %2 + movq xm%6, %4 + punpckldq xm%1, xm%6 + pmovzxbw m%1, xm%1 + movq xm%6, %3 + movq xm%7, %5 + punpckldq xm%6, xm%7 + pmovzxbw m%6, xm%6 + psubw m%1, m%6 +%endmacro + +INIT_YMM avx2 +cglobal satd_8x4, 4, 6, 4, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + ; Load rows 0 and 2 to m0 and 1 and 3 to m1 + ; Each set of 4 columns share 128-bit lanes + LOAD_PACK_DIFF_Qx2 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + 2, 3 + LOAD_PACK_DIFF_Qx2 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + 2, 3 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 8 + RET + +; Load diffs of 4 entries for 4 rows +; Each set of two rows share 128-bit lanes +%macro LOAD_PACK_DIFF_Dx4 12 + movd xm%1, %2 + movd xm%10, %4 + punpckldq xm%1, xm%10 + movd xm%10, %6 + movd xm%11, %8 + punpckldq xm%10, xm%11 + punpcklqdq xm%1, xm%10 + pmovzxbw m%1, xm%1 + movd xm%10, %3 + movd xm%11, %5 + punpckldq xm%10, xm%11 + movd xm%11, %7 + movd xm%12, %9 + punpckldq xm%11, xm%12 + punpcklqdq xm%10, xm%11 + pmovzxbw m%10, xm%10 + psubw m%1, m%10 +%endmacro + +INIT_YMM avx2 +cglobal satd_4x8, 4, 8, 5, src, src_stride, dst, dst_stride, \ + src4, dst4, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src4q, [srcq+src_strideq*4] + lea dst4q, [dstq+dst_strideq*4] + ; Load rows 0, 2, 4 and 6 to m0 and 1, 3, 5 and 7 to m1. + ; Lanes split the low and high rows of m0 and m1. + LOAD_PACK_DIFF_Dx4 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 2, 3, 4 + LOAD_PACK_DIFF_Dx4 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 2, 3, 4 + + HADAMARD_4x4_PACKED 1 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation. + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + sub ax, 8 + RET + +; Rudimentary fast hadamard transform +; Two Hadamard transforms share an 128-bit lane. +%macro HADAMARD_4x4 0 + ; 4->0, 3->2, 2->3, 1->2, 0->1 + %define ROTATE SWAP 4, 3, 2, 1, 0 + + ; Stage 1 + paddw m0, m1, m2 + psubw m1, m2 + paddw m2, m3, m4 + psubw m3, m4 + ROTATE + + ; Stage 2 + paddw m0, m1, m3 + psubw m1, m3 + paddw m3, m2, m4 + psubw m2, m4 + SWAP 3, 2, 1 + ROTATE + + ; Transpose + ; Since two transforms share an 128-bit lane, unpacking results in a single + ; transform's values on each register. This has to be resolved later. + ; A and B indicate different 4x4 transforms. + + ; Start + ; m1 B (a3 a2 a1 a0) A (a3 a2 a1 a0) + ; m2 B (b3 b2 b1 b0) A (b3 b2 b1 b0) + ; m3 B (c3 c2 c1 c0) A (c3 c2 c1 c0) + ; m4 B (d3 d2 d1 d0) A (d3 d2 d1 d0) + + ; Stage 1 + ; m1 A (b3 a3 b2 a2 b1 a1 b0 a0) + ; m2 B (b3 a3 b2 a2 b1 a1 b0 a0) + ; m3 A (d3 c3 d2 c2 d1 c1 d0 c0) + ; m4 B (d3 c3 d2 c2 d1 c1 d0 c0) + punpcklwd m0, m1, m2 + punpckhwd m1, m2 + punpcklwd m2, m3, m4 + punpckhwd m3, m4 + ROTATE + + ; m1 A (d3 c3 b3 a3 d2 c2 b2 a2) + ; m2 A (d1 c1 b1 a1 d0 c0 b0 a0) + ; m3 B (d3 c3 b3 a3 d2 c2 b2 a2) + ; m4 B (d1 c1 b1 a1 d0 c0 b0 a0) + punpckldq m0, m1, m3 + punpckhdq m1, m3 + punpckldq m3, m2, m4 + punpckhdq m2, m4 + SWAP 3, 2, 1 + ROTATE + + ; Make the transforms share 128-bit lanes again. + ; m1 B (d0 c0 b0 a0) A (d0 c0 b0 a0) + ; m2 B (d1 c1 b1 a1) A (d1 c1 b1 a1) + ; m3 B (d2 c2 b2 a2) A (d2 c2 b2 a2) + ; m4 B (d3 c3 b3 a3) A (d3 c3 b3 a3) + punpcklqdq m0, m1, m2 + punpckhqdq m1, m2 + punpcklqdq m2, m3, m4 + punpckhqdq m3, m4 + ROTATE + + ; Stage 1 + paddw m0, m1, m2 + psubw m1, m2 + paddw m2, m3, m4 + psubw m3, m4 + ROTATE + + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw m0, m1, m3 + pmaxsw m1, m3 + ; m2 is free + ; 0x7FFF + pcmpeqb m3, m3 + psrlw m3, 1 + + paddsw m0, m3 + psubw m1, m0 + + paddw m0, m2, m4 + pmaxsw m2, m4 + paddsw m0, m3 + psubw m2, m0 + + paddw m1, m2 + SWAP 1, 0 +%endmacro + +; Load diffs of 16 entries for 1 row +%macro LOAD_DIFF_DQ 4 + movu xm%1, %2 + movu xm%4, %3 + vpmovzxbw m%1, xm%1 + vpmovzxbw m%4, xm%4 + psubw m%1, m%4 +%endmacro + +INIT_YMM avx2 +cglobal satd_16x4, 4, 6, 5, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_4x4 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + ; Avoids overflow in this case + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 16 + RET + +INIT_YMM avx2 +cglobal satd_4x16, 4, 8, 7, src, src_stride, dst, dst_stride, \ + src4, dst4, src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src4q, [srcq+src_strideq*4] + lea dst4q, [dstq+dst_strideq*4] + LOAD_PACK_DIFF_Dx4 0, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 4, 5, 6 + LOAD_PACK_DIFF_Dx4 1, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 4, 5, 6 + lea srcq, [srcq+src_strideq*8] + lea dstq, [dstq+dst_strideq*8] + lea src4q, [src4q+src_strideq*8] + lea dst4q, [dst4q+dst_strideq*8] + LOAD_PACK_DIFF_Dx4 2, [srcq], [dstq], \ + [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src4q], [dst4q], \ + [src4q+src_strideq*2], [dst4q+dst_strideq*2], \ + 4, 5, 6 + LOAD_PACK_DIFF_Dx4 3, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src4q+src_strideq*1], [dst4q+dst_strideq*1], \ + [src4q+src_stride3q], [dst4q+dst_stride3q], \ + 4, 5, 6 + HADAMARD_4x4_PACKED 2 + + ; Reduce horizontally + vextracti128 xm1, m0, 1 + paddw xm0, xm1 + pshufd xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q3232 + paddw xm0, xm1 + pshuflw xm1, xm0, q1111 + + ; Perform normalization during the final stage of accumulation + pavgw xm0, xm1 + movd eax, xm0 + movzx eax, ax + + ; Add an offset for how the final butterfly stage and the first stage of + ; accumulation was done. Since this offset is an even number, this can + ; safely be done after normalization using pavgw. + sub ax, 16 + RET + +; On x86-64 we can transpose in-place without spilling registers. +; By clever choices of the order to apply the butterflies and the order of +; their outputs, we can take the rows in order and output the columns in order +; without any extra operations and using just one temporary register. +%macro TRANSPOSE8x8 9 + punpckhwd m%9, m%5, m%6 + punpcklwd m%5, m%6 + ; m%6 is free + punpckhwd m%6, m%1, m%2 + punpcklwd m%1, m%2 + ; m%2 is free + punpckhwd m%2, m%7, m%8 + punpcklwd m%7, m%8 + ; m%8 is free + punpckhwd m%8, m%3, m%4 + punpcklwd m%3, m%4 + ; m%4 is free + punpckhdq m%4, m%1, m%3 + punpckldq m%1, m%3 + ; m%3 is free + punpckldq m%3, m%5, m%7 + punpckhdq m%5, m%7 + ; m%7 is free + punpckhdq m%7, m%6, m%8 + punpckldq m%6, m%8 + ; m%8 is free + punpckldq m%8, m%9, m%2 + punpckhdq m%9, m%2 + ; m%2 is free + punpckhqdq m%2, m%1, m%3 + punpcklqdq m%1, m%3 + ; m%3 is free + punpcklqdq m%3, m%4, m%5 + punpckhqdq m%4, m%5 + ; m%5 is free + punpcklqdq m%5, m%6, m%8 + punpckhqdq m%6, m%8 + ; m%8 is free + punpckhqdq m%8, m%7, m%9 + punpcklqdq m%7, m%9 +%endmacro + +; Load diff of 8 entries for 1 row +%macro LOAD_DIFF_Q 4 + movq %1, %2 + movq %4, %3 + punpcklbw %1, %4 + pmaddubsw %1, hsub +%endmacro + +%macro HADAMARD_8_STAGE_1 9 + paddw m%9, m%1, m%2 + psubw m%1, m%2 + paddw m%2, m%3, m%4 + psubw m%3, m%4 + paddw m%4, m%5, m%6 + psubw m%5, m%6 + paddw m%6, m%7, m%8 + psubw m%7, m%8 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +%macro HADAMARD_8_STAGE_2 9 + paddw m%9, m%1, m%3 ; 0 + psubw m%1, m%3 ; 2 + paddw m%3, m%2, m%4 ; 1 + psubw m%2, m%4 ; 3 + SWAP %3, %2, %1 + paddw m%4, m%5, m%7 ; 4 + psubw m%5, m%7 ; 6 + paddw m%7, m%6, m%8 ; 5 + psubw m%6, m%8 ; 7 + SWAP %7, %6, %5 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +%macro HADAMARD_8_STAGE_3 9 + paddw m%9, m%1, m%5 ; 0 + psubw m%1, m%5 ; 4 + paddw m%5, m%2, m%6 ; 1 + psubw m%2, m%6 ; 5 + paddw m%6, m%3, m%7 ; 2 + psubw m%3, m%7 ; 6 + paddw m%7, m%4, m%8 ; 3 + psubw m%4, m%8 ; 7 + SWAP %5, %2, %6, %3, %7, %4, %1 + ; 8->9, 7->8, 6->7, 5->6, 4->5, 3->4, 2->3, 1->2, 9->1 + SWAP %8, %7, %6, %5, %4, %3, %2, %1, %9 +%endmacro + +; Rudimentary fast hadamard transform +%macro HADAMARD_8x8 0 + HADAMARD_8_STAGE_1 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_2 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_3 1, 2, 3, 4, 5, 6, 7, 8, 0 + + TRANSPOSE8x8 1, 2, 3, 4, 5, 6, 7, 8, 0 + + HADAMARD_8_STAGE_1 1, 2, 3, 4, 5, 6, 7, 8, 0 + HADAMARD_8_STAGE_2 1, 2, 3, 4, 5, 6, 7, 8, 0 + + ; Stage 3 + ; Use the fact that + ; (abs(a+b)+abs(a-b))/2 = max(abs(a),abs(b)) + ; to merge the final butterfly with the abs and the first stage of + ; accumulation. + ; Avoid pabsw by using max(a, b) + max(a + b + 0x7FFF, 0x7FFF) instead. + ; Actually calculates (abs(a+b)+abs(a-b))/2-0x7FFF. + ; The final sum must be offset to compensate for subtracting 0x7FFF. + paddw m0, m1, m5 + pmaxsw m1, m5 + ; m1 is free + ; 0x7FFF + pcmpeqb m5, m5 + psrlw m5, 1 + + paddsw m0, m5 + psubw m1, m0 + + paddw m0, m2, m6 + pmaxsw m2, m6 + paddsw m0, m5 + psubw m2, m0 + + paddw m0, m3, m7 + pmaxsw m3, m7 + paddsw m0, m5 + psubw m3, m0 + + paddw m0, m4, m8 + pmaxsw m4, m8 + paddsw m0, m5 + psubw m4, m0 + + paddw m1, m2 + paddw m3, m4 + + paddw m1, m3 + SWAP 1, 0 +%endmacro + +; Only works with 128 bit vectors +%macro SATD_8x8_FN 0 +cglobal satd_8x8, 4, 6, 10, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_Q m1, [srcq], [dstq], m2 + LOAD_DIFF_Q m2, [srcq+src_strideq*1], [dstq+dst_strideq*1], m3 + LOAD_DIFF_Q m3, [srcq+src_strideq*2], [dstq+dst_strideq*2], m4 + LOAD_DIFF_Q m4, [srcq+src_stride3q], [dstq+dst_stride3q], m5 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_Q m5, [srcq], [dstq], m6 + LOAD_DIFF_Q m6, [srcq+src_strideq*1], [dstq+dst_strideq*1], m7 + LOAD_DIFF_Q m7, [srcq+src_strideq*2], [dstq+dst_strideq*2], m8 + LOAD_DIFF_Q m8, [srcq+src_stride3q], [dstq+dst_stride3q], m9 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + pshufd m1, m0, q3232 + paddd m0, m1 + pshuflw m1, m0, q3232 + paddd m0, m1 + movd eax, m0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 32-2 + shr eax, 2 + RET +%endmacro + +INIT_XMM ssse3 +SATD_8x8_FN + +INIT_XMM avx2 +SATD_8x8_FN + +INIT_YMM avx2 +cglobal satd_16x8, 4, 6, 9, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3 + ; Load rows into m1-m8 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_DQ 5, [srcq], [dstq], 0 + LOAD_DIFF_DQ 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 8, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 64-2 + shr eax, 2 + RET + +%macro LOAD_DIFF_Qx2 7 + movq xm%1, %2 + movq xm%6, %3 + punpcklbw xm%1, xm%6 + movq xm%6, %4 + movq xm%7, %5 + punpcklbw xm%6, xm%7 + vinserti128 m%1, xm%6, 1 + pmaddubsw m%1, hsub +%endmacro + +INIT_YMM avx2 +cglobal satd_8x16, 4, 8, 11, src, src_stride, dst, dst_stride, \ + src8, dst8, src_stride3, dst_stride3 + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + lea src8q, [srcq+src_strideq*8] + lea dst8q, [dstq+dst_strideq*8] + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + LOAD_DIFF_Qx2 1, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 4, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + lea src8q, [src8q+src_strideq*4] + lea dst8q, [dst8q+dst_strideq*4] + LOAD_DIFF_Qx2 5, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 8, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pxor m2, m2 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + paddd m0, m1 + + vextracti128 xm1, m0, 1 + paddd xm0, xm1 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 64-2 + shr eax, 2 + RET + +; Less optimized, boilerplate implementations + +INIT_YMM avx2 +cglobal satd_8x32, 4, 9, 13, src, src_stride, dst, dst_stride, \ + src8, dst8, src_stride3, dst_stride3, cnt + ; ones for converting to 32-bit with pmaddwd + pcmpeqw m11, m11 + pabsw m11, m11 + ; sum + pxor m12, m12 + mov cntd, 1 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + lea src8q, [srcq+src_strideq*8] + lea dst8q, [dstq+dst_strideq*8] +.loop: + %define hsub m0 + mova hsub, [maddubsw_hsub] + ; Load rows into m1-m8 + LOAD_DIFF_Qx2 1, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 4, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + lea src8q, [src8q+src_strideq*4] + lea dst8q, [dst8q+dst_strideq*4] + LOAD_DIFF_Qx2 5, [srcq], [dstq], \ + [src8q], [dst8q], \ + 9, 10 + LOAD_DIFF_Qx2 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], \ + [src8q+src_strideq*1], [dst8q+dst_strideq*1], \ + 9, 10 + LOAD_DIFF_Qx2 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], \ + [src8q+src_strideq*2], [dst8q+dst_strideq*2], \ + 9, 10 + LOAD_DIFF_Qx2 8, [srcq+src_stride3q], [dstq+dst_stride3q], \ + [src8q+src_stride3q], [dst8q+dst_stride3q], \ + 9, 10 + + HADAMARD_8x8 + + ; Reduce horizontally and convert to 32 bits + pmaddwd m0, m11 + paddd m12, m0 + + lea srcq, [srcq+src_stride3q*4] + lea dstq, [dstq+dst_stride3q*4] + lea src8q, [src8q+src_stride3q*4] + lea dst8q, [dst8q+dst_stride3q*4] + dec cntd + jge .loop + + vextracti128 xm0, m12, 1 + paddd xm0, xm12 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, 128-2 + shr eax, 2 + RET + +INIT_YMM avx2 +cglobal satd_16x8_internal, 0, 0, 0, \ + dummy1, src_stride, dummy2, dst_stride, \ + src_stride3, dst_stride3, src, dst + %define hadd m9 + %define sum m10 + ; Load rows into m1-m8 + LOAD_DIFF_DQ 1, [srcq], [dstq], 0 + LOAD_DIFF_DQ 2, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 3, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 4, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + LOAD_DIFF_DQ 5, [srcq], [dstq], 0 + LOAD_DIFF_DQ 6, [srcq+src_strideq*1], [dstq+dst_strideq*1], 0 + LOAD_DIFF_DQ 7, [srcq+src_strideq*2], [dstq+dst_strideq*2], 0 + LOAD_DIFF_DQ 8, [srcq+src_stride3q], [dstq+dst_stride3q], 0 + + HADAMARD_8x8 + + pmaddwd m0, hadd + paddd sum, m0 + ret + +%macro SATD_NXM 2 +%if %1 > 16 +%if %2 > 8 +cglobal satd_%1x%2, 4, 10, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + w, h +%else +cglobal satd_%1x%2, 4, 9, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + w +%endif +%else ; %2 > 8 +cglobal satd_%1x%2, 4, 9, 11, src, src_stride, dst, dst_stride, \ + src_stride3, dst_stride3, call_src, call_dst, \ + h +%endif + ; ones for converting to 32-bit with pmaddwd + pcmpeqw m9, m9 + pabsw m9, m9 + ; sum + pxor m10, m10 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] +%if %2 > 8 + mov hd, %2/8 - 1 +.looph: +%endif +%if %1 > 16 + mov wd, %1/16 - 1 +.loopv: +%endif + mov call_srcq, srcq + mov call_dstq, dstq + call m(satd_16x8_internal) +%if %1 > 16 + add srcq, 16 + add dstq, 16 + dec wd + jge .loopv + sub srcq, %1 + sub dstq, %1 +%endif +%if %2 > 8 + lea srcq, [srcq+src_strideq*8] + lea dstq, [dstq+dst_strideq*8] + dec hd + jge .looph +%endif + + ; Reduce horizontally + vextracti128 xm0, m10, 1 + paddd xm0, xm10 + pshufd xm1, xm0, q3232 + paddd xm0, xm1 + pshuflw xm1, xm0, q3232 + paddd xm0, xm1 + movd eax, xm0 + + ; Normalize + ; Add rounding offset and an offset for how the final butterfly stage and + ; the first stage of accumulation was done. + sub eax, %1*%2/2 - 2 + shr eax, 2 + RET +%endmacro + +INIT_YMM avx2 +SATD_NXM 16, 16 +SATD_NXM 32, 32 +SATD_NXM 64, 64 +SATD_NXM 128, 128 + +SATD_NXM 16, 32 +SATD_NXM 32, 16 +SATD_NXM 32, 64 +SATD_NXM 64, 32 +SATD_NXM 64, 128 +SATD_NXM 128, 64 + +SATD_NXM 32, 8 +SATD_NXM 16, 64 +SATD_NXM 64, 16 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/satd16_avx2.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd16_avx2.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/satd16_avx2.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/satd16_avx2.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1129 @@ +; Copyright (c) 2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +%if ARCH_X86_64 + +SECTION_RODATA 32 + +align 32 +pw_1x16: times 16 dw 1 + +SECTION .text + +%macro NORMALIZE4PT 0 + add eax, 2 + shr eax, 2 +%endmacro + +%macro NORMALIZE8PT 0 + add eax, 4 + shr eax, 3 +%endmacro + +; Add and subtract registers +; +; Takes m0 and m1 as both input and output. +; Requires m2 as a free register. +; +; If we start with this permutation: +; +; m0 0 1 2 3 4 5 6 7 +; m1 8 9 10 11 12 13 14 15 +; +; Then the output will be as such: +; +; m0 [0+8][1+9][2+10][3+11] [4+12][5+13][6+14][7+15] +; m1 [0-8][1-9][2-10][3-11] [4-12][5-13][6-14][7-15] +%macro BUTTERFLY 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + ; use alternate registers 3,4,5 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 32 + %define V ym + %elif VEC_SIZE == 16 + %define V xm + %endif + + ; Use m2 as a temporary register, then swap + ; so that m0 and m1 contain the output. + %if BIT_PRECISION == 16 + paddw V%+ 2, V%+ 0, V%+ 1 + psubw V%+ 0, V%+ 1 + %elif BIT_PRECISION == 32 + paddd ym2, ym0, ym1 + psubd ym0, ym1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + + SWAP 2, 1, 0 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +; Interleave packed rows together (in m0 and m1). +; m2 should contain a free register. +; +; Macro argument takes size in bits of each element (where one +; element is the difference between two original source pixels). +; +; If we start with this permutation: +; +; m0 0 1 2 3 4 5 6 7 +; m1 8 9 10 11 12 13 14 15 +; +; Then, after INTERLEAVE, this will be the permutation: +; +; m0 0 8 1 9 2 10 3 11 +; m1 4 12 5 13 6 14 7 15 +%macro INTERLEAVE 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + %if BIT_PRECISION == 16 + punpcklwd V%+ 2, V%+ 0, V%+ 1 + punpckhwd V%+ 0, V%+ 1 + SWAP 2, 1, 0 + %elif BIT_PRECISION == 32 + punpckldq ym2, ym0, ym1 + punpckhdq ym0, ym1 + ; AVX2 shuffles operate over 128-bit halves of the full ymm register + ; in parallel, so these shuffles are required to fix up the permutation. + vperm2i128 ym1, ym2, ym0, 0x20 + vperm2i128 ym0, ym2, ym0, 0x31 + SWAP 0, 1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +; Interleave pairs of 2 elements (in m0 and m1) +; m2 should contain a free register. +%macro INTERLEAVE_PAIRS 3 + %define BIT_PRECISION %1 + %define VEC_SIZE %2 + %define USE_ALT %3 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + %if BIT_PRECISION == 16 + punpckldq V%+ 2, V%+ 0, V%+ 1 + punpckhdq V%+ 0, V%+ 1 + %elif BIT_PRECISION == 32 + punpcklqdq ym2, ym0, ym1 + punpckhqdq ym0, ym1 + %else + %error Incorrect precision specified (16 or 32 expected) + %endif + SWAP 2, 1, 0 + + %if USE_ALT == 1 + SWAP 3, 0 + SWAP 4, 1 + SWAP 5, 2 + %endif +%endmacro + +%macro HADAMARD_4X4_PACKED 2 + %define BIT_PRECISION %1 + ; Register size to use (in bytes) + %define VEC_SIZE %2 + + %if VEC_SIZE == 16 + %define V xm + %elif VEC_SIZE == 32 + %define V ym + %else + %error Invalid vector size (expected 16 or 32) + %endif + + ; Starting registers: + + ; m0 0 1 2 3 + ; m1 4 5 6 7 + ; m2 8 9 10 11 + ; m3 12 13 14 15 + + ; Where each number represents an index of the + ; original block of differences. + + ; Pack rows 0,2 and 1,3 into m0 and m1 + %if BIT_PRECISION == 16 + %if VEC_SIZE == 16 + ; In this case, each row only has 64 bits, so we use + ; punpcklqdq only. The high 64 bits are always 0. + punpcklqdq xm0, xm2 + punpcklqdq xm1, xm3 + %elif VEC_SIZE == 32 + ; The upper 128 bits of all input registers are zeroed + punpcklqdq m4, m0, m2 + punpcklqdq m5, m1, m3 + punpckhqdq m0, m0, m2 + punpckhqdq m1, m1, m3 + vinserti128 m0, m4, xm0, 1 + vinserti128 m1, m5, xm1, 1 + %endif + %elif BIT_PRECISION == 32 + vinserti128 ym0, ym0, xm2, 1 + vinserti128 ym1, ym1, xm3, 1 + %else + %error Invalid bit precision (expected 16 or 32) + %endif + + ; Now that we've packed rows 0-2 and 1-3 together, + ; this is our permutation: + + ; m0 0 1 2 3 8 9 10 11 + ; m1 4 5 6 7 12 13 14 15 + + ; For a 8x4 transform (with 16-bit coefficients), this pattern is + ; extended for each 128-bit half but for the second block, and thus + ; all comments also apply to the upper 128-bits for the 8x4 transform. + + BUTTERFLY %1, %2, 0 + + ; m0 [0+4][1+5][2+6][3+7] [8+12][9+13][10+14][11+15] + ; m1 [0-4][1-5][2-6][3-7] [8-12][9-13][10-14][11-15] + + INTERLEAVE %1, %2, 0 + + ; m0 [ 0+4][ 0-4][ 1+5][ 1-5] [2 + 6][2 - 6][3 + 7][3 - 7] + ; m1 [8+12][8-12][9+13][9-13] [10+14][10-14][11+15][11-15] + + BUTTERFLY %1, %2, 0 + + ; m0 [0+4+8+12][0-4+8-12][1+5+9+13][1-5+9-13] [2+6+10+14][2-6+10-14][3+7+11+15][3-7+11-15] + ; m1 [0+4-8-12][0-4-8+12][1+5-9-13][1-5-9+13] [2+6-10-14][2-6-10+14][3+7-11-15][3-7-11+15] + + ; for one row: + ; [0+1+2+3][0-1+2-3][0+1-2-3][0-1-2+3] + ; For the vertical transform, these are packed into a new column. + + INTERLEAVE_PAIRS %1, %2, 0 + + ; p0 p1 p2 p3 + ; m0 [0+4+ 8+12][0-4+ 8-12][0+4- 8-12][0-4- 8+12] [1+5+ 9+13][1-5+ 9-13][1+5- 9-13][1-5- 9+13] + ; m1 [2+6+10+14][2-6+10-14][2+6-10-14][2-6-10+14] [3+7+11+15][3-7+11-15][3+7-11-15][3-7-11+15] + + ; According to this grid: + + ; p0 q0 r0 s0 + ; p1 q1 r1 s1 + ; p2 q2 r2 s2 + ; p3 q3 r3 s3 + + ; Horizontal transform; since the output is transposed from the original order, + ; we can do the same steps as the vertical transform and the result will be the same. + BUTTERFLY %1, %2, 0 + INTERLEAVE %1, %2, 0 + BUTTERFLY %1, %2, 0 + + ; Finished horizontal transform except for the last step (interleaving pairs), + ; which we skip, because after this we add up the absolute value of the + ; coefficients, which is a commutative operation (order does not matter). +%endmacro + +; Horizontal sum of mm register +; +; Inputs: +; %1 = Element size in bits (16 or 32) +; %2 = Size of input register in bytes (16 or 32) +; You can e.g. pass 16 for this argument if you +; only want to sum up the bottom 128-bits of a +; ymm register. +; %3 = Input register number +; %4 = Temporary register number +; %5 = Output register (e.g., eax) +%macro HSUM 5 + %define E_SIZE %1 + %define REG_SIZE %2 + %define INPUT %3 + %define TMP %4 + %define OUTPUT %5 + + %if REG_SIZE == 16 + %define V xm + %elif REG_SIZE == 32 + %define V ym + %else + %error Invalid register size (expected 16 or 32) + %endif + + %if E_SIZE == 16 + ; Add adjacent pairs of 16-bit elements to produce 32-bit results, + ; then proceed with 32-bit sum + pmaddwd V%+INPUT, [pw_1x16] + %endif + + %if mmsize == 32 && REG_SIZE == 32 + ; Add upper half of ymm to xmm + vextracti128 xm%+TMP, ym%+INPUT, 1 + paddd xm%+INPUT, xm%+TMP + %endif + + ; Reduce 32-bit results + pshufd xm%+TMP, xm%+INPUT, q2323 + paddd xm%+INPUT, xm%+TMP + pshufd xm%+TMP, xm%+INPUT, q1111 + paddd xm%+INPUT, xm%+TMP + movd OUTPUT, xm%+INPUT +%endmacro + +; given m0-7, do butterfly as follows: +; (m0, m1) = butterfly(m0, m1) +; (m2, m3) = butterfly(m2, m3) +; (m4, m5) = butterfly(m4, m5) +; (m6, m7) = butterfly(m6, m7) +%macro BUTTERFLY_8X8 0 + ; m8 is free + paddd m8, m0, m1 + psubd m0, m1 + SWAP 8, 1, 0 + + ; m8 is free + paddd m8, m2, m3 + psubd m2, m3 + SWAP 8, 3, 2 + + paddd m8, m4, m5 + psubd m4, m5 + SWAP 8, 5, 4 + + paddd m8, m6, m7 + psubd m6, m7 + SWAP 8, 7, 6 +%endmacro + +%macro HADAMARD_8X8_VERTICAL 0 + BUTTERFLY_8X8 + ; m0-7 contain a0-7 + + SWAP 2, 1 + SWAP 6, 5 + + BUTTERFLY_8X8 + + SWAP 1, 4 + SWAP 3, 6 + + BUTTERFLY_8X8 + + SWAP 2, 1 + SWAP 2, 4 + SWAP 3, 6 + SWAP 5, 6 +%endmacro + +; Transpose rows m0-7. +; Output is also contained in m0-7. +; +; Uses m8, m10-15 as temporary registers (i.e. m9 is left unchanged.) +%macro TRANSPOSE8X8D 0 + SWAP 9, 0 + SWAP 10, 1 + SWAP 11, 2 + SWAP 12, 3 + SWAP 13, 4 + SWAP 14, 5 + SWAP 15, 6 + SWAP 2, 7 + + punpckldq m6, m9, m10 + punpckldq m1, m11, m12 + punpckhdq m8, m9, m10 + punpckldq m4, m13, m14 + punpckldq m9, m15, m2 + vshufps m3, m6, m1, 0x4e + vpblendd m10, m6, m3, 0xcc + vshufps m6, m4, m9, 0x4e + punpckhdq m7, m11, m12 + vpblendd m11, m4, m6, 0xcc + vpblendd m12, m3, m1, 0xcc + vperm2i128 m3, m10, m11, 0x20 + punpckhdq m5, m13, m14 + vpblendd m13, m6, m9, 0xcc + punpckhdq m4, m15, m2 + vperm2i128 m2, m12, m13, 0x20 + vshufps m14, m8, m7, 0x4e + vpblendd m15, m14, m7, 0xcc + vshufps m7, m5, m4, 0x4e + vpblendd m8, m8, m14, 0xcc + vpblendd m5, m5, m7, 0xcc + vperm2i128 m6, m8, m5, 0x20 + vpblendd m4, m7, m4, 0xcc + vperm2i128 m7, m15, m4, 0x20 + vperm2i128 m1, m10, m11, 0x31 + vperm2i128 m9, m12, m13, 0x31 + vperm2i128 m5, m8, m5, 0x31 + vperm2i128 m4, m15, m4, 0x31 + + SWAP 0, 9 + + ; Output order is as follows: + ; 3 2 6 7 1 0 5 4 + + ; sort rows + SWAP 3, 0 + ; 0 2 6 7 1 3 5 4 + SWAP 1, 2 + ; 0 1 6 7 2 3 5 4 + SWAP 6, 2 + ; 0 1 2 7 6 3 5 4 + SWAP 7, 3 + ; 0 1 2 3 6 7 5 4 + SWAP 6, 4 + ; 0 1 2 3 4 7 5 6 + SWAP 7, 5 + ; 0 1 2 3 4 5 7 6 + SWAP 6, 7 + ; 0 1 2 3 4 5 6 7 +%endmacro + +; m0-7 as input; add coefficients to ymm9. +INIT_YMM avx2 +cglobal satd_8x8_hbd_internal, 0, 0, 0, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + HADAMARD_8X8_VERTICAL + + TRANSPOSE8X8D + + HADAMARD_8X8_VERTICAL + + REPX {pabsd x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + + ; Add m0-7 + paddd m0, m4 + paddd m1, m5 + paddd m2, m6 + paddd m3, m7 + + paddd m0, m2 + paddd m1, m3 + + paddd m0, m1 + paddd ymm9, m0 + ret + +%macro LOAD_DIFF_8X8 0 + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + movu xm4, [srcq + 0*src_strideq] + movu xm5, [srcq + 1*src_strideq] + movu xm6, [srcq + 2*src_strideq] + movu xm7, [srcq + src_stride3q ] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + + pmovsxwd m0, xm0 + pmovsxwd m1, xm1 + pmovsxwd m2, xm2 + pmovsxwd m3, xm3 + pmovsxwd m4, xm4 + pmovsxwd m5, xm5 + pmovsxwd m6, xm6 + pmovsxwd m7, xm7 +%endmacro + +INIT_YMM avx2 +cglobal satd_8x8_hbd, 5, 7, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + LOAD_DIFF_8X8 + + ; m0-7 contain rows of 8x8 block to transform + ; with 32-bit coefficients + + HADAMARD_8X8_VERTICAL + + TRANSPOSE8X8D + + HADAMARD_8X8_VERTICAL + + REPX {pabsd x, x}, m0, m1, m2, m3, m4, m5, m6, m7 + + ; Add m0-7 + paddd m0, m4 + paddd m1, m5 + paddd m2, m6 + paddd m3, m7 + + paddd m0, m2 + paddd m1, m3 + + paddd m0, m1 + + HSUM 32, 32, 0, 1, eax + NORMALIZE8PT + RET + +INIT_YMM avx2 +cglobal satd_4x4_hbd, 5, 7, 8, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + + ; src -= dst + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + + HADAMARD_4X4_PACKED 16, 16 + + ; Sum up absolute value of transform coefficients + pabsw xm0, xm0 + pabsw xm1, xm1 + paddw xm0, xm1 + HSUM 16, 16, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + ; this gives a nicer disassembly + RESET_MM_PERMUTATION + + ; Load src rows + pmovzxwd xm0, [srcq + 0*src_strideq] + pmovzxwd xm1, [srcq + 1*src_strideq] + pmovzxwd xm2, [srcq + 2*src_strideq] + pmovzxwd xm3, [srcq + src_stride3q ] + + ; Load dst rows + pmovzxwd xm4, [dstq + 0*dst_strideq] + pmovzxwd xm5, [dstq + 1*dst_strideq] + pmovzxwd xm6, [dstq + 2*dst_strideq] + pmovzxwd xm7, [dstq + dst_stride3q ] + + ; src -= dst + psubd xm0, xm4 + psubd xm1, xm5 + psubd xm2, xm6 + psubd xm3, xm7 + + HADAMARD_4X4_PACKED 32, 32 + + pabsd m0, m0 + pabsd m1, m1 + paddd m0, m1 + HSUM 32, 32, 0, 1, eax + NORMALIZE4PT + RET + +; 32-bit input rows are in m0-3; result is in m0. +; Uses m0-5 as temporary registers. +%macro HADAMARD_8X4_12BPC 0 + vperm2i128 m4, m0, m2, 0x31 + vperm2i128 m5, m1, m3, 0x31 + vinserti128 m0, m0, xm2, 1 + vinserti128 m1, m1, xm3, 1 + + ; Swap so m3,m4 are used as inputs. + SWAP 3, 4, 5 + + ; instead of using HADAMARD_4X4_PACKED twice, we interleave + ; 2 transforms operating over different registers for more + ; opportunity for instruction level parallelism. + + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE 32, 32, 0 + INTERLEAVE 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE_PAIRS 32, 32, 0 + INTERLEAVE_PAIRS 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + INTERLEAVE 32, 32, 0 + INTERLEAVE 32, 32, 1 + BUTTERFLY 32, 32, 0 + BUTTERFLY 32, 32, 1 + + pabsd m0, m0 + pabsd m1, m1 + pabsd m3, m3 + pabsd m4, m4 + + paddd m0, m1 + paddd m3, m4 + paddd m0, m3 +%endmacro + +INIT_YMM avx2 +cglobal satd_16x4_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movu m0, [srcq + 0*src_strideq] + movu m1, [srcq + 1*src_strideq] + movu m2, [srcq + 2*src_strideq] + movu m3, [srcq + src_stride3q ] + + ; src -= dst + psubw m0, [dstq + 0*dst_strideq] + psubw m1, [dstq + 1*dst_strideq] + psubw m2, [dstq + 2*dst_strideq] + psubw m3, [dstq + dst_stride3q ] + +.10bpc_main: + + ; Original permutation + ; m0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + ; m1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + ; m2 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 + ; m3 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + + ; Two registers perform 2 4x4 transforms in parallel + + punpcklqdq m4, m0, m2 + punpcklqdq m5, m1, m3 + + punpckhqdq m0, m0, m2 + punpckhqdq m1, m1, m3 + + SWAP 4, 3 + SWAP 5, 4 + + ; New permutation + ; m0 0 1 2 3 32 33 34 35 8 9 10 11 40 41 42 43 + ; m1 16 17 18 19 48 49 50 51 24 25 26 27 56 57 58 59 + ; m3 4 5 6 7 36 37 38 39 12 13 14 15 44 45 46 47 + ; m4 20 21 22 23 52 53 54 55 28 29 30 31 60 61 62 63 + + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE 16, 32, 0 + INTERLEAVE 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE_PAIRS 16, 32, 0 + INTERLEAVE_PAIRS 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + INTERLEAVE 16, 32, 0 + INTERLEAVE 16, 32, 1 + BUTTERFLY 16, 32, 0 + BUTTERFLY 16, 32, 1 + + pabsw m0, m0 + pabsw m1, m1 + pabsw m3, m3 + pabsw m4, m4 + + paddw m0, m1 + paddw m3, m4 + paddw m0, m3 + + HSUM 16, 32, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + RESET_MM_PERMUTATION + + mov bdmaxd, 2 + pxor m6, m6 +.12bpc_loop: + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + + pmovsxwd m0, xm0 + pmovsxwd m1, xm1 + pmovsxwd m2, xm2 + pmovsxwd m3, xm3 + + add srcq, 16 + add dstq, 16 + + HADAMARD_8X4_12BPC + paddd m6, m0 + dec bdmaxd + jnz .12bpc_loop + + HSUM 32, 32, 6, 1, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_4x16_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; BLOCK 1 + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; BLOCK 2 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + ; BLOCK 3 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; BLOCK 4 + movq xm8, [srcq + 0*src_strideq] + movq xm9, [srcq + 1*src_strideq] + movq xm10, [srcq + 2*src_strideq] + movq xm11, [srcq + src_stride3q ] + + psubw xm8, [dstq + 0*dst_strideq] + psubw xm9, [dstq + 1*dst_strideq] + psubw xm10, [dstq + 2*dst_strideq] + psubw xm11, [dstq + dst_stride3q ] + + vinserti128 m4, m4, xm8, 1 + vinserti128 m5, m5, xm9, 1 + vinserti128 m6, m6, xm10, 1 + vinserti128 m7, m7, xm11, 1 + + punpcklqdq m0, m0, m4 + punpcklqdq m1, m1, m5 + punpcklqdq m2, m2, m6 + punpcklqdq m3, m3, m7 + + jmp m(satd_16x4_hbd).10bpc_main + +.12bpc: + mov bdmaxd, 2 + pxor m8, m8 + +.12bpc_loop: + ; BLOCK 1 + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + pmovsxwd xm0, xm0 + pmovsxwd xm1, xm1 + pmovsxwd xm2, xm2 + pmovsxwd xm3, xm3 + + ; BLOCK 2 + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + pmovsxwd xm4, xm4 + pmovsxwd xm5, xm5 + pmovsxwd xm6, xm6 + pmovsxwd xm7, xm7 + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + HADAMARD_8X4_12BPC + paddd m8, m0 + dec bdmaxd + jnz .12bpc_loop + + HSUM 32, 32, 8, 0, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_8x4_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + ; Load src rows + movu xm0, [srcq + 0*src_strideq] + movu xm1, [srcq + 1*src_strideq] + movu xm2, [srcq + 2*src_strideq] + movu xm3, [srcq + src_stride3q ] + + ; src -= dst + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + +.10bpc_main: + HADAMARD_4X4_PACKED 16, 32 + + pabsw m0, m0 + pabsw m1, m1 + paddw m0, m1 + HSUM 16, 32, 0, 1, eax + NORMALIZE4PT + RET +.12bpc: + RESET_MM_PERMUTATION + + pmovzxwd m0, [srcq + 0*src_strideq] + pmovzxwd m1, [srcq + 1*src_strideq] + pmovzxwd m2, [srcq + 2*src_strideq] + pmovzxwd m3, [srcq + src_stride3q ] + + pmovzxwd m4, [dstq + 0*dst_strideq] + pmovzxwd m5, [dstq + 1*dst_strideq] + pmovzxwd m6, [dstq + 2*dst_strideq] + pmovzxwd m7, [dstq + dst_stride3q ] + + ; src -= dst + psubd m0, m4 + psubd m1, m5 + psubd m2, m6 + psubd m3, m7 + +.12bpc_main: + HADAMARD_8X4_12BPC + HSUM 32, 32, 0, 1, eax + NORMALIZE4PT + RET + +INIT_YMM avx2 +cglobal satd_4x8_hbd, 5, 7, 12, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + cmp bdmaxd, (1 << 10) - 1 + jne .12bpc + + movq xm0, [srcq + 0*src_strideq] + movq xm1, [srcq + 1*src_strideq] + movq xm2, [srcq + 2*src_strideq] + movq xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + movq xm4, [srcq + 0*src_strideq] + movq xm5, [srcq + 1*src_strideq] + movq xm6, [srcq + 2*src_strideq] + movq xm7, [srcq + src_stride3q ] + + ; This loads past the number of elements we are technically supposed + ; to read, however, this should still be safe, since at least one + ; valid element is in the memory address. + psubw xm0, [dstq + 0*dst_strideq] + psubw xm1, [dstq + 1*dst_strideq] + psubw xm2, [dstq + 2*dst_strideq] + psubw xm3, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + psubw xm4, [dstq + 0*dst_strideq] + psubw xm5, [dstq + 1*dst_strideq] + psubw xm6, [dstq + 2*dst_strideq] + psubw xm7, [dstq + dst_stride3q ] + + punpcklqdq xm0, xm0, xm4 + punpcklqdq xm1, xm1, xm5 + punpcklqdq xm2, xm2, xm6 + punpcklqdq xm3, xm3, xm7 + + ; Jump to HADAMARD_4X4_PACKED in 8x4 satd, this saves us some binary size + ; by deduplicating the shared code. + jmp m(satd_8x4_hbd).10bpc_main + ; No return; we return in the other function. + +.12bpc: + RESET_MM_PERMUTATION + + pmovzxwd xm0, [srcq + 0*src_strideq] + pmovzxwd xm1, [srcq + 1*src_strideq] + pmovzxwd xm2, [srcq + 2*src_strideq] + pmovzxwd xm3, [srcq + src_stride3q ] + lea srcq, [srcq + 4*src_strideq] + + pmovzxwd xm4, [dstq + 0*dst_strideq] + pmovzxwd xm5, [dstq + 1*dst_strideq] + pmovzxwd xm6, [dstq + 2*dst_strideq] + pmovzxwd xm7, [dstq + dst_stride3q ] + lea dstq, [dstq + 4*dst_strideq] + + ; src -= dst + psubd xm0, xm4 + psubd xm1, xm5 + psubd xm2, xm6 + psubd xm3, xm7 + + pmovzxwd xm4, [srcq + 0*src_strideq] + pmovzxwd xm5, [srcq + 1*src_strideq] + pmovzxwd xm6, [srcq + 2*src_strideq] + pmovzxwd xm7, [srcq + src_stride3q ] + + pmovzxwd xm8, [dstq + 0*dst_strideq] + pmovzxwd xm9, [dstq + 1*dst_strideq] + pmovzxwd xm10, [dstq + 2*dst_strideq] + pmovzxwd xm11, [dstq + dst_stride3q ] + + ; src -= dst (second block) + psubd xm4, xm8 + psubd xm5, xm9 + psubd xm6, xm10 + psubd xm7, xm11 + + vinserti128 m0, m0, xm4, 1 + vinserti128 m1, m1, xm5, 1 + vinserti128 m2, m2, xm6, 1 + vinserti128 m3, m3, xm7, 1 + + ; Jump to HADAMARD_4X4_PACKED in 8x4 satd, this saves us some binary size + ; by deduplicating the shared code. + jmp m(satd_8x4_hbd).12bpc_main + ; No return; we return in the other function. + + +; , +%macro SATD_NXM 2 + +INIT_YMM avx2 +cglobal satd_%1x%2_hbd, 5, 10, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3, nsrc_stride4, ndst_stride4, rows + lea nsrc_stride4q, [4*src_strideq] + lea ndst_stride4q, [4*dst_strideq] + + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + neg nsrc_stride4q + neg ndst_stride4q + + pxor m9, m9 + + ; Height contains the number of rows. + mov rowsd, %2/8 +.outer: + mov bdmaxd, %1/8 + +; Loop over blocks in same row. +.loop: + LOAD_DIFF_8X8 + + ; Fix up pointers and go to next block in same row. + lea srcq, [srcq + nsrc_stride4q + 16] + lea dstq, [dstq + ndst_stride4q + 16] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + lea srcq, [srcq + 8*src_strideq - (%1*16)/8] + lea dstq, [dstq + 8*dst_strideq - (%1*16)/8] + + dec rowsd + jnz .outer + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +%macro SATD_NX8 1 +INIT_YMM avx2 +cglobal satd_%1x8_hbd, 5, 9, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3, nsrc_stride4, ndst_stride4 + lea nsrc_stride4q, [4*src_strideq] + lea ndst_stride4q, [4*dst_strideq] + + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + neg nsrc_stride4q + neg ndst_stride4q + + pxor m9, m9 + mov bdmaxd, %1/8 + +.loop: + LOAD_DIFF_8X8 + + lea srcq, [srcq + nsrc_stride4q + 16] + lea dstq, [dstq + ndst_stride4q + 16] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +%macro SATD_8XM 1 +INIT_YMM avx2 +cglobal satd_8x%1_hbd, 5, 7, 16, src, src_stride, dst, dst_stride, bdmax, \ + src_stride3, dst_stride3 + lea src_stride3q, [3*src_strideq] + lea dst_stride3q, [3*dst_strideq] + + pxor m9, m9 + mov bdmaxd, %1/8 + +.loop: + LOAD_DIFF_8X8 + + lea srcq, [srcq + 4*src_strideq] + lea dstq, [dstq + 4*dst_strideq] + + call m(satd_8x8_hbd_internal) + dec bdmaxd + jnz .loop + + HSUM 32, 32, 9, 0, eax + NORMALIZE8PT + RET +%endmacro + +SATD_NXM 16, 16 +SATD_NXM 32, 32 +SATD_NXM 64, 64 +SATD_NXM 128, 128 +SATD_NXM 16, 32 +SATD_NXM 16, 64 +SATD_NXM 32, 16 +SATD_NXM 32, 64 +SATD_NXM 64, 16 +SATD_NXM 64, 32 +SATD_NXM 64, 128 +SATD_NXM 128, 64 +SATD_NX8 16 +SATD_NX8 32 +SATD_8XM 16 +SATD_8XM 32 + +%endif ; ARCH_X86_64 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sse.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sse.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/sse.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/sse.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,511 @@ +; Copyright (c) 2020-2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +; Must match crate::dist::rust::GET_WEIGHTED_SSE_SHIFT +%define get_weighted_sse_shift 8 +%define get_weighted_sse_round (1 << get_weighted_sse_shift >> 1) + +SECTION_RODATA 32 +addsub: times 16 db 1, -1 +rounding: times 4 dq get_weighted_sse_round + +SECTION .text + +%define m(x) mangle(private_prefix %+ _ %+ x %+ SUFFIX) + +; Consolidate scaling and rounding to one place so that it is easier to change. + +%macro SSE_SCALE_4X4 0 + ; Multiply and shift using scalar code + mov scaled, [scaleq] + imul rax, scaleq + add rax, get_weighted_sse_round + shr rax, get_weighted_sse_shift +%endmacro + +; 1 is the input and output register. +; 2-3 are tmp registers. +%macro SSE_SCALE 2-3 + ; Reduce 32-bit sums to 64-bits sums. + pshufd m%2, m%1, q3311 + paddd m%1, m%2 + + LOAD_SCALES %2, %3 + + ; Multiply and shift with rounding. + pmuludq m%1, m%2 + mova m%2, [rounding] + paddq m%1, m%2 + psrlq m%1, get_weighted_sse_shift +%endmacro + +%macro LOAD_SCALES_4X8 2 + ; Load 1 scale from each of the 2 rows. + movd m%1, [scaleq] + movd m%2, [scaleq+scale_strideq] + ; 64-bit unpack since our loads have only one value each. + punpcklqdq m%1, m%2 +%endmacro + +; 2 is unused +%macro LOAD_SCALES_8X4 2 + ; Convert to 64-bits. + ; It doesn't matter that the upper halves are full of garbage. + movq m%1, [scaleq] + pshufd m%1, m%1, q1100 +%endmacro + +; 2 is unused +%macro LOAD_SCALES_16X4 2 + pmovzxdq m%1, [scaleq] +%endmacro + +; Separate from other scale macros, since it uses 2 inputs. +; 1-2 are inputs regs and 1 is the output reg. +; 3-4 are tmp registers +%macro SSE_SCALE_32X4 4 + pshufd m%3, m%1, q3311 + paddd m%1, m%3 + pshufd m%3, m%2, q3311 + paddd m%2, m%3 + + ; Load scale for 4x4 blocks and convert to 64-bits. + ; It doesn't matter if the upper halves are full of garbage. + ; raw load: 0, 1, 2, 3 | 4, 5, 6, 7 + ; unpack low: 0, 1 | 4, 5 + ; unpack high: 2, 3, | 6, 7 + mova m%4, [scaleq] + punpckldq m%3, m%4, m%4 + punpckhdq m%4, m%4 + + pmuludq m%1, m%3 + pmuludq m%2, m%4 + mova m%3, [rounding] + paddq m%1, m%3 + paddq m%2, m%3 + psrlq m%1, get_weighted_sse_shift + psrlq m%2, get_weighted_sse_shift + paddq m%1, m%2 +%endmacro + +INIT_XMM ssse3 +; Use scale_stride's register to store src_stride3 +cglobal weighted_sse_4x4, 6, 7, 5, \ + src, src_stride, dst, dst_stride, scale, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + movq m0, [addsub] + movd m1, [srcq] + movd m2, [dstq] + punpcklbw m1, m2 + movd m2, [srcq+src_strideq] + movd m3, [dstq+dst_strideq] + punpcklbw m2, m3 + pmaddubsw m1, m0 + pmaddubsw m2, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + paddd m1, m2 + movd m2, [srcq+src_strideq*2] + movd m3, [dstq+dst_strideq*2] + punpcklbw m2, m3 + movd m3, [srcq+src_stride3q] + movd m4, [dstq+dst_stride3q] + punpcklbw m3, m4 + pmaddubsw m2, m0 + pmaddubsw m3, m0 + pmaddwd m2, m2 + pmaddwd m3, m3 + paddd m2, m3 + paddd m1, m2 + + pshuflw m0, m1, q3232 + paddd m0, m1 + movd eax, m0 + + ; Multiply and shift using scalar code. + SSE_SCALE_4X4 + RET + +%macro WEIGHTED_SSE_4X8_KERNEL 0 + movd m1, [srcq] + movd m2, [srcq+src_strideq*4] + punpckldq m1, m2 + movd m2, [dstq] + movd m3, [dstq+dst_strideq*4] + add srcq, src_strideq + add dstq, dst_strideq + punpckldq m2, m3 + punpcklbw m1, m2 + movd m2, [srcq] + movd m3, [srcq+src_strideq*4] + punpckldq m2, m3 + movd m3, [dstq] + movd m4, [dstq+dst_strideq*4] + add srcq, src_strideq + add dstq, dst_strideq + punpckldq m3, m4 + punpcklbw m2, m3 + pmaddubsw m1, m0 + pmaddubsw m2, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + paddd m1, m2 + movd m2, [srcq] + movd m3, [srcq+src_strideq*4] + punpckldq m2, m3 + movd m3, [dstq] + movd m4, [dstq+dst_strideq*4] + add srcq, src_strideq + add dstq, dst_strideq + punpckldq m3, m4 + punpcklbw m2, m3 + movd m3, [srcq] + movd m4, [srcq+src_strideq*4] + punpckldq m3, m4 + movd m4, [dstq] + movd m5, [dstq+dst_strideq*4] + punpckldq m4, m5 + punpcklbw m3, m4 + pmaddubsw m2, m0 + pmaddubsw m3, m0 + pmaddwd m2, m2 + pmaddwd m3, m3 + paddd m2, m3 + paddd m1, m2 + + %define LOAD_SCALES LOAD_SCALES_4X8 + SSE_SCALE 1, 2, 3 +%endmacro + +INIT_XMM ssse3 +cglobal weighted_sse_4x8, 6, 6, 6, \ + src, src_stride, dst, dst_stride, scale, scale_stride + mova m0, [addsub] + WEIGHTED_SSE_4X8_KERNEL + + pshufd m0, m1, q3232 + paddq m1, m0 + movq rax, m1 + RET + +INIT_XMM ssse3 +cglobal weighted_sse_4x16, 6, 6, 7, \ + src, src_stride, dst, dst_stride, scale, scale_stride + mova m0, [addsub] + + WEIGHTED_SSE_4X8_KERNEL + ; Swap so the use of this macro will use m6 as the result + SWAP 1, 6 + + lea scaleq, [scaleq+scale_strideq*2] + ; Already incremented by stride 3 times, but must go up 5 more to get to 8 + add srcq, src_strideq + add dstq, dst_strideq + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + WEIGHTED_SSE_4X8_KERNEL + paddq m6, m1 + + pshufd m0, m6, q3232 + paddq m6, m0 + movq rax, m6 + RET + +%macro WEIGHTED_SSE_8X4_KERNEL 0 + movq m1, [srcq] + movq m2, [dstq] + punpcklbw m1, m2 + movq m2, [srcq+src_strideq] + movq m3, [dstq+dst_strideq] + punpcklbw m2, m3 + pmaddubsw m1, m0 + pmaddubsw m2, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + paddd m1, m2 + movq m2, [srcq+src_strideq*2] + movq m3, [dstq+dst_strideq*2] + punpcklbw m2, m3 + movq m3, [srcq+src_stride3q] + movq m4, [dstq+dst_stride3q] + punpcklbw m3, m4 + pmaddubsw m2, m0 + pmaddubsw m3, m0 + pmaddwd m2, m2 + pmaddwd m3, m3 + paddd m2, m3 + paddd m1, m2 + + %define LOAD_SCALES LOAD_SCALES_8X4 + SSE_SCALE 1, 2 +%endmacro + +%macro WEIGHTED_SSE_16X4_KERNEL 0 + pmovzxbw m0, [srcq] + pmovzxbw m1, [dstq] + psubw m0, m1 + pmaddwd m0, m0 + pmovzxbw m1, [srcq+src_strideq] + pmovzxbw m2, [dstq+dst_strideq] + psubw m1, m2 + pmaddwd m1, m1 + paddd m0, m1 + pmovzxbw m1, [srcq+src_strideq*2] + pmovzxbw m2, [dstq+dst_strideq*2] + psubw m1, m2 + pmaddwd m1, m1 + pmovzxbw m2, [srcq+src_stride3q] + pmovzxbw m3, [dstq+dst_stride3q] + psubw m2, m3 + pmaddwd m2, m2 + paddd m1, m2 + paddd m1, m0 + + %define LOAD_SCALES LOAD_SCALES_16X4 + SSE_SCALE 1, 2 +%endmacro + +%macro WEIGHTED_SSE_32X4_KERNEL 0 + ; Unpacking high and low results in sums that are 8 samples apart. To + ; correctly apply weights, two separate registers are needed to accumulate. + mova m2, [srcq] + mova m3, [dstq] + punpcklbw m1, m2, m3 + punpckhbw m2, m3 + mova m4, [srcq+src_strideq] + mova m5, [dstq+dst_strideq] + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + pmaddubsw m1, m0 + pmaddubsw m2, m0 + pmaddubsw m3, m0 + pmaddubsw m4, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + pmaddwd m3, m3 + pmaddwd m4, m4 + ; Accumulate + paddd m1, m3 + paddd m2, m4 + mova m4, [srcq+src_strideq*2] + mova m5, [dstq+dst_strideq*2] + punpcklbw m3, m4, m5 + punpckhbw m4, m5 + mova m6, [srcq+src_stride3q] + mova m7, [dstq+dst_stride3q] + punpcklbw m5, m6, m7 + punpckhbw m6, m7 + pmaddubsw m3, m0 + pmaddubsw m4, m0 + pmaddubsw m5, m0 + pmaddubsw m6, m0 + pmaddwd m3, m3 + pmaddwd m4, m4 + pmaddwd m5, m5 + pmaddwd m6, m6 + paddd m3, m5 + paddd m4, m6 + paddd m1, m3 + paddd m2, m4 + + SSE_SCALE_32X4 1, 2, 3, 4 +%endmacro + +%macro WEIGHTED_SSE 2 ; w, h +%if %1 == 8 +%if %2 == 4 +; Use scale_stride's register to store src_stride3 +cglobal weighted_sse_%1x%2, 6, 7, 5, \ + src, src_stride, dst, dst_stride, scale, \ + src_stride3, dst_stride3 +%else +cglobal weighted_sse_%1x%2, 6, 9, 6, \ + src, src_stride, dst, dst_stride, scale, scale_stride, \ + src_stride3, dst_stride3, h +%endif +%elif %1 == 16 +%if %2 == 4 +; Use scale_stride's register to store src_stride3 +cglobal weighted_sse_%1x%2, 6, 7, 4, \ + src, src_stride, dst, dst_stride, scale, \ + src_stride3, dst_stride3 +%else +cglobal weighted_sse_%1x%2, 6, 9, 5, \ + src, src_stride, dst, dst_stride, scale, scale_stride, \ + src_stride3, dst_stride3, h +%endif +%elif %1 == 32 +cglobal weighted_sse_%1x%2, 6, 9, 9, \ + src, src_stride, dst, dst_stride, scale, scale_stride, \ + src_stride3, dst_stride3, h +%else ; > 32 +cglobal weighted_sse_%1x%2, 6, 10, 9, \ + src, src_stride, dst, dst_stride, scale, scale_stride, \ + src_stride3, dst_stride3, h, w +%endif +; === Setup === +; kernel_width/kernel_height: number of elements that the kernel processes. +; m0: except for when w == 16, m0 is used to hold a constant 1, -1... vector +; register for diffing the two sources. +; sum: The kernel stores it's results on m1. The last vector register is used +; unless only one iteration is done. + +; Default the kernel width to the width of this function. +%define kernel_width %1 +%define kernel_height 4 +%if %1 == 8 + mova m0, [addsub] +%endif + +%if %1 >= 32 + mova m0, [addsub] + ; Iterate multiple times when w > 32. + %define kernel_width 32 +%endif + +%if %1 > kernel_width || %2 > kernel_height + ; Add onto the last used vector register. + %assign sum xmm_regs_used-1 +%else + ; Use the result from the kernel + %define sum 1 +%endif + + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] +%if %1 > kernel_width || %2 > kernel_height + pxor m%[sum], m%[sum] +%endif +%if %2 > kernel_height + mov hd, %2/kernel_height-1 +.loop: +%endif + +%if %1 > kernel_width + mov wd, %1/kernel_width-1 +.loop_horiz: +%endif + + WEIGHTED_SSE_%[kernel_width]X%[kernel_height]_KERNEL +%if %2 > kernel_height || %1 > kernel_width + paddq m%[sum], m1 +%endif + +%if %1 > kernel_width + add scaleq, kernel_width*4/4 + add srcq, kernel_width + add dstq, kernel_width + dec wq + jge .loop_horiz +%endif + +%if %2 > kernel_height + ; Move down 4 rows. +%if %1 > kernel_width + ; src/dst is incremented by width when processing multi iteration rows. + ; Reduce the offset by the width of the row. + lea srcq, [srcq+src_strideq*4 - %1] + lea dstq, [dstq+dst_strideq*4 - %1] + ; The behaviour for scale is similar + lea scaleq, [scaleq+scale_strideq - %1*4/4] +%else + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*4] + add scaleq, scale_strideq +%endif + dec hq + jge .loop +%endif + +%if mmsize == 16 + pshufd m2, m%[sum], q3232 + paddq m%[sum], m2 + movq rax, m%[sum] +%elif mmsize == 32 + vextracti128 xm2, m%[sum], 1 + paddq xm%[sum], xm2 + pshufd xm2, xm%[sum], q3232 + paddq xm%[sum], xm2 + movq rax, xm%[sum] +%endif + RET + + %undef sum + %undef kernel_width +%endmacro + +INIT_XMM ssse3 +WEIGHTED_SSE 8, 4 +%if ARCH_X86_64 +WEIGHTED_SSE 8, 8 +WEIGHTED_SSE 8, 16 +WEIGHTED_SSE 8, 32 +%endif ; ARCH_X86_64 + +INIT_YMM avx2 +WEIGHTED_SSE 16, 4 +%if ARCH_X86_64 +WEIGHTED_SSE 16, 8 +WEIGHTED_SSE 16, 16 +WEIGHTED_SSE 16, 32 +WEIGHTED_SSE 16, 64 + +WEIGHTED_SSE 32, 8 +WEIGHTED_SSE 32, 16 +WEIGHTED_SSE 32, 32 +WEIGHTED_SSE 32, 64 + +WEIGHTED_SSE 64, 16 +WEIGHTED_SSE 64, 32 +WEIGHTED_SSE 64, 64 +WEIGHTED_SSE 64, 128 + +WEIGHTED_SSE 128, 64 +WEIGHTED_SSE 128, 128 +%endif ; ARCH_X86_64 + +INIT_XMM sse2 + +cglobal weighted_sse_4x4_hbd, 6, 8, 4, \ + src, src_stride, dst, dst_stride, scale, scale_stride, \ + src_stride3, dst_stride3 + lea src_stride3q, [src_strideq*3] + lea dst_stride3q, [dst_strideq*3] + movq m0, [srcq] + movq m1, [dstq] + psubw m0, m1 + pmaddwd m0, m0 + movq m1, [srcq+src_strideq] + movq m2, [dstq+dst_strideq] + psubw m1, m2 + pmaddwd m1, m1 + paddd m0, m1 + movq m1, [srcq+src_strideq*2] + movq m2, [dstq+dst_strideq*2] + psubw m1, m2 + pmaddwd m1, m1 + movq m2, [srcq+src_stride3q] + movq m3, [dstq+dst_stride3q] + psubw m2, m3 + pmaddwd m2, m2 + paddd m1, m2 + paddd m0, m1 + + pshuflw m1, m0, q3232 + paddd m0, m1 + movd eax, m0 + + ; Multiply and shift using scalar code. + SSE_SCALE_4X4 + RET diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/tables.asm clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/tables.asm --- clamav-1.4.3+dfsg/.cargo/vendor/rav1e/src/x86/tables.asm 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rav1e/src/x86/tables.asm 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,563 @@ +; Copyright (c) 2019-2022, The rav1e contributors. All rights reserved +; +; This source code is subject to the terms of the BSD 2 Clause License and +; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +; was not distributed with this source code in the LICENSE file, you can +; obtain it at www.aomedia.org/license/software. If the Alliance for Open +; Media Patent License 1.0 was not distributed with this source code in the +; PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +; Copyright © 2018, VideoLAN and dav1d authors +; Copyright © 2018, Two Orioles, LLC +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%include "config.asm" +%include "ext/x86/x86inc.asm" + +SECTION_RODATA 16 + +align 8, db 0 +const mc_subpel_filters, db 0, 1, -3, 63, 4, -1, 0, 0, ; REGULAR + db 0, 1, -5, 61, 9, -2, 0, 0, + db 0, 1, -6, 58, 14, -4, 1, 0, + db 0, 1, -7, 55, 19, -5, 1, 0, + db 0, 1, -7, 51, 24, -6, 1, 0, + db 0, 1, -8, 47, 29, -6, 1, 0, + db 0, 1, -7, 42, 33, -6, 1, 0, + db 0, 1, -7, 38, 38, -7, 1, 0, + db 0, 1, -6, 33, 42, -7, 1, 0, + db 0, 1, -6, 29, 47, -8, 1, 0, + db 0, 1, -6, 24, 51, -7, 1, 0, + db 0, 1, -5, 19, 55, -7, 1, 0, + db 0, 1, -4, 14, 58, -6, 1, 0, + db 0, 0, -2, 9, 61, -5, 1, 0, + db 0, 0, -1, 4, 63, -3, 1, 0, + db 0, 1, 14, 31, 17, 1, 0, 0, ; SMOOTH + db 0, 0, 13, 31, 18, 2, 0, 0, + db 0, 0, 11, 31, 20, 2, 0, 0, + db 0, 0, 10, 30, 21, 3, 0, 0, + db 0, 0, 9, 29, 22, 4, 0, 0, + db 0, 0, 8, 28, 23, 5, 0, 0, + db 0, -1, 8, 27, 24, 6, 0, 0, + db 0, -1, 7, 26, 26, 7, -1, 0, + db 0, 0, 6, 24, 27, 8, -1, 0, + db 0, 0, 5, 23, 28, 8, 0, 0, + db 0, 0, 4, 22, 29, 9, 0, 0, + db 0, 0, 3, 21, 30, 10, 0, 0, + db 0, 0, 2, 20, 31, 11, 0, 0, + db 0, 0, 2, 18, 31, 13, 0, 0, + db 0, 0, 1, 17, 31, 14, 1, 0, + db -1, 1, -3, 63, 4, -1, 1, 0, ; SHARP + db -1, 3, -6, 62, 8, -3, 2, -1, + db -1, 4, -9, 60, 13, -5, 3, -1, + db -2, 5, -11, 58, 19, -7, 3, -1, + db -2, 5, -11, 54, 24, -9, 4, -1, + db -2, 5, -12, 50, 30, -10, 4, -1, + db -2, 5, -12, 45, 35, -11, 5, -1, + db -2, 6, -12, 40, 40, -12, 6, -2, + db -1, 5, -11, 35, 45, -12, 5, -2, + db -1, 4, -10, 30, 50, -12, 5, -2, + db -1, 4, -9, 24, 54, -11, 5, -2, + db -1, 3, -7, 19, 58, -11, 5, -2, + db -1, 3, -5, 13, 60, -9, 4, -1, + db -1, 2, -3, 8, 62, -6, 3, -1, + db 0, 1, -1, 4, 63, -3, 1, -1, + db 0, 0, -2, 63, 4, -1, 0, 0, ; REGULAR 4 + db 0, 0, -4, 61, 9, -2, 0, 0, + db 0, 0, -5, 58, 14, -3, 0, 0, + db 0, 0, -6, 55, 19, -4, 0, 0, + db 0, 0, -6, 51, 24, -5, 0, 0, + db 0, 0, -7, 47, 29, -5, 0, 0, + db 0, 0, -6, 42, 33, -5, 0, 0, + db 0, 0, -6, 38, 38, -6, 0, 0, + db 0, 0, -5, 33, 42, -6, 0, 0, + db 0, 0, -5, 29, 47, -7, 0, 0, + db 0, 0, -5, 24, 51, -6, 0, 0, + db 0, 0, -4, 19, 55, -6, 0, 0, + db 0, 0, -3, 14, 58, -5, 0, 0, + db 0, 0, -2, 9, 61, -4, 0, 0, + db 0, 0, -1, 4, 63, -2, 0, 0, + db 0, 0, 15, 31, 17, 1, 0, 0, ; SMOOTH 4 + db 0, 0, 13, 31, 18, 2, 0, 0, + db 0, 0, 11, 31, 20, 2, 0, 0, + db 0, 0, 10, 30, 21, 3, 0, 0, + db 0, 0, 9, 29, 22, 4, 0, 0, + db 0, 0, 8, 28, 23, 5, 0, 0, + db 0, 0, 7, 27, 24, 6, 0, 0, + db 0, 0, 6, 26, 26, 6, 0, 0, + db 0, 0, 6, 24, 27, 7, 0, 0, + db 0, 0, 5, 23, 28, 8, 0, 0, + db 0, 0, 4, 22, 29, 9, 0, 0, + db 0, 0, 3, 21, 30, 10, 0, 0, + db 0, 0, 2, 20, 31, 11, 0, 0, + db 0, 0, 2, 18, 31, 13, 0, 0, + db 0, 0, 1, 17, 31, 15, 0, 0, + ; Bilin scaled being very rarely used, add a new table entry + ; and use the put/prep_8tap_scaled code, thus acting as a + ; scaled bilinear filter. + db 0, 0, 0, 60, 4, 0, 0, 0, + db 0, 0, 0, 56, 8, 0, 0, 0, + db 0, 0, 0, 52, 12, 0, 0, 0, + db 0, 0, 0, 48, 16, 0, 0, 0, + db 0, 0, 0, 44, 20, 0, 0, 0, + db 0, 0, 0, 40, 24, 0, 0, 0, + db 0, 0, 0, 36, 28, 0, 0, 0, + db 0, 0, 0, 32, 32, 0, 0, 0, + db 0, 0, 0, 28, 36, 0, 0, 0, + db 0, 0, 0, 24, 40, 0, 0, 0, + db 0, 0, 0, 20, 44, 0, 0, 0, + db 0, 0, 0, 16, 48, 0, 0, 0, + db 0, 0, 0, 12, 52, 0, 0, 0, + db 0, 0, 0, 8, 56, 0, 0, 0, + db 0, 0, 0, 4, 60, 0, 0, 0 + +align 64, db 0 +const filter_intra_taps, db -6, 10, -5, 2, -3, 1, -3, 1, ; 0 + db -4, 6, -3, 2, -3, 2, -3, 1, + db 0, 0, 10, 0, 1, 10, 1, 2, + db 0, 0, 6, 0, 2, 6, 2, 2, + db 0, 12, 0, 9, 0, 7, 10, 5, + db 0, 2, 0, 2, 0, 2, 6, 3, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 12, 0, 9, 0, 7, 0, 5, 0, + db -10, 16, -6, 0, -4, 0, -2, 0, ; 1 + db -10, 16, -6, 0, -4, 0, -2, 0, + db 0, 0, 16, 0, 0, 16, 0, 0, + db 0, 0, 16, 0, 0, 16, 0, 0, + db 0, 10, 0, 6, 0, 4, 16, 2, + db 0, 0, 0, 0, 0, 0, 16, 0, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 10, 0, 6, 0, 4, 0, 2, 0, + db -8, 8, -8, 0, -8, 0, -8, 0, ; 2 + db -4, 4, -4, 0, -4, 0, -4, 0, + db 0, 0, 8, 0, 0, 8, 0, 0, + db 0, 0, 4, 0, 0, 4, 0, 0, + db 0, 16, 0, 16, 0, 16, 8, 16, + db 0, 0, 0, 0, 0, 0, 4, 0, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 16, 0, 16, 0, 16, 0, 16, 0, + db -2, 8, -1, 3, -1, 2, 0, 1, ; 3 + db -1, 4, -1, 3, -1, 2, -1, 2, + db 0, 0, 8, 0, 3, 8, 2, 3, + db 0, 0, 4, 0, 3, 4, 2, 3, + db 0, 10, 0, 6, 0, 4, 8, 2, + db 0, 3, 0, 4, 0, 4, 4, 3, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 10, 0, 6, 0, 4, 0, 3, 0, + db -12, 14, -10, 0, -9, 0, -8, 0, ; 4 + db -10, 12, -9, 1, -8, 0, -7, 0, + db 0, 0, 14, 0, 0, 14, 0, 0, + db 0, 0, 12, 0, 0, 12, 0, 1, + db 0, 14, 0, 12, 0, 11, 14, 10, + db 0, 0, 0, 0, 0, 1, 12, 1, + db 0, 0, 0, 0, 0, 0, 0, 0, + db 14, 0, 12, 0, 11, 0, 9, 0 + +align 64, db 0 +const sgr_x_by_x, db 255, 128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17, + db 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9, + db 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, + db 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, + db 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, + db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + db 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + db 0 + +align 8, db 0 +const mc_warp_filter, db 0, 127, 0, 0, 0, 1, 0, 0, 0, 127, 0, 0, -1, 2, 0, 0, ; [-1, 0) + db 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, 0, + db 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, 0, + db 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, 0, + db 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, 0, + db 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, 0, + db 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, 0, + db 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, 0, + db 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, 0, + db 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, 0, + db 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, 0, + db 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, 0, + db 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, 0, + db 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, 0, + db 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, 0, + db 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, 0, + db 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, 0, + db 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, 0, + db 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, 0, + db 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, 0, + db 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, 0, + db 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, 0, + db 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, 0, + db 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, 0, + db 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, 0, + db 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, 0, + db 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, 0, + db 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, 0, + db 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, 0, + db 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, 0, + db 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, 0, + db 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, 0, + db 0, 0, 1, 0, 0, 127, 0, 0, 0, -1, 2, 0, 0, 127, 0, 0, ; [0, 1) + db 0, -3, 4, 1, 1, 127, -2, 0, 0, -5, 6, 1, 1, 127, -2, 0, + db 0, -6, 8, 1, 2, 126, -3, 0, -1, -7, 11, 2, 2, 126, -4, -1, + db -1, -8, 13, 2, 3, 125, -5, -1, -1, -10, 16, 3, 3, 124, -6, -1, + db -1, -11, 18, 3, 4, 123, -7, -1, -1, -12, 20, 3, 4, 122, -7, -1, + db -1, -13, 23, 3, 4, 121, -8, -1, -2, -14, 25, 4, 5, 120, -9, -1, + db -1, -15, 27, 4, 5, 119, -10, -1, -1, -16, 30, 4, 5, 118, -11, -1, + db -2, -17, 33, 5, 6, 116, -12, -1, -2, -17, 35, 5, 6, 114, -12, -1, + db -2, -18, 38, 5, 6, 113, -13, -1, -2, -19, 41, 6, 7, 111, -14, -2, + db -2, -19, 43, 6, 7, 110, -15, -2, -2, -20, 46, 6, 7, 108, -15, -2, + db -2, -20, 49, 6, 7, 106, -16, -2, -2, -21, 51, 7, 7, 104, -16, -2, + db -2, -21, 54, 7, 7, 102, -17, -2, -2, -21, 56, 7, 8, 100, -18, -2, + db -2, -22, 59, 7, 8, 98, -18, -2, -2, -22, 62, 7, 8, 96, -19, -2, + db -2, -22, 64, 7, 8, 94, -19, -2, -2, -22, 67, 8, 8, 91, -20, -2, + db -2, -22, 69, 8, 8, 89, -20, -2, -2, -22, 72, 8, 8, 87, -21, -2, + db -2, -21, 74, 8, 8, 84, -21, -2, -2, -22, 77, 8, 8, 82, -21, -2, + db -2, -21, 79, 8, 8, 79, -21, -2, -2, -21, 82, 8, 8, 77, -22, -2, + db -2, -21, 84, 8, 8, 74, -21, -2, -2, -21, 87, 8, 8, 72, -22, -2, + db -2, -20, 89, 8, 8, 69, -22, -2, -2, -20, 91, 8, 8, 67, -22, -2, + db -2, -19, 94, 8, 7, 64, -22, -2, -2, -19, 96, 8, 7, 62, -22, -2, + db -2, -18, 98, 8, 7, 59, -22, -2, -2, -18, 100, 8, 7, 56, -21, -2, + db -2, -17, 102, 7, 7, 54, -21, -2, -2, -16, 104, 7, 7, 51, -21, -2, + db -2, -16, 106, 7, 6, 49, -20, -2, -2, -15, 108, 7, 6, 46, -20, -2, + db -2, -15, 110, 7, 6, 43, -19, -2, -2, -14, 111, 7, 6, 41, -19, -2, + db -1, -13, 113, 6, 5, 38, -18, -2, -1, -12, 114, 6, 5, 35, -17, -2, + db -1, -12, 116, 6, 5, 33, -17, -2, -1, -11, 118, 5, 4, 30, -16, -1, + db -1, -10, 119, 5, 4, 27, -15, -1, -1, -9, 120, 5, 4, 25, -14, -2, + db -1, -8, 121, 4, 3, 23, -13, -1, -1, -7, 122, 4, 3, 20, -12, -1, + db -1, -7, 123, 4, 3, 18, -11, -1, -1, -6, 124, 3, 3, 16, -10, -1, + db -1, -5, 125, 3, 2, 13, -8, -1, -1, -4, 126, 2, 2, 11, -7, -1, + db 0, -3, 126, 2, 1, 8, -6, 0, 0, -2, 127, 1, 1, 6, -5, 0, + db 0, -2, 127, 1, 1, 4, -3, 0, 0, 0, 127, 0, 0, 2, -1, 0, + db 0, 0, 127, 0, 0, 1, 0, 0, 0, 0, 127, 0, 0, -1, 2, 0, ; [1, 2) + db 0, 1, 127, -1, 0, -3, 4, 0, 0, 1, 126, -2, 0, -4, 6, 1, + db 0, 1, 126, -3, 0, -5, 8, 1, 0, 1, 125, -4, 0, -6, 11, 1, + db 0, 1, 124, -4, 0, -7, 13, 1, 0, 2, 123, -5, 0, -8, 15, 1, + db 0, 2, 122, -6, 0, -9, 18, 1, 0, 2, 121, -6, 0, -10, 20, 1, + db 0, 2, 120, -7, 0, -11, 22, 2, 0, 2, 119, -8, 0, -12, 25, 2, + db 0, 3, 117, -8, 0, -13, 27, 2, 0, 3, 116, -9, 0, -13, 29, 2, + db 0, 3, 114, -10, 0, -14, 32, 3, 0, 3, 113, -10, 0, -15, 35, 2, + db 0, 3, 111, -11, 0, -15, 37, 3, 0, 3, 109, -11, 0, -16, 40, 3, + db 0, 3, 108, -12, 0, -16, 42, 3, 0, 4, 106, -13, 0, -17, 45, 3, + db 0, 4, 104, -13, 0, -17, 47, 3, 0, 4, 102, -14, 0, -17, 50, 3, + db 0, 4, 100, -14, 0, -17, 52, 3, 0, 4, 98, -15, 0, -18, 55, 4, + db 0, 4, 96, -15, 0, -18, 58, 3, 0, 4, 94, -16, 0, -18, 60, 4, + db 0, 4, 91, -16, 0, -18, 63, 4, 0, 4, 89, -16, 0, -18, 65, 4, + db 0, 4, 87, -17, 0, -18, 68, 4, 0, 4, 85, -17, 0, -18, 70, 4, + db 0, 4, 82, -17, 0, -18, 73, 4, 0, 4, 80, -17, 0, -18, 75, 4, + db 0, 4, 78, -18, 0, -18, 78, 4, 0, 4, 75, -18, 0, -17, 80, 4, + db 0, 4, 73, -18, 0, -17, 82, 4, 0, 4, 70, -18, 0, -17, 85, 4, + db 0, 4, 68, -18, 0, -17, 87, 4, 0, 4, 65, -18, 0, -16, 89, 4, + db 0, 4, 63, -18, 0, -16, 91, 4, 0, 4, 60, -18, 0, -16, 94, 4, + db 0, 3, 58, -18, 0, -15, 96, 4, 0, 4, 55, -18, 0, -15, 98, 4, + db 0, 3, 52, -17, 0, -14, 100, 4, 0, 3, 50, -17, 0, -14, 102, 4, + db 0, 3, 47, -17, 0, -13, 104, 4, 0, 3, 45, -17, 0, -13, 106, 4, + db 0, 3, 42, -16, 0, -12, 108, 3, 0, 3, 40, -16, 0, -11, 109, 3, + db 0, 3, 37, -15, 0, -11, 111, 3, 0, 2, 35, -15, 0, -10, 113, 3, + db 0, 3, 32, -14, 0, -10, 114, 3, 0, 2, 29, -13, 0, -9, 116, 3, + db 0, 2, 27, -13, 0, -8, 117, 3, 0, 2, 25, -12, 0, -8, 119, 2, + db 0, 2, 22, -11, 0, -7, 120, 2, 0, 1, 20, -10, 0, -6, 121, 2, + db 0, 1, 18, -9, 0, -6, 122, 2, 0, 1, 15, -8, 0, -5, 123, 2, + db 0, 1, 13, -7, 0, -4, 124, 1, 0, 1, 11, -6, 0, -4, 125, 1, + db 0, 1, 8, -5, 0, -3, 126, 1, 0, 1, 6, -4, 0, -2, 126, 1, + db 0, 0, 4, -3, 0, -1, 127, 1, 0, 0, 2, -1, 0, 0, 127, 0, + db 0, 0, 2, -1, 0, 0, 127, 0 ; dummy (replicate row index 191) + +; Values that are 0 will never be used +align 2, db 0 +const dr_intra_derivative, dw 0, ; Angles: + dw 1023, 0, ; 3, 93, 183 + dw 547, ; 6, 96, 186 + dw 372, 0, 0, ; 9, 99, 189 + dw 273, ; 14, 104, 194 + dw 215, 0, ; 17, 107, 197 + dw 178, ; 20, 110, 200 + dw 151, 0, ; 23, 113, 203 (113 & 203 are base angles) + dw 132, ; 26, 116, 206 + dw 116, 0, ; 29, 119, 209 + dw 102, 0, ; 32, 122, 212 + dw 90, ; 36, 126, 216 + dw 80, 0, ; 39, 129, 219 + dw 71, ; 42, 132, 222 + dw 64, 0, ; 45, 135, 225 (45 & 135 are base angles) + dw 57, ; 48, 138, 228 + dw 51, 0, ; 51, 141, 231 + dw 45, 0, ; 54, 144, 234 + dw 40, ; 58, 148, 238 + dw 35, 0, ; 61, 151, 241 + dw 31, ; 64, 154, 244 + dw 27, 0, ; 67, 157, 247 (67 & 157 are base angles) + dw 23, ; 70, 160, 250 + dw 19, 0, ; 73, 163, 253 + dw 15, 0, ; 76, 166, 256 + dw 11, 0, ; 81, 171, 261 + dw 7, ; 84, 174, 264 + dw 3 ; 87, 177, 267 + +; Taken from the spec. Range is [-2048, 2047], mean is 0 and stddev is 512 +align 2, db 0 +const gaussian_sequence, dw 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820, + dw 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800, + dw 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588, + dw -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368, + dw 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4, + dw 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396, + dw 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740, + dw 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292, + dw 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532, + dw 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704, + dw 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96, + dw -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244, + dw 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136, + dw 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676, + dw -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400, + dw -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844, + dw -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96, + dw -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356, + dw 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280, + dw 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808, + dw 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228, + dw -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136, + dw -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264, + dw -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388, + dw 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500, + dw 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384, + dw 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220, + dw -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148, + dw 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572, + dw -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516, + dw 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916, + dw -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492, + dw 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560, + dw -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108, + dw -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516, + dw -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88, + dw -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196, + dw -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864, + dw 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920, + dw 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564, + dw -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876, + dw -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244, + dw 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184, + dw 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364, + dw -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72, + dw 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24, + dw 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4, + dw -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120, + dw 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108, + dw -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296, + dw 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336, + dw -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164, + dw -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264, + dw 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536, + dw -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296, + dw -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696, + dw 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204, + dw 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212, + dw -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40, + dw 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384, + dw 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8, + dw 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704, + dw -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348, + dw -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592, + dw -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420, + dw 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220, + dw -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208, + dw -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544, + dw -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288, + dw -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240, + dw -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132, + dw 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16, + dw -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044, + dw -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732, + dw 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460, + dw -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52, + dw -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104, + dw -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460, + dw 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716, + dw -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960, + dw 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476, + dw 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692, + dw 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352, + dw -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144, + dw -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44, + dw 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356, + dw 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452, + dw -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552, + dw -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264, + dw -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448, + dw -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588, + dw 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464, + dw 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216, + dw 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132, + dw 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412, + dw 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48, + dw 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196, + dw 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48, + dw -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292, + dw 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32, + dw -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012, + dw -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120, + dw -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56, + dw 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416, + dw -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404, + dw -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92, + dw 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904, + dw 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728, + dw 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584, + dw 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48, + dw 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180, + dw 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528, + dw 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364, + dw -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260, + dw -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324, + dw -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64, + dw 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120, + dw -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168, + dw -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888, + dw 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588, + dw -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484, + dw 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580, + dw 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392, + dw 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80, + dw -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688, + dw 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4, + dw -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300, + dw 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444, + dw 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192, + dw 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160, + dw 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188, + dw -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404, + dw -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400, + dw 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92, + dw -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824, + dw 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620, + dw 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720, + dw 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620, + dw -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508, + dw -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736, + dw 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836, + dw 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180, + dw 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140, + dw -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32, + dw -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916, + dw 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368, + dw -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380, + dw -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572, + dw -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864, + dw 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908, + dw -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84, + dw 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396, + dw -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360, + dw 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928, + dw -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288, + dw 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196, + dw 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504, + dw 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272, + dw 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344, + dw -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208, + dw -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156, + dw -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240, + dw -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432, + dw 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244, + dw 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584, + dw 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24, + dw 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300, + dw -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416, + dw 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380, + dw -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384, + dw 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88, + dw 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876, + dw -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320, + dw -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88, + dw -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196, + dw -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120, + dw 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664, + dw -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0, + dw -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264, + dw -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288, + dw -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56, + dw 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148, + dw 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156, + dw -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144, + dw -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148, + dw 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944, + dw 428, -484 + +align 8, db 0 +const resize_filter, db 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 1, -128, -2, 1, 0, 0, + db 0, -1, 3, -127, -4, 2, -1, 0, 0, -1, 4, -127, -6, 3, -1, 0, + db 0, -2, 6, -126, -8, 3, -1, 0, 0, -2, 7, -125, -11, 4, -1, 0, + db 1, -2, 8, -125, -13, 5, -2, 0, 1, -3, 9, -124, -15, 6, -2, 0, + db 1, -3, 10, -123, -18, 6, -2, 1, 1, -3, 11, -122, -20, 7, -3, 1, + db 1, -4, 12, -121, -22, 8, -3, 1, 1, -4, 13, -120, -25, 9, -3, 1, + db 1, -4, 14, -118, -28, 9, -3, 1, 1, -4, 15, -117, -30, 10, -4, 1, + db 1, -5, 16, -116, -32, 11, -4, 1, 1, -5, 16, -114, -35, 12, -4, 1, + db 1, -5, 17, -112, -38, 12, -4, 1, 1, -5, 18, -111, -40, 13, -5, 1, + db 1, -5, 18, -109, -43, 14, -5, 1, 1, -6, 19, -107, -45, 14, -5, 1, + db 1, -6, 19, -105, -48, 15, -5, 1, 1, -6, 19, -103, -51, 16, -5, 1, + db 1, -6, 20, -101, -53, 16, -6, 1, 1, -6, 20, -99, -56, 17, -6, 1, + db 1, -6, 20, -97, -58, 17, -6, 1, 1, -6, 20, -95, -61, 18, -6, 1, + db 2, -7, 20, -93, -64, 18, -6, 2, 2, -7, 20, -91, -66, 19, -6, 1, + db 2, -7, 20, -88, -69, 19, -6, 1, 2, -7, 20, -86, -71, 19, -6, 1, + db 2, -7, 20, -84, -74, 20, -7, 2, 2, -7, 20, -81, -76, 20, -7, 1, + db 2, -7, 20, -79, -79, 20, -7, 2, 1, -7, 20, -76, -81, 20, -7, 2, + db 2, -7, 20, -74, -84, 20, -7, 2, 1, -6, 19, -71, -86, 20, -7, 2, + db 1, -6, 19, -69, -88, 20, -7, 2, 1, -6, 19, -66, -91, 20, -7, 2, + db 2, -6, 18, -64, -93, 20, -7, 2, 1, -6, 18, -61, -95, 20, -6, 1, + db 1, -6, 17, -58, -97, 20, -6, 1, 1, -6, 17, -56, -99, 20, -6, 1, + db 1, -6, 16, -53, -101, 20, -6, 1, 1, -5, 16, -51, -103, 19, -6, 1, + db 1, -5, 15, -48, -105, 19, -6, 1, 1, -5, 14, -45, -107, 19, -6, 1, + db 1, -5, 14, -43, -109, 18, -5, 1, 1, -5, 13, -40, -111, 18, -5, 1, + db 1, -4, 12, -38, -112, 17, -5, 1, 1, -4, 12, -35, -114, 16, -5, 1, + db 1, -4, 11, -32, -116, 16, -5, 1, 1, -4, 10, -30, -117, 15, -4, 1, + db 1, -3, 9, -28, -118, 14, -4, 1, 1, -3, 9, -25, -120, 13, -4, 1, + db 1, -3, 8, -22, -121, 12, -4, 1, 1, -3, 7, -20, -122, 11, -3, 1, + db 1, -2, 6, -18, -123, 10, -3, 1, 0, -2, 6, -15, -124, 9, -3, 1, + db 0, -2, 5, -13, -125, 8, -2, 1, 0, -1, 4, -11, -125, 7, -2, 0, + db 0, -1, 3, -8, -126, 6, -2, 0, 0, -1, 3, -6, -127, 4, -1, 0, + db 0, -1, 2, -4, -127, 3, -1, 0, 0, 0, 1, -2, -128, 1, 0, 0, + +align 16, db 0 ; Unused +const obmc_masks, db 0, 0, + ; 2 + db 19, 0, + ; 4 + db 25, 14, 5, 0, + ; 8 + db 28, 22, 16, 11, 7, 3, 0, 0, + ; 16 + db 30, 27, 24, 21, 18, 15, 12, 10, 8, 6, 4, 3, 0, 0, 0, 0, + ; 32 + db 31, 29, 28, 26, 24, 23, 21, 20, 19, 17, 16, 14, 13, 12, 11, 9, + db 8, 7, 6, 5, 4, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"edc0d779823dacd5a4823ff8d4134c4b36a8fb979d88eb3833f08b499c313c17","Cargo.lock":"e788778a39ca992c25543c223459479101dbe115e9dd39e379837bee5b02da79","Cargo.toml":"ede178958614874fe4d066eca23ffcf15505b47546f81e12a4e21f31a8d8411a","Cargo.toml.orig":"2776f738ec3a0e976532541fb9de38de68bd293811db6e6e9360a16fbd3d0b30","LICENSE":"f78709143bb9643a3fd32071a371e261e14765cb69425831a4d1c586d2e72d0d","README.md":"3a049e0c53ba9f03be4946d23288dcfa889d1f8b82b5124072849d076c4a7a21","src/av1encoder.rs":"a478dbbf760b3b20bcd6fff41d243bc055b27869b3655ef132177b3edf8ac976","src/dirtyalpha.rs":"55997b9bbdfbd222444361cb3b1e73b014b2727f780ab1f302b2dab5b25b01d4","src/error.rs":"9f95f9bc8ae34626ad9e8486194cfc79d4a5b48fc22b54721f1091ed97059484","src/lib.rs":"afa030555b890f63b3944e98185c10a59a417f2a341ba6b78c43b94710513ebd"},"package":"ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "97338936031b2aba8839e3deec7d991d3b87f392" + }, + "path_in_vcs": "ravif" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,794 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-parse" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb75b6571a02b86e1bc8152d5ca71e0eb8f0c93b49e75a14e4743f3f285f209" +dependencies = [ + "arrayvec", + "bitreader", + "byteorder", + "fallible_collections", + "leb128", + "log", +] + +[[package]] +name = "avif-serialize" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitreader" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "886559b1e163d56c765bc3a985febb4eee8009f625244511d8ee3c432e08c066" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "bitstream-io" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afa0fc725d5ac9efc66f47b4c533ee850eb34aa6105681b5349c27157346ffa" +dependencies = [ + "core2", +] + +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fallible_collections" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3e85d14d419ba3e1db925519461c0d17a49bdd2d67ea6316fa965ca7acdf74" + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nasm-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12fcfa1bd49e0342ec1d07ed2be83b59963e7acbeb9310e1bb2c07b69dadd959" +dependencies = [ + "jobserver", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cc", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "nasm-rs", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.12.0" +dependencies = [ + "avif-parse", + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.83" +name = "ravif" +version = "0.12.0" +authors = ["Kornel Lesiński "] +build = false +include = [ + "README.md", + "LICENSE", + "Cargo.toml", + "/src/*.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "rav1e-based pure Rust library for encoding images in AVIF format (powers the `cavif` tool)" +homepage = "https://lib.rs/crates/ravif" +readme = "README.md" +keywords = [ + "avif", + "convert", + "av1", + "rav1f", + "cav1f", +] +categories = [ + "multimedia::images", + "multimedia::encoding", +] +license = "BSD-3-Clause" +repository = "https://github.com/kornelski/cavif-rs" + +[package.metadata.release] +tag = false + +[features] +asm = ["rav1e/asm"] +default = [ + "asm", + "threading", +] +threading = [ + "dep:rayon", + "rav1e/threading", +] + +[lib] +name = "ravif" +path = "src/lib.rs" + +[dependencies.avif-serialize] +version = "0.8.3" + +[dependencies.imgref] +version = "1.11.0" + +[dependencies.loop9] +version = "0.1.5" + +[dependencies.quick-error] +version = "2.0.1" + +[dependencies.rav1e] +version = "0.8.1" +default-features = false + +[dependencies.rayon] +version = "1.10.0" +optional = true + +[dependencies.rgb] +version = "0.8.50" +default-features = false + +[dev-dependencies.avif-parse] +version = "1.3.2" + +[target.'cfg(target = "wasm32-unknown-unknown")'.dependencies.rav1e] +version = "0.8" +features = ["wasm"] +default-features = false + +[profile.dev.package."*"] +opt-level = 2 +debug = 0 + +[profile.release] +lto = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,44 @@ +[package] +name = "ravif" +description = "rav1e-based pure Rust library for encoding images in AVIF format (powers the `cavif` tool)" +version = "0.12.0" +authors = ["Kornel Lesiński "] +edition = "2021" +license = "BSD-3-Clause" +readme = "README.md" +keywords = ["avif", "convert", "av1", "rav1f", "cav1f"] +categories = ["multimedia::images", "multimedia::encoding"] +homepage = "https://lib.rs/crates/ravif" +repository = "https://github.com/kornelski/cavif-rs" +include = ["README.md", "LICENSE", "Cargo.toml", "/src/*.rs"] +rust-version = "1.83" + +[dependencies] +avif-serialize = "0.8.3" +imgref = "1.11.0" +rav1e = { version = "0.8.1", default-features = false } +rayon = { version = "1.10.0", optional = true } +rgb = { version = "0.8.50", default-features = false } +loop9 = "0.1.5" +quick-error = "2.0.1" + +[target.'cfg(target = "wasm32-unknown-unknown")'.dependencies] +rav1e = { version = "0.8", default-features = false, features = ["wasm"] } + +[features] +default = ["asm", "threading"] +asm = ["rav1e/asm"] +threading = ["dep:rayon", "rav1e/threading"] + +[profile.release] +lto = true + +[profile.dev.package."*"] +debug = false +opt-level = 2 + +[dev-dependencies] +avif-parse = "1.3.2" + +[package.metadata.release] +tag = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/ravif/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, Kornel +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/README.md clamav-1.4.6+dfsg/.cargo/vendor/ravif/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +# `ravif` — Pure Rust library for AVIF image encoding + +Encoder for AVIF images. Based on [`rav1e`](https://lib.rs/crates/rav1e) and [`avif-serialize`](https://lib.rs/crates/avif-serialize). + +The API is just a single `encode_rgba()` function call that spits an AVIF image. + +This library powers the [`cavif`](https://lib.rs/crates/cavif) encoder. It has an encoding configuration specifically tuned for still images, and gives better quality/performance than stock `rav1e`. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/av1encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/av1encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/av1encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/av1encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,736 @@ +#![allow(deprecated)] +use crate::dirtyalpha::blurred_dirty_alpha; +use crate::error::Error; +#[cfg(not(feature = "threading"))] +use crate::rayoff as rayon; +use imgref::{Img, ImgVec}; +use rav1e::prelude::*; +use rgb::{RGB8, RGBA8}; + +/// For [`Encoder::with_internal_color_model`] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum ColorModel { + /// Standard color model for photographic content. Usually the best choice. + /// This library always uses full-resolution color (4:4:4). + /// This library will automatically choose between BT.601 or BT.709. + YCbCr, + /// RGB channels are encoded without color space transformation. + /// Usually results in larger file sizes, and is less compatible than `YCbCr`. + /// Use only if the content really makes use of RGB, e.g. anaglyph images or RGB subpixel anti-aliasing. + RGB, +} + +/// Handling of color channels in transparent images. For [`Encoder::with_alpha_color_mode`] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum AlphaColorMode { + /// Use unassociated alpha channel and leave color channels unchanged, even if there's redundant color data in transparent areas. + UnassociatedDirty, + /// Use unassociated alpha channel, but set color channels of transparent areas to a solid color to eliminate invisible data and improve compression. + UnassociatedClean, + /// Store color channels of transparent images in premultiplied form. + /// This requires support for premultiplied alpha in AVIF decoders. + /// + /// It may reduce file sizes due to clearing of fully-transparent pixels, but + /// may also increase file sizes due to creation of new edges in the color channels. + /// + /// Note that this is only internal detail for the AVIF file. + /// It does not change meaning of `RGBA` in this library — it's always unassociated. + Premultiplied, +} + +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +pub enum BitDepth { + Eight, + Ten, + /// Same as `Ten` + #[default] + Auto, +} + +/// The newly-created image file + extra info FYI +#[non_exhaustive] +#[derive(Clone)] +pub struct EncodedImage { + /// AVIF (HEIF+AV1) encoded image data + pub avif_file: Vec, + /// FYI: number of bytes of AV1 payload used for the color + pub color_byte_size: usize, + /// FYI: number of bytes of AV1 payload used for the alpha channel + pub alpha_byte_size: usize, +} + +/// Encoder config builder +#[derive(Debug, Clone)] +pub struct Encoder { + /// 0-255 scale + quantizer: u8, + /// 0-255 scale + alpha_quantizer: u8, + /// rav1e preset 1 (slow) 10 (fast but crappy) + speed: u8, + /// True if RGBA input has already been premultiplied. It inserts appropriate metadata. + premultiplied_alpha: bool, + /// Which pixel format to use in AVIF file. RGB tends to give larger files. + color_model: ColorModel, + /// How many threads should be used (0 = match core count), None - use global rayon thread pool + threads: Option, + /// [`AlphaColorMode`] + alpha_color_mode: AlphaColorMode, + /// 8 or 10 + output_depth: BitDepth, +} + +/// Builder methods +impl Encoder { + /// Start here + #[must_use] + pub fn new() -> Self { + Self { + quantizer: quality_to_quantizer(80.), + alpha_quantizer: quality_to_quantizer(80.), + speed: 5, + output_depth: BitDepth::default(), + premultiplied_alpha: false, + color_model: ColorModel::YCbCr, + threads: None, + alpha_color_mode: AlphaColorMode::UnassociatedClean, + } + } + + /// Quality `1..=100`. Panics if out of range. + #[inline(always)] + #[track_caller] + #[must_use] + pub fn with_quality(mut self, quality: f32) -> Self { + assert!(quality >= 1. && quality <= 100.); + self.quantizer = quality_to_quantizer(quality); + self + } + + #[doc(hidden)] + #[deprecated(note = "Renamed to with_bit_depth")] + pub fn with_depth(self, depth: Option) -> Self { + self.with_bit_depth(depth.map(|d| if d >= 10 { BitDepth::Ten } else { BitDepth::Eight }).unwrap_or(BitDepth::Auto)) + } + + /// Internal precision to use in the encoded AV1 data, for both color and alpha. 10-bit depth works best, even for 8-bit inputs/outputs. + /// + /// Use 8-bit depth only as a workaround for decoders that need it. + /// + /// This setting does not affect pixel inputs for this library. + #[inline(always)] + #[must_use] + pub fn with_bit_depth(mut self, depth: BitDepth) -> Self { + self.output_depth = depth; + self + } + + /// Quality for the alpha channel only. `1..=100`. Panics if out of range. + #[inline(always)] + #[track_caller] + #[must_use] + pub fn with_alpha_quality(mut self, quality: f32) -> Self { + assert!(quality >= 1. && quality <= 100.); + self.alpha_quantizer = quality_to_quantizer(quality); + self + } + + /// * 1 = very very slow, but max compression. + /// * 10 = quick, but larger file sizes and lower quality. + /// + /// Panics if outside `1..=10`. + #[inline(always)] + #[track_caller] + #[must_use] + pub fn with_speed(mut self, speed: u8) -> Self { + assert!(speed >= 1 && speed <= 10); + self.speed = speed; + self + } + + /// Changes how color channels are stored in the image. The default is YCbCr. + /// + /// Note that this is only internal detail for the AVIF file, and doesn't + /// change color model of inputs to encode functions. + #[inline(always)] + #[must_use] + pub fn with_internal_color_model(mut self, color_model: ColorModel) -> Self { + self.color_model = color_model; + self + } + + #[doc(hidden)] + #[deprecated = "Renamed to `with_internal_color_model()`"] + pub fn with_internal_color_space(self, color_model: ColorModel) -> Self { + self.with_internal_color_model(color_model) + } + + /// Configures `rayon` thread pool size. + /// The default `None` is to use all threads in the default `rayon` thread pool. + #[inline(always)] + #[track_caller] + #[must_use] + pub fn with_num_threads(mut self, num_threads: Option) -> Self { + assert!(num_threads.map_or(true, |n| n > 0)); + self.threads = num_threads; + self + } + + /// Configure handling of color channels in transparent images + /// + /// Note that this doesn't affect input format for this library, + /// which for RGBA is always uncorrelated alpha. + #[inline(always)] + #[must_use] + pub fn with_alpha_color_mode(mut self, mode: AlphaColorMode) -> Self { + self.alpha_color_mode = mode; + self.premultiplied_alpha = mode == AlphaColorMode::Premultiplied; + self + } +} + +/// Once done with config, call one of the `encode_*` functions +impl Encoder { + /// Make a new AVIF image from RGBA pixels (non-premultiplied, alpha last) + /// + /// Make the `Img` for the `buffer` like this: + /// + /// ```rust,ignore + /// Img::new(&pixels_rgba[..], width, height) + /// ``` + /// + /// If you have pixels as `u8` slice, then use the `rgb` crate, and do: + /// + /// ```rust,ignore + /// use rgb::ComponentSlice; + /// let pixels_rgba = pixels_u8.as_rgba(); + /// ``` + /// + /// If all pixels are opaque, the alpha channel will be left out automatically. + /// + /// This function takes 8-bit inputs, but will generate an AVIF file using 10-bit depth. + /// + /// returns AVIF file with info about sizes about AV1 payload. + pub fn encode_rgba(&self, in_buffer: Img<&[rgb::RGBA]>) -> Result { + let new_alpha = self.convert_alpha_8bit(in_buffer); + let buffer = new_alpha.as_ref().map(|b| b.as_ref()).unwrap_or(in_buffer); + let use_alpha = buffer.pixels().any(|px| px.a != 255); + if !use_alpha { + return self.encode_rgb_internal_from_8bit(buffer.width(), buffer.height(), buffer.pixels().map(|px| px.rgb())); + } + + let width = buffer.width(); + let height = buffer.height(); + let matrix_coefficients = match self.color_model { + ColorModel::YCbCr => MatrixCoefficients::BT601, + ColorModel::RGB => MatrixCoefficients::Identity, + }; + match self.output_depth { + BitDepth::Eight => { + let planes = buffer.pixels().map(|px| { + let (y, u, v) = match self.color_model { + ColorModel::YCbCr => rgb_to_8_bit_ycbcr(px.rgb(), BT601), + ColorModel::RGB => rgb_to_8_bit_gbr(px.rgb()), + }; + [y, u, v] + }); + let alpha = buffer.pixels().map(|px| px.a); + self.encode_raw_planes_8_bit(width, height, planes, Some(alpha), PixelRange::Full, matrix_coefficients) + }, + BitDepth::Ten | BitDepth::Auto => { + let planes = buffer.pixels().map(|px| { + let (y, u, v) = match self.color_model { + ColorModel::YCbCr => rgb_to_10_bit_ycbcr(px.rgb(), BT601), + ColorModel::RGB => rgb_to_10_bit_gbr(px.rgb()), + }; + [y, u, v] + }); + let alpha = buffer.pixels().map(|px| to_ten(px.a)); + self.encode_raw_planes_10_bit(width, height, planes, Some(alpha), PixelRange::Full, matrix_coefficients) + }, + } + } + + fn convert_alpha_8bit(&self, in_buffer: Img<&[RGBA8]>) -> Option> { + match self.alpha_color_mode { + AlphaColorMode::UnassociatedDirty => None, + AlphaColorMode::UnassociatedClean => blurred_dirty_alpha(in_buffer), + AlphaColorMode::Premultiplied => { + let prem = in_buffer.pixels() + .map(|px| { + if px.a == 0 || px.a == 255 { + RGBA8::default() + } else { + RGBA8::new( + (u16::from(px.r) * 255 / u16::from(px.a)) as u8, + (u16::from(px.g) * 255 / u16::from(px.a)) as u8, + (u16::from(px.b) * 255 / u16::from(px.a)) as u8, + px.a, + ) + } + }) + .collect(); + Some(ImgVec::new(prem, in_buffer.width(), in_buffer.height())) + }, + } + } + + /// Make a new AVIF image from RGB pixels + /// + /// Make the `Img` for the `buffer` like this: + /// + /// ```rust,ignore + /// Img::new(&pixels_rgb[..], width, height) + /// ``` + /// + /// If you have pixels as `u8` slice, then first do: + /// + /// ```rust,ignore + /// use rgb::ComponentSlice; + /// let pixels_rgb = pixels_u8.as_rgb(); + /// ``` + /// + /// returns AVIF file, size of color metadata + #[inline] + pub fn encode_rgb(&self, buffer: Img<&[RGB8]>) -> Result { + self.encode_rgb_internal_from_8bit(buffer.width(), buffer.height(), buffer.pixels()) + } + + fn encode_rgb_internal_from_8bit(&self, width: usize, height: usize, pixels: impl Iterator + Send + Sync) -> Result { + let matrix_coefficients = match self.color_model { + ColorModel::YCbCr => MatrixCoefficients::BT601, + ColorModel::RGB => MatrixCoefficients::Identity, + }; + + match self.output_depth { + BitDepth::Eight => { + let planes = pixels.map(|px| { + let (y, u, v) = match self.color_model { + ColorModel::YCbCr => rgb_to_8_bit_ycbcr(px, BT601), + ColorModel::RGB => rgb_to_8_bit_gbr(px), + }; + [y, u, v] + }); + self.encode_raw_planes_8_bit(width, height, planes, None::<[_; 0]>, PixelRange::Full, matrix_coefficients) + }, + BitDepth::Ten | BitDepth::Auto => { + let planes = pixels.map(|px| { + let (y, u, v) = match self.color_model { + ColorModel::YCbCr => rgb_to_10_bit_ycbcr(px, BT601), + ColorModel::RGB => rgb_to_10_bit_gbr(px), + }; + [y, u, v] + }); + self.encode_raw_planes_10_bit(width, height, planes, None::<[_; 0]>, PixelRange::Full, matrix_coefficients) + }, + } + } + + /// Encodes AVIF from 3 planar channels that are in the color space described by `matrix_coefficients`, + /// with sRGB transfer characteristics and color primaries. + /// + /// Alpha always uses full range. Chroma subsampling is not supported, and it's a bad idea for AVIF anyway. + /// If there's no alpha, use `None::<[_; 0]>`. + /// + /// `color_pixel_range` should be `PixelRange::Full` to avoid worsening already small 8-bit dynamic range. + /// Support for limited range may be removed in the future. + /// + /// If `AlphaColorMode::Premultiplied` has been set, the alpha pixels must be premultiplied. + /// `AlphaColorMode::UnassociatedClean` has no effect in this function, and is equivalent to `AlphaColorMode::UnassociatedDirty`. + /// + /// returns AVIF file, size of color metadata, size of alpha metadata overhead + #[inline] + pub fn encode_raw_planes_8_bit( + &self, width: usize, height: usize, planes: impl IntoIterator + Send, alpha: Option + Send>, + color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, + ) -> Result { + self.encode_raw_planes_internal(width, height, planes, alpha, color_pixel_range, matrix_coefficients, 8) + } + + /// Encodes AVIF from 3 planar channels that are in the color space described by `matrix_coefficients`, + /// with sRGB transfer characteristics and color primaries. + /// + /// The pixels are 10-bit (values `0.=1023`). + /// + /// Alpha always uses full range. Chroma subsampling is not supported, and it's a bad idea for AVIF anyway. + /// If there's no alpha, use `None::<[_; 0]>`. + /// + /// `color_pixel_range` should be `PixelRange::Full`. Support for limited range may be removed in the future. + /// + /// If `AlphaColorMode::Premultiplied` has been set, the alpha pixels must be premultiplied. + /// `AlphaColorMode::UnassociatedClean` has no effect in this function, and is equivalent to `AlphaColorMode::UnassociatedDirty`. + /// + /// returns AVIF file, size of color metadata, size of alpha metadata overhead + #[inline] + pub fn encode_raw_planes_10_bit( + &self, width: usize, height: usize, planes: impl IntoIterator + Send, alpha: Option + Send>, + color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, + ) -> Result { + self.encode_raw_planes_internal(width, height, planes, alpha, color_pixel_range, matrix_coefficients, 10) + } + + #[inline(never)] + fn encode_raw_planes_internal( + &self, width: usize, height: usize, planes: impl IntoIterator + Send, alpha: Option + Send>, + color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, input_pixels_bit_depth: u8, + ) -> Result { + let color_description = Some(ColorDescription { + transfer_characteristics: TransferCharacteristics::SRGB, + color_primaries: ColorPrimaries::BT709, // sRGB-compatible + matrix_coefficients, + }); + + let threads = self.threads.map(|threads| { + if threads > 0 { threads } else { rayon::current_num_threads() } + }); + + let encode_color = move || { + encode_to_av1::

( + &Av1EncodeConfig { + width, + height, + bit_depth: input_pixels_bit_depth.into(), + quantizer: self.quantizer.into(), + speed: SpeedTweaks::from_my_preset(self.speed, self.quantizer), + threads, + pixel_range: color_pixel_range, + chroma_sampling: ChromaSampling::Cs444, + color_description, + }, + move |frame| init_frame_3(width, height, planes, frame), + ) + }; + let encode_alpha = move || { + alpha.map(|alpha| { + encode_to_av1::

( + &Av1EncodeConfig { + width, + height, + bit_depth: input_pixels_bit_depth.into(), + quantizer: self.alpha_quantizer.into(), + speed: SpeedTweaks::from_my_preset(self.speed, self.alpha_quantizer), + threads, + pixel_range: PixelRange::Full, + chroma_sampling: ChromaSampling::Cs400, + color_description: None, + }, + |frame| init_frame_1(width, height, alpha, frame), + ) + }) + }; + #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + let (color, alpha) = (encode_color(), encode_alpha()); + #[cfg(not(all(target_arch = "wasm32", not(target_feature = "atomics"))))] + let (color, alpha) = rayon::join(encode_color, encode_alpha); + let (color, alpha) = (color?, alpha.transpose()?); + + let avif_file = avif_serialize::Aviffy::new() + .matrix_coefficients(match matrix_coefficients { + MatrixCoefficients::Identity => avif_serialize::constants::MatrixCoefficients::Rgb, + MatrixCoefficients::BT709 => avif_serialize::constants::MatrixCoefficients::Bt709, + MatrixCoefficients::Unspecified => avif_serialize::constants::MatrixCoefficients::Unspecified, + MatrixCoefficients::BT601 => avif_serialize::constants::MatrixCoefficients::Bt601, + MatrixCoefficients::YCgCo => avif_serialize::constants::MatrixCoefficients::Ycgco, + MatrixCoefficients::BT2020NCL => avif_serialize::constants::MatrixCoefficients::Bt2020Ncl, + MatrixCoefficients::BT2020CL => avif_serialize::constants::MatrixCoefficients::Bt2020Cl, + _ => return Err(Error::Unsupported("matrix coefficients")), + }) + .premultiplied_alpha(self.premultiplied_alpha) + .to_vec(&color, alpha.as_deref(), width as u32, height as u32, input_pixels_bit_depth); + let color_byte_size = color.len(); + let alpha_byte_size = alpha.as_ref().map_or(0, |a| a.len()); + + Ok(EncodedImage { + avif_file, color_byte_size, alpha_byte_size, + }) + } +} + +#[inline(always)] +fn to_ten(x: u8) -> u16 { + (u16::from(x) << 2) | (u16::from(x) >> 6) +} + +#[inline(always)] +fn rgb_to_10_bit_gbr(px: rgb::RGB) -> (u16, u16, u16) { + (to_ten(px.g), to_ten(px.b), to_ten(px.r)) +} + +#[inline(always)] +fn rgb_to_8_bit_gbr(px: rgb::RGB) -> (u8, u8, u8) { + (px.g, px.b, px.r) +} + +// const REC709: [f32; 3] = [0.2126, 0.7152, 0.0722]; +const BT601: [f32; 3] = [0.2990, 0.5870, 0.1140]; + +#[inline(always)] +fn rgb_to_ycbcr(px: rgb::RGB, depth: u8, matrix: [f32; 3]) -> (f32, f32, f32) { + let max_value = ((1 << depth) - 1) as f32; + let scale = max_value / 255.; + let shift = (max_value * 0.5).round(); + let y = scale * matrix[0] * f32::from(px.r) + scale * matrix[1] * f32::from(px.g) + scale * matrix[2] * f32::from(px.b); + let cb = (f32::from(px.b) * scale - y).mul_add(0.5 / (1. - matrix[2]), shift); + let cr = (f32::from(px.r) * scale - y).mul_add(0.5 / (1. - matrix[0]), shift); + (y.round(), cb.round(), cr.round()) +} + +#[inline(always)] +fn rgb_to_10_bit_ycbcr(px: rgb::RGB, matrix: [f32; 3]) -> (u16, u16, u16) { + let (y, u, v) = rgb_to_ycbcr(px, 10, matrix); + (y as u16, u as u16, v as u16) +} + +#[inline(always)] +fn rgb_to_8_bit_ycbcr(px: rgb::RGB, matrix: [f32; 3]) -> (u8, u8, u8) { + let (y, u, v) = rgb_to_ycbcr(px, 8, matrix); + (y as u8, u as u8, v as u8) +} + +fn quality_to_quantizer(quality: f32) -> u8 { + let q = quality / 100.; + let x = if q >= 0.85 { (1. - q) * 3. } else if q > 0.25 { 1. - 0.125 - q * 0.5 } else { 1. - q }; + (x * 255.).round() as u8 +} + +#[derive(Debug, Copy, Clone)] +struct SpeedTweaks { + pub speed_preset: u8, + + pub fast_deblock: Option, + pub reduced_tx_set: Option, + pub tx_domain_distortion: Option, + pub tx_domain_rate: Option, + pub encode_bottomup: Option, + pub rdo_tx_decision: Option, + pub cdef: Option, + /// loop restoration filter + pub lrf: Option, + pub sgr_complexity_full: Option, + pub use_satd_subpel: Option, + pub inter_tx_split: Option, + pub fine_directional_intra: Option, + pub complex_prediction_modes: Option, + pub partition_range: Option<(u8, u8)>, + pub min_tile_size: u16, +} + +impl SpeedTweaks { + pub fn from_my_preset(speed: u8, quantizer: u8) -> Self { + let low_quality = quantizer < quality_to_quantizer(55.); + let high_quality = quantizer > quality_to_quantizer(80.); + let max_block_size = if high_quality { 16 } else { 64 }; + + Self { + speed_preset: speed, + + partition_range: Some(match speed { + 0 => (4, 64.min(max_block_size)), + 1 if low_quality => (4, 64.min(max_block_size)), + 2 if low_quality => (4, 32.min(max_block_size)), + 1..=4 => (4, 16), + 5..=8 => (8, 16), + _ => (16, 16), + }), + + complex_prediction_modes: Some(speed <= 1), // 2x-3x slower, 2% better + sgr_complexity_full: Some(speed <= 2), // 15% slower, barely improves anything -/+1% + + encode_bottomup: Some(speed <= 2), // may be costly (+60%), may even backfire + + // big blocks disabled at 3 + + // these two are together? + rdo_tx_decision: Some(speed <= 4 && !high_quality), // it tends to blur subtle textures + reduced_tx_set: Some(speed == 4 || speed >= 9), // It interacts with tx_domain_distortion too? + + // 4px blocks disabled at 5 + + fine_directional_intra: Some(speed <= 6), + fast_deblock: Some(speed >= 7 && !high_quality), // mixed bag? + + // 8px blocks disabled at 8 + lrf: Some(low_quality && speed <= 8), // hardly any help for hi-q images. recovers some q at low quality + cdef: Some(low_quality && speed <= 9), // hardly any help for hi-q images. recovers some q at low quality + + inter_tx_split: Some(speed >= 9), // mixed bag even when it works, and it backfires if not used together with reduced_tx_set + tx_domain_rate: Some(speed >= 10), // 20% faster, but also 10% larger files! + + tx_domain_distortion: None, // very mixed bag, sometimes helps speed sometimes it doesn't + use_satd_subpel: Some(false), // doesn't make sense + min_tile_size: match speed { + 0 => 4096, + 1 => 2048, + 2 => 1024, + 3 => 512, + 4 => 256, + _ => 128, + } * if high_quality { 2 } else { 1 }, + } + } + + pub(crate) fn speed_settings(&self) -> SpeedSettings { + let mut speed_settings = SpeedSettings::from_preset(self.speed_preset); + + speed_settings.multiref = false; + speed_settings.rdo_lookahead_frames = 1; + speed_settings.scene_detection_mode = SceneDetectionSpeed::None; + speed_settings.motion.include_near_mvs = false; + + if let Some(v) = self.fast_deblock { speed_settings.fast_deblock = v; } + if let Some(v) = self.reduced_tx_set { speed_settings.transform.reduced_tx_set = v; } + if let Some(v) = self.tx_domain_distortion { speed_settings.transform.tx_domain_distortion = v; } + if let Some(v) = self.tx_domain_rate { speed_settings.transform.tx_domain_rate = v; } + if let Some(v) = self.encode_bottomup { speed_settings.partition.encode_bottomup = v; } + if let Some(v) = self.rdo_tx_decision { speed_settings.transform.rdo_tx_decision = v; } + if let Some(v) = self.cdef { speed_settings.cdef = v; } + if let Some(v) = self.lrf { speed_settings.lrf = v; } + if let Some(v) = self.inter_tx_split { speed_settings.transform.enable_inter_tx_split = v; } + if let Some(v) = self.sgr_complexity_full { speed_settings.sgr_complexity = if v { SGRComplexityLevel::Full } else { SGRComplexityLevel::Reduced } }; + if let Some(v) = self.use_satd_subpel { speed_settings.motion.use_satd_subpel = v; } + if let Some(v) = self.fine_directional_intra { speed_settings.prediction.fine_directional_intra = v; } + if let Some(v) = self.complex_prediction_modes { speed_settings.prediction.prediction_modes = if v { PredictionModesSetting::ComplexAll } else { PredictionModesSetting::Simple} }; + if let Some((min, max)) = self.partition_range { + debug_assert!(min <= max); + fn sz(s: u8) -> BlockSize { + match s { + 4 => BlockSize::BLOCK_4X4, + 8 => BlockSize::BLOCK_8X8, + 16 => BlockSize::BLOCK_16X16, + 32 => BlockSize::BLOCK_32X32, + 64 => BlockSize::BLOCK_64X64, + 128 => BlockSize::BLOCK_128X128, + _ => panic!("bad size {s}"), + } + } + speed_settings.partition.partition_range = PartitionRange::new(sz(min), sz(max)); + } + + speed_settings + } +} + +struct Av1EncodeConfig { + pub width: usize, + pub height: usize, + pub bit_depth: usize, + pub quantizer: usize, + pub speed: SpeedTweaks, + /// 0 means num_cpus + pub threads: Option, + pub pixel_range: PixelRange, + pub chroma_sampling: ChromaSampling, + pub color_description: Option, +} + +fn rav1e_config(p: &Av1EncodeConfig) -> Config { + // AV1 needs all the CPU power you can give it, + // except when it'd create inefficiently tiny tiles + let tiles = { + let threads = p.threads.unwrap_or_else(rayon::current_num_threads); + threads.min((p.width * p.height) / (p.speed.min_tile_size as usize).pow(2)) + }; + let speed_settings = p.speed.speed_settings(); + let cfg = Config::new() + .with_encoder_config(EncoderConfig { + width: p.width, + height: p.height, + time_base: Rational::new(1, 1), + sample_aspect_ratio: Rational::new(1, 1), + bit_depth: p.bit_depth, + chroma_sampling: p.chroma_sampling, + chroma_sample_position: ChromaSamplePosition::Unknown, + pixel_range: p.pixel_range, + color_description: p.color_description, + mastering_display: None, + content_light: None, + enable_timing_info: false, + still_picture: true, + error_resilient: false, + switch_frame_interval: 0, + min_key_frame_interval: 0, + max_key_frame_interval: 0, + reservoir_frame_delay: None, + low_latency: false, + quantizer: p.quantizer, + min_quantizer: p.quantizer as _, + bitrate: 0, + tune: Tune::Psychovisual, + tile_cols: 0, + tile_rows: 0, + tiles, + film_grain_params: None, + level_idx: None, + speed_settings, + }); + + if let Some(threads) = p.threads { + cfg.with_threads(threads) + } else { + cfg + } +} + +fn init_frame_3( + width: usize, height: usize, planes: impl IntoIterator + Send, frame: &mut Frame

, +) -> Result<(), Error> { + let mut f = frame.planes.iter_mut(); + let mut planes = planes.into_iter(); + + // it doesn't seem to be necessary to fill padding area + let mut y = f.next().unwrap().mut_slice(Default::default()); + let mut u = f.next().unwrap().mut_slice(Default::default()); + let mut v = f.next().unwrap().mut_slice(Default::default()); + + for ((y, u), v) in y.rows_iter_mut().zip(u.rows_iter_mut()).zip(v.rows_iter_mut()).take(height) { + let y = &mut y[..width]; + let u = &mut u[..width]; + let v = &mut v[..width]; + for ((y, u), v) in y.iter_mut().zip(u).zip(v) { + let px = planes.next().ok_or(Error::TooFewPixels)?; + *y = px[0]; + *u = px[1]; + *v = px[2]; + } + } + Ok(()) +} + +fn init_frame_1(width: usize, height: usize, planes: impl IntoIterator + Send, frame: &mut Frame

) -> Result<(), Error> { + let mut y = frame.planes[0].mut_slice(Default::default()); + let mut planes = planes.into_iter(); + + for y in y.rows_iter_mut().take(height) { + let y = &mut y[..width]; + for y in y.iter_mut() { + *y = planes.next().ok_or(Error::TooFewPixels)?; + } + } + Ok(()) +} + +#[inline(never)] +fn encode_to_av1(p: &Av1EncodeConfig, init: impl FnOnce(&mut Frame

) -> Result<(), Error>) -> Result, Error> { + let mut ctx: Context

+

wasip2

+ +A Bytecode Alliance project + +

+ WASIp2 API Bindings for Rust +

+ +

+ Crates.io version + Download + docs.rs docs +

+
+ +This crate contains bindings for [WASIp2](https://github.com/WebAssembly/WASI) +APIs for the worlds: + +* [`wasi:cli/command`] +* [`wasi:http/proxy`] + +This crate is procedurally generated from [WIT] files using [`wit-bindgen`]. + +[`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli +[`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http +[WIT]: https://component-model.bytecodealliance.org/design/wit.html +[`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen +[components]: https://component-model.bytecodealliance.org/ +[`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools + +# Usage + +Depending on this crate can be done by adding it to your dependencies: + +```sh +$ cargo add wasip2 +``` + +Next you can use the APIs in the root of the module like so: + +```rust +fn main() { + let stdout = wasip2::cli::stdout::get_stdout(); + stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap(); +} +``` + +This crate can currently be used in three main ways. + +- One is to use it and compile for the [`wasm32-wasip2` target] in Rust 1.82 and later. + this is the simplest approach, as all the tools needed are included in the + Rust tooling, however it doesn't yet support some of the features of the + other approaches. + +- Another is to use it and compile using [`cargo component`]. This is essentially + the same as the next option, except that `cargo component` handles most of the + steps for you. `cargo component` also has a number of additional features for + working with dependencies and custom WIT interfaces. + +- And the third is to compile for the `wasm32-wasip1` target, and then adapt + the resulting modules into component using `wasm-tools component new`; see + the next section here for details. + +[`wasm32-wasip2` target]: https://blog.rust-lang.org/2024/11/26/wasip2-tier-2.html +[`cargo component`]: https://github.com/bytecodealliance/cargo-component + +## Building with wasm32-wasip1 and `cargo component new`. + +The `wasm32-wasip2` target works with a simple `cargo build --target wasm32-wasip2` +and doesn't need a lot of documentation here, and `cargo component` has its own +documentation, so here we have some documentation for the `wasm32-wasip1` way. + +``` +$ cargo build --target wasm32-wasip1 +``` + +Next you'll want an "adapter" to convert the Rust standard library's usage of +`wasi_snapshot_preview1` to the component model. An example adapter can be found +from [Wasmtime's release page](https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm). + +``` +$ curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm +``` + +Next to create a component you'll use the [`wasm-tools`] CLI to create a +component: + +``` +$ cargo install wasm-tools +$ wasm-tools component new target/wasm32-wasip1/debug/foo.wasm \ + --adapt ./wasi_snapshot_preview1.command.wasm \ + -o component.wasm +``` + +And finally the component can be run by a runtime that has Component Model +support, such as [Wasmtime]: + +``` +$ wasmtime run component.wasm +Hello, world! +``` + +[Wasmtime]: https://github.com/bytecodealliance/wasmtime + +# Development + +The bulk of the `wasip2` crate is generated by the [`wit-bindgen`] tool. The +`src/bindings.rs` file can be regenerated with: + +``` +$ ./ci/regenerate.sh +``` + +WASI definitions are located in the `wit` directory of this repository. +Currently they're copied from upstream repositories but are hoped to be better +managed in the future. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/cli-command-no_std.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command-no_std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/cli-command-no_std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command-no_std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +wasip2::cli::command::export!(Example); + +struct Example; + +impl wasip2::exports::cli::run::Guest for Example { + fn run() -> Result<(), ()> { + let stdout = wasip2::cli::stdout::get_stdout(); + stdout.blocking_write_and_flush(b"Hello, WASI!").unwrap(); + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/cli-command.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/cli-command.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/cli-command.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +use std::io::Write as _; + +wasip2::cli::command::export!(Example); + +struct Example; + +impl wasip2::exports::cli::run::Guest for Example { + fn run() -> Result<(), ()> { + let mut stdout = wasip2::cli::stdout::get_stdout(); + stdout.write_all(b"Hello, WASI!").unwrap(); + stdout.flush().unwrap(); + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/hello-world-no_std.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world-no_std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/hello-world-no_std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world-no_std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +fn main() { + let stdout = wasip2::cli::stdout::get_stdout(); + stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/hello-world.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/hello-world.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/hello-world.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use std::io::Write as _; + +fn main() { + let mut stdout = wasip2::cli::stdout::get_stdout(); + stdout.write_all(b"Hello, world!\n").unwrap(); + stdout.flush().unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/http-proxy-no_std.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy-no_std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/http-proxy-no_std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy-no_std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +use wasip2::http::types::{ + Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam, +}; + +wasip2::http::proxy::export!(Example); + +struct Example; + +impl wasip2::exports::http::incoming_handler::Guest for Example { + fn handle(_request: IncomingRequest, response_out: ResponseOutparam) { + let resp = OutgoingResponse::new(Fields::new()); + let body = resp.body().unwrap(); + + ResponseOutparam::set(response_out, Ok(resp)); + + let out = body.write().unwrap(); + out.blocking_write_and_flush(b"Hello, WASI!").unwrap(); + drop(out); + + OutgoingBody::finish(body, None).unwrap(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/http-proxy.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/examples/http-proxy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/examples/http-proxy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +use std::io::Write as _; + +use wasip2::http::types::{ + Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam, +}; + +wasip2::http::proxy::export!(Example); + +struct Example; + +impl wasip2::exports::http::incoming_handler::Guest for Example { + fn handle(_request: IncomingRequest, response_out: ResponseOutparam) { + let resp = OutgoingResponse::new(Fields::new()); + let body = resp.body().unwrap(); + + ResponseOutparam::set(response_out, Ok(resp)); + + let mut out = body.write().unwrap(); + out.write_all(b"Hello, WASI!").unwrap(); + out.flush().unwrap(); + drop(out); + + OutgoingBody::finish(body, None).unwrap(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/command.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/command.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/command.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/command.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,627 @@ +// Generated by `wit-bindgen` 0.46.0. DO NOT EDIT! +// Options used: +// * std_feature +// * with "wasi:cli/environment@0.2.4" = "crate::cli::environment" +// * with "wasi:cli/exit@0.2.4" = "crate::cli::exit" +// * with "wasi:cli/stdin@0.2.4" = "crate::cli::stdin" +// * with "wasi:cli/stdout@0.2.4" = "crate::cli::stdout" +// * with "wasi:cli/stderr@0.2.4" = "crate::cli::stderr" +// * with "wasi:cli/terminal-input@0.2.4" = "crate::cli::terminal_input" +// * with "wasi:cli/terminal-output@0.2.4" = "crate::cli::terminal_output" +// * with "wasi:cli/terminal-stdin@0.2.4" = "crate::cli::terminal_stdin" +// * with "wasi:cli/terminal-stdout@0.2.4" = "crate::cli::terminal_stdout" +// * with "wasi:cli/terminal-stderr@0.2.4" = "crate::cli::terminal_stderr" +// * with "wasi:clocks/monotonic-clock@0.2.4" = "crate::clocks::monotonic_clock" +// * with "wasi:clocks/wall-clock@0.2.4" = "crate::clocks::wall_clock" +// * with "wasi:filesystem/types@0.2.4" = "crate::filesystem::types" +// * with "wasi:filesystem/preopens@0.2.4" = "crate::filesystem::preopens" +// * with "wasi:io/error@0.2.4" = "crate::io::error" +// * with "wasi:io/poll@0.2.4" = "crate::io::poll" +// * with "wasi:io/streams@0.2.4" = "crate::io::streams" +// * with "wasi:random/random@0.2.4" = "crate::random::random" +// * with "wasi:random/insecure@0.2.4" = "crate::random::insecure" +// * with "wasi:random/insecure-seed@0.2.4" = "crate::random::insecure_seed" +// * with "wasi:sockets/network@0.2.4" = "crate::sockets::network" +// * with "wasi:sockets/instance-network@0.2.4" = "crate::sockets::instance_network" +// * with "wasi:sockets/tcp@0.2.4" = "crate::sockets::tcp" +// * with "wasi:sockets/tcp-create-socket@0.2.4" = "crate::sockets::tcp_create_socket" +// * with "wasi:sockets/udp@0.2.4" = "crate::sockets::udp" +// * with "wasi:sockets/udp-create-socket@0.2.4" = "crate::sockets::udp_create_socket" +// * with "wasi:sockets/ip-name-lookup@0.2.4" = "crate::sockets::ip_name_lookup" +// * type_section_suffix: "rust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-command-world" +// * default-bindings-module: "$crate" +// * export-macro-name: _export_command +// * pub-export-macro +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::environment as __with_name0; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::exit as __with_name1; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::error as __with_name2; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::poll as __with_name3; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::streams as __with_name4; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stdin as __with_name5; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stdout as __with_name6; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stderr as __with_name7; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::terminal_input as __with_name8; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::terminal_output as __with_name9; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::terminal_stdin as __with_name10; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::terminal_stdout as __with_name11; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::terminal_stderr as __with_name12; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::clocks::monotonic_clock as __with_name13; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::clocks::wall_clock as __with_name14; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::filesystem::types as __with_name15; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::filesystem::preopens as __with_name16; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::network as __with_name17; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::instance_network as __with_name18; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::udp as __with_name19; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::udp_create_socket as __with_name20; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::tcp as __with_name21; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::tcp_create_socket as __with_name22; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::sockets::ip_name_lookup as __with_name23; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::random::random as __with_name24; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::random::insecure as __with_name25; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::random::insecure_seed as __with_name26; +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] +pub mod exports { + pub mod wasi { + pub mod cli { + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod run { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[doc(hidden)] + #[allow(non_snake_case, unused_unsafe)] + pub unsafe fn _export_run_cabi() -> i32 { + unsafe { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = { T::run() }; + let result1 = match result0 { + Ok(_) => 0i32, + Err(_) => 1i32, + }; + result1 + } + } + pub trait Guest { + /// Run the program. + #[allow(async_fn_in_trait)] + fn run() -> Result<(), ()>; + } + #[doc(hidden)] + #[macro_export] + macro_rules! __export_wasi_cli_run_0_2_4_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "wasi:cli/run@0.2.4#run")] unsafe extern "C" fn export_run() -> + i32 { unsafe { $($path_to_types)*:: _export_run_cabi::<$ty > () } + } }; + }; + } + #[doc(hidden)] + pub use __export_wasi_cli_run_0_2_4_cabi; + } + } + } +} +#[rustfmt::skip] +mod _rt { + #![allow(dead_code, clippy::all)] + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen::rt::run_ctors_once(); + } +} +/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as +/// the root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! _export_command{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// _export_command!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] +#[macro_export] +macro_rules! __export_command_impl { + ($ty:ident) => { + $crate::_export_command!($ty with_types_in $crate); + }; + ($ty:ident with_types_in $($path_to_types_root:tt)*) => { + $($path_to_types_root)*:: + exports::wasi::cli::run::__export_wasi_cli_run_0_2_4_cabi!($ty with_types_in + $($path_to_types_root)*:: exports::wasi::cli::run); const _ : () = { + #[rustfmt::skip] #[cfg(target_arch = "wasm32")] #[unsafe (link_section = + "component-type:wit-bindgen:0.46.0:wasi:cli@0.2.4:command:imports and exportsrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-command-world")] + #[doc(hidden)] #[allow(clippy::octal_escapes)] pub static + __WIT_BINDGEN_COMPONENT_TYPE : [u8; 10773] = * + b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x97S\x01A\x02\x01AI\x01\ +B\x0a\x01o\x02ss\x01p\0\x01@\0\0\x01\x04\0\x0fget-environment\x01\x02\x01ps\x01@\ +\0\0\x03\x04\0\x0dget-arguments\x01\x04\x01ks\x01@\0\0\x05\x04\0\x0binitial-cwd\x01\ +\x06\x03\0\x1awasi:cli/environment@0.2.4\x05\0\x01B\x03\x01j\0\0\x01@\x01\x06sta\ +tus\0\x01\0\x04\0\x04exit\x01\x01\x03\0\x13wasi:cli/exit@0.2.4\x05\x01\x01B\x04\x04\ +\0\x05error\x03\x01\x01h\0\x01@\x01\x04self\x01\0s\x04\0\x1d[method]error.to-deb\ +ug-string\x01\x02\x03\0\x13wasi:io/error@0.2.4\x05\x02\x01B\x0a\x04\0\x08pollabl\ +e\x03\x01\x01h\0\x01@\x01\x04self\x01\0\x7f\x04\0\x16[method]pollable.ready\x01\x02\ +\x01@\x01\x04self\x01\x01\0\x04\0\x16[method]pollable.block\x01\x03\x01p\x01\x01\ +py\x01@\x01\x02in\x04\0\x05\x04\0\x04poll\x01\x06\x03\0\x12wasi:io/poll@0.2.4\x05\ +\x03\x02\x03\0\x02\x05error\x02\x03\0\x03\x08pollable\x01B(\x02\x03\x02\x01\x04\x04\ +\0\x05error\x03\0\0\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x02\x01i\x01\x01\ +q\x02\x15last-operation-failed\x01\x04\0\x06closed\0\0\x04\0\x0cstream-error\x03\ +\0\x05\x04\0\x0cinput-stream\x03\x01\x04\0\x0doutput-stream\x03\x01\x01h\x07\x01\ +p}\x01j\x01\x0a\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0b\x04\0\x19[method]inpu\ +t-stream.read\x01\x0c\x04\0\"[method]input-stream.blocking-read\x01\x0c\x01j\x01\ +w\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0d\x04\0\x19[method]input-stream.skip\x01\ +\x0e\x04\0\"[method]input-stream.blocking-skip\x01\x0e\x01i\x03\x01@\x01\x04self\ +\x09\0\x0f\x04\0\x1e[method]input-stream.subscribe\x01\x10\x01h\x08\x01@\x01\x04\ +self\x11\0\x0d\x04\0![method]output-stream.check-write\x01\x12\x01j\0\x01\x06\x01\ +@\x02\x04self\x11\x08contents\x0a\0\x13\x04\0\x1b[method]output-stream.write\x01\ +\x14\x04\0.[method]output-stream.blocking-write-and-flush\x01\x14\x01@\x01\x04se\ +lf\x11\0\x13\x04\0\x1b[method]output-stream.flush\x01\x15\x04\0$[method]output-s\ +tream.blocking-flush\x01\x15\x01@\x01\x04self\x11\0\x0f\x04\0\x1f[method]output-\ +stream.subscribe\x01\x16\x01@\x02\x04self\x11\x03lenw\0\x13\x04\0\"[method]outpu\ +t-stream.write-zeroes\x01\x17\x04\05[method]output-stream.blocking-write-zeroes-\ +and-flush\x01\x17\x01@\x03\x04self\x11\x03src\x09\x03lenw\0\x0d\x04\0\x1c[method\ +]output-stream.splice\x01\x18\x04\0%[method]output-stream.blocking-splice\x01\x18\ +\x03\0\x15wasi:io/streams@0.2.4\x05\x06\x02\x03\0\x04\x0cinput-stream\x01B\x05\x02\ +\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x09ge\ +t-stdin\x01\x03\x03\0\x14wasi:cli/stdin@0.2.4\x05\x08\x02\x03\0\x04\x0doutput-st\ +ream\x01B\x05\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\ +\0\x02\x04\0\x0aget-stdout\x01\x03\x03\0\x15wasi:cli/stdout@0.2.4\x05\x0a\x01B\x05\ +\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0a\ +get-stderr\x01\x03\x03\0\x15wasi:cli/stderr@0.2.4\x05\x0b\x01B\x01\x04\0\x0eterm\ +inal-input\x03\x01\x03\0\x1dwasi:cli/terminal-input@0.2.4\x05\x0c\x01B\x01\x04\0\ +\x0fterminal-output\x03\x01\x03\0\x1ewasi:cli/terminal-output@0.2.4\x05\x0d\x02\x03\ +\0\x08\x0eterminal-input\x01B\x06\x02\x03\x02\x01\x0e\x04\0\x0eterminal-input\x03\ +\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\x04\0\x12get-terminal-stdin\x01\x04\x03\0\x1d\ +wasi:cli/terminal-stdin@0.2.4\x05\x0f\x02\x03\0\x09\x0fterminal-output\x01B\x06\x02\ +\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\ +\x04\0\x13get-terminal-stdout\x01\x04\x03\0\x1ewasi:cli/terminal-stdout@0.2.4\x05\ +\x11\x01B\x06\x02\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\ +\x02\x01@\0\0\x03\x04\0\x13get-terminal-stderr\x01\x04\x03\0\x1ewasi:cli/termina\ +l-stderr@0.2.4\x05\x12\x01B\x0f\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x01\ +w\x04\0\x07instant\x03\0\x02\x01w\x04\0\x08duration\x03\0\x04\x01@\0\0\x03\x04\0\ +\x03now\x01\x06\x01@\0\0\x05\x04\0\x0aresolution\x01\x07\x01i\x01\x01@\x01\x04wh\ +en\x03\0\x08\x04\0\x11subscribe-instant\x01\x09\x01@\x01\x04when\x05\0\x08\x04\0\ +\x12subscribe-duration\x01\x0a\x03\0!wasi:clocks/monotonic-clock@0.2.4\x05\x13\x01\ +B\x05\x01r\x02\x07secondsw\x0bnanosecondsy\x04\0\x08datetime\x03\0\0\x01@\0\0\x01\ +\x04\0\x03now\x01\x02\x04\0\x0aresolution\x01\x02\x03\0\x1cwasi:clocks/wall-cloc\ +k@0.2.4\x05\x14\x02\x03\0\x04\x05error\x02\x03\0\x0e\x08datetime\x01Br\x02\x03\x02\ +\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\0\x0doutput-strea\ +m\x03\0\x02\x02\x03\x02\x01\x15\x04\0\x05error\x03\0\x04\x02\x03\x02\x01\x16\x04\ +\0\x08datetime\x03\0\x06\x01w\x04\0\x08filesize\x03\0\x08\x01m\x08\x07unknown\x0c\ +block-device\x10character-device\x09directory\x04fifo\x0dsymbolic-link\x0cregula\ +r-file\x06socket\x04\0\x0fdescriptor-type\x03\0\x0a\x01n\x06\x04read\x05write\x13\ +file-integrity-sync\x13data-integrity-sync\x14requested-write-sync\x10mutate-dir\ +ectory\x04\0\x10descriptor-flags\x03\0\x0c\x01n\x01\x0esymlink-follow\x04\0\x0ap\ +ath-flags\x03\0\x0e\x01n\x04\x06create\x09directory\x09exclusive\x08truncate\x04\ +\0\x0aopen-flags\x03\0\x10\x01w\x04\0\x0alink-count\x03\0\x12\x01k\x07\x01r\x06\x04\ +type\x0b\x0alink-count\x13\x04size\x09\x15data-access-timestamp\x14\x1bdata-modi\ +fication-timestamp\x14\x17status-change-timestamp\x14\x04\0\x0fdescriptor-stat\x03\ +\0\x15\x01q\x03\x09no-change\0\0\x03now\0\0\x09timestamp\x01\x07\0\x04\0\x0dnew-\ +timestamp\x03\0\x17\x01r\x02\x04type\x0b\x04names\x04\0\x0fdirectory-entry\x03\0\ +\x19\x01m%\x06access\x0bwould-block\x07already\x0ebad-descriptor\x04busy\x08dead\ +lock\x05quota\x05exist\x0efile-too-large\x15illegal-byte-sequence\x0bin-progress\ +\x0binterrupted\x07invalid\x02io\x0cis-directory\x04loop\x0etoo-many-links\x0cme\ +ssage-size\x0dname-too-long\x09no-device\x08no-entry\x07no-lock\x13insufficient-\ +memory\x12insufficient-space\x0dnot-directory\x09not-empty\x0fnot-recoverable\x0b\ +unsupported\x06no-tty\x0eno-such-device\x08overflow\x0dnot-permitted\x04pipe\x09\ +read-only\x0cinvalid-seek\x0etext-file-busy\x0ccross-device\x04\0\x0aerror-code\x03\ +\0\x1b\x01m\x06\x06normal\x0asequential\x06random\x09will-need\x09dont-need\x08n\ +o-reuse\x04\0\x06advice\x03\0\x1d\x01r\x02\x05lowerw\x05upperw\x04\0\x13metadata\ +-hash-value\x03\0\x1f\x04\0\x0adescriptor\x03\x01\x04\0\x16directory-entry-strea\ +m\x03\x01\x01h!\x01i\x01\x01j\x01$\x01\x1c\x01@\x02\x04self#\x06offset\x09\0%\x04\ +\0\"[method]descriptor.read-via-stream\x01&\x01i\x03\x01j\x01'\x01\x1c\x01@\x02\x04\ +self#\x06offset\x09\0(\x04\0#[method]descriptor.write-via-stream\x01)\x01@\x01\x04\ +self#\0(\x04\0$[method]descriptor.append-via-stream\x01*\x01j\0\x01\x1c\x01@\x04\ +\x04self#\x06offset\x09\x06length\x09\x06advice\x1e\0+\x04\0\x19[method]descript\ +or.advise\x01,\x01@\x01\x04self#\0+\x04\0\x1c[method]descriptor.sync-data\x01-\x01\ +j\x01\x0d\x01\x1c\x01@\x01\x04self#\0.\x04\0\x1c[method]descriptor.get-flags\x01\ +/\x01j\x01\x0b\x01\x1c\x01@\x01\x04self#\00\x04\0\x1b[method]descriptor.get-type\ +\x011\x01@\x02\x04self#\x04size\x09\0+\x04\0\x1b[method]descriptor.set-size\x012\ +\x01@\x03\x04self#\x15data-access-timestamp\x18\x1bdata-modification-timestamp\x18\ +\0+\x04\0\x1c[method]descriptor.set-times\x013\x01p}\x01o\x024\x7f\x01j\x015\x01\ +\x1c\x01@\x03\x04self#\x06length\x09\x06offset\x09\06\x04\0\x17[method]descripto\ +r.read\x017\x01j\x01\x09\x01\x1c\x01@\x03\x04self#\x06buffer4\x06offset\x09\08\x04\ +\0\x18[method]descriptor.write\x019\x01i\"\x01j\x01:\x01\x1c\x01@\x01\x04self#\0\ +;\x04\0![method]descriptor.read-directory\x01<\x04\0\x17[method]descriptor.sync\x01\ +-\x01@\x02\x04self#\x04paths\0+\x04\0&[method]descriptor.create-directory-at\x01\ +=\x01j\x01\x16\x01\x1c\x01@\x01\x04self#\0>\x04\0\x17[method]descriptor.stat\x01\ +?\x01@\x03\x04self#\x0apath-flags\x0f\x04paths\0>\x04\0\x1a[method]descriptor.st\ +at-at\x01@\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x15data-access-timestamp\ +\x18\x1bdata-modification-timestamp\x18\0+\x04\0\x1f[method]descriptor.set-times\ +-at\x01A\x01@\x05\x04self#\x0eold-path-flags\x0f\x08old-paths\x0enew-descriptor#\ +\x08new-paths\0+\x04\0\x1a[method]descriptor.link-at\x01B\x01i!\x01j\x01\xc3\0\x01\ +\x1c\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x0aopen-flags\x11\x05flags\x0d\ +\0\xc4\0\x04\0\x1a[method]descriptor.open-at\x01E\x01j\x01s\x01\x1c\x01@\x02\x04\ +self#\x04paths\0\xc6\0\x04\0\x1e[method]descriptor.readlink-at\x01G\x04\0&[metho\ +d]descriptor.remove-directory-at\x01=\x01@\x04\x04self#\x08old-paths\x0enew-desc\ +riptor#\x08new-paths\0+\x04\0\x1c[method]descriptor.rename-at\x01H\x01@\x03\x04s\ +elf#\x08old-paths\x08new-paths\0+\x04\0\x1d[method]descriptor.symlink-at\x01I\x04\ +\0![method]descriptor.unlink-file-at\x01=\x01@\x02\x04self#\x05other#\0\x7f\x04\0\ +![method]descriptor.is-same-object\x01J\x01j\x01\x20\x01\x1c\x01@\x01\x04self#\0\ +\xcb\0\x04\0\x20[method]descriptor.metadata-hash\x01L\x01@\x03\x04self#\x0apath-\ +flags\x0f\x04paths\0\xcb\0\x04\0#[method]descriptor.metadata-hash-at\x01M\x01h\"\ +\x01k\x1a\x01j\x01\xcf\0\x01\x1c\x01@\x01\x04self\xce\0\0\xd0\0\x04\03[method]di\ +rectory-entry-stream.read-directory-entry\x01Q\x01h\x05\x01k\x1c\x01@\x01\x03err\ +\xd2\0\0\xd3\0\x04\0\x15filesystem-error-code\x01T\x03\0\x1bwasi:filesystem/type\ +s@0.2.4\x05\x17\x02\x03\0\x0f\x0adescriptor\x01B\x07\x02\x03\x02\x01\x18\x04\0\x0a\ +descriptor\x03\0\0\x01i\x01\x01o\x02\x02s\x01p\x03\x01@\0\0\x04\x04\0\x0fget-dir\ +ectories\x01\x05\x03\0\x1ewasi:filesystem/preopens@0.2.4\x05\x19\x01B\x11\x04\0\x07\ +network\x03\x01\x01m\x15\x07unknown\x0daccess-denied\x0dnot-supported\x10invalid\ +-argument\x0dout-of-memory\x07timeout\x14concurrency-conflict\x0fnot-in-progress\ +\x0bwould-block\x0dinvalid-state\x10new-socket-limit\x14address-not-bindable\x0e\ +address-in-use\x12remote-unreachable\x12connection-refused\x10connection-reset\x12\ +connection-aborted\x12datagram-too-large\x11name-unresolvable\x1atemporary-resol\ +ver-failure\x1apermanent-resolver-failure\x04\0\x0aerror-code\x03\0\x01\x01m\x02\ +\x04ipv4\x04ipv6\x04\0\x11ip-address-family\x03\0\x03\x01o\x04}}}}\x04\0\x0cipv4\ +-address\x03\0\x05\x01o\x08{{{{{{{{\x04\0\x0cipv6-address\x03\0\x07\x01q\x02\x04\ +ipv4\x01\x06\0\x04ipv6\x01\x08\0\x04\0\x0aip-address\x03\0\x09\x01r\x02\x04port{\ +\x07address\x06\x04\0\x13ipv4-socket-address\x03\0\x0b\x01r\x04\x04port{\x09flow\ +-infoy\x07address\x08\x08scope-idy\x04\0\x13ipv6-socket-address\x03\0\x0d\x01q\x02\ +\x04ipv4\x01\x0c\0\x04ipv6\x01\x0e\0\x04\0\x11ip-socket-address\x03\0\x0f\x03\0\x1a\ +wasi:sockets/network@0.2.4\x05\x1a\x02\x03\0\x11\x07network\x01B\x05\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x10instance-networ\ +k\x01\x03\x03\0#wasi:sockets/instance-network@0.2.4\x05\x1c\x02\x03\0\x11\x0aerr\ +or-code\x02\x03\0\x11\x11ip-socket-address\x02\x03\0\x11\x11ip-address-family\x01\ +BD\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\x01\x1b\x04\0\x07ne\ +twork\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x04\x02\x03\x02\x01\ +\x1e\x04\0\x11ip-socket-address\x03\0\x06\x02\x03\x02\x01\x1f\x04\0\x11ip-addres\ +s-family\x03\0\x08\x01p}\x01r\x02\x04data\x0a\x0eremote-address\x07\x04\0\x11inc\ +oming-datagram\x03\0\x0b\x01k\x07\x01r\x02\x04data\x0a\x0eremote-address\x0d\x04\ +\0\x11outgoing-datagram\x03\0\x0e\x04\0\x0audp-socket\x03\x01\x04\0\x18incoming-\ +datagram-stream\x03\x01\x04\0\x18outgoing-datagram-stream\x03\x01\x01h\x10\x01h\x03\ +\x01j\0\x01\x05\x01@\x03\x04self\x13\x07network\x14\x0dlocal-address\x07\0\x15\x04\ +\0\x1d[method]udp-socket.start-bind\x01\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e\ +[method]udp-socket.finish-bind\x01\x17\x01i\x11\x01i\x12\x01o\x02\x18\x19\x01j\x01\ +\x1a\x01\x05\x01@\x02\x04self\x13\x0eremote-address\x0d\0\x1b\x04\0\x19[method]u\ +dp-socket.stream\x01\x1c\x01j\x01\x07\x01\x05\x01@\x01\x04self\x13\0\x1d\x04\0\x20\ +[method]udp-socket.local-address\x01\x1e\x04\0![method]udp-socket.remote-address\ +\x01\x1e\x01@\x01\x04self\x13\0\x09\x04\0![method]udp-socket.address-family\x01\x1f\ +\x01j\x01}\x01\x05\x01@\x01\x04self\x13\0\x20\x04\0$[method]udp-socket.unicast-h\ +op-limit\x01!\x01@\x02\x04self\x13\x05value}\0\x15\x04\0([method]udp-socket.set-\ +unicast-hop-limit\x01\"\x01j\x01w\x01\x05\x01@\x01\x04self\x13\0#\x04\0&[method]\ +udp-socket.receive-buffer-size\x01$\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[\ +method]udp-socket.set-receive-buffer-size\x01%\x04\0#[method]udp-socket.send-buf\ +fer-size\x01$\x04\0'[method]udp-socket.set-send-buffer-size\x01%\x01i\x01\x01@\x01\ +\x04self\x13\0&\x04\0\x1c[method]udp-socket.subscribe\x01'\x01h\x11\x01p\x0c\x01\ +j\x01)\x01\x05\x01@\x02\x04self(\x0bmax-resultsw\0*\x04\0([method]incoming-datag\ +ram-stream.receive\x01+\x01@\x01\x04self(\0&\x04\0*[method]incoming-datagram-str\ +eam.subscribe\x01,\x01h\x12\x01@\x01\x04self-\0#\x04\0+[method]outgoing-datagram\ +-stream.check-send\x01.\x01p\x0f\x01@\x02\x04self-\x09datagrams/\0#\x04\0%[metho\ +d]outgoing-datagram-stream.send\x010\x01@\x01\x04self-\0&\x04\0*[method]outgoing\ +-datagram-stream.subscribe\x011\x03\0\x16wasi:sockets/udp@0.2.4\x05\x20\x02\x03\0\ +\x13\x0audp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\0\0\x02\x03\ +\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\x11ip-addre\ +ss-family\x03\0\x04\x02\x03\x02\x01!\x04\0\x0audp-socket\x03\0\x06\x01i\x07\x01j\ +\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-udp-socket\ +\x01\x0a\x03\0$wasi:sockets/udp-create-socket@0.2.4\x05\"\x02\x03\0\x0d\x08durat\ +ion\x01BT\x02\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\ +\0\x0doutput-stream\x03\0\x02\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x04\x02\ +\x03\x02\x01#\x04\0\x08duration\x03\0\x06\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\x08\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x0a\x02\x03\x02\x01\x1e\x04\ +\0\x11ip-socket-address\x03\0\x0c\x02\x03\x02\x01\x1f\x04\0\x11ip-address-family\ +\x03\0\x0e\x01m\x03\x07receive\x04send\x04both\x04\0\x0dshutdown-type\x03\0\x10\x04\ +\0\x0atcp-socket\x03\x01\x01h\x12\x01h\x09\x01j\0\x01\x0b\x01@\x03\x04self\x13\x07\ +network\x14\x0dlocal-address\x0d\0\x15\x04\0\x1d[method]tcp-socket.start-bind\x01\ +\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e[method]tcp-socket.finish-bind\x01\x17\x01\ +@\x03\x04self\x13\x07network\x14\x0eremote-address\x0d\0\x15\x04\0\x20[method]tc\ +p-socket.start-connect\x01\x18\x01i\x01\x01i\x03\x01o\x02\x19\x1a\x01j\x01\x1b\x01\ +\x0b\x01@\x01\x04self\x13\0\x1c\x04\0![method]tcp-socket.finish-connect\x01\x1d\x04\ +\0\x1f[method]tcp-socket.start-listen\x01\x17\x04\0\x20[method]tcp-socket.finish\ +-listen\x01\x17\x01i\x12\x01o\x03\x1e\x19\x1a\x01j\x01\x1f\x01\x0b\x01@\x01\x04s\ +elf\x13\0\x20\x04\0\x19[method]tcp-socket.accept\x01!\x01j\x01\x0d\x01\x0b\x01@\x01\ +\x04self\x13\0\"\x04\0\x20[method]tcp-socket.local-address\x01#\x04\0![method]tc\ +p-socket.remote-address\x01#\x01@\x01\x04self\x13\0\x7f\x04\0\x1f[method]tcp-soc\ +ket.is-listening\x01$\x01@\x01\x04self\x13\0\x0f\x04\0![method]tcp-socket.addres\ +s-family\x01%\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[method]tcp-socket.set-\ +listen-backlog-size\x01&\x01j\x01\x7f\x01\x0b\x01@\x01\x04self\x13\0'\x04\0%[met\ +hod]tcp-socket.keep-alive-enabled\x01(\x01@\x02\x04self\x13\x05value\x7f\0\x15\x04\ +\0)[method]tcp-socket.set-keep-alive-enabled\x01)\x01j\x01\x07\x01\x0b\x01@\x01\x04\ +self\x13\0*\x04\0'[method]tcp-socket.keep-alive-idle-time\x01+\x01@\x02\x04self\x13\ +\x05value\x07\0\x15\x04\0+[method]tcp-socket.set-keep-alive-idle-time\x01,\x04\0\ +&[method]tcp-socket.keep-alive-interval\x01+\x04\0*[method]tcp-socket.set-keep-a\ +live-interval\x01,\x01j\x01y\x01\x0b\x01@\x01\x04self\x13\0-\x04\0#[method]tcp-s\ +ocket.keep-alive-count\x01.\x01@\x02\x04self\x13\x05valuey\0\x15\x04\0'[method]t\ +cp-socket.set-keep-alive-count\x01/\x01j\x01}\x01\x0b\x01@\x01\x04self\x13\00\x04\ +\0\x1c[method]tcp-socket.hop-limit\x011\x01@\x02\x04self\x13\x05value}\0\x15\x04\ +\0\x20[method]tcp-socket.set-hop-limit\x012\x01j\x01w\x01\x0b\x01@\x01\x04self\x13\ +\03\x04\0&[method]tcp-socket.receive-buffer-size\x014\x04\0*[method]tcp-socket.s\ +et-receive-buffer-size\x01&\x04\0#[method]tcp-socket.send-buffer-size\x014\x04\0\ +'[method]tcp-socket.set-send-buffer-size\x01&\x01i\x05\x01@\x01\x04self\x13\05\x04\ +\0\x1c[method]tcp-socket.subscribe\x016\x01@\x02\x04self\x13\x0dshutdown-type\x11\ +\0\x15\x04\0\x1b[method]tcp-socket.shutdown\x017\x03\0\x16wasi:sockets/tcp@0.2.4\ +\x05$\x02\x03\0\x15\x0atcp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\0\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\ +\x11ip-address-family\x03\0\x04\x02\x03\x02\x01%\x04\0\x0atcp-socket\x03\0\x06\x01\ +i\x07\x01j\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-\ +tcp-socket\x01\x0a\x03\0$wasi:sockets/tcp-create-socket@0.2.4\x05&\x02\x03\0\x11\ +\x0aip-address\x01B\x16\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\ +\x04\x02\x03\x02\x01'\x04\0\x0aip-address\x03\0\x06\x04\0\x16resolve-address-str\ +eam\x03\x01\x01h\x08\x01k\x07\x01j\x01\x0a\x01\x05\x01@\x01\x04self\x09\0\x0b\x04\ +\03[method]resolve-address-stream.resolve-next-address\x01\x0c\x01i\x01\x01@\x01\ +\x04self\x09\0\x0d\x04\0([method]resolve-address-stream.subscribe\x01\x0e\x01h\x03\ +\x01i\x08\x01j\x01\x10\x01\x05\x01@\x02\x07network\x0f\x04names\0\x11\x04\0\x11r\ +esolve-addresses\x01\x12\x03\0!wasi:sockets/ip-name-lookup@0.2.4\x05(\x01B\x05\x01\ +p}\x01@\x01\x03lenw\0\0\x04\0\x10get-random-bytes\x01\x01\x01@\0\0w\x04\0\x0eget\ +-random-u64\x01\x02\x03\0\x18wasi:random/random@0.2.4\x05)\x01B\x05\x01p}\x01@\x01\ +\x03lenw\0\0\x04\0\x19get-insecure-random-bytes\x01\x01\x01@\0\0w\x04\0\x17get-i\ +nsecure-random-u64\x01\x02\x03\0\x1awasi:random/insecure@0.2.4\x05*\x01B\x03\x01\ +o\x02ww\x01@\0\0\0\x04\0\x0dinsecure-seed\x01\x01\x03\0\x1fwasi:random/insecure-\ +seed@0.2.4\x05+\x01B\x03\x01j\0\0\x01@\0\0\0\x04\0\x03run\x01\x01\x04\0\x12wasi:\ +cli/run@0.2.4\x05,\x04\0\x16wasi:cli/command@0.2.4\x04\0\x0b\x0d\x01\0\x07comman\ +d\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.239.0\x10\ +wit-bindgen-rust\x060.46.0"; + }; + }; +} +#[doc(inline)] +pub use __export_command_impl as _export_command; +#[rustfmt::skip] +#[cfg(target_arch = "wasm32")] + +#[cfg_attr(feature = "rustc-dep-of-std", unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:cli@0.2.4:command-with-all-of-its-exports-removed:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-command-world-in-libstd"))] +#[cfg_attr(not(feature = "rustc-dep-of-std"), unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:cli@0.2.4:command-with-all-of-its-exports-removed:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-command-world"))] + +#[doc(hidden)] +#[allow(clippy::octal_escapes)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 10794] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x8cS\x01A\x02\x01AG\x01\ +B\x0a\x01o\x02ss\x01p\0\x01@\0\0\x01\x04\0\x0fget-environment\x01\x02\x01ps\x01@\ +\0\0\x03\x04\0\x0dget-arguments\x01\x04\x01ks\x01@\0\0\x05\x04\0\x0binitial-cwd\x01\ +\x06\x03\0\x1awasi:cli/environment@0.2.4\x05\0\x01B\x03\x01j\0\0\x01@\x01\x06sta\ +tus\0\x01\0\x04\0\x04exit\x01\x01\x03\0\x13wasi:cli/exit@0.2.4\x05\x01\x01B\x04\x04\ +\0\x05error\x03\x01\x01h\0\x01@\x01\x04self\x01\0s\x04\0\x1d[method]error.to-deb\ +ug-string\x01\x02\x03\0\x13wasi:io/error@0.2.4\x05\x02\x01B\x0a\x04\0\x08pollabl\ +e\x03\x01\x01h\0\x01@\x01\x04self\x01\0\x7f\x04\0\x16[method]pollable.ready\x01\x02\ +\x01@\x01\x04self\x01\x01\0\x04\0\x16[method]pollable.block\x01\x03\x01p\x01\x01\ +py\x01@\x01\x02in\x04\0\x05\x04\0\x04poll\x01\x06\x03\0\x12wasi:io/poll@0.2.4\x05\ +\x03\x02\x03\0\x02\x05error\x02\x03\0\x03\x08pollable\x01B(\x02\x03\x02\x01\x04\x04\ +\0\x05error\x03\0\0\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x02\x01i\x01\x01\ +q\x02\x15last-operation-failed\x01\x04\0\x06closed\0\0\x04\0\x0cstream-error\x03\ +\0\x05\x04\0\x0cinput-stream\x03\x01\x04\0\x0doutput-stream\x03\x01\x01h\x07\x01\ +p}\x01j\x01\x0a\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0b\x04\0\x19[method]inpu\ +t-stream.read\x01\x0c\x04\0\"[method]input-stream.blocking-read\x01\x0c\x01j\x01\ +w\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0d\x04\0\x19[method]input-stream.skip\x01\ +\x0e\x04\0\"[method]input-stream.blocking-skip\x01\x0e\x01i\x03\x01@\x01\x04self\ +\x09\0\x0f\x04\0\x1e[method]input-stream.subscribe\x01\x10\x01h\x08\x01@\x01\x04\ +self\x11\0\x0d\x04\0![method]output-stream.check-write\x01\x12\x01j\0\x01\x06\x01\ +@\x02\x04self\x11\x08contents\x0a\0\x13\x04\0\x1b[method]output-stream.write\x01\ +\x14\x04\0.[method]output-stream.blocking-write-and-flush\x01\x14\x01@\x01\x04se\ +lf\x11\0\x13\x04\0\x1b[method]output-stream.flush\x01\x15\x04\0$[method]output-s\ +tream.blocking-flush\x01\x15\x01@\x01\x04self\x11\0\x0f\x04\0\x1f[method]output-\ +stream.subscribe\x01\x16\x01@\x02\x04self\x11\x03lenw\0\x13\x04\0\"[method]outpu\ +t-stream.write-zeroes\x01\x17\x04\05[method]output-stream.blocking-write-zeroes-\ +and-flush\x01\x17\x01@\x03\x04self\x11\x03src\x09\x03lenw\0\x0d\x04\0\x1c[method\ +]output-stream.splice\x01\x18\x04\0%[method]output-stream.blocking-splice\x01\x18\ +\x03\0\x15wasi:io/streams@0.2.4\x05\x06\x02\x03\0\x04\x0cinput-stream\x01B\x05\x02\ +\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x09ge\ +t-stdin\x01\x03\x03\0\x14wasi:cli/stdin@0.2.4\x05\x08\x02\x03\0\x04\x0doutput-st\ +ream\x01B\x05\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\ +\0\x02\x04\0\x0aget-stdout\x01\x03\x03\0\x15wasi:cli/stdout@0.2.4\x05\x0a\x01B\x05\ +\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0a\ +get-stderr\x01\x03\x03\0\x15wasi:cli/stderr@0.2.4\x05\x0b\x01B\x01\x04\0\x0eterm\ +inal-input\x03\x01\x03\0\x1dwasi:cli/terminal-input@0.2.4\x05\x0c\x01B\x01\x04\0\ +\x0fterminal-output\x03\x01\x03\0\x1ewasi:cli/terminal-output@0.2.4\x05\x0d\x02\x03\ +\0\x08\x0eterminal-input\x01B\x06\x02\x03\x02\x01\x0e\x04\0\x0eterminal-input\x03\ +\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\x04\0\x12get-terminal-stdin\x01\x04\x03\0\x1d\ +wasi:cli/terminal-stdin@0.2.4\x05\x0f\x02\x03\0\x09\x0fterminal-output\x01B\x06\x02\ +\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\ +\x04\0\x13get-terminal-stdout\x01\x04\x03\0\x1ewasi:cli/terminal-stdout@0.2.4\x05\ +\x11\x01B\x06\x02\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\ +\x02\x01@\0\0\x03\x04\0\x13get-terminal-stderr\x01\x04\x03\0\x1ewasi:cli/termina\ +l-stderr@0.2.4\x05\x12\x01B\x0f\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x01\ +w\x04\0\x07instant\x03\0\x02\x01w\x04\0\x08duration\x03\0\x04\x01@\0\0\x03\x04\0\ +\x03now\x01\x06\x01@\0\0\x05\x04\0\x0aresolution\x01\x07\x01i\x01\x01@\x01\x04wh\ +en\x03\0\x08\x04\0\x11subscribe-instant\x01\x09\x01@\x01\x04when\x05\0\x08\x04\0\ +\x12subscribe-duration\x01\x0a\x03\0!wasi:clocks/monotonic-clock@0.2.4\x05\x13\x01\ +B\x05\x01r\x02\x07secondsw\x0bnanosecondsy\x04\0\x08datetime\x03\0\0\x01@\0\0\x01\ +\x04\0\x03now\x01\x02\x04\0\x0aresolution\x01\x02\x03\0\x1cwasi:clocks/wall-cloc\ +k@0.2.4\x05\x14\x02\x03\0\x04\x05error\x02\x03\0\x0e\x08datetime\x01Br\x02\x03\x02\ +\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\0\x0doutput-strea\ +m\x03\0\x02\x02\x03\x02\x01\x15\x04\0\x05error\x03\0\x04\x02\x03\x02\x01\x16\x04\ +\0\x08datetime\x03\0\x06\x01w\x04\0\x08filesize\x03\0\x08\x01m\x08\x07unknown\x0c\ +block-device\x10character-device\x09directory\x04fifo\x0dsymbolic-link\x0cregula\ +r-file\x06socket\x04\0\x0fdescriptor-type\x03\0\x0a\x01n\x06\x04read\x05write\x13\ +file-integrity-sync\x13data-integrity-sync\x14requested-write-sync\x10mutate-dir\ +ectory\x04\0\x10descriptor-flags\x03\0\x0c\x01n\x01\x0esymlink-follow\x04\0\x0ap\ +ath-flags\x03\0\x0e\x01n\x04\x06create\x09directory\x09exclusive\x08truncate\x04\ +\0\x0aopen-flags\x03\0\x10\x01w\x04\0\x0alink-count\x03\0\x12\x01k\x07\x01r\x06\x04\ +type\x0b\x0alink-count\x13\x04size\x09\x15data-access-timestamp\x14\x1bdata-modi\ +fication-timestamp\x14\x17status-change-timestamp\x14\x04\0\x0fdescriptor-stat\x03\ +\0\x15\x01q\x03\x09no-change\0\0\x03now\0\0\x09timestamp\x01\x07\0\x04\0\x0dnew-\ +timestamp\x03\0\x17\x01r\x02\x04type\x0b\x04names\x04\0\x0fdirectory-entry\x03\0\ +\x19\x01m%\x06access\x0bwould-block\x07already\x0ebad-descriptor\x04busy\x08dead\ +lock\x05quota\x05exist\x0efile-too-large\x15illegal-byte-sequence\x0bin-progress\ +\x0binterrupted\x07invalid\x02io\x0cis-directory\x04loop\x0etoo-many-links\x0cme\ +ssage-size\x0dname-too-long\x09no-device\x08no-entry\x07no-lock\x13insufficient-\ +memory\x12insufficient-space\x0dnot-directory\x09not-empty\x0fnot-recoverable\x0b\ +unsupported\x06no-tty\x0eno-such-device\x08overflow\x0dnot-permitted\x04pipe\x09\ +read-only\x0cinvalid-seek\x0etext-file-busy\x0ccross-device\x04\0\x0aerror-code\x03\ +\0\x1b\x01m\x06\x06normal\x0asequential\x06random\x09will-need\x09dont-need\x08n\ +o-reuse\x04\0\x06advice\x03\0\x1d\x01r\x02\x05lowerw\x05upperw\x04\0\x13metadata\ +-hash-value\x03\0\x1f\x04\0\x0adescriptor\x03\x01\x04\0\x16directory-entry-strea\ +m\x03\x01\x01h!\x01i\x01\x01j\x01$\x01\x1c\x01@\x02\x04self#\x06offset\x09\0%\x04\ +\0\"[method]descriptor.read-via-stream\x01&\x01i\x03\x01j\x01'\x01\x1c\x01@\x02\x04\ +self#\x06offset\x09\0(\x04\0#[method]descriptor.write-via-stream\x01)\x01@\x01\x04\ +self#\0(\x04\0$[method]descriptor.append-via-stream\x01*\x01j\0\x01\x1c\x01@\x04\ +\x04self#\x06offset\x09\x06length\x09\x06advice\x1e\0+\x04\0\x19[method]descript\ +or.advise\x01,\x01@\x01\x04self#\0+\x04\0\x1c[method]descriptor.sync-data\x01-\x01\ +j\x01\x0d\x01\x1c\x01@\x01\x04self#\0.\x04\0\x1c[method]descriptor.get-flags\x01\ +/\x01j\x01\x0b\x01\x1c\x01@\x01\x04self#\00\x04\0\x1b[method]descriptor.get-type\ +\x011\x01@\x02\x04self#\x04size\x09\0+\x04\0\x1b[method]descriptor.set-size\x012\ +\x01@\x03\x04self#\x15data-access-timestamp\x18\x1bdata-modification-timestamp\x18\ +\0+\x04\0\x1c[method]descriptor.set-times\x013\x01p}\x01o\x024\x7f\x01j\x015\x01\ +\x1c\x01@\x03\x04self#\x06length\x09\x06offset\x09\06\x04\0\x17[method]descripto\ +r.read\x017\x01j\x01\x09\x01\x1c\x01@\x03\x04self#\x06buffer4\x06offset\x09\08\x04\ +\0\x18[method]descriptor.write\x019\x01i\"\x01j\x01:\x01\x1c\x01@\x01\x04self#\0\ +;\x04\0![method]descriptor.read-directory\x01<\x04\0\x17[method]descriptor.sync\x01\ +-\x01@\x02\x04self#\x04paths\0+\x04\0&[method]descriptor.create-directory-at\x01\ +=\x01j\x01\x16\x01\x1c\x01@\x01\x04self#\0>\x04\0\x17[method]descriptor.stat\x01\ +?\x01@\x03\x04self#\x0apath-flags\x0f\x04paths\0>\x04\0\x1a[method]descriptor.st\ +at-at\x01@\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x15data-access-timestamp\ +\x18\x1bdata-modification-timestamp\x18\0+\x04\0\x1f[method]descriptor.set-times\ +-at\x01A\x01@\x05\x04self#\x0eold-path-flags\x0f\x08old-paths\x0enew-descriptor#\ +\x08new-paths\0+\x04\0\x1a[method]descriptor.link-at\x01B\x01i!\x01j\x01\xc3\0\x01\ +\x1c\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x0aopen-flags\x11\x05flags\x0d\ +\0\xc4\0\x04\0\x1a[method]descriptor.open-at\x01E\x01j\x01s\x01\x1c\x01@\x02\x04\ +self#\x04paths\0\xc6\0\x04\0\x1e[method]descriptor.readlink-at\x01G\x04\0&[metho\ +d]descriptor.remove-directory-at\x01=\x01@\x04\x04self#\x08old-paths\x0enew-desc\ +riptor#\x08new-paths\0+\x04\0\x1c[method]descriptor.rename-at\x01H\x01@\x03\x04s\ +elf#\x08old-paths\x08new-paths\0+\x04\0\x1d[method]descriptor.symlink-at\x01I\x04\ +\0![method]descriptor.unlink-file-at\x01=\x01@\x02\x04self#\x05other#\0\x7f\x04\0\ +![method]descriptor.is-same-object\x01J\x01j\x01\x20\x01\x1c\x01@\x01\x04self#\0\ +\xcb\0\x04\0\x20[method]descriptor.metadata-hash\x01L\x01@\x03\x04self#\x0apath-\ +flags\x0f\x04paths\0\xcb\0\x04\0#[method]descriptor.metadata-hash-at\x01M\x01h\"\ +\x01k\x1a\x01j\x01\xcf\0\x01\x1c\x01@\x01\x04self\xce\0\0\xd0\0\x04\03[method]di\ +rectory-entry-stream.read-directory-entry\x01Q\x01h\x05\x01k\x1c\x01@\x01\x03err\ +\xd2\0\0\xd3\0\x04\0\x15filesystem-error-code\x01T\x03\0\x1bwasi:filesystem/type\ +s@0.2.4\x05\x17\x02\x03\0\x0f\x0adescriptor\x01B\x07\x02\x03\x02\x01\x18\x04\0\x0a\ +descriptor\x03\0\0\x01i\x01\x01o\x02\x02s\x01p\x03\x01@\0\0\x04\x04\0\x0fget-dir\ +ectories\x01\x05\x03\0\x1ewasi:filesystem/preopens@0.2.4\x05\x19\x01B\x11\x04\0\x07\ +network\x03\x01\x01m\x15\x07unknown\x0daccess-denied\x0dnot-supported\x10invalid\ +-argument\x0dout-of-memory\x07timeout\x14concurrency-conflict\x0fnot-in-progress\ +\x0bwould-block\x0dinvalid-state\x10new-socket-limit\x14address-not-bindable\x0e\ +address-in-use\x12remote-unreachable\x12connection-refused\x10connection-reset\x12\ +connection-aborted\x12datagram-too-large\x11name-unresolvable\x1atemporary-resol\ +ver-failure\x1apermanent-resolver-failure\x04\0\x0aerror-code\x03\0\x01\x01m\x02\ +\x04ipv4\x04ipv6\x04\0\x11ip-address-family\x03\0\x03\x01o\x04}}}}\x04\0\x0cipv4\ +-address\x03\0\x05\x01o\x08{{{{{{{{\x04\0\x0cipv6-address\x03\0\x07\x01q\x02\x04\ +ipv4\x01\x06\0\x04ipv6\x01\x08\0\x04\0\x0aip-address\x03\0\x09\x01r\x02\x04port{\ +\x07address\x06\x04\0\x13ipv4-socket-address\x03\0\x0b\x01r\x04\x04port{\x09flow\ +-infoy\x07address\x08\x08scope-idy\x04\0\x13ipv6-socket-address\x03\0\x0d\x01q\x02\ +\x04ipv4\x01\x0c\0\x04ipv6\x01\x0e\0\x04\0\x11ip-socket-address\x03\0\x0f\x03\0\x1a\ +wasi:sockets/network@0.2.4\x05\x1a\x02\x03\0\x11\x07network\x01B\x05\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x10instance-networ\ +k\x01\x03\x03\0#wasi:sockets/instance-network@0.2.4\x05\x1c\x02\x03\0\x11\x0aerr\ +or-code\x02\x03\0\x11\x11ip-socket-address\x02\x03\0\x11\x11ip-address-family\x01\ +BD\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\x01\x1b\x04\0\x07ne\ +twork\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x04\x02\x03\x02\x01\ +\x1e\x04\0\x11ip-socket-address\x03\0\x06\x02\x03\x02\x01\x1f\x04\0\x11ip-addres\ +s-family\x03\0\x08\x01p}\x01r\x02\x04data\x0a\x0eremote-address\x07\x04\0\x11inc\ +oming-datagram\x03\0\x0b\x01k\x07\x01r\x02\x04data\x0a\x0eremote-address\x0d\x04\ +\0\x11outgoing-datagram\x03\0\x0e\x04\0\x0audp-socket\x03\x01\x04\0\x18incoming-\ +datagram-stream\x03\x01\x04\0\x18outgoing-datagram-stream\x03\x01\x01h\x10\x01h\x03\ +\x01j\0\x01\x05\x01@\x03\x04self\x13\x07network\x14\x0dlocal-address\x07\0\x15\x04\ +\0\x1d[method]udp-socket.start-bind\x01\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e\ +[method]udp-socket.finish-bind\x01\x17\x01i\x11\x01i\x12\x01o\x02\x18\x19\x01j\x01\ +\x1a\x01\x05\x01@\x02\x04self\x13\x0eremote-address\x0d\0\x1b\x04\0\x19[method]u\ +dp-socket.stream\x01\x1c\x01j\x01\x07\x01\x05\x01@\x01\x04self\x13\0\x1d\x04\0\x20\ +[method]udp-socket.local-address\x01\x1e\x04\0![method]udp-socket.remote-address\ +\x01\x1e\x01@\x01\x04self\x13\0\x09\x04\0![method]udp-socket.address-family\x01\x1f\ +\x01j\x01}\x01\x05\x01@\x01\x04self\x13\0\x20\x04\0$[method]udp-socket.unicast-h\ +op-limit\x01!\x01@\x02\x04self\x13\x05value}\0\x15\x04\0([method]udp-socket.set-\ +unicast-hop-limit\x01\"\x01j\x01w\x01\x05\x01@\x01\x04self\x13\0#\x04\0&[method]\ +udp-socket.receive-buffer-size\x01$\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[\ +method]udp-socket.set-receive-buffer-size\x01%\x04\0#[method]udp-socket.send-buf\ +fer-size\x01$\x04\0'[method]udp-socket.set-send-buffer-size\x01%\x01i\x01\x01@\x01\ +\x04self\x13\0&\x04\0\x1c[method]udp-socket.subscribe\x01'\x01h\x11\x01p\x0c\x01\ +j\x01)\x01\x05\x01@\x02\x04self(\x0bmax-resultsw\0*\x04\0([method]incoming-datag\ +ram-stream.receive\x01+\x01@\x01\x04self(\0&\x04\0*[method]incoming-datagram-str\ +eam.subscribe\x01,\x01h\x12\x01@\x01\x04self-\0#\x04\0+[method]outgoing-datagram\ +-stream.check-send\x01.\x01p\x0f\x01@\x02\x04self-\x09datagrams/\0#\x04\0%[metho\ +d]outgoing-datagram-stream.send\x010\x01@\x01\x04self-\0&\x04\0*[method]outgoing\ +-datagram-stream.subscribe\x011\x03\0\x16wasi:sockets/udp@0.2.4\x05\x20\x02\x03\0\ +\x13\x0audp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\0\0\x02\x03\ +\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\x11ip-addre\ +ss-family\x03\0\x04\x02\x03\x02\x01!\x04\0\x0audp-socket\x03\0\x06\x01i\x07\x01j\ +\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-udp-socket\ +\x01\x0a\x03\0$wasi:sockets/udp-create-socket@0.2.4\x05\"\x02\x03\0\x0d\x08durat\ +ion\x01BT\x02\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\ +\0\x0doutput-stream\x03\0\x02\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x04\x02\ +\x03\x02\x01#\x04\0\x08duration\x03\0\x06\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\x08\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x0a\x02\x03\x02\x01\x1e\x04\ +\0\x11ip-socket-address\x03\0\x0c\x02\x03\x02\x01\x1f\x04\0\x11ip-address-family\ +\x03\0\x0e\x01m\x03\x07receive\x04send\x04both\x04\0\x0dshutdown-type\x03\0\x10\x04\ +\0\x0atcp-socket\x03\x01\x01h\x12\x01h\x09\x01j\0\x01\x0b\x01@\x03\x04self\x13\x07\ +network\x14\x0dlocal-address\x0d\0\x15\x04\0\x1d[method]tcp-socket.start-bind\x01\ +\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e[method]tcp-socket.finish-bind\x01\x17\x01\ +@\x03\x04self\x13\x07network\x14\x0eremote-address\x0d\0\x15\x04\0\x20[method]tc\ +p-socket.start-connect\x01\x18\x01i\x01\x01i\x03\x01o\x02\x19\x1a\x01j\x01\x1b\x01\ +\x0b\x01@\x01\x04self\x13\0\x1c\x04\0![method]tcp-socket.finish-connect\x01\x1d\x04\ +\0\x1f[method]tcp-socket.start-listen\x01\x17\x04\0\x20[method]tcp-socket.finish\ +-listen\x01\x17\x01i\x12\x01o\x03\x1e\x19\x1a\x01j\x01\x1f\x01\x0b\x01@\x01\x04s\ +elf\x13\0\x20\x04\0\x19[method]tcp-socket.accept\x01!\x01j\x01\x0d\x01\x0b\x01@\x01\ +\x04self\x13\0\"\x04\0\x20[method]tcp-socket.local-address\x01#\x04\0![method]tc\ +p-socket.remote-address\x01#\x01@\x01\x04self\x13\0\x7f\x04\0\x1f[method]tcp-soc\ +ket.is-listening\x01$\x01@\x01\x04self\x13\0\x0f\x04\0![method]tcp-socket.addres\ +s-family\x01%\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[method]tcp-socket.set-\ +listen-backlog-size\x01&\x01j\x01\x7f\x01\x0b\x01@\x01\x04self\x13\0'\x04\0%[met\ +hod]tcp-socket.keep-alive-enabled\x01(\x01@\x02\x04self\x13\x05value\x7f\0\x15\x04\ +\0)[method]tcp-socket.set-keep-alive-enabled\x01)\x01j\x01\x07\x01\x0b\x01@\x01\x04\ +self\x13\0*\x04\0'[method]tcp-socket.keep-alive-idle-time\x01+\x01@\x02\x04self\x13\ +\x05value\x07\0\x15\x04\0+[method]tcp-socket.set-keep-alive-idle-time\x01,\x04\0\ +&[method]tcp-socket.keep-alive-interval\x01+\x04\0*[method]tcp-socket.set-keep-a\ +live-interval\x01,\x01j\x01y\x01\x0b\x01@\x01\x04self\x13\0-\x04\0#[method]tcp-s\ +ocket.keep-alive-count\x01.\x01@\x02\x04self\x13\x05valuey\0\x15\x04\0'[method]t\ +cp-socket.set-keep-alive-count\x01/\x01j\x01}\x01\x0b\x01@\x01\x04self\x13\00\x04\ +\0\x1c[method]tcp-socket.hop-limit\x011\x01@\x02\x04self\x13\x05value}\0\x15\x04\ +\0\x20[method]tcp-socket.set-hop-limit\x012\x01j\x01w\x01\x0b\x01@\x01\x04self\x13\ +\03\x04\0&[method]tcp-socket.receive-buffer-size\x014\x04\0*[method]tcp-socket.s\ +et-receive-buffer-size\x01&\x04\0#[method]tcp-socket.send-buffer-size\x014\x04\0\ +'[method]tcp-socket.set-send-buffer-size\x01&\x01i\x05\x01@\x01\x04self\x13\05\x04\ +\0\x1c[method]tcp-socket.subscribe\x016\x01@\x02\x04self\x13\x0dshutdown-type\x11\ +\0\x15\x04\0\x1b[method]tcp-socket.shutdown\x017\x03\0\x16wasi:sockets/tcp@0.2.4\ +\x05$\x02\x03\0\x15\x0atcp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\0\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\ +\x11ip-address-family\x03\0\x04\x02\x03\x02\x01%\x04\0\x0atcp-socket\x03\0\x06\x01\ +i\x07\x01j\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-\ +tcp-socket\x01\x0a\x03\0$wasi:sockets/tcp-create-socket@0.2.4\x05&\x02\x03\0\x11\ +\x0aip-address\x01B\x16\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\ +\x04\x02\x03\x02\x01'\x04\0\x0aip-address\x03\0\x06\x04\0\x16resolve-address-str\ +eam\x03\x01\x01h\x08\x01k\x07\x01j\x01\x0a\x01\x05\x01@\x01\x04self\x09\0\x0b\x04\ +\03[method]resolve-address-stream.resolve-next-address\x01\x0c\x01i\x01\x01@\x01\ +\x04self\x09\0\x0d\x04\0([method]resolve-address-stream.subscribe\x01\x0e\x01h\x03\ +\x01i\x08\x01j\x01\x10\x01\x05\x01@\x02\x07network\x0f\x04names\0\x11\x04\0\x11r\ +esolve-addresses\x01\x12\x03\0!wasi:sockets/ip-name-lookup@0.2.4\x05(\x01B\x05\x01\ +p}\x01@\x01\x03lenw\0\0\x04\0\x10get-random-bytes\x01\x01\x01@\0\0w\x04\0\x0eget\ +-random-u64\x01\x02\x03\0\x18wasi:random/random@0.2.4\x05)\x01B\x05\x01p}\x01@\x01\ +\x03lenw\0\0\x04\0\x19get-insecure-random-bytes\x01\x01\x01@\0\0w\x04\0\x17get-i\ +nsecure-random-u64\x01\x02\x03\0\x1awasi:random/insecure@0.2.4\x05*\x01B\x03\x01\ +o\x02ww\x01@\0\0\0\x04\0\x0dinsecure-seed\x01\x01\x03\0\x1fwasi:random/insecure-\ +seed@0.2.4\x05+\x04\06wasi:cli/command-with-all-of-its-exports-removed@0.2.4\x04\ +\0\x0b-\x01\0'command-with-all-of-its-exports-removed\x03\0\0\0G\x09producers\x01\ +\x0cprocessed-by\x02\x0dwit-component\x070.239.0\x10wit-bindgen-rust\x060.46.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen::rt::maybe_link_cabi_realloc(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/ext/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/ext/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +#[cfg(feature = "std")] +mod std; + +impl core::fmt::Display for crate::io::error::Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(&self.to_debug_string()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/ext/std.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/std.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/ext/std.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/ext/std.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +use std::error::Error; +use std::io; +use std::num::NonZeroU64; + +use crate::io::streams::StreamError; + +impl Error for crate::io::error::Error {} + +impl io::Read for crate::io::streams::InputStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let n = buf + .len() + .try_into() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + match self.blocking_read(n) { + Ok(chunk) => { + let n = chunk.len(); + if n > buf.len() { + return Err(io::Error::new( + io::ErrorKind::Other, + "more bytes read than requested", + )); + } + buf[..n].copy_from_slice(&chunk); + Ok(n) + } + Err(StreamError::Closed) => Ok(0), + Err(StreamError::LastOperationFailed(e)) => { + Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string())) + } + } + } +} + +impl io::Write for crate::io::streams::OutputStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + let n = loop { + match self.check_write().map(NonZeroU64::new) { + Ok(Some(n)) => { + break n; + } + Ok(None) => { + self.subscribe().block(); + } + Err(StreamError::Closed) => return Ok(0), + Err(StreamError::LastOperationFailed(e)) => { + return Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string())) + } + }; + }; + let n = n + .get() + .try_into() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let n = buf.len().min(n); + crate::io::streams::OutputStream::write(self, &buf[..n]).map_err(|e| match e { + StreamError::Closed => io::ErrorKind::UnexpectedEof.into(), + StreamError::LastOperationFailed(e) => { + io::Error::new(io::ErrorKind::Other, e.to_debug_string()) + } + })?; + Ok(n) + } + + fn flush(&mut self) -> io::Result<()> { + self.blocking_flush() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/imports.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/imports.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/imports.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/imports.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10238 @@ +// Generated by `wit-bindgen` 0.46.0. DO NOT EDIT! +// Options used: +// * std_feature +// * type_section_suffix: "rust-wasip2-1.0.1+wasi-0.2.4-from-crates-io" +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] +pub mod wasi { + pub mod cli { + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod environment { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + #[allow(async_fn_in_trait)] + pub fn get_environment() -> _rt::Vec<(_rt::String, _rt::String)> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/environment@0.2.4")] + unsafe extern "C" { + #[link_name = "get-environment"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l2; + let len10 = l3; + let mut result10 = _rt::Vec::with_capacity(len10); + for i in 0..len10 { + let base = base10 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + let e10 = { + let l4 = *base.add(0).cast::<*mut u8>(); + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts(l4.cast(), len6, len6); + let l7 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len9 = l8; + let bytes9 = _rt::Vec::from_raw_parts(l7.cast(), len9, len9); + (_rt::string_lift(bytes6), _rt::string_lift(bytes9)) + }; + result10.push(e10); + } + _rt::cabi_dealloc( + base10, + len10 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result11 = result10; + result11 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Get the POSIX-style arguments to the program. + #[allow(async_fn_in_trait)] + pub fn get_arguments() -> _rt::Vec<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/environment@0.2.4")] + unsafe extern "C" { + #[link_name = "get-arguments"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base7 = l2; + let len7 = l3; + let mut result7 = _rt::Vec::with_capacity(len7); + for i in 0..len7 { + let base = base7 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e7 = { + let l4 = *base.add(0).cast::<*mut u8>(); + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts(l4.cast(), len6, len6); + _rt::string_lift(bytes6) + }; + result7.push(e7); + } + _rt::cabi_dealloc( + base7, + len7 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result8 = result7; + result8 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + #[allow(async_fn_in_trait)] + pub fn initial_cwd() -> Option<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/environment@0.2.4")] + unsafe extern "C" { + #[link_name = "initial-cwd"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod exit { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + #[allow(unused_unsafe, clippy::all)] + /// Exit the current instance and any linked instances. + #[allow(async_fn_in_trait)] + pub fn exit(status: Result<(), ()>) -> () { + unsafe { + let result0 = match status { + Ok(_) => 0i32, + Err(_) => 1i32, + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/exit@0.2.4")] + unsafe extern "C" { + #[link_name = "exit"] + fn wit_import1(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32) { + unreachable!() + } + wit_import1(result0); + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod stdin { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + pub type InputStream = super::super::super::wasi::io::streams::InputStream; + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn get_stdin() -> InputStream { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/stdin@0.2.4")] + unsafe extern "C" { + #[link_name = "get-stdin"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + super::super::super::wasi::io::streams::InputStream::from_handle( + ret as u32, + ) + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod stdout { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + pub type OutputStream = super::super::super::wasi::io::streams::OutputStream; + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn get_stdout() -> OutputStream { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/stdout@0.2.4")] + unsafe extern "C" { + #[link_name = "get-stdout"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + super::super::super::wasi::io::streams::OutputStream::from_handle( + ret as u32, + ) + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod stderr { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + pub type OutputStream = super::super::super::wasi::io::streams::OutputStream; + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn get_stderr() -> OutputStream { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/stderr@0.2.4")] + unsafe extern "C" { + #[link_name = "get-stderr"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + super::super::super::wasi::io::streams::OutputStream::from_handle( + ret as u32, + ) + } + } + } + /// Terminal input. + /// + /// In the future, this may include functions for disabling echoing, + /// disabling input buffering so that keyboard events are sent through + /// immediately, querying supported features, and so on. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod terminal_input { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// The input side of a terminal. + #[derive(Debug)] + #[repr(transparent)] + pub struct TerminalInput { + handle: _rt::Resource, + } + impl TerminalInput { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for TerminalInput { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/terminal-input@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]terminal-input"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + } + /// Terminal output. + /// + /// In the future, this may include functions for querying the terminal + /// size, being notified of terminal size changes, querying supported + /// features, and so on. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod terminal_output { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// The output side of a terminal. + #[derive(Debug)] + #[repr(transparent)] + pub struct TerminalOutput { + handle: _rt::Resource, + } + impl TerminalOutput { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for TerminalOutput { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/terminal-output@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]terminal-output"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + } + /// An interface providing an optional `terminal-input` for stdin as a + /// link-time authority. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod terminal_stdin { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type TerminalInput = super::super::super::wasi::cli::terminal_input::TerminalInput; + #[allow(unused_unsafe, clippy::all)] + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + #[allow(async_fn_in_trait)] + pub fn get_terminal_stdin() -> Option { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/terminal-stdin@0.2.4")] + unsafe extern "C" { + #[link_name = "get-terminal-stdin"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::cli::terminal_input::TerminalInput::from_handle( + l3 as u32, + ) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + /// An interface providing an optional `terminal-output` for stdout as a + /// link-time authority. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod terminal_stdout { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type TerminalOutput = super::super::super::wasi::cli::terminal_output::TerminalOutput; + #[allow(unused_unsafe, clippy::all)] + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + #[allow(async_fn_in_trait)] + pub fn get_terminal_stdout() -> Option { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/terminal-stdout@0.2.4")] + unsafe extern "C" { + #[link_name = "get-terminal-stdout"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::cli::terminal_output::TerminalOutput::from_handle( + l3 as u32, + ) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + /// An interface providing an optional `terminal-output` for stderr as a + /// link-time authority. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod terminal_stderr { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type TerminalOutput = super::super::super::wasi::cli::terminal_output::TerminalOutput; + #[allow(unused_unsafe, clippy::all)] + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + #[allow(async_fn_in_trait)] + pub fn get_terminal_stderr() -> Option { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:cli/terminal-stderr@0.2.4")] + unsafe extern "C" { + #[link_name = "get-terminal-stderr"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::cli::terminal_output::TerminalOutput::from_handle( + l3 as u32, + ) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + } + pub mod clocks { + /// WASI Monotonic Clock is a clock API intended to let users measure elapsed + /// time. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + /// + /// A monotonic clock is a clock which has an unspecified initial value, and + /// successive reads of the clock will produce non-decreasing values. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod monotonic_clock { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Pollable = super::super::super::wasi::io::poll::Pollable; + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + pub type Instant = u64; + /// A duration of time, in nanoseconds. + pub type Duration = u64; + #[allow(unused_unsafe, clippy::all)] + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + #[allow(async_fn_in_trait)] + pub fn now() -> Instant { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/monotonic-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "now"] + fn wit_import0() -> i64; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i64 { + unreachable!() + } + let ret = wit_import0(); + ret as u64 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + #[allow(async_fn_in_trait)] + pub fn resolution() -> Duration { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/monotonic-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "resolution"] + fn wit_import0() -> i64; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i64 { + unreachable!() + } + let ret = wit_import0(); + ret as u64 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the specified instant + /// has occurred. + #[allow(async_fn_in_trait)] + pub fn subscribe_instant(when: Instant) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/monotonic-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "subscribe-instant"] + fn wit_import0(_: i64) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i64) -> i32 { + unreachable!() + } + let ret = wit_import0(_rt::as_i64(when)); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` that will resolve after the specified duration has + /// elapsed from the time this function is invoked. + #[allow(async_fn_in_trait)] + pub fn subscribe_duration(when: Duration) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/monotonic-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "subscribe-duration"] + fn wit_import0(_: i64) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i64) -> i32 { + unreachable!() + } + let ret = wit_import0(_rt::as_i64(when)); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + /// WASI Wall Clock is a clock API intended to let users query the current + /// time. The name "wall" makes an analogy to a "clock on the wall", which + /// is not necessarily monotonic as it may be reset. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + /// + /// A wall clock is a clock which measures the date and time according to + /// some external reference. + /// + /// External references may be reset, so this clock is not necessarily + /// monotonic, making it unsuitable for measuring elapsed time. + /// + /// It is intended for reporting the current date and time for humans. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod wall_clock { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + /// A time and date in seconds plus nanoseconds. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Datetime { + pub seconds: u64, + pub nanoseconds: u32, + } + impl ::core::fmt::Debug for Datetime { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Datetime") + .field("seconds", &self.seconds) + .field("nanoseconds", &self.nanoseconds) + .finish() + } + } + #[allow(unused_unsafe, clippy::all)] + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + #[allow(async_fn_in_trait)] + pub fn now() -> Datetime { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 16]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/wall-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "now"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::(); + let l3 = *ptr0.add(8).cast::(); + let result4 = Datetime { + seconds: l2 as u64, + nanoseconds: l3 as u32, + }; + result4 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + #[allow(async_fn_in_trait)] + pub fn resolution() -> Datetime { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 16]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:clocks/wall-clock@0.2.4")] + unsafe extern "C" { + #[link_name = "resolution"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::(); + let l3 = *ptr0.add(8).cast::(); + let result4 = Datetime { + seconds: l2 as u64, + nanoseconds: l3 as u32, + }; + result4 + } + } + } + } + pub mod filesystem { + /// WASI filesystem is a filesystem API primarily intended to let users run WASI + /// programs that access their files on their existing filesystems, without + /// significant overhead. + /// + /// It is intended to be roughly portable between Unix-family platforms and + /// Windows, though it does not hide many of the major differences. + /// + /// Paths are passed as interface-type `string`s, meaning they must consist of + /// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain + /// paths which are not accessible by this API. + /// + /// The directory separator in WASI is always the forward-slash (`/`). + /// + /// All paths in WASI are relative paths, and are interpreted relative to a + /// `descriptor` referring to a base directory. If a `path` argument to any WASI + /// function starts with `/`, or if any step of resolving a `path`, including + /// `..` and symbolic link steps, reaches a directory outside of the base + /// directory, or reaches a symlink to an absolute or rooted path in the + /// underlying filesystem, the function fails with `error-code::not-permitted`. + /// + /// For more information about WASI path resolution and sandboxing, see + /// [WASI filesystem path resolution]. + /// + /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod types { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type InputStream = super::super::super::wasi::io::streams::InputStream; + pub type OutputStream = super::super::super::wasi::io::streams::OutputStream; + pub type Error = super::super::super::wasi::io::streams::Error; + pub type Datetime = super::super::super::wasi::clocks::wall_clock::Datetime; + /// File size or length of a region within a file. + pub type Filesize = u64; + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum DescriptorType { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + Unknown, + /// The descriptor refers to a block device inode. + BlockDevice, + /// The descriptor refers to a character device inode. + CharacterDevice, + /// The descriptor refers to a directory inode. + Directory, + /// The descriptor refers to a named pipe. + Fifo, + /// The file refers to a symbolic link inode. + SymbolicLink, + /// The descriptor refers to a regular file inode. + RegularFile, + /// The descriptor refers to a socket. + Socket, + } + impl ::core::fmt::Debug for DescriptorType { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + DescriptorType::Unknown => { + f.debug_tuple("DescriptorType::Unknown").finish() + } + DescriptorType::BlockDevice => { + f.debug_tuple("DescriptorType::BlockDevice").finish() + } + DescriptorType::CharacterDevice => { + f.debug_tuple("DescriptorType::CharacterDevice").finish() + } + DescriptorType::Directory => { + f.debug_tuple("DescriptorType::Directory").finish() + } + DescriptorType::Fifo => { + f.debug_tuple("DescriptorType::Fifo").finish() + } + DescriptorType::SymbolicLink => { + f.debug_tuple("DescriptorType::SymbolicLink").finish() + } + DescriptorType::RegularFile => { + f.debug_tuple("DescriptorType::RegularFile").finish() + } + DescriptorType::Socket => { + f.debug_tuple("DescriptorType::Socket").finish() + } + } + } + } + impl DescriptorType { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> DescriptorType { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => DescriptorType::Unknown, + 1 => DescriptorType::BlockDevice, + 2 => DescriptorType::CharacterDevice, + 3 => DescriptorType::Directory, + 4 => DescriptorType::Fifo, + 5 => DescriptorType::SymbolicLink, + 6 => DescriptorType::RegularFile, + 7 => DescriptorType::Socket, + _ => panic!("invalid enum discriminant"), + } + } + } + wit_bindgen::rt::bitflags::bitflags! { + #[doc = " Descriptor flags."] #[doc = ""] #[doc = + " Note: This was called `fdflags` in earlier versions of WASI."] + #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] pub + struct DescriptorFlags : u8 { #[doc = " Read mode: Data can be read."] + const READ = 1 << 0; #[doc = " Write mode: Data can be written to."] + const WRITE = 1 << 1; #[doc = + " Request that writes be performed according to synchronized I/O file"] + #[doc = + " integrity completion. The data stored in the file and the file's"] + #[doc = + " metadata are synchronized. This is similar to `O_SYNC` in POSIX."] + #[doc = ""] #[doc = + " The precise semantics of this operation have not yet been defined for"] + #[doc = + " WASI. At this time, it should be interpreted as a request, and not a"] + #[doc = " requirement."] const FILE_INTEGRITY_SYNC = 1 << 2; #[doc = + " Request that writes be performed according to synchronized I/O data"] + #[doc = " integrity completion. Only the data stored in the file is"] + #[doc = " synchronized. This is similar to `O_DSYNC` in POSIX."] #[doc = + ""] #[doc = + " The precise semantics of this operation have not yet been defined for"] + #[doc = + " WASI. At this time, it should be interpreted as a request, and not a"] + #[doc = " requirement."] const DATA_INTEGRITY_SYNC = 1 << 3; #[doc = + " Requests that reads be performed at the same level of integrity"] #[doc + = " requested for writes. This is similar to `O_RSYNC` in POSIX."] #[doc + = ""] #[doc = + " The precise semantics of this operation have not yet been defined for"] + #[doc = + " WASI. At this time, it should be interpreted as a request, and not a"] + #[doc = " requirement."] const REQUESTED_WRITE_SYNC = 1 << 4; #[doc = + " Mutating directories mode: Directory contents may be mutated."] #[doc = + ""] #[doc = + " When this flag is unset on a descriptor, operations using the"] #[doc = + " descriptor which would create, rename, delete, modify the data or"] + #[doc = + " metadata of filesystem objects, or obtain another handle which"] #[doc + = + " would permit any of those, shall fail with `error-code::read-only` if"] + #[doc = " they would otherwise succeed."] #[doc = ""] #[doc = + " This may only be set on directories."] const MUTATE_DIRECTORY = 1 << 5; + } + } + wit_bindgen::rt::bitflags::bitflags! { + #[doc = " Flags determining the method of how paths are resolved."] + #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] pub + struct PathFlags : u8 { #[doc = + " As long as the resolved path corresponds to a symbolic link, it is"] + #[doc = " expanded."] const SYMLINK_FOLLOW = 1 << 0; } + } + wit_bindgen::rt::bitflags::bitflags! { + #[doc = " Open flags used by `open-at`."] #[derive(PartialEq, Eq, + PartialOrd, Ord, Hash, Debug, Clone, Copy)] pub struct OpenFlags : u8 { + #[doc = + " Create file if it does not exist, similar to `O_CREAT` in POSIX."] + const CREATE = 1 << 0; #[doc = + " Fail if not a directory, similar to `O_DIRECTORY` in POSIX."] const + DIRECTORY = 1 << 1; #[doc = + " Fail if file already exists, similar to `O_EXCL` in POSIX."] const + EXCLUSIVE = 1 << 2; #[doc = + " Truncate file to size 0, similar to `O_TRUNC` in POSIX."] const + TRUNCATE = 1 << 3; } + } + /// Number of hard links to an inode. + pub type LinkCount = u64; + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct DescriptorStat { + /// File type. + pub type_: DescriptorType, + /// Number of hard links to the file. + pub link_count: LinkCount, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + pub size: Filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + pub data_access_timestamp: Option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + pub data_modification_timestamp: Option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + pub status_change_timestamp: Option, + } + impl ::core::fmt::Debug for DescriptorStat { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("DescriptorStat") + .field("type", &self.type_) + .field("link-count", &self.link_count) + .field("size", &self.size) + .field("data-access-timestamp", &self.data_access_timestamp) + .field( + "data-modification-timestamp", + &self.data_modification_timestamp, + ) + .field("status-change-timestamp", &self.status_change_timestamp) + .finish() + } + } + /// When setting a timestamp, this gives the value to set it to. + #[derive(Clone, Copy)] + pub enum NewTimestamp { + /// Leave the timestamp set to its previous value. + NoChange, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + Now, + /// Set the timestamp to the given value. + Timestamp(Datetime), + } + impl ::core::fmt::Debug for NewTimestamp { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + NewTimestamp::NoChange => { + f.debug_tuple("NewTimestamp::NoChange").finish() + } + NewTimestamp::Now => f.debug_tuple("NewTimestamp::Now").finish(), + NewTimestamp::Timestamp(e) => { + f.debug_tuple("NewTimestamp::Timestamp").field(e).finish() + } + } + } + } + /// A directory entry. + #[derive(Clone)] + pub struct DirectoryEntry { + /// The type of the file referred to by this directory entry. + pub type_: DescriptorType, + /// The name of the object. + pub name: _rt::String, + } + impl ::core::fmt::Debug for DirectoryEntry { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("DirectoryEntry") + .field("type", &self.type_) + .field("name", &self.name) + .finish() + } + } + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum ErrorCode { + /// Permission denied, similar to `EACCES` in POSIX. + Access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + WouldBlock, + /// Connection already in progress, similar to `EALREADY` in POSIX. + Already, + /// Bad descriptor, similar to `EBADF` in POSIX. + BadDescriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + Busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + Deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + Quota, + /// File exists, similar to `EEXIST` in POSIX. + Exist, + /// File too large, similar to `EFBIG` in POSIX. + FileTooLarge, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + IllegalByteSequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + InProgress, + /// Interrupted function, similar to `EINTR` in POSIX. + Interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + Invalid, + /// I/O error, similar to `EIO` in POSIX. + Io, + /// Is a directory, similar to `EISDIR` in POSIX. + IsDirectory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + Loop, + /// Too many links, similar to `EMLINK` in POSIX. + TooManyLinks, + /// Message too large, similar to `EMSGSIZE` in POSIX. + MessageSize, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + NameTooLong, + /// No such device, similar to `ENODEV` in POSIX. + NoDevice, + /// No such file or directory, similar to `ENOENT` in POSIX. + NoEntry, + /// No locks available, similar to `ENOLCK` in POSIX. + NoLock, + /// Not enough space, similar to `ENOMEM` in POSIX. + InsufficientMemory, + /// No space left on device, similar to `ENOSPC` in POSIX. + InsufficientSpace, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + NotDirectory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + NotEmpty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + NotRecoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + Unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + NoTty, + /// No such device or address, similar to `ENXIO` in POSIX. + NoSuchDevice, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + Overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + NotPermitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + Pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + ReadOnly, + /// Invalid seek, similar to `ESPIPE` in POSIX. + InvalidSeek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + TextFileBusy, + /// Cross-device link, similar to `EXDEV` in POSIX. + CrossDevice, + } + impl ErrorCode { + pub fn name(&self) -> &'static str { + match self { + ErrorCode::Access => "access", + ErrorCode::WouldBlock => "would-block", + ErrorCode::Already => "already", + ErrorCode::BadDescriptor => "bad-descriptor", + ErrorCode::Busy => "busy", + ErrorCode::Deadlock => "deadlock", + ErrorCode::Quota => "quota", + ErrorCode::Exist => "exist", + ErrorCode::FileTooLarge => "file-too-large", + ErrorCode::IllegalByteSequence => "illegal-byte-sequence", + ErrorCode::InProgress => "in-progress", + ErrorCode::Interrupted => "interrupted", + ErrorCode::Invalid => "invalid", + ErrorCode::Io => "io", + ErrorCode::IsDirectory => "is-directory", + ErrorCode::Loop => "loop", + ErrorCode::TooManyLinks => "too-many-links", + ErrorCode::MessageSize => "message-size", + ErrorCode::NameTooLong => "name-too-long", + ErrorCode::NoDevice => "no-device", + ErrorCode::NoEntry => "no-entry", + ErrorCode::NoLock => "no-lock", + ErrorCode::InsufficientMemory => "insufficient-memory", + ErrorCode::InsufficientSpace => "insufficient-space", + ErrorCode::NotDirectory => "not-directory", + ErrorCode::NotEmpty => "not-empty", + ErrorCode::NotRecoverable => "not-recoverable", + ErrorCode::Unsupported => "unsupported", + ErrorCode::NoTty => "no-tty", + ErrorCode::NoSuchDevice => "no-such-device", + ErrorCode::Overflow => "overflow", + ErrorCode::NotPermitted => "not-permitted", + ErrorCode::Pipe => "pipe", + ErrorCode::ReadOnly => "read-only", + ErrorCode::InvalidSeek => "invalid-seek", + ErrorCode::TextFileBusy => "text-file-busy", + ErrorCode::CrossDevice => "cross-device", + } + } + pub fn message(&self) -> &'static str { + match self { + ErrorCode::Access => { + "Permission denied, similar to `EACCES` in POSIX." + } + ErrorCode::WouldBlock => { + "Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX." + } + ErrorCode::Already => { + "Connection already in progress, similar to `EALREADY` in POSIX." + } + ErrorCode::BadDescriptor => { + "Bad descriptor, similar to `EBADF` in POSIX." + } + ErrorCode::Busy => { + "Device or resource busy, similar to `EBUSY` in POSIX." + } + ErrorCode::Deadlock => { + "Resource deadlock would occur, similar to `EDEADLK` in POSIX." + } + ErrorCode::Quota => { + "Storage quota exceeded, similar to `EDQUOT` in POSIX." + } + ErrorCode::Exist => "File exists, similar to `EEXIST` in POSIX.", + ErrorCode::FileTooLarge => { + "File too large, similar to `EFBIG` in POSIX." + } + ErrorCode::IllegalByteSequence => { + "Illegal byte sequence, similar to `EILSEQ` in POSIX." + } + ErrorCode::InProgress => { + "Operation in progress, similar to `EINPROGRESS` in POSIX." + } + ErrorCode::Interrupted => { + "Interrupted function, similar to `EINTR` in POSIX." + } + ErrorCode::Invalid => { + "Invalid argument, similar to `EINVAL` in POSIX." + } + ErrorCode::Io => "I/O error, similar to `EIO` in POSIX.", + ErrorCode::IsDirectory => { + "Is a directory, similar to `EISDIR` in POSIX." + } + ErrorCode::Loop => { + "Too many levels of symbolic links, similar to `ELOOP` in POSIX." + } + ErrorCode::TooManyLinks => { + "Too many links, similar to `EMLINK` in POSIX." + } + ErrorCode::MessageSize => { + "Message too large, similar to `EMSGSIZE` in POSIX." + } + ErrorCode::NameTooLong => { + "Filename too long, similar to `ENAMETOOLONG` in POSIX." + } + ErrorCode::NoDevice => { + "No such device, similar to `ENODEV` in POSIX." + } + ErrorCode::NoEntry => { + "No such file or directory, similar to `ENOENT` in POSIX." + } + ErrorCode::NoLock => { + "No locks available, similar to `ENOLCK` in POSIX." + } + ErrorCode::InsufficientMemory => { + "Not enough space, similar to `ENOMEM` in POSIX." + } + ErrorCode::InsufficientSpace => { + "No space left on device, similar to `ENOSPC` in POSIX." + } + ErrorCode::NotDirectory => { + "Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX." + } + ErrorCode::NotEmpty => { + "Directory not empty, similar to `ENOTEMPTY` in POSIX." + } + ErrorCode::NotRecoverable => { + "State not recoverable, similar to `ENOTRECOVERABLE` in POSIX." + } + ErrorCode::Unsupported => { + "Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX." + } + ErrorCode::NoTty => { + "Inappropriate I/O control operation, similar to `ENOTTY` in POSIX." + } + ErrorCode::NoSuchDevice => { + "No such device or address, similar to `ENXIO` in POSIX." + } + ErrorCode::Overflow => { + "Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX." + } + ErrorCode::NotPermitted => { + "Operation not permitted, similar to `EPERM` in POSIX." + } + ErrorCode::Pipe => "Broken pipe, similar to `EPIPE` in POSIX.", + ErrorCode::ReadOnly => { + "Read-only file system, similar to `EROFS` in POSIX." + } + ErrorCode::InvalidSeek => { + "Invalid seek, similar to `ESPIPE` in POSIX." + } + ErrorCode::TextFileBusy => { + "Text file busy, similar to `ETXTBSY` in POSIX." + } + ErrorCode::CrossDevice => { + "Cross-device link, similar to `EXDEV` in POSIX." + } + } + } + } + impl ::core::fmt::Debug for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("ErrorCode") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl ::core::fmt::Display for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + #[cfg(feature = "std")] + impl std::error::Error for ErrorCode {} + impl ErrorCode { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> ErrorCode { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => ErrorCode::Access, + 1 => ErrorCode::WouldBlock, + 2 => ErrorCode::Already, + 3 => ErrorCode::BadDescriptor, + 4 => ErrorCode::Busy, + 5 => ErrorCode::Deadlock, + 6 => ErrorCode::Quota, + 7 => ErrorCode::Exist, + 8 => ErrorCode::FileTooLarge, + 9 => ErrorCode::IllegalByteSequence, + 10 => ErrorCode::InProgress, + 11 => ErrorCode::Interrupted, + 12 => ErrorCode::Invalid, + 13 => ErrorCode::Io, + 14 => ErrorCode::IsDirectory, + 15 => ErrorCode::Loop, + 16 => ErrorCode::TooManyLinks, + 17 => ErrorCode::MessageSize, + 18 => ErrorCode::NameTooLong, + 19 => ErrorCode::NoDevice, + 20 => ErrorCode::NoEntry, + 21 => ErrorCode::NoLock, + 22 => ErrorCode::InsufficientMemory, + 23 => ErrorCode::InsufficientSpace, + 24 => ErrorCode::NotDirectory, + 25 => ErrorCode::NotEmpty, + 26 => ErrorCode::NotRecoverable, + 27 => ErrorCode::Unsupported, + 28 => ErrorCode::NoTty, + 29 => ErrorCode::NoSuchDevice, + 30 => ErrorCode::Overflow, + 31 => ErrorCode::NotPermitted, + 32 => ErrorCode::Pipe, + 33 => ErrorCode::ReadOnly, + 34 => ErrorCode::InvalidSeek, + 35 => ErrorCode::TextFileBusy, + 36 => ErrorCode::CrossDevice, + _ => panic!("invalid enum discriminant"), + } + } + } + /// File or memory access pattern advisory information. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum Advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + Normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + Sequential, + /// The application expects to access the specified data in a random + /// order. + Random, + /// The application expects to access the specified data in the near + /// future. + WillNeed, + /// The application expects that it will not access the specified data + /// in the near future. + DontNeed, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + NoReuse, + } + impl ::core::fmt::Debug for Advice { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + Advice::Normal => f.debug_tuple("Advice::Normal").finish(), + Advice::Sequential => { + f.debug_tuple("Advice::Sequential").finish() + } + Advice::Random => f.debug_tuple("Advice::Random").finish(), + Advice::WillNeed => f.debug_tuple("Advice::WillNeed").finish(), + Advice::DontNeed => f.debug_tuple("Advice::DontNeed").finish(), + Advice::NoReuse => f.debug_tuple("Advice::NoReuse").finish(), + } + } + } + impl Advice { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> Advice { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => Advice::Normal, + 1 => Advice::Sequential, + 2 => Advice::Random, + 3 => Advice::WillNeed, + 4 => Advice::DontNeed, + 5 => Advice::NoReuse, + _ => panic!("invalid enum discriminant"), + } + } + } + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct MetadataHashValue { + /// 64 bits of a 128-bit hash value. + pub lower: u64, + /// Another 64 bits of a 128-bit hash value. + pub upper: u64, + } + impl ::core::fmt::Debug for MetadataHashValue { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("MetadataHashValue") + .field("lower", &self.lower) + .field("upper", &self.upper) + .finish() + } + } + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + #[derive(Debug)] + #[repr(transparent)] + pub struct Descriptor { + handle: _rt::Resource, + } + impl Descriptor { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for Descriptor { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]descriptor"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// A stream of directory entries. + #[derive(Debug)] + #[repr(transparent)] + pub struct DirectoryEntryStream { + handle: _rt::Resource, + } + impl DirectoryEntryStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for DirectoryEntryStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]directory-entry-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + #[allow(async_fn_in_trait)] + pub fn read_via_stream( + &self, + offset: Filesize, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.read-via-stream"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(offset), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::io::streams::InputStream::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + #[allow(async_fn_in_trait)] + pub fn write_via_stream( + &self, + offset: Filesize, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.write-via-stream"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(offset), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::io::streams::OutputStream::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in POSIX. + #[allow(async_fn_in_trait)] + pub fn append_via_stream(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.append-via-stream"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::io::streams::OutputStream::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + #[allow(async_fn_in_trait)] + pub fn advise( + &self, + offset: Filesize, + length: Filesize, + advice: Advice, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.advise"] + fn wit_import1(_: i32, _: i64, _: i64, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1( + _: i32, + _: i64, + _: i64, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + _rt::as_i64(offset), + _rt::as_i64(length), + advice.clone() as i32, + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l3 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + #[allow(async_fn_in_trait)] + pub fn sync_data(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.sync-data"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l3 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn get_flags(&self) -> Result { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.get-flags"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + DescriptorFlags::empty() + | DescriptorFlags::from_bits_retain(((l3 as u8) << 0) as _) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn get_type(&self) -> Result { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.get-type"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + DescriptorType::_lift(l3 as u8) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn set_size(&self, size: Filesize) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.set-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(size), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l3 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn set_times( + &self, + data_access_timestamp: NewTimestamp, + data_modification_timestamp: NewTimestamp, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let (result1_0, result1_1, result1_2) = match data_access_timestamp { + NewTimestamp::NoChange => (0i32, 0i64, 0i32), + NewTimestamp::Now => (1i32, 0i64, 0i32), + NewTimestamp::Timestamp(e) => { + let super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: seconds0, + nanoseconds: nanoseconds0, + } = e; + (2i32, _rt::as_i64(seconds0), _rt::as_i32(nanoseconds0)) + } + }; + let (result3_0, result3_1, result3_2) = match data_modification_timestamp { + NewTimestamp::NoChange => (0i32, 0i64, 0i32), + NewTimestamp::Now => (1i32, 0i64, 0i32), + NewTimestamp::Timestamp(e) => { + let super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: seconds2, + nanoseconds: nanoseconds2, + } = e; + (2i32, _rt::as_i64(seconds2), _rt::as_i32(nanoseconds2)) + } + }; + let ptr4 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.set-times"] + fn wit_import5( + _: i32, + _: i32, + _: i64, + _: i32, + _: i32, + _: i64, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import5( + _: i32, + _: i32, + _: i64, + _: i32, + _: i32, + _: i64, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import5( + (self).handle() as i32, + result1_0, + result1_1, + result1_2, + result3_0, + result3_1, + result3_2, + ptr4, + ); + let l6 = i32::from(*ptr4.add(0).cast::()); + let result8 = match l6 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l7 = i32::from(*ptr4.add(1).cast::()); + ErrorCode::_lift(l7 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + #[allow(async_fn_in_trait)] + pub fn read( + &self, + length: Filesize, + offset: Filesize, + ) -> Result<(_rt::Vec, bool), ErrorCode> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.read"] + fn wit_import1(_: i32, _: i64, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1( + _: i32, + _: i64, + _: i64, + _: *mut u8, + ) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + _rt::as_i64(length), + _rt::as_i64(offset), + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result8 = match l2 { + 0 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let l6 = i32::from( + *ptr0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + ( + _rt::Vec::from_raw_parts(l3.cast(), len5, len5), + _rt::bool_lift(l6 as u8), + ) + }; + Ok(e) + } + 1 => { + let e = { + let l7 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + ErrorCode::_lift(l7 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + #[allow(async_fn_in_trait)] + pub fn write( + &self, + buffer: &[u8], + offset: Filesize, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let vec0 = buffer; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.write"] + fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: i64, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: i64, + _: *mut u8, + ) { + unreachable!() + } + wit_import2( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + _rt::as_i64(offset), + ptr1, + ); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result6 = match l3 { + 0 => { + let e = { + let l4 = *ptr1.add(8).cast::(); + l4 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr1.add(8).cast::()); + ErrorCode::_lift(l5 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + #[allow(async_fn_in_trait)] + pub fn read_directory(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.read-directory"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + DirectoryEntryStream::from_handle(l3 as u32) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + #[allow(async_fn_in_trait)] + pub fn sync(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.sync"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l3 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn create_directory_at(&self, path: &str) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.create-directory-at"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result5 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(1).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn stat(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 104]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 104], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.stat"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result16 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(8).cast::()); + let l4 = *ptr0.add(16).cast::(); + let l5 = *ptr0.add(24).cast::(); + let l6 = i32::from(*ptr0.add(32).cast::()); + let l9 = i32::from(*ptr0.add(56).cast::()); + let l12 = i32::from(*ptr0.add(80).cast::()); + DescriptorStat { + type_: DescriptorType::_lift(l3 as u8), + link_count: l4 as u64, + size: l5 as u64, + data_access_timestamp: match l6 { + 0 => None, + 1 => { + let e = { + let l7 = *ptr0.add(40).cast::(); + let l8 = *ptr0.add(48).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l7 as u64, + nanoseconds: l8 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + data_modification_timestamp: match l9 { + 0 => None, + 1 => { + let e = { + let l10 = *ptr0.add(64).cast::(); + let l11 = *ptr0.add(72).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l10 as u64, + nanoseconds: l11 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + status_change_timestamp: match l12 { + 0 => None, + 1 => { + let e = { + let l13 = *ptr0.add(88).cast::(); + let l14 = *ptr0.add(96).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l13 as u64, + nanoseconds: l14 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Ok(e) + } + 1 => { + let e = { + let l15 = i32::from(*ptr0.add(8).cast::()); + ErrorCode::_lift(l15 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result16 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + #[allow(async_fn_in_trait)] + pub fn stat_at( + &self, + path_flags: PathFlags, + path: &str, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 104]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 104], + ); + let flags0 = path_flags; + let vec1 = path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let ptr2 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.stat-at"] + fn wit_import3( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import3( + (self).handle() as i32, + (flags0.bits() >> 0) as i32, + ptr1.cast_mut(), + len1, + ptr2, + ); + let l4 = i32::from(*ptr2.add(0).cast::()); + let result18 = match l4 { + 0 => { + let e = { + let l5 = i32::from(*ptr2.add(8).cast::()); + let l6 = *ptr2.add(16).cast::(); + let l7 = *ptr2.add(24).cast::(); + let l8 = i32::from(*ptr2.add(32).cast::()); + let l11 = i32::from(*ptr2.add(56).cast::()); + let l14 = i32::from(*ptr2.add(80).cast::()); + DescriptorStat { + type_: DescriptorType::_lift(l5 as u8), + link_count: l6 as u64, + size: l7 as u64, + data_access_timestamp: match l8 { + 0 => None, + 1 => { + let e = { + let l9 = *ptr2.add(40).cast::(); + let l10 = *ptr2.add(48).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l9 as u64, + nanoseconds: l10 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + data_modification_timestamp: match l11 { + 0 => None, + 1 => { + let e = { + let l12 = *ptr2.add(64).cast::(); + let l13 = *ptr2.add(72).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l12 as u64, + nanoseconds: l13 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + status_change_timestamp: match l14 { + 0 => None, + 1 => { + let e = { + let l15 = *ptr2.add(88).cast::(); + let l16 = *ptr2.add(96).cast::(); + super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: l15 as u64, + nanoseconds: l16 as u32, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Ok(e) + } + 1 => { + let e = { + let l17 = i32::from(*ptr2.add(8).cast::()); + ErrorCode::_lift(l17 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result18 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + #[allow(async_fn_in_trait)] + pub fn set_times_at( + &self, + path_flags: PathFlags, + path: &str, + data_access_timestamp: NewTimestamp, + data_modification_timestamp: NewTimestamp, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let flags0 = path_flags; + let vec1 = path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let (result3_0, result3_1, result3_2) = match data_access_timestamp { + NewTimestamp::NoChange => (0i32, 0i64, 0i32), + NewTimestamp::Now => (1i32, 0i64, 0i32), + NewTimestamp::Timestamp(e) => { + let super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: seconds2, + nanoseconds: nanoseconds2, + } = e; + (2i32, _rt::as_i64(seconds2), _rt::as_i32(nanoseconds2)) + } + }; + let (result5_0, result5_1, result5_2) = match data_modification_timestamp { + NewTimestamp::NoChange => (0i32, 0i64, 0i32), + NewTimestamp::Now => (1i32, 0i64, 0i32), + NewTimestamp::Timestamp(e) => { + let super::super::super::wasi::clocks::wall_clock::Datetime { + seconds: seconds4, + nanoseconds: nanoseconds4, + } = e; + (2i32, _rt::as_i64(seconds4), _rt::as_i32(nanoseconds4)) + } + }; + let ptr6 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.set-times-at"] + fn wit_import7( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: i64, + _: i32, + _: i32, + _: i64, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import7( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: i64, + _: i32, + _: i32, + _: i64, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import7( + (self).handle() as i32, + (flags0.bits() >> 0) as i32, + ptr1.cast_mut(), + len1, + result3_0, + result3_1, + result3_2, + result5_0, + result5_1, + result5_2, + ptr6, + ); + let l8 = i32::from(*ptr6.add(0).cast::()); + let result10 = match l8 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l9 = i32::from(*ptr6.add(1).cast::()); + ErrorCode::_lift(l9 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result10 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Create a hard link. + /// + /// Fails with `error-code::no-entry` if the old path does not exist, + /// with `error-code::exist` if the new path already exists, and + /// `error-code::not-permitted` if the old path is not a file. + /// + /// Note: This is similar to `linkat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn link_at( + &self, + old_path_flags: PathFlags, + old_path: &str, + new_descriptor: &Descriptor, + new_path: &str, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let flags0 = old_path_flags; + let vec1 = old_path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let vec2 = new_path; + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + let ptr3 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.link-at"] + fn wit_import4( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import4( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import4( + (self).handle() as i32, + (flags0.bits() >> 0) as i32, + ptr1.cast_mut(), + len1, + (new_descriptor).handle() as i32, + ptr2.cast_mut(), + len2, + ptr3, + ); + let l5 = i32::from(*ptr3.add(0).cast::()); + let result7 = match l5 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from(*ptr3.add(1).cast::()); + ErrorCode::_lift(l6 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Open a file or directory. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn open_at( + &self, + path_flags: PathFlags, + path: &str, + open_flags: OpenFlags, + flags: DescriptorFlags, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let flags0 = path_flags; + let vec1 = path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let flags2 = open_flags; + let flags3 = flags; + let ptr4 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.open-at"] + fn wit_import5( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import5( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import5( + (self).handle() as i32, + (flags0.bits() >> 0) as i32, + ptr1.cast_mut(), + len1, + (flags2.bits() >> 0) as i32, + (flags3.bits() >> 0) as i32, + ptr4, + ); + let l6 = i32::from(*ptr4.add(0).cast::()); + let result9 = match l6 { + 0 => { + let e = { + let l7 = *ptr4.add(4).cast::(); + Descriptor::from_handle(l7 as u32) + }; + Ok(e) + } + 1 => { + let e = { + let l8 = i32::from(*ptr4.add(4).cast::()); + ErrorCode::_lift(l8 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result9 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn readlink_at(&self, path: &str) -> Result<_rt::String, ErrorCode> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let vec0 = path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.readlink-at"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result8 = match l3 { + 0 => { + let e = { + let l4 = *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts( + l4.cast(), + len6, + len6, + ); + _rt::string_lift(bytes6) + }; + Ok(e) + } + 1 => { + let e = { + let l7 = i32::from( + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + ErrorCode::_lift(l7 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + #[allow(async_fn_in_trait)] + pub fn remove_directory_at(&self, path: &str) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.remove-directory-at"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result5 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(1).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn rename_at( + &self, + old_path: &str, + new_descriptor: &Descriptor, + new_path: &str, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = old_path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let vec1 = new_path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let ptr2 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.rename-at"] + fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import3( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + (new_descriptor).handle() as i32, + ptr1.cast_mut(), + len1, + ptr2, + ); + let l4 = i32::from(*ptr2.add(0).cast::()); + let result6 = match l4 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr2.add(1).cast::()); + ErrorCode::_lift(l5 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + #[allow(async_fn_in_trait)] + pub fn symlink_at( + &self, + old_path: &str, + new_path: &str, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = old_path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let vec1 = new_path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let ptr2 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.symlink-at"] + fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import3( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + ptr1.cast_mut(), + len1, + ptr2, + ); + let l4 = i32::from(*ptr2.add(0).cast::()); + let result6 = match l4 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr2.add(1).cast::()); + ErrorCode::_lift(l5 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + #[allow(async_fn_in_trait)] + pub fn unlink_file_at(&self, path: &str) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = path; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.unlink-file-at"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result5 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(1).cast::()); + ErrorCode::_lift(l4 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + #[allow(async_fn_in_trait)] + pub fn is_same_object(&self, other: &Descriptor) -> bool { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.is-same-object"] + fn wit_import0(_: i32, _: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32, _: i32) -> i32 { + unreachable!() + } + let ret = wit_import0( + (self).handle() as i32, + (other).handle() as i32, + ); + _rt::bool_lift(ret as u8) + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encouraged to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + #[allow(async_fn_in_trait)] + pub fn metadata_hash(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 24]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 24], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.metadata-hash"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + let l4 = *ptr0.add(16).cast::(); + MetadataHashValue { + lower: l3 as u64, + upper: l4 as u64, + } + }; + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr0.add(8).cast::()); + ErrorCode::_lift(l5 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl Descriptor { + #[allow(unused_unsafe, clippy::all)] + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + #[allow(async_fn_in_trait)] + pub fn metadata_hash_at( + &self, + path_flags: PathFlags, + path: &str, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 24]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 24], + ); + let flags0 = path_flags; + let vec1 = path; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let ptr2 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]descriptor.metadata-hash-at"] + fn wit_import3( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import3( + (self).handle() as i32, + (flags0.bits() >> 0) as i32, + ptr1.cast_mut(), + len1, + ptr2, + ); + let l4 = i32::from(*ptr2.add(0).cast::()); + let result8 = match l4 { + 0 => { + let e = { + let l5 = *ptr2.add(8).cast::(); + let l6 = *ptr2.add(16).cast::(); + MetadataHashValue { + lower: l5 as u64, + upper: l6 as u64, + } + }; + Ok(e) + } + 1 => { + let e = { + let l7 = i32::from(*ptr2.add(8).cast::()); + ErrorCode::_lift(l7 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl DirectoryEntryStream { + #[allow(unused_unsafe, clippy::all)] + /// Read a single directory entry from a `directory-entry-stream`. + #[allow(async_fn_in_trait)] + pub fn read_directory_entry( + &self, + ) -> Result, ErrorCode> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 5 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 5 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]directory-entry-stream.read-directory-entry"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result9 = match l2 { + 0 => { + let e = { + let l3 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l3 { + 0 => None, + 1 => { + let e = { + let l4 = i32::from( + *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l5 = *ptr0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *ptr0 + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, + ); + DirectoryEntry { + type_: DescriptorType::_lift(l4 as u8), + name: _rt::string_lift(bytes7), + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Ok(e) + } + 1 => { + let e = { + let l8 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + ErrorCode::_lift(l8 as u8) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result9 + } + } + } + #[allow(unused_unsafe, clippy::all)] + /// Attempts to extract a filesystem-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// filesystem-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are filesystem-related errors. + #[allow(async_fn_in_trait)] + pub fn filesystem_error_code(err: &Error) -> Option { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 2]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/types@0.2.4")] + unsafe extern "C" { + #[link_name = "filesystem-error-code"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((err).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + ErrorCode::_lift(l3 as u8) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod preopens { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Descriptor = super::super::super::wasi::filesystem::types::Descriptor; + #[allow(unused_unsafe, clippy::all)] + /// Return the set of preopened directories, and their paths. + #[allow(async_fn_in_trait)] + pub fn get_directories() -> _rt::Vec<(Descriptor, _rt::String)> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:filesystem/preopens@0.2.4")] + unsafe extern "C" { + #[link_name = "get-directories"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base8 = l2; + let len8 = l3; + let mut result8 = _rt::Vec::with_capacity(len8); + for i in 0..len8 { + let base = base8 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + let e8 = { + let l4 = *base.add(0).cast::(); + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts(l5.cast(), len7, len7); + ( + super::super::super::wasi::filesystem::types::Descriptor::from_handle( + l4 as u32, + ), + _rt::string_lift(bytes7), + ) + }; + result8.push(e8); + } + _rt::cabi_dealloc( + base8, + len8 * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result9 = result8; + result9 + } + } + } + } + pub mod io { + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod error { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// A resource which represents some error information. + /// + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. + /// + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams/stream-error` type. + /// + /// To provide more specific error information, other interfaces may + /// offer functions to "downcast" this error into more specific types. For example, + /// errors returned from streams derived from filesystem types can be described using + /// the filesystem's own error-code type. This is done using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow` + /// parameter and returns an `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + #[derive(Debug)] + #[repr(transparent)] + pub struct Error { + handle: _rt::Resource, + } + impl Error { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for Error { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/error@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]error"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl Error { + #[allow(unused_unsafe, clippy::all)] + /// Returns a string that is suitable to assist humans in debugging + /// this error. + /// + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. + #[allow(async_fn_in_trait)] + pub fn to_debug_string(&self) -> _rt::String { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/error@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]error.to-debug-string"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len4 = l3; + let bytes4 = _rt::Vec::from_raw_parts(l2.cast(), len4, len4); + let result5 = _rt::string_lift(bytes4); + result5 + } + } + } + } + /// A poll API intended to let users wait for I/O events on multiple handles + /// at once. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod poll { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// `pollable` represents a single I/O event which may be ready, or not. + #[derive(Debug)] + #[repr(transparent)] + pub struct Pollable { + handle: _rt::Resource, + } + impl Pollable { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for Pollable { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/poll@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]pollable"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl Pollable { + #[allow(unused_unsafe, clippy::all)] + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + #[allow(async_fn_in_trait)] + pub fn ready(&self) -> bool { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/poll@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]pollable.ready"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + _rt::bool_lift(ret as u8) + } + } + } + impl Pollable { + #[allow(unused_unsafe, clippy::all)] + /// `block` returns immediately if the pollable is ready, and otherwise + /// blocks until ready. + /// + /// This function is equivalent to calling `poll.poll` on a list + /// containing only this pollable. + #[allow(async_fn_in_trait)] + pub fn block(&self) -> () { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/poll@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]pollable.block"] + fn wit_import0(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) { + unreachable!() + } + wit_import0((self).handle() as i32); + } + } + } + #[allow(unused_unsafe, clippy::all)] + /// Poll for completion on a set of pollables. + /// + /// This function takes a list of pollables, which identify I/O sources of + /// interest, and waits until one or more of the events is ready for I/O. + /// + /// The result `list` contains one or more indices of handles in the + /// argument list that is ready for I/O. + /// + /// This function traps if either: + /// - the list is empty, or: + /// - the list contains more elements than can be indexed with a `u32` value. + /// + /// A timeout can be implemented by adding a pollable from the + /// wasi-clocks API to the list. + /// + /// This function does not return a `result`; polling in itself does not + /// do any I/O so it doesn't fail. If any of the I/O sources identified by + /// the pollables has an error, it is indicated by marking the source as + /// being ready for I/O. + #[allow(async_fn_in_trait)] + pub fn poll(in_: &[&Pollable]) -> _rt::Vec { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let vec0 = in_; + let len0 = vec0.len(); + let layout0 = _rt::alloc::Layout::from_size_align(vec0.len() * 4, 4) + .unwrap(); + let (result0, _cleanup0) = wit_bindgen::rt::Cleanup::new(layout0); + for (i, e) in vec0.into_iter().enumerate() { + let base = result0.add(i * 4); + { + *base.add(0).cast::() = (e).handle() as i32; + } + } + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/poll@0.2.4")] + unsafe extern "C" { + #[link_name = "poll"] + fn wit_import2(_: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2(_: *mut u8, _: usize, _: *mut u8) { + unreachable!() + } + wit_import2(result0, len0, ptr1); + let l3 = *ptr1.add(0).cast::<*mut u8>(); + let l4 = *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let result6 = _rt::Vec::from_raw_parts(l3.cast(), len5, len5); + result6 + } + } + } + /// WASI I/O is an I/O abstraction API which is currently focused on providing + /// stream types. + /// + /// In the future, the component model is expected to add built-in stream types; + /// when it does, they are expected to subsume this API. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod streams { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Error = super::super::super::wasi::io::error::Error; + pub type Pollable = super::super::super::wasi::io::poll::Pollable; + /// An error for input-stream and output-stream operations. + pub enum StreamError { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + /// + /// After this, the stream will be closed. All future operations return + /// `stream-error::closed`. + LastOperationFailed(Error), + /// The stream is closed: no more input will be accepted by the + /// stream. A closed output-stream will return this error on all + /// future operations. + Closed, + } + impl ::core::fmt::Debug for StreamError { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + StreamError::LastOperationFailed(e) => { + f.debug_tuple("StreamError::LastOperationFailed") + .field(e) + .finish() + } + StreamError::Closed => { + f.debug_tuple("StreamError::Closed").finish() + } + } + } + } + impl ::core::fmt::Display for StreamError { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + write!(f, "{:?}", self) + } + } + #[cfg(feature = "std")] + impl std::error::Error for StreamError {} + /// An input bytestream. + /// + /// `input-stream`s are *non-blocking* to the extent practical on underlying + /// platforms. I/O operations always return promptly; if fewer bytes are + /// promptly available than requested, they return the number of bytes promptly + /// available, which could even be zero. To wait for data to be available, + /// use the `subscribe` function to obtain a `pollable` which can be polled + /// for using `wasi:io/poll`. + #[derive(Debug)] + #[repr(transparent)] + pub struct InputStream { + handle: _rt::Resource, + } + impl InputStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for InputStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]input-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// An output bytestream. + /// + /// `output-stream`s are *non-blocking* to the extent practical on + /// underlying platforms. Except where specified otherwise, I/O operations also + /// always return promptly, after the number of bytes that can be written + /// promptly, which could even be zero. To wait for the stream to be ready to + /// accept data, the `subscribe` function to obtain a `pollable` which can be + /// polled for using `wasi:io/poll`. + /// + /// Dropping an `output-stream` while there's still an active write in + /// progress may result in the data being lost. Before dropping the stream, + /// be sure to fully flush your writes. + #[derive(Debug)] + #[repr(transparent)] + pub struct OutputStream { + handle: _rt::Resource, + } + impl OutputStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for OutputStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]output-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl InputStream { + #[allow(unused_unsafe, clippy::all)] + /// Perform a non-blocking read from the stream. + /// + /// When the source of a `read` is binary data, the bytes from the source + /// are returned verbatim. When the source of a `read` is known to the + /// implementation to be text, bytes containing the UTF-8 encoding of the + /// text are returned. + /// + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// available. + /// + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. + /// + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. + /// + /// The `len` parameter is a `u64`, which could represent a list of u8 which + /// is not possible to allocate in wasm32, or not desirable to allocate as + /// as a return value by the callee. The callee may return a list of bytes + /// less than `len` in size while more bytes are available for reading. + #[allow(async_fn_in_trait)] + pub fn read(&self, len: u64) -> Result<_rt::Vec, StreamError> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]input-stream.read"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result9 = match l2 { + 0 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + _rt::Vec::from_raw_parts(l3.cast(), len5, len5) + }; + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + let v8 = match l6 { + 0 => { + let e8 = { + let l7 = *ptr0 + .add(4 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l7 as u32, + ) + }; + StreamError::LastOperationFailed(e8) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v8 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result9 + } + } + } + impl InputStream { + #[allow(unused_unsafe, clippy::all)] + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, behavior is identical to `read`. + #[allow(async_fn_in_trait)] + pub fn blocking_read( + &self, + len: u64, + ) -> Result<_rt::Vec, StreamError> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]input-stream.blocking-read"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result9 = match l2 { + 0 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + _rt::Vec::from_raw_parts(l3.cast(), len5, len5) + }; + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + let v8 = match l6 { + 0 => { + let e8 = { + let l7 = *ptr0 + .add(4 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l7 as u32, + ) + }; + StreamError::LastOperationFailed(e8) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v8 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result9 + } + } + } + impl InputStream { + #[allow(unused_unsafe, clippy::all)] + /// Skip bytes from a stream. Returns number of bytes skipped. + /// + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. + #[allow(async_fn_in_trait)] + pub fn skip(&self, len: u64) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]input-stream.skip"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr0.add(12).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl InputStream { + #[allow(unused_unsafe, clippy::all)] + /// Skip bytes from a stream, after blocking until at least one byte + /// can be skipped. Except for blocking behavior, identical to `skip`. + #[allow(async_fn_in_trait)] + pub fn blocking_skip(&self, len: u64) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]input-stream.blocking-skip"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr0.add(12).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl InputStream { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once either the specified stream + /// has bytes available to read or the other end of the stream has been + /// closed. + /// The created `pollable` is a child resource of the `input-stream`. + /// Implementations may trap if the `input-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]input-stream.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Check readiness for writing. This function never blocks. + /// + /// Returns the number of bytes permitted for the next call to `write`, + /// or an error. Calling `write` with more bytes than this function has + /// permitted will trap. + /// + /// When this function returns 0 bytes, the `subscribe` pollable will + /// become ready when this function will report at least 1 byte, or an + /// error. + #[allow(async_fn_in_trait)] + pub fn check_write(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.check-write"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr0.add(12).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Perform a write. This function never blocks. + /// + /// When the destination of a `write` is binary data, the bytes from + /// `contents` are written verbatim. When the destination of a `write` is + /// known to the implementation to be text, the bytes of `contents` are + /// transcoded from UTF-8 into the encoding of the destination and then + /// written. + /// + /// Precondition: check-write gave permit of Ok(n) and contents has a + /// length of less than or equal to n. Otherwise, this function will trap. + /// + /// returns Err(closed) without writing if the stream has closed since + /// the last call to check-write provided a permit. + #[allow(async_fn_in_trait)] + pub fn write(&self, contents: &[u8]) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let vec0 = contents; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.write"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result7 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(4).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr1.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Perform a write of up to 4096 bytes, and then flush the stream. Block + /// until all of these operations are complete, or an error occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + #[allow(async_fn_in_trait)] + pub fn blocking_write_and_flush( + &self, + contents: &[u8], + ) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let vec0 = contents; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.blocking-write-and-flush"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result7 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(4).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr1.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Request to flush buffered output. This function never blocks. + /// + /// This tells the output-stream that the caller intends any buffered + /// output to be flushed. the output which is expected to be flushed + /// is all that has been passed to `write` prior to this call. + /// + /// Upon calling this function, the `output-stream` will not accept any + /// writes (`check-write` will return `ok(0)`) until the flush has + /// completed. The `subscribe` pollable will become ready when the + /// flush has completed and the stream can accept more writes. + #[allow(async_fn_in_trait)] + pub fn flush(&self) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.flush"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + let v5 = match l3 { + 0 => { + let e5 = { + let l4 = *ptr0.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l4 as u32, + ) + }; + StreamError::LastOperationFailed(e5) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v5 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + #[allow(async_fn_in_trait)] + pub fn blocking_flush(&self) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.blocking-flush"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + let v5 = match l3 { + 0 => { + let e5 = { + let l4 = *ptr0.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l4 as u32, + ) + }; + StreamError::LastOperationFailed(e5) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v5 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the output-stream + /// is ready for more writing, or an error has occurred. When this + /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an + /// error. + /// + /// If the stream is closed, this pollable is always ready immediately. + /// + /// The created `pollable` is a child resource of the `output-stream`. + /// Implementations may trap if the `output-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Write zeroes to a stream. + /// + /// This should be used precisely like `write` with the exact same + /// preconditions (must use check-write first), but instead of + /// passing a list of bytes, you simply pass the number of zero-bytes + /// that should be written. + #[allow(async_fn_in_trait)] + pub fn write_zeroes(&self, len: u64) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.write-zeroes"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + let v5 = match l3 { + 0 => { + let e5 = { + let l4 = *ptr0.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l4 as u32, + ) + }; + StreamError::LastOperationFailed(e5) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v5 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Perform a write of up to 4096 zeroes, and then flush the stream. + /// Block until all of these operations are complete, or an error + /// occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + #[allow(async_fn_in_trait)] + pub fn blocking_write_zeroes_and_flush( + &self, + len: u64, + ) -> Result<(), StreamError> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.blocking-write-zeroes-and-flush"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&len), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + let v5 = match l3 { + 0 => { + let e5 = { + let l4 = *ptr0.add(8).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l4 as u32, + ) + }; + StreamError::LastOperationFailed(e5) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v5 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivalent to: + /// 1. calling `check-write` on the `output-stream` + /// 2. calling `read` on the `input-stream` with the smaller of the + /// `check-write` permitted length and the `len` provided to `splice` + /// 3. calling `write` on the `output-stream` with that read data. + /// + /// Any error reported by the call to `check-write`, `read`, or + /// `write` ends the splice and reports that error. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + #[allow(async_fn_in_trait)] + pub fn splice( + &self, + src: &InputStream, + len: u64, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.splice"] + fn wit_import1(_: i32, _: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1( + _: i32, + _: i32, + _: i64, + _: *mut u8, + ) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + (src).handle() as i32, + _rt::as_i64(&len), + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr0.add(12).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl OutputStream { + #[allow(unused_unsafe, clippy::all)] + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until the + /// `output-stream` is ready for writing, and the `input-stream` + /// is ready for reading, before performing the `splice`. + #[allow(async_fn_in_trait)] + pub fn blocking_splice( + &self, + src: &InputStream, + len: u64, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:io/streams@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]output-stream.blocking-splice"] + fn wit_import1(_: i32, _: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1( + _: i32, + _: i32, + _: i64, + _: *mut u8, + ) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + (src).handle() as i32, + _rt::as_i64(&len), + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let v6 = match l4 { + 0 => { + let e6 = { + let l5 = *ptr0.add(12).cast::(); + super::super::super::wasi::io::error::Error::from_handle( + l5 as u32, + ) + }; + StreamError::LastOperationFailed(e6) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + StreamError::Closed + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + } + } + pub mod random { + /// WASI Random is a random data API. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod random { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + /// Return `len` cryptographically-secure random or pseudo-random bytes. + /// + /// This function must produce data at least as cryptographically secure and + /// fast as an adequately seeded cryptographically-secure pseudo-random + /// number generator (CSPRNG). It must not block, from the perspective of + /// the calling program, under any circumstances, including on the first + /// request and on requests for numbers of bytes. The returned data must + /// always be unpredictable. + /// + /// This function must always return fresh data. Deterministic environments + /// must omit this function, rather than implementing it with deterministic + /// data. + #[allow(async_fn_in_trait)] + pub fn get_random_bytes(len: u64) -> _rt::Vec { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:random/random@0.2.4")] + unsafe extern "C" { + #[link_name = "get-random-bytes"] + fn wit_import1(_: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i64, _: *mut u8) { + unreachable!() + } + wit_import1(_rt::as_i64(&len), ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len4 = l3; + let result5 = _rt::Vec::from_raw_parts(l2.cast(), len4, len4); + result5 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Return a cryptographically-secure random or pseudo-random `u64` value. + /// + /// This function returns the same type of data as `get-random-bytes`, + /// represented as a `u64`. + #[allow(async_fn_in_trait)] + pub fn get_random_u64() -> u64 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:random/random@0.2.4")] + unsafe extern "C" { + #[link_name = "get-random-u64"] + fn wit_import0() -> i64; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i64 { + unreachable!() + } + let ret = wit_import0(); + ret as u64 + } + } + } + /// The insecure interface for insecure pseudo-random numbers. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod insecure { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + /// Return `len` insecure pseudo-random bytes. + /// + /// This function is not cryptographically secure. Do not use it for + /// anything related to security. + /// + /// There are no requirements on the values of the returned bytes, however + /// implementations are encouraged to return evenly distributed values with + /// a long period. + #[allow(async_fn_in_trait)] + pub fn get_insecure_random_bytes(len: u64) -> _rt::Vec { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:random/insecure@0.2.4")] + unsafe extern "C" { + #[link_name = "get-insecure-random-bytes"] + fn wit_import1(_: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i64, _: *mut u8) { + unreachable!() + } + wit_import1(_rt::as_i64(&len), ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len4 = l3; + let result5 = _rt::Vec::from_raw_parts(l2.cast(), len4, len4); + result5 + } + } + #[allow(unused_unsafe, clippy::all)] + /// Return an insecure pseudo-random `u64` value. + /// + /// This function returns the same type of pseudo-random data as + /// `get-insecure-random-bytes`, represented as a `u64`. + #[allow(async_fn_in_trait)] + pub fn get_insecure_random_u64() -> u64 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:random/insecure@0.2.4")] + unsafe extern "C" { + #[link_name = "get-insecure-random-u64"] + fn wit_import0() -> i64; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i64 { + unreachable!() + } + let ret = wit_import0(); + ret as u64 + } + } + } + /// The insecure-seed interface for seeding hash-map DoS resistance. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod insecure_seed { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + #[allow(unused_unsafe, clippy::all)] + /// Return a 128-bit value that may contain a pseudo-random value. + /// + /// The returned value is not required to be computed from a CSPRNG, and may + /// even be entirely deterministic. Host implementations are encouraged to + /// provide pseudo-random values to any program exposed to + /// attacker-controlled content, to enable DoS protection built into many + /// languages' hash-map implementations. + /// + /// This function is intended to only be called once, by a source language + /// to initialize Denial Of Service (DoS) protection in its hash-map + /// implementation. + /// + /// # Expected future evolution + /// + /// This will likely be changed to a value import, to prevent it from being + /// called multiple times and potentially used for purposes other than DoS + /// protection. + #[allow(async_fn_in_trait)] + pub fn insecure_seed() -> (u64, u64) { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 16]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:random/insecure-seed@0.2.4")] + unsafe extern "C" { + #[link_name = "insecure-seed"] + fn wit_import1(_: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: *mut u8) { + unreachable!() + } + wit_import1(ptr0); + let l2 = *ptr0.add(0).cast::(); + let l3 = *ptr0.add(8).cast::(); + let result4 = (l2 as u64, l3 as u64); + result4 + } + } + } + } + pub mod sockets { + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod network { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// An opaque resource that represents access to (a subset of) the network. + /// This enables context-based security for networking. + /// There is no need for this to map 1:1 to a physical network interface. + #[derive(Debug)] + #[repr(transparent)] + pub struct Network { + handle: _rt::Resource, + } + impl Network { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for Network { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/network@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]network"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Error codes. + /// + /// In theory, every API can return any error code. + /// In practice, API's typically only return the errors documented per API + /// combined with a couple of errors that are always possible: + /// - `unknown` + /// - `access-denied` + /// - `not-supported` + /// - `out-of-memory` + /// - `concurrency-conflict` + /// + /// See each individual API for what the POSIX equivalents are. They sometimes differ per API. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum ErrorCode { + /// Unknown error + Unknown, + /// Access denied. + /// + /// POSIX equivalent: EACCES, EPERM + AccessDenied, + /// The operation is not supported. + /// + /// POSIX equivalent: EOPNOTSUPP + NotSupported, + /// One of the arguments is invalid. + /// + /// POSIX equivalent: EINVAL + InvalidArgument, + /// Not enough memory to complete the operation. + /// + /// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY + OutOfMemory, + /// The operation timed out before it could finish completely. + Timeout, + /// This operation is incompatible with another asynchronous operation that is already in progress. + /// + /// POSIX equivalent: EALREADY + ConcurrencyConflict, + /// Trying to finish an asynchronous operation that: + /// - has not been started yet, or: + /// - was already finished by a previous `finish-*` call. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + NotInProgress, + /// The operation has been aborted because it could not be completed immediately. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + WouldBlock, + /// The operation is not valid in the socket's current state. + InvalidState, + /// A new socket resource could not be created because of a system limit. + NewSocketLimit, + /// A bind operation failed because the provided address is not an address that the `network` can bind to. + AddressNotBindable, + /// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. + AddressInUse, + /// The remote address is not reachable + RemoteUnreachable, + /// The TCP connection was forcefully rejected + ConnectionRefused, + /// The TCP connection was reset. + ConnectionReset, + /// A TCP connection was aborted. + ConnectionAborted, + /// The size of a datagram sent to a UDP socket exceeded the maximum + /// supported size. + DatagramTooLarge, + /// Name does not exist or has no suitable associated IP addresses. + NameUnresolvable, + /// A temporary failure in name resolution occurred. + TemporaryResolverFailure, + /// A permanent failure in name resolution occurred. + PermanentResolverFailure, + } + impl ErrorCode { + pub fn name(&self) -> &'static str { + match self { + ErrorCode::Unknown => "unknown", + ErrorCode::AccessDenied => "access-denied", + ErrorCode::NotSupported => "not-supported", + ErrorCode::InvalidArgument => "invalid-argument", + ErrorCode::OutOfMemory => "out-of-memory", + ErrorCode::Timeout => "timeout", + ErrorCode::ConcurrencyConflict => "concurrency-conflict", + ErrorCode::NotInProgress => "not-in-progress", + ErrorCode::WouldBlock => "would-block", + ErrorCode::InvalidState => "invalid-state", + ErrorCode::NewSocketLimit => "new-socket-limit", + ErrorCode::AddressNotBindable => "address-not-bindable", + ErrorCode::AddressInUse => "address-in-use", + ErrorCode::RemoteUnreachable => "remote-unreachable", + ErrorCode::ConnectionRefused => "connection-refused", + ErrorCode::ConnectionReset => "connection-reset", + ErrorCode::ConnectionAborted => "connection-aborted", + ErrorCode::DatagramTooLarge => "datagram-too-large", + ErrorCode::NameUnresolvable => "name-unresolvable", + ErrorCode::TemporaryResolverFailure => { + "temporary-resolver-failure" + } + ErrorCode::PermanentResolverFailure => { + "permanent-resolver-failure" + } + } + } + pub fn message(&self) -> &'static str { + match self { + ErrorCode::Unknown => "Unknown error", + ErrorCode::AccessDenied => { + "Access denied. + + POSIX equivalent: EACCES, EPERM" + } + ErrorCode::NotSupported => { + "The operation is not supported. + + POSIX equivalent: EOPNOTSUPP" + } + ErrorCode::InvalidArgument => { + "One of the arguments is invalid. + + POSIX equivalent: EINVAL" + } + ErrorCode::OutOfMemory => { + "Not enough memory to complete the operation. + + POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY" + } + ErrorCode::Timeout => { + "The operation timed out before it could finish completely." + } + ErrorCode::ConcurrencyConflict => { + "This operation is incompatible with another asynchronous operation that is already in progress. + + POSIX equivalent: EALREADY" + } + ErrorCode::NotInProgress => { + "Trying to finish an asynchronous operation that: + - has not been started yet, or: + - was already finished by a previous `finish-*` call. + + Note: this is scheduled to be removed when `future`s are natively supported." + } + ErrorCode::WouldBlock => { + "The operation has been aborted because it could not be completed immediately. + + Note: this is scheduled to be removed when `future`s are natively supported." + } + ErrorCode::InvalidState => { + "The operation is not valid in the socket's current state." + } + ErrorCode::NewSocketLimit => { + "A new socket resource could not be created because of a system limit." + } + ErrorCode::AddressNotBindable => { + "A bind operation failed because the provided address is not an address that the `network` can bind to." + } + ErrorCode::AddressInUse => { + "A bind operation failed because the provided address is already in use or because there are no ephemeral ports available." + } + ErrorCode::RemoteUnreachable => { + "The remote address is not reachable" + } + ErrorCode::ConnectionRefused => { + "The TCP connection was forcefully rejected" + } + ErrorCode::ConnectionReset => "The TCP connection was reset.", + ErrorCode::ConnectionAborted => "A TCP connection was aborted.", + ErrorCode::DatagramTooLarge => { + "The size of a datagram sent to a UDP socket exceeded the maximum + supported size." + } + ErrorCode::NameUnresolvable => { + "Name does not exist or has no suitable associated IP addresses." + } + ErrorCode::TemporaryResolverFailure => { + "A temporary failure in name resolution occurred." + } + ErrorCode::PermanentResolverFailure => { + "A permanent failure in name resolution occurred." + } + } + } + } + impl ::core::fmt::Debug for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("ErrorCode") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl ::core::fmt::Display for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + #[cfg(feature = "std")] + impl std::error::Error for ErrorCode {} + impl ErrorCode { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> ErrorCode { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => ErrorCode::Unknown, + 1 => ErrorCode::AccessDenied, + 2 => ErrorCode::NotSupported, + 3 => ErrorCode::InvalidArgument, + 4 => ErrorCode::OutOfMemory, + 5 => ErrorCode::Timeout, + 6 => ErrorCode::ConcurrencyConflict, + 7 => ErrorCode::NotInProgress, + 8 => ErrorCode::WouldBlock, + 9 => ErrorCode::InvalidState, + 10 => ErrorCode::NewSocketLimit, + 11 => ErrorCode::AddressNotBindable, + 12 => ErrorCode::AddressInUse, + 13 => ErrorCode::RemoteUnreachable, + 14 => ErrorCode::ConnectionRefused, + 15 => ErrorCode::ConnectionReset, + 16 => ErrorCode::ConnectionAborted, + 17 => ErrorCode::DatagramTooLarge, + 18 => ErrorCode::NameUnresolvable, + 19 => ErrorCode::TemporaryResolverFailure, + 20 => ErrorCode::PermanentResolverFailure, + _ => panic!("invalid enum discriminant"), + } + } + } + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum IpAddressFamily { + /// Similar to `AF_INET` in POSIX. + Ipv4, + /// Similar to `AF_INET6` in POSIX. + Ipv6, + } + impl ::core::fmt::Debug for IpAddressFamily { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + IpAddressFamily::Ipv4 => { + f.debug_tuple("IpAddressFamily::Ipv4").finish() + } + IpAddressFamily::Ipv6 => { + f.debug_tuple("IpAddressFamily::Ipv6").finish() + } + } + } + } + impl IpAddressFamily { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> IpAddressFamily { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => IpAddressFamily::Ipv4, + 1 => IpAddressFamily::Ipv6, + _ => panic!("invalid enum discriminant"), + } + } + } + pub type Ipv4Address = (u8, u8, u8, u8); + pub type Ipv6Address = (u16, u16, u16, u16, u16, u16, u16, u16); + #[derive(Clone, Copy)] + pub enum IpAddress { + Ipv4(Ipv4Address), + Ipv6(Ipv6Address), + } + impl ::core::fmt::Debug for IpAddress { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + IpAddress::Ipv4(e) => { + f.debug_tuple("IpAddress::Ipv4").field(e).finish() + } + IpAddress::Ipv6(e) => { + f.debug_tuple("IpAddress::Ipv6").field(e).finish() + } + } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Ipv4SocketAddress { + /// sin_port + pub port: u16, + /// sin_addr + pub address: Ipv4Address, + } + impl ::core::fmt::Debug for Ipv4SocketAddress { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Ipv4SocketAddress") + .field("port", &self.port) + .field("address", &self.address) + .finish() + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Ipv6SocketAddress { + /// sin6_port + pub port: u16, + /// sin6_flowinfo + pub flow_info: u32, + /// sin6_addr + pub address: Ipv6Address, + /// sin6_scope_id + pub scope_id: u32, + } + impl ::core::fmt::Debug for Ipv6SocketAddress { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Ipv6SocketAddress") + .field("port", &self.port) + .field("flow-info", &self.flow_info) + .field("address", &self.address) + .field("scope-id", &self.scope_id) + .finish() + } + } + #[derive(Clone, Copy)] + pub enum IpSocketAddress { + Ipv4(Ipv4SocketAddress), + Ipv6(Ipv6SocketAddress), + } + impl ::core::fmt::Debug for IpSocketAddress { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + IpSocketAddress::Ipv4(e) => { + f.debug_tuple("IpSocketAddress::Ipv4").field(e).finish() + } + IpSocketAddress::Ipv6(e) => { + f.debug_tuple("IpSocketAddress::Ipv6").field(e).finish() + } + } + } + } + } + /// This interface provides a value-export of the default network handle.. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod instance_network { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + pub type Network = super::super::super::wasi::sockets::network::Network; + #[allow(unused_unsafe, clippy::all)] + /// Get a handle to the default network. + #[allow(async_fn_in_trait)] + pub fn instance_network() -> Network { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/instance-network@0.2.4")] + unsafe extern "C" { + #[link_name = "instance-network"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + super::super::super::wasi::sockets::network::Network::from_handle( + ret as u32, + ) + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod udp { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Pollable = super::super::super::wasi::io::poll::Pollable; + pub type Network = super::super::super::wasi::sockets::network::Network; + pub type ErrorCode = super::super::super::wasi::sockets::network::ErrorCode; + pub type IpSocketAddress = super::super::super::wasi::sockets::network::IpSocketAddress; + pub type IpAddressFamily = super::super::super::wasi::sockets::network::IpAddressFamily; + /// A received datagram. + #[derive(Clone)] + pub struct IncomingDatagram { + /// The payload. + /// + /// Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + pub data: _rt::Vec, + /// The source address. + /// + /// This field is guaranteed to match the remote address the stream was initialized with, if any. + /// + /// Equivalent to the `src_addr` out parameter of `recvfrom`. + pub remote_address: IpSocketAddress, + } + impl ::core::fmt::Debug for IncomingDatagram { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("IncomingDatagram") + .field("data", &self.data) + .field("remote-address", &self.remote_address) + .finish() + } + } + /// A datagram to be sent out. + #[derive(Clone)] + pub struct OutgoingDatagram { + /// The payload. + pub data: _rt::Vec, + /// The destination address. + /// + /// The requirements on this field depend on how the stream was initialized: + /// - with a remote address: this field must be None or match the stream's remote address exactly. + /// - without a remote address: this field is required. + /// + /// If this value is None, the send operation is equivalent to `send` in POSIX. Otherwise it is equivalent to `sendto`. + pub remote_address: Option, + } + impl ::core::fmt::Debug for OutgoingDatagram { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("OutgoingDatagram") + .field("data", &self.data) + .field("remote-address", &self.remote_address) + .finish() + } + } + /// A UDP socket handle. + #[derive(Debug)] + #[repr(transparent)] + pub struct UdpSocket { + handle: _rt::Resource, + } + impl UdpSocket { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for UdpSocket { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]udp-socket"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + #[derive(Debug)] + #[repr(transparent)] + pub struct IncomingDatagramStream { + handle: _rt::Resource, + } + impl IncomingDatagramStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for IncomingDatagramStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]incoming-datagram-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + #[derive(Debug)] + #[repr(transparent)] + pub struct OutgoingDatagramStream { + handle: _rt::Resource, + } + impl OutgoingDatagramStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for OutgoingDatagramStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]outgoing-datagram-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the port is zero, the socket will be bound to a random free port. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn start_bind( + &self, + network: &Network, + local_address: IpSocketAddress, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + use super::super::super::wasi::sockets::network::IpSocketAddress as V4; + let ( + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ) = match local_address { + V4::Ipv4(e) => { + let super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: port0, + address: address0, + } = e; + let (t1_0, t1_1, t1_2, t1_3) = address0; + ( + 0i32, + _rt::as_i32(port0), + _rt::as_i32(t1_0), + _rt::as_i32(t1_1), + _rt::as_i32(t1_2), + _rt::as_i32(t1_3), + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + ) + } + V4::Ipv6(e) => { + let super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: port2, + flow_info: flow_info2, + address: address2, + scope_id: scope_id2, + } = e; + let (t3_0, t3_1, t3_2, t3_3, t3_4, t3_5, t3_6, t3_7) = address2; + ( + 1i32, + _rt::as_i32(port2), + _rt::as_i32(flow_info2), + _rt::as_i32(t3_0), + _rt::as_i32(t3_1), + _rt::as_i32(t3_2), + _rt::as_i32(t3_3), + _rt::as_i32(t3_4), + _rt::as_i32(t3_5), + _rt::as_i32(t3_6), + _rt::as_i32(t3_7), + _rt::as_i32(scope_id2), + ) + } + }; + let ptr6 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.start-bind"] + fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import7( + (self).handle() as i32, + (network).handle() as i32, + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ptr6, + ); + let l8 = i32::from(*ptr6.add(0).cast::()); + let result10 = match l8 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l9 = i32::from(*ptr6.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l9 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result10 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn finish_bind(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.finish-bind"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Set up inbound & outbound communication channels, optionally to a specific peer. + /// + /// This function only changes the local socket configuration and does not generate any network traffic. + /// On success, the `remote-address` of the socket is updated. The `local-address` may be updated as well, + /// based on the best network path to `remote-address`. + /// + /// When a `remote-address` is provided, the returned streams are limited to communicating with that specific peer: + /// - `send` can only be used to send to this destination. + /// - `receive` will only return datagrams sent from the provided `remote-address`. + /// + /// This method may be called multiple times on the same socket to change its association, but + /// only the most recently returned pair of streams will be operational. Implementations may trap if + /// the streams returned by a previous invocation haven't been dropped yet before calling `stream` again. + /// + /// The POSIX equivalent in pseudo-code is: + /// ```text + /// if (was previously connected) { + /// connect(s, AF_UNSPEC) + /// } + /// if (remote_address is Some) { + /// connect(s, remote_address) + /// } + /// ``` + /// + /// Unlike in POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-state`: The socket is not bound. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn stream( + &self, + remote_address: Option, + ) -> Result< + (IncomingDatagramStream, OutgoingDatagramStream), + ErrorCode, + > { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ( + result6_0, + result6_1, + result6_2, + result6_3, + result6_4, + result6_5, + result6_6, + result6_7, + result6_8, + result6_9, + result6_10, + result6_11, + result6_12, + ) = match remote_address { + Some(e) => { + use super::super::super::wasi::sockets::network::IpSocketAddress as V4; + let ( + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ) = match e { + V4::Ipv4(e) => { + let super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: port0, + address: address0, + } = e; + let (t1_0, t1_1, t1_2, t1_3) = address0; + ( + 0i32, + _rt::as_i32(port0), + _rt::as_i32(t1_0), + _rt::as_i32(t1_1), + _rt::as_i32(t1_2), + _rt::as_i32(t1_3), + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + ) + } + V4::Ipv6(e) => { + let super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: port2, + flow_info: flow_info2, + address: address2, + scope_id: scope_id2, + } = e; + let (t3_0, t3_1, t3_2, t3_3, t3_4, t3_5, t3_6, t3_7) = address2; + ( + 1i32, + _rt::as_i32(port2), + _rt::as_i32(flow_info2), + _rt::as_i32(t3_0), + _rt::as_i32(t3_1), + _rt::as_i32(t3_2), + _rt::as_i32(t3_3), + _rt::as_i32(t3_4), + _rt::as_i32(t3_5), + _rt::as_i32(t3_6), + _rt::as_i32(t3_7), + _rt::as_i32(scope_id2), + ) + } + }; + ( + 1i32, + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ) + } + None => { + ( + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + ) + } + }; + let ptr7 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.stream"] + fn wit_import8( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import8( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import8( + (self).handle() as i32, + result6_0, + result6_1, + result6_2, + result6_3, + result6_4, + result6_5, + result6_6, + result6_7, + result6_8, + result6_9, + result6_10, + result6_11, + result6_12, + ptr7, + ); + let l9 = i32::from(*ptr7.add(0).cast::()); + let result13 = match l9 { + 0 => { + let e = { + let l10 = *ptr7.add(4).cast::(); + let l11 = *ptr7.add(8).cast::(); + ( + IncomingDatagramStream::from_handle(l10 as u32), + OutgoingDatagramStream::from_handle(l11 as u32), + ) + }; + Ok(e) + } + 1 => { + let e = { + let l12 = i32::from(*ptr7.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l12 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result13 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Get the current bound address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn local_address(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 36]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 36], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.local-address"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result22 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + use super::super::super::wasi::sockets::network::IpSocketAddress as V20; + let v20 = match l3 { + 0 => { + let e20 = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let l5 = i32::from(*ptr0.add(10).cast::()); + let l6 = i32::from(*ptr0.add(11).cast::()); + let l7 = i32::from(*ptr0.add(12).cast::()); + let l8 = i32::from(*ptr0.add(13).cast::()); + super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: l4 as u16, + address: (l5 as u8, l6 as u8, l7 as u8, l8 as u8), + } + }; + V20::Ipv4(e20) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e20 = { + let l9 = i32::from(*ptr0.add(8).cast::()); + let l10 = *ptr0.add(12).cast::(); + let l11 = i32::from(*ptr0.add(16).cast::()); + let l12 = i32::from(*ptr0.add(18).cast::()); + let l13 = i32::from(*ptr0.add(20).cast::()); + let l14 = i32::from(*ptr0.add(22).cast::()); + let l15 = i32::from(*ptr0.add(24).cast::()); + let l16 = i32::from(*ptr0.add(26).cast::()); + let l17 = i32::from(*ptr0.add(28).cast::()); + let l18 = i32::from(*ptr0.add(30).cast::()); + let l19 = *ptr0.add(32).cast::(); + super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: l9 as u16, + flow_info: l10 as u32, + address: ( + l11 as u16, + l12 as u16, + l13 as u16, + l14 as u16, + l15 as u16, + l16 as u16, + l17 as u16, + l18 as u16, + ), + scope_id: l19 as u32, + } + }; + V20::Ipv6(e20) + } + }; + v20 + }; + Ok(e) + } + 1 => { + let e = { + let l21 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l21 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result22 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Get the address the socket is currently streaming to. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not streaming to a specific remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn remote_address(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 36]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 36], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.remote-address"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result22 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + use super::super::super::wasi::sockets::network::IpSocketAddress as V20; + let v20 = match l3 { + 0 => { + let e20 = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let l5 = i32::from(*ptr0.add(10).cast::()); + let l6 = i32::from(*ptr0.add(11).cast::()); + let l7 = i32::from(*ptr0.add(12).cast::()); + let l8 = i32::from(*ptr0.add(13).cast::()); + super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: l4 as u16, + address: (l5 as u8, l6 as u8, l7 as u8, l8 as u8), + } + }; + V20::Ipv4(e20) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e20 = { + let l9 = i32::from(*ptr0.add(8).cast::()); + let l10 = *ptr0.add(12).cast::(); + let l11 = i32::from(*ptr0.add(16).cast::()); + let l12 = i32::from(*ptr0.add(18).cast::()); + let l13 = i32::from(*ptr0.add(20).cast::()); + let l14 = i32::from(*ptr0.add(22).cast::()); + let l15 = i32::from(*ptr0.add(24).cast::()); + let l16 = i32::from(*ptr0.add(26).cast::()); + let l17 = i32::from(*ptr0.add(28).cast::()); + let l18 = i32::from(*ptr0.add(30).cast::()); + let l19 = *ptr0.add(32).cast::(); + super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: l9 as u16, + flow_info: l10 as u32, + address: ( + l11 as u16, + l12 as u16, + l13 as u16, + l14 as u16, + l15 as u16, + l16 as u16, + l17 as u16, + l18 as u16, + ), + scope_id: l19 as u32, + } + }; + V20::Ipv6(e20) + } + }; + v20 + }; + Ok(e) + } + 1 => { + let e = { + let l21 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l21 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result22 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + #[allow(async_fn_in_trait)] + pub fn address_family(&self) -> IpAddressFamily { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.address-family"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::sockets::network::IpAddressFamily::_lift( + ret as u8, + ) + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + #[allow(async_fn_in_trait)] + pub fn unicast_hop_limit(&self) -> Result { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.unicast-hop-limit"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + l3 as u8 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_unicast_hop_limit(&self, value: u8) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.set-unicast-hop-limit"] + fn wit_import1(_: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i32(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + #[allow(async_fn_in_trait)] + pub fn receive_buffer_size(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.receive-buffer-size"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_receive_buffer_size( + &self, + value: u64, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.set-receive-buffer-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn send_buffer_size(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.send-buffer-size"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_send_buffer_size(&self, value: u64) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.set-send-buffer-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl UdpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the socket is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]udp-socket.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl IncomingDatagramStream { + #[allow(unused_unsafe, clippy::all)] + /// Receive messages on the socket. + /// + /// This function attempts to receive up to `max-results` datagrams on the socket without blocking. + /// The returned list may contain fewer elements than requested, but never more. + /// + /// This function returns successfully with an empty list when either: + /// - `max-results` is 0, or: + /// - `max-results` is greater than 0, but no results are immediately available. + /// This function never returns `error(would-block)`. + /// + /// # Typical errors + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn receive( + &self, + max_results: u64, + ) -> Result<_rt::Vec, ErrorCode> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-datagram-stream.receive"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + _rt::as_i64(&max_results), + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result28 = match l2 { + 0 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base26 = l3; + let len26 = l4; + let mut result26 = _rt::Vec::with_capacity(len26); + for i in 0..len26 { + let base = base26 + .add(i * (32 + 2 * ::core::mem::size_of::<*const u8>())); + let e26 = { + let l5 = *base.add(0).cast::<*mut u8>(); + let l6 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let l8 = i32::from( + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + use super::super::super::wasi::sockets::network::IpSocketAddress as V25; + let v25 = match l8 { + 0 => { + let e25 = { + let l9 = i32::from( + *base + .add(4 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l10 = i32::from( + *base + .add(6 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l11 = i32::from( + *base + .add(7 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l12 = i32::from( + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l13 = i32::from( + *base + .add(9 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: l9 as u16, + address: (l10 as u8, l11 as u8, l12 as u8, l13 as u8), + } + }; + V25::Ipv4(e25) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e25 = { + let l14 = i32::from( + *base + .add(4 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l15 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let l16 = i32::from( + *base + .add(12 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l17 = i32::from( + *base + .add(14 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l18 = i32::from( + *base + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l19 = i32::from( + *base + .add(18 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l20 = i32::from( + *base + .add(20 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l21 = i32::from( + *base + .add(22 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l22 = i32::from( + *base + .add(24 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l23 = i32::from( + *base + .add(26 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l24 = *base + .add(28 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: l14 as u16, + flow_info: l15 as u32, + address: ( + l16 as u16, + l17 as u16, + l18 as u16, + l19 as u16, + l20 as u16, + l21 as u16, + l22 as u16, + l23 as u16, + ), + scope_id: l24 as u32, + } + }; + V25::Ipv6(e25) + } + }; + IncomingDatagram { + data: _rt::Vec::from_raw_parts(l5.cast(), len7, len7), + remote_address: v25, + } + }; + result26.push(e26); + } + _rt::cabi_dealloc( + base26, + len26 * (32 + 2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result26 + }; + Ok(e) + } + 1 => { + let e = { + let l27 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l27 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result28 + } + } + } + impl IncomingDatagramStream { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the stream is ready to receive again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-datagram-stream.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl OutgoingDatagramStream { + #[allow(unused_unsafe, clippy::all)] + /// Check readiness for sending. This function never blocks. + /// + /// Returns the number of datagrams permitted for the next call to `send`, + /// or an error. Calling `send` with more datagrams than this function has + /// permitted will trap. + /// + /// When this function returns ok(0), the `subscribe` pollable will + /// become ready when this function will report at least ok(1), or an + /// error. + /// + /// Never returns `would-block`. + #[allow(async_fn_in_trait)] + pub fn check_send(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-datagram-stream.check-send"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl OutgoingDatagramStream { + #[allow(unused_unsafe, clippy::all)] + /// Send messages on the socket. + /// + /// This function attempts to send all provided `datagrams` on the socket without blocking and + /// returns how many messages were actually sent (or queued for sending). This function never + /// returns `error(would-block)`. If none of the datagrams were able to be sent, `ok(0)` is returned. + /// + /// This function semantically behaves the same as iterating the `datagrams` list and sequentially + /// sending each individual datagram until either the end of the list has been reached or the first error occurred. + /// If at least one datagram has been sent successfully, this function never returns an error. + /// + /// If the input list is empty, the function returns `ok(0)`. + /// + /// Each call to `send` must be permitted by a preceding `check-send`. Implementations must trap if + /// either `check-send` was not called or `datagrams` contains more items than `check-send` permitted. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The socket is in "connected" mode and `remote-address` is `some` value that does not match the address passed to `stream`. (EISCONN) + /// - `invalid-argument`: The socket is not "connected" and no value for `remote-address` was provided. (EDESTADDRREQ) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn send( + &self, + datagrams: &[OutgoingDatagram], + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let vec7 = datagrams; + let len7 = vec7.len(); + let layout7 = _rt::alloc::Layout::from_size_align( + vec7.len() * (32 + 3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ) + .unwrap(); + let (result7, _cleanup7) = wit_bindgen::rt::Cleanup::new( + layout7, + ); + for (i, e) in vec7.into_iter().enumerate() { + let base = result7 + .add(i * (32 + 3 * ::core::mem::size_of::<*const u8>())); + { + let OutgoingDatagram { + data: data0, + remote_address: remote_address0, + } = e; + let vec1 = data0; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len1; + *base.add(0).cast::<*mut u8>() = ptr1.cast_mut(); + match remote_address0 { + Some(e) => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + use super::super::super::wasi::sockets::network::IpSocketAddress as V6; + match e { + V6::Ipv4(e) => { + *base + .add(4 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: port2, + address: address2, + } = e; + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(port2)) as u16; + let (t3_0, t3_1, t3_2, t3_3) = address2; + *base + .add(10 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t3_0)) as u8; + *base + .add(11 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t3_1)) as u8; + *base + .add(12 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t3_2)) as u8; + *base + .add(13 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t3_3)) as u8; + } + V6::Ipv6(e) => { + *base + .add(4 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: port4, + flow_info: flow_info4, + address: address4, + scope_id: scope_id4, + } = e; + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(port4)) as u16; + *base + .add(12 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(flow_info4); + let (t5_0, t5_1, t5_2, t5_3, t5_4, t5_5, t5_6, t5_7) = address4; + *base + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_0)) as u16; + *base + .add(18 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_1)) as u16; + *base + .add(20 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_2)) as u16; + *base + .add(22 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_3)) as u16; + *base + .add(24 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_4)) as u16; + *base + .add(26 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_5)) as u16; + *base + .add(28 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_6)) as u16; + *base + .add(30 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (_rt::as_i32(t5_7)) as u16; + *base + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(scope_id4); + } + } + } + None => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + }; + } + } + let ptr8 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-datagram-stream.send"] + fn wit_import9(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import9( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import9((self).handle() as i32, result7, len7, ptr8); + let l10 = i32::from(*ptr8.add(0).cast::()); + let result13 = match l10 { + 0 => { + let e = { + let l11 = *ptr8.add(8).cast::(); + l11 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l12 = i32::from(*ptr8.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l12 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result13 + } + } + } + impl OutgoingDatagramStream { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the stream is ready to send again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-datagram-stream.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod udp_create_socket { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type ErrorCode = super::super::super::wasi::sockets::network::ErrorCode; + pub type IpAddressFamily = super::super::super::wasi::sockets::network::IpAddressFamily; + pub type UdpSocket = super::super::super::wasi::sockets::udp::UdpSocket; + #[allow(unused_unsafe, clippy::all)] + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, + /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References: + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn create_udp_socket( + address_family: IpAddressFamily, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/udp-create-socket@0.2.4")] + unsafe extern "C" { + #[link_name = "create-udp-socket"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1(address_family.clone() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::sockets::udp::UdpSocket::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod tcp { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type InputStream = super::super::super::wasi::io::streams::InputStream; + pub type OutputStream = super::super::super::wasi::io::streams::OutputStream; + pub type Pollable = super::super::super::wasi::io::poll::Pollable; + pub type Duration = super::super::super::wasi::clocks::monotonic_clock::Duration; + pub type Network = super::super::super::wasi::sockets::network::Network; + pub type ErrorCode = super::super::super::wasi::sockets::network::ErrorCode; + pub type IpSocketAddress = super::super::super::wasi::sockets::network::IpSocketAddress; + pub type IpAddressFamily = super::super::super::wasi::sockets::network::IpAddressFamily; + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum ShutdownType { + /// Similar to `SHUT_RD` in POSIX. + Receive, + /// Similar to `SHUT_WR` in POSIX. + Send, + /// Similar to `SHUT_RDWR` in POSIX. + Both, + } + impl ::core::fmt::Debug for ShutdownType { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + ShutdownType::Receive => { + f.debug_tuple("ShutdownType::Receive").finish() + } + ShutdownType::Send => { + f.debug_tuple("ShutdownType::Send").finish() + } + ShutdownType::Both => { + f.debug_tuple("ShutdownType::Both").finish() + } + } + } + } + impl ShutdownType { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> ShutdownType { + if !cfg!(debug_assertions) { + return unsafe { ::core::mem::transmute(val) }; + } + match val { + 0 => ShutdownType::Receive, + 1 => ShutdownType::Send, + 2 => ShutdownType::Both, + _ => panic!("invalid enum discriminant"), + } + } + } + /// A TCP socket resource. + /// + /// The socket can be in one of the following states: + /// - `unbound` + /// - `bind-in-progress` + /// - `bound` (See note below) + /// - `listen-in-progress` + /// - `listening` + /// - `connect-in-progress` + /// - `connected` + /// - `closed` + /// See + /// for more information. + /// + /// Note: Except where explicitly mentioned, whenever this documentation uses + /// the term "bound" without backticks it actually means: in the `bound` state *or higher*. + /// (i.e. `bound`, `listen-in-progress`, `listening`, `connect-in-progress` or `connected`) + /// + /// In addition to the general error codes documented on the + /// `network::error-code` type, TCP socket methods may always return + /// `error(invalid-state)` when in the `closed` state. + #[derive(Debug)] + #[repr(transparent)] + pub struct TcpSocket { + handle: _rt::Resource, + } + impl TcpSocket { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for TcpSocket { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]tcp-socket"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// Bind can be attempted multiple times on the same socket, even with + /// different arguments on each iteration. But never concurrently and + /// only as long as the previous bind failed. Once a bind succeeds, the + /// binding can't be changed anymore. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) + /// - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT + /// state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR + /// socket option should be set implicitly on all platforms, except on Windows where this is the default behavior + /// and SO_REUSEADDR performs something different entirely. + /// + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn start_bind( + &self, + network: &Network, + local_address: IpSocketAddress, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + use super::super::super::wasi::sockets::network::IpSocketAddress as V4; + let ( + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ) = match local_address { + V4::Ipv4(e) => { + let super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: port0, + address: address0, + } = e; + let (t1_0, t1_1, t1_2, t1_3) = address0; + ( + 0i32, + _rt::as_i32(port0), + _rt::as_i32(t1_0), + _rt::as_i32(t1_1), + _rt::as_i32(t1_2), + _rt::as_i32(t1_3), + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + ) + } + V4::Ipv6(e) => { + let super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: port2, + flow_info: flow_info2, + address: address2, + scope_id: scope_id2, + } = e; + let (t3_0, t3_1, t3_2, t3_3, t3_4, t3_5, t3_6, t3_7) = address2; + ( + 1i32, + _rt::as_i32(port2), + _rt::as_i32(flow_info2), + _rt::as_i32(t3_0), + _rt::as_i32(t3_1), + _rt::as_i32(t3_2), + _rt::as_i32(t3_3), + _rt::as_i32(t3_4), + _rt::as_i32(t3_5), + _rt::as_i32(t3_6), + _rt::as_i32(t3_7), + _rt::as_i32(scope_id2), + ) + } + }; + let ptr6 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.start-bind"] + fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import7( + (self).handle() as i32, + (network).handle() as i32, + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ptr6, + ); + let l8 = i32::from(*ptr6.add(0).cast::()); + let result10 = match l8 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l9 = i32::from(*ptr6.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l9 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result10 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn finish_bind(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.finish-bind"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the `connected` state. + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// After a failed connection attempt, the socket will be in the `closed` + /// state and the only valid action left is to `drop` the socket. A single + /// socket can not be used to connect more than once. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) + /// - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN) + /// - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows) + /// - `timeout`: Connection timed out. (ETIMEDOUT) + /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) + /// - `connection-reset`: The connection was reset. (ECONNRESET) + /// - `connection-aborted`: The connection was aborted. (ECONNABORTED) + /// - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `not-in-progress`: A connect operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// The POSIX equivalent of `start-connect` is the regular `connect` syscall. + /// Because all WASI sockets are non-blocking this is expected to return + /// EINPROGRESS, which should be translated to `ok()` in WASI. + /// + /// The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT` + /// with a timeout of 0 on the socket descriptor. Followed by a check for + /// the `SO_ERROR` socket option, in case the poll signaled readiness. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn start_connect( + &self, + network: &Network, + remote_address: IpSocketAddress, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + use super::super::super::wasi::sockets::network::IpSocketAddress as V4; + let ( + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ) = match remote_address { + V4::Ipv4(e) => { + let super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: port0, + address: address0, + } = e; + let (t1_0, t1_1, t1_2, t1_3) = address0; + ( + 0i32, + _rt::as_i32(port0), + _rt::as_i32(t1_0), + _rt::as_i32(t1_1), + _rt::as_i32(t1_2), + _rt::as_i32(t1_3), + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + 0i32, + ) + } + V4::Ipv6(e) => { + let super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: port2, + flow_info: flow_info2, + address: address2, + scope_id: scope_id2, + } = e; + let (t3_0, t3_1, t3_2, t3_3, t3_4, t3_5, t3_6, t3_7) = address2; + ( + 1i32, + _rt::as_i32(port2), + _rt::as_i32(flow_info2), + _rt::as_i32(t3_0), + _rt::as_i32(t3_1), + _rt::as_i32(t3_2), + _rt::as_i32(t3_3), + _rt::as_i32(t3_4), + _rt::as_i32(t3_5), + _rt::as_i32(t3_6), + _rt::as_i32(t3_7), + _rt::as_i32(scope_id2), + ) + } + }; + let ptr6 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.start-connect"] + fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import7( + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import7( + (self).handle() as i32, + (network).handle() as i32, + result5_0, + result5_1, + result5_2, + result5_3, + result5_4, + result5_5, + result5_6, + result5_7, + result5_8, + result5_9, + result5_10, + result5_11, + ptr6, + ); + let l8 = i32::from(*ptr6.add(0).cast::()); + let result10 = match l8 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l9 = i32::from(*ptr6.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l9 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result10 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn finish_connect( + &self, + ) -> Result<(InputStream, OutputStream), ErrorCode> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 12]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 12], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.finish-connect"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + let l4 = *ptr0.add(8).cast::(); + ( + super::super::super::wasi::io::streams::InputStream::from_handle( + l3 as u32, + ), + super::super::super::wasi::io::streams::OutputStream::from_handle( + l4 as u32, + ), + ) + }; + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l5 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Start listening for new connections. + /// + /// Transitions the socket into the `listening` state. + /// + /// Unlike POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the `listening` state. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) + /// - `not-in-progress`: A listen operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the listen operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `listen` as part of either `start-listen` or `finish-listen`. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn start_listen(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.start-listen"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn finish_listen(&self) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.finish-listen"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Accept a new client socket. + /// + /// The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `keep-alive-enabled` + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// - `hop-limit` + /// - `receive-buffer-size` + /// - `send-buffer-size` + /// + /// On success, this function returns the newly accepted client socket along with + /// a pair of streams that can be used to read & write to the connection. + /// + /// # Typical errors + /// - `invalid-state`: Socket is not in the `listening` state. (EINVAL) + /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) + /// - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn accept( + &self, + ) -> Result<(TcpSocket, InputStream, OutputStream), ErrorCode> { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.accept"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result7 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + let l4 = *ptr0.add(8).cast::(); + let l5 = *ptr0.add(12).cast::(); + ( + TcpSocket::from_handle(l3 as u32), + super::super::super::wasi::io::streams::InputStream::from_handle( + l4 as u32, + ), + super::super::super::wasi::io::streams::OutputStream::from_handle( + l5 as u32, + ), + ) + }; + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l6 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Get the bound local address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn local_address(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 36]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 36], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.local-address"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result22 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + use super::super::super::wasi::sockets::network::IpSocketAddress as V20; + let v20 = match l3 { + 0 => { + let e20 = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let l5 = i32::from(*ptr0.add(10).cast::()); + let l6 = i32::from(*ptr0.add(11).cast::()); + let l7 = i32::from(*ptr0.add(12).cast::()); + let l8 = i32::from(*ptr0.add(13).cast::()); + super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: l4 as u16, + address: (l5 as u8, l6 as u8, l7 as u8, l8 as u8), + } + }; + V20::Ipv4(e20) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e20 = { + let l9 = i32::from(*ptr0.add(8).cast::()); + let l10 = *ptr0.add(12).cast::(); + let l11 = i32::from(*ptr0.add(16).cast::()); + let l12 = i32::from(*ptr0.add(18).cast::()); + let l13 = i32::from(*ptr0.add(20).cast::()); + let l14 = i32::from(*ptr0.add(22).cast::()); + let l15 = i32::from(*ptr0.add(24).cast::()); + let l16 = i32::from(*ptr0.add(26).cast::()); + let l17 = i32::from(*ptr0.add(28).cast::()); + let l18 = i32::from(*ptr0.add(30).cast::()); + let l19 = *ptr0.add(32).cast::(); + super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: l9 as u16, + flow_info: l10 as u32, + address: ( + l11 as u16, + l12 as u16, + l13 as u16, + l14 as u16, + l15 as u16, + l16 as u16, + l17 as u16, + l18 as u16, + ), + scope_id: l19 as u32, + } + }; + V20::Ipv6(e20) + } + }; + v20 + }; + Ok(e) + } + 1 => { + let e = { + let l21 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l21 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result22 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn remote_address(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 36]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 36], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.remote-address"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result22 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(4).cast::()); + use super::super::super::wasi::sockets::network::IpSocketAddress as V20; + let v20 = match l3 { + 0 => { + let e20 = { + let l4 = i32::from(*ptr0.add(8).cast::()); + let l5 = i32::from(*ptr0.add(10).cast::()); + let l6 = i32::from(*ptr0.add(11).cast::()); + let l7 = i32::from(*ptr0.add(12).cast::()); + let l8 = i32::from(*ptr0.add(13).cast::()); + super::super::super::wasi::sockets::network::Ipv4SocketAddress { + port: l4 as u16, + address: (l5 as u8, l6 as u8, l7 as u8, l8 as u8), + } + }; + V20::Ipv4(e20) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e20 = { + let l9 = i32::from(*ptr0.add(8).cast::()); + let l10 = *ptr0.add(12).cast::(); + let l11 = i32::from(*ptr0.add(16).cast::()); + let l12 = i32::from(*ptr0.add(18).cast::()); + let l13 = i32::from(*ptr0.add(20).cast::()); + let l14 = i32::from(*ptr0.add(22).cast::()); + let l15 = i32::from(*ptr0.add(24).cast::()); + let l16 = i32::from(*ptr0.add(26).cast::()); + let l17 = i32::from(*ptr0.add(28).cast::()); + let l18 = i32::from(*ptr0.add(30).cast::()); + let l19 = *ptr0.add(32).cast::(); + super::super::super::wasi::sockets::network::Ipv6SocketAddress { + port: l9 as u16, + flow_info: l10 as u32, + address: ( + l11 as u16, + l12 as u16, + l13 as u16, + l14 as u16, + l15 as u16, + l16 as u16, + l17 as u16, + l18 as u16, + ), + scope_id: l19 as u32, + } + }; + V20::Ipv6(e20) + } + }; + v20 + }; + Ok(e) + } + 1 => { + let e = { + let l21 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l21 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result22 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Whether the socket is in the `listening` state. + /// + /// Equivalent to the SO_ACCEPTCONN socket option. + #[allow(async_fn_in_trait)] + pub fn is_listening(&self) -> bool { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.is-listening"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + _rt::bool_lift(ret as u8) + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + #[allow(async_fn_in_trait)] + pub fn address_family(&self) -> IpAddressFamily { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.address-family"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::sockets::network::IpAddressFamily::_lift( + ret as u8, + ) + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Hints the desired listen queue size. Implementations are free to ignore this. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// + /// # Typical errors + /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. + /// - `invalid-argument`: (set) The provided value was 0. + /// - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state. + #[allow(async_fn_in_trait)] + pub fn set_listen_backlog_size( + &self, + value: u64, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-listen-backlog-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Enables or disables keepalive. + /// + /// The keepalive behavior can be adjusted using: + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// These properties can be configured while `keep-alive-enabled` is false, but only come into effect when `keep-alive-enabled` is true. + /// + /// Equivalent to the SO_KEEPALIVE socket option. + #[allow(async_fn_in_trait)] + pub fn keep_alive_enabled(&self) -> Result { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.keep-alive-enabled"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + _rt::bool_lift(l3 as u8) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_keep_alive_enabled( + &self, + value: bool, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-keep-alive-enabled"] + fn wit_import1(_: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: *mut u8) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + match &value { + true => 1, + false => 0, + }, + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Amount of time the connection has to be idle before TCP starts sending keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS) + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + #[allow(async_fn_in_trait)] + pub fn keep_alive_idle_time(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.keep-alive-idle-time"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_keep_alive_idle_time( + &self, + value: Duration, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-keep-alive-idle-time"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// The time between keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPINTVL socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + #[allow(async_fn_in_trait)] + pub fn keep_alive_interval(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.keep-alive-interval"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_keep_alive_interval( + &self, + value: Duration, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-keep-alive-interval"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// The maximum amount of keepalive packets TCP should send before aborting the connection. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPCNT socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + #[allow(async_fn_in_trait)] + pub fn keep_alive_count(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.keep-alive-count"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + l3 as u32 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_keep_alive_count(&self, value: u32) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-keep-alive-count"] + fn wit_import1(_: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i32(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + #[allow(async_fn_in_trait)] + pub fn hop_limit(&self) -> Result { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.hop-limit"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + l3 as u8 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_hop_limit(&self, value: u8) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-hop-limit"] + fn wit_import1(_: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i32(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + #[allow(async_fn_in_trait)] + pub fn receive_buffer_size(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.receive-buffer-size"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_receive_buffer_size( + &self, + value: u64, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-receive-buffer-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn send_buffer_size(&self) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.send-buffer-size"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(8).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + #[allow(async_fn_in_trait)] + pub fn set_send_buffer_size(&self, value: u64) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.set-send-buffer-size"] + fn wit_import1(_: i32, _: i64, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i64, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, _rt::as_i64(&value), ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which can be used to poll for, or block on, + /// completion of any of the asynchronous operations of this socket. + /// + /// When `finish-bind`, `finish-listen`, `finish-connect` or `accept` + /// return `error(would-block)`, this pollable can be used to wait for + /// their success or failure, after which the method can be retried. + /// + /// The pollable is not limited to the async operation that happens to be + /// in progress at the time of calling `subscribe` (if any). Theoretically, + /// `subscribe` only has to be called once per socket and can then be + /// (re)used for the remainder of the socket's lifetime. + /// + /// See + /// for more information. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl TcpSocket { + #[allow(unused_unsafe, clippy::all)] + /// Initiate a graceful shutdown. + /// + /// - `receive`: The socket is not expecting to receive any data from + /// the peer. The `input-stream` associated with this socket will be + /// closed. Any data still in the receive queue at time of calling + /// this method will be discarded. + /// - `send`: The socket has no more data to send to the peer. The `output-stream` + /// associated with this socket will be closed and a FIN packet will be sent. + /// - `both`: Same effect as `receive` & `send` combined. + /// + /// This function is idempotent; shutting down a direction more than once + /// has no effect and returns `ok`. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn shutdown( + &self, + shutdown_type: ShutdownType, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]tcp-socket.shutdown"] + fn wit_import1(_: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: *mut u8) { + unreachable!() + } + wit_import1( + (self).handle() as i32, + shutdown_type.clone() as i32, + ptr0, + ); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(1).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l3 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod tcp_create_socket { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type ErrorCode = super::super::super::wasi::sockets::network::ErrorCode; + pub type IpAddressFamily = super::super::super::wasi::sockets::network::IpAddressFamily; + pub type TcpSocket = super::super::super::wasi::sockets::tcp::TcpSocket; + #[allow(unused_unsafe, clippy::all)] + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` + /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn create_tcp_socket( + address_family: IpAddressFamily, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/tcp-create-socket@0.2.4")] + unsafe extern "C" { + #[link_name = "create-tcp-socket"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1(address_family.clone() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result5 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::wasi::sockets::tcp::TcpSocket::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l4 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result5 + } + } + } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod ip_name_lookup { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Pollable = super::super::super::wasi::io::poll::Pollable; + pub type Network = super::super::super::wasi::sockets::network::Network; + pub type ErrorCode = super::super::super::wasi::sockets::network::ErrorCode; + pub type IpAddress = super::super::super::wasi::sockets::network::IpAddress; + #[derive(Debug)] + #[repr(transparent)] + pub struct ResolveAddressStream { + handle: _rt::Resource, + } + impl ResolveAddressStream { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for ResolveAddressStream { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/ip-name-lookup@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]resolve-address-stream"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + #[allow(unused_unsafe, clippy::all)] + /// Resolve an internet host name to a list of IP addresses. + /// + /// Unicode domain names are automatically converted to ASCII using IDNA encoding. + /// If the input is an IP address string, the address is parsed and returned + /// as-is without making any external requests. + /// + /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. + /// + /// This function never blocks. It either immediately fails or immediately + /// returns successfully with a `resolve-address-stream` that can be used + /// to (asynchronously) fetch the results. + /// + /// # Typical errors + /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. + /// + /// # References: + /// - + /// - + /// - + /// - + #[allow(async_fn_in_trait)] + pub fn resolve_addresses( + network: &Network, + name: &str, + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 8]); + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/ip-name-lookup@0.2.4")] + unsafe extern "C" { + #[link_name = "resolve-addresses"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((network).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result6 = match l3 { + 0 => { + let e = { + let l4 = *ptr1.add(4).cast::(); + ResolveAddressStream::from_handle(l4 as u32) + }; + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr1.add(4).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l5 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + impl ResolveAddressStream { + #[allow(unused_unsafe, clippy::all)] + /// Returns the next address from the resolver. + /// + /// This function should be called multiple times. On each call, it will + /// return the next address in connection order preference. If all + /// addresses have been exhausted, this function returns `none`. + /// + /// This function never returns IPv4-mapped IPv6 addresses. + /// + /// # Typical errors + /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) + /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) + /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) + /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) + #[allow(async_fn_in_trait)] + pub fn resolve_next_address( + &self, + ) -> Result, ErrorCode> { + unsafe { + #[repr(align(2))] + struct RetArea([::core::mem::MaybeUninit; 22]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 22], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/ip-name-lookup@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]resolve-address-stream.resolve-next-address"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result19 = match l2 { + 0 => { + let e = { + let l3 = i32::from(*ptr0.add(2).cast::()); + match l3 { + 0 => None, + 1 => { + let e = { + let l4 = i32::from(*ptr0.add(4).cast::()); + use super::super::super::wasi::sockets::network::IpAddress as V17; + let v17 = match l4 { + 0 => { + let e17 = { + let l5 = i32::from(*ptr0.add(6).cast::()); + let l6 = i32::from(*ptr0.add(7).cast::()); + let l7 = i32::from(*ptr0.add(8).cast::()); + let l8 = i32::from(*ptr0.add(9).cast::()); + (l5 as u8, l6 as u8, l7 as u8, l8 as u8) + }; + V17::Ipv4(e17) + } + n => { + debug_assert_eq!(n, 1, "invalid enum discriminant"); + let e17 = { + let l9 = i32::from(*ptr0.add(6).cast::()); + let l10 = i32::from(*ptr0.add(8).cast::()); + let l11 = i32::from(*ptr0.add(10).cast::()); + let l12 = i32::from(*ptr0.add(12).cast::()); + let l13 = i32::from(*ptr0.add(14).cast::()); + let l14 = i32::from(*ptr0.add(16).cast::()); + let l15 = i32::from(*ptr0.add(18).cast::()); + let l16 = i32::from(*ptr0.add(20).cast::()); + ( + l9 as u16, + l10 as u16, + l11 as u16, + l12 as u16, + l13 as u16, + l14 as u16, + l15 as u16, + l16 as u16, + ) + }; + V17::Ipv6(e17) + } + }; + v17 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Ok(e) + } + 1 => { + let e = { + let l18 = i32::from(*ptr0.add(2).cast::()); + super::super::super::wasi::sockets::network::ErrorCode::_lift( + l18 as u8, + ) + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result19 + } + } + } + impl ResolveAddressStream { + #[allow(unused_unsafe, clippy::all)] + /// Create a `pollable` which will resolve once the stream is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:sockets/ip-name-lookup@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]resolve-address-stream.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::wasi::io::poll::Pollable::from_handle( + ret as u32, + ) + } + } + } + } + } +} +#[rustfmt::skip] +mod _rt { + #![allow(dead_code, clippy::all)] + pub use alloc_crate::vec::Vec; + pub use alloc_crate::string::String; + pub unsafe fn string_lift(bytes: Vec) -> String { + if cfg!(debug_assertions) { + String::from_utf8(bytes).unwrap() + } else { + unsafe { String::from_utf8_unchecked(bytes) } + } + } + pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) { + if size == 0 { + return; + } + unsafe { + let layout = alloc::Layout::from_size_align_unchecked(size, align); + alloc::dealloc(ptr, layout); + } + } + pub unsafe fn invalid_enum_discriminant() -> T { + if cfg!(debug_assertions) { + panic!("invalid enum discriminant") + } else { + unsafe { core::hint::unreachable_unchecked() } + } + } + use core::fmt; + use core::marker; + use core::sync::atomic::{AtomicU32, Ordering::Relaxed}; + /// A type which represents a component model resource, either imported or + /// exported into this component. + /// + /// This is a low-level wrapper which handles the lifetime of the resource + /// (namely this has a destructor). The `T` provided defines the component model + /// intrinsics that this wrapper uses. + /// + /// One of the chief purposes of this type is to provide `Deref` implementations + /// to access the underlying data when it is owned. + /// + /// This type is primarily used in generated code for exported and imported + /// resources. + #[repr(transparent)] + pub struct Resource { + handle: AtomicU32, + _marker: marker::PhantomData, + } + /// A trait which all wasm resources implement, namely providing the ability to + /// drop a resource. + /// + /// This generally is implemented by generated code, not user-facing code. + #[allow(clippy::missing_safety_doc)] + pub unsafe trait WasmResource { + /// Invokes the `[resource-drop]...` intrinsic. + unsafe fn drop(handle: u32); + } + impl Resource { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + debug_assert!(handle != 0 && handle != u32::MAX); + Self { + handle: AtomicU32::new(handle), + _marker: marker::PhantomData, + } + } + /// Takes ownership of the handle owned by `resource`. + /// + /// Note that this ideally would be `into_handle` taking `Resource` by + /// ownership. The code generator does not enable that in all situations, + /// unfortunately, so this is provided instead. + /// + /// Also note that `take_handle` is in theory only ever called on values + /// owned by a generated function. For example a generated function might + /// take `Resource` as an argument but then call `take_handle` on a + /// reference to that argument. In that sense the dynamic nature of + /// `take_handle` should only be exposed internally to generated code, not + /// to user code. + #[doc(hidden)] + pub fn take_handle(resource: &Resource) -> u32 { + resource.handle.swap(u32::MAX, Relaxed) + } + #[doc(hidden)] + pub fn handle(resource: &Resource) -> u32 { + resource.handle.load(Relaxed) + } + } + impl fmt::Debug for Resource { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Resource").field("handle", &self.handle).finish() + } + } + impl Drop for Resource { + fn drop(&mut self) { + unsafe { + match self.handle.load(Relaxed) { + u32::MAX => {} + other => T::drop(other), + } + } + } + } + pub unsafe fn bool_lift(val: u8) -> bool { + if cfg!(debug_assertions) { + match val { + 0 => false, + 1 => true, + _ => panic!("invalid bool discriminant"), + } + } else { + val != 0 + } + } + pub use alloc_crate::alloc; + pub fn as_i64(t: T) -> i64 { + t.as_i64() + } + pub trait AsI64 { + fn as_i64(self) -> i64; + } + impl<'a, T: Copy + AsI64> AsI64 for &'a T { + fn as_i64(self) -> i64 { + (*self).as_i64() + } + } + impl AsI64 for i64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + impl AsI64 for u64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + pub trait AsI32 { + fn as_i32(self) -> i32; + } + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + extern crate alloc as alloc_crate; +} +#[rustfmt::skip] +#[cfg(target_arch = "wasm32")] + +#[cfg_attr(feature = "rustc-dep-of-std", unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:cli@0.2.4:imports:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-in-libstd"))] +#[cfg_attr(not(feature = "rustc-dep-of-std"), unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:cli@0.2.4:imports:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io"))] + +#[doc(hidden)] +#[allow(clippy::octal_escapes)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 10730] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xecR\x01A\x02\x01AG\x01\ +B\x0a\x01o\x02ss\x01p\0\x01@\0\0\x01\x04\0\x0fget-environment\x01\x02\x01ps\x01@\ +\0\0\x03\x04\0\x0dget-arguments\x01\x04\x01ks\x01@\0\0\x05\x04\0\x0binitial-cwd\x01\ +\x06\x03\0\x1awasi:cli/environment@0.2.4\x05\0\x01B\x03\x01j\0\0\x01@\x01\x06sta\ +tus\0\x01\0\x04\0\x04exit\x01\x01\x03\0\x13wasi:cli/exit@0.2.4\x05\x01\x01B\x04\x04\ +\0\x05error\x03\x01\x01h\0\x01@\x01\x04self\x01\0s\x04\0\x1d[method]error.to-deb\ +ug-string\x01\x02\x03\0\x13wasi:io/error@0.2.4\x05\x02\x01B\x0a\x04\0\x08pollabl\ +e\x03\x01\x01h\0\x01@\x01\x04self\x01\0\x7f\x04\0\x16[method]pollable.ready\x01\x02\ +\x01@\x01\x04self\x01\x01\0\x04\0\x16[method]pollable.block\x01\x03\x01p\x01\x01\ +py\x01@\x01\x02in\x04\0\x05\x04\0\x04poll\x01\x06\x03\0\x12wasi:io/poll@0.2.4\x05\ +\x03\x02\x03\0\x02\x05error\x02\x03\0\x03\x08pollable\x01B(\x02\x03\x02\x01\x04\x04\ +\0\x05error\x03\0\0\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x02\x01i\x01\x01\ +q\x02\x15last-operation-failed\x01\x04\0\x06closed\0\0\x04\0\x0cstream-error\x03\ +\0\x05\x04\0\x0cinput-stream\x03\x01\x04\0\x0doutput-stream\x03\x01\x01h\x07\x01\ +p}\x01j\x01\x0a\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0b\x04\0\x19[method]inpu\ +t-stream.read\x01\x0c\x04\0\"[method]input-stream.blocking-read\x01\x0c\x01j\x01\ +w\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0d\x04\0\x19[method]input-stream.skip\x01\ +\x0e\x04\0\"[method]input-stream.blocking-skip\x01\x0e\x01i\x03\x01@\x01\x04self\ +\x09\0\x0f\x04\0\x1e[method]input-stream.subscribe\x01\x10\x01h\x08\x01@\x01\x04\ +self\x11\0\x0d\x04\0![method]output-stream.check-write\x01\x12\x01j\0\x01\x06\x01\ +@\x02\x04self\x11\x08contents\x0a\0\x13\x04\0\x1b[method]output-stream.write\x01\ +\x14\x04\0.[method]output-stream.blocking-write-and-flush\x01\x14\x01@\x01\x04se\ +lf\x11\0\x13\x04\0\x1b[method]output-stream.flush\x01\x15\x04\0$[method]output-s\ +tream.blocking-flush\x01\x15\x01@\x01\x04self\x11\0\x0f\x04\0\x1f[method]output-\ +stream.subscribe\x01\x16\x01@\x02\x04self\x11\x03lenw\0\x13\x04\0\"[method]outpu\ +t-stream.write-zeroes\x01\x17\x04\05[method]output-stream.blocking-write-zeroes-\ +and-flush\x01\x17\x01@\x03\x04self\x11\x03src\x09\x03lenw\0\x0d\x04\0\x1c[method\ +]output-stream.splice\x01\x18\x04\0%[method]output-stream.blocking-splice\x01\x18\ +\x03\0\x15wasi:io/streams@0.2.4\x05\x06\x02\x03\0\x04\x0cinput-stream\x01B\x05\x02\ +\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x09ge\ +t-stdin\x01\x03\x03\0\x14wasi:cli/stdin@0.2.4\x05\x08\x02\x03\0\x04\x0doutput-st\ +ream\x01B\x05\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\ +\0\x02\x04\0\x0aget-stdout\x01\x03\x03\0\x15wasi:cli/stdout@0.2.4\x05\x0a\x01B\x05\ +\x02\x03\x02\x01\x09\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0a\ +get-stderr\x01\x03\x03\0\x15wasi:cli/stderr@0.2.4\x05\x0b\x01B\x01\x04\0\x0eterm\ +inal-input\x03\x01\x03\0\x1dwasi:cli/terminal-input@0.2.4\x05\x0c\x01B\x01\x04\0\ +\x0fterminal-output\x03\x01\x03\0\x1ewasi:cli/terminal-output@0.2.4\x05\x0d\x02\x03\ +\0\x08\x0eterminal-input\x01B\x06\x02\x03\x02\x01\x0e\x04\0\x0eterminal-input\x03\ +\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\x04\0\x12get-terminal-stdin\x01\x04\x03\0\x1d\ +wasi:cli/terminal-stdin@0.2.4\x05\x0f\x02\x03\0\x09\x0fterminal-output\x01B\x06\x02\ +\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\x02\x01@\0\0\x03\ +\x04\0\x13get-terminal-stdout\x01\x04\x03\0\x1ewasi:cli/terminal-stdout@0.2.4\x05\ +\x11\x01B\x06\x02\x03\x02\x01\x10\x04\0\x0fterminal-output\x03\0\0\x01i\x01\x01k\ +\x02\x01@\0\0\x03\x04\0\x13get-terminal-stderr\x01\x04\x03\0\x1ewasi:cli/termina\ +l-stderr@0.2.4\x05\x12\x01B\x0f\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x01\ +w\x04\0\x07instant\x03\0\x02\x01w\x04\0\x08duration\x03\0\x04\x01@\0\0\x03\x04\0\ +\x03now\x01\x06\x01@\0\0\x05\x04\0\x0aresolution\x01\x07\x01i\x01\x01@\x01\x04wh\ +en\x03\0\x08\x04\0\x11subscribe-instant\x01\x09\x01@\x01\x04when\x05\0\x08\x04\0\ +\x12subscribe-duration\x01\x0a\x03\0!wasi:clocks/monotonic-clock@0.2.4\x05\x13\x01\ +B\x05\x01r\x02\x07secondsw\x0bnanosecondsy\x04\0\x08datetime\x03\0\0\x01@\0\0\x01\ +\x04\0\x03now\x01\x02\x04\0\x0aresolution\x01\x02\x03\0\x1cwasi:clocks/wall-cloc\ +k@0.2.4\x05\x14\x02\x03\0\x04\x05error\x02\x03\0\x0e\x08datetime\x01Br\x02\x03\x02\ +\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\0\x0doutput-strea\ +m\x03\0\x02\x02\x03\x02\x01\x15\x04\0\x05error\x03\0\x04\x02\x03\x02\x01\x16\x04\ +\0\x08datetime\x03\0\x06\x01w\x04\0\x08filesize\x03\0\x08\x01m\x08\x07unknown\x0c\ +block-device\x10character-device\x09directory\x04fifo\x0dsymbolic-link\x0cregula\ +r-file\x06socket\x04\0\x0fdescriptor-type\x03\0\x0a\x01n\x06\x04read\x05write\x13\ +file-integrity-sync\x13data-integrity-sync\x14requested-write-sync\x10mutate-dir\ +ectory\x04\0\x10descriptor-flags\x03\0\x0c\x01n\x01\x0esymlink-follow\x04\0\x0ap\ +ath-flags\x03\0\x0e\x01n\x04\x06create\x09directory\x09exclusive\x08truncate\x04\ +\0\x0aopen-flags\x03\0\x10\x01w\x04\0\x0alink-count\x03\0\x12\x01k\x07\x01r\x06\x04\ +type\x0b\x0alink-count\x13\x04size\x09\x15data-access-timestamp\x14\x1bdata-modi\ +fication-timestamp\x14\x17status-change-timestamp\x14\x04\0\x0fdescriptor-stat\x03\ +\0\x15\x01q\x03\x09no-change\0\0\x03now\0\0\x09timestamp\x01\x07\0\x04\0\x0dnew-\ +timestamp\x03\0\x17\x01r\x02\x04type\x0b\x04names\x04\0\x0fdirectory-entry\x03\0\ +\x19\x01m%\x06access\x0bwould-block\x07already\x0ebad-descriptor\x04busy\x08dead\ +lock\x05quota\x05exist\x0efile-too-large\x15illegal-byte-sequence\x0bin-progress\ +\x0binterrupted\x07invalid\x02io\x0cis-directory\x04loop\x0etoo-many-links\x0cme\ +ssage-size\x0dname-too-long\x09no-device\x08no-entry\x07no-lock\x13insufficient-\ +memory\x12insufficient-space\x0dnot-directory\x09not-empty\x0fnot-recoverable\x0b\ +unsupported\x06no-tty\x0eno-such-device\x08overflow\x0dnot-permitted\x04pipe\x09\ +read-only\x0cinvalid-seek\x0etext-file-busy\x0ccross-device\x04\0\x0aerror-code\x03\ +\0\x1b\x01m\x06\x06normal\x0asequential\x06random\x09will-need\x09dont-need\x08n\ +o-reuse\x04\0\x06advice\x03\0\x1d\x01r\x02\x05lowerw\x05upperw\x04\0\x13metadata\ +-hash-value\x03\0\x1f\x04\0\x0adescriptor\x03\x01\x04\0\x16directory-entry-strea\ +m\x03\x01\x01h!\x01i\x01\x01j\x01$\x01\x1c\x01@\x02\x04self#\x06offset\x09\0%\x04\ +\0\"[method]descriptor.read-via-stream\x01&\x01i\x03\x01j\x01'\x01\x1c\x01@\x02\x04\ +self#\x06offset\x09\0(\x04\0#[method]descriptor.write-via-stream\x01)\x01@\x01\x04\ +self#\0(\x04\0$[method]descriptor.append-via-stream\x01*\x01j\0\x01\x1c\x01@\x04\ +\x04self#\x06offset\x09\x06length\x09\x06advice\x1e\0+\x04\0\x19[method]descript\ +or.advise\x01,\x01@\x01\x04self#\0+\x04\0\x1c[method]descriptor.sync-data\x01-\x01\ +j\x01\x0d\x01\x1c\x01@\x01\x04self#\0.\x04\0\x1c[method]descriptor.get-flags\x01\ +/\x01j\x01\x0b\x01\x1c\x01@\x01\x04self#\00\x04\0\x1b[method]descriptor.get-type\ +\x011\x01@\x02\x04self#\x04size\x09\0+\x04\0\x1b[method]descriptor.set-size\x012\ +\x01@\x03\x04self#\x15data-access-timestamp\x18\x1bdata-modification-timestamp\x18\ +\0+\x04\0\x1c[method]descriptor.set-times\x013\x01p}\x01o\x024\x7f\x01j\x015\x01\ +\x1c\x01@\x03\x04self#\x06length\x09\x06offset\x09\06\x04\0\x17[method]descripto\ +r.read\x017\x01j\x01\x09\x01\x1c\x01@\x03\x04self#\x06buffer4\x06offset\x09\08\x04\ +\0\x18[method]descriptor.write\x019\x01i\"\x01j\x01:\x01\x1c\x01@\x01\x04self#\0\ +;\x04\0![method]descriptor.read-directory\x01<\x04\0\x17[method]descriptor.sync\x01\ +-\x01@\x02\x04self#\x04paths\0+\x04\0&[method]descriptor.create-directory-at\x01\ +=\x01j\x01\x16\x01\x1c\x01@\x01\x04self#\0>\x04\0\x17[method]descriptor.stat\x01\ +?\x01@\x03\x04self#\x0apath-flags\x0f\x04paths\0>\x04\0\x1a[method]descriptor.st\ +at-at\x01@\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x15data-access-timestamp\ +\x18\x1bdata-modification-timestamp\x18\0+\x04\0\x1f[method]descriptor.set-times\ +-at\x01A\x01@\x05\x04self#\x0eold-path-flags\x0f\x08old-paths\x0enew-descriptor#\ +\x08new-paths\0+\x04\0\x1a[method]descriptor.link-at\x01B\x01i!\x01j\x01\xc3\0\x01\ +\x1c\x01@\x05\x04self#\x0apath-flags\x0f\x04paths\x0aopen-flags\x11\x05flags\x0d\ +\0\xc4\0\x04\0\x1a[method]descriptor.open-at\x01E\x01j\x01s\x01\x1c\x01@\x02\x04\ +self#\x04paths\0\xc6\0\x04\0\x1e[method]descriptor.readlink-at\x01G\x04\0&[metho\ +d]descriptor.remove-directory-at\x01=\x01@\x04\x04self#\x08old-paths\x0enew-desc\ +riptor#\x08new-paths\0+\x04\0\x1c[method]descriptor.rename-at\x01H\x01@\x03\x04s\ +elf#\x08old-paths\x08new-paths\0+\x04\0\x1d[method]descriptor.symlink-at\x01I\x04\ +\0![method]descriptor.unlink-file-at\x01=\x01@\x02\x04self#\x05other#\0\x7f\x04\0\ +![method]descriptor.is-same-object\x01J\x01j\x01\x20\x01\x1c\x01@\x01\x04self#\0\ +\xcb\0\x04\0\x20[method]descriptor.metadata-hash\x01L\x01@\x03\x04self#\x0apath-\ +flags\x0f\x04paths\0\xcb\0\x04\0#[method]descriptor.metadata-hash-at\x01M\x01h\"\ +\x01k\x1a\x01j\x01\xcf\0\x01\x1c\x01@\x01\x04self\xce\0\0\xd0\0\x04\03[method]di\ +rectory-entry-stream.read-directory-entry\x01Q\x01h\x05\x01k\x1c\x01@\x01\x03err\ +\xd2\0\0\xd3\0\x04\0\x15filesystem-error-code\x01T\x03\0\x1bwasi:filesystem/type\ +s@0.2.4\x05\x17\x02\x03\0\x0f\x0adescriptor\x01B\x07\x02\x03\x02\x01\x18\x04\0\x0a\ +descriptor\x03\0\0\x01i\x01\x01o\x02\x02s\x01p\x03\x01@\0\0\x04\x04\0\x0fget-dir\ +ectories\x01\x05\x03\0\x1ewasi:filesystem/preopens@0.2.4\x05\x19\x01B\x11\x04\0\x07\ +network\x03\x01\x01m\x15\x07unknown\x0daccess-denied\x0dnot-supported\x10invalid\ +-argument\x0dout-of-memory\x07timeout\x14concurrency-conflict\x0fnot-in-progress\ +\x0bwould-block\x0dinvalid-state\x10new-socket-limit\x14address-not-bindable\x0e\ +address-in-use\x12remote-unreachable\x12connection-refused\x10connection-reset\x12\ +connection-aborted\x12datagram-too-large\x11name-unresolvable\x1atemporary-resol\ +ver-failure\x1apermanent-resolver-failure\x04\0\x0aerror-code\x03\0\x01\x01m\x02\ +\x04ipv4\x04ipv6\x04\0\x11ip-address-family\x03\0\x03\x01o\x04}}}}\x04\0\x0cipv4\ +-address\x03\0\x05\x01o\x08{{{{{{{{\x04\0\x0cipv6-address\x03\0\x07\x01q\x02\x04\ +ipv4\x01\x06\0\x04ipv6\x01\x08\0\x04\0\x0aip-address\x03\0\x09\x01r\x02\x04port{\ +\x07address\x06\x04\0\x13ipv4-socket-address\x03\0\x0b\x01r\x04\x04port{\x09flow\ +-infoy\x07address\x08\x08scope-idy\x04\0\x13ipv6-socket-address\x03\0\x0d\x01q\x02\ +\x04ipv4\x01\x0c\0\x04ipv6\x01\x0e\0\x04\0\x11ip-socket-address\x03\0\x0f\x03\0\x1a\ +wasi:sockets/network@0.2.4\x05\x1a\x02\x03\0\x11\x07network\x01B\x05\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x10instance-networ\ +k\x01\x03\x03\0#wasi:sockets/instance-network@0.2.4\x05\x1c\x02\x03\0\x11\x0aerr\ +or-code\x02\x03\0\x11\x11ip-socket-address\x02\x03\0\x11\x11ip-address-family\x01\ +BD\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\x01\x1b\x04\0\x07ne\ +twork\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x04\x02\x03\x02\x01\ +\x1e\x04\0\x11ip-socket-address\x03\0\x06\x02\x03\x02\x01\x1f\x04\0\x11ip-addres\ +s-family\x03\0\x08\x01p}\x01r\x02\x04data\x0a\x0eremote-address\x07\x04\0\x11inc\ +oming-datagram\x03\0\x0b\x01k\x07\x01r\x02\x04data\x0a\x0eremote-address\x0d\x04\ +\0\x11outgoing-datagram\x03\0\x0e\x04\0\x0audp-socket\x03\x01\x04\0\x18incoming-\ +datagram-stream\x03\x01\x04\0\x18outgoing-datagram-stream\x03\x01\x01h\x10\x01h\x03\ +\x01j\0\x01\x05\x01@\x03\x04self\x13\x07network\x14\x0dlocal-address\x07\0\x15\x04\ +\0\x1d[method]udp-socket.start-bind\x01\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e\ +[method]udp-socket.finish-bind\x01\x17\x01i\x11\x01i\x12\x01o\x02\x18\x19\x01j\x01\ +\x1a\x01\x05\x01@\x02\x04self\x13\x0eremote-address\x0d\0\x1b\x04\0\x19[method]u\ +dp-socket.stream\x01\x1c\x01j\x01\x07\x01\x05\x01@\x01\x04self\x13\0\x1d\x04\0\x20\ +[method]udp-socket.local-address\x01\x1e\x04\0![method]udp-socket.remote-address\ +\x01\x1e\x01@\x01\x04self\x13\0\x09\x04\0![method]udp-socket.address-family\x01\x1f\ +\x01j\x01}\x01\x05\x01@\x01\x04self\x13\0\x20\x04\0$[method]udp-socket.unicast-h\ +op-limit\x01!\x01@\x02\x04self\x13\x05value}\0\x15\x04\0([method]udp-socket.set-\ +unicast-hop-limit\x01\"\x01j\x01w\x01\x05\x01@\x01\x04self\x13\0#\x04\0&[method]\ +udp-socket.receive-buffer-size\x01$\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[\ +method]udp-socket.set-receive-buffer-size\x01%\x04\0#[method]udp-socket.send-buf\ +fer-size\x01$\x04\0'[method]udp-socket.set-send-buffer-size\x01%\x01i\x01\x01@\x01\ +\x04self\x13\0&\x04\0\x1c[method]udp-socket.subscribe\x01'\x01h\x11\x01p\x0c\x01\ +j\x01)\x01\x05\x01@\x02\x04self(\x0bmax-resultsw\0*\x04\0([method]incoming-datag\ +ram-stream.receive\x01+\x01@\x01\x04self(\0&\x04\0*[method]incoming-datagram-str\ +eam.subscribe\x01,\x01h\x12\x01@\x01\x04self-\0#\x04\0+[method]outgoing-datagram\ +-stream.check-send\x01.\x01p\x0f\x01@\x02\x04self-\x09datagrams/\0#\x04\0%[metho\ +d]outgoing-datagram-stream.send\x010\x01@\x01\x04self-\0&\x04\0*[method]outgoing\ +-datagram-stream.subscribe\x011\x03\0\x16wasi:sockets/udp@0.2.4\x05\x20\x02\x03\0\ +\x13\x0audp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\0\0\x02\x03\ +\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\x11ip-addre\ +ss-family\x03\0\x04\x02\x03\x02\x01!\x04\0\x0audp-socket\x03\0\x06\x01i\x07\x01j\ +\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-udp-socket\ +\x01\x0a\x03\0$wasi:sockets/udp-create-socket@0.2.4\x05\"\x02\x03\0\x0d\x08durat\ +ion\x01BT\x02\x03\x02\x01\x07\x04\0\x0cinput-stream\x03\0\0\x02\x03\x02\x01\x09\x04\ +\0\x0doutput-stream\x03\0\x02\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\x04\x02\ +\x03\x02\x01#\x04\0\x08duration\x03\0\x06\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\x08\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x0a\x02\x03\x02\x01\x1e\x04\ +\0\x11ip-socket-address\x03\0\x0c\x02\x03\x02\x01\x1f\x04\0\x11ip-address-family\ +\x03\0\x0e\x01m\x03\x07receive\x04send\x04both\x04\0\x0dshutdown-type\x03\0\x10\x04\ +\0\x0atcp-socket\x03\x01\x01h\x12\x01h\x09\x01j\0\x01\x0b\x01@\x03\x04self\x13\x07\ +network\x14\x0dlocal-address\x0d\0\x15\x04\0\x1d[method]tcp-socket.start-bind\x01\ +\x16\x01@\x01\x04self\x13\0\x15\x04\0\x1e[method]tcp-socket.finish-bind\x01\x17\x01\ +@\x03\x04self\x13\x07network\x14\x0eremote-address\x0d\0\x15\x04\0\x20[method]tc\ +p-socket.start-connect\x01\x18\x01i\x01\x01i\x03\x01o\x02\x19\x1a\x01j\x01\x1b\x01\ +\x0b\x01@\x01\x04self\x13\0\x1c\x04\0![method]tcp-socket.finish-connect\x01\x1d\x04\ +\0\x1f[method]tcp-socket.start-listen\x01\x17\x04\0\x20[method]tcp-socket.finish\ +-listen\x01\x17\x01i\x12\x01o\x03\x1e\x19\x1a\x01j\x01\x1f\x01\x0b\x01@\x01\x04s\ +elf\x13\0\x20\x04\0\x19[method]tcp-socket.accept\x01!\x01j\x01\x0d\x01\x0b\x01@\x01\ +\x04self\x13\0\"\x04\0\x20[method]tcp-socket.local-address\x01#\x04\0![method]tc\ +p-socket.remote-address\x01#\x01@\x01\x04self\x13\0\x7f\x04\0\x1f[method]tcp-soc\ +ket.is-listening\x01$\x01@\x01\x04self\x13\0\x0f\x04\0![method]tcp-socket.addres\ +s-family\x01%\x01@\x02\x04self\x13\x05valuew\0\x15\x04\0*[method]tcp-socket.set-\ +listen-backlog-size\x01&\x01j\x01\x7f\x01\x0b\x01@\x01\x04self\x13\0'\x04\0%[met\ +hod]tcp-socket.keep-alive-enabled\x01(\x01@\x02\x04self\x13\x05value\x7f\0\x15\x04\ +\0)[method]tcp-socket.set-keep-alive-enabled\x01)\x01j\x01\x07\x01\x0b\x01@\x01\x04\ +self\x13\0*\x04\0'[method]tcp-socket.keep-alive-idle-time\x01+\x01@\x02\x04self\x13\ +\x05value\x07\0\x15\x04\0+[method]tcp-socket.set-keep-alive-idle-time\x01,\x04\0\ +&[method]tcp-socket.keep-alive-interval\x01+\x04\0*[method]tcp-socket.set-keep-a\ +live-interval\x01,\x01j\x01y\x01\x0b\x01@\x01\x04self\x13\0-\x04\0#[method]tcp-s\ +ocket.keep-alive-count\x01.\x01@\x02\x04self\x13\x05valuey\0\x15\x04\0'[method]t\ +cp-socket.set-keep-alive-count\x01/\x01j\x01}\x01\x0b\x01@\x01\x04self\x13\00\x04\ +\0\x1c[method]tcp-socket.hop-limit\x011\x01@\x02\x04self\x13\x05value}\0\x15\x04\ +\0\x20[method]tcp-socket.set-hop-limit\x012\x01j\x01w\x01\x0b\x01@\x01\x04self\x13\ +\03\x04\0&[method]tcp-socket.receive-buffer-size\x014\x04\0*[method]tcp-socket.s\ +et-receive-buffer-size\x01&\x04\0#[method]tcp-socket.send-buffer-size\x014\x04\0\ +'[method]tcp-socket.set-send-buffer-size\x01&\x01i\x05\x01@\x01\x04self\x13\05\x04\ +\0\x1c[method]tcp-socket.subscribe\x016\x01@\x02\x04self\x13\x0dshutdown-type\x11\ +\0\x15\x04\0\x1b[method]tcp-socket.shutdown\x017\x03\0\x16wasi:sockets/tcp@0.2.4\ +\x05$\x02\x03\0\x15\x0atcp-socket\x01B\x0c\x02\x03\x02\x01\x1b\x04\0\x07network\x03\ +\0\0\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\x02\x02\x03\x02\x01\x1f\x04\0\ +\x11ip-address-family\x03\0\x04\x02\x03\x02\x01%\x04\0\x0atcp-socket\x03\0\x06\x01\ +i\x07\x01j\x01\x08\x01\x03\x01@\x01\x0eaddress-family\x05\0\x09\x04\0\x11create-\ +tcp-socket\x01\x0a\x03\0$wasi:sockets/tcp-create-socket@0.2.4\x05&\x02\x03\0\x11\ +\x0aip-address\x01B\x16\x02\x03\x02\x01\x05\x04\0\x08pollable\x03\0\0\x02\x03\x02\ +\x01\x1b\x04\0\x07network\x03\0\x02\x02\x03\x02\x01\x1d\x04\0\x0aerror-code\x03\0\ +\x04\x02\x03\x02\x01'\x04\0\x0aip-address\x03\0\x06\x04\0\x16resolve-address-str\ +eam\x03\x01\x01h\x08\x01k\x07\x01j\x01\x0a\x01\x05\x01@\x01\x04self\x09\0\x0b\x04\ +\03[method]resolve-address-stream.resolve-next-address\x01\x0c\x01i\x01\x01@\x01\ +\x04self\x09\0\x0d\x04\0([method]resolve-address-stream.subscribe\x01\x0e\x01h\x03\ +\x01i\x08\x01j\x01\x10\x01\x05\x01@\x02\x07network\x0f\x04names\0\x11\x04\0\x11r\ +esolve-addresses\x01\x12\x03\0!wasi:sockets/ip-name-lookup@0.2.4\x05(\x01B\x05\x01\ +p}\x01@\x01\x03lenw\0\0\x04\0\x10get-random-bytes\x01\x01\x01@\0\0w\x04\0\x0eget\ +-random-u64\x01\x02\x03\0\x18wasi:random/random@0.2.4\x05)\x01B\x05\x01p}\x01@\x01\ +\x03lenw\0\0\x04\0\x19get-insecure-random-bytes\x01\x01\x01@\0\0w\x04\0\x17get-i\ +nsecure-random-u64\x01\x02\x03\0\x1awasi:random/insecure@0.2.4\x05*\x01B\x03\x01\ +o\x02ww\x01@\0\0\0\x04\0\x0dinsecure-seed\x01\x01\x03\0\x1fwasi:random/insecure-\ +seed@0.2.4\x05+\x04\0\x16wasi:cli/imports@0.2.4\x04\0\x0b\x0d\x01\0\x07imports\x03\ +\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.239.0\x10wit-\ +bindgen-rust\x060.46.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen::rt::maybe_link_cabi_realloc(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,296 @@ +//! Raw API bindings to the [WebAssembly System Interface (WASI)][WASI] +//! +//! [WASI]: https://github.com/WebAssembly/WASI +//! +//! This crate provides Rust API bindings to the imports of [WASI] [worlds] such +//! as: +//! +//! * [`wasi:cli/command`] +//! * [`wasi:http/proxy`] +//! +//! This crate is procedurally generated with the [`wit-bindgen`] bindings +//! generator. Note that generated code is published to crates.io to slim this +//! crate down in terms of build dependencies and resources. +//! +//! # What is WASI? +//! +//! [WASI] is a set of APIs defined for the WebAssembly [Component Model] to +//! help components interact with the outside world. Core WebAssembly has no +//! intrinsic ability to access the host, for example `println!` don't work, but +//! [WASI] defines how to do so with the [`wasi:cli/stdio`] package. +//! +//! [WASI] is defined by an IDL called [WIT] using files that have the extension +//! `*.wit`. [WASI] and [WIT] are themselves then both defined in terms of the +//! [Component Model] in terms of types available and base semantics for APIs. +//! +//! [WASI] defines a number of standard "worlds" which are a description of a +//! what a WebAssembly component can import from an embedding and must export to +//! an embedding. An example world is [`wasi:cli/command`] which is a world for +//! running CLI applications. This world provides basic system utilities such as +//! clocks, a filesystem, CLI arguments, etc. The one required export is a main +//! function. +//! +//! The purpose of this crate is to provide pregenerated bindings to access +//! [WASI]-defined imports available to components. +//! +//! # What is a Component? +//! +//! An important aspect of [WASI] is that it is defined in terms of the +//! [Component Model]. The [Component Model] is a proposal for WebAssembly which +//! is a new format for wasm binaries, a component. A component contains "core" +//! WebAssembly modules (which are [standard WebAssembly modules]) but also has +//! the ability to do more: +//! +//! * A component can contain multiple core WebAssembly modules. +//! * Types used with component imports and exports are more comprehensive than +//! core WebAssembly. Core WebAssembly provides integers and floats, for +//! example, and components build on this and add strings, records (aka a Rust +//! `struct`), variants (aka a Rust `enum`), and resources (think a file +//! descriptor on Unix). +//! * A component provides procedural instructions of how to instantiate its +//! internal core WebAssembly modules with the imports it has. +//! +//! The [Component Model] is a not considered an official WebAssembly standard +//! at this time. It has been in development for 5 years (as of January 2024), +//! however, and the WASI 0.2.0 milestone (more on versioning in a moment) in +//! January 2024 represents a concrete target for ecosystems to use. Runtimes +//! such as [Wasmtime] support the [Component Model] for out-of-browser usage +//! and [jco] is an example of how components can be run in a browser. +//! +//! A full description of the component model is out of scope for this crate's +//! documentation but it suffices to say that [WASI], and this crate, are +//! intended to target components. Components use core WebAssembly modules as an +//! important technical detail, but the final output of this crate is intended +//! to be a component. +//! +//! # What are generated bindings? +//! +//! Above it was seen that [WASI] is defined with [WIT]. These programmatic +//! descriptions of [WASI] APIs are not suitable for use directly in Rust, +//! however these descriptions define how Rust can use them. Each [WIT] function +//! has a defined meaning in core WebAssembly via the [Canonical ABI]. This is a +//! lower level than most users want to operate at, however, so the generated +//! bindings in this crate serve as the bridge. +//! +//! More specifically the generated functions in this crate take the [Canonical +//! ABI] format of [WIT] functions and provide idiomatic Rust functions to call. +//! For example the [`wasi:cli/environment`] definition includes: +//! +//! ```wit +//! interface environment { +//! // ... +//! get-environment: func() -> list>; +//! // ... +//! } +//! ``` +//! +//! This corresponds to +//! [`wasi::cli::environment::get_environment`](crate::cli::environment::get_environment). +//! +//! Bindings are pre-generated in this crate with the [`wit-bindgen`] tool. You +//! can also generate your own bindings with [`wit-bindgen`] and [WASI] [WIT] +//! files too, but that's not covered by this crate. +//! +//! # WASI Today and `wasi_snapshot_preview1` +//! +//! This crate is based on the 0.2.0 version of [WASI] APIs. This version of +//! [WASI] was declared "phase 3" (suitable for general use and testing) in +//! January of 2024. Prior to this 0.2.0 "preview2" release of [WASI] there was +//! `wasi_snapshot_preview1`. This previous "preview1" release of [WASI] was +//! circa 2019 and was the initial vision for [WASI] as a standard. Development +//! of [WASI] migrated to the [Component Model] in the meantime. +//! +//! This means that the old `wasi_snapshot_preview1` interfaces are no longer +//! provided by this crate because [WASI] is no longer defined by those +//! interfaces. This includes the historical `*.witx` format which has now been +//! sueprseded. Note that the 0.11.x release series of this crate contains +//! bindings to the historical `wasi_snapshot_preview1` APIs if you're +//! interested in using them. +//! +//! # Crate Organization +//! +//! This crate is currently entirely generated by [`wit-bindgen`] which has the +//! following structure: +//! +//! * Each [WIT] package with bindings corresponds to a top-level module. For +//! example [`wasi:random`] can be found in the [`random`] module. +//! * Each [WIT] interface then corresponds to a submodule of its package's +//! module. For example [`wasi:random/insecure`] can be found in the +//! [`random::insecure`] module. +//! * Each [WIT] function has a Rust function with an idiomatic signature. +//! module. For example [`random::insecure::get_insecure_random_u64`]. +//! +//! Note that [WIT] documentation is rendered as rustdoc documentation in these +//! APIs as well. +//! +//! # Using this Crate +//! +//! This crate is intended to be easiest to use with a future +//! `wasm32-wasip2` target added to the Rust compiler. In the meantime +//! it's recommended to use the `wasm32-wasip1` target instead: +//! +//! ```sh +//! $ cargo build --target wasm32-wasip1 +//! ``` +//! +//! Note that the output of the `wasm32-wasip1` target is a core wasm module, not +//! a component, so to turn it into a component you can use the [`wasm-tools`] +//! CLI in combination with an "adapter module" for the `wasi_snapshot_preview1` +//! APIs that the Rust standard library uses (example adapters can be found on +//! [Wasmtime's release page][adapters] as +//! [`wasi_snapshot_preview1.command.wasm`] for example) +//! +//! ```sh +//! $ wasm-tools component new ./target/wasm32-wasip1/debug/my-app.wasm \ +//! --adapt ./wasi_snapshot_preview1.command.wasm \ +//! -o my-component.wasm +//! ``` +//! +//! ## Export Macros +//! +//! In addition to providing bindings for imports this crate also provides +//! macros to export the `wasi:cli/run` and `wasi:http/proxy` worlds, see their +//! respective documentation for more information: +//! +//! - [`wasi::cli::command::export!`](crate::cli::command::export) +//! - [`wasi::http::proxy::export!`](crate::http::proxy::export) +//! +//! [worlds]: https://component-model.bytecodealliance.org/design/worlds.html +//! [`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli/ +//! [`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http +//! [`wasi:cli/stdio`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/stdio.wit +//! [`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen/ +//! [Component Model]: https://component-model.bytecodealliance.org/ +//! [WIT]: https://component-model.bytecodealliance.org/design/wit.html +//! [standard WebAssembly modules]: https://webassembly.github.io/spec/ +//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime +//! [jco]: https://github.com/bytecodealliance/jco +//! [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md +//! [`wasi:cli/environment`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/environment.wit +//! [`wasi:random`]: https://github.com/WebAssembly/wasi-random +//! [`wasi:random/insecure`]: https://github.com/WebAssembly/wasi-random/blob/main/wit/insecure.wit +//! [`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools +//! [adapters]: https://github.com/bytecodealliance/wasmtime/releases +//! [`wasi_snapshot_preview1.command.wasm`]: https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm + +#![no_std] + +#[cfg(feature = "std")] +extern crate std; + +pub mod ext; + +// These modules are all auto-generated by `./ci/regenerate.sh` +#[allow(unused_imports)] +mod command; +mod imports; +#[allow(unused_imports)] +mod proxy; + +// generated bindings start with the package namespace, which in this case is +// `wasi`, but the crate is already called wasi, so lift everything up one level +// to the root of this crate. +pub use imports::wasi::*; + +// Expand the `cli` and `http` modules with `export!` macros for the +// command/proxy worlds, but also retain all the contents defined in the +// `bindings` module as well. +pub mod cli { + pub use super::imports::wasi::cli::*; + + pub mod command { + /// Generate an exported instance of the `wasi:cli/command` world. + /// + /// This macro generate the `#[no_mangle]` functions necessary to + /// export this interface. It takes an argument which is a type that + /// must implement the + /// [`exports::cli::run::Guest`](crate::exports::cli::run::Guest) + /// trait. + /// + /// ``` + /// struct MyCliRunner; + /// + /// impl wasip2::exports::cli::run::Guest for MyCliRunner { + /// fn run() -> Result<(), ()> { + /// // ... + /// # panic!(); + /// } + /// } + /// + /// wasip2::cli::command::export!(MyCliRunner); + /// ``` + /// + /// ## Compatibility with `wasm32-wasip1` targets + /// + /// This macro is not compatible with `wasm32-wasip1` `bin` targets + /// which instead use a `fn main()` with the + /// `wasi_snapshot_preview1.command.wasm` adapter. This macro _can_ be + /// used with the `reactor` or `proxy` adapters. + /// + /// + #[doc(inline)] + pub use crate::command::_export_command as export; + } +} + +pub mod http { + pub use super::proxy::wasi::http::*; + + pub mod proxy { + /// Generate an exported instance of the `wasi:http/proxy` world. + /// + /// This macro will generate `#[no_mangle]` functions as necessary to + /// export an implementation of the + /// [`exports::http::incoming_handler::Guest`](crate::exports::http::incoming_handler::Guest) + /// trait. This macro takes + /// an argument which is a type that implements this trait: + /// + /// ``` + /// use wasip2::http::types::{IncomingRequest, ResponseOutparam}; + /// + /// struct MyIncomingHandler; + /// + /// impl wasip2::exports::http::incoming_handler::Guest for MyIncomingHandler { + /// fn handle(request: IncomingRequest, response_out: ResponseOutparam) { + /// // ... + /// # panic!(); + /// } + /// } + /// + /// wasip2::http::proxy::export!(MyIncomingHandler); + /// ``` + /// + /// + #[doc(inline)] + pub use crate::proxy::_export_proxy as export; + } +} + +pub mod exports { + // This is required by the `export!` macros of this crate which assume that + // the types it's referring to show up as `exports::wasi::...`. + // + // This isn't part of the public interface, though, so hide this. + #[doc(hidden)] + pub mod wasi { + pub use crate::command::exports::wasi::*; + pub use crate::proxy::exports::wasi::*; + } + + // These are the restructured public interface of this crate. + pub use crate::command::exports::wasi::cli; + pub use crate::proxy::exports::wasi::http; +} + +// These macros are used by recursive invocations of the macro, but they're +// `#[doc(hidden)]` as it's not part of the public interface. +#[doc(hidden)] +pub use crate::command::_export_command; +#[doc(hidden)] +pub use crate::proxy::_export_proxy; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/proxy.rs clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/proxy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/src/proxy.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/src/proxy.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7447 @@ +// Generated by `wit-bindgen` 0.46.0. DO NOT EDIT! +// Options used: +// * std_feature +// * with "wasi:cli/stdin@0.2.4" = "crate::cli::stdin" +// * with "wasi:cli/stdout@0.2.4" = "crate::cli::stdout" +// * with "wasi:cli/stderr@0.2.4" = "crate::cli::stderr" +// * with "wasi:clocks/monotonic-clock@0.2.4" = "crate::clocks::monotonic_clock" +// * with "wasi:clocks/wall-clock@0.2.4" = "crate::clocks::wall_clock" +// * with "wasi:io/error@0.2.4" = "crate::io::error" +// * with "wasi:io/poll@0.2.4" = "crate::io::poll" +// * with "wasi:io/streams@0.2.4" = "crate::io::streams" +// * with "wasi:random/random@0.2.4" = "crate::random::random" +// * type_section_suffix: "rust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-proxy-world" +// * default-bindings-module: "$crate" +// * export-macro-name: _export_proxy +// * pub-export-macro +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::poll as __with_name0; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::clocks::monotonic_clock as __with_name1; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::clocks::wall_clock as __with_name2; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::random::random as __with_name3; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::error as __with_name4; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::io::streams as __with_name5; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stdout as __with_name6; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stderr as __with_name7; +#[allow(unfulfilled_lint_expectations, unused_imports)] +use crate::cli::stdin as __with_name8; +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] +pub mod wasi { + pub mod http { + /// This interface defines all of the types and methods for implementing + /// HTTP Requests and Responses, both incoming and outgoing, as well as + /// their headers, trailers, and bodies. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod types { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type Duration = super::super::super::__with_name1::Duration; + pub type InputStream = super::super::super::__with_name5::InputStream; + pub type OutputStream = super::super::super::__with_name5::OutputStream; + pub type IoError = super::super::super::__with_name4::Error; + pub type Pollable = super::super::super::__with_name0::Pollable; + /// This type corresponds to HTTP standard Methods. + #[derive(Clone)] + pub enum Method { + Get, + Head, + Post, + Put, + Delete, + Connect, + Options, + Trace, + Patch, + Other(_rt::String), + } + impl ::core::fmt::Debug for Method { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + Method::Get => f.debug_tuple("Method::Get").finish(), + Method::Head => f.debug_tuple("Method::Head").finish(), + Method::Post => f.debug_tuple("Method::Post").finish(), + Method::Put => f.debug_tuple("Method::Put").finish(), + Method::Delete => f.debug_tuple("Method::Delete").finish(), + Method::Connect => f.debug_tuple("Method::Connect").finish(), + Method::Options => f.debug_tuple("Method::Options").finish(), + Method::Trace => f.debug_tuple("Method::Trace").finish(), + Method::Patch => f.debug_tuple("Method::Patch").finish(), + Method::Other(e) => { + f.debug_tuple("Method::Other").field(e).finish() + } + } + } + } + /// This type corresponds to HTTP standard Related Schemes. + #[derive(Clone)] + pub enum Scheme { + Http, + Https, + Other(_rt::String), + } + impl ::core::fmt::Debug for Scheme { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + Scheme::Http => f.debug_tuple("Scheme::Http").finish(), + Scheme::Https => f.debug_tuple("Scheme::Https").finish(), + Scheme::Other(e) => { + f.debug_tuple("Scheme::Other").field(e).finish() + } + } + } + } + /// Defines the case payload type for `DNS-error` above: + #[derive(Clone)] + pub struct DnsErrorPayload { + pub rcode: Option<_rt::String>, + pub info_code: Option, + } + impl ::core::fmt::Debug for DnsErrorPayload { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("DnsErrorPayload") + .field("rcode", &self.rcode) + .field("info-code", &self.info_code) + .finish() + } + } + /// Defines the case payload type for `TLS-alert-received` above: + #[derive(Clone)] + pub struct TlsAlertReceivedPayload { + pub alert_id: Option, + pub alert_message: Option<_rt::String>, + } + impl ::core::fmt::Debug for TlsAlertReceivedPayload { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("TlsAlertReceivedPayload") + .field("alert-id", &self.alert_id) + .field("alert-message", &self.alert_message) + .finish() + } + } + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + #[derive(Clone)] + pub struct FieldSizePayload { + pub field_name: Option<_rt::String>, + pub field_size: Option, + } + impl ::core::fmt::Debug for FieldSizePayload { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("FieldSizePayload") + .field("field-name", &self.field_name) + .field("field-size", &self.field_size) + .finish() + } + } + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// + #[derive(Clone)] + pub enum ErrorCode { + DnsTimeout, + DnsError(DnsErrorPayload), + DestinationNotFound, + DestinationUnavailable, + DestinationIpProhibited, + DestinationIpUnroutable, + ConnectionRefused, + ConnectionTerminated, + ConnectionTimeout, + ConnectionReadTimeout, + ConnectionWriteTimeout, + ConnectionLimitReached, + TlsProtocolError, + TlsCertificateError, + TlsAlertReceived(TlsAlertReceivedPayload), + HttpRequestDenied, + HttpRequestLengthRequired, + HttpRequestBodySize(Option), + HttpRequestMethodInvalid, + HttpRequestUriInvalid, + HttpRequestUriTooLong, + HttpRequestHeaderSectionSize(Option), + HttpRequestHeaderSize(Option), + HttpRequestTrailerSectionSize(Option), + HttpRequestTrailerSize(FieldSizePayload), + HttpResponseIncomplete, + HttpResponseHeaderSectionSize(Option), + HttpResponseHeaderSize(FieldSizePayload), + HttpResponseBodySize(Option), + HttpResponseTrailerSectionSize(Option), + HttpResponseTrailerSize(FieldSizePayload), + HttpResponseTransferCoding(Option<_rt::String>), + HttpResponseContentCoding(Option<_rt::String>), + HttpResponseTimeout, + HttpUpgradeFailed, + HttpProtocolError, + LoopDetected, + ConfigurationError, + /// This is a catch-all error for anything that doesn't fit cleanly into a + /// more specific case. It also includes an optional string for an + /// unstructured description of the error. Users should not depend on the + /// string for diagnosing errors, as it's not required to be consistent + /// between implementations. + InternalError(Option<_rt::String>), + } + impl ::core::fmt::Debug for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + ErrorCode::DnsTimeout => { + f.debug_tuple("ErrorCode::DnsTimeout").finish() + } + ErrorCode::DnsError(e) => { + f.debug_tuple("ErrorCode::DnsError").field(e).finish() + } + ErrorCode::DestinationNotFound => { + f.debug_tuple("ErrorCode::DestinationNotFound").finish() + } + ErrorCode::DestinationUnavailable => { + f.debug_tuple("ErrorCode::DestinationUnavailable").finish() + } + ErrorCode::DestinationIpProhibited => { + f.debug_tuple("ErrorCode::DestinationIpProhibited").finish() + } + ErrorCode::DestinationIpUnroutable => { + f.debug_tuple("ErrorCode::DestinationIpUnroutable").finish() + } + ErrorCode::ConnectionRefused => { + f.debug_tuple("ErrorCode::ConnectionRefused").finish() + } + ErrorCode::ConnectionTerminated => { + f.debug_tuple("ErrorCode::ConnectionTerminated").finish() + } + ErrorCode::ConnectionTimeout => { + f.debug_tuple("ErrorCode::ConnectionTimeout").finish() + } + ErrorCode::ConnectionReadTimeout => { + f.debug_tuple("ErrorCode::ConnectionReadTimeout").finish() + } + ErrorCode::ConnectionWriteTimeout => { + f.debug_tuple("ErrorCode::ConnectionWriteTimeout").finish() + } + ErrorCode::ConnectionLimitReached => { + f.debug_tuple("ErrorCode::ConnectionLimitReached").finish() + } + ErrorCode::TlsProtocolError => { + f.debug_tuple("ErrorCode::TlsProtocolError").finish() + } + ErrorCode::TlsCertificateError => { + f.debug_tuple("ErrorCode::TlsCertificateError").finish() + } + ErrorCode::TlsAlertReceived(e) => { + f.debug_tuple("ErrorCode::TlsAlertReceived") + .field(e) + .finish() + } + ErrorCode::HttpRequestDenied => { + f.debug_tuple("ErrorCode::HttpRequestDenied").finish() + } + ErrorCode::HttpRequestLengthRequired => { + f.debug_tuple("ErrorCode::HttpRequestLengthRequired") + .finish() + } + ErrorCode::HttpRequestBodySize(e) => { + f.debug_tuple("ErrorCode::HttpRequestBodySize") + .field(e) + .finish() + } + ErrorCode::HttpRequestMethodInvalid => { + f.debug_tuple("ErrorCode::HttpRequestMethodInvalid").finish() + } + ErrorCode::HttpRequestUriInvalid => { + f.debug_tuple("ErrorCode::HttpRequestUriInvalid").finish() + } + ErrorCode::HttpRequestUriTooLong => { + f.debug_tuple("ErrorCode::HttpRequestUriTooLong").finish() + } + ErrorCode::HttpRequestHeaderSectionSize(e) => { + f.debug_tuple("ErrorCode::HttpRequestHeaderSectionSize") + .field(e) + .finish() + } + ErrorCode::HttpRequestHeaderSize(e) => { + f.debug_tuple("ErrorCode::HttpRequestHeaderSize") + .field(e) + .finish() + } + ErrorCode::HttpRequestTrailerSectionSize(e) => { + f.debug_tuple("ErrorCode::HttpRequestTrailerSectionSize") + .field(e) + .finish() + } + ErrorCode::HttpRequestTrailerSize(e) => { + f.debug_tuple("ErrorCode::HttpRequestTrailerSize") + .field(e) + .finish() + } + ErrorCode::HttpResponseIncomplete => { + f.debug_tuple("ErrorCode::HttpResponseIncomplete").finish() + } + ErrorCode::HttpResponseHeaderSectionSize(e) => { + f.debug_tuple("ErrorCode::HttpResponseHeaderSectionSize") + .field(e) + .finish() + } + ErrorCode::HttpResponseHeaderSize(e) => { + f.debug_tuple("ErrorCode::HttpResponseHeaderSize") + .field(e) + .finish() + } + ErrorCode::HttpResponseBodySize(e) => { + f.debug_tuple("ErrorCode::HttpResponseBodySize") + .field(e) + .finish() + } + ErrorCode::HttpResponseTrailerSectionSize(e) => { + f.debug_tuple("ErrorCode::HttpResponseTrailerSectionSize") + .field(e) + .finish() + } + ErrorCode::HttpResponseTrailerSize(e) => { + f.debug_tuple("ErrorCode::HttpResponseTrailerSize") + .field(e) + .finish() + } + ErrorCode::HttpResponseTransferCoding(e) => { + f.debug_tuple("ErrorCode::HttpResponseTransferCoding") + .field(e) + .finish() + } + ErrorCode::HttpResponseContentCoding(e) => { + f.debug_tuple("ErrorCode::HttpResponseContentCoding") + .field(e) + .finish() + } + ErrorCode::HttpResponseTimeout => { + f.debug_tuple("ErrorCode::HttpResponseTimeout").finish() + } + ErrorCode::HttpUpgradeFailed => { + f.debug_tuple("ErrorCode::HttpUpgradeFailed").finish() + } + ErrorCode::HttpProtocolError => { + f.debug_tuple("ErrorCode::HttpProtocolError").finish() + } + ErrorCode::LoopDetected => { + f.debug_tuple("ErrorCode::LoopDetected").finish() + } + ErrorCode::ConfigurationError => { + f.debug_tuple("ErrorCode::ConfigurationError").finish() + } + ErrorCode::InternalError(e) => { + f.debug_tuple("ErrorCode::InternalError").field(e).finish() + } + } + } + } + impl ::core::fmt::Display for ErrorCode { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + write!(f, "{:?}", self) + } + } + #[cfg(feature = "std")] + impl std::error::Error for ErrorCode {} + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + #[derive(Clone, Copy)] + pub enum HeaderError { + /// This error indicates that a `field-name` or `field-value` was + /// syntactically invalid when used with an operation that sets headers in a + /// `fields`. + InvalidSyntax, + /// This error indicates that a forbidden `field-name` was used when trying + /// to set a header in a `fields`. + Forbidden, + /// This error indicates that the operation on the `fields` was not + /// permitted because the fields are immutable. + Immutable, + } + impl ::core::fmt::Debug for HeaderError { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + HeaderError::InvalidSyntax => { + f.debug_tuple("HeaderError::InvalidSyntax").finish() + } + HeaderError::Forbidden => { + f.debug_tuple("HeaderError::Forbidden").finish() + } + HeaderError::Immutable => { + f.debug_tuple("HeaderError::Immutable").finish() + } + } + } + } + impl ::core::fmt::Display for HeaderError { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + write!(f, "{:?}", self) + } + } + #[cfg(feature = "std")] + impl std::error::Error for HeaderError {} + /// Field keys are always strings. + /// + /// Field keys should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + /// + /// # Deprecation + /// + /// This type has been deprecated in favor of the `field-name` type. + pub type FieldKey = _rt::String; + /// Field names are always strings. + /// + /// Field names should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + pub type FieldName = FieldKey; + /// Field values should always be ASCII strings. However, in + /// reality, HTTP implementations often have to interpret malformed values, + /// so they are provided as a list of bytes. + pub type FieldValue = _rt::Vec; + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. Fields are a common representation used for both + /// Headers and Trailers. + /// + /// A `fields` may be mutable or immutable. A `fields` created using the + /// constructor, `from-list`, or `clone` will be mutable, but a `fields` + /// resource given by other means (including, but not limited to, + /// `incoming-request.headers`, `outgoing-request.headers`) might be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + #[derive(Debug)] + #[repr(transparent)] + pub struct Fields { + handle: _rt::Resource, + } + impl Fields { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for Fields { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]fields"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Headers is an alias for Fields. + pub type Headers = Fields; + /// Trailers is an alias for Fields. + pub type Trailers = Fields; + /// Represents an incoming HTTP Request. + #[derive(Debug)] + #[repr(transparent)] + pub struct IncomingRequest { + handle: _rt::Resource, + } + impl IncomingRequest { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for IncomingRequest { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]incoming-request"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents an outgoing HTTP Request. + #[derive(Debug)] + #[repr(transparent)] + pub struct OutgoingRequest { + handle: _rt::Resource, + } + impl OutgoingRequest { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for OutgoingRequest { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]outgoing-request"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Parameters for making an HTTP Request. Each of these parameters is + /// currently an optional timeout applicable to the transport layer of the + /// HTTP protocol. + /// + /// These timeouts are separate from any the user may use to bound a + /// blocking call to `wasi:io/poll.poll`. + #[derive(Debug)] + #[repr(transparent)] + pub struct RequestOptions { + handle: _rt::Resource, + } + impl RequestOptions { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for RequestOptions { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]request-options"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents the ability to send an HTTP Response. + /// + /// This resource is used by the `wasi:http/incoming-handler` interface to + /// allow a Response to be sent corresponding to the Request provided as the + /// other argument to `incoming-handler.handle`. + #[derive(Debug)] + #[repr(transparent)] + pub struct ResponseOutparam { + handle: _rt::Resource, + } + impl ResponseOutparam { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for ResponseOutparam { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]response-outparam"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// This type corresponds to the HTTP standard Status Code. + pub type StatusCode = u16; + /// Represents an incoming HTTP Response. + #[derive(Debug)] + #[repr(transparent)] + pub struct IncomingResponse { + handle: _rt::Resource, + } + impl IncomingResponse { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for IncomingResponse { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]incoming-response"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents an incoming HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, indicating that the full contents of the + /// body have been received. This resource represents the contents as + /// an `input-stream` and the delivery of trailers as a `future-trailers`, + /// and ensures that the user of this interface may only be consuming either + /// the body contents or waiting on trailers at any given time. + #[derive(Debug)] + #[repr(transparent)] + pub struct IncomingBody { + handle: _rt::Resource, + } + impl IncomingBody { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for IncomingBody { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]incoming-body"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents a future which may eventually return trailers, or an error. + /// + /// In the case that the incoming HTTP Request or Response did not have any + /// trailers, this future will resolve to the empty set of trailers once the + /// complete Request or Response body has been received. + #[derive(Debug)] + #[repr(transparent)] + pub struct FutureTrailers { + handle: _rt::Resource, + } + impl FutureTrailers { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for FutureTrailers { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]future-trailers"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents an outgoing HTTP Response. + #[derive(Debug)] + #[repr(transparent)] + pub struct OutgoingResponse { + handle: _rt::Resource, + } + impl OutgoingResponse { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for OutgoingResponse { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]outgoing-response"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents an outgoing HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, inducating the full contents of the body + /// have been sent. This resource represents the contents as an + /// `output-stream` child resource, and the completion of the body (with + /// optional trailers) with a static function that consumes the + /// `outgoing-body` resource, and ensures that the user of this interface + /// may not write to the body contents after the body has been finished. + /// + /// If the user code drops this resource, as opposed to calling the static + /// method `finish`, the implementation should treat the body as incomplete, + /// and that an error has occurred. The implementation should propagate this + /// error to the HTTP protocol by whatever means it has available, + /// including: corrupting the body on the wire, aborting the associated + /// Request, or sending a late status code for the Response. + #[derive(Debug)] + #[repr(transparent)] + pub struct OutgoingBody { + handle: _rt::Resource, + } + impl OutgoingBody { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for OutgoingBody { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]outgoing-body"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + /// Represents a future which may eventually return an incoming HTTP + /// Response, or an error. + /// + /// This resource is returned by the `wasi:http/outgoing-handler` interface to + /// provide the HTTP Response corresponding to the sent Request. + #[derive(Debug)] + #[repr(transparent)] + pub struct FutureIncomingResponse { + handle: _rt::Resource, + } + impl FutureIncomingResponse { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: unsafe { _rt::Resource::from_handle(handle) }, + } + } + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + unsafe impl _rt::WasmResource for FutureIncomingResponse { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[resource-drop]future-incoming-response"] + fn drop(_: i32); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn drop(_: i32) { + unreachable!() + } + unsafe { + drop(_handle as i32); + } + } + } + #[allow(unused_unsafe, clippy::all)] + /// Attempts to extract a http-related `error` from the wasi:io `error` + /// provided. + /// + /// Stream operations which return + /// `wasi:io/stream/stream-error::last-operation-failed` have a payload of + /// type `wasi:io/error/error` with more information about the operation + /// that failed. This payload can be passed through to this function to see + /// if there's http-related information about the error to return. + /// + /// Note that this function is fallible because not all io-errors are + /// http-related errors. + #[allow(async_fn_in_trait)] + pub fn http_error_code(err: &IoError) -> Option { + unsafe { + #[repr(align(8))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 24 + 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 24 + + 4 * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "http-error-code"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((err).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result66 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(8).cast::()); + let v65 = match l3 { + 0 => ErrorCode::DnsTimeout, + 1 => { + let e65 = { + let l4 = i32::from(*ptr0.add(16).cast::()); + let l8 = i32::from( + *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + DnsErrorPayload { + rcode: match l4 { + 0 => None, + 1 => { + let e = { + let l5 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, + ); + _rt::string_lift(bytes7) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + info_code: match l8 { + 0 => None, + 1 => { + let e = { + let l9 = i32::from( + *ptr0 + .add(18 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + l9 as u16 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::DnsError(e65) + } + 2 => ErrorCode::DestinationNotFound, + 3 => ErrorCode::DestinationUnavailable, + 4 => ErrorCode::DestinationIpProhibited, + 5 => ErrorCode::DestinationIpUnroutable, + 6 => ErrorCode::ConnectionRefused, + 7 => ErrorCode::ConnectionTerminated, + 8 => ErrorCode::ConnectionTimeout, + 9 => ErrorCode::ConnectionReadTimeout, + 10 => ErrorCode::ConnectionWriteTimeout, + 11 => ErrorCode::ConnectionLimitReached, + 12 => ErrorCode::TlsProtocolError, + 13 => ErrorCode::TlsCertificateError, + 14 => { + let e65 = { + let l10 = i32::from(*ptr0.add(16).cast::()); + let l12 = i32::from( + *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + TlsAlertReceivedPayload { + alert_id: match l10 { + 0 => None, + 1 => { + let e = { + let l11 = i32::from(*ptr0.add(17).cast::()); + l11 as u8 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + alert_message: match l12 { + 0 => None, + 1 => { + let e = { + let l13 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len15 = l14; + let bytes15 = _rt::Vec::from_raw_parts( + l13.cast(), + len15, + len15, + ); + _rt::string_lift(bytes15) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::TlsAlertReceived(e65) + } + 15 => ErrorCode::HttpRequestDenied, + 16 => ErrorCode::HttpRequestLengthRequired, + 17 => { + let e65 = { + let l16 = i32::from(*ptr0.add(16).cast::()); + match l16 { + 0 => None, + 1 => { + let e = { + let l17 = *ptr0.add(24).cast::(); + l17 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestBodySize(e65) + } + 18 => ErrorCode::HttpRequestMethodInvalid, + 19 => ErrorCode::HttpRequestUriInvalid, + 20 => ErrorCode::HttpRequestUriTooLong, + 21 => { + let e65 = { + let l18 = i32::from(*ptr0.add(16).cast::()); + match l18 { + 0 => None, + 1 => { + let e = { + let l19 = *ptr0.add(20).cast::(); + l19 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSectionSize(e65) + } + 22 => { + let e65 = { + let l20 = i32::from(*ptr0.add(16).cast::()); + match l20 { + 0 => None, + 1 => { + let e = { + let l21 = i32::from( + *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l25 = i32::from( + *ptr0 + .add(16 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l21 { + 0 => None, + 1 => { + let e = { + let l22 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l23 = *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len24 = l23; + let bytes24 = _rt::Vec::from_raw_parts( + l22.cast(), + len24, + len24, + ); + _rt::string_lift(bytes24) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l25 { + 0 => None, + 1 => { + let e = { + let l26 = *ptr0 + .add(20 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l26 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSize(e65) + } + 23 => { + let e65 = { + let l27 = i32::from(*ptr0.add(16).cast::()); + match l27 { + 0 => None, + 1 => { + let e = { + let l28 = *ptr0.add(20).cast::(); + l28 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestTrailerSectionSize(e65) + } + 24 => { + let e65 = { + let l29 = i32::from(*ptr0.add(16).cast::()); + let l33 = i32::from( + *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l29 { + 0 => None, + 1 => { + let e = { + let l30 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l31 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len32 = l31; + let bytes32 = _rt::Vec::from_raw_parts( + l30.cast(), + len32, + len32, + ); + _rt::string_lift(bytes32) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l33 { + 0 => None, + 1 => { + let e = { + let l34 = *ptr0 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l34 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpRequestTrailerSize(e65) + } + 25 => ErrorCode::HttpResponseIncomplete, + 26 => { + let e65 = { + let l35 = i32::from(*ptr0.add(16).cast::()); + match l35 { + 0 => None, + 1 => { + let e = { + let l36 = *ptr0.add(20).cast::(); + l36 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseHeaderSectionSize(e65) + } + 27 => { + let e65 = { + let l37 = i32::from(*ptr0.add(16).cast::()); + let l41 = i32::from( + *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l37 { + 0 => None, + 1 => { + let e = { + let l38 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len40 = l39; + let bytes40 = _rt::Vec::from_raw_parts( + l38.cast(), + len40, + len40, + ); + _rt::string_lift(bytes40) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l41 { + 0 => None, + 1 => { + let e = { + let l42 = *ptr0 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l42 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseHeaderSize(e65) + } + 28 => { + let e65 = { + let l43 = i32::from(*ptr0.add(16).cast::()); + match l43 { + 0 => None, + 1 => { + let e = { + let l44 = *ptr0.add(24).cast::(); + l44 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseBodySize(e65) + } + 29 => { + let e65 = { + let l45 = i32::from(*ptr0.add(16).cast::()); + match l45 { + 0 => None, + 1 => { + let e = { + let l46 = *ptr0.add(20).cast::(); + l46 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTrailerSectionSize(e65) + } + 30 => { + let e65 = { + let l47 = i32::from(*ptr0.add(16).cast::()); + let l51 = i32::from( + *ptr0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l47 { + 0 => None, + 1 => { + let e = { + let l48 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l49 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len50 = l49; + let bytes50 = _rt::Vec::from_raw_parts( + l48.cast(), + len50, + len50, + ); + _rt::string_lift(bytes50) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l51 { + 0 => None, + 1 => { + let e = { + let l52 = *ptr0 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l52 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseTrailerSize(e65) + } + 31 => { + let e65 = { + let l53 = i32::from(*ptr0.add(16).cast::()); + match l53 { + 0 => None, + 1 => { + let e = { + let l54 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l55 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len56 = l55; + let bytes56 = _rt::Vec::from_raw_parts( + l54.cast(), + len56, + len56, + ); + _rt::string_lift(bytes56) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTransferCoding(e65) + } + 32 => { + let e65 = { + let l57 = i32::from(*ptr0.add(16).cast::()); + match l57 { + 0 => None, + 1 => { + let e = { + let l58 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l59 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len60 = l59; + let bytes60 = _rt::Vec::from_raw_parts( + l58.cast(), + len60, + len60, + ); + _rt::string_lift(bytes60) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseContentCoding(e65) + } + 33 => ErrorCode::HttpResponseTimeout, + 34 => ErrorCode::HttpUpgradeFailed, + 35 => ErrorCode::HttpProtocolError, + 36 => ErrorCode::LoopDetected, + 37 => ErrorCode::ConfigurationError, + n => { + debug_assert_eq!(n, 38, "invalid enum discriminant"); + let e65 = { + let l61 = i32::from(*ptr0.add(16).cast::()); + match l61 { + 0 => None, + 1 => { + let e = { + let l62 = *ptr0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l63 = *ptr0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len64 = l63; + let bytes64 = _rt::Vec::from_raw_parts( + l62.cast(), + len64, + len64, + ); + _rt::string_lift(bytes64) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::InternalError(e65) + } + }; + v65 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result66 + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + #[allow(async_fn_in_trait)] + pub fn new() -> Self { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[constructor]fields"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + Fields::from_handle(ret as u32) + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The tuple is a pair of the field name, represented as a string, and + /// Value, represented as a list of bytes. + /// + /// An error result will be returned if any `field-name` or `field-value` is + /// syntactically invalid, or if a field is forbidden. + #[allow(async_fn_in_trait)] + pub fn from_list( + entries: &[(FieldName, FieldValue)], + ) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let vec3 = entries; + let len3 = vec3.len(); + let layout3 = _rt::alloc::Layout::from_size_align( + vec3.len() * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ) + .unwrap(); + let (result3, _cleanup3) = wit_bindgen::rt::Cleanup::new( + layout3, + ); + for (i, e) in vec3.into_iter().enumerate() { + let base = result3 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + { + let (t0_0, t0_1) = e; + let vec1 = t0_0; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len1; + *base.add(0).cast::<*mut u8>() = ptr1.cast_mut(); + let vec2 = t0_1; + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + } + let ptr4 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[static]fields.from-list"] + fn wit_import5(_: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import5( + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import5(result3, len3, ptr4); + let l6 = i32::from(*ptr4.add(0).cast::()); + let result10 = match l6 { + 0 => { + let e = { + let l7 = *ptr4.add(4).cast::(); + Fields::from_handle(l7 as u32) + }; + Ok(e) + } + 1 => { + let e = { + let l8 = i32::from(*ptr4.add(4).cast::()); + let v9 = match l8 { + 0 => HeaderError::InvalidSyntax, + 1 => HeaderError::Forbidden, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + HeaderError::Immutable + } + }; + v9 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result10 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Get all of the values corresponding to a name. If the name is not present + /// in this `fields` or is syntactically invalid, an empty list is returned. + /// However, if the name is present but empty, this is represented by a list + /// with one or more empty field-values present. + #[allow(async_fn_in_trait)] + pub fn get(&self, name: &str) -> _rt::Vec { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.get"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = *ptr1.add(0).cast::<*mut u8>(); + let l4 = *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base8 = l3; + let len8 = l4; + let mut result8 = _rt::Vec::with_capacity(len8); + for i in 0..len8 { + let base = base8 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e8 = { + let l5 = *base.add(0).cast::<*mut u8>(); + let l6 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + _rt::Vec::from_raw_parts(l5.cast(), len7, len7) + }; + result8.push(e8); + } + _rt::cabi_dealloc( + base8, + len8 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result9 = result8; + result9 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Returns `true` when the name is present in this `fields`. If the name is + /// syntactically invalid, `false` is returned. + #[allow(async_fn_in_trait)] + pub fn has(&self, name: &str) -> bool { + unsafe { + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.has"] + fn wit_import1(_: i32, _: *mut u8, _: usize) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1( + _: i32, + _: *mut u8, + _: usize, + ) -> i32 { + unreachable!() + } + let ret = wit_import1( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + ); + _rt::bool_lift(ret as u8) + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Set all of the values for a name. Clears any existing values for that + /// name, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or any of + /// the `field-value`s are syntactically invalid. + #[allow(async_fn_in_trait)] + pub fn set( + &self, + name: &str, + value: &[FieldValue], + ) -> Result<(), HeaderError> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let vec2 = value; + let len2 = vec2.len(); + let layout2 = _rt::alloc::Layout::from_size_align( + vec2.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ) + .unwrap(); + let (result2, _cleanup2) = wit_bindgen::rt::Cleanup::new( + layout2, + ); + for (i, e) in vec2.into_iter().enumerate() { + let base = result2 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec1 = e; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len1; + *base.add(0).cast::<*mut u8>() = ptr1.cast_mut(); + } + } + let ptr3 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.set"] + fn wit_import4( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import4( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import4( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + result2, + len2, + ptr3, + ); + let l5 = i32::from(*ptr3.add(0).cast::()); + let result8 = match l5 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from(*ptr3.add(1).cast::()); + let v7 = match l6 { + 0 => HeaderError::InvalidSyntax, + 1 => HeaderError::Forbidden, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + HeaderError::Immutable + } + }; + v7 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Delete all values for a name. Does nothing if no values for the name + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` is + /// syntactically invalid. + #[allow(async_fn_in_trait)] + pub fn delete(&self, name: &str) -> Result<(), HeaderError> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.delete"] + fn wit_import2(_: i32, _: *mut u8, _: usize, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import2((self).handle() as i32, ptr0.cast_mut(), len0, ptr1); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result6 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(1).cast::()); + let v5 = match l4 { + 0 => HeaderError::InvalidSyntax, + 1 => HeaderError::Forbidden, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + HeaderError::Immutable + } + }; + v5 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Append a value for a name. Does not change or delete any existing + /// values for that name. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or + /// `field-value` are syntactically invalid. + #[allow(async_fn_in_trait)] + pub fn append( + &self, + name: &str, + value: &[u8], + ) -> Result<(), HeaderError> { + unsafe { + #[repr(align(1))] + struct RetArea([::core::mem::MaybeUninit; 2]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2], + ); + let vec0 = name; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + let vec1 = value; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + let ptr2 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.append"] + fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: *mut u8, + _: usize, + _: *mut u8, + _: usize, + _: *mut u8, + ) { + unreachable!() + } + wit_import3( + (self).handle() as i32, + ptr0.cast_mut(), + len0, + ptr1.cast_mut(), + len1, + ptr2, + ); + let l4 = i32::from(*ptr2.add(0).cast::()); + let result7 = match l4 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr2.add(1).cast::()); + let v6 = match l5 { + 0 => HeaderError::InvalidSyntax, + 1 => HeaderError::Forbidden, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + HeaderError::Immutable + } + }; + v6 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result7 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Retrieve the full set of names and values in the Fields. Like the + /// constructor, the list represents each name-value pair. + /// + /// The outer list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The names and values are always returned in the original casing and in + /// the order in which they will be serialized for transport. + #[allow(async_fn_in_trait)] + pub fn entries(&self) -> _rt::Vec<(FieldName, FieldValue)> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.entries"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = *ptr0.add(0).cast::<*mut u8>(); + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l2; + let len10 = l3; + let mut result10 = _rt::Vec::with_capacity(len10); + for i in 0..len10 { + let base = base10 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + let e10 = { + let l4 = *base.add(0).cast::<*mut u8>(); + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts( + l4.cast(), + len6, + len6, + ); + let l7 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len9 = l8; + ( + _rt::string_lift(bytes6), + _rt::Vec::from_raw_parts(l7.cast(), len9, len9), + ) + }; + result10.push(e10); + } + _rt::cabi_dealloc( + base10, + len10 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result11 = result10; + result11 + } + } + } + impl Fields { + #[allow(unused_unsafe, clippy::all)] + /// Make a deep copy of the Fields. Equivalent in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + #[allow(async_fn_in_trait)] + pub fn clone(&self) -> Fields { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]fields.clone"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + Fields::from_handle(ret as u32) + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Returns the method of the incoming request. + #[allow(async_fn_in_trait)] + pub fn method(&self) -> Method { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.method"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let v6 = match l2 { + 0 => Method::Get, + 1 => Method::Head, + 2 => Method::Post, + 3 => Method::Put, + 4 => Method::Delete, + 5 => Method::Connect, + 6 => Method::Options, + 7 => Method::Trace, + 8 => Method::Patch, + n => { + debug_assert_eq!(n, 9, "invalid enum discriminant"); + let e6 = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Method::Other(e6) + } + }; + let result7 = v6; + result7 + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Returns the path with query parameters from the request, as a string. + #[allow(async_fn_in_trait)] + pub fn path_with_query(&self) -> Option<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.path-with-query"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Returns the protocol scheme from the request. + #[allow(async_fn_in_trait)] + pub fn scheme(&self) -> Option { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.scheme"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result8 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + let v7 = match l3 { + 0 => Scheme::Http, + 1 => Scheme::Https, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + let e7 = { + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *ptr0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts( + l4.cast(), + len6, + len6, + ); + _rt::string_lift(bytes6) + }; + Scheme::Other(e7) + } + }; + v7 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Returns the authority of the Request's target URI, if present. + #[allow(async_fn_in_trait)] + pub fn authority(&self) -> Option<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.authority"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the `headers` associated with the request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// The `headers` returned are a child resource: it must be dropped before + /// the parent `incoming-request` is dropped. Dropping this + /// `incoming-request` before all children are dropped will trap. + #[allow(async_fn_in_trait)] + pub fn headers(&self) -> Headers { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.headers"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + Fields::from_handle(ret as u32) + } + } + } + impl IncomingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + #[allow(async_fn_in_trait)] + pub fn consume(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-request.consume"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + IncomingBody::from_handle(l3 as u32) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Construct a new `outgoing-request` with a default `method` of `GET`, and + /// `none` values for `path-with-query`, `scheme`, and `authority`. + /// + /// * `headers` is the HTTP Headers for the Request. + /// + /// It is possible to construct, or manipulate with the accessor functions + /// below, an `outgoing-request` with an invalid combination of `scheme` + /// and `authority`, or `headers` which are not permitted to be sent. + /// It is the obligation of the `outgoing-handler.handle` implementation + /// to reject invalid constructions of `outgoing-request`. + #[allow(async_fn_in_trait)] + pub fn new(headers: Headers) -> Self { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[constructor]outgoing-request"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((&headers).take_handle() as i32); + OutgoingRequest::from_handle(ret as u32) + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Returns the resource corresponding to the outgoing Body for this + /// Request. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-request` can be retrieved at most once. Subsequent + /// calls will return error. + #[allow(async_fn_in_trait)] + pub fn body(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.body"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + OutgoingBody::from_handle(l3 as u32) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the Method for the Request. + #[allow(async_fn_in_trait)] + pub fn method(&self) -> Method { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.method"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let v6 = match l2 { + 0 => Method::Get, + 1 => Method::Head, + 2 => Method::Post, + 3 => Method::Put, + 4 => Method::Delete, + 5 => Method::Connect, + 6 => Method::Options, + 7 => Method::Trace, + 8 => Method::Patch, + n => { + debug_assert_eq!(n, 9, "invalid enum discriminant"); + let e6 = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Method::Other(e6) + } + }; + let result7 = v6; + result7 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Set the Method for the Request. Fails if the string present in a + /// `method.other` argument is not a syntactically valid method. + #[allow(async_fn_in_trait)] + pub fn set_method(&self, method: &Method) -> Result<(), ()> { + unsafe { + let (result1_0, result1_1, result1_2) = match method { + Method::Get => (0i32, ::core::ptr::null_mut(), 0usize), + Method::Head => (1i32, ::core::ptr::null_mut(), 0usize), + Method::Post => (2i32, ::core::ptr::null_mut(), 0usize), + Method::Put => (3i32, ::core::ptr::null_mut(), 0usize), + Method::Delete => (4i32, ::core::ptr::null_mut(), 0usize), + Method::Connect => (5i32, ::core::ptr::null_mut(), 0usize), + Method::Options => (6i32, ::core::ptr::null_mut(), 0usize), + Method::Trace => (7i32, ::core::ptr::null_mut(), 0usize), + Method::Patch => (8i32, ::core::ptr::null_mut(), 0usize), + Method::Other(e) => { + let vec0 = e; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + (9i32, ptr0.cast_mut(), len0) + } + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.set-method"] + fn wit_import2(_: i32, _: i32, _: *mut u8, _: usize) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: i32, + _: *mut u8, + _: usize, + ) -> i32 { + unreachable!() + } + let ret = wit_import2( + (self).handle() as i32, + result1_0, + result1_1, + result1_2, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. + #[allow(async_fn_in_trait)] + pub fn path_with_query(&self) -> Option<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.path-with-query"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Set the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. Fails is the + /// string given is not a syntactically valid path and query uri component. + #[allow(async_fn_in_trait)] + pub fn set_path_with_query( + &self, + path_with_query: Option<&str>, + ) -> Result<(), ()> { + unsafe { + let (result1_0, result1_1, result1_2) = match path_with_query { + Some(e) => { + let vec0 = e; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + (1i32, ptr0.cast_mut(), len0) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.set-path-with-query"] + fn wit_import2(_: i32, _: i32, _: *mut u8, _: usize) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: i32, + _: *mut u8, + _: usize, + ) -> i32 { + unreachable!() + } + let ret = wit_import2( + (self).handle() as i32, + result1_0, + result1_1, + result1_2, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. + #[allow(async_fn_in_trait)] + pub fn scheme(&self) -> Option { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.scheme"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result8 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from( + *ptr0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + let v7 = match l3 { + 0 => Scheme::Http, + 1 => Scheme::Https, + n => { + debug_assert_eq!(n, 2, "invalid enum discriminant"); + let e7 = { + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *ptr0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len6 = l5; + let bytes6 = _rt::Vec::from_raw_parts( + l4.cast(), + len6, + len6, + ); + _rt::string_lift(bytes6) + }; + Scheme::Other(e7) + } + }; + v7 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result8 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Set the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. Fails if the + /// string given is not a syntactically valid uri scheme. + #[allow(async_fn_in_trait)] + pub fn set_scheme(&self, scheme: Option<&Scheme>) -> Result<(), ()> { + unsafe { + let (result2_0, result2_1, result2_2, result2_3) = match scheme { + Some(e) => { + let (result1_0, result1_1, result1_2) = match e { + Scheme::Http => (0i32, ::core::ptr::null_mut(), 0usize), + Scheme::Https => (1i32, ::core::ptr::null_mut(), 0usize), + Scheme::Other(e) => { + let vec0 = e; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + (2i32, ptr0.cast_mut(), len0) + } + }; + (1i32, result1_0, result1_1, result1_2) + } + None => (0i32, 0i32, ::core::ptr::null_mut(), 0usize), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.set-scheme"] + fn wit_import3( + _: i32, + _: i32, + _: i32, + _: *mut u8, + _: usize, + ) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import3( + _: i32, + _: i32, + _: i32, + _: *mut u8, + _: usize, + ) -> i32 { + unreachable!() + } + let ret = wit_import3( + (self).handle() as i32, + result2_0, + result2_1, + result2_2, + result2_3, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. + #[allow(async_fn_in_trait)] + pub fn authority(&self) -> Option<_rt::String> { + unsafe { + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 3 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 3 + * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.authority"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result6 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l4 = *ptr0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len5 = l4; + let bytes5 = _rt::Vec::from_raw_parts( + l3.cast(), + len5, + len5, + ); + _rt::string_lift(bytes5) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result6 + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Set the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. Fails if the string given is + /// not a syntactically valid URI authority. + #[allow(async_fn_in_trait)] + pub fn set_authority(&self, authority: Option<&str>) -> Result<(), ()> { + unsafe { + let (result1_0, result1_1, result1_2) = match authority { + Some(e) => { + let vec0 = e; + let ptr0 = vec0.as_ptr().cast::(); + let len0 = vec0.len(); + (1i32, ptr0.cast_mut(), len0) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.set-authority"] + fn wit_import2(_: i32, _: i32, _: *mut u8, _: usize) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: i32, + _: *mut u8, + _: usize, + ) -> i32 { + unreachable!() + } + let ret = wit_import2( + (self).handle() as i32, + result1_0, + result1_1, + result1_2, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl OutgoingRequest { + #[allow(unused_unsafe, clippy::all)] + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + #[allow(async_fn_in_trait)] + pub fn headers(&self) -> Headers { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-request.headers"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + Fields::from_handle(ret as u32) + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// Construct a default `request-options` value. + #[allow(async_fn_in_trait)] + pub fn new() -> Self { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[constructor]request-options"] + fn wit_import0() -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0() -> i32 { + unreachable!() + } + let ret = wit_import0(); + RequestOptions::from_handle(ret as u32) + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// The timeout for the initial connect to the HTTP Server. + #[allow(async_fn_in_trait)] + pub fn connect_timeout(&self) -> Option { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.connect-timeout"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// Set the timeout for the initial connect to the HTTP Server. An error + /// return value indicates that this timeout is not supported. + #[allow(async_fn_in_trait)] + pub fn set_connect_timeout( + &self, + duration: Option, + ) -> Result<(), ()> { + unsafe { + let (result0_0, result0_1) = match duration { + Some(e) => (1i32, _rt::as_i64(e)), + None => (0i32, 0i64), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.set-connect-timeout"] + fn wit_import1(_: i32, _: i32, _: i64) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: i64) -> i32 { + unreachable!() + } + let ret = wit_import1( + (self).handle() as i32, + result0_0, + result0_1, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// The timeout for receiving the first byte of the Response body. + #[allow(async_fn_in_trait)] + pub fn first_byte_timeout(&self) -> Option { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.first-byte-timeout"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// Set the timeout for receiving the first byte of the Response body. An + /// error return value indicates that this timeout is not supported. + #[allow(async_fn_in_trait)] + pub fn set_first_byte_timeout( + &self, + duration: Option, + ) -> Result<(), ()> { + unsafe { + let (result0_0, result0_1) = match duration { + Some(e) => (1i32, _rt::as_i64(e)), + None => (0i32, 0i64), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.set-first-byte-timeout"] + fn wit_import1(_: i32, _: i32, _: i64) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: i64) -> i32 { + unreachable!() + } + let ret = wit_import1( + (self).handle() as i32, + result0_0, + result0_1, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + #[allow(async_fn_in_trait)] + pub fn between_bytes_timeout(&self) -> Option { + unsafe { + #[repr(align(8))] + struct RetArea([::core::mem::MaybeUninit; 16]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 16], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.between-bytes-timeout"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = *ptr0.add(8).cast::(); + l3 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl RequestOptions { + #[allow(unused_unsafe, clippy::all)] + /// Set the timeout for receiving subsequent chunks of bytes in the Response + /// body stream. An error return value indicates that this timeout is not + /// supported. + #[allow(async_fn_in_trait)] + pub fn set_between_bytes_timeout( + &self, + duration: Option, + ) -> Result<(), ()> { + unsafe { + let (result0_0, result0_1) = match duration { + Some(e) => (1i32, _rt::as_i64(e)), + None => (0i32, 0i64), + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]request-options.set-between-bytes-timeout"] + fn wit_import1(_: i32, _: i32, _: i64) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: i32, _: i64) -> i32 { + unreachable!() + } + let ret = wit_import1( + (self).handle() as i32, + result0_0, + result0_1, + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl ResponseOutparam { + #[allow(unused_unsafe, clippy::all)] + /// Set the value of the `response-outparam` to either send a response, + /// or indicate an error. + /// + /// This method consumes the `response-outparam` to ensure that it is + /// called at most once. If it is never called, the implementation + /// will respond with an error. + /// + /// The user may provide an `error` to `response` to allow the + /// implementation determine how to respond with an HTTP error response. + #[allow(async_fn_in_trait)] + pub fn set( + param: ResponseOutparam, + response: Result, + ) -> () { + unsafe { + let ( + result38_0, + result38_1, + result38_2, + result38_3, + result38_4, + result38_5, + result38_6, + result38_7, + ) = match &response { + Ok(e) => { + ( + 0i32, + (e).take_handle() as i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + Err(e) => { + let ( + result37_0, + result37_1, + result37_2, + result37_3, + result37_4, + result37_5, + result37_6, + ) = match e { + ErrorCode::DnsTimeout => { + ( + 0i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::DnsError(e) => { + let DnsErrorPayload { + rcode: rcode0, + info_code: info_code0, + } = e; + let (result2_0, result2_1, result2_2) = match rcode0 { + Some(e) => { + let vec1 = e; + let ptr1 = vec1.as_ptr().cast::(); + let len1 = vec1.len(); + (1i32, ptr1.cast_mut(), len1) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + let (result3_0, result3_1) = match info_code0 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 1i32, + result2_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result2_1); + t + }, + result2_2 as *mut u8, + result3_0 as *mut u8, + result3_1 as usize, + 0i32, + ) + } + ErrorCode::DestinationNotFound => { + ( + 2i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::DestinationUnavailable => { + ( + 3i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::DestinationIpProhibited => { + ( + 4i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::DestinationIpUnroutable => { + ( + 5i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionRefused => { + ( + 6i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionTerminated => { + ( + 7i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionTimeout => { + ( + 8i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionReadTimeout => { + ( + 9i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionWriteTimeout => { + ( + 10i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConnectionLimitReached => { + ( + 11i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::TlsProtocolError => { + ( + 12i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::TlsCertificateError => { + ( + 13i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::TlsAlertReceived(e) => { + let TlsAlertReceivedPayload { + alert_id: alert_id4, + alert_message: alert_message4, + } = e; + let (result5_0, result5_1) = match alert_id4 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + let (result7_0, result7_1, result7_2) = match alert_message4 { + Some(e) => { + let vec6 = e; + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + (1i32, ptr6.cast_mut(), len6) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + ( + 14i32, + result5_0, + ::core::mem::MaybeUninit::new(i64::from(result5_1) as u64), + result7_0 as *mut u8, + result7_1, + result7_2, + 0i32, + ) + } + ErrorCode::HttpRequestDenied => { + ( + 15i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestLengthRequired => { + ( + 16i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestBodySize(e) => { + let (result8_0, result8_1) = match e { + Some(e) => (1i32, _rt::as_i64(e)), + None => (0i32, 0i64), + }; + ( + 17i32, + result8_0, + ::core::mem::MaybeUninit::new(result8_1 as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestMethodInvalid => { + ( + 18i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestUriInvalid => { + ( + 19i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestUriTooLong => { + ( + 20i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestHeaderSectionSize(e) => { + let (result9_0, result9_1) = match e { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 21i32, + result9_0, + ::core::mem::MaybeUninit::new(i64::from(result9_1) as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestHeaderSize(e) => { + let ( + result14_0, + result14_1, + result14_2, + result14_3, + result14_4, + result14_5, + ) = match e { + Some(e) => { + let FieldSizePayload { + field_name: field_name10, + field_size: field_size10, + } = e; + let (result12_0, result12_1, result12_2) = match field_name10 { + Some(e) => { + let vec11 = e; + let ptr11 = vec11.as_ptr().cast::(); + let len11 = vec11.len(); + (1i32, ptr11.cast_mut(), len11) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + let (result13_0, result13_1) = match field_size10 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 1i32, + result12_0, + result12_1, + result12_2, + result13_0, + result13_1, + ) + } + None => { + (0i32, 0i32, ::core::ptr::null_mut(), 0usize, 0i32, 0i32) + } + }; + ( + 22i32, + result14_0, + ::core::mem::MaybeUninit::new(i64::from(result14_1) as u64), + result14_2, + result14_3 as *mut u8, + result14_4 as usize, + result14_5, + ) + } + ErrorCode::HttpRequestTrailerSectionSize(e) => { + let (result15_0, result15_1) = match e { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 23i32, + result15_0, + ::core::mem::MaybeUninit::new(i64::from(result15_1) as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpRequestTrailerSize(e) => { + let FieldSizePayload { + field_name: field_name16, + field_size: field_size16, + } = e; + let (result18_0, result18_1, result18_2) = match field_name16 { + Some(e) => { + let vec17 = e; + let ptr17 = vec17.as_ptr().cast::(); + let len17 = vec17.len(); + (1i32, ptr17.cast_mut(), len17) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + let (result19_0, result19_1) = match field_size16 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 24i32, + result18_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result18_1); + t + }, + result18_2 as *mut u8, + result19_0 as *mut u8, + result19_1 as usize, + 0i32, + ) + } + ErrorCode::HttpResponseIncomplete => { + ( + 25i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseHeaderSectionSize(e) => { + let (result20_0, result20_1) = match e { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 26i32, + result20_0, + ::core::mem::MaybeUninit::new(i64::from(result20_1) as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseHeaderSize(e) => { + let FieldSizePayload { + field_name: field_name21, + field_size: field_size21, + } = e; + let (result23_0, result23_1, result23_2) = match field_name21 { + Some(e) => { + let vec22 = e; + let ptr22 = vec22.as_ptr().cast::(); + let len22 = vec22.len(); + (1i32, ptr22.cast_mut(), len22) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + let (result24_0, result24_1) = match field_size21 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 27i32, + result23_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result23_1); + t + }, + result23_2 as *mut u8, + result24_0 as *mut u8, + result24_1 as usize, + 0i32, + ) + } + ErrorCode::HttpResponseBodySize(e) => { + let (result25_0, result25_1) = match e { + Some(e) => (1i32, _rt::as_i64(e)), + None => (0i32, 0i64), + }; + ( + 28i32, + result25_0, + ::core::mem::MaybeUninit::new(result25_1 as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseTrailerSectionSize(e) => { + let (result26_0, result26_1) = match e { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 29i32, + result26_0, + ::core::mem::MaybeUninit::new(i64::from(result26_1) as u64), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseTrailerSize(e) => { + let FieldSizePayload { + field_name: field_name27, + field_size: field_size27, + } = e; + let (result29_0, result29_1, result29_2) = match field_name27 { + Some(e) => { + let vec28 = e; + let ptr28 = vec28.as_ptr().cast::(); + let len28 = vec28.len(); + (1i32, ptr28.cast_mut(), len28) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + let (result30_0, result30_1) = match field_size27 { + Some(e) => (1i32, _rt::as_i32(e)), + None => (0i32, 0i32), + }; + ( + 30i32, + result29_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result29_1); + t + }, + result29_2 as *mut u8, + result30_0 as *mut u8, + result30_1 as usize, + 0i32, + ) + } + ErrorCode::HttpResponseTransferCoding(e) => { + let (result32_0, result32_1, result32_2) = match e { + Some(e) => { + let vec31 = e; + let ptr31 = vec31.as_ptr().cast::(); + let len31 = vec31.len(); + (1i32, ptr31.cast_mut(), len31) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + ( + 31i32, + result32_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result32_1); + t + }, + result32_2 as *mut u8, + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseContentCoding(e) => { + let (result34_0, result34_1, result34_2) = match e { + Some(e) => { + let vec33 = e; + let ptr33 = vec33.as_ptr().cast::(); + let len33 = vec33.len(); + (1i32, ptr33.cast_mut(), len33) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + ( + 32i32, + result34_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result34_1); + t + }, + result34_2 as *mut u8, + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpResponseTimeout => { + ( + 33i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpUpgradeFailed => { + ( + 34i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::HttpProtocolError => { + ( + 35i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::LoopDetected => { + ( + 36i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::ConfigurationError => { + ( + 37i32, + 0i32, + ::core::mem::MaybeUninit::::zeroed(), + ::core::ptr::null_mut(), + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + ErrorCode::InternalError(e) => { + let (result36_0, result36_1, result36_2) = match e { + Some(e) => { + let vec35 = e; + let ptr35 = vec35.as_ptr().cast::(); + let len35 = vec35.len(); + (1i32, ptr35.cast_mut(), len35) + } + None => (0i32, ::core::ptr::null_mut(), 0usize), + }; + ( + 38i32, + result36_0, + { + let mut t = ::core::mem::MaybeUninit::::uninit(); + t.as_mut_ptr().cast::<*mut u8>().write(result36_1); + t + }, + result36_2 as *mut u8, + ::core::ptr::null_mut(), + 0usize, + 0i32, + ) + } + }; + ( + 1i32, + result37_0, + result37_1, + result37_2, + result37_3, + result37_4, + result37_5, + result37_6, + ) + } + }; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[static]response-outparam.set"] + fn wit_import39( + _: i32, + _: i32, + _: i32, + _: i32, + _: ::core::mem::MaybeUninit, + _: *mut u8, + _: *mut u8, + _: usize, + _: i32, + ); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import39( + _: i32, + _: i32, + _: i32, + _: i32, + _: ::core::mem::MaybeUninit, + _: *mut u8, + _: *mut u8, + _: usize, + _: i32, + ) { + unreachable!() + } + wit_import39( + (¶m).take_handle() as i32, + result38_0, + result38_1, + result38_2, + result38_3, + result38_4, + result38_5, + result38_6, + result38_7, + ); + } + } + } + impl IncomingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns the status code from the incoming response. + #[allow(async_fn_in_trait)] + pub fn status(&self) -> StatusCode { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-response.status"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + ret as u16 + } + } + } + impl IncomingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns the headers from the incoming response. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `incoming-response` is dropped. + #[allow(async_fn_in_trait)] + pub fn headers(&self) -> Headers { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-response.headers"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + Fields::from_handle(ret as u32) + } + } + } + impl IncomingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + #[allow(async_fn_in_trait)] + pub fn consume(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-response.consume"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + IncomingBody::from_handle(l3 as u32) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl IncomingBody { + #[allow(unused_unsafe, clippy::all)] + /// Returns the contents of the body, as a stream of bytes. + /// + /// Returns success on first call: the stream representing the contents + /// can be retrieved at most once. Subsequent calls will return error. + /// + /// The returned `input-stream` resource is a child: it must be dropped + /// before the parent `incoming-body` is dropped, or consumed by + /// `incoming-body.finish`. + /// + /// This invariant ensures that the implementation can determine whether + /// the user is consuming the contents of the body, waiting on the + /// `future-trailers` to be ready, or neither. This allows for network + /// backpressure is to be applied when the user is consuming the body, + /// and for that backpressure to not inhibit delivery of the trailers if + /// the user does not read the entire body. + #[allow(async_fn_in_trait)] + pub fn stream(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]incoming-body.stream"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::__with_name5::InputStream::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl IncomingBody { + #[allow(unused_unsafe, clippy::all)] + /// Takes ownership of `incoming-body`, and returns a `future-trailers`. + /// This function will trap if the `input-stream` child is still alive. + #[allow(async_fn_in_trait)] + pub fn finish(this: IncomingBody) -> FutureTrailers { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[static]incoming-body.finish"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((&this).take_handle() as i32); + FutureTrailers::from_handle(ret as u32) + } + } + } + impl FutureTrailers { + #[allow(unused_unsafe, clippy::all)] + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]future-trailers.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::__with_name0::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl FutureTrailers { + #[allow(unused_unsafe, clippy::all)] + /// Returns the contents of the trailers, or an error which occurred, + /// once the future is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the trailers or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the HTTP Request or Response + /// body, as well as any trailers, were received successfully, or that an + /// error occurred receiving them. The optional `trailers` indicates whether + /// or not trailers were present in the body. + /// + /// When some `trailers` are returned by this method, the `trailers` + /// resource is immutable, and a child. Use of the `set`, `append`, or + /// `delete` methods will return an error, and the resource must be + /// dropped before the parent `future-trailers` is dropped. + #[allow(async_fn_in_trait)] + pub fn get( + &self, + ) -> Option, ErrorCode>, ()>> { + unsafe { + #[repr(align(8))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 40 + 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 40 + + 4 * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]future-trailers.get"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result70 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(8).cast::()); + match l3 { + 0 => { + let e = { + let l4 = i32::from(*ptr0.add(16).cast::()); + match l4 { + 0 => { + let e = { + let l5 = i32::from(*ptr0.add(24).cast::()); + match l5 { + 0 => None, + 1 => { + let e = { + let l6 = *ptr0.add(28).cast::(); + Fields::from_handle(l6 as u32) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Ok(e) + } + 1 => { + let e = { + let l7 = i32::from(*ptr0.add(24).cast::()); + let v69 = match l7 { + 0 => ErrorCode::DnsTimeout, + 1 => { + let e69 = { + let l8 = i32::from(*ptr0.add(32).cast::()); + let l12 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + DnsErrorPayload { + rcode: match l8 { + 0 => None, + 1 => { + let e = { + let l9 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len11 = l10; + let bytes11 = _rt::Vec::from_raw_parts( + l9.cast(), + len11, + len11, + ); + _rt::string_lift(bytes11) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + info_code: match l12 { + 0 => None, + 1 => { + let e = { + let l13 = i32::from( + *ptr0 + .add(34 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + l13 as u16 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::DnsError(e69) + } + 2 => ErrorCode::DestinationNotFound, + 3 => ErrorCode::DestinationUnavailable, + 4 => ErrorCode::DestinationIpProhibited, + 5 => ErrorCode::DestinationIpUnroutable, + 6 => ErrorCode::ConnectionRefused, + 7 => ErrorCode::ConnectionTerminated, + 8 => ErrorCode::ConnectionTimeout, + 9 => ErrorCode::ConnectionReadTimeout, + 10 => ErrorCode::ConnectionWriteTimeout, + 11 => ErrorCode::ConnectionLimitReached, + 12 => ErrorCode::TlsProtocolError, + 13 => ErrorCode::TlsCertificateError, + 14 => { + let e69 = { + let l14 = i32::from(*ptr0.add(32).cast::()); + let l16 = i32::from( + *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + TlsAlertReceivedPayload { + alert_id: match l14 { + 0 => None, + 1 => { + let e = { + let l15 = i32::from(*ptr0.add(33).cast::()); + l15 as u8 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + alert_message: match l16 { + 0 => None, + 1 => { + let e = { + let l17 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len19 = l18; + let bytes19 = _rt::Vec::from_raw_parts( + l17.cast(), + len19, + len19, + ); + _rt::string_lift(bytes19) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::TlsAlertReceived(e69) + } + 15 => ErrorCode::HttpRequestDenied, + 16 => ErrorCode::HttpRequestLengthRequired, + 17 => { + let e69 = { + let l20 = i32::from(*ptr0.add(32).cast::()); + match l20 { + 0 => None, + 1 => { + let e = { + let l21 = *ptr0.add(40).cast::(); + l21 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestBodySize(e69) + } + 18 => ErrorCode::HttpRequestMethodInvalid, + 19 => ErrorCode::HttpRequestUriInvalid, + 20 => ErrorCode::HttpRequestUriTooLong, + 21 => { + let e69 = { + let l22 = i32::from(*ptr0.add(32).cast::()); + match l22 { + 0 => None, + 1 => { + let e = { + let l23 = *ptr0.add(36).cast::(); + l23 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSectionSize(e69) + } + 22 => { + let e69 = { + let l24 = i32::from(*ptr0.add(32).cast::()); + match l24 { + 0 => None, + 1 => { + let e = { + let l25 = i32::from( + *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l29 = i32::from( + *ptr0 + .add(32 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l25 { + 0 => None, + 1 => { + let e = { + let l26 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len28 = l27; + let bytes28 = _rt::Vec::from_raw_parts( + l26.cast(), + len28, + len28, + ); + _rt::string_lift(bytes28) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l29 { + 0 => None, + 1 => { + let e = { + let l30 = *ptr0 + .add(36 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l30 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSize(e69) + } + 23 => { + let e69 = { + let l31 = i32::from(*ptr0.add(32).cast::()); + match l31 { + 0 => None, + 1 => { + let e = { + let l32 = *ptr0.add(36).cast::(); + l32 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestTrailerSectionSize(e69) + } + 24 => { + let e69 = { + let l33 = i32::from(*ptr0.add(32).cast::()); + let l37 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l33 { + 0 => None, + 1 => { + let e = { + let l34 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l35 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len36 = l35; + let bytes36 = _rt::Vec::from_raw_parts( + l34.cast(), + len36, + len36, + ); + _rt::string_lift(bytes36) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l37 { + 0 => None, + 1 => { + let e = { + let l38 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l38 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpRequestTrailerSize(e69) + } + 25 => ErrorCode::HttpResponseIncomplete, + 26 => { + let e69 = { + let l39 = i32::from(*ptr0.add(32).cast::()); + match l39 { + 0 => None, + 1 => { + let e = { + let l40 = *ptr0.add(36).cast::(); + l40 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseHeaderSectionSize(e69) + } + 27 => { + let e69 = { + let l41 = i32::from(*ptr0.add(32).cast::()); + let l45 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l41 { + 0 => None, + 1 => { + let e = { + let l42 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l43 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len44 = l43; + let bytes44 = _rt::Vec::from_raw_parts( + l42.cast(), + len44, + len44, + ); + _rt::string_lift(bytes44) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l45 { + 0 => None, + 1 => { + let e = { + let l46 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l46 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseHeaderSize(e69) + } + 28 => { + let e69 = { + let l47 = i32::from(*ptr0.add(32).cast::()); + match l47 { + 0 => None, + 1 => { + let e = { + let l48 = *ptr0.add(40).cast::(); + l48 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseBodySize(e69) + } + 29 => { + let e69 = { + let l49 = i32::from(*ptr0.add(32).cast::()); + match l49 { + 0 => None, + 1 => { + let e = { + let l50 = *ptr0.add(36).cast::(); + l50 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTrailerSectionSize(e69) + } + 30 => { + let e69 = { + let l51 = i32::from(*ptr0.add(32).cast::()); + let l55 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l51 { + 0 => None, + 1 => { + let e = { + let l52 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l53 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len54 = l53; + let bytes54 = _rt::Vec::from_raw_parts( + l52.cast(), + len54, + len54, + ); + _rt::string_lift(bytes54) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l55 { + 0 => None, + 1 => { + let e = { + let l56 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l56 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseTrailerSize(e69) + } + 31 => { + let e69 = { + let l57 = i32::from(*ptr0.add(32).cast::()); + match l57 { + 0 => None, + 1 => { + let e = { + let l58 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l59 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len60 = l59; + let bytes60 = _rt::Vec::from_raw_parts( + l58.cast(), + len60, + len60, + ); + _rt::string_lift(bytes60) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTransferCoding(e69) + } + 32 => { + let e69 = { + let l61 = i32::from(*ptr0.add(32).cast::()); + match l61 { + 0 => None, + 1 => { + let e = { + let l62 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l63 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len64 = l63; + let bytes64 = _rt::Vec::from_raw_parts( + l62.cast(), + len64, + len64, + ); + _rt::string_lift(bytes64) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseContentCoding(e69) + } + 33 => ErrorCode::HttpResponseTimeout, + 34 => ErrorCode::HttpUpgradeFailed, + 35 => ErrorCode::HttpProtocolError, + 36 => ErrorCode::LoopDetected, + 37 => ErrorCode::ConfigurationError, + n => { + debug_assert_eq!(n, 38, "invalid enum discriminant"); + let e69 = { + let l65 = i32::from(*ptr0.add(32).cast::()); + match l65 { + 0 => None, + 1 => { + let e = { + let l66 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l67 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len68 = l67; + let bytes68 = _rt::Vec::from_raw_parts( + l66.cast(), + len68, + len68, + ); + _rt::string_lift(bytes68) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::InternalError(e69) + } + }; + v69 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result70 + } + } + } + impl OutgoingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Construct an `outgoing-response`, with a default `status-code` of `200`. + /// If a different `status-code` is needed, it must be set via the + /// `set-status-code` method. + /// + /// * `headers` is the HTTP Headers for the Response. + #[allow(async_fn_in_trait)] + pub fn new(headers: Headers) -> Self { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[constructor]outgoing-response"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((&headers).take_handle() as i32); + OutgoingResponse::from_handle(ret as u32) + } + } + } + impl OutgoingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Get the HTTP Status Code for the Response. + #[allow(async_fn_in_trait)] + pub fn status_code(&self) -> StatusCode { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-response.status-code"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + ret as u16 + } + } + } + impl OutgoingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Set the HTTP Status Code for the Response. Fails if the status-code + /// given is not a valid http status code. + #[allow(async_fn_in_trait)] + pub fn set_status_code( + &self, + status_code: StatusCode, + ) -> Result<(), ()> { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-response.set-status-code"] + fn wit_import0(_: i32, _: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32, _: i32) -> i32 { + unreachable!() + } + let ret = wit_import0( + (self).handle() as i32, + _rt::as_i32(status_code), + ); + match ret { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + } + } + } + impl OutgoingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + #[allow(async_fn_in_trait)] + pub fn headers(&self) -> Headers { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-response.headers"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + Fields::from_handle(ret as u32) + } + } + } + impl OutgoingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns the resource corresponding to the outgoing Body for this Response. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-response` can be retrieved at most once. Subsequent + /// calls will return error. + #[allow(async_fn_in_trait)] + pub fn body(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-response.body"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + OutgoingBody::from_handle(l3 as u32) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl OutgoingBody { + #[allow(unused_unsafe, clippy::all)] + /// Returns a stream for writing the body contents. + /// + /// The returned `output-stream` is a child resource: it must be dropped + /// before the parent `outgoing-body` resource is dropped (or finished), + /// otherwise the `outgoing-body` drop or `finish` will trap. + /// + /// Returns success on the first call: the `output-stream` resource for + /// this `outgoing-body` may be retrieved at most once. Subsequent calls + /// will return error. + #[allow(async_fn_in_trait)] + pub fn write(&self) -> Result { + unsafe { + #[repr(align(4))] + struct RetArea([::core::mem::MaybeUninit; 8]); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 8], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]outgoing-body.write"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result4 = match l2 { + 0 => { + let e = { + let l3 = *ptr0.add(4).cast::(); + super::super::super::__with_name5::OutputStream::from_handle( + l3 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result4 + } + } + } + impl OutgoingBody { + #[allow(unused_unsafe, clippy::all)] + /// Finalize an outgoing body, optionally providing trailers. This must be + /// called to signal that the response is complete. If the `outgoing-body` + /// is dropped without calling `outgoing-body.finalize`, the implementation + /// should treat the body as corrupted. + /// + /// Fails if the body's `outgoing-request` or `outgoing-response` was + /// constructed with a Content-Length header, and the contents written + /// to the body (via `write`) does not match the value given in the + /// Content-Length. + #[allow(async_fn_in_trait)] + pub fn finish( + this: OutgoingBody, + trailers: Option, + ) -> Result<(), ErrorCode> { + unsafe { + #[repr(align(8))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 24 + 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 24 + + 4 * ::core::mem::size_of::<*const u8>()], + ); + let (result0_0, result0_1) = match &trailers { + Some(e) => (1i32, (e).take_handle() as i32), + None => (0i32, 0i32), + }; + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[static]outgoing-body.finish"] + fn wit_import2(_: i32, _: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import2( + (&this).take_handle() as i32, + result0_0, + result0_1, + ptr1, + ); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result67 = match l3 { + 0 => { + let e = (); + Ok(e) + } + 1 => { + let e = { + let l4 = i32::from(*ptr1.add(8).cast::()); + let v66 = match l4 { + 0 => ErrorCode::DnsTimeout, + 1 => { + let e66 = { + let l5 = i32::from(*ptr1.add(16).cast::()); + let l9 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + DnsErrorPayload { + rcode: match l5 { + 0 => None, + 1 => { + let e = { + let l6 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len8 = l7; + let bytes8 = _rt::Vec::from_raw_parts( + l6.cast(), + len8, + len8, + ); + _rt::string_lift(bytes8) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + info_code: match l9 { + 0 => None, + 1 => { + let e = { + let l10 = i32::from( + *ptr1 + .add(18 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + l10 as u16 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::DnsError(e66) + } + 2 => ErrorCode::DestinationNotFound, + 3 => ErrorCode::DestinationUnavailable, + 4 => ErrorCode::DestinationIpProhibited, + 5 => ErrorCode::DestinationIpUnroutable, + 6 => ErrorCode::ConnectionRefused, + 7 => ErrorCode::ConnectionTerminated, + 8 => ErrorCode::ConnectionTimeout, + 9 => ErrorCode::ConnectionReadTimeout, + 10 => ErrorCode::ConnectionWriteTimeout, + 11 => ErrorCode::ConnectionLimitReached, + 12 => ErrorCode::TlsProtocolError, + 13 => ErrorCode::TlsCertificateError, + 14 => { + let e66 = { + let l11 = i32::from(*ptr1.add(16).cast::()); + let l13 = i32::from( + *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + TlsAlertReceivedPayload { + alert_id: match l11 { + 0 => None, + 1 => { + let e = { + let l12 = i32::from(*ptr1.add(17).cast::()); + l12 as u8 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + alert_message: match l13 { + 0 => None, + 1 => { + let e = { + let l14 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len16 = l15; + let bytes16 = _rt::Vec::from_raw_parts( + l14.cast(), + len16, + len16, + ); + _rt::string_lift(bytes16) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::TlsAlertReceived(e66) + } + 15 => ErrorCode::HttpRequestDenied, + 16 => ErrorCode::HttpRequestLengthRequired, + 17 => { + let e66 = { + let l17 = i32::from(*ptr1.add(16).cast::()); + match l17 { + 0 => None, + 1 => { + let e = { + let l18 = *ptr1.add(24).cast::(); + l18 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestBodySize(e66) + } + 18 => ErrorCode::HttpRequestMethodInvalid, + 19 => ErrorCode::HttpRequestUriInvalid, + 20 => ErrorCode::HttpRequestUriTooLong, + 21 => { + let e66 = { + let l19 = i32::from(*ptr1.add(16).cast::()); + match l19 { + 0 => None, + 1 => { + let e = { + let l20 = *ptr1.add(20).cast::(); + l20 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSectionSize(e66) + } + 22 => { + let e66 = { + let l21 = i32::from(*ptr1.add(16).cast::()); + match l21 { + 0 => None, + 1 => { + let e = { + let l22 = i32::from( + *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l26 = i32::from( + *ptr1 + .add(16 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l22 { + 0 => None, + 1 => { + let e = { + let l23 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l24 = *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len25 = l24; + let bytes25 = _rt::Vec::from_raw_parts( + l23.cast(), + len25, + len25, + ); + _rt::string_lift(bytes25) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l26 { + 0 => None, + 1 => { + let e = { + let l27 = *ptr1 + .add(20 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l27 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSize(e66) + } + 23 => { + let e66 = { + let l28 = i32::from(*ptr1.add(16).cast::()); + match l28 { + 0 => None, + 1 => { + let e = { + let l29 = *ptr1.add(20).cast::(); + l29 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestTrailerSectionSize(e66) + } + 24 => { + let e66 = { + let l30 = i32::from(*ptr1.add(16).cast::()); + let l34 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l30 { + 0 => None, + 1 => { + let e = { + let l31 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l32 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len33 = l32; + let bytes33 = _rt::Vec::from_raw_parts( + l31.cast(), + len33, + len33, + ); + _rt::string_lift(bytes33) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l34 { + 0 => None, + 1 => { + let e = { + let l35 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l35 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpRequestTrailerSize(e66) + } + 25 => ErrorCode::HttpResponseIncomplete, + 26 => { + let e66 = { + let l36 = i32::from(*ptr1.add(16).cast::()); + match l36 { + 0 => None, + 1 => { + let e = { + let l37 = *ptr1.add(20).cast::(); + l37 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseHeaderSectionSize(e66) + } + 27 => { + let e66 = { + let l38 = i32::from(*ptr1.add(16).cast::()); + let l42 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l38 { + 0 => None, + 1 => { + let e = { + let l39 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l40 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len41 = l40; + let bytes41 = _rt::Vec::from_raw_parts( + l39.cast(), + len41, + len41, + ); + _rt::string_lift(bytes41) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l42 { + 0 => None, + 1 => { + let e = { + let l43 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l43 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseHeaderSize(e66) + } + 28 => { + let e66 = { + let l44 = i32::from(*ptr1.add(16).cast::()); + match l44 { + 0 => None, + 1 => { + let e = { + let l45 = *ptr1.add(24).cast::(); + l45 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseBodySize(e66) + } + 29 => { + let e66 = { + let l46 = i32::from(*ptr1.add(16).cast::()); + match l46 { + 0 => None, + 1 => { + let e = { + let l47 = *ptr1.add(20).cast::(); + l47 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTrailerSectionSize(e66) + } + 30 => { + let e66 = { + let l48 = i32::from(*ptr1.add(16).cast::()); + let l52 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l48 { + 0 => None, + 1 => { + let e = { + let l49 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l50 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len51 = l50; + let bytes51 = _rt::Vec::from_raw_parts( + l49.cast(), + len51, + len51, + ); + _rt::string_lift(bytes51) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l52 { + 0 => None, + 1 => { + let e = { + let l53 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l53 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseTrailerSize(e66) + } + 31 => { + let e66 = { + let l54 = i32::from(*ptr1.add(16).cast::()); + match l54 { + 0 => None, + 1 => { + let e = { + let l55 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l56 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len57 = l56; + let bytes57 = _rt::Vec::from_raw_parts( + l55.cast(), + len57, + len57, + ); + _rt::string_lift(bytes57) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTransferCoding(e66) + } + 32 => { + let e66 = { + let l58 = i32::from(*ptr1.add(16).cast::()); + match l58 { + 0 => None, + 1 => { + let e = { + let l59 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l60 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len61 = l60; + let bytes61 = _rt::Vec::from_raw_parts( + l59.cast(), + len61, + len61, + ); + _rt::string_lift(bytes61) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseContentCoding(e66) + } + 33 => ErrorCode::HttpResponseTimeout, + 34 => ErrorCode::HttpUpgradeFailed, + 35 => ErrorCode::HttpProtocolError, + 36 => ErrorCode::LoopDetected, + 37 => ErrorCode::ConfigurationError, + n => { + debug_assert_eq!(n, 38, "invalid enum discriminant"); + let e66 = { + let l62 = i32::from(*ptr1.add(16).cast::()); + match l62 { + 0 => None, + 1 => { + let e = { + let l63 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l64 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len65 = l64; + let bytes65 = _rt::Vec::from_raw_parts( + l63.cast(), + len65, + len65, + ); + _rt::string_lift(bytes65) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::InternalError(e66) + } + }; + v66 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result67 + } + } + } + impl FutureIncomingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + #[allow(async_fn_in_trait)] + pub fn subscribe(&self) -> Pollable { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]future-incoming-response.subscribe"] + fn wit_import0(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import0(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import0((self).handle() as i32); + super::super::super::__with_name0::Pollable::from_handle( + ret as u32, + ) + } + } + } + impl FutureIncomingResponse { + #[allow(unused_unsafe, clippy::all)] + /// Returns the incoming HTTP Response, or an error, once one is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the response or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the incoming HTTP Response + /// status and headers have received successfully, or that an error + /// occurred. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + #[allow(async_fn_in_trait)] + pub fn get( + &self, + ) -> Option, ()>> { + unsafe { + #[repr(align(8))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 40 + 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 40 + + 4 * ::core::mem::size_of::<*const u8>()], + ); + let ptr0 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/types@0.2.4")] + unsafe extern "C" { + #[link_name = "[method]future-incoming-response.get"] + fn wit_import1(_: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import1(_: i32, _: *mut u8) { + unreachable!() + } + wit_import1((self).handle() as i32, ptr0); + let l2 = i32::from(*ptr0.add(0).cast::()); + let result69 = match l2 { + 0 => None, + 1 => { + let e = { + let l3 = i32::from(*ptr0.add(8).cast::()); + match l3 { + 0 => { + let e = { + let l4 = i32::from(*ptr0.add(16).cast::()); + match l4 { + 0 => { + let e = { + let l5 = *ptr0.add(24).cast::(); + IncomingResponse::from_handle(l5 as u32) + }; + Ok(e) + } + 1 => { + let e = { + let l6 = i32::from(*ptr0.add(24).cast::()); + let v68 = match l6 { + 0 => ErrorCode::DnsTimeout, + 1 => { + let e68 = { + let l7 = i32::from(*ptr0.add(32).cast::()); + let l11 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + DnsErrorPayload { + rcode: match l7 { + 0 => None, + 1 => { + let e = { + let l8 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + let bytes10 = _rt::Vec::from_raw_parts( + l8.cast(), + len10, + len10, + ); + _rt::string_lift(bytes10) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + info_code: match l11 { + 0 => None, + 1 => { + let e = { + let l12 = i32::from( + *ptr0 + .add(34 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + l12 as u16 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::DnsError(e68) + } + 2 => ErrorCode::DestinationNotFound, + 3 => ErrorCode::DestinationUnavailable, + 4 => ErrorCode::DestinationIpProhibited, + 5 => ErrorCode::DestinationIpUnroutable, + 6 => ErrorCode::ConnectionRefused, + 7 => ErrorCode::ConnectionTerminated, + 8 => ErrorCode::ConnectionTimeout, + 9 => ErrorCode::ConnectionReadTimeout, + 10 => ErrorCode::ConnectionWriteTimeout, + 11 => ErrorCode::ConnectionLimitReached, + 12 => ErrorCode::TlsProtocolError, + 13 => ErrorCode::TlsCertificateError, + 14 => { + let e68 = { + let l13 = i32::from(*ptr0.add(32).cast::()); + let l15 = i32::from( + *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + TlsAlertReceivedPayload { + alert_id: match l13 { + 0 => None, + 1 => { + let e = { + let l14 = i32::from(*ptr0.add(33).cast::()); + l14 as u8 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + alert_message: match l15 { + 0 => None, + 1 => { + let e = { + let l16 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l17 = *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len18 = l17; + let bytes18 = _rt::Vec::from_raw_parts( + l16.cast(), + len18, + len18, + ); + _rt::string_lift(bytes18) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::TlsAlertReceived(e68) + } + 15 => ErrorCode::HttpRequestDenied, + 16 => ErrorCode::HttpRequestLengthRequired, + 17 => { + let e68 = { + let l19 = i32::from(*ptr0.add(32).cast::()); + match l19 { + 0 => None, + 1 => { + let e = { + let l20 = *ptr0.add(40).cast::(); + l20 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestBodySize(e68) + } + 18 => ErrorCode::HttpRequestMethodInvalid, + 19 => ErrorCode::HttpRequestUriInvalid, + 20 => ErrorCode::HttpRequestUriTooLong, + 21 => { + let e68 = { + let l21 = i32::from(*ptr0.add(32).cast::()); + match l21 { + 0 => None, + 1 => { + let e = { + let l22 = *ptr0.add(36).cast::(); + l22 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSectionSize(e68) + } + 22 => { + let e68 = { + let l23 = i32::from(*ptr0.add(32).cast::()); + match l23 { + 0 => None, + 1 => { + let e = { + let l24 = i32::from( + *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l28 = i32::from( + *ptr0 + .add(32 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l24 { + 0 => None, + 1 => { + let e = { + let l25 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l26 = *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len27 = l26; + let bytes27 = _rt::Vec::from_raw_parts( + l25.cast(), + len27, + len27, + ); + _rt::string_lift(bytes27) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l28 { + 0 => None, + 1 => { + let e = { + let l29 = *ptr0 + .add(36 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l29 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestHeaderSize(e68) + } + 23 => { + let e68 = { + let l30 = i32::from(*ptr0.add(32).cast::()); + match l30 { + 0 => None, + 1 => { + let e = { + let l31 = *ptr0.add(36).cast::(); + l31 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpRequestTrailerSectionSize(e68) + } + 24 => { + let e68 = { + let l32 = i32::from(*ptr0.add(32).cast::()); + let l36 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l32 { + 0 => None, + 1 => { + let e = { + let l33 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l34 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len35 = l34; + let bytes35 = _rt::Vec::from_raw_parts( + l33.cast(), + len35, + len35, + ); + _rt::string_lift(bytes35) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l36 { + 0 => None, + 1 => { + let e = { + let l37 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l37 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpRequestTrailerSize(e68) + } + 25 => ErrorCode::HttpResponseIncomplete, + 26 => { + let e68 = { + let l38 = i32::from(*ptr0.add(32).cast::()); + match l38 { + 0 => None, + 1 => { + let e = { + let l39 = *ptr0.add(36).cast::(); + l39 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseHeaderSectionSize(e68) + } + 27 => { + let e68 = { + let l40 = i32::from(*ptr0.add(32).cast::()); + let l44 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l40 { + 0 => None, + 1 => { + let e = { + let l41 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l42 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len43 = l42; + let bytes43 = _rt::Vec::from_raw_parts( + l41.cast(), + len43, + len43, + ); + _rt::string_lift(bytes43) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l44 { + 0 => None, + 1 => { + let e = { + let l45 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l45 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseHeaderSize(e68) + } + 28 => { + let e68 = { + let l46 = i32::from(*ptr0.add(32).cast::()); + match l46 { + 0 => None, + 1 => { + let e = { + let l47 = *ptr0.add(40).cast::(); + l47 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseBodySize(e68) + } + 29 => { + let e68 = { + let l48 = i32::from(*ptr0.add(32).cast::()); + match l48 { + 0 => None, + 1 => { + let e = { + let l49 = *ptr0.add(36).cast::(); + l49 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTrailerSectionSize(e68) + } + 30 => { + let e68 = { + let l50 = i32::from(*ptr0.add(32).cast::()); + let l54 = i32::from( + *ptr0 + .add(32 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + FieldSizePayload { + field_name: match l50 { + 0 => None, + 1 => { + let e = { + let l51 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l52 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len53 = l52; + let bytes53 = _rt::Vec::from_raw_parts( + l51.cast(), + len53, + len53, + ); + _rt::string_lift(bytes53) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l54 { + 0 => None, + 1 => { + let e = { + let l55 = *ptr0 + .add(36 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l55 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + ErrorCode::HttpResponseTrailerSize(e68) + } + 31 => { + let e68 = { + let l56 = i32::from(*ptr0.add(32).cast::()); + match l56 { + 0 => None, + 1 => { + let e = { + let l57 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l58 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len59 = l58; + let bytes59 = _rt::Vec::from_raw_parts( + l57.cast(), + len59, + len59, + ); + _rt::string_lift(bytes59) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseTransferCoding(e68) + } + 32 => { + let e68 = { + let l60 = i32::from(*ptr0.add(32).cast::()); + match l60 { + 0 => None, + 1 => { + let e = { + let l61 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l62 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len63 = l62; + let bytes63 = _rt::Vec::from_raw_parts( + l61.cast(), + len63, + len63, + ); + _rt::string_lift(bytes63) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::HttpResponseContentCoding(e68) + } + 33 => ErrorCode::HttpResponseTimeout, + 34 => ErrorCode::HttpUpgradeFailed, + 35 => ErrorCode::HttpProtocolError, + 36 => ErrorCode::LoopDetected, + 37 => ErrorCode::ConfigurationError, + n => { + debug_assert_eq!(n, 38, "invalid enum discriminant"); + let e68 = { + let l64 = i32::from(*ptr0.add(32).cast::()); + match l64 { + 0 => None, + 1 => { + let e = { + let l65 = *ptr0 + .add(32 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l66 = *ptr0 + .add(32 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len67 = l66; + let bytes67 = _rt::Vec::from_raw_parts( + l65.cast(), + len67, + len67, + ); + _rt::string_lift(bytes67) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + ErrorCode::InternalError(e68) + } + }; + v68 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Ok(e) + } + 1 => { + let e = (); + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result69 + } + } + } + } + /// This interface defines a handler of outgoing HTTP Requests. It should be + /// imported by components which wish to make HTTP Requests. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod outgoing_handler { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + pub type OutgoingRequest = super::super::super::wasi::http::types::OutgoingRequest; + pub type RequestOptions = super::super::super::wasi::http::types::RequestOptions; + pub type FutureIncomingResponse = super::super::super::wasi::http::types::FutureIncomingResponse; + pub type ErrorCode = super::super::super::wasi::http::types::ErrorCode; + #[allow(unused_unsafe, clippy::all)] + /// This function is invoked with an outgoing HTTP Request, and it returns + /// a resource `future-incoming-response` which represents an HTTP Response + /// which may arrive in the future. + /// + /// The `options` argument accepts optional parameters for the HTTP + /// protocol's transport layer. + /// + /// This function may return an error if the `outgoing-request` is invalid + /// or not allowed to be made. Otherwise, protocol errors are reported + /// through the `future-incoming-response`. + #[allow(async_fn_in_trait)] + pub fn handle( + request: OutgoingRequest, + options: Option, + ) -> Result { + unsafe { + #[repr(align(8))] + struct RetArea( + [::core::mem::MaybeUninit< + u8, + >; 24 + 4 * ::core::mem::size_of::<*const u8>()], + ); + let mut ret_area = RetArea( + [::core::mem::MaybeUninit::uninit(); 24 + + 4 * ::core::mem::size_of::<*const u8>()], + ); + let (result0_0, result0_1) = match &options { + Some(e) => (1i32, (e).take_handle() as i32), + None => (0i32, 0i32), + }; + let ptr1 = ret_area.0.as_mut_ptr().cast::(); + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:http/outgoing-handler@0.2.4")] + unsafe extern "C" { + #[link_name = "handle"] + fn wit_import2(_: i32, _: i32, _: i32, _: *mut u8); + } + #[cfg(not(target_arch = "wasm32"))] + unsafe extern "C" fn wit_import2( + _: i32, + _: i32, + _: i32, + _: *mut u8, + ) { + unreachable!() + } + wit_import2( + (&request).take_handle() as i32, + result0_0, + result0_1, + ptr1, + ); + let l3 = i32::from(*ptr1.add(0).cast::()); + let result68 = match l3 { + 0 => { + let e = { + let l4 = *ptr1.add(8).cast::(); + super::super::super::wasi::http::types::FutureIncomingResponse::from_handle( + l4 as u32, + ) + }; + Ok(e) + } + 1 => { + let e = { + let l5 = i32::from(*ptr1.add(8).cast::()); + use super::super::super::wasi::http::types::ErrorCode as V67; + let v67 = match l5 { + 0 => V67::DnsTimeout, + 1 => { + let e67 = { + let l6 = i32::from(*ptr1.add(16).cast::()); + let l10 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::DnsErrorPayload { + rcode: match l6 { + 0 => None, + 1 => { + let e = { + let l7 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len9 = l8; + let bytes9 = _rt::Vec::from_raw_parts( + l7.cast(), + len9, + len9, + ); + _rt::string_lift(bytes9) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + info_code: match l10 { + 0 => None, + 1 => { + let e = { + let l11 = i32::from( + *ptr1 + .add(18 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + l11 as u16 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + V67::DnsError(e67) + } + 2 => V67::DestinationNotFound, + 3 => V67::DestinationUnavailable, + 4 => V67::DestinationIpProhibited, + 5 => V67::DestinationIpUnroutable, + 6 => V67::ConnectionRefused, + 7 => V67::ConnectionTerminated, + 8 => V67::ConnectionTimeout, + 9 => V67::ConnectionReadTimeout, + 10 => V67::ConnectionWriteTimeout, + 11 => V67::ConnectionLimitReached, + 12 => V67::TlsProtocolError, + 13 => V67::TlsCertificateError, + 14 => { + let e67 = { + let l12 = i32::from(*ptr1.add(16).cast::()); + let l14 = i32::from( + *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::TlsAlertReceivedPayload { + alert_id: match l12 { + 0 => None, + 1 => { + let e = { + let l13 = i32::from(*ptr1.add(17).cast::()); + l13 as u8 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + alert_message: match l14 { + 0 => None, + 1 => { + let e = { + let l15 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l16 = *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len17 = l16; + let bytes17 = _rt::Vec::from_raw_parts( + l15.cast(), + len17, + len17, + ); + _rt::string_lift(bytes17) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + V67::TlsAlertReceived(e67) + } + 15 => V67::HttpRequestDenied, + 16 => V67::HttpRequestLengthRequired, + 17 => { + let e67 = { + let l18 = i32::from(*ptr1.add(16).cast::()); + match l18 { + 0 => None, + 1 => { + let e = { + let l19 = *ptr1.add(24).cast::(); + l19 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpRequestBodySize(e67) + } + 18 => V67::HttpRequestMethodInvalid, + 19 => V67::HttpRequestUriInvalid, + 20 => V67::HttpRequestUriTooLong, + 21 => { + let e67 = { + let l20 = i32::from(*ptr1.add(16).cast::()); + match l20 { + 0 => None, + 1 => { + let e = { + let l21 = *ptr1.add(20).cast::(); + l21 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpRequestHeaderSectionSize(e67) + } + 22 => { + let e67 = { + let l22 = i32::from(*ptr1.add(16).cast::()); + match l22 { + 0 => None, + 1 => { + let e = { + let l23 = i32::from( + *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + let l27 = i32::from( + *ptr1 + .add(16 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::FieldSizePayload { + field_name: match l23 { + 0 => None, + 1 => { + let e = { + let l24 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l25 = *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len26 = l25; + let bytes26 = _rt::Vec::from_raw_parts( + l24.cast(), + len26, + len26, + ); + _rt::string_lift(bytes26) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l27 { + 0 => None, + 1 => { + let e = { + let l28 = *ptr1 + .add(20 + 4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l28 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpRequestHeaderSize(e67) + } + 23 => { + let e67 = { + let l29 = i32::from(*ptr1.add(16).cast::()); + match l29 { + 0 => None, + 1 => { + let e = { + let l30 = *ptr1.add(20).cast::(); + l30 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpRequestTrailerSectionSize(e67) + } + 24 => { + let e67 = { + let l31 = i32::from(*ptr1.add(16).cast::()); + let l35 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::FieldSizePayload { + field_name: match l31 { + 0 => None, + 1 => { + let e = { + let l32 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l33 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len34 = l33; + let bytes34 = _rt::Vec::from_raw_parts( + l32.cast(), + len34, + len34, + ); + _rt::string_lift(bytes34) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l35 { + 0 => None, + 1 => { + let e = { + let l36 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l36 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + V67::HttpRequestTrailerSize(e67) + } + 25 => V67::HttpResponseIncomplete, + 26 => { + let e67 = { + let l37 = i32::from(*ptr1.add(16).cast::()); + match l37 { + 0 => None, + 1 => { + let e = { + let l38 = *ptr1.add(20).cast::(); + l38 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpResponseHeaderSectionSize(e67) + } + 27 => { + let e67 = { + let l39 = i32::from(*ptr1.add(16).cast::()); + let l43 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::FieldSizePayload { + field_name: match l39 { + 0 => None, + 1 => { + let e = { + let l40 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l41 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len42 = l41; + let bytes42 = _rt::Vec::from_raw_parts( + l40.cast(), + len42, + len42, + ); + _rt::string_lift(bytes42) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l43 { + 0 => None, + 1 => { + let e = { + let l44 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l44 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + V67::HttpResponseHeaderSize(e67) + } + 28 => { + let e67 = { + let l45 = i32::from(*ptr1.add(16).cast::()); + match l45 { + 0 => None, + 1 => { + let e = { + let l46 = *ptr1.add(24).cast::(); + l46 as u64 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpResponseBodySize(e67) + } + 29 => { + let e67 = { + let l47 = i32::from(*ptr1.add(16).cast::()); + match l47 { + 0 => None, + 1 => { + let e = { + let l48 = *ptr1.add(20).cast::(); + l48 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpResponseTrailerSectionSize(e67) + } + 30 => { + let e67 = { + let l49 = i32::from(*ptr1.add(16).cast::()); + let l53 = i32::from( + *ptr1 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + super::super::super::wasi::http::types::FieldSizePayload { + field_name: match l49 { + 0 => None, + 1 => { + let e = { + let l50 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l51 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len52 = l51; + let bytes52 = _rt::Vec::from_raw_parts( + l50.cast(), + len52, + len52, + ); + _rt::string_lift(bytes52) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + field_size: match l53 { + 0 => None, + 1 => { + let e = { + let l54 = *ptr1 + .add(20 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + l54 as u32 + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + } + }; + V67::HttpResponseTrailerSize(e67) + } + 31 => { + let e67 = { + let l55 = i32::from(*ptr1.add(16).cast::()); + match l55 { + 0 => None, + 1 => { + let e = { + let l56 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l57 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len58 = l57; + let bytes58 = _rt::Vec::from_raw_parts( + l56.cast(), + len58, + len58, + ); + _rt::string_lift(bytes58) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpResponseTransferCoding(e67) + } + 32 => { + let e67 = { + let l59 = i32::from(*ptr1.add(16).cast::()); + match l59 { + 0 => None, + 1 => { + let e = { + let l60 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l61 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len62 = l61; + let bytes62 = _rt::Vec::from_raw_parts( + l60.cast(), + len62, + len62, + ); + _rt::string_lift(bytes62) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::HttpResponseContentCoding(e67) + } + 33 => V67::HttpResponseTimeout, + 34 => V67::HttpUpgradeFailed, + 35 => V67::HttpProtocolError, + 36 => V67::LoopDetected, + 37 => V67::ConfigurationError, + n => { + debug_assert_eq!(n, 38, "invalid enum discriminant"); + let e67 = { + let l63 = i32::from(*ptr1.add(16).cast::()); + match l63 { + 0 => None, + 1 => { + let e = { + let l64 = *ptr1 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l65 = *ptr1 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len66 = l65; + let bytes66 = _rt::Vec::from_raw_parts( + l64.cast(), + len66, + len66, + ); + _rt::string_lift(bytes66) + }; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + } + }; + V67::InternalError(e67) + } + }; + v67 + }; + Err(e) + } + _ => _rt::invalid_enum_discriminant(), + }; + result68 + } + } + } + } +} +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] +pub mod exports { + pub mod wasi { + pub mod http { + /// This interface defines a handler of incoming HTTP Requests. It should + /// be exported by components which can respond to HTTP Requests. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod incoming_handler { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type IncomingRequest = super::super::super::super::wasi::http::types::IncomingRequest; + pub type ResponseOutparam = super::super::super::super::wasi::http::types::ResponseOutparam; + #[doc(hidden)] + #[allow(non_snake_case, unused_unsafe)] + pub unsafe fn _export_handle_cabi(arg0: i32, arg1: i32) { + unsafe { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + { + T::handle( + super::super::super::super::wasi::http::types::IncomingRequest::from_handle( + arg0 as u32, + ), + super::super::super::super::wasi::http::types::ResponseOutparam::from_handle( + arg1 as u32, + ), + ) + }; + } + } + pub trait Guest { + /// This function is invoked with an incoming HTTP Request, and a resource + /// `response-outparam` which provides the capability to reply with an HTTP + /// Response. The response is sent by calling the `response-outparam.set` + /// method, which allows execution to continue after the response has been + /// sent. This enables both streaming to the response body, and performing other + /// work. + /// + /// The implementor of this function must write a response to the + /// `response-outparam` before returning, or else the caller will respond + /// with an error on its behalf. + #[allow(async_fn_in_trait)] + fn handle( + request: IncomingRequest, + response_out: ResponseOutparam, + ) -> (); + } + #[doc(hidden)] + #[macro_export] + macro_rules! __export_wasi_http_incoming_handler_0_2_4_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "wasi:http/incoming-handler@0.2.4#handle")] unsafe extern "C" fn + export_handle(arg0 : i32, arg1 : i32,) { unsafe { + $($path_to_types)*:: _export_handle_cabi::<$ty > (arg0, arg1) } } + }; + }; + } + #[doc(hidden)] + pub use __export_wasi_http_incoming_handler_0_2_4_cabi; + } + } + } +} +#[rustfmt::skip] +mod _rt { + #![allow(dead_code, clippy::all)] + pub use alloc_crate::string::String; + pub use alloc_crate::vec::Vec; + use core::fmt; + use core::marker; + use core::sync::atomic::{AtomicU32, Ordering::Relaxed}; + /// A type which represents a component model resource, either imported or + /// exported into this component. + /// + /// This is a low-level wrapper which handles the lifetime of the resource + /// (namely this has a destructor). The `T` provided defines the component model + /// intrinsics that this wrapper uses. + /// + /// One of the chief purposes of this type is to provide `Deref` implementations + /// to access the underlying data when it is owned. + /// + /// This type is primarily used in generated code for exported and imported + /// resources. + #[repr(transparent)] + pub struct Resource { + handle: AtomicU32, + _marker: marker::PhantomData, + } + /// A trait which all wasm resources implement, namely providing the ability to + /// drop a resource. + /// + /// This generally is implemented by generated code, not user-facing code. + #[allow(clippy::missing_safety_doc)] + pub unsafe trait WasmResource { + /// Invokes the `[resource-drop]...` intrinsic. + unsafe fn drop(handle: u32); + } + impl Resource { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + debug_assert!(handle != 0 && handle != u32::MAX); + Self { + handle: AtomicU32::new(handle), + _marker: marker::PhantomData, + } + } + /// Takes ownership of the handle owned by `resource`. + /// + /// Note that this ideally would be `into_handle` taking `Resource` by + /// ownership. The code generator does not enable that in all situations, + /// unfortunately, so this is provided instead. + /// + /// Also note that `take_handle` is in theory only ever called on values + /// owned by a generated function. For example a generated function might + /// take `Resource` as an argument but then call `take_handle` on a + /// reference to that argument. In that sense the dynamic nature of + /// `take_handle` should only be exposed internally to generated code, not + /// to user code. + #[doc(hidden)] + pub fn take_handle(resource: &Resource) -> u32 { + resource.handle.swap(u32::MAX, Relaxed) + } + #[doc(hidden)] + pub fn handle(resource: &Resource) -> u32 { + resource.handle.load(Relaxed) + } + } + impl fmt::Debug for Resource { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Resource").field("handle", &self.handle).finish() + } + } + impl Drop for Resource { + fn drop(&mut self) { + unsafe { + match self.handle.load(Relaxed) { + u32::MAX => {} + other => T::drop(other), + } + } + } + } + pub unsafe fn string_lift(bytes: Vec) -> String { + if cfg!(debug_assertions) { + String::from_utf8(bytes).unwrap() + } else { + unsafe { String::from_utf8_unchecked(bytes) } + } + } + pub unsafe fn invalid_enum_discriminant() -> T { + if cfg!(debug_assertions) { + panic!("invalid enum discriminant") + } else { + unsafe { core::hint::unreachable_unchecked() } + } + } + pub use alloc_crate::alloc; + pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) { + if size == 0 { + return; + } + unsafe { + let layout = alloc::Layout::from_size_align_unchecked(size, align); + alloc::dealloc(ptr, layout); + } + } + pub unsafe fn bool_lift(val: u8) -> bool { + if cfg!(debug_assertions) { + match val { + 0 => false, + 1 => true, + _ => panic!("invalid bool discriminant"), + } + } else { + val != 0 + } + } + pub fn as_i64(t: T) -> i64 { + t.as_i64() + } + pub trait AsI64 { + fn as_i64(self) -> i64; + } + impl<'a, T: Copy + AsI64> AsI64 for &'a T { + fn as_i64(self) -> i64 { + (*self).as_i64() + } + } + impl AsI64 for i64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + impl AsI64 for u64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + pub trait AsI32 { + fn as_i32(self) -> i32; + } + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen::rt::run_ctors_once(); + } + extern crate alloc as alloc_crate; +} +/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as +/// the root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! _export_proxy{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// _export_proxy!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] +#[macro_export] +macro_rules! __export_proxy_impl { + ($ty:ident) => { + $crate::_export_proxy!($ty with_types_in $crate); + }; + ($ty:ident with_types_in $($path_to_types_root:tt)*) => { + $($path_to_types_root)*:: + exports::wasi::http::incoming_handler::__export_wasi_http_incoming_handler_0_2_4_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::wasi::http::incoming_handler); + const _ : () = { #[rustfmt::skip] #[cfg(target_arch = "wasm32")] #[unsafe + (link_section = + "component-type:wit-bindgen:0.46.0:wasi:http@0.2.4:proxy:imports and exportsrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-proxy-world")] + #[doc(hidden)] #[allow(clippy::octal_escapes)] pub static + __WIT_BINDGEN_COMPONENT_TYPE : [u8; 7040] = * + b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x846\x01A\x02\x01A#\x01\ +B\x0a\x04\0\x08pollable\x03\x01\x01h\0\x01@\x01\x04self\x01\0\x7f\x04\0\x16[meth\ +od]pollable.ready\x01\x02\x01@\x01\x04self\x01\x01\0\x04\0\x16[method]pollable.b\ +lock\x01\x03\x01p\x01\x01py\x01@\x01\x02in\x04\0\x05\x04\0\x04poll\x01\x06\x03\0\ +\x12wasi:io/poll@0.2.4\x05\0\x02\x03\0\0\x08pollable\x01B\x0f\x02\x03\x02\x01\x01\ +\x04\0\x08pollable\x03\0\0\x01w\x04\0\x07instant\x03\0\x02\x01w\x04\0\x08duratio\ +n\x03\0\x04\x01@\0\0\x03\x04\0\x03now\x01\x06\x01@\0\0\x05\x04\0\x0aresolution\x01\ +\x07\x01i\x01\x01@\x01\x04when\x03\0\x08\x04\0\x11subscribe-instant\x01\x09\x01@\ +\x01\x04when\x05\0\x08\x04\0\x12subscribe-duration\x01\x0a\x03\0!wasi:clocks/mon\ +otonic-clock@0.2.4\x05\x02\x01B\x05\x01r\x02\x07secondsw\x0bnanosecondsy\x04\0\x08\ +datetime\x03\0\0\x01@\0\0\x01\x04\0\x03now\x01\x02\x04\0\x0aresolution\x01\x02\x03\ +\0\x1cwasi:clocks/wall-clock@0.2.4\x05\x03\x01B\x05\x01p}\x01@\x01\x03lenw\0\0\x04\ +\0\x10get-random-bytes\x01\x01\x01@\0\0w\x04\0\x0eget-random-u64\x01\x02\x03\0\x18\ +wasi:random/random@0.2.4\x05\x04\x01B\x04\x04\0\x05error\x03\x01\x01h\0\x01@\x01\ +\x04self\x01\0s\x04\0\x1d[method]error.to-debug-string\x01\x02\x03\0\x13wasi:io/\ +error@0.2.4\x05\x05\x02\x03\0\x04\x05error\x01B(\x02\x03\x02\x01\x06\x04\0\x05er\ +ror\x03\0\0\x02\x03\x02\x01\x01\x04\0\x08pollable\x03\0\x02\x01i\x01\x01q\x02\x15\ +last-operation-failed\x01\x04\0\x06closed\0\0\x04\0\x0cstream-error\x03\0\x05\x04\ +\0\x0cinput-stream\x03\x01\x04\0\x0doutput-stream\x03\x01\x01h\x07\x01p}\x01j\x01\ +\x0a\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0b\x04\0\x19[method]input-stream.re\ +ad\x01\x0c\x04\0\"[method]input-stream.blocking-read\x01\x0c\x01j\x01w\x01\x06\x01\ +@\x02\x04self\x09\x03lenw\0\x0d\x04\0\x19[method]input-stream.skip\x01\x0e\x04\0\ +\"[method]input-stream.blocking-skip\x01\x0e\x01i\x03\x01@\x01\x04self\x09\0\x0f\ +\x04\0\x1e[method]input-stream.subscribe\x01\x10\x01h\x08\x01@\x01\x04self\x11\0\ +\x0d\x04\0![method]output-stream.check-write\x01\x12\x01j\0\x01\x06\x01@\x02\x04\ +self\x11\x08contents\x0a\0\x13\x04\0\x1b[method]output-stream.write\x01\x14\x04\0\ +.[method]output-stream.blocking-write-and-flush\x01\x14\x01@\x01\x04self\x11\0\x13\ +\x04\0\x1b[method]output-stream.flush\x01\x15\x04\0$[method]output-stream.blocki\ +ng-flush\x01\x15\x01@\x01\x04self\x11\0\x0f\x04\0\x1f[method]output-stream.subsc\ +ribe\x01\x16\x01@\x02\x04self\x11\x03lenw\0\x13\x04\0\"[method]output-stream.wri\ +te-zeroes\x01\x17\x04\05[method]output-stream.blocking-write-zeroes-and-flush\x01\ +\x17\x01@\x03\x04self\x11\x03src\x09\x03lenw\0\x0d\x04\0\x1c[method]output-strea\ +m.splice\x01\x18\x04\0%[method]output-stream.blocking-splice\x01\x18\x03\0\x15wa\ +si:io/streams@0.2.4\x05\x07\x02\x03\0\x05\x0doutput-stream\x01B\x05\x02\x03\x02\x01\ +\x08\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0aget-stdout\x01\ +\x03\x03\0\x15wasi:cli/stdout@0.2.4\x05\x09\x01B\x05\x02\x03\x02\x01\x08\x04\0\x0d\ +output-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0aget-stderr\x01\x03\x03\0\x15\ +wasi:cli/stderr@0.2.4\x05\x0a\x02\x03\0\x05\x0cinput-stream\x01B\x05\x02\x03\x02\ +\x01\x0b\x04\0\x0cinput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x09get-stdin\x01\ +\x03\x03\0\x14wasi:cli/stdin@0.2.4\x05\x0c\x02\x03\0\x01\x08duration\x01B\xc1\x01\ +\x02\x03\x02\x01\x0d\x04\0\x08duration\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x0cinpu\ +t-stream\x03\0\x02\x02\x03\x02\x01\x08\x04\0\x0doutput-stream\x03\0\x04\x02\x03\x02\ +\x01\x06\x04\0\x08io-error\x03\0\x06\x02\x03\x02\x01\x01\x04\0\x08pollable\x03\0\ +\x08\x01q\x0a\x03get\0\0\x04head\0\0\x04post\0\0\x03put\0\0\x06delete\0\0\x07con\ +nect\0\0\x07options\0\0\x05trace\0\0\x05patch\0\0\x05other\x01s\0\x04\0\x06metho\ +d\x03\0\x0a\x01q\x03\x04HTTP\0\0\x05HTTPS\0\0\x05other\x01s\0\x04\0\x06scheme\x03\ +\0\x0c\x01ks\x01k{\x01r\x02\x05rcode\x0e\x09info-code\x0f\x04\0\x11DNS-error-pay\ +load\x03\0\x10\x01k}\x01r\x02\x08alert-id\x12\x0dalert-message\x0e\x04\0\x1aTLS-\ +alert-received-payload\x03\0\x13\x01ky\x01r\x02\x0afield-name\x0e\x0afield-size\x15\ +\x04\0\x12field-size-payload\x03\0\x16\x01kw\x01k\x17\x01q'\x0bDNS-timeout\0\0\x09\ +DNS-error\x01\x11\0\x15destination-not-found\0\0\x17destination-unavailable\0\0\x19\ +destination-IP-prohibited\0\0\x19destination-IP-unroutable\0\0\x12connection-ref\ +used\0\0\x15connection-terminated\0\0\x12connection-timeout\0\0\x17connection-re\ +ad-timeout\0\0\x18connection-write-timeout\0\0\x18connection-limit-reached\0\0\x12\ +TLS-protocol-error\0\0\x15TLS-certificate-error\0\0\x12TLS-alert-received\x01\x14\ +\0\x13HTTP-request-denied\0\0\x1cHTTP-request-length-required\0\0\x16HTTP-reques\ +t-body-size\x01\x18\0\x1bHTTP-request-method-invalid\0\0\x18HTTP-request-URI-inv\ +alid\0\0\x19HTTP-request-URI-too-long\0\0\x20HTTP-request-header-section-size\x01\ +\x15\0\x18HTTP-request-header-size\x01\x19\0!HTTP-request-trailer-section-size\x01\ +\x15\0\x19HTTP-request-trailer-size\x01\x17\0\x18HTTP-response-incomplete\0\0!HT\ +TP-response-header-section-size\x01\x15\0\x19HTTP-response-header-size\x01\x17\0\ +\x17HTTP-response-body-size\x01\x18\0\"HTTP-response-trailer-section-size\x01\x15\ +\0\x1aHTTP-response-trailer-size\x01\x17\0\x1dHTTP-response-transfer-coding\x01\x0e\ +\0\x1cHTTP-response-content-coding\x01\x0e\0\x15HTTP-response-timeout\0\0\x13HTT\ +P-upgrade-failed\0\0\x13HTTP-protocol-error\0\0\x0dloop-detected\0\0\x13configur\ +ation-error\0\0\x0einternal-error\x01\x0e\0\x04\0\x0aerror-code\x03\0\x1a\x01q\x03\ +\x0einvalid-syntax\0\0\x09forbidden\0\0\x09immutable\0\0\x04\0\x0cheader-error\x03\ +\0\x1c\x01s\x04\0\x09field-key\x03\0\x1e\x04\0\x0afield-name\x03\0\x1f\x01p}\x04\ +\0\x0bfield-value\x03\0!\x04\0\x06fields\x03\x01\x04\0\x07headers\x03\0#\x04\0\x08\ +trailers\x03\0#\x04\0\x10incoming-request\x03\x01\x04\0\x10outgoing-request\x03\x01\ +\x04\0\x0frequest-options\x03\x01\x04\0\x11response-outparam\x03\x01\x01{\x04\0\x0b\ +status-code\x03\0*\x04\0\x11incoming-response\x03\x01\x04\0\x0dincoming-body\x03\ +\x01\x04\0\x0ffuture-trailers\x03\x01\x04\0\x11outgoing-response\x03\x01\x04\0\x0d\ +outgoing-body\x03\x01\x04\0\x18future-incoming-response\x03\x01\x01i#\x01@\0\02\x04\ +\0\x13[constructor]fields\x013\x01o\x02\x20\"\x01p4\x01j\x012\x01\x1d\x01@\x01\x07\ +entries5\06\x04\0\x18[static]fields.from-list\x017\x01h#\x01p\"\x01@\x02\x04self\ +8\x04name\x20\09\x04\0\x12[method]fields.get\x01:\x01@\x02\x04self8\x04name\x20\0\ +\x7f\x04\0\x12[method]fields.has\x01;\x01j\0\x01\x1d\x01@\x03\x04self8\x04name\x20\ +\x05value9\0<\x04\0\x12[method]fields.set\x01=\x01@\x02\x04self8\x04name\x20\0<\x04\ +\0\x15[method]fields.delete\x01>\x01@\x03\x04self8\x04name\x20\x05value\"\0<\x04\ +\0\x15[method]fields.append\x01?\x01@\x01\x04self8\05\x04\0\x16[method]fields.en\ +tries\x01@\x01@\x01\x04self8\02\x04\0\x14[method]fields.clone\x01A\x01h&\x01@\x01\ +\x04self\xc2\0\0\x0b\x04\0\x1f[method]incoming-request.method\x01C\x01@\x01\x04s\ +elf\xc2\0\0\x0e\x04\0([method]incoming-request.path-with-query\x01D\x01k\x0d\x01\ +@\x01\x04self\xc2\0\0\xc5\0\x04\0\x1f[method]incoming-request.scheme\x01F\x04\0\"\ +[method]incoming-request.authority\x01D\x01i$\x01@\x01\x04self\xc2\0\0\xc7\0\x04\ +\0\x20[method]incoming-request.headers\x01H\x01i-\x01j\x01\xc9\0\0\x01@\x01\x04s\ +elf\xc2\0\0\xca\0\x04\0\x20[method]incoming-request.consume\x01K\x01i'\x01@\x01\x07\ +headers\xc7\0\0\xcc\0\x04\0\x1d[constructor]outgoing-request\x01M\x01h'\x01i0\x01\ +j\x01\xcf\0\0\x01@\x01\x04self\xce\0\0\xd0\0\x04\0\x1d[method]outgoing-request.b\ +ody\x01Q\x01@\x01\x04self\xce\0\0\x0b\x04\0\x1f[method]outgoing-request.method\x01\ +R\x01j\0\0\x01@\x02\x04self\xce\0\x06method\x0b\0\xd3\0\x04\0#[method]outgoing-r\ +equest.set-method\x01T\x01@\x01\x04self\xce\0\0\x0e\x04\0([method]outgoing-reque\ +st.path-with-query\x01U\x01@\x02\x04self\xce\0\x0fpath-with-query\x0e\0\xd3\0\x04\ +\0,[method]outgoing-request.set-path-with-query\x01V\x01@\x01\x04self\xce\0\0\xc5\ +\0\x04\0\x1f[method]outgoing-request.scheme\x01W\x01@\x02\x04self\xce\0\x06schem\ +e\xc5\0\0\xd3\0\x04\0#[method]outgoing-request.set-scheme\x01X\x04\0\"[method]ou\ +tgoing-request.authority\x01U\x01@\x02\x04self\xce\0\x09authority\x0e\0\xd3\0\x04\ +\0&[method]outgoing-request.set-authority\x01Y\x01@\x01\x04self\xce\0\0\xc7\0\x04\ +\0\x20[method]outgoing-request.headers\x01Z\x01i(\x01@\0\0\xdb\0\x04\0\x1c[const\ +ructor]request-options\x01\\\x01h(\x01k\x01\x01@\x01\x04self\xdd\0\0\xde\0\x04\0\ +'[method]request-options.connect-timeout\x01_\x01@\x02\x04self\xdd\0\x08duration\ +\xde\0\0\xd3\0\x04\0+[method]request-options.set-connect-timeout\x01`\x04\0*[met\ +hod]request-options.first-byte-timeout\x01_\x04\0.[method]request-options.set-fi\ +rst-byte-timeout\x01`\x04\0-[method]request-options.between-bytes-timeout\x01_\x04\ +\01[method]request-options.set-between-bytes-timeout\x01`\x01i)\x01i/\x01j\x01\xe2\ +\0\x01\x1b\x01@\x02\x05param\xe1\0\x08response\xe3\0\x01\0\x04\0\x1d[static]resp\ +onse-outparam.set\x01d\x01h,\x01@\x01\x04self\xe5\0\0+\x04\0\x20[method]incoming\ +-response.status\x01f\x01@\x01\x04self\xe5\0\0\xc7\0\x04\0![method]incoming-resp\ +onse.headers\x01g\x01@\x01\x04self\xe5\0\0\xca\0\x04\0![method]incoming-response\ +.consume\x01h\x01h-\x01i\x03\x01j\x01\xea\0\0\x01@\x01\x04self\xe9\0\0\xeb\0\x04\ +\0\x1c[method]incoming-body.stream\x01l\x01i.\x01@\x01\x04this\xc9\0\0\xed\0\x04\ +\0\x1c[static]incoming-body.finish\x01n\x01h.\x01i\x09\x01@\x01\x04self\xef\0\0\xf0\ +\0\x04\0![method]future-trailers.subscribe\x01q\x01i%\x01k\xf2\0\x01j\x01\xf3\0\x01\ +\x1b\x01j\x01\xf4\0\0\x01k\xf5\0\x01@\x01\x04self\xef\0\0\xf6\0\x04\0\x1b[method\ +]future-trailers.get\x01w\x01@\x01\x07headers\xc7\0\0\xe2\0\x04\0\x1e[constructo\ +r]outgoing-response\x01x\x01h/\x01@\x01\x04self\xf9\0\0+\x04\0%[method]outgoing-\ +response.status-code\x01z\x01@\x02\x04self\xf9\0\x0bstatus-code+\0\xd3\0\x04\0)[\ +method]outgoing-response.set-status-code\x01{\x01@\x01\x04self\xf9\0\0\xc7\0\x04\ +\0![method]outgoing-response.headers\x01|\x01@\x01\x04self\xf9\0\0\xd0\0\x04\0\x1e\ +[method]outgoing-response.body\x01}\x01h0\x01i\x05\x01j\x01\xff\0\0\x01@\x01\x04\ +self\xfe\0\0\x80\x01\x04\0\x1b[method]outgoing-body.write\x01\x81\x01\x01j\0\x01\ +\x1b\x01@\x02\x04this\xcf\0\x08trailers\xf3\0\0\x82\x01\x04\0\x1c[static]outgoin\ +g-body.finish\x01\x83\x01\x01h1\x01@\x01\x04self\x84\x01\0\xf0\0\x04\0*[method]f\ +uture-incoming-response.subscribe\x01\x85\x01\x01i,\x01j\x01\x86\x01\x01\x1b\x01\ +j\x01\x87\x01\0\x01k\x88\x01\x01@\x01\x04self\x84\x01\0\x89\x01\x04\0$[method]fu\ +ture-incoming-response.get\x01\x8a\x01\x01h\x07\x01k\x1b\x01@\x01\x03err\x8b\x01\ +\0\x8c\x01\x04\0\x0fhttp-error-code\x01\x8d\x01\x03\0\x15wasi:http/types@0.2.4\x05\ +\x0e\x02\x03\0\x09\x10outgoing-request\x02\x03\0\x09\x0frequest-options\x02\x03\0\ +\x09\x18future-incoming-response\x02\x03\0\x09\x0aerror-code\x01B\x0f\x02\x03\x02\ +\x01\x0f\x04\0\x10outgoing-request\x03\0\0\x02\x03\x02\x01\x10\x04\0\x0frequest-\ +options\x03\0\x02\x02\x03\x02\x01\x11\x04\0\x18future-incoming-response\x03\0\x04\ +\x02\x03\x02\x01\x12\x04\0\x0aerror-code\x03\0\x06\x01i\x01\x01i\x03\x01k\x09\x01\ +i\x05\x01j\x01\x0b\x01\x07\x01@\x02\x07request\x08\x07options\x0a\0\x0c\x04\0\x06\ +handle\x01\x0d\x03\0\x20wasi:http/outgoing-handler@0.2.4\x05\x13\x02\x03\0\x09\x10\ +incoming-request\x02\x03\0\x09\x11response-outparam\x01B\x08\x02\x03\x02\x01\x14\ +\x04\0\x10incoming-request\x03\0\0\x02\x03\x02\x01\x15\x04\0\x11response-outpara\ +m\x03\0\x02\x01i\x01\x01i\x03\x01@\x02\x07request\x04\x0cresponse-out\x05\x01\0\x04\ +\0\x06handle\x01\x06\x04\0\x20wasi:http/incoming-handler@0.2.4\x05\x16\x04\0\x15\ +wasi:http/proxy@0.2.4\x04\0\x0b\x0b\x01\0\x05proxy\x03\0\0\0G\x09producers\x01\x0c\ +processed-by\x02\x0dwit-component\x070.239.0\x10wit-bindgen-rust\x060.46.0"; + }; + }; +} +#[doc(inline)] +pub use __export_proxy_impl as _export_proxy; +#[rustfmt::skip] +#[cfg(target_arch = "wasm32")] + +#[cfg_attr(feature = "rustc-dep-of-std", unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:http@0.2.4:proxy-with-all-of-its-exports-removed:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-proxy-world-in-libstd"))] +#[cfg_attr(not(feature = "rustc-dep-of-std"), unsafe(link_section = "component-type:wit-bindgen:0.46.0:wasi:http@0.2.4:proxy-with-all-of-its-exports-removed:encoded worldrust-wasip2-1.0.1+wasi-0.2.4-from-crates-io-proxy-world"))] + +#[doc(hidden)] +#[allow(clippy::octal_escapes)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6921] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xed4\x01A\x02\x01A\x1f\ +\x01B\x0a\x04\0\x08pollable\x03\x01\x01h\0\x01@\x01\x04self\x01\0\x7f\x04\0\x16[\ +method]pollable.ready\x01\x02\x01@\x01\x04self\x01\x01\0\x04\0\x16[method]pollab\ +le.block\x01\x03\x01p\x01\x01py\x01@\x01\x02in\x04\0\x05\x04\0\x04poll\x01\x06\x03\ +\0\x12wasi:io/poll@0.2.4\x05\0\x02\x03\0\0\x08pollable\x01B\x0f\x02\x03\x02\x01\x01\ +\x04\0\x08pollable\x03\0\0\x01w\x04\0\x07instant\x03\0\x02\x01w\x04\0\x08duratio\ +n\x03\0\x04\x01@\0\0\x03\x04\0\x03now\x01\x06\x01@\0\0\x05\x04\0\x0aresolution\x01\ +\x07\x01i\x01\x01@\x01\x04when\x03\0\x08\x04\0\x11subscribe-instant\x01\x09\x01@\ +\x01\x04when\x05\0\x08\x04\0\x12subscribe-duration\x01\x0a\x03\0!wasi:clocks/mon\ +otonic-clock@0.2.4\x05\x02\x01B\x05\x01r\x02\x07secondsw\x0bnanosecondsy\x04\0\x08\ +datetime\x03\0\0\x01@\0\0\x01\x04\0\x03now\x01\x02\x04\0\x0aresolution\x01\x02\x03\ +\0\x1cwasi:clocks/wall-clock@0.2.4\x05\x03\x01B\x05\x01p}\x01@\x01\x03lenw\0\0\x04\ +\0\x10get-random-bytes\x01\x01\x01@\0\0w\x04\0\x0eget-random-u64\x01\x02\x03\0\x18\ +wasi:random/random@0.2.4\x05\x04\x01B\x04\x04\0\x05error\x03\x01\x01h\0\x01@\x01\ +\x04self\x01\0s\x04\0\x1d[method]error.to-debug-string\x01\x02\x03\0\x13wasi:io/\ +error@0.2.4\x05\x05\x02\x03\0\x04\x05error\x01B(\x02\x03\x02\x01\x06\x04\0\x05er\ +ror\x03\0\0\x02\x03\x02\x01\x01\x04\0\x08pollable\x03\0\x02\x01i\x01\x01q\x02\x15\ +last-operation-failed\x01\x04\0\x06closed\0\0\x04\0\x0cstream-error\x03\0\x05\x04\ +\0\x0cinput-stream\x03\x01\x04\0\x0doutput-stream\x03\x01\x01h\x07\x01p}\x01j\x01\ +\x0a\x01\x06\x01@\x02\x04self\x09\x03lenw\0\x0b\x04\0\x19[method]input-stream.re\ +ad\x01\x0c\x04\0\"[method]input-stream.blocking-read\x01\x0c\x01j\x01w\x01\x06\x01\ +@\x02\x04self\x09\x03lenw\0\x0d\x04\0\x19[method]input-stream.skip\x01\x0e\x04\0\ +\"[method]input-stream.blocking-skip\x01\x0e\x01i\x03\x01@\x01\x04self\x09\0\x0f\ +\x04\0\x1e[method]input-stream.subscribe\x01\x10\x01h\x08\x01@\x01\x04self\x11\0\ +\x0d\x04\0![method]output-stream.check-write\x01\x12\x01j\0\x01\x06\x01@\x02\x04\ +self\x11\x08contents\x0a\0\x13\x04\0\x1b[method]output-stream.write\x01\x14\x04\0\ +.[method]output-stream.blocking-write-and-flush\x01\x14\x01@\x01\x04self\x11\0\x13\ +\x04\0\x1b[method]output-stream.flush\x01\x15\x04\0$[method]output-stream.blocki\ +ng-flush\x01\x15\x01@\x01\x04self\x11\0\x0f\x04\0\x1f[method]output-stream.subsc\ +ribe\x01\x16\x01@\x02\x04self\x11\x03lenw\0\x13\x04\0\"[method]output-stream.wri\ +te-zeroes\x01\x17\x04\05[method]output-stream.blocking-write-zeroes-and-flush\x01\ +\x17\x01@\x03\x04self\x11\x03src\x09\x03lenw\0\x0d\x04\0\x1c[method]output-strea\ +m.splice\x01\x18\x04\0%[method]output-stream.blocking-splice\x01\x18\x03\0\x15wa\ +si:io/streams@0.2.4\x05\x07\x02\x03\0\x05\x0doutput-stream\x01B\x05\x02\x03\x02\x01\ +\x08\x04\0\x0doutput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0aget-stdout\x01\ +\x03\x03\0\x15wasi:cli/stdout@0.2.4\x05\x09\x01B\x05\x02\x03\x02\x01\x08\x04\0\x0d\ +output-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x0aget-stderr\x01\x03\x03\0\x15\ +wasi:cli/stderr@0.2.4\x05\x0a\x02\x03\0\x05\x0cinput-stream\x01B\x05\x02\x03\x02\ +\x01\x0b\x04\0\x0cinput-stream\x03\0\0\x01i\x01\x01@\0\0\x02\x04\0\x09get-stdin\x01\ +\x03\x03\0\x14wasi:cli/stdin@0.2.4\x05\x0c\x02\x03\0\x01\x08duration\x01B\xc1\x01\ +\x02\x03\x02\x01\x0d\x04\0\x08duration\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x0cinpu\ +t-stream\x03\0\x02\x02\x03\x02\x01\x08\x04\0\x0doutput-stream\x03\0\x04\x02\x03\x02\ +\x01\x06\x04\0\x08io-error\x03\0\x06\x02\x03\x02\x01\x01\x04\0\x08pollable\x03\0\ +\x08\x01q\x0a\x03get\0\0\x04head\0\0\x04post\0\0\x03put\0\0\x06delete\0\0\x07con\ +nect\0\0\x07options\0\0\x05trace\0\0\x05patch\0\0\x05other\x01s\0\x04\0\x06metho\ +d\x03\0\x0a\x01q\x03\x04HTTP\0\0\x05HTTPS\0\0\x05other\x01s\0\x04\0\x06scheme\x03\ +\0\x0c\x01ks\x01k{\x01r\x02\x05rcode\x0e\x09info-code\x0f\x04\0\x11DNS-error-pay\ +load\x03\0\x10\x01k}\x01r\x02\x08alert-id\x12\x0dalert-message\x0e\x04\0\x1aTLS-\ +alert-received-payload\x03\0\x13\x01ky\x01r\x02\x0afield-name\x0e\x0afield-size\x15\ +\x04\0\x12field-size-payload\x03\0\x16\x01kw\x01k\x17\x01q'\x0bDNS-timeout\0\0\x09\ +DNS-error\x01\x11\0\x15destination-not-found\0\0\x17destination-unavailable\0\0\x19\ +destination-IP-prohibited\0\0\x19destination-IP-unroutable\0\0\x12connection-ref\ +used\0\0\x15connection-terminated\0\0\x12connection-timeout\0\0\x17connection-re\ +ad-timeout\0\0\x18connection-write-timeout\0\0\x18connection-limit-reached\0\0\x12\ +TLS-protocol-error\0\0\x15TLS-certificate-error\0\0\x12TLS-alert-received\x01\x14\ +\0\x13HTTP-request-denied\0\0\x1cHTTP-request-length-required\0\0\x16HTTP-reques\ +t-body-size\x01\x18\0\x1bHTTP-request-method-invalid\0\0\x18HTTP-request-URI-inv\ +alid\0\0\x19HTTP-request-URI-too-long\0\0\x20HTTP-request-header-section-size\x01\ +\x15\0\x18HTTP-request-header-size\x01\x19\0!HTTP-request-trailer-section-size\x01\ +\x15\0\x19HTTP-request-trailer-size\x01\x17\0\x18HTTP-response-incomplete\0\0!HT\ +TP-response-header-section-size\x01\x15\0\x19HTTP-response-header-size\x01\x17\0\ +\x17HTTP-response-body-size\x01\x18\0\"HTTP-response-trailer-section-size\x01\x15\ +\0\x1aHTTP-response-trailer-size\x01\x17\0\x1dHTTP-response-transfer-coding\x01\x0e\ +\0\x1cHTTP-response-content-coding\x01\x0e\0\x15HTTP-response-timeout\0\0\x13HTT\ +P-upgrade-failed\0\0\x13HTTP-protocol-error\0\0\x0dloop-detected\0\0\x13configur\ +ation-error\0\0\x0einternal-error\x01\x0e\0\x04\0\x0aerror-code\x03\0\x1a\x01q\x03\ +\x0einvalid-syntax\0\0\x09forbidden\0\0\x09immutable\0\0\x04\0\x0cheader-error\x03\ +\0\x1c\x01s\x04\0\x09field-key\x03\0\x1e\x04\0\x0afield-name\x03\0\x1f\x01p}\x04\ +\0\x0bfield-value\x03\0!\x04\0\x06fields\x03\x01\x04\0\x07headers\x03\0#\x04\0\x08\ +trailers\x03\0#\x04\0\x10incoming-request\x03\x01\x04\0\x10outgoing-request\x03\x01\ +\x04\0\x0frequest-options\x03\x01\x04\0\x11response-outparam\x03\x01\x01{\x04\0\x0b\ +status-code\x03\0*\x04\0\x11incoming-response\x03\x01\x04\0\x0dincoming-body\x03\ +\x01\x04\0\x0ffuture-trailers\x03\x01\x04\0\x11outgoing-response\x03\x01\x04\0\x0d\ +outgoing-body\x03\x01\x04\0\x18future-incoming-response\x03\x01\x01i#\x01@\0\02\x04\ +\0\x13[constructor]fields\x013\x01o\x02\x20\"\x01p4\x01j\x012\x01\x1d\x01@\x01\x07\ +entries5\06\x04\0\x18[static]fields.from-list\x017\x01h#\x01p\"\x01@\x02\x04self\ +8\x04name\x20\09\x04\0\x12[method]fields.get\x01:\x01@\x02\x04self8\x04name\x20\0\ +\x7f\x04\0\x12[method]fields.has\x01;\x01j\0\x01\x1d\x01@\x03\x04self8\x04name\x20\ +\x05value9\0<\x04\0\x12[method]fields.set\x01=\x01@\x02\x04self8\x04name\x20\0<\x04\ +\0\x15[method]fields.delete\x01>\x01@\x03\x04self8\x04name\x20\x05value\"\0<\x04\ +\0\x15[method]fields.append\x01?\x01@\x01\x04self8\05\x04\0\x16[method]fields.en\ +tries\x01@\x01@\x01\x04self8\02\x04\0\x14[method]fields.clone\x01A\x01h&\x01@\x01\ +\x04self\xc2\0\0\x0b\x04\0\x1f[method]incoming-request.method\x01C\x01@\x01\x04s\ +elf\xc2\0\0\x0e\x04\0([method]incoming-request.path-with-query\x01D\x01k\x0d\x01\ +@\x01\x04self\xc2\0\0\xc5\0\x04\0\x1f[method]incoming-request.scheme\x01F\x04\0\"\ +[method]incoming-request.authority\x01D\x01i$\x01@\x01\x04self\xc2\0\0\xc7\0\x04\ +\0\x20[method]incoming-request.headers\x01H\x01i-\x01j\x01\xc9\0\0\x01@\x01\x04s\ +elf\xc2\0\0\xca\0\x04\0\x20[method]incoming-request.consume\x01K\x01i'\x01@\x01\x07\ +headers\xc7\0\0\xcc\0\x04\0\x1d[constructor]outgoing-request\x01M\x01h'\x01i0\x01\ +j\x01\xcf\0\0\x01@\x01\x04self\xce\0\0\xd0\0\x04\0\x1d[method]outgoing-request.b\ +ody\x01Q\x01@\x01\x04self\xce\0\0\x0b\x04\0\x1f[method]outgoing-request.method\x01\ +R\x01j\0\0\x01@\x02\x04self\xce\0\x06method\x0b\0\xd3\0\x04\0#[method]outgoing-r\ +equest.set-method\x01T\x01@\x01\x04self\xce\0\0\x0e\x04\0([method]outgoing-reque\ +st.path-with-query\x01U\x01@\x02\x04self\xce\0\x0fpath-with-query\x0e\0\xd3\0\x04\ +\0,[method]outgoing-request.set-path-with-query\x01V\x01@\x01\x04self\xce\0\0\xc5\ +\0\x04\0\x1f[method]outgoing-request.scheme\x01W\x01@\x02\x04self\xce\0\x06schem\ +e\xc5\0\0\xd3\0\x04\0#[method]outgoing-request.set-scheme\x01X\x04\0\"[method]ou\ +tgoing-request.authority\x01U\x01@\x02\x04self\xce\0\x09authority\x0e\0\xd3\0\x04\ +\0&[method]outgoing-request.set-authority\x01Y\x01@\x01\x04self\xce\0\0\xc7\0\x04\ +\0\x20[method]outgoing-request.headers\x01Z\x01i(\x01@\0\0\xdb\0\x04\0\x1c[const\ +ructor]request-options\x01\\\x01h(\x01k\x01\x01@\x01\x04self\xdd\0\0\xde\0\x04\0\ +'[method]request-options.connect-timeout\x01_\x01@\x02\x04self\xdd\0\x08duration\ +\xde\0\0\xd3\0\x04\0+[method]request-options.set-connect-timeout\x01`\x04\0*[met\ +hod]request-options.first-byte-timeout\x01_\x04\0.[method]request-options.set-fi\ +rst-byte-timeout\x01`\x04\0-[method]request-options.between-bytes-timeout\x01_\x04\ +\01[method]request-options.set-between-bytes-timeout\x01`\x01i)\x01i/\x01j\x01\xe2\ +\0\x01\x1b\x01@\x02\x05param\xe1\0\x08response\xe3\0\x01\0\x04\0\x1d[static]resp\ +onse-outparam.set\x01d\x01h,\x01@\x01\x04self\xe5\0\0+\x04\0\x20[method]incoming\ +-response.status\x01f\x01@\x01\x04self\xe5\0\0\xc7\0\x04\0![method]incoming-resp\ +onse.headers\x01g\x01@\x01\x04self\xe5\0\0\xca\0\x04\0![method]incoming-response\ +.consume\x01h\x01h-\x01i\x03\x01j\x01\xea\0\0\x01@\x01\x04self\xe9\0\0\xeb\0\x04\ +\0\x1c[method]incoming-body.stream\x01l\x01i.\x01@\x01\x04this\xc9\0\0\xed\0\x04\ +\0\x1c[static]incoming-body.finish\x01n\x01h.\x01i\x09\x01@\x01\x04self\xef\0\0\xf0\ +\0\x04\0![method]future-trailers.subscribe\x01q\x01i%\x01k\xf2\0\x01j\x01\xf3\0\x01\ +\x1b\x01j\x01\xf4\0\0\x01k\xf5\0\x01@\x01\x04self\xef\0\0\xf6\0\x04\0\x1b[method\ +]future-trailers.get\x01w\x01@\x01\x07headers\xc7\0\0\xe2\0\x04\0\x1e[constructo\ +r]outgoing-response\x01x\x01h/\x01@\x01\x04self\xf9\0\0+\x04\0%[method]outgoing-\ +response.status-code\x01z\x01@\x02\x04self\xf9\0\x0bstatus-code+\0\xd3\0\x04\0)[\ +method]outgoing-response.set-status-code\x01{\x01@\x01\x04self\xf9\0\0\xc7\0\x04\ +\0![method]outgoing-response.headers\x01|\x01@\x01\x04self\xf9\0\0\xd0\0\x04\0\x1e\ +[method]outgoing-response.body\x01}\x01h0\x01i\x05\x01j\x01\xff\0\0\x01@\x01\x04\ +self\xfe\0\0\x80\x01\x04\0\x1b[method]outgoing-body.write\x01\x81\x01\x01j\0\x01\ +\x1b\x01@\x02\x04this\xcf\0\x08trailers\xf3\0\0\x82\x01\x04\0\x1c[static]outgoin\ +g-body.finish\x01\x83\x01\x01h1\x01@\x01\x04self\x84\x01\0\xf0\0\x04\0*[method]f\ +uture-incoming-response.subscribe\x01\x85\x01\x01i,\x01j\x01\x86\x01\x01\x1b\x01\ +j\x01\x87\x01\0\x01k\x88\x01\x01@\x01\x04self\x84\x01\0\x89\x01\x04\0$[method]fu\ +ture-incoming-response.get\x01\x8a\x01\x01h\x07\x01k\x1b\x01@\x01\x03err\x8b\x01\ +\0\x8c\x01\x04\0\x0fhttp-error-code\x01\x8d\x01\x03\0\x15wasi:http/types@0.2.4\x05\ +\x0e\x02\x03\0\x09\x10outgoing-request\x02\x03\0\x09\x0frequest-options\x02\x03\0\ +\x09\x18future-incoming-response\x02\x03\0\x09\x0aerror-code\x01B\x0f\x02\x03\x02\ +\x01\x0f\x04\0\x10outgoing-request\x03\0\0\x02\x03\x02\x01\x10\x04\0\x0frequest-\ +options\x03\0\x02\x02\x03\x02\x01\x11\x04\0\x18future-incoming-response\x03\0\x04\ +\x02\x03\x02\x01\x12\x04\0\x0aerror-code\x03\0\x06\x01i\x01\x01i\x03\x01k\x09\x01\ +i\x05\x01j\x01\x0b\x01\x07\x01@\x02\x07request\x08\x07options\x0a\0\x0c\x04\0\x06\ +handle\x01\x0d\x03\0\x20wasi:http/outgoing-handler@0.2.4\x05\x13\x04\05wasi:http\ +/proxy-with-all-of-its-exports-removed@0.2.4\x04\0\x0b+\x01\0%proxy-with-all-of-\ +its-exports-removed\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-compo\ +nent\x070.239.0\x10wit-bindgen-rust\x060.46.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen::rt::maybe_link_cabi_realloc(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/command.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/command.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/command.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/command.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +package wasi:cli@0.2.4; + +@since(version = 0.2.0) +world command { + @since(version = 0.2.0) + include imports; + + @since(version = 0.2.0) + export run; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/environment.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/environment.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/environment.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/environment.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +@since(version = 0.2.0) +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + @since(version = 0.2.0) + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + @since(version = 0.2.0) + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + @since(version = 0.2.0) + initial-cwd: func() -> option; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/exit.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/exit.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/exit.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/exit.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +@since(version = 0.2.0) +interface exit { + /// Exit the current instance and any linked instances. + @since(version = 0.2.0) + exit: func(status: result); + + /// Exit the current instance and any linked instances, reporting the + /// specified status code to the host. + /// + /// The meaning of the code depends on the context, with 0 usually meaning + /// "success", and other values indicating various types of failure. + /// + /// This function does not return; the effect is analogous to a trap, but + /// without the connotation that something bad has happened. + @unstable(feature = cli-exit-with-code) + exit-with-code: func(status-code: u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/imports.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/imports.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/imports.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/imports.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +package wasi:cli@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + include wasi:clocks/imports@0.2.4; + @since(version = 0.2.0) + include wasi:filesystem/imports@0.2.4; + @since(version = 0.2.0) + include wasi:sockets/imports@0.2.4; + @since(version = 0.2.0) + include wasi:random/imports@0.2.4; + @since(version = 0.2.0) + include wasi:io/imports@0.2.4; + + @since(version = 0.2.0) + import environment; + @since(version = 0.2.0) + import exit; + @since(version = 0.2.0) + import stdin; + @since(version = 0.2.0) + import stdout; + @since(version = 0.2.0) + import stderr; + @since(version = 0.2.0) + import terminal-input; + @since(version = 0.2.0) + import terminal-output; + @since(version = 0.2.0) + import terminal-stdin; + @since(version = 0.2.0) + import terminal-stdout; + @since(version = 0.2.0) + import terminal-stderr; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/run.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/run.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/run.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/run.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +@since(version = 0.2.0) +interface run { + /// Run the program. + @since(version = 0.2.0) + run: func() -> result; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/stdio.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/stdio.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/stdio.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/stdio.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +@since(version = 0.2.0) +interface stdin { + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{input-stream}; + + @since(version = 0.2.0) + get-stdin: func() -> input-stream; +} + +@since(version = 0.2.0) +interface stdout { + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{output-stream}; + + @since(version = 0.2.0) + get-stdout: func() -> output-stream; +} + +@since(version = 0.2.0) +interface stderr { + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{output-stream}; + + @since(version = 0.2.0) + get-stderr: func() -> output-stream; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/terminal.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/terminal.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/cli/terminal.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/cli/terminal.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +@since(version = 0.2.0) +interface terminal-input { + /// The input side of a terminal. + @since(version = 0.2.0) + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +@since(version = 0.2.0) +interface terminal-output { + /// The output side of a terminal. + @since(version = 0.2.0) + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stdin { + @since(version = 0.2.0) + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stdout { + @since(version = 0.2.0) + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stderr { + @since(version = 0.2.0) + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stderr: func() -> option; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/monotonic-clock.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/monotonic-clock.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/monotonic-clock.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/monotonic-clock.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +package wasi:clocks@0.2.4; +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +@since(version = 0.2.0) +interface monotonic-clock { + @since(version = 0.2.0) + use wasi:io/poll@0.2.4.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + @since(version = 0.2.0) + type instant = u64; + + /// A duration of time, in nanoseconds. + @since(version = 0.2.0) + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + @since(version = 0.2.0) + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + @since(version = 0.2.0) + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// has occurred. + @since(version = 0.2.0) + subscribe-instant: func( + when: instant, + ) -> pollable; + + /// Create a `pollable` that will resolve after the specified duration has + /// elapsed from the time this function is invoked. + @since(version = 0.2.0) + subscribe-duration: func( + when: duration, + ) -> pollable; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/timezone.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/timezone.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/timezone.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/timezone.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +package wasi:clocks@0.2.4; + +@unstable(feature = clocks-timezone) +interface timezone { + @unstable(feature = clocks-timezone) + use wall-clock.{datetime}; + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + @unstable(feature = clocks-timezone) + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + @unstable(feature = clocks-timezone) + utc-offset: func(when: datetime) -> s32; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + @unstable(feature = clocks-timezone) + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/wall-clock.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/wall-clock.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/wall-clock.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/wall-clock.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +package wasi:clocks@0.2.4; +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +@since(version = 0.2.0) +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + @since(version = 0.2.0) + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + @since(version = 0.2.0) + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + @since(version = 0.2.0) + resolution: func() -> datetime; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/world.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/world.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/world.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/clocks/world.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +package wasi:clocks@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import monotonic-clock; + @since(version = 0.2.0) + import wall-clock; + @unstable(feature = clocks-timezone) + import timezone; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/preopens.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/preopens.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/preopens.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/preopens.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +package wasi:filesystem@0.2.4; + +@since(version = 0.2.0) +interface preopens { + @since(version = 0.2.0) + use types.{descriptor}; + + /// Return the set of preopened directories, and their paths. + @since(version = 0.2.0) + get-directories: func() -> list>; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/types.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/types.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/types.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/types.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,676 @@ +package wasi:filesystem@0.2.4; +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +@since(version = 0.2.0) +interface types { + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{input-stream, output-stream, error}; + @since(version = 0.2.0) + use wasi:clocks/wall-clock@0.2.4.{datetime}; + + /// File size or length of a region within a file. + @since(version = 0.2.0) + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + @since(version = 0.2.0) + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + @since(version = 0.2.0) + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrity + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + @since(version = 0.2.0) + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + @since(version = 0.2.0) + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + @since(version = 0.2.0) + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + @since(version = 0.2.0) + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + @since(version = 0.2.0) + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + @since(version = 0.2.0) + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + @since(version = 0.2.0) + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + @since(version = 0.2.0) + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + @since(version = 0.2.0) + read-via-stream: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + @since(version = 0.2.0) + write-via-stream: func( + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in POSIX. + @since(version = 0.2.0) + append-via-stream: func() -> result; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + @since(version = 0.2.0) + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + @since(version = 0.2.0) + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + @since(version = 0.2.0) + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + @since(version = 0.2.0) + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + @since(version = 0.2.0) + read: func( + /// The maximum number of bytes to read. + length: filesize, + /// The offset within the file at which to read. + offset: filesize, + ) -> result, bool>, error-code>; + + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + @since(version = 0.2.0) + write: func( + /// Data to write + buffer: list, + /// The offset within the file at which to write. + offset: filesize, + ) -> result; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + @since(version = 0.2.0) + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + @since(version = 0.2.0) + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + @since(version = 0.2.0) + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + @since(version = 0.2.0) + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Fails with `error-code::no-entry` if the old path does not exist, + /// with `error-code::exist` if the new path already exists, and + /// `error-code::not-permitted` if the old path is not a file. + /// + /// Note: This is similar to `linkat` in POSIX. + @since(version = 0.2.0) + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + @since(version = 0.2.0) + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + @since(version = 0.2.0) + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + @since(version = 0.2.0) + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + @since(version = 0.2.0) + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + @since(version = 0.2.0) + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + @since(version = 0.2.0) + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + @since(version = 0.2.0) + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encouraged to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + @since(version = 0.2.0) + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + @since(version = 0.2.0) + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + @since(version = 0.2.0) + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + @since(version = 0.2.0) + read-directory-entry: func() -> result, error-code>; + } + + /// Attempts to extract a filesystem-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// filesystem-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are filesystem-related errors. + @since(version = 0.2.0) + filesystem-error-code: func(err: borrow) -> option; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/world.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/world.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/world.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/filesystem/world.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +package wasi:filesystem@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import types; + @since(version = 0.2.0) + import preopens; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/handler.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/handler.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/handler.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/handler.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +/// This interface defines a handler of incoming HTTP Requests. It should +/// be exported by components which can respond to HTTP Requests. +@since(version = 0.2.0) +interface incoming-handler { + @since(version = 0.2.0) + use types.{incoming-request, response-outparam}; + + /// This function is invoked with an incoming HTTP Request, and a resource + /// `response-outparam` which provides the capability to reply with an HTTP + /// Response. The response is sent by calling the `response-outparam.set` + /// method, which allows execution to continue after the response has been + /// sent. This enables both streaming to the response body, and performing other + /// work. + /// + /// The implementor of this function must write a response to the + /// `response-outparam` before returning, or else the caller will respond + /// with an error on its behalf. + @since(version = 0.2.0) + handle: func( + request: incoming-request, + response-out: response-outparam + ); +} + +/// This interface defines a handler of outgoing HTTP Requests. It should be +/// imported by components which wish to make HTTP Requests. +@since(version = 0.2.0) +interface outgoing-handler { + @since(version = 0.2.0) + use types.{ + outgoing-request, request-options, future-incoming-response, error-code + }; + + /// This function is invoked with an outgoing HTTP Request, and it returns + /// a resource `future-incoming-response` which represents an HTTP Response + /// which may arrive in the future. + /// + /// The `options` argument accepts optional parameters for the HTTP + /// protocol's transport layer. + /// + /// This function may return an error if the `outgoing-request` is invalid + /// or not allowed to be made. Otherwise, protocol errors are reported + /// through the `future-incoming-response`. + @since(version = 0.2.0) + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/proxy.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/proxy.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/proxy.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/proxy.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +package wasi:http@0.2.4; + +/// The `wasi:http/imports` world imports all the APIs for HTTP proxies. +/// It is intended to be `include`d in other worlds. +@since(version = 0.2.0) +world imports { + /// HTTP proxies have access to time and randomness. + @since(version = 0.2.0) + import wasi:clocks/monotonic-clock@0.2.4; + @since(version = 0.2.0) + import wasi:clocks/wall-clock@0.2.4; + @since(version = 0.2.0) + import wasi:random/random@0.2.4; + + /// Proxies have standard output and error streams which are expected to + /// terminate in a developer-facing console provided by the host. + @since(version = 0.2.0) + import wasi:cli/stdout@0.2.4; + @since(version = 0.2.0) + import wasi:cli/stderr@0.2.4; + + /// TODO: this is a temporary workaround until component tooling is able to + /// gracefully handle the absence of stdin. Hosts must return an eof stream + /// for this import, which is what wasi-libc + tooling will do automatically + /// when this import is properly removed. + @since(version = 0.2.0) + import wasi:cli/stdin@0.2.4; + + /// This is the default handler to use when user code simply wants to make an + /// HTTP request (e.g., via `fetch()`). + @since(version = 0.2.0) + import outgoing-handler; +} + +/// The `wasi:http/proxy` world captures a widely-implementable intersection of +/// hosts that includes HTTP forward and reverse proxies. Components targeting +/// this world may concurrently stream in and out any number of incoming and +/// outgoing HTTP requests. +@since(version = 0.2.0) +world proxy { + @since(version = 0.2.0) + include imports; + + /// The host delivers incoming HTTP requests to a component by calling the + /// `handle` function of this exported interface. A host may arbitrarily reuse + /// or not reuse component instance when delivering incoming HTTP requests and + /// thus a component must be able to handle 0..N calls to `handle`. + @since(version = 0.2.0) + export incoming-handler; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/types.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/types.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/http/types.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/http/types.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,688 @@ +/// This interface defines all of the types and methods for implementing +/// HTTP Requests and Responses, both incoming and outgoing, as well as +/// their headers, trailers, and bodies. +@since(version = 0.2.0) +interface types { + @since(version = 0.2.0) + use wasi:clocks/monotonic-clock@0.2.4.{duration}; + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{input-stream, output-stream}; + @since(version = 0.2.0) + use wasi:io/error@0.2.4.{error as io-error}; + @since(version = 0.2.0) + use wasi:io/poll@0.2.4.{pollable}; + + /// This type corresponds to HTTP standard Methods. + @since(version = 0.2.0) + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + @since(version = 0.2.0) + variant scheme { + HTTP, + HTTPS, + other(string) + } + + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// + @since(version = 0.2.0) + variant error-code { + DNS-timeout, + DNS-error(DNS-error-payload), + destination-not-found, + destination-unavailable, + destination-IP-prohibited, + destination-IP-unroutable, + connection-refused, + connection-terminated, + connection-timeout, + connection-read-timeout, + connection-write-timeout, + connection-limit-reached, + TLS-protocol-error, + TLS-certificate-error, + TLS-alert-received(TLS-alert-received-payload), + HTTP-request-denied, + HTTP-request-length-required, + HTTP-request-body-size(option), + HTTP-request-method-invalid, + HTTP-request-URI-invalid, + HTTP-request-URI-too-long, + HTTP-request-header-section-size(option), + HTTP-request-header-size(option), + HTTP-request-trailer-section-size(option), + HTTP-request-trailer-size(field-size-payload), + HTTP-response-incomplete, + HTTP-response-header-section-size(option), + HTTP-response-header-size(field-size-payload), + HTTP-response-body-size(option), + HTTP-response-trailer-section-size(option), + HTTP-response-trailer-size(field-size-payload), + HTTP-response-transfer-coding(option), + HTTP-response-content-coding(option), + HTTP-response-timeout, + HTTP-upgrade-failed, + HTTP-protocol-error, + loop-detected, + configuration-error, + /// This is a catch-all error for anything that doesn't fit cleanly into a + /// more specific case. It also includes an optional string for an + /// unstructured description of the error. Users should not depend on the + /// string for diagnosing errors, as it's not required to be consistent + /// between implementations. + internal-error(option) + } + + /// Defines the case payload type for `DNS-error` above: + @since(version = 0.2.0) + record DNS-error-payload { + rcode: option, + info-code: option + } + + /// Defines the case payload type for `TLS-alert-received` above: + @since(version = 0.2.0) + record TLS-alert-received-payload { + alert-id: option, + alert-message: option + } + + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + @since(version = 0.2.0) + record field-size-payload { + field-name: option, + field-size: option + } + + /// Attempts to extract a http-related `error` from the wasi:io `error` + /// provided. + /// + /// Stream operations which return + /// `wasi:io/stream/stream-error::last-operation-failed` have a payload of + /// type `wasi:io/error/error` with more information about the operation + /// that failed. This payload can be passed through to this function to see + /// if there's http-related information about the error to return. + /// + /// Note that this function is fallible because not all io-errors are + /// http-related errors. + @since(version = 0.2.0) + http-error-code: func(err: borrow) -> option; + + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + @since(version = 0.2.0) + variant header-error { + /// This error indicates that a `field-name` or `field-value` was + /// syntactically invalid when used with an operation that sets headers in a + /// `fields`. + invalid-syntax, + + /// This error indicates that a forbidden `field-name` was used when trying + /// to set a header in a `fields`. + forbidden, + + /// This error indicates that the operation on the `fields` was not + /// permitted because the fields are immutable. + immutable, + } + + /// Field names are always strings. + /// + /// Field names should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + @since(version = 0.2.1) + type field-name = field-key; + + /// Field keys are always strings. + /// + /// Field keys should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + /// + /// # Deprecation + /// + /// This type has been deprecated in favor of the `field-name` type. + @since(version = 0.2.0) + @deprecated(version = 0.2.2) + type field-key = string; + + /// Field values should always be ASCII strings. However, in + /// reality, HTTP implementations often have to interpret malformed values, + /// so they are provided as a list of bytes. + @since(version = 0.2.0) + type field-value = list; + + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. Fields are a common representation used for both + /// Headers and Trailers. + /// + /// A `fields` may be mutable or immutable. A `fields` created using the + /// constructor, `from-list`, or `clone` will be mutable, but a `fields` + /// resource given by other means (including, but not limited to, + /// `incoming-request.headers`, `outgoing-request.headers`) might be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + @since(version = 0.2.0) + resource fields { + + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + @since(version = 0.2.0) + constructor(); + + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The tuple is a pair of the field name, represented as a string, and + /// Value, represented as a list of bytes. + /// + /// An error result will be returned if any `field-name` or `field-value` is + /// syntactically invalid, or if a field is forbidden. + @since(version = 0.2.0) + from-list: static func( + entries: list> + ) -> result; + + /// Get all of the values corresponding to a name. If the name is not present + /// in this `fields` or is syntactically invalid, an empty list is returned. + /// However, if the name is present but empty, this is represented by a list + /// with one or more empty field-values present. + @since(version = 0.2.0) + get: func(name: field-name) -> list; + + /// Returns `true` when the name is present in this `fields`. If the name is + /// syntactically invalid, `false` is returned. + @since(version = 0.2.0) + has: func(name: field-name) -> bool; + + /// Set all of the values for a name. Clears any existing values for that + /// name, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or any of + /// the `field-value`s are syntactically invalid. + @since(version = 0.2.0) + set: func(name: field-name, value: list) -> result<_, header-error>; + + /// Delete all values for a name. Does nothing if no values for the name + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` is + /// syntactically invalid. + @since(version = 0.2.0) + delete: func(name: field-name) -> result<_, header-error>; + + /// Append a value for a name. Does not change or delete any existing + /// values for that name. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or + /// `field-value` are syntactically invalid. + @since(version = 0.2.0) + append: func(name: field-name, value: field-value) -> result<_, header-error>; + + /// Retrieve the full set of names and values in the Fields. Like the + /// constructor, the list represents each name-value pair. + /// + /// The outer list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The names and values are always returned in the original casing and in + /// the order in which they will be serialized for transport. + @since(version = 0.2.0) + entries: func() -> list>; + + /// Make a deep copy of the Fields. Equivalent in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + @since(version = 0.2.0) + clone: func() -> fields; + } + + /// Headers is an alias for Fields. + @since(version = 0.2.0) + type headers = fields; + + /// Trailers is an alias for Fields. + @since(version = 0.2.0) + type trailers = fields; + + /// Represents an incoming HTTP Request. + @since(version = 0.2.0) + resource incoming-request { + + /// Returns the method of the incoming request. + @since(version = 0.2.0) + method: func() -> method; + + /// Returns the path with query parameters from the request, as a string. + @since(version = 0.2.0) + path-with-query: func() -> option; + + /// Returns the protocol scheme from the request. + @since(version = 0.2.0) + scheme: func() -> option; + + /// Returns the authority of the Request's target URI, if present. + @since(version = 0.2.0) + authority: func() -> option; + + /// Get the `headers` associated with the request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// The `headers` returned are a child resource: it must be dropped before + /// the parent `incoming-request` is dropped. Dropping this + /// `incoming-request` before all children are dropped will trap. + @since(version = 0.2.0) + headers: func() -> headers; + + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + @since(version = 0.2.0) + consume: func() -> result; + } + + /// Represents an outgoing HTTP Request. + @since(version = 0.2.0) + resource outgoing-request { + + /// Construct a new `outgoing-request` with a default `method` of `GET`, and + /// `none` values for `path-with-query`, `scheme`, and `authority`. + /// + /// * `headers` is the HTTP Headers for the Request. + /// + /// It is possible to construct, or manipulate with the accessor functions + /// below, an `outgoing-request` with an invalid combination of `scheme` + /// and `authority`, or `headers` which are not permitted to be sent. + /// It is the obligation of the `outgoing-handler.handle` implementation + /// to reject invalid constructions of `outgoing-request`. + @since(version = 0.2.0) + constructor( + headers: headers + ); + + /// Returns the resource corresponding to the outgoing Body for this + /// Request. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-request` can be retrieved at most once. Subsequent + /// calls will return error. + @since(version = 0.2.0) + body: func() -> result; + + /// Get the Method for the Request. + @since(version = 0.2.0) + method: func() -> method; + /// Set the Method for the Request. Fails if the string present in a + /// `method.other` argument is not a syntactically valid method. + @since(version = 0.2.0) + set-method: func(method: method) -> result; + + /// Get the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. + @since(version = 0.2.0) + path-with-query: func() -> option; + /// Set the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. Fails is the + /// string given is not a syntactically valid path and query uri component. + @since(version = 0.2.0) + set-path-with-query: func(path-with-query: option) -> result; + + /// Get the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. + @since(version = 0.2.0) + scheme: func() -> option; + /// Set the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. Fails if the + /// string given is not a syntactically valid uri scheme. + @since(version = 0.2.0) + set-scheme: func(scheme: option) -> result; + + /// Get the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. + @since(version = 0.2.0) + authority: func() -> option; + /// Set the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. Fails if the string given is + /// not a syntactically valid URI authority. + @since(version = 0.2.0) + set-authority: func(authority: option) -> result; + + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + @since(version = 0.2.0) + headers: func() -> headers; + } + + /// Parameters for making an HTTP Request. Each of these parameters is + /// currently an optional timeout applicable to the transport layer of the + /// HTTP protocol. + /// + /// These timeouts are separate from any the user may use to bound a + /// blocking call to `wasi:io/poll.poll`. + @since(version = 0.2.0) + resource request-options { + /// Construct a default `request-options` value. + @since(version = 0.2.0) + constructor(); + + /// The timeout for the initial connect to the HTTP Server. + @since(version = 0.2.0) + connect-timeout: func() -> option; + + /// Set the timeout for the initial connect to the HTTP Server. An error + /// return value indicates that this timeout is not supported. + @since(version = 0.2.0) + set-connect-timeout: func(duration: option) -> result; + + /// The timeout for receiving the first byte of the Response body. + @since(version = 0.2.0) + first-byte-timeout: func() -> option; + + /// Set the timeout for receiving the first byte of the Response body. An + /// error return value indicates that this timeout is not supported. + @since(version = 0.2.0) + set-first-byte-timeout: func(duration: option) -> result; + + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + @since(version = 0.2.0) + between-bytes-timeout: func() -> option; + + /// Set the timeout for receiving subsequent chunks of bytes in the Response + /// body stream. An error return value indicates that this timeout is not + /// supported. + @since(version = 0.2.0) + set-between-bytes-timeout: func(duration: option) -> result; + } + + /// Represents the ability to send an HTTP Response. + /// + /// This resource is used by the `wasi:http/incoming-handler` interface to + /// allow a Response to be sent corresponding to the Request provided as the + /// other argument to `incoming-handler.handle`. + @since(version = 0.2.0) + resource response-outparam { + /// Send an HTTP 1xx response. + /// + /// Unlike `response-outparam.set`, this does not consume the + /// `response-outparam`, allowing the guest to send an arbitrary number of + /// informational responses before sending the final response using + /// `response-outparam.set`. + /// + /// This will return an `HTTP-protocol-error` if `status` is not in the + /// range [100-199], or an `internal-error` if the implementation does not + /// support informational responses. + @unstable(feature = informational-outbound-responses) + send-informational: func( + status: u16, + headers: headers + ) -> result<_, error-code>; + + /// Set the value of the `response-outparam` to either send a response, + /// or indicate an error. + /// + /// This method consumes the `response-outparam` to ensure that it is + /// called at most once. If it is never called, the implementation + /// will respond with an error. + /// + /// The user may provide an `error` to `response` to allow the + /// implementation determine how to respond with an HTTP error response. + @since(version = 0.2.0) + set: static func( + param: response-outparam, + response: result, + ); + } + + /// This type corresponds to the HTTP standard Status Code. + @since(version = 0.2.0) + type status-code = u16; + + /// Represents an incoming HTTP Response. + @since(version = 0.2.0) + resource incoming-response { + + /// Returns the status code from the incoming response. + @since(version = 0.2.0) + status: func() -> status-code; + + /// Returns the headers from the incoming response. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `incoming-response` is dropped. + @since(version = 0.2.0) + headers: func() -> headers; + + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + @since(version = 0.2.0) + consume: func() -> result; + } + + /// Represents an incoming HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, indicating that the full contents of the + /// body have been received. This resource represents the contents as + /// an `input-stream` and the delivery of trailers as a `future-trailers`, + /// and ensures that the user of this interface may only be consuming either + /// the body contents or waiting on trailers at any given time. + @since(version = 0.2.0) + resource incoming-body { + + /// Returns the contents of the body, as a stream of bytes. + /// + /// Returns success on first call: the stream representing the contents + /// can be retrieved at most once. Subsequent calls will return error. + /// + /// The returned `input-stream` resource is a child: it must be dropped + /// before the parent `incoming-body` is dropped, or consumed by + /// `incoming-body.finish`. + /// + /// This invariant ensures that the implementation can determine whether + /// the user is consuming the contents of the body, waiting on the + /// `future-trailers` to be ready, or neither. This allows for network + /// backpressure is to be applied when the user is consuming the body, + /// and for that backpressure to not inhibit delivery of the trailers if + /// the user does not read the entire body. + @since(version = 0.2.0) + %stream: func() -> result; + + /// Takes ownership of `incoming-body`, and returns a `future-trailers`. + /// This function will trap if the `input-stream` child is still alive. + @since(version = 0.2.0) + finish: static func(this: incoming-body) -> future-trailers; + } + + /// Represents a future which may eventually return trailers, or an error. + /// + /// In the case that the incoming HTTP Request or Response did not have any + /// trailers, this future will resolve to the empty set of trailers once the + /// complete Request or Response body has been received. + @since(version = 0.2.0) + resource future-trailers { + + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + @since(version = 0.2.0) + subscribe: func() -> pollable; + + /// Returns the contents of the trailers, or an error which occurred, + /// once the future is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the trailers or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the HTTP Request or Response + /// body, as well as any trailers, were received successfully, or that an + /// error occurred receiving them. The optional `trailers` indicates whether + /// or not trailers were present in the body. + /// + /// When some `trailers` are returned by this method, the `trailers` + /// resource is immutable, and a child. Use of the `set`, `append`, or + /// `delete` methods will return an error, and the resource must be + /// dropped before the parent `future-trailers` is dropped. + @since(version = 0.2.0) + get: func() -> option, error-code>>>; + } + + /// Represents an outgoing HTTP Response. + @since(version = 0.2.0) + resource outgoing-response { + + /// Construct an `outgoing-response`, with a default `status-code` of `200`. + /// If a different `status-code` is needed, it must be set via the + /// `set-status-code` method. + /// + /// * `headers` is the HTTP Headers for the Response. + @since(version = 0.2.0) + constructor(headers: headers); + + /// Get the HTTP Status Code for the Response. + @since(version = 0.2.0) + status-code: func() -> status-code; + + /// Set the HTTP Status Code for the Response. Fails if the status-code + /// given is not a valid http status code. + @since(version = 0.2.0) + set-status-code: func(status-code: status-code) -> result; + + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + @since(version = 0.2.0) + headers: func() -> headers; + + /// Returns the resource corresponding to the outgoing Body for this Response. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-response` can be retrieved at most once. Subsequent + /// calls will return error. + @since(version = 0.2.0) + body: func() -> result; + } + + /// Represents an outgoing HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, inducating the full contents of the body + /// have been sent. This resource represents the contents as an + /// `output-stream` child resource, and the completion of the body (with + /// optional trailers) with a static function that consumes the + /// `outgoing-body` resource, and ensures that the user of this interface + /// may not write to the body contents after the body has been finished. + /// + /// If the user code drops this resource, as opposed to calling the static + /// method `finish`, the implementation should treat the body as incomplete, + /// and that an error has occurred. The implementation should propagate this + /// error to the HTTP protocol by whatever means it has available, + /// including: corrupting the body on the wire, aborting the associated + /// Request, or sending a late status code for the Response. + @since(version = 0.2.0) + resource outgoing-body { + + /// Returns a stream for writing the body contents. + /// + /// The returned `output-stream` is a child resource: it must be dropped + /// before the parent `outgoing-body` resource is dropped (or finished), + /// otherwise the `outgoing-body` drop or `finish` will trap. + /// + /// Returns success on the first call: the `output-stream` resource for + /// this `outgoing-body` may be retrieved at most once. Subsequent calls + /// will return error. + @since(version = 0.2.0) + write: func() -> result; + + /// Finalize an outgoing body, optionally providing trailers. This must be + /// called to signal that the response is complete. If the `outgoing-body` + /// is dropped without calling `outgoing-body.finalize`, the implementation + /// should treat the body as corrupted. + /// + /// Fails if the body's `outgoing-request` or `outgoing-response` was + /// constructed with a Content-Length header, and the contents written + /// to the body (via `write`) does not match the value given in the + /// Content-Length. + @since(version = 0.2.0) + finish: static func( + this: outgoing-body, + trailers: option + ) -> result<_, error-code>; + } + + /// Represents a future which may eventually return an incoming HTTP + /// Response, or an error. + /// + /// This resource is returned by the `wasi:http/outgoing-handler` interface to + /// provide the HTTP Response corresponding to the sent Request. + @since(version = 0.2.0) + resource future-incoming-response { + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + @since(version = 0.2.0) + subscribe: func() -> pollable; + + /// Returns the incoming HTTP Response, or an error, once one is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the response or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the incoming HTTP Response + /// status and headers have received successfully, or that an error + /// occurred. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + @since(version = 0.2.0) + get: func() -> option>>; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/error.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/error.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/error.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/error.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +package wasi:io@0.2.4; + +@since(version = 0.2.0) +interface error { + /// A resource which represents some error information. + /// + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. + /// + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams/stream-error` type. + /// + /// To provide more specific error information, other interfaces may + /// offer functions to "downcast" this error into more specific types. For example, + /// errors returned from streams derived from filesystem types can be described using + /// the filesystem's own error-code type. This is done using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow` + /// parameter and returns an `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + @since(version = 0.2.0) + resource error { + /// Returns a string that is suitable to assist humans in debugging + /// this error. + /// + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. + @since(version = 0.2.0) + to-debug-string: func() -> string; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/poll.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/poll.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/poll.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/poll.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +package wasi:io@0.2.4; + +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +@since(version = 0.2.0) +interface poll { + /// `pollable` represents a single I/O event which may be ready, or not. + @since(version = 0.2.0) + resource pollable { + + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + @since(version = 0.2.0) + ready: func() -> bool; + + /// `block` returns immediately if the pollable is ready, and otherwise + /// blocks until ready. + /// + /// This function is equivalent to calling `poll.poll` on a list + /// containing only this pollable. + @since(version = 0.2.0) + block: func(); + } + + /// Poll for completion on a set of pollables. + /// + /// This function takes a list of pollables, which identify I/O sources of + /// interest, and waits until one or more of the events is ready for I/O. + /// + /// The result `list` contains one or more indices of handles in the + /// argument list that is ready for I/O. + /// + /// This function traps if either: + /// - the list is empty, or: + /// - the list contains more elements than can be indexed with a `u32` value. + /// + /// A timeout can be implemented by adding a pollable from the + /// wasi-clocks API to the list. + /// + /// This function does not return a `result`; polling in itself does not + /// do any I/O so it doesn't fail. If any of the I/O sources identified by + /// the pollables has an error, it is indicated by marking the source as + /// being ready for I/O. + @since(version = 0.2.0) + poll: func(in: list>) -> list; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/streams.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/streams.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/streams.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/streams.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,290 @@ +package wasi:io@0.2.4; + +/// WASI I/O is an I/O abstraction API which is currently focused on providing +/// stream types. +/// +/// In the future, the component model is expected to add built-in stream types; +/// when it does, they are expected to subsume this API. +@since(version = 0.2.0) +interface streams { + @since(version = 0.2.0) + use error.{error}; + @since(version = 0.2.0) + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + @since(version = 0.2.0) + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + /// + /// After this, the stream will be closed. All future operations return + /// `stream-error::closed`. + last-operation-failed(error), + /// The stream is closed: no more input will be accepted by the + /// stream. A closed output-stream will return this error on all + /// future operations. + closed + } + + /// An input bytestream. + /// + /// `input-stream`s are *non-blocking* to the extent practical on underlying + /// platforms. I/O operations always return promptly; if fewer bytes are + /// promptly available than requested, they return the number of bytes promptly + /// available, which could even be zero. To wait for data to be available, + /// use the `subscribe` function to obtain a `pollable` which can be polled + /// for using `wasi:io/poll`. + @since(version = 0.2.0) + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// When the source of a `read` is binary data, the bytes from the source + /// are returned verbatim. When the source of a `read` is known to the + /// implementation to be text, bytes containing the UTF-8 encoding of the + /// text are returned. + /// + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// available. + /// + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. + /// + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. + /// + /// The `len` parameter is a `u64`, which could represent a list of u8 which + /// is not possible to allocate in wasm32, or not desirable to allocate as + /// as a return value by the callee. The callee may return a list of bytes + /// less than `len` in size while more bytes are available for reading. + @since(version = 0.2.0) + read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, behavior is identical to `read`. + @since(version = 0.2.0) + blocking-read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Skip bytes from a stream. Returns number of bytes skipped. + /// + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. + @since(version = 0.2.0) + skip: func( + /// The maximum number of bytes to skip. + len: u64, + ) -> result; + + /// Skip bytes from a stream, after blocking until at least one byte + /// can be skipped. Except for blocking behavior, identical to `skip`. + @since(version = 0.2.0) + blocking-skip: func( + /// The maximum number of bytes to skip. + len: u64, + ) -> result; + + /// Create a `pollable` which will resolve once either the specified stream + /// has bytes available to read or the other end of the stream has been + /// closed. + /// The created `pollable` is a child resource of the `input-stream`. + /// Implementations may trap if the `input-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + + /// An output bytestream. + /// + /// `output-stream`s are *non-blocking* to the extent practical on + /// underlying platforms. Except where specified otherwise, I/O operations also + /// always return promptly, after the number of bytes that can be written + /// promptly, which could even be zero. To wait for the stream to be ready to + /// accept data, the `subscribe` function to obtain a `pollable` which can be + /// polled for using `wasi:io/poll`. + /// + /// Dropping an `output-stream` while there's still an active write in + /// progress may result in the data being lost. Before dropping the stream, + /// be sure to fully flush your writes. + @since(version = 0.2.0) + resource output-stream { + /// Check readiness for writing. This function never blocks. + /// + /// Returns the number of bytes permitted for the next call to `write`, + /// or an error. Calling `write` with more bytes than this function has + /// permitted will trap. + /// + /// When this function returns 0 bytes, the `subscribe` pollable will + /// become ready when this function will report at least 1 byte, or an + /// error. + @since(version = 0.2.0) + check-write: func() -> result; + + /// Perform a write. This function never blocks. + /// + /// When the destination of a `write` is binary data, the bytes from + /// `contents` are written verbatim. When the destination of a `write` is + /// known to the implementation to be text, the bytes of `contents` are + /// transcoded from UTF-8 into the encoding of the destination and then + /// written. + /// + /// Precondition: check-write gave permit of Ok(n) and contents has a + /// length of less than or equal to n. Otherwise, this function will trap. + /// + /// returns Err(closed) without writing if the stream has closed since + /// the last call to check-write provided a permit. + @since(version = 0.2.0) + write: func( + contents: list + ) -> result<_, stream-error>; + + /// Perform a write of up to 4096 bytes, and then flush the stream. Block + /// until all of these operations are complete, or an error occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + @since(version = 0.2.0) + blocking-write-and-flush: func( + contents: list + ) -> result<_, stream-error>; + + /// Request to flush buffered output. This function never blocks. + /// + /// This tells the output-stream that the caller intends any buffered + /// output to be flushed. the output which is expected to be flushed + /// is all that has been passed to `write` prior to this call. + /// + /// Upon calling this function, the `output-stream` will not accept any + /// writes (`check-write` will return `ok(0)`) until the flush has + /// completed. The `subscribe` pollable will become ready when the + /// flush has completed and the stream can accept more writes. + @since(version = 0.2.0) + flush: func() -> result<_, stream-error>; + + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + @since(version = 0.2.0) + blocking-flush: func() -> result<_, stream-error>; + + /// Create a `pollable` which will resolve once the output-stream + /// is ready for more writing, or an error has occurred. When this + /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an + /// error. + /// + /// If the stream is closed, this pollable is always ready immediately. + /// + /// The created `pollable` is a child resource of the `output-stream`. + /// Implementations may trap if the `output-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + @since(version = 0.2.0) + subscribe: func() -> pollable; + + /// Write zeroes to a stream. + /// + /// This should be used precisely like `write` with the exact same + /// preconditions (must use check-write first), but instead of + /// passing a list of bytes, you simply pass the number of zero-bytes + /// that should be written. + @since(version = 0.2.0) + write-zeroes: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Perform a write of up to 4096 zeroes, and then flush the stream. + /// Block until all of these operations are complete, or an error + /// occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + @since(version = 0.2.0) + blocking-write-zeroes-and-flush: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivalent to: + /// 1. calling `check-write` on the `output-stream` + /// 2. calling `read` on the `input-stream` with the smaller of the + /// `check-write` permitted length and the `len` provided to `splice` + /// 3. calling `write` on the `output-stream` with that read data. + /// + /// Any error reported by the call to `check-write`, `read`, or + /// `write` ends the splice and reports that error. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + @since(version = 0.2.0) + splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + len: u64, + ) -> result; + + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until the + /// `output-stream` is ready for writing, and the `input-stream` + /// is ready for reading, before performing the `splice`. + @since(version = 0.2.0) + blocking-splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + len: u64, + ) -> result; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/world.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/world.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/io/world.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/io/world.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +package wasi:io@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import streams; + + @since(version = 0.2.0) + import poll; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure-seed.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure-seed.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure-seed.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure-seed.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +package wasi:random@0.2.4; +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure-seed { + /// Return a 128-bit value that may contain a pseudo-random value. + /// + /// The returned value is not required to be computed from a CSPRNG, and may + /// even be entirely deterministic. Host implementations are encouraged to + /// provide pseudo-random values to any program exposed to + /// attacker-controlled content, to enable DoS protection built into many + /// languages' hash-map implementations. + /// + /// This function is intended to only be called once, by a source language + /// to initialize Denial Of Service (DoS) protection in its hash-map + /// implementation. + /// + /// # Expected future evolution + /// + /// This will likely be changed to a value import, to prevent it from being + /// called multiple times and potentially used for purposes other than DoS + /// protection. + @since(version = 0.2.0) + insecure-seed: func() -> tuple; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/insecure.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +package wasi:random@0.2.4; +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure { + /// Return `len` insecure pseudo-random bytes. + /// + /// This function is not cryptographically secure. Do not use it for + /// anything related to security. + /// + /// There are no requirements on the values of the returned bytes, however + /// implementations are encouraged to return evenly distributed values with + /// a long period. + @since(version = 0.2.0) + get-insecure-random-bytes: func(len: u64) -> list; + + /// Return an insecure pseudo-random `u64` value. + /// + /// This function returns the same type of pseudo-random data as + /// `get-insecure-random-bytes`, represented as a `u64`. + @since(version = 0.2.0) + get-insecure-random-u64: func() -> u64; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/random.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/random.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/random.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/random.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +package wasi:random@0.2.4; +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface random { + /// Return `len` cryptographically-secure random or pseudo-random bytes. + /// + /// This function must produce data at least as cryptographically secure and + /// fast as an adequately seeded cryptographically-secure pseudo-random + /// number generator (CSPRNG). It must not block, from the perspective of + /// the calling program, under any circumstances, including on the first + /// request and on requests for numbers of bytes. The returned data must + /// always be unpredictable. + /// + /// This function must always return fresh data. Deterministic environments + /// must omit this function, rather than implementing it with deterministic + /// data. + @since(version = 0.2.0) + get-random-bytes: func(len: u64) -> list; + + /// Return a cryptographically-secure random or pseudo-random `u64` value. + /// + /// This function returns the same type of data as `get-random-bytes`, + /// represented as a `u64`. + @since(version = 0.2.0) + get-random-u64: func() -> u64; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/world.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/world.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/random/world.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/random/world.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +package wasi:random@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import random; + + @since(version = 0.2.0) + import insecure; + + @since(version = 0.2.0) + import insecure-seed; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/instance-network.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/instance-network.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/instance-network.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/instance-network.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ + +/// This interface provides a value-export of the default network handle.. +@since(version = 0.2.0) +interface instance-network { + @since(version = 0.2.0) + use network.{network}; + + /// Get a handle to the default network. + @since(version = 0.2.0) + instance-network: func() -> network; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/ip-name-lookup.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/ip-name-lookup.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/ip-name-lookup.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/ip-name-lookup.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +@since(version = 0.2.0) +interface ip-name-lookup { + @since(version = 0.2.0) + use wasi:io/poll@0.2.4.{pollable}; + @since(version = 0.2.0) + use network.{network, error-code, ip-address}; + + /// Resolve an internet host name to a list of IP addresses. + /// + /// Unicode domain names are automatically converted to ASCII using IDNA encoding. + /// If the input is an IP address string, the address is parsed and returned + /// as-is without making any external requests. + /// + /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. + /// + /// This function never blocks. It either immediately fails or immediately + /// returns successfully with a `resolve-address-stream` that can be used + /// to (asynchronously) fetch the results. + /// + /// # Typical errors + /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. + /// + /// # References: + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + resolve-addresses: func(network: borrow, name: string) -> result; + + @since(version = 0.2.0) + resource resolve-address-stream { + /// Returns the next address from the resolver. + /// + /// This function should be called multiple times. On each call, it will + /// return the next address in connection order preference. If all + /// addresses have been exhausted, this function returns `none`. + /// + /// This function never returns IPv4-mapped IPv6 addresses. + /// + /// # Typical errors + /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) + /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) + /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) + /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) + @since(version = 0.2.0) + resolve-next-address: func() -> result, error-code>; + + /// Create a `pollable` which will resolve once the stream is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/network.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/network.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/network.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/network.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,169 @@ +@since(version = 0.2.0) +interface network { + @unstable(feature = network-error-code) + use wasi:io/error@0.2.4.{error}; + + /// An opaque resource that represents access to (a subset of) the network. + /// This enables context-based security for networking. + /// There is no need for this to map 1:1 to a physical network interface. + @since(version = 0.2.0) + resource network; + + /// Error codes. + /// + /// In theory, every API can return any error code. + /// In practice, API's typically only return the errors documented per API + /// combined with a couple of errors that are always possible: + /// - `unknown` + /// - `access-denied` + /// - `not-supported` + /// - `out-of-memory` + /// - `concurrency-conflict` + /// + /// See each individual API for what the POSIX equivalents are. They sometimes differ per API. + @since(version = 0.2.0) + enum error-code { + /// Unknown error + unknown, + + /// Access denied. + /// + /// POSIX equivalent: EACCES, EPERM + access-denied, + + /// The operation is not supported. + /// + /// POSIX equivalent: EOPNOTSUPP + not-supported, + + /// One of the arguments is invalid. + /// + /// POSIX equivalent: EINVAL + invalid-argument, + + /// Not enough memory to complete the operation. + /// + /// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY + out-of-memory, + + /// The operation timed out before it could finish completely. + timeout, + + /// This operation is incompatible with another asynchronous operation that is already in progress. + /// + /// POSIX equivalent: EALREADY + concurrency-conflict, + + /// Trying to finish an asynchronous operation that: + /// - has not been started yet, or: + /// - was already finished by a previous `finish-*` call. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + not-in-progress, + + /// The operation has been aborted because it could not be completed immediately. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + would-block, + + + /// The operation is not valid in the socket's current state. + invalid-state, + + /// A new socket resource could not be created because of a system limit. + new-socket-limit, + + /// A bind operation failed because the provided address is not an address that the `network` can bind to. + address-not-bindable, + + /// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. + address-in-use, + + /// The remote address is not reachable + remote-unreachable, + + + /// The TCP connection was forcefully rejected + connection-refused, + + /// The TCP connection was reset. + connection-reset, + + /// A TCP connection was aborted. + connection-aborted, + + + /// The size of a datagram sent to a UDP socket exceeded the maximum + /// supported size. + datagram-too-large, + + + /// Name does not exist or has no suitable associated IP addresses. + name-unresolvable, + + /// A temporary failure in name resolution occurred. + temporary-resolver-failure, + + /// A permanent failure in name resolution occurred. + permanent-resolver-failure, + } + + /// Attempts to extract a network-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// network-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are network-related errors. + @unstable(feature = network-error-code) + network-error-code: func(err: borrow) -> option; + + @since(version = 0.2.0) + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + @since(version = 0.2.0) + type ipv4-address = tuple; + @since(version = 0.2.0) + type ipv6-address = tuple; + + @since(version = 0.2.0) + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + @since(version = 0.2.0) + record ipv4-socket-address { + /// sin_port + port: u16, + /// sin_addr + address: ipv4-address, + } + + @since(version = 0.2.0) + record ipv6-socket-address { + /// sin6_port + port: u16, + /// sin6_flowinfo + flow-info: u32, + /// sin6_addr + address: ipv6-address, + /// sin6_scope_id + scope-id: u32, + } + + @since(version = 0.2.0) + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp-create-socket.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp-create-socket.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp-create-socket.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp-create-socket.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +@since(version = 0.2.0) +interface tcp-create-socket { + @since(version = 0.2.0) + use network.{network, error-code, ip-address-family}; + @since(version = 0.2.0) + use tcp.{tcp-socket}; + + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` + /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + create-tcp-socket: func(address-family: ip-address-family) -> result; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/tcp.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,387 @@ +@since(version = 0.2.0) +interface tcp { + @since(version = 0.2.0) + use wasi:io/streams@0.2.4.{input-stream, output-stream}; + @since(version = 0.2.0) + use wasi:io/poll@0.2.4.{pollable}; + @since(version = 0.2.0) + use wasi:clocks/monotonic-clock@0.2.4.{duration}; + @since(version = 0.2.0) + use network.{network, error-code, ip-socket-address, ip-address-family}; + + @since(version = 0.2.0) + enum shutdown-type { + /// Similar to `SHUT_RD` in POSIX. + receive, + + /// Similar to `SHUT_WR` in POSIX. + send, + + /// Similar to `SHUT_RDWR` in POSIX. + both, + } + + /// A TCP socket resource. + /// + /// The socket can be in one of the following states: + /// - `unbound` + /// - `bind-in-progress` + /// - `bound` (See note below) + /// - `listen-in-progress` + /// - `listening` + /// - `connect-in-progress` + /// - `connected` + /// - `closed` + /// See + /// for more information. + /// + /// Note: Except where explicitly mentioned, whenever this documentation uses + /// the term "bound" without backticks it actually means: in the `bound` state *or higher*. + /// (i.e. `bound`, `listen-in-progress`, `listening`, `connect-in-progress` or `connected`) + /// + /// In addition to the general error codes documented on the + /// `network::error-code` type, TCP socket methods may always return + /// `error(invalid-state)` when in the `closed` state. + @since(version = 0.2.0) + resource tcp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// Bind can be attempted multiple times on the same socket, even with + /// different arguments on each iteration. But never concurrently and + /// only as long as the previous bind failed. Once a bind succeeds, the + /// binding can't be changed anymore. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) + /// - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT + /// state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR + /// socket option should be set implicitly on all platforms, except on Windows where this is the default behavior + /// and SO_REUSEADDR performs something different entirely. + /// + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-bind: func() -> result<_, error-code>; + + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the `connected` state. + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// After a failed connection attempt, the socket will be in the `closed` + /// state and the only valid action left is to `drop` the socket. A single + /// socket can not be used to connect more than once. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) + /// - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN) + /// - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows) + /// - `timeout`: Connection timed out. (ETIMEDOUT) + /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) + /// - `connection-reset`: The connection was reset. (ECONNRESET) + /// - `connection-aborted`: The connection was aborted. (ECONNABORTED) + /// - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `not-in-progress`: A connect operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// The POSIX equivalent of `start-connect` is the regular `connect` syscall. + /// Because all WASI sockets are non-blocking this is expected to return + /// EINPROGRESS, which should be translated to `ok()` in WASI. + /// + /// The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT` + /// with a timeout of 0 on the socket descriptor. Followed by a check for + /// the `SO_ERROR` socket option, in case the poll signaled readiness. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-connect: func() -> result, error-code>; + + /// Start listening for new connections. + /// + /// Transitions the socket into the `listening` state. + /// + /// Unlike POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the `listening` state. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) + /// - `not-in-progress`: A listen operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the listen operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `listen` as part of either `start-listen` or `finish-listen`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-listen: func() -> result<_, error-code>; + @since(version = 0.2.0) + finish-listen: func() -> result<_, error-code>; + + /// Accept a new client socket. + /// + /// The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `keep-alive-enabled` + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// - `hop-limit` + /// - `receive-buffer-size` + /// - `send-buffer-size` + /// + /// On success, this function returns the newly accepted client socket along with + /// a pair of streams that can be used to read & write to the connection. + /// + /// # Typical errors + /// - `invalid-state`: Socket is not in the `listening` state. (EINVAL) + /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) + /// - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + accept: func() -> result, error-code>; + + /// Get the bound local address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + local-address: func() -> result; + + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + remote-address: func() -> result; + + /// Whether the socket is in the `listening` state. + /// + /// Equivalent to the SO_ACCEPTCONN socket option. + @since(version = 0.2.0) + is-listening: func() -> bool; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + @since(version = 0.2.0) + address-family: func() -> ip-address-family; + + /// Hints the desired listen queue size. Implementations are free to ignore this. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// + /// # Typical errors + /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. + /// - `invalid-argument`: (set) The provided value was 0. + /// - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state. + @since(version = 0.2.0) + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + + /// Enables or disables keepalive. + /// + /// The keepalive behavior can be adjusted using: + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// These properties can be configured while `keep-alive-enabled` is false, but only come into effect when `keep-alive-enabled` is true. + /// + /// Equivalent to the SO_KEEPALIVE socket option. + @since(version = 0.2.0) + keep-alive-enabled: func() -> result; + @since(version = 0.2.0) + set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; + + /// Amount of time the connection has to be idle before TCP starts sending keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS) + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-idle-time: func() -> result; + @since(version = 0.2.0) + set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; + + /// The time between keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPINTVL socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-interval: func() -> result; + @since(version = 0.2.0) + set-keep-alive-interval: func(value: duration) -> result<_, error-code>; + + /// The maximum amount of keepalive packets TCP should send before aborting the connection. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPCNT socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-count: func() -> result; + @since(version = 0.2.0) + set-keep-alive-count: func(value: u32) -> result<_, error-code>; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + @since(version = 0.2.0) + hop-limit: func() -> result; + @since(version = 0.2.0) + set-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + receive-buffer-size: func() -> result; + @since(version = 0.2.0) + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + @since(version = 0.2.0) + send-buffer-size: func() -> result; + @since(version = 0.2.0) + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + + /// Create a `pollable` which can be used to poll for, or block on, + /// completion of any of the asynchronous operations of this socket. + /// + /// When `finish-bind`, `finish-listen`, `finish-connect` or `accept` + /// return `error(would-block)`, this pollable can be used to wait for + /// their success or failure, after which the method can be retried. + /// + /// The pollable is not limited to the async operation that happens to be + /// in progress at the time of calling `subscribe` (if any). Theoretically, + /// `subscribe` only has to be called once per socket and can then be + /// (re)used for the remainder of the socket's lifetime. + /// + /// See + /// for more information. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + + /// Initiate a graceful shutdown. + /// + /// - `receive`: The socket is not expecting to receive any data from + /// the peer. The `input-stream` associated with this socket will be + /// closed. Any data still in the receive queue at time of calling + /// this method will be discarded. + /// - `send`: The socket has no more data to send to the peer. The `output-stream` + /// associated with this socket will be closed and a FIN packet will be sent. + /// - `both`: Same effect as `receive` & `send` combined. + /// + /// This function is idempotent; shutting down a direction more than once + /// has no effect and returns `ok`. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp-create-socket.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp-create-socket.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp-create-socket.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp-create-socket.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +@since(version = 0.2.0) +interface udp-create-socket { + @since(version = 0.2.0) + use network.{network, error-code, ip-address-family}; + @since(version = 0.2.0) + use udp.{udp-socket}; + + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, + /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References: + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + create-udp-socket: func(address-family: ip-address-family) -> result; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/udp.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,288 @@ +@since(version = 0.2.0) +interface udp { + @since(version = 0.2.0) + use wasi:io/poll@0.2.4.{pollable}; + @since(version = 0.2.0) + use network.{network, error-code, ip-socket-address, ip-address-family}; + + /// A received datagram. + @since(version = 0.2.0) + record incoming-datagram { + /// The payload. + /// + /// Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + data: list, + + /// The source address. + /// + /// This field is guaranteed to match the remote address the stream was initialized with, if any. + /// + /// Equivalent to the `src_addr` out parameter of `recvfrom`. + remote-address: ip-socket-address, + } + + /// A datagram to be sent out. + @since(version = 0.2.0) + record outgoing-datagram { + /// The payload. + data: list, + + /// The destination address. + /// + /// The requirements on this field depend on how the stream was initialized: + /// - with a remote address: this field must be None or match the stream's remote address exactly. + /// - without a remote address: this field is required. + /// + /// If this value is None, the send operation is equivalent to `send` in POSIX. Otherwise it is equivalent to `sendto`. + remote-address: option, + } + + /// A UDP socket handle. + @since(version = 0.2.0) + resource udp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the port is zero, the socket will be bound to a random free port. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-bind: func() -> result<_, error-code>; + + /// Set up inbound & outbound communication channels, optionally to a specific peer. + /// + /// This function only changes the local socket configuration and does not generate any network traffic. + /// On success, the `remote-address` of the socket is updated. The `local-address` may be updated as well, + /// based on the best network path to `remote-address`. + /// + /// When a `remote-address` is provided, the returned streams are limited to communicating with that specific peer: + /// - `send` can only be used to send to this destination. + /// - `receive` will only return datagrams sent from the provided `remote-address`. + /// + /// This method may be called multiple times on the same socket to change its association, but + /// only the most recently returned pair of streams will be operational. Implementations may trap if + /// the streams returned by a previous invocation haven't been dropped yet before calling `stream` again. + /// + /// The POSIX equivalent in pseudo-code is: + /// ```text + /// if (was previously connected) { + /// connect(s, AF_UNSPEC) + /// } + /// if (remote_address is Some) { + /// connect(s, remote_address) + /// } + /// ``` + /// + /// Unlike in POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-state`: The socket is not bound. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + %stream: func(remote-address: option) -> result, error-code>; + + /// Get the current bound address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + local-address: func() -> result; + + /// Get the address the socket is currently streaming to. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not streaming to a specific remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + @since(version = 0.2.0) + address-family: func() -> ip-address-family; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + @since(version = 0.2.0) + unicast-hop-limit: func() -> result; + @since(version = 0.2.0) + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + receive-buffer-size: func() -> result; + @since(version = 0.2.0) + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + @since(version = 0.2.0) + send-buffer-size: func() -> result; + @since(version = 0.2.0) + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + + /// Create a `pollable` which will resolve once the socket is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + @since(version = 0.2.0) + resource incoming-datagram-stream { + /// Receive messages on the socket. + /// + /// This function attempts to receive up to `max-results` datagrams on the socket without blocking. + /// The returned list may contain fewer elements than requested, but never more. + /// + /// This function returns successfully with an empty list when either: + /// - `max-results` is 0, or: + /// - `max-results` is greater than 0, but no results are immediately available. + /// This function never returns `error(would-block)`. + /// + /// # Typical errors + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + receive: func(max-results: u64) -> result, error-code>; + + /// Create a `pollable` which will resolve once the stream is ready to receive again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + @since(version = 0.2.0) + resource outgoing-datagram-stream { + /// Check readiness for sending. This function never blocks. + /// + /// Returns the number of datagrams permitted for the next call to `send`, + /// or an error. Calling `send` with more datagrams than this function has + /// permitted will trap. + /// + /// When this function returns ok(0), the `subscribe` pollable will + /// become ready when this function will report at least ok(1), or an + /// error. + /// + /// Never returns `would-block`. + check-send: func() -> result; + + /// Send messages on the socket. + /// + /// This function attempts to send all provided `datagrams` on the socket without blocking and + /// returns how many messages were actually sent (or queued for sending). This function never + /// returns `error(would-block)`. If none of the datagrams were able to be sent, `ok(0)` is returned. + /// + /// This function semantically behaves the same as iterating the `datagrams` list and sequentially + /// sending each individual datagram until either the end of the list has been reached or the first error occurred. + /// If at least one datagram has been sent successfully, this function never returns an error. + /// + /// If the input list is empty, the function returns `ok(0)`. + /// + /// Each call to `send` must be permitted by a preceding `check-send`. Implementations must trap if + /// either `check-send` was not called or `datagrams` contains more items than `check-send` permitted. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The socket is in "connected" mode and `remote-address` is `some` value that does not match the address passed to `stream`. (EISCONN) + /// - `invalid-argument`: The socket is not "connected" and no value for `remote-address` was provided. (EDESTADDRREQ) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + send: func(datagrams: list) -> result; + + /// Create a `pollable` which will resolve once the stream is ready to send again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/world.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/world.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/world.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/deps/sockets/world.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +package wasi:sockets@0.2.4; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import instance-network; + @since(version = 0.2.0) + import network; + @since(version = 0.2.0) + import udp; + @since(version = 0.2.0) + import udp-create-socket; + @since(version = 0.2.0) + import tcp; + @since(version = 0.2.0) + import tcp-create-socket; + @since(version = 0.2.0) + import ip-name-lookup; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/wasi-crate.wit clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/wasi-crate.wit --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/wit/wasi-crate.wit 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/wit/wasi-crate.wit 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +package rust:wasi; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo/config clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo/config --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo/config 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo/config 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +# TODO: we shouldn't check this in to git, need to figure out how to avoid doing +# that. +[target.wasm32-unknown-unknown] +runner = 'cargo run -p wasm-bindgen-cli --bin wasm-bindgen-test-runner --' + +[target.'cfg(all())'] +rustflags = [ + "-Adead_code", + "-Anon_upper_case_globals", + "-Aunused_doc_comments", + "-Aclippy::large_enum_variant", + "-Aclippy::missing_safety_doc", + "-Aclippy::new_without_default", + "-Aclippy::overly_complex_bool_expr", + "-Aclippy::too_many_arguments", + "-Aclippy::type_complexity" +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"3aeb51357b665c9dcdf3ba9a9e54bc1888e17cef435b287fcbc37987aa861c0f","CONTRIBUTING.md":"aa138d76f5cb25bba1a6942a230373aaed6be73c619f945cc4657e13ba69f897","Cargo.toml":"30dc8c10c522df2360aa9c8811299da71c612f0069d943339ae8357ade9ebef2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"36a2db1bda9f5fc21d8d6ed8d34a13fb049a1db642129d0d1af269634a068a33","_package.json":"7a84fbc7f68f390315d93d2d808d5b27344644eb5df59a51bbe7a854d2a6231a","build.rs":"95d57e593c411b82bf88819765d6422db2a65c1bf489b63f87e0aefeb721fc41","examples/README.md":"e5396e95d8130948e48b767ab505c46bc69f6ff3ebfe0d9709068cf42c250818","examples/import_js/README.md":"bb53d4a264e9a084effdc7a22ca7d5acca0207b411478b98782d881b7fcade51","examples/import_js/index.html":"f4825d155bfe0059aa182a506d6d076d1ba5f118e46365ac902b12f27a6c8c0d","examples/import_js/index.js":"d425b7b0636dc5c5046bc96e6bfe6ef3bb1503fa91c54f40ecb457a1b060ee5c","examples/import_js/package.json":"f65f4a456da892c99cf3a5c961283e4d39780a56be5b6ae5fb2bbc9f235fdaae","examples/import_js/webpack.config.js":"fc314556d2f0c6266cde7c47afaceebe474be97c0401985a23d822ad9dd0105a","guide/book.toml":"d8cae5ae5fbeaab5b6852c64b975d37f51592a8e9eedba22c898672d9b11e9be","guide/src/SUMMARY.md":"3cd53341dc5e6246e77dcb3f71a69091c25c847fbd74302ba9a5536284dfc6ec","guide/src/_headers":"401cee68df5967f0aa509a1b978a83f06e8e830deca1433964703e7a1ac2c646","guide/src/contributing/design/describe.md":"3186f9795be894708788e50d2ee745b9bd73bc94fb3dce67f3f1fd5e7fbd3659","guide/src/contributing/design/exporting-rust-struct.md":"2ead6b67f241bab543bb96c80e90b63abd67822a7c94190d2f2d1c9809a59b87","guide/src/contributing/design/exporting-rust.md":"ad88a5e0fccafe6c27e5a8bd951cf3e2fee1846da77a665f255999d9dd5961a6","guide/src/contributing/design/importing-js-struct.md":"848d0b144b28a5ae1ca3760438e71b938cfb2ee350f5b902fd08c38a0a64e27b","guide/src/contributing/design/importing-js.md":"c949c8921c213ba21b08f705d4611304acba47b68c35484fe968a80194f3a9ab","guide/src/contributing/design/index.md":"bf99c93e3925eee343f0c8fa59f9f0018fe04a0004867738c4234a895f399af9","guide/src/contributing/design/js-objects-in-rust.md":"0a18922b509ed8a6cc6724b81af6e6d469b75b3796dba770949a8b59d8067455","guide/src/contributing/design/rust-type-conversions.md":"3eb1b6b5b6b138d5f39148612ede378fc73137b32458a8c17c6d4b1cf9e8b7e4","guide/src/contributing/index.md":"d02b4f2f238b9fdb62fbc09bef3f0e9fc0ccb3f8cf977d0f2c6ebc1ec2634e42","guide/src/contributing/js-sys/adding-more-apis.md":"d6626d530fa5b73f045a20bf123d5e261ac2ca3bd64cbb80b655612f9b9a6276","guide/src/contributing/js-sys/index.md":"9c0864ca52e8699148e789c2a6ba2d3044ba2358d7106a1b7fd725d3720dbb54","guide/src/contributing/js-sys/testing.md":"d1f613c88793ffce61b2d77aa40e3a91a1de3c73ab9f8eaedfc39da16c93ad07","guide/src/contributing/publishing.md":"7aaeaab68e4173712b346b02444e31de983326c8871ecac0f42a5552647f65eb","guide/src/contributing/team.md":"a3f993cb1afeee767e85077d135b1ea08850c433a69c436ebe6b7a48124ed945","guide/src/contributing/testing.md":"c3c720acfea72768117fbc2b95181b48caae1eaae1e3660d44ac5cb883d9e259","guide/src/contributing/web-sys/index.md":"6b4d5e00cbbcaab29295a3bd60e90b7f72b118758966622a307d9222488707c1","guide/src/contributing/web-sys/logging.md":"ee960ec9adc174183fb349acdbf5fc647b6f9a290022be9b118b9de37b8b5687","guide/src/contributing/web-sys/overview.md":"e6179317f75aa8e836e3c803f5d814e87119763709eea47b04cebc86c089d80a","guide/src/contributing/web-sys/supporting-more-web-apis.md":"a3817d09c6cdc3cb28a1b77cdad5e4436ab5bc37f9d681b1e495815ca91de85a","guide/src/contributing/web-sys/testing.md":"77f8e4b45bd0e27676dd503474bc32f91672b23c6ab7127a4f5b828dc8ea40e4","guide/src/examples/2d-canvas.md":"44a0eb82ec3398ee63a6df5aab103f1b002082eac2d129f656d8519cbc0829e7","guide/src/examples/2d-canvas.png":"b202cd79b20c00d49c40d71225eefea99306015858a432ceb7592d53c15300f7","guide/src/examples/add.md":"8dac740d6a4c499d868c29d8426d113da9cdd6ef22bf8084b8cf8c1de513b09c","guide/src/examples/char.md":"93f94a1b670322d0dc21b46d749909c414f9f254e2dd97afd8afe8cb0e5ab908","guide/src/examples/closures.md":"669dfc47a670271d7ce7a3bd2c08620b698b01ea8b2a7b1cc2047a77e7617130","guide/src/examples/console-log.md":"6552f4d766291cddc0eade75e4f64de9f10e00b89a0bedb1b15dcf7baa90b6e0","guide/src/examples/dom.md":"44ad74370b3727ec98f958273c639e767f2ae5b75e96ef53e74be1833a630272","guide/src/examples/fetch.md":"0f9d08e240bc5ced13ab154182aedef7fa7b00cba784c65727aa15be27f86d7c","guide/src/examples/hello-world.md":"d5f4d830c316a91e951cdaeab5cb23ae47dbc910b05de849e67bef1ea709564f","guide/src/examples/import-js.md":"0480a6aa32b1fdc1347cb3d0c4f2a006caeb33c75ed21eb78ad800f012cbc2c6","guide/src/examples/index.md":"4e629f42d7bfb52bc35856b6e21c3aa7433563482697212d7b54f1bf619b56ed","guide/src/examples/julia.md":"0cd4ae1de24d657d7869c984dec61cc8b796621365be633212bdb2a6d57ce727","guide/src/examples/paint.md":"06c6c04f121080e0e5600b4ad300df9e93b5d4b6342f42c421e6dec1f2955ced","guide/src/examples/performance.md":"de888713cf0a047bd4a28a1ca890be51d99b6aaabc9a2b134280b768a7148377","guide/src/examples/raytrace.md":"6769cf3b7bd14e9814e751927fde8c5acb443c5e82758285a1ee4f91e577a870","guide/src/examples/request-animation-frame.md":"26eef6b203acc0b2667d9c4380c39a44eb4b97991efeded9ca32cc9ab454e993","guide/src/examples/synchronous-instantiation.md":"c2f887e4754535c453d22438c3179d71d2468d8994a61330a362132c73157ef1","guide/src/examples/todomvc.md":"b872c5631eae969368d147342fca16dadb6f0412f8922230c27271370e9d3d97","guide/src/examples/wasm-audio-worklet.md":"a2f390bef5f69365da496ddfe8995520cf8441770a6026037b1882fcd4d5ea34","guide/src/examples/wasm-in-wasm.md":"5439a690e7107736e6f8b92e475f0a45e83ab9a1e5a0fe02e8f6dd93372590c6","guide/src/examples/wasm-in-web-worker.md":"b05c2285be7802251ac71ae7e4a91ddf52ab286336308a6328f4b143cd5811c4","guide/src/examples/wasm2js.md":"48f953dfa1b17b68e5d983231e991797e32e9bc22b9c3db72c2d055e08449a00","guide/src/examples/weather_report.md":"0b6778aa7f44c0bb0ba18daaf7623cfe1776b133611a6cf136935d82ef388db1","guide/src/examples/web-audio.md":"32bb18c9e4f167614ce3fb61d1d04265449f88da40949834b50baf9e37063fbd","guide/src/examples/webgl.md":"15570a0a081c2301981a1fbca0bd39dfcf35221c64ddfb8e8f4477660658cb08","guide/src/examples/webrtc_datachannel.md":"47b06b1b00c41f048fad3c2206399cae2d8dbd90b6d83953c138826f11677eb5","guide/src/examples/websockets.md":"704f9d5c1d13426e6e64e132cb0204be3c10a54dbfa5f1c834adc4efb4a1b8d2","guide/src/examples/without-a-bundler.md":"ecebd50a1d4ab8e2996fb01188cbde0c49da096a1c25027da68b97371c025540","guide/src/introduction.md":"981c2c4d0224cdc4ad71d70f85c6dbd9b2194c174f24c5e9d52d74c0f49613b4","guide/src/reference/accessing-properties-of-untyped-js-values.md":"a91e3eb706ddd15628072978906e2faca31560de616c0630316d9f6eff6b55bf","guide/src/reference/arbitrary-data-with-serde.md":"b281146412f6bda893f146e84721677f003cad57af941552c2faf534b61b2d98","guide/src/reference/attributes/index.md":"12b57ebbd0c9ba42d9f10d752c9943d9beec90d659d1b1ff9e9bfea02572a2c8","guide/src/reference/attributes/on-js-imports/catch.md":"da230e6986ca29f1e82313b82275ab9c3b2144906271cf82b27772541d781d84","guide/src/reference/attributes/on-js-imports/constructor.md":"89f8be11c567b4611c84209b34351238553d5360d7f7665ea25332e1544c5b99","guide/src/reference/attributes/on-js-imports/extends.md":"84ece37398ba0df66f890982315f082c52b5f027e03c20527755abe610c2567c","guide/src/reference/attributes/on-js-imports/final.md":"2599df0288dab5d57c70d6bb19b79d8bbd027e5e1435924127e01121ab60e20a","guide/src/reference/attributes/on-js-imports/getter-and-setter.md":"27f3c2738688a43e611524e5e3ab7174a1993026a69098b75780a388aeb5e745","guide/src/reference/attributes/on-js-imports/index.md":"2219a4514fe9597cbbe6c46014b57c38f1e85f3d0775a8a7880f50858cb13633","guide/src/reference/attributes/on-js-imports/indexing-getter-setter-deleter.md":"11d5c03f922294894fe0147fae96e04b26a5adb36ce91296e52729a9fe5931c2","guide/src/reference/attributes/on-js-imports/js_class.md":"d51c5f05b71bbf6b6ec8e0c36314ae299fd7eb07be989e721b79b599405b3486","guide/src/reference/attributes/on-js-imports/js_name.md":"12457466f3510256a51a78f52b09f7cb1c0b0ce3ef636e028cd2c372fa9e8738","guide/src/reference/attributes/on-js-imports/js_namespace.md":"acaccd162a982c1c17b659ce5daa1d5a0d184b9b07728fc5bb17a89f327ffafa","guide/src/reference/attributes/on-js-imports/method.md":"d54246efce5d7a104702439ba509bcc5bfbb0b57253edebdb696617daca80bcd","guide/src/reference/attributes/on-js-imports/module.md":"b47cd5ccbb69955f1d47101accc96fcd562abecbf7e34826f7f3c585d6b9dad0","guide/src/reference/attributes/on-js-imports/no_deref.md":"7d58bb3b6f768e38b949727abd1ee621ad09ebc537f83a8a20d0eeddf3771b95","guide/src/reference/attributes/on-js-imports/raw_module.md":"f363e5f3bc401b7e350eeec49cffde85dfb2346d597f38d98993fe5bfb9ff649","guide/src/reference/attributes/on-js-imports/static_method_of.md":"d5a5d9623ee55097f26e190b478e75f2e7d2ffc30e51ec647f39933d3d4e3b18","guide/src/reference/attributes/on-js-imports/structural.md":"364e01a5792029e9a5fa582375736efcee006352834ee273d218da89b77dd8bf","guide/src/reference/attributes/on-js-imports/typescript_type.md":"abdb26584e88bed32c4dc7b2d4ed2e3cb2007f1bbf73412fa87dec823db76b2a","guide/src/reference/attributes/on-js-imports/variadic.md":"1ecf00149be472e3111f188c053092f3274fb33453414516a305084d8e92c4df","guide/src/reference/attributes/on-js-imports/vendor_prefix.md":"47a8d47e0cd745cca697f6d944e145f02695ca422255c3d6e1c9b2b719994b1b","guide/src/reference/attributes/on-rust-exports/constructor.md":"8708873e656827869b6708be1997f9212ee801b997b6f223c5a2af09ab7eedae","guide/src/reference/attributes/on-rust-exports/getter-and-setter.md":"464a2d41a791bd8ba5a8b1c4aa64b2f865c42b98a2d1289bb65e766e98a1b56a","guide/src/reference/attributes/on-rust-exports/getter_with_clone.md":"11a04dba4d66c19be0e234014d21ccf9cd0b76169b723e90ceb81d719478f283","guide/src/reference/attributes/on-rust-exports/index.md":"9fe778a0dd013a874db484cb22b1d9867bfe6d69cfbbe5cfeaa8ab78cf19daab","guide/src/reference/attributes/on-rust-exports/inspectable.md":"52fbcfdb83c426430a95692d566a4709255e25b24be5704d7378a4196a8c5908","guide/src/reference/attributes/on-rust-exports/js_class.md":"f4c0d8e8021001578f7d300e88c438d1a7806c17cc0d8acc3b4134922a75affc","guide/src/reference/attributes/on-rust-exports/js_name.md":"77f035b6391b9e44f254a411ba18687c5fa6110e276be73b5ea347701c8dad42","guide/src/reference/attributes/on-rust-exports/main.md":"d1a42470fb0457b3471e96ba22ca270c1cfc9d5fa781240a9d8b1aef32641ff8","guide/src/reference/attributes/on-rust-exports/readonly.md":"a5da847ad36557f03b1c79a83d14c219dce914021266133c204260bc041b9b89","guide/src/reference/attributes/on-rust-exports/skip.md":"b9972241b8d473d1a46ef3c2861065ca296cdc923883c404f19f1d859bf914a6","guide/src/reference/attributes/on-rust-exports/skip_jsdoc.md":"6c400bb6dac1083449758448e5e7a576d40f371592cd597ea95ec441fefe19f8","guide/src/reference/attributes/on-rust-exports/skip_typescript.md":"1622c29b0d93a884bd0b5b2a62107a594e2919758c80592566e7786efe788b89","guide/src/reference/attributes/on-rust-exports/start.md":"dda9cfebb7cceac4b7b4868f82a9e12d3d33215f4f59d1ef40eacf2c33d90933","guide/src/reference/attributes/on-rust-exports/typescript_custom_section.md":"6dd69f15b6f6f632880b7a65cc49abe8f4f95fdead753c576d81a3268dae4985","guide/src/reference/browser-support.md":"177fff4ee6a68c85f045cec47bc7aa40de66fc95f8cb59128e8ef2d6972dbd7b","guide/src/reference/cli.md":"572d8312a88403a0e0f0ca8744037da6fa8f73f2adddd57243f789972deaa452","guide/src/reference/deployment.md":"1954466cd2ac6c5326258364f6390b10cee9c2729e7c2779f2a50f950c7c9523","guide/src/reference/index.md":"c603c3a7f265afb7c7b5eb391b32f6115f8842f3f422fd3730be4f90c4796bc4","guide/src/reference/iterating-over-js-values.md":"ec00f09516eb7de98bf7296f44b6aa9ceee3fae1dcdb7cdf8f36963d45b7ebeb","guide/src/reference/js-promises-and-rust-futures.md":"5f0c0b990f5b55c8d9485f7cc66a617f79cc232705562f306af97785c7ed1f79","guide/src/reference/js-snippets.md":"dff5adcbf66f06322e606c672ef070c2a0375f1ae592ca8a9da36a50324735cc","guide/src/reference/optimize-size.md":"c10abc1ea0902c9a57b74808bcf75bf092c0c2bb4082962b85d18df7593602c1","guide/src/reference/passing-rust-closures-to-js.md":"ce75e529a42f47e74f9d96085a93871879667af3e300c8ddedd9879960d2c36f","guide/src/reference/receiving-js-closures-in-rust.md":"fc9c80ba5e1a5f243a66f68caba27e8103652aeac3765a9fad2d0e16113fede3","guide/src/reference/reference-types.md":"91d178b7fe2ec82eec4d8926a08b39ac16898172d6f65aee84347c6918033c67","guide/src/reference/rust-targets.md":"467d5cf7eaa1d4b89f9f5b2248cdd1a10340ca1db263ffff5c483ce10dcfbf54","guide/src/reference/static-js-objects.md":"930288fc463d16a46a6546f5f65af21ff6e4b94259d9a1e8bca9d660f9770604","guide/src/reference/types.md":"859123f51fa932fa37d7e47cd5c46956929793bd3accea050d3be516080ed78f","guide/src/reference/types/bool.md":"e954d93ec5096837d4dd2db3f23e71c14483279e347ca8908ecb49aded6e497a","guide/src/reference/types/boxed-number-slices.md":"1a217a68ff549f4208f99863d6616521c9d466542c1156bcc2be7d3a73e4edd4","guide/src/reference/types/boxed-slices.md":"f244161c0897d38d5100f32e94bc5b87dbc8277d831536d29d6214d3d0bdf7a8","guide/src/reference/types/char.md":"01f2f7bdb25a9a52edd93dcbbca6a29269a8d5adf6cb94dcadea29a7aace22f4","guide/src/reference/types/exported-rust-types.md":"d2f601d7d39ae92326c5624e1e2a2795f1f47accb92ec030c987b6c709681906","guide/src/reference/types/imported-js-types.md":"c82dba871a26afb7b90ceec59892adfec9bec550665a74d190a4fda639f61d5d","guide/src/reference/types/jsvalue.md":"46d74da47f8a517249de4dd096351c10d658d9c3535950a34c1fc5d5b42eb2f7","guide/src/reference/types/non-null.md":"a79c6f6df2fc81cf7f596815d6cc6d1b0f3a49944ca3e08d2b5e6bcdaf837cc9","guide/src/reference/types/number-slices.md":"f380258fc058527c7dd6f49664a4e9dff69f0b03d626071aeb61efefb2a0b646","guide/src/reference/types/numbers.md":"cce95c07be08c1f16327fd4c7e79b7c480db9cc95e2b07514d31e51bd6122101","guide/src/reference/types/pointers.md":"c2f5b7bac9b49a8e91facd5597fa1df0a6b4c5319627c8022232c21ae9f86755","guide/src/reference/types/result.md":"78be87e86c35d2bbc1b863217c1a7592af9f2c699902f44e22d1bc4b1c0664c0","guide/src/reference/types/str.md":"6cc086b02ae3d3565678e69d91dbf105f1f310009097a37fad4c812e25d4b7c0","guide/src/reference/types/string.md":"9e42298135e0aec11bb924e3a2b5002335cfe290240b48db12dc981156177cd0","guide/src/reference/weak-references.md":"1686a057fc28672d7281af3678688f804adc113fa307fb4229a479d0600ee93c","guide/src/reference/working-with-duck-typed-interfaces.md":"a23f1f98019fed2060e1fbce954ec457e77a3a17524f34ca861d256d2ad4b6ef","guide/src/wasm-bindgen-test/asynchronous-tests.md":"c24c381b719b4bd7b0c181da1db59170e822c142eb22f95c4a6eeb8fd36df3ab","guide/src/wasm-bindgen-test/browsers.md":"84a862202b6b326cb60eb54f032d8d398fbde82c297b750cfa58bf75afedb066","guide/src/wasm-bindgen-test/continuous-integration.md":"5865990ef231b3c99a9c1bc18f7b7f054a29b77ac7b671fcf1cd6bb4f4304ae8","guide/src/wasm-bindgen-test/index.md":"64fbcd222c3c597109d2717a3574abf2041ff325c26ee07d58c4cd7ba1c1f8ad","guide/src/wasm-bindgen-test/usage.md":"a1da64eaaf8fe9bea366724e08a4ba63dc984f86a28cc393fe00dc394ab244d6","guide/src/web-sys/cargo-features.md":"0e50067a7a46cee3d1b21a2690aabc539379cb1452de377ebaa0eaa4e5e587b2","guide/src/web-sys/function-overloads.md":"90a08bb955f7c79e573f83c31d5e7431ae1e3ad7001792ff8ff52e4299364fcd","guide/src/web-sys/index.md":"345499d0840fd23a2e5eb5ac497665decbb3f836fe9f4f88301ae4b5fbd8d44f","guide/src/web-sys/inheritance.md":"8f18af20b930497e2fae4a266dd27e317d1ea3510266c21b32f351354b495ff2","guide/src/web-sys/type-translations.md":"687ef5e4a3961fddcb94d24f69abec0ea64f6df306f4593974b69589215980b1","guide/src/web-sys/unstable-apis.md":"e74c3e72136d6906dd60258a27f34e1ea4612e7c8e95662596475dc557151cfb","guide/src/web-sys/using-web-sys.md":"523e16af6e27703a4a0582568bc97710350222af20801907268d2d8c197fb667","publish.rs":"6352715cf06a9e373a141e34991fa97ec5bdeb0ce7d623a4fbbe9448ef1bea35","releases/friends.sh":"f896ccdcb8445d29ed6dd0d9a360f94d4f33af2f1cc9965e7bb38b156c45949d","releases/release-announcement-template.md":"fcb3c75cdb8d5d6ce8a198f5570c967313f751d1eef0790b34a518772b2e8a38","src/cache/intern.rs":"b78abd7502ad069bbeb61073d1972c717a469849222037565b50514192c187a9","src/cache/mod.rs":"8989143b55160dbc142cb20c6e066cf0a3f70d6c97fbc9aa0fac59bd62bd865b","src/cast.rs":"da53f21aa485c0dae184350d2693ab41e3fc7a34fa300c19ad718f2b7fc2d42b","src/closure.rs":"14abb62c4f4ec073531ed2f6baf9de2e40f13d527d4331da5bf5fd896682257c","src/convert/closures.rs":"51479d4012c18a886653590514290a121893837777e8ab7cc104d3e883129e9d","src/convert/impls.rs":"defe584fff1fe6ad668109d6b1155199f253ae827899ce582415d5b5d6c542e8","src/convert/mod.rs":"566ffd1f546afdb8d24c6c0d6faa00a28596a67ca6f2f39e9485add54400443c","src/convert/slices.rs":"e6cf79787d0031267051da6f03ccb1c1ea1f18952c5458f00d720381daec6725","src/convert/traits.rs":"ccee20adf821982f57a55b9958109a348dcc911ce2d81979328734071430037e","src/describe.rs":"9993bd16b9aa8bfd8d15fc92604f58c7f67e080449dab3c9c2e4c4904b3776af","src/externref.rs":"199a2a31d31bea3b15002ce8075148a91d49ffc71fead08039b5c4f2ab0d2562","src/lib.rs":"3ae23196694cbb6ba3b23971b95fa9fc360c984e4389fe35e61bf6c01951a620","tests/headless/externref_heap_live_count.rs":"41b2758762c91bd2d05995b1b8989651a6bf2e586ffad5597ff63f6d2dc6d755","tests/headless/main.js":"6de0a19b91330e9bc68334c4f1fa11c1cd6bf273f5ea3e470933ad800c962679","tests/headless/main.rs":"d86245fdd476cb6c275c0649d76fd348ab55b7952ece325c1ed4ec00051a1f73","tests/headless/modules.js":"a407c81d2670309ed484adf98a2e522f6ea031b1286416eb7bf184df7433d5da","tests/headless/modules.rs":"74f77f88bb5280862c06087d78c48ba930736e58db9a1e6c80450bb0e032b789","tests/headless/snippets.rs":"baf9d3c68e1b567fcba4e073cc0d24a8f039955e10dd1275e4a389574ff556d7","tests/headless/snippets1.js":"8bd0c367fdbc61f509728255750094bb36200a1aea74079611ad7cfa9c5f3f28","tests/headless/strings.js":"fca2d7a1afae31663607f956134a4f447aaee0f85d828addc3c4c1440f2e18e5","tests/headless/strings.rs":"4a64d8a4f9329a282d0f87408c0645ded71a7d023eaad40a32eaf60886a08375","tests/must_use.rs":"cae67a8740cd2c969a6b33316cd5036639048d9bbfecf55a5f45faaa624de1d0","tests/non_wasm.rs":"d2cca0b81824ac392f55b8d583d2f361ac11bed892968113e33fb3148572b853","tests/std-crate-no-std-dep.rs":"47f0e32bad7b9b11ca77d66d904eb3408c3528732899479039fb6db4c6e9ed9e","tests/unwrap_throw.rs":"79f05fa37249cea08689592d53d856019a90fd1b72c41413f7fcda5cf5913356","tests/wasm/api.js":"daf4b7e2b76b718431235eda5e221dd53037fb6bebbec6023c7e3fd2b806f763","tests/wasm/api.rs":"12219ffafbb57ba8ed315c56f5e18de412df84757e002ae11cb9d2beec13b0e3","tests/wasm/arg_names.js":"0d7de3801257e18756a974bdd2950d2fb06755f7c0d1c681e03b56d97e828e34","tests/wasm/arg_names.rs":"decd8f71a58ebf662a586b7f19e41f6666782df0da74a8a2c69b7a504661dd79","tests/wasm/bigint.js":"b6d045afbbb7d5e8723b41ee2e9c22357c8c4c4aed804bbca2a9b42a19906354","tests/wasm/bigint.rs":"5a7e0e6e6753a5ce08c199334fd89f1cfeabc1305301d988d6f748e001ccfa2c","tests/wasm/char.js":"de540498439728ed74324f526885b4098cdedf0d6b105217cc3ff6abbd77207c","tests/wasm/char.rs":"c43692b5b5d754564355a2715a6a2c88184e0475f2391baf3f9053793b3a0ab5","tests/wasm/classes.js":"aaf4c1300a5e14a06931463a01bbce3c3acfa57de225707f142199e133f03bd7","tests/wasm/classes.rs":"857355b1ab17ad2ec51d6dd3f1b3ceb837601cfb7c36d7a262d2f92681605a60","tests/wasm/closures.js":"6df2da8bad116c9ef244f35f4f14d1fd432e6faf43df30882c6464a521cc606c","tests/wasm/closures.rs":"8e8216f319b9dd3ee2fc83607c62850296a9f0db5a6dc2fb36a87dbb9b170307","tests/wasm/comments.js":"2c3bf2e79ecc33f0fba33d13a91a1ae9390f9f7a466af8eb215636662e20462a","tests/wasm/comments.rs":"5a0068fe3e214c07da92a46b6e45a2771fbd8e04f14cb7802f32082b87a459a0","tests/wasm/duplicate_deps.js":"2226e4f65525c545ab45109879b16b2a92341b440178e75d3a9efb3ed10f7b03","tests/wasm/duplicate_deps.rs":"3a91569e54f56e178dc164f2d2b8537ec6a10b3161c23e1cc8e552805cd868f4","tests/wasm/duplicates.rs":"a2b4a7960e8a7c9b3fda943e8aadb7cbc0ba8fa1a6956baf40ba2f129bd591ee","tests/wasm/duplicates_a.js":"d3d685e95a54b911c2b9a64f7c0f245e3e492491368355044ae2cd12c3332044","tests/wasm/duplicates_b.js":"cd6c87905a5c5514239bba52a03e6c151d79a57a477f52a073b61ef18c98f642","tests/wasm/duplicates_c.js":"93399409996d182b5fe02548d3c5c3e1681939629e0261d6f19f8c1ee3b08dfc","tests/wasm/enum_vecs.js":"28426c3d99ac369d3e87d7ccd177af677bb8bc3d701a152b5f271fc88952bf96","tests/wasm/enum_vecs.rs":"ae3c4c062b63a08481bb1426ba8146e03d9f5d60cc5298880081bbba5ad650bd","tests/wasm/enums.js":"a9277bc042a208b545641f43d9354f7b3ce0e2240d8f9f0af9016bad6a5d5bab","tests/wasm/enums.rs":"c35c6658ec377182c819554108e6e01813323c9258d069fe4c962aec6a1c35c7","tests/wasm/final.js":"cfa7c496291f08b98f0406190ee4deaab9ade890d65ada4c223a76135e66f619","tests/wasm/final.rs":"25b0a85e87686e3f7a7a44e3ac25402d504eec7f9813a74ffd63c5f4428ee0ff","tests/wasm/futures.js":"175745daafcaed4cc0233809f4829228528c87030459645e8493b013cd3e9f98","tests/wasm/futures.rs":"24af063658319fc76d89a30a9582e885465dfde520c6eae34eb5b8b668aa05cc","tests/wasm/getters_and_setters.js":"8ba2d939aab232074860cdf1e01d1c58faee49a31ef35b585c962aceccb870a5","tests/wasm/getters_and_setters.rs":"0dc0e87014ce7e17970883b2e579b921a99a3c9115d67ed781e015f5f27c0ca3","tests/wasm/ignore.rs":"e0b02bab0f015ab1378b33e008129098dbc28bae4a4c443ef9def29e6646f647","tests/wasm/import_class.js":"d1bd1dc7df5bfde686bea6fbcd32db6009b6853712cafb446af263fdebb1fb78","tests/wasm/import_class.rs":"0678cb9272a28f818a54f182e8f229235f6bc79e220738dbf68561bc19d7e0de","tests/wasm/imports.js":"4069b7cf12ae0cca30a1e92750d0715e782a5c795ff21c0d5aae738f726ae8b1","tests/wasm/imports.rs":"56cb87c812c1fb3f6573ca166caa483e97380433d10b1c86fc1237a191630fe1","tests/wasm/imports_2.js":"ab251fc0a0a1921c60d316160bc120fd97da3c3753804174cfda2f08ff43208d","tests/wasm/intrinsics.rs":"1eac40553375d1e5250a9242df19837d1b448296d53ceb41f842c80996e958e9","tests/wasm/js_keywords.js":"d247be675cc73540fea4b2e50bb2b7fcedb2b0d511d85be6fb646876d3025562","tests/wasm/js_keywords.rs":"6944d856346b528c321ac24b1f986e4858d22b37f8f24ad0d393fe7c4ac079d7","tests/wasm/js_objects.js":"a2be00dab58716e4cbbaeba4da8512ba924c39d3f1cb405ba769ab8a780ed7fc","tests/wasm/js_objects.rs":"86f77308ffacc9337d21f62671ce269e723468a53404d0679da43e5e95c90135","tests/wasm/jscast.js":"d678058645d2d370c45ec5fd5bc9b94612b1e70035a9e0f524c134369f06fe1d","tests/wasm/jscast.rs":"bd9041fd4f74cd69435f4d4be019a887d680d7fac86134e42954e94d7c1c5cab","tests/wasm/link_to.js":"b371f4c82da171ce5a3e21a6de172cd1c910a4ff26e021d1a7ede5bfd7829c40","tests/wasm/link_to.rs":"1cbc53a58cf0fb693a8e775c94e3cbebc68f2355d98f4ce972abc42ffd62d014","tests/wasm/linked_module.js":"412bcf020b68e7e5511f4def869cc3384c1e98b923a9b82e25748b40b5b6e640","tests/wasm/macro_rules.rs":"6a8cf079f72aef96a004d559f5a06214ce8b096a3675a5c61c9794aa14448640","tests/wasm/main.rs":"cd81eb4bf0ff84e2b27963ccfee0550e26c96d3e7e1c1342e18c9b17fe6d28a9","tests/wasm/math.js":"9deb196ab7ad3d5d1f98d7d0b6ee60cb125212a4a1281ba0141cc3713fdea892","tests/wasm/math.rs":"be9000d84c6b6b091455e3b20ee7f5a88dbcfc0d38db97fad3dd167970c4b4a3","tests/wasm/no_shims.rs":"6c44ce90e1fcb8d41a7c2d369ce7a2735ba5ce799dcf07b41cbc3ccaa2f27a6a","tests/wasm/node.js":"6ae82d7f07a35b260e085158b080fb7d2c2c40865f579cc7c8688de090f8fa61","tests/wasm/node.rs":"e8b6448045682729bf359f1a70bdb24af57129a554ae2e2dcea1beb0b1715e65","tests/wasm/option.js":"0d0cba722045698e9621f2565acf854bf3085c8739622798085aaa6b58e3edbe","tests/wasm/option.rs":"d82123f7349e22873e636341a52e99e256213e77d4d7ab8450ba6379be2128b7","tests/wasm/optional_primitives.js":"37484639631e1c50bdc055a08babff18d4be9f7a9291f0f3395e1a7c519e5cac","tests/wasm/optional_primitives.rs":"502803cf27b78dd8a6c1d75ae954b71cc017f803486867a87c0474e5d53a6567","tests/wasm/owned.js":"645b47e87fe52e08fbc07951736ab29f4dbab20c051913dba6228b2a08bad0bd","tests/wasm/owned.rs":"99af8eb8c30485b028f37d24352e2db747a425a00ebfed29e02400d87c756f32","tests/wasm/result.js":"78212259f886d864885eca7599199434bd7abec915a2e7fa3b73dfe63284e15c","tests/wasm/result.rs":"a4a4486d3edb6e242d32a9f12916a6cb5d38e07f646f69969ece6838a351448c","tests/wasm/result_jserror.js":"3ea04e68937f15d869535b3bb119d8886dfcde3c16c12c4a18a995f358552154","tests/wasm/result_jserror.rs":"ae4cbd3362841d070722f99fa0dadaf3233661803c73c65a9e63746b58a72134","tests/wasm/rethrow.js":"0a495a8d1b735277e18cc3fc3edf8bd2a72586441d3884134182e5052786ab84","tests/wasm/rethrow.rs":"59dcf192c9e85b0d98031c135d2aa2eda4902a2bc5b740a9ddf1e75dc9cdd23e","tests/wasm/should_panic.rs":"234929575bc55d9181d49938518888cb273bd5f3b1c9f826f94ee8956f1f5584","tests/wasm/simple.js":"10d1d531a6ecf91c1cb0457e8b2d6b43d00555a5f532a903da046fe10417fdc7","tests/wasm/simple.rs":"644ff8a67c3b17c511c7b488831f2e4dd274c1a0784e780dfb560b52552f992e","tests/wasm/slice.js":"f81dafe018089de221b523ef32d56044b9635421aa1f896342a7635d4fbce4f3","tests/wasm/slice.rs":"ea6447e6bcfd41622ec0cda927e86609067c2e0e3049217a7f1985e96c90d99d","tests/wasm/string_vecs.js":"4e422ed793de1bfbc7c9c538f3c10150b625279aff51bd2af92ebd7914130d88","tests/wasm/string_vecs.rs":"1f113573c6f4b5d50a66f34eafa7cc6ccdce042e86ed6efc353c094619ea1561","tests/wasm/struct_vecs.js":"dfc0a5109132ab8df94e0e16680cfe20d4c017179f43ad7ba5331db7d5c0154f","tests/wasm/struct_vecs.rs":"1b8b2de6ed50a4f04b11a002f0444419ace7419bf4441993537d2f16f89ee790","tests/wasm/structural.js":"ac504a1dbb7222c70270530a284eec56ace0bc47b95e8f9331f4b2df1d28c3f9","tests/wasm/structural.rs":"dda0e9cea09b94dd84ae39d6cf0949aa305062b7a466fdcb53370f5ee9e3dff5","tests/wasm/truthy_falsy.rs":"26ef766eb5c3dcc7f507c519b6ac4a37b3ad901f3ed6f5274307c12e549b5fec","tests/wasm/usize.js":"521714b75033d9e18117de2cae2cd690c477faa88daefbbc82a09e60f4e901a8","tests/wasm/usize.rs":"b97455844d1f7acfbae7fcc69ec0bd8de871201281e802173a62574b8f3d7983","tests/wasm/validate_prt.js":"a726a85f4805648d9e69c804a266bbedaed942228a1b3a46274a91bcb83eafe9","tests/wasm/validate_prt.rs":"cea3db07f10d2bf057af99b90655179371bccf1db67e7364d476b00ecbf24a93","tests/wasm/variadic.js":"30d3bb656c0eb29b69c7e653f3201b5210b8a78e962b4678336c4d9889182adb","tests/wasm/variadic.rs":"1cabd34ad64475cc705853a2b9a8f619f6aed6ee3f3d8179793f8198df1ac178","tests/wasm/vendor_prefix.js":"1424c7fea77fea13179a50030afeffdf4b277dcb6d7b1e5ce3eea681ec2c47f4","tests/wasm/vendor_prefix.rs":"eabd627e14e09ec637d7e7a5b0bccced7e3370203351e4ce8610a5c66fac502b","tests/worker/dedicated.rs":"c0bc877a84c71724b69391792e6403ab72240243039d1301caf5116a0aaa5d17","tests/worker/modules.js":"a407c81d2670309ed484adf98a2e522f6ea031b1286416eb7bf184df7433d5da","tests/worker/modules.rs":"7eeb46835d911868842a3e7434fc2c6d0e042943eb10e7ad76336065cdf18db7","tests/worker/service.rs":"2b64943e9ca5abf91e92c5d1399dca4b628b860eed9806d4443ab3c74dcc593b","tests/worker/shared.rs":"32a492d4dd089341a3737181c632efe650fb64b53c9317d8d6be742005133ff5"},"package":"4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"} \ No newline at end of file +{"files":{".cargo/config":"9b44eb089106a9088a9b6c483f4d59829a3b5b74975c805e18272d829a2b5e55",".cargo_vcs_info.json":"869ac2ca1f2f1d1be857af2ac3926513bf2272f9418eca54844f119a8bd56f95",".github/actions/setup-geckodriver/action.yml":"a6a8c001a328504b4aeb33aceff8840eb629d4897d6b9bd2643a7809bcdc30cf",".github/actions/setup-geckodriver/main.js":"f184dc857b9ab2872818776fb5c8f8d33bb38ae14b0a91035e8ba8a838d319f8",".github/workflows/main.yml":"eecdd50c68fbc30f7e3ce4994e5f1c1f86ab3223af08136d5313288157e61033","CHANGELOG.md":"3aeb51357b665c9dcdf3ba9a9e54bc1888e17cef435b287fcbc37987aa861c0f","CONTRIBUTING.md":"aa138d76f5cb25bba1a6942a230373aaed6be73c619f945cc4657e13ba69f897","Cargo.toml":"30dc8c10c522df2360aa9c8811299da71c612f0069d943339ae8357ade9ebef2","Cargo.toml.orig":"feeca96f0778788ecf8e9738bd9f048f253705408accf3c489e5109a63f9e765","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"36a2db1bda9f5fc21d8d6ed8d34a13fb049a1db642129d0d1af269634a068a33","_package.json":"7a84fbc7f68f390315d93d2d808d5b27344644eb5df59a51bbe7a854d2a6231a","build.rs":"95d57e593c411b82bf88819765d6422db2a65c1bf489b63f87e0aefeb721fc41","examples/.gitignore":"ff0812e01a86e4a8d9f4f2bd85e5a9a296e8fee0e656cac921f64f20bd72bb0b","examples/README.md":"e5396e95d8130948e48b767ab505c46bc69f6ff3ebfe0d9709068cf42c250818","examples/import_js/README.md":"bb53d4a264e9a084effdc7a22ca7d5acca0207b411478b98782d881b7fcade51","examples/import_js/index.html":"f4825d155bfe0059aa182a506d6d076d1ba5f118e46365ac902b12f27a6c8c0d","examples/import_js/index.js":"d425b7b0636dc5c5046bc96e6bfe6ef3bb1503fa91c54f40ecb457a1b060ee5c","examples/import_js/package.json":"f65f4a456da892c99cf3a5c961283e4d39780a56be5b6ae5fb2bbc9f235fdaae","examples/import_js/webpack.config.js":"fc314556d2f0c6266cde7c47afaceebe474be97c0401985a23d822ad9dd0105a","guide/.gitignore":"3c4dbff9eeda9410a0b9eb423472981db8997d666388b4cd2424700c3974d64b","guide/book.toml":"d8cae5ae5fbeaab5b6852c64b975d37f51592a8e9eedba22c898672d9b11e9be","guide/src/SUMMARY.md":"3cd53341dc5e6246e77dcb3f71a69091c25c847fbd74302ba9a5536284dfc6ec","guide/src/_headers":"401cee68df5967f0aa509a1b978a83f06e8e830deca1433964703e7a1ac2c646","guide/src/contributing/design/describe.md":"3186f9795be894708788e50d2ee745b9bd73bc94fb3dce67f3f1fd5e7fbd3659","guide/src/contributing/design/exporting-rust-struct.md":"2ead6b67f241bab543bb96c80e90b63abd67822a7c94190d2f2d1c9809a59b87","guide/src/contributing/design/exporting-rust.md":"ad88a5e0fccafe6c27e5a8bd951cf3e2fee1846da77a665f255999d9dd5961a6","guide/src/contributing/design/importing-js-struct.md":"848d0b144b28a5ae1ca3760438e71b938cfb2ee350f5b902fd08c38a0a64e27b","guide/src/contributing/design/importing-js.md":"c949c8921c213ba21b08f705d4611304acba47b68c35484fe968a80194f3a9ab","guide/src/contributing/design/index.md":"bf99c93e3925eee343f0c8fa59f9f0018fe04a0004867738c4234a895f399af9","guide/src/contributing/design/js-objects-in-rust.md":"0a18922b509ed8a6cc6724b81af6e6d469b75b3796dba770949a8b59d8067455","guide/src/contributing/design/rust-type-conversions.md":"3eb1b6b5b6b138d5f39148612ede378fc73137b32458a8c17c6d4b1cf9e8b7e4","guide/src/contributing/index.md":"d02b4f2f238b9fdb62fbc09bef3f0e9fc0ccb3f8cf977d0f2c6ebc1ec2634e42","guide/src/contributing/js-sys/adding-more-apis.md":"d6626d530fa5b73f045a20bf123d5e261ac2ca3bd64cbb80b655612f9b9a6276","guide/src/contributing/js-sys/index.md":"9c0864ca52e8699148e789c2a6ba2d3044ba2358d7106a1b7fd725d3720dbb54","guide/src/contributing/js-sys/testing.md":"d1f613c88793ffce61b2d77aa40e3a91a1de3c73ab9f8eaedfc39da16c93ad07","guide/src/contributing/publishing.md":"7aaeaab68e4173712b346b02444e31de983326c8871ecac0f42a5552647f65eb","guide/src/contributing/team.md":"a3f993cb1afeee767e85077d135b1ea08850c433a69c436ebe6b7a48124ed945","guide/src/contributing/testing.md":"c3c720acfea72768117fbc2b95181b48caae1eaae1e3660d44ac5cb883d9e259","guide/src/contributing/web-sys/index.md":"6b4d5e00cbbcaab29295a3bd60e90b7f72b118758966622a307d9222488707c1","guide/src/contributing/web-sys/logging.md":"ee960ec9adc174183fb349acdbf5fc647b6f9a290022be9b118b9de37b8b5687","guide/src/contributing/web-sys/overview.md":"e6179317f75aa8e836e3c803f5d814e87119763709eea47b04cebc86c089d80a","guide/src/contributing/web-sys/supporting-more-web-apis.md":"a3817d09c6cdc3cb28a1b77cdad5e4436ab5bc37f9d681b1e495815ca91de85a","guide/src/contributing/web-sys/testing.md":"77f8e4b45bd0e27676dd503474bc32f91672b23c6ab7127a4f5b828dc8ea40e4","guide/src/examples/2d-canvas.md":"44a0eb82ec3398ee63a6df5aab103f1b002082eac2d129f656d8519cbc0829e7","guide/src/examples/2d-canvas.png":"b202cd79b20c00d49c40d71225eefea99306015858a432ceb7592d53c15300f7","guide/src/examples/add.md":"8dac740d6a4c499d868c29d8426d113da9cdd6ef22bf8084b8cf8c1de513b09c","guide/src/examples/char.md":"93f94a1b670322d0dc21b46d749909c414f9f254e2dd97afd8afe8cb0e5ab908","guide/src/examples/closures.md":"669dfc47a670271d7ce7a3bd2c08620b698b01ea8b2a7b1cc2047a77e7617130","guide/src/examples/console-log.md":"6552f4d766291cddc0eade75e4f64de9f10e00b89a0bedb1b15dcf7baa90b6e0","guide/src/examples/dom.md":"44ad74370b3727ec98f958273c639e767f2ae5b75e96ef53e74be1833a630272","guide/src/examples/fetch.md":"0f9d08e240bc5ced13ab154182aedef7fa7b00cba784c65727aa15be27f86d7c","guide/src/examples/hello-world.md":"d5f4d830c316a91e951cdaeab5cb23ae47dbc910b05de849e67bef1ea709564f","guide/src/examples/import-js.md":"0480a6aa32b1fdc1347cb3d0c4f2a006caeb33c75ed21eb78ad800f012cbc2c6","guide/src/examples/index.md":"4e629f42d7bfb52bc35856b6e21c3aa7433563482697212d7b54f1bf619b56ed","guide/src/examples/julia.md":"0cd4ae1de24d657d7869c984dec61cc8b796621365be633212bdb2a6d57ce727","guide/src/examples/paint.md":"06c6c04f121080e0e5600b4ad300df9e93b5d4b6342f42c421e6dec1f2955ced","guide/src/examples/performance.md":"de888713cf0a047bd4a28a1ca890be51d99b6aaabc9a2b134280b768a7148377","guide/src/examples/raytrace.md":"6769cf3b7bd14e9814e751927fde8c5acb443c5e82758285a1ee4f91e577a870","guide/src/examples/request-animation-frame.md":"26eef6b203acc0b2667d9c4380c39a44eb4b97991efeded9ca32cc9ab454e993","guide/src/examples/synchronous-instantiation.md":"c2f887e4754535c453d22438c3179d71d2468d8994a61330a362132c73157ef1","guide/src/examples/todomvc.md":"b872c5631eae969368d147342fca16dadb6f0412f8922230c27271370e9d3d97","guide/src/examples/wasm-audio-worklet.md":"a2f390bef5f69365da496ddfe8995520cf8441770a6026037b1882fcd4d5ea34","guide/src/examples/wasm-in-wasm.md":"5439a690e7107736e6f8b92e475f0a45e83ab9a1e5a0fe02e8f6dd93372590c6","guide/src/examples/wasm-in-web-worker.md":"b05c2285be7802251ac71ae7e4a91ddf52ab286336308a6328f4b143cd5811c4","guide/src/examples/wasm2js.md":"48f953dfa1b17b68e5d983231e991797e32e9bc22b9c3db72c2d055e08449a00","guide/src/examples/weather_report.md":"0b6778aa7f44c0bb0ba18daaf7623cfe1776b133611a6cf136935d82ef388db1","guide/src/examples/web-audio.md":"32bb18c9e4f167614ce3fb61d1d04265449f88da40949834b50baf9e37063fbd","guide/src/examples/webgl.md":"15570a0a081c2301981a1fbca0bd39dfcf35221c64ddfb8e8f4477660658cb08","guide/src/examples/webrtc_datachannel.md":"47b06b1b00c41f048fad3c2206399cae2d8dbd90b6d83953c138826f11677eb5","guide/src/examples/websockets.md":"704f9d5c1d13426e6e64e132cb0204be3c10a54dbfa5f1c834adc4efb4a1b8d2","guide/src/examples/without-a-bundler.md":"ecebd50a1d4ab8e2996fb01188cbde0c49da096a1c25027da68b97371c025540","guide/src/introduction.md":"981c2c4d0224cdc4ad71d70f85c6dbd9b2194c174f24c5e9d52d74c0f49613b4","guide/src/reference/accessing-properties-of-untyped-js-values.md":"a91e3eb706ddd15628072978906e2faca31560de616c0630316d9f6eff6b55bf","guide/src/reference/arbitrary-data-with-serde.md":"b281146412f6bda893f146e84721677f003cad57af941552c2faf534b61b2d98","guide/src/reference/attributes/index.md":"12b57ebbd0c9ba42d9f10d752c9943d9beec90d659d1b1ff9e9bfea02572a2c8","guide/src/reference/attributes/on-js-imports/catch.md":"da230e6986ca29f1e82313b82275ab9c3b2144906271cf82b27772541d781d84","guide/src/reference/attributes/on-js-imports/constructor.md":"89f8be11c567b4611c84209b34351238553d5360d7f7665ea25332e1544c5b99","guide/src/reference/attributes/on-js-imports/extends.md":"84ece37398ba0df66f890982315f082c52b5f027e03c20527755abe610c2567c","guide/src/reference/attributes/on-js-imports/final.md":"2599df0288dab5d57c70d6bb19b79d8bbd027e5e1435924127e01121ab60e20a","guide/src/reference/attributes/on-js-imports/getter-and-setter.md":"27f3c2738688a43e611524e5e3ab7174a1993026a69098b75780a388aeb5e745","guide/src/reference/attributes/on-js-imports/index.md":"2219a4514fe9597cbbe6c46014b57c38f1e85f3d0775a8a7880f50858cb13633","guide/src/reference/attributes/on-js-imports/indexing-getter-setter-deleter.md":"11d5c03f922294894fe0147fae96e04b26a5adb36ce91296e52729a9fe5931c2","guide/src/reference/attributes/on-js-imports/js_class.md":"d51c5f05b71bbf6b6ec8e0c36314ae299fd7eb07be989e721b79b599405b3486","guide/src/reference/attributes/on-js-imports/js_name.md":"12457466f3510256a51a78f52b09f7cb1c0b0ce3ef636e028cd2c372fa9e8738","guide/src/reference/attributes/on-js-imports/js_namespace.md":"acaccd162a982c1c17b659ce5daa1d5a0d184b9b07728fc5bb17a89f327ffafa","guide/src/reference/attributes/on-js-imports/method.md":"d54246efce5d7a104702439ba509bcc5bfbb0b57253edebdb696617daca80bcd","guide/src/reference/attributes/on-js-imports/module.md":"b47cd5ccbb69955f1d47101accc96fcd562abecbf7e34826f7f3c585d6b9dad0","guide/src/reference/attributes/on-js-imports/no_deref.md":"7d58bb3b6f768e38b949727abd1ee621ad09ebc537f83a8a20d0eeddf3771b95","guide/src/reference/attributes/on-js-imports/raw_module.md":"f363e5f3bc401b7e350eeec49cffde85dfb2346d597f38d98993fe5bfb9ff649","guide/src/reference/attributes/on-js-imports/static_method_of.md":"d5a5d9623ee55097f26e190b478e75f2e7d2ffc30e51ec647f39933d3d4e3b18","guide/src/reference/attributes/on-js-imports/structural.md":"364e01a5792029e9a5fa582375736efcee006352834ee273d218da89b77dd8bf","guide/src/reference/attributes/on-js-imports/typescript_type.md":"abdb26584e88bed32c4dc7b2d4ed2e3cb2007f1bbf73412fa87dec823db76b2a","guide/src/reference/attributes/on-js-imports/variadic.md":"1ecf00149be472e3111f188c053092f3274fb33453414516a305084d8e92c4df","guide/src/reference/attributes/on-js-imports/vendor_prefix.md":"47a8d47e0cd745cca697f6d944e145f02695ca422255c3d6e1c9b2b719994b1b","guide/src/reference/attributes/on-rust-exports/constructor.md":"8708873e656827869b6708be1997f9212ee801b997b6f223c5a2af09ab7eedae","guide/src/reference/attributes/on-rust-exports/getter-and-setter.md":"464a2d41a791bd8ba5a8b1c4aa64b2f865c42b98a2d1289bb65e766e98a1b56a","guide/src/reference/attributes/on-rust-exports/getter_with_clone.md":"11a04dba4d66c19be0e234014d21ccf9cd0b76169b723e90ceb81d719478f283","guide/src/reference/attributes/on-rust-exports/index.md":"9fe778a0dd013a874db484cb22b1d9867bfe6d69cfbbe5cfeaa8ab78cf19daab","guide/src/reference/attributes/on-rust-exports/inspectable.md":"52fbcfdb83c426430a95692d566a4709255e25b24be5704d7378a4196a8c5908","guide/src/reference/attributes/on-rust-exports/js_class.md":"f4c0d8e8021001578f7d300e88c438d1a7806c17cc0d8acc3b4134922a75affc","guide/src/reference/attributes/on-rust-exports/js_name.md":"77f035b6391b9e44f254a411ba18687c5fa6110e276be73b5ea347701c8dad42","guide/src/reference/attributes/on-rust-exports/main.md":"d1a42470fb0457b3471e96ba22ca270c1cfc9d5fa781240a9d8b1aef32641ff8","guide/src/reference/attributes/on-rust-exports/readonly.md":"a5da847ad36557f03b1c79a83d14c219dce914021266133c204260bc041b9b89","guide/src/reference/attributes/on-rust-exports/skip.md":"b9972241b8d473d1a46ef3c2861065ca296cdc923883c404f19f1d859bf914a6","guide/src/reference/attributes/on-rust-exports/skip_jsdoc.md":"6c400bb6dac1083449758448e5e7a576d40f371592cd597ea95ec441fefe19f8","guide/src/reference/attributes/on-rust-exports/skip_typescript.md":"1622c29b0d93a884bd0b5b2a62107a594e2919758c80592566e7786efe788b89","guide/src/reference/attributes/on-rust-exports/start.md":"dda9cfebb7cceac4b7b4868f82a9e12d3d33215f4f59d1ef40eacf2c33d90933","guide/src/reference/attributes/on-rust-exports/typescript_custom_section.md":"6dd69f15b6f6f632880b7a65cc49abe8f4f95fdead753c576d81a3268dae4985","guide/src/reference/browser-support.md":"177fff4ee6a68c85f045cec47bc7aa40de66fc95f8cb59128e8ef2d6972dbd7b","guide/src/reference/cli.md":"572d8312a88403a0e0f0ca8744037da6fa8f73f2adddd57243f789972deaa452","guide/src/reference/deployment.md":"1954466cd2ac6c5326258364f6390b10cee9c2729e7c2779f2a50f950c7c9523","guide/src/reference/index.md":"c603c3a7f265afb7c7b5eb391b32f6115f8842f3f422fd3730be4f90c4796bc4","guide/src/reference/iterating-over-js-values.md":"ec00f09516eb7de98bf7296f44b6aa9ceee3fae1dcdb7cdf8f36963d45b7ebeb","guide/src/reference/js-promises-and-rust-futures.md":"5f0c0b990f5b55c8d9485f7cc66a617f79cc232705562f306af97785c7ed1f79","guide/src/reference/js-snippets.md":"dff5adcbf66f06322e606c672ef070c2a0375f1ae592ca8a9da36a50324735cc","guide/src/reference/optimize-size.md":"c10abc1ea0902c9a57b74808bcf75bf092c0c2bb4082962b85d18df7593602c1","guide/src/reference/passing-rust-closures-to-js.md":"ce75e529a42f47e74f9d96085a93871879667af3e300c8ddedd9879960d2c36f","guide/src/reference/receiving-js-closures-in-rust.md":"fc9c80ba5e1a5f243a66f68caba27e8103652aeac3765a9fad2d0e16113fede3","guide/src/reference/reference-types.md":"91d178b7fe2ec82eec4d8926a08b39ac16898172d6f65aee84347c6918033c67","guide/src/reference/rust-targets.md":"467d5cf7eaa1d4b89f9f5b2248cdd1a10340ca1db263ffff5c483ce10dcfbf54","guide/src/reference/static-js-objects.md":"930288fc463d16a46a6546f5f65af21ff6e4b94259d9a1e8bca9d660f9770604","guide/src/reference/types.md":"859123f51fa932fa37d7e47cd5c46956929793bd3accea050d3be516080ed78f","guide/src/reference/types/bool.md":"e954d93ec5096837d4dd2db3f23e71c14483279e347ca8908ecb49aded6e497a","guide/src/reference/types/boxed-number-slices.md":"1a217a68ff549f4208f99863d6616521c9d466542c1156bcc2be7d3a73e4edd4","guide/src/reference/types/boxed-slices.md":"f244161c0897d38d5100f32e94bc5b87dbc8277d831536d29d6214d3d0bdf7a8","guide/src/reference/types/char.md":"01f2f7bdb25a9a52edd93dcbbca6a29269a8d5adf6cb94dcadea29a7aace22f4","guide/src/reference/types/exported-rust-types.md":"d2f601d7d39ae92326c5624e1e2a2795f1f47accb92ec030c987b6c709681906","guide/src/reference/types/imported-js-types.md":"c82dba871a26afb7b90ceec59892adfec9bec550665a74d190a4fda639f61d5d","guide/src/reference/types/jsvalue.md":"46d74da47f8a517249de4dd096351c10d658d9c3535950a34c1fc5d5b42eb2f7","guide/src/reference/types/non-null.md":"a79c6f6df2fc81cf7f596815d6cc6d1b0f3a49944ca3e08d2b5e6bcdaf837cc9","guide/src/reference/types/number-slices.md":"f380258fc058527c7dd6f49664a4e9dff69f0b03d626071aeb61efefb2a0b646","guide/src/reference/types/numbers.md":"cce95c07be08c1f16327fd4c7e79b7c480db9cc95e2b07514d31e51bd6122101","guide/src/reference/types/pointers.md":"c2f5b7bac9b49a8e91facd5597fa1df0a6b4c5319627c8022232c21ae9f86755","guide/src/reference/types/result.md":"78be87e86c35d2bbc1b863217c1a7592af9f2c699902f44e22d1bc4b1c0664c0","guide/src/reference/types/str.md":"6cc086b02ae3d3565678e69d91dbf105f1f310009097a37fad4c812e25d4b7c0","guide/src/reference/types/string.md":"9e42298135e0aec11bb924e3a2b5002335cfe290240b48db12dc981156177cd0","guide/src/reference/weak-references.md":"1686a057fc28672d7281af3678688f804adc113fa307fb4229a479d0600ee93c","guide/src/reference/working-with-duck-typed-interfaces.md":"a23f1f98019fed2060e1fbce954ec457e77a3a17524f34ca861d256d2ad4b6ef","guide/src/wasm-bindgen-test/asynchronous-tests.md":"c24c381b719b4bd7b0c181da1db59170e822c142eb22f95c4a6eeb8fd36df3ab","guide/src/wasm-bindgen-test/browsers.md":"84a862202b6b326cb60eb54f032d8d398fbde82c297b750cfa58bf75afedb066","guide/src/wasm-bindgen-test/continuous-integration.md":"5865990ef231b3c99a9c1bc18f7b7f054a29b77ac7b671fcf1cd6bb4f4304ae8","guide/src/wasm-bindgen-test/index.md":"64fbcd222c3c597109d2717a3574abf2041ff325c26ee07d58c4cd7ba1c1f8ad","guide/src/wasm-bindgen-test/usage.md":"a1da64eaaf8fe9bea366724e08a4ba63dc984f86a28cc393fe00dc394ab244d6","guide/src/web-sys/cargo-features.md":"0e50067a7a46cee3d1b21a2690aabc539379cb1452de377ebaa0eaa4e5e587b2","guide/src/web-sys/function-overloads.md":"90a08bb955f7c79e573f83c31d5e7431ae1e3ad7001792ff8ff52e4299364fcd","guide/src/web-sys/index.md":"345499d0840fd23a2e5eb5ac497665decbb3f836fe9f4f88301ae4b5fbd8d44f","guide/src/web-sys/inheritance.md":"8f18af20b930497e2fae4a266dd27e317d1ea3510266c21b32f351354b495ff2","guide/src/web-sys/type-translations.md":"687ef5e4a3961fddcb94d24f69abec0ea64f6df306f4593974b69589215980b1","guide/src/web-sys/unstable-apis.md":"e74c3e72136d6906dd60258a27f34e1ea4612e7c8e95662596475dc557151cfb","guide/src/web-sys/using-web-sys.md":"523e16af6e27703a4a0582568bc97710350222af20801907268d2d8c197fb667","publish.rs":"6352715cf06a9e373a141e34991fa97ec5bdeb0ce7d623a4fbbe9448ef1bea35","releases/friends.sh":"f896ccdcb8445d29ed6dd0d9a360f94d4f33af2f1cc9965e7bb38b156c45949d","releases/release-announcement-template.md":"fcb3c75cdb8d5d6ce8a198f5570c967313f751d1eef0790b34a518772b2e8a38","src/cache/intern.rs":"b78abd7502ad069bbeb61073d1972c717a469849222037565b50514192c187a9","src/cache/mod.rs":"8989143b55160dbc142cb20c6e066cf0a3f70d6c97fbc9aa0fac59bd62bd865b","src/cast.rs":"da53f21aa485c0dae184350d2693ab41e3fc7a34fa300c19ad718f2b7fc2d42b","src/closure.rs":"14abb62c4f4ec073531ed2f6baf9de2e40f13d527d4331da5bf5fd896682257c","src/convert/closures.rs":"51479d4012c18a886653590514290a121893837777e8ab7cc104d3e883129e9d","src/convert/impls.rs":"defe584fff1fe6ad668109d6b1155199f253ae827899ce582415d5b5d6c542e8","src/convert/mod.rs":"566ffd1f546afdb8d24c6c0d6faa00a28596a67ca6f2f39e9485add54400443c","src/convert/slices.rs":"e6cf79787d0031267051da6f03ccb1c1ea1f18952c5458f00d720381daec6725","src/convert/traits.rs":"ccee20adf821982f57a55b9958109a348dcc911ce2d81979328734071430037e","src/describe.rs":"9993bd16b9aa8bfd8d15fc92604f58c7f67e080449dab3c9c2e4c4904b3776af","src/externref.rs":"199a2a31d31bea3b15002ce8075148a91d49ffc71fead08039b5c4f2ab0d2562","src/lib.rs":"3ae23196694cbb6ba3b23971b95fa9fc360c984e4389fe35e61bf6c01951a620","tests/headless/externref_heap_live_count.rs":"41b2758762c91bd2d05995b1b8989651a6bf2e586ffad5597ff63f6d2dc6d755","tests/headless/main.js":"6de0a19b91330e9bc68334c4f1fa11c1cd6bf273f5ea3e470933ad800c962679","tests/headless/main.rs":"d86245fdd476cb6c275c0649d76fd348ab55b7952ece325c1ed4ec00051a1f73","tests/headless/modules.js":"a407c81d2670309ed484adf98a2e522f6ea031b1286416eb7bf184df7433d5da","tests/headless/modules.rs":"74f77f88bb5280862c06087d78c48ba930736e58db9a1e6c80450bb0e032b789","tests/headless/snippets.rs":"baf9d3c68e1b567fcba4e073cc0d24a8f039955e10dd1275e4a389574ff556d7","tests/headless/snippets1.js":"8bd0c367fdbc61f509728255750094bb36200a1aea74079611ad7cfa9c5f3f28","tests/headless/strings.js":"fca2d7a1afae31663607f956134a4f447aaee0f85d828addc3c4c1440f2e18e5","tests/headless/strings.rs":"4a64d8a4f9329a282d0f87408c0645ded71a7d023eaad40a32eaf60886a08375","tests/must_use.rs":"cae67a8740cd2c969a6b33316cd5036639048d9bbfecf55a5f45faaa624de1d0","tests/non_wasm.rs":"d2cca0b81824ac392f55b8d583d2f361ac11bed892968113e33fb3148572b853","tests/std-crate-no-std-dep.rs":"47f0e32bad7b9b11ca77d66d904eb3408c3528732899479039fb6db4c6e9ed9e","tests/unwrap_throw.rs":"79f05fa37249cea08689592d53d856019a90fd1b72c41413f7fcda5cf5913356","tests/wasm/api.js":"daf4b7e2b76b718431235eda5e221dd53037fb6bebbec6023c7e3fd2b806f763","tests/wasm/api.rs":"12219ffafbb57ba8ed315c56f5e18de412df84757e002ae11cb9d2beec13b0e3","tests/wasm/arg_names.js":"0d7de3801257e18756a974bdd2950d2fb06755f7c0d1c681e03b56d97e828e34","tests/wasm/arg_names.rs":"decd8f71a58ebf662a586b7f19e41f6666782df0da74a8a2c69b7a504661dd79","tests/wasm/bigint.js":"b6d045afbbb7d5e8723b41ee2e9c22357c8c4c4aed804bbca2a9b42a19906354","tests/wasm/bigint.rs":"5a7e0e6e6753a5ce08c199334fd89f1cfeabc1305301d988d6f748e001ccfa2c","tests/wasm/char.js":"de540498439728ed74324f526885b4098cdedf0d6b105217cc3ff6abbd77207c","tests/wasm/char.rs":"c43692b5b5d754564355a2715a6a2c88184e0475f2391baf3f9053793b3a0ab5","tests/wasm/classes.js":"aaf4c1300a5e14a06931463a01bbce3c3acfa57de225707f142199e133f03bd7","tests/wasm/classes.rs":"857355b1ab17ad2ec51d6dd3f1b3ceb837601cfb7c36d7a262d2f92681605a60","tests/wasm/closures.js":"6df2da8bad116c9ef244f35f4f14d1fd432e6faf43df30882c6464a521cc606c","tests/wasm/closures.rs":"8e8216f319b9dd3ee2fc83607c62850296a9f0db5a6dc2fb36a87dbb9b170307","tests/wasm/comments.js":"2c3bf2e79ecc33f0fba33d13a91a1ae9390f9f7a466af8eb215636662e20462a","tests/wasm/comments.rs":"5a0068fe3e214c07da92a46b6e45a2771fbd8e04f14cb7802f32082b87a459a0","tests/wasm/duplicate_deps.js":"2226e4f65525c545ab45109879b16b2a92341b440178e75d3a9efb3ed10f7b03","tests/wasm/duplicate_deps.rs":"3a91569e54f56e178dc164f2d2b8537ec6a10b3161c23e1cc8e552805cd868f4","tests/wasm/duplicates.rs":"a2b4a7960e8a7c9b3fda943e8aadb7cbc0ba8fa1a6956baf40ba2f129bd591ee","tests/wasm/duplicates_a.js":"d3d685e95a54b911c2b9a64f7c0f245e3e492491368355044ae2cd12c3332044","tests/wasm/duplicates_b.js":"cd6c87905a5c5514239bba52a03e6c151d79a57a477f52a073b61ef18c98f642","tests/wasm/duplicates_c.js":"93399409996d182b5fe02548d3c5c3e1681939629e0261d6f19f8c1ee3b08dfc","tests/wasm/enum_vecs.js":"28426c3d99ac369d3e87d7ccd177af677bb8bc3d701a152b5f271fc88952bf96","tests/wasm/enum_vecs.rs":"ae3c4c062b63a08481bb1426ba8146e03d9f5d60cc5298880081bbba5ad650bd","tests/wasm/enums.js":"a9277bc042a208b545641f43d9354f7b3ce0e2240d8f9f0af9016bad6a5d5bab","tests/wasm/enums.rs":"c35c6658ec377182c819554108e6e01813323c9258d069fe4c962aec6a1c35c7","tests/wasm/final.js":"cfa7c496291f08b98f0406190ee4deaab9ade890d65ada4c223a76135e66f619","tests/wasm/final.rs":"25b0a85e87686e3f7a7a44e3ac25402d504eec7f9813a74ffd63c5f4428ee0ff","tests/wasm/futures.js":"175745daafcaed4cc0233809f4829228528c87030459645e8493b013cd3e9f98","tests/wasm/futures.rs":"24af063658319fc76d89a30a9582e885465dfde520c6eae34eb5b8b668aa05cc","tests/wasm/getters_and_setters.js":"8ba2d939aab232074860cdf1e01d1c58faee49a31ef35b585c962aceccb870a5","tests/wasm/getters_and_setters.rs":"0dc0e87014ce7e17970883b2e579b921a99a3c9115d67ed781e015f5f27c0ca3","tests/wasm/ignore.rs":"e0b02bab0f015ab1378b33e008129098dbc28bae4a4c443ef9def29e6646f647","tests/wasm/import_class.js":"d1bd1dc7df5bfde686bea6fbcd32db6009b6853712cafb446af263fdebb1fb78","tests/wasm/import_class.rs":"0678cb9272a28f818a54f182e8f229235f6bc79e220738dbf68561bc19d7e0de","tests/wasm/imports.js":"4069b7cf12ae0cca30a1e92750d0715e782a5c795ff21c0d5aae738f726ae8b1","tests/wasm/imports.rs":"56cb87c812c1fb3f6573ca166caa483e97380433d10b1c86fc1237a191630fe1","tests/wasm/imports_2.js":"ab251fc0a0a1921c60d316160bc120fd97da3c3753804174cfda2f08ff43208d","tests/wasm/intrinsics.rs":"1eac40553375d1e5250a9242df19837d1b448296d53ceb41f842c80996e958e9","tests/wasm/js_keywords.js":"d247be675cc73540fea4b2e50bb2b7fcedb2b0d511d85be6fb646876d3025562","tests/wasm/js_keywords.rs":"6944d856346b528c321ac24b1f986e4858d22b37f8f24ad0d393fe7c4ac079d7","tests/wasm/js_objects.js":"a2be00dab58716e4cbbaeba4da8512ba924c39d3f1cb405ba769ab8a780ed7fc","tests/wasm/js_objects.rs":"86f77308ffacc9337d21f62671ce269e723468a53404d0679da43e5e95c90135","tests/wasm/jscast.js":"d678058645d2d370c45ec5fd5bc9b94612b1e70035a9e0f524c134369f06fe1d","tests/wasm/jscast.rs":"bd9041fd4f74cd69435f4d4be019a887d680d7fac86134e42954e94d7c1c5cab","tests/wasm/link_to.js":"b371f4c82da171ce5a3e21a6de172cd1c910a4ff26e021d1a7ede5bfd7829c40","tests/wasm/link_to.rs":"1cbc53a58cf0fb693a8e775c94e3cbebc68f2355d98f4ce972abc42ffd62d014","tests/wasm/linked_module.js":"412bcf020b68e7e5511f4def869cc3384c1e98b923a9b82e25748b40b5b6e640","tests/wasm/macro_rules.rs":"6a8cf079f72aef96a004d559f5a06214ce8b096a3675a5c61c9794aa14448640","tests/wasm/main.rs":"cd81eb4bf0ff84e2b27963ccfee0550e26c96d3e7e1c1342e18c9b17fe6d28a9","tests/wasm/math.js":"9deb196ab7ad3d5d1f98d7d0b6ee60cb125212a4a1281ba0141cc3713fdea892","tests/wasm/math.rs":"be9000d84c6b6b091455e3b20ee7f5a88dbcfc0d38db97fad3dd167970c4b4a3","tests/wasm/no_shims.rs":"6c44ce90e1fcb8d41a7c2d369ce7a2735ba5ce799dcf07b41cbc3ccaa2f27a6a","tests/wasm/node.js":"6ae82d7f07a35b260e085158b080fb7d2c2c40865f579cc7c8688de090f8fa61","tests/wasm/node.rs":"e8b6448045682729bf359f1a70bdb24af57129a554ae2e2dcea1beb0b1715e65","tests/wasm/option.js":"0d0cba722045698e9621f2565acf854bf3085c8739622798085aaa6b58e3edbe","tests/wasm/option.rs":"d82123f7349e22873e636341a52e99e256213e77d4d7ab8450ba6379be2128b7","tests/wasm/optional_primitives.js":"37484639631e1c50bdc055a08babff18d4be9f7a9291f0f3395e1a7c519e5cac","tests/wasm/optional_primitives.rs":"502803cf27b78dd8a6c1d75ae954b71cc017f803486867a87c0474e5d53a6567","tests/wasm/owned.js":"645b47e87fe52e08fbc07951736ab29f4dbab20c051913dba6228b2a08bad0bd","tests/wasm/owned.rs":"99af8eb8c30485b028f37d24352e2db747a425a00ebfed29e02400d87c756f32","tests/wasm/result.js":"78212259f886d864885eca7599199434bd7abec915a2e7fa3b73dfe63284e15c","tests/wasm/result.rs":"a4a4486d3edb6e242d32a9f12916a6cb5d38e07f646f69969ece6838a351448c","tests/wasm/result_jserror.js":"3ea04e68937f15d869535b3bb119d8886dfcde3c16c12c4a18a995f358552154","tests/wasm/result_jserror.rs":"ae4cbd3362841d070722f99fa0dadaf3233661803c73c65a9e63746b58a72134","tests/wasm/rethrow.js":"0a495a8d1b735277e18cc3fc3edf8bd2a72586441d3884134182e5052786ab84","tests/wasm/rethrow.rs":"59dcf192c9e85b0d98031c135d2aa2eda4902a2bc5b740a9ddf1e75dc9cdd23e","tests/wasm/should_panic.rs":"234929575bc55d9181d49938518888cb273bd5f3b1c9f826f94ee8956f1f5584","tests/wasm/simple.js":"10d1d531a6ecf91c1cb0457e8b2d6b43d00555a5f532a903da046fe10417fdc7","tests/wasm/simple.rs":"644ff8a67c3b17c511c7b488831f2e4dd274c1a0784e780dfb560b52552f992e","tests/wasm/slice.js":"f81dafe018089de221b523ef32d56044b9635421aa1f896342a7635d4fbce4f3","tests/wasm/slice.rs":"ea6447e6bcfd41622ec0cda927e86609067c2e0e3049217a7f1985e96c90d99d","tests/wasm/string_vecs.js":"4e422ed793de1bfbc7c9c538f3c10150b625279aff51bd2af92ebd7914130d88","tests/wasm/string_vecs.rs":"1f113573c6f4b5d50a66f34eafa7cc6ccdce042e86ed6efc353c094619ea1561","tests/wasm/struct_vecs.js":"dfc0a5109132ab8df94e0e16680cfe20d4c017179f43ad7ba5331db7d5c0154f","tests/wasm/struct_vecs.rs":"1b8b2de6ed50a4f04b11a002f0444419ace7419bf4441993537d2f16f89ee790","tests/wasm/structural.js":"ac504a1dbb7222c70270530a284eec56ace0bc47b95e8f9331f4b2df1d28c3f9","tests/wasm/structural.rs":"dda0e9cea09b94dd84ae39d6cf0949aa305062b7a466fdcb53370f5ee9e3dff5","tests/wasm/truthy_falsy.rs":"26ef766eb5c3dcc7f507c519b6ac4a37b3ad901f3ed6f5274307c12e549b5fec","tests/wasm/usize.js":"521714b75033d9e18117de2cae2cd690c477faa88daefbbc82a09e60f4e901a8","tests/wasm/usize.rs":"b97455844d1f7acfbae7fcc69ec0bd8de871201281e802173a62574b8f3d7983","tests/wasm/validate_prt.js":"a726a85f4805648d9e69c804a266bbedaed942228a1b3a46274a91bcb83eafe9","tests/wasm/validate_prt.rs":"cea3db07f10d2bf057af99b90655179371bccf1db67e7364d476b00ecbf24a93","tests/wasm/variadic.js":"30d3bb656c0eb29b69c7e653f3201b5210b8a78e962b4678336c4d9889182adb","tests/wasm/variadic.rs":"1cabd34ad64475cc705853a2b9a8f619f6aed6ee3f3d8179793f8198df1ac178","tests/wasm/vendor_prefix.js":"1424c7fea77fea13179a50030afeffdf4b277dcb6d7b1e5ce3eea681ec2c47f4","tests/wasm/vendor_prefix.rs":"eabd627e14e09ec637d7e7a5b0bccced7e3370203351e4ce8610a5c66fac502b","tests/worker/dedicated.rs":"c0bc877a84c71724b69391792e6403ab72240243039d1301caf5116a0aaa5d17","tests/worker/modules.js":"a407c81d2670309ed484adf98a2e522f6ea031b1286416eb7bf184df7433d5da","tests/worker/modules.rs":"7eeb46835d911868842a3e7434fc2c6d0e042943eb10e7ad76336065cdf18db7","tests/worker/service.rs":"2b64943e9ca5abf91e92c5d1399dca4b628b860eed9806d4443ab3c74dcc593b","tests/worker/shared.rs":"32a492d4dd089341a3737181c632efe650fb64b53c9317d8d6be742005133ff5"},"package":"4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "2a4a4936238cf11e863353e410f453c94e21c7dd" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/action.yml clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/action.yml --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/action.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/action.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +name: 'Setup Geckodriver' +description: 'Setup Geckodriver' + +runs: + using: node20 + main: 'main.js' diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/main.js clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/main.js --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/main.js 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/actions/setup-geckodriver/main.js 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +const child_process = require('child_process'); +const fs = require('fs'); + +function set_env(name, val) { + fs.appendFileSync(process.env['GITHUB_ENV'], `${name}=${val}\n`) +} + +function fetch(url) { + child_process.execFileSync('curl', ['--retry', '5', '-LO', url]) +} + +const version = '0.24.0'; + +if (process.platform === 'win32') { + const file = `geckodriver-v${version}-win64.zip`; + fetch(`https://github.com/mozilla/geckodriver/releases/download/v${version}/${file}`); + child_process.execFileSync('unzip', [file]); + set_env("GECKODRIVER", process.cwd() + '/geckodriver.exe'); +} else { + const file = `geckodriver-v${version}-linux64.tar.gz`; + fetch(`https://github.com/mozilla/geckodriver/releases/download/v${version}/${file}`); + child_process.execFileSync('tar', ['xf', file]); + set_env("GECKODRIVER", process.cwd() + '/geckodriver'); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/.github/workflows/main.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,520 @@ +name: CI +on: + push: + branches: [main] + tags-ignore: [dev] + pull_request: + branches: [main] +defaults: + run: + shell: bash + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + # Check Code style quickly by running `rustfmt` over all code + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup component add rustfmt + - run: cargo fmt --all -- --check + + # Run `cargo check` over everything + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: cargo check --all + + # Run `cargo clippy` over everything + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-backend -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-cli -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-cli-support -- -D warnings + - run: cargo clippy --no-deps --all-features -p example-tests -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-externref-xform -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-futures -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p js-sys -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro-support -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-multi-value-xform -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-shared -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-test -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-test-macro -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-threads-xform -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p typescript-tests -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-wasm-conventions -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-wasm-interpreter -- -D warnings + - run: cargo clippy --no-deps --all-features -p wasm-bindgen-webidl -- -D warnings + - run: cargo clippy --no-deps --all-features -p webidl-tests -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p web-sys -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown --tests -- -D warnings + - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-benchmark -- -D warnings + - run: for i in examples/*/; do cd "$i"; cargo +stable clippy --no-deps --all-features --target wasm32-unknown-unknown -- -D warnings || exit 1; cd ../..; done + + test_wasm_bindgen: + name: "Run wasm-bindgen crate tests (unix)" + runs-on: ubuntu-latest + env: + WASM_BINDGEN_SPLIT_LINKED_MODULES: 1 + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - uses: ./.github/actions/setup-geckodriver + - run: cargo test --target wasm32-unknown-unknown + - run: cargo test --target wasm32-unknown-unknown --features serde-serialize + - run: cargo test --target wasm32-unknown-unknown --features enable-interning + - run: cargo test --target wasm32-unknown-unknown -p wasm-bindgen-futures + - run: cargo test --target wasm32-unknown-unknown --test wasm + env: + WASM_BINDGEN_NO_DEBUG: 1 + - run: cargo test --target wasm32-unknown-unknown + env: + WASM_BINDGEN_EXTERNREF: 1 + - run: cargo test --target wasm32-unknown-unknown + env: + WASM_BINDGEN_MULTI_VALUE: 1 + + test_threads: + name: "Run wasm-bindgen crate tests with multithreading enabled" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup default nightly-2024-02-06 + - run: rustup target add wasm32-unknown-unknown + - run: rustup component add rust-src + # Note: we only run the browser tests here, because wasm-bindgen doesn't support threading in Node yet. + - run: | + RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' \ + cargo test --target wasm32-unknown-unknown --test headless -Z build-std=std,panic_abort + + # I don't know why this is failing so comment this out for now, but ideally + # this would be figured out at some point and solved. + # test_wasm_bindgen_windows: + # name: "Run wasm-bindgen crate tests (Windows)" + # runs-on: windows-latest + # steps: + # - uses: actions/checkout@v4 + # - run: rustup update --no-self-update stable && rustup default stable + # - run: rustup target add wasm32-unknown-unknown + # - uses: actions/setup-node@v4 + # with: + # node-version: '20' + # - uses: ./.github/actions/setup-geckodriver + # - run: cargo test --target wasm32-unknown-unknown + # env: + # RUST_LOG: wasm_bindgen_test_runner + # GECKODRIVER_ARGS: --log trace + # - run: cargo test --target wasm32-unknown-unknown -p js-sys + # - run: cargo test --target wasm32-unknown-unknown -p webidl-tests + # env: + # WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1 + # - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features "Node Window Document" + + test_native: + name: Run native tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - run: cargo test + - run: cargo test -p wasm-bindgen-cli-support + - run: cargo test -p wasm-bindgen-cli + - run: cargo test -p wasm-bindgen-externref-xform + - run: cargo test -p wasm-bindgen-macro-support + - run: cargo test -p wasm-bindgen-multi-value-xform + - run: cargo test -p wasm-bindgen-wasm-interpreter + - run: cargo test -p wasm-bindgen-futures + - run: cargo test -p wasm-bindgen-shared + + test_web_sys: + name: "Run web-sys crate tests" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - uses: ./.github/actions/setup-geckodriver + - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown + - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Node + - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Element + - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Window + - run: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features + - run: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features + env: + RUSTFLAGS: --cfg=web_sys_unstable_apis + + check_web_sys: + name: "Verify that web-sys is compiled correctly" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: cd crates/web-sys && cargo run --release --package wasm-bindgen-webidl -- webidls src/features ./Cargo.toml + - run: git diff --exit-code + + test_js_sys: + name: "Run js-sys crate tests" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - uses: ./.github/actions/setup-geckodriver + - run: cargo test -p js-sys --target wasm32-unknown-unknown + - run: cargo test -p js-sys --target wasm32-unknown-unknown + env: + RUSTFLAGS: --cfg=js_sys_unstable_apis + + test_webidl: + name: "Run wasm-bindgen-webidl crate tests" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - run: cargo test -p wasm-bindgen-webidl + - run: cargo test -p webidl-tests --target wasm32-unknown-unknown + env: + WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1 + - run: cargo test -p webidl-tests --target wasm32-unknown-unknown + env: + RUSTFLAGS: --cfg=web_sys_unstable_apis + + test_typescript_output: + name: "Test TypeScript output of wasm-bindgen" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: actions/setup-node@v4 + with: + node-version: '20' + - run: cd crates/typescript-tests && ./run.sh + + test_deno: + name: "Build and test the deno example" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - uses: denoland/setup-deno@v1 + with: + deno-version: v1.x + - run: cd examples/deno && ./build.sh && deno run --allow-read test.ts + + test_ui: + name: Run UI compile-fail tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update 1.76.0 && rustup default 1.76.0 + - run: cargo test -p wasm-bindgen-macro + - run: cargo test -p wasm-bindgen-test-macro + + build_examples: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f + - run: | + curl -L https://github.com/WebAssembly/binaryen/releases/download/version_112/binaryen-version_112-x86_64-linux.tar.gz -sSf > binaryen-version_112-x86_64-linux.tar.gz + tar -xz -f binaryen-version_112-x86_64-linux.tar.gz binaryen-version_112/bin/wasm2js + echo "$PWD/binaryen-version_112/bin" >> $GITHUB_PATH + - run: | + cargo build -p wasm-bindgen-cli + ln -snf `pwd`/target/debug/wasm-bindgen $(dirname `which cargo`)/wasm-bindgen + - run: mv _package.json package.json && npm install && rm package.json + - run: | + for dir in `ls examples | grep -v README | grep -v raytrace | grep -v deno | grep -v wasm-audio-worklet`; do + (cd examples/$dir && + (npm run build -- --output-path ../../exbuild/$dir || + (./build.sh && mkdir -p ../../exbuild/$dir && cp -r ./* ../../exbuild/$dir && rm ../../exbuild/$dir/**/.gitignore)) + ) || exit 1; + done + env: + RUSTFLAGS: --cfg=web_sys_unstable_apis + - uses: actions/upload-artifact@v4 + with: + name: examples1 + path: exbuild + + build_nightly: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup default nightly-2024-02-06 + - run: rustup target add wasm32-unknown-unknown + - run: rustup component add rust-src + - run: | + for dir in raytrace-parallel wasm-audio-worklet; do + (cd examples/$dir && + ./build.sh && mkdir -p ../../exbuild/$dir && cp -r ./* ../../exbuild/$dir + ) || exit 1; + done + - uses: actions/upload-artifact@v4 + with: + name: examples2 + path: exbuild + + test_examples: + needs: + - build_examples + - build_nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: examples1 + path: exbuild + - uses: actions/download-artifact@v4 + with: + name: examples2 + path: exbuild + - run: rustup update --no-self-update stable && rustup default stable + - run: cargo test -p example-tests + env: + EXBUILD: ${{ github.workspace }}/exbuild + + build_benchmarks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add wasm32-unknown-unknown + - run: cargo build --manifest-path benchmarks/Cargo.toml --release --target wasm32-unknown-unknown + - run: cargo run -p wasm-bindgen-cli -- target/wasm32-unknown-unknown/release/wasm_bindgen_benchmark.wasm --out-dir benchmarks/pkg --target web + - uses: actions/upload-artifact@v4 + with: + name: benchmarks + path: benchmarks + + dist_linux_x86_64_musl: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add x86_64-unknown-linux-musl + - run: sudo apt update -y && sudo apt install musl-tools -y + - run: | + cargo build --manifest-path crates/cli/Cargo.toml --target x86_64-unknown-linux-musl --features vendored-openssl --release + strip -g target/x86_64-unknown-linux-musl/release/wasm-bindgen + strip -g target/x86_64-unknown-linux-musl/release/wasm-bindgen-test-runner + strip -g target/x86_64-unknown-linux-musl/release/wasm2es6js + - uses: actions/upload-artifact@v4 + with: + name: dist_linux_x86_64_musl + path: "target/x86_64-unknown-linux-musl/release/wasm*" + + dist_linux_aarch64_gnu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add aarch64-unknown-linux-gnu + - run: sudo apt update -y && sudo apt install gcc-aarch64-linux-gnu -y + - run: | + cargo build --manifest-path crates/cli/Cargo.toml --target aarch64-unknown-linux-gnu --features vendored-openssl --release + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc + - uses: actions/upload-artifact@v4 + with: + name: dist_linux_aarch64_gnu + path: "target/aarch64-unknown-linux-gnu/release/wasm*" + + dist_macos_x86_64: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: cargo build --manifest-path crates/cli/Cargo.toml --release + env: + MACOSX_DEPLOYMENT_TARGET: 10.7 + - uses: actions/upload-artifact@v4 + with: + name: dist_macos_x86_64 + path: "target/release/wasm*" + + dist_macos_aarch64: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add aarch64-apple-darwin + - run: | + cargo build --manifest-path crates/cli/Cargo.toml --target aarch64-apple-darwin --release + env: + MACOSX_DEPLOYMENT_TARGET: 10.7 + - uses: actions/upload-artifact@v4 + with: + name: dist_macos_aarch64 + path: "target/aarch64-apple-darwin/release/wasm*" + + dist_windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: cargo build --manifest-path crates/cli/Cargo.toml --release + env: + RUSTFLAGS: -Ctarget-feature=+crt-static + - uses: actions/upload-artifact@v4 + with: + name: dist_windows + path: "target/release/wasm*" + + doc_book: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.28/mdbook-v0.4.28-x86_64-unknown-linux-gnu.tar.gz | tar xzf - + echo $PWD >> $GITHUB_PATH + - run: (cd guide && mdbook build) + - uses: actions/upload-artifact@v4 + with: + name: doc_book + path: guide/book/html + + doc_api: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update nightly && rustup default nightly + - run: cargo doc --no-deps --features 'serde-serialize' + - run: cargo doc --no-deps --manifest-path crates/js-sys/Cargo.toml + - run: cargo doc --no-deps --manifest-path crates/web-sys/Cargo.toml --all-features + env: + RUSTDOCFLAGS: --cfg=web_sys_unstable_apis + - run: cargo doc --no-deps --manifest-path crates/futures/Cargo.toml + - run: tar czvf docs.tar.gz target/doc + - uses: actions/upload-artifact@v4 + with: + name: doc_api + path: docs.tar.gz + + + deploy: + permissions: + contents: write # to push changes in repo (jamesives/github-pages-deploy-action) + + needs: + - doc_api + - doc_book + - dist_linux_x86_64_musl + - dist_linux_aarch64_gnu + - dist_macos_x86_64 + - dist_macos_aarch64 + - dist_windows + - build_examples + - build_nightly + - build_benchmarks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/download-artifact@v4 + with: + path: artifacts + - run: find artifacts + - run: | + set -ex + mkdir -p gh-release + tag=`git describe --tags` + mk() { + target=$1 + src=$2 + name=wasm-bindgen-$tag-$target + mkdir -p tmp/$name + rm -f artifacts/$src/*.d + rm -f artifacts/$src/*.pdb + cp README.md \ + LICENSE-MIT \ + LICENSE-APACHE \ + artifacts/$src/wasm* \ + tmp/$name/ + chmod +x tmp/$name/wasm* + tar czvf gh-release/$name.tar.gz -C tmp $name + sha256sum gh-release/$name.tar.gz > gh-release/$name.tar.gz.sha256sum + } + mk x86_64-unknown-linux-musl dist_linux_x86_64_musl + mk aarch64-unknown-linux-gnu dist_linux_aarch64_gnu + mk x86_64-apple-darwin dist_macos_x86_64 + mk aarch64-apple-darwin dist_macos_aarch64 + mk x86_64-pc-windows-msvc dist_windows + - uses: actions/upload-artifact@v4 + with: + name: gh-release + path: gh-release + - run: | + mv artifacts/doc_book gh-pages + tar xf artifacts/doc_api/docs.tar.gz + mv target/doc gh-pages/api + mv artifacts/examples1 gh-pages/exbuild + mv artifacts/examples2/* gh-pages/exbuild + mv artifacts/benchmarks gh-pages/benchmarks + tar czf gh-pages.tar.gz gh-pages + - uses: actions/upload-artifact@v4 + with: + name: gh-pages + path: gh-pages.tar.gz + - uses: JamesIves/github-pages-deploy-action@v4 + with: + branch: gh-pages + folder: gh-pages + single-commit: true + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + - uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: "gh-release/*.tar.gz*" + - uses: dtolnay/rust-toolchain@stable + if: startsWith(github.ref, 'refs/tags/') + - run: rustc publish.rs + if: startsWith(github.ref, 'refs/tags/') + - run: ./publish publish + if: startsWith(github.ref, 'refs/tags/') + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_PUBLISH_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +[package] +name = "wasm-bindgen" +version = "0.2.92" +authors = ["The wasm-bindgen Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +categories = ["wasm"] +repository = "https://github.com/rustwasm/wasm-bindgen" +homepage = "https://rustwasm.github.io/" +documentation = "https://docs.rs/wasm-bindgen" +description = """ +Easy support for interacting between JS and Rust. +""" +edition = "2018" +rust-version = "1.57" + +[package.metadata.docs.rs] +features = ["serde-serialize"] + +[lib] +test = false + +[features] +default = ["spans", "std"] +spans = ["wasm-bindgen-macro/spans"] +std = [] +serde-serialize = ["serde", "serde_json", "std"] +enable-interning = ["std"] + +# Whether or not the `#[wasm_bindgen]` macro is strict and generates an error on +# all unused attributes +strict-macro = ["wasm-bindgen-macro/strict-macro"] + +# Enables gg-alloc as system allocator when using wasm-bindgen-test to check that large pointers +# are handled correctly +gg-alloc = ["wasm-bindgen-test/gg-alloc"] + +# This is only for debugging wasm-bindgen! No stability guarantees, so enable +# this at your own peril! +xxx_debug_only_print_generated_code = [ + "wasm-bindgen-macro/xxx_debug_only_print_generated_code", +] + +[dependencies] +wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.92" } +serde = { version = "1.0", optional = true } +serde_json = { version = "1.0", optional = true } +cfg-if = "1.0.0" + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +js-sys = { path = 'crates/js-sys', version = '0.3.69' } +wasm-bindgen-test = { path = 'crates/test', version = '=0.3.42' } +wasm-bindgen-futures = { path = 'crates/futures', version = '=0.4.42' } +serde_derive = "1.0" +wasm-bindgen-test-crate-a = { path = 'tests/crates/a', version = '0.1' } +wasm-bindgen-test-crate-b = { path = 'tests/crates/b', version = '0.1' } + +[workspace] +members = [ + "benchmarks", + "crates/cli", + "crates/js-sys", + "crates/test", + "crates/test/sample", + "crates/example-tests", + "crates/typescript-tests", + "crates/web-sys", + "crates/webidl", + "crates/webidl-tests", + "examples/add", + "examples/canvas", + "examples/char", + "examples/closures", + "examples/console_log", + "examples/deno", + "examples/dom", + "examples/duck-typed-interfaces", + "examples/fetch", + "examples/guide-supported-types-examples", + "examples/hello_world", + "examples/import_js/crate", + "examples/julia_set", + "examples/paint", + "examples/performance", + "examples/raytrace-parallel", + "examples/request-animation-frame", + "examples/todomvc", + "examples/wasm-audio-worklet", + "examples/wasm-in-wasm", + "examples/wasm-in-wasm-imports", + "examples/wasm-in-web-worker", + "examples/wasm2js", + "examples/weather_report", + "examples/webaudio", + "examples/webgl", + "examples/webrtc_datachannel", + "examples/websockets", + "examples/webxr", + "examples/without-a-bundler", + "examples/without-a-bundler-no-modules", + "examples/synchronous-instantiation", + "tests/no-std", +] +resolver = "2" + +[patch.crates-io] +wasm-bindgen = { path = '.' } +wasm-bindgen-futures = { path = 'crates/futures' } +js-sys = { path = 'crates/js-sys' } +web-sys = { path = 'crates/web-sys' } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/examples/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/examples/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/examples/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/examples/.gitignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +package-lock.json +pkg +dist +wasm-pack.log diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/guide/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/guide/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen/guide/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen/guide/.gitignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +book diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-backend/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-backend/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"0993a9c0b1946ba425a58db37f553c9b7fce2d420e0666d8d2397705eba2e187","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/ast.rs":"880a7260126a5d77ba1ad748b199c9a2ff2da806a8f849e1160495f5d2d62203","src/codegen.rs":"1250afc06bee817a2b62287388502ea6028c44936e1dd2e43c038231f773b0f4","src/encode.rs":"1350ccc927d7afdc1379a41127ce890dd50350a7773660b73f37d505a6229c16","src/error.rs":"18e23656cf81d363dae25b6340a725b8135badd91a2702a83cd80e19821e99ba","src/lib.rs":"14ade320b537315ec4c575f9f3c7a35ff4e9385114c4c26a35b2ee270a897cb4","src/util.rs":"7f305ad4c71e9d11ac9c5e9ab452d3c885dcfe8141084411892f042ccc54ba5e"},"package":"614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"} \ No newline at end of file +{"files":{"Cargo.toml":"0993a9c0b1946ba425a58db37f553c9b7fce2d420e0666d8d2397705eba2e187","Cargo.toml.orig":"3227ecd8d18d00e5639372848723a44921b2325c287202092e9b7b18becb402d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/ast.rs":"880a7260126a5d77ba1ad748b199c9a2ff2da806a8f849e1160495f5d2d62203","src/codegen.rs":"1250afc06bee817a2b62287388502ea6028c44936e1dd2e43c038231f773b0f4","src/encode.rs":"1350ccc927d7afdc1379a41127ce890dd50350a7773660b73f37d505a6229c16","src/error.rs":"18e23656cf81d363dae25b6340a725b8135badd91a2702a83cd80e19821e99ba","src/lib.rs":"14ade320b537315ec4c575f9f3c7a35ff4e9385114c4c26a35b2ee270a897cb4","src/util.rs":"7f305ad4c71e9d11ac9c5e9ab452d3c885dcfe8141084411892f042ccc54ba5e"},"package":"614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-backend/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-backend/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-backend/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +[package] +name = "wasm-bindgen-backend" +version = "0.2.92" +authors = ["The wasm-bindgen Developers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/backend" +homepage = "https://rustwasm.github.io/wasm-bindgen/" +documentation = "https://docs.rs/wasm-bindgen-backend" +description = """ +Backend code generation of the wasm-bindgen tool +""" +edition = "2018" +rust-version = "1.57" + +[features] +spans = [] +extra-traits = ["syn/extra-traits"] + +[dependencies] +bumpalo = "3.0.0" +log = "0.4" +once_cell = "1.12" +proc-macro2 = "1.0" +quote = '1.0' +syn = { version = '2.0', features = ['full'] } +wasm-bindgen-shared = { path = "../shared", version = "=0.2.92" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"093e170a2b89fa922b67f34ce85a154ba6c92ced4335c088aea8bea36627e44d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ef5ffff199bf75993b81c3c1de8dbe19babb22b89170763323fa11a85c62f045","src/lib.rs":"8ba70e362eeb15efaf686df366c3525c24272d61141e31585e1f642b030a54c9","src/worker.js":"cb5c33dd41cfad622abce5464a3ceae478904ea16ddc3c6c769ee33e0c086692","tests/ui.rs":"aed1b0f4e8c99b06657c54f3a74de4b3535ce567fb20e4d2fc6911b361c3d934","ui-tests/async-errors.rs":"f3ab249b3741b38c6213651a5cd36f8b9873bad34bd49d13b780d21bed47272b","ui-tests/async-errors.stderr":"f8b39f3239ef21b654ab7850cf38c97bd2eaf94e9e8a2bf05687088d25d92b9f","ui-tests/attribute-fails-to-parse.rs":"c21c2a250534ca7e80fc462804efc0db8a71b6b0cdb0c57c5cab444d081f68de","ui-tests/attribute-fails-to-parse.stderr":"3bc77befbbe7e2d0744dd81067a75cb70c3f2d8bd9c60ec5bcb2dfb65fc1a593","ui-tests/bad-signatures.rs":"96b53e9327cc75747510b548b97cff86429532d5cdf65cc991211bca5646abc2","ui-tests/bad-signatures.stderr":"931e934ccbc43e4cee41a46ecaa3953c3ccdef69450519a838b9af428f75fa72","ui-tests/import-local.rs":"783ef9ebb792111ec7fd335cbc4f684381609c86c0af660fd5ab35cf04cacbf4","ui-tests/import-local.stderr":"6e90ad05c3783d7c69ff4e156458c63ee45ceb7ea8ebc38e1ca52e7f46e8bcf8","ui-tests/invalid-attr.rs":"603cf0bcb95a42a35e535a7d9577dc8c5e6175af4cd27d83fdf77cd6b67acf48","ui-tests/invalid-attr.stderr":"e1fd9450e16f1d672cb708bcbaf99a07f916c48d3e961c1dd1e92bd835d3ec53","ui-tests/invalid-enums.rs":"bf473e1bbafbcde82c946311e824d97bd1f941cfc5c1495025d8a7a513b90a19","ui-tests/invalid-enums.stderr":"ecd549ab69e7d7d645922857e2a83b7171f97a276afeb9f113407a4181b2b9e2","ui-tests/invalid-imports.rs":"94724ba9f08fde1830d82b332aa1833850018d8738daefda3fe2516190b6842f","ui-tests/invalid-imports.stderr":"21c96f9bb3b9d0951161b05ad413739ab436242a107e4fe0f9b029b9fa4b061e","ui-tests/invalid-items.rs":"ca919f7fe6c0d9fd4218ec43c85d7b43f478ed3042959479eb42adc23f4edf02","ui-tests/invalid-items.stderr":"a7392f1b918cac6eda3cefa5244dc555e4b6332836cab0bbd341b992672cd064","ui-tests/invalid-methods.rs":"c463bee9962d936ef2aeb4051ebc5558c0b7fefe6e459f3a325482763746969f","ui-tests/invalid-methods.stderr":"ca21b68621674208b7f95b4a201b9726e4bc07ffa127140dc13656d68db2e2e2","ui-tests/invalid-setter.rs":"db9666df889b58246a51ebc7d753e41ac4382475257a589499a4e886e6fbc45f","ui-tests/invalid-setter.stderr":"d1629836ec39727bfa4737538e9f991cda6fbaeb1c0f8c878cb13757e66daac5","ui-tests/link-to.rs":"be7003f80bf05cffa1301d049bd8f3792513a3f3922da3e74f4b58086970bb85","ui-tests/link-to.stderr":"c582600658db54acf3c16ffde723320a4cbcca3514cc30659badb524a06f66e7","ui-tests/main-async.rs":"0d9aedf6158295d9b4c9ed391f979073c1e294c0be8cdd310444d941826b02bb","ui-tests/main-async.stderr":"ef9b711e9db3bbc3d0cbc315044eb6f72139bea4b1785b12f33d521e280d5056","ui-tests/main-debug.rs":"b9fa920c4fc28b0815aed752b90e77723c3291670b6e35372d9d2b05a1ac19eb","ui-tests/main-debug.stderr":"67f5ccb2df878c02a3b394273ccf531fad68f289712140956186c0e9fd83f8f3","ui-tests/main-infallible.rs":"a75d80b13fed301181d69bb6f67ad082c3f1976ec9effef17aadb31bb1160f2a","ui-tests/main-infallible.stderr":"11629a59febd8874c1a87791f82e43cfefc9e10d7c5352f322c80293518b8f47","ui-tests/main-jsvalue.rs":"5f9be90d6603c836aa7eaba0a6014975b6974e895602f4171f5631bf937a4278","ui-tests/main-jsvalue.stderr":"9d6989822f1656100be44f5a99f3a6c0d8127fbd0d47b7a34f2c8806aa957f3d","ui-tests/main-unit.rs":"88c746ad86b282c0da5271a335126396db6701b963d7db3286271edfd5b0a503","ui-tests/main-unit.stderr":"5ca86669158c9bff919785ad330745ed80d38e3ff8d1d32c3ff47752fcec8196","ui-tests/main.rs":"0dbbca3882dcec75e1137e6043fd053d8c8cc6a17276ee1dc9088cfaaf565e88","ui-tests/main.stderr":"dd04c49d88dab17ffa0add6603b81407b7f4f43cef63c1afc19bcf0e25a11128","ui-tests/missing-catch.rs":"705bf784db641b30131510b5c47192014e19aeeeb6f73ede1d5356ad2c29915c","ui-tests/missing-catch.stderr":"42dc8cb6ef178771aa7a8fc23ef60315c1ffb764aaf1fd672ba908a7a239c3ce","ui-tests/non-public-function.rs":"0fe075b32c211870bcde0f7dce0eceaffb61a4f8a6ffbd90946a59d7d220343c","ui-tests/non-public-function.stderr":"c9f6f5123b6c3462b8952d6e468ed13c566635d4939b98c9098d2a713f5aa2df","ui-tests/pub-not-copy.rs":"1e50f0b63a6e6363b0926cf947b0492a9803ddb35370f32e733a32506df9b556","ui-tests/pub-not-copy.stderr":"1090980d08622552b82c13da82b4c26ce309314b6062f0c5443a65eff5255d00","ui-tests/start-function.rs":"a56f1309182e597370555c18aa31e240e70e82585d6e72ab4c42e2229a8c1a53","ui-tests/start-function.stderr":"ba9abe2807e1a23e98f5cab51b32f0ce83dcee46198105702ec89e98e60eb289","ui-tests/struct-fields.rs":"8e70ca9716e4432a014a279cf2714aa4e15d2d9dfb198ad93f2fe9b6037ff8c4","ui-tests/struct-fields.stderr":"10b1b5878f522724e1b00831b2c5a806762983c52e3772d6cd600b80141eb9bd","ui-tests/structural-and-final.rs":"1571b078a9d0be6c96ab97be10f1bf369dbb740f04fa312834f49a64130f8d30","ui-tests/structural-and-final.stderr":"cf21dec2851d3f667b93a317ba9e4657a623c49e8b779ea64669452297ba0a17","ui-tests/traits-not-implemented.rs":"3445e15b9c61f84a1f8d703a3a4fe2d2e2d85960ff6b2ac718644d97bf1564e1","ui-tests/traits-not-implemented.stderr":"048efa757323d0bf75c4e140f987f33336faaf5e5b15ec603f012fb7d2dd80e0","ui-tests/unknown-type-in-import.rs":"7fbc95bb82d0d60568b8daf27236418219c57447d1dc2e2e384e5f907bac3e3e","ui-tests/unknown-type-in-import.stderr":"348350a2591544623f96246d860b47c64ef43933b8ac447ec7ff6fab7bac00c0","ui-tests/unused-attributes.rs":"7c20441c30e53376c9e72fcf82da0cc6e7462eec3087f9eb74f9682eaf7fb3e6","ui-tests/unused-attributes.stderr":"461a3724155d6007e75191233d0ff9a4897eeaed04f2ab8582636f17e62f46ac","ui-tests/update-all-references.sh":"8b8dbf31e7ada1314956db7a20ab14b13af3ae246a6295afdc7dc96af8ec3773","ui-tests/update-references.sh":"65375c25981646e08e8589449a06be4505b1a2c9e10d35f650be4b1b495dff22","ui-tests/wasm-bindgen.rs":"49ba1dc3f1847d564afb472ff965e1bf00398e660771b2481bd65515f28439ab","ui-tests/wasm-bindgen.stderr":"5df70ec3ee78b071f6db86a4bfd146acb30ae30d6d1d97512b60c8a8be4920c5"},"package":"a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"} \ No newline at end of file +{"files":{"Cargo.toml":"093e170a2b89fa922b67f34ce85a154ba6c92ced4335c088aea8bea36627e44d","Cargo.toml.orig":"916c3ecfeeb28129303b49f850deadd949d0ab5812a915cdf5c54f3b5230fab5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ef5ffff199bf75993b81c3c1de8dbe19babb22b89170763323fa11a85c62f045","src/lib.rs":"8ba70e362eeb15efaf686df366c3525c24272d61141e31585e1f642b030a54c9","src/worker.js":"cb5c33dd41cfad622abce5464a3ceae478904ea16ddc3c6c769ee33e0c086692","tests/ui.rs":"aed1b0f4e8c99b06657c54f3a74de4b3535ce567fb20e4d2fc6911b361c3d934","ui-tests/async-errors.rs":"f3ab249b3741b38c6213651a5cd36f8b9873bad34bd49d13b780d21bed47272b","ui-tests/async-errors.stderr":"f8b39f3239ef21b654ab7850cf38c97bd2eaf94e9e8a2bf05687088d25d92b9f","ui-tests/attribute-fails-to-parse.rs":"c21c2a250534ca7e80fc462804efc0db8a71b6b0cdb0c57c5cab444d081f68de","ui-tests/attribute-fails-to-parse.stderr":"3bc77befbbe7e2d0744dd81067a75cb70c3f2d8bd9c60ec5bcb2dfb65fc1a593","ui-tests/bad-signatures.rs":"96b53e9327cc75747510b548b97cff86429532d5cdf65cc991211bca5646abc2","ui-tests/bad-signatures.stderr":"931e934ccbc43e4cee41a46ecaa3953c3ccdef69450519a838b9af428f75fa72","ui-tests/import-local.rs":"783ef9ebb792111ec7fd335cbc4f684381609c86c0af660fd5ab35cf04cacbf4","ui-tests/import-local.stderr":"6e90ad05c3783d7c69ff4e156458c63ee45ceb7ea8ebc38e1ca52e7f46e8bcf8","ui-tests/invalid-attr.rs":"603cf0bcb95a42a35e535a7d9577dc8c5e6175af4cd27d83fdf77cd6b67acf48","ui-tests/invalid-attr.stderr":"e1fd9450e16f1d672cb708bcbaf99a07f916c48d3e961c1dd1e92bd835d3ec53","ui-tests/invalid-enums.rs":"bf473e1bbafbcde82c946311e824d97bd1f941cfc5c1495025d8a7a513b90a19","ui-tests/invalid-enums.stderr":"ecd549ab69e7d7d645922857e2a83b7171f97a276afeb9f113407a4181b2b9e2","ui-tests/invalid-imports.rs":"94724ba9f08fde1830d82b332aa1833850018d8738daefda3fe2516190b6842f","ui-tests/invalid-imports.stderr":"21c96f9bb3b9d0951161b05ad413739ab436242a107e4fe0f9b029b9fa4b061e","ui-tests/invalid-items.rs":"ca919f7fe6c0d9fd4218ec43c85d7b43f478ed3042959479eb42adc23f4edf02","ui-tests/invalid-items.stderr":"a7392f1b918cac6eda3cefa5244dc555e4b6332836cab0bbd341b992672cd064","ui-tests/invalid-methods.rs":"c463bee9962d936ef2aeb4051ebc5558c0b7fefe6e459f3a325482763746969f","ui-tests/invalid-methods.stderr":"ca21b68621674208b7f95b4a201b9726e4bc07ffa127140dc13656d68db2e2e2","ui-tests/invalid-setter.rs":"db9666df889b58246a51ebc7d753e41ac4382475257a589499a4e886e6fbc45f","ui-tests/invalid-setter.stderr":"d1629836ec39727bfa4737538e9f991cda6fbaeb1c0f8c878cb13757e66daac5","ui-tests/link-to.rs":"be7003f80bf05cffa1301d049bd8f3792513a3f3922da3e74f4b58086970bb85","ui-tests/link-to.stderr":"c582600658db54acf3c16ffde723320a4cbcca3514cc30659badb524a06f66e7","ui-tests/main-async.rs":"0d9aedf6158295d9b4c9ed391f979073c1e294c0be8cdd310444d941826b02bb","ui-tests/main-async.stderr":"ef9b711e9db3bbc3d0cbc315044eb6f72139bea4b1785b12f33d521e280d5056","ui-tests/main-debug.rs":"b9fa920c4fc28b0815aed752b90e77723c3291670b6e35372d9d2b05a1ac19eb","ui-tests/main-debug.stderr":"67f5ccb2df878c02a3b394273ccf531fad68f289712140956186c0e9fd83f8f3","ui-tests/main-infallible.rs":"a75d80b13fed301181d69bb6f67ad082c3f1976ec9effef17aadb31bb1160f2a","ui-tests/main-infallible.stderr":"11629a59febd8874c1a87791f82e43cfefc9e10d7c5352f322c80293518b8f47","ui-tests/main-jsvalue.rs":"5f9be90d6603c836aa7eaba0a6014975b6974e895602f4171f5631bf937a4278","ui-tests/main-jsvalue.stderr":"9d6989822f1656100be44f5a99f3a6c0d8127fbd0d47b7a34f2c8806aa957f3d","ui-tests/main-unit.rs":"88c746ad86b282c0da5271a335126396db6701b963d7db3286271edfd5b0a503","ui-tests/main-unit.stderr":"5ca86669158c9bff919785ad330745ed80d38e3ff8d1d32c3ff47752fcec8196","ui-tests/main.rs":"0dbbca3882dcec75e1137e6043fd053d8c8cc6a17276ee1dc9088cfaaf565e88","ui-tests/main.stderr":"dd04c49d88dab17ffa0add6603b81407b7f4f43cef63c1afc19bcf0e25a11128","ui-tests/missing-catch.rs":"705bf784db641b30131510b5c47192014e19aeeeb6f73ede1d5356ad2c29915c","ui-tests/missing-catch.stderr":"42dc8cb6ef178771aa7a8fc23ef60315c1ffb764aaf1fd672ba908a7a239c3ce","ui-tests/non-public-function.rs":"0fe075b32c211870bcde0f7dce0eceaffb61a4f8a6ffbd90946a59d7d220343c","ui-tests/non-public-function.stderr":"c9f6f5123b6c3462b8952d6e468ed13c566635d4939b98c9098d2a713f5aa2df","ui-tests/pub-not-copy.rs":"1e50f0b63a6e6363b0926cf947b0492a9803ddb35370f32e733a32506df9b556","ui-tests/pub-not-copy.stderr":"1090980d08622552b82c13da82b4c26ce309314b6062f0c5443a65eff5255d00","ui-tests/start-function.rs":"a56f1309182e597370555c18aa31e240e70e82585d6e72ab4c42e2229a8c1a53","ui-tests/start-function.stderr":"ba9abe2807e1a23e98f5cab51b32f0ce83dcee46198105702ec89e98e60eb289","ui-tests/struct-fields.rs":"8e70ca9716e4432a014a279cf2714aa4e15d2d9dfb198ad93f2fe9b6037ff8c4","ui-tests/struct-fields.stderr":"10b1b5878f522724e1b00831b2c5a806762983c52e3772d6cd600b80141eb9bd","ui-tests/structural-and-final.rs":"1571b078a9d0be6c96ab97be10f1bf369dbb740f04fa312834f49a64130f8d30","ui-tests/structural-and-final.stderr":"cf21dec2851d3f667b93a317ba9e4657a623c49e8b779ea64669452297ba0a17","ui-tests/traits-not-implemented.rs":"3445e15b9c61f84a1f8d703a3a4fe2d2e2d85960ff6b2ac718644d97bf1564e1","ui-tests/traits-not-implemented.stderr":"048efa757323d0bf75c4e140f987f33336faaf5e5b15ec603f012fb7d2dd80e0","ui-tests/unknown-type-in-import.rs":"7fbc95bb82d0d60568b8daf27236418219c57447d1dc2e2e384e5f907bac3e3e","ui-tests/unknown-type-in-import.stderr":"348350a2591544623f96246d860b47c64ef43933b8ac447ec7ff6fab7bac00c0","ui-tests/unused-attributes.rs":"7c20441c30e53376c9e72fcf82da0cc6e7462eec3087f9eb74f9682eaf7fb3e6","ui-tests/unused-attributes.stderr":"461a3724155d6007e75191233d0ff9a4897eeaed04f2ab8582636f17e62f46ac","ui-tests/update-all-references.sh":"8b8dbf31e7ada1314956db7a20ab14b13af3ae246a6295afdc7dc96af8ec3773","ui-tests/update-references.sh":"65375c25981646e08e8589449a06be4505b1a2c9e10d35f650be4b1b495dff22","ui-tests/wasm-bindgen.rs":"49ba1dc3f1847d564afb472ff965e1bf00398e660771b2481bd65515f28439ab","ui-tests/wasm-bindgen.stderr":"5df70ec3ee78b071f6db86a4bfd146acb30ae30d6d1d97512b60c8a8be4920c5"},"package":"a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +[package] +name = "wasm-bindgen-macro" +version = "0.2.92" +authors = ["The wasm-bindgen Developers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro" +homepage = "https://rustwasm.github.io/wasm-bindgen/" +documentation = "https://docs.rs/wasm-bindgen" +description = """ +Definition of the `#[wasm_bindgen]` attribute, an internal dependency +""" +edition = "2018" +rust-version = "1.57" + +[lib] +proc-macro = true + +[features] +spans = ["wasm-bindgen-macro-support/spans"] +xxx_debug_only_print_generated_code = [] +strict-macro = ["wasm-bindgen-macro-support/strict-macro"] + +[dependencies] +wasm-bindgen-macro-support = { path = "../macro-support", version = "=0.2.92" } +quote = "1.0" + +[dev-dependencies] +trybuild = "1.0" +wasm-bindgen = { path = "../..", version = "0.2.92" } +wasm-bindgen-futures = { path = "../futures", version = "0.4.42" } +web-sys = { path = "../web-sys", version = "0.3.69", features = ["Worker"] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro-support/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro-support/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"f9c34eece31aebd21b9bc2a1d0d2a24b25ecf96f3650e7fe533edb2a079e2266","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/lib.rs":"4f212183a9d5a2682d6156f7b011f789fa23002099268940af090336f067d6fa","src/parser.rs":"eb1467d83a8c6ec18b5f0886f8f2c9ee71e920c266c429586b50db8bddf31795"},"package":"e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"} \ No newline at end of file +{"files":{"Cargo.toml":"f9c34eece31aebd21b9bc2a1d0d2a24b25ecf96f3650e7fe533edb2a079e2266","Cargo.toml.orig":"c09549fc97fce97b63f69cc062a2949de761bb2d68de456251096a4d3b1e4127","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/lib.rs":"4f212183a9d5a2682d6156f7b011f789fa23002099268940af090336f067d6fa","src/parser.rs":"eb1467d83a8c6ec18b5f0886f8f2c9ee71e920c266c429586b50db8bddf31795"},"package":"e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro-support/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-macro-support/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-macro-support/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +[package] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +authors = ["The wasm-bindgen Developers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support" +homepage = "https://rustwasm.github.io/wasm-bindgen/" +documentation = "https://docs.rs/wasm-bindgen" +description = """ +The part of the implementation of the `#[wasm_bindgen]` attribute that is not in the shared backend crate +""" +edition = '2018' +rust-version = "1.57" + +[features] +spans = ["wasm-bindgen-backend/spans"] +extra-traits = ["syn/extra-traits"] +strict-macro = [] + +[dependencies] +syn = { version = '2.0', features = ['visit', 'full'] } +quote = '1.0' +proc-macro2 = "1.0" +wasm-bindgen-backend = { path = "../backend", version = "=0.2.92" } +wasm-bindgen-shared = { path = "../shared", version = "=0.2.92" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-shared/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-shared/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"a4484c6f5cad71c431d1db04e47dfcdd95009ab7af4eead17cbd1646072f3dc4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","build.rs":"1945abcbf05206be9463f60094b4363079f284781ed009feadb0137953826c26","src/lib.rs":"bac2013d5a4764975b171e89abd10c6a20428f445aa385a42811df734c621f4a","src/schema_hash_approval.rs":"6f86df6c10b9373a0789cbaa5e01ff2dbae66426d6512dbf60233e1113558478"},"package":"af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"} \ No newline at end of file +{"files":{"Cargo.toml":"a4484c6f5cad71c431d1db04e47dfcdd95009ab7af4eead17cbd1646072f3dc4","Cargo.toml.orig":"d0dacded5b26e7c8767e7bab1f2993977a66c9f8dab37288c84115faeffd1a25","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","build.rs":"1945abcbf05206be9463f60094b4363079f284781ed009feadb0137953826c26","src/lib.rs":"bac2013d5a4764975b171e89abd10c6a20428f445aa385a42811df734c621f4a","src/schema_hash_approval.rs":"6f86df6c10b9373a0789cbaa5e01ff2dbae66426d6512dbf60233e1113558478"},"package":"af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-shared/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasm-bindgen-shared/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasm-bindgen-shared/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "wasm-bindgen-shared" +version = "0.2.92" +authors = ["The wasm-bindgen Developers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared" +homepage = "https://rustwasm.github.io/wasm-bindgen/" +documentation = "https://docs.rs/wasm-bindgen-shared" +description = """ +Shared support between wasm-bindgen and wasm-bindgen cli, an internal +dependency. +""" +edition = "2018" +rust-version = "1.57" + +# Because only a single `wasm_bindgen` version can be used in a dependency +# graph, pretend we link a native library so that `cargo` will provide better +# error messages than the esoteric linker errors we would otherwise trigger. +links = "wasm_bindgen" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"83a8e4fc9c85f557c910b58ac357a705895efe950b5c72b9f7e61b181b6e1ead","Cargo.toml":"d37a9d03f2dad57772564f53df91098755c95600bbfedcb03337ce439bdf084a","Changes.md":"89999e9ffb5aabfefd8e117bb16f87e8871050a8223ec53282dc05ccf5de7eca","LICENSE-APACHE":"769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb","LICENSE-MIT":"573f5227db835cd30bbdd3aed3f82615f80119a4d5c82b4daf642dbfe2b6afde","README.md":"af4bf85c471ed63ee9221f2a147597762db8ab9fb992e1f7ae8442f1727eea8b","benches/msb8.rs":"7d7073ecb764e5d2525410b89916e58f32fb032ac9e5bd14f3353884e477f2aa","bin/lzw.rs":"6fe3a12f9ae09b9f24d6d5f4b3555fba6843bd58635010ef6ba9729849b83ebd","examples/lzw-compress.rs":"2e6ae724d7aa4b233dab99a4c01d7077432f36d609e2104107f4d91405832fe3","examples/lzw-decompress.rs":"3673c5af5c8833f34f005b6c12d1f51d8d2e6f223ecad1a0bac3f579929b66a9","src/decode.rs":"3b0508d3a0130ee8dbd8ba14f05bdf3fa34e012fc6a8fae9db853abad0798e40","src/decode_into_async.rs":"56612029218776b82fccaaed3668386891246a49fe15d8aba99294995578c9e0","src/encode.rs":"53dc03a8289e8f89f5f9c17c42097919dba648fbf0daf2cad9039437839cc1c7","src/encode_into_async.rs":"073ba3b32a3e7c80fcbda87c224a45645a982ccf32e5218546978c5227a2f8db","src/error.rs":"700deb53b7a280050db5bc9b9531f431de3a8db39d1c43ba5a0f89a1ecb365a6","src/lib.rs":"e970340ccac19053be9f48e8aed814afd04453efe348e4c5a0f2bf6cc4a99f9c","tests/async.rs":"1869d5c0b07d3a5e21ac3dcd6800b9fe1e19f1137491c577983628e92a4d2ead","tests/implicit_reset.rs":"6b934736835ea3740d8f966e2209d0cf95c2c43d7dbcc3f03affd0cae2f1ce24","tests/roundtrip.rs":"ac4b6070c0485ea8cd3b6365bb3caf666b5b73cf8cec2e787413bead3badc99e","tests/roundtrip_vec.rs":"a03f9a7a265f52ded6f6cc84f78c5dd24877f1a7c528ae1c070e65e3812a544e"},"package":"53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"b65026a35ec50a4da63f8998cf28192be7dfb9296fb3c485d3a0b43a51dffb8f",".github/workflows/rust.yml":"4210df10abb942cdbb6962cdd38d1310136f25e1d755e8659708906bc7013fbd","Cargo.lock":"344a72eb6255e4037332a2ca05777323131fc6cd8a076a3a2c3f420873392c18","Cargo.toml":"66fd92299a4c1ddb2027d51387c1e78e0839b94bba152bf482b90932122302d0","Cargo.toml.orig":"cf90bb0c46d5c905181e4e8a55519df1587c2b0db64fe24a9005907f8efe6355","Changes.md":"01e4cd478adb52a55df406f4f2b25c80d75770848179cabbbfd003e464fefddc","LICENSE-APACHE":"769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb","LICENSE-MIT":"573f5227db835cd30bbdd3aed3f82615f80119a4d5c82b4daf642dbfe2b6afde","README.md":"af4bf85c471ed63ee9221f2a147597762db8ab9fb992e1f7ae8442f1727eea8b","benches/msb8.rs":"7d7073ecb764e5d2525410b89916e58f32fb032ac9e5bd14f3353884e477f2aa","bin/lzw.rs":"6fe3a12f9ae09b9f24d6d5f4b3555fba6843bd58635010ef6ba9729849b83ebd","examples/lzw-compress.rs":"2e6ae724d7aa4b233dab99a4c01d7077432f36d609e2104107f4d91405832fe3","examples/lzw-decompress.rs":"3673c5af5c8833f34f005b6c12d1f51d8d2e6f223ecad1a0bac3f579929b66a9","src/decode.rs":"cfbeff7fc5c17e62ba848da79b95a2e62f7f520b8c2e21f7a508e35dda42e52b","src/decode_into_async.rs":"56612029218776b82fccaaed3668386891246a49fe15d8aba99294995578c9e0","src/encode.rs":"e0e10222cbf989be70116ed459b0396eee32a4a0a8f06e8d235a4789f383d59b","src/encode_into_async.rs":"073ba3b32a3e7c80fcbda87c224a45645a982ccf32e5218546978c5227a2f8db","src/error.rs":"700deb53b7a280050db5bc9b9531f431de3a8db39d1c43ba5a0f89a1ecb365a6","src/lib.rs":"e970340ccac19053be9f48e8aed814afd04453efe348e4c5a0f2bf6cc4a99f9c","tests/async.rs":"1869d5c0b07d3a5e21ac3dcd6800b9fe1e19f1137491c577983628e92a4d2ead","tests/end_of_buffer.rs":"9cc4d820b16bbe06edc72808d638185483ce52f7c1148f838d9de85dfc551d30","tests/implicit_reset.rs":"6b934736835ea3740d8f966e2209d0cf95c2c43d7dbcc3f03affd0cae2f1ce24","tests/roundtrip.rs":"83e1040e866a1d103acd52e8f92d7a8a92e71529406d0361d3040bc574f019d4","tests/roundtrip_vec.rs":"2f8fc58c174192a86bfdf6c3bbbf8209fb534e6fd1b1ea3669246e8032c9f0a3"},"package":"a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "git": { + "sha1": "c75ea1f6d935cc56bad8674396b7cb0dd7275f99", + "dirty": true + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/weezl/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +name: Rust CI +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable, beta, nightly] + features: ["", "alloc", "std", "async"] + steps: + - uses: actions/checkout@v2 + - run: rustup default ${{ matrix.rust }} + - name: build + run: > + cargo build --verbose --no-default-features --features "$FEATURES" + env: + FEATURES: ${{ matrix.features }} + - name: test + run: > + cargo test --tests --benches --no-default-features --features "$FEATURES" --release + if: ${{ matrix.rust != '1.34.2' }} + env: + FEATURES: ${{ matrix.features }} + build_msrv: + runs-on: ubuntu-latest + strategy: + matrix: + features: ["", "std"] + steps: + - uses: actions/checkout@v2 + - run: rustup default "1.34.2" + - name: build + run: cargo build --verbose --no-default-features --features "$FEATURES" + env: + FEATURES: ${{ matrix.features }} + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + - name: Run rustfmt check + uses: actions-rs/cargo@v1 + with: + command: fmt + args: -- --check diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -1,824 +1,824 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 4 + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "memchr", + "regex-automata", + "serde", ] [[package]] name = "bumpalo" version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cast" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" dependencies = [ - "rustc_version 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "textwrap", + "unicode-width", ] [[package]] name = "criterion" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "oorandom 11.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "plotters 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_cbor 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "cast 0.3.0", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", ] [[package]] name = "criterion-plot" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ - "cast 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.7", + "itertools", ] [[package]] name = "crossbeam-channel" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils", ] [[package]] name = "crossbeam-deque" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "once_cell", + "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "once_cell", ] [[package]] name = "csv" version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ - "bstr 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", ] [[package]] name = "csv-core" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "either" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "futures" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ - "futures-channel 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] name = "futures-channel" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ - "futures-core 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-sink", ] [[package]] name = "futures-core" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-io" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-sink" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "futures-channel 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", ] [[package]] name = "half" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "itertools" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ - "either 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ - "wasm-bindgen 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "mio" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", - "windows-sys 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "log", + "wasi", + "windows-sys", ] [[package]] name = "num-traits" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "num_cpus" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "once_cell" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "plotters" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" dependencies = [ - "num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "plotters-backend 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "plotters-svg 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.58 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" dependencies = [ - "plotters-backend 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "plotters-backend", ] [[package]] name = "proc-macro2" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "unicode-ident 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident", ] [[package]] name = "quote" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "rayon" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ - "crossbeam-channel 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", ] [[package]] name = "regex" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ - "regex-syntax 0.6.27 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax", ] [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "ryu" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" [[package]] name = "serde" version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" [[package]] name = "serde_cbor" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", + "half", + "serde", ] [[package]] name = "serde_derive" version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" dependencies = [ - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ - "itoa 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 1.0.2", + "ryu", + "serde", ] [[package]] name = "slab" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "socket2" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] name = "syn" version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-ident 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_json", ] [[package]] name = "tokio" version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ - "bytes 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", ] [[package]] name = "tokio-macros" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "tokio-util" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 1.19.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "log", + "pin-project-lite", + "tokio", ] [[package]] name = "unicode-ident" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "unicode-width" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "walkdir" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ - "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi", + "winapi-util", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ - "bumpalo 3.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ - "proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "web-sys" version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ - "js-sys 0.3.58 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys", + "wasm-bindgen", ] [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.12" dependencies = [ - "criterion 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 1.19.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion", + "futures", + "tokio", + "tokio-util", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", - "windows_i686_gnu 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", - "windows_i686_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", - "windows_x86_64_gnu 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", - "windows_x86_64_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -"checksum bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -"checksum bstr 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -"checksum bumpalo 3.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" -"checksum bytes 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -"checksum cast 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -"checksum cast 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -"checksum clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -"checksum criterion 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -"checksum criterion-plot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" -"checksum crossbeam-channel 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" -"checksum crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -"checksum crossbeam-epoch 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" -"checksum crossbeam-utils 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" -"checksum csv 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -"checksum csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -"checksum either 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" -"checksum futures 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" -"checksum futures-channel 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" -"checksum futures-core 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" -"checksum futures-io 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" -"checksum futures-sink 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" -"checksum futures-task 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" -"checksum futures-util 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" -"checksum half 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -"checksum hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -"checksum itertools 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -"checksum itoa 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" -"checksum itoa 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" -"checksum js-sys 0.3.58 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.126 (registry+https://github.com/rust-lang/crates.io-index)" = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" -"checksum log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -"checksum memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -"checksum memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -"checksum mio 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" -"checksum num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -"checksum num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -"checksum once_cell 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" -"checksum oorandom 11.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -"checksum pin-project-lite 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" -"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -"checksum plotters 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" -"checksum plotters-backend 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" -"checksum plotters-svg 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" -"checksum proc-macro2 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" -"checksum quote 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" -"checksum rayon 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" -"checksum rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" -"checksum regex 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" -"checksum regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -"checksum regex-syntax 0.6.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" -"checksum rustc_version 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -"checksum ryu 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" -"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum semver 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" -"checksum serde 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)" = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" -"checksum serde_cbor 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -"checksum serde_derive 1.0.138 (registry+https://github.com/rust-lang/crates.io-index)" = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" -"checksum serde_json 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" -"checksum slab 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" -"checksum socket2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -"checksum syn 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum tinytemplate 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -"checksum tokio 1.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" -"checksum tokio-macros 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" -"checksum tokio-util 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -"checksum unicode-ident 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" -"checksum unicode-width 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -"checksum walkdir 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -"checksum wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -"checksum wasm-bindgen 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" -"checksum wasm-bindgen-backend 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" -"checksum wasm-bindgen-macro 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" -"checksum wasm-bindgen-macro-support 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" -"checksum wasm-bindgen-shared 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)" = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" -"checksum web-sys 0.3.58 (registry+https://github.com/rust-lang/crates.io-index)" = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" -"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum windows-sys 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -"checksum windows_aarch64_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" -"checksum windows_i686_gnu 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" -"checksum windows_i686_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" -"checksum windows_x86_64_gnu 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" -"checksum windows_x86_64_msvc 0.36.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -12,20 +12,36 @@ [package] edition = "2018" name = "weezl" -version = "0.1.8" +version = "0.1.12" authors = ["The image-rs Developers"] +build = false exclude = ["benches/*.lzw"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Fast LZW compression and decompression." documentation = "https://docs.rs/weezl" readme = "README.md" license = "MIT OR Apache-2.0" -repository = "https://github.com/image-rs/lzw" +repository = "https://github.com/image-rs/weezl" [package.metadata.docs.rs] all-features = true +[features] +alloc = [] +async = [ + "futures", + "std", +] +default = ["std"] +std = ["alloc"] + [lib] name = "weezl" +path = "src/lib.rs" bench = false [[bin]] @@ -36,33 +52,45 @@ [[example]] name = "lzw-compress" +path = "examples/lzw-compress.rs" required-features = ["std"] [[example]] name = "lzw-decompress" +path = "examples/lzw-decompress.rs" required-features = ["std"] [[test]] name = "async" +path = "tests/async.rs" required-features = [ "async", "std", ] [[test]] +name = "end_of_buffer" +path = "tests/end_of_buffer.rs" +required-features = ["alloc"] + +[[test]] +name = "implicit_reset" +path = "tests/implicit_reset.rs" +required-features = ["std"] + +[[test]] name = "roundtrip" +path = "tests/roundtrip.rs" required-features = ["std"] [[test]] name = "roundtrip_vec" +path = "tests/roundtrip_vec.rs" required-features = ["alloc"] -[[test]] -name = "implicit_reset" -required-features = ["std"] - [[bench]] name = "msb8" +path = "benches/msb8.rs" harness = false required-features = ["std"] @@ -90,12 +118,3 @@ version = "0.6.2" features = ["compat"] default-features = false - -[features] -alloc = [] -async = [ - "futures", - "std", -] -default = ["std"] -std = ["alloc"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,90 @@ +[package] +name = "weezl" +version = "0.1.12" +license = "MIT OR Apache-2.0" +description = "Fast LZW compression and decompression." +authors = ["The image-rs Developers"] +readme = "README.md" +repository = "https://github.com/image-rs/weezl" +documentation = "https://docs.rs/weezl" +edition = "2018" +exclude = ["benches/*.lzw"] + +[lib] +name = "weezl" +bench = false + +[dependencies.futures] +optional = true +version = "0.3.12" +default-features = false +features = ["std"] + +[dev-dependencies] +criterion = "0.3.1" +[dev-dependencies.tokio] +version = "1" +default-features = false +features = ["macros", "io-util", "net", "rt", "rt-multi-thread"] +[dev-dependencies.tokio-util] +version = "0.6.2" +default-features = false +features = ["compat"] + +[features] +default = ["std"] +# Enable usage of the standard library and in particular any interface that +# requires the io interfaces `Read` and `Write`. +std = ["alloc"] +# Enable usage of the `alloc` crate. You should always have this feature +# enabled. Without this feature neither the encoder nor the decoder exists. +# This is purely a reservation for future possibilities. +alloc = [] +# Enable usage of `async` through `futures`. This is basically the blocker +# for `1.0` as we may track its version. Note that this negates no_std right +# now but implicitly through being required from futures. We also use the +# `std::io::Error` interface. Note that this features is NOT supported on +# 1.34.2 but only on stable. +async = ["futures", "std"] + +[[bin]] +name = "lzw" +path = "bin/lzw.rs" +bench = false +required-features = ["std"] + +[[bench]] +name = "msb8" +harness = false +required-features = ["std"] + +[[example]] +name = "lzw-compress" +required-features = ["std"] + +[[example]] +name = "lzw-decompress" +required-features = ["std"] + +[[test]] +name = "async" +required-features = ["async", "std"] + +[[test]] +name = "roundtrip" +required-features = ["std"] + +[[test]] +name = "roundtrip_vec" +required-features = ["alloc"] + +[[test]] +name = "implicit_reset" +required-features = ["std"] + +[[test]] +name = "end_of_buffer" +required-features = ["alloc"] + +[package.metadata.docs.rs] +all-features = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/Changes.md clamav-1.4.6+dfsg/.cargo/vendor/weezl/Changes.md --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/Changes.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/Changes.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,36 @@ +## Version 0.1.12 + +- Further adjusted a debug assertion for TIFF compatibility. It still had one + of its OR conditions formulated incorrectly, relying on equality of the + code word mask and the size switch code. In TIFF we hit the limit of the + code dictionary (all 12-bit words) one code later than we would detect a + code switch that we need to ignore. + +## Version 0.1.11 + +- Adjusted a debug assertion that handled 1-bit code sizes incorrectly in the + decoder (relevant for TIFF but non-standard for GIF). In that case the size + switch semantics are a bit messy. + +## Version 0.1.10 + +- Reverted changes made in 0.1.9 to the behavior of the decoder under non + libtiff-compatibility mode. Trying to read the decoder with an empty output + buffer will at least inspect the next symbol and either error or indicate the + end-of-stream accordingly. + +## Version 0.1.9 (yanked) + +- Increased decoding throughput by 3—30% depending on CPU and data. +- Added `{encode,decode}::Configuration` as builder types for their respective + module. They can be cheaply cloned. +- Added `decode::Configuration::with_yield_on_full_buffer` to explicitly opt-in + to libtiff compatibility. The decoder will not read or interpret further + symbols of the decoding stream when the output buffer is full. This enables a + caller to stop fetching symbols and elide an end of stream marker based on + out-of-band length information. The decoder might otherwise error, trying to + interpret data that does not belong to the stream. + ## Version 0.1.8 - Fixed incorrect state after `Decoder::reset` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/src/decode.rs clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/decode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/src/decode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/decode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -86,6 +86,13 @@ struct Link { prev: Code, byte: u8, + first: u8, +} + +#[derive(Clone)] +struct DerivationBase { + code: Code, + first: u8, } #[derive(Default)] @@ -116,17 +123,24 @@ fn new(min_size: u8) -> Self; fn reset(&mut self, min_size: u8); fn bump_code_size(&mut self); + /// Retrieve the next symbol, refilling if necessary. fn next_symbol(&mut self, inp: &mut &[u8]) -> Option; /// Refill the internal buffer. fn refill_bits(&mut self, inp: &mut &[u8]); - /// Get the next buffered code word. - fn get_bits(&mut self) -> Option; + + fn peek_bits(&self, code: &mut [Code; BURST]) -> usize; + fn consume_bits(&mut self, code_cnt: u8); + fn max_code(&self) -> Code; fn code_size(&self) -> u8; } -struct DecodeState { +trait CodegenConstants { + const YIELD_ON_FULL: bool; +} + +struct DecodeState { /// The original minimum code size. min_size: u8, /// The table of decoded codes. @@ -134,7 +148,7 @@ /// The buffer of decoded data. buffer: Buffer, /// The link which we are still decoding and its original code. - last: Option<(Code, Link)>, + last: Option, /// The next code entry. next_code: Code, /// Code to reset all tables. @@ -149,8 +163,15 @@ implicit_reset: bool, /// The buffer for decoded words. code_buffer: CodeBuffer, + #[allow(dead_code)] + constants: core::marker::PhantomData, } +// We have a buffer of 64 bits. So at max size at most 5 units can be read at once without +// refilling the buffer. At smaller code sizes there are more. We tune for 6 here, by slight +// experimentation. This may be an architecture dependent constant. +const BURST: usize = 6; + struct Buffer { bytes: Box<[u8]>, read_mark: usize, @@ -162,6 +183,65 @@ depths: Vec, } +/// Describes the static parameters for creating a decoder. +#[derive(Clone, Debug)] +pub struct Configuration { + order: BitOrder, + size: u8, + tiff: bool, + yield_on_full: bool, +} + +impl Configuration { + /// Create a configuration to decode with the specified bit order and symbol size. + pub fn new(order: BitOrder, size: u8) -> Self { + super::assert_decode_size(size); + Configuration { + order, + size, + tiff: false, + yield_on_full: false, + } + } + + /// Create a configuration for a TIFF compatible decoder. + pub fn with_tiff_size_switch(order: BitOrder, size: u8) -> Self { + super::assert_decode_size(size); + Configuration { + order, + size, + tiff: true, + yield_on_full: false, + } + } + + /// Immediately yield to the caller when the decoder buffer is full. + /// + /// This can be used for `libtiff` compatibility. It will use a "relaxed" stream interpretation + /// that need not contain an explicit EOF. Instead, the decoder is expected to stop fetching + /// symbols when some out-of-band specified length of the decoded text has been reached. The + /// caller indicates this maximum length through the available output buffer space. + /// + /// Symbols afterwards must not be expected to be valid. On filling the output buffer space + /// completely, the decoder will return immediately to the caller instead of potentially + /// interpreting the following bit-stream (and returning an error on doing so). + /// + /// Default: `false`. + pub fn with_yield_on_full_buffer(self, do_yield: bool) -> Self { + Configuration { + yield_on_full: do_yield, + ..self + } + } + + /// Create a new decoder with the define configuration. + pub fn build(self) -> Decoder { + Decoder { + state: Decoder::from_configuration(&self), + } + } +} + impl Decoder { /// Create a new decoder with the specified bit order and symbol size. /// @@ -173,14 +253,7 @@ /// /// The `size` needs to be in the interval `0..=12`. pub fn new(order: BitOrder, size: u8) -> Self { - type Boxed = Box; - super::assert_decode_size(size); - let state = match order { - BitOrder::Lsb => Box::new(DecodeState::::new(size)) as Boxed, - BitOrder::Msb => Box::new(DecodeState::::new(size)) as Boxed, - }; - - Decoder { state } + Configuration::new(order, size).build() } /// Create a TIFF compatible decoder with the specified bit order and symbol size. @@ -193,22 +266,50 @@ /// /// The `size` needs to be in the interval `0..=12`. pub fn with_tiff_size_switch(order: BitOrder, size: u8) -> Self { + Configuration::with_tiff_size_switch(order, size).build() + } + + fn from_configuration(configuration: &Configuration) -> Box { + struct NoYield; + struct YieldOnFull; + + impl CodegenConstants for NoYield { + const YIELD_ON_FULL: bool = false; + } + + impl CodegenConstants for YieldOnFull { + const YIELD_ON_FULL: bool = true; + } + type Boxed = Box; - super::assert_decode_size(size); - let state = match order { - BitOrder::Lsb => { - let mut state = Box::new(DecodeState::::new(size)); - state.is_tiff = true; + match (configuration.order, configuration.yield_on_full) { + (BitOrder::Lsb, false) => { + let mut state = + Box::new(DecodeState::::new(configuration.size)); + state.is_tiff = configuration.tiff; state as Boxed } - BitOrder::Msb => { - let mut state = Box::new(DecodeState::::new(size)); - state.is_tiff = true; + (BitOrder::Lsb, true) => { + let mut state = Box::new(DecodeState::::new( + configuration.size, + )); + state.is_tiff = configuration.tiff; state as Boxed } - }; - - Decoder { state } + (BitOrder::Msb, false) => { + let mut state = + Box::new(DecodeState::::new(configuration.size)); + state.is_tiff = configuration.tiff; + state as Boxed + } + (BitOrder::Msb, true) => { + let mut state = Box::new(DecodeState::::new( + configuration.size, + )); + state.is_tiff = configuration.tiff; + state as Boxed + } + } } /// Decode some bytes from `inp` and write result to `out`. @@ -554,7 +655,7 @@ #[path = "decode_into_async.rs"] mod impl_decode_into_async; -impl DecodeState { +impl DecodeState { fn new(min_size: u8) -> Self { DecodeState { min_size, @@ -568,6 +669,7 @@ is_tiff: false, implicit_reset: true, code_buffer: CodeBuffer::new(min_size), + constants: core::marker::PhantomData, } } @@ -584,7 +686,7 @@ } } -impl Stateful for DecodeState { +impl Stateful for DecodeState { fn has_ended(&self) -> bool { self.has_ended } @@ -685,7 +787,10 @@ self.buffer.fill_reconstruct(&self.table, init_code); let link = self.table.at(init_code).clone(); - code_link = Some((init_code, link)); + code_link = Some(DerivationBase { + code: init_code, + first: link.first, + }); } else { // We require an explicit reset. status = Err(LzwError::InvalidCode); @@ -694,7 +799,10 @@ // Reconstruct the first code in the buffer. self.buffer.fill_reconstruct(&self.table, init_code); let link = self.table.at(init_code).clone(); - code_link = Some((init_code, link)); + code_link = Some(DerivationBase { + code: init_code, + first: link.first, + }); } } } @@ -704,14 +812,16 @@ }; // Track an empty `burst` (see below) means we made no progress. - let mut burst_required_for_progress = false; + let mut have_yet_to_decode_data = false; + // Restore the previous state, if any. - if let Some((code, link)) = code_link.take() { - code_link = Some((code, link)); + if code_link.is_some() { let remain = self.buffer.buffer(); // Check if we can fully finish the buffer. if remain.len() > out.len() { if out.is_empty() { + // This also implies the buffer is _not_ empty and we will not enter any + // decoding loop. status = Ok(LzwStatus::NoProgress); } else { out.copy_from_slice(&remain[..out.len()]); @@ -720,210 +830,297 @@ } } else if remain.is_empty() { status = Ok(LzwStatus::NoProgress); - burst_required_for_progress = true; + have_yet_to_decode_data = true; } else { let consumed = remain.len(); out[..consumed].copy_from_slice(remain); self.buffer.consume(consumed); out = &mut out[consumed..]; - burst_required_for_progress = false; + have_yet_to_decode_data = false; } } - // The tracking state for a burst. - // These are actually initialized later but compiler wasn't smart enough to fully optimize - // out the init code so that appears outside th loop. - // TODO: maybe we can make it part of the state but it's dubious if that really gives a - // benefit over stack usage? Also the slices stored here would need some treatment as we - // can't infect the main struct with a lifetime. - let mut burst = [0; 6]; - let mut bytes = [0u16; 6]; - let mut target: [&mut [u8]; 6] = Default::default(); // A special reference to out slice which holds the last decoded symbol. let mut last_decoded: Option<&[u8]> = None; - while let Some((mut code, mut link)) = code_link.take() { - if out.is_empty() && !self.buffer.buffer().is_empty() { - code_link = Some((code, link)); - break; - } + if self.buffer.buffer().is_empty() { + // Hot loop that writes data to the output as long as we can do so directly from the + // input stream. As an invariant of this block we did not need to use the buffer to + // store a decoded code word. Testing the condition ahead of time avoids a test in the + // loop body since every code path where the buffer is filled already breaks. + // + // In a previous iteration of the code we trusted compiler optimization to work this + // out but it seems that it does not. Another edit hidden behind some performance work + // then edited out the check, inadvertently changing the behavior for callers that + // relied on being able to provide an empty output buffer and still receiving a useful + // signal about the state of the stream. + + // A burst is a sequence of code words that are independently decoded, i.e. they do not + // change the state of the decoder in ways that would influence the interpretation of + // each other. That is: they are not special symbols, they do not make us increase the + // code size, they are each codes already in the tree before the burst. + // + // The tracking state for a burst. These are actually initialized later but compiler + // wasn't smart enough to fully optimize out the init code so that appears outside the + // loop. + let mut burst = [0; BURST]; + let mut burst_byte_len = [0u16; BURST]; + let mut burst_byte = [0u8; BURST]; + let mut target: [&mut [u8]; BURST] = Default::default(); + + loop { + // In particular, we *also* break if the output buffer is still empty. Especially + // when the output parameter was an empty slice, we must try to fetch at least one + // code but with YIELD_ON_FULL we do not. + if CgC::YIELD_ON_FULL && out.is_empty() { + break; + } - let mut burst_size = 0; - // Ensure the code buffer is full, we're about to request some codes. - // Note that this also ensures at least one code is in the buffer if any input is left. - self.refill_bits(&mut inp); - // A burst is a sequence of decodes that are completely independent of each other. This - // is the case if neither is an end code, a clear code, or a next code, i.e. we have - // all of them in the decoding table and thus known their depths, and additionally if - // we can decode them directly into the output buffer. - for b in &mut burst { - // TODO: does it actually make a perf difference to avoid reading new bits here? - *b = match self.get_bits() { - None => break, - Some(code) => code, + let mut deriv = match code_link.take() { + Some(link) => link, + None => { + // TODO: we do not need to break here. This does not indicate that the buffer + // has been filled, rather it indicates we have reset the state. The next code + // should be part of the initial alphabet. However the first code is special in + // the sense of not creating a new code itself. This is handled correctly in + // the initialization prior to the loop; and in particular that handling as + // written currently relies on putting it into the buffer; so handling it we + // would need to ensure that either the buffer is fully cleared after its use, + // or use another implementation of handling that first code. + break; + } }; - // We can commit the previous burst code, and will take a slice from the output - // buffer. This also avoids the bounds check in the tight loop later. - if burst_size > 0 { - let len = bytes[burst_size - 1]; - let (into, tail) = out.split_at_mut(usize::from(len)); - target[burst_size - 1] = into; - out = tail; + // Ensure the code buffer is full, we're about to request some codes. + // Note that this also ensures at least one code is in the buffer if any input is left. + self.refill_bits(&mut inp); + let cnt = self.code_buffer.peek_bits(&mut burst); + + // No code left in the buffer, and no more bytes to refill the buffer. + if cnt == 0 { + if have_yet_to_decode_data { + status = Ok(LzwStatus::NoProgress); + } + + code_link = Some(deriv); + break; } - // Check that we don't overflow the code size with all codes we burst decode. - if let Some(potential_code) = self.next_code.checked_add(burst_size as u16) { + debug_assert!( + // When the table is full, we have a max code above the size switch. + self.table.inner.len() >= MAX_ENTRIES - usize::from(self.is_tiff) + // When the code size is 2 we have a bit code: (0, 1, CLS, EOF). Then the + // computed next_code is 4 which already exceeds the bit width from the start. + // Then we will immediately switch code size after this code. + // + // TODO: this is the reason for some saturating and non-sharp comparisons in + // the code below. Maybe it makes sense to revisit turning this into a compile + // time choice? + || (self.code_buffer.code_size() == 1 && self.next_code < 4) + || (self.code_buffer.code_size() == 2 && self.next_code == 4) + || self.code_buffer.max_code() - Code::from(self.is_tiff) >= self.next_code, + "Table: {}, code_size: {}, next_code: {}, table_condition: {}", + self.table.is_full(), + self.code_buffer.code_size(), + self.next_code, + self.code_buffer.max_code() - Code::from(self.is_tiff), + ); + + let mut burst_size = 0; + let left_before_size_switch = (self.code_buffer.max_code() + - Code::from(self.is_tiff)) + .saturating_sub(self.next_code); + + // A burst is a sequence of decodes that are completely independent of each other. This + // is the case if neither is an end code, a clear code, or a next code, i.e. we have + // all of them in the decoding table and thus known their depths, and additionally if + // we can decode them directly into the output buffer. + for b in &burst[..cnt] { + // We can commit the previous burst code, and will take a slice from the output + // buffer. This also avoids the bounds check in the tight loop later. + if burst_size > 0 { + let len = burst_byte_len[burst_size - 1]; + let (into, tail) = out.split_at_mut(usize::from(len)); + target[burst_size - 1] = into; + out = tail; + } + + // Check that we don't overflow the code size with all codes we burst decode. burst_size += 1; - if potential_code == self.code_buffer.max_code() - Code::from(self.is_tiff) { + + if burst_size > usize::from(left_before_size_switch) { break; } - } else { - // next_code overflowed - break; - } - // A burst code can't be special. - if *b == self.clear_code || *b == self.end_code || *b >= self.next_code { - break; - } + let read_code = *b; - // Read the code length and check that we can decode directly into the out slice. - let len = self.table.depths[usize::from(*b)]; - if out.len() < usize::from(len) { - break; - } + // A burst code can't be special. + if read_code == self.clear_code + || read_code == self.end_code + || read_code >= self.next_code + { + break; + } - bytes[burst_size - 1] = len; - } + // Read the code length and check that we can decode directly into the out slice. + let len = self.table.depths[usize::from(read_code)]; - // No code left, and no more bytes to fill the buffer. - if burst_size == 0 { - if burst_required_for_progress { - status = Ok(LzwStatus::NoProgress); + if out.len() < usize::from(len) { + break; + } + + // We do exactly one more code (the one being inspected in the current iteration) + // after the 'burst'. When we want to break decoding precisely on the supplied + // buffer, we check if this is the last code to be decoded into it. + if CgC::YIELD_ON_FULL { + if out.len() == usize::from(len) { + break; + } + } + + burst_byte_len[burst_size - 1] = len; } - code_link = Some((code, link)); - break; - } - burst_required_for_progress = false; - // Note that the very last code in the burst buffer doesn't actually belong to the - // burst itself. TODO: sometimes it could, we just don't differentiate between the - // breaks and a loop end condition above. That may be a speed advantage? - let (&new_code, burst) = burst[..burst_size].split_last().unwrap(); - - // The very tight loop for restoring the actual burst. - for (&burst, target) in burst.iter().zip(&mut target[..burst_size - 1]) { - let cha = self.table.reconstruct(burst, target); - // TODO: this pushes into a Vec, maybe we can make this cleaner. - // Theoretically this has a branch and llvm tends to be flaky with code layout for - // the case of requiring an allocation (which can't occur in practice). - let new_link = self.table.derive(&link, cha, code); - self.next_code += 1; - code = burst; - link = new_link; - } + self.code_buffer.consume_bits(burst_size as u8); + have_yet_to_decode_data = false; - // Update the slice holding the last decoded word. - if let Some(new_last) = target[..burst_size - 1].last_mut() { - let slice = core::mem::replace(new_last, &mut []); - last_decoded = Some(&*slice); - } + // Note that the very last code in the burst buffer doesn't actually belong to the + // burst itself. TODO: sometimes it could, we just don't differentiate between the + // breaks and a loop end condition above. That may be a speed advantage? + let (&new_code, burst) = burst[..burst_size].split_last().unwrap(); + + // The very tight loop for restoring the actual burst. These can be reconstructed in + // parallel since none of them depend on a prior constructed. Only the derivation of + // new codes is not parallel. There are no size changes here either. + let burst_targets = &mut target[..burst_size - 1]; - // Now handle the special codes. - if new_code == self.clear_code { - self.reset_tables(); - last_decoded = None; - continue; - } + if !self.table.is_full() { + self.next_code += burst_targets.len() as u16; + } - if new_code == self.end_code { - self.has_ended = true; - status = Ok(LzwStatus::Done); - last_decoded = None; - break; - } + for ((&burst, target), byte) in + burst.iter().zip(&mut *burst_targets).zip(&mut burst_byte) + { + *byte = self.table.reconstruct(burst, target); + } - if new_code > self.next_code { - status = Err(LzwError::InvalidCode); - last_decoded = None; - break; - } + self.table.derive_burst(&mut deriv, burst, &burst_byte[..]); - let required_len = if new_code == self.next_code { - self.table.depths[usize::from(code)] + 1 - } else { - self.table.depths[usize::from(new_code)] - }; + // Now handle the special codes. + if new_code == self.clear_code { + self.reset_tables(); + last_decoded = None; + // Restarts in the next call to the entry point. + break; + } - let cha; - let is_in_buffer; - // Check if we will need to store our current state into the buffer. - if usize::from(required_len) > out.len() { - is_in_buffer = true; - if new_code == self.next_code { - // last_decoded will be Some if we have restored any code into the out slice. - // Otherwise it will still be present in the buffer. - if let Some(last) = last_decoded.take() { - self.buffer.bytes[..last.len()].copy_from_slice(last); - self.buffer.write_mark = last.len(); - self.buffer.read_mark = last.len(); - } + if new_code == self.end_code { + self.has_ended = true; + status = Ok(LzwStatus::Done); + last_decoded = None; + break; + } - cha = self.buffer.fill_cscsc(); - } else { - // Restore the decoded word into the buffer. + if new_code > self.next_code { + status = Err(LzwError::InvalidCode); last_decoded = None; - cha = self.buffer.fill_reconstruct(&self.table, new_code); + break; } - } else { - is_in_buffer = false; - let (target, tail) = out.split_at_mut(usize::from(required_len)); - out = tail; - - if new_code == self.next_code { - // Reconstruct high. - let source = match last_decoded.take() { - Some(last) => last, - None => &self.buffer.bytes[..self.buffer.write_mark], - }; - cha = source[0]; - target[..source.len()].copy_from_slice(source); - target[source.len()..][0] = source[0]; + + let required_len = if new_code == self.next_code { + self.table.depths[usize::from(deriv.code)] + 1 } else { - cha = self.table.reconstruct(new_code, target); + self.table.depths[usize::from(new_code)] + }; + + // We need the decoded data of the new code if it is the `next_code`. This is the + // special case of LZW decoding that is demonstrated by `banana` (or form cScSc). In + // all other cases we only need the first character of the decoded data. + let have_next_code = new_code == self.next_code; + + // Update the slice holding the last decoded word. + if have_next_code { + // If we did not have any burst code, we still hold that slice in the buffer. + if let Some(new_last) = target[..burst_size - 1].last_mut() { + let slice = core::mem::replace(new_last, &mut []); + last_decoded = Some(&*slice); + } } - // A new decoded word. - last_decoded = Some(target); - } + let cha; + let is_in_buffer = usize::from(required_len) > out.len(); + // Check if we will need to store our current state into the buffer. + if is_in_buffer { + if have_next_code { + // last_decoded will be Some if we have restored any code into the out slice. + // Otherwise it will still be present in the buffer. + if let Some(last) = last_decoded.take() { + self.buffer.bytes[..last.len()].copy_from_slice(last); + self.buffer.write_mark = last.len(); + self.buffer.read_mark = last.len(); + } - let new_link; - // Each newly read code creates one new code/link based on the preceding code if we - // have enough space to put it there. - if !self.table.is_full() { - let link = self.table.derive(&link, cha, code); + cha = self.buffer.fill_cscsc(); + } else { + // Restore the decoded word into the buffer. + last_decoded = None; + cha = self.buffer.fill_reconstruct(&self.table, new_code); + } + } else { + let (target, tail) = out.split_at_mut(usize::from(required_len)); + out = tail; - if self.next_code == self.code_buffer.max_code() - Code::from(self.is_tiff) - && self.code_buffer.code_size() < MAX_CODESIZE - { - self.bump_code_size(); + if have_next_code { + // Reconstruct high. + let source = match last_decoded.take() { + Some(last) => last, + None => &self.buffer.bytes[..self.buffer.write_mark], + }; + + // We don't *actually* expect the unwrap to happen. Each source is at least 1 + // byte long. But llvm doesn't know this (too much indirect loads and cases). + cha = source.get(0).map(|x| *x).unwrap_or(0); + target[..source.len()].copy_from_slice(source); + target[source.len()..][0] = cha; + } else { + cha = self.table.reconstruct(new_code, target); + } + + // A new decoded word. + last_decoded = Some(target); } - self.next_code += 1; - new_link = link; - } else { - // It's actually quite likely that the next code will be a reset but just in case. - // FIXME: this path hasn't been tested very well. - new_link = link.clone(); - } + // Each newly read code creates one new code/link based on the preceding code if we + // have enough space to put it there. + if !self.table.is_full() { + self.table.derive(&deriv, cha); + + if self.next_code >= self.code_buffer.max_code() - Code::from(self.is_tiff) + && self.code_buffer.code_size() < MAX_CODESIZE + { + self.bump_code_size(); + } - // store the information on the decoded word. - code_link = Some((new_code, new_link)); + self.next_code += 1; + } - // Can't make any more progress with decoding. - if is_in_buffer { - break; + // store the information on the decoded word. + code_link = Some(DerivationBase { + code: new_code, + first: cha, + }); + + // Can't make any more progress with decoding. + // + // We have more data buffered but not enough space to put it? We want fetch a next + // symbol if possible as in the case of it being a new symbol we can refer to the + // buffered output as the source for that symbol's meaning and do a memcpy. + // + // Since this test is after decoding at least one code, we can now check for an + // empty buffer and still guarantee progress when one was passed as a parameter. + if is_in_buffer || out.is_empty() { + break; + } } } @@ -932,6 +1129,7 @@ if let Some(tail) = last_decoded { self.buffer.bytes[..tail.len()].copy_from_slice(tail); self.buffer.write_mark = tail.len(); + // Mark the full buffer as having been consumed. self.buffer.read_mark = tail.len(); } @@ -954,7 +1152,7 @@ } } -impl DecodeState { +impl DecodeState { fn next_symbol(&mut self, inp: &mut &[u8]) -> Option { self.code_buffer.next_symbol(inp) } @@ -966,10 +1164,6 @@ fn refill_bits(&mut self, inp: &mut &[u8]) { self.code_buffer.refill_bits(inp) } - - fn get_bits(&mut self) -> Option { - self.code_buffer.get_bits() - } } impl CodeBuffer for MsbBuffer { @@ -992,7 +1186,15 @@ self.refill_bits(inp); } - self.get_bits() + if self.bits < self.code_size { + return None; + } + + let mask = u64::from(self.code_mask); + let rotbuf = self.bit_buffer.rotate_left(self.code_size.into()); + self.bit_buffer = rotbuf & !mask; + self.bits -= self.code_size; + Some((rotbuf & mask) as u16) } fn bump_code_size(&mut self) { @@ -1020,16 +1222,42 @@ self.bits += new_bits; } - fn get_bits(&mut self) -> Option { - if self.bits < self.code_size { - return None; + fn peek_bits(&self, code: &mut [Code; BURST]) -> usize { + let mut bit_buffer = self.bit_buffer; + let mask = u64::from(self.code_mask); + let mut consumed = 0; + let mut cnt = 0; + + for b in code { + let consumed_after = consumed + self.code_size; + if consumed_after > self.bits { + break; + } + + cnt += 1; + consumed = consumed_after; + + let rotbuf = bit_buffer.rotate_left(self.code_size.into()); + *b = (rotbuf & mask) as u16; + // The read bits are 'appended' but we never interpret those appended bits. + bit_buffer = rotbuf; } - let mask = u64::from(self.code_mask); - let rotbuf = self.bit_buffer.rotate_left(self.code_size.into()); - self.bit_buffer = rotbuf & !mask; - self.bits -= self.code_size; - Some((rotbuf & mask) as u16) + cnt + } + + fn consume_bits(&mut self, code_cnt: u8) { + let bits = self.code_size * code_cnt; + debug_assert!(bits <= self.bits); + + if bits >= self.bits { + self.bit_buffer = 0; + } else { + // bits < self.bits so this must be smaller than the number size. + self.bit_buffer = self.bit_buffer << bits; + } + + self.bits = self.bits.wrapping_sub(bits); } fn max_code(&self) -> Code { @@ -1061,7 +1289,15 @@ self.refill_bits(inp); } - self.get_bits() + if self.bits < self.code_size { + return None; + } + + let mask = u64::from(self.code_mask); + let code = self.bit_buffer & mask; + self.bit_buffer >>= self.code_size; + self.bits -= self.code_size; + Some(code as u16) } fn bump_code_size(&mut self) { @@ -1089,16 +1325,40 @@ self.bits += new_bits; } - fn get_bits(&mut self) -> Option { - if self.bits < self.code_size { - return None; + fn peek_bits(&self, code: &mut [Code; BURST]) -> usize { + let mut bit_buffer = self.bit_buffer; + let mask = u64::from(self.code_mask); + let mut consumed = 0; + let mut cnt = 0; + + for b in code { + let consumed_after = consumed + self.code_size; + if consumed_after > self.bits { + break; + } + + cnt += 1; + consumed = consumed_after; + + *b = (bit_buffer & mask) as u16; + bit_buffer = bit_buffer >> self.code_size; } - let mask = u64::from(self.code_mask); - let code = self.bit_buffer & mask; - self.bit_buffer >>= self.code_size; - self.bits -= self.code_size; - Some(code as u16) + cnt + } + + fn consume_bits(&mut self, code_cnt: u8) { + let bits = self.code_size * code_cnt; + debug_assert!(bits <= self.bits); + + if bits >= self.bits { + self.bit_buffer = 0; + } else { + // bits < self.bits so this must be smaller than the number size. + self.bit_buffer = self.bit_buffer >> bits; + } + + self.bits = self.bits.wrapping_sub(bits); } fn max_code(&self) -> Code { @@ -1195,17 +1455,40 @@ self.inner.len() >= MAX_ENTRIES } - fn derive(&mut self, from: &Link, byte: u8, prev: Code) -> Link { - let link = from.derive(byte, prev); - let depth = self.depths[usize::from(prev)] + 1; - self.inner.push(link.clone()); + fn derive(&mut self, from: &DerivationBase, byte: u8) { + let link = from.derive(byte); + let depth = self.depths[usize::from(from.code)] + 1; + self.inner.push(link); self.depths.push(depth); - link + } + + // Derive multiple codes in a row, where each base is guaranteed to already exist. + fn derive_burst(&mut self, from: &mut DerivationBase, burst: &[Code], first: &[u8]) { + let mut depth_of = from.code; + // Note that false data dependency we want to get rid of! + // TODO: this pushes into a Vec, maybe we can make this cleaner. + for &code in burst { + let depth = self.depths[usize::from(depth_of)] + 1; + self.depths.push(depth); + depth_of = code; + } + + // Llvm tends to be flaky with code layout for the case of requiring an allocation. It's + // not clear if that can occur in practice but it relies on iterator size hint.. + let extensions = burst.iter().zip(first); + self.inner.extend(extensions.map(|(&code, &first)| { + let link = from.derive(first); + from.code = code; + from.first = first; + link + })); } fn reconstruct(&self, code: Code, out: &mut [u8]) -> u8 { let mut code_iter = code; let table = &self.inner[..=usize::from(code)]; + let first = table[usize::from(code)].first; + let len = code_iter; for ch in out.iter_mut().rev() { //(code, cha) = self.table[k as usize]; @@ -1216,19 +1499,30 @@ code_iter = core::cmp::min(len, entry.prev); *ch = entry.byte; } - out[0] + + first } } impl Link { fn base(byte: u8) -> Self { - Link { prev: 0, byte } + Link { + prev: 0, + byte, + first: byte, + } } +} +impl DerivationBase { // TODO: this has self type to make it clear we might depend on the old in a future // optimization. However, that has no practical purpose right now. - fn derive(&self, byte: u8, prev: Code) -> Self { - Link { prev, byte } + fn derive(&self, byte: u8) -> Link { + Link { + prev: self.code, + byte, + first: self.first, + } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/src/encode.rs clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/encode.rs --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/src/encode.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/src/encode.rs 2006-07-24 01:21:28.000000000 +0000 @@ -176,6 +176,51 @@ char_continuation: [Code; 256], } +/// Describes the static parameters for creating a decoder. +#[derive(Clone, Debug)] +pub struct Configuration { + order: BitOrder, + size: u8, + tiff: bool, +} + +impl Configuration { + /// Create a configuration to decode with the specified bit order and symbol size. + /// + /// # Panics + /// + /// The `size` needs to be in the interval `2..=12`. + pub fn new(order: BitOrder, size: u8) -> Self { + super::assert_encode_size(size); + Configuration { + order, + size, + tiff: false, + } + } + + /// Create a configuration for a TIFF compatible decoder. + /// + /// # Panics + /// + /// The `size` needs to be in the interval `2..=12`. + pub fn with_tiff_size_switch(order: BitOrder, size: u8) -> Self { + super::assert_encode_size(size); + Configuration { + order, + size, + tiff: true, + } + } + + /// Create a new decoder with the define configuration. + pub fn build(self) -> Encoder { + Encoder { + state: Encoder::from_configuration(&self), + } + } +} + impl Encoder { /// Create a new encoder with the specified bit order and symbol size. /// @@ -187,14 +232,7 @@ /// /// The `size` needs to be in the interval `2..=12`. pub fn new(order: BitOrder, size: u8) -> Self { - type Boxed = Box; - super::assert_encode_size(size); - let state = match order { - BitOrder::Lsb => Box::new(EncodeState::::new(size)) as Boxed, - BitOrder::Msb => Box::new(EncodeState::::new(size)) as Boxed, - }; - - Encoder { state } + Configuration::new(order, size).build() } /// Create a TIFF compatible encoder with the specified bit order and symbol size. @@ -207,22 +245,22 @@ /// /// The `size` needs to be in the interval `2..=12`. pub fn with_tiff_size_switch(order: BitOrder, size: u8) -> Self { - type Boxed = Box; - super::assert_encode_size(size); - let state = match order { + Configuration::with_tiff_size_switch(order, size).build() + } + + fn from_configuration(cfg: &Configuration) -> Box { + match cfg.order { BitOrder::Lsb => { - let mut state = Box::new(EncodeState::::new(size)); - state.is_tiff = true; - state as Boxed + let mut state = EncodeState::::new(cfg.size); + state.is_tiff = cfg.tiff; + Box::new(state) } BitOrder::Msb => { - let mut state = Box::new(EncodeState::::new(size)); - state.is_tiff = true; - state as Boxed + let mut state = EncodeState::::new(cfg.size); + state.is_tiff = cfg.tiff; + Box::new(state) } - }; - - Encoder { state } + } } /// Encode some bytes from `inp` into `out`. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/end_of_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/end_of_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/end_of_buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/end_of_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use weezl::{decode, BitOrder}; + +#[test] +fn stop_after_end_of_buffer() { + let inp = vec![0x00u8, 0x01, 0x02, 0xff]; + let mut decoder = decode::Configuration::new(BitOrder::Lsb, 7) + .with_yield_on_full_buffer(true) + .build(); + let mut out = vec![0u8, 0u8, 0u8]; + let status = decoder.decode_bytes(&inp, &mut out).status; + assert!(status.is_ok(), "{:?} {:?}", status, out); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/roundtrip.rs clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/roundtrip.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +use std::io; use std::{env, fs}; use weezl::{decode, encode, BitOrder}; @@ -8,59 +9,120 @@ } #[test] -fn roundtrip_all() { +fn roundtrip_all_lsb_tiny() { + roundtrip_all(BitOrder::Lsb, 1); +} + +#[test] +fn roundtrip_all_msb_tiny() { + roundtrip_all(BitOrder::Msb, 1); +} + +#[test] +fn roundtrip_all_lsb() { + roundtrip_all(BitOrder::Lsb, 1 << 20); +} + +#[test] +fn roundtrip_all_msb() { + roundtrip_all(BitOrder::Msb, 1 << 20); +} + +fn roundtrip_all(bit_order: BitOrder, max_io_len: usize) { let file = env::args().next().unwrap(); let data = fs::read(file).unwrap(); for &flavor in &[Flavor::Gif, Flavor::Tiff] { - for &bit_order in &[BitOrder::Lsb, BitOrder::Msb] { - for bit_width in 2..8 { - let data: Vec<_> = data - .iter() - .copied() - .map(|b| b & ((1 << bit_width) - 1)) - .collect(); - - println!("Roundtrip test {:?} {:?} {}", flavor, bit_order, bit_width); - assert_roundtrips(&*data, flavor, bit_width, bit_order); - } + for bit_width in 2..8 { + let data: Vec<_> = data + .iter() + .copied() + .map(|b| b & ((1 << bit_width) - 1)) + .collect(); + + let enc = match flavor { + Flavor::Gif => encode::Configuration::new, + Flavor::Tiff => encode::Configuration::with_tiff_size_switch, + }(bit_order, bit_width); + + let dec = match flavor { + Flavor::Gif => decode::Configuration::new, + Flavor::Tiff => decode::Configuration::with_tiff_size_switch, + }(bit_order, bit_width); + + let yielding = dec.clone().with_yield_on_full_buffer(true); + + println!("Roundtrip test {:?} {:?} {}", flavor, bit_order, bit_width); + assert_roundtrips(&*data, enc.clone(), dec, max_io_len); + + // Our encoder always passes an enclosed stream. So this must be the same. + assert_roundtrips(&*data, enc, yielding, max_io_len); } } } -fn assert_roundtrips(data: &[u8], flavor: Flavor, bit_width: u8, bit_order: BitOrder) { - let (c, d): ( - fn(BitOrder, u8) -> encode::Encoder, - fn(BitOrder, u8) -> decode::Decoder, - ) = match flavor { - Flavor::Gif => (encode::Encoder::new, decode::Decoder::new), - Flavor::Tiff => ( - encode::Encoder::with_tiff_size_switch, - decode::Decoder::with_tiff_size_switch, - ), +fn assert_roundtrips( + data: &[u8], + enc: encode::Configuration, + dec: decode::Configuration, + max_io_len: usize, +) { + let mut encoder = enc.clone().build(); + let mut writer = TinyWrite { + data: Vec::with_capacity(2 * data.len() + 40), + max_write_len: max_io_len, }; - let mut encoder = c(bit_order, bit_width); - let mut buffer = Vec::with_capacity(2 * data.len() + 40); - let _ = encoder.into_stream(&mut buffer).encode_all(data); + let _ = encoder.into_stream(&mut writer).encode_all(data); - let mut decoder = d(bit_order, bit_width); + let mut decoder = dec.clone().build(); let mut compare = vec![]; - let result = decoder - .into_stream(&mut compare) - .decode_all(buffer.as_slice()); - assert!( - result.status.is_ok(), - "{:?}, {}, {:?}", - bit_order, - bit_width, - result.status - ); - assert!( - data == &*compare, - "{:?}, {}\n{:?}\n{:?}", - bit_order, - bit_width, - data, - compare - ); + + let buf_reader = TinyRead { + data: &writer.data, + max_read_len: max_io_len, + }; + let result = decoder.into_stream(&mut compare).decode_all(buf_reader); + assert!(result.status.is_ok(), "{:?}, {:?}", dec, result.status); + assert!(data == &*compare, "{:?}\n{:?}\n{:?}", dec, data, compare); +} + +struct TinyRead<'a> { + data: &'a [u8], + max_read_len: usize, +} + +impl io::BufRead for TinyRead<'_> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + Ok(&self.data[..self.data.len().min(self.max_read_len)]) + } + fn consume(&mut self, n: usize) { + debug_assert!(n <= self.max_read_len); + self.data = &self.data[n..]; + } +} + +impl io::Read for TinyRead<'_> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let n = self.data.len().min(buf.len()).min(self.max_read_len); + buf[..n].copy_from_slice(&self.data[..n]); + self.data = &self.data[n..]; + Ok(n) + } +} + +struct TinyWrite { + data: Vec, + max_write_len: usize, +} + +impl io::Write for TinyWrite { + fn write(&mut self, buf: &[u8]) -> io::Result { + let n = buf.len().min(self.max_write_len); + self.data.extend_from_slice(&buf[..n]); + Ok(n) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/roundtrip_vec.rs clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip_vec.rs --- clamav-1.4.3+dfsg/.cargo/vendor/weezl/tests/roundtrip_vec.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/weezl/tests/roundtrip_vec.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,22 +8,29 @@ } #[test] -fn roundtrip_all() { +fn roundtrip_all_lsb() { + roundtrip_all(BitOrder::Lsb); +} + +#[test] +fn roundtrip_all_msb() { + roundtrip_all(BitOrder::Msb); +} + +fn roundtrip_all(bit_order: BitOrder) { let file = env::args().next().unwrap(); let data = fs::read(file).unwrap(); for &flavor in &[Flavor::Gif, Flavor::Tiff] { - for &bit_order in &[BitOrder::Lsb, BitOrder::Msb] { - for bit_width in 2..8 { - let data: Vec<_> = data - .iter() - .copied() - .map(|b| b & ((1 << bit_width) - 1)) - .collect(); + for bit_width in 2..8 { + let data: Vec<_> = data + .iter() + .copied() + .map(|b| b & ((1 << bit_width) - 1)) + .collect(); - println!("Roundtrip test {:?} {:?} {}", flavor, bit_order, bit_width); - assert_roundtrips(&*data, flavor, bit_width, bit_order); - } + println!("Roundtrip test {:?} {:?} {}", flavor, bit_order, bit_width); + assert_roundtrips(&*data, flavor, bit_width, bit_order); } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/which/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/which/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"66b8ad6c0bd9e6fcad662bd8784d0b92bcfc6b57cdf1df63d985c925b821516a","Cargo.toml":"5e158650a21b22c6ba2ce18abe79103b5042d78860396ce4d00c31ad36b25df8","LICENSE.txt":"0041560f5d419c30e1594567f3b7ac2bc078ff6a68f437e0348ba85d9cf99112","README.md":"1fbcd4bacd07328f84265715a825cd6811930117bb129e22625b020d12f47b45","deny.toml":"4e30f727201c8bb41500a57ca14a80f15bb29793b8c7fa6b815b5412f17af58c","src/checker.rs":"35ca1342931df0ac0b84e2c677ca1af3d74ade995c6aa0deeb9e4c3114f476b0","src/error.rs":"00315874353628366851cd0817a60059cb2c784fd315407a2c30f38021b18dc6","src/finder.rs":"dfd444a84353b5e0d3efceccff394f8c86bfc64bf56891bda406450e148100d8","src/helper.rs":"42cf60a98c017fcbf96d8cbf5880398b4f191c4b2445c43028c35ad57a1b846a","src/lib.rs":"0962694a7b8a1f66c3ac2871e484ffa1641cf93947fd9c668848f789bebf94ab","tests/basic.rs":"d3c9f35073b4c4f6ad977baaeb3d8668c170253d005cfc258749a0cbe8429512"},"package":"87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"99ca3b90f1ac83111fe0bb70cca6dc912b35408144a14088686e82cb07328fda",".github/workflows/rust.yml":"9148bb8fd36bc912c1d1ceebe251936edf1671c6e4f4090f0012ea169e849b10","CHANGELOG.md":"66b8ad6c0bd9e6fcad662bd8784d0b92bcfc6b57cdf1df63d985c925b821516a","Cargo.toml":"5e158650a21b22c6ba2ce18abe79103b5042d78860396ce4d00c31ad36b25df8","Cargo.toml.orig":"53c4ad11c115c3fd972adb7fb0341b1790e40920caf492ee46be04d6e9d8f456","LICENSE.txt":"0041560f5d419c30e1594567f3b7ac2bc078ff6a68f437e0348ba85d9cf99112","README.md":"1fbcd4bacd07328f84265715a825cd6811930117bb129e22625b020d12f47b45","deny.toml":"4e30f727201c8bb41500a57ca14a80f15bb29793b8c7fa6b815b5412f17af58c","src/checker.rs":"35ca1342931df0ac0b84e2c677ca1af3d74ade995c6aa0deeb9e4c3114f476b0","src/error.rs":"00315874353628366851cd0817a60059cb2c784fd315407a2c30f38021b18dc6","src/finder.rs":"dfd444a84353b5e0d3efceccff394f8c86bfc64bf56891bda406450e148100d8","src/helper.rs":"42cf60a98c017fcbf96d8cbf5880398b4f191c4b2445c43028c35ad57a1b846a","src/lib.rs":"0962694a7b8a1f66c3ac2871e484ffa1641cf93947fd9c668848f789bebf94ab","tests/basic.rs":"d3c9f35073b4c4f6ad977baaeb3d8668c170253d005cfc258749a0cbe8429512"},"package":"87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/which/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/which/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/which/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "35196c186f8fbec8dc40919cffa726a8bfc10998" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/which/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/which/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/which/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/which/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +name: Main workflow +on: + push: + pull_request: + +jobs: + # Run the `rustfmt` code formatter + rustfmt: + name: Rustfmt [Formatter] + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + profile: minimal + components: rustfmt + + - name: Build | Format + run: cargo fmt --all -- --check + + # Run the `clippy` linting tool + clippy: + name: Clippy [Linter] + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + profile: minimal + components: clippy + + - name: Build | Lint + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --workspace --all-targets --all-features -- -Dwarnings + + # Ensure that the project could be successfully compiled + cargo_check: + name: Compile + strategy: + matrix: + target: [x86_64-unknown-linux-musl, wasm32-wasi] + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + target: ${{ matrix.target }} + + - name: Build | Check + run: cargo check --workspace --target ${{ matrix.target }} + + # Run tests on Linux, macOS, and Windows + # On both Rust stable and Rust nightly + test: + name: Test Suite + runs-on: ${{ matrix.os }} + needs: cargo_check # First check then run expansive tests + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + rust: [1.63, stable, nightly] + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + + # Run the ignored tests that expect the above setup + - name: Build | Test + run: cargo test --workspace --all-features -- --include-ignored + cargo-deny: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: EmbarkStudios/cargo-deny-action@v1 \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/which/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/which/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/which/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/which/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,30 @@ +[package] +name = "which" +version = "4.4.2" +edition = "2021" +rust-version = "1.63" +authors = ["Harry Fei "] +repository = "https://github.com/harryfei/which-rs.git" +documentation = "https://docs.rs/which/" +license = "MIT" +description = "A Rust equivalent of Unix command \"which\". Locate installed executable in cross platforms." +readme = "README.md" +categories = ["os", "filesystem"] +keywords = ["which", "which-rs", "unix", "command"] + +[dependencies] +either = "1.6.1" +regex = { version = "1.5.5", optional = true } +rustix = { version = "0.38.10", default-features = false, features = ["fs", "std"] } + +[target.'cfg(any(windows, unix, target_os = "redox"))'.dependencies] +home = "0.5.5" + +[target.'cfg(windows)'.dependencies] +once_cell = "1" + +[dev-dependencies] +tempfile = "3.3.0" + +[package.metadata.docs.rs] +all-features = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/widestring/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/widestring/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"2910a9fd978149bd353cbb227df2151f376e93af4ba06b47b630896af191be24","Cargo.toml":"21f259f6190e84963e3dbe4c513accb98309e0de1c9e24cac5b897a9d58bacdd","LICENSE":"36bb253818ac13761081556ff5c457d626da9df1eb4f56194d9ad3926c418a68","LICENSES/Apache-2.0.txt":"074e6e32c86a4c0ef8b3ed25b721ca23aca83df277cd88106ef7177c354615ff","LICENSES/MIT.txt":"b85dcd3e453d05982552c52b5fc9e0bdd6d23c6f8e844b984a88af32570b0cc0","Makefile.toml":"7deceae498555e82edbdcc197290e159785e8d3551c3223bb04fe43135a6c39b","README.md":"7316bed9700315b4bca8d06fd53b967e8b2e339ddb48318ce3778fd9b808664c","debug_metadata/README.md":"627cc0475b9f0239d8599f6a63a0c6237f7495880c5df9b3fb83189627a5180b","debug_metadata/widestring.natvis":"15546caf5cb439da6955db0929d4df40ba33988e98550ff1d2b1c072f1caebbf","src/error.rs":"0da845333052a615db35b7edbc17572e42f94b0c9ebb48c77c9661f4a5a1c67a","src/example.txt":"ea18aef399fcdc1acb9132efdd6d2ecf6e339fa5810c9c385d733da14f58828f","src/iter.rs":"cafc099b97a723731cb772fb8f5a67a6ad3b5e4fd3873b7ca6b52008e321a7d0","src/lib.rs":"cbfd35f9f35f9c9521b99fa31d696b9c1edd92e7a0f47c03c88ab9f0bc93160b","src/macros.rs":"fd9fcf133f1840237a7fce536768493eeb9d38275177fb3ba400900cf80a72fa","src/platform/mod.rs":"370e032d7f43b5893d40350ac0428ec494af68c84d9f37b9ff2f93a5d7176550","src/platform/other.rs":"bc67c5aa65b8245813f4d2cdc1f0f43ceb9e72721be120d3b40c28447f47b5f2","src/platform/windows.rs":"1739ffaf89872aa12496a674e94be916ed21e44e25ce768cfbd29d9aa48497c7","src/test_be.txt":"a21b330b6267fded5376da75969f441f2b6b5263b51529cdaed8109a3d973353","src/test_le.txt":"bc82fcfd0dac8fc92963cfcc75fc72610edbfb56a786573d5db507e949c9b79f","src/ucstr.rs":"cc93f7e44345ab1c2b551f4713092495a4190d71b201e26b164a9fdb7ac6e929","src/ucstring.rs":"a43e2f3f0a5ffbeae58a2cbd28402c8a96d0bef916cb784b59b279b368dd655b","src/ustr.rs":"9184ed6e7a5a397412709d6d5bc1d1f3518b679fdb9848ed2c838f54b69e4b48","src/ustr/iter.rs":"d4335b86e7bbc231c13be58fd2276ecd499a2d30244fee105f2830516c5cf7ce","src/ustring.rs":"31311bcd7d97f72cec8ff71e9704ffbb9ecba6e83e7db41283a4ae23f1edbebe","src/ustring/iter.rs":"8129c093bdbf4e7bcc5bd9305cc5ef88f0a1d4307f5fd3a0472e10584afdf03c","src/utfstr.rs":"65c0c9f9a9deb416b8538a8bb8facc1d2d0350e360af6d702da302fd46709358","src/utfstr/iter.rs":"d0bbe2c7fe63ee116049b6f7b6f242ffff637855cc426b845b2a6ebacb516d6a","src/utfstring.rs":"5185571944851376fe9cd29bc1ca05aae2c449c8f04f759488102357aa42a19d","src/utfstring/iter.rs":"e60b2547c24f799fdb8489f6c870a4b2061759305503e3a2e04c74e0624c67e9","tests/debugger_visualizer.rs":"965fdb6d000cdc96ea3ca2f6c270b6d28b01ac789bf92d95cd02ab607dd9b394"},"package":"7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"56dd53279ad10ca81a8b0ecdc685f4f55f88206a5460f242aaeec39aada7f2c5",".reuse/dep5":"7aa615df0376504c0dfa905f81759d00e64155345640a802db721b72ad4ec19e","CHANGELOG.md":"2910a9fd978149bd353cbb227df2151f376e93af4ba06b47b630896af191be24","Cargo.toml":"21f259f6190e84963e3dbe4c513accb98309e0de1c9e24cac5b897a9d58bacdd","Cargo.toml.orig":"8e8aa7e6c431c8b1baf9a75496810f2be5fb7782bb040b0d2ba8431e57ab38ba","LICENSE":"36bb253818ac13761081556ff5c457d626da9df1eb4f56194d9ad3926c418a68","LICENSES/Apache-2.0.txt":"074e6e32c86a4c0ef8b3ed25b721ca23aca83df277cd88106ef7177c354615ff","LICENSES/MIT.txt":"b85dcd3e453d05982552c52b5fc9e0bdd6d23c6f8e844b984a88af32570b0cc0","Makefile.toml":"7deceae498555e82edbdcc197290e159785e8d3551c3223bb04fe43135a6c39b","README.md":"7316bed9700315b4bca8d06fd53b967e8b2e339ddb48318ce3778fd9b808664c","debug_metadata/README.md":"627cc0475b9f0239d8599f6a63a0c6237f7495880c5df9b3fb83189627a5180b","debug_metadata/widestring.natvis":"15546caf5cb439da6955db0929d4df40ba33988e98550ff1d2b1c072f1caebbf","src/error.rs":"0da845333052a615db35b7edbc17572e42f94b0c9ebb48c77c9661f4a5a1c67a","src/example.txt":"ea18aef399fcdc1acb9132efdd6d2ecf6e339fa5810c9c385d733da14f58828f","src/iter.rs":"cafc099b97a723731cb772fb8f5a67a6ad3b5e4fd3873b7ca6b52008e321a7d0","src/lib.rs":"cbfd35f9f35f9c9521b99fa31d696b9c1edd92e7a0f47c03c88ab9f0bc93160b","src/macros.rs":"fd9fcf133f1840237a7fce536768493eeb9d38275177fb3ba400900cf80a72fa","src/platform/mod.rs":"370e032d7f43b5893d40350ac0428ec494af68c84d9f37b9ff2f93a5d7176550","src/platform/other.rs":"bc67c5aa65b8245813f4d2cdc1f0f43ceb9e72721be120d3b40c28447f47b5f2","src/platform/windows.rs":"1739ffaf89872aa12496a674e94be916ed21e44e25ce768cfbd29d9aa48497c7","src/test_be.txt":"a21b330b6267fded5376da75969f441f2b6b5263b51529cdaed8109a3d973353","src/test_le.txt":"bc82fcfd0dac8fc92963cfcc75fc72610edbfb56a786573d5db507e949c9b79f","src/ucstr.rs":"cc93f7e44345ab1c2b551f4713092495a4190d71b201e26b164a9fdb7ac6e929","src/ucstring.rs":"a43e2f3f0a5ffbeae58a2cbd28402c8a96d0bef916cb784b59b279b368dd655b","src/ustr.rs":"9184ed6e7a5a397412709d6d5bc1d1f3518b679fdb9848ed2c838f54b69e4b48","src/ustr/iter.rs":"d4335b86e7bbc231c13be58fd2276ecd499a2d30244fee105f2830516c5cf7ce","src/ustring.rs":"31311bcd7d97f72cec8ff71e9704ffbb9ecba6e83e7db41283a4ae23f1edbebe","src/ustring/iter.rs":"8129c093bdbf4e7bcc5bd9305cc5ef88f0a1d4307f5fd3a0472e10584afdf03c","src/utfstr.rs":"65c0c9f9a9deb416b8538a8bb8facc1d2d0350e360af6d702da302fd46709358","src/utfstr/iter.rs":"d0bbe2c7fe63ee116049b6f7b6f242ffff637855cc426b845b2a6ebacb516d6a","src/utfstring.rs":"5185571944851376fe9cd29bc1ca05aae2c449c8f04f759488102357aa42a19d","src/utfstring/iter.rs":"e60b2547c24f799fdb8489f6c870a4b2061759305503e3a2e04c74e0624c67e9","tests/debugger_visualizer.rs":"965fdb6d000cdc96ea3ca2f6c270b6d28b01ac789bf92d95cd02ab607dd9b394"},"package":"7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/widestring/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/widestring/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/widestring/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c73148638884c4fc65cc475d88d57c88cebccc3f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/widestring/.reuse/dep5 clamav-1.4.6+dfsg/.cargo/vendor/widestring/.reuse/dep5 --- clamav-1.4.3+dfsg/.cargo/vendor/widestring/.reuse/dep5 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/widestring/.reuse/dep5 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Copyright: Kathryn Long +License: MIT OR Apache-2.0 + +Files: * +Copyright: 2021 Kathryn Long +License: MIT OR Apache-2.0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/widestring/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/widestring/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/widestring/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/widestring/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +[package] +name = "widestring" +# Remember to keep in sync with html_root_url crate attribute +version = "1.1.0" +description = "A wide string Rust library for converting to and from wide strings, such as those often used in Windows API or other FFI libaries. Both `u16` and `u32` string types are provided, including support for UTF-16 and UTF-32, malformed encoding, C-style strings, etc." +repository = "https://github.com/starkat99/widestring-rs" +readme = "README.md" +keywords = ["wide", "string", "win32", "utf-16", "utf-32"] +categories = ["text-processing", "encoding", "development-tools::ffi", "no-std"] +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.58" +exclude = [".git*", ".editorconfig"] + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +# Enable to use the #[debugger_visualizer] attribute. Requires Rust 1.71+ +debugger_visualizer = ["alloc"] + +[dev-dependencies] +debugger_test = "0.1" +debugger_test_parser = "0.1" +winapi = { version = "0.3", features = ["winbase"] } + +[package.metadata.docs.rs] +rustc-args = ["--cfg", "docsrs"] + +[[test]] +name = "debugger_visualizer" +path = "tests/debugger_visualizer.rs" +required-features = ["debugger_visualizer"] +test = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-core/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-core/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"483877d1a465dc6a4c190fdc206eb83293e6102d548dcf0f2e2093fa075694f5","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"3bcfa95b17c7748ff6139e7482ebad2d24645ac3606e4b4f88318c72122d1386","src/agile_reference.rs":"801b3bbe3674e2665bdcb12a08f06f7782be60a14c3a033289f32aa35db1fce1","src/array.rs":"c9975db941876ce329ed851b5e6ad989a660f9da0f91e8dece7333fda2274e01","src/as_impl.rs":"018954b44fe4c16d62a959f5578c5a26b968d0f9a3f156f1bac10492b934d949","src/com_interface.rs":"afc47510e80e829b5ebb2a801840104725dfcea3c5920a424b089948a14f8d15","src/error.rs":"c9115facaaa7369e91e3d959e9278770d727e52bb0108df099ae5c90feb52fdf","src/event.rs":"cc3502add9db70efb2627ddc5c709853a56ccbfee37923d67b56ed338b9d8f44","src/guid.rs":"dd82af578fef2519173614600a15ada073d5e7c973fd2e951eb5abef9b1553d0","src/hresult.rs":"00155798c154614c4c9a0a2da20814dddb537a1e21c88bc3dff65598fdf7ee03","src/imp/bindings.rs":"805fe0012f5bbf639f6d66cfdbe21f4f855c4ec3eee2610f457dbf3b80defad7","src/imp/com_bindings.rs":"3f88e91dd17daf657c9e29e82628fc84fa02b942bca1ae5ca682e4a2a89ccb6e","src/imp/delay_load.rs":"26492b2ef34f4a3ac35f41050a9088ee15603caf0a59c6e74fdf423bfcb96829","src/imp/factory_cache.rs":"fcec72750d06a262878720a13f82b7365075c6b038b28426532b233aae8baa84","src/imp/generic_factory.rs":"cbf8b251e2758d98bf6bbd7c73b20a2e31e60e0d006b2febc51e247c039fab85","src/imp/heap.rs":"646e31462f37f96a9d6928997c2bbacc333eabb3989e9999e89ff95e9565e4ba","src/imp/mod.rs":"503ab66c7911e5ad6dfd2311f81674798c84e41d3c023b4868f80ad3a3593b8f","src/imp/ref_count.rs":"ded51b50923eb1d542432d216b56604b6cef564f664740a3ad8290ad8d88b8e6","src/imp/sha1.rs":"0ff2ba4d1f77b5ec3859567fec1a3d75175a844914c5f7ec068c8581dc2b7f4a","src/imp/waiter.rs":"575cfdbe9befc22b1e8fa91e15f303d830b23673d07a5361992229e0440081b2","src/imp/weak_ref_count.rs":"5d58f4bdcb4b6fbb55be672b7bd885307c9cac17ee4f212c899a54e76a039ded","src/inspectable.rs":"32c4881d567d90254556a4185cd0dd5b984c932183db7c8b4c51bcbac53e41ac","src/interface.rs":"4a4588085d5401585aabc62a131d2601134f4fb80ba2199fe066e6df6c84ead3","src/lib.rs":"9673f8d82af0325a5924b9afe07af39e7ea82731c3caca126e39cd9596dd4e63","src/param.rs":"cb62f173048e84f6355662223d34be482449393fc049fc45980d1bf087dc8e77","src/runtime_name.rs":"b330db95b0ce32c963d6b43a0b152cd96e136e5b38b92c02223fb53b30f83ecf","src/runtime_type.rs":"cf3697b442b2bc77e1a8981128eb5f4c282603a01f7081399f1e11587670d0bc","src/scoped_interface.rs":"c11be14a0c95c3c9b055741e4b9c353d6bb6efe88075ceb05fd606b6ac34a2a6","src/strings/bstr.rs":"569ff0cf6157cb869ec14f773261fe95ee1d065cade7b04d3ee44f0dfbdec149","src/strings/hstring.rs":"ea3913393e655b6c48270df04fbb82eb9fc4b1d3f1d673bd04872a33d160f38d","src/strings/literals.rs":"5b998ebd3a750a7f42c2013b354a58f6c289f5f433f154a9ac34b47e23ec9429","src/strings/mod.rs":"4aaf6d2efe2396e541bd5d9ddff859d3374bfda4914b67daf645ee3b48cc3852","src/strings/pcstr.rs":"3c29064d22e632dc9f30c8d6933e41d5c755d2c82462c6570318bebe12a5c1a3","src/strings/pcwstr.rs":"86a36da73bdcd12af9a6e1be09470443b42017a0613c432ac3e559cfdc7f3ff2","src/strings/pstr.rs":"151d29125932d874aefcda01975913f87e8561b3d240e84c9db39e891b78a484","src/strings/pwstr.rs":"de99eb08f1f3c351854d1ed1f978460669b53ae39dc118e788a9f66a562d2c7c","src/type.rs":"fc263c265f799c7d5b326cebbbc20a8f96ee438b1cc444d9925caab22db8e488","src/unknown.rs":"5a1888c35ad9db383216bbe1c15dde3ea316d40ba2783392067060706f7ec812","src/weak.rs":"b1d1740d65ad0b9f296342afbac0c6994eb2fa0ea7dba4882b64b246e309d9da","windows.natvis":"f9bd327a207011f85debdd3d67828668f71b56e7e429a7172dab1286738ca238"},"package":"33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"a5a42308a9f992ee0812972b85e3af284efef610d7accf40007d2048a72c9798","Cargo.toml":"483877d1a465dc6a4c190fdc206eb83293e6102d548dcf0f2e2093fa075694f5","Cargo.toml.orig":"0e681d06ac92cea60c23c386bcdb73ac1e6bebbf9231cb81889829aa1e4ec344","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"3bcfa95b17c7748ff6139e7482ebad2d24645ac3606e4b4f88318c72122d1386","src/agile_reference.rs":"801b3bbe3674e2665bdcb12a08f06f7782be60a14c3a033289f32aa35db1fce1","src/array.rs":"c9975db941876ce329ed851b5e6ad989a660f9da0f91e8dece7333fda2274e01","src/as_impl.rs":"018954b44fe4c16d62a959f5578c5a26b968d0f9a3f156f1bac10492b934d949","src/com_interface.rs":"afc47510e80e829b5ebb2a801840104725dfcea3c5920a424b089948a14f8d15","src/error.rs":"c9115facaaa7369e91e3d959e9278770d727e52bb0108df099ae5c90feb52fdf","src/event.rs":"cc3502add9db70efb2627ddc5c709853a56ccbfee37923d67b56ed338b9d8f44","src/guid.rs":"dd82af578fef2519173614600a15ada073d5e7c973fd2e951eb5abef9b1553d0","src/hresult.rs":"00155798c154614c4c9a0a2da20814dddb537a1e21c88bc3dff65598fdf7ee03","src/imp/bindings.rs":"805fe0012f5bbf639f6d66cfdbe21f4f855c4ec3eee2610f457dbf3b80defad7","src/imp/com_bindings.rs":"3f88e91dd17daf657c9e29e82628fc84fa02b942bca1ae5ca682e4a2a89ccb6e","src/imp/delay_load.rs":"26492b2ef34f4a3ac35f41050a9088ee15603caf0a59c6e74fdf423bfcb96829","src/imp/factory_cache.rs":"fcec72750d06a262878720a13f82b7365075c6b038b28426532b233aae8baa84","src/imp/generic_factory.rs":"cbf8b251e2758d98bf6bbd7c73b20a2e31e60e0d006b2febc51e247c039fab85","src/imp/heap.rs":"646e31462f37f96a9d6928997c2bbacc333eabb3989e9999e89ff95e9565e4ba","src/imp/mod.rs":"503ab66c7911e5ad6dfd2311f81674798c84e41d3c023b4868f80ad3a3593b8f","src/imp/ref_count.rs":"ded51b50923eb1d542432d216b56604b6cef564f664740a3ad8290ad8d88b8e6","src/imp/sha1.rs":"0ff2ba4d1f77b5ec3859567fec1a3d75175a844914c5f7ec068c8581dc2b7f4a","src/imp/waiter.rs":"575cfdbe9befc22b1e8fa91e15f303d830b23673d07a5361992229e0440081b2","src/imp/weak_ref_count.rs":"5d58f4bdcb4b6fbb55be672b7bd885307c9cac17ee4f212c899a54e76a039ded","src/inspectable.rs":"32c4881d567d90254556a4185cd0dd5b984c932183db7c8b4c51bcbac53e41ac","src/interface.rs":"4a4588085d5401585aabc62a131d2601134f4fb80ba2199fe066e6df6c84ead3","src/lib.rs":"9673f8d82af0325a5924b9afe07af39e7ea82731c3caca126e39cd9596dd4e63","src/param.rs":"cb62f173048e84f6355662223d34be482449393fc049fc45980d1bf087dc8e77","src/runtime_name.rs":"b330db95b0ce32c963d6b43a0b152cd96e136e5b38b92c02223fb53b30f83ecf","src/runtime_type.rs":"cf3697b442b2bc77e1a8981128eb5f4c282603a01f7081399f1e11587670d0bc","src/scoped_interface.rs":"c11be14a0c95c3c9b055741e4b9c353d6bb6efe88075ceb05fd606b6ac34a2a6","src/strings/bstr.rs":"569ff0cf6157cb869ec14f773261fe95ee1d065cade7b04d3ee44f0dfbdec149","src/strings/hstring.rs":"ea3913393e655b6c48270df04fbb82eb9fc4b1d3f1d673bd04872a33d160f38d","src/strings/literals.rs":"5b998ebd3a750a7f42c2013b354a58f6c289f5f433f154a9ac34b47e23ec9429","src/strings/mod.rs":"4aaf6d2efe2396e541bd5d9ddff859d3374bfda4914b67daf645ee3b48cc3852","src/strings/pcstr.rs":"3c29064d22e632dc9f30c8d6933e41d5c755d2c82462c6570318bebe12a5c1a3","src/strings/pcwstr.rs":"86a36da73bdcd12af9a6e1be09470443b42017a0613c432ac3e559cfdc7f3ff2","src/strings/pstr.rs":"151d29125932d874aefcda01975913f87e8561b3d240e84c9db39e891b78a484","src/strings/pwstr.rs":"de99eb08f1f3c351854d1ed1f978460669b53ae39dc118e788a9f66a562d2c7c","src/type.rs":"fc263c265f799c7d5b326cebbbc20a8f96ee438b1cc444d9925caab22db8e488","src/unknown.rs":"5a1888c35ad9db383216bbe1c15dde3ea316d40ba2783392067060706f7ec812","src/weak.rs":"b1d1740d65ad0b9f296342afbac0c6994eb2fa0ea7dba4882b64b246e309d9da","windows.natvis":"f9bd327a207011f85debdd3d67828668f71b56e7e429a7172dab1286738ca238"},"package":"33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-core/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-core/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-core/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "3a605cba064b26f2a198ac58085f8c8836f47c38" + }, + "path_in_vcs": "crates/libs/core" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-core/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows-core/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows-core/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-core/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "windows-core" +version = "0.52.0" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Rust for Windows" +repository = "https://github.com/microsoft/windows-rs" +readme = "readme.md" +categories = ["os::windows-apis"] + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] + +[dependencies.windows-targets] +version = "0.52.0" +path = "../targets" + +[features] +default = [] +implement = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"ff53899cc9a441f18f66fd21c4784716a0aab5020a21cba5764ac8ee1e1f34cd","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"3bcfa95b17c7748ff6139e7482ebad2d24645ac3606e4b4f88318c72122d1386","src/Windows/Wdk/Foundation/mod.rs":"20b32a858e9053cf60501c1bf73e9e73429b559a0ead1d0f99c18cf5c7f87c62","src/Windows/Wdk/Graphics/Direct3D/mod.rs":"b491612762294e97e9618771a7e11adaff190a3df3c5a1494da47de3f2e55bda","src/Windows/Wdk/Graphics/mod.rs":"d69902b8e241ff56d3cac2a648b40946d999dee0c21d8e54e5b471d612a10373","src/Windows/Wdk/Storage/FileSystem/Minifilters/mod.rs":"355133683c937771170226d4dc8917792397fffef5fa96a6032f8b05bd3656c6","src/Windows/Wdk/Storage/FileSystem/mod.rs":"baf35fbdc604cfc7caca64a1b7d71fc1cfc7188cf3991eee46258b43e0f60984","src/Windows/Wdk/Storage/mod.rs":"b393a8f908458c172fe5eaac195789f9719e0a5d7a9cb6dc980dbdb8bd198a44","src/Windows/Wdk/System/IO/mod.rs":"5395da986f92e7a8aee4b7796f1fa23a33024807f592d0f517e6e41799249073","src/Windows/Wdk/System/OfflineRegistry/mod.rs":"c1766ae9cc54a51c63596f4f6eb9d916b8a36218871d72e7c8a33d5aa8007b19","src/Windows/Wdk/System/Registry/mod.rs":"599fbaec01766b0a165c90c484affbcfd882f92d2705666c2737d09ce0efb4ba","src/Windows/Wdk/System/SystemInformation/mod.rs":"be972dfea89c1b8bd86947535f0e47644703db97d94542f2f0915ca738be8de3","src/Windows/Wdk/System/SystemServices/mod.rs":"90ccad952368d2b69ffdf7b08a89d9be1bc91eba9b419cf3588e87ac212c7eb7","src/Windows/Wdk/System/Threading/mod.rs":"0bf570e60e23bb281f2b6ed5ff3127666a46fd3b214247f61bc7f46557c092da","src/Windows/Wdk/System/mod.rs":"0f83083d4a2c6fce7307ef3fc4f6091eab211614da07a3d49bbfe9558f881b9f","src/Windows/Wdk/mod.rs":"d1f4517f7544f2d83935da1cdd3e03e4f0d58ddc76998c5886de142b717fa465","src/Windows/Win32/Data/HtmlHelp/mod.rs":"e7e6fdccea3ad91cda27ec6698c99df6fc01d1489042e65afa3f53d5db5f8cab","src/Windows/Win32/Data/RightsManagement/mod.rs":"aba7db25a328ff884a14d8bfd988dc58a5ff4ef35f40839779f22a2ebe76cb57","src/Windows/Win32/Data/mod.rs":"bf6a79c22d6cafc75f44a7bfc72c816e479a17987064b7adfaa3ec2750f01e41","src/Windows/Win32/Devices/AllJoyn/mod.rs":"02babd5b386a1472f2319f0101314ee0912895b1699d2abc7ea75488f2bd10db","src/Windows/Win32/Devices/BiometricFramework/mod.rs":"d024c6786852af281eba3eab483b3591147f14faf7c32ab0732304f6a90ea93b","src/Windows/Win32/Devices/Bluetooth/mod.rs":"d7b988c92870a9c5bed800025d8b5392e5c2533e19ee38d074b612aa6a064f0c","src/Windows/Win32/Devices/Communication/mod.rs":"a6949a741e3f3eb5d1e0b3a403b5755c59736249eb2c169cf7580c0c05336db4","src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs":"36b76cb25dac4381126c2d13b7b449083eea1511a3f10ef4a12843b1c14a23a9","src/Windows/Win32/Devices/DeviceQuery/mod.rs":"cd220d5ffeb7f540d539f55a23dffa11913b5c60ed21bc263dfb7957b6f342fe","src/Windows/Win32/Devices/Display/mod.rs":"4a256453c780ae2c5ae5c13212334daab42e659c559f72d9bbf24a5e7fa53bc8","src/Windows/Win32/Devices/Enumeration/Pnp/mod.rs":"88efec18d6dc9dd4ececc24b0ed62d829bead8e78ee069ecb420756cf6db8b69","src/Windows/Win32/Devices/Enumeration/mod.rs":"bcb6ce6da58560617f5faa1eeb2adeab4c5160eb4e86da6f9fc05b38c557c4e7","src/Windows/Win32/Devices/Fax/mod.rs":"235cc2691da29c401c168bd9a618f0e9004c754d157adbf09df60a7e9df732d2","src/Windows/Win32/Devices/HumanInterfaceDevice/mod.rs":"13291bbd8971833a93552add6917c60eec9461e55b7723cc32ebc863bb773361","src/Windows/Win32/Devices/PortableDevices/mod.rs":"183b9f9f3978ca10c9b38cfefe15ebe99034488883c526019ae48656001d1df6","src/Windows/Win32/Devices/Properties/mod.rs":"3a453aae0c83ef10b5c29fc136c7f1b86163e8167767f7326e1745dd78c3a2d4","src/Windows/Win32/Devices/Pwm/mod.rs":"c8a5d4566e51b614bb2e8bcdd0ce2650fea5e147160af4dae800ea054897e207","src/Windows/Win32/Devices/Sensors/mod.rs":"9e2411c07e1b3be2e283b9023793703c625c156acf978f476045ad484a2dbae6","src/Windows/Win32/Devices/SerialCommunication/mod.rs":"960a3ab21f2ac344a95dad9a79cfbc64e0bc67cbdec168f62d1cfd8741fccce4","src/Windows/Win32/Devices/Tapi/mod.rs":"d603565057b5964c9808d3a8e36a5093be1c04e3fb7bc9293139a510ceeac0b2","src/Windows/Win32/Devices/Usb/mod.rs":"cdf192649ab39b9ba76805b420bc93f8b8f1ea4c40fcece02c1f4e2c3eff24a5","src/Windows/Win32/Devices/WebServicesOnDevices/mod.rs":"c793c7a26a9ccd75e790ce361cbe65b3bbc418a6d4eb386a59af09bc361a008c","src/Windows/Win32/Devices/mod.rs":"48fec1cc37dcf54ac7c2838bd3a2b62ea3c5fd26fed08f27cc8aa511c19cbbe8","src/Windows/Win32/Foundation/mod.rs":"ee8378fd7a513d263aca8d5d441625965c746658f5a595f571d82e7a6cf71b36","src/Windows/Win32/Gaming/mod.rs":"de10172a298f1ec41c0bed43e828c7f8049142adc66faaf99103beb7dc0d54e8","src/Windows/Win32/Globalization/mod.rs":"232b0887d68c4b573b4bb3d39e95bc27da3897b930cb1eff3ad8da60d5d342e5","src/Windows/Win32/Graphics/Dwm/mod.rs":"2c0c64f25df323385c877c768263a1e69063aa7817530b825f28d34d15a39a7c","src/Windows/Win32/Graphics/Gdi/mod.rs":"7541447de1a074b92c93d003fdf2897a04f279127a36d69ab0e4ab09ea8dae49","src/Windows/Win32/Graphics/GdiPlus/mod.rs":"13460005d472709cf33b4b143889eae4c057ddff920d23591d9b2c4defb2081d","src/Windows/Win32/Graphics/Hlsl/mod.rs":"f0fa2ad8f50faa1e9ca1e3183c5ab8c10359e254c781237f32afae931d475bb6","src/Windows/Win32/Graphics/OpenGL/mod.rs":"813403eb3eeea3da519b0ecfd4cbf630b2e85a0cc0730221ec3d40bd0e279ba0","src/Windows/Win32/Graphics/Printing/PrintTicket/mod.rs":"a7c5bfe6011003ed5247aa0544b21139fcf204df2c50714b324a28ea869468bc","src/Windows/Win32/Graphics/Printing/mod.rs":"0022861c3801ae72ea99f9641737e3ad556de90aed87b009b8d8061c03dd5315","src/Windows/Win32/Graphics/mod.rs":"b553dc21e2ca071ff6e215e882d22088a8ddc7dd029bb1bff8b655649e913a52","src/Windows/Win32/Management/MobileDeviceManagementRegistration/mod.rs":"70b13306d1a000e8ce7a70a714f33df6b1ef296d66c86945440641809ce906d3","src/Windows/Win32/Management/mod.rs":"4deebf9977e6b947f904b3333a5bf63538bf30f879af29c9212433e93b53817a","src/Windows/Win32/Media/Audio/mod.rs":"e844e42702f51310d5c2e60fd896ee0ee24a1f78f2adb8a06405fe69e1802365","src/Windows/Win32/Media/DxMediaObjects/mod.rs":"b09cb6e430fd9b94c39d137f76fc60d6880921a1aec9fcea613d27d8fae84fac","src/Windows/Win32/Media/KernelStreaming/mod.rs":"1b707e8b3615be48e4e0daad48b42fb78d6e7f0b99e3d2670ba1ec6965cd08b6","src/Windows/Win32/Media/Multimedia/mod.rs":"1276ebad2ed99b04e372cffd1a9ed66f64b901b022d8b38a502622be7aee0bc4","src/Windows/Win32/Media/Streaming/mod.rs":"bf38a5cfaa87724f7a759568cb4bcbf74ea5e29f8c1c1bb1f531a551bbf16bbb","src/Windows/Win32/Media/WindowsMediaFormat/mod.rs":"ed7253ea6a7a3d239e062849d5e37d9910f86e6c403be2223fa156826045c5e1","src/Windows/Win32/Media/mod.rs":"66744d3f4ee3c78f123178b27e9bfc490409f99b9c6d4e7dddfad84963acd028","src/Windows/Win32/NetworkManagement/Dhcp/mod.rs":"e17a7a0354748584d8fac6c3aba986b929b41b08d8e77fe55b95c034351be24d","src/Windows/Win32/NetworkManagement/Dns/mod.rs":"b4c2610b0abd259ff039ead42dc20a29126c6b9af1b66bac9fc180977447af45","src/Windows/Win32/NetworkManagement/InternetConnectionWizard/mod.rs":"f18f3c55cd887bcec82c56c2503bfb85576066553a377aa1380e34d6dbb374c8","src/Windows/Win32/NetworkManagement/IpHelper/mod.rs":"eb0be9b2a840b83779427fca04b94e39070b84b8be6cfe30ad96cd5b7cca4580","src/Windows/Win32/NetworkManagement/Multicast/mod.rs":"4a0ac5e8dbf9ae5bc3af47ad7b30b8f1f621c5247b0e0277de9f09f4eaf18056","src/Windows/Win32/NetworkManagement/Ndis/mod.rs":"f5b83dead2d196ea9a4b92b524f467a7d4d8f620c7219aef903ac098b5a05716","src/Windows/Win32/NetworkManagement/NetBios/mod.rs":"7487268b11ea45c93d1b998db8fe7f0750d1a18d1682f59f22cf0273d7e505fa","src/Windows/Win32/NetworkManagement/NetManagement/mod.rs":"fa4490af37605395433f34e0d2e9670772d45ad736e6822dd75942f82cb8de7c","src/Windows/Win32/NetworkManagement/NetShell/mod.rs":"937b4a1dff5225891cfcf5bf0ae09d7ace9912d532fa0f6cbcca36575139c060","src/Windows/Win32/NetworkManagement/NetworkDiagnosticsFramework/mod.rs":"2b4582e3aa60d4fed836fdc5c63dd2a0fc1fb7ac548bcbf36c72f965b5d72a45","src/Windows/Win32/NetworkManagement/P2P/mod.rs":"5b90f05db45b73cb274bcb0c865984c417d8c8ba1dd01e71cb7032cc4f6d936c","src/Windows/Win32/NetworkManagement/QoS/mod.rs":"69a6221529057028ea2f2ae622ed596efa33e9847586f73e204b2d33d59d142a","src/Windows/Win32/NetworkManagement/Rras/mod.rs":"126b5b0ea795c7fd479e6e311c2d81e490161c2f1ce135e98ed2a266e762cc04","src/Windows/Win32/NetworkManagement/Snmp/mod.rs":"7086b06425e3e575f7d34b5564bb45c83144118ae6b7391c9793fd6c54ee5b03","src/Windows/Win32/NetworkManagement/WNet/mod.rs":"b9f82d5d392996569f46e2f8a596193ffa65c7168112faee644fc81d2ff70769","src/Windows/Win32/NetworkManagement/WebDav/mod.rs":"72c65f43a52d99536e31a2381b8a7b21b5c830a394554294e417ab414b105f73","src/Windows/Win32/NetworkManagement/WiFi/mod.rs":"ce30e91ffff192954e32f223a1fceb4d06c8dcd0e4169a1ad9bfe0769a7b3532","src/Windows/Win32/NetworkManagement/WindowsConnectionManager/mod.rs":"7a31e03d9d9f5fe7738f8683cac2c885762396904cdedca14abd1e8a38220c73","src/Windows/Win32/NetworkManagement/WindowsFilteringPlatform/mod.rs":"35cbc85ab0134c3413001d71d4e7f4cf2d2a038ef44b42e5e16bd33fe52c80a1","src/Windows/Win32/NetworkManagement/WindowsFirewall/mod.rs":"18e103f13e37d1f21fc695159cdf960b8c916a8a4f6e9a3c09123af0e5da3e02","src/Windows/Win32/NetworkManagement/WindowsNetworkVirtualization/mod.rs":"b4694a524e8c55c2b6accf3852f05cfa012682cfbc3b22283de42ddfe0791ebc","src/Windows/Win32/NetworkManagement/mod.rs":"bfc0e3c898d79ebe20e6fc711facade5b632b4ae121c28077b7eab6934ed1992","src/Windows/Win32/Networking/ActiveDirectory/mod.rs":"639a6d76b7c099104294543d0dae12ab3f8ae22b2af6ea5950f49de0a19f1c27","src/Windows/Win32/Networking/Clustering/mod.rs":"30b0d72782908fb57ec3e4923fc12e54cafef70f17a7ebdc66c90a3b400e1c82","src/Windows/Win32/Networking/HttpServer/mod.rs":"fdf6a9414fd6c46e02ee9d9df85faaef18a7432ce2072e29c2b7e0e2967f0dfa","src/Windows/Win32/Networking/Ldap/mod.rs":"8c3038199930128460e763962bd72d6578ac75a291bb739ef1e50832b4f0d1ba","src/Windows/Win32/Networking/WebSocket/mod.rs":"8a58e2faf42e55f2118e612c48b06de28e388686f396cfaf443e7891b96d8d9c","src/Windows/Win32/Networking/WinHttp/mod.rs":"4920431d66810c59711b74d4eb7ff2d50fd5fa2b4ee666269afaf2a874b4ab5b","src/Windows/Win32/Networking/WinInet/mod.rs":"2ebfd5512d3c225946ee26b7b805f67d332b1463288407d346119f61d2e19733","src/Windows/Win32/Networking/WinSock/mod.rs":"204bc39a8213167dcab8dd273c57e5fae3afbac8fa3887dbe43ad082d55446e4","src/Windows/Win32/Networking/WindowsWebServices/mod.rs":"0b6fb56d4e757a9bc51b3fffc4652bb489ee2f767fdd2a439113a586a6fdeeb7","src/Windows/Win32/Networking/mod.rs":"0429eb5803f0703acdb3ea0f1c819ea6e9efa4293d485320d91383e2fa642c69","src/Windows/Win32/Security/AppLocker/mod.rs":"c9ffaf5bf45f3a730cfd0b008d49b138eeea192e6a8620c9973692c2326f758b","src/Windows/Win32/Security/Authentication/Identity/mod.rs":"64fed7fade2b48818b75efbe17f9b247bc7d3a90fac42369d8aee4569d1f24a9","src/Windows/Win32/Security/Authentication/mod.rs":"65750cc9bb1cd1bd24313b7da49f25c99166fecbf5b3919dc3c01f37553ee371","src/Windows/Win32/Security/Authorization/mod.rs":"8f815ef1e07914982c627898d4dc071a703e86240e9a9f946878e3210bc23ac7","src/Windows/Win32/Security/Credentials/mod.rs":"156b04b25235957710a9198355d42c2bda40bfa273368caf9d8b20caedc69e6a","src/Windows/Win32/Security/Cryptography/Catalog/mod.rs":"69e110c8b0d6cbc2efb8def07d2f7953897c012c46b1aa0500a46404b6969d3a","src/Windows/Win32/Security/Cryptography/Certificates/mod.rs":"cd37ae782fe0d80933233397a0cea700e2879676213e40bb6b352fdba893a54d","src/Windows/Win32/Security/Cryptography/Sip/mod.rs":"746640f8b09a2c9407d89ea592fb0c1aa1d6d7b2c149c1d756c6daf36e68d8b9","src/Windows/Win32/Security/Cryptography/UI/mod.rs":"fb911ef0f1fdb3bdf041742d4788b6ac3c7e320454769a33c18daca6d5fe8b50","src/Windows/Win32/Security/Cryptography/mod.rs":"3c35607f54a387487e2fffbfd671ce17147e0d38097a1663b8541ea68c848cf5","src/Windows/Win32/Security/DiagnosticDataQuery/mod.rs":"72d7fa7bafd06809dc294f76c26c48e94373575e73d238ec254f03408486fc29","src/Windows/Win32/Security/DirectoryServices/mod.rs":"9257d98cf9f707df30a6021f00da4d91788958ce3a7bd86f1dd1a085b98018c2","src/Windows/Win32/Security/EnterpriseData/mod.rs":"4cdda8f31619584faf5a773801d2f99998a5f5876eb0da7bc503afd6e5cbf8f4","src/Windows/Win32/Security/ExtensibleAuthenticationProtocol/mod.rs":"7ac85b9ad3ba8a235e8ee91227b3394e23ac8f47c9c19579fb74ae7ebd7947de","src/Windows/Win32/Security/Isolation/mod.rs":"258bad95b793de887dfe695e6a5b703b01828cb5233849be66cee18a3b6411e8","src/Windows/Win32/Security/LicenseProtection/mod.rs":"17a51f78e1ad133a82c098466abbd1028f852853c98a7d606dda18a2509b9099","src/Windows/Win32/Security/NetworkAccessProtection/mod.rs":"72a2ea527b530a0118cedbd6b728057c0ab67ee78058e19978424858b1e6b0d7","src/Windows/Win32/Security/WinTrust/mod.rs":"b4a6a71e80f47a37aa05b25bab93654652d79f885fbed5d928193d99ae70e5f5","src/Windows/Win32/Security/WinWlx/mod.rs":"f0c149a46394bd173158d2741531c7af850cb1180d9915d43a88fdee9e2fa855","src/Windows/Win32/Security/mod.rs":"b35db507ad9380695f15b7ba798d0e677e08cc84b905577489d7e63994f00673","src/Windows/Win32/Storage/Cabinets/mod.rs":"e928f4da0c576de84077ccea0448153c5a5636bad49d6ae0dc6151e4abbe19db","src/Windows/Win32/Storage/CloudFilters/mod.rs":"c7dd7180ca25d9b2e01fb5951541c69aaa3d015c31b6a6bafaccc11fd18a8c9f","src/Windows/Win32/Storage/Compression/mod.rs":"22cb1e9b4abbcc3c9345c3b62c5cabac80c0f74dbbab870f09d4030db12f43ca","src/Windows/Win32/Storage/DistributedFileSystem/mod.rs":"81d1d8652a2c8432754b123f875efc65a661ecde241f4541c698ec4336f89283","src/Windows/Win32/Storage/FileHistory/mod.rs":"51155942044b1c84ffa018b18851fe54f262a49ada60fff8df763ee9c38f4924","src/Windows/Win32/Storage/FileSystem/mod.rs":"62de1e36d41b1efdb8651c887dae8fbfb0ca2dc34e4d3a789e716f50e424630d","src/Windows/Win32/Storage/Imapi/mod.rs":"85bc966fe8a9aee71ba7e526058369a96d0a5b14389b284f377ba4d1df2c1c87","src/Windows/Win32/Storage/IndexServer/mod.rs":"938958de534b65e1af2a4afad5b6911a783e7517a136ed792d8e602fba9abfa6","src/Windows/Win32/Storage/InstallableFileSystems/mod.rs":"5d5c5f27be6e2c89b4bbb5507624cdf99bcb46f39b9d64e65f3f39edef7f9a49","src/Windows/Win32/Storage/IscsiDisc/mod.rs":"9ddbf4dc3615b17e361143cae523b89d0e55f5088fe938c1009453acbe115c1e","src/Windows/Win32/Storage/Jet/mod.rs":"a9644cd862855d6d8ffd38b19563145446ee589c6c7a8f18e7b9c25962fbd490","src/Windows/Win32/Storage/Nvme/mod.rs":"24c768d01640b48f3a8406e80a05f588c7edbff273f573e32ef1222bcfe6550d","src/Windows/Win32/Storage/OfflineFiles/mod.rs":"1731e23074a8c92669460d6ff84ef7a26cf32f11265c3cb59e93038c84439ed8","src/Windows/Win32/Storage/OperationRecorder/mod.rs":"5999d081c94f8c2323951a7126813803299bb60217550a48a90437a69be99db0","src/Windows/Win32/Storage/Packaging/Appx/mod.rs":"fa76e97d4e7a502db5ee733430c6c6146ca75f973822ac0158ae2752c0cace42","src/Windows/Win32/Storage/Packaging/mod.rs":"f7f0994f7816af4d9f18d8336544b3a9c3db62a272f79ce91cb6a573e665be6e","src/Windows/Win32/Storage/ProjectedFileSystem/mod.rs":"114963523c77ac74fae655943ac9aeca3de2aaf6558255a7d4483f0660738601","src/Windows/Win32/Storage/StructuredStorage/mod.rs":"72d8e7ed6e51bbb128fe759b36a31d08e397a021d3b70cbcce79cac6dee4a977","src/Windows/Win32/Storage/Vhd/mod.rs":"b57e26dc3b8a217b608fd9204025914d6c2b25005f52357afd6f69fb5bc43c6e","src/Windows/Win32/Storage/Xps/mod.rs":"b10b39e4c54fbad143957d884bd1867c21cc5135ca47c8ecc351ed3f0fdfd44d","src/Windows/Win32/Storage/mod.rs":"6a382c16cd957177330437b3ed9747c77f7dfdc4e826a14e1213ceb66e17706a","src/Windows/Win32/System/AddressBook/mod.rs":"0c3c6a0e9071d2fdaf0c475cde725a8370346d16cb000ebea373a11c72443388","src/Windows/Win32/System/Antimalware/mod.rs":"71c50e08bc1767e70a710d306b1b64a89ecf00fa6974aec62db4af002c8b2228","src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs":"31c97e160a91fb59e9480970e2494119e83cce7f9e3f7945c7289347047037d5","src/Windows/Win32/System/ApplicationVerifier/mod.rs":"17c52576ab522266e72343d120252f0d4bb1e6b244ff9c5c5c38531a06d11ccf","src/Windows/Win32/System/ClrHosting/mod.rs":"fab866abe537be550bc3c77130b65e6106c53d933199a17f86fcf06ee75a8ae8","src/Windows/Win32/System/Com/Marshal/mod.rs":"1f04deab60c3ffa9a404486bf3aedf5799ef409393668513ee6645f5658829d5","src/Windows/Win32/System/Com/StructuredStorage/mod.rs":"56b25e3fbda76110db3e3c6335a4e27f703c7c7be9366e78d35f0f02d2994859","src/Windows/Win32/System/Com/Urlmon/mod.rs":"5bb352468e1c3487d54c8a8157a00dbb4a7385a565b7dc57ca07bd46c38f14ad","src/Windows/Win32/System/Com/mod.rs":"30e7c0b7ea3db8f9b9d9bafa85a3fbdd01070eb0cc43124306f210274f03cae5","src/Windows/Win32/System/ComponentServices/mod.rs":"7b2ba528379e4b22a7de4b61cadd925259cb972fb484da285c3360ca36e76ea4","src/Windows/Win32/System/Console/mod.rs":"a5eb9bef1283ad246c2171415afc4e0cd1626bcdeb8918d970e28f73b444cb14","src/Windows/Win32/System/CorrelationVector/mod.rs":"2170686b3dc82243a39c8e275cf5eb83a58d50ca5004324e9b3f99d0c54aaada","src/Windows/Win32/System/DataExchange/mod.rs":"197fb5fb49beb2653865bf1dead6193706be9900248d77eacc5733992f40b0ca","src/Windows/Win32/System/DeploymentServices/mod.rs":"3cb62aec8f2967d29f5efea0ffb1c48184fdedcc6d07f42e61fbd4a01e34252e","src/Windows/Win32/System/DeveloperLicensing/mod.rs":"30162501a442c7a8fa23ed72c9e6bf67768800fc170947b01f0bb09b64300deb","src/Windows/Win32/System/Diagnostics/Ceip/mod.rs":"ceda2ba33aa12edd1e02ad896320a35d0e7ea0f6d7b6ee5d53f28de18840ecf1","src/Windows/Win32/System/Diagnostics/Debug/Extensions/mod.rs":"04de20f10090af85880d15bef24029863fbdd18e069af06d47077a3f21f77b78","src/Windows/Win32/System/Diagnostics/Debug/mod.rs":"97be8fa2512bd4fb5c2097c8539e45a65ef75d7265eab01795252099291a7ae2","src/Windows/Win32/System/Diagnostics/Etw/mod.rs":"516ec30d47dc7633fded6f3b4612797bfdcd913386c6a718724b33d6ba4df2ac","src/Windows/Win32/System/Diagnostics/ProcessSnapshotting/mod.rs":"02d366ebf86d5d4a69821f72841789cd8e6a5e5982740f18088915e06224272b","src/Windows/Win32/System/Diagnostics/ToolHelp/mod.rs":"d8009a4856899743f52491fd1a6980f4fc4c8ca1f9e4a33751ccb31e32eb7934","src/Windows/Win32/System/Diagnostics/mod.rs":"26028a11b3e3bb236f387361b5866860d949379a91e65c6ea40eaf75ac8c9fe2","src/Windows/Win32/System/DistributedTransactionCoordinator/mod.rs":"19a760bac272c261189e25120c562988afcffc83ff792da604715a66d4d3f7e2","src/Windows/Win32/System/Environment/mod.rs":"56413bba141e59a0282467de796f47a922e4c8bd2dbb1a4fb7ec844cbad1a220","src/Windows/Win32/System/ErrorReporting/mod.rs":"20acdd9023d1b6586877556959fbc5c6858c8e775e3d2ee2728185410da99899","src/Windows/Win32/System/EventCollector/mod.rs":"acbbf978dfb0164de14f47c376b75f054bf98b68667be0f34f402082abe82df9","src/Windows/Win32/System/EventLog/mod.rs":"effc8b56a355a344456922ef5cdb7029f219396c7c0b118bef3ded086b4bb5f2","src/Windows/Win32/System/EventNotificationService/mod.rs":"9f7af63f6dd9e7056d68d8c8e2a52452a6c389563f0085d510242439e0df26f3","src/Windows/Win32/System/GroupPolicy/mod.rs":"50675fdcf9f72643b8fc252cef4cdf23e29fe064ae074dfe150a85d91cc83698","src/Windows/Win32/System/HostCompute/mod.rs":"128a34f564ce9b5241f8ea32c2fb7f823a660509bac6a4cd49ed69bb7346e728","src/Windows/Win32/System/HostComputeNetwork/mod.rs":"1568865224729da97e3ae2aec01bf9e2595ec8379f0191adcafcb20aa2fab1d7","src/Windows/Win32/System/HostComputeSystem/mod.rs":"bef988d2d76c40d0bbb77b81f811c7bcc766e3b59b07a9051ac76a2cf1fb90c4","src/Windows/Win32/System/Hypervisor/mod.rs":"215ce3706497cd6c935a518dcc40bf0ed78f7ee82679149c57e460787db62f7a","src/Windows/Win32/System/IO/mod.rs":"6488cd3decb96d7e0e83e556674cf4f8436931d799f7a86e7437ef97dda8660e","src/Windows/Win32/System/Iis/mod.rs":"c66fee548888b439ba1340778a3870c98a24e1b9f0b9db8a317df277583ae4ec","src/Windows/Win32/System/Ioctl/mod.rs":"e2ae22d1e07d9586fb61980784835d42c7ab54b43151aa74a56b5fa8b0672249","src/Windows/Win32/System/JobObjects/mod.rs":"45410125f4aaec823e36c7d68c86bf40879098cc2a0cebac969d04ba08a1ef58","src/Windows/Win32/System/Js/mod.rs":"c09797265f170f075485f08623cbdda8fa20fc277c37d941b7925c26446d67ff","src/Windows/Win32/System/Kernel/mod.rs":"03585feeb015913542d68ee10609725d372f8d83094f178f1bd18cab80ca88be","src/Windows/Win32/System/LibraryLoader/mod.rs":"03c6ba7b39cd63d1b9073465928c0e2f3fbf7ee6ec92262e9c864f596b55eb74","src/Windows/Win32/System/Mailslots/mod.rs":"043fdc8597e2f05a423f577923389d4f49b8dad8ac5b32ef32402992f4ce42aa","src/Windows/Win32/System/Mapi/mod.rs":"9f4b8ff581c141b6f79be2e0da1520ea7a869aa5a1e9c790755507abdeba1aa4","src/Windows/Win32/System/Memory/NonVolatile/mod.rs":"2672fd82e4cdcff746e174618a7243eafbd7c52e8b4d95de7b68b3c3afb3702c","src/Windows/Win32/System/Memory/mod.rs":"efa4bc12c33f715d7096ea3f582e65eb2720d37debf58764fadf36f6218ae63f","src/Windows/Win32/System/MessageQueuing/mod.rs":"24fe429da30d052254349c49048b36e60ae07c9fe5e45d2ed082111ee62a613c","src/Windows/Win32/System/MixedReality/mod.rs":"34a985476f50bdfd4d78410897962d69f2e52db6c6a626364bdf70860a42279b","src/Windows/Win32/System/Ole/mod.rs":"d3d4196c7e3f08d6fb193fd1991b60e7f4d45f45b56ebcba966a514dacbc5bcb","src/Windows/Win32/System/PasswordManagement/mod.rs":"948b79beeb324c878f62283f176090f5c348efb7a07c4e2cccc1e52524ec78ed","src/Windows/Win32/System/Performance/HardwareCounterProfiling/mod.rs":"794c452d4da8c13fceec76d5ea9346f91082dc74a003ad6d059a4050c3e149e5","src/Windows/Win32/System/Performance/mod.rs":"48fcfa03724690d1878c4690a3ad541c8d11065540ae7e5d923358247ade1e47","src/Windows/Win32/System/Pipes/mod.rs":"fcb982a3e590945e308cd7cead36d596ec425efd379b84d7c7eeb6779981b95c","src/Windows/Win32/System/Power/mod.rs":"defa33a0438046c08c716da7ddc17853cada024d1f30124dda0dc8dca53c975b","src/Windows/Win32/System/ProcessStatus/mod.rs":"ccf1ec510f71686cd2f946e7b78db571ff6f004e2ea2553a91a962d47d40b62e","src/Windows/Win32/System/Recovery/mod.rs":"1bfad927942ad4bad356b6903da74932be3698ae649ad64b59f172f1089e787a","src/Windows/Win32/System/Registry/mod.rs":"3dccaad2d607f25bd301c604cdb1fd5a65a771423c1945f130dc108689b64e12","src/Windows/Win32/System/RemoteDesktop/mod.rs":"f126140a22c0f4f3c89333385bac1e2967e756e75fbec1723c539f82e411626b","src/Windows/Win32/System/RemoteManagement/mod.rs":"5c6b6fc7921527679725122b7a2ca91c8f6912ac0781c6c096984fb82b661873","src/Windows/Win32/System/RestartManager/mod.rs":"b4e7233bd69e3a7ee28128da8b46d67d1c9f0ad30a5a881a9ef4c1f380a60fc9","src/Windows/Win32/System/Restore/mod.rs":"68edbac4b91925644041d3af65fb8fe19e27396a57f0383e9de1a385fe4558d3","src/Windows/Win32/System/Rpc/mod.rs":"a9249cd1232da6d0a689077600be964da37f6c67de108098345864856cb654cd","src/Windows/Win32/System/Search/Common/mod.rs":"9be8b496ca00d317d489d04e61ddaa47ae0b38a24b1bc16fabbde7dc001450c6","src/Windows/Win32/System/Search/mod.rs":"d7604d38d66fa4b05e33f7d4be2cb3e70af2d96e93fef8382ae6c5f532d8ebb3","src/Windows/Win32/System/SecurityCenter/mod.rs":"5e6be46cd0addd8777116291b2b689b0d80b09f636dec626bd0d8f7788437b86","src/Windows/Win32/System/Services/mod.rs":"23999c6d2249ed2d5e82b72496449c7342058bbaeb608f62f1b7d3ad5106bb30","src/Windows/Win32/System/SetupAndMigration/mod.rs":"d14b7414b79e72d10e44d2e81fe94b42acf770c8270f9bb1fc3f06a2d8647c71","src/Windows/Win32/System/Shutdown/mod.rs":"31e6f79f4a3a2d500ee38bc91ff164ba618b21e332fac9d7f9c1897307229623","src/Windows/Win32/System/StationsAndDesktops/mod.rs":"03cd113389fcb2337c06cbff36142ca764e737fe85921e0e020ea0b3dd2d0998","src/Windows/Win32/System/SubsystemForLinux/mod.rs":"5d0bd693d95c5015c24bf3caa98c0e992640f90e52edd407f8fd8fd45f65170d","src/Windows/Win32/System/SystemInformation/mod.rs":"15e25c04da5979826ca7f6e15de6ed788a61e0eb2e9215400dc7428d8dea70e2","src/Windows/Win32/System/SystemServices/mod.rs":"edd591c9ea164c7d6f4e7b7174f33054261a122a231f3ea8ce5cdacb5bcd2475","src/Windows/Win32/System/Threading/mod.rs":"6258ef99d17078002020644540a608a89cdf20436daefa3970a65348e6793c1c","src/Windows/Win32/System/Time/mod.rs":"1bfcb0aeb931adcab9b2739af96b1de90c3a43e29b510db9dccdacf6cc064587","src/Windows/Win32/System/TpmBaseServices/mod.rs":"16e445eb36e8f8124d3c6311d983cc4b7bbb5a2d1362a14ea5cdbac717884629","src/Windows/Win32/System/UserAccessLogging/mod.rs":"a668b512c3245bd85811a31d438504df260557a63225a80ed6ba0626e8539c80","src/Windows/Win32/System/Variant/mod.rs":"ac4697c87f732593f9d19f00e74ceaa59ed9b95abadd96068bce414d28cb4a8b","src/Windows/Win32/System/VirtualDosMachines/mod.rs":"f16da933dab5056880ef7b89645c767173b98d3569ad2bd55de3aa7f620252be","src/Windows/Win32/System/WindowsProgramming/mod.rs":"bec8a8dd0d79f57907b6d9227a66f27cbe3bc5e08184b72d596a91b0902a02b4","src/Windows/Win32/System/Wmi/mod.rs":"1cb49df5c1f918fffd8641890f1b18304f3cbc34a64894647551ec30d7f5068e","src/Windows/Win32/System/mod.rs":"1bd40cab9bc999eba658e06b15875b0ff419f6fbc60a261b982421b25fad5b86","src/Windows/Win32/UI/Accessibility/mod.rs":"eb8ea17d00dbdfaa0deb79737a517bc327139f2741406ff73af9dd604492ab67","src/Windows/Win32/UI/ColorSystem/mod.rs":"54c3d56ce9e16b54bfd4034e8b517f4b5559f7631e1e7817d7b27ee6115c694c","src/Windows/Win32/UI/Controls/Dialogs/mod.rs":"ae6da55cf126899dc7b172f75c9688b36e55996477c5c55013d67e80b1525f5f","src/Windows/Win32/UI/Controls/mod.rs":"f640c676c8c3511175fc2ffcf41f7d3486e139f1946b1573608a52bcfa411585","src/Windows/Win32/UI/HiDpi/mod.rs":"8e046edda260ef42d78340520f68d64e08a856916ceb824672f54f0546db01e6","src/Windows/Win32/UI/Input/Ime/mod.rs":"1a1d517ae3304be826625d56324c485196a83962ccf005a0cb1e8104075b324d","src/Windows/Win32/UI/Input/KeyboardAndMouse/mod.rs":"a227d3f977501620aafd4bef4bf804cae218d8a6c626e842153eefefcfcc69d5","src/Windows/Win32/UI/Input/Pointer/mod.rs":"a5cfbfd22782024da5e34b833ebecd43d2e2ac5f9fb7b29d3b8d244c65049b18","src/Windows/Win32/UI/Input/Touch/mod.rs":"d38a8e8a13fa1ab62580c236ed206abd56b5e839a53022821388f38a4b0261da","src/Windows/Win32/UI/Input/XboxController/mod.rs":"a8bd54ecce694b157d657133cfb4823534782655634d29f1aaad80fbbeb24210","src/Windows/Win32/UI/Input/mod.rs":"b98a96fa62ba85c88acc2e869170b8ff7306c08283a79439e7ec0258d7d8ec55","src/Windows/Win32/UI/InteractionContext/mod.rs":"56a01b7954c67177deb242b6f31f2488e55d85d5b4a1b4c0d34a06fda2c46d02","src/Windows/Win32/UI/Magnification/mod.rs":"fcbb8c27d177af82aea12523cde88b69466ba25ee9c961a3a96e89ccdfa004fd","src/Windows/Win32/UI/Shell/PropertiesSystem/mod.rs":"fcf02f6ca53cf565cd7a07bfe63f7d9fa1ce776947e4efb86fe73daeb3029be4","src/Windows/Win32/UI/Shell/mod.rs":"9d1a035392107171083e6c4a22d59770868a7381e4c3346f052b231aeda08083","src/Windows/Win32/UI/TabletPC/mod.rs":"f03aec1df3d3f756aad83497a124312d0f3e60b09c316692c48642937d51deb4","src/Windows/Win32/UI/TextServices/mod.rs":"4ea89ba3ae55fc1ccbb1395e0d9451cb25a9a452a7108aedcf0adec887039081","src/Windows/Win32/UI/WindowsAndMessaging/mod.rs":"9c3346a8efaaebbb297e8493a5599712744b13e673580b6f00dfb051d2a530c8","src/Windows/Win32/UI/mod.rs":"52fe9e33b44eb0bb6de1b4639f40e8ee6b104b57cc76d5bf61f6f519e32d6506","src/Windows/Win32/Web/InternetExplorer/mod.rs":"de5746ea7790d7b89cf8e22977c3eb1496ec11154f994d1860f84807a138c6f6","src/Windows/Win32/Web/mod.rs":"f9db4e7e91da18e453720cf471f03b899abcc09f8ecb48f666eb1014f1e29701","src/Windows/Win32/mod.rs":"61b768982158ba0a197638a3911fd0139b358d14e202a901b28af0b8b16bd6f0","src/Windows/mod.rs":"50beed6deaa8af370b7844f34b2bc58079defac61a293a63b349e98e9a8e420d","src/core/literals.rs":"285762703adf45db848a8fcf8e0e4556e44401fbdcb92c2b03dbf09f230cfe43","src/core/mod.rs":"8cb0ee31f5e9631f6e7f4ff3d29263e7c246a98d7865e5d29e97a6963952ad35","src/lib.rs":"99089ddba17b0bfdc77f3a877a5d572c4adebca10d02a31d79e63879fd58b99d"},"package":"282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f0a46a95cf21ffb73a508fe9248ab96c18b74e4a2cee3a16638b0e72cf2fa1ff","Cargo.toml":"ff53899cc9a441f18f66fd21c4784716a0aab5020a21cba5764ac8ee1e1f34cd","Cargo.toml.orig":"e3966aa39979c7b7b7e65bc771fd1f562d59605c33faeda8c13f441694f26aa6","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"3bcfa95b17c7748ff6139e7482ebad2d24645ac3606e4b4f88318c72122d1386","src/Windows/Wdk/Foundation/mod.rs":"20b32a858e9053cf60501c1bf73e9e73429b559a0ead1d0f99c18cf5c7f87c62","src/Windows/Wdk/Graphics/Direct3D/mod.rs":"b491612762294e97e9618771a7e11adaff190a3df3c5a1494da47de3f2e55bda","src/Windows/Wdk/Graphics/mod.rs":"d69902b8e241ff56d3cac2a648b40946d999dee0c21d8e54e5b471d612a10373","src/Windows/Wdk/Storage/FileSystem/Minifilters/mod.rs":"355133683c937771170226d4dc8917792397fffef5fa96a6032f8b05bd3656c6","src/Windows/Wdk/Storage/FileSystem/mod.rs":"baf35fbdc604cfc7caca64a1b7d71fc1cfc7188cf3991eee46258b43e0f60984","src/Windows/Wdk/Storage/mod.rs":"b393a8f908458c172fe5eaac195789f9719e0a5d7a9cb6dc980dbdb8bd198a44","src/Windows/Wdk/System/IO/mod.rs":"5395da986f92e7a8aee4b7796f1fa23a33024807f592d0f517e6e41799249073","src/Windows/Wdk/System/OfflineRegistry/mod.rs":"c1766ae9cc54a51c63596f4f6eb9d916b8a36218871d72e7c8a33d5aa8007b19","src/Windows/Wdk/System/Registry/mod.rs":"599fbaec01766b0a165c90c484affbcfd882f92d2705666c2737d09ce0efb4ba","src/Windows/Wdk/System/SystemInformation/mod.rs":"be972dfea89c1b8bd86947535f0e47644703db97d94542f2f0915ca738be8de3","src/Windows/Wdk/System/SystemServices/mod.rs":"90ccad952368d2b69ffdf7b08a89d9be1bc91eba9b419cf3588e87ac212c7eb7","src/Windows/Wdk/System/Threading/mod.rs":"0bf570e60e23bb281f2b6ed5ff3127666a46fd3b214247f61bc7f46557c092da","src/Windows/Wdk/System/mod.rs":"0f83083d4a2c6fce7307ef3fc4f6091eab211614da07a3d49bbfe9558f881b9f","src/Windows/Wdk/mod.rs":"d1f4517f7544f2d83935da1cdd3e03e4f0d58ddc76998c5886de142b717fa465","src/Windows/Win32/Data/HtmlHelp/mod.rs":"e7e6fdccea3ad91cda27ec6698c99df6fc01d1489042e65afa3f53d5db5f8cab","src/Windows/Win32/Data/RightsManagement/mod.rs":"aba7db25a328ff884a14d8bfd988dc58a5ff4ef35f40839779f22a2ebe76cb57","src/Windows/Win32/Data/mod.rs":"bf6a79c22d6cafc75f44a7bfc72c816e479a17987064b7adfaa3ec2750f01e41","src/Windows/Win32/Devices/AllJoyn/mod.rs":"02babd5b386a1472f2319f0101314ee0912895b1699d2abc7ea75488f2bd10db","src/Windows/Win32/Devices/BiometricFramework/mod.rs":"d024c6786852af281eba3eab483b3591147f14faf7c32ab0732304f6a90ea93b","src/Windows/Win32/Devices/Bluetooth/mod.rs":"d7b988c92870a9c5bed800025d8b5392e5c2533e19ee38d074b612aa6a064f0c","src/Windows/Win32/Devices/Communication/mod.rs":"a6949a741e3f3eb5d1e0b3a403b5755c59736249eb2c169cf7580c0c05336db4","src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs":"36b76cb25dac4381126c2d13b7b449083eea1511a3f10ef4a12843b1c14a23a9","src/Windows/Win32/Devices/DeviceQuery/mod.rs":"cd220d5ffeb7f540d539f55a23dffa11913b5c60ed21bc263dfb7957b6f342fe","src/Windows/Win32/Devices/Display/mod.rs":"4a256453c780ae2c5ae5c13212334daab42e659c559f72d9bbf24a5e7fa53bc8","src/Windows/Win32/Devices/Enumeration/Pnp/mod.rs":"88efec18d6dc9dd4ececc24b0ed62d829bead8e78ee069ecb420756cf6db8b69","src/Windows/Win32/Devices/Enumeration/mod.rs":"bcb6ce6da58560617f5faa1eeb2adeab4c5160eb4e86da6f9fc05b38c557c4e7","src/Windows/Win32/Devices/Fax/mod.rs":"235cc2691da29c401c168bd9a618f0e9004c754d157adbf09df60a7e9df732d2","src/Windows/Win32/Devices/HumanInterfaceDevice/mod.rs":"13291bbd8971833a93552add6917c60eec9461e55b7723cc32ebc863bb773361","src/Windows/Win32/Devices/PortableDevices/mod.rs":"183b9f9f3978ca10c9b38cfefe15ebe99034488883c526019ae48656001d1df6","src/Windows/Win32/Devices/Properties/mod.rs":"3a453aae0c83ef10b5c29fc136c7f1b86163e8167767f7326e1745dd78c3a2d4","src/Windows/Win32/Devices/Pwm/mod.rs":"c8a5d4566e51b614bb2e8bcdd0ce2650fea5e147160af4dae800ea054897e207","src/Windows/Win32/Devices/Sensors/mod.rs":"9e2411c07e1b3be2e283b9023793703c625c156acf978f476045ad484a2dbae6","src/Windows/Win32/Devices/SerialCommunication/mod.rs":"960a3ab21f2ac344a95dad9a79cfbc64e0bc67cbdec168f62d1cfd8741fccce4","src/Windows/Win32/Devices/Tapi/mod.rs":"d603565057b5964c9808d3a8e36a5093be1c04e3fb7bc9293139a510ceeac0b2","src/Windows/Win32/Devices/Usb/mod.rs":"cdf192649ab39b9ba76805b420bc93f8b8f1ea4c40fcece02c1f4e2c3eff24a5","src/Windows/Win32/Devices/WebServicesOnDevices/mod.rs":"c793c7a26a9ccd75e790ce361cbe65b3bbc418a6d4eb386a59af09bc361a008c","src/Windows/Win32/Devices/mod.rs":"48fec1cc37dcf54ac7c2838bd3a2b62ea3c5fd26fed08f27cc8aa511c19cbbe8","src/Windows/Win32/Foundation/mod.rs":"ee8378fd7a513d263aca8d5d441625965c746658f5a595f571d82e7a6cf71b36","src/Windows/Win32/Gaming/mod.rs":"de10172a298f1ec41c0bed43e828c7f8049142adc66faaf99103beb7dc0d54e8","src/Windows/Win32/Globalization/mod.rs":"232b0887d68c4b573b4bb3d39e95bc27da3897b930cb1eff3ad8da60d5d342e5","src/Windows/Win32/Graphics/Dwm/mod.rs":"2c0c64f25df323385c877c768263a1e69063aa7817530b825f28d34d15a39a7c","src/Windows/Win32/Graphics/Gdi/mod.rs":"7541447de1a074b92c93d003fdf2897a04f279127a36d69ab0e4ab09ea8dae49","src/Windows/Win32/Graphics/GdiPlus/mod.rs":"13460005d472709cf33b4b143889eae4c057ddff920d23591d9b2c4defb2081d","src/Windows/Win32/Graphics/Hlsl/mod.rs":"f0fa2ad8f50faa1e9ca1e3183c5ab8c10359e254c781237f32afae931d475bb6","src/Windows/Win32/Graphics/OpenGL/mod.rs":"813403eb3eeea3da519b0ecfd4cbf630b2e85a0cc0730221ec3d40bd0e279ba0","src/Windows/Win32/Graphics/Printing/PrintTicket/mod.rs":"a7c5bfe6011003ed5247aa0544b21139fcf204df2c50714b324a28ea869468bc","src/Windows/Win32/Graphics/Printing/mod.rs":"0022861c3801ae72ea99f9641737e3ad556de90aed87b009b8d8061c03dd5315","src/Windows/Win32/Graphics/mod.rs":"b553dc21e2ca071ff6e215e882d22088a8ddc7dd029bb1bff8b655649e913a52","src/Windows/Win32/Management/MobileDeviceManagementRegistration/mod.rs":"70b13306d1a000e8ce7a70a714f33df6b1ef296d66c86945440641809ce906d3","src/Windows/Win32/Management/mod.rs":"4deebf9977e6b947f904b3333a5bf63538bf30f879af29c9212433e93b53817a","src/Windows/Win32/Media/Audio/mod.rs":"e844e42702f51310d5c2e60fd896ee0ee24a1f78f2adb8a06405fe69e1802365","src/Windows/Win32/Media/DxMediaObjects/mod.rs":"b09cb6e430fd9b94c39d137f76fc60d6880921a1aec9fcea613d27d8fae84fac","src/Windows/Win32/Media/KernelStreaming/mod.rs":"1b707e8b3615be48e4e0daad48b42fb78d6e7f0b99e3d2670ba1ec6965cd08b6","src/Windows/Win32/Media/Multimedia/mod.rs":"1276ebad2ed99b04e372cffd1a9ed66f64b901b022d8b38a502622be7aee0bc4","src/Windows/Win32/Media/Streaming/mod.rs":"bf38a5cfaa87724f7a759568cb4bcbf74ea5e29f8c1c1bb1f531a551bbf16bbb","src/Windows/Win32/Media/WindowsMediaFormat/mod.rs":"ed7253ea6a7a3d239e062849d5e37d9910f86e6c403be2223fa156826045c5e1","src/Windows/Win32/Media/mod.rs":"66744d3f4ee3c78f123178b27e9bfc490409f99b9c6d4e7dddfad84963acd028","src/Windows/Win32/NetworkManagement/Dhcp/mod.rs":"e17a7a0354748584d8fac6c3aba986b929b41b08d8e77fe55b95c034351be24d","src/Windows/Win32/NetworkManagement/Dns/mod.rs":"b4c2610b0abd259ff039ead42dc20a29126c6b9af1b66bac9fc180977447af45","src/Windows/Win32/NetworkManagement/InternetConnectionWizard/mod.rs":"f18f3c55cd887bcec82c56c2503bfb85576066553a377aa1380e34d6dbb374c8","src/Windows/Win32/NetworkManagement/IpHelper/mod.rs":"eb0be9b2a840b83779427fca04b94e39070b84b8be6cfe30ad96cd5b7cca4580","src/Windows/Win32/NetworkManagement/Multicast/mod.rs":"4a0ac5e8dbf9ae5bc3af47ad7b30b8f1f621c5247b0e0277de9f09f4eaf18056","src/Windows/Win32/NetworkManagement/Ndis/mod.rs":"f5b83dead2d196ea9a4b92b524f467a7d4d8f620c7219aef903ac098b5a05716","src/Windows/Win32/NetworkManagement/NetBios/mod.rs":"7487268b11ea45c93d1b998db8fe7f0750d1a18d1682f59f22cf0273d7e505fa","src/Windows/Win32/NetworkManagement/NetManagement/mod.rs":"fa4490af37605395433f34e0d2e9670772d45ad736e6822dd75942f82cb8de7c","src/Windows/Win32/NetworkManagement/NetShell/mod.rs":"937b4a1dff5225891cfcf5bf0ae09d7ace9912d532fa0f6cbcca36575139c060","src/Windows/Win32/NetworkManagement/NetworkDiagnosticsFramework/mod.rs":"2b4582e3aa60d4fed836fdc5c63dd2a0fc1fb7ac548bcbf36c72f965b5d72a45","src/Windows/Win32/NetworkManagement/P2P/mod.rs":"5b90f05db45b73cb274bcb0c865984c417d8c8ba1dd01e71cb7032cc4f6d936c","src/Windows/Win32/NetworkManagement/QoS/mod.rs":"69a6221529057028ea2f2ae622ed596efa33e9847586f73e204b2d33d59d142a","src/Windows/Win32/NetworkManagement/Rras/mod.rs":"126b5b0ea795c7fd479e6e311c2d81e490161c2f1ce135e98ed2a266e762cc04","src/Windows/Win32/NetworkManagement/Snmp/mod.rs":"7086b06425e3e575f7d34b5564bb45c83144118ae6b7391c9793fd6c54ee5b03","src/Windows/Win32/NetworkManagement/WNet/mod.rs":"b9f82d5d392996569f46e2f8a596193ffa65c7168112faee644fc81d2ff70769","src/Windows/Win32/NetworkManagement/WebDav/mod.rs":"72c65f43a52d99536e31a2381b8a7b21b5c830a394554294e417ab414b105f73","src/Windows/Win32/NetworkManagement/WiFi/mod.rs":"ce30e91ffff192954e32f223a1fceb4d06c8dcd0e4169a1ad9bfe0769a7b3532","src/Windows/Win32/NetworkManagement/WindowsConnectionManager/mod.rs":"7a31e03d9d9f5fe7738f8683cac2c885762396904cdedca14abd1e8a38220c73","src/Windows/Win32/NetworkManagement/WindowsFilteringPlatform/mod.rs":"35cbc85ab0134c3413001d71d4e7f4cf2d2a038ef44b42e5e16bd33fe52c80a1","src/Windows/Win32/NetworkManagement/WindowsFirewall/mod.rs":"18e103f13e37d1f21fc695159cdf960b8c916a8a4f6e9a3c09123af0e5da3e02","src/Windows/Win32/NetworkManagement/WindowsNetworkVirtualization/mod.rs":"b4694a524e8c55c2b6accf3852f05cfa012682cfbc3b22283de42ddfe0791ebc","src/Windows/Win32/NetworkManagement/mod.rs":"bfc0e3c898d79ebe20e6fc711facade5b632b4ae121c28077b7eab6934ed1992","src/Windows/Win32/Networking/ActiveDirectory/mod.rs":"639a6d76b7c099104294543d0dae12ab3f8ae22b2af6ea5950f49de0a19f1c27","src/Windows/Win32/Networking/Clustering/mod.rs":"30b0d72782908fb57ec3e4923fc12e54cafef70f17a7ebdc66c90a3b400e1c82","src/Windows/Win32/Networking/HttpServer/mod.rs":"fdf6a9414fd6c46e02ee9d9df85faaef18a7432ce2072e29c2b7e0e2967f0dfa","src/Windows/Win32/Networking/Ldap/mod.rs":"8c3038199930128460e763962bd72d6578ac75a291bb739ef1e50832b4f0d1ba","src/Windows/Win32/Networking/WebSocket/mod.rs":"8a58e2faf42e55f2118e612c48b06de28e388686f396cfaf443e7891b96d8d9c","src/Windows/Win32/Networking/WinHttp/mod.rs":"4920431d66810c59711b74d4eb7ff2d50fd5fa2b4ee666269afaf2a874b4ab5b","src/Windows/Win32/Networking/WinInet/mod.rs":"2ebfd5512d3c225946ee26b7b805f67d332b1463288407d346119f61d2e19733","src/Windows/Win32/Networking/WinSock/mod.rs":"204bc39a8213167dcab8dd273c57e5fae3afbac8fa3887dbe43ad082d55446e4","src/Windows/Win32/Networking/WindowsWebServices/mod.rs":"0b6fb56d4e757a9bc51b3fffc4652bb489ee2f767fdd2a439113a586a6fdeeb7","src/Windows/Win32/Networking/mod.rs":"0429eb5803f0703acdb3ea0f1c819ea6e9efa4293d485320d91383e2fa642c69","src/Windows/Win32/Security/AppLocker/mod.rs":"c9ffaf5bf45f3a730cfd0b008d49b138eeea192e6a8620c9973692c2326f758b","src/Windows/Win32/Security/Authentication/Identity/mod.rs":"64fed7fade2b48818b75efbe17f9b247bc7d3a90fac42369d8aee4569d1f24a9","src/Windows/Win32/Security/Authentication/mod.rs":"65750cc9bb1cd1bd24313b7da49f25c99166fecbf5b3919dc3c01f37553ee371","src/Windows/Win32/Security/Authorization/mod.rs":"8f815ef1e07914982c627898d4dc071a703e86240e9a9f946878e3210bc23ac7","src/Windows/Win32/Security/Credentials/mod.rs":"156b04b25235957710a9198355d42c2bda40bfa273368caf9d8b20caedc69e6a","src/Windows/Win32/Security/Cryptography/Catalog/mod.rs":"69e110c8b0d6cbc2efb8def07d2f7953897c012c46b1aa0500a46404b6969d3a","src/Windows/Win32/Security/Cryptography/Certificates/mod.rs":"cd37ae782fe0d80933233397a0cea700e2879676213e40bb6b352fdba893a54d","src/Windows/Win32/Security/Cryptography/Sip/mod.rs":"746640f8b09a2c9407d89ea592fb0c1aa1d6d7b2c149c1d756c6daf36e68d8b9","src/Windows/Win32/Security/Cryptography/UI/mod.rs":"fb911ef0f1fdb3bdf041742d4788b6ac3c7e320454769a33c18daca6d5fe8b50","src/Windows/Win32/Security/Cryptography/mod.rs":"3c35607f54a387487e2fffbfd671ce17147e0d38097a1663b8541ea68c848cf5","src/Windows/Win32/Security/DiagnosticDataQuery/mod.rs":"72d7fa7bafd06809dc294f76c26c48e94373575e73d238ec254f03408486fc29","src/Windows/Win32/Security/DirectoryServices/mod.rs":"9257d98cf9f707df30a6021f00da4d91788958ce3a7bd86f1dd1a085b98018c2","src/Windows/Win32/Security/EnterpriseData/mod.rs":"4cdda8f31619584faf5a773801d2f99998a5f5876eb0da7bc503afd6e5cbf8f4","src/Windows/Win32/Security/ExtensibleAuthenticationProtocol/mod.rs":"7ac85b9ad3ba8a235e8ee91227b3394e23ac8f47c9c19579fb74ae7ebd7947de","src/Windows/Win32/Security/Isolation/mod.rs":"258bad95b793de887dfe695e6a5b703b01828cb5233849be66cee18a3b6411e8","src/Windows/Win32/Security/LicenseProtection/mod.rs":"17a51f78e1ad133a82c098466abbd1028f852853c98a7d606dda18a2509b9099","src/Windows/Win32/Security/NetworkAccessProtection/mod.rs":"72a2ea527b530a0118cedbd6b728057c0ab67ee78058e19978424858b1e6b0d7","src/Windows/Win32/Security/WinTrust/mod.rs":"b4a6a71e80f47a37aa05b25bab93654652d79f885fbed5d928193d99ae70e5f5","src/Windows/Win32/Security/WinWlx/mod.rs":"f0c149a46394bd173158d2741531c7af850cb1180d9915d43a88fdee9e2fa855","src/Windows/Win32/Security/mod.rs":"b35db507ad9380695f15b7ba798d0e677e08cc84b905577489d7e63994f00673","src/Windows/Win32/Storage/Cabinets/mod.rs":"e928f4da0c576de84077ccea0448153c5a5636bad49d6ae0dc6151e4abbe19db","src/Windows/Win32/Storage/CloudFilters/mod.rs":"c7dd7180ca25d9b2e01fb5951541c69aaa3d015c31b6a6bafaccc11fd18a8c9f","src/Windows/Win32/Storage/Compression/mod.rs":"22cb1e9b4abbcc3c9345c3b62c5cabac80c0f74dbbab870f09d4030db12f43ca","src/Windows/Win32/Storage/DistributedFileSystem/mod.rs":"81d1d8652a2c8432754b123f875efc65a661ecde241f4541c698ec4336f89283","src/Windows/Win32/Storage/FileHistory/mod.rs":"51155942044b1c84ffa018b18851fe54f262a49ada60fff8df763ee9c38f4924","src/Windows/Win32/Storage/FileSystem/mod.rs":"62de1e36d41b1efdb8651c887dae8fbfb0ca2dc34e4d3a789e716f50e424630d","src/Windows/Win32/Storage/Imapi/mod.rs":"85bc966fe8a9aee71ba7e526058369a96d0a5b14389b284f377ba4d1df2c1c87","src/Windows/Win32/Storage/IndexServer/mod.rs":"938958de534b65e1af2a4afad5b6911a783e7517a136ed792d8e602fba9abfa6","src/Windows/Win32/Storage/InstallableFileSystems/mod.rs":"5d5c5f27be6e2c89b4bbb5507624cdf99bcb46f39b9d64e65f3f39edef7f9a49","src/Windows/Win32/Storage/IscsiDisc/mod.rs":"9ddbf4dc3615b17e361143cae523b89d0e55f5088fe938c1009453acbe115c1e","src/Windows/Win32/Storage/Jet/mod.rs":"a9644cd862855d6d8ffd38b19563145446ee589c6c7a8f18e7b9c25962fbd490","src/Windows/Win32/Storage/Nvme/mod.rs":"24c768d01640b48f3a8406e80a05f588c7edbff273f573e32ef1222bcfe6550d","src/Windows/Win32/Storage/OfflineFiles/mod.rs":"1731e23074a8c92669460d6ff84ef7a26cf32f11265c3cb59e93038c84439ed8","src/Windows/Win32/Storage/OperationRecorder/mod.rs":"5999d081c94f8c2323951a7126813803299bb60217550a48a90437a69be99db0","src/Windows/Win32/Storage/Packaging/Appx/mod.rs":"fa76e97d4e7a502db5ee733430c6c6146ca75f973822ac0158ae2752c0cace42","src/Windows/Win32/Storage/Packaging/mod.rs":"f7f0994f7816af4d9f18d8336544b3a9c3db62a272f79ce91cb6a573e665be6e","src/Windows/Win32/Storage/ProjectedFileSystem/mod.rs":"114963523c77ac74fae655943ac9aeca3de2aaf6558255a7d4483f0660738601","src/Windows/Win32/Storage/StructuredStorage/mod.rs":"72d8e7ed6e51bbb128fe759b36a31d08e397a021d3b70cbcce79cac6dee4a977","src/Windows/Win32/Storage/Vhd/mod.rs":"b57e26dc3b8a217b608fd9204025914d6c2b25005f52357afd6f69fb5bc43c6e","src/Windows/Win32/Storage/Xps/mod.rs":"b10b39e4c54fbad143957d884bd1867c21cc5135ca47c8ecc351ed3f0fdfd44d","src/Windows/Win32/Storage/mod.rs":"6a382c16cd957177330437b3ed9747c77f7dfdc4e826a14e1213ceb66e17706a","src/Windows/Win32/System/AddressBook/mod.rs":"0c3c6a0e9071d2fdaf0c475cde725a8370346d16cb000ebea373a11c72443388","src/Windows/Win32/System/Antimalware/mod.rs":"71c50e08bc1767e70a710d306b1b64a89ecf00fa6974aec62db4af002c8b2228","src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs":"31c97e160a91fb59e9480970e2494119e83cce7f9e3f7945c7289347047037d5","src/Windows/Win32/System/ApplicationVerifier/mod.rs":"17c52576ab522266e72343d120252f0d4bb1e6b244ff9c5c5c38531a06d11ccf","src/Windows/Win32/System/ClrHosting/mod.rs":"fab866abe537be550bc3c77130b65e6106c53d933199a17f86fcf06ee75a8ae8","src/Windows/Win32/System/Com/Marshal/mod.rs":"1f04deab60c3ffa9a404486bf3aedf5799ef409393668513ee6645f5658829d5","src/Windows/Win32/System/Com/StructuredStorage/mod.rs":"56b25e3fbda76110db3e3c6335a4e27f703c7c7be9366e78d35f0f02d2994859","src/Windows/Win32/System/Com/Urlmon/mod.rs":"5bb352468e1c3487d54c8a8157a00dbb4a7385a565b7dc57ca07bd46c38f14ad","src/Windows/Win32/System/Com/mod.rs":"30e7c0b7ea3db8f9b9d9bafa85a3fbdd01070eb0cc43124306f210274f03cae5","src/Windows/Win32/System/ComponentServices/mod.rs":"7b2ba528379e4b22a7de4b61cadd925259cb972fb484da285c3360ca36e76ea4","src/Windows/Win32/System/Console/mod.rs":"a5eb9bef1283ad246c2171415afc4e0cd1626bcdeb8918d970e28f73b444cb14","src/Windows/Win32/System/CorrelationVector/mod.rs":"2170686b3dc82243a39c8e275cf5eb83a58d50ca5004324e9b3f99d0c54aaada","src/Windows/Win32/System/DataExchange/mod.rs":"197fb5fb49beb2653865bf1dead6193706be9900248d77eacc5733992f40b0ca","src/Windows/Win32/System/DeploymentServices/mod.rs":"3cb62aec8f2967d29f5efea0ffb1c48184fdedcc6d07f42e61fbd4a01e34252e","src/Windows/Win32/System/DeveloperLicensing/mod.rs":"30162501a442c7a8fa23ed72c9e6bf67768800fc170947b01f0bb09b64300deb","src/Windows/Win32/System/Diagnostics/Ceip/mod.rs":"ceda2ba33aa12edd1e02ad896320a35d0e7ea0f6d7b6ee5d53f28de18840ecf1","src/Windows/Win32/System/Diagnostics/Debug/Extensions/mod.rs":"04de20f10090af85880d15bef24029863fbdd18e069af06d47077a3f21f77b78","src/Windows/Win32/System/Diagnostics/Debug/mod.rs":"97be8fa2512bd4fb5c2097c8539e45a65ef75d7265eab01795252099291a7ae2","src/Windows/Win32/System/Diagnostics/Etw/mod.rs":"516ec30d47dc7633fded6f3b4612797bfdcd913386c6a718724b33d6ba4df2ac","src/Windows/Win32/System/Diagnostics/ProcessSnapshotting/mod.rs":"02d366ebf86d5d4a69821f72841789cd8e6a5e5982740f18088915e06224272b","src/Windows/Win32/System/Diagnostics/ToolHelp/mod.rs":"d8009a4856899743f52491fd1a6980f4fc4c8ca1f9e4a33751ccb31e32eb7934","src/Windows/Win32/System/Diagnostics/mod.rs":"26028a11b3e3bb236f387361b5866860d949379a91e65c6ea40eaf75ac8c9fe2","src/Windows/Win32/System/DistributedTransactionCoordinator/mod.rs":"19a760bac272c261189e25120c562988afcffc83ff792da604715a66d4d3f7e2","src/Windows/Win32/System/Environment/mod.rs":"56413bba141e59a0282467de796f47a922e4c8bd2dbb1a4fb7ec844cbad1a220","src/Windows/Win32/System/ErrorReporting/mod.rs":"20acdd9023d1b6586877556959fbc5c6858c8e775e3d2ee2728185410da99899","src/Windows/Win32/System/EventCollector/mod.rs":"acbbf978dfb0164de14f47c376b75f054bf98b68667be0f34f402082abe82df9","src/Windows/Win32/System/EventLog/mod.rs":"effc8b56a355a344456922ef5cdb7029f219396c7c0b118bef3ded086b4bb5f2","src/Windows/Win32/System/EventNotificationService/mod.rs":"9f7af63f6dd9e7056d68d8c8e2a52452a6c389563f0085d510242439e0df26f3","src/Windows/Win32/System/GroupPolicy/mod.rs":"50675fdcf9f72643b8fc252cef4cdf23e29fe064ae074dfe150a85d91cc83698","src/Windows/Win32/System/HostCompute/mod.rs":"128a34f564ce9b5241f8ea32c2fb7f823a660509bac6a4cd49ed69bb7346e728","src/Windows/Win32/System/HostComputeNetwork/mod.rs":"1568865224729da97e3ae2aec01bf9e2595ec8379f0191adcafcb20aa2fab1d7","src/Windows/Win32/System/HostComputeSystem/mod.rs":"bef988d2d76c40d0bbb77b81f811c7bcc766e3b59b07a9051ac76a2cf1fb90c4","src/Windows/Win32/System/Hypervisor/mod.rs":"215ce3706497cd6c935a518dcc40bf0ed78f7ee82679149c57e460787db62f7a","src/Windows/Win32/System/IO/mod.rs":"6488cd3decb96d7e0e83e556674cf4f8436931d799f7a86e7437ef97dda8660e","src/Windows/Win32/System/Iis/mod.rs":"c66fee548888b439ba1340778a3870c98a24e1b9f0b9db8a317df277583ae4ec","src/Windows/Win32/System/Ioctl/mod.rs":"e2ae22d1e07d9586fb61980784835d42c7ab54b43151aa74a56b5fa8b0672249","src/Windows/Win32/System/JobObjects/mod.rs":"45410125f4aaec823e36c7d68c86bf40879098cc2a0cebac969d04ba08a1ef58","src/Windows/Win32/System/Js/mod.rs":"c09797265f170f075485f08623cbdda8fa20fc277c37d941b7925c26446d67ff","src/Windows/Win32/System/Kernel/mod.rs":"03585feeb015913542d68ee10609725d372f8d83094f178f1bd18cab80ca88be","src/Windows/Win32/System/LibraryLoader/mod.rs":"03c6ba7b39cd63d1b9073465928c0e2f3fbf7ee6ec92262e9c864f596b55eb74","src/Windows/Win32/System/Mailslots/mod.rs":"043fdc8597e2f05a423f577923389d4f49b8dad8ac5b32ef32402992f4ce42aa","src/Windows/Win32/System/Mapi/mod.rs":"9f4b8ff581c141b6f79be2e0da1520ea7a869aa5a1e9c790755507abdeba1aa4","src/Windows/Win32/System/Memory/NonVolatile/mod.rs":"2672fd82e4cdcff746e174618a7243eafbd7c52e8b4d95de7b68b3c3afb3702c","src/Windows/Win32/System/Memory/mod.rs":"efa4bc12c33f715d7096ea3f582e65eb2720d37debf58764fadf36f6218ae63f","src/Windows/Win32/System/MessageQueuing/mod.rs":"24fe429da30d052254349c49048b36e60ae07c9fe5e45d2ed082111ee62a613c","src/Windows/Win32/System/MixedReality/mod.rs":"34a985476f50bdfd4d78410897962d69f2e52db6c6a626364bdf70860a42279b","src/Windows/Win32/System/Ole/mod.rs":"d3d4196c7e3f08d6fb193fd1991b60e7f4d45f45b56ebcba966a514dacbc5bcb","src/Windows/Win32/System/PasswordManagement/mod.rs":"948b79beeb324c878f62283f176090f5c348efb7a07c4e2cccc1e52524ec78ed","src/Windows/Win32/System/Performance/HardwareCounterProfiling/mod.rs":"794c452d4da8c13fceec76d5ea9346f91082dc74a003ad6d059a4050c3e149e5","src/Windows/Win32/System/Performance/mod.rs":"48fcfa03724690d1878c4690a3ad541c8d11065540ae7e5d923358247ade1e47","src/Windows/Win32/System/Pipes/mod.rs":"fcb982a3e590945e308cd7cead36d596ec425efd379b84d7c7eeb6779981b95c","src/Windows/Win32/System/Power/mod.rs":"defa33a0438046c08c716da7ddc17853cada024d1f30124dda0dc8dca53c975b","src/Windows/Win32/System/ProcessStatus/mod.rs":"ccf1ec510f71686cd2f946e7b78db571ff6f004e2ea2553a91a962d47d40b62e","src/Windows/Win32/System/Recovery/mod.rs":"1bfad927942ad4bad356b6903da74932be3698ae649ad64b59f172f1089e787a","src/Windows/Win32/System/Registry/mod.rs":"3dccaad2d607f25bd301c604cdb1fd5a65a771423c1945f130dc108689b64e12","src/Windows/Win32/System/RemoteDesktop/mod.rs":"f126140a22c0f4f3c89333385bac1e2967e756e75fbec1723c539f82e411626b","src/Windows/Win32/System/RemoteManagement/mod.rs":"5c6b6fc7921527679725122b7a2ca91c8f6912ac0781c6c096984fb82b661873","src/Windows/Win32/System/RestartManager/mod.rs":"b4e7233bd69e3a7ee28128da8b46d67d1c9f0ad30a5a881a9ef4c1f380a60fc9","src/Windows/Win32/System/Restore/mod.rs":"68edbac4b91925644041d3af65fb8fe19e27396a57f0383e9de1a385fe4558d3","src/Windows/Win32/System/Rpc/mod.rs":"a9249cd1232da6d0a689077600be964da37f6c67de108098345864856cb654cd","src/Windows/Win32/System/Search/Common/mod.rs":"9be8b496ca00d317d489d04e61ddaa47ae0b38a24b1bc16fabbde7dc001450c6","src/Windows/Win32/System/Search/mod.rs":"d7604d38d66fa4b05e33f7d4be2cb3e70af2d96e93fef8382ae6c5f532d8ebb3","src/Windows/Win32/System/SecurityCenter/mod.rs":"5e6be46cd0addd8777116291b2b689b0d80b09f636dec626bd0d8f7788437b86","src/Windows/Win32/System/Services/mod.rs":"23999c6d2249ed2d5e82b72496449c7342058bbaeb608f62f1b7d3ad5106bb30","src/Windows/Win32/System/SetupAndMigration/mod.rs":"d14b7414b79e72d10e44d2e81fe94b42acf770c8270f9bb1fc3f06a2d8647c71","src/Windows/Win32/System/Shutdown/mod.rs":"31e6f79f4a3a2d500ee38bc91ff164ba618b21e332fac9d7f9c1897307229623","src/Windows/Win32/System/StationsAndDesktops/mod.rs":"03cd113389fcb2337c06cbff36142ca764e737fe85921e0e020ea0b3dd2d0998","src/Windows/Win32/System/SubsystemForLinux/mod.rs":"5d0bd693d95c5015c24bf3caa98c0e992640f90e52edd407f8fd8fd45f65170d","src/Windows/Win32/System/SystemInformation/mod.rs":"15e25c04da5979826ca7f6e15de6ed788a61e0eb2e9215400dc7428d8dea70e2","src/Windows/Win32/System/SystemServices/mod.rs":"edd591c9ea164c7d6f4e7b7174f33054261a122a231f3ea8ce5cdacb5bcd2475","src/Windows/Win32/System/Threading/mod.rs":"6258ef99d17078002020644540a608a89cdf20436daefa3970a65348e6793c1c","src/Windows/Win32/System/Time/mod.rs":"1bfcb0aeb931adcab9b2739af96b1de90c3a43e29b510db9dccdacf6cc064587","src/Windows/Win32/System/TpmBaseServices/mod.rs":"16e445eb36e8f8124d3c6311d983cc4b7bbb5a2d1362a14ea5cdbac717884629","src/Windows/Win32/System/UserAccessLogging/mod.rs":"a668b512c3245bd85811a31d438504df260557a63225a80ed6ba0626e8539c80","src/Windows/Win32/System/Variant/mod.rs":"ac4697c87f732593f9d19f00e74ceaa59ed9b95abadd96068bce414d28cb4a8b","src/Windows/Win32/System/VirtualDosMachines/mod.rs":"f16da933dab5056880ef7b89645c767173b98d3569ad2bd55de3aa7f620252be","src/Windows/Win32/System/WindowsProgramming/mod.rs":"bec8a8dd0d79f57907b6d9227a66f27cbe3bc5e08184b72d596a91b0902a02b4","src/Windows/Win32/System/Wmi/mod.rs":"1cb49df5c1f918fffd8641890f1b18304f3cbc34a64894647551ec30d7f5068e","src/Windows/Win32/System/mod.rs":"1bd40cab9bc999eba658e06b15875b0ff419f6fbc60a261b982421b25fad5b86","src/Windows/Win32/UI/Accessibility/mod.rs":"eb8ea17d00dbdfaa0deb79737a517bc327139f2741406ff73af9dd604492ab67","src/Windows/Win32/UI/ColorSystem/mod.rs":"54c3d56ce9e16b54bfd4034e8b517f4b5559f7631e1e7817d7b27ee6115c694c","src/Windows/Win32/UI/Controls/Dialogs/mod.rs":"ae6da55cf126899dc7b172f75c9688b36e55996477c5c55013d67e80b1525f5f","src/Windows/Win32/UI/Controls/mod.rs":"f640c676c8c3511175fc2ffcf41f7d3486e139f1946b1573608a52bcfa411585","src/Windows/Win32/UI/HiDpi/mod.rs":"8e046edda260ef42d78340520f68d64e08a856916ceb824672f54f0546db01e6","src/Windows/Win32/UI/Input/Ime/mod.rs":"1a1d517ae3304be826625d56324c485196a83962ccf005a0cb1e8104075b324d","src/Windows/Win32/UI/Input/KeyboardAndMouse/mod.rs":"a227d3f977501620aafd4bef4bf804cae218d8a6c626e842153eefefcfcc69d5","src/Windows/Win32/UI/Input/Pointer/mod.rs":"a5cfbfd22782024da5e34b833ebecd43d2e2ac5f9fb7b29d3b8d244c65049b18","src/Windows/Win32/UI/Input/Touch/mod.rs":"d38a8e8a13fa1ab62580c236ed206abd56b5e839a53022821388f38a4b0261da","src/Windows/Win32/UI/Input/XboxController/mod.rs":"a8bd54ecce694b157d657133cfb4823534782655634d29f1aaad80fbbeb24210","src/Windows/Win32/UI/Input/mod.rs":"b98a96fa62ba85c88acc2e869170b8ff7306c08283a79439e7ec0258d7d8ec55","src/Windows/Win32/UI/InteractionContext/mod.rs":"56a01b7954c67177deb242b6f31f2488e55d85d5b4a1b4c0d34a06fda2c46d02","src/Windows/Win32/UI/Magnification/mod.rs":"fcbb8c27d177af82aea12523cde88b69466ba25ee9c961a3a96e89ccdfa004fd","src/Windows/Win32/UI/Shell/PropertiesSystem/mod.rs":"fcf02f6ca53cf565cd7a07bfe63f7d9fa1ce776947e4efb86fe73daeb3029be4","src/Windows/Win32/UI/Shell/mod.rs":"9d1a035392107171083e6c4a22d59770868a7381e4c3346f052b231aeda08083","src/Windows/Win32/UI/TabletPC/mod.rs":"f03aec1df3d3f756aad83497a124312d0f3e60b09c316692c48642937d51deb4","src/Windows/Win32/UI/TextServices/mod.rs":"4ea89ba3ae55fc1ccbb1395e0d9451cb25a9a452a7108aedcf0adec887039081","src/Windows/Win32/UI/WindowsAndMessaging/mod.rs":"9c3346a8efaaebbb297e8493a5599712744b13e673580b6f00dfb051d2a530c8","src/Windows/Win32/UI/mod.rs":"52fe9e33b44eb0bb6de1b4639f40e8ee6b104b57cc76d5bf61f6f519e32d6506","src/Windows/Win32/Web/InternetExplorer/mod.rs":"de5746ea7790d7b89cf8e22977c3eb1496ec11154f994d1860f84807a138c6f6","src/Windows/Win32/Web/mod.rs":"f9db4e7e91da18e453720cf471f03b899abcc09f8ecb48f666eb1014f1e29701","src/Windows/Win32/mod.rs":"61b768982158ba0a197638a3911fd0139b358d14e202a901b28af0b8b16bd6f0","src/Windows/mod.rs":"50beed6deaa8af370b7844f34b2bc58079defac61a293a63b349e98e9a8e420d","src/core/literals.rs":"285762703adf45db848a8fcf8e0e4556e44401fbdcb92c2b03dbf09f230cfe43","src/core/mod.rs":"8cb0ee31f5e9631f6e7f4ff3d29263e7c246a98d7865e5d29e97a6963952ad35","src/lib.rs":"99089ddba17b0bfdc77f3a877a5d572c4adebca10d02a31d79e63879fd58b99d"},"package":"282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "3a605cba064b26f2a198ac58085f8c8836f47c38" + }, + "path_in_vcs": "crates/libs/sys" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows-sys/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-sys/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,256 @@ +[package] +name = "windows-sys" +version = "0.52.0" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Rust for Windows" +repository = "https://github.com/microsoft/windows-rs" +readme = "readme.md" +categories = ["os::windows-apis"] + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] +all-features = true + +[dependencies.windows-targets] +version = "0.52.0" +path = "../targets" + +[features] +default = [] +docs = [] +# generated features +Wdk = [] +Wdk_Foundation = ["Wdk"] +Wdk_Graphics = ["Wdk"] +Wdk_Graphics_Direct3D = ["Wdk_Graphics"] +Wdk_Storage = ["Wdk"] +Wdk_Storage_FileSystem = ["Wdk_Storage"] +Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"] +Wdk_System = ["Wdk"] +Wdk_System_IO = ["Wdk_System"] +Wdk_System_OfflineRegistry = ["Wdk_System"] +Wdk_System_Registry = ["Wdk_System"] +Wdk_System_SystemInformation = ["Wdk_System"] +Wdk_System_SystemServices = ["Wdk_System"] +Wdk_System_Threading = ["Wdk_System"] +Win32 = [] +Win32_Data = ["Win32"] +Win32_Data_HtmlHelp = ["Win32_Data"] +Win32_Data_RightsManagement = ["Win32_Data"] +Win32_Devices = ["Win32"] +Win32_Devices_AllJoyn = ["Win32_Devices"] +Win32_Devices_BiometricFramework = ["Win32_Devices"] +Win32_Devices_Bluetooth = ["Win32_Devices"] +Win32_Devices_Communication = ["Win32_Devices"] +Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"] +Win32_Devices_DeviceQuery = ["Win32_Devices"] +Win32_Devices_Display = ["Win32_Devices"] +Win32_Devices_Enumeration = ["Win32_Devices"] +Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"] +Win32_Devices_Fax = ["Win32_Devices"] +Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"] +Win32_Devices_PortableDevices = ["Win32_Devices"] +Win32_Devices_Properties = ["Win32_Devices"] +Win32_Devices_Pwm = ["Win32_Devices"] +Win32_Devices_Sensors = ["Win32_Devices"] +Win32_Devices_SerialCommunication = ["Win32_Devices"] +Win32_Devices_Tapi = ["Win32_Devices"] +Win32_Devices_Usb = ["Win32_Devices"] +Win32_Devices_WebServicesOnDevices = ["Win32_Devices"] +Win32_Foundation = ["Win32"] +Win32_Gaming = ["Win32"] +Win32_Globalization = ["Win32"] +Win32_Graphics = ["Win32"] +Win32_Graphics_Dwm = ["Win32_Graphics"] +Win32_Graphics_Gdi = ["Win32_Graphics"] +Win32_Graphics_GdiPlus = ["Win32_Graphics"] +Win32_Graphics_Hlsl = ["Win32_Graphics"] +Win32_Graphics_OpenGL = ["Win32_Graphics"] +Win32_Graphics_Printing = ["Win32_Graphics"] +Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"] +Win32_Management = ["Win32"] +Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"] +Win32_Media = ["Win32"] +Win32_Media_Audio = ["Win32_Media"] +Win32_Media_DxMediaObjects = ["Win32_Media"] +Win32_Media_KernelStreaming = ["Win32_Media"] +Win32_Media_Multimedia = ["Win32_Media"] +Win32_Media_Streaming = ["Win32_Media"] +Win32_Media_WindowsMediaFormat = ["Win32_Media"] +Win32_NetworkManagement = ["Win32"] +Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"] +Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"] +Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"] +Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"] +Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"] +Win32_Networking = ["Win32"] +Win32_Networking_ActiveDirectory = ["Win32_Networking"] +Win32_Networking_Clustering = ["Win32_Networking"] +Win32_Networking_HttpServer = ["Win32_Networking"] +Win32_Networking_Ldap = ["Win32_Networking"] +Win32_Networking_WebSocket = ["Win32_Networking"] +Win32_Networking_WinHttp = ["Win32_Networking"] +Win32_Networking_WinInet = ["Win32_Networking"] +Win32_Networking_WinSock = ["Win32_Networking"] +Win32_Networking_WindowsWebServices = ["Win32_Networking"] +Win32_Security = ["Win32"] +Win32_Security_AppLocker = ["Win32_Security"] +Win32_Security_Authentication = ["Win32_Security"] +Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"] +Win32_Security_Authorization = ["Win32_Security"] +Win32_Security_Credentials = ["Win32_Security"] +Win32_Security_Cryptography = ["Win32_Security"] +Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"] +Win32_Security_DiagnosticDataQuery = ["Win32_Security"] +Win32_Security_DirectoryServices = ["Win32_Security"] +Win32_Security_EnterpriseData = ["Win32_Security"] +Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"] +Win32_Security_Isolation = ["Win32_Security"] +Win32_Security_LicenseProtection = ["Win32_Security"] +Win32_Security_NetworkAccessProtection = ["Win32_Security"] +Win32_Security_WinTrust = ["Win32_Security"] +Win32_Security_WinWlx = ["Win32_Security"] +Win32_Storage = ["Win32"] +Win32_Storage_Cabinets = ["Win32_Storage"] +Win32_Storage_CloudFilters = ["Win32_Storage"] +Win32_Storage_Compression = ["Win32_Storage"] +Win32_Storage_DistributedFileSystem = ["Win32_Storage"] +Win32_Storage_FileHistory = ["Win32_Storage"] +Win32_Storage_FileSystem = ["Win32_Storage"] +Win32_Storage_Imapi = ["Win32_Storage"] +Win32_Storage_IndexServer = ["Win32_Storage"] +Win32_Storage_InstallableFileSystems = ["Win32_Storage"] +Win32_Storage_IscsiDisc = ["Win32_Storage"] +Win32_Storage_Jet = ["Win32_Storage"] +Win32_Storage_Nvme = ["Win32_Storage"] +Win32_Storage_OfflineFiles = ["Win32_Storage"] +Win32_Storage_OperationRecorder = ["Win32_Storage"] +Win32_Storage_Packaging = ["Win32_Storage"] +Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"] +Win32_Storage_ProjectedFileSystem = ["Win32_Storage"] +Win32_Storage_StructuredStorage = ["Win32_Storage"] +Win32_Storage_Vhd = ["Win32_Storage"] +Win32_Storage_Xps = ["Win32_Storage"] +Win32_System = ["Win32"] +Win32_System_AddressBook = ["Win32_System"] +Win32_System_Antimalware = ["Win32_System"] +Win32_System_ApplicationInstallationAndServicing = ["Win32_System"] +Win32_System_ApplicationVerifier = ["Win32_System"] +Win32_System_ClrHosting = ["Win32_System"] +Win32_System_Com = ["Win32_System"] +Win32_System_Com_Marshal = ["Win32_System_Com"] +Win32_System_Com_StructuredStorage = ["Win32_System_Com"] +Win32_System_Com_Urlmon = ["Win32_System_Com"] +Win32_System_ComponentServices = ["Win32_System"] +Win32_System_Console = ["Win32_System"] +Win32_System_CorrelationVector = ["Win32_System"] +Win32_System_DataExchange = ["Win32_System"] +Win32_System_DeploymentServices = ["Win32_System"] +Win32_System_DeveloperLicensing = ["Win32_System"] +Win32_System_Diagnostics = ["Win32_System"] +Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"] +Win32_System_DistributedTransactionCoordinator = ["Win32_System"] +Win32_System_Environment = ["Win32_System"] +Win32_System_ErrorReporting = ["Win32_System"] +Win32_System_EventCollector = ["Win32_System"] +Win32_System_EventLog = ["Win32_System"] +Win32_System_EventNotificationService = ["Win32_System"] +Win32_System_GroupPolicy = ["Win32_System"] +Win32_System_HostCompute = ["Win32_System"] +Win32_System_HostComputeNetwork = ["Win32_System"] +Win32_System_HostComputeSystem = ["Win32_System"] +Win32_System_Hypervisor = ["Win32_System"] +Win32_System_IO = ["Win32_System"] +Win32_System_Iis = ["Win32_System"] +Win32_System_Ioctl = ["Win32_System"] +Win32_System_JobObjects = ["Win32_System"] +Win32_System_Js = ["Win32_System"] +Win32_System_Kernel = ["Win32_System"] +Win32_System_LibraryLoader = ["Win32_System"] +Win32_System_Mailslots = ["Win32_System"] +Win32_System_Mapi = ["Win32_System"] +Win32_System_Memory = ["Win32_System"] +Win32_System_Memory_NonVolatile = ["Win32_System_Memory"] +Win32_System_MessageQueuing = ["Win32_System"] +Win32_System_MixedReality = ["Win32_System"] +Win32_System_Ole = ["Win32_System"] +Win32_System_PasswordManagement = ["Win32_System"] +Win32_System_Performance = ["Win32_System"] +Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"] +Win32_System_Pipes = ["Win32_System"] +Win32_System_Power = ["Win32_System"] +Win32_System_ProcessStatus = ["Win32_System"] +Win32_System_Recovery = ["Win32_System"] +Win32_System_Registry = ["Win32_System"] +Win32_System_RemoteDesktop = ["Win32_System"] +Win32_System_RemoteManagement = ["Win32_System"] +Win32_System_RestartManager = ["Win32_System"] +Win32_System_Restore = ["Win32_System"] +Win32_System_Rpc = ["Win32_System"] +Win32_System_Search = ["Win32_System"] +Win32_System_Search_Common = ["Win32_System_Search"] +Win32_System_SecurityCenter = ["Win32_System"] +Win32_System_Services = ["Win32_System"] +Win32_System_SetupAndMigration = ["Win32_System"] +Win32_System_Shutdown = ["Win32_System"] +Win32_System_StationsAndDesktops = ["Win32_System"] +Win32_System_SubsystemForLinux = ["Win32_System"] +Win32_System_SystemInformation = ["Win32_System"] +Win32_System_SystemServices = ["Win32_System"] +Win32_System_Threading = ["Win32_System"] +Win32_System_Time = ["Win32_System"] +Win32_System_TpmBaseServices = ["Win32_System"] +Win32_System_UserAccessLogging = ["Win32_System"] +Win32_System_Variant = ["Win32_System"] +Win32_System_VirtualDosMachines = ["Win32_System"] +Win32_System_WindowsProgramming = ["Win32_System"] +Win32_System_Wmi = ["Win32_System"] +Win32_UI = ["Win32"] +Win32_UI_Accessibility = ["Win32_UI"] +Win32_UI_ColorSystem = ["Win32_UI"] +Win32_UI_Controls = ["Win32_UI"] +Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"] +Win32_UI_HiDpi = ["Win32_UI"] +Win32_UI_Input = ["Win32_UI"] +Win32_UI_Input_Ime = ["Win32_UI_Input"] +Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"] +Win32_UI_Input_Pointer = ["Win32_UI_Input"] +Win32_UI_Input_Touch = ["Win32_UI_Input"] +Win32_UI_Input_XboxController = ["Win32_UI_Input"] +Win32_UI_InteractionContext = ["Win32_UI"] +Win32_UI_Magnification = ["Win32_UI"] +Win32_UI_Shell = ["Win32_UI"] +Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"] +Win32_UI_TabletPC = ["Win32_UI"] +Win32_UI_TextServices = ["Win32_UI"] +Win32_UI_WindowsAndMessaging = ["Win32_UI"] +Win32_Web = ["Win32"] +Win32_Web_InternetExplorer = ["Win32_Web"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"bc53e92f81d6744d83d59a3161ae21df6ba5e7794b4922b243fd5a0e4cd9ca0e","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"091f8b1d0c59ae0bf8d464a4f4d5c314907f7e2e29eca686bd42929a7df50b9b","src/lib.rs":"0605ad98583e44549d5bd02291fb84ea628857f3700c81844beb16f00e10c47a"},"package":"6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5e4ae79f3b0de025ff23fb0032eb4d2355168e1ed51cae35b436695d4ab5e7ea","Cargo.toml":"bc53e92f81d6744d83d59a3161ae21df6ba5e7794b4922b243fd5a0e4cd9ca0e","Cargo.toml.orig":"4a2d52c20b7c1ffc0fb961c4ea76774bca3739a0ac8b9b2f1700ad0678e20def","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"091f8b1d0c59ae0bf8d464a4f4d5c314907f7e2e29eca686bd42929a7df50b9b","src/lib.rs":"0605ad98583e44549d5bd02291fb84ea628857f3700c81844beb16f00e10c47a"},"package":"6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/libs/targets" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows-targets/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows-targets/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,38 @@ + +[package] +name = "windows-targets" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import libs for Windows" +repository = "https://github.com/microsoft/windows-rs" +readme = "readme.md" + +[lints] +workspace = true + +[target.'cfg(all(target_arch = "x86", target_env = "msvc", not(windows_raw_dylib)))'.dependencies] +windows_i686_msvc = { path = "../../targets/i686_msvc", version = "0.52.5" } + +[target.'cfg(all(any(target_arch = "x86_64", target_arch = "arm64ec"), target_env = "msvc", not(windows_raw_dylib)))'.dependencies] +windows_x86_64_msvc = { path = "../../targets/x86_64_msvc", version = "0.52.5" } + +[target.'cfg(all(target_arch = "aarch64", target_env = "msvc", not(windows_raw_dylib)))'.dependencies] +windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.52.5" } + +[target.'cfg(all(target_arch = "x86", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))'.dependencies] +windows_i686_gnu = { path = "../../targets/i686_gnu", version = "0.52.5" } + +[target.'cfg(all(target_arch = "x86_64", target_env = "gnu", not(target_abi = "llvm"), not(windows_raw_dylib)))'.dependencies] +windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.52.5" } + +[target.i686-pc-windows-gnullvm.dependencies] +windows_i686_gnullvm = { path = "../../targets/i686_gnullvm", version = "0.52.5" } + +[target.x86_64-pc-windows-gnullvm.dependencies] +windows_x86_64_gnullvm = { path = "../../targets/x86_64_gnullvm", version = "0.52.5" } + +[target.aarch64-pc-windows-gnullvm.dependencies] +windows_aarch64_gnullvm = { path = "../../targets/aarch64_gnullvm", version = "0.52.5" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"5bce7856d20a6a17a029b12b46354ed586d43592c8c021c8ffa237c5fcf35dfc","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"8583b882d3030faa43cae37d5f040ad2917278df9c7e85975f51767628b53396","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ec6ea0c7340ce3d93e9cadf8f436a4e784cde4fda027a339fb96e9c8ce6fb707","Cargo.toml":"5bce7856d20a6a17a029b12b46354ed586d43592c8c021c8ffa237c5fcf35dfc","Cargo.toml.orig":"9d24b32d201f850856650790e39be5905a8881e3addfb10510a04d2062f61685","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"8583b882d3030faa43cae37d5f040ad2917278df9c7e85975f51767628b53396","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/aarch64_gnullvm" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_gnullvm/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_gnullvm/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"01611c00552e077ba6b0aa1a2bfdd25d1aa8157cb453cc3e1e092610c609b2ea","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"33ed26f6a49d4dff5d807fda0e82c7a75d2b7ef068ef1aaa153bef3989b1409d","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"2c75eb0bdf3a7aad686c87c868ab32e929ac01e2f82855e570d9c6db170e36fd","Cargo.toml":"01611c00552e077ba6b0aa1a2bfdd25d1aa8157cb453cc3e1e092610c609b2ea","Cargo.toml.orig":"77a3ee19fa9ad5e21885c3d0fc5a2ecb8d99ffd5d976097202ad2fd591580d6b","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"33ed26f6a49d4dff5d807fda0e82c7a75d2b7ef068ef1aaa153bef3989b1409d","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/aarch64_msvc" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_aarch64_msvc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_aarch64_msvc/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_aarch64_msvc" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"9653fad6c637ee915f272aad4cfe67cf31242d6a2fd96124e571a36213e0ee0f","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"f5e34350f9909e631c3e44b01c1d8b87204faecf1aa45118c5499bb9e76eeedd","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"0e686a5cd3672426b81afe2a591f4ad8a408c8b7433760bdeef06c194ff6b8de","Cargo.toml":"9653fad6c637ee915f272aad4cfe67cf31242d6a2fd96124e571a36213e0ee0f","Cargo.toml.orig":"ced33dae5f2149a2d604d7bc0565697a43c7e32adcb69bb25ae20f47d5cbd223","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"f5e34350f9909e631c3e44b01c1d8b87204faecf1aa45118c5499bb9e76eeedd","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/i686_gnu" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnu/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnu/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_i686_gnu" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"6405f908afd6b1f48b7a726ccca5a7aa5cc73725b22308c6cd29bb43cece30a7","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"d621a17fa48dd94ed99dc3f2778c149f37bccd9b9b198bf985ad2286eff9eea1","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"c13024cdef057b2c1689673cc62ce679b9eceb66dfc54412e6caf8a8d6d0c8a1","Cargo.toml":"6405f908afd6b1f48b7a726ccca5a7aa5cc73725b22308c6cd29bb43cece30a7","Cargo.toml.orig":"57a0f18bf153d2ab4ced32d851053eac923ff756be8bf9282dacd06a441f3222","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"d621a17fa48dd94ed99dc3f2778c149f37bccd9b9b198bf985ad2286eff9eea1","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/i686_gnullvm" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_gnullvm/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_gnullvm/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_i686_gnullvm" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"405cd9bed75f895c16b57194f7a0bedab3b606d49b1dd34c791efbc489076afd","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"14a27a20c732f4c0d44c629b4d19a3a191675e55d1b2283a4a51782115914943","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3dd17a591805e36ab1c8b51791a41f5326cfccec4f5e57bf878dc9ba22cb25ca","Cargo.toml":"405cd9bed75f895c16b57194f7a0bedab3b606d49b1dd34c791efbc489076afd","Cargo.toml.orig":"52999f058a00ff6003959c90d15d40cc1776710b6d9efa89e21c9a78be2464c8","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"14a27a20c732f4c0d44c629b4d19a3a191675e55d1b2283a4a51782115914943","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/i686_msvc" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_i686_msvc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_i686_msvc/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_i686_msvc" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"eb28ed71f562685b15ddf6bacd58c1893555d1a66f28217a8134fa72c1418ef2","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"111a6f2a6284312da2f2d6aba570e5c4f5c50e481203d67f5c7a018f7cf14c33","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"fd58438751008fbc90704da6bb985fc3a2ed6b62bab1422c8a491bfeb0efede6","Cargo.toml":"eb28ed71f562685b15ddf6bacd58c1893555d1a66f28217a8134fa72c1418ef2","Cargo.toml.orig":"b9395fd23ed67b90c3f2f553bf08c713e13e023b560d7d44c3e97f30c2f2ecd8","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"111a6f2a6284312da2f2d6aba570e5c4f5c50e481203d67f5c7a018f7cf14c33","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/x86_64_gnu" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnu/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnu/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_x86_64_gnu" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"406147928a3348d0e864caa9c55422c95f2cdbf9420e5b62b59c08a2b40bc052","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"fd2be1fc2b9514d4cc68a8b3bcf29f1ca5b8a948fc0d70fefd5581a6649b45c1","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e60e74ed869b34804575862a65509da96bde4e90e0d768417e9eb62797d3660a","Cargo.toml":"406147928a3348d0e864caa9c55422c95f2cdbf9420e5b62b59c08a2b40bc052","Cargo.toml.orig":"47f8a8b6adb0d80d1aacba59f6b23553d164b2fcf8e2ed3fea33439b3e850680","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/libwindows.0.52.0.a":"fd2be1fc2b9514d4cc68a8b3bcf29f1ca5b8a948fc0d70fefd5581a6649b45c1","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/x86_64_gnullvm" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_gnullvm/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_gnullvm/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"1a525a53037c66b2eaf6428af7be96be0caaadf7b2bb55ee854eb1519a1d8d3e","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"62a75b87a720e0e9bb3cf526c4b95a456c85440be30bcda291ab5c7fdb1465b4","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"8d23d77fdd02e7ab8808baabd0ec390be9a37cd512b45bc7f6de00d3cc1de342","Cargo.toml":"1a525a53037c66b2eaf6428af7be96be0caaadf7b2bb55ee854eb1519a1d8d3e","Cargo.toml.orig":"8e63dca2c446338439c16c17d806d8651a110b7fe6534f6c0c10e0e9e100e29d","build.rs":"9a83c55ec67fd48d6df4adccfbe0f3245f4002b543cacb586005d8991bddb29e","lib/windows.0.52.0.lib":"62a75b87a720e0e9bb3cf526c4b95a456c85440be30bcda291ab5c7fdb1465b4","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/lib.rs":"bdf6c7cf1fc01f69cc1d4e52948d1f246fdd310e6323d5dd1efd23f1daf382ef"},"package":"bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ae896c59e4d05895cb17d3b2c3c7c56ccac47207" + }, + "path_in_vcs": "crates/targets/x86_64_msvc" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/windows_x86_64_msvc/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/windows_x86_64_msvc/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "windows_x86_64_msvc" +version = "0.52.5" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.56" +license = "MIT OR Apache-2.0" +description = "Import lib for Windows" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"03d9d161e240da3907c919286b81543af846e48c233bc5f6a60bd2906046f2ee","Cargo.lock":"39845fc193494629191da865e9fd1e7a9fd135c837ac75569627f7c009d093dc","Cargo.toml":"871d1bbb96cf118398ccaa8df5997eeb5e9d97c7d3392227cbe0020d5c8fb6b4","Cargo.toml.orig":"ea40499885c848463b2efa2600f2be2a07bc0cb4b1bb2323ce36bac471f478f8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-Apache-2.0_WITH_LLVM-exception":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4473d64adb6b173923f3acfd525b81aab1912dc0bc625a3643c132d7a8be3079","build.rs":"99b4276049457d3ea1d304277d66b0ff1abba0b9b1f5d60a5e25bdd3fd897a91","src/examples.rs":"c7329d7518ddcd42436d62fc4ffcb552d9920c95f3483b6426f0921268866665","src/examples/_0_world_imports.rs":"99d00cb52b5b12bdbafa1e5834e2d4f5e7f7b462a06a07e40becd18b01cd8ded","src/examples/_1_interface_imports.rs":"5cc5031ec71e1715efcd955a512ead215949ce0a8b2890d995fda7df2c3095b2","src/examples/_2_imported_resources.rs":"b29ca6f519cba51706e3ef201705a0daf8d4347d47a54b4780603fc7322d9d60","src/examples/_3_world_exports.rs":"1e4ddab02890bacc2793fa2f1dd7137e39bbb6f56e855c9a9232336915caf37d","src/examples/_4_exported_resources.rs":"68b5d95a370a89cceff82a54915d15d9c848da01d3bff65077508766f18afe93","src/lib.rs":"9cf176a10b2cabe19f97f7a995dc37d4269e69b97ad6382655252889b0e01e42","src/rt/async_support.rs":"35bc6439add5f95e9fca98f4a6b73494e429d1d6d589bbae3038d19097bc4a3c","src/rt/async_support/abi_buffer.rs":"60b1f04630a969eb74438961b00e94fb4e71882369b53966c5d022ccaa4aeab1","src/rt/async_support/cabi.rs":"ebd8e18ad9c7a97fdaa19de56338e63d36f4caa43f1ce059855e6ca46a6db034","src/rt/async_support/error_context.rs":"0ca2af5e1cce94194ac5edea3ba35f1b270e4af05c3d7d78ec4ebc8e22dda598","src/rt/async_support/future_support.rs":"30bec93f0cd5a7adfea044714d1c49ea9d3390e3f5a9c9c515366e8475f75421","src/rt/async_support/stream_support.rs":"8d5754b6ab5dbf1ab2de4c792c4ea93640775577374ad665e6b49ca632210c97","src/rt/async_support/subtask.rs":"ee1037a7aabba768b42a18d412badaf5bb967bc4961534288c3847d8484204a5","src/rt/async_support/waitable.rs":"2038cb5cfa53d45e279ec3d6e9a4f5cf254d6cd41a1db48f66c6c21b9d18cd7f","src/rt/async_support/waitable_set.rs":"1c8bbc28da16d3e952e174950033be3617cbc12b93ca39bdb4ba58b74f63fa09","src/rt/libwit_bindgen_cabi.a":"4ac348f17776441d20db02cf6e0fb40ff5f31c0cb326eb53b289974219dbebf2","src/rt/mod.rs":"ca1f66a571ecb3cf2b4f1cbca75cb735dcb6e8091ece69d04ab4d15e27a5fdc0","src/rt/wit_bindgen_cabi.c":"73afa563433ba0238534b9c18cdb233366804568db165ccdf26f57b676a13fe8","src/rt/wit_bindgen_cabi.o":"aa94fc26a2829b9da6ca20b14eb5a14cf8c195a615fcaeb7ed47db3c2e0bdbeb","src/rt/wit_bindgen_cabi_realloc.c":"329055acad8d5e71d930bcdf88dce6c5f8e7b02865a2124df4261423586d733a","src/rt/wit_bindgen_cabi_realloc.o":"029c7cc5104b17890d248767b3d9057bcd99e82427c00992dd660e725a867c93","src/rt/wit_bindgen_cabi_realloc.rs":"4c9699d9c912a4341acf88f56b6af7665fe1a69d64198dbaa713ad7e8108609c","src/rt/wit_bindgen_cabi_wasip3.c":"ddb8eedcfdd53c07382d005f7d75bd7d7513c6c647814cab01a5128c2ac6a94e","src/rt/wit_bindgen_cabi_wasip3.o":"a5f701492faa0c6f27e21c33572123bcfeadab2c9f41d6e5c8f896535824e617","wasi-cli@0.2.0.wasm":"60b274319c9dce183269a0e3ad922b8ee4ead915f34d171de9da23a390863119"},"package":"f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4c0e9a4edb73efb7b41758562eb0055c0e99cf92" + }, + "path_in_vcs": "crates/guest-rust" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,428 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "foldhash", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "prettyplease" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d441c3b2ebf55cebf796bfdc265d67fa09db17b7bb6bd4be75c509e1e8fec3" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9c45b374136f52f2d6311062c7146bff20fec063c3f5d46a410bd937746955" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wasm-encoder" +version = "0.239.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.239.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.239.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" +dependencies = [ + "bitflags", + "hashbrown", + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +dependencies = [ + "bitflags", + "futures", + "once_cell", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabd629f94da277abc739c71353397046401518efb2c707669f805205f0b9890" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a4232e841089fa5f3c4fc732a92e1c74e1a3958db3b12f1de5934da2027f1f4" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0d4698c2913d8d9c2b220d116409c3f51a7aa8d7765151b886918367179ee9" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.239.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a866b19dba2c94d706ec58c92a4c62ab63e482b4c935d2a085ac94caecb136" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.239.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55c92c939d667b7bf0c6bf2d1f67196529758f99a2a45a3355cc56964fd5315d" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.82.0" +name = "wit-bindgen" +version = "0.46.0" +authors = ["Alex Crichton "] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Rust bindings generator and runtime support for WIT and the component model. +Used when compiling Rust programs to the component model. +""" +homepage = "https://github.com/bytecodealliance/wit-bindgen" +readme = "README.md" +license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" +repository = "https://github.com/bytecodealliance/wit-bindgen" + +[package.metadata.docs.rs] +all-features = true + +[features] +async = [ + "macros", + "std", + "dep:futures", + "dep:once_cell", + "wit-bindgen-rust-macro/async", +] +bitflags = ["dep:bitflags"] +default = [ + "macros", + "realloc", + "async", + "std", + "bitflags", +] +macros = ["dep:wit-bindgen-rust-macro"] +realloc = [] +rustc-dep-of-std = [ + "dep:core", + "dep:alloc", +] +std = [] + +[lib] +name = "wit_bindgen" +path = "src/lib.rs" + +[dependencies.alloc] +version = "1.0" +optional = true +package = "rustc-std-workspace-alloc" + +[dependencies.bitflags] +version = "2.3.3" +optional = true + +[dependencies.core] +version = "1.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.futures] +version = "0.3.30" +optional = true + +[dependencies.once_cell] +version = "1.19.0" +optional = true + +[dependencies.wit-bindgen-rust-macro] +version = "0.46.0" +optional = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +[package] +name = "wit-bindgen" +authors = ["Alex Crichton "] +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } +homepage = 'https://github.com/bytecodealliance/wit-bindgen' +description = """ +Rust bindings generator and runtime support for WIT and the component model. +Used when compiling Rust programs to the component model. +""" + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +wit-bindgen-rust-macro = { path = "./macro", optional = true, version = "0.46.0" } +bitflags = { workspace = true, optional = true } +futures = { version = "0.3.30", optional = true } +once_cell = { version = "1.19.0", optional = true } + +# When built as part of libstd +core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" } +alloc = { version = "1.0", optional = true, package = "rustc-std-workspace-alloc" } + +[features] +default = ["macros", "realloc", "async", "std", "bitflags"] +macros = ["dep:wit-bindgen-rust-macro"] +realloc = [] +std = [] +async = ["macros", "std", "dep:futures", "dep:once_cell", "wit-bindgen-rust-macro/async"] +bitflags = ["dep:bitflags"] + +# Unstable feature to support being a libstd dependency +rustc-dep-of-std = ["dep:core", "dep:alloc"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-Apache-2.0_WITH_LLVM-exception clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-Apache-2.0_WITH_LLVM-exception --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-Apache-2.0_WITH_LLVM-exception 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-Apache-2.0_WITH_LLVM-exception 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,220 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://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. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/README.md clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +
+

wit-bindgen

+ +

+ Guest Rust language bindings generator for + WIT + and the + Component Model + +

+ +A Bytecode Alliance project + +

+ supported rustc stable + Documentation Status +

+
+ +# About + +This crate provides a macro, [`generate!`], to automatically generate Rust +bindings for a [WIT] [world]. For more information about this crate see the +[online documentation] which includes some examples and longer form reference +documentation as well. + +This crate is developed as a portion of the [`wit-bindgen` repository] which +also contains a CLI and generators for other languages. + +[`generate!`]: https://docs.rs/wit-bindgen/latest/wit_bindgen/macro.generate.html +[WIT]: https://component-model.bytecodealliance.org/design/wit.html +[world]: https://component-model.bytecodealliance.org/design/worlds.html +[online documentation]: https://docs.rs/wit-bindgen +[`wit-bindgen` repository]: https://github.com/bytecodealliance/wit-bindgen + +# License + +This project is licensed under the Apache 2.0 license with the LLVM exception. +See [LICENSE](LICENSE) for more details. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this project by you, as defined in the Apache-2.0 license, +shall be licensed as above, without any additional terms or conditions. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/build.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or(String::new()); + let target_family = env::var("CARGO_CFG_TARGET_FAMILY").unwrap_or(String::new()); + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + if target_family != "wasm" { + return; + } + + if target_arch != "wasm32" { + panic!("only wasm32 supports cabi-realloc right now"); + } + + let mut src = env::current_dir().unwrap(); + src.push("src"); + src.push("rt"); + src.push("libwit_bindgen_cabi.a"); + + let dst_name = format!( + "wit_bindgen_cabi{}", + env!("CARGO_PKG_VERSION").replace(".", "_") + ); + let dst = out_dir.join(format!("lib{dst_name}.a")); + + std::fs::copy(&src, &dst).unwrap(); + + println!("cargo:rustc-link-lib=static={dst_name}"); + println!("cargo:rustc-link-search=native={}", out_dir.display()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_0_world_imports.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_0_world_imports.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_0_world_imports.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_0_world_imports.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +crate::generate!({ + inline: r#" + package example:world-imports; + + world with-imports { + /// Fetch a greeting to present. + import greet: func() -> string; + + /// Log a message to the host. + import log: func(msg: string); + + import my-custom-host: interface { + tick: func(); + } + } + "#, +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_1_interface_imports.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_1_interface_imports.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_1_interface_imports.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_1_interface_imports.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +crate::generate!({ + inline: r#" + package example:interface-imports; + + interface logging { + enum level { + debug, + info, + warn, + error, + } + + log: func(level: level, msg: string); + } + + world with-imports { + // Local interfaces can be imported. + import logging; + + // Dependencies can also be referenced, and they're loaded from the + // `path` directive specified below. + import wasi:cli/environment@0.2.0; + } + "#, + + path: "wasi-cli@0.2.0.wasm", + + // specify that this interface dependency should be generated as well. + with: { + "wasi:cli/environment@0.2.0": generate, + } +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_2_imported_resources.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_2_imported_resources.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_2_imported_resources.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_2_imported_resources.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +crate::generate!({ + inline: r#" + package example:imported-resources; + + world import-some-resources { + enum level { + debug, + info, + warn, + error, + } + resource logger { + constructor(max-level: level); + + get-max-level: func() -> level; + set-max-level: func(level: level); + + log: func(level: level, msg: string); + } + } + "#, +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_3_world_exports.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_3_world_exports.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_3_world_exports.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_3_world_exports.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +crate::generate!({ + inline: r#" + package example:world-exports; + + world with-exports { + import log: func(msg: string); + + export run: func(); + + /// An example of exporting an interface inline naming it directly. + export environment: interface { + get: func(var: string) -> string; + set: func(var: string, val: string); + } + + /// An example of exporting an interface defined in this file. + export units; + + /// An example of exporting an interface defined in a dependency. + export wasi:random/insecure@0.2.0; + } + + interface units { + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + + /// Renders the number of bytes as a human readable string. + bytes-to-string: func(bytes: u64) -> string; + + /// Renders the provided duration as a human readable string. + duration-to-string: func(dur: duration) -> string; + } + "#, + + // provided here to get the export macro rendered in documentation, not + // required for external use. + pub_export_macro: true, + + // provided to specify the path to `wasi:*` dependencies referenced above. + path: "wasi-cli@0.2.0.wasm", + + // specify that these interface dependencies should be generated as well. + with: { + "wasi:random/insecure@0.2.0": generate, + "wasi:clocks/monotonic-clock@0.2.0": generate, + "wasi:io/poll@0.2.0": generate + } +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_4_exported_resources.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_4_exported_resources.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples/_4_exported_resources.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples/_4_exported_resources.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +crate::generate!({ + inline: r#" + package example:exported-resources; + + world import-some-resources { + export logging; + } + + interface logging { + enum level { + debug, + info, + warn, + error, + } + resource logger { + constructor(max-level: level); + + get-max-level: func() -> level; + set-max-level: func(level: level); + + log: func(level: level, msg: string); + } + } + "#, +}); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/examples.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/examples.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +//! Examples of output of the [`generate!`] macro. +//! +//! This module is only included in docs.rs documentation and is not present in +//! the actual crate when compiling from crates.io. The purpose of this module +//! is to showcase what the output of the [`generate!`] macro looks like. +//! +//! [`generate!`]: crate::generate + +/// An example of generated bindings for top-level imported functions and +/// interfaces into a world. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_0_world_imports.rs")] +/// ``` +pub mod _0_world_imports; + +/// An example of importing interfaces into a world. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_1_interface_imports.rs")] +/// ``` +pub mod _1_interface_imports; + +/// An example of importing resources into a world. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_2_imported_resources.rs")] +/// ``` +pub mod _2_imported_resources; + +/// An example of exporting items from a world and the traits that they +/// generate. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_3_world_exports.rs")] +/// ``` +pub mod _3_world_exports; + +/// An example of exporting resources from a world and the traits that they +/// generate. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_4_exported_resources.rs")] +/// ``` +pub mod _4_exported_resources; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,881 @@ +//! Bindings generation support for Rust with the Component Model. +//! +//! This crate is a bindings generator for [WIT] and the [Component Model]. +//! Users are likely interested in the [`generate!`] macro which actually +//! generates bindings. Otherwise this crate provides any runtime support +//! necessary for the macro-generated code. +//! +//! [WIT]: https://component-model.bytecodealliance.org/design/wit.html +//! [Component Model]: https://component-model.bytecodealliance.org/ + +#![no_std] + +#[cfg(not(feature = "rustc-dep-of-std"))] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +/// Generate bindings for an input WIT document. +/// +/// This macro is the bread-and-butter of the `wit-bindgen` crate. The macro +/// here will parse [WIT] as input and generate Rust bindings to work with the +/// `world` that's specified in the [WIT]. For a primer on WIT see [this +/// documentation][WIT] and for a primer on worlds see [here][worlds]. +/// +/// [WIT]: https://component-model.bytecodealliance.org/design/wit.html +/// [worlds]: https://component-model.bytecodealliance.org/design/worlds.html +/// +/// This macro takes as input a [WIT package] as well as a [`world`][worlds] +/// within that package. It will then generate a Rust function for all `import`s +/// into the world. If there are any `export`s then a Rust `trait` will be +/// generated for you to implement. The macro additionally takes a number of +/// configuration parameters documented below as well. +/// +/// Basic invocation of the macro can look like: +/// +/// ``` +/// use wit_bindgen::generate; +/// # macro_rules! generate { ($($t:tt)*) => () } +/// +/// generate!(); +/// ``` +/// +/// This will parse a WIT package in the `wit` folder adjacent to your project's +/// `Cargo.toml` file. Within this WIT package there must be precisely one +/// `world` and that world will be the one that has bindings generated for it. +/// All other options remain at their default values (more on this below). +/// +/// If your WIT package has more than one `world`, or if you want to select a +/// world from the dependencies, you can specify a world explicitly: +/// +/// ``` +/// use wit_bindgen::generate; +/// # macro_rules! generate { ($($t:tt)*) => () } +/// +/// generate!("my-world"); +/// generate!("wasi:cli/imports"); +/// ``` +/// +/// This form of the macro takes a single string as an argument which is a +/// "world specifier" to select which world is being generated. As a single +/// string, such as `"my-world"`, this selects the world named `my-world` in the +/// package being parsed in the `wit` folder. The longer form specification +/// `"wasi:cli/imports"` indicates that the `wasi:cli` package, located in the +/// `wit/deps` folder, will have a world named `imports` and those bindings will +/// be generated. +/// +/// If your WIT package is located in a different directory than one called +/// `wit` then it can be specified with the `in` keyword: +/// +/// ``` +/// use wit_bindgen::generate; +/// # macro_rules! generate { ($($t:tt)*) => () } +/// +/// generate!(in "./my/other/path/to/wit"); +/// generate!("a-world" in "../path/to/wit"); +/// ``` +/// +/// The full-form of the macro, however, takes a braced structure which is a +/// "bag of options": +/// +/// ``` +/// use wit_bindgen::generate; +/// # macro_rules! generate { ($($t:tt)*) => () } +/// +/// generate!({ +/// world: "my-world", +/// path: "../path/to/wit", +/// // ... +/// }); +/// ``` +/// +/// For documentation on each option, see below. +/// +/// ## Exploring generated bindings +/// +/// Once bindings have been generated they can be explored via a number of means +/// to see what was generated: +/// +/// * Using `cargo doc` should render all of the generated bindings in addition +/// to the original comments in the WIT format itself. +/// * If your IDE supports `rust-analyzer` code completion should be available +/// to explore and see types. +/// * The `wit-bindgen` CLI tool, packaged as `wit-bindgen-cli` on crates.io, +/// can be executed the same as the `generate!` macro and the output can be +/// read. +/// * If you're seeing an error, `WIT_BINDGEN_DEBUG=1` can help debug what's +/// happening (more on this below) by emitting macro output to a file. +/// * This documentation can be consulted for various constructs as well. +/// +/// Currently browsing generated code may have road bumps on the way. If you run +/// into issues or have idea of how to improve the situation please [file an +/// issue]. +/// +/// [file an issue]: https://github.com/bytecodealliance/wit-bindgen/issues/new +/// +/// ## Namespacing +/// +/// In WIT, worlds can import and export `interface`s, functions, and types. Each +/// `interface` can either be "anonymous" and only named within the context of a +/// `world` or it can have a "package ID" associated with it. Names in Rust take +/// into account all the names associated with a WIT `interface`. For example +/// the package ID `foo:bar/baz` would create a `mod foo` which contains a `mod +/// bar` which contains a `mod baz`. +/// +/// WIT imports and exports are additionally separated into their own +/// namespaces. Imports are generated at the level of the `generate!` macro +/// where exports are generated under an `exports` namespace. +/// +/// ## Imports +/// +/// Imports into a `world` can be types, resources, functions, and interfaces. +/// Each of these is bound as a Rust type, function, or module. The intent is +/// that the WIT interfaces map to what is roughly idiomatic Rust for the given +/// interface. +/// +/// ### Imports: Top-level functions and types +/// +/// Imports at the top-level of a world are generated directly where the +/// `generate!` macro is invoked. +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r" +/// package a:b; +/// +/// world the-world { +/// record fahrenheit { +/// degrees: f32, +/// } +/// +/// import what-temperature-is-it: func() -> fahrenheit; +/// +/// record celsius { +/// degrees: f32, +/// } +/// +/// import convert-to-celsius: func(a: fahrenheit) -> celsius; +/// } +/// ", +/// }); +/// +/// fn test() { +/// let current_temp = what_temperature_is_it(); +/// println!("current temp in fahrenheit is {}", current_temp.degrees); +/// let in_celsius: Celsius = convert_to_celsius(current_temp); +/// println!("current temp in celsius is {}", in_celsius.degrees); +/// } +/// ``` +/// +/// ### Imports: Interfaces +/// +/// Interfaces are placed into submodules where the `generate!` macro is +/// invoked and are namespaced based on their identifiers. +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r" +/// package my:test; +/// +/// interface logging { +/// enum level { +/// debug, +/// info, +/// error, +/// } +/// log: func(level: level, msg: string); +/// } +/// +/// world the-world { +/// import logging; +/// import global-logger: interface { +/// use logging.{level}; +/// +/// set-current-level: func(level: level); +/// get-current-level: func() -> level; +/// } +/// } +/// ", +/// }); +/// +/// // `my` and `test` are from `package my:test;` and `logging` is for the +/// // interfac name. +/// use my::test::logging::Level; +/// +/// fn test() { +/// let current_level = global_logger::get_current_level(); +/// println!("current logging level is {current_level:?}"); +/// global_logger::set_current_level(Level::Error); +/// +/// my::test::logging::log(Level::Info, "Hello there!"); +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// ### Imports: Resources +/// +/// Imported resources generate a type named after the name of the resource. +/// This type is then used both for borrows as `&T` as well as via ownership as +/// `T`. Resource methods are bound as methods on the type `T`. +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// interface logger { +/// enum level { +/// debug, +/// info, +/// error, +/// } +/// +/// resource logger { +/// constructor(destination: string); +/// log: func(level: level, msg: string); +/// } +/// } +/// +/// // Note that while this world does not textually import the above +/// // `logger` interface it is a transitive dependency via the `use` +/// // statement so the "elaborated world" imports the logger. +/// world the-world { +/// use logger.{logger}; +/// +/// import get-global-logger: func() -> logger; +/// } +/// "#, +/// }); +/// +/// use my::test::logger::Level; +/// +/// fn test() { +/// let logger = get_global_logger(); +/// logger.log(Level::Debug, "This is a global message"); +/// +/// let logger2 = Logger::new("/tmp/other.log"); +/// logger2.log(Level::Info, "This is not a global message"); +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// Note in the above example the lack of import of `Logger`. The `use` +/// statement imported the `Logger` type, an alias of it, from the `logger` +/// interface into `the-world`. This generated a Rust `type` alias so `Logger` +/// was available at the top-level. +/// +/// ## Exports: Basic Usage +/// +/// A WIT world can not only `import` functionality but can additionally +/// `export` functionality as well. An `export` represents a contract that the +/// Rust program must implement to be able to work correctly. The `generate!` +/// macro's goal is to take care of all the low-level and ABI details for you, +/// so the end result is that `generate!`, for exports, will generate Rust +/// `trait`s that you must implement. +/// +/// A minimal example of this is: +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// world my-world { +/// export hello: func(); +/// } +/// "#, +/// }); +/// +/// struct MyComponent; +/// +/// impl Guest for MyComponent { +/// fn hello() {} +/// } +/// +/// export!(MyComponent); +/// # +/// # fn main() {} +/// ``` +/// +/// Here the `Guest` trait was generated by the `generate!` macro and represents +/// the functions at the top-level of `my-world`, in this case the function +/// `hello`. A custom type, here called `MyComponent`, is created and the trait +/// is implemented for that type. +/// +/// Additionally a macro is generated by `generate!` (macros generating macros) +/// called `export!`. The `export!` macro is given a component that implements +/// the export `trait`s and then it will itself generate all necessary +/// `#[unsafe(no_mangle)]` functions to implement the ABI required. +/// +/// ## Exports: Multiple Interfaces +/// +/// Each `interface` in WIT will generate a `trait` that must be implemented in +/// addition to the top-level `trait` for the world. All traits are named +/// `Guest` here and are namespaced appropriately in modules: +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// interface a { +/// func-in-a: func(); +/// second-func-in-a: func(); +/// } +/// +/// world my-world { +/// export a; +/// export b: interface { +/// func-in-b: func(); +/// } +/// export c: func(); +/// } +/// "#, +/// }); +/// +/// struct MyComponent; +/// +/// impl Guest for MyComponent { +/// fn c() {} +/// } +/// +/// impl exports::my::test::a::Guest for MyComponent { +/// fn func_in_a() {} +/// fn second_func_in_a() {} +/// } +/// +/// impl exports::b::Guest for MyComponent { +/// fn func_in_b() {} +/// } +/// +/// export!(MyComponent); +/// # +/// # fn main() {} +/// ``` +/// +/// Here note that there were three `Guest` traits generated for each of the +/// three groups: two interfaces and one `world`. Also note that traits (and +/// types) for exports are namespaced in an `exports` module. +/// +/// Note that when the top-level `world` does not have any exported functions, +/// or if an interface does not have any functions, then no `trait` is +/// generated: +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// interface a { +/// type my-type = u32; +/// } +/// +/// world my-world { +/// export b: interface { +/// use a.{my-type}; +/// +/// foo: func() -> my-type; +/// } +/// } +/// "#, +/// }); +/// +/// struct MyComponent; +/// +/// impl exports::b::Guest for MyComponent { +/// fn foo() -> u32 { +/// 42 +/// } +/// } +/// +/// export!(MyComponent); +/// # +/// # fn main() {} +/// ``` +/// +/// ## Exports: Resources +/// +/// Exporting a resource is significantly different than importing a resource. +/// A component defining a resource can create new resources of that type at any +/// time, for example. Additionally resources can be "dereferenced" into their +/// underlying values within the component. +/// +/// Owned resources have a custom type generated and borrowed resources are +/// generated with a type of the same name suffixed with `Borrow<'_>`, such as +/// `MyResource` and `MyResourceBorrow<'_>`. +/// +/// Like `interface`s the methods and functions used with a `resource` are +/// packaged up into a `trait`. +/// +/// Specifying a custom resource type is done with an associated type on the +/// corresponding trait for the resource's containing interface/world: +/// +/// ``` +/// use wit_bindgen::generate; +/// use std::cell::{RefCell, Cell}; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// interface logging { +/// enum level { +/// debug, +/// info, +/// error, +/// } +/// +/// resource logger { +/// constructor(level: level); +/// log: func(level: level, msg: string); +/// level: func() -> level; +/// set-level: func(level: level); +/// } +/// } +/// +/// world my-world { +/// export logging; +/// } +/// "#, +/// }); +/// +/// use exports::my::test::logging::{Guest, GuestLogger, Level}; +/// +/// struct MyComponent; +/// +/// // Note that the `logging` interface has no methods of its own but a trait +/// // is required to be implemented here to specify the type of `Logger`. +/// impl Guest for MyComponent { +/// type Logger = MyLogger; +/// } +/// +/// struct MyLogger { +/// level: Cell, +/// contents: RefCell, +/// } +/// +/// impl GuestLogger for MyLogger { +/// fn new(level: Level) -> MyLogger { +/// MyLogger { +/// level: Cell::new(level), +/// contents: RefCell::new(String::new()), +/// } +/// } +/// +/// fn log(&self, level: Level, msg: String) { +/// if level as u32 <= self.level.get() as u32 { +/// self.contents.borrow_mut().push_str(&msg); +/// self.contents.borrow_mut().push_str("\n"); +/// } +/// } +/// +/// fn level(&self) -> Level { +/// self.level.get() +/// } +/// +/// fn set_level(&self, level: Level) { +/// self.level.set(level); +/// } +/// } +/// +/// export!(MyComponent); +/// # +/// # fn main() {} +/// ``` +/// +/// It's important to note that resources in Rust do not get `&mut self` as +/// methods, but instead are required to be defined with `&self`. This requires +/// the use of interior mutability such as `Cell` and `RefCell` above from the +/// `std::cell` module. +/// +/// ## Exports: The `export!` macro +/// +/// Components are created by having exported WebAssembly functions with +/// specific names, and these functions are not created when `generate!` is +/// invoked. Instead these functions are created afterwards once you've defined +/// your own type an implemented the various `trait`s for it. The +/// `#[unsafe(no_mangle)]` functions that will become the component are created +/// with the generated `export!` macro. +/// +/// Each call to `generate!` will itself generate a macro called `export!`. +/// The macro's first argument is the name of a type that implements the traits +/// generated: +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// inline: r#" +/// package my:test; +/// +/// world my-world { +/// # export hello: func(); +/// // ... +/// } +/// "#, +/// }); +/// +/// struct MyComponent; +/// +/// impl Guest for MyComponent { +/// # fn hello() {} +/// // ... +/// } +/// +/// export!(MyComponent); +/// # +/// # fn main() {} +/// ``` +/// +/// This argument is a Rust type which implements the `Guest` traits generated +/// by `generate!`. Note that all `Guest` traits must be implemented for the +/// type provided or an error will be generated. +/// +/// This macro additionally accepts a second argument. The macro itself needs to +/// be able to find the module where the `generate!` macro itself was originally +/// invoked. Currently that can't be done automatically so a path to where +/// `generate!` was provided can also be passed to the macro. By default, the +/// argument is set to `self`: +/// +/// ``` +/// use wit_bindgen::generate; +/// +/// generate!({ +/// // ... +/// # inline: r#" +/// # package my:test; +/// # +/// # world my-world { +/// # export hello: func(); +/// # // ... +/// # } +/// # "#, +/// }); +/// # +/// # struct MyComponent; +/// # +/// # impl Guest for MyComponent { +/// # fn hello() {} +/// # // ... +/// # } +/// # +/// export!(MyComponent with_types_in self); +/// # +/// # fn main() {} +/// ``` +/// +/// This indicates that the current module, referred to with `self`, is the one +/// which had the `generate!` macro expanded. +/// +/// If, however, the `generate!` macro was run in a different module then that +/// must be configured: +/// +/// ``` +/// mod bindings { +/// wit_bindgen::generate!({ +/// // ... +/// # inline: r#" +/// # package my:test; +/// # +/// # world my-world { +/// # export hello: func(); +/// # // ... +/// # } +/// # "#, +/// }); +/// } +/// # +/// # struct MyComponent; +/// # +/// # impl bindings::Guest for MyComponent { +/// # fn hello() {} +/// # // ... +/// # } +/// # +/// bindings::export!(MyComponent with_types_in bindings); +/// # +/// # fn main() {} +/// ``` +/// +/// ## Debugging output to `generate!` +/// +/// While `wit-bindgen` is tested to the best of our ability there are +/// inevitably bugs and issues that arise. These can range from bad error +/// messages to misconfigured invocations to bugs in the macro itself. To assist +/// with debugging these situations the macro recognizes an environment +/// variable: +/// +/// ```shell +/// export WIT_BINDGEN_DEBUG=1 +/// ``` +/// +/// When set the macro will emit the result of expansion to a file and then +/// `include!` that file. Any error messages generated by `rustc` should then +/// point to the generated file and allow you to open it up, read it, and +/// inspect it. This can often provide better context to the error than rustc +/// provides by default with macros. +/// +/// It is not recommended to set this environment variable by default as it will +/// cause excessive rebuilds of Cargo projects. It's recommended to only use it +/// as necessary to debug issues. +/// +/// ## Options to `generate!` +/// +/// The full list of options that can be passed to the `generate!` macro are as +/// follows. Note that there are no required options, they all have default +/// values. +/// +/// +/// ``` +/// use wit_bindgen::generate; +/// # macro_rules! generate { ($($t:tt)*) => () } +/// +/// generate!({ +/// // The name of the world that bindings are being generated for. If this +/// // is not specified then it's required that the package selected +/// // below has a single `world` in it. +/// world: "my-world", +/// +/// // Path to parse WIT and its dependencies from. Defaults to the `wit` +/// // folder adjacent to your `Cargo.toml`. +/// // +/// // This parameter also supports the form of a list, such as: +/// // ["../path/to/wit1", "../path/to/wit2"] +/// // Usually used in testing, our test suite may want to generate code +/// // from wit files located in multiple paths within a single mod, and we +/// // don't want to copy these files again. Currently these locations must +/// // be ordered, as later paths can't contain dependencies on earlier +/// // paths. This restriction may be lifted in the future. +/// path: "../path/to/wit", +/// +/// // Enables passing "inline WIT". If specified this is the default +/// // package that a world is selected from. Any dependencies that this +/// // inline WIT refers to must be defined in the `path` option above. +/// // +/// // By default this is not specified. +/// inline: " +/// world my-world { +/// import wasi:cli/imports; +/// +/// export my-run: func() +/// } +/// ", +/// +/// // Additional traits to derive for all defined types. Note that not all +/// // types may be able to implement these traits, such as resources. +/// // +/// // By default this set is empty. +/// additional_derives: [PartialEq, Eq, Hash, Clone], +/// +/// // When generating bindings for interfaces that are not defined in the +/// // same package as `world`, this option can be used to either generate +/// // those bindings or point to already generated bindings. +/// // For example, if your world refers to WASI types then the `wasi` crate +/// // already has generated bindings for all WASI types and structures. In this +/// // situation the key `with` here can be used to use those types +/// // elsewhere rather than regenerating types. +/// // If for example your world refers to some type and you want to use +/// // your own custom implementation of that type then you can specify +/// // that here as well. There is a requirement on the remapped (custom) +/// // type to have the same internal structure and identical to what would +/// // wit-bindgen generate (including alignment, etc.), since +/// // lifting/lowering uses its fields directly. +/// // +/// // If, however, your world refers to interfaces for which you don't have +/// // already generated bindings then you can use the special `generate` value +/// // to have those bindings generated. +/// // +/// // The `with` key here works for interfaces and individual types. +/// // +/// // When an interface or type is specified here no bindings will be +/// // generated at all. It's assumed bindings are fully generated +/// // somewhere else. This is an indicator that any further references to types +/// // defined in these interfaces should use the upstream paths specified +/// // here instead. +/// // +/// // Any unused keys in this map are considered an error. +/// with: { +/// "wasi:io/poll": wasi::io::poll, +/// "some:package/my-interface": generate, +/// "some:package/my-interface/my-type": my_crate::types::MyType, +/// }, +/// +/// // Indicates that all interfaces not present in `with` should be assumed +/// // to be marked with `generate`. +/// generate_all, +/// +/// // An optional list of function names to skip generating bindings for. +/// // This is only applicable to imports and the name specified is the name +/// // of the function. +/// skip: ["foo", "bar", "baz"], +/// +/// // Configuration of how Rust types are generated. +/// // +/// // This option will change how WIT types are mapped to Rust types. There +/// // are a number of ways this can be done depending on the context. For +/// // example a Rust `&str` is suitable to pass to an imported function but +/// // an exported function receives a `String`. These both represent the +/// // WIT type `string`, however. +/// // +/// // Type generation becomes extra-significant when aggregates come into +/// // play (such as a WIT `record` or `variant`), especially when the +/// // aggregate is used both in an imported function and exported one. +/// // +/// // There are three modes of ownership, documented here, but only one +/// // can be specified. +/// // +/// // The default mode is "Owning" meaning that all Rust types will by +/// // default contain their owned containers. For example a `record` with +/// // a `string` will map to a Rust `struct` containing a `String`. This +/// // maximizes the chance that types can be shared between imports and +/// // exports but can come at a cost where calling an import may require +/// // more allocations than necessary. +/// ownership: Owning, +/// +/// // Specifies an alternative name for the `export!` macro generated for +/// // any exports this world has. +/// // +/// // Defaults to "export" +/// export_macro_name: "export", +/// +/// // Indicates whether the `export!` macro is `pub` or just `pub(crate)`. +/// // +/// // This defaults to `false`. +/// pub_export_macro: false, +/// +/// // The second mode of ownership is "Borrowing". This mode then +/// // additionally has a boolean flag indicating whether duplicate types +/// // should be generated if necessary. +/// // +/// // This mode will prefer using borrowed values in Rust to represent WIT +/// // values where possible. For example if the argument to an imported +/// // function is a record-with-a-string then in Rust that will generate a +/// // `struct` with a lifetime parameter storing `&'a str`. +/// // +/// // The `duplicate_if_necessary` flag will cause duplicate types to be +/// // generated when a WIT type is used both in an import and export. In +/// // this situation one will be called `FooParam` and one will be called +/// // `FooResult` (where `foo` is the WIT name). +/// // +/// // It's generally recommended to not turn this on unless performance +/// // requires it. Even if so, please feel free to open an issue on the +/// // `wit-bindgen` repository to help improve the default "Owning" use +/// // case above if possible. +/// ownership: Borrowing { duplicate_if_necessary: false }, +/// +/// // The generated `export!` macro, if any, will by default look for +/// // generated types adjacent to where the `export!` macro is invoked +/// // through the `self` module. This option can be used to change the +/// // defaults to look somewhere else instead. +/// default_bindings_module: "path::to::bindings", +/// +/// // This will suffix the custom section containing component type +/// // information with the specified string. This is not required by +/// // default but if the same world is generated in two different locations +/// // in the crate then one bindings generation location will need this +/// // suffix to avoid having the custom sections corrupt each other. +/// type_section_suffix: "suffix", +/// +/// // Configures the path to the `wit-bindgen` crate itself. By default +/// // this is `wit_bindgen` assuming that your crate depends on the +/// // `wit-bindgen` crate itself. +/// runtime_path: "path::to::wit_bindgen", +/// +/// // Configure where the `bitflags` crate is located. By default this +/// // is `wit_bindgen::bitflags` which already reexports `bitflags` for +/// // you. +/// bitflags_path: "path::to::bitflags", +/// +/// // Indicates that instead of `&str` and `String` the `&[u8]` and +/// // `Vec` types should be used. Only intended for cases where +/// // compiled size is of the utmost concern as this can avoid pulling in +/// // UTF-8 validation. +/// raw_strings, +/// +/// // Emits `#[cfg(feature = "std")]` around `impl Error for ... {}` blocks +/// // for generated types. This is a niche option that is only here to +/// // support the standard library itself depending on this crate one day. +/// std_feature, +/// +/// // Disable a workaround to force wasm constructors to be run only once +/// // when exported functions are called. +/// disable_run_ctors_once_workaround: false, +/// +/// // Whether to generate unused `record`, `enum`, `variant` types. +/// // By default, they will not be generated unless they are used as input +/// // or return value of a function. +/// generate_unused_types: false, +/// +/// // A list of "features" which correspond to WIT features to activate +/// // when parsing WIT files. This enables `@unstable` annotations showing +/// // up and having bindings generated for them. +/// // +/// // By default this is an empty list. +/// features: ["foo", "bar", "baz"], +/// +/// // Disables generation of a `#[used]` static to try harder to get the +/// // custom section describing WIT types linked into the binary when +/// // used in library-like situations. This is `false` by default with +/// // `#[used]` statics being emitted. +/// disable_custom_section_link_helpers: false, +/// +/// // Write generated code to a .rs file, which allows the compiler to +/// // emit more useful diagnostics for errors in the generated code. This +/// // is primarily useful for `wit-bindgen` developers. +/// // +/// // This does the same thing as setting `WIT_BINDGEN_DEBUG=1`, except +/// // that it can be used on a more fine-grained basis (i.e. it only affects +/// // the specific `generate!` call where it is used. +/// debug: true, +/// +/// // Generate async import and/or export bindings. +/// // +/// // The resulting bindings will use the component model +/// // [async ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md). +/// // +/// // If this option is not provided then the WIT's source annotation will +/// // be used instead. +/// async: true, // all bindings are async +/// async: false, // all bindings are sync +/// // With an array per-function configuration can be specified. A leading +/// // '-' will disable async for that particular function. +/// async: [ +/// "wasi:http/types@0.3.0-draft#[static]body.finish", +/// "import:wasi:http/handler@0.3.0-draft#handle", +/// "-export:wasi:http/handler@0.3.0-draft#handle", +/// "all", +/// ], +/// }); +/// ``` +/// +/// [WIT package]: https://component-model.bytecodealliance.org/design/packages.html +#[cfg(feature = "macros")] +pub use wit_bindgen_rust_macro::generate; + +#[cfg(docsrs)] +pub mod examples; + +#[doc(hidden)] +pub mod rt; + +#[cfg(feature = "async")] +pub use rt::async_support::{ + backpressure_dec, backpressure_inc, backpressure_set, block_on, spawn, yield_async, + yield_blocking, AbiBuffer, FutureRead, FutureReader, FutureWrite, FutureWriteCancel, + FutureWriteError, FutureWriter, StreamRead, StreamReader, StreamResult, StreamWrite, + StreamWriter, +}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/abi_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/abi_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/abi_buffer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/abi_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,417 @@ +use crate::rt::async_support::StreamVtable; +use crate::rt::Cleanup; +use std::alloc::Layout; +use std::mem::{self, MaybeUninit}; +use std::ptr; +use std::vec::Vec; + +/// A helper structure used with a stream to handle the canonical ABI +/// representation of lists and track partial writes. +/// +/// This structure is returned whenever a write to a stream completes. This +/// keeps track of the original buffer used to perform a write (`Vec`) and +/// additionally tracks any partial writes. Writes can then be resumed with +/// this buffer again or the partial write can be converted back to `Vec` to +/// get access to the remaining values. +/// +/// This value is created through the [`StreamWrite`](super::StreamWrite) +/// future's return value. +pub struct AbiBuffer { + rust_storage: Vec>, + vtable: &'static StreamVtable, + alloc: Option, + cursor: usize, +} + +impl AbiBuffer { + pub(crate) fn new(mut vec: Vec, vtable: &'static StreamVtable) -> AbiBuffer { + assert_eq!(vtable.lower.is_some(), vtable.lift.is_some()); + + // SAFETY: We're converting `Vec` to `Vec>`, which + // should be safe. + let rust_storage = unsafe { + let ptr = vec.as_mut_ptr(); + let len = vec.len(); + let cap = vec.capacity(); + mem::forget(vec); + Vec::>::from_raw_parts(ptr.cast(), len, cap) + }; + + // If `lower` is provided then the canonical ABI format is different + // from the native format, so all items are converted at this time. + // + // Note that this is probably pretty inefficient for "big" use cases + // but it's hoped that "big" use cases are using `u8` and therefore + // skip this entirely. + let alloc = vtable.lower.and_then(|lower| { + let layout = Layout::from_size_align( + vtable.layout.size() * rust_storage.len(), + vtable.layout.align(), + ) + .unwrap(); + let (mut ptr, cleanup) = Cleanup::new(layout); + let cleanup = cleanup?; + // SAFETY: All items in `rust_storage` are already initialized so + // it should be safe to read them and move ownership into the + // canonical ABI format. + unsafe { + for item in rust_storage.iter() { + let item = item.assume_init_read(); + lower(item, ptr); + ptr = ptr.add(vtable.layout.size()); + } + } + + Some(cleanup) + }); + AbiBuffer { + rust_storage, + alloc, + vtable, + cursor: 0, + } + } + + /// Returns the canonical ABI pointer/length to pass off to a write + /// operation. + pub(crate) fn abi_ptr_and_len(&self) -> (*const u8, usize) { + // If there's no `lower` operation then it means that `T`'s layout is + // the same in the canonical ABI so it can be used as-is. In this + // situation the list would have been un-tampered with above. + if self.vtable.lower.is_none() { + // SAFETY: this should be in-bounds, so it should be safe. + let ptr = unsafe { self.rust_storage.as_ptr().add(self.cursor).cast() }; + let len = self.rust_storage.len() - self.cursor; + return (ptr, len.try_into().unwrap()); + } + + // Othereise when `lower` is present that means that `self.alloc` has + // the ABI pointer we should pass along. + let ptr = self + .alloc + .as_ref() + .map(|c| c.ptr.as_ptr()) + .unwrap_or(ptr::null_mut()); + ( + // SAFETY: this should be in-bounds, so it should be safe. + unsafe { ptr.add(self.cursor * self.vtable.layout.size()) }, + self.rust_storage.len() - self.cursor, + ) + } + + /// Converts this `AbiBuffer` back into a `Vec` + /// + /// This commit consumes this buffer and yields back unwritten values as a + /// `Vec`. The remaining items in `Vec` have not yet been written and + /// all written items have been removed from the front of the list. + /// + /// Note that the backing storage of the returned `Vec` has not changed + /// from whe this buffer was created. + /// + /// Also note that this can be an expensive operation if a partial write + /// occurred as this will involve shifting items from the end of the vector + /// to the start of the vector. + pub fn into_vec(mut self) -> Vec { + self.take_vec() + } + + /// Returns the number of items remaining in this buffer. + pub fn remaining(&self) -> usize { + self.rust_storage.len() - self.cursor + } + + /// Advances this buffer by `amt` items. + /// + /// This signals that `amt` items are no longer going to be yielded from + /// `abi_ptr_and_len`. Additionally this will perform any deallocation + /// necessary for the starting `amt` items in this list. + pub(crate) fn advance(&mut self, amt: usize) { + assert!(amt + self.cursor <= self.rust_storage.len()); + let Some(dealloc_lists) = self.vtable.dealloc_lists else { + self.cursor += amt; + return; + }; + let (mut ptr, len) = self.abi_ptr_and_len(); + assert!(amt <= len); + for _ in 0..amt { + // SAFETY: we're managing the pointer passed to `dealloc_lists` and + // it was initialized with a `lower`, and then the pointer + // arithmetic should all be in-bounds. + unsafe { + dealloc_lists(ptr.cast_mut()); + ptr = ptr.add(self.vtable.layout.size()); + } + } + self.cursor += amt; + } + + fn take_vec(&mut self) -> Vec { + // First, if necessary, convert remaining values within `self.alloc` + // back into `self.rust_storage`. This is necessary when a lift + // operation is available meaning that the representation of `T` is + // different in the canonical ABI. + // + // Note that when `lift` is provided then when this original + // `AbiBuffer` was created it moved ownership of all values from the + // original vector into the `alloc` value. This is the reverse + // operation, moving all the values back into the vector. + if let Some(lift) = self.vtable.lift { + let (mut ptr, mut len) = self.abi_ptr_and_len(); + // SAFETY: this should be safe as `lift` is operating on values that + // were initialized with a previous `lower`, and the pointer + // arithmetic here should all be in-bounds. + unsafe { + for dst in self.rust_storage[self.cursor..].iter_mut() { + dst.write(lift(ptr.cast_mut())); + ptr = ptr.add(self.vtable.layout.size()); + len -= 1; + } + assert_eq!(len, 0); + } + } + + // Next extract the rust storage and zero out this struct's fields. + // This is also the location where a "shift" happens to remove items + // from the beginning of the returned vector as those have already been + // transferred somewhere else. + let mut storage = mem::take(&mut self.rust_storage); + storage.drain(..self.cursor); + self.cursor = 0; + self.alloc = None; + + // SAFETY: we're casting `Vec>` here to `Vec`. The + // elements were either always initialized (`lift` is `None`) or we just + // re-initialized them above from `self.alloc`. + unsafe { + let ptr = storage.as_mut_ptr(); + let len = storage.len(); + let cap = storage.capacity(); + mem::forget(storage); + Vec::::from_raw_parts(ptr.cast(), len, cap) + } + } +} + +impl Drop for AbiBuffer { + fn drop(&mut self) { + let _ = self.take_vec(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; + use std::vec; + + extern "C" fn cancel(_: u32) -> u32 { + todo!() + } + extern "C" fn drop(_: u32) { + todo!() + } + extern "C" fn new() -> u64 { + todo!() + } + extern "C" fn start_read(_: u32, _: *mut u8, _: usize) -> u32 { + todo!() + } + extern "C" fn start_write(_: u32, _: *const u8, _: usize) -> u32 { + todo!() + } + + static BLANK: StreamVtable = StreamVtable { + cancel_read: cancel, + cancel_write: cancel, + drop_readable: drop, + drop_writable: drop, + dealloc_lists: None, + lift: None, + lower: None, + layout: unsafe { Layout::from_size_align_unchecked(1, 1) }, + new, + start_read, + start_write, + }; + + #[test] + fn blank_advance_to_end() { + let mut buffer = AbiBuffer::new(vec![1, 2, 3, 4], &BLANK); + assert_eq!(buffer.remaining(), 4); + buffer.advance(1); + assert_eq!(buffer.remaining(), 3); + buffer.advance(2); + assert_eq!(buffer.remaining(), 1); + buffer.advance(1); + assert_eq!(buffer.remaining(), 0); + assert_eq!(buffer.into_vec(), []); + } + + #[test] + fn blank_advance_partial() { + let buffer = AbiBuffer::new(vec![1, 2, 3, 4], &BLANK); + assert_eq!(buffer.into_vec(), [1, 2, 3, 4]); + let mut buffer = AbiBuffer::new(vec![1, 2, 3, 4], &BLANK); + buffer.advance(1); + assert_eq!(buffer.into_vec(), [2, 3, 4]); + let mut buffer = AbiBuffer::new(vec![1, 2, 3, 4], &BLANK); + buffer.advance(1); + buffer.advance(2); + assert_eq!(buffer.into_vec(), [4]); + } + + #[test] + fn blank_ptr_eq() { + let mut buf = vec![1, 2, 3, 4]; + let ptr = buf.as_mut_ptr(); + let mut buffer = AbiBuffer::new(buf, &BLANK); + let (a, b) = buffer.abi_ptr_and_len(); + assert_eq!(a, ptr); + assert_eq!(b, 4); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [1, 2, 3, 4]); + } + + buffer.advance(1); + let (a, b) = buffer.abi_ptr_and_len(); + assert_eq!(a, ptr.wrapping_add(1)); + assert_eq!(b, 3); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [2, 3, 4]); + } + + buffer.advance(2); + let (a, b) = buffer.abi_ptr_and_len(); + assert_eq!(a, ptr.wrapping_add(3)); + assert_eq!(b, 1); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [4]); + } + + let ret = buffer.into_vec(); + assert_eq!(ret, [4]); + assert_eq!(ret.as_ptr(), ptr); + } + + #[derive(PartialEq, Eq, Debug)] + struct B(u8); + + static OP: StreamVtable = StreamVtable { + cancel_read: cancel, + cancel_write: cancel, + drop_readable: drop, + drop_writable: drop, + dealloc_lists: Some(|_ptr| {}), + lift: Some(|ptr| unsafe { B(*ptr - 1) }), + lower: Some(|b, ptr| unsafe { + *ptr = b.0 + 1; + }), + layout: unsafe { Layout::from_size_align_unchecked(1, 1) }, + new, + start_read, + start_write, + }; + + #[test] + fn op_advance_to_end() { + let mut buffer = AbiBuffer::new(vec![B(1), B(2), B(3), B(4)], &OP); + assert_eq!(buffer.remaining(), 4); + buffer.advance(1); + assert_eq!(buffer.remaining(), 3); + buffer.advance(2); + assert_eq!(buffer.remaining(), 1); + buffer.advance(1); + assert_eq!(buffer.remaining(), 0); + assert_eq!(buffer.into_vec(), []); + } + + #[test] + fn op_advance_partial() { + let buffer = AbiBuffer::new(vec![B(1), B(2), B(3), B(4)], &OP); + assert_eq!(buffer.into_vec(), [B(1), B(2), B(3), B(4)]); + let mut buffer = AbiBuffer::new(vec![B(1), B(2), B(3), B(4)], &OP); + buffer.advance(1); + assert_eq!(buffer.into_vec(), [B(2), B(3), B(4)]); + let mut buffer = AbiBuffer::new(vec![B(1), B(2), B(3), B(4)], &OP); + buffer.advance(1); + buffer.advance(2); + assert_eq!(buffer.into_vec(), [B(4)]); + } + + #[test] + fn op_ptrs() { + let mut buf = vec![B(1), B(2), B(3), B(4)]; + let ptr = buf.as_mut_ptr().cast::(); + let mut buffer = AbiBuffer::new(buf, &OP); + let (a, b) = buffer.abi_ptr_and_len(); + let base = a; + assert_ne!(a, ptr); + assert_eq!(b, 4); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [2, 3, 4, 5]); + } + + buffer.advance(1); + let (a, b) = buffer.abi_ptr_and_len(); + assert_ne!(a, ptr.wrapping_add(1)); + assert_eq!(a, base.wrapping_add(1)); + assert_eq!(b, 3); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [3, 4, 5]); + } + + buffer.advance(2); + let (a, b) = buffer.abi_ptr_and_len(); + assert_ne!(a, ptr.wrapping_add(3)); + assert_eq!(a, base.wrapping_add(3)); + assert_eq!(b, 1); + unsafe { + assert_eq!(std::slice::from_raw_parts(a, b), [5]); + } + + let ret = buffer.into_vec(); + assert_eq!(ret, [B(4)]); + assert_eq!(ret.as_ptr(), ptr.cast()); + } + + #[test] + fn dealloc_lists() { + static DEALLOCS: AtomicUsize = AtomicUsize::new(0); + static OP: StreamVtable = StreamVtable { + cancel_read: cancel, + cancel_write: cancel, + drop_readable: drop, + drop_writable: drop, + dealloc_lists: Some(|ptr| { + let prev = DEALLOCS.fetch_add(1, Relaxed); + assert_eq!(unsafe { usize::from(*ptr) }, prev + 1); + }), + lift: Some(|ptr| unsafe { B(*ptr) }), + lower: Some(|b, ptr| unsafe { + *ptr = b.0; + }), + layout: unsafe { Layout::from_size_align_unchecked(1, 1) }, + new, + start_read, + start_write, + }; + + assert_eq!(DEALLOCS.load(Relaxed), 0); + let buf = vec![B(1), B(2), B(3), B(4)]; + let mut buffer = AbiBuffer::new(buf, &OP); + assert_eq!(DEALLOCS.load(Relaxed), 0); + buffer.abi_ptr_and_len(); + assert_eq!(DEALLOCS.load(Relaxed), 0); + + buffer.advance(1); + assert_eq!(DEALLOCS.load(Relaxed), 1); + buffer.abi_ptr_and_len(); + assert_eq!(DEALLOCS.load(Relaxed), 1); + buffer.advance(2); + assert_eq!(DEALLOCS.load(Relaxed), 3); + buffer.abi_ptr_and_len(); + assert_eq!(DEALLOCS.load(Relaxed), 3); + buffer.into_vec(); + assert_eq!(DEALLOCS.load(Relaxed), 3); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/cabi.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/cabi.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/cabi.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/cabi.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,112 @@ +//! Definition of the "C ABI" of how imported functions interact with exported +//! tasks. +//! +//! Ok this crate is written in Rust, why in the world does this exist? This +//! comment is intended to explain this rationale but the tl;dr; is we want +//! this to work: +//! +//! * Within a single component ... +//! * One rust crate uses `wit-bindgen 0.A.0` to generate an exported function. +//! * One rust crate uses `wit-bindgen 0.B.0` to bind an imported function. +//! * The two crates are connected in the application with +//! `std::future::Future`. +//! +//! Without this module this situation won't work because 0.A.0 has no +//! knowledge of 0.B.0 meaning that 0.B.0 has no means of inserting a `waitable` +//! into the `waitable-set` managed by 0.A.0's export. +//! +//! To solve this problem the long-term intention is that something will live +//! in `wasi-libc` itself, but in the meantime it's living "somewhere" within +//! `wit-bindgen 0.*.0`. Specifically all `wit-bindgen` versions will +//! reference, via C linkage, a single function which is used to manipulate a +//! single pointer in linear memory. This pointer is a `wasip3_task` structure +//! which has all the various fields to use it. +//! +//! The `wasip3_task_set` symbol is itself defined in C inside of the +//! `src/wit_bindgen_cabi.c` file at this time, specifically because it's +//! annotated with `__weak__` meaning that any definition of it suffices. This +//! isn't possible to define in stable Rust (specifically `__weak__`). +//! +//! Once `wasip3_task_set` is defined everything then operates via indirection, +//! aka based off the returned pointer. The intention is that exported functions +//! will set this (it's sort of like an executor) and then imported functions +//! will all use this as the source of registering waitables. In the end that +//! means that it's possible to share types with `std::future::Future` that +//! are backed at the ABI level with this "channel". +//! +//! In the future it's hoped that this can move into `wasi-libc` itself, or if +//! `wasi-libc` provides something else that would be prioritized over this. +//! For now this is basically an affordance that we're going to be frequently +//! releaseing new major versions of `wit-bindgen` and we don't want to force +//! applications to all be using the exact same version of the bindings +//! generator and async bindings. +//! +//! Additionally for now this file is serving as documentation of this +//! interface. + +use core::ffi::c_void; + +#[cfg(target_family = "wasm")] +extern "C" { + /// Sets the global task pointer to `ptr` provided. Returns the previous + /// value. + /// + /// This function acts as a dual getter and a setter. To get the + /// current task pointer a dummy `ptr` can be provided (e.g. NULL) and then + /// it's passed back when you're done working with it. When setting the + /// current task pointer it's recommended to call this and then call it + /// again with the previous value when the tasks's work is done. + /// + /// For executors they need to ensure that the `ptr` passed in lives for + /// the entire lifetime of the component model task. + pub fn wasip3_task_set(ptr: *mut wasip3_task) -> *mut wasip3_task; +} + +#[cfg(not(target_family = "wasm"))] +pub unsafe extern "C" fn wasip3_task_set(ptr: *mut wasip3_task) -> *mut wasip3_task { + let _ = ptr; + unreachable!(); +} + +/// The first version of `wasip3_task` which implies the existence of the +/// fields `ptr`, `waitable_register`, and `waitable_unregister`. +pub const WASIP3_TASK_V1: u32 = 1; + +/// Indirect "vtable" used to connect imported functions and exported tasks. +/// Executors (e.g. exported functions) define and manage this while imports +/// use it. +#[repr(C)] +pub struct wasip3_task { + /// Currently `WASIP3_TASK_V1`. Indicates what fields are present next + /// depending on the version here. + pub version: u32, + + /// Private pointer owned by the `wasip3_task` itself, passed to callbacks + /// below as the first argument. + pub ptr: *mut c_void, + + /// Register a new `waitable` for this exported task. + /// + /// This exported task will add `waitable` to its `waitable-set`. When it + /// becomes ready then `callback` will be invoked with the ready code as + /// well as the `callback_ptr` provided. + /// + /// If `waitable` was previously registered with this task then the + /// previous `callback_ptr` is returned. Otherwise `NULL` is returned. + /// + /// It's the caller's responsibility to ensure that `callback_ptr` is valid + /// until `callback` is invoked, `waitable_unregister` is invoked, or + /// `waitable_register` is called again to overwrite the value. + pub waitable_register: unsafe extern "C" fn( + ptr: *mut c_void, + waitable: u32, + callback: unsafe extern "C" fn(callback_ptr: *mut c_void, code: u32), + callback_ptr: *mut c_void, + ) -> *mut c_void, + + /// Removes the `waitable` from this task's `waitable-set`. + /// + /// Returns the `callback_ptr` passed to `waitable_register` if present, or + /// `NULL` if it's not present. + pub waitable_unregister: unsafe extern "C" fn(ptr: *mut c_void, waitable: u32) -> *mut c_void, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/error_context.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/error_context.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/error_context.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/error_context.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,94 @@ +//! Raw bindings to `error-context` in the canonical ABI. + +use std::fmt::{self, Debug, Display}; +use std::ptr; +use std::string::String; + +/// Represents the Component Model `error-context` type. +#[derive(PartialEq, Eq)] +pub struct ErrorContext { + handle: u32, +} + +impl ErrorContext { + /// Call the `error-context.new` canonical built-in function. + pub fn new(debug_message: &str) -> ErrorContext { + unsafe { + let handle = new(debug_message.as_ptr(), debug_message.len()); + ErrorContext::from_handle(handle) + } + } + + #[doc(hidden)] + pub fn from_handle(handle: u32) -> Self { + Self { handle } + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + self.handle + } + + /// Extract the debug message from a given [`ErrorContext`] + pub fn debug_message(&self) -> String { + unsafe { + let mut ret = RetPtr { + ptr: ptr::null_mut(), + len: 0, + }; + debug_message(self.handle, &mut ret); + String::from_raw_parts(ret.ptr, ret.len, ret.len) + } + } +} + +impl Debug for ErrorContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ErrorContext") + .field("debug_message", &self.debug_message()) + .finish() + } +} + +impl Display for ErrorContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.debug_message(), f) + } +} + +impl std::error::Error for ErrorContext {} + +impl Drop for ErrorContext { + fn drop(&mut self) { + #[cfg(target_arch = "wasm32")] + unsafe { + drop(self.handle) + } + } +} + +#[repr(C)] +struct RetPtr { + ptr: *mut u8, + len: usize, +} + +#[cfg(not(target_arch = "wasm32"))] +unsafe fn new(_: *const u8, _: usize) -> u32 { + unreachable!() +} +#[cfg(not(target_arch = "wasm32"))] +fn debug_message(_: u32, _: &mut RetPtr) { + unreachable!() +} + +#[cfg(target_arch = "wasm32")] +#[link(wasm_import_module = "$root")] +extern "C" { + #[link_name = "[error-context-new-utf8]"] + fn new(_: *const u8, _: usize) -> u32; + #[link_name = "[error-context-drop]"] + fn drop(_: u32); + #[link_name = "[error-context-debug-message-utf8]"] + fn debug_message(_: u32, _: &mut RetPtr); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/future_support.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/future_support.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/future_support.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/future_support.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,734 @@ +//! Runtime support for `future` in the component model. +//! +//! There are a number of tricky concerns to all balance when implementing +//! bindings to `future`, specifically with how it interacts with Rust. This +//! will attempt to go over some of the high-level details of the implementation +//! here. +//! +//! ## Leak safety +//! +//! It's safe to leak any value at any time currently in Rust. In other words +//! Rust doesn't have linear types (yet). Typically this isn't really a problem +//! but the component model intrinsics we're working with here operate by being +//! given a pointer and then at some point in the future the pointer may be +//! read. This means that it's our responsibility to keep this pointer alive and +//! valid for the entire duration of an asynchronous operation. +//! +//! Chiefly this means that borrowed values are a no-no in this module. For +//! example if you were to send a `&[u8]` as an implementation of +//! `future>` that would not be sound. For example: +//! +//! * The future send operation is started, recording an address of `&[u8]`. +//! * The future is then leaked. +//! * According to rustc, later in code the original `&[u8]` is then no longer +//! borrowed. +//! * The original source of `&[u8]` could then be deallocated. +//! * Then the component model actually reads the pointer that it was given. +//! +//! This constraint effectively means that all types flowing in-and-out of +//! futures, streams, and async APIs are all "owned values", notably no +//! lifetimes. This requires, for example, that `future>` operates on +//! `Vec`. +//! +//! This is in stark contrast to bindings generated for `list` otherwise, +//! however, where for example a synchronous import with a `list` argument +//! would be bound with a `&[u8]` argument. Until Rust has some form of linear +//! types, however, it's not possible to loosen this restriction soundly because +//! it's generally not safe to leak an active I/O operation. This restriction is +//! similar to why it's so difficult to bind `io_uring` in safe Rust, which +//! operates similarly to the component model where pointers are submitted and +//! read in the future after the original call for submission returns. +//! +//! ## Lowering Owned Values +//! +//! According to the above everything with futures/streams operates on owned +//! values already, but this also affects precisely how lifting and lowering is +//! performed. In general any active asynchronous operation could be cancelled +//! at any time, meaning we have to deal with situations such as: +//! +//! * A `write` hasn't even started yet. +//! * A `write` was started and then cancelled. +//! * A `write` was started and then the other end dropped the channel. +//! * A `write` was started and then the other end received the value. +//! +//! In all of these situations regardless of the structure of `T` we can't leak +//! memory. The `future.write` intrinsic, however, takes no ownership of the +//! memory involved which means that we're still responsible for cleaning up +//! lists. It does take ownership, however, of `own` handles and other +//! resources. +//! +//! The way that this is solved for futures/streams is to lean further into +//! processing owned values. Namely lowering a `T` takes `T`-by-value, not `&T`. +//! This means that lowering operates similarly to return values of exported +//! functions, not parameters to imported functions. By lowering an owned value +//! of `T` this preserves a nice property where the lowered value has exclusive +//! ownership of all of its pointers/resources/etc. Lowering `&T` may require a +//! "cleanup list" for example which we avoid here entirely. +//! +//! This then makes the second and third cases above, getting a value back after +//! lowering, much easier. Namely re-acquisition of a value is simple `lift` +//! operation as if we received a value on the channel. +//! +//! ## Inefficiencies +//! +//! The above requirements generally mean that this is not a hyper-efficient +//! implementation. All writes and reads, for example, start out with allocation +//! memory on the heap to be owned by the asynchronous operation. Writing a +//! `list` to a future passes ownership of `Vec` but in theory doesn't +//! not actually require relinquishing ownership of the vector. Furthermore +//! there's no way to re-acquire a `T` after it has been sent, but all of `T` is +//! still valid except for `own` resources. +//! +//! That's all to say that this implementation can probably still be improved +//! upon, but doing so is thought to be pretty nontrivial at this time. It +//! should be noted though that there are other high-level inefficiencies with +//! WIT unrelated to this module. For example `list` is not always +//! represented the same in Rust as it is in the canonical ABI. That means that +//! sending `list` into a future might require copying the entire list and +//! changing its layout. Currently this is par-for-the-course with bindings. +//! +//! ## Linear (exactly once) Writes +//! +//! The component model requires that a writable end of a future must be written +//! to before closing, otherwise the drop operation traps. Ideally usage of +//! this API shouldn't result in traps so this is modeled in the Rust-level API +//! to prevent this trap from occurring. Rust does not support linear types +//! (types that must be used exactly once), instead it only has affine types +//! (types which must be used at most once), meaning that this requires some +//! runtime support. +//! +//! Specifically the `FutureWriter` structure stores two auxiliary Rust-specific +//! pieces of information: +//! +//! * A `should_write_default_value` boolean - if `true` on destruction then a +//! value has not yet been written and something must be written. +//! * A `default: fn() -> T` constructor to lazily create the default value to +//! be sent in this situation. +//! +//! This `default` field is provided by the user when the future is initially +//! created. Additionally during `Drop` a new Rust-level task will be spawned to +//! perform the write in the background. That'll keep the component-level task +//! alive until that write completes but otherwise shouldn't hinder anything +//! else. + +use { + crate::rt::async_support::waitable::{WaitableOp, WaitableOperation}, + crate::rt::async_support::ReturnCode, + crate::rt::Cleanup, + std::{ + alloc::Layout, + fmt, + future::{Future, IntoFuture}, + marker, + pin::Pin, + ptr, + sync::atomic::{AtomicU32, Ordering::Relaxed}, + task::{Context, Poll}, + }, +}; + +/// Function table used for [`FutureWriter`] and [`FutureReader`] +/// +/// Instances of this table are generated by `wit_bindgen::generate!`. This is +/// not a trait to enable different `FutureVtable<()>` instances to exist, for +/// example, through different calls to `wit_bindgen::generate!`. +/// +/// It's not intended that any user implements this vtable, instead it's +/// intended to only be auto-generated. +#[doc(hidden)] +pub struct FutureVtable { + /// The Canonical ABI layout of `T` in-memory. + pub layout: Layout, + + /// A callback to consume a value of `T` and lower it to the canonical ABI + /// pointed to by `dst`. + /// + /// The `dst` pointer should have `self.layout`. This is used to convert + /// in-memory representations in Rust to their canonical representations in + /// the component model. + pub lower: unsafe fn(value: T, dst: *mut u8), + + /// A callback to deallocate any lists within the canonical ABI value `dst` + /// provided. + /// + /// This is used when a value is successfully sent to another component. In + /// such a situation it may be possible that the canonical lowering of `T` + /// has lists that are still owned by this component and must be + /// deallocated. This is akin to a `post-return` callback for returns of + /// exported functions. + pub dealloc_lists: unsafe fn(dst: *mut u8), + + /// A callback to lift a value of `T` from the canonical ABI representation + /// provided. + pub lift: unsafe fn(dst: *mut u8) -> T, + + /// The raw `future.write` intrinsic. + pub start_write: unsafe extern "C" fn(future: u32, val: *const u8) -> u32, + /// The raw `future.read` intrinsic. + pub start_read: unsafe extern "C" fn(future: u32, val: *mut u8) -> u32, + /// The raw `future.cancel-write` intrinsic. + pub cancel_write: unsafe extern "C" fn(future: u32) -> u32, + /// The raw `future.cancel-read` intrinsic. + pub cancel_read: unsafe extern "C" fn(future: u32) -> u32, + /// The raw `future.drop-writable` intrinsic. + pub drop_writable: unsafe extern "C" fn(future: u32), + /// The raw `future.drop-readable` intrinsic. + pub drop_readable: unsafe extern "C" fn(future: u32), + /// The raw `future.new` intrinsic. + pub new: unsafe extern "C" fn() -> u64, +} + +/// Helper function to create a new read/write pair for a component model +/// future. +/// +/// # Unsafety +/// +/// This function is unsafe as it requires the functions within `vtable` to +/// correctly uphold the contracts of the component model. +pub unsafe fn future_new( + default: fn() -> T, + vtable: &'static FutureVtable, +) -> (FutureWriter, FutureReader) { + unsafe { + let handles = (vtable.new)(); + let reader = handles as u32; + let writer = (handles >> 32) as u32; + rtdebug!("future.new() = [{writer}, {reader}]"); + ( + FutureWriter::new(writer, default, vtable), + FutureReader::new(reader, vtable), + ) + } +} + +/// Represents the writable end of a Component Model `future`. +/// +/// A [`FutureWriter`] can be used to send a single value of `T` to the other +/// end of a `future`. In a sense this is similar to a oneshot channel in Rust. +pub struct FutureWriter { + handle: u32, + vtable: &'static FutureVtable, + + /// Whether or not a value should be written during `drop`. + /// + /// This is set to `false` when a value is successfully written or when a + /// value is written but the future is witnessed as being dropped. + /// + /// Note that this is set to `true` on construction to ensure that only + /// location which actually witness a completed write set it to `false`. + should_write_default_value: bool, + + /// Constructor for the default value to write during `drop`, should one + /// need to be written. + default: fn() -> T, +} + +impl FutureWriter { + /// Helper function to wrap a handle/vtable into a `FutureWriter`. + /// + /// # Unsafety + /// + /// This function is unsafe as it requires the functions within `vtable` to + /// correctly uphold the contracts of the component model. + #[doc(hidden)] + pub unsafe fn new(handle: u32, default: fn() -> T, vtable: &'static FutureVtable) -> Self { + Self { + handle, + default, + should_write_default_value: true, + vtable, + } + } + + /// Write the specified `value` to this `future`. + /// + /// This method is equivalent to an `async fn` which sends the `value` into + /// this future. The asynchronous operation acts as a rendezvous where the + /// operation does not complete until the other side has successfully + /// received the value. + /// + /// # Return Value + /// + /// The returned [`FutureWrite`] is a future that can be `.await`'d. The + /// return value of this future is: + /// + /// * `Ok(())` - the `value` was sent and received. The `self` value was + /// consumed along the way and will no longer be accessible. + /// * `Err(FutureWriteError { value })` - an attempt was made to send + /// `value` but the other half of this [`FutureWriter`] was dropped before + /// the value was received. This consumes `self` because the channel is + /// now dropped, but `value` is returned in case the caller wants to reuse + /// it. + /// + /// # Cancellation + /// + /// The returned future can be cancelled normally via `drop` which means + /// that the `value` provided here, along with this `FutureWriter` itself, + /// will be lost. There is also [`FutureWrite::cancel`] which can be used to + /// possibly re-acquire `value` and `self` if the operation was cancelled. + /// In such a situation the operation can be retried at a future date. + pub fn write(self, value: T) -> FutureWrite { + FutureWrite { + op: WaitableOperation::new((self, value)), + } + } +} + +impl fmt::Debug for FutureWriter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FutureWriter") + .field("handle", &self.handle) + .finish() + } +} + +impl Drop for FutureWriter { + fn drop(&mut self) { + // If a value has not yet been written into this writer than that must + // be done so now. Perform a "clone" of `self` by moving our data into a + // subtask, but ensure that `should_write_default_value` is set to + // `false` to avoid infinite loops by accident. Once the task is spawned + // we're done and the subtask's destructor of the closed-over + // `FutureWriter` will be responsible for performing the + // `drop-writable` call below. + // + // Note, though, that if `should_write_default_value` is `false` then a + // write has already happened and we can go ahead and just synchronously + // drop this writer as we would any other handle. + if self.should_write_default_value { + let clone = FutureWriter { + handle: self.handle, + default: self.default, + should_write_default_value: false, + vtable: self.vtable, + }; + crate::rt::async_support::spawn(async move { + let value = (clone.default)(); + let _ = clone.write(value).await; + }); + } else { + unsafe { + rtdebug!("future.drop-writable({})", self.handle); + (self.vtable.drop_writable)(self.handle); + } + } + } +} + +/// Represents a write operation which may be cancelled prior to completion. +/// +/// This is returned by [`FutureWriter::write`]. +pub struct FutureWrite { + op: WaitableOperation>, +} + +struct FutureWriteOp(marker::PhantomData); + +enum WriteComplete { + Written, + Dropped(T), + Cancelled(T), +} + +unsafe impl WaitableOp for FutureWriteOp +where + T: 'static, +{ + type Start = (FutureWriter, T); + type InProgress = (FutureWriter, Option); + type Result = (WriteComplete, FutureWriter); + type Cancel = FutureWriteCancel; + + fn start((writer, value): Self::Start) -> (u32, Self::InProgress) { + // TODO: it should be safe to store the lower-destination in + // `WaitableOperation` using `Pin` memory and such, but that would + // require some type-level trickery to get a correctly-sized value + // plumbed all the way to here. For now just dynamically allocate it and + // leave the optimization of leaving out this dynamic allocation to the + // future. + // + // In lieu of that a dedicated location on the heap is created for the + // lowering, and then `value`, as an owned value, is lowered into this + // pointer to initialize it. + let (ptr, cleanup) = Cleanup::new(writer.vtable.layout); + // SAFETY: `ptr` is allocated with `vtable.layout` and should be + // safe to use here. + let code = unsafe { + (writer.vtable.lower)(value, ptr); + (writer.vtable.start_write)(writer.handle, ptr) + }; + rtdebug!("future.write({}, {ptr:?}) = {code:#x}", writer.handle); + (code, (writer, cleanup)) + } + + fn start_cancelled((writer, value): Self::Start) -> Self::Cancel { + FutureWriteCancel::Cancelled(value, writer) + } + + fn in_progress_update( + (mut writer, cleanup): Self::InProgress, + code: u32, + ) -> Result { + let ptr = cleanup + .as_ref() + .map(|c| c.ptr.as_ptr()) + .unwrap_or(ptr::null_mut()); + match code { + super::BLOCKED => Err((writer, cleanup)), + + // The other end has dropped its end. + // + // The value was not received by the other end so `ptr` still has + // all of its resources intact. Use `lift` to construct a new + // instance of `T` which takes ownership of pointers and resources + // and such. The allocation of `ptr` is then cleaned up naturally + // when `cleanup` goes out of scope. + super::DROPPED | super::CANCELLED => { + // SAFETY: we're the ones managing `ptr` so we know it's safe to + // pass here. + let value = unsafe { (writer.vtable.lift)(ptr) }; + let status = if code == super::DROPPED { + // This writer has been witnessed to be dropped, meaning that + // `writer` is going to get destroyed soon as this return + // value propagates up the stack. There's no need to write + // the default value, so set this to `false`. + writer.should_write_default_value = false; + WriteComplete::Dropped(value) + } else { + WriteComplete::Cancelled(value) + }; + Ok((status, writer)) + } + + // This write has completed. + // + // Here we need to clean up our allocations. The `ptr` exclusively + // owns all of the value being sent and we notably need to cleanup + // the transitive list allocations present in this pointer. Use + // `dealloc_lists` for that (effectively a post-return lookalike). + // + // Afterwards the `cleanup` itself is naturally dropped and cleaned + // up. + super::COMPLETED => { + // A value was written, so no need to write the default value. + writer.should_write_default_value = false; + + // SAFETY: we're the ones managing `ptr` so we know it's safe to + // pass here. + unsafe { + (writer.vtable.dealloc_lists)(ptr); + } + Ok((WriteComplete::Written, writer)) + } + + other => unreachable!("unexpected code {other:?}"), + } + } + + fn in_progress_waitable((writer, _): &Self::InProgress) -> u32 { + writer.handle + } + + fn in_progress_cancel((writer, _): &Self::InProgress) -> u32 { + // SAFETY: we're managing `writer` and all the various operational bits, + // so this relies on `WaitableOperation` being safe. + let code = unsafe { (writer.vtable.cancel_write)(writer.handle) }; + rtdebug!("future.cancel-write({}) = {code:#x}", writer.handle); + code + } + + fn result_into_cancel((result, writer): Self::Result) -> Self::Cancel { + match result { + // The value was actually sent, meaning we can't yield back the + // future nor the value. + WriteComplete::Written => FutureWriteCancel::AlreadySent, + + // The value was not sent because the other end either hung up or we + // successfully cancelled. In both cases return back the value here + // with the writer. + WriteComplete::Dropped(val) => FutureWriteCancel::Dropped(val), + WriteComplete::Cancelled(val) => FutureWriteCancel::Cancelled(val, writer), + } + } +} + +impl Future for FutureWrite { + type Output = Result<(), FutureWriteError>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.pin_project() + .poll_complete(cx) + .map(|(result, _writer)| match result { + WriteComplete::Written => Ok(()), + WriteComplete::Dropped(value) | WriteComplete::Cancelled(value) => { + Err(FutureWriteError { value }) + } + }) + } +} + +impl FutureWrite { + fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation>> { + // SAFETY: we've chosen that when `Self` is pinned that it translates to + // always pinning the inner field, so that's codified here. + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) } + } + + /// Cancel this write if it hasn't already completed. + /// + /// This method can be used to cancel a write-in-progress and re-acquire + /// the writer and the value being sent. Note that the write operation may + /// succeed racily or the other end may also drop racily, and these + /// outcomes are reflected in the returned value here. + /// + /// # Panics + /// + /// Panics if the operation has already been completed via `Future::poll`, + /// or if this method is called twice. + pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel { + self.pin_project().cancel() + } +} + +/// Error type in the result of [`FutureWrite`], or the error type that is a result of +/// a failure to write a future. +pub struct FutureWriteError { + /// The value that could not be sent. + pub value: T, +} + +impl fmt::Debug for FutureWriteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FutureWriteError").finish_non_exhaustive() + } +} + +impl fmt::Display for FutureWriteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "read end dropped".fmt(f) + } +} + +impl std::error::Error for FutureWriteError {} + +/// Result of [`FutureWrite::cancel`]. +#[derive(Debug)] +pub enum FutureWriteCancel { + /// The cancel request raced with the receipt of the sent value, and the + /// value was actually sent. Neither the value nor the writer are made + /// available here as both are gone. + AlreadySent, + + /// The other end was dropped before cancellation happened. + /// + /// In this case the original value is returned back to the caller but the + /// writer itself is not longer accessible as it's no longer usable. + Dropped(T), + + /// The pending write was successfully cancelled and the value being written + /// is returned along with the writer to resume again in the future if + /// necessary. + Cancelled(T, FutureWriter), +} + +/// Represents the readable end of a Component Model `future`. +pub struct FutureReader { + handle: AtomicU32, + vtable: &'static FutureVtable, +} + +impl fmt::Debug for FutureReader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FutureReader") + .field("handle", &self.handle) + .finish() + } +} + +impl FutureReader { + #[doc(hidden)] + pub fn new(handle: u32, vtable: &'static FutureVtable) -> Self { + Self { + handle: AtomicU32::new(handle), + vtable, + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + let ret = self.opt_handle().unwrap(); + self.handle.store(u32::MAX, Relaxed); + ret + } + + fn handle(&self) -> u32 { + self.opt_handle().unwrap() + } + + fn opt_handle(&self) -> Option { + match self.handle.load(Relaxed) { + u32::MAX => None, + other => Some(other), + } + } +} + +impl IntoFuture for FutureReader { + type Output = T; + type IntoFuture = FutureRead; + + /// Convert this object into a `Future` which will resolve when a value is + /// written to the writable end of this `future`. + fn into_future(self) -> Self::IntoFuture { + FutureRead { + op: WaitableOperation::new(self), + } + } +} + +impl Drop for FutureReader { + fn drop(&mut self) { + let Some(handle) = self.opt_handle() else { + return; + }; + unsafe { + rtdebug!("future.drop-readable({handle})"); + (self.vtable.drop_readable)(handle); + } + } +} + +/// Represents a read operation which may be cancelled prior to completion. +/// +/// This represents a read operation on a [`FutureReader`] and is created via +/// `IntoFuture`. +pub struct FutureRead { + op: WaitableOperation>, +} + +struct FutureReadOp(marker::PhantomData); + +enum ReadComplete { + Value(T), + Cancelled, +} + +unsafe impl WaitableOp for FutureReadOp +where + T: 'static, +{ + type Start = FutureReader; + type InProgress = (FutureReader, Option); + type Result = (ReadComplete, FutureReader); + type Cancel = Result>; + + fn start(reader: Self::Start) -> (u32, Self::InProgress) { + let (ptr, cleanup) = Cleanup::new(reader.vtable.layout); + // SAFETY: `ptr` is allocated with `vtable.layout` and should be + // safe to use here. Its lifetime for the async operation is hinged on + // `WaitableOperation` being safe. + let code = unsafe { (reader.vtable.start_read)(reader.handle(), ptr) }; + rtdebug!("future.read({}, {ptr:?}) = {code:#x}", reader.handle()); + (code, (reader, cleanup)) + } + + fn start_cancelled(state: Self::Start) -> Self::Cancel { + Err(state) + } + + fn in_progress_update( + (reader, cleanup): Self::InProgress, + code: u32, + ) -> Result { + match ReturnCode::decode(code) { + ReturnCode::Blocked => Err((reader, cleanup)), + + // Let `cleanup` fall out of scope to clean up its allocation here, + // and otherwise tahe reader is plumbed through to possibly restart + // the read in the future. + ReturnCode::Cancelled(0) => Ok((ReadComplete::Cancelled, reader)), + + // The read has completed, so lift the value from the stored memory and + // `cleanup` naturally falls out of scope after transferring ownership of + // everything to the returned `value`. + ReturnCode::Completed(0) => { + let ptr = cleanup + .as_ref() + .map(|c| c.ptr.as_ptr()) + .unwrap_or(ptr::null_mut()); + + // SAFETY: we're the ones managing `ptr` so we know it's safe to + // pass here. + let value = unsafe { (reader.vtable.lift)(ptr) }; + Ok((ReadComplete::Value(value), reader)) + } + + other => panic!("unexpected code {other:?}"), + } + } + + fn in_progress_waitable((reader, _): &Self::InProgress) -> u32 { + reader.handle() + } + + fn in_progress_cancel((reader, _): &Self::InProgress) -> u32 { + // SAFETY: we're managing `reader` and all the various operational bits, + // so this relies on `WaitableOperation` being safe. + let code = unsafe { (reader.vtable.cancel_read)(reader.handle()) }; + rtdebug!("future.cancel-read({}) = {code:#x}", reader.handle()); + code + } + + fn result_into_cancel((value, reader): Self::Result) -> Self::Cancel { + match value { + // The value was actually read, so thread that through here. + ReadComplete::Value(value) => Ok(value), + + // The read was successfully cancelled, so thread through the + // `reader` to possibly restart later on. + ReadComplete::Cancelled => Err(reader), + } + } +} + +impl Future for FutureRead { + type Output = T; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.pin_project() + .poll_complete(cx) + .map(|(result, _reader)| match result { + ReadComplete::Value(val) => val, + // This is only possible if, after calling `FutureRead::cancel`, + // the future is polled again. The `cancel` method is documented + // as "don't do that" so this is left to panic. + ReadComplete::Cancelled => panic!("cannot poll after cancelling"), + }) + } +} + +impl FutureRead { + fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation>> { + // SAFETY: we've chosen that when `Self` is pinned that it translates to + // always pinning the inner field, so that's codified here. + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) } + } + + /// Cancel this read if it hasn't already completed. + /// + /// Return values include: + /// + /// * `Ok(value)` - future completed before this cancellation request + /// was received. + /// * `Err(reader)` - read operation was cancelled and it can be retried in + /// the future if desired. + /// + /// # Panics + /// + /// Panics if the operation has already been completed via `Future::poll`, + /// or if this method is called twice. Additionally if this method completes + /// then calling `poll` again on `self` will panic. + pub fn cancel(self: Pin<&mut Self>) -> Result> { + self.pin_project().cancel() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/stream_support.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/stream_support.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/stream_support.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/stream_support.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,604 @@ +//! For a high-level overview of how this module is implemented see the +//! module documentation in `future_support.rs`. + +use crate::rt::async_support::waitable::{WaitableOp, WaitableOperation}; +use crate::rt::async_support::{AbiBuffer, ReturnCode, DROPPED}; +use { + crate::rt::Cleanup, + std::{ + alloc::Layout, + fmt, + future::Future, + marker, + pin::Pin, + ptr, + sync::atomic::{AtomicU32, Ordering::Relaxed}, + task::{Context, Poll}, + vec::Vec, + }, +}; + +/// Operations that a stream requires throughout the implementation. +/// +/// This is generated by `wit_bindgen::generate!` primarily. +#[doc(hidden)] +pub struct StreamVtable { + /// The in-memory canonical ABI layout of a single value of `T`. + pub layout: Layout, + + /// An optional callback where if provided will lower an owned `T` value + /// into the `dst` pointer. + /// + /// If this is called the ownership of all of `T`'s lists and resources are + /// passed to `dst`, possibly by reallocating if `T`'s layout differs from + /// the canonical ABI layout. + /// + /// If this is `None` then it means that `T` has the same layout in-memory + /// in Rust as it does in the canonical ABI. In such a situation the + /// lower/lift operation can be dropped. + pub lower: Option, + + /// Callback used to deallocate any owned lists in `dst` after a value has + /// been successfully sent along a stream. + /// + /// `None` means that `T` has no lists internally. + pub dealloc_lists: Option, + + /// Dual of `lower`, and like `lower` if this is missing then it means that + /// `T` has the same in-memory representation in Rust and the canonical ABI. + pub lift: Option T>, + + /// The raw `stream.write` intrinsic. + pub start_write: unsafe extern "C" fn(stream: u32, val: *const u8, amt: usize) -> u32, + /// The raw `stream.read` intrinsic. + pub start_read: unsafe extern "C" fn(stream: u32, val: *mut u8, amt: usize) -> u32, + /// The raw `stream.cancel-write` intrinsic. + pub cancel_write: unsafe extern "C" fn(stream: u32) -> u32, + /// The raw `stream.cancel-read` intrinsic. + pub cancel_read: unsafe extern "C" fn(stream: u32) -> u32, + /// The raw `stream.drop-writable` intrinsic. + pub drop_writable: unsafe extern "C" fn(stream: u32), + /// The raw `stream.drop-readable` intrinsic. + pub drop_readable: unsafe extern "C" fn(stream: u32), + /// The raw `stream.new` intrinsic. + pub new: unsafe extern "C" fn() -> u64, +} + +/// Helper function to create a new read/write pair for a component model +/// stream. +pub unsafe fn stream_new( + vtable: &'static StreamVtable, +) -> (StreamWriter, StreamReader) { + unsafe { + let handles = (vtable.new)(); + let reader = handles as u32; + let writer = (handles >> 32) as u32; + rtdebug!("stream.new() = [{writer}, {reader}]"); + ( + StreamWriter::new(writer, vtable), + StreamReader::new(reader, vtable), + ) + } +} + +/// Represents the writable end of a Component Model `stream`. +pub struct StreamWriter { + handle: u32, + vtable: &'static StreamVtable, + done: bool, +} + +impl StreamWriter { + #[doc(hidden)] + pub unsafe fn new(handle: u32, vtable: &'static StreamVtable) -> Self { + Self { + handle, + vtable, + done: false, + } + } + + /// Initiate a write of the `values` provided into this stream. + /// + /// This method is akin to an `async fn` except that the returned + /// [`StreamWrite`] future can also be cancelled via [`StreamWrite::cancel`] + /// to re-acquire undelivered values. + /// + /// This method will perform at most a single write of the `values` + /// provided. The returned future will resolve once the write has completed. + /// + /// # Return Values + /// + /// The returned [`StreamWrite`] future returns a tuple of `(result, buf)`. + /// The `result` can be `StreamResult::Complete(n)` meaning that `n` values + /// were sent from `values` into this writer. A result of + /// `StreamResult::Dropped` means that no values were sent and the other side + /// has hung-up and sending values will no longer be possible. + /// + /// The `buf` returned is an [`AbiBuffer`] which retains ownership of the + /// original `values` provided here. That can be used to re-acquire `values` + /// through the [`AbiBuffer::into_vec`] method. The `buf` maintains an + /// internal cursor of how many values have been written and if the write + /// should be resumed to write the entire buffer then the + /// [`StreamWriter::write_buf`] method can be used to resume writing at the + /// next value in the buffer. + /// + /// # Cancellation + /// + /// The returned [`StreamWrite`] future can be cancelled like any other Rust + /// future via `drop`, but this means that `values` will be lost within the + /// future. The [`StreamWrite::cancel`] method can be used to re-acquire the + /// in-progress write that is being done with `values`. This is effectively + /// a way of forcing the future to immediately resolve. + /// + /// Note that if this future is cancelled via `drop` it does not mean that + /// no values were sent. It may be possible that values were still sent + /// despite being cancelled. Cancelling a write and determining what + /// happened must be done with [`StreamWrite::cancel`]. + pub fn write(&mut self, values: Vec) -> StreamWrite<'_, T> { + self.write_buf(AbiBuffer::new(values, self.vtable)) + } + + /// Same as [`StreamWriter::write`], except this takes [`AbiBuffer`] + /// instead of `Vec`. + pub fn write_buf(&mut self, values: AbiBuffer) -> StreamWrite<'_, T> { + StreamWrite { + op: WaitableOperation::new((self, values)), + } + } + + /// Writes all of the `values` provided into this stream. + /// + /// This is a higher-level method than [`StreamWriter::write`] and does not + /// expose cancellation for example. This will successively attempt to write + /// all of `values` provided into this stream. Upon completion the same + /// vector will be returned and any remaining elements in the vector were + /// not sent because the stream was dropped. + pub async fn write_all(&mut self, values: Vec) -> Vec { + // Perform an initial write which converts `values` into `AbiBuffer`. + let (mut status, mut buf) = self.write(values).await; + + // While the previous write completed and there's still remaining items + // in the buffer, perform another write. + while let StreamResult::Complete(_) = status { + if buf.remaining() == 0 { + break; + } + (status, buf) = self.write_buf(buf).await; + + // FIXME(WebAssembly/component-model#490) + if status == StreamResult::Cancelled { + status = StreamResult::Complete(0); + } + } + + // Return back any values that weren't written by shifting them to the + // front of the returned vector. + assert!(buf.remaining() == 0 || matches!(status, StreamResult::Dropped)); + buf.into_vec() + } + + /// Writes the singular `value` provided + /// + /// This is a higher-level method than [`StreamWriter::write`] and does not + /// expose cancellation for example. This will attempt to send `value` on + /// this stream. + /// + /// If the other end hangs up then the value is returned back as + /// `Some(value)`, otherwise `None` is returned indicating the value was + /// sent. + pub async fn write_one(&mut self, value: T) -> Option { + // TODO: can probably be a bit more efficient about this and avoid + // moving `value` onto the heap in some situations, but that's left as + // an optimization for later. + self.write_all(std::vec![value]).await.pop() + } +} + +impl fmt::Debug for StreamWriter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StreamWriter") + .field("handle", &self.handle) + .finish() + } +} + +impl Drop for StreamWriter { + fn drop(&mut self) { + rtdebug!("stream.drop-writable({})", self.handle); + unsafe { + (self.vtable.drop_writable)(self.handle); + } + } +} + +/// Represents a write operation which may be cancelled prior to completion. +pub struct StreamWrite<'a, T: 'static> { + op: WaitableOperation>, +} + +struct StreamWriteOp<'a, T: 'static>(marker::PhantomData<(&'a mut StreamWriter, T)>); + +/// Result of a [`StreamWriter::write`] or [`StreamReader::read`] operation, +/// yielded by the [`StreamWrite`] or [`StreamRead`] futures. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum StreamResult { + /// The provided number of values were successfully transferred. + /// + /// For writes this is how many items were written, and for reads this is + /// how many items were read. + Complete(usize), + /// No values were written, the other end has dropped its handle. + Dropped, + /// No values were written, the operation was cancelled. + Cancelled, +} + +unsafe impl<'a, T> WaitableOp for StreamWriteOp<'a, T> +where + T: 'static, +{ + type Start = (&'a mut StreamWriter, AbiBuffer); + type InProgress = (&'a mut StreamWriter, AbiBuffer); + type Result = (StreamResult, AbiBuffer); + type Cancel = (StreamResult, AbiBuffer); + + fn start((writer, buf): Self::Start) -> (u32, Self::InProgress) { + if writer.done { + return (DROPPED, (writer, buf)); + } + + let (ptr, len) = buf.abi_ptr_and_len(); + // SAFETY: sure hope this is safe, everything in this module and + // `AbiBuffer` is trying to make this safe. + let code = unsafe { (writer.vtable.start_write)(writer.handle, ptr, len) }; + rtdebug!( + "stream.write({}, {ptr:?}, {len}) = {code:#x}", + writer.handle + ); + (code, (writer, buf)) + } + + fn start_cancelled((_writer, buf): Self::Start) -> Self::Cancel { + (StreamResult::Cancelled, buf) + } + + fn in_progress_update( + (writer, mut buf): Self::InProgress, + code: u32, + ) -> Result { + match ReturnCode::decode(code) { + ReturnCode::Blocked => Err((writer, buf)), + ReturnCode::Dropped(0) => Ok((StreamResult::Dropped, buf)), + ReturnCode::Cancelled(0) => Ok((StreamResult::Cancelled, buf)), + code @ (ReturnCode::Completed(amt) + | ReturnCode::Dropped(amt) + | ReturnCode::Cancelled(amt)) => { + let amt = amt.try_into().unwrap(); + buf.advance(amt); + if let ReturnCode::Dropped(_) = code { + writer.done = true; + } + Ok((StreamResult::Complete(amt), buf)) + } + } + } + + fn in_progress_waitable((writer, _): &Self::InProgress) -> u32 { + writer.handle + } + + fn in_progress_cancel((writer, _): &Self::InProgress) -> u32 { + // SAFETY: we're managing `writer` and all the various operational bits, + // so this relies on `WaitableOperation` being safe. + let code = unsafe { (writer.vtable.cancel_write)(writer.handle) }; + rtdebug!("stream.cancel-write({}) = {code:#x}", writer.handle); + code + } + + fn result_into_cancel(result: Self::Result) -> Self::Cancel { + result + } +} + +impl Future for StreamWrite<'_, T> { + type Output = (StreamResult, AbiBuffer); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.pin_project().poll_complete(cx) + } +} + +impl<'a, T: 'static> StreamWrite<'a, T> { + fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation>> { + // SAFETY: we've chosen that when `Self` is pinned that it translates to + // always pinning the inner field, so that's codified here. + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) } + } + + /// Cancel this write if it hasn't already completed. + /// + /// This method can be used to cancel a write-in-progress and re-acquire + /// values being sent. Note that the result here may still indicate that + /// some values were written if the race to cancel the write was lost. + /// + /// # Panics + /// + /// Panics if the operation has already been completed via `Future::poll`, + /// or if this method is called twice. + pub fn cancel(self: Pin<&mut Self>) -> (StreamResult, AbiBuffer) { + self.pin_project().cancel() + } +} + +/// Represents the readable end of a Component Model `stream`. +pub struct StreamReader { + handle: AtomicU32, + vtable: &'static StreamVtable, + done: bool, +} + +impl fmt::Debug for StreamReader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StreamReader") + .field("handle", &self.handle) + .finish() + } +} + +impl StreamReader { + #[doc(hidden)] + pub fn new(handle: u32, vtable: &'static StreamVtable) -> Self { + Self { + handle: AtomicU32::new(handle), + vtable, + done: false, + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + let ret = self.opt_handle().unwrap(); + self.handle.store(u32::MAX, Relaxed); + ret + } + + fn handle(&self) -> u32 { + self.opt_handle().unwrap() + } + + fn opt_handle(&self) -> Option { + match self.handle.load(Relaxed) { + u32::MAX => None, + other => Some(other), + } + } + + /// Starts a new read operation on this stream into `buf`. + /// + /// This method will read values into the spare capacity of the `buf` + /// provided. If `buf` has no spare capacity then this will be equivalent + /// to a zero-length read. + /// + /// Upon completion the `buf` will be yielded back to the caller via the + /// completion of the [`StreamRead`] future. + /// + /// # Cancellation + /// + /// Cancelling the returned future can be done with `drop` like all Rust + /// futures, but it does not mean that no values were read. To accurately + /// determine if values were read the [`StreamRead::cancel`] method must be + /// used. + pub fn read(&mut self, buf: Vec) -> StreamRead<'_, T> { + StreamRead { + op: WaitableOperation::new((self, buf)), + } + } + + /// Reads a single item from this stream. + /// + /// This is a higher-level method than [`StreamReader::read`] in that it + /// reads only a single item and does not expose control over cancellation. + pub async fn next(&mut self) -> Option { + // TODO: should amortize this allocation and avoid doing it every time. + // Or somehow perhaps make this more optimal. + let (_result, mut buf) = self.read(Vec::with_capacity(1)).await; + buf.pop() + } + + /// Reads all items from this stream and returns the list. + /// + /// This method will read all remaining items from this stream into a list + /// and await the stream to be dropped. + pub async fn collect(mut self) -> Vec { + let mut ret = Vec::new(); + loop { + // If there's no more spare capacity then reserve room for one item + // which should trigger `Vec`'s built-in resizing logic, which will + // free up likely more capacity than just one slot. + if ret.len() == ret.capacity() { + ret.reserve(1); + } + let (status, buf) = self.read(ret).await; + ret = buf; + match status { + StreamResult::Complete(_) => {} + StreamResult::Dropped => break, + StreamResult::Cancelled => unreachable!(), + } + } + ret + } +} + +impl Drop for StreamReader { + fn drop(&mut self) { + let Some(handle) = self.opt_handle() else { + return; + }; + unsafe { + rtdebug!("stream.drop-readable({})", handle); + (self.vtable.drop_readable)(handle); + } + } +} + +/// Represents a read operation which may be cancelled prior to completion. +pub struct StreamRead<'a, T: 'static> { + op: WaitableOperation>, +} + +struct StreamReadOp<'a, T: 'static>(marker::PhantomData<(&'a mut StreamReader, T)>); + +unsafe impl<'a, T> WaitableOp for StreamReadOp<'a, T> +where + T: 'static, +{ + type Start = (&'a mut StreamReader, Vec); + type InProgress = (&'a mut StreamReader, Vec, Option); + type Result = (StreamResult, Vec); + type Cancel = (StreamResult, Vec); + + fn start((reader, mut buf): Self::Start) -> (u32, Self::InProgress) { + if reader.done { + return (DROPPED, (reader, buf, None)); + } + + let cap = buf.spare_capacity_mut(); + let ptr; + let cleanup; + // If `T` requires a lifting operation, then allocate a slab of memory + // which will store the canonical ABI read. Otherwise we can use the + // raw capacity in `buf` itself. + if reader.vtable.lift.is_some() { + let layout = Layout::from_size_align( + reader.vtable.layout.size() * cap.len(), + reader.vtable.layout.align(), + ) + .unwrap(); + (ptr, cleanup) = Cleanup::new(layout); + } else { + ptr = cap.as_mut_ptr().cast(); + cleanup = None; + } + // SAFETY: `ptr` is either in `buf` or in `cleanup`, both of which will + // persist with this async operation itself. + let code = unsafe { (reader.vtable.start_read)(reader.handle(), ptr, cap.len()) }; + rtdebug!( + "stream.read({}, {ptr:?}, {}) = {code:#x}", + reader.handle(), + cap.len() + ); + (code, (reader, buf, cleanup)) + } + + fn start_cancelled((_, buf): Self::Start) -> Self::Cancel { + (StreamResult::Cancelled, buf) + } + + fn in_progress_update( + (reader, mut buf, cleanup): Self::InProgress, + code: u32, + ) -> Result { + match ReturnCode::decode(code) { + ReturnCode::Blocked => Err((reader, buf, cleanup)), + + // Note that the `cleanup`, if any, is discarded here. + ReturnCode::Dropped(0) => Ok((StreamResult::Dropped, buf)), + + // When an in-progress read is successfully cancelled then the + // allocation that was being read into, if any, is just discarded. + // + // TODO: should maybe thread this around like `AbiBuffer` to cache + // the read allocation? + ReturnCode::Cancelled(0) => Ok((StreamResult::Cancelled, buf)), + + code @ (ReturnCode::Completed(amt) + | ReturnCode::Dropped(amt) + | ReturnCode::Cancelled(amt)) => { + let amt = usize::try_from(amt).unwrap(); + let cur_len = buf.len(); + assert!(amt <= buf.capacity() - cur_len); + + match reader.vtable.lift { + // With a `lift` operation this now requires reading `amt` items + // from `cleanup` and pushing them into `buf`. + Some(lift) => { + let mut ptr = cleanup + .as_ref() + .map(|c| c.ptr.as_ptr()) + .unwrap_or(ptr::null_mut()); + for _ in 0..amt { + unsafe { + buf.push(lift(ptr)); + ptr = ptr.add(reader.vtable.layout.size()); + } + } + } + + // If no `lift` was necessary, then the results of this operation + // were read directly into `buf`, so just update its length now that + // values have been initialized. + None => unsafe { buf.set_len(cur_len + amt) }, + } + + // Intentionally dispose of `cleanup` here as, if it was used, all + // allocations have been read from it and appended to `buf`. + drop(cleanup); + if let ReturnCode::Dropped(_) = code { + reader.done = true; + } + Ok((StreamResult::Complete(amt), buf)) + } + } + } + + fn in_progress_waitable((reader, ..): &Self::InProgress) -> u32 { + reader.handle() + } + + fn in_progress_cancel((reader, ..): &Self::InProgress) -> u32 { + // SAFETY: we're managing `reader` and all the various operational bits, + // so this relies on `WaitableOperation` being safe. + let code = unsafe { (reader.vtable.cancel_read)(reader.handle()) }; + rtdebug!("stream.cancel-read({}) = {code:#x}", reader.handle()); + code + } + + fn result_into_cancel(result: Self::Result) -> Self::Cancel { + result + } +} + +impl Future for StreamRead<'_, T> { + type Output = (StreamResult, Vec); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.pin_project().poll_complete(cx) + } +} + +impl<'a, T> StreamRead<'a, T> { + fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation>> { + // SAFETY: we've chosen that when `Self` is pinned that it translates to + // always pinning the inner field, so that's codified here. + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().op) } + } + + /// Cancel this read if it hasn't already completed. + /// + /// This method will initiate a cancellation operation for this active + /// read. This may race with the actual read itself and so this may actually + /// complete with some results. + /// + /// The final result of cancellation is returned, along with the original + /// buffer. + /// + /// # Panics + /// + /// Panics if the operation has already been completed via `Future::poll`, + /// or if this method is called twice. + pub fn cancel(self: Pin<&mut Self>) -> (StreamResult, Vec) { + self.pin_project().cancel() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/subtask.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/subtask.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/subtask.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/subtask.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,289 @@ +//! Bindings used to manage subtasks, or invocations of imported functions. +//! +//! See `future_support` for some more discussion but the basic idea is the same +//! where we require that everything is passed by ownership to primarily deal +//! with the possibility of leaking futures. By always requiring ownership we +//! can guarantee that even when a future is leaked all its parameters passed to +//! the canonical ABI are additionally leaked with it which should be memory +//! safe. + +use crate::rt::async_support::waitable::{WaitableOp, WaitableOperation}; +use crate::rt::async_support::{ + STATUS_RETURNED, STATUS_RETURNED_CANCELLED, STATUS_STARTED, STATUS_STARTED_CANCELLED, + STATUS_STARTING, +}; +use crate::rt::Cleanup; +use std::alloc::Layout; +use std::future::Future; +use std::marker; +use std::num::NonZeroU32; +use std::ptr; + +/// Raw operations used to invoke an imported asynchronous function. +/// +/// This trait is implemented by generated bindings and is used to implement +/// asynchronous imports. +/// +/// # Unsafety +/// +/// All operations/constants must be self-consistent for how this module expects +/// them all to be used. +pub unsafe trait Subtask { + /// The in-memory layout of both parameters and results allocated with + /// parameters coming first. + const ABI_LAYOUT: Layout; + + /// The offset, in bytes, from the start of `ABI_LAYOUT` to where the + /// results will be stored. + const RESULTS_OFFSET: usize; + + /// The parameters to this task. + type Params; + /// The representation of lowered parameters for this task. + /// + /// This is used to account for how lowered imports may have up to 4 flat + /// arguments or may also be indirect as well in memory. Either way this + /// represents the actual ABI values passed to the import. + type ParamsLower: Copy; + /// The results of this task. + type Results; + + /// The raw function import using `[async-lower]` and the canonical ABI. + unsafe fn call_import(params: Self::ParamsLower, results: *mut u8) -> u32; + + /// Bindings-generated version of lowering `params`. + /// + /// This may use the heap-allocated `dst`, which is an uninitialized + /// allocation of `Self::ABI_LAYOUT`. This returns any ABI parameters + /// necessary to actually invoke the imported function. + /// + /// Note that `ParamsLower` may return `dst` if there are more ABI + /// parameters than are allowed flat params (as specified by the canonical + /// ABI). + unsafe fn params_lower(params: Self::Params, dst: *mut u8) -> Self::ParamsLower; + + /// Bindings-generated version of deallocating any lists stored within + /// `lower`. + unsafe fn params_dealloc_lists(lower: Self::ParamsLower); + + /// Bindings-generated version of deallocating not only owned lists within + /// `lower` but also deallocating any owned resources. + unsafe fn params_dealloc_lists_and_own(lower: Self::ParamsLower); + + /// Bindings-generated version of lifting the results stored at `src`. + unsafe fn results_lift(src: *mut u8) -> Self::Results; + + /// Helper function to actually perform this asynchronous call with + /// `params`. + fn call(params: Self::Params) -> impl Future + where + Self: Sized, + { + async { + match WaitableOperation::>::new(Start { params }).await { + Ok(results) => results, + Err(_) => unreachable!( + "cancellation is not exposed API-wise, \ + should not be possible" + ), + } + } + } +} + +struct SubtaskOps(marker::PhantomData); + +struct Start { + params: T::Params, +} + +unsafe impl WaitableOp for SubtaskOps { + type Start = Start; + type InProgress = InProgress; + type Result = Result; + type Cancel = Result; + + fn start(state: Self::Start) -> (u32, Self::InProgress) { + unsafe { + let (ptr_params, cleanup) = Cleanup::new(T::ABI_LAYOUT); + let ptr_results = ptr_params.add(T::RESULTS_OFFSET); + let params_lower = T::params_lower(state.params, ptr_params); + let packed = T::call_import(params_lower, ptr_results); + let code = packed & 0xf; + let subtask = NonZeroU32::new(packed >> 4).map(|handle| SubtaskHandle { handle }); + rtdebug!("({ptr_params:?}, {ptr_results:?}) = ({code:#x}, {subtask:#x?})"); + + ( + code, + InProgress { + params_lower, + params_and_results: cleanup, + subtask, + started: false, + _marker: marker::PhantomData, + }, + ) + } + } + + fn start_cancelled(_state: Self::Start) -> Self::Cancel { + Err(()) + } + + fn in_progress_update( + mut state: Self::InProgress, + code: u32, + ) -> Result { + match code { + // Nothing new to do in this state, we're still waiting for the task + // to start. + STATUS_STARTING => { + assert!(!state.started); + Err(state) + } + + // Still not done yet, but we can record that this is started and + // otherwise deallocate lists in the parameters. + STATUS_STARTED => { + state.flag_started(); + Err(state) + } + + STATUS_RETURNED => { + // Conditionally flag as started if we haven't otherwise + // explicitly transitioned through `STATUS_STARTED`. + if !state.started { + state.flag_started(); + } + + // Now that our results have been written we can read them. + // + // Note that by dropping `state` here we'll both deallocate the + // params/results storage area as well as the subtask handle + // itself. + unsafe { Ok(Ok(T::results_lift(state.ptr_results()))) } + } + + // This subtask was dropped which forced cancellation. Said + // cancellation stopped the subtask before it reached the "started" + // state, meaning that we still own all of the parameters in their + // lowered form. + // + // In this situation we lift the parameters, even after we + // previously lowered them, back into `T::Params`. That notably + // re-acquires ownership and is suitable for disposing of all of + // the parameters via normal Rust-based destructors. + STATUS_STARTED_CANCELLED => { + assert!(!state.started); + unsafe { + T::params_dealloc_lists_and_own(state.params_lower); + } + Ok(Err(())) + } + + // This subtask was dropped which forced cancellation. Said + // cancellation stopped the subtask before it reached the "returned" + // state, meaning that it started, received the arguments, but then + // did not complete. + // + // In this situation we may have already received `STATUS_STARTED`, + // but we also might not have. This means we conditionally need + // to flag this task as started which will deallocate all lists + // owned by the parameters. + // + // After that though we do not have ownership of the parameters any + // more (e.g. own resources are all gone) so there's nothing to + // return. Here we yield a result and dispose of the in-progress + // state. + STATUS_RETURNED_CANCELLED => { + if !state.started { + state.flag_started(); + } + Ok(Err(())) + } + + other => panic!("unknown code {other:#x}"), + } + } + + fn in_progress_waitable(state: &Self::InProgress) -> u32 { + // This shouldn't get called in the one case this isn't present: when + // `STATUS_RETURNED` is returned and no waitable is created. That's the + // `unwrap()` condition here. + state.subtask.as_ref().unwrap().handle.get() + } + + fn in_progress_cancel(state: &Self::InProgress) -> u32 { + unsafe { cancel(Self::in_progress_waitable(state)) } + } + + fn result_into_cancel(result: Self::Result) -> Self::Cancel { + result + } +} + +#[derive(Debug)] +struct SubtaskHandle { + handle: NonZeroU32, +} + +impl Drop for SubtaskHandle { + fn drop(&mut self) { + unsafe { + drop(self.handle.get()); + } + } +} + +struct InProgress { + params_and_results: Option, + params_lower: T::ParamsLower, + started: bool, + subtask: Option, + _marker: marker::PhantomData, +} + +impl InProgress { + fn flag_started(&mut self) { + assert!(!self.started); + self.started = true; + + // SAFETY: the initial entrypoint of `call` requires that the vtable is + // setup correctly and we're obeying the invariants of the vtable, + // deallocating lists in an allocation that we exclusively own. + unsafe { + T::params_dealloc_lists(self.params_lower); + } + } + + fn ptr_results(&self) -> *mut u8 { + // SAFETY: the `T` trait has unsafely promised us that the offset is + // in-bounds of the allocation layout. + unsafe { + self.params_and_results + .as_ref() + .map(|c| c.ptr.as_ptr()) + .unwrap_or(ptr::null_mut()) + .add(T::RESULTS_OFFSET) + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +unsafe fn drop(_: u32) { + unreachable!() +} + +#[cfg(not(target_arch = "wasm32"))] +unsafe fn cancel(_: u32) -> u32 { + unreachable!() +} + +#[cfg(target_arch = "wasm32")] +#[link(wasm_import_module = "$root")] +extern "C" { + #[link_name = "[subtask-cancel]"] + fn cancel(handle: u32) -> u32; + #[link_name = "[subtask-drop]"] + fn drop(handle: u32); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,466 @@ +//! Generic support for "any waitable" and performing asynchronous operations on +//! that waitable. + +use super::cabi; +use std::ffi::c_void; +use std::future::Future; +use std::marker; +use std::mem; +use std::pin::Pin; +use std::ptr; +use std::task::{Context, Poll, Waker}; + +/// Generic future-based operation on any "waitable" in the component model. +/// +/// This is used right now to power futures and streams for both read/write +/// halves. This structure is driven by `S`, an implementation of +/// [`WaitableOp`], which codifies the various state transitions and what to do +/// on each state transition. +pub struct WaitableOperation { + state: WaitableOperationState, + /// Storage for the final result of this asynchronous operation, if it's + /// completed asynchronously. + completion_status: CompletionStatus, +} + +/// Structure used to store the `u32` return code from the canonical ABI about +/// an asynchronous operation. +/// +/// When an asynchronous operation is started and it does not immediately +/// complete then this structure is used to asynchronously fill in the return +/// code. A `Pin<&mut CompletionStatus>` is used to register a pointer with +/// `FutureState` to get filled in. +/// +/// Note that this means that this type is participating in unsafe lifetime +/// management and has properties it needs to uphold as a result. Specifically +/// the `PhantomPinned` field here means that `Pin` actually has meaning for +/// this structure, notably that once `Pin<&mut CompletionStatus>` is created +/// then it's guaranteed the destructor will be run before the backing memory +/// is deallocated. That's used in `WaitableOperation` above to share an +/// internal pointer of this data structure with `FuturesState` safely. The +/// destructor of `WaitableOperation` will deregister from `FutureState` meaning +/// that if `FuturesState` has a pointer here then it should be valid . +struct CompletionStatus { + /// Where the async operation's code is filled in, and `None` until that + /// happens. + code: Option, + + waker: Option, + + /// This is necessary to ensure that `Pin<&mut CompletionStatus>` carries + /// the "pin guarantee", basically to mean that it's not safe to construct + /// `Pin<&mut CompletionStatus>` and it must somehow require `unsafe` code. + _pinned: marker::PhantomPinned, +} + +/// Helper trait to be used with `WaitableOperation` to assist with machinery +/// necessary to track in-flight reads/writes on futures. +/// +/// # Unsafety +/// +/// This trait is `unsafe` as it has various guarantees that must be upheld by +/// implementors such as: +/// +/// * `S::in_progress_waitable` must always return the same value for the state +/// given. +pub unsafe trait WaitableOp { + /// Initial state of this operation, used to kick off the actual component + /// model operation and transition to `InProgress`. + type Start; + + /// Intermediate state of this operation when the component model is + /// involved but it hasn't resolved just yet. + type InProgress; + + /// Result type of this operation. + type Result; + + /// Result of when this operation is cancelled. + type Cancel; + + /// Starts the async operation. + /// + /// This method will actually call `{future,stream}.{read,write}` with + /// `state` provided. The return code of the intrinsic is returned here + /// along with the `InProgress` state. + fn start(state: Self::Start) -> (u32, Self::InProgress); + + /// Optionally complete the async operation. + /// + /// This method will transition from the `InProgress` state, with some + /// status code that was received, to either a completed result or a new + /// `InProgress` state. This is invoked when: + /// + /// * a new status code has been received by an async export's `callback` + /// * cancellation returned a code to be processed here + fn in_progress_update( + state: Self::InProgress, + code: u32, + ) -> Result; + + /// Conversion from the "start" state to the "cancel" result, needed when an + /// operation is cancelled before it's started. + fn start_cancelled(state: Self::Start) -> Self::Cancel; + + /// Acquires the component-model `waitable` index that the `InProgress` + /// state is waiting on. + fn in_progress_waitable(state: &Self::InProgress) -> u32; + + /// Initiates a request for cancellation of this operation. Returns the + /// status code returned by the `{future,stream}.cancel-{read,write}` + /// intrinsic. + /// + /// Note that this must synchronously complete the operation somehow. This + /// cannot return a status code indicating that an operation is pending, + /// instead the operation must be complete with the returned code. That may + /// mean that this intrinsic can block while figuring things out in the + /// component model ABI, for example. + fn in_progress_cancel(state: &Self::InProgress) -> u32; + + /// Converts a "completion result" into a "cancel result". This is necessary + /// when an in-progress operation is cancelled so the in-progress result is + /// first acquired and then transitioned to a cancel request. + fn result_into_cancel(result: Self::Result) -> Self::Cancel; +} + +enum WaitableOperationState { + Start(S::Start), + InProgress(S::InProgress), + Done, +} + +impl WaitableOperation +where + S: WaitableOp, +{ + /// Creates a new operation in the initial state. + pub fn new(state: S::Start) -> WaitableOperation { + WaitableOperation { + state: WaitableOperationState::Start(state), + completion_status: CompletionStatus { + code: None, + waker: None, + _pinned: marker::PhantomPinned, + }, + } + } + + fn pin_project( + self: Pin<&mut Self>, + ) -> (&mut WaitableOperationState, Pin<&mut CompletionStatus>) { + // SAFETY: this is the one method used to project from `Pin<&mut Self>` + // to the fields, and the contract we're deciding on is that + // `state` is never pinned but the `CompletionStatus` is. That's used + // to share a raw pointer with the completion callback with + // respect to `Option` internally. + unsafe { + let me = self.get_unchecked_mut(); + (&mut me.state, Pin::new_unchecked(&mut me.completion_status)) + } + } + + /// Registers a completion of `waitable` within the current task's future to: + /// + /// * Fill in `completion_status` with the result of a completion event. + /// * Call `cx.waker().wake()`. + pub fn register_waker(self: Pin<&mut Self>, waitable: u32, cx: &mut Context) { + let (_, mut completion_status) = self.pin_project(); + debug_assert!(completion_status.as_mut().code_mut().is_none()); + *completion_status.as_mut().waker_mut() = Some(cx.waker().clone()); + + // SAFETY: There's quite a lot going on here. First is the usage of + // `task` below, and for that see `unregister_waker` below for why this + // pattern should be safe. + // + // Otherwise we're handing off a pointer to `completion_status` to the + // `task` itself. That should be safe as we're guaranteed, via + // `Pin<&mut Self>`, that before `&mut Self` is deallocated the + // destructor will be run which will perform de-registration via + // cancellation. + unsafe { + let task = cabi::wasip3_task_set(ptr::null_mut()); + assert!(!task.is_null()); + assert!((*task).version >= cabi::WASIP3_TASK_V1); + let ptr: *mut CompletionStatus = completion_status.get_unchecked_mut(); + let prev = ((*task).waitable_register)((*task).ptr, waitable, cabi_wake, ptr.cast()); + // We might be inserting a waker for the first time or overwriting + // the previous waker. Only assert the expected value here if the + // previous value was non-null. + if !prev.is_null() { + assert_eq!(ptr, prev.cast()); + } + cabi::wasip3_task_set(task); + } + + unsafe extern "C" fn cabi_wake(ptr: *mut c_void, code: u32) { + let ptr: &mut CompletionStatus = &mut *ptr.cast::(); + ptr.code = Some(code); + ptr.waker.take().unwrap().wake() + } + } + + /// Deregisters the corresponding `register_waker` within the current task + /// for the `waitable` passed here. + /// + /// This relinquishes control of the original `completion_status` pointer + /// passed to `register_waker` after this call has completed. + pub fn unregister_waker(self: Pin<&mut Self>, waitable: u32) { + // SAFETY: the contract of `wasip3_task_set` is that the returned + // pointer is valid for the lifetime of our entire task, so it's valid + // for this stack frame. Additionally we assert it's non-null to + // double-check it's initialized and additionally check the version for + // the fields that we access. + // + // Otherwise the `waitable_unregister` callback should be safe because: + // + // * We're fulfilling the contract where the first argument must be + // `(*task).ptr` + // * We own the `waitable` that we're passing in, so we're fulfilling + // the contract that arbitrary waitables for other units of work + // aren't being manipulated. + unsafe { + let task = cabi::wasip3_task_set(ptr::null_mut()); + assert!(!task.is_null()); + assert!((*task).version >= cabi::WASIP3_TASK_V1); + let prev = ((*task).waitable_unregister)((*task).ptr, waitable); + + // Note that `_prev` here is not guaranteed to be either `NULL` or + // not. A racy completion notification may have come in and + // removed our waitable from the map even though we're in the + // `InProgress` state, meaning it may not be present. + // + // The main thing is that after this method is called the + // internal `completion_status` is guaranteed to no longer be in + // `task`. + // + // Note, though, that if present this must be our `CompletionStatus` + // pointer. + if !prev.is_null() { + let ptr: *mut CompletionStatus = self.pin_project().1.get_unchecked_mut(); + assert_eq!(ptr, prev.cast()); + } + + cabi::wasip3_task_set(task); + } + } + + /// Polls this operation to see if it has completed yet. + /// + /// This is intended to be used within `Future::poll`. + pub fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + use WaitableOperationState::*; + + let (state, completion_status) = self.as_mut().pin_project(); + + // First up, determine the completion status, if any, that's available. + let optional_code = match state { + // If this operation hasn't actually started yet then now's the + // time to start it. + Start(_) => { + let Start(s) = mem::replace(state, Done) else { + unreachable!() + }; + let (code, s) = S::start(s); + *state = InProgress(s); + Some(code) + } + + // This operation was previously queued so we're just waiting on + // the completion to come in. Read the completion status and + // interpret it down below. + // + // Note that it's the responsibility of the completion callback at + // the ABI level that we install to fill in this pointer, e.g. it's + // part of the `register_waker` contract. + InProgress(_) => completion_status.code_mut().take(), + + // This write has already completed, it's a Rust-level API violation + // to call this function again. + Done => panic!("cannot re-poll after operation completes"), + }; + + self.poll_complete_with_code(Some(cx), optional_code) + } + + /// After acquiring the current return of this operation in `optional_code`, + /// figures out what to do with it. + /// + /// The `cx` argument is optional to do nothing in the case that + /// `optional_code` is not present. + fn poll_complete_with_code( + mut self: Pin<&mut Self>, + cx: Option<&mut Context>, + optional_code: Option, + ) -> Poll { + use WaitableOperationState::*; + + let (state, _completion_status) = self.as_mut().pin_project(); + + // If a status code is provided, then extract the in-progress state and + // see what it thinks about this code. If we're done, yay! If not then + // record the new in-progress state and fall through to registering a + // waker. + // + // If no status code is available then that means we were polled before + // the status came back, so just re-register the waker. + if let Some(code) = optional_code { + let InProgress(in_progress) = mem::replace(state, Done) else { + unreachable!() + }; + match S::in_progress_update(in_progress, code) { + Ok(result) => return Poll::Ready(result), + Err(in_progress) => *state = InProgress(in_progress), + } + } + + let in_progress = match state { + InProgress(s) => s, + _ => unreachable!(), + }; + + // The operation is still in progress. + // + // Register the `cx.waker()` to get notified when `writer.handle` + // receives its completion. + if let Some(cx) = cx { + let handle = S::in_progress_waitable(in_progress); + self.register_waker(handle, cx); + } + Poll::Pending + } + + /// Cancels the in-flight operation, if it's still in-flight, and sees what + /// happened. + /// + /// Defers to `S` how to communicate the current status through the + /// cancellation type. + /// + /// # Panics + /// + /// Panics if the operation has already been completed via `poll_complete` + /// above. + /// Panics if this method is called twice. + pub fn cancel(mut self: Pin<&mut Self>) -> S::Cancel { + use WaitableOperationState::*; + + let (state, mut completion_status) = self.as_mut().pin_project(); + let in_progress = match state { + // This operation was never actually started, so there's no need to + // cancel anything, just pull out the value and return it. + Start(_) => { + let Start(s) = mem::replace(state, Done) else { + unreachable!() + }; + return S::start_cancelled(s); + } + + // This operation is actively in progress, fall through to below. + InProgress(s) => s, + + // This operation was already completed after a `poll_complete` + // above advanced to the `Done` state, or this was cancelled twice. + // In such situations this is a programmer error to call this + // method, so panic. + Done => panic!("cannot cancel operation after completing it"), + }; + + // Our operation is in-progress, let's take a look at the pending + // completion code, if any. + match completion_status.as_mut().code_mut().take() { + // A completion code, or status update, is available. This can + // happen for example if an export received a status update for + // this operation but then during the subsequent poll we decided + // that the future should be dropped instead, aka a race between + // two events. In this situation though to fully process the + // cancellation we need to see what's up, so check to see if the + // operation is done with this code. + // + // Note that in this branch it's known that this operation's waker + // is not registered with the exported task because the exported + // task already delivered us the completion code, which + // automatically deregisters it at this time. + Some(code) => { + match self.as_mut().poll_complete_with_code(None, Some(code)) { + // The operation completed without us needing to cancel it, + // so just convert that to the `Cancel` type. In this + // situation no cancellation is necessary, the async + // operation is now inert, and we can immediately return. + Poll::Ready(result) => return S::result_into_cancel(result), + + // The operation, despite receiving an update via a code, + // has not yet completed. In this case we do indeed need to + // perform cancellation, so fall through to below. + Poll::Pending => {} + } + } + + // A completion code is not yet available. In this situation we + // deregister our waker from the exported task's waitable set and + // callback handling since we'll be no longer waiting for events. + // Cancellation below happens synchronously. + // + // After we've unregistered fall through to below. + None => { + let waitable = S::in_progress_waitable(in_progress); + self.as_mut().unregister_waker(waitable); + } + } + + // This operation is guaranteed actively in progress at this point. + // That means we really do in fact need to cancel it. Here the + // appropriate cancellation intrinsic for the component model is + // invoked which returns the final completion status for this + // operation. + // + // The completion code is forwarded to `poll_complete_with_code` which + // determines what happened as a result. Note that at this time + // cancellation is required to be a synchronous operation in Rust, even + // if it's async in the component model, since that's the only way for + // this to be sound. Rust doesn't currently have linear types or async + // destructors for example to ensure otherwise that if this were to + // proceed asynchronously that we could rely on it being invoked. + let (InProgress(in_progress), _) = self.as_mut().pin_project() else { + unreachable!() + }; + let code = S::in_progress_cancel(in_progress); + match self.poll_complete_with_code(None, Some(code)) { + Poll::Ready(result) => S::result_into_cancel(result), + Poll::Pending => unreachable!(), + } + } +} + +impl Future for WaitableOperation { + type Output = S::Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.poll_complete(cx) + } +} + +impl Drop for WaitableOperation { + fn drop(&mut self) { + // SAFETY: we're in the destructor here so the value `self` is about + // to go away and we can guarantee we're not moving out of it. + let mut pin = unsafe { Pin::new_unchecked(self) }; + + let (state, _) = pin.as_mut().pin_project(); + + // If this operation has already completed then skip cancellation, + // otherwise it's our job to cancel anything in-flight. + if let WaitableOperationState::Done = state { + return; + } + pin.cancel(); + } +} + +impl CompletionStatus { + fn code_mut(self: Pin<&mut Self>) -> &mut Option { + unsafe { &mut self.get_unchecked_mut().code } + } + + fn waker_mut(self: Pin<&mut Self>) -> &mut Option { + unsafe { &mut self.get_unchecked_mut().waker } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable_set.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable_set.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable_set.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support/waitable_set.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +//! Low-level FFI-like bindings around `waitable-set` in the canonical ABI. + +use std::num::NonZeroU32; + +pub struct WaitableSet(NonZeroU32); + +impl WaitableSet { + pub fn new() -> WaitableSet { + let ret = WaitableSet(NonZeroU32::new(unsafe { new() }).unwrap()); + rtdebug!("waitable-set.new() = {}", ret.0.get()); + ret + } + + pub fn join(&self, waitable: u32) { + rtdebug!("waitable-set.join({waitable}, {})", self.0.get()); + unsafe { join(waitable, self.0.get()) } + } + + pub fn remove_waitable_from_all_sets(waitable: u32) { + rtdebug!("waitable-set.join({waitable}, 0)"); + unsafe { join(waitable, 0) } + } + + pub fn wait(&self) -> (u32, u32, u32) { + unsafe { + let mut payload = [0; 2]; + let event0 = wait(self.0.get(), &mut payload); + rtdebug!( + "waitable-set.wait({}) = ({event0}, {:#x}, {:#x})", + self.0.get(), + payload[0], + payload[1], + ); + (event0, payload[0], payload[1]) + } + } + + pub fn poll(&self) -> (u32, u32, u32) { + unsafe { + let mut payload = [0; 2]; + let event0 = poll(self.0.get(), &mut payload); + rtdebug!( + "waitable-set.poll({}) = ({event0}, {:#x}, {:#x})", + self.0.get(), + payload[0], + payload[1], + ); + (event0, payload[0], payload[1]) + } + } + + pub fn as_raw(&self) -> u32 { + self.0.get() + } +} + +impl Drop for WaitableSet { + fn drop(&mut self) { + unsafe { + rtdebug!("waitable-set.drop({})", self.0.get()); + drop(self.0.get()); + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +unsafe fn new() -> u32 { + unreachable!() +} +#[cfg(not(target_arch = "wasm32"))] +unsafe fn drop(_: u32) { + unreachable!() +} +#[cfg(not(target_arch = "wasm32"))] +unsafe fn join(_: u32, _: u32) { + unreachable!() +} +#[cfg(not(target_arch = "wasm32"))] +unsafe fn wait(_: u32, _: *mut [u32; 2]) -> u32 { + unreachable!(); +} +#[cfg(not(target_arch = "wasm32"))] +unsafe fn poll(_: u32, _: *mut [u32; 2]) -> u32 { + unreachable!(); +} + +#[cfg(target_arch = "wasm32")] +#[link(wasm_import_module = "$root")] +extern "C" { + #[link_name = "[waitable-set-new]"] + fn new() -> u32; + #[link_name = "[waitable-set-drop]"] + fn drop(set: u32); + #[link_name = "[waitable-join]"] + fn join(waitable: u32, set: u32); + #[link_name = "[waitable-set-wait]"] + fn wait(_: u32, _: *mut [u32; 2]) -> u32; + #[link_name = "[waitable-set-poll]"] + fn poll(_: u32, _: *mut [u32; 2]) -> u32; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/async_support.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,634 @@ +#![deny(missing_docs)] +// TODO: Switch to interior mutability (e.g. use Mutexes or thread-local +// RefCells) and remove this, since even in single-threaded mode `static mut` +// references can be a hazard due to recursive access. +#![allow(static_mut_refs)] + +extern crate std; +use core::sync::atomic::{AtomicBool, Ordering}; +use std::boxed::Box; +use std::collections::BTreeMap; +use std::ffi::c_void; +use std::future::Future; +use std::mem; +use std::pin::Pin; +use std::ptr; +use std::sync::Arc; +use std::task::{Context, Poll, Wake, Waker}; +use std::vec::Vec; + +use futures::channel::oneshot; +use futures::future::FutureExt; +use futures::stream::{FuturesUnordered, StreamExt}; + +macro_rules! rtdebug { + ($($f:tt)*) => { + // Change this flag to enable debugging, right now we're not using a + // crate like `log` or such to reduce runtime deps. Intended to be used + // during development for now. + if false { + std::eprintln!($($f)*); + } + } + +} + +mod abi_buffer; +mod cabi; +mod error_context; +mod future_support; +mod stream_support; +mod subtask; +mod waitable; +mod waitable_set; + +use self::waitable_set::WaitableSet; +pub use abi_buffer::*; +pub use error_context::*; +pub use future_support::*; +pub use stream_support::*; +#[doc(hidden)] +pub use subtask::Subtask; + +pub use futures; + +type BoxFuture = Pin + 'static>>; + +/// Represents a task created by either a call to an async-lifted export or a +/// future run using `block_on` or `start_task`. +struct FutureState { + /// Remaining work to do (if any) before this task can be considered "done". + /// + /// Note that we won't tell the host the task is done until this is drained + /// and `waitables` is empty. + tasks: FuturesUnordered, + + /// The waitable set containing waitables created by this task, if any. + waitable_set: Option, + + /// State of all waitables in `waitable_set`, and the ptr/callback they're + /// associated with. + // + // Note that this is a `BTreeMap` rather than a `HashMap` only because, as + // of this writing, initializing the default hasher for `HashMap` requires + // calling `wasi_snapshot_preview1:random_get`, which requires initializing + // the `wasi_snapshot_preview1` adapter when targeting `wasm32-wasip2` and + // later, and that's expensive enough that we'd prefer to avoid it for apps + // which otherwise make no use of the adapter. + waitables: BTreeMap, + + /// Raw structure used to pass to `cabi::wasip3_task_set` + wasip3_task: cabi::wasip3_task, + + /// Rust-level state for the waker, notably a bool as to whether this has + /// been woken. + waker: Arc, + + /// Clone of `waker` field, but represented as `std::task::Waker`. + waker_clone: Waker, +} + +impl FutureState { + fn new(future: BoxFuture) -> FutureState { + let waker = Arc::new(FutureWaker::default()); + FutureState { + waker_clone: waker.clone().into(), + waker, + tasks: [future].into_iter().collect(), + waitable_set: None, + waitables: BTreeMap::new(), + wasip3_task: cabi::wasip3_task { + // This pointer is filled in before calling `wasip3_task_set`. + ptr: ptr::null_mut(), + version: cabi::WASIP3_TASK_V1, + waitable_register, + waitable_unregister, + }, + } + } + + fn get_or_create_waitable_set(&mut self) -> &WaitableSet { + self.waitable_set.get_or_insert_with(WaitableSet::new) + } + + fn add_waitable(&mut self, waitable: u32) { + self.get_or_create_waitable_set().join(waitable) + } + + fn remove_waitable(&mut self, waitable: u32) { + WaitableSet::remove_waitable_from_all_sets(waitable) + } + + fn remaining_work(&self) -> bool { + !self.waitables.is_empty() + } + + /// Handles the `event{0,1,2}` event codes and returns a corresponding + /// return code along with a flag whether this future is "done" or not. + fn callback(&mut self, event0: u32, event1: u32, event2: u32) -> (u32, bool) { + match event0 { + EVENT_NONE => rtdebug!("EVENT_NONE"), + EVENT_SUBTASK => rtdebug!("EVENT_SUBTASK({event1:#x}, {event2:#x})"), + EVENT_STREAM_READ => rtdebug!("EVENT_STREAM_READ({event1:#x}, {event2:#x})"), + EVENT_STREAM_WRITE => rtdebug!("EVENT_STREAM_WRITE({event1:#x}, {event2:#x})"), + EVENT_FUTURE_READ => rtdebug!("EVENT_FUTURE_READ({event1:#x}, {event2:#x})"), + EVENT_FUTURE_WRITE => rtdebug!("EVENT_FUTURE_WRITE({event1:#x}, {event2:#x})"), + EVENT_CANCEL => { + rtdebug!("EVENT_CANCEL"); + + // Cancellation is mapped to destruction in Rust, so return a + // code/bool indicating we're done. The caller will then + // appropriately deallocate this `FutureState` which will + // transitively run all destructors. + return (CALLBACK_CODE_EXIT, true); + } + _ => unreachable!(), + } + if event0 != EVENT_NONE { + self.deliver_waitable_event(event1, event2) + } + + self.poll() + } + + /// Deliver the `code` event to the `waitable` store within our map. This + /// waitable should be present because it's part of the waitable set which + /// is kept in-sync with our map. + fn deliver_waitable_event(&mut self, waitable: u32, code: u32) { + self.remove_waitable(waitable); + let (ptr, callback) = self.waitables.remove(&waitable).unwrap(); + unsafe { + callback(ptr, code); + } + } + + /// Poll this task until it either completes or can't make immediate + /// progress. + /// + /// Returns the code representing what happened along with a boolean as to + /// whether this execution is done. + fn poll(&mut self) -> (u32, bool) { + self.with_p3_task_set(|me| { + let mut context = Context::from_waker(&me.waker_clone); + + loop { + // Reset the waker before polling to clear out any pending + // notification, if any. + me.waker.0.store(false, Ordering::Relaxed); + + // Poll our future, handling `SPAWNED` around this. + let poll; + unsafe { + poll = me.tasks.poll_next_unpin(&mut context); + if !SPAWNED.is_empty() { + me.tasks.extend(SPAWNED.drain(..)); + } + } + + match poll { + // A future completed, yay! Keep going to see if more have + // completed. + Poll::Ready(Some(())) => (), + + // The `FuturesUnordered` list is empty meaning that there's no + // more work left to do, so we're done. + Poll::Ready(None) => { + assert!(!me.remaining_work()); + assert!(me.tasks.is_empty()); + break (CALLBACK_CODE_EXIT, true); + } + + // Some future within `FuturesUnordered` is not ready yet. If + // our `waker` was signaled then that means this is a yield + // operation, otherwise it means we're blocking on something. + Poll::Pending => { + assert!(!me.tasks.is_empty()); + if me.waker.0.load(Ordering::Relaxed) { + break (CALLBACK_CODE_YIELD, false); + } + + assert!(me.remaining_work()); + let waitable = me.waitable_set.as_ref().unwrap().as_raw(); + break (CALLBACK_CODE_WAIT | (waitable << 4), false); + } + } + } + }) + } + + fn with_p3_task_set(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + // Finish our `wasip3_task` by initializing its self-referential pointer, + // and then register it for the duration of this function with + // `wasip3_task_set`. The previous value of `wasip3_task_set` will get + // restored when this function returns. + struct ResetTask(*mut cabi::wasip3_task); + impl Drop for ResetTask { + fn drop(&mut self) { + unsafe { + cabi::wasip3_task_set(self.0); + } + } + } + let self_raw = self as *mut FutureState; + self.wasip3_task.ptr = self_raw.cast(); + let prev = unsafe { cabi::wasip3_task_set(&mut self.wasip3_task) }; + let _reset = ResetTask(prev); + + f(self) + } +} + +impl Drop for FutureState { + fn drop(&mut self) { + // If this state has active tasks then they need to be dropped which may + // execute arbitrary code. This arbitrary code might require the p3 APIs + // for managing waitables, notably around removing them. In this + // situation we ensure that the p3 task is set while futures are being + // destroyed. + if !self.tasks.is_empty() { + self.with_p3_task_set(|me| { + me.tasks = Default::default(); + }) + } + } +} + +unsafe extern "C" fn waitable_register( + ptr: *mut c_void, + waitable: u32, + callback: unsafe extern "C" fn(*mut c_void, u32), + callback_ptr: *mut c_void, +) -> *mut c_void { + let ptr = ptr.cast::(); + assert!(!ptr.is_null()); + (*ptr).add_waitable(waitable); + match (*ptr).waitables.insert(waitable, (callback_ptr, callback)) { + Some((prev, _)) => prev, + None => ptr::null_mut(), + } +} + +unsafe extern "C" fn waitable_unregister(ptr: *mut c_void, waitable: u32) -> *mut c_void { + let ptr = ptr.cast::(); + assert!(!ptr.is_null()); + (*ptr).remove_waitable(waitable); + match (*ptr).waitables.remove(&waitable) { + Some((prev, _)) => prev, + None => ptr::null_mut(), + } +} + +#[derive(Default)] +struct FutureWaker(AtomicBool); + +impl Wake for FutureWaker { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + + fn wake_by_ref(self: &Arc) { + self.0.store(true, Ordering::Relaxed) + } +} + +/// Any newly-deferred work queued by calls to the `spawn` function while +/// polling the current task. +static mut SPAWNED: Vec = Vec::new(); + +const EVENT_NONE: u32 = 0; +const EVENT_SUBTASK: u32 = 1; +const EVENT_STREAM_READ: u32 = 2; +const EVENT_STREAM_WRITE: u32 = 3; +const EVENT_FUTURE_READ: u32 = 4; +const EVENT_FUTURE_WRITE: u32 = 5; +const EVENT_CANCEL: u32 = 6; + +const CALLBACK_CODE_EXIT: u32 = 0; +const CALLBACK_CODE_YIELD: u32 = 1; +const CALLBACK_CODE_WAIT: u32 = 2; +const _CALLBACK_CODE_POLL: u32 = 3; + +const STATUS_STARTING: u32 = 0; +const STATUS_STARTED: u32 = 1; +const STATUS_RETURNED: u32 = 2; +const STATUS_STARTED_CANCELLED: u32 = 3; +const STATUS_RETURNED_CANCELLED: u32 = 4; + +const BLOCKED: u32 = 0xffff_ffff; +const COMPLETED: u32 = 0x0; +const DROPPED: u32 = 0x1; +const CANCELLED: u32 = 0x2; + +/// Return code of stream/future operations. +#[derive(PartialEq, Debug, Copy, Clone)] +enum ReturnCode { + /// The operation is blocked and has not completed. + Blocked, + /// The operation completed with the specified number of items. + Completed(u32), + /// The other end is dropped, but before that the specified number of items + /// were transferred. + Dropped(u32), + /// The operation was cancelled, but before that the specified number of + /// items were transferred. + Cancelled(u32), +} + +impl ReturnCode { + fn decode(val: u32) -> ReturnCode { + if val == BLOCKED { + return ReturnCode::Blocked; + } + let amt = val >> 4; + match val & 0xf { + COMPLETED => ReturnCode::Completed(amt), + DROPPED => ReturnCode::Dropped(amt), + CANCELLED => ReturnCode::Cancelled(amt), + _ => panic!("unknown return code {val:#x}"), + } + } +} + +/// Starts execution of the `task` provided, an asynchronous computation. +/// +/// This is used for async-lifted exports at their definition site. The +/// representation of the export is `task` and this function is called from the +/// entrypoint. The code returned here is the same as the callback associated +/// with this export, and the callback will be used if this task doesn't exit +/// immediately with its result. +#[doc(hidden)] +pub fn start_task(task: impl Future + 'static) -> i32 { + // Allocate a new `FutureState` which will track all state necessary for + // our exported task. + let state = Box::into_raw(Box::new(FutureState::new(Box::pin(task)))); + + // Store our `FutureState` into our context-local-storage slot and then + // pretend we got EVENT_NONE to kick off everything. + // + // SAFETY: we should own `context.set` as we're the root level exported + // task, and then `callback` is only invoked when context-local storage is + // valid. + unsafe { + assert!(context_get().is_null()); + context_set(state.cast()); + callback(EVENT_NONE, 0, 0) as i32 + } +} + +/// Handle a progress notification from the host regarding either a call to an +/// async-lowered import or a stream/future read/write operation. +/// +/// # Unsafety +/// +/// This function assumes that `context_get()` returns a `FutureState`. +#[doc(hidden)] +pub unsafe fn callback(event0: u32, event1: u32, event2: u32) -> u32 { + // Acquire our context-local state, assert it's not-null, and then reset + // the state to null while we're running to help prevent any unintended + // usage. + let state = context_get().cast::(); + assert!(!state.is_null()); + unsafe { + context_set(ptr::null_mut()); + } + + // Use `state` to run the `callback` function in the context of our event + // codes we received. If the callback decides to exit then we're done with + // our future so deallocate it. Otherwise put our future back in + // context-local storage and forward the code. + unsafe { + let (rc, done) = (*state).callback(event0, event1, event2); + if done { + drop(Box::from_raw(state)); + } else { + context_set(state.cast()); + } + rtdebug!(" => (cb) {rc:#x}"); + rc + } +} + +/// Defer the specified future to be run after the current async-lifted export +/// task has returned a value. +/// +/// The task will remain in a running state until all spawned futures have +/// completed. +pub fn spawn(future: impl Future + 'static) { + unsafe { SPAWNED.push(Box::pin(future)) } +} + +/// Run the specified future to completion, returning the result. +/// +/// This uses `waitable-set.wait` to poll for progress on any in-progress calls +/// to async-lowered imports as necessary. +// TODO: refactor so `'static` bounds aren't necessary +pub fn block_on(future: impl Future + 'static) -> T { + let (tx, mut rx) = oneshot::channel(); + let state = &mut FutureState::new(Box::pin(future.map(move |v| drop(tx.send(v)))) as BoxFuture); + let mut event = (EVENT_NONE, 0, 0); + loop { + match state.callback(event.0, event.1, event.2) { + (_, true) => break rx.try_recv().unwrap().unwrap(), + (CALLBACK_CODE_YIELD, false) => event = state.waitable_set.as_ref().unwrap().poll(), + _ => event = state.waitable_set.as_ref().unwrap().wait(), + } + } +} + +/// Call the `yield` canonical built-in function. +/// +/// This yields control to the host temporarily, allowing other tasks to make +/// progress. It's a good idea to call this inside a busy loop which does not +/// otherwise ever yield control the host. +/// +/// Note that this function is a blocking function, not an `async` function. +/// That means that this is not an async yield which allows other tasks in this +/// component to progress, but instead this will block the current function +/// until the host gets back around to returning from this yield. Asynchronous +/// functions should probably use [`yield_async`] instead. +/// +/// # Return Value +/// +/// This function returns a `bool` which indicates whether execution should +/// continue after this yield point. A return value of `true` means that the +/// task was not cancelled and execution should continue. A return value of +/// `false`, however, means that the task was cancelled while it was suspended +/// at this yield point. The caller should return back and exit from the task +/// ASAP in this situation. +pub fn yield_blocking() -> bool { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn yield_() -> bool { + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[thread-yield]"] + fn yield_() -> bool; + } + // Note that the return value from the raw intrinsic is inverted, the + // canonical ABI returns "did this task get cancelled" while this function + // works as "should work continue going". + unsafe { !yield_() } +} + +/// The asynchronous counterpart to [`yield_blocking`]. +/// +/// This function does not block the current task but instead gives the +/// Rust-level executor a chance to yield control back to the host temporarily. +/// This means that other Rust-level tasks may also be able to progress during +/// this yield operation. +/// +/// # Return Value +/// +/// Unlike [`yield_blocking`] this function does not return anything. If this +/// component task is cancelled while paused at this yield point then the future +/// will be dropped and a Rust-level destructor will take over and clean up the +/// task. It's not necessary to do anything with the return value of this +/// function other than ensuring that you `.await` the function call. +pub async fn yield_async() { + #[derive(Default)] + struct Yield { + yielded: bool, + } + + impl Future for Yield { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<()> { + if self.yielded { + Poll::Ready(()) + } else { + self.yielded = true; + context.waker().wake_by_ref(); + Poll::Pending + } + } + } + + Yield::default().await; +} + +/// Call the `backpressure.set` canonical built-in function. +/// +/// When `enabled` is `true`, this tells the host to defer any new calls to this +/// component instance until further notice (i.e. until `backpressure.set` is +/// called again with `enabled` set to `false`). +#[deprecated = "use backpressure_{inc,dec} instead"] +pub fn backpressure_set(enabled: bool) { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn backpressure_set(_: i32) { + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[backpressure-set]"] + fn backpressure_set(_: i32); + } + + unsafe { backpressure_set(if enabled { 1 } else { 0 }) } +} + +/// Call the `backpressure.inc` canonical built-in function. +pub fn backpressure_inc() { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn backpressure_inc() { + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[backpressure-inc]"] + fn backpressure_inc(); + } + + unsafe { backpressure_inc() } +} + +/// Call the `backpressure.dec` canonical built-in function. +pub fn backpressure_dec() { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn backpressure_dec() { + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[backpressure-dec]"] + fn backpressure_dec(); + } + + unsafe { backpressure_dec() } +} + +fn context_get() -> *mut u8 { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn get() -> *mut u8 { + unreachable!() + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[context-get-0]"] + fn get() -> *mut u8; + } + + unsafe { get() } +} + +unsafe fn context_set(value: *mut u8) { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn set(_: *mut u8) { + unreachable!() + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "$root")] + extern "C" { + #[link_name = "[context-set-0]"] + fn set(value: *mut u8); + } + + unsafe { set(value) } +} + +#[doc(hidden)] +pub struct TaskCancelOnDrop { + _priv: (), +} + +impl TaskCancelOnDrop { + #[doc(hidden)] + pub fn new() -> TaskCancelOnDrop { + TaskCancelOnDrop { _priv: () } + } + + #[doc(hidden)] + pub fn forget(self) { + mem::forget(self); + } +} + +impl Drop for TaskCancelOnDrop { + fn drop(&mut self) { + #[cfg(not(target_arch = "wasm32"))] + unsafe fn cancel() { + unreachable!() + } + + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "[export]$root")] + extern "C" { + #[link_name = "[task-cancel]"] + fn cancel(); + } + + unsafe { cancel() } + } +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/libwit_bindgen_cabi.a and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/libwit_bindgen_cabi.a differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,230 @@ +use core::alloc::Layout; +use core::ptr::{self, NonNull}; + +// Re-export `bitflags` so that we can reference it from macros. +#[cfg(feature = "bitflags")] +pub use bitflags; + +#[cfg(not(feature = "bitflags"))] +pub mod bitflags { + #[macro_export] + macro_rules! bitflags { + ( + $(#[$attr:meta])* + $vis:vis struct $name:ident : $repr:ty { + $( + $(#[$flag_attr:meta])* + const $flag:ident = $val:expr; + )* + } + ) => { + $(#[$attr])* + $vis struct $name { + bits: $repr, + } + + impl $name { + $( + $(#[$flag_attr])* + $vis const $flag: Self = Self { bits: $val }; + )* + $vis fn empty() -> Self { + Self { bits: 0 } + } + + $vis fn from_bits_retain(bits: $repr) -> Self { + Self { bits } + } + + $vis fn bits(&self) -> $repr { + self.bits + } + } + + impl core::ops::BitOr<$name> for $name { + type Output = Self; + fn bitor(self, rhs: $name) -> $name { + Self { bits: self.bits | rhs.bits } + } + } + + impl core::ops::BitAnd<$name> for $name { + type Output = Self; + fn bitand(self, rhs: $name) -> $name { + Self { bits: self.bits & rhs.bits } + } + } + + impl core::ops::BitXor<$name> for $name { + type Output = Self; + fn bitxor(self, rhs: $name) -> $name { + Self { bits: self.bits ^ rhs.bits } + } + } + }; + } + + pub use crate::bitflags; +} + +/// For more information about this see `./ci/rebuild-libwit-bindgen-cabi.sh`. +#[cfg(not(target_env = "p2"))] +mod wit_bindgen_cabi_realloc; + +/// This function is called from generated bindings and will be deleted by +/// the linker. The purpose of this function is to force a reference to the +/// symbol `cabi_realloc` to make its way through to the final linker +/// command line. That way `wasm-ld` will pick it up, see it needs to be +/// exported, and then export it. +/// +/// For more information about this see `./ci/rebuild-libwit-bindgen-cabi.sh`. +pub fn maybe_link_cabi_realloc() { + #[cfg(all(target_family = "wasm", not(target_env = "p2")))] + { + extern "C" { + fn cabi_realloc( + old_ptr: *mut u8, + old_len: usize, + align: usize, + new_len: usize, + ) -> *mut u8; + } + // Force the `cabi_realloc` symbol to be referenced from here. This + // is done with a `#[used]` Rust `static` to ensure that this + // reference makes it all the way to the linker before it's + // considered for garbage collection. When the linker sees it it'll + // remove this `static` here (due to it not actually being needed) + // but the linker will have at that point seen the `cabi_realloc` + // symbol and it should get exported. + #[used] + static _NAME_DOES_NOT_MATTER: unsafe extern "C" fn( + *mut u8, + usize, + usize, + usize, + ) -> *mut u8 = cabi_realloc; + } +} + +/// NB: this function is called by a generated function in the +/// `cabi_realloc` module above. It's otherwise never explicitly called. +/// +/// For more information about this see `./ci/rebuild-libwit-bindgen-cabi.sh`. +#[cfg(not(target_env = "p2"))] +pub unsafe fn cabi_realloc( + old_ptr: *mut u8, + old_len: usize, + align: usize, + new_len: usize, +) -> *mut u8 { + use alloc::alloc::{alloc as allocate, handle_alloc_error, realloc, Layout}; + + let layout; + let ptr = if old_len == 0 { + if new_len == 0 { + return align as *mut u8; + } + layout = Layout::from_size_align_unchecked(new_len, align); + allocate(layout) + } else { + debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!"); + layout = Layout::from_size_align_unchecked(old_len, align); + realloc(old_ptr, layout, new_len) + }; + if ptr.is_null() { + // Print a nice message in debug mode, but in release mode don't + // pull in so many dependencies related to printing so just emit an + // `unreachable` instruction. + if cfg!(debug_assertions) { + handle_alloc_error(layout); + } else { + #[cfg(target_arch = "wasm32")] + core::arch::wasm32::unreachable(); + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + } + } + return ptr; +} + +/// Provide a hook for generated export functions to run static constructors at +/// most once. +/// +/// wit-bindgen-rust generates a call to this function at the start of all +/// component export functions. Importantly, it is not called as part of +/// `cabi_realloc`, which is a *core* export func, but should not execute ctors. +#[cfg(target_arch = "wasm32")] +pub fn run_ctors_once() { + static mut RUN: bool = false; + unsafe { + if !RUN { + // This function is synthesized by `wasm-ld` to run all static + // constructors. wasm-ld will either provide an implementation + // of this symbol, or synthesize a wrapper around each + // exported function to (unconditionally) run ctors. By using + // this function, the linked module is opting into "manually" + // running ctors. + extern "C" { + fn __wasm_call_ctors(); + } + __wasm_call_ctors(); + RUN = true; + } + } +} + +/// Support for using the Component Model Async ABI +#[cfg(feature = "async")] +pub mod async_support; + +/// Cleanup helper used to deallocate blocks of canonical ABI data from +/// lowerings. +pub struct Cleanup { + ptr: NonNull, + layout: Layout, +} + +// Usage of the returned pointer is always unsafe and must abide by these +// conventions, but this structure itself has no inherent reason to not be +// send/sync. +unsafe impl Send for Cleanup {} +unsafe impl Sync for Cleanup {} + +impl Cleanup { + /// Allocates a chunk of memory with `layout` and returns an object to clean + /// it up. + /// + /// Always returns a pointer which is null if `layout` has size zero. The + /// optional cleanup returned will be present if `layout` has a non-zero + /// size. When dropped `Cleanup` will deallocate the pointer returned. + pub fn new(layout: Layout) -> (*mut u8, Option) { + use alloc::alloc; + + if layout.size() == 0 { + return (ptr::null_mut(), None); + } + let ptr = unsafe { alloc::alloc(layout) }; + let ptr = match NonNull::new(ptr) { + Some(ptr) => ptr, + None => alloc::handle_alloc_error(layout), + }; + (ptr.as_ptr(), Some(Cleanup { ptr, layout })) + } + + /// Discards this cleanup to leak its memory or intentionally transfer + /// ownership to some other location. + pub fn forget(self) { + core::mem::forget(self); + } +} + +impl Drop for Cleanup { + fn drop(&mut self) { + unsafe { + for i in 0..self.layout.size() { + *self.ptr.add(i).as_ptr() = 0xff; + } + alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.c clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.c --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.c 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh + +#include +#include + +extern void *cabi_realloc_wit_bindgen_0_41_0(void *ptr, size_t old_size, size_t align, size_t new_size); + +__attribute__((__weak__, __export_name__("cabi_realloc"))) +void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { + return cabi_realloc_wit_bindgen_0_41_0(ptr, old_size, align, new_size); +} + +static void *WASIP3_TASK = NULL; + +__attribute__((__weak__)) +void *wasip3_task_set(void *ptr) { + void *ret = WASIP3_TASK; + WASIP3_TASK = ptr; + return ret; +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.o and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi.o differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.c clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.c --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.c 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh + +#include + +extern void *cabi_realloc_wit_bindgen_0_46_0(void *ptr, size_t old_size, size_t align, size_t new_size); + +__attribute__((__weak__, __export_name__("cabi_realloc"))) +void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { + return cabi_realloc_wit_bindgen_0_46_0(ptr, old_size, align, new_size); +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.o and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.o differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.rs clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_realloc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_46_0( + old_ptr: *mut u8, + old_len: usize, + align: usize, + new_len: usize, +) -> *mut u8 { + crate::rt::cabi_realloc(old_ptr, old_len, align, new_len) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.c clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.c --- clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.c 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh + +#include + +static void *WASIP3_TASK = NULL; + +__attribute__((__weak__)) +void *wasip3_task_set(void *ptr) { + void *ret = WASIP3_TASK; + WASIP3_TASK = ptr; + return ret; +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.o and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/src/rt/wit_bindgen_cabi_wasip3.o differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/wit-bindgen/wasi-cli@0.2.0.wasm and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/wit-bindgen/wasi-cli@0.2.0.wasm differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"4b39574257d3ca22e2df141fdf28f17875944006af936e83c01663ff58501822",".travis.yml":"0b6cffd464cdfeaffdf609fe5d4b964529eb64c1bd8767bafc9f76028d1c5a6d","Cargo.lock":"7370623d5cb96760da2a412ae7f29a2bf314f0eb5e9a02cc82216a51c8101dc0","Cargo.toml":"b11d5218858a9e8f06f9225911c35684bdfdb50e35ca9132cc018818f830e5cc","Cargo.toml.orig":"f0d380edeffe24f34d01fb00a81b6f6aa0d96edecc6e7e4f5143574faad8d839","LICENSE":"1327309babc5f34582ae4731b9022c75ff6fa9903eb17cfd113f4abae95b898b","README.md":"44cb71cb8238ecba36e0e71ca675ae7ff62d5221211ccc2a64eaf33977712fa7","examples/resize.rs":"d6078859732b535126a3eb23e9aa87dbbbc817b30398bb21c0cb2f2e6e19761e","scripts/id_rsa.enc":"0d9a526c3c2a27c2e579f6b53b222f4b14e642482802dbccd685bd19263a4897","scripts/travis-doc-upload.cfg":"b83b0a6a0f39014545a7b3cc42a95b1779ffc9121c477d91abf7fce1f2af67bb","src/lib.rs":"f3aeb3e4bfccc1974c0f0d06aad51d0227e0e7af6a55214dc853e5977d76a520"},"package":"7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "11178efa16ee13217e0a442100e19b11a9fda531" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/y4m/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/.travis.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +language: rust +rust: + - stable + - beta + - nightly + +before_install: + - if [[ "$TRAVIS_RUST_VERSION" == *stable* ]]; then rustup component add rustfmt; cargo fmt --version; fi + +script: + - if [[ "$TRAVIS_RUST_VERSION" == *stable* ]]; then cargo fmt -- --check || (echo "Please reformat your code with 'cargo fmt' (version $(cargo fmt --version))"; false); fi + - cargo build -v + - cargo test -v + - cargo doc -v +after_success: + - curl http://docs.piston.rs/travis-doc-upload.sh | sh diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "resize" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d90e9bbc087131e45af0987e701ba91910ccb5da78560dc1889e5105cf552d" + +[[package]] +name = "y4m" +version = "0.8.0" +dependencies = [ + "resize", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "y4m" +version = "0.8.0" +authors = ["Kagami Hiiragi "] +description = "YUV4MPEG2 (.y4m) Encoder/Decoder." +homepage = "https://github.com/image-rs/y4m" +documentation = "https://docs.rs/y4m" +readme = "README.md" +keywords = [ + "y4m", + "YUV4MPEG2", + "video", + "decoder", + "encoder", +] +license = "MIT" +repository = "https://github.com/image-rs/y4m.git" + +[dev-dependencies.resize] +version = "0.4" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +[package] +name = "y4m" +version = "0.8.0" +authors = ["Kagami Hiiragi "] +description = "YUV4MPEG2 (.y4m) Encoder/Decoder." +keywords = ["y4m", "YUV4MPEG2", "video", "decoder", "encoder"] +license = "MIT" +readme = "README.md" +homepage = "https://github.com/image-rs/y4m" +repository = "https://github.com/image-rs/y4m.git" +documentation = "https://docs.rs/y4m" + +[dev-dependencies] +resize = "0.4" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/y4m/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2019 PistonDevelopers +Copyright (c) 2019 image-rs contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/README.md clamav-1.4.6+dfsg/.cargo/vendor/y4m/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +# y4m [![Build Status](https://travis-ci.com/image-rs/y4m.png?branch=master)](https://travis-ci.com/github/image-rs/y4m) [![crates.io](https://img.shields.io/crates/v/y4m.svg)](https://crates.io/crates/y4m) + +YUV4MPEG2 (.y4m) Encoder/Decoder. [Format specification](https://wiki.multimedia.cx/index.php?title=YUV4MPEG2). + +## Usage + +Simple stream copying: + +```rust +extern crate y4m; +use std::io; + +let mut infh = io::stdin(); +let mut outfh = io::stdout(); +let mut dec = y4m::decode(&mut infh).unwrap(); +let mut enc = y4m::encode(dec.get_width(), dec.get_height(), dec.get_framerate()) + .with_colorspace(dec.get_colorspace()) + .write_header(&mut outfh) + .unwrap(); +loop { + match dec.read_frame() { + Ok(frame) => if enc.write_frame(&frame).is_err() { break }, + _ => break, + } +} +``` + +See [API documentation](https://docs.rs/y4m) for overview of all available methods. See also [this example](examples/resize.rs) on how to resize input y4m into grayscale y4m of different resolution: + +```bash +cargo build --release --example resize +ffmpeg -i in.mkv -f yuv4mpegpipe - | target/release/examples/resize - 640x360 - | mpv - +``` + +## License + +Library is licensed under [MIT](LICENSE). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/examples/resize.rs clamav-1.4.6+dfsg/.cargo/vendor/y4m/examples/resize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/examples/resize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/examples/resize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,57 @@ +extern crate resize; +extern crate y4m; + +use resize::Pixel::Gray8; +use resize::Type::Triangle; +use std::env; +use std::fs::File; +use std::io; + +fn main() { + let args: Vec<_> = env::args().collect(); + if args.len() != 4 { + return println!("Usage: {} in.y4m WxH out.y4m", args[0]); + } + + let mut infh: Box = if args[1] == "-" { + Box::new(io::stdin()) + } else { + Box::new(File::open(&args[1]).unwrap()) + }; + let mut decoder = y4m::decode(&mut infh).unwrap(); + + if decoder.get_bit_depth() != 8 { + panic!( + "Unsupported bit depth {}, this example only supports 8.", + decoder.get_bit_depth() + ); + } + let (w1, h1) = (decoder.get_width(), decoder.get_height()); + let dst_dims: Vec<_> = args[2].split("x").map(|s| s.parse().unwrap()).collect(); + let (w2, h2) = (dst_dims[0], dst_dims[1]); + let mut resizer = resize::new(w1, h1, w2, h2, Gray8, Triangle); + let mut dst = vec![0; w2 * h2]; + + let mut outfh: Box = if args[3] == "-" { + Box::new(io::stdout()) + } else { + Box::new(File::create(&args[3]).unwrap()) + }; + let mut encoder = y4m::encode(w2, h2, decoder.get_framerate()) + .with_colorspace(y4m::Colorspace::Cmono) + .write_header(&mut outfh) + .unwrap(); + + loop { + match decoder.read_frame() { + Ok(frame) => { + resizer.resize(frame.get_y_plane(), &mut dst); + let out_frame = y4m::Frame::new([&dst, &[], &[]], None); + if encoder.write_frame(&out_frame).is_err() { + break; + } + } + _ => break, + } + } +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/y4m/scripts/id_rsa.enc and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/y4m/scripts/id_rsa.enc differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/scripts/travis-doc-upload.cfg clamav-1.4.6+dfsg/.cargo/vendor/y4m/scripts/travis-doc-upload.cfg --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/scripts/travis-doc-upload.cfg 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/scripts/travis-doc-upload.cfg 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,3 @@ +PROJECT_NAME=y4m +DOCS_REPO=PistonDevelopers/docs.git +SSH_KEY_TRAVIS_ID=5d3a3cfaa652 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/y4m/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/y4m/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/y4m/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/y4m/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,675 @@ +//! # YUV4MPEG2 (.y4m) Encoder/Decoder +#![deny(missing_docs)] + +use std::fmt; +use std::io; +use std::io::Read; +use std::io::Write; +use std::num; +use std::str; + +const MAX_PARAMS_SIZE: usize = 1024; +const FILE_MAGICK: &[u8] = b"YUV4MPEG2 "; +const FRAME_MAGICK: &[u8] = b"FRAME"; +const TERMINATOR: u8 = 0x0A; +const FIELD_SEP: u8 = b' '; +const RATIO_SEP: u8 = b':'; + +/// Both encoding and decoding errors. +#[derive(Debug)] +pub enum Error { + /// End of the file. Technically not an error, but it's easier to process + /// that way. + EOF, + /// Bad input parameters provided. + BadInput, + /// Unknown colorspace (possibly just unimplemented). + UnknownColorspace, + /// Error while parsing the file/frame header. + // TODO(Kagami): Better granularity of parse errors. + ParseError(ParseError), + /// Error while reading/writing the file. + IoError(io::Error), + /// Out of memory (limits exceeded). + OutOfMemory, +} + +impl std::error::Error for crate::Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Error::EOF => None, + Error::BadInput => None, + Error::UnknownColorspace => None, + Error::ParseError(ref err) => Some(err), + Error::IoError(ref err) => Some(err), + Error::OutOfMemory => None, + } + } +} + +impl fmt::Display for crate::Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::EOF => write!(f, "End of file"), + Error::BadInput => write!(f, "Bad input parameters provided"), + Error::UnknownColorspace => write!(f, "Bad input parameters provided"), + Error::ParseError(ref err) => err.fmt(f), + Error::IoError(ref err) => err.fmt(f), + Error::OutOfMemory => write!(f, "Out of memory (limits exceeded)"), + } + } +} + +/// Granular ParseError Definiations +pub enum ParseError { + /// Error reading y4m header + InvalidY4M, + /// Error parsing int + Int, + /// Error parsing UTF8 + Utf8, + /// General Parsing Error + General, +} + +impl std::error::Error for crate::ParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + ParseError::InvalidY4M => None, + ParseError::Int => None, + ParseError::Utf8 => None, + ParseError::General => None, + } + } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ParseError::InvalidY4M => write!(f, "Error parsing y4m header"), + ParseError::Int => write!(f, "Error parsing Int"), + ParseError::Utf8 => write!(f, "Error parsing UTF8"), + ParseError::General => write!(f, "General parsing error"), + } + } +} + +impl fmt::Debug for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ParseError::InvalidY4M => write!(f, "Error parsing y4m header"), + ParseError::Int => write!(f, "Error parsing Int"), + ParseError::Utf8 => write!(f, "Error parsing UTF8"), + ParseError::General => write!(f, "General parsing error"), + } + } +} + +macro_rules! parse_error { + ($p:expr) => { + return Err(Error::ParseError($p)) + }; +} + +impl From for Error { + fn from(err: io::Error) -> Error { + match err.kind() { + io::ErrorKind::UnexpectedEof => Error::EOF, + _ => Error::IoError(err), + } + } +} + +impl From for Error { + fn from(_: num::ParseIntError) -> Error { + Error::ParseError(ParseError::Int) + } +} + +impl From for Error { + fn from(_: str::Utf8Error) -> Error { + Error::ParseError(ParseError::Utf8) + } +} + +trait EnhancedRead { + fn read_until(&mut self, ch: u8, buf: &mut [u8]) -> Result; +} + +impl EnhancedRead for R { + // Current implementation does one `read` call per byte. This might be a + // bit slow for long headers but it simplifies things: we don't need to + // check whether start of the next frame is already read and so on. + fn read_until(&mut self, ch: u8, buf: &mut [u8]) -> Result { + let mut collected = 0; + while collected < buf.len() { + let chunk_size = self.read(&mut buf[collected..=collected])?; + if chunk_size == 0 { + return Err(Error::EOF); + } + if buf[collected] == ch { + return Ok(collected); + } + collected += chunk_size; + } + parse_error!(ParseError::General) + } +} + +fn parse_bytes(buf: &[u8]) -> Result { + // A bit kludgy but seems like there is no other way. + Ok(str::from_utf8(buf)?.parse()?) +} + +/// A newtype wrapper around Vec to ensure validity as a vendor extension. +#[derive(Debug, Clone)] +pub struct VendorExtensionString(Vec); + +impl VendorExtensionString { + /// Create a new vendor extension string. + /// + /// For example, setting to `b"COLORRANGE=FULL"` sets the interpretation of + /// the YUV values to cover the full range (rather a limited "studio swing" + /// range). + /// + /// The argument `x_option` must not contain a space (b' ') character, + /// otherwise [Error::BadInput] is returned. + pub fn new(value: Vec) -> Result { + if value.contains(&b' ') { + return Err(Error::BadInput); + } + Ok(VendorExtensionString(value)) + } + /// Get the vendor extension string. + pub fn value(&self) -> &[u8] { + self.0.as_slice() + } +} + +/// Simple ratio structure since stdlib lacks one. +#[derive(Debug, Clone, Copy)] +pub struct Ratio { + /// Numerator. + pub num: usize, + /// Denominator. + pub den: usize, +} + +impl Ratio { + /// Create a new ratio. + pub fn new(num: usize, den: usize) -> Ratio { + Ratio { num, den } + } + + /// Parse a ratio from a byte slice. + pub fn parse(value: &[u8]) -> Result { + let parts: Vec<_> = value.splitn(2, |&b| b == RATIO_SEP).collect(); + if parts.len() != 2 { + parse_error!(ParseError::General) + } + let num = parse_bytes(parts[0])?; + let den = parse_bytes(parts[1])?; + Ok(Ratio::new(num, den)) + } +} + +impl fmt::Display for Ratio { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.num, self.den) + } +} + +/// Colorspace (color model/pixel format). Only subset of them is supported. +/// +/// From libavformat/yuv4mpegenc.c: +/// +/// > yuv4mpeg can only handle yuv444p, yuv422p, yuv420p, yuv411p and gray8 +/// pixel formats. And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, +/// yuv444p10, yuv422p10, yuv420p10, yuv444p12, yuv422p12, yuv420p12, +/// yuv444p14, yuv422p14, yuv420p14, yuv444p16, yuv422p16, yuv420p16, gray9, +/// gray10, gray12 and gray16 pixel formats. +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum Colorspace { + /// Grayscale only, 8-bit. + Cmono, + /// Grayscale only, 12-bit. + Cmono12, + /// 4:2:0 with coincident chroma planes, 8-bit. + C420, + /// 4:2:0 with coincident chroma planes, 10-bit. + C420p10, + /// 4:2:0 with coincident chroma planes, 12-bit. + C420p12, + /// 4:2:0 with biaxially-displaced chroma planes, 8-bit. + C420jpeg, + /// 4:2:0 with vertically-displaced chroma planes, 8-bit. + C420paldv, + /// Found in some files. Same as `C420`. + C420mpeg2, + /// 4:2:2, 8-bit. + C422, + /// 4:2:2, 10-bit. + C422p10, + /// 4:2:2, 12-bit. + C422p12, + /// 4:4:4, 8-bit. + C444, + /// 4:4:4, 10-bit. + C444p10, + /// 4:4:4, 12-bit. + C444p12, +} + +impl Colorspace { + /// Return the bit depth per sample + #[inline] + pub fn get_bit_depth(self) -> usize { + match self { + Colorspace::Cmono + | Colorspace::C420 + | Colorspace::C422 + | Colorspace::C444 + | Colorspace::C420jpeg + | Colorspace::C420paldv + | Colorspace::C420mpeg2 => 8, + Colorspace::C420p10 | Colorspace::C422p10 | Colorspace::C444p10 => 10, + Colorspace::Cmono12 + | Colorspace::C420p12 + | Colorspace::C422p12 + | Colorspace::C444p12 => 12, + } + } + + /// Return the number of bytes in a sample + #[inline] + pub fn get_bytes_per_sample(self) -> usize { + if self.get_bit_depth() <= 8 { + 1 + } else { + 2 + } + } +} + +fn get_plane_sizes(width: usize, height: usize, colorspace: Colorspace) -> (usize, usize, usize) { + let y_plane_size = width * height * colorspace.get_bytes_per_sample(); + + let c420_chroma_size = + ((width + 1) / 2) * ((height + 1) / 2) * colorspace.get_bytes_per_sample(); + let c422_chroma_size = ((width + 1) / 2) * height * colorspace.get_bytes_per_sample(); + + let c420_sizes = (y_plane_size, c420_chroma_size, c420_chroma_size); + let c422_sizes = (y_plane_size, c422_chroma_size, c422_chroma_size); + let c444_sizes = (y_plane_size, y_plane_size, y_plane_size); + + match colorspace { + Colorspace::Cmono | Colorspace::Cmono12 => (y_plane_size, 0, 0), + Colorspace::C420 + | Colorspace::C420p10 + | Colorspace::C420p12 + | Colorspace::C420jpeg + | Colorspace::C420paldv + | Colorspace::C420mpeg2 => c420_sizes, + Colorspace::C422 | Colorspace::C422p10 | Colorspace::C422p12 => c422_sizes, + Colorspace::C444 | Colorspace::C444p10 | Colorspace::C444p12 => c444_sizes, + } +} + +/// Limits on the resources `Decoder` is allowed to use. +#[derive(Clone, Copy, Debug)] +pub struct Limits { + /// Maximum allowed size of frame buffer, default is 1 GiB. + pub bytes: usize, +} + +impl Default for Limits { + fn default() -> Limits { + Limits { + bytes: 1024 * 1024 * 1024, + } + } +} + +/// YUV4MPEG2 decoder. +pub struct Decoder { + reader: R, + params_buf: Vec, + frame_buf: Vec, + raw_params: Vec, + width: usize, + height: usize, + framerate: Ratio, + pixel_aspect: Ratio, + colorspace: Colorspace, + y_len: usize, + u_len: usize, +} + +impl Decoder { + /// Create a new decoder instance. + pub fn new(reader: R) -> Result, Error> { + Decoder::new_with_limits(reader, Limits::default()) + } + + /// Create a new decoder instance with custom limits. + pub fn new_with_limits(mut reader: R, limits: Limits) -> Result, Error> { + let mut params_buf = vec![0; MAX_PARAMS_SIZE]; + let end_params_pos = reader.read_until(TERMINATOR, &mut params_buf)?; + if end_params_pos < FILE_MAGICK.len() || !params_buf.starts_with(FILE_MAGICK) { + parse_error!(ParseError::InvalidY4M) + } + let raw_params = params_buf[FILE_MAGICK.len()..end_params_pos].to_owned(); + let mut width = 0; + let mut height = 0; + // Framerate is actually required per spec, but let's be a bit more + // permissive as per ffmpeg behavior. + let mut framerate = Ratio::new(25, 1); + let mut pixel_aspect = Ratio::new(1, 1); + let mut colorspace = None; + // We shouldn't convert it to string because encoding is unspecified. + for param in raw_params.split(|&b| b == FIELD_SEP) { + if param.is_empty() { + continue; + } + let (name, value) = (param[0], ¶m[1..]); + // TODO(Kagami): interlacing, comment. + match name { + b'W' => width = parse_bytes(value)?, + b'H' => height = parse_bytes(value)?, + b'F' => framerate = Ratio::parse(value)?, + b'A' => pixel_aspect = Ratio::parse(value)?, + b'C' => { + colorspace = match value { + b"mono" => Some(Colorspace::Cmono), + b"mono12" => Some(Colorspace::Cmono12), + b"420" => Some(Colorspace::C420), + b"420p10" => Some(Colorspace::C420p10), + b"420p12" => Some(Colorspace::C420p12), + b"422" => Some(Colorspace::C422), + b"422p10" => Some(Colorspace::C422p10), + b"422p12" => Some(Colorspace::C422p12), + b"444" => Some(Colorspace::C444), + b"444p10" => Some(Colorspace::C444p10), + b"444p12" => Some(Colorspace::C444p12), + b"420jpeg" => Some(Colorspace::C420jpeg), + b"420paldv" => Some(Colorspace::C420paldv), + b"420mpeg2" => Some(Colorspace::C420mpeg2), + _ => return Err(Error::UnknownColorspace), + } + } + _ => {} + } + } + let colorspace = colorspace.unwrap_or(Colorspace::C420); + if width == 0 || height == 0 { + parse_error!(ParseError::General) + } + let (y_len, u_len, v_len) = get_plane_sizes(width, height, colorspace); + let frame_size = y_len + u_len + v_len; + if frame_size > limits.bytes { + return Err(Error::OutOfMemory); + } + let frame_buf = vec![0; frame_size]; + Ok(Decoder { + reader, + params_buf, + frame_buf, + raw_params, + width, + height, + framerate, + pixel_aspect, + colorspace, + y_len, + u_len, + }) + } + + /// Iterate over frames. End of input is indicated by `Error::EOF`. + pub fn read_frame(&mut self) -> Result { + let end_params_pos = self.reader.read_until(TERMINATOR, &mut self.params_buf)?; + if end_params_pos < FRAME_MAGICK.len() || !self.params_buf.starts_with(FRAME_MAGICK) { + parse_error!(ParseError::InvalidY4M) + } + // We don't parse frame params currently but user has access to them. + let start_params_pos = FRAME_MAGICK.len(); + let raw_params = if end_params_pos - start_params_pos > 0 { + // Check for extra space. + if self.params_buf[start_params_pos] != FIELD_SEP { + parse_error!(ParseError::InvalidY4M) + } + Some(self.params_buf[start_params_pos + 1..end_params_pos].to_owned()) + } else { + None + }; + self.reader.read_exact(&mut self.frame_buf)?; + Ok(Frame::new( + [ + &self.frame_buf[0..self.y_len], + &self.frame_buf[self.y_len..self.y_len + self.u_len], + &self.frame_buf[self.y_len + self.u_len..], + ], + raw_params, + )) + } + + /// Return file width. + #[inline] + pub fn get_width(&self) -> usize { + self.width + } + /// Return file height. + #[inline] + pub fn get_height(&self) -> usize { + self.height + } + /// Return file framerate. + #[inline] + pub fn get_framerate(&self) -> Ratio { + self.framerate + } + /// Return file pixel aspect. + #[inline] + pub fn get_pixel_aspect(&self) -> Ratio { + self.pixel_aspect + } + /// Return file colorspace. + /// + /// **NOTE:** normally all .y4m should have colorspace param, but there are + /// files encoded without that tag and it's unclear what should we do in + /// that case. Currently C420 is implied by default as per ffmpeg behavior. + #[inline] + pub fn get_colorspace(&self) -> Colorspace { + self.colorspace + } + /// Return file raw parameters. + #[inline] + pub fn get_raw_params(&self) -> &[u8] { + &self.raw_params + } + /// Return the bit depth per sample + #[inline] + pub fn get_bit_depth(&self) -> usize { + self.colorspace.get_bit_depth() + } + /// Return the number of bytes in a sample + #[inline] + pub fn get_bytes_per_sample(&self) -> usize { + self.colorspace.get_bytes_per_sample() + } +} + +/// A single frame. +#[derive(Debug)] +pub struct Frame<'f> { + planes: [&'f [u8]; 3], + raw_params: Option>, +} + +impl<'f> Frame<'f> { + /// Create a new frame with optional parameters. + /// No heap allocations are made. + pub fn new(planes: [&'f [u8]; 3], raw_params: Option>) -> Frame<'f> { + Frame { planes, raw_params } + } + + /// Create a new frame from data in 16-bit format. + pub fn from_u16(planes: [&'f [u16]; 3], raw_params: Option>) -> Frame<'f> { + Frame::new( + [ + unsafe { + std::slice::from_raw_parts::( + planes[0].as_ptr() as *const u8, + planes[0].len() * 2, + ) + }, + unsafe { + std::slice::from_raw_parts::( + planes[1].as_ptr() as *const u8, + planes[1].len() * 2, + ) + }, + unsafe { + std::slice::from_raw_parts::( + planes[2].as_ptr() as *const u8, + planes[2].len() * 2, + ) + }, + ], + raw_params, + ) + } + + /// Return Y (first) plane. + #[inline] + pub fn get_y_plane(&self) -> &[u8] { + self.planes[0] + } + /// Return U (second) plane. Empty in case of grayscale. + #[inline] + pub fn get_u_plane(&self) -> &[u8] { + self.planes[1] + } + /// Return V (third) plane. Empty in case of grayscale. + #[inline] + pub fn get_v_plane(&self) -> &[u8] { + self.planes[2] + } + /// Return frame raw parameters if any. + #[inline] + pub fn get_raw_params(&self) -> Option<&[u8]> { + self.raw_params.as_ref().map(|v| &v[..]) + } +} + +/// Encoder builder. Allows to set y4m file parameters using builder pattern. +// TODO(Kagami): Accept all known tags and raw params. +#[derive(Debug)] +pub struct EncoderBuilder { + width: usize, + height: usize, + framerate: Ratio, + pixel_aspect: Ratio, + colorspace: Colorspace, + vendor_extensions: Vec>, +} + +impl EncoderBuilder { + /// Create a new encoder builder. + pub fn new(width: usize, height: usize, framerate: Ratio) -> EncoderBuilder { + EncoderBuilder { + width, + height, + framerate, + pixel_aspect: Ratio::new(1, 1), + colorspace: Colorspace::C420, + vendor_extensions: vec![], + } + } + + /// Specify file colorspace. + pub fn with_colorspace(mut self, colorspace: Colorspace) -> Self { + self.colorspace = colorspace; + self + } + + /// Specify file pixel aspect. + pub fn with_pixel_aspect(mut self, pixel_aspect: Ratio) -> Self { + self.pixel_aspect = pixel_aspect; + self + } + + /// Add vendor extension. + pub fn append_vendor_extension(mut self, x_option: VendorExtensionString) -> Self { + self.vendor_extensions.push(x_option.0); + self + } + + /// Write header to the stream and create encoder instance. + pub fn write_header(self, mut writer: W) -> Result, Error> { + // XXX(Kagami): Beware that FILE_MAGICK already contains space. + writer.write_all(FILE_MAGICK)?; + write!( + writer, + "W{} H{} F{}", + self.width, self.height, self.framerate + )?; + if self.pixel_aspect.num != 1 || self.pixel_aspect.den != 1 { + write!(writer, " A{}", self.pixel_aspect)?; + } + for x_option in self.vendor_extensions.iter() { + write!(writer, " X")?; + writer.write_all(x_option)?; + } + write!(writer, " {:?}", self.colorspace)?; + writer.write_all(&[TERMINATOR])?; + let (y_len, u_len, v_len) = get_plane_sizes(self.width, self.height, self.colorspace); + Ok(Encoder { + writer, + y_len, + u_len, + v_len, + }) + } +} + +/// YUV4MPEG2 encoder. +pub struct Encoder { + writer: W, + y_len: usize, + u_len: usize, + v_len: usize, +} + +impl Encoder { + /// Write next frame to the stream. + pub fn write_frame(&mut self, frame: &Frame) -> Result<(), Error> { + if frame.get_y_plane().len() != self.y_len + || frame.get_u_plane().len() != self.u_len + || frame.get_v_plane().len() != self.v_len + { + return Err(Error::BadInput); + } + self.writer.write_all(FRAME_MAGICK)?; + if let Some(params) = frame.get_raw_params() { + self.writer.write_all(&[FIELD_SEP])?; + self.writer.write_all(params)?; + } + self.writer.write_all(&[TERMINATOR])?; + self.writer.write_all(frame.get_y_plane())?; + self.writer.write_all(frame.get_u_plane())?; + self.writer.write_all(frame.get_v_plane())?; + Ok(()) + } +} + +/// Create a new decoder instance. Alias for `Decoder::new`. +pub fn decode(reader: R) -> Result, Error> { + Decoder::new(reader) +} + +/// Create a new encoder builder. Alias for `EncoderBuilder::new`. +pub fn encode(width: usize, height: usize, framerate: Ratio) -> EncoderBuilder { + EncoderBuilder::new(width, height, framerate) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"c73c7e5a30cf846631c1c3090d1d8d4e7f431cdd7ac69eab0eeee220dd5aaf14","CHANGELOG.md":"876e5a74db78bdc53677ec4d489ce7b2fc87840f2dc094423cef406138082708","CONTRIBUTING.md":"a0980739c88a1b5fe71e487ec49ead40a33e96042d4cb2310240ac1a635c97d3","Cargo.lock":"9adbe12fc472d426f20aac56b7bc051f1e2b88057ac35ca2abedc8c714d1b230","Cargo.toml":"aa4901b586f87bddae43ffe5aada7860ecbb8c49da81e92b47e3c72fa7632750","Cargo.toml.orig":"5ef0cf44154c1fce2604ceefbd6f6b8f49262e7cf02c5ee57ed5e1c7ade9376b","LICENSE-APACHE":"9d185ac6703c4b0453974c0d85e9eee43e6941009296bb1f5eb0b54e2329e9f3","LICENSE-BSD":"83c1763356e822adde0a2cae748d938a73fdc263849ccff6b27776dff213bd32","LICENSE-MIT":"1a2f5c12ddc934d58956aa5dbdd3255fe55fd957633ab7d0d39e4f0daa73f7df","POLICIES.md":"43dbf7f7b6e003fe080099e51ea2b70b5d99fa2185ee54717a914202a42e1a82","README.md":"3d2a9c183a16038d8ba7bbeb4fa963f6793ae70aabf9d7df52967c47440e775b","build.rs":"7314278de5615bc432c65a123958136c98e996ce7c8cbf5f9d69a90f694d694b","cargo.sh":"f1899964e521b76e650470c508319a6738c4fe296e75908b628d35e965598f4a","ci/check_all_toolchains_tested.sh":"e67462dc8744126d54ecf15cbb3941147e3158953eed476af8e4cddf56dc352b","ci/check_fmt.sh":"0668de6302f287dc6c037ba5863bb6d2b3cb7efb14be35a5c594ad353e8275a7","ci/check_job_dependencies.sh":"79291a5abd881f9151260af741aadc38d1c4df2e22593d60cc424723d201c265","ci/check_readme.sh":"00abb89eb4d94c26773f6a568faada404868c1be023e7048f970392a76ba4a31","ci/check_todo.sh":"6b7085c06b45d80d51f2853ebd4d83675790b8a5ac7b61a075c967cfb7db56a7","ci/check_versions.sh":"04a0ae151dfbb5c26d8af5722ba312dab75733e08a1eefc0680e67b053730065","ci/release_crate_version.sh":"0048efe5c2eb256f79c93689359aba729929a46b389559697763b880354c8f4a","clippy.toml":"df67a6131fff2fe52309e797d2dfad080fc8cbdfcb1baa7f14415b3e397c291c","githooks/pre-push":"ab6ddb90a7024042ce41cdbe7e4cd2c2bc7fe40b4f6cacb7aba1309cf3fa2a1a","rustfmt.toml":"47800771c2ffb8e12eecebc29b8282aea5353ec0bc5c2ccd9ba9d8e5dd6454ab","src/byte_slice.rs":"529c446a79e450b307911ed955b6d7b1dbf51292b62ce9c3bfb9c0b714681079","src/byteorder.rs":"f13b4e9920a2e59c287f4e6663ebfa763b0b633001a3470f45f4644af1e1ff37","src/deprecated.rs":"df993f07cb37628012e45716aa74237a1294b98eef80f1ec69a9b17b9f354342","src/doctests.rs":"15b4641dd8a9c93b6ce630516f04aba4aa439072d08ba9820d597ae4127424cd","src/error.rs":"66669735be40dd8b12c890eafddb662c616248bff7f49f0d9fe0f9fa4b2e2214","src/impls.rs":"e3663534b85a388888e62070e778e2858feb52c4d3c4672b3ddf5e5b3af3bc16","src/layout.rs":"de10e484907c65da3fdc74aae5cd24088b1614bab4d11b9df9b45d9ccf4caba4","src/lib.rs":"af5865a5f7a328c03d6a00c01637ba4a02aba82e27ff26c09ff26555a03274dc","src/macros.rs":"4ac6288c039aca5f3442a659b68be2b5e492a7eba2c3623078e69b37a96a0201","src/pointer/inner.rs":"38639869f3c4e34b7c1fdad8be644f1d60a7327249bb32d207f0764d832e3b2e","src/pointer/invariant.rs":"817452ba94b18db728d405eec2512afcc8e8aa771151899d4839700216ad6041","src/pointer/mod.rs":"867bc068873c414d7d6405cc46d237fc379aca6b120233d161e762d24445c097","src/pointer/ptr.rs":"4a6f2bccae5df01acdf211b6aa3873a8fcbd37c7a2cdc66761954da67739e546","src/pointer/transmute.rs":"d462cde3836ccaee37228d2591a9d8567899c3998fe2599c089d0551b134b53c","src/ref.rs":"d04af28227fc6508486b9a67a8c2af1f054e86f298116fa44975925bb6aba204","src/split_at.rs":"7e3b048af0a1f99be0761e661b106de631c62439d36cb04640677f8970cc773c","src/util/macro_util.rs":"46d77dbbe600faef8abf3b1e3cdc180038eab6f6c15f2cf38ac6ddbf31e9d367","src/util/macros.rs":"cef2f957b2e766dd074a9b39a1ad3de5790d236a00fb287bb96e7f0078452dea","src/util/mod.rs":"e2cf58991a988411f945e03b16751adc8afd16b20d6c13e6cfdcbd053f7ea5ba","src/wrappers.rs":"77622f48a95b6b2e5d4beffa4b9db4a3c9a41c63c4bb20ac2478dccf82189d21","testdata/include_value/data":"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589","tests/trybuild.rs":"cbee2dd970cc0737f9a91e4b5e90ea9f1ce0c2639767550c1754519c2d73942d","tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs":"d41e080139456e38ee162a57e489749ed46f4ab3d548b873fff5e3cfd1915089","tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr":"4d6f6a622aaf9652774459000ae22fa9ba185f94038937e29db60a83201ebb11","tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs":"7068df4b45955c6f40bd71dfaa51ed87c850221a142fc5471b6354d5ed7a2c46","tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr":"6e811a51f5ca455fa40d7d3d9c82d9f77920d7e951edf04df123b54442416de2","tests/ui-msrv/diagnostic-not-implemented-immutable.rs":"701f02b3e7dbb91ea6257cc08b5aeaed81a32be83f2424ca3887655926b568de","tests/ui-msrv/diagnostic-not-implemented-immutable.stderr":"6ad821a39c1d87e135b7f2271e8764d256cdb8a29a59a3b71d60a308494833c5","tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs":"aaedc974685ddc133c1f6c547f51f480057db9932700210ea513be55ddb3497f","tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr":"6d4171e67ba7db879f669e4a29c70bc6da2136e6bb863a7db2e4018ddce52b25","tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs":"b030a925ff39cb2ea9b1777273f0bcfd982d972fa43cb5f2b6fdc1e6da467312","tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr":"b86aefff7280c4e9b4d1dad00be80967be770ffd5b03c7be5ee71fe36ba44287","tests/ui-msrv/diagnostic-not-implemented-known-layout.rs":"1e9d77125b68169b231d62da4fb1a1a76fb71bf7a1c4275a096a0715873b4fd2","tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr":"0c01befe42780668a7b85786a53f63988e933451f6195a67b9c8e21d806152f6","tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs":"922b8eab7092dba41ec37b3ebcad7b48eb8d391e54dff3f2869bcf1954c85003","tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr":"94acea9ac40ea7c7f57537797235f44dc7416211125aa3dc0349711568a6f9a9","tests/ui-msrv/diagnostic-not-implemented-unaligned.rs":"8af59d04924492eff43708cb504a421d9c5b8e42cae1ea0a80118f911af47e7b","tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr":"1b9d9aa822179c417f1615cfd0db5db7cdfa2efed766732e7aff54eb2394b775","tests/ui-msrv/include_value_not_from_bytes.rs":"74f4d54dad245eff591cb46344fd1f25fb27b73de941c04d1ee82b0ad2639807","tests/ui-msrv/include_value_not_from_bytes.stderr":"38fb361f9b342dd1924cfd6c2067c9a7adc6f3d1433656354cd3e819402d5f94","tests/ui-msrv/include_value_wrong_size.rs":"5a0561eeb4cb245cf5b68547b43faa2432c56bfe23f7f50677a0b110dab60cdb","tests/ui-msrv/include_value_wrong_size.stderr":"df5f93c98a658e40f195e65ccc3b0460d3e70ddf080412ff24edba1dd8da032d","tests/ui-msrv/invalid-impls/invalid-impls.rs":"8f1cf816cc77f5dd6d19bba4a463ec46a4281523c7551ab8ebcdb46197fc7732","tests/ui-msrv/invalid-impls/invalid-impls.stderr":"92414680bf94c4f9f4cad7884c5efc2eb24f1b40a09c658470b9728d4816f47c","tests/ui-msrv/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-msrv/max-align.stderr":"38775aa2a8bc035eedbc57ab0081c865b804d9a7fc5200ec425210fdea6a69d1","tests/ui-msrv/ptr-is-invariant-over-v.rs":"4c691e3644e233fabb501b260b3d6d070df7cba60b8c227615aad51cf9a148e6","tests/ui-msrv/ptr-is-invariant-over-v.stderr":"53059c3e75196a59c54948cb4389c9d09315fb1b2a1fdd8f07566dd3a189f817","tests/ui-msrv/transmute-dst-not-frombytes.rs":"2d045c51d4ea1a435ca3f4e435412eeb0ac6511597dccab8e0040d4903f2b7df","tests/ui-msrv/transmute-dst-not-frombytes.stderr":"4884cc5106c88290ce93f415a6f04be824546849fff8252080efae0c27cb9c31","tests/ui-msrv/transmute-mut-const.rs":"5689e8cbc11728f948d0263009a2219e272734e317bd20abd00bd4ddcefba713","tests/ui-msrv/transmute-mut-const.stderr":"df4b2a4c358c29279f16c591c088ca2d7bc10264827c3278df0771c8c6734e3b","tests/ui-msrv/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr":"40edcbbf7713493d2bf757b5851f6a8059faa166832ddff70266641ca60c6d18","tests/ui-msrv/transmute-mut-dst-not-frombytes.rs":"2b95c8d73c6a321137b5a59c12f554e7433b10f0e95e3ac657330bce0bab149c","tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr":"f7d2010e522be6c7cf92267f631fd8460458a31318e864ab4178e9585b41c537","tests/ui-msrv/transmute-mut-dst-not-intobytes.rs":"2e4da8d35584a2bbeaea33398bb5773a2d40aeee2e2ea7272e9382940cb97ec3","tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr":"11a249f3b16a36558130ac3c529320e400277840f69c7551f4b31de1b684808d","tests/ui-msrv/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-msrv/transmute-mut-dst-unsized.stderr":"dafce50cd8df1aa51d357f00e83c446d708a115ad2c18677b23f1b14d8bbfd25","tests/ui-msrv/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-msrv/transmute-mut-illegal-lifetime.stderr":"ff5965b190242ce05735d7c072c11565c5bd8609261c83dd06396ae8416dfbaa","tests/ui-msrv/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-msrv/transmute-mut-src-dst-not-references.stderr":"fc2740d55afdb07bdde457ac259f48ef5b3e13503968299e51791576328b207d","tests/ui-msrv/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-msrv/transmute-mut-src-immutable.stderr":"6854b18881116cecf0c716eac01aac312bfe43a295a797c4ad01ac8b7ea7d81c","tests/ui-msrv/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-msrv/transmute-mut-src-not-a-reference.stderr":"538af460b18f588b6075307de50ba1307f98189d2f2aea74346a77ad8b64710c","tests/ui-msrv/transmute-mut-src-not-frombytes.rs":"647cb1a8fa51b4e833fd3f498a471a344318affc0d2ca8080a7f17dc8a27b30a","tests/ui-msrv/transmute-mut-src-not-frombytes.stderr":"898fc436cea7ae655f35495e4e601ddef08933bc1069ed7129a7edd417b5d347","tests/ui-msrv/transmute-mut-src-not-intobytes.rs":"40ed14c627923d668173d9d5b3ee5cb0462a126ad4f209224205abc4a3f33b45","tests/ui-msrv/transmute-mut-src-not-intobytes.stderr":"aaed331e17675f0f5fa4cba627122cf38c30c0e1287e225d0bba0831cb92ee6e","tests/ui-msrv/transmute-mut-src-unsized.rs":"8ed4d688fc7f465c3dbd475f6628c265cecd4e57b31a3d5a929f02f3dca7a474","tests/ui-msrv/transmute-mut-src-unsized.stderr":"28aaf147561de1bda9f84959ce1463cfd472537af36c20134020032d9ac051a0","tests/ui-msrv/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-msrv/transmute-ptr-to-usize.stderr":"97f97dfca59430f123b802e21ccb463041eddabdcc840621036454249c83df20","tests/ui-msrv/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-msrv/transmute-ref-dst-mutable.stderr":"289e040b3e725546081dfd07640e499a5622915954f12c871708d3f46ff43d7a","tests/ui-msrv/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr":"b6c1f2aede85cce47f5ca379b9ae5a77c777e7c60de6590578c47432ebacae88","tests/ui-msrv/transmute-ref-dst-not-frombytes.rs":"88f5a210bea3e3a775f92b6aaf4586e62cb9c6f61bcdc1cd7e63ad9ad214b863","tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr":"c17eee33de0e94d29cbb04f7e7ddd3e6b11793fe24d59bae498a3763b7eab983","tests/ui-msrv/transmute-ref-dst-not-nocell.rs":"71ed55ef424c8173bb438c6a1985a1a53e09d7964950d64a50ddb914c3425760","tests/ui-msrv/transmute-ref-dst-not-nocell.stderr":"3983f0ec4ead95d693c5cc189751c18fff5553c4507bafcbd16b35c7c5d8715d","tests/ui-msrv/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-msrv/transmute-ref-dst-unsized.stderr":"6d108355c49d1fcaa03b33f84b24ed5e530179eaf9d10407a639dc493fc9beaf","tests/ui-msrv/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-msrv/transmute-ref-illegal-lifetime.stderr":"4f2a3e71cda94564f2343ca9ff23de3eca0d2ff465cedacab187151183813092","tests/ui-msrv/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-msrv/transmute-ref-src-dst-not-references.stderr":"003bb1ccb5cf8322416e00e0fa5645f94d76aad875e60d281daae9625eb583a4","tests/ui-msrv/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-msrv/transmute-ref-src-not-a-reference.stderr":"5a8d829089820ec79d9cd8d9ffac7dbde430914fdad691d46edcd96414d5cad0","tests/ui-msrv/transmute-ref-src-not-intobytes.rs":"81c6fa9775976ab678585a19a174470225e05f0b0cb43ceb754c198a8f0c9732","tests/ui-msrv/transmute-ref-src-not-intobytes.stderr":"42bcfe9f4f3126b6b274bf7838793a449be50b45b484caa7e608143ee492e520","tests/ui-msrv/transmute-ref-src-not-nocell.rs":"0f1cf580d97ed69667b02bfe5de1425ceb0678fc43bf2130e65adc38f3dc5f3f","tests/ui-msrv/transmute-ref-src-not-nocell.stderr":"542ac3b71708fb9373701924b31d16e2db09f6e14ce140491e737dce5400573c","tests/ui-msrv/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-msrv/transmute-ref-src-unsized.stderr":"2d89281a87f6322c34bcf1cc87227d0088d2fc3ac7cf36f0dc6142f17069876c","tests/ui-msrv/transmute-size-decrease.rs":"d191596652adbc26329449af4b2183bdae0a387ee668690b1de8535b71495eb7","tests/ui-msrv/transmute-size-decrease.stderr":"d11ad6ec7bc90cce95a2bb415bdbb5273f684c0b5dd49d982f59c4a719b921c4","tests/ui-msrv/transmute-size-increase-allow-shrink.rs":"d24d67d0012bf85d06b7e5ca790ca725d5fd559052d35322a72490897963cb42","tests/ui-msrv/transmute-size-increase-allow-shrink.stderr":"94a4e467ff346ddc56e35b667b424113cfb9d2c65276b47530f09c771a8681bd","tests/ui-msrv/transmute-size-increase.rs":"8ca917f831b736bfadb6ccee22acde205098678a3a2cb3cc753dfecacafcb0be","tests/ui-msrv/transmute-size-increase.stderr":"dc42334ddbd0e67151a3122cdfdd63d3b7ae9162027bdb61004579331aeb4dd3","tests/ui-msrv/transmute-src-not-intobytes.rs":"e88bbf21c2512b9c04f938ead3990161f9b050aa469d9164244966ba6e2f02dd","tests/ui-msrv/transmute-src-not-intobytes.stderr":"50f65a51782e96e82fe9e8162cb86bb9db710a30331320e420b38d65034a8419","tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs":"534191c737297f8d60d1227a9cbbb9700bb08db15783d9191df3a64c8424e303","tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr":"af8bfea743c5ec2272d4828573f1e984615c63b808dc19b70e27c77cbfc5cc4a","tests/ui-msrv/try_transmute-size-decrease.rs":"b0b9722d8032c1af00202c7bd99ac65e92ffb3dae67e17a6c10724ba86a3b1f0","tests/ui-msrv/try_transmute-size-decrease.stderr":"f70e66f6c58c3bdefd6144a1f40be18f37b819937eddb7a84dad2c5b01a5d93c","tests/ui-msrv/try_transmute-size-increase.rs":"d67d46178f8a945ab2ac5f40b71949468c337b799fec8fd24c241b94d8a6c87b","tests/ui-msrv/try_transmute-size-increase.stderr":"a79eefcba3e2ccb28841b896cd87b426508ee77139a9ae68711fb5b5f203202e","tests/ui-msrv/try_transmute-src-not-intobytes.rs":"fe267df8308820b9d6f6f3c2ba9f139d1f06c9355dcda85a72af312cf1485eb8","tests/ui-msrv/try_transmute-src-not-intobytes.stderr":"a387fa192db75cecfb18009928b87860a65a74cb39ab003977fbb03b3e95ca6a","tests/ui-msrv/try_transmute_mut-alignment-increase.rs":"7515fa447232f1a59b9b6fae435bbf19095ab4538ae0459c9f38678ae0b67ebb","tests/ui-msrv/try_transmute_mut-alignment-increase.stderr":"58dec98bb403f1acd267eedadb4c52a9a6b6582d7946407f502f4e85ace21aca","tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs":"d5150c8c6dac0d727f91763964a211da00c9842d3130c4c600b4ff6475ef6b83","tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr":"115f1d3aca310204ad6e2a5f2d31d1c9897448981047308d0702bef10225fc2a","tests/ui-msrv/try_transmute_mut-size-decrease.rs":"d18f22001da76c8781c8f276657ea73a0de92144e8a2f9c07cdcc2e2fd0df9d5","tests/ui-msrv/try_transmute_mut-size-decrease.stderr":"417da7753854af83dc1974dfb75273de779d20c376aaeed8069fbc074e32e6c5","tests/ui-msrv/try_transmute_mut-size-increase.rs":"29dbecad8f2e42a844e1a0a0e656be1724029362a8b8349b1a9cb6415fd7af6b","tests/ui-msrv/try_transmute_mut-size-increase.stderr":"f7830b448ce48a2eb38eb6af1a67fc5de70f7b4848ad2102ad9375e8e2e30e9e","tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs":"5146bff98d4fa7ad8edeb1f5a4e4d869b6296ca3ad6c239066ba7ae0584f3c1a","tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr":"ebe8b735a66f8292f7bf52e0f53122ab3f04a2f3d274eba28f124bfceb166dfe","tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs":"cee71e9cf881cf442861326320d58d30b95b9ed051dcd20c5bf1867869c1f792","tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr":"fa66b0b69cc549046c0ac0b3a1d45f7a4baacd3aa31b27f967d883b4a55d5674","tests/ui-msrv/try_transmute_ref-alignment-increase.rs":"11ae7f214f83b50e9fb7e556ea3d64d07baa274ef18143e0ff4fd76b1095fd64","tests/ui-msrv/try_transmute_ref-alignment-increase.stderr":"0f32103fdd51fc8328516ed7c039d1c369d5955399a5ed6a30294cde616d7a0c","tests/ui-msrv/try_transmute_ref-dst-mutable.rs":"1ed1c2bf9f6588cc8b2eb57afac161052ac8124e7065606b2aaab51db2aa3457","tests/ui-msrv/try_transmute_ref-dst-mutable.stderr":"8e32cfc1c968313e3d20f8d97f2f464c57635ba749f4882a7d11b41fa13f3fbe","tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs":"8a52c04394cc7f3d89b6b93e3906aef833931f730ba5beaed83cb4072334aa01","tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr":"c6141f063a6b51023d99c1b19f30a601a122f12d4ff70fe80bbe259cd95d930c","tests/ui-msrv/try_transmute_ref-size-decrease.rs":"81fabb98426fec9f0809e9706461d10b0fa67fe4bece21d2fe5547be4f7bb9ce","tests/ui-msrv/try_transmute_ref-size-decrease.stderr":"88ec42ee7efd6b336c5a0aac4d4725e1a12f12769a3a53f8804bab0916489c30","tests/ui-msrv/try_transmute_ref-size-increase.rs":"3ba36df7628324b50cfebec229f721b865de15d368b8fd3da2fa197d111fb31b","tests/ui-msrv/try_transmute_ref-size-increase.stderr":"731f5de96aad014412ff7f62fbf12d1c4f8a82d2008340917640588729c787bf","tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs":"cb455e796e85ac9af743f9b3a1ece8c5e8ee9e4a18128e84685d3c124c595ebe","tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr":"8494ad555cb66d69851a2c173fd4c64e53625ddd1228bd883b97bcd9cf553301","tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs":"d41e080139456e38ee162a57e489749ed46f4ab3d548b873fff5e3cfd1915089","tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr":"9eee5e4a97d966296a52727198ee6a65320eca7ea8039b57e0df114085533c30","tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs":"7068df4b45955c6f40bd71dfaa51ed87c850221a142fc5471b6354d5ed7a2c46","tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr":"022d5a33685c806823dbbd3b3d91c72379c021ab1b2a0d257341ef7a2cb94bc9","tests/ui-nightly/diagnostic-not-implemented-immutable.rs":"701f02b3e7dbb91ea6257cc08b5aeaed81a32be83f2424ca3887655926b568de","tests/ui-nightly/diagnostic-not-implemented-immutable.stderr":"38c4a04fb954ec958da10c4de2f209edbd00c8ada1e20cdcf1155a49ae8e0ea9","tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs":"aaedc974685ddc133c1f6c547f51f480057db9932700210ea513be55ddb3497f","tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr":"af5d6ef94fe84932f68df10a2485406db7fd01eec83875121e4f62522bc0ef52","tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs":"b030a925ff39cb2ea9b1777273f0bcfd982d972fa43cb5f2b6fdc1e6da467312","tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr":"d6b552c50d90cadab581d88e97e89ad3a0ba524db96fb1a238f8a956b28be61d","tests/ui-nightly/diagnostic-not-implemented-known-layout.rs":"1e9d77125b68169b231d62da4fb1a1a76fb71bf7a1c4275a096a0715873b4fd2","tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr":"c4b1c6cf4d9b6c219bbd76d3ad97b480e5195ed03430b9b08b96f7b499de5632","tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs":"922b8eab7092dba41ec37b3ebcad7b48eb8d391e54dff3f2869bcf1954c85003","tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr":"b1b4a6f8a645f84b8743be5fc9c56076159ef5fb64ca00aa597270400f9c18f0","tests/ui-nightly/diagnostic-not-implemented-unaligned.rs":"8af59d04924492eff43708cb504a421d9c5b8e42cae1ea0a80118f911af47e7b","tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr":"866caedb43090c3c84c3f874197da0355dd68b4c9c408db7e70b312a46c95a9f","tests/ui-nightly/include_value_not_from_bytes.rs":"74f4d54dad245eff591cb46344fd1f25fb27b73de941c04d1ee82b0ad2639807","tests/ui-nightly/include_value_not_from_bytes.stderr":"aed85100bea1880d5a43b03581fd9d6a4fbb90a3d4b152905c81f74e39bbc54a","tests/ui-nightly/include_value_wrong_size.rs":"5a0561eeb4cb245cf5b68547b43faa2432c56bfe23f7f50677a0b110dab60cdb","tests/ui-nightly/include_value_wrong_size.stderr":"8e629e37dda26ab8dcb22240997656df3ad9e29f5c03f081106e86a0f75f9a69","tests/ui-nightly/invalid-impls/invalid-impls.rs":"8f1cf816cc77f5dd6d19bba4a463ec46a4281523c7551ab8ebcdb46197fc7732","tests/ui-nightly/invalid-impls/invalid-impls.stderr":"484525cb1fe73974262a663301f49717ccc05d2891ab375d8e9ea4a2c0d61acd","tests/ui-nightly/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-nightly/max-align.stderr":"e6a1e261b02aa0fded5a3f3e3cdda6afe067f0d1430d684e3d7bd24af2e8635a","tests/ui-nightly/ptr-is-invariant-over-v.rs":"4c691e3644e233fabb501b260b3d6d070df7cba60b8c227615aad51cf9a148e6","tests/ui-nightly/ptr-is-invariant-over-v.stderr":"19b66549d832d10b4909d4d454752ef26de61611805c3d458b8e45498fc7a771","tests/ui-nightly/transmute-dst-not-frombytes.rs":"2d045c51d4ea1a435ca3f4e435412eeb0ac6511597dccab8e0040d4903f2b7df","tests/ui-nightly/transmute-dst-not-frombytes.stderr":"b48189d050615eb0d32f69d9abdb2a0d73b633fbbf8bcbfc8577d215078c506b","tests/ui-nightly/transmute-mut-const.rs":"5689e8cbc11728f948d0263009a2219e272734e317bd20abd00bd4ddcefba713","tests/ui-nightly/transmute-mut-const.stderr":"ad33bf966e5ff2eedb8027dcbc091dcf3eb4a1bfd5179e5bc0dc563b4c130ad3","tests/ui-nightly/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr":"71bbe3ef3c2e1acdb27e132730a353f59502e96ce0e0dd561f37d83f66a87fd7","tests/ui-nightly/transmute-mut-dst-not-frombytes.rs":"2b95c8d73c6a321137b5a59c12f554e7433b10f0e95e3ac657330bce0bab149c","tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr":"2d8b7a070e595f01893c4fb411e94f83f66b476d09bbd5054716d0c6d99a7bbb","tests/ui-nightly/transmute-mut-dst-not-intobytes.rs":"2e4da8d35584a2bbeaea33398bb5773a2d40aeee2e2ea7272e9382940cb97ec3","tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr":"675414f04d0cb1c50c31e79abcf637237c2c67d36cac29454c41695dd2246239","tests/ui-nightly/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-nightly/transmute-mut-dst-unsized.stderr":"286054e4de6ad2c7beb5773974275633508f8320370570b95579afea932d6a74","tests/ui-nightly/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-nightly/transmute-mut-illegal-lifetime.stderr":"b0379252732ca51314077fa20d3fb4bfcbee61f486229547c807ed0d7dede9c8","tests/ui-nightly/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-nightly/transmute-mut-src-dst-not-references.stderr":"0e1e17242ec0b1e9052087b18ccdde9fa117e430a3675b624c49d36eb933ee88","tests/ui-nightly/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-nightly/transmute-mut-src-immutable.stderr":"d99fc596f5732e5a4b193028812e047ba0c748017a94fd55d4f7802849159359","tests/ui-nightly/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-nightly/transmute-mut-src-not-a-reference.stderr":"3085a0120d3dcbc1d01d226e0b4235fe39da9a956444aabdedac9ec938aca609","tests/ui-nightly/transmute-mut-src-not-frombytes.rs":"647cb1a8fa51b4e833fd3f498a471a344318affc0d2ca8080a7f17dc8a27b30a","tests/ui-nightly/transmute-mut-src-not-frombytes.stderr":"38ecc0fdfce9a35a736d43e3314d7727043d97c6cdc45a8e5d629efa4e28b6e3","tests/ui-nightly/transmute-mut-src-not-intobytes.rs":"40ed14c627923d668173d9d5b3ee5cb0462a126ad4f209224205abc4a3f33b45","tests/ui-nightly/transmute-mut-src-not-intobytes.stderr":"8ff84cdf030145ee6af39eb8660b3cc12baefda1a1c99f03a8ec168b07270eac","tests/ui-nightly/transmute-mut-src-unsized.rs":"8ed4d688fc7f465c3dbd475f6628c265cecd4e57b31a3d5a929f02f3dca7a474","tests/ui-nightly/transmute-mut-src-unsized.stderr":"3e53f2e5c4007d9a65af4213d4b11fc1ff49220e2d3d5d015772d8f2e6f87c8f","tests/ui-nightly/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-nightly/transmute-ptr-to-usize.stderr":"e6848fffdc9069e97e3bc9863cd58e582f847710950511a596f54d9b89c0d204","tests/ui-nightly/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-nightly/transmute-ref-dst-mutable.stderr":"96d38ce9a807ad7b60a846a8f5558c447da0d6cbe9225a077df4997712424d9a","tests/ui-nightly/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr":"8ed2540877865fcdfca6e150465996a8f2872eb122ed5d647825e9181ae64754","tests/ui-nightly/transmute-ref-dst-not-frombytes.rs":"88f5a210bea3e3a775f92b6aaf4586e62cb9c6f61bcdc1cd7e63ad9ad214b863","tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr":"5cb1f280d96bd54c39ea5181f9f00530d56cc5294e53b17a84a81cd843cf774f","tests/ui-nightly/transmute-ref-dst-not-nocell.rs":"71ed55ef424c8173bb438c6a1985a1a53e09d7964950d64a50ddb914c3425760","tests/ui-nightly/transmute-ref-dst-not-nocell.stderr":"2be667ca15049ad165980aa68f057be236325067df6d2d8ab3dcb56ccad9e191","tests/ui-nightly/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-nightly/transmute-ref-dst-unsized.stderr":"1cd2f5e592729c3b54eee0c5913ed9c725565f3e6cb76d20719ef48ff23a6d67","tests/ui-nightly/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-nightly/transmute-ref-illegal-lifetime.stderr":"cb98c1b304334e58fc61be1c4b7782e68ab92d90a44c9627326d94d14a44cc38","tests/ui-nightly/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-nightly/transmute-ref-src-dst-not-references.stderr":"ca5b956d99998df493f7c72df6bd315b8cd6f1f9b113a45416b0088f1e368900","tests/ui-nightly/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-nightly/transmute-ref-src-not-a-reference.stderr":"f7b51be513a0603070e218bdd1ca2c47a94c58151ab5649f68877ea3d83268f4","tests/ui-nightly/transmute-ref-src-not-intobytes.rs":"81c6fa9775976ab678585a19a174470225e05f0b0cb43ceb754c198a8f0c9732","tests/ui-nightly/transmute-ref-src-not-intobytes.stderr":"fd9af9448514dc1aee1c7898d20cbeb34cc089b2e279c0307937f3b781f62f54","tests/ui-nightly/transmute-ref-src-not-nocell.rs":"0f1cf580d97ed69667b02bfe5de1425ceb0678fc43bf2130e65adc38f3dc5f3f","tests/ui-nightly/transmute-ref-src-not-nocell.stderr":"4f9d005f1a9d0345e9c0efd6103c5e808573aa431a49c122275bdfc74a850594","tests/ui-nightly/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-nightly/transmute-ref-src-unsized.stderr":"18c3a7284981e9f402cfb43e7ce87e75f3dab3c43d462cf534c12ad337403783","tests/ui-nightly/transmute-size-decrease.rs":"d191596652adbc26329449af4b2183bdae0a387ee668690b1de8535b71495eb7","tests/ui-nightly/transmute-size-decrease.stderr":"5bea10ccca340f92874f09380e109d52d28693283b7c9d06385924a7f5f40d9b","tests/ui-nightly/transmute-size-increase-allow-shrink.rs":"d24d67d0012bf85d06b7e5ca790ca725d5fd559052d35322a72490897963cb42","tests/ui-nightly/transmute-size-increase-allow-shrink.stderr":"e649f6b3290b27aded981ccf0826893d92502de117f0a90273eb8a7f55ccd3da","tests/ui-nightly/transmute-size-increase.rs":"8ca917f831b736bfadb6ccee22acde205098678a3a2cb3cc753dfecacafcb0be","tests/ui-nightly/transmute-size-increase.stderr":"cd1e47fc2a228429c48fb65bbae98958f9beb49a84945f67dfe5075c5eef6621","tests/ui-nightly/transmute-src-not-intobytes.rs":"e88bbf21c2512b9c04f938ead3990161f9b050aa469d9164244966ba6e2f02dd","tests/ui-nightly/transmute-src-not-intobytes.stderr":"d9e4accc84059bd31ad624677c9d364b57171b035ca3254dc6f30053709d32af","tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs":"534191c737297f8d60d1227a9cbbb9700bb08db15783d9191df3a64c8424e303","tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr":"ac89c317d93991d710092435572e4222770615d2f0de61b73e85fbe1ad99b7f0","tests/ui-nightly/try_transmute-size-decrease.rs":"b0b9722d8032c1af00202c7bd99ac65e92ffb3dae67e17a6c10724ba86a3b1f0","tests/ui-nightly/try_transmute-size-decrease.stderr":"6e806fd13bd2d961d0af597272637cb2a9db5a1de88a1228bc4643ffc9d3e156","tests/ui-nightly/try_transmute-size-increase.rs":"d67d46178f8a945ab2ac5f40b71949468c337b799fec8fd24c241b94d8a6c87b","tests/ui-nightly/try_transmute-size-increase.stderr":"21f82b6e4aa0f8b4495f064c560f7f2715b06b3f409acb0834455b6a32477e56","tests/ui-nightly/try_transmute-src-not-intobytes.rs":"fe267df8308820b9d6f6f3c2ba9f139d1f06c9355dcda85a72af312cf1485eb8","tests/ui-nightly/try_transmute-src-not-intobytes.stderr":"aa37d60f5866b4d57377db1fe5316ed931aefe0d3783219ff6a4b82f03a0a452","tests/ui-nightly/try_transmute_mut-alignment-increase.rs":"7515fa447232f1a59b9b6fae435bbf19095ab4538ae0459c9f38678ae0b67ebb","tests/ui-nightly/try_transmute_mut-alignment-increase.stderr":"3315b7cf6107cf9bf09d12ec0aa7c7aa63e1bd3cf7fe9ce214fa85dfd4b3e1ad","tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs":"d5150c8c6dac0d727f91763964a211da00c9842d3130c4c600b4ff6475ef6b83","tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr":"f8d3bf10967dbdc127fcac5b98bcb72c11eb5003d5d6ce8b82f2a25c35597cb4","tests/ui-nightly/try_transmute_mut-size-decrease.rs":"d18f22001da76c8781c8f276657ea73a0de92144e8a2f9c07cdcc2e2fd0df9d5","tests/ui-nightly/try_transmute_mut-size-decrease.stderr":"d62d253558dea1cca500a610cc0c8403773936f3eb074cae6a3bdff5cfb3d29c","tests/ui-nightly/try_transmute_mut-size-increase.rs":"29dbecad8f2e42a844e1a0a0e656be1724029362a8b8349b1a9cb6415fd7af6b","tests/ui-nightly/try_transmute_mut-size-increase.stderr":"7881a25d87477e01ba7d129f8216dfa4638679bff1dd0cf18079f48cbc037593","tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs":"5146bff98d4fa7ad8edeb1f5a4e4d869b6296ca3ad6c239066ba7ae0584f3c1a","tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr":"4a093f081eec127d766d235c5dc69e12474d8d07124ae65cfb635b4cdafbc401","tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs":"cee71e9cf881cf442861326320d58d30b95b9ed051dcd20c5bf1867869c1f792","tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr":"f9d412670dd39de3b09234901e3442934c30997e2b74982c6373172943981c48","tests/ui-nightly/try_transmute_ref-alignment-increase.rs":"11ae7f214f83b50e9fb7e556ea3d64d07baa274ef18143e0ff4fd76b1095fd64","tests/ui-nightly/try_transmute_ref-alignment-increase.stderr":"2dbec7ad47e5c4be0ab7b4abb4ef84ca9863e8e03dc4272c00271cfe6197fd0b","tests/ui-nightly/try_transmute_ref-dst-mutable.rs":"1ed1c2bf9f6588cc8b2eb57afac161052ac8124e7065606b2aaab51db2aa3457","tests/ui-nightly/try_transmute_ref-dst-mutable.stderr":"028d0a5e4828d2f2b8aa0f317d9fede4a16f2d442414214d86052f52740726a5","tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs":"8a52c04394cc7f3d89b6b93e3906aef833931f730ba5beaed83cb4072334aa01","tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr":"1a314c7a2414f67cfad65561c98af81f3c364eaa050406306278906ae5111745","tests/ui-nightly/try_transmute_ref-size-decrease.rs":"81fabb98426fec9f0809e9706461d10b0fa67fe4bece21d2fe5547be4f7bb9ce","tests/ui-nightly/try_transmute_ref-size-decrease.stderr":"d3b5656878ade1e940e3bc9d2289ebaaa588f0c12af9dbb26165aa5b73d5198b","tests/ui-nightly/try_transmute_ref-size-increase.rs":"3ba36df7628324b50cfebec229f721b865de15d368b8fd3da2fa197d111fb31b","tests/ui-nightly/try_transmute_ref-size-increase.stderr":"f2c09ea04ef8bcc49bb2dd7df573c2bab8cad5754b72d8d5cbf6c471991d485b","tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs":"cb455e796e85ac9af743f9b3a1ece8c5e8ee9e4a18128e84685d3c124c595ebe","tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr":"47742a4955efaeb09f0a9c32f3b233e516867364c255fb85fcd7e3058925ea8f","tests/ui-stable/diagnostic-not-implemented-from-bytes.rs":"d41e080139456e38ee162a57e489749ed46f4ab3d548b873fff5e3cfd1915089","tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr":"fe9123522f5b3fa708c45654038260de96c154c960a161dd8c5bb7bb46a41ef2","tests/ui-stable/diagnostic-not-implemented-from-zeros.rs":"7068df4b45955c6f40bd71dfaa51ed87c850221a142fc5471b6354d5ed7a2c46","tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr":"070c8b4c5fe7aee42b37b444b8c98ef92a6d9cdb9faa01ee48cb6f0c8c5133e8","tests/ui-stable/diagnostic-not-implemented-immutable.rs":"701f02b3e7dbb91ea6257cc08b5aeaed81a32be83f2424ca3887655926b568de","tests/ui-stable/diagnostic-not-implemented-immutable.stderr":"40641032b6145223854f70ebfc31726c0a7a191e5f2517bbb79a58d13d251f86","tests/ui-stable/diagnostic-not-implemented-into-bytes.rs":"aaedc974685ddc133c1f6c547f51f480057db9932700210ea513be55ddb3497f","tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr":"cb41574733d5efa7fdfa3835d8c063876a9212e3e80ed2586730e0f69ac202f0","tests/ui-stable/diagnostic-not-implemented-issue-1296.rs":"b030a925ff39cb2ea9b1777273f0bcfd982d972fa43cb5f2b6fdc1e6da467312","tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr":"99447c8a209d2e9fe4e17fb46a3f69c278636c86c738e59ef302541aab29a1f7","tests/ui-stable/diagnostic-not-implemented-known-layout.rs":"1e9d77125b68169b231d62da4fb1a1a76fb71bf7a1c4275a096a0715873b4fd2","tests/ui-stable/diagnostic-not-implemented-known-layout.stderr":"d6a92e77b18efaa29954c999d6705e3a050be4bb758575294329cb34d5e23f55","tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs":"922b8eab7092dba41ec37b3ebcad7b48eb8d391e54dff3f2869bcf1954c85003","tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr":"9a4eecd6aa31e8ac2a8bcef61775befb94a30074b7d94a04e907b1d77130374f","tests/ui-stable/diagnostic-not-implemented-unaligned.rs":"8af59d04924492eff43708cb504a421d9c5b8e42cae1ea0a80118f911af47e7b","tests/ui-stable/diagnostic-not-implemented-unaligned.stderr":"abf6bacea329be8fb7a4e04db1faa8f3c0da3bb225372f266f4f4e3c5aff75cf","tests/ui-stable/include_value_not_from_bytes.rs":"74f4d54dad245eff591cb46344fd1f25fb27b73de941c04d1ee82b0ad2639807","tests/ui-stable/include_value_not_from_bytes.stderr":"c03f2fd5f1e541b624d310ac99a981fe1d93db55054a4fb824f31a1da62eb3a2","tests/ui-stable/include_value_wrong_size.rs":"5a0561eeb4cb245cf5b68547b43faa2432c56bfe23f7f50677a0b110dab60cdb","tests/ui-stable/include_value_wrong_size.stderr":"d1a76cd36830c8b07bb1204ebc95aeadf0a1a54ff7cc924635c0dbd3efa0b3a4","tests/ui-stable/invalid-impls/invalid-impls.rs":"8f1cf816cc77f5dd6d19bba4a463ec46a4281523c7551ab8ebcdb46197fc7732","tests/ui-stable/invalid-impls/invalid-impls.stderr":"ec0340b85be7ad6c5c0b6d711a659806a7e3191b6bcbdacf8d26245f47dd439a","tests/ui-stable/max-align.rs":"ffcb6687c98e5629d01b17cbd0845ec195007cc39aa244b26a77d17688c8f13d","tests/ui-stable/max-align.stderr":"a8bd50e80cd0ae680a52ea71d06d259a43300dcfbf6b336a12cb371fe84e119b","tests/ui-stable/ptr-is-invariant-over-v.rs":"4c691e3644e233fabb501b260b3d6d070df7cba60b8c227615aad51cf9a148e6","tests/ui-stable/ptr-is-invariant-over-v.stderr":"54e6c4b0099a85be81e33dda62485e226f488c17ccbc6c8b10ab37bf1227e456","tests/ui-stable/transmute-dst-not-frombytes.rs":"2d045c51d4ea1a435ca3f4e435412eeb0ac6511597dccab8e0040d4903f2b7df","tests/ui-stable/transmute-dst-not-frombytes.stderr":"3483a7f22d41c6be4247f6698e3a1999171cd81ed94c0bb200fadf0873bcb3dd","tests/ui-stable/transmute-mut-const.rs":"5689e8cbc11728f948d0263009a2219e272734e317bd20abd00bd4ddcefba713","tests/ui-stable/transmute-mut-const.stderr":"c05b601177992521b71aa80a97022457641c59b57cc91ff0a0c2b1bc499df2b3","tests/ui-stable/transmute-mut-dst-not-a-reference.rs":"5d784ab588f081bfc304501f811a85ea2662f88fff8274ccbd53172ec255212c","tests/ui-stable/transmute-mut-dst-not-a-reference.stderr":"7a6e78f3cc02001e52e24d961b6de19957b681a2834ea4f62e877e7167a5910a","tests/ui-stable/transmute-mut-dst-not-frombytes.rs":"2b95c8d73c6a321137b5a59c12f554e7433b10f0e95e3ac657330bce0bab149c","tests/ui-stable/transmute-mut-dst-not-frombytes.stderr":"966a02969f6a2ddf51cc4e83a36bc66174f35d2175d5e721e9f4b38ab87ceeeb","tests/ui-stable/transmute-mut-dst-not-intobytes.rs":"2e4da8d35584a2bbeaea33398bb5773a2d40aeee2e2ea7272e9382940cb97ec3","tests/ui-stable/transmute-mut-dst-not-intobytes.stderr":"fe160d78b398eab07a20ee31e480049cb1a60188217507b65e83ffadba3e9f66","tests/ui-stable/transmute-mut-dst-unsized.rs":"58c3423c07dd06ca98e61439f318ba5f3f7fc68ca9cb59371ebc482ad54709db","tests/ui-stable/transmute-mut-dst-unsized.stderr":"ac307733451954b13496b6983ea759d253b70f76143dda083c1eaf922d24587f","tests/ui-stable/transmute-mut-illegal-lifetime.rs":"ec18bf7b3d9bd2674b43d0e04fc0545227473d43b07e2bbccc19c2068df33673","tests/ui-stable/transmute-mut-illegal-lifetime.stderr":"3a43e0be32ef3589fe3fa713d387bd3976bd8c75813f9641bbf7c539e10bed41","tests/ui-stable/transmute-mut-src-dst-not-references.rs":"0b73d42fbcecba3483e24d4e9296d24d551de18822b45120e225356c5ccefad8","tests/ui-stable/transmute-mut-src-dst-not-references.stderr":"830581700736527e224bd923da3cd9c215e68556d2379c678174c08eff1501d6","tests/ui-stable/transmute-mut-src-dst-unsized.stderr":"e53116bd827f30dff68f24c4b6a86dc634aa3b2804ce00c037ee95b4b5dcb0b9","tests/ui-stable/transmute-mut-src-immutable.rs":"606aba0c01726255c9be7e67a032ce854209c62dffec16d5dd2c8f484e19979a","tests/ui-stable/transmute-mut-src-immutable.stderr":"7c24d82d943695955b3ec1f0a53a349645fd3de1d549f3be989532e3774279bf","tests/ui-stable/transmute-mut-src-not-a-reference.rs":"e627a60c6f6d1b398bdcfc9307dbc57b268cc784b4967d1afaceed7eebd5db47","tests/ui-stable/transmute-mut-src-not-a-reference.stderr":"29b09aea59cfdb4b6535c5d33ec803539f28e53cce81938767ea0c22a1b1ce7d","tests/ui-stable/transmute-mut-src-not-frombytes.rs":"647cb1a8fa51b4e833fd3f498a471a344318affc0d2ca8080a7f17dc8a27b30a","tests/ui-stable/transmute-mut-src-not-frombytes.stderr":"cd3f9d8d939033fa0214b35182d4591769c5d02ba17292856764531c175f4bd6","tests/ui-stable/transmute-mut-src-not-intobytes.rs":"40ed14c627923d668173d9d5b3ee5cb0462a126ad4f209224205abc4a3f33b45","tests/ui-stable/transmute-mut-src-not-intobytes.stderr":"b12556019f6a69284899756e3c3c65098fe9fbbad261f851ac90f96d87a524f7","tests/ui-stable/transmute-mut-src-unsized.rs":"8ed4d688fc7f465c3dbd475f6628c265cecd4e57b31a3d5a929f02f3dca7a474","tests/ui-stable/transmute-mut-src-unsized.stderr":"26cd4d952dfd909c87567459d22d349934c85a3e061aba56bed2f0951720eecd","tests/ui-stable/transmute-ptr-to-usize.rs":"ea33dc39115509988d9abd6ac6536d88d82082417b21da9f9bc8cf8369c69618","tests/ui-stable/transmute-ptr-to-usize.stderr":"9b69640228c8558a70a0512a7508f3cd3cd0d0183614e4162cbeee829aca7764","tests/ui-stable/transmute-ref-dst-mutable.rs":"1c48caae9912f70dec5f5a99a0c880fe6a3022f11fd412438b8a1576803e5f73","tests/ui-stable/transmute-ref-dst-mutable.stderr":"fc83b5283cb5319fd7a2b79f94ed0a49f16bce5b222f7e1cc5ce5a879f3de650","tests/ui-stable/transmute-ref-dst-not-a-reference.rs":"c4b8a6c1970e30390d0a301e2dbe718b9eeef743299f7e91cd12c582ec203af7","tests/ui-stable/transmute-ref-dst-not-a-reference.stderr":"e8a126f4832344b8a69591fcc25e22bbbb29f2078b809a47f8afa40ac1087a1f","tests/ui-stable/transmute-ref-dst-not-frombytes.rs":"88f5a210bea3e3a775f92b6aaf4586e62cb9c6f61bcdc1cd7e63ad9ad214b863","tests/ui-stable/transmute-ref-dst-not-frombytes.stderr":"eb8fced405758edb7c29b7c9c73bf07698e839fb71fd07c84aa343c173e54c40","tests/ui-stable/transmute-ref-dst-not-nocell.rs":"71ed55ef424c8173bb438c6a1985a1a53e09d7964950d64a50ddb914c3425760","tests/ui-stable/transmute-ref-dst-not-nocell.stderr":"e939607d2028a038930dcca2f194c3f9072ceebc912eab3f3ead6a53e86ee037","tests/ui-stable/transmute-ref-dst-unsized.rs":"c374df8d00541fd34fff37e231e341501a427961f60d88ad3e3c375085cc060d","tests/ui-stable/transmute-ref-dst-unsized.stderr":"4e84bbb4c4a8b47ca63c710cb28bfe87e4ff175845ca30f049880dc6d9647486","tests/ui-stable/transmute-ref-illegal-lifetime.rs":"6812bbf7ec851a8591464f10864dbd1f225e65ed5793b6f6375cbe8a9db50b14","tests/ui-stable/transmute-ref-illegal-lifetime.stderr":"45ab741d710dc5a01a21ab64f99927e7da5593328b2037b9bc82a87bc0969136","tests/ui-stable/transmute-ref-src-dst-not-references.rs":"7311602a0153b260d819e9608e8e66ef5904919a2349a95187919d8211e48e23","tests/ui-stable/transmute-ref-src-dst-not-references.stderr":"2bff9f290ec40458939a1633f850853b3486220cfd40bc24c4e52635b7455742","tests/ui-stable/transmute-ref-src-dst-unsized.stderr":"ecbfb5e0a5c06fce54b4fe6a50682c9bc6b7807cca137aaa73b8ea5f663c49ab","tests/ui-stable/transmute-ref-src-not-a-reference.rs":"a921f168fa6cb3c6a19894cecdb118bc3164275746672a916aa5194b92f2fb57","tests/ui-stable/transmute-ref-src-not-a-reference.stderr":"52efb101d85126138395fbed84c7cb911f86ea4457b991d91b2b6ec66521bcff","tests/ui-stable/transmute-ref-src-not-intobytes.rs":"81c6fa9775976ab678585a19a174470225e05f0b0cb43ceb754c198a8f0c9732","tests/ui-stable/transmute-ref-src-not-intobytes.stderr":"567de31ddc6aed234cd5bd11204847de4478016dcbd223ae182d4579efde98c3","tests/ui-stable/transmute-ref-src-not-nocell.rs":"0f1cf580d97ed69667b02bfe5de1425ceb0678fc43bf2130e65adc38f3dc5f3f","tests/ui-stable/transmute-ref-src-not-nocell.stderr":"32c77219dccbca2de8527a27dec52ba98667fdaeb500afdd380db4ad595cf28f","tests/ui-stable/transmute-ref-src-unsized.rs":"d7797488f0ab5db89944ac7db25625c63aef72e6e4ed481d00a083449050b813","tests/ui-stable/transmute-ref-src-unsized.stderr":"94e78082b1f598945fccb75119939e4279d4d156f4928c4ff1d0d43ad4d46a1d","tests/ui-stable/transmute-size-decrease.rs":"d191596652adbc26329449af4b2183bdae0a387ee668690b1de8535b71495eb7","tests/ui-stable/transmute-size-decrease.stderr":"617695b7858c0ef01c2a9f7fefc8f7aeb1d6e438f6e36b13a1901d84118e7e01","tests/ui-stable/transmute-size-increase-allow-shrink.rs":"d24d67d0012bf85d06b7e5ca790ca725d5fd559052d35322a72490897963cb42","tests/ui-stable/transmute-size-increase-allow-shrink.stderr":"ef5f1f95974b6ee25773d0d5e95e202d7c9ada56fba2b1ece29326ee3bb6e899","tests/ui-stable/transmute-size-increase.rs":"8ca917f831b736bfadb6ccee22acde205098678a3a2cb3cc753dfecacafcb0be","tests/ui-stable/transmute-size-increase.stderr":"2c5593d90e962ae7ed4ba91f5dbfa50f31f8fe58ff9f7eb0af69b7a4757d8fbf","tests/ui-stable/transmute-src-not-intobytes.rs":"e88bbf21c2512b9c04f938ead3990161f9b050aa469d9164244966ba6e2f02dd","tests/ui-stable/transmute-src-not-intobytes.stderr":"2adbf1b31d95d5a65b20d636164482066e7969376e7b3eea6b08010c7b34427c","tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs":"534191c737297f8d60d1227a9cbbb9700bb08db15783d9191df3a64c8424e303","tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr":"15bdd10761070140c4a729ad24ffa0749d0a554515ef499dba0717db5a862070","tests/ui-stable/try_transmute-size-decrease.rs":"b0b9722d8032c1af00202c7bd99ac65e92ffb3dae67e17a6c10724ba86a3b1f0","tests/ui-stable/try_transmute-size-decrease.stderr":"e072f6306d1382230f8737b93e40e6be6ec98df7fa3ee07028ec0684328058ab","tests/ui-stable/try_transmute-size-increase.rs":"d67d46178f8a945ab2ac5f40b71949468c337b799fec8fd24c241b94d8a6c87b","tests/ui-stable/try_transmute-size-increase.stderr":"3be5aeb6aa65e18003b1fec52ed6fb016ed6b64dc61135437230e65afbbb28cf","tests/ui-stable/try_transmute-src-not-intobytes.rs":"fe267df8308820b9d6f6f3c2ba9f139d1f06c9355dcda85a72af312cf1485eb8","tests/ui-stable/try_transmute-src-not-intobytes.stderr":"74106b79b00d7e2464ae0da4a2bd6731f9f4047cfac42f50d1edd3b299fa1b85","tests/ui-stable/try_transmute_mut-alignment-increase.rs":"7515fa447232f1a59b9b6fae435bbf19095ab4538ae0459c9f38678ae0b67ebb","tests/ui-stable/try_transmute_mut-alignment-increase.stderr":"e02554663c47493331b96520a06f26931701fa523928bddab658ac09b9a342d1","tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs":"d5150c8c6dac0d727f91763964a211da00c9842d3130c4c600b4ff6475ef6b83","tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr":"f89d3ad14122abf12ccd14839b46946a47a256a16b3f427e834268fb6aae21c6","tests/ui-stable/try_transmute_mut-size-decrease.rs":"d18f22001da76c8781c8f276657ea73a0de92144e8a2f9c07cdcc2e2fd0df9d5","tests/ui-stable/try_transmute_mut-size-decrease.stderr":"6fb3cab7b22d9c7a5e142ac191c0a4ed16588126d1d505a2dc7f35897d2c7c71","tests/ui-stable/try_transmute_mut-size-increase.rs":"29dbecad8f2e42a844e1a0a0e656be1724029362a8b8349b1a9cb6415fd7af6b","tests/ui-stable/try_transmute_mut-size-increase.stderr":"d663f2900d092c1f51ff6c2794c420d01b673f08d878f0021dce3b6e8c65bf12","tests/ui-stable/try_transmute_mut-src-not-frombytes.rs":"5146bff98d4fa7ad8edeb1f5a4e4d869b6296ca3ad6c239066ba7ae0584f3c1a","tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr":"60cbdeb32d2dba97972bdef580b776b613963fb9ee26818a2277c4aec1533b00","tests/ui-stable/try_transmute_mut-src-not-intobytes.rs":"cee71e9cf881cf442861326320d58d30b95b9ed051dcd20c5bf1867869c1f792","tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr":"799b21a2986e9aef14a257e27fe9c00b090192cafaeae7a557e5f7fa035d1887","tests/ui-stable/try_transmute_ref-alignment-increase.rs":"11ae7f214f83b50e9fb7e556ea3d64d07baa274ef18143e0ff4fd76b1095fd64","tests/ui-stable/try_transmute_ref-alignment-increase.stderr":"d1deea8a3d804eaa3e3b30423d1caecb35a5aca034f4665f1222e7e8515f5f42","tests/ui-stable/try_transmute_ref-dst-mutable.rs":"1ed1c2bf9f6588cc8b2eb57afac161052ac8124e7065606b2aaab51db2aa3457","tests/ui-stable/try_transmute_ref-dst-mutable.stderr":"b639bae41e7bb7ece5c5eb1468d72c3144dec40982f209da5499025c96bae0bd","tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs":"8a52c04394cc7f3d89b6b93e3906aef833931f730ba5beaed83cb4072334aa01","tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr":"b6b54d2b8b6011e08d955f63395b423d1ede5fea840e7d062da89a3e665d3d79","tests/ui-stable/try_transmute_ref-size-decrease.rs":"81fabb98426fec9f0809e9706461d10b0fa67fe4bece21d2fe5547be4f7bb9ce","tests/ui-stable/try_transmute_ref-size-decrease.stderr":"d6f18947532766c75af5dfe9dc294f652f0ee4a9d41e07429af647690eca5f65","tests/ui-stable/try_transmute_ref-size-increase.rs":"3ba36df7628324b50cfebec229f721b865de15d368b8fd3da2fa197d111fb31b","tests/ui-stable/try_transmute_ref-size-increase.stderr":"fab69d46601049112baca89e6e957c45defb9864d30f7e9c6d517c4c78887168","tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs":"cb455e796e85ac9af743f9b3a1ece8c5e8ee9e4a18128e84685d3c124c595ebe","tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr":"110fd6c127e17ead1ac137bd399c54252158b58670dd2b557e5c08da39b32e9d","win-cargo.bat":"dbde5af501630f6d14a0681d27f30ef2ffaeb1753d14be2f7cb1a7f285458c07"},"package":"0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "53013612da51c61ec3f1a059fc3b89c080ca4b56" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ + + +# Changelog + +## Releases + +We track releases and release notes using [GitHub +Releases](https://github.com/google/zerocopy/releases). + +## Yanks and Regressions + +### 0.2.2 through 0.2.8, 0.3.0 through 0.3.1, 0.4.0, 0.5.0, 0.6.0 through 0.6.5, 0.7.0 through 0.7.30 + +*Security advisories for this bug have been published as +[RUSTSEC-2023-0074][rustsec-advisory] and [GHSA-3mv5-343c-w2qg][github-advisory].* + +In these versions, the `Ref` methods `into_ref`, `into_mut`, `into_slice`, and +`into_mut_slice` were permitted in combination with the standard library +`cell::Ref` and `cell::RefMut` types for `Ref`'s `B` type parameter. These +combinations are unsound, and may permit safe code to exhibit undefined +behavior. Fixes have been published to each affected minor version which do not +permit this code to compile. + +See [#716][issue-716] for more details. + +[rustsec-advisory]: https://rustsec.org/advisories/RUSTSEC-2023-0074.html +[github-advisory]: https://github.com/google/zerocopy/security/advisories/GHSA-3mv5-343c-w2qg +[issue-716]: https://github.com/google/zerocopy/issues/716 + +### 0.7.27, 0.7.28 + +These versions were briefly yanked due to a non-soundness regression reported in +[#672][pull-672]. After reconsidering our yanking policy in [#679][issue-679], +we un-yanked these versions. + +[pull-672]: https://github.com/google/zerocopy/pull/672 +[issue-679]: https://github.com/google/zerocopy/issues/679 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/CONTRIBUTING.md clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CONTRIBUTING.md --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/CONTRIBUTING.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ + + +# How to Contribute + +See our [Contributing Guide](https://github.com/google/zerocopy/discussions/1318). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,296 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elain" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba39bdf557eef05f2c1c2e986cbab6b85329b922e7606e5b63ee4c5037ba77a" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "trybuild" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f" +dependencies = [ + "basic-toml", + "dissimilar", + "glob", + "once_cell", + "serde", + "serde_derive", + "serde_json", + "termcolor", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.27" +dependencies = [ + "either", + "elain", + "glob", + "itertools", + "rand", + "rustversion", + "static_assertions", + "trybuild", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,127 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56.0" +name = "zerocopy" +version = "0.8.27" +authors = [ + "Joshua Liebow-Feeser ", + "Jack Wrenn ", +] +build = "build.rs" +exclude = [".*"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """Zerocopy makes zero-cost memory manipulation effortless. We write "unsafe" so you don't have to.""" +readme = "README.md" +keywords = [ + "cast", + "convert", + "transmute", + "transmutation", + "type-punning", +] +categories = [ + "embedded", + "encoding", + "no-std::no-alloc", + "parsing", + "rust-patterns", +] +license = "BSD-2-Clause OR Apache-2.0 OR MIT" +repository = "https://github.com/google/zerocopy" + +[package.metadata.build-rs] +zerocopy-core-error-1-81-0 = "1.81.0" +zerocopy-diagnostic-on-unimplemented-1-78-0 = "1.78.0" +zerocopy-generic-bounds-in-const-fn-1-61-0 = "1.61.0" +zerocopy-target-has-atomics-1-60-0 = "1.60.0" +zerocopy-aarch64-simd-1-59-0 = "1.59.0" +zerocopy-panic-in-const-and-vec-try-reserve-1-57-0 = "1.57.0" + +[package.metadata.ci] +pinned-stable = "1.89.0" +pinned-nightly = "nightly-2025-09-05" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "doc_cfg", + "--generate-link-to-definition", +] + +[package.metadata.playground] +features = ["__internal_use_only_features_that_work_on_stable"] + +[features] +__internal_use_only_features_that_work_on_stable = [ + "alloc", + "derive", + "simd", + "std", +] +alloc = [] +derive = ["zerocopy-derive"] +float-nightly = [] +simd = [] +simd-nightly = ["simd"] +std = ["alloc"] + +[lib] +name = "zerocopy" +path = "src/lib.rs" + +[[test]] +name = "trybuild" +path = "tests/trybuild.rs" + +[dependencies.zerocopy-derive] +version = "=0.8.27" +optional = true + +[dev-dependencies.either] +version = "=1.13.0" + +[dev-dependencies.elain] +version = "0.3.0" + +[dev-dependencies.glob] +version = "=0.3.2" + +[dev-dependencies.itertools] +version = "0.11" + +[dev-dependencies.rand] +version = "0.8.5" +features = ["small_rng"] +default-features = false + +[dev-dependencies.rustversion] +version = "1.0" + +[dev-dependencies.static_assertions] +version = "1.1" + +[dev-dependencies.trybuild] +version = "=1.0.89" +features = ["diff"] + +[dev-dependencies.zerocopy-derive] +version = "=0.8.27" + +[target."cfg(any())".dependencies.zerocopy-derive] +version = "=0.8.27" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,111 @@ +# Copyright 2018 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +# Put both crates in a single workspace so that `trybuild` compiler errors have +# paths that are stable regardless of the path to the repository root. This +# avoids issues like: +# https://github.com/dtolnay/trybuild/issues/207#issuecomment-131227.594 +[workspace] + +[package] +edition = "2021" +name = "zerocopy" +version = "0.8.27" +authors = ["Joshua Liebow-Feeser ", "Jack Wrenn "] +description = "Zerocopy makes zero-cost memory manipulation effortless. We write \"unsafe\" so you don't have to." +categories = ["embedded", "encoding", "no-std::no-alloc", "parsing", "rust-patterns"] +keywords = ["cast", "convert", "transmute", "transmutation", "type-punning"] +license = "BSD-2-Clause OR Apache-2.0 OR MIT" +repository = "https://github.com/google/zerocopy" +rust-version = "1.56.0" + +exclude = [".*"] + +[package.metadata.build-rs] +# These key/value pairs are parsed by `build.rs`. Each entry names a `--cfg` +# which will be emitted if zerocopy is built with a toolchain version at least +# as high as the specified version. In the emitted `--cfg`, dashes are replaced +# by underscores. +# +# Each name is suffixed with the version it corresponds to. This is a convention +# used in the codebase to make it less likely for us to make mistakes when +# writing `doc_cfg` attributes. + +# From 1.81.0, Rust supports the `core::error::Error` trait. +zerocopy-core-error-1-81-0 = "1.81.0" + +# From 1.78.0, Rust supports the `#[diagnostic::on_unimplemented]` attribute. +zerocopy-diagnostic-on-unimplemented-1-78-0 = "1.78.0" + +# From 1.61.0, Rust supports generic types with trait bounds in `const fn`. +zerocopy-generic-bounds-in-const-fn-1-61-0 = "1.61.0" + +# From 1.60.0, Rust supports `cfg(target_has_atomics)`, which allows us to +# detect whether a target supports particular sets of atomics. +zerocopy-target-has-atomics-1-60-0 = "1.60.0" + +# When the "simd" feature is enabled, include SIMD types from the +# `core::arch::aarch64` module, which was stabilized in 1.59.0. On earlier Rust +# versions, these types require the "simd-nightly" feature. +zerocopy-aarch64-simd-1-59-0 = "1.59.0" + +# Permit panicking in `const fn`s and calling `Vec::try_reserve`. +zerocopy-panic-in-const-and-vec-try-reserve-1-57-0 = "1.57.0" + +[package.metadata.ci] +# The versions of the stable and nightly compiler toolchains to use in CI. +pinned-stable = "1.89.0" +pinned-nightly = "nightly-2025-09-05" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] + +[package.metadata.playground] +features = ["__internal_use_only_features_that_work_on_stable"] + +[features] +alloc = [] +derive = ["zerocopy-derive"] +simd = [] +simd-nightly = ["simd"] +float-nightly = [] +std = ["alloc"] +# This feature depends on all other features that work on the stable compiler. +# We make no stability guarantees about this feature; it may be modified or +# removed at any time. +__internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd", "std"] + +[dependencies] +zerocopy-derive = { version = "=0.8.27", path = "zerocopy-derive", optional = true } + +# The "associated proc macro pattern" ensures that the versions of zerocopy and +# zerocopy-derive remain equal, even if the 'derive' feature isn't used. +# See: https://github.com/matklad/macro-dep-test +[target.'cfg(any())'.dependencies] +zerocopy-derive = { version = "=0.8.27", path = "zerocopy-derive" } + +[dev-dependencies] +# More recent versions of `either` have an MSRV higher than ours. +either = "=1.13.0" +# FIXME(#381) Remove this dependency once we have our own layout gadgets. +elain = "0.3.0" +# More recent versions of `glob` have an MSRV higher than ours. +glob = "=0.3.2" +itertools = "0.11" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +rustversion = "1.0" +static_assertions = "1.1" +testutil = { path = "testutil" } +# Pinned to a specific version so that the version used for local development +# and the version used in CI are guaranteed to be the same. Future versions +# sometimes change the output format slightly, so a version mismatch can cause +# CI test failures. +trybuild = { version = "=1.0.89", features = ["diff"] } +# In tests, unlike in production, zerocopy-derive is not optional +zerocopy-derive = { version = "=0.8.27", path = "zerocopy-derive" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Fuchsia 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 + + http://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. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-BSD clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-BSD --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-BSD 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-BSD 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +Copyright 2019 The Fuchsia Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright 2023 The Fuchsia Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/POLICIES.md clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/POLICIES.md --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/POLICIES.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/POLICIES.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,119 @@ + + +# Zerocopy's Policies + +## Soundness + +Zerocopy is expressly designed for use in security-critical contexts. It is used +in hardware security firmware, cryptographic implementations, hypervisors, and +more. We understand that software in these contexts has a very high bar for +correctness, and we take our responsibility to meet that bar very seriously. + +This section describes policies which are designed to ensure the correctness and +soundness of our code and prevent regressions. + +### Forwards-compatibility + +Rust does not currently have a formal memory model. As such, while Rust provides +guarantees about the semantics of some operations, the semantics of many +operations is up in the air and subject to change. + +Zerocopy strives to ensure that our code - and code emitted by our custom +derives - is sound under any version of Rust as early as our MSRV, and will +continue to be sound under any future version of Rust. The policies in this +section are designed to help ensure that we live up to this goal. + +### Safety comments + +Each non-test `unsafe` block must be annotated with a "safety comment" which +provides a rationale for its soundness. In order to ensure that our soundness is +forwards-compatible, safety comments must satisfy the following criteria: +- Safety comments must constitute a (possibly informal) proof that all of Rust's + soundness rules are upheld. +- Safety comments must only rely for their correctness on statements which + appear in the stable versions of the [Rust Reference] or standard library + documentation (ie, the docs for [core], [alloc], and [std]); arguments which + rely on text from the beta or nightly versions of these documents are not + considered complete. +- All statements from the Reference or standard library documentation which are + relied upon for soundness must be quoted in the safety comment. This ensures + that there is no ambiguity as to what aspect of the text is being cited. This + is especially important in cases where the text of these documents changes in + the future. Such changes are of course required to be backwards-compatible, + but may change the manner in which a particular guarantee is explained. + +We use the [`clippy::undocumented_unsafe_blocks`] lint to ensure that `unsafe` +blocks cannot be added without a safety comment. Note that there are a few +outstanding uncommented `unsafe` blocks which are tracked in [#429]. Our goal is +to reach 100% safety comment coverage and not regress once we've reached it. + +[Rust Reference]: https://doc.rust-lang.org/reference/ +[core]: https://doc.rust-lang.org/stable/core/ +[alloc]: https://doc.rust-lang.org/stable/alloc/ +[std]: https://doc.rust-lang.org/stable/std/ +[`clippy::undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#/undocumented_unsafe_blocks +[#429]: https://github.com/google/zerocopy/issues/429 + +#### Exceptions to our safety comment policy + +In rare circumstances, the soundness of an `unsafe` block may depend upon +semantics which are widely agreed upon but not formally guaranteed. In order to +avoid slowing down zerocopy's development to an unreasonable degree, a safety +comment may violate our safety comment policy so long as all of the following +hold: +- The safety comment's correctness may rely on semantics which are not + guaranteed in official Rust documentation *so long as* a member of the Rust + team has articulated in an official communication (e.g. a comment on a Rust + GitHub repo) that Rust intends to guarantee particular semantics. +- There exists an active effort to formalize the guarantee in Rust's official + documentation. + +### Target architecture support + +Zerocopy bases its soundness on guarantees made about the semantics of Rust +which appear in the Rust Reference or standard library documentation; zerocopy +is sound so long as these guarantees hold. There are known cases in which these +guarantees do not hold on certain target architectures (see +[rust-lang/unsafe-code-guidelines#461]); on such target architectures, zerocopy +may be unsound. We consider it outside of zerocopy's scope to reason about these +cases. Zerocopy makes no effort maintain soundness in cases where Rust's +documented guarantees do not hold. + +[rust-lang/unsafe-code-guidelines#461]: https://github.com/rust-lang/unsafe-code-guidelines/issues/461 + +## MSRV + + + +Without the `derive` feature enabled, zerocopy's minimum supported Rust version +(MSRV) is encoded the `package.rust-version` field in its `Cargo.toml` file. For +zerocopy, we consider an increase in MSRV to be a semver-breaking change, and +will only increase our MSRV during semver-breaking version changes (e.g., 0.1 -> +0.2, 1.0 -> 2.0, etc). + +For zerocopy with the `derive` feature enabled, and for the zerocopy-derive +crate, we inherit the maximum MSRV any of our dependencies. As of this writing +(2024-10-03), at least one dependency (syn) does *not* consider MSRV increases +to be semver-breaking changes. Thus, using the `derive` feature may result in +the effective MSRV increasing within a semver version train. + +## Yanking + +Whenever a bug or regression is identified, we will yank any affected versions +which are part of the current version train. For example, if the most recent +version is 0.10.20 and a bug is uncovered, we will release a fix in 0.10.21 and +yank all 0.10.X versions which are affected. We *may* also yank versions in +previous version trains on a case-by-case basis, but we don't guarantee it. + +For information about a particular yanked or un-yanked version, see our [yank +log][yank-log]. + +[yank-log]: https://github.com/google/zerocopy/blob/main/CHANGELOG.md#yanks-and-regressions diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/README.md clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,213 @@ + + +# zerocopy + +***Fast, safe, compile error. Pick two.*** + +Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe` +so you don't have to. + +*For an overview of what's changed from zerocopy 0.7, check out our [release +notes][release-notes], which include a step-by-step upgrading guide.* + +*Have questions? Need more out of zerocopy? Submit a [customer request +issue][customer-request-issue] or ask the maintainers on +[GitHub][github-q-a] or [Discord][discord]!* + +[customer-request-issue]: https://github.com/google/zerocopy/issues/new/choose +[release-notes]: https://github.com/google/zerocopy/discussions/1680 +[github-q-a]: https://github.com/google/zerocopy/discussions/categories/q-a +[discord]: https://discord.gg/MAvWH2R6zk + +## Overview + +###### Conversion Traits + +Zerocopy provides four derivable traits for zero-cost conversions: +- `TryFromBytes` indicates that a type may safely be converted from + certain byte sequences (conditional on runtime checks) +- `FromZeros` indicates that a sequence of zero bytes represents a valid + instance of a type +- `FromBytes` indicates that a type may safely be converted from an + arbitrary byte sequence +- `IntoBytes` indicates that a type may safely be converted *to* a byte + sequence + +These traits support sized types, slices, and [slice DSTs][slice-dsts]. + +[slice-dsts]: KnownLayout#dynamically-sized-types + +###### Marker Traits + +Zerocopy provides three derivable marker traits that do not provide any +functionality themselves, but are required to call certain methods provided +by the conversion traits: +- `KnownLayout` indicates that zerocopy can reason about certain layout + qualities of a type +- `Immutable` indicates that a type is free from interior mutability, + except by ownership or an exclusive (`&mut`) borrow +- `Unaligned` indicates that a type's alignment requirement is 1 + +You should generally derive these marker traits whenever possible. + +###### Conversion Macros + +Zerocopy provides six macros for safe casting between types: + +- (`try_`[try_transmute])`transmute` (conditionally) converts a value of + one type to a value of another type of the same size +- (`try_`[try_transmute_mut])`transmute_mut` (conditionally) converts a + mutable reference of one type to a mutable reference of another type of + the same size +- (`try_`[try_transmute_ref])`transmute_ref` (conditionally) converts a + mutable or immutable reference of one type to an immutable reference of + another type of the same size + +These macros perform *compile-time* size and alignment checks, meaning that +unconditional casts have zero cost at runtime. Conditional casts do not need +to validate size or alignment runtime, but do need to validate contents. + +These macros cannot be used in generic contexts. For generic conversions, +use the methods defined by the [conversion traits](#conversion-traits). + +###### Byteorder-Aware Numerics + +Zerocopy provides byte-order aware integer types that support these +conversions; see the `byteorder` module. These types are especially useful +for network parsing. + +## Cargo Features + +- **`alloc`** + By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled, + the `alloc` crate is added as a dependency, and some allocation-related + functionality is added. + +- **`std`** + By default, `zerocopy` is `no_std`. When the `std` feature is enabled, the + `std` crate is added as a dependency (ie, `no_std` is disabled), and + support for some `std` types is added. `std` implies `alloc`. + +- **`derive`** + Provides derives for the core marker traits via the `zerocopy-derive` + crate. These derives are re-exported from `zerocopy`, so it is not + necessary to depend on `zerocopy-derive` directly. + + However, you may experience better compile times if you instead directly + depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`, + since doing so will allow Rust to compile these crates in parallel. To do + so, do *not* enable the `derive` feature, and list both dependencies in + your `Cargo.toml` with the same leading non-zero version number; e.g: + + ```toml + [dependencies] + zerocopy = "0.X" + zerocopy-derive = "0.X" + ``` + + To avoid the risk of [duplicate import errors][duplicate-import-errors] if + one of your dependencies enables zerocopy's `derive` feature, import + derives as `use zerocopy_derive::*` rather than by name (e.g., `use + zerocopy_derive::FromBytes`). + +- **`simd`** + When the `simd` feature is enabled, `FromZeros`, `FromBytes`, and + `IntoBytes` impls are emitted for all stable SIMD types which exist on the + target platform. Note that the layout of SIMD types is not yet stabilized, + so these impls may be removed in the future if layout changes make them + invalid. For more information, see the Unsafe Code Guidelines Reference + page on the [layout of packed SIMD vectors][simd-layout]. + +- **`simd-nightly`** + Enables the `simd` feature and adds support for SIMD types which are only + available on nightly. Since these types are unstable, support for any type + may be removed at any point in the future. + +- **`float-nightly`** + Adds support for the unstable `f16` and `f128` types. These types are + not yet fully implemented and may not be supported on all platforms. + +[duplicate-import-errors]: https://github.com/google/zerocopy/issues/1587 +[simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html + +## Security Ethos + +Zerocopy is expressly designed for use in security-critical contexts. We +strive to ensure that that zerocopy code is sound under Rust's current +memory model, and *any future memory model*. We ensure this by: +- **...not 'guessing' about Rust's semantics.** + We annotate `unsafe` code with a precise rationale for its soundness that + cites a relevant section of Rust's official documentation. When Rust's + documented semantics are unclear, we work with the Rust Operational + Semantics Team to clarify Rust's documentation. +- **...rigorously testing our implementation.** + We run tests using [Miri], ensuring that zerocopy is sound across a wide + array of supported target platforms of varying endianness and pointer + width, and across both current and experimental memory models of Rust. +- **...formally proving the correctness of our implementation.** + We apply formal verification tools like [Kani][kani] to prove zerocopy's + correctness. + +For more information, see our full [soundness policy]. + +[Miri]: https://github.com/rust-lang/miri +[Kani]: https://github.com/model-checking/kani +[soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness + +## Relationship to Project Safe Transmute + +[Project Safe Transmute] is an official initiative of the Rust Project to +develop language-level support for safer transmutation. The Project consults +with crates like zerocopy to identify aspects of safer transmutation that +would benefit from compiler support, and has developed an [experimental, +compiler-supported analysis][mcp-transmutability] which determines whether, +for a given type, any value of that type may be soundly transmuted into +another type. Once this functionality is sufficiently mature, zerocopy +intends to replace its internal transmutability analysis (implemented by our +custom derives) with the compiler-supported one. This change will likely be +an implementation detail that is invisible to zerocopy's users. + +Project Safe Transmute will not replace the need for most of zerocopy's +higher-level abstractions. The experimental compiler analysis is a tool for +checking the soundness of `unsafe` code, not a tool to avoid writing +`unsafe` code altogether. For the foreseeable future, crates like zerocopy +will still be required in order to provide higher-level abstractions on top +of the building block provided by Project Safe Transmute. + +[Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html +[mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411 + +## MSRV + +See our [MSRV policy]. + +[MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv + +## Changelog + +Zerocopy uses [GitHub Releases]. + +[GitHub Releases]: https://github.com/google/zerocopy/releases + +## Thanks + +Zerocopy is maintained by engineers at Google and Amazon with help from +[many wonderful contributors][contributors]. Thank you to everyone who has +lent a hand in making Rust a little more secure! + +[contributors]: https://github.com/google/zerocopy/graphs/contributors + +## Disclaimer + +Disclaimer: Zerocopy is not an officially supported Google product. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/build.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,256 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Sometimes we want to use lints which were added after our MSRV. +// `unknown_lints` is `warn` by default and we deny warnings in CI, so without +// this attribute, any unknown lint would cause a CI failure when testing with +// our MSRV. +#![allow(unknown_lints)] +#![deny(renamed_and_removed_lints)] +#![deny( + anonymous_parameters, + deprecated_in_future, + late_bound_lifetime_arguments, + missing_copy_implementations, + missing_debug_implementations, + path_statements, + patterns_in_fns_without_body, + rust_2018_idioms, + trivial_numeric_casts, + unreachable_pub, + unsafe_op_in_unsafe_fn, + unused_extern_crates, + variant_size_differences +)] +#![deny( + clippy::all, + clippy::alloc_instead_of_core, + clippy::arithmetic_side_effects, + clippy::as_underscore, + clippy::assertions_on_result_states, + clippy::as_conversions, + clippy::correctness, + clippy::dbg_macro, + clippy::decimal_literal_representation, + clippy::get_unwrap, + clippy::indexing_slicing, + clippy::missing_inline_in_public_items, + clippy::missing_safety_doc, + clippy::obfuscated_if_else, + clippy::perf, + clippy::print_stdout, + clippy::style, + clippy::suspicious, + clippy::todo, + clippy::undocumented_unsafe_blocks, + clippy::unimplemented, + clippy::unnested_or_patterns, + clippy::unwrap_used, + clippy::use_debug +)] + +use std::{env, fs, process::Command, str}; + +fn main() { + // Avoid unnecessary re-building. + println!("cargo:rerun-if-changed=build.rs"); + // This is necessary because changes to the list of detected Rust toolchain + // versions will affect what `--cfg`s this script emits. Without this, + // changes to that list have no effect on the build without running `cargo + // clean` or similar. + println!("cargo:rerun-if-changed=Cargo.toml"); + + let version_cfgs = parse_version_cfgs_from_cargo_toml(); + let rustc_version = rustc_version(); + + if rustc_version >= (Version { major: 1, minor: 77, patch: 0 }) { + for version_cfg in &version_cfgs { + // This tells the `unexpected_cfgs` lint to expect to see all of + // these `cfg`s. The `cargo::` syntax was only added in 1.77, so we + // don't emit these on earlier toolchain versions. + println!("cargo:rustc-check-cfg=cfg({})", version_cfg.cfg_name); + + // This tells the `unexpected_cfgs` lint to expect to see `cfg`s of + // the form `rust = "1.2.3"`. These aren't real `cfg`s, but we use + // them in `cfg_attr(doc_cfg, doc(cfg(rust = "1.2.3")))` on items + // that are version-gated so that the rendered Rustdoc shows which + // Rust toolchain versions those items are available on. + let Version { major, minor, patch } = version_cfg.version; + println!("cargo:rustc-check-cfg=cfg(rust, values(\"{}.{}.{}\"))", major, minor, patch); + } + // FIXME(https://github.com/rust-lang/rust/issues/124816): Remove these + // once they're no longer needed. + println!("cargo:rustc-check-cfg=cfg(doc_cfg)"); + println!("cargo:rustc-check-cfg=cfg(kani)"); + println!( + "cargo:rustc-check-cfg=cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)" + ); + println!("cargo:rustc-check-cfg=cfg(coverage_nightly)"); + } + + for version_cfg in version_cfgs { + if rustc_version >= version_cfg.version { + println!("cargo:rustc-cfg={}", version_cfg.cfg_name); + } + } +} + +#[derive(Debug, Ord, PartialEq, PartialOrd, Eq)] +struct Version { + major: usize, + minor: usize, + patch: usize, +} + +#[derive(Debug)] +struct VersionCfg { + version: Version, + cfg_name: String, +} + +const ITER_FIRST_NEXT_EXPECT_MSG: &str = "unreachable: a string split cannot produce 0 items"; + +fn parse_version_cfgs_from_cargo_toml() -> Vec { + let cargo_toml = fs::read_to_string("Cargo.toml").expect("failed to read Cargo.toml"); + + // Expect a Cargo.toml with the following format: + // + // ... + // + // [package.metadata.build-rs] + // # Comments... + // zerocopy-panic-in-const-fn = "1.57.0" + // + // ... + // + // [...] + // + // In other words, the following sections, in order: + // - Arbitrary content + // - The literal header `[package.metadata.build-rs]` + // - Any number of: + // - Comments + // - Key/value pairs + // - A TOML table, indicating the end of the section we care about + + const TABLE_HEADER: &str = "[package.metadata.build-rs]"; + + if !cargo_toml.contains(TABLE_HEADER) { + panic!("{}", format!("Cargo.toml does not contain `{}`", TABLE_HEADER)); + } + + // Now that we know there's at least one instance of `TABLE_HEADER`, we + // consume the iterator until we find the text following that first + // instance. This isn't terribly bullet-proof, but we also authored + // `Cargo.toml`, and we'd have to mess up pretty badly to accidentally put + // two copies of the same table header in that file. + let mut iter = cargo_toml.split(TABLE_HEADER); + let _prefix = iter.next().expect(ITER_FIRST_NEXT_EXPECT_MSG); + let rest = iter.next().expect("unreachable: we already confirmed that there's a table header"); + + // Scan until we find the next table section, which should start with a `[` + // character at the beginning of a line. + let mut iter = rest.split("\n["); + let section = iter.next().expect("unreachable: a string split cannot produce 0 items"); + + section + .lines() + .filter_map(|line| { + // Parse lines of one of the following forms: + // + // # Comment + // + // name-of-key = "1.2.3" # Comment + // + // Comments on their own line are ignored, and comments after a + // key/value pair will be stripped before further processing. + + // We don't need to handle the case where the `#` character isn't a + // comment (which can happen if it's inside a string) since we authored + // `Cargo.toml` and, in this section, we only put Rust version numbers + // in strings. + let before_comment = line.split('#').next().expect(ITER_FIRST_NEXT_EXPECT_MSG); + let before_comment_without_whitespace = before_comment.trim_start(); + if before_comment_without_whitespace.is_empty() { + return None; + } + + // At this point, assuming Cargo.toml is correctly formatted according + // to the format expected by this function, we know that + // `before_comment_without_whitespace` is of the form: + // + // name-of-key = "1.2.3" # Comment + // + // ...with no leading whitespace, and where the trailing comment is + // optional. + + let mut iter = before_comment_without_whitespace.split_whitespace(); + let name = iter.next().expect(ITER_FIRST_NEXT_EXPECT_MSG); + const EXPECT_MSG: &str = + "expected lines of the format `name-of-key = \"1.2.3\" # Comment`"; + let equals_sign = iter.next().expect(EXPECT_MSG); + let value = iter.next().expect(EXPECT_MSG); + + assert_eq!(equals_sign, "=", "{}", EXPECT_MSG); + + // Replace dashes with underscores. + let name = name.replace('-', "_"); + + // Strip the quotation marks. + let value = value.trim_start_matches('"').trim_end_matches('"'); + + let mut iter = value.split('.'); + let major = iter.next().expect(ITER_FIRST_NEXT_EXPECT_MSG); + let minor = iter.next().expect(EXPECT_MSG); + let patch = iter.next().expect(EXPECT_MSG); + + assert_eq!(iter.next(), None, "{}", EXPECT_MSG); + + let major: usize = major.parse().expect(EXPECT_MSG); + let minor: usize = minor.parse().expect(EXPECT_MSG); + let patch: usize = patch.parse().expect(EXPECT_MSG); + + Some(VersionCfg { version: Version { major, minor, patch }, cfg_name: name }) + }) + .collect() +} + +fn rustc_version() -> Version { + let rustc_cmd_name = env::var_os("RUSTC").expect("could not get rustc command name"); + let version = + Command::new(rustc_cmd_name).arg("--version").output().expect("could not invoke rustc"); + if !version.status.success() { + panic!( + "rustc failed with status: {}\nrustc output: {}", + version.status, + String::from_utf8_lossy(version.stderr.as_slice()) + ); + } + + const RUSTC_EXPECT_MSG: &str = "could not parse rustc version output"; + let version = str::from_utf8(version.stdout.as_slice()).expect(RUSTC_EXPECT_MSG); + let version = version.trim_start_matches("rustc "); + // The version string is sometimes followed by other information such as the + // string `-nightly` or other build information. We don't care about any of + // that. + let version = version + .split(|c: char| c != '.' && !c.is_ascii_digit()) + .next() + .expect(ITER_FIRST_NEXT_EXPECT_MSG); + let mut iter = version.split('.'); + let major = iter.next().expect(ITER_FIRST_NEXT_EXPECT_MSG); + let minor = iter.next().expect(RUSTC_EXPECT_MSG); + let patch = iter.next().expect(RUSTC_EXPECT_MSG); + + let major: usize = major.parse().expect(RUSTC_EXPECT_MSG); + let minor: usize = minor.parse().expect(RUSTC_EXPECT_MSG); + let patch: usize = patch.parse().expect(RUSTC_EXPECT_MSG); + + Version { major, minor, patch } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/cargo.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/cargo.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/cargo.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/cargo.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail + +# Build `cargo-zerocopy` without any RUSTFLAGS set in the environment +env -u RUSTFLAGS cargo +stable build --manifest-path tools/Cargo.toml -p cargo-zerocopy -q +# Thin wrapper around the `cargo-zerocopy` binary in `tools/cargo-zerocopy` +./tools/target/debug/cargo-zerocopy $@ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_all_toolchains_tested.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_all_toolchains_tested.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_all_toolchains_tested.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_all_toolchains_tested.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail + +# Check whether the set of toolchains tested in this file (other than +# 'msrv', 'stable', and 'nightly') is equal to the set of toolchains +# listed in the 'package.metadata.build-rs' section of Cargo.toml. +# +# If the inputs to `diff` are not identical, `diff` exits with a +# non-zero error code, which causes this script to fail (thanks to +# `set -e`). +diff \ + <(cat .github/workflows/ci.yml | yq '.jobs.build_test.strategy.matrix.toolchain | .[]' | \ + sort -u | grep -v '^\(msrv\|stable\|nightly\)$') \ + <(cargo metadata -q --format-version 1 | \ + jq -r ".packages[] | select(.name == \"zerocopy\").metadata.\"build-rs\" | keys | .[]" | \ + sort -u) >&2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_fmt.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_fmt.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_fmt.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_fmt.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail +files=$(find . -iname '*.rs' -type f -not -path './target/*') +# check that find succeeded +if [[ -z $files ]] +then + exit 1 +fi +./cargo.sh +nightly fmt --check -- $files >&2 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_job_dependencies.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_job_dependencies.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_job_dependencies.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_job_dependencies.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail +which yq > /dev/null +jobs=$(for i in $(find .github -iname '*.yaml' -or -iname '*.yml') + do + # Select jobs that are triggered by pull request. + if yq -e '.on | has("pull_request")' "$i" 2>/dev/null >/dev/null + then + # This gets the list of jobs that all-jobs-succeed does not depend on. + comm -23 \ + <(yq -r '.jobs | keys | .[]' "$i" | sort | uniq) \ + <(yq -r '.jobs.all-jobs-succeed.needs[]' "$i" | sort | uniq) + fi + + # The grep call here excludes all-jobs-succeed from the list of jobs that + # all-jobs-succeed does not depend on. If all-jobs-succeed does + # not depend on itself, we do not care about it. + done | sort | uniq | (grep -v '^all-jobs-succeed$' || true) +) + +if [ -n "$jobs" ] +then + missing_jobs="$(echo "$jobs" | tr ' ' '\n')" + echo "all-jobs-succeed missing dependencies on some jobs: $missing_jobs" | tee -a $GITHUB_STEP_SUMMARY >&2 + exit 1 +fi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_readme.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_readme.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_readme.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_readme.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail + +# Install again in case the installation failed during the +# `generate_cache` step. We treat that step as best-effort and +# suppress all errors from it. +cargo install -q cargo-readme --version 3.2.0 + +diff <(cargo -q run --manifest-path tools/Cargo.toml -p generate-readme) README.md >&2 +exit $? diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_todo.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_todo.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_todo.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_todo.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# +# Copyright 2025 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -euo pipefail + +# This allows us to leave XODO comments in this file and have them still be +# picked up by this script without having the script itself trigger false +# positives. The alternative would be to exclude this script entirely, which +# would mean that we couldn't use XODO comments in this script. +KEYWORD=$(echo XODO | sed -e 's/X/T/') + +# Make sure `rg` is installed (if this fails, `set -e` above will cause the +# script to exit). +rg --version >/dev/null + +# -H: Print filename (default for multiple files/recursive) +# -n: Print line number +# -w: Match whole words +output=$(rg -H -n -w "$KEYWORD" || true) + +if [ -n "$output" ]; then + echo "Found $KEYWORD markers in the codebase." >&2 + echo "$KEYWORD is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase, use FIXME." >&2 + echo "" >&2 + echo "$output" >&2 + exit 1 +fi diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_versions.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_versions.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/check_versions.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/check_versions.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail + +# Usage: version +function version { + cargo metadata -q --format-version 1 | jq -r ".packages[] | select(.name == \"$1\").version" +} + +ver_zerocopy=$(version zerocopy) +ver_zerocopy_derive=$(version zerocopy-derive) + +# Usage: dependency-version +function dependency-version { + KIND="$1" + TARGET="$2" + cargo metadata -q --format-version 1 \ + | jq -r ".packages[] | select(.name == \"zerocopy\").dependencies[] | select((.name == \"zerocopy-derive\") and .kind == $KIND and .target == $TARGET).req" +} + +# The non-dev dependency version (kind `null` filters out the dev +# dependency, and target `null` filters out the targeted version). +zerocopy_derive_dep_ver=$(dependency-version null null) + +# The non-dev dependency, targeted version (kind `null` filters out +# the dev dependency). +zerocopy_derive_targeted_ver=$(dependency-version null '"cfg(any())"') + +# The dev dependency version (kind `"dev"` selects only the dev +# dependency). +zerocopy_derive_dev_dep_ver=$(dependency-version '"dev"' null) + +function assert-match { + VER_A="$1" + VER_B="$2" + SUCCESS_MSG="$3" + FAILURE_MSG="$4" + if [[ "$VER_A" == "$VER_B" ]]; then + echo "$SUCCESS_MSG" | tee -a $GITHUB_STEP_SUMMARY + else + echo "$FAILURE_MSG" | tee -a $GITHUB_STEP_SUMMARY >&2 + exit 1 + fi +} + +assert-match "$ver_zerocopy" "$ver_zerocopy_derive" \ + "Same crate version ($ver_zerocopy) found for zerocopy and zerocopy-derive." \ + "Different crate versions found for zerocopy ($ver_zerocopy) and zerocopy-derive ($ver_zerocopy_derive)." + +# Note the leading `=` sign - the dependency needs to be an exact one. +assert-match "=$ver_zerocopy_derive" "$zerocopy_derive_dep_ver" \ + "zerocopy depends upon same version of zerocopy-derive in-tree ($zerocopy_derive_dep_ver)." \ + "zerocopy depends upon different version of zerocopy-derive ($zerocopy_derive_dep_ver) than the one in-tree ($ver_zerocopy_derive)." + +# Note the leading `=` sign - the dependency needs to be an exact one. +assert-match "=$ver_zerocopy_derive" "$zerocopy_derive_dev_dep_ver" \ + "In dev mode, zerocopy depends upon same version of zerocopy-derive in-tree ($zerocopy_derive_dev_dep_ver)." \ + "In dev mode, zerocopy depends upon different version of zerocopy-derive ($zerocopy_derive_dev_dep_ver) than the one in-tree ($ver_zerocopy_derive)." + +assert-match "$zerocopy_derive_dep_ver" "$zerocopy_derive_targeted_ver" \ + "Same crate version ($zerocopy_derive_dep_ver) found for optional and targeted zerocopy-derive dependency." \ + "Different crate versions found for optional ($zerocopy_derive_dep_ver) and targeted ($zerocopy_derive_targeted_ver) dependency." diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/release_crate_version.sh clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/release_crate_version.sh --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/ci/release_crate_version.sh 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/ci/release_crate_version.sh 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +VERSION="$1" + +sed -i -e "s/^zerocopy-derive = { version = \"=[0-9a-zA-Z\.-]*\"/zerocopy-derive = { version = \"=$VERSION\"/" Cargo.toml +sed -i -e "s/^version = \"[0-9a-zA-Z\.-]*\"/version = \"$VERSION\"/" Cargo.toml zerocopy-derive/Cargo.toml diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/clippy.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/clippy.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +# Copyright 2023 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +accept-comment-above-statement = true +accept-comment-above-attributes = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/githooks/pre-push clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/githooks/pre-push --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/githooks/pre-push 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/githooks/pre-push 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# +# Copyright 2024 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +set -eo pipefail +echo "Running pre-push git hook: $0" +# Forego redirecting stdout to /dev/null on check_fmt.sh because the output from +# `cargo fmt` is useful (and the good stuff is not delivered by stderr). +# +# Background all jobs and wait for them so they can run in parallel. +./ci/check_fmt.sh & FMT_PID=$! +./ci/check_all_toolchains_tested.sh >/dev/null & TOOLCHAINS_PID=$! +./ci/check_job_dependencies.sh >/dev/null & JOB_DEPS_PID=$! +./ci/check_readme.sh >/dev/null & README_PID=$! +./ci/check_todo.sh >/dev/null & XODO_PID=$! +./ci/check_versions.sh >/dev/null & VERSIONS_PID=$! + +# `wait ` exits with the same status code as the job it's waiting for. +# Since we `set -e` above, this will have the effect of causing the entire +# script to exit with a non-zero status code if any of these jobs does the same. +# Note that, while `wait` (with no PID argument) waits for all backgrounded +# jobs, it exits with code 0 even if one of the backgrounded jobs does not, so +# we can't use it here. +wait $FMT_PID +wait $TOOLCHAINS_PID +wait $JOB_DEPS_PID +wait $README_PID +wait $XODO_PID +wait $VERSIONS_PID + +# Ensure that this script calls all scripts in `ci/*`. This isn't a foolproof +# check since it just checks for the string in this script (e.g., it could be in +# a comment, which would trigger a false positive), but it should catch obvious +# errors. Also note that this entire hook is a nice-to-have - failures that +# aren't caught here will still be caught in CI. +# +# This was added because, in #728, we added `ci/check_all_toolchains_tested.sh` +# without calling it from this script. +GLOBIGNORE="./*/release_crate_version.sh" # We don't want to run this one +for f in ./ci/*; do + grep "$f" githooks/pre-push >/dev/null || { echo "$f not called from githooks/pre-push" >&2 ; exit 1; } +done +unset GLOBIGNORE diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +# Copyright 2022 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +edition = "2024" + +# The "Default" setting has a heuristic which splits lines too aggressively. +# We are willing to revisit this setting in future versions of rustfmt. +# Bugs: +# * https://github.com/rust-lang/rustfmt/issues/3119 +# * https://github.com/rust-lang/rustfmt/issues/3120 +use_small_heuristics = "Max" + +# Prevent carriage returns +newline_style = "Unix" + +imports_granularity = "Crate" +group_imports = "StdExternalCrate" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/byte_slice.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byte_slice.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/byte_slice.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byte_slice.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,397 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Traits for types that encapsulate a `[u8]`. +//! +//! These traits are used to bound the `B` parameter of [`Ref`]. + +use core::{ + cell, + ops::{Deref, DerefMut}, +}; + +// For each trait polyfill, as soon as the corresponding feature is stable, the +// polyfill import will be unused because method/function resolution will prefer +// the inherent method/function over a trait method/function. Thus, we suppress +// the `unused_imports` warning. +// +// See the documentation on `util::polyfills` for more information. +#[allow(unused_imports)] +use crate::util::polyfills::{self, NonNullExt as _, NumExt as _}; +#[cfg(doc)] +use crate::Ref; + +/// A mutable or immutable reference to a byte slice. +/// +/// `ByteSlice` abstracts over the mutability of a byte slice reference, and is +/// implemented for various special reference types such as +/// [`Ref<[u8]>`](core::cell::Ref) and [`RefMut<[u8]>`](core::cell::RefMut). +/// +/// # Safety +/// +/// Implementations of `ByteSlice` must promise that their implementations of +/// [`Deref`] and [`DerefMut`] are "stable". In particular, given `B: ByteSlice` +/// and `b: B`, two calls, each to either `b.deref()` or `b.deref_mut()`, must +/// return a byte slice with the same address and length. This must hold even if +/// the two calls are separated by an arbitrary sequence of calls to methods on +/// `ByteSlice`, [`ByteSliceMut`], [`IntoByteSlice`], or [`IntoByteSliceMut`], +/// or on their super-traits. This does *not* need to hold if the two calls are +/// separated by any method calls, field accesses, or field modifications *other +/// than* those from these traits. +/// +/// Note that this also implies that, given `b: B`, the address and length +/// cannot be modified via objects other than `b`, either on the same thread or +/// on another thread. +pub unsafe trait ByteSlice: Deref + Sized {} + +/// A mutable reference to a byte slice. +/// +/// `ByteSliceMut` abstracts over various ways of storing a mutable reference to +/// a byte slice, and is implemented for various special reference types such as +/// `RefMut<[u8]>`. +/// +/// `ByteSliceMut` is a shorthand for [`ByteSlice`] and [`DerefMut`]. +pub trait ByteSliceMut: ByteSlice + DerefMut {} +impl ByteSliceMut for B {} + +/// A [`ByteSlice`] which can be copied without violating dereference stability. +/// +/// # Safety +/// +/// If `B: CopyableByteSlice`, then the dereference stability properties +/// required by [`ByteSlice`] (see that trait's safety documentation) do not +/// only hold regarding two calls to `b.deref()` or `b.deref_mut()`, but also +/// hold regarding `c.deref()` or `c.deref_mut()`, where `c` is produced by +/// copying `b`. +pub unsafe trait CopyableByteSlice: ByteSlice + Copy + CloneableByteSlice {} + +/// A [`ByteSlice`] which can be cloned without violating dereference stability. +/// +/// # Safety +/// +/// If `B: CloneableByteSlice`, then the dereference stability properties +/// required by [`ByteSlice`] (see that trait's safety documentation) do not +/// only hold regarding two calls to `b.deref()` or `b.deref_mut()`, but also +/// hold regarding `c.deref()` or `c.deref_mut()`, where `c` is produced by +/// `b.clone()`, `b.clone().clone()`, etc. +pub unsafe trait CloneableByteSlice: ByteSlice + Clone {} + +/// A [`ByteSlice`] that can be split in two. +/// +/// # Safety +/// +/// Unsafe code may depend for its soundness on the assumption that `split_at` +/// and `split_at_unchecked` are implemented correctly. In particular, given `B: +/// SplitByteSlice` and `b: B`, if `b.deref()` returns a byte slice with address +/// `addr` and length `len`, then if `split <= len`, both of these +/// invocations: +/// - `b.split_at(split)` +/// - `b.split_at_unchecked(split)` +/// +/// ...will return `(first, second)` such that: +/// - `first`'s address is `addr` and its length is `split` +/// - `second`'s address is `addr + split` and its length is `len - split` +pub unsafe trait SplitByteSlice: ByteSlice { + /// Attempts to split `self` at the midpoint. + /// + /// `s.split_at(mid)` returns `Ok((s[..mid], s[mid..]))` if `mid <= + /// s.deref().len()` and otherwise returns `Err(s)`. + /// + /// # Safety + /// + /// Unsafe code may rely on this function correctly implementing the above + /// functionality. + #[inline] + fn split_at(self, mid: usize) -> Result<(Self, Self), Self> { + if mid <= self.deref().len() { + // SAFETY: Above, we ensure that `mid <= self.deref().len()`. By + // invariant on `ByteSlice`, a supertrait of `SplitByteSlice`, + // `.deref()` is guaranteed to be "stable"; i.e., it will always + // dereference to a byte slice of the same address and length. Thus, + // we can be sure that the above precondition remains satisfied + // through the call to `split_at_unchecked`. + unsafe { Ok(self.split_at_unchecked(mid)) } + } else { + Err(self) + } + } + + /// Splits the slice at the midpoint, possibly omitting bounds checks. + /// + /// `s.split_at_unchecked(mid)` returns `s[..mid]` and `s[mid..]`. + /// + /// # Safety + /// + /// `mid` must not be greater than `self.deref().len()`. + /// + /// # Panics + /// + /// Implementations of this method may choose to perform a bounds check and + /// panic if `mid > self.deref().len()`. They may also panic for any other + /// reason. Since it is optional, callers must not rely on this behavior for + /// soundness. + #[must_use] + unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self); +} + +/// A shorthand for [`SplitByteSlice`] and [`ByteSliceMut`]. +pub trait SplitByteSliceMut: SplitByteSlice + ByteSliceMut {} +impl SplitByteSliceMut for B {} + +#[allow(clippy::missing_safety_doc)] // There's a `Safety` section on `into_byte_slice`. +/// A [`ByteSlice`] that conveys no ownership, and so can be converted into a +/// byte slice. +/// +/// Some `ByteSlice` types (notably, the standard library's [`Ref`] type) convey +/// ownership, and so they cannot soundly be moved by-value into a byte slice +/// type (`&[u8]`). Some methods in this crate's API (such as [`Ref::into_ref`]) +/// are only compatible with `ByteSlice` types without these ownership +/// semantics. +/// +/// [`Ref`]: core::cell::Ref +pub unsafe trait IntoByteSlice<'a>: ByteSlice { + /// Coverts `self` into a `&[u8]`. + /// + /// # Safety + /// + /// The returned reference has the same address and length as `self.deref()` + /// and `self.deref_mut()`. + /// + /// Note that, combined with the safety invariant on [`ByteSlice`], this + /// safety invariant implies that the returned reference is "stable" in the + /// sense described in the `ByteSlice` docs. + fn into_byte_slice(self) -> &'a [u8]; +} + +#[allow(clippy::missing_safety_doc)] // There's a `Safety` section on `into_byte_slice_mut`. +/// A [`ByteSliceMut`] that conveys no ownership, and so can be converted into a +/// mutable byte slice. +/// +/// Some `ByteSliceMut` types (notably, the standard library's [`RefMut`] type) +/// convey ownership, and so they cannot soundly be moved by-value into a byte +/// slice type (`&mut [u8]`). Some methods in this crate's API (such as +/// [`Ref::into_mut`]) are only compatible with `ByteSliceMut` types without +/// these ownership semantics. +/// +/// [`RefMut`]: core::cell::RefMut +pub unsafe trait IntoByteSliceMut<'a>: IntoByteSlice<'a> + ByteSliceMut { + /// Coverts `self` into a `&mut [u8]`. + /// + /// # Safety + /// + /// The returned reference has the same address and length as `self.deref()` + /// and `self.deref_mut()`. + /// + /// Note that, combined with the safety invariant on [`ByteSlice`], this + /// safety invariant implies that the returned reference is "stable" in the + /// sense described in the `ByteSlice` docs. + fn into_byte_slice_mut(self) -> &'a mut [u8]; +} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl ByteSlice for &[u8] {} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl CopyableByteSlice for &[u8] {} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl CloneableByteSlice for &[u8] {} + +// SAFETY: This delegates to `polyfills:split_at_unchecked`, which is documented +// to correctly split `self` into two slices at the given `mid` point. +unsafe impl SplitByteSlice for &[u8] { + #[inline] + unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { + // SAFETY: By contract on caller, `mid` is not greater than + // `bytes.len()`. + unsafe { (<[u8]>::get_unchecked(self, ..mid), <[u8]>::get_unchecked(self, mid..)) } + } +} + +// SAFETY: See inline. +unsafe impl<'a> IntoByteSlice<'a> for &'a [u8] { + #[inline(always)] + fn into_byte_slice(self) -> &'a [u8] { + // SAFETY: It would be patently insane to implement `::deref` as anything other than `fn deref(&self) -> &[u8] { + // *self }`. Assuming this holds, then `self` is stable as required by + // `into_byte_slice`. + self + } +} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl ByteSlice for &mut [u8] {} + +// SAFETY: This delegates to `polyfills:split_at_mut_unchecked`, which is +// documented to correctly split `self` into two slices at the given `mid` +// point. +unsafe impl SplitByteSlice for &mut [u8] { + #[inline] + unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { + use core::slice::from_raw_parts_mut; + + // `l_ptr` is non-null, because `self` is non-null, by invariant on + // `&mut [u8]`. + let l_ptr = self.as_mut_ptr(); + + // SAFETY: By contract on caller, `mid` is not greater than + // `self.len()`. + let r_ptr = unsafe { l_ptr.add(mid) }; + + let l_len = mid; + + // SAFETY: By contract on caller, `mid` is not greater than + // `self.len()`. + // + // FIXME(#67): Remove this allow. See NumExt for more details. + #[allow(unstable_name_collisions)] + let r_len = unsafe { self.len().unchecked_sub(mid) }; + + // SAFETY: These invocations of `from_raw_parts_mut` satisfy its + // documented safety preconditions [1]: + // - The data `l_ptr` and `r_ptr` are valid for both reads and writes of + // `l_len` and `r_len` bytes, respectively, and they are trivially + // aligned. In particular: + // - The entire memory range of each slice is contained within a + // single allocated object, since `l_ptr` and `r_ptr` are both + // derived from within the address range of `self`. + // - Both `l_ptr` and `r_ptr` are non-null and trivially aligned. + // `self` is non-null by invariant on `&mut [u8]`, and the + // operations that derive `l_ptr` and `r_ptr` from `self` do not + // nullify either pointer. + // - The data `l_ptr` and `r_ptr` point to `l_len` and `r_len`, + // respectively, consecutive properly initialized values of type `u8`. + // This is true for `self` by invariant on `&mut [u8]`, and remains + // true for these two sub-slices of `self`. + // - The memory referenced by the returned slice cannot be accessed + // through any other pointer (not derived from the return value) for + // the duration of lifetime `'a``, because: + // - `split_at_unchecked` consumes `self` (which is not `Copy`), + // - `split_at_unchecked` does not exfiltrate any references to this + // memory, besides those references returned below, + // - the returned slices are non-overlapping. + // - The individual sizes of the sub-slices of `self` are no larger than + // `isize::MAX`, because their combined sizes are no larger than + // `isize::MAX`, by invariant on `self`. + // + // [1] https://doc.rust-lang.org/std/slice/fn.from_raw_parts_mut.html#safety + unsafe { (from_raw_parts_mut(l_ptr, l_len), from_raw_parts_mut(r_ptr, r_len)) } + } +} + +// SAFETY: See inline. +unsafe impl<'a> IntoByteSlice<'a> for &'a mut [u8] { + #[inline(always)] + fn into_byte_slice(self) -> &'a [u8] { + // SAFETY: It would be patently insane to implement `::deref` as anything other than `fn deref(&self) -> &[u8] { + // *self }`. Assuming this holds, then `self` is stable as required by + // `into_byte_slice`. + self + } +} + +// SAFETY: See inline. +unsafe impl<'a> IntoByteSliceMut<'a> for &'a mut [u8] { + #[inline(always)] + fn into_byte_slice_mut(self) -> &'a mut [u8] { + // SAFETY: It would be patently insane to implement `::deref` as anything other than `fn deref_mut(&mut self) -> &mut + // [u8] { *self }`. Assuming this holds, then `self` is stable as + // required by `into_byte_slice_mut`. + self + } +} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl ByteSlice for cell::Ref<'_, [u8]> {} + +// SAFETY: This delegates to stdlib implementation of `Ref::map_split`, which is +// assumed to be correct, and `SplitByteSlice::split_at_unchecked`, which is +// documented to correctly split `self` into two slices at the given `mid` +// point. +unsafe impl SplitByteSlice for cell::Ref<'_, [u8]> { + #[inline] + unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { + cell::Ref::map_split(self, |slice| + // SAFETY: By precondition on caller, `mid` is not greater than + // `slice.len()`. + unsafe { + SplitByteSlice::split_at_unchecked(slice, mid) + }) + } +} + +// FIXME(#429): Add a "SAFETY" comment and remove this `allow`. +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl ByteSlice for cell::RefMut<'_, [u8]> {} + +// SAFETY: This delegates to stdlib implementation of `RefMut::map_split`, which +// is assumed to be correct, and `SplitByteSlice::split_at_unchecked`, which is +// documented to correctly split `self` into two slices at the given `mid` +// point. +unsafe impl SplitByteSlice for cell::RefMut<'_, [u8]> { + #[inline] + unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { + cell::RefMut::map_split(self, |slice| + // SAFETY: By precondition on caller, `mid` is not greater than + // `slice.len()` + unsafe { + SplitByteSlice::split_at_unchecked(slice, mid) + }) + } +} + +#[cfg(kani)] +mod proofs { + use super::*; + + fn any_vec() -> Vec { + let len = kani::any(); + kani::assume(len <= isize::MAX as usize); + vec![0u8; len] + } + + #[kani::proof] + fn prove_split_at_unchecked() { + let v = any_vec(); + let slc = v.as_slice(); + let mid = kani::any(); + kani::assume(mid <= slc.len()); + let (l, r) = unsafe { slc.split_at_unchecked(mid) }; + assert_eq!(l.len() + r.len(), slc.len()); + + let slc: *const _ = slc; + let l: *const _ = l; + let r: *const _ = r; + + assert_eq!(slc.cast::(), l.cast::()); + assert_eq!(unsafe { slc.cast::().add(mid) }, r.cast::()); + + let mut v = any_vec(); + let slc = v.as_mut_slice(); + let len = slc.len(); + let mid = kani::any(); + kani::assume(mid <= slc.len()); + let (l, r) = unsafe { slc.split_at_unchecked(mid) }; + assert_eq!(l.len() + r.len(), len); + + let l: *mut _ = l; + let r: *mut _ = r; + let slc: *mut _ = slc; + + assert_eq!(slc.cast::(), l.cast::()); + assert_eq!(unsafe { slc.cast::().add(mid) }, r.cast::()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/byteorder.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byteorder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/byteorder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/byteorder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1530 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Byte order-aware numeric primitives. +//! +//! This module contains equivalents of the native multi-byte integer types with +//! no alignment requirement and supporting byte order conversions. +//! +//! For each native multi-byte integer type - `u16`, `i16`, `u32`, etc - and +//! floating point type - `f32` and `f64` - an equivalent type is defined by +//! this module - [`U16`], [`I16`], [`U32`], [`F32`], [`F64`], etc. Unlike their +//! native counterparts, these types have alignment 1, and take a type parameter +//! specifying the byte order in which the bytes are stored in memory. Each type +//! implements this crate's relevant conversion and marker traits. +//! +//! These two properties, taken together, make these types useful for defining +//! data structures whose memory layout matches a wire format such as that of a +//! network protocol or a file format. Such formats often have multi-byte values +//! at offsets that do not respect the alignment requirements of the equivalent +//! native types, and stored in a byte order not necessarily the same as that of +//! the target platform. +//! +//! Type aliases are provided for common byte orders in the [`big_endian`], +//! [`little_endian`], [`network_endian`], and [`native_endian`] submodules. +//! +//! # Example +//! +//! One use of these types is for representing network packet formats, such as +//! UDP: +//! +//! ```rust +//! use zerocopy::{*, byteorder::network_endian::U16}; +//! # use zerocopy_derive::*; +//! +//! #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] +//! #[repr(C)] +//! struct UdpHeader { +//! src_port: U16, +//! dst_port: U16, +//! length: U16, +//! checksum: U16, +//! } +//! +//! #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] +//! #[repr(C, packed)] +//! struct UdpPacket { +//! header: UdpHeader, +//! body: [u8], +//! } +//! +//! impl UdpPacket { +//! fn parse(bytes: &[u8]) -> Option<&UdpPacket> { +//! UdpPacket::ref_from_bytes(bytes).ok() +//! } +//! } +//! ``` + +use core::{ + convert::{TryFrom, TryInto}, + fmt::{Binary, Debug, LowerHex, Octal, UpperHex}, + hash::Hash, + num::TryFromIntError, +}; + +use super::*; + +/// A type-level representation of byte order. +/// +/// This type is implemented by [`BigEndian`] and [`LittleEndian`], which +/// represent big-endian and little-endian byte order respectively. This module +/// also provides a number of useful aliases for those types: [`NativeEndian`], +/// [`NetworkEndian`], [`BE`], and [`LE`]. +/// +/// `ByteOrder` types can be used to specify the byte order of the types in this +/// module - for example, [`U32`] is a 32-bit integer stored in +/// big-endian byte order. +/// +/// [`U32`]: U32 +pub trait ByteOrder: + Copy + Clone + Debug + Display + Eq + PartialEq + Ord + PartialOrd + Hash + private::Sealed +{ + #[doc(hidden)] + const ORDER: Order; +} + +mod private { + pub trait Sealed {} + + impl Sealed for super::BigEndian {} + impl Sealed for super::LittleEndian {} +} + +#[allow(missing_copy_implementations, missing_debug_implementations)] +#[doc(hidden)] +pub enum Order { + BigEndian, + LittleEndian, +} + +/// Big-endian byte order. +/// +/// See [`ByteOrder`] for more details. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub enum BigEndian {} + +impl ByteOrder for BigEndian { + const ORDER: Order = Order::BigEndian; +} + +impl Display for BigEndian { + #[inline] + fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result { + match *self {} + } +} + +/// Little-endian byte order. +/// +/// See [`ByteOrder`] for more details. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub enum LittleEndian {} + +impl ByteOrder for LittleEndian { + const ORDER: Order = Order::LittleEndian; +} + +impl Display for LittleEndian { + #[inline] + fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result { + match *self {} + } +} + +/// The endianness used by this platform. +/// +/// This is a type alias for [`BigEndian`] or [`LittleEndian`] depending on the +/// endianness of the target platform. +#[cfg(target_endian = "big")] +pub type NativeEndian = BigEndian; + +/// The endianness used by this platform. +/// +/// This is a type alias for [`BigEndian`] or [`LittleEndian`] depending on the +/// endianness of the target platform. +#[cfg(target_endian = "little")] +pub type NativeEndian = LittleEndian; + +/// The endianness used in many network protocols. +/// +/// This is a type alias for [`BigEndian`]. +pub type NetworkEndian = BigEndian; + +/// A type alias for [`BigEndian`]. +pub type BE = BigEndian; + +/// A type alias for [`LittleEndian`]. +pub type LE = LittleEndian; + +macro_rules! impl_fmt_trait { + ($name:ident, $native:ident, $trait:ident) => { + impl $trait for $name { + #[inline(always)] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + $trait::fmt(&self.get(), f) + } + } + }; +} + +macro_rules! impl_fmt_traits { + ($name:ident, $native:ident, "floating point number") => { + impl_fmt_trait!($name, $native, Display); + }; + ($name:ident, $native:ident, "unsigned integer") => { + impl_fmt_traits!($name, $native, @all_types); + }; + ($name:ident, $native:ident, "signed integer") => { + impl_fmt_traits!($name, $native, @all_types); + }; + ($name:ident, $native:ident, @all_types) => { + impl_fmt_trait!($name, $native, Display); + impl_fmt_trait!($name, $native, Octal); + impl_fmt_trait!($name, $native, LowerHex); + impl_fmt_trait!($name, $native, UpperHex); + impl_fmt_trait!($name, $native, Binary); + }; +} + +macro_rules! impl_ops_traits { + ($name:ident, $native:ident, "floating point number") => { + impl_ops_traits!($name, $native, @all_types); + impl_ops_traits!($name, $native, @signed_integer_floating_point); + + impl PartialOrd for $name { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { + self.get().partial_cmp(&other.get()) + } + } + }; + ($name:ident, $native:ident, "unsigned integer") => { + impl_ops_traits!($name, $native, @signed_unsigned_integer); + impl_ops_traits!($name, $native, @all_types); + }; + ($name:ident, $native:ident, "signed integer") => { + impl_ops_traits!($name, $native, @signed_unsigned_integer); + impl_ops_traits!($name, $native, @signed_integer_floating_point); + impl_ops_traits!($name, $native, @all_types); + }; + ($name:ident, $native:ident, @signed_unsigned_integer) => { + impl_ops_traits!(@without_byteorder_swap $name, $native, BitAnd, bitand, BitAndAssign, bitand_assign); + impl_ops_traits!(@without_byteorder_swap $name, $native, BitOr, bitor, BitOrAssign, bitor_assign); + impl_ops_traits!(@without_byteorder_swap $name, $native, BitXor, bitxor, BitXorAssign, bitxor_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Shl, shl, ShlAssign, shl_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Shr, shr, ShrAssign, shr_assign); + + impl core::ops::Not for $name { + type Output = $name; + + #[inline(always)] + fn not(self) -> $name { + let self_native = $native::from_ne_bytes(self.0); + $name((!self_native).to_ne_bytes(), PhantomData) + } + } + + impl PartialOrd for $name { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl Ord for $name { + #[inline(always)] + fn cmp(&self, other: &Self) -> Ordering { + self.get().cmp(&other.get()) + } + } + + impl PartialOrd<$native> for $name { + #[inline(always)] + fn partial_cmp(&self, other: &$native) -> Option { + self.get().partial_cmp(other) + } + } + }; + ($name:ident, $native:ident, @signed_integer_floating_point) => { + impl core::ops::Neg for $name { + type Output = $name; + + #[inline(always)] + fn neg(self) -> $name { + let self_native: $native = self.get(); + #[allow(clippy::arithmetic_side_effects)] + $name::::new(-self_native) + } + } + }; + ($name:ident, $native:ident, @all_types) => { + impl_ops_traits!(@with_byteorder_swap $name, $native, Add, add, AddAssign, add_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Div, div, DivAssign, div_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Mul, mul, MulAssign, mul_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Rem, rem, RemAssign, rem_assign); + impl_ops_traits!(@with_byteorder_swap $name, $native, Sub, sub, SubAssign, sub_assign); + }; + (@with_byteorder_swap $name:ident, $native:ident, $trait:ident, $method:ident, $trait_assign:ident, $method_assign:ident) => { + impl core::ops::$trait<$name> for $name { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $name) -> $name { + let self_native: $native = self.get(); + let rhs_native: $native = rhs.get(); + let result_native = core::ops::$trait::$method(self_native, rhs_native); + $name::::new(result_native) + } + } + + impl core::ops::$trait<$name> for $native { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $name) -> $name { + let rhs_native: $native = rhs.get(); + let result_native = core::ops::$trait::$method(self, rhs_native); + $name::::new(result_native) + } + } + + impl core::ops::$trait<$native> for $name { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $native) -> $name { + let self_native: $native = self.get(); + let result_native = core::ops::$trait::$method(self_native, rhs); + $name::::new(result_native) + } + } + + impl core::ops::$trait_assign<$name> for $name { + #[inline(always)] + fn $method_assign(&mut self, rhs: $name) { + *self = core::ops::$trait::$method(*self, rhs); + } + } + + impl core::ops::$trait_assign<$name> for $native { + #[inline(always)] + fn $method_assign(&mut self, rhs: $name) { + let rhs_native: $native = rhs.get(); + *self = core::ops::$trait::$method(*self, rhs_native); + } + } + + impl core::ops::$trait_assign<$native> for $name { + #[inline(always)] + fn $method_assign(&mut self, rhs: $native) { + *self = core::ops::$trait::$method(*self, rhs); + } + } + }; + // Implement traits in terms of the same trait on the native type, but + // without performing a byte order swap when both operands are byteorder + // types. This only works for bitwise operations like `&`, `|`, etc. + // + // When only one operand is a byteorder type, we still need to perform a + // byteorder swap. + (@without_byteorder_swap $name:ident, $native:ident, $trait:ident, $method:ident, $trait_assign:ident, $method_assign:ident) => { + impl core::ops::$trait<$name> for $name { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $name) -> $name { + let self_native = $native::from_ne_bytes(self.0); + let rhs_native = $native::from_ne_bytes(rhs.0); + let result_native = core::ops::$trait::$method(self_native, rhs_native); + $name(result_native.to_ne_bytes(), PhantomData) + } + } + + impl core::ops::$trait<$name> for $native { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $name) -> $name { + // No runtime cost - just byte packing + let rhs_native = $native::from_ne_bytes(rhs.0); + // (Maybe) runtime cost - byte order swap + let slf_byteorder = $name::::new(self); + // No runtime cost - just byte packing + let slf_native = $native::from_ne_bytes(slf_byteorder.0); + // Runtime cost - perform the operation + let result_native = core::ops::$trait::$method(slf_native, rhs_native); + // No runtime cost - just byte unpacking + $name(result_native.to_ne_bytes(), PhantomData) + } + } + + impl core::ops::$trait<$native> for $name { + type Output = $name; + + #[inline(always)] + fn $method(self, rhs: $native) -> $name { + // (Maybe) runtime cost - byte order swap + let rhs_byteorder = $name::::new(rhs); + // No runtime cost - just byte packing + let rhs_native = $native::from_ne_bytes(rhs_byteorder.0); + // No runtime cost - just byte packing + let slf_native = $native::from_ne_bytes(self.0); + // Runtime cost - perform the operation + let result_native = core::ops::$trait::$method(slf_native, rhs_native); + // No runtime cost - just byte unpacking + $name(result_native.to_ne_bytes(), PhantomData) + } + } + + impl core::ops::$trait_assign<$name> for $name { + #[inline(always)] + fn $method_assign(&mut self, rhs: $name) { + *self = core::ops::$trait::$method(*self, rhs); + } + } + + impl core::ops::$trait_assign<$name> for $native { + #[inline(always)] + fn $method_assign(&mut self, rhs: $name) { + // (Maybe) runtime cost - byte order swap + let rhs_native = rhs.get(); + // Runtime cost - perform the operation + *self = core::ops::$trait::$method(*self, rhs_native); + } + } + + impl core::ops::$trait_assign<$native> for $name { + #[inline(always)] + fn $method_assign(&mut self, rhs: $native) { + *self = core::ops::$trait::$method(*self, rhs); + } + } + }; +} + +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + }; +} + +macro_rules! define_max_value_constant { + ($name:ident, $bytes:expr, "unsigned integer") => { + /// The maximum value. + /// + /// This constant should be preferred to constructing a new value using + /// `new`, as `new` may perform an endianness swap depending on the + /// endianness `O` and the endianness of the platform. + pub const MAX_VALUE: $name = $name([0xFFu8; $bytes], PhantomData); + }; + // We don't provide maximum and minimum value constants for signed values + // and floats because there's no way to do it generically - it would require + // a different value depending on the value of the `ByteOrder` type + // parameter. Currently, one workaround would be to provide implementations + // for concrete implementations of that trait. In the long term, if we are + // ever able to make the `new` constructor a const fn, we could use that + // instead. + ($name:ident, $bytes:expr, "signed integer") => {}; + ($name:ident, $bytes:expr, "floating point number") => {}; +} + +macro_rules! define_type { + ( + $article:ident, + $description:expr, + $name:ident, + $native:ident, + $bits:expr, + $bytes:expr, + $from_be_fn:path, + $to_be_fn:path, + $from_le_fn:path, + $to_le_fn:path, + $number_kind:tt, + [$($larger_native:ty),*], + [$($larger_native_try:ty),*], + [$($larger_byteorder:ident),*], + [$($larger_byteorder_try:ident),*] + ) => { + doc_comment! { + concat!($description, " stored in a given byte order. + +`", stringify!($name), "` is like the native `", stringify!($native), "` type with +two major differences: First, it has no alignment requirement (its alignment is 1). +Second, the endianness of its memory layout is given by the type parameter `O`, +which can be any type which implements [`ByteOrder`]. In particular, this refers +to [`BigEndian`], [`LittleEndian`], [`NativeEndian`], and [`NetworkEndian`]. + +", stringify!($article), " `", stringify!($name), "` can be constructed using +the [`new`] method, and its contained value can be obtained as a native +`",stringify!($native), "` using the [`get`] method, or updated in place with +the [`set`] method. In all cases, if the endianness `O` is not the same as the +endianness of the current platform, an endianness swap will be performed in +order to uphold the invariants that a) the layout of `", stringify!($name), "` +has endianness `O` and that, b) the layout of `", stringify!($native), "` has +the platform's native endianness. + +`", stringify!($name), "` implements [`FromBytes`], [`IntoBytes`], and [`Unaligned`], +making it useful for parsing and serialization. See the module documentation for an +example of how it can be used for parsing UDP packets. + +[`new`]: crate::byteorder::", stringify!($name), "::new +[`get`]: crate::byteorder::", stringify!($name), "::get +[`set`]: crate::byteorder::", stringify!($name), "::set +[`FromBytes`]: crate::FromBytes +[`IntoBytes`]: crate::IntoBytes +[`Unaligned`]: crate::Unaligned"), + #[derive(Copy, Clone, Eq, PartialEq, Hash)] + #[cfg_attr(any(feature = "derive", test), derive(KnownLayout, Immutable, FromBytes, IntoBytes, Unaligned))] + #[repr(transparent)] + pub struct $name([u8; $bytes], PhantomData); + } + + #[cfg(not(any(feature = "derive", test)))] + impl_known_layout!(O => $name); + + #[allow(unused_unsafe)] // Unused when `feature = "derive"`. + // SAFETY: `$name` is `repr(transparent)`, and so it has the same + // layout as its only non-zero field, which is a `u8` array. `u8` arrays + // are `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, + // `IntoBytes`, and `Unaligned`. + const _: () = unsafe { + impl_or_verify!(O => Immutable for $name); + impl_or_verify!(O => TryFromBytes for $name); + impl_or_verify!(O => FromZeros for $name); + impl_or_verify!(O => FromBytes for $name); + impl_or_verify!(O => IntoBytes for $name); + impl_or_verify!(O => Unaligned for $name); + }; + + impl Default for $name { + #[inline(always)] + fn default() -> $name { + $name::ZERO + } + } + + impl $name { + /// The value zero. + /// + /// This constant should be preferred to constructing a new value + /// using `new`, as `new` may perform an endianness swap depending + /// on the endianness and platform. + pub const ZERO: $name = $name([0u8; $bytes], PhantomData); + + define_max_value_constant!($name, $bytes, $number_kind); + + /// Constructs a new value from bytes which are already in `O` byte + /// order. + #[must_use = "has no side effects"] + #[inline(always)] + pub const fn from_bytes(bytes: [u8; $bytes]) -> $name { + $name(bytes, PhantomData) + } + + /// Extracts the bytes of `self` without swapping the byte order. + /// + /// The returned bytes will be in `O` byte order. + #[must_use = "has no side effects"] + #[inline(always)] + pub const fn to_bytes(self) -> [u8; $bytes] { + self.0 + } + } + + impl $name { + maybe_const_trait_bounded_fn! { + /// Constructs a new value, possibly performing an endianness + /// swap to guarantee that the returned value has endianness + /// `O`. + #[must_use = "has no side effects"] + #[inline(always)] + pub const fn new(n: $native) -> $name { + let bytes = match O::ORDER { + Order::BigEndian => $to_be_fn(n), + Order::LittleEndian => $to_le_fn(n), + }; + + $name(bytes, PhantomData) + } + } + + maybe_const_trait_bounded_fn! { + /// Returns the value as a primitive type, possibly performing + /// an endianness swap to guarantee that the return value has + /// the endianness of the native platform. + #[must_use = "has no side effects"] + #[inline(always)] + pub const fn get(self) -> $native { + match O::ORDER { + Order::BigEndian => $from_be_fn(self.0), + Order::LittleEndian => $from_le_fn(self.0), + } + } + } + + /// Updates the value in place as a primitive type, possibly + /// performing an endianness swap to guarantee that the stored value + /// has the endianness `O`. + #[inline(always)] + pub fn set(&mut self, n: $native) { + *self = Self::new(n); + } + } + + // The reasoning behind which traits to implement here is to only + // implement traits which won't cause inference issues. Notably, + // comparison traits like PartialEq and PartialOrd tend to cause + // inference issues. + + impl From<$name> for [u8; $bytes] { + #[inline(always)] + fn from(x: $name) -> [u8; $bytes] { + x.0 + } + } + + impl From<[u8; $bytes]> for $name { + #[inline(always)] + fn from(bytes: [u8; $bytes]) -> $name { + $name(bytes, PhantomData) + } + } + + impl From<$name> for $native { + #[inline(always)] + fn from(x: $name) -> $native { + x.get() + } + } + + impl From<$native> for $name { + #[inline(always)] + fn from(x: $native) -> $name { + $name::new(x) + } + } + + $( + impl From<$name> for $larger_native { + #[inline(always)] + fn from(x: $name) -> $larger_native { + x.get().into() + } + } + )* + + $( + impl TryFrom<$larger_native_try> for $name { + type Error = TryFromIntError; + #[inline(always)] + fn try_from(x: $larger_native_try) -> Result<$name, TryFromIntError> { + $native::try_from(x).map($name::new) + } + } + )* + + $( + impl From<$name> for $larger_byteorder

{ + #[inline(always)] + fn from(x: $name) -> $larger_byteorder

{ + $larger_byteorder::new(x.get().into()) + } + } + )* + + $( + impl TryFrom<$larger_byteorder_try

> for $name { + type Error = TryFromIntError; + #[inline(always)] + fn try_from(x: $larger_byteorder_try

) -> Result<$name, TryFromIntError> { + x.get().try_into().map($name::new) + } + } + )* + + impl AsRef<[u8; $bytes]> for $name { + #[inline(always)] + fn as_ref(&self) -> &[u8; $bytes] { + &self.0 + } + } + + impl AsMut<[u8; $bytes]> for $name { + #[inline(always)] + fn as_mut(&mut self) -> &mut [u8; $bytes] { + &mut self.0 + } + } + + impl PartialEq<$name> for [u8; $bytes] { + #[inline(always)] + fn eq(&self, other: &$name) -> bool { + self.eq(&other.0) + } + } + + impl PartialEq<[u8; $bytes]> for $name { + #[inline(always)] + fn eq(&self, other: &[u8; $bytes]) -> bool { + self.0.eq(other) + } + } + + impl PartialEq<$native> for $name { + #[inline(always)] + fn eq(&self, other: &$native) -> bool { + self.get().eq(other) + } + } + + impl_fmt_traits!($name, $native, $number_kind); + impl_ops_traits!($name, $native, $number_kind); + + impl Debug for $name { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + // This results in a format like "U16(42)". + f.debug_tuple(stringify!($name)).field(&self.get()).finish() + } + } + }; +} + +define_type!( + A, + "A 16-bit unsigned integer", + U16, + u16, + 16, + 2, + u16::from_be_bytes, + u16::to_be_bytes, + u16::from_le_bytes, + u16::to_le_bytes, + "unsigned integer", + [u32, u64, u128, usize], + [u32, u64, u128, usize], + [U32, U64, U128, Usize], + [U32, U64, U128, Usize] +); +define_type!( + A, + "A 32-bit unsigned integer", + U32, + u32, + 32, + 4, + u32::from_be_bytes, + u32::to_be_bytes, + u32::from_le_bytes, + u32::to_le_bytes, + "unsigned integer", + [u64, u128], + [u64, u128], + [U64, U128], + [U64, U128] +); +define_type!( + A, + "A 64-bit unsigned integer", + U64, + u64, + 64, + 8, + u64::from_be_bytes, + u64::to_be_bytes, + u64::from_le_bytes, + u64::to_le_bytes, + "unsigned integer", + [u128], + [u128], + [U128], + [U128] +); +define_type!( + A, + "A 128-bit unsigned integer", + U128, + u128, + 128, + 16, + u128::from_be_bytes, + u128::to_be_bytes, + u128::from_le_bytes, + u128::to_le_bytes, + "unsigned integer", + [], + [], + [], + [] +); +define_type!( + A, + "A word-sized unsigned integer", + Usize, + usize, + mem::size_of::() * 8, + mem::size_of::(), + usize::from_be_bytes, + usize::to_be_bytes, + usize::from_le_bytes, + usize::to_le_bytes, + "unsigned integer", + [], + [], + [], + [] +); +define_type!( + An, + "A 16-bit signed integer", + I16, + i16, + 16, + 2, + i16::from_be_bytes, + i16::to_be_bytes, + i16::from_le_bytes, + i16::to_le_bytes, + "signed integer", + [i32, i64, i128, isize], + [i32, i64, i128, isize], + [I32, I64, I128, Isize], + [I32, I64, I128, Isize] +); +define_type!( + An, + "A 32-bit signed integer", + I32, + i32, + 32, + 4, + i32::from_be_bytes, + i32::to_be_bytes, + i32::from_le_bytes, + i32::to_le_bytes, + "signed integer", + [i64, i128], + [i64, i128], + [I64, I128], + [I64, I128] +); +define_type!( + An, + "A 64-bit signed integer", + I64, + i64, + 64, + 8, + i64::from_be_bytes, + i64::to_be_bytes, + i64::from_le_bytes, + i64::to_le_bytes, + "signed integer", + [i128], + [i128], + [I128], + [I128] +); +define_type!( + An, + "A 128-bit signed integer", + I128, + i128, + 128, + 16, + i128::from_be_bytes, + i128::to_be_bytes, + i128::from_le_bytes, + i128::to_le_bytes, + "signed integer", + [], + [], + [], + [] +); +define_type!( + An, + "A word-sized signed integer", + Isize, + isize, + mem::size_of::() * 8, + mem::size_of::(), + isize::from_be_bytes, + isize::to_be_bytes, + isize::from_le_bytes, + isize::to_le_bytes, + "signed integer", + [], + [], + [], + [] +); + +// FIXME(https://github.com/rust-lang/rust/issues/72447): Use the endianness +// conversion methods directly once those are const-stable. +macro_rules! define_float_conversion { + ($ty:ty, $bits:ident, $bytes:expr, $mod:ident) => { + mod $mod { + use super::*; + + define_float_conversion!($ty, $bits, $bytes, from_be_bytes, to_be_bytes); + define_float_conversion!($ty, $bits, $bytes, from_le_bytes, to_le_bytes); + } + }; + ($ty:ty, $bits:ident, $bytes:expr, $from:ident, $to:ident) => { + // Clippy: The suggestion of using `from_bits()` instead doesn't work + // because `from_bits` is not const-stable on our MSRV. + #[allow(clippy::unnecessary_transmutes)] + pub(crate) const fn $from(bytes: [u8; $bytes]) -> $ty { + transmute!($bits::$from(bytes)) + } + + pub(crate) const fn $to(f: $ty) -> [u8; $bytes] { + // Clippy: The suggestion of using `f.to_bits()` instead doesn't + // work because `to_bits` is not const-stable on our MSRV. + #[allow(clippy::unnecessary_transmutes)] + let bits: $bits = transmute!(f); + bits.$to() + } + }; +} + +define_float_conversion!(f32, u32, 4, f32_ext); +define_float_conversion!(f64, u64, 8, f64_ext); + +define_type!( + An, + "A 32-bit floating point number", + F32, + f32, + 32, + 4, + f32_ext::from_be_bytes, + f32_ext::to_be_bytes, + f32_ext::from_le_bytes, + f32_ext::to_le_bytes, + "floating point number", + [f64], + [], + [F64], + [] +); +define_type!( + An, + "A 64-bit floating point number", + F64, + f64, + 64, + 8, + f64_ext::from_be_bytes, + f64_ext::to_be_bytes, + f64_ext::from_le_bytes, + f64_ext::to_le_bytes, + "floating point number", + [], + [], + [], + [] +); + +macro_rules! module { + ($name:ident, $trait:ident, $endianness_str:expr) => { + /// Numeric primitives stored in + #[doc = $endianness_str] + /// byte order. + pub mod $name { + use super::$trait; + + module!(@ty U16, $trait, "16-bit unsigned integer", $endianness_str); + module!(@ty U32, $trait, "32-bit unsigned integer", $endianness_str); + module!(@ty U64, $trait, "64-bit unsigned integer", $endianness_str); + module!(@ty U128, $trait, "128-bit unsigned integer", $endianness_str); + module!(@ty I16, $trait, "16-bit signed integer", $endianness_str); + module!(@ty I32, $trait, "32-bit signed integer", $endianness_str); + module!(@ty I64, $trait, "64-bit signed integer", $endianness_str); + module!(@ty I128, $trait, "128-bit signed integer", $endianness_str); + module!(@ty F32, $trait, "32-bit floating point number", $endianness_str); + module!(@ty F64, $trait, "64-bit floating point number", $endianness_str); + } + }; + (@ty $ty:ident, $trait:ident, $desc_str:expr, $endianness_str:expr) => { + /// A + #[doc = $desc_str] + /// stored in + #[doc = $endianness_str] + /// byte order. + pub type $ty = crate::byteorder::$ty<$trait>; + }; +} + +module!(big_endian, BigEndian, "big-endian"); +module!(little_endian, LittleEndian, "little-endian"); +module!(network_endian, NetworkEndian, "network-endian"); +module!(native_endian, NativeEndian, "native-endian"); + +#[cfg(any(test, kani))] +mod tests { + use super::*; + + #[cfg(not(kani))] + mod compatibility { + pub(super) use rand::{ + distributions::{Distribution, Standard}, + rngs::SmallRng, + Rng, SeedableRng, + }; + + pub(crate) trait Arbitrary {} + + impl Arbitrary for T {} + } + + #[cfg(kani)] + mod compatibility { + pub(crate) use kani::Arbitrary; + + pub(crate) struct SmallRng; + + impl SmallRng { + pub(crate) fn seed_from_u64(_state: u64) -> Self { + Self + } + } + + pub(crate) trait Rng { + fn sample>(&mut self, _distr: D) -> T + where + T: Arbitrary, + { + kani::any() + } + } + + impl Rng for SmallRng {} + + pub(crate) trait Distribution {} + impl Distribution for U {} + + pub(crate) struct Standard; + } + + use compatibility::*; + + // A native integer type (u16, i32, etc). + trait Native: Arbitrary + FromBytes + IntoBytes + Immutable + Copy + PartialEq + Debug { + const ZERO: Self; + const MAX_VALUE: Self; + + type Distribution: Distribution; + const DIST: Self::Distribution; + + fn rand(rng: &mut R) -> Self { + rng.sample(Self::DIST) + } + + #[cfg_attr(kani, allow(unused))] + fn checked_add(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_div(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_mul(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_rem(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_sub(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_shl(self, rhs: Self) -> Option; + + #[cfg_attr(kani, allow(unused))] + fn checked_shr(self, rhs: Self) -> Option; + + fn is_nan(self) -> bool; + + /// For `f32` and `f64`, NaN values are not considered equal to + /// themselves. This method is like `assert_eq!`, but it treats NaN + /// values as equal. + fn assert_eq_or_nan(self, other: Self) { + let slf = (!self.is_nan()).then(|| self); + let other = (!other.is_nan()).then(|| other); + assert_eq!(slf, other); + } + } + + trait ByteArray: + FromBytes + IntoBytes + Immutable + Copy + AsRef<[u8]> + AsMut<[u8]> + Debug + Default + Eq + { + /// Invert the order of the bytes in the array. + fn invert(self) -> Self; + } + + trait ByteOrderType: + FromBytes + IntoBytes + Unaligned + Copy + Eq + Debug + Hash + From + { + type Native: Native; + type ByteArray: ByteArray; + + const ZERO: Self; + + fn new(native: Self::Native) -> Self; + fn get(self) -> Self::Native; + fn set(&mut self, native: Self::Native); + fn from_bytes(bytes: Self::ByteArray) -> Self; + fn into_bytes(self) -> Self::ByteArray; + + /// For `f32` and `f64`, NaN values are not considered equal to + /// themselves. This method is like `assert_eq!`, but it treats NaN + /// values as equal. + fn assert_eq_or_nan(self, other: Self) { + let slf = (!self.get().is_nan()).then(|| self); + let other = (!other.get().is_nan()).then(|| other); + assert_eq!(slf, other); + } + } + + trait ByteOrderTypeUnsigned: ByteOrderType { + const MAX_VALUE: Self; + } + + macro_rules! impl_byte_array { + ($bytes:expr) => { + impl ByteArray for [u8; $bytes] { + fn invert(mut self) -> [u8; $bytes] { + self.reverse(); + self + } + } + }; + } + + impl_byte_array!(2); + impl_byte_array!(4); + impl_byte_array!(8); + impl_byte_array!(16); + + macro_rules! impl_byte_order_type_unsigned { + ($name:ident, unsigned) => { + impl ByteOrderTypeUnsigned for $name { + const MAX_VALUE: $name = $name::MAX_VALUE; + } + }; + ($name:ident, signed) => {}; + } + + macro_rules! impl_traits { + ($name:ident, $native:ident, $sign:ident $(, @$float:ident)?) => { + impl Native for $native { + // For some types, `0 as $native` is required (for example, when + // `$native` is a floating-point type; `0` is an integer), but + // for other types, it's a trivial cast. In all cases, Clippy + // thinks it's dangerous. + #[allow(trivial_numeric_casts, clippy::as_conversions)] + const ZERO: $native = 0 as $native; + const MAX_VALUE: $native = $native::MAX; + + type Distribution = Standard; + const DIST: Standard = Standard; + + impl_traits!(@float_dependent_methods $(@$float)?); + } + + impl ByteOrderType for $name { + type Native = $native; + type ByteArray = [u8; mem::size_of::<$native>()]; + + const ZERO: $name = $name::ZERO; + + fn new(native: $native) -> $name { + $name::new(native) + } + + fn get(self) -> $native { + $name::get(self) + } + + fn set(&mut self, native: $native) { + $name::set(self, native) + } + + fn from_bytes(bytes: [u8; mem::size_of::<$native>()]) -> $name { + $name::from(bytes) + } + + fn into_bytes(self) -> [u8; mem::size_of::<$native>()] { + <[u8; mem::size_of::<$native>()]>::from(self) + } + } + + impl_byte_order_type_unsigned!($name, $sign); + }; + (@float_dependent_methods) => { + fn checked_add(self, rhs: Self) -> Option { self.checked_add(rhs) } + fn checked_div(self, rhs: Self) -> Option { self.checked_div(rhs) } + fn checked_mul(self, rhs: Self) -> Option { self.checked_mul(rhs) } + fn checked_rem(self, rhs: Self) -> Option { self.checked_rem(rhs) } + fn checked_sub(self, rhs: Self) -> Option { self.checked_sub(rhs) } + fn checked_shl(self, rhs: Self) -> Option { self.checked_shl(rhs.try_into().unwrap_or(u32::MAX)) } + fn checked_shr(self, rhs: Self) -> Option { self.checked_shr(rhs.try_into().unwrap_or(u32::MAX)) } + fn is_nan(self) -> bool { false } + }; + (@float_dependent_methods @float) => { + fn checked_add(self, rhs: Self) -> Option { Some(self + rhs) } + fn checked_div(self, rhs: Self) -> Option { Some(self / rhs) } + fn checked_mul(self, rhs: Self) -> Option { Some(self * rhs) } + fn checked_rem(self, rhs: Self) -> Option { Some(self % rhs) } + fn checked_sub(self, rhs: Self) -> Option { Some(self - rhs) } + fn checked_shl(self, _rhs: Self) -> Option { unimplemented!() } + fn checked_shr(self, _rhs: Self) -> Option { unimplemented!() } + fn is_nan(self) -> bool { self.is_nan() } + }; + } + + impl_traits!(U16, u16, unsigned); + impl_traits!(U32, u32, unsigned); + impl_traits!(U64, u64, unsigned); + impl_traits!(U128, u128, unsigned); + impl_traits!(Usize, usize, unsigned); + impl_traits!(I16, i16, signed); + impl_traits!(I32, i32, signed); + impl_traits!(I64, i64, signed); + impl_traits!(I128, i128, signed); + impl_traits!(Isize, isize, unsigned); + impl_traits!(F32, f32, signed, @float); + impl_traits!(F64, f64, signed, @float); + + macro_rules! call_for_unsigned_types { + ($fn:ident, $byteorder:ident) => { + $fn::>(); + $fn::>(); + $fn::>(); + $fn::>(); + $fn::>(); + }; + } + + macro_rules! call_for_signed_types { + ($fn:ident, $byteorder:ident) => { + $fn::>(); + $fn::>(); + $fn::>(); + $fn::>(); + $fn::>(); + }; + } + + macro_rules! call_for_float_types { + ($fn:ident, $byteorder:ident) => { + $fn::>(); + $fn::>(); + }; + } + + macro_rules! call_for_all_types { + ($fn:ident, $byteorder:ident) => { + call_for_unsigned_types!($fn, $byteorder); + call_for_signed_types!($fn, $byteorder); + call_for_float_types!($fn, $byteorder); + }; + } + + #[cfg(target_endian = "big")] + type NonNativeEndian = LittleEndian; + #[cfg(target_endian = "little")] + type NonNativeEndian = BigEndian; + + // We use a `u64` seed so that we can use `SeedableRng::seed_from_u64`. + // `SmallRng`'s `SeedableRng::Seed` differs by platform, so if we wanted to + // call `SeedableRng::from_seed`, which takes a `Seed`, we would need + // conditional compilation by `target_pointer_width`. + const RNG_SEED: u64 = 0x7A03CAE2F32B5B8F; + + const RAND_ITERS: usize = if cfg!(any(miri, kani)) { + // The tests below which use this constant used to take a very long time + // on Miri, which slows down local development and CI jobs. We're not + // using Miri to check for the correctness of our code, but rather its + // soundness, and at least in the context of these particular tests, a + // single loop iteration is just as good for surfacing UB as multiple + // iterations are. + // + // As of the writing of this comment, here's one set of measurements: + // + // $ # RAND_ITERS == 1 + // $ cargo miri test -- -Z unstable-options --report-time endian + // test byteorder::tests::test_native_endian ... ok <0.049s> + // test byteorder::tests::test_non_native_endian ... ok <0.061s> + // + // $ # RAND_ITERS == 1024 + // $ cargo miri test -- -Z unstable-options --report-time endian + // test byteorder::tests::test_native_endian ... ok <25.716s> + // test byteorder::tests::test_non_native_endian ... ok <38.127s> + 1 + } else { + 1024 + }; + + #[test] + fn test_const_methods() { + use big_endian::*; + + #[rustversion::since(1.61.0)] + const _U: U16 = U16::new(0); + #[rustversion::since(1.61.0)] + const _NATIVE: u16 = _U.get(); + const _FROM_BYTES: U16 = U16::from_bytes([0, 1]); + const _BYTES: [u8; 2] = _FROM_BYTES.to_bytes(); + } + + #[cfg_attr(test, test)] + #[cfg_attr(kani, kani::proof)] + fn test_zero() { + fn test_zero() { + assert_eq!(T::ZERO.get(), T::Native::ZERO); + } + + call_for_all_types!(test_zero, NativeEndian); + call_for_all_types!(test_zero, NonNativeEndian); + } + + #[cfg_attr(test, test)] + #[cfg_attr(kani, kani::proof)] + fn test_max_value() { + fn test_max_value() { + assert_eq!(T::MAX_VALUE.get(), T::Native::MAX_VALUE); + } + + call_for_unsigned_types!(test_max_value, NativeEndian); + call_for_unsigned_types!(test_max_value, NonNativeEndian); + } + + #[cfg_attr(test, test)] + #[cfg_attr(kani, kani::proof)] + fn test_endian() { + fn test(invert: bool) { + let mut r = SmallRng::seed_from_u64(RNG_SEED); + for _ in 0..RAND_ITERS { + let native = T::Native::rand(&mut r); + let mut bytes = T::ByteArray::default(); + bytes.as_mut_bytes().copy_from_slice(native.as_bytes()); + if invert { + bytes = bytes.invert(); + } + let mut from_native = T::new(native); + let from_bytes = T::from_bytes(bytes); + + from_native.assert_eq_or_nan(from_bytes); + from_native.get().assert_eq_or_nan(native); + from_bytes.get().assert_eq_or_nan(native); + + assert_eq!(from_native.into_bytes(), bytes); + assert_eq!(from_bytes.into_bytes(), bytes); + + let updated = T::Native::rand(&mut r); + from_native.set(updated); + from_native.get().assert_eq_or_nan(updated); + } + } + + fn test_native() { + test::(false); + } + + fn test_non_native() { + test::(true); + } + + call_for_all_types!(test_native, NativeEndian); + call_for_all_types!(test_non_native, NonNativeEndian); + } + + #[test] + fn test_ops_impls() { + // Test implementations of traits in `core::ops`. Some of these are + // fairly banal, but some are optimized to perform the operation without + // swapping byte order (namely, bit-wise operations which are identical + // regardless of byte order). These are important to test, and while + // we're testing those anyway, it's trivial to test all of the impls. + + fn test( + op_t_t: FTT, + op_t_n: FTN, + op_n_t: FNT, + op_n_n: FNN, + op_n_n_checked: Option, + op_assign: Option<(FATT, FATN, FANT)>, + ) where + T: ByteOrderType, + FTT: Fn(T, T) -> T, + FTN: Fn(T, T::Native) -> T, + FNT: Fn(T::Native, T) -> T, + FNN: Fn(T::Native, T::Native) -> T::Native, + FNNChecked: Fn(T::Native, T::Native) -> Option, + + FATT: Fn(&mut T, T), + FATN: Fn(&mut T, T::Native), + FANT: Fn(&mut T::Native, T), + { + let mut r = SmallRng::seed_from_u64(RNG_SEED); + for _ in 0..RAND_ITERS { + let n0 = T::Native::rand(&mut r); + let n1 = T::Native::rand(&mut r); + let t0 = T::new(n0); + let t1 = T::new(n1); + + // If this operation would overflow/underflow, skip it rather + // than attempt to catch and recover from panics. + if matches!(&op_n_n_checked, Some(checked) if checked(n0, n1).is_none()) { + continue; + } + + let t_t_res = op_t_t(t0, t1); + let t_n_res = op_t_n(t0, n1); + let n_t_res = op_n_t(n0, t1); + let n_n_res = op_n_n(n0, n1); + + // For `f32` and `f64`, NaN values are not considered equal to + // themselves. We store `Option`/`Option` and store + // NaN as `None` so they can still be compared. + let val_or_none = |t: T| (!T::Native::is_nan(t.get())).then(|| t.get()); + let t_t_res = val_or_none(t_t_res); + let t_n_res = val_or_none(t_n_res); + let n_t_res = val_or_none(n_t_res); + let n_n_res = (!T::Native::is_nan(n_n_res)).then(|| n_n_res); + assert_eq!(t_t_res, n_n_res); + assert_eq!(t_n_res, n_n_res); + assert_eq!(n_t_res, n_n_res); + + if let Some((op_assign_t_t, op_assign_t_n, op_assign_n_t)) = &op_assign { + let mut t_t_res = t0; + op_assign_t_t(&mut t_t_res, t1); + let mut t_n_res = t0; + op_assign_t_n(&mut t_n_res, n1); + let mut n_t_res = n0; + op_assign_n_t(&mut n_t_res, t1); + + // For `f32` and `f64`, NaN values are not considered equal to + // themselves. We store `Option`/`Option` and store + // NaN as `None` so they can still be compared. + let t_t_res = val_or_none(t_t_res); + let t_n_res = val_or_none(t_n_res); + let n_t_res = (!T::Native::is_nan(n_t_res)).then(|| n_t_res); + assert_eq!(t_t_res, n_n_res); + assert_eq!(t_n_res, n_n_res); + assert_eq!(n_t_res, n_n_res); + } + } + } + + macro_rules! test { + ( + @binary + $trait:ident, + $method:ident $([$checked_method:ident])?, + $trait_assign:ident, + $method_assign:ident, + $($call_for_macros:ident),* + ) => {{ + fn t() + where + T: ByteOrderType, + T: core::ops::$trait, + T: core::ops::$trait, + T::Native: core::ops::$trait, + T::Native: core::ops::$trait, + + T: core::ops::$trait_assign, + T: core::ops::$trait_assign, + T::Native: core::ops::$trait_assign, + T::Native: core::ops::$trait_assign, + { + test::( + core::ops::$trait::$method, + core::ops::$trait::$method, + core::ops::$trait::$method, + core::ops::$trait::$method, + { + #[allow(unused_mut, unused_assignments)] + let mut op_native_checked = None:: Option>; + $( + op_native_checked = Some(T::Native::$checked_method); + )? + op_native_checked + }, + Some(( + >::$method_assign, + >::$method_assign, + >::$method_assign + )), + ); + } + + $( + $call_for_macros!(t, NativeEndian); + $call_for_macros!(t, NonNativeEndian); + )* + }}; + ( + @unary + $trait:ident, + $method:ident, + $($call_for_macros:ident),* + ) => {{ + fn t() + where + T: ByteOrderType, + T: core::ops::$trait, + T::Native: core::ops::$trait, + { + test::( + |slf, _rhs| core::ops::$trait::$method(slf), + |slf, _rhs| core::ops::$trait::$method(slf), + |slf, _rhs| core::ops::$trait::$method(slf).into(), + |slf, _rhs| core::ops::$trait::$method(slf), + None:: Option>, + None::<(fn(&mut T, T), fn(&mut T, T::Native), fn(&mut T::Native, T))>, + ); + } + + $( + $call_for_macros!(t, NativeEndian); + $call_for_macros!(t, NonNativeEndian); + )* + }}; + } + + test!(@binary Add, add[checked_add], AddAssign, add_assign, call_for_all_types); + test!(@binary Div, div[checked_div], DivAssign, div_assign, call_for_all_types); + test!(@binary Mul, mul[checked_mul], MulAssign, mul_assign, call_for_all_types); + test!(@binary Rem, rem[checked_rem], RemAssign, rem_assign, call_for_all_types); + test!(@binary Sub, sub[checked_sub], SubAssign, sub_assign, call_for_all_types); + + test!(@binary BitAnd, bitand, BitAndAssign, bitand_assign, call_for_unsigned_types, call_for_signed_types); + test!(@binary BitOr, bitor, BitOrAssign, bitor_assign, call_for_unsigned_types, call_for_signed_types); + test!(@binary BitXor, bitxor, BitXorAssign, bitxor_assign, call_for_unsigned_types, call_for_signed_types); + test!(@binary Shl, shl[checked_shl], ShlAssign, shl_assign, call_for_unsigned_types, call_for_signed_types); + test!(@binary Shr, shr[checked_shr], ShrAssign, shr_assign, call_for_unsigned_types, call_for_signed_types); + + test!(@unary Not, not, call_for_signed_types, call_for_unsigned_types); + test!(@unary Neg, neg, call_for_signed_types, call_for_float_types); + } + + #[test] + fn test_debug_impl() { + // Ensure that Debug applies format options to the inner value. + let val = U16::::new(10); + assert_eq!(format!("{:?}", val), "U16(10)"); + assert_eq!(format!("{:03?}", val), "U16(010)"); + assert_eq!(format!("{:x?}", val), "U16(a)"); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/deprecated.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/deprecated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/deprecated.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/deprecated.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,211 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Deprecated items. These are kept separate so that they don't clutter up +//! other modules. + +use super::*; + +impl Ref +where + B: ByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + #[deprecated(since = "0.8.0", note = "renamed to `Ref::from_bytes`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new(bytes: B) -> Option> { + Self::from_bytes(bytes).ok() + } +} + +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + #[deprecated(since = "0.8.0", note = "renamed to `Ref::from_prefix`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_from_prefix(bytes: B) -> Option<(Ref, B)> { + Self::from_prefix(bytes).ok() + } +} + +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + #[deprecated(since = "0.8.0", note = "renamed to `Ref::from_suffix`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_from_suffix(bytes: B) -> Option<(B, Ref)> { + Self::from_suffix(bytes).ok() + } +} + +impl Ref +where + B: ByteSlice, + T: Unaligned + KnownLayout + Immutable + ?Sized, +{ + #[deprecated( + since = "0.8.0", + note = "use `Ref::from_bytes`; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_unaligned(bytes: B) -> Option> { + Self::from_bytes(bytes).ok() + } +} + +impl Ref +where + B: SplitByteSlice, + T: Unaligned + KnownLayout + Immutable + ?Sized, +{ + #[deprecated( + since = "0.8.0", + note = "use `Ref::from_prefix`; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_unaligned_from_prefix(bytes: B) -> Option<(Ref, B)> { + Self::from_prefix(bytes).ok() + } +} + +impl Ref +where + B: SplitByteSlice, + T: Unaligned + KnownLayout + Immutable + ?Sized, +{ + #[deprecated( + since = "0.8.0", + note = "use `Ref::from_suffix`; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_unaligned_from_suffix(bytes: B) -> Option<(B, Ref)> { + Self::from_suffix(bytes).ok() + } +} + +impl Ref +where + B: ByteSlice, + T: Immutable, +{ + #[deprecated(since = "0.8.0", note = "`Ref::from_bytes` now supports slices")] + #[doc(hidden)] + #[inline(always)] + pub fn new_slice(bytes: B) -> Option> { + Self::from_bytes(bytes).ok() + } +} + +impl Ref +where + B: ByteSlice, + T: Unaligned + Immutable, +{ + #[deprecated( + since = "0.8.0", + note = "`Ref::from_bytes` now supports slices; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[inline(always)] + pub fn new_slice_unaligned(bytes: B) -> Option> { + Ref::from_bytes(bytes).ok() + } +} + +impl<'a, B, T> Ref +where + B: 'a + IntoByteSlice<'a>, + T: FromBytes + Immutable, +{ + #[deprecated(since = "0.8.0", note = "`Ref::into_ref` now supports slices")] + #[doc(hidden)] + #[inline(always)] + pub fn into_slice(self) -> &'a [T] { + Ref::into_ref(self) + } +} + +impl<'a, B, T> Ref +where + B: 'a + IntoByteSliceMut<'a>, + T: FromBytes + IntoBytes + Immutable, +{ + #[deprecated(since = "0.8.0", note = "`Ref::into_mut` now supports slices")] + #[doc(hidden)] + #[inline(always)] + pub fn into_mut_slice(self) -> &'a mut [T] { + Ref::into_mut(self) + } +} + +impl Ref +where + B: SplitByteSlice, + T: Immutable, +{ + #[deprecated(since = "0.8.0", note = "replaced by `Ref::from_prefix_with_elems`")] + #[must_use = "has no side effects"] + #[doc(hidden)] + #[inline(always)] + pub fn new_slice_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { + Ref::from_prefix_with_elems(bytes, count).ok() + } + + #[deprecated(since = "0.8.0", note = "replaced by `Ref::from_suffix_with_elems`")] + #[must_use = "has no side effects"] + #[doc(hidden)] + #[inline(always)] + pub fn new_slice_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { + Ref::from_suffix_with_elems(bytes, count).ok() + } +} + +impl Ref +where + B: SplitByteSlice, + T: Unaligned + Immutable, +{ + #[deprecated( + since = "0.8.0", + note = "use `Ref::from_prefix_with_elems`; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_slice_unaligned_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { + Ref::from_prefix_with_elems(bytes, count).ok() + } + + #[deprecated( + since = "0.8.0", + note = "use `Ref::from_suffix_with_elems`; for `T: Unaligned`, the returned `CastError` implements `Into`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_slice_unaligned_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { + Ref::from_suffix_with_elems(bytes, count).ok() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/doctests.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/doctests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/doctests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/doctests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +// Copyright 2025 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#![cfg(feature = "derive")] // Required for derives on `SliceDst` +#![allow(dead_code)] + +//! Our UI test framework, built on the `trybuild` crate, does not support +//! testing for post-monomorphization errors. Instead, we use doctests, which +//! are able to test for post-monomorphization errors. + +use crate::*; + +#[derive(KnownLayout, FromBytes, IntoBytes, Immutable)] +#[repr(C)] +#[allow(missing_debug_implementations, missing_copy_implementations)] +pub struct SliceDst { + pub t: T, + pub u: [U], +} + +#[allow(clippy::must_use_candidate, clippy::missing_inline_in_public_items, clippy::todo)] +impl SliceDst { + pub fn new() -> &'static SliceDst { + todo!() + } + + pub fn new_mut() -> &'static mut SliceDst { + todo!() + } +} + +/// We require that the alignment of the destination type is not larger than the +/// alignment of the source type. +/// +/// ```compile_fail,E0080 +/// let increase_alignment: &u16 = zerocopy::transmute_ref!(&[0u8; 2]); +/// ``` +/// +/// ```compile_fail,E0080 +/// let mut src = [0u8; 2]; +/// let increase_alignment: &mut u16 = zerocopy::transmute_mut!(&mut src); +/// ``` +enum TransmuteRefMutAlignmentIncrease {} + +/// We require that the size of the destination type is not larger than the size +/// of the source type. +/// +/// ```compile_fail,E0080 +/// let increase_size: &[u8; 2] = zerocopy::transmute_ref!(&0u8); +/// ``` +/// +/// ```compile_fail,E0080 +/// let mut src = 0u8; +/// let increase_size: &mut [u8; 2] = zerocopy::transmute_mut!(&mut src); +/// ``` +enum TransmuteRefMutSizeIncrease {} + +/// We require that the size of the destination type is not smaller than the +/// size of the source type. +/// +/// ```compile_fail,E0080 +/// let decrease_size: &u8 = zerocopy::transmute_ref!(&[0u8; 2]); +/// ``` +/// +/// ```compile_fail,E0080 +/// let mut src = [0u8; 2]; +/// let decrease_size: &mut u8 = zerocopy::transmute_mut!(&mut src); +/// ``` +enum TransmuteRefMutSizeDecrease {} + +/// It's not possible in the general case to increase the trailing slice offset +/// during a reference transmutation - some pointer metadata values would not be +/// supportable, and so such a transmutation would be fallible. +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &SliceDst = SliceDst::new(); +/// let increase_offset: &SliceDst<[u8; 2], u8> = zerocopy::transmute_ref!(src); +/// ``` +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &mut SliceDst = SliceDst::new_mut(); +/// let increase_offset: &mut SliceDst<[u8; 2], u8> = zerocopy::transmute_mut!(src); +/// ``` +enum TransmuteRefMutDstOffsetIncrease {} + +/// Reference transmutes are not possible when the difference between the source +/// and destination types' trailing slice offsets is not a multiple of the +/// destination type's trailing slice element size. +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &SliceDst<[u8; 3], [u8; 2]> = SliceDst::new(); +/// let _: &SliceDst<[u8; 2], [u8; 2]> = zerocopy::transmute_ref!(src); +/// ``` +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &mut SliceDst<[u8; 3], [u8; 2]> = SliceDst::new_mut(); +/// let _: &mut SliceDst<[u8; 2], [u8; 2]> = zerocopy::transmute_mut!(src); +/// ``` +enum TransmuteRefMutDstOffsetNotMultiple {} + +/// Reference transmutes are not possible when the source's trailing slice +/// element size is not a multiple of the destination's. +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &SliceDst<(), [u8; 3]> = SliceDst::new(); +/// let _: &SliceDst<(), [u8; 2]> = zerocopy::transmute_ref!(src); +/// ``` +/// +/// ```compile_fail,E0080 +/// use zerocopy::doctests::SliceDst; +/// let src: &mut SliceDst<(), [u8; 3]> = SliceDst::new_mut(); +/// let _: &mut SliceDst<(), [u8; 2]> = zerocopy::transmute_mut!(src); +/// ``` +enum TransmuteRefMutDstElemSizeNotMultiple {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1081 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Types related to error reporting. +//! +//! ## Single failure mode errors +//! +//! Generally speaking, zerocopy's conversions may fail for one of up to three +//! reasons: +//! - [`AlignmentError`]: the conversion source was improperly aligned +//! - [`SizeError`]: the conversion source was of incorrect size +//! - [`ValidityError`]: the conversion source contained invalid data +//! +//! Methods that only have one failure mode, like +//! [`FromBytes::read_from_bytes`], return that mode's corresponding error type +//! directly. +//! +//! ## Compound errors +//! +//! Conversion methods that have either two or three possible failure modes +//! return one of these error types: +//! - [`CastError`]: the error type of reference conversions +//! - [`TryCastError`]: the error type of fallible reference conversions +//! - [`TryReadError`]: the error type of fallible read conversions +//! +//! ## [`Unaligned`] destination types +//! +//! For [`Unaligned`] destination types, alignment errors are impossible. All +//! compound error types support infallibly discarding the alignment error via +//! [`From`] so long as `Dst: Unaligned`. For example, see [`>::from`][size-error-from]. +//! +//! [size-error-from]: struct.SizeError.html#method.from-1 +//! +//! ## Accessing the conversion source +//! +//! All error types provide an `into_src` method that converts the error into +//! the source value underlying the failed conversion. +//! +//! ## Display formatting +//! +//! All error types provide a `Display` implementation that produces a +//! human-readable error message. When `debug_assertions` are enabled, these +//! error messages are verbose and may include potentially sensitive +//! information, including: +//! +//! - the names of the involved types +//! - the sizes of the involved types +//! - the addresses of the involved types +//! - the contents of the involved types +//! +//! When `debug_assertions` are disabled (as is default for `release` builds), +//! such potentially sensitive information is excluded. +//! +//! In the future, we may support manually configuring this behavior. If you are +//! interested in this feature, [let us know on GitHub][issue-1457] so we know +//! to prioritize it. +//! +//! [issue-1457]: https://github.com/google/zerocopy/issues/1457 +//! +//! ## Validation order +//! +//! Our conversion methods typically check alignment, then size, then bit +//! validity. However, we do not guarantee that this is always the case, and +//! this behavior may change between releases. +//! +//! ## `Send`, `Sync`, and `'static` +//! +//! Our error types are `Send`, `Sync`, and `'static` when their `Src` parameter +//! is `Send`, `Sync`, or `'static`, respectively. This can cause issues when an +//! error is sent or synchronized across threads; e.g.: +//! +//! ```compile_fail,E0515 +//! use zerocopy::*; +//! +//! let result: SizeError<&[u8], u32> = std::thread::spawn(|| { +//! let source = &mut [0u8, 1, 2][..]; +//! // Try (and fail) to read a `u32` from `source`. +//! u32::read_from_bytes(source).unwrap_err() +//! }).join().unwrap(); +//! ``` +//! +//! To work around this, use [`map_src`][CastError::map_src] to convert the +//! source parameter to an unproblematic type; e.g.: +//! +//! ``` +//! use zerocopy::*; +//! +//! let result: SizeError<(), u32> = std::thread::spawn(|| { +//! let source = &mut [0u8, 1, 2][..]; +//! // Try (and fail) to read a `u32` from `source`. +//! u32::read_from_bytes(source).unwrap_err() +//! // Erase the error source. +//! .map_src(drop) +//! }).join().unwrap(); +//! ``` +//! +//! Alternatively, use `.to_string()` to eagerly convert the error into a +//! human-readable message; e.g.: +//! +//! ``` +//! use zerocopy::*; +//! +//! let result: Result = std::thread::spawn(|| { +//! let source = &mut [0u8, 1, 2][..]; +//! // Try (and fail) to read a `u32` from `source`. +//! u32::read_from_bytes(source) +//! // Eagerly render the error message. +//! .map_err(|err| err.to_string()) +//! }).join().unwrap(); +//! ``` +#[cfg(zerocopy_core_error_1_81_0)] +use core::error::Error; +use core::{ + convert::Infallible, + fmt::{self, Debug, Write}, + ops::Deref, +}; +#[cfg(all(not(zerocopy_core_error_1_81_0), any(feature = "std", test)))] +use std::error::Error; + +use crate::{util::SendSyncPhantomData, KnownLayout, TryFromBytes, Unaligned}; +#[cfg(doc)] +use crate::{FromBytes, Ref}; + +/// Zerocopy's generic error type. +/// +/// Generally speaking, zerocopy's conversions may fail for one of up to three +/// reasons: +/// - [`AlignmentError`]: the conversion source was improperly aligned +/// - [`SizeError`]: the conversion source was of incorrect size +/// - [`ValidityError`]: the conversion source contained invalid data +/// +/// However, not all conversions produce all errors. For instance, +/// [`FromBytes::ref_from_bytes`] may fail due to alignment or size issues, but +/// not validity issues. This generic error type captures these +/// (im)possibilities via parameterization: `A` is parameterized with +/// [`AlignmentError`], `S` is parameterized with [`SizeError`], and `V` is +/// parameterized with [`Infallible`]. +/// +/// Zerocopy never uses this type directly in its API. Rather, we provide three +/// pre-parameterized aliases: +/// - [`CastError`]: the error type of reference conversions +/// - [`TryCastError`]: the error type of fallible reference conversions +/// - [`TryReadError`]: the error type of fallible read conversions +#[derive(PartialEq, Eq)] +pub enum ConvertError { + /// The conversion source was improperly aligned. + Alignment(A), + /// The conversion source was of incorrect size. + Size(S), + /// The conversion source contained invalid data. + Validity(V), +} + +impl From, S, V>> + for ConvertError +{ + /// Infallibly discards the alignment error from this `ConvertError` since + /// `Dst` is unaligned. + /// + /// Since [`Dst: Unaligned`], it is impossible to encounter an alignment + /// error. This method permits discarding that alignment error infallibly + /// and replacing it with [`Infallible`]. + /// + /// [`Dst: Unaligned`]: crate::Unaligned + /// + /// # Examples + /// + /// ``` + /// use core::convert::Infallible; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, KnownLayout, Unaligned, Immutable)] + /// #[repr(C, packed)] + /// struct Bools { + /// one: bool, + /// two: bool, + /// many: [bool], + /// } + /// + /// impl Bools { + /// fn parse(bytes: &[u8]) -> Result<&Bools, AlignedTryCastError<&[u8], Bools>> { + /// // Since `Bools: Unaligned`, we can infallibly discard + /// // the alignment error. + /// Bools::try_ref_from_bytes(bytes).map_err(Into::into) + /// } + /// } + /// ``` + #[inline] + fn from(err: ConvertError, S, V>) -> ConvertError { + match err { + ConvertError::Alignment(e) => ConvertError::Alignment(Infallible::from(e)), + ConvertError::Size(e) => ConvertError::Size(e), + ConvertError::Validity(e) => ConvertError::Validity(e), + } + } +} + +impl fmt::Debug for ConvertError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Alignment(e) => f.debug_tuple("Alignment").field(e).finish(), + Self::Size(e) => f.debug_tuple("Size").field(e).finish(), + Self::Validity(e) => f.debug_tuple("Validity").field(e).finish(), + } + } +} + +/// Produces a human-readable error message. +/// +/// The message differs between debug and release builds. When +/// `debug_assertions` are enabled, this message is verbose and includes +/// potentially sensitive information. +impl fmt::Display for ConvertError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Alignment(e) => e.fmt(f), + Self::Size(e) => e.fmt(f), + Self::Validity(e) => e.fmt(f), + } + } +} + +#[cfg(any(zerocopy_core_error_1_81_0, feature = "std", test))] +#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] +impl Error for ConvertError +where + A: fmt::Display + fmt::Debug, + S: fmt::Display + fmt::Debug, + V: fmt::Display + fmt::Debug, +{ +} + +/// The error emitted if the conversion source is improperly aligned. +#[derive(PartialEq, Eq)] +pub struct AlignmentError { + /// The source value involved in the conversion. + src: Src, + /// The inner destination type inolved in the conversion. + /// + /// INVARIANT: An `AlignmentError` may only be constructed if `Dst`'s + /// alignment requirement is greater than one. + dst: SendSyncPhantomData, +} + +impl AlignmentError { + /// # Safety + /// + /// The caller must ensure that `Dst`'s alignment requirement is greater + /// than one. + pub(crate) unsafe fn new_unchecked(src: Src) -> Self { + // INVARIANT: The caller guarantees that `Dst`'s alignment requirement + // is greater than one. + Self { src, dst: SendSyncPhantomData::default() } + } + + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + self.src + } + + pub(crate) fn with_src(self, new_src: NewSrc) -> AlignmentError { + // INVARIANT: `with_src` doesn't change the type of `Dst`, so the + // invariant that `Dst`'s alignment requirement is greater than one is + // preserved. + AlignmentError { src: new_src, dst: SendSyncPhantomData::default() } + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::*; + /// + /// let unaligned = Unalign::new(0u16); + /// + /// // Attempt to deref `unaligned`. This might fail with an alignment error. + /// let maybe_n: Result<&u16, AlignmentError<&Unalign, u16>> = unaligned.try_deref(); + /// + /// // Map the error's source to its address as a usize. + /// let maybe_n: Result<&u16, AlignmentError> = maybe_n.map_err(|err| { + /// err.map_src(|src| src as *const _ as usize) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> AlignmentError { + AlignmentError { src: f(self.src), dst: SendSyncPhantomData::default() } + } + + pub(crate) fn into(self) -> ConvertError { + ConvertError::Alignment(self) + } + + /// Format extra details for a verbose, human-readable error message. + /// + /// This formatting may include potentially sensitive information. + fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + where + Src: Deref, + Dst: KnownLayout, + { + #[allow(clippy::as_conversions)] + let addr = self.src.deref() as *const _ as *const (); + let addr_align = 2usize.pow((crate::util::AsAddress::addr(addr)).trailing_zeros()); + + f.write_str("\n\nSource type: ")?; + f.write_str(core::any::type_name::())?; + + f.write_str("\nSource address: ")?; + addr.fmt(f)?; + f.write_str(" (a multiple of ")?; + addr_align.fmt(f)?; + f.write_str(")")?; + + f.write_str("\nDestination type: ")?; + f.write_str(core::any::type_name::())?; + + f.write_str("\nDestination alignment: ")?; + ::LAYOUT.align.get().fmt(f)?; + + Ok(()) + } +} + +impl From> for Infallible { + #[inline(always)] + fn from(_: AlignmentError) -> Infallible { + // SAFETY: `AlignmentError`s can only be constructed when `Dst`'s + // alignment requirement is greater than one. In this block, `Dst: + // Unaligned`, which means that its alignment requirement is equal to + // one. Thus, it's not possible to reach here at runtime. + unsafe { core::hint::unreachable_unchecked() } + } +} + +#[cfg(test)] +impl AlignmentError { + // A convenience constructor so that test code doesn't need to write + // `unsafe`. + fn new_checked(src: Src) -> AlignmentError { + assert_ne!(core::mem::align_of::(), 1); + // SAFETY: The preceding assertion guarantees that `Dst`'s alignment + // requirement is greater than one. + unsafe { AlignmentError::new_unchecked(src) } + } +} + +impl fmt::Debug for AlignmentError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AlignmentError").finish() + } +} + +/// Produces a human-readable error message. +/// +/// The message differs between debug and release builds. When +/// `debug_assertions` are enabled, this message is verbose and includes +/// potentially sensitive information. +impl fmt::Display for AlignmentError +where + Src: Deref, + Dst: KnownLayout, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.")?; + + if cfg!(debug_assertions) { + self.display_verbose_extras(f) + } else { + Ok(()) + } + } +} + +#[cfg(any(zerocopy_core_error_1_81_0, feature = "std", test))] +#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] +impl Error for AlignmentError +where + Src: Deref, + Dst: KnownLayout, +{ +} + +impl From> + for ConvertError, S, V> +{ + #[inline(always)] + fn from(err: AlignmentError) -> Self { + Self::Alignment(err) + } +} + +/// The error emitted if the conversion source is of incorrect size. +#[derive(PartialEq, Eq)] +pub struct SizeError { + /// The source value involved in the conversion. + src: Src, + /// The inner destination type inolved in the conversion. + dst: SendSyncPhantomData, +} + +impl SizeError { + pub(crate) fn new(src: Src) -> Self { + Self { src, dst: SendSyncPhantomData::default() } + } + + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + self.src + } + + /// Sets the source value associated with the conversion error. + pub(crate) fn with_src(self, new_src: NewSrc) -> SizeError { + SizeError { src: new_src, dst: SendSyncPhantomData::default() } + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::*; + /// + /// let source: [u8; 3] = [0, 1, 2]; + /// + /// // Try to read a `u32` from `source`. This will fail because there are insufficient + /// // bytes in `source`. + /// let maybe_u32: Result> = u32::read_from_bytes(&source[..]); + /// + /// // Map the error's source to its size. + /// let maybe_u32: Result> = maybe_u32.map_err(|err| { + /// err.map_src(|src| src.len()) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> SizeError { + SizeError { src: f(self.src), dst: SendSyncPhantomData::default() } + } + + /// Sets the destination type associated with the conversion error. + pub(crate) fn with_dst(self) -> SizeError { + SizeError { src: self.src, dst: SendSyncPhantomData::default() } + } + + /// Converts the error into a general [`ConvertError`]. + pub(crate) fn into(self) -> ConvertError { + ConvertError::Size(self) + } + + /// Format extra details for a verbose, human-readable error message. + /// + /// This formatting may include potentially sensitive information. + fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + where + Src: Deref, + Dst: KnownLayout, + { + // include the source type + f.write_str("\nSource type: ")?; + f.write_str(core::any::type_name::())?; + + // include the source.deref() size + let src_size = core::mem::size_of_val(&*self.src); + f.write_str("\nSource size: ")?; + src_size.fmt(f)?; + f.write_str(" byte")?; + if src_size != 1 { + f.write_char('s')?; + } + + // if `Dst` is `Sized`, include the `Dst` size + if let crate::SizeInfo::Sized { size } = Dst::LAYOUT.size_info { + f.write_str("\nDestination size: ")?; + size.fmt(f)?; + f.write_str(" byte")?; + if size != 1 { + f.write_char('s')?; + } + } + + // include the destination type + f.write_str("\nDestination type: ")?; + f.write_str(core::any::type_name::())?; + + Ok(()) + } +} + +impl fmt::Debug for SizeError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SizeError").finish() + } +} + +/// Produces a human-readable error message. +/// +/// The message differs between debug and release builds. When +/// `debug_assertions` are enabled, this message is verbose and includes +/// potentially sensitive information. +impl fmt::Display for SizeError +where + Src: Deref, + Dst: KnownLayout, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.")?; + if cfg!(debug_assertions) { + f.write_str("\n")?; + self.display_verbose_extras(f)?; + } + Ok(()) + } +} + +#[cfg(any(zerocopy_core_error_1_81_0, feature = "std", test))] +#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] +impl Error for SizeError +where + Src: Deref, + Dst: KnownLayout, +{ +} + +impl From> for ConvertError, V> { + #[inline(always)] + fn from(err: SizeError) -> Self { + Self::Size(err) + } +} + +/// The error emitted if the conversion source contains invalid data. +#[derive(PartialEq, Eq)] +pub struct ValidityError { + /// The source value involved in the conversion. + pub(crate) src: Src, + /// The inner destination type inolved in the conversion. + dst: SendSyncPhantomData, +} + +impl ValidityError { + pub(crate) fn new(src: Src) -> Self { + Self { src, dst: SendSyncPhantomData::default() } + } + + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + self.src + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::*; + /// + /// let source: u8 = 42; + /// + /// // Try to transmute the `source` to a `bool`. This will fail. + /// let maybe_bool: Result> = try_transmute!(source); + /// + /// // Drop the error's source. + /// let maybe_bool: Result> = maybe_bool.map_err(|err| { + /// err.map_src(drop) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> ValidityError { + ValidityError { src: f(self.src), dst: SendSyncPhantomData::default() } + } + + /// Converts the error into a general [`ConvertError`]. + pub(crate) fn into(self) -> ConvertError { + ConvertError::Validity(self) + } + + /// Format extra details for a verbose, human-readable error message. + /// + /// This formatting may include potentially sensitive information. + fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + where + Dst: KnownLayout, + { + f.write_str("Destination type: ")?; + f.write_str(core::any::type_name::())?; + Ok(()) + } +} + +impl fmt::Debug for ValidityError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ValidityError").finish() + } +} + +/// Produces a human-readable error message. +/// +/// The message differs between debug and release builds. When +/// `debug_assertions` are enabled, this message is verbose and includes +/// potentially sensitive information. +impl fmt::Display for ValidityError +where + Dst: KnownLayout + TryFromBytes, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("The conversion failed because the source bytes are not a valid value of the destination type.")?; + if cfg!(debug_assertions) { + f.write_str("\n\n")?; + self.display_verbose_extras(f)?; + } + Ok(()) + } +} + +#[cfg(any(zerocopy_core_error_1_81_0, feature = "std", test))] +#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] +impl Error for ValidityError where Dst: KnownLayout + TryFromBytes {} + +impl From> + for ConvertError> +{ + #[inline(always)] + fn from(err: ValidityError) -> Self { + Self::Validity(err) + } +} + +/// The error type of reference conversions. +/// +/// Reference conversions, like [`FromBytes::ref_from_bytes`] may emit +/// [alignment](AlignmentError) and [size](SizeError) errors. +// Bounds on generic parameters are not enforced in type aliases, but they do +// appear in rustdoc. +#[allow(type_alias_bounds)] +pub type CastError = + ConvertError, SizeError, Infallible>; + +impl CastError { + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + match self { + Self::Alignment(e) => e.src, + Self::Size(e) => e.src, + Self::Validity(i) => match i {}, + } + } + + /// Sets the source value associated with the conversion error. + pub(crate) fn with_src(self, new_src: NewSrc) -> CastError { + match self { + Self::Alignment(e) => CastError::Alignment(e.with_src(new_src)), + Self::Size(e) => CastError::Size(e.with_src(new_src)), + Self::Validity(i) => match i {}, + } + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::*; + /// + /// let source: [u8; 3] = [0, 1, 2]; + /// + /// // Try to read a `u32` from `source`. This will fail because there are insufficient + /// // bytes in `source`. + /// let maybe_u32: Result<&u32, CastError<&[u8], u32>> = u32::ref_from_bytes(&source[..]); + /// + /// // Map the error's source to its size and address. + /// let maybe_u32: Result<&u32, CastError<(usize, usize), u32>> = maybe_u32.map_err(|err| { + /// err.map_src(|src| (src.len(), src.as_ptr() as usize)) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> CastError { + match self { + Self::Alignment(e) => CastError::Alignment(e.map_src(f)), + Self::Size(e) => CastError::Size(e.map_src(f)), + Self::Validity(i) => match i {}, + } + } + + /// Converts the error into a general [`ConvertError`]. + pub(crate) fn into(self) -> TryCastError + where + Dst: TryFromBytes, + { + match self { + Self::Alignment(e) => TryCastError::Alignment(e), + Self::Size(e) => TryCastError::Size(e), + Self::Validity(i) => match i {}, + } + } +} + +impl From> for SizeError { + /// Infallibly extracts the [`SizeError`] from this `CastError` since `Dst` + /// is unaligned. + /// + /// Since [`Dst: Unaligned`], it is impossible to encounter an alignment + /// error, and so the only error that can be encountered at runtime is a + /// [`SizeError`]. This method permits extracting that `SizeError` + /// infallibly. + /// + /// [`Dst: Unaligned`]: crate::Unaligned + /// + /// # Examples + /// + /// ```rust + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] + /// #[repr(C)] + /// struct UdpHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] + /// #[repr(C, packed)] + /// struct UdpPacket { + /// header: UdpHeader, + /// body: [u8], + /// } + /// + /// impl UdpPacket { + /// pub fn parse(bytes: &[u8]) -> Result<&UdpPacket, SizeError<&[u8], UdpPacket>> { + /// // Since `UdpPacket: Unaligned`, we can map the `CastError` to a `SizeError`. + /// UdpPacket::ref_from_bytes(bytes).map_err(Into::into) + /// } + /// } + /// ``` + #[inline(always)] + fn from(err: CastError) -> SizeError { + match err { + #[allow(unreachable_code)] + CastError::Alignment(e) => match Infallible::from(e) {}, + CastError::Size(e) => e, + CastError::Validity(i) => match i {}, + } + } +} + +/// The error type of fallible reference conversions. +/// +/// Fallible reference conversions, like [`TryFromBytes::try_ref_from_bytes`] +/// may emit [alignment](AlignmentError), [size](SizeError), and +/// [validity](ValidityError) errors. +// Bounds on generic parameters are not enforced in type aliases, but they do +// appear in rustdoc. +#[allow(type_alias_bounds)] +pub type TryCastError = + ConvertError, SizeError, ValidityError>; + +// FIXME(#1139): Remove the `TryFromBytes` here and in other downstream +// locations (all the way to `ValidityError`) if we determine it's not necessary +// for rich validity errors. +impl TryCastError { + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + match self { + Self::Alignment(e) => e.src, + Self::Size(e) => e.src, + Self::Validity(e) => e.src, + } + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use core::num::NonZeroU32; + /// use zerocopy::*; + /// + /// let source: [u8; 3] = [0, 0, 0]; + /// + /// // Try to read a `NonZeroU32` from `source`. + /// let maybe_u32: Result<&NonZeroU32, TryCastError<&[u8], NonZeroU32>> + /// = NonZeroU32::try_ref_from_bytes(&source[..]); + /// + /// // Map the error's source to its size and address. + /// let maybe_u32: Result<&NonZeroU32, TryCastError<(usize, usize), NonZeroU32>> = + /// maybe_u32.map_err(|err| { + /// err.map_src(|src| (src.len(), src.as_ptr() as usize)) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> TryCastError { + match self { + Self::Alignment(e) => TryCastError::Alignment(e.map_src(f)), + Self::Size(e) => TryCastError::Size(e.map_src(f)), + Self::Validity(e) => TryCastError::Validity(e.map_src(f)), + } + } +} + +impl From> for TryCastError { + #[inline] + fn from(value: CastError) -> Self { + match value { + CastError::Alignment(e) => Self::Alignment(e), + CastError::Size(e) => Self::Size(e), + CastError::Validity(i) => match i {}, + } + } +} + +/// The error type of fallible read-conversions. +/// +/// Fallible read-conversions, like [`TryFromBytes::try_read_from_bytes`] may emit +/// [size](SizeError) and [validity](ValidityError) errors, but not alignment errors. +// Bounds on generic parameters are not enforced in type aliases, but they do +// appear in rustdoc. +#[allow(type_alias_bounds)] +pub type TryReadError = + ConvertError, ValidityError>; + +impl TryReadError { + /// Produces the source underlying the failed conversion. + #[inline] + pub fn into_src(self) -> Src { + match self { + Self::Alignment(i) => match i {}, + Self::Size(e) => e.src, + Self::Validity(e) => e.src, + } + } + + /// Maps the source value associated with the conversion error. + /// + /// This can help mitigate [issues with `Send`, `Sync` and `'static` + /// bounds][self#send-sync-and-static]. + /// + /// # Examples + /// + /// ``` + /// use core::num::NonZeroU32; + /// use zerocopy::*; + /// + /// let source: [u8; 3] = [0, 0, 0]; + /// + /// // Try to read a `NonZeroU32` from `source`. + /// let maybe_u32: Result> + /// = NonZeroU32::try_read_from_bytes(&source[..]); + /// + /// // Map the error's source to its size. + /// let maybe_u32: Result> = + /// maybe_u32.map_err(|err| { + /// err.map_src(|src| src.len()) + /// }); + /// ``` + #[inline] + pub fn map_src(self, f: impl FnOnce(Src) -> NewSrc) -> TryReadError { + match self { + Self::Alignment(i) => match i {}, + Self::Size(e) => TryReadError::Size(e.map_src(f)), + Self::Validity(e) => TryReadError::Validity(e.map_src(f)), + } + } +} + +/// The error type of well-aligned, fallible casts. +/// +/// This is like [`TryCastError`], but for casts that are always well-aligned. +/// It is identical to `TryCastError`, except that its alignment error is +/// [`Infallible`]. +/// +/// As of this writing, none of zerocopy's API produces this error directly. +/// However, it is useful since it permits users to infallibly discard alignment +/// errors when they can prove statically that alignment errors are impossible. +/// +/// # Examples +/// +/// ``` +/// use core::convert::Infallible; +/// use zerocopy::*; +/// # use zerocopy_derive::*; +/// +/// #[derive(TryFromBytes, KnownLayout, Unaligned, Immutable)] +/// #[repr(C, packed)] +/// struct Bools { +/// one: bool, +/// two: bool, +/// many: [bool], +/// } +/// +/// impl Bools { +/// fn parse(bytes: &[u8]) -> Result<&Bools, AlignedTryCastError<&[u8], Bools>> { +/// // Since `Bools: Unaligned`, we can infallibly discard +/// // the alignment error. +/// Bools::try_ref_from_bytes(bytes).map_err(Into::into) +/// } +/// } +/// ``` +#[allow(type_alias_bounds)] +pub type AlignedTryCastError = + ConvertError, ValidityError>; + +/// The error type of a failed allocation. +/// +/// This type is intended to be deprecated in favor of the standard library's +/// [`AllocError`] type once it is stabilized. When that happens, this type will +/// be replaced by a type alias to the standard library type. We do not intend +/// to treat this as a breaking change; users who wish to avoid breakage should +/// avoid writing code which assumes that this is *not* such an alias. For +/// example, implementing the same trait for both types will result in an impl +/// conflict once this type is an alias. +/// +/// [`AllocError`]: https://doc.rust-lang.org/alloc/alloc/struct.AllocError.html +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct AllocError; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_send_sync() { + // Test that all error types are `Send + Sync` even if `Dst: !Send + + // !Sync`. + + #[allow(dead_code)] + fn is_send_sync(_t: T) {} + + #[allow(dead_code)] + fn alignment_err_is_send_sync(err: AlignmentError) { + is_send_sync(err) + } + + #[allow(dead_code)] + fn size_err_is_send_sync(err: SizeError) { + is_send_sync(err) + } + + #[allow(dead_code)] + fn validity_err_is_send_sync( + err: ValidityError, + ) { + is_send_sync(err) + } + + #[allow(dead_code)] + fn convert_error_is_send_sync( + err: ConvertError< + AlignmentError, + SizeError, + ValidityError, + >, + ) { + is_send_sync(err) + } + } + + #[test] + fn alignment_display() { + #[repr(C, align(128))] + struct Aligned { + bytes: [u8; 128], + } + + impl_known_layout!(elain::Align::<8>); + + let aligned = Aligned { bytes: [0; 128] }; + + let bytes = &aligned.bytes[1..]; + let addr = crate::util::AsAddress::addr(bytes); + assert_eq!( + AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), + format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ + \nSource type: &[u8]\ + \nSource address: 0x{:x} (a multiple of 1)\ + \nDestination type: elain::Align<8>\ + \nDestination alignment: 8", addr) + ); + + let bytes = &aligned.bytes[2..]; + let addr = crate::util::AsAddress::addr(bytes); + assert_eq!( + AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), + format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ + \nSource type: &[u8]\ + \nSource address: 0x{:x} (a multiple of 2)\ + \nDestination type: elain::Align<8>\ + \nDestination alignment: 8", addr) + ); + + let bytes = &aligned.bytes[3..]; + let addr = crate::util::AsAddress::addr(bytes); + assert_eq!( + AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), + format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ + \nSource type: &[u8]\ + \nSource address: 0x{:x} (a multiple of 1)\ + \nDestination type: elain::Align<8>\ + \nDestination alignment: 8", addr) + ); + + let bytes = &aligned.bytes[4..]; + let addr = crate::util::AsAddress::addr(bytes); + assert_eq!( + AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), + format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ + \nSource type: &[u8]\ + \nSource address: 0x{:x} (a multiple of 4)\ + \nDestination type: elain::Align<8>\ + \nDestination alignment: 8", addr) + ); + } + + #[test] + fn size_display() { + assert_eq!( + SizeError::<_, [u8]>::new(&[0u8; 2][..]).to_string(), + "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\ + \nSource type: &[u8]\ + \nSource size: 2 bytes\ + \nDestination type: [u8]" + ); + + assert_eq!( + SizeError::<_, [u8; 2]>::new(&[0u8; 1][..]).to_string(), + "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\ + \nSource type: &[u8]\ + \nSource size: 1 byte\ + \nDestination size: 2 bytes\ + \nDestination type: [u8; 2]" + ); + } + + #[test] + fn validity_display() { + assert_eq!( + ValidityError::<_, bool>::new(&[2u8; 1][..]).to_string(), + "The conversion failed because the source bytes are not a valid value of the destination type.\n\ + \n\ + Destination type: bool" + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/impls.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2081 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{ + cell::{Cell, UnsafeCell}, + mem::MaybeUninit as CoreMaybeUninit, + ptr::NonNull, +}; + +use super::*; + +// SAFETY: Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a +// zero-sized type to have a size of 0 and an alignment of 1." +// - `Immutable`: `()` self-evidently does not contain any `UnsafeCell`s. +// - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: There is only +// one possible sequence of 0 bytes, and `()` is inhabited. +// - `IntoBytes`: Since `()` has size 0, it contains no padding bytes. +// - `Unaligned`: `()` has alignment 1. +// +// [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#tuple-layout +const _: () = unsafe { + unsafe_impl!((): Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_unaligned!(()); +}; + +// SAFETY: +// - `Immutable`: These types self-evidently do not contain any `UnsafeCell`s. +// - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: all bit +// patterns are valid for numeric types [1] +// - `IntoBytes`: numeric types have no padding bytes [1] +// - `Unaligned` (`u8` and `i8` only): The reference [2] specifies the size of +// `u8` and `i8` as 1 byte. We also know that: +// - Alignment is >= 1 [3] +// - Size is an integer multiple of alignment [4] +// - The only value >= 1 for which 1 is an integer multiple is 1 Therefore, +// the only possible alignment for `u8` and `i8` is 1. +// +// [1] Per https://doc.rust-lang.org/1.81.0/reference/types/numeric.html#bit-validity: +// +// For every numeric type, `T`, the bit validity of `T` is equivalent to +// the bit validity of `[u8; size_of::()]`. An uninitialized byte is +// not a valid `u8`. +// +// [2] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#primitive-data-layout +// +// [3] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: +// +// Alignment is measured in bytes, and must be at least 1. +// +// [4] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: +// +// The size of a value is always a multiple of its alignment. +// +// FIXME(#278): Once we've updated the trait docs to refer to `u8`s rather than +// bits or bytes, update this comment, especially the reference to [1]. +const _: () = unsafe { + unsafe_impl!(u8: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + unsafe_impl!(i8: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_unaligned!(u8, i8); + unsafe_impl!(u16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(i16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(u32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(i32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(u64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(i64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(u128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(i128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(usize: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(isize: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(f32: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(f64: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + #[cfg(feature = "float-nightly")] + unsafe_impl!(#[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] f16: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); + #[cfg(feature = "float-nightly")] + unsafe_impl!(#[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] f128: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); +}; + +// SAFETY: +// - `Immutable`: `bool` self-evidently does not contain any `UnsafeCell`s. +// - `FromZeros`: Valid since "[t]he value false has the bit pattern 0x00" [1]. +// - `IntoBytes`: Since "the boolean type has a size and alignment of 1 each" +// and "The value false has the bit pattern 0x00 and the value true has the +// bit pattern 0x01" [1]. Thus, the only byte of the bool is always +// initialized. +// - `Unaligned`: Per the reference [1], "[a]n object with the boolean type has +// a size and alignment of 1 each." +// +// [1] https://doc.rust-lang.org/1.81.0/reference/types/boolean.html +const _: () = unsafe { unsafe_impl!(bool: Immutable, FromZeros, IntoBytes, Unaligned) }; +assert_unaligned!(bool); + +// SAFETY: The impl must only return `true` for its argument if the original +// `Maybe` refers to a valid `bool`. We only return true if the `u8` value +// is 0 or 1, and both of these are valid values for `bool` [1]. +// +// [1] Per https://doc.rust-lang.org/1.81.0/reference/types/boolean.html: +// +// The value false has the bit pattern 0x00 and the value true has the bit +// pattern 0x01. +const _: () = unsafe { + unsafe_impl!(=> TryFromBytes for bool; |byte| { + let byte = byte.transmute::(); + *byte.unaligned_as_ref() < 2 + }) +}; +impl_size_eq!(bool, u8); + +// SAFETY: +// - `Immutable`: `char` self-evidently does not contain any `UnsafeCell`s. +// - `FromZeros`: Per reference [1], "[a] value of type char is a Unicode scalar +// value (i.e. a code point that is not a surrogate), represented as a 32-bit +// unsigned word in the 0x0000 to 0xD7FF or 0xE000 to 0x10FFFF range" which +// contains 0x0000. +// - `IntoBytes`: `char` is per reference [1] "represented as a 32-bit unsigned +// word" (`u32`) which is `IntoBytes`. Note that unlike `u32`, not all bit +// patterns are valid for `char`. +// +// [1] https://doc.rust-lang.org/1.81.0/reference/types/textual.html +const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) }; + +// SAFETY: The impl must only return `true` for its argument if the original +// `Maybe` refers to a valid `char`. `char::from_u32` guarantees that it +// returns `None` if its input is not a valid `char` [1]. +// +// [1] Per https://doc.rust-lang.org/core/primitive.char.html#method.from_u32: +// +// `from_u32()` will return `None` if the input is not a valid value for a +// `char`. +const _: () = unsafe { + unsafe_impl!(=> TryFromBytes for char; |c| { + let c = c.transmute::, invariant::Valid, _>(); + let c = c.read_unaligned().into_inner(); + char::from_u32(c).is_some() + }); +}; + +impl_size_eq!(char, Unalign); + +// SAFETY: Per the Reference [1], `str` has the same layout as `[u8]`. +// - `Immutable`: `[u8]` does not contain any `UnsafeCell`s. +// - `FromZeros`, `IntoBytes`, `Unaligned`: `[u8]` is `FromZeros`, `IntoBytes`, +// and `Unaligned`. +// +// Note that we don't `assert_unaligned!(str)` because `assert_unaligned!` uses +// `align_of`, which only works for `Sized` types. +// +// FIXME(#429): +// - Add quotes from documentation. +// - Improve safety proof for `FromZeros` and `IntoBytes`; having the same +// layout as `[u8]` isn't sufficient. +// +// [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#str-layout +const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unaligned) }; + +// SAFETY: The impl must only return `true` for its argument if the original +// `Maybe` refers to a valid `str`. `str::from_utf8` guarantees that it +// returns `Err` if its input is not a valid `str` [1]. +// +// [2] Per https://doc.rust-lang.org/core/str/fn.from_utf8.html#errors: +// +// Returns `Err` if the slice is not UTF-8. +const _: () = unsafe { + unsafe_impl!(=> TryFromBytes for str; |c| { + let c = c.transmute::<[u8], invariant::Valid, _>(); + let c = c.unaligned_as_ref(); + core::str::from_utf8(c).is_ok() + }) +}; + +impl_size_eq!(str, [u8]); + +macro_rules! unsafe_impl_try_from_bytes_for_nonzero { + ($($nonzero:ident[$prim:ty]),*) => { + $( + unsafe_impl!(=> TryFromBytes for $nonzero; |n| { + impl_size_eq!($nonzero, Unalign<$prim>); + + let n = n.transmute::, invariant::Valid, _>(); + $nonzero::new(n.read_unaligned().into_inner()).is_some() + }); + )* + } +} + +// `NonZeroXxx` is `IntoBytes`, but not `FromZeros` or `FromBytes`. +// +// SAFETY: +// - `IntoBytes`: `NonZeroXxx` has the same layout as its associated primitive. +// Since it is the same size, this guarantees it has no padding - integers +// have no padding, and there's no room for padding if it can represent all +// of the same values except 0. +// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that `Option` +// and `Option` both have size 1. [1] [2] This is worded in a way +// that makes it unclear whether it's meant as a guarantee, but given the +// purpose of those types, it's virtually unthinkable that that would ever +// change. `Option` cannot be smaller than its contained type, which implies +// that, and `NonZeroX8` are of size 1 or 0. `NonZeroX8` can represent +// multiple states, so they cannot be 0 bytes, which means that they must be 1 +// byte. The only valid alignment for a 1-byte type is 1. +// +// FIXME(#429): +// - Add quotes from documentation. +// - Add safety comment for `Immutable`. How can we prove that `NonZeroXxx` +// doesn't contain any `UnsafeCell`s? It's obviously true, but it's not clear +// how we'd prove it short of adding text to the stdlib docs that says so +// explicitly, which likely wouldn't be accepted. +// +// [1] https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroU8.html +// +// `NonZeroU8` is guaranteed to have the same layout and bit validity as `u8` with +// the exception that 0 is not a valid instance +// +// [2] https://doc.rust-lang.org/1.81.0/std/num/type.NonZeroI8.html +// +// FIXME(https://github.com/rust-lang/rust/pull/104082): Cite documentation that +// layout is the same as primitive layout. +const _: () = unsafe { + unsafe_impl!(NonZeroU8: Immutable, IntoBytes, Unaligned); + unsafe_impl!(NonZeroI8: Immutable, IntoBytes, Unaligned); + assert_unaligned!(NonZeroU8, NonZeroI8); + unsafe_impl!(NonZeroU16: Immutable, IntoBytes); + unsafe_impl!(NonZeroI16: Immutable, IntoBytes); + unsafe_impl!(NonZeroU32: Immutable, IntoBytes); + unsafe_impl!(NonZeroI32: Immutable, IntoBytes); + unsafe_impl!(NonZeroU64: Immutable, IntoBytes); + unsafe_impl!(NonZeroI64: Immutable, IntoBytes); + unsafe_impl!(NonZeroU128: Immutable, IntoBytes); + unsafe_impl!(NonZeroI128: Immutable, IntoBytes); + unsafe_impl!(NonZeroUsize: Immutable, IntoBytes); + unsafe_impl!(NonZeroIsize: Immutable, IntoBytes); + unsafe_impl_try_from_bytes_for_nonzero!( + NonZeroU8[u8], + NonZeroI8[i8], + NonZeroU16[u16], + NonZeroI16[i16], + NonZeroU32[u32], + NonZeroI32[i32], + NonZeroU64[u64], + NonZeroI64[i64], + NonZeroU128[u128], + NonZeroI128[i128], + NonZeroUsize[usize], + NonZeroIsize[isize] + ); +}; + +// SAFETY: +// - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`, `IntoBytes`: +// The Rust compiler reuses `0` value to represent `None`, so +// `size_of::>() == size_of::()`; see `NonZeroXxx` +// documentation. +// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that `Option` +// and `Option` both have size 1. [1] [2] This is worded in a way +// that makes it unclear whether it's meant as a guarantee, but given the +// purpose of those types, it's virtually unthinkable that that would ever +// change. The only valid alignment for a 1-byte type is 1. +// +// FIXME(#429): Add quotes from documentation. +// +// [1] https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html +// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html +// +// FIXME(https://github.com/rust-lang/rust/pull/104082): Cite documentation for +// layout guarantees. +const _: () = unsafe { + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_unaligned!(Option, Option); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); + unsafe_impl!(Option: TryFromBytes, FromZeros, FromBytes, IntoBytes); +}; + +// SAFETY: While it's not fully documented, the consensus is that `Box` does +// not contain any `UnsafeCell`s for `T: Sized` [1]. This is not a complete +// proof, but we are accepting this as a known risk per #1358. +// +// [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/492 +#[cfg(feature = "alloc")] +const _: () = unsafe { + unsafe_impl!( + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + T: Sized => Immutable for Box + ) +}; + +// SAFETY: The following types can be transmuted from `[0u8; size_of::()]`. [1] +// +// [1] Per https://doc.rust-lang.org/1.89.0/core/option/index.html#representation: +// +// Rust guarantees to optimize the following types `T` such that [`Option`] +// has the same size and alignment as `T`. In some of these cases, Rust +// further guarantees that `transmute::<_, Option>([0u8; size_of::()])` +// is sound and produces `Option::::None`. These cases are identified by +// the second column: +// +// | `T` | `transmute::<_, Option>([0u8; size_of::()])` sound? | +// |-----------------------------------|-----------------------------------------------------------| +// | [`Box`] | when `U: Sized` | +// | `&U` | when `U: Sized` | +// | `&mut U` | when `U: Sized` | +// | [`ptr::NonNull`] | when `U: Sized` | +// | `fn`, `extern "C" fn`[^extern_fn] | always | +// +// [^extern_fn]: this remains true for `unsafe` variants, any argument/return +// types, and any other ABI: `[unsafe] extern "abi" fn` (_e.g._, `extern +// "system" fn`) +const _: () = unsafe { + #[cfg(feature = "alloc")] + unsafe_impl!( + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + T => TryFromBytes for Option>; |c| pointer::is_zeroed(c) + ); + #[cfg(feature = "alloc")] + unsafe_impl!( + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + T => FromZeros for Option> + ); + unsafe_impl!( + T => TryFromBytes for Option<&'_ T>; |c| pointer::is_zeroed(c) + ); + unsafe_impl!(T => FromZeros for Option<&'_ T>); + unsafe_impl!( + T => TryFromBytes for Option<&'_ mut T>; |c| pointer::is_zeroed(c) + ); + unsafe_impl!(T => FromZeros for Option<&'_ mut T>); + unsafe_impl!( + T => TryFromBytes for Option>; |c| pointer::is_zeroed(c) + ); + unsafe_impl!(T => FromZeros for Option>); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_fn!(...)); + unsafe_impl_for_power_set!( + A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_fn!(...); + |c| pointer::is_zeroed(c) + ); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_unsafe_fn!(...)); + unsafe_impl_for_power_set!( + A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_unsafe_fn!(...); + |c| pointer::is_zeroed(c) + ); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_extern_c_fn!(...)); + unsafe_impl_for_power_set!( + A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_extern_c_fn!(...); + |c| pointer::is_zeroed(c) + ); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => FromZeros for opt_unsafe_extern_c_fn!(...)); + unsafe_impl_for_power_set!( + A, B, C, D, E, F, G, H, I, J, K, L -> M => TryFromBytes for opt_unsafe_extern_c_fn!(...); + |c| pointer::is_zeroed(c) + ); +}; + +// SAFETY: `[unsafe] [extern "C"] fn()` self-evidently do not contain +// `UnsafeCell`s. This is not a proof, but we are accepting this as a known risk +// per #1358. +const _: () = unsafe { + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_fn!(...)); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_unsafe_fn!(...)); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_extern_c_fn!(...)); + unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_unsafe_extern_c_fn!(...)); +}; + +#[cfg(all( + zerocopy_target_has_atomics_1_60_0, + any( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + ) +))] +#[cfg_attr(doc_cfg, doc(cfg(rust = "1.60.0")))] +mod atomics { + use super::*; + + macro_rules! impl_traits_for_atomics { + ($($atomics:ident [$primitives:ident]),* $(,)?) => { + $( + impl_known_layout!($atomics); + impl_for_transmute_from!(=> TryFromBytes for $atomics [UnsafeCell<$primitives>]); + impl_for_transmute_from!(=> FromZeros for $atomics [UnsafeCell<$primitives>]); + impl_for_transmute_from!(=> FromBytes for $atomics [UnsafeCell<$primitives>]); + impl_for_transmute_from!(=> IntoBytes for $atomics [UnsafeCell<$primitives>]); + )* + }; + } + + /// Implements `TransmuteFrom` for `$atomic`, `$prim`, and + /// `UnsafeCell<$prim>`. + /// + /// # Safety + /// + /// `$atomic` must have the same size and bit validity as `$prim`. + macro_rules! unsafe_impl_transmute_from_for_atomic { + ($($($tyvar:ident)? => $atomic:ty [$prim:ty]),*) => {{ + crate::util::macros::__unsafe(); + + use core::cell::UnsafeCell; + use crate::pointer::{PtrInner, SizeEq, TransmuteFrom, invariant::Valid}; + + $( + // SAFETY: The caller promised that `$atomic` and `$prim` have + // the same size and bit validity. + unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for $prim {} + // SAFETY: The caller promised that `$atomic` and `$prim` have + // the same size and bit validity. + unsafe impl<$($tyvar)?> TransmuteFrom<$prim, Valid, Valid> for $atomic {} + + // SAFETY: The caller promised that `$atomic` and `$prim` have + // the same size. + unsafe impl<$($tyvar)?> SizeEq<$atomic> for $prim { + #[inline] + fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, $prim> { + // SAFETY: The caller promised that `$atomic` and + // `$prim` have the same size. Thus, this cast preserves + // address, referent size, and provenance. + unsafe { cast!(a) } + } + } + // SAFETY: See previous safety comment. + unsafe impl<$($tyvar)?> SizeEq<$prim> for $atomic { + #[inline] + fn cast_from_raw(p: PtrInner<'_, $prim>) -> PtrInner<'_, $atomic> { + // SAFETY: See previous safety comment. + unsafe { cast!(p) } + } + } + // SAFETY: The caller promised that `$atomic` and `$prim` have + // the same size. `UnsafeCell` has the same size as `T` [1]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout: + // + // `UnsafeCell` has the same in-memory representation as + // its inner type `T`. A consequence of this guarantee is that + // it is possible to convert between `T` and `UnsafeCell`. + unsafe impl<$($tyvar)?> SizeEq<$atomic> for UnsafeCell<$prim> { + #[inline] + fn cast_from_raw(a: PtrInner<'_, $atomic>) -> PtrInner<'_, UnsafeCell<$prim>> { + // SAFETY: See previous safety comment. + unsafe { cast!(a) } + } + } + // SAFETY: See previous safety comment. + unsafe impl<$($tyvar)?> SizeEq> for $atomic { + #[inline] + fn cast_from_raw(p: PtrInner<'_, UnsafeCell<$prim>>) -> PtrInner<'_, $atomic> { + // SAFETY: See previous safety comment. + unsafe { cast!(p) } + } + } + + // SAFETY: The caller promised that `$atomic` and `$prim` have + // the same bit validity. `UnsafeCell` has the same bit + // validity as `T` [1]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.UnsafeCell.html#memory-layout: + // + // `UnsafeCell` has the same in-memory representation as + // its inner type `T`. A consequence of this guarantee is that + // it is possible to convert between `T` and `UnsafeCell`. + unsafe impl<$($tyvar)?> TransmuteFrom<$atomic, Valid, Valid> for core::cell::UnsafeCell<$prim> {} + // SAFETY: See previous safety comment. + unsafe impl<$($tyvar)?> TransmuteFrom, Valid, Valid> for $atomic {} + )* + }}; + } + + #[cfg(target_has_atomic = "8")] + #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "8")))] + mod atomic_8 { + use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU8}; + + use super::*; + + impl_traits_for_atomics!(AtomicU8[u8], AtomicI8[i8]); + + impl_known_layout!(AtomicBool); + + impl_for_transmute_from!(=> TryFromBytes for AtomicBool [UnsafeCell]); + impl_for_transmute_from!(=> FromZeros for AtomicBool [UnsafeCell]); + impl_for_transmute_from!(=> IntoBytes for AtomicBool [UnsafeCell]); + + // SAFETY: Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the + // same size as `bool`, `u8`, and `i8` respectively. Since a type's + // alignment cannot be smaller than 1 [2], and since its alignment + // cannot be greater than its size [3], the only possible value for the + // alignment is 1. Thus, it is sound to implement `Unaligned`. + // + // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU8.html: + // + // This type has the same size, alignment, and bit validity as the + // underlying integer type + // + // [2] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: + // + // Alignment is measured in bytes, and must be at least 1. + // + // [3] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#size-and-alignment: + // + // The size of a value is always a multiple of its alignment. + const _: () = unsafe { + unsafe_impl!(AtomicBool: Unaligned); + unsafe_impl!(AtomicU8: Unaligned); + unsafe_impl!(AtomicI8: Unaligned); + assert_unaligned!(AtomicBool, AtomicU8, AtomicI8); + }; + + // SAFETY: `AtomicU8`, `AtomicI8`, and `AtomicBool` have the same size + // and bit validity as `u8`, `i8`, and `bool` respectively [1][2][3]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU8.html: + // + // This type has the same size, alignment, and bit validity as the + // underlying integer type, `u8`. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI8.html: + // + // This type has the same size, alignment, and bit validity as the + // underlying integer type, `i8`. + // + // [3] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicBool.html: + // + // This type has the same size, alignment, and bit validity a `bool`. + const _: () = unsafe { + unsafe_impl_transmute_from_for_atomic!( + => AtomicU8 [u8], + => AtomicI8 [i8], + => AtomicBool [bool] + ) + }; + } + + #[cfg(target_has_atomic = "16")] + #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "16")))] + mod atomic_16 { + use core::sync::atomic::{AtomicI16, AtomicU16}; + + use super::*; + + impl_traits_for_atomics!(AtomicU16[u16], AtomicI16[i16]); + + // SAFETY: `AtomicU16` and `AtomicI16` have the same size and bit + // validity as `u16` and `i16` respectively [1][2]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU16.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `u16`. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI16.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `i16`. + const _: () = unsafe { + unsafe_impl_transmute_from_for_atomic!(=> AtomicU16 [u16], => AtomicI16 [i16]) + }; + } + + #[cfg(target_has_atomic = "32")] + #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "32")))] + mod atomic_32 { + use core::sync::atomic::{AtomicI32, AtomicU32}; + + use super::*; + + impl_traits_for_atomics!(AtomicU32[u32], AtomicI32[i32]); + + // SAFETY: `AtomicU32` and `AtomicI32` have the same size and bit + // validity as `u32` and `i32` respectively [1][2]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU32.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `u32`. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI32.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `i32`. + const _: () = unsafe { + unsafe_impl_transmute_from_for_atomic!(=> AtomicU32 [u32], => AtomicI32 [i32]) + }; + } + + #[cfg(target_has_atomic = "64")] + #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "64")))] + mod atomic_64 { + use core::sync::atomic::{AtomicI64, AtomicU64}; + + use super::*; + + impl_traits_for_atomics!(AtomicU64[u64], AtomicI64[i64]); + + // SAFETY: `AtomicU64` and `AtomicI64` have the same size and bit + // validity as `u64` and `i64` respectively [1][2]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicU64.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `u64`. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicI64.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `i64`. + const _: () = unsafe { + unsafe_impl_transmute_from_for_atomic!(=> AtomicU64 [u64], => AtomicI64 [i64]) + }; + } + + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "ptr")))] + mod atomic_ptr { + use core::sync::atomic::{AtomicIsize, AtomicPtr, AtomicUsize}; + + use super::*; + + impl_traits_for_atomics!(AtomicUsize[usize], AtomicIsize[isize]); + + impl_known_layout!(T => AtomicPtr); + + // FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement + // those traits for `*mut T`. + impl_for_transmute_from!(T => TryFromBytes for AtomicPtr [UnsafeCell<*mut T>]); + impl_for_transmute_from!(T => FromZeros for AtomicPtr [UnsafeCell<*mut T>]); + + // SAFETY: `AtomicUsize` and `AtomicIsize` have the same size and bit + // validity as `usize` and `isize` respectively [1][2]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicUsize.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `usize`. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicIsize.html: + // + // This type has the same size and bit validity as the underlying + // integer type, `isize`. + const _: () = unsafe { + unsafe_impl_transmute_from_for_atomic!(=> AtomicUsize [usize], => AtomicIsize [isize]) + }; + + // SAFETY: Per + // https://doc.rust-lang.org/1.85.0/std/sync/atomic/struct.AtomicPtr.html: + // + // This type has the same size and bit validity as a `*mut T`. + const _: () = unsafe { unsafe_impl_transmute_from_for_atomic!(T => AtomicPtr [*mut T]) }; + } +} + +// SAFETY: Per reference [1]: "For all T, the following are guaranteed: +// size_of::>() == 0 align_of::>() == 1". This +// gives: +// - `Immutable`: `PhantomData` has no fields. +// - `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: There is only +// one possible sequence of 0 bytes, and `PhantomData` is inhabited. +// - `IntoBytes`: Since `PhantomData` has size 0, it contains no padding bytes. +// - `Unaligned`: Per the preceding reference, `PhantomData` has alignment 1. +// +// [1] https://doc.rust-lang.org/1.81.0/std/marker/struct.PhantomData.html#layout-1 +const _: () = unsafe { + unsafe_impl!(T: ?Sized => Immutable for PhantomData); + unsafe_impl!(T: ?Sized => TryFromBytes for PhantomData); + unsafe_impl!(T: ?Sized => FromZeros for PhantomData); + unsafe_impl!(T: ?Sized => FromBytes for PhantomData); + unsafe_impl!(T: ?Sized => IntoBytes for PhantomData); + unsafe_impl!(T: ?Sized => Unaligned for PhantomData); + assert_unaligned!(PhantomData<()>, PhantomData, PhantomData); +}; + +impl_for_transmute_from!(T: TryFromBytes => TryFromBytes for Wrapping[]); +impl_for_transmute_from!(T: FromZeros => FromZeros for Wrapping[]); +impl_for_transmute_from!(T: FromBytes => FromBytes for Wrapping[]); +impl_for_transmute_from!(T: IntoBytes => IntoBytes for Wrapping[]); +assert_unaligned!(Wrapping<()>, Wrapping); + +// SAFETY: Per [1], `Wrapping` has the same layout as `T`. Since its single +// field (of type `T`) is public, it would be a breaking change to add or remove +// fields. Thus, we know that `Wrapping` contains a `T` (as opposed to just +// having the same size and alignment as `T`) with no pre- or post-padding. +// Thus, `Wrapping` must have `UnsafeCell`s covering the same byte ranges as +// `Inner = T`. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: +// +// `Wrapping` is guaranteed to have the same layout and ABI as `T` +const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for Wrapping) }; + +// SAFETY: Per [1] in the preceding safety comment, `Wrapping` has the same +// alignment as `T`. +const _: () = unsafe { unsafe_impl!(T: Unaligned => Unaligned for Wrapping) }; + +// SAFETY: `TryFromBytes` (with no validator), `FromZeros`, `FromBytes`: +// `MaybeUninit` has no restrictions on its contents. +const _: () = unsafe { + unsafe_impl!(T => TryFromBytes for CoreMaybeUninit); + unsafe_impl!(T => FromZeros for CoreMaybeUninit); + unsafe_impl!(T => FromBytes for CoreMaybeUninit); +}; + +// SAFETY: `MaybeUninit` has `UnsafeCell`s covering the same byte ranges as +// `Inner = T`. This is not explicitly documented, but it can be inferred. Per +// [1], `MaybeUninit` has the same size as `T`. Further, note the signature +// of `MaybeUninit::assume_init_ref` [2]: +// +// pub unsafe fn assume_init_ref(&self) -> &T +// +// If the argument `&MaybeUninit` and the returned `&T` had `UnsafeCell`s at +// different offsets, this would be unsound. Its existence is proof that this is +// not the case. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: +// +// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as +// `T`. +// +// [2] https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#method.assume_init_ref +const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for CoreMaybeUninit) }; + +// SAFETY: Per [1] in the preceding safety comment, `MaybeUninit` has the +// same alignment as `T`. +const _: () = unsafe { unsafe_impl!(T: Unaligned => Unaligned for CoreMaybeUninit) }; +assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit); + +// SAFETY: `ManuallyDrop` has the same layout as `T` [1]. This strongly +// implies, but does not guarantee, that it contains `UnsafeCell`s covering the +// same byte ranges as in `T`. However, it also implements `Defer` +// [2], which provides the ability to convert `&ManuallyDrop -> &T`. This, +// combined with having the same size as `T`, implies that `ManuallyDrop` +// exactly contains a `T` with the same fields and `UnsafeCell`s covering the +// same byte ranges, or else the `Deref` impl would permit safe code to obtain +// different shared references to the same region of memory with different +// `UnsafeCell` coverage, which would in turn permit interior mutation that +// would violate the invariants of a shared reference. +// +// [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +// `T` +// +// [2] https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E +const _: () = unsafe { unsafe_impl!(T: ?Sized + Immutable => Immutable for ManuallyDrop) }; + +impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop[]); +impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop[]); +impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop[]); +impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop[]); +// SAFETY: `ManuallyDrop` has the same layout as `T` [1], and thus has the +// same alignment as `T`. +// +// [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +// `T` +const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop) }; +assert_unaligned!(ManuallyDrop<()>, ManuallyDrop); + +impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for Cell[UnsafeCell]); +// SAFETY: `Cell` has the same in-memory representation as `T` [1], and thus +// has the same alignment as `T`. +// +// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.Cell.html#memory-layout: +// +// `Cell` has the same in-memory representation as its inner type `T`. +const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for Cell) }; + +impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for UnsafeCell[]); +impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for UnsafeCell[]); +impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell[]); +// SAFETY: `UnsafeCell` has the same in-memory representation as `T` [1], and +// thus has the same alignment as `T`. +// +// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: +// +// `UnsafeCell` has the same in-memory representation as its inner type +// `T`. +const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for UnsafeCell) }; +assert_unaligned!(UnsafeCell<()>, UnsafeCell); + +// SAFETY: See safety comment in `is_bit_valid` impl. +unsafe impl TryFromBytes for UnsafeCell { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + } + + #[inline] + fn is_bit_valid(candidate: Maybe<'_, Self, A>) -> bool { + // The only way to implement this function is using an exclusive-aliased + // pointer. `UnsafeCell`s cannot be read via shared-aliased pointers + // (other than by using `unsafe` code, which we can't use since we can't + // guarantee how our users are accessing or modifying the `UnsafeCell`). + // + // `is_bit_valid` is documented as panicking or failing to monomorphize + // if called with a shared-aliased pointer on a type containing an + // `UnsafeCell`. In practice, it will always be a monorphization error. + // Since `is_bit_valid` is `#[doc(hidden)]` and only called directly + // from this crate, we only need to worry about our own code incorrectly + // calling `UnsafeCell::is_bit_valid`. The post-monomorphization error + // makes it easier to test that this is truly the case, and also means + // that if we make a mistake, it will cause downstream code to fail to + // compile, which will immediately surface the mistake and give us a + // chance to fix it quickly. + let c = candidate.into_exclusive_or_pme(); + + // SAFETY: Since `UnsafeCell` and `T` have the same layout and bit + // validity, `UnsafeCell` is bit-valid exactly when its wrapped `T` + // is. Thus, this is a sound implementation of + // `UnsafeCell::is_bit_valid`. + T::is_bit_valid(c.get_mut()) + } +} + +// SAFETY: Per the reference [1]: +// +// An array of `[T; N]` has a size of `size_of::() * N` and the same +// alignment of `T`. Arrays are laid out so that the zero-based `nth` element +// of the array is offset from the start of the array by `n * size_of::()` +// bytes. +// +// ... +// +// Slices have the same layout as the section of the array they slice. +// +// In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s laid +// out back-to-back with no bytes in between. Therefore, `[T]` or `[T; N]` are +// `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, and `IntoBytes` if `T` +// is (respectively). Furthermore, since an array/slice has "the same alignment +// of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is. +// +// Note that we don't `assert_unaligned!` for slice types because +// `assert_unaligned!` uses `align_of`, which only works for `Sized` types. +// +// [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#array-layout +const _: () = unsafe { + unsafe_impl!(const N: usize, T: Immutable => Immutable for [T; N]); + unsafe_impl!(const N: usize, T: TryFromBytes => TryFromBytes for [T; N]; |c| { + // Note that this call may panic, but it would still be sound even if it + // did. `is_bit_valid` does not promise that it will not panic (in fact, + // it explicitly warns that it's a possibility), and we have not + // violated any safety invariants that we must fix before returning. + <[T] as TryFromBytes>::is_bit_valid(c.as_slice()) + }); + unsafe_impl!(const N: usize, T: FromZeros => FromZeros for [T; N]); + unsafe_impl!(const N: usize, T: FromBytes => FromBytes for [T; N]); + unsafe_impl!(const N: usize, T: IntoBytes => IntoBytes for [T; N]); + unsafe_impl!(const N: usize, T: Unaligned => Unaligned for [T; N]); + assert_unaligned!([(); 0], [(); 1], [u8; 0], [u8; 1]); + unsafe_impl!(T: Immutable => Immutable for [T]); + unsafe_impl!(T: TryFromBytes => TryFromBytes for [T]; |c| { + // SAFETY: Per the reference [1]: + // + // An array of `[T; N]` has a size of `size_of::() * N` and the + // same alignment of `T`. Arrays are laid out so that the zero-based + // `nth` element of the array is offset from the start of the array by + // `n * size_of::()` bytes. + // + // ... + // + // Slices have the same layout as the section of the array they slice. + // + // In other words, the layout of a `[T] is a sequence of `T`s laid out + // back-to-back with no bytes in between. If all elements in `candidate` + // are `is_bit_valid`, so too is `candidate`. + // + // Note that any of the below calls may panic, but it would still be + // sound even if it did. `is_bit_valid` does not promise that it will + // not panic (in fact, it explicitly warns that it's a possibility), and + // we have not violated any safety invariants that we must fix before + // returning. + c.iter().all(::is_bit_valid) + }); + unsafe_impl!(T: FromZeros => FromZeros for [T]); + unsafe_impl!(T: FromBytes => FromBytes for [T]); + unsafe_impl!(T: IntoBytes => IntoBytes for [T]); + unsafe_impl!(T: Unaligned => Unaligned for [T]); +}; + +// SAFETY: +// - `Immutable`: Raw pointers do not contain any `UnsafeCell`s. +// - `FromZeros`: For thin pointers (note that `T: Sized`), the zero pointer is +// considered "null". [1] No operations which require provenance are legal on +// null pointers, so this is not a footgun. +// - `TryFromBytes`: By the same reasoning as for `FromZeroes`, we can implement +// `TryFromBytes` for thin pointers provided that +// [`TryFromByte::is_bit_valid`] only produces `true` for zeroed bytes. +// +// NOTE(#170): Implementing `FromBytes` and `IntoBytes` for raw pointers would +// be sound, but carries provenance footguns. We want to support `FromBytes` and +// `IntoBytes` for raw pointers eventually, but we are holding off until we can +// figure out how to address those footguns. +// +// [1] FIXME(https://github.com/rust-lang/rust/pull/116988): Cite the +// documentation once this PR lands. +const _: () = unsafe { + unsafe_impl!(T: ?Sized => Immutable for *const T); + unsafe_impl!(T: ?Sized => Immutable for *mut T); + unsafe_impl!(T => TryFromBytes for *const T; |c| pointer::is_zeroed(c)); + unsafe_impl!(T => FromZeros for *const T); + unsafe_impl!(T => TryFromBytes for *mut T; |c| pointer::is_zeroed(c)); + unsafe_impl!(T => FromZeros for *mut T); +}; + +// SAFETY: `NonNull` self-evidently does not contain `UnsafeCell`s. This is +// not a proof, but we are accepting this as a known risk per #1358. +const _: () = unsafe { unsafe_impl!(T: ?Sized => Immutable for NonNull) }; + +// SAFETY: Reference types do not contain any `UnsafeCell`s. +const _: () = unsafe { + unsafe_impl!(T: ?Sized => Immutable for &'_ T); + unsafe_impl!(T: ?Sized => Immutable for &'_ mut T); +}; + +// SAFETY: `Option` is not `#[non_exhaustive]` [1], which means that the types +// in its variants cannot change, and no new variants can be added. `Option` +// does not contain any `UnsafeCell`s outside of `T`. [1] +// +// [1] https://doc.rust-lang.org/core/option/enum.Option.html +const _: () = unsafe { unsafe_impl!(T: Immutable => Immutable for Option) }; + +// SIMD support +// +// Per the Unsafe Code Guidelines Reference [1]: +// +// Packed SIMD vector types are `repr(simd)` homogeneous tuple-structs +// containing `N` elements of type `T` where `N` is a power-of-two and the +// size and alignment requirements of `T` are equal: +// +// ```rust +// #[repr(simd)] +// struct Vector(T_0, ..., T_(N - 1)); +// ``` +// +// ... +// +// The size of `Vector` is `N * size_of::()` and its alignment is an +// implementation-defined function of `T` and `N` greater than or equal to +// `align_of::()`. +// +// ... +// +// Vector elements are laid out in source field order, enabling random access +// to vector elements by reinterpreting the vector as an array: +// +// ```rust +// union U { +// vec: Vector, +// arr: [T; N] +// } +// +// assert_eq!(size_of::>(), size_of::<[T; N]>()); +// assert!(align_of::>() >= align_of::<[T; N]>()); +// +// unsafe { +// let u = U { vec: Vector(t_0, ..., t_(N - 1)) }; +// +// assert_eq!(u.vec.0, u.arr[0]); +// // ... +// assert_eq!(u.vec.(N - 1), u.arr[N - 1]); +// } +// ``` +// +// Given this background, we can observe that: +// - The size and bit pattern requirements of a SIMD type are equivalent to the +// equivalent array type. Thus, for any SIMD type whose primitive `T` is +// `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, or `IntoBytes`, that +// SIMD type is also `Immutable`, `TryFromBytes`, `FromZeros`, `FromBytes`, or +// `IntoBytes` respectively. +// - Since no upper bound is placed on the alignment, no SIMD type can be +// guaranteed to be `Unaligned`. +// +// Also per [1]: +// +// This chapter represents the consensus from issue #38. The statements in +// here are not (yet) "guaranteed" not to change until an RFC ratifies them. +// +// See issue #38 [2]. While this behavior is not technically guaranteed, the +// likelihood that the behavior will change such that SIMD types are no longer +// `TryFromBytes`, `FromZeros`, `FromBytes`, or `IntoBytes` is next to zero, as +// that would defeat the entire purpose of SIMD types. Nonetheless, we put this +// behavior behind the `simd` Cargo feature, which requires consumers to opt +// into this stability hazard. +// +// [1] https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html +// [2] https://github.com/rust-lang/unsafe-code-guidelines/issues/38 +#[cfg(feature = "simd")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "simd")))] +mod simd { + /// Defines a module which implements `TryFromBytes`, `FromZeros`, + /// `FromBytes`, and `IntoBytes` for a set of types from a module in + /// `core::arch`. + /// + /// `$arch` is both the name of the defined module and the name of the + /// module in `core::arch`, and `$typ` is the list of items from that module + /// to implement `FromZeros`, `FromBytes`, and `IntoBytes` for. + #[allow(unused_macros)] // `allow(unused_macros)` is needed because some + // target/feature combinations don't emit any impls + // and thus don't use this macro. + macro_rules! simd_arch_mod { + ($(#[cfg $cfg:tt])* $(#[cfg_attr $cfg_attr:tt])? $arch:ident, $mod:ident, $($typ:ident),*) => { + $(#[cfg $cfg])* + #[cfg_attr(doc_cfg, doc(cfg $($cfg)*))] + $(#[cfg_attr $cfg_attr])? + mod $mod { + use core::arch::$arch::{$($typ),*}; + + use crate::*; + impl_known_layout!($($typ),*); + // SAFETY: See comment on module definition for justification. + const _: () = unsafe { + $( unsafe_impl!($typ: Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes); )* + }; + } + }; + } + + #[rustfmt::skip] + const _: () = { + simd_arch_mod!( + #[cfg(target_arch = "x86")] + x86, x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i + ); + simd_arch_mod!( + #[cfg(all(feature = "simd-nightly", target_arch = "x86"))] + x86, x86_nightly, __m512bh, __m512, __m512d, __m512i + ); + simd_arch_mod!( + #[cfg(target_arch = "x86_64")] + x86_64, x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i + ); + simd_arch_mod!( + #[cfg(all(feature = "simd-nightly", target_arch = "x86_64"))] + x86_64, x86_64_nightly, __m512bh, __m512, __m512d, __m512i + ); + simd_arch_mod!( + #[cfg(target_arch = "wasm32")] + wasm32, wasm32, v128 + ); + simd_arch_mod!( + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))] + powerpc, powerpc, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long + ); + simd_arch_mod!( + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))] + powerpc64, powerpc64, vector_bool_long, vector_double, vector_signed_long, vector_unsigned_long + ); + #[cfg(zerocopy_aarch64_simd_1_59_0)] + simd_arch_mod!( + // NOTE(https://github.com/rust-lang/stdarch/issues/1484): NEON intrinsics are currently + // broken on big-endian platforms. + #[cfg(all(target_arch = "aarch64", target_endian = "little"))] + #[cfg_attr(doc_cfg, doc(cfg(rust = "1.59.0")))] + aarch64, aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t, + int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t, + int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, + poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t, + poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t, + uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x8_t, uint32x2_t, uint32x4_t, + uint64x1_t, uint64x2_t + ); + }; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::pointer::invariant; + + #[test] + fn test_impls() { + // A type that can supply test cases for testing + // `TryFromBytes::is_bit_valid`. All types passed to `assert_impls!` + // must implement this trait; that macro uses it to generate runtime + // tests for `TryFromBytes` impls. + // + // All `T: FromBytes` types are provided with a blanket impl. Other + // types must implement `TryFromBytesTestable` directly (ie using + // `impl_try_from_bytes_testable!`). + trait TryFromBytesTestable { + fn with_passing_test_cases)>(f: F); + fn with_failing_test_cases(f: F); + } + + impl TryFromBytesTestable for T { + fn with_passing_test_cases)>(f: F) { + // Test with a zeroed value. + f(Self::new_box_zeroed().unwrap()); + + let ffs = { + let mut t = Self::new_zeroed(); + let ptr: *mut T = &mut t; + // SAFETY: `T: FromBytes` + unsafe { ptr::write_bytes(ptr.cast::(), 0xFF, mem::size_of::()) }; + t + }; + + // Test with a value initialized with 0xFF. + f(Box::new(ffs)); + } + + fn with_failing_test_cases(_f: F) {} + } + + macro_rules! impl_try_from_bytes_testable_for_null_pointer_optimization { + ($($tys:ty),*) => { + $( + impl TryFromBytesTestable for Option<$tys> { + fn with_passing_test_cases)>(f: F) { + // Test with a zeroed value. + f(Box::new(None)); + } + + fn with_failing_test_cases(f: F) { + for pos in 0..mem::size_of::() { + let mut bytes = [0u8; mem::size_of::()]; + bytes[pos] = 0x01; + f(&mut bytes[..]); + } + } + } + )* + }; + } + + // Implements `TryFromBytesTestable`. + macro_rules! impl_try_from_bytes_testable { + // Base case for recursion (when the list of types has run out). + (=> @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {}; + // Implements for type(s) with no type parameters. + ($ty:ty $(,$tys:ty)* => @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { + impl TryFromBytesTestable for $ty { + impl_try_from_bytes_testable!( + @methods @success $($success_case),* + $(, @failure $($failure_case),*)? + ); + } + impl_try_from_bytes_testable!($($tys),* => @success $($success_case),* $(, @failure $($failure_case),*)?); + }; + // Implements for multiple types with no type parameters. + ($($($ty:ty),* => @success $($success_case:expr), * $(, @failure $($failure_case:expr),*)?;)*) => { + $( + impl_try_from_bytes_testable!($($ty),* => @success $($success_case),* $(, @failure $($failure_case),*)*); + )* + }; + // Implements only the methods; caller must invoke this from inside + // an impl block. + (@methods @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { + fn with_passing_test_cases)>(_f: F) { + $( + _f(Box::::from($success_case)); + )* + } + + fn with_failing_test_cases(_f: F) { + $($( + let mut case = $failure_case; + _f(case.as_mut_bytes()); + )*)? + } + }; + } + + impl_try_from_bytes_testable_for_null_pointer_optimization!( + Box>, + &'static UnsafeCell, + &'static mut UnsafeCell, + NonNull>, + fn(), + FnManyArgs, + extern "C" fn(), + ECFnManyArgs + ); + + macro_rules! bx { + ($e:expr) => { + Box::new($e) + }; + } + + // Note that these impls are only for types which are not `FromBytes`. + // `FromBytes` types are covered by a preceding blanket impl. + impl_try_from_bytes_testable!( + bool => @success true, false, + @failure 2u8, 3u8, 0xFFu8; + char => @success '\u{0}', '\u{D7FF}', '\u{E000}', '\u{10FFFF}', + @failure 0xD800u32, 0xDFFFu32, 0x110000u32; + str => @success "", "hello", "❤️🧡💛💚💙💜", + @failure [0, 159, 146, 150]; + [u8] => @success vec![].into_boxed_slice(), vec![0, 1, 2].into_boxed_slice(); + NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, + NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, + NonZeroUsize, NonZeroIsize + => @success Self::new(1).unwrap(), + // Doing this instead of `0` ensures that we always satisfy + // the size and alignment requirements of `Self` (whereas `0` + // may be any integer type with a different size or alignment + // than some `NonZeroXxx` types). + @failure Option::::None; + [bool; 0] => @success []; + [bool; 1] + => @success [true], [false], + @failure [2u8], [3u8], [0xFFu8]; + [bool] + => @success vec![true, false].into_boxed_slice(), vec![false, true].into_boxed_slice(), + @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; + Unalign + => @success Unalign::new(false), Unalign::new(true), + @failure 2u8, 0xFFu8; + ManuallyDrop + => @success ManuallyDrop::new(false), ManuallyDrop::new(true), + @failure 2u8, 0xFFu8; + ManuallyDrop<[u8]> + => @success bx!(ManuallyDrop::new([])), bx!(ManuallyDrop::new([0u8])), bx!(ManuallyDrop::new([0u8, 1u8])); + ManuallyDrop<[bool]> + => @success bx!(ManuallyDrop::new([])), bx!(ManuallyDrop::new([false])), bx!(ManuallyDrop::new([false, true])), + @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; + ManuallyDrop<[UnsafeCell]> + => @success bx!(ManuallyDrop::new([UnsafeCell::new(0)])), bx!(ManuallyDrop::new([UnsafeCell::new(0), UnsafeCell::new(1)])); + ManuallyDrop<[UnsafeCell]> + => @success bx!(ManuallyDrop::new([UnsafeCell::new(false)])), bx!(ManuallyDrop::new([UnsafeCell::new(false), UnsafeCell::new(true)])), + @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; + Wrapping + => @success Wrapping(false), Wrapping(true), + @failure 2u8, 0xFFu8; + *const NotZerocopy + => @success ptr::null::(), + @failure [0x01; mem::size_of::<*const NotZerocopy>()]; + *mut NotZerocopy + => @success ptr::null_mut::(), + @failure [0x01; mem::size_of::<*mut NotZerocopy>()]; + ); + + // Use the trick described in [1] to allow us to call methods + // conditional on certain trait bounds. + // + // In all of these cases, methods return `Option`, where `R` is the + // return type of the method we're conditionally calling. The "real" + // implementations (the ones defined in traits using `&self`) return + // `Some`, and the default implementations (the ones defined as inherent + // methods using `&mut self`) return `None`. + // + // [1] https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md + mod autoref_trick { + use super::*; + + pub(super) struct AutorefWrapper(pub(super) PhantomData); + + pub(super) trait TestIsBitValidShared { + #[allow(clippy::needless_lifetimes)] + fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>( + &self, + candidate: Maybe<'ptr, T, A>, + ) -> Option; + } + + impl TestIsBitValidShared for AutorefWrapper { + #[allow(clippy::needless_lifetimes)] + fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>( + &self, + candidate: Maybe<'ptr, T, A>, + ) -> Option { + Some(T::is_bit_valid(candidate)) + } + } + + pub(super) trait TestTryFromRef { + #[allow(clippy::needless_lifetimes)] + fn test_try_from_ref<'bytes>( + &self, + bytes: &'bytes [u8], + ) -> Option>; + } + + impl TestTryFromRef for AutorefWrapper { + #[allow(clippy::needless_lifetimes)] + fn test_try_from_ref<'bytes>( + &self, + bytes: &'bytes [u8], + ) -> Option> { + Some(T::try_ref_from_bytes(bytes).ok()) + } + } + + pub(super) trait TestTryFromMut { + #[allow(clippy::needless_lifetimes)] + fn test_try_from_mut<'bytes>( + &self, + bytes: &'bytes mut [u8], + ) -> Option>; + } + + impl TestTryFromMut for AutorefWrapper { + #[allow(clippy::needless_lifetimes)] + fn test_try_from_mut<'bytes>( + &self, + bytes: &'bytes mut [u8], + ) -> Option> { + Some(T::try_mut_from_bytes(bytes).ok()) + } + } + + pub(super) trait TestTryReadFrom { + fn test_try_read_from(&self, bytes: &[u8]) -> Option>; + } + + impl TestTryReadFrom for AutorefWrapper { + fn test_try_read_from(&self, bytes: &[u8]) -> Option> { + Some(T::try_read_from_bytes(bytes).ok()) + } + } + + pub(super) trait TestAsBytes { + #[allow(clippy::needless_lifetimes)] + fn test_as_bytes<'slf, 't>(&'slf self, t: &'t T) -> Option<&'t [u8]>; + } + + impl TestAsBytes for AutorefWrapper { + #[allow(clippy::needless_lifetimes)] + fn test_as_bytes<'slf, 't>(&'slf self, t: &'t T) -> Option<&'t [u8]> { + Some(t.as_bytes()) + } + } + } + + use autoref_trick::*; + + // Asserts that `$ty` is one of a list of types which are allowed to not + // provide a "real" implementation for `$fn_name`. Since the + // `autoref_trick` machinery fails silently, this allows us to ensure + // that the "default" impls are only being used for types which we + // expect. + // + // Note that, since this is a runtime test, it is possible to have an + // allowlist which is too restrictive if the function in question is + // never called for a particular type. For example, if `as_bytes` is not + // supported for a particular type, and so `test_as_bytes` returns + // `None`, methods such as `test_try_from_ref` may never be called for + // that type. As a result, it's possible that, for example, adding + // `as_bytes` support for a type would cause other allowlist assertions + // to fail. This means that allowlist assertion failures should not + // automatically be taken as a sign of a bug. + macro_rules! assert_on_allowlist { + ($fn_name:ident($ty:ty) $(: $($tys:ty),*)?) => {{ + use core::any::TypeId; + + let allowlist: &[TypeId] = &[ $($(TypeId::of::<$tys>()),*)? ]; + let allowlist_names: &[&str] = &[ $($(stringify!($tys)),*)? ]; + + let id = TypeId::of::<$ty>(); + assert!(allowlist.contains(&id), "{} is not on allowlist for {}: {:?}", stringify!($ty), stringify!($fn_name), allowlist_names); + }}; + } + + // Asserts that `$ty` implements any `$trait` and doesn't implement any + // `!$trait`. Note that all `$trait`s must come before any `!$trait`s. + // + // For `T: TryFromBytes`, uses `TryFromBytesTestable` to test success + // and failure cases. + macro_rules! assert_impls { + ($ty:ty: TryFromBytes) => { + // "Default" implementations that match the "real" + // implementations defined in the `autoref_trick` module above. + #[allow(unused, non_local_definitions)] + impl AutorefWrapper<$ty> { + #[allow(clippy::needless_lifetimes)] + fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>( + &mut self, + candidate: Maybe<'ptr, $ty, A>, + ) -> Option { + assert_on_allowlist!( + test_is_bit_valid_shared($ty): + ManuallyDrop>, + ManuallyDrop<[UnsafeCell]>, + ManuallyDrop<[UnsafeCell]>, + CoreMaybeUninit, + CoreMaybeUninit>, + Wrapping> + ); + + None + } + + #[allow(clippy::needless_lifetimes)] + fn test_try_from_ref<'bytes>(&mut self, _bytes: &'bytes [u8]) -> Option> { + assert_on_allowlist!( + test_try_from_ref($ty): + ManuallyDrop<[UnsafeCell]> + ); + + None + } + + #[allow(clippy::needless_lifetimes)] + fn test_try_from_mut<'bytes>(&mut self, _bytes: &'bytes mut [u8]) -> Option> { + assert_on_allowlist!( + test_try_from_mut($ty): + Option>>, + Option<&'static UnsafeCell>, + Option<&'static mut UnsafeCell>, + Option>>, + Option, + Option, + Option, + Option, + *const NotZerocopy, + *mut NotZerocopy + ); + + None + } + + fn test_try_read_from(&mut self, _bytes: &[u8]) -> Option> { + assert_on_allowlist!( + test_try_read_from($ty): + str, + ManuallyDrop<[u8]>, + ManuallyDrop<[bool]>, + ManuallyDrop<[UnsafeCell]>, + [u8], + [bool] + ); + + None + } + + fn test_as_bytes(&mut self, _t: &$ty) -> Option<&[u8]> { + assert_on_allowlist!( + test_as_bytes($ty): + Option<&'static UnsafeCell>, + Option<&'static mut UnsafeCell>, + Option>>, + Option>>, + Option, + Option, + Option, + Option, + CoreMaybeUninit, + CoreMaybeUninit, + CoreMaybeUninit>, + ManuallyDrop>, + ManuallyDrop<[UnsafeCell]>, + ManuallyDrop<[UnsafeCell]>, + Wrapping>, + *const NotZerocopy, + *mut NotZerocopy + ); + + None + } + } + + <$ty as TryFromBytesTestable>::with_passing_test_cases(|mut val| { + // FIXME(#494): These tests only get exercised for types + // which are `IntoBytes`. Once we implement #494, we should + // be able to support non-`IntoBytes` types by zeroing + // padding. + + // We define `w` and `ww` since, in the case of the inherent + // methods, Rust thinks they're both borrowed mutably at the + // same time (given how we use them below). If we just + // defined a single `w` and used it for multiple operations, + // this would conflict. + // + // We `#[allow(unused_mut]` for the cases where the "real" + // impls are used, which take `&self`. + #[allow(unused_mut)] + let (mut w, mut ww) = (AutorefWrapper::<$ty>(PhantomData), AutorefWrapper::<$ty>(PhantomData)); + + let c = Ptr::from_ref(&*val); + let c = c.forget_aligned(); + // SAFETY: FIXME(#899): This is unsound. `$ty` is not + // necessarily `IntoBytes`, but that's the corner we've + // backed ourselves into by using `Ptr::from_ref`. + let c = unsafe { c.assume_initialized() }; + let res = w.test_is_bit_valid_shared(c); + if let Some(res) = res { + assert!(res, "{}::is_bit_valid({:?}) (shared `Ptr`): got false, expected true", stringify!($ty), val); + } + + let c = Ptr::from_mut(&mut *val); + let c = c.forget_aligned(); + // SAFETY: FIXME(#899): This is unsound. `$ty` is not + // necessarily `IntoBytes`, but that's the corner we've + // backed ourselves into by using `Ptr::from_ref`. + let c = unsafe { c.assume_initialized() }; + let res = <$ty as TryFromBytes>::is_bit_valid(c); + assert!(res, "{}::is_bit_valid({:?}) (exclusive `Ptr`): got false, expected true", stringify!($ty), val); + + // `bytes` is `Some(val.as_bytes())` if `$ty: IntoBytes + + // Immutable` and `None` otherwise. + let bytes = w.test_as_bytes(&*val); + + // The inner closure returns + // `Some($ty::try_ref_from_bytes(bytes))` if `$ty: + // Immutable` and `None` otherwise. + let res = bytes.and_then(|bytes| ww.test_try_from_ref(bytes)); + if let Some(res) = res { + assert!(res.is_some(), "{}::try_ref_from_bytes({:?}): got `None`, expected `Some`", stringify!($ty), val); + } + + if let Some(bytes) = bytes { + // We need to get a mutable byte slice, and so we clone + // into a `Vec`. However, we also need these bytes to + // satisfy `$ty`'s alignment requirement, which isn't + // guaranteed for `Vec`. In order to get around + // this, we create a `Vec` which is twice as long as we + // need. There is guaranteed to be an aligned byte range + // of size `size_of_val(val)` within that range. + let val = &*val; + let size = mem::size_of_val(val); + let align = mem::align_of_val(val); + + let mut vec = bytes.to_vec(); + vec.extend(bytes); + let slc = vec.as_slice(); + let offset = slc.as_ptr().align_offset(align); + let bytes_mut = &mut vec.as_mut_slice()[offset..offset+size]; + bytes_mut.copy_from_slice(bytes); + + let res = ww.test_try_from_mut(bytes_mut); + if let Some(res) = res { + assert!(res.is_some(), "{}::try_mut_from_bytes({:?}): got `None`, expected `Some`", stringify!($ty), val); + } + } + + let res = bytes.and_then(|bytes| ww.test_try_read_from(bytes)); + if let Some(res) = res { + assert!(res.is_some(), "{}::try_read_from_bytes({:?}): got `None`, expected `Some`", stringify!($ty), val); + } + }); + #[allow(clippy::as_conversions)] + <$ty as TryFromBytesTestable>::with_failing_test_cases(|c| { + #[allow(unused_mut)] // For cases where the "real" impls are used, which take `&self`. + let mut w = AutorefWrapper::<$ty>(PhantomData); + + // This is `Some($ty::try_ref_from_bytes(c))` if `$ty: + // Immutable` and `None` otherwise. + let res = w.test_try_from_ref(c); + if let Some(res) = res { + assert!(res.is_none(), "{}::try_ref_from_bytes({:?}): got Some, expected None", stringify!($ty), c); + } + + let res = w.test_try_from_mut(c); + if let Some(res) = res { + assert!(res.is_none(), "{}::try_mut_from_bytes({:?}): got Some, expected None", stringify!($ty), c); + } + + + let res = w.test_try_read_from(c); + if let Some(res) = res { + assert!(res.is_none(), "{}::try_read_from_bytes({:?}): got Some, expected None", stringify!($ty), c); + } + }); + + #[allow(dead_code)] + const _: () = { static_assertions::assert_impl_all!($ty: TryFromBytes); }; + }; + ($ty:ty: $trait:ident) => { + #[allow(dead_code)] + const _: () = { static_assertions::assert_impl_all!($ty: $trait); }; + }; + ($ty:ty: !$trait:ident) => { + #[allow(dead_code)] + const _: () = { static_assertions::assert_not_impl_any!($ty: $trait); }; + }; + ($ty:ty: $($trait:ident),* $(,)? $(!$negative_trait:ident),*) => { + $( + assert_impls!($ty: $trait); + )* + + $( + assert_impls!($ty: !$negative_trait); + )* + }; + } + + // NOTE: The negative impl assertions here are not necessarily + // prescriptive. They merely serve as change detectors to make sure + // we're aware of what trait impls are getting added with a given + // change. Of course, some impls would be invalid (e.g., `bool: + // FromBytes`), and so this change detection is very important. + + assert_impls!( + (): KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned + ); + assert_impls!( + u8: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned + ); + assert_impls!( + i8: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned + ); + assert_impls!( + u16: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + i16: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + u32: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + i32: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + u64: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + i64: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + u128: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + i128: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + usize: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + isize: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + #[cfg(feature = "float-nightly")] + assert_impls!( + f16: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + f32: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + f64: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + #[cfg(feature = "float-nightly")] + assert_impls!( + f128: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + !Unaligned + ); + assert_impls!( + bool: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + IntoBytes, + Unaligned, + !FromBytes + ); + assert_impls!( + char: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + str: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + IntoBytes, + Unaligned, + !FromBytes + ); + + assert_impls!( + NonZeroU8: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + Unaligned, + !FromZeros, + !FromBytes + ); + assert_impls!( + NonZeroI8: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + Unaligned, + !FromZeros, + !FromBytes + ); + assert_impls!( + NonZeroU16: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroI16: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroU32: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroI32: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroU64: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroI64: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroU128: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroI128: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroUsize: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + assert_impls!( + NonZeroIsize: KnownLayout, + Immutable, + TryFromBytes, + IntoBytes, + !FromBytes, + !Unaligned + ); + + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); + + // Implements none of the ZC traits. + struct NotZerocopy; + + #[rustfmt::skip] + type FnManyArgs = fn( + NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, + ) -> (NotZerocopy, NotZerocopy); + + // Allowed, because we're not actually using this type for FFI. + #[allow(improper_ctypes_definitions)] + #[rustfmt::skip] + type ECFnManyArgs = extern "C" fn( + NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, + ) -> (NotZerocopy, NotZerocopy); + + #[cfg(feature = "alloc")] + assert_impls!(Option>>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option]>>: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option<&'static UnsafeCell>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option<&'static [UnsafeCell]>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option<&'static mut UnsafeCell>: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option<&'static mut [UnsafeCell]>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option>>: KnownLayout, TryFromBytes, FromZeros, Immutable, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option]>>: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Option: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + + assert_impls!(PhantomData: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_impls!(PhantomData>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + assert_impls!(PhantomData<[u8]>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + + assert_impls!(ManuallyDrop: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + // This test is important because it allows us to test our hand-rolled + // implementation of ` as TryFromBytes>::is_bit_valid`. + assert_impls!(ManuallyDrop: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); + assert_impls!(ManuallyDrop<[u8]>: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + // This test is important because it allows us to test our hand-rolled + // implementation of ` as TryFromBytes>::is_bit_valid`. + assert_impls!(ManuallyDrop<[bool]>: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); + assert_impls!(ManuallyDrop: !Immutable, !TryFromBytes, !KnownLayout, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(ManuallyDrop<[NotZerocopy]>: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(ManuallyDrop>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); + assert_impls!(ManuallyDrop<[UnsafeCell]>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); + assert_impls!(ManuallyDrop<[UnsafeCell]>: KnownLayout, TryFromBytes, FromZeros, IntoBytes, Unaligned, !Immutable, !FromBytes); + + assert_impls!(CoreMaybeUninit: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, Unaligned, !IntoBytes); + assert_impls!(CoreMaybeUninit: KnownLayout, TryFromBytes, FromZeros, FromBytes, !Immutable, !IntoBytes, !Unaligned); + assert_impls!(CoreMaybeUninit>: KnownLayout, TryFromBytes, FromZeros, FromBytes, Unaligned, !Immutable, !IntoBytes); + + assert_impls!(Wrapping: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + // This test is important because it allows us to test our hand-rolled + // implementation of ` as TryFromBytes>::is_bit_valid`. + assert_impls!(Wrapping: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); + assert_impls!(Wrapping: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(Wrapping>: KnownLayout, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned, !Immutable); + + assert_impls!(Unalign: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, Unaligned); + // This test is important because it allows us to test our hand-rolled + // implementation of ` as TryFromBytes>::is_bit_valid`. + assert_impls!(Unalign: KnownLayout, Immutable, TryFromBytes, FromZeros, IntoBytes, Unaligned, !FromBytes); + assert_impls!(Unalign: KnownLayout, Unaligned, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes); + + assert_impls!( + [u8]: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned + ); + assert_impls!( + [bool]: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + IntoBytes, + Unaligned, + !FromBytes + ); + assert_impls!([NotZerocopy]: KnownLayout, !Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!( + [u8; 0]: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned, + ); + assert_impls!( + [NotZerocopy; 0]: KnownLayout, + !Immutable, + !TryFromBytes, + !FromZeros, + !FromBytes, + !IntoBytes, + !Unaligned + ); + assert_impls!( + [u8; 1]: KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned, + ); + assert_impls!( + [NotZerocopy; 1]: KnownLayout, + !Immutable, + !TryFromBytes, + !FromZeros, + !FromBytes, + !IntoBytes, + !Unaligned + ); + + assert_impls!(*const NotZerocopy: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(*mut NotZerocopy: KnownLayout, Immutable, TryFromBytes, FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(*const [NotZerocopy]: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(*mut [NotZerocopy]: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(*const dyn Debug: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + assert_impls!(*mut dyn Debug: KnownLayout, Immutable, !TryFromBytes, !FromZeros, !FromBytes, !IntoBytes, !Unaligned); + + #[cfg(feature = "simd")] + { + #[allow(unused_macros)] + macro_rules! test_simd_arch_mod { + ($arch:ident, $($typ:ident),*) => { + { + use core::arch::$arch::{$($typ),*}; + use crate::*; + $( assert_impls!($typ: KnownLayout, Immutable, TryFromBytes, FromZeros, FromBytes, IntoBytes, !Unaligned); )* + } + }; + } + #[cfg(target_arch = "x86")] + test_simd_arch_mod!(x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i); + + #[cfg(all(feature = "simd-nightly", target_arch = "x86"))] + test_simd_arch_mod!(x86, __m512bh, __m512, __m512d, __m512i); + + #[cfg(target_arch = "x86_64")] + test_simd_arch_mod!(x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i); + + #[cfg(all(feature = "simd-nightly", target_arch = "x86_64"))] + test_simd_arch_mod!(x86_64, __m512bh, __m512, __m512d, __m512i); + + #[cfg(target_arch = "wasm32")] + test_simd_arch_mod!(wasm32, v128); + + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))] + test_simd_arch_mod!( + powerpc, + vector_bool_long, + vector_double, + vector_signed_long, + vector_unsigned_long + ); + + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))] + test_simd_arch_mod!( + powerpc64, + vector_bool_long, + vector_double, + vector_signed_long, + vector_unsigned_long + ); + #[cfg(all(target_arch = "aarch64", zerocopy_aarch64_simd_1_59_0))] + #[rustfmt::skip] + test_simd_arch_mod!( + aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t, + int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t, + int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, + poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t, + poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t, + uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x8_t, uint32x2_t, uint32x4_t, + uint64x1_t, uint64x2_t + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2066 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{mem, num::NonZeroUsize}; + +use crate::util; + +/// The target pointer width, counted in bits. +const POINTER_WIDTH_BITS: usize = mem::size_of::() * 8; + +/// The layout of a type which might be dynamically-sized. +/// +/// `DstLayout` describes the layout of sized types, slice types, and "slice +/// DSTs" - ie, those that are known by the type system to have a trailing slice +/// (as distinguished from `dyn Trait` types - such types *might* have a +/// trailing slice type, but the type system isn't aware of it). +/// +/// Note that `DstLayout` does not have any internal invariants, so no guarantee +/// is made that a `DstLayout` conforms to any of Rust's requirements regarding +/// the layout of real Rust types or instances of types. +#[doc(hidden)] +#[allow(missing_debug_implementations, missing_copy_implementations)] +#[cfg_attr(any(kani, test), derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub struct DstLayout { + pub(crate) align: NonZeroUsize, + pub(crate) size_info: SizeInfo, + // Is it guaranteed statically (without knowing a value's runtime metadata) + // that the top-level type contains no padding? This does *not* apply + // recursively - for example, `[(u8, u16)]` has `statically_shallow_unpadded + // = true` even though this type likely has padding inside each `(u8, u16)`. + pub(crate) statically_shallow_unpadded: bool, +} + +#[cfg_attr(any(kani, test), derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub(crate) enum SizeInfo { + Sized { size: usize }, + SliceDst(TrailingSliceLayout), +} + +#[cfg_attr(any(kani, test), derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub(crate) struct TrailingSliceLayout { + // The offset of the first byte of the trailing slice field. Note that this + // is NOT the same as the minimum size of the type. For example, consider + // the following type: + // + // struct Foo { + // a: u16, + // b: u8, + // c: [u8], + // } + // + // In `Foo`, `c` is at byte offset 3. When `c.len() == 0`, `c` is followed + // by a padding byte. + pub(crate) offset: usize, + // The size of the element type of the trailing slice field. + pub(crate) elem_size: E, +} + +impl SizeInfo { + /// Attempts to create a `SizeInfo` from `Self` in which `elem_size` is a + /// `NonZeroUsize`. If `elem_size` is 0, returns `None`. + #[allow(unused)] + const fn try_to_nonzero_elem_size(&self) -> Option> { + Some(match *self { + SizeInfo::Sized { size } => SizeInfo::Sized { size }, + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => { + if let Some(elem_size) = NonZeroUsize::new(elem_size) { + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) + } else { + return None; + } + } + }) + } +} + +#[doc(hidden)] +#[derive(Copy, Clone)] +#[cfg_attr(test, derive(Debug))] +#[allow(missing_debug_implementations)] +pub enum CastType { + Prefix, + Suffix, +} + +#[cfg_attr(test, derive(Debug))] +pub(crate) enum MetadataCastError { + Alignment, + Size, +} + +impl DstLayout { + /// The minimum possible alignment of a type. + const MIN_ALIGN: NonZeroUsize = match NonZeroUsize::new(1) { + Some(min_align) => min_align, + None => const_unreachable!(), + }; + + /// The maximum theoretic possible alignment of a type. + /// + /// For compatibility with future Rust versions, this is defined as the + /// maximum power-of-two that fits into a `usize`. See also + /// [`DstLayout::CURRENT_MAX_ALIGN`]. + pub(crate) const THEORETICAL_MAX_ALIGN: NonZeroUsize = + match NonZeroUsize::new(1 << (POINTER_WIDTH_BITS - 1)) { + Some(max_align) => max_align, + None => const_unreachable!(), + }; + + /// The current, documented max alignment of a type \[1\]. + /// + /// \[1\] Per : + /// + /// The alignment value must be a power of two from 1 up to + /// 229. + #[cfg(not(kani))] + #[cfg(not(target_pointer_width = "16"))] + pub(crate) const CURRENT_MAX_ALIGN: NonZeroUsize = match NonZeroUsize::new(1 << 28) { + Some(max_align) => max_align, + None => const_unreachable!(), + }; + + #[cfg(not(kani))] + #[cfg(target_pointer_width = "16")] + pub(crate) const CURRENT_MAX_ALIGN: NonZeroUsize = match NonZeroUsize::new(1 << 15) { + Some(max_align) => max_align, + None => const_unreachable!(), + }; + + /// Assumes that this layout lacks static shallow padding. + /// + /// # Panics + /// + /// This method does not panic. + /// + /// # Safety + /// + /// If `self` describes the size and alignment of type that lacks static + /// shallow padding, unsafe code may assume that the result of this method + /// accurately reflects the size, alignment, and lack of static shallow + /// padding of that type. + const fn assume_shallow_unpadded(self) -> Self { + Self { statically_shallow_unpadded: true, ..self } + } + + /// Constructs a `DstLayout` for a zero-sized type with `repr_align` + /// alignment (or 1). If `repr_align` is provided, then it must be a power + /// of two. + /// + /// # Panics + /// + /// This function panics if the supplied `repr_align` is not a power of two. + /// + /// # Safety + /// + /// Unsafe code may assume that the contract of this function is satisfied. + #[doc(hidden)] + #[must_use] + #[inline] + pub const fn new_zst(repr_align: Option) -> DstLayout { + let align = match repr_align { + Some(align) => align, + None => Self::MIN_ALIGN, + }; + + const_assert!(align.get().is_power_of_two()); + + DstLayout { + align, + size_info: SizeInfo::Sized { size: 0 }, + statically_shallow_unpadded: true, + } + } + + /// Constructs a `DstLayout` which describes `T` and assumes `T` may contain + /// padding. + /// + /// # Safety + /// + /// Unsafe code may assume that `DstLayout` is the correct layout for `T`. + #[doc(hidden)] + #[must_use] + #[inline] + pub const fn for_type() -> DstLayout { + // SAFETY: `align` is correct by construction. `T: Sized`, and so it is + // sound to initialize `size_info` to `SizeInfo::Sized { size }`; the + // `size` field is also correct by construction. `unpadded` can safely + // default to `false`. + DstLayout { + align: match NonZeroUsize::new(mem::align_of::()) { + Some(align) => align, + None => const_unreachable!(), + }, + size_info: SizeInfo::Sized { size: mem::size_of::() }, + statically_shallow_unpadded: false, + } + } + + /// Constructs a `DstLayout` which describes a `T` that does not contain + /// padding. + /// + /// # Safety + /// + /// Unsafe code may assume that `DstLayout` is the correct layout for `T`. + #[doc(hidden)] + #[must_use] + #[inline] + pub const fn for_unpadded_type() -> DstLayout { + Self::for_type::().assume_shallow_unpadded() + } + + /// Constructs a `DstLayout` which describes `[T]`. + /// + /// # Safety + /// + /// Unsafe code may assume that `DstLayout` is the correct layout for `[T]`. + pub(crate) const fn for_slice() -> DstLayout { + // SAFETY: The alignment of a slice is equal to the alignment of its + // element type, and so `align` is initialized correctly. + // + // Since this is just a slice type, there is no offset between the + // beginning of the type and the beginning of the slice, so it is + // correct to set `offset: 0`. The `elem_size` is correct by + // construction. Since `[T]` is a (degenerate case of a) slice DST, it + // is correct to initialize `size_info` to `SizeInfo::SliceDst`. + DstLayout { + align: match NonZeroUsize::new(mem::align_of::()) { + Some(align) => align, + None => const_unreachable!(), + }, + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + offset: 0, + elem_size: mem::size_of::(), + }), + statically_shallow_unpadded: true, + } + } + + /// Constructs a complete `DstLayout` reflecting a `repr(C)` struct with the + /// given alignment modifiers and fields. + /// + /// This method cannot be used to match the layout of a record with the + /// default representation, as that representation is mostly unspecified. + /// + /// # Safety + /// + /// For any definition of a `repr(C)` struct, if this method is invoked with + /// alignment modifiers and fields corresponding to that definition, the + /// resulting `DstLayout` will correctly encode the layout of that struct. + /// + /// We make no guarantees to the behavior of this method when it is invoked + /// with arguments that cannot correspond to a valid `repr(C)` struct. + #[must_use] + #[inline] + pub const fn for_repr_c_struct( + repr_align: Option, + repr_packed: Option, + fields: &[DstLayout], + ) -> DstLayout { + let mut layout = DstLayout::new_zst(repr_align); + + let mut i = 0; + #[allow(clippy::arithmetic_side_effects)] + while i < fields.len() { + #[allow(clippy::indexing_slicing)] + let field = fields[i]; + layout = layout.extend(field, repr_packed); + i += 1; + } + + layout = layout.pad_to_align(); + + // SAFETY: `layout` accurately describes the layout of a `repr(C)` + // struct with `repr_align` or `repr_packed` alignment modifications and + // the given `fields`. The `layout` is constructed using a sequence of + // invocations of `DstLayout::{new_zst,extend,pad_to_align}`. The + // documentation of these items vows that invocations in this manner + // will accurately describe a type, so long as: + // + // - that type is `repr(C)`, + // - its fields are enumerated in the order they appear, + // - the presence of `repr_align` and `repr_packed` are correctly accounted for. + // + // We respect all three of these preconditions above. + layout + } + + /// Like `Layout::extend`, this creates a layout that describes a record + /// whose layout consists of `self` followed by `next` that includes the + /// necessary inter-field padding, but not any trailing padding. + /// + /// In order to match the layout of a `#[repr(C)]` struct, this method + /// should be invoked for each field in declaration order. To add trailing + /// padding, call `DstLayout::pad_to_align` after extending the layout for + /// all fields. If `self` corresponds to a type marked with + /// `repr(packed(N))`, then `repr_packed` should be set to `Some(N)`, + /// otherwise `None`. + /// + /// This method cannot be used to match the layout of a record with the + /// default representation, as that representation is mostly unspecified. + /// + /// # Safety + /// + /// If a (potentially hypothetical) valid `repr(C)` Rust type begins with + /// fields whose layout are `self`, and those fields are immediately + /// followed by a field whose layout is `field`, then unsafe code may rely + /// on `self.extend(field, repr_packed)` producing a layout that correctly + /// encompasses those two components. + /// + /// We make no guarantees to the behavior of this method if these fragments + /// cannot appear in a valid Rust type (e.g., the concatenation of the + /// layouts would lead to a size larger than `isize::MAX`). + #[doc(hidden)] + #[must_use] + #[inline] + pub const fn extend(self, field: DstLayout, repr_packed: Option) -> Self { + use util::{max, min, padding_needed_for}; + + // If `repr_packed` is `None`, there are no alignment constraints, and + // the value can be defaulted to `THEORETICAL_MAX_ALIGN`. + let max_align = match repr_packed { + Some(max_align) => max_align, + None => Self::THEORETICAL_MAX_ALIGN, + }; + + const_assert!(max_align.get().is_power_of_two()); + + // We use Kani to prove that this method is robust to future increases + // in Rust's maximum allowed alignment. However, if such a change ever + // actually occurs, we'd like to be notified via assertion failures. + #[cfg(not(kani))] + { + const_debug_assert!(self.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get()); + const_debug_assert!(field.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get()); + if let Some(repr_packed) = repr_packed { + const_debug_assert!(repr_packed.get() <= DstLayout::CURRENT_MAX_ALIGN.get()); + } + } + + // The field's alignment is clamped by `repr_packed` (i.e., the + // `repr(packed(N))` attribute, if any) [1]. + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // The alignments of each field, for the purpose of positioning + // fields, is the smaller of the specified alignment and the alignment + // of the field's type. + let field_align = min(field.align, max_align); + + // The struct's alignment is the maximum of its previous alignment and + // `field_align`. + let align = max(self.align, field_align); + + let (interfield_padding, size_info) = match self.size_info { + // If the layout is already a DST, we panic; DSTs cannot be extended + // with additional fields. + SizeInfo::SliceDst(..) => const_panic!("Cannot extend a DST with additional fields."), + + SizeInfo::Sized { size: preceding_size } => { + // Compute the minimum amount of inter-field padding needed to + // satisfy the field's alignment, and offset of the trailing + // field. [1] + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // Inter-field padding is guaranteed to be the minimum + // required in order to satisfy each field's (possibly + // altered) alignment. + let padding = padding_needed_for(preceding_size, field_align); + + // This will not panic (and is proven to not panic, with Kani) + // if the layout components can correspond to a leading layout + // fragment of a valid Rust type, but may panic otherwise (e.g., + // combining or aligning the components would create a size + // exceeding `isize::MAX`). + let offset = match preceding_size.checked_add(padding) { + Some(offset) => offset, + None => const_panic!("Adding padding to `self`'s size overflows `usize`."), + }; + + ( + padding, + match field.size_info { + SizeInfo::Sized { size: field_size } => { + // If the trailing field is sized, the resulting layout + // will be sized. Its size will be the sum of the + // preceding layout, the size of the new field, and the + // size of inter-field padding between the two. + // + // This will not panic (and is proven with Kani to not + // panic) if the layout components can correspond to a + // leading layout fragment of a valid Rust type, but may + // panic otherwise (e.g., combining or aligning the + // components would create a size exceeding + // `usize::MAX`). + let size = match offset.checked_add(field_size) { + Some(size) => size, + None => const_panic!("`field` cannot be appended without the total size overflowing `usize`"), + }; + SizeInfo::Sized { size } + } + SizeInfo::SliceDst(TrailingSliceLayout { + offset: trailing_offset, + elem_size, + }) => { + // If the trailing field is dynamically sized, so too + // will the resulting layout. The offset of the trailing + // slice component is the sum of the offset of the + // trailing field and the trailing slice offset within + // that field. + // + // This will not panic (and is proven with Kani to not + // panic) if the layout components can correspond to a + // leading layout fragment of a valid Rust type, but may + // panic otherwise (e.g., combining or aligning the + // components would create a size exceeding + // `usize::MAX`). + let offset = match offset.checked_add(trailing_offset) { + Some(offset) => offset, + None => const_panic!("`field` cannot be appended without the total size overflowing `usize`"), + }; + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) + } + }, + ) + } + }; + + let statically_shallow_unpadded = self.statically_shallow_unpadded + && field.statically_shallow_unpadded + && interfield_padding == 0; + + DstLayout { align, size_info, statically_shallow_unpadded } + } + + /// Like `Layout::pad_to_align`, this routine rounds the size of this layout + /// up to the nearest multiple of this type's alignment or `repr_packed` + /// (whichever is less). This method leaves DST layouts unchanged, since the + /// trailing padding of DSTs is computed at runtime. + /// + /// The accompanying boolean is `true` if the resulting composition of + /// fields necessitated static (as opposed to dynamic) padding; otherwise + /// `false`. + /// + /// In order to match the layout of a `#[repr(C)]` struct, this method + /// should be invoked after the invocations of [`DstLayout::extend`]. If + /// `self` corresponds to a type marked with `repr(packed(N))`, then + /// `repr_packed` should be set to `Some(N)`, otherwise `None`. + /// + /// This method cannot be used to match the layout of a record with the + /// default representation, as that representation is mostly unspecified. + /// + /// # Safety + /// + /// If a (potentially hypothetical) valid `repr(C)` type begins with fields + /// whose layout are `self` followed only by zero or more bytes of trailing + /// padding (not included in `self`), then unsafe code may rely on + /// `self.pad_to_align(repr_packed)` producing a layout that correctly + /// encapsulates the layout of that type. + /// + /// We make no guarantees to the behavior of this method if `self` cannot + /// appear in a valid Rust type (e.g., because the addition of trailing + /// padding would lead to a size larger than `isize::MAX`). + #[doc(hidden)] + #[must_use] + #[inline] + pub const fn pad_to_align(self) -> Self { + use util::padding_needed_for; + + let (static_padding, size_info) = match self.size_info { + // For sized layouts, we add the minimum amount of trailing padding + // needed to satisfy alignment. + SizeInfo::Sized { size: unpadded_size } => { + let padding = padding_needed_for(unpadded_size, self.align); + let size = match unpadded_size.checked_add(padding) { + Some(size) => size, + None => const_panic!("Adding padding caused size to overflow `usize`."), + }; + (padding, SizeInfo::Sized { size }) + } + // For DST layouts, trailing padding depends on the length of the + // trailing DST and is computed at runtime. This does not alter the + // offset or element size of the layout, so we leave `size_info` + // unchanged. + size_info @ SizeInfo::SliceDst(_) => (0, size_info), + }; + + let statically_shallow_unpadded = self.statically_shallow_unpadded && static_padding == 0; + + DstLayout { align: self.align, size_info, statically_shallow_unpadded } + } + + /// Produces `true` if `self` requires static padding; otherwise `false`. + #[must_use] + #[inline(always)] + pub const fn requires_static_padding(self) -> bool { + !self.statically_shallow_unpadded + } + + /// Produces `true` if there exists any metadata for which a type of layout + /// `self` would require dynamic trailing padding; otherwise `false`. + #[must_use] + #[inline(always)] + pub const fn requires_dynamic_padding(self) -> bool { + // A `% self.align.get()` cannot panic, since `align` is non-zero. + #[allow(clippy::arithmetic_side_effects)] + match self.size_info { + SizeInfo::Sized { .. } => false, + SizeInfo::SliceDst(trailing_slice_layout) => { + // SAFETY: This predicate is formally proved sound by + // `proofs::prove_requires_dynamic_padding`. + trailing_slice_layout.offset % self.align.get() != 0 + || trailing_slice_layout.elem_size % self.align.get() != 0 + } + } + } + + /// Validates that a cast is sound from a layout perspective. + /// + /// Validates that the size and alignment requirements of a type with the + /// layout described in `self` would not be violated by performing a + /// `cast_type` cast from a pointer with address `addr` which refers to a + /// memory region of size `bytes_len`. + /// + /// If the cast is valid, `validate_cast_and_convert_metadata` returns + /// `(elems, split_at)`. If `self` describes a dynamically-sized type, then + /// `elems` is the maximum number of trailing slice elements for which a + /// cast would be valid (for sized types, `elem` is meaningless and should + /// be ignored). `split_at` is the index at which to split the memory region + /// in order for the prefix (suffix) to contain the result of the cast, and + /// in order for the remaining suffix (prefix) to contain the leftover + /// bytes. + /// + /// There are three conditions under which a cast can fail: + /// - The smallest possible value for the type is larger than the provided + /// memory region + /// - A prefix cast is requested, and `addr` does not satisfy `self`'s + /// alignment requirement + /// - A suffix cast is requested, and `addr + bytes_len` does not satisfy + /// `self`'s alignment requirement (as a consequence, since all instances + /// of the type are a multiple of its alignment, no size for the type will + /// result in a starting address which is properly aligned) + /// + /// # Safety + /// + /// The caller may assume that this implementation is correct, and may rely + /// on that assumption for the soundness of their code. In particular, the + /// caller may assume that, if `validate_cast_and_convert_metadata` returns + /// `Some((elems, split_at))`, then: + /// - A pointer to the type (for dynamically sized types, this includes + /// `elems` as its pointer metadata) describes an object of size `size <= + /// bytes_len` + /// - If this is a prefix cast: + /// - `addr` satisfies `self`'s alignment + /// - `size == split_at` + /// - If this is a suffix cast: + /// - `split_at == bytes_len - size` + /// - `addr + split_at` satisfies `self`'s alignment + /// + /// Note that this method does *not* ensure that a pointer constructed from + /// its return values will be a valid pointer. In particular, this method + /// does not reason about `isize` overflow, which is a requirement of many + /// Rust pointer APIs, and may at some point be determined to be a validity + /// invariant of pointer types themselves. This should never be a problem so + /// long as the arguments to this method are derived from a known-valid + /// pointer (e.g., one derived from a safe Rust reference), but it is + /// nonetheless the caller's responsibility to justify that pointer + /// arithmetic will not overflow based on a safety argument *other than* the + /// mere fact that this method returned successfully. + /// + /// # Panics + /// + /// `validate_cast_and_convert_metadata` will panic if `self` describes a + /// DST whose trailing slice element is zero-sized. + /// + /// If `addr + bytes_len` overflows `usize`, + /// `validate_cast_and_convert_metadata` may panic, or it may return + /// incorrect results. No guarantees are made about when + /// `validate_cast_and_convert_metadata` will panic. The caller should not + /// rely on `validate_cast_and_convert_metadata` panicking in any particular + /// condition, even if `debug_assertions` are enabled. + #[allow(unused)] + #[inline(always)] + pub(crate) const fn validate_cast_and_convert_metadata( + &self, + addr: usize, + bytes_len: usize, + cast_type: CastType, + ) -> Result<(usize, usize), MetadataCastError> { + // `debug_assert!`, but with `#[allow(clippy::arithmetic_side_effects)]`. + macro_rules! __const_debug_assert { + ($e:expr $(, $msg:expr)?) => { + const_debug_assert!({ + #[allow(clippy::arithmetic_side_effects)] + let e = $e; + e + } $(, $msg)?); + }; + } + + // Note that, in practice, `self` is always a compile-time constant. We + // do this check earlier than needed to ensure that we always panic as a + // result of bugs in the program (such as calling this function on an + // invalid type) instead of allowing this panic to be hidden if the cast + // would have failed anyway for runtime reasons (such as a too-small + // memory region). + // + // FIXME(#67): Once our MSRV is 1.65, use let-else: + // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements + let size_info = match self.size_info.try_to_nonzero_elem_size() { + Some(size_info) => size_info, + None => const_panic!("attempted to cast to slice type with zero-sized element"), + }; + + // Precondition + __const_debug_assert!( + addr.checked_add(bytes_len).is_some(), + "`addr` + `bytes_len` > usize::MAX" + ); + + // Alignment checks go in their own block to avoid introducing variables + // into the top-level scope. + { + // We check alignment for `addr` (for prefix casts) or `addr + + // bytes_len` (for suffix casts). For a prefix cast, the correctness + // of this check is trivial - `addr` is the address the object will + // live at. + // + // For a suffix cast, we know that all valid sizes for the type are + // a multiple of the alignment (and by safety precondition, we know + // `DstLayout` may only describe valid Rust types). Thus, a + // validly-sized instance which lives at a validly-aligned address + // must also end at a validly-aligned address. Thus, if the end + // address for a suffix cast (`addr + bytes_len`) is not aligned, + // then no valid start address will be aligned either. + let offset = match cast_type { + CastType::Prefix => 0, + CastType::Suffix => bytes_len, + }; + + // Addition is guaranteed not to overflow because `offset <= + // bytes_len`, and `addr + bytes_len <= usize::MAX` is a + // precondition of this method. Modulus is guaranteed not to divide + // by 0 because `align` is non-zero. + #[allow(clippy::arithmetic_side_effects)] + if (addr + offset) % self.align.get() != 0 { + return Err(MetadataCastError::Alignment); + } + } + + let (elems, self_bytes) = match size_info { + SizeInfo::Sized { size } => { + if size > bytes_len { + return Err(MetadataCastError::Size); + } + (0, size) + } + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => { + // Calculate the maximum number of bytes that could be consumed + // - any number of bytes larger than this will either not be a + // multiple of the alignment, or will be larger than + // `bytes_len`. + let max_total_bytes = + util::round_down_to_next_multiple_of_alignment(bytes_len, self.align); + // Calculate the maximum number of bytes that could be consumed + // by the trailing slice. + // + // FIXME(#67): Once our MSRV is 1.65, use let-else: + // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements + let max_slice_and_padding_bytes = match max_total_bytes.checked_sub(offset) { + Some(max) => max, + // `bytes_len` too small even for 0 trailing slice elements. + None => return Err(MetadataCastError::Size), + }; + + // Calculate the number of elements that fit in + // `max_slice_and_padding_bytes`; any remaining bytes will be + // considered padding. + // + // Guaranteed not to divide by zero: `elem_size` is non-zero. + #[allow(clippy::arithmetic_side_effects)] + let elems = max_slice_and_padding_bytes / elem_size.get(); + // Guaranteed not to overflow on multiplication: `usize::MAX >= + // max_slice_and_padding_bytes >= (max_slice_and_padding_bytes / + // elem_size) * elem_size`. + // + // Guaranteed not to overflow on addition: + // - max_slice_and_padding_bytes == max_total_bytes - offset + // - elems * elem_size <= max_slice_and_padding_bytes == max_total_bytes - offset + // - elems * elem_size + offset <= max_total_bytes <= usize::MAX + #[allow(clippy::arithmetic_side_effects)] + let without_padding = offset + elems * elem_size.get(); + // `self_bytes` is equal to the offset bytes plus the bytes + // consumed by the trailing slice plus any padding bytes + // required to satisfy the alignment. Note that we have computed + // the maximum number of trailing slice elements that could fit + // in `self_bytes`, so any padding is guaranteed to be less than + // the size of an extra element. + // + // Guaranteed not to overflow: + // - By previous comment: without_padding == elems * elem_size + + // offset <= max_total_bytes + // - By construction, `max_total_bytes` is a multiple of + // `self.align`. + // - At most, adding padding needed to round `without_padding` + // up to the next multiple of the alignment will bring + // `self_bytes` up to `max_total_bytes`. + #[allow(clippy::arithmetic_side_effects)] + let self_bytes = + without_padding + util::padding_needed_for(without_padding, self.align); + (elems, self_bytes) + } + }; + + __const_debug_assert!(self_bytes <= bytes_len); + + let split_at = match cast_type { + CastType::Prefix => self_bytes, + // Guaranteed not to underflow: + // - In the `Sized` branch, only returns `size` if `size <= + // bytes_len`. + // - In the `SliceDst` branch, calculates `self_bytes <= + // max_toatl_bytes`, which is upper-bounded by `bytes_len`. + #[allow(clippy::arithmetic_side_effects)] + CastType::Suffix => bytes_len - self_bytes, + }; + + Ok((elems, split_at)) + } +} + +pub(crate) use cast_from_raw::cast_from_raw; +mod cast_from_raw { + use crate::{pointer::PtrInner, *}; + + /// Implements [`>::cast_from_raw`][cast_from_raw]. + /// + /// # PME + /// + /// Generates a post-monomorphization error if it is not possible to satisfy + /// the soundness conditions of [`SizeEq::cast_from_raw`][cast_from_raw] + /// for `Src` and `Dst`. + /// + /// [cast_from_raw]: crate::pointer::SizeEq::cast_from_raw + // + // FIXME(#1817): Support Sized->Unsized and Unsized->Sized casts + pub(crate) fn cast_from_raw(src: PtrInner<'_, Src>) -> PtrInner<'_, Dst> + where + Src: KnownLayout + ?Sized, + Dst: KnownLayout + ?Sized, + { + // At compile time (specifically, post-monomorphization time), we need + // to compute two things: + // - Whether, given *any* `*Src`, it is possible to construct a `*Dst` + // which addresses the same number of bytes (ie, whether, for any + // `Src` pointer metadata, there exists `Dst` pointer metadata that + // addresses the same number of bytes) + // - If this is possible, any information necessary to perform the + // `Src`->`Dst` metadata conversion at runtime. + // + // Assume that `Src` and `Dst` are slice DSTs, and define: + // - `S_OFF = Src::LAYOUT.size_info.offset` + // - `S_ELEM = Src::LAYOUT.size_info.elem_size` + // - `D_OFF = Dst::LAYOUT.size_info.offset` + // - `D_ELEM = Dst::LAYOUT.size_info.elem_size` + // + // We are trying to solve the following equation: + // + // D_OFF + d_meta * D_ELEM = S_OFF + s_meta * S_ELEM + // + // At runtime, we will be attempting to compute `d_meta`, given `s_meta` + // (a runtime value) and all other parameters (which are compile-time + // values). We can solve like so: + // + // D_OFF + d_meta * D_ELEM = S_OFF + s_meta * S_ELEM + // + // d_meta * D_ELEM = S_OFF - D_OFF + s_meta * S_ELEM + // + // d_meta = (S_OFF - D_OFF + s_meta * S_ELEM)/D_ELEM + // + // Since `d_meta` will be a `usize`, we need the right-hand side to be + // an integer, and this needs to hold for *any* value of `s_meta` (in + // order for our conversion to be infallible - ie, to not have to reject + // certain values of `s_meta` at runtime). This means that: + // - `s_meta * S_ELEM` must be a multiple of `D_ELEM` + // - Since this must hold for any value of `s_meta`, `S_ELEM` must be a + // multiple of `D_ELEM` + // - `S_OFF - D_OFF` must be a multiple of `D_ELEM` + // + // Thus, let `OFFSET_DELTA_ELEMS = (S_OFF - D_OFF)/D_ELEM` and + // `ELEM_MULTIPLE = S_ELEM/D_ELEM`. We can rewrite the above expression + // as: + // + // d_meta = (S_OFF - D_OFF + s_meta * S_ELEM)/D_ELEM + // + // d_meta = OFFSET_DELTA_ELEMS + s_meta * ELEM_MULTIPLE + // + // Thus, we just need to compute the following and confirm that they + // have integer solutions in order to both a) determine whether + // infallible `Src` -> `Dst` casts are possible and, b) pre-compute the + // parameters necessary to perform those casts at runtime. These + // parameters are encapsulated in `CastParams`, which acts as a witness + // that such infallible casts are possible. + + /// The parameters required in order to perform a pointer cast from + /// `Src` to `Dst` as described above. + /// + /// These are a compile-time function of the layouts of `Src` and `Dst`. + /// + /// # Safety + /// + /// `offset_delta_elems` and `elem_multiple` must be valid as described + /// above. + /// + /// `Src`'s alignment must not be smaller than `Dst`'s alignment. + #[derive(Copy, Clone)] + struct CastParams { + offset_delta_elems: usize, + elem_multiple: usize, + } + + impl CastParams { + const fn try_compute(src: &DstLayout, dst: &DstLayout) -> Option { + if src.align.get() < dst.align.get() { + return None; + } + + let (src, dst) = if let (SizeInfo::SliceDst(src), SizeInfo::SliceDst(dst)) = + (src.size_info, dst.size_info) + { + (src, dst) + } else { + return None; + }; + + let offset_delta = if let Some(od) = src.offset.checked_sub(dst.offset) { + od + } else { + return None; + }; + + let dst_elem_size = if let Some(e) = NonZeroUsize::new(dst.elem_size) { + e + } else { + return None; + }; + + // PANICS: `dst_elem_size: NonZeroUsize`, so this won't div by zero. + #[allow(clippy::arithmetic_side_effects)] + let delta_mod_other_elem = offset_delta % dst_elem_size.get(); + + // PANICS: `dst_elem_size: NonZeroUsize`, so this won't div by zero. + #[allow(clippy::arithmetic_side_effects)] + let elem_remainder = src.elem_size % dst_elem_size.get(); + + if delta_mod_other_elem != 0 || src.elem_size < dst.elem_size || elem_remainder != 0 + { + return None; + } + + // PANICS: `dst_elem_size: NonZeroUsize`, so this won't div by zero. + #[allow(clippy::arithmetic_side_effects)] + let offset_delta_elems = offset_delta / dst_elem_size.get(); + + // PANICS: `dst_elem_size: NonZeroUsize`, so this won't div by zero. + #[allow(clippy::arithmetic_side_effects)] + let elem_multiple = src.elem_size / dst_elem_size.get(); + + // SAFETY: We checked above that `src.align >= dst.align`. + Some(CastParams { + // SAFETY: We checked above that this is an exact ratio. + offset_delta_elems, + // SAFETY: We checked above that this is an exact ratio. + elem_multiple, + }) + } + + /// # Safety + /// + /// `src_meta` describes a `Src` whose size is no larger than + /// `isize::MAX`. + /// + /// The returned metadata describes a `Dst` of the same size as the + /// original `Src`. + unsafe fn cast_metadata(self, src_meta: usize) -> usize { + #[allow(unused)] + use crate::util::polyfills::*; + + // SAFETY: `self` is a witness that the following equation + // holds: + // + // D_OFF + d_meta * D_ELEM = S_OFF + s_meta * S_ELEM + // + // Since the caller promises that `src_meta` is valid `Src` + // metadata, this math will not overflow, and the returned value + // will describe a `Dst` of the same size. + #[allow(unstable_name_collisions)] + unsafe { + self.offset_delta_elems + .unchecked_add(src_meta.unchecked_mul(self.elem_multiple)) + } + } + } + + trait Params { + const CAST_PARAMS: CastParams; + } + + impl Params for Dst + where + Src: KnownLayout + ?Sized, + Dst: KnownLayout + ?Sized, + { + const CAST_PARAMS: CastParams = + match CastParams::try_compute(&Src::LAYOUT, &Dst::LAYOUT) { + Some(params) => params, + None => const_panic!( + "cannot `transmute_ref!` or `transmute_mut!` between incompatible types" + ), + }; + } + + let src_meta = ::pointer_to_metadata(src.as_non_null().as_ptr()); + let params = >::CAST_PARAMS; + + // SAFETY: `src: PtrInner`, and so by invariant on `PtrInner`, `src`'s + // referent is no larger than `isize::MAX`. + let dst_meta = unsafe { params.cast_metadata(src_meta) }; + + let dst = ::raw_from_ptr_len(src.as_non_null().cast(), dst_meta); + + // SAFETY: By post-condition on `params.cast_metadata`, `dst` addresses + // the same number of bytes as `src`. Since `src: PtrInner`, `src` has + // provenance for its entire referent, which lives inside of a single + // allocation. Since `dst` has the same address as `src` and was + // constructed using provenance-preserving operations, it addresses a + // subset of those bytes, and has provenance for those bytes. + unsafe { PtrInner::new(dst) } + } +} + +// FIXME(#67): For some reason, on our MSRV toolchain, this `allow` isn't +// enforced despite having `#![allow(unknown_lints)]` at the crate root, but +// putting it here works. Once our MSRV is high enough that this bug has been +// fixed, remove this `allow`. +#[allow(unknown_lints)] +#[cfg(test)] +mod tests { + use super::*; + + /// Tests of when a sized `DstLayout` is extended with a sized field. + #[allow(clippy::decimal_literal_representation)] + #[test] + fn test_dst_layout_extend_sized_with_sized() { + // This macro constructs a layout corresponding to a `u8` and extends it + // with a zero-sized trailing field of given alignment `n`. The macro + // tests that the resulting layout has both size and alignment `min(n, + // P)` for all valid values of `repr(packed(P))`. + macro_rules! test_align_is_size { + ($n:expr) => { + let base = DstLayout::for_type::(); + let trailing_field = DstLayout::for_type::>(); + + let packs = + core::iter::once(None).chain((0..29).map(|p| NonZeroUsize::new(2usize.pow(p)))); + + for pack in packs { + let composite = base.extend(trailing_field, pack); + let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN); + let align = $n.min(max_align.get()); + assert_eq!( + composite, + DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::Sized { size: align }, + statically_shallow_unpadded: false, + } + ) + } + }; + } + + test_align_is_size!(1); + test_align_is_size!(2); + test_align_is_size!(4); + test_align_is_size!(8); + test_align_is_size!(16); + test_align_is_size!(32); + test_align_is_size!(64); + test_align_is_size!(128); + test_align_is_size!(256); + test_align_is_size!(512); + test_align_is_size!(1024); + test_align_is_size!(2048); + test_align_is_size!(4096); + test_align_is_size!(8192); + test_align_is_size!(16384); + test_align_is_size!(32768); + test_align_is_size!(65536); + test_align_is_size!(131072); + test_align_is_size!(262144); + test_align_is_size!(524288); + test_align_is_size!(1048576); + test_align_is_size!(2097152); + test_align_is_size!(4194304); + test_align_is_size!(8388608); + test_align_is_size!(16777216); + test_align_is_size!(33554432); + test_align_is_size!(67108864); + test_align_is_size!(33554432); + test_align_is_size!(134217728); + test_align_is_size!(268435456); + } + + /// Tests of when a sized `DstLayout` is extended with a DST field. + #[test] + fn test_dst_layout_extend_sized_with_dst() { + // Test that for all combinations of real-world alignments and + // `repr_packed` values, that the extension of a sized `DstLayout`` with + // a DST field correctly computes the trailing offset in the composite + // layout. + + let aligns = (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()); + let packs = core::iter::once(None).chain(aligns.clone().map(Some)); + + for align in aligns { + for pack in packs.clone() { + let base = DstLayout::for_type::(); + let elem_size = 42; + let trailing_field_offset = 11; + + let trailing_field = DstLayout { + align, + size_info: SizeInfo::SliceDst(TrailingSliceLayout { elem_size, offset: 11 }), + statically_shallow_unpadded: false, + }; + + let composite = base.extend(trailing_field, pack); + + let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN).get(); + + let align = align.get().min(max_align); + + assert_eq!( + composite, + DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + elem_size, + offset: align + trailing_field_offset, + }), + statically_shallow_unpadded: false, + } + ) + } + } + } + + /// Tests that calling `pad_to_align` on a sized `DstLayout` adds the + /// expected amount of trailing padding. + #[test] + fn test_dst_layout_pad_to_align_with_sized() { + // For all valid alignments `align`, construct a one-byte layout aligned + // to `align`, call `pad_to_align`, and assert that the size of the + // resulting layout is equal to `align`. + for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) { + let layout = DstLayout { + align, + size_info: SizeInfo::Sized { size: 1 }, + statically_shallow_unpadded: true, + }; + + assert_eq!( + layout.pad_to_align(), + DstLayout { + align, + size_info: SizeInfo::Sized { size: align.get() }, + statically_shallow_unpadded: align.get() == 1 + } + ); + } + + // Test explicitly-provided combinations of unpadded and padded + // counterparts. + + macro_rules! test { + (unpadded { size: $unpadded_size:expr, align: $unpadded_align:expr } + => padded { size: $padded_size:expr, align: $padded_align:expr }) => { + let unpadded = DstLayout { + align: NonZeroUsize::new($unpadded_align).unwrap(), + size_info: SizeInfo::Sized { size: $unpadded_size }, + statically_shallow_unpadded: false, + }; + let padded = unpadded.pad_to_align(); + + assert_eq!( + padded, + DstLayout { + align: NonZeroUsize::new($padded_align).unwrap(), + size_info: SizeInfo::Sized { size: $padded_size }, + statically_shallow_unpadded: false, + } + ); + }; + } + + test!(unpadded { size: 0, align: 4 } => padded { size: 0, align: 4 }); + test!(unpadded { size: 1, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 2, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 3, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 4, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 5, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 6, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 7, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 8, align: 4 } => padded { size: 8, align: 4 }); + + let current_max_align = DstLayout::CURRENT_MAX_ALIGN.get(); + + test!(unpadded { size: 1, align: current_max_align } + => padded { size: current_max_align, align: current_max_align }); + + test!(unpadded { size: current_max_align + 1, align: current_max_align } + => padded { size: current_max_align * 2, align: current_max_align }); + } + + /// Tests that calling `pad_to_align` on a DST `DstLayout` is a no-op. + #[test] + fn test_dst_layout_pad_to_align_with_dst() { + for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) { + for offset in 0..10 { + for elem_size in 0..10 { + let layout = DstLayout { + align, + size_info: SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }), + statically_shallow_unpadded: false, + }; + assert_eq!(layout.pad_to_align(), layout); + } + } + } + } + + // This test takes a long time when running under Miri, so we skip it in + // that case. This is acceptable because this is a logic test that doesn't + // attempt to expose UB. + #[test] + #[cfg_attr(miri, ignore)] + fn test_validate_cast_and_convert_metadata() { + #[allow(non_local_definitions)] + impl From for SizeInfo { + fn from(size: usize) -> SizeInfo { + SizeInfo::Sized { size } + } + } + + #[allow(non_local_definitions)] + impl From<(usize, usize)> for SizeInfo { + fn from((offset, elem_size): (usize, usize)) -> SizeInfo { + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) + } + } + + fn layout>(s: S, align: usize) -> DstLayout { + DstLayout { + size_info: s.into(), + align: NonZeroUsize::new(align).unwrap(), + statically_shallow_unpadded: false, + } + } + + /// This macro accepts arguments in the form of: + /// + /// layout(_, _).validate(_, _, _), Ok(Some((_, _))) + /// | | | | | | | + /// size ---------+ | | | | | | + /// align -----------+ | | | | | + /// addr ------------------------+ | | | | + /// bytes_len ----------------------+ | | | + /// cast_type -------------------------+ | | + /// elems ------------------------------------------+ | + /// split_at ------------------------------------------+ + /// + /// `.validate` is shorthand for `.validate_cast_and_convert_metadata` + /// for brevity. + /// + /// Each argument can either be an iterator or a wildcard. Each + /// wildcarded variable is implicitly replaced by an iterator over a + /// representative sample of values for that variable. Each `test!` + /// invocation iterates over every combination of values provided by + /// each variable's iterator (ie, the cartesian product) and validates + /// that the results are expected. + /// + /// The final argument uses the same syntax, but it has a different + /// meaning: + /// - If it is `Ok(pat)`, then the pattern `pat` is supplied to + /// a matching assert to validate the computed result for each + /// combination of input values. + /// - If it is `Err(Some(msg) | None)`, then `test!` validates that the + /// call to `validate_cast_and_convert_metadata` panics with the given + /// panic message or, if the current Rust toolchain version is too + /// early to support panicking in `const fn`s, panics with *some* + /// message. In the latter case, the `const_panic!` macro is used, + /// which emits code which causes a non-panicking error at const eval + /// time, but which does panic when invoked at runtime. Thus, it is + /// merely difficult to predict the *value* of this panic. We deem + /// that testing against the real panic strings on stable and nightly + /// toolchains is enough to ensure correctness. + /// + /// Note that the meta-variables that match these variables have the + /// `tt` type, and some valid expressions are not valid `tt`s (such as + /// `a..b`). In this case, wrap the expression in parentheses, and it + /// will become valid `tt`. + macro_rules! test { + ( + layout($size:tt, $align:tt) + .validate($addr:tt, $bytes_len:tt, $cast_type:tt), $expect:pat $(,)? + ) => { + itertools::iproduct!( + test!(@generate_size $size), + test!(@generate_align $align), + test!(@generate_usize $addr), + test!(@generate_usize $bytes_len), + test!(@generate_cast_type $cast_type) + ).for_each(|(size_info, align, addr, bytes_len, cast_type)| { + // Temporarily disable the panic hook installed by the test + // harness. If we don't do this, all panic messages will be + // kept in an internal log. On its own, this isn't a + // problem, but if a non-caught panic ever happens (ie, in + // code later in this test not in this macro), all of the + // previously-buffered messages will be dumped, hiding the + // real culprit. + let previous_hook = std::panic::take_hook(); + // I don't understand why, but this seems to be required in + // addition to the previous line. + std::panic::set_hook(Box::new(|_| {})); + let actual = std::panic::catch_unwind(|| { + layout(size_info, align).validate_cast_and_convert_metadata(addr, bytes_len, cast_type) + }).map_err(|d| { + let msg = d.downcast::<&'static str>().ok().map(|s| *s.as_ref()); + assert!(msg.is_some() || cfg!(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)), "non-string panic messages are not permitted when `--cfg zerocopy_panic_in_const_and_vec_try_reserve` is set"); + msg + }); + std::panic::set_hook(previous_hook); + + assert!( + matches!(actual, $expect), + "layout({:?}, {}).validate_cast_and_convert_metadata({}, {}, {:?})" ,size_info, align, addr, bytes_len, cast_type + ); + }); + }; + (@generate_usize _) => { 0..8 }; + // Generate sizes for both Sized and !Sized types. + (@generate_size _) => { + test!(@generate_size (_)).chain(test!(@generate_size (_, _))) + }; + // Generate sizes for both Sized and !Sized types by chaining + // specified iterators for each. + (@generate_size ($sized_sizes:tt | $unsized_sizes:tt)) => { + test!(@generate_size ($sized_sizes)).chain(test!(@generate_size $unsized_sizes)) + }; + // Generate sizes for Sized types. + (@generate_size (_)) => { test!(@generate_size (0..8)) }; + (@generate_size ($sizes:expr)) => { $sizes.into_iter().map(Into::::into) }; + // Generate sizes for !Sized types. + (@generate_size ($min_sizes:tt, $elem_sizes:tt)) => { + itertools::iproduct!( + test!(@generate_min_size $min_sizes), + test!(@generate_elem_size $elem_sizes) + ).map(Into::::into) + }; + (@generate_fixed_size _) => { (0..8).into_iter().map(Into::::into) }; + (@generate_min_size _) => { 0..8 }; + (@generate_elem_size _) => { 1..8 }; + (@generate_align _) => { [1, 2, 4, 8, 16] }; + (@generate_opt_usize _) => { [None].into_iter().chain((0..8).map(Some).into_iter()) }; + (@generate_cast_type _) => { [CastType::Prefix, CastType::Suffix] }; + (@generate_cast_type $variant:ident) => { [CastType::$variant] }; + // Some expressions need to be wrapped in parentheses in order to be + // valid `tt`s (required by the top match pattern). See the comment + // below for more details. This arm removes these parentheses to + // avoid generating an `unused_parens` warning. + (@$_:ident ($vals:expr)) => { $vals }; + (@$_:ident $vals:expr) => { $vals }; + } + + const EVENS: [usize; 8] = [0, 2, 4, 6, 8, 10, 12, 14]; + const ODDS: [usize; 8] = [1, 3, 5, 7, 9, 11, 13, 15]; + + // base_size is too big for the memory region. + test!( + layout(((1..8) | ((1..8), (1..8))), _).validate([0], [0], _), + Ok(Err(MetadataCastError::Size)) + ); + test!( + layout(((2..8) | ((2..8), (2..8))), _).validate([0], [1], Prefix), + Ok(Err(MetadataCastError::Size)) + ); + test!( + layout(((2..8) | ((2..8), (2..8))), _).validate([0x1000_0000 - 1], [1], Suffix), + Ok(Err(MetadataCastError::Size)) + ); + + // addr is unaligned for prefix cast + test!(layout(_, [2]).validate(ODDS, _, Prefix), Ok(Err(MetadataCastError::Alignment))); + test!(layout(_, [2]).validate(ODDS, _, Prefix), Ok(Err(MetadataCastError::Alignment))); + + // addr is aligned, but end of buffer is unaligned for suffix cast + test!(layout(_, [2]).validate(EVENS, ODDS, Suffix), Ok(Err(MetadataCastError::Alignment))); + test!(layout(_, [2]).validate(EVENS, ODDS, Suffix), Ok(Err(MetadataCastError::Alignment))); + + // Unfortunately, these constants cannot easily be used in the + // implementation of `validate_cast_and_convert_metadata`, since + // `panic!` consumes a string literal, not an expression. + // + // It's important that these messages be in a separate module. If they + // were at the function's top level, we'd pass them to `test!` as, e.g., + // `Err(TRAILING)`, which would run into a subtle Rust footgun - the + // `TRAILING` identifier would be treated as a pattern to match rather + // than a value to check for equality. + mod msgs { + pub(super) const TRAILING: &str = + "attempted to cast to slice type with zero-sized element"; + pub(super) const OVERFLOW: &str = "`addr` + `bytes_len` > usize::MAX"; + } + + // casts with ZST trailing element types are unsupported + test!(layout((_, [0]), _).validate(_, _, _), Err(Some(msgs::TRAILING) | None),); + + // addr + bytes_len must not overflow usize + test!(layout(_, _).validate([usize::MAX], (1..100), _), Err(Some(msgs::OVERFLOW) | None)); + test!(layout(_, _).validate((1..100), [usize::MAX], _), Err(Some(msgs::OVERFLOW) | None)); + test!( + layout(_, _).validate( + [usize::MAX / 2 + 1, usize::MAX], + [usize::MAX / 2 + 1, usize::MAX], + _ + ), + Err(Some(msgs::OVERFLOW) | None) + ); + + // Validates that `validate_cast_and_convert_metadata` satisfies its own + // documented safety postconditions, and also a few other properties + // that aren't documented but we want to guarantee anyway. + fn validate_behavior( + (layout, addr, bytes_len, cast_type): (DstLayout, usize, usize, CastType), + ) { + if let Ok((elems, split_at)) = + layout.validate_cast_and_convert_metadata(addr, bytes_len, cast_type) + { + let (size_info, align) = (layout.size_info, layout.align); + let debug_str = format!( + "layout({:?}, {}).validate_cast_and_convert_metadata({}, {}, {:?}) => ({}, {})", + size_info, align, addr, bytes_len, cast_type, elems, split_at + ); + + // If this is a sized type (no trailing slice), then `elems` is + // meaningless, but in practice we set it to 0. Callers are not + // allowed to rely on this, but a lot of math is nicer if + // they're able to, and some callers might accidentally do that. + let sized = matches!(layout.size_info, SizeInfo::Sized { .. }); + assert!(!(sized && elems != 0), "{}", debug_str); + + let resulting_size = match layout.size_info { + SizeInfo::Sized { size } => size, + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => { + let padded_size = |elems| { + let without_padding = offset + elems * elem_size; + without_padding + util::padding_needed_for(without_padding, align) + }; + + let resulting_size = padded_size(elems); + // Test that `validate_cast_and_convert_metadata` + // computed the largest possible value that fits in the + // given range. + assert!(padded_size(elems + 1) > bytes_len, "{}", debug_str); + resulting_size + } + }; + + // Test safety postconditions guaranteed by + // `validate_cast_and_convert_metadata`. + assert!(resulting_size <= bytes_len, "{}", debug_str); + match cast_type { + CastType::Prefix => { + assert_eq!(addr % align, 0, "{}", debug_str); + assert_eq!(resulting_size, split_at, "{}", debug_str); + } + CastType::Suffix => { + assert_eq!(split_at, bytes_len - resulting_size, "{}", debug_str); + assert_eq!((addr + split_at) % align, 0, "{}", debug_str); + } + } + } else { + let min_size = match layout.size_info { + SizeInfo::Sized { size } => size, + SizeInfo::SliceDst(TrailingSliceLayout { offset, .. }) => { + offset + util::padding_needed_for(offset, layout.align) + } + }; + + // If a cast is invalid, it is either because... + // 1. there are insufficient bytes at the given region for type: + let insufficient_bytes = bytes_len < min_size; + // 2. performing the cast would misalign type: + let base = match cast_type { + CastType::Prefix => 0, + CastType::Suffix => bytes_len, + }; + let misaligned = (base + addr) % layout.align != 0; + + assert!(insufficient_bytes || misaligned); + } + } + + let sizes = 0..8; + let elem_sizes = 1..8; + let size_infos = sizes + .clone() + .map(Into::::into) + .chain(itertools::iproduct!(sizes, elem_sizes).map(Into::::into)); + let layouts = itertools::iproduct!(size_infos, [1, 2, 4, 8, 16, 32]) + .filter(|(size_info, align)| !matches!(size_info, SizeInfo::Sized { size } if size % align != 0)) + .map(|(size_info, align)| layout(size_info, align)); + itertools::iproduct!(layouts, 0..8, 0..8, [CastType::Prefix, CastType::Suffix]) + .for_each(validate_behavior); + } + + #[test] + #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] + fn test_validate_rust_layout() { + use core::{ + convert::TryInto as _, + ptr::{self, NonNull}, + }; + + use crate::util::testutil::*; + + // This test synthesizes pointers with various metadata and uses Rust's + // built-in APIs to confirm that Rust makes decisions about type layout + // which are consistent with what we believe is guaranteed by the + // language. If this test fails, it doesn't just mean our code is wrong + // - it means we're misunderstanding the language's guarantees. + + #[derive(Debug)] + struct MacroArgs { + offset: usize, + align: NonZeroUsize, + elem_size: Option, + } + + /// # Safety + /// + /// `test` promises to only call `addr_of_slice_field` on a `NonNull` + /// which points to a valid `T`. + /// + /// `with_elems` must produce a pointer which points to a valid `T`. + fn test NonNull>( + args: MacroArgs, + with_elems: W, + addr_of_slice_field: Option) -> NonNull>, + ) { + let dst = args.elem_size.is_some(); + let layout = { + let size_info = match args.elem_size { + Some(elem_size) => { + SizeInfo::SliceDst(TrailingSliceLayout { offset: args.offset, elem_size }) + } + None => SizeInfo::Sized { + // Rust only supports types whose sizes are a multiple + // of their alignment. If the macro created a type like + // this: + // + // #[repr(C, align(2))] + // struct Foo([u8; 1]); + // + // ...then Rust will automatically round the type's size + // up to 2. + size: args.offset + util::padding_needed_for(args.offset, args.align), + }, + }; + DstLayout { size_info, align: args.align, statically_shallow_unpadded: false } + }; + + for elems in 0..128 { + let ptr = with_elems(elems); + + if let Some(addr_of_slice_field) = addr_of_slice_field { + let slc_field_ptr = addr_of_slice_field(ptr).as_ptr(); + // SAFETY: Both `slc_field_ptr` and `ptr` are pointers to + // the same valid Rust object. + // Work around https://github.com/rust-lang/rust-clippy/issues/12280 + let offset: usize = + unsafe { slc_field_ptr.byte_offset_from(ptr.as_ptr()).try_into().unwrap() }; + assert_eq!(offset, args.offset); + } + + // SAFETY: `ptr` points to a valid `T`. + let (size, align) = unsafe { + (mem::size_of_val_raw(ptr.as_ptr()), mem::align_of_val_raw(ptr.as_ptr())) + }; + + // Avoid expensive allocation when running under Miri. + let assert_msg = if !cfg!(miri) { + format!("\n{:?}\nsize:{}, align:{}", args, size, align) + } else { + String::new() + }; + + let without_padding = + args.offset + args.elem_size.map(|elem_size| elems * elem_size).unwrap_or(0); + assert!(size >= without_padding, "{}", assert_msg); + assert_eq!(align, args.align.get(), "{}", assert_msg); + + // This encodes the most important part of the test: our + // understanding of how Rust determines the layout of repr(C) + // types. Sized repr(C) types are trivial, but DST types have + // some subtlety. Note that: + // - For sized types, `without_padding` is just the size of the + // type that we constructed for `Foo`. Since we may have + // requested a larger alignment, `Foo` may actually be larger + // than this, hence `padding_needed_for`. + // - For unsized types, `without_padding` is dynamically + // computed from the offset, the element size, and element + // count. We expect that the size of the object should be + // `offset + elem_size * elems` rounded up to the next + // alignment. + let expected_size = + without_padding + util::padding_needed_for(without_padding, args.align); + assert_eq!(expected_size, size, "{}", assert_msg); + + // For zero-sized element types, + // `validate_cast_and_convert_metadata` just panics, so we skip + // testing those types. + if args.elem_size.map(|elem_size| elem_size > 0).unwrap_or(true) { + let addr = ptr.addr().get(); + let (got_elems, got_split_at) = layout + .validate_cast_and_convert_metadata(addr, size, CastType::Prefix) + .unwrap(); + // Avoid expensive allocation when running under Miri. + let assert_msg = if !cfg!(miri) { + format!( + "{}\nvalidate_cast_and_convert_metadata({}, {})", + assert_msg, addr, size, + ) + } else { + String::new() + }; + assert_eq!(got_split_at, size, "{}", assert_msg); + if dst { + assert!(got_elems >= elems, "{}", assert_msg); + if got_elems != elems { + // If `validate_cast_and_convert_metadata` + // returned more elements than `elems`, that + // means that `elems` is not the maximum number + // of elements that can fit in `size` - in other + // words, there is enough padding at the end of + // the value to fit at least one more element. + // If we use this metadata to synthesize a + // pointer, despite having a different element + // count, we still expect it to have the same + // size. + let got_ptr = with_elems(got_elems); + // SAFETY: `got_ptr` is a pointer to a valid `T`. + let size_of_got_ptr = unsafe { mem::size_of_val_raw(got_ptr.as_ptr()) }; + assert_eq!(size_of_got_ptr, size, "{}", assert_msg); + } + } else { + // For sized casts, the returned element value is + // technically meaningless, and we don't guarantee any + // particular value. In practice, it's always zero. + assert_eq!(got_elems, 0, "{}", assert_msg) + } + } + } + } + + macro_rules! validate_against_rust { + ($offset:literal, $align:literal $(, $elem_size:literal)?) => {{ + #[repr(C, align($align))] + struct Foo([u8; $offset]$(, [[u8; $elem_size]])?); + + let args = MacroArgs { + offset: $offset, + align: $align.try_into().unwrap(), + elem_size: { + #[allow(unused)] + let ret = None::; + $(let ret = Some($elem_size);)? + ret + } + }; + + #[repr(C, align($align))] + struct FooAlign; + // Create an aligned buffer to use in order to synthesize + // pointers to `Foo`. We don't ever load values from these + // pointers - we just do arithmetic on them - so having a "real" + // block of memory as opposed to a validly-aligned-but-dangling + // pointer is only necessary to make Miri happy since we run it + // with "strict provenance" checking enabled. + let aligned_buf = Align::<_, FooAlign>::new([0u8; 1024]); + let with_elems = |elems| { + let slc = NonNull::slice_from_raw_parts(NonNull::from(&aligned_buf.t), elems); + #[allow(clippy::as_conversions)] + NonNull::new(slc.as_ptr() as *mut Foo).unwrap() + }; + let addr_of_slice_field = { + #[allow(unused)] + let f = None::) -> NonNull>; + $( + // SAFETY: `test` promises to only call `f` with a `ptr` + // to a valid `Foo`. + let f: Option) -> NonNull> = Some(|ptr: NonNull| unsafe { + NonNull::new(ptr::addr_of_mut!((*ptr.as_ptr()).1)).unwrap().cast::() + }); + let _ = $elem_size; + )? + f + }; + + test::(args, with_elems, addr_of_slice_field); + }}; + } + + // Every permutation of: + // - offset in [0, 4] + // - align in [1, 16] + // - elem_size in [0, 4] (plus no elem_size) + validate_against_rust!(0, 1); + validate_against_rust!(0, 1, 0); + validate_against_rust!(0, 1, 1); + validate_against_rust!(0, 1, 2); + validate_against_rust!(0, 1, 3); + validate_against_rust!(0, 1, 4); + validate_against_rust!(0, 2); + validate_against_rust!(0, 2, 0); + validate_against_rust!(0, 2, 1); + validate_against_rust!(0, 2, 2); + validate_against_rust!(0, 2, 3); + validate_against_rust!(0, 2, 4); + validate_against_rust!(0, 4); + validate_against_rust!(0, 4, 0); + validate_against_rust!(0, 4, 1); + validate_against_rust!(0, 4, 2); + validate_against_rust!(0, 4, 3); + validate_against_rust!(0, 4, 4); + validate_against_rust!(0, 8); + validate_against_rust!(0, 8, 0); + validate_against_rust!(0, 8, 1); + validate_against_rust!(0, 8, 2); + validate_against_rust!(0, 8, 3); + validate_against_rust!(0, 8, 4); + validate_against_rust!(0, 16); + validate_against_rust!(0, 16, 0); + validate_against_rust!(0, 16, 1); + validate_against_rust!(0, 16, 2); + validate_against_rust!(0, 16, 3); + validate_against_rust!(0, 16, 4); + validate_against_rust!(1, 1); + validate_against_rust!(1, 1, 0); + validate_against_rust!(1, 1, 1); + validate_against_rust!(1, 1, 2); + validate_against_rust!(1, 1, 3); + validate_against_rust!(1, 1, 4); + validate_against_rust!(1, 2); + validate_against_rust!(1, 2, 0); + validate_against_rust!(1, 2, 1); + validate_against_rust!(1, 2, 2); + validate_against_rust!(1, 2, 3); + validate_against_rust!(1, 2, 4); + validate_against_rust!(1, 4); + validate_against_rust!(1, 4, 0); + validate_against_rust!(1, 4, 1); + validate_against_rust!(1, 4, 2); + validate_against_rust!(1, 4, 3); + validate_against_rust!(1, 4, 4); + validate_against_rust!(1, 8); + validate_against_rust!(1, 8, 0); + validate_against_rust!(1, 8, 1); + validate_against_rust!(1, 8, 2); + validate_against_rust!(1, 8, 3); + validate_against_rust!(1, 8, 4); + validate_against_rust!(1, 16); + validate_against_rust!(1, 16, 0); + validate_against_rust!(1, 16, 1); + validate_against_rust!(1, 16, 2); + validate_against_rust!(1, 16, 3); + validate_against_rust!(1, 16, 4); + validate_against_rust!(2, 1); + validate_against_rust!(2, 1, 0); + validate_against_rust!(2, 1, 1); + validate_against_rust!(2, 1, 2); + validate_against_rust!(2, 1, 3); + validate_against_rust!(2, 1, 4); + validate_against_rust!(2, 2); + validate_against_rust!(2, 2, 0); + validate_against_rust!(2, 2, 1); + validate_against_rust!(2, 2, 2); + validate_against_rust!(2, 2, 3); + validate_against_rust!(2, 2, 4); + validate_against_rust!(2, 4); + validate_against_rust!(2, 4, 0); + validate_against_rust!(2, 4, 1); + validate_against_rust!(2, 4, 2); + validate_against_rust!(2, 4, 3); + validate_against_rust!(2, 4, 4); + validate_against_rust!(2, 8); + validate_against_rust!(2, 8, 0); + validate_against_rust!(2, 8, 1); + validate_against_rust!(2, 8, 2); + validate_against_rust!(2, 8, 3); + validate_against_rust!(2, 8, 4); + validate_against_rust!(2, 16); + validate_against_rust!(2, 16, 0); + validate_against_rust!(2, 16, 1); + validate_against_rust!(2, 16, 2); + validate_against_rust!(2, 16, 3); + validate_against_rust!(2, 16, 4); + validate_against_rust!(3, 1); + validate_against_rust!(3, 1, 0); + validate_against_rust!(3, 1, 1); + validate_against_rust!(3, 1, 2); + validate_against_rust!(3, 1, 3); + validate_against_rust!(3, 1, 4); + validate_against_rust!(3, 2); + validate_against_rust!(3, 2, 0); + validate_against_rust!(3, 2, 1); + validate_against_rust!(3, 2, 2); + validate_against_rust!(3, 2, 3); + validate_against_rust!(3, 2, 4); + validate_against_rust!(3, 4); + validate_against_rust!(3, 4, 0); + validate_against_rust!(3, 4, 1); + validate_against_rust!(3, 4, 2); + validate_against_rust!(3, 4, 3); + validate_against_rust!(3, 4, 4); + validate_against_rust!(3, 8); + validate_against_rust!(3, 8, 0); + validate_against_rust!(3, 8, 1); + validate_against_rust!(3, 8, 2); + validate_against_rust!(3, 8, 3); + validate_against_rust!(3, 8, 4); + validate_against_rust!(3, 16); + validate_against_rust!(3, 16, 0); + validate_against_rust!(3, 16, 1); + validate_against_rust!(3, 16, 2); + validate_against_rust!(3, 16, 3); + validate_against_rust!(3, 16, 4); + validate_against_rust!(4, 1); + validate_against_rust!(4, 1, 0); + validate_against_rust!(4, 1, 1); + validate_against_rust!(4, 1, 2); + validate_against_rust!(4, 1, 3); + validate_against_rust!(4, 1, 4); + validate_against_rust!(4, 2); + validate_against_rust!(4, 2, 0); + validate_against_rust!(4, 2, 1); + validate_against_rust!(4, 2, 2); + validate_against_rust!(4, 2, 3); + validate_against_rust!(4, 2, 4); + validate_against_rust!(4, 4); + validate_against_rust!(4, 4, 0); + validate_against_rust!(4, 4, 1); + validate_against_rust!(4, 4, 2); + validate_against_rust!(4, 4, 3); + validate_against_rust!(4, 4, 4); + validate_against_rust!(4, 8); + validate_against_rust!(4, 8, 0); + validate_against_rust!(4, 8, 1); + validate_against_rust!(4, 8, 2); + validate_against_rust!(4, 8, 3); + validate_against_rust!(4, 8, 4); + validate_against_rust!(4, 16); + validate_against_rust!(4, 16, 0); + validate_against_rust!(4, 16, 1); + validate_against_rust!(4, 16, 2); + validate_against_rust!(4, 16, 3); + validate_against_rust!(4, 16, 4); + } +} + +#[cfg(kani)] +mod proofs { + use core::alloc::Layout; + + use super::*; + + impl kani::Arbitrary for DstLayout { + fn any() -> Self { + let align: NonZeroUsize = kani::any(); + let size_info: SizeInfo = kani::any(); + + kani::assume(align.is_power_of_two()); + kani::assume(align < DstLayout::THEORETICAL_MAX_ALIGN); + + // For testing purposes, we most care about instantiations of + // `DstLayout` that can correspond to actual Rust types. We use + // `Layout` to verify that our `DstLayout` satisfies the validity + // conditions of Rust layouts. + kani::assume( + match size_info { + SizeInfo::Sized { size } => Layout::from_size_align(size, align.get()), + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size: _ }) => { + // `SliceDst` cannot encode an exact size, but we know + // it is at least `offset` bytes. + Layout::from_size_align(offset, align.get()) + } + } + .is_ok(), + ); + + Self { align: align, size_info: size_info, statically_shallow_unpadded: kani::any() } + } + } + + impl kani::Arbitrary for SizeInfo { + fn any() -> Self { + let is_sized: bool = kani::any(); + + match is_sized { + true => { + let size: usize = kani::any(); + + kani::assume(size <= isize::MAX as _); + + SizeInfo::Sized { size } + } + false => SizeInfo::SliceDst(kani::any()), + } + } + } + + impl kani::Arbitrary for TrailingSliceLayout { + fn any() -> Self { + let elem_size: usize = kani::any(); + let offset: usize = kani::any(); + + kani::assume(elem_size < isize::MAX as _); + kani::assume(offset < isize::MAX as _); + + TrailingSliceLayout { elem_size, offset } + } + } + + #[kani::proof] + fn prove_requires_dynamic_padding() { + let layout: DstLayout = kani::any(); + + let SizeInfo::SliceDst(size_info) = layout.size_info else { + kani::assume(false); + loop {} + }; + + let meta: usize = kani::any(); + + let Some(trailing_slice_size) = size_info.elem_size.checked_mul(meta) else { + // The `trailing_slice_size` exceeds `usize::MAX`; `meta` is invalid. + kani::assume(false); + loop {} + }; + + let Some(unpadded_size) = size_info.offset.checked_add(trailing_slice_size) else { + // The `unpadded_size` exceeds `usize::MAX`; `meta`` is invalid. + kani::assume(false); + loop {} + }; + + if unpadded_size >= isize::MAX as usize { + // The `unpadded_size` exceeds `isize::MAX`; `meta` is invalid. + kani::assume(false); + loop {} + } + + let trailing_padding = util::padding_needed_for(unpadded_size, layout.align); + + if !layout.requires_dynamic_padding() { + assert!(trailing_padding == 0); + } + } + + #[kani::proof] + fn prove_dst_layout_extend() { + use crate::util::{max, min, padding_needed_for}; + + let base: DstLayout = kani::any(); + let field: DstLayout = kani::any(); + let packed: Option = kani::any(); + + if let Some(max_align) = packed { + kani::assume(max_align.is_power_of_two()); + kani::assume(base.align <= max_align); + } + + // The base can only be extended if it's sized. + kani::assume(matches!(base.size_info, SizeInfo::Sized { .. })); + let base_size = if let SizeInfo::Sized { size } = base.size_info { + size + } else { + unreachable!(); + }; + + // Under the above conditions, `DstLayout::extend` will not panic. + let composite = base.extend(field, packed); + + // The field's alignment is clamped by `max_align` (i.e., the + // `packed` attribute, if any) [1]. + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // The alignments of each field, for the purpose of positioning + // fields, is the smaller of the specified alignment and the + // alignment of the field's type. + let field_align = min(field.align, packed.unwrap_or(DstLayout::THEORETICAL_MAX_ALIGN)); + + // The struct's alignment is the maximum of its previous alignment and + // `field_align`. + assert_eq!(composite.align, max(base.align, field_align)); + + // Compute the minimum amount of inter-field padding needed to + // satisfy the field's alignment, and offset of the trailing field. + // [1] + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // Inter-field padding is guaranteed to be the minimum required in + // order to satisfy each field's (possibly altered) alignment. + let padding = padding_needed_for(base_size, field_align); + let offset = base_size + padding; + + // For testing purposes, we'll also construct `alloc::Layout` + // stand-ins for `DstLayout`, and show that `extend` behaves + // comparably on both types. + let base_analog = Layout::from_size_align(base_size, base.align.get()).unwrap(); + + match field.size_info { + SizeInfo::Sized { size: field_size } => { + if let SizeInfo::Sized { size: composite_size } = composite.size_info { + // If the trailing field is sized, the resulting layout will + // be sized. Its size will be the sum of the preceding + // layout, the size of the new field, and the size of + // inter-field padding between the two. + assert_eq!(composite_size, offset + field_size); + + let field_analog = + Layout::from_size_align(field_size, field_align.get()).unwrap(); + + if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog) + { + assert_eq!(actual_offset, offset); + assert_eq!(actual_composite.size(), composite_size); + assert_eq!(actual_composite.align(), composite.align.get()); + } else { + // An error here reflects that composite of `base` + // and `field` cannot correspond to a real Rust type + // fragment, because such a fragment would violate + // the basic invariants of a valid Rust layout. At + // the time of writing, `DstLayout` is a little more + // permissive than `Layout`, so we don't assert + // anything in this branch (e.g., unreachability). + } + } else { + panic!("The composite of two sized layouts must be sized.") + } + } + SizeInfo::SliceDst(TrailingSliceLayout { + offset: field_offset, + elem_size: field_elem_size, + }) => { + if let SizeInfo::SliceDst(TrailingSliceLayout { + offset: composite_offset, + elem_size: composite_elem_size, + }) = composite.size_info + { + // The offset of the trailing slice component is the sum + // of the offset of the trailing field and the trailing + // slice offset within that field. + assert_eq!(composite_offset, offset + field_offset); + // The elem size is unchanged. + assert_eq!(composite_elem_size, field_elem_size); + + let field_analog = + Layout::from_size_align(field_offset, field_align.get()).unwrap(); + + if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog) + { + assert_eq!(actual_offset, offset); + assert_eq!(actual_composite.size(), composite_offset); + assert_eq!(actual_composite.align(), composite.align.get()); + } else { + // An error here reflects that composite of `base` + // and `field` cannot correspond to a real Rust type + // fragment, because such a fragment would violate + // the basic invariants of a valid Rust layout. At + // the time of writing, `DstLayout` is a little more + // permissive than `Layout`, so we don't assert + // anything in this branch (e.g., unreachability). + } + } else { + panic!("The extension of a layout with a DST must result in a DST.") + } + } + } + } + + #[kani::proof] + #[kani::should_panic] + fn prove_dst_layout_extend_dst_panics() { + let base: DstLayout = kani::any(); + let field: DstLayout = kani::any(); + let packed: Option = kani::any(); + + if let Some(max_align) = packed { + kani::assume(max_align.is_power_of_two()); + kani::assume(base.align <= max_align); + } + + kani::assume(matches!(base.size_info, SizeInfo::SliceDst(..))); + + let _ = base.extend(field, packed); + } + + #[kani::proof] + fn prove_dst_layout_pad_to_align() { + use crate::util::padding_needed_for; + + let layout: DstLayout = kani::any(); + + let padded = layout.pad_to_align(); + + // Calling `pad_to_align` does not alter the `DstLayout`'s alignment. + assert_eq!(padded.align, layout.align); + + if let SizeInfo::Sized { size: unpadded_size } = layout.size_info { + if let SizeInfo::Sized { size: padded_size } = padded.size_info { + // If the layout is sized, it will remain sized after padding is + // added. Its sum will be its unpadded size and the size of the + // trailing padding needed to satisfy its alignment + // requirements. + let padding = padding_needed_for(unpadded_size, layout.align); + assert_eq!(padded_size, unpadded_size + padding); + + // Prove that calling `DstLayout::pad_to_align` behaves + // identically to `Layout::pad_to_align`. + let layout_analog = + Layout::from_size_align(unpadded_size, layout.align.get()).unwrap(); + let padded_analog = layout_analog.pad_to_align(); + assert_eq!(padded_analog.align(), layout.align.get()); + assert_eq!(padded_analog.size(), padded_size); + } else { + panic!("The padding of a sized layout must result in a sized layout.") + } + } else { + // If the layout is a DST, padding cannot be statically added. + assert_eq!(padded.size_info, layout.size_info); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6786 @@ +// Copyright 2018 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// After updating the following doc comment, make sure to run the following +// command to update `README.md` based on its contents: +// +// cargo -q run --manifest-path tools/Cargo.toml -p generate-readme > README.md + +//! ***Fast, safe, compile error. Pick two.*** +//! +//! Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe` +//! so you don't have to. +//! +//! *For an overview of what's changed from zerocopy 0.7, check out our [release +//! notes][release-notes], which include a step-by-step upgrading guide.* +//! +//! *Have questions? Need more out of zerocopy? Submit a [customer request +//! issue][customer-request-issue] or ask the maintainers on +//! [GitHub][github-q-a] or [Discord][discord]!* +//! +//! [customer-request-issue]: https://github.com/google/zerocopy/issues/new/choose +//! [release-notes]: https://github.com/google/zerocopy/discussions/1680 +//! [github-q-a]: https://github.com/google/zerocopy/discussions/categories/q-a +//! [discord]: https://discord.gg/MAvWH2R6zk +//! +//! # Overview +//! +//! ##### Conversion Traits +//! +//! Zerocopy provides four derivable traits for zero-cost conversions: +//! - [`TryFromBytes`] indicates that a type may safely be converted from +//! certain byte sequences (conditional on runtime checks) +//! - [`FromZeros`] indicates that a sequence of zero bytes represents a valid +//! instance of a type +//! - [`FromBytes`] indicates that a type may safely be converted from an +//! arbitrary byte sequence +//! - [`IntoBytes`] indicates that a type may safely be converted *to* a byte +//! sequence +//! +//! These traits support sized types, slices, and [slice DSTs][slice-dsts]. +//! +//! [slice-dsts]: KnownLayout#dynamically-sized-types +//! +//! ##### Marker Traits +//! +//! Zerocopy provides three derivable marker traits that do not provide any +//! functionality themselves, but are required to call certain methods provided +//! by the conversion traits: +//! - [`KnownLayout`] indicates that zerocopy can reason about certain layout +//! qualities of a type +//! - [`Immutable`] indicates that a type is free from interior mutability, +//! except by ownership or an exclusive (`&mut`) borrow +//! - [`Unaligned`] indicates that a type's alignment requirement is 1 +//! +//! You should generally derive these marker traits whenever possible. +//! +//! ##### Conversion Macros +//! +//! Zerocopy provides six macros for safe casting between types: +//! +//! - ([`try_`][try_transmute])[`transmute`] (conditionally) converts a value of +//! one type to a value of another type of the same size +//! - ([`try_`][try_transmute_mut])[`transmute_mut`] (conditionally) converts a +//! mutable reference of one type to a mutable reference of another type of +//! the same size +//! - ([`try_`][try_transmute_ref])[`transmute_ref`] (conditionally) converts a +//! mutable or immutable reference of one type to an immutable reference of +//! another type of the same size +//! +//! These macros perform *compile-time* size and alignment checks, meaning that +//! unconditional casts have zero cost at runtime. Conditional casts do not need +//! to validate size or alignment runtime, but do need to validate contents. +//! +//! These macros cannot be used in generic contexts. For generic conversions, +//! use the methods defined by the [conversion traits](#conversion-traits). +//! +//! ##### Byteorder-Aware Numerics +//! +//! Zerocopy provides byte-order aware integer types that support these +//! conversions; see the [`byteorder`] module. These types are especially useful +//! for network parsing. +//! +//! # Cargo Features +//! +//! - **`alloc`** +//! By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled, +//! the `alloc` crate is added as a dependency, and some allocation-related +//! functionality is added. +//! +//! - **`std`** +//! By default, `zerocopy` is `no_std`. When the `std` feature is enabled, the +//! `std` crate is added as a dependency (ie, `no_std` is disabled), and +//! support for some `std` types is added. `std` implies `alloc`. +//! +//! - **`derive`** +//! Provides derives for the core marker traits via the `zerocopy-derive` +//! crate. These derives are re-exported from `zerocopy`, so it is not +//! necessary to depend on `zerocopy-derive` directly. +//! +//! However, you may experience better compile times if you instead directly +//! depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`, +//! since doing so will allow Rust to compile these crates in parallel. To do +//! so, do *not* enable the `derive` feature, and list both dependencies in +//! your `Cargo.toml` with the same leading non-zero version number; e.g: +//! +//! ```toml +//! [dependencies] +//! zerocopy = "0.X" +//! zerocopy-derive = "0.X" +//! ``` +//! +//! To avoid the risk of [duplicate import errors][duplicate-import-errors] if +//! one of your dependencies enables zerocopy's `derive` feature, import +//! derives as `use zerocopy_derive::*` rather than by name (e.g., `use +//! zerocopy_derive::FromBytes`). +//! +//! - **`simd`** +//! When the `simd` feature is enabled, `FromZeros`, `FromBytes`, and +//! `IntoBytes` impls are emitted for all stable SIMD types which exist on the +//! target platform. Note that the layout of SIMD types is not yet stabilized, +//! so these impls may be removed in the future if layout changes make them +//! invalid. For more information, see the Unsafe Code Guidelines Reference +//! page on the [layout of packed SIMD vectors][simd-layout]. +//! +//! - **`simd-nightly`** +//! Enables the `simd` feature and adds support for SIMD types which are only +//! available on nightly. Since these types are unstable, support for any type +//! may be removed at any point in the future. +//! +//! - **`float-nightly`** +//! Adds support for the unstable `f16` and `f128` types. These types are +//! not yet fully implemented and may not be supported on all platforms. +//! +//! [duplicate-import-errors]: https://github.com/google/zerocopy/issues/1587 +//! [simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html +//! +//! # Security Ethos +//! +//! Zerocopy is expressly designed for use in security-critical contexts. We +//! strive to ensure that that zerocopy code is sound under Rust's current +//! memory model, and *any future memory model*. We ensure this by: +//! - **...not 'guessing' about Rust's semantics.** +//! We annotate `unsafe` code with a precise rationale for its soundness that +//! cites a relevant section of Rust's official documentation. When Rust's +//! documented semantics are unclear, we work with the Rust Operational +//! Semantics Team to clarify Rust's documentation. +//! - **...rigorously testing our implementation.** +//! We run tests using [Miri], ensuring that zerocopy is sound across a wide +//! array of supported target platforms of varying endianness and pointer +//! width, and across both current and experimental memory models of Rust. +//! - **...formally proving the correctness of our implementation.** +//! We apply formal verification tools like [Kani][kani] to prove zerocopy's +//! correctness. +//! +//! For more information, see our full [soundness policy]. +//! +//! [Miri]: https://github.com/rust-lang/miri +//! [Kani]: https://github.com/model-checking/kani +//! [soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness +//! +//! # Relationship to Project Safe Transmute +//! +//! [Project Safe Transmute] is an official initiative of the Rust Project to +//! develop language-level support for safer transmutation. The Project consults +//! with crates like zerocopy to identify aspects of safer transmutation that +//! would benefit from compiler support, and has developed an [experimental, +//! compiler-supported analysis][mcp-transmutability] which determines whether, +//! for a given type, any value of that type may be soundly transmuted into +//! another type. Once this functionality is sufficiently mature, zerocopy +//! intends to replace its internal transmutability analysis (implemented by our +//! custom derives) with the compiler-supported one. This change will likely be +//! an implementation detail that is invisible to zerocopy's users. +//! +//! Project Safe Transmute will not replace the need for most of zerocopy's +//! higher-level abstractions. The experimental compiler analysis is a tool for +//! checking the soundness of `unsafe` code, not a tool to avoid writing +//! `unsafe` code altogether. For the foreseeable future, crates like zerocopy +//! will still be required in order to provide higher-level abstractions on top +//! of the building block provided by Project Safe Transmute. +//! +//! [Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html +//! [mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411 +//! +//! # MSRV +//! +//! See our [MSRV policy]. +//! +//! [MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv +//! +//! # Changelog +//! +//! Zerocopy uses [GitHub Releases]. +//! +//! [GitHub Releases]: https://github.com/google/zerocopy/releases +//! +//! # Thanks +//! +//! Zerocopy is maintained by engineers at Google and Amazon with help from +//! [many wonderful contributors][contributors]. Thank you to everyone who has +//! lent a hand in making Rust a little more secure! +//! +//! [contributors]: https://github.com/google/zerocopy/graphs/contributors + +// Sometimes we want to use lints which were added after our MSRV. +// `unknown_lints` is `warn` by default and we deny warnings in CI, so without +// this attribute, any unknown lint would cause a CI failure when testing with +// our MSRV. +#![allow(unknown_lints, non_local_definitions, unreachable_patterns)] +#![deny(renamed_and_removed_lints)] +#![deny( + anonymous_parameters, + deprecated_in_future, + late_bound_lifetime_arguments, + missing_copy_implementations, + missing_debug_implementations, + missing_docs, + path_statements, + patterns_in_fns_without_body, + rust_2018_idioms, + trivial_numeric_casts, + unreachable_pub, + unsafe_op_in_unsafe_fn, + unused_extern_crates, + // We intentionally choose not to deny `unused_qualifications`. When items + // are added to the prelude (e.g., `core::mem::size_of`), this has the + // consequence of making some uses trigger this lint on the latest toolchain + // (e.g., `mem::size_of`), but fixing it (e.g. by replacing with `size_of`) + // does not work on older toolchains. + // + // We tested a more complicated fix in #1413, but ultimately decided that, + // since this lint is just a minor style lint, the complexity isn't worth it + // - it's fine to occasionally have unused qualifications slip through, + // especially since these do not affect our user-facing API in any way. + variant_size_differences +)] +#![cfg_attr( + __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, + deny(fuzzy_provenance_casts, lossy_provenance_casts) +)] +#![deny( + clippy::all, + clippy::alloc_instead_of_core, + clippy::arithmetic_side_effects, + clippy::as_underscore, + clippy::assertions_on_result_states, + clippy::as_conversions, + clippy::correctness, + clippy::dbg_macro, + clippy::decimal_literal_representation, + clippy::double_must_use, + clippy::get_unwrap, + clippy::indexing_slicing, + clippy::missing_inline_in_public_items, + clippy::missing_safety_doc, + clippy::must_use_candidate, + clippy::must_use_unit, + clippy::obfuscated_if_else, + clippy::perf, + clippy::print_stdout, + clippy::return_self_not_must_use, + clippy::std_instead_of_core, + clippy::style, + clippy::suspicious, + clippy::todo, + clippy::undocumented_unsafe_blocks, + clippy::unimplemented, + clippy::unnested_or_patterns, + clippy::unwrap_used, + clippy::use_debug +)] +// `clippy::incompatible_msrv` (implied by `clippy::suspicious`): This sometimes +// has false positives, and we test on our MSRV in CI, so it doesn't help us +// anyway. +#![allow(clippy::needless_lifetimes, clippy::type_complexity, clippy::incompatible_msrv)] +#![deny( + rustdoc::bare_urls, + rustdoc::broken_intra_doc_links, + rustdoc::invalid_codeblock_attributes, + rustdoc::invalid_html_tags, + rustdoc::invalid_rust_codeblocks, + rustdoc::missing_crate_level_docs, + rustdoc::private_intra_doc_links +)] +// In test code, it makes sense to weight more heavily towards concise, readable +// code over correct or debuggable code. +#![cfg_attr(any(test, kani), allow( + // In tests, you get line numbers and have access to source code, so panic + // messages are less important. You also often unwrap a lot, which would + // make expect'ing instead very verbose. + clippy::unwrap_used, + // In tests, there's no harm to "panic risks" - the worst that can happen is + // that your test will fail, and you'll fix it. By contrast, panic risks in + // production code introduce the possibly of code panicking unexpectedly "in + // the field". + clippy::arithmetic_side_effects, + clippy::indexing_slicing, +))] +#![cfg_attr(not(any(test, kani, feature = "std")), no_std)] +// NOTE: This attribute should have the effect of causing CI to fail if +// `stdarch_x86_avx512` - which is currently stable in 1.89.0-nightly as of this +// writing on 2025-06-10 - has its stabilization rolled back. +// +// FIXME(#2583): Remove once `stdarch_x86_avx512` is stabilized in 1.89.0, and +// 1.89.0 has been released as stable. +#![cfg_attr( + all(feature = "simd-nightly", any(target_arch = "x86", target_arch = "x86_64")), + expect(stable_features) +)] +// FIXME(#2583): Remove once `stdarch_x86_avx512` is stabilized in 1.89.0, and +// 1.89.0 has been released as stable. Replace with version detection for 1.89.0 +// (see #2574 for a draft implementation). +#![cfg_attr( + all(feature = "simd-nightly", any(target_arch = "x86", target_arch = "x86_64")), + feature(stdarch_x86_avx512) +)] +#![cfg_attr( + all(feature = "simd-nightly", target_arch = "arm"), + feature(stdarch_arm_dsp, stdarch_arm_neon_intrinsics) +)] +#![cfg_attr( + all(feature = "simd-nightly", any(target_arch = "powerpc", target_arch = "powerpc64")), + feature(stdarch_powerpc) +)] +#![cfg_attr(feature = "float-nightly", feature(f16, f128))] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![cfg_attr( + __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, + feature(layout_for_ptr, coverage_attribute) +)] + +// This is a hack to allow zerocopy-derive derives to work in this crate. They +// assume that zerocopy is linked as an extern crate, so they access items from +// it as `zerocopy::Xxx`. This makes that still work. +#[cfg(any(feature = "derive", test))] +extern crate self as zerocopy; + +#[doc(hidden)] +#[macro_use] +pub mod util; + +pub mod byte_slice; +pub mod byteorder; +mod deprecated; + +#[doc(hidden)] +pub mod doctests; + +// This module is `pub` so that zerocopy's error types and error handling +// documentation is grouped together in a cohesive module. In practice, we +// expect most users to use the re-export of `error`'s items to avoid identifier +// stuttering. +pub mod error; +mod impls; +#[doc(hidden)] +pub mod layout; +mod macros; +#[doc(hidden)] +pub mod pointer; +mod r#ref; +mod split_at; +// FIXME(#252): If we make this pub, come up with a better name. +mod wrappers; + +use core::{ + cell::{Cell, UnsafeCell}, + cmp::Ordering, + fmt::{self, Debug, Display, Formatter}, + hash::Hasher, + marker::PhantomData, + mem::{self, ManuallyDrop, MaybeUninit as CoreMaybeUninit}, + num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, + }, + ops::{Deref, DerefMut}, + ptr::{self, NonNull}, + slice, +}; +#[cfg(feature = "std")] +use std::io; + +use crate::pointer::invariant::{self, BecauseExclusive}; +pub use crate::{ + byte_slice::*, + byteorder::*, + error::*, + r#ref::*, + split_at::{Split, SplitAt}, + wrappers::*, +}; + +#[cfg(any(feature = "alloc", test, kani))] +extern crate alloc; +#[cfg(any(feature = "alloc", test))] +use alloc::{boxed::Box, vec::Vec}; +#[cfg(any(feature = "alloc", test))] +use core::alloc::Layout; + +use util::MetadataOf; + +// Used by `KnownLayout`. +#[doc(hidden)] +pub use crate::layout::*; +// Used by `TryFromBytes::is_bit_valid`. +#[doc(hidden)] +pub use crate::pointer::{invariant::BecauseImmutable, Maybe, Ptr}; +// For each trait polyfill, as soon as the corresponding feature is stable, the +// polyfill import will be unused because method/function resolution will prefer +// the inherent method/function over a trait method/function. Thus, we suppress +// the `unused_imports` warning. +// +// See the documentation on `util::polyfills` for more information. +#[allow(unused_imports)] +use crate::util::polyfills::{self, NonNullExt as _, NumExt as _}; + +#[rustversion::nightly] +#[cfg(all(test, not(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)))] +const _: () = { + #[deprecated = "some tests may be skipped due to missing RUSTFLAGS=\"--cfg __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS\""] + const _WARNING: () = (); + #[warn(deprecated)] + _WARNING +}; + +// These exist so that code which was written against the old names will get +// less confusing error messages when they upgrade to a more recent version of +// zerocopy. On our MSRV toolchain, the error messages read, for example: +// +// error[E0603]: trait `FromZeroes` is private +// --> examples/deprecated.rs:1:15 +// | +// 1 | use zerocopy::FromZeroes; +// | ^^^^^^^^^^ private trait +// | +// note: the trait `FromZeroes` is defined here +// --> /Users/josh/workspace/zerocopy/src/lib.rs:1845:5 +// | +// 1845 | use FromZeros as FromZeroes; +// | ^^^^^^^^^^^^^^^^^^^^^^^ +// +// The "note" provides enough context to make it easy to figure out how to fix +// the error. +/// Implements [`KnownLayout`]. +/// +/// This derive analyzes various aspects of a type's layout that are needed for +/// some of zerocopy's APIs. It can be applied to structs, enums, and unions; +/// e.g.: +/// +/// ``` +/// # use zerocopy_derive::KnownLayout; +/// #[derive(KnownLayout)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(KnownLayout)] +/// enum MyEnum { +/// # V00, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(KnownLayout)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// # Limitations +/// +/// This derive cannot currently be applied to unsized structs without an +/// explicit `repr` attribute. +/// +/// Some invocations of this derive run afoul of a [known bug] in Rust's type +/// privacy checker. For example, this code: +/// +/// ```compile_fail,E0446 +/// use zerocopy::*; +/// # use zerocopy_derive::*; +/// +/// #[derive(KnownLayout)] +/// #[repr(C)] +/// pub struct PublicType { +/// leading: Foo, +/// trailing: Bar, +/// } +/// +/// #[derive(KnownLayout)] +/// struct Foo; +/// +/// #[derive(KnownLayout)] +/// struct Bar; +/// ``` +/// +/// ...results in a compilation error: +/// +/// ```text +/// error[E0446]: private type `Bar` in public interface +/// --> examples/bug.rs:3:10 +/// | +/// 3 | #[derive(KnownLayout)] +/// | ^^^^^^^^^^^ can't leak private type +/// ... +/// 14 | struct Bar; +/// | ---------- `Bar` declared as private +/// | +/// = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +/// ``` +/// +/// This issue arises when `#[derive(KnownLayout)]` is applied to `repr(C)` +/// structs whose trailing field type is less public than the enclosing struct. +/// +/// To work around this, mark the trailing field type `pub` and annotate it with +/// `#[doc(hidden)]`; e.g.: +/// +/// ```no_run +/// use zerocopy::*; +/// # use zerocopy_derive::*; +/// +/// #[derive(KnownLayout)] +/// #[repr(C)] +/// pub struct PublicType { +/// leading: Foo, +/// trailing: Bar, +/// } +/// +/// #[derive(KnownLayout)] +/// struct Foo; +/// +/// #[doc(hidden)] +/// #[derive(KnownLayout)] +/// pub struct Bar; // <- `Bar` is now also `pub` +/// ``` +/// +/// [known bug]: https://github.com/rust-lang/rust/issues/45713 +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::KnownLayout; +#[allow(unused)] +use {FromZeros as FromZeroes, IntoBytes as AsBytes, Ref as LayoutVerified}; + +/// Indicates that zerocopy can reason about certain aspects of a type's layout. +/// +/// This trait is required by many of zerocopy's APIs. It supports sized types, +/// slices, and [slice DSTs](#dynamically-sized-types). +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(KnownLayout)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::KnownLayout; +/// #[derive(KnownLayout)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(KnownLayout)] +/// enum MyEnum { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(KnownLayout)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated analysis to deduce the layout +/// characteristics of types. You **must** implement this trait via the derive. +/// +/// # Dynamically-sized types +/// +/// `KnownLayout` supports slice-based dynamically sized types ("slice DSTs"). +/// +/// A slice DST is a type whose trailing field is either a slice or another +/// slice DST, rather than a type with fixed size. For example: +/// +/// ``` +/// #[repr(C)] +/// struct PacketHeader { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[repr(C)] +/// struct Packet { +/// header: PacketHeader, +/// body: [u8], +/// } +/// ``` +/// +/// It can be useful to think of slice DSTs as a generalization of slices - in +/// other words, a normal slice is just the special case of a slice DST with +/// zero leading fields. In particular: +/// - Like slices, slice DSTs can have different lengths at runtime +/// - Like slices, slice DSTs cannot be passed by-value, but only by reference +/// or via other indirection such as `Box` +/// - Like slices, a reference (or `Box`, or other pointer type) to a slice DST +/// encodes the number of elements in the trailing slice field +/// +/// ## Slice DST layout +/// +/// Just like other composite Rust types, the layout of a slice DST is not +/// well-defined unless it is specified using an explicit `#[repr(...)]` +/// attribute such as `#[repr(C)]`. [Other representations are +/// supported][reprs], but in this section, we'll use `#[repr(C)]` as our +/// example. +/// +/// A `#[repr(C)]` slice DST is laid out [just like sized `#[repr(C)]` +/// types][repr-c-structs], but the presenence of a variable-length field +/// introduces the possibility of *dynamic padding*. In particular, it may be +/// necessary to add trailing padding *after* the trailing slice field in order +/// to satisfy the outer type's alignment, and the amount of padding required +/// may be a function of the length of the trailing slice field. This is just a +/// natural consequence of the normal `#[repr(C)]` rules applied to slice DSTs, +/// but it can result in surprising behavior. For example, consider the +/// following type: +/// +/// ``` +/// #[repr(C)] +/// struct Foo { +/// a: u32, +/// b: u8, +/// z: [u16], +/// } +/// ``` +/// +/// Assuming that `u32` has alignment 4 (this is not true on all platforms), +/// then `Foo` has alignment 4 as well. Here is the smallest possible value for +/// `Foo`: +/// +/// ```text +/// byte offset | 01234567 +/// field | aaaab--- +/// >< +/// ``` +/// +/// In this value, `z` has length 0. Abiding by `#[repr(C)]`, the lowest offset +/// that we can place `z` at is 5, but since `z` has alignment 2, we need to +/// round up to offset 6. This means that there is one byte of padding between +/// `b` and `z`, then 0 bytes of `z` itself (denoted `><` in this diagram), and +/// then two bytes of padding after `z` in order to satisfy the overall +/// alignment of `Foo`. The size of this instance is 8 bytes. +/// +/// What about if `z` has length 1? +/// +/// ```text +/// byte offset | 01234567 +/// field | aaaab-zz +/// ``` +/// +/// In this instance, `z` has length 1, and thus takes up 2 bytes. That means +/// that we no longer need padding after `z` in order to satisfy `Foo`'s +/// alignment. We've now seen two different values of `Foo` with two different +/// lengths of `z`, but they both have the same size - 8 bytes. +/// +/// What about if `z` has length 2? +/// +/// ```text +/// byte offset | 012345678901 +/// field | aaaab-zzzz-- +/// ``` +/// +/// Now `z` has length 2, and thus takes up 4 bytes. This brings our un-padded +/// size to 10, and so we now need another 2 bytes of padding after `z` to +/// satisfy `Foo`'s alignment. +/// +/// Again, all of this is just a logical consequence of the `#[repr(C)]` rules +/// applied to slice DSTs, but it can be surprising that the amount of trailing +/// padding becomes a function of the trailing slice field's length, and thus +/// can only be computed at runtime. +/// +/// [reprs]: https://doc.rust-lang.org/reference/type-layout.html#representations +/// [repr-c-structs]: https://doc.rust-lang.org/reference/type-layout.html#reprc-structs +/// +/// ## What is a valid size? +/// +/// There are two places in zerocopy's API that we refer to "a valid size" of a +/// type. In normal casts or conversions, where the source is a byte slice, we +/// need to know whether the source byte slice is a valid size of the +/// destination type. In prefix or suffix casts, we need to know whether *there +/// exists* a valid size of the destination type which fits in the source byte +/// slice and, if so, what the largest such size is. +/// +/// As outlined above, a slice DST's size is defined by the number of elements +/// in its trailing slice field. However, there is not necessarily a 1-to-1 +/// mapping between trailing slice field length and overall size. As we saw in +/// the previous section with the type `Foo`, instances with both 0 and 1 +/// elements in the trailing `z` field result in a `Foo` whose size is 8 bytes. +/// +/// When we say "x is a valid size of `T`", we mean one of two things: +/// - If `T: Sized`, then we mean that `x == size_of::()` +/// - If `T` is a slice DST, then we mean that there exists a `len` such that the instance of +/// `T` with `len` trailing slice elements has size `x` +/// +/// When we say "largest possible size of `T` that fits in a byte slice", we +/// mean one of two things: +/// - If `T: Sized`, then we mean `size_of::()` if the byte slice is at least +/// `size_of::()` bytes long +/// - If `T` is a slice DST, then we mean to consider all values, `len`, such +/// that the instance of `T` with `len` trailing slice elements fits in the +/// byte slice, and to choose the largest such `len`, if any +/// +/// +/// # Safety +/// +/// This trait does not convey any safety guarantees to code outside this crate. +/// +/// You must not rely on the `#[doc(hidden)]` internals of `KnownLayout`. Future +/// releases of zerocopy may make backwards-breaking changes to these items, +/// including changes that only affect soundness, which may cause code which +/// uses those items to silently become unsound. +/// +#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::KnownLayout")] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.KnownLayout.html"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(KnownLayout)]` to `{Self}`") +)] +pub unsafe trait KnownLayout { + // The `Self: Sized` bound makes it so that `KnownLayout` can still be + // object safe. It's not currently object safe thanks to `const LAYOUT`, and + // it likely won't be in the future, but there's no reason not to be + // forwards-compatible with object safety. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// The type of metadata stored in a pointer to `Self`. + /// + /// This is `()` for sized types and `usize` for slice DSTs. + type PointerMetadata: PointerMetadata; + + /// A maybe-uninitialized analog of `Self` + /// + /// # Safety + /// + /// `Self::LAYOUT` and `Self::MaybeUninit::LAYOUT` are identical. + /// `Self::MaybeUninit` admits uninitialized bytes in all positions. + #[doc(hidden)] + type MaybeUninit: ?Sized + KnownLayout; + + /// The layout of `Self`. + /// + /// # Safety + /// + /// Callers may assume that `LAYOUT` accurately reflects the layout of + /// `Self`. In particular: + /// - `LAYOUT.align` is equal to `Self`'s alignment + /// - If `Self: Sized`, then `LAYOUT.size_info == SizeInfo::Sized { size }` + /// where `size == size_of::()` + /// - If `Self` is a slice DST, then `LAYOUT.size_info == + /// SizeInfo::SliceDst(slice_layout)` where: + /// - The size, `size`, of an instance of `Self` with `elems` trailing + /// slice elements is equal to `slice_layout.offset + + /// slice_layout.elem_size * elems` rounded up to the nearest multiple + /// of `LAYOUT.align` + /// - For such an instance, any bytes in the range `[slice_layout.offset + + /// slice_layout.elem_size * elems, size)` are padding and must not be + /// assumed to be initialized + #[doc(hidden)] + const LAYOUT: DstLayout; + + /// SAFETY: The returned pointer has the same address and provenance as + /// `bytes`. If `Self` is a DST, the returned pointer's referent has `elems` + /// elements in its trailing slice. + #[doc(hidden)] + fn raw_from_ptr_len(bytes: NonNull, meta: Self::PointerMetadata) -> NonNull; + + /// Extracts the metadata from a pointer to `Self`. + /// + /// # Safety + /// + /// `pointer_to_metadata` always returns the correct metadata stored in + /// `ptr`. + #[doc(hidden)] + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata; + + /// Computes the length of the byte range addressed by `ptr`. + /// + /// Returns `None` if the resulting length would not fit in an `usize`. + /// + /// # Safety + /// + /// Callers may assume that `size_of_val_raw` always returns the correct + /// size. + /// + /// Callers may assume that, if `ptr` addresses a byte range whose length + /// fits in an `usize`, this will return `Some`. + #[doc(hidden)] + #[must_use] + #[inline(always)] + fn size_of_val_raw(ptr: NonNull) -> Option { + let meta = Self::pointer_to_metadata(ptr.as_ptr()); + // SAFETY: `size_for_metadata` promises to only return `None` if the + // resulting size would not fit in a `usize`. + Self::size_for_metadata(meta) + } + + #[doc(hidden)] + #[must_use] + #[inline(always)] + fn raw_dangling() -> NonNull { + let meta = Self::PointerMetadata::from_elem_count(0); + Self::raw_from_ptr_len(NonNull::dangling(), meta) + } + + /// Computes the size of an object of type `Self` with the given pointer + /// metadata. + /// + /// # Safety + /// + /// `size_for_metadata` promises to return `None` if and only if the + /// resulting size would not fit in a `usize`. Note that the returned size + /// could exceed the actual maximum valid size of an allocated object, + /// `isize::MAX`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::KnownLayout; + /// + /// assert_eq!(u8::size_for_metadata(()), Some(1)); + /// assert_eq!(u16::size_for_metadata(()), Some(2)); + /// assert_eq!(<[u8]>::size_for_metadata(42), Some(42)); + /// assert_eq!(<[u16]>::size_for_metadata(42), Some(84)); + /// + /// // This size exceeds the maximum valid object size (`isize::MAX`): + /// assert_eq!(<[u8]>::size_for_metadata(usize::MAX), Some(usize::MAX)); + /// + /// // This size, if computed, would exceed `usize::MAX`: + /// assert_eq!(<[u16]>::size_for_metadata(usize::MAX), None); + /// ``` + #[inline(always)] + fn size_for_metadata(meta: Self::PointerMetadata) -> Option { + meta.size_for_metadata(Self::LAYOUT) + } +} + +/// Efficiently produces the [`TrailingSliceLayout`] of `T`. +#[inline(always)] +pub(crate) fn trailing_slice_layout() -> TrailingSliceLayout +where + T: ?Sized + KnownLayout, +{ + trait LayoutFacts { + const SIZE_INFO: TrailingSliceLayout; + } + + impl LayoutFacts for T + where + T: KnownLayout, + { + const SIZE_INFO: TrailingSliceLayout = match T::LAYOUT.size_info { + crate::SizeInfo::Sized { .. } => const_panic!("unreachable"), + crate::SizeInfo::SliceDst(info) => info, + }; + } + + T::SIZE_INFO +} + +/// The metadata associated with a [`KnownLayout`] type. +#[doc(hidden)] +pub trait PointerMetadata: Copy + Eq + Debug { + /// Constructs a `Self` from an element count. + /// + /// If `Self = ()`, this returns `()`. If `Self = usize`, this returns + /// `elems`. No other types are currently supported. + fn from_elem_count(elems: usize) -> Self; + + /// Computes the size of the object with the given layout and pointer + /// metadata. + /// + /// # Panics + /// + /// If `Self = ()`, `layout` must describe a sized type. If `Self = usize`, + /// `layout` must describe a slice DST. Otherwise, `size_for_metadata` may + /// panic. + /// + /// # Safety + /// + /// `size_for_metadata` promises to only return `None` if the resulting size + /// would not fit in a `usize`. + fn size_for_metadata(self, layout: DstLayout) -> Option; +} + +impl PointerMetadata for () { + #[inline] + #[allow(clippy::unused_unit)] + fn from_elem_count(_elems: usize) -> () {} + + #[inline] + fn size_for_metadata(self, layout: DstLayout) -> Option { + match layout.size_info { + SizeInfo::Sized { size } => Some(size), + // NOTE: This branch is unreachable, but we return `None` rather + // than `unreachable!()` to avoid generating panic paths. + SizeInfo::SliceDst(_) => None, + } + } +} + +impl PointerMetadata for usize { + #[inline] + fn from_elem_count(elems: usize) -> usize { + elems + } + + #[inline] + fn size_for_metadata(self, layout: DstLayout) -> Option { + match layout.size_info { + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => { + let slice_len = elem_size.checked_mul(self)?; + let without_padding = offset.checked_add(slice_len)?; + without_padding.checked_add(util::padding_needed_for(without_padding, layout.align)) + } + // NOTE: This branch is unreachable, but we return `None` rather + // than `unreachable!()` to avoid generating panic paths. + SizeInfo::Sized { .. } => None, + } + } +} + +// SAFETY: Delegates safety to `DstLayout::for_slice`. +unsafe impl KnownLayout for [T] { + #[allow(clippy::missing_inline_in_public_items, dead_code)] + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + } + + type PointerMetadata = usize; + + // SAFETY: `CoreMaybeUninit::LAYOUT` and `T::LAYOUT` are identical + // because `CoreMaybeUninit` has the same size and alignment as `T` [1]. + // Consequently, `[CoreMaybeUninit]::LAYOUT` and `[T]::LAYOUT` are + // identical, because they both lack a fixed-sized prefix and because they + // inherit the alignments of their inner element type (which are identical) + // [2][3]. + // + // `[CoreMaybeUninit]` admits uninitialized bytes at all positions + // because `CoreMaybeUninit` admits uninitialized bytes at all positions + // and because the inner elements of `[CoreMaybeUninit]` are laid out + // back-to-back [2][3]. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as + // `T` + // + // [2] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#slice-layout: + // + // Slices have the same layout as the section of the array they slice. + // + // [3] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#array-layout: + // + // An array of `[T; N]` has a size of `size_of::() * N` and the same + // alignment of `T`. Arrays are laid out so that the zero-based `nth` + // element of the array is offset from the start of the array by `n * + // size_of::()` bytes. + type MaybeUninit = [CoreMaybeUninit]; + + const LAYOUT: DstLayout = DstLayout::for_slice::(); + + // SAFETY: `.cast` preserves address and provenance. The returned pointer + // refers to an object with `elems` elements by construction. + #[inline(always)] + fn raw_from_ptr_len(data: NonNull, elems: usize) -> NonNull { + // FIXME(#67): Remove this allow. See NonNullExt for more details. + #[allow(unstable_name_collisions)] + NonNull::slice_from_raw_parts(data.cast::(), elems) + } + + #[inline(always)] + fn pointer_to_metadata(ptr: *mut [T]) -> usize { + #[allow(clippy::as_conversions)] + let slc = ptr as *const [()]; + + // SAFETY: + // - `()` has alignment 1, so `slc` is trivially aligned. + // - `slc` was derived from a non-null pointer. + // - The size is 0 regardless of the length, so it is sound to + // materialize a reference regardless of location. + // - By invariant, `self.ptr` has valid provenance. + let slc = unsafe { &*slc }; + + // This is correct because the preceding `as` cast preserves the number + // of slice elements. [1] + // + // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast: + // + // For slice types like `[T]` and `[U]`, the raw pointer types `*const + // [T]`, `*mut [T]`, `*const [U]`, and `*mut [U]` encode the number of + // elements in this slice. Casts between these raw pointer types + // preserve the number of elements. ... The same holds for `str` and + // any compound type whose unsized tail is a slice type, such as + // struct `Foo(i32, [u8])` or `(u64, Foo)`. + slc.len() + } +} + +#[rustfmt::skip] +impl_known_layout!( + (), + u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64, + bool, char, + NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, + NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize +); +#[rustfmt::skip] +#[cfg(feature = "float-nightly")] +impl_known_layout!( + #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] + f16, + #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))] + f128 +); +#[rustfmt::skip] +impl_known_layout!( + T => Option, + T: ?Sized => PhantomData, + T => Wrapping, + T => CoreMaybeUninit, + T: ?Sized => *const T, + T: ?Sized => *mut T, + T: ?Sized => &'_ T, + T: ?Sized => &'_ mut T, +); +impl_known_layout!(const N: usize, T => [T; N]); + +// SAFETY: `str` has the same representation as `[u8]`. `ManuallyDrop` [1], +// `UnsafeCell` [2], and `Cell` [3] have the same representation as `T`. +// +// [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +// `T` +// +// [2] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.UnsafeCell.html#memory-layout: +// +// `UnsafeCell` has the same in-memory representation as its inner type +// `T`. +// +// [3] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.Cell.html#memory-layout: +// +// `Cell` has the same in-memory representation as `T`. +const _: () = unsafe { + unsafe_impl_known_layout!( + #[repr([u8])] + str + ); + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ManuallyDrop); + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] UnsafeCell); + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] Cell); +}; + +// SAFETY: +// - By consequence of the invariant on `T::MaybeUninit` that `T::LAYOUT` and +// `T::MaybeUninit::LAYOUT` are equal, `T` and `T::MaybeUninit` have the same: +// - Fixed prefix size +// - Alignment +// - (For DSTs) trailing slice element size +// - By consequence of the above, referents `T::MaybeUninit` and `T` have the +// require the same kind of pointer metadata, and thus it is valid to perform +// an `as` cast from `*mut T` and `*mut T::MaybeUninit`, and this operation +// preserves referent size (ie, `size_of_val_raw`). +const _: () = unsafe { + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T::MaybeUninit)] MaybeUninit) +}; + +/// Analyzes whether a type is [`FromZeros`]. +/// +/// This derive analyzes, at compile time, whether the annotated type satisfies +/// the [safety conditions] of `FromZeros` and implements `FromZeros` and its +/// supertraits if it is sound to do so. This derive can be applied to structs, +/// enums, and unions; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{FromZeros, Immutable}; +/// #[derive(FromZeros)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromZeros)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromZeros, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// [safety conditions]: trait@FromZeros#safety +/// +/// # Analysis +/// +/// *This section describes, roughly, the analysis performed by this derive to +/// determine whether it is sound to implement `FromZeros` for a given type. +/// Unless you are modifying the implementation of this derive, or attempting to +/// manually implement `FromZeros` for a type yourself, you don't need to read +/// this section.* +/// +/// If a type has the following properties, then this derive can implement +/// `FromZeros` for that type: +/// +/// - If the type is a struct, all of its fields must be `FromZeros`. +/// - If the type is an enum: +/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`, +/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`). +/// - It must have a variant with a discriminant/tag of `0`, and its fields +/// must be `FromZeros`. See [the reference] for a description of +/// discriminant values are specified. +/// - The fields of that variant must be `FromZeros`. +/// +/// This analysis is subject to change. Unsafe code may *only* rely on the +/// documented [safety conditions] of `FromZeros`, and must *not* rely on the +/// implementation details of this derive. +/// +/// [the reference]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations +/// +/// ## Why isn't an explicit representation required for structs? +/// +/// Neither this derive, nor the [safety conditions] of `FromZeros`, requires +/// that structs are marked with `#[repr(C)]`. +/// +/// Per the [Rust reference](reference), +/// +/// > The representation of a type can change the padding between fields, but +/// > does not change the layout of the fields themselves. +/// +/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations +/// +/// Since the layout of structs only consists of padding bytes and field bytes, +/// a struct is soundly `FromZeros` if: +/// 1. its padding is soundly `FromZeros`, and +/// 2. its fields are soundly `FromZeros`. +/// +/// The answer to the first question is always yes: padding bytes do not have +/// any validity constraints. A [discussion] of this question in the Unsafe Code +/// Guidelines Working Group concluded that it would be virtually unimaginable +/// for future versions of rustc to add validity constraints to padding bytes. +/// +/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174 +/// +/// Whether a struct is soundly `FromZeros` therefore solely depends on whether +/// its fields are `FromZeros`. +// FIXME(#146): Document why we don't require an enum to have an explicit `repr` +// attribute. +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::FromZeros; +/// Analyzes whether a type is [`Immutable`]. +/// +/// This derive analyzes, at compile time, whether the annotated type satisfies +/// the [safety conditions] of `Immutable` and implements `Immutable` if it is +/// sound to do so. This derive can be applied to structs, enums, and unions; +/// e.g.: +/// +/// ``` +/// # use zerocopy_derive::Immutable; +/// #[derive(Immutable)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Immutable)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// # Analysis +/// +/// *This section describes, roughly, the analysis performed by this derive to +/// determine whether it is sound to implement `Immutable` for a given type. +/// Unless you are modifying the implementation of this derive, you don't need +/// to read this section.* +/// +/// If a type has the following properties, then this derive can implement +/// `Immutable` for that type: +/// +/// - All fields must be `Immutable`. +/// +/// This analysis is subject to change. Unsafe code may *only* rely on the +/// documented [safety conditions] of `Immutable`, and must *not* rely on the +/// implementation details of this derive. +/// +/// [safety conditions]: trait@Immutable#safety +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::Immutable; + +/// Types which are free from interior mutability. +/// +/// `T: Immutable` indicates that `T` does not permit interior mutation, except +/// by ownership or an exclusive (`&mut`) borrow. +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(Immutable)]`][derive] (requires the `derive` Cargo feature); +/// e.g.: +/// +/// ``` +/// # use zerocopy_derive::Immutable; +/// #[derive(Immutable)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Immutable)] +/// enum MyEnum { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `Immutable`. +/// +/// # Safety +/// +/// Unsafe code outside of this crate must not make any assumptions about `T` +/// based on `T: Immutable`. We reserve the right to relax the requirements for +/// `Immutable` in the future, and if unsafe code outside of this crate makes +/// assumptions based on `T: Immutable`, future relaxations may cause that code +/// to become unsound. +/// +// # Safety (Internal) +// +// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given +// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location +// within the byte range addressed by `t`. This includes ranges of length 0 +// (e.g., `UnsafeCell<()>` and `[UnsafeCell; 0]`). If a type implements +// `Immutable` which violates this assumptions, it may cause this crate to +// exhibit [undefined behavior]. +// +// [`UnsafeCell`]: core::cell::UnsafeCell +// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html +#[cfg_attr( + feature = "derive", + doc = "[derive]: zerocopy_derive::Immutable", + doc = "[derive-analysis]: zerocopy_derive::Immutable#analysis" +)] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html"), + doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html#analysis"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(Immutable)]` to `{Self}`") +)] +pub unsafe trait Immutable { + // The `Self: Sized` bound makes it so that `Immutable` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; +} + +/// Implements [`TryFromBytes`]. +/// +/// This derive synthesizes the runtime checks required to check whether a +/// sequence of initialized bytes corresponds to a valid instance of a type. +/// This derive can be applied to structs, enums, and unions; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{TryFromBytes, Immutable}; +/// #[derive(TryFromBytes)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(TryFromBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # V00, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(TryFromBytes, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// # Portability +/// +/// To ensure consistent endianness for enums with multi-byte representations, +/// explicitly specify and convert each discriminant using `.to_le()` or +/// `.to_be()`; e.g.: +/// +/// ``` +/// # use zerocopy_derive::TryFromBytes; +/// // `DataStoreVersion` is encoded in little-endian. +/// #[derive(TryFromBytes)] +/// #[repr(u32)] +/// pub enum DataStoreVersion { +/// /// Version 1 of the data store. +/// V1 = 9u32.to_le(), +/// +/// /// Version 2 of the data store. +/// V2 = 10u32.to_le(), +/// } +/// ``` +/// +/// [safety conditions]: trait@TryFromBytes#safety +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::TryFromBytes; + +/// Types for which some bit patterns are valid. +/// +/// A memory region of the appropriate length which contains initialized bytes +/// can be viewed as a `TryFromBytes` type so long as the runtime value of those +/// bytes corresponds to a [*valid instance*] of that type. For example, +/// [`bool`] is `TryFromBytes`, so zerocopy can transmute a [`u8`] into a +/// [`bool`] so long as it first checks that the value of the [`u8`] is `0` or +/// `1`. +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(TryFromBytes)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{TryFromBytes, Immutable}; +/// #[derive(TryFromBytes)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(TryFromBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # V00, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(TryFromBytes, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive ensures that the runtime check of whether bytes correspond to a +/// valid instance is sound. You **must** implement this trait via the derive. +/// +/// # What is a "valid instance"? +/// +/// In Rust, each type has *bit validity*, which refers to the set of bit +/// patterns which may appear in an instance of that type. It is impossible for +/// safe Rust code to produce values which violate bit validity (ie, values +/// outside of the "valid" set of bit patterns). If `unsafe` code produces an +/// invalid value, this is considered [undefined behavior]. +/// +/// Rust's bit validity rules are currently being decided, which means that some +/// types have three classes of bit patterns: those which are definitely valid, +/// and whose validity is documented in the language; those which may or may not +/// be considered valid at some point in the future; and those which are +/// definitely invalid. +/// +/// Zerocopy takes a conservative approach, and only considers a bit pattern to +/// be valid if its validity is a documenteed guarantee provided by the +/// language. +/// +/// For most use cases, Rust's current guarantees align with programmers' +/// intuitions about what ought to be valid. As a result, zerocopy's +/// conservatism should not affect most users. +/// +/// If you are negatively affected by lack of support for a particular type, +/// we encourage you to let us know by [filing an issue][github-repo]. +/// +/// # `TryFromBytes` is not symmetrical with [`IntoBytes`] +/// +/// There are some types which implement both `TryFromBytes` and [`IntoBytes`], +/// but for which `TryFromBytes` is not guaranteed to accept all byte sequences +/// produced by `IntoBytes`. In other words, for some `T: TryFromBytes + +/// IntoBytes`, there exist values of `t: T` such that +/// `TryFromBytes::try_ref_from_bytes(t.as_bytes()) == None`. Code should not +/// generally assume that values produced by `IntoBytes` will necessarily be +/// accepted as valid by `TryFromBytes`. +/// +/// # Safety +/// +/// On its own, `T: TryFromBytes` does not make any guarantees about the layout +/// or representation of `T`. It merely provides the ability to perform a +/// validity check at runtime via methods like [`try_ref_from_bytes`]. +/// +/// You must not rely on the `#[doc(hidden)]` internals of `TryFromBytes`. +/// Future releases of zerocopy may make backwards-breaking changes to these +/// items, including changes that only affect soundness, which may cause code +/// which uses those items to silently become unsound. +/// +/// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html +/// [github-repo]: https://github.com/google/zerocopy +/// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes +/// [*valid instance*]: #what-is-a-valid-instance +#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::TryFromBytes")] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.TryFromBytes.html"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(TryFromBytes)]` to `{Self}`") +)] +pub unsafe trait TryFromBytes { + // The `Self: Sized` bound makes it so that `TryFromBytes` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// Does a given memory range contain a valid instance of `Self`? + /// + /// # Safety + /// + /// Unsafe code may assume that, if `is_bit_valid(candidate)` returns true, + /// `*candidate` contains a valid `Self`. + /// + /// # Panics + /// + /// `is_bit_valid` may panic. Callers are responsible for ensuring that any + /// `unsafe` code remains sound even in the face of `is_bit_valid` + /// panicking. (We support user-defined validation routines; so long as + /// these routines are not required to be `unsafe`, there is no way to + /// ensure that these do not generate panics.) + /// + /// Besides user-defined validation routines panicking, `is_bit_valid` will + /// either panic or fail to compile if called on a pointer with [`Shared`] + /// aliasing when `Self: !Immutable`. + /// + /// [`UnsafeCell`]: core::cell::UnsafeCell + /// [`Shared`]: invariant::Shared + #[doc(hidden)] + fn is_bit_valid(candidate: Maybe<'_, Self, A>) -> bool; + + /// Attempts to interpret the given `source` as a `&Self`. + /// + /// If the bytes of `source` are a valid instance of `Self`, this method + /// returns a reference to those bytes interpreted as a `Self`. If the + /// length of `source` is not a [valid size of `Self`][valid-size], or if + /// `source` is not appropriately aligned, or if `source` is not a valid + /// instance of `Self`, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::try_ref_from_bytes(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the byte sequence `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..]; + /// + /// let packet = Packet::try_ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..]; + /// assert!(Packet::try_ref_from_bytes(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_bytes(source: &[u8]) -> Result<&Self, TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + static_assert_dst_is_not_zst!(Self); + match Ptr::from_ref(source).try_cast_into_no_leftover::(None) { + Ok(source) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match source.try_into_valid() { + Ok(valid) => Ok(valid.as_ref()), + Err(e) => { + Err(e.map_src(|src| src.as_bytes::().as_ref()).into()) + } + } + } + Err(e) => Err(e.map_src(Ptr::as_ref).into()), + } + } + + /// Attempts to interpret the prefix of the given `source` as a `&Self`. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the leading bytes of `source`. If that prefix is a valid + /// instance of `Self`, this method returns a reference to those bytes + /// interpreted as `Self`, and a reference to the remaining bytes. If there + /// are insufficient bytes, or if `source` is not appropriately aligned, or + /// if those bytes are not a valid instance of `Self`, this returns `Err`. + /// If [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::try_ref_from_prefix(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// + /// let (packet, suffix) = Packet::try_ref_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]); + /// assert_eq!(suffix, &[6u8][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// assert!(Packet::try_ref_from_prefix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + static_assert_dst_is_not_zst!(Self); + try_ref_from_prefix_suffix(source, CastType::Prefix, None) + } + + /// Attempts to interpret the suffix of the given `source` as a `&Self`. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the trailing bytes of `source`. If that suffix is a + /// valid instance of `Self`, this method returns a reference to those bytes + /// interpreted as `Self`, and a reference to the preceding bytes. If there + /// are insufficient bytes, or if the suffix of `source` would not be + /// appropriately aligned, or if the suffix is not a valid instance of + /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you + /// can [infallibly discard the alignment error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::try_ref_from_suffix(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &[0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let (prefix, packet) = Packet::try_ref_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(prefix, &[0u8][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..]; + /// assert!(Packet::try_ref_from_suffix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + static_assert_dst_is_not_zst!(Self); + try_ref_from_prefix_suffix(source, CastType::Suffix, None).map(swap) + } + + /// Attempts to interpret the given `source` as a `&mut Self` without + /// copying. + /// + /// If the bytes of `source` are a valid instance of `Self`, this method + /// returns a reference to those bytes interpreted as a `Self`. If the + /// length of `source` is not a [valid size of `Self`][valid-size], or if + /// `source` is not appropriately aligned, or if `source` is not a valid + /// instance of `Self`, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::try_mut_from_bytes(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..]; + /// + /// let packet = Packet::try_mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]); + /// + /// packet.temperature = 111; + /// + /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// assert!(Packet::try_mut_from_bytes(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_bytes(bytes: &mut [u8]) -> Result<&mut Self, TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + static_assert_dst_is_not_zst!(Self); + match Ptr::from_mut(bytes).try_cast_into_no_leftover::(None) { + Ok(source) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match source.try_into_valid() { + Ok(source) => Ok(source.as_mut()), + Err(e) => { + Err(e.map_src(|src| src.as_bytes::().as_mut()).into()) + } + } + } + Err(e) => Err(e.map_src(Ptr::as_mut).into()), + } + } + + /// Attempts to interpret the prefix of the given `source` as a `&mut + /// Self`. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the leading bytes of `source`. If that prefix is a valid + /// instance of `Self`, this method returns a reference to those bytes + /// interpreted as `Self`, and a reference to the remaining bytes. If there + /// are insufficient bytes, or if `source` is not appropriately aligned, or + /// if the bytes are not a valid instance of `Self`, this returns `Err`. If + /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::try_mut_from_prefix(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// + /// let (packet, suffix) = Packet::try_mut_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]); + /// assert_eq!(suffix, &[6u8][..]); + /// + /// packet.temperature = 111; + /// suffix[0] = 222; + /// + /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5, 222]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// assert!(Packet::try_mut_from_prefix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_prefix( + source: &mut [u8], + ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + static_assert_dst_is_not_zst!(Self); + try_mut_from_prefix_suffix(source, CastType::Prefix, None) + } + + /// Attempts to interpret the suffix of the given `source` as a `&mut + /// Self`. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the trailing bytes of `source`. If that suffix is a + /// valid instance of `Self`, this method returns a reference to those bytes + /// interpreted as `Self`, and a reference to the preceding bytes. If there + /// are insufficient bytes, or if the suffix of `source` would not be + /// appropriately aligned, or if the suffix is not a valid instance of + /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you + /// can [infallibly discard the alignment error][ConvertError::from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::try_mut_from_suffix(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &mut [0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let (prefix, packet) = Packet::try_mut_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(prefix, &[0u8][..]); + /// + /// prefix[0] = 111; + /// packet.temperature = 222; + /// + /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..]; + /// assert!(Packet::try_mut_from_suffix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_suffix( + source: &mut [u8], + ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + static_assert_dst_is_not_zst!(Self); + try_mut_from_prefix_suffix(source, CastType::Suffix, None).map(swap) + } + + /// Attempts to interpret the given `source` as a `&Self` with a DST length + /// equal to `count`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self` with `count` trailing elements. If the length of `source` is not + /// equal to the size of `Self` with `count` elements, if `source` is not + /// appropriately aligned, or if `source` does not contain a valid instance + /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], + /// you can [infallibly discard the alignment error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let packet = Packet::try_ref_from_bytes_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_ref_from_bytes_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_ref_from_bytes`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let src = 0xCAFEu16.as_bytes(); + /// let zsty = ZSTy::try_ref_from_bytes_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_bytes_with_elems( + source: &[u8], + count: usize, + ) -> Result<&Self, TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + match Ptr::from_ref(source).try_cast_into_no_leftover::(Some(count)) + { + Ok(source) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match source.try_into_valid() { + Ok(source) => Ok(source.as_ref()), + Err(e) => { + Err(e.map_src(|src| src.as_bytes::().as_ref()).into()) + } + } + } + Err(e) => Err(e.map_src(Ptr::as_ref).into()), + } + } + + /// Attempts to interpret the prefix of the given `source` as a `&Self` with + /// a DST length equal to `count`. + /// + /// This method attempts to return a reference to the prefix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the remaining bytes. If the length of `source` is less than the size + /// of `Self` with `count` elements, if `source` is not appropriately + /// aligned, or if the prefix of `source` does not contain a valid instance + /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], + /// you can [infallibly discard the alignment error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..]; + /// + /// let (packet, suffix) = Packet::try_ref_from_prefix_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(suffix, &[8u8][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_ref_from_prefix_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let src = 0xCAFEu16.as_bytes(); + /// let (zsty, _) = ZSTy::try_ref_from_prefix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_prefix_with_elems( + source: &[u8], + count: usize, + ) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + try_ref_from_prefix_suffix(source, CastType::Prefix, Some(count)) + } + + /// Attempts to interpret the suffix of the given `source` as a `&Self` with + /// a DST length equal to `count`. + /// + /// This method attempts to return a reference to the suffix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the preceding bytes. If the length of `source` is less than the size + /// of `Self` with `count` elements, if the suffix of `source` is not + /// appropriately aligned, or if the suffix of `source` does not contain a + /// valid instance of `Self`, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &[123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let (prefix, packet) = Packet::try_ref_from_suffix_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(prefix, &[123u8][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_ref_from_suffix_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let src = 0xCAFEu16.as_bytes(); + /// let (_, zsty) = ZSTy::try_ref_from_suffix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn try_ref_from_suffix_with_elems( + source: &[u8], + count: usize, + ) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + try_ref_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap) + } + + /// Attempts to interpret the given `source` as a `&mut Self` with a DST + /// length equal to `count`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self` with `count` trailing elements. If the length of `source` is not + /// equal to the size of `Self` with `count` elements, if `source` is not + /// appropriately aligned, or if `source` does not contain a valid instance + /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], + /// you can [infallibly discard the alignment error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let packet = Packet::try_mut_from_bytes_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// + /// packet.temperature = 111; + /// + /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_mut_from_bytes_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_mut_from_bytes`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let mut src = 0xCAFEu16; + /// let src = src.as_mut_bytes(); + /// let zsty = ZSTy::try_mut_from_bytes_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_mut_from_bytes`]: TryFromBytes::try_mut_from_bytes + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_bytes_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<&mut Self, TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + match Ptr::from_mut(source).try_cast_into_no_leftover::(Some(count)) + { + Ok(source) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match source.try_into_valid() { + Ok(source) => Ok(source.as_mut()), + Err(e) => { + Err(e.map_src(|src| src.as_bytes::().as_mut()).into()) + } + } + } + Err(e) => Err(e.map_src(Ptr::as_mut).into()), + } + } + + /// Attempts to interpret the prefix of the given `source` as a `&mut Self` + /// with a DST length equal to `count`. + /// + /// This method attempts to return a reference to the prefix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the remaining bytes. If the length of `source` is less than the size + /// of `Self` with `count` elements, if `source` is not appropriately + /// aligned, or if the prefix of `source` does not contain a valid instance + /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], + /// you can [infallibly discard the alignment error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..]; + /// + /// let (packet, suffix) = Packet::try_mut_from_prefix_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(suffix, &[8u8][..]); + /// + /// packet.temperature = 111; + /// suffix[0] = 222; + /// + /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7, 222]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_mut_from_prefix_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let mut src = 0xCAFEu16; + /// let src = src.as_mut_bytes(); + /// let (zsty, _) = ZSTy::try_mut_from_prefix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_prefix_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + try_mut_from_prefix_suffix(source, CastType::Prefix, Some(count)) + } + + /// Attempts to interpret the suffix of the given `source` as a `&mut Self` + /// with a DST length equal to `count`. + /// + /// This method attempts to return a reference to the suffix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the preceding bytes. If the length of `source` is less than the size + /// of `Self` with `count` elements, if the suffix of `source` is not + /// appropriately aligned, or if the suffix of `source` does not contain a + /// valid instance of `Self`, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][ConvertError::from]. + /// + /// [self-unaligned]: Unaligned + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// marshmallows: [[u8; 2]], + /// } + /// + /// let bytes = &mut [123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..]; + /// + /// let (prefix, packet) = Packet::try_mut_from_suffix_with_elems(bytes, 3).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]); + /// assert_eq!(prefix, &[123u8][..]); + /// + /// prefix[0] = 111; + /// packet.temperature = 222; + /// + /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..]; + /// assert!(Packet::try_mut_from_suffix_with_elems(bytes, 3).is_err()); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use core::num::NonZeroU16; + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(TryFromBytes, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: NonZeroU16, + /// trailing_dst: [()], + /// } + /// + /// let mut src = 0xCAFEu16; + /// let src = src.as_mut_bytes(); + /// let (_, zsty) = ZSTy::try_mut_from_suffix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn try_mut_from_suffix_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>> + where + Self: KnownLayout + IntoBytes, + { + try_mut_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap) + } + + /// Attempts to read the given `source` as a `Self`. + /// + /// If `source.len() != size_of::()` or the bytes are not a valid + /// instance of `Self`, this returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// } + /// + /// let bytes = &[0xC0, 0xC0, 240, 77][..]; + /// + /// let packet = Packet::try_read_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &mut [0x10, 0xC0, 240, 77][..]; + /// assert!(Packet::try_read_from_bytes(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_read_from_bytes(source: &[u8]) -> Result> + where + Self: Sized, + { + let candidate = match CoreMaybeUninit::::read_from_bytes(source) { + Ok(candidate) => candidate, + Err(e) => { + return Err(TryReadError::Size(e.with_dst())); + } + }; + // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of + // its bytes are initialized. + unsafe { try_read_from(source, candidate) } + } + + /// Attempts to read a `Self` from the prefix of the given `source`. + /// + /// This attempts to read a `Self` from the first `size_of::()` bytes + /// of `source`, returning that `Self` and any remaining bytes. If + /// `source.len() < size_of::()` or the bytes are not a valid instance + /// of `Self`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// + /// let (packet, suffix) = Packet::try_read_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(suffix, &[0u8, 1, 2, 3, 4, 5, 6][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..]; + /// assert!(Packet::try_read_from_prefix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), TryReadError<&[u8], Self>> + where + Self: Sized, + { + let (candidate, suffix) = match CoreMaybeUninit::::read_from_prefix(source) { + Ok(candidate) => candidate, + Err(e) => { + return Err(TryReadError::Size(e.with_dst())); + } + }; + // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of + // its bytes are initialized. + unsafe { try_read_from(source, candidate).map(|slf| (slf, suffix)) } + } + + /// Attempts to read a `Self` from the suffix of the given `source`. + /// + /// This attempts to read a `Self` from the last `size_of::()` bytes + /// of `source`, returning that `Self` and any preceding bytes. If + /// `source.len() < size_of::()` or the bytes are not a valid instance + /// of `Self`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// # #![allow(non_camel_case_types)] // For C0::xC0 + /// use zerocopy::TryFromBytes; + /// # use zerocopy_derive::*; + /// + /// // The only valid value of this type is the byte `0xC0` + /// #[derive(TryFromBytes)] + /// #[repr(u8)] + /// enum C0 { xC0 = 0xC0 } + /// + /// // The only valid value of this type is the bytes `0xC0C0`. + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct C0C0(C0, C0); + /// + /// #[derive(TryFromBytes)] + /// #[repr(C)] + /// struct Packet { + /// magic_number: C0C0, + /// mug_size: u8, + /// temperature: u8, + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 0xC0, 0xC0, 240, 77][..]; + /// + /// let (prefix, packet) = Packet::try_read_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(packet.mug_size, 240); + /// assert_eq!(packet.temperature, 77); + /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]); + /// + /// // These bytes are not valid instance of `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 0x10, 0xC0, 240, 77][..]; + /// assert!(Packet::try_read_from_suffix(bytes).is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn try_read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), TryReadError<&[u8], Self>> + where + Self: Sized, + { + let (prefix, candidate) = match CoreMaybeUninit::::read_from_suffix(source) { + Ok(candidate) => candidate, + Err(e) => { + return Err(TryReadError::Size(e.with_dst())); + } + }; + // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of + // its bytes are initialized. + unsafe { try_read_from(source, candidate).map(|slf| (prefix, slf)) } + } +} + +#[inline(always)] +fn try_ref_from_prefix_suffix( + source: &[u8], + cast_type: CastType, + meta: Option, +) -> Result<(&T, &[u8]), TryCastError<&[u8], T>> { + match Ptr::from_ref(source).try_cast_into::(cast_type, meta) { + Ok((source, prefix_suffix)) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match source.try_into_valid() { + Ok(valid) => Ok((valid.as_ref(), prefix_suffix.as_ref())), + Err(e) => Err(e.map_src(|src| src.as_bytes::().as_ref()).into()), + } + } + Err(e) => Err(e.map_src(Ptr::as_ref).into()), + } +} + +#[inline(always)] +fn try_mut_from_prefix_suffix( + candidate: &mut [u8], + cast_type: CastType, + meta: Option, +) -> Result<(&mut T, &mut [u8]), TryCastError<&mut [u8], T>> { + match Ptr::from_mut(candidate).try_cast_into::(cast_type, meta) { + Ok((candidate, prefix_suffix)) => { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + // + // Note that one panic or post-monomorphization error condition is + // calling `try_into_valid` (and thus `is_bit_valid`) with a shared + // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic + // condition will not happen. + match candidate.try_into_valid() { + Ok(valid) => Ok((valid.as_mut(), prefix_suffix.as_mut())), + Err(e) => Err(e.map_src(|src| src.as_bytes::().as_mut()).into()), + } + } + Err(e) => Err(e.map_src(Ptr::as_mut).into()), + } +} + +#[inline(always)] +fn swap((t, u): (T, U)) -> (U, T) { + (u, t) +} + +/// # Safety +/// +/// All bytes of `candidate` must be initialized. +#[inline(always)] +unsafe fn try_read_from( + source: S, + mut candidate: CoreMaybeUninit, +) -> Result> { + // We use `from_mut` despite not mutating via `c_ptr` so that we don't need + // to add a `T: Immutable` bound. + let c_ptr = Ptr::from_mut(&mut candidate); + // SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from + // `candidate`, which the caller promises is entirely initialized. Since + // `candidate` is a `MaybeUninit`, it has no validity requirements, and so + // no values written to an `Initialized` `c_ptr` can violate its validity. + // Since `c_ptr` has `Exclusive` aliasing, no mutations may happen except + // via `c_ptr` so long as it is live, so we don't need to worry about the + // fact that `c_ptr` may have more restricted validity than `candidate`. + let c_ptr = unsafe { c_ptr.assume_validity::() }; + let c_ptr = c_ptr.transmute(); + + // Since we don't have `T: KnownLayout`, we hack around that by using + // `Wrapping`, which implements `KnownLayout` even if `T` doesn't. + // + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to fix + // before returning. + // + // Note that one panic or post-monomorphization error condition is calling + // `try_into_valid` (and thus `is_bit_valid`) with a shared pointer when + // `Self: !Immutable`. Since `Self: Immutable`, this panic condition will + // not happen. + if !Wrapping::::is_bit_valid(c_ptr.forget_aligned()) { + return Err(ValidityError::new(source).into()); + } + + fn _assert_same_size_and_validity() + where + Wrapping: pointer::TransmuteFrom, + T: pointer::TransmuteFrom, invariant::Valid, invariant::Valid>, + { + } + + _assert_same_size_and_validity::(); + + // SAFETY: We just validated that `candidate` contains a valid + // `Wrapping`, which has the same size and bit validity as `T`, as + // guaranteed by the preceding type assertion. + Ok(unsafe { candidate.assume_init() }) +} + +/// Types for which a sequence of `0` bytes is a valid instance. +/// +/// Any memory region of the appropriate length which is guaranteed to contain +/// only zero bytes can be viewed as any `FromZeros` type with no runtime +/// overhead. This is useful whenever memory is known to be in a zeroed state, +/// such memory returned from some allocation routines. +/// +/// # Warning: Padding bytes +/// +/// Note that, when a value is moved or copied, only the non-padding bytes of +/// that value are guaranteed to be preserved. It is unsound to assume that +/// values written to padding bytes are preserved after a move or copy. For more +/// details, see the [`FromBytes` docs][frombytes-warning-padding-bytes]. +/// +/// [frombytes-warning-padding-bytes]: FromBytes#warning-padding-bytes +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(FromZeros)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{FromZeros, Immutable}; +/// #[derive(FromZeros)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromZeros)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromZeros, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `FromZeros`. +/// +/// # Safety +/// +/// *This section describes what is required in order for `T: FromZeros`, and +/// what unsafe code may assume of such types. If you don't plan on implementing +/// `FromZeros` manually, and you don't plan on writing unsafe code that +/// operates on `FromZeros` types, then you don't need to read this section.* +/// +/// If `T: FromZeros`, then unsafe code may assume that it is sound to produce a +/// `T` whose bytes are all initialized to zero. If a type is marked as +/// `FromZeros` which violates this contract, it may cause undefined behavior. +/// +/// `#[derive(FromZeros)]` only permits [types which satisfy these +/// requirements][derive-analysis]. +/// +#[cfg_attr( + feature = "derive", + doc = "[derive]: zerocopy_derive::FromZeros", + doc = "[derive-analysis]: zerocopy_derive::FromZeros#analysis" +)] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html"), + doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html#analysis"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromZeros)]` to `{Self}`") +)] +pub unsafe trait FromZeros: TryFromBytes { + // The `Self: Sized` bound makes it so that `FromZeros` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// Overwrites `self` with zeros. + /// + /// Sets every byte in `self` to 0. While this is similar to doing `*self = + /// Self::new_zeroed()`, it differs in that `zero` does not semantically + /// drop the current value and replace it with a new one — it simply + /// modifies the bytes of the existing value. + /// + /// # Examples + /// + /// ``` + /// # use zerocopy::FromZeros; + /// # use zerocopy_derive::*; + /// # + /// #[derive(FromZeros)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let mut header = PacketHeader { + /// src_port: 100u16.to_be_bytes(), + /// dst_port: 200u16.to_be_bytes(), + /// length: 300u16.to_be_bytes(), + /// checksum: 400u16.to_be_bytes(), + /// }; + /// + /// header.zero(); + /// + /// assert_eq!(header.src_port, [0, 0]); + /// assert_eq!(header.dst_port, [0, 0]); + /// assert_eq!(header.length, [0, 0]); + /// assert_eq!(header.checksum, [0, 0]); + /// ``` + #[inline(always)] + fn zero(&mut self) { + let slf: *mut Self = self; + let len = mem::size_of_val(self); + // SAFETY: + // - `self` is guaranteed by the type system to be valid for writes of + // size `size_of_val(self)`. + // - `u8`'s alignment is 1, and thus `self` is guaranteed to be aligned + // as required by `u8`. + // - Since `Self: FromZeros`, the all-zeros instance is a valid instance + // of `Self.` + // + // FIXME(#429): Add references to docs and quotes. + unsafe { ptr::write_bytes(slf.cast::(), 0, len) }; + } + + /// Creates an instance of `Self` from zeroed bytes. + /// + /// # Examples + /// + /// ``` + /// # use zerocopy::FromZeros; + /// # use zerocopy_derive::*; + /// # + /// #[derive(FromZeros)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let header: PacketHeader = FromZeros::new_zeroed(); + /// + /// assert_eq!(header.src_port, [0, 0]); + /// assert_eq!(header.dst_port, [0, 0]); + /// assert_eq!(header.length, [0, 0]); + /// assert_eq!(header.checksum, [0, 0]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + fn new_zeroed() -> Self + where + Self: Sized, + { + // SAFETY: `FromZeros` says that the all-zeros bit pattern is legal. + unsafe { mem::zeroed() } + } + + /// Creates a `Box` from zeroed bytes. + /// + /// This function is useful for allocating large values on the heap and + /// zero-initializing them, without ever creating a temporary instance of + /// `Self` on the stack. For example, `<[u8; 1048576]>::new_box_zeroed()` + /// will allocate `[u8; 1048576]` directly on the heap; it does not require + /// storing `[u8; 1048576]` in a temporary variable on the stack. + /// + /// On systems that use a heap implementation that supports allocating from + /// pre-zeroed memory, using `new_box_zeroed` (or related functions) may + /// have performance benefits. + /// + /// # Errors + /// + /// Returns an error on allocation failure. Allocation failure is guaranteed + /// never to cause a panic or an abort. + #[must_use = "has no side effects (other than allocation)"] + #[cfg(any(feature = "alloc", test))] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[inline] + fn new_box_zeroed() -> Result, AllocError> + where + Self: Sized, + { + // If `T` is a ZST, then return a proper boxed instance of it. There is + // no allocation, but `Box` does require a correct dangling pointer. + let layout = Layout::new::(); + if layout.size() == 0 { + // Construct the `Box` from a dangling pointer to avoid calling + // `Self::new_zeroed`. This ensures that stack space is never + // allocated for `Self` even on lower opt-levels where this branch + // might not get optimized out. + + // SAFETY: Per [1], when `T` is a ZST, `Box`'s only validity + // requirements are that the pointer is non-null and sufficiently + // aligned. Per [2], `NonNull::dangling` produces a pointer which + // is sufficiently aligned. Since the produced pointer is a + // `NonNull`, it is non-null. + // + // [1] Per https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout: + // + // For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. + // + // [2] Per https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.dangling: + // + // Creates a new `NonNull` that is dangling, but well-aligned. + return Ok(unsafe { Box::from_raw(NonNull::dangling().as_ptr()) }); + } + + // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. + #[allow(clippy::undocumented_unsafe_blocks)] + let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::() }; + if ptr.is_null() { + return Err(AllocError); + } + // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. + #[allow(clippy::undocumented_unsafe_blocks)] + Ok(unsafe { Box::from_raw(ptr) }) + } + + /// Creates a `Box<[Self]>` (a boxed slice) from zeroed bytes. + /// + /// This function is useful for allocating large values of `[Self]` on the + /// heap and zero-initializing them, without ever creating a temporary + /// instance of `[Self; _]` on the stack. For example, + /// `u8::new_box_slice_zeroed(1048576)` will allocate the slice directly on + /// the heap; it does not require storing the slice on the stack. + /// + /// On systems that use a heap implementation that supports allocating from + /// pre-zeroed memory, using `new_box_slice_zeroed` may have performance + /// benefits. + /// + /// If `Self` is a zero-sized type, then this function will return a + /// `Box<[Self]>` that has the correct `len`. Such a box cannot contain any + /// actual information, but its `len()` property will report the correct + /// value. + /// + /// # Errors + /// + /// Returns an error on allocation failure. Allocation failure is + /// guaranteed never to cause a panic or an abort. + #[must_use = "has no side effects (other than allocation)"] + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[inline] + fn new_box_zeroed_with_elems(count: usize) -> Result, AllocError> + where + Self: KnownLayout, + { + // SAFETY: `alloc::alloc::alloc_zeroed` is a valid argument of + // `new_box`. The referent of the pointer returned by `alloc_zeroed` + // (and, consequently, the `Box` derived from it) is a valid instance of + // `Self`, because `Self` is `FromZeros`. + unsafe { crate::util::new_box(count, alloc::alloc::alloc_zeroed) } + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromZeros::new_box_zeroed_with_elems`")] + #[doc(hidden)] + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[must_use = "has no side effects (other than allocation)"] + #[inline(always)] + fn new_box_slice_zeroed(len: usize) -> Result, AllocError> + where + Self: Sized, + { + <[Self]>::new_box_zeroed_with_elems(len) + } + + /// Creates a `Vec` from zeroed bytes. + /// + /// This function is useful for allocating large values of `Vec`s and + /// zero-initializing them, without ever creating a temporary instance of + /// `[Self; _]` (or many temporary instances of `Self`) on the stack. For + /// example, `u8::new_vec_zeroed(1048576)` will allocate directly on the + /// heap; it does not require storing intermediate values on the stack. + /// + /// On systems that use a heap implementation that supports allocating from + /// pre-zeroed memory, using `new_vec_zeroed` may have performance benefits. + /// + /// If `Self` is a zero-sized type, then this function will return a + /// `Vec` that has the correct `len`. Such a `Vec` cannot contain any + /// actual information, but its `len()` property will report the correct + /// value. + /// + /// # Errors + /// + /// Returns an error on allocation failure. Allocation failure is + /// guaranteed never to cause a panic or an abort. + #[must_use = "has no side effects (other than allocation)"] + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + #[inline(always)] + fn new_vec_zeroed(len: usize) -> Result, AllocError> + where + Self: Sized, + { + <[Self]>::new_box_zeroed_with_elems(len).map(Into::into) + } + + /// Extends a `Vec` by pushing `additional` new items onto the end of + /// the vector. The new items are initialized with zeros. + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))] + #[inline(always)] + fn extend_vec_zeroed(v: &mut Vec, additional: usize) -> Result<(), AllocError> + where + Self: Sized, + { + // PANICS: We pass `v.len()` for `position`, so the `position > v.len()` + // panic condition is not satisfied. + ::insert_vec_zeroed(v, v.len(), additional) + } + + /// Inserts `additional` new items into `Vec` at `position`. The new + /// items are initialized with zeros. + /// + /// # Panics + /// + /// Panics if `position > v.len()`. + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))] + #[inline] + fn insert_vec_zeroed( + v: &mut Vec, + position: usize, + additional: usize, + ) -> Result<(), AllocError> + where + Self: Sized, + { + assert!(position <= v.len()); + // We only conditionally compile on versions on which `try_reserve` is + // stable; the Clippy lint is a false positive. + v.try_reserve(additional).map_err(|_| AllocError)?; + // SAFETY: The `try_reserve` call guarantees that these cannot overflow: + // * `ptr.add(position)` + // * `position + additional` + // * `v.len() + additional` + // + // `v.len() - position` cannot overflow because we asserted that + // `position <= v.len()`. + unsafe { + // This is a potentially overlapping copy. + let ptr = v.as_mut_ptr(); + #[allow(clippy::arithmetic_side_effects)] + ptr.add(position).copy_to(ptr.add(position + additional), v.len() - position); + ptr.add(position).write_bytes(0, additional); + #[allow(clippy::arithmetic_side_effects)] + v.set_len(v.len() + additional); + } + + Ok(()) + } +} + +/// Analyzes whether a type is [`FromBytes`]. +/// +/// This derive analyzes, at compile time, whether the annotated type satisfies +/// the [safety conditions] of `FromBytes` and implements `FromBytes` and its +/// supertraits if it is sound to do so. This derive can be applied to structs, +/// enums, and unions; +/// e.g.: +/// +/// ``` +/// # use zerocopy_derive::{FromBytes, FromZeros, Immutable}; +/// #[derive(FromBytes)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E, +/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D, +/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C, +/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B, +/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A, +/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, +/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68, +/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77, +/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86, +/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95, +/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4, +/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3, +/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2, +/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1, +/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0, +/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF, +/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE, +/// # VFF, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromBytes, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// [safety conditions]: trait@FromBytes#safety +/// +/// # Analysis +/// +/// *This section describes, roughly, the analysis performed by this derive to +/// determine whether it is sound to implement `FromBytes` for a given type. +/// Unless you are modifying the implementation of this derive, or attempting to +/// manually implement `FromBytes` for a type yourself, you don't need to read +/// this section.* +/// +/// If a type has the following properties, then this derive can implement +/// `FromBytes` for that type: +/// +/// - If the type is a struct, all of its fields must be `FromBytes`. +/// - If the type is an enum: +/// - It must have a defined representation which is one of `u8`, `u16`, `i8`, +/// or `i16`. +/// - The maximum number of discriminants must be used (so that every possible +/// bit pattern is a valid one). +/// - Its fields must be `FromBytes`. +/// +/// This analysis is subject to change. Unsafe code may *only* rely on the +/// documented [safety conditions] of `FromBytes`, and must *not* rely on the +/// implementation details of this derive. +/// +/// ## Why isn't an explicit representation required for structs? +/// +/// Neither this derive, nor the [safety conditions] of `FromBytes`, requires +/// that structs are marked with `#[repr(C)]`. +/// +/// Per the [Rust reference](reference), +/// +/// > The representation of a type can change the padding between fields, but +/// > does not change the layout of the fields themselves. +/// +/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations +/// +/// Since the layout of structs only consists of padding bytes and field bytes, +/// a struct is soundly `FromBytes` if: +/// 1. its padding is soundly `FromBytes`, and +/// 2. its fields are soundly `FromBytes`. +/// +/// The answer to the first question is always yes: padding bytes do not have +/// any validity constraints. A [discussion] of this question in the Unsafe Code +/// Guidelines Working Group concluded that it would be virtually unimaginable +/// for future versions of rustc to add validity constraints to padding bytes. +/// +/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174 +/// +/// Whether a struct is soundly `FromBytes` therefore solely depends on whether +/// its fields are `FromBytes`. +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::FromBytes; + +/// Types for which any bit pattern is valid. +/// +/// Any memory region of the appropriate length which contains initialized bytes +/// can be viewed as any `FromBytes` type with no runtime overhead. This is +/// useful for efficiently parsing bytes as structured data. +/// +/// # Warning: Padding bytes +/// +/// Note that, when a value is moved or copied, only the non-padding bytes of +/// that value are guaranteed to be preserved. It is unsound to assume that +/// values written to padding bytes are preserved after a move or copy. For +/// example, the following is unsound: +/// +/// ```rust,no_run +/// use core::mem::{size_of, transmute}; +/// use zerocopy::FromZeros; +/// # use zerocopy_derive::*; +/// +/// // Assume `Foo` is a type with padding bytes. +/// #[derive(FromZeros, Default)] +/// struct Foo { +/// # /* +/// ... +/// # */ +/// } +/// +/// let mut foo: Foo = Foo::default(); +/// FromZeros::zero(&mut foo); +/// // UNSOUND: Although `FromZeros::zero` writes zeros to all bytes of `foo`, +/// // those writes are not guaranteed to be preserved in padding bytes when +/// // `foo` is moved, so this may expose padding bytes as `u8`s. +/// let foo_bytes: [u8; size_of::()] = unsafe { transmute(foo) }; +/// ``` +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(FromBytes)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{FromBytes, Immutable}; +/// #[derive(FromBytes)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E, +/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D, +/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C, +/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B, +/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A, +/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, +/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68, +/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77, +/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86, +/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95, +/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4, +/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3, +/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2, +/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1, +/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0, +/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF, +/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE, +/// # VFF, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(FromBytes, Immutable)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `FromBytes`. +/// +/// # Safety +/// +/// *This section describes what is required in order for `T: FromBytes`, and +/// what unsafe code may assume of such types. If you don't plan on implementing +/// `FromBytes` manually, and you don't plan on writing unsafe code that +/// operates on `FromBytes` types, then you don't need to read this section.* +/// +/// If `T: FromBytes`, then unsafe code may assume that it is sound to produce a +/// `T` whose bytes are initialized to any sequence of valid `u8`s (in other +/// words, any byte value which is not uninitialized). If a type is marked as +/// `FromBytes` which violates this contract, it may cause undefined behavior. +/// +/// `#[derive(FromBytes)]` only permits [types which satisfy these +/// requirements][derive-analysis]. +/// +#[cfg_attr( + feature = "derive", + doc = "[derive]: zerocopy_derive::FromBytes", + doc = "[derive-analysis]: zerocopy_derive::FromBytes#analysis" +)] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html"), + doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html#analysis"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromBytes)]` to `{Self}`") +)] +pub unsafe trait FromBytes: FromZeros { + // The `Self: Sized` bound makes it so that `FromBytes` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// Interprets the given `source` as a `&Self`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self`. If the length of `source` is not a [valid size of + /// `Self`][valid-size], or if `source` is not appropriately aligned, this + /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can + /// [infallibly discard the alignment error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::ref_from_bytes(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// #[derive(FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// header: PacketHeader, + /// body: [u8], + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..]; + /// + /// let packet = Packet::ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.header.src_port, [0, 1]); + /// assert_eq!(packet.header.dst_port, [2, 3]); + /// assert_eq!(packet.header.length, [4, 5]); + /// assert_eq!(packet.header.checksum, [6, 7]); + /// assert_eq!(packet.body, [8, 9, 10, 11]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + static_assert_dst_is_not_zst!(Self); + match Ptr::from_ref(source).try_cast_into_no_leftover::<_, BecauseImmutable>(None) { + Ok(ptr) => Ok(ptr.recall_validity().as_ref()), + Err(err) => Err(err.map_src(|src| src.as_ref())), + } + } + + /// Interprets the prefix of the given `source` as a `&Self` without + /// copying. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the leading bytes of `source`, then attempts to return + /// both a reference to those bytes interpreted as a `Self`, and a reference + /// to the remaining bytes. If there are insufficient bytes, or if `source` + /// is not appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. See [`ref_from_prefix_with_elems`], which does + /// support such types. Attempting to use this method on such types results + /// in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::ref_from_prefix(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// [`ref_from_prefix_with_elems`]: FromBytes::ref_from_prefix_with_elems + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// #[derive(FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// header: PacketHeader, + /// body: [[u8; 2]], + /// } + /// + /// // These are more bytes than are needed to encode a `Packet`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][..]; + /// + /// let (packet, suffix) = Packet::ref_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(packet.header.src_port, [0, 1]); + /// assert_eq!(packet.header.dst_port, [2, 3]); + /// assert_eq!(packet.header.length, [4, 5]); + /// assert_eq!(packet.header.checksum, [6, 7]); + /// assert_eq!(packet.body, [[8, 9], [10, 11], [12, 13]]); + /// assert_eq!(suffix, &[14u8][..]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), CastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + static_assert_dst_is_not_zst!(Self); + ref_from_prefix_suffix(source, None, CastType::Prefix) + } + + /// Interprets the suffix of the given bytes as a `&Self`. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the trailing bytes of `source`, then attempts to return + /// both a reference to those bytes interpreted as a `Self`, and a reference + /// to the preceding bytes. If there are insufficient bytes, or if that + /// suffix of `source` is not appropriately aligned, this returns `Err`. If + /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. See [`ref_from_suffix_with_elems`], which does + /// support such types. Attempting to use this method on such types results + /// in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = ZSTy::ref_from_suffix(0u16.as_bytes()); // ⚠ Compile Error! + /// ``` + /// + /// [`ref_from_suffix_with_elems`]: FromBytes::ref_from_suffix_with_elems + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct PacketTrailer { + /// frame_check_sequence: [u8; 4], + /// } + /// + /// // These are more bytes than are needed to encode a `PacketTrailer`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (prefix, trailer) = PacketTrailer::ref_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(prefix, &[0, 1, 2, 3, 4, 5][..]); + /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), CastError<&[u8], Self>> + where + Self: Immutable + KnownLayout, + { + static_assert_dst_is_not_zst!(Self); + ref_from_prefix_suffix(source, None, CastType::Suffix).map(swap) + } + + /// Interprets the given `source` as a `&mut Self`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self`. If the length of `source` is not a [valid size of + /// `Self`][valid-size], or if `source` is not appropriately aligned, this + /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can + /// [infallibly discard the alignment error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. See [`mut_from_prefix_with_elems`], which does + /// support such types. Attempting to use this method on such types results + /// in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::mut_from_bytes(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// [`mut_from_prefix_with_elems`]: FromBytes::mut_from_prefix_with_elems + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// // These bytes encode a `PacketHeader`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..]; + /// + /// let header = PacketHeader::mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(header.src_port, [0, 1]); + /// assert_eq!(header.dst_port, [2, 3]); + /// assert_eq!(header.length, [4, 5]); + /// assert_eq!(header.checksum, [6, 7]); + /// + /// header.checksum = [0, 0]; + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn mut_from_bytes(source: &mut [u8]) -> Result<&mut Self, CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout, + { + static_assert_dst_is_not_zst!(Self); + match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) { + Ok(ptr) => Ok(ptr.recall_validity::<_, (_, (_, _))>().as_mut()), + Err(err) => Err(err.map_src(|src| src.as_mut())), + } + } + + /// Interprets the prefix of the given `source` as a `&mut Self` without + /// copying. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the leading bytes of `source`, then attempts to return + /// both a reference to those bytes interpreted as a `Self`, and a reference + /// to the remaining bytes. If there are insufficient bytes, or if `source` + /// is not appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. See [`mut_from_suffix_with_elems`], which does + /// support such types. Attempting to use this method on such types results + /// in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::mut_from_prefix(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// [`mut_from_suffix_with_elems`]: FromBytes::mut_from_suffix_with_elems + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// // These are more bytes than are needed to encode a `PacketHeader`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (header, body) = PacketHeader::mut_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(header.src_port, [0, 1]); + /// assert_eq!(header.dst_port, [2, 3]); + /// assert_eq!(header.length, [4, 5]); + /// assert_eq!(header.checksum, [6, 7]); + /// assert_eq!(body, &[8, 9][..]); + /// + /// header.checksum = [0, 0]; + /// body.fill(1); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 1, 1]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn mut_from_prefix( + source: &mut [u8], + ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout, + { + static_assert_dst_is_not_zst!(Self); + mut_from_prefix_suffix(source, None, CastType::Prefix) + } + + /// Interprets the suffix of the given `source` as a `&mut Self` without + /// copying. + /// + /// This method computes the [largest possible size of `Self`][valid-size] + /// that can fit in the trailing bytes of `source`, then attempts to return + /// both a reference to those bytes interpreted as a `Self`, and a reference + /// to the preceding bytes. If there are insufficient bytes, or if that + /// suffix of `source` is not appropriately aligned, this returns `Err`. If + /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][size-error-from]. + /// + /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let mut source = [85, 85]; + /// let _ = ZSTy::mut_from_suffix(&mut source[..]); // ⚠ Compile Error! + /// ``` + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct PacketTrailer { + /// frame_check_sequence: [u8; 4], + /// } + /// + /// // These are more bytes than are needed to encode a `PacketTrailer`. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (prefix, trailer) = PacketTrailer::mut_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]); + /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]); + /// + /// prefix.fill(0); + /// trailer.frame_check_sequence.fill(1); + /// + /// assert_eq!(bytes, [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn mut_from_suffix( + source: &mut [u8], + ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout, + { + static_assert_dst_is_not_zst!(Self); + mut_from_prefix_suffix(source, None, CastType::Suffix).map(swap) + } + + /// Interprets the given `source` as a `&Self` with a DST length equal to + /// `count`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self` with `count` trailing elements. If the length of `source` is not + /// equal to the size of `Self` with `count` elements, or if `source` is not + /// appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(FromBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..]; + /// + /// let pixels = <[Pixel]>::ref_from_bytes_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 0, g: 1, b: 2, a: 3 }, + /// Pixel { r: 4, g: 5, b: 6, a: 7 }, + /// ]); + /// + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`ref_from_bytes`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &[85, 85][..]; + /// let zsty = ZSTy::ref_from_bytes_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`ref_from_bytes`]: FromBytes::ref_from_bytes + #[must_use = "has no side effects"] + #[inline] + fn ref_from_bytes_with_elems( + source: &[u8], + count: usize, + ) -> Result<&Self, CastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + let source = Ptr::from_ref(source); + let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count)); + match maybe_slf { + Ok(slf) => Ok(slf.recall_validity().as_ref()), + Err(err) => Err(err.map_src(|s| s.as_ref())), + } + } + + /// Interprets the prefix of the given `source` as a DST `&Self` with length + /// equal to `count`. + /// + /// This method attempts to return a reference to the prefix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the remaining bytes. If there are insufficient bytes, or if `source` + /// is not appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(FromBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// // These are more bytes than are needed to encode two `Pixel`s. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (pixels, suffix) = <[Pixel]>::ref_from_prefix_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 0, g: 1, b: 2, a: 3 }, + /// Pixel { r: 4, g: 5, b: 6, a: 7 }, + /// ]); + /// + /// assert_eq!(suffix, &[8, 9]); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`ref_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &[85, 85][..]; + /// let (zsty, _) = ZSTy::ref_from_prefix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`ref_from_prefix`]: FromBytes::ref_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn ref_from_prefix_with_elems( + source: &[u8], + count: usize, + ) -> Result<(&Self, &[u8]), CastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + ref_from_prefix_suffix(source, Some(count), CastType::Prefix) + } + + /// Interprets the suffix of the given `source` as a DST `&Self` with length + /// equal to `count`. + /// + /// This method attempts to return a reference to the suffix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the preceding bytes. If there are insufficient bytes, or if that + /// suffix of `source` is not appropriately aligned, this returns `Err`. If + /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(FromBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// // These are more bytes than are needed to encode two `Pixel`s. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (prefix, pixels) = <[Pixel]>::ref_from_suffix_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(prefix, &[0, 1]); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 2, g: 3, b: 4, a: 5 }, + /// Pixel { r: 6, g: 7, b: 8, a: 9 }, + /// ]); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`ref_from_suffix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &[85, 85][..]; + /// let (_, zsty) = ZSTy::ref_from_suffix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`ref_from_suffix`]: FromBytes::ref_from_suffix + #[must_use = "has no side effects"] + #[inline] + fn ref_from_suffix_with_elems( + source: &[u8], + count: usize, + ) -> Result<(&[u8], &Self), CastError<&[u8], Self>> + where + Self: KnownLayout + Immutable, + { + ref_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap) + } + + /// Interprets the given `source` as a `&mut Self` with a DST length equal + /// to `count`. + /// + /// This method attempts to return a reference to `source` interpreted as a + /// `Self` with `count` trailing elements. If the length of `source` is not + /// equal to the size of `Self` with `count` elements, or if `source` is not + /// appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..]; + /// + /// let pixels = <[Pixel]>::mut_from_bytes_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 0, g: 1, b: 2, a: 3 }, + /// Pixel { r: 4, g: 5, b: 6, a: 7 }, + /// ]); + /// + /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 }; + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`mut_from`] which + /// do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &mut [85, 85][..]; + /// let zsty = ZSTy::mut_from_bytes_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`mut_from`]: FromBytes::mut_from + #[must_use = "has no side effects"] + #[inline] + fn mut_from_bytes_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<&mut Self, CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout + Immutable, + { + let source = Ptr::from_mut(source); + let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count)); + match maybe_slf { + Ok(slf) => Ok(slf + .recall_validity::<_, (_, (_, (BecauseExclusive, BecauseExclusive)))>() + .as_mut()), + Err(err) => Err(err.map_src(|s| s.as_mut())), + } + } + + /// Interprets the prefix of the given `source` as a `&mut Self` with DST + /// length equal to `count`. + /// + /// This method attempts to return a reference to the prefix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the preceding bytes. If there are insufficient bytes, or if `source` + /// is not appropriately aligned, this returns `Err`. If [`Self: + /// Unaligned`][self-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// // These are more bytes than are needed to encode two `Pixel`s. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (pixels, suffix) = <[Pixel]>::mut_from_prefix_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 0, g: 1, b: 2, a: 3 }, + /// Pixel { r: 4, g: 5, b: 6, a: 7 }, + /// ]); + /// + /// assert_eq!(suffix, &[8, 9]); + /// + /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 }; + /// suffix.fill(1); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 1, 1]); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`mut_from_prefix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &mut [85, 85][..]; + /// let (zsty, _) = ZSTy::mut_from_prefix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`mut_from_prefix`]: FromBytes::mut_from_prefix + #[must_use = "has no side effects"] + #[inline] + fn mut_from_prefix_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout, + { + mut_from_prefix_suffix(source, Some(count), CastType::Prefix) + } + + /// Interprets the suffix of the given `source` as a `&mut Self` with DST + /// length equal to `count`. + /// + /// This method attempts to return a reference to the suffix of `source` + /// interpreted as a `Self` with `count` trailing elements, and a reference + /// to the remaining bytes. If there are insufficient bytes, or if that + /// suffix of `source` is not appropriately aligned, this returns `Err`. If + /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the + /// alignment error][size-error-from]. + /// + /// [self-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Debug, PartialEq, Eq)] + /// #[derive(FromBytes, IntoBytes, Immutable)] + /// #[repr(C)] + /// struct Pixel { + /// r: u8, + /// g: u8, + /// b: u8, + /// a: u8, + /// } + /// + /// // These are more bytes than are needed to encode two `Pixel`s. + /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (prefix, pixels) = <[Pixel]>::mut_from_suffix_with_elems(bytes, 2).unwrap(); + /// + /// assert_eq!(prefix, &[0, 1]); + /// + /// assert_eq!(pixels, &[ + /// Pixel { r: 2, g: 3, b: 4, a: 5 }, + /// Pixel { r: 6, g: 7, b: 8, a: 9 }, + /// ]); + /// + /// prefix.fill(9); + /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 }; + /// + /// assert_eq!(bytes, [9, 9, 2, 3, 4, 5, 0, 0, 0, 0]); + /// ``` + /// + /// Since an explicit `count` is provided, this method supports types with + /// zero-sized trailing slice elements. Methods such as [`mut_from_suffix`] + /// which do not take an explicit count do not support such types. + /// + /// ``` + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] + /// #[repr(C, packed)] + /// struct ZSTy { + /// leading_sized: [u8; 2], + /// trailing_dst: [()], + /// } + /// + /// let src = &mut [85, 85][..]; + /// let (_, zsty) = ZSTy::mut_from_suffix_with_elems(src, 42).unwrap(); + /// assert_eq!(zsty.trailing_dst.len(), 42); + /// ``` + /// + /// [`mut_from_suffix`]: FromBytes::mut_from_suffix + #[must_use = "has no side effects"] + #[inline] + fn mut_from_suffix_with_elems( + source: &mut [u8], + count: usize, + ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>> + where + Self: IntoBytes + KnownLayout, + { + mut_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap) + } + + /// Reads a copy of `Self` from the given `source`. + /// + /// If `source.len() != size_of::()`, `read_from_bytes` returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// // These bytes encode a `PacketHeader`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..]; + /// + /// let header = PacketHeader::read_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(header.src_port, [0, 1]); + /// assert_eq!(header.dst_port, [2, 3]); + /// assert_eq!(header.length, [4, 5]); + /// assert_eq!(header.checksum, [6, 7]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn read_from_bytes(source: &[u8]) -> Result> + where + Self: Sized, + { + match Ref::<_, Unalign>::sized_from(source) { + Ok(r) => Ok(Ref::read(&r).into_inner()), + Err(CastError::Size(e)) => Err(e.with_dst()), + Err(CastError::Alignment(_)) => { + // SAFETY: `Unalign` is trivially aligned, so + // `Ref::sized_from` cannot fail due to unmet alignment + // requirements. + unsafe { core::hint::unreachable_unchecked() } + } + Err(CastError::Validity(i)) => match i {}, + } + } + + /// Reads a copy of `Self` from the prefix of the given `source`. + /// + /// This attempts to read a `Self` from the first `size_of::()` bytes + /// of `source`, returning that `Self` and any remaining bytes. If + /// `source.len() < size_of::()`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// // These are more bytes than are needed to encode a `PacketHeader`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (header, body) = PacketHeader::read_from_prefix(bytes).unwrap(); + /// + /// assert_eq!(header.src_port, [0, 1]); + /// assert_eq!(header.dst_port, [2, 3]); + /// assert_eq!(header.length, [4, 5]); + /// assert_eq!(header.checksum, [6, 7]); + /// assert_eq!(body, [8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), SizeError<&[u8], Self>> + where + Self: Sized, + { + match Ref::<_, Unalign>::sized_from_prefix(source) { + Ok((r, suffix)) => Ok((Ref::read(&r).into_inner(), suffix)), + Err(CastError::Size(e)) => Err(e.with_dst()), + Err(CastError::Alignment(_)) => { + // SAFETY: `Unalign` is trivially aligned, so + // `Ref::sized_from_prefix` cannot fail due to unmet alignment + // requirements. + unsafe { core::hint::unreachable_unchecked() } + } + Err(CastError::Validity(i)) => match i {}, + } + } + + /// Reads a copy of `Self` from the suffix of the given `source`. + /// + /// This attempts to read a `Self` from the last `size_of::()` bytes + /// of `source`, returning that `Self` and any preceding bytes. If + /// `source.len() < size_of::()`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::FromBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes)] + /// #[repr(C)] + /// struct PacketTrailer { + /// frame_check_sequence: [u8; 4], + /// } + /// + /// // These are more bytes than are needed to encode a `PacketTrailer`. + /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let (prefix, trailer) = PacketTrailer::read_from_suffix(bytes).unwrap(); + /// + /// assert_eq!(prefix, [0, 1, 2, 3, 4, 5]); + /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline] + fn read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), SizeError<&[u8], Self>> + where + Self: Sized, + { + match Ref::<_, Unalign>::sized_from_suffix(source) { + Ok((prefix, r)) => Ok((prefix, Ref::read(&r).into_inner())), + Err(CastError::Size(e)) => Err(e.with_dst()), + Err(CastError::Alignment(_)) => { + // SAFETY: `Unalign` is trivially aligned, so + // `Ref::sized_from_suffix` cannot fail due to unmet alignment + // requirements. + unsafe { core::hint::unreachable_unchecked() } + } + Err(CastError::Validity(i)) => match i {}, + } + } + + /// Reads a copy of `self` from an `io::Read`. + /// + /// This is useful for interfacing with operating system byte sinks (files, + /// sockets, etc.). + /// + /// # Examples + /// + /// ```no_run + /// use zerocopy::{byteorder::big_endian::*, FromBytes}; + /// use std::fs::File; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes)] + /// #[repr(C)] + /// struct BitmapFileHeader { + /// signature: [u8; 2], + /// size: U32, + /// reserved: U64, + /// offset: U64, + /// } + /// + /// let mut file = File::open("image.bin").unwrap(); + /// let header = BitmapFileHeader::read_from_io(&mut file).unwrap(); + /// ``` + #[cfg(feature = "std")] + #[inline(always)] + fn read_from_io(mut src: R) -> io::Result + where + Self: Sized, + R: io::Read, + { + // NOTE(#2319, #2320): We do `buf.zero()` separately rather than + // constructing `let buf = CoreMaybeUninit::zeroed()` because, if `Self` + // contains padding bytes, then a typed copy of `CoreMaybeUninit` + // will not necessarily preserve zeros written to those padding byte + // locations, and so `buf` could contain uninitialized bytes. + let mut buf = CoreMaybeUninit::::uninit(); + buf.zero(); + + let ptr = Ptr::from_mut(&mut buf); + // SAFETY: After `buf.zero()`, `buf` consists entirely of initialized, + // zeroed bytes. Since `MaybeUninit` has no validity requirements, `ptr` + // cannot be used to write values which will violate `buf`'s bit + // validity. Since `ptr` has `Exclusive` aliasing, nothing other than + // `ptr` may be used to mutate `ptr`'s referent, and so its bit validity + // cannot be violated even though `buf` may have more permissive bit + // validity than `ptr`. + let ptr = unsafe { ptr.assume_validity::() }; + let ptr = ptr.as_bytes::(); + src.read_exact(ptr.as_mut())?; + // SAFETY: `buf` entirely consists of initialized bytes, and `Self` is + // `FromBytes`. + Ok(unsafe { buf.assume_init() }) + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_bytes`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn ref_from(source: &[u8]) -> Option<&Self> + where + Self: KnownLayout + Immutable, + { + Self::ref_from_bytes(source).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_bytes`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn mut_from(source: &mut [u8]) -> Option<&mut Self> + where + Self: KnownLayout + IntoBytes, + { + Self::mut_from_bytes(source).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_prefix_with_elems`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn slice_from_prefix(source: &[u8], count: usize) -> Option<(&[Self], &[u8])> + where + Self: Sized + Immutable, + { + <[Self]>::ref_from_prefix_with_elems(source, count).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_suffix_with_elems`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn slice_from_suffix(source: &[u8], count: usize) -> Option<(&[u8], &[Self])> + where + Self: Sized + Immutable, + { + <[Self]>::ref_from_suffix_with_elems(source, count).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_prefix_with_elems`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn mut_slice_from_prefix(source: &mut [u8], count: usize) -> Option<(&mut [Self], &mut [u8])> + where + Self: Sized + IntoBytes, + { + <[Self]>::mut_from_prefix_with_elems(source, count).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_suffix_with_elems`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn mut_slice_from_suffix(source: &mut [u8], count: usize) -> Option<(&mut [u8], &mut [Self])> + where + Self: Sized + IntoBytes, + { + <[Self]>::mut_from_suffix_with_elems(source, count).ok() + } + + #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::read_from_bytes`")] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + fn read_from(source: &[u8]) -> Option + where + Self: Sized, + { + Self::read_from_bytes(source).ok() + } +} + +/// Interprets the given affix of the given bytes as a `&Self`. +/// +/// This method computes the largest possible size of `Self` that can fit in the +/// prefix or suffix bytes of `source`, then attempts to return both a reference +/// to those bytes interpreted as a `Self`, and a reference to the excess bytes. +/// If there are insufficient bytes, or if that affix of `source` is not +/// appropriately aligned, this returns `Err`. +#[inline(always)] +fn ref_from_prefix_suffix( + source: &[u8], + meta: Option, + cast_type: CastType, +) -> Result<(&T, &[u8]), CastError<&[u8], T>> { + let (slf, prefix_suffix) = Ptr::from_ref(source) + .try_cast_into::<_, BecauseImmutable>(cast_type, meta) + .map_err(|err| err.map_src(|s| s.as_ref()))?; + Ok((slf.recall_validity().as_ref(), prefix_suffix.as_ref())) +} + +/// Interprets the given affix of the given bytes as a `&mut Self` without +/// copying. +/// +/// This method computes the largest possible size of `Self` that can fit in the +/// prefix or suffix bytes of `source`, then attempts to return both a reference +/// to those bytes interpreted as a `Self`, and a reference to the excess bytes. +/// If there are insufficient bytes, or if that affix of `source` is not +/// appropriately aligned, this returns `Err`. +#[inline(always)] +fn mut_from_prefix_suffix( + source: &mut [u8], + meta: Option, + cast_type: CastType, +) -> Result<(&mut T, &mut [u8]), CastError<&mut [u8], T>> { + let (slf, prefix_suffix) = Ptr::from_mut(source) + .try_cast_into::<_, BecauseExclusive>(cast_type, meta) + .map_err(|err| err.map_src(|s| s.as_mut()))?; + Ok((slf.recall_validity::<_, (_, (_, _))>().as_mut(), prefix_suffix.as_mut())) +} + +/// Analyzes whether a type is [`IntoBytes`]. +/// +/// This derive analyzes, at compile time, whether the annotated type satisfies +/// the [safety conditions] of `IntoBytes` and implements `IntoBytes` if it is +/// sound to do so. This derive can be applied to structs and enums (see below +/// for union support); e.g.: +/// +/// ``` +/// # use zerocopy_derive::{IntoBytes}; +/// #[derive(IntoBytes)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(IntoBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// [safety conditions]: trait@IntoBytes#safety +/// +/// # Error Messages +/// +/// On Rust toolchains prior to 1.78.0, due to the way that the custom derive +/// for `IntoBytes` is implemented, you may get an error like this: +/// +/// ```text +/// error[E0277]: the trait bound `(): PaddingFree` is not satisfied +/// --> lib.rs:23:10 +/// | +/// 1 | #[derive(IntoBytes)] +/// | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` +/// | +/// = help: the following implementations were found: +/// <() as PaddingFree> +/// ``` +/// +/// This error indicates that the type being annotated has padding bytes, which +/// is illegal for `IntoBytes` types. Consider reducing the alignment of some +/// fields by using types in the [`byteorder`] module, wrapping field types in +/// [`Unalign`], adding explicit struct fields where those padding bytes would +/// be, or using `#[repr(packed)]`. See the Rust Reference's page on [type +/// layout] for more information about type layout and padding. +/// +/// [type layout]: https://doc.rust-lang.org/reference/type-layout.html +/// +/// # Unions +/// +/// Currently, union bit validity is [up in the air][union-validity], and so +/// zerocopy does not support `#[derive(IntoBytes)]` on unions by default. +/// However, implementing `IntoBytes` on a union type is likely sound on all +/// existing Rust toolchains - it's just that it may become unsound in the +/// future. You can opt-in to `#[derive(IntoBytes)]` support on unions by +/// passing the unstable `zerocopy_derive_union_into_bytes` cfg: +/// +/// ```shell +/// $ RUSTFLAGS='--cfg zerocopy_derive_union_into_bytes' cargo build +/// ``` +/// +/// However, it is your responsibility to ensure that this derive is sound on +/// the specific versions of the Rust toolchain you are using! We make no +/// stability or soundness guarantees regarding this cfg, and may remove it at +/// any point. +/// +/// We are actively working with Rust to stabilize the necessary language +/// guarantees to support this in a forwards-compatible way, which will enable +/// us to remove the cfg gate. As part of this effort, we need to know how much +/// demand there is for this feature. If you would like to use `IntoBytes` on +/// unions, [please let us know][discussion]. +/// +/// [union-validity]: https://github.com/rust-lang/unsafe-code-guidelines/issues/438 +/// [discussion]: https://github.com/google/zerocopy/discussions/1802 +/// +/// # Analysis +/// +/// *This section describes, roughly, the analysis performed by this derive to +/// determine whether it is sound to implement `IntoBytes` for a given type. +/// Unless you are modifying the implementation of this derive, or attempting to +/// manually implement `IntoBytes` for a type yourself, you don't need to read +/// this section.* +/// +/// If a type has the following properties, then this derive can implement +/// `IntoBytes` for that type: +/// +/// - If the type is a struct, its fields must be [`IntoBytes`]. Additionally: +/// - if the type is `repr(transparent)` or `repr(packed)`, it is +/// [`IntoBytes`] if its fields are [`IntoBytes`]; else, +/// - if the type is `repr(C)` with at most one field, it is [`IntoBytes`] +/// if its field is [`IntoBytes`]; else, +/// - if the type has no generic parameters, it is [`IntoBytes`] if the type +/// is sized and has no padding bytes; else, +/// - if the type is `repr(C)`, its fields must be [`Unaligned`]. +/// - If the type is an enum: +/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`, +/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`). +/// - It must have no padding bytes. +/// - Its fields must be [`IntoBytes`]. +/// +/// This analysis is subject to change. Unsafe code may *only* rely on the +/// documented [safety conditions] of `FromBytes`, and must *not* rely on the +/// implementation details of this derive. +/// +/// [Rust Reference]: https://doc.rust-lang.org/reference/type-layout.html +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::IntoBytes; + +/// Types that can be converted to an immutable slice of initialized bytes. +/// +/// Any `IntoBytes` type can be converted to a slice of initialized bytes of the +/// same size. This is useful for efficiently serializing structured data as raw +/// bytes. +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(IntoBytes)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::IntoBytes; +/// #[derive(IntoBytes)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(IntoBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `IntoBytes`. See the [derive +/// documentation][derive] for guidance on how to interpret error messages +/// produced by the derive's analysis. +/// +/// # Safety +/// +/// *This section describes what is required in order for `T: IntoBytes`, and +/// what unsafe code may assume of such types. If you don't plan on implementing +/// `IntoBytes` manually, and you don't plan on writing unsafe code that +/// operates on `IntoBytes` types, then you don't need to read this section.* +/// +/// If `T: IntoBytes`, then unsafe code may assume that it is sound to treat any +/// `t: T` as an immutable `[u8]` of length `size_of_val(t)`. If a type is +/// marked as `IntoBytes` which violates this contract, it may cause undefined +/// behavior. +/// +/// `#[derive(IntoBytes)]` only permits [types which satisfy these +/// requirements][derive-analysis]. +/// +#[cfg_attr( + feature = "derive", + doc = "[derive]: zerocopy_derive::IntoBytes", + doc = "[derive-analysis]: zerocopy_derive::IntoBytes#analysis" +)] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html"), + doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html#analysis"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(IntoBytes)]` to `{Self}`") +)] +pub unsafe trait IntoBytes { + // The `Self: Sized` bound makes it so that this function doesn't prevent + // `IntoBytes` from being object safe. Note that other `IntoBytes` methods + // prevent object safety, but those provide a benefit in exchange for object + // safety. If at some point we remove those methods, change their type + // signatures, or move them out of this trait so that `IntoBytes` is object + // safe again, it's important that this function not prevent object safety. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// Gets the bytes of this value. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::IntoBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(IntoBytes, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let header = PacketHeader { + /// src_port: [0, 1], + /// dst_port: [2, 3], + /// length: [4, 5], + /// checksum: [6, 7], + /// }; + /// + /// let bytes = header.as_bytes(); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + fn as_bytes(&self) -> &[u8] + where + Self: Immutable, + { + // Note that this method does not have a `Self: Sized` bound; + // `size_of_val` works for unsized values too. + let len = mem::size_of_val(self); + let slf: *const Self = self; + + // SAFETY: + // - `slf.cast::()` is valid for reads for `len * size_of::()` + // many bytes because... + // - `slf` is the same pointer as `self`, and `self` is a reference + // which points to an object whose size is `len`. Thus... + // - The entire region of `len` bytes starting at `slf` is contained + // within a single allocation. + // - `slf` is non-null. + // - `slf` is trivially aligned to `align_of::() == 1`. + // - `Self: IntoBytes` ensures that all of the bytes of `slf` are + // initialized. + // - Since `slf` is derived from `self`, and `self` is an immutable + // reference, the only other references to this memory region that + // could exist are other immutable references, and those don't allow + // mutation. `Self: Immutable` prohibits types which contain + // `UnsafeCell`s, which are the only types for which this rule + // wouldn't be sufficient. + // - The total size of the resulting slice is no larger than + // `isize::MAX` because no allocation produced by safe code can be + // larger than `isize::MAX`. + // + // FIXME(#429): Add references to docs and quotes. + unsafe { slice::from_raw_parts(slf.cast::(), len) } + } + + /// Gets the bytes of this value mutably. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::IntoBytes; + /// # use zerocopy_derive::*; + /// + /// # #[derive(Eq, PartialEq, Debug)] + /// #[derive(FromBytes, IntoBytes, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let mut header = PacketHeader { + /// src_port: [0, 1], + /// dst_port: [2, 3], + /// length: [4, 5], + /// checksum: [6, 7], + /// }; + /// + /// let bytes = header.as_mut_bytes(); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]); + /// + /// bytes.reverse(); + /// + /// assert_eq!(header, PacketHeader { + /// src_port: [7, 6], + /// dst_port: [5, 4], + /// length: [3, 2], + /// checksum: [1, 0], + /// }); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + fn as_mut_bytes(&mut self) -> &mut [u8] + where + Self: FromBytes, + { + // Note that this method does not have a `Self: Sized` bound; + // `size_of_val` works for unsized values too. + let len = mem::size_of_val(self); + let slf: *mut Self = self; + + // SAFETY: + // - `slf.cast::()` is valid for reads and writes for `len * + // size_of::()` many bytes because... + // - `slf` is the same pointer as `self`, and `self` is a reference + // which points to an object whose size is `len`. Thus... + // - The entire region of `len` bytes starting at `slf` is contained + // within a single allocation. + // - `slf` is non-null. + // - `slf` is trivially aligned to `align_of::() == 1`. + // - `Self: IntoBytes` ensures that all of the bytes of `slf` are + // initialized. + // - `Self: FromBytes` ensures that no write to this memory region + // could result in it containing an invalid `Self`. + // - Since `slf` is derived from `self`, and `self` is a mutable + // reference, no other references to this memory region can exist. + // - The total size of the resulting slice is no larger than + // `isize::MAX` because no allocation produced by safe code can be + // larger than `isize::MAX`. + // + // FIXME(#429): Add references to docs and quotes. + unsafe { slice::from_raw_parts_mut(slf.cast::(), len) } + } + + /// Writes a copy of `self` to `dst`. + /// + /// If `dst.len() != size_of_val(self)`, `write_to` returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::IntoBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(IntoBytes, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let header = PacketHeader { + /// src_port: [0, 1], + /// dst_port: [2, 3], + /// length: [4, 5], + /// checksum: [6, 7], + /// }; + /// + /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0]; + /// + /// header.write_to(&mut bytes[..]); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]); + /// ``` + /// + /// If too many or too few target bytes are provided, `write_to` returns + /// `Err` and leaves the target bytes unmodified: + /// + /// ``` + /// # use zerocopy::IntoBytes; + /// # let header = u128::MAX; + /// let mut excessive_bytes = &mut [0u8; 128][..]; + /// + /// let write_result = header.write_to(excessive_bytes); + /// + /// assert!(write_result.is_err()); + /// assert_eq!(excessive_bytes, [0u8; 128]); + /// ``` + #[must_use = "callers should check the return value to see if the operation succeeded"] + #[inline] + #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]` + fn write_to(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>> + where + Self: Immutable, + { + let src = self.as_bytes(); + if dst.len() == src.len() { + // SAFETY: Within this branch of the conditional, we have ensured + // that `dst.len()` is equal to `src.len()`. Neither the size of the + // source nor the size of the destination change between the above + // size check and the invocation of `copy_unchecked`. + unsafe { util::copy_unchecked(src, dst) } + Ok(()) + } else { + Err(SizeError::new(self)) + } + } + + /// Writes a copy of `self` to the prefix of `dst`. + /// + /// `write_to_prefix` writes `self` to the first `size_of_val(self)` bytes + /// of `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::IntoBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(IntoBytes, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let header = PacketHeader { + /// src_port: [0, 1], + /// dst_port: [2, 3], + /// length: [4, 5], + /// checksum: [6, 7], + /// }; + /// + /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + /// + /// header.write_to_prefix(&mut bytes[..]); + /// + /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 0, 0]); + /// ``` + /// + /// If insufficient target bytes are provided, `write_to_prefix` returns + /// `Err` and leaves the target bytes unmodified: + /// + /// ``` + /// # use zerocopy::IntoBytes; + /// # let header = u128::MAX; + /// let mut insufficient_bytes = &mut [0, 0][..]; + /// + /// let write_result = header.write_to_suffix(insufficient_bytes); + /// + /// assert!(write_result.is_err()); + /// assert_eq!(insufficient_bytes, [0, 0]); + /// ``` + #[must_use = "callers should check the return value to see if the operation succeeded"] + #[inline] + #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]` + fn write_to_prefix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>> + where + Self: Immutable, + { + let src = self.as_bytes(); + match dst.get_mut(..src.len()) { + Some(dst) => { + // SAFETY: Within this branch of the `match`, we have ensured + // through fallible subslicing that `dst.len()` is equal to + // `src.len()`. Neither the size of the source nor the size of + // the destination change between the above subslicing operation + // and the invocation of `copy_unchecked`. + unsafe { util::copy_unchecked(src, dst) } + Ok(()) + } + None => Err(SizeError::new(self)), + } + } + + /// Writes a copy of `self` to the suffix of `dst`. + /// + /// `write_to_suffix` writes `self` to the last `size_of_val(self)` bytes of + /// `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::IntoBytes; + /// # use zerocopy_derive::*; + /// + /// #[derive(IntoBytes, Immutable)] + /// #[repr(C)] + /// struct PacketHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// let header = PacketHeader { + /// src_port: [0, 1], + /// dst_port: [2, 3], + /// length: [4, 5], + /// checksum: [6, 7], + /// }; + /// + /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + /// + /// header.write_to_suffix(&mut bytes[..]); + /// + /// assert_eq!(bytes, [0, 0, 0, 1, 2, 3, 4, 5, 6, 7]); + /// + /// let mut insufficient_bytes = &mut [0, 0][..]; + /// + /// let write_result = header.write_to_suffix(insufficient_bytes); + /// + /// assert!(write_result.is_err()); + /// assert_eq!(insufficient_bytes, [0, 0]); + /// ``` + /// + /// If insufficient target bytes are provided, `write_to_suffix` returns + /// `Err` and leaves the target bytes unmodified: + /// + /// ``` + /// # use zerocopy::IntoBytes; + /// # let header = u128::MAX; + /// let mut insufficient_bytes = &mut [0, 0][..]; + /// + /// let write_result = header.write_to_suffix(insufficient_bytes); + /// + /// assert!(write_result.is_err()); + /// assert_eq!(insufficient_bytes, [0, 0]); + /// ``` + #[must_use = "callers should check the return value to see if the operation succeeded"] + #[inline] + #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]` + fn write_to_suffix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>> + where + Self: Immutable, + { + let src = self.as_bytes(); + let start = if let Some(start) = dst.len().checked_sub(src.len()) { + start + } else { + return Err(SizeError::new(self)); + }; + let dst = if let Some(dst) = dst.get_mut(start..) { + dst + } else { + // get_mut() should never return None here. We return a `SizeError` + // rather than .unwrap() because in the event the branch is not + // optimized away, returning a value is generally lighter-weight + // than panicking. + return Err(SizeError::new(self)); + }; + // SAFETY: Through fallible subslicing of `dst`, we have ensured that + // `dst.len()` is equal to `src.len()`. Neither the size of the source + // nor the size of the destination change between the above subslicing + // operation and the invocation of `copy_unchecked`. + unsafe { + util::copy_unchecked(src, dst); + } + Ok(()) + } + + /// Writes a copy of `self` to an `io::Write`. + /// + /// This is a shorthand for `dst.write_all(self.as_bytes())`, and is useful + /// for interfacing with operating system byte sinks (files, sockets, etc.). + /// + /// # Examples + /// + /// ```no_run + /// use zerocopy::{byteorder::big_endian::U16, FromBytes, IntoBytes}; + /// use std::fs::File; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] + /// #[repr(C, packed)] + /// struct GrayscaleImage { + /// height: U16, + /// width: U16, + /// pixels: [U16], + /// } + /// + /// let image = GrayscaleImage::ref_from_bytes(&[0, 0, 0, 0][..]).unwrap(); + /// let mut file = File::create("image.bin").unwrap(); + /// image.write_to_io(&mut file).unwrap(); + /// ``` + /// + /// If the write fails, `write_to_io` returns `Err` and a partial write may + /// have occurred; e.g.: + /// + /// ``` + /// # use zerocopy::IntoBytes; + /// + /// let src = u128::MAX; + /// let mut dst = [0u8; 2]; + /// + /// let write_result = src.write_to_io(&mut dst[..]); + /// + /// assert!(write_result.is_err()); + /// assert_eq!(dst, [255, 255]); + /// ``` + #[cfg(feature = "std")] + #[inline(always)] + fn write_to_io(&self, mut dst: W) -> io::Result<()> + where + Self: Immutable, + W: io::Write, + { + dst.write_all(self.as_bytes()) + } + + #[deprecated(since = "0.8.0", note = "`IntoBytes::as_bytes_mut` was renamed to `as_mut_bytes`")] + #[doc(hidden)] + #[inline] + fn as_bytes_mut(&mut self) -> &mut [u8] + where + Self: FromBytes, + { + self.as_mut_bytes() + } +} + +/// Analyzes whether a type is [`Unaligned`]. +/// +/// This derive analyzes, at compile time, whether the annotated type satisfies +/// the [safety conditions] of `Unaligned` and implements `Unaligned` if it is +/// sound to do so. This derive can be applied to structs, enums, and unions; +/// e.g.: +/// +/// ``` +/// # use zerocopy_derive::Unaligned; +/// #[derive(Unaligned)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Unaligned)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Unaligned)] +/// #[repr(packed)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// # Analysis +/// +/// *This section describes, roughly, the analysis performed by this derive to +/// determine whether it is sound to implement `Unaligned` for a given type. +/// Unless you are modifying the implementation of this derive, or attempting to +/// manually implement `Unaligned` for a type yourself, you don't need to read +/// this section.* +/// +/// If a type has the following properties, then this derive can implement +/// `Unaligned` for that type: +/// +/// - If the type is a struct or union: +/// - If `repr(align(N))` is provided, `N` must equal 1. +/// - If the type is `repr(C)` or `repr(transparent)`, all fields must be +/// [`Unaligned`]. +/// - If the type is not `repr(C)` or `repr(transparent)`, it must be +/// `repr(packed)` or `repr(packed(1))`. +/// - If the type is an enum: +/// - If `repr(align(N))` is provided, `N` must equal 1. +/// - It must be a field-less enum (meaning that all variants have no fields). +/// - It must be `repr(i8)` or `repr(u8)`. +/// +/// [safety conditions]: trait@Unaligned#safety +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::Unaligned; + +/// Types with no alignment requirement. +/// +/// If `T: Unaligned`, then `align_of::() == 1`. +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(Unaligned)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::Unaligned; +/// #[derive(Unaligned)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Unaligned)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant0, +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(Unaligned)] +/// #[repr(packed)] +/// union MyUnion { +/// # variant: u8, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `Unaligned`. +/// +/// # Safety +/// +/// *This section describes what is required in order for `T: Unaligned`, and +/// what unsafe code may assume of such types. If you don't plan on implementing +/// `Unaligned` manually, and you don't plan on writing unsafe code that +/// operates on `Unaligned` types, then you don't need to read this section.* +/// +/// If `T: Unaligned`, then unsafe code may assume that it is sound to produce a +/// reference to `T` at any memory location regardless of alignment. If a type +/// is marked as `Unaligned` which violates this contract, it may cause +/// undefined behavior. +/// +/// `#[derive(Unaligned)]` only permits [types which satisfy these +/// requirements][derive-analysis]. +/// +#[cfg_attr( + feature = "derive", + doc = "[derive]: zerocopy_derive::Unaligned", + doc = "[derive-analysis]: zerocopy_derive::Unaligned#analysis" +)] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html"), + doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html#analysis"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(Unaligned)]` to `{Self}`") +)] +pub unsafe trait Unaligned { + // The `Self: Sized` bound makes it so that `Unaligned` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; +} + +/// Derives optimized [`PartialEq`] and [`Eq`] implementations. +/// +/// This derive can be applied to structs and enums implementing both +/// [`Immutable`] and [`IntoBytes`]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{ByteEq, Immutable, IntoBytes}; +/// #[derive(ByteEq, Immutable, IntoBytes)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(ByteEq, Immutable, IntoBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// The standard library's [`derive(Eq, PartialEq)`][derive@PartialEq] computes +/// equality by individually comparing each field. Instead, the implementation +/// of [`PartialEq::eq`] emitted by `derive(ByteHash)` converts the entirety of +/// `self` and `other` to byte slices and compares those slices for equality. +/// This may have performance advantages. +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::ByteEq; +/// Derives an optimized [`Hash`] implementation. +/// +/// This derive can be applied to structs and enums implementing both +/// [`Immutable`] and [`IntoBytes`]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{ByteHash, Immutable, IntoBytes}; +/// #[derive(ByteHash, Immutable, IntoBytes)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(ByteHash, Immutable, IntoBytes)] +/// #[repr(u8)] +/// enum MyEnum { +/// # Variant, +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// The standard library's [`derive(Hash)`][derive@Hash] produces hashes by +/// individually hashing each field and combining the results. Instead, the +/// implementations of [`Hash::hash()`] and [`Hash::hash_slice()`] generated by +/// `derive(ByteHash)` convert the entirety of `self` to a byte slice and hashes +/// it in a single call to [`Hasher::write()`]. This may have performance +/// advantages. +/// +/// [`Hash`]: core::hash::Hash +/// [`Hash::hash()`]: core::hash::Hash::hash() +/// [`Hash::hash_slice()`]: core::hash::Hash::hash_slice() +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::ByteHash; +/// Implements [`SplitAt`]. +/// +/// This derive can be applied to structs; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{ByteEq, Immutable, IntoBytes}; +/// #[derive(ByteEq, Immutable, IntoBytes)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ... +/// # */ +/// } +/// ``` +#[cfg(any(feature = "derive", test))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use zerocopy_derive::SplitAt; + +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] +mod alloc_support { + use super::*; + + /// Extends a `Vec` by pushing `additional` new items onto the end of the + /// vector. The new items are initialized with zeros. + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[doc(hidden)] + #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")] + #[inline(always)] + pub fn extend_vec_zeroed( + v: &mut Vec, + additional: usize, + ) -> Result<(), AllocError> { + ::extend_vec_zeroed(v, additional) + } + + /// Inserts `additional` new items into `Vec` at `position`. The new + /// items are initialized with zeros. + /// + /// # Panics + /// + /// Panics if `position > v.len()`. + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[doc(hidden)] + #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")] + #[inline(always)] + pub fn insert_vec_zeroed( + v: &mut Vec, + position: usize, + additional: usize, + ) -> Result<(), AllocError> { + ::insert_vec_zeroed(v, position, additional) + } +} + +#[cfg(feature = "alloc")] +#[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] +#[doc(hidden)] +pub use alloc_support::*; + +#[cfg(test)] +#[allow(clippy::assertions_on_result_states, clippy::unreadable_literal)] +mod tests { + use static_assertions::assert_impl_all; + + use super::*; + use crate::util::testutil::*; + + // An unsized type. + // + // This is used to test the custom derives of our traits. The `[u8]` type + // gets a hand-rolled impl, so it doesn't exercise our custom derives. + #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Unaligned, Immutable)] + #[repr(transparent)] + struct Unsized([u8]); + + impl Unsized { + fn from_mut_slice(slc: &mut [u8]) -> &mut Unsized { + // SAFETY: This *probably* sound - since the layouts of `[u8]` and + // `Unsized` are the same, so are the layouts of `&mut [u8]` and + // `&mut Unsized`. [1] Even if it turns out that this isn't actually + // guaranteed by the language spec, we can just change this since + // it's in test code. + // + // [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/375 + unsafe { mem::transmute(slc) } + } + } + + #[test] + fn test_known_layout() { + // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout. + // Test that `PhantomData<$ty>` has the same layout as `()` regardless + // of `$ty`. + macro_rules! test { + ($ty:ty, $expect:expr) => { + let expect = $expect; + assert_eq!(<$ty as KnownLayout>::LAYOUT, expect); + assert_eq!( as KnownLayout>::LAYOUT, expect); + assert_eq!( as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT); + }; + } + + let layout = + |offset, align, trailing_slice_elem_size, statically_shallow_unpadded| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: match trailing_slice_elem_size { + None => SizeInfo::Sized { size: offset }, + Some(elem_size) => { + SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) + } + }, + statically_shallow_unpadded, + }; + + test!((), layout(0, 1, None, false)); + test!(u8, layout(1, 1, None, false)); + // Use `align_of` because `u64` alignment may be smaller than 8 on some + // platforms. + test!(u64, layout(8, mem::align_of::(), None, false)); + test!(AU64, layout(8, 8, None, false)); + + test!(Option<&'static ()>, usize::LAYOUT); + + test!([()], layout(0, 1, Some(0), true)); + test!([u8], layout(0, 1, Some(1), true)); + test!(str, layout(0, 1, Some(1), true)); + } + + #[cfg(feature = "derive")] + #[test] + fn test_known_layout_derive() { + // In this and other files (`late_compile_pass.rs`, + // `mid_compile_pass.rs`, and `struct.rs`), we test success and failure + // modes of `derive(KnownLayout)` for the following combination of + // properties: + // + // +------------+--------------------------------------+-----------+ + // | | trailing field properties | | + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // |------------+----------+----------------+----------+-----------| + // | N | N | N | N | KL00 | + // | N | N | N | Y | KL01 | + // | N | N | Y | N | KL02 | + // | N | N | Y | Y | KL03 | + // | N | Y | N | N | KL04 | + // | N | Y | N | Y | KL05 | + // | N | Y | Y | N | KL06 | + // | N | Y | Y | Y | KL07 | + // | Y | N | N | N | KL08 | + // | Y | N | N | Y | KL09 | + // | Y | N | Y | N | KL10 | + // | Y | N | Y | Y | KL11 | + // | Y | Y | N | N | KL12 | + // | Y | Y | N | Y | KL13 | + // | Y | Y | Y | N | KL14 | + // | Y | Y | Y | Y | KL15 | + // +------------+----------+----------------+----------+-----------+ + + struct NotKnownLayout { + _t: T, + } + + #[derive(KnownLayout)] + #[repr(C)] + struct AlignSize + where + elain::Align: elain::Alignment, + { + _align: elain::Align, + size: [u8; SIZE], + } + + type AU16 = AlignSize<2, 2>; + type AU32 = AlignSize<4, 4>; + + fn _assert_kl(_: &T) {} + + let sized_layout = |align, size| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::Sized { size }, + statically_shallow_unpadded: false, + }; + + let unsized_layout = |align, elem_size, offset, statically_shallow_unpadded| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }), + statically_shallow_unpadded, + }; + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | N | N | Y | KL01 | + #[allow(dead_code)] + #[derive(KnownLayout)] + struct KL01(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(4, 8)); + + // ...with `align(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(align(64))] + struct KL01Align(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); + + // ...with `packed`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(packed)] + struct KL01Packed(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 6)); + + // ...with `packed(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(packed(2))] + struct KL01PackedN(NotKnownLayout, NotKnownLayout); + + assert_impl_all!(KL01PackedN: KnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 6)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | N | Y | Y | KL03 | + #[allow(dead_code)] + #[derive(KnownLayout)] + struct KL03(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 1)); + + // ... with `align(N)` + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(align(64))] + struct KL03Align(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); + + // ... with `packed`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(packed)] + struct KL03Packed(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 5)); + + // ... with `packed(N)` + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(packed(2))] + struct KL03PackedN(NotKnownLayout, u8); + + assert_impl_all!(KL03PackedN: KnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 6)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | Y | N | Y | KL05 | + #[allow(dead_code)] + #[derive(KnownLayout)] + struct KL05(u8, T); + + fn _test_kl05(t: T) -> impl KnownLayout { + KL05(0u8, t) + } + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | Y | Y | Y | KL07 | + #[allow(dead_code)] + #[derive(KnownLayout)] + struct KL07(u8, T); + + fn _test_kl07(t: T) -> impl KnownLayout { + let _ = KL07(0u8, t); + } + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | N | Y | N | KL10 | + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C)] + struct KL10(NotKnownLayout, [u8]); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), None) + .extend(<[u8] as KnownLayout>::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(4, 1, 4, false)); + + // ...with `align(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, align(64))] + struct KL10Align(NotKnownLayout, [u8]); + + let repr_align = NonZeroUsize::new(64); + + let expected = DstLayout::new_zst(repr_align) + .extend(DstLayout::for_type::>(), None) + .extend(<[u8] as KnownLayout>::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(64, 1, 4, false)); + + // ...with `packed`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, packed)] + struct KL10Packed(NotKnownLayout, [u8]); + + let repr_packed = NonZeroUsize::new(1); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(1, 1, 4, false)); + + // ...with `packed(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, packed(2))] + struct KL10PackedN(NotKnownLayout, [u8]); + + let repr_packed = NonZeroUsize::new(2); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(2, 1, 4, false)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | N | Y | Y | KL11 | + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C)] + struct KL11(NotKnownLayout, u8); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), None) + .extend(::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(8, 16)); + + // ...with `align(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, align(64))] + struct KL11Align(NotKnownLayout, u8); + + let repr_align = NonZeroUsize::new(64); + + let expected = DstLayout::new_zst(repr_align) + .extend(DstLayout::for_type::>(), None) + .extend(::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); + + // ...with `packed`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, packed)] + struct KL11Packed(NotKnownLayout, u8); + + let repr_packed = NonZeroUsize::new(1); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 9)); + + // ...with `packed(N)`: + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C, packed(2))] + struct KL11PackedN(NotKnownLayout, u8); + + let repr_packed = NonZeroUsize::new(2); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 10)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | Y | Y | N | KL14 | + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C)] + struct KL14(u8, T); + + fn _test_kl14(kl: &KL14) { + _assert_kl(kl) + } + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | Y | Y | Y | KL15 | + #[allow(dead_code)] + #[derive(KnownLayout)] + #[repr(C)] + struct KL15(u8, T); + + fn _test_kl15(t: T) -> impl KnownLayout { + let _ = KL15(0u8, t); + } + + // Test a variety of combinations of field types: + // - () + // - u8 + // - AU16 + // - [()] + // - [u8] + // - [AU16] + + #[allow(clippy::upper_case_acronyms, dead_code)] + #[derive(KnownLayout)] + #[repr(C)] + struct KLTU(T, U); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 0)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 0, 0, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 0, false)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 0, 1, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2, false)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 0, 2, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 1, 2, false)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2, false)); + + // Test a variety of field counts. + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF0; + + assert_eq!(::LAYOUT, sized_layout(1, 0)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF1([u8]); + + assert_eq!(::LAYOUT, unsized_layout(1, 1, 0, true)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF2(NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(1, 1, 1, false)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF3(NotKnownLayout, NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(2, 1, 4, false)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF4(NotKnownLayout, NotKnownLayout, NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(4, 1, 8, false)); + } + + #[test] + fn test_object_safety() { + fn _takes_no_cell(_: &dyn Immutable) {} + fn _takes_unaligned(_: &dyn Unaligned) {} + } + + #[test] + fn test_from_zeros_only() { + // Test types that implement `FromZeros` but not `FromBytes`. + + assert!(!bool::new_zeroed()); + assert_eq!(char::new_zeroed(), '\0'); + + #[cfg(feature = "alloc")] + { + assert_eq!(bool::new_box_zeroed(), Ok(Box::new(false))); + assert_eq!(char::new_box_zeroed(), Ok(Box::new('\0'))); + + assert_eq!( + <[bool]>::new_box_zeroed_with_elems(3).unwrap().as_ref(), + [false, false, false] + ); + assert_eq!( + <[char]>::new_box_zeroed_with_elems(3).unwrap().as_ref(), + ['\0', '\0', '\0'] + ); + + assert_eq!(bool::new_vec_zeroed(3).unwrap().as_ref(), [false, false, false]); + assert_eq!(char::new_vec_zeroed(3).unwrap().as_ref(), ['\0', '\0', '\0']); + } + + let mut string = "hello".to_string(); + let s: &mut str = string.as_mut(); + assert_eq!(s, "hello"); + s.zero(); + assert_eq!(s, "\0\0\0\0\0"); + } + + #[test] + fn test_zst_count_preserved() { + // Test that, when an explicit count is provided to for a type with a + // ZST trailing slice element, that count is preserved. This is + // important since, for such types, all element counts result in objects + // of the same size, and so the correct behavior is ambiguous. However, + // preserving the count as requested by the user is the behavior that we + // document publicly. + + // FromZeros methods + #[cfg(feature = "alloc")] + assert_eq!(<[()]>::new_box_zeroed_with_elems(3).unwrap().len(), 3); + #[cfg(feature = "alloc")] + assert_eq!(<()>::new_vec_zeroed(3).unwrap().len(), 3); + + // FromBytes methods + assert_eq!(<[()]>::ref_from_bytes_with_elems(&[][..], 3).unwrap().len(), 3); + assert_eq!(<[()]>::ref_from_prefix_with_elems(&[][..], 3).unwrap().0.len(), 3); + assert_eq!(<[()]>::ref_from_suffix_with_elems(&[][..], 3).unwrap().1.len(), 3); + assert_eq!(<[()]>::mut_from_bytes_with_elems(&mut [][..], 3).unwrap().len(), 3); + assert_eq!(<[()]>::mut_from_prefix_with_elems(&mut [][..], 3).unwrap().0.len(), 3); + assert_eq!(<[()]>::mut_from_suffix_with_elems(&mut [][..], 3).unwrap().1.len(), 3); + } + + #[test] + fn test_read_write() { + const VAL: u64 = 0x12345678; + #[cfg(target_endian = "big")] + const VAL_BYTES: [u8; 8] = VAL.to_be_bytes(); + #[cfg(target_endian = "little")] + const VAL_BYTES: [u8; 8] = VAL.to_le_bytes(); + const ZEROS: [u8; 8] = [0u8; 8]; + + // Test `FromBytes::{read_from, read_from_prefix, read_from_suffix}`. + + assert_eq!(u64::read_from_bytes(&VAL_BYTES[..]), Ok(VAL)); + // The first 8 bytes are from `VAL_BYTES` and the second 8 bytes are all + // zeros. + let bytes_with_prefix: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]); + assert_eq!(u64::read_from_prefix(&bytes_with_prefix[..]), Ok((VAL, &ZEROS[..]))); + assert_eq!(u64::read_from_suffix(&bytes_with_prefix[..]), Ok((&VAL_BYTES[..], 0))); + // The first 8 bytes are all zeros and the second 8 bytes are from + // `VAL_BYTES` + let bytes_with_suffix: [u8; 16] = transmute!([[0; 8], VAL_BYTES]); + assert_eq!(u64::read_from_prefix(&bytes_with_suffix[..]), Ok((0, &VAL_BYTES[..]))); + assert_eq!(u64::read_from_suffix(&bytes_with_suffix[..]), Ok((&ZEROS[..], VAL))); + + // Test `IntoBytes::{write_to, write_to_prefix, write_to_suffix}`. + + let mut bytes = [0u8; 8]; + assert_eq!(VAL.write_to(&mut bytes[..]), Ok(())); + assert_eq!(bytes, VAL_BYTES); + let mut bytes = [0u8; 16]; + assert_eq!(VAL.write_to_prefix(&mut bytes[..]), Ok(())); + let want: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]); + assert_eq!(bytes, want); + let mut bytes = [0u8; 16]; + assert_eq!(VAL.write_to_suffix(&mut bytes[..]), Ok(())); + let want: [u8; 16] = transmute!([[0; 8], VAL_BYTES]); + assert_eq!(bytes, want); + } + + #[test] + #[cfg(feature = "std")] + fn test_read_io_with_padding_soundness() { + // This test is designed to exhibit potential UB in + // `FromBytes::read_from_io`. (see #2319, #2320). + + // On most platforms (where `align_of::() == 2`), `WithPadding` + // will have inter-field padding between `x` and `y`. + #[derive(FromBytes)] + #[repr(C)] + struct WithPadding { + x: u8, + y: u16, + } + struct ReadsInRead; + impl std::io::Read for ReadsInRead { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + // This body branches on every byte of `buf`, ensuring that it + // exhibits UB if any byte of `buf` is uninitialized. + if buf.iter().all(|&x| x == 0) { + Ok(buf.len()) + } else { + buf.iter_mut().for_each(|x| *x = 0); + Ok(buf.len()) + } + } + } + assert!(matches!(WithPadding::read_from_io(ReadsInRead), Ok(WithPadding { x: 0, y: 0 }))); + } + + #[test] + #[cfg(feature = "std")] + fn test_read_write_io() { + let mut long_buffer = [0, 0, 0, 0]; + assert!(matches!(u16::MAX.write_to_io(&mut long_buffer[..]), Ok(()))); + assert_eq!(long_buffer, [255, 255, 0, 0]); + assert!(matches!(u16::read_from_io(&long_buffer[..]), Ok(u16::MAX))); + + let mut short_buffer = [0, 0]; + assert!(u32::MAX.write_to_io(&mut short_buffer[..]).is_err()); + assert_eq!(short_buffer, [255, 255]); + assert!(u32::read_from_io(&short_buffer[..]).is_err()); + } + + #[test] + fn test_try_from_bytes_try_read_from() { + assert_eq!(::try_read_from_bytes(&[0]), Ok(false)); + assert_eq!(::try_read_from_bytes(&[1]), Ok(true)); + + assert_eq!(::try_read_from_prefix(&[0, 2]), Ok((false, &[2][..]))); + assert_eq!(::try_read_from_prefix(&[1, 2]), Ok((true, &[2][..]))); + + assert_eq!(::try_read_from_suffix(&[2, 0]), Ok((&[2][..], false))); + assert_eq!(::try_read_from_suffix(&[2, 1]), Ok((&[2][..], true))); + + // If we don't pass enough bytes, it fails. + assert!(matches!( + ::try_read_from_bytes(&[]), + Err(TryReadError::Size(_)) + )); + assert!(matches!( + ::try_read_from_prefix(&[]), + Err(TryReadError::Size(_)) + )); + assert!(matches!( + ::try_read_from_suffix(&[]), + Err(TryReadError::Size(_)) + )); + + // If we pass too many bytes, it fails. + assert!(matches!( + ::try_read_from_bytes(&[0, 0]), + Err(TryReadError::Size(_)) + )); + + // If we pass an invalid value, it fails. + assert!(matches!( + ::try_read_from_bytes(&[2]), + Err(TryReadError::Validity(_)) + )); + assert!(matches!( + ::try_read_from_prefix(&[2, 0]), + Err(TryReadError::Validity(_)) + )); + assert!(matches!( + ::try_read_from_suffix(&[0, 2]), + Err(TryReadError::Validity(_)) + )); + + // Reading from a misaligned buffer should still succeed. Since `AU64`'s + // alignment is 8, and since we read from two adjacent addresses one + // byte apart, it is guaranteed that at least one of them (though + // possibly both) will be misaligned. + let bytes: [u8; 9] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + assert_eq!(::try_read_from_bytes(&bytes[..8]), Ok(AU64(0))); + assert_eq!(::try_read_from_bytes(&bytes[1..9]), Ok(AU64(0))); + + assert_eq!( + ::try_read_from_prefix(&bytes[..8]), + Ok((AU64(0), &[][..])) + ); + assert_eq!( + ::try_read_from_prefix(&bytes[1..9]), + Ok((AU64(0), &[][..])) + ); + + assert_eq!( + ::try_read_from_suffix(&bytes[..8]), + Ok((&[][..], AU64(0))) + ); + assert_eq!( + ::try_read_from_suffix(&bytes[1..9]), + Ok((&[][..], AU64(0))) + ); + } + + #[test] + fn test_ref_from_mut_from() { + // Test `FromBytes::{ref_from, mut_from}{,_prefix,Suffix}` success cases + // Exhaustive coverage for these methods is covered by the `Ref` tests above, + // which these helper methods defer to. + + let mut buf = + Align::<[u8; 16], AU64>::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + + assert_eq!( + AU64::ref_from_bytes(&buf.t[8..]).unwrap().0.to_ne_bytes(), + [8, 9, 10, 11, 12, 13, 14, 15] + ); + let suffix = AU64::mut_from_bytes(&mut buf.t[8..]).unwrap(); + suffix.0 = 0x0101010101010101; + // The `[u8:9]` is a non-half size of the full buffer, which would catch + // `from_prefix` having the same implementation as `from_suffix` (issues #506, #511). + assert_eq!( + <[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(), + (&[0, 1, 2, 3, 4, 5, 6][..], &[7u8, 1, 1, 1, 1, 1, 1, 1, 1]) + ); + let (prefix, suffix) = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap(); + assert_eq!(prefix, &mut [1u8, 2, 3, 4, 5, 6, 7][..]); + suffix.0 = 0x0202020202020202; + let (prefix, suffix) = <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap(); + assert_eq!(prefix, &mut [0u8, 1, 2, 3, 4, 5][..]); + suffix[0] = 42; + assert_eq!( + <[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(), + (&[0u8, 1, 2, 3, 4, 5, 42, 7, 2], &[2u8, 2, 2, 2, 2, 2, 2][..]) + ); + <[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap().0[1] = 30; + assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]); + } + + #[test] + fn test_ref_from_mut_from_error() { + // Test `FromBytes::{ref_from, mut_from}{,_prefix,Suffix}` error cases. + + // Fail because the buffer is too large. + let mut buf = Align::<[u8; 16], AU64>::default(); + // `buf.t` should be aligned to 8, so only the length check should fail. + assert!(AU64::ref_from_bytes(&buf.t[..]).is_err()); + assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err()); + assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err()); + assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err()); + + // Fail because the buffer is too small. + let mut buf = Align::<[u8; 4], AU64>::default(); + assert!(AU64::ref_from_bytes(&buf.t[..]).is_err()); + assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err()); + assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err()); + assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err()); + assert!(AU64::ref_from_prefix(&buf.t[..]).is_err()); + assert!(AU64::mut_from_prefix(&mut buf.t[..]).is_err()); + assert!(AU64::ref_from_suffix(&buf.t[..]).is_err()); + assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err()); + assert!(<[u8; 8]>::ref_from_prefix(&buf.t[..]).is_err()); + assert!(<[u8; 8]>::mut_from_prefix(&mut buf.t[..]).is_err()); + assert!(<[u8; 8]>::ref_from_suffix(&buf.t[..]).is_err()); + assert!(<[u8; 8]>::mut_from_suffix(&mut buf.t[..]).is_err()); + + // Fail because the alignment is insufficient. + let mut buf = Align::<[u8; 13], AU64>::default(); + assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err()); + assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err()); + assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err()); + assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err()); + assert!(AU64::ref_from_prefix(&buf.t[1..]).is_err()); + assert!(AU64::mut_from_prefix(&mut buf.t[1..]).is_err()); + assert!(AU64::ref_from_suffix(&buf.t[..]).is_err()); + assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err()); + } + + #[test] + fn test_to_methods() { + /// Run a series of tests by calling `IntoBytes` methods on `t`. + /// + /// `bytes` is the expected byte sequence returned from `t.as_bytes()` + /// before `t` has been modified. `post_mutation` is the expected + /// sequence returned from `t.as_bytes()` after `t.as_mut_bytes()[0]` + /// has had its bits flipped (by applying `^= 0xFF`). + /// + /// `N` is the size of `t` in bytes. + fn test( + t: &mut T, + bytes: &[u8], + post_mutation: &T, + ) { + // Test that we can access the underlying bytes, and that we get the + // right bytes and the right number of bytes. + assert_eq!(t.as_bytes(), bytes); + + // Test that changes to the underlying byte slices are reflected in + // the original object. + t.as_mut_bytes()[0] ^= 0xFF; + assert_eq!(t, post_mutation); + t.as_mut_bytes()[0] ^= 0xFF; + + // `write_to` rejects slices that are too small or too large. + assert!(t.write_to(&mut vec![0; N - 1][..]).is_err()); + assert!(t.write_to(&mut vec![0; N + 1][..]).is_err()); + + // `write_to` works as expected. + let mut bytes = [0; N]; + assert_eq!(t.write_to(&mut bytes[..]), Ok(())); + assert_eq!(bytes, t.as_bytes()); + + // `write_to_prefix` rejects slices that are too small. + assert!(t.write_to_prefix(&mut vec![0; N - 1][..]).is_err()); + + // `write_to_prefix` works with exact-sized slices. + let mut bytes = [0; N]; + assert_eq!(t.write_to_prefix(&mut bytes[..]), Ok(())); + assert_eq!(bytes, t.as_bytes()); + + // `write_to_prefix` works with too-large slices, and any bytes past + // the prefix aren't modified. + let mut too_many_bytes = vec![0; N + 1]; + too_many_bytes[N] = 123; + assert_eq!(t.write_to_prefix(&mut too_many_bytes[..]), Ok(())); + assert_eq!(&too_many_bytes[..N], t.as_bytes()); + assert_eq!(too_many_bytes[N], 123); + + // `write_to_suffix` rejects slices that are too small. + assert!(t.write_to_suffix(&mut vec![0; N - 1][..]).is_err()); + + // `write_to_suffix` works with exact-sized slices. + let mut bytes = [0; N]; + assert_eq!(t.write_to_suffix(&mut bytes[..]), Ok(())); + assert_eq!(bytes, t.as_bytes()); + + // `write_to_suffix` works with too-large slices, and any bytes + // before the suffix aren't modified. + let mut too_many_bytes = vec![0; N + 1]; + too_many_bytes[0] = 123; + assert_eq!(t.write_to_suffix(&mut too_many_bytes[..]), Ok(())); + assert_eq!(&too_many_bytes[1..], t.as_bytes()); + assert_eq!(too_many_bytes[0], 123); + } + + #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Immutable)] + #[repr(C)] + struct Foo { + a: u32, + b: Wrapping, + c: Option, + } + + let expected_bytes: Vec = if cfg!(target_endian = "little") { + vec![1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0] + } else { + vec![0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0] + }; + let post_mutation_expected_a = + if cfg!(target_endian = "little") { 0x00_00_00_FE } else { 0xFF_00_00_01 }; + test::<_, 12>( + &mut Foo { a: 1, b: Wrapping(2), c: None }, + expected_bytes.as_bytes(), + &Foo { a: post_mutation_expected_a, b: Wrapping(2), c: None }, + ); + test::<_, 3>( + Unsized::from_mut_slice(&mut [1, 2, 3]), + &[1, 2, 3], + Unsized::from_mut_slice(&mut [0xFE, 2, 3]), + ); + } + + #[test] + fn test_array() { + #[derive(FromBytes, IntoBytes, Immutable)] + #[repr(C)] + struct Foo { + a: [u16; 33], + } + + let foo = Foo { a: [0xFFFF; 33] }; + let expected = [0xFFu8; 66]; + assert_eq!(foo.as_bytes(), &expected[..]); + } + + #[test] + fn test_new_zeroed() { + assert!(!bool::new_zeroed()); + assert_eq!(u64::new_zeroed(), 0); + // This test exists in order to exercise unsafe code, especially when + // running under Miri. + #[allow(clippy::unit_cmp)] + { + assert_eq!(<()>::new_zeroed(), ()); + } + } + + #[test] + fn test_transparent_packed_generic_struct() { + #[derive(IntoBytes, FromBytes, Unaligned)] + #[repr(transparent)] + #[allow(dead_code)] // We never construct this type + struct Foo { + _t: T, + _phantom: PhantomData<()>, + } + + assert_impl_all!(Foo: FromZeros, FromBytes, IntoBytes); + assert_impl_all!(Foo: Unaligned); + + #[derive(IntoBytes, FromBytes, Unaligned)] + #[repr(C, packed)] + #[allow(dead_code)] // We never construct this type + struct Bar { + _t: T, + _u: U, + } + + assert_impl_all!(Bar: FromZeros, FromBytes, IntoBytes, Unaligned); + } + + #[cfg(feature = "alloc")] + mod alloc { + use super::*; + + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[test] + fn test_extend_vec_zeroed() { + // Test extending when there is an existing allocation. + let mut v = vec![100u16, 200, 300]; + FromZeros::extend_vec_zeroed(&mut v, 3).unwrap(); + assert_eq!(v.len(), 6); + assert_eq!(&*v, &[100, 200, 300, 0, 0, 0]); + drop(v); + + // Test extending when there is no existing allocation. + let mut v: Vec = Vec::new(); + FromZeros::extend_vec_zeroed(&mut v, 3).unwrap(); + assert_eq!(v.len(), 3); + assert_eq!(&*v, &[0, 0, 0]); + drop(v); + } + + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[test] + fn test_extend_vec_zeroed_zst() { + // Test extending when there is an existing (fake) allocation. + let mut v = vec![(), (), ()]; + <()>::extend_vec_zeroed(&mut v, 3).unwrap(); + assert_eq!(v.len(), 6); + assert_eq!(&*v, &[(), (), (), (), (), ()]); + drop(v); + + // Test extending when there is no existing (fake) allocation. + let mut v: Vec<()> = Vec::new(); + <()>::extend_vec_zeroed(&mut v, 3).unwrap(); + assert_eq!(&*v, &[(), (), ()]); + drop(v); + } + + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[test] + fn test_insert_vec_zeroed() { + // Insert at start (no existing allocation). + let mut v: Vec = Vec::new(); + u64::insert_vec_zeroed(&mut v, 0, 2).unwrap(); + assert_eq!(v.len(), 2); + assert_eq!(&*v, &[0, 0]); + drop(v); + + // Insert at start. + let mut v = vec![100u64, 200, 300]; + u64::insert_vec_zeroed(&mut v, 0, 2).unwrap(); + assert_eq!(v.len(), 5); + assert_eq!(&*v, &[0, 0, 100, 200, 300]); + drop(v); + + // Insert at middle. + let mut v = vec![100u64, 200, 300]; + u64::insert_vec_zeroed(&mut v, 1, 1).unwrap(); + assert_eq!(v.len(), 4); + assert_eq!(&*v, &[100, 0, 200, 300]); + drop(v); + + // Insert at end. + let mut v = vec![100u64, 200, 300]; + u64::insert_vec_zeroed(&mut v, 3, 1).unwrap(); + assert_eq!(v.len(), 4); + assert_eq!(&*v, &[100, 200, 300, 0]); + drop(v); + } + + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + #[test] + fn test_insert_vec_zeroed_zst() { + // Insert at start (no existing fake allocation). + let mut v: Vec<()> = Vec::new(); + <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap(); + assert_eq!(v.len(), 2); + assert_eq!(&*v, &[(), ()]); + drop(v); + + // Insert at start. + let mut v = vec![(), (), ()]; + <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap(); + assert_eq!(v.len(), 5); + assert_eq!(&*v, &[(), (), (), (), ()]); + drop(v); + + // Insert at middle. + let mut v = vec![(), (), ()]; + <()>::insert_vec_zeroed(&mut v, 1, 1).unwrap(); + assert_eq!(v.len(), 4); + assert_eq!(&*v, &[(), (), (), ()]); + drop(v); + + // Insert at end. + let mut v = vec![(), (), ()]; + <()>::insert_vec_zeroed(&mut v, 3, 1).unwrap(); + assert_eq!(v.len(), 4); + assert_eq!(&*v, &[(), (), (), ()]); + drop(v); + } + + #[test] + fn test_new_box_zeroed() { + assert_eq!(u64::new_box_zeroed(), Ok(Box::new(0))); + } + + #[test] + fn test_new_box_zeroed_array() { + drop(<[u32; 0x1000]>::new_box_zeroed()); + } + + #[test] + fn test_new_box_zeroed_zst() { + // This test exists in order to exercise unsafe code, especially + // when running under Miri. + #[allow(clippy::unit_cmp)] + { + assert_eq!(<()>::new_box_zeroed(), Ok(Box::new(()))); + } + } + + #[test] + fn test_new_box_zeroed_with_elems() { + let mut s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(3).unwrap(); + assert_eq!(s.len(), 3); + assert_eq!(&*s, &[0, 0, 0]); + s[1] = 3; + assert_eq!(&*s, &[0, 3, 0]); + } + + #[test] + fn test_new_box_zeroed_with_elems_empty() { + let s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(0).unwrap(); + assert_eq!(s.len(), 0); + } + + #[test] + fn test_new_box_zeroed_with_elems_zst() { + let mut s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(3).unwrap(); + assert_eq!(s.len(), 3); + assert!(s.get(10).is_none()); + // This test exists in order to exercise unsafe code, especially + // when running under Miri. + #[allow(clippy::unit_cmp)] + { + assert_eq!(s[1], ()); + } + s[2] = (); + } + + #[test] + fn test_new_box_zeroed_with_elems_zst_empty() { + let s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(0).unwrap(); + assert_eq!(s.len(), 0); + } + + #[test] + fn new_box_zeroed_with_elems_errors() { + assert_eq!(<[u16]>::new_box_zeroed_with_elems(usize::MAX), Err(AllocError)); + + let max = >::try_from(isize::MAX).unwrap(); + assert_eq!( + <[u16]>::new_box_zeroed_with_elems((max / mem::size_of::()) + 1), + Err(AllocError) + ); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1623 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +/// Safely transmutes a value of one type to a value of another type of the same +/// size. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// const fn transmute(src: Src) -> Dst +/// where +/// Src: IntoBytes, +/// Dst: FromBytes, +/// size_of::() == size_of::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// However, unlike a function, this macro can only be invoked when the types of +/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are +/// inferred from the calling context; they cannot be explicitly specified in +/// the macro invocation. +/// +/// Note that the `Src` produced by the expression `$e` will *not* be dropped. +/// Semantically, its bits will be copied into a new value of type `Dst`, the +/// original `Src` will be forgotten, and the value of type `Dst` will be +/// returned. +/// +/// # `#![allow(shrink)]` +/// +/// If `#![allow(shrink)]` is provided, `transmute!` additionally supports +/// transmutations that shrink the size of the value; e.g.: +/// +/// ``` +/// # use zerocopy::transmute; +/// let u: u32 = transmute!(#![allow(shrink)] 0u64); +/// assert_eq!(u, 0u32); +/// ``` +/// +/// # Examples +/// +/// ``` +/// # use zerocopy::transmute; +/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; +/// +/// let two_dimensional: [[u8; 4]; 2] = transmute!(one_dimensional); +/// +/// assert_eq!(two_dimensional, [[0, 1, 2, 3], [4, 5, 6, 7]]); +/// ``` +/// +/// # Use in `const` contexts +/// +/// This macro can be invoked in `const` contexts. +#[macro_export] +macro_rules! transmute { + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two types + // have the same size. `core::mem::transmute` uses compiler magic to enforce + // this so long as the types are concrete. + (#![allow(shrink)] $e:expr) => {{ + let mut e = $e; + if false { + // This branch, though never taken, ensures that the type of `e` is + // `IntoBytes` and that the type of the outer macro invocation + // expression is `FromBytes`. + + fn transmute(src: Src) -> Dst + where + Src: $crate::IntoBytes, + Dst: $crate::FromBytes, + { + let _ = src; + loop {} + } + loop {} + #[allow(unreachable_code)] + transmute(e) + } else { + use $crate::util::macro_util::core_reexport::mem::ManuallyDrop; + + // NOTE: `repr(packed)` is important! It ensures that the size of + // `Transmute` won't be rounded up to accommodate `Src`'s or `Dst`'s + // alignment, which would break the size comparison logic below. + // + // As an example of why this is problematic, consider `Src = [u8; + // 5]`, `Dst = u32`. The total size of `Transmute` would + // be 8, and so we would reject a `[u8; 5]` to `u32` transmute as + // being size-increasing, which it isn't. + #[repr(C, packed)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + + // SAFETY: `Transmute` is a `reper(C)` union whose `src` field has + // type `ManuallyDrop`. Thus, the `src` field starts at byte + // offset 0 within `Transmute` [1]. `ManuallyDrop` has the same + // layout and bit validity as `T`, so it is sound to transmute `Src` + // to `Transmute`. + // + // [1] https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: + // + // `ManuallyDrop` is guaranteed to have the same layout and bit + // validity as `T` + let u: Transmute<_, _> = unsafe { + // Clippy: We can't annotate the types; this macro is designed + // to infer the types from the calling context. + #[allow(clippy::missing_transmute_annotations)] + $crate::util::macro_util::core_reexport::mem::transmute(e) + }; + + if false { + // SAFETY: This code is never executed. + e = ManuallyDrop::into_inner(unsafe { u.src }); + // Suppress the `unused_assignments` lint on the previous line. + let _ = e; + loop {} + } else { + // SAFETY: Per the safety comment on `let u` above, the `dst` + // field in `Transmute` starts at byte offset 0, and has the + // same layout and bit validity as `Dst`. + // + // Transmuting `Src` to `Transmute` above using + // `core::mem::transmute` ensures that `size_of::() == + // size_of::>()`. A `#[repr(C, packed)]` + // union has the maximum size of all of its fields [1], so this + // is equivalent to `size_of::() >= size_of::()`. + // + // The outer `if`'s `false` branch ensures that `Src: IntoBytes` + // and `Dst: FromBytes`. This, combined with the size bound, + // ensures that this transmute is sound. + // + // [1] Per https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions: + // + // The union will have a size of the maximum size of all of + // its fields rounded to its alignment + let dst = unsafe { u.dst }; + $crate::util::macro_util::must_use(ManuallyDrop::into_inner(dst)) + } + } + }}; + ($e:expr) => {{ + let e = $e; + if false { + // This branch, though never taken, ensures that the type of `e` is + // `IntoBytes` and that the type of the outer macro invocation + // expression is `FromBytes`. + + fn transmute(src: Src) -> Dst + where + Src: $crate::IntoBytes, + Dst: $crate::FromBytes, + { + let _ = src; + loop {} + } + loop {} + #[allow(unreachable_code)] + transmute(e) + } else { + // SAFETY: `core::mem::transmute` ensures that the type of `e` and + // the type of this macro invocation expression have the same size. + // We know this transmute is safe thanks to the `IntoBytes` and + // `FromBytes` bounds enforced by the `false` branch. + let u = unsafe { + // Clippy: We can't annotate the types; this macro is designed + // to infer the types from the calling context. + #[allow(clippy::missing_transmute_annotations, unnecessary_transmutes)] + $crate::util::macro_util::core_reexport::mem::transmute(e) + }; + $crate::util::macro_util::must_use(u) + } + }}; +} + +/// Safely transmutes a mutable or immutable reference of one type to an +/// immutable reference of another type of the same size and compatible +/// alignment. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst +/// where +/// 'src: 'dst, +/// Src: IntoBytes + Immutable + ?Sized, +/// Dst: FromBytes + Immutable + ?Sized, +/// align_of::() >= align_of::(), +/// size_compatible::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// The types `Src` and `Dst` are inferred from the calling context; they cannot +/// be explicitly specified in the macro invocation. +/// +/// # Size compatibility +/// +/// `transmute_ref!` supports transmuting between `Sized` types or between +/// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves +/// the number of bytes of the referent, even if doing so requires updating the +/// metadata stored in an unsized "fat" reference: +/// +/// ``` +/// # use zerocopy::transmute_ref; +/// # use core::mem::size_of_val; // Not in the prelude on our MSRV +/// let src: &[[u8; 2]] = &[[0, 1], [2, 3]][..]; +/// let dst: &[u8] = transmute_ref!(src); +/// +/// assert_eq!(src.len(), 2); +/// assert_eq!(dst.len(), 4); +/// assert_eq!(dst, [0, 1, 2, 3]); +/// assert_eq!(size_of_val(src), size_of_val(dst)); +/// ``` +/// +/// # Errors +/// +/// Violations of the alignment and size compatibility checks are detected +/// *after* the compiler performs monomorphization. This has two important +/// consequences. +/// +/// First, it means that generic code will *never* fail these conditions: +/// +/// ``` +/// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable}; +/// fn transmute_ref(src: &Src) -> &Dst +/// where +/// Src: IntoBytes + Immutable, +/// Dst: FromBytes + Immutable, +/// { +/// transmute_ref!(src) +/// } +/// ``` +/// +/// Instead, failures will only be detected once generic code is instantiated +/// with concrete types: +/// +/// ```compile_fail,E0080 +/// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable}; +/// # +/// # fn transmute_ref(src: &Src) -> &Dst +/// # where +/// # Src: IntoBytes + Immutable, +/// # Dst: FromBytes + Immutable, +/// # { +/// # transmute_ref!(src) +/// # } +/// let src: &u16 = &0; +/// let dst: &u8 = transmute_ref(src); +/// ``` +/// +/// Second, the fact that violations are detected after monomorphization means +/// that `cargo check` will usually not detect errors, even when types are +/// concrete. Instead, `cargo build` must be used to detect such errors. +/// +/// # Examples +/// +/// Transmuting between `Sized` types: +/// +/// ``` +/// # use zerocopy::transmute_ref; +/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; +/// +/// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional); +/// +/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]); +/// ``` +/// +/// Transmuting between unsized types: +/// +/// ``` +/// # use {zerocopy::*, zerocopy_derive::*}; +/// # type u16 = zerocopy::byteorder::native_endian::U16; +/// # type u32 = zerocopy::byteorder::native_endian::U32; +/// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)] +/// #[repr(C)] +/// struct SliceDst { +/// t: T, +/// u: [U], +/// } +/// +/// type Src = SliceDst; +/// type Dst = SliceDst; +/// +/// let src = Src::ref_from_bytes(&[0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); +/// let dst: &Dst = transmute_ref!(src); +/// +/// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]); +/// assert_eq!(src.u.len(), 2); +/// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]); +/// +/// assert_eq!(dst.t.as_bytes(), [0, 1]); +/// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]); +/// ``` +/// +/// # Use in `const` contexts +/// +/// This macro can be invoked in `const` contexts only when `Src: Sized` and +/// `Dst: Sized`. +#[macro_export] +macro_rules! transmute_ref { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size or alignment. + + // Ensure that the source type is a reference or a mutable reference + // (note that mutable references are implicitly reborrowed here). + let e: &_ = $e; + + #[allow(unused, clippy::diverging_sub_expression)] + if false { + // This branch, though never taken, ensures that the type of `e` is + // `&T` where `T: IntoBytes + Immutable`, and that the type of this + // macro expression is `&U` where `U: FromBytes + Immutable`. + + struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T); + struct AssertSrcIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T); + struct AssertDstIsFromBytes<'a, U: ?::core::marker::Sized + $crate::FromBytes>(&'a U); + struct AssertDstIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T); + + let _ = AssertSrcIsIntoBytes(e); + let _ = AssertSrcIsImmutable(e); + + if true { + #[allow(unused, unreachable_code)] + let u = AssertDstIsFromBytes(loop {}); + u.0 + } else { + #[allow(unused, unreachable_code)] + let u = AssertDstIsImmutable(loop {}); + u.0 + } + } else { + use $crate::util::macro_util::TransmuteRefDst; + let t = $crate::util::macro_util::Wrap::new(e); + // SAFETY: The `if false` branch ensures that: + // - `Src: IntoBytes + Immutable` + // - `Dst: FromBytes + Immutable` + unsafe { + t.transmute_ref() + } + } + }} +} + +/// Safely transmutes a mutable reference of one type to a mutable reference of +/// another type of the same size and compatible alignment. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst +/// where +/// 'src: 'dst, +/// Src: FromBytes + IntoBytes, +/// Dst: FromBytes + IntoBytes, +/// align_of::() >= align_of::(), +/// size_compatible::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// The types `Src` and `Dst` are inferred from the calling context; they cannot +/// be explicitly specified in the macro invocation. +/// +/// # Size compatibility +/// +/// `transmute_mut!` supports transmuting between `Sized` types or between +/// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves +/// the number of bytes of the referent, even if doing so requires updating the +/// metadata stored in an unsized "fat" reference: +/// +/// ``` +/// # use zerocopy::transmute_mut; +/// # use core::mem::size_of_val; // Not in the prelude on our MSRV +/// let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..]; +/// let dst: &mut [u8] = transmute_mut!(src); +/// +/// assert_eq!(dst.len(), 4); +/// assert_eq!(dst, [0, 1, 2, 3]); +/// let dst_size = size_of_val(dst); +/// assert_eq!(src.len(), 2); +/// assert_eq!(size_of_val(src), dst_size); +/// ``` +/// +/// # Errors +/// +/// Violations of the alignment and size compatibility checks are detected +/// *after* the compiler performs monomorphization. This has two important +/// consequences. +/// +/// First, it means that generic code will *never* fail these conditions: +/// +/// ``` +/// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable}; +/// fn transmute_mut(src: &mut Src) -> &mut Dst +/// where +/// Src: FromBytes + IntoBytes, +/// Dst: FromBytes + IntoBytes, +/// { +/// transmute_mut!(src) +/// } +/// ``` +/// +/// Instead, failures will only be detected once generic code is instantiated +/// with concrete types: +/// +/// ```compile_fail,E0080 +/// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable}; +/// # +/// # fn transmute_mut(src: &mut Src) -> &mut Dst +/// # where +/// # Src: FromBytes + IntoBytes, +/// # Dst: FromBytes + IntoBytes, +/// # { +/// # transmute_mut!(src) +/// # } +/// let src: &mut u16 = &mut 0; +/// let dst: &mut u8 = transmute_mut(src); +/// ``` +/// +/// Second, the fact that violations are detected after monomorphization means +/// that `cargo check` will usually not detect errors, even when types are +/// concrete. Instead, `cargo build` must be used to detect such errors. +/// +/// +/// # Examples +/// +/// Transmuting between `Sized` types: +/// +/// ``` +/// # use zerocopy::transmute_mut; +/// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; +/// +/// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional); +/// +/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]); +/// +/// two_dimensional.reverse(); +/// +/// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]); +/// ``` +/// +/// Transmuting between unsized types: +/// +/// ``` +/// # use {zerocopy::*, zerocopy_derive::*}; +/// # type u16 = zerocopy::byteorder::native_endian::U16; +/// # type u32 = zerocopy::byteorder::native_endian::U32; +/// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)] +/// #[repr(C)] +/// struct SliceDst { +/// t: T, +/// u: [U], +/// } +/// +/// type Src = SliceDst; +/// type Dst = SliceDst; +/// +/// let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7]; +/// let src = Src::mut_from_bytes(&mut bytes[..]).unwrap(); +/// let dst: &mut Dst = transmute_mut!(src); +/// +/// assert_eq!(dst.t.as_bytes(), [0, 1]); +/// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]); +/// +/// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]); +/// assert_eq!(src.u.len(), 2); +/// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]); +/// +/// ``` +#[macro_export] +macro_rules! transmute_mut { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because, for backwards-compatibility on v0.8.x, we use the autoref + // specialization trick to dispatch to different `transmute_mut` + // implementations: one which doesn't require `Src: KnownLayout + Dst: + // KnownLayout` when `Src: Sized + Dst: Sized`, and one which requires + // `KnownLayout` bounds otherwise. + + // Ensure that the source type is a mutable reference. + let e: &mut _ = $e; + + #[allow(unused)] + use $crate::util::macro_util::TransmuteMutDst as _; + let t = $crate::util::macro_util::Wrap::new(e); + t.transmute_mut() + }} +} + +/// Conditionally transmutes a value of one type to a value of another type of +/// the same size. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// fn try_transmute(src: Src) -> Result> +/// where +/// Src: IntoBytes, +/// Dst: TryFromBytes, +/// size_of::() == size_of::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// However, unlike a function, this macro can only be invoked when the types of +/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are +/// inferred from the calling context; they cannot be explicitly specified in +/// the macro invocation. +/// +/// Note that the `Src` produced by the expression `$e` will *not* be dropped. +/// Semantically, its bits will be copied into a new value of type `Dst`, the +/// original `Src` will be forgotten, and the value of type `Dst` will be +/// returned. +/// +/// # Examples +/// +/// ``` +/// # use zerocopy::*; +/// // 0u8 → bool = false +/// assert_eq!(try_transmute!(0u8), Ok(false)); +/// +/// // 1u8 → bool = true +/// assert_eq!(try_transmute!(1u8), Ok(true)); +/// +/// // 2u8 → bool = error +/// assert!(matches!( +/// try_transmute!(2u8), +/// Result::::Err(ValidityError { .. }) +/// )); +/// ``` +#[macro_export] +macro_rules! try_transmute { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size. `core::mem::transmute` uses compiler magic + // to enforce this so long as the types are concrete. + + let e = $e; + if false { + // Check that the sizes of the source and destination types are + // equal. + + // SAFETY: This code is never executed. + Ok(unsafe { + // Clippy: We can't annotate the types; this macro is designed + // to infer the types from the calling context. + #[allow(clippy::missing_transmute_annotations)] + $crate::util::macro_util::core_reexport::mem::transmute(e) + }) + } else { + $crate::util::macro_util::try_transmute::<_, _>(e) + } + }} +} + +/// Conditionally transmutes a mutable or immutable reference of one type to an +/// immutable reference of another type of the same size and compatible +/// alignment. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> +/// where +/// Src: IntoBytes + Immutable, +/// Dst: TryFromBytes + Immutable, +/// size_of::() == size_of::(), +/// align_of::() >= align_of::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// However, unlike a function, this macro can only be invoked when the types of +/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are +/// inferred from the calling context; they cannot be explicitly specified in +/// the macro invocation. +/// +/// # Examples +/// +/// ``` +/// # use zerocopy::*; +/// // 0u8 → bool = false +/// assert_eq!(try_transmute_ref!(&0u8), Ok(&false)); +/// +/// // 1u8 → bool = true +/// assert_eq!(try_transmute_ref!(&1u8), Ok(&true)); +/// +/// // 2u8 → bool = error +/// assert!(matches!( +/// try_transmute_ref!(&2u8), +/// Result::<&bool, _>::Err(ValidityError { .. }) +/// )); +/// ``` +/// +/// # Alignment increase error message +/// +/// Because of limitations on macros, the error message generated when +/// `try_transmute_ref!` is used to transmute from a type of lower alignment to +/// a type of higher alignment is somewhat confusing. For example, the following +/// code: +/// +/// ```compile_fail +/// let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]); +/// ``` +/// +/// ...generates the following error: +/// +/// ```text +/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types +/// --> example.rs:1:47 +/// | +/// 1 | let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]); +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = note: source type: `AlignOf<[u8; 2]>` (8 bits) +/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) +/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)/// ``` +/// ``` +/// +/// This is saying that `max(align_of::(), align_of::()) != +/// align_of::()`, which is equivalent to `align_of::() < +/// align_of::()`. +#[macro_export] +macro_rules! try_transmute_ref { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size. `core::mem::transmute` uses compiler magic + // to enforce this so long as the types are concrete. + + // Ensure that the source type is a reference or a mutable reference + // (note that mutable references are implicitly reborrowed here). + let e: &_ = $e; + + #[allow(unreachable_code, unused, clippy::diverging_sub_expression)] + if false { + // This branch, though never taken, ensures that `size_of::() == + // size_of::()` and that that `align_of::() >= + // align_of::()`. + + // `t` is inferred to have type `T` because it's assigned to `e` (of + // type `&T`) as `&t`. + let mut t = loop {}; + e = &t; + + // `u` is inferred to have type `U` because it's used as `Ok(&u)` as + // the value returned from this branch. + let u; + + $crate::assert_size_eq!(t, u); + $crate::assert_align_gt_eq!(t, u); + + Ok(&u) + } else { + $crate::util::macro_util::try_transmute_ref::<_, _>(e) + } + }} +} + +/// Conditionally transmutes a mutable reference of one type to a mutable +/// reference of another type of the same size and compatible alignment. +/// +/// This macro behaves like an invocation of this function: +/// +/// ```ignore +/// fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> +/// where +/// Src: FromBytes + IntoBytes, +/// Dst: TryFromBytes + IntoBytes, +/// size_of::() == size_of::(), +/// align_of::() >= align_of::(), +/// { +/// # /* +/// ... +/// # */ +/// } +/// ``` +/// +/// However, unlike a function, this macro can only be invoked when the types of +/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are +/// inferred from the calling context; they cannot be explicitly specified in +/// the macro invocation. +/// +/// # Examples +/// +/// ``` +/// # use zerocopy::*; +/// // 0u8 → bool = false +/// let src = &mut 0u8; +/// assert_eq!(try_transmute_mut!(src), Ok(&mut false)); +/// +/// // 1u8 → bool = true +/// let src = &mut 1u8; +/// assert_eq!(try_transmute_mut!(src), Ok(&mut true)); +/// +/// // 2u8 → bool = error +/// let src = &mut 2u8; +/// assert!(matches!( +/// try_transmute_mut!(src), +/// Result::<&mut bool, _>::Err(ValidityError { .. }) +/// )); +/// ``` +/// +/// # Alignment increase error message +/// +/// Because of limitations on macros, the error message generated when +/// `try_transmute_ref!` is used to transmute from a type of lower alignment to +/// a type of higher alignment is somewhat confusing. For example, the following +/// code: +/// +/// ```compile_fail +/// let src = &mut [0u8; 2]; +/// let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src); +/// ``` +/// +/// ...generates the following error: +/// +/// ```text +/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types +/// --> example.rs:2:51 +/// | +/// 2 | let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src); +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = note: source type: `AlignOf<[u8; 2]>` (8 bits) +/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) +/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) +/// ``` +/// +/// This is saying that `max(align_of::(), align_of::()) != +/// align_of::()`, which is equivalent to `align_of::() < +/// align_of::()`. +#[macro_export] +macro_rules! try_transmute_mut { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size. `core::mem::transmute` uses compiler magic + // to enforce this so long as the types are concrete. + + // Ensure that the source type is a mutable reference. + let e: &mut _ = $e; + + #[allow(unreachable_code, unused, clippy::diverging_sub_expression)] + if false { + // This branch, though never taken, ensures that `size_of::() == + // size_of::()` and that that `align_of::() >= + // align_of::()`. + + // `t` is inferred to have type `T` because it's assigned to `e` (of + // type `&mut T`) as `&mut t`. + let mut t = loop {}; + e = &mut t; + + // `u` is inferred to have type `U` because it's used as `Ok(&mut + // u)` as the value returned from this branch. + let u; + + $crate::assert_size_eq!(t, u); + $crate::assert_align_gt_eq!(t, u); + + Ok(&mut u) + } else { + $crate::util::macro_util::try_transmute_mut::<_, _>(e) + } + }} +} + +/// Includes a file and safely transmutes it to a value of an arbitrary type. +/// +/// The file will be included as a byte array, `[u8; N]`, which will be +/// transmuted to another type, `T`. `T` is inferred from the calling context, +/// and must implement [`FromBytes`]. +/// +/// The file is located relative to the current file (similarly to how modules +/// are found). The provided path is interpreted in a platform-specific way at +/// compile time. So, for instance, an invocation with a Windows path containing +/// backslashes `\` would not compile correctly on Unix. +/// +/// `include_value!` is ignorant of byte order. For byte order-aware types, see +/// the [`byteorder`] module. +/// +/// [`FromBytes`]: crate::FromBytes +/// [`byteorder`]: crate::byteorder +/// +/// # Examples +/// +/// Assume there are two files in the same directory with the following +/// contents: +/// +/// File `data` (no trailing newline): +/// +/// ```text +/// abcd +/// ``` +/// +/// File `main.rs`: +/// +/// ```rust +/// use zerocopy::include_value; +/// # macro_rules! include_value { +/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) }; +/// # } +/// +/// fn main() { +/// let as_u32: u32 = include_value!("data"); +/// assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// let as_i32: i32 = include_value!("data"); +/// assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// } +/// ``` +/// +/// # Use in `const` contexts +/// +/// This macro can be invoked in `const` contexts. +#[doc(alias("include_bytes", "include_data", "include_type"))] +#[macro_export] +macro_rules! include_value { + ($file:expr $(,)?) => { + $crate::transmute!(*::core::include_bytes!($file)) + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! cryptocorrosion_derive_traits { + ( + #[repr($repr:ident)] + $(#[$attr:meta])* + $vis:vis struct $name:ident $(<$($tyvar:ident),*>)? + $( + ( + $($tuple_field_vis:vis $tuple_field_ty:ty),* + ); + )? + + $( + { + $($field_vis:vis $field_name:ident: $field_ty:ty,)* + } + )? + ) => { + $crate::cryptocorrosion_derive_traits!(@assert_allowed_struct_repr #[repr($repr)]); + + $(#[$attr])* + #[repr($repr)] + $vis struct $name $(<$($tyvar),*>)? + $( + ( + $($tuple_field_vis $tuple_field_ty),* + ); + )? + + $( + { + $($field_vis $field_name: $field_ty,)* + } + )? + + // SAFETY: See inline. + unsafe impl $(<$($tyvar),*>)? $crate::TryFromBytes for $name$(<$($tyvar),*>)? + where + $( + $($tuple_field_ty: $crate::FromBytes,)* + )? + + $( + $($field_ty: $crate::FromBytes,)* + )? + { + fn is_bit_valid(_c: $crate::Maybe<'_, Self, A>) -> bool + where + A: $crate::pointer::invariant::Reference + { + // SAFETY: This macro only accepts `#[repr(C)]` and + // `#[repr(transparent)]` structs, and this `impl` block + // requires all field types to be `FromBytes`. Thus, all + // initialized byte sequences constitutes valid instances of + // `Self`. + true + } + + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` and + // `#[repr(transparent)]` structs, and this `impl` block requires all + // field types to be `FromBytes`, which is a sub-trait of `FromZeros`. + unsafe impl $(<$($tyvar),*>)? $crate::FromZeros for $name$(<$($tyvar),*>)? + where + $( + $($tuple_field_ty: $crate::FromBytes,)* + )? + + $( + $($field_ty: $crate::FromBytes,)* + )? + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` and + // `#[repr(transparent)]` structs, and this `impl` block requires all + // field types to be `FromBytes`. + unsafe impl $(<$($tyvar),*>)? $crate::FromBytes for $name$(<$($tyvar),*>)? + where + $( + $($tuple_field_ty: $crate::FromBytes,)* + )? + + $( + $($field_ty: $crate::FromBytes,)* + )? + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` and + // `#[repr(transparent)]` structs, this `impl` block requires all field + // types to be `IntoBytes`, and a padding check is used to ensures that + // there are no padding bytes. + unsafe impl $(<$($tyvar),*>)? $crate::IntoBytes for $name$(<$($tyvar),*>)? + where + $( + $($tuple_field_ty: $crate::IntoBytes,)* + )? + + $( + $($field_ty: $crate::IntoBytes,)* + )? + + (): $crate::util::macro_util::PaddingFree< + Self, + { + $crate::cryptocorrosion_derive_traits!( + @struct_padding_check #[repr($repr)] + $(($($tuple_field_ty),*))? + $({$($field_ty),*})? + ) + }, + >, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` and + // `#[repr(transparent)]` structs, and this `impl` block requires all + // field types to be `Immutable`. + unsafe impl $(<$($tyvar),*>)? $crate::Immutable for $name$(<$($tyvar),*>)? + where + $( + $($tuple_field_ty: $crate::Immutable,)* + )? + + $( + $($field_ty: $crate::Immutable,)* + )? + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; + (@assert_allowed_struct_repr #[repr(transparent)]) => {}; + (@assert_allowed_struct_repr #[repr(C)]) => {}; + (@assert_allowed_struct_repr #[$_attr:meta]) => { + compile_error!("repr must be `#[repr(transparent)]` or `#[repr(C)]`"); + }; + ( + @struct_padding_check #[repr(transparent)] + $(($($tuple_field_ty:ty),*))? + $({$($field_ty:ty),*})? + ) => { + // SAFETY: `#[repr(transparent)]` structs cannot have the same layout as + // their single non-zero-sized field, and so cannot have any padding + // outside of that field. + 0 + }; + ( + @struct_padding_check #[repr(C)] + $(($($tuple_field_ty:ty),*))? + $({$($field_ty:ty),*})? + ) => { + $crate::struct_padding!( + Self, + [ + $($($tuple_field_ty),*)? + $($($field_ty),*)? + ] + ) + }; + ( + #[repr(C)] + $(#[$attr:meta])* + $vis:vis union $name:ident { + $( + $field_name:ident: $field_ty:ty, + )* + } + ) => { + $(#[$attr])* + #[repr(C)] + $vis union $name { + $( + $field_name: $field_ty, + )* + } + + // SAFETY: See inline. + unsafe impl $crate::TryFromBytes for $name + where + $( + $field_ty: $crate::FromBytes, + )* + { + fn is_bit_valid(_c: $crate::Maybe<'_, Self, A>) -> bool + where + A: $crate::pointer::invariant::Reference + { + // SAFETY: This macro only accepts `#[repr(C)]` unions, and this + // `impl` block requires all field types to be `FromBytes`. + // Thus, all initialized byte sequences constitutes valid + // instances of `Self`. + true + } + + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` + // block requires all field types to be `FromBytes`, which is a + // sub-trait of `FromZeros`. + unsafe impl $crate::FromZeros for $name + where + $( + $field_ty: $crate::FromBytes, + )* + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` + // block requires all field types to be `FromBytes`. + unsafe impl $crate::FromBytes for $name + where + $( + $field_ty: $crate::FromBytes, + )* + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` unions, this `impl` + // block requires all field types to be `IntoBytes`, and a padding check + // is used to ensures that there are no padding bytes before or after + // any field. + unsafe impl $crate::IntoBytes for $name + where + $( + $field_ty: $crate::IntoBytes, + )* + (): $crate::util::macro_util::PaddingFree< + Self, + { + $crate::union_padding!( + Self, + [$($field_ty),*] + ) + }, + >, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` + // block requires all field types to be `Immutable`. + unsafe impl $crate::Immutable for $name + where + $( + $field_ty: $crate::Immutable, + )* + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + }; +} + +#[cfg(test)] +mod tests { + use crate::{ + byteorder::native_endian::{U16, U32}, + util::testutil::*, + *, + }; + + #[derive(KnownLayout, Immutable, FromBytes, IntoBytes, PartialEq, Debug)] + #[repr(C)] + struct SliceDst { + a: T, + b: [U], + } + + #[test] + fn test_transmute() { + // Test that memory is transmuted as expected. + let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; + let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; + let x: [[u8; 2]; 4] = transmute!(array_of_u8s); + assert_eq!(x, array_of_arrays); + let x: [u8; 8] = transmute!(array_of_arrays); + assert_eq!(x, array_of_u8s); + + // Test that memory is transmuted as expected when shrinking. + let x: [[u8; 2]; 3] = transmute!(#![allow(shrink)] array_of_u8s); + assert_eq!(x, [[0u8, 1], [2, 3], [4, 5]]); + + // Test that the source expression's value is forgotten rather than + // dropped. + #[derive(IntoBytes)] + #[repr(transparent)] + struct PanicOnDrop(()); + impl Drop for PanicOnDrop { + fn drop(&mut self) { + panic!("PanicOnDrop::drop"); + } + } + #[allow(clippy::let_unit_value)] + let _: () = transmute!(PanicOnDrop(())); + #[allow(clippy::let_unit_value)] + let _: () = transmute!(#![allow(shrink)] PanicOnDrop(())); + + // Test that `transmute!` is legal in a const context. + const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7]; + const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]]; + const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S); + assert_eq!(X, ARRAY_OF_ARRAYS); + const X_SHRINK: [[u8; 2]; 3] = transmute!(#![allow(shrink)] ARRAY_OF_U8S); + assert_eq!(X_SHRINK, [[0u8, 1], [2, 3], [4, 5]]); + + // Test that `transmute!` works with `!Immutable` types. + let x: usize = transmute!(UnsafeCell::new(1usize)); + assert_eq!(x, 1); + let x: UnsafeCell = transmute!(1usize); + assert_eq!(x.into_inner(), 1); + let x: UnsafeCell = transmute!(UnsafeCell::new(1usize)); + assert_eq!(x.into_inner(), 1); + } + + // A `Sized` type which doesn't implement `KnownLayout` (it is "not + // `KnownLayout`", or `Nkl`). + // + // This permits us to test that `transmute_ref!` and `transmute_mut!` work + // for types which are `Sized + !KnownLayout`. When we added support for + // slice DSTs in #1924, this new support relied on `KnownLayout`, but we + // need to make sure to remain backwards-compatible with code which uses + // these macros with types which are `!KnownLayout`. + #[derive(FromBytes, IntoBytes, Immutable, PartialEq, Eq, Debug)] + #[repr(transparent)] + struct Nkl(T); + + #[test] + fn test_transmute_ref() { + // Test that memory is transmuted as expected. + let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; + let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; + let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s); + assert_eq!(*x, array_of_arrays); + let x: &[u8; 8] = transmute_ref!(&array_of_arrays); + assert_eq!(*x, array_of_u8s); + + // Test that `transmute_ref!` is legal in a const context. + const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7]; + const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]]; + #[allow(clippy::redundant_static_lifetimes)] + const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S); + assert_eq!(*X, ARRAY_OF_ARRAYS); + + // Before 1.61.0, we can't define the `const fn transmute_ref` function + // that we do on and after 1.61.0. + #[cfg(not(zerocopy_generic_bounds_in_const_fn_1_61_0))] + { + // Test that `transmute_ref!` supports non-`KnownLayout` `Sized` types. + const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]); + const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]); + const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref!(&ARRAY_OF_NKL_U8S); + assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS); + } + + #[cfg(zerocopy_generic_bounds_in_const_fn_1_61_0)] + { + // Call through a generic function to make sure our autoref + // specialization trick works even when types are generic. + const fn transmute_ref(t: &T) -> &U + where + T: IntoBytes + Immutable, + U: FromBytes + Immutable, + { + transmute_ref!(t) + } + + // Test that `transmute_ref!` supports non-`KnownLayout` `Sized` types. + const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]); + const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]); + const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref(&ARRAY_OF_NKL_U8S); + assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS); + } + + // Test that `transmute_ref!` works on slice DSTs in and that memory is + // transmuted as expected. + let slice_dst_of_u8s = + SliceDst::::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap(); + let slice_dst_of_u16s = + SliceDst::::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap(); + let x: &SliceDst = transmute_ref!(slice_dst_of_u8s); + assert_eq!(x, slice_dst_of_u16s); + + let slice_dst_of_u8s = + SliceDst::::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap(); + let x: &[u8] = transmute_ref!(slice_dst_of_u8s); + assert_eq!(x, [0, 1, 2, 3, 4, 5]); + + let x: &[u8] = transmute_ref!(slice_dst_of_u16s); + assert_eq!(x, [0, 1, 2, 3, 4, 5]); + + let x: &[U16] = transmute_ref!(slice_dst_of_u16s); + let slice_of_u16s: &[U16] = <[U16]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap(); + assert_eq!(x, slice_of_u16s); + + // Test that transmuting from a type with larger trailing slice offset + // and larger trailing slice element works. + let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..]; + let slice_dst_big = SliceDst::::ref_from_bytes(bytes).unwrap(); + let slice_dst_small = SliceDst::::ref_from_bytes(bytes).unwrap(); + let x: &SliceDst = transmute_ref!(slice_dst_big); + assert_eq!(x, slice_dst_small); + + // Test that it's legal to transmute a reference while shrinking the + // lifetime (note that `X` has the lifetime `'static`). + let x: &[u8; 8] = transmute_ref!(X); + assert_eq!(*x, ARRAY_OF_U8S); + + // Test that `transmute_ref!` supports decreasing alignment. + let u = AU64(0); + let array = [0, 0, 0, 0, 0, 0, 0, 0]; + let x: &[u8; 8] = transmute_ref!(&u); + assert_eq!(*x, array); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: &u8 = transmute_ref!(&mut x); + assert_eq!(*y, 0); + } + + #[test] + fn test_try_transmute() { + // Test that memory is transmuted with `try_transmute` as expected. + let array_of_bools = [false, true, false, true, false, true, false, true]; + let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]]; + let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools); + assert_eq!(x, Ok(array_of_arrays)); + let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays); + assert_eq!(x, Ok(array_of_bools)); + + // Test that `try_transmute!` works with `!Immutable` types. + let x: Result = try_transmute!(UnsafeCell::new(1usize)); + assert_eq!(x.unwrap(), 1); + let x: Result, _> = try_transmute!(1usize); + assert_eq!(x.unwrap().into_inner(), 1); + let x: Result, _> = try_transmute!(UnsafeCell::new(1usize)); + assert_eq!(x.unwrap().into_inner(), 1); + + #[derive(FromBytes, IntoBytes, Debug, PartialEq)] + #[repr(transparent)] + struct PanicOnDrop(T); + + impl Drop for PanicOnDrop { + fn drop(&mut self) { + panic!("PanicOnDrop dropped"); + } + } + + // Since `try_transmute!` semantically moves its argument on failure, + // the `PanicOnDrop` is not dropped, and thus this shouldn't panic. + let x: Result = try_transmute!(PanicOnDrop(1usize)); + assert_eq!(x, Ok(1)); + + // Since `try_transmute!` semantically returns ownership of its argument + // on failure, the `PanicOnDrop` is returned rather than dropped, and + // thus this shouldn't panic. + let y: Result = try_transmute!(PanicOnDrop(2u8)); + // We have to use `map_err` instead of comparing against + // `Err(PanicOnDrop(2u8))` because the latter would create and then drop + // its `PanicOnDrop` temporary, which would cause a panic. + assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8)); + mem::forget(y); + } + + #[test] + fn test_try_transmute_ref() { + // Test that memory is transmuted with `try_transmute_ref` as expected. + let array_of_bools = &[false, true, false, true, false, true, false, true]; + let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]]; + let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools); + assert_eq!(x, Ok(array_of_arrays)); + let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays); + assert_eq!(x, Ok(array_of_bools)); + + // Test that it's legal to transmute a reference while shrinking the + // lifetime. + { + let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools); + assert_eq!(x, Ok(array_of_arrays)); + } + + // Test that `try_transmute_ref!` supports decreasing alignment. + let u = AU64(0); + let array = [0u8, 0, 0, 0, 0, 0, 0, 0]; + let x: Result<&[u8; 8], _> = try_transmute_ref!(&u); + assert_eq!(x, Ok(&array)); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: Result<&u8, _> = try_transmute_ref!(&mut x); + assert_eq!(y, Ok(&0)); + } + + #[test] + fn test_try_transmute_mut() { + // Test that memory is transmuted with `try_transmute_mut` as expected. + let array_of_u8s = &mut [0u8, 1, 0, 1, 0, 1, 0, 1]; + let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; + let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_u8s); + assert_eq!(x, Ok(array_of_arrays)); + + let array_of_bools = &mut [false, true, false, true, false, true, false, true]; + let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; + let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays); + assert_eq!(x, Ok(array_of_bools)); + + // Test that it's legal to transmute a reference while shrinking the + // lifetime. + let array_of_bools = &mut [false, true, false, true, false, true, false, true]; + let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; + { + let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays); + assert_eq!(x, Ok(array_of_bools)); + } + + // Test that `try_transmute_mut!` supports decreasing alignment. + let u = &mut AU64(0); + let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0]; + let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u); + assert_eq!(x, Ok(array)); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: Result<&mut u8, _> = try_transmute_mut!(&mut x); + assert_eq!(y, Ok(&mut 0)); + } + + #[test] + fn test_transmute_mut() { + // Test that memory is transmuted as expected. + let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; + let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; + let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s); + assert_eq!(*x, array_of_arrays); + let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); + assert_eq!(*x, array_of_u8s); + + { + // Test that it's legal to transmute a reference while shrinking the + // lifetime. + let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); + assert_eq!(*x, array_of_u8s); + } + + // Test that `transmute_mut!` supports non-`KnownLayout` types. + let mut array_of_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]); + let mut array_of_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]); + let x: &mut Nkl<[[u8; 2]; 4]> = transmute_mut!(&mut array_of_u8s); + assert_eq!(*x, array_of_arrays); + let x: &mut Nkl<[u8; 8]> = transmute_mut!(&mut array_of_arrays); + assert_eq!(*x, array_of_u8s); + + // Test that `transmute_mut!` supports decreasing alignment. + let mut u = AU64(0); + let array = [0, 0, 0, 0, 0, 0, 0, 0]; + let x: &[u8; 8] = transmute_mut!(&mut u); + assert_eq!(*x, array); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: &u8 = transmute_mut!(&mut x); + assert_eq!(*y, 0); + + // Test that `transmute_mut!` works on slice DSTs in and that memory is + // transmuted as expected. + let mut bytes = [0, 1, 2, 3, 4, 5, 6]; + let slice_dst_of_u8s = SliceDst::::mut_from_bytes(&mut bytes[..]).unwrap(); + let mut bytes = [0, 1, 2, 3, 4, 5, 6]; + let slice_dst_of_u16s = SliceDst::::mut_from_bytes(&mut bytes[..]).unwrap(); + let x: &mut SliceDst = transmute_mut!(slice_dst_of_u8s); + assert_eq!(x, slice_dst_of_u16s); + + // Test that `transmute_mut!` works on slices that memory is transmuted + // as expected. + let array_of_u16s: &mut [u16] = &mut [0u16, 1, 2]; + let array_of_i16s: &mut [i16] = &mut [0i16, 1, 2]; + let x: &mut [i16] = transmute_mut!(array_of_u16s); + assert_eq!(x, array_of_i16s); + + // Test that transmuting from a type with larger trailing slice offset + // and larger trailing slice element works. + let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7]; + let slice_dst_big = SliceDst::::mut_from_bytes(&mut bytes[..]).unwrap(); + let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7]; + let slice_dst_small = SliceDst::::mut_from_bytes(&mut bytes[..]).unwrap(); + let x: &mut SliceDst = transmute_mut!(slice_dst_big); + assert_eq!(x, slice_dst_small); + } + + #[test] + fn test_macros_evaluate_args_once() { + let mut ctr = 0; + #[allow(clippy::useless_transmute)] + let _: usize = transmute!({ + ctr += 1; + 0usize + }); + assert_eq!(ctr, 1); + + let mut ctr = 0; + let _: &usize = transmute_ref!({ + ctr += 1; + &0usize + }); + assert_eq!(ctr, 1); + + let mut ctr: usize = 0; + let _: &mut usize = transmute_mut!({ + ctr += 1; + &mut ctr + }); + assert_eq!(ctr, 1); + + let mut ctr = 0; + #[allow(clippy::useless_transmute)] + let _: usize = try_transmute!({ + ctr += 1; + 0usize + }) + .unwrap(); + assert_eq!(ctr, 1); + } + + #[test] + fn test_include_value() { + const AS_U32: u32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + const AS_I32: i32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + } + + #[test] + #[allow(non_camel_case_types, unreachable_pub, dead_code)] + fn test_cryptocorrosion_derive_traits() { + // Test the set of invocations added in + // https://github.com/cryptocorrosion/cryptocorrosion/pull/85 + + fn assert_impls() {} + + cryptocorrosion_derive_traits! { + #[repr(C)] + #[derive(Clone, Copy)] + pub union vec128_storage { + d: [u32; 4], + q: [u64; 2], + } + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u32x4_generic([u32; 4]); + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u64x2_generic([u64; 2]); + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct u128x1_generic([u128; 1]); + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Default)] + #[allow(non_camel_case_types)] + pub struct x2(pub [W; 2], PhantomData); + } + + enum NotZerocopy {} + assert_impls::>(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone, Default)] + #[allow(non_camel_case_types)] + pub struct x4(pub [W; 4]); + } + + assert_impls::>(); + + #[cfg(feature = "simd")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + #[cfg(target_arch = "x86")] + use core::arch::x86::{__m128i, __m256i}; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64::{__m128i, __m256i}; + + cryptocorrosion_derive_traits! { + #[repr(C)] + #[derive(Copy, Clone)] + pub struct X4(__m128i, __m128i, __m128i, __m128i); + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(C)] + /// Generic wrapper for unparameterized storage of any of the possible impls. + /// Converting into and out of this type should be essentially free, although it may be more + /// aligned than a particular impl requires. + #[allow(non_camel_case_types)] + #[derive(Copy, Clone)] + pub union vec128_storage { + u32x4: [u32; 4], + u64x2: [u64; 2], + u128x1: [u128; 1], + sse2: __m128i, + } + } + + assert_impls::(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[allow(non_camel_case_types)] + #[derive(Copy, Clone)] + pub struct vec { + x: __m128i, + s3: PhantomData, + s4: PhantomData, + ni: PhantomData, + } + } + + assert_impls::>(); + + cryptocorrosion_derive_traits! { + #[repr(transparent)] + #[derive(Copy, Clone)] + pub struct u32x4x2_avx2 { + x: __m256i, + ni: PhantomData, + } + } + + assert_impls::>(); + } + + // Make sure that our derive works for `#[repr(C)]` structs even though + // cryptocorrosion doesn't currently have any. + cryptocorrosion_derive_traits! { + #[repr(C)] + #[derive(Copy, Clone, Debug, PartialEq)] + pub struct ReprC(u8, u8, u16); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/inner.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/inner.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/inner.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/inner.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,747 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{marker::PhantomData, mem, ops::Range, ptr::NonNull}; + +pub use _def::PtrInner; + +#[allow(unused_imports)] +use crate::util::polyfills::NumExt as _; +use crate::{ + layout::{CastType, MetadataCastError}, + util::AsAddress, + AlignmentError, CastError, KnownLayout, MetadataOf, SizeError, SplitAt, +}; + +mod _def { + use super::*; + /// The inner pointer stored inside a [`Ptr`][crate::Ptr]. + /// + /// `PtrInner<'a, T>` is [covariant] in `'a` and invariant in `T`. + /// + /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html + #[allow(missing_debug_implementations)] + pub struct PtrInner<'a, T> + where + T: ?Sized, + { + /// # Invariants + /// + /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid + /// provenance for its referent, which is entirely contained in some + /// Rust allocation, `A`. + /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live + /// for at least `'a`. + /// + /// # Postconditions + /// + /// By virtue of these invariants, code may assume the following, which + /// are logical implications of the invariants: + /// - `ptr`'s referent is not larger than `isize::MAX` bytes \[1\] + /// - `ptr`'s referent does not wrap around the address space \[1\] + /// + /// \[1\] Per : + /// + /// For any allocated object with `base` address, `size`, and a set of + /// `addresses`, the following are guaranteed: + /// ... + /// - `size <= isize::MAX` + /// + /// As a consequence of these guarantees, given any address `a` within + /// the set of addresses of an allocated object: + /// ... + /// - It is guaranteed that, given `o = a - base` (i.e., the offset of + /// `a` within the allocated object), `base + o` will not wrap around + /// the address space (in other words, will not overflow `usize`) + ptr: NonNull, + // SAFETY: `&'a UnsafeCell` is covariant in `'a` and invariant in `T` + // [1]. We use this construction rather than the equivalent `&mut T`, + // because our MSRV of 1.65 prohibits `&mut` types in const contexts. + // + // [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance + _marker: PhantomData<&'a core::cell::UnsafeCell>, + } + + impl<'a, T: 'a + ?Sized> Copy for PtrInner<'a, T> {} + impl<'a, T: 'a + ?Sized> Clone for PtrInner<'a, T> { + #[inline(always)] + fn clone(&self) -> PtrInner<'a, T> { + // SAFETY: None of the invariants on `ptr` are affected by having + // multiple copies of a `PtrInner`. + *self + } + } + + impl<'a, T: 'a + ?Sized> PtrInner<'a, T> { + /// Constructs a `Ptr` from a [`NonNull`]. + /// + /// # Safety + /// + /// The caller promises that: + /// + /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid + /// provenance for its referent, which is entirely contained in some + /// Rust allocation, `A`. + /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live + /// for at least `'a`. + #[inline(always)] + #[must_use] + pub const unsafe fn new(ptr: NonNull) -> PtrInner<'a, T> { + // SAFETY: The caller has promised to satisfy all safety invariants + // of `PtrInner`. + Self { ptr, _marker: PhantomData } + } + + /// Converts this `PtrInner` to a [`NonNull`]. + /// + /// Note that this method does not consume `self`. The caller should + /// watch out for `unsafe` code which uses the returned `NonNull` in a + /// way that violates the safety invariants of `self`. + #[inline(always)] + #[must_use] + pub const fn as_non_null(&self) -> NonNull { + self.ptr + } + } +} + +impl<'a, T: ?Sized> PtrInner<'a, T> { + /// Constructs a `PtrInner` from a reference. + #[inline] + pub(crate) fn from_ref(ptr: &'a T) -> Self { + let ptr = NonNull::from(ptr); + // SAFETY: + // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on + // `&'a T` [1], has valid provenance for its referent, which is + // entirely contained in some Rust allocation, `A`. + // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on + // `&'a T`, is guaranteed to live for at least `'a`. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: + // + // For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, + // when such values cross an API boundary, the following invariants + // must generally be upheld: + // ... + // - if `size_of_val(t) > 0`, then `t` is dereferenceable for + // `size_of_val(t)` many bytes + // + // If `t` points at address `a`, being “dereferenceable” for N bytes + // means that the memory range `[a, a + N)` is all contained within a + // single allocated object. + unsafe { Self::new(ptr) } + } + + /// Constructs a `PtrInner` from a mutable reference. + #[inline] + pub(crate) fn from_mut(ptr: &'a mut T) -> Self { + let ptr = NonNull::from(ptr); + // SAFETY: + // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on + // `&'a mut T` [1], has valid provenance for its referent, which is + // entirely contained in some Rust allocation, `A`. + // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on + // `&'a mut T`, is guaranteed to live for at least `'a`. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: + // + // For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, + // when such values cross an API boundary, the following invariants + // must generally be upheld: + // ... + // - if `size_of_val(t) > 0`, then `t` is dereferenceable for + // `size_of_val(t)` many bytes + // + // If `t` points at address `a`, being “dereferenceable” for N bytes + // means that the memory range `[a, a + N)` is all contained within a + // single allocated object. + unsafe { Self::new(ptr) } + } + + #[must_use] + #[inline(always)] + pub fn cast_sized(self) -> PtrInner<'a, U> + where + T: Sized, + { + static_assert!(T, U => mem::size_of::() >= mem::size_of::()); + // SAFETY: By the preceding assert, `U` is no larger than `T`, which is + // the size of `self`'s referent. + unsafe { self.cast() } + } + + /// # Safety + /// + /// `U` must not be larger than the size of `self`'s referent. + #[must_use] + #[inline(always)] + pub unsafe fn cast(self) -> PtrInner<'a, U> { + let ptr = self.as_non_null().cast::(); + + // SAFETY: The caller promises that `U` is no larger than `self`'s + // referent. Thus, `ptr` addresses a subset of the bytes addressed by + // `self`. + // + // 0. By invariant on `self`, if `self`'s referent is not zero sized, + // then `self` has valid provenance for its referent, which is + // entirely contained in some Rust allocation, `A`. Thus, the same + // holds of `ptr`. + // 1. By invariant on `self`, if `self`'s referent is not zero sized, + // then `A` is guaranteed to live for at least `'a`. + unsafe { PtrInner::new(ptr) } + } +} + +#[allow(clippy::needless_lifetimes)] +impl<'a, T> PtrInner<'a, T> +where + T: ?Sized + KnownLayout, +{ + /// Extracts the metadata of this `ptr`. + pub(crate) fn meta(self) -> MetadataOf { + let meta = T::pointer_to_metadata(self.as_non_null().as_ptr()); + // SAFETY: By invariant on `PtrInner`, `self.as_non_null()` addresses no + // more than `isize::MAX` bytes. + unsafe { MetadataOf::new_unchecked(meta) } + } + + /// Produces a `PtrInner` with the same address and provenance as `self` but + /// the given `meta`. + /// + /// # Safety + /// + /// The caller promises that if `self`'s referent is not zero sized, then + /// a pointer constructed from its address with the given `meta` metadata + /// will address a subset of the allocation pointed to by `self`. + #[inline] + pub(crate) unsafe fn with_meta(self, meta: T::PointerMetadata) -> Self + where + T: KnownLayout, + { + let raw = T::raw_from_ptr_len(self.as_non_null().cast(), meta); + + // SAFETY: + // + // Lemma 0: `raw` either addresses zero bytes, or addresses a subset of + // the allocation pointed to by `self` and has the same + // provenance as `self`. Proof: `raw` is constructed using + // provenance-preserving operations, and the caller has + // promised that, if `self`'s referent is not zero-sized, the + // resulting pointer addresses a subset of the allocation + // pointed to by `self`. + // + // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `ptr` is derived from some valid Rust allocation, + // `A`. + // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `ptr` has valid provenance for `A`. + // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `ptr` addresses a byte range which is entirely + // contained in `A`. + // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte + // range whose length fits in an `isize`. + // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte + // range which does not wrap around the address space. + // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `A` is guaranteed to live for at least `'a`. + unsafe { PtrInner::new(raw) } + } + + pub(crate) fn as_bytes(self) -> PtrInner<'a, [u8]> { + let ptr = self.as_non_null(); + let bytes = match T::size_of_val_raw(ptr) { + Some(bytes) => bytes, + // SAFETY: `KnownLayout::size_of_val_raw` promises to always + // return `Some` so long as the resulting size fits in a + // `usize`. By invariant on `PtrInner`, `self` refers to a range + // of bytes whose size fits in an `isize`, which implies that it + // also fits in a `usize`. + None => unsafe { core::hint::unreachable_unchecked() }, + }; + + let ptr = core::ptr::slice_from_raw_parts_mut(ptr.cast::().as_ptr(), bytes); + + // SAFETY: `ptr` has the same address as `ptr = self.as_non_null()`, + // which is non-null by construction. + let ptr = unsafe { NonNull::new_unchecked(ptr) }; + + // SAFETY: `ptr` points to `bytes` `u8`s starting at the same address as + // `self`'s referent. Since `bytes` is the length of `self`'s referent, + // `ptr` addresses the same byte range as `self`. Thus, by invariant on + // `self` (as a `PtrInner`): + // + // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid + // provenance for its referent, which is entirely contained in some + // Rust allocation, `A`. + // 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live + // for at least `'a`. + unsafe { PtrInner::new(ptr) } + } +} + +#[allow(clippy::needless_lifetimes)] +impl<'a, T> PtrInner<'a, T> +where + T: ?Sized + KnownLayout, +{ + /// Splits `T` in two. + /// + /// # Safety + /// + /// The caller promises that: + /// - `l_len.get() <= self.meta()`. + /// + /// ## (Non-)Overlap + /// + /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed that + /// `left` and `right` are contiguous and non-overlapping if + /// `l_len.padding_needed_for() == 0`. This is true for all `[T]`. + /// + /// If `l_len.padding_needed_for() != 0`, then the left pointer will overlap + /// the right pointer to satisfy `T`'s padding requirements. + pub(crate) unsafe fn split_at_unchecked( + self, + l_len: crate::util::MetadataOf, + ) -> (Self, PtrInner<'a, [T::Elem]>) + where + T: SplitAt, + { + let l_len = l_len.get(); + + // SAFETY: The caller promises that `l_len.get() <= self.meta()`. + // Trivially, `0 <= l_len`. + let left = unsafe { self.with_meta(l_len) }; + + let right = self.trailing_slice(); + // SAFETY: The caller promises that `l_len <= self.meta() = slf.meta()`. + // Trivially, `slf.meta() <= slf.meta()`. + let right = unsafe { right.slice_unchecked(l_len..self.meta().get()) }; + + // SAFETY: If `l_len.padding_needed_for() == 0`, then `left` and `right` + // are non-overlapping. Proof: `left` is constructed `slf` with `l_len` + // as its (exclusive) upper bound. If `l_len.padding_needed_for() == 0`, + // then `left` requires no trailing padding following its final element. + // Since `right` is constructed from `slf`'s trailing slice with `l_len` + // as its (inclusive) lower bound, no byte is referred to by both + // pointers. + // + // Conversely, `l_len.padding_needed_for() == N`, where `N + // > 0`, `left` requires `N` bytes of trailing padding following its + // final element. Since `right` is constructed from the trailing slice + // of `slf` with `l_len` as its (inclusive) lower bound, the first `N` + // bytes of `right` are aliased by `left`. + (left, right) + } + + /// Produces the trailing slice of `self`. + pub(crate) fn trailing_slice(self) -> PtrInner<'a, [T::Elem]> + where + T: SplitAt, + { + let offset = crate::trailing_slice_layout::().offset; + + let bytes = self.as_non_null().cast::().as_ptr(); + + // SAFETY: + // - By invariant on `T: KnownLayout`, `T::LAYOUT` describes `T`'s + // layout. `offset` is the offset of the trailing slice within `T`, + // which is by definition in-bounds or one byte past the end of any + // `T`, regardless of metadata. By invariant on `PtrInner`, `self` + // (and thus `bytes`) points to a byte range of size `<= isize::MAX`, + // and so `offset <= isize::MAX`. Since `size_of::() == 1`, + // `offset * size_of::() <= isize::MAX`. + // - If `offset > 0`, then by invariant on `PtrInner`, `self` (and thus + // `bytes`) points to a byte range entirely contained within the same + // allocated object as `self`. As explained above, this offset results + // in a pointer to or one byte past the end of this allocated object. + let bytes = unsafe { bytes.add(offset) }; + + // SAFETY: By the preceding safety argument, `bytes` is within or one + // byte past the end of the same allocated object as `self`, which + // ensures that it is non-null. + let bytes = unsafe { NonNull::new_unchecked(bytes) }; + + let ptr = KnownLayout::raw_from_ptr_len(bytes, self.meta().get()); + + // SAFETY: + // 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from + // some valid Rust allocation, `A`, because `ptr` is derived from + // the same allocated object as `self`. + // 1. If `ptr`'s referent is not zero sized, then `ptr` has valid + // provenance for `A` because `raw` is derived from the same + // allocated object as `self` via provenance-preserving operations. + // 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a byte + // range which is entirely contained in `A`, by previous safety proof + // on `bytes`. + // 3. `ptr` addresses a byte range whose length fits in an `isize`, by + // consequence of #2. + // 4. `ptr` addresses a byte range which does not wrap around the + // address space, by consequence of #2. + // 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to + // live for at least `'a`, because `ptr` is derived from `self`. + unsafe { PtrInner::new(ptr) } + } +} + +#[allow(clippy::needless_lifetimes)] +impl<'a, T> PtrInner<'a, [T]> { + /// Creates a pointer which addresses the given `range` of self. + /// + /// # Safety + /// + /// `range` is a valid range (`start <= end`) and `end <= self.meta()`. + pub(crate) unsafe fn slice_unchecked(self, range: Range) -> Self { + let base = self.as_non_null().cast::().as_ptr(); + + // SAFETY: The caller promises that `start <= end <= self.meta()`. By + // invariant, if `self`'s referent is not zero-sized, then `self` refers + // to a byte range which is contained within a single allocation, which + // is no more than `isize::MAX` bytes long, and which does not wrap + // around the address space. Thus, this pointer arithmetic remains + // in-bounds of the same allocation, and does not wrap around the + // address space. The offset (in bytes) does not overflow `isize`. + // + // If `self`'s referent is zero-sized, then these conditions are + // trivially satisfied. + let base = unsafe { base.add(range.start) }; + + // SAFETY: The caller promises that `start <= end`, and so this will not + // underflow. + #[allow(unstable_name_collisions)] + let len = unsafe { range.end.unchecked_sub(range.start) }; + + let ptr = core::ptr::slice_from_raw_parts_mut(base, len); + + // SAFETY: By invariant, `self`'s referent is either a ZST or lives + // entirely in an allocation. `ptr` points inside of or one byte past + // the end of that referent. Thus, in either case, `ptr` is non-null. + let ptr = unsafe { NonNull::new_unchecked(ptr) }; + + // SAFETY: + // + // Lemma 0: `ptr` addresses a subset of the bytes addressed by `self`, + // and has the same provenance. Proof: The caller guarantees + // that `start <= end <= self.meta()`. Thus, `base` is + // in-bounds of `self`, and `base + (end - start)` is also + // in-bounds of self. Finally, `ptr` is constructed using + // provenance-preserving operations. + // + // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `ptr` has valid provenance for its referent, + // which is entirely contained in some Rust allocation, `A`. + // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not + // zero sized, then `A` is guaranteed to live for at least `'a`. + unsafe { PtrInner::new(ptr) } + } + + /// Iteratively projects the elements `PtrInner` from `PtrInner<[T]>`. + pub(crate) fn iter(&self) -> impl Iterator> { + // FIXME(#429): Once `NonNull::cast` documents that it preserves + // provenance, cite those docs. + let base = self.as_non_null().cast::().as_ptr(); + (0..self.meta().get()).map(move |i| { + // FIXME(https://github.com/rust-lang/rust/issues/74265): Use + // `NonNull::get_unchecked_mut`. + + // SAFETY: If the following conditions are not satisfied + // `pointer::cast` may induce Undefined Behavior [1]: + // + // > - The computed offset, `count * size_of::()` bytes, must not + // > overflow `isize``. + // > - If the computed offset is non-zero, then `self` must be + // > derived from a pointer to some allocated object, and the + // > entire memory range between `self` and the result must be in + // > bounds of that allocated object. In particular, this range + // > must not “wrap around” the edge of the address space. + // + // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add + // + // We satisfy both of these conditions here: + // - By invariant on `Ptr`, `self` addresses a byte range whose + // length fits in an `isize`. Since `elem` is contained in `self`, + // the computed offset of `elem` must fit within `isize.` + // - If the computed offset is non-zero, then this means that the + // referent is not zero-sized. In this case, `base` points to an + // allocated object (by invariant on `self`). Thus: + // - By contract, `self.meta()` accurately reflects the number of + // elements in the slice. `i` is in bounds of `c.meta()` by + // construction, and so the result of this addition cannot + // overflow past the end of the allocation referred to by `c`. + // - By invariant on `Ptr`, `self` addresses a byte range which + // does not wrap around the address space. Since `elem` is + // contained in `self`, the computed offset of `elem` must wrap + // around the address space. + // + // FIXME(#429): Once `pointer::add` documents that it preserves + // provenance, cite those docs. + let elem = unsafe { base.add(i) }; + + // SAFETY: `elem` must not be null. `base` is constructed from a + // `NonNull` pointer, and the addition that produces `elem` must not + // overflow or wrap around, so `elem >= base > 0`. + // + // FIXME(#429): Once `NonNull::new_unchecked` documents that it + // preserves provenance, cite those docs. + let elem = unsafe { NonNull::new_unchecked(elem) }; + + // SAFETY: The safety invariants of `Ptr::new` (see definition) are + // satisfied: + // 0. If `elem`'s referent is not zero sized, then `elem` has valid + // provenance for its referent, because it derived from `self` + // using a series of provenance-preserving operations, and + // because `self` has valid provenance for its referent. By the + // same argument, `elem`'s referent is entirely contained within + // the same allocated object as `self`'s referent. + // 1. If `elem`'s referent is not zero sized, then the allocation of + // `elem` is guaranteed to live for at least `'a`, because `elem` + // is entirely contained in `self`, which lives for at least `'a` + // by invariant on `Ptr`. + unsafe { PtrInner::new(elem) } + }) + } +} + +impl<'a, T, const N: usize> PtrInner<'a, [T; N]> { + /// Casts this pointer-to-array into a slice. + /// + /// # Safety + /// + /// Callers may assume that the returned `PtrInner` references the same + /// address and length as `self`. + #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_slice(self) -> PtrInner<'a, [T]> { + let start = self.as_non_null().cast::().as_ptr(); + let slice = core::ptr::slice_from_raw_parts_mut(start, N); + // SAFETY: `slice` is not null, because it is derived from `start` + // which is non-null. + let slice = unsafe { NonNull::new_unchecked(slice) }; + // SAFETY: Lemma: In the following safety arguments, note that `slice` + // is derived from `self` in two steps: first, by casting `self: [T; N]` + // to `start: T`, then by constructing a pointer to a slice starting at + // `start` of length `N`. As a result, `slice` references exactly the + // same allocation as `self`, if any. + // + // 0. By the above lemma, if `slice`'s referent is not zero sized, then + // `slice` has the same referent as `self`. By invariant on `self`, + // this referent is entirely contained within some allocation, `A`. + // Because `slice` was constructed using provenance-preserving + // operations, it has provenance for its entire referent. + // 1. By the above lemma, if `slice`'s referent is not zero sized, then + // `A` is guaranteed to live for at least `'a`, because it is derived + // from the same allocation as `self`, which, by invariant on `Ptr`, + // lives for at least `'a`. + unsafe { PtrInner::new(slice) } + } +} + +impl<'a> PtrInner<'a, [u8]> { + /// Attempts to cast `self` to a `U` using the given cast type. + /// + /// If `U` is a slice DST and pointer metadata (`meta`) is provided, then + /// the cast will only succeed if it would produce an object with the given + /// metadata. + /// + /// Returns `None` if the resulting `U` would be invalidly-aligned, if no + /// `U` can fit in `self`, or if the provided pointer metadata describes an + /// invalid instance of `U`. On success, returns a pointer to the + /// largest-possible `U` which fits in `self`. + /// + /// # Safety + /// + /// The caller may assume that this implementation is correct, and may rely + /// on that assumption for the soundness of their code. In particular, the + /// caller may assume that, if `try_cast_into` returns `Some((ptr, + /// remainder))`, then `ptr` and `remainder` refer to non-overlapping byte + /// ranges within `self`, and that `ptr` and `remainder` entirely cover + /// `self`. Finally: + /// - If this is a prefix cast, `ptr` has the same address as `self`. + /// - If this is a suffix cast, `remainder` has the same address as `self`. + #[inline] + pub(crate) fn try_cast_into( + self, + cast_type: CastType, + meta: Option, + ) -> Result<(PtrInner<'a, U>, PtrInner<'a, [u8]>), CastError> + where + U: 'a + ?Sized + KnownLayout, + { + // PANICS: By invariant, the byte range addressed by + // `self.as_non_null()` does not wrap around the address space. This + // implies that the sum of the address (represented as a `usize`) and + // length do not overflow `usize`, as required by + // `validate_cast_and_convert_metadata`. Thus, this call to + // `validate_cast_and_convert_metadata` will only panic if `U` is a DST + // whose trailing slice element is zero-sized. + let maybe_metadata = MetadataOf::::validate_cast_and_convert_metadata( + AsAddress::addr(self.as_non_null().as_ptr()), + self.meta(), + cast_type, + meta, + ); + + let (elems, split_at) = match maybe_metadata { + Ok((elems, split_at)) => (elems, split_at), + Err(MetadataCastError::Alignment) => { + // SAFETY: Since `validate_cast_and_convert_metadata` returned + // an alignment error, `U` must have an alignment requirement + // greater than one. + let err = unsafe { AlignmentError::<_, U>::new_unchecked(self) }; + return Err(CastError::Alignment(err)); + } + Err(MetadataCastError::Size) => return Err(CastError::Size(SizeError::new(self))), + }; + + // SAFETY: `validate_cast_and_convert_metadata` promises to return + // `split_at <= self.meta()`. + // + // Lemma 0: `l_slice` and `r_slice` are non-overlapping. Proof: By + // contract on `PtrInner::split_at_unchecked`, the produced `PtrInner`s + // are always non-overlapping if `self` is a `[T]`; here it is a `[u8]`. + let (l_slice, r_slice) = unsafe { self.split_at_unchecked(split_at) }; + + let (target, remainder) = match cast_type { + CastType::Prefix => (l_slice, r_slice), + CastType::Suffix => (r_slice, l_slice), + }; + + let base = target.as_non_null().cast::(); + + let ptr = U::raw_from_ptr_len(base, elems.get()); + + // SAFETY: + // 0. By invariant, if `target`'s referent is not zero sized, then + // `target` has provenance valid for some Rust allocation, `A`. + // Because `ptr` is derived from `target` via provenance-preserving + // operations, `ptr` will also have provenance valid for its entire + // referent. + // 1. `validate_cast_and_convert_metadata` promises that the object + // described by `elems` and `split_at` lives at a byte range which is + // a subset of the input byte range. Thus, by invariant, if + // `target`'s referent is not zero sized, then `target` refers to an + // allocation which is guaranteed to live for at least `'a`, and thus + // so does `ptr`. + Ok((unsafe { PtrInner::new(ptr) }, remainder)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::*; + + #[test] + fn test_meta() { + let arr = [1; 16]; + let dst = <[u8]>::ref_from_bytes(&arr[..]).unwrap(); + let ptr = PtrInner::from_ref(dst); + assert_eq!(ptr.meta().get(), 16); + + // SAFETY: 8 is less than 16 + let ptr = unsafe { ptr.with_meta(8) }; + + assert_eq!(ptr.meta().get(), 8); + } + + #[test] + fn test_split_at() { + fn test_split_at() { + #[derive(FromBytes, KnownLayout, SplitAt, Immutable)] + #[repr(C)] + struct SliceDst { + prefix: [u8; OFFSET], + trailing: [u8], + } + + let n: usize = BUFFER_SIZE - OFFSET; + let arr = [1; BUFFER_SIZE]; + let dst = SliceDst::::ref_from_bytes(&arr[..]).unwrap(); + let ptr = PtrInner::from_ref(dst); + for i in 0..=n { + assert_eq!(ptr.meta().get(), n); + // SAFETY: `i` is in bounds by construction. + let i = unsafe { MetadataOf::new_unchecked(i) }; + // SAFETY: `i` is in bounds by construction. + let (l, r) = unsafe { ptr.split_at_unchecked(i) }; + // SAFETY: Points to a valid value by construction. + #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] + // Clippy false positive + let l_sum: usize = l + .trailing_slice() + .iter() + .map(|ptr| unsafe { core::ptr::read_unaligned(ptr.as_non_null().as_ptr()) } + as usize) + .sum(); + // SAFETY: Points to a valid value by construction. + #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] + // Clippy false positive + let r_sum: usize = r + .iter() + .map(|ptr| unsafe { core::ptr::read_unaligned(ptr.as_non_null().as_ptr()) } + as usize) + .sum(); + assert_eq!(l_sum, i.get()); + assert_eq!(r_sum, n - i.get()); + assert_eq!(l_sum + r_sum, n); + } + } + + test_split_at::<0, 16>(); + test_split_at::<1, 17>(); + test_split_at::<2, 18>(); + } + + #[test] + fn test_trailing_slice() { + fn test_trailing_slice() { + #[derive(FromBytes, KnownLayout, SplitAt, Immutable)] + #[repr(C)] + struct SliceDst { + prefix: [u8; OFFSET], + trailing: [u8], + } + + let n: usize = BUFFER_SIZE - OFFSET; + let arr = [1; BUFFER_SIZE]; + let dst = SliceDst::::ref_from_bytes(&arr[..]).unwrap(); + let ptr = PtrInner::from_ref(dst); + + assert_eq!(ptr.meta().get(), n); + let trailing = ptr.trailing_slice(); + assert_eq!(trailing.meta().get(), n); + + assert_eq!( + // SAFETY: We assume this to be sound for the sake of this test, + // which will fail, here, in miri, if the safety precondition of + // `offset_of` is not satisfied. + unsafe { + #[allow(clippy::as_conversions)] + let offset = (trailing.as_non_null().as_ptr() as *mut u8) + .offset_from(ptr.as_non_null().as_ptr() as *mut _); + offset + }, + isize::try_from(OFFSET).unwrap(), + ); + + // SAFETY: Points to a valid value by construction. + #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] + // Clippy false positive + let trailing: usize = + trailing + .iter() + .map(|ptr| unsafe { core::ptr::read_unaligned(ptr.as_non_null().as_ptr()) } + as usize) + .sum(); + + assert_eq!(trailing, n); + } + + test_trailing_slice::<0, 16>(); + test_trailing_slice::<1, 17>(); + test_trailing_slice::<2, 18>(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/invariant.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/invariant.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/invariant.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/invariant.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,253 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#![allow(missing_copy_implementations, missing_debug_implementations)] + +//! The parameterized invariants of a [`Ptr`][super::Ptr]. +//! +//! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`]) +//! triples implementing the [`Invariants`] trait. + +/// The invariants of a [`Ptr`][super::Ptr]. +pub trait Invariants: Sealed { + type Aliasing: Aliasing; + type Alignment: Alignment; + type Validity: Validity; +} + +impl Invariants for (A, AA, V) { + type Aliasing = A; + type Alignment = AA; + type Validity = V; +} + +/// The aliasing invariant of a [`Ptr`][super::Ptr]. +/// +/// All aliasing invariants must permit reading from the bytes of a pointer's +/// referent which are not covered by [`UnsafeCell`]s. +/// +/// [`UnsafeCell`]: core::cell::UnsafeCell +pub trait Aliasing: Sealed { + /// Is `Self` [`Exclusive`]? + #[doc(hidden)] + const IS_EXCLUSIVE: bool; +} + +/// The alignment invariant of a [`Ptr`][super::Ptr]. +pub trait Alignment: Sealed {} + +/// The validity invariant of a [`Ptr`][super::Ptr]. +/// +/// # Safety +/// +/// In this section, we will use `Ptr` as a shorthand for `Ptr>` for brevity. +/// +/// Each `V: Validity` defines a set of bit values which may appear in the +/// referent of a `Ptr`, denoted `S(T, V)`. Each `V: Validity`, in its +/// documentation, provides a definition of `S(T, V)` which must be valid for +/// all `T: ?Sized`. Any `V: Validity` must guarantee that this set is only a +/// function of the *bit validity* of the referent type, `T`, and not of any +/// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U` +/// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`. +/// +/// It is guaranteed that the referent of any `ptr: Ptr` is a member of +/// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for +/// any existing `Ptr`s or any `Ptr`s that that code creates. +/// +/// An important implication of this guarantee is that it restricts what +/// transmutes are sound, where "transmute" is used in this context to refer to +/// changing the referent type or validity invariant of a `Ptr`, as either +/// change may change the set of bit values permitted to appear in the referent. +/// In particular, the following are necessary (but not sufficient) conditions +/// in order for a transmute from `src: Ptr` to `dst: Ptr` to be +/// sound: +/// - If `S(T, V) = S(U, W)`, then no restrictions apply; otherwise, +/// - If `dst` permits mutation of its referent (e.g. via `Exclusive` aliasing +/// or interior mutation under `Shared` aliasing), then it must hold that +/// `S(T, V) ⊇ S(U, W)` - in other words, the transmute must not expand the +/// set of allowed referent bit patterns. A violation of this requirement +/// would permit using `dst` to write `x` where `x ∈ S(U, W)` but `x ∉ S(T, +/// V)`, which would violate the guarantee that `src`'s referent may only +/// contain values in `S(T, V)`. +/// - If the referent may be mutated without going through `dst` while `dst` is +/// live (e.g. via interior mutation on a `Shared`-aliased `Ptr` or `&` +/// reference), then it must hold that `S(T, V) ⊆ S(U, W)` - in other words, +/// the transmute must not shrink the set of allowed referent bit patterns. A +/// violation of this requirement would permit using `src` or another +/// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where +/// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that +/// `dst`'s referent may only contain values in `S(U, W)`. +pub unsafe trait Validity: Sealed {} + +/// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`]. +/// +/// # Safety +/// +/// Given `A: Reference`, callers may assume that either `A = Shared` or `A = +/// Exclusive`. +pub trait Reference: Aliasing + Sealed {} + +/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`. +/// +/// The referent of a shared-aliased `Ptr` may be concurrently referenced by any +/// number of shared-aliased `Ptr` or `&T` references, or by any number of +/// `Ptr` or `&U` references as permitted by `T`'s library safety invariants, +/// and may not be concurrently referenced by any exclusively-aliased `Ptr`s or +/// `&mut` references. The referent must not be mutated, except via +/// [`UnsafeCell`]s, and only when permitted by `T`'s library safety invariants. +/// +/// [`UnsafeCell`]: core::cell::UnsafeCell +pub enum Shared {} +impl Aliasing for Shared { + const IS_EXCLUSIVE: bool = false; +} +impl Reference for Shared {} + +/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`. +/// +/// The referent of an exclusively-aliased `Ptr` may not be concurrently +/// referenced by any other `Ptr`s or references, and may not be accessed (read +/// or written) other than via this `Ptr`. +pub enum Exclusive {} +impl Aliasing for Exclusive { + const IS_EXCLUSIVE: bool = true; +} +impl Reference for Exclusive {} + +/// It is unknown whether the pointer is aligned. +pub enum Unaligned {} + +impl Alignment for Unaligned {} + +/// The referent is aligned: for `Ptr`, the referent's address is a multiple +/// of the `T`'s alignment. +pub enum Aligned {} +impl Alignment for Aligned {} + +/// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized +/// bytes. +pub enum Uninit {} +// SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a +// function of any property of `T` other than its bit validity (in fact, it's +// not even a property of `T`'s bit validity, but this is more than we are +// required to uphold). +unsafe impl Validity for Uninit {} + +/// The byte ranges initialized in `T` are also initialized in the referent of a +/// `Ptr`. +/// +/// Formally: uninitialized bytes may only be present in `Ptr`'s referent +/// where they are guaranteed to be present in `T`. This is a dynamic property: +/// if, at a particular byte offset, a valid enum discriminant is set, the +/// subsequent bytes may only have uninitialized bytes as specified by the +/// corresponding enum. +/// +/// Formally, given `len = size_of_val_raw(ptr)`, at every byte offset, `b`, in +/// the range `[0, len)`: +/// - If, in any instance `t: T` of length `len`, the byte at offset `b` in `t` +/// is initialized, then the byte at offset `b` within `*ptr` must be +/// initialized. +/// - Let `c` be the contents of the byte range `[0, b)` in `*ptr`. Let `S` be +/// the subset of valid instances of `T` of length `len` which contain `c` in +/// the offset range `[0, b)`. If, in any instance of `t: T` in `S`, the byte +/// at offset `b` in `t` is initialized, then the byte at offset `b` in `*ptr` +/// must be initialized. +/// +/// Pragmatically, this means that if `*ptr` is guaranteed to contain an enum +/// type at a particular offset, and the enum discriminant stored in `*ptr` +/// corresponds to a valid variant of that enum type, then it is guaranteed +/// that the appropriate bytes of `*ptr` are initialized as defined by that +/// variant's bit validity (although note that the variant may contain another +/// enum type, in which case the same rules apply depending on the state of +/// its discriminant, and so on recursively). +pub enum AsInitialized {} +// SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and +// is not a function of any property of `T` other than its bit validity. +unsafe impl Validity for AsInitialized {} + +/// The byte ranges in the referent are fully initialized. In other words, if +/// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`. +pub enum Initialized {} +// SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is +// not a function of any property of `T` other than its bit validity (in fact, +// it's not even a property of `T`'s bit validity, but this is more than we are +// required to uphold). +unsafe impl Validity for Initialized {} + +/// The referent of a `Ptr` is valid for `T`, upholding bit validity and any +/// library safety invariants. +pub enum Valid {} +// SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a +// function of any property of `T` other than its bit validity. +unsafe impl Validity for Valid {} + +/// # Safety +/// +/// `DT: CastableFrom` is sound if `SV = DV = Uninit` or `SV = DV = +/// Initialized`. +pub unsafe trait CastableFrom {} + +// SAFETY: `SV = DV = Uninit`. +unsafe impl CastableFrom for DT {} +// SAFETY: `SV = DV = Initialized`. +unsafe impl CastableFrom for DT {} + +/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations. +/// +/// `T: Read` implies that a pointer to `T` with aliasing `A` permits +/// unsynchronized read operations. This can be because `A` is [`Exclusive`] or +/// because `T` does not permit interior mutation. +/// +/// # Safety +/// +/// `T: Read` if either of the following conditions holds: +/// - `A` is [`Exclusive`] +/// - `T` implements [`Immutable`](crate::Immutable) +/// +/// As a consequence, if `T: Read`, then any `Ptr` is +/// permitted to perform unsynchronized reads from its referent. +pub trait Read {} + +impl Read for T {} +impl Read for T {} + +/// Unsynchronized reads are permitted because only one live [`Ptr`](crate::Ptr) +/// or reference may exist to the referent bytes at a time. +#[derive(Copy, Clone, Debug)] +#[doc(hidden)] +pub enum BecauseExclusive {} + +/// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s or +/// references permit interior mutation. +#[derive(Copy, Clone, Debug)] +#[doc(hidden)] +pub enum BecauseImmutable {} + +use sealed::Sealed; +mod sealed { + use super::*; + + pub trait Sealed {} + + impl Sealed for Shared {} + impl Sealed for Exclusive {} + + impl Sealed for Unaligned {} + impl Sealed for Aligned {} + + impl Sealed for Uninit {} + impl Sealed for AsInitialized {} + impl Sealed for Initialized {} + impl Sealed for Valid {} + + impl Sealed for (A, AA, V) {} + + impl Sealed for BecauseImmutable {} + impl Sealed for BecauseExclusive {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Abstractions over raw pointers. + +mod inner; +#[doc(hidden)] +pub mod invariant; +mod ptr; +mod transmute; + +#[doc(hidden)] +pub use {inner::PtrInner, transmute::*}; +#[doc(hidden)] +pub use { + invariant::{BecauseExclusive, BecauseImmutable, Read}, + ptr::Ptr, +}; + +/// A shorthand for a maybe-valid, maybe-aligned reference. Used as the argument +/// to [`TryFromBytes::is_bit_valid`]. +/// +/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid +pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> = + Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>; + +/// Checks if the referent is zeroed. +pub(crate) fn is_zeroed(ptr: Ptr<'_, T, I>) -> bool +where + T: crate::Immutable + crate::KnownLayout, + I: invariant::Invariants, + I::Aliasing: invariant::Reference, +{ + ptr.as_bytes::().as_ref().iter().all(|&byte| byte == 0) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/ptr.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/ptr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/ptr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/ptr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1460 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{ + fmt::{Debug, Formatter}, + marker::PhantomData, +}; + +use crate::{ + pointer::{ + inner::PtrInner, + invariant::*, + transmute::{MutationCompatible, SizeEq, TransmuteFromPtr}, + }, + AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError, +}; + +/// Module used to gate access to [`Ptr`]'s fields. +mod def { + #[cfg(doc)] + use super::super::invariant; + use super::*; + + /// A raw pointer with more restrictions. + /// + /// `Ptr` is similar to [`NonNull`], but it is more restrictive in the + /// following ways (note that these requirements only hold of non-zero-sized + /// referents): + /// - It must derive from a valid allocation. + /// - It must reference a byte range which is contained inside the + /// allocation from which it derives. + /// - As a consequence, the byte range it references must have a size + /// which does not overflow `isize`. + /// + /// Depending on how `Ptr` is parameterized, it may have additional + /// invariants: + /// - `ptr` conforms to the aliasing invariant of + /// [`I::Aliasing`](invariant::Aliasing). + /// - `ptr` conforms to the alignment invariant of + /// [`I::Alignment`](invariant::Alignment). + /// - `ptr` conforms to the validity invariant of + /// [`I::Validity`](invariant::Validity). + /// + /// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`. + /// + /// [`NonNull`]: core::ptr::NonNull + /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html + pub struct Ptr<'a, T, I> + where + T: ?Sized, + I: Invariants, + { + /// # Invariants + /// + /// 0. `ptr` conforms to the aliasing invariant of + /// [`I::Aliasing`](invariant::Aliasing). + /// 1. `ptr` conforms to the alignment invariant of + /// [`I::Alignment`](invariant::Alignment). + /// 2. `ptr` conforms to the validity invariant of + /// [`I::Validity`](invariant::Validity). + // SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`. + ptr: PtrInner<'a, T>, + _invariants: PhantomData, + } + + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + /// Constructs a new `Ptr` from a [`PtrInner`]. + /// + /// # Safety + /// + /// The caller promises that: + /// + /// 0. `ptr` conforms to the aliasing invariant of + /// [`I::Aliasing`](invariant::Aliasing). + /// 1. `ptr` conforms to the alignment invariant of + /// [`I::Alignment`](invariant::Alignment). + /// 2. `ptr` conforms to the validity invariant of + /// [`I::Validity`](invariant::Validity). + pub(crate) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> { + // SAFETY: The caller has promised to satisfy all safety invariants + // of `Ptr`. + Self { ptr, _invariants: PhantomData } + } + + /// Converts this `Ptr` to a [`PtrInner`]. + /// + /// Note that this method does not consume `self`. The caller should + /// watch out for `unsafe` code which uses the returned value in a way + /// that violates the safety invariants of `self`. + pub(crate) fn as_inner(&self) -> PtrInner<'a, T> { + self.ptr + } + } +} + +#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. +pub use def::Ptr; + +/// External trait implementations on [`Ptr`]. +mod _external { + use super::*; + + /// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants + /// (besides aliasing) are unaffected by the number of references that exist + /// to `Ptr`'s referent. The notable cases are: + /// - Alignment is a property of the referent type (`T`) and the address, + /// both of which are unchanged + /// - Let `S(T, V)` be the set of bit values permitted to appear in the + /// referent of a `Ptr>`. Since this copy + /// does not change `I::Validity` or `T`, `S(T, I::Validity)` is also + /// unchanged. + /// + /// We are required to guarantee that the referents of the original `Ptr` + /// and of the copy (which, of course, are actually the same since they + /// live in the same byte address range) both remain in the set `S(T, + /// I::Validity)`. Since this invariant holds on the original `Ptr`, it + /// cannot be violated by the original `Ptr`, and thus the original `Ptr` + /// cannot be used to violate this invariant on the copy. The inverse + /// holds as well. + impl<'a, T, I> Copy for Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + } + + /// SAFETY: See the safety comment on `Copy`. + impl<'a, T, I> Clone for Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + impl<'a, T, I> Debug for Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + self.as_inner().as_non_null().fmt(f) + } + } +} + +/// Methods for converting to and from `Ptr` and Rust's safe reference types. +mod _conversions { + use super::*; + + /// `&'a T` → `Ptr<'a, T>` + impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)> + where + T: 'a + ?Sized, + { + /// Constructs a `Ptr` from a shared reference. + #[doc(hidden)] + #[inline] + pub fn from_ref(ptr: &'a T) -> Self { + let inner = PtrInner::from_ref(ptr); + // SAFETY: + // 0. `ptr`, by invariant on `&'a T`, conforms to the aliasing + // invariant of `Shared`. + // 1. `ptr`, by invariant on `&'a T`, conforms to the alignment + // invariant of `Aligned`. + // 2. `ptr`'s referent, by invariant on `&'a T`, is a bit-valid `T`. + // This satisfies the requirement that a `Ptr` + // point to a bit-valid `T`. Even if `T` permits interior + // mutation, this invariant guarantees that the returned `Ptr` + // can only ever be used to modify the referent to store + // bit-valid `T`s, which ensures that the returned `Ptr` cannot + // be used to violate the soundness of the original `ptr: &'a T` + // or of any other references that may exist to the same + // referent. + unsafe { Self::from_inner(inner) } + } + } + + /// `&'a mut T` → `Ptr<'a, T>` + impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> + where + T: 'a + ?Sized, + { + /// Constructs a `Ptr` from an exclusive reference. + #[inline] + pub(crate) fn from_mut(ptr: &'a mut T) -> Self { + let inner = PtrInner::from_mut(ptr); + // SAFETY: + // 0. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing + // invariant of `Exclusive`. + // 1. `ptr`, by invariant on `&'a mut T`, conforms to the alignment + // invariant of `Aligned`. + // 2. `ptr`'s referent, by invariant on `&'a mut T`, is a bit-valid + // `T`. This satisfies the requirement that a `Ptr` point to a bit-valid `T`. This invariant guarantees + // that the returned `Ptr` can only ever be used to modify the + // referent to store bit-valid `T`s, which ensures that the + // returned `Ptr` cannot be used to violate the soundness of the + // original `ptr: &'a mut T`. + unsafe { Self::from_inner(inner) } + } + } + + /// `Ptr<'a, T>` → `&'a T` + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + I::Aliasing: Reference, + { + /// Converts `self` to a shared reference. + // This consumes `self`, not `&self`, because `self` is, logically, a + // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so + // this doesn't prevent the caller from still using the pointer after + // calling `as_ref`. + #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_ref(self) -> &'a T { + let raw = self.as_inner().as_non_null(); + // SAFETY: This invocation of `NonNull::as_ref` satisfies its + // documented safety preconditions: + // + // 1. The pointer is properly aligned. This is ensured by-contract + // on `Ptr`, because the `I::Alignment` is `Aligned`. + // + // 2. If the pointer's referent is not zero-sized, then the pointer + // must be “dereferenceable” in the sense defined in the module + // documentation; i.e.: + // + // > The memory range of the given size starting at the pointer + // > must all be within the bounds of a single allocated object. + // > [2] + // + // This is ensured by contract on all `PtrInner`s. + // + // 3. The pointer must point to a validly-initialized instance of + // `T`. This is ensured by-contract on `Ptr`, because the + // `I::Validity` is `Valid`. + // + // 4. You must enforce Rust’s aliasing rules. This is ensured by + // contract on `Ptr`, because `I::Aliasing: Reference`. Either it + // is `Shared` or `Exclusive`. If it is `Shared`, other + // references may not mutate the referent outside of + // `UnsafeCell`s. + // + // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref + // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety + unsafe { raw.as_ref() } + } + } + + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + I::Aliasing: Reference, + { + /// Reborrows `self`, producing another `Ptr`. + /// + /// Since `self` is borrowed immutably, this prevents any mutable + /// methods from being called on `self` as long as the returned `Ptr` + /// exists. + #[doc(hidden)] + #[inline] + #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. + pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I> + where + 'a: 'b, + { + // SAFETY: The following all hold by invariant on `self`, and thus + // hold of `ptr = self.as_inner()`: + // 0. SEE BELOW. + // 1. `ptr` conforms to the alignment invariant of + // [`I::Alignment`](invariant::Alignment). + // 2. `ptr` conforms to the validity invariant of + // [`I::Validity`](invariant::Validity). `self` and the returned + // `Ptr` permit the same bit values in their referents since they + // have the same referent type (`T`) and the same validity + // (`I::Validity`). Thus, regardless of what mutation is + // permitted (`Exclusive` aliasing or `Shared`-aliased interior + // mutation), neither can be used to write a value to the + // referent which violates the other's validity invariant. + // + // For aliasing (0 above), since `I::Aliasing: Reference`, + // there are two cases for `I::Aliasing`: + // - For `invariant::Shared`: `'a` outlives `'b`, and so the + // returned `Ptr` does not permit accessing the referent any + // longer than is possible via `self`. For shared aliasing, it is + // sound for multiple `Ptr`s to exist simultaneously which + // reference the same memory, so creating a new one is not + // problematic. + // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we + // return a `Ptr` with lifetime `'b`, `self` is inaccessible to + // the caller for the lifetime `'b` - in other words, `self` is + // inaccessible to the caller as long as the returned `Ptr` + // exists. Since `self` is an exclusive `Ptr`, no other live + // references or `Ptr`s may exist which refer to the same memory + // while `self` is live. Thus, as long as the returned `Ptr` + // exists, no other references or `Ptr`s which refer to the same + // memory may be live. + unsafe { Ptr::from_inner(self.as_inner()) } + } + } + + /// `Ptr<'a, T>` → `&'a mut T` + impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> + where + T: 'a + ?Sized, + { + /// Converts `self` to a mutable reference. + #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_mut(self) -> &'a mut T { + let mut raw = self.as_inner().as_non_null(); + // SAFETY: This invocation of `NonNull::as_mut` satisfies its + // documented safety preconditions: + // + // 1. The pointer is properly aligned. This is ensured by-contract + // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`. + // + // 2. If the pointer's referent is not zero-sized, then the pointer + // must be “dereferenceable” in the sense defined in the module + // documentation; i.e.: + // + // > The memory range of the given size starting at the pointer + // > must all be within the bounds of a single allocated object. + // > [2] + // + // This is ensured by contract on all `PtrInner`s. + // + // 3. The pointer must point to a validly-initialized instance of + // `T`. This is ensured by-contract on `Ptr`, because the + // validity invariant is `Valid`. + // + // 4. You must enforce Rust’s aliasing rules. This is ensured by + // contract on `Ptr`, because the `ALIASING_INVARIANT` is + // `Exclusive`. + // + // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut + // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety + unsafe { raw.as_mut() } + } + } + + /// `Ptr<'a, T>` → `Ptr<'a, U>` + impl<'a, T: ?Sized, I> Ptr<'a, T, I> + where + I: Invariants, + { + pub(crate) fn transmute(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> + where + V: Validity, + U: TransmuteFromPtr + SizeEq + ?Sized, + { + // SAFETY: + // - `SizeEq::cast_from_raw` promises to preserve address, + // provenance, and the number of bytes in the referent + // - If aliasing is `Shared`, then by `U: TransmuteFromPtr`, at + // least one of the following holds: + // - `T: Immutable` and `U: Immutable`, in which case it is + // trivially sound for shared code to operate on a `&T` and `&U` + // at the same time, as neither can perform interior mutation + // - It is directly guaranteed that it is sound for shared code to + // operate on these references simultaneously + // - By `U: TransmuteFromPtr`, it is + // sound to perform this transmute. + unsafe { self.transmute_unchecked(SizeEq::cast_from_raw) } + } + + #[doc(hidden)] + #[inline(always)] + #[must_use] + pub fn recall_validity(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> + where + V: Validity, + T: TransmuteFromPtr, + { + // SAFETY: + // - This cast is a no-op, and so trivially preserves address, + // referent size, and provenance + // - It is trivially sound to have multiple `&T` referencing the same + // referent simultaneously + // - By `T: TransmuteFromPtr`, it is + // sound to perform this transmute. + let ptr = unsafe { self.transmute_unchecked(SizeEq::cast_from_raw) }; + // SAFETY: `self` and `ptr` have the same address and referent type. + // Therefore, if `self` satisfies `I::Alignment`, then so does + // `ptr`. + unsafe { ptr.assume_alignment::() } + } + + /// Casts to a different (unsized) target type without checking interior + /// mutability. + /// + /// Callers should prefer [`cast_unsized`] where possible. + /// + /// [`cast_unsized`]: Ptr::cast_unsized + /// + /// # Safety + /// + /// The caller promises that `u = cast(p)` is a pointer cast with the + /// following properties: + /// - `u` addresses a subset of the bytes addressed by `p` + /// - `u` has the same provenance as `p` + /// - If `I::Aliasing` is [`Shared`], it must not be possible for safe + /// code, operating on a `&T` and `&U` with the same referent + /// simultaneously, to cause undefined behavior + /// - It is sound to transmute a pointer of type `T` with aliasing + /// `I::Aliasing` and validity `I::Validity` to a pointer of type `U` + /// with aliasing `I::Aliasing` and validity `V`. This is a subtle + /// soundness requirement that is a function of `T`, `U`, + /// `I::Aliasing`, `I::Validity`, and `V`, and may depend upon the + /// presence, absence, or specific location of `UnsafeCell`s in `T` + /// and/or `U`. See [`Validity`] for more details. + #[doc(hidden)] + #[inline] + pub unsafe fn transmute_unchecked( + self, + cast: F, + ) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> + where + V: Validity, + F: FnOnce(PtrInner<'a, T>) -> PtrInner<'a, U>, + { + let ptr = cast(self.as_inner()); + + // SAFETY: + // + // The following safety arguments rely on the fact that the caller + // promises that `cast` returns a `PtrInner` which addresses a + // prefix of the bytes of `*self`, and so properties that hold of + // `*self` also hold of `*ptr`. + // + // 0. `ptr` conforms to the aliasing invariant of `I::Aliasing`: + // - `Exclusive`: `self` is the only `Ptr` or reference which is + // permitted to read or modify the referent for the lifetime + // `'a`. Since we consume `self` by value, the returned pointer + // remains the only `Ptr` or reference which is permitted to + // read or modify the referent for the lifetime `'a`. + // - `Shared`: Since `self` has aliasing `Shared`, we know that + // no other code may mutate the referent during the lifetime + // `'a`, except via `UnsafeCell`s, and except as permitted by + // `T`'s library safety invariants. The caller promises that + // any safe operations which can be permitted on a `&T` and a + // `&U` simultaneously must be sound. Thus, no operations on a + // `&U` could violate `&T`'s library safety invariants, and + // vice-versa. Since any mutation via shared references outside + // of `UnsafeCell`s is unsound, this must be impossible using + // `&T` and `&U`. + // - `Inaccessible`: There are no restrictions we need to uphold. + // 1. `ptr` trivially satisfies the alignment invariant `Unaligned`. + // 2. The caller promises that `ptr` conforms to the validity + // invariant `V` with respect to its referent type, `U`. + unsafe { Ptr::from_inner(ptr) } + } + } + + /// `Ptr<'a, T, (_, _, _)>` → `Ptr<'a, Unalign, (_, Aligned, _)>` + impl<'a, T, I> Ptr<'a, T, I> + where + I: Invariants, + { + /// Converts a `Ptr` an unaligned `T` into a `Ptr` to an aligned + /// `Unalign`. + pub(crate) fn into_unalign( + self, + ) -> Ptr<'a, crate::Unalign, (I::Aliasing, Aligned, I::Validity)> { + // SAFETY: + // - This cast preserves provenance. + // - This cast preserves address. `Unalign` promises to have the + // same size as `T`, and so the cast returns a pointer addressing + // the same byte range as `p`. + // - By the same argument, the returned pointer refers to + // `UnsafeCell`s at the same locations as `p`. + // - `Unalign` promises to have the same bit validity as `T`. By + // invariant on `Validity`, the set of bit patterns allowed in the + // referent of a `Ptr` is only a function of the + // validity of `X` and of `V`. Thus, the set of bit patterns + // allowed in the referent of a `Ptr` is + // the same as the set of bit patterns allowed in the referent of + // a `Ptr, (_, _, I::Validity)>`. As a result, `self` + // and the returned `Ptr` permit the same set of bit patterns in + // their referents, and so neither can be used to violate the + // validity of the other. + let ptr = unsafe { self.transmute_unchecked(PtrInner::cast_sized) }; + ptr.bikeshed_recall_aligned() + } + } + + impl<'a, T, I> Ptr<'a, T, I> + where + T: ?Sized, + I: Invariants, + I::Aliasing: Reference, + { + /// Reads the referent. + #[must_use] + #[inline] + pub fn read_unaligned(self) -> T + where + T: Copy, + T: Read, + { + (*self.into_unalign().as_ref()).into_inner() + } + + /// Views the value as an aligned reference. + /// + /// This is only available if `T` is [`Unaligned`]. + #[must_use] + #[inline] + pub fn unaligned_as_ref(self) -> &'a T + where + T: crate::Unaligned, + { + self.bikeshed_recall_aligned().as_ref() + } + } +} + +/// State transitions between invariants. +mod _transitions { + use super::*; + use crate::pointer::transmute::TryTransmuteFromPtr; + + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + /// Returns a `Ptr` with [`Exclusive`] aliasing if `self` already has + /// `Exclusive` aliasing, or generates a compile-time assertion failure. + /// + /// This allows code which is generic over aliasing to down-cast to a + /// concrete aliasing. + /// + /// [`Exclusive`]: crate::pointer::invariant::Exclusive + #[inline] + pub(crate) fn into_exclusive_or_pme( + self, + ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> { + // NOTE(https://github.com/rust-lang/rust/issues/131625): We do this + // rather than just having `Aliasing::IS_EXCLUSIVE` have the panic + // behavior because doing it that way causes rustdoc to fail while + // attempting to document hidden items (since it evaluates the + // constant - and thus panics). + trait AliasingExt: Aliasing { + const IS_EXCL: bool; + } + + impl AliasingExt for A { + const IS_EXCL: bool = { + const_assert!(Self::IS_EXCLUSIVE); + true + }; + } + + assert!(I::Aliasing::IS_EXCL); + + // SAFETY: We've confirmed that `self` already has the aliasing + // `Exclusive`. If it didn't, either the preceding assert would fail + // or evaluating `I::Aliasing::IS_EXCL` would fail. We're *pretty* + // sure that it's guaranteed to fail const eval, but the `assert!` + // provides a backstop in case that doesn't work. + unsafe { self.assume_exclusive() } + } + + /// Assumes that `self` satisfies the invariants `H`. + /// + /// # Safety + /// + /// The caller promises that `self` satisfies the invariants `H`. + unsafe fn assume_invariants(self) -> Ptr<'a, T, H> { + // SAFETY: The caller has promised to satisfy all parameterized + // invariants of `Ptr`. `Ptr`'s other invariants are satisfied + // by-contract by the source `Ptr`. + unsafe { Ptr::from_inner(self.as_inner()) } + } + + /// Helps the type system unify two distinct invariant types which are + /// actually the same. + pub(crate) fn unify_invariants< + H: Invariants, + >( + self, + ) -> Ptr<'a, T, H> { + // SAFETY: The associated type bounds on `H` ensure that the + // invariants are unchanged. + unsafe { self.assume_invariants::() } + } + + /// Assumes that `self` satisfies the aliasing requirement of `A`. + /// + /// # Safety + /// + /// The caller promises that `self` satisfies the aliasing requirement + /// of `A`. + #[inline] + pub(crate) unsafe fn assume_aliasing( + self, + ) -> Ptr<'a, T, (A, I::Alignment, I::Validity)> { + // SAFETY: The caller promises that `self` satisfies the aliasing + // requirements of `A`. + unsafe { self.assume_invariants() } + } + + /// Assumes `self` satisfies the aliasing requirement of [`Exclusive`]. + /// + /// # Safety + /// + /// The caller promises that `self` satisfies the aliasing requirement + /// of `Exclusive`. + /// + /// [`Exclusive`]: crate::pointer::invariant::Exclusive + #[inline] + pub(crate) unsafe fn assume_exclusive( + self, + ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> { + // SAFETY: The caller promises that `self` satisfies the aliasing + // requirements of `Exclusive`. + unsafe { self.assume_aliasing::() } + } + + /// Assumes that `self`'s referent is validly-aligned for `T` if + /// required by `A`. + /// + /// # Safety + /// + /// The caller promises that `self`'s referent conforms to the alignment + /// invariant of `T` if required by `A`. + #[inline] + pub(crate) unsafe fn assume_alignment( + self, + ) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)> { + // SAFETY: The caller promises that `self`'s referent is + // well-aligned for `T` if required by `A` . + unsafe { self.assume_invariants() } + } + + /// Checks the `self`'s alignment at runtime, returning an aligned `Ptr` + /// on success. + pub(crate) fn try_into_aligned( + self, + ) -> Result, AlignmentError> + where + T: Sized, + { + if let Err(err) = + crate::util::validate_aligned_to::<_, T>(self.as_inner().as_non_null()) + { + return Err(err.with_src(self)); + } + + // SAFETY: We just checked the alignment. + Ok(unsafe { self.assume_alignment::() }) + } + + /// Recalls that `self`'s referent is validly-aligned for `T`. + #[inline] + // FIXME(#859): Reconsider the name of this method before making it + // public. + pub(crate) fn bikeshed_recall_aligned( + self, + ) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)> + where + T: crate::Unaligned, + { + // SAFETY: The bound `T: Unaligned` ensures that `T` has no + // non-trivial alignment requirement. + unsafe { self.assume_alignment::() } + } + + /// Assumes that `self`'s referent conforms to the validity requirement + /// of `V`. + /// + /// # Safety + /// + /// The caller promises that `self`'s referent conforms to the validity + /// requirement of `V`. + #[doc(hidden)] + #[must_use] + #[inline] + pub unsafe fn assume_validity( + self, + ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> { + // SAFETY: The caller promises that `self`'s referent conforms to + // the validity requirement of `V`. + unsafe { self.assume_invariants() } + } + + /// A shorthand for `self.assume_validity()`. + /// + /// # Safety + /// + /// The caller promises to uphold the safety preconditions of + /// `self.assume_validity()`. + #[doc(hidden)] + #[must_use] + #[inline] + pub unsafe fn assume_initialized( + self, + ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> { + // SAFETY: The caller has promised to uphold the safety + // preconditions. + unsafe { self.assume_validity::() } + } + + /// A shorthand for `self.assume_validity()`. + /// + /// # Safety + /// + /// The caller promises to uphold the safety preconditions of + /// `self.assume_validity()`. + #[doc(hidden)] + #[must_use] + #[inline] + pub unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> { + // SAFETY: The caller has promised to uphold the safety + // preconditions. + unsafe { self.assume_validity::() } + } + + /// Recalls that `self`'s referent is initialized. + #[doc(hidden)] + #[must_use] + #[inline] + // FIXME(#859): Reconsider the name of this method before making it + // public. + pub fn bikeshed_recall_initialized_from_bytes( + self, + ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> + where + T: crate::IntoBytes + crate::FromBytes, + I: Invariants, + { + // SAFETY: The `T: IntoBytes + FromBytes` bound ensures that `T`'s + // bit validity is equivalent to `[u8]`. In other words, the set of + // allowed referents for a `Ptr` is the set of + // initialized bit patterns. The same is true of the set of allowed + // referents for any `Ptr<_, (_, _, Initialized)>`. Thus, this call + // does not change the set of allowed values in the referent. + unsafe { self.assume_initialized() } + } + + /// Recalls that `self`'s referent is initialized. + #[doc(hidden)] + #[must_use] + #[inline] + // FIXME(#859): Reconsider the name of this method before making it + // public. + pub fn bikeshed_recall_initialized_immutable( + self, + ) -> Ptr<'a, T, (Shared, I::Alignment, Initialized)> + where + T: crate::IntoBytes + crate::Immutable, + I: Invariants, + { + // SAFETY: Let `O` (for "old") be the set of allowed bit patterns in + // `self`'s referent, and let `N` (for "new") be the set of allowed + // bit patterns in the referent of the returned `Ptr`. `T: + // IntoBytes` and `I: Invariants` ensures that `O` + // cannot contain any uninitialized bit patterns. Since the returned + // `Ptr` has validity `Initialized`, `N` is equal to the set of all + // initialized bit patterns. Thus, `O` is a subset of `N`, and so + // the returned `Ptr`'s validity invariant is upheld. + // + // Since `T: Immutable` and aliasing is `Shared`, the returned `Ptr` + // cannot be used to modify the referent. Before this call, `self`'s + // referent is guaranteed by invariant on `Ptr` to satisfy `self`'s + // validity invariant. Since the returned `Ptr` cannot be used to + // modify the referent, this guarantee cannot be violated by the + // returned `Ptr` (even if `O` is a strict subset of `N`). + unsafe { self.assume_initialized() } + } + + /// Checks that `self`'s referent is validly initialized for `T`, + /// returning a `Ptr` with `Valid` on success. + /// + /// # Panics + /// + /// This method will panic if + /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics. + /// + /// # Safety + /// + /// On error, unsafe code may rely on this method's returned + /// `ValidityError` containing `self`. + #[inline] + pub(crate) fn try_into_valid( + mut self, + ) -> Result, ValidityError> + where + T: TryFromBytes + + Read + + TryTransmuteFromPtr, + I::Aliasing: Reference, + I: Invariants, + { + // This call may panic. If that happens, it doesn't cause any soundness + // issues, as we have not generated any invalid state which we need to + // fix before returning. + if T::is_bit_valid(self.reborrow().forget_aligned()) { + // SAFETY: If `T::is_bit_valid`, code may assume that `self` + // contains a bit-valid instance of `T`. By `T: + // TryTransmuteFromPtr`, so + // long as `self`'s referent conforms to the `Valid` validity + // for `T` (which we just confired), then this transmute is + // sound. + Ok(unsafe { self.assume_valid() }) + } else { + Err(ValidityError::new(self)) + } + } + + /// Forgets that `self`'s referent is validly-aligned for `T`. + #[doc(hidden)] + #[must_use] + #[inline] + pub fn forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Unaligned, I::Validity)> { + // SAFETY: `Unaligned` is less restrictive than `Aligned`. + unsafe { self.assume_invariants() } + } + } +} + +/// Casts of the referent type. +mod _casts { + use super::*; + + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized, + I: Invariants, + { + /// Casts to a different (unsized) target type without checking interior + /// mutability. + /// + /// Callers should prefer [`cast_unsized`] where possible. + /// + /// [`cast_unsized`]: Ptr::cast_unsized + /// + /// # Safety + /// + /// The caller promises that `u = cast(p)` is a pointer cast with the + /// following properties: + /// - `u` addresses a subset of the bytes addressed by `p` + /// - `u` has the same provenance as `p` + /// - If `I::Aliasing` is [`Shared`], it must not be possible for safe + /// code, operating on a `&T` and `&U` with the same referent + /// simultaneously, to cause undefined behavior + /// + /// `cast_unsized_unchecked` guarantees that the pointer passed to + /// `cast` will reference a byte sequence which is either contained + /// inside a single allocated object or is zero sized. In either case, + /// this means that its size will fit in an `isize` and it will not wrap + /// around the address space. + #[doc(hidden)] + #[inline] + pub unsafe fn cast_unsized_unchecked) -> PtrInner<'a, U>>( + self, + cast: F, + ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> + where + U: 'a + CastableFrom + ?Sized, + { + // SAFETY: + // - The caller promises that `u = cast(p)` is a pointer which + // satisfies: + // - `u` addresses a subset of the bytes addressed by `p` + // - `u` has the same provenance as `p` + // - If `I::Aliasing` is [`Shared`], it must not be possible for + // safe code, operating on a `&T` and `&U` with the same + // referent simultaneously, to cause undefined behavior + // - By `U: CastableFrom`, + // `I::Validity` is either `Uninit` or `Initialized`. In both + // cases, the bit validity `I::Validity` has the same semantics + // regardless of referent type. In other words, the set of allowed + // referent values for `Ptr` and `Ptr` are identical. As a consequence, neither + // `self` nor the returned `Ptr` can be used to write values which + // are invalid for the other. + // + // `transmute_unchecked` guarantees that it will only pass pointers + // to `cast` which either reference a zero-sized byte range or + // reference a byte range which is entirely contained inside of an + // allocated object. + unsafe { self.transmute_unchecked(cast) } + } + + /// Casts to a different (unsized) target type. + /// + /// # Safety + /// + /// The caller promises that `u = cast(p)` is a pointer cast with the + /// following properties: + /// - `u` addresses a subset of the bytes addressed by `p` + /// - `u` has the same provenance as `p` + #[doc(hidden)] + #[inline] + pub unsafe fn cast_unsized( + self, + cast: F, + ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> + where + T: MutationCompatible, + U: 'a + ?Sized + CastableFrom, + F: FnOnce(PtrInner<'a, T>) -> PtrInner<'a, U>, + { + // SAFETY: Because `T: MutationCompatible`, one + // of the following holds: + // - `T: Read` and `U: Read`, in which + // case one of the following holds: + // - `I::Aliasing` is `Exclusive` + // - `T` and `U` are both `Immutable` + // - It is sound for safe code to operate on `&T` and `&U` with the + // same referent simultaneously + // + // The caller promises all other safety preconditions. + unsafe { self.cast_unsized_unchecked(cast) } + } + } + + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + KnownLayout + ?Sized, + I: Invariants, + { + /// Casts this pointer-to-initialized into a pointer-to-bytes. + #[allow(clippy::wrong_self_convention)] + #[must_use] + #[inline] + pub fn as_bytes(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)> + where + T: Read, + I::Aliasing: Reference, + { + // SAFETY: `PtrInner::as_bytes` returns a pointer which addresses + // the same byte range as its argument, and which has the same + // provenance. + let ptr = unsafe { self.cast_unsized(PtrInner::as_bytes) }; + ptr.bikeshed_recall_aligned().recall_validity::() + } + } + + impl<'a, T, I, const N: usize> Ptr<'a, [T; N], I> + where + T: 'a, + I: Invariants, + { + /// Casts this pointer-to-array into a slice. + #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_slice(self) -> Ptr<'a, [T], I> { + let slice = self.as_inner().as_slice(); + // SAFETY: Note that, by post-condition on `PtrInner::as_slice`, + // `slice` refers to the same byte range as `self.as_inner()`. + // + // 0. Thus, `slice` conforms to the aliasing invariant of + // `I::Aliasing` because `self` does. + // 1. By the above lemma, `slice` conforms to the alignment + // invariant of `I::Alignment` because `self` does. + // 2. Since `[T; N]` and `[T]` have the same bit validity [1][2], + // and since `self` and the returned `Ptr` have the same validity + // invariant, neither `self` nor the returned `Ptr` can be used + // to write a value to the referent which violates the other's + // validity invariant. + // + // [1] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#array-layout: + // + // An array of `[T; N]` has a size of `size_of::() * N` and the + // same alignment of `T`. Arrays are laid out so that the + // zero-based `nth` element of the array is offset from the start + // of the array by `n * size_of::()` bytes. + // + // ... + // + // Slices have the same layout as the section of the array they + // slice. + // + // [2] Per https://doc.rust-lang.org/1.81.0/reference/types/array.html#array-types: + // + // All elements of arrays are always initialized + unsafe { Ptr::from_inner(slice) } + } + } + + /// For caller convenience, these methods are generic over alignment + /// invariant. In practice, the referent is always well-aligned, because the + /// alignment of `[u8]` is 1. + impl<'a, I> Ptr<'a, [u8], I> + where + I: Invariants, + { + /// Attempts to cast `self` to a `U` using the given cast type. + /// + /// If `U` is a slice DST and pointer metadata (`meta`) is provided, + /// then the cast will only succeed if it would produce an object with + /// the given metadata. + /// + /// Returns `None` if the resulting `U` would be invalidly-aligned, if + /// no `U` can fit in `self`, or if the provided pointer metadata + /// describes an invalid instance of `U`. On success, returns a pointer + /// to the largest-possible `U` which fits in `self`. + /// + /// # Safety + /// + /// The caller may assume that this implementation is correct, and may + /// rely on that assumption for the soundness of their code. In + /// particular, the caller may assume that, if `try_cast_into` returns + /// `Some((ptr, remainder))`, then `ptr` and `remainder` refer to + /// non-overlapping byte ranges within `self`, and that `ptr` and + /// `remainder` entirely cover `self`. Finally: + /// - If this is a prefix cast, `ptr` has the same address as `self`. + /// - If this is a suffix cast, `remainder` has the same address as + /// `self`. + #[inline(always)] + pub(crate) fn try_cast_into( + self, + cast_type: CastType, + meta: Option, + ) -> Result< + (Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, Ptr<'a, [u8], I>), + CastError, + > + where + I::Aliasing: Reference, + U: 'a + ?Sized + KnownLayout + Read, + { + let (inner, remainder) = + self.as_inner().try_cast_into(cast_type, meta).map_err(|err| { + err.map_src(|inner| + // SAFETY: `PtrInner::try_cast_into` promises to return its + // original argument on error, which was originally produced + // by `self.as_inner()`, which is guaranteed to satisfy + // `Ptr`'s invariants. + unsafe { Ptr::from_inner(inner) }) + })?; + + // SAFETY: + // 0. Since `U: Read`, either: + // - `I::Aliasing` is `Exclusive`, in which case both `src` and + // `ptr` conform to `Exclusive` + // - `I::Aliasing` is `Shared` and `U` is `Immutable` (we already + // know that `[u8]: Immutable`). In this case, neither `U` nor + // `[u8]` permit mutation, and so `Shared` aliasing is + // satisfied. + // 1. `ptr` conforms to the alignment invariant of `Aligned` because + // it is derived from `try_cast_into`, which promises that the + // object described by `target` is validly aligned for `U`. + // 2. By trait bound, `self` - and thus `target` - is a bit-valid + // `[u8]`. `Ptr<[u8], (_, _, Valid)>` and `Ptr<_, (_, _, + // Initialized)>` have the same bit validity, and so neither + // `self` nor `res` can be used to write a value to the referent + // which violates the other's validity invariant. + let res = unsafe { Ptr::from_inner(inner) }; + + // SAFETY: + // 0. `self` and `remainder` both have the type `[u8]`. Thus, they + // have `UnsafeCell`s at the same locations. Type casting does + // not affect aliasing. + // 1. `[u8]` has no alignment requirement. + // 2. `self` has validity `Valid` and has type `[u8]`. Since + // `remainder` references a subset of `self`'s referent, it is + // also a bit-valid `[u8]`. Thus, neither `self` nor `remainder` + // can be used to write a value to the referent which violates + // the other's validity invariant. + let remainder = unsafe { Ptr::from_inner(remainder) }; + + Ok((res, remainder)) + } + + /// Attempts to cast `self` into a `U`, failing if all of the bytes of + /// `self` cannot be treated as a `U`. + /// + /// In particular, this method fails if `self` is not validly-aligned + /// for `U` or if `self`'s size is not a valid size for `U`. + /// + /// # Safety + /// + /// On success, the caller may assume that the returned pointer + /// references the same byte range as `self`. + #[allow(unused)] + #[inline(always)] + pub(crate) fn try_cast_into_no_leftover( + self, + meta: Option, + ) -> Result, CastError> + where + I::Aliasing: Reference, + U: 'a + ?Sized + KnownLayout + Read, + { + // FIXME(#67): Remove this allow. See NonNulSlicelExt for more + // details. + #[allow(unstable_name_collisions)] + match self.try_cast_into(CastType::Prefix, meta) { + Ok((slf, remainder)) => { + if remainder.len() == 0 { + Ok(slf) + } else { + // Undo the cast so we can return the original bytes. + let slf = slf.as_bytes(); + // Restore the initial alignment invariant of `self`. + // + // SAFETY: The referent type of `slf` is now equal to + // that of `self`, but the alignment invariants + // nominally differ. Since `slf` and `self` refer to the + // same memory and no actions have been taken that would + // violate the original invariants on `self`, it is + // sound to apply the alignment invariant of `self` onto + // `slf`. + let slf = unsafe { slf.assume_alignment::() }; + let slf = slf.unify_invariants(); + Err(CastError::Size(SizeError::<_, U>::new(slf))) + } + } + Err(err) => Err(err), + } + } + } + + impl<'a, T, I> Ptr<'a, core::cell::UnsafeCell, I> + where + T: 'a + ?Sized, + I: Invariants, + { + /// Converts this `Ptr` into a pointer to the underlying data. + /// + /// This call borrows the `UnsafeCell` mutably (at compile-time) which + /// guarantees that we possess the only reference. + /// + /// This is like [`UnsafeCell::get_mut`], but for `Ptr`. + /// + /// [`UnsafeCell::get_mut`]: core::cell::UnsafeCell::get_mut + #[must_use] + #[inline(always)] + pub fn get_mut(self) -> Ptr<'a, T, I> { + // SAFETY: + // - The closure uses an `as` cast, which preserves address range + // and provenance. + // - Aliasing is `Exclusive`, and so we are not required to promise + // anything about the locations of `UnsafeCell`s. + // - `UnsafeCell` has the same bit validity as `T` [1]. + // Technically the term "representation" doesn't guarantee this, + // but the subsequent sentence in the documentation makes it clear + // that this is the intention. + // + // By invariant on `Validity`, since `T` and `UnsafeCell` have + // the same bit validity, then the set of values which may appear + // in the referent of a `Ptr` is the same as the set + // which may appear in the referent of a `Ptr, (_, + // _, V)>`. Thus, neither `self` nor `ptr` may be used to write a + // value to the referent which would violate the other's validity + // invariant. + // + // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: + // + // `UnsafeCell` has the same in-memory representation as its + // inner type `T`. A consequence of this guarantee is that it is + // possible to convert between `T` and `UnsafeCell`. + #[allow(clippy::as_conversions)] + let ptr = unsafe { self.transmute_unchecked(|ptr| cast!(ptr)) }; + + // SAFETY: `UnsafeCell` has the same alignment as `T` [1], + // and so if `self` is guaranteed to be aligned, then so is the + // returned `Ptr`. + // + // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: + // + // `UnsafeCell` has the same in-memory representation as + // its inner type `T`. A consequence of this guarantee is that + // it is possible to convert between `T` and `UnsafeCell`. + let ptr = unsafe { ptr.assume_alignment::() }; + ptr.unify_invariants() + } + } +} + +/// Projections through the referent. +mod _project { + use super::*; + + impl<'a, T, I> Ptr<'a, [T], I> + where + T: 'a, + I: Invariants, + I::Aliasing: Reference, + { + /// Iteratively projects the elements `Ptr` from `Ptr<[T]>`. + pub(crate) fn iter(&self) -> impl Iterator> { + // SAFETY: + // 0. `elem` conforms to the aliasing invariant of `I::Aliasing` + // because projection does not impact the aliasing invariant. + // 1. `elem`, conditionally, conforms to the validity invariant of + // `I::Alignment`. If `elem` is projected from data well-aligned + // for `[T]`, `elem` will be valid for `T`. + // 2. FIXME: Need to cite facts about `[T]`'s layout (same for the + // preceding points) + self.as_inner().iter().map(|elem| unsafe { Ptr::from_inner(elem) }) + } + } + + #[allow(clippy::needless_lifetimes)] + impl<'a, T, I> Ptr<'a, T, I> + where + T: 'a + ?Sized + KnownLayout, + I: Invariants, + { + /// The number of slice elements in the object referenced by `self`. + pub(crate) fn len(&self) -> usize { + self.as_inner().meta().get() + } + } +} + +#[cfg(test)] +mod tests { + use core::mem::{self, MaybeUninit}; + + use super::*; + #[allow(unused)] // Needed on our MSRV, but considered unused on later toolchains. + use crate::util::AsAddress; + use crate::{pointer::BecauseImmutable, util::testutil::AU64, FromBytes, Immutable}; + + mod test_ptr_try_cast_into_soundness { + use super::*; + + // This test is designed so that if `Ptr::try_cast_into_xxx` are + // buggy, it will manifest as unsoundness that Miri can detect. + + // - If `size_of::() == 0`, `N == 4` + // - Else, `N == 4 * size_of::()` + // + // Each test will be run for each metadata in `metas`. + fn test(metas: I) + where + T: ?Sized + KnownLayout + Immutable + FromBytes, + I: IntoIterator> + Clone, + { + let mut bytes = [MaybeUninit::::uninit(); N]; + let initialized = [MaybeUninit::new(0u8); N]; + for start in 0..=bytes.len() { + for end in start..=bytes.len() { + // Set all bytes to uninitialized other than those in + // the range we're going to pass to `try_cast_from`. + // This allows Miri to detect out-of-bounds reads + // because they read uninitialized memory. Without this, + // some out-of-bounds reads would still be in-bounds of + // `bytes`, and so might spuriously be accepted. + bytes = [MaybeUninit::::uninit(); N]; + let bytes = &mut bytes[start..end]; + // Initialize only the byte range we're going to pass to + // `try_cast_from`. + bytes.copy_from_slice(&initialized[start..end]); + + let bytes = { + let bytes: *const [MaybeUninit] = bytes; + #[allow(clippy::as_conversions)] + let bytes = bytes as *const [u8]; + // SAFETY: We just initialized these bytes to valid + // `u8`s. + unsafe { &*bytes } + }; + + // SAFETY: The bytes in `slf` must be initialized. + unsafe fn validate_and_get_len< + T: ?Sized + KnownLayout + FromBytes + Immutable, + >( + slf: Ptr<'_, T, (Shared, Aligned, Initialized)>, + ) -> usize { + let t = slf.recall_validity().as_ref(); + + let bytes = { + let len = mem::size_of_val(t); + let t: *const T = t; + // SAFETY: + // - We know `t`'s bytes are all initialized + // because we just read it from `slf`, which + // points to an initialized range of bytes. If + // there's a bug and this doesn't hold, then + // that's exactly what we're hoping Miri will + // catch! + // - Since `T: FromBytes`, `T` doesn't contain + // any `UnsafeCell`s, so it's okay for `t: T` + // and a `&[u8]` to the same memory to be + // alive concurrently. + unsafe { core::slice::from_raw_parts(t.cast::(), len) } + }; + + // This assertion ensures that `t`'s bytes are read + // and compared to another value, which in turn + // ensures that Miri gets a chance to notice if any + // of `t`'s bytes are uninitialized, which they + // shouldn't be (see the comment above). + assert_eq!(bytes, vec![0u8; bytes.len()]); + + mem::size_of_val(t) + } + + for meta in metas.clone().into_iter() { + for cast_type in [CastType::Prefix, CastType::Suffix] { + if let Ok((slf, remaining)) = Ptr::from_ref(bytes) + .try_cast_into::(cast_type, meta) + { + // SAFETY: All bytes in `bytes` have been + // initialized. + let len = unsafe { validate_and_get_len(slf) }; + assert_eq!(remaining.len(), bytes.len() - len); + #[allow(unstable_name_collisions)] + let bytes_addr = bytes.as_ptr().addr(); + #[allow(unstable_name_collisions)] + let remaining_addr = + remaining.as_inner().as_non_null().as_ptr().addr(); + match cast_type { + CastType::Prefix => { + assert_eq!(remaining_addr, bytes_addr + len) + } + CastType::Suffix => assert_eq!(remaining_addr, bytes_addr), + } + + if let Some(want) = meta { + let got = KnownLayout::pointer_to_metadata( + slf.as_inner().as_non_null().as_ptr(), + ); + assert_eq!(got, want); + } + } + } + + if let Ok(slf) = Ptr::from_ref(bytes) + .try_cast_into_no_leftover::(meta) + { + // SAFETY: All bytes in `bytes` have been + // initialized. + let len = unsafe { validate_and_get_len(slf) }; + assert_eq!(len, bytes.len()); + + if let Some(want) = meta { + let got = KnownLayout::pointer_to_metadata( + slf.as_inner().as_non_null().as_ptr(), + ); + assert_eq!(got, want); + } + } + } + } + } + } + + #[derive(FromBytes, KnownLayout, Immutable)] + #[repr(C)] + struct SliceDst { + a: u8, + trailing: [T], + } + + // Each test case becomes its own `#[test]` function. We do this because + // this test in particular takes far, far longer to execute under Miri + // than all of our other tests combined. Previously, we had these + // execute sequentially in a single test function. We run Miri tests in + // parallel in CI, but this test being sequential meant that most of + // that parallelism was wasted, as all other tests would finish in a + // fraction of the total execution time, leaving this test to execute on + // a single thread for the remainder of the test. By putting each test + // case in its own function, we permit better use of available + // parallelism. + macro_rules! test { + ($test_name:ident: $ty:ty) => { + #[test] + #[allow(non_snake_case)] + fn $test_name() { + const S: usize = core::mem::size_of::<$ty>(); + const N: usize = if S == 0 { 4 } else { S * 4 }; + test::<$ty, _, N>([None]); + + // If `$ty` is a ZST, then we can't pass `None` as the + // pointer metadata, or else computing the correct trailing + // slice length will panic. + if S == 0 { + test::<[$ty], _, N>([Some(0), Some(1), Some(2), Some(3)]); + test::, _, N>([Some(0), Some(1), Some(2), Some(3)]); + } else { + test::<[$ty], _, N>([None, Some(0), Some(1), Some(2), Some(3)]); + test::, _, N>([None, Some(0), Some(1), Some(2), Some(3)]); + } + } + }; + ($ty:ident) => { + test!($ty: $ty); + }; + ($($ty:ident),*) => { $(test!($ty);)* } + } + + test!(empty_tuple: ()); + test!(u8, u16, u32, u64, u128, usize, AU64); + test!(i8, i16, i32, i64, i128, isize); + test!(f32, f64); + } + + #[test] + fn test_try_cast_into_explicit_count() { + macro_rules! test { + ($ty:ty, $bytes:expr, $elems:expr, $expect:expr) => {{ + let bytes = [0u8; $bytes]; + let ptr = Ptr::from_ref(&bytes[..]); + let res = + ptr.try_cast_into::<$ty, BecauseImmutable>(CastType::Prefix, Some($elems)); + if let Some(expect) = $expect { + let (ptr, _) = res.unwrap(); + assert_eq!( + KnownLayout::pointer_to_metadata(ptr.as_inner().as_non_null().as_ptr()), + expect + ); + } else { + let _ = res.unwrap_err(); + } + }}; + } + + #[derive(KnownLayout, Immutable)] + #[repr(C)] + struct ZstDst { + u: [u8; 8], + slc: [()], + } + + test!(ZstDst, 8, 0, Some(0)); + test!(ZstDst, 7, 0, None); + + test!(ZstDst, 8, usize::MAX, Some(usize::MAX)); + test!(ZstDst, 7, usize::MAX, None); + + #[derive(KnownLayout, Immutable)] + #[repr(C)] + struct Dst { + u: [u8; 8], + slc: [u8], + } + + test!(Dst, 8, 0, Some(0)); + test!(Dst, 7, 0, None); + + test!(Dst, 9, 1, Some(1)); + test!(Dst, 8, 1, None); + + // If we didn't properly check for overflow, this would cause the + // metadata to overflow to 0, and thus the cast would spuriously + // succeed. + test!(Dst, 8, usize::MAX - 8 + 1, None); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/transmute.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/transmute.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/pointer/transmute.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/pointer/transmute.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,479 @@ +// Copyright 2025 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{ + cell::{Cell, UnsafeCell}, + mem::{ManuallyDrop, MaybeUninit}, + num::Wrapping, +}; + +use crate::{ + pointer::{invariant::*, PtrInner}, + FromBytes, Immutable, IntoBytes, Unalign, +}; + +/// Transmutations which are sound to attempt, conditional on validating the bit +/// validity of the destination type. +/// +/// If a `Ptr` transmutation is `TryTransmuteFromPtr`, then it is sound to +/// perform that transmutation so long as some additional mechanism is used to +/// validate that the referent is bit-valid for the destination type. That +/// validation mechanism could be a type bound (such as `TransmuteFrom`) or a +/// runtime validity check. +/// +/// # Safety +/// +/// ## Post-conditions +/// +/// Given `Dst: TryTransmuteFromPtr`, callers may assume the +/// following: +/// +/// Given `src: Ptr<'a, Src, (A, _, SV)>`, if the referent of `src` is +/// `DV`-valid for `Dst`, then it is sound to transmute `src` into `dst: Ptr<'a, +/// Dst, (A, Unaligned, DV)>` by preserving pointer address and metadata. +/// +/// ## Pre-conditions +/// +/// Given `src: Ptr` and `dst: Ptr`, +/// `Dst: TryTransmuteFromPtr` is sound if all of the +/// following hold: +/// - Forwards transmutation: Either of the following hold: +/// - So long as `dst` is active, no mutation of `dst`'s referent is allowed +/// except via `dst` itself +/// - The set of `DV`-valid `Dst`s is a superset of the set of `SV`-valid +/// `Src`s +/// - Reverse transmutation: Either of the following hold: +/// - `dst` does not permit mutation of its referent +/// - The set of `DV`-valid `Dst`s is a subset of the set of `SV`-valid `Src`s +/// - No safe code, given access to `src` and `dst`, can cause undefined +/// behavior: Any of the following hold: +/// - `A` is `Exclusive` +/// - `Src: Immutable` and `Dst: Immutable` +/// - It is sound for shared code to operate on a `&Src` and `&Dst` which +/// reference the same byte range at the same time +/// +/// ## Proof +/// +/// Given: +/// - `src: Ptr<'a, Src, (A, _, SV)>` +/// - `src`'s referent is `DV`-valid for `Dst` +/// - `Dst: SizeEq` +/// +/// We are trying to prove that it is sound to perform a pointer address- and +/// metadata-preserving transmute from `src` to a `dst: Ptr<'a, Dst, (A, +/// Unaligned, DV)>`. We need to prove that such a transmute does not violate +/// any of `src`'s invariants, and that it satisfies all invariants of the +/// destination `Ptr` type. +/// +/// First, all of `src`'s `PtrInner` invariants are upheld. `src`'s address and +/// metadata are unchanged, so: +/// - If its referent is not zero sized, then it still has valid provenance for +/// its referent, which is still entirely contained in some Rust allocation, +/// `A` +/// - If its referent is not zero sized, `A` is guaranteed to live for at least +/// `'a` +/// +/// Since `Dst: SizeEq`, and since `dst` has the same address and metadata +/// as `src`, `dst` addresses the same byte range as `src`. `dst` also has the +/// same lifetime as `src`. Therefore, all of the `PtrInner` invariants +/// mentioned above also hold for `dst`. +/// +/// Second, since `src`'s address is unchanged, it still satisfies its +/// alignment. Since `dst`'s alignment is `Unaligned`, it trivially satisfies +/// its alignment. +/// +/// Third, aliasing is either `Exclusive` or `Shared`: +/// - If it is `Exclusive`, then both `src` and `dst` satisfy `Exclusive` +/// aliasing trivially: since `src` and `dst` have the same lifetime, `src` is +/// inaccessible so long as `dst` is alive, and no other live `Ptr`s or +/// references may reference the same referent. +/// - If it is `Shared`, then either: +/// - `Src: Immutable` and `Dst: Immutable`, and so `UnsafeCell`s trivially +/// cover the same byte ranges in both types. +/// - It is explicitly sound for safe code to operate on a `&Src` and a `&Dst` +/// pointing to the same byte range at the same time. +/// +/// Fourth, `src`'s validity is satisfied. By invariant, `src`'s referent began +/// as an `SV`-valid `Src`. It is guaranteed to remain so, as either of the +/// following hold: +/// - `dst` does not permit mutation of its referent. +/// - The set of `DV`-valid `Dst`s is a superset of the set of `SV`-valid +/// `Src`s. Thus, any value written via `dst` is guaranteed to be `SV`-valid +/// for `Src`. +/// +/// Fifth, `dst`'s validity is satisfied. It is a given of this proof that the +/// referent is `DV`-valid for `Dst`. It is guaranteed to remain so, as either +/// of the following hold: +/// - So long as `dst` is active, no mutation of the referent is allowed except +/// via `dst` itself. +/// - The set of `DV`-valid `Dst`s is a superset of the set of `SV`-valid +/// `Src`s. Thus, any value written via `src` is guaranteed to be a `DV`-valid +/// `Dst`. +pub unsafe trait TryTransmuteFromPtr: + SizeEq +{ +} + +#[allow(missing_copy_implementations, missing_debug_implementations)] +pub enum BecauseMutationCompatible {} + +// SAFETY: +// - Forwards transmutation: By `Dst: MutationCompatible`, we +// know that at least one of the following holds: +// - So long as `dst: Ptr` is active, no mutation of its referent is +// allowed except via `dst` itself if either of the following hold: +// - Aliasing is `Exclusive`, in which case, so long as the `Dst` `Ptr` +// exists, no mutation is permitted except via that `Ptr` +// - Aliasing is `Shared`, `Src: Immutable`, and `Dst: Immutable`, in which +// case no mutation is possible via either `Ptr` +// - `Dst: TransmuteFrom`. Since `Dst: SizeEq`, this bound +// guarantees that the set of `DV`-valid `Dst`s is a supserset of the set of +// `SV`-valid `Src`s. +// - Reverse transmutation: `Src: TransmuteFrom`. Since `Dst: +// SizeEq`, this guarantees that the set of `DV`-valid `Dst`s is a subset +// of the set of `SV`-valid `Src`s. +// - No safe code, given access to `src` and `dst`, can cause undefined +// behavior: By `Dst: MutationCompatible`, at least one of +// the following holds: +// - `A` is `Exclusive` +// - `Src: Immutable` and `Dst: Immutable` +// - `Dst: InvariantsEq`, which guarantees that `Src` and `Dst` have the +// same invariants, and have `UnsafeCell`s covering the same byte ranges +unsafe impl + TryTransmuteFromPtr for Dst +where + A: Aliasing, + SV: Validity, + DV: Validity, + Src: TransmuteFrom + ?Sized, + Dst: MutationCompatible + SizeEq + ?Sized, +{ +} + +// SAFETY: +// - Forwards transmutation: Since aliasing is `Shared` and `Src: Immutable`, +// `src` does not permit mutation of its referent. +// - Reverse transmutation: Since aliasing is `Shared` and `Dst: Immutable`, +// `dst` does not permit mutation of its referent. +// - No safe code, given access to `src` and `dst`, can cause undefined +// behavior: `Src: Immutable` and `Dst: Immutable` +unsafe impl TryTransmuteFromPtr for Dst +where + SV: Validity, + DV: Validity, + Src: Immutable + ?Sized, + Dst: Immutable + SizeEq + ?Sized, +{ +} + +/// Denotes that `src: Ptr` and `dst: Ptr`, +/// referencing the same referent at the same time, cannot be used by safe code +/// to break library safety invariants of `Src` or `Self`. +/// +/// # Safety +/// +/// At least one of the following must hold: +/// - `Src: Read` and `Self: Read` +/// - `Self: InvariantsEq`, and, for some `V`: +/// - `Dst: TransmuteFrom` +/// - `Src: TransmuteFrom` +pub unsafe trait MutationCompatible {} + +#[allow(missing_copy_implementations, missing_debug_implementations)] +pub enum BecauseRead {} + +// SAFETY: `Src: Read` and `Dst: Read`. +unsafe impl + MutationCompatible for Dst +where + Src: Read, + Dst: Read, +{ +} + +/// Denotes that two types have the same invariants. +/// +/// # Safety +/// +/// It is sound for safe code to operate on a `&T` and a `&Self` pointing to the +/// same referent at the same time - no such safe code can cause undefined +/// behavior. +pub unsafe trait InvariantsEq {} + +// SAFETY: Trivially sound to have multiple `&T` pointing to the same referent. +unsafe impl InvariantsEq for T {} + +// SAFETY: `Dst: InvariantsEq + TransmuteFrom`, and `Src: +// TransmuteFrom`. +unsafe impl + MutationCompatible for Dst +where + Src: TransmuteFrom, + Dst: TransmuteFrom + InvariantsEq, +{ +} + +pub(crate) enum BecauseInvariantsEq {} + +macro_rules! unsafe_impl_invariants_eq { + ($tyvar:ident => $t:ty, $u:ty) => {{ + crate::util::macros::__unsafe(); + // SAFETY: The caller promises that this is sound. + unsafe impl<$tyvar> InvariantsEq<$t> for $u {} + // SAFETY: The caller promises that this is sound. + unsafe impl<$tyvar> InvariantsEq<$u> for $t {} + }}; +} + +impl_transitive_transmute_from!(T => MaybeUninit => T => Wrapping); +impl_transitive_transmute_from!(T => Wrapping => T => MaybeUninit); + +// SAFETY: `ManuallyDrop` has the same size and bit validity as `T` [1], and +// implements `Deref` [2]. Thus, it is already possible for safe +// code to obtain a `&T` and a `&ManuallyDrop` to the same referent at the +// same time. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit +// validity as `T` +// +// [2] https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E +unsafe impl InvariantsEq for ManuallyDrop {} +// SAFETY: See previous safety comment. +unsafe impl InvariantsEq> for T {} + +/// Transmutations which are always sound. +/// +/// `TransmuteFromPtr` is a shorthand for [`TryTransmuteFromPtr`] and +/// [`TransmuteFrom`]. +/// +/// # Safety +/// +/// `Dst: TransmuteFromPtr` is equivalent to `Dst: +/// TryTransmuteFromPtr + TransmuteFrom`. +pub unsafe trait TransmuteFromPtr: + TryTransmuteFromPtr + TransmuteFrom +{ +} + +// SAFETY: The `where` bounds are equivalent to the safety invariant on +// `TransmuteFromPtr`. +unsafe impl + TransmuteFromPtr for Dst +where + Dst: TransmuteFrom + TryTransmuteFromPtr, +{ +} + +/// Denotes that any `SV`-valid `Src` may soundly be transmuted into a +/// `DV`-valid `Self`. +/// +/// # Safety +/// +/// Given `src: Ptr` and `dst: Ptr`, if the +/// referents of `src` and `dst` are the same size, then the set of bit patterns +/// allowed to appear in `src`'s referent must be a subset of the set allowed to +/// appear in `dst`'s referent. +/// +/// If the referents are not the same size, then `Dst: TransmuteFrom` conveys no safety guarantee. +pub unsafe trait TransmuteFrom {} + +/// # Safety +/// +/// `T` and `Self` must have the same vtable kind (`Sized`, slice DST, `dyn`, +/// etc) and have the same size. In particular: +/// - If `T: Sized` and `Self: Sized`, then their sizes must be equal +/// - If `T: ?Sized` and `Self: ?Sized`, then it must be the case that, given +/// any `t: PtrInner<'_, T>`, `>::cast_from_raw(t)` produces +/// a pointer which addresses the same number of bytes as `t`. *Note that it +/// is **not** guaranteed that an `as` cast preserves referent size: it may be +/// the case that `cast_from_raw` modifies the pointer's metadata in order to +/// preserve referent size, which an `as` cast does not do.* +pub unsafe trait SizeEq { + fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, Self>; +} + +// SAFETY: `T` trivially has the same size and vtable kind as `T`, and since +// pointer `*mut T -> *mut T` pointer casts are no-ops, this cast trivially +// preserves referent size (when `T: ?Sized`). +unsafe impl SizeEq for T { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, T> { + t + } +} + +// SAFETY: Since `Src: IntoBytes`, the set of valid `Src`'s is the set of +// initialized bit patterns, which is exactly the set allowed in the referent of +// any `Initialized` `Ptr`. +unsafe impl TransmuteFrom for Dst +where + Src: IntoBytes + ?Sized, + Dst: ?Sized, +{ +} + +// SAFETY: Since `Dst: FromBytes`, any initialized bit pattern may appear in the +// referent of a `Ptr`. This is exactly equal to the set of +// bit patterns which may appear in the referent of any `Initialized` `Ptr`. +unsafe impl TransmuteFrom for Dst +where + Src: ?Sized, + Dst: FromBytes + ?Sized, +{ +} + +// FIXME(#2354): This seems like a smell - the soundness of this bound has +// nothing to do with `Src` or `Dst` - we're basically just saying `[u8; N]` is +// transmutable into `[u8; N]`. + +// SAFETY: The set of allowed bit patterns in the referent of any `Initialized` +// `Ptr` is the same regardless of referent type. +unsafe impl TransmuteFrom for Dst +where + Src: ?Sized, + Dst: ?Sized, +{ +} + +// FIXME(#2354): This seems like a smell - the soundness of this bound has +// nothing to do with `Dst` - we're basically just saying that any type is +// transmutable into `MaybeUninit<[u8; N]>`. + +// SAFETY: A `Dst` with validity `Uninit` permits any byte sequence, and +// therefore can be transmuted from any value. +unsafe impl TransmuteFrom for Dst +where + Src: ?Sized, + Dst: ?Sized, + V: Validity, +{ +} + +// SAFETY: +// - `ManuallyDrop` has the same size as `T` [1] +// - `ManuallyDrop` has the same validity as `T` [1] +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +// `T` +const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => ManuallyDrop) }; + +// SAFETY: +// - `Unalign` promises to have the same size as `T`. +// - `Unalign` promises to have the same validity as `T`. +const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Unalign) }; +// SAFETY: `Unalign` promises to have the same size and validity as `T`. +// Given `u: &Unalign`, it is already possible to obtain `let t = +// u.try_deref().unwrap()`. Because `Unalign` has the same size as `T`, the +// returned `&T` must point to the same referent as `u`, and thus it must be +// sound for these two references to exist at the same time since it's already +// possible for safe code to get into this state. +const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign) }; + +// SAFETY: +// - `Wrapping` has the same size as `T` [1]. +// - `Wrapping` has only one field, which is `pub` [2]. We are also +// guaranteed per that `Wrapping` has the same layout as `T` [1]. The only +// way for both of these to be true simultaneously is for `Wrapping` to +// have the same bit validity as `T`. In particular, in order to change the +// bit validity, one of the following would need to happen: +// - `Wrapping` could change its `repr`, but this would violate the layout +// guarantee. +// - `Wrapping` could add or change its fields, but this would be a +// stability-breaking change. +// +// [1] Per https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html#layout-1: +// +// `Wrapping` is guaranteed to have the same layout and ABI as `T`. +// +// [2] Definition from https://doc.rust-lang.org/1.85.0/core/num/struct.Wrapping.html: +// +// ``` +// #[repr(transparent)] +// pub struct Wrapping(pub T); +// ``` +const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Wrapping) }; + +// SAFETY: By the preceding safety proof, `Wrapping` and `T` have the same +// layout and bit validity. Since a `Wrapping`'s `T` field is `pub`, given +// `w: &Wrapping`, it's possible to do `let t = &w.t`, which means that it's +// already possible for safe code to obtain a `&Wrapping` and a `&T` pointing +// to the same referent at the same time. Thus, this must be sound. +const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping) }; + +// SAFETY: +// - `UnsafeCell` has the same size as `T` [1]. +// - Per [1], `UnsafeCell` has the same bit validity as `T`. Technically the +// term "representation" doesn't guarantee this, but the subsequent sentence +// in the documentation makes it clear that this is the intention. +// +// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: +// +// `UnsafeCell` has the same in-memory representation as its inner type +// `T`. A consequence of this guarantee is that it is possible to convert +// between `T` and `UnsafeCell`. +const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeCell) }; + +// SAFETY: +// - `Cell` has the same size as `T` [1]. +// - Per [1], `Cell` has the same bit validity as `T`. Technically the term +// "representation" doesn't guarantee this, but it does promise to have the +// "same memory layout and caveats as `UnsafeCell`." The `UnsafeCell` docs +// [2] make it clear that bit validity is the intention even if that phrase +// isn't used. +// +// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.Cell.html#memory-layout: +// +// `Cell` has the same memory layout and caveats as `UnsafeCell`. In +// particular, this means that `Cell` has the same in-memory representation +// as its inner type `T`. +// +// [2] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: +// +// `UnsafeCell` has the same in-memory representation as its inner type +// `T`. A consequence of this guarantee is that it is possible to convert +// between `T` and `UnsafeCell`. +const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => Cell) }; + +impl_transitive_transmute_from!(T: ?Sized => Cell => T => UnsafeCell); +impl_transitive_transmute_from!(T: ?Sized => UnsafeCell => T => Cell); + +// SAFETY: `MaybeUninit` has no validity requirements. Currently this is not +// explicitly guaranteed, but it's obvious from `MaybeUninit`'s documentation +// that this is the intention: +// https://doc.rust-lang.org/1.85.0/core/mem/union.MaybeUninit.html +unsafe impl TransmuteFrom for MaybeUninit {} + +// SAFETY: `MaybeUninit` has the same size as `T` [1]. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: +// +// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as +// `T` +unsafe impl SizeEq for MaybeUninit { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, MaybeUninit> { + // SAFETY: Per preceding safety comment, `MaybeUninit` and `T` have + // the same size, and so this cast preserves referent size. + unsafe { cast!(t) } + } +} + +// SAFETY: See previous safety comment. +unsafe impl SizeEq> for T { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, MaybeUninit>) -> PtrInner<'_, T> { + // SAFETY: Per preceding safety comment, `MaybeUninit` and `T` have + // the same size, and so this cast preserves referent size. + unsafe { cast!(t) } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/ref.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/ref.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/ref.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/ref.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1175 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use super::*; + +mod def { + use core::marker::PhantomData; + + use crate::{ + ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, + IntoByteSliceMut, + }; + + /// A typed reference derived from a byte slice. + /// + /// A `Ref` is a reference to a `T` which is stored in a byte slice, `B`. + /// Unlike a native reference (`&T` or `&mut T`), `Ref` has the same + /// mutability as the byte slice it was constructed from (`B`). + /// + /// # Examples + /// + /// `Ref` can be used to treat a sequence of bytes as a structured type, and + /// to read and write the fields of that type as if the byte slice reference + /// were simply a reference to that type. + /// + /// ```rust + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] + /// #[repr(C)] + /// struct UdpHeader { + /// src_port: [u8; 2], + /// dst_port: [u8; 2], + /// length: [u8; 2], + /// checksum: [u8; 2], + /// } + /// + /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] + /// #[repr(C, packed)] + /// struct UdpPacket { + /// header: UdpHeader, + /// body: [u8], + /// } + /// + /// impl UdpPacket { + /// pub fn parse(bytes: B) -> Option> { + /// Ref::from_bytes(bytes).ok() + /// } + /// } + /// ``` + pub struct Ref( + // INVARIANTS: The referent (via `.deref`, `.deref_mut`, `.into`) byte + // slice is aligned to `T`'s alignment and its size corresponds to a + // valid size for `T`. + B, + PhantomData, + ); + + impl Ref { + /// Constructs a new `Ref`. + /// + /// # Safety + /// + /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to + /// a byte slice which is aligned to `T`'s alignment and whose size is a + /// valid size for `T`. + /// + /// [`deref`]: core::ops::Deref::deref + /// [`deref_mut`]: core::ops::DerefMut::deref_mut + /// [`into`]: core::convert::Into::into + pub(crate) unsafe fn new_unchecked(bytes: B) -> Ref { + // INVARIANTS: The caller has promised that `bytes`'s referent is + // validly-aligned and has a valid size. + Ref(bytes, PhantomData) + } + } + + impl Ref { + /// Access the byte slice as a [`ByteSlice`]. + /// + /// # Safety + /// + /// The caller promises not to call methods on the returned + /// [`ByteSlice`] other than `ByteSlice` methods (for example, via + /// `Any::downcast_ref`). + /// + /// `as_byte_slice` promises to return a `ByteSlice` whose referent is + /// validly-aligned for `T` and has a valid size for `T`. + pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice { + // INVARIANTS: The caller promises not to call methods other than + // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability + // guarantees that calling `ByteSlice` methods will not change the + // address or length of `self.0`'s referent. + // + // SAFETY: By invariant on `self.0`, the alignment and size + // post-conditions are upheld. + &self.0 + } + } + + impl Ref { + /// Access the byte slice as a [`ByteSliceMut`]. + /// + /// # Safety + /// + /// The caller promises not to call methods on the returned + /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via + /// `Any::downcast_mut`). + /// + /// `as_byte_slice` promises to return a `ByteSlice` whose referent is + /// validly-aligned for `T` and has a valid size for `T`. + pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut { + // INVARIANTS: The caller promises not to call methods other than + // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference + // stability guarantees that calling `ByteSlice` methods will not + // change the address or length of `self.0`'s referent. + // + // SAFETY: By invariant on `self.0`, the alignment and size + // post-conditions are upheld. + &mut self.0 + } + } + + impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref { + /// Access the byte slice as an [`IntoByteSlice`]. + /// + /// # Safety + /// + /// The caller promises not to call methods on the returned + /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example, + /// via `Any::downcast_ref`). + /// + /// `as_byte_slice` promises to return a `ByteSlice` whose referent is + /// validly-aligned for `T` and has a valid size for `T`. + pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> { + // INVARIANTS: The caller promises not to call methods other than + // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference + // stability guarantees that calling `ByteSlice` methods will not + // change the address or length of `self.0`'s referent. + // + // SAFETY: By invariant on `self.0`, the alignment and size + // post-conditions are upheld. + self.0 + } + } + + impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref { + /// Access the byte slice as an [`IntoByteSliceMut`]. + /// + /// # Safety + /// + /// The caller promises not to call methods on the returned + /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for + /// example, via `Any::downcast_mut`). + /// + /// `as_byte_slice` promises to return a `ByteSlice` whose referent is + /// validly-aligned for `T` and has a valid size for `T`. + pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> { + // INVARIANTS: The caller promises not to call methods other than + // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference + // stability guarantees that calling `ByteSlice` methods will not + // change the address or length of `self.0`'s referent. + // + // SAFETY: By invariant on `self.0`, the alignment and size + // post-conditions are upheld. + self.0 + } + } + + impl Clone for Ref { + #[inline] + fn clone(&self) -> Ref { + // INVARIANTS: Since `B: CloneableByteSlice`, `self.0.clone()` has + // the same address and length as `self.0`. Since `self.0` upholds + // the field invariants, so does `self.0.clone()`. + Ref(self.0.clone(), PhantomData) + } + } + + // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `.0` has the + // same address and length as the original `Ref`'s `.0`. Since the original + // upholds the field invariants, so does the copy. + impl Copy for Ref {} +} + +#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. +pub use def::Ref; + +impl Ref +where + B: ByteSlice, +{ + #[must_use = "has no side effects"] + pub(crate) fn sized_from(bytes: B) -> Result, CastError> { + if bytes.len() != mem::size_of::() { + return Err(SizeError::new(bytes).into()); + } + if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { + return Err(err.with_src(bytes).into()); + } + + // SAFETY: We just validated size and alignment. + Ok(unsafe { Ref::new_unchecked(bytes) }) + } +} + +impl Ref +where + B: SplitByteSlice, +{ + #[must_use = "has no side effects"] + pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref, B), CastError> { + if bytes.len() < mem::size_of::() { + return Err(SizeError::new(bytes).into()); + } + if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { + return Err(err.with_src(bytes).into()); + } + let (bytes, suffix) = + bytes.split_at(mem::size_of::()).map_err(|b| SizeError::new(b).into())?; + // SAFETY: We just validated alignment and that `bytes` is at least as + // large as `T`. `bytes.split_at(mem::size_of::())?` ensures that the + // new `bytes` is exactly the size of `T`. By safety postcondition on + // `SplitByteSlice::split_at` we can rely on `split_at` to produce the + // correct `bytes` and `suffix`. + let r = unsafe { Ref::new_unchecked(bytes) }; + Ok((r, suffix)) + } + + #[must_use = "has no side effects"] + pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref), CastError> { + let bytes_len = bytes.len(); + let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::()) { + split_at + } else { + return Err(SizeError::new(bytes).into()); + }; + let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?; + if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { + return Err(err.with_src(bytes).into()); + } + // SAFETY: Since `split_at` is defined as `bytes_len - size_of::()`, + // the `bytes` which results from `let (prefix, bytes) = + // bytes.split_at(split_at)?` has length `size_of::()`. After + // constructing `bytes`, we validate that it has the proper alignment. + // By safety postcondition on `SplitByteSlice::split_at` we can rely on + // `split_at` to produce the correct `prefix` and `bytes`. + let r = unsafe { Ref::new_unchecked(bytes) }; + Ok((prefix, r)) + } +} + +impl Ref +where + B: ByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + /// Constructs a `Ref` from a byte slice. + /// + /// If the length of `source` is not a [valid size of `T`][valid-size], or + /// if `source` is not appropriately aligned for `T`, this returns `Err`. If + /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error! + /// ``` + #[must_use = "has no side effects"] + #[inline] + pub fn from_bytes(source: B) -> Result, CastError> { + static_assert_dst_is_not_zst!(T); + if let Err(e) = + Ptr::from_ref(source.deref()).try_cast_into_no_leftover::(None) + { + return Err(e.with_src(()).with_src(source)); + } + // SAFETY: `try_cast_into_no_leftover` validates size and alignment. + Ok(unsafe { Ref::new_unchecked(source) }) + } +} + +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + /// Constructs a `Ref` from the prefix of a byte slice. + /// + /// This method computes the [largest possible size of `T`][valid-size] that + /// can fit in the leading bytes of `source`, then attempts to return both a + /// `Ref` to those bytes, and a reference to the remaining bytes. If there + /// are insufficient bytes, or if `source` is not appropriately aligned, + /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can + /// [infallibly discard the alignment error][size-error-from]. + /// + /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error! + /// ``` + #[must_use = "has no side effects"] + #[inline] + pub fn from_prefix(source: B) -> Result<(Ref, B), CastError> { + static_assert_dst_is_not_zst!(T); + let remainder = match Ptr::from_ref(source.deref()) + .try_cast_into::(CastType::Prefix, None) + { + Ok((_, remainder)) => remainder, + Err(e) => { + return Err(e.with_src(()).with_src(source)); + } + }; + + // SAFETY: `remainder` is constructed as a subset of `source`, and so it + // cannot have a larger size than `source`. Both of their `len` methods + // measure bytes (`source` deref's to `[u8]`, and `remainder` is a + // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot + // underflow. + #[allow(unstable_name_collisions)] + let split_at = unsafe { source.len().unchecked_sub(remainder.len()) }; + let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; + // SAFETY: `try_cast_into` validates size and alignment, and returns a + // `split_at` that indicates how many bytes of `source` correspond to a + // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we + // can rely on `split_at` to produce the correct `source` and `suffix`. + let r = unsafe { Ref::new_unchecked(bytes) }; + Ok((r, suffix)) + } + + /// Constructs a `Ref` from the suffix of a byte slice. + /// + /// This method computes the [largest possible size of `T`][valid-size] that + /// can fit in the trailing bytes of `source`, then attempts to return both + /// a `Ref` to those bytes, and a reference to the preceding bytes. If there + /// are insufficient bytes, or if that suffix of `source` is not + /// appropriately aligned, this returns `Err`. If [`T: + /// Unaligned`][t-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. + /// + /// [valid-size]: crate::KnownLayout#what-is-a-valid-size + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// [slice-dst]: KnownLayout#dynamically-sized-types + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error! + /// ``` + #[must_use = "has no side effects"] + #[inline] + pub fn from_suffix(source: B) -> Result<(B, Ref), CastError> { + static_assert_dst_is_not_zst!(T); + let remainder = match Ptr::from_ref(source.deref()) + .try_cast_into::(CastType::Suffix, None) + { + Ok((_, remainder)) => remainder, + Err(e) => { + let e = e.with_src(()); + return Err(e.with_src(source)); + } + }; + + let split_at = remainder.len(); + let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; + // SAFETY: `try_cast_into` validates size and alignment, and returns a + // `split_at` that indicates how many bytes of `source` correspond to a + // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we + // can rely on `split_at` to produce the correct `prefix` and `bytes`. + let r = unsafe { Ref::new_unchecked(bytes) }; + Ok((prefix, r)) + } +} + +impl Ref +where + B: ByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + /// Constructs a `Ref` from the given bytes with DST length equal to `count` + /// without copying. + /// + /// This method attempts to return a `Ref` to the prefix of `source` + /// interpreted as a `T` with `count` trailing elements, and a reference to + /// the remaining bytes. If the length of `source` is not equal to the size + /// of `Self` with `count` elements, or if `source` is not appropriately + /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can + /// [infallibly discard the alignment error][size-error-from]. + /// + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! + /// ``` + #[inline] + pub fn from_bytes_with_elems(source: B, count: usize) -> Result, CastError> { + static_assert_dst_is_not_zst!(T); + let expected_len = match T::size_for_metadata(count) { + Some(len) => len, + None => return Err(SizeError::new(source).into()), + }; + if source.len() != expected_len { + return Err(SizeError::new(source).into()); + } + Self::from_bytes(source) + } +} + +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + Immutable + ?Sized, +{ + /// Constructs a `Ref` from the prefix of the given bytes with DST + /// length equal to `count` without copying. + /// + /// This method attempts to return a `Ref` to the prefix of `source` + /// interpreted as a `T` with `count` trailing elements, and a reference to + /// the remaining bytes. If there are insufficient bytes, or if `source` is + /// not appropriately aligned, this returns `Err`. If [`T: + /// Unaligned`][t-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! + /// ``` + #[inline] + pub fn from_prefix_with_elems( + source: B, + count: usize, + ) -> Result<(Ref, B), CastError> { + static_assert_dst_is_not_zst!(T); + let expected_len = match T::size_for_metadata(count) { + Some(len) => len, + None => return Err(SizeError::new(source).into()), + }; + let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?; + Self::from_bytes(prefix).map(move |l| (l, bytes)) + } + + /// Constructs a `Ref` from the suffix of the given bytes with DST length + /// equal to `count` without copying. + /// + /// This method attempts to return a `Ref` to the suffix of `source` + /// interpreted as a `T` with `count` trailing elements, and a reference to + /// the preceding bytes. If there are insufficient bytes, or if that suffix + /// of `source` is not appropriately aligned, this returns `Err`. If [`T: + /// Unaligned`][t-unaligned], you can [infallibly discard the alignment + /// error][size-error-from]. + /// + /// [t-unaligned]: Unaligned + /// [size-error-from]: error/struct.SizeError.html#method.from-1 + /// + /// # Compile-Time Assertions + /// + /// This method cannot yet be used on unsized types whose dynamically-sized + /// component is zero-sized. Attempting to use this method on such types + /// results in a compile-time assertion error; e.g.: + /// + /// ```compile_fail,E0080 + /// use zerocopy::*; + /// # use zerocopy_derive::*; + /// + /// #[derive(Immutable, KnownLayout)] + /// #[repr(C)] + /// struct ZSTy { + /// leading_sized: u16, + /// trailing_dst: [()], + /// } + /// + /// let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! + /// ``` + #[inline] + pub fn from_suffix_with_elems( + source: B, + count: usize, + ) -> Result<(B, Ref), CastError> { + static_assert_dst_is_not_zst!(T); + let expected_len = match T::size_for_metadata(count) { + Some(len) => len, + None => return Err(SizeError::new(source).into()), + }; + let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) { + split_at + } else { + return Err(SizeError::new(source).into()); + }; + // SAFETY: The preceding `source.len().checked_sub(expected_len)` + // guarantees that `split_at` is in-bounds. + let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) }; + Self::from_bytes(suffix).map(move |l| (bytes, l)) + } +} + +impl<'a, B, T> Ref +where + B: 'a + IntoByteSlice<'a>, + T: FromBytes + KnownLayout + Immutable + ?Sized, +{ + /// Converts this `Ref` into a reference. + /// + /// `into_ref` consumes the `Ref`, and returns a reference to `T`. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that + /// there is no conflict with a method on the inner type. + #[must_use = "has no side effects"] + #[inline(always)] + pub fn into_ref(r: Self) -> &'a T { + // Presumably unreachable, since we've guarded each constructor of `Ref`. + static_assert_dst_is_not_zst!(T); + + // SAFETY: We don't call any methods on `b` other than those provided by + // `IntoByteSlice`. + let b = unsafe { r.into_byte_slice() }; + + // PANICS: By post-condition on `into_byte_slice`, `b`'s size and + // alignment are valid for `T`. By post-condition, `b.into_byte_slice()` + // produces a byte slice with identical address and length to that + // produced by `b.deref()`. + let ptr = Ptr::from_ref(b.into_byte_slice()) + .try_cast_into_no_leftover::(None) + .expect("zerocopy internal error: into_ref should be infallible"); + let ptr = ptr.recall_validity(); + ptr.as_ref() + } +} + +impl<'a, B, T> Ref +where + B: 'a + IntoByteSliceMut<'a>, + T: FromBytes + IntoBytes + KnownLayout + ?Sized, +{ + /// Converts this `Ref` into a mutable reference. + /// + /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that + /// there is no conflict with a method on the inner type. + #[must_use = "has no side effects"] + #[inline(always)] + pub fn into_mut(r: Self) -> &'a mut T { + // Presumably unreachable, since we've guarded each constructor of `Ref`. + static_assert_dst_is_not_zst!(T); + + // SAFETY: We don't call any methods on `b` other than those provided by + // `IntoByteSliceMut`. + let b = unsafe { r.into_byte_slice_mut() }; + + // PANICS: By post-condition on `into_byte_slice_mut`, `b`'s size and + // alignment are valid for `T`. By post-condition, + // `b.into_byte_slice_mut()` produces a byte slice with identical + // address and length to that produced by `b.deref_mut()`. + let ptr = Ptr::from_mut(b.into_byte_slice_mut()) + .try_cast_into_no_leftover::(None) + .expect("zerocopy internal error: into_ref should be infallible"); + let ptr = ptr.recall_validity::<_, (_, (_, _))>(); + ptr.as_mut() + } +} + +impl Ref +where + B: ByteSlice, + T: ?Sized, +{ + /// Gets the underlying bytes. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is + /// no conflict with a method on the inner type. + #[inline] + pub fn bytes(r: &Self) -> &[u8] { + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSlice`. + unsafe { r.as_byte_slice().deref() } + } +} + +impl Ref +where + B: ByteSliceMut, + T: ?Sized, +{ + /// Gets the underlying bytes mutably. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that + /// there is no conflict with a method on the inner type. + #[inline] + pub fn bytes_mut(r: &mut Self) -> &mut [u8] { + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSliceMut`. + unsafe { r.as_byte_slice_mut().deref_mut() } + } +} + +impl Ref +where + B: ByteSlice, + T: FromBytes, +{ + /// Reads a copy of `T`. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no + /// conflict with a method on the inner type. + #[must_use = "has no side effects"] + #[inline] + pub fn read(r: &Self) -> T { + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSlice`. + let b = unsafe { r.as_byte_slice() }; + + // SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a + // valid size and ailgnment for `T`. By safety invariant on `ByteSlice`, + // we know that this is preserved via `.deref()`. Because `T: + // FromBytes`, it is sound to interpret these bytes as a `T`. + unsafe { ptr::read(b.deref().as_ptr().cast::()) } + } +} + +impl Ref +where + B: ByteSliceMut, + T: IntoBytes, +{ + /// Writes the bytes of `t` and then forgets `t`. + /// + /// Note: this is an associated function, which means that you have to call + /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there + /// is no conflict with a method on the inner type. + #[inline] + pub fn write(r: &mut Self, t: T) { + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSliceMut`. + let b = unsafe { r.as_byte_slice_mut() }; + + // SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is + // a valid size and ailgnment for `T`. By safety invariant on + // `ByteSlice`, we know that this is preserved via `.deref()`. Writing + // `t` to the buffer will allow all of the bytes of `t` to be accessed + // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound. + unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::(), t) } + } +} + +impl Deref for Ref +where + B: ByteSlice, + T: FromBytes + KnownLayout + Immutable + ?Sized, +{ + type Target = T; + #[inline] + fn deref(&self) -> &T { + // Presumably unreachable, since we've guarded each constructor of `Ref`. + static_assert_dst_is_not_zst!(T); + + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSlice`. + let b = unsafe { self.as_byte_slice() }; + + // PANICS: By postcondition on `as_byte_slice`, `b`'s size and alignment + // are valid for `T`, and by invariant on `ByteSlice`, these are + // preserved through `.deref()`, so this `unwrap` will not panic. + let ptr = Ptr::from_ref(b.deref()) + .try_cast_into_no_leftover::(None) + .expect("zerocopy internal error: Deref::deref should be infallible"); + let ptr = ptr.recall_validity(); + ptr.as_ref() + } +} + +impl DerefMut for Ref +where + B: ByteSliceMut, + // FIXME(#251): We can't remove `Immutable` here because it's required by + // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can + // add a separate inherent method for this? + T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn deref_mut(&mut self) -> &mut T { + // Presumably unreachable, since we've guarded each constructor of `Ref`. + static_assert_dst_is_not_zst!(T); + + // SAFETY: We don't call any methods on `b` other than those provided by + // `ByteSliceMut`. + let b = unsafe { self.as_byte_slice_mut() }; + + // PANICS: By postcondition on `as_byte_slice_mut`, `b`'s size and + // alignment are valid for `T`, and by invariant on `ByteSlice`, these + // are preserved through `.deref_mut()`, so this `unwrap` will not + // panic. + let ptr = Ptr::from_mut(b.deref_mut()) + .try_cast_into_no_leftover::(None) + .expect("zerocopy internal error: DerefMut::deref_mut should be infallible"); + let ptr = ptr.recall_validity::<_, (_, (_, (BecauseExclusive, BecauseExclusive)))>(); + ptr.as_mut() + } +} + +impl Display for Ref +where + B: ByteSlice, + T: FromBytes + Display + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + let inner: &T = self; + inner.fmt(fmt) + } +} + +impl Debug for Ref +where + B: ByteSlice, + T: FromBytes + Debug + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + let inner: &T = self; + fmt.debug_tuple("Ref").field(&inner).finish() + } +} + +impl Eq for Ref +where + B: ByteSlice, + T: FromBytes + Eq + KnownLayout + Immutable + ?Sized, +{ +} + +impl PartialEq for Ref +where + B: ByteSlice, + T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.deref().eq(other.deref()) + } +} + +impl Ord for Ref +where + B: ByteSlice, + T: FromBytes + Ord + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + let inner: &T = self; + let other_inner: &T = other; + inner.cmp(other_inner) + } +} + +impl PartialOrd for Ref +where + B: ByteSlice, + T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + let inner: &T = self; + let other_inner: &T = other; + inner.partial_cmp(other_inner) + } +} + +#[cfg(test)] +#[allow(clippy::assertions_on_result_states)] +mod tests { + use core::convert::TryInto as _; + + use super::*; + use crate::util::testutil::*; + + #[test] + fn test_mut_slice_into_ref() { + // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed + // `Ref` was not supported. + let mut buf = [0u8]; + let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap(); + assert_eq!(Ref::into_ref(r), &0); + } + + #[test] + fn test_address() { + // Test that the `Deref` and `DerefMut` implementations return a + // reference which points to the right region of memory. + + let buf = [0]; + let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap(); + let buf_ptr = buf.as_ptr(); + let deref_ptr: *const u8 = r.deref(); + assert_eq!(buf_ptr, deref_ptr); + + let buf = [0]; + let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap(); + let buf_ptr = buf.as_ptr(); + let deref_ptr = r.deref().as_ptr(); + assert_eq!(buf_ptr, deref_ptr); + } + + // Verify that values written to a `Ref` are properly shared between the + // typed and untyped representations, that reads via `deref` and `read` + // behave the same, and that writes via `deref_mut` and `write` behave the + // same. + fn test_new_helper(mut r: Ref<&mut [u8], AU64>) { + // assert that the value starts at 0 + assert_eq!(*r, AU64(0)); + assert_eq!(Ref::read(&r), AU64(0)); + + // Assert that values written to the typed value are reflected in the + // byte slice. + const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); + *r = VAL1; + assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); + *r = AU64(0); + Ref::write(&mut r, VAL1); + assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); + + // Assert that values written to the byte slice are reflected in the + // typed value. + const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1` + Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]); + assert_eq!(*r, VAL2); + assert_eq!(Ref::read(&r), VAL2); + } + + // Verify that values written to a `Ref` are properly shared between the + // typed and untyped representations; pass a value with `typed_len` `AU64`s + // backed by an array of `typed_len * 8` bytes. + fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) { + // Assert that the value starts out zeroed. + assert_eq!(&*r, vec![AU64(0); typed_len].as_slice()); + + // Check the backing storage is the exact same slice. + let untyped_len = typed_len * 8; + assert_eq!(Ref::bytes(&r).len(), untyped_len); + assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::()); + + // Assert that values written to the typed value are reflected in the + // byte slice. + const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); + for typed in &mut *r { + *typed = VAL1; + } + assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice()); + + // Assert that values written to the byte slice are reflected in the + // typed value. + const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1 + Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len)); + assert!(r.iter().copied().all(|x| x == VAL2)); + } + + #[test] + fn test_new_aligned_sized() { + // Test that a properly-aligned, properly-sized buffer works for new, + // new_from_prefix, and new_from_suffix, and that new_from_prefix and + // new_from_suffix return empty slices. Test that a properly-aligned + // buffer whose length is a multiple of the element size works for + // new_slice. + + // A buffer with an alignment of 8. + let mut buf = Align::<[u8; 8], AU64>::default(); + // `buf.t` should be aligned to 8, so this should always succeed. + test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap()); + { + // In a block so that `r` and `suffix` don't live too long. + buf.set_default(); + let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); + assert!(suffix.is_empty()); + test_new_helper(r); + } + { + buf.set_default(); + let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); + assert!(prefix.is_empty()); + test_new_helper(r); + } + + // A buffer with alignment 8 and length 24. We choose this length very + // intentionally: if we instead used length 16, then the prefix and + // suffix lengths would be identical. In the past, we used length 16, + // which resulted in this test failing to discover the bug uncovered in + // #506. + let mut buf = Align::<[u8; 24], AU64>::default(); + // `buf.t` should be aligned to 8 and have a length which is a multiple + // of `size_of::()`, so this should always succeed. + test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3); + buf.set_default(); + let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap(); + test_new_helper_slice(r, 3); + + let ascending: [u8; 24] = (0..24).collect::>().try_into().unwrap(); + // 16 ascending bytes followed by 8 zeros. + let mut ascending_prefix = ascending; + ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); + // 8 zeros followed by 16 ascending bytes. + let mut ascending_suffix = ascending; + ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); + { + buf.t = ascending_suffix; + let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap(); + assert_eq!(suffix, &ascending[8..]); + test_new_helper_slice(r, 1); + } + { + buf.t = ascending_prefix; + let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap(); + assert_eq!(prefix, &ascending[..16]); + test_new_helper_slice(r, 1); + } + } + + #[test] + fn test_new_oversized() { + // Test that a properly-aligned, overly-sized buffer works for + // `new_from_prefix` and `new_from_suffix`, and that they return the + // remainder and prefix of the slice respectively. + + let mut buf = Align::<[u8; 16], AU64>::default(); + { + // In a block so that `r` and `suffix` don't live too long. `buf.t` + // should be aligned to 8, so this should always succeed. + let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); + assert_eq!(suffix.len(), 8); + test_new_helper(r); + } + { + buf.set_default(); + // `buf.t` should be aligned to 8, so this should always succeed. + let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); + assert_eq!(prefix.len(), 8); + test_new_helper(r); + } + } + + #[test] + #[allow(clippy::cognitive_complexity)] + fn test_new_error() { + // Fail because the buffer is too large. + + // A buffer with an alignment of 8. + let buf = Align::<[u8; 16], AU64>::default(); + // `buf.t` should be aligned to 8, so only the length check should fail. + assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); + + // Fail because the buffer is too small. + + // A buffer with an alignment of 8. + let buf = Align::<[u8; 4], AU64>::default(); + // `buf.t` should be aligned to 8, so only the length check should fail. + assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); + assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err()); + assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); + + // Fail because the length is not a multiple of the element size. + + let buf = Align::<[u8; 12], AU64>::default(); + // `buf.t` has length 12, but element size is 8. + assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err()); + + // Fail because the buffer is too short. + let buf = Align::<[u8; 12], AU64>::default(); + // `buf.t` has length 12, but the element size is 8 (and we're expecting + // two of them). For each function, we test with a length that would + // cause the size to overflow `usize`, and with a normal length that + // will fail thanks to the buffer being too short; these are different + // error paths, and while the error types are the same, the distinction + // shows up in code coverage metrics. + let n = (usize::MAX / mem::size_of::()) + 1; + assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err()); + assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err()); + assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err()); + assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err()); + assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err()); + assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err()); + + // Fail because the alignment is insufficient. + + // A buffer with an alignment of 8. An odd buffer size is chosen so that + // the last byte of the buffer has odd alignment. + let buf = Align::<[u8; 13], AU64>::default(); + // Slicing from 1, we get a buffer with size 12 (so the length check + // should succeed) but an alignment of only 1, which is insufficient. + assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err()); + assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err()); + assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err()); + assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err()); + assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err()); + assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err()); + // Slicing is unnecessary here because `new_from_suffix` uses the suffix + // of the slice, which has odd alignment. + assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); + + // Fail due to arithmetic overflow. + + let buf = Align::<[u8; 16], AU64>::default(); + let unreasonable_len = usize::MAX / mem::size_of::() + 1; + assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err()); + assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err()); + } + + #[test] + #[allow(unstable_name_collisions)] + #[allow(clippy::as_conversions)] + fn test_into_ref_mut() { + #[allow(unused)] + use crate::util::AsAddress as _; + + let mut buf = Align::<[u8; 8], u64>::default(); + let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); + let rf = Ref::into_ref(r); + assert_eq!(rf, &0u64); + let buf_addr = (&buf.t as *const [u8; 8]).addr(); + assert_eq!((rf as *const u64).addr(), buf_addr); + + let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap(); + let rf = Ref::into_mut(r); + assert_eq!(rf, &mut 0u64); + assert_eq!((rf as *mut u64).addr(), buf_addr); + + *rf = u64::MAX; + assert_eq!(buf.t, [0xFF; 8]); + } + + #[test] + fn test_display_debug() { + let buf = Align::<[u8; 8], u64>::default(); + let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); + assert_eq!(format!("{}", r), "0"); + assert_eq!(format!("{:?}", r), "Ref(0)"); + + let buf = Align::<[u8; 8], u64>::default(); + let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap(); + assert_eq!(format!("{:?}", r), "Ref([0])"); + } + + #[test] + fn test_eq() { + let buf1 = 0_u64; + let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); + let buf2 = 0_u64; + let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); + assert_eq!(r1, r2); + } + + #[test] + fn test_ne() { + let buf1 = 0_u64; + let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); + let buf2 = 1_u64; + let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); + assert_ne!(r1, r2); + } + + #[test] + fn test_ord() { + let buf1 = 0_u64; + let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); + let buf2 = 1_u64; + let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); + assert!(r1 < r2); + assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less)); + assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/split_at.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/split_at.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/split_at.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/split_at.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,904 @@ +// Copyright 2025 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use super::*; +use crate::pointer::invariant::{Aligned, Exclusive, Invariants, Shared, Valid}; + +/// Types that can be split in two. +/// +/// This trait generalizes Rust's existing support for splitting slices to +/// support slices and slice-based dynamically-sized types ("slice DSTs"). +/// +/// # Implementation +/// +/// **Do not implement this trait yourself!** Instead, use +/// [`#[derive(SplitAt)]`][derive]; e.g.: +/// +/// ``` +/// # use zerocopy_derive::{SplitAt, KnownLayout}; +/// #[derive(SplitAt, KnownLayout)] +/// #[repr(C)] +/// struct MyStruct { +/// # /* +/// ..., +/// # */ +/// // `SplitAt` types must have at least one field. +/// field: T, +/// } +/// ``` +/// +/// This derive performs a sophisticated, compile-time safety analysis to +/// determine whether a type is `SplitAt`. +/// +/// # Safety +/// +/// This trait does not convey any safety guarantees to code outside this crate. +/// +/// You must not rely on the `#[doc(hidden)]` internals of `SplitAt`. Future +/// releases of zerocopy may make backwards-breaking changes to these items, +/// including changes that only affect soundness, which may cause code which +/// uses those items to silently become unsound. +/// +#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::SplitAt")] +#[cfg_attr( + not(feature = "derive"), + doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.SplitAt.html"), +)] +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented(note = "Consider adding `#[derive(SplitAt)]` to `{Self}`") +)] +// # Safety +// +// The trailing slice is well-aligned for its element type. `Self` is `[T]`, or +// a `repr(C)` or `repr(transparent)` slice DST. +pub unsafe trait SplitAt: KnownLayout { + /// The element type of the trailing slice. + type Elem; + + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + /// Unsafely splits `self` in two. + /// + /// # Safety + /// + /// The caller promises that `l_len` is not greater than the length of + /// `self`'s trailing slice. + #[inline] + #[must_use] + unsafe fn split_at_unchecked(&self, l_len: usize) -> Split<&Self> { + // SAFETY: By precondition on the caller, `l_len <= self.len()`. + unsafe { Split::<&Self>::new(self, l_len) } + } + + /// Attempts to split `self` in two. + /// + /// Returns `None` if `l_len` is greater than the length of `self`'s + /// trailing slice. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: [u8], + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at(packet.length as usize).unwrap(); + /// + /// // Use the `Immutable` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_immutable(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// ``` + #[inline] + #[must_use = "has no side effects"] + fn split_at(&self, l_len: usize) -> Option> { + MetadataOf::new_in_bounds(self, l_len).map( + #[inline(always)] + |l_len| { + // SAFETY: We have ensured that `l_len <= self.len()` (by + // post-condition on `MetadataOf::new_in_bounds`) + unsafe { Split::new(self, l_len.get()) } + }, + ) + } + + /// Unsafely splits `self` in two. + /// + /// # Safety + /// + /// The caller promises that `l_len` is not greater than the length of + /// `self`'s trailing slice. + #[inline] + #[must_use] + unsafe fn split_at_mut_unchecked(&mut self, l_len: usize) -> Split<&mut Self> { + // SAFETY: By precondition on the caller, `l_len <= self.len()`. + unsafe { Split::<&mut Self>::new(self, l_len) } + } + + /// Attempts to split `self` in two. + /// + /// Returns `None` if `l_len` is greater than the length of `self`'s + /// trailing slice, or if the given `l_len` would result in [the trailing + /// padding](KnownLayout#slice-dst-layout) of the left portion overlapping + /// the right portion. + /// + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: B, + /// } + /// + /// // These bytes encode a `Packet`. + /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// { + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at_mut(packet.length as usize).unwrap(); + /// + /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_into_bytes(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// + /// rest.fill(0); + /// } + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); + /// ``` + #[inline] + fn split_at_mut(&mut self, l_len: usize) -> Option> { + MetadataOf::new_in_bounds(self, l_len).map( + #[inline(always)] + |l_len| { + // SAFETY: We have ensured that `l_len <= self.len()` (by + // post-condition on `MetadataOf::new_in_bounds`) + unsafe { Split::new(self, l_len.get()) } + }, + ) + } +} + +// SAFETY: `[T]`'s trailing slice is `[T]`, which is trivially aligned. +unsafe impl SplitAt for [T] { + type Elem = T; + + #[inline] + #[allow(dead_code)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + } +} + +/// A `T` that has been split into two possibly-overlapping parts. +/// +/// For some dynamically sized types, the padding that appears after the +/// trailing slice field [is a dynamic function of the trailing slice +/// length](KnownLayout#slice-dst-layout). If `T` is split at a length that +/// requires trailing padding, the trailing padding of the left part of the +/// split `T` will overlap the right part. If `T` is a mutable reference or +/// permits interior mutation, you must ensure that the left and right parts do +/// not overlap. You can do this at zero-cost using using +/// [`Self::via_immutable`], [`Self::via_into_bytes`], or +/// [`Self::via_unaligned`], or with a dynamic check by using +/// [`Self::via_runtime_check`]. +#[derive(Debug)] +pub struct Split { + /// A pointer to the source slice DST. + source: T, + /// The length of the future left half of `source`. + /// + /// # Safety + /// + /// If `source` is a pointer to a slice DST, `l_len` is no greater than + /// `source`'s length. + l_len: usize, +} + +impl Split { + /// Produces a `Split` of `source` with `l_len`. + /// + /// # Safety + /// + /// `l_len` is no greater than `source`'s length. + #[inline(always)] + unsafe fn new(source: T, l_len: usize) -> Self { + Self { source, l_len } + } +} + +impl<'a, T> Split<&'a T> +where + T: ?Sized + SplitAt, +{ + #[inline(always)] + fn into_ptr(self) -> Split> { + let source = Ptr::from_ref(self.source); + // SAFETY: `Ptr::from_ref(self.source)` points to exactly `self.source` + // and thus maintains the invariants of `self` with respect to `l_len`. + unsafe { Split::new(source, self.l_len) } + } + + /// Produces the split parts of `self`, using [`Immutable`] to ensure that + /// it is sound to have concurrent references to both parts. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: [u8], + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at(packet.length as usize).unwrap(); + /// + /// // Use the `Immutable` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_immutable(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_immutable(self) -> (&'a T, &'a [T::Elem]) + where + T: Immutable, + { + let (l, r) = self.into_ptr().via_immutable(); + (l.as_ref(), r.as_ref()) + } + + /// Produces the split parts of `self`, using [`IntoBytes`] to ensure that + /// it is sound to have concurrent references to both parts. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, IntoBytes)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: B, + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::<[u8]>::ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at(packet.length as usize).unwrap(); + /// + /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_into_bytes(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_into_bytes(self) -> (&'a T, &'a [T::Elem]) + where + T: IntoBytes, + { + let (l, r) = self.into_ptr().via_into_bytes(); + (l.as_ref(), r.as_ref()) + } + + /// Produces the split parts of `self`, using [`Unaligned`] to ensure that + /// it is sound to have concurrent references to both parts. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Unaligned)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: [u8], + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::ref_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at(packet.length as usize).unwrap(); + /// + /// // Use the `Unaligned` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_unaligned(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_unaligned(self) -> (&'a T, &'a [T::Elem]) + where + T: Unaligned, + { + let (l, r) = self.into_ptr().via_unaligned(); + (l.as_ref(), r.as_ref()) + } + + /// Produces the split parts of `self`, using a dynamic check to ensure that + /// it is sound to have concurrent references to both parts. You should + /// prefer using [`Self::via_immutable`], [`Self::via_into_bytes`], or + /// [`Self::via_unaligned`], which have no runtime cost. + /// + /// Note that this check is overly conservative if `T` is [`Immutable`]; for + /// some types, this check will reject some splits which + /// [`Self::via_immutable`] will accept. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes, IntoBytes, network_endian::U16}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Debug)] + /// #[repr(C, align(2))] + /// struct Packet { + /// length: U16, + /// body: [u8], + /// } + /// + /// // These bytes encode a `Packet`. + /// let bytes = [ + /// 4u16.to_be(), + /// 1u16.to_be(), + /// 2u16.to_be(), + /// 3u16.to_be(), + /// 4u16.to_be() + /// ]; + /// + /// let packet = Packet::ref_from_bytes(bytes.as_bytes()).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [0, 1, 0, 2, 0, 3, 0, 4]); + /// + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at(packet.length.into()).unwrap(); + /// + /// // Use a dynamic check to prove that it's okay to return concurrent + /// // references to `packet` and `rest`. + /// let (packet, rest) = split.via_runtime_check().unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [0, 1, 0, 2]); + /// assert_eq!(rest, [0, 3, 0, 4]); + /// + /// // Attempt to split `packet` at `length - 1`. + /// let idx = packet.length.get() - 1; + /// let split = packet.split_at(idx as usize).unwrap(); + /// + /// // Attempt (and fail) to use a dynamic check to prove that it's okay + /// // to return concurrent references to `packet` and `rest`. Note that + /// // this is a case of `via_runtime_check` being overly conservative. + /// // Although the left and right parts indeed overlap, the `Immutable` + /// // bound ensures that concurrently referencing these overlapping + /// // parts is sound. + /// assert!(split.via_runtime_check().is_err()); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_runtime_check(self) -> Result<(&'a T, &'a [T::Elem]), Self> { + match self.into_ptr().via_runtime_check() { + Ok((l, r)) => Ok((l.as_ref(), r.as_ref())), + Err(s) => Err(s.into_ref()), + } + } + + /// Unsafely produces the split parts of `self`. + /// + /// # Safety + /// + /// If `T` permits interior mutation, the trailing padding bytes of the left + /// portion must not overlap the right portion. For some dynamically sized + /// types, the padding that appears after the trailing slice field [is a + /// dynamic function of the trailing slice + /// length](KnownLayout#slice-dst-layout). Thus, for some types, this + /// condition is dependent on the length of the left portion. + #[must_use = "has no side effects"] + #[inline(always)] + pub unsafe fn via_unchecked(self) -> (&'a T, &'a [T::Elem]) { + // SAFETY: The aliasing of `self.into_ptr()` is not `Exclusive`, but the + // caller has promised that if `T` permits interior mutation then the + // left and right portions of `self` split at `l_len` do not overlap. + let (l, r) = unsafe { self.into_ptr().via_unchecked() }; + (l.as_ref(), r.as_ref()) + } +} + +impl<'a, T> Split<&'a mut T> +where + T: ?Sized + SplitAt, +{ + #[inline(always)] + fn into_ptr(self) -> Split> { + let source = Ptr::from_mut(self.source); + // SAFETY: `Ptr::from_mut(self.source)` points to exactly `self.source`, + // and thus maintains the invariants of `self` with respect to `l_len`. + unsafe { Split::new(source, self.l_len) } + } + + /// Produces the split parts of `self`, using [`IntoBytes`] to ensure that + /// it is sound to have concurrent references to both parts. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: B, + /// } + /// + /// // These bytes encode a `Packet`. + /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// { + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at_mut(packet.length as usize).unwrap(); + /// + /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_into_bytes(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// + /// rest.fill(0); + /// } + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_into_bytes(self) -> (&'a mut T, &'a mut [T::Elem]) + where + T: IntoBytes, + { + let (l, r) = self.into_ptr().via_into_bytes(); + (l.as_mut(), r.as_mut()) + } + + /// Produces the split parts of `self`, using [`Unaligned`] to ensure that + /// it is sound to have concurrent references to both parts. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes, Unaligned)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: B, + /// } + /// + /// // These bytes encode a `Packet`. + /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// { + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at_mut(packet.length as usize).unwrap(); + /// + /// // Use the `Unaligned` bound on `Packet` to prove that it's okay to + /// // return concurrent references to `packet` and `rest`. + /// let (packet, rest) = split.via_unaligned(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// + /// rest.fill(0); + /// } + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_unaligned(self) -> (&'a mut T, &'a mut [T::Elem]) + where + T: Unaligned, + { + let (l, r) = self.into_ptr().via_unaligned(); + (l.as_mut(), r.as_mut()) + } + + /// Produces the split parts of `self`, using a dynamic check to ensure that + /// it is sound to have concurrent references to both parts. You should + /// prefer using [`Self::via_into_bytes`] or [`Self::via_unaligned`], which + /// have no runtime cost. + /// + /// # Examples + /// + /// ``` + /// use zerocopy::{SplitAt, FromBytes}; + /// # use zerocopy_derive::*; + /// + /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes, Debug)] + /// #[repr(C)] + /// struct Packet { + /// length: u8, + /// body: B, + /// } + /// + /// // These bytes encode a `Packet`. + /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; + /// + /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// { + /// // Attempt to split `packet` at `length`. + /// let split = packet.split_at_mut(packet.length as usize).unwrap(); + /// + /// // Use a dynamic check to prove that it's okay to return concurrent + /// // references to `packet` and `rest`. + /// let (packet, rest) = split.via_runtime_check().unwrap(); + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4]); + /// assert_eq!(rest, [5, 6, 7, 8, 9]); + /// + /// rest.fill(0); + /// } + /// + /// assert_eq!(packet.length, 4); + /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); + /// ``` + #[must_use = "has no side effects"] + #[inline(always)] + pub fn via_runtime_check(self) -> Result<(&'a mut T, &'a mut [T::Elem]), Self> { + match self.into_ptr().via_runtime_check() { + Ok((l, r)) => Ok((l.as_mut(), r.as_mut())), + Err(s) => Err(s.into_mut()), + } + } + + /// Unsafely produces the split parts of `self`. + /// + /// # Safety + /// + /// The trailing padding bytes of the left portion must not overlap the + /// right portion. For some dynamically sized types, the padding that + /// appears after the trailing slice field [is a dynamic function of the + /// trailing slice length](KnownLayout#slice-dst-layout). Thus, for some + /// types, this condition is dependent on the length of the left portion. + #[must_use = "has no side effects"] + #[inline(always)] + pub unsafe fn via_unchecked(self) -> (&'a mut T, &'a mut [T::Elem]) { + // SAFETY: The aliasing of `self.into_ptr()` is `Exclusive`, and the + // caller has promised that the left and right portions of `self` split + // at `l_len` do not overlap. + let (l, r) = unsafe { self.into_ptr().via_unchecked() }; + (l.as_mut(), r.as_mut()) + } +} + +impl<'a, T, I> Split> +where + T: ?Sized + SplitAt, + I: Invariants, +{ + fn into_ref(self) -> Split<&'a T> + where + I: Invariants, + { + // SAFETY: `self.source.as_ref()` points to exactly the same referent as + // `self.source` and thus maintains the invariants of `self` with + // respect to `l_len`. + unsafe { Split::new(self.source.as_ref(), self.l_len) } + } + + fn into_mut(self) -> Split<&'a mut T> + where + I: Invariants, + { + // SAFETY: `self.source.as_mut()` points to exactly the same referent as + // `self.source` and thus maintains the invariants of `self` with + // respect to `l_len`. + unsafe { Split::new(self.source.unify_invariants().as_mut(), self.l_len) } + } + + /// Produces the length of `self`'s left part. + #[inline(always)] + fn l_len(&self) -> MetadataOf { + // SAFETY: By invariant on `Split`, `self.l_len` is not greater than the + // length of `self.source`. + unsafe { MetadataOf::::new_unchecked(self.l_len) } + } + + /// Produces the split parts of `self`, using [`Immutable`] to ensure that + /// it is sound to have concurrent references to both parts. + #[inline(always)] + fn via_immutable(self) -> (Ptr<'a, T, I>, Ptr<'a, [T::Elem], I>) + where + T: Immutable, + I: Invariants, + { + // SAFETY: `Aliasing = Shared` and `T: Immutable`. + unsafe { self.via_unchecked() } + } + + /// Produces the split parts of `self`, using [`IntoBytes`] to ensure that + /// it is sound to have concurrent references to both parts. + #[inline(always)] + fn via_into_bytes(self) -> (Ptr<'a, T, I>, Ptr<'a, [T::Elem], I>) + where + T: IntoBytes, + { + // SAFETY: By `T: IntoBytes`, `T` has no padding for any length. + // Consequently, `T` can be split into non-overlapping parts at any + // index. + unsafe { self.via_unchecked() } + } + + /// Produces the split parts of `self`, using [`Unaligned`] to ensure that + /// it is sound to have concurrent references to both parts. + #[inline(always)] + fn via_unaligned(self) -> (Ptr<'a, T, I>, Ptr<'a, [T::Elem], I>) + where + T: Unaligned, + { + // SAFETY: By `T: SplitAt + Unaligned`, `T` is either a slice or a + // `repr(C)` or `repr(transparent)` slice DST that is well-aligned at + // any address and length. If `T` is a slice DST with alignment 1, + // `repr(C)` or `repr(transparent)` ensures that no padding is placed + // after the final element of the trailing slice. Consequently, `T` can + // be split into strictly non-overlapping parts any any index. + unsafe { self.via_unchecked() } + } + + /// Produces the split parts of `self`, using a dynamic check to ensure that + /// it is sound to have concurrent references to both parts. You should + /// prefer using [`Self::via_immutable`], [`Self::via_into_bytes`], or + /// [`Self::via_unaligned`], which have no runtime cost. + #[inline(always)] + fn via_runtime_check(self) -> Result<(Ptr<'a, T, I>, Ptr<'a, [T::Elem], I>), Self> { + let l_len = self.l_len(); + // FIXME(#1290): Once we require `KnownLayout` on all fields, add an + // `IS_IMMUTABLE` associated const, and add `T::IS_IMMUTABLE ||` to the + // below check. + if l_len.padding_needed_for() == 0 { + // SAFETY: By `T: SplitAt`, `T` is either `[T]`, or a `repr(C)` or + // `repr(transparent)` slice DST, for which the trailing padding + // needed to accommodate `l_len` trailing elements is + // `l_len.padding_needed_for()`. If no trailing padding is required, + // the left and right parts are strictly non-overlapping. + Ok(unsafe { self.via_unchecked() }) + } else { + Err(self) + } + } + + /// Unsafely produces the split parts of `self`. + /// + /// # Safety + /// + /// The caller promises that if `I::Aliasing` is [`Exclusive`] or `T` + /// permits interior mutation, then `l_len.padding_needed_for() == 0`. + #[inline(always)] + unsafe fn via_unchecked(self) -> (Ptr<'a, T, I>, Ptr<'a, [T::Elem], I>) { + let l_len = self.l_len(); + let inner = self.source.as_inner(); + + // SAFETY: By invariant on `Self::l_len`, `l_len` is not greater than + // the length of `inner`'s trailing slice. + let (left, right) = unsafe { inner.split_at_unchecked(l_len) }; + + // Lemma 0: `left` and `right` conform to the aliasing invariant + // `I::Aliasing`. Proof: If `I::Aliasing` is `Exclusive` or `T` permits + // interior mutation, the caller promises that `l_len.padding_needed_for() + // == 0`. Consequently, by post-condition on `PtrInner::split_at_unchecked`, + // there is no trailing padding after `left`'s final element that would + // overlap into `right`. If `I::Aliasing` is shared and `T` forbids interior + // mutation, then overlap between their referents is permissible. + + // SAFETY: + // 0. `left` conforms to the aliasing invariant of `I::Aliasing`, by Lemma 0. + // 1. `left` conforms to the alignment invariant of `I::Alignment, because + // the referents of `left` and `Self` have the same address and type + // (and, thus, alignment requirement). + // 2. `left` conforms to the validity invariant of `I::Validity`, neither + // the type nor bytes of `left`'s referent have been changed. + let left = unsafe { Ptr::from_inner(left) }; + + // SAFETY: + // 0. `right` conforms to the aliasing invariant of `I::Aliasing`, by Lemma + // 0. + // 1. `right` conforms to the alignment invariant of `I::Alignment, because + // if `ptr` with `I::Alignment = Aligned`, then by invariant on `T: + // SplitAt`, the trailing slice of `ptr` (from which `right` is derived) + // will also be well-aligned. + // 2. `right` conforms to the validity invariant of `I::Validity`, + // because `right: [T::Elem]` is derived from the trailing slice of + // `ptr`, which, by contract on `T: SplitAt::Elem`, has type + // `[T::Elem]`. The `left` part cannot be used to invalidate `right`, + // because the caller promises that if `I::Aliasing` is `Exclusive` + // or `T` permits interior mutation, then `l_len.padding_needed_for() + // == 0` and thus the parts will be non-overlapping. + let right = unsafe { Ptr::from_inner(right) }; + + (left, right) + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "derive")] + #[test] + fn test_split_at() { + use crate::{FromBytes, Immutable, IntoBytes, KnownLayout, SplitAt}; + + #[derive(FromBytes, KnownLayout, SplitAt, IntoBytes, Immutable, Debug)] + #[repr(C)] + struct SliceDst { + prefix: [u8; OFFSET], + trailing: [u8], + } + + #[allow(clippy::as_conversions)] + fn test_split_at() { + // Test `split_at` + let n: usize = BUFFER_SIZE - OFFSET; + let arr = [1; BUFFER_SIZE]; + let dst = SliceDst::::ref_from_bytes(&arr[..]).unwrap(); + for i in 0..=n { + let (l, r) = dst.split_at(i).unwrap().via_runtime_check().unwrap(); + let l_sum: u8 = l.trailing.iter().sum(); + let r_sum: u8 = r.iter().sum(); + assert_eq!(l_sum, i as u8); + assert_eq!(r_sum, (n - i) as u8); + assert_eq!(l_sum + r_sum, n as u8); + } + + // Test `split_at_mut` + let n: usize = BUFFER_SIZE - OFFSET; + let mut arr = [1; BUFFER_SIZE]; + let dst = SliceDst::::mut_from_bytes(&mut arr[..]).unwrap(); + for i in 0..=n { + let (l, r) = dst.split_at_mut(i).unwrap().via_runtime_check().unwrap(); + let l_sum: u8 = l.trailing.iter().sum(); + let r_sum: u8 = r.iter().sum(); + assert_eq!(l_sum, i as u8); + assert_eq!(r_sum, (n - i) as u8); + assert_eq!(l_sum + r_sum, n as u8); + } + } + + test_split_at::<0, 16>(); + test_split_at::<1, 17>(); + test_split_at::<2, 18>(); + } + + #[cfg(feature = "derive")] + #[test] + #[allow(clippy::as_conversions)] + fn test_split_at_overlapping() { + use crate::{FromBytes, Immutable, IntoBytes, KnownLayout, SplitAt}; + + #[derive(FromBytes, KnownLayout, SplitAt, Immutable)] + #[repr(C, align(2))] + struct SliceDst { + prefix: u8, + trailing: [u8], + } + + const N: usize = 16; + + let arr = [1u16; N]; + let dst = SliceDst::ref_from_bytes(arr.as_bytes()).unwrap(); + + for i in 0..N { + let split = dst.split_at(i).unwrap().via_runtime_check(); + if i % 2 == 1 { + assert!(split.is_ok()); + } else { + assert!(split.is_err()); + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/macro_util.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macro_util.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/macro_util.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macro_util.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1335 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Utilities used by macros and by `zerocopy-derive`. +//! +//! These are defined here `zerocopy` rather than in code generated by macros or +//! by `zerocopy-derive` so that they can be compiled once rather than +//! recompiled for every invocation (e.g., if they were defined in generated +//! code, then deriving `IntoBytes` and `FromBytes` on three different types +//! would result in the code in question being emitted and compiled six +//! different times). + +#![allow(missing_debug_implementations)] + +// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove +// this `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[cfg(not(target_pointer_width = "16"))] +use core::ptr::{self, NonNull}; +use core::{ + marker::PhantomData, + mem::{self, ManuallyDrop}, +}; + +use crate::{ + pointer::{ + invariant::{self, BecauseExclusive, BecauseImmutable, Invariants}, + BecauseInvariantsEq, InvariantsEq, SizeEq, TryTransmuteFromPtr, + }, + FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, Ptr, TryFromBytes, ValidityError, +}; + +/// Projects the type of the field at `Index` in `Self`. +/// +/// The `Index` parameter is any sort of handle that identifies the field; its +/// definition is the obligation of the implementer. +/// +/// # Safety +/// +/// Unsafe code may assume that this accurately reflects the definition of +/// `Self`. +pub unsafe trait Field { + /// The type of the field at `Index`. + type Type: ?Sized; +} + +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented( + message = "`{T}` has {PADDING_BYTES} total byte(s) of padding", + label = "types with padding cannot implement `IntoBytes`", + note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields", + note = "consider adding explicit fields where padding would be", + note = "consider using `#[repr(packed)]` to remove padding" + ) +)] +pub trait PaddingFree {} +impl PaddingFree for () {} + +// FIXME(#1112): In the slice DST case, we should delegate to *both* +// `PaddingFree` *and* `DynamicPaddingFree` (and probably rename `PaddingFree` +// to `StaticPaddingFree` or something - or introduce a third trait with that +// name) so that we can have more clear error messages. + +#[cfg_attr( + zerocopy_diagnostic_on_unimplemented_1_78_0, + diagnostic::on_unimplemented( + message = "`{T}` has one or more padding bytes", + label = "types with padding cannot implement `IntoBytes`", + note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields", + note = "consider adding explicit fields where padding would be", + note = "consider using `#[repr(packed)]` to remove padding" + ) +)] +pub trait DynamicPaddingFree {} +impl DynamicPaddingFree for () {} + +/// A type whose size is equal to `align_of::()`. +#[repr(C)] +pub struct AlignOf { + // This field ensures that: + // - The size is always at least 1 (the minimum possible alignment). + // - If the alignment is greater than 1, Rust has to round up to the next + // multiple of it in order to make sure that `Align`'s size is a multiple + // of that alignment. Without this field, its size could be 0, which is a + // valid multiple of any alignment. + _u: u8, + _a: [T; 0], +} + +impl AlignOf { + #[inline(never)] // Make `missing_inline_in_public_items` happy. + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + pub fn into_t(self) -> T { + unreachable!() + } +} + +/// A type whose size is equal to `max(align_of::(), align_of::())`. +#[repr(C)] +pub union MaxAlignsOf { + _t: ManuallyDrop>, + _u: ManuallyDrop>, +} + +impl MaxAlignsOf { + #[inline(never)] // Make `missing_inline_in_public_items` happy. + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + pub fn new(_t: T, _u: U) -> MaxAlignsOf { + unreachable!() + } +} + +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[cfg(not(target_pointer_width = "16"))] +const _64K: usize = 1 << 16; + +// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove +// this `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[cfg(not(target_pointer_width = "16"))] +#[repr(C, align(65536))] +struct Aligned64kAllocation([u8; _64K]); + +/// A pointer to an aligned allocation of size 2^16. +/// +/// # Safety +/// +/// `ALIGNED_64K_ALLOCATION` is guaranteed to point to the entirety of an +/// allocation with size and alignment 2^16, and to have valid provenance. +// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove +// this `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[cfg(not(target_pointer_width = "16"))] +pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = { + const REF: &Aligned64kAllocation = &Aligned64kAllocation([0; _64K]); + let ptr: *const Aligned64kAllocation = REF; + let ptr: *const [u8] = ptr::slice_from_raw_parts(ptr.cast(), _64K); + // SAFETY: + // - `ptr` is derived from a Rust reference, which is guaranteed to be + // non-null. + // - `ptr` is derived from an `&Aligned64kAllocation`, which has size and + // alignment `_64K` as promised. Its length is initialized to `_64K`, + // which means that it refers to the entire allocation. + // - `ptr` is derived from a Rust reference, which is guaranteed to have + // valid provenance. + // + // FIXME(#429): Once `NonNull::new_unchecked` docs document that it + // preserves provenance, cite those docs. + // FIXME: Replace this `as` with `ptr.cast_mut()` once our MSRV >= 1.65 + #[allow(clippy::as_conversions)] + unsafe { + NonNull::new_unchecked(ptr as *mut _) + } +}; + +/// Computes the offset of the base of the field `$trailing_field_name` within +/// the type `$ty`. +/// +/// `trailing_field_offset!` produces code which is valid in a `const` context. +// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove +// this `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! trailing_field_offset { + ($ty:ty, $trailing_field_name:tt) => {{ + let min_size = { + let zero_elems: *const [()] = + $crate::util::macro_util::core_reexport::ptr::slice_from_raw_parts( + $crate::util::macro_util::core_reexport::ptr::NonNull::<()>::dangling() + .as_ptr() + .cast_const(), + 0, + ); + // SAFETY: + // - If `$ty` is `Sized`, `size_of_val_raw` is always safe to call. + // - Otherwise: + // - If `$ty` is not a slice DST, this pointer conversion will + // fail due to "mismatched vtable kinds", and compilation will + // fail. + // - If `$ty` is a slice DST, we have constructed `zero_elems` to + // have zero trailing slice elements. Per the `size_of_val_raw` + // docs, "For the special case where the dynamic tail length is + // 0, this function is safe to call." [1] + // + // [1] https://doc.rust-lang.org/nightly/std/mem/fn.size_of_val_raw.html + unsafe { + #[allow(clippy::as_conversions)] + $crate::util::macro_util::core_reexport::mem::size_of_val_raw( + zero_elems as *const $ty, + ) + } + }; + + assert!(min_size <= _64K); + + #[allow(clippy::as_conversions)] + let ptr = ALIGNED_64K_ALLOCATION.as_ptr() as *const $ty; + + // SAFETY: + // - Thanks to the preceding `assert!`, we know that the value with zero + // elements fits in `_64K` bytes, and thus in the allocation addressed + // by `ALIGNED_64K_ALLOCATION`. The offset of the trailing field is + // guaranteed to be no larger than this size, so this field projection + // is guaranteed to remain in-bounds of its allocation. + // - Because the minimum size is no larger than `_64K` bytes, and + // because an object's size must always be a multiple of its alignment + // [1], we know that `$ty`'s alignment is no larger than `_64K`. The + // allocation addressed by `ALIGNED_64K_ALLOCATION` is guaranteed to + // be aligned to `_64K`, so `ptr` is guaranteed to satisfy `$ty`'s + // alignment. + // - As required by `addr_of!`, we do not write through `field`. + // + // Note that, as of [2], this requirement is technically unnecessary + // for Rust versions >= 1.75.0, but no harm in guaranteeing it anyway + // until we bump our MSRV. + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html: + // + // The size of a value is always a multiple of its alignment. + // + // [2] https://github.com/rust-lang/reference/pull/1387 + let field = unsafe { + $crate::util::macro_util::core_reexport::ptr::addr_of!((*ptr).$trailing_field_name) + }; + // SAFETY: + // - Both `ptr` and `field` are derived from the same allocated object. + // - By the preceding safety comment, `field` is in bounds of that + // allocated object. + // - The distance, in bytes, between `ptr` and `field` is required to be + // a multiple of the size of `u8`, which is trivially true because + // `u8`'s size is 1. + // - The distance, in bytes, cannot overflow `isize`. This is guaranteed + // because no allocated object can have a size larger than can fit in + // `isize`. [1] + // - The distance being in-bounds cannot rely on wrapping around the + // address space. This is guaranteed because the same is guaranteed of + // allocated objects. [1] + // + // [1] FIXME(#429), FIXME(https://github.com/rust-lang/rust/pull/116675): + // Once these are guaranteed in the Reference, cite it. + let offset = unsafe { field.cast::().offset_from(ptr.cast::()) }; + // Guaranteed not to be lossy: `field` comes after `ptr`, so the offset + // from `ptr` to `field` is guaranteed to be positive. + assert!(offset >= 0); + Some( + #[allow(clippy::as_conversions)] + { + offset as usize + }, + ) + }}; +} + +/// Computes alignment of `$ty: ?Sized`. +/// +/// `align_of!` produces code which is valid in a `const` context. +// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove +// this `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! align_of { + ($ty:ty) => {{ + // SAFETY: `OffsetOfTrailingIsAlignment` is `repr(C)`, and its layout is + // guaranteed [1] to begin with the single-byte layout for `_byte`, + // followed by the padding needed to align `_trailing`, then the layout + // for `_trailing`, and finally any trailing padding bytes needed to + // correctly-align the entire struct. + // + // This macro computes the alignment of `$ty` by counting the number of + // bytes preceding `_trailing`. For instance, if the alignment of `$ty` + // is `1`, then no padding is required align `_trailing` and it will be + // located immediately after `_byte` at offset 1. If the alignment of + // `$ty` is 2, then a single padding byte is required before + // `_trailing`, and `_trailing` will be located at offset 2. + + // This correspondence between offset and alignment holds for all valid + // Rust alignments, and we confirm this exhaustively (or, at least up to + // the maximum alignment supported by `trailing_field_offset!`) in + // `test_align_of_dst`. + // + // [1]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprc + + #[repr(C)] + struct OffsetOfTrailingIsAlignment { + _byte: u8, + _trailing: $ty, + } + + trailing_field_offset!(OffsetOfTrailingIsAlignment, _trailing) + }}; +} + +mod size_to_tag { + pub trait SizeToTag { + type Tag; + } + + impl SizeToTag<1> for () { + type Tag = u8; + } + impl SizeToTag<2> for () { + type Tag = u16; + } + impl SizeToTag<4> for () { + type Tag = u32; + } + impl SizeToTag<8> for () { + type Tag = u64; + } + impl SizeToTag<16> for () { + type Tag = u128; + } +} + +/// An alias for the unsigned integer of the given size in bytes. +#[doc(hidden)] +pub type SizeToTag = <() as size_to_tag::SizeToTag>::Tag; + +// We put `Sized` in its own module so it can have the same name as the standard +// library `Sized` without shadowing it in the parent module. +#[cfg(zerocopy_diagnostic_on_unimplemented_1_78_0)] +mod __size_of { + #[diagnostic::on_unimplemented( + message = "`{Self}` is unsized", + label = "`IntoBytes` needs all field types to be `Sized` in order to determine whether there is padding", + note = "consider using `#[repr(packed)]` to remove padding", + note = "`IntoBytes` does not require the fields of `#[repr(packed)]` types to be `Sized`" + )] + pub trait Sized: core::marker::Sized {} + impl Sized for T {} + + #[inline(always)] + #[must_use] + #[allow(clippy::needless_maybe_sized)] + pub const fn size_of() -> usize { + core::mem::size_of::() + } +} + +#[cfg(not(zerocopy_diagnostic_on_unimplemented_1_78_0))] +pub use core::mem::size_of; + +#[cfg(zerocopy_diagnostic_on_unimplemented_1_78_0)] +pub use __size_of::size_of; + +/// How many padding bytes does the struct type `$t` have? +/// +/// `$ts` is the list of the type of every field in `$t`. `$t` must be a struct +/// type, or else `struct_padding!`'s result may be meaningless. +/// +/// Note that `struct_padding!`'s results are independent of `repcr` since they +/// only consider the size of the type and the sizes of the fields. Whatever the +/// repr, the size of the type already takes into account any padding that the +/// compiler has decided to add. Structs with well-defined representations (such +/// as `repr(C)`) can use this macro to check for padding. Note that while this +/// may yield some consistent value for some `repr(Rust)` structs, it is not +/// guaranteed across platforms or compilations. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! struct_padding { + ($t:ty, [$($ts:ty),*]) => { + $crate::util::macro_util::size_of::<$t>() - (0 $(+ $crate::util::macro_util::size_of::<$ts>())*) + }; +} + +/// Does the `repr(C)` struct type `$t` have padding? +/// +/// `$ts` is the list of the type of every field in `$t`. `$t` must be a +/// `repr(C)` struct type, or else `struct_has_padding!`'s result may be +/// meaningless. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! repr_c_struct_has_padding { + ($t:ty, [$($ts:tt),*]) => {{ + let layout = $crate::DstLayout::for_repr_c_struct( + $crate::util::macro_util::core_reexport::option::Option::None, + $crate::util::macro_util::core_reexport::option::Option::None, + &[$($crate::repr_c_struct_has_padding!(@field $ts),)*] + ); + layout.requires_static_padding() || layout.requires_dynamic_padding() + }}; + (@field [$t:ty]) => { + <[$t] as $crate::KnownLayout>::LAYOUT + }; + (@field $t:ty) => { + $crate::DstLayout::for_unpadded_type::<$t>() + }; +} + +/// Does the union type `$t` have padding? +/// +/// `$ts` is the list of the type of every field in `$t`. `$t` must be a union +/// type, or else `union_padding!`'s result may be meaningless. +/// +/// Note that `union_padding!`'s results are independent of `repr` since they +/// only consider the size of the type and the sizes of the fields. Whatever the +/// repr, the size of the type already takes into account any padding that the +/// compiler has decided to add. Unions with well-defined representations (such +/// as `repr(C)`) can use this macro to check for padding. Note that while this +/// may yield some consistent value for some `repr(Rust)` unions, it is not +/// guaranteed across platforms or compilations. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! union_padding { + ($t:ty, [$($ts:ty),*]) => {{ + let mut max = 0; + $({ + let padding = $crate::util::macro_util::size_of::<$t>() - $crate::util::macro_util::size_of::<$ts>(); + if padding > max { + max = padding; + } + })* + max + }}; +} + +/// How many padding bytes does the enum type `$t` have? +/// +/// `$disc` is the type of the enum tag, and `$ts` is a list of fields in each +/// square-bracket-delimited variant. `$t` must be an enum, or else +/// `enum_padding!`'s result may be meaningless. An enum has padding if any of +/// its variant structs [1][2] contain padding, and so all of the variants of an +/// enum must be "full" in order for the enum to not have padding. +/// +/// The results of `enum_padding!` require that the enum is not `repr(Rust)`, as +/// `repr(Rust)` enums may niche the enum's tag and reduce the total number of +/// bytes required to represent the enum as a result. As long as the enum is +/// `repr(C)`, `repr(int)`, or `repr(C, int)`, this will consistently return +/// whether the enum contains any padding bytes. +/// +/// [1]: https://doc.rust-lang.org/1.81.0/reference/type-layout.html#reprc-enums-with-fields +/// [2]: https://doc.rust-lang.org/1.81.0/reference/type-layout.html#primitive-representation-of-enums-with-fields +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! enum_padding { + ($t:ty, $disc:ty, $([$($ts:ty),*]),*) => {{ + let mut max = 0; + $({ + let padding = $crate::util::macro_util::size_of::<$t>() + - ( + $crate::util::macro_util::size_of::<$disc>() + $(+ $crate::util::macro_util::size_of::<$ts>())* + ); + if padding > max { + max = padding; + } + })* + max + }}; +} + +/// Does `t` have alignment greater than or equal to `u`? If not, this macro +/// produces a compile error. It must be invoked in a dead codepath. This is +/// used in `transmute_ref!` and `transmute_mut!`. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! assert_align_gt_eq { + ($t:ident, $u: ident) => {{ + // The comments here should be read in the context of this macro's + // invocations in `transmute_ref!` and `transmute_mut!`. + if false { + // The type wildcard in this bound is inferred to be `T` because + // `align_of.into_t()` is assigned to `t` (which has type `T`). + let align_of: $crate::util::macro_util::AlignOf<_> = unreachable!(); + $t = align_of.into_t(); + // `max_aligns` is inferred to have type `MaxAlignsOf` because + // of the inferred types of `t` and `u`. + let mut max_aligns = $crate::util::macro_util::MaxAlignsOf::new($t, $u); + + // This transmute will only compile successfully if + // `align_of::() == max(align_of::(), align_of::())` - in + // other words, if `align_of::() >= align_of::()`. + // + // SAFETY: This code is never run. + max_aligns = unsafe { + // Clippy: We can't annotate the types; this macro is designed + // to infer the types from the calling context. + #[allow(clippy::missing_transmute_annotations)] + $crate::util::macro_util::core_reexport::mem::transmute(align_of) + }; + } else { + loop {} + } + }}; +} + +/// Do `t` and `u` have the same size? If not, this macro produces a compile +/// error. It must be invoked in a dead codepath. This is used in +/// `transmute_ref!` and `transmute_mut!`. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! assert_size_eq { + ($t:ident, $u: ident) => {{ + // The comments here should be read in the context of this macro's + // invocations in `transmute_ref!` and `transmute_mut!`. + if false { + // SAFETY: This code is never run. + $u = unsafe { + // Clippy: + // - It's okay to transmute a type to itself. + // - We can't annotate the types; this macro is designed to + // infer the types from the calling context. + #[allow(clippy::useless_transmute, clippy::missing_transmute_annotations)] + $crate::util::macro_util::core_reexport::mem::transmute($t) + }; + } else { + loop {} + } + }}; +} + +/// Is a given source a valid instance of `Dst`? +/// +/// If so, returns `src` casted to a `Ptr`. Otherwise returns `None`. +/// +/// # Safety +/// +/// Unsafe code may assume that, if `try_cast_or_pme(src)` returns `Ok`, +/// `*src` is a bit-valid instance of `Dst`, and that the size of `Src` is +/// greater than or equal to the size of `Dst`. +/// +/// Unsafe code may assume that, if `try_cast_or_pme(src)` returns `Err`, the +/// encapsulated `Ptr` value is the original `src`. `try_cast_or_pme` cannot +/// guarantee that the referent has not been modified, as it calls user-defined +/// code (`TryFromBytes::is_bit_valid`). +/// +/// # Panics +/// +/// `try_cast_or_pme` may either produce a post-monomorphization error or a +/// panic if `Dst` not the same size as `Src`. Otherwise, `try_cast_or_pme` +/// panics under the same circumstances as [`is_bit_valid`]. +/// +/// [`is_bit_valid`]: TryFromBytes::is_bit_valid +#[doc(hidden)] +#[inline] +fn try_cast_or_pme( + src: Ptr<'_, Src, I>, +) -> Result< + Ptr<'_, Dst, (I::Aliasing, invariant::Unaligned, invariant::Valid)>, + ValidityError, Dst>, +> +where + // FIXME(#2226): There should be a `Src: FromBytes` bound here, but doing so + // requires deeper surgery. + Src: invariant::Read, + Dst: TryFromBytes + + invariant::Read + + TryTransmuteFromPtr, + I: Invariants, + I::Aliasing: invariant::Reference, +{ + static_assert!(Src, Dst => mem::size_of::() == mem::size_of::()); + + // SAFETY: This is a pointer cast, satisfying the following properties: + // - `p as *mut Dst` addresses a subset of the `bytes` addressed by `src`, + // because we assert above that the size of `Dst` equal to the size of + // `Src`. + // - `p as *mut Dst` is a provenance-preserving cast + let c_ptr = unsafe { src.cast_unsized(|p| cast!(p)) }; + + match c_ptr.try_into_valid() { + Ok(ptr) => Ok(ptr), + Err(err) => { + // Re-cast `Ptr` to `Ptr`. + let ptr = err.into_src(); + // SAFETY: This is a pointer cast, satisfying the following + // properties: + // - `p as *mut Src` addresses a subset of the `bytes` addressed by + // `ptr`, because we assert above that the size of `Dst` is equal + // to the size of `Src`. + // - `p as *mut Src` is a provenance-preserving cast + let ptr = unsafe { ptr.cast_unsized(|p| cast!(p)) }; + // SAFETY: `ptr` is `src`, and has the same alignment invariant. + let ptr = unsafe { ptr.assume_alignment::() }; + // SAFETY: `ptr` is `src` and has the same validity invariant. + let ptr = unsafe { ptr.assume_validity::() }; + Err(ValidityError::new(ptr.unify_invariants())) + } + } +} + +/// Attempts to transmute `Src` into `Dst`. +/// +/// A helper for `try_transmute!`. +/// +/// # Panics +/// +/// `try_transmute` may either produce a post-monomorphization error or a panic +/// if `Dst` is bigger than `Src`. Otherwise, `try_transmute` panics under the +/// same circumstances as [`is_bit_valid`]. +/// +/// [`is_bit_valid`]: TryFromBytes::is_bit_valid +#[inline(always)] +pub fn try_transmute(src: Src) -> Result> +where + Src: IntoBytes, + Dst: TryFromBytes, +{ + static_assert!(Src, Dst => mem::size_of::() == mem::size_of::()); + + let mu_src = mem::MaybeUninit::new(src); + // SAFETY: By invariant on `&`, the following are satisfied: + // - `&mu_src` is valid for reads + // - `&mu_src` is properly aligned + // - `&mu_src`'s referent is bit-valid + let mu_src_copy = unsafe { core::ptr::read(&mu_src) }; + // SAFETY: `MaybeUninit` has no validity constraints. + let mut mu_dst: mem::MaybeUninit = + unsafe { crate::util::transmute_unchecked(mu_src_copy) }; + + let ptr = Ptr::from_mut(&mut mu_dst); + + // SAFETY: Since `Src: IntoBytes`, and since `size_of::() == + // size_of::()` by the preceding assertion, all of `mu_dst`'s bytes are + // initialized. + let ptr = unsafe { ptr.assume_validity::() }; + + // SAFETY: `MaybeUninit` and `T` have the same size [1], so this cast + // preserves the referent's size. This cast preserves provenance. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, alignment, and + // ABI as `T` + let ptr: Ptr<'_, Dst, _> = unsafe { + ptr.cast_unsized(|ptr: crate::pointer::PtrInner<'_, mem::MaybeUninit>| { + ptr.cast_sized() + }) + }; + + if Dst::is_bit_valid(ptr.forget_aligned()) { + // SAFETY: Since `Dst::is_bit_valid`, we know that `ptr`'s referent is + // bit-valid for `Dst`. `ptr` points to `mu_dst`, and no intervening + // operations have mutated it, so it is a bit-valid `Dst`. + Ok(unsafe { mu_dst.assume_init() }) + } else { + // SAFETY: `mu_src` was constructed from `src` and never modified, so it + // is still bit-valid. + Err(ValidityError::new(unsafe { mu_src.assume_init() })) + } +} + +/// Attempts to transmute `&Src` into `&Dst`. +/// +/// A helper for `try_transmute_ref!`. +/// +/// # Panics +/// +/// `try_transmute_ref` may either produce a post-monomorphization error or a +/// panic if `Dst` is bigger or has a stricter alignment requirement than `Src`. +/// Otherwise, `try_transmute_ref` panics under the same circumstances as +/// [`is_bit_valid`]. +/// +/// [`is_bit_valid`]: TryFromBytes::is_bit_valid +#[inline(always)] +pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> +where + Src: IntoBytes + Immutable, + Dst: TryFromBytes + Immutable, +{ + let ptr = Ptr::from_ref(src); + let ptr = ptr.bikeshed_recall_initialized_immutable(); + match try_cast_or_pme::(ptr) { + Ok(ptr) => { + static_assert!(Src, Dst => mem::align_of::() <= mem::align_of::()); + // SAFETY: We have checked that `Dst` does not have a stricter + // alignment requirement than `Src`. + let ptr = unsafe { ptr.assume_alignment::() }; + Ok(ptr.as_ref()) + } + Err(err) => Err(err.map_src(|ptr| { + // SAFETY: Because `Src: Immutable` and we create a `Ptr` via + // `Ptr::from_ref`, the resulting `Ptr` is a shared-and-`Immutable` + // `Ptr`, which does not permit mutation of its referent. Therefore, + // no mutation could have happened during the call to + // `try_cast_or_pme` (any such mutation would be unsound). + // + // `try_cast_or_pme` promises to return its original argument, and + // so we know that we are getting back the same `ptr` that we + // originally passed, and that `ptr` was a bit-valid `Src`. + let ptr = unsafe { ptr.assume_valid() }; + ptr.as_ref() + })), + } +} + +/// Attempts to transmute `&mut Src` into `&mut Dst`. +/// +/// A helper for `try_transmute_mut!`. +/// +/// # Panics +/// +/// `try_transmute_mut` may either produce a post-monomorphization error or a +/// panic if `Dst` is bigger or has a stricter alignment requirement than `Src`. +/// Otherwise, `try_transmute_mut` panics under the same circumstances as +/// [`is_bit_valid`]. +/// +/// [`is_bit_valid`]: TryFromBytes::is_bit_valid +#[inline(always)] +pub fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> +where + Src: FromBytes + IntoBytes, + Dst: TryFromBytes + IntoBytes, +{ + let ptr = Ptr::from_mut(src); + let ptr = ptr.bikeshed_recall_initialized_from_bytes(); + match try_cast_or_pme::(ptr) { + Ok(ptr) => { + static_assert!(Src, Dst => mem::align_of::() <= mem::align_of::()); + // SAFETY: We have checked that `Dst` does not have a stricter + // alignment requirement than `Src`. + let ptr = unsafe { ptr.assume_alignment::() }; + Ok(ptr.as_mut()) + } + Err(err) => { + Err(err.map_src(|ptr| ptr.recall_validity::<_, (_, BecauseInvariantsEq)>().as_mut())) + } + } +} + +// Used in `transmute_ref!` and friends. +// +// This permits us to use the autoref specialization trick to dispatch to +// associated functions for `transmute_ref` and `transmute_mut` when both `Src` +// and `Dst` are `Sized`, and to trait methods otherwise. The associated +// functions, unlike the trait methods, do not require a `KnownLayout` bound. +// This permits us to add support for transmuting references to unsized types +// without breaking backwards-compatibility (on v0.8.x) with the old +// implementation, which did not require a `KnownLayout` bound to transmute +// sized types. +#[derive(Copy, Clone)] +pub struct Wrap(pub Src, pub PhantomData); + +impl Wrap { + #[inline(always)] + pub const fn new(src: Src) -> Self { + Wrap(src, PhantomData) + } +} + +impl<'a, Src, Dst> Wrap<&'a Src, &'a Dst> { + /// # Safety + /// The caller must guarantee that: + /// - `Src: IntoBytes + Immutable` + /// - `Dst: FromBytes + Immutable` + /// + /// # PME + /// + /// Instantiating this method PMEs unless both: + /// - `mem::size_of::() == mem::size_of::()` + /// - `mem::align_of::() <= mem::align_of::()` + #[inline(always)] + #[must_use] + pub const unsafe fn transmute_ref(self) -> &'a Dst { + static_assert!(Src, Dst => mem::size_of::() == mem::size_of::()); + static_assert!(Src, Dst => mem::align_of::() <= mem::align_of::()); + + let src: *const Src = self.0; + let dst = src.cast::(); + // SAFETY: + // - We know that it is sound to view the target type of the input reference + // (`Src`) as the target type of the output reference (`Dst`) because the + // caller has guaranteed that `Src: IntoBytes`, `Dst: FromBytes`, and + // `size_of::() == size_of::()`. + // - We know that there are no `UnsafeCell`s, and thus we don't have to + // worry about `UnsafeCell` overlap, because `Src: Immutable` and `Dst: + // Immutable`. + // - The caller has guaranteed that alignment is not increased. + // - We know that the returned lifetime will not outlive the input lifetime + // thanks to the lifetime bounds on this function. + // + // FIXME(#67): Once our MSRV is 1.58, replace this `transmute` with `&*dst`. + #[allow(clippy::transmute_ptr_to_ref)] + unsafe { + mem::transmute(dst) + } + } +} + +impl<'a, Src, Dst> Wrap<&'a mut Src, &'a mut Dst> { + /// Transmutes a mutable reference of one type to a mutable reference of another + /// type. + /// + /// # PME + /// + /// Instantiating this method PMEs unless both: + /// - `mem::size_of::() == mem::size_of::()` + /// - `mem::align_of::() <= mem::align_of::()` + #[inline(always)] + #[must_use] + pub fn transmute_mut(self) -> &'a mut Dst + where + Src: FromBytes + IntoBytes, + Dst: FromBytes + IntoBytes, + { + static_assert!(Src, Dst => mem::size_of::() == mem::size_of::()); + static_assert!(Src, Dst => mem::align_of::() <= mem::align_of::()); + + let src: *mut Src = self.0; + let dst = src.cast::(); + // SAFETY: + // - We know that it is sound to view the target type of the input + // reference (`Src`) as the target type of the output reference + // (`Dst`) and vice-versa because `Src: FromBytes + IntoBytes`, `Dst: + // FromBytes + IntoBytes`, and (as asserted above) `size_of::() + // == size_of::()`. + // - We asserted above that alignment will not increase. + // - We know that the returned lifetime will not outlive the input + // lifetime thanks to the lifetime bounds on this function. + unsafe { &mut *dst } + } +} + +pub trait TransmuteRefDst<'a> { + type Dst: ?Sized; + + #[must_use] + fn transmute_ref(self) -> &'a Self::Dst; +} + +impl<'a, Src: ?Sized, Dst: ?Sized> TransmuteRefDst<'a> for Wrap<&'a Src, &'a Dst> +where + Src: KnownLayout + IntoBytes + Immutable, + Dst: KnownLayout + FromBytes + Immutable, +{ + type Dst = Dst; + + #[inline(always)] + fn transmute_ref(self) -> &'a Dst { + static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => { + Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get() + }, "cannot transmute reference when destination type has higher alignment than source type"); + + // SAFETY: We only use `S` as `S` and `D` as `D`. + unsafe { + unsafe_with_size_eq!(, D> { + let ptr = Ptr::from_ref(self.0) + .transmute::, invariant::Valid, BecauseImmutable>() + .recall_validity::() + .transmute::, invariant::Initialized, (crate::pointer::BecauseMutationCompatible, _)>() + .recall_validity::(); + + #[allow(unused_unsafe)] + // SAFETY: The preceding `static_assert!` ensures that + // `T::LAYOUT.align >= U::LAYOUT.align`. Since `self.0` is + // validly-aligned for `T`, it is also validly-aligned for `U`. + let ptr = unsafe { ptr.assume_alignment() }; + + &ptr.as_ref().0 + }) + } + } +} + +pub trait TransmuteMutDst<'a> { + type Dst: ?Sized; + #[must_use] + fn transmute_mut(self) -> &'a mut Self::Dst; +} + +impl<'a, Src: ?Sized, Dst: ?Sized> TransmuteMutDst<'a> for Wrap<&'a mut Src, &'a mut Dst> +where + Src: KnownLayout + FromBytes + IntoBytes, + Dst: KnownLayout + FromBytes + IntoBytes, +{ + type Dst = Dst; + + #[inline(always)] + fn transmute_mut(self) -> &'a mut Dst { + static_assert!(Src: ?Sized + KnownLayout, Dst: ?Sized + KnownLayout => { + Src::LAYOUT.align.get() >= Dst::LAYOUT.align.get() + }, "cannot transmute reference when destination type has higher alignment than source type"); + + // SAFETY: We only use `S` as `S` and `D` as `D`. + unsafe { + unsafe_with_size_eq!(, D> { + let ptr = Ptr::from_mut(self.0) + .transmute::, invariant::Valid, _>() + .recall_validity::() + .transmute::, invariant::Initialized, _>() + .recall_validity::(); + + #[allow(unused_unsafe)] + // SAFETY: The preceding `static_assert!` ensures that + // `T::LAYOUT.align >= U::LAYOUT.align`. Since `self.0` is + // validly-aligned for `T`, it is also validly-aligned for `U`. + let ptr = unsafe { ptr.assume_alignment() }; + + &mut ptr.as_mut().0 + }) + } + } +} + +/// A function which emits a warning if its return value is not used. +#[must_use] +#[inline(always)] +pub const fn must_use(t: T) -> T { + t +} + +// NOTE: We can't change this to a `pub use core as core_reexport` until [1] is +// fixed or we update to a semver-breaking version (as of this writing, 0.8.0) +// on the `main` branch. +// +// [1] https://github.com/obi1kenobi/cargo-semver-checks/issues/573 +pub mod core_reexport { + pub use core::*; + + pub mod mem { + pub use core::mem::*; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::testutil::*; + + #[test] + fn test_align_of() { + macro_rules! test { + ($ty:ty) => { + assert_eq!(mem::size_of::>(), mem::align_of::<$ty>()); + }; + } + + test!(()); + test!(u8); + test!(AU64); + test!([AU64; 2]); + } + + #[test] + fn test_max_aligns_of() { + macro_rules! test { + ($t:ty, $u:ty) => { + assert_eq!( + mem::size_of::>(), + core::cmp::max(mem::align_of::<$t>(), mem::align_of::<$u>()) + ); + }; + } + + test!(u8, u8); + test!(u8, AU64); + test!(AU64, u8); + } + + #[test] + fn test_typed_align_check() { + // Test that the type-based alignment check used in + // `assert_align_gt_eq!` behaves as expected. + + macro_rules! assert_t_align_gteq_u_align { + ($t:ty, $u:ty, $gteq:expr) => { + assert_eq!( + mem::size_of::>() == mem::size_of::>(), + $gteq + ); + }; + } + + assert_t_align_gteq_u_align!(u8, u8, true); + assert_t_align_gteq_u_align!(AU64, AU64, true); + assert_t_align_gteq_u_align!(AU64, u8, true); + assert_t_align_gteq_u_align!(u8, AU64, false); + } + + // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove + // this `cfg` when `size_of_val_raw` is stabilized. + #[allow(clippy::decimal_literal_representation)] + #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] + #[test] + fn test_trailing_field_offset() { + assert_eq!(mem::align_of::(), _64K); + + macro_rules! test { + (#[$cfg:meta] ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {{ + #[$cfg] + struct Test($(#[allow(dead_code)] $ts,)* #[allow(dead_code)] $trailing_field_ty); + assert_eq!(test!(@offset $($ts),* ; $trailing_field_ty), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => { + test!(#[$cfg] ($($ts),* ; $trailing_field_ty) => $expect); + test!($(#[$cfgs])* ($($ts),* ; $trailing_field_ty) => $expect); + }; + (@offset ; $_trailing:ty) => { trailing_field_offset!(Test, 0) }; + (@offset $_t:ty ; $_trailing:ty) => { trailing_field_offset!(Test, 1) }; + } + + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; u8) => Some(0)); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; [u8]) => Some(0)); + test!(#[repr(C)] #[repr(C, packed)] (u8; u8) => Some(1)); + test!(#[repr(C)] (; AU64) => Some(0)); + test!(#[repr(C)] (; [AU64]) => Some(0)); + test!(#[repr(C)] (u8; AU64) => Some(8)); + test!(#[repr(C)] (u8; [AU64]) => Some(8)); + + #[derive( + Immutable, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone, + )] + #[repr(C)] + pub(crate) struct Nested { + _t: T, + _u: U, + } + + test!(#[repr(C)] (; Nested) => Some(0)); + test!(#[repr(C)] (; Nested) => Some(0)); + test!(#[repr(C)] (u8; Nested) => Some(8)); + test!(#[repr(C)] (u8; Nested) => Some(8)); + + // Test that `packed(N)` limits the offset of the trailing field. + test!(#[repr(C, packed( 1))] (u8; elain::Align< 2>) => Some( 1)); + test!(#[repr(C, packed( 2))] (u8; elain::Align< 4>) => Some( 2)); + test!(#[repr(C, packed( 4))] (u8; elain::Align< 8>) => Some( 4)); + test!(#[repr(C, packed( 8))] (u8; elain::Align< 16>) => Some( 8)); + test!(#[repr(C, packed( 16))] (u8; elain::Align< 32>) => Some( 16)); + test!(#[repr(C, packed( 32))] (u8; elain::Align< 64>) => Some( 32)); + test!(#[repr(C, packed( 64))] (u8; elain::Align< 128>) => Some( 64)); + test!(#[repr(C, packed( 128))] (u8; elain::Align< 256>) => Some( 128)); + test!(#[repr(C, packed( 256))] (u8; elain::Align< 512>) => Some( 256)); + test!(#[repr(C, packed( 512))] (u8; elain::Align< 1024>) => Some( 512)); + test!(#[repr(C, packed( 1024))] (u8; elain::Align< 2048>) => Some( 1024)); + test!(#[repr(C, packed( 2048))] (u8; elain::Align< 4096>) => Some( 2048)); + test!(#[repr(C, packed( 4096))] (u8; elain::Align< 8192>) => Some( 4096)); + test!(#[repr(C, packed( 8192))] (u8; elain::Align< 16384>) => Some( 8192)); + test!(#[repr(C, packed( 16384))] (u8; elain::Align< 32768>) => Some( 16384)); + test!(#[repr(C, packed( 32768))] (u8; elain::Align< 65536>) => Some( 32768)); + test!(#[repr(C, packed( 65536))] (u8; elain::Align< 131072>) => Some( 65536)); + /* Alignments above 65536 are not yet supported. + test!(#[repr(C, packed( 131072))] (u8; elain::Align< 262144>) => Some( 131072)); + test!(#[repr(C, packed( 262144))] (u8; elain::Align< 524288>) => Some( 262144)); + test!(#[repr(C, packed( 524288))] (u8; elain::Align< 1048576>) => Some( 524288)); + test!(#[repr(C, packed( 1048576))] (u8; elain::Align< 2097152>) => Some( 1048576)); + test!(#[repr(C, packed( 2097152))] (u8; elain::Align< 4194304>) => Some( 2097152)); + test!(#[repr(C, packed( 4194304))] (u8; elain::Align< 8388608>) => Some( 4194304)); + test!(#[repr(C, packed( 8388608))] (u8; elain::Align< 16777216>) => Some( 8388608)); + test!(#[repr(C, packed( 16777216))] (u8; elain::Align< 33554432>) => Some( 16777216)); + test!(#[repr(C, packed( 33554432))] (u8; elain::Align< 67108864>) => Some( 33554432)); + test!(#[repr(C, packed( 67108864))] (u8; elain::Align< 33554432>) => Some( 67108864)); + test!(#[repr(C, packed( 33554432))] (u8; elain::Align<134217728>) => Some( 33554432)); + test!(#[repr(C, packed(134217728))] (u8; elain::Align<268435456>) => Some(134217728)); + test!(#[repr(C, packed(268435456))] (u8; elain::Align<268435456>) => Some(268435456)); + */ + + // Test that `align(N)` does not limit the offset of the trailing field. + test!(#[repr(C, align( 1))] (u8; elain::Align< 2>) => Some( 2)); + test!(#[repr(C, align( 2))] (u8; elain::Align< 4>) => Some( 4)); + test!(#[repr(C, align( 4))] (u8; elain::Align< 8>) => Some( 8)); + test!(#[repr(C, align( 8))] (u8; elain::Align< 16>) => Some( 16)); + test!(#[repr(C, align( 16))] (u8; elain::Align< 32>) => Some( 32)); + test!(#[repr(C, align( 32))] (u8; elain::Align< 64>) => Some( 64)); + test!(#[repr(C, align( 64))] (u8; elain::Align< 128>) => Some( 128)); + test!(#[repr(C, align( 128))] (u8; elain::Align< 256>) => Some( 256)); + test!(#[repr(C, align( 256))] (u8; elain::Align< 512>) => Some( 512)); + test!(#[repr(C, align( 512))] (u8; elain::Align< 1024>) => Some( 1024)); + test!(#[repr(C, align( 1024))] (u8; elain::Align< 2048>) => Some( 2048)); + test!(#[repr(C, align( 2048))] (u8; elain::Align< 4096>) => Some( 4096)); + test!(#[repr(C, align( 4096))] (u8; elain::Align< 8192>) => Some( 8192)); + test!(#[repr(C, align( 8192))] (u8; elain::Align< 16384>) => Some( 16384)); + test!(#[repr(C, align( 16384))] (u8; elain::Align< 32768>) => Some( 32768)); + test!(#[repr(C, align( 32768))] (u8; elain::Align< 65536>) => Some( 65536)); + /* Alignments above 65536 are not yet supported. + test!(#[repr(C, align( 65536))] (u8; elain::Align< 131072>) => Some( 131072)); + test!(#[repr(C, align( 131072))] (u8; elain::Align< 262144>) => Some( 262144)); + test!(#[repr(C, align( 262144))] (u8; elain::Align< 524288>) => Some( 524288)); + test!(#[repr(C, align( 524288))] (u8; elain::Align< 1048576>) => Some( 1048576)); + test!(#[repr(C, align( 1048576))] (u8; elain::Align< 2097152>) => Some( 2097152)); + test!(#[repr(C, align( 2097152))] (u8; elain::Align< 4194304>) => Some( 4194304)); + test!(#[repr(C, align( 4194304))] (u8; elain::Align< 8388608>) => Some( 8388608)); + test!(#[repr(C, align( 8388608))] (u8; elain::Align< 16777216>) => Some( 16777216)); + test!(#[repr(C, align( 16777216))] (u8; elain::Align< 33554432>) => Some( 33554432)); + test!(#[repr(C, align( 33554432))] (u8; elain::Align< 67108864>) => Some( 67108864)); + test!(#[repr(C, align( 67108864))] (u8; elain::Align< 33554432>) => Some( 33554432)); + test!(#[repr(C, align( 33554432))] (u8; elain::Align<134217728>) => Some(134217728)); + test!(#[repr(C, align(134217728))] (u8; elain::Align<268435456>) => Some(268435456)); + */ + } + + // FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove + // this `cfg` when `size_of_val_raw` is stabilized. + #[allow(clippy::decimal_literal_representation)] + #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] + #[test] + fn test_align_of_dst() { + // Test that `align_of!` correctly computes the alignment of DSTs. + assert_eq!(align_of!([elain::Align<1>]), Some(1)); + assert_eq!(align_of!([elain::Align<2>]), Some(2)); + assert_eq!(align_of!([elain::Align<4>]), Some(4)); + assert_eq!(align_of!([elain::Align<8>]), Some(8)); + assert_eq!(align_of!([elain::Align<16>]), Some(16)); + assert_eq!(align_of!([elain::Align<32>]), Some(32)); + assert_eq!(align_of!([elain::Align<64>]), Some(64)); + assert_eq!(align_of!([elain::Align<128>]), Some(128)); + assert_eq!(align_of!([elain::Align<256>]), Some(256)); + assert_eq!(align_of!([elain::Align<512>]), Some(512)); + assert_eq!(align_of!([elain::Align<1024>]), Some(1024)); + assert_eq!(align_of!([elain::Align<2048>]), Some(2048)); + assert_eq!(align_of!([elain::Align<4096>]), Some(4096)); + assert_eq!(align_of!([elain::Align<8192>]), Some(8192)); + assert_eq!(align_of!([elain::Align<16384>]), Some(16384)); + assert_eq!(align_of!([elain::Align<32768>]), Some(32768)); + assert_eq!(align_of!([elain::Align<65536>]), Some(65536)); + /* Alignments above 65536 are not yet supported. + assert_eq!(align_of!([elain::Align<131072>]), Some(131072)); + assert_eq!(align_of!([elain::Align<262144>]), Some(262144)); + assert_eq!(align_of!([elain::Align<524288>]), Some(524288)); + assert_eq!(align_of!([elain::Align<1048576>]), Some(1048576)); + assert_eq!(align_of!([elain::Align<2097152>]), Some(2097152)); + assert_eq!(align_of!([elain::Align<4194304>]), Some(4194304)); + assert_eq!(align_of!([elain::Align<8388608>]), Some(8388608)); + assert_eq!(align_of!([elain::Align<16777216>]), Some(16777216)); + assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432)); + assert_eq!(align_of!([elain::Align<67108864>]), Some(67108864)); + assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432)); + assert_eq!(align_of!([elain::Align<134217728>]), Some(134217728)); + assert_eq!(align_of!([elain::Align<268435456>]), Some(268435456)); + */ + } + + #[test] + fn test_enum_casts() { + // Test that casting the variants of enums with signed integer reprs to + // unsigned integers obeys expected signed -> unsigned casting rules. + + #[repr(i8)] + enum ReprI8 { + MinusOne = -1, + Zero = 0, + Min = i8::MIN, + Max = i8::MAX, + } + + #[allow(clippy::as_conversions)] + let x = ReprI8::MinusOne as u8; + assert_eq!(x, u8::MAX); + + #[allow(clippy::as_conversions)] + let x = ReprI8::Zero as u8; + assert_eq!(x, 0); + + #[allow(clippy::as_conversions)] + let x = ReprI8::Min as u8; + assert_eq!(x, 128); + + #[allow(clippy::as_conversions)] + let x = ReprI8::Max as u8; + assert_eq!(x, 127); + } + + #[test] + fn test_struct_padding() { + // Test that, for each provided repr, `struct_padding!` reports the + // expected value. + macro_rules! test { + (#[$cfg:meta] ($($ts:ty),*) => $expect:expr) => {{ + #[$cfg] + #[allow(dead_code)] + struct Test($($ts),*); + assert_eq!(struct_padding!(Test, [$($ts),*]), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),*) => $expect:expr) => { + test!(#[$cfg] ($($ts),*) => $expect); + test!($(#[$cfgs])* ($($ts),*) => $expect); + }; + } + + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] () => 0); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8) => 0); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8, ()) => 0); + test!(#[repr(C)] #[repr(packed)] (u8, u8) => 0); + + test!(#[repr(C)] (u8, AU64) => 7); + // Rust won't let you put `#[repr(packed)]` on a type which contains a + // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. + // It's not ideal, but it definitely has align > 1 on /some/ of our CI + // targets, and this isn't a particularly complex macro we're testing + // anyway. + test!(#[repr(packed)] (u8, u64) => 0); + } + + #[test] + fn test_repr_c_struct_padding() { + // Test that, for each provided repr, `repr_c_struct_padding!` reports + // the expected value. + macro_rules! test { + (($($ts:tt),*) => $expect:expr) => {{ + #[repr(C)] + #[allow(dead_code)] + struct Test($($ts),*); + assert_eq!(repr_c_struct_has_padding!(Test, [$($ts),*]), $expect); + }}; + } + + // Test static padding + test!(() => false); + test!(([u8]) => false); + test!((u8) => false); + test!((u8, [u8]) => false); + test!((u8, ()) => false); + test!((u8, (), [u8]) => false); + test!((u8, u8) => false); + test!((u8, u8, [u8]) => false); + + test!((u8, AU64) => true); + test!((u8, AU64, [u8]) => true); + + // Test dynamic padding + test!((AU64, [AU64]) => false); + test!((u8, [AU64]) => true); + + #[repr(align(4))] + struct AU32(#[allow(unused)] u32); + test!((AU64, [AU64]) => false); + test!((AU64, [AU32]) => true); + } + + #[test] + fn test_union_padding() { + // Test that, for each provided repr, `union_padding!` reports the + // expected value. + macro_rules! test { + (#[$cfg:meta] {$($fs:ident: $ts:ty),*} => $expect:expr) => {{ + #[$cfg] + #[allow(unused)] // fields are never read + union Test{ $($fs: $ts),* } + assert_eq!(union_padding!(Test, [$($ts),*]), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* {$($fs:ident: $ts:ty),*} => $expect:expr) => { + test!(#[$cfg] {$($fs: $ts),*} => $expect); + test!($(#[$cfgs])* {$($fs: $ts),*} => $expect); + }; + } + + test!(#[repr(C)] #[repr(packed)] {a: u8} => 0); + test!(#[repr(C)] #[repr(packed)] {a: u8, b: u8} => 0); + + // Rust won't let you put `#[repr(packed)]` on a type which contains a + // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. + // It's not ideal, but it definitely has align > 1 on /some/ of our CI + // targets, and this isn't a particularly complex macro we're testing + // anyway. + test!(#[repr(C)] #[repr(packed)] {a: u8, b: u64} => 7); + } + + #[test] + fn test_enum_padding() { + // Test that, for each provided repr, `enum_has_padding!` reports the + // expected value. + macro_rules! test { + (#[repr($disc:ident $(, $c:ident)?)] { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => { + test!(@case #[repr($disc $(, $c)?)] { $($vs ($($ts),*),)* } => $expect); + }; + (#[repr($disc:ident $(, $c:ident)?)] #[$cfg:meta] $(#[$cfgs:meta])* { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => { + test!(@case #[repr($disc $(, $c)?)] #[$cfg] { $($vs ($($ts),*),)* } => $expect); + test!(#[repr($disc $(, $c)?)] $(#[$cfgs])* { $($vs ($($ts),*),)* } => $expect); + }; + (@case #[repr($disc:ident $(, $c:ident)?)] $(#[$cfg:meta])? { $($vs:ident ($($ts:ty),*),)* } => $expect:expr) => {{ + #[repr($disc $(, $c)?)] + $(#[$cfg])? + #[allow(unused)] // variants and fields are never used + enum Test { + $($vs ($($ts),*),)* + } + assert_eq!( + enum_padding!(Test, $disc, $([$($ts),*]),*), + $expect + ); + }}; + } + + #[allow(unused)] + #[repr(align(2))] + struct U16(u16); + + #[allow(unused)] + #[repr(align(4))] + struct U32(u32); + + test!(#[repr(u8)] #[repr(C)] { + A(u8), + } => 0); + test!(#[repr(u16)] #[repr(C)] { + A(u8, u8), + B(U16), + } => 0); + test!(#[repr(u32)] #[repr(C)] { + A(u8, u8, u8, u8), + B(U16, u8, u8), + C(u8, u8, U16), + D(U16, U16), + E(U32), + } => 0); + + // `repr(int)` can pack the discriminant more efficiently + test!(#[repr(u8)] { + A(u8, U16), + } => 0); + test!(#[repr(u8)] { + A(u8, U16, U32), + } => 0); + + // `repr(C)` cannot + test!(#[repr(u8, C)] { + A(u8, U16), + } => 2); + test!(#[repr(u8, C)] { + A(u8, u8, u8, U32), + } => 4); + + // And field ordering can always cause problems + test!(#[repr(u8)] #[repr(C)] { + A(U16, u8), + } => 2); + test!(#[repr(u8)] #[repr(C)] { + A(U32, u8, u8, u8), + } => 4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/macros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,941 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +/// Unsafely implements trait(s) for a type. +/// +/// # Safety +/// +/// The trait impl must be sound. +/// +/// When implementing `TryFromBytes`: +/// - If no `is_bit_valid` impl is provided, then it must be valid for +/// `is_bit_valid` to unconditionally return `true`. In other words, it must +/// be the case that any initialized sequence of bytes constitutes a valid +/// instance of `$ty`. +/// - If an `is_bit_valid` impl is provided, then the impl of `is_bit_valid` +/// must only return `true` if its argument refers to a valid `$ty`. +macro_rules! unsafe_impl { + // Implement `$trait` for `$ty` with no bounds. + ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident| $is_bit_valid:expr)?) => {{ + crate::util::macros::__unsafe(); + + $(#[$attr])* + // SAFETY: The caller promises that this is sound. + unsafe impl $trait for $ty { + unsafe_impl!(@method $trait $(; |$candidate| $is_bit_valid)?); + } + }}; + + // Implement all `$traits` for `$ty` with no bounds. + // + // The 2 arms under this one are there so we can apply + // N attributes for each one of M trait implementations. + // The simple solution of: + // + // ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => { + // $( unsafe_impl!( $(#[$attrs])* $ty: $traits ) );* + // } + // + // Won't work. The macro processor sees that the outer repetition + // contains both $attrs and $traits and expects them to match the same + // amount of fragments. + // + // To solve this we must: + // 1. Pack the attributes into a single token tree fragment we can match over. + // 2. Expand the traits. + // 3. Unpack and expand the attributes. + ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => { + unsafe_impl!(@impl_traits_with_packed_attrs { $(#[$attrs])* } $ty: $($traits),*) + }; + + (@impl_traits_with_packed_attrs $attrs:tt $ty:ty: $($traits:ident),*) => {{ + $( unsafe_impl!(@unpack_attrs $attrs $ty: $traits); )* + }}; + + (@unpack_attrs { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => { + unsafe_impl!($(#[$attrs])* $ty: $traits); + }; + + // This arm is identical to the following one, except it contains a + // preceding `const`. If we attempt to handle these with a single arm, there + // is an inherent ambiguity between `const` (the keyword) and `const` (the + // ident match for `$tyvar:ident`). + // + // To explain how this works, consider the following invocation: + // + // unsafe_impl!(const N: usize, T: ?Sized + Copy => Clone for Foo); + // + // In this invocation, here are the assignments to meta-variables: + // + // |---------------|------------| + // | Meta-variable | Assignment | + // |---------------|------------| + // | $constname | N | + // | $constty | usize | + // | $tyvar | T | + // | $optbound | Sized | + // | $bound | Copy | + // | $trait | Clone | + // | $ty | Foo | + // |---------------|------------| + // + // The following arm has the same behavior with the exception of the lack of + // support for a leading `const` parameter. + ( + $(#[$attr:meta])* + const $constname:ident : $constty:ident $(,)? + $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* + => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)? + ) => { + unsafe_impl!( + @inner + $(#[$attr])* + @const $constname: $constty, + $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* + => $trait for $ty $(; |$candidate| $is_bit_valid)? + ); + }; + ( + $(#[$attr:meta])* + $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* + => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)? + ) => {{ + unsafe_impl!( + @inner + $(#[$attr])* + $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* + => $trait for $ty $(; |$candidate| $is_bit_valid)? + ); + }}; + ( + @inner + $(#[$attr:meta])* + $(@const $constname:ident : $constty:ident,)* + $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)* + => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)? + ) => {{ + crate::util::macros::__unsafe(); + + $(#[$attr])* + #[allow(non_local_definitions)] + // SAFETY: The caller promises that this is sound. + unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),* $(, const $constname: $constty,)*> $trait for $ty { + unsafe_impl!(@method $trait $(; |$candidate| $is_bit_valid)?); + } + }}; + + (@method TryFromBytes ; |$candidate:ident| $is_bit_valid:expr) => { + #[allow(clippy::missing_inline_in_public_items, dead_code)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() {} + + #[inline] + fn is_bit_valid($candidate: Maybe<'_, Self, AA>) -> bool { + $is_bit_valid + } + }; + (@method TryFromBytes) => { + #[allow(clippy::missing_inline_in_public_items)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() {} + #[inline(always)] fn is_bit_valid(_: Maybe<'_, Self, AA>) -> bool { true } + }; + (@method $trait:ident) => { + #[allow(clippy::missing_inline_in_public_items, dead_code)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() {} + }; + (@method $trait:ident; |$_candidate:ident| $_is_bit_valid:expr) => { + compile_error!("Can't provide `is_bit_valid` impl for trait other than `TryFromBytes`"); + }; +} + +/// Implements `$trait` for `$ty` where `$ty: TransmuteFrom<$repr>` (and +/// vice-versa). +/// +/// Calling this macro is safe; the internals of the macro emit appropriate +/// trait bounds which ensure that the given impl is sound. +macro_rules! impl_for_transmute_from { + ( + $(#[$attr:meta])* + $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?)? + => $trait:ident for $ty:ty [$($unsafe_cell:ident)? <$repr:ty>] + ) => { + const _: () = { + $(#[$attr])* + #[allow(non_local_definitions)] + + // SAFETY: `is_trait` (defined and used below) requires `T: + // TransmuteFrom`, `R: TransmuteFrom`, and `R: $trait`. It is + // called using `$ty` and `$repr`, ensuring that `$ty` and `$repr` + // have equivalent bit validity, and ensuring that `$repr: $trait`. + // The supported traits - `TryFromBytes`, `FromZeros`, `FromBytes`, + // and `IntoBytes` - are defined only in terms of the bit validity + // of a type. Therefore, `$repr: $trait` ensures that `$ty: $trait` + // is sound. + unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?> $trait for $ty { + #[allow(dead_code, clippy::missing_inline_in_public_items)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() { + use crate::pointer::{*, invariant::Valid}; + + impl_for_transmute_from!(@assert_is_supported_trait $trait); + + fn is_trait() + where + T: TransmuteFrom + ?Sized, + R: TransmuteFrom + ?Sized, + R: $trait, + { + } + + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn f<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?>() { + is_trait::<$ty, $repr>(); + } + } + + impl_for_transmute_from!( + @is_bit_valid + $(<$tyvar $(: $(? $optbound +)* $($bound +)*)?>)? + $trait for $ty [$($unsafe_cell)? <$repr>] + ); + } + }; + }; + (@assert_is_supported_trait TryFromBytes) => {}; + (@assert_is_supported_trait FromZeros) => {}; + (@assert_is_supported_trait FromBytes) => {}; + (@assert_is_supported_trait IntoBytes) => {}; + ( + @is_bit_valid + $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)? + TryFromBytes for $ty:ty [UnsafeCell<$repr:ty>] + ) => { + #[inline] + fn is_bit_valid(candidate: Maybe<'_, Self, A>) -> bool { + let c: Maybe<'_, Self, crate::pointer::invariant::Exclusive> = candidate.into_exclusive_or_pme(); + let c: Maybe<'_, $repr, _> = c.transmute::<_, _, (_, (_, (BecauseExclusive, BecauseExclusive)))>(); + // SAFETY: This macro ensures that `$repr` and `Self` have the same + // size and bit validity. Thus, a bit-valid instance of `$repr` is + // also a bit-valid instance of `Self`. + <$repr as TryFromBytes>::is_bit_valid(c) + } + }; + ( + @is_bit_valid + $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)? + TryFromBytes for $ty:ty [<$repr:ty>] + ) => { + #[inline] + fn is_bit_valid(candidate: $crate::Maybe<'_, Self, A>) -> bool { + // SAFETY: This macro ensures that `$repr` and `Self` have the same + // size and bit validity. Thus, a bit-valid instance of `$repr` is + // also a bit-valid instance of `Self`. + <$repr as TryFromBytes>::is_bit_valid(candidate.transmute()) + } + }; + ( + @is_bit_valid + $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)? + $trait:ident for $ty:ty [$($unsafe_cell:ident)? <$repr:ty>] + ) => { + // Trait other than `TryFromBytes`; no `is_bit_valid` impl. + }; +} + +/// Implements a trait for a type, bounding on each member of the power set of +/// a set of type variables. This is useful for implementing traits for tuples +/// or `fn` types. +/// +/// The last argument is the name of a macro which will be called in every +/// `impl` block, and is expected to expand to the name of the type for which to +/// implement the trait. +/// +/// For example, the invocation: +/// ```ignore +/// unsafe_impl_for_power_set!(A, B => Foo for type!(...)) +/// ``` +/// ...expands to: +/// ```ignore +/// unsafe impl Foo for type!() { ... } +/// unsafe impl Foo for type!(B) { ... } +/// unsafe impl Foo for type!(A, B) { ... } +/// ``` +macro_rules! unsafe_impl_for_power_set { + ( + $first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...) + $(; |$candidate:ident| $is_bit_valid:expr)? + ) => { + unsafe_impl_for_power_set!( + $($rest),* $(-> $ret)? => $trait for $macro!(...) + $(; |$candidate| $is_bit_valid)? + ); + unsafe_impl_for_power_set!( + @impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...) + $(; |$candidate| $is_bit_valid)? + ); + }; + ( + $(-> $ret:ident)? => $trait:ident for $macro:ident!(...) + $(; |$candidate:ident| $is_bit_valid:expr)? + ) => { + unsafe_impl_for_power_set!( + @impl $(-> $ret)? => $trait for $macro!(...) + $(; |$candidate| $is_bit_valid)? + ); + }; + ( + @impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...) + $(; |$candidate:ident| $is_bit_valid:expr)? + ) => { + unsafe_impl!( + $($vars,)* $($ret)? => $trait for $macro!($($vars),* $(-> $ret)?) + $(; |$candidate| $is_bit_valid)? + ); + }; +} + +/// Expands to an `Option` type with the given argument types and +/// return type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_extern_c_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + +/// Expands to an `Option` type with the given argument +/// types and return type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_unsafe_extern_c_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + +/// Expands to an `Option` type with the given argument types and return +/// type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + +/// Expands to an `Option` type with the given argument types and +/// return type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_unsafe_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + +/// Implements trait(s) for a type or verifies the given implementation by +/// referencing an existing (derived) implementation. +/// +/// This macro exists so that we can provide zerocopy-derive as an optional +/// dependency and still get the benefit of using its derives to validate that +/// our trait impls are sound. +/// +/// When compiling without `--cfg 'feature = "derive"` and without `--cfg test`, +/// `impl_or_verify!` emits the provided trait impl. When compiling with either +/// of those cfgs, it is expected that the type in question is deriving the +/// traits instead. In this case, `impl_or_verify!` emits code which validates +/// that the given trait impl is at least as restrictive as the the impl emitted +/// by the custom derive. This has the effect of confirming that the impl which +/// is emitted when the `derive` feature is disabled is actually sound (on the +/// assumption that the impl emitted by the custom derive is sound). +/// +/// The caller is still required to provide a safety comment (e.g. using the +/// `const _: () = unsafe` macro) . The reason for this restriction is that, while +/// `impl_or_verify!` can guarantee that the provided impl is sound when it is +/// compiled with the appropriate cfgs, there is no way to guarantee that it is +/// ever compiled with those cfgs. In particular, it would be possible to +/// accidentally place an `impl_or_verify!` call in a context that is only ever +/// compiled when the `derive` feature is disabled. If that were to happen, +/// there would be nothing to prevent an unsound trait impl from being emitted. +/// Requiring a safety comment reduces the likelihood of emitting an unsound +/// impl in this case, and also provides useful documentation for readers of the +/// code. +/// +/// Finally, if a `TryFromBytes::is_bit_valid` impl is provided, it must adhere +/// to the safety preconditions of [`unsafe_impl!`]. +/// +/// ## Example +/// +/// ```rust,ignore +/// // Note that these derives are gated by `feature = "derive"` +/// #[cfg_attr(any(feature = "derive", test), derive(FromZeros, FromBytes, IntoBytes, Unaligned))] +/// #[repr(transparent)] +/// struct Wrapper(T); +/// +/// const _: () = unsafe { +/// /// SAFETY: +/// /// `Wrapper` is `repr(transparent)`, so it is sound to implement any +/// /// zerocopy trait if `T` implements that trait. +/// impl_or_verify!(T: FromZeros => FromZeros for Wrapper); +/// impl_or_verify!(T: FromBytes => FromBytes for Wrapper); +/// impl_or_verify!(T: IntoBytes => IntoBytes for Wrapper); +/// impl_or_verify!(T: Unaligned => Unaligned for Wrapper); +/// } +/// ``` +macro_rules! impl_or_verify { + // The following two match arms follow the same pattern as their + // counterparts in `unsafe_impl!`; see the documentation on those arms for + // more details. + ( + const $constname:ident : $constty:ident $(,)? + $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* + => $trait:ident for $ty:ty + ) => { + impl_or_verify!(@impl { unsafe_impl!( + const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty + ); }); + impl_or_verify!(@verify $trait, { + impl Subtrait for $ty {} + }); + }; + ( + $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* + => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)? + ) => { + impl_or_verify!(@impl { unsafe_impl!( + $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty + $(; |$candidate| $is_bit_valid)? + ); }); + impl_or_verify!(@verify $trait, { + impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + }); + }; + (@impl $impl_block:tt) => { + #[cfg(not(any(feature = "derive", test)))] + { $impl_block }; + }; + (@verify $trait:ident, $impl_block:tt) => { + #[cfg(any(feature = "derive", test))] + { + // On some toolchains, `Subtrait` triggers the `dead_code` lint + // because it is implemented but never used. + #[allow(dead_code)] + trait Subtrait: $trait {} + $impl_block + }; + }; +} + +/// Implements `KnownLayout` for a sized type. +macro_rules! impl_known_layout { + ($(const $constvar:ident : $constty:ty, $tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => { + $(impl_known_layout!(@inner const $constvar: $constty, $tyvar $(: ?$optbound)? => $ty);)* + }; + ($($tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => { + $(impl_known_layout!(@inner , $tyvar $(: ?$optbound)? => $ty);)* + }; + ($($(#[$attrs:meta])* $ty:ty),*) => { $(impl_known_layout!(@inner , => $(#[$attrs])* $ty);)* }; + (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $(#[$attrs:meta])* $ty:ty) => { + const _: () = { + use core::ptr::NonNull; + + #[allow(non_local_definitions)] + $(#[$attrs])* + // SAFETY: Delegates safety to `DstLayout::for_type`. + unsafe impl<$($tyvar $(: ?$optbound)?)? $(, const $constvar : $constty)?> KnownLayout for $ty { + #[allow(clippy::missing_inline_in_public_items)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {} + + type PointerMetadata = (); + + // SAFETY: `CoreMaybeUninit::LAYOUT` and `T::LAYOUT` are + // identical because `CoreMaybeUninit` has the same size and + // alignment as `T` [1], and `CoreMaybeUninit` admits + // uninitialized bytes in all positions. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, + // alignment, and ABI as `T` + type MaybeUninit = core::mem::MaybeUninit; + + const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>(); + + // SAFETY: `.cast` preserves address and provenance. + // + // FIXME(#429): Add documentation to `.cast` that promises that + // it preserves provenance. + #[inline(always)] + fn raw_from_ptr_len(bytes: NonNull, _meta: ()) -> NonNull { + bytes.cast::() + } + + #[inline(always)] + fn pointer_to_metadata(_ptr: *mut Self) -> () { + } + } + }; + }; +} + +/// Implements `KnownLayout` for a type in terms of the implementation of +/// another type with the same representation. +/// +/// # Safety +/// +/// - `$ty` and `$repr` must have the same: +/// - Fixed prefix size +/// - Alignment +/// - (For DSTs) trailing slice element size +/// - It must be valid to perform an `as` cast from `*mut $repr` to `*mut $ty`, +/// and this operation must preserve referent size (ie, `size_of_val_raw`). +macro_rules! unsafe_impl_known_layout { + ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => {{ + use core::ptr::NonNull; + + crate::util::macros::__unsafe(); + + #[allow(non_local_definitions)] + // SAFETY: The caller promises that this is sound. + unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty { + #[allow(clippy::missing_inline_in_public_items, dead_code)] + #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] + fn only_derive_is_allowed_to_implement_this_trait() {} + + type PointerMetadata = <$repr as KnownLayout>::PointerMetadata; + type MaybeUninit = <$repr as KnownLayout>::MaybeUninit; + + const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT; + + // SAFETY: All operations preserve address and provenance. Caller + // has promised that the `as` cast preserves size. + // + // FIXME(#429): Add documentation to `NonNull::new_unchecked` that + // it preserves provenance. + #[inline(always)] + fn raw_from_ptr_len(bytes: NonNull, meta: <$repr as KnownLayout>::PointerMetadata) -> NonNull { + #[allow(clippy::as_conversions)] + let ptr = <$repr>::raw_from_ptr_len(bytes, meta).as_ptr() as *mut Self; + // SAFETY: `ptr` was converted from `bytes`, which is non-null. + unsafe { NonNull::new_unchecked(ptr) } + } + + #[inline(always)] + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata { + #[allow(clippy::as_conversions)] + let ptr = ptr as *mut $repr; + <$repr>::pointer_to_metadata(ptr) + } + } + }}; +} + +/// Uses `align_of` to confirm that a type or set of types have alignment 1. +/// +/// Note that `align_of` requires `T: Sized`, so this macro doesn't work for +/// unsized types. +macro_rules! assert_unaligned { + ($($tys:ty),*) => { + $( + // We only compile this assertion under `cfg(test)` to avoid taking + // an extra non-dev dependency (and making this crate more expensive + // to compile for our dependents). + #[cfg(test)] + static_assertions::const_assert_eq!(core::mem::align_of::<$tys>(), 1); + )* + }; +} + +/// Emits a function definition as either `const fn` or `fn` depending on +/// whether the current toolchain version supports `const fn` with generic trait +/// bounds. +macro_rules! maybe_const_trait_bounded_fn { + // This case handles both `self` methods (where `self` is by value) and + // non-method functions. Each `$args` may optionally be followed by `: + // $arg_tys:ty`, which can be omitted for `self`. + ($(#[$attr:meta])* $vis:vis const fn $name:ident($($args:ident $(: $arg_tys:ty)?),* $(,)?) $(-> $ret_ty:ty)? $body:block) => { + #[cfg(zerocopy_generic_bounds_in_const_fn_1_61_0)] + $(#[$attr])* $vis const fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body + + #[cfg(not(zerocopy_generic_bounds_in_const_fn_1_61_0))] + $(#[$attr])* $vis fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body + }; +} + +/// Either panic (if the current Rust toolchain supports panicking in `const +/// fn`) or evaluate a constant that will cause an array indexing error whose +/// error message will include the format string. +/// +/// The type that this expression evaluates to must be `Copy`, or else the +/// non-panicking desugaring will fail to compile. +macro_rules! const_panic { + (@non_panic $($_arg:tt)+) => {{ + // This will type check to whatever type is expected based on the call + // site. + let panic: [_; 0] = []; + // This will always fail (since we're indexing into an array of size 0. + #[allow(unconditional_panic)] + panic[0] + }}; + ($($arg:tt)+) => {{ + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + panic!($($arg)+); + #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] + const_panic!(@non_panic $($arg)+) + }}; +} + +/// Either assert (if the current Rust toolchain supports panicking in `const +/// fn`) or evaluate the expression and, if it evaluates to `false`, call +/// `const_panic!`. This is used in place of `assert!` in const contexts to +/// accommodate old toolchains. +macro_rules! const_assert { + ($e:expr) => {{ + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + assert!($e); + #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] + { + let e = $e; + if !e { + let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e))); + } + } + }}; + ($e:expr, $($args:tt)+) => {{ + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + assert!($e, $($args)+); + #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] + { + let e = $e; + if !e { + let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e), ": ", stringify!($arg)), $($args)*); + } + } + }}; +} + +/// Like `const_assert!`, but relative to `debug_assert!`. +macro_rules! const_debug_assert { + ($e:expr $(, $msg:expr)?) => {{ + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + debug_assert!($e $(, $msg)?); + #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] + { + // Use this (rather than `#[cfg(debug_assertions)]`) to ensure that + // `$e` is always compiled even if it will never be evaluated at + // runtime. + if cfg!(debug_assertions) { + let e = $e; + if !e { + let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e) $(, ": ", $msg)?)); + } + } + } + }} +} + +/// Either invoke `unreachable!()` or `loop {}` depending on whether the Rust +/// toolchain supports panicking in `const fn`. +macro_rules! const_unreachable { + () => {{ + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + unreachable!(); + + #[cfg(not(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] + loop {} + }}; +} + +/// Asserts at compile time that `$condition` is true for `Self` or the given +/// `$tyvar`s. Unlike `const_assert`, this is *strictly* a compile-time check; +/// it cannot be evaluated in a runtime context. The condition is checked after +/// monomorphization and, upon failure, emits a compile error. +macro_rules! static_assert { + (Self $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )? => $condition:expr $(, $args:tt)*) => {{ + trait StaticAssert { + const ASSERT: bool; + } + + impl StaticAssert for T { + const ASSERT: bool = { + const_assert!($condition $(, $args)*); + $condition + }; + } + + const_assert!(::ASSERT); + }}; + ($($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* => $condition:expr $(, $args:tt)*) => {{ + trait StaticAssert { + const ASSERT: bool; + } + + // NOTE: We use `PhantomData` so we can support unsized types. + impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?,)*> StaticAssert for ($(core::marker::PhantomData<$tyvar>,)*) { + const ASSERT: bool = { + const_assert!($condition $(, $args)*); + $condition + }; + } + + const_assert!(<($(core::marker::PhantomData<$tyvar>,)*) as StaticAssert>::ASSERT); + }}; +} + +/// Assert at compile time that `tyvar` does not have a zero-sized DST +/// component. +macro_rules! static_assert_dst_is_not_zst { + ($tyvar:ident) => {{ + use crate::KnownLayout; + static_assert!($tyvar: ?Sized + KnownLayout => { + let dst_is_zst = match $tyvar::LAYOUT.size_info { + crate::SizeInfo::Sized { .. } => false, + crate::SizeInfo::SliceDst(TrailingSliceLayout { elem_size, .. }) => { + elem_size == 0 + } + }; + !dst_is_zst + }, "cannot call this method on a dynamically-sized type whose trailing slice element is zero-sized"); + }} +} + +/// # Safety +/// +/// The caller must ensure that the cast does not grow the size of the referent. +/// Preserving or shrinking the size of the referent are both acceptable. +macro_rules! cast { + ($p:expr) => {{ + let ptr: crate::pointer::PtrInner<'_, _> = $p; + let ptr = ptr.as_non_null(); + let ptr = ptr.as_ptr(); + #[allow(clippy::as_conversions)] + let ptr = ptr as *mut _; + #[allow(unused_unsafe)] + // SAFETY: `NonNull::as_ptr` returns a non-null pointer, so the argument + // to `NonNull::new_unchecked` is also non-null. + let ptr = unsafe { core::ptr::NonNull::new_unchecked(ptr) }; + // SAFETY: The caller promises that the cast preserves or shrinks + // referent size. By invariant on `$p: PtrInner` (guaranteed by type + // annotation above), `$p` refers to a byte range entirely contained + // inside of a single allocation, has provenance for that whole byte + // range, and will not outlive the allocation. All of these conditions + // are preserved when preserving or shrinking referent size. + crate::pointer::PtrInner::new(ptr) + }}; +} + +/// Implements `TransmuteFrom` and `SizeEq` for `T` and `$wrapper`. +/// +/// # Safety +/// +/// `T` and `$wrapper` must have the same bit validity, and must have the +/// same size in the sense of `SizeEq`. +macro_rules! unsafe_impl_for_transparent_wrapper { + (T $(: ?$optbound:ident)? => $wrapper:ident) => {{ + crate::util::macros::__unsafe(); + + use crate::pointer::{TransmuteFrom, PtrInner, SizeEq, invariant::Valid}; + + // SAFETY: The caller promises that `T` and `$wrapper` have the same + // bit validity. + unsafe impl TransmuteFrom for $wrapper {} + // SAFETY: See previous safety comment. + unsafe impl TransmuteFrom<$wrapper, Valid, Valid> for T {} + // SAFETY: The caller promises that `T` and `$wrapper` satisfy + // `SizeEq`. + unsafe impl SizeEq for $wrapper { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, $wrapper> { + // SAFETY: See previous safety comment. + unsafe { cast!(t) } + } + } + // SAFETY: See previous safety comment. + unsafe impl SizeEq<$wrapper> for T { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, $wrapper>) -> PtrInner<'_, T> { + // SAFETY: See previous safety comment. + unsafe { cast!(t) } + } + } + }}; +} + +macro_rules! impl_transitive_transmute_from { + ($($tyvar:ident $(: ?$optbound:ident)?)? => $t:ty => $u:ty => $v:ty) => { + const _: () = { + use crate::pointer::{TransmuteFrom, PtrInner, SizeEq, invariant::Valid}; + + // SAFETY: Since `$u: SizeEq<$t>` and `$v: SizeEq`, this impl is + // transitively sound. + unsafe impl<$($tyvar $(: ?$optbound)?)?> SizeEq<$t> for $v + where + $u: SizeEq<$t>, + $v: SizeEq<$u>, + { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, $t>) -> PtrInner<'_, $v> { + let u = <$u as SizeEq<_>>::cast_from_raw(t); + <$v as SizeEq<_>>::cast_from_raw(u) + } + } + + // SAFETY: Since `$u: TransmuteFrom<$t, Valid, Valid>`, it is sound + // to transmute a bit-valid `$t` to a bit-valid `$u`. Since `$v: + // TransmuteFrom<$u, Valid, Valid>`, it is sound to transmute that + // bit-valid `$u` to a bit-valid `$v`. + unsafe impl<$($tyvar $(: ?$optbound)?)?> TransmuteFrom<$t, Valid, Valid> for $v + where + $u: TransmuteFrom<$t, Valid, Valid>, + $v: TransmuteFrom<$u, Valid, Valid>, + {} + }; + }; +} + +#[rustfmt::skip] +macro_rules! impl_size_eq { + ($t:ty, $u:ty) => { + const _: () = { + use crate::{KnownLayout, pointer::{PtrInner, SizeEq}}; + + static_assert!(=> { + let t = <$t as KnownLayout>::LAYOUT; + let u = <$u as KnownLayout>::LAYOUT; + t.align.get() >= u.align.get() && match (t.size_info, u.size_info) { + (SizeInfo::Sized { size: t }, SizeInfo::Sized { size: u }) => t == u, + ( + SizeInfo::SliceDst(TrailingSliceLayout { offset: t_offset, elem_size: t_elem_size }), + SizeInfo::SliceDst(TrailingSliceLayout { offset: u_offset, elem_size: u_elem_size }) + ) => t_offset == u_offset && t_elem_size == u_elem_size, + _ => false, + } + }); + + // SAFETY: See inline. + unsafe impl SizeEq<$t> for $u { + #[inline(always)] + fn cast_from_raw(t: PtrInner<'_, $t>) -> PtrInner<'_, $u> { + // SAFETY: We've asserted that their + // `KnownLayout::LAYOUT.size_info`s are equal, and so this + // cast is guaranteed to preserve address and referent size. + // It trivially preserves provenance. + unsafe { cast!(t) } + } + } + // SAFETY: See previous safety comment. + unsafe impl SizeEq<$u> for $t { + #[inline(always)] + fn cast_from_raw(u: PtrInner<'_, $u>) -> PtrInner<'_, $t> { + // SAFETY: See previous safety comment. + unsafe { cast!(u) } + } + } + }; + }; +} + +/// Invokes `$blk` in a context in which `$src<$t>` and `$dst<$u>` implement +/// `SizeEq`. +/// +/// This macro emits code which implements `SizeEq`, and ensures that the impl +/// is sound via PME. +/// +/// # Safety +/// +/// Inside of `$blk`, the caller must only use `$src` and `$dst` as `$src<$t>` +/// and `$dst<$u>`. The caller must not use `$src` or `$dst` to wrap any other +/// types. +macro_rules! unsafe_with_size_eq { + (<$src:ident<$t:ident>, $dst:ident<$u:ident>> $blk:expr) => {{ + crate::util::macros::__unsafe(); + + use crate::{KnownLayout, pointer::PtrInner}; + + #[repr(transparent)] + struct $src(T); + + #[repr(transparent)] + struct $dst(U); + + // SAFETY: Since `$src` is a `#[repr(transparent)]` wrapper around + // `T`, it has the same bit validity and size as `T`. + unsafe_impl_for_transparent_wrapper!(T: ?Sized => $src); + + // SAFETY: Since `$dst` is a `#[repr(transparent)]` wrapper around + // `T`, it has the same bit validity and size as `T`. + unsafe_impl_for_transparent_wrapper!(T: ?Sized => $dst); + + // SAFETY: `$src` is a `#[repr(transparent)]` wrapper around `T` with + // no added semantics. + unsafe impl InvariantsEq<$src> for T {} + + // SAFETY: `$dst` is a `#[repr(transparent)]` wrapper around `T` with + // no added semantics. + unsafe impl InvariantsEq<$dst> for T {} + + // SAFETY: See inline for the soundness of this impl when + // `cast_from_raw` is actually instantiated (otherwise, PMEs may not be + // triggered). + // + // We manually instantiate `cast_from_raw` below to ensure that this PME + // can be triggered, and the caller promises not to use `$src` and + // `$dst` with any wrapped types other than `$t` and `$u` respectively. + unsafe impl SizeEq<$src> for $dst + where + T: KnownLayout, + U: KnownLayout, + { + fn cast_from_raw(src: PtrInner<'_, $src>) -> PtrInner<'_, Self> { + // SAFETY: `crate::layout::cast_from_raw` promises to satisfy + // the safety invariants of `SizeEq::cast_from_raw`, or to + // generate a PME. Since `$src` and `$dst` are + // `#[repr(transparent)]` wrappers around `T` and `U` + // respectively, a `cast_from_raw` impl which satisfies the + // conditions for casting from `NonNull` to `NonNull` also + // satisfies the conditions for casting from `NonNull<$src>` + // to `NonNull<$dst>`. + + // SAFETY: By the preceding safety comment, this cast preserves + // referent size. + let src: PtrInner<'_, T> = unsafe { cast!(src) }; + let dst: PtrInner<'_, U> = crate::layout::cast_from_raw(src); + // SAFETY: By the preceding safety comment, this cast preserves + // referent size. + unsafe { cast!(dst) } + } + } + + // See safety comment on the preceding `unsafe impl` block for an + // explanation of why we need this block. + if 1 == 0 { + let ptr = <$t as KnownLayout>::raw_dangling(); + #[allow(unused_unsafe)] + // SAFETY: This call is never executed. + let ptr = unsafe { crate::pointer::PtrInner::new(ptr) }; + #[allow(unused_unsafe)] + // SAFETY: This call is never executed. + let ptr = unsafe { cast!(ptr) }; + let _ = <$dst<$u> as SizeEq<$src<$t>>>::cast_from_raw(ptr); + } + + impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for $src[]); + impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for $src[]); + impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for $src[]); + impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for $src[]); + + impl_for_transmute_from!(U: ?Sized + TryFromBytes => TryFromBytes for $dst[]); + impl_for_transmute_from!(U: ?Sized + FromBytes => FromBytes for $dst[]); + impl_for_transmute_from!(U: ?Sized + FromZeros => FromZeros for $dst[]); + impl_for_transmute_from!(U: ?Sized + IntoBytes => IntoBytes for $dst[]); + + // SAFETY: `$src` is a `#[repr(transparent)]` wrapper around `T`, and + // so permits interior mutation exactly when `T` does. + unsafe_impl!(T: ?Sized + Immutable => Immutable for $src); + + // SAFETY: `$dst` is a `#[repr(transparent)]` wrapper around `T`, and + // so permits interior mutation exactly when `T` does. + unsafe_impl!(T: ?Sized + Immutable => Immutable for $dst); + + $blk + }}; +} + +/// A no-op `unsafe fn` for use in macro expansions. +/// +/// Calling this function in a macro expansion ensures that the macro's caller +/// must wrap the call in `unsafe { ... }`. +pub(crate) const unsafe fn __unsafe() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/util/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/util/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,827 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +pub(crate) mod macros; + +#[doc(hidden)] +pub mod macro_util; + +use core::{ + marker::PhantomData, + mem::{self, ManuallyDrop}, + num::NonZeroUsize, + ptr::NonNull, +}; + +use super::*; + +/// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the +/// wrapped `T` is. +pub(crate) struct SendSyncPhantomData(PhantomData); + +// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound +// to be called from multiple threads. +unsafe impl Send for SendSyncPhantomData {} +// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound +// to be called from multiple threads. +unsafe impl Sync for SendSyncPhantomData {} + +impl Default for SendSyncPhantomData { + fn default() -> SendSyncPhantomData { + SendSyncPhantomData(PhantomData) + } +} + +impl PartialEq for SendSyncPhantomData { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl Eq for SendSyncPhantomData {} + +pub(crate) trait AsAddress { + fn addr(self) -> usize; +} + +impl AsAddress for &T { + #[inline(always)] + fn addr(self) -> usize { + let ptr: *const T = self; + AsAddress::addr(ptr) + } +} + +impl AsAddress for &mut T { + #[inline(always)] + fn addr(self) -> usize { + let ptr: *const T = self; + AsAddress::addr(ptr) + } +} + +impl AsAddress for NonNull { + #[inline(always)] + fn addr(self) -> usize { + AsAddress::addr(self.as_ptr()) + } +} + +impl AsAddress for *const T { + #[inline(always)] + fn addr(self) -> usize { + // FIXME(#181), FIXME(https://github.com/rust-lang/rust/issues/95228): + // Use `.addr()` instead of `as usize` once it's stable, and get rid of + // this `allow`. Currently, `as usize` is the only way to accomplish + // this. + #[allow(clippy::as_conversions)] + #[cfg_attr( + __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, + allow(lossy_provenance_casts) + )] + return self.cast::<()>() as usize; + } +} + +impl AsAddress for *mut T { + #[inline(always)] + fn addr(self) -> usize { + let ptr: *const T = self; + AsAddress::addr(ptr) + } +} + +/// Validates that `t` is aligned to `align_of::()`. +#[inline(always)] +pub(crate) fn validate_aligned_to(t: T) -> Result<(), AlignmentError<(), U>> { + // `mem::align_of::()` is guaranteed to return a non-zero value, which in + // turn guarantees that this mod operation will not panic. + #[allow(clippy::arithmetic_side_effects)] + let remainder = t.addr() % mem::align_of::(); + if remainder == 0 { + Ok(()) + } else { + // SAFETY: We just confirmed that `t.addr() % align_of::() != 0`. + // That's only possible if `align_of::() > 1`. + Err(unsafe { AlignmentError::new_unchecked(()) }) + } +} + +/// Returns the bytes needed to pad `len` to the next multiple of `align`. +/// +/// This function assumes that align is a power of two; there are no guarantees +/// on the answer it gives if this is not the case. +#[cfg_attr( + kani, + kani::requires(len <= isize::MAX as usize), + kani::requires(align.is_power_of_two()), + kani::ensures(|&p| (len + p) % align.get() == 0), + // Ensures that we add the minimum required padding. + kani::ensures(|&p| p < align.get()), +)] +pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize { + #[cfg(kani)] + #[kani::proof_for_contract(padding_needed_for)] + fn proof() { + padding_needed_for(kani::any(), kani::any()); + } + + // Abstractly, we want to compute: + // align - (len % align). + // Handling the case where len%align is 0. + // Because align is a power of two, len % align = len & (align-1). + // Guaranteed not to underflow as align is nonzero. + #[allow(clippy::arithmetic_side_effects)] + let mask = align.get() - 1; + + // To efficiently subtract this value from align, we can use the bitwise complement. + // Note that ((!len) & (align-1)) gives us a number that with (len & + // (align-1)) sums to align-1. So subtracting 1 from x before taking the + // complement subtracts `len` from `align`. Some quick inspection of + // cases shows that this also handles the case where `len % align = 0` + // correctly too: len-1 % align then equals align-1, so the complement mod + // align will be 0, as desired. + // + // The following reasoning can be verified quickly by an SMT solver + // supporting the theory of bitvectors: + // ```smtlib + // ; Naive implementation of padding + // (define-fun padding1 ( + // (len (_ BitVec 32)) + // (align (_ BitVec 32))) (_ BitVec 32) + // (ite + // (= (_ bv0 32) (bvand len (bvsub align (_ bv1 32)))) + // (_ bv0 32) + // (bvsub align (bvand len (bvsub align (_ bv1 32)))))) + // + // ; The implementation below + // (define-fun padding2 ( + // (len (_ BitVec 32)) + // (align (_ BitVec 32))) (_ BitVec 32) + // (bvand (bvnot (bvsub len (_ bv1 32))) (bvsub align (_ bv1 32)))) + // + // (define-fun is-power-of-two ((x (_ BitVec 32))) Bool + // (= (_ bv0 32) (bvand x (bvsub x (_ bv1 32))))) + // + // (declare-const len (_ BitVec 32)) + // (declare-const align (_ BitVec 32)) + // ; Search for a case where align is a power of two and padding2 disagrees with padding1 + // (assert (and (is-power-of-two align) + // (not (= (padding1 len align) (padding2 len align))))) + // (simplify (padding1 (_ bv300 32) (_ bv32 32))) ; 20 + // (simplify (padding2 (_ bv300 32) (_ bv32 32))) ; 20 + // (simplify (padding1 (_ bv322 32) (_ bv32 32))) ; 30 + // (simplify (padding2 (_ bv322 32) (_ bv32 32))) ; 30 + // (simplify (padding1 (_ bv8 32) (_ bv8 32))) ; 0 + // (simplify (padding2 (_ bv8 32) (_ bv8 32))) ; 0 + // (check-sat) ; unsat, also works for 64-bit bitvectors + // ``` + !(len.wrapping_sub(1)) & mask +} + +/// Rounds `n` down to the largest value `m` such that `m <= n` and `m % align +/// == 0`. +/// +/// # Panics +/// +/// May panic if `align` is not a power of two. Even if it doesn't panic in this +/// case, it will produce nonsense results. +#[inline(always)] +#[cfg_attr( + kani, + kani::requires(align.is_power_of_two()), + kani::ensures(|&m| m <= n && m % align.get() == 0), + // Guarantees that `m` is the *largest* value such that `m % align == 0`. + kani::ensures(|&m| { + // If this `checked_add` fails, then the next multiple would wrap + // around, which trivially satisfies the "largest value" requirement. + m.checked_add(align.get()).map(|next_mul| next_mul > n).unwrap_or(true) + }) +)] +pub(crate) const fn round_down_to_next_multiple_of_alignment( + n: usize, + align: NonZeroUsize, +) -> usize { + #[cfg(kani)] + #[kani::proof_for_contract(round_down_to_next_multiple_of_alignment)] + fn proof() { + round_down_to_next_multiple_of_alignment(kani::any(), kani::any()); + } + + let align = align.get(); + #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)] + debug_assert!(align.is_power_of_two()); + + // Subtraction can't underflow because `align.get() >= 1`. + #[allow(clippy::arithmetic_side_effects)] + let mask = !(align - 1); + n & mask +} + +pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { + if a.get() < b.get() { + b + } else { + a + } +} + +pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { + if a.get() > b.get() { + b + } else { + a + } +} + +/// Copies `src` into the prefix of `dst`. +/// +/// # Safety +/// +/// The caller guarantees that `src.len() <= dst.len()`. +#[inline(always)] +pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) { + debug_assert!(src.len() <= dst.len()); + // SAFETY: This invocation satisfies the safety contract of + // copy_nonoverlapping [1]: + // - `src.as_ptr()` is trivially valid for reads of `src.len()` bytes + // - `dst.as_ptr()` is valid for writes of `src.len()` bytes, because the + // caller has promised that `src.len() <= dst.len()` + // - `src` and `dst` are, trivially, properly aligned + // - the region of memory beginning at `src` with a size of `src.len()` + // bytes does not overlap with the region of memory beginning at `dst` + // with the same size, because `dst` is derived from an exclusive + // reference. + unsafe { + core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); + }; +} + +/// Unsafely transmutes the given `src` into a type `Dst`. +/// +/// # Safety +/// +/// The value `src` must be a valid instance of `Dst`. +#[inline(always)] +pub(crate) const unsafe fn transmute_unchecked(src: Src) -> Dst { + static_assert!(Src, Dst => core::mem::size_of::() == core::mem::size_of::()); + + #[repr(C)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + + // SAFETY: Since `Transmute` is `#[repr(C)]`, its `src` and `dst` + // fields both start at the same offset and the types of those fields are + // transparent wrappers around `Src` and `Dst` [1]. Consequently, + // initializng `Transmute` with with `src` and then reading out `dst` is + // equivalent to transmuting from `Src` to `Dst` [2]. Transmuting from `src` + // to `Dst` is valid because — by contract on the caller — `src` is a valid + // instance of `Dst`. + // + // [1] Per https://doc.rust-lang.org/1.82.0/std/mem/struct.ManuallyDrop.html: + // + // `ManuallyDrop` is guaranteed to have the same layout and bit + // validity as `T`, and is subject to the same layout optimizations as + // `T`. + // + // [2] Per https://doc.rust-lang.org/1.82.0/reference/items/unions.html#reading-and-writing-union-fields: + // + // Effectively, writing to and then reading from a union with the C + // representation is analogous to a transmute from the type used for + // writing to the type used for reading. + unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) } +} + +/// Uses `allocate` to create a `Box`. +/// +/// # Errors +/// +/// Returns an error on allocation failure. Allocation failure is guaranteed +/// never to cause a panic or an abort. +/// +/// # Safety +/// +/// `allocate` must be either `alloc::alloc::alloc` or +/// `alloc::alloc::alloc_zeroed`. The referent of the box returned by `new_box` +/// has the same bit-validity as the referent of the pointer returned by the +/// given `allocate` and sufficient size to store `T` with `meta`. +#[must_use = "has no side effects (other than allocation)"] +#[cfg(feature = "alloc")] +#[inline] +pub(crate) unsafe fn new_box( + meta: T::PointerMetadata, + allocate: unsafe fn(core::alloc::Layout) -> *mut u8, +) -> Result, AllocError> +where + T: ?Sized + crate::KnownLayout, +{ + let size = match T::size_for_metadata(meta) { + Some(size) => size, + None => return Err(AllocError), + }; + + let align = T::LAYOUT.align.get(); + // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a bug in + // which sufficiently-large allocations (those which, when rounded up to the + // alignment, overflow `isize`) are not rejected, which can cause undefined + // behavior. See #64 for details. + // + // FIXME(#67): Once our MSRV is > 1.64.0, remove this assertion. + #[allow(clippy::as_conversions)] + let max_alloc = (isize::MAX as usize).saturating_sub(align); + if size > max_alloc { + return Err(AllocError); + } + + // FIXME(https://github.com/rust-lang/rust/issues/55724): Use + // `Layout::repeat` once it's stabilized. + let layout = Layout::from_size_align(size, align).or(Err(AllocError))?; + + let ptr = if layout.size() != 0 { + // SAFETY: By contract on the caller, `allocate` is either + // `alloc::alloc::alloc` or `alloc::alloc::alloc_zeroed`. The above + // check ensures their shared safety precondition: that the supplied + // layout is not zero-sized type [1]. + // + // [1] Per https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.alloc: + // + // This function is unsafe because undefined behavior can result if + // the caller does not ensure that layout has non-zero size. + let ptr = unsafe { allocate(layout) }; + match NonNull::new(ptr) { + Some(ptr) => ptr, + None => return Err(AllocError), + } + } else { + let align = T::LAYOUT.align.get(); + // We use `transmute` instead of an `as` cast since Miri (with strict + // provenance enabled) notices and complains that an `as` cast creates a + // pointer with no provenance. Miri isn't smart enough to realize that + // we're only executing this branch when we're constructing a zero-sized + // `Box`, which doesn't require provenance. + // + // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. All + // bits of a `usize` are initialized. + #[allow(unknown_lints)] // For `integer_to_ptr_transmutes` + #[allow(clippy::useless_transmute, integer_to_ptr_transmutes)] + let dangling = unsafe { mem::transmute::(align) }; + // SAFETY: `dangling` is constructed from `T::LAYOUT.align`, which is a + // `NonZeroUsize`, which is guaranteed to be non-zero. + // + // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is + // zero, but it does require a non-null dangling pointer for its + // allocation. + // + // FIXME(https://github.com/rust-lang/rust/issues/95228): Use + // `std::ptr::without_provenance` once it's stable. That may optimize + // better. As written, Rust may assume that this consumes "exposed" + // provenance, and thus Rust may have to assume that this may consume + // provenance from any pointer whose provenance has been exposed. + unsafe { NonNull::new_unchecked(dangling) } + }; + + let ptr = T::raw_from_ptr_len(ptr, meta); + + // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. Make sure to + // include a justification that `ptr.as_ptr()` is validly-aligned in the ZST + // case (in which we manually construct a dangling pointer) and to justify + // why `Box` is safe to drop (it's because `allocate` uses the system + // allocator). + #[allow(clippy::undocumented_unsafe_blocks)] + Ok(unsafe { alloc::boxed::Box::from_raw(ptr.as_ptr()) }) +} + +mod len_of { + use super::*; + + /// A witness type for metadata of a valid instance of `&T`. + pub(crate) struct MetadataOf { + /// # Safety + /// + /// The size of an instance of `&T` with the given metadata is not + /// larger than `isize::MAX`. + meta: T::PointerMetadata, + _p: PhantomData, + } + + impl Copy for MetadataOf {} + impl Clone for MetadataOf { + fn clone(&self) -> Self { + *self + } + } + + impl MetadataOf + where + T: KnownLayout, + { + /// Returns `None` if `meta` is greater than `t`'s metadata. + #[inline(always)] + pub(crate) fn new_in_bounds(t: &T, meta: usize) -> Option + where + T: KnownLayout, + { + if meta <= Ptr::from_ref(t).len() { + // SAFETY: We have checked that `meta` is not greater than `t`'s + // metadata, which, by invariant on `&T`, addresses no more than + // `isize::MAX` bytes [1][2]. + // + // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: + // + // For all types, `T: ?Sized`, and for all `t: &T` or `t: + // &mut T`, when such values cross an API boundary, the + // following invariants must generally be upheld: + // + // * `t` is non-null + // * `t` is aligned to `align_of_val(t)` + // * if `size_of_val(t) > 0`, then `t` is dereferenceable for + // `size_of_val(t)` many bytes + // + // If `t` points at address `a`, being "dereferenceable" for + // N bytes means that the memory range `[a, a + N)` is all + // contained within a single allocated object. + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object: + // + // For any allocated object with `base` address, `size`, and + // a set of `addresses`, the following are guaranteed: + // - For all addresses `a` in `addresses`, `a` is in the + // range `base .. (base + size)` (note that this requires + // `a < base + size`, not `a <= base + size`) + // - `base` is not equal to [`null()`] (i.e., the address + // with the numerical value 0) + // - `base + size <= usize::MAX` + // - `size <= isize::MAX` + Some(unsafe { Self::new_unchecked(meta) }) + } else { + None + } + } + + /// # Safety + /// + /// The size of an instance of `&T` with the given metadata is not + /// larger than `isize::MAX`. + pub(crate) unsafe fn new_unchecked(meta: T::PointerMetadata) -> Self { + // SAFETY: The caller has promised that the size of an instance of + // `&T` with the given metadata is not larger than `isize::MAX`. + Self { meta, _p: PhantomData } + } + + pub(crate) fn get(&self) -> T::PointerMetadata + where + T::PointerMetadata: Copy, + { + self.meta + } + + #[inline] + pub(crate) fn padding_needed_for(&self) -> usize + where + T: KnownLayout, + { + let trailing_slice_layout = crate::trailing_slice_layout::(); + // SAFETY: By invariant on `self`, a `&T` with metadata `self.meta` + // describes an object of size `<= isize::MAX`. This computes the + // size of such a `&T` without any trailing padding, and so neither + // the multiplication nor the addition will overflow. + // + // FIXME(#67): Remove this allow. See NumExt for more details. + #[allow(unstable_name_collisions, clippy::incompatible_msrv)] + let unpadded_size = unsafe { + let trailing_size = self.meta.unchecked_mul(trailing_slice_layout.elem_size); + trailing_size.unchecked_add(trailing_slice_layout.offset) + }; + + util::padding_needed_for(unpadded_size, T::LAYOUT.align) + } + + #[inline(always)] + pub(crate) fn validate_cast_and_convert_metadata( + addr: usize, + bytes_len: MetadataOf<[u8]>, + cast_type: CastType, + meta: Option, + ) -> Result<(MetadataOf, MetadataOf<[u8]>), MetadataCastError> { + let layout = match meta { + None => T::LAYOUT, + // This can return `None` if the metadata describes an object + // which can't fit in an `isize`. + Some(meta) => { + let size = match T::size_for_metadata(meta) { + Some(size) => size, + None => return Err(MetadataCastError::Size), + }; + DstLayout { + align: T::LAYOUT.align, + size_info: crate::SizeInfo::Sized { size }, + statically_shallow_unpadded: false, + } + } + }; + // Lemma 0: By contract on `validate_cast_and_convert_metadata`, if + // the result is `Ok(..)`, then a `&T` with `elems` trailing slice + // elements is no larger in size than `bytes_len.get()`. + let (elems, split_at) = + layout.validate_cast_and_convert_metadata(addr, bytes_len.get(), cast_type)?; + let elems = T::PointerMetadata::from_elem_count(elems); + + // For a slice DST type, if `meta` is `Some(elems)`, then we + // synthesize `layout` to describe a sized type whose size is equal + // to the size of the instance that we are asked to cast. For sized + // types, `validate_cast_and_convert_metadata` returns `elems == 0`. + // Thus, in this case, we need to use the `elems` passed by the + // caller, not the one returned by + // `validate_cast_and_convert_metadata`. + // + // Lemma 1: A `&T` with `elems` trailing slice elements is no larger + // in size than `bytes_len.get()`. Proof: + // - If `meta` is `None`, then `elems` satisfies this condition by + // Lemma 0. + // - If `meta` is `Some(meta)`, then `layout` describes an object + // whose size is equal to the size of an `&T` with `meta` + // metadata. By Lemma 0, that size is not larger than + // `bytes_len.get()`. + // + // Lemma 2: A `&T` with `elems` trailing slice elements is no larger + // than `isize::MAX` bytes. Proof: By Lemma 1, a `&T` with metadata + // `elems` is not larger in size than `bytes_len.get()`. By + // invariant on `MetadataOf<[u8]>`, a `&[u8]` with metadata + // `bytes_len` is not larger than `isize::MAX`. Because + // `size_of::()` is `1`, a `&[u8]` with metadata `bytes_len` has + // size `bytes_len.get()` bytes. Therefore, a `&T` with metadata + // `elems` has size not larger than `isize::MAX`. + let elems = meta.unwrap_or(elems); + + // SAFETY: See Lemma 2. + let elems = unsafe { MetadataOf::new_unchecked(elems) }; + + // SAFETY: Let `size` be the size of a `&T` with metadata `elems`. + // By post-condition on `validate_cast_and_convert_metadata`, one of + // the following conditions holds: + // - `split_at == size`, in which case, by Lemma 2, `split_at <= + // isize::MAX`. Since `size_of::() == 1`, a `[u8]` with + // `split_at` elems has size not larger than `isize::MAX`. + // - `split_at == bytes_len - size`. Since `bytes_len: + // MetadataOf`, and since `size` is non-negative, `split_at` + // addresses no more bytes than `bytes_len` does. Since + // `bytes_len: MetadataOf`, `bytes_len` describes a `[u8]` + // which has no more than `isize::MAX` bytes, and thus so does + // `split_at`. + let split_at = unsafe { MetadataOf::<[u8]>::new_unchecked(split_at) }; + Ok((elems, split_at)) + } + } +} + +pub(crate) use len_of::MetadataOf; + +/// Since we support multiple versions of Rust, there are often features which +/// have been stabilized in the most recent stable release which do not yet +/// exist (stably) on our MSRV. This module provides polyfills for those +/// features so that we can write more "modern" code, and just remove the +/// polyfill once our MSRV supports the corresponding feature. Without this, +/// we'd have to write worse/more verbose code and leave FIXME comments sprinkled +/// throughout the codebase to update to the new pattern once it's stabilized. +/// +/// Each trait is imported as `_` at the crate root; each polyfill should "just +/// work" at usage sites. +pub(crate) mod polyfills { + use core::ptr::{self, NonNull}; + + // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our + // MSRV is 1.70, when that function was stabilized. + // + // The `#[allow(unused)]` is necessary because, on sufficiently recent + // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent + // method rather than to this trait, and so this trait is considered unused. + // + // FIXME(#67): Once our MSRV is 1.70, remove this. + #[allow(unused)] + pub(crate) trait NonNullExt { + fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>; + } + + impl NonNullExt for NonNull { + // NOTE on coverage: this will never be tested in nightly since it's a + // polyfill for a feature which has been stabilized on our nightly + // toolchain. + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + #[inline(always)] + fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> { + let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len); + // SAFETY: `ptr` is converted from `data`, which is non-null. + unsafe { NonNull::new_unchecked(ptr) } + } + } + + // A polyfill for `Self::unchecked_sub` that we can use until methods like + // `usize::unchecked_sub` is stabilized. + // + // The `#[allow(unused)]` is necessary because, on sufficiently recent + // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent + // method rather than to this trait, and so this trait is considered unused. + // + // FIXME(#67): Once our MSRV is high enough, remove this. + #[allow(unused)] + pub(crate) trait NumExt { + /// Add without checking for overflow. + /// + /// # Safety + /// + /// The caller promises that the addition will not overflow. + unsafe fn unchecked_add(self, rhs: Self) -> Self; + + /// Subtract without checking for underflow. + /// + /// # Safety + /// + /// The caller promises that the subtraction will not underflow. + unsafe fn unchecked_sub(self, rhs: Self) -> Self; + + /// Multiply without checking for overflow. + /// + /// # Safety + /// + /// The caller promises that the multiplication will not overflow. + unsafe fn unchecked_mul(self, rhs: Self) -> Self; + } + + // NOTE on coverage: these will never be tested in nightly since they're + // polyfills for a feature which has been stabilized on our nightly + // toolchain. + impl NumExt for usize { + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + #[inline(always)] + unsafe fn unchecked_add(self, rhs: usize) -> usize { + match self.checked_add(rhs) { + Some(x) => x, + None => { + // SAFETY: The caller promises that the addition will not + // underflow. + unsafe { core::hint::unreachable_unchecked() } + } + } + } + + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + #[inline(always)] + unsafe fn unchecked_sub(self, rhs: usize) -> usize { + match self.checked_sub(rhs) { + Some(x) => x, + None => { + // SAFETY: The caller promises that the subtraction will not + // underflow. + unsafe { core::hint::unreachable_unchecked() } + } + } + } + + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + #[inline(always)] + unsafe fn unchecked_mul(self, rhs: usize) -> usize { + match self.checked_mul(rhs) { + Some(x) => x, + None => { + // SAFETY: The caller promises that the multiplication will + // not overflow. + unsafe { core::hint::unreachable_unchecked() } + } + } + } + } +} + +#[cfg(test)] +pub(crate) mod testutil { + use crate::*; + + /// A `T` which is aligned to at least `align_of::()`. + #[derive(Default)] + pub(crate) struct Align { + pub(crate) t: T, + _a: [A; 0], + } + + impl Align { + pub(crate) fn set_default(&mut self) { + self.t = T::default(); + } + } + + impl Align { + pub(crate) const fn new(t: T) -> Align { + Align { t, _a: [] } + } + } + + /// A `T` which is guaranteed not to satisfy `align_of::()`. + /// + /// It must be the case that `align_of::() < align_of::()` in order + /// for this type to work properly. + #[repr(C)] + pub(crate) struct ForceUnalign { + // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is + // placed at the minimum offset that guarantees its alignment. If + // `align_of::() < align_of::()`, then that offset will be + // guaranteed *not* to satisfy `align_of::()`. + // + // Note that we need `T: Unaligned` in order to guarantee that there is + // no padding between `_u` and `t`. + _u: u8, + pub(crate) t: T, + _a: [A; 0], + } + + impl ForceUnalign { + pub(crate) fn new(t: T) -> ForceUnalign { + ForceUnalign { _u: 0, t, _a: [] } + } + } + // A `u64` with alignment 8. + // + // Though `u64` has alignment 8 on some platforms, it's not guaranteed. By + // contrast, `AU64` is guaranteed to have alignment 8 on all platforms. + #[derive( + KnownLayout, + Immutable, + FromBytes, + IntoBytes, + Eq, + PartialEq, + Ord, + PartialOrd, + Default, + Debug, + Copy, + Clone, + )] + #[repr(C, align(8))] + pub(crate) struct AU64(pub(crate) u64); + + impl AU64 { + // Converts this `AU64` to bytes using this platform's endianness. + pub(crate) fn to_bytes(self) -> [u8; 8] { + crate::transmute!(self) + } + } + + impl Display for AU64 { + #[cfg_attr( + all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), + coverage(off) + )] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_round_down_to_next_multiple_of_alignment() { + fn alt_impl(n: usize, align: NonZeroUsize) -> usize { + let mul = n / align.get(); + mul * align.get() + } + + for align in [1, 2, 4, 8, 16] { + for n in 0..256 { + let align = NonZeroUsize::new(align).unwrap(); + let want = alt_impl(n, align); + let got = round_down_to_next_multiple_of_alignment(n, align); + assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({}, {})", n, align); + } + } + } + + #[rustversion::since(1.57.0)] + #[test] + #[should_panic] + fn test_round_down_to_next_multiple_of_alignment_zerocopy_panic_in_const_and_vec_try_reserve() { + round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/wrappers.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/wrappers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/src/wrappers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/src/wrappers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,752 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{fmt, hash::Hash}; + +use super::*; + +/// A type with no alignment requirement. +/// +/// An `Unalign` wraps a `T`, removing any alignment requirement. `Unalign` +/// has the same size and bit validity as `T`, but not necessarily the same +/// alignment [or ABI]. This is useful if a type with an alignment requirement +/// needs to be read from a chunk of memory which provides no alignment +/// guarantees. +/// +/// Since `Unalign` has no alignment requirement, the inner `T` may not be +/// properly aligned in memory. There are five ways to access the inner `T`: +/// - by value, using [`get`] or [`into_inner`] +/// - by reference inside of a callback, using [`update`] +/// - fallibly by reference, using [`try_deref`] or [`try_deref_mut`]; these can +/// fail if the `Unalign` does not satisfy `T`'s alignment requirement at +/// runtime +/// - unsafely by reference, using [`deref_unchecked`] or +/// [`deref_mut_unchecked`]; it is the caller's responsibility to ensure that +/// the `Unalign` satisfies `T`'s alignment requirement +/// - (where `T: Unaligned`) infallibly by reference, using [`Deref::deref`] or +/// [`DerefMut::deref_mut`] +/// +/// [or ABI]: https://github.com/google/zerocopy/issues/164 +/// [`get`]: Unalign::get +/// [`into_inner`]: Unalign::into_inner +/// [`update`]: Unalign::update +/// [`try_deref`]: Unalign::try_deref +/// [`try_deref_mut`]: Unalign::try_deref_mut +/// [`deref_unchecked`]: Unalign::deref_unchecked +/// [`deref_mut_unchecked`]: Unalign::deref_mut_unchecked +/// +/// # Example +/// +/// In this example, we need `EthernetFrame` to have no alignment requirement - +/// and thus implement [`Unaligned`]. `EtherType` is `#[repr(u16)]` and so +/// cannot implement `Unaligned`. We use `Unalign` to relax `EtherType`'s +/// alignment requirement so that `EthernetFrame` has no alignment requirement +/// and can implement `Unaligned`. +/// +/// ```rust +/// use zerocopy::*; +/// # use zerocopy_derive::*; +/// # #[derive(FromBytes, KnownLayout, Immutable, Unaligned)] #[repr(C)] struct Mac([u8; 6]); +/// +/// # #[derive(PartialEq, Copy, Clone, Debug)] +/// #[derive(TryFromBytes, KnownLayout, Immutable)] +/// #[repr(u16)] +/// enum EtherType { +/// Ipv4 = 0x0800u16.to_be(), +/// Arp = 0x0806u16.to_be(), +/// Ipv6 = 0x86DDu16.to_be(), +/// # /* +/// ... +/// # */ +/// } +/// +/// #[derive(TryFromBytes, KnownLayout, Immutable, Unaligned)] +/// #[repr(C)] +/// struct EthernetFrame { +/// src: Mac, +/// dst: Mac, +/// ethertype: Unalign, +/// payload: [u8], +/// } +/// +/// let bytes = &[ +/// # 0, 1, 2, 3, 4, 5, +/// # 6, 7, 8, 9, 10, 11, +/// # /* +/// ... +/// # */ +/// 0x86, 0xDD, // EtherType +/// 0xDE, 0xAD, 0xBE, 0xEF // Payload +/// ][..]; +/// +/// // PANICS: Guaranteed not to panic because `bytes` is of the right +/// // length, has the right contents, and `EthernetFrame` has no +/// // alignment requirement. +/// let packet = EthernetFrame::try_ref_from_bytes(&bytes).unwrap(); +/// +/// assert_eq!(packet.ethertype.get(), EtherType::Ipv6); +/// assert_eq!(packet.payload, [0xDE, 0xAD, 0xBE, 0xEF]); +/// ``` +/// +/// # Safety +/// +/// `Unalign` is guaranteed to have the same size and bit validity as `T`, +/// and to have [`UnsafeCell`]s covering the same byte ranges as `T`. +/// `Unalign` is guaranteed to have alignment 1. +// NOTE: This type is sound to use with types that need to be dropped. The +// reason is that the compiler-generated drop code automatically moves all +// values to aligned memory slots before dropping them in-place. This is not +// well-documented, but it's hinted at in places like [1] and [2]. However, this +// also means that `T` must be `Sized`; unless something changes, we can never +// support unsized `T`. [3] +// +// [1] https://github.com/rust-lang/rust/issues/54148#issuecomment-420529646 +// [2] https://github.com/google/zerocopy/pull/126#discussion_r1018512323 +// [3] https://github.com/google/zerocopy/issues/209 +#[allow(missing_debug_implementations)] +#[derive(Default, Copy)] +#[cfg_attr(any(feature = "derive", test), derive(Immutable, FromBytes, IntoBytes, Unaligned))] +#[repr(C, packed)] +pub struct Unalign(T); + +// We do not use `derive(KnownLayout)` on `Unalign`, because the derive is not +// smart enough to realize that `Unalign` is always sized and thus emits a +// `KnownLayout` impl bounded on `T: KnownLayout.` This is overly restrictive. +impl_known_layout!(T => Unalign); + +// SAFETY: +// - `Unalign` promises to have alignment 1, and so we don't require that `T: +// Unaligned`. +// - `Unalign` has the same bit validity as `T`, and so it is `FromZeros`, +// `FromBytes`, or `IntoBytes` exactly when `T` is as well. +// - `Immutable`: `Unalign` has the same fields as `T`, so it contains +// `UnsafeCell`s exactly when `T` does. +// - `TryFromBytes`: `Unalign` has the same the same bit validity as `T`, so +// `T::is_bit_valid` is a sound implementation of `is_bit_valid`. +#[allow(unused_unsafe)] // Unused when `feature = "derive"`. +const _: () = unsafe { + impl_or_verify!(T => Unaligned for Unalign); + impl_or_verify!(T: Immutable => Immutable for Unalign); + impl_or_verify!( + T: TryFromBytes => TryFromBytes for Unalign; + |c| T::is_bit_valid(c.transmute()) + ); + impl_or_verify!(T: FromZeros => FromZeros for Unalign); + impl_or_verify!(T: FromBytes => FromBytes for Unalign); + impl_or_verify!(T: IntoBytes => IntoBytes for Unalign); +}; + +// Note that `Unalign: Clone` only if `T: Copy`. Since the inner `T` may not be +// aligned, there's no way to safely call `T::clone`, and so a `T: Clone` bound +// is not sufficient to implement `Clone` for `Unalign`. +impl Clone for Unalign { + #[inline(always)] + fn clone(&self) -> Unalign { + *self + } +} + +impl Unalign { + /// Constructs a new `Unalign`. + #[inline(always)] + pub const fn new(val: T) -> Unalign { + Unalign(val) + } + + /// Consumes `self`, returning the inner `T`. + #[inline(always)] + pub const fn into_inner(self) -> T { + // SAFETY: Since `Unalign` is `#[repr(C, packed)]`, it has the same size + // and bit validity as `T`. + // + // We do this instead of just destructuring in order to prevent + // `Unalign`'s `Drop::drop` from being run, since dropping is not + // supported in `const fn`s. + // + // FIXME(https://github.com/rust-lang/rust/issues/73255): Destructure + // instead of using unsafe. + unsafe { crate::util::transmute_unchecked(self) } + } + + /// Attempts to return a reference to the wrapped `T`, failing if `self` is + /// not properly aligned. + /// + /// If `self` does not satisfy `align_of::()`, then `try_deref` returns + /// `Err`. + /// + /// If `T: Unaligned`, then `Unalign` implements [`Deref`], and callers + /// may prefer [`Deref::deref`], which is infallible. + #[inline(always)] + pub fn try_deref(&self) -> Result<&T, AlignmentError<&Self, T>> { + let inner = Ptr::from_ref(self).transmute(); + match inner.try_into_aligned() { + Ok(aligned) => Ok(aligned.as_ref()), + Err(err) => Err(err.map_src(|src| src.into_unalign().as_ref())), + } + } + + /// Attempts to return a mutable reference to the wrapped `T`, failing if + /// `self` is not properly aligned. + /// + /// If `self` does not satisfy `align_of::()`, then `try_deref` returns + /// `Err`. + /// + /// If `T: Unaligned`, then `Unalign` implements [`DerefMut`], and + /// callers may prefer [`DerefMut::deref_mut`], which is infallible. + #[inline(always)] + pub fn try_deref_mut(&mut self) -> Result<&mut T, AlignmentError<&mut Self, T>> { + let inner = Ptr::from_mut(self).transmute::<_, _, (_, (_, _))>(); + match inner.try_into_aligned() { + Ok(aligned) => Ok(aligned.as_mut()), + Err(err) => Err(err.map_src(|src| src.into_unalign().as_mut())), + } + } + + /// Returns a reference to the wrapped `T` without checking alignment. + /// + /// If `T: Unaligned`, then `Unalign` implements[ `Deref`], and callers + /// may prefer [`Deref::deref`], which is safe. + /// + /// # Safety + /// + /// The caller must guarantee that `self` satisfies `align_of::()`. + #[inline(always)] + pub const unsafe fn deref_unchecked(&self) -> &T { + // SAFETY: `Unalign` is `repr(transparent)`, so there is a valid `T` + // at the same memory location as `self`. It has no alignment guarantee, + // but the caller has promised that `self` is properly aligned, so we + // know that it is sound to create a reference to `T` at this memory + // location. + // + // We use `mem::transmute` instead of `&*self.get_ptr()` because + // dereferencing pointers is not stable in `const` on our current MSRV + // (1.56 as of this writing). + unsafe { mem::transmute(self) } + } + + /// Returns a mutable reference to the wrapped `T` without checking + /// alignment. + /// + /// If `T: Unaligned`, then `Unalign` implements[ `DerefMut`], and + /// callers may prefer [`DerefMut::deref_mut`], which is safe. + /// + /// # Safety + /// + /// The caller must guarantee that `self` satisfies `align_of::()`. + #[inline(always)] + pub unsafe fn deref_mut_unchecked(&mut self) -> &mut T { + // SAFETY: `self.get_mut_ptr()` returns a raw pointer to a valid `T` at + // the same memory location as `self`. It has no alignment guarantee, + // but the caller has promised that `self` is properly aligned, so we + // know that the pointer itself is aligned, and thus that it is sound to + // create a reference to a `T` at this memory location. + unsafe { &mut *self.get_mut_ptr() } + } + + /// Gets an unaligned raw pointer to the inner `T`. + /// + /// # Safety + /// + /// The returned raw pointer is not necessarily aligned to + /// `align_of::()`. Most functions which operate on raw pointers require + /// those pointers to be aligned, so calling those functions with the result + /// of `get_ptr` will result in undefined behavior if alignment is not + /// guaranteed using some out-of-band mechanism. In general, the only + /// functions which are safe to call with this pointer are those which are + /// explicitly documented as being sound to use with an unaligned pointer, + /// such as [`read_unaligned`]. + /// + /// Even if the caller is permitted to mutate `self` (e.g. they have + /// ownership or a mutable borrow), it is not guaranteed to be sound to + /// write through the returned pointer. If writing is required, prefer + /// [`get_mut_ptr`] instead. + /// + /// [`read_unaligned`]: core::ptr::read_unaligned + /// [`get_mut_ptr`]: Unalign::get_mut_ptr + #[inline(always)] + pub const fn get_ptr(&self) -> *const T { + ptr::addr_of!(self.0) + } + + /// Gets an unaligned mutable raw pointer to the inner `T`. + /// + /// # Safety + /// + /// The returned raw pointer is not necessarily aligned to + /// `align_of::()`. Most functions which operate on raw pointers require + /// those pointers to be aligned, so calling those functions with the result + /// of `get_ptr` will result in undefined behavior if alignment is not + /// guaranteed using some out-of-band mechanism. In general, the only + /// functions which are safe to call with this pointer are those which are + /// explicitly documented as being sound to use with an unaligned pointer, + /// such as [`read_unaligned`]. + /// + /// [`read_unaligned`]: core::ptr::read_unaligned + // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. + #[inline(always)] + pub fn get_mut_ptr(&mut self) -> *mut T { + ptr::addr_of_mut!(self.0) + } + + /// Sets the inner `T`, dropping the previous value. + // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. + #[inline(always)] + pub fn set(&mut self, t: T) { + *self = Unalign::new(t); + } + + /// Updates the inner `T` by calling a function on it. + /// + /// If [`T: Unaligned`], then `Unalign` implements [`DerefMut`], and that + /// impl should be preferred over this method when performing updates, as it + /// will usually be faster and more ergonomic. + /// + /// For large types, this method may be expensive, as it requires copying + /// `2 * size_of::()` bytes. \[1\] + /// + /// \[1\] Since the inner `T` may not be aligned, it would not be sound to + /// invoke `f` on it directly. Instead, `update` moves it into a + /// properly-aligned location in the local stack frame, calls `f` on it, and + /// then moves it back to its original location in `self`. + /// + /// [`T: Unaligned`]: Unaligned + #[inline] + pub fn update O>(&mut self, f: F) -> O { + if mem::align_of::() == 1 { + // While we advise callers to use `DerefMut` when `T: Unaligned`, + // not all callers will be able to guarantee `T: Unaligned` in all + // cases. In particular, callers who are themselves providing an API + // which is generic over `T` may sometimes be called by *their* + // callers with `T` such that `align_of::() == 1`, but cannot + // guarantee this in the general case. Thus, this optimization may + // sometimes be helpful. + + // SAFETY: Since `T`'s alignment is 1, `self` satisfies its + // alignment by definition. + let t = unsafe { self.deref_mut_unchecked() }; + return f(t); + } + + // On drop, this moves `copy` out of itself and uses `ptr::write` to + // overwrite `slf`. + struct WriteBackOnDrop { + copy: ManuallyDrop, + slf: *mut Unalign, + } + + impl Drop for WriteBackOnDrop { + fn drop(&mut self) { + // SAFETY: We never use `copy` again as required by + // `ManuallyDrop::take`. + let copy = unsafe { ManuallyDrop::take(&mut self.copy) }; + // SAFETY: `slf` is the raw pointer value of `self`. We know it + // is valid for writes and properly aligned because `self` is a + // mutable reference, which guarantees both of these properties. + unsafe { ptr::write(self.slf, Unalign::new(copy)) }; + } + } + + // SAFETY: We know that `self` is valid for reads, properly aligned, and + // points to an initialized `Unalign` because it is a mutable + // reference, which guarantees all of these properties. + // + // Since `T: !Copy`, it would be unsound in the general case to allow + // both the original `Unalign` and the copy to be used by safe code. + // We guarantee that the copy is used to overwrite the original in the + // `Drop::drop` impl of `WriteBackOnDrop`. So long as this `drop` is + // called before any other safe code executes, soundness is upheld. + // While this method can terminate in two ways (by returning normally or + // by unwinding due to a panic in `f`), in both cases, `write_back` is + // dropped - and its `drop` called - before any other safe code can + // execute. + let copy = unsafe { ptr::read(self) }.into_inner(); + let mut write_back = WriteBackOnDrop { copy: ManuallyDrop::new(copy), slf: self }; + + let ret = f(&mut write_back.copy); + + drop(write_back); + ret + } +} + +impl Unalign { + /// Gets a copy of the inner `T`. + // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. + #[inline(always)] + pub fn get(&self) -> T { + let Unalign(val) = *self; + val + } +} + +impl Deref for Unalign { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &T { + Ptr::from_ref(self).transmute().bikeshed_recall_aligned().as_ref() + } +} + +impl DerefMut for Unalign { + #[inline(always)] + fn deref_mut(&mut self) -> &mut T { + Ptr::from_mut(self).transmute::<_, _, (_, (_, _))>().bikeshed_recall_aligned().as_mut() + } +} + +impl PartialOrd> for Unalign { + #[inline(always)] + fn partial_cmp(&self, other: &Unalign) -> Option { + PartialOrd::partial_cmp(self.deref(), other.deref()) + } +} + +impl Ord for Unalign { + #[inline(always)] + fn cmp(&self, other: &Unalign) -> Ordering { + Ord::cmp(self.deref(), other.deref()) + } +} + +impl PartialEq> for Unalign { + #[inline(always)] + fn eq(&self, other: &Unalign) -> bool { + PartialEq::eq(self.deref(), other.deref()) + } +} + +impl Eq for Unalign {} + +impl Hash for Unalign { + #[inline(always)] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.deref().hash(state); + } +} + +impl Debug for Unalign { + #[inline(always)] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(self.deref(), f) + } +} + +impl Display for Unalign { + #[inline(always)] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self.deref(), f) + } +} + +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// `MaybeUninit` is identical to the [standard library +/// `MaybeUninit`][core-maybe-uninit] type except that it supports unsized +/// types. +/// +/// # Layout +/// +/// The same layout guarantees and caveats apply to `MaybeUninit` as apply to +/// the [standard library `MaybeUninit`][core-maybe-uninit] with one exception: +/// for `T: !Sized`, there is no single value for `T`'s size. Instead, for such +/// types, the following are guaranteed: +/// - Every [valid size][valid-size] for `T` is a valid size for +/// `MaybeUninit` and vice versa +/// - Given `t: *const T` and `m: *const MaybeUninit` with identical fat +/// pointer metadata, `t` and `m` address the same number of bytes (and +/// likewise for `*mut`) +/// +/// [core-maybe-uninit]: core::mem::MaybeUninit +/// [valid-size]: crate::KnownLayout#what-is-a-valid-size +#[repr(transparent)] +#[doc(hidden)] +pub struct MaybeUninit( + // SAFETY: `MaybeUninit` has the same size as `T`, because (by invariant + // on `T::MaybeUninit`) `T::MaybeUninit` has `T::LAYOUT` identical to `T`, + // and because (invariant on `T::LAYOUT`) we can trust that `LAYOUT` + // accurately reflects the layout of `T`. By invariant on `T::MaybeUninit`, + // it admits uninitialized bytes in all positions. Because `MaybeUninit` is + // marked `repr(transparent)`, these properties additionally hold true for + // `Self`. + T::MaybeUninit, +); + +#[doc(hidden)] +impl MaybeUninit { + /// Constructs a `MaybeUninit` initialized with the given value. + #[inline(always)] + pub fn new(val: T) -> Self + where + T: Sized, + Self: Sized, + { + // SAFETY: It is valid to transmute `val` to `MaybeUninit` because it + // is both valid to transmute `val` to `T::MaybeUninit`, and it is valid + // to transmute from `T::MaybeUninit` to `MaybeUninit`. + // + // First, it is valid to transmute `val` to `T::MaybeUninit` because, by + // invariant on `T::MaybeUninit`: + // - For `T: Sized`, `T` and `T::MaybeUninit` have the same size. + // - All byte sequences of the correct size are valid values of + // `T::MaybeUninit`. + // + // Second, it is additionally valid to transmute from `T::MaybeUninit` + // to `MaybeUninit`, because `MaybeUninit` is a + // `repr(transparent)` wrapper around `T::MaybeUninit`. + // + // These two transmutes are collapsed into one so we don't need to add a + // `T::MaybeUninit: Sized` bound to this function's `where` clause. + unsafe { crate::util::transmute_unchecked(val) } + } + + /// Constructs an uninitialized `MaybeUninit`. + #[must_use] + #[inline(always)] + pub fn uninit() -> Self + where + T: Sized, + Self: Sized, + { + let uninit = CoreMaybeUninit::::uninit(); + // SAFETY: It is valid to transmute from `CoreMaybeUninit` to + // `MaybeUninit` since they both admit uninitialized bytes in all + // positions, and they have the same size (i.e., that of `T`). + // + // `MaybeUninit` has the same size as `T`, because (by invariant on + // `T::MaybeUninit`) `T::MaybeUninit` has `T::LAYOUT` identical to `T`, + // and because (invariant on `T::LAYOUT`) we can trust that `LAYOUT` + // accurately reflects the layout of `T`. + // + // `CoreMaybeUninit` has the same size as `T` [1] and admits + // uninitialized bytes in all positions. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, alignment, + // and ABI as `T` + unsafe { crate::util::transmute_unchecked(uninit) } + } + + /// Creates a `Box>`. + /// + /// This function is useful for allocating large, uninit values on the heap + /// without ever creating a temporary instance of `Self` on the stack. + /// + /// # Errors + /// + /// Returns an error on allocation failure. Allocation failure is guaranteed + /// never to cause a panic or an abort. + #[cfg(feature = "alloc")] + #[inline] + pub fn new_boxed_uninit(meta: T::PointerMetadata) -> Result, AllocError> { + // SAFETY: `alloc::alloc::alloc_zeroed` is a valid argument of + // `new_box`. The referent of the pointer returned by `alloc` (and, + // consequently, the `Box` derived from it) is a valid instance of + // `Self`, because `Self` is `MaybeUninit` and thus admits arbitrary + // (un)initialized bytes. + unsafe { crate::util::new_box(meta, alloc::alloc::alloc) } + } + + /// Extracts the value from the `MaybeUninit` container. + /// + /// # Safety + /// + /// The caller must ensure that `self` is in an bit-valid state. Depending + /// on subsequent use, it may also need to be in a library-valid state. + #[inline(always)] + pub unsafe fn assume_init(self) -> T + where + T: Sized, + Self: Sized, + { + // SAFETY: The caller guarantees that `self` is in an bit-valid state. + unsafe { crate::util::transmute_unchecked(self) } + } +} + +impl fmt::Debug for MaybeUninit { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(core::any::type_name::()) + } +} + +#[cfg(test)] +mod tests { + use core::panic::AssertUnwindSafe; + + use super::*; + use crate::util::testutil::*; + + #[test] + fn test_unalign() { + // Test methods that don't depend on alignment. + let mut u = Unalign::new(AU64(123)); + assert_eq!(u.get(), AU64(123)); + assert_eq!(u.into_inner(), AU64(123)); + assert_eq!(u.get_ptr(), <*const _>::cast::(&u)); + assert_eq!(u.get_mut_ptr(), <*mut _>::cast::(&mut u)); + u.set(AU64(321)); + assert_eq!(u.get(), AU64(321)); + + // Test methods that depend on alignment (when alignment is satisfied). + let mut u: Align<_, AU64> = Align::new(Unalign::new(AU64(123))); + assert_eq!(u.t.try_deref().unwrap(), &AU64(123)); + assert_eq!(u.t.try_deref_mut().unwrap(), &mut AU64(123)); + // SAFETY: The `Align<_, AU64>` guarantees proper alignment. + assert_eq!(unsafe { u.t.deref_unchecked() }, &AU64(123)); + // SAFETY: The `Align<_, AU64>` guarantees proper alignment. + assert_eq!(unsafe { u.t.deref_mut_unchecked() }, &mut AU64(123)); + *u.t.try_deref_mut().unwrap() = AU64(321); + assert_eq!(u.t.get(), AU64(321)); + + // Test methods that depend on alignment (when alignment is not + // satisfied). + let mut u: ForceUnalign<_, AU64> = ForceUnalign::new(Unalign::new(AU64(123))); + assert!(matches!(u.t.try_deref(), Err(AlignmentError { .. }))); + assert!(matches!(u.t.try_deref_mut(), Err(AlignmentError { .. }))); + + // Test methods that depend on `T: Unaligned`. + let mut u = Unalign::new(123u8); + assert_eq!(u.try_deref(), Ok(&123)); + assert_eq!(u.try_deref_mut(), Ok(&mut 123)); + assert_eq!(u.deref(), &123); + assert_eq!(u.deref_mut(), &mut 123); + *u = 21; + assert_eq!(u.get(), 21); + + // Test that some `Unalign` functions and methods are `const`. + const _UNALIGN: Unalign = Unalign::new(0); + const _UNALIGN_PTR: *const u64 = _UNALIGN.get_ptr(); + const _U64: u64 = _UNALIGN.into_inner(); + // Make sure all code is considered "used". + // + // FIXME(https://github.com/rust-lang/rust/issues/104084): Remove this + // attribute. + #[allow(dead_code)] + const _: () = { + let x: Align<_, AU64> = Align::new(Unalign::new(AU64(123))); + // Make sure that `deref_unchecked` is `const`. + // + // SAFETY: The `Align<_, AU64>` guarantees proper alignment. + let au64 = unsafe { x.t.deref_unchecked() }; + match au64 { + AU64(123) => {} + _ => const_unreachable!(), + } + }; + } + + #[test] + fn test_unalign_update() { + let mut u = Unalign::new(AU64(123)); + u.update(|a| a.0 += 1); + assert_eq!(u.get(), AU64(124)); + + // Test that, even if the callback panics, the original is still + // correctly overwritten. Use a `Box` so that Miri is more likely to + // catch any unsoundness (which would likely result in two `Box`es for + // the same heap object, which is the sort of thing that Miri would + // probably catch). + let mut u = Unalign::new(Box::new(AU64(123))); + let res = std::panic::catch_unwind(AssertUnwindSafe(|| { + u.update(|a| { + a.0 += 1; + panic!(); + }) + })); + assert!(res.is_err()); + assert_eq!(u.into_inner(), Box::new(AU64(124))); + + // Test the align_of::() == 1 optimization. + let mut u = Unalign::new([0u8, 1]); + u.update(|a| a[0] += 1); + assert_eq!(u.get(), [1u8, 1]); + } + + #[test] + fn test_unalign_copy_clone() { + // Test that `Copy` and `Clone` do not cause soundness issues. This test + // is mainly meant to exercise UB that would be caught by Miri. + + // `u.t` is definitely not validly-aligned for `AU64`'s alignment of 8. + let u = ForceUnalign::<_, AU64>::new(Unalign::new(AU64(123))); + #[allow(clippy::clone_on_copy)] + let v = u.t.clone(); + let w = u.t; + assert_eq!(u.t.get(), v.get()); + assert_eq!(u.t.get(), w.get()); + assert_eq!(v.get(), w.get()); + } + + #[test] + fn test_unalign_trait_impls() { + let zero = Unalign::new(0u8); + let one = Unalign::new(1u8); + + assert!(zero < one); + assert_eq!(PartialOrd::partial_cmp(&zero, &one), Some(Ordering::Less)); + assert_eq!(Ord::cmp(&zero, &one), Ordering::Less); + + assert_ne!(zero, one); + assert_eq!(zero, zero); + assert!(!PartialEq::eq(&zero, &one)); + assert!(PartialEq::eq(&zero, &zero)); + + fn hash(t: &T) -> u64 { + let mut h = std::collections::hash_map::DefaultHasher::new(); + t.hash(&mut h); + h.finish() + } + + assert_eq!(hash(&zero), hash(&0u8)); + assert_eq!(hash(&one), hash(&1u8)); + + assert_eq!(format!("{:?}", zero), format!("{:?}", 0u8)); + assert_eq!(format!("{:?}", one), format!("{:?}", 1u8)); + assert_eq!(format!("{}", zero), format!("{}", 0u8)); + assert_eq!(format!("{}", one), format!("{}", 1u8)); + } + + #[test] + #[allow(clippy::as_conversions)] + fn test_maybe_uninit() { + // int + { + let input = 42; + let uninit = MaybeUninit::new(input); + // SAFETY: `uninit` is in an initialized state + let output = unsafe { uninit.assume_init() }; + assert_eq!(input, output); + } + + // thin ref + { + let input = 42; + let uninit = MaybeUninit::new(&input); + // SAFETY: `uninit` is in an initialized state + let output = unsafe { uninit.assume_init() }; + assert_eq!(&input as *const _, output as *const _); + assert_eq!(input, *output); + } + + // wide ref + { + let input = [1, 2, 3, 4]; + let uninit = MaybeUninit::new(&input[..]); + // SAFETY: `uninit` is in an initialized state + let output = unsafe { uninit.assume_init() }; + assert_eq!(&input[..] as *const _, output as *const _); + assert_eq!(input, *output); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/testdata/include_value/data clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/testdata/include_value/data --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/testdata/include_value/data 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/testdata/include_value/data 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +abcd \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/trybuild.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/trybuild.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/trybuild.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/trybuild.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,55 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Many of our UI tests require the "derive" feature to function properly. In +// particular: +// - Some tests directly include `zerocopy-derive/tests/include.rs`, which +// derives traits on the `AU16` type. +// - The file `invalid-impls.rs` directly includes `src/util/macros.rs` in order +// to test the `impl_or_verify!` macro which is defined in that file. +// Specifically, it tests the verification portion of that macro, which is +// enabled when `cfg(any(feature = "derive", test))`. While `--cfg test` is of +// course passed to the code in the file you're reading right now, `trybuild` +// does not pass `--cfg test` when it invokes Cargo. As a result, this +// `trybuild` test only tests the correct behavior when the "derive" feature +// is enabled. +#![cfg(feature = "derive")] + +use testutil::{set_rustflags_w_warnings, ToolchainVersion}; + +#[test] +#[cfg_attr(miri, ignore)] +fn ui() { + let version = ToolchainVersion::extract_from_pwd().unwrap(); + // See the doc comment on this method for an explanation of what this does + // and why we store source files in different directories. + let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning(); + + // Set `-Wwarnings` in the `RUSTFLAGS` environment variable to ensure that + // `.stderr` files reflect what the typical user would encounter. + set_rustflags_w_warnings(); + + let t = trybuild::TestCases::new(); + t.compile_fail(format!("tests/{}/*.rs", source_files_dirname)); +} + +#[test] +#[cfg_attr(miri, ignore)] +fn ui_invalid_impls() { + let version = ToolchainVersion::extract_from_pwd().unwrap(); + // See the doc comment on this method for an explanation of what this does + // and why we store source files in different directories. + let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning(); + + // Set `-Wwarnings` in the `RUSTFLAGS` environment variable to ensure that + // `.stderr` files reflect what the typical user would encounter. + set_rustflags_w_warnings(); + + let t = trybuild::TestCases::new(); + t.compile_fail(format!("tests/{}/invalid-impls/*.rs", source_files_dirname)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_bytes::(); +} + +fn takes_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs:18:24 + | +18 | takes_from_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_from_bytes` + --> tests/ui-msrv/diagnostic-not-implemented-from-bytes.rs:21:24 + | +21 | fn takes_from_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromZeros; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_zeros::(); +} + +fn takes_from_zeros() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-from-zeros.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs:18:24 + | +18 | takes_from_zeros::(); + | ^^^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_from_zeros` + --> tests/ui-msrv/diagnostic-not-implemented-from-zeros.rs:21:24 + | +21 | fn takes_from_zeros() {} + | ^^^^^^^^^ required by this bound in `takes_from_zeros` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Immutable; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_immutable::(); +} + +fn takes_immutable() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-immutable.rs:18:23 + | +18 | takes_immutable::(); + | ^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_immutable` + --> tests/ui-msrv/diagnostic-not-implemented-immutable.rs:21:23 + | +21 | fn takes_immutable() {} + | ^^^^^^^^^ required by this bound in `takes_immutable` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::IntoBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_into_bytes::(); +} + +fn takes_into_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-into-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs:18:24 + | +18 | takes_into_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_into_bytes` + --> tests/ui-msrv/diagnostic-not-implemented-into-bytes.rs:21:24 + | +21 | fn takes_into_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_into_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::{Immutable, IntoBytes}; + +fn main() { + // This is adapted from #1296, which includes the following text: + // + // The compiler errors when a type is missing Immutable are somewhat + // misleading, although I'm not sure there's much zerocopy can do about + // this. An example where the compiler recommends adding a reference + // rather than implementing Immutable (some were even more confusing than + // this): + // + // error[E0277]: the trait bound `virtio::wl::CtrlVfdNewDmabuf: zerocopy::Immutable` is not satisfied + // --> devices/src/virtio/wl.rs:317:20 + // | + // 317 | .write_obj(ctrl_vfd_new_dmabuf) + // | --------- ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `virtio::wl::CtrlVfdNewDmabuf` + // | | + // | required by a bound introduced by this call + // | + // note: required by a bound in `virtio::descriptor_utils::Writer::write_obj` + // --> devices/src/virtio/descriptor_utils.rs:536:25 + // | + // 536 | pub fn write_obj(&mut self, val: T) -> io::Result<()> { + // | ^^^^^^^^^ required by this bound in `Writer::write_obj` + // help: consider borrowing here + // | + // 317 | .write_obj(&ctrl_vfd_new_dmabuf) + // | + + // 317 | .write_obj(&mut ctrl_vfd_new_dmabuf) + // | ++++ + // + // Taking the compiler's suggestion results in a different error with a + // recommendation to remove the reference (back to the original code). + // + // As of this writing, the described problem is still happening thanks to + // https://github.com/rust-lang/rust/issues/130563. We include this test so + // that we can capture the current behavior, but we will update it once that + // Rust issue is fixed. + Foo.write_obj(NotZerocopy(())); +} + +struct Foo; + +impl Foo { + fn write_obj(&mut self, _val: T) {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-issue-1296.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | ^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | ^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::KnownLayout; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_known_layout::(); +} + +fn takes_known_layout() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-known-layout.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::KnownLayout` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-known-layout.rs:18:26 + | +18 | takes_known_layout::(); + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_known_layout` + --> tests/ui-msrv/diagnostic-not-implemented-known-layout.rs:21:26 + | +21 | fn takes_known_layout() {} + | ^^^^^^^^^^^ required by this bound in `takes_known_layout` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::TryFromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_try_from_bytes::(); +} + +fn takes_try_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs:18:28 + | +18 | takes_try_from_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_try_from_bytes` + --> tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs:21:28 + | +21 | fn takes_try_from_bytes() {} + | ^^^^^^^^^^^^ required by this bound in `takes_try_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Unaligned; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_unaligned::(); +} + +fn takes_unaligned() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/diagnostic-not-implemented-unaligned.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/diagnostic-not-implemented-unaligned.rs:18:23 + | +18 | takes_unaligned::(); + | ^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + | +note: required by a bound in `takes_unaligned` + --> tests/ui-msrv/diagnostic-not-implemented-unaligned.rs:21:23 + | +21 | fn takes_unaligned() {} + | ^^^^^^^^^ required by this bound in `takes_unaligned` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +#[macro_use] +extern crate zerocopy; + +use util::NotZerocopy; + +fn main() {} + +// Should fail because `NotZerocopy: !FromBytes`. +const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_not_from_bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-msrv/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `NOT_FROM_BYTES::transmute` + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/include_value_wrong_size.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/include_value_wrong_size.rs:15:25 + | +15 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Since some macros from `macros.rs` are unused. +#![allow(unused)] + +extern crate zerocopy; +extern crate zerocopy_derive; + +include!("../../../src/util/macros.rs"); + +use zerocopy::*; +use zerocopy_derive::*; + +fn main() {} + +#[derive(FromBytes, IntoBytes, Unaligned)] +#[repr(transparent)] +struct Foo(T); + +const _: () = unsafe { + impl_or_verify!(T => TryFromBytes for Foo); + impl_or_verify!(T => FromZeros for Foo); + impl_or_verify!(T => FromBytes for Foo); + impl_or_verify!(T => IntoBytes for Foo); + impl_or_verify!(T => Unaligned for Foo); +}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/invalid-impls/invalid-impls.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,159 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:5 + | +27 | impl_or_verify!(T => TryFromBytes for Foo); + | ---------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::TryFromBytes` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:5 + | +27 | impl_or_verify!(T => TryFromBytes for Foo); + | ---------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +27 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromZeros` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::FromZeros` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:5 + | +28 | impl_or_verify!(T => FromZeros for Foo); + | ------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::FromZeros` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:5 + | +28 | impl_or_verify!(T => FromZeros for Foo); + | ------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +28 | impl_or_verify!(T: zerocopy::FromZeros => FromZeros for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:5 + | +29 | impl_or_verify!(T => FromBytes for Foo); + | ------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::FromBytes` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:5 + | +29 | impl_or_verify!(T => FromBytes for Foo); + | ------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +29 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:30:5 + | +30 | impl_or_verify!(T => IntoBytes for Foo); + | ------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::IntoBytes` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:21 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:30:5 + | +30 | impl_or_verify!(T => IntoBytes for Foo); + | ------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +30 | impl_or_verify!(T: zerocopy::IntoBytes => IntoBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:31:5 + | +31 | impl_or_verify!(T => Unaligned for Foo); + | ------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::Unaligned` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:32 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:31:5 + | +31 | impl_or_verify!(T => Unaligned for Foo); + | ------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +31 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/max-align.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-msrv/max-align.rs:96:11 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +use zerocopy::pointer::{ + invariant::{Aligned, Exclusive, Shared, Valid}, + Ptr, +}; + +fn _when_exclusive<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Exclusive, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Exclusive, Aligned, Valid)>, +) { + _small = big; +} + +fn _when_shared<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Shared, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Shared, Aligned, Valid)>, +) { + _small = big; +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/ptr-is-invariant-over-v.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +error[E0623]: lifetime mismatch + --> tests/ui-msrv/ptr-is-invariant-over-v.rs:10:14 + | +7 | big: Ptr<'small, &'big u32, (Exclusive, Aligned, Valid)>, + | --------------------------------------------------- these two types are declared with different lifetimes... +... +10 | _small = big; + | ^^^ ...but data from `big` flows into `big` here + +error[E0623]: lifetime mismatch + --> tests/ui-msrv/ptr-is-invariant-over-v.rs:17:14 + | +14 | big: Ptr<'small, &'big u32, (Shared, Aligned, Valid)>, + | ------------------------------------------------ these two types are declared with different lifetimes... +... +17 | _small = big; + | ^^^ ...but data from `big` flows into `big` here diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` + --> tests/ui-msrv/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `DST_NOT_FROM_BYTES::transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-msrv/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(const_item_mutation)]` on by default + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-msrv/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-msrv/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants + --> tests/ui-msrv/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-msrv/transmute-mut-const.rs:20:57 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | --------------------^^^^^^^^^^^^- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `IntoBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-dst-not-intobytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-msrv/transmute-mut-illegal-lifetime.rs:14:56 + | +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | | help: consider mutably borrowing here: `&mut 0usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | | help: consider mutably borrowing here: `&mut 0usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-intobytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type to +// a sized destination type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-msrv/transmute-mut-src-unsized.rs:17:35 + | +17 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | + = note: required because of the requirements on the impl of `TransmuteMutDst<'_>` for `Wrap<&mut [u8], &mut [u8; 1]>` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ptr-to-usize.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `*const usize` + | +note: required by a bound in `POINTER_VALUE::transmute` + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `POINTER_VALUE::transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Dst: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `Dst` + | +note: required by `AssertDstIsFromBytes` + --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::FromBytes)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `Immutable` +const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Dst: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `Dst` + | +note: required by `AssertDstIsImmutable` + --> tests/ui-msrv/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-msrv/transmute-ref-illegal-lifetime.rs:14:52 + | +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected reference, found `usize` + | | help: consider borrowing here: `&0usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected reference, found `usize` + | | help: consider borrowing here: `&0usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `Src` + | +note: required by `AssertSrcIsIntoBytes` + --> tests/ui-msrv/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsIntoBytes` + --> tests/ui-msrv/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::IntoBytes)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `Immutable` +const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `zerocopy::Immutable` + | +note: required by `AssertSrcIsImmutable` + --> tests/ui-msrv/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsImmutable` + --> tests/ui-msrv/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | + = note: required because of the requirements on the impl of `TransmuteRefDst<'_>` for `Wrap<&[u8], &[u8; 1]>` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-decrease.rs:20:27 + | +20 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-increase.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` + --> tests/ui-msrv/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `SRC_NOT_AS_BYTES::transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:58 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | Dst: TryFromBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:33 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:58 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute-size-decrease.rs:19:41 + | +19 | let _decrease_size: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// `try_transmute!` does not support transmuting from a smaller type to a larger +// one. +fn main() { + let _increase_size: Result = try_transmute!(0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute-size-increase.rs:19:43 + | +19 | let _increase_size: Result = try_transmute!(0u8); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + // `try_transmute` requires that the source type implements `IntoBytes` + let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute-src-not-intobytes.rs:18:47 + | +18 | let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | Src: IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let src = &mut [0u8; 2]; + let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_mut-alignment-increase.rs:20:48 + | +20 | let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_mut; + +fn main() { + // `try_transmute_mut` requires that the destination type implements + // `IntoBytes` + let src = &mut AU16(0); + let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let src = &mut AU16(0); + let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_mut-size-decrease.rs:20:46 + | +20 | let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let src = &mut 0u8; + let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +warning: unused import: `util::AU16` + --> tests/ui-msrv/try_transmute_mut-size-increase.rs:13:5 + | +13 | use util::AU16; + | ^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_mut-size-increase.rs:20:51 + | +20 | let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::IntoBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `FromBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `IntoBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_ref-alignment-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::try_transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `try_transmute_ref!` requires that its destination type be an immutable + // reference. + let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | help: try using a variant of the expected enum: `Err($crate::util::macro_util::try_transmute_ref::<_, _>(e))` + | + = note: expected enum `Result<&mut u8, _>` + found enum `Result<&_, ValidityError<&u8, _>>` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_ref-size-decrease.rs:19:42 + | +19 | let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/try_transmute_ref-size-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | +19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | +19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `zerocopy::Immutable` + | +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_bytes::(); +} + +fn takes_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs:18:24 + | +18 | takes_from_bytes::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `takes_from_bytes` + --> tests/ui-nightly/diagnostic-not-implemented-from-bytes.rs:21:24 + | +21 | fn takes_from_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromZeros; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_zeros::(); +} + +fn takes_from_zeros() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-from-zeros.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs:18:24 + | +18 | takes_from_zeros::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromZeros` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `takes_from_zeros` + --> tests/ui-nightly/diagnostic-not-implemented-from-zeros.rs:21:24 + | +21 | fn takes_from_zeros() {} + | ^^^^^^^^^ required by this bound in `takes_from_zeros` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Immutable; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_immutable::(); +} + +fn takes_immutable() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-immutable.rs:18:23 + | +18 | takes_immutable::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `takes_immutable` + --> tests/ui-nightly/diagnostic-not-implemented-immutable.rs:21:23 + | +21 | fn takes_immutable() {} + | ^^^^^^^^^ required by this bound in `takes_immutable` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::IntoBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_into_bytes::(); +} + +fn takes_into_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-into-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs:18:24 + | +18 | takes_into_bytes::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `takes_into_bytes` + --> tests/ui-nightly/diagnostic-not-implemented-into-bytes.rs:21:24 + | +21 | fn takes_into_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_into_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::{Immutable, IntoBytes}; + +fn main() { + // This is adapted from #1296, which includes the following text: + // + // The compiler errors when a type is missing Immutable are somewhat + // misleading, although I'm not sure there's much zerocopy can do about + // this. An example where the compiler recommends adding a reference + // rather than implementing Immutable (some were even more confusing than + // this): + // + // error[E0277]: the trait bound `virtio::wl::CtrlVfdNewDmabuf: zerocopy::Immutable` is not satisfied + // --> devices/src/virtio/wl.rs:317:20 + // | + // 317 | .write_obj(ctrl_vfd_new_dmabuf) + // | --------- ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `virtio::wl::CtrlVfdNewDmabuf` + // | | + // | required by a bound introduced by this call + // | + // note: required by a bound in `virtio::descriptor_utils::Writer::write_obj` + // --> devices/src/virtio/descriptor_utils.rs:536:25 + // | + // 536 | pub fn write_obj(&mut self, val: T) -> io::Result<()> { + // | ^^^^^^^^^ required by this bound in `Writer::write_obj` + // help: consider borrowing here + // | + // 317 | .write_obj(&ctrl_vfd_new_dmabuf) + // | + + // 317 | .write_obj(&mut ctrl_vfd_new_dmabuf) + // | ++++ + // + // Taking the compiler's suggestion results in a different error with a + // recommendation to remove the reference (back to the original code). + // + // As of this writing, the described problem is still happening thanks to + // https://github.com/rust-lang/rust/issues/130563. We include this test so + // that we can capture the current behavior, but we will update it once that + // Rust issue is fixed. + Foo.write_obj(NotZerocopy(())); +} + +struct Foo; + +impl Foo { + fn write_obj(&mut self, _val: T) {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-issue-1296.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | --------- ^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | | + | required by a bound introduced by this call + | +note: required by a bound in `Foo::write_obj` + --> tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs:58:21 + | +58 | fn write_obj(&mut self, _val: T) {} + | ^^^^^^^^^ required by this bound in `Foo::write_obj` +help: consider borrowing here + | +52 | Foo.write_obj(&NotZerocopy(())); + | + +52 | Foo.write_obj(&mut NotZerocopy(())); + | ++++ + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | --------- ^^^^^^^^^^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `Foo::write_obj` + --> tests/ui-nightly/diagnostic-not-implemented-issue-1296.rs:58:33 + | +58 | fn write_obj(&mut self, _val: T) {} + | ^^^^^^^^^ required by this bound in `Foo::write_obj` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::KnownLayout; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_known_layout::(); +} + +fn takes_known_layout() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-known-layout.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::KnownLayout` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-known-layout.rs:18:26 + | +18 | takes_known_layout::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::KnownLayout` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(KnownLayout)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others +note: required by a bound in `takes_known_layout` + --> tests/ui-nightly/diagnostic-not-implemented-known-layout.rs:21:26 + | +21 | fn takes_known_layout() {} + | ^^^^^^^^^^^ required by this bound in `takes_known_layout` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::TryFromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_try_from_bytes::(); +} + +fn takes_try_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs:18:28 + | +18 | takes_try_from_bytes::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `takes_try_from_bytes` + --> tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs:21:28 + | +21 | fn takes_try_from_bytes() {} + | ^^^^^^^^^^^^ required by this bound in `takes_try_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Unaligned; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_unaligned::(); +} + +fn takes_unaligned() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/diagnostic-not-implemented-unaligned.rs:18:23 + | +18 | takes_unaligned::(); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required by a bound in `takes_unaligned` + --> tests/ui-nightly/diagnostic-not-implemented-unaligned.rs:21:23 + | +21 | fn takes_unaligned() {} + | ^^^^^^^^^ required by this bound in `takes_unaligned` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +#[macro_use] +extern crate zerocopy; + +use util::NotZerocopy; + +fn main() {} + +// Should fail because `NotZerocopy: !FromBytes`. +const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_not_from_bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-nightly/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/include_value_wrong_size.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +error[E0080]: transmuting from 4-byte type to 8-byte type: `[u8; 4]` -> `u64` + --> tests/ui-nightly/include_value_wrong_size.rs:15:25 + | +15 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `WRONG_SIZE` failed here + | + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/include_value_wrong_size.rs:15:25 + | +15 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Since some macros from `macros.rs` are unused. +#![allow(unused)] + +extern crate zerocopy; +extern crate zerocopy_derive; + +include!("../../../src/util/macros.rs"); + +use zerocopy::*; +use zerocopy_derive::*; + +fn main() {} + +#[derive(FromBytes, IntoBytes, Unaligned)] +#[repr(transparent)] +struct Foo(T); + +const _: () = unsafe { + impl_or_verify!(T => TryFromBytes for Foo); + impl_or_verify!(T => FromZeros for Foo); + impl_or_verify!(T => FromBytes for Foo); + impl_or_verify!(T => IntoBytes for Foo); + impl_or_verify!(T => Unaligned for Foo); +}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/invalid-impls/invalid-impls.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:27:43 + | + 27 | impl_or_verify!(T => TryFromBytes for Foo); + | ^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::TryFromBytes` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 + | + 22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:27:5 + | + 27 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `TryFromBytes` + | + 27 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromZeros` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:28:40 + | + 28 | impl_or_verify!(T => FromZeros for Foo); + | ^^^^^^ the trait `zerocopy::FromZeros` is not implemented for `T` + | + = note: Consider adding `#[derive(FromZeros)]` to `T` +note: required for `Foo` to implement `zerocopy::FromZeros` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 + | + 22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:28:5 + | + 28 | impl_or_verify!(T => FromZeros for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `FromZeros` + | + 28 | impl_or_verify!(T: zerocopy::FromZeros => FromZeros for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:29:40 + | + 29 | impl_or_verify!(T => FromBytes for Foo); + | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(FromBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::FromBytes` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 + | + 22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:29:5 + | + 29 | impl_or_verify!(T => FromBytes for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `FromBytes` + | + 29 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:30:40 + | + 30 | impl_or_verify!(T => IntoBytes for Foo); + | ^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(IntoBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::IntoBytes` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:21 + | + 22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:30:5 + | + 30 | impl_or_verify!(T => IntoBytes for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `IntoBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `IntoBytes` + | + 30 | impl_or_verify!(T: zerocopy::IntoBytes => IntoBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:31:40 + | + 31 | impl_or_verify!(T => Unaligned for Foo); + | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` + | + = note: Consider adding `#[derive(Unaligned)]` to `T` +note: required for `Foo` to implement `zerocopy::Unaligned` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:32 + | + 22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:31:5 + | + 31 | impl_or_verify!(T => Unaligned for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `Unaligned` + | + 31 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/max-align.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-nightly/max-align.rs:96:17 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +use zerocopy::pointer::{ + invariant::{Aligned, Exclusive, Shared, Valid}, + Ptr, +}; + +fn _when_exclusive<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Exclusive, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Exclusive, Aligned, Valid)>, +) { + _small = big; +} + +fn _when_shared<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Shared, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Shared, Aligned, Valid)>, +) { + _small = big; +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/ptr-is-invariant-over-v.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error: lifetime may not live long enough + --> tests/ui-nightly/ptr-is-invariant-over-v.rs:10:5 + | + 6 | fn _when_exclusive<'big: 'small, 'small>( + | ---- ------ lifetime `'small` defined here + | | + | lifetime `'big` defined here +... +10 | _small = big; + | ^^^^^^^^^^^^ assignment requires that `'small` must outlive `'big` + | + = help: consider adding the following bound: `'small: 'big` + = note: requirement occurs because of the type `Ptr<'_, &u32, (invariant::Exclusive, Aligned, Valid)>`, which makes the generic argument `&u32` invariant + = note: the struct `Ptr<'a, T, I>` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> tests/ui-nightly/ptr-is-invariant-over-v.rs:17:5 + | +13 | fn _when_shared<'big: 'small, 'small>( + | ---- ------ lifetime `'small` defined here + | | + | lifetime `'big` defined here +... +17 | _small = big; + | ^^^^^^^^^^^^ assignment requires that `'small` must outlive `'big` + | + = help: consider adding the following bound: `'small: 'big` + = note: requirement occurs because of the type `Ptr<'_, &u32, (Shared, Aligned, Valid)>`, which makes the generic argument `&u32` invariant + = note: the struct `Ptr<'a, T, I>` is invariant over the parameter `T` + = help: see for more information about variance diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` + --> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-nightly/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-nightly/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0015]: cannot call non-const method `Wrap::<&mut [u8; 2], &mut [u8; 2]>::transmute_mut` in constants + --> tests/ui-nightly/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38 + | + 24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromBytes` is not implemented for `Dst` + --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:21:1 + | + 21 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `IntoBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-dst-not-intobytes.rs:24:36 + | + 24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `IntoBytes` is not implemented for `Dst` + --> tests/ui-nightly/transmute-mut-dst-not-intobytes.rs:21:1 + | + 21 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | + 17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | impl<'a, Src, Dst> Wrap<&'a mut Src, &'a mut Dst> { + | ^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` +... + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-nightly/transmute-mut-illegal-lifetime.rs:14:56 + | +12 | let mut x = 0u64; + | ----- binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize); + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize); + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38 + | + 24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromBytes` is not implemented for `Src` + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:17:1 + | + 17 | struct Src; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Src` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-intobytes.rs:24:36 + | + 24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `IntoBytes` is not implemented for `Src` + --> tests/ui-nightly/transmute-mut-src-not-intobytes.rs:17:1 + | + 17 | struct Src; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type to +// a sized destination type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-nightly/transmute-mut-src-unsized.rs:17:35 + | +17 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | + = note: required for `Wrap<&mut [u8], &mut [u8; 1]>` to implement `TransmuteMutDst<'_>` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ptr-to-usize.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `IntoBytes` is not implemented for `*const usize` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` + = help: the trait `IntoBytes` is implemented for `usize` +note: required by a bound in `POINTER_VALUE::transmute` + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Dst: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `zerocopy::FromBytes` is not implemented for `Dst` + --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:20:1 + | +20 | struct Dst(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::FromBytes)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `Immutable` +const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Dst: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `zerocopy::Immutable` is not implemented for `Dst` + --> tests/ui-nightly/transmute-ref-dst-not-nocell.rs:20:1 + | +20 | struct Dst(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `Dst` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertDstIsImmutable` + --> tests/ui-nightly/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | + 17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wrap::<&'a Src, &'a Dst>::transmute_ref` + --> src/util/macro_util.rs + | + | impl<'a, Src, Dst> Wrap<&'a Src, &'a Dst> { + | ^^^ required by this bound in `Wrap::<&Src, &Dst>::transmute_ref` +... + | pub const unsafe fn transmute_ref(self) -> &'a Dst { + | ------------- required by a bound in this associated function + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-nightly/transmute-ref-illegal-lifetime.rs:14:52 + | +12 | let x = 0u64; + | - binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize); + | + + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize); + | + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `zerocopy::IntoBytes` is not implemented for `Src` + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:20:1 + | +20 | struct Src(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `AssertSrcIsIntoBytes` + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `Src` + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:20:1 + | +20 | struct Src(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `AssertSrcIsIntoBytes` + --> tests/ui-nightly/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::IntoBytes)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `Immutable` +const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `zerocopy::Immutable` is not implemented for `Src` + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:20:1 + | +20 | struct Src(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `Src` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertSrcIsImmutable` + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Immutable` is not implemented for `Src` + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:20:1 + | +20 | struct Src(AU16); + | ^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `Src` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertSrcIsImmutable` + --> tests/ui-nightly/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | + = note: required for `Wrap<&[u8], &[u8; 1]>` to implement `TransmuteRefDst<'_>` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +error[E0080]: transmuting from 2-byte type to 1-byte type: `AU16` -> `u8` + --> tests/ui-nightly/transmute-size-decrease.rs:20:27 + | +20 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ evaluation of `DECREASE_SIZE` failed here + | + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-decrease.rs:20:27 + | +20 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +error[E0080]: transmuting from 1-byte type to 2-byte type: `u8` -> `Transmute` + --> tests/ui-nightly/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INCREASE_SIZE` failed here + | + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +error[E0080]: transmuting from 1-byte type to 2-byte type: `u8` -> `AU16` + --> tests/ui-nightly/transmute-size-increase.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ evaluation of `INCREASE_SIZE` failed here + | + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-increase.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound + | required by a bound introduced by this call + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` + --> tests/ui-nightly/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:33 + | + 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:58 + | + 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | pub fn try_transmute(src: Src) -> Result> + | ------------- required by a bound in this function +... + | Dst: TryFromBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:58 + | + 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute-size-decrease.rs:19:41 + | +19 | let _decrease_size: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// `try_transmute!` does not support transmuting from a smaller type to a larger +// one. +fn main() { + let _increase_size: Result = try_transmute!(0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute-size-increase.rs:19:43 + | +19 | let _increase_size: Result = try_transmute!(0u8); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + // `try_transmute` requires that the source type implements `IntoBytes` + let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute-src-not-intobytes.rs:18:47 + | + 18 | let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | pub fn try_transmute(src: Src) -> Result> + | ------------- required by a bound in this function + | where + | Src: IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let src = &mut [0u8; 2]; + let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_mut-alignment-increase.rs:20:48 + | +20 | let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_mut; + +fn main() { + // `try_transmute_mut` requires that the destination type implements + // `IntoBytes` + let src = &mut AU16(0); + let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 + | + 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | + 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | pub fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | + 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | pub fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | + 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let src = &mut AU16(0); + let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_mut-size-decrease.rs:20:46 + | +20 | let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let src = &mut 0u8; + let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +warning: unused import: `util::AU16` + --> tests/ui-nightly/try_transmute_mut-size-increase.rs:13:5 + | +13 | use util::AU16; + | ^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_mut-size-increase.rs:20:51 + | +20 | let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::IntoBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `FromBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromBytes` is not implemented for `Src` + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:15:1 + | + 15 | struct Src; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Src` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromBytes` is not implemented for `Dst` + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:19:1 + | + 19 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `IntoBytes` is not implemented for `Dst` + --> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:19:1 + | + 19 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `IntoBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `IntoBytes` is not implemented for `Src` + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:15:1 + | + 15 | struct Src; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromBytes` is not implemented for `Dst` + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:19:1 + | + 19 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:23:40 + | + 23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `IntoBytes` is not implemented for `Dst` + --> tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs:19:1 + | + 19 | struct Dst; + | ^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_ref-alignment-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::try_transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `try_transmute_ref!` requires that its destination type be an immutable + // reference. + let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/try_transmute_ref-dst-mutable.rs:18:33 + | + 18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | arguments to this enum variant are incorrect + | + = note: expected mutable reference `&mut u8` + found reference `&_` +help: the type constructed contains `&_` due to the type of the argument passed + --> tests/ui-nightly/try_transmute_ref-dst-mutable.rs:18:33 + | + 18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this argument influences the type of `Ok` +note: tuple variant defined here + --> $RUST/core/src/result.rs + | + | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^ + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected enum `Result<&mut u8, _>` + found enum `Result<&_, ValidityError<&u8, _>>` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,120 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 + | + 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | + 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | + 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | + 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_ref-size-decrease.rs:19:42 + | +19 | let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/try_transmute_ref-size-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | + 19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function + | where + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | + 19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../../zerocopy-derive/tests/include.rs + | + 48 | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function + | where + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_bytes::(); +} + +fn takes_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-from-bytes.rs:18:24 + | +18 | takes_from_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `takes_from_bytes` + --> tests/ui-stable/diagnostic-not-implemented-from-bytes.rs:21:24 + | +21 | fn takes_from_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::FromZeros; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_from_zeros::(); +} + +fn takes_from_zeros() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-from-zeros.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-from-zeros.rs:18:24 + | +18 | takes_from_zeros::(); + | ^^^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `takes_from_zeros` + --> tests/ui-stable/diagnostic-not-implemented-from-zeros.rs:21:24 + | +21 | fn takes_from_zeros() {} + | ^^^^^^^^^ required by this bound in `takes_from_zeros` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Immutable; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_immutable::(); +} + +fn takes_immutable() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-immutable.rs:18:23 + | +18 | takes_immutable::(); + | ^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `takes_immutable` + --> tests/ui-stable/diagnostic-not-implemented-immutable.rs:21:23 + | +21 | fn takes_immutable() {} + | ^^^^^^^^^ required by this bound in `takes_immutable` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::IntoBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_into_bytes::(); +} + +fn takes_into_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-into-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-into-bytes.rs:18:24 + | +18 | takes_into_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `takes_into_bytes` + --> tests/ui-stable/diagnostic-not-implemented-into-bytes.rs:21:24 + | +21 | fn takes_into_bytes() {} + | ^^^^^^^^^ required by this bound in `takes_into_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::{Immutable, IntoBytes}; + +fn main() { + // This is adapted from #1296, which includes the following text: + // + // The compiler errors when a type is missing Immutable are somewhat + // misleading, although I'm not sure there's much zerocopy can do about + // this. An example where the compiler recommends adding a reference + // rather than implementing Immutable (some were even more confusing than + // this): + // + // error[E0277]: the trait bound `virtio::wl::CtrlVfdNewDmabuf: zerocopy::Immutable` is not satisfied + // --> devices/src/virtio/wl.rs:317:20 + // | + // 317 | .write_obj(ctrl_vfd_new_dmabuf) + // | --------- ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `virtio::wl::CtrlVfdNewDmabuf` + // | | + // | required by a bound introduced by this call + // | + // note: required by a bound in `virtio::descriptor_utils::Writer::write_obj` + // --> devices/src/virtio/descriptor_utils.rs:536:25 + // | + // 536 | pub fn write_obj(&mut self, val: T) -> io::Result<()> { + // | ^^^^^^^^^ required by this bound in `Writer::write_obj` + // help: consider borrowing here + // | + // 317 | .write_obj(&ctrl_vfd_new_dmabuf) + // | + + // 317 | .write_obj(&mut ctrl_vfd_new_dmabuf) + // | ++++ + // + // Taking the compiler's suggestion results in a different error with a + // recommendation to remove the reference (back to the original code). + // + // As of this writing, the described problem is still happening thanks to + // https://github.com/rust-lang/rust/issues/130563. We include this test so + // that we can capture the current behavior, but we will update it once that + // Rust issue is fixed. + Foo.write_obj(NotZerocopy(())); +} + +struct Foo; + +impl Foo { + fn write_obj(&mut self, _val: T) {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-issue-1296.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | --------- ^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | | + | required by a bound introduced by this call + | +note: required by a bound in `Foo::write_obj` + --> tests/ui-stable/diagnostic-not-implemented-issue-1296.rs:58:21 + | +58 | fn write_obj(&mut self, _val: T) {} + | ^^^^^^^^^ required by this bound in `Foo::write_obj` +help: consider borrowing here + | +52 | Foo.write_obj(&NotZerocopy(())); + | + +52 | Foo.write_obj(&mut NotZerocopy(())); + | ++++ + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-issue-1296.rs:52:19 + | +52 | Foo.write_obj(NotZerocopy(())); + | --------- ^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | | + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `Foo::write_obj` + --> tests/ui-stable/diagnostic-not-implemented-issue-1296.rs:58:33 + | +58 | fn write_obj(&mut self, _val: T) {} + | ^^^^^^^^^ required by this bound in `Foo::write_obj` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::KnownLayout; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_known_layout::(); +} + +fn takes_known_layout() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-known-layout.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::KnownLayout` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-known-layout.rs:18:26 + | +18 | takes_known_layout::(); + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(KnownLayout)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others +note: required by a bound in `takes_known_layout` + --> tests/ui-stable/diagnostic-not-implemented-known-layout.rs:21:26 + | +21 | fn takes_known_layout() {} + | ^^^^^^^^^^^ required by this bound in `takes_known_layout` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::TryFromBytes; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_try_from_bytes::(); +} + +fn takes_try_from_bytes() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs:18:28 + | +18 | takes_try_from_bytes::(); + | ^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `takes_try_from_bytes` + --> tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs:21:28 + | +21 | fn takes_try_from_bytes() {} + | ^^^^^^^^^^^^ required by this bound in `takes_try_from_bytes` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::NotZerocopy; +use zerocopy::Unaligned; + +fn main() { + // We expect the proper diagnostic to be emitted on Rust 1.78.0 and later. + takes_unaligned::(); +} + +fn takes_unaligned() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/diagnostic-not-implemented-unaligned.rs:18:23 + | +18 | takes_unaligned::(); + | ^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(Unaligned)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required by a bound in `takes_unaligned` + --> tests/ui-stable/diagnostic-not-implemented-unaligned.rs:21:23 + | +21 | fn takes_unaligned() {} + | ^^^^^^^^^ required by this bound in `takes_unaligned` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +#[macro_use] +extern crate zerocopy; + +use util::NotZerocopy; + +fn main() {} + +// Should fail because `NotZerocopy: !FromBytes`. +const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_not_from_bytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-stable/include_value_not_from_bytes.rs:19:42 + | +19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/include_value_wrong_size.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/include_value_wrong_size.rs:15:25 + | +15 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Since some macros from `macros.rs` are unused. +#![allow(unused)] + +extern crate zerocopy; +extern crate zerocopy_derive; + +include!("../../../src/util/macros.rs"); + +use zerocopy::*; +use zerocopy_derive::*; + +fn main() {} + +#[derive(FromBytes, IntoBytes, Unaligned)] +#[repr(transparent)] +struct Foo(T); + +const _: () = unsafe { + impl_or_verify!(T => TryFromBytes for Foo); + impl_or_verify!(T => FromZeros for Foo); + impl_or_verify!(T => FromBytes for Foo); + impl_or_verify!(T => IntoBytes for Foo); + impl_or_verify!(T => Unaligned for Foo); +}; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/invalid-impls/invalid-impls.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:27:43 + | +27 | impl_or_verify!(T => TryFromBytes for Foo); + | ^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::TryFromBytes` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:27:5 + | +27 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `TryFromBytes` + | +27 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromZeros` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:28:40 + | +28 | impl_or_verify!(T => FromZeros for Foo); + | ^^^^^^ the trait `zerocopy::FromZeros` is not implemented for `T` + | + = note: Consider adding `#[derive(FromZeros)]` to `T` +note: required for `Foo` to implement `zerocopy::FromZeros` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:28:5 + | +28 | impl_or_verify!(T => FromZeros for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `FromZeros` + | +28 | impl_or_verify!(T: zerocopy::FromZeros => FromZeros for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:29:40 + | +29 | impl_or_verify!(T => FromBytes for Foo); + | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(FromBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::FromBytes` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:29:5 + | +29 | impl_or_verify!(T => FromBytes for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `FromBytes` + | +29 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:30:40 + | +30 | impl_or_verify!(T => IntoBytes for Foo); + | ^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `T` + | + = note: Consider adding `#[derive(IntoBytes)]` to `T` +note: required for `Foo` to implement `zerocopy::IntoBytes` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:21 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:30:5 + | +30 | impl_or_verify!(T => IntoBytes for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `IntoBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `IntoBytes` + | +30 | impl_or_verify!(T: zerocopy::IntoBytes => IntoBytes for Foo); + | +++++++++++++++++++++ + +error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:31:40 + | +31 | impl_or_verify!(T => Unaligned for Foo); + | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` + | + = note: Consider adding `#[derive(Unaligned)]` to `T` +note: required for `Foo` to implement `zerocopy::Unaligned` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:32 + | +22 | #[derive(FromBytes, IntoBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/util/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:31:5 + | +31 | impl_or_verify!(T => Unaligned for Foo); + | ------------------------------------------ in this macro invocation + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `Unaligned` + | +31 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/max-align.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-stable/max-align.rs:96:17 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +use zerocopy::pointer::{ + invariant::{Aligned, Exclusive, Shared, Valid}, + Ptr, +}; + +fn _when_exclusive<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Exclusive, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Exclusive, Aligned, Valid)>, +) { + _small = big; +} + +fn _when_shared<'big: 'small, 'small>( + big: Ptr<'small, &'big u32, (Shared, Aligned, Valid)>, + mut _small: Ptr<'small, &'small u32, (Shared, Aligned, Valid)>, +) { + _small = big; +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/ptr-is-invariant-over-v.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +error: lifetime may not live long enough + --> tests/ui-stable/ptr-is-invariant-over-v.rs:10:5 + | +6 | fn _when_exclusive<'big: 'small, 'small>( + | ---- ------ lifetime `'small` defined here + | | + | lifetime `'big` defined here +... +10 | _small = big; + | ^^^^^^^^^^^^ assignment requires that `'small` must outlive `'big` + | + = help: consider adding the following bound: `'small: 'big` + = note: requirement occurs because of the type `Ptr<'_, &u32, (invariant::Exclusive, Aligned, Valid)>`, which makes the generic argument `&u32` invariant + = note: the struct `Ptr<'a, T, I>` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> tests/ui-stable/ptr-is-invariant-over-v.rs:17:5 + | +13 | fn _when_shared<'big: 'small, 'small>( + | ---- ------ lifetime `'small` defined here + | | + | lifetime `'big` defined here +... +17 | _small = big; + | ^^^^^^^^^^^^ assignment requires that `'small` must outlive `'big` + | + = help: consider adding the following bound: `'small: 'big` + = note: requirement occurs because of the type `Ptr<'_, &u32, (Shared, Aligned, Valid)>`, which makes the generic argument `&u32` invariant + = note: the struct `Ptr<'a, T, I>` is invariant over the parameter `T` + = help: see for more information about variance diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` + --> tests/ui-stable/transmute-dst-not-frombytes.rs:19:41 + | +19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-stable/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-stable/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0015]: cannot call non-const method `Wrap::<&mut [u8; 2], &mut [u8; 2]>::transmute_mut` in constants + --> tests/ui-stable/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-stable/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `IntoBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-stable/transmute-mut-dst-not-intobytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | impl<'a, Src, Dst> Wrap<&'a mut Src, &'a mut Dst> { + | ^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` +... + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-stable/transmute-mut-illegal-lifetime.rs:14:56 + | +12 | let mut x = 0u64; + | ----- binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize); + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsSized` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsSized` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsSized` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsSized` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsSized` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsSized` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/util/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` +... + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `AlignOf` + --> src/util/macro_util.rs + | + | pub struct AlignOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `MaxAlignsOf` + --> src/util/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `AlignOf` + --> src/util/macro_util.rs + | + | pub struct AlignOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `std::intrinsics::transmute` + --> $RUST/core/src/intrinsics/mod.rs + | + | pub const unsafe fn transmute(src: Src) -> Dst; + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `transmute_mut` + --> src/util/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `transmute_mut` + --> src/util/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-immutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize); + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = note: Consider adding `#[derive(FromBytes)]` to `Src` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromBytes, zerocopy::Immutable)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-intobytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type to +// a sized destination type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-stable/transmute-mut-src-unsized.rs:17:35 + | +17 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | + = note: required for `Wrap<&mut [u8], &mut [u8; 1]>` to implement `TransmuteMutDst<'_>` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ptr-to-usize.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `IntoBytes` is not implemented for `*const usize` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` + = help: the trait `IntoBytes` is implemented for `usize` +note: required by a bound in `POINTER_VALUE::transmute` + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Dst: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `zerocopy::FromBytes` is not implemented for `Dst` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:23:34 + | +23 | const DST_NOT_FROM_BYTES: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::FromBytes)] +#[repr(transparent)] +struct Dst(AU16); + +// `transmute_ref` requires that the destination type implements `Immutable` +const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Dst: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `zerocopy::Immutable` is not implemented for `Dst` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(Immutable)]` to `Dst` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertDstIsImmutable` + --> tests/ui-stable/transmute-ref-dst-not-nocell.rs:23:33 + | +23 | const DST_NOT_IMMUTABLE: &Dst = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wrap::<&'a Src, &'a Dst>::transmute_ref` + --> src/util/macro_util.rs + | + | impl<'a, Src, Dst> Wrap<&'a Src, &'a Dst> { + | ^^^ required by this bound in `Wrap::<&Src, &Dst>::transmute_ref` +... + | pub const unsafe fn transmute_ref(self) -> &'a Dst { + | ------------- required by a bound in this associated function + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-illegal-lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-stable/transmute-ref-illegal-lifetime.rs:14:52 + | +12 | let x = 0u64; + | - binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize); + | + + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsSized` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsSized` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsSized` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsSized` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsSized` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsSized` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/util/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` +... + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `AlignOf` + --> src/util/macro_util.rs + | + | pub struct AlignOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `MaxAlignsOf` + --> src/util/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `AlignOf` + --> src/util/macro_util.rs + | + | pub struct AlignOf { + | ^ required by the implicit `Sized` requirement on this type parameter in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `std::intrinsics::transmute` + --> $RUST/core/src/intrinsics/mod.rs + | + | pub const unsafe fn transmute(src: Src) -> Dst; + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `transmute_ref` + --> src/util/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `transmute_ref` + --> src/util/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by the implicit `Sized` requirement on this type parameter in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-a-reference.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize); + | + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::Immutable)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `zerocopy::IntoBytes` is not implemented for `Src` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `AssertSrcIsIntoBytes` + --> tests/ui-stable/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `Src` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `AssertSrcIsIntoBytes` + --> tests/ui-stable/transmute-ref-src-not-intobytes.rs:23:33 + | +23 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute_ref; + +fn main() {} + +#[derive(zerocopy::IntoBytes)] +#[repr(transparent)] +struct Src(AU16); + +// `transmute_ref` requires that the source type implements `Immutable` +const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-not-nocell.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `zerocopy::Immutable` is not implemented for `Src` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(Immutable)]` to `Src` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertSrcIsImmutable` + --> tests/ui-stable/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `Src` + | + = note: Consider adding `#[derive(Immutable)]` to `Src` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `AssertSrcIsImmutable` + --> tests/ui-stable/transmute-ref-src-not-nocell.rs:23:34 + | +23 | const SRC_NOT_IMMUTABLE: &AU16 = transmute_ref!(&Src(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsImmutable` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0271]: type mismatch resolving `<[u8; 1] as KnownLayout>::PointerMetadata == usize` + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | + = note: required for `Wrap<&[u8], &[u8; 1]>` to implement `TransmuteRefDst<'_>` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-decrease.rs:20:27 + | +20 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase-allow-shrink.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-increase.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `IntoBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` + --> tests/ui-stable/transmute-src-not-intobytes.rs:19:32 + | +19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +// Copyright 2022 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,73 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:33 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:58 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | pub fn try_transmute(src: Src) -> Result> + | ------------- required by a bound in this function +... + | Dst: TryFromBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:58 + | +17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result = try_transmute!(AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute-size-decrease.rs:19:41 + | +19 | let _decrease_size: Result = try_transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute; + +// `try_transmute!` does not support transmuting from a smaller type to a larger +// one. +fn main() { + let _increase_size: Result = try_transmute!(0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute-size-increase.rs:19:43 + | +19 | let _increase_size: Result = try_transmute!(0u8); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute; + +fn main() { + // `try_transmute` requires that the source type implements `IntoBytes` + let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute-src-not-intobytes.rs:18:47 + | +18 | let src_not_into_bytes: Result = try_transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute` + --> src/util/macro_util.rs + | + | pub fn try_transmute(src: Src) -> Result> + | ------------- required by a bound in this function + | where + | Src: IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute` + = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let src = &mut [0u8; 2]; + let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_mut-alignment-increase.rs:20:48 + | +20 | let _increase_size: Result<&mut AU16, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_mut; + +fn main() { + // `try_transmute_mut` requires that the destination type implements + // `IntoBytes` + let src = &mut AU16(0); + let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | pub fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute_mut` + --> src/util/macro_util.rs + | + | pub fn try_transmute_mut(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `try_transmute_mut` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 + | +20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let src = &mut AU16(0); + let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_mut-size-decrease.rs:20:46 + | +20 | let _decrease_size: Result<&mut u8, _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_mut; + +// `try_transmute_mut!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let src = &mut 0u8; + let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +warning: unused import: `util::AU16` + --> tests/ui-stable/try_transmute_mut-size-increase.rs:13:5 + | +13 | use util::AU16; + | ^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_mut-size-increase.rs:20:51 + | +20 | let _increase_size: Result<&mut [u8; 2], _> = try_transmute_mut!(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::IntoBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `FromBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-frombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = note: Consider adding `#[derive(FromBytes)]` to `Src` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-frombytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +#[derive(zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::TryFromBytes)] +#[repr(C)] +struct Dst; + +fn main() { + // `try_transmute_mut` requires that the source type implements `IntoBytes` + let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_mut-src-not-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `Src: IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Src` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function + | where + | Src: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(FromBytes)]` to `Dst` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute_mut-src-not-intobytes.rs:23:40 + | +23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst` + | + = note: Consider adding `#[derive(IntoBytes)]` to `Dst` + = help: the following other types implement trait `IntoBytes`: + () + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required by a bound in `Wrap::<&'a mut Src, &'a mut Dst>::transmute_mut` + --> src/util/macro_util.rs + | + | pub fn transmute_mut(self) -> &'a mut Dst + | ------------- required by a bound in this associated function +... + | Dst: FromBytes + IntoBytes, + | ^^^^^^^^^ required by this bound in `Wrap::<&mut Src, &mut Dst>::transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_ref-alignment-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::try_transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `try_transmute_ref!` requires that its destination type be an immutable + // reference. + let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-mutable.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> tests/ui-stable/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | arguments to this enum variant are incorrect + | + = note: expected mutable reference `&mut u8` + found reference `&_` +help: the type constructed contains `&_` due to the type of the argument passed + --> tests/ui-stable/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this argument influences the type of `Ok` +note: tuple variant defined here + --> $RUST/core/src/result.rs + | + | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^ + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/try_transmute_ref-dst-mutable.rs:18:33 + | +18 | let _: Result<&mut u8, _> = try_transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected enum `Result<&mut u8, _>` + found enum `Result<&_, ValidityError<&u8, _>>` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function +... + | Dst: TryFromBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 + | +19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required by a bound in `ValidityError` + --> src/error.rs + | + | pub struct ValidityError { + | ^^^^^^^^^^^^ required by this bound in `ValidityError` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +fn main() { + let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_ref-size-decrease.rs:19:42 + | +19 | let _decrease_size: Result<&u8, _> = try_transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::try_transmute_ref; + +// `try_transmute_ref!` does not support transmuting from a smaller type to a +// larger one. +fn main() { + let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/try_transmute_ref-size-increase.rs:19:44 + | +19 | let _increase_size: Result<&AU16, _> = try_transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +include!("../../zerocopy-derive/tests/include.rs"); + +extern crate zerocopy; + +use util::{NotZerocopy, AU16}; +use zerocopy::try_transmute_ref; + +fn main() { + // `try_transmute_ref` requires that the source type implements `Immutable` + // and `IntoBytes` + let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | +19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function + | where + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.rs:19:48 + | +19 | let src_not_into_bytes: Result<&AU16, _> = try_transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(Immutable)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + Box + F32 + and $N others +note: required by a bound in `try_transmute_ref` + --> src/util/macro_util.rs + | + | pub fn try_transmute_ref(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> + | ----------------- required by a bound in this function + | where + | Src: IntoBytes + Immutable, + | ^^^^^^^^^ required by this bound in `try_transmute_ref` + = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/win-cargo.bat clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/win-cargo.bat --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy/win-cargo.bat 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy/win-cargo.bat 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +@rem Copyright 2024 The Fuchsia Authors + +@rem Licensed under a BSD-style license , Apache License, Version 2.0 +@rem , or the MIT +@rem license , at your option. +@rem This file may not be copied, modified, or distributed except according to +@rem those terms. + +@rem Build `cargo-zerocopy` without any RUSTFLAGS set in the environment +@set TEMP_RUSTFLAGS=%RUSTFLAGS% +@set RUSTFLAGS= +@cargo +stable build --manifest-path tools/Cargo.toml -p cargo-zerocopy -q +@set RUSTFLAGS=%TEMP_RUSTFLAGS% +@set TEMP_RUSTFLAGS= +@rem Thin wrapper around the `cargo-zerocopy` binary in `tools/cargo-zerocopy` +@tools\target\debug\cargo-zerocopy %* diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"8a03c2e942d9b86f25b786f8ccdf88394a9ab879dd74c9a8b07a2739e6d3e9c9","Cargo.lock":"066e64338cf273667171e492528c54deb224a9fae929a9d7500997ed41f9a3fa","Cargo.toml":"2ccfdabb2d8e2a0afab38abe0739ae3e93c35f7d730dc3317279c6cc888eef21","Cargo.toml.orig":"0a65b24a9b6bd0ae50c366abaaeee58b33ddfc42c3c3122841c32f4dd2c83295","LICENSE-APACHE":"9d185ac6703c4b0453974c0d85e9eee43e6941009296bb1f5eb0b54e2329e9f3","LICENSE-BSD":"83c1763356e822adde0a2cae748d938a73fdc263849ccff6b27776dff213bd32","LICENSE-MIT":"1a2f5c12ddc934d58956aa5dbdd3255fe55fd957633ab7d0d39e4f0daa73f7df","src/enum.rs":"0f2bf3d6efc532f6bbe36a9f2c0c61da11c29e01161fef8903e392e7ce992488","src/ext.rs":"e779f1994eac9e28bf30357ddf9431cd05c6cf8536a3f1f8fae0e808a4e18818","src/lib.rs":"42c3c3bf9744f279ebf4b0f6b0a7708215f67a6e20e6ba297e8c1e485e813cce","src/output_tests.rs":"cdd7ff44e0be36bd7c74398bb4f9ecd0cf431fd37910f5c864221b0f84338cf4","src/repr.rs":"2766afad6cf7bd24ee67ee02452e638dac474e8d00edb51dff54f9e9691d2526","tests/crate_path.rs":"9083a9ed020b254e3ae632207ec6f72dd3eede94081f76f0378bdb62308398df","tests/deprecated.rs":"a8c7e51d3c43fcea40fd1873f5237ad1e6d8f12e2b011f012d0bafa484da245b","tests/enum_from_zeros.rs":"1e712a2802195af290c7ebefb8645158eef96698dfb93b323f9ce234e878c58d","tests/enum_known_layout.rs":"9a36492810c0a7744e651dc8dd8a5749a81dd678b8cd6713ebe3aaa5fe17d7e6","tests/enum_no_cell.rs":"0024ffbd04551350ff2c4d8c4262fc22ebadc599d1f641bedf1bf24d6a060c78","tests/enum_to_bytes.rs":"cf7d0c482e833d2b4f6f677f4c45495f654bdc4862b5044a183dea56533a2e7a","tests/enum_try_from_bytes.rs":"f6d3ce1277182cc659286c01f6eaf52220c10ff0290b23865268a69a67556daf","tests/enum_unaligned.rs":"e04c9d1fa0f8abcd2353cab94015da010e2b3bdee65e23186c7bd13ff89d54c3","tests/eq.rs":"97fd62ff73c474e00921edc3e1bac639dfe757db1b9419d7ed97894a2b76b682","tests/hash.rs":"f0dd3df5f177b6806def5334d38f89348308e56680f7624ca3753ef503f98604","tests/hygiene.rs":"5ee71dbb525e5e40161e9b886d322b2969c60da152c2e87c59e759fc24cd143d","tests/include.rs":"2c042273938a26638d9251d6f08b4d99ab3666d9871fdf19c57bf86007798ab2","tests/issue_2117.rs":"7cd6480a9684c7efe915753057973363a0e2bce93bea5a85d3139ea9b2f519bd","tests/paths_and_modules.rs":"07a0cc3006e5b60dd32fb0530fa4e5c9e4438d38b3cdd4eb7aca456e6f45a121","tests/priv_in_pub.rs":"cf800572fb32f8a31dc68bf74833abbc40a15ca70a5aad243a496dac136c8ed0","tests/struct_from_bytes.rs":"95dc1d2fec9917044da0bad9a4e217641f3052f95bb8d5f7511fdf72683ce040","tests/struct_from_zeros.rs":"3436b3c34d0ccd69b456dc41264a6c5d3af60f1f955e08f6475cc9ace3cd5f95","tests/struct_known_layout.rs":"3eadf41f559ee62471171f7075b9e6745cdeae3c0a7343ba65f100f17651cdaa","tests/struct_no_cell.rs":"aea0ef4836d5ad38a968304ea57a2cbf46c8b60864c98dd421c72b3369aafb6c","tests/struct_to_bytes.rs":"373adad8dd5d38ad86aa432b5bab7fcf3f95dee2cd0f1cd616390d9d4755a615","tests/struct_try_from_bytes.rs":"b37c8b0388604f6f7d42fa52e19ce57a71c898339d411fcb5d7f11de0e8fcce5","tests/struct_unaligned.rs":"405ac720c3ce5f6b63ca17248455d45ca92967f8a43b3f347deec03fdb841c6e","tests/trybuild.rs":"a240f2b14fbd84a9f61e8eaf9dcccdbea9359802bf81189f9939dcc06a81afd0","tests/ui-msrv/derive_transparent.rs":"a822e79244df0da55fad83b8cde327f3c1dab7011c8e0b828221d3921537f9ad","tests/ui-msrv/derive_transparent.stderr":"9ce9d216e2c51b252a67b0e1b5b9db034dd9e35e1efcc84ec8f8a7d11d4b378d","tests/ui-msrv/enum.rs":"cbaa483762e1f9ba8448279d740cf5ad9444b144aa9fc31300cfb89cfc123db9","tests/ui-msrv/enum.stderr":"f78d7e763d13fa96d24ee9d991b09b1c3f27058dc195f05a5478aa5bf0fab811","tests/ui-msrv/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-msrv/enum_from_bytes_u8_too_few.stderr":"a5ab2757166ef9dfa51a09d3dbddd5e9e2b1a46bd3d4b8d175b33a90747878d7","tests/ui-msrv/late_compile_pass.rs":"242d13124ee2fb28413fabec77019ad38b3a1a49ce4f6a783dac8b9c244ea0a5","tests/ui-msrv/late_compile_pass.stderr":"0c518781f144fbe091ad8165ecfbd9341621eda13b67b05e9ea797f1d0587f9e","tests/ui-msrv/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-msrv/mid_compile_pass.stderr":"02f51290ac6e31ebab51d7917df644163f6c2346877506d7debe8a6351acda95","tests/ui-msrv/msrv_specific.rs":"ef23fd947a553a97fd7d2c2c201b1b1ca98a11cb59894325c2b3ccd61b0dd980","tests/ui-msrv/msrv_specific.stderr":"7aec6f7f077f12f6d35ef31504b9e80fa070245a0feb776b6cc8720614f8f64c","tests/ui-msrv/struct.rs":"f8f07369ec53ab84a62a3ed435cc762268ed98ba44b7c0a2f387388fc15fe25c","tests/ui-msrv/struct.stderr":"b1970c0a893ac7e167f33ff2d97c9cc1a09dac141ea2ff4fc27a6d09aa13bdda","tests/ui-msrv/union.rs":"8bf1cf5267427674a17be834debb16cd4177c5a1103019c0b52ef24e91b6e6c7","tests/ui-msrv/union.stderr":"557f3a446af9213c905e7449ff71f6d62ea8a61547312d3358082b590fe17680","tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs":"a0168adcd0dfdc46e84421937c704b713a1307a4fc2efc19bac5dc32f6758e89","tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr":"0b9af4f767cc1d6fc591d75b046d31617b5230f012d8ce7c70d7c20ffd6178ca","tests/ui-nightly/absence_of_deprecated_warning.rs":"126083dc4f3efaa51c0606ab68073fea904dc3f71805782b47117bb4ca563b44","tests/ui-nightly/absence_of_deprecated_warning.stderr":"7177d3bbc4b897037c34775f801baef8461483d55915443f07a165f67c5b5f16","tests/ui-nightly/derive_transparent.rs":"a822e79244df0da55fad83b8cde327f3c1dab7011c8e0b828221d3921537f9ad","tests/ui-nightly/derive_transparent.stderr":"f7bff4f69ed5474350f5b056f05cf05bf6ce2a7f9443dc31bd7465ed201ecdc3","tests/ui-nightly/enum.rs":"cbaa483762e1f9ba8448279d740cf5ad9444b144aa9fc31300cfb89cfc123db9","tests/ui-nightly/enum.stderr":"c13aba9d65c51723c0779510fbea68f60d569256a1004e353fddd5000b361731","tests/ui-nightly/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-nightly/enum_from_bytes_u8_too_few.stderr":"6523010fb4d9d3b5313778c144878904647f6ece5e985e8ceac01fb2c6d69f3b","tests/ui-nightly/late_compile_pass.rs":"242d13124ee2fb28413fabec77019ad38b3a1a49ce4f6a783dac8b9c244ea0a5","tests/ui-nightly/late_compile_pass.stderr":"7854a41cbca727f15aea4450137318ffc3fdfe37f1f392fb27fb1288c51a4452","tests/ui-nightly/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-nightly/mid_compile_pass.stderr":"9ad9aeb1e55ab8e84ce0b818e59c9df25f91c47fe1648fad5b129ebb35c493ac","tests/ui-nightly/struct.rs":"f8f07369ec53ab84a62a3ed435cc762268ed98ba44b7c0a2f387388fc15fe25c","tests/ui-nightly/struct.stderr":"9c5e5a8edfc5edc8ba479a76710416de06c056e32c49a56e9f2a6e650d220764","tests/ui-nightly/union.rs":"8bf1cf5267427674a17be834debb16cd4177c5a1103019c0b52ef24e91b6e6c7","tests/ui-nightly/union.stderr":"761ac67a394449703de65a0cb14bda01441922ac515d03e3e082461962e5f6fd","tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs":"a0168adcd0dfdc46e84421937c704b713a1307a4fc2efc19bac5dc32f6758e89","tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr":"1462a888754048e09c81c93ee4e46c860a85c7683655f35c1b9a305b386b2676","tests/ui-stable/derive_transparent.rs":"a822e79244df0da55fad83b8cde327f3c1dab7011c8e0b828221d3921537f9ad","tests/ui-stable/derive_transparent.stderr":"860580857bf308398132e3b15880eb8bf8ddb829b67154f2ea3901bd14d86b5a","tests/ui-stable/enum.rs":"cbaa483762e1f9ba8448279d740cf5ad9444b144aa9fc31300cfb89cfc123db9","tests/ui-stable/enum.stderr":"8d3d75fde3d95285fa68edeec7a6b16ead45d89b0d209ea3332cea1289f9f4c3","tests/ui-stable/enum_from_bytes_u8_too_few.rs":"afbec6f24a4bfca472f2929abc5125d8f5b305a0a1b472a1215ad7739ed63100","tests/ui-stable/enum_from_bytes_u8_too_few.stderr":"b3edb381f968f6f2ad9ab4810132df5962b0650460e07f77af818ababf124fe7","tests/ui-stable/late_compile_pass.rs":"242d13124ee2fb28413fabec77019ad38b3a1a49ce4f6a783dac8b9c244ea0a5","tests/ui-stable/late_compile_pass.stderr":"237080723e742cb032e11f595896e931eceafe9a4e23f8fe74257696ca1e85bd","tests/ui-stable/mid_compile_pass.rs":"b80b01bfd383c537173f7d630ec2789a2af3e01bc6d53c807fdcf271b235d0c9","tests/ui-stable/mid_compile_pass.stderr":"0c8fa05159e21c087c8a2a87fb506b0fcd9692c84010c4c7eafd4c1bb1c390c3","tests/ui-stable/struct.rs":"f8f07369ec53ab84a62a3ed435cc762268ed98ba44b7c0a2f387388fc15fe25c","tests/ui-stable/struct.stderr":"673b57c0e4c3b7057a6a3631b492d8737f1599358292516e84d4093eb1c2e046","tests/ui-stable/union.rs":"8bf1cf5267427674a17be834debb16cd4177c5a1103019c0b52ef24e91b6e6c7","tests/ui-stable/union.stderr":"ffed7859e5c5b838bb3a66707cbaf1c1230e3f3164be241c6650b4b2c4fa93d2","tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs":"a0168adcd0dfdc46e84421937c704b713a1307a4fc2efc19bac5dc32f6758e89","tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr":"5ab86d509f2a9ef55e47e34373c57241f528f568e0936553e71c8ddb13f490c0","tests/union_from_bytes.rs":"6cb7ecc1a18985bc65b09a48581ae2b5a5b1c4947e0ca46bf00f0dfabe49c5a1","tests/union_from_zeros.rs":"f2dfc80bf4422b8dc5164a467c31021be1d6868e0d65eafda3714345770782b5","tests/union_known_layout.rs":"9af0d34af3a443ca52b25448f4353bd45eebda67203a890a5dbf7471481f728d","tests/union_no_cell.rs":"be5040a2e878fafa34b7d153a698b31ce6c1577b4d0bfd24df2902b666805be9","tests/union_to_bytes.rs":"bef8e076a781fa5fa6ec3bab759add6f981c7c42527d0123db5780dd98b6a99d","tests/union_try_from_bytes.rs":"8fafc7c81827bd932183d04ed83a3f72ab8ac48490fe40b85cdc0c71e02e35ae","tests/union_unaligned.rs":"eb3a44fe2f3bf66acf6303765dd4c4cf65063d4bb3318d0e8160998651a7f5bf","tests/unsafe_cell.rs":"754045859595316399dc2747eda0e7560ff536f5a0e2763bb8f5c1cf7c6128ad"},"package":"88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "53013612da51c61ec3f1a059fc3b89c080ca4b56" + }, + "path_in_vcs": "zerocopy-derive" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,266 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fdaeca4cf44ed4ac623e86ef41f056e848dbeab7ec043ecb7326ba300b36fd0" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "prettyplease" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "trybuild" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f" +dependencies = [ + "basic-toml", + "dissimilar", + "glob", + "once_cell", + "serde", + "serde_derive", + "serde_json", + "termcolor", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +dependencies = [ + "dissimilar", + "libc", + "once_cell", + "prettyplease", + "proc-macro2", + "quote", + "rustversion", + "static_assertions", + "syn", + "trybuild", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,200 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "zerocopy-derive" +version = "0.8.27" +authors = [ + "Joshua Liebow-Feeser ", + "Jack Wrenn ", +] +build = false +exclude = [ + ".*", + "tests/enum_from_bytes.rs", + "tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Custom derive for traits from the zerocopy crate" +readme = false +license = "BSD-2-Clause OR Apache-2.0 OR MIT" +repository = "https://github.com/google/zerocopy" + +[lib] +name = "zerocopy_derive" +path = "src/lib.rs" +proc-macro = true + +[[test]] +name = "crate_path" +path = "tests/crate_path.rs" + +[[test]] +name = "deprecated" +path = "tests/deprecated.rs" + +[[test]] +name = "enum_from_zeros" +path = "tests/enum_from_zeros.rs" + +[[test]] +name = "enum_known_layout" +path = "tests/enum_known_layout.rs" + +[[test]] +name = "enum_no_cell" +path = "tests/enum_no_cell.rs" + +[[test]] +name = "enum_to_bytes" +path = "tests/enum_to_bytes.rs" + +[[test]] +name = "enum_try_from_bytes" +path = "tests/enum_try_from_bytes.rs" + +[[test]] +name = "enum_unaligned" +path = "tests/enum_unaligned.rs" + +[[test]] +name = "eq" +path = "tests/eq.rs" + +[[test]] +name = "hash" +path = "tests/hash.rs" + +[[test]] +name = "hygiene" +path = "tests/hygiene.rs" + +[[test]] +name = "include" +path = "tests/include.rs" + +[[test]] +name = "issue_2117" +path = "tests/issue_2117.rs" + +[[test]] +name = "paths_and_modules" +path = "tests/paths_and_modules.rs" + +[[test]] +name = "priv_in_pub" +path = "tests/priv_in_pub.rs" + +[[test]] +name = "struct_from_bytes" +path = "tests/struct_from_bytes.rs" + +[[test]] +name = "struct_from_zeros" +path = "tests/struct_from_zeros.rs" + +[[test]] +name = "struct_known_layout" +path = "tests/struct_known_layout.rs" + +[[test]] +name = "struct_no_cell" +path = "tests/struct_no_cell.rs" + +[[test]] +name = "struct_to_bytes" +path = "tests/struct_to_bytes.rs" + +[[test]] +name = "struct_try_from_bytes" +path = "tests/struct_try_from_bytes.rs" + +[[test]] +name = "struct_unaligned" +path = "tests/struct_unaligned.rs" + +[[test]] +name = "trybuild" +path = "tests/trybuild.rs" + +[[test]] +name = "union_from_bytes" +path = "tests/union_from_bytes.rs" + +[[test]] +name = "union_from_zeros" +path = "tests/union_from_zeros.rs" + +[[test]] +name = "union_known_layout" +path = "tests/union_known_layout.rs" + +[[test]] +name = "union_no_cell" +path = "tests/union_no_cell.rs" + +[[test]] +name = "union_to_bytes" +path = "tests/union_to_bytes.rs" + +[[test]] +name = "union_try_from_bytes" +path = "tests/union_try_from_bytes.rs" + +[[test]] +name = "union_unaligned" +path = "tests/union_unaligned.rs" + +[[test]] +name = "unsafe_cell" +path = "tests/unsafe_cell.rs" + +[dependencies.proc-macro2] +version = "1.0.1" + +[dependencies.quote] +version = "1.0.10" + +[dependencies.syn] +version = "2.0.46" +features = ["full"] + +[dev-dependencies.dissimilar] +version = "1.0.9" + +[dev-dependencies.libc] +version = "=0.2.163" + +[dev-dependencies.once_cell] +version = "=1.9" + +[dev-dependencies.prettyplease] +version = "=0.2.17" + +[dev-dependencies.rustversion] +version = "1.0" + +[dev-dependencies.static_assertions] +version = "1.1" + +[dev-dependencies.trybuild] +version = "=1.0.89" +features = ["diff"] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(zerocopy_derive_union_into_bytes)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +# Copyright 2019 The Fuchsia Authors +# +# Licensed under a BSD-style license , Apache License, Version 2.0 +# , or the MIT +# license , at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +[package] +edition = "2021" +name = "zerocopy-derive" +version = "0.8.27" +authors = ["Joshua Liebow-Feeser ", "Jack Wrenn "] +description = "Custom derive for traits from the zerocopy crate" +license = "BSD-2-Clause OR Apache-2.0 OR MIT" +repository = "https://github.com/google/zerocopy" + +# We prefer to include tests when publishing to crates.io so that Crater [1] can +# detect regressions in our test suite. These two tests are excessively large, +# so we exclude them to keep the published crate file small. +# +# [1] https://github.com/rust-lang/crater +exclude = [".*", "tests/enum_from_bytes.rs", "tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled"] + +[lints.rust] +# See #1792 for more context. +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zerocopy_derive_union_into_bytes)'] } + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.1" +quote = "1.0.10" +syn = { version = "2.0.46", features = ["full"] } + +[dev-dependencies] +dissimilar = "1.0.9" +# We don't use this directly, but trybuild does. On the MSRV toolchain, the +# version resolver fails to select any version for once_cell unless we +# depend on it directly. +once_cell = "=1.9" +# Same MSRV issue as above. +libc = "=0.2.163" +# This is the latest version which is compatible with `syn` 2.0.46, which we pin +# to in CI for MSRV compatibility reasons. +prettyplease = "=0.2.17" +rustversion = "1.0" +static_assertions = "1.1" +testutil = { path = "../testutil" } +# Pinned to a specific version so that the version used for local development +# and the version used in CI are guaranteed to be the same. Future versions +# sometimes change the output format slightly, so a version mismatch can cause +# CI test failures. +trybuild = { version = "=1.0.89", features = ["diff"] } +zerocopy = { path = "../", features = ["derive"] } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Fuchsia 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 + + http://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. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-BSD clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-BSD --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-BSD 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-BSD 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +Copyright 2019 The Fuchsia Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +Copyright 2023 The Fuchsia Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/enum.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,386 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{parse_quote, DataEnum, Error, Fields, Generics, Ident, Path}; + +use crate::{derive_try_from_bytes_inner, repr::EnumRepr, Trait}; + +/// Generates a tag enum for the given enum. This generates an enum with the +/// same non-align `repr`s, variants, and corresponding discriminants, but none +/// of the fields. +pub(crate) fn generate_tag_enum(repr: &EnumRepr, data: &DataEnum) -> TokenStream { + let variants = data.variants.iter().map(|v| { + let ident = &v.ident; + if let Some((eq, discriminant)) = &v.discriminant { + quote! { #ident #eq #discriminant } + } else { + quote! { #ident } + } + }); + + // Don't include any `repr(align)` when generating the tag enum, as that + // could add padding after the tag but before any variants, which is not the + // correct behavior. + let repr = match repr { + EnumRepr::Transparent(span) => quote::quote_spanned! { *span => #[repr(transparent)] }, + EnumRepr::Compound(c, _) => quote! { #c }, + }; + + quote! { + #repr + #[allow(dead_code, non_camel_case_types)] + enum ___ZerocopyTag { + #(#variants,)* + } + } +} + +fn tag_ident(variant_ident: &Ident) -> Ident { + Ident::new(&format!("___ZEROCOPY_TAG_{}", variant_ident), variant_ident.span()) +} + +/// Generates a constant for the tag associated with each variant of the enum. +/// When we match on the enum's tag, each arm matches one of these constants. We +/// have to use constants here because: +/// +/// - The type that we're matching on is not the type of the tag, it's an +/// integer of the same size as the tag type and with the same bit patterns. +/// - We can't read the enum tag as an enum because the bytes may not represent +/// a valid variant. +/// - Patterns do not currently support const expressions, so we have to assign +/// these constants to names rather than use them inline in the `match` +/// statement. +fn generate_tag_consts(data: &DataEnum) -> TokenStream { + let tags = data.variants.iter().map(|v| { + let variant_ident = &v.ident; + let tag_ident = tag_ident(variant_ident); + + quote! { + // This casts the enum variant to its discriminant, and then + // converts the discriminant to the target integral type via a + // numeric cast [1]. + // + // Because these are the same size, this is defined to be a no-op + // and therefore is a lossless conversion [2]. + // + // [1]: https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#enum-cast + // [2]: https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#numeric-cast + #[allow(non_upper_case_globals)] + const #tag_ident: ___ZerocopyTagPrimitive = + ___ZerocopyTag::#variant_ident as ___ZerocopyTagPrimitive; + } + }); + + quote! { + #(#tags)* + } +} + +fn variant_struct_ident(variant_ident: &Ident) -> Ident { + Ident::new(&format!("___ZerocopyVariantStruct_{}", variant_ident), variant_ident.span()) +} + +/// Generates variant structs for the given enum variant. +/// +/// These are structs associated with each variant of an enum. They are +/// `repr(C)` tuple structs with the same fields as the variant after a +/// `MaybeUninit<___ZerocopyInnerTag>`. +/// +/// In order to unify the generated types for `repr(C)` and `repr(int)` enums, +/// we use a "fused" representation with fields for both an inner tag and an +/// outer tag. Depending on the repr, we will set one of these tags to the tag +/// type and the other to `()`. This lets us generate the same code but put the +/// tags in different locations. +fn generate_variant_structs( + enum_name: &Ident, + generics: &Generics, + data: &DataEnum, + zerocopy_crate: &Path, +) -> TokenStream { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + // All variant structs have a `PhantomData>` field because we + // don't know which generic parameters each variant will use, and unused + // generic parameters are a compile error. + let phantom_ty = quote! { + core_reexport::marker::PhantomData<#enum_name #ty_generics> + }; + + let variant_structs = data.variants.iter().filter_map(|variant| { + // We don't generate variant structs for unit variants because we only + // need to check the tag. This helps cut down our generated code a bit. + if matches!(variant.fields, Fields::Unit) { + return None; + } + + let variant_struct_ident = variant_struct_ident(&variant.ident); + let field_types = variant.fields.iter().map(|f| &f.ty); + + let variant_struct = parse_quote! { + #[repr(C)] + #[allow(non_snake_case)] + struct #variant_struct_ident #impl_generics ( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + #(#field_types,)* + #phantom_ty, + ) #where_clause; + }; + + // We do this rather than emitting `#[derive(::zerocopy::TryFromBytes)]` + // because that is not hygienic, and this is also more performant. + let try_from_bytes_impl = + derive_try_from_bytes_inner(&variant_struct, Trait::TryFromBytes, zerocopy_crate) + .expect("derive_try_from_bytes_inner should not fail on synthesized type"); + + Some(quote! { + #variant_struct + #try_from_bytes_impl + }) + }); + + quote! { + #(#variant_structs)* + } +} + +fn generate_variants_union(generics: &Generics, data: &DataEnum) -> TokenStream { + let (_, ty_generics, _) = generics.split_for_impl(); + + let fields = data.variants.iter().filter_map(|variant| { + // We don't generate variant structs for unit variants because we only + // need to check the tag. This helps cut down our generated code a bit. + if matches!(variant.fields, Fields::Unit) { + return None; + } + + // Field names are prefixed with `__field_` to prevent name collision with + // the `__nonempty` field. + let field_name = Ident::new(&format!("__field_{}", &variant.ident), variant.ident.span()); + let variant_struct_ident = variant_struct_ident(&variant.ident); + + Some(quote! { + #field_name: core_reexport::mem::ManuallyDrop< + #variant_struct_ident #ty_generics + >, + }) + }); + + quote! { + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants #generics { + #(#fields)* + // Enums can have variants with no fields, but unions must + // have at least one field. So we just add a trailing unit + // to ensure that this union always has at least one field. + // Because this union is `repr(C)`, this unit type does not + // affect the layout. + __nonempty: (), + } + } +} + +/// Generates an implementation of `is_bit_valid` for an arbitrary enum. +/// +/// The general process is: +/// +/// 1. Generate a tag enum. This is an enum with the same repr, variants, and +/// corresponding discriminants as the original enum, but without any fields +/// on the variants. This gives us access to an enum where the variants have +/// the same discriminants as the one we're writing `is_bit_valid` for. +/// 2. Make constants from the variants of the tag enum. We need these because +/// we can't put const exprs in match arms. +/// 3. Generate variant structs. These are structs which have the same fields as +/// each variant of the enum, and are `#[repr(C)]` with an optional "inner +/// tag". +/// 4. Generate a variants union, with one field for each variant struct type. +/// 5. And finally, our raw enum is a `#[repr(C)]` struct of an "outer tag" and +/// the variants union. +/// +/// See these reference links for fully-worked example decompositions. +/// +/// - `repr(C)`: +/// - `repr(int)`: +/// - `repr(C, int)`: +pub(crate) fn derive_is_bit_valid( + enum_ident: &Ident, + repr: &EnumRepr, + generics: &Generics, + data: &DataEnum, + zerocopy_crate: &Path, +) -> Result { + let trait_path = Trait::TryFromBytes.crate_path(zerocopy_crate); + let tag_enum = generate_tag_enum(repr, data); + let tag_consts = generate_tag_consts(data); + + let (outer_tag_type, inner_tag_type) = if repr.is_c() { + (quote! { ___ZerocopyTag }, quote! { () }) + } else if repr.is_primitive() { + (quote! { () }, quote! { ___ZerocopyTag }) + } else { + return Err(Error::new( + Span::call_site(), + "must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout", + )); + }; + + let variant_structs = generate_variant_structs(enum_ident, generics, data, zerocopy_crate); + let variants_union = generate_variants_union(generics, data); + + let (_, ty_generics, _) = generics.split_for_impl(); + + let match_arms = data.variants.iter().map(|variant| { + let tag_ident = tag_ident(&variant.ident); + let variant_struct_ident = variant_struct_ident(&variant.ident); + + if matches!(variant.fields, Fields::Unit) { + // Unit variants don't need any further validation beyond checking + // the tag. + quote! { + #tag_ident => true + } + } else { + quote! { + #tag_ident => { + // SAFETY: + // - This cast is from a `repr(C)` union which has a field + // of type `variant_struct_ident` to that variant struct + // type itself. This addresses a subset of the bytes + // addressed by `variants`. + // - The returned pointer is cast from `p`, and so has the + // same provenance as `p`. + // - We checked that the tag of the enum matched the + // constant for this variant, so this cast preserves + // types and locations of all fields. Therefore, any + // `UnsafeCell`s will have the same location as in the + // original type. + let variant = unsafe { + variants.cast_unsized_unchecked( + |p: #zerocopy_crate::pointer::PtrInner<'_, ___ZerocopyVariants #ty_generics>| { + p.cast_sized::<#variant_struct_ident #ty_generics>() + } + ) + }; + // SAFETY: `cast_unsized_unchecked` removes the + // initialization invariant from `p`, so we re-assert that + // all of the bytes are initialized. + let variant = unsafe { variant.assume_initialized() }; + < + #variant_struct_ident #ty_generics as #trait_path + >::is_bit_valid(variant) + } + } + } + }); + + Ok(quote! { + // SAFETY: We use `is_bit_valid` to validate that the bit pattern of the + // enum's tag corresponds to one of the enum's discriminants. Then, we + // check the bit validity of each field of the corresponding variant. + // Thus, this is a sound implementation of `is_bit_valid`. + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: #zerocopy_crate::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> #zerocopy_crate::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: #zerocopy_crate::pointer::invariant::Reference, + { + use #zerocopy_crate::util::macro_util::core_reexport; + + #tag_enum + + type ___ZerocopyTagPrimitive = #zerocopy_crate::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + + #tag_consts + + type ___ZerocopyOuterTag = #outer_tag_type; + type ___ZerocopyInnerTag = #inner_tag_type; + + #variant_structs + + #variants_union + + #[repr(C)] + struct ___ZerocopyRawEnum #generics { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants #ty_generics, + } + + let tag = { + // SAFETY: + // - The provided cast addresses a subset of the bytes addressed + // by `candidate` because it addresses the starting tag of the + // enum. + // - Because the pointer is cast from `candidate`, it has the + // same provenance as it. + // - There are no `UnsafeCell`s in the tag because it is a + // primitive integer. + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized_unchecked(|p: #zerocopy_crate::pointer::PtrInner<'_, Self>| { + p.cast_sized::<___ZerocopyTagPrimitive>() + }) + }; + // SAFETY: `tag_ptr` is casted from `candidate`, whose referent + // is `Initialized`. Since we have not written uninitialized + // bytes into the referent, `tag_ptr` is also `Initialized`. + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.recall_validity::<_, (_, (_, _))>().read_unaligned::<#zerocopy_crate::BecauseImmutable>() + }; + + // SAFETY: + // - The raw enum has the same fields in the same locations as the + // input enum, and may have a lower alignment. This guarantees + // that it addresses a subset of the bytes addressed by + // `candidate`. + // - The returned pointer is cast from `p`, and so has the same + // provenance as `p`. + // - The raw enum has the same types at the same locations as the + // original enum, and so preserves the locations of any + // `UnsafeCell`s. + let raw_enum = unsafe { + candidate.cast_unsized_unchecked(|p: #zerocopy_crate::pointer::PtrInner<'_, Self>| { + p.cast_sized::<___ZerocopyRawEnum #ty_generics>() + }) + }; + // SAFETY: `cast_unsized_unchecked` removes the initialization + // invariant from `p`, so we re-assert that all of the bytes are + // initialized. + let raw_enum = unsafe { raw_enum.assume_initialized() }; + // SAFETY: + // - This projection returns a subfield of `this` using + // `addr_of_mut!`. + // - Because the subfield pointer is derived from `this`, it has the + // same provenance. + // - The locations of `UnsafeCell`s in the subfield match the + // locations of `UnsafeCell`s in `this`. This is because the + // subfield pointer just points to a smaller portion of the + // overall struct. + let variants = unsafe { + use #zerocopy_crate::pointer::PtrInner; + raw_enum.cast_unsized_unchecked(|p: PtrInner<'_, ___ZerocopyRawEnum #ty_generics>| { + let p = p.as_non_null().as_ptr(); + let ptr = core_reexport::ptr::addr_of_mut!((*p).variants); + // SAFETY: `ptr` is a projection into `p`, which is + // `NonNull`, and guaranteed not to wrap around the address + // space. Thus, `ptr` cannot be null. + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(ptr) }; + unsafe { PtrInner::new(ptr) } + }) + }; + + #[allow(non_upper_case_globals)] + match tag { + #(#match_arms,)* + _ => false, + } + } + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/ext.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/ext.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/ext.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/ext.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,114 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; +use syn::{Data, DataEnum, DataStruct, DataUnion, Field, Ident, Index, Type, Visibility}; + +pub(crate) trait DataExt { + /// Extracts the names and types of all fields. For enums, extracts the + /// names and types of fields from each variant. For tuple structs, the + /// names are the indices used to index into the struct (ie, `0`, `1`, etc). + /// + /// FIXME: Extracting field names for enums doesn't really make sense. Types + /// makes sense because we don't care about where they live - we just care + /// about transitive ownership. But for field names, we'd only use them when + /// generating is_bit_valid, which cares about where they live. + fn fields(&self) -> Vec<(&Visibility, TokenStream, &Type)>; + + fn variants(&self) -> Vec>; + + fn tag(&self) -> Option; +} + +impl DataExt for Data { + fn fields(&self) -> Vec<(&Visibility, TokenStream, &Type)> { + match self { + Data::Struct(strc) => strc.fields(), + Data::Enum(enm) => enm.fields(), + Data::Union(un) => un.fields(), + } + } + + fn variants(&self) -> Vec> { + match self { + Data::Struct(strc) => strc.variants(), + Data::Enum(enm) => enm.variants(), + Data::Union(un) => un.variants(), + } + } + + fn tag(&self) -> Option { + match self { + Data::Struct(strc) => strc.tag(), + Data::Enum(enm) => enm.tag(), + Data::Union(un) => un.tag(), + } + } +} + +impl DataExt for DataStruct { + fn fields(&self) -> Vec<(&Visibility, TokenStream, &Type)> { + map_fields(&self.fields) + } + + fn variants(&self) -> Vec> { + vec![self.fields()] + } + + fn tag(&self) -> Option { + None + } +} + +impl DataExt for DataEnum { + fn fields(&self) -> Vec<(&Visibility, TokenStream, &Type)> { + map_fields(self.variants.iter().flat_map(|var| &var.fields)) + } + + fn variants(&self) -> Vec> { + self.variants.iter().map(|var| map_fields(&var.fields)).collect() + } + + fn tag(&self) -> Option { + Some(Ident::new("___ZerocopyTag", Span::call_site())) + } +} + +impl DataExt for DataUnion { + fn fields(&self) -> Vec<(&Visibility, TokenStream, &Type)> { + map_fields(&self.fields.named) + } + + fn variants(&self) -> Vec> { + vec![self.fields()] + } + + fn tag(&self) -> Option { + None + } +} + +fn map_fields<'a>( + fields: impl 'a + IntoIterator, +) -> Vec<(&'a Visibility, TokenStream, &'a Type)> { + fields + .into_iter() + .enumerate() + .map(|(idx, f)| { + ( + &f.vis, + f.ident + .as_ref() + .map(ToTokens::to_token_stream) + .unwrap_or_else(|| Index::from(idx).to_token_stream()), + &f.ty, + ) + }) + .collect() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1883 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Derive macros for [zerocopy]'s traits. +//! +//! [zerocopy]: https://docs.rs/zerocopy + +// Sometimes we want to use lints which were added after our MSRV. +// `unknown_lints` is `warn` by default and we deny warnings in CI, so without +// this attribute, any unknown lint would cause a CI failure when testing with +// our MSRV. +#![allow(unknown_lints)] +#![deny(renamed_and_removed_lints)] +#![deny(clippy::all, clippy::missing_safety_doc, clippy::undocumented_unsafe_blocks)] +// Inlining format args isn't supported on our MSRV. +#![allow(clippy::uninlined_format_args)] +#![deny( + rustdoc::bare_urls, + rustdoc::broken_intra_doc_links, + rustdoc::invalid_codeblock_attributes, + rustdoc::invalid_html_tags, + rustdoc::invalid_rust_codeblocks, + rustdoc::missing_crate_level_docs, + rustdoc::private_intra_doc_links +)] +#![recursion_limit = "128"] + +mod r#enum; +mod ext; +#[cfg(test)] +mod output_tests; +mod repr; + +use proc_macro2::{Span, TokenStream, TokenTree}; +use quote::{quote, ToTokens}; +use syn::{ + parse_quote, Attribute, Data, DataEnum, DataStruct, DataUnion, DeriveInput, Error, Expr, + ExprLit, ExprUnary, GenericParam, Ident, Lit, Meta, Path, Type, UnOp, WherePredicate, +}; + +use crate::{ext::*, repr::*}; + +// FIXME(https://github.com/rust-lang/rust/issues/54140): Some errors could be +// made better if we could add multiple lines of error output like this: +// +// error: unsupported representation +// --> enum.rs:28:8 +// | +// 28 | #[repr(transparent)] +// | +// help: required by the derive of FromBytes +// +// Instead, we have more verbose error messages like "unsupported representation +// for deriving FromZeros, FromBytes, IntoBytes, or Unaligned on an enum" +// +// This will probably require Span::error +// (https://doc.rust-lang.org/nightly/proc_macro/struct.Span.html#method.error), +// which is currently unstable. Revisit this once it's stable. + +/// Defines a derive function named `$outer` which parses its input +/// `TokenStream` as a `DeriveInput` and then invokes the `$inner` function. +/// +/// Note that the separate `$outer` parameter is required - proc macro functions +/// are currently required to live at the crate root, and so the caller must +/// specify the name in order to avoid name collisions. +macro_rules! derive { + ($trait:ident => $outer:ident => $inner:ident) => { + #[proc_macro_derive($trait, attributes(zerocopy))] + pub fn $outer(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ast = syn::parse_macro_input!(ts as DeriveInput); + let zerocopy_crate = match extract_zerocopy_crate(&ast.attrs) { + Ok(zerocopy_crate) => zerocopy_crate, + Err(e) => return e.into_compile_error().into(), + }; + $inner(&ast, Trait::$trait, &zerocopy_crate).into_ts().into() + } + }; +} + +trait IntoTokenStream { + fn into_ts(self) -> TokenStream; +} + +impl IntoTokenStream for TokenStream { + fn into_ts(self) -> TokenStream { + self + } +} + +impl IntoTokenStream for Result { + fn into_ts(self) -> TokenStream { + match self { + Ok(ts) => ts, + Err(err) => err.to_compile_error(), + } + } +} + +/// Attempt to extract a crate path from the provided attributes. Defaults to `::zerocopy` if not +/// found. +fn extract_zerocopy_crate(attrs: &[Attribute]) -> Result { + let mut path = parse_quote!(::zerocopy); + + for attr in attrs { + if let Meta::List(ref meta_list) = attr.meta { + if meta_list.path.is_ident("zerocopy") { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("crate") { + let expr = meta.value().and_then(|value| value.parse()); + if let Ok(Expr::Lit(ExprLit { lit: Lit::Str(lit), .. })) = expr { + if let Ok(path_lit) = lit.parse() { + path = path_lit; + return Ok(()); + } + } + + return Err(Error::new( + Span::call_site(), + "`crate` attribute requires a path as the value", + )); + } + + Err(Error::new( + Span::call_site(), + format!("unknown attribute encountered: {}", meta.path.into_token_stream()), + )) + })?; + } + } + } + + Ok(path) +} + +derive!(KnownLayout => derive_known_layout => derive_known_layout_inner); +derive!(Immutable => derive_no_cell => derive_no_cell_inner); +derive!(TryFromBytes => derive_try_from_bytes => derive_try_from_bytes_inner); +derive!(FromZeros => derive_from_zeros => derive_from_zeros_inner); +derive!(FromBytes => derive_from_bytes => derive_from_bytes_inner); +derive!(IntoBytes => derive_into_bytes => derive_into_bytes_inner); +derive!(Unaligned => derive_unaligned => derive_unaligned_inner); +derive!(ByteHash => derive_hash => derive_hash_inner); +derive!(ByteEq => derive_eq => derive_eq_inner); +derive!(SplitAt => derive_split_at => derive_split_at_inner); + +/// Deprecated: prefer [`FromZeros`] instead. +#[deprecated(since = "0.8.0", note = "`FromZeroes` was renamed to `FromZeros`")] +#[doc(hidden)] +#[proc_macro_derive(FromZeroes)] +pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_from_zeros(ts) +} + +/// Deprecated: prefer [`IntoBytes`] instead. +#[deprecated(since = "0.8.0", note = "`AsBytes` was renamed to `IntoBytes`")] +#[doc(hidden)] +#[proc_macro_derive(AsBytes)] +pub fn derive_as_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_into_bytes(ts) +} + +fn derive_known_layout_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let is_repr_c_struct = match &ast.data { + Data::Struct(..) => { + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + if repr.is_c() { + Some(repr) + } else { + None + } + } + Data::Enum(..) | Data::Union(..) => None, + }; + + let fields = ast.data.fields(); + + let (self_bounds, inner_extras, outer_extras) = if let ( + Some(repr), + Some((trailing_field, leading_fields)), + ) = (is_repr_c_struct, fields.split_last()) + { + let (_vis, trailing_field_name, trailing_field_ty) = trailing_field; + let leading_fields_tys = leading_fields.iter().map(|(_vis, _name, ty)| ty); + + let core_path = quote!(#zerocopy_crate::util::macro_util::core_reexport); + let repr_align = repr + .get_align() + .map(|align| { + let align = align.t.get(); + quote!(#core_path::num::NonZeroUsize::new(#align as usize)) + }) + .unwrap_or_else(|| quote!(#core_path::option::Option::None)); + let repr_packed = repr + .get_packed() + .map(|packed| { + let packed = packed.get(); + quote!(#core_path::num::NonZeroUsize::new(#packed as usize)) + }) + .unwrap_or_else(|| quote!(#core_path::option::Option::None)); + + let make_methods = |trailing_field_ty| { + quote! { + // SAFETY: + // - The returned pointer has the same address and provenance as + // `bytes`: + // - The recursive call to `raw_from_ptr_len` preserves both + // address and provenance. + // - The `as` cast preserves both address and provenance. + // - `NonNull::new_unchecked` preserves both address and + // provenance. + // - If `Self` is a slice DST, the returned pointer encodes + // `elems` elements in the trailing slice: + // - This is true of the recursive call to `raw_from_ptr_len`. + // - `trailing.as_ptr() as *mut Self` preserves trailing slice + // element count [1]. + // - `NonNull::new_unchecked` preserves trailing slice element + // count. + // + // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast: + // + // `*const T`` / `*mut T` can be cast to `*const U` / `*mut U` + // with the following behavior: + // ... + // - If `T` and `U` are both unsized, the pointer is also + // returned unchanged. In particular, the metadata is + // preserved exactly. + // + // For instance, a cast from `*const [T]` to `*const [U]` + // preserves the number of elements. ... The same holds + // for str and any compound type whose unsized tail is a + // slice type, such as struct `Foo(i32, [u8])` or `(u64, Foo)`. + #[inline(always)] + fn raw_from_ptr_len( + bytes: #zerocopy_crate::util::macro_util::core_reexport::ptr::NonNull, + meta: Self::PointerMetadata, + ) -> #zerocopy_crate::util::macro_util::core_reexport::ptr::NonNull { + use #zerocopy_crate::KnownLayout; + let trailing = <#trailing_field_ty as KnownLayout>::raw_from_ptr_len(bytes, meta); + let slf = trailing.as_ptr() as *mut Self; + // SAFETY: Constructed from `trailing`, which is non-null. + unsafe { #zerocopy_crate::util::macro_util::core_reexport::ptr::NonNull::new_unchecked(slf) } + } + + #[inline(always)] + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata { + <#trailing_field_ty>::pointer_to_metadata(ptr as *mut _) + } + } + }; + + let inner_extras = { + let leading_fields_tys = leading_fields_tys.clone(); + let methods = make_methods(*trailing_field_ty); + let (_, ty_generics, _) = ast.generics.split_for_impl(); + + quote!( + type PointerMetadata = <#trailing_field_ty as #zerocopy_crate::KnownLayout>::PointerMetadata; + + type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit #ty_generics; + + // SAFETY: `LAYOUT` accurately describes the layout of `Self`. + // The documentation of `DstLayout::for_repr_c_struct` vows that + // invocations in this manner will accurately describe a type, + // so long as: + // + // - that type is `repr(C)`, + // - its fields are enumerated in the order they appear, + // - the presence of `repr_align` and `repr_packed` are + // correctly accounted for. + // + // We respect all three of these preconditions here. This + // expansion is only used if `is_repr_c_struct`, we enumerate + // the fields in order, and we extract the values of `align(N)` + // and `packed(N)`. + const LAYOUT: #zerocopy_crate::DstLayout = { + use #zerocopy_crate::util::macro_util::core_reexport::num::NonZeroUsize; + use #zerocopy_crate::{DstLayout, KnownLayout}; + + DstLayout::for_repr_c_struct( + #repr_align, + #repr_packed, + &[ + #(DstLayout::for_type::<#leading_fields_tys>(),)* + <#trailing_field_ty as KnownLayout>::LAYOUT + ], + ) + }; + + #methods + ) + }; + + let outer_extras = { + let ident = &ast.ident; + let vis = &ast.vis; + let params = &ast.generics.params; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + + let predicates = if let Some(where_clause) = where_clause { + where_clause.predicates.clone() + } else { + Default::default() + }; + + // Generate a valid ident for a type-level handle to a field of a + // given `name`. + let field_index = + |name| Ident::new(&format!("__Zerocopy_Field_{}", name), ident.span()); + + let field_indices: Vec<_> = + fields.iter().map(|(_vis, name, _ty)| field_index(name)).collect(); + + // Define the collection of type-level field handles. + let field_defs = field_indices.iter().zip(&fields).map(|(idx, (vis, _, _))| { + quote! { + #[allow(non_camel_case_types)] + #vis struct #idx; + } + }); + + let field_impls = field_indices.iter().zip(&fields).map(|(idx, (_, _, ty))| quote! { + // SAFETY: `#ty` is the type of `#ident`'s field at `#idx`. + unsafe impl #impl_generics #zerocopy_crate::util::macro_util::Field<#idx> for #ident #ty_generics + where + #predicates + { + type Type = #ty; + } + }); + + let trailing_field_index = field_index(trailing_field_name); + let leading_field_indices = + leading_fields.iter().map(|(_vis, name, _ty)| field_index(name)); + + let trailing_field_ty = quote! { + <#ident #ty_generics as + #zerocopy_crate::util::macro_util::Field<#trailing_field_index> + >::Type + }; + + let methods = make_methods(&parse_quote! { + <#trailing_field_ty as #zerocopy_crate::KnownLayout>::MaybeUninit + }); + + quote! { + #(#field_defs)* + + #(#field_impls)* + + // SAFETY: This has the same layout as the derive target type, + // except that it admits uninit bytes. This is ensured by using + // the same repr as the target type, and by using field types + // which have the same layout as the target type's fields, + // except that they admit uninit bytes. We indirect through + // `Field` to ensure that occurrences of `Self` resolve to + // `#ty`, not `__ZerocopyKnownLayoutMaybeUninit` (see #2116). + #repr + #[doc(hidden)] + // Required on some rustc versions due to a lint that is only + // triggered when `derive(KnownLayout)` is applied to `repr(C)` + // structs that are generated by macros. See #2177 for details. + #[allow(private_bounds)] + #vis struct __ZerocopyKnownLayoutMaybeUninit<#params> ( + #(#zerocopy_crate::util::macro_util::core_reexport::mem::MaybeUninit< + <#ident #ty_generics as + #zerocopy_crate::util::macro_util::Field<#leading_field_indices> + >::Type + >,)* + // NOTE(#2302): We wrap in `ManuallyDrop` here in case the + // type we're operating on is both generic and + // `repr(packed)`. In that case, Rust needs to know that the + // type is *either* `Sized` or has a trivial `Drop`. + // `ManuallyDrop` has a trivial `Drop`, and so satisfies + // this requirement. + #zerocopy_crate::util::macro_util::core_reexport::mem::ManuallyDrop< + <#trailing_field_ty as #zerocopy_crate::KnownLayout>::MaybeUninit + > + ) + where + #trailing_field_ty: #zerocopy_crate::KnownLayout, + #predicates; + + // SAFETY: We largely defer to the `KnownLayout` implementation on + // the derive target type (both by using the same tokens, and by + // deferring to impl via type-level indirection). This is sound, + // since `__ZerocopyKnownLayoutMaybeUninit` is guaranteed to + // have the same layout as the derive target type, except that + // `__ZerocopyKnownLayoutMaybeUninit` admits uninit bytes. + unsafe impl #impl_generics #zerocopy_crate::KnownLayout for __ZerocopyKnownLayoutMaybeUninit #ty_generics + where + #trailing_field_ty: #zerocopy_crate::KnownLayout, + #predicates + { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + + type PointerMetadata = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::PointerMetadata; + + type MaybeUninit = Self; + + const LAYOUT: #zerocopy_crate::DstLayout = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::LAYOUT; + + #methods + } + } + }; + + (SelfBounds::None, inner_extras, Some(outer_extras)) + } else { + // For enums, unions, and non-`repr(C)` structs, we require that + // `Self` is sized, and as a result don't need to reason about the + // internals of the type. + ( + SelfBounds::SIZED, + quote!( + type PointerMetadata = (); + type MaybeUninit = + #zerocopy_crate::util::macro_util::core_reexport::mem::MaybeUninit; + + // SAFETY: `LAYOUT` is guaranteed to accurately describe the + // layout of `Self`, because that is the documented safety + // contract of `DstLayout::for_type`. + const LAYOUT: #zerocopy_crate::DstLayout = #zerocopy_crate::DstLayout::for_type::(); + + // SAFETY: `.cast` preserves address and provenance. + // + // FIXME(#429): Add documentation to `.cast` that promises that + // it preserves provenance. + #[inline(always)] + fn raw_from_ptr_len( + bytes: #zerocopy_crate::util::macro_util::core_reexport::ptr::NonNull, + _meta: (), + ) -> #zerocopy_crate::util::macro_util::core_reexport::ptr::NonNull + { + bytes.cast::() + } + + #[inline(always)] + fn pointer_to_metadata(_ptr: *mut Self) -> () {} + ), + None, + ) + }; + + Ok(match &ast.data { + Data::Struct(strct) => { + let require_trait_bound_on_field_types = if self_bounds == SelfBounds::SIZED { + FieldBounds::None + } else { + FieldBounds::TRAILING_SELF + }; + + // A bound on the trailing field is required, since structs are + // unsized if their trailing field is unsized. Reflecting the layout + // of an usized trailing field requires that the field is + // `KnownLayout`. + ImplBlockBuilder::new( + ast, + strct, + Trait::KnownLayout, + require_trait_bound_on_field_types, + zerocopy_crate, + ) + .self_type_trait_bounds(self_bounds) + .inner_extras(inner_extras) + .outer_extras(outer_extras) + .build() + } + Data::Enum(enm) => { + // A bound on the trailing field is not required, since enums cannot + // currently be unsized. + ImplBlockBuilder::new(ast, enm, Trait::KnownLayout, FieldBounds::None, zerocopy_crate) + .self_type_trait_bounds(SelfBounds::SIZED) + .inner_extras(inner_extras) + .outer_extras(outer_extras) + .build() + } + Data::Union(unn) => { + // A bound on the trailing field is not required, since unions + // cannot currently be unsized. + ImplBlockBuilder::new(ast, unn, Trait::KnownLayout, FieldBounds::None, zerocopy_crate) + .self_type_trait_bounds(SelfBounds::SIZED) + .inner_extras(inner_extras) + .outer_extras(outer_extras) + .build() + } + }) +} + +fn derive_no_cell_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> TokenStream { + match &ast.data { + Data::Struct(strct) => ImplBlockBuilder::new( + ast, + strct, + Trait::Immutable, + FieldBounds::ALL_SELF, + zerocopy_crate, + ) + .build(), + Data::Enum(enm) => { + ImplBlockBuilder::new(ast, enm, Trait::Immutable, FieldBounds::ALL_SELF, zerocopy_crate) + .build() + } + Data::Union(unn) => { + ImplBlockBuilder::new(ast, unn, Trait::Immutable, FieldBounds::ALL_SELF, zerocopy_crate) + .build() + } + } +} + +fn derive_try_from_bytes_inner( + ast: &DeriveInput, + top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + match &ast.data { + Data::Struct(strct) => derive_try_from_bytes_struct(ast, strct, top_level, zerocopy_crate), + Data::Enum(enm) => derive_try_from_bytes_enum(ast, enm, top_level, zerocopy_crate), + Data::Union(unn) => Ok(derive_try_from_bytes_union(ast, unn, top_level, zerocopy_crate)), + } +} + +fn derive_from_zeros_inner( + ast: &DeriveInput, + top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let try_from_bytes = derive_try_from_bytes_inner(ast, top_level, zerocopy_crate)?; + let from_zeros = match &ast.data { + Data::Struct(strct) => derive_from_zeros_struct(ast, strct, zerocopy_crate), + Data::Enum(enm) => derive_from_zeros_enum(ast, enm, zerocopy_crate)?, + Data::Union(unn) => derive_from_zeros_union(ast, unn, zerocopy_crate), + }; + Ok(IntoIterator::into_iter([try_from_bytes, from_zeros]).collect()) +} + +fn derive_from_bytes_inner( + ast: &DeriveInput, + top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let from_zeros = derive_from_zeros_inner(ast, top_level, zerocopy_crate)?; + let from_bytes = match &ast.data { + Data::Struct(strct) => derive_from_bytes_struct(ast, strct, zerocopy_crate), + Data::Enum(enm) => derive_from_bytes_enum(ast, enm, zerocopy_crate)?, + Data::Union(unn) => derive_from_bytes_union(ast, unn, zerocopy_crate), + }; + + Ok(IntoIterator::into_iter([from_zeros, from_bytes]).collect()) +} + +fn derive_into_bytes_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + match &ast.data { + Data::Struct(strct) => derive_into_bytes_struct(ast, strct, zerocopy_crate), + Data::Enum(enm) => derive_into_bytes_enum(ast, enm, zerocopy_crate), + Data::Union(unn) => derive_into_bytes_union(ast, unn, zerocopy_crate), + } +} + +fn derive_unaligned_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + match &ast.data { + Data::Struct(strct) => derive_unaligned_struct(ast, strct, zerocopy_crate), + Data::Enum(enm) => derive_unaligned_enum(ast, enm, zerocopy_crate), + Data::Union(unn) => derive_unaligned_union(ast, unn, zerocopy_crate), + } +} + +fn derive_hash_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + // This doesn't delegate to `impl_block` because `impl_block` assumes it is deriving a + // `zerocopy`-defined trait, and these trait impls share a common shape that `Hash` does not. + // In particular, `zerocopy` traits contain a method that only `zerocopy_derive` macros + // are supposed to implement, and `impl_block` generating this trait method is incompatible + // with `Hash`. + let type_ident = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let where_predicates = where_clause.map(|clause| &clause.predicates); + Ok(quote! { + // FIXME(#553): Add a test that generates a warning when + // `#[allow(deprecated)]` isn't present. + #[allow(deprecated)] + // While there are not currently any warnings that this suppresses (that + // we're aware of), it's good future-proofing hygiene. + #[automatically_derived] + impl #impl_generics #zerocopy_crate::util::macro_util::core_reexport::hash::Hash for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + fn hash(&self, state: &mut H) + where + H: #zerocopy_crate::util::macro_util::core_reexport::hash::Hasher, + { + #zerocopy_crate::util::macro_util::core_reexport::hash::Hasher::write( + state, + #zerocopy_crate::IntoBytes::as_bytes(self) + ) + } + + fn hash_slice(data: &[Self], state: &mut H) + where + H: #zerocopy_crate::util::macro_util::core_reexport::hash::Hasher, + { + #zerocopy_crate::util::macro_util::core_reexport::hash::Hasher::write( + state, + #zerocopy_crate::IntoBytes::as_bytes(data) + ) + } + } + }) +} + +fn derive_eq_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + // This doesn't delegate to `impl_block` because `impl_block` assumes it is deriving a + // `zerocopy`-defined trait, and these trait impls share a common shape that `Eq` does not. + // In particular, `zerocopy` traits contain a method that only `zerocopy_derive` macros + // are supposed to implement, and `impl_block` generating this trait method is incompatible + // with `Eq`. + let type_ident = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let where_predicates = where_clause.map(|clause| &clause.predicates); + Ok(quote! { + // FIXME(#553): Add a test that generates a warning when + // `#[allow(deprecated)]` isn't present. + #[allow(deprecated)] + // While there are not currently any warnings that this suppresses (that + // we're aware of), it's good future-proofing hygiene. + #[automatically_derived] + impl #impl_generics #zerocopy_crate::util::macro_util::core_reexport::cmp::PartialEq for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + fn eq(&self, other: &Self) -> bool { + #zerocopy_crate::util::macro_util::core_reexport::cmp::PartialEq::eq( + #zerocopy_crate::IntoBytes::as_bytes(self), + #zerocopy_crate::IntoBytes::as_bytes(other), + ) + } + } + + // FIXME(#553): Add a test that generates a warning when + // `#[allow(deprecated)]` isn't present. + #[allow(deprecated)] + // While there are not currently any warnings that this suppresses (that + // we're aware of), it's good future-proofing hygiene. + #[automatically_derived] + impl #impl_generics #zerocopy_crate::util::macro_util::core_reexport::cmp::Eq for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + } + }) +} + +fn derive_split_at_inner( + ast: &DeriveInput, + _top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + + match &ast.data { + Data::Struct(_) => {} + Data::Enum(_) | Data::Union(_) => { + return Err(Error::new(Span::call_site(), "can only be applied to structs")); + } + }; + + if repr.get_packed().is_some() { + return Err(Error::new(Span::call_site(), "must not have #[repr(packed)] attribute")); + } + + if !(repr.is_c() || repr.is_transparent()) { + return Err(Error::new(Span::call_site(), "must have #[repr(C)] or #[repr(transparent)] in order to guarantee this type's layout is splitable")); + } + + let fields = ast.data.fields(); + let trailing_field = if let Some(((_, _, trailing_field), _)) = fields.split_last() { + trailing_field + } else { + return Err(Error::new(Span::call_site(), "must at least one field")); + }; + + // SAFETY: `#ty`, per the above checks, is `repr(C)` or `repr(transparent)` + // and is not packed; its trailing field is guaranteed to be well-aligned + // for its type. By invariant on `FieldBounds::TRAILING_SELF`, the trailing + // slice of the trailing field is also well-aligned for its type. + Ok(ImplBlockBuilder::new( + ast, + &ast.data, + Trait::SplitAt, + FieldBounds::TRAILING_SELF, + zerocopy_crate, + ) + .inner_extras(quote! { + type Elem = <#trailing_field as ::zerocopy::SplitAt>::Elem; + }) + .build()) +} + +/// A struct is `TryFromBytes` if: +/// - all fields are `TryFromBytes` +fn derive_try_from_bytes_struct( + ast: &DeriveInput, + strct: &DataStruct, + top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let extras = + try_gen_trivial_is_bit_valid(ast, top_level, zerocopy_crate).unwrap_or_else(|| { + let fields = strct.fields(); + let field_names = fields.iter().map(|(_vis, name, _ty)| name); + let field_tys = fields.iter().map(|(_vis, _name, ty)| ty); + quote!( + // SAFETY: We use `is_bit_valid` to validate that each field is + // bit-valid, and only return `true` if all of them are. The bit + // validity of a struct is just the composition of the bit + // validities of its fields, so this is a sound implementation of + // `is_bit_valid`. + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: #zerocopy_crate::Maybe, + ) -> #zerocopy_crate::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: #zerocopy_crate::pointer::invariant::Reference, + { + use #zerocopy_crate::util::macro_util::core_reexport; + use #zerocopy_crate::pointer::PtrInner; + + true #(&& { + // SAFETY: + // - `project` is a field projection, and so it addresses a + // subset of the bytes addressed by `slf` + // - ..., and so it preserves provenance + // - ..., and `*slf` is a struct, so `UnsafeCell`s exist at + // the same byte ranges in the returned pointer's referent + // as they do in `*slf` + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).#field_names); + // SAFETY: `cast_unsized_unchecked` promises that + // `slf` will either reference a zero-sized byte + // range, or else will reference a byte range that + // is entirely contained within an allocated + // object. In either case, this guarantees that + // field projection will not wrap around the address + // space, and so `field` will be non-null. + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + // SAFETY: + // 0. `ptr` addresses a subset of the bytes of + // `slf`, so by invariant on `slf: PtrInner`, + // if `ptr`'s referent is not zero sized, + // then `ptr` has valid provenance for its + // referent, which is entirely contained in + // some Rust allocation, `A`. + // 1. By invariant on `slf: PtrInner`, if + // `ptr`'s referent is not zero sized, `A` is + // guaranteed to live for at least `'a`. + unsafe { PtrInner::new(ptr) } + }; + + candidate.reborrow().cast_unsized_unchecked(project) + }; + + <#field_tys as #zerocopy_crate::TryFromBytes>::is_bit_valid(field_candidate) + })* + } + ) + }); + Ok(ImplBlockBuilder::new( + ast, + strct, + Trait::TryFromBytes, + FieldBounds::ALL_SELF, + zerocopy_crate, + ) + .inner_extras(extras) + .build()) +} + +/// A union is `TryFromBytes` if: +/// - all of its fields are `TryFromBytes` and `Immutable` +fn derive_try_from_bytes_union( + ast: &DeriveInput, + unn: &DataUnion, + top_level: Trait, + zerocopy_crate: &Path, +) -> TokenStream { + // FIXME(#5): Remove the `Immutable` bound. + let field_type_trait_bounds = + FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); + let extras = + try_gen_trivial_is_bit_valid(ast, top_level, zerocopy_crate).unwrap_or_else(|| { + let fields = unn.fields(); + let field_names = fields.iter().map(|(_vis, name, _ty)| name); + let field_tys = fields.iter().map(|(_vis, _name, ty)| ty); + quote!( + // SAFETY: We use `is_bit_valid` to validate that any field is + // bit-valid; we only return `true` if at least one of them is. The + // bit validity of a union is not yet well defined in Rust, but it + // is guaranteed to be no more strict than this definition. See #696 + // for a more in-depth discussion. + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: #zerocopy_crate::Maybe<'_, Self,___ZerocopyAliasing> + ) -> #zerocopy_crate::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: #zerocopy_crate::pointer::invariant::Reference, + { + use #zerocopy_crate::util::macro_util::core_reexport; + use #zerocopy_crate::pointer::PtrInner; + + false #(|| { + // SAFETY: + // - `project` is a field projection, and so it addresses a + // subset of the bytes addressed by `slf` + // - ..., and so it preserves provenance + // - Since `Self: Immutable` is enforced by + // `self_type_trait_bounds`, neither `*slf` nor the + // returned pointer's referent contain any `UnsafeCell`s + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).#field_names); + // SAFETY: `cast_unsized_unchecked` promises that + // `slf` will either reference a zero-sized byte + // range, or else will reference a byte range that + // is entirely contained within an allocated + // object. In either case, this guarantees that + // field projection will not wrap around the address + // space, and so `field` will be non-null. + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + // SAFETY: + // 0. `ptr` addresses a subset of the bytes of + // `slf`, so by invariant on `slf: PtrInner`, + // if `ptr`'s referent is not zero sized, + // then `ptr` has valid provenance for its + // referent, which is entirely contained in + // some Rust allocation, `A`. + // 1. By invariant on `slf: PtrInner`, if + // `ptr`'s referent is not zero sized, `A` is + // guaranteed to live for at least `'a`. + unsafe { PtrInner::new(ptr) } + }; + + candidate.reborrow().cast_unsized_unchecked(project) + }; + + <#field_tys as #zerocopy_crate::TryFromBytes>::is_bit_valid(field_candidate) + })* + } + ) + }); + ImplBlockBuilder::new(ast, unn, Trait::TryFromBytes, field_type_trait_bounds, zerocopy_crate) + .inner_extras(extras) + .build() +} + +fn derive_try_from_bytes_enum( + ast: &DeriveInput, + enm: &DataEnum, + top_level: Trait, + zerocopy_crate: &Path, +) -> Result { + let repr = EnumRepr::from_attrs(&ast.attrs)?; + + // If an enum has no fields, it has a well-defined integer representation, + // and every possible bit pattern corresponds to a valid discriminant tag, + // then it *could* be `FromBytes` (even if the user hasn't derived + // `FromBytes`). This holds if, for `repr(uN)` or `repr(iN)`, there are 2^N + // variants. + let could_be_from_bytes = enum_size_from_repr(&repr) + .map(|size| enm.fields().is_empty() && enm.variants.len() == 1usize << size) + .unwrap_or(false); + + let trivial_is_bit_valid = try_gen_trivial_is_bit_valid(ast, top_level, zerocopy_crate); + let extra = match (trivial_is_bit_valid, could_be_from_bytes) { + (Some(is_bit_valid), _) => is_bit_valid, + // SAFETY: It would be sound for the enum to implement `FromBytes`, as + // required by `gen_trivial_is_bit_valid_unchecked`. + (None, true) => unsafe { gen_trivial_is_bit_valid_unchecked(zerocopy_crate) }, + (None, false) => { + r#enum::derive_is_bit_valid(&ast.ident, &repr, &ast.generics, enm, zerocopy_crate)? + } + }; + + Ok(ImplBlockBuilder::new(ast, enm, Trait::TryFromBytes, FieldBounds::ALL_SELF, zerocopy_crate) + .inner_extras(extra) + .build()) +} + +/// Attempts to generate a `TryFromBytes::is_bit_valid` instance that +/// unconditionally returns true. +/// +/// This is possible when the `top_level` trait is `FromBytes` and there are no +/// generic type parameters. In this case, we know that compilation will succeed +/// only if the type is unconditionally `FromBytes`. Type parameters are not +/// supported because a type with type parameters could be `TryFromBytes` but +/// not `FromBytes` depending on its type parameters, and so deriving a trivial +/// `is_bit_valid` would be either unsound or, assuming we add a defensive +/// `Self: FromBytes` bound (as we currently do), overly restrictive. Consider, +/// for example, that `Foo` ought to be `TryFromBytes` but not `FromBytes` +/// in this example: +/// +/// ```rust,ignore +/// #[derive(FromBytes)] +/// #[repr(transparent)] +/// struct Foo(T); +/// ``` +/// +/// This should be used where possible. Using this impl is faster to codegen, +/// faster to compile, and is friendlier on the optimizer. +fn try_gen_trivial_is_bit_valid( + ast: &DeriveInput, + top_level: Trait, + zerocopy_crate: &Path, +) -> Option { + // If the top-level trait is `FromBytes` and `Self` has no type parameters, + // then the `FromBytes` derive will fail compilation if `Self` is not + // actually soundly `FromBytes`, and so we can rely on that for our + // `is_bit_valid` impl. It's plausible that we could make changes - or Rust + // could make changes (such as the "trivial bounds" language feature) - that + // make this no longer true. To hedge against these, we include an explicit + // `Self: FromBytes` check in the generated `is_bit_valid`, which is + // bulletproof. + if top_level == Trait::FromBytes && ast.generics.params.is_empty() { + Some(quote!( + // SAFETY: See inline. + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: #zerocopy_crate::Maybe, + ) -> #zerocopy_crate::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: #zerocopy_crate::pointer::invariant::Reference, + { + if false { + fn assert_is_from_bytes() + where + T: #zerocopy_crate::FromBytes, + T: ?#zerocopy_crate::util::macro_util::core_reexport::marker::Sized, + { + } + + assert_is_from_bytes::(); + } + + // SAFETY: The preceding code only compiles if `Self: + // FromBytes`. Thus, this code only compiles if all initialized + // byte sequences represent valid instances of `Self`. + true + } + )) + } else { + None + } +} + +/// Generates a `TryFromBytes::is_bit_valid` instance that unconditionally +/// returns true. +/// +/// This should be used where possible, (although `try_gen_trivial_is_bit_valid` +/// should be preferred over this for safety reasons). Using this impl is faster +/// to codegen, faster to compile, and is friendlier on the optimizer. +/// +/// # Safety +/// +/// The caller must ensure that all initialized bit patterns are valid for +/// `Self`. +unsafe fn gen_trivial_is_bit_valid_unchecked(zerocopy_crate: &Path) -> proc_macro2::TokenStream { + quote!( + // SAFETY: The caller of `gen_trivial_is_bit_valid_unchecked` has + // promised that all initialized bit patterns are valid for `Self`. + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: #zerocopy_crate::Maybe, + ) -> #zerocopy_crate::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: #zerocopy_crate::pointer::invariant::Reference, + { + true + } + ) +} + +/// A struct is `FromZeros` if: +/// - all fields are `FromZeros` +fn derive_from_zeros_struct( + ast: &DeriveInput, + strct: &DataStruct, + zerocopy_crate: &Path, +) -> TokenStream { + ImplBlockBuilder::new(ast, strct, Trait::FromZeros, FieldBounds::ALL_SELF, zerocopy_crate) + .build() +} + +/// Returns `Ok(index)` if variant `index` of the enum has a discriminant of +/// zero. If `Err(bool)` is returned, the boolean is true if the enum has +/// unknown discriminants (e.g. discriminants set to const expressions which we +/// can't evaluate in a proc macro). If the enum has unknown discriminants, then +/// it might have a zero variant that we just can't detect. +fn find_zero_variant(enm: &DataEnum) -> Result { + // Discriminants can be anywhere in the range [i128::MIN, u128::MAX] because + // the discriminant type may be signed or unsigned. Since we only care about + // tracking the discriminant when it's less than or equal to zero, we can + // avoid u128 -> i128 conversions and bounds checking by making the "next + // discriminant" value implicitly negative. + // Technically 64 bits is enough, but 128 is better for future compatibility + // with https://github.com/rust-lang/rust/issues/56071 + let mut next_negative_discriminant = Some(0); + + // Sometimes we encounter explicit discriminants that we can't know the + // value of (e.g. a constant expression that requires evaluation). These + // could evaluate to zero or a negative number, but we can't assume that + // they do (no false positives allowed!). So we treat them like strictly- + // positive values that can't result in any zero variants, and track whether + // we've encountered any unknown discriminants. + let mut has_unknown_discriminants = false; + + for (i, v) in enm.variants.iter().enumerate() { + match v.discriminant.as_ref() { + // Implicit discriminant + None => { + match next_negative_discriminant.as_mut() { + Some(0) => return Ok(i), + // n is nonzero so subtraction is always safe + Some(n) => *n -= 1, + None => (), + } + } + // Explicit positive discriminant + Some((_, Expr::Lit(ExprLit { lit: Lit::Int(int), .. }))) => { + match int.base10_parse::().ok() { + Some(0) => return Ok(i), + Some(_) => next_negative_discriminant = None, + None => { + // Numbers should never fail to parse, but just in case: + has_unknown_discriminants = true; + next_negative_discriminant = None; + } + } + } + // Explicit negative discriminant + Some((_, Expr::Unary(ExprUnary { op: UnOp::Neg(_), expr, .. }))) => match &**expr { + Expr::Lit(ExprLit { lit: Lit::Int(int), .. }) => { + match int.base10_parse::().ok() { + Some(0) => return Ok(i), + // x is nonzero so subtraction is always safe + Some(x) => next_negative_discriminant = Some(x - 1), + None => { + // Numbers should never fail to parse, but just in + // case: + has_unknown_discriminants = true; + next_negative_discriminant = None; + } + } + } + // Unknown negative discriminant (e.g. const repr) + _ => { + has_unknown_discriminants = true; + next_negative_discriminant = None; + } + }, + // Unknown discriminant (e.g. const expr) + _ => { + has_unknown_discriminants = true; + next_negative_discriminant = None; + } + } + } + + Err(has_unknown_discriminants) +} + +/// An enum is `FromZeros` if: +/// - one of the variants has a discriminant of `0` +/// - that variant's fields are all `FromZeros` +fn derive_from_zeros_enum( + ast: &DeriveInput, + enm: &DataEnum, + zerocopy_crate: &Path, +) -> Result { + let repr = EnumRepr::from_attrs(&ast.attrs)?; + + // We don't actually care what the repr is; we just care that it's one of + // the allowed ones. + match repr { + Repr::Compound( + Spanned { t: CompoundRepr::C | CompoundRepr::Primitive(_), span: _ }, + _, + ) => {} + Repr::Transparent(_) + | Repr::Compound(Spanned { t: CompoundRepr::Rust, span: _ }, _) => return Err(Error::new(Span::call_site(), "must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout")), + } + + let zero_variant = match find_zero_variant(enm) { + Ok(index) => enm.variants.iter().nth(index).unwrap(), + // Has unknown variants + Err(true) => { + return Err(Error::new_spanned( + ast, + "FromZeros only supported on enums with a variant that has a discriminant of `0`\n\ + help: This enum has discriminants which are not literal integers. One of those may \ + define or imply which variant has a discriminant of zero. Use a literal integer to \ + define or imply the variant with a discriminant of zero.", + )); + } + // Does not have unknown variants + Err(false) => { + return Err(Error::new_spanned( + ast, + "FromZeros only supported on enums with a variant that has a discriminant of `0`", + )); + } + }; + + let explicit_bounds = zero_variant + .fields + .iter() + .map(|field| { + let ty = &field.ty; + parse_quote! { #ty: #zerocopy_crate::FromZeros } + }) + .collect::>(); + + Ok(ImplBlockBuilder::new( + ast, + enm, + Trait::FromZeros, + FieldBounds::Explicit(explicit_bounds), + zerocopy_crate, + ) + .build()) +} + +/// Unions are `FromZeros` if +/// - all fields are `FromZeros` and `Immutable` +fn derive_from_zeros_union( + ast: &DeriveInput, + unn: &DataUnion, + zerocopy_crate: &Path, +) -> TokenStream { + // FIXME(#5): Remove the `Immutable` bound. It's only necessary for + // compatibility with `derive(TryFromBytes)` on unions; not for soundness. + let field_type_trait_bounds = + FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); + ImplBlockBuilder::new(ast, unn, Trait::FromZeros, field_type_trait_bounds, zerocopy_crate) + .build() +} + +/// A struct is `FromBytes` if: +/// - all fields are `FromBytes` +fn derive_from_bytes_struct( + ast: &DeriveInput, + strct: &DataStruct, + zerocopy_crate: &Path, +) -> TokenStream { + ImplBlockBuilder::new(ast, strct, Trait::FromBytes, FieldBounds::ALL_SELF, zerocopy_crate) + .build() +} + +/// An enum is `FromBytes` if: +/// - Every possible bit pattern must be valid, which means that every bit +/// pattern must correspond to a different enum variant. Thus, for an enum +/// whose layout takes up N bytes, there must be 2^N variants. +/// - Since we must know N, only representations which guarantee the layout's +/// size are allowed. These are `repr(uN)` and `repr(iN)` (`repr(C)` implies an +/// implementation-defined size). `usize` and `isize` technically guarantee the +/// layout's size, but would require us to know how large those are on the +/// target platform. This isn't terribly difficult - we could emit a const +/// expression that could call `core::mem::size_of` in order to determine the +/// size and check against the number of enum variants, but a) this would be +/// platform-specific and, b) even on Rust's smallest bit width platform (32), +/// this would require ~4 billion enum variants, which obviously isn't a thing. +/// - All fields of all variants are `FromBytes`. +fn derive_from_bytes_enum( + ast: &DeriveInput, + enm: &DataEnum, + zerocopy_crate: &Path, +) -> Result { + let repr = EnumRepr::from_attrs(&ast.attrs)?; + + let variants_required = 1usize << enum_size_from_repr(&repr)?; + if enm.variants.len() != variants_required { + return Err(Error::new_spanned( + ast, + format!( + "FromBytes only supported on {} enum with {} variants", + repr.repr_type_name(), + variants_required + ), + )); + } + + Ok(ImplBlockBuilder::new(ast, enm, Trait::FromBytes, FieldBounds::ALL_SELF, zerocopy_crate) + .build()) +} + +// Returns `None` if the enum's size is not guaranteed by the repr. +fn enum_size_from_repr(repr: &EnumRepr) -> Result { + use CompoundRepr::*; + use PrimitiveRepr::*; + use Repr::*; + match repr { + Transparent(span) + | Compound( + Spanned { t: C | Rust | Primitive(U32 | I32 | U64 | I64 | U128 | I128 | Usize | Isize), span }, + _, + ) => Err(Error::new(*span, "`FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16`")), + Compound(Spanned { t: Primitive(U8 | I8), span: _ }, _align) => Ok(8), + Compound(Spanned { t: Primitive(U16 | I16), span: _ }, _align) => Ok(16), + } +} + +/// Unions are `FromBytes` if +/// - all fields are `FromBytes` and `Immutable` +fn derive_from_bytes_union( + ast: &DeriveInput, + unn: &DataUnion, + zerocopy_crate: &Path, +) -> TokenStream { + // FIXME(#5): Remove the `Immutable` bound. It's only necessary for + // compatibility with `derive(TryFromBytes)` on unions; not for soundness. + let field_type_trait_bounds = + FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); + ImplBlockBuilder::new(ast, unn, Trait::FromBytes, field_type_trait_bounds, zerocopy_crate) + .build() +} + +fn derive_into_bytes_struct( + ast: &DeriveInput, + strct: &DataStruct, + zerocopy_crate: &Path, +) -> Result { + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + + let is_transparent = repr.is_transparent(); + let is_c = repr.is_c(); + let is_packed_1 = repr.is_packed_1(); + let num_fields = strct.fields().len(); + + let (padding_check, require_unaligned_fields) = if is_transparent || is_packed_1 { + // No padding check needed. + // - repr(transparent): The layout and ABI of the whole struct is the + // same as its only non-ZST field (meaning there's no padding outside + // of that field) and we require that field to be `IntoBytes` (meaning + // there's no padding in that field). + // - repr(packed): Any inter-field padding bytes are removed, meaning + // that any padding bytes would need to come from the fields, all of + // which we require to be `IntoBytes` (meaning they don't have any + // padding). Note that this holds regardless of other `repr` + // attributes, including `repr(Rust)`. [1] + // + // [1] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#the-alignment-modifiers: + // + // An important consequence of these rules is that a type with + // `#[repr(packed(1))]`` (or `#[repr(packed)]``) will have no + // inter-field padding. + (None, false) + } else if is_c && !repr.is_align_gt_1() && num_fields <= 1 { + // No padding check needed. A repr(C) struct with zero or one field has + // no padding unless #[repr(align)] explicitly adds padding, which we + // check for in this branch's condition. + (None, false) + } else if ast.generics.params.is_empty() { + // Is the last field a syntactic slice, i.e., `[SomeType]`. + let is_syntactic_dst = + strct.fields().last().map(|(_, _, ty)| matches!(ty, Type::Slice(_))).unwrap_or(false); + // Since there are no generics, we can emit a padding check. All reprs + // guarantee that fields won't overlap [1], so the padding check is + // sound. This is more permissive than the next case, which requires + // that all field types implement `Unaligned`. + // + // [1] Per https://doc.rust-lang.org/1.81.0/reference/type-layout.html#the-rust-representation: + // + // The only data layout guarantees made by [`repr(Rust)`] are those + // required for soundness. They are: + // ... + // 2. The fields do not overlap. + // ... + if is_c && is_syntactic_dst { + (Some(PaddingCheck::ReprCStruct), false) + } else { + (Some(PaddingCheck::Struct), false) + } + } else if is_c && !repr.is_align_gt_1() { + // We can't use a padding check since there are generic type arguments. + // Instead, we require all field types to implement `Unaligned`. This + // ensures that the `repr(C)` layout algorithm will not insert any + // padding unless #[repr(align)] explicitly adds padding, which we check + // for in this branch's condition. + // + // FIXME(#10): Support type parameters for non-transparent, non-packed + // structs without requiring `Unaligned`. + (None, true) + } else { + return Err(Error::new(Span::call_site(), "must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout")); + }; + + let field_bounds = if require_unaligned_fields { + FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Unaligned)]) + } else { + FieldBounds::ALL_SELF + }; + + Ok(ImplBlockBuilder::new(ast, strct, Trait::IntoBytes, field_bounds, zerocopy_crate) + .padding_check(padding_check) + .build()) +} + +/// If the type is an enum: +/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`, +/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`). +/// - It must have no padding bytes. +/// - Its fields must be `IntoBytes`. +fn derive_into_bytes_enum( + ast: &DeriveInput, + enm: &DataEnum, + zerocopy_crate: &Path, +) -> Result { + let repr = EnumRepr::from_attrs(&ast.attrs)?; + if !repr.is_c() && !repr.is_primitive() { + return Err(Error::new(Span::call_site(), "must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout")); + } + + let tag_type_definition = r#enum::generate_tag_enum(&repr, enm); + Ok(ImplBlockBuilder::new(ast, enm, Trait::IntoBytes, FieldBounds::ALL_SELF, zerocopy_crate) + .padding_check(PaddingCheck::Enum { tag_type_definition }) + .build()) +} + +/// A union is `IntoBytes` if: +/// - all fields are `IntoBytes` +/// - `repr(C)`, `repr(transparent)`, or `repr(packed)` +/// - no padding (size of union equals size of each field type) +fn derive_into_bytes_union( + ast: &DeriveInput, + unn: &DataUnion, + zerocopy_crate: &Path, +) -> Result { + // See #1792 for more context. + // + // By checking for `zerocopy_derive_union_into_bytes` both here and in the + // generated code, we ensure that `--cfg zerocopy_derive_union_into_bytes` + // need only be passed *either* when compiling this crate *or* when + // compiling the user's crate. The former is preferable, but in some + // situations (such as when cross-compiling using `cargo build --target`), + // it doesn't get propagated to this crate's build by default. + let cfg_compile_error = if cfg!(zerocopy_derive_union_into_bytes) { + quote!() + } else { + let error_message = "requires --cfg zerocopy_derive_union_into_bytes; +please let us know you use this feature: https://github.com/google/zerocopy/discussions/1802"; + quote!( + const _: () = { + #[cfg(not(zerocopy_derive_union_into_bytes))] + #zerocopy_crate::util::macro_util::core_reexport::compile_error!(#error_message); + }; + ) + }; + + // FIXME(#10): Support type parameters. + if !ast.generics.params.is_empty() { + return Err(Error::new(Span::call_site(), "unsupported on types with type parameters")); + } + + // Because we don't support generics, we don't need to worry about + // special-casing different reprs. So long as there is *some* repr which + // guarantees the layout, our `PaddingCheck::Union` guarantees that there is + // no padding. + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + if !repr.is_c() && !repr.is_transparent() && !repr.is_packed_1() { + return Err(Error::new( + Span::call_site(), + "must be #[repr(C)], #[repr(packed)], or #[repr(transparent)]", + )); + } + + let impl_block = + ImplBlockBuilder::new(ast, unn, Trait::IntoBytes, FieldBounds::ALL_SELF, zerocopy_crate) + .padding_check(PaddingCheck::Union) + .build(); + Ok(quote!(#cfg_compile_error #impl_block)) +} + +/// A struct is `Unaligned` if: +/// - `repr(align)` is no more than 1 and either +/// - `repr(C)` or `repr(transparent)` and +/// - all fields `Unaligned` +/// - `repr(packed)` +fn derive_unaligned_struct( + ast: &DeriveInput, + strct: &DataStruct, + zerocopy_crate: &Path, +) -> Result { + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + repr.unaligned_validate_no_align_gt_1()?; + + let field_bounds = if repr.is_packed_1() { + FieldBounds::None + } else if repr.is_c() || repr.is_transparent() { + FieldBounds::ALL_SELF + } else { + return Err(Error::new(Span::call_site(), "must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment")); + }; + + Ok(ImplBlockBuilder::new(ast, strct, Trait::Unaligned, field_bounds, zerocopy_crate).build()) +} + +/// An enum is `Unaligned` if: +/// - No `repr(align(N > 1))` +/// - `repr(u8)` or `repr(i8)` +fn derive_unaligned_enum( + ast: &DeriveInput, + enm: &DataEnum, + zerocopy_crate: &Path, +) -> Result { + let repr = EnumRepr::from_attrs(&ast.attrs)?; + repr.unaligned_validate_no_align_gt_1()?; + + if !repr.is_u8() && !repr.is_i8() { + return Err(Error::new(Span::call_site(), "must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment")); + } + + Ok(ImplBlockBuilder::new(ast, enm, Trait::Unaligned, FieldBounds::ALL_SELF, zerocopy_crate) + .build()) +} + +/// Like structs, a union is `Unaligned` if: +/// - `repr(align)` is no more than 1 and either +/// - `repr(C)` or `repr(transparent)` and +/// - all fields `Unaligned` +/// - `repr(packed)` +fn derive_unaligned_union( + ast: &DeriveInput, + unn: &DataUnion, + zerocopy_crate: &Path, +) -> Result { + let repr = StructUnionRepr::from_attrs(&ast.attrs)?; + repr.unaligned_validate_no_align_gt_1()?; + + let field_type_trait_bounds = if repr.is_packed_1() { + FieldBounds::None + } else if repr.is_c() || repr.is_transparent() { + FieldBounds::ALL_SELF + } else { + return Err(Error::new(Span::call_site(), "must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment")); + }; + + Ok(ImplBlockBuilder::new(ast, unn, Trait::Unaligned, field_type_trait_bounds, zerocopy_crate) + .build()) +} + +/// This enum describes what kind of padding check needs to be generated for the +/// associated impl. +enum PaddingCheck { + /// Check that the sum of the fields' sizes exactly equals the struct's + /// size. + Struct, + /// Check that a `repr(C)` struct has no padding. + ReprCStruct, + /// Check that the size of each field exactly equals the union's size. + Union, + /// Check that every variant of the enum contains no padding. + /// + /// Because doing so requires a tag enum, this padding check requires an + /// additional `TokenStream` which defines the tag enum as `___ZerocopyTag`. + Enum { tag_type_definition: TokenStream }, +} + +impl PaddingCheck { + /// Returns the idents of the trait to use and the macro to call in order to + /// validate that a type passes the relevant padding check. + fn validator_trait_and_macro_idents(&self) -> (Ident, Ident) { + let (trt, mcro) = match self { + PaddingCheck::Struct => ("PaddingFree", "struct_padding"), + PaddingCheck::ReprCStruct => ("DynamicPaddingFree", "repr_c_struct_has_padding"), + PaddingCheck::Union => ("PaddingFree", "union_padding"), + PaddingCheck::Enum { .. } => ("PaddingFree", "enum_padding"), + }; + + let trt = Ident::new(trt, Span::call_site()); + let mcro = Ident::new(mcro, Span::call_site()); + (trt, mcro) + } + + /// Sometimes performing the padding check requires some additional + /// "context" code. For enums, this is the definition of the tag enum. + fn validator_macro_context(&self) -> Option<&TokenStream> { + match self { + PaddingCheck::Struct | PaddingCheck::ReprCStruct | PaddingCheck::Union => None, + PaddingCheck::Enum { tag_type_definition } => Some(tag_type_definition), + } + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum Trait { + KnownLayout, + Immutable, + TryFromBytes, + FromZeros, + FromBytes, + IntoBytes, + Unaligned, + Sized, + ByteHash, + ByteEq, + SplitAt, +} + +impl ToTokens for Trait { + fn to_tokens(&self, tokens: &mut TokenStream) { + // According to [1], the format of the derived `Debug`` output is not + // stable and therefore not guaranteed to represent the variant names. + // Indeed with the (unstable) `fmt-debug` compiler flag [2], it can + // return only a minimalized output or empty string. To make sure this + // code will work in the future and independent of the compiler flag, we + // translate the variants to their names manually here. + // + // [1] https://doc.rust-lang.org/1.81.0/std/fmt/trait.Debug.html#stability + // [2] https://doc.rust-lang.org/beta/unstable-book/compiler-flags/fmt-debug.html + let s = match self { + Trait::KnownLayout => "KnownLayout", + Trait::Immutable => "Immutable", + Trait::TryFromBytes => "TryFromBytes", + Trait::FromZeros => "FromZeros", + Trait::FromBytes => "FromBytes", + Trait::IntoBytes => "IntoBytes", + Trait::Unaligned => "Unaligned", + Trait::Sized => "Sized", + Trait::ByteHash => "ByteHash", + Trait::ByteEq => "ByteEq", + Trait::SplitAt => "SplitAt", + }; + let ident = Ident::new(s, Span::call_site()); + tokens.extend(core::iter::once(TokenTree::Ident(ident))); + } +} + +impl Trait { + fn crate_path(&self, zerocopy_crate: &Path) -> Path { + match self { + Self::Sized => { + parse_quote!(#zerocopy_crate::util::macro_util::core_reexport::marker::#self) + } + _ => parse_quote!(#zerocopy_crate::#self), + } + } +} + +#[derive(Debug, Eq, PartialEq)] +enum TraitBound { + Slf, + Other(Trait), +} + +enum FieldBounds<'a> { + None, + All(&'a [TraitBound]), + Trailing(&'a [TraitBound]), + Explicit(Vec), +} + +impl<'a> FieldBounds<'a> { + const ALL_SELF: FieldBounds<'a> = FieldBounds::All(&[TraitBound::Slf]); + const TRAILING_SELF: FieldBounds<'a> = FieldBounds::Trailing(&[TraitBound::Slf]); +} + +#[derive(Debug, Eq, PartialEq)] +enum SelfBounds<'a> { + None, + All(&'a [Trait]), +} + +// FIXME(https://github.com/rust-lang/rust-clippy/issues/12908): This is a false +// positive. Explicit lifetimes are actually necessary here. +#[allow(clippy::needless_lifetimes)] +impl<'a> SelfBounds<'a> { + const SIZED: Self = Self::All(&[Trait::Sized]); +} + +/// Normalizes a slice of bounds by replacing [`TraitBound::Slf`] with `slf`. +fn normalize_bounds(slf: Trait, bounds: &[TraitBound]) -> impl '_ + Iterator { + bounds.iter().map(move |bound| match bound { + TraitBound::Slf => slf, + TraitBound::Other(trt) => *trt, + }) +} + +struct ImplBlockBuilder<'a, D: DataExt> { + input: &'a DeriveInput, + data: &'a D, + trt: Trait, + field_type_trait_bounds: FieldBounds<'a>, + zerocopy_crate: &'a Path, + self_type_trait_bounds: SelfBounds<'a>, + padding_check: Option, + inner_extras: Option, + outer_extras: Option, +} + +impl<'a, D: DataExt> ImplBlockBuilder<'a, D> { + fn new( + input: &'a DeriveInput, + data: &'a D, + trt: Trait, + field_type_trait_bounds: FieldBounds<'a>, + zerocopy_crate: &'a Path, + ) -> Self { + Self { + input, + data, + trt, + field_type_trait_bounds, + zerocopy_crate, + self_type_trait_bounds: SelfBounds::None, + padding_check: None, + inner_extras: None, + outer_extras: None, + } + } + + fn self_type_trait_bounds(mut self, self_type_trait_bounds: SelfBounds<'a>) -> Self { + self.self_type_trait_bounds = self_type_trait_bounds; + self + } + + fn padding_check>>(mut self, padding_check: P) -> Self { + self.padding_check = padding_check.into(); + self + } + + fn inner_extras(mut self, inner_extras: TokenStream) -> Self { + self.inner_extras = Some(inner_extras); + self + } + + fn outer_extras>>(mut self, outer_extras: T) -> Self { + self.outer_extras = outer_extras.into(); + self + } + + fn build(self) -> TokenStream { + // In this documentation, we will refer to this hypothetical struct: + // + // #[derive(FromBytes)] + // struct Foo + // where + // T: Copy, + // I: Clone, + // I::Item: Clone, + // { + // a: u8, + // b: T, + // c: I::Item, + // } + // + // We extract the field types, which in this case are `u8`, `T`, and + // `I::Item`. We re-use the existing parameters and where clauses. If + // `require_trait_bound == true` (as it is for `FromBytes), we add where + // bounds for each field's type: + // + // impl FromBytes for Foo + // where + // T: Copy, + // I: Clone, + // I::Item: Clone, + // T: FromBytes, + // I::Item: FromBytes, + // { + // } + // + // NOTE: It is standard practice to only emit bounds for the type + // parameters themselves, not for field types based on those parameters + // (e.g., `T` vs `T::Foo`). For a discussion of why this is standard + // practice, see https://github.com/rust-lang/rust/issues/26925. + // + // The reason we diverge from this standard is that doing it that way + // for us would be unsound. E.g., consider a type, `T` where `T: + // FromBytes` but `T::Foo: !FromBytes`. It would not be sound for us to + // accept a type with a `T::Foo` field as `FromBytes` simply because `T: + // FromBytes`. + // + // While there's no getting around this requirement for us, it does have + // the pretty serious downside that, when lifetimes are involved, the + // trait solver ties itself in knots: + // + // #[derive(Unaligned)] + // #[repr(C)] + // struct Dup<'a, 'b> { + // a: PhantomData<&'a u8>, + // b: PhantomData<&'b u8>, + // } + // + // error[E0283]: type annotations required: cannot resolve `core::marker::PhantomData<&'a u8>: zerocopy::Unaligned` + // --> src/main.rs:6:10 + // | + // 6 | #[derive(Unaligned)] + // | ^^^^^^^^^ + // | + // = note: required by `zerocopy::Unaligned` + + let type_ident = &self.input.ident; + let trait_path = self.trt.crate_path(self.zerocopy_crate); + let fields = self.data.fields(); + let variants = self.data.variants(); + let tag = self.data.tag(); + let zerocopy_crate = self.zerocopy_crate; + + fn bound_tt( + ty: &Type, + traits: impl Iterator, + zerocopy_crate: &Path, + ) -> WherePredicate { + let traits = traits.map(|t| t.crate_path(zerocopy_crate)); + parse_quote!(#ty: #(#traits)+*) + } + let field_type_bounds: Vec<_> = match (self.field_type_trait_bounds, &fields[..]) { + (FieldBounds::All(traits), _) => fields + .iter() + .map(|(_vis, _name, ty)| { + bound_tt(ty, normalize_bounds(self.trt, traits), zerocopy_crate) + }) + .collect(), + (FieldBounds::None, _) | (FieldBounds::Trailing(..), []) => vec![], + (FieldBounds::Trailing(traits), [.., last]) => { + vec![bound_tt(last.2, normalize_bounds(self.trt, traits), zerocopy_crate)] + } + (FieldBounds::Explicit(bounds), _) => bounds, + }; + + // Don't bother emitting a padding check if there are no fields. + #[allow(unstable_name_collisions)] // See `BoolExt` below + let padding_check_bound = self + .padding_check + .and_then(|check| (!fields.is_empty()).then_some(check)) + .map(|check| { + let variant_types = variants.iter().map(|var| { + let types = var.iter().map(|(_vis, _name, ty)| ty); + quote!([#(#types),*]) + }); + let validator_context = check.validator_macro_context(); + let (trt, validator_macro) = check.validator_trait_and_macro_idents(); + let t = tag.iter(); + parse_quote! { + (): #zerocopy_crate::util::macro_util::#trt< + Self, + { + #validator_context + #zerocopy_crate::#validator_macro!(Self, #(#t,)* #(#variant_types),*) + } + > + } + }); + + let self_bounds: Option = match self.self_type_trait_bounds { + SelfBounds::None => None, + SelfBounds::All(traits) => { + Some(bound_tt(&parse_quote!(Self), traits.iter().copied(), zerocopy_crate)) + } + }; + + let bounds = self + .input + .generics + .where_clause + .as_ref() + .map(|where_clause| where_clause.predicates.iter()) + .into_iter() + .flatten() + .chain(field_type_bounds.iter()) + .chain(padding_check_bound.iter()) + .chain(self_bounds.iter()); + + // The parameters with trait bounds, but without type defaults. + let params = self.input.generics.params.clone().into_iter().map(|mut param| { + match &mut param { + GenericParam::Type(ty) => ty.default = None, + GenericParam::Const(cnst) => cnst.default = None, + GenericParam::Lifetime(_) => {} + } + quote!(#param) + }); + + // The identifiers of the parameters without trait bounds or type + // defaults. + let param_idents = self.input.generics.params.iter().map(|param| match param { + GenericParam::Type(ty) => { + let ident = &ty.ident; + quote!(#ident) + } + GenericParam::Lifetime(l) => { + let ident = &l.lifetime; + quote!(#ident) + } + GenericParam::Const(cnst) => { + let ident = &cnst.ident; + quote!({#ident}) + } + }); + + let inner_extras = self.inner_extras; + let impl_tokens = quote! { + // FIXME(#553): Add a test that generates a warning when + // `#[allow(deprecated)]` isn't present. + #[allow(deprecated)] + // While there are not currently any warnings that this suppresses + // (that we're aware of), it's good future-proofing hygiene. + #[automatically_derived] + unsafe impl < #(#params),* > #trait_path for #type_ident < #(#param_idents),* > + where + #(#bounds,)* + { + fn only_derive_is_allowed_to_implement_this_trait() {} + + #inner_extras + } + }; + + if let Some(outer_extras) = self.outer_extras { + // So that any items defined in `#outer_extras` don't conflict with + // existing names defined in this scope. + quote! { + const _: () = { + #impl_tokens + + #outer_extras + }; + } + } else { + impl_tokens + } + } +} + +// A polyfill for `Option::then_some`, which was added after our MSRV. +// +// The `#[allow(unused)]` is necessary because, on sufficiently recent toolchain +// versions, `b.then_some(...)` resolves to the inherent method rather than to +// this trait, and so this trait is considered unused. +// +// FIXME(#67): Remove this once our MSRV is >= 1.62. +#[allow(unused)] +trait BoolExt { + fn then_some(self, t: T) -> Option; +} + +impl BoolExt for bool { + fn then_some(self, t: T) -> Option { + if self { + Some(t) + } else { + None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/output_tests.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/output_tests.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/output_tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/output_tests.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2362 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use dissimilar::Chunk; +use proc_macro2::TokenStream; + +use crate::IntoTokenStream; + +macro_rules! use_as_trait_name { + ($($alias:ident => $derive:ident),* $(,)?) => { + $(use super::$derive as $alias;)* + }; +} + +// This permits invocations of `test!` to be more ergonomic, passing the name of +// the trait under test rather than the name of the inner derive function. +use_as_trait_name!( + KnownLayout => derive_known_layout_inner, + Immutable => derive_no_cell_inner, + TryFromBytes => derive_try_from_bytes_inner, + FromZeros => derive_from_zeros_inner, + FromBytes => derive_from_bytes_inner, + IntoBytes => derive_into_bytes_inner, + Unaligned => derive_unaligned_inner, + ByteHash => derive_hash_inner, + ByteEq => derive_eq_inner, + SplitAt => derive_split_at_inner, +); + +/// Test that the given derive input expands to the expected output. +/// +/// Equality is tested by formatting both token streams using `prettyplease` and +/// performing string equality on the results. This has the effect of making the +/// tests less brittle and robust against meaningless formatting changes. +// Adapted from https://github.com/joshlf/synstructure/blob/400499aaf54840056ff56718beb7810540e6be59/src/macros.rs#L212-L317 +macro_rules! test { + ($name:ident { $($i:tt)* } expands to { $($o:tt)* }) => { + { + #[allow(dead_code)] + fn ensure_compiles() { + $($i)* + $($o)* + } + + test!($name { $($i)* } expands to { $($o)* } no_build); + } + }; + + ($name:ident { $($i:tt)* } expands to { $($o:tt)* } no_build) => { + { + let ts: proc_macro2::TokenStream = quote::quote!( $($i)* ); + let ast = syn::parse2::(ts).unwrap(); + let res = $name(&ast, crate::Trait::$name, &syn::parse_quote!(::zerocopy)); + let expected_toks = quote::quote!( $($o)* ); + assert_eq_streams(expected_toks.into(), res.into_ts().into()); + } + }; +} + +#[track_caller] +fn assert_eq_streams(expect: TokenStream, res: TokenStream) { + let pretty = + |ts: TokenStream| prettyplease::unparse(&syn::parse_file(&ts.to_string()).unwrap()); + + let expect = pretty(expect.clone()); + let res = pretty(res.clone()); + if expect != res { + let diff = dissimilar::diff(&expect, &res) + .into_iter() + .flat_map(|chunk| { + let (prefix, chunk) = match chunk { + Chunk::Equal(chunk) => (" ", chunk), + Chunk::Delete(chunk) => ("-", chunk), + Chunk::Insert(chunk) => ("+", chunk), + }; + [prefix, chunk, "\n"] + }) + .collect::(); + + panic!( + "\ +test failed: +got: +``` +{} +``` + +diff (expected vs got): +``` +{} +```\n", + res, diff + ); + } +} + +#[test] +fn test_known_layout() { + test! { + KnownLayout { + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::KnownLayout for Foo + where + Self: ::zerocopy::util::macro_util::core_reexport::marker::Sized, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + + type PointerMetadata = (); + + type MaybeUninit = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit; + + const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::(); + + #[inline(always)] + fn raw_from_ptr_len( + bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull, + _meta: (), + ) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull { + bytes.cast::() + } + + #[inline(always)] + fn pointer_to_metadata(_ptr: *mut Self) -> () {} + } + } no_build + } + + test! { + KnownLayout { + #[repr(C, align(2))] + struct Foo(T, U); + } + expands to { + const _: () = { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::KnownLayout for Foo + where + U: ::zerocopy::KnownLayout, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + type PointerMetadata = ::PointerMetadata; + type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit; + const LAYOUT: ::zerocopy::DstLayout = { + use ::zerocopy::util::macro_util::core_reexport::num::NonZeroUsize; + use ::zerocopy::{DstLayout, KnownLayout}; + DstLayout::for_repr_c_struct( + ::zerocopy::util::macro_util::core_reexport::num::NonZeroUsize::new( + 2u32 as usize, + ), + ::zerocopy::util::macro_util::core_reexport::option::Option::None, + &[DstLayout::for_type::(), ::LAYOUT], + ) + }; + #[inline(always)] + fn raw_from_ptr_len( + bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull, + meta: Self::PointerMetadata, + ) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull { + use ::zerocopy::KnownLayout; + let trailing = ::raw_from_ptr_len(bytes, meta); + let slf = trailing.as_ptr() as *mut Self; + unsafe { + ::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked( + slf, + ) + } + } + #[inline(always)] + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata { + ::pointer_to_metadata(ptr as *mut _) + } + } + #[allow(non_camel_case_types)] + struct __Zerocopy_Field_0; + #[allow(non_camel_case_types)] + struct __Zerocopy_Field_1; + unsafe impl ::zerocopy::util::macro_util::Field<__Zerocopy_Field_0> + for Foo { + type Type = T; + } + unsafe impl ::zerocopy::util::macro_util::Field<__Zerocopy_Field_1> + for Foo { + type Type = U; + } + #[repr(C)] + #[repr(align(2))] + #[doc(hidden)] + #[allow(private_bounds)] + struct __ZerocopyKnownLayoutMaybeUninit( + ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit< + as ::zerocopy::util::macro_util::Field<__Zerocopy_Field_0>>::Type, + >, + ::zerocopy::util::macro_util::core_reexport::mem::ManuallyDrop< + < as ::zerocopy::util::macro_util::Field< + __Zerocopy_Field_1, + >>::Type as ::zerocopy::KnownLayout>::MaybeUninit, + >, + ) + where + as ::zerocopy::util::macro_util::Field< + __Zerocopy_Field_1, + >>::Type: ::zerocopy::KnownLayout; + unsafe impl ::zerocopy::KnownLayout for __ZerocopyKnownLayoutMaybeUninit + where + as ::zerocopy::util::macro_util::Field< + __Zerocopy_Field_1, + >>::Type: ::zerocopy::KnownLayout, + { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + type PointerMetadata = as ::zerocopy::KnownLayout>::PointerMetadata; + type MaybeUninit = Self; + const LAYOUT: ::zerocopy::DstLayout = as ::zerocopy::KnownLayout>::LAYOUT; + #[inline(always)] + fn raw_from_ptr_len( + bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull, + meta: Self::PointerMetadata, + ) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull { + use ::zerocopy::KnownLayout; + let trailing = << as ::zerocopy::util::macro_util::Field< + __Zerocopy_Field_1, + >>::Type as ::zerocopy::KnownLayout>::MaybeUninit as KnownLayout>::raw_from_ptr_len( + bytes, + meta, + ); + let slf = trailing.as_ptr() as *mut Self; + unsafe { + ::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked( + slf, + ) + } + } + #[inline(always)] + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata { + << as ::zerocopy::util::macro_util::Field< + __Zerocopy_Field_1, + >>::Type as ::zerocopy::KnownLayout>::MaybeUninit>::pointer_to_metadata( + ptr as *mut _, + ) + } + } + }; + } no_build + } +} + +#[test] +fn test_immutable() { + test! { + Immutable { + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::Immutable for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_try_from_bytes() { + test! { + TryFromBytes { + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + true + } + } + } no_build + } +} + +#[test] +fn test_from_zeros() { + test! { + FromZeros { + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + true + } + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_from_bytes_struct() { + test! { + FromBytes { + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + + true + } + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_from_bytes_union() { + test! { + FromBytes { + union Foo { + a: u8, + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo + where + u8: ::zerocopy::TryFromBytes + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + + true + } + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromZeros for Foo + where + u8: ::zerocopy::FromZeros + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromBytes for Foo + where + u8: ::zerocopy::FromBytes + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_into_bytes_struct() { + test! { + IntoBytes { + #[repr(C)] + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::IntoBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } + + test! { + IntoBytes { + #[repr(C)] + struct Foo { + a: u8, + b: u8, + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::IntoBytes for Foo + where + u8: ::zerocopy::IntoBytes, + u8: ::zerocopy::IntoBytes, + (): ::zerocopy::util::macro_util::PaddingFree< + Self, + { ::zerocopy::struct_padding!(Self, [u8, u8]) }, + >, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } + + test! { + IntoBytes { + #[repr(C)] + struct Foo { + a: u8, + b: [Trailing], + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::IntoBytes for Foo + where + u8: ::zerocopy::IntoBytes, + [Trailing]: ::zerocopy::IntoBytes, + (): ::zerocopy::util::macro_util::DynamicPaddingFree< + Self, + { ::zerocopy::repr_c_struct_has_padding!(Self, [u8, [Trailing]]) }, + >, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } + + test! { + IntoBytes { + #[repr(C)] + struct Foo { + a: u8, + b: [Trailing], + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::IntoBytes for Foo + where + u8: ::zerocopy::IntoBytes + ::zerocopy::Unaligned, + [Trailing]: ::zerocopy::IntoBytes + ::zerocopy::Unaligned, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_into_bytes_enum() { + macro_rules! test_repr { + ($(#[$attr:meta])*) => { + $(test! { + IntoBytes { + #[$attr] + enum Foo { + Bar, + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::IntoBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + })* + }; + } + + test_repr! { + #[repr(C)] + #[repr(u8)] + #[repr(u16)] + #[repr(u32)] + #[repr(u64)] + #[repr(u128)] + #[repr(usize)] + #[repr(i8)] + #[repr(i16)] + #[repr(i32)] + #[repr(i64)] + #[repr(i128)] + #[repr(isize)] + } +} + +#[test] +fn test_unaligned() { + test! { + Unaligned { + #[repr(C)] + struct Foo; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::Unaligned for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_try_from_bytes_enum() { + test! { + TryFromBytes { + #[repr(u8)] + enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref> + where + X: Deref, + { + UnitLike, + StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] }, + TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> + where + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + + #[repr(u8)] + #[allow(dead_code, non_camel_case_types)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = (); + type ___ZerocopyInnerTag = ___ZerocopyTag; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).5); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).6); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), + } + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, + } + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyTagPrimitive>() }) + }; + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.recall_validity::<_, (_, (_, _))>().read_unaligned::<::zerocopy::BecauseImmutable>() + }; + let raw_enum = unsafe { + candidate.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyRawEnum<'a, N, X, Y>>() }) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + use ::zerocopy::pointer::PtrInner; + raw_enum.cast_unsized_unchecked(|p: PtrInner<'_, ___ZerocopyRawEnum<'a, N, X, Y>>| { + let p = p.as_non_null().as_ptr(); + let ptr = core_reexport::ptr::addr_of_mut!((*p).variants); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(ptr) }; + unsafe { PtrInner::new(ptr) } + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, + } + } + } + } no_build + } + + test! { + TryFromBytes { + #[repr(u32)] + enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref> + where + X: Deref, + { + UnitLike, + StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] }, + TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> + where + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + + #[repr(u32)] + #[allow(dead_code, non_camel_case_types)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = (); + type ___ZerocopyInnerTag = ___ZerocopyTag; + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).5); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).6); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), + } + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, + } + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyTagPrimitive> ()}) + }; + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.recall_validity::<_, (_, (_, _))>().read_unaligned::<::zerocopy::BecauseImmutable>() + }; + let raw_enum = unsafe { + candidate.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyRawEnum<'a, N, X, Y>> ()}) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + use ::zerocopy::pointer::PtrInner; + raw_enum.cast_unsized_unchecked(|p: PtrInner<'_, ___ZerocopyRawEnum<'a, N, X, Y>>| { + let p = p.as_non_null().as_ptr(); + let ptr = core_reexport::ptr::addr_of_mut!((*p).variants); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(ptr) }; + unsafe { PtrInner::new(ptr) } + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, + } + } + } + } no_build + } + + test! { + TryFromBytes { + #[repr(C)] + enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref> + where + X: Deref, + { + UnitLike, + StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] }, + TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>), + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ComplexWithGenerics<'a, { N }, X, Y> + where + X: Deref, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + + #[repr(C)] + #[allow(dead_code, non_camel_case_types)] + enum ___ZerocopyTag { + UnitLike, + StructLike, + TupleLike, + } + type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag< + { core_reexport::mem::size_of::<___ZerocopyTag>() }, + >; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive; + #[allow(non_upper_case_globals)] + const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive = + ___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive; + type ___ZerocopyOuterTag = ___ZerocopyTag; + type ___ZerocopyInnerTag = (); + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + u8, + X, + X::Target, + Y::Target, + [(X, Y); N], + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + u8: ::zerocopy::TryFromBytes, + X: ::zerocopy::TryFromBytes, + X::Target: ::zerocopy::TryFromBytes, + Y::Target: ::zerocopy::TryFromBytes, + [(X, Y); N]: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).5); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + <[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).6); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>( + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>, + bool, + Y, + PhantomData<&'a [(X, Y); N]>, + core_reexport::marker::PhantomData>, + ) + where + X: Deref; + #[allow(deprecated)] + #[automatically_derived] + unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes + for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y> + where + X: Deref, + core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes, + bool: ::zerocopy::TryFromBytes, + Y: ::zerocopy::TryFromBytes, + PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes, + core_reexport::marker::PhantomData>: + ::zerocopy::TryFromBytes, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + fn is_bit_valid<___ZerocopyAliasing>( + mut candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + use ::zerocopy::util::macro_util::core_reexport; + use ::zerocopy::pointer::PtrInner; + + true && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).0); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).1); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).2); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + ::is_bit_valid(field_candidate) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).3); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + as ::zerocopy::TryFromBytes>::is_bit_valid( + field_candidate, + ) + } && { + let field_candidate = unsafe { + let project = |slf: PtrInner<'_, Self>| { + let slf = slf.as_non_null().as_ptr(); + let field = core_reexport::ptr::addr_of_mut!((*slf).4); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(field) }; + unsafe { PtrInner::new(ptr) } + }; + candidate.reborrow().cast_unsized_unchecked(project) + }; + , + > as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + } + } + } + #[repr(C)] + #[allow(non_snake_case)] + union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> { + __field_StructLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>, + __field_TupleLike: + core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>, + __nonempty: (), + } + #[repr(C)] + struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> { + tag: ___ZerocopyOuterTag, + variants: ___ZerocopyVariants<'a, N, X, Y>, + } + let tag = { + let tag_ptr = unsafe { + candidate.reborrow().cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyTagPrimitive> ()}) + }; + let tag_ptr = unsafe { tag_ptr.assume_initialized() }; + tag_ptr.recall_validity::<_, (_, (_, _))>().read_unaligned::<::zerocopy::BecauseImmutable>() + }; + let raw_enum = unsafe { + candidate.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, Self>| { p.cast_sized::<___ZerocopyRawEnum<'a, N, X, Y>> ()}) + }; + let raw_enum = unsafe { raw_enum.assume_initialized() }; + let variants = unsafe { + use ::zerocopy::pointer::PtrInner; + raw_enum.cast_unsized_unchecked(|p: PtrInner<'_, ___ZerocopyRawEnum<'a, N, X, Y>>| { + let p = p.as_non_null().as_ptr(); + let ptr = core_reexport::ptr::addr_of_mut!((*p).variants); + let ptr = unsafe { core_reexport::ptr::NonNull::new_unchecked(ptr) }; + unsafe { PtrInner::new(ptr) } + }) + }; + #[allow(non_upper_case_globals)] + match tag { + ___ZEROCOPY_TAG_UnitLike => true, + ___ZEROCOPY_TAG_StructLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + ___ZEROCOPY_TAG_TupleLike => { + let variant = unsafe { + variants.cast_unsized_unchecked(|p: ::zerocopy::pointer::PtrInner<'_, ___ZerocopyVariants<'a, N, X, Y>>| { + p.cast_sized::<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>() + }) + }; + let variant = unsafe { variant.assume_initialized() }; + <___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid ( + variant) + } + _ => false, + } + } + } + } no_build + } +} + +// This goes at the bottom because it's so verbose and it makes scrolling past +// other code a pain. +#[test] +fn test_from_bytes_enum() { + test! { + FromBytes { + #[repr(u8)] + enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + + true + } + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::FromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_try_from_bytes_trivial_is_bit_valid_enum() { + // Even when we aren't deriving `FromBytes` as the top-level trait, + // `TryFromBytes` on enums still detects whether we *could* derive + // `FromBytes`, and if so, performs the same "trivial `is_bit_valid`" + // optimization. + test! { + TryFromBytes { + #[repr(u8)] + enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, + } + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference, + { + true + } + } + } no_build + } +} + +#[test] +fn test_hash() { + test! { + ByteHash { + struct Foo(T) where Self: Sized; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + impl ::zerocopy::util::macro_util::core_reexport::hash::Hash for Foo + where + Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable, + Self: Sized, + { + fn hash(&self, state: &mut H) + where + H: ::zerocopy::util::macro_util::core_reexport::hash::Hasher, + { + ::zerocopy::util::macro_util::core_reexport::hash::Hasher::write( + state, + ::zerocopy::IntoBytes::as_bytes(self) + ) + } + + fn hash_slice(data: &[Self], state: &mut H) + where + H: ::zerocopy::util::macro_util::core_reexport::hash::Hasher, + { + ::zerocopy::util::macro_util::core_reexport::hash::Hasher::write( + state, + ::zerocopy::IntoBytes::as_bytes(data) + ) + } + } + } no_build + } +} + +#[test] +fn test_eq() { + test! { + ByteEq { + struct Foo(T) where Self: Sized; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + impl ::zerocopy::util::macro_util::core_reexport::cmp::PartialEq for Foo + where + Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable, + Self: Sized, + { + fn eq(&self, other: &Self) -> bool { + ::zerocopy::util::macro_util::core_reexport::cmp::PartialEq::eq( + ::zerocopy::IntoBytes::as_bytes(self), + ::zerocopy::IntoBytes::as_bytes(other), + ) + } + } + + #[allow(deprecated)] + #[automatically_derived] + impl ::zerocopy::util::macro_util::core_reexport::cmp::Eq for Foo + where + Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable, + Self: Sized, + { + } + } no_build + } +} + +#[test] +fn test_split_at() { + test! { + SplitAt { + #[repr(C)] + struct Foo(T) where Self: Copy; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::SplitAt for Foo + where + Self: Copy, + T: ::zerocopy::SplitAt, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + type Elem = ::Elem; + } + } no_build + } + + test! { + SplitAt { + #[repr(transparent)] + struct Foo(T) where Self: Copy; + } expands to { + #[allow(deprecated)] + #[automatically_derived] + unsafe impl ::zerocopy::SplitAt for Foo + where + Self: Copy, + T: ::zerocopy::SplitAt, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + type Elem = ::Elem; + } + } no_build + } + + test! { + SplitAt { + #[repr(packed)] + struct Foo(T) where Self: Copy; + } expands to { + ::core::compile_error! { + "must not have #[repr(packed)] attribute" + } + } no_build + } + + test! { + SplitAt { + #[repr(packed(2))] + struct Foo(T) where Self: Copy; + } expands to { + ::core::compile_error! { + "must not have #[repr(packed)] attribute" + } + } no_build + } + + test! { + SplitAt { + enum Foo {} + } expands to { + ::core::compile_error! { + "can only be applied to structs" + } + } no_build + } + + test! { + SplitAt { + union Foo { a: () } + } expands to { + ::core::compile_error! { + "can only be applied to structs" + } + } no_build + } + + test! { + SplitAt { + struct Foo(T) where Self: Copy; + } expands to { + ::core::compile_error! { + "must have #[repr(C)] or #[repr(transparent)] in order to guarantee this type's layout is splitable" + } + } no_build + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/repr.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/repr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/src/repr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/src/repr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,849 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{ + convert::{Infallible, TryFrom}, + num::NonZeroU32, +}; + +use proc_macro2::{Span, TokenStream}; +use quote::{quote_spanned, ToTokens, TokenStreamExt as _}; +use syn::{ + punctuated::Punctuated, spanned::Spanned as _, token::Comma, Attribute, Error, LitInt, Meta, + MetaList, +}; + +/// The computed representation of a type. +/// +/// This is the result of processing all `#[repr(...)]` attributes on a type, if +/// any. A `Repr` is only capable of representing legal combinations of +/// `#[repr(...)]` attributes. +#[cfg_attr(test, derive(Copy, Clone, Debug))] +pub(crate) enum Repr { + /// `#[repr(transparent)]` + Transparent(Span), + /// A compound representation: `repr(C)`, `repr(Rust)`, or `repr(Int)` + /// optionally combined with `repr(packed(...))` or `repr(align(...))` + Compound(Spanned>, Option>>), +} + +/// A compound representation: `repr(C)`, `repr(Rust)`, or `repr(Int)`. +#[cfg_attr(test, derive(Copy, Clone, Debug, Eq, PartialEq))] +pub(crate) enum CompoundRepr { + C, + Rust, + Primitive(Prim), +} + +/// `repr(Int)` +#[derive(Copy, Clone)] +#[cfg_attr(test, derive(Debug, Eq, PartialEq))] +pub(crate) enum PrimitiveRepr { + U8, + U16, + U32, + U64, + U128, + Usize, + I8, + I16, + I32, + I64, + I128, + Isize, +} + +/// `repr(packed(...))` or `repr(align(...))` +#[cfg_attr(test, derive(Copy, Clone, Debug, Eq, PartialEq))] +pub(crate) enum AlignRepr { + Packed(Packed), + Align(NonZeroU32), +} + +/// The representations which can legally appear on a struct or union type. +pub(crate) type StructUnionRepr = Repr; + +/// The representations which can legally appear on an enum type. +pub(crate) type EnumRepr = Repr; + +impl Repr { + /// Gets the name of this "repr type" - the non-align `repr(X)` that is used + /// in prose to refer to this type. + /// + /// For example, we would refer to `#[repr(C, align(4))] struct Foo { ... }` + /// as a "`repr(C)` struct". + pub(crate) fn repr_type_name(&self) -> &str + where + Prim: Copy + With, + { + use CompoundRepr::*; + use PrimitiveRepr::*; + use Repr::*; + match self { + Transparent(_span) => "repr(transparent)", + Compound(Spanned { t: repr, span: _ }, _align) => match repr { + C => "repr(C)", + Rust => "repr(Rust)", + Primitive(prim) => prim.with(|prim| match prim { + U8 => "repr(u8)", + U16 => "repr(u16)", + U32 => "repr(u32)", + U64 => "repr(u64)", + U128 => "repr(u128)", + Usize => "repr(usize)", + I8 => "repr(i8)", + I16 => "repr(i16)", + I32 => "repr(i32)", + I64 => "repr(i64)", + I128 => "repr(i128)", + Isize => "repr(isize)", + }), + }, + } + } + + pub(crate) fn is_transparent(&self) -> bool { + matches!(self, Repr::Transparent(_)) + } + + pub(crate) fn is_c(&self) -> bool { + use CompoundRepr::*; + matches!(self, Repr::Compound(Spanned { t: C, span: _ }, _align)) + } + + pub(crate) fn is_primitive(&self) -> bool { + use CompoundRepr::*; + matches!(self, Repr::Compound(Spanned { t: Primitive(_), span: _ }, _align)) + } + + pub(crate) fn get_packed(&self) -> Option<&Packed> { + use AlignRepr::*; + use Repr::*; + if let Compound(_, Some(Spanned { t: Packed(p), span: _ })) = self { + Some(p) + } else { + None + } + } + + pub(crate) fn get_align(&self) -> Option> { + use AlignRepr::*; + use Repr::*; + if let Compound(_, Some(Spanned { t: Align(n), span })) = self { + Some(Spanned::new(*n, *span)) + } else { + None + } + } + + pub(crate) fn is_align_gt_1(&self) -> bool { + self.get_align().map(|n| n.t.get() > 1).unwrap_or(false) + } + + /// When deriving `Unaligned`, validate that the decorated type has no + /// `#[repr(align(N))]` attribute where `N > 1`. If no such attribute exists + /// (including if `N == 1`), this returns `Ok(())`, and otherwise it returns + /// a descriptive error. + pub(crate) fn unaligned_validate_no_align_gt_1(&self) -> Result<(), Error> { + if let Some(n) = self.get_align().filter(|n| n.t.get() > 1) { + Err(Error::new( + n.span, + "cannot derive `Unaligned` on type with alignment greater than 1", + )) + } else { + Ok(()) + } + } +} + +impl Repr { + /// Does `self` describe a `#[repr(packed)]` or `#[repr(packed(1))]` type? + pub(crate) fn is_packed_1(&self) -> bool { + self.get_packed().map(|n| n.get() == 1).unwrap_or(false) + } +} + +impl Repr { + fn get_primitive(&self) -> Option<&PrimitiveRepr> { + use CompoundRepr::*; + use Repr::*; + if let Compound(Spanned { t: Primitive(p), span: _ }, _align) = self { + Some(p) + } else { + None + } + } + + /// Does `self` describe a `#[repr(u8)]` type? + pub(crate) fn is_u8(&self) -> bool { + matches!(self.get_primitive(), Some(PrimitiveRepr::U8)) + } + + /// Does `self` describe a `#[repr(i8)]` type? + pub(crate) fn is_i8(&self) -> bool { + matches!(self.get_primitive(), Some(PrimitiveRepr::I8)) + } +} + +impl ToTokens for Repr +where + Prim: With + Copy, + Packed: With + Copy, +{ + fn to_tokens(&self, ts: &mut TokenStream) { + use Repr::*; + match self { + Transparent(span) => ts.append_all(quote_spanned! { *span=> #[repr(transparent)] }), + Compound(repr, align) => { + repr.to_tokens(ts); + if let Some(align) = align { + align.to_tokens(ts); + } + } + } + } +} + +impl + Copy> ToTokens for Spanned> { + fn to_tokens(&self, ts: &mut TokenStream) { + use CompoundRepr::*; + match &self.t { + C => ts.append_all(quote_spanned! { self.span=> #[repr(C)] }), + Rust => ts.append_all(quote_spanned! { self.span=> #[repr(Rust)] }), + Primitive(prim) => prim.with(|prim| Spanned::new(prim, self.span).to_tokens(ts)), + } + } +} + +impl ToTokens for Spanned { + fn to_tokens(&self, ts: &mut TokenStream) { + use PrimitiveRepr::*; + match self.t { + U8 => ts.append_all(quote_spanned! { self.span => #[repr(u8)] }), + U16 => ts.append_all(quote_spanned! { self.span => #[repr(u16)] }), + U32 => ts.append_all(quote_spanned! { self.span => #[repr(u32)] }), + U64 => ts.append_all(quote_spanned! { self.span => #[repr(u64)] }), + U128 => ts.append_all(quote_spanned! { self.span => #[repr(u128)] }), + Usize => ts.append_all(quote_spanned! { self.span => #[repr(usize)] }), + I8 => ts.append_all(quote_spanned! { self.span => #[repr(i8)] }), + I16 => ts.append_all(quote_spanned! { self.span => #[repr(i16)] }), + I32 => ts.append_all(quote_spanned! { self.span => #[repr(i32)] }), + I64 => ts.append_all(quote_spanned! { self.span => #[repr(i64)] }), + I128 => ts.append_all(quote_spanned! { self.span => #[repr(i128)] }), + Isize => ts.append_all(quote_spanned! { self.span => #[repr(isize)] }), + } + } +} + +impl + Copy> ToTokens for Spanned> { + fn to_tokens(&self, ts: &mut TokenStream) { + use AlignRepr::*; + // We use `syn::Index` instead of `u32` because `quote_spanned!` + // serializes `u32` literals as `123u32`, not just `123`. Rust doesn't + // recognize that as a valid argument to `#[repr(align(...))]` or + // `#[repr(packed(...))]`. + let to_index = |n: NonZeroU32| syn::Index { index: n.get(), span: self.span }; + match self.t { + Packed(n) => n.with(|n| { + let n = to_index(n); + ts.append_all(quote_spanned! { self.span => #[repr(packed(#n))] }) + }), + Align(n) => { + let n = to_index(n); + ts.append_all(quote_spanned! { self.span => #[repr(align(#n))] }) + } + } + } +} + +/// The result of parsing a single `#[repr(...)]` attribute or a single +/// directive inside a compound `#[repr(..., ...)]` attribute. +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(test, derive(Debug))] +pub(crate) enum RawRepr { + Transparent, + C, + Rust, + U8, + U16, + U32, + U64, + U128, + Usize, + I8, + I16, + I32, + I64, + I128, + Isize, + Align(NonZeroU32), + PackedN(NonZeroU32), + Packed, +} + +/// The error from converting from a `RawRepr`. +#[cfg_attr(test, derive(Debug, Eq, PartialEq))] +pub(crate) enum FromRawReprError { + /// The `RawRepr` doesn't affect the high-level repr we're parsing (e.g. + /// it's `align(...)` and we're parsing a `CompoundRepr`). + None, + /// The `RawRepr` is invalid for the high-level repr we're parsing (e.g. + /// it's `packed` repr and we're parsing an `AlignRepr` for an enum type). + Err(E), +} + +/// The representation hint is not supported for the decorated type. +#[cfg_attr(test, derive(Copy, Clone, Debug, Eq, PartialEq))] +pub(crate) struct UnsupportedReprError; + +impl> TryFrom for CompoundRepr { + type Error = FromRawReprError; + fn try_from( + raw: RawRepr, + ) -> Result, FromRawReprError> { + use RawRepr::*; + match raw { + C => Ok(CompoundRepr::C), + Rust => Ok(CompoundRepr::Rust), + raw @ (U8 | U16 | U32 | U64 | U128 | Usize | I8 | I16 | I32 | I64 | I128 | Isize) => { + Prim::try_with_or( + || match raw { + U8 => Ok(PrimitiveRepr::U8), + U16 => Ok(PrimitiveRepr::U16), + U32 => Ok(PrimitiveRepr::U32), + U64 => Ok(PrimitiveRepr::U64), + U128 => Ok(PrimitiveRepr::U128), + Usize => Ok(PrimitiveRepr::Usize), + I8 => Ok(PrimitiveRepr::I8), + I16 => Ok(PrimitiveRepr::I16), + I32 => Ok(PrimitiveRepr::I32), + I64 => Ok(PrimitiveRepr::I64), + I128 => Ok(PrimitiveRepr::I128), + Isize => Ok(PrimitiveRepr::Isize), + Transparent | C | Rust | Align(_) | PackedN(_) | Packed => { + Err(UnsupportedReprError) + } + }, + UnsupportedReprError, + ) + .map(CompoundRepr::Primitive) + .map_err(FromRawReprError::Err) + } + Transparent | Align(_) | PackedN(_) | Packed => Err(FromRawReprError::None), + } + } +} + +impl> TryFrom for AlignRepr { + type Error = FromRawReprError; + fn try_from(raw: RawRepr) -> Result, FromRawReprError> { + use RawRepr::*; + match raw { + Packed | PackedN(_) => Pcked::try_with_or( + || match raw { + Packed => Ok(NonZeroU32::new(1).unwrap()), + PackedN(n) => Ok(n), + U8 | U16 | U32 | U64 | U128 | Usize | I8 | I16 | I32 | I64 | I128 | Isize + | Transparent | C | Rust | Align(_) => Err(UnsupportedReprError), + }, + UnsupportedReprError, + ) + .map(AlignRepr::Packed) + .map_err(FromRawReprError::Err), + Align(n) => Ok(AlignRepr::Align(n)), + U8 | U16 | U32 | U64 | U128 | Usize | I8 | I16 | I32 | I64 | I128 | Isize + | Transparent | C | Rust => Err(FromRawReprError::None), + } + } +} + +/// The error from extracting a high-level repr type from a list of `RawRepr`s. +#[cfg_attr(test, derive(Copy, Clone, Debug, Eq, PartialEq))] +enum FromRawReprsError { + /// One of the `RawRepr`s is invalid for the high-level repr we're parsing + /// (e.g. there's a `packed` repr and we're parsing an `AlignRepr` for an + /// enum type). + Single(E), + /// Two `RawRepr`s appear which both affect the high-level repr we're + /// parsing (e.g., the list is `#[repr(align(2), packed)]`). Note that we + /// conservatively treat redundant reprs as conflicting (e.g. + /// `#[repr(packed, packed)]`). + Conflict, +} + +/// Tries to extract a high-level repr from a list of `RawRepr`s. +fn try_from_raw_reprs<'a, E, R: TryFrom>>( + r: impl IntoIterator>, +) -> Result>, Spanned>> { + // Walk the list of `RawRepr`s and attempt to convert each to an `R`. Bail + // if we find any errors. If we find more than one which converts to an `R`, + // bail with a `Conflict` error. + r.into_iter().try_fold(None, |found: Option>, raw| { + let new = match Spanned::::try_from(*raw) { + Ok(r) => r, + // This `RawRepr` doesn't convert to an `R`, so keep the current + // found `R`, if any. + Err(FromRawReprError::None) => return Ok(found), + // This repr is unsupported for the decorated type (e.g. + // `repr(packed)` on an enum). + Err(FromRawReprError::Err(Spanned { t: err, span })) => { + return Err(Spanned::new(FromRawReprsError::Single(err), span)) + } + }; + + if let Some(found) = found { + // We already found an `R`, but this `RawRepr` also converts to an + // `R`, so that's a conflict. + // + // `Span::join` returns `None` if the two spans are from different + // files or if we're not on the nightly compiler. In that case, just + // use `new`'s span. + let span = found.span.join(new.span).unwrap_or(new.span); + Err(Spanned::new(FromRawReprsError::Conflict, span)) + } else { + Ok(Some(new)) + } + }) +} + +/// The error returned from [`Repr::from_attrs`]. +#[cfg_attr(test, derive(Copy, Clone, Debug, Eq, PartialEq))] +enum FromAttrsError { + FromRawReprs(FromRawReprsError), + Unrecognized, +} + +impl From> for FromAttrsError { + fn from(err: FromRawReprsError) -> FromAttrsError { + FromAttrsError::FromRawReprs(err) + } +} + +impl From for FromAttrsError { + fn from(_err: UnrecognizedReprError) -> FromAttrsError { + FromAttrsError::Unrecognized + } +} + +impl From> for Error { + fn from(err: Spanned) -> Error { + let Spanned { t: err, span } = err; + match err { + FromAttrsError::FromRawReprs(FromRawReprsError::Single( + _err @ UnsupportedReprError, + )) => Error::new(span, "unsupported representation hint for the decorated type"), + FromAttrsError::FromRawReprs(FromRawReprsError::Conflict) => { + // NOTE: This says "another" rather than "a preceding" because + // when one of the reprs involved is `transparent`, we detect + // that condition in `Repr::from_attrs`, and at that point we + // can't tell which repr came first, so we might report this on + // the first involved repr rather than the second, third, etc. + Error::new(span, "this conflicts with another representation hint") + } + FromAttrsError::Unrecognized => Error::new(span, "unrecognized representation hint"), + } + } +} + +impl Repr { + fn from_attrs_inner(attrs: &[Attribute]) -> Result, Spanned> + where + Prim: With, + Packed: With, + { + let raw_reprs = RawRepr::from_attrs(attrs).map_err(Spanned::from)?; + + let transparent = { + let mut transparents = raw_reprs.iter().filter_map(|Spanned { t, span }| match t { + RawRepr::Transparent => Some(span), + _ => None, + }); + let first = transparents.next(); + let second = transparents.next(); + match (first, second) { + (None, None) => None, + (Some(span), None) => Some(*span), + (Some(_), Some(second)) => { + return Err(Spanned::new( + FromAttrsError::FromRawReprs(FromRawReprsError::Conflict), + *second, + )) + } + // An iterator can't produce a value only on the second call to + // `.next()`. + (None, Some(_)) => unreachable!(), + } + }; + + let compound: Option>> = + try_from_raw_reprs(raw_reprs.iter()).map_err(Spanned::from)?; + let align: Option>> = + try_from_raw_reprs(raw_reprs.iter()).map_err(Spanned::from)?; + + if let Some(span) = transparent { + if compound.is_some() || align.is_some() { + // Arbitrarily report the problem on the `transparent` span. Any + // span will do. + return Err(Spanned::new(FromRawReprsError::Conflict.into(), span)); + } + + Ok(Repr::Transparent(span)) + } else { + Ok(Repr::Compound( + compound.unwrap_or(Spanned::new(CompoundRepr::Rust, Span::call_site())), + align, + )) + } + } +} + +impl Repr { + pub(crate) fn from_attrs(attrs: &[Attribute]) -> Result, Error> + where + Prim: With, + Packed: With, + { + Repr::from_attrs_inner(attrs).map_err(Into::into) + } +} + +/// The representation hint could not be parsed or was unrecognized. +struct UnrecognizedReprError; + +impl RawRepr { + fn from_attrs( + attrs: &[Attribute], + ) -> Result>, Spanned> { + let mut reprs = Vec::new(); + for attr in attrs { + // Ignore documentation attributes. + if attr.path().is_ident("doc") { + continue; + } + if let Meta::List(ref meta_list) = attr.meta { + if meta_list.path.is_ident("repr") { + let parsed: Punctuated = + match meta_list.parse_args_with(Punctuated::parse_terminated) { + Ok(parsed) => parsed, + Err(_) => { + return Err(Spanned::new( + UnrecognizedReprError, + meta_list.tokens.span(), + )) + } + }; + for meta in parsed { + let s = meta.span(); + reprs.push( + RawRepr::from_meta(&meta) + .map(|r| Spanned::new(r, s)) + .map_err(|e| Spanned::new(e, s))?, + ); + } + } + } + } + + Ok(reprs) + } + + fn from_meta(meta: &Meta) -> Result { + let (path, list) = match meta { + Meta::Path(path) => (path, None), + Meta::List(list) => (&list.path, Some(list)), + _ => return Err(UnrecognizedReprError), + }; + + let ident = path.get_ident().ok_or(UnrecognizedReprError)?; + + // Only returns `Ok` for non-zero power-of-two values. + let parse_nzu64 = |list: &MetaList| { + list.parse_args::() + .and_then(|int| int.base10_parse::()) + .map_err(|_| UnrecognizedReprError) + .and_then(|nz| { + if nz.get().is_power_of_two() { + Ok(nz) + } else { + Err(UnrecognizedReprError) + } + }) + }; + + use RawRepr::*; + Ok(match (ident.to_string().as_str(), list) { + ("u8", None) => U8, + ("u16", None) => U16, + ("u32", None) => U32, + ("u64", None) => U64, + ("u128", None) => U128, + ("usize", None) => Usize, + ("i8", None) => I8, + ("i16", None) => I16, + ("i32", None) => I32, + ("i64", None) => I64, + ("i128", None) => I128, + ("isize", None) => Isize, + ("C", None) => C, + ("transparent", None) => Transparent, + ("Rust", None) => Rust, + ("packed", None) => Packed, + ("packed", Some(list)) => PackedN(parse_nzu64(list)?), + ("align", Some(list)) => Align(parse_nzu64(list)?), + _ => return Err(UnrecognizedReprError), + }) + } +} + +pub(crate) use util::*; +mod util { + use super::*; + /// A value with an associated span. + #[derive(Copy, Clone)] + #[cfg_attr(test, derive(Debug))] + pub(crate) struct Spanned { + pub(crate) t: T, + pub(crate) span: Span, + } + + impl Spanned { + pub(super) fn new(t: T, span: Span) -> Spanned { + Spanned { t, span } + } + + pub(super) fn from(s: Spanned) -> Spanned + where + T: From, + { + let Spanned { t: u, span } = s; + Spanned::new(u.into(), span) + } + + /// Delegates to `T: TryFrom`, preserving span information in both the + /// success and error cases. + pub(super) fn try_from( + u: Spanned, + ) -> Result, FromRawReprError>> + where + T: TryFrom>, + { + let Spanned { t: u, span } = u; + T::try_from(u).map(|t| Spanned { t, span }).map_err(|err| match err { + FromRawReprError::None => FromRawReprError::None, + FromRawReprError::Err(e) => FromRawReprError::Err(Spanned::new(e, span)), + }) + } + } + + // Used to permit implementing `With for T: Inhabited` and for + // `Infallible` without a blanket impl conflict. + pub(crate) trait Inhabited {} + impl Inhabited for PrimitiveRepr {} + impl Inhabited for NonZeroU32 {} + + pub(crate) trait With { + fn with O>(self, f: F) -> O; + fn try_with_or Result>(f: F, err: E) -> Result + where + Self: Sized; + } + + impl With for T { + fn with O>(self, f: F) -> O { + f(self) + } + + fn try_with_or Result>(f: F, _err: E) -> Result { + f() + } + } + + impl With for Infallible { + fn with O>(self, _f: F) -> O { + match self {} + } + + fn try_with_or Result>(_f: F, err: E) -> Result { + Err(err) + } + } +} + +#[cfg(test)] +mod tests { + use syn::parse_quote; + + use super::*; + + impl From for Spanned { + fn from(t: T) -> Spanned { + Spanned::new(t, Span::call_site()) + } + } + + // We ignore spans for equality in testing since real spans are hard to + // synthesize and don't implement `PartialEq`. + impl PartialEq for Spanned { + fn eq(&self, other: &Spanned) -> bool { + self.t.eq(&other.t) + } + } + + impl Eq for Spanned {} + + impl PartialEq for Repr { + fn eq(&self, other: &Repr) -> bool { + match (self, other) { + (Repr::Transparent(_), Repr::Transparent(_)) => true, + (Repr::Compound(sc, sa), Repr::Compound(oc, oa)) => (sc, sa) == (oc, oa), + _ => false, + } + } + } + + fn s() -> Span { + Span::call_site() + } + + #[test] + fn test() { + // Test that a given `#[repr(...)]` attribute parses and returns the + // given `Repr` or error. + macro_rules! test { + ($(#[$attr:meta])* => $repr:expr) => { + test!(@inner $(#[$attr])* => Repr => Ok($repr)); + }; + // In the error case, the caller must explicitly provide the name of + // the `Repr` type to assist in type inference. + (@error $(#[$attr:meta])* => $typ:ident => $repr:expr) => { + test!(@inner $(#[$attr])* => $typ => Err($repr)); + }; + (@inner $(#[$attr:meta])* => $typ:ident => $repr:expr) => { + let attr: Attribute = parse_quote!($(#[$attr])*); + let mut got = $typ::from_attrs_inner(&[attr]); + let expect: Result, _> = $repr; + if false { + // Force Rust to infer `got` as having the same type as + // `expect`. + got = expect; + } + assert_eq!(got, expect, stringify!($(#[$attr])*)); + }; + } + + use AlignRepr::*; + use CompoundRepr::*; + use PrimitiveRepr::*; + let nz = |n: u32| NonZeroU32::new(n).unwrap(); + + test!(#[repr(transparent)] => StructUnionRepr::Transparent(s())); + test!(#[repr()] => StructUnionRepr::Compound(Rust.into(), None)); + test!(#[repr(packed)] => StructUnionRepr::Compound(Rust.into(), Some(Packed(nz(1)).into()))); + test!(#[repr(packed(2))] => StructUnionRepr::Compound(Rust.into(), Some(Packed(nz(2)).into()))); + test!(#[repr(align(1))] => StructUnionRepr::Compound(Rust.into(), Some(Align(nz(1)).into()))); + test!(#[repr(align(2))] => StructUnionRepr::Compound(Rust.into(), Some(Align(nz(2)).into()))); + test!(#[repr(C)] => StructUnionRepr::Compound(C.into(), None)); + test!(#[repr(C, packed)] => StructUnionRepr::Compound(C.into(), Some(Packed(nz(1)).into()))); + test!(#[repr(C, packed(2))] => StructUnionRepr::Compound(C.into(), Some(Packed(nz(2)).into()))); + test!(#[repr(C, align(1))] => StructUnionRepr::Compound(C.into(), Some(Align(nz(1)).into()))); + test!(#[repr(C, align(2))] => StructUnionRepr::Compound(C.into(), Some(Align(nz(2)).into()))); + + test!(#[repr(transparent)] => EnumRepr::Transparent(s())); + test!(#[repr()] => EnumRepr::Compound(Rust.into(), None)); + test!(#[repr(align(1))] => EnumRepr::Compound(Rust.into(), Some(Align(nz(1)).into()))); + test!(#[repr(align(2))] => EnumRepr::Compound(Rust.into(), Some(Align(nz(2)).into()))); + + macro_rules! for_each_compound_repr { + ($($r:tt => $var:expr),*) => { + $( + test!(#[repr($r)] => EnumRepr::Compound($var.into(), None)); + test!(#[repr($r, align(1))] => EnumRepr::Compound($var.into(), Some(Align(nz(1)).into()))); + test!(#[repr($r, align(2))] => EnumRepr::Compound($var.into(), Some(Align(nz(2)).into()))); + )* + } + } + + for_each_compound_repr!( + C => C, + u8 => Primitive(U8), + u16 => Primitive(U16), + u32 => Primitive(U32), + u64 => Primitive(U64), + usize => Primitive(Usize), + i8 => Primitive(I8), + i16 => Primitive(I16), + i32 => Primitive(I32), + i64 => Primitive(I64), + isize => Primitive(Isize) + ); + + use FromAttrsError::*; + use FromRawReprsError::*; + + // Run failure tests which are valid for both `StructUnionRepr` and + // `EnumRepr`. + macro_rules! for_each_repr_type { + ($($repr:ident),*) => { + $( + // Invalid packed or align attributes + test!(@error #[repr(packed(0))] => $repr => Unrecognized.into()); + test!(@error #[repr(packed(3))] => $repr => Unrecognized.into()); + test!(@error #[repr(align(0))] => $repr => Unrecognized.into()); + test!(@error #[repr(align(3))] => $repr => Unrecognized.into()); + + // Conflicts + test!(@error #[repr(transparent, transparent)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(transparent, C)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(transparent, Rust)] => $repr => FromRawReprs(Conflict).into()); + + test!(@error #[repr(C, transparent)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(C, C)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(C, Rust)] => $repr => FromRawReprs(Conflict).into()); + + test!(@error #[repr(Rust, transparent)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(Rust, C)] => $repr => FromRawReprs(Conflict).into()); + test!(@error #[repr(Rust, Rust)] => $repr => FromRawReprs(Conflict).into()); + )* + } + } + + for_each_repr_type!(StructUnionRepr, EnumRepr); + + // Enum-specific conflicts. + // + // We don't bother to test every combination since that would be a huge + // number (enums can have primitive reprs u8, u16, u32, u64, usize, i8, + // i16, i32, i64, and isize). Instead, since the conflict logic doesn't + // care what specific value of `PrimitiveRepr` is present, we assume + // that testing against u8 alone is fine. + test!(@error #[repr(transparent, u8)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(u8, transparent)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(C, u8)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(u8, C)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(Rust, u8)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(u8, Rust)] => EnumRepr => FromRawReprs(Conflict).into()); + test!(@error #[repr(u8, u8)] => EnumRepr => FromRawReprs(Conflict).into()); + + // Illegal struct/union reprs + test!(@error #[repr(u8)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(u16)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(u32)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(u64)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(usize)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(i8)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(i16)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(i32)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(i64)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(isize)] => StructUnionRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + + // Illegal enum reprs + test!(@error #[repr(packed)] => EnumRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(packed(1))] => EnumRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + test!(@error #[repr(packed(2))] => EnumRepr => FromRawReprs(Single(UnsupportedReprError)).into()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/crate_path.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/crate_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/crate_path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/crate_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,189 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Make sure that the derive macros will respect the +// `#[zerocopy(crate = "...")]` attribute when renaming the crate. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[test] +fn test_gen_custom_zerocopy() { + #[derive( + imp::ByteEq, + imp::ByteHash, + imp::IntoBytes, + imp::FromBytes, + imp::Unaligned, + imp::Immutable, + imp::KnownLayout, + )] + #[zerocopy(crate = "fake_zerocopy")] + #[repr(packed)] + struct SomeStruct { + a: u16, + b: u32, + } + + impl AssertNotZerocopyIntoBytes for SomeStruct {} + impl AssertNotZerocopyFromBytes for SomeStruct {} + impl AssertNotZerocopyUnaligned for SomeStruct {} + impl AssertNotZerocopyImmutable for SomeStruct {} + impl AssertNotZerocopyKnownLayout for SomeStruct {} + + fake_zerocopy::assert::(); +} + +mod fake_zerocopy { + use ::std::{io, ptr::NonNull, unimplemented}; + + pub use super::imp::*; + + pub fn assert() + where + T: IntoBytes + FromBytes + Unaligned + Immutable, + { + } + + pub unsafe trait IntoBytes { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + fn as_bytes(&self) -> &[u8] + where + Self: Immutable, + { + unimplemented!() + } + } + + pub unsafe trait FromBytes: FromZeros { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + } + + pub unsafe trait Unaligned { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + } + + pub unsafe trait Immutable { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + } + + pub unsafe trait KnownLayout { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + + type PointerMetadata: PointerMetadata; + + type MaybeUninit: ?Sized + KnownLayout; + + const LAYOUT: DstLayout; + + fn raw_from_ptr_len(bytes: NonNull, meta: Self::PointerMetadata) -> NonNull; + + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata; + } + + macro_rules! impl_ty { + ($ty:ty $(as $generic:ident)?) => { + unsafe impl$(<$generic: IntoBytes>)? IntoBytes for $ty { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + unimplemented!() + } + } + + unsafe impl$(<$generic: FromBytes>)? FromBytes for $ty { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + unimplemented!() + } + } + + unsafe impl$(<$generic: Unaligned>)? Unaligned for $ty { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + unimplemented!() + } + } + + unsafe impl$(<$generic: Immutable>)? Immutable for $ty { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + unimplemented!() + } + } + + unsafe impl$(<$generic: KnownLayout>)? KnownLayout for $ty { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + unimplemented!() + } + + type PointerMetadata = (); + + type MaybeUninit = (); + + const LAYOUT: DstLayout = DstLayout::new_zst(None); + + fn raw_from_ptr_len( + bytes: NonNull, + meta: Self::PointerMetadata, + ) -> NonNull { + unimplemented!() + } + + fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata { + unimplemented!() + } + } + }; + } + + impl_ty!(()); + impl_ty!(u16); + impl_ty!(u32); + impl_ty!([T] as T); + impl_ty!(::std::mem::MaybeUninit as T); +} + +pub trait AssertNotZerocopyIntoBytes {} +impl AssertNotZerocopyIntoBytes for T {} + +pub trait AssertNotZerocopyFromBytes {} +impl AssertNotZerocopyFromBytes for T {} + +pub trait AssertNotZerocopyUnaligned {} +impl AssertNotZerocopyUnaligned for T {} + +pub trait AssertNotZerocopyImmutable {} +impl AssertNotZerocopyImmutable for T {} + +pub trait AssertNotZerocopyKnownLayout {} +impl AssertNotZerocopyKnownLayout for T {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/deprecated.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/deprecated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/deprecated.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/deprecated.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] +#![deny(deprecated)] + +include!("include.rs"); + +// Make sure no deprecation warnings are generated from our derives (see #553). + +#[macro_export] +macro_rules! test { + ($name:ident => $ty:item => $($trait:ident),*) => { + #[allow(non_snake_case)] + mod $name { + $( + mod $trait { + use super::super::*; + + #[deprecated = "do not use"] + #[derive(imp::$trait)] + $ty + + #[allow(deprecated)] + fn _allow_deprecated() { + util_assert_impl_all!($name: imp::$trait); + } + } + )* + } + }; +} + +// NOTE: `FromBytes` is tested separately in `enum_from_bytes.rs` since it +// requires 256-variant enums which are extremely verbose; such enums are +// already in that file. +test!(Enum => #[repr(u8)] enum Enum { A, } => TryFromBytes, FromZeros, KnownLayout, Immutable, IntoBytes, Unaligned); + +test!(Struct => #[repr(C)] struct Struct; => TryFromBytes, FromZeros, FromBytes, KnownLayout, Immutable, IntoBytes, Unaligned); + +test!(Union => #[repr(C)] union Union{ a: (), } => TryFromBytes, FromZeros, FromBytes, KnownLayout, Immutable, IntoBytes, Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_from_zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_from_zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_from_zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_from_zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::FromZeros)] +#[repr(C)] +enum Foo { + A, +} + +util_assert_impl_all!(Foo: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(C)] +enum Bar { + A = 0, +} + +util_assert_impl_all!(Bar: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(C)] +enum TwoVariantsHasExplicitZero { + A = 1, + B = 0, +} + +util_assert_impl_all!(TwoVariantsHasExplicitZero: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(i8)] +enum ImplicitNonFirstVariantIsZero { + A = -1, + B, +} + +util_assert_impl_all!(ImplicitNonFirstVariantIsZero: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(u64)] +enum LargeDiscriminant { + A = 0xFFFF_FFFF_FFFF_FFFF, + B = 0x0000_0000_0000_0000, +} + +util_assert_impl_all!(LargeDiscriminant: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(C)] +enum FirstVariantIsZeroable { + A(u32), + B { foo: u32 }, +} + +util_assert_impl_all!(FirstVariantIsZeroable: imp::FromZeros); + +#[derive(imp::FromZeros)] +#[repr(u8)] +enum FirstVariantIsZeroableSecondIsNot { + A(bool), + B(::core::num::NonZeroU8), +} + +util_assert_impl_all!(FirstVariantIsZeroableSecondIsNot: imp::FromZeros); + +// MSRV does not support data-carrying enum variants with explicit discriminants +#[cfg(not(__ZEROCOPY_TOOLCHAIN = "msrv"))] +mod msrv_only { + use super::*; + + #[derive(imp::FromZeros)] + #[repr(u8)] + enum ImplicitFirstVariantIsZeroable { + A(bool), + B(::core::num::NonZeroU8) = 1, + } + + util_assert_impl_all!(ImplicitFirstVariantIsZeroable: imp::FromZeros); + + #[derive(imp::FromZeros)] + #[repr(i8)] + enum ImplicitNonFirstVariantIsZeroable { + A(::core::num::NonZeroU8) = 1, + B = -1, + C(bool), + } + + util_assert_impl_all!(ImplicitNonFirstVariantIsZeroable: imp::FromZeros); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_known_layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_known_layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_known_layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_known_layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::KnownLayout)] +enum Foo { + A, +} + +util_assert_impl_all!(Foo: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +enum Bar { + A = 0, +} + +util_assert_impl_all!(Bar: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +enum Baz { + A = 1, + B = 0, +} + +util_assert_impl_all!(Baz: imp::KnownLayout); + +// Deriving `KnownLayout` should work if the enum has bounded parameters. + +#[derive(imp::KnownLayout)] +#[repr(C)] +enum WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::KnownLayout, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::KnownLayout, +{ + Variant([T; N], imp::PhantomData<&'a &'b ()>), +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::KnownLayout); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_no_cell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_no_cell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_no_cell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_no_cell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::Immutable)] +enum Foo { + A, +} + +util_assert_impl_all!(Foo: imp::Immutable); + +#[derive(imp::Immutable)] +enum Bar { + A = 0, +} + +util_assert_impl_all!(Bar: imp::Immutable); + +#[derive(imp::Immutable)] +enum Baz { + A = 1, + B = 0, +} + +util_assert_impl_all!(Baz: imp::Immutable); + +// Deriving `Immutable` should work if the enum has bounded parameters. + +#[derive(imp::Immutable)] +#[repr(C)] +enum WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::Immutable, const N: ::core::primitive::usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Immutable, +{ + Variant([T; N], imp::PhantomData<&'a &'b ()>), + UnsafeCell(imp::PhantomData>, &'a imp::UnsafeCell<()>), +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::Immutable); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_to_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_to_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_to_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_to_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,133 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// An enum is `IntoBytes` if if has a defined repr. + +#[derive(imp::IntoBytes)] +#[repr(C)] +enum C { + A, +} + +util_assert_impl_all!(C: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u8)] +enum U8 { + A, +} + +util_assert_impl_all!(U8: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u16)] +enum U16 { + A, +} + +util_assert_impl_all!(U16: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u32)] +enum U32 { + A, +} + +util_assert_impl_all!(U32: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u64)] +enum U64 { + A, +} + +util_assert_impl_all!(U64: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(usize)] +enum Usize { + A, +} + +util_assert_impl_all!(Usize: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(i8)] +enum I8 { + A, +} + +util_assert_impl_all!(I8: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(i16)] +enum I16 { + A, +} + +util_assert_impl_all!(I16: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(i32)] +enum I32 { + A, +} + +util_assert_impl_all!(I32: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(i64)] +enum I64 { + A, +} + +util_assert_impl_all!(I64: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(isize)] +enum Isize { + A, +} + +util_assert_impl_all!(Isize: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u8)] +enum HasData { + A(u8), + B(i8), +} + +util_assert_impl_all!(HasData: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(u32)] +enum HasData32 { + A(u32), + B(i32), + C([u8; 4]), + D([u16; 2]), +} + +util_assert_impl_all!(HasData: imp::IntoBytes); + +// After #1752 landed but before #1758 was fixed, this failed to compile because +// the padding check treated the tag type as being `#[repr(u8, align(2))] struct +// Tag { A }`, which is two bytes long, rather than the correct `#[repr(u8)] +// struct Tag { A }`, which is one byte long. +#[derive(imp::IntoBytes)] +#[repr(u8, align(2))] +enum BadTagWouldHavePadding { + A(u8, u16), +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_try_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_try_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_try_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_try_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,644 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(Eq, PartialEq, Debug, imp::Immutable, imp::KnownLayout, imp::TryFromBytes)] +#[repr(u8)] +enum Foo { + A, +} + +util_assert_impl_all!(Foo: imp::TryFromBytes); + +#[test] +fn test_foo() { + imp::assert_eq!(::try_read_from_bytes(&[0]), imp::Ok(Foo::A)); + imp::assert!(::try_read_from_bytes(&[]).is_err()); + imp::assert!(::try_read_from_bytes(&[1]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0]).is_err()); +} + +#[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)] +#[repr(u16)] +enum Bar { + A = 0, +} + +util_assert_impl_all!(Bar: imp::TryFromBytes); + +#[test] +fn test_bar() { + imp::assert_eq!(::try_read_from_bytes(&[0, 0]), imp::Ok(Bar::A)); + imp::assert!(::try_read_from_bytes(&[]).is_err()); + imp::assert!(::try_read_from_bytes(&[0]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 1]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0, 0]).is_err()); +} + +#[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)] +#[repr(u32)] +enum Baz { + A = 1, + B = 0, +} + +util_assert_impl_all!(Baz: imp::TryFromBytes); + +#[test] +fn test_baz() { + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&1u32)), + imp::Ok(Baz::A) + ); + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&0u32)), + imp::Ok(Baz::B) + ); + imp::assert!(::try_read_from_bytes(&[]).is_err()); + imp::assert!(::try_read_from_bytes(&[0]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0, 0]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0, 0, 0, 0]).is_err()); +} + +// Test hygiene - make sure that `i8` being shadowed doesn't cause problems for +// the code emitted by the derive. +type i8 = bool; + +const THREE: ::core::primitive::i8 = 3; + +#[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)] +#[repr(i8)] +enum Blah { + A = 1, + B = 0, + C = 1 + 2, + D = 3 + THREE, +} + +util_assert_impl_all!(Blah: imp::TryFromBytes); + +#[test] +fn test_blah() { + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&1i8)), + imp::Ok(Blah::A) + ); + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&0i8)), + imp::Ok(Blah::B) + ); + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&3i8)), + imp::Ok(Blah::C) + ); + imp::assert_eq!( + ::try_read_from_bytes(imp::IntoBytes::as_bytes(&6i8)), + imp::Ok(Blah::D) + ); + imp::assert!(::try_read_from_bytes(&[]).is_err()); + imp::assert!(::try_read_from_bytes(&[4]).is_err()); + imp::assert!(::try_read_from_bytes(&[0, 0]).is_err()); +} + +#[derive( + Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes, +)] +#[repr(C)] +enum FieldlessButNotUnitOnly { + A, + B(), + C {}, +} + +#[test] +fn test_fieldless_but_not_unit_only() { + const SIZE: usize = ::core::mem::size_of::(); + let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::A); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(FieldlessButNotUnitOnly::A) + ); + let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::B()); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(FieldlessButNotUnitOnly::B()) + ); + let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::C {}); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(FieldlessButNotUnitOnly::C {}) + ); + imp::assert!(::try_read_from_bytes( + &[0xFF; SIZE][..] + ) + .is_err()); +} + +#[derive( + Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes, +)] +#[repr(C)] +enum WeirdDiscriminants { + A = -7, + B, + C = 33, +} + +#[test] +fn test_weird_discriminants() { + const SIZE: usize = ::core::mem::size_of::(); + let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::A); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(WeirdDiscriminants::A) + ); + let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::B); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(WeirdDiscriminants::B) + ); + let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::C); + imp::assert_eq!( + ::try_read_from_bytes(&disc[..]), + imp::Ok(WeirdDiscriminants::C) + ); + imp::assert!( + ::try_read_from_bytes(&[0xFF; SIZE][..]).is_err() + ); +} + +// Technically non-portable since this is only `IntoBytes` if the discriminant +// is an `i32` or `u32`, but we'll cross that bridge when we get to it... +#[derive( + Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes, +)] +#[repr(C)] +enum HasFields { + A(u32), + B { foo: ::core::num::NonZeroU32 }, +} + +#[test] +fn test_has_fields() { + const SIZE: usize = ::core::mem::size_of::(); + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFields::A(10)); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFields::A(10)), + ); + + let bytes: [u8; SIZE] = + ::zerocopy::transmute!(HasFields::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFields::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }), + ); +} + +#[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)] +#[repr(C, align(16))] +enum HasFieldsAligned { + A(u32), + B { foo: ::core::num::NonZeroU32 }, +} + +util_assert_impl_all!(HasFieldsAligned: imp::TryFromBytes); + +#[test] +fn test_has_fields_aligned() { + const SIZE: usize = ::core::mem::size_of::(); + + #[derive(imp::IntoBytes)] + #[repr(C)] + struct BytesOfHasFieldsAligned { + has_fields: HasFields, + padding: [u8; 8], + } + + let wrap = |has_fields| BytesOfHasFieldsAligned { has_fields, padding: [0; 8] }; + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFields::A(10))); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsAligned::A(10)), + ); + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFields::B { + foo: ::core::num::NonZeroU32::new(123456).unwrap() + })); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsAligned::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }), + ); +} + +#[derive( + Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes, +)] +#[repr(u32)] +enum HasFieldsPrimitive { + A(u32), + B { foo: ::core::num::NonZeroU32 }, +} + +#[test] +fn test_has_fields_primitive() { + const SIZE: usize = ::core::mem::size_of::(); + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFieldsPrimitive::A(10)); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsPrimitive::A(10)), + ); + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFieldsPrimitive::B { + foo: ::core::num::NonZeroU32::new(123456).unwrap(), + }); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsPrimitive::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }), + ); +} + +#[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)] +#[repr(u32, align(16))] +enum HasFieldsPrimitiveAligned { + A(u32), + B { foo: ::core::num::NonZeroU32 }, +} + +util_assert_impl_all!(HasFieldsPrimitiveAligned: imp::TryFromBytes); + +#[test] +fn test_has_fields_primitive_aligned() { + const SIZE: usize = ::core::mem::size_of::(); + + #[derive(imp::IntoBytes)] + #[repr(C)] + struct BytesOfHasFieldsPrimitiveAligned { + has_fields: HasFieldsPrimitive, + padding: [u8; 8], + } + + let wrap = |has_fields| BytesOfHasFieldsPrimitiveAligned { has_fields, padding: [0; 8] }; + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFieldsPrimitive::A(10))); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsPrimitiveAligned::A(10)), + ); + + let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFieldsPrimitive::B { + foo: ::core::num::NonZeroU32::new(123456).unwrap() + })); + imp::assert_eq!( + ::try_read_from_bytes(&bytes[..]), + imp::Ok(HasFieldsPrimitiveAligned::B { + foo: ::core::num::NonZeroU32::new(123456).unwrap() + }), + ); +} + +#[derive(imp::TryFromBytes)] +#[repr(align(4), u32)] +enum HasReprAlignFirst { + A, + B, +} + +util_assert_impl_all!(HasReprAlignFirst: imp::TryFromBytes); + +#[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)] +#[repr(u8)] +enum Complex { + UnitLike, + StructLike { a: u8, b: u16 }, + TupleLike(bool, char), +} + +util_assert_impl_all!(Complex: imp::TryFromBytes); + +#[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)] +#[repr(u8)] +enum ComplexWithGenerics { + UnitLike, + StructLike { a: u8, b: X }, + TupleLike(bool, Y), +} + +util_assert_impl_all!(ComplexWithGenerics: imp::TryFromBytes); + +#[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)] +#[repr(C)] +enum GenericWithLifetimes<'a, 'b, X: 'a, Y: 'b> { + Foo(::core::marker::PhantomData<&'a X>), + Bar(::core::marker::PhantomData<&'b Y>), +} + +#[derive(Clone, Copy, imp::TryFromBytes)] +struct A; + +#[derive(imp::TryFromBytes)] +#[repr(C)] +enum B { + A(A), + A2 { a: A }, +} + +#[derive(imp::TryFromBytes)] +#[repr(u8)] +enum FooU8 { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, +} + +#[test] +fn test_trivial_is_bit_valid() { + // Though we don't derive `FromBytes`, `FooU8` *could* soundly implement + // `FromBytes`. Therefore, `TryFromBytes` derive's `is_bit_valid` impl is + // trivial - it unconditionally returns `true`. + util_assert_not_impl_any!(FooU8: imp::FromBytes); + util::test_trivial_is_bit_valid::(); +} + +#[deny(non_camel_case_types)] +mod issue_2051 { + use super::*; + + // Test that the `non_camel_case_types` lint isn't triggered by generated code. + // Prevents regressions of #2051. + #[repr(u32)] + #[derive(imp::TryFromBytes)] + #[allow(non_camel_case_types)] + pub enum Code { + I32_ADD, + I32_SUB, + I32_MUL, + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/enum_unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,49 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// An enum is `Unaligned` if: +// - No `repr(align(N > 1))` +// - `repr(u8)` or `repr(i8)` + +#[derive(imp::Unaligned)] +#[repr(u8)] +enum Foo { + A, +} + +util_assert_impl_all!(Foo: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(i8)] +enum Bar { + A, +} + +util_assert_impl_all!(Bar: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(u8, align(1))] +enum Baz { + A, +} + +util_assert_impl_all!(Baz: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(i8, align(1))] +enum Blah { + B, +} + +util_assert_impl_all!(Blah: imp::Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/eq.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/eq.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/eq.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/eq.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::Debug, imp::IntoBytes, imp::Immutable, imp::ByteEq)] +#[repr(C)] +struct Struct { + a: u64, + b: u32, + c: u32, +} + +util_assert_impl_all!(Struct: imp::IntoBytes, imp::PartialEq, imp::Eq); + +#[test] +fn test_eq() { + use imp::{assert_eq, assert_ne}; + let a = Struct { a: 10, b: 15, c: 20 }; + let b = Struct { a: 10, b: 15, c: 25 }; + assert_eq!(a, a); + assert_ne!(a, b); + assert_ne!(b, a); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/hash.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hash.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/hash.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hash.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::IntoBytes, imp::Immutable, imp::ByteHash)] +#[repr(C)] +struct Struct { + a: u64, + b: u32, + c: u32, +} + +util_assert_impl_all!(Struct: imp::IntoBytes, imp::hash::Hash); + +#[test] +fn test_hash() { + use imp::{ + hash::{Hash, Hasher}, + DefaultHasher, + }; + fn hash(val: impl Hash) -> u64 { + let mut hasher = DefaultHasher::new(); + val.hash(&mut hasher); + hasher.finish() + } + hash(Struct { a: 10, b: 15, c: 20 }); + hash(&[Struct { a: 10, b: 15, c: 20 }, Struct { a: 5, b: 4, c: 3 }]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/hygiene.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hygiene.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/hygiene.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/hygiene.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// Make sure that macro hygiene will ensure that when we reference "zerocopy", +// that will work properly even if they've renamed the crate and have not +// imported its traits. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +extern crate zerocopy as _zerocopy; + +#[derive(_zerocopy::KnownLayout, _zerocopy::FromBytes, _zerocopy::Unaligned)] +#[repr(C)] +struct TypeParams<'a, T, I: imp::Iterator> { + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [::core::primitive::u8]>, + f: imp::PhantomData<&'static ::core::primitive::str>, + g: imp::PhantomData, +} + +util_assert_impl_all!( + TypeParams<'static, (), imp::IntoIter<()>>: + _zerocopy::KnownLayout, + _zerocopy::FromZeros, + _zerocopy::FromBytes, + _zerocopy::Unaligned +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/include.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/include.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/include.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/include.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,129 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// ON THE PRELUDE: All of the tests in this directory (excepting UI tests) +// disable the prelude via `#![no_implicit_prelude]`. This ensures that all code +// emitted by our derives doesn't accidentally assume that the prelude is +// included, which helps ensure that items are referred to by absolute path, +// which in turn ensures that these items can't accidentally refer to names +// which have been shadowed. For example, the code `x == None` could behave +// incorrectly if, in the scope in which the derive is invoked, `None` has been +// shadowed by `CONST None: Option = Some(1)`. +// +// `mod imp` allows us to import items and refer to them in this module without +// introducing the risk that this hides bugs in which derive-emitted code uses +// names which are not fully-qualified. For such a bug to manifest, it would +// need to be of the form `imp::Foo`, which is unlikely to happen by accident. +mod imp { + // Since this file is included in every test file, and since not every test + // file uses every item here, we allow unused imports to avoid generating + // warnings. + #[allow(unused)] + pub use { + ::core::{ + self, assert_eq, assert_ne, + cell::UnsafeCell, + convert::TryFrom, + hash, + marker::PhantomData, + mem::{ManuallyDrop, MaybeUninit}, + option::IntoIter, + prelude::v1::*, + primitive::*, + }, + ::std::{collections::hash_map::DefaultHasher, prelude::v1::*}, + ::zerocopy::*, + }; +} + +// These items go in their own module (rather than the top level) for the same +// reason that we use `mod imp` above. See its comment for more details. +pub mod util { + /// A type that doesn't implement any zerocopy traits. + pub struct NotZerocopy(pub T); + + /// A `u16` with alignment 2. + /// + /// Though `u16` has alignment 2 on some platforms, it's not guaranteed. By + /// contrast, `util::AU16` is guaranteed to have alignment 2. + #[derive( + super::imp::KnownLayout, + super::imp::Immutable, + super::imp::FromBytes, + super::imp::IntoBytes, + Copy, + Clone, + )] + #[repr(C, align(2))] + pub struct AU16(pub u16); + + // Since we can't import these by path (ie, `util::assert_impl_all!`), use a + // name prefix to ensure our derive-emitted code isn't accidentally relying + // on `assert_impl_all!` being in scope. + #[macro_export] + macro_rules! util_assert_impl_all { + ($type:ty: $($trait:path),+ $(,)?) => { + const _: fn() = || { + use ::core::prelude::v1::*; + ::static_assertions::assert_impl_all!($type: $($trait),+); + }; + }; + } + + // Since we can't import these by path (ie, `util::assert_not_impl_any!`), + // use a name prefix to ensure our derive-emitted code isn't accidentally + // relying on `assert_not_impl_any!` being in scope. + #[macro_export] + macro_rules! util_assert_not_impl_any { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + use ::core::prelude::v1::*; + ::static_assertions::assert_not_impl_any!($x: $($t),+); + }; + }; + } + + #[macro_export] + macro_rules! test_trivial_is_bit_valid { + ($x:ty => $name:ident) => { + #[test] + fn $name() { + util::test_trivial_is_bit_valid::<$x>(); + } + }; + } + + // Under some circumstances, our `TryFromBytes` derive generates a trivial + // `is_bit_valid` impl that unconditionally returns `true`. This test + // attempts to validate that this is, indeed, the behavior of our + // `TryFromBytes` derive. It is not foolproof, but is likely to catch some + // mistakes. + // + // As of this writing, this happens when deriving `TryFromBytes` thanks to a + // top-level `#[derive(FromBytes)]`. + pub fn test_trivial_is_bit_valid() { + // This test works based on the insight that a trivial `is_bit_valid` + // impl should never load any bytes from memory. Thus, while it is + // technically a violation of `is_bit_valid`'s safety precondition to + // pass a pointer to uninitialized memory, the `is_bit_valid` impl we + // expect our derives to generate should never touch this memory, and + // thus should never exhibit UB. By contrast, if our derives are + // spuriously generating non-trivial `is_bit_valid` impls, this should + // cause UB which may be caught by Miri. + + let buf = super::imp::MaybeUninit::::uninit(); + let ptr = super::imp::Ptr::from_ref(&buf); + // SAFETY: This is intentionally unsound; see the preceding comment. + let ptr = unsafe { ptr.assume_initialized() }; + + // SAFETY: `T` and `MaybeUninit` have the same layout, so this is a + // size-preserving cast. It is also a provenance-preserving cast. + let ptr = unsafe { ptr.cast_unsized_unchecked(|p| p.cast_sized()) }; + assert!(::is_bit_valid(ptr)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/issue_2117.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/issue_2117.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/issue_2117.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/issue_2117.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] +#![forbid(unexpected_cfgs)] + +include!("include.rs"); + +// Make sure no unexpected `cfg`s are emitted by our derives (see #2117). + +#[derive(imp::KnownLayout)] +#[repr(C)] +pub struct Test(pub [u8; 32]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/paths_and_modules.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/paths_and_modules.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/paths_and_modules.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/paths_and_modules.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// Ensure that types that are use'd and types that are referenced by path work. + +mod foo { + use super::*; + + #[derive(imp::FromBytes, imp::IntoBytes, imp::Unaligned)] + #[repr(C)] + pub struct Foo { + foo: u8, + } + + #[derive(imp::FromBytes, imp::IntoBytes, imp::Unaligned)] + #[repr(C)] + pub struct Bar { + bar: u8, + } +} + +use foo::Foo; + +#[derive(imp::FromBytes, imp::IntoBytes, imp::Unaligned)] +#[repr(C)] +struct Baz { + foo: Foo, + bar: foo::Bar, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/priv_in_pub.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/priv_in_pub.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/priv_in_pub.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/priv_in_pub.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// FIXME(#847): Make this test succeed on earlier Rust versions. +#[::rustversion::stable(1.59)] +mod test { + use super::*; + + // These derives do not result in E0446 as of Rust 1.59.0, because of + // https://github.com/rust-lang/rust/pull/90586. + // + // This change eliminates one of the major downsides of emitting `where` + // bounds for field types (i.e., the emission of E0446 for private field + // types). + + #[derive(imp::KnownLayout, imp::IntoBytes, imp::FromZeros, imp::FromBytes, imp::Unaligned)] + #[repr(C)] + pub struct Public(Private); + + #[derive(imp::KnownLayout, imp::IntoBytes, imp::FromZeros, imp::FromBytes, imp::Unaligned)] + #[repr(C)] + struct Private(()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,77 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `FromBytes` if: +// - all fields are `FromBytes` + +#[derive(imp::FromBytes)] +struct Zst; + +util_assert_impl_all!(Zst: imp::FromBytes); +test_trivial_is_bit_valid!(Zst => test_zst_trivial_is_bit_valid); + +#[derive(imp::FromBytes)] +struct One { + a: u8, +} + +util_assert_impl_all!(One: imp::FromBytes); +test_trivial_is_bit_valid!(One => test_one_trivial_is_bit_valid); + +#[derive(imp::FromBytes)] +struct Two { + a: u8, + b: Zst, +} + +util_assert_impl_all!(Two: imp::FromBytes); +test_trivial_is_bit_valid!(Two => test_two_trivial_is_bit_valid); + +#[derive(imp::FromBytes)] +struct Unsized { + a: [u8], +} + +util_assert_impl_all!(Unsized: imp::FromBytes); + +#[derive(imp::FromBytes)] +struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [::core::primitive::u8]>, + d: imp::PhantomData<&'static ::core::primitive::str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromBytes); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::FromBytes); +util_assert_impl_all!(TypeParams<'static, [util::AU16], imp::IntoIter<()>>: imp::FromBytes); +test_trivial_is_bit_valid!(TypeParams<'static, (), imp::IntoIter<()>> => test_type_params_trivial_is_bit_valid); + +// Deriving `FromBytes` should work if the struct has bounded parameters. + +#[derive(imp::FromBytes)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::FromBytes, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::FromBytes; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromBytes); +test_trivial_is_bit_valid!(WithParams<'static, 'static, u8, 42> => test_with_params_trivial_is_bit_valid); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_from_zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `FromZeros` if: +// - all fields are `FromZeros` + +#[derive(imp::FromZeros)] +struct Zst; + +util_assert_impl_all!(Zst: imp::FromZeros); + +#[derive(imp::FromZeros)] +struct One { + a: bool, +} + +util_assert_impl_all!(One: imp::FromZeros); + +#[derive(imp::FromZeros)] +struct Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::FromZeros); + +#[derive(imp::FromZeros)] +struct Unsized { + a: [u8], +} + +util_assert_impl_all!(Unsized: imp::FromZeros); + +#[derive(imp::FromZeros)] +struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [u8]>, + d: imp::PhantomData<&'static str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromZeros); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::FromZeros); +util_assert_impl_all!(TypeParams<'static, [util::AU16], imp::IntoIter<()>>: imp::FromZeros); + +// Deriving `FromZeros` should work if the struct has bounded parameters. + +#[derive(imp::FromZeros)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::FromZeros, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::FromZeros; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromZeros); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_known_layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_known_layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_known_layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_known_layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,114 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +extern crate rustversion; + +include!("include.rs"); + +#[derive(imp::KnownLayout)] +struct Zst; + +util_assert_impl_all!(Zst: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +struct One { + a: bool, +} + +util_assert_impl_all!(One: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +struct Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +struct TypeParams<'a, T, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [::core::primitive::u8]>, + d: imp::PhantomData<&'static ::core::primitive::str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::KnownLayout); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::KnownLayout); + +// Deriving `KnownLayout` should work if the struct has bounded parameters. +// +// N.B. We limit this test to rustc >= 1.62, since earlier versions of rustc ICE +// when `KnownLayout` is derived on a `repr(C)` struct whose trailing field +// contains non-static lifetimes. +#[rustversion::since(1.62)] +const _: () = { + #[derive(imp::KnownLayout)] + #[repr(C)] + struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::KnownLayout, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, + ) + where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::KnownLayout; + + util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::KnownLayout); +}; + +const _: () = { + // Similar to the previous test, except that the trailing field contains + // only static lifetimes. This is exercisable on all supported toolchains. + + #[derive(imp::KnownLayout)] + #[repr(C)] + struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::KnownLayout, const N: usize>( + &'a &'b [T; N], + imp::PhantomData<&'static ()>, + ) + where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::KnownLayout; + + util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::KnownLayout); +}; + +// Deriving `KnownLayout` should work if the struct references `Self`. See +// #2116. + +#[derive(imp::KnownLayout)] +#[repr(C)] +struct WithSelfReference { + leading: [u8; Self::N], + trailing: [[u8; Self::N]], +} + +impl WithSelfReference { + const N: usize = 42; +} + +util_assert_impl_all!(WithSelfReference: imp::KnownLayout); + +// Deriving `KnownLayout` should work with generic `repr(packed)` types. See +// #2302. + +#[derive(imp::KnownLayout)] +#[repr(C, packed)] +struct Packet

{ + payload: P, +} + +util_assert_impl_all!(Packet: imp::KnownLayout); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_no_cell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_no_cell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_no_cell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_no_cell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,97 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(imp::Immutable)] +struct Zst; + +util_assert_impl_all!(Zst: imp::Immutable); + +#[derive(imp::Immutable)] +struct One { + a: bool, +} + +util_assert_impl_all!(One: imp::Immutable); + +#[derive(imp::Immutable)] +struct Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::Immutable); + +#[derive(imp::Immutable)] +struct Three { + a: [u8], +} + +util_assert_impl_all!(Three: imp::Immutable); + +#[derive(imp::Immutable)] +struct Four<'a> { + field: &'a imp::UnsafeCell, +} + +util_assert_impl_all!(Four<'static>: imp::Immutable); + +#[derive(imp::Immutable)] +struct TypeParams<'a, T, U, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [::core::primitive::u8]>, + d: imp::PhantomData<&'static ::core::primitive::str>, + e: imp::PhantomData, + f: imp::PhantomData, + g: T, +} + +util_assert_impl_all!(TypeParams<'static, (), (), imp::IntoIter<()>>: imp::Immutable); +util_assert_impl_all!(TypeParams<'static, util::AU16, util::AU16, imp::IntoIter<()>>: imp::Immutable); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::UnsafeCell, imp::IntoIter<()>>: imp::Immutable); +util_assert_not_impl_any!(TypeParams<'static, imp::UnsafeCell<()>, (), imp::IntoIter<()>>: imp::Immutable); +util_assert_not_impl_any!(TypeParams<'static, [imp::UnsafeCell; 0], (), imp::IntoIter<()>>: imp::Immutable); +util_assert_not_impl_any!(TypeParams<'static, (), (), imp::IntoIter>>: imp::Immutable); + +trait Trait { + type Assoc; +} + +impl Trait for imp::UnsafeCell { + type Assoc = T; +} + +#[derive(imp::Immutable)] +struct WithAssocType { + field: ::Assoc, +} + +util_assert_impl_all!(WithAssocType>: imp::Immutable); + +// Deriving `Immutable` should work if the struct has bounded parameters. + +#[derive(imp::Immutable)] +#[repr(C)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::Immutable, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, + imp::PhantomData>, + &'a imp::UnsafeCell<()>, +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Immutable; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::Immutable); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_to_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_to_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_to_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_to_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,203 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `IntoBytes` if: +// - all fields are `IntoBytes` +// - `repr(C)` or `repr(transparent)` and +// - no padding (size of struct equals sum of size of field types) +// - `repr(packed)` + +#[derive(imp::IntoBytes)] +#[repr(C)] +struct CZst; + +util_assert_impl_all!(CZst: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C)] +struct C { + a: u8, + b: u8, + c: util::AU16, +} + +util_assert_impl_all!(C: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C)] +struct SyntacticUnsized { + a: u8, + b: u8, + c: [util::AU16], +} + +util_assert_impl_all!(C: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(transparent)] +struct Transparent { + a: u8, + b: CZst, +} + +util_assert_impl_all!(Transparent: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(transparent)] +struct TransparentGeneric { + a: CZst, + b: T, +} + +util_assert_impl_all!(TransparentGeneric: imp::IntoBytes); +util_assert_impl_all!(TransparentGeneric<[u64]>: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +struct CZstPacked; + +util_assert_impl_all!(CZstPacked: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +struct CPacked { + a: u8, + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. + b: u16, +} + +util_assert_impl_all!(CPacked: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed(2))] +// The same caveats as for CPacked apply - we're assuming u64 is at least +// 4-byte aligned by default. Without packed(2), this should fail, as there +// would be padding between a/b assuming u64 is 4+ byte aligned. +struct CPacked2 { + a: u16, + b: u64, +} + +util_assert_impl_all!(CPacked2: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +struct CPackedGeneric { + t: T, + // Unsized types stored in `repr(packed)` structs must not be dropped + // because dropping them in-place might be unsound depending on the + // alignment of the outer struct. Sized types can be dropped by first being + // moved to an aligned stack variable, but this isn't possible with unsized + // types. + u: imp::ManuallyDrop, +} + +util_assert_impl_all!(CPackedGeneric: imp::IntoBytes); +util_assert_impl_all!(CPackedGeneric: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(packed)] +struct PackedGeneric { + t: T, + // Unsized types stored in `repr(packed)` structs must not be dropped + // because dropping them in-place might be unsound depending on the + // alignment of the outer struct. Sized types can be dropped by first being + // moved to an aligned stack variable, but this isn't possible with unsized + // types. + u: imp::ManuallyDrop, +} + +util_assert_impl_all!(PackedGeneric: imp::IntoBytes); +util_assert_impl_all!(PackedGeneric: imp::IntoBytes); + +// This test is non-portable, but works so long as Rust happens to lay this +// struct out with no padding. +#[derive(imp::IntoBytes)] +struct Unpacked { + a: u8, + b: u8, +} + +util_assert_impl_all!(Unpacked: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C)] +struct ReprCGenericOneField { + t: T, +} + +// Even though `ReprCGenericOneField` has generic type arguments, since it only +// has one field, we don't require that its field types implement `Unaligned`. +util_assert_impl_all!(ReprCGenericOneField: imp::IntoBytes); +util_assert_impl_all!(ReprCGenericOneField<[util::AU16]>: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C)] +struct ReprCGenericMultipleFields { + t: T, + u: U, +} + +// Since `ReprCGenericMultipleFields` is generic and has more than one field, +// all field types must implement `Unaligned`. +util_assert_impl_all!(ReprCGenericMultipleFields: imp::IntoBytes); +util_assert_impl_all!(ReprCGenericMultipleFields: imp::IntoBytes); +util_assert_not_impl_any!(ReprCGenericMultipleFields: imp::IntoBytes); +util_assert_not_impl_any!(ReprCGenericMultipleFields: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(transparent)] +struct Unsized { + a: [u8], +} + +util_assert_impl_all!(Unsized: imp::IntoBytes); + +// Deriving `IntoBytes` should work if the struct has bounded parameters. + +#[derive(imp::IntoBytes)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::IntoBytes, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::IntoBytes; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::IntoBytes); + +// Test for the failure reported in #1182. + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +pub struct IndexEntryFlags(u8); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +pub struct IndexEntry { + block_number: imp::native_endian::U64, + flags: IndexEntryFlags, + block_id: [u8; SIZE_BLOCK_ID], +} + +util_assert_impl_all!(IndexEntry<0>: imp::IntoBytes); +util_assert_impl_all!(IndexEntry<1>: imp::IntoBytes); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_try_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_try_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_try_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_try_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,259 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `imp::TryFromBytes` if: +// - all fields are `imp::TryFromBytes` + +#[test] +fn zst() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&()); + let candidate = candidate.forget_aligned(); + // SAFETY: `&()` trivially consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = <() as imp::TryFromBytes>::is_bit_valid(candidate); + imp::assert!(is_bit_valid); +} + +#[derive(imp::TryFromBytes)] +#[repr(C)] +struct One { + a: u8, +} + +util_assert_impl_all!(One: imp::TryFromBytes); + +#[test] +fn one() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&One { a: 42 }); + let candidate = candidate.forget_aligned(); + // SAFETY: `&One` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate); + imp::assert!(is_bit_valid); +} + +#[derive(imp::TryFromBytes)] +#[repr(C)] +struct Two { + a: bool, + b: (), +} + +util_assert_impl_all!(Two: imp::TryFromBytes); + +#[test] +fn two() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&Two { a: false, b: () }); + let candidate = candidate.forget_aligned(); + // SAFETY: `&Two` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate); + imp::assert!(is_bit_valid); +} + +#[test] +fn two_bad() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + let candidate = candidate.forget_aligned(); + // SAFETY: `&Two` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { candidate.cast_unsized_unchecked(|p| p.cast::()) }; + + // SAFETY: `candidate`'s referent is as-initialized as `Two`. + let candidate = unsafe { candidate.assume_initialized() }; + + let is_bit_valid = ::is_bit_valid(candidate); + imp::assert!(!is_bit_valid); +} + +#[derive(imp::TryFromBytes)] +#[repr(C)] +struct Unsized { + a: [u8], +} + +util_assert_impl_all!(Unsized: imp::TryFromBytes); + +#[test] +fn un_sized() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&[16, 12, 42][..]); + let candidate = candidate.forget_aligned(); + // SAFETY: `&Unsized` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { + candidate.cast_unsized_unchecked(|p| { + let ptr = + imp::core::ptr::NonNull::new_unchecked(p.as_non_null().as_ptr() as *mut Unsized); + ::zerocopy::pointer::PtrInner::new(ptr) + }) + }; + + // SAFETY: `candidate`'s referent is as-initialized as `Two`. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate); + imp::assert!(is_bit_valid); +} + +#[derive(imp::TryFromBytes)] +#[repr(C)] +struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [u8]>, + d: imp::PhantomData<&'static str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::TryFromBytes); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::TryFromBytes); +util_assert_impl_all!(TypeParams<'static, [util::AU16], imp::IntoIter<()>>: imp::TryFromBytes); + +// Deriving `imp::TryFromBytes` should work if the struct has bounded parameters. + +#[derive(imp::TryFromBytes)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::TryFromBytes, const N: usize>( + imp::PhantomData<&'a &'b ()>, + [T], +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::TryFromBytes; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::TryFromBytes); + +#[derive(imp::FromBytes)] +#[repr(C)] +struct MaybeFromBytes(T); + +#[test] +fn test_maybe_from_bytes() { + // When deriving `FromBytes` on a type with no generic parameters, we emit a + // trivial `is_bit_valid` impl that always returns true. This test confirms + // that we *don't* spuriously do that when generic parameters are present. + + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + let candidate = candidate.bikeshed_recall_initialized_from_bytes(); + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = + unsafe { candidate.cast_unsized_unchecked(|p| p.cast::>()) }; + + // SAFETY: `[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = as imp::TryFromBytes>::is_bit_valid(candidate); + imp::assert!(!is_bit_valid); +} + +#[derive(Debug, PartialEq, Eq, imp::TryFromBytes, imp::Immutable, imp::KnownLayout)] +#[repr(C, packed)] +struct CPacked { + a: u8, + // NOTE: The `u32` type is not guaranteed to have alignment 4, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u32` here. Luckily, these tests run in CI on + // platforms on which `u32` has alignment 4, so this isn't that big of a + // deal. + b: u32, +} + +#[test] +fn c_packed() { + let candidate = &[42u8, 0xFF, 0xFF, 0xFF, 0xFF]; + let converted = ::try_ref_from_bytes(candidate); + imp::assert_eq!(converted, imp::Ok(&CPacked { a: 42, b: u32::MAX })); +} + +#[derive(imp::TryFromBytes, imp::KnownLayout, imp::Immutable)] +#[repr(C, packed)] +struct CPackedUnsized { + a: u8, + // NOTE: The `u32` type is not guaranteed to have alignment 4, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u32` here. Luckily, these tests run in CI on + // platforms on which `u32` has alignment 4, so this isn't that big of a + // deal. + b: [u32], +} + +#[test] +fn c_packed_unsized() { + let candidate = &[42u8, 0xFF, 0xFF, 0xFF, 0xFF]; + let converted = ::try_ref_from_bytes(candidate); + imp::assert!(converted.is_ok()); +} + +#[derive(imp::TryFromBytes)] +#[repr(packed)] +struct PackedUnsized { + a: u8, + // NOTE: The `u32` type is not guaranteed to have alignment 4, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u32` here. Luckily, these tests run in CI on + // platforms on which `u32` has alignment 4, so this isn't that big of a + // deal. + b: [u32], +} + +#[test] +fn packed_unsized() { + let candidate = &[42u8, 0xFF, 0xFF, 0xFF, 0xFF]; + let converted = ::try_ref_from_bytes(candidate); + imp::assert!(converted.is_ok()); + + let candidate = &[42u8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + let converted = ::try_ref_from_bytes(candidate); + imp::assert!(converted.is_err()); + + let candidate = &[42u8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + let converted = ::try_ref_from_bytes(candidate); + imp::assert!(converted.is_ok()); +} + +#[derive(imp::TryFromBytes)] +struct A; + +#[derive(imp::TryFromBytes)] +struct B { + a: A, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/struct_unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `Unaligned` if: +// - `repr(align)` is no more than 1 and either +// - `repr(C)` or `repr(transparent)` and +// - all fields Unaligned +// - `repr(packed)` + +#[derive(imp::Unaligned)] +#[repr(C)] +struct Foo { + a: u8, +} + +util_assert_impl_all!(Foo: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(transparent)] +struct Bar { + a: u8, +} + +util_assert_impl_all!(Bar: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(packed)] +struct Baz { + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. + a: u16, +} + +util_assert_impl_all!(Baz: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(C, align(1))] +struct FooAlign { + a: u8, +} + +util_assert_impl_all!(FooAlign: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(transparent)] +struct Unsized { + a: [u8], +} + +util_assert_impl_all!(Unsized: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(C)] +struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [::core::primitive::u8]>, + d: imp::PhantomData<&'static ::core::primitive::str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::Unaligned); +util_assert_impl_all!(TypeParams<'static, ::core::primitive::u8, imp::IntoIter<()>>: imp::Unaligned); +util_assert_impl_all!(TypeParams<'static, [::core::primitive::u8], imp::IntoIter<()>>: imp::Unaligned); + +// Deriving `Unaligned` should work if the struct has bounded parameters. + +#[derive(imp::Unaligned)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::Unaligned, const N: usize>( + [T; N], + imp::PhantomData<&'a &'b ()>, +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Unaligned; + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/trybuild.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/trybuild.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/trybuild.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/trybuild.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,60 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#![allow(clippy::uninlined_format_args)] + +use std::env; + +use testutil::set_rustflags_w_warnings; + +fn test(subdir: &str) { + let version = testutil::ToolchainVersion::extract_from_pwd().unwrap(); + // See the doc comment on this method for an explanation of what this does + // and why we store source files in different directories. + let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning(); + + // Set `-Wwarnings` in the `RUSTFLAGS` environment variable to ensure that + // `.stderr` files reflect what the typical user would encounter. + set_rustflags_w_warnings(); + + let t = trybuild::TestCases::new(); + t.compile_fail(format!("tests/{}/{}/*.rs", source_files_dirname, subdir)); +} + +#[test] +#[cfg_attr(miri, ignore)] +fn ui() { + test(""); + + // This tests the behavior when `--cfg zerocopy_derive_union_into_bytes` is + // not present, so remove it. If this logic is wrong, that's fine - it will + // exhibit as a test failure that we can debug at that point. + let rustflags = env::var("RUSTFLAGS").unwrap(); + let new_rustflags = rustflags.replace("--cfg zerocopy_derive_union_into_bytes", ""); + + // SAFETY: None of our code is concurrently accessinv env vars. It's + // possible that the test framework has spawned other threads that are + // concurrently accessing env vars, but we can't do anything about that. + #[allow(unused_unsafe)] // `set_var` is safe on our MSRV. + unsafe { + env::set_var("RUSTFLAGS", new_rustflags) + }; + + test("union_into_bytes_cfg"); + + // Reset RUSTFLAGS in case we later add other tests which rely on its value. + // This isn't strictly necessary, but it's easier to add this now when we're + // thinking about the semantics of these env vars than to debug later when + // we've forgotten about it. + // + // SAFETY: See previous safety comment. + #[allow(unused_unsafe)] // `set_var` is safe on our MSRV. + unsafe { + env::set_var("RUSTFLAGS", rustflags) + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use core::marker::PhantomData; + +use zerocopy::{FromBytes, FromZeros, IntoBytes, TryFromBytes, Unaligned}; + +use self::util::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(IntoBytes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +util_assert_impl_all!(TransparentStruct: TryFromBytes); +util_assert_impl_all!(TransparentStruct: FromZeros); +util_assert_impl_all!(TransparentStruct: FromBytes); +util_assert_impl_all!(TransparentStruct: IntoBytes); +util_assert_impl_all!(TransparentStruct: Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:34:1 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `zerocopy::TryFromBytes` for `TransparentStruct` + --> tests/ui-msrv/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:34:1 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `::static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:35:1 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `FromZeros` for `TransparentStruct` + --> tests/ui-msrv/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:35:1 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `::static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:36:1 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `zerocopy::FromBytes` for `TransparentStruct` + --> tests/ui-msrv/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:36:1 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `::static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:37:1 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `zerocopy::IntoBytes` for `TransparentStruct` + --> tests/ui-msrv/derive_transparent.rs:24:10 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:37:1 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `::static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:38:1 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `zerocopy::Unaligned` for `TransparentStruct` + --> tests/ui-msrv/derive_transparent.rs:24:32 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:38:1 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `::static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,577 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// +// Generic errors +// + +#[derive(FromBytes)] +#[repr("foo")] +enum Generic1 { + A, +} + +#[derive(FromBytes)] +#[repr(foo)] +enum Generic2 { + A, +} + +#[derive(FromBytes)] +#[repr(transparent)] +enum Generic3 { + A, +} + +#[derive(FromBytes)] +#[repr(u8, u16)] +enum Generic4 { + A, +} + +#[derive(FromBytes)] +enum Generic5 { + A, +} + +// +// Immutable errors +// + +#[derive(Immutable)] +enum Immutable1 { + A(core::cell::UnsafeCell<()>), +} + +#[derive(Immutable)] +enum Never {} + +#[derive(Immutable)] +enum Immutable2 { + Uninhabited(Never, core::cell::UnsafeCell), + Inhabited(u8), +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +enum TryFromBytes1 { + A, +} + +#[derive(TryFromBytes)] +enum TryFromBytes2 { + A, + B(u8), +} + +struct NotTryFromBytes; + +#[derive(TryFromBytes)] +#[repr(u8)] +enum TryFromBytes3 { + A(NotTryFromBytes), +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +enum FromZeros1 { + A(u8), +} + +#[derive(FromZeros)] +enum FromZeros2 { + A, + B(u8), +} + +#[derive(FromZeros)] +enum FromZeros3 { + A = 1, + B, +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros4 { + A = 1, + B = 2, +} + +const NEGATIVE_ONE: i8 = -1; + +#[derive(FromZeros)] +#[repr(i8)] +enum FromZeros5 { + A = NEGATIVE_ONE, + B, +} + +struct NotFromZeros; + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros6 { + A(NotFromZeros), +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros7 { + A = 1, + B(NotFromZeros), +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +enum FromBytes1 { + A, +} + +#[derive(FromBytes)] +#[repr(C)] +enum FromBytes2 { + A, +} + +#[derive(FromBytes)] +#[repr(usize)] +enum FromBytes3 { + A, +} + +#[derive(FromBytes)] +#[repr(isize)] +enum FromBytes4 { + A, +} + +#[derive(FromBytes)] +#[repr(u32)] +enum FromBytes5 { + A, +} + +#[derive(FromBytes)] +#[repr(i32)] +enum FromBytes6 { + A, +} + +#[derive(FromBytes)] +#[repr(u64)] +enum FromBytes7 { + A, +} + +#[derive(FromBytes)] +#[repr(i64)] +enum FromBytes8 { + A, +} + +#[derive(FromBytes)] +#[repr(u8)] +enum FooU8 { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255(bool), +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +enum Unaligned1 { + A, +} + +#[derive(Unaligned)] +#[repr(u16)] +enum Unaligned2 { + A, +} + +#[derive(Unaligned)] +#[repr(i16)] +enum Unaligned3 { + A, +} + +#[derive(Unaligned)] +#[repr(u32)] +enum Unaligned4 { + A, +} + +#[derive(Unaligned)] +#[repr(i32)] +enum Unaligned5 { + A, +} + +#[derive(Unaligned)] +#[repr(u64)] +enum Unaligned6 { + A, +} + +#[derive(Unaligned)] +#[repr(i64)] +enum Unaligned7 { + A, +} + +#[derive(Unaligned)] +#[repr(usize)] +enum Unaligned8 { + A, +} + +#[derive(Unaligned)] +#[repr(isize)] +enum Unaligned9 { + A, +} + +#[derive(Unaligned)] +#[repr(u8, align(2))] +enum Unaligned10 { + A, +} + +#[derive(Unaligned)] +#[repr(i8, align(2))] +enum Unaligned11 { + A, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +enum Unaligned12 { + A, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +enum Unaligned13 { + A, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes1 { + A, + B(u8), +} + +#[derive(IntoBytes)] +#[repr(C, align(4))] +struct Align4IntoBytes(u32); + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes2 { + A(Align4IntoBytes), +} + +#[derive(IntoBytes)] +#[repr(u32)] +enum IntoBytes3 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes4 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes5 { + A(u32), +} + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes6 { + A(T), +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,406 @@ +error: unrecognized representation hint + --> tests/ui-msrv/enum.rs:19:8 + | +19 | #[repr("foo")] + | ^^^^^ + +error: unrecognized representation hint + --> tests/ui-msrv/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:30:10 + | +30 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-msrv/enum.rs:37:12 + | +37 | #[repr(u8, u16)] + | ^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:42:10 + | +42 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:69:10 + | +69 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:74:10 + | +74 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:92:10 + | +92 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:97:10 + | +97 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:103:10 + | +103 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-msrv/enum.rs:110:1 + | +110 | / #[repr(u8)] +111 | | enum FromZeros4 { +112 | | A = 1, +113 | | B = 2, +114 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` +help: This enum has discriminants which are not literal integers. One of those may define or imply which variant has a discriminant of zero. Use a literal integer to define or imply the variant with a discriminant of zero. + --> tests/ui-msrv/enum.rs:119:1 + | +119 | / #[repr(i8)] +120 | | enum FromZeros5 { +121 | | A = NEGATIVE_ONE, +122 | | B, +123 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-msrv/enum.rs:134:1 + | +134 | / #[repr(u8)] +135 | | enum FromZeros7 { +136 | | A = 1, +137 | | B(NotFromZeros), +138 | | } + | |_^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:144:10 + | +144 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:150:8 + | +150 | #[repr(C)] + | ^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:156:8 + | +156 | #[repr(usize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:162:8 + | +162 | #[repr(isize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:168:8 + | +168 | #[repr(u32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:174:8 + | +174 | #[repr(i32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:180:8 + | +180 | #[repr(u64)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-msrv/enum.rs:186:8 + | +186 | #[repr(i64)] + | ^^^ + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:456:10 + | +456 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:462:10 + | +462 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:468:10 + | +468 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:474:10 + | +474 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:480:10 + | +480 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:486:10 + | +486 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:492:10 + | +492 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:498:10 + | +498 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/enum.rs:504:10 + | +504 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-msrv/enum.rs:511:12 + | +511 | #[repr(u8, align(2))] + | ^^^^^ + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-msrv/enum.rs:517:12 + | +517 | #[repr(i8, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/enum.rs:523:18 + | +523 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/enum.rs:529:18 + | +529 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:562:10 + | +562 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/enum.rs:568:10 + | +568 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> tests/ui-msrv/enum.rs:576:7 + | +576 | A(T), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + +error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants + --> tests/ui-msrv/enum.rs:136:9 + | +136 | A = 1, + | ^ disallowed custom discriminant +137 | B(NotFromZeros), + | --------------- tuple variant defined here + | + = note: see issue #60553 for more information + +error[E0565]: meta item in `repr` must be an identifier + --> tests/ui-msrv/enum.rs:19:8 + | +19 | #[repr("foo")] + | ^^^^^ + +error[E0552]: unrecognized representation hint + --> tests/ui-msrv/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + +error[E0566]: conflicting representation hints + --> tests/ui-msrv/enum.rs:37:8 + | +37 | #[repr(u8, u16)] + | ^^ ^^^ + | + = note: `#[deny(conflicting_repr_hints)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error[E0277]: the trait bound `UnsafeCell<()>: Immutable` is not satisfied + --> tests/ui-msrv/enum.rs:51:10 + | +51 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell<()>` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell: Immutable` is not satisfied + --> tests/ui-msrv/enum.rs:59:10 + | +59 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotTryFromBytes: TryFromBytes` is not satisfied + --> tests/ui-msrv/enum.rs:82:10 + | +82 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotTryFromBytes` + | + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotFromZeros: TryFromBytes` is not satisfied + --> tests/ui-msrv/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotFromZeros` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotFromZeros: FromZeros` is not satisfied + --> tests/ui-msrv/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotFromZeros` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-msrv/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/enum.rs:538:10 + | +538 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/enum.rs:549:10 + | +549 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/enum.rs:555:10 + | +555 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic `Self` types are currently not permitted in anonymous constants + --> tests/ui-msrv/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | +note: not a concrete type + --> tests/ui-msrv/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,272 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +#[derive(FromBytes)] +#[repr(u8)] +enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error: FromBytes only supported on repr(u8) enum with 256 variants + --> tests/ui-msrv/enum_from_bytes_u8_too_few.rs:15:1 + | +15 | / #[repr(u8)] +16 | | enum Foo { +17 | | Variant0, +18 | | Variant1, +... | +271 | | Variant254, +272 | | } + | |_^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::KnownLayout; + +use self::util::util::{NotZerocopy, AU16}; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +struct TryFromBytes1 { + value: NotZerocopy, +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +struct FromZeros1 { + value: NotZerocopy, +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +struct FromBytes1 { + value: NotZerocopy, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + value: NotZerocopy, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned1 { + aligned: AU16, +} + +// This specifically tests a bug we had in an old version of the code in which +// the trait bound would only be enforced for the first field's type. +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned2 { + unaligned: u8, + aligned: AU16, +} + +#[derive(Unaligned)] +#[repr(transparent)] +struct Unaligned3 { + aligned: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,97 @@ +warning: unused import: `zerocopy::KnownLayout` + --> tests/ui-msrv/late_compile_pass.rs:15:5 + | +15 | use zerocopy::KnownLayout; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:29:10 + | +29 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:56:10 + | +56 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:66:10 + | +66 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:74:10 + | +74 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:81:10 + | +81 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::KnownLayout; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// KnownLayout errors +// + +fn assert_kl(_: &T) {} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | N | N | KL04 | +#[derive(KnownLayout)] +struct KL04(u8, T); + +fn test_kl04(kl: &KL04) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | Y | N | KL06 | +#[derive(KnownLayout)] +struct KL06(u8, T); + +fn test_kl06(kl: &KL06) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | N | KL12 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL12(u8, T); + +fn test_kl12(kl: &KL12) { + assert_kl(kl) +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | Y | KL13 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL13(u8, T); + +fn test_kl13(t: T) -> impl KnownLayout { + KL13(0u8, t) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/mid_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,97 @@ +error[E0277]: the trait bound `T: KnownLayout` is not satisfied + --> tests/ui-msrv/mid_compile_pass.rs:59:26 + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T` + | +note: required because of the requirements on the impl of `KnownLayout` for `KL13` + --> tests/ui-msrv/mid_compile_pass.rs:55:10 + | +55 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | +++++++++++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-msrv/mid_compile_pass.rs:31:15 + | +30 | fn test_kl04(kl: &KL04) { + | - this type parameter needs to be `std::marker::Sized` +31 | assert_kl(kl); + | ^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `KL04` + --> tests/ui-msrv/mid_compile_pass.rs:28:8 + | +28 | struct KL04(u8, T); + | ^^^^ +note: required because of the requirements on the impl of `KnownLayout` for `KL04` + --> tests/ui-msrv/mid_compile_pass.rs:27:10 + | +27 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ +note: required by a bound in `assert_kl` + --> tests/ui-msrv/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +30 - fn test_kl04(kl: &KL04) { +30 + fn test_kl04(kl: &KL04) { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-msrv/mid_compile_pass.rs:40:15 + | +39 | fn test_kl06(kl: &KL06) { + | - this type parameter needs to be `std::marker::Sized` +40 | assert_kl(kl); + | ^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `KL06` + --> tests/ui-msrv/mid_compile_pass.rs:37:8 + | +37 | struct KL06(u8, T); + | ^^^^ +note: required because of the requirements on the impl of `KnownLayout` for `KL06` + --> tests/ui-msrv/mid_compile_pass.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ +note: required by a bound in `assert_kl` + --> tests/ui-msrv/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +39 - fn test_kl06(kl: &KL06) { +39 + fn test_kl06(kl: &KL06) { + | + +error[E0277]: the trait bound `T: KnownLayout` is not satisfied + --> tests/ui-msrv/mid_compile_pass.rs:50:15 + | +50 | assert_kl(kl) + | ^^ + | | + | expected an implementor of trait `KnownLayout` + | help: consider borrowing here: `&kl` + | +note: required because of the requirements on the impl of `KnownLayout` for `KL12` + --> tests/ui-msrv/mid_compile_pass.rs:45:10 + | +45 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ +note: required by a bound in `assert_kl` + --> tests/ui-msrv/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// This file contains tests which trigger errors on MSRV during a different +// compiler pass compared to the stable or nightly toolchains. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::IntoBytes; + +use self::util::util::AU16; + +fn main() {} + +// `repr(C, packed(2))` is not equivalent to `repr(C, packed)`. +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes1 { + t0: T, + // Add a second field to avoid triggering the "repr(C) struct with one + // field" special case. + t1: T, +} + +fn is_into_bytes_1() { + if false { + is_into_bytes_1::>(); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/msrv_specific.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +warning: unused `#[macro_use]` import + --> tests/ui-msrv/msrv_specific.rs:12:1 + | +12 | #[macro_use] + | ^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/msrv_specific.rs:36:9 + | +36 | is_into_bytes_1::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | +note: required because of the requirements on the impl of `zerocopy::IntoBytes` for `IntoBytes1` + --> tests/ui-msrv/msrv_specific.rs:25:10 + | +25 | #[derive(IntoBytes)] + | ^^^^^^^^^ +note: required by a bound in `is_into_bytes_1` + --> tests/ui-msrv/msrv_specific.rs:34:23 + | +34 | fn is_into_bytes_1() { + | ^^^^^^^^^ required by this bound in `is_into_bytes_1` + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::{IntoBytes, KnownLayout}; + +use self::util::util::AU16; + +fn main() {} + +// +// KnownLayout errors +// + +struct NotKnownLayout; + +struct NotKnownLayoutDst([u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | N | N | KL00 | +#[derive(KnownLayout)] +struct KL00(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | Y | N | KL02 | +#[derive(KnownLayout)] +struct KL02(u8, [u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | N | KL08 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL08(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | Y | KL09 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL09(NotKnownLayout, NotKnownLayout); + +// +// Immutable errors +// + +#[derive(Immutable)] +struct Immutable1 { + a: core::cell::UnsafeCell<()>, +} + +#[derive(Immutable)] +struct Immutable2 { + a: [core::cell::UnsafeCell; 0], +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +#[repr(packed)] +struct TryFromBytesPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(packed(1))] +struct TryFromBytesPackedN { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed)] +struct TryFromBytesCPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed(1))] +struct TryFromBytesCPackedN { + foo: AU16, +} + +// +// IntoBytes errors +// + +// Since `IntoBytes1` has at least one generic parameter, an `IntoBytes` impl is +// emitted in which each field type is given an `Unaligned` bound. Since `foo`'s +// type doesn't implement `Unaligned`, this should fail. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + foo: AU16, + bar: T, +} + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes2 { + foo: u8, + bar: AU16, +} + +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes3 { + foo: u8, + // We'd prefer to use AU64 here, but you can't use aligned types in + // packed structs. + bar: u64, +} + +type SliceU8 = [u8]; + +// Padding between `u8` and `SliceU8`. `SliceU8` doesn't syntactically look like +// a slice, so this case is handled by our `Sized` support. +// +// NOTE(#1708): This exists to ensure that our error messages are good when a +// field is unsized. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes4 { + a: u8, + b: SliceU8, +} + +// Padding between `u8` and `[u16]`. `[u16]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes5 { + a: u8, + b: [u16], +} + +// Trailing padding after `[u8]`. `[u8]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes6 { + a: u16, + b: [u8], +} + +// Padding between `u8` and `u16` and also trailing padding after `[u8]`. `[u8]` +// is syntactically identifiable as a slice, so this case is handled by our +// `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes7 { + a: u8, + b: u16, + c: [u8], +} + +#[derive(IntoBytes)] +#[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs +struct IntoBytes8 { + a: u8, +} + +#[derive(IntoBytes)] +struct IntoBytes9 { + t: T, +} + +#[derive(IntoBytes)] +#[repr(packed(2))] +struct IntoBytes10 { + t: T, +} + +// `repr(C, packed(2))` is not equivalent to `repr(C, packed)`. +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes11 { + t0: T, + // Add a second field to avoid triggering the "repr(C) struct with one + // field" special case. + t1: T, +} + +fn is_into_bytes_11() { + if false { + is_into_bytes_11::>(); + } +} + +// `repr(C, align(2))` is not sufficient to guarantee the layout of this type. +#[derive(IntoBytes)] +#[repr(C, align(2))] +struct IntoBytes12 { + t: T, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +struct Unaligned1; + +#[derive(Unaligned)] +#[repr(transparent, align(2))] +struct Unaligned2 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(packed, align(2))] +struct Unaligned3; + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4; + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5; + +#[derive(Unaligned)] +struct Unaligned6; + +#[derive(Unaligned)] +#[repr(packed(2))] +struct Unaligned7; + +// Test the error message emitted when conflicting reprs appear on different +// lines. On the nightly compiler, this emits a "joint span" that spans both +// problematic repr token trees and everything in between. +#[derive(Copy, Clone)] +#[repr(packed(2), C)] +#[derive(Unaligned)] +#[repr(C, packed(2))] +struct WeirdReprSpan; + +#[derive(SplitAt)] +#[repr(C)] +struct SplitAtNotKnownLayout([u8]); + +#[derive(SplitAt, KnownLayout)] +#[repr(C)] +struct SplitAtSized(u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/struct.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,281 @@ +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:167:11 + | +167 | #[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs + | ^ + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/struct.rs:172:10 + | +172 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/struct.rs:177:10 + | +177 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-msrv/struct.rs:200:10 + | +200 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-msrv/struct.rs:211:11 + | +211 | #[repr(C, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:221:16 + | +221 | #[repr(packed, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:225:18 + | +225 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:229:18 + | +229 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/struct.rs:232:10 + | +232 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/struct.rs:235:10 + | +235 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-msrv/struct.rs:245:8 + | +245 | #[repr(C, packed(2))] + | ^ + +error[E0692]: transparent struct cannot have other repr hints + --> tests/ui-msrv/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/struct.rs:31:10 + | +31 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL00`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL00` + --> tests/ui-msrv/struct.rs:32:8 + | +32 | struct KL00(u8, NotKnownLayoutDst); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/struct.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL02`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL02` + --> tests/ui-msrv/struct.rs:37:8 + | +37 | struct KL02(u8, [u8]); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotKnownLayoutDst: zerocopy::KnownLayout` is not satisfied + --> tests/ui-msrv/struct.rs:41:10 + | +41 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayoutDst` + | + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-msrv/struct.rs:47:10 + | +47 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayout` + | + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/struct.rs:55:10 + | +55 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/struct.rs:60:10 + | +60 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell` + | + = note: required because of the requirements on the impl of `zerocopy::Immutable` for `[UnsafeCell; 0]` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-msrv/struct.rs:100:10 + | +100 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/struct.rs:107:10 + | +107 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/struct.rs:114:10 + | +114 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/struct.rs:130:10 + | +130 | #[derive(IntoBytes)] + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `IntoBytes4`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `IntoBytes4` + --> tests/ui-msrv/struct.rs:132:8 + | +132 | struct IntoBytes4 { + | ^^^^^^^^^^ +note: required by a bound in `std::mem::size_of` + --> $RUST/core/src/mem/mod.rs + | + | pub const fn size_of() -> usize { + | ^ required by this bound in `std::mem::size_of` + = note: this error originates in the macro `::zerocopy::struct_padding` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/struct.rs:134:8 + | +134 | b: SliceU8, + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `std::mem::size_of` + --> $RUST/core/src/mem/mod.rs + | + | pub const fn size_of() -> usize { + | ^ required by this bound in `std::mem::size_of` + +error[E0277]: the trait bound `(): DynamicPaddingFree` is not satisfied + --> tests/ui-msrv/struct.rs:139:10 + | +139 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `DynamicPaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as DynamicPaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): DynamicPaddingFree` is not satisfied + --> tests/ui-msrv/struct.rs:148:10 + | +148 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `DynamicPaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as DynamicPaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): DynamicPaddingFree` is not satisfied + --> tests/ui-msrv/struct.rs:158:10 + | +158 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `DynamicPaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as DynamicPaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `SplitAtNotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-msrv/struct.rs:248:10 + | +248 | #[derive(SplitAt)] + | ^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `SplitAtNotKnownLayout` + | +note: required by a bound in `SplitAt` + --> $WORKSPACE/src/split_at.rs + | + | pub unsafe trait SplitAt: KnownLayout { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `SplitAt` + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `u8: SplitAt` is not satisfied + --> tests/ui-msrv/struct.rs:252:10 + | +252 | #[derive(SplitAt, KnownLayout)] + | ^^^^^^^ the trait `SplitAt` is not implemented for `u8` + | + = help: see issue #48214 + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0271]: type mismatch resolving `::PointerMetadata == usize` + --> tests/ui-msrv/struct.rs:252:10 + | +252 | #[derive(SplitAt, KnownLayout)] + | ^^^^^^^ expected `()`, found `usize` + | + = help: see issue #48214 + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use std::mem::ManuallyDrop; + +use self::util::util::AU16; + +fn main() {} + +// +// Immutable errors +// + +#[derive(Immutable)] +union Immutable1 { + a: ManuallyDrop>, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes1 { + foo: ManuallyDrop, +} + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes2 { + foo: u8, + bar: [u8; 2], +} + +// Need a `repr` attribute +#[derive(IntoBytes)] +union IntoBytes3 { + foo: u8, +} + +// `repr(packed(2))` isn't equivalent to `repr(packed)` +#[derive(IntoBytes)] +#[repr(packed(2))] +union IntoBytes4 { + foo: u8, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +union Unaligned1 { + foo: i16, + bar: AU16, +} + +// Transparent unions are unstable; see issue #60405 +// for more information. + +// #[derive(Unaligned)] +// #[repr(transparent, align(2))] +// union Unaligned2 { +// foo: u8, +// } + +#[derive(Unaligned)] +#[repr(packed, align(2))] +union Unaligned3 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5 { + foo: u8, +} + +#[derive(Unaligned)] +union Unaligned6 { + foo: i16, + bar: AU16, +} + +#[derive(Unaligned)] +#[repr(packed(2))] +union Unaligned7 { + foo: i16, + bar: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,84 @@ +error: unsupported on types with type parameters + --> tests/ui-msrv/union.rs:34:10 + | +34 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-msrv/union.rs:48:10 + | +48 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-msrv/union.rs:54:10 + | +54 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-msrv/union.rs:65:11 + | +65 | #[repr(C, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/union.rs:81:16 + | +81 | #[repr(packed, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/union.rs:87:18 + | +87 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-msrv/union.rs:93:18 + | +93 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/union.rs:98:10 + | +98 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-msrv/union.rs:104:10 + | +104 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-msrv/union.rs:25:10 + | +25 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = note: required because of the requirements on the impl of `zerocopy::Immutable` for `ManuallyDrop>` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `(): PaddingFree` is not satisfied + --> tests/ui-msrv/union.rs:40:10 + | +40 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `PaddingFree` is not implemented for `()` + | + = help: the following implementations were found: + <() as PaddingFree> + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! See: https://github.com/google/zerocopy/issues/553 +//! zerocopy must still allow derives of deprecated types. +//! This test has a hand-written impl of a deprecated type, and should result in a compilation +//! error. If zerocopy does not tack an allow(deprecated) annotation onto its impls, then this +//! test will fail because more than one compile error will be generated. +#![deny(deprecated)] + +extern crate zerocopy; + +use zerocopy::IntoBytes; + +#[derive(IntoBytes)] +#[repr(C)] +union Foo { + a: u8, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error: requires --cfg zerocopy_derive_union_into_bytes; +please let us know you use this feature: https://github.com/google/zerocopy/discussions/1802 + --> tests/ui-msrv/union_into_bytes_cfg/union_into_bytes_cfg.rs:20:10 + | +20 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! See: https://github.com/google/zerocopy/issues/553 +//! zerocopy must still allow derives of deprecated types. +//! This test has a hand-written impl of a deprecated type, and should result in a compilation +//! error. If zerocopy does not tack an allow(deprecated) annotation onto its impls, then this +//! test will fail because more than one compile error will be generated. +#![deny(deprecated)] + +extern crate zerocopy; + +use zerocopy::IntoBytes; + +#[deprecated = "Do not use"] +#[derive(IntoBytes)] +#[repr(C)] +struct OldHeader { + field_a: usize, + collection: [u8; 8], +} + +trait T {} + +// Intentionally trigger a deprecation error +impl T for OldHeader {} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/absence_of_deprecated_warning.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error: use of deprecated struct `OldHeader`: Do not use + --> tests/ui-nightly/absence_of_deprecated_warning.rs:31:12 + | +31 | impl T for OldHeader {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-nightly/absence_of_deprecated_warning.rs:14:9 + | +14 | #![deny(deprecated)] + | ^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use core::marker::PhantomData; + +use zerocopy::{FromBytes, FromZeros, IntoBytes, TryFromBytes, Unaligned}; + +use self::util::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(IntoBytes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +util_assert_impl_all!(TransparentStruct: TryFromBytes); +util_assert_impl_all!(TransparentStruct: FromZeros); +util_assert_impl_all!(TransparentStruct: FromBytes); +util_assert_impl_all!(TransparentStruct: IntoBytes); +util_assert_impl_all!(TransparentStruct: Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,169 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:34:23 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::TryFromBytes` + --> tests/ui-nightly/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:34:1 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:35:23 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromZeros` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required for `TransparentStruct` to implement `FromZeros` + --> tests/ui-nightly/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:35:1 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:36:23 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::FromBytes` + --> tests/ui-nightly/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:36:1 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:37:23 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required for `TransparentStruct` to implement `zerocopy::IntoBytes` + --> tests/ui-nightly/derive_transparent.rs:24:10 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:37:1 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `IntoBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:38:23 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::Unaligned` + --> tests/ui-nightly/derive_transparent.rs:24:32 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:38:1 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,577 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// +// Generic errors +// + +#[derive(FromBytes)] +#[repr("foo")] +enum Generic1 { + A, +} + +#[derive(FromBytes)] +#[repr(foo)] +enum Generic2 { + A, +} + +#[derive(FromBytes)] +#[repr(transparent)] +enum Generic3 { + A, +} + +#[derive(FromBytes)] +#[repr(u8, u16)] +enum Generic4 { + A, +} + +#[derive(FromBytes)] +enum Generic5 { + A, +} + +// +// Immutable errors +// + +#[derive(Immutable)] +enum Immutable1 { + A(core::cell::UnsafeCell<()>), +} + +#[derive(Immutable)] +enum Never {} + +#[derive(Immutable)] +enum Immutable2 { + Uninhabited(Never, core::cell::UnsafeCell), + Inhabited(u8), +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +enum TryFromBytes1 { + A, +} + +#[derive(TryFromBytes)] +enum TryFromBytes2 { + A, + B(u8), +} + +struct NotTryFromBytes; + +#[derive(TryFromBytes)] +#[repr(u8)] +enum TryFromBytes3 { + A(NotTryFromBytes), +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +enum FromZeros1 { + A(u8), +} + +#[derive(FromZeros)] +enum FromZeros2 { + A, + B(u8), +} + +#[derive(FromZeros)] +enum FromZeros3 { + A = 1, + B, +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros4 { + A = 1, + B = 2, +} + +const NEGATIVE_ONE: i8 = -1; + +#[derive(FromZeros)] +#[repr(i8)] +enum FromZeros5 { + A = NEGATIVE_ONE, + B, +} + +struct NotFromZeros; + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros6 { + A(NotFromZeros), +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros7 { + A = 1, + B(NotFromZeros), +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +enum FromBytes1 { + A, +} + +#[derive(FromBytes)] +#[repr(C)] +enum FromBytes2 { + A, +} + +#[derive(FromBytes)] +#[repr(usize)] +enum FromBytes3 { + A, +} + +#[derive(FromBytes)] +#[repr(isize)] +enum FromBytes4 { + A, +} + +#[derive(FromBytes)] +#[repr(u32)] +enum FromBytes5 { + A, +} + +#[derive(FromBytes)] +#[repr(i32)] +enum FromBytes6 { + A, +} + +#[derive(FromBytes)] +#[repr(u64)] +enum FromBytes7 { + A, +} + +#[derive(FromBytes)] +#[repr(i64)] +enum FromBytes8 { + A, +} + +#[derive(FromBytes)] +#[repr(u8)] +enum FooU8 { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255(bool), +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +enum Unaligned1 { + A, +} + +#[derive(Unaligned)] +#[repr(u16)] +enum Unaligned2 { + A, +} + +#[derive(Unaligned)] +#[repr(i16)] +enum Unaligned3 { + A, +} + +#[derive(Unaligned)] +#[repr(u32)] +enum Unaligned4 { + A, +} + +#[derive(Unaligned)] +#[repr(i32)] +enum Unaligned5 { + A, +} + +#[derive(Unaligned)] +#[repr(u64)] +enum Unaligned6 { + A, +} + +#[derive(Unaligned)] +#[repr(i64)] +enum Unaligned7 { + A, +} + +#[derive(Unaligned)] +#[repr(usize)] +enum Unaligned8 { + A, +} + +#[derive(Unaligned)] +#[repr(isize)] +enum Unaligned9 { + A, +} + +#[derive(Unaligned)] +#[repr(u8, align(2))] +enum Unaligned10 { + A, +} + +#[derive(Unaligned)] +#[repr(i8, align(2))] +enum Unaligned11 { + A, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +enum Unaligned12 { + A, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +enum Unaligned13 { + A, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes1 { + A, + B(u8), +} + +#[derive(IntoBytes)] +#[repr(C, align(4))] +struct Align4IntoBytes(u32); + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes2 { + A(Align4IntoBytes), +} + +#[derive(IntoBytes)] +#[repr(u32)] +enum IntoBytes3 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes4 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes5 { + A(u32), +} + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes6 { + A(T), +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,555 @@ +error: unrecognized representation hint + --> tests/ui-nightly/enum.rs:19:8 + | +19 | #[repr("foo")] + | ^^^^^ + +error: unrecognized representation hint + --> tests/ui-nightly/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:30:10 + | +30 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-nightly/enum.rs:37:8 + | +37 | #[repr(u8, u16)] + | ^^^^^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:42:10 + | +42 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:69:10 + | +69 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:74:10 + | +74 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:92:10 + | +92 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:97:10 + | +97 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:103:10 + | +103 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-nightly/enum.rs:110:1 + | +110 | / #[repr(u8)] +111 | | enum FromZeros4 { +112 | | A = 1, +113 | | B = 2, +114 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + help: This enum has discriminants which are not literal integers. One of those may define or imply which variant has a discriminant of zero. Use a literal integer to define or imply the variant with a discriminant of zero. + --> tests/ui-nightly/enum.rs:119:1 + | +119 | / #[repr(i8)] +120 | | enum FromZeros5 { +121 | | A = NEGATIVE_ONE, +122 | | B, +123 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-nightly/enum.rs:134:1 + | +134 | / #[repr(u8)] +135 | | enum FromZeros7 { +136 | | A = 1, +137 | | B(NotFromZeros), +138 | | } + | |_^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:144:10 + | +144 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:150:8 + | +150 | #[repr(C)] + | ^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:156:8 + | +156 | #[repr(usize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:162:8 + | +162 | #[repr(isize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:168:8 + | +168 | #[repr(u32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:174:8 + | +174 | #[repr(i32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:180:8 + | +180 | #[repr(u64)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-nightly/enum.rs:186:8 + | +186 | #[repr(i64)] + | ^^^ + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:456:10 + | +456 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:462:10 + | +462 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:468:10 + | +468 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:474:10 + | +474 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:480:10 + | +480 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:486:10 + | +486 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:492:10 + | +492 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:498:10 + | +498 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/enum.rs:504:10 + | +504 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-nightly/enum.rs:511:12 + | +511 | #[repr(u8, align(2))] + | ^^^^^^^^ + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-nightly/enum.rs:517:12 + | +517 | #[repr(i8, align(2))] + | ^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/enum.rs:523:8 + | +523 | #[repr(align(1), align(2))] + | ^^^^^^^^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/enum.rs:529:8 + | +529 | #[repr(align(2), align(4))] + | ^^^^^^^^^^^^^^^^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:562:10 + | +562 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/enum.rs:568:10 + | +568 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> tests/ui-nightly/enum.rs:576:7 + | +576 | A(T), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0565]: meta item in `repr` must be an identifier + --> tests/ui-nightly/enum.rs:19:1 + | +19 | #[repr("foo")] + | ^^^^^^^^^^^^^^ + +error[E0552]: unrecognized representation hint + --> tests/ui-nightly/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + | + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit + +error[E0566]: conflicting representation hints + --> tests/ui-nightly/enum.rs:37:8 + | +37 | #[repr(u8, u16)] + | ^^ ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +error[E0277]: the trait bound `UnsafeCell<()>: Immutable` is not satisfied + --> tests/ui-nightly/enum.rs:51:10 + | +51 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `Immutable`: + &T + &mut T + () + *const T + *mut T + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `UnsafeCell: Immutable` is not satisfied + --> tests/ui-nightly/enum.rs:59:10 + | +59 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell` + = help: the following other types implement trait `Immutable`: + &T + &mut T + () + *const T + *mut T + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotTryFromBytes: TryFromBytes` is not satisfied + --> tests/ui-nightly/enum.rs:82:10 + | +82 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `TryFromBytes` is not implemented for `NotTryFromBytes` + --> tests/ui-nightly/enum.rs:80:1 + | +80 | struct NotTryFromBytes; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotTryFromBytes` + = help: the following other types implement trait `TryFromBytes`: + () + *const T + *mut T + ::is_bit_valid::___ZerocopyVariantStruct_A + ::is_bit_valid::___ZerocopyVariantStruct_A + AtomicBool + AtomicI16 + AtomicI32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotFromZeros: TryFromBytes` is not satisfied + --> tests/ui-nightly/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `TryFromBytes` is not implemented for `NotFromZeros` + --> tests/ui-nightly/enum.rs:125:1 + | +125 | struct NotFromZeros; + | ^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotFromZeros` + = help: the following other types implement trait `TryFromBytes`: + () + *const T + *mut T + ::is_bit_valid::___ZerocopyVariantStruct_A + ::is_bit_valid::___ZerocopyVariantStruct_A + AtomicBool + AtomicI16 + AtomicI32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotFromZeros: FromZeros` is not satisfied + --> tests/ui-nightly/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromZeros` is not implemented for `NotFromZeros` + --> tests/ui-nightly/enum.rs:125:1 + | +125 | struct NotFromZeros; + | ^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromZeros)]` to `NotFromZeros` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes1` has 1 total byte(s) of padding + --> tests/ui-nightly/enum.rs:538:10 + | +538 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes2` has 3 total byte(s) of padding + --> tests/ui-nightly/enum.rs:549:10 + | +549 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes3` has 2 total byte(s) of padding + --> tests/ui-nightly/enum.rs:555:10 + | +555 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error: generic `Self` types are currently not permitted in anonymous constants + --> tests/ui-nightly/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | +note: not a concrete type + --> tests/ui-nightly/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required for `FooU8` to implement `FromBytes` + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_is_from_bytes` + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,272 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +#[derive(FromBytes)] +#[repr(u8)] +enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error: FromBytes only supported on repr(u8) enum with 256 variants + --> tests/ui-nightly/enum_from_bytes_u8_too_few.rs:15:1 + | + 15 | / #[repr(u8)] + 16 | | enum Foo { + 17 | | Variant0, + 18 | | Variant1, +... | +271 | | Variant254, +272 | | } + | |_^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::KnownLayout; + +use self::util::util::{NotZerocopy, AU16}; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +struct TryFromBytes1 { + value: NotZerocopy, +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +struct FromZeros1 { + value: NotZerocopy, +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +struct FromBytes1 { + value: NotZerocopy, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + value: NotZerocopy, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned1 { + aligned: AU16, +} + +// This specifically tests a bug we had in an old version of the code in which +// the trait bound would only be enforced for the first field's type. +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned2 { + unaligned: u8, + aligned: AU16, +} + +#[derive(Unaligned)] +#[repr(transparent)] +struct Unaligned3 { + aligned: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,331 @@ +warning: unused import: `zerocopy::KnownLayout` + --> tests/ui-nightly/late_compile_pass.rs:15:5 + | +15 | use zerocopy::KnownLayout; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:29:10 + | +29 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromZeros` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `FromZeros` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:56:10 + | +56 | #[derive(IntoBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:66:10 + | +66 | #[derive(Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `AU16` + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:74:10 + | +74 | #[derive(Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `AU16` + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:81:10 + | +81 | #[derive(Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `AU16` + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + --> tests/ui-nightly/../include.rs + | + | pub struct NotZerocopy(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `FromBytes1` to implement `zerocopy::FromBytes` + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `::is_bit_valid::assert_is_from_bytes` + --> tests/ui-nightly/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::KnownLayout; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// KnownLayout errors +// + +fn assert_kl(_: &T) {} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | N | N | KL04 | +#[derive(KnownLayout)] +struct KL04(u8, T); + +fn test_kl04(kl: &KL04) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | Y | N | KL06 | +#[derive(KnownLayout)] +struct KL06(u8, T); + +fn test_kl06(kl: &KL06) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | N | KL12 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL12(u8, T); + +fn test_kl12(kl: &KL12) { + assert_kl(kl) +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | Y | KL13 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL13(u8, T); + +fn test_kl13(t: T) -> impl KnownLayout { + KL13(0u8, t) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/mid_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +error[E0277]: the trait bound `T: KnownLayout` is not satisfied + --> tests/ui-nightly/mid_compile_pass.rs:59:26 + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T` +60 | KL13(0u8, t) + | ------------ return type was inferred to be `KL13` here + | + = note: Consider adding `#[derive(KnownLayout)]` to `T` +note: required for `KL13` to implement `KnownLayout` + --> tests/ui-nightly/mid_compile_pass.rs:55:10 + | +55 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `KnownLayout` + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | +++++++++++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-nightly/mid_compile_pass.rs:31:15 + | +30 | fn test_kl04(kl: &KL04) { + | - this type parameter needs to be `Sized` +31 | assert_kl(kl); + | --------- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `KL04` + --> tests/ui-nightly/mid_compile_pass.rs:28:8 + | +28 | struct KL04(u8, T); + | ^^^^ +note: required for `KL04` to implement `KnownLayout` + --> tests/ui-nightly/mid_compile_pass.rs:27:10 + | +27 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-nightly/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +30 - fn test_kl04(kl: &KL04) { +30 + fn test_kl04(kl: &KL04) { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-nightly/mid_compile_pass.rs:40:15 + | +39 | fn test_kl06(kl: &KL06) { + | - this type parameter needs to be `Sized` +40 | assert_kl(kl); + | --------- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `KL06` + --> tests/ui-nightly/mid_compile_pass.rs:37:8 + | +37 | struct KL06(u8, T); + | ^^^^ +note: required for `KL06` to implement `KnownLayout` + --> tests/ui-nightly/mid_compile_pass.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-nightly/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +39 - fn test_kl06(kl: &KL06) { +39 + fn test_kl06(kl: &KL06) { + | + +error[E0277]: the trait bound `KL12: KnownLayout` is not satisfied + --> tests/ui-nightly/mid_compile_pass.rs:50:15 + | +50 | assert_kl(kl) + | --------- ^^ the trait `KnownLayout` is not implemented for `KL12` + | | + | required by a bound introduced by this call + | +note: required for `KL12` to implement `KnownLayout` + --> tests/ui-nightly/mid_compile_pass.rs:45:10 + | +45 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-nightly/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +50 | assert_kl(&kl) + | + +50 | assert_kl(&mut kl) + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::{IntoBytes, KnownLayout}; + +use self::util::util::AU16; + +fn main() {} + +// +// KnownLayout errors +// + +struct NotKnownLayout; + +struct NotKnownLayoutDst([u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | N | N | KL00 | +#[derive(KnownLayout)] +struct KL00(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | Y | N | KL02 | +#[derive(KnownLayout)] +struct KL02(u8, [u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | N | KL08 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL08(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | Y | KL09 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL09(NotKnownLayout, NotKnownLayout); + +// +// Immutable errors +// + +#[derive(Immutable)] +struct Immutable1 { + a: core::cell::UnsafeCell<()>, +} + +#[derive(Immutable)] +struct Immutable2 { + a: [core::cell::UnsafeCell; 0], +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +#[repr(packed)] +struct TryFromBytesPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(packed(1))] +struct TryFromBytesPackedN { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed)] +struct TryFromBytesCPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed(1))] +struct TryFromBytesCPackedN { + foo: AU16, +} + +// +// IntoBytes errors +// + +// Since `IntoBytes1` has at least one generic parameter, an `IntoBytes` impl is +// emitted in which each field type is given an `Unaligned` bound. Since `foo`'s +// type doesn't implement `Unaligned`, this should fail. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + foo: AU16, + bar: T, +} + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes2 { + foo: u8, + bar: AU16, +} + +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes3 { + foo: u8, + // We'd prefer to use AU64 here, but you can't use aligned types in + // packed structs. + bar: u64, +} + +type SliceU8 = [u8]; + +// Padding between `u8` and `SliceU8`. `SliceU8` doesn't syntactically look like +// a slice, so this case is handled by our `Sized` support. +// +// NOTE(#1708): This exists to ensure that our error messages are good when a +// field is unsized. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes4 { + a: u8, + b: SliceU8, +} + +// Padding between `u8` and `[u16]`. `[u16]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes5 { + a: u8, + b: [u16], +} + +// Trailing padding after `[u8]`. `[u8]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes6 { + a: u16, + b: [u8], +} + +// Padding between `u8` and `u16` and also trailing padding after `[u8]`. `[u8]` +// is syntactically identifiable as a slice, so this case is handled by our +// `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes7 { + a: u8, + b: u16, + c: [u8], +} + +#[derive(IntoBytes)] +#[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs +struct IntoBytes8 { + a: u8, +} + +#[derive(IntoBytes)] +struct IntoBytes9 { + t: T, +} + +#[derive(IntoBytes)] +#[repr(packed(2))] +struct IntoBytes10 { + t: T, +} + +// `repr(C, packed(2))` is not equivalent to `repr(C, packed)`. +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes11 { + t0: T, + // Add a second field to avoid triggering the "repr(C) struct with one + // field" special case. + t1: T, +} + +fn is_into_bytes_11() { + if false { + is_into_bytes_11::>(); + } +} + +// `repr(C, align(2))` is not sufficient to guarantee the layout of this type. +#[derive(IntoBytes)] +#[repr(C, align(2))] +struct IntoBytes12 { + t: T, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +struct Unaligned1; + +#[derive(Unaligned)] +#[repr(transparent, align(2))] +struct Unaligned2 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(packed, align(2))] +struct Unaligned3; + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4; + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5; + +#[derive(Unaligned)] +struct Unaligned6; + +#[derive(Unaligned)] +#[repr(packed(2))] +struct Unaligned7; + +// Test the error message emitted when conflicting reprs appear on different +// lines. On the nightly compiler, this emits a "joint span" that spans both +// problematic repr token trees and everything in between. +#[derive(Copy, Clone)] +#[repr(packed(2), C)] +#[derive(Unaligned)] +#[repr(C, packed(2))] +struct WeirdReprSpan; + +#[derive(SplitAt)] +#[repr(C)] +struct SplitAtNotKnownLayout([u8]); + +#[derive(SplitAt, KnownLayout)] +#[repr(C)] +struct SplitAtSized(u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/struct.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,525 @@ +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:167:8 + | +167 | #[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs + | ^^^^ + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/struct.rs:172:10 + | +172 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/struct.rs:177:10 + | +177 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-nightly/struct.rs:200:10 + | +200 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-nightly/struct.rs:211:11 + | +211 | #[repr(C, align(2))] + | ^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:221:8 + | +221 | #[repr(packed, align(2))] + | ^^^^^^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:225:8 + | +225 | #[repr(align(1), align(2))] + | ^^^^^^^^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:229:8 + | +229 | #[repr(align(2), align(4))] + | ^^^^^^^^^^^^^^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/struct.rs:232:10 + | +232 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/struct.rs:235:10 + | +235 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-nightly/struct.rs:243:19 + | +243 | #[repr(packed(2), C)] + | ___________________^ +244 | | #[derive(Unaligned)] +245 | | #[repr(C, packed(2))] + | |________^ + +error[E0692]: transparent struct cannot have other repr hints + --> tests/ui-nightly/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/struct.rs:31:10 + | +31 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL00`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL00` + --> tests/ui-nightly/struct.rs:32:8 + | +32 | struct KL00(u8, NotKnownLayoutDst); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/struct.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL02`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL02` + --> tests/ui-nightly/struct.rs:37:8 + | +37 | struct KL02(u8, [u8]); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotKnownLayoutDst: zerocopy::KnownLayout` is not satisfied + --> tests/ui-nightly/struct.rs:41:10 + | +41 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayoutDst` + --> tests/ui-nightly/struct.rs:27:1 + | +27 | struct NotKnownLayoutDst([u8]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(KnownLayout)]` to `NotKnownLayoutDst` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `NotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-nightly/struct.rs:47:10 + | +47 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayout` + --> tests/ui-nightly/struct.rs:25:1 + | +25 | struct NotKnownLayout; + | ^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(KnownLayout)]` to `NotKnownLayout` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/struct.rs:55:10 + | +55 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `UnsafeCell: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/struct.rs:60:10 + | +60 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = note: required for `[UnsafeCell; 0]` to implement `zerocopy::Immutable` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:71:1 + | +71 | struct TryFromBytesPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:77:1 + | +77 | struct TryFromBytesPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:83:1 + | +83 | struct TryFromBytesCPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:89:1 + | +89 | struct TryFromBytesCPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/struct.rs:100:10 + | +100 | #[derive(IntoBytes)] + | ^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `AU16` + --> tests/ui-nightly/../include.rs + | + 63 | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes2` has 1 total byte(s) of padding + --> tests/ui-nightly/struct.rs:107:10 + | +107 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes3` has 1 total byte(s) of padding + --> tests/ui-nightly/struct.rs:114:10 + | +114 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/struct.rs:130:10 + | +130 | #[derive(IntoBytes)] + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `IntoBytes4`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `IntoBytes4` + --> tests/ui-nightly/struct.rs:132:8 + | +132 | struct IntoBytes4 { + | ^^^^^^^^^^ + = note: required for `IntoBytes4` to implement `macro_util::__size_of::Sized` +note: required by a bound in `macro_util::__size_of::size_of` + --> $WORKSPACE/src/util/macro_util.rs + | + | pub const fn size_of() -> usize { + | ^^^^^ required by this bound in `size_of` + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `[u8]` is unsized + --> tests/ui-nightly/struct.rs:134:8 + | +134 | b: SliceU8, + | ^^^^^^^ `IntoBytes` needs all field types to be `Sized` in order to determine whether there is padding + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: consider using `#[repr(packed)]` to remove padding + = note: `IntoBytes` does not require the fields of `#[repr(packed)]` types to be `Sized` + = note: required for `[u8]` to implement `macro_util::__size_of::Sized` +note: required by a bound in `macro_util::__size_of::size_of` + --> $WORKSPACE/src/util/macro_util.rs + | + | pub const fn size_of() -> usize { + | ^^^^^ required by this bound in `size_of` + +error[E0277]: `IntoBytes5` has one or more padding bytes + --> tests/ui-nightly/struct.rs:139:10 + | +139 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes6` has one or more padding bytes + --> tests/ui-nightly/struct.rs:148:10 + | +148 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes7` has one or more padding bytes + --> tests/ui-nightly/struct.rs:158:10 + | +158 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0587]: type has conflicting packed and align representation hints + --> tests/ui-nightly/struct.rs:222:1 + | +222 | struct Unaligned3; + | ^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `SplitAtNotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-nightly/struct.rs:248:10 + | +248 | #[derive(SplitAt)] + | ^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::KnownLayout` is not implemented for `SplitAtNotKnownLayout` + --> tests/ui-nightly/struct.rs:250:1 + | +250 | struct SplitAtNotKnownLayout([u8]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(KnownLayout)]` to `SplitAtNotKnownLayout` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others +note: required by a bound in `SplitAt` + --> $WORKSPACE/src/split_at.rs + | + 61 | pub unsafe trait SplitAt: KnownLayout { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `SplitAt` + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `u8: SplitAt` is not satisfied + --> tests/ui-nightly/struct.rs:252:10 + | +252 | #[derive(SplitAt, KnownLayout)] + | ^^^^^^^ the trait `SplitAt` is not implemented for `u8` + | + = note: Consider adding `#[derive(SplitAt)]` to `u8` + = help: the following other types implement trait `SplitAt`: + SplitAtNotKnownLayout + SplitAtSized + [T] + = help: see issue #48214 + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-nightly/struct.rs:195:28 + | +195 | is_into_bytes_11::>(); + | ^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `zerocopy::Unaligned` is not implemented for `AU16` + --> tests/ui-nightly/../include.rs + | + 63 | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required for `IntoBytes11` to implement `zerocopy::IntoBytes` + --> tests/ui-nightly/struct.rs:184:10 + | +184 | #[derive(IntoBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `is_into_bytes_11` + --> tests/ui-nightly/struct.rs:193:24 + | +193 | fn is_into_bytes_11() { + | ^^^^^^^^^ required by this bound in `is_into_bytes_11` + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use std::mem::ManuallyDrop; + +use self::util::util::AU16; + +fn main() {} + +// +// Immutable errors +// + +#[derive(Immutable)] +union Immutable1 { + a: ManuallyDrop>, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes1 { + foo: ManuallyDrop, +} + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes2 { + foo: u8, + bar: [u8; 2], +} + +// Need a `repr` attribute +#[derive(IntoBytes)] +union IntoBytes3 { + foo: u8, +} + +// `repr(packed(2))` isn't equivalent to `repr(packed)` +#[derive(IntoBytes)] +#[repr(packed(2))] +union IntoBytes4 { + foo: u8, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +union Unaligned1 { + foo: i16, + bar: AU16, +} + +// Transparent unions are unstable; see issue #60405 +// for more information. + +// #[derive(Unaligned)] +// #[repr(transparent, align(2))] +// union Unaligned2 { +// foo: u8, +// } + +#[derive(Unaligned)] +#[repr(packed, align(2))] +union Unaligned3 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5 { + foo: u8, +} + +#[derive(Unaligned)] +union Unaligned6 { + foo: i16, + bar: AU16, +} + +#[derive(Unaligned)] +#[repr(packed(2))] +union Unaligned7 { + foo: i16, + bar: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +error: unsupported on types with type parameters + --> tests/ui-nightly/union.rs:34:10 + | +34 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-nightly/union.rs:48:10 + | +48 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-nightly/union.rs:54:10 + | +54 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-nightly/union.rs:65:11 + | +65 | #[repr(C, align(2))] + | ^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/union.rs:81:8 + | +81 | #[repr(packed, align(2))] + | ^^^^^^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/union.rs:87:8 + | +87 | #[repr(align(1), align(2))] + | ^^^^^^^^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-nightly/union.rs:93:8 + | +93 | #[repr(align(2), align(4))] + | ^^^^^^^^^^^^^^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/union.rs:98:10 + | +98 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-nightly/union.rs:104:10 + | +104 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition name: `zerocopy_derive_union_into_bytes` + --> tests/ui-nightly/union.rs:40:10 + | +40 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = help: expected names are: `docsrs`, `feature`, and `test` and 31 more + = note: using a cfg inside a derive macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try referring to `IntoBytes` crate for guidance on how handle this unexpected cfg + = help: the derive macro `IntoBytes` may come from an old version of the `zerocopy_derive` crate, try updating your dependency with `cargo update -p zerocopy_derive` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-nightly/union.rs:25:10 + | +25 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = note: required for `ManuallyDrop>` to implement `zerocopy::Immutable` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0277]: `IntoBytes2` has 1 total byte(s) of padding + --> tests/ui-nightly/union.rs:40:10 + | +40 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | + 9 + #![feature(trivial_bounds)] + | + +error[E0587]: type has conflicting packed and align representation hints + --> tests/ui-nightly/union.rs:82:1 + | +82 | union Unaligned3 { + | ^^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/union.rs:106:1 + | +106 | union Unaligned7 { + | ^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../include.rs + | + 63 | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! See: https://github.com/google/zerocopy/issues/553 +//! zerocopy must still allow derives of deprecated types. +//! This test has a hand-written impl of a deprecated type, and should result in a compilation +//! error. If zerocopy does not tack an allow(deprecated) annotation onto its impls, then this +//! test will fail because more than one compile error will be generated. +#![deny(deprecated)] + +extern crate zerocopy; + +use zerocopy::IntoBytes; + +#[derive(IntoBytes)] +#[repr(C)] +union Foo { + a: u8, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error: requires --cfg zerocopy_derive_union_into_bytes; + please let us know you use this feature: https://github.com/google/zerocopy/discussions/1802 + --> tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs:20:10 + | +20 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition name: `zerocopy_derive_union_into_bytes` + --> tests/ui-nightly/union_into_bytes_cfg/union_into_bytes_cfg.rs:20:10 + | +20 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = help: expected names are: `docsrs`, `feature`, and `test` and 31 more + = note: using a cfg inside a derive macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try referring to `IntoBytes` crate for guidance on how handle this unexpected cfg + = help: the derive macro `IntoBytes` may come from an old version of the `zerocopy_derive` crate, try updating your dependency with `cargo update -p zerocopy_derive` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use core::marker::PhantomData; + +use zerocopy::{FromBytes, FromZeros, IntoBytes, TryFromBytes, Unaligned}; + +use self::util::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(IntoBytes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +util_assert_impl_all!(TransparentStruct: TryFromBytes); +util_assert_impl_all!(TransparentStruct: FromZeros); +util_assert_impl_all!(TransparentStruct: FromBytes); +util_assert_impl_all!(TransparentStruct: IntoBytes); +util_assert_impl_all!(TransparentStruct: Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/derive_transparent.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:34:23 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::TryFromBytes` + --> tests/ui-stable/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:34:1 + | +34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-stable/derive_transparent.rs:35:23 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others +note: required for `TransparentStruct` to implement `FromZeros` + --> tests/ui-stable/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:35:1 + | +35 | util_assert_impl_all!(TransparentStruct: FromZeros); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:36:23 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::FromBytes` + --> tests/ui-stable/derive_transparent.rs:24:21 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:36:1 + | +36 | util_assert_impl_all!(TransparentStruct: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:37:23 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others +note: required for `TransparentStruct` to implement `zerocopy::IntoBytes` + --> tests/ui-stable/derive_transparent.rs:24:10 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:37:1 + | +37 | util_assert_impl_all!(TransparentStruct: IntoBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `IntoBytes` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/derive_transparent.rs:38:23 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(Unaligned)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required for `TransparentStruct` to implement `zerocopy::Unaligned` + --> tests/ui-stable/derive_transparent.rs:24:32 + | +24 | #[derive(IntoBytes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:38:1 + | +38 | util_assert_impl_all!(TransparentStruct: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `util_assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,577 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// +// Generic errors +// + +#[derive(FromBytes)] +#[repr("foo")] +enum Generic1 { + A, +} + +#[derive(FromBytes)] +#[repr(foo)] +enum Generic2 { + A, +} + +#[derive(FromBytes)] +#[repr(transparent)] +enum Generic3 { + A, +} + +#[derive(FromBytes)] +#[repr(u8, u16)] +enum Generic4 { + A, +} + +#[derive(FromBytes)] +enum Generic5 { + A, +} + +// +// Immutable errors +// + +#[derive(Immutable)] +enum Immutable1 { + A(core::cell::UnsafeCell<()>), +} + +#[derive(Immutable)] +enum Never {} + +#[derive(Immutable)] +enum Immutable2 { + Uninhabited(Never, core::cell::UnsafeCell), + Inhabited(u8), +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +enum TryFromBytes1 { + A, +} + +#[derive(TryFromBytes)] +enum TryFromBytes2 { + A, + B(u8), +} + +struct NotTryFromBytes; + +#[derive(TryFromBytes)] +#[repr(u8)] +enum TryFromBytes3 { + A(NotTryFromBytes), +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +enum FromZeros1 { + A(u8), +} + +#[derive(FromZeros)] +enum FromZeros2 { + A, + B(u8), +} + +#[derive(FromZeros)] +enum FromZeros3 { + A = 1, + B, +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros4 { + A = 1, + B = 2, +} + +const NEGATIVE_ONE: i8 = -1; + +#[derive(FromZeros)] +#[repr(i8)] +enum FromZeros5 { + A = NEGATIVE_ONE, + B, +} + +struct NotFromZeros; + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros6 { + A(NotFromZeros), +} + +#[derive(FromZeros)] +#[repr(u8)] +enum FromZeros7 { + A = 1, + B(NotFromZeros), +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +enum FromBytes1 { + A, +} + +#[derive(FromBytes)] +#[repr(C)] +enum FromBytes2 { + A, +} + +#[derive(FromBytes)] +#[repr(usize)] +enum FromBytes3 { + A, +} + +#[derive(FromBytes)] +#[repr(isize)] +enum FromBytes4 { + A, +} + +#[derive(FromBytes)] +#[repr(u32)] +enum FromBytes5 { + A, +} + +#[derive(FromBytes)] +#[repr(i32)] +enum FromBytes6 { + A, +} + +#[derive(FromBytes)] +#[repr(u64)] +enum FromBytes7 { + A, +} + +#[derive(FromBytes)] +#[repr(i64)] +enum FromBytes8 { + A, +} + +#[derive(FromBytes)] +#[repr(u8)] +enum FooU8 { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255(bool), +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +enum Unaligned1 { + A, +} + +#[derive(Unaligned)] +#[repr(u16)] +enum Unaligned2 { + A, +} + +#[derive(Unaligned)] +#[repr(i16)] +enum Unaligned3 { + A, +} + +#[derive(Unaligned)] +#[repr(u32)] +enum Unaligned4 { + A, +} + +#[derive(Unaligned)] +#[repr(i32)] +enum Unaligned5 { + A, +} + +#[derive(Unaligned)] +#[repr(u64)] +enum Unaligned6 { + A, +} + +#[derive(Unaligned)] +#[repr(i64)] +enum Unaligned7 { + A, +} + +#[derive(Unaligned)] +#[repr(usize)] +enum Unaligned8 { + A, +} + +#[derive(Unaligned)] +#[repr(isize)] +enum Unaligned9 { + A, +} + +#[derive(Unaligned)] +#[repr(u8, align(2))] +enum Unaligned10 { + A, +} + +#[derive(Unaligned)] +#[repr(i8, align(2))] +enum Unaligned11 { + A, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +enum Unaligned12 { + A, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +enum Unaligned13 { + A, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes1 { + A, + B(u8), +} + +#[derive(IntoBytes)] +#[repr(C, align(4))] +struct Align4IntoBytes(u32); + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes2 { + A(Align4IntoBytes), +} + +#[derive(IntoBytes)] +#[repr(u32)] +enum IntoBytes3 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes4 { + A(u32), + B(u16), +} + +#[derive(IntoBytes)] +enum IntoBytes5 { + A(u32), +} + +#[derive(IntoBytes)] +#[repr(u8)] +enum IntoBytes6 { + A(T), +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,502 @@ +error: unrecognized representation hint + --> tests/ui-stable/enum.rs:19:8 + | +19 | #[repr("foo")] + | ^^^^^ + +error: unrecognized representation hint + --> tests/ui-stable/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:30:10 + | +30 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-stable/enum.rs:37:12 + | +37 | #[repr(u8, u16)] + | ^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:42:10 + | +42 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:69:10 + | +69 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:74:10 + | +74 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:92:10 + | +92 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:97:10 + | +97 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:103:10 + | +103 | #[derive(FromZeros)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-stable/enum.rs:110:1 + | +110 | / #[repr(u8)] +111 | | enum FromZeros4 { +112 | | A = 1, +113 | | B = 2, +114 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + help: This enum has discriminants which are not literal integers. One of those may define or imply which variant has a discriminant of zero. Use a literal integer to define or imply the variant with a discriminant of zero. + --> tests/ui-stable/enum.rs:119:1 + | +119 | / #[repr(i8)] +120 | | enum FromZeros5 { +121 | | A = NEGATIVE_ONE, +122 | | B, +123 | | } + | |_^ + +error: FromZeros only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-stable/enum.rs:134:1 + | +134 | / #[repr(u8)] +135 | | enum FromZeros7 { +136 | | A = 1, +137 | | B(NotFromZeros), +138 | | } + | |_^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:144:10 + | +144 | #[derive(FromBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:150:8 + | +150 | #[repr(C)] + | ^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:156:8 + | +156 | #[repr(usize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:162:8 + | +162 | #[repr(isize)] + | ^^^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:168:8 + | +168 | #[repr(u32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:174:8 + | +174 | #[repr(i32)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:180:8 + | +180 | #[repr(u64)] + | ^^^ + +error: `FromBytes` only supported on enums with `#[repr(...)]` attributes `u8`, `i8`, `u16`, or `i16` + --> tests/ui-stable/enum.rs:186:8 + | +186 | #[repr(i64)] + | ^^^ + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:456:10 + | +456 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:462:10 + | +462 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:468:10 + | +468 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:474:10 + | +474 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:480:10 + | +480 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:486:10 + | +486 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:492:10 + | +492 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:498:10 + | +498 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/enum.rs:504:10 + | +504 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-stable/enum.rs:511:12 + | +511 | #[repr(u8, align(2))] + | ^^^^^ + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-stable/enum.rs:517:12 + | +517 | #[repr(i8, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/enum.rs:523:18 + | +523 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/enum.rs:529:18 + | +529 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:562:10 + | +562 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/enum.rs:568:10 + | +568 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> tests/ui-stable/enum.rs:576:7 + | +576 | A(T), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + +error[E0565]: meta item in `repr` must be an identifier + --> tests/ui-stable/enum.rs:19:1 + | +19 | #[repr("foo")] + | ^^^^^^^^^^^^^^ + +error[E0552]: unrecognized representation hint + --> tests/ui-stable/enum.rs:25:8 + | +25 | #[repr(foo)] + | ^^^ + | + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0566]: conflicting representation hints + --> tests/ui-stable/enum.rs:37:8 + | +37 | #[repr(u8, u16)] + | ^^ ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +error[E0277]: the trait bound `UnsafeCell<()>: Immutable` is not satisfied + --> tests/ui-stable/enum.rs:51:10 + | +51 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `Immutable`: + &T + &mut T + () + *const T + *mut T + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell: Immutable` is not satisfied + --> tests/ui-stable/enum.rs:59:10 + | +59 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `Immutable` is not implemented for `UnsafeCell` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell` + = help: the following other types implement trait `Immutable`: + &T + &mut T + () + *const T + *mut T + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotTryFromBytes: TryFromBytes` is not satisfied + --> tests/ui-stable/enum.rs:82:10 + | +82 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotTryFromBytes` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotTryFromBytes` + = help: the following other types implement trait `TryFromBytes`: + () + *const T + *mut T + ::is_bit_valid::___ZerocopyVariantStruct_A + ::is_bit_valid::___ZerocopyVariantStruct_A + AtomicBool + AtomicI16 + AtomicI32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotFromZeros: TryFromBytes` is not satisfied + --> tests/ui-stable/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotFromZeros` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotFromZeros` + = help: the following other types implement trait `TryFromBytes`: + () + *const T + *mut T + ::is_bit_valid::___ZerocopyVariantStruct_A + ::is_bit_valid::___ZerocopyVariantStruct_A + AtomicBool + AtomicI16 + AtomicI32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotFromZeros: FromZeros` is not satisfied + --> tests/ui-stable/enum.rs:127:10 + | +127 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotFromZeros` + | + = note: Consider adding `#[derive(FromZeros)]` to `NotFromZeros` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes1` has 1 total byte(s) of padding + --> tests/ui-stable/enum.rs:538:10 + | +538 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes2` has 3 total byte(s) of padding + --> tests/ui-stable/enum.rs:549:10 + | +549 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes3` has 2 total byte(s) of padding + --> tests/ui-stable/enum.rs:555:10 + | +555 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic `Self` types are currently not permitted in anonymous constants + --> tests/ui-stable/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | +note: not a concrete type + --> tests/ui-stable/enum.rs:573:10 + | +573 | #[derive(IntoBytes)] + | ^^^^^^^^^ + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required for `FooU8` to implement `FromBytes` + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_is_from_bytes` + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,272 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +#[derive(FromBytes)] +#[repr(u8)] +enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/enum_from_bytes_u8_too_few.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error: FromBytes only supported on repr(u8) enum with 256 variants + --> tests/ui-stable/enum_from_bytes_u8_too_few.rs:15:1 + | +15 | / #[repr(u8)] +16 | | enum Foo { +17 | | Variant0, +18 | | Variant1, +... | +271 | | Variant254, +272 | | } + | |_^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::KnownLayout; + +use self::util::util::{NotZerocopy, AU16}; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +struct TryFromBytes1 { + value: NotZerocopy, +} + +// +// FromZeros errors +// + +#[derive(FromZeros)] +struct FromZeros1 { + value: NotZerocopy, +} + +// +// FromBytes errors +// + +#[derive(FromBytes)] +struct FromBytes1 { + value: NotZerocopy, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + value: NotZerocopy, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned1 { + aligned: AU16, +} + +// This specifically tests a bug we had in an old version of the code in which +// the trait bound would only be enforced for the first field's type. +#[derive(Unaligned)] +#[repr(C)] +struct Unaligned2 { + unaligned: u8, + aligned: AU16, +} + +#[derive(Unaligned)] +#[repr(transparent)] +struct Unaligned3 { + aligned: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,236 @@ +warning: unused import: `zerocopy::KnownLayout` + --> tests/ui-stable/late_compile_pass.rs:15:5 + | +15 | use zerocopy::KnownLayout; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:29:10 + | +29 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:38:10 + | +38 | #[derive(FromZeros)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::TryFromBytes`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromZeros` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromZeros)]` to `NotZerocopy` + = help: the following other types implement trait `FromZeros`: + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:56:10 + | +56 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::IntoBytes`: + () + AU16 + AtomicBool + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:66:10 + | +66 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:74:10 + | +74 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:81:10 + | +81 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `FromBytes1` to implement `zerocopy::FromBytes` + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `::is_bit_valid::assert_is_from_bytes` + --> tests/ui-stable/late_compile_pass.rs:47:10 + | +47 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +extern crate zerocopy; + +use zerocopy::KnownLayout; + +fn main() {} + +// These tests cause errors which are generated by a later compilation pass than +// the other errors we generate, and so if they're compiled in the same file, +// the compiler will never get to that pass, and so we won't get the errors. + +// +// KnownLayout errors +// + +fn assert_kl(_: &T) {} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | N | N | KL04 | +#[derive(KnownLayout)] +struct KL04(u8, T); + +fn test_kl04(kl: &KL04) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | Y | Y | N | KL06 | +#[derive(KnownLayout)] +struct KL06(u8, T); + +fn test_kl06(kl: &KL06) { + assert_kl(kl); +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | N | KL12 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL12(u8, T); + +fn test_kl12(kl: &KL12) { + assert_kl(kl) +} + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | Y | N | Y | KL13 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL13(u8, T); + +fn test_kl13(t: T) -> impl KnownLayout { + KL13(0u8, t) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/mid_compile_pass.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +error[E0277]: the trait bound `T: KnownLayout` is not satisfied + --> tests/ui-stable/mid_compile_pass.rs:59:26 + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T` +60 | KL13(0u8, t) + | ------------ return type was inferred to be `KL13` here + | + = note: Consider adding `#[derive(KnownLayout)]` to `T` +note: required for `KL13` to implement `KnownLayout` + --> tests/ui-stable/mid_compile_pass.rs:55:10 + | +55 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` with trait `KnownLayout` + | +59 | fn test_kl13(t: T) -> impl KnownLayout { + | +++++++++++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-stable/mid_compile_pass.rs:31:15 + | +30 | fn test_kl04(kl: &KL04) { + | - this type parameter needs to be `Sized` +31 | assert_kl(kl); + | --------- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `KL04` + --> tests/ui-stable/mid_compile_pass.rs:28:8 + | +28 | struct KL04(u8, T); + | ^^^^ +note: required for `KL04` to implement `KnownLayout` + --> tests/ui-stable/mid_compile_pass.rs:27:10 + | +27 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-stable/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +30 - fn test_kl04(kl: &KL04) { +30 + fn test_kl04(kl: &KL04) { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui-stable/mid_compile_pass.rs:40:15 + | +39 | fn test_kl06(kl: &KL06) { + | - this type parameter needs to be `Sized` +40 | assert_kl(kl); + | --------- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `KL06` + --> tests/ui-stable/mid_compile_pass.rs:37:8 + | +37 | struct KL06(u8, T); + | ^^^^ +note: required for `KL06` to implement `KnownLayout` + --> tests/ui-stable/mid_compile_pass.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-stable/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +39 - fn test_kl06(kl: &KL06) { +39 + fn test_kl06(kl: &KL06) { + | + +error[E0277]: the trait bound `KL12: KnownLayout` is not satisfied + --> tests/ui-stable/mid_compile_pass.rs:50:15 + | +50 | assert_kl(kl) + | --------- ^^ the trait `KnownLayout` is not implemented for `KL12` + | | + | required by a bound introduced by this call + | +note: required for `KL12` to implement `KnownLayout` + --> tests/ui-stable/mid_compile_pass.rs:45:10 + | +45 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_kl` + --> tests/ui-stable/mid_compile_pass.rs:23:26 + | +23 | fn assert_kl(_: &T) {} + | ^^^^^^^^^^^ required by this bound in `assert_kl` + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +50 | assert_kl(&kl) + | + +50 | assert_kl(&mut kl) + | ++++ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use zerocopy::{IntoBytes, KnownLayout}; + +use self::util::util::AU16; + +fn main() {} + +// +// KnownLayout errors +// + +struct NotKnownLayout; + +struct NotKnownLayoutDst([u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | N | N | KL00 | +#[derive(KnownLayout)] +struct KL00(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | N | N | Y | N | KL02 | +#[derive(KnownLayout)] +struct KL02(u8, [u8]); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | N | KL08 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL08(u8, NotKnownLayoutDst); + +// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | +// | Y | N | N | Y | KL09 | +#[derive(KnownLayout)] +#[repr(C)] +struct KL09(NotKnownLayout, NotKnownLayout); + +// +// Immutable errors +// + +#[derive(Immutable)] +struct Immutable1 { + a: core::cell::UnsafeCell<()>, +} + +#[derive(Immutable)] +struct Immutable2 { + a: [core::cell::UnsafeCell; 0], +} + +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +#[repr(packed)] +struct TryFromBytesPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(packed(1))] +struct TryFromBytesPackedN { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed)] +struct TryFromBytesCPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed(1))] +struct TryFromBytesCPackedN { + foo: AU16, +} + +// +// IntoBytes errors +// + +// Since `IntoBytes1` has at least one generic parameter, an `IntoBytes` impl is +// emitted in which each field type is given an `Unaligned` bound. Since `foo`'s +// type doesn't implement `Unaligned`, this should fail. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes1 { + foo: AU16, + bar: T, +} + +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes2 { + foo: u8, + bar: AU16, +} + +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes3 { + foo: u8, + // We'd prefer to use AU64 here, but you can't use aligned types in + // packed structs. + bar: u64, +} + +type SliceU8 = [u8]; + +// Padding between `u8` and `SliceU8`. `SliceU8` doesn't syntactically look like +// a slice, so this case is handled by our `Sized` support. +// +// NOTE(#1708): This exists to ensure that our error messages are good when a +// field is unsized. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes4 { + a: u8, + b: SliceU8, +} + +// Padding between `u8` and `[u16]`. `[u16]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes5 { + a: u8, + b: [u16], +} + +// Trailing padding after `[u8]`. `[u8]` is syntactically identifiable as a +// slice, so this case is handled by our `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes6 { + a: u16, + b: [u8], +} + +// Padding between `u8` and `u16` and also trailing padding after `[u8]`. `[u8]` +// is syntactically identifiable as a slice, so this case is handled by our +// `repr(C)` slice DST support. +#[derive(IntoBytes)] +#[repr(C)] +struct IntoBytes7 { + a: u8, + b: u16, + c: [u8], +} + +#[derive(IntoBytes)] +#[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs +struct IntoBytes8 { + a: u8, +} + +#[derive(IntoBytes)] +struct IntoBytes9 { + t: T, +} + +#[derive(IntoBytes)] +#[repr(packed(2))] +struct IntoBytes10 { + t: T, +} + +// `repr(C, packed(2))` is not equivalent to `repr(C, packed)`. +#[derive(IntoBytes)] +#[repr(C, packed(2))] +struct IntoBytes11 { + t0: T, + // Add a second field to avoid triggering the "repr(C) struct with one + // field" special case. + t1: T, +} + +fn is_into_bytes_11() { + if false { + is_into_bytes_11::>(); + } +} + +// `repr(C, align(2))` is not sufficient to guarantee the layout of this type. +#[derive(IntoBytes)] +#[repr(C, align(2))] +struct IntoBytes12 { + t: T, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +struct Unaligned1; + +#[derive(Unaligned)] +#[repr(transparent, align(2))] +struct Unaligned2 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(packed, align(2))] +struct Unaligned3; + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4; + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5; + +#[derive(Unaligned)] +struct Unaligned6; + +#[derive(Unaligned)] +#[repr(packed(2))] +struct Unaligned7; + +// Test the error message emitted when conflicting reprs appear on different +// lines. On the nightly compiler, this emits a "joint span" that spans both +// problematic repr token trees and everything in between. +#[derive(Copy, Clone)] +#[repr(packed(2), C)] +#[derive(Unaligned)] +#[repr(C, packed(2))] +struct WeirdReprSpan; + +#[derive(SplitAt)] +#[repr(C)] +struct SplitAtNotKnownLayout([u8]); + +#[derive(SplitAt, KnownLayout)] +#[repr(C)] +struct SplitAtSized(u8); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/struct.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,445 @@ +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:167:11 + | +167 | #[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs + | ^ + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/struct.rs:172:10 + | +172 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/struct.rs:177:10 + | +177 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout + --> tests/ui-stable/struct.rs:200:10 + | +200 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-stable/struct.rs:211:11 + | +211 | #[repr(C, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:221:16 + | +221 | #[repr(packed, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:225:18 + | +225 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:229:18 + | +229 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/struct.rs:232:10 + | +232 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/struct.rs:235:10 + | +235 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this conflicts with another representation hint + --> tests/ui-stable/struct.rs:245:8 + | +245 | #[repr(C, packed(2))] + | ^ + +error[E0692]: transparent struct cannot have other repr hints + --> tests/ui-stable/struct.rs:215:8 + | +215 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/struct.rs:31:10 + | +31 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL00`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL00` + --> tests/ui-stable/struct.rs:32:8 + | +32 | struct KL00(u8, NotKnownLayoutDst); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/struct.rs:36:10 + | +36 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `KL02`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `KL02` + --> tests/ui-stable/struct.rs:37:8 + | +37 | struct KL02(u8, [u8]); + | ^^^^ + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotKnownLayoutDst: zerocopy::KnownLayout` is not satisfied + --> tests/ui-stable/struct.rs:41:10 + | +41 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayoutDst` + | + = note: Consider adding `#[derive(KnownLayout)]` to `NotKnownLayoutDst` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-stable/struct.rs:47:10 + | +47 | #[derive(KnownLayout)] + | ^^^^^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `NotKnownLayout` + | + = note: Consider adding `#[derive(KnownLayout)]` to `NotKnownLayout` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/struct.rs:55:10 + | +55 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/struct.rs:60:10 + | +60 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = note: required for `[UnsafeCell; 0]` to implement `zerocopy::Immutable` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-stable/struct.rs:71:1 + | +71 | struct TryFromBytesPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-stable/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-stable/struct.rs:77:1 + | +77 | struct TryFromBytesPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-stable/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-stable/struct.rs:83:1 + | +83 | struct TryFromBytesCPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-stable/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-stable/struct.rs:89:1 + | +89 | struct TryFromBytesCPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-stable/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/struct.rs:100:10 + | +100 | #[derive(IntoBytes)] + | ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes2` has 1 total byte(s) of padding + --> tests/ui-stable/struct.rs:107:10 + | +107 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes3` has 1 total byte(s) of padding + --> tests/ui-stable/struct.rs:114:10 + | +114 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/struct.rs:130:10 + | +130 | #[derive(IntoBytes)] + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `IntoBytes4`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `IntoBytes4` + --> tests/ui-stable/struct.rs:132:8 + | +132 | struct IntoBytes4 { + | ^^^^^^^^^^ + = note: required for `IntoBytes4` to implement `macro_util::__size_of::Sized` +note: required by a bound in `macro_util::__size_of::size_of` + --> $WORKSPACE/src/util/macro_util.rs + | + | pub const fn size_of() -> usize { + | ^^^^^ required by this bound in `size_of` + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `[u8]` is unsized + --> tests/ui-stable/struct.rs:134:8 + | +134 | b: SliceU8, + | ^^^^^^^ `IntoBytes` needs all field types to be `Sized` in order to determine whether there is padding + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: consider using `#[repr(packed)]` to remove padding + = note: `IntoBytes` does not require the fields of `#[repr(packed)]` types to be `Sized` + = note: required for `[u8]` to implement `macro_util::__size_of::Sized` +note: required by a bound in `macro_util::__size_of::size_of` + --> $WORKSPACE/src/util/macro_util.rs + | + | pub const fn size_of() -> usize { + | ^^^^^ required by this bound in `size_of` + +error[E0277]: `IntoBytes5` has one or more padding bytes + --> tests/ui-stable/struct.rs:139:10 + | +139 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes6` has one or more padding bytes + --> tests/ui-stable/struct.rs:148:10 + | +148 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes7` has one or more padding bytes + --> tests/ui-stable/struct.rs:158:10 + | +158 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `DynamicPaddingFree` is not implemented for `()` + but trait `DynamicPaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0587]: type has conflicting packed and align representation hints + --> tests/ui-stable/struct.rs:222:1 + | +222 | struct Unaligned3; + | ^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `SplitAtNotKnownLayout: zerocopy::KnownLayout` is not satisfied + --> tests/ui-stable/struct.rs:248:10 + | +248 | #[derive(SplitAt)] + | ^^^^^^^ the trait `zerocopy::KnownLayout` is not implemented for `SplitAtNotKnownLayout` + | + = note: Consider adding `#[derive(KnownLayout)]` to `SplitAtNotKnownLayout` + = help: the following other types implement trait `zerocopy::KnownLayout`: + &T + &mut T + () + *const T + *mut T + AU16 + AtomicBool + AtomicI16 + and $N others +note: required by a bound in `SplitAt` + --> $WORKSPACE/src/split_at.rs + | + | pub unsafe trait SplitAt: KnownLayout { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `SplitAt` + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `u8: SplitAt` is not satisfied + --> tests/ui-stable/struct.rs:252:10 + | +252 | #[derive(SplitAt, KnownLayout)] + | ^^^^^^^ the trait `SplitAt` is not implemented for `u8` + | + = note: Consider adding `#[derive(SplitAt)]` to `u8` + = help: the following other types implement trait `SplitAt`: + SplitAtNotKnownLayout + SplitAtSized + [T] + = help: see issue #48214 + = note: this error originates in the derive macro `SplitAt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied + --> tests/ui-stable/struct.rs:195:28 + | +195 | is_into_bytes_11::>(); + | ^^^^^^^^^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `AU16` + | + = note: Consider adding `#[derive(Unaligned)]` to `AU16` + = help: the following other types implement trait `zerocopy::Unaligned`: + () + AtomicBool + AtomicI8 + AtomicU8 + Cell + F32 + F64 + I128 + and $N others +note: required for `IntoBytes11` to implement `zerocopy::IntoBytes` + --> tests/ui-stable/struct.rs:184:10 + | +184 | #[derive(IntoBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `is_into_bytes_11` + --> tests/ui-stable/struct.rs:193:24 + | +193 | fn is_into_bytes_11() { + | ^^^^^^^^^ required by this bound in `is_into_bytes_11` + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,109 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#[macro_use] +extern crate zerocopy; + +#[path = "../include.rs"] +mod util; + +use std::mem::ManuallyDrop; + +use self::util::util::AU16; + +fn main() {} + +// +// Immutable errors +// + +#[derive(Immutable)] +union Immutable1 { + a: ManuallyDrop>, +} + +// +// IntoBytes errors +// + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes1 { + foo: ManuallyDrop, +} + +#[derive(IntoBytes)] +#[repr(C)] +union IntoBytes2 { + foo: u8, + bar: [u8; 2], +} + +// Need a `repr` attribute +#[derive(IntoBytes)] +union IntoBytes3 { + foo: u8, +} + +// `repr(packed(2))` isn't equivalent to `repr(packed)` +#[derive(IntoBytes)] +#[repr(packed(2))] +union IntoBytes4 { + foo: u8, +} + +// +// Unaligned errors +// + +#[derive(Unaligned)] +#[repr(C, align(2))] +union Unaligned1 { + foo: i16, + bar: AU16, +} + +// Transparent unions are unstable; see issue #60405 +// for more information. + +// #[derive(Unaligned)] +// #[repr(transparent, align(2))] +// union Unaligned2 { +// foo: u8, +// } + +#[derive(Unaligned)] +#[repr(packed, align(2))] +union Unaligned3 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(1), align(2))] +struct Unaligned4 { + foo: u8, +} + +#[derive(Unaligned)] +#[repr(align(2), align(4))] +struct Unaligned5 { + foo: u8, +} + +#[derive(Unaligned)] +union Unaligned6 { + foo: i16, + bar: AU16, +} + +#[derive(Unaligned)] +#[repr(packed(2))] +union Unaligned7 { + foo: i16, + bar: AU16, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,130 @@ +error: unsupported on types with type parameters + --> tests/ui-stable/union.rs:34:10 + | +34 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-stable/union.rs:48:10 + | +48 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must be #[repr(C)], #[repr(packed)], or #[repr(transparent)] + --> tests/ui-stable/union.rs:54:10 + | +54 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive `Unaligned` on type with alignment greater than 1 + --> tests/ui-stable/union.rs:65:11 + | +65 | #[repr(C, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/union.rs:81:16 + | +81 | #[repr(packed, align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/union.rs:87:18 + | +87 | #[repr(align(1), align(2))] + | ^^^^^ + +error: this conflicts with another representation hint + --> tests/ui-stable/union.rs:93:18 + | +93 | #[repr(align(2), align(4))] + | ^^^^^ + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/union.rs:98:10 + | +98 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment + --> tests/ui-stable/union.rs:104:10 + | +104 | #[derive(Unaligned)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition name: `zerocopy_derive_union_into_bytes` + --> tests/ui-stable/union.rs:40:10 + | +40 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = help: expected names are: `docsrs`, `feature`, and `test` and 31 more + = note: using a cfg inside a derive macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try referring to `IntoBytes` crate for guidance on how handle this unexpected cfg + = help: the derive macro `IntoBytes` may come from an old version of the `zerocopy_derive` crate, try updating your dependency with `cargo update -p zerocopy_derive` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `UnsafeCell<()>: zerocopy::Immutable` is not satisfied + --> tests/ui-stable/union.rs:25:10 + | +25 | #[derive(Immutable)] + | ^^^^^^^^^ the trait `zerocopy::Immutable` is not implemented for `UnsafeCell<()>` + | + = note: Consider adding `#[derive(Immutable)]` to `UnsafeCell<()>` + = help: the following other types implement trait `zerocopy::Immutable`: + &T + &mut T + () + *const T + *mut T + AU16 + F32 + F64 + and $N others + = note: required for `ManuallyDrop>` to implement `zerocopy::Immutable` + = help: see issue #48214 + = note: this error originates in the derive macro `Immutable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `IntoBytes2` has 1 total byte(s) of padding + --> tests/ui-stable/union.rs:40:10 + | +40 | #[derive(IntoBytes)] + | ^^^^^^^^^ types with padding cannot implement `IntoBytes` + | + = note: consider using `zerocopy::Unalign` to lower the alignment of individual fields + = note: consider adding explicit fields where padding would be + = note: consider using `#[repr(packed)]` to remove padding + = help: the trait `PaddingFree` is not implemented for `()` + but trait `PaddingFree` is implemented for it + = help: see issue #48214 + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0587]: type has conflicting packed and align representation hints + --> tests/ui-stable/union.rs:82:1 + | +82 | union Unaligned3 { + | ^^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-stable/union.rs:106:1 + | +106 | union Unaligned7 { + | ^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-stable/../include.rs + | + | pub struct AU16(pub u16); + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! See: https://github.com/google/zerocopy/issues/553 +//! zerocopy must still allow derives of deprecated types. +//! This test has a hand-written impl of a deprecated type, and should result in a compilation +//! error. If zerocopy does not tack an allow(deprecated) annotation onto its impls, then this +//! test will fail because more than one compile error will be generated. +#![deny(deprecated)] + +extern crate zerocopy; + +use zerocopy::IntoBytes; + +#[derive(IntoBytes)] +#[repr(C)] +union Foo { + a: u8, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error: requires --cfg zerocopy_derive_union_into_bytes; + please let us know you use this feature: https://github.com/google/zerocopy/discussions/1802 + --> tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs:20:10 + | +20 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition name: `zerocopy_derive_union_into_bytes` + --> tests/ui-stable/union_into_bytes_cfg/union_into_bytes_cfg.rs:20:10 + | +20 | #[derive(IntoBytes)] + | ^^^^^^^^^ + | + = help: expected names are: `docsrs`, `feature`, and `test` and 31 more + = note: using a cfg inside a derive macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try referring to `IntoBytes` crate for guidance on how handle this unexpected cfg + = help: the derive macro `IntoBytes` may come from an old version of the `zerocopy_derive` crate, try updating your dependency with `cargo update -p zerocopy_derive` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A union is `imp::FromBytes` if: +// - all fields are `imp::FromBytes` + +#[derive(Clone, Copy, imp::Immutable, imp::FromBytes)] +union Zst { + a: (), +} + +util_assert_impl_all!(Zst: imp::FromBytes); +test_trivial_is_bit_valid!(Zst => test_zst_trivial_is_bit_valid); + +#[derive(imp::Immutable, imp::FromBytes)] +union One { + a: u8, +} + +util_assert_impl_all!(One: imp::FromBytes); +test_trivial_is_bit_valid!(One => test_one_trivial_is_bit_valid); + +#[derive(imp::Immutable, imp::FromBytes)] +union Two { + a: u8, + b: Zst, +} + +util_assert_impl_all!(Two: imp::FromBytes); +test_trivial_is_bit_valid!(Two => test_two_trivial_is_bit_valid); + +#[derive(imp::Immutable, imp::FromBytes)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [u8]>, + f: imp::PhantomData<&'static str>, + g: imp::PhantomData, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromBytes); +test_trivial_is_bit_valid!(TypeParams<'static, (), imp::IntoIter<()>> => test_type_params_trivial_is_bit_valid); + +// Deriving `imp::FromBytes` should work if the union has bounded parameters. + +#[derive(imp::Immutable, imp::FromBytes)] +#[repr(C)] +union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::FromBytes, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Copy + imp::FromBytes, +{ + a: [T; N], + b: imp::PhantomData<&'a &'b ()>, +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromBytes); +test_trivial_is_bit_valid!(WithParams<'static, 'static, u8, 42> => test_with_params_trivial_is_bit_valid); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_zeros.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_zeros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_zeros.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_from_zeros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A union is `imp::FromZeros` if: +// - all fields are `imp::FromZeros` + +#[derive(Clone, Copy, imp::Immutable, imp::FromZeros)] +union Zst { + a: (), +} + +util_assert_impl_all!(Zst: imp::FromZeros); + +#[derive(imp::Immutable, imp::FromZeros)] +union One { + a: bool, +} + +util_assert_impl_all!(One: imp::FromZeros); + +#[derive(imp::Immutable, imp::FromZeros)] +union Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::FromZeros); + +#[derive(imp::Immutable, imp::FromZeros)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [u8]>, + f: imp::PhantomData<&'static str>, + g: imp::PhantomData, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromZeros); + +// Deriving `imp::FromZeros` should work if the union has bounded parameters. + +#[derive(imp::Immutable, imp::FromZeros)] +#[repr(C)] +union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::FromZeros, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Copy + imp::FromZeros, +{ + a: [T; N], + b: imp::PhantomData<&'a &'b ()>, +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromZeros); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_known_layout.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_known_layout.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_known_layout.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_known_layout.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,66 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(Clone, Copy, imp::KnownLayout)] +union Zst { + a: (), +} + +util_assert_impl_all!(Zst: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +union One { + a: bool, +} + +util_assert_impl_all!(One: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +union Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::KnownLayout); + +#[derive(imp::KnownLayout)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [u8]>, + f: imp::PhantomData<&'static str>, + g: imp::PhantomData, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::KnownLayout); + +// Deriving `imp::KnownLayout` should work if the union has bounded parameters. + +#[derive(imp::KnownLayout)] +#[repr(C)] +union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::KnownLayout, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Copy + imp::KnownLayout, +{ + a: [T; N], + b: imp::PhantomData<&'a &'b ()>, +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::KnownLayout); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_no_cell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_no_cell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_no_cell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_no_cell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +#[derive(Clone, Copy, imp::Immutable)] +union Zst { + a: (), +} + +util_assert_impl_all!(Zst: imp::Immutable); + +#[derive(imp::Immutable)] +union One { + a: bool, +} + +util_assert_impl_all!(One: imp::Immutable); + +#[derive(imp::Immutable)] +union Two { + a: bool, + b: Zst, +} + +util_assert_impl_all!(Two: imp::Immutable); + +#[derive(imp::Immutable)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [::core::primitive::u8]>, + f: imp::PhantomData<&'static ::core::primitive::str>, + g: imp::PhantomData, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::Immutable); + +// Deriving `imp::Immutable` should work if the union has bounded parameters. + +#[derive(imp::Immutable)] +#[repr(C)] +union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::Immutable, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::Copy + imp::Immutable, +{ + a: [T; N], + b: imp::PhantomData<&'a &'b ()>, + c: imp::PhantomData>, + d: &'a imp::UnsafeCell<()>, +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::Immutable); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_to_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_to_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_to_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_to_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,75 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A union is `imp::IntoBytes` if: +// - all fields are `imp::IntoBytes` +// - `repr(C)` or `repr(transparent)` and +// - no padding (size of union equals size of each field type) +// - `repr(packed)` + +#[derive(imp::IntoBytes, Clone, Copy)] +#[repr(C)] +union CZst { + a: (), +} + +util_assert_impl_all!(CZst: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C)] +union C { + a: u8, + b: u8, +} + +util_assert_impl_all!(C: imp::IntoBytes); + +// Transparent unions are unstable; see issue #60405 +// for more information. + +// #[derive(imp::IntoBytes)] +// #[repr(transparent)] +// union Transparent { +// a: u8, +// b: CZst, +// } + +// is_as_bytes!(Transparent); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +union CZstPacked { + a: (), +} + +util_assert_impl_all!(CZstPacked: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +union CPacked { + a: u8, + b: i8, +} + +util_assert_impl_all!(CPacked: imp::IntoBytes); + +#[derive(imp::IntoBytes)] +#[repr(C, packed)] +union CMultibytePacked { + a: i32, + b: u32, + c: f32, +} + +util_assert_impl_all!(CMultibytePacked: imp::IntoBytes); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_try_from_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_try_from_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_try_from_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_try_from_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,183 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A struct is `imp::TryFromBytes` if: +// - any of its fields are `imp::TryFromBytes` + +#[derive(imp::Immutable, imp::TryFromBytes)] +union One { + a: u8, +} + +util_assert_impl_all!(One: imp::TryFromBytes); + +#[test] +fn one() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&One { a: 42 }); + let candidate = candidate.forget_aligned(); + // SAFETY: `&One` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate); + assert!(is_bit_valid); +} + +#[derive(imp::Immutable, imp::TryFromBytes)] +#[repr(C)] +union Two { + a: bool, + b: bool, +} + +util_assert_impl_all!(Two: imp::TryFromBytes); + +#[test] +fn two() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate_a = ::zerocopy::Ptr::from_ref(&Two { a: false }); + let candidate_a = candidate_a.forget_aligned(); + // SAFETY: `&Two` consists entirely of initialized bytes. + let candidate_a = unsafe { candidate_a.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate_a); + assert!(is_bit_valid); + + let candidate_b = ::zerocopy::Ptr::from_ref(&Two { b: true }); + let candidate_b = candidate_b.forget_aligned(); + // SAFETY: `&Two` consists entirely of initialized bytes. + let candidate_b = unsafe { candidate_b.assume_initialized() }; + let is_bit_valid = ::is_bit_valid(candidate_b); + assert!(is_bit_valid); +} + +#[test] +fn two_bad() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + let candidate = candidate.forget_aligned(); + // SAFETY: `&[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { candidate.cast_unsized_unchecked(|p| p.cast::()) }; + + // SAFETY: `candidate`'s referent is as-initialized as `Two`. + let candidate = unsafe { candidate.assume_initialized() }; + + let is_bit_valid = ::is_bit_valid(candidate); + assert!(!is_bit_valid); +} + +#[derive(imp::Immutable, imp::TryFromBytes)] +#[repr(C)] +union BoolAndZst { + a: bool, + b: (), +} + +#[test] +fn bool_and_zst() { + // FIXME(#5): Use `try_transmute` in this test once it's available. + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + let candidate = candidate.forget_aligned(); + // SAFETY: `&[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { candidate.cast_unsized_unchecked(|p| p.cast::()) }; + + // SAFETY: `candidate`'s referent is fully initialized. + let candidate = unsafe { candidate.assume_initialized() }; + + let is_bit_valid = ::is_bit_valid(candidate); + assert!(is_bit_valid); +} + +#[derive(imp::FromBytes)] +#[repr(C)] +union MaybeFromBytes { + t: T, +} + +#[test] +fn test_maybe_from_bytes() { + // When deriving `FromBytes` on a type with no generic parameters, we emit a + // trivial `is_bit_valid` impl that always returns true. This test confirms + // that we *don't* spuriously do that when generic parameters are present. + + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + let candidate = candidate.bikeshed_recall_initialized_from_bytes(); + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = + unsafe { candidate.cast_unsized_unchecked(|p| p.cast::>()) }; + + // SAFETY: `[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = as imp::TryFromBytes>::is_bit_valid(candidate); + imp::assert!(!is_bit_valid); +} + +#[derive(imp::Immutable, imp::TryFromBytes)] +#[repr(C)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: I::Item, + b: u8, + c: imp::PhantomData<&'a [u8]>, + d: imp::PhantomData<&'static str>, + e: imp::PhantomData, + f: T, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::TryFromBytes); +util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::TryFromBytes); +util_assert_impl_all!(TypeParams<'static, [util::AU16; 2], imp::IntoIter<()>>: imp::TryFromBytes); + +// Deriving `imp::TryFromBytes` should work if the union has bounded parameters. + +#[derive(imp::Immutable, imp::TryFromBytes)] +#[repr(C)] +union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::TryFromBytes, const N: usize> +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + imp::TryFromBytes + imp::Copy, +{ + a: imp::PhantomData<&'a &'b ()>, + b: T, +} + +util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::TryFromBytes); + +#[derive(Clone, Copy, imp::TryFromBytes, imp::Immutable)] +struct A; + +#[derive(imp::TryFromBytes)] +union B { + a: A, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_unaligned.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_unaligned.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/union_unaligned.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/union_unaligned.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,77 @@ +// Copyright 2019 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// A union is `Unaligned` if: +// - `repr(align)` is no more than 1 and either +// - `repr(C)` or `repr(transparent)` and +// - all fields `Unaligned` +// - `repr(packed)` + +#[derive(imp::Unaligned)] +#[repr(C)] +union Foo { + a: imp::u8, +} + +util_assert_impl_all!(Foo: imp::Unaligned); + +// Transparent unions are unstable; see issue #60405 +// for more information. + +// #[derive(Unaligned)] +// #[repr(transparent)] +// union Bar { +// a: u8, +// } + +// is_unaligned!(Bar); + +#[derive(imp::Unaligned)] +#[repr(packed)] +union Baz { + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. + a: u16, +} + +util_assert_impl_all!(Baz: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(C, align(1))] +union FooAlign { + a: imp::u8, +} + +util_assert_impl_all!(FooAlign: imp::Unaligned); + +#[derive(imp::Unaligned)] +#[repr(C)] +union TypeParams<'a, T: imp::Copy, I: imp::Iterator> +where + I::Item: imp::Copy, +{ + a: T, + c: I::Item, + d: u8, + e: imp::PhantomData<&'a [imp::u8]>, + f: imp::PhantomData<&'static imp::str>, + g: imp::PhantomData, +} + +util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::Unaligned); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/unsafe_cell.rs clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/unsafe_cell.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zerocopy-derive/tests/unsafe_cell.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zerocopy-derive/tests/unsafe_cell.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +// Copyright 2025 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +// See comment in `include.rs` for why we disable the prelude. +#![no_implicit_prelude] +#![allow(warnings)] + +include!("include.rs"); + +// Test to make sure that all of our derives are compatible with `UnsafeCell`s. +// +// We test both `FromBytes` and `FromZeros`, as the `FromBytes` implied derive +// of `TryFromBytes` emits a trivial `is_bit_valid` impl - we want to test the +// non-trivial impl, which deriving `FromZeros` accomplishes. + +#[derive(imp::FromBytes, imp::IntoBytes, imp::KnownLayout, imp::Unaligned)] +#[repr(C)] +struct StructFromBytes(imp::UnsafeCell); + +#[derive(imp::FromZeros, imp::IntoBytes, imp::KnownLayout, imp::Unaligned)] +#[repr(C)] +struct StructFromZeros(imp::UnsafeCell); + +#[derive(imp::FromZeros, imp::IntoBytes, imp::KnownLayout, imp::Unaligned)] +#[repr(u8)] +enum EnumFromZeros { + A(imp::UnsafeCell), +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"8a3d559ea62fc8b7ef4723bf83ea21e31a72063053267881fe67ed4c3958151f","CHANGELOG.md":"3b6dcd5ee2c52ab91265c12d8dfaa7d0a2d4f05a08de2557041dece734e98e41","Cargo.lock":"9afddfc1a3156acdbd8e28ea2da635184655732493f81b47943893fdcf474b2e","Cargo.toml":"388c982105d008dcf5d6238440dcfdddeaaba6c2062795234158638211220584","Cargo.toml.orig":"b7354c409e245fd2e26c13d88f81a9c1dc59bec7a88516ad57b91fc4a786730b","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"d30047bca3b516639339a3c279bb84c3483124fb5a9dafe3c75056a85090e745","LICENSE-ZLIB":"d201d14804d3bcd3b944147173175e4abfbd838b7c8069b6bd3452496bf13e6c","README.md":"1adae359f289c130fe2b098b412820d7da9924cb1bc52aeee8707971bab412b2","src/bit_depth.rs":"879b5b4b3ac99fc567f8d281662dc4125109f835b3944d023d038a084b2c0dd9","src/bytestream.rs":"a8dbecb5f82bcb9b7b7876fed2325c89f9ed9b1263494225d43468f1edbb12a5","src/bytestream/reader.rs":"636fbe748d5942d4fb6894f5d4ef221281ab95e402e614ad7dbe67d6f0dad5a6","src/bytestream/reader/no_std_readers.rs":"2512f0ab865c816754e7eca02ebad55b7dde0470cf6c942ad81ffb29ec2dc763","src/bytestream/reader/std_readers.rs":"3bc05b80b11d150f022409ff69fcb6af4677aea446e967ca93174df096651037","src/bytestream/traits.rs":"ff864a329da213b51bb38cbbf5c763661d78b52f9f8e62e33ebe2eed47458025","src/bytestream/writer.rs":"8152b7cdc966828025a4edf417d522c665339c906ca0892cab8410ffb9d54990","src/bytestream/writer/no_std_writer.rs":"6c57a2b26fc9519787c14a694a7adf74e6e5b919ee9b269eedff494c0a476658","src/bytestream/writer/std_writer.rs":"838996feb755763cb78db981b51f5d60015ce1dffbd580ae73e781b1e0166fa2","src/colorspace.rs":"83bb7668285abeb9b4ddbc6eec00ea954c41a565cc154f6e910dd46e952ce7dc","src/lib.rs":"7a6943465b77d9827c3a1db1113b4f44e25afee6622fb6abcd378da79afd2a64","src/log.rs":"1655ea004aee621e4a93e57b6787693348348d8bb23f06feffc1e49537ea7565","src/options.rs":"9a29e94bed783c49f664f1583705fdd5a8b80a5e4e78868fd229d12691eec09d","src/options/decoder.rs":"187a1bd16e51ecad3edbd6ca5fdad8be2b84af581434aad132b92a780cabb7b8","src/options/encoder.rs":"57a5c12b1808a67c3bd70bce490cf7dea249263c67432bbafb0465c7769f7fa1","src/result.rs":"92a098ba09ae4e5202da45a2d2165a6df804d3952e8c657950d064e4714afcaa","src/serde.rs":"aad9fa47df57bbfc851cfd63c4e9b2f0fe061c1f76bfbd6bb5acdda840799a22"},"package":"111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5132d177b04fe3661f4f6bb249fe4a233ac7da2d" + }, + "path_in_vcs": "crates/zune-core" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/zune-core/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +## 0.2.14 + +- Fixed building with no-std +- Add `peek_at` and `pos` for writer +- Make serde non default +- Add option to make PNG add an alpha channel + +## 0.2.12 + +- Add endianness conversion +- Hide exposed values for EncoderOptions +- Add Float32 bit depth +- Remove support for BitDepth 10 and 12 +- Add bit_size method + +## 0.2.1 + +Improve documentation on various parts + +## 0.2.0 + +Initial version \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "zune-core" +version = "0.5.0" +dependencies = [ + "log", + "serde", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "zune-core" +version = "0.5.0" +build = false +exclude = ["tests/"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Core utilities for image processing in the zune family of crates" +readme = "README.md" +keywords = ["image"] +categories = [ + "multimedia::images", + "multimedia::encoding", +] +license = "MIT OR Apache-2.0 OR Zlib" +repository = "https://github.com/etemesi254/zune-image" + +[features] +std = [] + +[lib] +name = "zune_core" +path = "src/lib.rs" + +[dependencies.log] +version = "0.4" +optional = true + +[dependencies.serde] +version = "1.0" +optional = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[package] +name = "zune-core" +version = "0.5.0" +edition = "2021" +description = "Core utilities for image processing in the zune family of crates" +exclude = ["tests/"] +repository = "https://github.com/etemesi254/zune-image" +keywords = ["image"] +categories = ["multimedia::images", "multimedia::encoding"] +license = "MIT OR Apache-2.0 OR Zlib" + +[features] +# When present, we can use std facilities to detect +# if a specific feature exists +# Not enabled by default. Other zune crates can enable dep:zune-core/std by default. +# But if we enable it here, they can't disable it anymore. +# See: https://github.com/rust-lang/cargo/issues/8366 +std = [] + +[dependencies] +log = { version = "0.4", optional = true } +serde = { version = "1.0", optional = true } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) zune-image developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-ZLIB clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-ZLIB --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/LICENSE-ZLIB 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/LICENSE-ZLIB 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +zlib License + +(C) zune-image developers + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/README.md clamav-1.4.6+dfsg/.cargo/vendor/zune-core/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +## Zune core + +Core primitives necessary for image manipulations + +This crate contains small set of primitives +necessary for image manipulations which are shared among most `zune-` family +of decoders and encoders. + +### Items present + +Currently,it contains. + +- Colorspace definitions +- Bit depth definitions. +- Decoder and encoder options \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bit_depth.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bit_depth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bit_depth.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bit_depth.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image bit depth, information and manipulations + +/// The image bit depth. +/// +/// The library successfully supports depths up to +/// 16 bits, as the underlying storage is usually a `u16`. +/// +/// This allows us to comfortably support a wide variety of images +/// e.g 10 bit av1, 16 bit png and ppm. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitDepth { + /// U8 bit depth. + /// + /// Images with such bit depth use [`u8`] to store + /// pixels and use the whole range from 0-255. + /// + /// It is currently the smallest supported bit depth + /// by the library. + /// + /// For images with bit depths lower than this, they will be scaled + /// to this bit depth + Eight, + /// U16 bit depth + /// + /// Images with such bit depths use [`u16`] to store values and use the whole range + /// i.e 0-65535 + /// + /// Data is stored and processed in native endian. + Sixteen, + /// Floating point 32 bit data, range is 0.0 to 1.0 + /// + /// Uses f32 to store data + Float32, + /// Bit depth information is unknown + Unknown +} + +/// The underlying bit representation of the image +/// +/// This represents the minimum rust type that +/// can be used to represent image data, required +/// by `Channel` struct in zune-image +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitType { + /// Images represented using a [`u8`] as their + /// underlying pixel storage + U8, + /// Images represented using a [`u16`] as their + /// underlying pixel storage. + U16, + /// Images represented using a [`f32`] as their + /// underlying pixel storage + F32 +} + +impl BitType { + /// Return the equivalent of the image bit type's depth + pub fn to_depth(self) -> BitDepth { + match self { + BitType::U8 => BitDepth::Eight, + BitType::U16 => BitDepth::Sixteen, + BitType::F32 => BitDepth::Float32 + } + } +} + +impl Default for BitDepth { + fn default() -> Self { + Self::Unknown + } +} + +impl BitDepth { + /// Get the max value supported by the bit depth + /// + /// During conversion from one bit depth to another + /// + /// larger values should be clamped to this bit depth + #[rustfmt::skip] + #[allow(clippy::zero_prefixed_literal)] + pub const fn max_value(self) -> u16 + { + match self + { + Self::Eight => (1 << 08) - 1, + Self::Sixteen => u16::MAX, + Self::Float32 => 1, + Self::Unknown => 0, + } + } + + /// Return the minimum number of bits that can be used to represent + /// each pixel in the image + /// + /// All bit depths below 8 return a bit type of `BitType::U8`. + /// and all those above 8 and below 16 return a bit type of `BitType::SixTeen` + /// + /// # Returns + /// An enum whose variants represent the minimum size for an unsigned integer + /// which can store the image pixels without overflow + /// + /// # Example + /// + /// ``` + /// use zune_core::bit_depth::{BitDepth, BitType}; + /// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8); + /// + /// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16); + /// ``` + /// + /// See also [size_of](BitDepth::size_of) + pub const fn bit_type(self) -> BitType { + match self { + Self::Eight => BitType::U8, + Self::Sixteen => BitType::U16, + Self::Float32 => BitType::F32, + Self::Unknown => panic!("Unknown bit type") + } + } + /// Get the number of bytes needed to store a specific bit depth + /// + /// + /// # Example + /// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store + /// the pixels, and a size_of [`u8`] is 1 + /// + /// For images greater than 8 bits and less than 16 bits(2 bytes), we can use a [`u16`] to + /// store the pixels, a size_of [`u16`] is 2. + /// ``` + /// use zune_core::bit_depth::BitDepth; + /// let depth = BitDepth::Sixteen; + /// // greater 12 bits is greater than 8 and less than 16 + /// assert_eq!(depth.size_of(),2); + /// ``` + pub const fn size_of(self) -> usize { + match self { + Self::Eight => core::mem::size_of::(), + Self::Sixteen => core::mem::size_of::(), + Self::Float32 => core::mem::size_of::(), + Self::Unknown => panic!("Unknown bit type") + } + } + pub const fn bit_size(&self) -> usize { + self.size_of() * 8 + } +} + +/// Byte endianness of returned samples +/// this is useful when the decoder returns samples which span more +/// than one byte yet the type returned is `&[u8]` +/// +/// This helps you interpret how those bytes should be reconstructed +/// to a higher order type +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum ByteEndian { + /// Little Endian byte-order + LE, + /// Big Endian byte-order + BE +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/no_std_readers.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/no_std_readers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/no_std_readers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/no_std_readers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,198 @@ +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; +use crate::bytestream::ZByteReaderTrait; +/// Wraps an in memory buffer providing it with a `Seek` method +/// but works in `no_std` environments +/// +/// `std::io::Cursor` is available in std environments, but we also need support +/// for `no_std` environments so this serves as a drop in replacement +pub struct ZCursor> { + stream: T, + position: usize +} + +impl> ZCursor { + pub fn new(buffer: T) -> ZCursor { + ZCursor { + stream: buffer, + position: 0 + } + } +} + +impl> ZCursor { + /// Move forward `num` bytes from + /// the current position. + /// + /// It doesn't check that position overflowed, new position + /// may point past the internal buffer, all subsequent reads will + /// either return an error or zero depending on the method called + #[inline] + pub fn skip(&mut self, num: usize) { + // Can this overflow ?? + self.position = self.position.wrapping_add(num); + } + /// Move back `num` bytes from the current position + /// + /// + /// This saturates at zero, it can never be negative or wraparound + /// when the value becomes too small + #[inline] + pub fn rewind(&mut self, num: usize) { + self.position = self.position.saturating_sub(num); + } +} + +impl> ZByteReaderTrait for ZCursor { + #[inline(always)] + fn read_byte_no_error(&mut self) -> u8 { + let byte = self.stream.as_ref().get(self.position).unwrap_or(&0); + self.position += 1; + *byte + } + #[inline(always)] + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + let bytes_read = self.read_bytes(buf)?; + if bytes_read != buf.len() { + // restore read to initial position it was in. + self.rewind(bytes_read); + // not all bytes were read. + return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len())); + } + Ok(()) + } + + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> { + if self.position + N <= self.stream.as_ref().len() { + // we are in bounds + let reference = self.stream.as_ref(); + let position = self.position; + if let Some(buf_ref) = reference.get(position..position + N) { + self.position += N; + buf.copy_from_slice(buf_ref); + return Ok(()); + } + } + Err(ZByteIoError::Generic("Cannot satisfy read")) + } + + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]) { + if self.position + N <= self.stream.as_ref().len() { + // we are in bounds + let reference = self.stream.as_ref(); + let position = self.position; + if let Some(buf_ref) = reference.get(position..position + N) { + self.position += N; + buf.copy_from_slice(buf_ref); + } + } + } + + #[inline(always)] + fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + let len = self.peek_bytes(buf)?; + self.skip(len); + Ok(len) + } + + #[inline(always)] + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result { + let stream_end = self.stream.as_ref().len(); + + let start = core::cmp::min(self.position, stream_end); + let end = core::cmp::min(self.position + buf.len(), stream_end); + + let slice = self.stream.as_ref().get(start..end).unwrap(); + buf[..slice.len()].copy_from_slice(slice); + let len = slice.len(); + + Ok(len) + } + + #[inline(always)] + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + self.read_exact_bytes(buf)?; + self.rewind(buf.len()); + Ok(()) + } + + #[inline(always)] + fn z_seek(&mut self, from: ZSeekFrom) -> Result { + let (base_pos, offset) = match from { + ZSeekFrom::Start(n) => { + self.position = n as usize; + return Ok(n); + } + ZSeekFrom::End(n) => (self.stream.as_ref().len(), n as isize), + ZSeekFrom::Current(n) => (self.position, n as isize) + }; + match base_pos.checked_add_signed(offset) { + Some(n) => { + self.position = n; + Ok(self.position as u64) + } + None => Err(ZByteIoError::SeekError("Negative seek")) + } + } + + #[inline(always)] + fn is_eof(&mut self) -> Result { + Ok(self.position >= self.stream.as_ref().len()) + } + #[inline(always)] + fn z_position(&mut self) -> Result { + Ok(self.position as u64) + } + + fn read_remaining(&mut self, sink: &mut alloc::vec::Vec) -> Result { + let start = self.position; + let end = self.stream.as_ref().len(); + match self.stream.as_ref().get(start..end) { + None => { + return Err(ZByteIoError::Generic( + "Somehow read remaining couldn't satisfy it's invariants" + )) + } + Some(e) => { + sink.extend_from_slice(e); + } + } + self.skip(end - start); + Ok(end - start) + } +} + +#[cfg(feature = "std")] +impl> std::io::Seek for ZCursor { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + let (base_pos, offset) = match pos { + std::io::SeekFrom::Start(n) => { + self.position = n as usize; + return Ok(n); + } + std::io::SeekFrom::End(n) => (self.stream.as_ref().len(), n as isize), + std::io::SeekFrom::Current(n) => (self.position, n as isize) + }; + match base_pos.checked_add_signed(offset) { + Some(n) => { + self.position = n; + Ok(self.position as u64) + } + None => Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Negative seek" + )) + } + } +} +// +// #[cfg(feature = "std")] +// impl> std::io::Read for ZCursor { +// fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +// self.read_bytes(buf).map_err(|x|{ std::io::Error::new()}) +// } +// } +impl> From for ZCursor { + fn from(value: T) -> Self { + ZCursor::new(value) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/std_readers.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/std_readers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/std_readers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader/std_readers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +#![cfg(feature = "std")] + +use std::io; +use std::io::SeekFrom; + +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; +use crate::bytestream::ZByteReaderTrait; +// note (cae): If Rust ever stabilizes trait specialization, specialize this for Cursor +impl ZByteReaderTrait for T { + #[inline(always)] + fn read_byte_no_error(&mut self) -> u8 { + let mut buf = [0]; + let _ = self.read(&mut buf); + buf[0] + } + #[inline(always)] + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + let mut bytes_read = 0; + + while bytes_read < buf.len() { + match self.read(&mut buf[bytes_read..]) { + Ok(0) => { + // if a read returns zero bytes read, it means it encountered an EOF so we seek + // back to where we started because some paths may aggressively read forward and + // ZCursor maintains the position. + + // NB: (cae) [tag=perf] This adds a branch on every read, and will slow down every function + // resting on it. Sorry + self.seek(SeekFrom::Current(-(bytes_read as i64))) + .map_err(ZByteIoError::from)?; + return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len())); + } + Ok(bytes) => { + bytes_read += bytes; + } + Err(e) => return Err(ZByteIoError::from(e)) + } + } + + Ok(()) + } + + #[inline] + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> { + self.read_exact_bytes(buf) + } + + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]) { + let _ = self.read_const_bytes(buf); + } + + #[inline(always)] + fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + self.read(buf).map_err(ZByteIoError::from) + } + + #[inline(always)] + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result { + // first read bytes to the buffer + let bytes_read = self.read_bytes(buf)?; + let converted = -i64::try_from(bytes_read).map_err(ZByteIoError::from)?; + self.seek(std::io::SeekFrom::Current(converted)) + .map_err(ZByteIoError::from)?; + + Ok(bytes_read) + } + + #[inline(always)] + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + // first read bytes to the buffer + self.read_exact_bytes(buf)?; + let converted = -i64::try_from(buf.len()).map_err(ZByteIoError::from)?; + self.seek(std::io::SeekFrom::Current(converted)) + .map_err(ZByteIoError::from)?; + + Ok(()) + } + + #[inline(always)] + fn z_seek(&mut self, from: ZSeekFrom) -> Result { + self.seek(from.to_std_seek()).map_err(ZByteIoError::from) + } + + #[inline(always)] + fn is_eof(&mut self) -> Result { + self.fill_buf() + .map(|b| b.is_empty()) + .map_err(ZByteIoError::from) + } + + #[inline(always)] + fn z_position(&mut self) -> Result { + self.stream_position().map_err(ZByteIoError::from) + } + + #[inline(always)] + fn read_remaining(&mut self, sink: &mut Vec) -> Result { + self.read_to_end(sink).map_err(ZByteIoError::from) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/reader.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,462 @@ +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; +use core::fmt::Formatter; + +pub(crate) mod no_std_readers; +pub(crate) mod std_readers; +use crate::bytestream::ZByteReaderTrait; + +/// Enumeration of possible methods to seek within an I/O object. +/// +/// It is analogous to the [SeekFrom](std::io::SeekFrom) in the std library but +/// it's here to allow this to work in no-std crates +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +pub enum ZSeekFrom { + /// Sets the offset to the provided number of bytes. + Start(u64), + + /// Sets the offset to the size of this object plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + End(i64), + + /// Sets the offset to the current position plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + Current(i64) +} + +impl ZSeekFrom { + /// Convert to [SeekFrom](std::io::SeekFrom) from the `std::io` library + /// + /// This is only present when std feature is present + #[cfg(feature = "std")] + pub(crate) fn to_std_seek(self) -> std::io::SeekFrom { + match self { + ZSeekFrom::Start(pos) => std::io::SeekFrom::Start(pos), + ZSeekFrom::End(pos) => std::io::SeekFrom::End(pos), + ZSeekFrom::Current(pos) => std::io::SeekFrom::Current(pos) + } + } +} + +pub enum ZByteIoError { + /// A standard library error + /// Only available with the `std` feature + #[cfg(feature = "std")] + StdIoError(std::io::Error), + /// An error converting from one type to another + TryFromIntError(core::num::TryFromIntError), + /// Not enough bytes to satisfy a read + // requested, read + NotEnoughBytes(usize, usize), + /// The output buffer is too small to write the bytes + NotEnoughBuffer(usize, usize), + /// An error that may occur randomly + Generic(&'static str), + /// An error that occurred during a seek operation + SeekError(&'static str), + /// An error that occurred during a seek operation + SeekErrorOwned(String) +} + +impl core::fmt::Debug for ZByteIoError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + #[cfg(feature = "std")] + ZByteIoError::StdIoError(err) => { + writeln!(f, "Underlying I/O error {}", err) + } + ZByteIoError::TryFromIntError(err) => { + writeln!(f, "Cannot convert to int {}", err) + } + ZByteIoError::NotEnoughBytes(found, expected) => { + writeln!(f, "Not enough bytes, expected {expected} but found {found}") + } + ZByteIoError::NotEnoughBuffer(expected, found) => { + writeln!( + f, + "Not enough buffer to write {expected} bytes, buffer size is {found}" + ) + } + ZByteIoError::Generic(err) => { + writeln!(f, "Generic I/O error: {err}") + } + ZByteIoError::SeekError(err) => { + writeln!(f, "Seek error: {err}") + } + ZByteIoError::SeekErrorOwned(err) => { + writeln!(f, "Seek error {err}") + } + } + } +} + +#[cfg(feature = "std")] +impl From for ZByteIoError { + fn from(value: std::io::Error) -> Self { + ZByteIoError::StdIoError(value) + } +} + +impl From for ZByteIoError { + fn from(value: core::num::TryFromIntError) -> Self { + ZByteIoError::TryFromIntError(value) + } +} + +impl From<&'static str> for ZByteIoError { + fn from(value: &'static str) -> Self { + ZByteIoError::Generic(value) + } +} + +/// The image reader wrapper +/// +/// This wraps anything that implements [ZByteReaderTrait] and +/// extends the ability of the core trait methods by providing +/// utilities like endian aware byte functions. +/// +/// This prevents each implementation from providing its own +pub struct ZReader { + inner: T, + temp_buffer: Vec +} + +impl ZReader { + /// Create a new reader from a source + /// that implements the [ZByteReaderTrait] + pub fn new(source: T) -> ZReader { + ZReader { + inner: source, + temp_buffer: vec![] + } + } + /// Destroy this reader returning + /// the underlying source of the bytes + /// from which we were decoding + #[inline(always)] + pub fn consume(self) -> T { + self.inner + } + /// Skip ahead ignoring `num` bytes + /// + /// For more advanced seek methods see [Self::seek] that allows + /// moving around via more advanced ways + /// + /// # Arguments + /// - num: The number of bytes to skip. + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - `Error` If something went wrong + #[inline(always)] + pub fn skip(&mut self, num: usize) -> Result { + self.inner.z_seek(ZSeekFrom::Current(num as i64)) + } + /// Move back from current position to a previous + /// position + /// + /// For more advanced seek methods see [Self::seek] that allows + /// moving around via more advanced ways + /// + /// # Arguments + /// - `num`: Positions to move before the current cursor + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - `Error` If something went wrong + #[inline(always)] + pub fn rewind(&mut self, num: usize) -> Result { + self.inner.z_seek(ZSeekFrom::Current(-(num as i64))) + } + /// Move around a stream of bytes + /// + /// This is analogous to the [std::io::Seek] trait with the same ergonomics + /// only implemented to allow use in a `no_std` environment + /// + /// # Arguments + /// - `from`: The seek operation type. + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - Error if something went wrong. + #[inline(always)] + pub fn seek(&mut self, from: ZSeekFrom) -> Result { + self.inner.z_seek(from) + } + + /// Read a single byte from the underlying stream + /// + /// If an error occurs, it will return `0` as default output + /// hence it may be difficult to distinguish a `0` from the underlying source + /// and a `0` from an error. + /// For that there is [Self::read_u8_err] + /// + /// # Returns. + /// - The next byte on the stream. + /// + #[inline(always)] + pub fn read_u8(&mut self) -> u8 { + self.inner.read_byte_no_error() + } + + /// Read a single byte returning an error if the read cannot be satisfied + /// + /// # Returns + /// - `Ok(u8)`: The next byte + /// - Error if the byte read could not be satisfied + #[inline(always)] + pub fn read_u8_err(&mut self) -> Result { + let mut buf = [0]; + self.inner.read_const_bytes(&mut buf)?; + Ok(buf[0]) + } + + /// Look ahead position bytes and return a reference + /// to num_bytes from that position, or an error if the + /// peek would be out of bounds. + /// + /// This doesn't increment the position, bytes would have to be discarded + /// at a later point. + #[inline] + pub fn peek_at(&mut self, position: usize, num_bytes: usize) -> Result<&[u8], ZByteIoError> { + // short circuit for zero + // important since implementations like File will + // cause a syscall on skip + if position != 0 { + // skip position bytes from start + self.skip(position)?; + } + if num_bytes > 20 * 1024 * 1024 { + // resize of 20 MBs, skipping too much, so panic + return Err(ZByteIoError::Generic("Too many bytes skipped")); + } + // resize buffer + self.temp_buffer.resize(num_bytes, 0); + // read bytes + match self.inner.peek_exact_bytes(&mut self.temp_buffer[..]) { + Ok(_) => { + // rewind back to where we were + if position != 0 { + self.rewind(position)?; + } + Ok(&self.temp_buffer) + } + Err(e) => Err(e) + } + } + /// Read a fixed number of known bytes to a buffer and return the bytes or an error + /// if it occurred. + /// + /// The size of the `N` value must be small enough to fit the stack space otherwise + /// this will cause a stack overflow :) + /// + /// If you can ignore errors, you can use [Self::read_fixed_bytes_or_zero] + /// + /// # Returns + /// - `Ok([u8;N])`: The bytes read from the source + /// - An error if it occurred. + #[inline(always)] + pub fn read_fixed_bytes_or_error(&mut self) -> Result<[u8; N], ZByteIoError> { + let mut byte_store: [u8; N] = [0; N]; + match self.inner.read_const_bytes(&mut byte_store) { + Ok(_) => Ok(byte_store), + Err(e) => Err(e) + } + } + /// Read a fixed bytes to an array and if that is impossible, return an array containing + /// zeros + /// + /// If you want to handle errors, use [Self::read_fixed_bytes_or_error] + #[inline(always)] + pub fn read_fixed_bytes_or_zero(&mut self) -> [u8; N] { + let mut byte_store: [u8; N] = [0; N]; + self.inner.read_const_bytes_no_error(&mut byte_store); + byte_store + } + + /// Move the cursor to a fixed position in the stream + /// + /// This will move the cursor to exacltly `position` bytes from the start of the buffer + /// + /// # Arguments + /// - `position`: The current position to move the cursor. + #[inline] + pub fn set_position(&mut self, position: usize) -> Result<(), ZByteIoError> { + self.seek(ZSeekFrom::Start(position as u64))?; + + Ok(()) + } + + /// Return true if the underlying buffer can no longer produce bytes + /// + /// This call may be expensive depending on the underlying buffer type, e.g if + /// it's a file, we have to ask the os whether we have more contents, or in other words make a syscall. + /// + /// Use that wisely + /// + /// # Returns + /// - `Ok(bool)`: True if we are in `EOF`, false if we can produce more bytes + /// - Error if something went wrong + #[inline(always)] + pub fn eof(&mut self) -> Result { + self.inner.is_eof() + } + + /// Return the current position of the inner reader or an error + /// if that occurred when reading. + /// + /// Like [eof](Self::eof), the perf characteristics may vary depending on underlying reader + /// + /// # Returns + /// - `Ok(u64)`: The current position of the inner reader + #[inline(always)] + pub fn position(&mut self) -> Result { + self.inner.z_position() + } + + /// Read a fixed number of bytes from the underlying reader returning + /// an error if that can't be satisfied + /// + /// Similar to [std::io::Read::read_exact] + /// + /// # Returns + /// - `Ok(())`: If the read was successful + /// - An error if the read was unsuccessful including failure to fill the whole bytes + pub fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + self.inner.read_exact_bytes(buf) + } + + /// Read some bytes from the inner reader, and return number of bytes read + /// + /// The implementation may not read bytes enough to fill the buffer + /// + /// Similar to [std::io::Read::read] + /// + /// # Returns + /// - `Ok(usize)`: Number of bytes actually read to the buffer + /// - An error if something went wrong + pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + self.inner.read_bytes(buf) + } +} + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} +macro_rules! get_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl ZReader + { + #[inline(always)] + fn $name(&mut self, mode: Mode) -> $int_type + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + self.inner.read_const_bytes_no_error(&mut space); + + match mode { + Mode::BE => $int_type::from_be_bytes(space), + Mode::LE => $int_type::from_le_bytes(space) + } + } + + #[inline(always)] + fn $name2(&mut self, mode: Mode) -> Result<$int_type, ZByteIoError> + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + match self.inner.read_const_bytes(&mut space) + { + Ok(_) => match mode { + Mode::BE => Ok($int_type::from_be_bytes(space)), + Mode::LE => Ok($int_type::from_le_bytes(space)) + }, + Err(e) => Err(e) + } + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name3(&mut self) -> Result<$int_type, ZByteIoError> + { + self.$name2(Mode::BE) + } + + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name4(&mut self) -> Result<$int_type, ZByteIoError> + { + self.$name2(Mode::LE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name5(&mut self) -> $int_type + { + self.$name(Mode::BE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name6(&mut self) -> $int_type + { + self.$name(Mode::LE) + } + } + }; +} + +get_single_type!( + get_u16_inner_or_default, + get_u16_inner_or_die, + get_u16_be_err, + get_u16_le_err, + get_u16_be, + get_u16_le, + u16 +); +get_single_type!( + get_u32_inner_or_default, + get_u32_inner_or_die, + get_u32_be_err, + get_u32_le_err, + get_u32_be, + get_u32_le, + u32 +); +get_single_type!( + get_u64_inner_or_default, + get_u64_inner_or_die, + get_u64_be_err, + get_u64_le_err, + get_u64_be, + get_u64_le, + u64 +); + +#[cfg(feature = "std")] +impl std::io::Read for ZReader +where + T: ZByteReaderTrait +{ + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + use std::io::ErrorKind; + self.read_bytes(buf) + .map_err(|e| std::io::Error::new(ErrorKind::Other, format!("{:?}", e))) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ +//! Traits for reading and writing images in zune +//! +//! +//! This exposes the traits and implementations for readers +//! and writers in the zune family of decoders and encoders. + +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; + +/// The de-facto Input trait implemented for readers. +/// +/// This provides the basic functions needed to quick and sometimes +/// heap free I/O for the zune image decoders with easy support for extending it +/// to multiple implementations. +/// +/// # Considerations +/// +/// If you have an in memory buffer, prefer [`ZCursor`](crate::bytestream::ZCursor) over [`Cursor`](std::io::Cursor). +/// We implement this trait for two types, `ZCursor`, and any thing that implements `BufRead`+`Seek`, `Cursor` falls in the latter +/// and since Rust doesn't have specialization for traits, we can only implement it once. This means functions like +/// [`read_byte_no_error`](crate::bytestream::ZByteReaderTrait::read_byte_no_error) are slower than they should be for `Cursor`. +/// +pub trait ZByteReaderTrait { + /// Read a single byte from the decoder and return + /// `0` if we can't read the byte, e.g because of EOF + /// + /// The implementation should try to be as fast as possible as this is called + /// from some hot loops where it may become the bottleneck + fn read_byte_no_error(&mut self) -> u8; + /// Read exact bytes required to fill `buf` or return an error if that isn't possible + /// + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>; + + /// Read exact bytes required to fill `buf` or return an error if that isn't possible + /// + /// This is the same as [`read_exact_bytes`](Self::read_exact_bytes) but implemented as a separate + /// method to allow some implementations to optimize it to cost fewer instructions + /// + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError>; + + /// Read exact bytes required to fill `buf` or ignore buf entirely if you can't fill it + /// due to an error like the inability to fill the buffer completely + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]); + + /// Read bytes into `buf` returning how many bytes you have read or an error if one occurred + /// + /// This doesn't guarantee that buf will be filled with bytes for such a guarantee see + /// [`read_exact_bytes`](Self::read_exact_bytes) + /// + /// ## Arguments + /// - `buf`: The buffer to fill with bytes + /// + /// ## Returns + /// - `Ok(usize)` - Actual bytes read into the buffer + /// - `Err()` - The error encountered when reading bytes for which we couldn't recover + fn read_bytes(&mut self, buf: &mut [u8]) -> Result; + /// Reads data into provided buffer but does not advance read position. + /// + /// + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result; + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>; + /// Seek into a new position from the buffer + /// + /// This is similar to the [seek](std::io::Seek::seek) function in the [Seek](std::io::Seek) trait + /// but implemented to work for no-std environments + fn z_seek(&mut self, from: ZSeekFrom) -> Result; + /// Report whether we are at the end of a stream. + /// + /// ## Warning + /// This may cause an additional syscall e.g when we are reading from a file, we must query the file + /// multiple times to check if we really are at the end of the file and the user didn't sneakily + /// add more contents to it hence use it with care + /// + /// ## Returns + /// - `Ok(bool)` - The answer to whether or not we are at end of file + /// - `Err()` - The error that occurred when we queried the underlying reader if we were at EOF + fn is_eof(&mut self) -> Result; + + /// Return the current position of the inner cursor. + /// + /// This can be used to check the advancement of the cursor + fn z_position(&mut self) -> Result; + /// Read all bytes remaining in this input to `sink` until we hit eof + /// + /// # Returns + /// - `Ok(usize)` The actual number of bytes added to the sink + /// - `Err()` An error that occurred when reading bytes + fn read_remaining(&mut self, sink: &mut alloc::vec::Vec) -> Result; +} + +/// The writer trait implemented for zune-image library of encoders +/// +/// Anything that implements this trait can be used as a sink +/// for writing encoded images +pub trait ZByteWriterTrait { + /// Write some bytes into the sink returning number of bytes written or + /// an error if something bad happened + /// + /// An implementation is free to write less bytes that are in buf, so the bytes written + /// cannot be guaranteed to be fully written + fn write_bytes(&mut self, buf: &[u8]) -> Result; + /// Write all bytes to the buffer or return an error if something occurred + /// + /// This will always write all bytes, if it can't fully write all bytes, it will + /// error out + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError>; + /// Write a fixed number of bytes and error out if we can't write the bytes + /// + /// This is provided to allow for optimized writes where possible. (when the compiler can const fold them) + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError>; + /// Ensure bytes are written to the sink. + /// + /// Implementations should treat this like linux `fsync`, and should implement + /// whatever writer's implementation of fsync should look like + /// + /// After this, the encoder should be able to guarantee that all in-core data is synced with the + /// storage decive + fn flush_bytes(&mut self) -> Result<(), ZByteIoError>; + + /// A hint to tell the implementation how big of a size we expect the image to be + /// An implementation like in memory `Vec` can use this to reserve additional memory to + /// prevent reallocation when encoding + /// + /// This is just a hint, akin to calling `Vec::reserve` and should be treated as such. + /// If your implementation doesn't support such, e.g file or mutable slices, it's okay to return + /// `Ok(())` + fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError>; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/no_std_writer.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/no_std_writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/no_std_writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/no_std_writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +// We cannot use the below impls and std ones because we'll re-implement the +// same trait fot &[u8] which is blanketed by write. Ending up with two separate implementations +#![cfg(not(feature = "std"))] +use crate::bytestream::{ZByteIoError, ZByteWriterTrait}; + +impl ZByteWriterTrait for &mut [u8] { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + // got from the write of std + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + Ok(amt) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + if buf.len() > self.len() { + return Err(ZByteIoError::NotEnoughBuffer(self.len(), buf.len())); + } + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + + Ok(()) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + if N > self.len() { + return Err(ZByteIoError::NotEnoughBuffer(self.len(), N)); + } + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + Ok(()) + } + + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + Ok(()) + } + fn reserve_capacity(&mut self, _: usize) -> Result<(), ZByteIoError> { + // can't really pre-allocate anything here + Ok(()) + } +} + +impl ZByteWriterTrait for &mut alloc::vec::Vec { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.extend_from_slice(buf); + Ok(()) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + self.extend_from_slice(buf); + Ok(()) + } + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + Ok(()) + } + fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError> { + self.reserve(size); + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/std_writer.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/std_writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/std_writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer/std_writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +#![cfg(feature = "std")] + +use std::io::Write; + +use crate::bytestream::ZByteIoError; + +impl crate::bytestream::ZByteWriterTrait for T { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + self.write(buf).map_err(ZByteIoError::StdIoError) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.write_all(buf).map_err(ZByteIoError::StdIoError) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + self.write_all_bytes(buf) + } + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + self.flush().map_err(ZByteIoError::StdIoError) + } + fn reserve_capacity(&mut self, _: usize) -> Result<(), ZByteIoError> { + // we can't reserve capacity, sorry to implementations where this + // matters + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream/writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ +use crate::bytestream::{ZByteIoError, ZByteWriterTrait}; + +mod no_std_writer; +mod std_writer; + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} + +/// Encapsulates a simple Byte writer with +/// support for Endian aware writes +pub struct ZWriter { + buffer: T, + bytes_written: usize +} + +impl ZWriter { + /// Write bytes from the buf into the bytestream + /// and return how many bytes were written + /// + /// # Arguments + /// - `buf`: The bytes to be written to the bytestream + /// + /// # Returns + /// - `Ok(usize)` - Number of bytes written + /// This number may be less than `buf.len()` if the length of the buffer is greater + /// than the internal bytestream length + /// + /// If you want to be sure that all bytes were written, see [`write_all`](Self::write_all) + /// + #[inline] + pub fn write(&mut self, buf: &[u8]) -> Result { + let bytes_written = self.buffer.write_bytes(buf)?; + self.bytes_written += bytes_written; + Ok(bytes_written) + } + /// Write all bytes from `buf` into the bytestream and return + /// and panic if not all bytes were written to the bytestream + /// + /// # Arguments + /// - `buf`: The bytes to be written into the bytestream + /// + ///# Returns + /// - `Ok(())`: Indicates all bytes were written into the bytestream + /// - `Err(&static str)`: In case all the bytes could not be written + /// to the stream + pub fn write_all(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.buffer.write_all_bytes(buf)?; + self.bytes_written += buf.len(); + Ok(()) + } + /// Create a new bytestream writer + /// Bytes are written from the start to the end and not assumptions + /// are made of the nature of the underlying stream + /// + /// # Arguments + pub fn new(data: T) -> ZWriter { + ZWriter { + buffer: data, + bytes_written: 0 + } + } + + /// Write a single byte into the bytestream or error out + /// if there is not enough space + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let mut buf = [0;10]; + /// let mut stream = ZWriter::new(&mut buf[..]); + /// assert!(stream.write_u8_err(34).is_ok()); + /// ``` + /// No space + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let mut no_space = []; + /// let mut stream = ZWriter::new(&mut no_space[..]); + /// assert!(stream.write_u8_err(32).is_err()); + /// ``` + /// + #[inline] + pub fn write_u8_err(&mut self, byte: u8) -> Result<(), ZByteIoError> { + self.write_const_bytes(&[byte]) + } + /// Write a fixed compile time known number of bytes to the sink + /// + /// This is provided since some implementations can optimize such writes by eliminating + /// some redundant code. + #[inline] + pub fn write_const_bytes( + &mut self, byte: &[u8; N] + ) -> Result<(), ZByteIoError> { + self.buffer.write_const_bytes(byte)?; + self.bytes_written += N; + Ok(()) + } + + /// Write a single byte in the stream or don't write + /// anything if the buffer is full and cannot support the byte read + /// + #[inline] + pub fn write_u8(&mut self, byte: u8) { + let _ = self.write_const_bytes(&[byte]); + } + /// Return the number of bytes written by this encoder + /// + /// The encoder keeps information of how many bytes were written and this method + /// returns that value. + /// + /// # Returns + /// Number of bytes written + pub fn bytes_written(&self) -> usize { + self.bytes_written + } + + /// Reserve some additional space to write. + /// + /// Some sinks like `Vec` allow reallocation and to prevent too much reallocation + /// one can use this to reserve additional space to encode + /// + /// # Example + /// + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let space_needed = 10; // Assume the image will fit into 10 bytes + /// let mut output = Vec::new(); + /// let mut sink = ZWriter::new(&mut output); + /// // now reserve some space + ///sink.reserve(space_needed).unwrap(); + /// // at this point, we can assume that ZWriter allocated space for output + /// ``` + pub fn reserve(&mut self, additional: usize) -> Result<(), ZByteIoError> { + self.buffer.reserve_capacity(additional) + } + /// Consume the writer and return the inner sink + /// we were writing to. + /// + /// After this, the writer can no longer be used + pub fn inner(self) -> T { + self.buffer + } + /// Return an immutable reference to the inner sink + pub fn inner_ref(&self) -> &T { + &self.buffer + } + /// Return a mutable reference to the inner sink + pub fn inner_mut(&mut self) -> &mut T { + &mut self.buffer + } +} + +macro_rules! write_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl ZWriter + { + #[inline(always)] + fn $name(&mut self, byte: $int_type, mode: Mode) -> Result<(), ZByteIoError> + { + + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + self.write_const_bytes(&bytes) + } + #[inline(always)] + fn $name2(&mut self, byte: $int_type, mode: Mode) + { + + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + let _ = self.write_const_bytes(&bytes); + + + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name3(&mut self, byte: $int_type) -> Result<(), ZByteIoError> + { + self.$name(byte, Mode::BE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name4(&mut self, byte: $int_type) -> Result<(), ZByteIoError> + { + self.$name(byte, Mode::LE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name5(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::BE) + } + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name6(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::LE) + } + } + }; +} + +write_single_type!( + write_u64_inner_or_die, + write_u64_inner_or_none, + write_u64_be_err, + write_u64_le_err, + write_u64_be, + write_u64_le, + u64 +); + +write_single_type!( + write_u32_inner_or_die, + write_u32_inner_or_none, + write_u32_be_err, + write_u32_le_err, + write_u32_be, + write_u32_le, + u32 +); + +write_single_type!( + write_u16_inner_or_die, + write_u16_inner_or_none, + write_u16_be_err, + write_u16_le_err, + write_u16_be, + write_u16_le, + u16 +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/bytestream.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/bytestream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! A simple implementation of a bytestream reader +//! and writer. +//! +//! This module contains two main structs that help in +//! byte reading and byte writing +//! +//! Useful for a lot of image readers and writers, it's put +//! here to minimize code reuse +pub use reader::ZReader; +pub use traits::*; +pub use writer::ZWriter; + +pub use crate::bytestream::reader::no_std_readers::*; +//use crate::bytestream::reader::std_readers::*; +pub use crate::bytestream::reader::ZByteIoError; + +mod reader; +mod traits; +mod writer; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/colorspace.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/colorspace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/colorspace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/colorspace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image Colorspace information and manipulation utilities. + +/// All possible image colorspaces +/// Some of them aren't yet supported exist here. +#[allow(clippy::upper_case_acronyms)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum ColorSpace { + /// Red, Green , Blue + RGB, + /// Red, Green, Blue, Alpha + RGBA, + /// YUV colorspace + YCbCr, + /// Grayscale colorspace + Luma, + /// Grayscale with alpha colorspace + LumaA, + YCCK, + /// Cyan , Magenta, Yellow, Black + CMYK, + /// Blue, Green, Red + BGR, + /// Blue, Green, Red, Alpha + BGRA, + /// The colorspace is unknown + Unknown, + /// Alpha Red Green Blue + ARGB, + /// Hue,Saturation,Lightness + /// Conversion from RGB to HSL and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSL, + /// Hue, Saturation,Value + /// + /// Conversion from RGB to HSV and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSV, + /// Multiple arbitrary image channels. + /// + /// This introduces **limited** support for multi-band/multichannel images + /// that can have n channels. + /// + /// The library contains optimized and well-supported routines for up to 4 image channels as is + /// more common out there, but some pipelines may require multi-band image support. + /// + /// For operations, multi-band images are assumed to be n-channel images with no alpha + /// to allow for generic processing, without necessarily caring for the underlying interpretation + MultiBand(core::num::NonZeroU32) +} + +impl ColorSpace { + /// Number of color channels present for a certain colorspace + /// + /// E.g. RGB returns 3 since it contains R,G and B colors to make up a pixel + pub const fn num_components(&self) -> usize { + match self { + Self::RGB | Self::YCbCr | Self::BGR | Self::HSV | Self::HSL => 3, + Self::RGBA | Self::YCCK | Self::CMYK | Self::BGRA | Self::ARGB => 4, + Self::Luma => 1, + Self::LumaA => 2, + Self::Unknown => 0, + Self::MultiBand(n) => n.get() as usize + } + } + + pub const fn has_alpha(&self) -> bool { + matches!(self, Self::RGBA | Self::LumaA | Self::BGRA | Self::ARGB) + } + + pub const fn is_grayscale(&self) -> bool { + matches!(self, Self::LumaA | Self::Luma) + } + + /// Returns the position of the alpha pixel in a pixel + /// + /// + /// That is for an array of color components say `[0,1,2,3]` if the image has an alpha channel + /// and is in RGBA format, this will return `Some(3)`, indicating alpha is found in the third index + /// but if the image is in `ARGB` format, it will return `Some(0)` indicating alpha is found in + /// index 0 + /// + /// If an image doesn't have an alpha channel returns `None` + /// + pub const fn alpha_position(&self) -> Option { + match self { + ColorSpace::RGBA => Some(3), + ColorSpace::LumaA => Some(1), + ColorSpace::BGRA => Some(3), + ColorSpace::ARGB => Some(0), + _ => None + } + } +} + +/// Encapsulates all colorspaces supported by +/// the library +/// +/// This explicitly leaves out multi-band images +pub static ALL_COLORSPACES: [ColorSpace; 12] = [ + ColorSpace::RGB, + ColorSpace::RGBA, + ColorSpace::LumaA, + ColorSpace::Luma, + ColorSpace::CMYK, + ColorSpace::BGRA, + ColorSpace::BGR, + ColorSpace::YCCK, + ColorSpace::YCbCr, + ColorSpace::ARGB, + ColorSpace::HSL, + ColorSpace::HSV +]; + +/// Color characteristics +/// +/// Gives more information about values in a certain +/// colorspace +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ColorCharacteristics { + /// Normal default gamma setting + /// The float contains gamma present + /// + /// The default gamma value is 2.2 but for + /// decoders that allow specifying gamma values,e.g PNG, + /// the gamma value becomes the specified value by the decoder + sRGB, + /// Linear transfer characteristics + /// The image is in linear colorspace + Linear +} +/// Represents a single channel color primary. +/// +/// This can be viewed as a 3D coordinate of the color primary +/// for a given colorspace +#[derive(Default, Debug, Copy, Clone)] +pub struct SingleColorPrimary { + pub x: f64, + pub y: f64, + pub z: f64 +} +/// A collection of red,green and blue color primaries placed +/// in one struct for easy manipulation +#[derive(Default, Debug, Copy, Clone)] +pub struct ColorPrimaries { + /// Red color primaries + pub red: SingleColorPrimary, + /// Green color primaries + pub green: SingleColorPrimary, + /// Blue color primaries + pub blue: SingleColorPrimary +} + +/// Rendering intents indicate what one may want to do with colors outside of it's gamut +/// +/// +/// Further reading +/// - [IBM Rendering Intent](https://www.ibm.com/docs/en/i/7.5?topic=management-rendering-intents) +/// - [ColorGate Blog](https://blog.colorgate.com/en/rendering-intent-explained) +#[derive(Eq, PartialEq, Clone, Copy, Debug)] +pub enum RenderingIntent { + AbsoluteColorimetric, + Saturation, + RelativeColorimetric, + Perceptual +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Core routines shared by all libraries +//! +//! This crate provides a set of core routines shared +//! by the decoders and encoders under `zune` umbrella +//! +//! It currently contains +//! +//! - A bytestream reader and writer with endian aware reads and writes +//! - Colorspace and bit depth information shared by images +//! - Image decoder and encoder options +//! - A simple enum type to hold image decoding results. +//! +//! This library is `#[no_std]` with `alloc` feature needed for defining `Vec` +//! which we need for storing decoded bytes. +//! +//! +//! # Features +//! - `no_std`: Enables `#[no_std]` compilation support. +//! +//! - `serde`: Enables serializing of some of the data structures +//! present in the crate +//! +//! +//! # Input/Output +//! +//! zune-image supports many different input and output devices. For input readers +//! we can read anything that implements `BufRead` + `Seek` and provide an optimized routine for +//! handling in memory buffers by using [`ZCursor`](crate::bytestream::ZCursor). +//! +//! For output, we support anything that implements `Write` trait, this includes files, standard io streams +//! network sockets, etc +//! +//! In a `no_std` environment. We can write to in memory buffers `&mut [u8]` and `&mut Vec` +//! +//! If you have an in memory buffer, use [`ZCursor`](crate::bytestream::ZCursor), +//! it's optimized for in memory buffers. +//! +//! +//! +#![cfg_attr(not(feature = "std"), no_std)] +#![macro_use] +extern crate alloc; +extern crate core; + +#[cfg(not(feature = "log"))] +pub mod log; + +#[cfg(feature = "log")] +pub use log; + +pub mod bit_depth; +pub mod bytestream; +pub mod colorspace; +pub mod options; +pub mod result; +mod serde; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/log.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/log.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/log.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/log.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +// #[macro_export] is required to make macros works across crates +// but it always put the macro in the crate root. +// #[doc(hidden)] + "pub use" is a workaround to namespace a macro. +pub use crate::{ + __debug as debug, __error as error, __info as info, __log_enabled as log_enabled, + __trace as trace, __warn as warn +}; + +#[repr(usize)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub enum Level { + Error = 1, + Warn, + Info, + Debug, + Trace +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_enabled { + ($lvl:expr) => {{ + let _ = $lvl; + false + }}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __error { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __warn { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __info { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __debug { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __trace { + ($($arg:tt)+) => {}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Global Decoder options +#![allow(clippy::zero_prefixed_literal)] + +use crate::bit_depth::ByteEndian; +use crate::colorspace::ColorSpace; + +/// A decoder that can handle errors +fn decoder_error_tolerance_mode() -> DecoderFlags { + // similar to fast options currently, so no need to write a new one + fast_options() +} +/// Fast decoder options +/// +/// Enables all intrinsics + unsafe routines +/// +/// Disables png adler and crc checking. +fn fast_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Command line options error resilient and fast +/// +/// Features +/// - Ignore CRC and Adler in png +/// - Do not error out on non-conformance in jpg +/// - Use unsafe paths +fn cmd_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Decoder options that are flags +/// +/// NOTE: When you extend this, add true or false to +/// all options above that return a `DecoderFlag` +#[derive(Copy, Debug, Clone, Default)] +pub struct DecoderFlags { + /// Whether the decoder should confirm and report adler mismatch + inflate_confirm_adler: bool, + /// Whether the PNG decoder should confirm crc + png_confirm_crc: bool, + /// Whether the png decoder should error out on image non-conformance + jpg_error_on_non_conformance: bool, + /// Whether the decoder should use unsafe platform specific intrinsics + /// + /// This will also shut down platform specific intrinsics `(ZUNE_USE_{EXT})` value + zune_use_unsafe: bool, + /// Whether we should use SSE2. + /// + /// This should be enabled for all x64 platforms but can be turned off if + /// `ZUNE_USE_UNSAFE` is false + zune_use_sse2: bool, + /// Whether we should use SSE3 instructions where possible. + zune_use_sse3: bool, + /// Whether we should use sse4.1 instructions where possible. + zune_use_sse41: bool, + /// Whether we should use avx instructions where possible. + zune_use_avx: bool, + /// Whether we should use avx2 instructions where possible. + zune_use_avx2: bool, + /// Whether the png decoder should add alpha channel where possible. + png_add_alpha_channel: bool, + /// Whether we should use neon instructions where possible. + zune_use_neon: bool, + /// Whether the png decoder should strip 16 bit to 8 bit + png_strip_16_bit_to_8_bit: bool, + /// Decode all frames for an animated images + png_decode_animated: bool, + jxl_decode_animated: bool +} + +/// Decoder options +/// +/// Not all options are respected by decoders all decoders +#[derive(Debug, Copy, Clone)] +pub struct DecoderOptions { + /// Maximum width for which decoders will + /// not try to decode images larger than + /// the specified width. + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_width: usize, + /// Maximum height for which decoders will not + /// try to decode images larger than the + /// specified height + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_height: usize, + /// Output colorspace + /// + /// The jpeg decoder allows conversion to a separate colorspace + /// than the input. + /// + /// I.e you can convert a RGB jpeg image to grayscale without + /// first decoding it to RGB to get + /// + /// - Default value: `ColorSpace::RGB` + /// - Respected by: `jpeg` + out_colorspace: ColorSpace, + + /// Maximum number of scans allowed + /// for progressive jpeg images + /// + /// Progressive jpegs have scans + /// + /// - Default value:100 + /// - Respected by: `jpeg` + max_scans: usize, + /// Maximum size for deflate. + /// Respected by all decoders that use inflate/deflate + deflate_limit: usize, + /// Boolean flags that influence decoding + flags: DecoderFlags, + /// The byte endian of the returned bytes will be stored in + /// in case a single pixel spans more than a byte + endianness: ByteEndian +} + +/// Initializers +impl DecoderOptions { + /// Create the decoder with options setting most configurable + /// options to be their safe counterparts + /// + /// This is the same as `default` option as default initializes + /// options to the safe variant. + /// + /// Note, decoders running on this will be slower as it disables + /// platform specific intrinsics + pub fn new_safe() -> DecoderOptions { + DecoderOptions::default() + } + + /// Create the decoder with options setting the configurable options + /// to the fast counterparts + /// + /// This enables platform specific code paths and enable use of unsafe + pub fn new_fast() -> DecoderOptions { + let flag = fast_options(); + DecoderOptions::default().set_decoder_flags(flag) + } + + /// Create the decoder options with the following characteristics + /// + /// - Use unsafe paths. + /// - Ignore error checksuming, e.g in png we do not confirm adler and crc in this mode + /// - Enable fast intrinsics paths + pub fn new_cmd() -> DecoderOptions { + let flag = cmd_options(); + DecoderOptions::default().set_decoder_flags(flag) + } +} + +/// Global options respected by all decoders +impl DecoderOptions { + /// Get maximum width configured for which the decoder + /// should not try to decode images greater than this width + pub const fn max_width(&self) -> usize { + self.max_width + } + + /// Get maximum height configured for which the decoder should + /// not try to decode images greater than this height + pub const fn max_height(&self) -> usize { + self.max_height + } + + /// Return true whether the decoder should be in strict mode + /// And reject most errors + pub fn strict_mode(&self) -> bool { + self.flags.jpg_error_on_non_conformance + | self.flags.png_confirm_crc + | self.flags.inflate_confirm_adler + } + /// Return true if the decoder should use unsafe + /// routines where possible + pub const fn use_unsafe(&self) -> bool { + self.flags.zune_use_unsafe + } + + /// Set maximum width for which the decoder should not try + /// decoding images greater than that width + /// + /// # Arguments + /// + /// * `width`: The maximum width allowed + /// + /// returns: DecoderOptions + pub fn set_max_width(mut self, width: usize) -> Self { + self.max_width = width; + self + } + + /// Set maximum height for which the decoder should not try + /// decoding images greater than that height + /// # Arguments + /// + /// * `height`: The maximum height allowed + /// + /// returns: DecoderOptions + /// + pub fn set_max_height(mut self, height: usize) -> Self { + self.max_height = height; + self + } + + /// Whether the routines can use unsafe platform specific + /// intrinsics when necessary + /// + /// Platform intrinsics are implemented for operations which + /// the compiler can't auto-vectorize, or we can do a marginably + /// better job at it + /// + /// All decoders with unsafe routines respect it. + /// + /// Treat this with caution, disabling it will cause slowdowns but + /// it's provided for mainly for debugging use. + /// + /// - Respected by: `png` and `jpeg`(decoders with unsafe routines) + pub fn set_use_unsafe(mut self, yes: bool) -> Self { + // first clear the flag + self.flags.zune_use_unsafe = yes; + self + } + + fn set_decoder_flags(mut self, flags: DecoderFlags) -> Self { + self.flags = flags; + self + } + /// Set whether the decoder should be in standards conforming/ + /// strict mode + /// + /// This reduces the error tolerance level for the decoders and invalid + /// samples will be rejected by the decoder + /// + /// # Arguments + /// + /// * `yes`: + /// + /// returns: DecoderOptions + /// + pub fn set_strict_mode(mut self, yes: bool) -> Self { + self.flags.jpg_error_on_non_conformance = yes; + self.flags.png_confirm_crc = yes; + self.flags.inflate_confirm_adler = yes; + self + } + + /// Set the byte endian for which raw samples will be stored in + /// in case a single pixel sample spans more than a byte. + /// + /// The default is usually native endian hence big endian values + /// will be converted to little endian on little endian systems, + /// + /// and little endian values will be converted to big endian on big endian systems + /// + /// # Arguments + /// + /// * `endian`: The endianness to which to set the bytes to + /// + /// returns: DecoderOptions + pub fn set_byte_endian(mut self, endian: ByteEndian) -> Self { + self.endianness = endian; + self + } + + /// Get the byte endian for which samples that span more than one byte will + /// be treated + pub const fn byte_endian(&self) -> ByteEndian { + self.endianness + } +} + +/// PNG specific options +impl DecoderOptions { + /// Whether the inflate decoder should confirm + /// adler checksums + pub const fn inflate_get_confirm_adler(&self) -> bool { + self.flags.inflate_confirm_adler + } + /// Set whether the inflate decoder should confirm + /// adler checksums + pub fn inflate_set_confirm_adler(mut self, yes: bool) -> Self { + self.flags.inflate_confirm_adler = yes; + self + } + /// Get default inflate limit for which the decoder + /// will not try to decompress further + pub const fn inflate_get_limit(&self) -> usize { + self.deflate_limit + } + /// Set the default inflate limit for which decompressors + /// relying on inflate won't surpass this limit + #[must_use] + pub fn inflate_set_limit(mut self, limit: usize) -> Self { + self.deflate_limit = limit; + self + } + /// Whether the inflate decoder should confirm + /// crc 32 checksums + pub const fn png_get_confirm_crc(&self) -> bool { + self.flags.png_confirm_crc + } + /// Set whether the png decoder should confirm + /// CRC 32 checksums + #[must_use] + pub fn png_set_confirm_crc(mut self, yes: bool) -> Self { + self.flags.png_confirm_crc = yes; + self + } + /// Set whether the png decoder should add an alpha channel to + /// images where possible. + /// + /// For Luma images, it converts it to Luma+Alpha + /// + /// For RGB images it converts it to RGB+Alpha + pub fn png_set_add_alpha_channel(mut self, yes: bool) -> Self { + self.flags.png_add_alpha_channel = yes; + self + } + /// Return true whether the png decoder should add an alpha + /// channel to images where possible + pub const fn png_get_add_alpha_channel(&self) -> bool { + self.flags.png_add_alpha_channel + } + + /// Whether the png decoder should reduce 16 bit images to 8 bit + /// images implicitly. + /// + /// Equivalent to [png::Transformations::STRIP_16](https://docs.rs/png/latest/png/struct.Transformations.html#associatedconstant.STRIP_16) + pub fn png_set_strip_to_8bit(mut self, yes: bool) -> Self { + self.flags.png_strip_16_bit_to_8_bit = yes; + self + } + + /// Return a boolean indicating whether the png decoder should reduce + /// 16 bit images to 8 bit images implicitly + pub const fn png_get_strip_to_8bit(&self) -> bool { + self.flags.png_strip_16_bit_to_8_bit + } + + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_decode_animated(&self) -> bool { + self.flags.png_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.png_decode_animated = yes; + self + } +} + +/// JPEG specific options +impl DecoderOptions { + /// Get maximum scans for which the jpeg decoder + /// should not go above for progressive images + pub const fn jpeg_get_max_scans(&self) -> usize { + self.max_scans + } + + /// Set maximum scans for which the jpeg decoder should + /// not exceed when reconstructing images. + pub fn jpeg_set_max_scans(mut self, max_scans: usize) -> Self { + self.max_scans = max_scans; + self + } + /// Get expected output colorspace set by the user for which the image + /// is expected to be reconstructed into. + /// + /// This may be different from the + pub const fn jpeg_get_out_colorspace(&self) -> ColorSpace { + self.out_colorspace + } + /// Set expected colorspace for which the jpeg output is expected to be in + /// + /// This is mainly provided as is, we do not guarantee the decoder can convert to all colorspaces + /// and the decoder can change it internally when it sees fit. + #[must_use] + pub fn jpeg_set_out_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.out_colorspace = colorspace; + self + } +} + +/// Intrinsics support +/// +/// These routines are compiled depending +/// on the platform they are used, if compiled for a platform +/// it doesn't support,(e.g avx2 on Arm), it will always return `false` +impl DecoderOptions { + /// Use SSE 2 code paths where possible + /// + /// This checks for existence of SSE2 first and returns + /// false if it's not present + #[allow(unreachable_code)] + pub fn use_sse2(&self) -> bool { + let opt = self.flags.zune_use_sse2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse2") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse2"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE 3 paths where possible + /// + /// + /// This also checks for SSE3 support and returns false if + /// it's not present + #[allow(unreachable_code)] + pub fn use_sse3(&self) -> bool { + let opt = self.flags.zune_use_sse3 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse3") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse3"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE4 paths where possible + /// + /// This also checks for sse 4.1 support and returns false if it + /// is not present + #[allow(unreachable_code)] + pub fn use_sse41(&self) -> bool { + let opt = self.flags.zune_use_sse41 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse4.1") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse4.1"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use AVX paths where possible + /// + /// This also checks for AVX support and returns false if it's + /// not present + #[allow(unreachable_code)] + pub fn use_avx(&self) -> bool { + let opt = self.flags.zune_use_avx | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use avx2 paths where possible + /// + /// This also checks for AVX2 support and returns false if it's not + /// present + #[allow(unreachable_code)] + pub fn use_avx2(&self) -> bool { + let opt = self.flags.zune_use_avx2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx2") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx2"))] + { + return true; + } + } + // everything failed return false + false + } + + #[allow(unreachable_code)] + pub fn use_neon(&self) -> bool { + let opt = self.flags.zune_use_neon | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(target_arch = "aarch64")] + { + // aarch64 implies neon on a compliant cpu + // but for real prod should do something better here + return true; + } + // everything failed return false + false + } +} + +/// JPEG_XL specific options +impl DecoderOptions { + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_decode_animated(&self) -> bool { + self.flags.jxl_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.jxl_decode_animated = yes; + self + } +} +impl Default for DecoderOptions { + /// Create a default and sane option for decoders + /// + /// The following are the defaults + /// + /// - All decoders + /// - max_width: 16536 + /// - max_height: 16535 + /// - use_unsafe: Use unsafe intrinsics where possible. + /// + /// - JPEG + /// - max_scans: 100 (progressive images only, artificial cap to prevent a specific DOS) + /// - error_on_non_conformance: False (slightly corrupt images will be allowed) + /// - DEFLATE + /// - deflate_limit: 1GB (will not continue decoding deflate archives larger than this) + /// - PNG + /// - endianness: Default endianess is Big Endian when decoding 16 bit images to be viewed as 8 byte images + /// - confirm_crc: False (CRC will not be confirmed to be safe) + /// - strip_16_bit_to_8: False, 16 bit images are handled as 16 bit images + /// - add alpha: False, alpha channel is not added where it isn't present + /// - decode_animated: True: All frames in an animated image are decoded + /// + /// - JXL + /// - decode_animated: True: All frames in an animated image are decoded + /// + fn default() -> Self { + Self { + out_colorspace: ColorSpace::RGB, + max_width: 1 << 14, + max_height: 1 << 14, + max_scans: 100, + deflate_limit: 1 << 30, + flags: decoder_error_tolerance_mode(), + endianness: ByteEndian::BE + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use crate::bit_depth::BitDepth; +use crate::colorspace::ColorSpace; + +/// Encoder options that are flags +#[derive(Copy, Debug, Clone, Default)] +struct EncoderFlags { + /// Whether JPEG images should be encoded as progressive images + jpeg_encode_progressive: bool, + /// Whether JPEG images should use optimized huffman tables + jpeg_optimize_huffman: bool, + /// Whether to not preserve metadata across image transformations + image_strip_metadata: bool +} + +/// Options shared by some of the encoders in +/// the `zune-` family of image crates +#[derive(Debug, Copy, Clone)] +pub struct EncoderOptions { + width: usize, + height: usize, + colorspace: ColorSpace, + quality: u8, + depth: BitDepth, + num_threads: u8, + effort: u8, + flags: EncoderFlags +} + +impl Default for EncoderOptions { + fn default() -> Self { + Self { + width: 0, + height: 0, + colorspace: ColorSpace::RGB, + quality: 80, + depth: BitDepth::Eight, + num_threads: 4, + effort: 4, + flags: EncoderFlags::default() + } + } +} + +impl EncoderOptions { + /// Create new encode options + /// + /// # Arguments + /// + /// * `width`: Image width + /// * `height`: Image height + /// * `colorspace`: Image colorspaces + /// * `depth`: Image depth + /// + /// returns: EncoderOptions + /// + pub fn new( + width: usize, height: usize, colorspace: ColorSpace, depth: BitDepth + ) -> EncoderOptions { + EncoderOptions { + width, + height, + colorspace, + depth, + ..Default::default() + } + } + /// Get the width for which the image will be encoded in + pub const fn width(&self) -> usize { + self.width + } + + /// Get height for which the image will be encoded in + /// + /// returns: usize + /// + /// # Panics + /// If height is zero + pub fn height(&self) -> usize { + assert_ne!(self.height, 0); + self.height + } + /// Get the depth for which the image will be encoded in + pub const fn depth(&self) -> BitDepth { + self.depth + } + /// Get the quality for which the image will be encoded with + /// + /// # Lossy + /// - Higher quality means some images take longer to write and + /// are big but they look good + /// + /// - Lower quality means small images and low quality. + /// + /// # Lossless + /// - High quality indicates more time is spent in making the file + /// smaller + /// + /// - Low quality indicates less time is spent in making the file bigger + pub const fn quality(&self) -> u8 { + self.quality + } + /// Get the colorspace for which the image will be encoded in + pub const fn colorspace(&self) -> ColorSpace { + self.colorspace + } + pub const fn effort(&self) -> u8 { + self.effort + } + + /// Set width for the image to be encoded + pub fn set_width(mut self, width: usize) -> Self { + self.width = width; + self + } + + /// Set height for the image to be encoded + pub fn set_height(mut self, height: usize) -> Self { + self.height = height; + self + } + /// Set depth for the image to be encoded + pub fn set_depth(mut self, depth: BitDepth) -> Self { + self.depth = depth; + self + } + /// Set quality of the image to be encoded + /// + /// Quality is clamped from 0..100 + /// + /// Quality means different options depending on the encoder, see + /// [get_quality](Self::quality) + pub fn set_quality(mut self, quality: u8) -> Self { + self.quality = quality.clamp(0, 100); + self + } + /// Set colorspace for the image to be encoded + pub fn set_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.colorspace = colorspace; + self + } + /// Set the number of threads allowed for multithreaded encoding + /// where supported + /// + /// Zero means use a single thread + pub fn set_num_threads(mut self, threads: u8) -> Self { + self.num_threads = threads; + + self + } + pub fn set_effort(mut self, effort: u8) -> Self { + self.effort = effort; + self + } + + /// Return number of threads configured for multithreading + /// where possible + /// + /// This is used for multi-threaded encoders, + /// currently only jpeg-xl + pub const fn num_threads(&self) -> u8 { + self.num_threads + } + + /// Set whether the encoder should remove metadata from the image + /// + /// When set to `true`, supported encoders will strip away metadata + /// from the resulting image. If set to false, where supported, encoders + /// will not remove metadata from images + pub fn set_strip_metadata(mut self, yes: bool) -> Self { + self.flags.image_strip_metadata = yes; + self + } + /// Whether or not the encoder should remove metadata from the image + /// + /// The default value is false, and encoders that respect this try to preserve as much + /// data as possible from one image to another + pub const fn strip_metadata(&self) -> bool { + !self.flags.image_strip_metadata + } +} + +/// JPEG options +impl EncoderOptions { + /// Whether the jpeg encoder should encode the image in progressive mode + /// + /// Default is `false`. + /// + /// This may be used to create slightly smaller images at the cost of more processing + /// time + pub const fn jpeg_encode_progressive(&self) -> bool { + self.flags.jpeg_encode_progressive + } + + /// Whether the jpeg encoder should optimize huffman tables to create smaller files + /// at the cost of processing time + /// + /// Default is `false`. + pub const fn jpeg_optimized_huffman_tables(&self) -> bool { + self.flags.jpeg_optimize_huffman + } + + /// Set whether the jpeg encoder should encode the imagei in progressive mode + /// + /// Default is `false` + pub fn set_jpeg_encode_progressive(mut self, yes: bool) -> Self { + self.flags.jpeg_optimize_huffman = yes; + self + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/options.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/options.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +//! Decoder and Encoder Options +//! +//! This module exposes a struct for which all implemented +//! decoders get shared options for decoding +//! +//! All supported options are put into one _Options to allow for global configurations +//! options e.g the same `DecoderOption` can be reused for all other decoders +//! +pub use decoder::DecoderOptions; +pub use encoder::EncoderOptions; + +mod decoder; +mod encoder; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/result.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/result.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/result.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/result.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decoding results for images +use alloc::vec::Vec; + +/// A simple enum that can hold decode +/// results of most images +#[non_exhaustive] +pub enum DecodingResult { + U8(Vec), + U16(Vec), + F32(Vec) +} + +impl DecodingResult { + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this won't fail because we created it with u8 + /// assert!(data.u8().is_some()); + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return nothing since the type is u18 + /// assert!(data.u8().is_none()); + /// + /// ``` + pub fn u8(self) -> Option> { + match self { + DecodingResult::U8(data) => Some(data), + _ => None + } + } + + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this will fail because we created it with u16 + /// assert!(data.u16().is_none()); + /// + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return something since the type is u16 + /// assert!(data.u16().is_some()); + /// + /// ``` + pub fn u16(self) -> Option> { + match self { + DecodingResult::U16(data) => Some(data), + _ => None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core/src/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core/src/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(feature = "serde")] +//! Serde support for serializing +//! crate datastructures +//! +//! Implements serialize for +//! - ColorSpace +//! - BitDepth +//! - ColorCharacteristics +use alloc::format; + +use serde::ser::*; + +use crate::bit_depth::BitDepth; +use crate::colorspace::{ColorCharacteristics, ColorSpace, RenderingIntent}; + +impl Serialize for ColorSpace { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + // colorspace serialization is simply it's debug value + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for BitDepth { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for ColorCharacteristics { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for RenderingIntent { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"5800ab418f46ded6c368ef3d2177c824f02e7c30411e03e8c19b595496976041","CHANGELOG.md":"3b6dcd5ee2c52ab91265c12d8dfaa7d0a2d4f05a08de2557041dece734e98e41","Cargo.toml":"65d39b608d230ee0a4d39d4de9388d695f2117322aff7005243d5b8e742a6526","Cargo.toml.orig":"cc3fa616bb3dd673abbdebce2d8b2a1a1ecb6a3dd9654313d6fcc0ab2d3c5f84","README.md":"1adae359f289c130fe2b098b412820d7da9924cb1bc52aeee8707971bab412b2","src/bit_depth.rs":"879b5b4b3ac99fc567f8d281662dc4125109f835b3944d023d038a084b2c0dd9","src/bytestream.rs":"ec12a04b4e1cfe1e592877b5ddc12df1f913677727525b88bfce935fc631519b","src/bytestream/reader.rs":"ca798f96876670bd8bd2a915cafc0eefaef57a09543a2fd310b0b4c3d48ad84a","src/bytestream/traits.rs":"fed12794c3bb7ee0fecc00ca96f96e96a6e3086407efb7b2b2aa10fbf2e01675","src/bytestream/writer.rs":"96227f650b813f68e1fd805ed523bbce7bf97af558bbe02b940e6dc2821eaeab","src/colorspace.rs":"070830c5f1056d3d0747f6cba1a12159379c192f5044584fb8d20b61abc338e7","src/lib.rs":"a627136eedec33bdf69996a43f8e8885c065f94d7c450d1503576e5b5922f44c","src/log.rs":"1655ea004aee621e4a93e57b6787693348348d8bb23f06feffc1e49537ea7565","src/options.rs":"9a29e94bed783c49f664f1583705fdd5a8b80a5e4e78868fd229d12691eec09d","src/options/decoder.rs":"f2c419e41c725319ebd777992e74dad19e4454869eed893145c882913ba26baf","src/options/encoder.rs":"22f86e152392a6f1d97832873498c172da34985454a7a0f2d1cb86295c7c58d0","src/result.rs":"92a098ba09ae4e5202da45a2d2165a6df804d3952e8c657950d064e4714afcaa","src/serde.rs":"23fe068415888dadb3daa1795f09214fb0d79e1a775fd7dce066386ee9334d59"},"package":"3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f8fbb123d5ed04441e8324a555bfcda0cb1bd28f" + }, + "path_in_vcs": "crates/zune-core" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +## 0.2.14 + +- Fixed building with no-std +- Add `peek_at` and `pos` for writer +- Make serde non default +- Add option to make PNG add an alpha channel + +## 0.2.12 + +- Add endianness conversion +- Hide exposed values for EncoderOptions +- Add Float32 bit depth +- Remove support for BitDepth 10 and 12 +- Add bit_size method + +## 0.2.1 + +Improve documentation on various parts + +## 0.2.0 + +Initial version \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "zune-core" +version = "0.4.12" +exclude = ["tests/"] +description = "Core utilities for image processing in the zune family of crates" +homepage = "https://github.com/etemesi254/zune-image/tree/dev/zune-core" +readme = "README.md" +keywords = ["image"] +categories = [ + "multimedia::images", + "multimedia::encoding", +] +license = "MIT OR Apache-2.0 OR Zlib" + +[dependencies.log] +version = "0.4.17" +optional = true + +[dependencies.serde] +version = "1.0.52" +optional = true + +[features] +std = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[package] +name = "zune-core" +version = "0.4.12" +edition = "2021" +description = "Core utilities for image processing in the zune family of crates" +exclude = ["tests/"] +homepage = "https://github.com/etemesi254/zune-image/tree/dev/zune-core" +keywords = ["image"] +categories = ["multimedia::images", "multimedia::encoding"] +license = "MIT OR Apache-2.0 OR Zlib" + +[features] +# When present, we can use std facilities to detect +# if a specific feature exists +# Not enabled by default. Other zune crates can enable dep:zune-core/std by default. +# But if we enable it here, they can't disable it anymore. +# See: https://github.com/rust-lang/cargo/issues/8366 +std = [] + +[dependencies] +log = { version = "0.4.17", optional = true } +serde = { version = "1.0.52", optional = true } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/README.md clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +## Zune core + +Core primitives necessary for image manipulations + +This crate contains small set of primitives +necessary for image manipulations which are shared among most `zune-` family +of decoders and encoders. + +### Items present + +Currently,it contains. + +- Colorspace definitions +- Bit depth definitions. +- Decoder and encoder options \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bit_depth.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bit_depth.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bit_depth.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bit_depth.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image bit depth, information and manipulations + +/// The image bit depth. +/// +/// The library successfully supports depths up to +/// 16 bits, as the underlying storage is usually a `u16`. +/// +/// This allows us to comfortably support a wide variety of images +/// e.g 10 bit av1, 16 bit png and ppm. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitDepth { + /// U8 bit depth. + /// + /// Images with such bit depth use [`u8`] to store + /// pixels and use the whole range from 0-255. + /// + /// It is currently the smallest supported bit depth + /// by the library. + /// + /// For images with bit depths lower than this, they will be scaled + /// to this bit depth + Eight, + /// U16 bit depth + /// + /// Images with such bit depths use [`u16`] to store values and use the whole range + /// i.e 0-65535 + /// + /// Data is stored and processed in native endian. + Sixteen, + /// Floating point 32 bit data, range is 0.0 to 1.0 + /// + /// Uses f32 to store data + Float32, + /// Bit depth information is unknown + Unknown +} + +/// The underlying bit representation of the image +/// +/// This represents the minimum rust type that +/// can be used to represent image data, required +/// by `Channel` struct in zune-image +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitType { + /// Images represented using a [`u8`] as their + /// underlying pixel storage + U8, + /// Images represented using a [`u16`] as their + /// underlying pixel storage. + U16, + /// Images represented using a [`f32`] as their + /// underlying pixel storage + F32 +} + +impl BitType { + /// Return the equivalent of the image bit type's depth + pub fn to_depth(self) -> BitDepth { + match self { + BitType::U8 => BitDepth::Eight, + BitType::U16 => BitDepth::Sixteen, + BitType::F32 => BitDepth::Float32 + } + } +} + +impl Default for BitDepth { + fn default() -> Self { + Self::Unknown + } +} + +impl BitDepth { + /// Get the max value supported by the bit depth + /// + /// During conversion from one bit depth to another + /// + /// larger values should be clamped to this bit depth + #[rustfmt::skip] + #[allow(clippy::zero_prefixed_literal)] + pub const fn max_value(self) -> u16 + { + match self + { + Self::Eight => (1 << 08) - 1, + Self::Sixteen => u16::MAX, + Self::Float32 => 1, + Self::Unknown => 0, + } + } + + /// Return the minimum number of bits that can be used to represent + /// each pixel in the image + /// + /// All bit depths below 8 return a bit type of `BitType::U8`. + /// and all those above 8 and below 16 return a bit type of `BitType::SixTeen` + /// + /// # Returns + /// An enum whose variants represent the minimum size for an unsigned integer + /// which can store the image pixels without overflow + /// + /// # Example + /// + /// ``` + /// use zune_core::bit_depth::{BitDepth, BitType}; + /// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8); + /// + /// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16); + /// ``` + /// + /// See also [size_of](BitDepth::size_of) + pub const fn bit_type(self) -> BitType { + match self { + Self::Eight => BitType::U8, + Self::Sixteen => BitType::U16, + Self::Float32 => BitType::F32, + Self::Unknown => panic!("Unknown bit type") + } + } + /// Get the number of bytes needed to store a specific bit depth + /// + /// + /// # Example + /// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store + /// the pixels, and a size_of [`u8`] is 1 + /// + /// For images greater than 8 bits and less than 16 bits(2 bytes), we can use a [`u16`] to + /// store the pixels, a size_of [`u16`] is 2. + /// ``` + /// use zune_core::bit_depth::BitDepth; + /// let depth = BitDepth::Sixteen; + /// // greater 12 bits is greater than 8 and less than 16 + /// assert_eq!(depth.size_of(),2); + /// ``` + pub const fn size_of(self) -> usize { + match self { + Self::Eight => core::mem::size_of::(), + Self::Sixteen => core::mem::size_of::(), + Self::Float32 => core::mem::size_of::(), + Self::Unknown => panic!("Unknown bit type") + } + } + pub const fn bit_size(&self) -> usize { + self.size_of() * 8 + } +} + +/// Byte endianness of returned samples +/// this is useful when the decoder returns samples which span more +/// than one byte yet the type returned is `&[u8]` +/// +/// This helps you interpret how those bytes should be reconstructed +/// to a higher order type +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum ByteEndian { + /// Little Endian byte-order + LE, + /// Big Endian byte-order + BE +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/reader.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use core::cmp::min; + +use crate::bytestream::traits::ZReaderTrait; + +const ERROR_MSG: &str = "No more bytes"; + +/// An encapsulation of a byte stream reader +/// +/// This provides an interface similar to [std::io::Cursor] but +/// it provides fine grained options for reading different integer data types from +/// the underlying buffer. +/// +/// There are two variants mainly error and non error variants, +/// the error variants are useful for cases where you need bytes +/// from the underlying stream, and cannot do with zero result. +/// the non error variants are useful when you may have proved data already exists +/// eg by using [`has`] method or you are okay with returning zero if the underlying +/// buffer has been completely read. +/// +/// [std::io::Cursor]: https://doc.rust-lang.org/std/io/struct.Cursor.html +/// [`has`]: Self::has +pub struct ZByteReader { + /// Data stream + stream: T, + position: usize +} + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} +#[cfg(feature = "std")] +impl std::io::Read for ZByteReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + Ok(self.read(buf).unwrap()) + } +} + +impl ZByteReader { + /// Create a new instance of the byte stream + /// + /// Bytes will be read from the start of `buf`. + /// + /// `buf` is expected to live as long as this and + /// all references to it live + /// + /// # Returns + /// A byte reader which will pull bits from bye + pub const fn new(buf: T) -> ZByteReader { + ZByteReader { + stream: buf, + position: 0 + } + } + /// Destroy this reader returning + /// the underlying source of the bytes + /// from which we were decoding + pub fn consume(self) -> T { + self.stream + } + /// Skip `num` bytes ahead of the stream. + /// + /// This bumps up the internal cursor wit a wrapping addition + /// The bytes between current position and `num` will be skipped + /// + /// # Arguments + /// `num`: How many bytes to skip + /// + /// # Note + /// This does not consider length of the buffer, so skipping more bytes + /// than possible and then reading bytes will return an error if using error variants + /// or zero if using non-error variants + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZByteReader; + /// let zero_to_hundred:Vec = (0..100).collect(); + /// let mut stream = ZByteReader::new(&zero_to_hundred); + /// // skip 37 bytes + /// stream.skip(37); + /// + /// assert_eq!(stream.get_u8(),37); + /// ``` + /// + /// See [`rewind`](ZByteReader::rewind) for moving the internal cursor back + pub fn skip(&mut self, num: usize) { + // Can this overflow ?? + self.position = self.position.wrapping_add(num); + } + /// Undo a buffer read by moving the position pointer `num` + /// bytes behind. + /// + /// This operation will saturate at zero + pub fn rewind(&mut self, num: usize) { + self.position = self.position.saturating_sub(num); + } + + /// Return whether the underlying buffer + /// has `num` bytes available for reading + /// + /// # Example + /// + /// ``` + /// use zune_core::bytestream::ZByteReader; + /// let data = [0_u8;120]; + /// let reader = ZByteReader::new(data.as_slice()); + /// assert!(reader.has(3)); + /// assert!(!reader.has(121)); + /// ``` + #[inline] + pub fn has(&self, num: usize) -> bool { + self.position.saturating_add(num) <= self.stream.get_len() + } + /// Get number of bytes available in the stream + #[inline] + pub fn get_bytes_left(&self) -> usize { + // Must be saturating to prevent underflow + self.stream.get_len().saturating_sub(self.position) + } + /// Get length of the underlying buffer. + /// + /// To get the number of bytes left in the buffer, + /// use [remaining] method + /// + /// [remaining]: Self::remaining + #[inline] + pub fn len(&self) -> usize { + self.stream.get_len() + } + /// Return true if the underlying buffer stream is empty + #[inline] + pub fn is_empty(&self) -> bool { + self.stream.get_len() == 0 + } + /// Get current position of the buffer. + #[inline] + pub const fn get_position(&self) -> usize { + self.position + } + /// Return true whether or not we read to the end of the + /// buffer and have no more bytes left. + #[inline] + pub fn eof(&self) -> bool { + self.position >= self.len() + } + /// Get number of bytes unread inside this + /// stream. + /// + /// To get the length of the underlying stream, + /// use [len] method + /// + /// [len]: Self::len() + #[inline] + pub fn remaining(&self) -> usize { + self.stream.get_len().saturating_sub(self.position) + } + /// Get a part of the bytestream as a reference. + /// + /// This increments the position to point past the bytestream + /// if position+num is in bounds + pub fn get(&mut self, num: usize) -> Result<&[u8], &'static str> { + match self.stream.get_slice(self.position..self.position + num) { + Some(bytes) => { + self.position += num; + Ok(bytes) + } + None => Err(ERROR_MSG) + } + } + /// Look ahead position bytes and return a reference + /// to num_bytes from that position, or an error if the + /// peek would be out of bounds. + /// + /// This doesn't increment the position, bytes would have to be discarded + /// at a later point. + #[inline] + pub fn peek_at(&self, position: usize, num_bytes: usize) -> Result<&[u8], &'static str> { + let start = self.position + position; + let end = self.position + position + num_bytes; + + match self.stream.get_slice(start..end) { + Some(bytes) => Ok(bytes), + None => Err(ERROR_MSG) + } + } + /// Get a fixed amount of bytes or return an error if we cant + /// satisfy the read + /// + /// This should be combined with [`has`] since if there are no + /// more bytes you get an error. + /// + /// But it's useful for cases where you expect bytes but they are not present + /// + /// For the zero variant see, [`get_fixed_bytes_or_zero`] + /// + /// # Example + /// ```rust + /// use zune_core::bytestream::ZByteReader; + /// let mut stream = ZByteReader::new([0x0,0x5,0x3,0x2].as_slice()); + /// let first_bytes = stream.get_fixed_bytes_or_err::<10>(); // not enough bytes + /// assert!(first_bytes.is_err()); + /// ``` + /// + /// [`has`]:Self::has + /// [`get_fixed_bytes_or_zero`]: Self::get_fixed_bytes_or_zero + #[inline] + pub fn get_fixed_bytes_or_err(&mut self) -> Result<[u8; N], &'static str> { + let mut byte_store: [u8; N] = [0; N]; + + match self.stream.get_slice(self.position..self.position + N) { + Some(bytes) => { + self.position += N; + byte_store.copy_from_slice(bytes); + + Ok(byte_store) + } + None => Err(ERROR_MSG) + } + } + + /// Get a fixed amount of bytes or return a zero array size + /// if we can't satisfy the read + /// + /// This should be combined with [`has`] since if there are no + /// more bytes you get a zero initialized array + /// + /// For the error variant see, [`get_fixed_bytes_or_err`] + /// + /// # Example + /// ```rust + /// use zune_core::bytestream::ZByteReader; + /// let mut stream = ZByteReader::new([0x0,0x5,0x3,0x2].as_slice()); + /// let first_bytes = stream.get_fixed_bytes_or_zero::<2>(); + /// assert_eq!(first_bytes,[0x0,0x5]); + /// ``` + /// + /// [`has`]:Self::has + /// [`get_fixed_bytes_or_err`]: Self::get_fixed_bytes_or_err + #[inline] + pub fn get_fixed_bytes_or_zero(&mut self) -> [u8; N] { + let mut byte_store: [u8; N] = [0; N]; + + match self.stream.get_slice(self.position..self.position + N) { + Some(bytes) => { + self.position += N; + byte_store.copy_from_slice(bytes); + + byte_store + } + None => byte_store + } + } + #[inline] + /// Skip bytes until a condition becomes false or the stream runs out of bytes + /// + /// # Example + /// + /// ```rust + /// use zune_core::bytestream::ZByteReader; + /// let mut stream = ZByteReader::new([0;10].as_slice()); + /// stream.skip_until_false(|x| x.is_ascii()) // skip until we meet a non ascii character + /// ``` + pub fn skip_until_false bool>(&mut self, func: F) { + // iterate until we have no more bytes + while !self.eof() { + // get a byte from stream + let byte = self.get_u8(); + + if !(func)(byte) { + // function returned false meaning we stop skipping + self.rewind(1); + break; + } + } + } + /// Return the remaining unread bytes in this byte reader + pub fn remaining_bytes(&self) -> &[u8] { + debug_assert!(self.position <= self.len()); + self.stream.get_slice(self.position..self.len()).unwrap() + } + + pub fn read(&mut self, buf: &mut [u8]) -> Result { + let buf_length = buf.len(); + let start = self.position; + let end = min(self.len(), self.position + buf_length); + let diff = end - start; + + buf[0..diff].copy_from_slice(self.stream.get_slice(start..end).unwrap()); + + self.skip(diff); + + Ok(diff) + } + + /// Read enough bytes to fill in + pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), &'static str> { + let size = self.read(buf)?; + + if size != buf.len() { + return Err("Could not read into the whole buffer"); + } + Ok(()) + } + + /// Set the cursor position + /// + /// After this, all reads will proceed from the position as an anchor + /// point + pub fn set_position(&mut self, position: usize) { + self.position = position; + } +} + +macro_rules! get_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl ZByteReader + { + #[inline(always)] + fn $name(&mut self, mode: Mode) -> $int_type + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + match self.stream.get_slice(self.position..self.position + SIZE_OF_VAL) + { + Some(position) => + { + space.copy_from_slice(position); + self.position += SIZE_OF_VAL; + + match mode + { + Mode::LE => $int_type::from_le_bytes(space), + Mode::BE => $int_type::from_be_bytes(space), + } + } + None => 0, + } + } + + #[inline(always)] + fn $name2(&mut self, mode: Mode) -> Result<$int_type, &'static str> + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + match self.stream.get_slice(self.position..self.position + SIZE_OF_VAL) + { + Some(position) => + { + space.copy_from_slice(position); + self.position += SIZE_OF_VAL; + + match mode + { + Mode::LE => Ok($int_type::from_le_bytes(space)), + Mode::BE => Ok($int_type::from_be_bytes(space)), + } + } + None => Err(ERROR_MSG), + } + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name3(&mut self) -> Result<$int_type, &'static str> + { + self.$name2(Mode::BE) + } + + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name4(&mut self) -> Result<$int_type, &'static str> + { + self.$name2(Mode::LE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name5(&mut self) -> $int_type + { + self.$name(Mode::BE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name6(&mut self) -> $int_type + { + self.$name(Mode::LE) + } + } + }; +} +// U8 implementation +// The benefit of our own unrolled u8 impl instead of macros is that this is sometimes used in some +// impls and is called multiple times, e.g jpeg during huffman decoding. +// we can make some functions leaner like get_u8 is branchless +impl ZByteReader +where + T: ZReaderTrait +{ + /// Retrieve a byte from the underlying stream + /// returning 0 if there are no more bytes available + /// + /// This means 0 might indicate a bit or an end of stream, but + /// this is useful for some scenarios where one needs a byte. + /// + /// For the panicking one, see [`get_u8_err`] + /// + /// [`get_u8_err`]: Self::get_u8_err + #[inline(always)] + pub fn get_u8(&mut self) -> u8 { + let byte = *self.stream.get_byte(self.position).unwrap_or(&0); + + self.position += usize::from(self.position < self.len()); + byte + } + + /// Retrieve a byte from the underlying stream + /// returning an error if there are no more bytes available + /// + /// For the non panicking one, see [`get_u8`] + /// + /// [`get_u8`]: Self::get_u8 + #[inline(always)] + pub fn get_u8_err(&mut self) -> Result { + match self.stream.get_byte(self.position) { + Some(byte) => { + self.position += 1; + Ok(*byte) + } + None => Err(ERROR_MSG) + } + } +} + +// u16,u32,u64 -> macros +get_single_type!( + get_u16_inner_or_default, + get_u16_inner_or_die, + get_u16_be_err, + get_u16_le_err, + get_u16_be, + get_u16_le, + u16 +); +get_single_type!( + get_u32_inner_or_default, + get_u32_inner_or_die, + get_u32_be_err, + get_u32_le_err, + get_u32_be, + get_u32_le, + u32 +); +get_single_type!( + get_u64_inner_or_default, + get_u64_inner_or_die, + get_u64_be_err, + get_u64_le_err, + get_u64_be, + get_u64_le, + u64 +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ +//! Traits for reading and writing images in zune +//! +//! +//! This exposes the traits and implementations for readers +//! and writers in the zune family of decoders and encoders. + +use alloc::vec::Vec; +use core::ops::Range; + +/// The underlying reader trait +/// +/// # Considerations +/// +///- When implementing this for a type, it is recommended to implement methods with +/// `#inline[(always)]` directive to allow the functions to get inlined in call sites, +/// this may make it faster on some situations since the call sites may be in hot loop. +/// +/// - If you are reading from a file and it's small , it is preferable to read it into memory +/// instead of using a file reader. +pub trait ZReaderTrait { + /// Get a single byte which is at position `index` + /// + /// # Arguments + /// - `index`: The position of the bytes + fn get_byte(&self, index: usize) -> Option<&u8>; + + /// Get a slice of bytes from a range of start..end + /// + /// # Arguments + /// + /// * `index`: The range of the bytes to read + /// + /// returns: `Option<&[u8]>` + /// + /// # Examples + /// + /// - Read 10 bytes from + /// ``` + /// extern crate alloc; + /// use alloc::vec::Vec; + /// use zune_core::bytestream::ZReaderTrait; + /// + /// let bytes = vec![0_u8;100]; + /// + /// // get ten bytes from 0..10 + /// let re = bytes.get_slice(0..10).unwrap(); + /// assert_eq!(10,re.len()) + /// + /// ``` + fn get_slice(&self, index: Range) -> Option<&[u8]>; + + /// Get total length of the underlying buffer. + /// + /// This should be the total bytes that are present in + /// the buffer. + /// + /// For files, this includes the file length. + /// For buffers this includes the internal buffer length + fn get_len(&self) -> usize; +} + +impl ZReaderTrait for &[u8] { + #[inline(always)] + fn get_byte(&self, index: usize) -> Option<&u8> { + self.get(index) + } + + #[inline(always)] + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.get(index) + } + + #[inline(always)] + fn get_len(&self) -> usize { + self.len() + } +} + +impl ZReaderTrait for Vec { + #[inline(always)] + fn get_byte(&self, index: usize) -> Option<&u8> { + self.get(index) + } + + #[inline(always)] + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.get(index) + } + + #[inline(always)] + fn get_len(&self) -> usize { + self.len() + } +} + +impl ZReaderTrait for &Vec { + #[inline(always)] + fn get_byte(&self, index: usize) -> Option<&u8> { + self.get(index) + } + + #[inline(always)] + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.get(index) + } + + #[inline(always)] + fn get_len(&self) -> usize { + self.len() + } +} + +impl ZReaderTrait for &[u8; N] { + fn get_byte(&self, index: usize) -> Option<&u8> { + self.get(index) + } + + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.get(index) + } + + fn get_len(&self) -> usize { + N + } +} + +impl ZReaderTrait for [u8; N] { + fn get_byte(&self, index: usize) -> Option<&u8> { + self.get(index) + } + + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.get(index) + } + + fn get_len(&self) -> usize { + N + } +} + +impl ZReaderTrait for dyn AsRef<&[u8]> { + fn get_byte(&self, index: usize) -> Option<&u8> { + self.as_ref().get(index) + } + + fn get_slice(&self, index: Range) -> Option<&[u8]> { + self.as_ref().get(index) + } + + fn get_len(&self) -> usize { + self.as_ref().len() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/writer.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use core::mem::size_of; + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} + +static ERROR_MSG: &str = "No more space"; + +/// Encapsulates a simple Byte writer with +/// support for Endian aware writes +pub struct ZByteWriter<'a> { + buffer: &'a mut [u8], + position: usize +} + +impl<'a> ZByteWriter<'a> { + /// Write bytes from the buf into the bytestream + /// and return how many bytes were written + /// + /// # Arguments + /// - `buf`: The bytes to be written to the bytestream + /// + /// # Returns + /// - `Ok(usize)` - Number of bytes written + /// This number may be less than `buf.len()` if the length of the buffer is greater + /// than the internal bytestream length + /// + /// If you want to be sure that all bytes were written, see [`write_all`](Self::write_all) + /// + #[inline] + pub fn write(&mut self, buf: &[u8]) -> Result { + let min = buf.len().min(self.bytes_left()); + // write + self.buffer[self.position..self.position + min].copy_from_slice(&buf[0..min]); + self.position += min; + + Ok(min) + } + /// Write all bytes from `buf` into the bytestream and return + /// and panic if not all bytes were written to the bytestream + /// + /// # Arguments + /// - `buf`: The bytes to be written into the bytestream + /// + ///# Returns + /// - `Ok(())`: Indicates all bytes were written into the bytestream + /// - `Err(&static str)`: In case all the bytes could not be written + /// to the stream + pub fn write_all(&mut self, buf: &[u8]) -> Result<(), &'static str> { + let size = self.write(buf)?; + + if size != buf.len() { + return Err("Could not write the whole buffer"); + } + Ok(()) + } + /// Create a new bytestream writer + /// Bytes are written from the start to the end and not assumptions + /// are made of the nature of the underlying stream + /// + /// # Arguments + pub fn new(data: &'a mut [u8]) -> ZByteWriter<'a> { + ZByteWriter { + buffer: data, + position: 0 + } + } + /// Return number of unwritten bytes in this stream + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let mut storage = [0;10]; + /// + /// let writer = ZByteWriter::new(&mut storage); + /// assert_eq!(writer.bytes_left(),10); // no bytes were written + /// ``` + pub const fn bytes_left(&self) -> usize { + self.buffer.len().saturating_sub(self.position) + } + + /// Return the number of bytes the writer has written + /// + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let mut stream = ZByteWriter::new(&mut []); + /// assert_eq!(stream.position(),0); + /// ``` + pub const fn position(&self) -> usize { + self.position + } + + /// Write a single byte into the bytestream or error out + /// if there is not enough space + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let mut buf = [0;10]; + /// let mut stream = ZByteWriter::new(&mut buf); + /// assert!(stream.write_u8_err(34).is_ok()); + /// ``` + /// No space + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let mut stream = ZByteWriter::new(&mut []); + /// assert!(stream.write_u8_err(32).is_err()); + /// ``` + /// + pub fn write_u8_err(&mut self, byte: u8) -> Result<(), &'static str> { + match self.buffer.get_mut(self.position) { + Some(m_byte) => { + self.position += 1; + *m_byte = byte; + + Ok(()) + } + None => Err(ERROR_MSG) + } + } + + /// Write a single byte in the stream or don't write + /// anything if the buffer is full and cannot support the byte read + /// + /// Should be combined with [`has`](Self::has) + pub fn write_u8(&mut self, byte: u8) { + if let Some(m_byte) = self.buffer.get_mut(self.position) { + self.position += 1; + *m_byte = byte; + } + } + /// Check if the byte writer can support + /// the following write + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let mut data = [0;10]; + /// let mut stream = ZByteWriter::new(&mut data); + /// assert!(stream.has(5)); + /// assert!(!stream.has(100)); + /// ``` + pub const fn has(&self, bytes: usize) -> bool { + self.position.saturating_add(bytes) <= self.buffer.len() + } + + /// Get length of the underlying buffer. + #[inline] + pub const fn len(&self) -> usize { + self.buffer.len() + } + /// Return true if the underlying buffer stream is empty + #[inline] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Return true whether or not we read to the end of the + /// buffer and have no more bytes left. + /// + /// If this is true, all non error variants will silently discard the + /// byte and all error variants will return an error on writing a byte + /// if any write occurs + /// + /// + #[inline] + pub const fn eof(&self) -> bool { + self.position >= self.len() + } + + /// Rewind the position of the internal cursor back by `by` bytes + /// + /// The position saturates at zero + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZByteWriter; + /// let bytes = &mut [1,2,4]; + /// let mut stream = ZByteWriter::new(bytes); + /// stream.write_u16_be(23); + /// // now internal cursor is at position 2. + /// // lets rewind it + /// stream.rewind(usize::MAX); + /// assert_eq!(stream.position(),0); + /// ``` + #[inline] + pub fn rewind(&mut self, by: usize) { + self.position = self.position.saturating_sub(by); + } + /// Move the internal cursor forward some bytes + /// + /// + /// This saturates at maximum value of usize in your platform. + #[inline] + pub fn skip(&mut self, by: usize) { + self.position = self.position.saturating_add(by); + } + + /// Look ahead position bytes and return a reference + /// to num_bytes from that position, or an error if the + /// peek would be out of bounds. + /// + /// This doesn't increment the position, bytes would have to be discarded + /// at a later point. + #[inline] + pub fn peek_at(&'a self, position: usize, num_bytes: usize) -> Result<&'a [u8], &'static str> { + let start = self.position + position; + let end = self.position + position + num_bytes; + + match self.buffer.get(start..end) { + Some(bytes) => Ok(bytes), + None => Err(ERROR_MSG) + } + } + + /// Set position for the internal cursor + /// + /// Further calls to write bytes will proceed from the + /// position set + pub fn set_position(&mut self, position: usize) { + self.position = position; + } +} + +macro_rules! write_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl<'a> ZByteWriter<'a> + { + #[inline(always)] + fn $name(&mut self, byte: $int_type, mode: Mode) -> Result<(), &'static str> + { + const SIZE: usize = size_of::<$int_type>(); + + match self.buffer.get_mut(self.position..self.position + SIZE) + { + Some(m_byte) => + { + self.position += SIZE; + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + + m_byte.copy_from_slice(&bytes); + + Ok(()) + } + None => Err(ERROR_MSG) + } + } + #[inline(always)] + fn $name2(&mut self, byte: $int_type, mode: Mode) + { + const SIZE: usize = size_of::<$int_type>(); + + if let Some(m_byte) = self.buffer.get_mut(self.position..self.position + SIZE) + { + self.position += SIZE; + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + + m_byte.copy_from_slice(&bytes); + } + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name3(&mut self, byte: $int_type) -> Result<(), &'static str> + { + self.$name(byte, Mode::BE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name4(&mut self, byte: $int_type) -> Result<(), &'static str> + { + self.$name(byte, Mode::LE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[doc=concat!("\nShould be combined with the [`has`](Self::has) method to ensure a write succeeds")] + #[inline] + pub fn $name5(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::BE) + } + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[doc=concat!("Should be combined with the [`has`](Self::has) method to ensure a write succeeds")] + #[inline] + pub fn $name6(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::LE) + } + } + }; +} + +write_single_type!( + write_u64_inner_or_die, + write_u64_inner_or_none, + write_u64_be_err, + write_u64_le_err, + write_u64_be, + write_u64_le, + u64 +); + +write_single_type!( + write_u32_inner_or_die, + write_u32_inner_or_none, + write_u32_be_err, + write_u32_le_err, + write_u32_be, + write_u32_le, + u32 +); + +write_single_type!( + write_u16_inner_or_die, + write_u16_inner_or_none, + write_u16_be_err, + write_u16_le_err, + write_u16_be, + write_u16_le, + u16 +); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/bytestream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! A simple implementation of a bytestream reader +//! and writer. +//! +//! This module contains two main structs that help in +//! byte reading and byte writing +//! +//! Useful for a lot of image readers and writers, it's put +//! here to minimize code reuse +pub use reader::ZByteReader; +pub use traits::*; +pub use writer::ZByteWriter; + +mod reader; +mod traits; +mod writer; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/colorspace.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/colorspace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/colorspace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/colorspace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image Colorspace information and manipulation utilities. + +/// All possible image colorspaces +/// Some of them aren't yet supported exist here. +#[allow(clippy::upper_case_acronyms)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum ColorSpace { + /// Red, Green , Blue + RGB, + /// Red, Green, Blue, Alpha + RGBA, + /// YUV colorspace + YCbCr, + /// Grayscale colorspace + Luma, + /// Grayscale with alpha colorspace + LumaA, + YCCK, + /// Cyan , Magenta, Yellow, Black + CMYK, + /// Blue, Green, Red + BGR, + /// Blue, Green, Red, Alpha + BGRA, + /// The colorspace is unknown + Unknown, + /// Alpha Red Green Blue + ARGB, + /// Hue,Saturation,Lightness + /// Conversion from RGB to HSL and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSL, + /// Hue, Saturation,Value + /// + /// Conversion from RGB to HSV and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSV +} + +impl ColorSpace { + /// Number of color channels present for a certain colorspace + /// + /// E.g. RGB returns 3 since it contains R,G and B colors to make up a pixel + pub const fn num_components(&self) -> usize { + match self { + Self::RGB | Self::YCbCr | Self::BGR | Self::HSV | Self::HSL => 3, + Self::RGBA | Self::YCCK | Self::CMYK | Self::BGRA | Self::ARGB => 4, + Self::Luma => 1, + Self::LumaA => 2, + Self::Unknown => 0 + } + } + + pub const fn has_alpha(&self) -> bool { + matches!(self, Self::RGBA | Self::LumaA | Self::BGRA | Self::ARGB) + } + + pub const fn is_grayscale(&self) -> bool { + matches!(self, Self::LumaA | Self::Luma) + } + + /// Returns the position of the alpha pixel in a pixel + /// + /// + /// That is for an array of color components say `[0,1,2,3]` if the image has an alpha channel + /// and is in RGBA format, this will return `Some(3)`, indicating alpha is found in the third index + /// but if the image is in `ARGB` format, it will return `Some(0)` indicating alpha is found in + /// index 0 + /// + /// If an image doesn't have an alpha channel returns `None` + /// + pub const fn alpha_position(&self) -> Option { + match self { + ColorSpace::RGBA => Some(3), + ColorSpace::LumaA => Some(1), + ColorSpace::BGRA => Some(3), + ColorSpace::ARGB => Some(0), + _ => None + } + } +} + +/// Encapsulates all colorspaces supported by +/// the library +pub static ALL_COLORSPACES: [ColorSpace; 12] = [ + ColorSpace::RGB, + ColorSpace::RGBA, + ColorSpace::LumaA, + ColorSpace::Luma, + ColorSpace::CMYK, + ColorSpace::BGRA, + ColorSpace::BGR, + ColorSpace::YCCK, + ColorSpace::YCbCr, + ColorSpace::ARGB, + ColorSpace::HSL, + ColorSpace::HSV +]; + +/// Color characteristics +/// +/// Gives more information about values in a certain +/// colorspace +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ColorCharacteristics { + /// Normal default gamma setting + /// The float contains gamma present + /// + /// The default gamma value is 2.2 but for + /// decoders that allow specifying gamma values,e.g PNG, + /// the gamma value becomes the specified value by the decoder + sRGB, + /// Linear transfer characteristics + /// The image is in linear colorspace + Linear +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Core routines shared by all libraries +//! +//! This crate provides a set of core routines shared +//! by the decoders and encoders under `zune` umbrella +//! +//! It currently contains +//! +//! - A bytestream reader and writer with endian aware reads and writes +//! - Colorspace and bit depth information shared by images +//! - Image decoder and encoder options +//! - A simple enum type to hold image decoding results. +//! +//! This library is `#[no_std]` with `alloc` feature needed for defining `Vec` +//! which we need for storing decoded bytes. +//! +//! +//! # Features +//! - `no_std`: Enables `#[no_std]` compilation support. +//! +//! - `serde`: Enables serializing of some of the data structures +//! present in the crate +//! +#![cfg_attr(not(feature = "std"), no_std)] +#![macro_use] +extern crate alloc; + +#[cfg(not(feature = "log"))] +pub mod log; + +#[cfg(feature = "log")] +pub use log; + +pub mod bit_depth; +pub mod bytestream; +pub mod colorspace; +pub mod options; +pub mod result; +mod serde; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/log.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/log.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/log.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/log.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +// #[macro_export] is required to make macros works across crates +// but it always put the macro in the crate root. +// #[doc(hidden)] + "pub use" is a workaround to namespace a macro. +pub use crate::{ + __debug as debug, __error as error, __info as info, __log_enabled as log_enabled, + __trace as trace, __warn as warn +}; + +#[repr(usize)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub enum Level { + Error = 1, + Warn, + Info, + Debug, + Trace +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_enabled { + ($lvl:expr) => {{ + let _ = $lvl; + false + }}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __error { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __warn { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __info { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __debug { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __trace { + ($($arg:tt)+) => {}; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Global Decoder options +#![allow(clippy::zero_prefixed_literal)] + +use crate::bit_depth::ByteEndian; +use crate::colorspace::ColorSpace; + +fn decoder_strict_mode() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: true, + png_confirm_crc: true, + jpg_error_on_non_conformance: true, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Fast decoder options +/// +/// Enables all intrinsics + unsafe routines +/// +/// Disables png adler and crc checking. +fn fast_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Command line options error resilient and fast +/// +/// Features +/// - Ignore CRC and Adler in png +/// - Do not error out on non-conformance in jpg +/// - Use unsafe paths +fn cmd_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Decoder options that are flags +/// +/// NOTE: When you extend this, add true or false to +/// all options above that return a `DecoderFlag` +#[derive(Copy, Debug, Clone, Default)] +pub struct DecoderFlags { + /// Whether the decoder should confirm and report adler mismatch + inflate_confirm_adler: bool, + /// Whether the PNG decoder should confirm crc + png_confirm_crc: bool, + /// Whether the png decoder should error out on image non-conformance + jpg_error_on_non_conformance: bool, + /// Whether the decoder should use unsafe platform specific intrinsics + /// + /// This will also shut down platform specific intrinsics `(ZUNE_USE_{EXT})` value + zune_use_unsafe: bool, + /// Whether we should use SSE2. + /// + /// This should be enabled for all x64 platforms but can be turned off if + /// `ZUNE_USE_UNSAFE` is false + zune_use_sse2: bool, + /// Whether we should use SSE3 instructions where possible. + zune_use_sse3: bool, + /// Whether we should use sse4.1 instructions where possible. + zune_use_sse41: bool, + /// Whether we should use avx instructions where possible. + zune_use_avx: bool, + /// Whether we should use avx2 instructions where possible. + zune_use_avx2: bool, + /// Whether the png decoder should add alpha channel where possible. + png_add_alpha_channel: bool, + /// Whether we should use neon instructions where possible. + zune_use_neon: bool, + /// Whether the png decoder should strip 16 bit to 8 bit + png_strip_16_bit_to_8_bit: bool, + /// Decode all frames for an animated images + png_decode_animated: bool, + jxl_decode_animated: bool +} + +/// Decoder options +/// +/// Not all options are respected by decoders all decoders +#[derive(Debug, Copy, Clone)] +pub struct DecoderOptions { + /// Maximum width for which decoders will + /// not try to decode images larger than + /// the specified width. + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_width: usize, + /// Maximum height for which decoders will not + /// try to decode images larger than the + /// specified height + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_height: usize, + /// Output colorspace + /// + /// The jpeg decoder allows conversion to a separate colorspace + /// than the input. + /// + /// I.e you can convert a RGB jpeg image to grayscale without + /// first decoding it to RGB to get + /// + /// - Default value: `ColorSpace::RGB` + /// - Respected by: `jpeg` + out_colorspace: ColorSpace, + + /// Maximum number of scans allowed + /// for progressive jpeg images + /// + /// Progressive jpegs have scans + /// + /// - Default value:100 + /// - Respected by: `jpeg` + max_scans: usize, + /// Maximum size for deflate. + /// Respected by all decoders that use inflate/deflate + deflate_limit: usize, + /// Boolean flags that influence decoding + flags: DecoderFlags, + /// The byte endian of the returned bytes will be stored in + /// in case a single pixel spans more than a byte + endianness: ByteEndian +} + +/// Initializers +impl DecoderOptions { + /// Create the decoder with options setting most configurable + /// options to be their safe counterparts + /// + /// This is the same as `default` option as default initializes + /// options to the safe variant. + /// + /// Note, decoders running on this will be slower as it disables + /// platform specific intrinsics + pub fn new_safe() -> DecoderOptions { + DecoderOptions::default() + } + + /// Create the decoder with options setting the configurable options + /// to the fast counterparts + /// + /// This enables platform specific code paths and enable use of unsafe + pub fn new_fast() -> DecoderOptions { + let flag = fast_options(); + DecoderOptions::default().set_decoder_flags(flag) + } + + /// Create the decoder options with the following characteristics + /// + /// - Use unsafe paths. + /// - Ignore error checksuming, e.g in png we do not confirm adler and crc in this mode + /// - Enable fast intrinsics paths + pub fn new_cmd() -> DecoderOptions { + let flag = cmd_options(); + DecoderOptions::default().set_decoder_flags(flag) + } +} + +/// Global options respected by all decoders +impl DecoderOptions { + /// Get maximum width configured for which the decoder + /// should not try to decode images greater than this width + pub const fn get_max_width(&self) -> usize { + self.max_width + } + + /// Get maximum height configured for which the decoder should + /// not try to decode images greater than this height + pub const fn get_max_height(&self) -> usize { + self.max_height + } + + /// Return true whether the decoder should be in strict mode + /// And reject most errors + pub fn get_strict_mode(&self) -> bool { + self.flags.jpg_error_on_non_conformance + | self.flags.png_confirm_crc + | self.flags.inflate_confirm_adler + } + /// Return true if the decoder should use unsafe + /// routines where possible + pub const fn get_use_unsafe(&self) -> bool { + self.flags.zune_use_unsafe + } + + /// Set maximum width for which the decoder should not try + /// decoding images greater than that width + /// + /// # Arguments + /// + /// * `width`: The maximum width allowed + /// + /// returns: DecoderOptions + pub fn set_max_width(mut self, width: usize) -> Self { + self.max_width = width; + self + } + + /// Set maximum height for which the decoder should not try + /// decoding images greater than that height + /// # Arguments + /// + /// * `height`: The maximum height allowed + /// + /// returns: DecoderOptions + /// + pub fn set_max_height(mut self, height: usize) -> Self { + self.max_height = height; + self + } + + /// Whether the routines can use unsafe platform specific + /// intrinsics when necessary + /// + /// Platform intrinsics are implemented for operations which + /// the compiler can't auto-vectorize, or we can do a marginably + /// better job at it + /// + /// All decoders with unsafe routines respect it. + /// + /// Treat this with caution, disabling it will cause slowdowns but + /// it's provided for mainly for debugging use. + /// + /// - Respected by: `png` and `jpeg`(decoders with unsafe routines) + pub fn set_use_unsafe(mut self, yes: bool) -> Self { + // first clear the flag + self.flags.zune_use_unsafe = yes; + self + } + + fn set_decoder_flags(mut self, flags: DecoderFlags) -> Self { + self.flags = flags; + self + } + /// Set whether the decoder should be in standards conforming/ + /// strict mode + /// + /// This reduces the error tolerance level for the decoders and invalid + /// samples will be rejected by the decoder + /// + /// # Arguments + /// + /// * `yes`: + /// + /// returns: DecoderOptions + /// + pub fn set_strict_mode(mut self, yes: bool) -> Self { + self.flags.jpg_error_on_non_conformance = yes; + self.flags.png_confirm_crc = yes; + self.flags.inflate_confirm_adler = yes; + self + } + + /// Set the byte endian for which raw samples will be stored in + /// in case a single pixel sample spans more than a byte. + /// + /// The default is usually native endian hence big endian values + /// will be converted to little endian on little endian systems, + /// + /// and little endian values will be converted to big endian on big endian systems + /// + /// # Arguments + /// + /// * `endian`: The endianness to which to set the bytes to + /// + /// returns: DecoderOptions + pub fn set_byte_endian(mut self, endian: ByteEndian) -> Self { + self.endianness = endian; + self + } + + /// Get the byte endian for which samples that span more than one byte will + /// be treated + pub const fn get_byte_endian(&self) -> ByteEndian { + self.endianness + } +} + +/// PNG specific options +impl DecoderOptions { + /// Whether the inflate decoder should confirm + /// adler checksums + pub const fn inflate_get_confirm_adler(&self) -> bool { + self.flags.inflate_confirm_adler + } + /// Set whether the inflate decoder should confirm + /// adler checksums + pub fn inflate_set_confirm_adler(mut self, yes: bool) -> Self { + self.flags.inflate_confirm_adler = yes; + self + } + /// Get default inflate limit for which the decoder + /// will not try to decompress further + pub const fn inflate_get_limit(&self) -> usize { + self.deflate_limit + } + /// Set the default inflate limit for which decompressors + /// relying on inflate won't surpass this limit + #[must_use] + pub fn inflate_set_limit(mut self, limit: usize) -> Self { + self.deflate_limit = limit; + self + } + /// Whether the inflate decoder should confirm + /// crc 32 checksums + pub const fn png_get_confirm_crc(&self) -> bool { + self.flags.png_confirm_crc + } + /// Set whether the png decoder should confirm + /// CRC 32 checksums + #[must_use] + pub fn png_set_confirm_crc(mut self, yes: bool) -> Self { + self.flags.png_confirm_crc = yes; + self + } + /// Set whether the png decoder should add an alpha channel to + /// images where possible. + /// + /// For Luma images, it converts it to Luma+Alpha + /// + /// For RGB images it converts it to RGB+Alpha + pub fn png_set_add_alpha_channel(mut self, yes: bool) -> Self { + self.flags.png_add_alpha_channel = yes; + self + } + /// Return true whether the png decoder should add an alpha + /// channel to images where possible + pub const fn png_get_add_alpha_channel(&self) -> bool { + self.flags.png_add_alpha_channel + } + + /// Whether the png decoder should reduce 16 bit images to 8 bit + /// images implicitly. + /// + /// Equivalent to [png::Transformations::STRIP_16](https://docs.rs/png/latest/png/struct.Transformations.html#associatedconstant.STRIP_16) + pub fn png_set_strip_to_8bit(mut self, yes: bool) -> Self { + self.flags.png_strip_16_bit_to_8_bit = yes; + self + } + + /// Return a boolean indicating whether the png decoder should reduce + /// 16 bit images to 8 bit images implicitly + pub const fn png_get_strip_to_8bit(&self) -> bool { + self.flags.png_strip_16_bit_to_8_bit + } + + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_decode_animated(&self) -> bool { + self.flags.png_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.png_decode_animated = yes; + self + } +} + +/// JPEG specific options +impl DecoderOptions { + /// Get maximum scans for which the jpeg decoder + /// should not go above for progressive images + pub const fn jpeg_get_max_scans(&self) -> usize { + self.max_scans + } + + /// Set maximum scans for which the jpeg decoder should + /// not exceed when reconstructing images. + pub fn jpeg_set_max_scans(mut self, max_scans: usize) -> Self { + self.max_scans = max_scans; + self + } + /// Get expected output colorspace set by the user for which the image + /// is expected to be reconstructed into. + /// + /// This may be different from the + pub const fn jpeg_get_out_colorspace(&self) -> ColorSpace { + self.out_colorspace + } + /// Set expected colorspace for which the jpeg output is expected to be in + /// + /// This is mainly provided as is, we do not guarantee the decoder can convert to all colorspaces + /// and the decoder can change it internally when it sees fit. + #[must_use] + pub fn jpeg_set_out_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.out_colorspace = colorspace; + self + } +} + +/// Intrinsics support +/// +/// These routines are compiled depending +/// on the platform they are used, if compiled for a platform +/// it doesn't support,(e.g avx2 on Arm), it will always return `false` +impl DecoderOptions { + /// Use SSE 2 code paths where possible + /// + /// This checks for existence of SSE2 first and returns + /// false if it's not present + #[allow(unreachable_code)] + pub fn use_sse2(&self) -> bool { + let opt = self.flags.zune_use_sse2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse2") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse2"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE 3 paths where possible + /// + /// + /// This also checks for SSE3 support and returns false if + /// it's not present + #[allow(unreachable_code)] + pub fn use_sse3(&self) -> bool { + let opt = self.flags.zune_use_sse3 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse3") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse3"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE4 paths where possible + /// + /// This also checks for sse 4.1 support and returns false if it + /// is not present + #[allow(unreachable_code)] + pub fn use_sse41(&self) -> bool { + let opt = self.flags.zune_use_sse41 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse4.1") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse4.1"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use AVX paths where possible + /// + /// This also checks for AVX support and returns false if it's + /// not present + #[allow(unreachable_code)] + pub fn use_avx(&self) -> bool { + let opt = self.flags.zune_use_avx | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use avx2 paths where possible + /// + /// This also checks for AVX2 support and returns false if it's not + /// present + #[allow(unreachable_code)] + pub fn use_avx2(&self) -> bool { + let opt = self.flags.zune_use_avx2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx2") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx2"))] + { + return true; + } + } + // everything failed return false + false + } + + #[allow(unreachable_code)] + pub fn use_neon(&self) -> bool { + let opt = self.flags.zune_use_neon | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(target_arch = "aarch64")] + { + // aarch64 implies neon on a compliant cpu + // but for real prod should do something better here + return true; + } + // everything failed return false + false + } +} + +/// JPEG_XL specific options +impl DecoderOptions { + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_decode_animated(&self) -> bool { + self.flags.jxl_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.jxl_decode_animated = yes; + self + } +} +impl Default for DecoderOptions { + fn default() -> Self { + Self { + out_colorspace: ColorSpace::RGB, + max_width: 1 << 14, + max_height: 1 << 14, + max_scans: 100, + deflate_limit: 1 << 30, + flags: decoder_strict_mode(), + endianness: ByteEndian::BE + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use crate::bit_depth::BitDepth; +use crate::colorspace::ColorSpace; + +/// Encoder options that are flags +#[derive(Copy, Debug, Clone, Default)] +struct EncoderFlags { + /// Whether JPEG images should be encoded as progressive images + jpeg_encode_progressive: bool, + /// Whether JPEG images should use optimized huffman tables + jpeg_optimize_huffman: bool, + /// Whether to not preserve metadata across image transformations + image_strip_metadata: bool +} + +/// Options shared by some of the encoders in +/// the `zune-` family of image crates +#[derive(Debug, Copy, Clone)] +pub struct EncoderOptions { + width: usize, + height: usize, + colorspace: ColorSpace, + quality: u8, + depth: BitDepth, + num_threads: u8, + effort: u8, + flags: EncoderFlags +} + +impl Default for EncoderOptions { + fn default() -> Self { + Self { + width: 0, + height: 0, + colorspace: ColorSpace::RGB, + quality: 80, + depth: BitDepth::Eight, + num_threads: 4, + effort: 4, + flags: EncoderFlags::default() + } + } +} + +impl EncoderOptions { + /// Create new encode options + /// + /// # Arguments + /// + /// * `width`: Image width + /// * `height`: Image height + /// * `colorspace`: Image colorspaces + /// * `depth`: Image depth + /// + /// returns: EncoderOptions + /// + pub fn new( + width: usize, height: usize, colorspace: ColorSpace, depth: BitDepth + ) -> EncoderOptions { + EncoderOptions { + width, + height, + colorspace, + depth, + ..Default::default() + } + } + /// Get the width for which the image will be encoded in + pub const fn get_width(&self) -> usize { + self.width + } + + /// Get height for which the image will be encoded in + /// + /// returns: usize + /// + /// # Panics + /// If height is zero + pub fn get_height(&self) -> usize { + assert_ne!(self.height, 0); + self.height + } + /// Get the depth for which the image will be encoded in + pub const fn get_depth(&self) -> BitDepth { + self.depth + } + /// Get the quality for which the image will be encoded with + /// + /// # Lossy + /// - Higher quality means some images take longer to write and + /// are big but they look good + /// + /// - Lower quality means small images and low quality. + /// + /// # Lossless + /// - High quality indicates more time is spent in making the file + /// smaller + /// + /// - Low quality indicates less time is spent in making the file bigger + pub const fn get_quality(&self) -> u8 { + self.quality + } + /// Get the colorspace for which the image will be encoded in + pub const fn get_colorspace(&self) -> ColorSpace { + self.colorspace + } + pub const fn get_effort(&self) -> u8 { + self.effort + } + + /// Set width for the image to be encoded + pub fn set_width(mut self, width: usize) -> Self { + self.width = width; + self + } + + /// Set height for the image to be encoded + pub fn set_height(mut self, height: usize) -> Self { + self.height = height; + self + } + /// Set depth for the image to be encoded + pub fn set_depth(mut self, depth: BitDepth) -> Self { + self.depth = depth; + self + } + /// Set quality of the image to be encoded + /// + /// Quality is clamped from 0..100 + /// + /// Quality means different options depending on the encoder, see + /// [get_quality](Self::get_quality) + pub fn set_quality(mut self, quality: u8) -> Self { + self.quality = quality.clamp(0, 100); + self + } + /// Set colorspace for the image to be encoded + pub fn set_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.colorspace = colorspace; + self + } + /// Set the number of threads allowed for multithreaded encoding + /// where supported + /// + /// Zero means use a single thread + pub fn set_num_threads(mut self, threads: u8) -> Self { + self.num_threads = threads; + + self + } + pub fn set_effort(mut self, effort: u8) -> Self { + self.effort = effort; + self + } + + /// Return number of threads configured for multithreading + /// where possible + /// + /// This is used for multi-threaded encoders, + /// currently only jpeg-xl + pub const fn get_num_threads(&self) -> u8 { + self.num_threads + } + + /// Set whether the encoder should remove metadata from the image + /// + /// When set to `true`, supported encoders will strip away metadata + /// from the resulting image. If set to false, where supported, encoders + /// will not remove metadata from images + pub fn set_strip_metadata(mut self, yes: bool) -> Self { + self.flags.image_strip_metadata = yes; + self + } + /// Whether or not the encoder should remove metadata from the image + /// + /// The default value is false, and encoders that respect this try to preserve as much + /// data as possible from one image to another + pub const fn strip_metadata(&self) -> bool { + !self.flags.image_strip_metadata + } +} + +/// JPEG options +impl EncoderOptions { + /// Whether the jpeg encoder should encode the image in progressive mode + /// + /// Default is `false`. + /// + /// This may be used to create slightly smaller images at the cost of more processing + /// time + pub const fn jpeg_encode_progressive(&self) -> bool { + self.flags.jpeg_encode_progressive + } + + /// Whether the jpeg encoder should optimize huffman tables to create smaller files + /// at the cost of processing time + /// + /// Default is `false`. + pub const fn jpeg_optimized_huffman_tables(&self) -> bool { + self.flags.jpeg_optimize_huffman + } + + /// Set whether the jpeg encoder should encode the imagei in progressive mode + /// + /// Default is `false` + pub fn set_jpeg_encode_progressive(mut self, yes: bool) -> Self { + self.flags.jpeg_optimize_huffman = yes; + self + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/options.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/options.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +//! Decoder and Encoder Options +//! +//! This module exposes a struct for which all implemented +//! decoders get shared options for decoding +//! +//! All supported options are put into one _Options to allow for global configurations +//! options e.g the same `DecoderOption` can be reused for all other decoders +//! +pub use decoder::DecoderOptions; +pub use encoder::EncoderOptions; + +mod decoder; +mod encoder; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/result.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/result.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/result.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/result.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decoding results for images +use alloc::vec::Vec; + +/// A simple enum that can hold decode +/// results of most images +#[non_exhaustive] +pub enum DecodingResult { + U8(Vec), + U16(Vec), + F32(Vec) +} + +impl DecodingResult { + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this won't fail because we created it with u8 + /// assert!(data.u8().is_some()); + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return nothing since the type is u18 + /// assert!(data.u8().is_none()); + /// + /// ``` + pub fn u8(self) -> Option> { + match self { + DecodingResult::U8(data) => Some(data), + _ => None + } + } + + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this will fail because we created it with u16 + /// assert!(data.u16().is_none()); + /// + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return something since the type is u16 + /// assert!(data.u16().is_some()); + /// + /// ``` + pub fn u16(self) -> Option> { + match self { + DecodingResult::U16(data) => Some(data), + _ => None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-core-0.4.12/src/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-core-0.4.12/src/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(feature = "serde")] +//! Serde support for serializing +//! crate datastructures +//! +//! Implements serialize for +//! - ColorSpace +//! - BitDepth +//! - ColorCharacteristics +use alloc::format; + +use serde::ser::*; + +use crate::bit_depth::BitDepth; +use crate::colorspace::{ColorCharacteristics, ColorSpace}; + +impl Serialize for ColorSpace { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + // colorspace serialization is simply it's debug value + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for BitDepth { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for ColorCharacteristics { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/.cargo-checksum.json 2025-06-17 01:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"e82df64959cb3ecd8c54555ff2296157455a52f9c19027a051b6c04b02ca2b6a","Cargo.toml":"f3da162dd3818fcdf23c9ce34930d66064106873a692d6994abd49b80e60ea66","README.md":"ad9675f80fd32f89ceabc856d8e5c4fea145aa8bbbf2cba423fdb3687ac634d9","src/bitstream.rs":"68dc48bb9b3143c7dc3603494cf105585915a7e793d6c0e4d7e7eff18bed59e0","src/constants.rs":"8fe65b0c99f92bdb7ae4918f48047b1ce53dd903f9e8248b6f93797fd9b850b1","src/crc.rs":"a2a2aa0fcf4b668bf99b4e0c9d5e33f9c465acaeec28992dad4469f86f01f37a","src/crc/crc_tables.rs":"6d6c5063e7c66cdd9c179c4ad302eefeb6dfd45e8ee78b21d7026efefeeb1ec3","src/decoder.rs":"dec3511b03a94e4a219e8945f9496200058ae8fc01b39e8b687d05540b544339","src/encoder.rs":"c99d7afda5c50bc52efc5d8e788da6a884d0e13b3b38865f760f5ed3d9fc65bd","src/encoder/fast_match_finder.rs":"67bcc3602a1705dd375128526d99334aee78777dc19bcc622757d78c43af90d6","src/errors.rs":"86ed95b4ac51a8d57dff8bac9c324f793d15d74e334fcc6d9822ad5ee531f919","src/gzip_constants.rs":"5c4c08a010470817f671b4dee8657ee65e35a1f76132da0ddd8872c24df4dc5c","src/lib.rs":"ee2b5b58f48ee36835bd4e312a26dace36be39d1c4af956f4e2e04d0620667f9","src/utils.rs":"5a72c84c72273dea894b05fb4dbc4d8690c1ace859fe1d16a702a93158326fa0"},"package":"73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"1aa1fe13706244305622b464deb9216c9bd081ba93f6b43a97034b6d21db6273","CHANGELOG.md":"e82df64959cb3ecd8c54555ff2296157455a52f9c19027a051b6c04b02ca2b6a","Cargo.toml":"f3da162dd3818fcdf23c9ce34930d66064106873a692d6994abd49b80e60ea66","Cargo.toml.orig":"a7e3d8fd82218e7f9f2172d41a048e4879abc81228589539e1ec750d72811f90","README.md":"ad9675f80fd32f89ceabc856d8e5c4fea145aa8bbbf2cba423fdb3687ac634d9","src/bitstream.rs":"68dc48bb9b3143c7dc3603494cf105585915a7e793d6c0e4d7e7eff18bed59e0","src/constants.rs":"8fe65b0c99f92bdb7ae4918f48047b1ce53dd903f9e8248b6f93797fd9b850b1","src/crc.rs":"a2a2aa0fcf4b668bf99b4e0c9d5e33f9c465acaeec28992dad4469f86f01f37a","src/crc/crc_tables.rs":"6d6c5063e7c66cdd9c179c4ad302eefeb6dfd45e8ee78b21d7026efefeeb1ec3","src/decoder.rs":"dec3511b03a94e4a219e8945f9496200058ae8fc01b39e8b687d05540b544339","src/encoder.rs":"c99d7afda5c50bc52efc5d8e788da6a884d0e13b3b38865f760f5ed3d9fc65bd","src/encoder/fast_match_finder.rs":"67bcc3602a1705dd375128526d99334aee78777dc19bcc622757d78c43af90d6","src/errors.rs":"86ed95b4ac51a8d57dff8bac9c324f793d15d74e334fcc6d9822ad5ee531f919","src/gzip_constants.rs":"5c4c08a010470817f671b4dee8657ee65e35a1f76132da0ddd8872c24df4dc5c","src/lib.rs":"ee2b5b58f48ee36835bd4e312a26dace36be39d1c4af956f4e2e04d0620667f9","src/utils.rs":"5a72c84c72273dea894b05fb4dbc4d8690c1ace859fe1d16a702a93158326fa0"},"package":"73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "69502ce83fdfecdd0beefd677e2abb3781b29d98" + }, + "path_in_vcs": "zune-inflate" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zune-inflate/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-inflate/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +[package] +name = "zune-inflate" +version = "0.2.54" +edition = "2021" +description = "A heavily optimized deflate decompressor in Pure Rust" +exclude = ["tests/"] +homepage = "https://github.com/etemesi254/zune-image/tree/main/zune-inflate" +keywords = ["compression", "inflate", "deflate"] +categories = ["compression"] +license = "MIT OR Apache-2.0 OR Zlib" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +zlib = ["simd-adler32"] +gzip = [] +std = ["simd-adler32/std"] + + +default = ["zlib", "gzip", "std"] + +[dependencies] +simd-adler32 = { version = "0.3.4", optional = true, default-features = false } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"3b5863a092e48fff9b71da99cf1e78d88190974faa1f00a015dff17755bf83c3","Benches.md":"5e0a2292e9a2b6d5d7923f4b847a9aead7ab656326ef58018d30dfa46c53cf20","Cargo.lock":"c3d75ebb74fd89360b3323f55ef28e3b4315aaf139ff149dd744bbc4d8c9b54d","Cargo.toml":"bd51df6320e0d7be0e3254024920c07a20c0afef3577938aab12c7b729d5070c","Cargo.toml.orig":"73aa1b7c3fad4cd17195d32671d8a357113227844f733e223cd05d95627c54d2","Changelog.md":"296a9f6db2fbc8813357d0cafb9c041efce7177d1f7b6026a7af81031defb879","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"d30047bca3b516639339a3c279bb84c3483124fb5a9dafe3c75056a85090e745","LICENSE-ZLIB":"d201d14804d3bcd3b944147173175e4abfbd838b7c8069b6bd3452496bf13e6c","README.md":"d58a4403ff2b9f7eba16f1284a9b4a4c7125bc92dacd8f0fac1ee112e3a8b8ee","src/bitstream.rs":"652cf824ee8b15249b026d7d27e1e08fad494ce3a3560abfe95beedde20eb6db","src/color_convert.rs":"e401a9c71beffd50a0b17330a5f64de82ad944e7f7cfe42a8a8bbf6b24ac245a","src/color_convert/avx.rs":"7be52b218a32ca06d8727dbd5d9ff18f0e09ee05c2147e2469e1b78f25e4f1f5","src/color_convert/neon64.rs":"d4b4b2ae87b57e857db6ade0b6c0a664182ebbad89aa5934e2959d06bf734d1d","src/color_convert/scalar.rs":"daf7a7595775ce00bec28997330bc72f0fd3cd113d764cf742a7b502ca93c108","src/components.rs":"4553c0bfad38aaf53af82db22a0f0fb5ab2b93125ab361f9b69485c5edd8f71d","src/decoder.rs":"d880c37195091cedb3f3281dc4ab13433b280618e7032f506fbb35d0a8441984","src/errors.rs":"106e9bca458efccd9b290ff5cf9365ad195d7afc3e414108111cc88b9c344e8f","src/headers.rs":"8509577e6d42013559d2aea39d03d70a6404640298f4db1dd59465b30e4ea1ed","src/huffman.rs":"921649bd61aeeecb11bf91d7e76afad583e54717255824bf0c2d4bb6160d6b10","src/idct.rs":"be856aec47d17f28dfaa98072f2317eb78be0f6b9dc9535f5d309e97da5cf8e8","src/idct/avx2.rs":"126185cc71e1b72e0f37632633d3d0fee5c974fde203f332bb36e30487fd3c66","src/idct/neon.rs":"919aad93765a5f025974798e9068c3a5b4497d3da4fe9ae63c901cb52c9c123e","src/idct/scalar.rs":"c2a682081ef33dabe957b46075136119b28fef44cdfff4cffb044b38a6cabbf1","src/lib.rs":"3b35d5daf358b00997c36f173ef056b7c44c62233af1a035b2ec80d02e61cbe7","src/marker.rs":"10014f879004c0b1ca4bca66155eb2385820cce02ae6e48a9e9b37ca60ecd294","src/mcu.rs":"768cedfab97acbdcaebd8c886f565af38bfcb6d405d9c56f6ffae3086124af0a","src/mcu_prog.rs":"1439d45fb116a1a0e377f764a0d6212e607e141c32f56c1a0325e98ac28b3c1e","src/misc.rs":"1ba8300b38095fc0cb2e91f615d401d7a6b45d20115f314df66153add7b776da","src/unsafe_utils.rs":"8fa830ca67b7f701461fe2382f8843faa33c98b5f83f1845f60c8ef788143c75","src/unsafe_utils_avx2.rs":"2e2a8294a8c8c6ca3e92356b47a088090c2c62853b37cfcadeba4ab55f545721","src/unsafe_utils_neon.rs":"b7087a9897c9e3c66a1bf7a910e7dab30e2a92ca3483c1b01101f69e07d05e87","src/upsampler.rs":"81ca309c31baf578b293abc6dbeb4d37b69f14b0e2811d15fe3bb9aa637cc01a","src/upsampler/avx2.rs":"381a709c4ce1b750de535e7fc37d02ff81188cfd11c81858c0489ad4d280f370","src/upsampler/neon.rs":"b8aefe165154227402282e66c9450d6d81c5e60c63b0626f979dc2b36dab71cb","src/upsampler/portable_simd.rs":"84b4f9756f00bcea68c4c7897a9cef6335bc3b96973f2328690d64f8f8e0011f","src/upsampler/scalar.rs":"c3a57d943b8df501feed9a4a59f3a2401d836383ce4dae2344ad518b002e201e","src/worker.rs":"c08e5ad28eb3013588d64377907aac8db964a87d59a5d8da7306766c227509ca"},"package":"e35aee689668bf9bd6f6f3a6c60bb29ba1244b3b43adfd50edd554a371da37d5"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f14152f0d74ecbb7df49308cc3c0548d64f63acb" + }, + "path_in_vcs": "crates/zune-jpeg" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Benches.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Benches.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Benches.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Benches.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +# Benchmarks of popular jpeg libraries + +Here I compare how long it takes popular JPEG decoders to decode the below 7680*4320 image +of (now defunct ?) [Cutefish OS](https://en.cutefishos.com/) default wallpaper. +![img](benches/images/speed_bench.jpg) + +## About benchmarks + +Benchmarks are weird, especially IO & multi-threaded programs. This library uses both of the above hence performance may +vary. + +For best results shut down your machine, go take coffee, think about life and how it came to be and why people should +save the environment. + +Then power up your machine, if it's a laptop connect it to a power supply and if there is a setting for performance +mode, tweak it. + +Then run. + +## Benchmarks vs real world usage + +Real world usage may vary. + +Notice that I'm using a large image but probably most decoding will be small to medium images. + +To make the library thread safe, we do about 1.5-1.7x more allocations than libjpeg-turbo. Although, do note that the +allocations do not occur at ago, we allocate when needed and deallocate when not needed. + +Do note if memory bandwidth is a limitation. This is not for you. + +## Reproducibility + +The benchmarks are carried out on my local machine with an AMD Ryzen 5 4500u + +The benchmarks are reproducible. + +To reproduce them + +1. Clone this repository +2. Install rust(if you don't have it yet) +3. `cd` into the directory. +4. Run `cargo bench` + +## Performance features of the three libraries + +| feature | image-rs/jpeg-decoder | libjpeg-turbo | zune-jpeg | +|------------------------------|-----------------------|---------------|-----------| +| multithreaded | ✅ | ❌ | ❌ | +| platform specific intrinsics | ✅ | ✅ | ✅ | + +- Image-rs/jpeg-decoder uses [rayon] under the hood but it's under a feature + flag. + +- libjpeg-turbo uses hand-written asm for platform specific intrinsics, ported to + the most common architectures out there but falls back to scalar + code if it can't run in a platform. + +# Finally benchmarks + +[here] + +## Notes + +Benchmarks are ran at least once a week to catch regressions early and +are uploaded to Github pages. + +Machine specs can be found on the other [landing page] + +Benchmarks may not reflect real world usage(threads, other I/O machine bottlenecks) + +[landing page]:https://etemesi254.github.io/posts/Zune-Benchmarks/ + +[here]:https://etemesi254.github.io/assets/criterion/report/index.html + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo + +[jpeg-decoder]:https://github.com/image-rs/jpeg-decoder + +[rayon]:https://github.com/rayon-rs/rayon \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" +dependencies = [ + "log", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.8" +dependencies = [ + "zune-core", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,67 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.87.0" +name = "zune-jpeg" +version = "0.5.8" +authors = ["caleb "] +build = false +exclude = [ + "/benches/images/*", + "/tests/*", + "/.idea/*", + "/.gradle/*", + "/test-images/*", + "fuzz/*", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A fast, correct and safe jpeg decoder" +readme = "README.md" +keywords = [ + "jpeg", + "jpeg-decoder", + "decoder", +] +categories = ["multimedia::images"] +license = "MIT OR Apache-2.0 OR Zlib" +repository = "https://github.com/etemesi254/zune-image/tree/dev/crates/zune-jpeg" + +[features] +default = [ + "x86", + "neon", + "std", +] +log = ["zune-core/log"] +neon = [] +portable_simd = [] +std = ["zune-core/std"] +x86 = [] + +[lib] +name = "zune_jpeg" +path = "src/lib.rs" + +[dependencies.zune-core] +version = "^0.5" + +[dev-dependencies] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(fuzzing)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +[package] +name = "zune-jpeg" +version = "0.5.8" +rust-version = "1.87.0" +authors = ["caleb "] +edition = "2021" +repository = "https://github.com/etemesi254/zune-image/tree/dev/crates/zune-jpeg" +license = "MIT OR Apache-2.0 OR Zlib" +keywords = ["jpeg", "jpeg-decoder", "decoder"] +categories = ["multimedia::images"] +exclude = ["/benches/images/*", "/tests/*", "/.idea/*", "/.gradle/*", "/test-images/*", "fuzz/*"] +description = "A fast, correct and safe jpeg decoder" + +[lints.rust] +# Disable feature checker for fuzzing since it's used and cargo doesn't +# seem to recognise fuzzing +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } + + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +x86 = [] +neon = [] +std = ["zune-core/std"] +portable_simd = [] +log = ["zune-core/log"] +default = ["x86", "neon", "std"] + + +[dependencies] +zune-core = { path = "../zune-core", version = "^0.5" } + + +[dev-dependencies] +zune-ppm = { path = "../zune-ppm" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Changelog.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Changelog.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/Changelog.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/Changelog.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +## Version 0.5.7 +- Move scalar idct to wrapping maths. +- Simd upsampling (mhils) +- Faster zero idct check (mhils) +## Version 0.5.6 + - Better support for truncated images (by https://github.com/mhils) + - fix 4:1:0 chroma subsampling (by https://github.com/mhils) + - Fix some crashes + - Fix some bug on last pixel sampling + +## Version 0.5.5 +- Support direct conversion of Luma to RGBA +## Version 0.5.4 +- Fix overriding color space when decoding Luma colorspace +## Version 0.5.3 +- Fix some decoding of some images with markers in progressive segments, see https://github.com/etemesi254/zune-image/issues/295 +## Version 0.5.1 + +- Fix decoding of particular images with a non-standard subsample, ( + see https://github.com/etemesi254/zune-image/issues/291) +- Add better RGB color detection of images to match libjpeg and stb_image formats + +----- + +## Version 0.3.17 + +- Fix no-std compilation + +## Version 0.3.16 + +- Add support for decoding to BGR and BGRA + +## Version 0.3.14 + +- Add ability to parse exif and ICC chunk. +- Fix images with one component that were down-sampled. + +### Version 0.3.13 + +- Allow decoding into pre-allocated buffer +- Clarify documentation + +### Version 0.3.11 + +- Add guards for SSE and AVX code paths(allows compiling for platforms that do not support it) + +### Version 0.3.0 + +- Overhaul to the whole decoder. +- Single threaded version +- Lightweight. + +### Version 0.2.0 + +- New `ZuneJpegOptions` struct, this is the now recommended way to set up decoding options for + decoding +- Deprecated previous options setting functions. +- More code cleanups +- Fixed new bugs discovered by fuzzing +- Removed dependency on `num_cpu` + +### Version 0.1.5 + +- Allow user to set memory limits in during decoding explicitly via `set_limits` +- Fixed some bugs discovered by fuzzing +- Correctly handle small images less than 16 pixels +- Gracefully handle incorrectly sampled images. + +### Version 0.1.4 + +- Remove all `unsafe` instances except platform dependent intrinsics. +- Numerous bug fixes identified by fuzzing. +- Expose `ImageInfo` to the crate root. + +### Version 0.1.3 + +- Fix numerous panics found by fuzzing(thanks to @[Shnatsel] for the corpus) +- Add new method `set_num_threads` that allows one to explicitly set the number of threads to use to decode the image. + +### Version 0.1.2 + +- Add more sub checks, contributed by @[5225225] +- Privatize some modules. + +### Version 0.1.1 + +- Fix rgba/rgbx decoding when avx optimized functions were used +- Initial support for fuzzing +- Remove `align_alloc` method which was unsound (Thanks to @[HeroicKatora] for pointing that out) + +[Shnatsel]:https://github.com/Shnatsel + +[HeroicKatora]:https://github.com/HeroicKatora + +[5225225]:https://github.com/5225225 \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) zune-image developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-ZLIB clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-ZLIB --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/LICENSE-ZLIB 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/LICENSE-ZLIB 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,19 @@ +zlib License + +(C) zune-image developers + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/README.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,104 @@ +# Zune-JPEG + +A fast, correct and safe jpeg decoder in pure Rust. + +## Usage + +The library provides a simple-to-use API for jpeg decoding +and an ability to add options to influence decoding. + +### Example + +```Rust +// Import the library +use zune_jpeg::JpegDecoder; +use std::fs::read; + +fn main()->Result<(),DecoderErrors> { + // load some jpeg data + let data = read("cat.jpg").unwrap(); + // create a decoder + let mut decoder = JpegDecoder::new(&data); + // decode the file + let pixels = decoder.decode()?; +} +``` + +The decoder supports more manipulations via `DecoderOptions`, +see additional documentation in the library. + +## Goals + +The implementation aims to have the following goals achieved, +in order of importance + +1. Safety - Do not segfault on errors or invalid input. Panics are okay, but + should be fixed when reported. `unsafe` is only used for SIMD intrinsics, + and can be turned off entirely both at compile time and at runtime. +2. Speed - Get the data as quickly as possible, which means + 1. Platform intrinsics code where justifiable + 2. Carefully written platform independent code that allows the + compiler to vectorize it. + 3. Regression tests. + 4. Watch the memory usage of the program +3. Usability - Provide utility functions like different color conversions functions. + +## Non-Goals + +- Bit identical results with libjpeg/libjpeg-turbo will never be an aim of this library. + Jpeg is a lossy format with very few parts specified by the standard + (i.e it doesn't give a reference upsampling and color conversion algorithm) + +## Features + +- [x] A Pretty fast 8*8 integer IDCT. +- [x] Fast Huffman Decoding +- [x] Fast color convert functions. +- [x] Support for extended colorspaces like GrayScale and RGBA +- [X] Single-threaded decoding. +- [X] Support for four component JPEGs, and esoteric color schemes like CYMK +- [X] Support for `no_std` +- [X] BGR/BGRA decoding support. + +## Crate Features + +| feature | on | Capabilities | +|---------|-----|---------------------------------------------------------------------------------------------| +| `x86` | yes | Enables `x86` specific instructions, specifically `avx` and `sse` for accelerated decoding. | +| `std` | yes | Enable linking to the `std` crate | + +Note that the `x86` features are automatically disabled on platforms that aren't x86 during compile +time hence there is no need to disable them explicitly if you are targeting such a platform. + +## Using in a `no_std` environment + +The crate can be used in a `no_std` environment with the `alloc` feature. + +But one is required to link to a working allocator for whatever environment the decoder +will be running on + +## Debug vs release + +The decoder heavily relies on platform specific intrinsics, namely AVX2 and SSE to gain speed-ups in decoding, +but they [perform poorly](https://godbolt.org/z/vPq57z13b) in debug builds. To get reasonable performance even +when compiling your program in debug mode, add this to your `Cargo.toml`: + +```toml +# `zune-jpeg` package will be always built with optimizations +[profile.dev.package.zune-jpeg] +opt-level = 3 +``` + +## Benchmarks + +The library tries to be at fast as [libjpeg-turbo] while being as safe as possible. +Platform specific intrinsics help get speed up intensive operations ensuring we can almost +match [libjpeg-turbo] speeds but speeds are always +- 10 ms of this library. + +For more up-to-date benchmarks, see the online repo with +benchmarks [here](https://etemesi254.github.io/assets/criterion/report/index.html) + + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo/ + +[image-rs/jpeg-decoder]:https://github.com/image-rs/jpeg-decoder/tree/master/src diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/bitstream.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/bitstream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/bitstream.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/bitstream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::if_not_else, + clippy::similar_names, + clippy::inline_always, + clippy::doc_markdown, + clippy::cast_sign_loss, + clippy::cast_possible_truncation +)] + +//! This file exposes a single struct that can decode a huffman encoded +//! Bitstream in a JPEG file +//! +//! This code is optimized for speed. +//! It's meant to be super duper super fast, because everyone else depends on this being fast. +//! It's (annoyingly) serial hence we cant use parallel bitstreams(it's variable length coding.) +//! +//! Furthermore, on the case of refills, we have to do bytewise processing because the standard decided +//! that we want to support markers in the middle of streams(seriously few people use RST markers). +//! +//! So we pull in all optimization steps: +//! - use `inline[always]`? ✅ , +//! - pre-execute most common cases ✅, +//! - add random comments ✅ +//! - fast paths ✅. +//! +//! Speed-wise: It is probably the fastest JPEG BitStream decoder to ever sail the seven seas because of +//! a couple of optimization tricks. +//! 1. Fast refills from libjpeg-turbo +//! 2. As few as possible branches in decoder fast paths. +//! 3. Accelerated AC table decoding borrowed from stb_image.h written by Fabian Gissen (@ rygorous), +//! improved by me to handle more cases. +//! 4. Safe and extensible routines(e.g. cool ways to eliminate bounds check) +//! 5. No unsafe here +//! +//! Readability comes as a second priority(I tried with variable names this time, and we are wayy better than libjpeg). +//! +//! Anyway if you are reading this it means your cool and I hope you get whatever part of the code you are looking for +//! (or learn something cool) +//! +//! Knock yourself out. +use alloc::format; +use alloc::string::ToString; +use core::cmp::min; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; + +use crate::errors::DecodeErrors; +use crate::huffman::{HuffmanTable, HUFF_LOOKAHEAD}; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::UN_ZIGZAG; + +macro_rules! decode_huff { + ($stream:tt,$symbol:tt,$table:tt) => { + let mut code_length = $symbol >> HUFF_LOOKAHEAD; + + ($symbol) &= (1 << HUFF_LOOKAHEAD) - 1; + + if code_length > i32::from(HUFF_LOOKAHEAD) + { + // if the symbol cannot be resolved in the first HUFF_LOOKAHEAD bits, + // we know it lies somewhere between HUFF_LOOKAHEAD and 16 bits since jpeg imposes 16 bit + // limit, we can therefore look 16 bits ahead and try to resolve the symbol + // starting from 1+HUFF_LOOKAHEAD bits. + $symbol = ($stream).peek_bits::<16>() as i32; + // (Credits to Sean T. Barrett stb library for this optimization) + // maxcode is pre-shifted 16 bytes long so that it has (16-code_length) + // zeroes at the end hence we do not need to shift in the inner loop. + while code_length < 17{ + if $symbol < $table.maxcode[code_length as usize] { + break; + } + code_length += 1; + } + + if code_length == 17{ + // symbol could not be decoded. + // + // We may think, lets fake zeroes, noo + // panic, because Huffman codes are sensitive, probably everything + // after this will be corrupt, so no need to continue. + // panic!("Bad Huffman code length"); + return Err(DecodeErrors::Format(format!("Bad Huffman Code 0x{:X}, corrupt JPEG",$symbol))) + } + + $symbol >>= (16-code_length); + ($symbol) = i32::from( + ($table).values + [(($symbol + ($table).offset[code_length as usize]) & 0xFF) as usize], + ); + } + if code_length> i32::from(($stream).bits_left){ + return Err(DecodeErrors::Format(format!("Code length {code_length} more than bits left {}",($stream).bits_left))) + } + // drop bits read + ($stream).drop_bits(code_length as u8); + }; +} + +/// A `BitStream` struct, a bit by bit reader with super powers +/// +#[rustfmt::skip] +pub(crate) struct BitStream { + /// A MSB type buffer that is used for some certain operations + pub buffer: u64, + /// A TOP aligned MSB type buffer that is used to accelerate some operations like + /// peek_bits and get_bits. + /// + /// By top aligned, I mean the top bit (63) represents the top bit in the buffer. + aligned_buffer: u64, + /// Tell us the bits left the two buffer + pub(crate) bits_left: u8, + /// Did we find a marker(RST/EOF) during decoding? + pub marker: Option, + /// An i16 with the bit corresponding to successive_low set to 1, others 0. + pub successive_low_mask: i16, + spec_start: u8, + spec_end: u8, + pub eob_run: i32, + pub overread_by: usize, + /// True if we have seen end of image marker. + /// Don't read anything after that. + pub seen_eoi: bool, +} + +impl BitStream { + /// Create a new BitStream + #[rustfmt::skip] + pub(crate) const fn new() -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_low_mask: 1, + spec_start: 0, + spec_end: 0, + eob_run: 0, + overread_by: 0, + seen_eoi: false, + } + } + + /// Create a new Bitstream for progressive decoding + #[allow(clippy::redundant_field_names)] + #[rustfmt::skip] + pub(crate) fn new_progressive(al: u8, spec_start: u8, spec_end: u8) -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_low_mask: 1i16 << al, + spec_start: spec_start, + spec_end: spec_end, + eob_run: 0, + overread_by: 0, + seen_eoi: false, + } + } + + /// Refill the bit buffer by (a maximum of) 32 bits + /// + /// # Arguments + /// - `reader`:`&mut BufReader`: A mutable reference to an underlying + /// File/Memory buffer containing a valid JPEG stream + /// + /// This function will only refill if `self.count` is less than 32 + #[inline(always)] // to many call sites? ( perf improvement by 4%) + pub fn refill(&mut self, reader: &mut ZReader) -> Result + where + T: ZByteReaderTrait + { + /// Macro version of a single byte refill. + /// Arguments + /// buffer-> our io buffer, because rust macros cannot get values from + /// the surrounding environment bits_left-> number of bits left + /// to full refill + macro_rules! refill { + ($buffer:expr,$byte:expr,$bits_left:expr) => { + // read a byte from the stream + $byte = u64::from(reader.read_u8()); + self.overread_by += usize::from(reader.eof()?); + // append to the buffer + // JPEG is a MSB type buffer so that means we append this + // to the lower end (0..8) of the buffer and push the rest bits above.. + $buffer = ($buffer << 8) | $byte; + // Increment bits left + $bits_left += 8; + // Check for special case of OxFF, to see if it's a stream or a marker + if $byte == 0xff { + // read next byte + let mut next_byte = u64::from(reader.read_u8()); + // Byte snuffing, if we encounter byte snuff, we skip the byte + if next_byte != 0x00 { + // skip that byte we read + while next_byte == 0xFF { + next_byte = u64::from(reader.read_u8()); + } + + if next_byte != 0x00 { + // Undo the byte append and return + $buffer >>= 8; + $bits_left -= 8; + + if $bits_left != 0 { + self.aligned_buffer = $buffer << (64 - $bits_left); + } + + let marker = Marker::from_u8(next_byte as u8); + self.marker = marker; + + if let Some(Marker::UNKNOWN(_)) = marker{ + return Err(DecodeErrors::Format("Unknown marker in bit stream".to_string())); + } + if next_byte == 0xD9 { + // special handling for eoi, fill some bytes,even if its zero, + // removes some panics + self.buffer <<= 8; + self.bits_left += 8; + self.aligned_buffer = self.buffer << (64 - self.bits_left); + } + + return Ok(false); + } + } + } + }; + } + + // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits) + if self.bits_left < 32 { + if self.marker.is_some() || self.overread_by > 0 || self.seen_eoi { + // found a marker, or we are in EOI + // also we are in over-reading mode, where we fill it with zeroes + + // fill with zeroes + self.buffer <<= 32; + self.bits_left += 32; + self.aligned_buffer = self.buffer << (64 - self.bits_left); + return Ok(true); + } + + // we optimize for the case where we don't have 255 in the stream and have 4 bytes left + // as it is the common case + // + // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is + // guaranteed not to advance in case of failure (is this true), so + // we revert the read later on (if we have 255), if this fails, we use the normal + // byte at a time read + + if let Ok(bytes) = reader.read_fixed_bytes_or_error::<4>() { + // we have 4 bytes to spare, read the 4 bytes into a temporary buffer + // create buffer + let msb_buf = u32::from_be_bytes(bytes); + // check if we have 0xff + if !has_byte(msb_buf, 255) { + self.bits_left += 32; + self.buffer <<= 32; + self.buffer |= u64::from(msb_buf); + self.aligned_buffer = self.buffer << (64 - self.bits_left); + return Ok(true); + } + + reader.rewind(4)?; + } + // This serves two reasons, + // 1: Make clippy shut up + // 2: Favour register reuse + let mut byte; + // 4 refills, if all succeed the stream should contain enough bits to decode a + // value + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + // Construct an MSB buffer whose top bits are the bitstream we are currently holding. + self.aligned_buffer = self.buffer << (64 - self.bits_left); + } + return Ok(true); + } + /// Decode the DC coefficient in a MCU block. + /// + /// The decoded coefficient is written to `dc_prediction` + /// + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::unwrap_used + )] + #[inline(always)] + fn decode_dc( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, dc_prediction: &mut i32 + ) -> Result + where + T: ZByteReaderTrait + { + let (mut symbol, r); + + if self.bits_left < 32 { + self.refill(reader)?; + }; + // look a head HUFF_LOOKAHEAD bits into the bitstream + symbol = self.peek_bits::(); + symbol = dc_table.lookup[symbol as usize]; + + decode_huff!(self, symbol, dc_table); + + if symbol != 0 { + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + } + // Update DC prediction + *dc_prediction = dc_prediction.wrapping_add(symbol); + + return Ok(true); + } + + /// Like `decode_dc` but we do not need the result of the component, we only want to remove it + /// from the bitstream of the MCU. + fn discard_dc( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable + ) -> Result + where + T: ZByteReaderTrait + { + let mut symbol; + + if self.bits_left < 32 { + self.refill(reader)?; + }; + // look a head HUFF_LOOKAHEAD bits into the bitstream + symbol = self.peek_bits::(); + symbol = dc_table.lookup[symbol as usize]; + + decode_huff!(self, symbol, dc_table); + + if symbol != 0 { + let _ = self.get_bits(symbol as u8); + } + + return Ok(true); + } + + /// Decode a Minimum Code Unit(MCU) as quickly as possible + /// + /// # Arguments + /// - reader: The bitstream from where we read more bits. + /// - dc_table: The Huffman table used to decode the DC coefficient + /// - ac_table: The Huffman table used to decode AC values + /// - block: A memory region where we will write out the decoded values + /// - DC prediction: Last DC value for this component + /// + #[allow( + clippy::many_single_char_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + #[inline(never)] + pub fn decode_mcu_block( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, ac_table: &HuffmanTable, + qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32 + ) -> Result + where + T: ZByteReaderTrait + { + // Get fast AC table as a reference before we enter the hot path + let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); + + let (mut symbol, mut r, mut fast_ac); + // Decode AC coefficients + let mut pos: usize = 1; + if self.bits_left < 1 && self.marker.is_some() { + return Err(DecodeErrors::Format( + "No more bytes left in stream before marker".to_string() + )); + } + // decode DC, dc prediction will contain the value + self.decode_dc(reader, dc_table, dc_prediction)?; + + // set dc to be the dc prediction. + block[0] = *dc_prediction * qt_table[0]; + + while pos < 64 { + self.refill(reader)?; + symbol = self.peek_bits::(); + fast_ac = ac_lookup[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fast_ac != 0 { + // FAST AC path + pos += ((fast_ac >> 4) & 15) as usize; // run + let t_pos = UN_ZIGZAG[min(pos, 63)] & 63; + + block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value + self.drop_bits((fast_ac & 15) as u8); + pos += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + pos += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + let t_pos = UN_ZIGZAG[pos & 63] & 63; + + block[t_pos] = symbol * qt_table[t_pos]; + + pos += 1; + } else if r != 15 { + return Ok(pos as u16); + } else { + pos += 16; + } + } + } + + return Ok(64); + } + + /// Advance the bitstream over a block but ignore the data contained. + /// + /// This updates DC prediction but we never dequantize and we never do any Zig-Zag translation + /// either. Still returns the index of the last component read. + pub fn discard_mcu_block( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, ac_table: &HuffmanTable + ) -> Result + where + T: ZByteReaderTrait + { + // Get fast AC table as a reference before we enter the hot path + let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); + + let (mut symbol, mut r, mut fast_ac); + // Decode AC coefficients + let mut pos: usize = 1; + + // decode DC, dc prediction will contain the value + self.discard_dc(reader, dc_table)?; + + while pos < 64 { + self.refill(reader)?; + symbol = self.peek_bits::(); + fast_ac = ac_lookup[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fast_ac != 0 { + // FAST AC path + pos += ((fast_ac >> 4) & 15) as usize; // run + + self.drop_bits((fast_ac & 15) as u8); + pos += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + pos += r as usize; + // Advance over bits but ignore. + let _ = self.get_bits(symbol as u8); + + pos += 1; + } else if r != 15 { + return Ok(pos as u16); + } else { + pos += 16; + } + } + } + + return Ok(64); + } + + /// Peek `look_ahead` bits ahead without discarding them from the buffer + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + const fn peek_bits(&self) -> i32 { + (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 + } + + /// Discard the next `N` bits without checking + #[inline] + fn drop_bits(&mut self, n: u8) { + // PS: Its a good check, but triggers fuzzer and a lot of false positives + //debug_assert!(self.bits_left >= n); + //self.bits_left -= n; + self.bits_left = self.bits_left.saturating_sub(n); + self.aligned_buffer <<= n; + } + + /// Read `n_bits` from the buffer and discard them + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + fn get_bits(&mut self, n_bits: u8) -> i32 { + let mask = (1_u64 << n_bits) - 1; + + self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits)); + let bits = (self.aligned_buffer & mask) as i32; + self.bits_left = self.bits_left.wrapping_sub(n_bits); + bits + } + + /// Decode a DC block + #[allow(clippy::cast_possible_truncation)] + #[inline] + pub(crate) fn decode_prog_dc_first( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, block: &mut i16, + dc_prediction: &mut i32 + ) -> Result<(), DecodeErrors> + where + T: ZByteReaderTrait + { + self.decode_dc(reader, dc_table, dc_prediction)?; + *block = (*dc_prediction as i16).wrapping_mul(self.successive_low_mask); + return Ok(()); + } + #[inline] + pub(crate) fn decode_prog_dc_refine( + &mut self, reader: &mut ZReader, block: &mut i16 + ) -> Result<(), DecodeErrors> + where + T: ZByteReaderTrait + { + // refinement scan + if self.bits_left < 1 { + self.refill(reader)?; + // if we find a marker, it may happens we don't refill. + // So let's confirm again that refill worked + if self.bits_left < 1 { + return Err(DecodeErrors::Format( + "Marker found where not expected in refine bit".to_string() + )); + } + } + + if self.get_bit() == 1 { + *block = block.wrapping_add(self.successive_low_mask); + } + + Ok(()) + } + + /// Get a single bit from the bitstream + fn get_bit(&mut self) -> u8 { + let k = (self.aligned_buffer >> 63) as u8; + // discard a bit + self.drop_bits(1); + return k; + } + pub(crate) fn decode_mcu_ac_first( + &mut self, reader: &mut ZReader, ac_table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZByteReaderTrait + { + let fast_ac = ac_table.ac_lookup.as_ref().unwrap(); + let bit = self.successive_low_mask; + + let mut k = self.spec_start as usize; + let (mut symbol, mut r, mut fac); + + // EOB runs are handled in mcu_prog.rs + 'block: loop { + self.refill(reader)?; + // Check for marker in the stream + + symbol = self.peek_bits::(); + fac = fast_ac[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fac != 0 { + // fast ac path + k += ((fac >> 4) & 15) as usize; // run + block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(bit); // value + self.drop_bits((fac & 15) as u8); + k += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + k += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(bit); + k += 1; + } else { + if r != 15 { + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + self.eob_run -= 1; + break; + } + + k += 16; + } + } + + if k > self.spec_end as usize { + break 'block; + } + } + return Ok(true); + } + #[allow(clippy::too_many_lines, clippy::op_ref)] + pub(crate) fn decode_mcu_ac_refine( + &mut self, reader: &mut ZReader, table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZByteReaderTrait + { + let bit = self.successive_low_mask; + + let mut k = self.spec_start; + let (mut symbol, mut r); + + if self.eob_run == 0 { + 'no_eob: loop { + // Decode a coefficient from the bit stream + self.refill(reader)?; + + symbol = self.peek_bits::(); + symbol = table.lookup[symbol as usize]; + + decode_huff!(self, symbol, table); + + r = symbol >> 4; + symbol &= 15; + + if symbol == 0 { + if r != 15 { + // EOB run is 2^r + bits + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + // EOB runs are handled by the eob logic + break 'no_eob; + } + } else { + if symbol != 1 { + return Err(DecodeErrors::HuffmanDecode( + "Bad Huffman code, corrupt JPEG?".to_string() + )); + } + // get sign bit + // We assume we have enough bits, which should be correct for sane images + // since we refill by 32 above + if self.get_bit() == 1 { + symbol = i32::from(bit); + } else { + symbol = i32::from(-bit); + } + } + + // Advance over already nonzero coefficients appending + // correction bits to the non-zeroes. + // A correction bit is 1 if the absolute value of the coefficient must be increased + + if k <= self.spec_end { + 'advance_nonzero: loop { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 { + if self.bits_left < 1 { + self.refill(reader)?; + if self.bits_left < 1 && self.marker.is_some() { + return Err(DecodeErrors::Format( + "Marker found where not expected in refine bit".to_string() + )); + } + } + if self.get_bit() == 1 && (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient += bit; + } else { + *coefficient -= bit; + } + } + } else { + r -= 1; + + if r < 0 { + // reached target zero coefficient. + break 'advance_nonzero; + } + }; + + if k == self.spec_end { + break 'advance_nonzero; + } + + k += 1; + } + } + + if symbol != 0 { + let pos = UN_ZIGZAG[k as usize & 63]; + // output new non-zero coefficient. + block[pos & 63] = symbol as i16; + } + + k += 1; + + if k > self.spec_end { + break 'no_eob; + } + } + } + if self.eob_run > 0 { + // only run if block does not consists of purely zeroes + if &block[1..] != &[0; 63] { + self.refill(reader)?; + + while k <= self.spec_end { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 && self.get_bit() == 1 { + // check if we already modified it, if so do nothing, otherwise + // append the correction bit. + if (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient = coefficient.wrapping_add(bit); + } else { + *coefficient = coefficient.wrapping_sub(bit); + } + } + } + if self.bits_left < 1 { + // refill at the last possible moment + self.refill(reader)?; + } + k += 1; + } + } + // count a block completed in EOB run + self.eob_run -= 1; + } + return Ok(true); + } + + pub fn update_progressive_params(&mut self, _ah: u8, al: u8, spec_start: u8, spec_end: u8) { + self.successive_low_mask = 1i16 << al; + self.spec_start = spec_start; + self.spec_end = spec_end; + } + + /// Reset the stream if we have a restart marker + /// + /// Restart markers indicate drop those bits in the stream and zero out + /// everything + #[cold] + pub fn reset(&mut self) { + self.bits_left = 0; + self.marker = None; + self.buffer = 0; + self.aligned_buffer = 0; + self.eob_run = 0; + } +} + +/// Do the equivalent of JPEG HUFF_EXTEND +#[inline(always)] +fn huff_extend(x: i32, s: i32) -> i32 { + // if x> 31) & (((-1) << (s)) + 1)) +} + +const fn has_zero(v: u32) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0; +} + +const fn has_byte(b: u32, val: u8) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + has_zero(b ^ ((!0_u32 / 255) * (val as u32))) +} + +// mod tests { +// use zune_core::bytestream::ZCursor; +// use zune_core::colorspace::ColorSpace; +// use zune_core::options::DecoderOptions; +// +// use crate::JpegDecoder; +// +// #[test] +// fn test_image() { +// let img = "/Users/etemesi/Downloads/test_IDX_45_RAND_168601280367171438891916_minimized_837.jpg"; +// let data = std::fs::read(img).unwrap(); +// let options = DecoderOptions::new_cmd().jpeg_set_out_colorspace(ColorSpace::RGB); +// let mut decoder = JpegDecoder::new_with_options(ZCursor::new(&data[..]), options); +// +// decoder.decode().unwrap(); +// println!("{:?}", decoder.options.jpeg_get_out_colorspace()) +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/avx.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/avx.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/avx.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/avx.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! AVX color conversion routines +//! +//! Okay these codes are cool +//! +//! Herein lies super optimized codes to do color conversions. +//! +//! +//! 1. The YCbCr to RGB use integer approximations and not the floating point equivalent. +//! That means we may be +- 2 of pixels generated by libjpeg-turbo jpeg decoding +//! (also libjpeg uses routines like `Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G`) +//! +//! Firstly, we use integers (fun fact:there is no part of this code base where were dealing with +//! floating points.., fun fact: the first fun fact wasn't even fun.) +//! +//! Secondly ,we have cool clamping code, especially for rgba , where we don't need clamping and we +//! spend our time cursing that Intel decided permute instructions to work like 2 128 bit vectors(the compiler opitmizes +//! it out to something cool). +//! +//! There isn't a lot here (not as fun as bitstream ) but I hope you find what you're looking for. +//! +//! O and ~~subscribe to my youtube channel~~ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#![cfg(feature = "x86")] +#![allow( + clippy::wildcard_imports, + clippy::cast_possible_truncation, + clippy::too_many_arguments, + clippy::inline_always, + clippy::doc_markdown, + dead_code +)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +use crate::color_convert::scalar::{CB_CF, CR_CF, C_G_CB_COEF_2, C_G_CR_COEF_1, YUV_RND, Y_CF}; + +pub union YmmRegister { + // both are 32 when using std::mem::size_of + mm256: __m256i, + // for avx color conversion + array: [i16; 16] +} + +const R_AVX_COEF: i32 = i32::from_ne_bytes([CR_CF.to_ne_bytes()[0], CR_CF.to_ne_bytes()[1], 0, 0]); +const B_AVX_COEF: i32 = i32::from_ne_bytes([0, 0, CB_CF.to_ne_bytes()[0], CB_CF.to_ne_bytes()[1]]); +const G_COEF_AVX_COEF: i32 = i32::from_ne_bytes([ + C_G_CR_COEF_1.to_ne_bytes()[0], + C_G_CR_COEF_1.to_ne_bytes()[1], + C_G_CB_COEF_2.to_ne_bytes()[0], + C_G_CB_COEF_2.to_ne_bytes()[1] +]); + +//-------------------------------------------------------------------------------------------------- +// AVX conversion routines +//-------------------------------------------------------------------------------------------------- + +/// +/// Convert YCBCR to RGB using AVX instructions +/// +/// # Note +///**IT IS THE RESPONSIBILITY OF THE CALLER TO CALL THIS IN CPUS SUPPORTING +/// AVX2 OTHERWISE THIS IS UB** +/// +/// *Peace* +/// +/// This library itself will ensure that it's never called in CPU's not +/// supporting AVX2 +/// +/// # Arguments +/// - `y`,`cb`,`cr`: A reference of 8 i32's +/// - `out`: The output array where we store our converted items +/// - `offset`: The position from 0 where we write these RGB values +#[inline(always)] +pub fn ycbcr_to_rgb_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // call this in another function to tell RUST to vectorize this + // storing + unsafe { + ycbcr_to_rgb_avx2_1(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn ycbcr_to_rgb_avx2_1( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + let (mut r, mut g, mut b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + + r = _mm256_packus_epi16(r, _mm256_setzero_si256()); + g = _mm256_packus_epi16(g, _mm256_setzero_si256()); + b = _mm256_packus_epi16(b, _mm256_setzero_si256()); + + r = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(r); + g = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(g); + b = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(b); + + let sh_r = _mm256_setr_epi8( + 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, + 9, 4, 15, 10, 5 + ); + let sh_g = _mm256_setr_epi8( + 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, + 14, 9, 4, 15, 10 + ); + let sh_b = _mm256_setr_epi8( + 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, + 3, 14, 9, 4, 15 + ); + + let r0 = _mm256_shuffle_epi8(r, sh_r); + let g0 = _mm256_shuffle_epi8(g, sh_g); + let b0 = _mm256_shuffle_epi8(b, sh_b); + + let m0 = _mm256_setr_epi8( + 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + 0, 0, -1, 0, 0 + ); + let m1 = _mm256_setr_epi8( + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + -1, 0, 0, -1, 0 + ); + + let p0 = _mm256_blendv_epi8(_mm256_blendv_epi8(r0, g0, m0), b0, m1); + let p1 = _mm256_blendv_epi8(_mm256_blendv_epi8(g0, b0, m0), r0, m1); + let p2 = _mm256_blendv_epi8(_mm256_blendv_epi8(b0, r0, m0), g0, m1); + + let rgb0 = _mm256_permute2x128_si256::<32>(p0, p1); + let rgb1 = _mm256_permute2x128_si256::<48>(p2, p0); + + _mm256_storeu_si256(out.as_mut_ptr().cast(), rgb0); + _mm_storeu_si128(out[32..].as_mut_ptr().cast(), _mm256_castsi256_si128(rgb1)); + + *offset += 48; +} + +// Enabled avx2 automatically enables avx. +#[inline] +#[target_feature(enable = "avx2")] +/// A baseline implementation of YCbCr to RGB conversion which does not carry +/// out clamping +/// +/// This is used by the `ycbcr_to_rgba_avx` and `ycbcr_to_rgbx` conversion +/// routines +unsafe fn ycbcr_to_rgb_baseline_no_clamp( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (__m256i, __m256i, __m256i) { + // Load values into a register + // + let y_c = _mm256_loadu_si256(y.as_ptr().cast()); + let cb_c = _mm256_loadu_si256(cb.as_ptr().cast()); + let cr_c = _mm256_loadu_si256(cr.as_ptr().cast()); + + // Here we want to use _mm256_madd_epi16 to perform 2 multiplications + // and one addition per instruction. + + // At first, we have to pack i16 U and V that stores u8 into one u8 [U,V] + // then zero extend, and keep in mind that lanes is already been permuted. + + let y_coeff = _mm256_set1_epi32(i32::from(Y_CF)); + let cr_coeff = _mm256_set1_epi32(R_AVX_COEF); + let cb_coeff = _mm256_set1_epi32(B_AVX_COEF); + let cg_coeff = _mm256_set1_epi32(G_COEF_AVX_COEF); + let v_rnd = _mm256_set1_epi32(i32::from(YUV_RND)); + let uv_bias = _mm256_set1_epi16(128); + + // UV in memory because x86/x86_64 is always little endian + let v_0 = _mm256_slli_epi16::<8>(cb_c); + let u_v_8 = _mm256_or_si256(v_0, cr_c); + + let mut u_v_lo = _mm256_unpacklo_epi8(u_v_8, _mm256_setzero_si256()); + let mut u_v_hi = _mm256_unpackhi_epi8(u_v_8, _mm256_setzero_si256()); + + let mut y_lo = _mm256_unpacklo_epi16(y_c, _mm256_setzero_si256()); + let mut y_hi = _mm256_unpackhi_epi16(y_c, _mm256_setzero_si256()); + + u_v_lo = _mm256_sub_epi16(u_v_lo, uv_bias); + u_v_hi = _mm256_sub_epi16(u_v_hi, uv_bias); + + y_lo = _mm256_madd_epi16(y_lo, y_coeff); + y_hi = _mm256_madd_epi16(y_hi, y_coeff); + + let mut r_lo = _mm256_madd_epi16(u_v_lo, cr_coeff); + let mut r_hi = _mm256_madd_epi16(u_v_hi, cr_coeff); + + let mut g_lo = _mm256_madd_epi16(u_v_lo, cg_coeff); + let mut g_hi = _mm256_madd_epi16(u_v_hi, cg_coeff); + + // This ordering is preferred to reduce register file pressure. + + y_lo = _mm256_add_epi32(y_lo, v_rnd); + y_hi = _mm256_add_epi32(y_hi, v_rnd); + + let mut b_lo = _mm256_madd_epi16(u_v_lo, cb_coeff); + let mut b_hi = _mm256_madd_epi16(u_v_hi, cb_coeff); + + r_lo = _mm256_add_epi32(r_lo, y_lo); + r_hi = _mm256_add_epi32(r_hi, y_hi); + + g_lo = _mm256_add_epi32(g_lo, y_lo); + g_hi = _mm256_add_epi32(g_hi, y_hi); + + b_lo = _mm256_add_epi32(b_lo, y_lo); + b_hi = _mm256_add_epi32(b_hi, y_hi); + + r_lo = _mm256_srai_epi32::<14>(r_lo); + r_hi = _mm256_srai_epi32::<14>(r_hi); + + g_lo = _mm256_srai_epi32::<14>(g_lo); + g_hi = _mm256_srai_epi32::<14>(g_hi); + + b_lo = _mm256_srai_epi32::<14>(b_lo); + b_hi = _mm256_srai_epi32::<14>(b_hi); + + let r = _mm256_packus_epi32(r_lo, r_hi); + let g = _mm256_packus_epi32(g_lo, g_hi); + let b = _mm256_packus_epi32(b_lo, b_hi); + + return (r, g, b); +} + +#[inline(always)] +pub fn ycbcr_to_rgba_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + unsafe { + ycbcr_to_rgba_unsafe(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +#[rustfmt::skip] +unsafe fn ycbcr_to_rgba_unsafe( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], + out: &mut [u8], + offset: &mut usize, +) +{ + // check if we have enough space to write. + let tmp:& mut [u8; 64] = out.get_mut(*offset..*offset + 64).expect("Slice to small cannot write").try_into().unwrap(); + + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + + // set alpha channel to 255 for opaque + + // And no these comments were not from me pressing the keyboard + + // Pack the integers into u8's using unsigned saturation. + let c = _mm256_packus_epi16(r, g); //aaaaa_bbbbb_aaaaa_bbbbbb + let d = _mm256_packus_epi16(b, _mm256_set1_epi16(255)); // cccccc_dddddd_ccccccc_ddddd + // transpose_u16 and interleave channels + let e = _mm256_unpacklo_epi8(c, d); //ab_ab_ab_ab_ab_ab_ab_ab + let f = _mm256_unpackhi_epi8(c, d); //cd_cd_cd_cd_cd_cd_cd_cd + // final transpose_u16 + let g = _mm256_unpacklo_epi8(e, f); //abcd_abcd_abcd_abcd_abcd + let h = _mm256_unpackhi_epi8(e, f); + + // undo packus shuffling... + let i = _mm256_permute2x128_si256::<{ shuffle(3, 2, 1, 0) }>(g, h); + + let j = _mm256_permute2x128_si256::<{ shuffle(1, 2, 3, 0) }>(g, h); + + let k = _mm256_permute2x128_si256::<{ shuffle(3, 2, 0, 1) }>(g, h); + + let l = _mm256_permute2x128_si256::<{ shuffle(0, 3, 2, 1) }>(g, h); + + let m = _mm256_blend_epi32::<0b1111_0000>(i, j); + + let n = _mm256_blend_epi32::<0b1111_0000>(k, l); + + // Store + // Use streaming instructions to prevent polluting the cache? + _mm256_storeu_si256(tmp.as_mut_ptr().cast(), m); + + _mm256_storeu_si256(tmp[32..].as_mut_ptr().cast(), n); + + *offset += 64; +} + +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/neon64.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/neon64.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/neon64.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/neon64.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Aarch64 color conversion routines +//! NEON is mandatory on aarch64. + +#![cfg(all(feature = "neon", target_arch = "aarch64"))] +use core::arch::aarch64::*; + +use crate::color_convert::scalar::{CB_CF, CR_CF, C_G_CB_COEF_2, C_G_CR_COEF_1, YUV_RND, Y_CF}; + +const C_1: u64 = u64::from_ne_bytes([ + Y_CF.to_ne_bytes()[0], + Y_CF.to_ne_bytes()[1], + CR_CF.to_ne_bytes()[0], + CR_CF.to_ne_bytes()[1], + CB_CF.to_ne_bytes()[0], + CB_CF.to_ne_bytes()[1], + C_G_CR_COEF_1.to_ne_bytes()[0], + C_G_CR_COEF_1.to_ne_bytes()[1] +]); +const C_2: u64 = u64::from_ne_bytes([ + C_G_CB_COEF_2.to_ne_bytes()[0], + C_G_CB_COEF_2.to_ne_bytes()[1], + 0, + 0, + 0, + 0, + 0, + 0 +]); + +#[inline(always)] +unsafe fn ycbcr_to_rgb_baseline_no_clamp( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (uint8x16_t, uint8x16_t, uint8x16_t) { + // NEON has 32 registers, so it is good idea to utilize a lot of variables at once + + let cb_cr_bias = vdupq_n_s16(128); + // 0 - Y coeff, 1 - Cr, 2 - Cb, 3 - G1, 4 - G2 + let coefficients = vcombine_s16(vcreate_s16(C_1), vcreate_s16(C_2)); + + let y0 = vld1q_s16(y.as_ptr().cast()); + let y1 = vld1q_s16(y[8..].as_ptr().cast()); + + let mut cb0 = vld1q_s16(cb.as_ptr().cast()); + let mut cb1 = vld1q_s16(cb[8..].as_ptr().cast()); + + let mut cr0 = vld1q_s16(cr.as_ptr().cast()); + let mut cr1 = vld1q_s16(cr[8..].as_ptr().cast()); + + cb0 = vsubq_s16(cb0, cb_cr_bias); + cb1 = vsubq_s16(cb1, cb_cr_bias); + + cr0 = vsubq_s16(cr0, cb_cr_bias); + cr1 = vsubq_s16(cr1, cb_cr_bias); + + let bias = vdupq_n_s32(i32::from(YUV_RND)); + + let acc0 = vmlal_laneq_s16::<0>(bias, vget_low_s16(y0), coefficients); + let acc1 = vmlal_high_laneq_s16::<0>(bias, y0, coefficients); + let acc2 = vmlal_laneq_s16::<0>(bias, vget_low_s16(y1), coefficients); + let acc3 = vmlal_high_laneq_s16::<0>(bias, y1, coefficients); + + let r0 = vmlal_laneq_s16::<1>(acc0, vget_low_s16(cr0), coefficients); + let r1 = vmlal_high_laneq_s16::<1>(acc1, cr0, coefficients); + let r2 = vmlal_laneq_s16::<1>(acc2, vget_low_s16(cr1), coefficients); + let r3 = vmlal_high_laneq_s16::<1>(acc3, cr1, coefficients); + + let b0 = vmlal_laneq_s16::<2>(acc0, vget_low_s16(cb0), coefficients); + let b1 = vmlal_high_laneq_s16::<2>(acc1, cb0, coefficients); + let b2 = vmlal_laneq_s16::<2>(acc2, vget_low_s16(cb1), coefficients); + let b3 = vmlal_high_laneq_s16::<2>(acc3, cb1, coefficients); + + // Saturating shift right with signed -> unsigned saturation + let qr0 = vqshrun_n_s32::<14>(r0); + let qr1 = vqshrun_n_s32::<14>(r1); + let qr2 = vqshrun_n_s32::<14>(r2); + let qr3 = vqshrun_n_s32::<14>(r3); + + let mut g0 = vmlal_laneq_s16::<4>(acc0, vget_low_s16(cb0), coefficients); + let mut g1 = vmlal_high_laneq_s16::<4>(acc1, cb0, coefficients); + let mut g2 = vmlal_laneq_s16::<4>(acc2, vget_low_s16(cb1), coefficients); + let mut g3 = vmlal_high_laneq_s16::<4>(acc3, cb1, coefficients); + + let qb0 = vqshrun_n_s32::<14>(b0); + let qb1 = vqshrun_n_s32::<14>(b1); + let qb2 = vqshrun_n_s32::<14>(b2); + let qb3 = vqshrun_n_s32::<14>(b3); + + let r0 = vqmovn_u16(vcombine_u16(qr0, qr1)); + let r1 = vqmovn_u16(vcombine_u16(qr2, qr3)); + + let b0 = vqmovn_u16(vcombine_u16(qb0, qb1)); + let b1 = vqmovn_u16(vcombine_u16(qb2, qb3)); + + g0 = vmlal_laneq_s16::<3>(g0, vget_low_s16(cr0), coefficients); + g1 = vmlal_high_laneq_s16::<3>(g1, cr0, coefficients); + g2 = vmlal_laneq_s16::<3>(g2, vget_low_s16(cr1), coefficients); + g3 = vmlal_high_laneq_s16::<3>(g3, cr1, coefficients); + + let qg0 = vqshrun_n_s32::<14>(g0); + let qg1 = vqshrun_n_s32::<14>(g1); + let qg2 = vqshrun_n_s32::<14>(g2); + let qg3 = vqshrun_n_s32::<14>(g3); + + let g0 = vqmovn_u16(vcombine_u16(qg0, qg1)); + let g1 = vqmovn_u16(vcombine_u16(qg2, qg3)); + + ( + vcombine_u8(r0, r1), + vcombine_u8(g0, g1), + vcombine_u8(b0, b1) + ) +} + +#[inline(always)] +pub fn ycbcr_to_rgb_neon( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // call this in another function to tell RUST to vectorize this + // storing + unsafe { + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + vst3q_u8(out.as_mut_ptr(), uint8x16x3_t(r, g, b)); + *offset += 48; + } +} + +#[inline(always)] +pub fn ycbcr_to_rgba_neon( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + unsafe { + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + vst4q_u8(out.as_mut_ptr(), uint8x16x4_t(r, g, b, vdupq_n_u8(255))); + *offset += 64; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use core::convert::TryInto; + +// Bt.601 Full Range inverse coefficients computed with 14 bits of precision with MPFR. +// This is important to keep them in i16. +// In most cases LLVM will detect what we're doing i16 widening to i32 math and will use +// appropriate optimizations. +pub(crate) const Y_CF: i16 = 16384; +pub(crate) const CR_CF: i16 = 22970; +pub(crate) const CB_CF: i16 = 29032; +pub(crate) const C_G_CR_COEF_1: i16 = -11700; +pub(crate) const C_G_CB_COEF_2: i16 = -5638; +pub(crate) const YUV_PREC: i16 = 14; +// Rounding const for YUV -> RGB conversion: floating equivalent 0.499(9). +pub(crate) const YUV_RND: i16 = (1 << (YUV_PREC - 1)) - 1; + +/// Limit values to 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, dead_code)] +fn clamp(a: i32) -> u8 { + a.clamp(0, 255) as u8 +} + +/// YCbCr to RGBA color conversion + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgba_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 64 elements for Rust to see we won't go out of bounds. + let opt: &mut [u8; 64] = output_position + .get_mut(0..64) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + for ((&y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(4)) + { + let cr = cr - 128; + let cb = cb - 128; + + let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND); + + let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC; + let g = (y0 + + i32::from(cr) * i32::from(C_G_CR_COEF_1) + + i32::from(cb) * i32::from(C_G_CB_COEF_2)) + >> YUV_PREC; + let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC; + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + out[3] = 255; + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + out[3] = 255; + } + } + *pos += 64; +} + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgb_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 48 elements + let opt: &mut [u8; 48] = output_position + .get_mut(0..48) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + + for ((&y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(3)) + { + let cr = cr - 128; + let cb = cb - 128; + + let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND); + + let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC; + let g = (y0 + + i32::from(cr) * i32::from(C_G_CR_COEF_1) + + i32::from(cb) * i32::from(C_G_CB_COEF_2)) + >> YUV_PREC; + let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC; + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + } + } + + // Increment pos + *pos += 48; +} + +pub fn ycbcr_to_grayscale(y: &[i16], width: usize, padded_width: usize, output: &mut [u8]) { + for (y_in, out) in y + .chunks_exact(padded_width) + .zip(output.chunks_exact_mut(width)) + { + for (y, out) in y_in.iter().zip(out.iter_mut()) { + *out = *y as u8; + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/color_convert.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/color_convert.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::many_single_char_names, + clippy::similar_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::too_many_arguments, + clippy::doc_markdown +)] + +//! Color space conversion routines +//! +//! This files exposes functions to convert one colorspace to another in a jpeg +//! image +//! +//! Currently supported conversions are +//! +//! - `YCbCr` to `RGB,RGBA,GRAYSCALE,RGBX`. +//! +//! +//! Hey there, if your reading this it means you probably need something, so let me help you. +//! +//! There are 3 supported cpu extensions here. +//! 1. Scalar +//! 2. SSE +//! 3. AVX +//! +//! There are two types of the color convert functions +//! +//! 1. Acts on 16 pixels. +//! 2. Acts on 8 pixels. +//! +//! The reason for this is because when implementing the AVX part it occurred to me that we can actually +//! do better and process 2 MCU's if we change IDCT return type to be `i16's`, since a lot of +//! CPU's these days support AVX extensions, it becomes nice if we optimize for that path , +//! therefore AVX routines can process 16 pixels directly and SSE and Scalar just compensate. +//! +//! By compensating, I mean I wrote the 16 pixels version operating on the 8 pixel version twice. +//! +//! Therefore if your looking to optimize some routines, probably start there. + +pub use scalar::ycbcr_to_grayscale; +use zune_core::colorspace::ColorSpace; +use zune_core::options::DecoderOptions; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(feature = "x86")] +pub use crate::color_convert::avx::{ycbcr_to_rgb_avx2, ycbcr_to_rgba_avx2}; +use crate::decoder::ColorConvert16Ptr; + +mod avx; +mod neon64; +mod scalar; + +#[allow(unused_variables)] +pub fn choose_ycbcr_to_rgb_convert_func( + type_need: ColorSpace, options: &DecoderOptions +) -> Option { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + use zune_core::log::debug; + if options.use_avx2() { + debug!("Using AVX optimised color conversion functions"); + + // I believe avx2 means sse4 is also available + // match colorspace + match type_need { + ColorSpace::RGB => return Some(ycbcr_to_rgb_avx2), + ColorSpace::RGBA => return Some(ycbcr_to_rgba_avx2), + _ => () // fall through to scalar, which has more types + }; + } + } + #[cfg(all(feature = "neon", target_arch = "aarch64"))] + { + if options.use_neon() { + use crate::color_convert::neon64::{ycbcr_to_rgb_neon, ycbcr_to_rgba_neon}; + match type_need { + ColorSpace::RGB => return Some(ycbcr_to_rgb_neon), + ColorSpace::RGBA => return Some(ycbcr_to_rgba_neon), + _ => () // fall through to scalar, which has more types + }; + } + } + // when there is no x86 or we haven't returned by here, resort to scalar + return match type_need { + ColorSpace::RGB => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + ColorSpace::RGBA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGRA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGR => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + _ => None + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/components.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/components.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/components.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/components.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This module exports a single struct to store information about +//! JPEG image components +//! +//! The data is extracted from a SOF header. + +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::log::trace; + +use crate::alloc::string::ToString; +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::upsampler::upsample_no_op; +const MAX_SAMP_FACTOR: usize = 4; + +/// Represents an up-sampler function, this function will be called to upsample +/// a down-sampled image + +pub type UpSampler = fn( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16] +); + +/// Component Data from start of frame +#[derive(Clone)] +pub(crate) struct Components { + /// The type of component that has the metadata below, can be Y,Cb or Cr + pub component_id: ComponentID, + /// Sub-sampling ratio of this component in the x-plane + pub vertical_sample: usize, + /// Sub-sampling ratio of this component in the y-plane + pub horizontal_sample: usize, + /// DC huffman table position + pub dc_huff_table: usize, + /// AC huffman table position for this element. + pub ac_huff_table: usize, + /// Quantization table number + pub quantization_table_number: u8, + /// Specifies quantization table to use with this component + pub quantization_table: [i32; 64], + /// dc prediction for the component + pub dc_pred: i32, + /// An up-sampling function, can be basic or SSE, depending + /// on the platform + pub up_sampler: UpSampler, + /// How pixels do we need to go to get to the next line? + pub width_stride: usize, + /// Component ID for progressive + pub id: u8, + /// Whether we need to decode this image component. + pub needed: bool, + /// Upsample scanline + pub raw_coeff: Vec, + /// Upsample destination, stores a scanline worth of sub sampled data + pub upsample_dest: Vec, + /// previous row, used to handle MCU boundaries + pub row_up: Vec, + /// current row, used to handle MCU boundaries again + pub row: Vec, + pub first_row_upsample_dest: Vec, + pub idct_pos: usize, + pub x: usize, + pub w2: usize, + pub y: usize, + pub sample_ratio: SampleRatios, + // a very annoying bug + pub fix_an_annoying_bug: usize +} + +impl Components { + /// Create a new instance from three bytes from the start of frame + #[inline] + pub fn from(a: [u8; 3], pos: u8) -> Result { + // it's a unique identifier. + // doesn't have to be ascending + // see tests/inputs/huge_sof_number + // + // For such cases, use the position of the component + // to determine width + + let id = match pos { + 0 => ComponentID::Y, + 1 => ComponentID::Cb, + 2 => ComponentID::Cr, + 3 => ComponentID::Q, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown component id found,{pos}, expected value between 1 and 4" + ))) + } + }; + + let horizontal_sample = (a[1] >> 4) as usize; + let vertical_sample = (a[1] & 0x0f) as usize; + // Match libjpeg turbo on checking for sampling factors + // Reject anything above 4 + if horizontal_sample > MAX_SAMP_FACTOR { + return Err(DecodeErrors::Format(format!( + "Bogus Horizontal Sampling Factor {horizontal_sample}" + ))); + } + if vertical_sample > MAX_SAMP_FACTOR { + return Err(DecodeErrors::Format(format!( + "Bogus Vertical Sampling Factor {vertical_sample}" + ))); + } + + let quantization_table_number = a[2]; + // confirm quantization number is between 0 and MAX_COMPONENTS + if usize::from(quantization_table_number) >= MAX_COMPONENTS { + return Err(DecodeErrors::Format(format!( + "Too large quantization number :{quantization_table_number}, expected value between 0 and {MAX_COMPONENTS}" + ))); + } + // check that upsampling ratios are powers of two + // if these fail, it's probably a corrupt image. + if !horizontal_sample.is_power_of_two() { + return Err(DecodeErrors::Format(format!( + "Horizontal sample is not a power of two({horizontal_sample}) cannot decode" + ))); + } + + // if !vertical_sample.is_power_of_two() { + // return Err(DecodeErrors::Format(format!( + // "Vertical sub-sample is not power of two({vertical_sample}) cannot decode" + // ))); + // } + if vertical_sample == 0 { + // Check for invalid vertical sample + return Err(DecodeErrors::Format("Vertical sample is zero".to_string())); + } + trace!( + "Component ID:{:?} \tHS:{} VS:{} QT:{}", + id, + horizontal_sample, + vertical_sample, + quantization_table_number + ); + + Ok(Components { + component_id: id, + vertical_sample, + horizontal_sample, + quantization_table_number, + first_row_upsample_dest: vec![], + // These two will be set with sof marker + dc_huff_table: 0, + ac_huff_table: 0, + quantization_table: [0; 64], + dc_pred: 0, + up_sampler: upsample_no_op, + // set later + width_stride: horizontal_sample, + id: a[0], + needed: true, + raw_coeff: vec![], + upsample_dest: vec![], + row_up: vec![], + row: vec![], + idct_pos: 0, + x: 0, + y: 0, + w2: 0, + sample_ratio: SampleRatios::None, + fix_an_annoying_bug: 1 + }) + } + /// Setup space for upsampling + /// + /// During upsample, we need a reference of the last row so that upsampling can + /// proceed correctly, + /// so we store the last line of every scanline and use it for the next upsampling procedure + /// to store this, but since we don't need it for 1v1 upsampling, + /// we only call this for routines that need upsampling + /// + /// # Requirements + /// - width stride of this element is set for the component. + pub fn setup_upsample_scanline(&mut self) { + self.row = vec![0; self.width_stride * self.vertical_sample]; + self.row_up = vec![0; self.width_stride * self.vertical_sample]; + self.first_row_upsample_dest = + vec![128; self.vertical_sample * self.width_stride * self.sample_ratio.sample()]; + self.upsample_dest = + vec![0; self.width_stride * self.sample_ratio.sample() * self.fix_an_annoying_bug * 8]; + } +} + +/// Component ID's +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum ComponentID { + /// Luminance channel + Y, + /// Blue chrominance + Cb, + /// Red chrominance + Cr, + /// Q or fourth component + Q +} + +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum SampleRatios { + HV, + V, + H, + Generic(usize, usize), + None +} + +impl SampleRatios { + pub fn sample(self) -> usize { + match self { + SampleRatios::HV => 4, + SampleRatios::V | SampleRatios::H => 2, + SampleRatios::Generic(a, b) => a * b, + SampleRatios::None => 1 + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1007 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Main image logic. +#![allow(clippy::doc_markdown)] + +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{error, trace, warn}; +use zune_core::options::DecoderOptions; + +use crate::color_convert::choose_ycbcr_to_rgb_convert_func; +use crate::components::{Components, SampleRatios}; +use crate::errors::{DecodeErrors, UnsupportedSchemes}; +use crate::headers::{ + parse_app1, parse_app13, parse_app14, parse_app2, parse_dqt, parse_huffman, parse_sos, + parse_start_of_frame +}; +use crate::huffman::HuffmanTable; +use crate::idct::{choose_idct_func, choose_idct_1x1_func, choose_idct_4x4_func}; +use crate::marker::Marker; +use crate::misc::SOFMarkers; +use crate::upsampler::{ + choose_horizontal_samp_function, choose_hv_samp_function, choose_v_samp_function, + generic_sampler, upsample_no_op +}; + +/// Maximum components +pub(crate) const MAX_COMPONENTS: usize = 4; + +/// Maximum image dimensions supported. +pub(crate) const MAX_DIMENSIONS: usize = 1 << 27; + +/// Color conversion function that can convert YCbCr colorspace to RGB(A/X) for +/// 16 values +/// +/// The following are guarantees to the following functions +/// +/// 1. The `&[i16]` slices passed contain 16 items +/// +/// 2. The slices passed are in the following order +/// `y,cb,cr` +/// +/// 3. `&mut [u8]` is zero initialized +/// +/// 4. `&mut usize` points to the position in the array where new values should +/// be used +/// +/// The pointer should +/// 1. Carry out color conversion +/// 2. Update `&mut usize` with the new position + +pub type ColorConvert16Ptr = fn(&[i16; 16], &[i16; 16], &[i16; 16], &mut [u8], &mut usize); + +/// IDCT function prototype +/// +/// This encapsulates a dequantize and IDCT function which will carry out the +/// following functions +/// +/// Multiply each 64 element block of `&mut [i16]` with `&Aligned32<[i32;64]>` +/// Carry out IDCT (type 3 dct) on ach block of 64 i16's +pub type IDCTPtr = fn(&mut [i32; 64], &mut [i16], usize); + +/// An encapsulation of an ICC chunk +pub(crate) struct ICCChunk { + pub(crate) seq_no: u8, + pub(crate) num_markers: u8, + pub(crate) data: Vec +} + +/// A JPEG Decoder Instance. +#[allow(clippy::upper_case_acronyms, clippy::struct_excessive_bools)] +pub struct JpegDecoder { + /// Struct to hold image information from SOI + pub(crate) info: ImageInfo, + /// Quantization tables, will be set to none and the tables will + /// be moved to `components` field + pub(crate) qt_tables: [Option<[i32; 64]>; MAX_COMPONENTS], + /// DC Huffman Tables with a maximum of 4 tables for each component + pub(crate) dc_huffman_tables: [Option; MAX_COMPONENTS], + /// AC Huffman Tables with a maximum of 4 tables for each component + pub(crate) ac_huffman_tables: [Option; MAX_COMPONENTS], + /// Image components, holds information like DC prediction and quantization + /// tables of a component + pub(crate) components: Vec, + /// maximum horizontal component of all channels in the image + pub(crate) h_max: usize, + // maximum vertical component of all channels in the image + pub(crate) v_max: usize, + /// mcu's width (interleaved scans) + pub(crate) mcu_width: usize, + /// MCU height(interleaved scans + pub(crate) mcu_height: usize, + /// Number of MCU's in the x plane + pub(crate) mcu_x: usize, + /// Number of MCU's in the y plane + pub(crate) mcu_y: usize, + /// Is the image interleaved? + pub(crate) is_interleaved: bool, + pub(crate) sub_sample_ratio: SampleRatios, + /// Image input colorspace, should be YCbCr for a sane image, might be + /// grayscale too + pub(crate) input_colorspace: ColorSpace, + // Progressive image details + /// Is the image progressive? + pub(crate) is_progressive: bool, + + /// Start of spectral scan + pub(crate) spec_start: u8, + /// End of spectral scan + pub(crate) spec_end: u8, + /// Successive approximation bit position high + pub(crate) succ_high: u8, + /// Successive approximation bit position low + pub(crate) succ_low: u8, + /// Number of components. + pub(crate) num_scans: u8, + /// For a scan, check if any component has vertical/horizontal sampling. + pub(crate) scan_subsampled: bool, + // Function pointers, for pointy stuff. + /// Dequantize and idct function + // This is determined at runtime which function to run, statically it's + // initialized to a platform independent one and during initialization + // of this struct, we check if we can switch to a faster one which + // depend on certain CPU extensions. + pub(crate) idct_func: IDCTPtr, + /// Specialized IDCT when we can guarantee only few coefficients are non-zero. + /// + /// **The callee must uphold a contract**. See [`choose_idct_4x4_func`]. + pub(crate) idct_4x4_func: IDCTPtr, + pub(crate) idct_1x1_func: IDCTPtr, + // Color convert function which acts on 16 YCbCr values + pub(crate) color_convert_16: ColorConvert16Ptr, + pub(crate) z_order: [usize; MAX_COMPONENTS], + /// restart markers + pub(crate) restart_interval: usize, + pub(crate) todo: usize, + // decoder options + pub(crate) options: DecoderOptions, + // byte-stream + pub(crate) stream: ZReader, + // Indicate whether headers have been decoded + pub(crate) headers_decoded: bool, + pub(crate) seen_sof: bool, + + // exif data, lifted from app2 + pub(crate) icc_data: Vec, + pub(crate) is_mjpeg: bool, + pub(crate) coeff: usize // Solves some weird bug :) +} + +impl JpegDecoder +where + T: ZByteReaderTrait +{ + #[allow(clippy::redundant_field_names)] + fn default(options: DecoderOptions, buffer: T) -> Self { + let color_convert = choose_ycbcr_to_rgb_convert_func(ColorSpace::RGB, &options).unwrap(); + JpegDecoder { + info: ImageInfo::default(), + qt_tables: [None, None, None, None], + dc_huffman_tables: [None, None, None, None], + ac_huffman_tables: [None, None, None, None], + components: vec![], + // Interleaved information + h_max: 1, + v_max: 1, + mcu_height: 0, + mcu_width: 0, + mcu_x: 0, + mcu_y: 0, + is_interleaved: false, + sub_sample_ratio: SampleRatios::None, + is_progressive: false, + spec_start: 0, + spec_end: 0, + succ_high: 0, + succ_low: 0, + num_scans: 0, + scan_subsampled: false, + idct_func: choose_idct_func(&options), + idct_4x4_func: choose_idct_4x4_func(&options), + idct_1x1_func: choose_idct_1x1_func(&options), + color_convert_16: color_convert, + input_colorspace: ColorSpace::YCbCr, + z_order: [0; MAX_COMPONENTS], + restart_interval: 0, + todo: 0x7fff_ffff, + options: options, + stream: ZReader::new(buffer), + headers_decoded: false, + seen_sof: false, + icc_data: vec![], + is_mjpeg: false, + coeff: 1 + } + } + /// Decode a buffer already in memory + /// + /// The buffer should be a valid jpeg file, perhaps created by the command + /// `std:::fs::read()` or a JPEG file downloaded from the internet. + /// + /// # Errors + /// See DecodeErrors for an explanation + pub fn decode(&mut self) -> Result, DecodeErrors> { + self.decode_headers()?; + let size = self.output_buffer_size().unwrap(); + let mut out = vec![0; size]; + self.decode_into(&mut out)?; + Ok(out) + } + + /// Create a new Decoder instance + /// + /// # Arguments + /// - `stream`: The raw bytes of a jpeg file. + #[must_use] + #[allow(clippy::new_without_default)] + pub fn new(stream: T) -> JpegDecoder { + JpegDecoder::default(DecoderOptions::default(), stream) + } + + /// Returns the image information + /// + /// This **must** be called after a subsequent call to [`decode`] or [`decode_headers`] + /// it will return `None` + /// + /// # Returns + /// - `Some(info)`: Image information,width, height, number of components + /// - None: Indicates image headers haven't been decoded + /// + /// [`decode`]: JpegDecoder::decode + /// [`decode_headers`]: JpegDecoder::decode_headers + #[must_use] + pub fn info(&self) -> Option { + // we check for fails to that call by comparing what we have to the default, if + // it's default we assume that the caller failed to uphold the + // guarantees. We can be sure that an image cannot be the default since + // its a hard panic in-case width or height are set to zero. + if !self.headers_decoded { + return None; + } + + return Some(self.info.clone()); + } + + /// Return the number of bytes required to hold a decoded image frame + /// decoded using the given input transformations + /// + /// # Returns + /// - `Some(usize)`: Minimum size for a buffer needed to decode the image + /// - `None`: Indicates the image was not decoded, or image dimensions would overflow a usize + /// + #[must_use] + pub fn output_buffer_size(&self) -> Option { + return if self.headers_decoded { + Some( + usize::from(self.width()) + .checked_mul(usize::from(self.height()))? + .checked_mul(self.options.jpeg_get_out_colorspace().num_components())? + ) + } else { + None + }; + } + + /// Get an immutable reference to the decoder options + /// for the decoder instance + /// + /// This can be used to modify options before actual decoding + /// but after initial creation + /// + /// # Example + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// + /// let mut decoder = JpegDecoder::new(ZCursor::new(&[])); + /// // get current options + /// let mut options = decoder.options(); + /// // modify it + /// let new_options = options.set_max_width(10); + /// // set it back + /// decoder.set_options(new_options); + /// + /// ``` + #[must_use] + pub const fn options(&self) -> &DecoderOptions { + &self.options + } + /// Return the input colorspace of the image + /// + /// This indicates the colorspace that is present in + /// the image, but this may be different to the colorspace that + /// the output will be transformed to + /// + /// # Returns + /// -`Some(Colorspace)`: Input colorspace + /// - None : Indicates the headers weren't decoded + #[must_use] + pub fn input_colorspace(&self) -> Option { + return if self.headers_decoded { Some(self.input_colorspace) } else { None }; + } + /// Set decoder options + /// + /// This can be used to set new options even after initialization + /// but before decoding. + /// + /// This does not bear any significance after decoding an image + /// + /// # Arguments + /// - `options`: New decoder options + /// + /// # Example + /// Set maximum jpeg progressive passes to be 4 + /// + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// let mut decoder =JpegDecoder::new(ZCursor::new(&[])); + /// // this works also because DecoderOptions implements `Copy` + /// let options = decoder.options().jpeg_set_max_scans(4); + /// // set the new options + /// decoder.set_options(options); + /// // now decode + /// decoder.decode().unwrap(); + /// ``` + pub fn set_options(&mut self, options: DecoderOptions) { + self.options = options; + } + /// Decode Decoder headers + /// + /// This routine takes care of parsing supported headers from a Decoder + /// image + /// + /// # Supported Headers + /// - APP(0) + /// - SOF(O) + /// - DQT -> Quantization tables + /// - DHT -> Huffman tables + /// - SOS -> Start of Scan + /// # Unsupported Headers + /// - SOF(n) -> Decoder images which are not baseline/progressive + /// - DAC -> Images using Arithmetic tables + /// - JPG(n) + fn decode_headers_internal(&mut self) -> Result<(), DecodeErrors> { + if self.headers_decoded { + trace!("Headers decoded!"); + return Ok(()); + } + + // match output colorspace here + // we know this will only be called once per image + // so makes sense + // We only care for ycbcr to rgb/rgba here + // in case one is using another colorspace. + // May god help you + let out_colorspace = self.options.jpeg_get_out_colorspace(); + + if matches!( + out_colorspace, + ColorSpace::BGR | ColorSpace::BGRA | ColorSpace::RGB | ColorSpace::RGBA + ) { + self.color_convert_16 = choose_ycbcr_to_rgb_convert_func( + self.options.jpeg_get_out_colorspace(), + &self.options + ) + .unwrap(); + } + // First two bytes should be jpeg soi marker + let magic_bytes = self.stream.get_u16_be_err()?; + + let mut last_byte = 0; + let mut bytes_before_marker = 0; + + if magic_bytes != 0xffd8 { + return Err(DecodeErrors::IllegalMagicBytes(magic_bytes)); + } + + loop { + // read a byte + let mut m = self.stream.read_u8_err()?; + + // AND OF COURSE some images will have fill bytes in their marker + // bitstreams because why not. + // + // I am disappointed as a man. + if (m == 0xFF || m == 0) && last_byte == 0xFF { + // This handles the edge case where + // images have markers with fill bytes(0xFF) + // or byte stuffing (0) + // I.e 0xFF 0xFF 0xDA + // and + // 0xFF 0 0xDA + // It should ignore those fill bytes and take 0xDA + // I don't know why such images exist + // but they do. + // so this is for you (with love) + while m == 0xFF || m == 0x0 { + last_byte = m; + m = self.stream.read_u8_err()?; + } + } + // Last byte should be 0xFF to confirm existence of a marker since markers look + // like OxFF(some marker data) + if last_byte == 0xFF { + let marker = Marker::from_u8(m); + if let Some(n) = marker { + if bytes_before_marker > 3 { + if self.options.strict_mode() + /*No reason to use this*/ + { + return Err(DecodeErrors::FormatStatic( + "[strict-mode]: Extra bytes between headers" + )); + } + + error!( + "Extra bytes {} before marker 0xFF{:X}", + bytes_before_marker - 3, + m + ); + } + + bytes_before_marker = 0; + + self.parse_marker_inner(n)?; + + // break after reading the start of scan. + // what follows is the image data + if n == Marker::SOS { + self.headers_decoded = true; + trace!("Input colorspace {:?}", self.input_colorspace); + + // Check if image is RGB + // The check is weird, we need to check if ID + // represents R, G and B in ascii, + // + // I am not sure if this is even specified in any standard, + // but jpegli https://github.com/google/jpegli does encode + // its images that way, so this will check for that. and handle it appropriately + // It is spefified here so that on a successful header decode,we can at least + // try to attribute image colorspace correctly. + // + // It was first the issue in https://github.com/etemesi254/zune-image/issues/291 + // that brought it to light + // + let mut is_rgb = self.components.len() == 3; + let chars = ['R', 'G', 'B']; + for (comp, single_char) in self.components.iter().zip(chars.iter()) { + is_rgb &= comp.id == (*single_char) as u8 + } + // Image is RGB, change colorspace + if is_rgb { + self.input_colorspace = ColorSpace::RGB; + } + + return Ok(()); + } + } else { + bytes_before_marker = 0; + + warn!("Marker 0xFF{:X} not known", m); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length : {length}" + ))); + } + + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize)?; + } + } + last_byte = m; + bytes_before_marker += 1; + } + // Check if image is RGB + } + #[allow(clippy::too_many_lines)] + pub(crate) fn parse_marker_inner(&mut self, m: Marker) -> Result<(), DecodeErrors> { + match m { + Marker::SOF(0..=2) => { + let marker = { + // choose marker + if m == Marker::SOF(0) || m == Marker::SOF(1) { + SOFMarkers::BaselineDct + } else { + self.is_progressive = true; + SOFMarkers::ProgressiveDctHuffman + } + }; + + trace!("Image encoding scheme =`{:?}`", marker); + // get components + parse_start_of_frame(marker, self)?; + } + // Start of Frame Segments not supported + Marker::SOF(v) => { + let feature = UnsupportedSchemes::from_int(v); + + if let Some(feature) = feature { + return Err(DecodeErrors::Unsupported(feature)); + } + + return Err(DecodeErrors::Format("Unsupported image format".to_string())); + } + //APP(0) segment + Marker::APP(0) => { + let mut length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + // skip for now + if length > 5 { + let mut buffer = [0u8; 5]; + self.stream.read_exact_bytes(&mut buffer)?; + if &buffer == b"AVI1\0" { + self.is_mjpeg = true; + } + length -= 5; + } + + self.stream.skip(length.saturating_sub(2) as usize)?; + + //parse_app(buf, m, &mut self.info)?; + } + Marker::APP(1) => { + parse_app1(self)?; + } + + Marker::APP(2) => { + parse_app2(self)?; + } + // Quantization tables + Marker::DQT => { + parse_dqt(self)?; + } + // Huffman tables + Marker::DHT => { + parse_huffman(self)?; + } + // Start of Scan Data + Marker::SOS => { + parse_sos(self)?; + } + Marker::EOI => return Err(DecodeErrors::FormatStatic("Premature End of image")), + + Marker::DAC | Marker::DNL => { + return Err(DecodeErrors::Format(format!( + "Parsing of the following header `{m:?}` is not supported,\ + cannot continue" + ))); + } + Marker::DRI => { + if self.stream.get_u16_be_err()? != 4 { + return Err(DecodeErrors::Format( + "Bad DRI length, Corrupt JPEG".to_string() + )); + } + + self.restart_interval = usize::from(self.stream.get_u16_be_err()?); + trace!("DRI marker present ({})", self.restart_interval); + + self.todo = self.restart_interval; + } + Marker::APP(14) => { + parse_app14(self)?; + } + Marker::APP(13) => { + parse_app13(self)?; + } + _ => { + warn!( + "Capabilities for processing marker \"{:?}\" not implemented", + m + ); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize)?; + } + } + Ok(()) + } + /// Get the embedded ICC profile if it exists + /// and is correct + /// + /// One needs not to decode the whole image to extract this, + /// calling [`decode_headers`] for an image with an ICC profile + /// allows you to decode this + /// + /// # Returns + /// - `Some(Vec)`: The raw ICC profile of the image + /// - `None`: May indicate an error in the ICC profile , non-existence of + /// an ICC profile, or that the headers weren't decoded. + /// + /// [`decode_headers`]:Self::decode_headers + #[must_use] + pub fn icc_profile(&self) -> Option> { + let mut marker_present: [Option<&ICCChunk>; 256] = [None; 256]; + + if !self.headers_decoded { + return None; + } + let num_markers = self.icc_data.len(); + + if num_markers == 0 || num_markers >= 255 { + return None; + } + // check validity + for chunk in &self.icc_data { + if usize::from(chunk.num_markers) != num_markers { + // all the lengths must match + return None; + } + if chunk.seq_no == 0 { + warn!("Zero sequence number in ICC, corrupt ICC chunk"); + return None; + } + if marker_present[usize::from(chunk.seq_no)].is_some() { + // duplicate seq_no + warn!("Duplicate sequence number in ICC, corrupt chunk"); + return None; + } + + marker_present[usize::from(chunk.seq_no)] = Some(chunk); + } + let mut data = Vec::with_capacity(1000); + // assemble the data now + for chunk in marker_present.get(1..=num_markers).unwrap() { + if let Some(ch) = chunk { + data.extend_from_slice(&ch.data); + } else { + warn!("Missing icc sequence number, corrupt ICC chunk "); + return None; + } + } + + Some(data) + } + /// Return the exif data for the file + /// + /// This returns the raw exif data starting at the + /// TIFF header + /// + /// # Returns + /// -`Some(data)`: The raw exif data, if present in the image + /// - None: May indicate the following + /// + /// 1. The image doesn't have exif data + /// 2. The image headers haven't been decoded + #[must_use] + pub fn exif(&self) -> Option<&Vec> { + return self.info.exif_data.as_ref(); + } + /// Return the XMP data for the file + /// + /// This returns raw XMP data starting at the XML header + /// One needs an XML/XMP decoder to extract valuable metadata + /// + /// + /// # Returns + /// - `Some(data)`: Raw xmp data + /// - `None`: May indicate the following + /// 1. The image does not have xmp data + /// 2. The image headers have not been decoded + /// + /// # Example + /// + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// let mut decoder = JpegDecoder::new(ZCursor::new(&[])); + /// // decode headers to extract xmp metadata if present + /// decoder.decode_headers().unwrap(); + /// if let Some(data) = decoder.xmp(){ + /// let stringified = String::from_utf8_lossy(data); + /// println!("XMP") + /// } else{ + /// println!("No XMP Found") + /// } + /// + /// ``` + pub fn xmp(&self) -> Option<&Vec> { + return self.info.xmp_data.as_ref(); + } + /// Return the IPTC data for the file + /// + /// This returns the raw IPTC data. + /// + /// # Returns + /// -`Some(data)`: The raw IPTC data, if present in the image + /// - None: May indicate the following + /// + /// 1. The image doesn't have IPTC data + /// 2. The image headers haven't been decoded + #[must_use] + pub fn iptc(&self) -> Option<&Vec> { + return self.info.iptc_data.as_ref(); + } + /// Get the output colorspace the image pixels will be decoded into + /// + /// + /// # Note. + /// This field can only be regarded after decoding headers, + /// as markers such as Adobe APP14 may dictate different colorspaces + /// than requested. + /// + /// Calling `decode_headers` is sufficient to know what colorspace the + /// output is, if this is called after `decode` it indicates the colorspace + /// the output is currently in + /// + /// Additionally not all input->output colorspace mappings are supported + /// but all input colorspaces can map to RGB colorspace, so that's a safe bet + /// if one is handling image formats + /// + ///# Returns + /// - `Some(Colorspace)`: If headers have been decoded, the colorspace the + ///output array will be in + ///- `None + #[must_use] + pub fn output_colorspace(&self) -> Option { + return if self.headers_decoded { + Some(self.options.jpeg_get_out_colorspace()) + } else { + None + }; + } + + /// Decode into a pre-allocated buffer + /// + /// It is an error if the buffer size is smaller than + /// [`output_buffer_size()`](Self::output_buffer_size) + /// + /// If the buffer is bigger than expected, we ignore the end padding bytes + /// + /// # Example + /// + /// - Read headers and then alloc a buffer big enough to hold the image + /// + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// let mut decoder = JpegDecoder::new(ZCursor::new(&[])); + /// // before we get output, we must decode the headers to get width + /// // height, and input colorspace + /// decoder.decode_headers().unwrap(); + /// + /// let mut out = vec![0;decoder.output_buffer_size().unwrap()]; + /// // write into out + /// decoder.decode_into(&mut out).unwrap(); + /// ``` + /// + /// + pub fn decode_into(&mut self, out: &mut [u8]) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + + let expected_size = self.output_buffer_size().unwrap(); + + if out.len() < expected_size { + // too small of a size + return Err(DecodeErrors::TooSmallOutput(expected_size, out.len())); + } + + // ensure we don't touch anyone else's scratch space + let out_len = core::cmp::min(out.len(), expected_size); + let out = &mut out[0..out_len]; + + if self.is_progressive { + self.decode_mcu_ycbcr_progressive(out) + } else { + self.decode_mcu_ycbcr_baseline(out) + } + } + + /// Read only headers from a jpeg image buffer + /// + /// This allows you to extract important information like + /// image width and height without decoding the full image + /// + /// # Examples + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::{JpegDecoder}; + /// + /// let img_data = std::fs::read("a_valid.jpeg").unwrap(); + /// let mut decoder = JpegDecoder::new(ZCursor::new(&img_data)); + /// decoder.decode_headers().unwrap(); + /// + /// println!("Total decoder dimensions are : {:?} pixels",decoder.dimensions()); + /// println!("Number of components in the image are {}", decoder.info().unwrap().components); + /// ``` + /// # Errors + /// See DecodeErrors enum for list of possible errors during decoding + pub fn decode_headers(&mut self) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + Ok(()) + } + /// Create a new decoder with the specified options to be used for decoding + /// an image + /// + /// # Arguments + /// - `buf`: The input buffer from where we will pull in compressed jpeg bytes from + /// - `options`: Options specific to this decoder instance + #[must_use] + pub fn new_with_options(buf: T, options: DecoderOptions) -> JpegDecoder { + JpegDecoder::default(options, buf) + } + + /// Set up-sampling routines in case an image is down sampled + pub(crate) fn set_upsampling(&mut self) -> Result<(), DecodeErrors> { + // no sampling, return early + // check if horizontal max ==1 + if self.h_max == self.v_max && self.h_max == 1 { + return Ok(()); + } + match (self.h_max, self.v_max) { + (1, 1) => { + self.sub_sample_ratio = SampleRatios::None; + } + (1, 2) => { + self.sub_sample_ratio = SampleRatios::V; + } + (2, 1) => { + self.sub_sample_ratio = SampleRatios::H; + } + (2, 2) => { + self.sub_sample_ratio = SampleRatios::HV; + } + (hs, vs) => { + self.sub_sample_ratio = SampleRatios::Generic(hs, vs) + // return Err(DecodeErrors::Format(format!( + // "Unknown down-sampling method ({hs},{vs}), cannot continue") + // )) + } + } + + for comp in &mut self.components { + let hs = self.h_max / comp.horizontal_sample; + let vs = self.v_max / comp.vertical_sample; + + let samp_factor = match (hs, vs) { + (1, 1) => { + comp.sample_ratio = SampleRatios::None; + upsample_no_op + } + (2, 1) => { + comp.sample_ratio = SampleRatios::H; + choose_horizontal_samp_function(&self.options) + } + (1, 2) => { + comp.sample_ratio = SampleRatios::V; + choose_v_samp_function(&self.options) + } + (2, 2) => { + comp.sample_ratio = SampleRatios::HV; + choose_hv_samp_function(&self.options) + } + (hs, vs) => { + comp.sample_ratio = SampleRatios::Generic(hs, vs); + generic_sampler() + } + }; + comp.setup_upsample_scanline(); + comp.up_sampler = samp_factor; + } + + return Ok(()); + } + #[must_use] + /// Get the width of the image as a u16 + /// + /// The width lies between 1 and 65535 + pub(crate) fn width(&self) -> u16 { + self.info.width + } + + /// Get the height of the image as a u16 + /// + /// The height lies between 1 and 65535 + #[must_use] + pub(crate) fn height(&self) -> u16 { + self.info.height + } + + /// Get image dimensions as a tuple of width and height + /// or `None` if the image hasn't been decoded. + /// + /// # Returns + /// - `Some(width,height)`: Image dimensions + /// - None : The image headers haven't been decoded + #[must_use] + pub const fn dimensions(&self) -> Option<(usize, usize)> { + return if self.headers_decoded { + Some((self.info.width as usize, self.info.height as usize)) + } else { + None + }; + } +} + +#[derive(Default, Clone, Eq, PartialEq, Debug)] +pub struct GainMapInfo { + pub data: Vec +} +/// A struct representing Image Information +#[derive(Default, Clone, Eq, PartialEq)] +#[allow(clippy::module_name_repetitions)] +pub struct ImageInfo { + /// Width of the image + pub width: u16, + /// Height of image + pub height: u16, + /// PixelDensity + pub pixel_density: u8, + /// Start of frame markers + pub sof: SOFMarkers, + /// Horizontal sample + pub x_density: u16, + /// Vertical sample + pub y_density: u16, + /// Number of components + pub components: u8, + /// Gain Map information, useful for + /// UHDR images + pub gain_map_info: Vec, + /// Multi picture information, useful for + /// UHDR images + pub multi_picture_information: Option>, + /// Exif Data + pub exif_data: Option>, + /// XMP Data + pub xmp_data: Option>, + /// IPTC Data + pub iptc_data: Option> +} + +impl ImageInfo { + /// Set width of the image + /// + /// Found in the start of frame + + pub(crate) fn set_width(&mut self, width: u16) { + self.width = width; + } + + /// Set height of the image + /// + /// Found in the start of frame + + pub(crate) fn set_height(&mut self, height: u16) { + self.height = height; + } + + /// Set the image density + /// + /// Found in the start of frame + + pub(crate) fn set_density(&mut self, density: u8) { + self.pixel_density = density; + } + + /// Set image Start of frame marker + /// + /// found in the Start of frame header + + pub(crate) fn set_sof_marker(&mut self, marker: SOFMarkers) { + self.sof = marker; + } + + /// Set image x-density(dots per pixel) + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_x(&mut self, sample: u16) { + self.x_density = sample; + } + + /// Set image y-density + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_y(&mut self, sample: u16) { + self.y_density = sample; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/errors.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/errors.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/errors.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/errors.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Contains most common errors that may be encountered in decoding a Decoder +//! image + +use alloc::string::String; +use core::fmt::{Debug, Display, Formatter}; + +use zune_core::bytestream::ZByteIoError; + +use crate::misc::{ + START_OF_FRAME_EXT_AR, START_OF_FRAME_EXT_SEQ, START_OF_FRAME_LOS_SEQ, + START_OF_FRAME_LOS_SEQ_AR, START_OF_FRAME_PROG_DCT_AR +}; + +/// Common Decode errors +#[allow(clippy::module_name_repetitions)] +pub enum DecodeErrors { + /// Any other thing we do not know + Format(String), + /// Any other thing we do not know but we + /// don't need to allocate space on the heap + FormatStatic(&'static str), + /// Illegal Magic Bytes + IllegalMagicBytes(u16), + /// problems with the Huffman Tables in a Decoder file + HuffmanDecode(String), + /// Image has zero width + ZeroError, + /// Discrete Quantization Tables error + DqtError(String), + /// Start of scan errors + SosError(String), + /// Start of frame errors + SofError(String), + /// UnsupportedImages + Unsupported(UnsupportedSchemes), + /// MCU errors + MCUError(String), + /// Exhausted data + ExhaustedData, + /// Large image dimensions(Corrupted data)? + LargeDimensions(usize), + /// Too small output for size + TooSmallOutput(usize, usize), + + IoErrors(ZByteIoError) +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeErrors {} + +impl From<&'static str> for DecodeErrors { + fn from(data: &'static str) -> Self { + return Self::FormatStatic(data); + } +} + +impl From for DecodeErrors { + fn from(data: ZByteIoError) -> Self { + return Self::IoErrors(data); + } +} +impl Debug for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self + { + Self::Format(ref a) => write!(f, "{a:?}"), + Self::FormatStatic(a) => write!(f, "{:?}", &a), + + Self::HuffmanDecode(ref reason) => + { + write!(f, "Error decoding huffman values: {reason}") + } + Self::ZeroError => write!(f, "Image width or height is set to zero, cannot continue"), + Self::DqtError(ref reason) => write!(f, "Error parsing DQT segment. Reason:{reason}"), + Self::SosError(ref reason) => write!(f, "Error parsing SOS Segment. Reason:{reason}"), + Self::SofError(ref reason) => write!(f, "Error parsing SOF segment. Reason:{reason}"), + Self::IllegalMagicBytes(bytes) => + { + write!(f, "Error parsing image. Illegal start bytes:{bytes:X}") + } + Self::MCUError(ref reason) => write!(f, "Error in decoding MCU. Reason {reason}"), + Self::Unsupported(ref image_type) => + { + write!(f, "{image_type:?}") + } + Self::ExhaustedData => write!(f, "Exhausted data in the image"), + Self::LargeDimensions(ref dimensions) => write!( + f, + "Too large dimensions {dimensions},library supports up to {}", crate::decoder::MAX_DIMENSIONS + ), + Self::TooSmallOutput(expected, found) => write!(f, "Too small output, expected buffer with at least {expected} bytes but got one with {found} bytes"), + Self::IoErrors(error)=>write!(f,"I/O errors {error:?}"), + } + } +} + +impl Display for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } +} + +/// Contains Unsupported/Yet-to-be supported Decoder image encoding types. +#[derive(Eq, PartialEq, Copy, Clone)] +pub enum UnsupportedSchemes { + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Debug for UnsupportedSchemes { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self { + Self::ExtendedSequentialHuffman => { + write!(f, "The library cannot yet decode images encoded using Extended Sequential Huffman encoding scheme yet.") + } + Self::LosslessHuffman => { + write!(f, "The library cannot yet decode images encoded with Lossless Huffman encoding scheme") + } + Self::ExtendedSequentialDctArithmetic => { + write!(f,"The library cannot yet decode Images Encoded with Extended Sequential DCT Arithmetic scheme") + } + Self::ProgressiveDctArithmetic => { + write!(f,"The library cannot yet decode images encoded with Progressive DCT Arithmetic scheme") + } + Self::LosslessArithmetic => { + write!(f,"The library cannot yet decode images encoded with Lossless Arithmetic encoding scheme") + } + } + } +} + +impl UnsupportedSchemes { + #[must_use] + /// Create an unsupported scheme from an integer + /// + /// # Returns + /// `Some(UnsupportedScheme)` if the int refers to a specific scheme, + /// otherwise returns `None` + pub fn from_int(int: u8) -> Option { + let int = u16::from_be_bytes([0xff, int]); + + match int { + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/headers.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/headers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/headers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/headers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decode Decoder markers/segments +//! +//! This file deals with decoding header information in a jpeg file +//! +use alloc::format; +use alloc::string::ToString; +use alloc::vec::Vec; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, trace, warn}; + +use crate::components::Components; +use crate::decoder::{GainMapInfo, ICCChunk, JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::misc::{SOFMarkers, UN_ZIGZAG}; + +///**B.2.4.2 Huffman table-specification syntax** +#[allow(clippy::similar_names, clippy::cast_sign_loss)] +pub(crate) fn parse_huffman( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> +where +{ + // Read the length of the Huffman table + let mut dht_length = i32::from(decoder.stream.get_u16_be_err()?.checked_sub(2).ok_or( + DecodeErrors::FormatStatic("Invalid Huffman length in image") + )?); + + while dht_length > 16 { + // HT information + let ht_info = decoder.stream.read_u8_err()?; + // third bit indicates whether the huffman encoding is DC or AC type + let dc_or_ac = (ht_info >> 4) & 0xF; + // Indicate the position of this table, should be less than 4; + let index = (ht_info & 0xF) as usize; + // read the number of symbols + let mut num_symbols: [u8; 17] = [0; 17]; + + if index >= MAX_COMPONENTS { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT index {index}, expected between 0 and 3" + ))); + } + + if dc_or_ac > 1 { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT position {dc_or_ac}, should be 0 or 1" + ))); + } + + decoder.stream.read_exact_bytes(&mut num_symbols[1..17])?; + + dht_length -= 1 + 16; + + let symbols_sum: i32 = num_symbols.iter().map(|f| i32::from(*f)).sum(); + + // The sum of the number of symbols cannot be greater than 256; + if symbols_sum > 256 { + return Err(DecodeErrors::FormatStatic( + "Encountered Huffman table with excessive length in DHT" + )); + } + if symbols_sum > dht_length { + return Err(DecodeErrors::HuffmanDecode(format!( + "Excessive Huffman table of length {symbols_sum} found when header length is {dht_length}" + ))); + } + dht_length -= symbols_sum; + // A table containing symbols in increasing code length + let mut symbols = [0; 256]; + + decoder + .stream + .read_exact_bytes(&mut symbols[0..(symbols_sum as usize)])?; + // store + match dc_or_ac { + 0 => { + decoder.dc_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + true, + decoder.is_progressive + )?); + } + _ => { + decoder.ac_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + false, + decoder.is_progressive + )?); + } + } + } + + if dht_length > 0 { + return Err(DecodeErrors::FormatStatic("Bogus Huffman table definition")); + } + + Ok(()) +} + +///**B.2.4.1 Quantization table-specification syntax** +#[allow(clippy::cast_possible_truncation, clippy::needless_range_loop)] +pub(crate) fn parse_dqt(img: &mut JpegDecoder) -> Result<(), DecodeErrors> { + // read length + let mut qt_length = + img.stream + .get_u16_be_err()? + .checked_sub(2) + .ok_or(DecodeErrors::FormatStatic( + "Invalid DQT length. Length should be greater than 2" + ))?; + // A single DQT header may have multiple QT's + while qt_length > 0 { + let qt_info = img.stream.read_u8_err()?; + // 0 = 8 bit otherwise 16 bit dqt + let precision = (qt_info >> 4) as usize; + // last 4 bits give us position + let table_position = (qt_info & 0x0f) as usize; + let precision_value = 64 * (precision + 1); + + if (precision_value + 1) as u16 > qt_length { + return Err(DecodeErrors::DqtError(format!("Invalid QT table bytes left :{}. Too small to construct a valid qt table which should be {} long", qt_length, precision_value + 1))); + } + + let dct_table = match precision { + 0 => { + let mut qt_values = [0; 64]; + + img.stream.read_exact_bytes(&mut qt_values)?; + + qt_length -= (precision_value as u16) + 1 /*QT BIT*/; + // carry out un zig-zag here + un_zig_zag(&qt_values) + } + 1 => { + // 16 bit quantization tables + let mut qt_values = [0_u16; 64]; + + for i in 0..64 { + qt_values[i] = img.stream.get_u16_be_err()?; + } + qt_length -= (precision_value as u16) + 1; + + un_zig_zag(&qt_values) + } + _ => { + return Err(DecodeErrors::DqtError(format!( + "Expected QT precision value of either 0 or 1, found {precision:?}" + ))); + } + }; + + if table_position >= MAX_COMPONENTS { + return Err(DecodeErrors::DqtError(format!( + "Too large table position for QT :{table_position}, expected between 0 and 3" + ))); + } + + trace!("Assigning qt table {table_position} with precision {precision}"); + img.qt_tables[table_position] = Some(dct_table); + } + + return Ok(()); +} + +/// Section:`B.2.2 Frame header syntax` + +pub(crate) fn parse_start_of_frame( + sof: SOFMarkers, img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + if img.seen_sof { + return Err(DecodeErrors::SofError( + "Two Start of Frame Markers".to_string() + )); + } + // Get length of the frame header + let length = img.stream.get_u16_be_err()?; + // usually 8, but can be 12 and 16, we currently support only 8 + // so sorry about that 12 bit images + let dt_precision = img.stream.read_u8_err()?; + + if dt_precision != 8 { + return Err(DecodeErrors::SofError(format!( + "The library can only parse 8-bit images, the image has {dt_precision} bits of precision" + ))); + } + + img.info.set_density(dt_precision); + + // read and set the image height. + let img_height = img.stream.get_u16_be_err()?; + img.info.set_height(img_height); + + // read and set the image width + let img_width = img.stream.get_u16_be_err()?; + img.info.set_width(img_width); + + trace!("Image width :{}", img_width); + trace!("Image height :{}", img_height); + + if usize::from(img_width) > img.options.max_width() { + return Err(DecodeErrors::Format(format!("Image width {} greater than width limit {}. If use `set_limits` if you want to support huge images", img_width, img.options.max_width()))); + } + + if usize::from(img_height) > img.options.max_height() { + return Err(DecodeErrors::Format(format!("Image height {} greater than height limit {}. If use `set_limits` if you want to support huge images", img_height, img.options.max_height()))); + } + + // Check image width or height is zero + if img_width == 0 || img_height == 0 { + return Err(DecodeErrors::ZeroError); + } + + // Number of components for the image. + let num_components = img.stream.read_u8_err()?; + + if num_components == 0 { + return Err(DecodeErrors::SofError( + "Number of components cannot be zero.".to_string() + )); + } + + let expected = 8 + 3 * u16::from(num_components); + // length should be equal to num components + if length != expected { + return Err(DecodeErrors::SofError(format!( + "Length of start of frame differs from expected {expected},value is {length}" + ))); + } + + trace!("Image components : {}", num_components); + + if num_components == 1 { + // SOF sets the number of image components + // and that to us translates to setting input and output + // colorspaces to zero + img.input_colorspace = ColorSpace::Luma; + //img.options = img.options.jpeg_set_out_colorspace(ColorSpace::Luma); + debug!("Overriding default colorspace set to Luma"); + } + if num_components == 4 && img.input_colorspace == ColorSpace::YCbCr { + trace!("Input image has 4 components, defaulting to CMYK colorspace"); + // https://entropymine.wordpress.com/2018/10/22/how-is-a-jpeg-images-color-type-determined/ + img.input_colorspace = ColorSpace::CMYK; + } + + // set number of components + img.info.components = num_components; + + let mut components = Vec::with_capacity(num_components as usize); + let mut temp = [0; 3]; + + for pos in 0..num_components { + // read 3 bytes for each component + img.stream.read_exact_bytes(&mut temp)?; + + // create a component. + let component = Components::from(temp, pos)?; + + components.push(component); + } + img.seen_sof = true; + + img.info.set_sof_marker(sof); + + img.components = components; + + Ok(()) +} + +/// Parse a start of scan data +pub(crate) fn parse_sos( + image: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // Scan header length + let ls = usize::from(image.stream.get_u16_be_err()?); + // Number of image components in scan + let ns = image.stream.read_u8_err()?; + + let mut seen: [_; 5] = [-1; { MAX_COMPONENTS + 1 }]; + + image.num_scans = ns; + let smallest_size = 6 + 2 * usize::from(ns); + + if ls != smallest_size { + return Err(DecodeErrors::SosError(format!( + "Bad SOS length {ls},corrupt jpeg" + ))); + } + + // Check number of components. + if !(1..5).contains(&ns) { + return Err(DecodeErrors::SosError(format!( + "Invalid number of components in start of scan {ns}, expected in range 1..5" + ))); + } + + if image.info.components == 0 { + return Err(DecodeErrors::FormatStatic( + "Error decoding SOF Marker, Number of components cannot be zero." + )); + } + + // consume spec parameters + image.scan_subsampled = false; + + for i in 0..ns { + let id = image.stream.read_u8_err()?; + + if seen.contains(&i32::from(id)) { + return Err(DecodeErrors::SofError(format!( + "Duplicate ID {id} seen twice in the same component" + ))); + } + + seen[usize::from(i)] = i32::from(id); + // DC and AC huffman table position + // top 4 bits contain dc huffman destination table + // lower four bits contain ac huffman destination table + let y = image.stream.read_u8_err()?; + + let mut j = 0; + + while j < image.info.components { + if image.components[j as usize].id == id { + break; + } + + j += 1; + } + + if j == image.info.components { + return Err(DecodeErrors::SofError(format!( + "Invalid component id {}, expected one one of {:?}", + id, + image.components.iter().map(|c| c.id).collect::>() + ))); + } + + let component = &mut image.components[usize::from(j)]; + component.dc_huff_table = usize::from((y >> 4) & 0xF); + component.ac_huff_table = usize::from(y & 0xF); + image.z_order[i as usize] = j as usize; + + if component.vertical_sample != 1 || component.horizontal_sample != 1 { + image.scan_subsampled = true; + } + + trace!( + "Assigned huffman tables {}/{} to component {j}, id={}", + image.components[usize::from(j)].dc_huff_table, + image.components[usize::from(j)].ac_huff_table, + image.components[usize::from(j)].id, + ); + } + + // Collect the component spec parameters + // This is only needed for progressive images but I'll read + // them in order to ensure they are correct according to the spec + + // Extract progressive information + + // https://www.w3.org/Graphics/JPEG/itu-t81.pdf + // Page 42 + + // Start of spectral / predictor selection. (between 0 and 63) + image.spec_start = image.stream.read_u8_err()?; + // End of spectral selection + image.spec_end = image.stream.read_u8_err()?; + + let bit_approx = image.stream.read_u8_err()?; + // successive approximation bit position high + image.succ_high = bit_approx >> 4; + + if image.spec_end > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Se parameter {}, range should be 0-63", + image.spec_end + ))); + } + if image.spec_start > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ss parameter {}, range should be 0-63", + image.spec_start + ))); + } + if image.succ_high > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ah parameter {}, range should be 0-13", + image.succ_low + ))); + } + // successive approximation bit position low + image.succ_low = bit_approx & 0xF; + + if image.succ_low > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Al parameter {}, range should be 0-13", + image.succ_low + ))); + } + // skip any bytes not read + image.stream.skip(smallest_size.saturating_sub(ls))?; + + trace!( + "Ss={}, Se={} Ah={} Al={}", + image.spec_start, + image.spec_end, + image.succ_high, + image.succ_low + ); + + Ok(()) +} + +/// Parse the APP13 (IPTC) segment. +pub(crate) fn parse_app13( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + const IPTC_PREFIX: &[u8] = b"Photoshop 3.0\0"; + // skip length. + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small APP13 length")); + } + // length bytes. + length -= 2; + + if length > IPTC_PREFIX.len() && decoder.stream.peek_at(0, IPTC_PREFIX.len())? == IPTC_PREFIX { + // skip bytes we read above. + decoder.stream.skip(IPTC_PREFIX.len())?; + length -= IPTC_PREFIX.len(); + + let iptc_bytes = decoder.stream.peek_at(0, length)?.to_vec(); + + decoder.info.iptc_data = Some(iptc_bytes); + } + + decoder.stream.skip(length)?; + Ok(()) +} + +/// Parse Adobe App14 segment +pub(crate) fn parse_app14( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // skip length + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small APP14 length")); + } + + if decoder.stream.peek_at(0, 5)? == b"Adobe" { + if length < 14 { + return Err(DecodeErrors::FormatStatic( + "Too short of a length for App14 segment" + )); + } + // move stream 6 bytes to remove adobe id + decoder.stream.skip(6)?; + // skip version, flags0 and flags1 + decoder.stream.skip(5)?; + // get color transform + let transform = decoder.stream.read_u8(); + // https://exiftool.org/TagNames/JPEG.html#Adobe + match transform { + 0 => decoder.input_colorspace = ColorSpace::CMYK, + 1 => decoder.input_colorspace = ColorSpace::YCbCr, + 2 => decoder.input_colorspace = ColorSpace::YCCK, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown Adobe colorspace {transform}" + ))) + } + } + // length = 2 + // adobe id = 6 + // version = 5 + // transform = 1 + length = length.saturating_sub(14); + } else { + warn!("Not a valid Adobe APP14 Segment, skipping"); + } + // skip any proceeding lengths. + // we do not need them + decoder.stream.skip(length)?; + + Ok(()) +} + +/// Parse the APP1 segment +/// +/// This contains the exif tag +pub(crate) fn parse_app1( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + const XMP_NAMESPACE_PREFIX: &[u8] = b"http://ns.adobe.com/xap/1.0/\0"; + + // contains exif data + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small app1 length")); + } + // length bytes + length -= 2; + + if length > 6 && decoder.stream.peek_at(0, 6)? == b"Exif\x00\x00" { + trace!("Exif segment present"); + // skip bytes we read above + decoder.stream.skip(6)?; + length -= 6; + + let exif_bytes = decoder.stream.peek_at(0, length)?.to_vec(); + + decoder.info.exif_data = Some(exif_bytes); + } else if length > XMP_NAMESPACE_PREFIX.len() + && decoder.stream.peek_at(0, XMP_NAMESPACE_PREFIX.len())? == XMP_NAMESPACE_PREFIX + { + trace!("XMP Data Present"); + decoder.stream.skip(XMP_NAMESPACE_PREFIX.len())?; + length -= XMP_NAMESPACE_PREFIX.len(); + let xmp_data = decoder.stream.peek_at(0, length)?.to_vec(); + decoder.info.xmp_data = Some(xmp_data); + } else { + warn!("Unknown format for APP1 tag, skipping"); + } + + decoder.stream.skip(length)?; + Ok(()) +} + +pub(crate) fn parse_app2( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + static HDR_META: &[u8] = b"urn:iso:std:iso:ts:21496:-1\0"; + static MPF_DATA: &[u8] = b"MPF\0"; + + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small app2 segment")); + } + // length bytes + length -= 2; + + if length > 14 && decoder.stream.peek_at(0, 12)? == *b"ICC_PROFILE\0" { + trace!("ICC Profile present"); + // skip 12 bytes which indicate ICC profile + length -= 12; + decoder.stream.skip(12)?; + let seq_no = decoder.stream.read_u8(); + let num_markers = decoder.stream.read_u8(); + // deduct the two bytes we read above + length -= 2; + + let data = decoder.stream.peek_at(0, length)?.to_vec(); + + let icc_chunk = ICCChunk { + seq_no, + num_markers, + data + }; + decoder.icc_data.push(icc_chunk); + } else if length > HDR_META.len() && decoder.stream.peek_at(0, HDR_META.len())? == HDR_META { + length = length.saturating_sub(HDR_META.len()); + decoder.stream.skip(HDR_META.len())?; + trace!("Gain Map metadata found"); + match length { + 4 => { + // If gain map metadata length == 4 then here it variables + // https://github.com/google/libultrahdr/blob/bf2aa439eea9ad5da483003fa44182f990f74091/lib/src/jpegr.cpp#L1076C1-L1077C35 + // 2 bytes minimum_version: (00 00) + // 2 bytes writer_version: (00 00) + // Perhaps nothing to do with it ? + let _ = decoder.stream.get_u16_be(); + let _ = decoder.stream.get_u16_be(); + length -= 4; + decoder + .info + .gain_map_info + .push(GainMapInfo { data: Vec::new() }); + } + n if n > 4 => { + // If there is perhaps useful gain map info + // we'll read this until end + // https://github.com/google/libultrahdr/blob/bf2aa439eea9ad5da483003fa44182f990f74091/lib/src/jpegr.cpp#L1323 + let data = decoder.stream.peek_at(0, length)?.to_vec(); + length -= data.len(); + decoder.stream.skip(data.len())?; + + decoder.info.gain_map_info.push(GainMapInfo { data }); + } + _ => {} + } + } else if length > MPF_DATA.len() && decoder.stream.peek_at(0, MPF_DATA.len())? == MPF_DATA { + trace!("MPF Signature present"); + length = length.saturating_sub(MPF_DATA.len()); + decoder.stream.skip(MPF_DATA.len())?; + // MPF signature taken from here + // https://github.com/google/libultrahdr/blob/bf2aa439eea9ad5da483003fa44182f990f74091/lib/include/ultrahdr/multipictureformat.h#L50 + // https://github.com/google/libultrahdr/blob/bf2aa439eea9ad5da483003fa44182f990f74091/lib/src/multipictureformat.cpp#L36 + // More info https://www.cipa.jp/std/documents/e/DC-X007-KEY_E.pdf + let data = decoder.stream.peek_at(0, length)?.to_vec(); + length -= data.len(); + decoder.stream.skip(data.len())?; + decoder.info.multi_picture_information = Some(data); + } + + decoder.stream.skip(length)?; + + Ok(()) +} + +/// Small utility function to print Un-zig-zagged quantization tables + +fn un_zig_zag(a: &[T]) -> [i32; 64] +where + T: Default + Copy, + i32: core::convert::From +{ + let mut output = [i32::default(); 64]; + + for i in 0..64 { + output[UN_ZIGZAG[i]] = i32::from(a[i]); + } + + output +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/huffman.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This file contains a single struct `HuffmanTable` that +//! stores Huffman tables needed during `BitStream` decoding. +#![allow(clippy::similar_names, clippy::module_name_repetitions)] + +use alloc::string::ToString; + +use crate::errors::DecodeErrors; + +/// Determines how many bits of lookahead we have for our bitstream decoder. + +pub const HUFF_LOOKAHEAD: u8 = 9; + +/// A struct which contains necessary tables for decoding a JPEG +/// huffman encoded bitstream + +pub struct HuffmanTable { + // element `[0]` of each array is unused + /// largest code of length k + pub(crate) maxcode: [i32; 18], + /// offset for codes of length k + /// Answers the question, where do code-lengths of length k end + /// Element 0 is unused + pub(crate) offset: [i32; 18], + /// lookup table for fast decoding + /// + /// top bits above HUFF_LOOKAHEAD contain the code length. + /// + /// Lower (8) bits contain the symbol in order of increasing code length. + pub(crate) lookup: [i32; 1 << HUFF_LOOKAHEAD], + + /// A table which can be used to decode small AC coefficients and + /// do an equivalent of receive_extend + pub(crate) ac_lookup: Option<[i16; 1 << HUFF_LOOKAHEAD]>, + + /// Directly represent contents of a JPEG DHT marker + /// + /// \# number of symbols with codes of length `k` bits + // bits[0] is unused + /// Symbols in order of increasing code length + pub(crate) values: [u8; 256] +} + +impl HuffmanTable { + pub fn new( + codes: &[u8; 17], values: [u8; 256], is_dc: bool, is_progressive: bool + ) -> Result { + let too_long_code = (i32::from(HUFF_LOOKAHEAD) + 1) << HUFF_LOOKAHEAD; + let mut p = HuffmanTable { + maxcode: [0; 18], + offset: [0; 18], + lookup: [too_long_code; 1 << HUFF_LOOKAHEAD], + values, + ac_lookup: None + }; + + p.make_derived_table(is_dc, is_progressive, codes)?; + + Ok(p) + } + + /// Create a new huffman tables with values that aren't fixed + /// used by fill_mjpeg_tables + pub fn new_unfilled( + codes: &[u8; 17], values: &[u8], is_dc: bool, is_progressive: bool + ) -> Result { + let mut buf = [0; 256]; + buf[..values.len()].copy_from_slice(values); + HuffmanTable::new(codes, buf, is_dc, is_progressive) + } + + /// Compute derived values for a Huffman table + /// + /// This routine performs some validation checks on the table + #[allow( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + clippy::too_many_lines, + clippy::needless_range_loop + )] + fn make_derived_table( + &mut self, is_dc: bool, _is_progressive: bool, bits: &[u8; 17] + ) -> Result<(), DecodeErrors> { + // build a list of code size + let mut huff_size = [0; 257]; + // Huffman code lengths + let mut huff_code: [u32; 257] = [0; 257]; + // figure C.1 make table of Huffman code length for each symbol + let mut p = 0; + + for l in 1..=16 { + let mut i = i32::from(bits[l]); + // table overrun is checked before ,so we dont need to check + while i != 0 { + huff_size[p] = l as u8; + p += 1; + i -= 1; + } + } + + huff_size[p] = 0; + + let num_symbols = p; + // Generate the codes themselves + // We also validate that the counts represent a legal Huffman code tree + let mut code = 0; + let mut si = i32::from(huff_size[0]); + + p = 0; + + while huff_size[p] != 0 { + while i32::from(huff_size[p]) == si { + huff_code[p] = code; + code += 1; + p += 1; + } + // maximum code of length si, pre-shifted by 16-k bits + self.maxcode[si as usize] = (code << (16 - si)) as i32; + // code is now 1 more than the last code used for code-length si; but + // it must still fit in si bits, since no code is allowed to be all ones. + if (code as i32) >= (1 << si) { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + + code <<= 1; + si += 1; + } + + // Figure F.15 generate decoding tables for bit-sequential decoding + p = 0; + + for l in 0..=16 { + if bits[l] == 0 { + // -1 if no codes of this length + self.maxcode[l] = -1; + } else { + // offset[l]=codes[index of 1st symbol of code length l + // minus minimum code of length l] + self.offset[l] = (p as i32) - (huff_code[p]) as i32; + p += usize::from(bits[l]); + } + } + + self.offset[17] = 0; + // we ensure that decode terminates + self.maxcode[17] = 0x000F_FFFF; + + /* + * Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0(left justified), indicating "too long"; + * (Note too long was set during initialization) + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + p = 0; + + for l in 1..=HUFF_LOOKAHEAD { + for _ in 1..=i32::from(bits[usize::from(l)]) { + // l -> Current code length, + // p => Its index in self.code and self.values + // Generate left justified code followed by all possible bit sequences + let mut look_bits = (huff_code[p] as usize) << (HUFF_LOOKAHEAD - l); + + for _ in 0..1 << (HUFF_LOOKAHEAD - l) { + self.lookup[look_bits] = + (i32::from(l) << HUFF_LOOKAHEAD) | i32::from(self.values[p]); + look_bits += 1; + } + + p += 1; + } + } + // build an ac table that does an equivalent of decode and receive_extend + if !is_dc { + let mut fast = [255; 1 << HUFF_LOOKAHEAD]; + // Iterate over number of symbols + for i in 0..num_symbols { + // get code size for an item + let s = huff_size[i]; + + if s <= HUFF_LOOKAHEAD { + // if it's lower than what we need for our lookup table create the table + let c = (huff_code[i] << (HUFF_LOOKAHEAD - s)) as usize; + let m = (1 << (HUFF_LOOKAHEAD - s)) as usize; + + for j in 0..m { + fast[c + j] = i as i16; + } + } + } + + // build a table that decodes both magnitude and value of small ACs in + // one go. + let mut fast_ac = [0; 1 << HUFF_LOOKAHEAD]; + + for i in 0..(1 << HUFF_LOOKAHEAD) { + let fast_v = fast[i]; + + if fast_v < 255 { + // get symbol value from AC table + let rs = self.values[fast_v as usize]; + // shift by 4 to get run length + let run = i16::from((rs >> 4) & 15); + // get magnitude bits stored at the lower 3 bits + let mag_bits = i16::from(rs & 15); + // length of the bit we've read + let len = i16::from(huff_size[fast_v as usize]); + + if mag_bits != 0 && (len + mag_bits) <= i16::from(HUFF_LOOKAHEAD) { + // magnitude code followed by receive_extend code + let mut k = (((i as i16) << len) & ((1 << HUFF_LOOKAHEAD) - 1)) + >> (i16::from(HUFF_LOOKAHEAD) - mag_bits); + let m = 1 << (mag_bits - 1); + + if k < m { + k += (!0_i16 << mag_bits) + 1; + }; + + // if result is small enough fit into fast ac table + if (-128..=127).contains(&k) { + fast_ac[i] = (k << 8) + (run << 4) + (len + mag_bits); + } + } + } + } + self.ac_lookup = Some(fast_ac); + } + + // Validate symbols as being reasonable + // For AC tables, we make no check, but accept all byte values 0..255 + // For DC tables, we require symbols to be in range 0..15 + if is_dc { + for i in 0..num_symbols { + let sym = self.values[i]; + + if sym > 15 { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/avx2.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/avx2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/avx2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/avx2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "x86")] +#![allow(dead_code)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +// Pack i32 to i16's, +// clamp them to be between 0-255 +// Undo shuffling +// Store back to array +macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt,$stride:tt) => { + let a = _mm256_packs_epi32($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp_avx(a); + + // /Undo shuffling + let c = _mm256_permute4x64_epi64(b, shuffle(3, 1, 2, 0)); + + // store first vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<0>(c), + ); + $index += $stride; + // second vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<1>(c), + ); + $index += $stride; + }; +} + +#[target_feature(enable = "avx2")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_avx2( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize, +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let rw0 = _mm256_loadu_si256(in_vector[00..].as_ptr().cast()); + let rw1 = _mm256_loadu_si256(in_vector[08..].as_ptr().cast()); + let rw2 = _mm256_loadu_si256(in_vector[16..].as_ptr().cast()); + let rw3 = _mm256_loadu_si256(in_vector[24..].as_ptr().cast()); + let rw4 = _mm256_loadu_si256(in_vector[32..].as_ptr().cast()); + let rw5 = _mm256_loadu_si256(in_vector[40..].as_ptr().cast()); + let rw6 = _mm256_loadu_si256(in_vector[48..].as_ptr().cast()); + let rw7 = _mm256_loadu_si256(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + let rw8 = _mm256_loadu_si256(in_vector[1..].as_ptr().cast()); + + let mut bitmap = _mm256_or_si256(rw1, rw2); + bitmap = _mm256_or_si256(bitmap, rw3); + bitmap = _mm256_or_si256(bitmap, rw4); + bitmap = _mm256_or_si256(bitmap, rw5); + bitmap = _mm256_or_si256(bitmap, rw6); + bitmap = _mm256_or_si256(bitmap, rw7); + bitmap = _mm256_or_si256(bitmap, rw8); + + if _mm256_testz_si256(bitmap, bitmap) == 1 { + // AC terms all zero, idct of the block is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + // Round by adding 0.5 * (1 << 3) and offset by adding (128 << 3) before scaling + let coeff = ((in_vector[0] + 4 + 1024) >> 3).clamp(0, 255) as i16; + let idct_value = _mm_set1_epi16(coeff); + + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + _mm_storeu_si128( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value, + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + let mut row0 = YmmRegister { mm256: rw0 }; + let mut row1 = YmmRegister { mm256: rw1 }; + let mut row2 = YmmRegister { mm256: rw2 }; + let mut row3 = YmmRegister { mm256: rw3 }; + + let mut row4 = YmmRegister { mm256: rw4 }; + let mut row5 = YmmRegister { mm256: rw5 }; + let mut row6 = YmmRegister { mm256: rw6 }; + let mut row7 = YmmRegister { mm256: rw7 }; + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = YmmRegister { + mm256: _mm256_slli_epi32((row0 + row4).mm256, 12), + }; + let mut t1 = YmmRegister { + mm256: _mm256_slli_epi32((row0 - row4).mm256, 12), + }; + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0.mm256 = _mm256_srai_epi32((x0 + t3).mm256, $scale); + row1.mm256 = _mm256_srai_epi32((x1 + t2).mm256, $scale); + row2.mm256 = _mm256_srai_epi32((x2 + t1).mm256, $scale); + row3.mm256 = _mm256_srai_epi32((x3 + t0).mm256, $scale); + + row4.mm256 = _mm256_srai_epi32((x3 - t0).mm256, $scale); + row5.mm256 = _mm256_srai_epi32((x2 - t1).mm256, $scale); + row6.mm256 = _mm256_srai_epi32((x1 - t2).mm256, $scale); + row7.mm256 = _mm256_srai_epi32((x0 - t3).mm256, $scale); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7, + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7, + ); + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector, stride); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector, stride); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector, stride); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector, stride); +} + + +#[target_feature(enable = "avx2")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_avx2_4x4( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize, +) { + let rw0 = _mm256_loadu_si256(in_vector[00..].as_ptr().cast()); + let rw1 = _mm256_loadu_si256(in_vector[08..].as_ptr().cast()); + let rw2 = _mm256_loadu_si256(in_vector[16..].as_ptr().cast()); + let rw3 = _mm256_loadu_si256(in_vector[24..].as_ptr().cast()); + + let mut row0 = YmmRegister { mm256: rw0 }; + let mut row1 = YmmRegister { mm256: rw1 }; + let mut row2 = YmmRegister { mm256: rw2 }; + let mut row3 = YmmRegister { mm256: rw3 }; + + let mut row4 = YmmRegister { mm256: rw0 }; + let mut row5 = YmmRegister { mm256: rw0 }; + let mut row6 = YmmRegister { mm256: rw0 }; + let mut row7 = YmmRegister { mm256: rw0 }; + + { + row0.mm256 = _mm256_slli_epi32(row0.mm256, 12); + row0 += 512; + + let i2 = row2; + + let p1 = i2 * 2217; + let p3 = i2 * 5352; + + let x0 = row0 + p3; + let x1 = row0 + p1; + let x2 = row0 - p1; + let x3 = row0 - p3; + + // odd part + let i4 = row3; + let i3 = row1; + + let p5 = (i4 + i3) * 4816; + + let p1 = p5 + i3 * -3685; + let p2 = p5 + i4 * -10497; + + let t3 = p5 + i3 * 867; + let t2 = p5 + i4 * -5945; + + let t1 = p2 + i3 * -1597; + let t0 = p1 + i4 * -8034; + + row0.mm256 = _mm256_srai_epi32((x0 + t3).mm256, 10); + row1.mm256 = _mm256_srai_epi32((x1 + t2).mm256, 10); + row2.mm256 = _mm256_srai_epi32((x2 + t1).mm256, 10); + row3.mm256 = _mm256_srai_epi32((x3 + t0).mm256, 10); + + row4.mm256 = _mm256_srai_epi32((x3 - t0).mm256, 10); + row5.mm256 = _mm256_srai_epi32((x2 - t1).mm256, 10); + row6.mm256 = _mm256_srai_epi32((x1 - t2).mm256, 10); + row7.mm256 = _mm256_srai_epi32((x0 - t3).mm256, 10); + } + + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7, + ); + + { + let i2 = row2; + let i0 = row0; + + row0.mm256 = _mm256_slli_epi32(i0.mm256, 12); + let t0 = row0 + SCALE_BITS; + + let t2 = i2 * 2217; + let t3 = i2 * 5352; + + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + // Rounding constant is already added into `t0` + let x0 = t0 + t3; + let x3 = t0 - t3; + let x1 = t0 + t2; + let x2 = t0 - t2; + + // odd part + let i3 = row3; + let i1 = row1; + + let p5 = (i3 + i1) * 4816; + + let p1 = p5 + i1 * -3685; + let p2 = p5 + i3 * -10497; + + let t3 = p5 + i1 * 867; + let t2 = p5 + i3 * -5945; + + let t1 = p2 + i1 * -1597; + let t0 = p1 + i3 * -8034; + + row0.mm256 = _mm256_srai_epi32((x0 + t3).mm256, 17); + row1.mm256 = _mm256_srai_epi32((x1 + t2).mm256, 17); + row2.mm256 = _mm256_srai_epi32((x2 + t1).mm256, 17); + row3.mm256 = _mm256_srai_epi32((x3 + t0).mm256, 17); + row4.mm256 = _mm256_srai_epi32((x3 - t0).mm256, 17); + row5.mm256 = _mm256_srai_epi32((x2 - t1).mm256, 17); + row6.mm256 = _mm256_srai_epi32((x1 - t2).mm256, 17); + row7.mm256 = _mm256_srai_epi32((x0 - t3).mm256, 17); + } + + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7, + ); + + let mut pos = 0; + + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector, stride); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector, stride); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector, stride); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector, stride); +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn clamp_avx(reg: __m256i) -> __m256i { + let min_s = _mm256_set1_epi16(0); + let max_s = _mm256_set1_epi16(255); + + let max_v = _mm256_max_epi16(reg, min_s); //max(a,0) + let min_v = _mm256_min_epi16(max_v, max_s); //min(max(a,0),255) + return min_v; +} + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + ((z << 6) | (y << 4) | (x << 2) | w) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/neon.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(target_arch = "aarch64")] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "neon")] + +use core::arch::aarch64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn pack_16(a: int32x4x2_t) -> int16x8_t { + vcombine_s16(vqmovn_s32(a.0), vqmovn_s32(a.1)) +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn condense_bottom_16(a: int32x4x2_t, b: int32x4x2_t) -> int16x8x2_t { + int16x8x2_t(pack_16(a), pack_16(b)) +} + +#[target_feature(enable = "neon")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_neon( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let mut row0 = YmmRegister::load(in_vector[00..].as_ptr().cast()); + let mut row1 = YmmRegister::load(in_vector[08..].as_ptr().cast()); + let mut row2 = YmmRegister::load(in_vector[16..].as_ptr().cast()); + let mut row3 = YmmRegister::load(in_vector[24..].as_ptr().cast()); + let mut row4 = YmmRegister::load(in_vector[32..].as_ptr().cast()); + let mut row5 = YmmRegister::load(in_vector[40..].as_ptr().cast()); + let mut row6 = YmmRegister::load(in_vector[48..].as_ptr().cast()); + let mut row7 = YmmRegister::load(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + // TODO this should be a shift/shuffle, not a likely unaligned load + let row8 = YmmRegister::load(in_vector[1..].as_ptr().cast()); + + let or_tree = (((row1 | row8) | (row2 | row3)) | ((row4 | row5) | (row6 | row7))); + + if or_tree.all_zero() { + // AC terms all zero, idct of the block is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + // Round by adding 0.5 * (1 << 3) and offset by adding (128 << 3) before scaling + let coeff = ((in_vector[0] + 4 + 1024) >> 3).clamp(0, 255) as i16; + let idct_value = vdupq_n_s16(coeff); + + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + vst1q_s16( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // Compiler does a pretty good job of optimizing add + mul pairs + // into multiply-acumulate pairs + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = (row0 + row4).const_shl::<12>(); + let mut t1 = (row0 - row4).const_shl::<12>(); + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0 = (x0 + t3).const_shra::<$scale>(); + row1 = (x1 + t2).const_shra::<$scale>(); + row2 = (x2 + t1).const_shra::<$scale>(); + row3 = (x3 + t0).const_shra::<$scale>(); + + row4 = (x3 - t0).const_shra::<$scale>(); + row5 = (x2 - t1).const_shra::<$scale>(); + row6 = (x1 - t2).const_shra::<$scale>(); + row7 = (x0 - t3).const_shra::<$scale>(); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // Pack i32 to i16's, + // clamp them to be between 0-255 + // Undo shuffling + // Store back to array + + // This could potentially be reorganized to take advantage of the multi-register stores + macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt) => { + let a = condense_bottom_16($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp256_neon(a); + + // store first vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.0 + ); + $index += stride; + // second vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.1 + ); + $index += stride; + }; + } + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector); +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp_neon(reg: int16x8_t) -> int16x8_t { + let min_s = vdupq_n_s16(0); + let max_s = vdupq_n_s16(255); + + let max_v = vmaxq_s16(reg, min_s); //max(a,0) + let min_v = vminq_s16(max_v, max_s); //min(max(a,0),255) + min_v +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp256_neon(reg: int16x8x2_t) -> int16x8x2_t { + int16x8x2_t(clamp_neon(reg.0), clamp_neon(reg.1)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_neon_clamp_256() { + unsafe { + let vals: [i16; 16] = [-1, -2, -3, 4, 256, 257, 258, 240, -1, 290, 2, 3, 4, 5, 6, 7]; + let loaded = vld1q_s16_x2(vals.as_ptr().cast()); + let shuffled = clamp256_neon(loaded); + + let mut result: [i16; 16] = [0; 16]; + + vst1q_s16_x2(result.as_mut_ptr().cast(), shuffled); + + assert_eq!( + result, + [0, 0, 0, 4, 255, 255, 255, 240, 0, 255, 2, 3, 4, 5, 6, 7] + ) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Platform independent IDCT algorithm +//! +//! Not as fast as AVX one. + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +#[inline(always)] +fn wa(a: i32, b: i32) -> i32 { + a.wrapping_add(b) +} + +#[inline(always)] +fn ws(a: i32, b: i32) -> i32 { + a.wrapping_sub(b) +} + +#[inline(always)] +fn wm(a: i32, b: i32) -> i32 { + a.wrapping_mul(b) +} + +#[inline] +pub fn idct_int_1x1(in_vector: &mut [i32; 64], mut out_vector: &mut [i16], stride: usize) { + let coeff = ((wa(wa(in_vector[0], 4), 1024) >> 3).clamp(0, 255)) as i16; + + out_vector[..8].fill(coeff); + for _ in 0..7 { + out_vector = &mut out_vector[stride..]; + out_vector[..8].fill(coeff); + } +} + +#[allow(unused_assignments)] +#[allow( + clippy::too_many_lines, + clippy::op_ref, + clippy::cast_possible_truncation +)] +pub fn idct_int(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + let mut pos = 0; + let mut i = 0; + + if &in_vector[1..] == &[0_i32; 63] { + return idct_int_1x1(in_vector, out_vector, stride); + } + + // vertical pass + for ptr in 0..8 { + let p2 = in_vector[ptr + 16]; + let p3 = in_vector[ptr + 48]; + + let p1 = wm(wa(p2, p3), 2217); + + let t2 = wa(p1, wm(p3, -7567)); + let t3 = wa(p1, wm(p2, 3135)); + + let p2 = in_vector[ptr]; + let p3 = in_vector[32 + ptr]; + + let t0 = fsh(wa(p2, p3)); + let t1 = fsh(ws(p2, p3)); + + let x0 = wa(wa(t0, t3), 512); + let x3 = wa(ws(t0, t3), 512); + let x1 = wa(wa(t1, t2), 512); + let x2 = wa(ws(t1, t2), 512); + + let mut t0 = in_vector[ptr + 56]; + let mut t1 = in_vector[ptr + 40]; + let mut t2 = in_vector[ptr + 24]; + let mut t3 = in_vector[ptr + 8]; + + let p3 = wa(t0, t2); + let p4 = wa(t1, t3); + let p1 = wa(t0, t3); + let p2 = wa(t1, t2); + let p5 = wm(wa(p3, p4), 4816); + + t0 = wm(t0, 1223); + t1 = wm(t1, 8410); + t2 = wm(t2, 12586); + t3 = wm(t3, 6149); + + let p1 = wa(p5, wm(p1, -3685)); + let p2 = wa(p5, wm(p2, -10497)); + let p3 = wm(p3, -8034); + let p4 = wm(p4, -1597); + + t3 = wa(t3, wa(p1, p4)); + t2 = wa(t2, wa(p2, p3)); + t1 = wa(t1, wa(p2, p4)); + t0 = wa(t0, wa(p1, p3)); + + in_vector[ptr] = ws(wa(x0, t3), 0) >> 10; + in_vector[ptr + 8] = ws(wa(x1, t2), 0) >> 10; + in_vector[ptr + 16] = ws(wa(x2, t1), 0) >> 10; + in_vector[ptr + 24] = ws(wa(x3, t0), 0) >> 10; + in_vector[ptr + 32] = ws(ws(x3, t0), 0) >> 10; + in_vector[ptr + 40] = ws(ws(x2, t1), 0) >> 10; + in_vector[ptr + 48] = ws(ws(x1, t2), 0) >> 10; + in_vector[ptr + 56] = ws(ws(x0, t3), 0) >> 10; + } + + // horizontal pass + while i < 64 { + let p2 = in_vector[i + 2]; + let p3 = in_vector[i + 6]; + + let p1 = wm(wa(p2, p3), 2217); + let t2 = wa(p1, wm(p3, -7567)); + let t3 = wa(p1, wm(p2, 3135)); + + let p2 = in_vector[i]; + let p3 = in_vector[i + 4]; + + let t0 = fsh(wa(p2, p3)); + let t1 = fsh(ws(p2, p3)); + + let x0 = wa(wa(t0, t3), SCALE_BITS); + let x3 = wa(ws(t0, t3), SCALE_BITS); + let x1 = wa(wa(t1, t2), SCALE_BITS); + let x2 = wa(ws(t1, t2), SCALE_BITS); + + let mut t0 = in_vector[i + 7]; + let mut t1 = in_vector[i + 5]; + let mut t2 = in_vector[i + 3]; + let mut t3 = in_vector[i + 1]; + + let p3 = wa(t0, t2); + let p4 = wa(t1, t3); + let p1 = wa(t0, t3); + let p2 = wa(t1, t2); + let p5 = wm(wa(p3, p4), f2f(1.175875602)); + + t0 = wm(t0, 1223); + t1 = wm(t1, 8410); + t2 = wm(t2, 12586); + t3 = wm(t3, 6149); + + let p1 = wa(p5, wm(p1, -3685)); + let p2 = wa(p5, wm(p2, -10497)); + let p3 = wm(p3, -8034); + let p4 = wm(p4, -1597); + + t3 = wa(t3, wa(p1, p4)); + t2 = wa(t2, wa(p2, p3)); + t1 = wa(t1, wa(p2, p4)); + t0 = wa(t0, wa(p1, p3)); + + let out: &mut [i16; 8] = out_vector + .get_mut(pos..pos + 8) + .unwrap() + .try_into() + .unwrap(); + + out[0] = clamp(wa(x0, t3) >> 17); + out[1] = clamp(wa(x1, t2) >> 17); + out[2] = clamp(wa(x2, t1) >> 17); + out[3] = clamp(wa(x3, t0) >> 17); + out[4] = clamp(ws(x3, t0) >> 17); + out[5] = clamp(ws(x2, t1) >> 17); + out[6] = clamp(ws(x1, t2) >> 17); + out[7] = clamp(ws(x0, t3) >> 17); + + i += 8; + pos += stride; + } +} + +#[inline] +#[allow(clippy::cast_possible_truncation)] +/// Multiply a number by 4096 +fn f2f(x: f32) -> i32 { + (x * 4096.0 + 0.5) as i32 +} + +#[inline] +/// Multiply a number by 4096 +fn fsh(x: i32) -> i32 { + x << 12 +} + +/// Clamp values between 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation)] +fn clamp(a: i32) -> i16 { + a.clamp(0, 255) as i16 +} + +/// IDCT assuming only the upper 4x4 is filled. +pub fn idct4x4(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + let mut pos = 0; + + // vertical pass + for ptr in 0..4 { + let i0 = wa(fsh(in_vector[ptr]), 512); + let i2 = in_vector[ptr + 16]; + + let p1 = wm(i2, 2217); + let p3 = wm(i2, 5352); + + let x0 = wa(i0, p3); + let x1 = wa(i0, p1); + let x2 = ws(i0, p1); + let x3 = ws(i0, p3); + + // odd part + let i4 = in_vector[ptr + 24]; + let i3 = in_vector[ptr + 8]; + + let p5 = wm(wa(i4, i3), 4816); + + let p1 = wa(p5, wm(i3, -3685)); + let p2 = wa(p5, wm(i4, -10497)); + + let t3 = wa(p5, wm(i3, 867)); + let t2 = wa(p5, wm(i4, -5945)); + + let t1 = wa(p2, wm(i3, -1597)); + let t0 = wa(p1, wm(i4, -8034)); + + in_vector[ptr] = wa(x0, t3) >> 10; + in_vector[ptr + 8] = wa(x1, t2) >> 10; + in_vector[ptr + 16] = wa(x2, t1) >> 10; + in_vector[ptr + 24] = wa(x3, t0) >> 10; + in_vector[ptr + 32] = ws(x3, t0) >> 10; + in_vector[ptr + 40] = ws(x2, t1) >> 10; + in_vector[ptr + 48] = ws(x1, t2) >> 10; + in_vector[ptr + 56] = ws(x0, t3) >> 10; + } + + // horizontal pass + for i in (0..8).map(|i| 8 * i) { + let i2 = in_vector[i + 2]; + let i0 = in_vector[i]; + + let t0 = wa(fsh(i0), SCALE_BITS); + let t2 = wm(i2, 2217); + let t3 = wm(i2, 5352); + + let x0 = wa(t0, t3); + let x3 = ws(t0, t3); + let x1 = wa(t0, t2); + let x2 = ws(t0, t2); + + // odd part + let i3 = in_vector[i + 3]; + let i1 = in_vector[i + 1]; + + let p5 = wm(wa(i3, i1), f2f(1.175875602)); + + let p1 = wa(p5, wm(i1, -3685)); + let p2 = wa(p5, wm(i3, -10497)); + + let t3 = wa(p5, wm(i1, 867)); + let t2 = wa(p5, wm(i3, -5945)); + + let t1 = wa(p2, wm(i1, -1597)); + let t0 = wa(p1, wm(i3, -8034)); + + let out: &mut [i16; 8] = out_vector + .get_mut(pos..pos + 8) + .unwrap() + .try_into() + .unwrap(); + + out.copy_from_slice(&[ + clamp(wa(x0, t3) >> 17), + clamp(wa(x1, t2) >> 17), + clamp(wa(x2, t1) >> 17), + clamp(wa(x3, t0) >> 17), + clamp(ws(x3, t0) >> 17), + clamp(ws(x2, t1) >> 17), + clamp(ws(x1, t2) >> 17), + clamp(ws(x0, t3) >> 17), + ]); + + pos += stride; + } + + in_vector[32..36].fill(0); + in_vector[40..44].fill(0); + in_vector[48..52].fill(0); + in_vector[56..60].fill(0); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/idct.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/idct.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Routines for IDCT +//! +//! Essentially we provide 2 routines for IDCT, a scalar implementation and a not super optimized +//! AVX2 one, i'll talk about them here. +//! +//! There are 2 reasons why we have the avx one +//! 1. No one compiles with -C target-features=avx2 hence binaries won't probably take advantage(even +//! if it exists). +//! 2. AVX employs zero short circuit in a way the scalar code cannot employ it. +//! - AVX does this by checking for MCU's whose 63 AC coefficients are zero and if true, it writes +//! values directly, if false, it goes the long way of calculating. +//! - Although this can be trivially implemented in the scalar version, it generates code +//! I'm not happy width(scalar version that basically loops and that is too many branches for me) +//! The avx one does a better job of using bitwise or's with (`_mm256_or_si256`) which is magnitudes of faster +//! than anything I could come up with +//! +//! The AVX code also has some cool transpose_u16 instructions which look so complicated to be cool +//! (spoiler alert, i barely understand how it works, that's why I credited the owner). +//! +#![allow( + clippy::excessive_precision, + clippy::unreadable_literal, + clippy::module_name_repetitions, + unused_parens, + clippy::wildcard_imports +)] + +use zune_core::log::debug; +use zune_core::options::DecoderOptions; + +use crate::decoder::IDCTPtr; +use crate::idct::scalar::{idct_int, idct_int_1x1}; + +#[cfg(feature = "x86")] +pub mod avx2; +#[cfg(feature = "neon")] +pub mod neon; + +pub mod scalar; + +/// Choose an appropriate IDCT function +#[allow(unused_variables)] +pub fn choose_idct_func(options: &DecoderOptions) -> IDCTPtr { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + if options.use_avx2() { + debug!("Using vector integer IDCT"); + return |a: &mut [i32; 64], b: &mut [i16], c: usize| { + // SAFETY: `options.use_avx2()` only returns true if avx2 is supported. + unsafe { avx2::idct_avx2(a,b,c) } + }; + } + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + { + if options.use_neon() { + debug!("Using vector integer IDCT"); + return |a: &mut [i32; 64], b: &mut [i16], c: usize| { + // SAFETY: `options.use_neon()` only returns true if neon is supported. + unsafe { neon::idct_neon(a,b,c) } + }; + } + } + debug!("Using scalar integer IDCT"); + // use generic one + return idct_int; +} + +/// Choose a function to implement 4x4 IDCT. +/// +/// These functions get the same input but have an extra contract: Only the first 4x4 block of +/// coefficients are non-zero. All other entries are zeroed. +/// +/// **The callee must uphold that contract on return** +pub fn choose_idct_4x4_func(_options: &DecoderOptions) -> IDCTPtr { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + if _options.use_avx2() { + debug!("Using vector integer IDCT"); + return |a: &mut [i32; 64], b: &mut [i16], c: usize| { + // SAFETY: `options.use_avx2()` only returns true if avx2 is supported. + unsafe { avx2::idct_avx2_4x4(a,b,c) } + }; + } + } + + scalar::idct4x4 +} + +pub fn choose_idct_1x1_func(_: &DecoderOptions) -> IDCTPtr { + // These are simple stores, no alternative implementation for now + idct_int_1x1 +} + +#[cfg(test)] +#[allow(unreachable_code)] +#[allow(dead_code)] +mod tests { + use super::*; + + #[test] + fn idct_test0() { + let stride = 8; + let mut coeff = [10; 64]; + let mut coeff2 = [10; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + let idct_func = choose_idct_func(&DecoderOptions::new_fast()); + idct_func(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test1() { + let stride = 8; + let mut coeff = [14; 64]; + let mut coeff2 = [14; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + let idct_func = choose_idct_func(&DecoderOptions::new_fast()); + idct_func(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test2() { + let stride = 8; + let mut coeff = [0; 64]; + coeff[0] = 255; + coeff[63] = -256; + let mut coeff2 = coeff; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + let idct_func = choose_idct_func(&DecoderOptions::new_fast()); + idct_func(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_zeros() { + let stride = 8; + let mut coeff = [0; 64]; + let mut coeff2 = [0; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + let idct_func = choose_idct_func(&DecoderOptions::new_fast()); + idct_func(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn idct_4x4() { + #[rustfmt::skip] + const A: [i32; 32] = [ + -254, -7, 0, 0, 0, 0, 0, 0, + 7, 0, -30, 32, 0, 0, 0, 0, + 7, 0, -30, 32, 0, 0, 0, 0, + 7, 0, -30, 32, 0, 0, 0, 0, + ]; + + let v: Vec = vec![ + choose_idct_func(&DecoderOptions::new_safe()), + choose_idct_4x4_func(&DecoderOptions::new_safe()), + choose_idct_func(&DecoderOptions::new_fast()), + choose_idct_4x4_func(&DecoderOptions::new_fast()), + ]; + let dct_names = vec![ + "safe idct", + "safe idct 4x4", + "fast idct", + "fast idct 4x4", + ]; + + let mut color = vec![]; + + for idct in v { + let mut a = [0i32; 64]; + a[..32].copy_from_slice(&A); + let mut b = [0i16; 64]; + + idct(&mut a, &mut b, 8); + + color.push(b); + } + + for (wnd, name) in color.windows(2).zip(&dct_names) { + let [a, b] = wnd else { unreachable!() }; + assert_eq!(a, b, "{name}"); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!This crate provides a library for decoding valid +//! ITU-T Rec. T.851 (09/2005) ITU-T T.81 (JPEG-1) or JPEG images. +//! +//! +//! +//! # Features +//! - SSE and AVX accelerated functions to speed up certain decoding operations +//! - FAST and accurate 32 bit IDCT algorithm +//! - Fast color convert functions +//! - RGBA and RGBX (4-Channel) color conversion functions +//! - YCbCr to Luma(Grayscale) conversion. +//! +//! # Usage +//! Add zune-jpeg to the dependencies in the project Cargo.toml +//! +//! ```toml +//! [dependencies] +//! zune_jpeg = "0.5" +//! ``` +//! # Examples +//! +//! ## Decode a JPEG file with default arguments. +//!```no_run +//! use std::fs::read; +//! use std::io::BufReader; +//! use zune_jpeg::JpegDecoder; +//! let file_contents = BufReader::new(std::fs::File::open("a_jpeg.file").unwrap()); +//! let mut decoder = JpegDecoder::new(file_contents); +//! let mut pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Migrating from version 0.4-- +//! +//! ### Motivation +//! zune v 0.5 reworks mainly the internal architecture of how we perform I/O +//! ,before the decoder accepted byte slices that represent the whole data as contiguous +//! but that was not ideal for all use cases, increasing memory e.g on massive files that had +//! to be read to memory. +//! +//! With v 0.5 a new I/O system is introduced, which generally introduces mechanisms to process +//! `std::io::Read + std::io::Seek` type of data feeds, (but which works in no-std), which means... +//! +//! ### What changes +//! +//! I/O code that looked like this +//! +//!```ignore +//! use zune_core::colorspace::ColorSpace; +//! use zune_jpeg::JpegDecoder; +//! // Read file into memory +//! let image = std::fs::read("image.jpg").unwrap(); +//! // Make a decoder from the slice +//! let mut decoder = JpegDecoder::new(&image); +//! // decode +//! decoder.decode().unwrap(); +//! ``` +//! +//! Now can be rewritten in two ways. +//! +//! 1. File I/O (Using bufreader) +//! +//!```no_run +//! use std::io::BufReader; +//! use zune_core::colorspace::ColorSpace; +//! use zune_jpeg::JpegDecoder; +//! +//! let image = BufReader::new(std::fs::File::open("image.jpg").unwrap()); +//! let mut decoder = JpegDecoder::new(image); +//! // decode +//! decoder.decode().unwrap(); +//! ``` +//! +//! 2. Reading to memory (but wrapping it in a Cursor like object) +//!```no_run +//! use zune_core::bytestream::ZCursor; +//! use zune_jpeg::JpegDecoder; +//! +//! let image_data =std::fs::read("image.jpg").unwrap(); +//! // Alternatively, you can use std::io::Cursor, +//! // but it is better speed wise to use ZCursor, and it also works in +//! // no-std environments +//! let mut cursor = ZCursor::new(image_data); +//! // use the wrapped item +//! let mut decoder = JpegDecoder::new(cursor); +//! // decode +//! decoder.decode().unwrap(); +//! ``` +//! +//! 3. Anything that implements [ZByteReaderTrait](zune_core::bytestream::traits::ZByteReaderTrait) +//! +//! ## Decode a JPEG file to RGBA format +//! +//! - Other (limited) supported formats are and BGR, BGRA +//! +//!```no_run +//! use zune_core::bytestream::ZCursor; +//! use zune_core::colorspace::ColorSpace; +//! use zune_core::options::DecoderOptions; +//! use zune_jpeg::JpegDecoder; +//! +//! let mut options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::RGBA); +//! +//! let mut decoder = JpegDecoder::new_with_options(ZCursor::new(&[]),options); +//! let pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Decode an image and get its width and height. +//!```no_run +//! use zune_core::bytestream::ZCursor; +//! use zune_jpeg::JpegDecoder; +//! +//! let mut decoder = JpegDecoder::new(ZCursor::new(&[])); +//! decoder.decode_headers().unwrap(); +//! let image_info = decoder.info().unwrap(); +//! println!("{},{}",image_info.width,image_info.height) +//! ``` +//! # Crate features. +//! This crate tries to be as minimal as possible while being extensible +//! enough to handle the complexities arising from parsing different types +//! of jpeg images. +//! +//! Safety is a top concern that is why we provide both static ways to disable unsafe code, +//! disabling x86 feature, and dynamic ,by using [`DecoderOptions::set_use_unsafe(false)`], +//! both of these disable platform specific optimizations, which reduce the speed of decompression. +//! +//! Please do note that careful consideration has been taken to ensure that the unsafe paths +//! are only unsafe because they depend on platform specific intrinsics, hence no need to disable them +//! +//! The crate tries to decode as many images as possible, as a best effort, even those violating the standard +//! , this means a lot of images may get silent warnings and wrong output, but if you are sure you will be handling +//! images that follow the spec, set `ZuneJpegOptions::set_strict` to true. +//! +//![`DecoderOptions::set_use_unsafe(false)`]: https://docs.rs/zune-core/latest/zune_core/options/struct.DecoderOptions.html#method.set_use_unsafe + +#![warn( + clippy::correctness, + clippy::perf, + clippy::pedantic, + clippy::inline_always, + clippy::missing_errors_doc, + clippy::panic +)] +#![allow( + clippy::needless_return, + clippy::similar_names, + clippy::inline_always, + clippy::similar_names, + clippy::doc_markdown, + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc +)] +// no_std compatibility +#![deny(clippy::std_instead_of_alloc, clippy::alloc_instead_of_core)] +#![cfg_attr(not(any(feature = "x86", feature = "neon")), forbid(unsafe_code))] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "portable_simd", feature(portable_simd))] +#![macro_use] +extern crate alloc; +extern crate core; + +pub use zune_core; + +pub use crate::decoder::{ImageInfo, JpegDecoder}; +pub use crate::marker::Marker; +mod bitstream; +mod color_convert; +mod components; +mod decoder; +pub mod errors; +mod headers; +mod huffman; +#[cfg(not(fuzzing))] +mod idct; +#[cfg(fuzzing)] +pub mod idct; +mod marker; +mod mcu; +mod mcu_prog; +mod misc; +mod unsafe_utils; +mod unsafe_utils_avx2; +mod unsafe_utils_neon; +mod upsampler; +mod worker; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/marker.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/marker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/marker.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/marker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow(clippy::upper_case_acronyms)] + +/// JPEG Markers +/// +/// **NOTE** This doesn't cover all markers, just the ones zune-jpeg supports. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Marker { + /// Start Of Frame markers + /// + /// - SOF(0): Baseline DCT (Huffman coding) + /// - SOF(1): Extended sequential DCT (Huffman coding) + /// - SOF(2): Progressive DCT (Huffman coding) + /// - SOF(3): Lossless (sequential) (Huffman coding) + /// - SOF(5): Differential sequential DCT (Huffman coding) + /// - SOF(6): Differential progressive DCT (Huffman coding) + /// - SOF(7): Differential lossless (sequential) (Huffman coding) + /// - SOF(9): Extended sequential DCT (arithmetic coding) + /// - SOF(10): Progressive DCT (arithmetic coding) + /// - SOF(11): Lossless (sequential) (arithmetic coding) + /// - SOF(13): Differential sequential DCT (arithmetic coding) + /// - SOF(14): Differential progressive DCT (arithmetic coding) + /// - SOF(15): Differential lossless (sequential) (arithmetic coding) + SOF(u8), + /// Define Huffman table(s) + DHT, + /// Define arithmetic coding conditioning(s) + DAC, + /// Restart with modulo 8 count `m` + RST(u8), + /// Start of image + SOI, + /// End of image + EOI, + /// Start of scan + SOS, + /// Define quantization table(s) + DQT, + /// Define number of lines + DNL, + /// Define restart interval + DRI, + /// Reserved for application segments + APP(u8), + /// Comment + COM, + /// Unknown markers + UNKNOWN(u8) +} + +impl Marker { + pub fn from_u8(n: u8) -> Option { + use self::Marker::{APP, COM, DAC, DHT, DNL, DQT, DRI, EOI, RST, SOF, SOI, SOS, UNKNOWN}; + + match n { + 0xFE => Some(COM), + 0xC0 => Some(SOF(0)), + 0xC1 => Some(SOF(1)), + 0xC2 => Some(SOF(2)), + 0xC4 => Some(DHT), + 0xCC => Some(DAC), + 0xD0 => Some(RST(0)), + 0xD1 => Some(RST(1)), + 0xD2 => Some(RST(2)), + 0xD3 => Some(RST(3)), + 0xD4 => Some(RST(4)), + 0xD5 => Some(RST(5)), + 0xD6 => Some(RST(6)), + 0xD7 => Some(RST(7)), + 0xD8 => Some(SOI), + 0xD9 => Some(EOI), + 0xDA => Some(SOS), + 0xDB => Some(DQT), + 0xDC => Some(DNL), + 0xDD => Some(DRI), + 0xE0 => Some(APP(0)), + 0xE1 => Some(APP(1)), + 0xE2 => Some(APP(2)), + 0xED => Some(APP(13)), + 0xEE => Some(APP(14)), + _ => Some(UNKNOWN(n)) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/mcu.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/mcu.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::vec::Vec; +use alloc::{format, vec}; +use core::cmp::min; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::colorspace::ColorSpace::Luma; +use zune_core::log::{error, trace, warn}; + +use crate::bitstream::BitStream; +use crate::components::SampleRatios; +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::marker::Marker; +use crate::mcu_prog::get_marker; +use crate::misc::{calculate_padded_width, setup_component_params}; +use crate::worker::{color_convert, upsample}; +use crate::JpegDecoder; + +/// The size of a DC block for a MCU. + +pub const DCT_BLOCK: usize = 64; + +impl JpegDecoder { + /// Check for existence of DC and AC Huffman Tables + pub(crate) fn check_tables(&self) -> Result<(), DecodeErrors> { + // check that dc and AC tables exist outside the hot path + for component in &self.components { + let _ = &self + .dc_huffman_tables + .get(component.dc_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman DC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No DC table for component {:?}", + component.component_id + )) + })?; + + let _ = &self + .ac_huffman_tables + .get(component.ac_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman AC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No AC table for component {:?}", + component.component_id + )) + })?; + } + Ok(()) + } + + /// Decode MCUs and carry out post processing. + /// + /// This is the main decoder loop for the library, the hot path. + /// + /// Because of this, we pull in some very crazy optimization tricks hence readability is a pinch + /// here. + #[allow( + clippy::similar_names, + clippy::too_many_lines, + clippy::cast_possible_truncation + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_baseline( + &mut self, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + // check dc and AC tables + self.check_tables()?; + + let (mut mcu_width, mut mcu_height); + + if self.is_interleaved { + // set upsampling functions + self.set_upsampling()?; + + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided bu 8. + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + + self.reset_params(); + + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + let width = usize::from(self.info.width); + + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut stream = BitStream::new(); + let mut tmp = [0_i32; DCT_BLOCK]; + + let comp_len = self.components.len(); + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || comp_len == 4 + // Special colorspace + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + // If all components are contained in the first scan of MCUs, then we can process into + // (upsampled) pixels immediately after each MCU, for convenience we use each row of MCUS. + // Otherwise, we must first wait until following SOS provide the remaining components. + let all_components_in_first_scan = usize::from(self.num_scans) == self.components.len(); + let mut progressive_mcus: [Vec; 4] = core::array::from_fn(|_| vec![]); + + if !all_components_in_first_scan { + for (component, mcu) in self.components.iter().zip(&mut progressive_mcus) { + let len = mcu_width + * component.vertical_sample + * component.horizontal_sample + * mcu_height + * 64; + *mcu = vec![0; len]; + } + } + + let mut pixels_written = 0; + + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + + 'sos: loop { + trace!( + "Baseline decoding of components: {:?}", + &self.z_order[..usize::from(self.num_scans)] + ); + + trace!("Decoding MCU width: {mcu_width}, height: {mcu_height}"); + + for i in 0..mcu_height { + if stream.overread_by > 0 { + pixels.get_mut(pixels_written..).map(|v| v.fill(128)); + if self.options.strict_mode() { + return Err(DecodeErrors::FormatStatic("Premature end of buffer")); + }; + + error!("Premature end of buffer"); + break; + } + + // decode a whole MCU width, + // this takes into account interleaved components. + let terminate = if all_components_in_first_scan { + self.decode_mcu_width::( + mcu_width, + i, + &mut tmp, + &mut stream, + &mut progressive_mcus + )? + } else { + /* NB: (cae). This code was added due to the issue at https://github.com/etemesi254/zune-image/issues/277 + * + * There is a particular set of images that interleave the start of scan (SOS) with the MCU, + * E.g if it's a three component image, we have SOS->MCU ->SOS->MCU ->SOS->MCU + * which presents a problem on decoding, we need to buffer the whole image before continuing since + * we won't have a row containing all the component data which will be needed e.g for color conversion. + * + * The mechanisms is that we decode the whole image upfront, which goes against the normal + * routine of decoding MCU width , so this requires more memory upfront than initial routines + * but it is a single image out of the many corpuses that exist, so its fine. + * (image in test-images/jpeg/sos_news.jpeg) + + * Code contributed by Aurelia Molzer (https://github.com/197g) + + * + */ + + self.decode_mcu_width::( + mcu_width, + i, + &mut tmp, + &mut stream, + &mut progressive_mcus + )? + }; + + // process that width up until it's impossible. This is faster than allocation the + // full components, which we skipped earlier. + if all_components_in_first_scan { + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + + match terminate { + McuContinuation::Ok => {} + McuContinuation::AnotherSos if all_components_in_first_scan => { + warn!("More than one SOS despite already having all components"); + return Ok(()); + } + McuContinuation::AnotherSos => continue 'sos, + McuContinuation::Terminate => { + warn!("Got terminate signal, will not process further"); + pixels.get_mut(pixels_written..).map(|v| v.fill(128)); + return Ok(()); + } + } + } + + // Breaks if we get here, looping only if we have restarted, i.e. found another SOS and + // continued at `'sos'. + break; + } + + if !all_components_in_first_scan { + self.finish_baseline_decoding(&progressive_mcus, mcu_width, pixels)?; + } + + // it may happen that some images don't have the whole buffer + // so we can't panic in case of that + // assert_eq!(pixels_written, pixels.len()); + + // For UHD usecases that tie two images separating them with EOI and + // SOI markers, it may happen that we do not reach this image end of image + // So this ensures we reach it + // Ensure we read EOI + if !stream.seen_eoi { + let marker = get_marker(&mut self.stream, &mut stream); + match marker { + Ok(_m) => { + trace!("Found marker {:?}", _m); + } + Err(_) => { + // ignore error + } + } + } + + trace!("Finished decoding image"); + + Ok(()) + } + + /// Process all MCUs when baseline decoding has been processing them component-after-component. + /// For simplicity this assembles the dequantized blocks in the order that the post processing + /// of an interleaved baseline decoding would use. + #[allow(clippy::too_many_lines)] + #[allow(clippy::cast_sign_loss)] + pub(crate) fn finish_baseline_decoding( + &mut self, block: &[Vec; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + let mcu_height = self.mcu_y; + + // Size of our output image(width*height) + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let width = usize::from(self.info.width); + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Mark only needed components for computing output colors. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || self.input_colorspace == ColorSpace::YCCK + || self.input_colorspace == ColorSpace::CMYK + { + comp.needed = true; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + // dequantize and idct have been performed, only color convert. + for i in 0..mcu_height { + // All the data is already in the right order, we just need to be able to pass it to + // the post_process & upsample method. That expects all the data to be stored as one + // row of MCUs in each component's `raw_coeff`. + 'component: for (position, component) in &mut self.components.iter_mut().enumerate() { + if !component.needed { + continue 'component; + } + + // step is the number of pixels this iteration wil be handling + // Given by the number of mcu's height and the length of the component block + // Since the component block contains the whole channel as raw pixels + // we this evenly divides the pixels into MCU blocks + // + // For interleaved images, this gives us the exact pixels comprising a whole MCU + // block + let step = block[position].len() / mcu_height; + + // where we will be reading our pixels from. + let slice = &block[position][i * step..][..step]; + let temp_channel = &mut component.raw_coeff; + temp_channel[..step].copy_from_slice(slice); + } + + // process that whole stripe of MCUs + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + + return Ok(()); + } + + fn decode_mcu_width( + &mut self, mcu_width: usize, mcu_height: usize, tmp: &mut [i32; 64], + stream: &mut BitStream, progressive: &mut [Vec; 4] + ) -> Result { + let is_one_by_one = !self.scan_subsampled; + + // The definition of MCU depends on the sampling factor of involved scans. When components + // have different factors then each Minimal-Coding-Unit is the least common multiple such + // that we have an integer number of blocks from each component. But the decoding of these + // components differs from it otherwise, we need an inner loop with a dynamic amount of + // coefficients per component, whereas otherwise we have exactly one block of coefficients + // encoded for each component in the bitstream order. + // + // We statically specialize on this to improve code generation of the common case a little + // bit. We could also special case common sub-sampling cases but be mindful of code bloat. + if is_one_by_one { + self.inner_decode_mcu_width::( + mcu_width, + mcu_height, + tmp, + stream, + progressive + ) + } else { + self.inner_decode_mcu_width::( + mcu_width, + mcu_height, + tmp, + stream, + progressive + ) + } + } + + // Inline-never ensures we do get this function optimize on its own, into two different + // versions, without the optimizer tripping up over the complexity that comes with the + // constant folding. And constant folding is quite important for performance here as + // when `not SAMPLED` then the inner loop has exactly one iteration per component in + // the scan. The difference was ~1% or a bit more. + fn inner_decode_mcu_width( + &mut self, mcu_width: usize, mcu_height: usize, tmp: &mut [i32; 64], + stream: &mut BitStream, progressive: &mut [Vec; 4] + ) -> Result { + let z_order = self.z_order; + let z_scans = &z_order[..usize::from(self.num_scans)]; + + // How much of the head of `tmp` was written by the last MCU decoding? We only check for + // two different cases and not all possible outcomes as this is only used to optimize the + // bytes written in `fill`. Since the clobber happens in UNZIGZAG order we'd be straddling + // most cache lines anyways even if we did a partial write with the exact length of the + // coefficient data which was written into `tmp`. + let mut clobber_more_than_4x4 = true; + + for j in 0..mcu_width { + // iterate over components + for &k in z_scans { + // we made this loop body massive due to several different paths that depend on + // static conditions. Note we (potentially) call into other functions so the + // compiler will not unroll anything here anyways. The gains from separating + // differently optimized loop bodies are much greater than a single additional jump + // here. + let component = &mut self.components[k]; + + let dc_table = self.dc_huffman_tables[component.dc_huff_table % MAX_COMPONENTS] + .as_ref() + .ok_or(DecodeErrors::FormatStatic("DC table not found"))?; + + let ac_table = self.ac_huffman_tables[component.ac_huff_table % MAX_COMPONENTS] + .as_ref() + .ok_or(DecodeErrors::FormatStatic("AC table not found"))?; + + let qt_table = &component.quantization_table; + let channel = if PROGRESSIVE { + let offset = + mcu_height * component.width_stride * 8 * component.vertical_sample; + &mut progressive[k][offset..] + } else { + &mut component.raw_coeff + }; + + let component_samples_needed = component.needed; + + // If image is interleaved iterate over scan components, + // otherwise if it-s non-interleaved, these routines iterate in + // trivial scanline order(Y,Cb,Cr) + // + // Turn the bounds into a compile time constant for a common special case. This + // allows the compiler to unroll the loop and then do a bunch of interleaving. + let v_step = if SAMPLED { 0..component.vertical_sample } else { 0..1 }; + + for v_samp in v_step { + let h_step = if SAMPLED { 0..component.horizontal_sample } else { 0..1 }; + + for h_samp in h_step { + let result = if component_samples_needed { + // Fill the array with zeroes, decode_mcu_block expects + // a zero based array. Clobber is in zig-zag order though. + // Writing consecutive entries is basically free in terms + // of memory throughput so we opt for a larger power of + // two which lets the compiler turn this into a repeated + // write of a zeroed vector register, which does not have + // any branches, instead of a more difficult pattern where + // we attempt to overwrite exactly one coefficient. + let clobber_len = if !clobber_more_than_4x4 { 32 } else { 64 }; + + tmp[..clobber_len].fill(0); + + stream.decode_mcu_block( + &mut self.stream, + dc_table, + ac_table, + qt_table, + tmp, + &mut component.dc_pred + ) + } else { + // We do not touch tmp so there is no need to reset it. + stream.discard_mcu_block(&mut self.stream, dc_table, ac_table) + }; + + // If an error occurs we can either propagate it + // as an error or print it and call terminate. + // + // This allows even corrupt images to render something, + // even if its bad, matching browsers. + // + // See example in https://github.com/etemesi254/zune-image/issues/293 + let len = if let Ok(len) = result { + len + } else { + // result.is_err() + return if self.options.strict_mode() { + Err(result.err().unwrap()) + } else { + error!("{}", result.err().unwrap()); + Ok(McuContinuation::Terminate) + }; + }; + + if component_samples_needed { + // tmp was only written partially, note that len is in ZigZag order. + clobber_more_than_4x4 = len > 10; + + let idct_position = { + // derived from stb and rewritten for my tastes + let c2 = v_samp * 8; + let c3 = ((j * component.horizontal_sample) + h_samp) * 8; + + component.width_stride * c2 + c3 + }; + + let idct_pos = channel.get_mut(idct_position..).unwrap(); + + if len <= 1 { + (self.idct_1x1_func)(tmp, idct_pos, component.width_stride); + } else if len <= 10 { + (self.idct_4x4_func)(tmp, idct_pos, component.width_stride); + } else { + // call idct. + (self.idct_func)(tmp, idct_pos, component.width_stride); + } + } + } + } + } + + self.todo = self.todo.wrapping_sub(1); + + if self.todo == 0 { + self.handle_rst_main(stream)?; + continue; + } + + if stream.marker.is_some() && stream.bits_left == 0 { + break; + } + } + + self.check_stream_marker_after_mcu_width(stream) + } + + fn check_stream_marker_after_mcu_width( + &mut self, stream: &mut BitStream + ) -> Result { + // After all interleaved components, that's an MCU + // handle stream markers + // + // In some corrupt images, it may occur that header markers occur in the stream. + // The spec EXPLICITLY FORBIDS this, specifically, in + // routine F.2.2.5 it says + // `The only valid marker which may occur within the Huffman coded data is the RSTm marker.` + // + // But libjpeg-turbo allows it because of some weird reason. so I'll also + // allow it because of some weird reason. + if let Some(m) = stream.marker { + if m == Marker::EOI { + // acknowledge and ignore EOI marker. + stream.marker.take(); + trace!("Found EOI marker"); + // Google Introduced the Ultra-HD image format which is basically + // stitching two images into one container. + // They basically separate two images via a EOI and SOI marker + // so let's just ensure if we ever see EOI, we never read past that + // ever. + // https://github.com/google/libultrahdr + stream.seen_eoi = true; + } else if let Marker::RST(_) = m { + //debug_assert_eq!(self.todo, 0); + if self.todo == 0 { + self.handle_rst(stream)?; + } + } else if let Marker::SOS = m { + self.parse_marker_inner(m)?; + stream.marker.take(); + stream.reset(); + trace!("Found SOS marker"); + return Ok(McuContinuation::AnotherSos); + } else { + if self.options.strict_mode() { + return Err(DecodeErrors::Format(format!( + "Marker {m:?} found where not expected" + ))); + } + error!( + "Marker `{:?}` Found within Huffman Stream, possibly corrupt jpeg", + m + ); + + self.parse_marker_inner(m)?; + stream.marker.take(); + stream.reset(); + return Ok(McuContinuation::Terminate); + } + } + + Ok(McuContinuation::Ok) + } + + // handle RST markers. + // No-op if not using restarts + // this routine is shared with mcu_prog + #[cold] + pub(crate) fn handle_rst(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> { + self.todo = self.restart_interval; + + if let Some(marker) = stream.marker { + // Found a marker + // Read stream and see what marker is stored there + match marker { + Marker::RST(_) => { + // reset stream + stream.reset(); + // Initialize dc predictions to zero for all components + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + // Start iterating again. from position. + } + Marker::EOI => { + // silent pass + } + _ => { + return Err(DecodeErrors::MCUError(format!( + "Marker {marker:?} found in bitstream, possibly corrupt jpeg" + ))); + } + } + } + Ok(()) + } + #[allow(clippy::too_many_lines, clippy::too_many_arguments)] + pub(crate) fn post_process( + &mut self, pixels: &mut [u8], i: usize, mcu_height: usize, width: usize, + padded_width: usize, pixels_written: &mut usize, upsampler_scratch_space: &mut [i16] + ) -> Result<(), DecodeErrors> { + let out_colorspace_components = self.options.jpeg_get_out_colorspace().num_components(); + + let mut px = *pixels_written; + // indicates whether image is vertically up-sampled + let is_vertically_sampled = self + .components + .iter() + .any(|c| c.sample_ratio == SampleRatios::HV || c.sample_ratio == SampleRatios::V); + + let mut comp_len = self.components.len(); + + // If we are moving from YCbCr -> Luma, we do not allocate storage for other components, so we + // will panic when we are trying to read samples, so for that case, + // hardcode it so that we don't panic when doing + // *samp = &samples[j][pos * padded_width..(pos + 1) * padded_width] + if out_colorspace_components < comp_len && self.options.jpeg_get_out_colorspace() == Luma { + comp_len = out_colorspace_components; + } + let mut color_conv_function = + |num_iters: usize, samples: [&[i16]; 4]| -> Result<(), DecodeErrors> { + for (pos, output) in pixels[px..] + .chunks_exact_mut(width * out_colorspace_components) + .take(num_iters) + .enumerate() + { + let mut raw_samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + // iterate over each line, since color-convert needs only + // one line + for (j, samp) in raw_samples.iter_mut().enumerate().take(comp_len) { + let temp = &samples[j].get(pos * padded_width..(pos + 1) * padded_width); + if temp.is_none() { + return Err(DecodeErrors::FormatStatic("Missing samples")); + } + *samp = temp.unwrap(); + } + color_convert( + &raw_samples, + self.color_convert_16, + self.input_colorspace, + self.options.jpeg_get_out_colorspace(), + output, + width, + padded_width + )?; + px += width * out_colorspace_components; + } + Ok(()) + }; + + let comps = &mut self.components[..]; + + if self.is_interleaved && self.options.jpeg_get_out_colorspace() != ColorSpace::Luma { + for comp in comps.iter_mut() { + upsample( + comp, + mcu_height, + i, + upsampler_scratch_space, + is_vertically_sampled + )?; + } + + if is_vertically_sampled { + if i > 0 { + // write the last line, it wasn't up-sampled as we didn't have row_down + // yet + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = &component.first_row_upsample_dest; + } + + // ensure length matches for all samples + let _first_len = samples[0].len(); + + // This was a good check, but can be caused to panic, esp on invalid/corrupt images. + // See one in issue https://github.com/etemesi254/zune-image/issues/262, so for now + // we just ignore and generate invalid images at the end. + + // + // + // for samp in samples.iter().take(comp_len) { + // assert_eq!(first_len, samp.len()); + // } + let num_iters = self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } + + // After up-sampling the last row, save any row that can be used for + // a later up-sampling, + // + // E.g the Y sample is not sampled but we haven't finished upsampling the last row of + // the previous mcu, since we don't have the down row, so save it + for component in comps.iter_mut() { + if component.sample_ratio != SampleRatios::H { + // We don't care about H sampling factors, since it's copied in the workers function + + // copy last row to be used for the next color conversion + let size = component.vertical_sample + * component.width_stride + * component.sample_ratio.sample(); + + let last_bytes = + component.raw_coeff.rchunks_exact_mut(size).next().unwrap(); + + component + .first_row_upsample_dest + .copy_from_slice(last_bytes); + } + } + } + + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = if component.sample_ratio == SampleRatios::None { + &component.raw_coeff + } else { + &component.upsample_dest + }; + } + + // we either do 7 or 8 MCU's depending on the state, this only applies to + // vertically sampled images + // + // for rows up until the last MCU, we do not upsample the last stride of the MCU + // which means that the number of iterations should take that into account is one less the + // up-sampled size + // + // For the last MCU, we upsample the last stride, meaning that if we hit the last MCU, we + // should sample full raw coeffs + let is_last_considered = is_vertically_sampled && (i != mcu_height.saturating_sub(1)); + + let num_iters = (8 - usize::from(is_last_considered)) * self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } else { + let mut channels_ref: [&[i16]; MAX_COMPONENTS] = [&[]; MAX_COMPONENTS]; + + self.components + .iter() + .enumerate() + .for_each(|(pos, x)| channels_ref[pos] = &x.raw_coeff); + + if let SampleRatios::Generic(_, v) = self.sub_sample_ratio { + color_conv_function(8 * v * self.coeff, channels_ref)?; + } else { + color_conv_function(8 * self.coeff, channels_ref)?; + } + } + + *pixels_written = px; + Ok(()) + } +} + +enum McuContinuation { + Ok, + AnotherSos, + Terminate +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/mcu_prog.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu_prog.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/mcu_prog.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/mcu_prog.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Routines for progressive decoding +/* +This file is needlessly complicated, + +It is that way to ensure we don't burn memory anyhow + +Memory is a scarce resource in some environments, I would like this to be viable +in such environments + +Half of the complexity comes from the jpeg spec, because progressive decoding, +is one hell of a ride. + +*/ +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; +use core::cmp::min; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, error, warn}; + +use crate::bitstream::BitStream; +use crate::components::SampleRatios; +use crate::decoder::{JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::headers::parse_sos; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::{calculate_padded_width, setup_component_params}; + +impl JpegDecoder { + /// Decode a progressive image + /// + /// This routine decodes a progressive image, stopping if it finds any error. + #[allow( + clippy::needless_range_loop, + clippy::cast_sign_loss, + clippy::redundant_else, + clippy::too_many_lines + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_progressive( + &mut self, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + let mut mcu_height; + + // memory location for decoded pixels for components + let mut block: [Vec; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]]; + let mut mcu_width; + + let mut seen_scans = 1; + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + self.reset_params(); + } + + if self.is_interleaved { + // this helps us catch component errors. + self.set_upsampling()?; + } + if self.is_interleaved { + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + mcu_width = (self.info.width as usize + 7) / 8; + mcu_height = (self.info.height as usize + 7) / 8; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + mcu_width *= 64; + + for i in 0..self.input_colorspace.num_components() { + let comp = &self.components[i]; + let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height; + + block[i] = vec![0; len]; + } + + let mut stream = BitStream::new_progressive(self.succ_low, self.spec_start, self.spec_end); + + // there are multiple scans in the stream, this should resolve the first scan + let result = self.parse_entropy_coded_data(&mut stream, &mut block); + + if result.is_err() { + return if self.options.strict_mode() { + Err(result.err().unwrap()) + } else { + error!("{}", result.err().unwrap()); + // Go process it and return as much as we can, exiting here + return self.finish_progressive_decoding(&block, pixels); + }; + } + + // extract marker + let mut marker = stream + .marker + .take() + .ok_or(DecodeErrors::FormatStatic("Marker missing where expected"))?; + + // if marker is EOI, we are done, otherwise continue scanning. + // + // In case we have a premature image, we print a warning or return + // an error, depending on the strictness of the decoder, so there + // is that logic to handle too + 'eoi: while marker != Marker::EOI { + match marker { + Marker::SOS => { + parse_sos(self)?; + + stream.update_progressive_params( + self.succ_high, + self.succ_low, + self.spec_start, + self.spec_end + ); + // after every SOS, marker, parse data for that scan. + let result = self.parse_entropy_coded_data(&mut stream, &mut block); + + // Do not error out too fast, allows the decoder to continue as much as possible + // even after errors + if result.is_err() { + return if self.options.strict_mode() { + Err(result.err().unwrap()) + } else { + error!("{}", result.err().unwrap()); + break 'eoi; + }; + } + // extract marker, might either indicate end of image or we continue + // scanning(hence the continue statement to determine). + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + seen_scans += 1; + if seen_scans > self.options.jpeg_get_max_scans() { + return Err(DecodeErrors::Format(format!( + "Too many scans, exceeded limit of {}", + self.options.jpeg_get_max_scans() + ))); + } + + stream.reset(); + continue 'eoi; + } + Err(msg) => { + if self.options.strict_mode() { + return Err(msg); + } + error!("{:?}", msg); + break 'eoi; + } + } + } + Marker::RST(_n) => { + self.handle_rst(&mut stream)?; + } + _ => { + self.parse_marker_inner(marker)?; + } + } + + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + } + Err(e) => { + if self.options.strict_mode() { + return Err(e); + } + error!("{}", e); + // If we can't get the marker, just break away + // allows us to decode some corrupt images + // e.g https://github.com/etemesi254/zune-image/issues/294 + break 'eoi; + } + } + } + + self.finish_progressive_decoding(&block, pixels) + } + + /// Reset progressive parameters + fn reset_prog_params(&mut self, stream: &mut BitStream) { + stream.reset(); + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + + // Also reset JPEG restart intervals + self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX }; + } + + #[allow(clippy::too_many_lines, clippy::cast_sign_loss)] + fn parse_entropy_coded_data( + &mut self, stream: &mut BitStream, buffer: &mut [Vec; MAX_COMPONENTS] + ) -> Result<(), DecodeErrors> { + self.reset_prog_params(stream); + + if usize::from(self.num_scans) > self.input_colorspace.num_components() { + return Err(DecodeErrors::Format(format!( + "Number of scans {} cannot be greater than number of components, {}", + self.num_scans, + self.input_colorspace.num_components() + ))); + } + if self.num_scans == 1 { + // Safety checks + if self.spec_end != 0 && self.spec_start == 0 { + return Err(DecodeErrors::FormatStatic( + "Can't merge DC and AC corrupt jpeg" + )); + } + // non interleaved data, process one block at a time in trivial scanline order + + let k = self.z_order[0]; + + if k >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {k}, corrupt image" + ))); + } + + let (mcu_width, mcu_height); + + if self.components[k].vertical_sample != 1 + || self.components[k].horizontal_sample != 1 + || !self.is_interleaved + { + // For non interleaved scans + // mcu's is the image dimensions divided by 8 + mcu_width = self.info.width.div_ceil(8) as usize; + mcu_height = self.info.height.div_ceil(8) as usize; + } else { + // For other channels, in an interleaved mcu, number of MCU's + // are determined by some weird maths done in headers.rs->parse_sos() + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } + + for i in 0..mcu_height { + for j in 0..mcu_width { + if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 { + // handle EOB runs here. + stream.eob_run -= 1; + } else { + let start = 64 * (j + i * (self.components[k].width_stride / 8)); + + let data: &mut [i16; 64] = buffer + .get_mut(k) + .unwrap() + .get_mut(start..start + 64) + .ok_or(DecodeErrors::FormatStatic("Slice to Small"))? + .try_into() + .unwrap(); + + if self.spec_start == 0 { + let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1); + let dc_table = self + .dc_huffman_tables + .get(pos) + .ok_or(DecodeErrors::FormatStatic( + "No huffman table for DC component" + ))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index {} not initialized" + ))?; + + let dc_pred = &mut self.components[k].dc_pred; + + if self.succ_high == 0 { + // first scan for this mcu + stream.decode_prog_dc_first( + &mut self.stream, + dc_table, + &mut data[0], + dc_pred + )?; + } else { + // refining scans for this MCU + stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?; + } + } else { + let pos = self.components[k].ac_huff_table; + let ac_table = self + .ac_huffman_tables + .get(pos) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{pos}" + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {pos} not initialized" + )) + })?; + + if self.succ_high == 0 { + debug_assert!(stream.eob_run == 0, "EOB run is not zero"); + + stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?; + } else { + // refinement scan + stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?; + } + // Check for a marker. + // It can appear in stream CC https://github.com/etemesi254/zune-image/issues/300 + // if let Some(marker) = stream.marker.take() { + // self.parse_marker_inner(marker)?; + // } + } + } + + // + EOB and investigate effect. + self.todo -= 1; + + self.handle_rst_main(stream)?; + } + } + } else { + if self.spec_end != 0 { + return Err(DecodeErrors::HuffmanDecode( + "Can't merge dc and AC corrupt jpeg".to_string() + )); + } + // process scan n elements in order + + // Do the error checking with allocs here. + // Make the one in the inner loop free of allocations. + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + + if n >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {n}, corrupt image" + ))); + } + + let component = &mut self.components[n]; + let _ = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{}", + component.dc_huff_table + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {} not initialized", + component.dc_huff_table + )) + })?; + } + // Interleaved scan + + // Components shall not be interleaved in progressive mode, except for + // the DC coefficients in the first scan for each component of a progressive frame. + for i in 0..self.mcu_y { + for j in 0..self.mcu_x { + // process scan n elements in order + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + let component = &mut self.components[n]; + let huff_table = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or(DecodeErrors::FormatStatic("No huffman table for component"))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index not initialized" + ))?; + + for v_samp in 0..component.vertical_sample { + for h_samp in 0..component.horizontal_sample { + let x2 = j * component.horizontal_sample + h_samp; + let y2 = i * component.vertical_sample + v_samp; + let position = 64 * (x2 + y2 * component.width_stride / 8); + let buf_n = &mut buffer[n]; + + let Some(data) = &mut buf_n.get_mut(position) else { + // TODO: (CAE), this is another weird sub-sampling bug, so on fix + // remove this + return Err(DecodeErrors::FormatStatic("Invalid image")); + }; + + if self.succ_high == 0 { + stream.decode_prog_dc_first( + &mut self.stream, + huff_table, + data, + &mut component.dc_pred + )?; + } else { + stream.decode_prog_dc_refine(&mut self.stream, data)?; + } + } + } + } + // We want wrapping subtraction here because it means + // we get a higher number in the case this underflows + self.todo -= 1; + // after every scan that's a mcu, count down restart markers. + self.handle_rst_main(stream)?; + } + } + } + return Ok(()); + } + + pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> { + if self.todo == 0 { + stream.refill(&mut self.stream)?; + } + + if self.todo == 0 + && self.restart_interval != 0 + && stream.marker.is_none() + && !stream.seen_eoi + { + // if no marker and we are to reset RST, look for the marker, this matches + // libjpeg-turbo behaviour and allows us to decode images in + // https://github.com/etemesi254/zune-image/issues/261 + let _start = self.stream.position()?; + // skip bytes until we find marker + let marker = get_marker(&mut self.stream, stream); + + // In some images, the RST marker on the last section may not be available + // as it is maybe stopped by an EOI marker, see in the case of https://github.com/etemesi254/zune-image/issues/292 + // what happened was that we would go looking for the RST marker exhausting all the data + // in the image and this would return an error, so for now + // translate it to a warning, but return the image decoded up + // until that point + if let Ok(marker) = marker { + let _end = self.stream.position()?; + stream.marker = Some(marker); + // NB some warnings may be false positives. + warn!( + "{} Extraneous bytes before marker {:?}", + _end - _start, + marker + ); + } else { + warn!("RST marker was not found, where expected, image may be garbled") + } + } + if self.todo == 0 { + self.handle_rst(stream)? + } + Ok(()) + } + #[allow(clippy::too_many_lines)] + #[allow(clippy::needless_range_loop, clippy::cast_sign_loss)] + fn finish_progressive_decoding( + &mut self, block: &[Vec; MAX_COMPONENTS], pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + // This function is complicated because we need to replicate + // the function in mcu.rs + // + // The advantage is that we do very little allocation and very lot + // channel reusing. + // The trick is to notice that we repeat the same procedure per MCU + // width. + // + // So we can set it up that we only allocate temporary storage large enough + // to store a single mcu width, then reuse it per invocation. + // + // This is advantageous to us. + // + // Remember we need to have the whole MCU buffer so we store 3 unprocessed + // channels in memory, and then we allocate the whole output buffer in memory, both of + // which are huge. + // + // + + let mcu_height = if self.is_interleaved { + self.mcu_y + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided by 8. + self.info.height.div_ceil(8) as usize + }; + + // Size of our output image(width*height) + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let width = usize::from(self.info.width); + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + let mut tmp = [0_i32; DCT_BLOCK]; + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || self.input_colorspace == ColorSpace::YCCK + || self.input_colorspace == ColorSpace::CMYK + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + // dequantize, idct and color convert. + for i in 0..mcu_height { + 'component: for (position, component) in &mut self.components.iter_mut().enumerate() { + if !component.needed { + continue 'component; + } + let qt_table = &component.quantization_table; + + // step is the number of pixels this iteration wil be handling + // Given by the number of mcu's height and the length of the component block + // Since the component block contains the whole channel as raw pixels + // we this evenly divides the pixels into MCU blocks + // + // For interleaved images, this gives us the exact pixels comprising a whole MCU + // block + let step = block[position].len() / mcu_height; + // where we will be reading our pixels from. + let start = i * step; + + let slice = &block[position][start..start + step]; + + let temp_channel = &mut component.raw_coeff; + + // The next logical step is to iterate width wise. + // To figure out how many pixels we iterate by we use effective pixels + // Given to us by component.x + // iterate per effective pixels. + let mcu_x = component.width_stride / 8; + + // iterate per every vertical sample. + for k in 0..component.vertical_sample { + for j in 0..mcu_x { + // after writing a single stride, we need to skip 8 rows. + // This does the row calculation + let width_stride = k * 8 * component.width_stride; + let start = j * 64 + width_stride; + + // See https://github.com/etemesi254/zune-image/issues/262 sample 3. + let Some(qt_slice) = slice.get(start..start + 64) else { + return Err(DecodeErrors::FormatStatic( + "Invalid slice , would panic, invalid image" + )); + }; + // dequantize + for ((x, out), qt_val) in + qt_slice.iter().zip(tmp.iter_mut()).zip(qt_table.iter()) + { + *out = i32::from(*x) * qt_val; + } + // determine where to write. + let sl = &mut temp_channel[component.idct_pos..]; + + component.idct_pos += 8; + // tmp now contains a dequantized block so idct it + (self.idct_func)(&mut tmp, sl, component.width_stride); + } + // after every write of 8, skip 7 since idct write stride wise 8 times. + // + // Remember each MCU is 8x8 block, so each idct will write 8 strides into + // sl + // + // and component.idct_pos is one stride long + component.idct_pos += 7 * component.width_stride; + } + component.idct_pos = 0; + } + + // process that width up until it's impossible + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + + debug!("Finished decoding image"); + + return Ok(()); + } + pub(crate) fn reset_params(&mut self) { + /* + Apparently, grayscale images which can be down sampled exists, which is weird in the sense + that it has one component Y, which is not usually down sampled. + + This means some calculations will be wrong, so for that we explicitly reset params + for such occurrences, warn and reset the image info to appear as if it were + a non-sampled image to ensure decoding works + */ + self.h_max = 1; + self.v_max = 1; + self.sub_sample_ratio = SampleRatios::None; + self.is_interleaved = false; + self.components[0].vertical_sample = 1; + self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8; + self.components[0].horizontal_sample = 1; + } +} + +///Get a marker from the bit-stream. +/// +/// This reads until it gets a marker or end of file is encountered +pub fn get_marker( + reader: &mut ZReader, stream: &mut BitStream +) -> Result +where + T: ZByteReaderTrait +{ + if let Some(marker) = stream.marker { + stream.marker = None; + return Ok(marker); + } + + // read until we get a marker + + while !reader.eof()? { + let marker = reader.read_u8_err()?; + + if marker == 255 { + let mut r = reader.read_u8_err()?; + // 0xFF 0XFF(some images may be like that) + while r == 0xFF { + r = reader.read_u8_err()?; + } + + if r != 0 { + return Marker::from_u8(r) + .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}"))); + } + } + } + return Err(DecodeErrors::ExhaustedData); +} + +// #[cfg(test)] +// mod tests{ +// use zune_core::bytestream::ZCursor; +// use crate::JpegDecoder; +// +// #[test] +// fn make_test(){ +// let img = "/Users/etemesi/Downloads/wrong_sampling.jpeg"; +// let data = ZCursor::new(std::fs::read(img).unwrap()); +// let mut decoder = JpegDecoder::new(data); +// decoder.decode().unwrap(); +// +// } +// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/misc.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/misc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/misc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/misc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Miscellaneous stuff +#![allow(dead_code)] + +use alloc::format; +use core::cmp::max; +use core::fmt; +use core::num::NonZeroU32; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{trace, warn}; + +use crate::components::{ComponentID, SampleRatios}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::JpegDecoder; + +/// Start of baseline DCT Huffman coding + +pub const START_OF_FRAME_BASE: u16 = 0xffc0; + +/// Start of another frame + +pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1; + +/// Start of progressive DCT encoding + +pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2; + +/// Start of Lossless sequential Huffman coding + +pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3; + +/// Start of extended sequential DCT arithmetic coding + +pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9; + +/// Start of Progressive DCT arithmetic coding + +pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca; + +/// Start of Lossless sequential Arithmetic coding + +pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb; + +/// Undo run length encoding of coefficients by placing them in natural order +/// +/// This is an index from position-in-bitstream to position-in-row-major-order. +#[rustfmt::skip] +pub const UN_ZIGZAG: [usize; 64 + 16] = [ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // Prevent overflowing + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 +]; + +/// Align data to a 16 byte boundary +#[repr(align(16))] +#[derive(Clone)] + +pub struct Aligned16(pub T); + +impl Default for Aligned16 +where + T: Default +{ + fn default() -> Self { + Aligned16(T::default()) + } +} + +/// Align data to a 32 byte boundary +#[repr(align(32))] +#[derive(Clone)] +pub struct Aligned32(pub T); + +impl Default for Aligned32 +where + T: Default +{ + fn default() -> Self { + Aligned32(T::default()) + } +} + +/// Markers that identify different Start of Image markers +/// They identify the type of encoding and whether the file use lossy(DCT) or +/// lossless compression and whether we use Huffman or arithmetic coding schemes +#[derive(Eq, PartialEq, Copy, Clone)] +#[allow(clippy::upper_case_acronyms)] +pub enum SOFMarkers { + /// Baseline DCT markers + BaselineDct, + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Progressive DCT, Huffman coding + ProgressiveDctHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Default for SOFMarkers { + fn default() -> Self { + Self::BaselineDct + } +} + +impl SOFMarkers { + /// Check if a certain marker is sequential DCT or not + + pub fn is_sequential_dct(self) -> bool { + matches!( + self, + Self::BaselineDct + | Self::ExtendedSequentialHuffman + | Self::ExtendedSequentialDctArithmetic + ) + } + + /// Check if a marker is a Lossles type or not + + pub fn is_lossless(self) -> bool { + matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic) + } + + /// Check whether a marker is a progressive marker or not + + pub fn is_progressive(self) -> bool { + matches!( + self, + Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic + ) + } + + /// Create a marker from an integer + + pub fn from_int(int: u16) -> Option { + match int { + START_OF_FRAME_BASE => Some(Self::BaselineDct), + START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman), + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} + +impl fmt::Debug for SOFMarkers { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self { + Self::BaselineDct => write!(f, "Baseline DCT"), + Self::ExtendedSequentialHuffman => { + write!(f, "Extended sequential DCT, Huffman Coding") + } + Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"), + Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"), + Self::ExtendedSequentialDctArithmetic => { + write!(f, "Extended sequential DCT, arithmetic coding") + } + Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"), + Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding") + } + } +} + +/// Set up component parameters. +/// +/// This modifies the components in place setting up details needed by other +/// parts fo the decoder. +pub(crate) fn setup_component_params( + img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + let img_width = img.width(); + let img_height = img.height(); + + // in case of adobe app14 being present, zero may indicate + // either CMYK if components are 4 or RGB if components are 3, + // see https://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html + // so since we may not know how many number of components + // we have when decoding app14, we have to defer that check + // until now. + // + // We know adobe app14 was present since it's the only one that can modify + // input colorspace to be CMYK + if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK { + img.input_colorspace = ColorSpace::RGB; + } + + for component in &mut img.components { + // compute interleaved image info + // h_max contains the maximum horizontal component + img.h_max = max(img.h_max, component.horizontal_sample); + // v_max contains the maximum vertical component + img.v_max = max(img.v_max, component.vertical_sample); + img.mcu_width = img.h_max * 8; + img.mcu_height = img.v_max * 8; + // Number of MCU's per width + img.mcu_x = usize::from(img.info.width).div_ceil(img.mcu_width); + // Number of MCU's per height + img.mcu_y = usize::from(img.info.height).div_ceil(img.mcu_height); + + if img.h_max != 1 || img.v_max != 1 { + // interleaved images have horizontal and vertical sampling factors + // not equal to 1. + img.is_interleaved = true; + } + // Extract quantization tables from the arrays into components + let qt_table = *img.qt_tables[component.quantization_table_number as usize] + .as_ref() + .ok_or_else(|| { + DecodeErrors::DqtError(format!( + "No quantization table for component {:?}", + component.component_id + )) + })?; + + let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max; + let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max; + component.x = x; + component.w2 = img.mcu_x * component.horizontal_sample * 8; + // probably not needed. :) + component.y = y; + component.quantization_table = qt_table; + // initially stride contains its horizontal sub-sampling + component.width_stride *= img.mcu_x * 8; + } + { + // Sampling factors are one thing that suck + // this fixes a specific problem with images like + // + // (2 2) None + // (2 1) H + // (2 1) H + // + // The images exist in the wild, the images are not meant to exist + // but they do, it's just an annoying horizontal sub-sampling that + // I don't know why it exists. + // But it does + // So we try to cope with that. + // I am not sure of how to explain how to fix it, but it involved a debugger + // and to much coke(the legal one) + // + // If this wasn't present, self.upsample_dest would have the wrong length + let mut handle_that_annoying_bug = false; + + if let Some(y_component) = img + .components + .iter() + .find(|c| c.component_id == ComponentID::Y) + { + if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 { + handle_that_annoying_bug = true; + } + } + if handle_that_annoying_bug { + for comp in &mut img.components { + if (comp.component_id != ComponentID::Y) + && (comp.horizontal_sample != 1 || comp.vertical_sample != 1) + { + comp.fix_an_annoying_bug = 2; + } + } + } + } + + if img.is_mjpeg { + fill_default_mjpeg_tables( + img.is_progressive, + &mut img.dc_huffman_tables, + &mut img.ac_huffman_tables + ); + } + + // check colorspace matches + if img.input_colorspace.num_components() > img.components.len() { + if img.input_colorspace == ColorSpace::YCCK { + // Some images may have YCCK format (from adobe app14 segment) which is supposed to be 4 components + // but only 3 components, see issue https://github.com/etemesi254/zune-image/issues/275 + // So this is the behaviour of other decoders + // - stb_image: Treats it as YCbCr image + // - libjpeg_turbo: Does not know how to parse YCCK images (transform 2 app14) so treats + // it as YCbCr + // So I will match that to match existing ones + warn!("Treating YCCK colorspace as YCbCr as component length does not match"); + img.input_colorspace = ColorSpace::YCbCr + } else { + // Note, translated this to a warning to handle valid images of the sort + // See https://github.com/etemesi254/zune-image/issues/288 where there + // was a CMYK image with two components which would be decoded to 4 components + // by the decoder. + // So with a warning that becomes supported. + // + // djpeg fails to render an image from that also probably because it does not + // understand the expected format. + if !img.options.strict_mode() { + warn!( + "Expected {} number of components but found {}", + img.input_colorspace.num_components(), + img.components.len() + ); + warn!("Defaulting to multisample to decode"); + + // N/B: We do not post process the color of such, treating it as multiband + // is the best option since I am not aware of grayscale+alpha which is the most common + // two band format in jpeg. + if img.components.len() > 0 { + img.input_colorspace = ColorSpace::MultiBand( + NonZeroU32::new(img.components.len() as u32).unwrap() + ); + } + } else { + let msg = format!( + "Expected {} number of components but found {}", + img.input_colorspace.num_components(), + img.components.len() + ); + + return Err(DecodeErrors::Format(msg)); + } + } + } + Ok(()) +} + +///Calculate number of fill bytes added to the end of a JPEG image +/// to fill the image +/// +/// JPEG usually inserts padding bytes if the image width cannot be evenly divided into +/// 8 , 16 or 32 chunks depending on the sub sampling ratio. So given a sub-sampling ratio, +/// and the actual width, this calculates the padded bytes that were added to the image +/// +/// # Params +/// -actual_width: Actual width of the image +/// -sub_sample: Sub sampling factor of the image +/// +/// # Returns +/// The padded width, this is how long the width is for a particular image +pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize { + match sub_sample { + SampleRatios::None | SampleRatios::V => { + // None+V sends one MCU row, so that's a simple calculation + ((actual_width + 7) / 8) * 8 + } + SampleRatios::H | SampleRatios::HV => { + // sends two rows, width can be expanded by up to 15 more bytes + ((actual_width + 15) / 16) * 16 + } + SampleRatios::Generic(h, _) => { + ((actual_width + ((h * 8).saturating_sub(1))) / (h * 8)) * (h * 8) + } + } +} + +// https://www.loc.gov/preservation/digital/formats/fdd/fdd000063.shtml +// "Avery Lee, writing in the rec.video.desktop newsgroup in 2001, commented that "MJPEG, or at +// least the MJPEG in AVIs having the MJPG fourcc, is restricted JPEG with a fixed -- and +// *omitted* -- Huffman table. The JPEG must be YCbCr colorspace, it must be 4:2:2, and it must +// use basic Huffman encoding, not arithmetic or progressive.... You can indeed extract the +// MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT +// segment to them, or else the decoder won't have any idea how to decompress the data. +// The exact table necessary is given in the OpenDML spec."" +pub fn fill_default_mjpeg_tables( + is_progressive: bool, dc_huffman_tables: &mut [Option], + ac_huffman_tables: &mut [Option] +) { + // Section K.3.3 + trace!("Filling with default mjpeg tables"); + + if dc_huffman_tables[0].is_none() { + // Table K.3 + dc_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if dc_huffman_tables[1].is_none() { + // Table K.4 + dc_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[0].is_none() { + // Table K.5 + ac_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, + 0x00, 0x00, 0x01, 0x7D + ], + &[ + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, + 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, + 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[1].is_none() { + // Table K.6 + ac_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, + 0x00, 0x01, 0x02, 0x77 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, + 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, + 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, + 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +#[cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +pub use crate::unsafe_utils_avx2::*; +#[cfg(all(feature = "neon", target_arch = "aarch64"))] +pub use crate::unsafe_utils_neon::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_avx2.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_avx2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_avx2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_avx2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub}; + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: __m256i +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, tmp) + }; + } + } +} + +impl Sub for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_sub_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_add_epi32(self.mm256, rhs.mm256); + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_add_epi32(self.mm256, tmp); + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + unsafe { + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, rhs.mm256) + } + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, tmp) + } + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs.mm256); + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_mullo_epi32(self.mm256, tmp); + } + } +} + +impl MulAssign<__m256i> for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: __m256i) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs); + } + } +} + +type Reg = YmmRegister; + +/// Transpose an array of 8 by 8 i32's using avx intrinsics +/// +/// This was translated from [here](https://newbedev.com/transpose-an-8x8-float-using-avx-avx2) +#[allow(unused_parens, clippy::too_many_arguments)] +#[target_feature(enable = "avx2")] +#[inline] +pub unsafe fn transpose( + v0: &mut Reg, v1: &mut Reg, v2: &mut Reg, v3: &mut Reg, v4: &mut Reg, v5: &mut Reg, + v6: &mut Reg, v7: &mut Reg +) { + macro_rules! merge_epi32 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi32(va, vb); + + $v3 = _mm256_unpackhi_epi32(va, vb); + }; + } + + macro_rules! merge_epi64 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi64(va, vb); + + $v3 = _mm256_unpackhi_epi64(va, vb); + }; + } + + macro_rules! merge_si128 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + $v2 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 2, 0, 0)); + + $v3 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 3, 0, 1)); + }; + } + + let (w0, w1, w2, w3, w4, w5, w6, w7); + + merge_epi32!((v0.mm256), (v1.mm256), w0, w1); + + merge_epi32!((v2.mm256), (v3.mm256), w2, w3); + + merge_epi32!((v4.mm256), (v5.mm256), w4, w5); + + merge_epi32!((v6.mm256), (v7.mm256), w6, w7); + + let (x0, x1, x2, x3, x4, x5, x6, x7); + + merge_epi64!(w0, w2, x0, x1); + + merge_epi64!(w1, w3, x2, x3); + + merge_epi64!(w4, w6, x4, x5); + + merge_epi64!(w5, w7, x6, x7); + + merge_si128!(x0, x4, (v0.mm256), (v1.mm256)); + + merge_si128!(x1, x5, (v2.mm256), (v3.mm256)); + + merge_si128!(x2, x6, (v4.mm256), (v5.mm256)); + + merge_si128!(x3, x7, (v6.mm256), (v7.mm256)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_neon.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/unsafe_utils_neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(all(feature = "neon", target_arch = "aarch64"))] +// TODO can this be extended to armv7 + +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +use core::arch::aarch64::*; +use core::ops::{Add, AddAssign, BitOr, BitOrAssign, Mul, MulAssign, Sub}; + +pub type VecType = int32x4x2_t; + +pub unsafe fn loadu(src: *const i32) -> VecType { + vld1q_s32_x2(src as *const _) +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: VecType +} + +impl YmmRegister { + #[inline] + pub unsafe fn load(src: *const i32) -> Self { + loadu(src).into() + } + + #[inline] + pub fn map2(self, other: Self, f: impl Fn(int32x4_t, int32x4_t) -> int32x4_t) -> Self { + let m0 = f(self.mm256.0, other.mm256.0); + let m1 = f(self.mm256.1, other.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + + #[inline] + pub fn all_zero(self) -> bool { + unsafe { + let both = vorrq_s32(self.mm256.0, self.mm256.1); + let both_unsigned = vreinterpretq_u32_s32(both); + 0 == vmaxvq_u32(both_unsigned) + } + } + + #[inline] + pub fn const_shl(self) -> Self { + // Ensure that we logically shift left + unsafe { + let m0 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.0))); + let m1 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.1))); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + } + + #[inline] + pub fn const_shra(self) -> Self { + unsafe { + let i0 = vshrq_n_s32::(self.mm256.0); + let i1 = vshrq_n_s32::(self.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(i0, i1) + } + } + } +} + +impl Add for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vaddq_s32(a, b)) } + } +} + +impl Sub for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vsubq_s32(a, b)) } + } +} + +impl AddAssign for YmmRegister +where + T: Into +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self + rhs; + } +} + +impl Mul for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vmulq_s32(a, b)) } + } +} + +impl MulAssign for YmmRegister +where + T: Into +{ + #[inline] + fn mul_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self * rhs; + } +} + +impl BitOr for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn bitor(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vorrq_s32(a, b)) } + } +} + +impl BitOrAssign for YmmRegister +where + T: Into +{ + #[inline] + fn bitor_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self | rhs; + } +} + +impl From for YmmRegister { + #[inline] + fn from(val: i32) -> Self { + unsafe { + let dup = vdupq_n_s32(val); + + YmmRegister { + mm256: int32x4x2_t(dup, dup) + } + } + } +} + +impl From for YmmRegister { + #[inline] + fn from(mm256: VecType) -> Self { + YmmRegister { mm256 } + } +} + +#[allow(clippy::too_many_arguments)] +#[inline] +unsafe fn transpose4( + v0: &mut int32x4_t, v1: &mut int32x4_t, v2: &mut int32x4_t, v3: &mut int32x4_t +) { + let w0 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + let w1 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + + *v0 = w0.0; + *v1 = w0.1; + *v2 = w1.0; + *v3 = w1.1; +} + +/// Transpose an array of 8 by 8 i32 +/// Arm has dedicated interleave/transpose instructions +/// we: +/// 1. Transpose the upper left and lower right quadrants +/// 2. Swap and transpose the upper right and lower left quadrants +#[allow(clippy::too_many_arguments)] +#[inline] +pub unsafe fn transpose( + v0: &mut YmmRegister, v1: &mut YmmRegister, v2: &mut YmmRegister, v3: &mut YmmRegister, + v4: &mut YmmRegister, v5: &mut YmmRegister, v6: &mut YmmRegister, v7: &mut YmmRegister +) { + use core::mem::swap; + + let ul0 = &mut v0.mm256.0; + let ul1 = &mut v1.mm256.0; + let ul2 = &mut v2.mm256.0; + let ul3 = &mut v3.mm256.0; + + let ur0 = &mut v0.mm256.1; + let ur1 = &mut v1.mm256.1; + let ur2 = &mut v2.mm256.1; + let ur3 = &mut v3.mm256.1; + + let ll0 = &mut v4.mm256.0; + let ll1 = &mut v5.mm256.0; + let ll2 = &mut v6.mm256.0; + let ll3 = &mut v7.mm256.0; + + let lr0 = &mut v4.mm256.1; + let lr1 = &mut v5.mm256.1; + let lr2 = &mut v6.mm256.1; + let lr3 = &mut v7.mm256.1; + + swap(ur0, ll0); + swap(ur1, ll1); + swap(ur2, ll2); + swap(ur3, ll3); + + transpose4(ul0, ul1, ul2, ul3); + + transpose4(ur0, ur1, ur2, ur3); + + transpose4(ll0, ll1, ll2, ll3); + + transpose4(lr0, lr1, lr2, lr3); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_transpose() { + fn get_val(i: usize, j: usize) -> i32 { + ((i * 8) / (j + 1)) as i32 + } + unsafe { + let mut vals: [i32; 8 * 8] = [0; 8 * 8]; + + for i in 0..8 { + for j in 0..8 { + // some order-dependent value of i and j + let value = get_val(i, j); + vals[i * 8 + j] = value; + } + } + + let mut regs: [YmmRegister; 8] = core::mem::transmute(vals); + let mut reg0 = regs[0]; + let mut reg1 = regs[1]; + let mut reg2 = regs[2]; + let mut reg3 = regs[3]; + let mut reg4 = regs[4]; + let mut reg5 = regs[5]; + let mut reg6 = regs[6]; + let mut reg7 = regs[7]; + + transpose( + &mut reg0, &mut reg1, &mut reg2, &mut reg3, &mut reg4, &mut reg5, &mut reg6, + &mut reg7 + ); + + regs[0] = reg0; + regs[1] = reg1; + regs[2] = reg2; + regs[3] = reg3; + regs[4] = reg4; + regs[5] = reg5; + regs[6] = reg6; + regs[7] = reg7; + + let vals_from_reg: [i32; 8 * 8] = core::mem::transmute(regs); + + for i in 0..8 { + for j in 0..i { + let orig = vals[i * 8 + j]; + vals[i * 8 + j] = vals[j * 8 + i]; + vals[j * 8 + i] = orig; + } + } + + for i in 0..8 { + for j in 0..8 { + assert_eq!(vals[j * 8 + i], get_val(i, j)); + assert_eq!(vals_from_reg[j * 8 + i], get_val(i, j)); + } + } + + assert_eq!(vals, vals_from_reg); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/avx2.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/avx2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/avx2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/avx2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2025. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +pub fn upsample_horizontal_avx2( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert!(input.len() > 2); + + let len = input.len(); + + if len < 18 { + return super::scalar::upsample_horizontal(input, in_near, in_far, scratch, output); + } + + // First two pixels + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + let v_three = _mm256_set1_epi16(3); + let v_two = _mm256_set1_epi16(2); + + let upsample16 = |input: &[i16; 18], output: &mut [i16; 32]| { + let in_ptr = input.as_ptr(); + let out_ptr = output.as_mut_ptr(); + + // SAFETY: The input is 18 * 16 bit long, so the loads are safe. + let (v_prev, v_curr, v_next) = unsafe { + ( + _mm256_loadu_si256(in_ptr.add(0) as *const __m256i), + _mm256_loadu_si256(in_ptr.add(1) as *const __m256i), + _mm256_loadu_si256(in_ptr.add(2) as *const __m256i), + ) + }; + + let v_common = _mm256_add_epi16(_mm256_mullo_epi16(v_curr, v_three), v_two); + + let v_even = _mm256_srai_epi16(_mm256_add_epi16(v_common, v_prev), 2); + let v_odd = _mm256_srai_epi16(_mm256_add_epi16(v_common, v_next), 2); + + let v_res_1 = _mm256_unpacklo_epi16(v_even, v_odd); + let v_res_2 = _mm256_unpackhi_epi16(v_even, v_odd); + + let v_final_1 = _mm256_permute2x128_si256(v_res_1, v_res_2, 0x20); + let v_final_2 = _mm256_permute2x128_si256(v_res_1, v_res_2, 0x31); + + // SAFETY: The output is 32 * 16 bit long, so the stores are safe. + unsafe { + _mm256_storeu_si256(out_ptr as *mut __m256i, v_final_1); + _mm256_storeu_si256(out_ptr.add(16) as *mut __m256i, v_final_2); + } + }; + + for (input, output) in input + .windows(18) + .step_by(16) + .zip(output[2..].chunks_exact_mut(32)) + { + upsample16(input.try_into().unwrap(), output.try_into().unwrap()); + } + + // Upsample the remainder. This may have some overlap, but that's fine. + if let Some(rest_input) = input.last_chunk::<18>() { + let end = output.len() - 2; + if let Some(rest_output) = output[..end].last_chunk_mut::<32>() { + upsample16(rest_input, rest_output); + } + } + + // Last two pixels. + output[output.len() - 2] = (3 * input[len - 1] + input[len - 2] + 2) >> 2; + output[output.len() - 1] = input[len - 1]; +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +pub fn upsample_vertical_avx2( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let len = input.len(); + + if len < 16 { + return super::scalar::upsample_vertical(input, in_near, in_far, scratch, output); + } + + let middle = output.len() / 2; + let (out_top, out_bottom) = output.split_at_mut(middle); + + let v_three = _mm256_set1_epi16(3); + let v_two = _mm256_set1_epi16(2); + + let upsample16 = |input: &[i16; 16], + in_near: &[i16; 16], + in_far: &[i16; 16], + out_top: &mut [i16; 16], + out_bottom: &mut [i16; 16]| { + // SAFETY: Inputs are all 16 * 16 bit long, so the loads are safe. + let (v_in, v_near, v_far) = unsafe { + ( + _mm256_loadu_si256(input.as_ptr() as *const __m256i), + _mm256_loadu_si256(in_near.as_ptr() as *const __m256i), + _mm256_loadu_si256(in_far.as_ptr() as *const __m256i), + ) + }; + + let v_common = _mm256_add_epi16(_mm256_mullo_epi16(v_in, v_three), v_two); + + let v_out_top = _mm256_srai_epi16(_mm256_add_epi16(v_common, v_near), 2); + let v_out_bottom = _mm256_srai_epi16(_mm256_add_epi16(v_common, v_far), 2); + + // SAFETY: Outputs are 16 * 16 bit long, so the stores are safe. + unsafe { + _mm256_storeu_si256(out_top.as_mut_ptr() as *mut __m256i, v_out_top); + _mm256_storeu_si256(out_bottom.as_mut_ptr() as *mut __m256i, v_out_bottom); + } + }; + + let chunks = input + .chunks_exact(16) + .zip(in_near.chunks_exact(16)) + .zip(in_far.chunks_exact(16)) + .zip(out_top.chunks_exact_mut(16)) + .zip(out_bottom.chunks_exact_mut(16)); + + for ((((input, in_near), in_far), out_top), out_bottom) in chunks { + upsample16( + input.try_into().unwrap(), + in_near.try_into().unwrap(), + in_far.try_into().unwrap(), + out_top.try_into().unwrap(), + out_bottom.try_into().unwrap(), + ); + } + + // Upsample the remainder. This may have some overlap, but that's fine. + // Edition upgrade will fix this nested awfulness. + if let Some(rest) = input.last_chunk::<16>() { + if let Some(rest_near) = in_near.last_chunk::<16>() { + if let Some(rest_far) = in_far.last_chunk::<16>() { + if let Some(mut rest_top) = out_top.last_chunk_mut::<16>() { + if let Some(mut rest_bottom) = out_bottom.last_chunk_mut::<16>() { + upsample16(rest, rest_near, rest_far, &mut rest_top, &mut rest_bottom); + } + } + } + } + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +pub fn upsample_hv_avx2( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 4, output.len()); + assert_eq!(input.len() * 2, scratch_space.len()); + + upsample_vertical_avx2(input, in_near, in_far, &mut [], scratch_space); + + let scratch_half = scratch_space.len() / 2; + let output_half = output.len() / 2; + + let (scratch_top, scratch_bottom) = scratch_space.split_at_mut(scratch_half); + let (out_top, out_bottom) = output.split_at_mut(output_half); + + let mut t = [0]; + upsample_horizontal_avx2(scratch_top, &[], &[], &mut t, out_top); + upsample_horizontal_avx2(scratch_bottom, &[], &[], &mut t, out_bottom); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/neon.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2025. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#[cfg(target_arch = "aarch64")] +use core::arch::aarch64::*; + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +pub fn upsample_horizontal_neon( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert!(input.len() > 2); + + let len = input.len(); + + if len < 10 { + return super::scalar::upsample_horizontal(input, in_near, in_far, scratch, output); + } + + // First two pixels + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + let v_three = vdupq_n_s16(3); + let v_two = vdupq_n_s16(2); + + let upsample8 = |input: &[i16; 10], output: &mut [i16; 16]| { + let in_ptr = input.as_ptr(); + let out_ptr = output.as_mut_ptr(); + + // SAFETY: The input is 10 * 16 bit long, so the loads are safe. + let (v_prev, v_curr, v_next) = unsafe { + ( + vld1q_s16(in_ptr), + vld1q_s16(in_ptr.add(1)), + vld1q_s16(in_ptr.add(2)), + ) + }; + + let v_common = vaddq_s16(vmulq_s16(v_curr, v_three), v_two); + let v_even = vshrq_n_s16::<2>(vaddq_s16(v_common, v_prev)); + let v_odd = vshrq_n_s16::<2>(vaddq_s16(v_common, v_next)); + + let v_res_1 = vzip1q_s16(v_even, v_odd); + let v_res_2 = vzip2q_s16(v_even, v_odd); + + // SAFETY: The output is 16 * 16 bit long, so the stores are safe. + unsafe { + vst1q_s16(out_ptr, v_res_1); + vst1q_s16(out_ptr.add(8), v_res_2); + } + }; + + for (input, output) in input + .windows(10) + .step_by(8) + .zip(output[2..].chunks_exact_mut(16)) + { + upsample8(input.try_into().unwrap(), output.try_into().unwrap()); + } + + // Upsample the remainder. This may have some overlap, but that's fine. + if let Some(rest_input) = input.last_chunk::<10>() { + let end = output.len() - 2; + if let Some(rest_output) = output[..end].last_chunk_mut::<16>() { + upsample8(rest_input, rest_output); + } + } + + // Last two pixels. + output[output.len() - 2] = (3 * input[len - 1] + input[len - 2] + 2) >> 2; + output[output.len() - 1] = input[len - 1]; +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +pub fn upsample_vertical_neon( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let len = input.len(); + + if len < 16 { + return super::scalar::upsample_vertical(input, in_near, in_far, scratch, output); + } + + let middle = output.len() / 2; + let (out_top, out_bottom) = output.split_at_mut(middle); + + let v_three = vdupq_n_s16(3); + let v_two = vdupq_n_s16(2); + + let upsample8 = |input: &[i16; 8], + in_near: &[i16; 8], + in_far: &[i16; 8], + out_top: &mut [i16; 8], + out_bottom: &mut [i16; 8]| { + // SAFETY: Inputs are all 8 * 16 bit long, so the loads are safe. + let (v_in, v_near, v_far) = unsafe { + ( + vld1q_s16(input.as_ptr()), + vld1q_s16(in_near.as_ptr()), + vld1q_s16(in_far.as_ptr()), + ) + }; + + let v_common = vaddq_s16(vmulq_s16(v_in, v_three), v_two); + let v_out_top = vshrq_n_s16::<2>(vaddq_s16(v_common, v_near)); + let v_out_bottom = vshrq_n_s16::<2>(vaddq_s16(v_common, v_far)); + + // SAFETY: Outputs are 8 * 16 bit long, so the stores are safe. + unsafe { + vst1q_s16(out_top.as_mut_ptr(), v_out_top); + vst1q_s16(out_bottom.as_mut_ptr(), v_out_bottom); + } + }; + + let chunks = input + .chunks_exact(8) + .zip(in_near.chunks_exact(8)) + .zip(in_far.chunks_exact(8)) + .zip(out_top.chunks_exact_mut(8)) + .zip(out_bottom.chunks_exact_mut(8)); + + for ((((input, in_near), in_far), out_top), out_bottom) in chunks { + upsample8( + input.try_into().unwrap(), + in_near.try_into().unwrap(), + in_far.try_into().unwrap(), + out_top.try_into().unwrap(), + out_bottom.try_into().unwrap(), + ); + } + + // Upsample the remainder. + if let Some(rest) = input.last_chunk::<8>() { + if let Some(rest_near) = in_near.last_chunk::<8>() { + if let Some(rest_far) = in_far.last_chunk::<8>() { + if let Some(mut rest_top) = out_top.last_chunk_mut::<8>() { + if let Some(mut rest_bottom) = out_bottom.last_chunk_mut::<8>() { + upsample8(rest, rest_near, rest_far, &mut rest_top, &mut rest_bottom); + } + } + } + } + } +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +pub fn upsample_hv_neon( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 4, output.len()); + assert_eq!(input.len() * 2, scratch_space.len()); + + upsample_vertical_neon(input, in_near, in_far, &mut [], scratch_space); + + let scratch_half = scratch_space.len() / 2; + let output_half = output.len() / 2; + + let (scratch_top, scratch_bottom) = scratch_space.split_at_mut(scratch_half); + let (out_top, out_bottom) = output.split_at_mut(output_half); + + let mut t = [0]; + upsample_horizontal_neon(scratch_top, &[], &[], &mut t, out_top); + upsample_horizontal_neon(scratch_bottom, &[], &[], &mut t, out_bottom); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/portable_simd.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/portable_simd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/portable_simd.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/portable_simd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use std::simd::prelude::*; + +const LANES: usize = 16; +type V = Simd; + +pub fn upsample_horizontal_simd( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert!(input.len() > 2); + + let len = input.len(); + + if len < 18 { + return super::scalar::upsample_horizontal(input, in_near, in_far, scratch, output); + } + + // First two pixels + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + let v_three = V::splat(3); + let v_two = V::splat(2); + + let upsample16 = |input: &[i16; 18], output: &mut [i16; 32]| { + let v_prev = V::from_slice(&input[0..LANES]); + let v_curr = V::from_slice(&input[1..LANES + 1]); + let v_next = V::from_slice(&input[2..LANES + 2]); + + let v_common = v_curr * v_three + v_two; + + let v_even = (v_common + v_prev) >> 2; + let v_odd = (v_common + v_next) >> 2; + + let (v_res_1, v_res_2) = v_even.interleave(v_odd); + + v_res_1.copy_to_slice(&mut output[0..LANES]); + v_res_2.copy_to_slice(&mut output[LANES..2 * LANES]); + }; + + for (input, output) in input + .windows(18) + .step_by(16) + .zip(output[2..].chunks_exact_mut(32)) + { + upsample16(input.try_into().unwrap(), output.try_into().unwrap()); + } + + // Upsample the remainder. This may have some overlap, but that's fine. + if let Some(rest_input) = input.last_chunk::<18>() { + let end = output.len() - 2; + if let Some(rest_output) = output[..end].last_chunk_mut::<32>() { + upsample16(rest_input, rest_output); + } + } + + // Last two pixels. + output[output.len() - 2] = (3 * input[len - 1] + input[len - 2] + 2) >> 2; + output[output.len() - 1] = input[len - 1]; +} + +pub fn upsample_vertical_simd( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + _scratch_space: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let len = input.len(); + + if len < 16 { + return super::scalar::upsample_vertical(input, in_near, in_far, _scratch_space, output); + } + + let middle = output.len() / 2; + let (out_top, out_bottom) = output.split_at_mut(middle); + + let v_three = V::splat(3); + let v_two = V::splat(2); + + let upsample16 = |input: &[i16; 16], + in_near: &[i16; 16], + in_far: &[i16; 16], + out_top: &mut [i16; 16], + out_bottom: &mut [i16; 16]| { + let v_in = V::from(*input); + let v_near = V::from(*in_near); + let v_far = V::from(*in_far); + + let v_common = v_in * v_three + v_two; + + let v_out_top = (v_common + v_near) >> 2; + let v_out_bottom = (v_common + v_far) >> 2; + + v_out_top.copy_to_slice(out_top.as_mut_slice()); + v_out_bottom.copy_to_slice(out_bottom.as_mut_slice()); + }; + + let chunks = input + .chunks_exact(16) + .zip(in_near.chunks_exact(16)) + .zip(in_far.chunks_exact(16)) + .zip(out_top.chunks_exact_mut(16)) + .zip(out_bottom.chunks_exact_mut(16)); + + for ((((input, in_near), in_far), out_top), out_bottom) in chunks { + upsample16( + input.try_into().unwrap(), + in_near.try_into().unwrap(), + in_far.try_into().unwrap(), + out_top.try_into().unwrap(), + out_bottom.try_into().unwrap(), + ); + } + + // Upsample the remainder. This may have some overlap, but that's fine. + // Edition upgrade will fix this nested awfulness. + if let Some(rest) = input.last_chunk::<16>() { + if let Some( rest_near) = in_near.last_chunk::<16>() { + if let Some( rest_far) = in_far.last_chunk::<16>() { + if let Some( rest_top) = out_top.last_chunk_mut::<16>() { + if let Some( rest_bottom) = out_bottom.last_chunk_mut::<16>() { + upsample16(rest, rest_near, rest_far, rest_top, rest_bottom); + } + } + } + } + } +} + +pub fn upsample_hv_simd( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16], +) { + assert_eq!(input.len() * 4, output.len()); + assert_eq!(input.len() * 2, scratch_space.len()); + + upsample_vertical_simd(input, in_near, in_far, &mut [], scratch_space); + + let scratch_half = scratch_space.len() / 2; + let output_half = output.len() / 2; + + let (scratch_top, scratch_bottom) = scratch_space.split_at_mut(scratch_half); + let (out_top, out_bottom) = output.split_at_mut(output_half); + + let mut t = [0]; + upsample_horizontal_simd(scratch_top, &[], &[], &mut t, out_top); + upsample_horizontal_simd(scratch_bottom, &[], &[], &mut t, out_bottom); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +pub fn upsample_horizontal( + input: &[i16], _ref: &[i16], _in_near: &[i16], _scratch: &mut [i16], output: &mut [i16] +) { + assert_eq!( + input.len() * 2, + output.len(), + "Input length is not half the size of the output length" + ); + assert!( + output.len() > 4 && input.len() > 2, + "Too Short of a vector, cannot upsample" + ); + + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + // This code is written for speed and not readability + // + // The readable code is + // + // for i in 1..input.len() - 1{ + // let sample = 3 * input[i] + 2; + // out[i * 2] = (sample + input[i - 1]) >> 2; + // out[i * 2 + 1] = (sample + input[i + 1]) >> 2; + // } + // + // The output of a pixel is determined by it's surrounding neighbours but we attach more weight to it's nearest + // neighbour (input[i]) than to the next nearest neighbour. + + for (output_window, input_window) in output[2..].chunks_exact_mut(2).zip(input.windows(3)) { + let sample = 3 * input_window[1] + 2; + + output_window[0] = (sample + input_window[0]) >> 2; + output_window[1] = (sample + input_window[2]) >> 2; + } + // Get lengths + let out_len = output.len() - 2; + let input_len = input.len() - 2; + + // slice the output vector + let f_out = &mut output[out_len..]; + let i_last = &input[input_len..]; + + // write out manually.. + f_out[0] = (3 * i_last[1] + i_last[0] + 2) >> 2; + f_out[1] = i_last[1]; +} +pub fn upsample_vertical( + input: &[i16], in_near: &[i16], in_far: &[i16], _scratch_space: &mut [i16], output: &mut [i16] +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let middle = output.len() / 2; + + let (out_top, out_bottom) = output.split_at_mut(middle); + + // for the first row, closest row is in_near + for ((near, far), x) in input.iter().zip(in_near.iter()).zip(out_top) { + *x = (((3 * near) + 2) + far) >> 2; + } + // for the second row, the closest row to input is in_far + for ((near, far), x) in input.iter().zip(in_far.iter()).zip(out_bottom) { + *x = (((3 * near) + 2) + far) >> 2; + } +} + +pub fn upsample_hv( + input: &[i16], in_near: &[i16], in_far: &[i16], scratch_space: &mut [i16], output: &mut [i16] +) { + + assert_eq!(input.len() * 4, output.len()); + assert_eq!(input.len() * 2, scratch_space.len()); + + let mut t = [0]; + upsample_vertical(input, in_near, in_far, &mut t, scratch_space); + // horizontal upsampling must be done separate for every line + // Otherwise it introduces artifacts that may cause the edge colors + // to appear on the other line. + + // Since this is called for two scanlines/widths currently + // splitting the inputs and outputs into half ensures we only handle + // one scanline per iteration + let scratch_half = scratch_space.len() / 2; + + let output_half = output.len() / 2; + + upsample_horizontal( + &scratch_space[..scratch_half], + &[], + &[], + &mut t, + &mut output[..output_half] + ); + + upsample_horizontal( + &scratch_space[scratch_half..], + &[], + &[], + &mut t, + &mut output[output_half..] + ); +} + +pub fn upsample_generic( + input: &[i16], _in_near: &[i16], _in_far: &[i16], _scratch_space: &mut [i16], + output: &mut [i16] +) { + // use nearest sample + let difference = output.len() / input.len(); + if difference > 0 { + // nearest neighbour + for (input, chunk_output) in input.iter().zip(output.chunks_exact_mut(difference)) { + chunk_output.iter_mut().for_each(|x| *x = *input); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/upsampler.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/upsampler.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Up-sampling routines +//! +//! The main upsampling method is a bi-linear interpolation or a "triangle +//! filter " or libjpeg turbo `fancy_upsampling` which is a good compromise +//! between speed and visual quality +//! +//! # The filter +//! Each output pixel is made from `(3*A+B)/4` where A is the original +//! pixel closer to the output and B is the one further. +//! +//! ```text +//!+---+---+ +//! | A | B | +//! +---+---+ +//! +-+-+-+-+ +//! | |P| | | +//! +-+-+-+-+ +//! ``` +//! +//! # Horizontal Bi-linear filter +//! ```text +//! |---+-----------+---+ +//! | | | | +//! | A | |p1 | p2| | B | +//! | | | | +//! |---+-----------+---+ +//! +//! ``` +//! For a horizontal bi-linear it's trivial to implement, +//! +//! `A` becomes the input closest to the output. +//! +//! `B` varies depending on output. +//! - For odd positions, input is the `next` pixel after A +//! - For even positions, input is the `previous` value before A. +//! +//! We iterate in a classic 1-D sliding window with a window of 3. +//! For our sliding window approach, `A` is the 1st and `B` is either the 0th term or 2nd term +//! depending on position we are writing.(see scalar code). +//! +//! For vector code see module sse for explanation. +//! +//! # Vertical bi-linear. +//! Vertical up-sampling is a bit trickier. +//! +//! ```text +//! +----+----+ +//! | A1 | A2 | +//! +----+----+ +//! +----+----+ +//! | p1 | p2 | +//! +----+-+--+ +//! +----+-+--+ +//! | p3 | p4 | +//! +----+-+--+ +//! +----+----+ +//! | B1 | B2 | +//! +----+----+ +//! ``` +//! +//! For `p1` +//! - `A1` is given a weight of `3` and `B1` is given a weight of 1. +//! +//! For `p3` +//! - `B1` is given a weight of `3` and `A1` is given a weight of 1 +//! +//! # Horizontal vertical downsampling/chroma quartering. +//! +//! Carry out a vertical filter in the first pass, then a horizontal filter in the second pass. +#![allow(unreachable_code)] +use zune_core::options::DecoderOptions; + +use crate::components::UpSampler; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(feature = "x86")] +mod avx2; +#[cfg(target_arch = "aarch64")] +#[cfg(feature = "neon")] +mod neon; +#[cfg(feature = "portable_simd")] +mod portable_simd; +mod scalar; + +// choose the best possible implementation for this platform +#[allow(unused_variables)] +pub fn choose_horizontal_samp_function(options: &DecoderOptions) -> UpSampler { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + if options.use_avx2() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_avx2()` only returns true if avx2 is supported. + unsafe { avx2::upsample_horizontal_avx2(a, b, c, d, e) } + }; + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + if options.use_neon() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_neon()` only returns true if neon is supported. + unsafe { neon::upsample_horizontal_neon(a, b, c, d, e) } + }; + } + #[cfg(feature = "portable_simd")] + return portable_simd::upsample_horizontal_simd; + return scalar::upsample_horizontal; +} + +#[allow(unused_variables)] +pub fn choose_hv_samp_function(options: &DecoderOptions) -> UpSampler { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + if options.use_avx2() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_avx2()` only returns true if avx2 is supported. + unsafe { avx2::upsample_hv_avx2(a, b, c, d, e) } + }; + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + if options.use_neon() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_neon()` only returns true if neon is supported. + unsafe { neon::upsample_hv_neon(a, b, c, d, e) } + }; + } + #[cfg(feature = "portable_simd")] + return portable_simd::upsample_hv_simd; + return scalar::upsample_hv; +} + +#[allow(unused_variables)] +pub fn choose_v_samp_function(options: &DecoderOptions) -> UpSampler { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + if options.use_avx2() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_avx2()` only returns true if avx2 is supported. + unsafe { avx2::upsample_vertical_avx2(a, b, c, d, e) } + }; + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + if options.use_neon() { + return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: `options.use_neon()` only returns true if neon is supported. + unsafe { neon::upsample_vertical_neon(a, b, c, d, e) } + }; + } + #[cfg(feature = "portable_simd")] + return portable_simd::upsample_vertical_simd; + return scalar::upsample_vertical; +} + +/// Upsample nothing + +pub fn upsample_no_op( + _input: &[i16], + _in_ref: &[i16], + _in_near: &[i16], + _scratch_space: &mut [i16], + _output: &mut [i16], +) { +} + +pub fn generic_sampler() -> UpSampler { + scalar::upsample_generic +} + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(feature = "portable_simd")] + mod portable_simd_impl { + use super::*; + + #[test] + fn portable_simd_vertical() { + _test_vertical(portable_simd::upsample_vertical_simd) + } + + #[test] + fn portable_simd_horizontal() { + _test_horizontal(portable_simd::upsample_horizontal_simd) + } + + #[test] + fn portable_simd_hv() { + _test_hv(portable_simd::upsample_hv_simd) + } + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + #[cfg(target_feature = "avx2")] + mod avx2_impl { + use super::*; + + #[test] + fn avx2_vertical() { + _test_vertical(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { avx2::upsample_vertical_avx2(a, b, c, d, e) } + }) + } + + #[test] + fn avx2_horizontal() { + _test_horizontal(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { avx2::upsample_horizontal_avx2(a, b, c, d, e) } + }) + } + + #[test] + fn avx2_hv() { + _test_hv(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { avx2::upsample_hv_avx2(a, b, c, d, e) } + }) + } + } + + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + #[cfg(target_feature = "neon")] + mod neon_impl { + use super::*; + + #[test] + fn neon_vertical() { + _test_vertical(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { neon::upsample_vertical_neon(a, b, c, d, e) } + }) + } + + #[test] + fn neon_horizontal() { + _test_horizontal(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { neon::upsample_horizontal_neon(a, b, c, d, e) } + }) + } + + #[test] + fn neon_hv() { + _test_hv(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| { + // SAFETY: Test guarded behind `target_feature` + unsafe { neon::upsample_hv_neon(a, b, c, d, e) } + }) + } + } + + fn _test_vertical(upsampler: UpSampler) { + let width = 1024; + let input: Vec = (0..width).map(|x| ((x + 10) % 256) as i16).collect(); + let in_near: Vec = (0..width).map(|x| ((x + 20) % 256) as i16).collect(); + let in_far: Vec = (0..width).map(|x| ((x + 30) % 256) as i16).collect(); + let mut scratch = vec![0i16; width]; + + let mut output_scalar = vec![0i16; width * 2]; + let mut output_fast = vec![0i16; width * 2]; + + scalar::upsample_vertical(&input, &in_near, &in_far, &mut scratch, &mut output_scalar); + upsampler(&input, &in_near, &in_far, &mut scratch, &mut output_fast); + + assert_eq!(output_scalar, output_fast); + } + + fn _test_horizontal(upsampler: UpSampler) { + _test_horizontal_even_width(upsampler); + _test_horizontal_odd_width(upsampler); + } + + fn _test_horizontal_even_width(upsampler: UpSampler) { + let width = 1024; + let input: Vec = (0..width).map(|x| ((x + 10) % 256) as i16).collect(); + + let mut scratch = vec![0i16; width]; + + let mut output_scalar = vec![0i16; width * 2]; + let mut output_fast = vec![0i16; width * 2]; + + scalar::upsample_horizontal(&input, &[], &[], &mut scratch, &mut output_scalar); + upsampler(&input, &[], &[], &mut scratch, &mut output_fast); + + assert_eq!(output_scalar, output_fast); + } + + fn _test_horizontal_odd_width(upsampler: UpSampler) { + let width = 33; + let input: Vec = (0..width).map(|x| ((x + 10) % 256) as i16).collect(); + let mut scratch = vec![0i16; width]; + let mut output_scalar = vec![0i16; width * 2]; + let mut output_fast = vec![0i16; width * 2]; + + scalar::upsample_horizontal(&input, &[], &[], &mut scratch, &mut output_scalar); + upsampler(&input, &[], &[], &mut scratch, &mut output_fast); + + assert_eq!(output_scalar, output_fast); + } + + fn _test_hv(upsampler: UpSampler) { + let width = 512; + let input: Vec = (0..width).map(|x| ((x + 10) % 256) as i16).collect(); + let in_near: Vec = (0..width).map(|x| ((x + 20) % 256) as i16).collect(); + let in_far: Vec = (0..width).map(|x| ((x + 30) % 256) as i16).collect(); + + // Output len is width * 4 for HV (vertical * 2, then horizontal * 2 for each row) + // scratch is width * 2 + let mut scratch_scalar = vec![0i16; width * 2]; + let mut scratch_fast = vec![0i16; width * 2]; + let mut output_scalar = vec![0i16; width * 4]; + let mut output_fast = vec![0i16; width * 4]; + + scalar::upsample_hv( + &input, + &in_near, + &in_far, + &mut scratch_scalar, + &mut output_scalar, + ); + upsampler( + &input, + &in_near, + &in_far, + &mut scratch_fast, + &mut output_fast, + ); + + assert_eq!(output_scalar, output_fast); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/worker.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/worker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg/src/worker.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg/src/worker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::format; +use core::convert::TryInto; + +use zune_core::colorspace::ColorSpace; + +use crate::color_convert::ycbcr_to_grayscale; +use crate::components::{Components, SampleRatios}; +use crate::decoder::{ColorConvert16Ptr, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; + +/// fast 0..255 * 0..255 => 0..255 rounded multiplication +/// +/// Borrowed from stb +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +#[inline] +fn blinn_8x8(in_val: u8, y: u8) -> u8 { + let t = i32::from(in_val) * i32::from(y) + 128; + return ((t + (t >> 8)) >> 8) as u8; +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +pub(crate) fn color_convert( + unprocessed: &[&[i16]; MAX_COMPONENTS], color_convert_16: ColorConvert16Ptr, + input_colorspace: ColorSpace, output_colorspace: ColorSpace, output: &mut [u8], width: usize, + padded_width: usize +) -> Result<(), DecodeErrors> { + if input_colorspace.num_components() == 3 && input_colorspace == output_colorspace { + // sort things like RGB to RGB conversion + copy_removing_padding(unprocessed, width, padded_width, output); + return Ok(()); + } + if input_colorspace.num_components() == 4 && input_colorspace == output_colorspace { + copy_removing_padding_4x(unprocessed, width, padded_width, output); + return Ok(()); + } + // color convert + match (input_colorspace, output_colorspace) { + (ColorSpace::YCbCr | ColorSpace::Luma, ColorSpace::Luma) => { + ycbcr_to_grayscale(unprocessed[0], width, padded_width, output); + } + ( + ColorSpace::YCbCr, + ColorSpace::RGB | ColorSpace::RGBA | ColorSpace::BGR | ColorSpace::BGRA + ) => { + color_convert_ycbcr( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::YCCK, ColorSpace::RGB) => { + color_convert_ycck_to_rgb::<3>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + + (ColorSpace::YCCK, ColorSpace::RGBA) => { + color_convert_ycck_to_rgb::<4>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::CMYK, ColorSpace::RGB) => { + color_convert_cymk_to_rgb::<3>(unprocessed, width, padded_width, output); + } + (ColorSpace::CMYK, ColorSpace::RGBA) => { + color_convert_cymk_to_rgb::<4>(unprocessed, width, padded_width, output); + } + (ColorSpace::MultiBand(n), _) => { + if n.get() != 2 { + return Err(DecodeErrors::Format(format!( + "Unknown multiband sample ({n}), please share sample" + ))); + } + copy_removing_padding_generic( + unprocessed, + width, + padded_width, + output, + n.get() as usize + ); + } + (ColorSpace::Luma, ColorSpace::RGB) => { + // duplicate the luma channel three times to form RGB + // Note, this may assume the direct conversion + // from luma to RGB is by duplicating + // + // There may be a bit more complex ways + // of doing it but won't get onto it + convert_luma_to_rgb(unprocessed, width, padded_width, output) + } + (ColorSpace::Luma, ColorSpace::RGBA) => { + // duplicate the luma channel three times to form RGB + // add 255 as alpha + // Note, this may assume the direct conversion + // from luma to RGB is by duplicating + // + // There may be a bit more complex ways + // of doing it but won't get onto it + convert_luma_to_rgba(unprocessed, width, padded_width, output) + } + + // For the other components we do nothing(currently) + _ => { + let msg = format!( + "Unimplemented colorspace mapping from {input_colorspace:?} to {output_colorspace:?}"); + + return Err(DecodeErrors::Format(msg)); + } + } + Ok(()) +} + +fn convert_luma_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for (pix_w, y_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[0].chunks_exact(padded_width)) + { + for (pix, c) in pix_w.chunks_exact_mut(3).zip(y_w) { + pix[0] = *c as u8; + pix[1] = *c as u8; + pix[2] = *c as u8; + } + } +} +fn convert_luma_to_rgba( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for (pix_w, y_w) in output + .chunks_exact_mut(width * 4) + .zip(mcu_block[0].chunks_exact(padded_width)) + { + for (pix, c) in pix_w.chunks_exact_mut(4).zip(y_w) { + pix[0] = *c as u8; + pix[1] = *c as u8; + pix[2] = *c as u8; + pix[3] = 255; + } + } +} +/// Copy a block to output removing padding bytes from input +/// if necessary +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn copy_removing_padding( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for (((pix_w, c_w), m_w), y_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + { + for (((pix, c), y), m) in pix_w.chunks_exact_mut(3).zip(c_w).zip(m_w).zip(y_w) { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + } + } +} +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn copy_removing_padding_4x( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * 4) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), y), m), k) in pix_w + .chunks_exact_mut(4) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + pix[3] = *k as u8; + } + } +} +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn copy_removing_padding_generic( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8], + channels: usize +) { + match channels { + // just do 2 for now + 2 => { + for ((pix_w, y_w), k_w) in output + .chunks_exact_mut(width * channels) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + { + for ((pix, c), k) in pix_w.chunks_exact_mut(2).zip(y_w).zip(k_w) { + pix[0] = *c as u8; + pix[1] = *k as u8; + } + } + } + _ => unreachable!() + } +} +/// Convert YCCK image to rgb +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn color_convert_ycck_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + color_convert_ycbcr( + mcu_block, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + for (pix_w, m_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for (pix, m) in pix_w.chunks_exact_mut(NUM_COMPONENTS).zip(m_w) { + let m = (*m) as u8; + pix[0] = blinn_8x8(255 - pix[0], m); + pix[1] = blinn_8x8(255 - pix[1], m); + pix[2] = blinn_8x8(255 - pix[2], m); + } + } +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn color_convert_cymk_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * NUM_COMPONENTS) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), m), y), k) in pix_w + .chunks_exact_mut(3) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + let c = *c as u8; + let m = *m as u8; + let y = *y as u8; + let k = *k as u8; + + pix[0] = blinn_8x8(c, k); + pix[1] = blinn_8x8(m, k); + pix[2] = blinn_8x8(y, k); + } + } +} + +/// Do color-conversion for interleaved MCU +#[allow( + clippy::similar_names, + clippy::too_many_arguments, + clippy::needless_pass_by_value, + clippy::unwrap_used +)] +fn color_convert_ycbcr( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + let num_components = output_colorspace.num_components(); + + let stride = width * num_components; + // Allocate temporary buffer for small widths less than 16. + let mut temp = [0; 64]; + // We need to chunk per width to ensure we can discard extra values at the end of the width. + // Since the encoder may pad bits to ensure the width is a multiple of 8. + for (((y_width, cb_width), cr_width), out) in mcu_block[0] + .chunks_exact(padded_width) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(output.chunks_exact_mut(stride)) + { + if width < 16 { + // allocate temporary buffers for the values received from idct + let mut y_out = [0; 16]; + let mut cb_out = [0; 16]; + let mut cr_out = [0; 16]; + // copy those small widths to that buffer + y_out[0..y_width.len()].copy_from_slice(y_width); + cb_out[0..cb_width.len()].copy_from_slice(cb_width); + cr_out[0..cr_width.len()].copy_from_slice(cr_width); + // we handle widths less than 16 a bit differently, allocating a temporary + // buffer and writing to that and then flushing to the out buffer + // because of the optimizations applied below, + (color_convert_16)(&y_out, &cb_out, &cr_out, &mut temp, &mut 0); + // copy to stride + out[0..width * num_components].copy_from_slice(&temp[0..width * num_components]); + // next + continue; + } + + // Chunk in outputs of 16 to pass to color_convert as an array of 16 i16's. + for (((y, cb), cr), out_c) in y_width + .chunks_exact(16) + .zip(cb_width.chunks_exact(16)) + .zip(cr_width.chunks_exact(16)) + .zip(out.chunks_exact_mut(16 * num_components)) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + out_c, + &mut 0 + ); + } + //we have more pixels in the end that can't be handled by the main loop. + //move pointer back a little bit to get last 16 bytes, + //color convert, and overwrite + //This means some values will be color converted twice. + for ((y, cb), cr) in y_width[width - 16..] + .chunks_exact(16) + .zip(cb_width[width - 16..].chunks_exact(16)) + .zip(cr_width[width - 16..].chunks_exact(16)) + .take(1) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + &mut temp, + &mut 0 + ); + } + + let rem = out[(width - 16) * num_components..] + .chunks_exact_mut(16 * num_components) + .next() + .unwrap(); + + rem.copy_from_slice(&temp[0..rem.len()]); + } +} +pub(crate) fn upsample( + component: &mut Components, mcu_height: usize, i: usize, upsampler_scratch_space: &mut [i16], + has_vertical_sample: bool +) -> Result<(), DecodeErrors> { + match component.sample_ratio { + SampleRatios::V | SampleRatios::HV => { + /* + When upsampling vertically sampled images, we have a certain problem + which is that we do not have all MCU's decoded, this usually sucks at boundaries + e.g we can't upsample the last mcu row, since the row_down currently doesn't exist + + To solve this we need to do two things + + 1. Carry over coefficients when we lack enough data to upsample + 2. Upsample when we have enough data + + To achieve (1), we store a previous row, and the current row in components themselves + which will later be used to make (2) + + To achieve (2), we take the stored previous row(second last MCU row), + current row(last mcu row) and row down(first row of newly decoded MCU) + + and upsample that and store it in first_row_upsample_dest, this contains + up-sampled coefficients for the last for the previous decoded mcu row. + + The caller is then expected to process first_row_upsample_dest before processing data + in component.upsample_dest which stores the up-sampled components excluding the last row + */ + + let mut dest_start = 0; + let stride_bytes_written = component.width_stride * component.sample_ratio.sample(); + + if i > 0 { + // Handle the last MCU of the previous row + // This wasn't up-sampled as we didn't have the row_down + // so we do it now + + let stride = component.width_stride; + + let dest = &mut component.first_row_upsample_dest[0..stride_bytes_written]; + + // get current row + let row = &component.row[..]; + let row_up = &component.row_up[..]; + let row_down = &component.raw_coeff[0..stride]; + (component.up_sampler)(row, row_up, row_down, upsampler_scratch_space, dest); + } + + // we have the Y component width stride. + // this may be higher than the actual width,(2x because vertical sampling) + // + // This will not upsample the last row + + // if false, do not upsample. + // set to false on the last row of an mcu + let mut upsample = true; + + let stride = component.width_stride * component.vertical_sample; + let stop_offset = component.raw_coeff.len() / component.width_stride; + + if component.raw_coeff.len() != stop_offset * stride { + // slice would panic below + return Err(DecodeErrors::FormatStatic( + "Invalid component dimensions, would panic" + )); + } + for (pos, curr_row) in component + .raw_coeff + .chunks_exact(component.width_stride) + .enumerate() + { + let mut dest: &mut [i16] = &mut []; + let mut row_up: &[i16] = &[]; + // row below current sample + let mut row_down: &[i16] = &[]; + + // Order of ifs matters + + if i == 0 && pos == 0 { + // first IMAGE row, row_up is the same as current row + // row_down is the row below. + row_up = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i > 0 && pos == 0 { + // first row of a new mcu, previous row was copied so use that + row_up = &component.row[..]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i == mcu_height.saturating_sub(1) && pos == stop_offset - 1 { + // last IMAGE row, adjust pointer to use previous row and current row + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + } else if pos > 0 && pos < stop_offset - 1 { + // other rows, get row up and row down relative to our current row + // ignore last row of each mcu + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if pos == stop_offset - 1 { + // last MCU in a row + // + // we need a row at the next MCU but we haven't decoded that MCU yet + // so we should save this and when we have the next MCU, + // do the upsampling + + // store the current row and previous row in a buffer + let prev_row = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + + component.row_up.copy_from_slice(prev_row); + component.row.copy_from_slice(curr_row); + upsample = false; + } else { + unreachable!("Uh oh!"); + } + if upsample { + dest = + &mut component.upsample_dest[dest_start..dest_start + stride_bytes_written]; + dest_start += stride_bytes_written; + } + + if upsample { + // upsample + (component.up_sampler)( + curr_row, + row_up, + row_down, + upsampler_scratch_space, + dest + ); + } + } + } + SampleRatios::H => { + //assert_eq!(component.raw_coeff.len() * 2, component.upsample_dest.len()); + // Before it was an assert, but numerous and numerous and numerous + // bug fixes and ad hoc solutions later, I have now just decided to keep it as a resize + component + .upsample_dest + .resize(component.raw_coeff.len() * 2, 0); + + let raw_coeff = &component.raw_coeff; + let dest_coeff = &mut component.upsample_dest; + + if has_vertical_sample { + /* + There have been images that have the following configurations. + + Component ID:Y HS:2 VS:2 QT:0 + Component ID:Cb HS:1 VS:1 QT:1 + Component ID:Cr HS:1 VS:2 QT:1 + + This brings out a nasty case of misaligned sampling factors. Cr will need to save a row because + of the way we process boundaries but Cb won't since Cr is horizontally sampled while Cb is + HV sampled with respect to the image sampling factors. + + So during decoding of one MCU, we could only do 7 and not 8 rows, but the SampleRatio::H never had to + save a single line, since it doesn't suffer from boundary issues. + + Now this takes care of that, saving the last MCU row in case it will be needed. + We save the previous row before up-sampling this row because the boundary issue is in + the last MCU row of the previous MCU. + + PS(cae): I can't add the image to the repo as it is nsfw, but can send if required + */ + let length = component.first_row_upsample_dest.len(); + component + .first_row_upsample_dest + .copy_from_slice(&dest_coeff.rchunks_exact(length).next().unwrap()); + } + // up-sample each row + for (single_row, output_stride) in raw_coeff + .chunks_exact(component.width_stride) + .zip(dest_coeff.chunks_exact_mut(component.width_stride * 2)) + { + // upsample using the fn pointer, should only be H, so no need for + // row up and row down + (component.up_sampler)(single_row, &[], &[], &mut [], output_stride); + } + } + SampleRatios::Generic(h, v) => { + let raw_coeff = &component.raw_coeff; + let dest_coeff = &mut component.upsample_dest; + + //let size = component.width_stride.div_ceil(v); + + // for (single_row, output_stride) in raw_coeff + // .chunks_exact(size) + // .zip(dest_coeff.chunks_exact_mut(component.width_stride * h)) + // { + // (component.up_sampler)(single_row, &[], &[], &mut [], output_stride); + // + // } + for (single_row, output_stride) in raw_coeff + .chunks_exact(component.width_stride) + .zip(dest_coeff.chunks_exact_mut(component.width_stride * h * v)) + { + for row in output_stride.chunks_exact_mut(component.width_stride * h) { + (component.up_sampler)(single_row, &[], &[], &mut [], row); + } + } + } + SampleRatios::None => {} + }; + Ok(()) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"dc9b021583ee70d84e4ecdbf91ea545587babc819e9d3e51a3c7064c2e38b898","Benches.md":"5e0a2292e9a2b6d5d7923f4b847a9aead7ab656326ef58018d30dfa46c53cf20","Cargo.lock":"038ce7ce03e524ded511d2150c11ad798ac8a9b04be7db0bceff3e893b3cfd34","Cargo.toml":"8fa62897326b6111c957b7ece926e19dc460b017da2ee58f651b0e9c4e79fd52","Cargo.toml.orig":"b84874c67f2b66aa79164f0a946d36b673a8e2a3e6bcc6a5ecdfc1b1c1e04530","Changelog.md":"ba92153246447d2951338d15922e9165a43ec66b755223bb5494d299afb7197d","README.md":"d58a4403ff2b9f7eba16f1284a9b4a4c7125bc92dacd8f0fac1ee112e3a8b8ee","src/bitstream.rs":"a0282b7dc7bd6650be136ba07d195df4ea35f071e20df156fa44bfb08a15c0de","src/color_convert.rs":"9acfe3d10b9cbe185a4de1fbf1350672a239a0f89c01c2217afb61bc6a7570ba","src/color_convert/avx.rs":"7be52b218a32ca06d8727dbd5d9ff18f0e09ee05c2147e2469e1b78f25e4f1f5","src/color_convert/neon64.rs":"b2d2ab7a92ec712b150ec9e007ab030d0b103c29a67d6fcb4b9dca5b01d1d6cb","src/color_convert/scalar.rs":"daf7a7595775ce00bec28997330bc72f0fd3cd113d764cf742a7b502ca93c108","src/components.rs":"f10d6cb79a14e76d151617330ab5fdb6cd4b4188c132132b590d6c2d799ab4fc","src/decoder.rs":"bf00a0ae8827709902fe1b7f53941374b4b78d82dba66ca6b01aca9d2ca41f7a","src/errors.rs":"6cffc17c3035860d33397bf7041c9a187352c9969181c717597e1a3a60907922","src/headers.rs":"e03fe57a3fb49bfd7b57447324ba50796f66c7dde8f9d22c5a9aa535b5358238","src/huffman.rs":"921649bd61aeeecb11bf91d7e76afad583e54717255824bf0c2d4bb6160d6b10","src/idct.rs":"3f13bffcad917132be9521dd9e773cb1b5138e4fc62a652ecaa658e4528b191e","src/idct/avx2.rs":"147dddafec6611072efe49a2fa69e554e7830f4d7117dc16f17489257dc1186a","src/idct/neon.rs":"a86faa66f084893d6f1b5a9c70533494ed7ae0d9b928ee330880e85c3764d2d7","src/idct/scalar.rs":"7bb6ed8cb9c347645e0a08e6f0c9233218e4016039a8683dd145c801b0120135","src/lib.rs":"40fc652d9dde24f0bd45c2eaa015a706164018e8fb70be36105db7428ee5716d","src/marker.rs":"2fb841df973ac2c9ad9ec25ca0222777ab023548ff3bf2d6fc9d1d78dd7b3605","src/mcu.rs":"4ad7d93dc85efc62612d165cf2dba58378ca1719244e133b6c5b319261186e6f","src/mcu_prog.rs":"19c30bec4eec2f0bbc294dae9e4722d7693eb460648226564bfb5fd7a1618a86","src/misc.rs":"4359da139b58f418f2e7beae18033a2601faad3df80b4866663fcd87653dae46","src/unsafe_utils.rs":"8fa830ca67b7f701461fe2382f8843faa33c98b5f83f1845f60c8ef788143c75","src/unsafe_utils_avx2.rs":"2e2a8294a8c8c6ca3e92356b47a088090c2c62853b37cfcadeba4ab55f545721","src/unsafe_utils_neon.rs":"b7087a9897c9e3c66a1bf7a910e7dab30e2a92ca3483c1b01101f69e07d05e87","src/upsampler.rs":"09b5192f4d7e58e7c348ad23f958d2a4677fdc49afdad70e5035e865a97beaf7","src/upsampler/scalar.rs":"efae37e90f82fdfaf40183126d89481066f0d006a2a2610ee8c2d423d30bf014","src/worker.rs":"ad40ff4185b60469428b956c8f0f24a666d488eeff9cf063a6c245cb06cddf0d"},"package":"29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "fa2c767a01d7d9373911d0bf63e0588553d67e0e" + }, + "path_in_vcs": "crates/zune-jpeg" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Benches.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Benches.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Benches.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Benches.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,79 @@ +# Benchmarks of popular jpeg libraries + +Here I compare how long it takes popular JPEG decoders to decode the below 7680*4320 image +of (now defunct ?) [Cutefish OS](https://en.cutefishos.com/) default wallpaper. +![img](benches/images/speed_bench.jpg) + +## About benchmarks + +Benchmarks are weird, especially IO & multi-threaded programs. This library uses both of the above hence performance may +vary. + +For best results shut down your machine, go take coffee, think about life and how it came to be and why people should +save the environment. + +Then power up your machine, if it's a laptop connect it to a power supply and if there is a setting for performance +mode, tweak it. + +Then run. + +## Benchmarks vs real world usage + +Real world usage may vary. + +Notice that I'm using a large image but probably most decoding will be small to medium images. + +To make the library thread safe, we do about 1.5-1.7x more allocations than libjpeg-turbo. Although, do note that the +allocations do not occur at ago, we allocate when needed and deallocate when not needed. + +Do note if memory bandwidth is a limitation. This is not for you. + +## Reproducibility + +The benchmarks are carried out on my local machine with an AMD Ryzen 5 4500u + +The benchmarks are reproducible. + +To reproduce them + +1. Clone this repository +2. Install rust(if you don't have it yet) +3. `cd` into the directory. +4. Run `cargo bench` + +## Performance features of the three libraries + +| feature | image-rs/jpeg-decoder | libjpeg-turbo | zune-jpeg | +|------------------------------|-----------------------|---------------|-----------| +| multithreaded | ✅ | ❌ | ❌ | +| platform specific intrinsics | ✅ | ✅ | ✅ | + +- Image-rs/jpeg-decoder uses [rayon] under the hood but it's under a feature + flag. + +- libjpeg-turbo uses hand-written asm for platform specific intrinsics, ported to + the most common architectures out there but falls back to scalar + code if it can't run in a platform. + +# Finally benchmarks + +[here] + +## Notes + +Benchmarks are ran at least once a week to catch regressions early and +are uploaded to Github pages. + +Machine specs can be found on the other [landing page] + +Benchmarks may not reflect real world usage(threads, other I/O machine bottlenecks) + +[landing page]:https://etemesi254.github.io/posts/Zune-Benchmarks/ + +[here]:https://etemesi254.github.io/assets/criterion/report/index.html + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo + +[jpeg-decoder]:https://github.com/image-rs/jpeg-decoder + +[rayon]:https://github.com/rayon-rs/rayon \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +dependencies = [ + "log", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.21" +dependencies = [ + "zune-core", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "zune-jpeg" +version = "0.4.21" +authors = ["caleb "] +build = false +exclude = [ + "/benches/images/*", + "/tests/*", + "/.idea/*", + "/.gradle/*", + "/test-images/*", + "fuzz/*", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A fast, correct and safe jpeg decoder" +readme = "README.md" +keywords = [ + "jpeg", + "jpeg-decoder", + "decoder", +] +categories = ["multimedia::images"] +license = "MIT OR Apache-2.0 OR Zlib" +repository = "https://github.com/etemesi254/zune-image/tree/dev/crates/zune-jpeg" + +[features] +default = [ + "x86", + "neon", + "std", +] +log = ["zune-core/log"] +neon = [] +std = ["zune-core/std"] +x86 = [] + +[lib] +name = "zune_jpeg" +path = "src/lib.rs" + +[dependencies.zune-core] +version = "0.4" + +[dev-dependencies] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(fuzzing)"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +[package] +name = "zune-jpeg" +version = "0.4.21" +authors = ["caleb "] +edition = "2021" +repository = "https://github.com/etemesi254/zune-image/tree/dev/crates/zune-jpeg" +license = "MIT OR Apache-2.0 OR Zlib" +keywords = ["jpeg", "jpeg-decoder", "decoder"] +categories = ["multimedia::images"] +exclude = ["/benches/images/*", "/tests/*", "/.idea/*", "/.gradle/*", "/test-images/*", "fuzz/*"] +description = "A fast, correct and safe jpeg decoder" + +[lints.rust] +# Disable feature checker for fuzzing since it's used and cargo doesn't +# seem to recognise fuzzing +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } + + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +x86 = [] +neon = [] +std = ["zune-core/std"] +log = ["zune-core/log"] +default = ["x86", "neon", "std"] + +[dependencies] +zune-core = { path = "../zune-core", version = "0.4" } + + +[dev-dependencies] +zune-ppm = { path = "../zune-ppm" } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Changelog.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Changelog.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Changelog.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/Changelog.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +## Version 0.3.17 + +- Fix no-std compilation + +## Version 0.3.16 + +- Add support for decoding to BGR and BGRA + +## Version 0.3.14 + +- Add ability to parse exif and ICC chunk. +- Fix images with one component that were down-sampled. + +### Version 0.3.13 + +- Allow decoding into pre-allocated buffer +- Clarify documentation + +### Version 0.3.11 + +- Add guards for SSE and AVX code paths(allows compiling for platforms that do not support it) + +### Version 0.3.0 + +- Overhaul to the whole decoder. +- Single threaded version +- Lightweight. + +### Version 0.2.0 + +- New `ZuneJpegOptions` struct, this is the now recommended way to set up decoding options for + decoding +- Deprecated previous options setting functions. +- More code cleanups +- Fixed new bugs discovered by fuzzing +- Removed dependency on `num_cpu` + +### Version 0.1.5 +- Allow user to set memory limits in during decoding explicitly via `set_limits` +- Fixed some bugs discovered by fuzzing +- Correctly handle small images less than 16 pixels +- Gracefully handle incorrectly sampled images. + +### Version 0.1.4 +- Remove all `unsafe` instances except platform dependent intrinsics. +- Numerous bug fixes identified by fuzzing. +- Expose `ImageInfo` to the crate root. + +### Version 0.1.3 +- Fix numerous panics found by fuzzing(thanks to @[Shnatsel] for the corpus) +- Add new method `set_num_threads` that allows one to explicitly set the number of threads to use to decode the image. + +### Version 0.1.2 +- Add more sub checks, contributed by @[5225225] +- Privatize some modules. + +### Version 0.1.1 +- Fix rgba/rgbx decoding when avx optimized functions were used +- Initial support for fuzzing +- Remove `align_alloc` method which was unsound (Thanks to @[HeroicKatora] for pointing that out) + +[Shnatsel]:https://github.com/Shnatsel +[HeroicKatora]:https://github.com/HeroicKatora +[5225225]:https://github.com/5225225 \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/README.md clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,104 @@ +# Zune-JPEG + +A fast, correct and safe jpeg decoder in pure Rust. + +## Usage + +The library provides a simple-to-use API for jpeg decoding +and an ability to add options to influence decoding. + +### Example + +```Rust +// Import the library +use zune_jpeg::JpegDecoder; +use std::fs::read; + +fn main()->Result<(),DecoderErrors> { + // load some jpeg data + let data = read("cat.jpg").unwrap(); + // create a decoder + let mut decoder = JpegDecoder::new(&data); + // decode the file + let pixels = decoder.decode()?; +} +``` + +The decoder supports more manipulations via `DecoderOptions`, +see additional documentation in the library. + +## Goals + +The implementation aims to have the following goals achieved, +in order of importance + +1. Safety - Do not segfault on errors or invalid input. Panics are okay, but + should be fixed when reported. `unsafe` is only used for SIMD intrinsics, + and can be turned off entirely both at compile time and at runtime. +2. Speed - Get the data as quickly as possible, which means + 1. Platform intrinsics code where justifiable + 2. Carefully written platform independent code that allows the + compiler to vectorize it. + 3. Regression tests. + 4. Watch the memory usage of the program +3. Usability - Provide utility functions like different color conversions functions. + +## Non-Goals + +- Bit identical results with libjpeg/libjpeg-turbo will never be an aim of this library. + Jpeg is a lossy format with very few parts specified by the standard + (i.e it doesn't give a reference upsampling and color conversion algorithm) + +## Features + +- [x] A Pretty fast 8*8 integer IDCT. +- [x] Fast Huffman Decoding +- [x] Fast color convert functions. +- [x] Support for extended colorspaces like GrayScale and RGBA +- [X] Single-threaded decoding. +- [X] Support for four component JPEGs, and esoteric color schemes like CYMK +- [X] Support for `no_std` +- [X] BGR/BGRA decoding support. + +## Crate Features + +| feature | on | Capabilities | +|---------|-----|---------------------------------------------------------------------------------------------| +| `x86` | yes | Enables `x86` specific instructions, specifically `avx` and `sse` for accelerated decoding. | +| `std` | yes | Enable linking to the `std` crate | + +Note that the `x86` features are automatically disabled on platforms that aren't x86 during compile +time hence there is no need to disable them explicitly if you are targeting such a platform. + +## Using in a `no_std` environment + +The crate can be used in a `no_std` environment with the `alloc` feature. + +But one is required to link to a working allocator for whatever environment the decoder +will be running on + +## Debug vs release + +The decoder heavily relies on platform specific intrinsics, namely AVX2 and SSE to gain speed-ups in decoding, +but they [perform poorly](https://godbolt.org/z/vPq57z13b) in debug builds. To get reasonable performance even +when compiling your program in debug mode, add this to your `Cargo.toml`: + +```toml +# `zune-jpeg` package will be always built with optimizations +[profile.dev.package.zune-jpeg] +opt-level = 3 +``` + +## Benchmarks + +The library tries to be at fast as [libjpeg-turbo] while being as safe as possible. +Platform specific intrinsics help get speed up intensive operations ensuring we can almost +match [libjpeg-turbo] speeds but speeds are always +- 10 ms of this library. + +For more up-to-date benchmarks, see the online repo with +benchmarks [here](https://etemesi254.github.io/assets/criterion/report/index.html) + + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo/ + +[image-rs/jpeg-decoder]:https://github.com/image-rs/jpeg-decoder/tree/master/src diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/bitstream.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/bitstream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/bitstream.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/bitstream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::if_not_else, + clippy::similar_names, + clippy::inline_always, + clippy::doc_markdown, + clippy::cast_sign_loss, + clippy::cast_possible_truncation +)] + +//! This file exposes a single struct that can decode a huffman encoded +//! Bitstream in a JPEG file +//! +//! This code is optimized for speed. +//! It's meant to be super duper super fast, because everyone else depends on this being fast. +//! It's (annoyingly) serial hence we cant use parallel bitstreams(it's variable length coding.) +//! +//! Furthermore, on the case of refills, we have to do bytewise processing because the standard decided +//! that we want to support markers in the middle of streams(seriously few people use RST markers). +//! +//! So we pull in all optimization steps: +//! - use `inline[always]`? ✅ , +//! - pre-execute most common cases ✅, +//! - add random comments ✅ +//! - fast paths ✅. +//! +//! Speed-wise: It is probably the fastest JPEG BitStream decoder to ever sail the seven seas because of +//! a couple of optimization tricks. +//! 1. Fast refills from libjpeg-turbo +//! 2. As few as possible branches in decoder fast paths. +//! 3. Accelerated AC table decoding borrowed from stb_image.h written by Fabian Gissen (@ rygorous), +//! improved by me to handle more cases. +//! 4. Safe and extensible routines(e.g. cool ways to eliminate bounds check) +//! 5. No unsafe here +//! +//! Readability comes as a second priority(I tried with variable names this time, and we are wayy better than libjpeg). +//! +//! Anyway if you are reading this it means your cool and I hope you get whatever part of the code you are looking for +//! (or learn something cool) +//! +//! Knock yourself out. +use alloc::string::ToString; +use core::cmp::min; +use alloc::format; + +use zune_core::bytestream::{ZByteReader, ZReaderTrait}; + +use crate::errors::DecodeErrors; +use crate::huffman::{HuffmanTable, HUFF_LOOKAHEAD}; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::UN_ZIGZAG; + +macro_rules! decode_huff { + ($stream:tt,$symbol:tt,$table:tt) => { + let mut code_length = $symbol >> HUFF_LOOKAHEAD; + + ($symbol) &= (1 << HUFF_LOOKAHEAD) - 1; + + if code_length > i32::from(HUFF_LOOKAHEAD) + { + // if the symbol cannot be resolved in the first HUFF_LOOKAHEAD bits, + // we know it lies somewhere between HUFF_LOOKAHEAD and 16 bits since jpeg imposes 16 bit + // limit, we can therefore look 16 bits ahead and try to resolve the symbol + // starting from 1+HUFF_LOOKAHEAD bits. + $symbol = ($stream).peek_bits::<16>() as i32; + // (Credits to Sean T. Barrett stb library for this optimization) + // maxcode is pre-shifted 16 bytes long so that it has (16-code_length) + // zeroes at the end hence we do not need to shift in the inner loop. + while code_length < 17{ + if $symbol < $table.maxcode[code_length as usize] { + break; + } + code_length += 1; + } + + if code_length == 17{ + // symbol could not be decoded. + // + // We may think, lets fake zeroes, noo + // panic, because Huffman codes are sensitive, probably everything + // after this will be corrupt, so no need to continue. + // panic!("Bad Huffman code length"); + return Err(DecodeErrors::Format(format!("Bad Huffman Code 0x{:X}, corrupt JPEG",$symbol))) + } + + $symbol >>= (16-code_length); + ($symbol) = i32::from( + ($table).values + [(($symbol + ($table).offset[code_length as usize]) & 0xFF) as usize], + ); + } + // drop bits read + ($stream).drop_bits(code_length as u8); + }; +} + +/// A `BitStream` struct, a bit by bit reader with super powers +/// +pub(crate) struct BitStream { + /// A MSB type buffer that is used for some certain operations + pub buffer: u64, + /// A TOP aligned MSB type buffer that is used to accelerate some operations like + /// peek_bits and get_bits. + /// + /// By top aligned, I mean the top bit (63) represents the top bit in the buffer. + aligned_buffer: u64, + /// Tell us the bits left the two buffer + pub(crate) bits_left: u8, + /// Did we find a marker(RST/EOF) during decoding? + pub marker: Option, + + /// Progressive decoding + pub successive_high: u8, + pub successive_low: u8, + spec_start: u8, + spec_end: u8, + pub eob_run: i32, + pub overread_by: usize, + /// True if we have seen end of image marker. + /// Don't read anything after that. + pub seen_eoi: bool, +} + +impl BitStream { + /// Create a new BitStream + pub(crate) const fn new() -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_high: 0, + successive_low: 0, + spec_start: 0, + spec_end: 0, + eob_run: 0, + overread_by: 0, + seen_eoi: false, + } + } + + /// Create a new Bitstream for progressive decoding + #[allow(clippy::redundant_field_names)] + pub(crate) fn new_progressive(ah: u8, al: u8, spec_start: u8, spec_end: u8) -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_high: ah, + successive_low: al, + spec_start: spec_start, + spec_end: spec_end, + eob_run: 0, + overread_by: 0, + seen_eoi: false, + } + } + + /// Refill the bit buffer by (a maximum of) 32 bits + /// + /// # Arguments + /// - `reader`:`&mut BufReader`: A mutable reference to an underlying + /// File/Memory buffer containing a valid JPEG stream + /// + /// This function will only refill if `self.count` is less than 32 + #[inline(always)] // to many call sites? ( perf improvement by 4%) + pub(crate) fn refill(&mut self, reader: &mut ZByteReader) -> Result + where + T: ZReaderTrait + { + /// Macro version of a single byte refill. + /// Arguments + /// buffer-> our io buffer, because rust macros cannot get values from + /// the surrounding environment bits_left-> number of bits left + /// to full refill + macro_rules! refill { + ($buffer:expr,$byte:expr,$bits_left:expr) => { + // read a byte from the stream + $byte = u64::from(reader.get_u8()); + self.overread_by += usize::from(reader.eof()); + // append to the buffer + // JPEG is a MSB type buffer so that means we append this + // to the lower end (0..8) of the buffer and push the rest bits above.. + $buffer = ($buffer << 8) | $byte; + // Increment bits left + $bits_left += 8; + // Check for special case of OxFF, to see if it's a stream or a marker + if $byte == 0xff { + // read next byte + let mut next_byte = u64::from(reader.get_u8()); + // Byte snuffing, if we encounter byte snuff, we skip the byte + if next_byte != 0x00 { + // skip that byte we read + while next_byte == 0xFF { + next_byte = u64::from(reader.get_u8()); + } + + if next_byte != 0x00 { + // Undo the byte append and return + $buffer >>= 8; + $bits_left -= 8; + + if $bits_left != 0 { + self.aligned_buffer = $buffer << (64 - $bits_left); + } + + self.marker = Marker::from_u8(next_byte as u8); + if next_byte == 0xD9 { + // special handling for eoi, fill some bytes,even if its zero, + // removes some panics + self.buffer <<= 8; + self.bits_left += 8; + self.aligned_buffer = self.buffer << (64 - self.bits_left); + + } + + return Ok(false); + } + } + } + }; + } + + + // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits) + if self.bits_left < 32 { + if self.marker.is_some() || self.overread_by > 0 || self.seen_eoi{ + // found a marker, or we are in EOI + // also we are in over-reading mode, where we fill it with zeroes + + // fill with zeroes + self.buffer <<= 32; + self.bits_left += 32; + self.aligned_buffer = self.buffer << (64 - self.bits_left); + return Ok(true); + } + + + // we optimize for the case where we don't have 255 in the stream and have 4 bytes left + // as it is the common case + // + // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is + // guaranteed not to advance in case of failure (is this true), so + // we revert the read later on (if we have 255), if this fails, we use the normal + // byte at a time read + + if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() { + // we have 4 bytes to spare, read the 4 bytes into a temporary buffer + // create buffer + let msb_buf = u32::from_be_bytes(bytes); + // check if we have 0xff + if !has_byte(msb_buf, 255) { + self.bits_left += 32; + self.buffer <<= 32; + self.buffer |= u64::from(msb_buf); + self.aligned_buffer = self.buffer << (64 - self.bits_left); + return Ok(true); + } + + reader.rewind(4); + } + // This serves two reasons, + // 1: Make clippy shut up + // 2: Favour register reuse + let mut byte; + // 4 refills, if all succeed the stream should contain enough bits to decode a + // value + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + // Construct an MSB buffer whose top bits are the bitstream we are currently holding. + self.aligned_buffer = self.buffer << (64 - self.bits_left); + } + return Ok(true); + } + /// Decode the DC coefficient in a MCU block. + /// + /// The decoded coefficient is written to `dc_prediction` + /// + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::unwrap_used + )] + #[inline(always)] + fn decode_dc( + &mut self, reader: &mut ZByteReader, dc_table: &HuffmanTable, dc_prediction: &mut i32 + ) -> Result + where + T: ZReaderTrait + { + let (mut symbol, r); + + if self.bits_left < 32 { + self.refill(reader)?; + }; + // look a head HUFF_LOOKAHEAD bits into the bitstream + symbol = self.peek_bits::(); + symbol = dc_table.lookup[symbol as usize]; + + decode_huff!(self, symbol, dc_table); + + if symbol != 0 { + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + } + // Update DC prediction + *dc_prediction = dc_prediction.wrapping_add(symbol); + + return Ok(true); + } + + /// Decode a Minimum Code Unit(MCU) as quickly as possible + /// + /// # Arguments + /// - reader: The bitstream from where we read more bits. + /// - dc_table: The Huffman table used to decode the DC coefficient + /// - ac_table: The Huffman table used to decode AC values + /// - block: A memory region where we will write out the decoded values + /// - DC prediction: Last DC value for this component + /// + #[allow( + clippy::many_single_char_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + #[inline(never)] + pub fn decode_mcu_block( + &mut self, reader: &mut ZByteReader, dc_table: &HuffmanTable, ac_table: &HuffmanTable, + qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32 + ) -> Result<(), DecodeErrors> + where + T: ZReaderTrait + { + // Get fast AC table as a reference before we enter the hot path + let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); + + let (mut symbol, mut r, mut fast_ac); + // Decode AC coefficients + let mut pos: usize = 1; + + // decode DC, dc prediction will contain the value + self.decode_dc(reader, dc_table, dc_prediction)?; + + // set dc to be the dc prediction. + block[0] = *dc_prediction * qt_table[0]; + + while pos < 64 { + self.refill(reader)?; + symbol = self.peek_bits::(); + fast_ac = ac_lookup[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fast_ac != 0 { + // FAST AC path + pos += ((fast_ac >> 4) & 15) as usize; // run + let t_pos = UN_ZIGZAG[min(pos, 63)] & 63; + + block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value + self.drop_bits((fast_ac & 15) as u8); + pos += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + pos += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + let t_pos = UN_ZIGZAG[pos & 63] & 63; + + block[t_pos] = symbol * qt_table[t_pos]; + + pos += 1; + } else if r != 15 { + return Ok(()); + } else { + pos += 16; + } + } + } + return Ok(()); + } + + /// Peek `look_ahead` bits ahead without discarding them from the buffer + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + const fn peek_bits(&self) -> i32 { + (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 + } + + /// Discard the next `N` bits without checking + #[inline] + fn drop_bits(&mut self, n: u8) { + debug_assert!(self.bits_left >= n); + //self.bits_left -= n; + self.bits_left = self.bits_left.saturating_sub(n); + self.aligned_buffer <<= n; + } + + /// Read `n_bits` from the buffer and discard them + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + fn get_bits(&mut self, n_bits: u8) -> i32 { + let mask = (1_u64 << n_bits) - 1; + + self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits)); + let bits = (self.aligned_buffer & mask) as i32; + self.bits_left = self.bits_left.wrapping_sub(n_bits); + bits + } + + /// Decode a DC block + #[allow(clippy::cast_possible_truncation)] + #[inline] + pub(crate) fn decode_prog_dc_first( + &mut self, reader: &mut ZByteReader, dc_table: &HuffmanTable, block: &mut i16, + dc_prediction: &mut i32 + ) -> Result<(), DecodeErrors> + where + T: ZReaderTrait + { + self.decode_dc(reader, dc_table, dc_prediction)?; + *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low); + return Ok(()); + } + #[inline] + pub(crate) fn decode_prog_dc_refine( + &mut self, reader: &mut ZByteReader, block: &mut i16 + ) -> Result<(), DecodeErrors> + where + T: ZReaderTrait + { + // refinement scan + if self.bits_left < 1 { + self.refill(reader)?; + } + + if self.get_bit() == 1 { + *block = block.wrapping_add(1 << self.successive_low); + } + + Ok(()) + } + + /// Get a single bit from the bitstream + fn get_bit(&mut self) -> u8 { + let k = (self.aligned_buffer >> 63) as u8; + // discard a bit + self.drop_bits(1); + return k; + } + pub(crate) fn decode_mcu_ac_first( + &mut self, reader: &mut ZByteReader, ac_table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZReaderTrait + { + let shift = self.successive_low; + let fast_ac = ac_table.ac_lookup.as_ref().unwrap(); + + let mut k = self.spec_start as usize; + let (mut symbol, mut r, mut fac); + + // EOB runs are handled in mcu_prog.rs + 'block: loop { + self.refill(reader)?; + + symbol = self.peek_bits::(); + fac = fast_ac[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fac != 0 { + // fast ac path + k += ((fac >> 4) & 15) as usize; // run + block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value + self.drop_bits((fac & 15) as u8); + k += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + k += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift); + k += 1; + } else { + if r != 15 { + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + self.eob_run -= 1; + break; + } + + k += 16; + } + } + + if k > self.spec_end as usize { + break 'block; + } + } + return Ok(true); + } + #[allow(clippy::too_many_lines, clippy::op_ref)] + pub(crate) fn decode_mcu_ac_refine( + &mut self, reader: &mut ZByteReader, table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZReaderTrait + { + let bit = (1 << self.successive_low) as i16; + + let mut k = self.spec_start; + let (mut symbol, mut r); + + if self.eob_run == 0 { + 'no_eob: loop { + // Decode a coefficient from the bit stream + self.refill(reader)?; + + symbol = self.peek_bits::(); + symbol = table.lookup[symbol as usize]; + + decode_huff!(self, symbol, table); + + r = symbol >> 4; + symbol &= 15; + + if symbol == 0 { + if r != 15 { + // EOB run is 2^r + bits + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + // EOB runs are handled by the eob logic + break 'no_eob; + } + } else { + if symbol != 1 { + return Err(DecodeErrors::HuffmanDecode( + "Bad Huffman code, corrupt JPEG?".to_string() + )); + } + // get sign bit + // We assume we have enough bits, which should be correct for sane images + // since we refill by 32 above + if self.get_bit() == 1 { + symbol = i32::from(bit); + } else { + symbol = i32::from(-bit); + } + } + + // Advance over already nonzero coefficients appending + // correction bits to the non-zeroes. + // A correction bit is 1 if the absolute value of the coefficient must be increased + + if k <= self.spec_end { + 'advance_nonzero: loop { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 { + if self.get_bit() == 1 && (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient += bit; + } else { + *coefficient -= bit; + } + } + + if self.bits_left < 1 { + self.refill(reader)?; + } + } else { + r -= 1; + + if r < 0 { + // reached target zero coefficient. + break 'advance_nonzero; + } + }; + + if k == self.spec_end { + break 'advance_nonzero; + } + + k += 1; + } + } + + if symbol != 0 { + let pos = UN_ZIGZAG[k as usize & 63]; + // output new non-zero coefficient. + block[pos & 63] = symbol as i16; + } + + k += 1; + + if k > self.spec_end { + break 'no_eob; + } + } + } + if self.eob_run > 0 { + // only run if block does not consists of purely zeroes + if &block[1..] != &[0; 63] { + self.refill(reader)?; + + while k <= self.spec_end { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 && self.get_bit() == 1 { + // check if we already modified it, if so do nothing, otherwise + // append the correction bit. + if (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient = coefficient.wrapping_add(bit); + } else { + *coefficient = coefficient.wrapping_sub(bit); + } + } + } + if self.bits_left < 1 { + // refill at the last possible moment + self.refill(reader)?; + } + k += 1; + } + } + // count a block completed in EOB run + self.eob_run -= 1; + } + return Ok(true); + } + + pub fn update_progressive_params(&mut self, ah: u8, al: u8, spec_start: u8, spec_end: u8) { + self.successive_high = ah; + self.successive_low = al; + self.spec_start = spec_start; + self.spec_end = spec_end; + } + + /// Reset the stream if we have a restart marker + /// + /// Restart markers indicate drop those bits in the stream and zero out + /// everything + #[cold] + pub fn reset(&mut self) { + self.bits_left = 0; + self.marker = None; + self.buffer = 0; + self.aligned_buffer = 0; + self.eob_run = 0; + } +} + +/// Do the equivalent of JPEG HUFF_EXTEND +#[inline(always)] +fn huff_extend(x: i32, s: i32) -> i32 { + // if x> 31) & (((-1) << (s)) + 1)) +} + +const fn has_zero(v: u32) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0; +} + +const fn has_byte(b: u32, val: u8) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + has_zero(b ^ ((!0_u32 / 255) * (val as u32))) +} + +// mod tests { +// use zune_core::bytestream::ZCursor; +// use crate::JpegDecoder; +// +// #[test] +// fn test_image() { +// let img = "/Users/etemesi/Downloads/PHO00008.JPG"; +// let data = std::fs::read(img).unwrap(); +// let mut decoder = JpegDecoder::new(ZCursor::new(&data[..])); +// decoder.decode().unwrap(); +// } +// } \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/avx.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/avx.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/avx.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/avx.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! AVX color conversion routines +//! +//! Okay these codes are cool +//! +//! Herein lies super optimized codes to do color conversions. +//! +//! +//! 1. The YCbCr to RGB use integer approximations and not the floating point equivalent. +//! That means we may be +- 2 of pixels generated by libjpeg-turbo jpeg decoding +//! (also libjpeg uses routines like `Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G`) +//! +//! Firstly, we use integers (fun fact:there is no part of this code base where were dealing with +//! floating points.., fun fact: the first fun fact wasn't even fun.) +//! +//! Secondly ,we have cool clamping code, especially for rgba , where we don't need clamping and we +//! spend our time cursing that Intel decided permute instructions to work like 2 128 bit vectors(the compiler opitmizes +//! it out to something cool). +//! +//! There isn't a lot here (not as fun as bitstream ) but I hope you find what you're looking for. +//! +//! O and ~~subscribe to my youtube channel~~ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#![cfg(feature = "x86")] +#![allow( + clippy::wildcard_imports, + clippy::cast_possible_truncation, + clippy::too_many_arguments, + clippy::inline_always, + clippy::doc_markdown, + dead_code +)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +use crate::color_convert::scalar::{CB_CF, CR_CF, C_G_CB_COEF_2, C_G_CR_COEF_1, YUV_RND, Y_CF}; + +pub union YmmRegister { + // both are 32 when using std::mem::size_of + mm256: __m256i, + // for avx color conversion + array: [i16; 16] +} + +const R_AVX_COEF: i32 = i32::from_ne_bytes([CR_CF.to_ne_bytes()[0], CR_CF.to_ne_bytes()[1], 0, 0]); +const B_AVX_COEF: i32 = i32::from_ne_bytes([0, 0, CB_CF.to_ne_bytes()[0], CB_CF.to_ne_bytes()[1]]); +const G_COEF_AVX_COEF: i32 = i32::from_ne_bytes([ + C_G_CR_COEF_1.to_ne_bytes()[0], + C_G_CR_COEF_1.to_ne_bytes()[1], + C_G_CB_COEF_2.to_ne_bytes()[0], + C_G_CB_COEF_2.to_ne_bytes()[1] +]); + +//-------------------------------------------------------------------------------------------------- +// AVX conversion routines +//-------------------------------------------------------------------------------------------------- + +/// +/// Convert YCBCR to RGB using AVX instructions +/// +/// # Note +///**IT IS THE RESPONSIBILITY OF THE CALLER TO CALL THIS IN CPUS SUPPORTING +/// AVX2 OTHERWISE THIS IS UB** +/// +/// *Peace* +/// +/// This library itself will ensure that it's never called in CPU's not +/// supporting AVX2 +/// +/// # Arguments +/// - `y`,`cb`,`cr`: A reference of 8 i32's +/// - `out`: The output array where we store our converted items +/// - `offset`: The position from 0 where we write these RGB values +#[inline(always)] +pub fn ycbcr_to_rgb_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // call this in another function to tell RUST to vectorize this + // storing + unsafe { + ycbcr_to_rgb_avx2_1(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn ycbcr_to_rgb_avx2_1( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + let (mut r, mut g, mut b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + + r = _mm256_packus_epi16(r, _mm256_setzero_si256()); + g = _mm256_packus_epi16(g, _mm256_setzero_si256()); + b = _mm256_packus_epi16(b, _mm256_setzero_si256()); + + r = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(r); + g = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(g); + b = _mm256_permute4x64_epi64::<{ shuffle(3, 1, 2, 0) }>(b); + + let sh_r = _mm256_setr_epi8( + 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, + 9, 4, 15, 10, 5 + ); + let sh_g = _mm256_setr_epi8( + 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, + 14, 9, 4, 15, 10 + ); + let sh_b = _mm256_setr_epi8( + 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, + 3, 14, 9, 4, 15 + ); + + let r0 = _mm256_shuffle_epi8(r, sh_r); + let g0 = _mm256_shuffle_epi8(g, sh_g); + let b0 = _mm256_shuffle_epi8(b, sh_b); + + let m0 = _mm256_setr_epi8( + 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + 0, 0, -1, 0, 0 + ); + let m1 = _mm256_setr_epi8( + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + -1, 0, 0, -1, 0 + ); + + let p0 = _mm256_blendv_epi8(_mm256_blendv_epi8(r0, g0, m0), b0, m1); + let p1 = _mm256_blendv_epi8(_mm256_blendv_epi8(g0, b0, m0), r0, m1); + let p2 = _mm256_blendv_epi8(_mm256_blendv_epi8(b0, r0, m0), g0, m1); + + let rgb0 = _mm256_permute2x128_si256::<32>(p0, p1); + let rgb1 = _mm256_permute2x128_si256::<48>(p2, p0); + + _mm256_storeu_si256(out.as_mut_ptr().cast(), rgb0); + _mm_storeu_si128(out[32..].as_mut_ptr().cast(), _mm256_castsi256_si128(rgb1)); + + *offset += 48; +} + +// Enabled avx2 automatically enables avx. +#[inline] +#[target_feature(enable = "avx2")] +/// A baseline implementation of YCbCr to RGB conversion which does not carry +/// out clamping +/// +/// This is used by the `ycbcr_to_rgba_avx` and `ycbcr_to_rgbx` conversion +/// routines +unsafe fn ycbcr_to_rgb_baseline_no_clamp( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (__m256i, __m256i, __m256i) { + // Load values into a register + // + let y_c = _mm256_loadu_si256(y.as_ptr().cast()); + let cb_c = _mm256_loadu_si256(cb.as_ptr().cast()); + let cr_c = _mm256_loadu_si256(cr.as_ptr().cast()); + + // Here we want to use _mm256_madd_epi16 to perform 2 multiplications + // and one addition per instruction. + + // At first, we have to pack i16 U and V that stores u8 into one u8 [U,V] + // then zero extend, and keep in mind that lanes is already been permuted. + + let y_coeff = _mm256_set1_epi32(i32::from(Y_CF)); + let cr_coeff = _mm256_set1_epi32(R_AVX_COEF); + let cb_coeff = _mm256_set1_epi32(B_AVX_COEF); + let cg_coeff = _mm256_set1_epi32(G_COEF_AVX_COEF); + let v_rnd = _mm256_set1_epi32(i32::from(YUV_RND)); + let uv_bias = _mm256_set1_epi16(128); + + // UV in memory because x86/x86_64 is always little endian + let v_0 = _mm256_slli_epi16::<8>(cb_c); + let u_v_8 = _mm256_or_si256(v_0, cr_c); + + let mut u_v_lo = _mm256_unpacklo_epi8(u_v_8, _mm256_setzero_si256()); + let mut u_v_hi = _mm256_unpackhi_epi8(u_v_8, _mm256_setzero_si256()); + + let mut y_lo = _mm256_unpacklo_epi16(y_c, _mm256_setzero_si256()); + let mut y_hi = _mm256_unpackhi_epi16(y_c, _mm256_setzero_si256()); + + u_v_lo = _mm256_sub_epi16(u_v_lo, uv_bias); + u_v_hi = _mm256_sub_epi16(u_v_hi, uv_bias); + + y_lo = _mm256_madd_epi16(y_lo, y_coeff); + y_hi = _mm256_madd_epi16(y_hi, y_coeff); + + let mut r_lo = _mm256_madd_epi16(u_v_lo, cr_coeff); + let mut r_hi = _mm256_madd_epi16(u_v_hi, cr_coeff); + + let mut g_lo = _mm256_madd_epi16(u_v_lo, cg_coeff); + let mut g_hi = _mm256_madd_epi16(u_v_hi, cg_coeff); + + // This ordering is preferred to reduce register file pressure. + + y_lo = _mm256_add_epi32(y_lo, v_rnd); + y_hi = _mm256_add_epi32(y_hi, v_rnd); + + let mut b_lo = _mm256_madd_epi16(u_v_lo, cb_coeff); + let mut b_hi = _mm256_madd_epi16(u_v_hi, cb_coeff); + + r_lo = _mm256_add_epi32(r_lo, y_lo); + r_hi = _mm256_add_epi32(r_hi, y_hi); + + g_lo = _mm256_add_epi32(g_lo, y_lo); + g_hi = _mm256_add_epi32(g_hi, y_hi); + + b_lo = _mm256_add_epi32(b_lo, y_lo); + b_hi = _mm256_add_epi32(b_hi, y_hi); + + r_lo = _mm256_srai_epi32::<14>(r_lo); + r_hi = _mm256_srai_epi32::<14>(r_hi); + + g_lo = _mm256_srai_epi32::<14>(g_lo); + g_hi = _mm256_srai_epi32::<14>(g_hi); + + b_lo = _mm256_srai_epi32::<14>(b_lo); + b_hi = _mm256_srai_epi32::<14>(b_hi); + + let r = _mm256_packus_epi32(r_lo, r_hi); + let g = _mm256_packus_epi32(g_lo, g_hi); + let b = _mm256_packus_epi32(b_lo, b_hi); + + return (r, g, b); +} + +#[inline(always)] +pub fn ycbcr_to_rgba_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + unsafe { + ycbcr_to_rgba_unsafe(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +#[rustfmt::skip] +unsafe fn ycbcr_to_rgba_unsafe( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], + out: &mut [u8], + offset: &mut usize, +) +{ + // check if we have enough space to write. + let tmp:& mut [u8; 64] = out.get_mut(*offset..*offset + 64).expect("Slice to small cannot write").try_into().unwrap(); + + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + + // set alpha channel to 255 for opaque + + // And no these comments were not from me pressing the keyboard + + // Pack the integers into u8's using unsigned saturation. + let c = _mm256_packus_epi16(r, g); //aaaaa_bbbbb_aaaaa_bbbbbb + let d = _mm256_packus_epi16(b, _mm256_set1_epi16(255)); // cccccc_dddddd_ccccccc_ddddd + // transpose_u16 and interleave channels + let e = _mm256_unpacklo_epi8(c, d); //ab_ab_ab_ab_ab_ab_ab_ab + let f = _mm256_unpackhi_epi8(c, d); //cd_cd_cd_cd_cd_cd_cd_cd + // final transpose_u16 + let g = _mm256_unpacklo_epi8(e, f); //abcd_abcd_abcd_abcd_abcd + let h = _mm256_unpackhi_epi8(e, f); + + // undo packus shuffling... + let i = _mm256_permute2x128_si256::<{ shuffle(3, 2, 1, 0) }>(g, h); + + let j = _mm256_permute2x128_si256::<{ shuffle(1, 2, 3, 0) }>(g, h); + + let k = _mm256_permute2x128_si256::<{ shuffle(3, 2, 0, 1) }>(g, h); + + let l = _mm256_permute2x128_si256::<{ shuffle(0, 3, 2, 1) }>(g, h); + + let m = _mm256_blend_epi32::<0b1111_0000>(i, j); + + let n = _mm256_blend_epi32::<0b1111_0000>(k, l); + + // Store + // Use streaming instructions to prevent polluting the cache? + _mm256_storeu_si256(tmp.as_mut_ptr().cast(), m); + + _mm256_storeu_si256(tmp[32..].as_mut_ptr().cast(), n); + + *offset += 64; +} + +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/neon64.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/neon64.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/neon64.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/neon64.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Aarch64 color conversion routines +//! NEON is mandatory on aarch64. + +#![cfg(all(feature = "neon", target_arch = "aarch64"))] +use std::arch::aarch64::*; + +use crate::color_convert::scalar::{CB_CF, CR_CF, C_G_CB_COEF_2, C_G_CR_COEF_1, YUV_RND, Y_CF}; + +const C_1: u64 = u64::from_ne_bytes([ + Y_CF.to_ne_bytes()[0], + Y_CF.to_ne_bytes()[1], + CR_CF.to_ne_bytes()[0], + CR_CF.to_ne_bytes()[1], + CB_CF.to_ne_bytes()[0], + CB_CF.to_ne_bytes()[1], + C_G_CR_COEF_1.to_ne_bytes()[0], + C_G_CR_COEF_1.to_ne_bytes()[1] +]); +const C_2: u64 = u64::from_ne_bytes([ + C_G_CB_COEF_2.to_ne_bytes()[0], + C_G_CB_COEF_2.to_ne_bytes()[1], + 0, + 0, + 0, + 0, + 0, + 0 +]); + +#[inline(always)] +unsafe fn ycbcr_to_rgb_baseline_no_clamp( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (uint8x16_t, uint8x16_t, uint8x16_t) { + // NEON has 32 registers, so it is good idea to utilize a lot of variables at once + + let cb_cr_bias = vdupq_n_s16(128); + // 0 - Y coeff, 1 - Cr, 2 - Cb, 3 - G1, 4 - G2 + let coefficients = vcombine_s16(vcreate_s16(C_1), vcreate_s16(C_2)); + + let y0 = vld1q_s16(y.as_ptr().cast()); + let y1 = vld1q_s16(y[8..].as_ptr().cast()); + + let mut cb0 = vld1q_s16(cb.as_ptr().cast()); + let mut cb1 = vld1q_s16(cb[8..].as_ptr().cast()); + + let mut cr0 = vld1q_s16(cr.as_ptr().cast()); + let mut cr1 = vld1q_s16(cr[8..].as_ptr().cast()); + + cb0 = vsubq_s16(cb0, cb_cr_bias); + cb1 = vsubq_s16(cb1, cb_cr_bias); + + cr0 = vsubq_s16(cr0, cb_cr_bias); + cr1 = vsubq_s16(cr1, cb_cr_bias); + + let bias = vdupq_n_s32(i32::from(YUV_RND)); + + let acc0 = vmlal_laneq_s16::<0>(bias, vget_low_s16(y0), coefficients); + let acc1 = vmlal_high_laneq_s16::<0>(bias, y0, coefficients); + let acc2 = vmlal_laneq_s16::<0>(bias, vget_low_s16(y1), coefficients); + let acc3 = vmlal_high_laneq_s16::<0>(bias, y1, coefficients); + + let r0 = vmlal_laneq_s16::<1>(acc0, vget_low_s16(cr0), coefficients); + let r1 = vmlal_high_laneq_s16::<1>(acc1, cr0, coefficients); + let r2 = vmlal_laneq_s16::<1>(acc2, vget_low_s16(cr1), coefficients); + let r3 = vmlal_high_laneq_s16::<1>(acc3, cr1, coefficients); + + let b0 = vmlal_laneq_s16::<2>(acc0, vget_low_s16(cb0), coefficients); + let b1 = vmlal_high_laneq_s16::<2>(acc1, cb0, coefficients); + let b2 = vmlal_laneq_s16::<2>(acc2, vget_low_s16(cb1), coefficients); + let b3 = vmlal_high_laneq_s16::<2>(acc3, cb1, coefficients); + + // Saturating shift right with signed -> unsigned saturation + let qr0 = vqshrun_n_s32::<14>(r0); + let qr1 = vqshrun_n_s32::<14>(r1); + let qr2 = vqshrun_n_s32::<14>(r2); + let qr3 = vqshrun_n_s32::<14>(r3); + + let mut g0 = vmlal_laneq_s16::<4>(acc0, vget_low_s16(cb0), coefficients); + let mut g1 = vmlal_high_laneq_s16::<4>(acc1, cb0, coefficients); + let mut g2 = vmlal_laneq_s16::<4>(acc2, vget_low_s16(cb1), coefficients); + let mut g3 = vmlal_high_laneq_s16::<4>(acc3, cb1, coefficients); + + let qb0 = vqshrun_n_s32::<14>(b0); + let qb1 = vqshrun_n_s32::<14>(b1); + let qb2 = vqshrun_n_s32::<14>(b2); + let qb3 = vqshrun_n_s32::<14>(b3); + + let r0 = vqmovn_u16(vcombine_u16(qr0, qr1)); + let r1 = vqmovn_u16(vcombine_u16(qr2, qr3)); + + let b0 = vqmovn_u16(vcombine_u16(qb0, qb1)); + let b1 = vqmovn_u16(vcombine_u16(qb2, qb3)); + + g0 = vmlal_laneq_s16::<3>(g0, vget_low_s16(cr0), coefficients); + g1 = vmlal_high_laneq_s16::<3>(g1, cr0, coefficients); + g2 = vmlal_laneq_s16::<3>(g2, vget_low_s16(cr1), coefficients); + g3 = vmlal_high_laneq_s16::<3>(g3, cr1, coefficients); + + let qg0 = vqshrun_n_s32::<14>(g0); + let qg1 = vqshrun_n_s32::<14>(g1); + let qg2 = vqshrun_n_s32::<14>(g2); + let qg3 = vqshrun_n_s32::<14>(g3); + + let g0 = vqmovn_u16(vcombine_u16(qg0, qg1)); + let g1 = vqmovn_u16(vcombine_u16(qg2, qg3)); + + ( + vcombine_u8(r0, r1), + vcombine_u8(g0, g1), + vcombine_u8(b0, b1) + ) +} + +#[inline(always)] +pub fn ycbcr_to_rgb_neon( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // call this in another function to tell RUST to vectorize this + // storing + unsafe { + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + vst3q_u8(out.as_mut_ptr(), uint8x16x3_t(r, g, b)); + *offset += 48; + } +} + +#[inline(always)] +pub fn ycbcr_to_rgba_neon( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + unsafe { + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + vst4q_u8(out.as_mut_ptr(), uint8x16x4_t(r, g, b, vdupq_n_u8(255))); + *offset += 64; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use core::convert::TryInto; + +// Bt.601 Full Range inverse coefficients computed with 14 bits of precision with MPFR. +// This is important to keep them in i16. +// In most cases LLVM will detect what we're doing i16 widening to i32 math and will use +// appropriate optimizations. +pub(crate) const Y_CF: i16 = 16384; +pub(crate) const CR_CF: i16 = 22970; +pub(crate) const CB_CF: i16 = 29032; +pub(crate) const C_G_CR_COEF_1: i16 = -11700; +pub(crate) const C_G_CB_COEF_2: i16 = -5638; +pub(crate) const YUV_PREC: i16 = 14; +// Rounding const for YUV -> RGB conversion: floating equivalent 0.499(9). +pub(crate) const YUV_RND: i16 = (1 << (YUV_PREC - 1)) - 1; + +/// Limit values to 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, dead_code)] +fn clamp(a: i32) -> u8 { + a.clamp(0, 255) as u8 +} + +/// YCbCr to RGBA color conversion + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgba_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 64 elements for Rust to see we won't go out of bounds. + let opt: &mut [u8; 64] = output_position + .get_mut(0..64) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + for ((&y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(4)) + { + let cr = cr - 128; + let cb = cb - 128; + + let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND); + + let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC; + let g = (y0 + + i32::from(cr) * i32::from(C_G_CR_COEF_1) + + i32::from(cb) * i32::from(C_G_CB_COEF_2)) + >> YUV_PREC; + let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC; + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + out[3] = 255; + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + out[3] = 255; + } + } + *pos += 64; +} + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgb_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 48 elements + let opt: &mut [u8; 48] = output_position + .get_mut(0..48) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + + for ((&y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(3)) + { + let cr = cr - 128; + let cb = cb - 128; + + let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND); + + let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC; + let g = (y0 + + i32::from(cr) * i32::from(C_G_CR_COEF_1) + + i32::from(cb) * i32::from(C_G_CB_COEF_2)) + >> YUV_PREC; + let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC; + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + } + } + + // Increment pos + *pos += 48; +} + +pub fn ycbcr_to_grayscale(y: &[i16], width: usize, padded_width: usize, output: &mut [u8]) { + for (y_in, out) in y + .chunks_exact(padded_width) + .zip(output.chunks_exact_mut(width)) + { + for (y, out) in y_in.iter().zip(out.iter_mut()) { + *out = *y as u8; + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/color_convert.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::many_single_char_names, + clippy::similar_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::too_many_arguments, + clippy::doc_markdown +)] + +//! Color space conversion routines +//! +//! This files exposes functions to convert one colorspace to another in a jpeg +//! image +//! +//! Currently supported conversions are +//! +//! - `YCbCr` to `RGB,RGBA,GRAYSCALE,RGBX`. +//! +//! +//! Hey there, if your reading this it means you probably need something, so let me help you. +//! +//! There are 3 supported cpu extensions here. +//! 1. Scalar +//! 2. SSE +//! 3. AVX +//! +//! There are two types of the color convert functions +//! +//! 1. Acts on 16 pixels. +//! 2. Acts on 8 pixels. +//! +//! The reason for this is because when implementing the AVX part it occurred to me that we can actually +//! do better and process 2 MCU's if we change IDCT return type to be `i16's`, since a lot of +//! CPU's these days support AVX extensions, it becomes nice if we optimize for that path , +//! therefore AVX routines can process 16 pixels directly and SSE and Scalar just compensate. +//! +//! By compensating, I mean I wrote the 16 pixels version operating on the 8 pixel version twice. +//! +//! Therefore if your looking to optimize some routines, probably start there. + +pub use scalar::ycbcr_to_grayscale; +use zune_core::colorspace::ColorSpace; +use zune_core::options::DecoderOptions; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(feature = "x86")] +pub use crate::color_convert::avx::{ycbcr_to_rgb_avx2, ycbcr_to_rgba_avx2}; +use crate::decoder::ColorConvert16Ptr; + +mod avx; +mod neon64; +mod scalar; + +#[allow(unused_variables)] +pub fn choose_ycbcr_to_rgb_convert_func( + type_need: ColorSpace, options: &DecoderOptions +) -> Option { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + use zune_core::log::debug; + if options.use_avx2() { + debug!("Using AVX optimised color conversion functions"); + + // I believe avx2 means sse4 is also available + // match colorspace + match type_need { + ColorSpace::RGB => return Some(ycbcr_to_rgb_avx2), + ColorSpace::RGBA => return Some(ycbcr_to_rgba_avx2), + _ => () // fall through to scalar, which has more types + }; + } + } + #[cfg(all(feature = "neon", target_arch = "aarch64"))] + { + if options.use_neon() { + use crate::color_convert::neon64::{ycbcr_to_rgb_neon, ycbcr_to_rgba_neon}; + match type_need { + ColorSpace::RGB => return Some(ycbcr_to_rgb_neon), + ColorSpace::RGBA => return Some(ycbcr_to_rgba_neon), + _ => () // fall through to scalar, which has more types + }; + } + } + // when there is no x86 or we haven't returned by here, resort to scalar + return match type_need { + ColorSpace::RGB => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + ColorSpace::RGBA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGRA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGR => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + _ => None + }; +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/components.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/components.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/components.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/components.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This module exports a single struct to store information about +//! JPEG image components +//! +//! The data is extracted from a SOF header. + +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::log::trace; + +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::upsampler::upsample_no_op; + +/// Represents an up-sampler function, this function will be called to upsample +/// a down-sampled image + +pub type UpSampler = fn( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16] +); + +/// Component Data from start of frame +#[derive(Clone)] +pub(crate) struct Components { + /// The type of component that has the metadata below, can be Y,Cb or Cr + pub component_id: ComponentID, + /// Sub-sampling ratio of this component in the x-plane + pub vertical_sample: usize, + /// Sub-sampling ratio of this component in the y-plane + pub horizontal_sample: usize, + /// DC huffman table position + pub dc_huff_table: usize, + /// AC huffman table position for this element. + pub ac_huff_table: usize, + /// Quantization table number + pub quantization_table_number: u8, + /// Specifies quantization table to use with this component + pub quantization_table: [i32; 64], + /// dc prediction for the component + pub dc_pred: i32, + /// An up-sampling function, can be basic or SSE, depending + /// on the platform + pub up_sampler: UpSampler, + /// How pixels do we need to go to get to the next line? + pub width_stride: usize, + /// Component ID for progressive + pub id: u8, + /// Whether we need to decode this image component. + pub needed: bool, + /// Upsample scanline + pub raw_coeff: Vec, + /// Upsample destination, stores a scanline worth of sub sampled data + pub upsample_dest: Vec, + /// previous row, used to handle MCU boundaries + pub row_up: Vec, + /// current row, used to handle MCU boundaries again + pub row: Vec, + pub first_row_upsample_dest: Vec, + pub idct_pos: usize, + pub x: usize, + pub w2: usize, + pub y: usize, + pub sample_ratio: SampleRatios, + // a very annoying bug + pub fix_an_annoying_bug: usize +} + +impl Components { + /// Create a new instance from three bytes from the start of frame + #[inline] + pub fn from(a: [u8; 3], pos: u8) -> Result { + // it's a unique identifier. + // doesn't have to be ascending + // see tests/inputs/huge_sof_number + // + // For such cases, use the position of the component + // to determine width + + let id = match pos { + 0 => ComponentID::Y, + 1 => ComponentID::Cb, + 2 => ComponentID::Cr, + 3 => ComponentID::Q, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown component id found,{pos}, expected value between 1 and 4" + ))) + } + }; + + let horizontal_sample = (a[1] >> 4) as usize; + let vertical_sample = (a[1] & 0x0f) as usize; + let quantization_table_number = a[2]; + // confirm quantization number is between 0 and MAX_COMPONENTS + if usize::from(quantization_table_number) >= MAX_COMPONENTS { + return Err(DecodeErrors::Format(format!( + "Too large quantization number :{quantization_table_number}, expected value between 0 and {MAX_COMPONENTS}" + ))); + } + // check that upsampling ratios are powers of two + // if these fail, it's probably a corrupt image. + if !horizontal_sample.is_power_of_two() { + return Err(DecodeErrors::Format(format!( + "Horizontal sample is not a power of two({horizontal_sample}) cannot decode" + ))); + } + + if !vertical_sample.is_power_of_two() { + return Err(DecodeErrors::Format(format!( + "Vertical sub-sample is not power of two({vertical_sample}) cannot decode" + ))); + } + + trace!( + "Component ID:{:?} \tHS:{} VS:{} QT:{}", + id, + horizontal_sample, + vertical_sample, + quantization_table_number + ); + + Ok(Components { + component_id: id, + vertical_sample, + horizontal_sample, + quantization_table_number, + first_row_upsample_dest: vec![], + // These two will be set with sof marker + dc_huff_table: 0, + ac_huff_table: 0, + quantization_table: [0; 64], + dc_pred: 0, + up_sampler: upsample_no_op, + // set later + width_stride: horizontal_sample, + id: a[0], + needed: true, + raw_coeff: vec![], + upsample_dest: vec![], + row_up: vec![], + row: vec![], + idct_pos: 0, + x: 0, + y: 0, + w2: 0, + sample_ratio: SampleRatios::None, + fix_an_annoying_bug: 1 + }) + } + /// Setup space for upsampling + /// + /// During upsample, we need a reference of the last row so that upsampling can + /// proceed correctly, + /// so we store the last line of every scanline and use it for the next upsampling procedure + /// to store this, but since we don't need it for 1v1 upsampling, + /// we only call this for routines that need upsampling + /// + /// # Requirements + /// - width stride of this element is set for the component. + pub fn setup_upsample_scanline(&mut self) { + self.row = vec![0; self.width_stride * self.vertical_sample]; + self.row_up = vec![0; self.width_stride * self.vertical_sample]; + self.first_row_upsample_dest = + vec![128; self.vertical_sample * self.width_stride * self.sample_ratio.sample()]; + self.upsample_dest = + vec![0; self.width_stride * self.sample_ratio.sample() * self.fix_an_annoying_bug * 8]; + } +} + +/// Component ID's +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum ComponentID { + /// Luminance channel + Y, + /// Blue chrominance + Cb, + /// Red chrominance + Cr, + /// Q or fourth component + Q +} + +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum SampleRatios { + HV, + V, + H, + Generic(usize, usize), + None +} + +impl SampleRatios { + pub fn sample(self) -> usize { + match self { + SampleRatios::HV => 4, + SampleRatios::V | SampleRatios::H => 2, + SampleRatios::Generic(a, b) => a * b, + SampleRatios::None => 1 + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Main image logic. +#![allow(clippy::doc_markdown)] + +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::bytestream::{ZByteReader, ZReaderTrait}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{error, trace, warn}; +use zune_core::options::DecoderOptions; + +use crate::color_convert::choose_ycbcr_to_rgb_convert_func; +use crate::components::{Components, SampleRatios}; +use crate::errors::{DecodeErrors, UnsupportedSchemes}; +use crate::headers::{ + parse_app1, parse_app13, parse_app14, parse_app2, parse_dqt, parse_huffman, parse_sos, + parse_start_of_frame +}; +use crate::huffman::HuffmanTable; +use crate::idct::choose_idct_func; +use crate::marker::Marker; +use crate::misc::SOFMarkers; +use crate::upsampler::{ + choose_horizontal_samp_function, choose_hv_samp_function, choose_v_samp_function, + generic_sampler, upsample_no_op +}; + +/// Maximum components +pub(crate) const MAX_COMPONENTS: usize = 4; + +/// Maximum image dimensions supported. +pub(crate) const MAX_DIMENSIONS: usize = 1 << 27; + +/// Color conversion function that can convert YCbCr colorspace to RGB(A/X) for +/// 16 values +/// +/// The following are guarantees to the following functions +/// +/// 1. The `&[i16]` slices passed contain 16 items +/// +/// 2. The slices passed are in the following order +/// `y,cb,cr` +/// +/// 3. `&mut [u8]` is zero initialized +/// +/// 4. `&mut usize` points to the position in the array where new values should +/// be used +/// +/// The pointer should +/// 1. Carry out color conversion +/// 2. Update `&mut usize` with the new position + +pub type ColorConvert16Ptr = fn(&[i16; 16], &[i16; 16], &[i16; 16], &mut [u8], &mut usize); + +/// IDCT function prototype +/// +/// This encapsulates a dequantize and IDCT function which will carry out the +/// following functions +/// +/// Multiply each 64 element block of `&mut [i16]` with `&Aligned32<[i32;64]>` +/// Carry out IDCT (type 3 dct) on ach block of 64 i16's +pub type IDCTPtr = fn(&mut [i32; 64], &mut [i16], usize); + +/// An encapsulation of an ICC chunk +pub(crate) struct ICCChunk { + pub(crate) seq_no: u8, + pub(crate) num_markers: u8, + pub(crate) data: Vec +} + +/// A JPEG Decoder Instance. +#[allow(clippy::upper_case_acronyms, clippy::struct_excessive_bools)] +pub struct JpegDecoder { + /// Struct to hold image information from SOI + pub(crate) info: ImageInfo, + /// Quantization tables, will be set to none and the tables will + /// be moved to `components` field + pub(crate) qt_tables: [Option<[i32; 64]>; MAX_COMPONENTS], + /// DC Huffman Tables with a maximum of 4 tables for each component + pub(crate) dc_huffman_tables: [Option; MAX_COMPONENTS], + /// AC Huffman Tables with a maximum of 4 tables for each component + pub(crate) ac_huffman_tables: [Option; MAX_COMPONENTS], + /// Image components, holds information like DC prediction and quantization + /// tables of a component + pub(crate) components: Vec, + /// maximum horizontal component of all channels in the image + pub(crate) h_max: usize, + // maximum vertical component of all channels in the image + pub(crate) v_max: usize, + /// mcu's width (interleaved scans) + pub(crate) mcu_width: usize, + /// MCU height(interleaved scans + pub(crate) mcu_height: usize, + /// Number of MCU's in the x plane + pub(crate) mcu_x: usize, + /// Number of MCU's in the y plane + pub(crate) mcu_y: usize, + /// Is the image interleaved? + pub(crate) is_interleaved: bool, + pub(crate) sub_sample_ratio: SampleRatios, + /// Image input colorspace, should be YCbCr for a sane image, might be + /// grayscale too + pub(crate) input_colorspace: ColorSpace, + // Progressive image details + /// Is the image progressive? + pub(crate) is_progressive: bool, + + /// Start of spectral scan + pub(crate) spec_start: u8, + /// End of spectral scan + pub(crate) spec_end: u8, + /// Successive approximation bit position high + pub(crate) succ_high: u8, + /// Successive approximation bit position low + pub(crate) succ_low: u8, + /// Number of components. + pub(crate) num_scans: u8, + // Function pointers, for pointy stuff. + /// Dequantize and idct function + // This is determined at runtime which function to run, statically it's + // initialized to a platform independent one and during initialization + // of this struct, we check if we can switch to a faster one which + // depend on certain CPU extensions. + pub(crate) idct_func: IDCTPtr, + // Color convert function which acts on 16 YCbCr values + pub(crate) color_convert_16: ColorConvert16Ptr, + pub(crate) z_order: [usize; MAX_COMPONENTS], + /// restart markers + pub(crate) restart_interval: usize, + pub(crate) todo: usize, + // decoder options + pub(crate) options: DecoderOptions, + // byte-stream + pub(crate) stream: ZByteReader, + // Indicate whether headers have been decoded + pub(crate) headers_decoded: bool, + pub(crate) seen_sof: bool, + // exif data, lifted from app2 + pub(crate) exif_data: Option>, + + pub(crate) icc_data: Vec, + pub(crate) is_mjpeg: bool, + pub(crate) coeff: usize // Solves some weird bug :) +} + +impl JpegDecoder +where + T: ZReaderTrait +{ + #[allow(clippy::redundant_field_names)] + fn default(options: DecoderOptions, buffer: T) -> Self { + let color_convert = choose_ycbcr_to_rgb_convert_func(ColorSpace::RGB, &options).unwrap(); + JpegDecoder { + info: ImageInfo::default(), + qt_tables: [None, None, None, None], + dc_huffman_tables: [None, None, None, None], + ac_huffman_tables: [None, None, None, None], + components: vec![], + // Interleaved information + h_max: 1, + v_max: 1, + mcu_height: 0, + mcu_width: 0, + mcu_x: 0, + mcu_y: 0, + is_interleaved: false, + sub_sample_ratio: SampleRatios::None, + is_progressive: false, + spec_start: 0, + spec_end: 0, + succ_high: 0, + succ_low: 0, + num_scans: 0, + idct_func: choose_idct_func(&options), + color_convert_16: color_convert, + input_colorspace: ColorSpace::YCbCr, + z_order: [0; MAX_COMPONENTS], + restart_interval: 0, + todo: 0x7fff_ffff, + options: options, + stream: ZByteReader::new(buffer), + headers_decoded: false, + seen_sof: false, + exif_data: None, + icc_data: vec![], + is_mjpeg: false, + coeff: 1 + } + } + /// Decode a buffer already in memory + /// + /// The buffer should be a valid jpeg file, perhaps created by the command + /// `std:::fs::read()` or a JPEG file downloaded from the internet. + /// + /// # Errors + /// See DecodeErrors for an explanation + pub fn decode(&mut self) -> Result, DecodeErrors> { + self.decode_headers()?; + let size = self.output_buffer_size().unwrap(); + let mut out = vec![0; size]; + self.decode_into(&mut out)?; + Ok(out) + } + + /// Create a new Decoder instance + /// + /// # Arguments + /// - `stream`: The raw bytes of a jpeg file. + #[must_use] + #[allow(clippy::new_without_default)] + pub fn new(stream: T) -> JpegDecoder { + JpegDecoder::default(DecoderOptions::default(), stream) + } + + /// Returns the image information + /// + /// This **must** be called after a subsequent call to [`decode`] or [`decode_headers`] + /// it will return `None` + /// + /// # Returns + /// - `Some(info)`: Image information,width, height, number of components + /// - None: Indicates image headers haven't been decoded + /// + /// [`decode`]: JpegDecoder::decode + /// [`decode_headers`]: JpegDecoder::decode_headers + #[must_use] + pub fn info(&self) -> Option { + // we check for fails to that call by comparing what we have to the default, if + // it's default we assume that the caller failed to uphold the + // guarantees. We can be sure that an image cannot be the default since + // its a hard panic in-case width or height are set to zero. + if !self.headers_decoded { + return None; + } + + return Some(self.info.clone()); + } + + /// Return the number of bytes required to hold a decoded image frame + /// decoded using the given input transformations + /// + /// # Returns + /// - `Some(usize)`: Minimum size for a buffer needed to decode the image + /// - `None`: Indicates the image was not decoded, or image dimensions would overflow a usize + /// + #[must_use] + pub fn output_buffer_size(&self) -> Option { + return if self.headers_decoded { + Some( + usize::from(self.width()) + .checked_mul(usize::from(self.height()))? + .checked_mul(self.options.jpeg_get_out_colorspace().num_components())? + ) + } else { + None + }; + } + + /// Get a mutable reference to the decoder options + /// for the decoder instance + /// + /// This can be used to modify options before actual decoding + /// but after initial creation + /// + /// # Example + /// ```no_run + /// use zune_jpeg::JpegDecoder; + /// + /// let mut decoder = JpegDecoder::new(&[]); + /// // get current options + /// let mut options = decoder.get_options(); + /// // modify it + /// let new_options = options.set_max_width(10); + /// // set it back + /// decoder.set_options(new_options); + /// + /// ``` + #[must_use] + pub const fn get_options(&self) -> &DecoderOptions { + &self.options + } + /// Return the input colorspace of the image + /// + /// This indicates the colorspace that is present in + /// the image, but this may be different to the colorspace that + /// the output will be transformed to + /// + /// # Returns + /// -`Some(Colorspace)`: Input colorspace + /// - None : Indicates the headers weren't decoded + #[must_use] + pub fn get_input_colorspace(&self) -> Option { + return if self.headers_decoded { Some(self.input_colorspace) } else { None }; + } + /// Set decoder options + /// + /// This can be used to set new options even after initialization + /// but before decoding. + /// + /// This does not bear any significance after decoding an image + /// + /// # Arguments + /// - `options`: New decoder options + /// + /// # Example + /// Set maximum jpeg progressive passes to be 4 + /// + /// ```no_run + /// use zune_jpeg::JpegDecoder; + /// let mut decoder =JpegDecoder::new(&[]); + /// // this works also because DecoderOptions implements `Copy` + /// let options = decoder.get_options().jpeg_set_max_scans(4); + /// // set the new options + /// decoder.set_options(options); + /// // now decode + /// decoder.decode().unwrap(); + /// ``` + pub fn set_options(&mut self, options: DecoderOptions) { + self.options = options; + } + /// Decode Decoder headers + /// + /// This routine takes care of parsing supported headers from a Decoder + /// image + /// + /// # Supported Headers + /// - APP(0) + /// - SOF(O) + /// - DQT -> Quantization tables + /// - DHT -> Huffman tables + /// - SOS -> Start of Scan + /// # Unsupported Headers + /// - SOF(n) -> Decoder images which are not baseline/progressive + /// - DAC -> Images using Arithmetic tables + /// - JPG(n) + fn decode_headers_internal(&mut self) -> Result<(), DecodeErrors> { + if self.headers_decoded { + trace!("Headers decoded!"); + return Ok(()); + } + // match output colorspace here + // we know this will only be called once per image + // so makes sense + // We only care for ycbcr to rgb/rgba here + // in case one is using another colorspace. + // May god help you + let out_colorspace = self.options.jpeg_get_out_colorspace(); + + if matches!( + out_colorspace, + ColorSpace::BGR | ColorSpace::BGRA | ColorSpace::RGB | ColorSpace::RGBA + ) { + self.color_convert_16 = choose_ycbcr_to_rgb_convert_func( + self.options.jpeg_get_out_colorspace(), + &self.options + ) + .unwrap(); + } + // First two bytes should be jpeg soi marker + let magic_bytes = self.stream.get_u16_be_err()?; + + let mut last_byte = 0; + let mut bytes_before_marker = 0; + + if magic_bytes != 0xffd8 { + return Err(DecodeErrors::IllegalMagicBytes(magic_bytes)); + } + + loop { + // read a byte + let mut m = self.stream.get_u8_err()?; + + // AND OF COURSE some images will have fill bytes in their marker + // bitstreams because why not. + // + // I am disappointed as a man. + if (m == 0xFF || m == 0) && last_byte == 0xFF { + // This handles the edge case where + // images have markers with fill bytes(0xFF) + // or byte stuffing (0) + // I.e 0xFF 0xFF 0xDA + // and + // 0xFF 0 0xDA + // It should ignore those fill bytes and take 0xDA + // I don't know why such images exist + // but they do. + // so this is for you (with love) + while m == 0xFF || m == 0x0 { + last_byte = m; + m = self.stream.get_u8_err()?; + } + } + // Last byte should be 0xFF to confirm existence of a marker since markers look + // like OxFF(some marker data) + if last_byte == 0xFF { + let marker = Marker::from_u8(m); + if let Some(n) = marker { + if bytes_before_marker > 3 { + if self.options.get_strict_mode() + /*No reason to use this*/ + { + return Err(DecodeErrors::FormatStatic( + "[strict-mode]: Extra bytes between headers" + )); + } + + error!( + "Extra bytes {} before marker 0xFF{:X}", + bytes_before_marker - 3, + m + ); + } + + bytes_before_marker = 0; + + self.parse_marker_inner(n)?; + + if n == Marker::SOS { + self.headers_decoded = true; + trace!("Input colorspace {:?}", self.input_colorspace); + return Ok(()); + } + } else { + bytes_before_marker = 0; + + warn!("Marker 0xFF{:X} not known", m); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length : {length}" + ))); + } + + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize); + } + } + last_byte = m; + bytes_before_marker += 1; + } + } + #[allow(clippy::too_many_lines)] + pub(crate) fn parse_marker_inner(&mut self, m: Marker) -> Result<(), DecodeErrors> { + match m { + Marker::SOF(0..=2) => { + let marker = { + // choose marker + if m == Marker::SOF(0) || m == Marker::SOF(1) { + SOFMarkers::BaselineDct + } else { + self.is_progressive = true; + SOFMarkers::ProgressiveDctHuffman + } + }; + + trace!("Image encoding scheme =`{:?}`", marker); + // get components + parse_start_of_frame(marker, self)?; + } + // Start of Frame Segments not supported + Marker::SOF(v) => { + let feature = UnsupportedSchemes::from_int(v); + + if let Some(feature) = feature { + return Err(DecodeErrors::Unsupported(feature)); + } + + return Err(DecodeErrors::Format("Unsupported image format".to_string())); + } + //APP(0) segment + Marker::APP(0) => { + let mut length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + // skip for now + if length > 5 && self.stream.has(5) { + let mut buffer = [0u8; 5]; + self.stream.read_exact(&mut buffer).unwrap(); + if &buffer == b"AVI1\0" { + self.is_mjpeg = true; + } + length -= 5; + } + self.stream.skip(length.saturating_sub(2) as usize); + + //parse_app(buf, m, &mut self.info)?; + } + Marker::APP(1) => { + parse_app1(self)?; + } + + Marker::APP(2) => { + parse_app2(self)?; + } + // Quantization tables + Marker::DQT => { + parse_dqt(self)?; + } + // Huffman tables + Marker::DHT => { + parse_huffman(self)?; + } + // Start of Scan Data + Marker::SOS => { + parse_sos(self)?; + + // break after reading the start of scan. + // what follows is the image data + return Ok(()); + } + Marker::EOI => return Err(DecodeErrors::FormatStatic("Premature End of image")), + + Marker::DAC | Marker::DNL => { + return Err(DecodeErrors::Format(format!( + "Parsing of the following header `{m:?}` is not supported,\ + cannot continue" + ))); + } + Marker::DRI => { + trace!("DRI marker present"); + + if self.stream.get_u16_be_err()? != 4 { + return Err(DecodeErrors::Format( + "Bad DRI length, Corrupt JPEG".to_string() + )); + } + + self.restart_interval = usize::from(self.stream.get_u16_be_err()?); + self.todo = self.restart_interval; + } + Marker::APP(13) => { + parse_app13(self)?; + } + Marker::APP(14) => { + parse_app14(self)?; + } + _ => { + warn!( + "Capabilities for processing marker \"{:?}\" not implemented", + m + ); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize); + } + } + Ok(()) + } + /// Get the embedded ICC profile if it exists + /// and is correct + /// + /// One needs not to decode the whole image to extract this, + /// calling [`decode_headers`] for an image with an ICC profile + /// allows you to decode this + /// + /// # Returns + /// - `Some(Vec)`: The raw ICC profile of the image + /// - `None`: May indicate an error in the ICC profile , non-existence of + /// an ICC profile, or that the headers weren't decoded. + /// + /// [`decode_headers`]:Self::decode_headers + #[must_use] + pub fn icc_profile(&self) -> Option> { + let mut marker_present: [Option<&ICCChunk>; 256] = [None; 256]; + + if !self.headers_decoded { + return None; + } + let num_markers = self.icc_data.len(); + + if num_markers == 0 || num_markers >= 255 { + return None; + } + // check validity + for chunk in &self.icc_data { + if usize::from(chunk.num_markers) != num_markers { + // all the lengths must match + return None; + } + if chunk.seq_no == 0 { + warn!("Zero sequence number in ICC, corrupt ICC chunk"); + return None; + } + if marker_present[usize::from(chunk.seq_no)].is_some() { + // duplicate seq_no + warn!("Duplicate sequence number in ICC, corrupt chunk"); + return None; + } + + marker_present[usize::from(chunk.seq_no)] = Some(chunk); + } + let mut data = Vec::with_capacity(1000); + // assemble the data now + for chunk in marker_present.get(1..=num_markers).unwrap() { + if let Some(ch) = chunk { + data.extend_from_slice(&ch.data); + } else { + warn!("Missing icc sequence number, corrupt ICC chunk "); + return None; + } + } + + Some(data) + } + /// Return the exif data for the file + /// + /// This returns the raw exif data starting at the + /// TIFF header + /// + /// # Returns + /// -`Some(data)`: The raw exif data, if present in the image + /// - None: May indicate the following + /// + /// 1. The image doesn't have exif data + /// 2. The image headers haven't been decoded + #[must_use] + pub fn exif(&self) -> Option<&Vec> { + return self.exif_data.as_ref(); + } + /// Get the output colorspace the image pixels will be decoded into + /// + /// + /// # Note. + /// This field can only be regarded after decoding headers, + /// as markers such as Adobe APP14 may dictate different colorspaces + /// than requested. + /// + /// Calling `decode_headers` is sufficient to know what colorspace the + /// output is, if this is called after `decode` it indicates the colorspace + /// the output is currently in + /// + /// Additionally not all input->output colorspace mappings are supported + /// but all input colorspaces can map to RGB colorspace, so that's a safe bet + /// if one is handling image formats + /// + ///# Returns + /// - `Some(Colorspace)`: If headers have been decoded, the colorspace the + ///output array will be in + ///- `None + #[must_use] + pub fn get_output_colorspace(&self) -> Option { + return if self.headers_decoded { + Some(self.options.jpeg_get_out_colorspace()) + } else { + None + }; + } + + /// Decode into a pre-allocated buffer + /// + /// It is an error if the buffer size is smaller than + /// [`output_buffer_size()`](Self::output_buffer_size) + /// + /// If the buffer is bigger than expected, we ignore the end padding bytes + /// + /// # Example + /// + /// - Read headers and then alloc a buffer big enough to hold the image + /// + /// ```no_run + /// use zune_jpeg::JpegDecoder; + /// let mut decoder = JpegDecoder::new(&[]); + /// // before we get output, we must decode the headers to get width + /// // height, and input colorspace + /// decoder.decode_headers().unwrap(); + /// + /// let mut out = vec![0;decoder.output_buffer_size().unwrap()]; + /// // write into out + /// decoder.decode_into(&mut out).unwrap(); + /// ``` + /// + /// + pub fn decode_into(&mut self, out: &mut [u8]) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + + let expected_size = self.output_buffer_size().unwrap(); + + if out.len() < expected_size { + // too small of a size + return Err(DecodeErrors::TooSmallOutput(expected_size, out.len())); + } + + // ensure we don't touch anyone else's scratch space + let out_len = core::cmp::min(out.len(), expected_size); + let out = &mut out[0..out_len]; + + if self.is_progressive { + self.decode_mcu_ycbcr_progressive(out) + } else { + self.decode_mcu_ycbcr_baseline(out) + } + } + + /// Read only headers from a jpeg image buffer + /// + /// This allows you to extract important information like + /// image width and height without decoding the full image + /// + /// # Examples + /// ```no_run + /// use zune_jpeg::{JpegDecoder}; + /// + /// let img_data = std::fs::read("a_valid.jpeg").unwrap(); + /// let mut decoder = JpegDecoder::new(&img_data); + /// decoder.decode_headers().unwrap(); + /// + /// println!("Total decoder dimensions are : {:?} pixels",decoder.dimensions()); + /// println!("Number of components in the image are {}", decoder.info().unwrap().components); + /// ``` + /// # Errors + /// See DecodeErrors enum for list of possible errors during decoding + pub fn decode_headers(&mut self) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + Ok(()) + } + /// Create a new decoder with the specified options to be used for decoding + /// an image + /// + /// # Arguments + /// - `buf`: The input buffer from where we will pull in compressed jpeg bytes from + /// - `options`: Options specific to this decoder instance + #[must_use] + pub fn new_with_options(buf: T, options: DecoderOptions) -> JpegDecoder { + JpegDecoder::default(options, buf) + } + + /// Set up-sampling routines in case an image is down sampled + pub(crate) fn set_upsampling(&mut self) -> Result<(), DecodeErrors> { + // no sampling, return early + // check if horizontal max ==1 + if self.h_max == self.v_max && self.h_max == 1 { + return Ok(()); + } + match (self.h_max, self.v_max) { + (1, 1) => { + self.sub_sample_ratio = SampleRatios::None; + } + (1, 2) => { + self.sub_sample_ratio = SampleRatios::V; + } + (2, 1) => { + self.sub_sample_ratio = SampleRatios::H; + } + (2, 2) => { + self.sub_sample_ratio = SampleRatios::HV; + } + (hs, vs) => { + self.sub_sample_ratio = SampleRatios::Generic(hs, vs) + // return Err(DecodeErrors::Format(format!( + // "Unknown down-sampling method ({hs},{vs}), cannot continue") + // )) + } + } + + for comp in self.components.iter_mut() { + let hs = self.h_max / comp.horizontal_sample; + let vs = self.v_max / comp.vertical_sample; + + let samp_factor = match (hs, vs) { + (1, 1) => { + comp.sample_ratio = SampleRatios::None; + upsample_no_op + } + (2, 1) => { + comp.sample_ratio = SampleRatios::H; + choose_horizontal_samp_function(self.options.get_use_unsafe()) + } + (1, 2) => { + comp.sample_ratio = SampleRatios::V; + choose_v_samp_function(self.options.get_use_unsafe()) + } + (2, 2) => { + comp.sample_ratio = SampleRatios::HV; + choose_hv_samp_function(self.options.get_use_unsafe()) + } + (hs, vs) => { + comp.sample_ratio = SampleRatios::Generic(hs, vs); + generic_sampler() + } + }; + comp.setup_upsample_scanline(); + comp.up_sampler = samp_factor; + } + + return Ok(()); + } + #[must_use] + /// Get the width of the image as a u16 + /// + /// The width lies between 1 and 65535 + pub(crate) fn width(&self) -> u16 { + self.info.width + } + + /// Get the height of the image as a u16 + /// + /// The height lies between 1 and 65535 + #[must_use] + pub(crate) fn height(&self) -> u16 { + self.info.height + } + + /// Get image dimensions as a tuple of width and height + /// or `None` if the image hasn't been decoded. + /// + /// # Returns + /// - `Some(width,height)`: Image dimensions + /// - None : The image headers haven't been decoded + #[must_use] + pub const fn dimensions(&self) -> Option<(usize, usize)> { + return if self.headers_decoded { + Some((self.info.width as usize, self.info.height as usize)) + } else { + None + }; + } +} + +/// A struct representing Image Information +#[derive(Default, Clone, Eq, PartialEq)] +#[allow(clippy::module_name_repetitions)] +pub struct ImageInfo { + /// Width of the image + pub width: u16, + /// Height of image + pub height: u16, + /// PixelDensity + pub pixel_density: u8, + /// Start of frame markers + pub sof: SOFMarkers, + /// Horizontal sample + pub x_density: u16, + /// Vertical sample + pub y_density: u16, + /// Number of components + pub components: u8, + pub iptc_data: Option> +} + +impl ImageInfo { + /// Set width of the image + /// + /// Found in the start of frame + + pub(crate) fn set_width(&mut self, width: u16) { + self.width = width; + } + + /// Set height of the image + /// + /// Found in the start of frame + + pub(crate) fn set_height(&mut self, height: u16) { + self.height = height; + } + + /// Set the image density + /// + /// Found in the start of frame + + pub(crate) fn set_density(&mut self, density: u8) { + self.pixel_density = density; + } + + /// Set image Start of frame marker + /// + /// found in the Start of frame header + + pub(crate) fn set_sof_marker(&mut self, marker: SOFMarkers) { + self.sof = marker; + } + + /// Set image x-density(dots per pixel) + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_x(&mut self, sample: u16) { + self.x_density = sample; + } + + /// Set image y-density + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_y(&mut self, sample: u16) { + self.y_density = sample; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/errors.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/errors.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/errors.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/errors.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Contains most common errors that may be encountered in decoding a Decoder +//! image + +use alloc::string::String; +use core::fmt::{Debug, Display, Formatter}; + +use crate::misc::{ + START_OF_FRAME_EXT_AR, START_OF_FRAME_EXT_SEQ, START_OF_FRAME_LOS_SEQ, + START_OF_FRAME_LOS_SEQ_AR, START_OF_FRAME_PROG_DCT_AR +}; + +/// Common Decode errors +#[allow(clippy::module_name_repetitions)] +#[derive(Clone)] +pub enum DecodeErrors { + /// Any other thing we do not know + Format(String), + /// Any other thing we do not know but we + /// don't need to allocate space on the heap + FormatStatic(&'static str), + /// Illegal Magic Bytes + IllegalMagicBytes(u16), + /// problems with the Huffman Tables in a Decoder file + HuffmanDecode(String), + /// Image has zero width + ZeroError, + /// Discrete Quantization Tables error + DqtError(String), + /// Start of scan errors + SosError(String), + /// Start of frame errors + SofError(String), + /// UnsupportedImages + Unsupported(UnsupportedSchemes), + /// MCU errors + MCUError(String), + /// Exhausted data + ExhaustedData, + /// Large image dimensions(Corrupted data)? + LargeDimensions(usize), + /// Too small output for size + TooSmallOutput(usize, usize) +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeErrors {} + +impl From<&'static str> for DecodeErrors { + fn from(data: &'static str) -> Self { + return Self::FormatStatic(data); + } +} + +impl Debug for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self + { + Self::Format(ref a) => write!(f, "{a:?}"), + Self::FormatStatic(a) => write!(f, "{:?}", &a), + + Self::HuffmanDecode(ref reason) => + { + write!(f, "Error decoding huffman values: {reason}") + } + Self::ZeroError => write!(f, "Image width or height is set to zero, cannot continue"), + Self::DqtError(ref reason) => write!(f, "Error parsing DQT segment. Reason:{reason}"), + Self::SosError(ref reason) => write!(f, "Error parsing SOS Segment. Reason:{reason}"), + Self::SofError(ref reason) => write!(f, "Error parsing SOF segment. Reason:{reason}"), + Self::IllegalMagicBytes(bytes) => + { + write!(f, "Error parsing image. Illegal start bytes:{bytes:X}") + } + Self::MCUError(ref reason) => write!(f, "Error in decoding MCU. Reason {reason}"), + Self::Unsupported(ref image_type) => + { + write!(f, "{image_type:?}") + } + Self::ExhaustedData => write!(f, "Exhausted data in the image"), + Self::LargeDimensions(ref dimensions) => write!( + f, + "Too large dimensions {dimensions},library supports up to {}", crate::decoder::MAX_DIMENSIONS + ), + Self::TooSmallOutput(expected, found) => write!(f, "Too small output, expected buffer with at least {expected} bytes but got one with {found} bytes") + } + } +} + +impl Display for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } +} + +/// Contains Unsupported/Yet-to-be supported Decoder image encoding types. +#[derive(Eq, PartialEq, Copy, Clone)] +pub enum UnsupportedSchemes { + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Debug for UnsupportedSchemes { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self { + Self::ExtendedSequentialHuffman => { + write!(f, "The library cannot yet decode images encoded using Extended Sequential Huffman encoding scheme yet.") + } + Self::LosslessHuffman => { + write!(f, "The library cannot yet decode images encoded with Lossless Huffman encoding scheme") + } + Self::ExtendedSequentialDctArithmetic => { + write!(f,"The library cannot yet decode Images Encoded with Extended Sequential DCT Arithmetic scheme") + } + Self::ProgressiveDctArithmetic => { + write!(f,"The library cannot yet decode images encoded with Progressive DCT Arithmetic scheme") + } + Self::LosslessArithmetic => { + write!(f,"The library cannot yet decode images encoded with Lossless Arithmetic encoding scheme") + } + } + } +} + +impl UnsupportedSchemes { + #[must_use] + /// Create an unsupported scheme from an integer + /// + /// # Returns + /// `Some(UnsupportedScheme)` if the int refers to a specific scheme, + /// otherwise returns `None` + pub fn from_int(int: u8) -> Option { + let int = u16::from_be_bytes([0xff, int]); + + match int { + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/headers.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/headers.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/headers.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/headers.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decode Decoder markers/segments +//! +//! This file deals with decoding header information in a jpeg file +//! +use alloc::format; +use alloc::string::ToString; +use alloc::vec::Vec; + +use zune_core::bytestream::ZReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, error, trace, warn}; + +use crate::components::Components; +use crate::decoder::{ICCChunk, JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::misc::{SOFMarkers, UN_ZIGZAG}; + +///**B.2.4.2 Huffman table-specification syntax** +#[allow(clippy::similar_names, clippy::cast_sign_loss)] +pub(crate) fn parse_huffman( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> +where +{ + // Read the length of the Huffman table + let mut dht_length = i32::from(decoder.stream.get_u16_be_err()?.checked_sub(2).ok_or( + DecodeErrors::FormatStatic("Invalid Huffman length in image") + )?); + + while dht_length > 16 { + // HT information + let ht_info = decoder.stream.get_u8_err()?; + // third bit indicates whether the huffman encoding is DC or AC type + let dc_or_ac = (ht_info >> 4) & 0xF; + // Indicate the position of this table, should be less than 4; + let index = (ht_info & 0xF) as usize; + // read the number of symbols + let mut num_symbols: [u8; 17] = [0; 17]; + + if index >= MAX_COMPONENTS { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT index {index}, expected between 0 and 3" + ))); + } + + if dc_or_ac > 1 { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT position {dc_or_ac}, should be 0 or 1" + ))); + } + + decoder + .stream + .read_exact(&mut num_symbols[1..17]) + .map_err(|_| DecodeErrors::ExhaustedData)?; + + dht_length -= 1 + 16; + + let symbols_sum: i32 = num_symbols.iter().map(|f| i32::from(*f)).sum(); + + // The sum of the number of symbols cannot be greater than 256; + if symbols_sum > 256 { + return Err(DecodeErrors::FormatStatic( + "Encountered Huffman table with excessive length in DHT" + )); + } + if symbols_sum > dht_length { + return Err(DecodeErrors::HuffmanDecode(format!( + "Excessive Huffman table of length {symbols_sum} found when header length is {dht_length}" + ))); + } + dht_length -= symbols_sum; + // A table containing symbols in increasing code length + let mut symbols = [0; 256]; + + decoder + .stream + .read_exact(&mut symbols[0..(symbols_sum as usize)]) + .map_err(|x| { + DecodeErrors::Format(format!("Could not read symbols into the buffer\n{x}")) + })?; + // store + match dc_or_ac { + 0 => { + decoder.dc_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + true, + decoder.is_progressive + )?); + } + _ => { + decoder.ac_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + false, + decoder.is_progressive + )?); + } + } + } + + if dht_length > 0 { + return Err(DecodeErrors::FormatStatic("Bogus Huffman table definition")); + } + + Ok(()) +} + +///**B.2.4.1 Quantization table-specification syntax** +#[allow(clippy::cast_possible_truncation, clippy::needless_range_loop)] +pub(crate) fn parse_dqt(img: &mut JpegDecoder) -> Result<(), DecodeErrors> { + // read length + let mut qt_length = + img.stream + .get_u16_be_err()? + .checked_sub(2) + .ok_or(DecodeErrors::FormatStatic( + "Invalid DQT length. Length should be greater than 2" + ))?; + // A single DQT header may have multiple QT's + while qt_length > 0 { + let qt_info = img.stream.get_u8_err()?; + // 0 = 8 bit otherwise 16 bit dqt + let precision = (qt_info >> 4) as usize; + // last 4 bits give us position + let table_position = (qt_info & 0x0f) as usize; + let precision_value = 64 * (precision + 1); + + if (precision_value + 1) as u16 > qt_length { + return Err(DecodeErrors::DqtError(format!("Invalid QT table bytes left :{}. Too small to construct a valid qt table which should be {} long", qt_length, precision_value + 1))); + } + + let dct_table = match precision { + 0 => { + let mut qt_values = [0; 64]; + + img.stream.read_exact(&mut qt_values).map_err(|x| { + DecodeErrors::Format(format!("Could not read symbols into the buffer\n{x}")) + })?; + qt_length -= (precision_value as u16) + 1 /*QT BIT*/; + // carry out un zig-zag here + un_zig_zag(&qt_values) + } + 1 => { + // 16 bit quantization tables + let mut qt_values = [0_u16; 64]; + + for i in 0..64 { + qt_values[i] = img.stream.get_u16_be_err()?; + } + qt_length -= (precision_value as u16) + 1; + + un_zig_zag(&qt_values) + } + _ => { + return Err(DecodeErrors::DqtError(format!( + "Expected QT precision value of either 0 or 1, found {precision:?}" + ))); + } + }; + + if table_position >= MAX_COMPONENTS { + return Err(DecodeErrors::DqtError(format!( + "Too large table position for QT :{table_position}, expected between 0 and 3" + ))); + } + + img.qt_tables[table_position] = Some(dct_table); + } + + return Ok(()); +} + +/// Section:`B.2.2 Frame header syntax` + +pub(crate) fn parse_start_of_frame( + sof: SOFMarkers, img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + if img.seen_sof { + return Err(DecodeErrors::SofError( + "Two Start of Frame Markers".to_string() + )); + } + // Get length of the frame header + let length = img.stream.get_u16_be_err()?; + // usually 8, but can be 12 and 16, we currently support only 8 + // so sorry about that 12 bit images + let dt_precision = img.stream.get_u8_err()?; + + if dt_precision != 8 { + return Err(DecodeErrors::SofError(format!( + "The library can only parse 8-bit images, the image has {dt_precision} bits of precision" + ))); + } + + img.info.set_density(dt_precision); + + // read and set the image height. + let img_height = img.stream.get_u16_be_err()?; + img.info.set_height(img_height); + + // read and set the image width + let img_width = img.stream.get_u16_be_err()?; + img.info.set_width(img_width); + + trace!("Image width :{}", img_width); + trace!("Image height :{}", img_height); + + if usize::from(img_width) > img.options.get_max_width() { + return Err(DecodeErrors::Format(format!("Image width {} greater than width limit {}. If use `set_limits` if you want to support huge images", img_width, img.options.get_max_width()))); + } + + if usize::from(img_height) > img.options.get_max_height() { + return Err(DecodeErrors::Format(format!("Image height {} greater than height limit {}. If use `set_limits` if you want to support huge images", img_height, img.options.get_max_height()))); + } + + // Check image width or height is zero + if img_width == 0 || img_height == 0 { + return Err(DecodeErrors::ZeroError); + } + + // Number of components for the image. + let num_components = img.stream.get_u8_err()?; + + if num_components == 0 { + return Err(DecodeErrors::SofError( + "Number of components cannot be zero.".to_string() + )); + } + + let expected = 8 + 3 * u16::from(num_components); + // length should be equal to num components + if length != expected { + return Err(DecodeErrors::SofError(format!( + "Length of start of frame differs from expected {expected},value is {length}" + ))); + } + + trace!("Image components : {}", num_components); + + if num_components == 1 { + // SOF sets the number of image components + // and that to us translates to setting input and output + // colorspaces to zero + img.input_colorspace = ColorSpace::Luma; + img.options = img.options.jpeg_set_out_colorspace(ColorSpace::Luma); + debug!("Overriding default colorspace set to Luma"); + } + if num_components == 4 && img.input_colorspace == ColorSpace::YCbCr { + trace!("Input image has 4 components, defaulting to CMYK colorspace"); + // https://entropymine.wordpress.com/2018/10/22/how-is-a-jpeg-images-color-type-determined/ + img.input_colorspace = ColorSpace::CMYK; + } + + // set number of components + img.info.components = num_components; + + let mut components = Vec::with_capacity(num_components as usize); + let mut temp = [0; 3]; + + for pos in 0..num_components { + // read 3 bytes for each component + img.stream + .read_exact(&mut temp) + .map_err(|x| DecodeErrors::Format(format!("Could not read component data\n{x}")))?; + // create a component. + let component = Components::from(temp, pos)?; + + components.push(component); + } + img.seen_sof = true; + + img.info.set_sof_marker(sof); + + img.components = components; + + Ok(()) +} + +/// Parse a start of scan data +pub(crate) fn parse_sos(image: &mut JpegDecoder) -> Result<(), DecodeErrors> { + // Scan header length + let ls = image.stream.get_u16_be_err()?; + // Number of image components in scan + let ns = image.stream.get_u8_err()?; + + let mut seen = [-1; { MAX_COMPONENTS + 1 }]; + + image.num_scans = ns; + + if ls != 6 + 2 * u16::from(ns) { + return Err(DecodeErrors::SosError(format!( + "Bad SOS length {ls},corrupt jpeg" + ))); + } + + // Check number of components. + if !(1..5).contains(&ns) { + return Err(DecodeErrors::SosError(format!( + "Number of components in start of scan should be less than 3 but more than 0. Found {ns}" + ))); + } + + if image.info.components == 0 { + return Err(DecodeErrors::FormatStatic( + "Error decoding SOF Marker, Number of components cannot be zero." + )); + } + + // consume spec parameters + for i in 0..ns { + // CS_i parameter, I don't need it so I might as well delete it + let id = image.stream.get_u8_err()?; + + if seen.contains(&i32::from(id)) { + return Err(DecodeErrors::SofError(format!( + "Duplicate ID {id} seen twice in the same component" + ))); + } + + seen[usize::from(i)] = i32::from(id); + // DC and AC huffman table position + // top 4 bits contain dc huffman destination table + // lower four bits contain ac huffman destination table + let y = image.stream.get_u8_err()?; + + let mut j = 0; + + while j < image.info.components { + if image.components[j as usize].id == id { + break; + } + + j += 1; + } + + if j == image.info.components { + return Err(DecodeErrors::SofError(format!( + "Invalid component id {}, expected a value between 0 and {}", + id, + image.components.len() + ))); + } + + image.components[usize::from(j)].dc_huff_table = usize::from((y >> 4) & 0xF); + image.components[usize::from(j)].ac_huff_table = usize::from(y & 0xF); + image.z_order[i as usize] = j as usize; + } + + // Collect the component spec parameters + // This is only needed for progressive images but I'll read + // them in order to ensure they are correct according to the spec + + // Extract progressive information + + // https://www.w3.org/Graphics/JPEG/itu-t81.pdf + // Page 42 + + // Start of spectral / predictor selection. (between 0 and 63) + image.spec_start = image.stream.get_u8_err()?; + // End of spectral selection + image.spec_end = image.stream.get_u8_err()?; + + let bit_approx = image.stream.get_u8_err()?; + // successive approximation bit position high + image.succ_high = bit_approx >> 4; + + if image.spec_end > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Se parameter {}, range should be 0-63", + image.spec_end + ))); + } + if image.spec_start > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ss parameter {}, range should be 0-63", + image.spec_start + ))); + } + if image.succ_high > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ah parameter {}, range should be 0-13", + image.succ_low + ))); + } + // successive approximation bit position low + image.succ_low = bit_approx & 0xF; + + if image.succ_low > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Al parameter {}, range should be 0-13", + image.succ_low + ))); + } + + trace!( + "Ss={}, Se={} Ah={} Al={}", + image.spec_start, + image.spec_end, + image.succ_high, + image.succ_low + ); + + Ok(()) +} + +/// Parse the APP13 (IPTC) segment. +pub(crate) fn parse_app13( + decoder: &mut JpegDecoder, +) -> Result<(), DecodeErrors> { + const IPTC_PREFIX: &[u8] = b"Photoshop 3.0"; + // skip length. + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small APP13 length")); + } + // length bytes. + length -= 2; + + if length > IPTC_PREFIX.len() && decoder.stream.peek_at(0, IPTC_PREFIX.len())? == IPTC_PREFIX { + // skip bytes we read above. + decoder.stream.skip(IPTC_PREFIX.len()); + length -= IPTC_PREFIX.len(); + + let iptc_bytes = decoder.stream.peek_at(0, length)?.to_vec(); + + decoder.info.iptc_data = Some(iptc_bytes); + } + + decoder.stream.skip(length); + Ok(()) +} + +/// Parse Adobe App14 segment +pub(crate) fn parse_app14( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // skip length + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 || !decoder.stream.has(length - 2) { + return Err(DecodeErrors::ExhaustedData); + } + if length < 14 { + return Err(DecodeErrors::FormatStatic( + "Too short of a length for App14 segment" + )); + } + if decoder.stream.peek_at(0, 5) == Ok(b"Adobe") { + // move stream 6 bytes to remove adobe id + decoder.stream.skip(6); + // skip version, flags0 and flags1 + decoder.stream.skip(5); + // get color transform + let transform = decoder.stream.get_u8(); + // https://exiftool.org/TagNames/JPEG.html#Adobe + match transform { + 0 => decoder.input_colorspace = ColorSpace::CMYK, + 1 => decoder.input_colorspace = ColorSpace::YCbCr, + 2 => decoder.input_colorspace = ColorSpace::YCCK, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown Adobe colorspace {transform}" + ))) + } + } + // length = 2 + // adobe id = 6 + // version = 5 + // transform = 1 + length = length.saturating_sub(14); + } else if decoder.options.get_strict_mode() { + return Err(DecodeErrors::FormatStatic("Corrupt Adobe App14 segment")); + } else { + length = length.saturating_sub(2); + error!("Not a valid Adobe APP14 Segment"); + } + // skip any proceeding lengths. + // we do not need them + decoder.stream.skip(length); + + Ok(()) +} + +/// Parse the APP1 segment +/// +/// This contains the exif tag +pub(crate) fn parse_app1( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // contains exif data + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 || !decoder.stream.has(length - 2) { + return Err(DecodeErrors::ExhaustedData); + } + // length bytes + length -= 2; + + if length > 6 && decoder.stream.peek_at(0, 6).unwrap() == b"Exif\x00\x00" { + trace!("Exif segment present"); + // skip bytes we read above + decoder.stream.skip(6); + length -= 6; + + let exif_bytes = decoder.stream.peek_at(0, length).unwrap().to_vec(); + + decoder.exif_data = Some(exif_bytes); + } else { + warn!("Wrongly formatted exif tag"); + } + + decoder.stream.skip(length); + Ok(()) +} + +pub(crate) fn parse_app2( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 || !decoder.stream.has(length - 2) { + return Err(DecodeErrors::ExhaustedData); + } + // length bytes + length -= 2; + + if length > 14 && decoder.stream.peek_at(0, 12).unwrap() == *b"ICC_PROFILE\0" { + trace!("ICC Profile present"); + // skip 12 bytes which indicate ICC profile + length -= 12; + decoder.stream.skip(12); + let seq_no = decoder.stream.get_u8(); + let num_markers = decoder.stream.get_u8(); + // deduct the two bytes we read above + length -= 2; + + let data = decoder.stream.peek_at(0, length).unwrap().to_vec(); + + let icc_chunk = ICCChunk { + seq_no, + num_markers, + data + }; + decoder.icc_data.push(icc_chunk); + } + + decoder.stream.skip(length); + + Ok(()) +} + +/// Small utility function to print Un-zig-zagged quantization tables + +fn un_zig_zag(a: &[T]) -> [i32; 64] +where + T: Default + Copy, + i32: core::convert::From +{ + let mut output = [i32::default(); 64]; + + for i in 0..64 { + output[UN_ZIGZAG[i]] = i32::from(a[i]); + } + + output +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/huffman.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This file contains a single struct `HuffmanTable` that +//! stores Huffman tables needed during `BitStream` decoding. +#![allow(clippy::similar_names, clippy::module_name_repetitions)] + +use alloc::string::ToString; + +use crate::errors::DecodeErrors; + +/// Determines how many bits of lookahead we have for our bitstream decoder. + +pub const HUFF_LOOKAHEAD: u8 = 9; + +/// A struct which contains necessary tables for decoding a JPEG +/// huffman encoded bitstream + +pub struct HuffmanTable { + // element `[0]` of each array is unused + /// largest code of length k + pub(crate) maxcode: [i32; 18], + /// offset for codes of length k + /// Answers the question, where do code-lengths of length k end + /// Element 0 is unused + pub(crate) offset: [i32; 18], + /// lookup table for fast decoding + /// + /// top bits above HUFF_LOOKAHEAD contain the code length. + /// + /// Lower (8) bits contain the symbol in order of increasing code length. + pub(crate) lookup: [i32; 1 << HUFF_LOOKAHEAD], + + /// A table which can be used to decode small AC coefficients and + /// do an equivalent of receive_extend + pub(crate) ac_lookup: Option<[i16; 1 << HUFF_LOOKAHEAD]>, + + /// Directly represent contents of a JPEG DHT marker + /// + /// \# number of symbols with codes of length `k` bits + // bits[0] is unused + /// Symbols in order of increasing code length + pub(crate) values: [u8; 256] +} + +impl HuffmanTable { + pub fn new( + codes: &[u8; 17], values: [u8; 256], is_dc: bool, is_progressive: bool + ) -> Result { + let too_long_code = (i32::from(HUFF_LOOKAHEAD) + 1) << HUFF_LOOKAHEAD; + let mut p = HuffmanTable { + maxcode: [0; 18], + offset: [0; 18], + lookup: [too_long_code; 1 << HUFF_LOOKAHEAD], + values, + ac_lookup: None + }; + + p.make_derived_table(is_dc, is_progressive, codes)?; + + Ok(p) + } + + /// Create a new huffman tables with values that aren't fixed + /// used by fill_mjpeg_tables + pub fn new_unfilled( + codes: &[u8; 17], values: &[u8], is_dc: bool, is_progressive: bool + ) -> Result { + let mut buf = [0; 256]; + buf[..values.len()].copy_from_slice(values); + HuffmanTable::new(codes, buf, is_dc, is_progressive) + } + + /// Compute derived values for a Huffman table + /// + /// This routine performs some validation checks on the table + #[allow( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + clippy::too_many_lines, + clippy::needless_range_loop + )] + fn make_derived_table( + &mut self, is_dc: bool, _is_progressive: bool, bits: &[u8; 17] + ) -> Result<(), DecodeErrors> { + // build a list of code size + let mut huff_size = [0; 257]; + // Huffman code lengths + let mut huff_code: [u32; 257] = [0; 257]; + // figure C.1 make table of Huffman code length for each symbol + let mut p = 0; + + for l in 1..=16 { + let mut i = i32::from(bits[l]); + // table overrun is checked before ,so we dont need to check + while i != 0 { + huff_size[p] = l as u8; + p += 1; + i -= 1; + } + } + + huff_size[p] = 0; + + let num_symbols = p; + // Generate the codes themselves + // We also validate that the counts represent a legal Huffman code tree + let mut code = 0; + let mut si = i32::from(huff_size[0]); + + p = 0; + + while huff_size[p] != 0 { + while i32::from(huff_size[p]) == si { + huff_code[p] = code; + code += 1; + p += 1; + } + // maximum code of length si, pre-shifted by 16-k bits + self.maxcode[si as usize] = (code << (16 - si)) as i32; + // code is now 1 more than the last code used for code-length si; but + // it must still fit in si bits, since no code is allowed to be all ones. + if (code as i32) >= (1 << si) { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + + code <<= 1; + si += 1; + } + + // Figure F.15 generate decoding tables for bit-sequential decoding + p = 0; + + for l in 0..=16 { + if bits[l] == 0 { + // -1 if no codes of this length + self.maxcode[l] = -1; + } else { + // offset[l]=codes[index of 1st symbol of code length l + // minus minimum code of length l] + self.offset[l] = (p as i32) - (huff_code[p]) as i32; + p += usize::from(bits[l]); + } + } + + self.offset[17] = 0; + // we ensure that decode terminates + self.maxcode[17] = 0x000F_FFFF; + + /* + * Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0(left justified), indicating "too long"; + * (Note too long was set during initialization) + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + p = 0; + + for l in 1..=HUFF_LOOKAHEAD { + for _ in 1..=i32::from(bits[usize::from(l)]) { + // l -> Current code length, + // p => Its index in self.code and self.values + // Generate left justified code followed by all possible bit sequences + let mut look_bits = (huff_code[p] as usize) << (HUFF_LOOKAHEAD - l); + + for _ in 0..1 << (HUFF_LOOKAHEAD - l) { + self.lookup[look_bits] = + (i32::from(l) << HUFF_LOOKAHEAD) | i32::from(self.values[p]); + look_bits += 1; + } + + p += 1; + } + } + // build an ac table that does an equivalent of decode and receive_extend + if !is_dc { + let mut fast = [255; 1 << HUFF_LOOKAHEAD]; + // Iterate over number of symbols + for i in 0..num_symbols { + // get code size for an item + let s = huff_size[i]; + + if s <= HUFF_LOOKAHEAD { + // if it's lower than what we need for our lookup table create the table + let c = (huff_code[i] << (HUFF_LOOKAHEAD - s)) as usize; + let m = (1 << (HUFF_LOOKAHEAD - s)) as usize; + + for j in 0..m { + fast[c + j] = i as i16; + } + } + } + + // build a table that decodes both magnitude and value of small ACs in + // one go. + let mut fast_ac = [0; 1 << HUFF_LOOKAHEAD]; + + for i in 0..(1 << HUFF_LOOKAHEAD) { + let fast_v = fast[i]; + + if fast_v < 255 { + // get symbol value from AC table + let rs = self.values[fast_v as usize]; + // shift by 4 to get run length + let run = i16::from((rs >> 4) & 15); + // get magnitude bits stored at the lower 3 bits + let mag_bits = i16::from(rs & 15); + // length of the bit we've read + let len = i16::from(huff_size[fast_v as usize]); + + if mag_bits != 0 && (len + mag_bits) <= i16::from(HUFF_LOOKAHEAD) { + // magnitude code followed by receive_extend code + let mut k = (((i as i16) << len) & ((1 << HUFF_LOOKAHEAD) - 1)) + >> (i16::from(HUFF_LOOKAHEAD) - mag_bits); + let m = 1 << (mag_bits - 1); + + if k < m { + k += (!0_i16 << mag_bits) + 1; + }; + + // if result is small enough fit into fast ac table + if (-128..=127).contains(&k) { + fast_ac[i] = (k << 8) + (run << 4) + (len + mag_bits); + } + } + } + } + self.ac_lookup = Some(fast_ac); + } + + // Validate symbols as being reasonable + // For AC tables, we make no check, but accept all byte values 0..255 + // For DC tables, we require symbols to be in range 0..15 + if is_dc { + for i in 0..num_symbols { + let sym = self.values[i]; + + if sym > 15 { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + } + } + + Ok(()) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/avx2.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/avx2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/avx2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/avx2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "x86")] +#![allow(dead_code)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +/// SAFETY +/// ------ +/// +/// It is the responsibility of the CALLER to ensure that this function is +/// called in contexts where the CPU supports it +/// +/// +/// For documentation see module docs. + +pub fn idct_avx2(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + unsafe { + // We don't call this method directly because we need to flag the code function + // with #[target_feature] so that the compiler does do weird stuff with + // it + idct_int_avx2_inner(in_vector, out_vector, stride); + } +} + +#[target_feature(enable = "avx2")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_int_avx2_inner( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let rw0 = _mm256_loadu_si256(in_vector[00..].as_ptr().cast()); + let rw1 = _mm256_loadu_si256(in_vector[08..].as_ptr().cast()); + let rw2 = _mm256_loadu_si256(in_vector[16..].as_ptr().cast()); + let rw3 = _mm256_loadu_si256(in_vector[24..].as_ptr().cast()); + let rw4 = _mm256_loadu_si256(in_vector[32..].as_ptr().cast()); + let rw5 = _mm256_loadu_si256(in_vector[40..].as_ptr().cast()); + let rw6 = _mm256_loadu_si256(in_vector[48..].as_ptr().cast()); + let rw7 = _mm256_loadu_si256(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + let rw8 = _mm256_loadu_si256(in_vector[1..].as_ptr().cast()); + + let zero = _mm256_setzero_si256(); + + let mut non_zero = 0; + + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw8, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw1, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw2, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw3, zero)); + + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw4, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw5, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw6, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw7, zero)); + + if non_zero == -8 { + // AC terms all zero, idct of the block is is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + let coeff = ((in_vector[0] + 4 + 1024) >> 3).clamp(0, 255) as i16; + let idct_value = _mm_set1_epi16(coeff); + + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + _mm_storeu_si128( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + let mut row0 = YmmRegister { mm256: rw0 }; + let mut row1 = YmmRegister { mm256: rw1 }; + let mut row2 = YmmRegister { mm256: rw2 }; + let mut row3 = YmmRegister { mm256: rw3 }; + + let mut row4 = YmmRegister { mm256: rw4 }; + let mut row5 = YmmRegister { mm256: rw5 }; + let mut row6 = YmmRegister { mm256: rw6 }; + let mut row7 = YmmRegister { mm256: rw7 }; + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = YmmRegister { + mm256: _mm256_slli_epi32((row0 + row4).mm256, 12) + }; + let mut t1 = YmmRegister { + mm256: _mm256_slli_epi32((row0 - row4).mm256, 12) + }; + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0.mm256 = _mm256_srai_epi32((x0 + t3).mm256, $scale); + row1.mm256 = _mm256_srai_epi32((x1 + t2).mm256, $scale); + row2.mm256 = _mm256_srai_epi32((x2 + t1).mm256, $scale); + row3.mm256 = _mm256_srai_epi32((x3 + t0).mm256, $scale); + + row4.mm256 = _mm256_srai_epi32((x3 - t0).mm256, $scale); + row5.mm256 = _mm256_srai_epi32((x2 - t1).mm256, $scale); + row6.mm256 = _mm256_srai_epi32((x1 - t2).mm256, $scale); + row7.mm256 = _mm256_srai_epi32((x0 - t3).mm256, $scale); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // Pack i32 to i16's, + // clamp them to be between 0-255 + // Undo shuffling + // Store back to array + macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt) => { + let a = _mm256_packs_epi32($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp_avx(a); + + // /Undo shuffling + let c = _mm256_permute4x64_epi64(b, shuffle(3, 1, 2, 0)); + + // store first vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<0>(c) + ); + $index += stride; + // second vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<1>(c) + ); + $index += stride; + }; + } + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector); +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn clamp_avx(reg: __m256i) -> __m256i { + let min_s = _mm256_set1_epi16(0); + let max_s = _mm256_set1_epi16(255); + + let max_v = _mm256_max_epi16(reg, min_s); //max(a,0) + let min_v = _mm256_min_epi16(max_v, max_s); //min(max(a,0),255) + return min_v; +} + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + ((z << 6) | (y << 4) | (x << 2) | w) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/neon.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(target_arch = "aarch64")] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "neon")] + +use core::arch::aarch64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +/// SAFETY +/// ------ +/// +/// It is the responsibility of the CALLER to ensure that this function is +/// called in contexts where the CPU supports it +/// +/// +/// For documentation see module docs. + +pub fn idct_neon(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + unsafe { + // We don't call this method directly because we need to flag the code function + // with #[target_feature] so that the compiler does do weird stuff with + // it + idct_int_neon_inner(in_vector, out_vector, stride); + } +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn pack_16(a: int32x4x2_t) -> int16x8_t { + vcombine_s16(vqmovn_s32(a.0), vqmovn_s32(a.1)) +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn condense_bottom_16(a: int32x4x2_t, b: int32x4x2_t) -> int16x8x2_t { + int16x8x2_t(pack_16(a), pack_16(b)) +} + +#[target_feature(enable = "neon")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_int_neon_inner( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let mut row0 = YmmRegister::load(in_vector[00..].as_ptr().cast()); + let mut row1 = YmmRegister::load(in_vector[08..].as_ptr().cast()); + let mut row2 = YmmRegister::load(in_vector[16..].as_ptr().cast()); + let mut row3 = YmmRegister::load(in_vector[24..].as_ptr().cast()); + let mut row4 = YmmRegister::load(in_vector[32..].as_ptr().cast()); + let mut row5 = YmmRegister::load(in_vector[40..].as_ptr().cast()); + let mut row6 = YmmRegister::load(in_vector[48..].as_ptr().cast()); + let mut row7 = YmmRegister::load(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + // TODO this should be a shift/shuffle, not a likely unaligned load + let row8 = YmmRegister::load(in_vector[1..].as_ptr().cast()); + + let or_tree = (((row1 | row8) | (row2 | row3)) | ((row4 | row5) | (row6 | row7))); + + if or_tree.all_zero() { + // AC terms all zero, idct of the block is is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + let coeff = ((in_vector[0] + 4 + 1024) >> 3).clamp(0, 255) as i16; + let idct_value = vdupq_n_s16(coeff); + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + vst1q_s16( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // Compiler does a pretty good job of optimizing add + mul pairs + // into multiply-acumulate pairs + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = (row0 + row4).const_shl::<12>(); + let mut t1 = (row0 - row4).const_shl::<12>(); + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0 = (x0 + t3).const_shra::<$scale>(); + row1 = (x1 + t2).const_shra::<$scale>(); + row2 = (x2 + t1).const_shra::<$scale>(); + row3 = (x3 + t0).const_shra::<$scale>(); + + row4 = (x3 - t0).const_shra::<$scale>(); + row5 = (x2 - t1).const_shra::<$scale>(); + row6 = (x1 - t2).const_shra::<$scale>(); + row7 = (x0 - t3).const_shra::<$scale>(); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // Pack i32 to i16's, + // clamp them to be between 0-255 + // Undo shuffling + // Store back to array + + // This could potentially be reorganized to take advantage of the multi-register stores + macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt) => { + let a = condense_bottom_16($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp256_neon(a); + + // store first vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.0 + ); + $index += stride; + // second vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.1 + ); + $index += stride; + }; + } + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector); +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp_neon(reg: int16x8_t) -> int16x8_t { + let min_s = vdupq_n_s16(0); + let max_s = vdupq_n_s16(255); + + let max_v = vmaxq_s16(reg, min_s); //max(a,0) + let min_v = vminq_s16(max_v, max_s); //min(max(a,0),255) + min_v +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp256_neon(reg: int16x8x2_t) -> int16x8x2_t { + int16x8x2_t(clamp_neon(reg.0), clamp_neon(reg.1)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_neon_clamp_256() { + unsafe { + let vals: [i16; 16] = [-1, -2, -3, 4, 256, 257, 258, 240, -1, 290, 2, 3, 4, 5, 6, 7]; + let loaded = vld1q_s16_x2(vals.as_ptr().cast()); + let shuffled = clamp256_neon(loaded); + + let mut result: [i16; 16] = [0; 16]; + + vst1q_s16_x2(result.as_mut_ptr().cast(), shuffled); + + assert_eq!( + result, + [0, 0, 0, 4, 255, 255, 255, 240, 0, 255, 2, 3, 4, 5, 6, 7] + ) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Platform independent IDCT algorithm +//! +//! Not as fast as AVX one. + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +#[allow(unused_assignments)] +#[allow( + clippy::too_many_lines, + clippy::op_ref, + clippy::cast_possible_truncation +)] +pub fn idct_int(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + // Temporary variables. + + let mut pos = 0; + + let mut i = 0; + // Don't check for zeroes inside loop, lift it and check outside + // we want to accelerate the case with 63 0 ac coeff + if &in_vector[1..] == &[0_i32; 63] { + // okay then if you work, yay, let's write you really quick + let coeff = [((in_vector[0] + 4 + 1024) >> 3).clamp(0, 255) as i16; 8]; + + macro_rules! store { + ($index:tt) => { + // position of the MCU + let mcu_stride: &mut [i16; 8] = out_vector + .get_mut($index..$index + 8) + .unwrap() + .try_into() + .unwrap(); + // copy coefficients + mcu_stride.copy_from_slice(&coeff); + // increment index + $index += stride; + }; + } + // write to four positions + store!(pos); + store!(pos); + store!(pos); + store!(pos); + + store!(pos); + store!(pos); + store!(pos); + store!(pos); + } else { + // because the compiler fails to see that it can be auto_vectorised so i'll + // leave it here check out [idct_int_slow, and idct_int_1D to get what i mean ] https://godbolt.org/z/8hqW9z9j9 + for ptr in 0..8 { + let p2 = in_vector[ptr + 16]; + let p3 = in_vector[ptr + 48]; + + let p1 = (p2 + p3).wrapping_mul(2217); + + let t2 = p1 + p3 * -7567; + let t3 = p1 + p2 * 3135; + + let p2 = in_vector[ptr]; + let p3 = in_vector[32 + ptr]; + let t0 = fsh(p2 + p3); + let t1 = fsh(p2 - p3); + + let x0 = t0 + t3 + 512; + let x3 = t0 - t3 + 512; + let x1 = t1 + t2 + 512; + let x2 = t1 - t2 + 512; + + // odd part + let mut t0 = in_vector[ptr + 56]; + let mut t1 = in_vector[ptr + 40]; + let mut t2 = in_vector[ptr + 24]; + let mut t3 = in_vector[ptr + 8]; + + let p3 = t0 + t2; + let p4 = t1 + t3; + let p1 = t0 + t3; + let p2 = t1 + t2; + let p5 = (p3 + p4) * 4816; + + t0 *= 1223; + t1 *= 8410; + t2 *= 12586; + t3 *= 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + p2 * -10497; + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + in_vector[ptr] = (x0 + t3) >> 10; + in_vector[ptr + 8] = (x1 + t2) >> 10; + in_vector[ptr + 16] = (x2 + t1) >> 10; + in_vector[ptr + 24] = (x3 + t0) >> 10; + in_vector[ptr + 32] = (x3 - t0) >> 10; + in_vector[ptr + 40] = (x2 - t1) >> 10; + in_vector[ptr + 48] = (x1 - t2) >> 10; + in_vector[ptr + 56] = (x0 - t3) >> 10; + } + + // This is vectorised in architectures supporting SSE 4.1 + while i < 64 { + // We won't try to short circuit here because it rarely works + + // Even part + let p2 = in_vector[i + 2]; + let p3 = in_vector[i + 6]; + + let p1 = (p2 + p3) * 2217; + let t2 = p1 + p3 * -7567; + let t3 = p1 + p2 * 3135; + + let p2 = in_vector[i]; + let p3 = in_vector[i + 4]; + + let t0 = fsh(p2 + p3); + let t1 = fsh(p2 - p3); + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + let x0 = t0 + t3 + SCALE_BITS; + let x3 = t0 - t3 + SCALE_BITS; + let x1 = t1 + t2 + SCALE_BITS; + let x2 = t1 - t2 + SCALE_BITS; + // odd part + let mut t0 = in_vector[i + 7]; + let mut t1 = in_vector[i + 5]; + let mut t2 = in_vector[i + 3]; + let mut t3 = in_vector[i + 1]; + + let p3 = t0 + t2; + let p4 = t1 + t3; + let p1 = t0 + t3; + let p2 = t1 + t2; + let p5 = (p3 + p4) * f2f(1.175875602); + + t0 = t0.wrapping_mul(1223); + t1 = t1.wrapping_mul(8410); + t2 = t2.wrapping_mul(12586); + t3 = t3.wrapping_mul(6149); + + let p1 = p5 + p1 * -3685; + let p2 = p5 + p2 * -10497; + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + let out: &mut [i16; 8] = out_vector + .get_mut(pos..pos + 8) + .unwrap() + .try_into() + .unwrap(); + + out[0] = clamp((x0 + t3) >> 17); + out[1] = clamp((x1 + t2) >> 17); + out[2] = clamp((x2 + t1) >> 17); + out[3] = clamp((x3 + t0) >> 17); + out[4] = clamp((x3 - t0) >> 17); + out[5] = clamp((x2 - t1) >> 17); + out[6] = clamp((x1 - t2) >> 17); + out[7] = clamp((x0 - t3) >> 17); + + i += 8; + + pos += stride; + } + } +} + +#[inline] +#[allow(clippy::cast_possible_truncation)] +/// Multiply a number by 4096 +fn f2f(x: f32) -> i32 { + (x * 4096.0 + 0.5) as i32 +} + +#[inline] +/// Multiply a number by 4096 +fn fsh(x: i32) -> i32 { + x << 12 +} + +/// Clamp values between 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation)] +fn clamp(a: i32) -> i16 { + a.clamp(0, 255) as i16 +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/idct.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Routines for IDCT +//! +//! Essentially we provide 2 routines for IDCT, a scalar implementation and a not super optimized +//! AVX2 one, i'll talk about them here. +//! +//! There are 2 reasons why we have the avx one +//! 1. No one compiles with -C target-features=avx2 hence binaries won't probably take advantage(even +//! if it exists). +//! 2. AVX employs zero short circuit in a way the scalar code cannot employ it. +//! - AVX does this by checking for MCU's whose 63 AC coefficients are zero and if true, it writes +//! values directly, if false, it goes the long way of calculating. +//! - Although this can be trivially implemented in the scalar version, it generates code +//! I'm not happy width(scalar version that basically loops and that is too many branches for me) +//! The avx one does a better job of using bitwise or's with (`_mm256_or_si256`) which is magnitudes of faster +//! than anything I could come up with +//! +//! The AVX code also has some cool transpose_u16 instructions which look so complicated to be cool +//! (spoiler alert, i barely understand how it works, that's why I credited the owner). +//! +#![allow( + clippy::excessive_precision, + clippy::unreadable_literal, + clippy::module_name_repetitions, + unused_parens, + clippy::wildcard_imports +)] + +use zune_core::log::debug; +use zune_core::options::DecoderOptions; + +use crate::decoder::IDCTPtr; +use crate::idct::scalar::idct_int; + +#[cfg(feature = "x86")] +pub mod avx2; +#[cfg(feature = "neon")] +pub mod neon; + +pub mod scalar; + +/// Choose an appropriate IDCT function +#[allow(unused_variables)] +pub fn choose_idct_func(options: &DecoderOptions) -> IDCTPtr { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + if options.use_avx2() { + debug!("Using vector integer IDCT"); + // use avx one + return crate::idct::avx2::idct_avx2; + } + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + { + if options.use_neon() { + debug!("Using vector integer IDCT"); + return crate::idct::neon::idct_neon; + } + } + debug!("Using scalar integer IDCT"); + // use generic one + return idct_int; +} + +#[cfg(test)] +#[allow(unreachable_code)] +#[allow(dead_code)] +mod tests { + use super::*; + + #[test] + fn idct_test0() { + let stride = 8; + let mut coeff = [10; 64]; + let mut coeff2 = [10; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test1() { + let stride = 8; + let mut coeff = [14; 64]; + let mut coeff2 = [14; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test2() { + let stride = 8; + let mut coeff = [0; 64]; + coeff[0] = 255; + coeff[63] = -256; + let mut coeff2 = coeff; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_zeros() { + let stride = 8; + let mut coeff = [0; 64]; + let mut coeff2 = [0; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + fn idct_fnc() -> IDCTPtr { + #[cfg(feature = "neon")] + #[cfg(target_arch = "aarch64")] + { + use crate::idct::neon::idct_neon; + return idct_neon; + } + + #[cfg(feature = "x86")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use crate::idct::avx2::idct_avx2; + return idct_avx2; + } + + idct_int + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!This crate provides a library for decoding valid +//! ITU-T Rec. T.851 (09/2005) ITU-T T.81 (JPEG-1) or JPEG images. +//! +//! +//! +//! # Features +//! - SSE and AVX accelerated functions to speed up certain decoding operations +//! - FAST and accurate 32 bit IDCT algorithm +//! - Fast color convert functions +//! - RGBA and RGBX (4-Channel) color conversion functions +//! - YCbCr to Luma(Grayscale) conversion. +//! +//! # Usage +//! Add zune-jpeg to the dependencies in the project Cargo.toml +//! +//! ```toml +//! [dependencies] +//! zune_jpeg = "0.3" +//! ``` +//! # Examples +//! +//! ## Decode a JPEG file with default arguments. +//!```no_run +//! use std::fs::read; +//! use zune_jpeg::JpegDecoder; +//! let file_contents = read("a_jpeg.file").unwrap(); +//! let mut decoder = JpegDecoder::new(&file_contents); +//! let mut pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Decode a JPEG file to RGBA format +//! +//! - Other (limited) supported formats are and BGR, BGRA +//! +//!```no_run +//! use zune_core::colorspace::ColorSpace; +//! use zune_core::options::DecoderOptions; +//! use zune_jpeg::JpegDecoder; +//! +//! let mut options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::RGBA); +//! +//! let mut decoder = JpegDecoder::new_with_options(&[],options); +//! let pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Decode an image and get it's width and height. +//!```no_run +//! use zune_jpeg::JpegDecoder; +//! +//! let mut decoder = JpegDecoder::new(&[]); +//! decoder.decode_headers().unwrap(); +//! let image_info = decoder.info().unwrap(); +//! println!("{},{}",image_info.width,image_info.height) +//! ``` +//! # Crate features. +//! This crate tries to be as minimal as possible while being extensible +//! enough to handle the complexities arising from parsing different types +//! of jpeg images. +//! +//! Safety is a top concern that is why we provide both static ways to disable unsafe code, +//! disabling x86 feature, and dynamic ,by using [`DecoderOptions::set_use_unsafe(false)`], +//! both of these disable platform specific optimizations, which reduce the speed of decompression. +//! +//! Please do note that careful consideration has been taken to ensure that the unsafe paths +//! are only unsafe because they depend on platform specific intrinsics, hence no need to disable them +//! +//! The crate tries to decode as many images as possible, as a best effort, even those violating the standard +//! , this means a lot of images may get silent warnings and wrong output, but if you are sure you will be handling +//! images that follow the spec, set `ZuneJpegOptions::set_strict` to true. +//! +//![`DecoderOptions::set_use_unsafe(false)`]: https://docs.rs/zune-core/0.2.1/zune_core/options/struct.DecoderOptions.html#method.set_use_unsafe + +#![warn( + clippy::correctness, + clippy::perf, + clippy::pedantic, + clippy::inline_always, + clippy::missing_errors_doc, + clippy::panic +)] +#![allow( + clippy::needless_return, + clippy::similar_names, + clippy::inline_always, + clippy::similar_names, + clippy::doc_markdown, + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc +)] +// no_std compatibility +#![deny(clippy::std_instead_of_alloc, clippy::alloc_instead_of_core)] +#![cfg_attr(not(any(feature = "x86", feature = "neon")), forbid(unsafe_code))] +#![cfg_attr(not(feature = "std"), no_std)] +#![macro_use] +extern crate alloc; +extern crate core; + +pub use zune_core; + +pub use crate::decoder::{ImageInfo, JpegDecoder}; + +mod bitstream; +mod color_convert; +mod components; +mod decoder; +pub mod errors; +mod headers; +mod huffman; +#[cfg(not(fuzzing))] +mod idct; +#[cfg(fuzzing)] +pub mod idct; +mod marker; +mod mcu; +mod mcu_prog; +mod misc; +mod unsafe_utils; +mod unsafe_utils_avx2; +mod unsafe_utils_neon; +mod upsampler; +mod worker; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/marker.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/marker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/marker.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/marker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow(clippy::upper_case_acronyms)] + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Marker { + /// Start Of Frame markers + /// + /// - SOF(0): Baseline DCT (Huffman coding) + /// - SOF(1): Extended sequential DCT (Huffman coding) + /// - SOF(2): Progressive DCT (Huffman coding) + /// - SOF(3): Lossless (sequential) (Huffman coding) + /// - SOF(5): Differential sequential DCT (Huffman coding) + /// - SOF(6): Differential progressive DCT (Huffman coding) + /// - SOF(7): Differential lossless (sequential) (Huffman coding) + /// - SOF(9): Extended sequential DCT (arithmetic coding) + /// - SOF(10): Progressive DCT (arithmetic coding) + /// - SOF(11): Lossless (sequential) (arithmetic coding) + /// - SOF(13): Differential sequential DCT (arithmetic coding) + /// - SOF(14): Differential progressive DCT (arithmetic coding) + /// - SOF(15): Differential lossless (sequential) (arithmetic coding) + SOF(u8), + /// Define Huffman table(s) + DHT, + /// Define arithmetic coding conditioning(s) + DAC, + /// Restart with modulo 8 count `m` + RST(u8), + /// Start of image + SOI, + /// End of image + EOI, + /// Start of scan + SOS, + /// Define quantization table(s) + DQT, + /// Define number of lines + DNL, + /// Define restart interval + DRI, + /// Reserved for application segments + APP(u8), + /// Comment + COM +} + +impl Marker { + pub fn from_u8(n: u8) -> Option { + use self::Marker::{APP, COM, DAC, DHT, DNL, DQT, DRI, EOI, RST, SOF, SOI, SOS}; + + match n { + 0xFE => Some(COM), + 0xC0 => Some(SOF(0)), + 0xC1 => Some(SOF(1)), + 0xC2 => Some(SOF(2)), + 0xC4 => Some(DHT), + 0xCC => Some(DAC), + 0xD0 => Some(RST(0)), + 0xD1 => Some(RST(1)), + 0xD2 => Some(RST(2)), + 0xD3 => Some(RST(3)), + 0xD4 => Some(RST(4)), + 0xD5 => Some(RST(5)), + 0xD6 => Some(RST(6)), + 0xD7 => Some(RST(7)), + 0xD8 => Some(SOI), + 0xD9 => Some(EOI), + 0xDA => Some(SOS), + 0xDB => Some(DQT), + 0xDC => Some(DNL), + 0xDD => Some(DRI), + 0xE0 => Some(APP(0)), + 0xE1 => Some(APP(1)), + 0xE2 => Some(APP(2)), + 0xED => Some(APP(13)), + 0xEE => Some(APP(14)), + _ => None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,705 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::{format, vec}; +use core::cmp::min; +use alloc::vec::Vec; +use zune_core::bytestream::ZReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::colorspace::ColorSpace::Luma; +use zune_core::log::{error, trace, warn}; + +use crate::bitstream::BitStream; +use crate::components::SampleRatios; +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::marker::Marker; +use crate::mcu_prog::get_marker; +use crate::misc::{calculate_padded_width, setup_component_params}; +use crate::worker::{color_convert, upsample}; +use crate::JpegDecoder; + +/// The size of a DC block for a MCU. + +pub const DCT_BLOCK: usize = 64; + +impl JpegDecoder { + /// Check for existence of DC and AC Huffman Tables + pub(crate) fn check_tables(&self) -> Result<(), DecodeErrors> { + // check that dc and AC tables exist outside the hot path + for component in &self.components { + let _ = &self + .dc_huffman_tables + .get(component.dc_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman DC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No DC table for component {:?}", + component.component_id + )) + })?; + + let _ = &self + .ac_huffman_tables + .get(component.ac_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman AC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No AC table for component {:?}", + component.component_id + )) + })?; + } + Ok(()) + } + + /// Decode MCUs and carry out post processing. + /// + /// This is the main decoder loop for the library, the hot path. + /// + /// Because of this, we pull in some very crazy optimization tricks hence readability is a pinch + /// here. + #[allow( + clippy::similar_names, + clippy::too_many_lines, + clippy::cast_possible_truncation + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_baseline( + &mut self, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + // check dc and AC tables + self.check_tables()?; + + let (mut mcu_width, mut mcu_height); + + if self.is_interleaved { + // set upsampling functions + self.set_upsampling()?; + + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided bu 8. + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + + self.reset_params(); + + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + let width = usize::from(self.info.width); + + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut stream = BitStream::new(); + let mut tmp = [0_i32; DCT_BLOCK]; + + let comp_len = self.components.len(); + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || comp_len == 4 + // Special colorspace + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + // If all components are contained in the first scan of MCUs, then we can process into + // (upsampled) pixels immediately after each MCU, for convenience we use each row of MCUS. + // Otherwise, we must first wait until following SOS provide the remaining components. + let all_components_in_first_scan = usize::from(self.num_scans) == self.components.len(); + let mut progressive_mcus: [Vec; 4] = core::array::from_fn(|_| vec![]); + + if !all_components_in_first_scan { + for (component, mcu) in self.components.iter().zip(&mut progressive_mcus) { + let len = mcu_width + * component.vertical_sample + * component.horizontal_sample + * mcu_height + * 64; + *mcu = vec![0; len]; + } + } + + let mut pixels_written = 0; + + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + + 'sos: loop { + trace!( + "Baseline decoding of components: {:?}", + &self.z_order[..usize::from(self.num_scans)] + ); + trace!("Decoding MCU width: {mcu_width}, height: {mcu_height}"); + + for i in 0..mcu_height { + // Report if we have no more bytes + // This may generate false negatives since we over-read bytes + // hence that why 37 is chosen(we assume if we over-read more than 37 bytes, we have a problem) + if stream.overread_by > 37 + // favourite number :) + { + if self.options.get_strict_mode() { + return Err(DecodeErrors::FormatStatic("Premature end of buffer")); + }; + + error!("Premature end of buffer"); + break; + } + + // decode a whole MCU width, + // this takes into account interleaved components. + let terminate = if all_components_in_first_scan { + self.decode_mcu_width::( + mcu_width, + i, + &mut tmp, + &mut stream, + &mut progressive_mcus, + )? + } else { + self.decode_mcu_width::( + mcu_width, + i, + &mut tmp, + &mut stream, + &mut progressive_mcus, + )? + }; + + // process that width up until it's impossible. This is faster than allocation the + // full components, which we skipped earlier. + if all_components_in_first_scan { + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space, + )?; + } + + match terminate { + McuContinuation::Ok => {} + McuContinuation::AnotherSos if all_components_in_first_scan => { + warn!("More than one SOS despite already having all components"); + return Ok(()); + } + McuContinuation::AnotherSos => continue 'sos, + McuContinuation::Terminate => { + warn!("Got terminate signal, will not process further"); + return Ok(()); + } + } + } + + // Breaks if we get here, looping only if we have restarted, i.e. found another SOS and + // continued at `'sos'. + break; + } + + if !all_components_in_first_scan { + self.finish_baseline_decoding(&progressive_mcus, mcu_width, pixels)?; + } + + // it may happen that some images don't have the whole buffer + // so we can't panic in case of that + // assert_eq!(pixels_written, pixels.len()); + + // For UHD usecases that tie two images separating them with EOI and + // SOI markers, it may happen that we do not reach this image end of image + // So this ensures we reach it + // Ensure we read EOI + if !stream.seen_eoi { + let marker = get_marker(&mut self.stream, &mut stream); + match marker { + Ok(_m) => { + trace!("Found marker {:?}", _m); + } + Err(_) => { + // ignore error + } + } + } + + trace!("Finished decoding image"); + + Ok(()) + } + + /// Process all MCUs when baseline decoding has been processing them component-after-component. + /// For simplicity this assembles the dequantized blocks in the order that the post processing + /// of an interleaved baseline decoding would use. + #[allow(clippy::too_many_lines)] + #[allow(clippy::cast_sign_loss)] + pub(crate) fn finish_baseline_decoding( + &mut self, block: &[Vec; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8], + ) -> Result<(), DecodeErrors> { + let mcu_height = self.mcu_y; + + // Size of our output image(width*height) + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let width = usize::from(self.info.width); + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Mark only needed components for computing output colors. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos, + ) == pos + || self.input_colorspace == ColorSpace::YCCK + || self.input_colorspace == ColorSpace::CMYK + { + comp.needed = true; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + // dequantize and idct have been performed, only color convert. + for i in 0..mcu_height { + // All the data is already in the right order, we just need to be able to pass it to + // the post_process & upsample method. That expects all the data to be stored as one + // row of MCUs in each component's `raw_coeff`. + 'component: for (position, component) in &mut self.components.iter_mut().enumerate() { + if !component.needed { + continue 'component; + } + + // step is the number of pixels this iteration wil be handling + // Given by the number of mcu's height and the length of the component block + // Since the component block contains the whole channel as raw pixels + // we this evenly divides the pixels into MCU blocks + // + // For interleaved images, this gives us the exact pixels comprising a whole MCU + // block + let step = block[position].len() / mcu_height; + + // where we will be reading our pixels from. + let slice = &block[position][i * step..][..step]; + let temp_channel = &mut component.raw_coeff; + temp_channel[..step].copy_from_slice(slice); + } + + // process that whole stripe of MCUs + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space, + )?; + } + + return Ok(()); + } + + fn decode_mcu_width( + &mut self, mcu_width: usize, mcu_height: usize, tmp: &mut [i32; 64], + stream: &mut BitStream, progressive: &mut [Vec; 4], + ) -> Result { + let z_order = self.z_order; + + for j in 0..mcu_width { + // iterate over components + for &k in &z_order[..usize::from(self.num_scans)] { + let component = &mut self.components[k]; + + let dc_table = self.dc_huffman_tables[component.dc_huff_table % MAX_COMPONENTS] + .as_ref() + .unwrap(); + + let ac_table = self.ac_huffman_tables[component.ac_huff_table % MAX_COMPONENTS] + .as_ref() + .unwrap(); + + let qt_table = &component.quantization_table; + let channel = if PROGRESSIVE { + let offset = + mcu_height * component.width_stride * 8 * component.vertical_sample; + &mut progressive[k][offset..] + } else { + &mut component.raw_coeff + }; + + // If image is interleaved iterate over scan components, + // otherwise if it-s non-interleaved, these routines iterate in + // trivial scanline order(Y,Cb,Cr) + for v_samp in 0..component.vertical_sample { + for h_samp in 0..component.horizontal_sample { + // Fill the array with zeroes, decode_mcu_block expects + // a zero based array. + tmp.fill(0); + + stream.decode_mcu_block( + &mut self.stream, + dc_table, + ac_table, + qt_table, + tmp, + &mut component.dc_pred, + )?; + + if component.needed { + let idct_position = { + // derived from stb and rewritten for my tastes + let c2 = v_samp * 8; + let c3 = ((j * component.horizontal_sample) + h_samp) * 8; + + component.width_stride * c2 + c3 + }; + + let idct_pos = channel.get_mut(idct_position..).unwrap(); + // call idct. + (self.idct_func)(tmp, idct_pos, component.width_stride); + } + } + } + } + + self.todo = self.todo.wrapping_sub(1); + + if self.todo == 0 { + self.handle_rst_main(stream)?; + continue; + } + + if stream.marker.is_some() && stream.bits_left == 0 { + break; + } + } + + // After all interleaved components, that's an MCU + // handle stream markers + // + // In some corrupt images, it may occur that header markers occur in the stream. + // The spec EXPLICITLY FORBIDS this, specifically, in + // routine F.2.2.5 it says + // `The only valid marker which may occur within the Huffman coded data is the RSTm marker.` + // + // But libjpeg-turbo allows it because of some weird reason. so I'll also + // allow it because of some weird reason. + if let Some(m) = stream.marker { + if m == Marker::EOI { + // acknowledge and ignore EOI marker. + stream.marker.take(); + trace!("Found EOI marker"); + // Google Introduced the Ultra-HD image format which is basically + // stitching two images into one container. + // They basically separate two images via a EOI and SOI marker + // so let's just ensure if we ever see EOI, we never read past that + // ever. + // https://github.com/google/libultrahdr + stream.seen_eoi = true; + } else if let Marker::RST(_) = m { + //debug_assert_eq!(self.todo, 0); + if self.todo == 0 { + self.handle_rst(stream)?; + } + } else if let Marker::SOS = m { + self.parse_marker_inner(m)?; + stream.marker.take(); + stream.reset(); + trace!("Found SOS marker"); + return Ok(McuContinuation::AnotherSos); + } else { + if self.options.get_strict_mode() { + return Err(DecodeErrors::Format(format!( + "Marker {m:?} found where not expected" + ))); + } + error!( + "Marker `{:?}` Found within Huffman Stream, possibly corrupt jpeg", + m + ); + + self.parse_marker_inner(m)?; + stream.marker.take(); + stream.reset(); + return Ok(McuContinuation::Terminate); + } + } + + Ok(McuContinuation::Ok) + } + // handle RST markers. + // No-op if not using restarts + // this routine is shared with mcu_prog + #[cold] + pub(crate) fn handle_rst(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> { + self.todo = self.restart_interval; + + if let Some(marker) = stream.marker { + // Found a marker + // Read stream and see what marker is stored there + match marker { + Marker::RST(_) => { + // reset stream + stream.reset(); + // Initialize dc predictions to zero for all components + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + // Start iterating again. from position. + } + Marker::EOI => { + // silent pass + } + _ => { + return Err(DecodeErrors::MCUError(format!( + "Marker {marker:?} found in bitstream, possibly corrupt jpeg" + ))); + } + } + } + Ok(()) + } + #[allow(clippy::too_many_lines, clippy::too_many_arguments)] + pub(crate) fn post_process( + &mut self, pixels: &mut [u8], i: usize, mcu_height: usize, width: usize, + padded_width: usize, pixels_written: &mut usize, upsampler_scratch_space: &mut [i16] + ) -> Result<(), DecodeErrors> { + let out_colorspace_components = self.options.jpeg_get_out_colorspace().num_components(); + + let mut px = *pixels_written; + // indicates whether image is vertically up-sampled + let is_vertically_sampled = self + .components + .iter() + .any(|c| c.sample_ratio == SampleRatios::HV || c.sample_ratio == SampleRatios::V); + + let mut comp_len = self.components.len(); + + // If we are moving from YCbCr -> Luma, we do not allocate storage for other components, so we + // will panic when we are trying to read samples, so for that case, + // hardcode it so that we don't panic when doing + // *samp = &samples[j][pos * padded_width..(pos + 1) * padded_width] + if out_colorspace_components < comp_len && self.options.jpeg_get_out_colorspace() == Luma { + comp_len = out_colorspace_components; + } + let mut color_conv_function = + |num_iters: usize, samples: [&[i16]; 4]| -> Result<(), DecodeErrors> { + for (pos, output) in pixels[px..] + .chunks_exact_mut(width * out_colorspace_components) + .take(num_iters) + .enumerate() + { + let mut raw_samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + // iterate over each line, since color-convert needs only + // one line + for (j, samp) in raw_samples.iter_mut().enumerate().take(comp_len) { + *samp = &samples[j][pos * padded_width..(pos + 1) * padded_width]; + } + color_convert( + &raw_samples, + self.color_convert_16, + self.input_colorspace, + self.options.jpeg_get_out_colorspace(), + output, + width, + padded_width + )?; + px += width * out_colorspace_components; + } + Ok(()) + }; + + let comps = &mut self.components[..]; + + if self.is_interleaved && self.options.jpeg_get_out_colorspace() != ColorSpace::Luma { + { + // duplicated so that we can check that samples match + // Fixes bug https://github.com/etemesi254/zune-image/issues/151 + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = if component.sample_ratio == SampleRatios::None { + &component.raw_coeff + } else { + &component.upsample_dest + }; + } + } + for comp in comps.iter_mut() { + upsample( + comp, + mcu_height, + i, + upsampler_scratch_space, + is_vertically_sampled + ); + } + + if is_vertically_sampled { + if i > 0 { + // write the last line, it wasn't up-sampled as we didn't have row_down + // yet + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = &component.first_row_upsample_dest; + } + + // ensure length matches for all samples + let _first_len = samples[0].len(); + + // This was a good check, but can be caused to panic, esp on invalid/corrupt images. + // See one in issue https://github.com/etemesi254/zune-image/issues/262, so for now + // we just ignore and generate invalid images at the end. + + // + // + // for samp in samples.iter().take(comp_len) { + // assert_eq!(first_len, samp.len()); + // } + let num_iters = self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } + + // After up-sampling the last row, save any row that can be used for + // a later up-sampling, + // + // E.g the Y sample is not sampled but we haven't finished upsampling the last row of + // the previous mcu, since we don't have the down row, so save it + for component in comps.iter_mut() { + if component.sample_ratio != SampleRatios::H { + // We don't care about H sampling factors, since it's copied in the workers function + + // copy last row to be used for the next color conversion + let size = component.vertical_sample + * component.width_stride + * component.sample_ratio.sample(); + + let last_bytes = + component.raw_coeff.rchunks_exact_mut(size).next().unwrap(); + + component + .first_row_upsample_dest + .copy_from_slice(last_bytes); + } + } + } + + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = if component.sample_ratio == SampleRatios::None { + &component.raw_coeff + } else { + &component.upsample_dest + }; + } + + // we either do 7 or 8 MCU's depending on the state, this only applies to + // vertically sampled images + // + // for rows up until the last MCU, we do not upsample the last stride of the MCU + // which means that the number of iterations should take that into account is one less the + // up-sampled size + // + // For the last MCU, we upsample the last stride, meaning that if we hit the last MCU, we + // should sample full raw coeffs + let is_last_considered = is_vertically_sampled && (i != mcu_height.saturating_sub(1)); + + let num_iters = (8 - usize::from(is_last_considered)) * self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } else { + let mut channels_ref: [&[i16]; MAX_COMPONENTS] = [&[]; MAX_COMPONENTS]; + + self.components + .iter() + .enumerate() + .for_each(|(pos, x)| channels_ref[pos] = &x.raw_coeff); + + if let SampleRatios::Generic(_, v) = self.sub_sample_ratio { + color_conv_function(8 * v * self.coeff, channels_ref)?; + } else { + color_conv_function(8 * self.coeff, channels_ref)?; + } + } + + *pixels_written = px; + Ok(()) + } +} + +enum McuContinuation { + Ok, + AnotherSos, + Terminate, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu_prog.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu_prog.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu_prog.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/mcu_prog.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Routines for progressive decoding +/* +This file is needlessly complicated, + +It is that way to ensure we don't burn memory anyhow + +Memory is a scarce resource in some environments, I would like this to be viable +in such environments + +Half of the complexity comes from the jpeg spec, because progressive decoding, +is one hell of a ride. + +*/ +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; +use core::cmp::min; +use zune_core::bytestream::{ZByteReader, ZReaderTrait}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, error, warn}; + +use crate::bitstream::BitStream; +use crate::components::{ComponentID, SampleRatios}; +use crate::decoder::{JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::headers::{parse_sos}; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::{calculate_padded_width, setup_component_params}; + +impl JpegDecoder { + /// Decode a progressive image + /// + /// This routine decodes a progressive image, stopping if it finds any error. + #[allow( + clippy::needless_range_loop, + clippy::cast_sign_loss, + clippy::redundant_else, + clippy::too_many_lines + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_progressive( + &mut self, pixels: &mut [u8], + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + let mut mcu_height; + + // memory location for decoded pixels for components + let mut block: [Vec; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]]; + let mut mcu_width; + + let mut seen_scans = 1; + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + self.reset_params(); + } + + if self.is_interleaved { + // this helps us catch component errors. + self.set_upsampling()?; + } + if self.is_interleaved { + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + mcu_width = (self.info.width as usize + 7) / 8; + mcu_height = (self.info.height as usize + 7) / 8; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + mcu_width *= 64; + + + for i in 0..self.input_colorspace.num_components() { + let comp = &self.components[i]; + let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height; + + block[i] = vec![0; len]; + } + + let mut stream = BitStream::new_progressive( + self.succ_high, + self.succ_low, + self.spec_start, + self.spec_end + ); + + // there are multiple scans in the stream, this should resolve the first scan + self.parse_entropy_coded_data(&mut stream, &mut block)?; + + // extract marker + let mut marker = stream + .marker + .take() + .ok_or(DecodeErrors::FormatStatic("Marker missing where expected"))?; + + // if marker is EOI, we are done, otherwise continue scanning. + // + // In case we have a premature image, we print a warning or return + // an error, depending on the strictness of the decoder, so there + // is that logic to handle too + 'eoi: while marker != Marker::EOI { + match marker { + Marker::SOS => { + parse_sos(self)?; + + stream.update_progressive_params( + self.succ_high, + self.succ_low, + self.spec_start, + self.spec_end + ); + // after every SOS, marker, parse data for that scan. + self.parse_entropy_coded_data(&mut stream, &mut block)?; + // extract marker, might either indicate end of image or we continue + // scanning(hence the continue statement to determine). + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + seen_scans += 1; + if seen_scans > self.options.jpeg_get_max_scans() { + return Err(DecodeErrors::Format(format!( + "Too many scans, exceeded limit of {}", + self.options.jpeg_get_max_scans() + ))); + } + + stream.reset(); + continue 'eoi; + } + Err(msg) => { + if self.options.get_strict_mode() { + return Err(msg); + } + error!("{:?}", msg); + break 'eoi; + } + } + } + Marker::RST(_n) => { + self.handle_rst(&mut stream)?; + } + _ => { + self.parse_marker_inner(marker)?; + } + } + + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + } + Err(e) => { + if self.options.get_strict_mode() { + return Err(e); + } + error!("{}", e); + } + } + } + + self.finish_progressive_decoding(&block, mcu_width, pixels) + } + + /// Reset progressive parameters + fn reset_prog_params(&mut self, stream: &mut BitStream) { + stream.reset(); + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + + // Also reset JPEG restart intervals + self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX }; + } + + #[allow(clippy::too_many_lines, clippy::cast_sign_loss)] + fn parse_entropy_coded_data( + &mut self, stream: &mut BitStream, buffer: &mut [Vec; MAX_COMPONENTS] + ) -> Result<(), DecodeErrors> { + self.reset_prog_params(stream); + + if usize::from(self.num_scans) > self.input_colorspace.num_components() { + return Err(DecodeErrors::Format(format!( + "Number of scans {} cannot be greater than number of components, {}", + self.num_scans, + self.input_colorspace.num_components() + ))); + } + if self.num_scans == 1 { + // Safety checks + if self.spec_end != 0 && self.spec_start == 0 { + return Err(DecodeErrors::FormatStatic( + "Can't merge DC and AC corrupt jpeg" + )); + } + // non interleaved data, process one block at a time in trivial scanline order + + let k = self.z_order[0]; + + if k >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {k}, corrupt image" + ))); + } + + let (mcu_width, mcu_height); + + if self.components[k].component_id == ComponentID::Y + && (self.components[k].vertical_sample != 1 + || self.components[k].horizontal_sample != 1) + || !self.is_interleaved + { + // For Y channel or non interleaved scans , + // mcu's is the image dimensions divided by 8 + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } else { + // For other channels, in an interleaved mcu, number of MCU's + // are determined by some weird maths done in headers.rs->parse_sos() + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } + + for i in 0..mcu_height { + for j in 0..mcu_width { + if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 { + // handle EOB runs here. + stream.eob_run -= 1; + } else { + let start = 64 * (j + i * (self.components[k].width_stride / 8)); + + let data: &mut [i16; 64] = buffer + .get_mut(k) + .unwrap() + .get_mut(start..start + 64) + .unwrap() + .try_into() + .unwrap(); + + if self.spec_start == 0 { + let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1); + let dc_table = self + .dc_huffman_tables + .get(pos) + .ok_or(DecodeErrors::FormatStatic( + "No huffman table for DC component" + ))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index {} not initialized" + ))?; + + let dc_pred = &mut self.components[k].dc_pred; + + if self.succ_high == 0 { + // first scan for this mcu + stream.decode_prog_dc_first( + &mut self.stream, + dc_table, + &mut data[0], + dc_pred + )?; + } else { + // refining scans for this MCU + stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?; + } + } else { + let pos = self.components[k].ac_huff_table; + let ac_table = self + .ac_huffman_tables + .get(pos) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{pos}" + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {pos} not initialized" + )) + })?; + + if self.succ_high == 0 { + debug_assert!(stream.eob_run == 0, "EOB run is not zero"); + + stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?; + } else { + // refinement scan + stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?; + } + } + } + + // + EOB and investigate effect. + self.todo -= 1; + + self.handle_rst_main(stream)?; + } + } + } else { + if self.spec_end != 0 { + return Err(DecodeErrors::HuffmanDecode( + "Can't merge dc and AC corrupt jpeg".to_string() + )); + } + // process scan n elements in order + + // Do the error checking with allocs here. + // Make the one in the inner loop free of allocations. + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + + if n >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {n}, corrupt image" + ))); + } + + let component = &mut self.components[n]; + let _ = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{}", + component.dc_huff_table + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {} not initialized", + component.dc_huff_table + )) + })?; + } + // Interleaved scan + + // Components shall not be interleaved in progressive mode, except for + // the DC coefficients in the first scan for each component of a progressive frame. + for i in 0..self.mcu_y { + for j in 0..self.mcu_x { + // process scan n elements in order + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + let component = &mut self.components[n]; + let huff_table = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or(DecodeErrors::FormatStatic("No huffman table for component"))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index not initialized" + ))?; + + for v_samp in 0..component.vertical_sample { + for h_samp in 0..component.horizontal_sample { + let x2 = j * component.horizontal_sample + h_samp; + let y2 = i * component.vertical_sample + v_samp; + let position = 64 * (x2 + y2 * component.width_stride / 8); + let buf_n = &mut buffer[n]; + + let Some(data) = &mut buf_n.get_mut(position) else { + // TODO: (CAE), this is another weird sub-sampling bug, so on fix + // remove this + return Err(DecodeErrors::FormatStatic("Invalid image")); + }; + + if self.succ_high == 0 { + stream.decode_prog_dc_first( + &mut self.stream, + huff_table, + data, + &mut component.dc_pred + )?; + } else { + stream.decode_prog_dc_refine(&mut self.stream, data)?; + } + } + } + } + // We want wrapping subtraction here because it means + // we get a higher number in the case this underflows + self.todo -= 1; + // after every scan that's a mcu, count down restart markers. + self.handle_rst_main(stream)?; + } + } + } + return Ok(()); + } + + pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> { + if self.todo == 0 { + stream.refill(&mut self.stream)?; + } + + if self.todo == 0 + && self.restart_interval != 0 + && stream.marker.is_none() + && !stream.seen_eoi + { + // if no marker and we are to reset RST, look for the marker, this matches + // libjpeg-turbo behaviour and allows us to decode images in + // https://github.com/etemesi254/zune-image/issues/261 + let _start = self.stream.get_position(); + // skip bytes until we find marker + let marker = get_marker(&mut self.stream, stream)?; + let _end = self.stream.get_position(); + stream.marker = Some(marker); + // NB some warnings may be false positives. + warn!( + "{} Extraneous bytes before marker {:?}", + _end - _start, + marker + ); + } + if self.todo == 0 { + self.handle_rst(stream)? + } + Ok(()) + } + #[allow(clippy::too_many_lines)] + #[allow(clippy::needless_range_loop, clippy::cast_sign_loss)] + fn finish_progressive_decoding( + &mut self, block: &[Vec; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + // This function is complicated because we need to replicate + // the function in mcu.rs + // + // The advantage is that we do very little allocation and very lot + // channel reusing. + // The trick is to notice that we repeat the same procedure per MCU + // width. + // + // So we can set it up that we only allocate temporary storage large enough + // to store a single mcu width, then reuse it per invocation. + // + // This is advantageous to us. + // + // Remember we need to have the whole MCU buffer so we store 3 unprocessed + // channels in memory, and then we allocate the whole output buffer in memory, both of + // which are huge. + // + // + + let mcu_height = if self.is_interleaved { + self.mcu_y + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided by 8. + ((self.info.height + 7) / 8) as usize + }; + + // Size of our output image(width*height) + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let width = usize::from(self.info.width); + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + //let mut pixels = vec![0; capacity * out_colorspace_components]; + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + let mut tmp = [0_i32; DCT_BLOCK]; + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos, + ) == pos + || self.input_colorspace == ColorSpace::YCCK + || self.input_colorspace == ColorSpace::CMYK + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + // dequantize, idct and color convert. + for i in 0..mcu_height { + 'component: for (position, component) in &mut self.components.iter_mut().enumerate() { + if !component.needed { + continue 'component; + } + let qt_table = &component.quantization_table; + + // step is the number of pixels this iteration wil be handling + // Given by the number of mcu's height and the length of the component block + // Since the component block contains the whole channel as raw pixels + // we this evenly divides the pixels into MCU blocks + // + // For interleaved images, this gives us the exact pixels comprising a whole MCU + // block + let step = block[position].len() / mcu_height; + // where we will be reading our pixels from. + let start = i * step; + + let slice = &block[position][start..start + step]; + + let temp_channel = &mut component.raw_coeff; + + // The next logical step is to iterate width wise. + // To figure out how many pixels we iterate by we use effective pixels + // Given to us by component.x + // iterate per effective pixels. + let mcu_x = component.width_stride / 8; + + // iterate per every vertical sample. + for k in 0..component.vertical_sample { + for j in 0..mcu_x { + // after writing a single stride, we need to skip 8 rows. + // This does the row calculation + let width_stride = k * 8 * component.width_stride; + let start = j * 64 + width_stride; + + // See https://github.com/etemesi254/zune-image/issues/262 sample 3. + let Some(qt_slice) = slice.get(start..start + 64) else { + return Err(DecodeErrors::FormatStatic("Invalid slice , would panic, invalid image")) + }; + // dequantize + for ((x, out), qt_val) in qt_slice + .iter() + .zip(tmp.iter_mut()) + .zip(qt_table.iter()) + { + *out = i32::from(*x) * qt_val; + } + // determine where to write. + let sl = &mut temp_channel[component.idct_pos..]; + + component.idct_pos += 8; + // tmp now contains a dequantized block so idct it + (self.idct_func)(&mut tmp, sl, component.width_stride); + } + // after every write of 8, skip 7 since idct write stride wise 8 times. + // + // Remember each MCU is 8x8 block, so each idct will write 8 strides into + // sl + // + // and component.idct_pos is one stride long + component.idct_pos += 7 * component.width_stride; + } + component.idct_pos = 0; + } + + // process that width up until it's impossible + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + + debug!("Finished decoding image"); + + return Ok(()); + } + pub(crate) fn reset_params(&mut self) { + /* + Apparently, grayscale images which can be down sampled exists, which is weird in the sense + that it has one component Y, which is not usually down sampled. + + This means some calculations will be wrong, so for that we explicitly reset params + for such occurrences, warn and reset the image info to appear as if it were + a non-sampled image to ensure decoding works + */ + self.h_max = 1; + self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma); + self.v_max = 1; + self.sub_sample_ratio = SampleRatios::None; + self.is_interleaved = false; + self.components[0].vertical_sample = 1; + self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8; + self.components[0].horizontal_sample = 1; + } +} + +///Get a marker from the bit-stream. +/// +/// This reads until it gets a marker or end of file is encountered +pub fn get_marker( + reader: &mut ZByteReader, stream: &mut BitStream +) -> Result +where + T: ZReaderTrait +{ + if let Some(marker) = stream.marker { + stream.marker = None; + return Ok(marker); + } + + // read until we get a marker + + while !reader.eof() { + let marker = reader.get_u8_err()?; + + if marker == 255 { + let mut r = reader.get_u8_err()?; + // 0xFF 0XFF(some images may be like that) + while r == 0xFF { + r = reader.get_u8_err()?; + } + + if r != 0 { + return Marker::from_u8(r) + .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}"))); + } + } + } + return Err(DecodeErrors::ExhaustedData); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/misc.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/misc.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/misc.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/misc.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Miscellaneous stuff +#![allow(dead_code)] + +use alloc::format; +use core::cmp::max; +use core::fmt; + +use zune_core::bytestream::{ZByteReader, ZReaderTrait}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{trace, warn}; + +use crate::components::{ComponentID, SampleRatios}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::JpegDecoder; + +/// Start of baseline DCT Huffman coding + +pub const START_OF_FRAME_BASE: u16 = 0xffc0; + +/// Start of another frame + +pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1; + +/// Start of progressive DCT encoding + +pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2; + +/// Start of Lossless sequential Huffman coding + +pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3; + +/// Start of extended sequential DCT arithmetic coding + +pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9; + +/// Start of Progressive DCT arithmetic coding + +pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca; + +/// Start of Lossless sequential Arithmetic coding + +pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb; + +/// Undo run length encoding of coefficients by placing them in natural order +#[rustfmt::skip] +pub const UN_ZIGZAG: [usize; 64 + 16] = [ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // Prevent overflowing + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 +]; + +/// Align data to a 16 byte boundary +#[repr(align(16))] +#[derive(Clone)] + +pub struct Aligned16(pub T); + +impl Default for Aligned16 +where + T: Default +{ + fn default() -> Self { + Aligned16(T::default()) + } +} + +/// Align data to a 32 byte boundary +#[repr(align(32))] +#[derive(Clone)] +pub struct Aligned32(pub T); + +impl Default for Aligned32 +where + T: Default +{ + fn default() -> Self { + Aligned32(T::default()) + } +} + +/// Markers that identify different Start of Image markers +/// They identify the type of encoding and whether the file use lossy(DCT) or +/// lossless compression and whether we use Huffman or arithmetic coding schemes +#[derive(Eq, PartialEq, Copy, Clone)] +#[allow(clippy::upper_case_acronyms)] +pub enum SOFMarkers { + /// Baseline DCT markers + BaselineDct, + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Progressive DCT, Huffman coding + ProgressiveDctHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Default for SOFMarkers { + fn default() -> Self { + Self::BaselineDct + } +} + +impl SOFMarkers { + /// Check if a certain marker is sequential DCT or not + + pub fn is_sequential_dct(self) -> bool { + matches!( + self, + Self::BaselineDct + | Self::ExtendedSequentialHuffman + | Self::ExtendedSequentialDctArithmetic + ) + } + + /// Check if a marker is a Lossles type or not + + pub fn is_lossless(self) -> bool { + matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic) + } + + /// Check whether a marker is a progressive marker or not + + pub fn is_progressive(self) -> bool { + matches!( + self, + Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic + ) + } + + /// Create a marker from an integer + + pub fn from_int(int: u16) -> Option { + match int { + START_OF_FRAME_BASE => Some(Self::BaselineDct), + START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman), + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} + +impl fmt::Debug for SOFMarkers { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self { + Self::BaselineDct => write!(f, "Baseline DCT"), + Self::ExtendedSequentialHuffman => { + write!(f, "Extended sequential DCT, Huffman Coding") + } + Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"), + Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"), + Self::ExtendedSequentialDctArithmetic => { + write!(f, "Extended sequential DCT, arithmetic coding") + } + Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"), + Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding") + } + } +} + +/// Read `buf.len()*2` data from the underlying `u8` buffer and convert it into +/// u16, and store it into `buf` +/// +/// # Arguments +/// - reader: A mutable reference to the underlying reader. +/// - buf: A mutable reference to a slice containing u16's +#[inline] +pub fn read_u16_into(reader: &mut ZByteReader, buf: &mut [u16]) -> Result<(), DecodeErrors> +where + T: ZReaderTrait +{ + for i in buf { + *i = reader.get_u16_be_err()?; + } + + Ok(()) +} + +/// Set up component parameters. +/// +/// This modifies the components in place setting up details needed by other +/// parts fo the decoder. +pub(crate) fn setup_component_params( + img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + let img_width = img.width(); + let img_height = img.height(); + + // in case of adobe app14 being present, zero may indicate + // either CMYK if components are 4 or RGB if components are 3, + // see https://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html + // so since we may not know how many number of components + // we have when decoding app14, we have to defer that check + // until now. + // + // We know adobe app14 was present since it's the only one that can modify + // input colorspace to be CMYK + if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK { + img.input_colorspace = ColorSpace::RGB; + } + + for component in &mut img.components { + // compute interleaved image info + // h_max contains the maximum horizontal component + img.h_max = max(img.h_max, component.horizontal_sample); + // v_max contains the maximum vertical component + img.v_max = max(img.v_max, component.vertical_sample); + img.mcu_width = img.h_max * 8; + img.mcu_height = img.v_max * 8; + // Number of MCU's per width + img.mcu_x = (usize::from(img.info.width) + img.mcu_width - 1) / img.mcu_width; + // Number of MCU's per height + img.mcu_y = (usize::from(img.info.height) + img.mcu_height - 1) / img.mcu_height; + + if img.h_max != 1 || img.v_max != 1 { + // interleaved images have horizontal and vertical sampling factors + // not equal to 1. + img.is_interleaved = true; + } + // Extract quantization tables from the arrays into components + let qt_table = *img.qt_tables[component.quantization_table_number as usize] + .as_ref() + .ok_or_else(|| { + DecodeErrors::DqtError(format!( + "No quantization table for component {:?}", + component.component_id + )) + })?; + + let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max; + let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max; + component.x = x; + component.w2 = img.mcu_x * component.horizontal_sample * 8; + // probably not needed. :) + component.y = y; + component.quantization_table = qt_table; + // initially stride contains its horizontal sub-sampling + component.width_stride *= img.mcu_x * 8; + } + { + // Sampling factors are one thing that suck + // this fixes a specific problem with images like + // + // (2 2) None + // (2 1) H + // (2 1) H + // + // The images exist in the wild, the images are not meant to exist + // but they do, it's just an annoying horizontal sub-sampling that + // I don't know why it exists. + // But it does + // So we try to cope with that. + // I am not sure of how to explain how to fix it, but it involved a debugger + // and to much coke(the legal one) + // + // If this wasn't present, self.upsample_dest would have the wrong length + let mut handle_that_annoying_bug = false; + + if let Some(y_component) = img + .components + .iter() + .find(|c| c.component_id == ComponentID::Y) + { + if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 { + handle_that_annoying_bug = true; + } + } + if handle_that_annoying_bug { + for comp in &mut img.components { + if (comp.component_id != ComponentID::Y) + && (comp.horizontal_sample != 1 || comp.vertical_sample != 1) + { + comp.fix_an_annoying_bug = 2; + } + } + } + } + + if img.is_mjpeg { + fill_default_mjpeg_tables( + img.is_progressive, + &mut img.dc_huffman_tables, + &mut img.ac_huffman_tables + ); + } + + // check colorspace matches + if img.input_colorspace.num_components() > img.components.len() { + if img.input_colorspace == ColorSpace::YCCK { + // Some images may have YCCK format (from adobe app14 segment) which is supposed to be 4 components + // but only 3 components, see issue https://github.com/etemesi254/zune-image/issues/275 + // So this is the behaviour of other decoders + // - stb_image: Treats it as YCbCr image + // - libjpeg_turbo: Does not know how to parse YCCK images (transform 2 app14) so treats + // it as YCbCr + // So I will match that to match existing ones + warn!("Treating YCCK colorspace as YCbCr as component length does not match"); + img.input_colorspace = ColorSpace::YCbCr + } else { + let msg = format!( + " Expected {} number of components but found {}", + img.input_colorspace.num_components(), + img.components.len() + ); + + return Err(DecodeErrors::Format(msg)); + } + } + Ok(()) +} + +///Calculate number of fill bytes added to the end of a JPEG image +/// to fill the image +/// +/// JPEG usually inserts padding bytes if the image width cannot be evenly divided into +/// 8 , 16 or 32 chunks depending on the sub sampling ratio. So given a sub-sampling ratio, +/// and the actual width, this calculates the padded bytes that were added to the image +/// +/// # Params +/// -actual_width: Actual width of the image +/// -sub_sample: Sub sampling factor of the image +/// +/// # Returns +/// The padded width, this is how long the width is for a particular image +pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize { + match sub_sample { + SampleRatios::None | SampleRatios::V => { + // None+V sends one MCU row, so that's a simple calculation + ((actual_width + 7) / 8) * 8 + } + SampleRatios::H | SampleRatios::HV => { + // sends two rows, width can be expanded by up to 15 more bytes + ((actual_width + 15) / 16) * 16 + } + SampleRatios::Generic(h, _) => { + ((actual_width + ((h * 8).saturating_sub(1))) / (h * 8)) * (h * 8) + } + } +} + +// https://www.loc.gov/preservation/digital/formats/fdd/fdd000063.shtml +// "Avery Lee, writing in the rec.video.desktop newsgroup in 2001, commented that "MJPEG, or at +// least the MJPEG in AVIs having the MJPG fourcc, is restricted JPEG with a fixed -- and +// *omitted* -- Huffman table. The JPEG must be YCbCr colorspace, it must be 4:2:2, and it must +// use basic Huffman encoding, not arithmetic or progressive.... You can indeed extract the +// MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT +// segment to them, or else the decoder won't have any idea how to decompress the data. +// The exact table necessary is given in the OpenDML spec."" +pub fn fill_default_mjpeg_tables( + is_progressive: bool, dc_huffman_tables: &mut [Option], + ac_huffman_tables: &mut [Option] +) { + // Section K.3.3 + trace!("Filling with default mjpeg tables"); + + if dc_huffman_tables[0].is_none() { + // Table K.3 + dc_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if dc_huffman_tables[1].is_none() { + // Table K.4 + dc_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[0].is_none() { + // Table K.5 + ac_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, + 0x00, 0x00, 0x01, 0x7D + ], + &[ + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, + 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, + 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[1].is_none() { + // Table K.6 + ac_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, + 0x00, 0x01, 0x02, 0x77 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, + 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, + 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, + 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +#[cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +pub use crate::unsafe_utils_avx2::*; +#[cfg(all(feature = "neon", target_arch = "aarch64"))] +pub use crate::unsafe_utils_neon::*; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_avx2.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_avx2.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_avx2.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_avx2.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub}; + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: __m256i +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, tmp) + }; + } + } +} + +impl Sub for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_sub_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_add_epi32(self.mm256, rhs.mm256); + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_add_epi32(self.mm256, tmp); + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + unsafe { + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, rhs.mm256) + } + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, tmp) + } + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs.mm256); + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_mullo_epi32(self.mm256, tmp); + } + } +} + +impl MulAssign<__m256i> for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: __m256i) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs); + } + } +} + +type Reg = YmmRegister; + +/// Transpose an array of 8 by 8 i32's using avx intrinsics +/// +/// This was translated from [here](https://newbedev.com/transpose-an-8x8-float-using-avx-avx2) +#[allow(unused_parens, clippy::too_many_arguments)] +#[target_feature(enable = "avx2")] +#[inline] +pub unsafe fn transpose( + v0: &mut Reg, v1: &mut Reg, v2: &mut Reg, v3: &mut Reg, v4: &mut Reg, v5: &mut Reg, + v6: &mut Reg, v7: &mut Reg +) { + macro_rules! merge_epi32 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi32(va, vb); + + $v3 = _mm256_unpackhi_epi32(va, vb); + }; + } + + macro_rules! merge_epi64 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi64(va, vb); + + $v3 = _mm256_unpackhi_epi64(va, vb); + }; + } + + macro_rules! merge_si128 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + $v2 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 2, 0, 0)); + + $v3 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 3, 0, 1)); + }; + } + + let (w0, w1, w2, w3, w4, w5, w6, w7); + + merge_epi32!((v0.mm256), (v1.mm256), w0, w1); + + merge_epi32!((v2.mm256), (v3.mm256), w2, w3); + + merge_epi32!((v4.mm256), (v5.mm256), w4, w5); + + merge_epi32!((v6.mm256), (v7.mm256), w6, w7); + + let (x0, x1, x2, x3, x4, x5, x6, x7); + + merge_epi64!(w0, w2, x0, x1); + + merge_epi64!(w1, w3, x2, x3); + + merge_epi64!(w4, w6, x4, x5); + + merge_epi64!(w5, w7, x6, x7); + + merge_si128!(x0, x4, (v0.mm256), (v1.mm256)); + + merge_si128!(x1, x5, (v2.mm256), (v3.mm256)); + + merge_si128!(x2, x6, (v4.mm256), (v5.mm256)); + + merge_si128!(x3, x7, (v6.mm256), (v7.mm256)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_neon.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_neon.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_neon.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/unsafe_utils_neon.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(all(feature = "neon", target_arch = "aarch64"))] +// TODO can this be extended to armv7 + +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +use core::arch::aarch64::*; +use core::ops::{Add, AddAssign, BitOr, BitOrAssign, Mul, MulAssign, Sub}; + +pub type VecType = int32x4x2_t; + +pub unsafe fn loadu(src: *const i32) -> VecType { + vld1q_s32_x2(src as *const _) +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: VecType +} + +impl YmmRegister { + #[inline] + pub unsafe fn load(src: *const i32) -> Self { + loadu(src).into() + } + + #[inline] + pub fn map2(self, other: Self, f: impl Fn(int32x4_t, int32x4_t) -> int32x4_t) -> Self { + let m0 = f(self.mm256.0, other.mm256.0); + let m1 = f(self.mm256.1, other.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + + #[inline] + pub fn all_zero(self) -> bool { + unsafe { + let both = vorrq_s32(self.mm256.0, self.mm256.1); + let both_unsigned = vreinterpretq_u32_s32(both); + 0 == vmaxvq_u32(both_unsigned) + } + } + + #[inline] + pub fn const_shl(self) -> Self { + // Ensure that we logically shift left + unsafe { + let m0 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.0))); + let m1 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.1))); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + } + + #[inline] + pub fn const_shra(self) -> Self { + unsafe { + let i0 = vshrq_n_s32::(self.mm256.0); + let i1 = vshrq_n_s32::(self.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(i0, i1) + } + } + } +} + +impl Add for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vaddq_s32(a, b)) } + } +} + +impl Sub for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vsubq_s32(a, b)) } + } +} + +impl AddAssign for YmmRegister +where + T: Into +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self + rhs; + } +} + +impl Mul for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vmulq_s32(a, b)) } + } +} + +impl MulAssign for YmmRegister +where + T: Into +{ + #[inline] + fn mul_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self * rhs; + } +} + +impl BitOr for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn bitor(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vorrq_s32(a, b)) } + } +} + +impl BitOrAssign for YmmRegister +where + T: Into +{ + #[inline] + fn bitor_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self | rhs; + } +} + +impl From for YmmRegister { + #[inline] + fn from(val: i32) -> Self { + unsafe { + let dup = vdupq_n_s32(val); + + YmmRegister { + mm256: int32x4x2_t(dup, dup) + } + } + } +} + +impl From for YmmRegister { + #[inline] + fn from(mm256: VecType) -> Self { + YmmRegister { mm256 } + } +} + +#[allow(clippy::too_many_arguments)] +#[inline] +unsafe fn transpose4( + v0: &mut int32x4_t, v1: &mut int32x4_t, v2: &mut int32x4_t, v3: &mut int32x4_t +) { + let w0 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + let w1 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + + *v0 = w0.0; + *v1 = w0.1; + *v2 = w1.0; + *v3 = w1.1; +} + +/// Transpose an array of 8 by 8 i32 +/// Arm has dedicated interleave/transpose instructions +/// we: +/// 1. Transpose the upper left and lower right quadrants +/// 2. Swap and transpose the upper right and lower left quadrants +#[allow(clippy::too_many_arguments)] +#[inline] +pub unsafe fn transpose( + v0: &mut YmmRegister, v1: &mut YmmRegister, v2: &mut YmmRegister, v3: &mut YmmRegister, + v4: &mut YmmRegister, v5: &mut YmmRegister, v6: &mut YmmRegister, v7: &mut YmmRegister +) { + use core::mem::swap; + + let ul0 = &mut v0.mm256.0; + let ul1 = &mut v1.mm256.0; + let ul2 = &mut v2.mm256.0; + let ul3 = &mut v3.mm256.0; + + let ur0 = &mut v0.mm256.1; + let ur1 = &mut v1.mm256.1; + let ur2 = &mut v2.mm256.1; + let ur3 = &mut v3.mm256.1; + + let ll0 = &mut v4.mm256.0; + let ll1 = &mut v5.mm256.0; + let ll2 = &mut v6.mm256.0; + let ll3 = &mut v7.mm256.0; + + let lr0 = &mut v4.mm256.1; + let lr1 = &mut v5.mm256.1; + let lr2 = &mut v6.mm256.1; + let lr3 = &mut v7.mm256.1; + + swap(ur0, ll0); + swap(ur1, ll1); + swap(ur2, ll2); + swap(ur3, ll3); + + transpose4(ul0, ul1, ul2, ul3); + + transpose4(ur0, ur1, ur2, ur3); + + transpose4(ll0, ll1, ll2, ll3); + + transpose4(lr0, lr1, lr2, lr3); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_transpose() { + fn get_val(i: usize, j: usize) -> i32 { + ((i * 8) / (j + 1)) as i32 + } + unsafe { + let mut vals: [i32; 8 * 8] = [0; 8 * 8]; + + for i in 0..8 { + for j in 0..8 { + // some order-dependent value of i and j + let value = get_val(i, j); + vals[i * 8 + j] = value; + } + } + + let mut regs: [YmmRegister; 8] = core::mem::transmute(vals); + let mut reg0 = regs[0]; + let mut reg1 = regs[1]; + let mut reg2 = regs[2]; + let mut reg3 = regs[3]; + let mut reg4 = regs[4]; + let mut reg5 = regs[5]; + let mut reg6 = regs[6]; + let mut reg7 = regs[7]; + + transpose( + &mut reg0, &mut reg1, &mut reg2, &mut reg3, &mut reg4, &mut reg5, &mut reg6, + &mut reg7 + ); + + regs[0] = reg0; + regs[1] = reg1; + regs[2] = reg2; + regs[3] = reg3; + regs[4] = reg4; + regs[5] = reg5; + regs[6] = reg6; + regs[7] = reg7; + + let vals_from_reg: [i32; 8 * 8] = core::mem::transmute(regs); + + for i in 0..8 { + for j in 0..i { + let orig = vals[i * 8 + j]; + vals[i * 8 + j] = vals[j * 8 + i]; + vals[j * 8 + i] = orig; + } + } + + for i in 0..8 { + for j in 0..8 { + assert_eq!(vals[j * 8 + i], get_val(i, j)); + assert_eq!(vals_from_reg[j * 8 + i], get_val(i, j)); + } + } + + assert_eq!(vals, vals_from_reg); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler/scalar.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler/scalar.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler/scalar.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler/scalar.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +pub fn upsample_horizontal( + input: &[i16], _ref: &[i16], _in_near: &[i16], _scratch: &mut [i16], output: &mut [i16] +) { + assert_eq!( + input.len() * 2, + output.len(), + "Input length is not half the size of the output length" + ); + assert!( + output.len() > 4 && input.len() > 2, + "Too Short of a vector, cannot upsample" + ); + + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + // This code is written for speed and not readability + // + // The readable code is + // + // for i in 1..input.len() - 1{ + // let sample = 3 * input[i] + 2; + // out[i * 2] = (sample + input[i - 1]) >> 2; + // out[i * 2 + 1] = (sample + input[i + 1]) >> 2; + // } + // + // The output of a pixel is determined by it's surrounding neighbours but we attach more weight to it's nearest + // neighbour (input[i]) than to the next nearest neighbour. + + for (output_window, input_window) in output[2..].chunks_exact_mut(2).zip(input.windows(3)) { + let sample = 3 * input_window[1] + 2; + + output_window[0] = (sample + input_window[0]) >> 2; + output_window[1] = (sample + input_window[2]) >> 2; + } + // Get lengths + let out_len = output.len() - 2; + let input_len = input.len() - 2; + + // slice the output vector + let f_out = &mut output[out_len..]; + let i_last = &input[input_len..]; + + // write out manually.. + f_out[0] = (3 * i_last[0] + i_last[1] + 2) >> 2; + f_out[1] = i_last[1]; +} +pub fn upsample_vertical( + input: &[i16], in_near: &[i16], in_far: &[i16], _scratch_space: &mut [i16], output: &mut [i16] +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let middle = output.len() / 2; + + let (out_top, out_bottom) = output.split_at_mut(middle); + + // for the first row, closest row is in_near + for ((near, far), x) in input.iter().zip(in_near.iter()).zip(out_top) { + *x = (((3 * near) + 2) + far) >> 2; + } + // for the second row, the closest row to input is in_far + for ((near, far), x) in input.iter().zip(in_far.iter()).zip(out_bottom) { + *x = (((3 * near) + 2) + far) >> 2; + } +} + +pub fn upsample_hv( + input: &[i16], in_near: &[i16], in_far: &[i16], scratch_space: &mut [i16], output: &mut [i16] +) { + assert_eq!(input.len() * 4, output.len()); + + let mut t = [0]; + upsample_vertical(input, in_near, in_far, &mut t, scratch_space); + // horizontal upsampling must be done separate for every line + // Otherwise it introduces artifacts that may cause the edge colors + // to appear on the other line. + + // Since this is called for two scanlines/widths currently + // splitting the inputs and outputs into half ensures we only handle + // one scanline per iteration + let scratch_half = scratch_space.len() / 2; + + let output_half = output.len() / 2; + + upsample_horizontal( + &scratch_space[..scratch_half], + &[], + &[], + &mut t, + &mut output[..output_half] + ); + + upsample_horizontal( + &scratch_space[scratch_half..], + &[], + &[], + &mut t, + &mut output[output_half..] + ); +} + +pub fn upsample_generic( + input: &[i16], _in_near: &[i16], _in_far: &[i16], _scratch_space: &mut [i16], + output: &mut [i16] +) { + // use nearest sample + let difference = output.len() / input.len(); + if difference > 0 { + // nearest neighbour + for (input, chunk_output) in input.iter().zip(output.chunks_exact_mut(difference)) { + chunk_output.iter_mut().for_each(|x| *x = *input); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/upsampler.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Up-sampling routines +//! +//! The main upsampling method is a bi-linear interpolation or a "triangle +//! filter " or libjpeg turbo `fancy_upsampling` which is a good compromise +//! between speed and visual quality +//! +//! # The filter +//! Each output pixel is made from `(3*A+B)/4` where A is the original +//! pixel closer to the output and B is the one further. +//! +//! ```text +//!+---+---+ +//! | A | B | +//! +---+---+ +//! +-+-+-+-+ +//! | |P| | | +//! +-+-+-+-+ +//! ``` +//! +//! # Horizontal Bi-linear filter +//! ```text +//! |---+-----------+---+ +//! | | | | +//! | A | |p1 | p2| | B | +//! | | | | +//! |---+-----------+---+ +//! +//! ``` +//! For a horizontal bi-linear it's trivial to implement, +//! +//! `A` becomes the input closest to the output. +//! +//! `B` varies depending on output. +//! - For odd positions, input is the `next` pixel after A +//! - For even positions, input is the `previous` value before A. +//! +//! We iterate in a classic 1-D sliding window with a window of 3. +//! For our sliding window approach, `A` is the 1st and `B` is either the 0th term or 2nd term +//! depending on position we are writing.(see scalar code). +//! +//! For vector code see module sse for explanation. +//! +//! # Vertical bi-linear. +//! Vertical up-sampling is a bit trickier. +//! +//! ```text +//! +----+----+ +//! | A1 | A2 | +//! +----+----+ +//! +----+----+ +//! | p1 | p2 | +//! +----+-+--+ +//! +----+-+--+ +//! | p3 | p4 | +//! +----+-+--+ +//! +----+----+ +//! | B1 | B2 | +//! +----+----+ +//! ``` +//! +//! For `p1` +//! - `A1` is given a weight of `3` and `B1` is given a weight of 1. +//! +//! For `p3` +//! - `B1` is given a weight of `3` and `A1` is given a weight of 1 +//! +//! # Horizontal vertical downsampling/chroma quartering. +//! +//! Carry out a vertical filter in the first pass, then a horizontal filter in the second pass. +use crate::components::UpSampler; + +mod scalar; + +// choose best possible implementation for this platform +pub fn choose_horizontal_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_horizontal; +} + +pub fn choose_hv_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_hv; +} + +pub fn choose_v_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_vertical; +} + +/// Upsample nothing + +pub fn upsample_no_op( + _input: &[i16], _in_ref: &[i16], _in_near: &[i16], _scratch_space: &mut [i16], + _output: &mut [i16] +) { +} + +pub fn generic_sampler() -> UpSampler { + scalar::upsample_generic +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/worker.rs clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/worker.rs --- clamav-1.4.3+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/worker.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/zune-jpeg-0.4.21/src/worker.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::format; +use core::convert::TryInto; + +use zune_core::colorspace::ColorSpace; + +use crate::color_convert::ycbcr_to_grayscale; +use crate::components::{Components, SampleRatios}; +use crate::decoder::{ColorConvert16Ptr, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; + +/// fast 0..255 * 0..255 => 0..255 rounded multiplication +/// +/// Borrowed from stb +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +#[inline] +fn blinn_8x8(in_val: u8, y: u8) -> u8 { + let t = i32::from(in_val) * i32::from(y) + 128; + return ((t + (t >> 8)) >> 8) as u8; +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +pub(crate) fn color_convert( + unprocessed: &[&[i16]; MAX_COMPONENTS], color_convert_16: ColorConvert16Ptr, + input_colorspace: ColorSpace, output_colorspace: ColorSpace, output: &mut [u8], width: usize, + padded_width: usize +) -> Result<(), DecodeErrors> // so many parameters.. +{ + // maximum sampling factors are in Y-channel, no need to pass them. + + if input_colorspace.num_components() == 3 && input_colorspace == output_colorspace { + // sort things like RGB to RGB conversion + copy_removing_padding(unprocessed, width, padded_width, output); + return Ok(()); + } + if input_colorspace.num_components() == 4 && input_colorspace == output_colorspace { + copy_removing_padding_4x(unprocessed, width, padded_width, output); + return Ok(()); + } + // color convert + match (input_colorspace, output_colorspace) { + (ColorSpace::YCbCr | ColorSpace::Luma, ColorSpace::Luma) => { + ycbcr_to_grayscale(unprocessed[0], width, padded_width, output); + } + ( + ColorSpace::YCbCr, + ColorSpace::RGB | ColorSpace::RGBA | ColorSpace::BGR | ColorSpace::BGRA + ) => { + color_convert_ycbcr( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::YCCK, ColorSpace::RGB) => { + color_convert_ycck_to_rgb::<3>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + + (ColorSpace::YCCK, ColorSpace::RGBA) => { + color_convert_ycck_to_rgb::<4>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::CMYK, ColorSpace::RGB) => { + color_convert_cymk_to_rgb::<3>(unprocessed, width, padded_width, output); + } + (ColorSpace::CMYK, ColorSpace::RGBA) => { + color_convert_cymk_to_rgb::<4>(unprocessed, width, padded_width, output); + } + // For the other components we do nothing(currently) + _ => { + let msg = format!( + "Unimplemented colorspace mapping from {input_colorspace:?} to {output_colorspace:?}"); + + return Err(DecodeErrors::Format(msg)); + } + } + Ok(()) +} + +/// Copy a block to output removing padding bytes from input +/// if necessary +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn copy_removing_padding( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for (((pix_w, c_w), m_w), y_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + { + for (((pix, c), y), m) in pix_w.chunks_exact_mut(3).zip(c_w).zip(m_w).zip(y_w) { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + } + } +} +fn copy_removing_padding_4x( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * 4) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), y), m), k) in pix_w + .chunks_exact_mut(4) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + pix[3] = *k as u8; + } + } +} +/// Convert YCCK image to rgb +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn color_convert_ycck_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + color_convert_ycbcr( + mcu_block, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + for (pix_w, m_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for (pix, m) in pix_w.chunks_exact_mut(NUM_COMPONENTS).zip(m_w) { + let m = (*m) as u8; + pix[0] = blinn_8x8(255 - pix[0], m); + pix[1] = blinn_8x8(255 - pix[1], m); + pix[2] = blinn_8x8(255 - pix[2], m); + } + } +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn color_convert_cymk_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * NUM_COMPONENTS) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), m), y), k) in pix_w + .chunks_exact_mut(3) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + let c = *c as u8; + let m = *m as u8; + let y = *y as u8; + let k = *k as u8; + + pix[0] = blinn_8x8(c, k); + pix[1] = blinn_8x8(m, k); + pix[2] = blinn_8x8(y, k); + } + } +} + +/// Do color-conversion for interleaved MCU +#[allow( + clippy::similar_names, + clippy::too_many_arguments, + clippy::needless_pass_by_value, + clippy::unwrap_used +)] +fn color_convert_ycbcr( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + let num_components = output_colorspace.num_components(); + + let stride = width * num_components; + // Allocate temporary buffer for small widths less than 16. + let mut temp = [0; 64]; + // We need to chunk per width to ensure we can discard extra values at the end of the width. + // Since the encoder may pad bits to ensure the width is a multiple of 8. + for (((y_width, cb_width), cr_width), out) in mcu_block[0] + .chunks_exact(padded_width) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(output.chunks_exact_mut(stride)) + { + if width < 16 { + // allocate temporary buffers for the values received from idct + let mut y_out = [0; 16]; + let mut cb_out = [0; 16]; + let mut cr_out = [0; 16]; + // copy those small widths to that buffer + y_out[0..y_width.len()].copy_from_slice(y_width); + cb_out[0..cb_width.len()].copy_from_slice(cb_width); + cr_out[0..cr_width.len()].copy_from_slice(cr_width); + // we handle widths less than 16 a bit differently, allocating a temporary + // buffer and writing to that and then flushing to the out buffer + // because of the optimizations applied below, + (color_convert_16)(&y_out, &cb_out, &cr_out, &mut temp, &mut 0); + // copy to stride + out[0..width * num_components].copy_from_slice(&temp[0..width * num_components]); + // next + continue; + } + + // Chunk in outputs of 16 to pass to color_convert as an array of 16 i16's. + for (((y, cb), cr), out_c) in y_width + .chunks_exact(16) + .zip(cb_width.chunks_exact(16)) + .zip(cr_width.chunks_exact(16)) + .zip(out.chunks_exact_mut(16 * num_components)) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + out_c, + &mut 0 + ); + } + //we have more pixels in the end that can't be handled by the main loop. + //move pointer back a little bit to get last 16 bytes, + //color convert, and overwrite + //This means some values will be color converted twice. + for ((y, cb), cr) in y_width[width - 16..] + .chunks_exact(16) + .zip(cb_width[width - 16..].chunks_exact(16)) + .zip(cr_width[width - 16..].chunks_exact(16)) + .take(1) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + &mut temp, + &mut 0 + ); + } + + let rem = out[(width - 16) * num_components..] + .chunks_exact_mut(16 * num_components) + .next() + .unwrap(); + + rem.copy_from_slice(&temp[0..rem.len()]); + } +} +pub(crate) fn upsample( + component: &mut Components, mcu_height: usize, i: usize, upsampler_scratch_space: &mut [i16], + has_vertical_sample: bool +) { + match component.sample_ratio { + SampleRatios::V | SampleRatios::HV => { + /* + When upsampling vertically sampled images, we have a certain problem + which is that we do not have all MCU's decoded, this usually sucks at boundaries + e.g we can't upsample the last mcu row, since the row_down currently doesn't exist + + To solve this we need to do two things + + 1. Carry over coefficients when we lack enough data to upsample + 2. Upsample when we have enough data + + To achieve (1), we store a previous row, and the current row in components themselves + which will later be used to make (2) + + To achieve (2), we take the stored previous row(second last MCU row), + current row(last mcu row) and row down(first row of newly decoded MCU) + + and upsample that and store it in first_row_upsample_dest, this contains + up-sampled coefficients for the last for the previous decoded mcu row. + + The caller is then expected to process first_row_upsample_dest before processing data + in component.upsample_dest which stores the up-sampled components excluding the last row + */ + + let mut dest_start = 0; + let stride_bytes_written = component.width_stride * component.sample_ratio.sample(); + + if i > 0 { + // Handle the last MCU of the previous row + // This wasn't up-sampled as we didn't have the row_down + // so we do it now + + let stride = component.width_stride; + + let dest = &mut component.first_row_upsample_dest[0..stride_bytes_written]; + + // get current row + let row = &component.row[..]; + let row_up = &component.row_up[..]; + let row_down = &component.raw_coeff[0..stride]; + (component.up_sampler)(row, row_up, row_down, upsampler_scratch_space, dest); + } + + // we have the Y component width stride. + // this may be higher than the actual width,(2x because vertical sampling) + // + // This will not upsample the last row + + // if false, do not upsample. + // set to false on the last row of an mcu + let mut upsample = true; + + let stride = component.width_stride * component.vertical_sample; + let stop_offset = component.raw_coeff.len() / component.width_stride; + for (pos, curr_row) in component + .raw_coeff + .chunks_exact(component.width_stride) + .enumerate() + { + let mut dest: &mut [i16] = &mut []; + let mut row_up: &[i16] = &[]; + // row below current sample + let mut row_down: &[i16] = &[]; + + // Order of ifs matters + + if i == 0 && pos == 0 { + // first IMAGE row, row_up is the same as current row + // row_down is the row below. + row_up = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i > 0 && pos == 0 { + // first row of a new mcu, previous row was copied so use that + row_up = &component.row[..]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i == mcu_height.saturating_sub(1) && pos == stop_offset - 1 { + // last IMAGE row, adjust pointer to use previous row and current row + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + } else if pos > 0 && pos < stop_offset - 1 { + // other rows, get row up and row down relative to our current row + // ignore last row of each mcu + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if pos == stop_offset - 1 { + // last MCU in a row + // + // we need a row at the next MCU but we haven't decoded that MCU yet + // so we should save this and when we have the next MCU, + // do the upsampling + + // store the current row and previous row in a buffer + let prev_row = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + + component.row_up.copy_from_slice(prev_row); + component.row.copy_from_slice(curr_row); + upsample = false; + } else { + unreachable!("Uh oh!"); + } + if upsample { + dest = + &mut component.upsample_dest[dest_start..dest_start + stride_bytes_written]; + dest_start += stride_bytes_written; + } + + if upsample { + // upsample + (component.up_sampler)( + curr_row, + row_up, + row_down, + upsampler_scratch_space, + dest + ); + } + } + } + SampleRatios::H => { + assert_eq!(component.raw_coeff.len() * 2, component.upsample_dest.len()); + + let raw_coeff = &component.raw_coeff; + let dest_coeff = &mut component.upsample_dest; + + if has_vertical_sample { + /* + There have been images that have the following configurations. + + Component ID:Y HS:2 VS:2 QT:0 + Component ID:Cb HS:1 VS:1 QT:1 + Component ID:Cr HS:1 VS:2 QT:1 + + This brings out a nasty case of misaligned sampling factors. Cr will need to save a row because + of the way we process boundaries but Cb won't since Cr is horizontally sampled while Cb is + HV sampled with respect to the image sampling factors. + + So during decoding of one MCU, we could only do 7 and not 8 rows, but the SampleRatio::H never had to + save a single line, since it doesn't suffer from boundary issues. + + Now this takes care of that, saving the last MCU row in case it will be needed. + We save the previous row before up-sampling this row because the boundary issue is in + the last MCU row of the previous MCU. + + PS(cae): I can't add the image to the repo as it is nsfw, but can send if required + */ + let length = component.first_row_upsample_dest.len(); + component + .first_row_upsample_dest + .copy_from_slice(&dest_coeff.rchunks_exact(length).next().unwrap()); + } + // up-sample each row + for (single_row, output_stride) in raw_coeff + .chunks_exact(component.width_stride) + .zip(dest_coeff.chunks_exact_mut(component.width_stride * 2)) + { + // upsample using the fn pointer, should only be H, so no need for + // row up and row down + (component.up_sampler)(single_row, &[], &[], &mut [], output_stride); + } + } + SampleRatios::Generic(h, v) => { + let raw_coeff = &component.raw_coeff; + let dest_coeff = &mut component.upsample_dest; + + + for (single_row, output_stride) in raw_coeff + .chunks_exact(component.width_stride) + .zip(dest_coeff.chunks_exact_mut(component.width_stride * h*v)) + { + // upsample using the fn pointer, should only be H, so no need for + // row up and row down + (component.up_sampler)(single_row, &[], &[], &mut [], output_stride); + } + } + SampleRatios::None => {} + }; +} diff -Nru clamav-1.4.3+dfsg/CMakeLists.txt clamav-1.4.6+dfsg/CMakeLists.txt --- clamav-1.4.3+dfsg/CMakeLists.txt 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/CMakeLists.txt 2026-08-06 21:12:04.000000000 +0000 @@ -1,11 +1,8 @@ # Copyright (C) 2019-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved. -if(WIN32) - cmake_minimum_required( VERSION 3.16 ) # For file(GET_RUNTIME_DEPENDENCIES) -else() - cmake_minimum_required( VERSION 3.14 ) -endif() +# CMake 3.17 preserves link directories from private static dependencies. +cmake_minimum_required( VERSION 3.17 ) set(CMAKE_C_STANDARD 90) set(CMAKE_C_STANDARD_REQUIRED ON) @@ -22,7 +19,7 @@ set(VERSION_SUFFIX "") project( ClamAV - VERSION "1.4.3" + VERSION "1.4.6" DESCRIPTION "ClamAV open source email, web, and end-point anti-virus toolkit." ) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) @@ -812,6 +809,7 @@ set(HAVE_MKSTEMP 1) set(HAVE_POLL 1) else() + check_symbol_exists(funlinkat "unistd.h" HAVE_FUNLINKAT) check_symbol_exists(fseeko "stdio.h" HAVE_FSEEKO) check_symbol_exists(getaddrinfo "netdb.h" HAVE_GETADDRINFO) check_symbol_exists(getpagesize "unistd.h" HAVE_GETPAGESIZE) diff -Nru clamav-1.4.3+dfsg/Cargo.lock clamav-1.4.6+dfsg/Cargo.lock --- clamav-1.4.3+dfsg/Cargo.lock 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/Cargo.lock 2026-08-06 21:12:04.000000000 +0000 @@ -1,18 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" @@ -24,6 +18,24 @@ ] [[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -39,12 +51,93 @@ ] [[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.17", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +dependencies = [ + "arrayvec", +] + +[[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,7 +162,7 @@ "regex", "rustc-hash", "shlex", - "syn 2.0.60", + "syn 2.0.113", "which", ] @@ -92,6 +185,15 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] +name = "bitstream-io" +version = "4.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +dependencies = [ + "core2", +] + +[[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -101,6 +203,12 @@ ] [[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + +[[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -119,10 +227,16 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] name = "bytes" -version = "1.9.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bzip2-rs" @@ -157,6 +271,11 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] [[package]] name = "cexpr" @@ -164,7 +283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -199,7 +318,6 @@ "hex", "hex-literal", "image", - "inflate", "libc", "log", "num-traits", @@ -208,7 +326,7 @@ "sha1", "sha2", "tempfile", - "thiserror", + "thiserror 1.0.59", "transpose", "unicode-segmentation", ] @@ -237,6 +355,15 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] name = "cpufeatures" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -266,9 +393,9 @@ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] @@ -343,6 +470,26 @@ ] [[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -354,12 +501,11 @@ [[package]] name = "exr" -version = "1.72.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", - "flume", "half", "lebe", "miniz_oxide", @@ -375,6 +521,26 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] name = "fdeflate" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -385,24 +551,15 @@ [[package]] name = "flate2" -version = "1.0.30" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] - -[[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -413,10 +570,22 @@ ] [[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] name = "gif" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" dependencies = [ "color_quant", "weezl", @@ -496,23 +665,45 @@ [[package]] name = "image" -version = "0.24.9" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", "color_quant", "exr", "gif", - "jpeg-decoder", + "image-webp", + "moxcms", "num-traits", "png", "qoi", + "ravif", + "rayon", + "rgb", "tiff", + "zune-core 0.5.0", + "zune-jpeg 0.5.8", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", ] [[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + +[[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -523,12 +714,14 @@ ] [[package]] -name = "inflate" -version = "0.4.5" +name = "interpolate_name" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ - "adler32", + "proc-macro2", + "quote", + "syn 2.0.113", ] [[package]] @@ -541,18 +734,27 @@ ] [[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "jpeg-decoder" -version = "0.3.1" +name = "jobserver" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "rayon", + "libc", ] [[package]] @@ -589,6 +791,16 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] +name = "libfuzzer-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] name = "libloading" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -605,20 +817,29 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] -name = "lock_api" -version = "0.4.12" +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "autocfg", - "scopeguard", + "imgref", ] [[package]] -name = "log" -version = "0.4.21" +name = "maybe-rayon" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] [[package]] name = "memchr" @@ -634,15 +855,31 @@ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] +name = "moxcms" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -653,6 +890,31 @@ ] [[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] name = "num-complex" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -662,6 +924,17 @@ ] [[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -671,6 +944,17 @@ ] [[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -693,10 +977,10 @@ "bytes", "encoding_rs", "enum-primitive-derive", - "itertools", + "itertools 0.10.5", "num-traits", "paste", - "thiserror", + "thiserror 1.0.59", "uuid", "widestring", ] @@ -708,6 +992,12 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -715,11 +1005,11 @@ [[package]] name = "png" -version = "0.17.13" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "crc32fast", "fdeflate", "flate2", @@ -727,13 +1017,22 @@ ] [[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] name = "prettyplease" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.113", ] [[package]] @@ -747,14 +1046,42 @@ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] [[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn 2.0.113", +] + +[[package]] +name = "pxfm" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" +dependencies = [ + "num-traits", +] + +[[package]] name = "qoi" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -764,6 +1091,12 @@ ] [[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -773,6 +1106,91 @@ ] [[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.14.0", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "thiserror 2.0.17", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -822,6 +1240,12 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" + +[[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -871,12 +1295,6 @@ checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] name = "serde" version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -893,7 +1311,7 @@ dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.113", ] [[package]] @@ -942,19 +1360,25 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] -name = "spin" -version = "0.9.8" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strength_reduce" @@ -975,9 +1399,9 @@ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -1002,7 +1426,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.59", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", ] [[package]] @@ -1013,18 +1446,32 @@ dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.113", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", ] [[package]] name = "tiff" -version = "0.9.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" dependencies = [ + "fax", "flate2", - "jpeg-decoder", + "half", + "quick-error", "weezl", + "zune-jpeg 0.4.21", ] [[package]] @@ -1077,12 +1524,32 @@ checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] name = "wasm-bindgen" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1103,7 +1570,7 @@ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.113", "wasm-bindgen-shared", ] @@ -1125,7 +1592,7 @@ dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.113", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1138,9 +1605,9 @@ [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "which" @@ -1243,6 +1710,50 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" + +[[package]] name = "zune-inflate" version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1250,3 +1761,21 @@ dependencies = [ "simd-adler32", ] + +[[package]] +name = "zune-jpeg" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +dependencies = [ + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35aee689668bf9bd6f6f3a6c60bb29ba1244b3b43adfd50edd554a371da37d5" +dependencies = [ + "zune-core 0.5.0", +] diff -Nru clamav-1.4.3+dfsg/INSTALL.md clamav-1.4.6+dfsg/INSTALL.md --- clamav-1.4.3+dfsg/INSTALL.md 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/INSTALL.md 2026-08-06 21:12:04.000000000 +0000 @@ -76,7 +76,7 @@ The Windows Visual Studio and Autotools build systems have been removed. You will need: -- CMake (3.14+ for Unix/Linux; 3.16+ for Windows) +- CMake 3.17 or newer - A C compiler toolchain such as `gcc`, `clang`, or Microsoft Visual Studio. - The Rust compiler toolchain. diff -Nru clamav-1.4.3+dfsg/Jenkinsfile clamav-1.4.6+dfsg/Jenkinsfile --- clamav-1.4.3+dfsg/Jenkinsfile 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/Jenkinsfile 2026-08-06 21:12:04.000000000 +0000 @@ -10,7 +10,7 @@ parameters( [ string(name: 'VERSION', - defaultValue: '1.4.3', + defaultValue: '1.4.6', description: 'ClamAV version string'), string(name: 'FRAMEWORK_BRANCH', defaultValue: '1.4', @@ -46,10 +46,10 @@ defaultValue: 'fuzz-regression-1.4', description: 'test-pipelines branch for fuzz regression tests'), string(name: 'FUZZ_CORPUS_BRANCH', - defaultValue: 'master', + defaultValue: '1.4', description: 'private-fuzz-corpus branch'), string(name: 'SHARED_LIB_BRANCH', - defaultValue: 'master', + defaultValue: 'main', description: 'tests-jenkins-shared-libraries branch') ] ) diff -Nru clamav-1.4.3+dfsg/NEWS.md clamav-1.4.6+dfsg/NEWS.md --- clamav-1.4.3+dfsg/NEWS.md 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/NEWS.md 2026-08-06 21:12:04.000000000 +0000 @@ -3,6 +3,203 @@ Note: This file refers to the official packages. Things described here may differ slightly from third-party binary packages. +## 1.4.6 + +ClamAV 1.4.6 is a patch release with the following fixes: + +- [CVE-2026-20345](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20345): + Fixed an indexing error while converting GPT partition names that could + read or write beyond a stack-allocated partition entry. + + This issue affects ClamAV 0.98.2 through 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to Atuin - Automated Vulnerability Discovery Engine, Tianchu Chen + of Tencent Xuanwu Lab for identifying this issue. + +- [CVE-2026-20339](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20339): + Fixed an integer overflow in the PESpin unpacker that could allocate an + undersized buffer and then write beyond it while rebuilding a PE file. + + This issue affects ClamAV 0.90 through 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to Feng Xue and, independently, Yazdan Soltani for identifying + this issue. + +- [CVE-2026-20346](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20346): + Fixed an integer underflow in the PDF parser that could cause a crash while + reading a malformed hex string. + + This issue affects ClamAV 1.4.5 and earlier, and ClamAV 1.5.0 through + 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to Tristan (@TristanInSec) for identifying this issue. + +- [CVE-2026-20347](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20347): + Fixed undefined behavior and integer overflow in the Mach-O parser that + could cause a crash while scanning a malformed Mach-O file. + + This issue affects ClamAV 1.4.5 and earlier, and ClamAV 1.5.0 through + 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to Tristan (@TristanInSec) for identifying this issue. + +- [CVE-2026-20348](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20348): + Fixed XAR parser size handling that could request an excessive allocation + or exceed scan limits while decompressing a malformed table of contents. + + This issue affects ClamAV 0.98.1 through 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to leduckhuong for identifying this issue. + +- [CVE-2025-8088](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-8088): + Adopted the upstream UnRAR project fix in ClamAV's bundled UnRAR library. + The fix rejects path separators in NTFS alternate data stream names to + prevent extraction outside ClamAV's temporary scan directory on Windows. + + This issue affects ClamAV 0.101.0 through 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + + Thank you to Yazdan Soltani for identifying that this issue affects ClamAV. + +- Fixed thread-safety issues in the `clamd` STATS command that could disclose + process memory or crash the daemon while scans and STATS requests run + concurrently. Also fixed partial socket-write handling used for large STATS + responses. + + This issue affects ClamAV 0.95 through 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + +- FreeBSD: Restored support for safe quarantine move and remove actions while + preserving protection against source-path replacement races. + + This issue affects ClamAV 1.4.5 and 1.5.3. + The fix is included in 1.4.6 and 1.5.4. + +- Upgraded the Rust `crossbeam-epoch` dependency to resolve the + RUSTSEC-2026-0204 advisory. + +## 1.4.5 + +ClamAV 1.4.5 is a patch release with the following fixes: + +- [CVE-2026-20217](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20217): + Fixed a bug in the PESpin unpacker cleanup path that could free pointers + into the scanned file buffer and crash the scanner. + + This issue affects ClamAV 1.5.2, 1.4.4, and all prior versions as far back + as 2005. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Atuin - Automated Vulnerability Discovery Engine, Tianchu Chen + of Tencent Xuanwu Lab for identifying this issue. + +- [CVE-2026-20213](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20213): + Fixed an integer overflow in PE rebuild size calculations that could be + reached through a malformed Aspack-packed PE file and lead to a heap buffer + overflow write. + + This issue affects ClamAV 1.5.2, 1.4.4, and all prior versions as far back + as 2007. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Trail of Bits, in collaboration with Anthropic, for identifying + this issue. + +- [CVE-2026-20216](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20216): + Fixed an InstallShield archive extraction limit bypass that could write far + more temporary data than intended and exhaust temporary storage. + + This issue affects ClamAV 1.5.2, 1.4.4, and all prior versions as far back + as 2009. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Mizu for identifying this issue. + +- [CVE-2026-20214](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20214): + Fixed an FSG unpacker loop underflow that could write past the section array + while scanning a malformed PE file. + + This issue affects ClamAV 1.5.2, 1.4.4, and all prior versions as far back + as 2004. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Trail of Bits, in collaboration with Anthropic, for identifying + this issue. + +- [CVE-2026-20243](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20243): + Fixed ALZ parser size handling bugs that could cause malformed ALZ archives + to panic, abort the scanner, or skip expected scan-limit handling. + + This issue affects ClamAV 1.5.0 through 1.5.2 and 1.4.0 through 1.4.4. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Yazdan Soltani for identifying this issue. + +- [CVE-2026-20215](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20215): + Fixed a 7z parser substream count overflow that could under-allocate parser + metadata arrays and write past them while reading a malformed archive. + + This issue affects ClamAV 1.5.2, 1.4.4, and all prior versions back to 2009. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Trail of Bits, in collaboration with Anthropic, for identifying + this issue. + +- [CVE-2026-20244](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20244): + Fixed 32-bit DMG parser size checks that could let a short mish stripe table + pass validation and crash 32-bit scanner builds. + + This issue affects 32-bit ClamAV builds from 0.98.1 through 1.5.2, including + 1.4.0 through 1.4.4 and 1.5.0 through 1.5.2. It does not affect 64-bit + builds. + The fix is included in 1.5.3 and 1.4.5. + + Thank you to Stanley John Tobias for identifying this issue. + +- Hardened `clamscan`, `clamdscan`, and `clamonacc` quarantine actions against + time-of-check/time-of-use races that could redirect copied, moved, or removed + files under unsafe quarantine directory configurations. + + Thank you to Hiroki Imai from Ricerca Security, Inc. for identifying this + issue. + +- Raised the minimum required CMake version to 3.17 to fix Linux builds with + libcurl v8.21.0 when linking static library dependencies. + +- ClamOnAcc: Fixed errors when recursively excluded paths are children of an + included path. + + This fix is courtesy of sharkautarch. + +## 1.4.4 + +ClamAV 1.4.4 is a patch release with the following fixes: + +- [CVE-2026-20031](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-20031): + Fixed an error handling bug in the HTML file parser that may crash the program + and cause a denial-of-service (DoS) condition. + + This issue was introduced in version 1.1.0. + The fix is included in 1.5.2 and 1.4.4. + +- Fixed a possible crash when scanning some TIFF files by upgrading the + affected ClamAV dependency, a Rust image library. + + Unfortunately, this change requires a newer Rust compiler for ClamAV. + The minimum Rust version for ClamAV 1.4.3 was 1.70.0. + The minimum Rust version for ClamAV 1.4.4 is now 1.87.0. + +- Upgraded the Rust `bytes` dependency to a newer version to resolve the + RUSTSEC-2026-0007 advisory. + +- Fixed a possible crash caused by invalid pointer alignment on some platforms. + This fix is courtesy of Hsuan-Ming Chen at Synology PSIRT. + ## 1.4.3 ClamAV 1.4.3 is a patch release with the following fixes: diff -Nru clamav-1.4.3+dfsg/clamav-config.h.cmake.in clamav-1.4.6+dfsg/clamav-config.h.cmake.in --- clamav-1.4.3+dfsg/clamav-config.h.cmake.in 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamav-config.h.cmake.in 2026-08-06 21:12:04.000000000 +0000 @@ -98,6 +98,9 @@ /* use "Cache-Control: no-cache" in freshclam */ #cmakedefine FRESHCLAM_NO_CACHE 1 +/* Have funlinkat */ +#cmakedefine HAVE_FUNLINKAT 1 + /* attrib aligned */ #cmakedefine HAVE_ATTRIB_ALIGNED 1 diff -Nru clamav-1.4.3+dfsg/clamd/scanner.c clamav-1.4.6+dfsg/clamd/scanner.c --- clamav-1.4.3+dfsg/clamd/scanner.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/scanner.c 2026-08-06 21:12:04.000000000 +0000 @@ -140,21 +140,11 @@ { struct scan_cb_data *scandata = data->data; const char *virname = NULL; - int ret; + cl_error_t ret = CL_SUCCESS; int type = scandata->type; struct cb_context context; - char *real_filename = NULL; - - if (NULL != filename) { - if (CL_SUCCESS != cli_realpath((const char *)filename, &real_filename)) { - conn_reply_errno(scandata->conn, msg, "File path check failure:"); - logg(LOGG_WARNING, "File path check failure for: %s\n", filename); - logg(LOGG_DEBUG, "Quarantine of the file may fail if file path contains symlinks.\n"); - } else { - free(filename); - filename = real_filename; - } - } + char *scan_filename = NULL; + const char *scan_path; /* detect disconnected socket, * this should NOT detect half-shutdown sockets (SHUT_WR) */ @@ -225,12 +215,35 @@ return CL_SUCCESS; } + scan_path = (NULL != msg) ? msg : filename; + /* + * Resolve the path used for the actual scan open. Keep filename as the + * client-visible name, but do not let a symlinked parent component change + * the object opened after cli_ftw() has performed its checks. + */ + if (NULL != scan_path) { + ret = cli_realpath(scan_path, &scan_filename); + if (CL_SUCCESS != ret) { + conn_reply_errno(scandata->conn, filename, "File path check failure:"); + logg(LOGG_WARNING, "File path check failure for: %s\n", filename); + scandata->errors++; + free(filename); + return (CL_EMEM == ret) ? ret : CL_SUCCESS; + } + scan_path = scan_filename; + } + if (type == TYPE_MULTISCAN) { client_conn_t *client_conn = (client_conn_t *)calloc(1, sizeof(struct client_conn_tag)); if (client_conn) { client_conn->scanfd = -1; client_conn->sd = scandata->odesc; - client_conn->filename = filename; + client_conn->filename = (NULL != scan_filename) ? scan_filename : filename; + if (NULL != scan_filename) { + client_conn->display_filename = filename; + scan_filename = NULL; + } + filename = NULL; client_conn->cmdtype = COMMAND_MULTISCANFILE; client_conn->term = scandata->conn->term; client_conn->options = scandata->options; @@ -238,7 +251,8 @@ client_conn->group = scandata->group; if (cl_engine_addref(scandata->engine)) { logg(LOGG_ERROR, "cl_engine_addref() failed\n"); - free(filename); + free(client_conn->filename); + free(client_conn->display_filename); free(client_conn); return CL_EMEM; } else { @@ -249,7 +263,8 @@ if (!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) { logg(LOGG_ERROR, "thread dispatch failed\n"); cl_engine_free(scandata->engine); - free(filename); + free(client_conn->filename); + free(client_conn->display_filename); free(client_conn); return CL_EMEM; } @@ -257,6 +272,7 @@ } else { logg(LOGG_ERROR, "Can't allocate memory for client_conn\n"); scandata->errors++; + free(scan_filename); free(filename); return CL_EMEM; } @@ -267,10 +283,11 @@ context.filename = filename; context.virsize = 0; context.scandata = scandata; - ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context); + ret = cl_scanfile_callback(scan_path, &virname, &scandata->scanned, scandata->engine, scandata->options, &context); thrmgr_setactivetask(NULL, NULL); if (thrmgr_group_need_terminate(scandata->conn->group)) { + free(scan_filename); free(filename); logg(LOGG_DEBUG, "Client disconnected while scanjob was active\n"); return ret == CL_ETIMEOUT ? ret : CL_BREAK; @@ -283,11 +300,13 @@ if (ret == CL_EACCES) { if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) { + free(scan_filename); free(filename); return CL_ETIMEOUT; } logg(LOGG_DEBUG, "Access denied: %s\n", filename); scandata->errors++; + free(scan_filename); free(filename); return CL_SUCCESS; } @@ -298,11 +317,12 @@ if (optget(scandata->opts, "PreludeEnable")->enabled) { prelude_logging(filename, virname, context.virhash, context.virsize); } - virusaction(filename, virname, scandata->opts); + virusaction(scan_path, virname, scandata->opts); } else { scandata->infected++; - virusaction(filename, virname, scandata->opts); + virusaction(scan_path, virname, scandata->opts); if (conn_reply_virus(scandata->conn, filename, virname) == -1) { + free(scan_filename); free(filename); return CL_ETIMEOUT; } @@ -318,6 +338,7 @@ } else if (ret != CL_CLEAN) { scandata->errors++; if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) { + free(scan_filename); free(filename); return CL_ETIMEOUT; } @@ -326,6 +347,7 @@ logg(LOGG_INFO, "%s: OK\n", filename); } + free(scan_filename); free(filename); if (ret == CL_EMEM) /* stop scanning */ diff -Nru clamav-1.4.3+dfsg/clamd/server-th.c clamav-1.4.6+dfsg/clamd/server-th.c --- clamav-1.4.3+dfsg/clamd/server-th.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/server-th.c 2026-08-06 21:12:04.000000000 +0000 @@ -136,6 +136,8 @@ if (conn->filename) free(conn->filename); + if (conn->display_filename) + free(conn->display_filename); logg(LOGG_DEBUG_NV, "Finished scanthread\n"); enum thrmgr_exit exit_code; if (virus != 0) { diff -Nru clamav-1.4.3+dfsg/clamd/session.c clamav-1.4.6+dfsg/clamd/session.c --- clamav-1.4.3+dfsg/clamd/session.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/session.c 2026-08-06 21:12:04.000000000 +0000 @@ -278,19 +278,28 @@ break; } case COMMAND_MULTISCANFILE: + { + char *scan_filename = conn->filename; + char *display_filename = (NULL != conn->display_filename) ? conn->display_filename : conn->filename; + thrmgr_setactivetask(NULL, "MULTISCANFILE"); scandata.group = NULL; scandata.type = TYPE_SCAN; scandata.thr_pool = NULL; /* TODO: check ret value */ - ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data); /* callback freed it */ - conn->filename = NULL; - *virus = scandata.infected; + ret = scan_callback(NULL, display_filename, scan_filename, visit_file, &data); /* callback freed display_filename */ + if (scan_filename != display_filename) { + free(scan_filename); + } + conn->filename = NULL; + conn->display_filename = NULL; + *virus = scandata.infected; if (ret == CL_BREAK) { thrmgr_group_terminate(conn->group); return 1; } return scandata.errors > 0 ? scandata.errors : 0; + } case COMMAND_FILDES: thrmgr_setactivetask(NULL, "FILDES"); #ifdef HAVE_FD_PASSING diff -Nru clamav-1.4.3+dfsg/clamd/session.h clamav-1.4.6+dfsg/clamd/session.h --- clamav-1.4.3+dfsg/clamd/session.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/session.h 2026-08-06 21:12:04.000000000 +0000 @@ -88,6 +88,7 @@ typedef struct client_conn_tag { enum commands cmdtype; char *filename; + char *display_filename; int scanfd; int sd; struct cl_scan_options *options; diff -Nru clamav-1.4.3+dfsg/clamd/thrmgr.c clamav-1.4.6+dfsg/clamd/thrmgr.c --- clamav-1.4.3+dfsg/clamd/thrmgr.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/thrmgr.c 2026-08-06 21:12:04.000000000 +0000 @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include // libclamav @@ -118,6 +120,113 @@ } *pools = NULL; static pthread_mutex_t pools_lock = PTHREAD_MUTEX_INITIALIZER; +struct stats_buffer { + char *data; + size_t length; + size_t capacity; +}; + +struct queue_stats { + long min_wait; + long max_wait; + long total_wait; + unsigned valid; + unsigned invalid; + unsigned item_count; +}; + +/** + * @brief Free a buffered STATS response. + * + * @param buffer Response buffer to free. + */ +static void stats_buffer_cleanup(struct stats_buffer *buffer) +{ + if (!buffer) + return; + + free(buffer->data); + memset(buffer, 0, sizeof(*buffer)); +} + +/** + * @brief Append formatted text to a buffered STATS response. + * + * @param buffer Response buffer to extend. + * @param format printf-style format string. + * @return CL_SUCCESS on success, or an error status. + */ +static cl_error_t stats_buffer_append(struct stats_buffer *buffer, const char *format, ...) +{ + cl_error_t status = CL_SUCCESS; + size_t required; + va_list args; + int needed; + int written; + + va_start(args, format); + needed = vsnprintf(NULL, 0, format, args); + va_end(args); + if (needed < 0) + return CL_EFORMAT; + + if ((size_t)needed >= SIZE_MAX - buffer->length) + return CL_EMEM; + required = buffer->length + (size_t)needed + 1; + + if (required > buffer->capacity) { + size_t capacity = buffer->capacity ? buffer->capacity : 1024; + char *data; + + while (capacity < required) { + if (capacity > SIZE_MAX / 2) { + capacity = required; + break; + } + capacity *= 2; + } + + data = realloc(buffer->data, capacity); + if (!data) + return CL_EMEM; + + buffer->data = data; + buffer->capacity = capacity; + } + + va_start(args, format); + written = vsnprintf(buffer->data + buffer->length, + buffer->capacity - buffer->length, format, args); + va_end(args); + if (written != needed) { + status = CL_EFORMAT; + goto done; + } + + buffer->length += (size_t)written; + +done: + return status; +} + +/** + * @brief Free a task descriptor and its owned resources. + * + * The caller must ensure that the descriptor is no longer visible to STATS + * and that its worker thread has stopped using it. + * + * @param desc Task descriptor to free. + */ +static void task_desc_free(struct task_desc *desc) +{ + if (!desc) + return; + + free(desc->filename); + pthread_mutex_destroy(&desc->mutex); + free(desc); +} + static void add_topools(threadpool_t *t) { struct threadpool_list *new = malloc(sizeof(*new)); @@ -156,104 +265,238 @@ while (desc) { struct task_desc *q = desc; desc = desc->nxt; - free(q); + task_desc_free(q); } t->tasks = NULL; pthread_mutex_unlock(&pools_lock); } -static void print_queue(int f, work_queue_t *queue, struct timeval *tv_now) +/** + * @brief Copy timing statistics from a work queue. + * + * The caller must hold the owning thread pool's mutex. + * + * @param queue Queue to summarize. + * @param tv_now Time used to calculate queue wait durations. + * @param stats Queue statistics to populate. + */ +static void stats_snapshot_queue(const work_queue_t *queue, const struct timeval *tv_now, struct queue_stats *stats) { - long umin = LONG_MAX, umax = 0, usum = 0; - unsigned invalids = 0, cnt = 0; - work_item_t *q; + const work_item_t *q; + + memset(stats, 0, sizeof(*stats)); + stats->min_wait = LONG_MAX; + stats->item_count = (unsigned)queue->item_count; - if (!queue->head) - return; for (q = queue->head; q; q = q->next) { long delta; delta = tv_now->tv_usec - q->time_queued.tv_usec; delta += (tv_now->tv_sec - q->time_queued.tv_sec) * 1000000; if (delta < 0) { - invalids++; + stats->invalid++; continue; } - if (delta > umax) - umax = delta; - if (delta < umin) - umin = delta; - usum += delta; - ++cnt; - } - mdprintf(f, " min_wait: %.6f max_wait: %.6f avg_wait: %.6f", - umin / 1e6, umax / 1e6, usum / (1e6 * cnt)); - if (invalids) - mdprintf(f, " (INVALID timestamps: %u)", invalids); - if (cnt + invalids != (unsigned)queue->item_count) - mdprintf(f, " (ERROR: %u != %u)", cnt + invalids, - (unsigned)queue->item_count); + if (delta > stats->max_wait) + stats->max_wait = delta; + if (delta < stats->min_wait) + stats->min_wait = delta; + stats->total_wait += delta; + stats->valid++; + } } -int thrmgr_printstats(int f, char term) +/** + * @brief Append a work queue snapshot to a buffered STATS response. + * + * @param buffer Response buffer to extend. + * @param stats Queue statistics to append. + * @return CL_SUCCESS on success, or an error status. + */ +static cl_error_t stats_buffer_append_queue(struct stats_buffer *buffer, const struct queue_stats *stats) +{ + cl_error_t status; + + if (!stats->item_count) + return CL_SUCCESS; + + status = stats_buffer_append(buffer, " min_wait: %.6f max_wait: %.6f avg_wait: %.6f", + stats->valid ? stats->min_wait / 1e6 : 0.0, + stats->valid ? stats->max_wait / 1e6 : 0.0, + stats->valid ? stats->total_wait / (1e6 * stats->valid) : 0.0); + if (CL_SUCCESS != status) + return status; + + if (stats->invalid) { + status = stats_buffer_append(buffer, " (INVALID timestamps: %u)", stats->invalid); + if (CL_SUCCESS != status) + return status; + } + + if (stats->valid + stats->invalid != stats->item_count) { + status = stats_buffer_append(buffer, " (ERROR: %u != %u)", stats->valid + stats->invalid, + stats->item_count); + if (CL_SUCCESS != status) + return status; + } + + return CL_SUCCESS; +} + +/** + * @brief Append a synchronized thread pool snapshot. + * + * The caller must hold pools_lock, which pins the pool while its mutex is + * acquired. No code may acquire pools_lock while holding a pool mutex. + * + * @param buffer Response buffer to extend. + * @param pool Thread pool to summarize. + * @param primary Whether this is the primary pool. + * @param tv_now Time captured for the subsequent task snapshot. + * @return CL_SUCCESS on success, or an error status. + */ +static cl_error_t stats_buffer_append_pool(struct stats_buffer *buffer, threadpool_t *pool, int primary, struct timeval *tv_now) +{ + struct queue_stats bulk_stats; + struct queue_stats single_stats; + cl_error_t status = CL_SUCCESS; + pool_state_t pool_state; + unsigned thr_alive; + unsigned thr_idle; + unsigned thr_max; + unsigned idle_timeout; + unsigned queue_items; + const char *state; + + if (pthread_mutex_lock(&pool->pool_mutex) != 0) { + logg(LOGG_ERROR, "Unable to lock thread pool mutex for statistics\n"); + return CL_ELOCK; + } + + pool_state = pool->state; + thr_alive = (unsigned)pool->thr_alive; + thr_idle = (unsigned)pool->thr_idle; + thr_max = (unsigned)pool->thr_max; + idle_timeout = (unsigned)pool->idle_timeout; + queue_items = (unsigned)pool->single_queue->item_count + (unsigned)pool->bulk_queue->item_count; + gettimeofday(tv_now, NULL); + stats_snapshot_queue(pool->bulk_queue, tv_now, &bulk_stats); + stats_snapshot_queue(pool->single_queue, tv_now, &single_stats); + + if (pthread_mutex_unlock(&pool->pool_mutex) != 0) { + logg(LOGG_ERROR, "Unable to unlock thread pool mutex for statistics\n"); + return CL_ELOCK; + } + + switch (pool_state) { + case POOL_INVALID: + state = "INVALID"; + break; + case POOL_VALID: + state = "VALID"; + break; + case POOL_EXIT: + state = "EXIT"; + break; + default: + state = "??"; + break; + } + + status = stats_buffer_append(buffer, "STATE: %s %s\n", state, primary ? "PRIMARY" : ""); + if (CL_SUCCESS != status) + goto done; + + status = stats_buffer_append(buffer, "THREADS: live %u idle %u max %u idle-timeout %u\n", + thr_alive, thr_idle, thr_max, idle_timeout); + if (CL_SUCCESS != status) + goto done; + + /* TODO: show both queues */ + status = stats_buffer_append(buffer, "QUEUE: %u items", queue_items); + if (CL_SUCCESS != status) + goto done; + + status = stats_buffer_append_queue(buffer, &bulk_stats); + if (CL_SUCCESS != status) + goto done; + + status = stats_buffer_append_queue(buffer, &single_stats); + if (CL_SUCCESS != status) + goto done; + + status = stats_buffer_append(buffer, "\n"); + +done: + return status; +} + +/** + * @brief Create an immutable snapshot of the STATS response. + * + * Pool and task state is formatted into an owned memory buffer while the + * corresponding descriptors are protected. The global pool lock is released + * before any response bytes are written to the client, so a slow or + * non-reading client cannot block scan-worker bookkeeping. + * + * @param response Response snapshot to populate. + * @return CL_SUCCESS on success, or an error status. + */ +static cl_error_t stats_response_create(struct stats_buffer *response) { struct threadpool_list *l; + cl_error_t status = CL_SUCCESS; unsigned cnt, pool_cnt = 0; - size_t pool_used = 0, pool_total = 0, seen_cnt = 0, error_flag = 0; + size_t pool_used = 0, pool_total = 0, seen_cnt = 0; float mem_heap = 0, mem_mmap = 0, mem_used = 0, mem_free = 0, mem_releasable = 0; - const struct cl_engine **seen = NULL; - int has_libc_memstats = 0; + struct cl_engine **seen = NULL; + int has_libc_memstats = 0; + + memset(response, 0, sizeof(*response)); + + if (pthread_mutex_lock(&pools_lock) != 0) { + logg(LOGG_ERROR, "Unable to lock thread pool statistics mutex\n"); + return CL_ELOCK; + } - pthread_mutex_lock(&pools_lock); for (cnt = 0, l = pools; l; l = l->nxt) cnt++; - mdprintf(f, "POOLS: %u\n\n", cnt); - for (l = pools; l && !error_flag; l = l->nxt) { + status = stats_buffer_append(response, "POOLS: %u\n\n", cnt); + if (CL_SUCCESS != status) + goto unlock; + + for (l = pools; l; l = l->nxt) { threadpool_t *pool = l->pool; - const char *state; struct timeval tv_now; struct task_desc *task; - cnt = 0; if (!pool) { - mdprintf(f, "NULL\n\n"); + status = stats_buffer_append(response, "NULL\n\n"); + if (CL_SUCCESS != status) + goto unlock; continue; } - /* now we can access desc->, knowing that they won't get freed - * because the other tasks can't quit while pool_mutex is taken - */ - switch (pool->state) { - case POOL_INVALID: - state = "INVALID"; - break; - case POOL_VALID: - state = "VALID"; - break; - case POOL_EXIT: - state = "EXIT"; - break; - default: - state = "??"; - break; - } - mdprintf(f, "STATE: %s %s\n", state, l->nxt ? "" : "PRIMARY"); - mdprintf(f, "THREADS: live %u idle %u max %u idle-timeout %u\n", pool->thr_alive, pool->thr_idle, pool->thr_max, - pool->idle_timeout); - /* TODO: show both queues */ - mdprintf(f, "QUEUE: %u items", pool->single_queue->item_count + pool->bulk_queue->item_count); - gettimeofday(&tv_now, NULL); - print_queue(f, pool->bulk_queue, &tv_now); - print_queue(f, pool->single_queue, &tv_now); - mdprintf(f, "\n"); + + status = stats_buffer_append_pool(response, pool, !l->nxt, &tv_now); + if (CL_SUCCESS != status) + goto unlock; + for (task = pool->tasks; task; task = task->nxt) { double delta; - size_t used, total; + + if (pthread_mutex_lock(&task->mutex) != 0) { + logg(LOGG_ERROR, "Unable to lock task statistics mutex\n"); + status = CL_ELOCK; + goto unlock; + } delta = tv_now.tv_usec - task->tv.tv_usec; delta += (tv_now.tv_sec - task->tv.tv_sec) * 1000000.0; - mdprintf(f, "\t%s %f %s\n", - task->command ? task->command : "N/A", - delta / 1e6, - task->filename ? task->filename : ""); - if (task->engine) { + + status = stats_buffer_append(response, "\t%s %f %s\n", + task->command ? task->command : "N/A", + delta / 1e6, + task->filename ? task->filename : ""); + + if (CL_SUCCESS == status && task->engine) { /* we usually have at most 2 engines so a linear * search is good enough */ size_t i; @@ -264,28 +507,59 @@ /* we need to count the memusage from the same * engine only once */ if (i == seen_cnt) { - const struct cl_engine **s; + struct cl_engine **s; /* new engine */ - ++seen_cnt; - s = realloc((void *)seen, seen_cnt * sizeof(*seen)); + s = realloc(seen, (seen_cnt + 1) * sizeof(*seen)); if (!s) { - error_flag = 1; - break; - } - seen = s; - seen[seen_cnt - 1] = task->engine; - - if (MPOOL_GETSTATS(task->engine, &used, &total) != -1) { - pool_used += used; - pool_total += total; - pool_cnt++; + status = CL_EMEM; + } else { + seen = s; + status = cl_engine_addref((struct cl_engine *)task->engine); + if (CL_SUCCESS == status) + seen[seen_cnt++] = (struct cl_engine *)task->engine; } } } + + if (pthread_mutex_unlock(&task->mutex) != 0) { + logg(LOGG_ERROR, "Unable to unlock task statistics mutex\n"); + status = CL_ELOCK; + } + + if (CL_SUCCESS != status) + goto unlock; } - mdprintf(f, "\n"); + + status = stats_buffer_append(response, "\n"); + if (CL_SUCCESS != status) + goto unlock; } - free((void *)seen); + +unlock: + if (pthread_mutex_unlock(&pools_lock) != 0) { + logg(LOGG_ERROR, "Unable to unlock thread pool statistics mutex\n"); + status = CL_ELOCK; + } + + if (CL_SUCCESS == status) { + for (cnt = 0; cnt < seen_cnt; cnt++) { + size_t used, total; + + if (MPOOL_GETSTATS(seen[cnt], &used, &total) != -1) { + pool_used += used; + pool_total += total; + pool_cnt++; + } + } + } + + for (cnt = 0; cnt < seen_cnt; cnt++) + cl_engine_free(seen[cnt]); + free(seen); + + if (CL_SUCCESS != status) + goto done; + #ifdef HAVE_MALLINFO { struct mallinfo inf = mallinfo(); @@ -297,19 +571,35 @@ has_libc_memstats = 1; } #endif - if (error_flag) { - mdprintf(f, "ERROR: error encountered while formatting statistics\n"); + + if (has_libc_memstats) + status = stats_buffer_append(response, + "MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM pools %u pools_used %.3fM pools_total %.3fM\n", + mem_heap, mem_mmap, mem_used, mem_free, mem_releasable, pool_cnt, + pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); + else + status = stats_buffer_append(response, + "MEMSTATS: heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %.3fM pools_total %.3fM\n", + pool_cnt, pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); + +done: + if (CL_SUCCESS != status) + stats_buffer_cleanup(response); + + return status; +} + +int thrmgr_printstats(int f, char term) +{ + struct stats_buffer response; + + if (CL_SUCCESS == stats_response_create(&response)) { + mdprintf(f, "%sEND%c", response.data, term); + stats_buffer_cleanup(&response); } else { - if (has_libc_memstats) - mdprintf(f, "MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM pools %u pools_used %.3fM pools_total %.3fM\n", - mem_heap, mem_mmap, mem_used, mem_free, mem_releasable, pool_cnt, - pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); - else - mdprintf(f, "MEMSTATS: heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %.3fM pools_total %.3fM\n", - pool_cnt, pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); + mdprintf(f, "ERROR: error encountered while formatting statistics\nEND%c", term); } - mdprintf(f, "END%c", term); - pthread_mutex_unlock(&pools_lock); + return 0; } @@ -344,12 +634,13 @@ return; } } - remove_frompools(threadpool); if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0) { logg(LOGG_ERROR, "Mutex unlock failed\n"); exit(-1); } + remove_frompools(threadpool); + pthread_mutex_destroy(&(threadpool->pool_mutex)); pthread_cond_destroy(&(threadpool->idle_cond)); pthread_cond_destroy(&(threadpool->queueable_single_cond)); @@ -540,21 +831,42 @@ static const char *IDLE_TASK = "IDLE"; -/* no mutex is needed, we are using thread local variable */ void thrmgr_setactivetask(const char *filename, const char *cmd) { struct task_desc *desc; + char *filename_copy = NULL; + char *old_filename; + pthread_once(&stats_tls_key_once, stats_tls_key_alloc); desc = pthread_getspecific(stats_tls_key); if (!desc) return; - desc->filename = filename; + + if (filename) { + filename_copy = strdup(filename); + if (!filename_copy) + logg(LOGG_ERROR, "Unable to copy active task filename\n"); + } + + if (pthread_mutex_lock(&desc->mutex) != 0) { + logg(LOGG_ERROR, "Unable to lock task statistics mutex\n"); + free(filename_copy); + return; + } + + old_filename = desc->filename; + desc->filename = filename_copy; if (cmd) { - if (cmd == IDLE_TASK && desc->command == cmd) - return; - desc->command = cmd; - gettimeofday(&desc->tv, NULL); + if (!(cmd == IDLE_TASK && desc->command == cmd)) { + desc->command = cmd; + gettimeofday(&desc->tv, NULL); + } } + + if (pthread_mutex_unlock(&desc->mutex) != 0) + logg(LOGG_ERROR, "Unable to unlock task statistics mutex\n"); + + free(old_filename); } void thrmgr_setactiveengine(const struct cl_engine *engine) @@ -564,17 +876,40 @@ desc = pthread_getspecific(stats_tls_key); if (!desc) return; + + if (pthread_mutex_lock(&desc->mutex) != 0) { + logg(LOGG_ERROR, "Unable to lock task statistics mutex\n"); + return; + } + desc->engine = engine; + + if (pthread_mutex_unlock(&desc->mutex) != 0) + logg(LOGG_ERROR, "Unable to unlock task statistics mutex\n"); } -/* thread pool mutex must be held on entry */ +/* Must be called without pool_mutex to preserve the pools_lock -> pool_mutex + * lock order used when collecting statistics. */ static void stats_init(threadpool_t *pool) { struct task_desc *desc = calloc(1, sizeof(*desc)); if (!desc) return; + + if (pthread_mutex_init(&desc->mutex, NULL) != 0) { + logg(LOGG_ERROR, "Unable to initialize task statistics mutex\n"); + free(desc); + return; + } + pthread_once(&stats_tls_key_once, stats_tls_key_alloc); - pthread_setspecific(stats_tls_key, desc); + if (pthread_setspecific(stats_tls_key, desc) != 0) { + logg(LOGG_ERROR, "Unable to initialize task statistics state\n"); + task_desc_free(desc); + return; + } + + pthread_mutex_lock(&pools_lock); if (!pool->tasks) pool->tasks = desc; else { @@ -582,24 +917,34 @@ pool->tasks->prv = desc; pool->tasks = desc; } + pthread_mutex_unlock(&pools_lock); } -/* thread pool mutex must be held on entry */ -static void stats_destroy(threadpool_t *pool) +/** + * @brief Unlink the calling worker's task descriptor. + * + * The caller must hold pools_lock. The returned descriptor is no longer + * visible to STATS and may be freed after releasing pools_lock. + * + * @param pool Thread pool owning the calling worker. + * @return The unlinked descriptor, or NULL if statistics were not initialized. + */ +static struct task_desc *stats_unlink_locked(threadpool_t *pool) { struct task_desc *desc = pthread_getspecific(stats_tls_key); + if (!desc) - return; - pthread_mutex_lock(&pools_lock); + return NULL; + if (desc->prv) desc->prv->nxt = desc->nxt; if (desc->nxt) desc->nxt->prv = desc->prv; if (pool->tasks == desc) pool->tasks = desc->nxt; - free(desc); pthread_setspecific(stats_tls_key, NULL); - pthread_mutex_unlock(&pools_lock); + + return desc; } static inline int thrmgr_contended(threadpool_t *pool, int bulk) @@ -661,20 +1006,21 @@ static void *thrmgr_worker(void *arg) { threadpool_t *threadpool = (threadpool_t *)arg; + struct task_desc *desc; void *job_data; - int retval, must_exit = FALSE, stats_inited = FALSE; + int retval, must_exit; struct timespec timeout; + stats_init(threadpool); + /* loop looking for work */ for (;;) { + must_exit = FALSE; + if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { logg(LOGG_ERROR, "Fatal: mutex lock failed\n"); exit(-2); } - if (!stats_inited) { - stats_init(threadpool); - stats_inited = TRUE; - } thrmgr_setactiveengine(NULL); thrmgr_setactivetask(NULL, IDLE_TASK); timeout.tv_sec = time(NULL) + threadpool->idle_timeout; @@ -702,26 +1048,54 @@ if (job_data) { threadpool->handler(job_data); } else if (must_exit) { - break; + /* A dispatcher can add work after the timed wait releases the + * pool mutex but before this worker retires. Make the final + * decision while holding both locks in the same order used by + * STATS so dispatch either observes this worker alive or starts + * a replacement after it has retired. */ + if (pthread_mutex_lock(&pools_lock) != 0) { + logg(LOGG_ERROR, "Fatal: pools mutex lock failed\n"); + exit(-2); + } + if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { + logg(LOGG_ERROR, "Fatal: mutex lock failed\n"); + exit(-2); + } + + if (threadpool->state == POOL_VALID && + (threadpool->single_queue->item_count != 0 || + threadpool->bulk_queue->item_count != 0)) { + if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { + logg(LOGG_ERROR, "Fatal: mutex unlock failed\n"); + exit(-2); + } + if (pthread_mutex_unlock(&pools_lock) != 0) { + logg(LOGG_ERROR, "Fatal: pools mutex unlock failed\n"); + exit(-2); + } + continue; + } + + desc = stats_unlink_locked(threadpool); + threadpool->thr_alive--; + if (threadpool->thr_alive == 0) { + /* signal that all threads are finished */ + pthread_cond_broadcast(&threadpool->pool_cond); + } + + if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { + logg(LOGG_ERROR, "Fatal: mutex unlock failed\n"); + exit(-2); + } + if (pthread_mutex_unlock(&pools_lock) != 0) { + logg(LOGG_ERROR, "Fatal: pools mutex unlock failed\n"); + exit(-2); + } + + task_desc_free(desc); + return NULL; } } - if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { - /* Fatal error */ - logg(LOGG_ERROR, "Fatal: mutex lock failed\n"); - exit(-2); - } - threadpool->thr_alive--; - if (threadpool->thr_alive == 0) { - /* signal that all threads are finished */ - pthread_cond_broadcast(&threadpool->pool_cond); - } - stats_destroy(threadpool); - if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { - /* Fatal error */ - logg(LOGG_ERROR, "Fatal: mutex unlock failed\n"); - exit(-2); - } - return NULL; } static int thrmgr_dispatch_internal(threadpool_t *threadpool, void *user_data, int bulk) diff -Nru clamav-1.4.3+dfsg/clamd/thrmgr.h clamav-1.4.6+dfsg/clamd/thrmgr.h --- clamav-1.4.3+dfsg/clamd/thrmgr.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamd/thrmgr.h 2026-08-06 21:12:04.000000000 +0000 @@ -49,7 +49,8 @@ } pool_state_t; struct task_desc { - const char *filename; + pthread_mutex_t mutex; + char *filename; const char *command; struct timeval tv; struct task_desc *prv; diff -Nru clamav-1.4.3+dfsg/clamdscan/client.c clamav-1.4.6+dfsg/clamdscan/client.c --- clamav-1.4.3+dfsg/clamdscan/client.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamdscan/client.c 2026-08-06 21:12:04.000000000 +0000 @@ -310,22 +310,11 @@ static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) { int ret; - char *real_path = NULL; char *fullpath = NULL; - /* Convert relative path to fullpath */ + /* Convert relative path to fullpath without resolving symlinks. */ fullpath = makeabs(file); - /* Convert fullpath to the real path (evaluating symlinks and . and ..). - Doing this early on will ensure that the scan results will appear consistent - across regular scans, --fdpass scans, and --stream scans. */ - if (CL_SUCCESS != cli_realpath(fullpath, &real_path)) { - logg(LOGG_DEBUG, "client_scan: Failed to determine real filename of %s.\n", fullpath); - } else { - free(fullpath); - fullpath = real_path; - } - if (!fullpath) return 0; if (!session) @@ -392,6 +381,7 @@ int client(const struct optstruct *opts, int *infected, int *err) { int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0; + int action_requested, client_side_multiscan = 0; const char *fname; if (optget(opts, "wait")->enabled) { @@ -407,14 +397,31 @@ } scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]); - remote = isremote(opts) | optget(opts, "stream")->enabled; + remote = isremote(opts) | optget(opts, "stream")->enabled; + action_requested = (NULL != action) || + optget(opts, "move")->enabled || + optget(opts, "copy")->enabled || + optget(opts, "remove")->enabled; + + if (action_requested && optget(opts, "allmatch")->enabled) { + logg(LOGG_WARNING, "--allmatch is ignored when quarantine actions are enabled.\n"); + } + + /* + * Quarantine actions must scan a client-opened file object so the action + * can run against the same object after the verdict. When multiscan is + * requested, use IDSESSION for client-side parallelism instead of sending + * whole directories to clamd. + */ + client_side_multiscan = action_requested && optget(opts, "multiscan")->enabled; #ifdef HAVE_FD_PASSING - if (!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) { + if (!remote && optget(clamdopts, "LocalSocket")->enabled && + (action_requested || optget(opts, "fdpass")->enabled || scandash || client_side_multiscan)) { scantype = FILDES; session = optget(opts, "multiscan")->enabled; } else #endif - if (remote || scandash) { + if (action_requested || remote || scandash || client_side_multiscan) { scantype = STREAM; session = optget(opts, "multiscan")->enabled; } else if (optget(opts, "multiscan")->enabled) @@ -443,7 +450,8 @@ return 2; } if ((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM; - if ((sockd = dconnect(clamdopts)) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL, clamdopts)) >= 0) + if ((sockd = dconnect(clamdopts)) >= 0 && + (ret = dsresult(sockd, scantype, NULL, NULL, false, &ret, NULL, clamdopts)) >= 0) *infected = ret; else errors = 1; diff -Nru clamav-1.4.3+dfsg/clamdscan/proto.c clamav-1.4.6+dfsg/clamdscan/proto.c --- clamav-1.4.3+dfsg/clamdscan/proto.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamdscan/proto.c 2026-08-06 21:12:04.000000000 +0000 @@ -45,6 +45,9 @@ #include #endif #ifndef _WIN32 +#include +#endif +#ifndef _WIN32 #include #include #include @@ -68,44 +71,151 @@ int printinfected; extern struct optstruct *clamdopts; +#define DEFAULT_MAX_ACTION_SOURCES 64 + +static unsigned int get_max_action_sources(void) +{ +#ifndef _WIN32 +#ifdef RLIMIT_NOFILE + struct rlimit rlim; + + if ((0 == getrlimit(RLIMIT_NOFILE, &rlim)) && (RLIM_INFINITY != rlim.rlim_cur)) { + rlim_t limit = rlim.rlim_cur; + + if (limit <= 16) { + return 1; + } + + limit = (limit - 16) / 2; + if (limit < 1) { + return 1; + } + if (limit < DEFAULT_MAX_ACTION_SOURCES) { + return (unsigned int)limit; + } + } +#endif +#endif + + return DEFAULT_MAX_ACTION_SOURCES; +} + +struct client_walk_policy { + bool check_cross_filesystems; + bool have_dev; + dev_t dev; +#ifdef C_LINUX + bool check_proc; + dev_t proc_dev; +#endif +}; + +/** + * Initialize client-side traversal policy for local quarantine actions. + * + * When clamdscan performs local actions, it walks paths client-side and sends + * individual files to clamd. Preserve clamd's procfs and CrossFilesystems=no + * behavior for those action scans so files skipped by daemon-side directory + * scans are not opened or quarantined by the client-side walk. + */ +static void client_walk_policy_init(struct client_walk_policy *policy, const char *path) +{ + STATBUF sb; + + policy->check_cross_filesystems = (NULL != action) && !optget(clamdopts, "CrossFilesystems")->enabled; + policy->have_dev = false; + policy->dev = 0; +#ifdef C_LINUX + policy->check_proc = false; + policy->proc_dev = 0; + + if ((NULL != action) && (0 == CLAMSTAT("/proc", &sb)) && !sb.st_size) { + policy->check_proc = true; + policy->proc_dev = sb.st_dev; + } +#endif + + if (policy->check_cross_filesystems && (0 == CLAMSTAT(path, &sb))) { + policy->have_dev = true; + policy->dev = sb.st_dev; + } +} + +/** + * Return nonzero when a path should be skipped by a client-side walk. + */ +static int client_path_excluded(const char *path, const struct client_walk_policy *policy) +{ + STATBUF sb; + + if (chkpath(path, clamdopts)) { + return 1; + } + +#ifdef C_LINUX + if ((NULL != policy) && policy->check_proc && + (0 == CLAMSTAT(path, &sb)) && (sb.st_dev == policy->proc_dev)) { + return 1; + } +#endif + + if ((NULL != policy) && policy->check_cross_filesystems && policy->have_dev && + (0 == CLAMSTAT(path, &sb)) && (sb.st_dev != policy->dev)) { + return 1; + } + + return 0; +} + static int ftw_chkpath(const char *path, struct cli_ftw_cbdata *data) { - UNUSEDPARAM(data); - return chkpath(path, clamdopts); + const struct client_walk_policy *policy = NULL; + + if ((NULL != data) && (NULL != data->data)) { + policy = (const struct client_walk_policy *)data->data; + } + + return client_path_excluded(path, policy); } /* Used by serial_callback() */ struct client_serial_data { + /* Must be first: ftw_chkpath() receives only cli_ftw_cbdata::data. */ + struct client_walk_policy walk_policy; int infected; int scantype; int printok; int files; int errors; + int flags; + int maxlevel; }; /* FTW callback for scanning in non IDSESSION mode * Returns SUCCESS or BREAK on success, CL_EXXX on error */ static cl_error_t serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { - int status = CL_EOPEN; + cl_error_t status = CL_EOPEN; struct client_serial_data *c = (struct client_serial_data *)data->data; int sockd, ret; - const char *f = filename; - char *real_filename = NULL; + const char *f = filename; + const char *scan_path = path; + char *real_filter_path = NULL; + action_source_t action_source; + bool have_action_source = false; + + action_source_init(&action_source); UNUSEDPARAM(sb); - if (reason != visit_directory_toplev) { - if (CL_SUCCESS != cli_realpath((const char *)path, &real_filename)) { - logg(LOGG_DEBUG, "Failed to determine real filename of %s.\n", path); - logg(LOGG_DEBUG, "Quarantine of the file may fail if file path contains symlinks.\n"); - } else { - path = real_filename; - } + if (CL_SUCCESS != cli_realpath((const char *)path, &real_filter_path)) { + logg(LOGG_DEBUG, "Failed to determine real filename of %s.\n", path); + } else { + scan_path = real_filter_path; } - if (chkpath(path, clamdopts)) { + if (client_path_excluded(scan_path, &c->walk_policy)) { /* Exclude the path */ status = CL_SUCCESS; goto done; @@ -134,12 +244,25 @@ status = CL_SUCCESS; goto done; case visit_directory_toplev: - if (c->scantype >= STREAM) { + if ((c->scantype >= STREAM) || action) { status = CL_SUCCESS; goto done; } - f = path; + f = scan_path; + break; case visit_file: + if (action) { + ret = action_source_open_path(f, scan_path, &action_source); + if (CL_SUCCESS != ret) { + logg(LOGG_WARNING, "Can't open file %s for safe quarantine action: %s\n", f, cl_strerror(ret)); + c->errors++; + status = CL_SUCCESS; + goto done; + } + have_action_source = true; + } else { + f = scan_path; + } break; } @@ -147,7 +270,7 @@ c->errors++; goto done; } - ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors, clamdopts); + ret = dsresult(sockd, c->scantype, f, have_action_source ? &action_source : NULL, have_action_source, &c->printok, &c->errors, clamdopts); closesocket(sockd); if (ret < 0) { c->errors++; @@ -161,8 +284,11 @@ status = CL_SUCCESS; done: - if (NULL != real_filename) { - free(real_filename); + if (have_action_source) { + action_source_close(&action_source); + } + if (NULL != real_filter_path) { + free(real_filter_path); } free(filename); return status; @@ -181,6 +307,9 @@ cdata.errors = 0; cdata.printok = printinfected ^ 1; cdata.scantype = scantype; + cdata.flags = flags; + cdata.maxlevel = maxlevel ? maxlevel : INT_MAX; + client_walk_policy_init(&cdata.walk_policy, file); data.data = &cdata; ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, ftw_chkpath); @@ -200,6 +329,8 @@ /* Used in IDSESSION mode */ struct client_parallel_data { + /* Must be first: ftw_chkpath() receives only cli_ftw_cbdata::data. */ + struct client_walk_policy walk_policy; int infected; int files; int errors; @@ -210,8 +341,11 @@ struct SCANID { unsigned int id; const char *file; + action_source_t *action_source; struct SCANID *next; } *ids; + unsigned int action_sources; + unsigned int max_action_sources; }; /* Sends a proper scan request to clamd and parses its replies @@ -220,6 +354,7 @@ static int dspresult(struct client_parallel_data *c) { const char *filename; + action_source_t *action_source; char *bol, *eol; unsigned int rid; int len; @@ -244,17 +379,17 @@ return 1; } filename = (*id)->file; + action_source = (*id)->action_source; if (len > 7) { char *colon = strrchr(bol, ':'); if (!colon) { logg(LOGG_ERROR, "Failed to parse reply\n"); - free((void *)filename); return 1; } else if (!memcmp(eol - 7, " FOUND", 6)) { c->infected++; c->printok = 0; logg(LOGG_INFO, "%s%s\n", filename, colon); - if (action) action(filename); + if (action && (NULL != action_source)) action(action_source); } else if (!memcmp(eol - 7, " ERROR", 6)) { c->errors++; c->printok = 0; @@ -262,6 +397,13 @@ } } free((void *)filename); + if (NULL != action_source) { + action_source_close(action_source); + free(action_source); + if (c->action_sources > 0) { + c->action_sources--; + } + } bol = (char *)*id; *id = (*id)->next; free(bol); @@ -270,6 +412,30 @@ return 0; } +static void free_scanids(struct client_parallel_data *c) +{ + struct SCANID *id; + + if (NULL == c) { + return; + } + + while (NULL != c->ids) { + id = c->ids; + c->ids = id->next; + + free((void *)id->file); + if (NULL != id->action_source) { + action_source_close(id->action_source); + free(id->action_source); + if (c->action_sources > 0) { + c->action_sources--; + } + } + free(id); + } +} + /* FTW callback for scanning in IDSESSION mode * Returns SUCCESS on success, CL_EXXX or BREAK on error */ static cl_error_t parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) @@ -278,24 +444,21 @@ struct client_parallel_data *c = (struct client_parallel_data *)data->data; struct SCANID *cid = NULL; - int res = CL_CLEAN; - - char *real_filename = NULL; + int res = 0; + action_source_t *action_source = NULL; + const char *scan_path = filename; + char *real_filter_path = NULL; UNUSEDPARAM(sb); UNUSEDPARAM(path); - if (reason != visit_directory_toplev) { - if (CL_SUCCESS != cli_realpath((const char *)filename, &real_filename)) { - logg(LOGG_DEBUG, "Failed to determine real filename of %s.\n", filename); - logg(LOGG_DEBUG, "Quarantine of the file may fail if file path contains symlinks.\n"); - } else { - free(filename); /* callback is responsible for free'ing filename parameter. */ - filename = real_filename; - } + if (CL_SUCCESS != cli_realpath((const char *)filename, &real_filter_path)) { + logg(LOGG_DEBUG, "Failed to determine real filename of %s.\n", filename); + } else { + scan_path = real_filter_path; } - if (chkpath(filename, clamdopts)) { + if (client_path_excluded(scan_path, &c->walk_policy)) { /* Exclude the path */ status = CL_SUCCESS; goto done; @@ -328,6 +491,29 @@ break; } + if (action) { + while (c->action_sources >= c->max_action_sources) { + if (dspresult(c)) { + status = CL_BREAK; + goto done; + } + } + + action_source = malloc(sizeof(*action_source)); + if (NULL == action_source) { + logg(LOGG_ERROR, "Failed to allocate action source: %s\n", strerror(errno)); + c->errors++; + status = CL_EMEM; + goto done; + } + if (CL_SUCCESS != action_source_open_path(filename, scan_path, action_source)) { + logg(LOGG_WARNING, "Can't open file %s for safe quarantine action.\n", filename); + c->errors++; + status = CL_SUCCESS; + goto done; + } + } + while (1) { /* consume all the available input to let some of the clamd * threads blocked on send() to be dead. @@ -356,11 +542,11 @@ switch (c->scantype) { #ifdef HAVE_FD_PASSING case FILDES: - res = send_fdpass(c->sockd, filename); + res = (NULL != action_source) ? send_fdpass_fd(c->sockd, action_source->scan_fd) : send_fdpass(c->sockd, scan_path); break; #endif case STREAM: - res = send_stream(c->sockd, filename, clamdopts); + res = (NULL != action_source) ? send_stream_fd_action(c->sockd, action_source->scan_fd, action_source->display_path, clamdopts) : send_stream(c->sockd, scan_path, clamdopts); break; } if (res <= 0) { @@ -377,20 +563,32 @@ goto done; } - cid->id = ++c->lastid; - cid->file = filename; - cid->next = c->ids; - c->ids = cid; + cid->id = ++c->lastid; + cid->file = filename; + cid->action_source = action_source; + cid->next = c->ids; + c->ids = cid; + if (NULL != action_source) { + c->action_sources++; + } /* Give up ownership of the filename to the client parallel scan ID list */ - filename = NULL; + filename = NULL; + action_source = NULL; status = CL_SUCCESS; done: + if (NULL != action_source) { + action_source_close(action_source); + free(action_source); + } if (NULL != filename) { free(filename); } + if (NULL != real_filter_path) { + free(real_filter_path); + } return status; } @@ -412,20 +610,24 @@ return 1; } - cdata.infected = 0; - cdata.files = 0; - cdata.errors = 0; - cdata.scantype = scantype; - cdata.lastid = 0; - cdata.ids = NULL; - cdata.printok = printinfected ^ 1; - data.data = &cdata; + cdata.infected = 0; + cdata.files = 0; + cdata.errors = 0; + cdata.scantype = scantype; + cdata.lastid = 0; + cdata.ids = NULL; + cdata.printok = printinfected ^ 1; + cdata.action_sources = 0; + cdata.max_action_sources = get_max_action_sources(); + client_walk_policy_init(&cdata.walk_policy, file); + data.data = &cdata; ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath); if (ftw != CL_SUCCESS) { *err += cdata.errors; *infected += cdata.infected; + free_scanids(&cdata); closesocket(cdata.sockd); return 1; } @@ -439,6 +641,7 @@ if (cdata.ids) { logg(LOGG_ERROR, "Clamd closed the connection before scanning all files.\n"); + free_scanids(&cdata); return 1; } if (cdata.errors) diff -Nru clamav-1.4.3+dfsg/clamonacc/client/client.c clamav-1.4.6+dfsg/clamonacc/client/client.c --- clamav-1.4.3+dfsg/clamonacc/client/client.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/client/client.c 2026-08-06 21:12:04.000000000 +0000 @@ -403,6 +403,8 @@ const struct optstruct *opts; cl_error_t err; int remote; + bool action_requested; + bool fdpass_requested; errno = 0; @@ -427,9 +429,17 @@ } remote = (*ctx)->isremote | optget(opts, "stream")->enabled; + action_requested = (NULL != action) || + optget(opts, "move")->enabled || + optget(opts, "copy")->enabled || + optget(opts, "remove")->enabled; + fdpass_requested = action_requested || optget(opts, "fdpass")->enabled; + if (action_requested && optget(opts, "allmatch")->enabled) { + logg(LOGG_WARNING, "--allmatch is ignored when quarantine actions are enabled.\n"); + } #ifdef HAVE_FD_PASSING - if (!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled)) { - if (onas_set_sock_only_once(*ctx) == CL_EWRITE) { + if (!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && fdpass_requested) { + if (onas_set_sock_only_once(*ctx, fdpass_requested) == CL_EWRITE) { return CL_EWRITE; } logg(LOGG_DEBUG, "ClamClient: client setup to scan via fd passing\n"); @@ -437,7 +447,7 @@ (*ctx)->session = optget(opts, "multiscan")->enabled; } else #endif - if (remote) { + if (action_requested || remote) { logg(LOGG_DEBUG, "ClamClient: client setup to scan via streaming\n"); (*ctx)->scantype = STREAM; (*ctx)->session = optget(opts, "multiscan")->enabled; @@ -534,20 +544,55 @@ CURL *curl = NULL; CURLcode curlcode = CURLE_OK; int errors = 0; - int ret; + int scan_result = 0; + int printok = 1; + cl_error_t status = CL_CLEAN; + action_source_t action_source; + char *resolved_action_path = NULL; + bool have_action_source = false; + bool regular_file = S_ISREG(sb.st_mode); static bool disconnected = false; + action_source_init(&action_source); + *infected = 0; + if (err) { + *err = 0; + } + if (ret_code) { + *ret_code = CL_SUCCESS; + } - if ((sb.st_mode & S_IFMT) != S_IFREG) { + if (!regular_file) { scantype = STREAM; } + if (action && (NULL != fname) && regular_file) { + if (fd >= 0) { + status = action_source_from_fd(fname, fd, &action_source); + } else { + status = cli_realpath(fname, &resolved_action_path); + if (CL_SUCCESS == status) { + status = action_source_open_path(fname, resolved_action_path, &action_source); + } + } + if (CL_SUCCESS != status) { + logg(LOGG_WARNING, "Can't open file %s for safe quarantine action: %s\n", fname, cl_strerror(status)); + goto done; + } + have_action_source = true; + if (scantype < STREAM) { + scantype = STREAM; + } + } + curlcode = onas_curl_init(&curl, tcpaddr, portnum, timeout); if (CURLE_OK != curlcode) { logg(LOGG_ERROR, "ClamClient: could not init curl for scanning, %s\n", curl_easy_strerror(curlcode)); /* curl cleanup done in onas_curl_init on error */ - return CL_ECREAT; + curl = NULL; + status = CL_ECREAT; + goto done; } curlcode = curl_easy_perform(curl); @@ -557,20 +602,43 @@ disconnected = true; } curl_easy_cleanup(curl); - return CL_ECREAT; + curl = NULL; + status = CL_ECREAT; + goto done; } if (disconnected) { logg(LOGG_INFO, "ClamClient: Connection to clamd re-established.\n"); disconnected = false; } - if ((ret = onas_dsresult(curl, scantype, maxstream, fname, fd, timeout, &ret, err, ret_code)) >= 0) { - *infected = ret; + if ((scan_result = onas_dsresult(curl, scantype, maxstream, fname, have_action_source ? &action_source : NULL, fd, timeout, + &printok, err, ret_code)) >= 0) { + *infected = scan_result; } else { - logg(LOGG_DEBUG, "ClamClient: connection could not be established ... return code %d\n", *ret_code); + logg(LOGG_DEBUG, "ClamClient: connection could not be established ... return code %d\n", ret_code ? *ret_code : scan_result); errors = 1; } - curl_easy_cleanup(curl); - return *infected ? CL_VIRUS : (errors ? CL_ECREAT : CL_CLEAN); + status = *infected ? CL_VIRUS : (errors ? CL_ECREAT : CL_CLEAN); + +done: + if ((CL_CLEAN != status) && (CL_VIRUS != status)) { + if (err && (0 == *err)) { + (*err)++; + } + if (ret_code && (CL_SUCCESS == *ret_code)) { + *ret_code = status; + } + } + + if (NULL != curl) { + curl_easy_cleanup(curl); + } + if (have_action_source) { + action_source_close(&action_source); + } + if (NULL != resolved_action_path) { + free(resolved_action_path); + } + return status; } diff -Nru clamav-1.4.3+dfsg/clamonacc/client/protocol.c clamav-1.4.6+dfsg/clamonacc/client/protocol.c --- clamav-1.4.3+dfsg/clamonacc/client/protocol.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/client/protocol.c 2026-08-06 21:12:04.000000000 +0000 @@ -72,7 +72,7 @@ /* Issues an INSTREAM command to clamd and streams the given file * Returns >0 on success, 0 soft fail, -1 hard fail */ -static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t timeout, uint64_t maxstream) +static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t timeout, uint64_t maxstream, bool action_stream, cl_error_t *ret_code) { uint32_t buf[BUFSIZ / sizeof(uint32_t)]; uint64_t len; @@ -108,41 +108,85 @@ } if ((uint64_t)statbuf.st_size > maxstream) { - ret = 0; + if (action_stream) { + logg(LOGG_ERROR, "%s: File size exceeds StreamMaxLength; refusing to send a truncated quarantine stream. ERROR\n", + filename ? filename : "FD"); + if (ret_code) { + *ret_code = CL_EMAXSIZE; + } + ret = -1; + } else { + ret = 0; + } goto strm_out; } - if (onas_sendln(curl, zINSTREAM, sizeof(zINSTREAM), timeout)) { - ret = -1; - goto strm_out; + if (0 != fd) { + (void)lseek(fd, 0, SEEK_SET); } - len = statbuf.st_size; - buf[0] = htonl(len); - if (onas_sendln(curl, (const char *)buf, sizeof(uint32_t), timeout)) { + if (onas_sendln(curl, zINSTREAM, sizeof(zINSTREAM), timeout)) { ret = -1; goto strm_out; } + len = statbuf.st_size; while (bytesRead < len) { - ssize_t ret = read(fd, buf, sizeof(buf)); - if (ret < 0) { + uint64_t remaining = len - bytesRead; + size_t read_len = (remaining < sizeof(buf)) ? (size_t)remaining : sizeof(buf); + ssize_t bytes = read(fd, buf, read_len); + uint32_t chunk_len; + + if (bytes < 0) { logg(LOGG_ERROR, "Failed to read from %s.\n", filename ? filename : "FD"); ret = -1; goto strm_out; - } else if (0 == ret) { + } else if (0 == bytes) { break; } - bytesRead += ret; + bytesRead += bytes; + + chunk_len = htonl((uint32_t)bytes); + if (onas_sendln(curl, (const char *)&chunk_len, sizeof(chunk_len), timeout) || + onas_sendln(curl, (const char *)buf, (size_t)bytes, timeout)) { + ret = -1; + goto strm_out; + } + } + + if (bytesRead < len) { + logg(LOGG_ERROR, "%s: File changed while streaming; refusing to send a partial INSTREAM chunk. ERROR\n", + filename ? filename : "FD"); + if (ret_code) { + *ret_code = CL_EREAD; + } + ret = -1; + goto strm_out; + } + + if (action_stream && S_ISREG(statbuf.st_mode) && (bytesRead == len)) { + ssize_t bytes = read(fd, buf, 1); - if (onas_sendln(curl, (const char *)buf, ret, timeout)) { + if (bytes < 0) { + logg(LOGG_ERROR, "Failed to read from %s.\n", filename ? filename : "FD"); + ret = -1; + goto strm_out; + } else if (bytes > 0) { + logg(LOGG_ERROR, "%s: File size exceeds StreamMaxLength; refusing to send a truncated quarantine stream. ERROR\n", + filename ? filename : "FD"); + if (ret_code) { + *ret_code = CL_EMAXSIZE; + } ret = -1; goto strm_out; } } *buf = 0; - onas_sendln(curl, (const char *)buf, 4, timeout); + if (onas_sendln(curl, (const char *)buf, 4, timeout)) { + ret = -1; + goto strm_out; + } strm_out: if (close_flag) { @@ -232,7 +276,8 @@ * This is used only in non IDSESSION mode * Returns the number of infected files or -1 on error * NOTE: filename may be NULL for STREAM scantype. */ -int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code) +int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, const action_source_t *action_source, + int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code) { int infected = 0, len = 0, beenthere = 0; char *bol, *eol; @@ -240,11 +285,17 @@ STATBUF sb; int sockd = -1; int (*recv_func)(struct onas_rcvln *, char **, char **, int64_t) = NULL; + const char *display_filename = (NULL != action_source) ? action_source->display_path : filename; + int scan_fd = (NULL != action_source) ? action_source->scan_fd : fd; - sockd = onas_get_sockd(); +#ifdef HAVE_FD_PASSING + if (FILDES == scantype) { + sockd = onas_get_sockd(); + } +#endif onas_recvlninit(&rcv, curl, sockd); - if (rcv.sockd > 0) { + if ((FILDES == scantype) && (rcv.sockd > 0)) { recv_func = &onas_fd_recvln; } else { recv_func = &onas_recvln; @@ -285,25 +336,30 @@ case STREAM: /* NULL filename safe in send_stream() */ - len = onas_send_stream(curl, filename, fd, timeout, maxstream); + len = onas_send_stream(curl, display_filename, scan_fd, timeout, maxstream, NULL != action_source, ret_code); break; #ifdef HAVE_FD_PASSING case FILDES: /* NULL filename safe in send_fdpass() */ - len = onas_fdpass(filename, fd, sockd); + len = onas_fdpass(display_filename, scan_fd, sockd); break; #endif } if (len <= 0) { *printok = 0; - if (errors && len < 0) { - /* Ignore error if len == 0 to reduce verbosity from file open() - "errors" where the file has been deleted before we have a chance - to scan it. */ + if (errors && ((len < 0) || (NULL != action_source))) { + /* + * Keep len == 0 as a soft skip for mutable path scans where a file + * disappeared before opening. Treat opened action-source failures + * as errors because the later action depends on that same object. + */ (*errors)++; } - infected = len; + if (ret_code && (CL_SUCCESS == *ret_code) && ((len < 0) || (NULL != action_source))) { + *ret_code = CL_EWRITE; + } + infected = ((NULL != action_source) && (0 == len)) ? -1 : len; goto done; } @@ -318,7 +374,7 @@ goto done; } beenthere = 1; - if (!filename) { + if (!display_filename) { logg(LOGG_INFO, "%s\n", bol); } if (len > 7) { @@ -365,17 +421,21 @@ } } - if (filename) { + if (display_filename) { if (scantype >= STREAM) { - logg(LOGG_INFO, "%s%s FOUND\n", filename, colon); + logg(LOGG_INFO, "%s%s FOUND\n", display_filename, colon); if (action) { - action(filename); + if (NULL != action_source) { + action(action_source); + } } } else { logg(LOGG_INFO, "%s FOUND\n", bol); *colon = '\0'; if (action) { - action(bol); + if (NULL != action_source) { + action(action_source); + } } } } @@ -391,8 +451,8 @@ } *printok = 0; - if (filename) { - (scantype >= STREAM) ? logg(LOGG_DEBUG, "%s%s\n", filename, colon) : logg(LOGG_DEBUG, "%s\n", bol); + if (display_filename) { + (scantype >= STREAM) ? logg(LOGG_DEBUG, "%s%s\n", display_filename, colon) : logg(LOGG_DEBUG, "%s\n", bol); } if (ret_code) { @@ -406,8 +466,8 @@ } *printok = 0; - if (filename) { - (scantype >= STREAM) ? logg(LOGG_INFO, "%s%s\n", filename, colon) : logg(LOGG_INFO, "%s\n", bol); + if (display_filename) { + (scantype >= STREAM) ? logg(LOGG_INFO, "%s%s\n", display_filename, colon) : logg(LOGG_INFO, "%s\n", bol); } if (ret_code) { @@ -419,8 +479,8 @@ } *printok = 0; - if (filename) { - (scantype >= STREAM) ? logg(LOGG_INFO, "%s%s\n", filename, colon) : logg(LOGG_INFO, "%s\n", bol); + if (display_filename) { + (scantype >= STREAM) ? logg(LOGG_INFO, "%s%s\n", display_filename, colon) : logg(LOGG_INFO, "%s\n", bol); } if (ret_code) { @@ -430,7 +490,7 @@ } } if (!beenthere) { - if (!filename) { + if (!display_filename) { logg(LOGG_INFO, "STDIN: noreply from clamd\n."); if (ret_code) { *ret_code = CL_EACCES; @@ -438,9 +498,9 @@ infected = -1; goto done; } - if (CLAMSTAT(filename, &sb) == -1) { + if (CLAMSTAT(display_filename, &sb) == -1) { logg(LOGG_INFO, "%s: stat() failed with %s, clamd may not be responding\n", - filename, strerror(errno)); + display_filename, strerror(errno)); if (ret_code) { *ret_code = CL_EACCES; } @@ -448,7 +508,7 @@ goto done; } if (!S_ISDIR(sb.st_mode)) { - logg(LOGG_INFO, "%s: no reply from clamd\n", filename); + logg(LOGG_INFO, "%s: no reply from clamd\n", display_filename); if (ret_code) { *ret_code = CL_EACCES; } diff -Nru clamav-1.4.3+dfsg/clamonacc/client/protocol.h clamav-1.4.6+dfsg/clamonacc/client/protocol.h --- clamav-1.4.3+dfsg/clamonacc/client/protocol.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/client/protocol.h 2026-08-06 21:12:04.000000000 +0000 @@ -27,5 +27,8 @@ #include "misc.h" #include "../clamonacc.h" -int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code); +struct action_source; + +int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, const struct action_source *action_source, + int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code); #endif diff -Nru clamav-1.4.3+dfsg/clamonacc/client/socket.c clamav-1.4.6+dfsg/clamonacc/client/socket.c --- clamav-1.4.3+dfsg/clamonacc/client/socket.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/client/socket.c 2026-08-06 21:12:04.000000000 +0000 @@ -41,10 +41,11 @@ /** * One time socket setup for unix file descriptor passing * - * @param ctx a point to the onas context struct + * @param ctx a pointer to the onas context struct + * @param allow_fdpass true if fd passing is enabled or required by this scan mode * @return CL_SUCCESS if writing to socket struct was successful, CL_EWRITE if the socket has already been written to */ -cl_error_t onas_set_sock_only_once(struct onas_context *ctx) +cl_error_t onas_set_sock_only_once(struct onas_context *ctx, bool allow_fdpass) { const struct optstruct *opt; @@ -54,7 +55,7 @@ if (((opt = optget(ctx->clamdopts, "LocalSocket")) ->enabled) && - optget(ctx->opts, "fdpass")->enabled) { + allow_fdpass) { memset((void *)&onas_sock, 0, sizeof(onas_sock)); onas_sock.sock.sun_family = AF_UNIX; strncpy(onas_sock.sock.sun_path, opt->strarg, sizeof(onas_sock.sock.sun_path)); diff -Nru clamav-1.4.3+dfsg/clamonacc/client/socket.h clamav-1.4.6+dfsg/clamonacc/client/socket.h --- clamav-1.4.3+dfsg/clamonacc/client/socket.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/client/socket.h 2026-08-06 21:12:04.000000000 +0000 @@ -20,6 +20,7 @@ #include #include +#include #include "optparser.h" #include "../clamonacc.h" @@ -30,5 +31,5 @@ struct sockaddr_un sock; }; -cl_error_t onas_set_sock_only_once(struct onas_context *ctx); +cl_error_t onas_set_sock_only_once(struct onas_context *ctx, bool allow_fdpass); int onas_get_sockd(void); diff -Nru clamav-1.4.3+dfsg/clamonacc/inotif/hash.c clamav-1.4.6+dfsg/clamonacc/inotif/hash.c --- clamav-1.4.3+dfsg/clamonacc/inotif/hash.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamonacc/inotif/hash.c 2026-08-06 21:12:04.000000000 +0000 @@ -547,7 +547,7 @@ if (NULL == curr->dirname) { logg(LOGG_DEBUG, "ClamHash: node's directory name is NULL!\n"); return CL_ERROR; - } else if (!strncmp(curr->dirname, dirname, n)) { + } else if (strlen(curr->dirname) == n && !memcmp(curr->dirname, dirname, n)) { if (curr->next != NULL) curr->next->prev = curr->prev; if (curr->prev != NULL) diff -Nru clamav-1.4.3+dfsg/clamscan/manager.c clamav-1.4.6+dfsg/clamscan/manager.c --- clamav-1.4.3+dfsg/clamscan/manager.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/clamscan/manager.c 2026-08-06 21:12:04.000000000 +0000 @@ -294,15 +294,21 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, struct cl_scan_options *options) { cl_error_t ret = CL_SUCCESS; - int fd, included; + int fd = -1; + int included = 0; unsigned i; const struct optstruct *opt; const char *virname = NULL; STATBUF sb; - struct metachain chain; - struct clamscan_cb_data data; + struct metachain chain = {0}; + struct clamscan_cb_data data = {0}; + action_source_t action_source; + bool have_action_source = false; + bool have_stat = false; + const char *scan_path = filename; + char *real_filter_path = NULL; - char *real_filename = NULL; + action_source_init(&action_source); if (NULL == filename || NULL == engine || NULL == opts || NULL == options) { logg(LOGG_INFO, "scanfile: Invalid args.\n"); @@ -310,17 +316,13 @@ goto done; } - ret = cli_realpath((const char *)filename, &real_filename); - if (CL_SUCCESS != ret) { - logg(LOGG_DEBUG, "Failed to determine real filename of %s.\n", filename); - logg(LOGG_DEBUG, "Quarantine of the file may fail if file path contains symlinks.\n"); - } else { - filename = real_filename; + if (CL_SUCCESS == cli_realpath(filename, &real_filter_path)) { + scan_path = real_filter_path; } if ((opt = optget(opts, "exclude"))->enabled) { while (opt) { - if (match_regex(filename, opt->strarg) == 1) { + if (match_regex(scan_path, opt->strarg) == 1) { if (!printinfected) logg(LOGG_INFO, "%s: Excluded\n", filename); @@ -335,7 +337,7 @@ included = 0; while (opt) { - if (match_regex(filename, opt->strarg) == 1) { + if (match_regex(scan_path, opt->strarg) == 1) { included = 1; break; } @@ -351,8 +353,44 @@ } } - /* argh, don't scan /proc files */ - if (CLAMSTAT(filename, &sb) != -1) { + if (!action && !have_stat && (CLAMSTAT(scan_path, &sb) != -1)) { + have_stat = true; + } + +#ifdef C_LINUX + if (action && procdev && (CLAMSTAT(scan_path, &sb) != -1) && (sb.st_dev == procdev)) { + if (!printinfected) + logg(LOGG_INFO, "%s: Excluded (/proc)\n", filename); + + goto done; + } +#endif + + if (action) { + /* + * Quarantine actions run on the same opened file object that is + * submitted to the scanner. Open it before file state checks so those + * checks describe the same object, including symlink targets on Windows + * where stat() can report the link entry as an empty file. + */ + ret = action_source_open_path(filename, scan_path, &action_source); + if (CL_SUCCESS != ret) { + logg(LOGG_WARNING, "Can't open file %s for safe quarantine action: %s\n", filename, cl_strerror(ret)); + info.errors++; + goto done; + } + fd = action_source.scan_fd; + have_action_source = true; + + if (action_source.has_stat) { + sb.st_dev = action_source.statbuf.st_dev; + sb.st_size = action_source.statbuf.st_size; + have_stat = true; + } + } + + if (have_stat) { + /* argh, don't scan /proc files */ #ifdef C_LINUX if (procdev && sb.st_dev == procdev) { if (!printinfected) @@ -361,6 +399,7 @@ goto done; } #endif + if (!sb.st_size) { if (!printinfected) logg(LOGG_INFO, "%s: Empty file\n", filename); @@ -372,8 +411,8 @@ } #ifndef _WIN32 - if (geteuid()) { - if (checkaccess(filename, NULL, R_OK) != 1) { + if (geteuid() && !have_action_source) { + if (checkaccess(scan_path, NULL, R_OK) != 1) { if (!printinfected) logg(LOGG_INFO, "%s: Access denied\n", filename); @@ -390,6 +429,7 @@ chain.chains[0] = strdup(filename); if (!chain.chains[0]) { free(chain.chains); + chain.chains = NULL; logg(LOGG_INFO, "Unable to allocate memory in scanfile()\n"); info.errors++; goto done; @@ -400,7 +440,7 @@ logg(LOGG_DEBUG, "Scanning %s\n", filename); - if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) == -1) { + if (!action && (fd = safe_open(scan_path, O_RDONLY | O_BINARY)) == -1) { logg(LOGG_WARNING, "Can't open file %s: %s\n", filename, strerror(errno)); info.errors++; goto done; @@ -436,19 +476,32 @@ info.errors++; } - for (i = 0; i < chain.nchains; i++) - free(chain.chains[i]); - - free(chain.chains); - close(fd); +done: + /* + * Run the action callback if the file was infected. + */ + if (ret == CL_VIRUS && action && have_action_source) { + action(&action_source); + } - if (ret == CL_VIRUS && action) - action(filename); + if (have_action_source) { + action_source_close(&action_source); + fd = -1; + } else if (fd != -1) { + close(fd); + fd = -1; + } -done: - if (NULL != real_filename) { - free(real_filename); + if (NULL != real_filter_path) { + free(real_filter_path); + } + if (NULL != chain.chains) { + for (i = 0; i < chain.nchains; i++) { + free(chain.chains[i]); + } + free(chain.chains); } + return; } @@ -458,6 +511,12 @@ struct dirent *dent; STATBUF sb; char *fname; +#ifdef _WIN32 + char **entries = NULL; + size_t entries_count = 0; + size_t entries_capacity = 0; + size_t entry_index; +#endif int included; const struct optstruct *opt; unsigned int dirlnk, filelnk; @@ -503,6 +562,94 @@ if ((dd = opendir(dirname)) != NULL) { info.dirs++; depth++; +#ifdef _WIN32 + while ((dent = readdir(dd))) { + char **new_entries; + char *entry_name; + + if (!dent->d_ino) { + continue; + } + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) { + continue; + } + + entry_name = strdup(dent->d_name); + if (NULL == entry_name) { + logg(LOGG_ERROR, "scandirs: Memory allocation failed for entry name\n"); + break; + } + + if (entries_count == entries_capacity) { + size_t new_capacity = (0 == entries_capacity) ? 32 : (entries_capacity * 2); + new_entries = realloc(entries, new_capacity * sizeof(*entries)); + if (NULL == new_entries) { + logg(LOGG_ERROR, "scandirs: Memory allocation failed for entries list\n"); + free(entry_name); + break; + } + entries = new_entries; + entries_capacity = new_capacity; + } + + entries[entries_count++] = entry_name; + } + closedir(dd); + dd = NULL; + + for (entry_index = 0; entry_index < entries_count; entry_index++) { + dent = NULL; + fname = malloc(strlen(dirname) + strlen(entries[entry_index]) + 2); + if (fname == NULL) { + logg(LOGG_ERROR, "scandirs: Memory allocation failed for fname\n"); + continue; + } + + if (!strcmp(dirname, PATHSEP)) + sprintf(fname, PATHSEP "%s", entries[entry_index]); + else + sprintf(fname, "%s" PATHSEP "%s", dirname, entries[entry_index]); + + if (LSTAT(fname, &sb) != -1) { + if (!optget(opts, "cross-fs")->enabled) { + if (sb.st_dev != dev) { + if (!printinfected) + logg(LOGG_INFO, "%s: Excluded\n", fname); + + free(fname); + continue; + } + } + if (S_ISLNK(sb.st_mode)) { + if (dirlnk != 2 && filelnk != 2) { + if (!printinfected) + logg(LOGG_INFO, "%s: Symbolic link\n", fname); + } else if (CLAMSTAT(fname, &sb) != -1) { + if (S_ISREG(sb.st_mode) && filelnk == 2) { + scanfile(fname, engine, opts, options); + } else if (S_ISDIR(sb.st_mode) && dirlnk == 2) { + if (recursion) + scandirs(fname, engine, opts, options, depth, dev); + } else { + if (!printinfected) + logg(LOGG_INFO, "%s: Symbolic link\n", fname); + } + } + } else if (S_ISREG(sb.st_mode)) { + scanfile(fname, engine, opts, options); + } else if (S_ISDIR(sb.st_mode) && recursion) { + scandirs(fname, engine, opts, options, depth, dev); + } + } + + free(fname); + } + + for (entry_index = 0; entry_index < entries_count; entry_index++) { + free(entries[entry_index]); + } + free(entries); +#else while ((dent = readdir(dd))) { if (dent->d_ino) { if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { @@ -556,6 +703,7 @@ } } closedir(dd); +#endif } else { if (!printinfected) logg(LOGG_INFO, "%s: Can't open directory.\n", dirname); diff -Nru clamav-1.4.3+dfsg/cmake/FindRust.cmake clamav-1.4.6+dfsg/cmake/FindRust.cmake --- clamav-1.4.3+dfsg/cmake/FindRust.cmake 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/cmake/FindRust.cmake 2026-08-06 21:12:04.000000000 +0000 @@ -471,6 +471,33 @@ list(APPEND CARGO_ARGS "--offline") endif() +string(STRIP "${RUSTFLAGS} $ENV{RUSTFLAGS}" RUSTFLAGS) + +if(RUSTFLAGS MATCHES "(^| )-Zsanitizer=[^ ]+($| )") + if(NOT rustc_VERSION MATCHES "-nightly") + message(FATAL_ERROR + "Rust sanitizer support requires a nightly Rust toolchain because " + "`-Zsanitizer` is unstable." + ) + endif() +endif() + +if(RUSTFLAGS MATCHES "(^| )-Zsanitizer=memory($| )") + if(NOT "${RUST_COMPILER_TARGET}" MATCHES "^(aarch64|x86_64)-unknown-linux-gnu$") + message(FATAL_ERROR + "Rust MemorySanitizer requires a target whose standard library can be " + "rebuilt with `-Zbuild-std`, and `${RUST_COMPILER_TARGET}` is not a " + "supported Rust MSan target. Use a supported Linux target or remove " + "`-Zsanitizer=memory` from RUSTFLAGS." + ) + endif() + + list(APPEND CARGO_ARGS + "-Zbuild-std=core,alloc,std,proc_macro,panic_abort" + "-Zbuild-std-features=panic_immediate_abort" + ) +endif() + if(NOT "${RUST_COMPILER_TARGET}" MATCHES "^universal-apple-darwin$") # Don't specify the target for macOS universal builds, we'll do that manually for each build. list(APPEND CARGO_ARGS "--target" ${RUST_COMPILER_TARGET}) @@ -488,7 +515,7 @@ else() set(CARGO_BUILD_TYPE "debug") endif() -string(STRIP "${RUSTFLAGS} $ENV{RUSTFLAGS}" RUSTFLAGS) +string(STRIP "${RUSTFLAGS}" RUSTFLAGS) find_package_handle_standard_args(Rust REQUIRED_VARS cargo_EXECUTABLE diff -Nru clamav-1.4.3+dfsg/common/actions.c clamav-1.4.6+dfsg/common/actions.c --- clamav-1.4.3+dfsg/common/actions.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/actions.c 2026-08-06 21:12:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2013-2026 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * Copyright (C) 2009-2013 Sourcefire, Inc. * * Author: aCaB, Micah Snyder @@ -27,20 +27,46 @@ #ifdef _WIN32 #include +#include #include +#include + +#ifndef STATUS_OBJECT_NAME_EXISTS +#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS)0x40000000L) +#endif +#ifndef STATUS_ACCESS_DENIED +#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) +#endif +#ifndef STATUS_OBJECT_NAME_COLLISION +#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS)0xC0000035L) +#endif #endif #if HAVE_CONFIG_H #include "clamav-config.h" #endif +#ifdef C_DARWIN +#include +#endif + #include +#include #include +#include +#include #include #include #if HAVE_UNISTD_H #include #endif +#if defined(C_LINUX) && !defined(_WIN32) +#include +#include +#ifndef RENAME_NOREPLACE +#define RENAME_NOREPLACE (1U << 0) +#endif +#endif #include #include #include @@ -55,47 +81,748 @@ #include "misc.h" #include "actions.h" -void (*action)(const char *) = NULL; +void (*action)(const action_source_t *) = NULL; unsigned int notmoved = 0, notremoved = 0; static char *actarget; static int targlen; +#ifndef _WIN32 +static int actarget_fd = -1; +static char *actarget_lockname = NULL; +static int action_unlinkat_nointr(int dirfd, const char *path, int flags); +static int traverse_to(const char *directory, bool want_directory_handle, int *out_handle); +#else +static HANDLE actarget_handle = NULL; +static char *actarget_normalized = NULL; +static int traverse_to(const char *directory, bool want_directory_handle, HANDLE *out_handle); +static size_t win32_path_root_length(const char *path, size_t path_len); +static int win32_open_existing_path(const char *path, bool is_directory, ACCESS_MASK desired_access, HANDLE *out_handle); +static int win32_delete_handle(HANDLE file_handle); +static int win32_delete_dest_name(const char *dest_name); +#endif +static bool action_cleanup_registered = false; +static void action_move(const action_source_t *source); +static void action_copy(const action_source_t *source); +static void action_remove(const action_source_t *source); -static int getdest(const char *fullpath, char **newname) +static int action_fstat_nointr(int fd, STATBUF *st) { - char *tmps, *filename; - int fd, i; + int rc; - tmps = strdup(fullpath); - if (!tmps) { - *newname = NULL; + do { + rc = FSTAT(fd, st); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static void action_cleanup(void) +{ +#ifndef _WIN32 + if ((-1 != actarget_fd) && (NULL != actarget_lockname)) { + if ((0 != action_unlinkat_nointr(actarget_fd, actarget_lockname, 0)) && (ENOENT != errno)) { + logg(LOGG_DEBUG, "action_cleanup: Failed to unlink quarantine lock '%s': %s\n", + actarget_lockname, + strerror(errno)); + } + } + + if (NULL != actarget_lockname) { + free(actarget_lockname); + actarget_lockname = NULL; + } + + if (-1 != actarget_fd) { + close(actarget_fd); + actarget_fd = -1; + } +#else + if ((NULL != actarget_handle) && (INVALID_HANDLE_VALUE != actarget_handle)) { + CloseHandle(actarget_handle); + actarget_handle = NULL; + } + if (NULL != actarget_normalized) { + free(actarget_normalized); + actarget_normalized = NULL; + actarget = NULL; + } +#endif +} + +static int action_close_dest_fd(int *fd) +{ + int close_fd; + + if ((NULL == fd) || (*fd < 0)) { + errno = EBADF; return -1; } - filename = basename(tmps); - if (!(*newname = (char *)malloc(targlen + strlen(filename) + 6))) { - free(tmps); + close_fd = *fd; + *fd = -1; + + return close(close_fd); +} + +#ifndef _WIN32 +static int action_open_nointr(const char *path, int flags) +{ + int fd; + + do { + fd = open(path, flags); + } while ((fd < 0) && (EINTR == errno)); + + return fd; +} + +static int action_openat_nointr(int dirfd, const char *path, int flags, mode_t mode) +{ + int fd; + + do { + fd = openat(dirfd, path, flags, mode); + } while ((fd < 0) && (EINTR == errno)); + + return fd; +} + +static int action_open_flags_with_largefile(int flags) +{ +#ifdef O_LARGEFILE + flags |= O_LARGEFILE; +#endif + return flags; +} + +static int action_directory_open_flags(void) +{ + int flags = O_NOFOLLOW; + +#ifdef O_SEARCH + flags |= O_SEARCH; +#elif defined(O_PATH) + flags |= O_PATH; +#else + flags |= O_RDONLY; +#endif +#ifdef O_DIRECTORY + flags |= O_DIRECTORY; +#endif +#ifdef O_NONBLOCK + flags |= O_NONBLOCK; +#endif + + return flags; +} + +static int action_source_open_flags(void) +{ + int flags = O_RDONLY | O_NOFOLLOW | O_BINARY; + +#ifdef O_NONBLOCK + flags |= O_NONBLOCK; +#endif + + return action_open_flags_with_largefile(flags); +} + +static int action_verify_directory_fd(int fd) +{ + STATBUF statbuf; + + if (0 != FSTAT(fd, &statbuf)) { return -1; } - sprintf(*newname, "%s" PATHSEP "%s", actarget, filename); - for (i = 1; i < 1000; i++) { - fd = open(*newname, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (!S_ISDIR(statbuf.st_mode)) { + errno = ENOTDIR; + return -1; + } + + return 0; +} + +static int action_open_directory_nointr(const char *path) +{ + int fd = action_open_nointr(path, action_directory_open_flags()); + + if (fd >= 0 && 0 != action_verify_directory_fd(fd)) { + close(fd); + fd = -1; + } + + return fd; +} + +static int action_openat_directory_nointr(int dirfd, const char *path) +{ + int fd = action_openat_nointr(dirfd, path, action_directory_open_flags(), 0); + + if (fd >= 0 && 0 != action_verify_directory_fd(fd)) { + close(fd); + fd = -1; + } + + return fd; +} + +static int action_openat_source_nointr(int dirfd, const char *path) +{ + return action_openat_nointr(dirfd, path, action_source_open_flags(), 0); +} + +static int action_mkdirat_nointr(int dirfd, const char *path, mode_t mode) +{ + int rc; + + do { + rc = mkdirat(dirfd, path, mode); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static int action_renameat_nointr(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) +{ + int rc; + + do { + rc = renameat(olddirfd, oldpath, newdirfd, newpath); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static int action_renameat_noreplace_nointr(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) +{ + int rc; + +#if defined(C_DARWIN) + do { + rc = renameatx_np(olddirfd, oldpath, newdirfd, newpath, RENAME_EXCL); + } while ((rc < 0) && (EINTR == errno)); +#elif defined(C_LINUX) && defined(SYS_renameat2) + do { + rc = (int)syscall( + SYS_renameat2, + olddirfd, + oldpath, + newdirfd, + newpath, + RENAME_NOREPLACE); + } while ((rc < 0) && (EINTR == errno)); +#else + UNUSEDPARAM(olddirfd); + UNUSEDPARAM(oldpath); + UNUSEDPARAM(newdirfd); + UNUSEDPARAM(newpath); + errno = ENOTSUP; + rc = -1; +#endif + + return rc; +} + +/** + * @brief Test whether no-replace rename works inside a private directory. + * + * Directory restore after a mismatched private capture depends on an atomic + * rename operation that refuses to overwrite the original basename. The + * expected-stat unlink path probes this before capture because a writable + * directory race can replace the checked regular file with a directory between + * restat and private capture; without no-replace restore, a refused action + * could still hide that directory in the private unlink directory. + * + * @param private_directory_fd Empty private directory fd used for this unlink. + * @return true No-replace rename failed with EEXIST as expected. + * @return false No-replace rename is unavailable or misbehaved. + */ +static bool action_private_dir_supports_noreplace_rename(int private_directory_fd) +{ + const char src_name[] = ".rename-noreplace-src"; + const char dst_name[] = ".rename-noreplace-dst"; + bool supported = false; + + if (private_directory_fd < 0) { + errno = EINVAL; + return false; + } + + if (0 != action_mkdirat_nointr(private_directory_fd, src_name, 0700)) { + return false; + } + + if (0 != action_mkdirat_nointr(private_directory_fd, dst_name, 0700)) { + (void)action_unlinkat_nointr(private_directory_fd, src_name, AT_REMOVEDIR); + return false; + } + + if (0 != action_renameat_noreplace_nointr( + private_directory_fd, + src_name, + private_directory_fd, + dst_name)) { + supported = (EEXIST == errno); + } + + (void)action_unlinkat_nointr(private_directory_fd, src_name, AT_REMOVEDIR); + (void)action_unlinkat_nointr(private_directory_fd, dst_name, AT_REMOVEDIR); + + if (!supported) { + errno = ENOTSUP; + } + + return supported; +} + +static int traverse_to(const char *directory, bool want_directory_handle, int *out_handle); + +#ifndef C_DARWIN +static ssize_t action_read_nointr(int fd, void *buf, size_t count) +{ + ssize_t rc; + + do { + rc = read(fd, buf, count); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static ssize_t action_write_nointr(int fd, const void *buf, size_t count) +{ + ssize_t rc; + + do { + rc = write(fd, buf, count); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} +#endif + +static off_t action_lseek_nointr(int fd, off_t offset, int whence) +{ + off_t rc; + + do { + rc = lseek(fd, offset, whence); + } while (((off_t)-1 == rc) && (EINTR == errno)); + + return rc; +} + +#ifndef C_DARWIN +static int action_ftruncate_nointr(int fd, off_t length) +{ + int rc; + + do { + rc = ftruncate(fd, length); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} +#endif + +static int action_unlinkat_nointr(int dirfd, const char *path, int flags) +{ + int rc; + + do { + rc = unlinkat(dirfd, path, flags); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +#if defined(__FreeBSD__) && defined(HAVE_FUNLINKAT) +static int action_funlinkat_nointr(int dirfd, const char *path, int fd, int flags) +{ + int rc; + + do { + rc = funlinkat(dirfd, path, fd, flags); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} +#endif + +#ifndef _WIN32 +static int action_fstatat_nointr(int dirfd, const char *path, STATBUF *st, int flags) +{ + int rc; + + do { +#if defined(HAVE_STAT64) && STAT64_OK + rc = fstatat64(dirfd, path, st, flags); +#else + rc = fstatat(dirfd, path, st, flags); +#endif + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static int action_validate_actarget_path(void) +{ + STATBUF fd_stat; + STATBUF path_stat; + + /* + * Destination entries are created through actarget_fd, but users see + * actarget/name. Refuse success if actarget no longer names that fd. + */ + if ((-1 == actarget_fd) || (NULL == actarget)) { + errno = EINVAL; + return -1; + } + + if (0 != action_fstat_nointr(actarget_fd, &fd_stat)) { + return -1; + } + + if (0 != CLAMSTAT(actarget, &path_stat)) { + return -1; + } + + if (!S_ISDIR(path_stat.st_mode) || + (path_stat.st_dev != fd_stat.st_dev) || + (path_stat.st_ino != fd_stat.st_ino)) { + errno = EAGAIN; + return -1; + } + + return 0; +} +#endif + +static int action_fchmod_nointr(int fd, mode_t mode) +{ + int rc; + + do { + rc = fchmod(fd, mode); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +#ifdef C_LINUX +static int action_futimens_nointr(int fd, const struct timespec times[2]) +{ + int rc; + + do { + rc = futimens(fd, times); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} +#endif + +static char *action_gen_quarantine_lockname(unsigned int attempt) +{ + int needed; + char *lockname = NULL; + + needed = snprintf(NULL, 0, ".clamav-quarantine-lock.%lu.%u", + (unsigned long)getpid(), + attempt); + if (needed < 0) { + return NULL; + } + + lockname = malloc((size_t)needed + 1); + if (NULL == lockname) { + return NULL; + } + + if (snprintf(lockname, (size_t)needed + 1, ".clamav-quarantine-lock.%lu.%u", + (unsigned long)getpid(), + attempt) != needed) { + free(lockname); + return NULL; + } + + return lockname; +} + +int action_setup_quarantine_lock_at(int directory_fd, const char *directory_path, char **lockname_out) +{ + char *lockname = NULL; + int fd = -1; + unsigned int i; + + if (directory_fd < 0 || NULL == lockname_out) { + return -1; + } + + *lockname_out = NULL; + + /* + * Create the lock relative to the validated directory handle so the lock + * stays bound to the directory we already traversed without following + * symlinks. + */ + for (i = 0; i < 100; i++) { + lockname = action_gen_quarantine_lockname(i); + if (NULL == lockname) { + return -1; + } + + fd = action_openat_nointr(directory_fd, lockname, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_BINARY, 0600); if (fd >= 0) { - free(tmps); - return fd; + if (0 != close(fd)) { + (void)action_unlinkat_nointr(directory_fd, lockname, 0); + free(lockname); + return -1; + } + + *lockname_out = lockname; + return 0; } - if (errno != EEXIST) break; - sprintf(*newname, "%s" PATHSEP "%s.%03u", actarget, filename, i); + + if (EEXIST != errno) { + logg(LOGG_INFO, "action_setup: Failed to create quarantine lock file in %s: %s\n", + (NULL != directory_path) ? directory_path : "(unknown)", + strerror(errno)); + free(lockname); + return -1; + } + + free(lockname); + lockname = NULL; } - free(tmps); - free(*newname); - *newname = NULL; + + logg(LOGG_INFO, "action_setup: Failed to create quarantine lock file in %s after repeated name collisions.\n", + (NULL != directory_path) ? directory_path : "(unknown)"); return -1; } -#ifdef _WIN32 +static int action_setup_quarantine_lock(void) +{ + return action_setup_quarantine_lock_at(actarget_fd, actarget, &actarget_lockname); +} +#endif + +#ifndef _WIN32 +#ifdef C_LINUX +static ssize_t action_flistxattr_nointr(int fd, char *list, size_t size) +{ + ssize_t rc; + + do { + rc = flistxattr(fd, list, size); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static ssize_t action_fgetxattr_nointr(int fd, const char *name, void *value, size_t size) +{ + ssize_t rc; + + do { + rc = fgetxattr(fd, name, value, size); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static int action_fsetxattr_nointr(int fd, const char *name, const void *value, size_t size, int flags) +{ + int rc; + + do { + rc = fsetxattr(fd, name, value, size, flags); + } while ((rc < 0) && (EINTR == errno)); + + return rc; +} + +static int linux_copy_xattrs(int src_fd, int dest_fd) +{ + ssize_t list_size; + char *names = NULL; + char *name = NULL; + int status = -1; + + list_size = action_flistxattr_nointr(src_fd, NULL, 0); + if (list_size < 0) { + if ((ENOTSUP == errno) || (EOPNOTSUPP == errno)) { + return 0; + } + return -1; + } + + if (0 == list_size) { + return 0; + } + + names = malloc((size_t)list_size); + if (NULL == names) { + return -1; + } + + list_size = action_flistxattr_nointr(src_fd, names, (size_t)list_size); + if (list_size < 0) { + if ((ENOTSUP == errno) || (EOPNOTSUPP == errno)) { + status = 0; + goto done; + } + goto done; + } + + for (name = names; name < names + list_size; name += strlen(name) + 1) { + ssize_t value_size; + void *value = NULL; + + value_size = action_fgetxattr_nointr(src_fd, name, NULL, 0); + if (value_size < 0) { + if (ENODATA == errno) { + continue; + } + goto done; + } + + if (value_size > 0) { + value = malloc((size_t)value_size); + if (NULL == value) { + goto done; + } + + value_size = action_fgetxattr_nointr(src_fd, name, value, (size_t)value_size); + if (value_size < 0) { + free(value); + if (ENODATA == errno) { + continue; + } + goto done; + } + } + + if (0 != action_fsetxattr_nointr(dest_fd, name, value, (size_t)((value_size < 0) ? 0 : value_size), 0)) { + int xattr_errno = errno; + + free(value); + + if ((EPERM == xattr_errno) || (EACCES == xattr_errno) || + (ENOTSUP == xattr_errno) || (EOPNOTSUPP == xattr_errno)) { + continue; + } + + errno = xattr_errno; + goto done; + } + + free(value); + } + + status = 0; + +done: + if (NULL != names) { + free(names); + } + + return status; +} + +static int linux_copy_file_metadata(int src_fd, int dest_fd) +{ + STATBUF src_stat; + struct timespec times[2]; + + if (0 != action_fstat_nointr(src_fd, &src_stat)) { + return -1; + } + + times[0] = src_stat.st_atim; + times[1] = src_stat.st_mtim; + if (0 != action_futimens_nointr(dest_fd, times)) { + return -1; + } + + if (0 != linux_copy_xattrs(src_fd, dest_fd)) { + int xattr_errno = errno; + logg(LOGG_DEBUG, "action: Failed to preserve extended attributes: %s\n", + strerror(xattr_errno)); + } + + return 0; +} +#endif + +static int filecopy_to_fd(const action_source_t *source, int dest_fd, STATBUF *src_stat_out) +{ + int src_fd; +#ifdef C_DARWIN +#else + char buf[8192]; + ssize_t got; +#endif + + if ((NULL == source) || (dest_fd < 0) || (source->scan_fd < 0) || (false == source->has_stat)) { + return -1; + } + + src_fd = source->scan_fd; + + if (!S_ISREG(source->statbuf.st_mode)) { + errno = EINVAL; + return -1; + } + + if (action_lseek_nointr(src_fd, 0, SEEK_SET) == (off_t)-1 || + action_lseek_nointr(dest_fd, 0, SEEK_SET) == (off_t)-1) { + return -1; + } + +#ifdef C_DARWIN + if (0 != fcopyfile(src_fd, dest_fd, NULL, COPYFILE_DATA | COPYFILE_XATTR)) { + return -1; + } +#else + while ((got = action_read_nointr(src_fd, buf, sizeof(buf))) > 0) { + size_t off = 0; + + while (off < (size_t)got) { + ssize_t wrote = action_write_nointr(dest_fd, buf + off, (size_t)got - off); + if (wrote <= 0) { + return -1; + } + off += (size_t)wrote; + } + } + + if (got < 0 || + action_ftruncate_nointr(dest_fd, action_lseek_nointr(dest_fd, 0, SEEK_CUR)) != 0 || + action_lseek_nointr(dest_fd, 0, SEEK_SET) == (off_t)-1) { + return -1; + } +#endif + +#ifdef C_LINUX + if (0 != linux_copy_file_metadata(src_fd, dest_fd)) { + return -1; + } +#endif + + if (0 != action_fchmod_nointr(dest_fd, S_IRUSR | S_IWUSR)) { + return -1; + } + + if (NULL != src_stat_out) { + *src_stat_out = source->statbuf; + } -typedef LONG (*PNTCF)( + return 0; +} +#else +typedef NTSTATUS(NTAPI *PNTCF)( PHANDLE FileHandle, // OUT ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, @@ -108,10 +835,1344 @@ PVOID EaBuffer, ULONG EaLength); -typedef void (*PRIUS)( +typedef VOID(NTAPI *PRIUS)( PUNICODE_STRING DestinationString, PCWSTR SourceString); +static ACCESS_MASK win32_directory_anchor_access(void) +{ + /* + * Directory handles are used as validated anchors for later relative + * opens/creates. They need traversal and attributes for validation, but + * not FILE_LIST_DIRECTORY, so drop-box ACLs that deny listing can work. + */ + return SYNCHRONIZE | FILE_TRAVERSE | FILE_READ_ATTRIBUTES; +} + +static HANDLE win32_openat( + HANDLE current_handle, + const char *filename, + PNTCF pNtCreateFile, + PRIUS pRtlInitUnicodeString, + ACCESS_MASK desiredAccess, + ULONG fileAttributes, + ULONG createDisposition, + ULONG createOptions, + ULONG shareAccess); + +static WCHAR *win32_utf8_to_utf16(const char *value) +{ + int value_wchars; + WCHAR *value_w = NULL; + + if (NULL == value) { + return NULL; + } + + value_wchars = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); + if (0 == value_wchars) { + return NULL; + } + + value_w = malloc((size_t)value_wchars * sizeof(WCHAR)); + if (NULL == value_w) { + return NULL; + } + + if (0 == MultiByteToWideChar(CP_UTF8, 0, value, -1, value_w, value_wchars)) { + free(value_w); + return NULL; + } + + return value_w; +} + +static bool win32_is_extended_path_w(const WCHAR *path) +{ + if (NULL == path) { + return false; + } + + return ((0 == wcsncmp(path, L"\\\\?\\", 4)) || + (0 == wcsncmp(path, L"\\\\.\\", 4))); +} + +static bool win32_is_drive_absolute_path_w(const WCHAR *path, size_t path_len) +{ + return (path_len >= 3) && + (((L'A' <= path[0]) && (L'Z' >= path[0])) || ((L'a' <= path[0]) && (L'z' >= path[0]))) && + (L':' == path[1]) && + ((L'\\' == path[2]) || (L'/' == path[2])); +} + +static WCHAR *win32_dup_extended_path_w(const WCHAR *path_w) +{ + size_t path_len; + size_t prefix_len; + size_t result_len; + const WCHAR *prefix = L"\\\\?\\"; + WCHAR *result = NULL; + + if (NULL == path_w) { + return NULL; + } + + if (true == win32_is_extended_path_w(path_w)) { + return _wcsdup(path_w); + } + + path_len = wcslen(path_w); + if (path_len < 2) { + return _wcsdup(path_w); + } + + if ((L'\\' == path_w[0]) && (L'\\' == path_w[1])) { + prefix = L"\\\\?\\UNC\\"; + prefix_len = wcslen(prefix); + result_len = prefix_len + path_len - 2; + result = malloc((result_len + 1) * sizeof(WCHAR)); + if (NULL == result) { + return NULL; + } + + memcpy(result, prefix, prefix_len * sizeof(WCHAR)); + memcpy(result + prefix_len, path_w + 2, (path_len - 1) * sizeof(WCHAR)); + return result; + } + + if (!win32_is_drive_absolute_path_w(path_w, path_len)) { + return _wcsdup(path_w); + } + + prefix_len = wcslen(prefix); + result_len = prefix_len + path_len; + result = malloc((result_len + 1) * sizeof(WCHAR)); + if (NULL == result) { + return NULL; + } + + memcpy(result, prefix, prefix_len * sizeof(WCHAR)); + memcpy(result + prefix_len, path_w, (path_len + 1) * sizeof(WCHAR)); + return result; +} + +static WCHAR *win32_dup_nonextended_path_w(const WCHAR *path_w) +{ + const WCHAR *body = path_w; + + if (NULL == path_w) { + return NULL; + } + + if (0 == wcsncmp(path_w, L"\\\\?\\UNC\\", 8)) { + size_t body_len = wcslen(path_w + 8); + WCHAR *result = malloc((body_len + 3) * sizeof(WCHAR)); + if (NULL == result) { + return NULL; + } + + result[0] = L'\\'; + result[1] = L'\\'; + memcpy(result + 2, path_w + 8, (body_len + 1) * sizeof(WCHAR)); + return result; + } + + if ((0 == wcsncmp(path_w, L"\\\\?\\", 4)) || (0 == wcsncmp(path_w, L"\\\\.\\", 4))) { + body = path_w + 4; + } + + return _wcsdup(body); +} + +static char *win32_utf16_to_utf8(const WCHAR *value) +{ + int value_bytes; + char *value_utf8 = NULL; + + if (NULL == value) { + return NULL; + } + + value_bytes = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL); + if (0 == value_bytes) { + return NULL; + } + + value_utf8 = malloc((size_t)value_bytes); + if (NULL == value_utf8) { + return NULL; + } + + if (0 == WideCharToMultiByte(CP_UTF8, 0, value, -1, value_utf8, value_bytes, NULL, NULL)) { + free(value_utf8); + return NULL; + } + + return value_utf8; +} + +static int win32_copy_handle_data(HANDLE src_handle, HANDLE dest_handle) +{ + BYTE buf[8192]; + DWORD got = 0; + DWORD wrote = 0; + LARGE_INTEGER zero; + + zero.QuadPart = 0; + if (FALSE == SetFilePointerEx(src_handle, zero, NULL, FILE_BEGIN)) { + logg(LOGG_INFO, "win32_copy_handle_data: SetFilePointerEx failed for source handle. Error: %lu\n", GetLastError()); + return -1; + } + if (FALSE == SetFilePointerEx(dest_handle, zero, NULL, FILE_BEGIN)) { + logg(LOGG_INFO, "win32_copy_handle_data: SetFilePointerEx failed for destination handle. Error: %lu\n", GetLastError()); + return -1; + } + + while (TRUE) { + if (FALSE == ReadFile(src_handle, buf, (DWORD)sizeof(buf), &got, NULL)) { + logg(LOGG_INFO, "win32_copy_handle_data: ReadFile failed. Error: %lu\n", GetLastError()); + return -1; + } + + if (0 == got) { + break; + } + + wrote = 0; + if ((FALSE == WriteFile(dest_handle, buf, got, &wrote, NULL)) || (wrote != got)) { + logg(LOGG_INFO, "win32_copy_handle_data: WriteFile failed. Error: %lu, wrote: %lu, expected: %lu\n", GetLastError(), wrote, got); + return -1; + } + } + + return 0; +} + +static int win32_copy_basic_info(HANDLE src_handle, HANDLE dest_handle) +{ + FILE_BASIC_INFO basic_info; + + if (FALSE == GetFileInformationByHandleEx( + src_handle, + FileBasicInfo, + &basic_info, + sizeof(FILE_BASIC_INFO))) { + return -1; + } + + if (FALSE == SetFileInformationByHandle( + dest_handle, + FileBasicInfo, + &basic_info, + sizeof(FILE_BASIC_INFO))) { + return -1; + } + + return 0; +} + +static int win32_open_existing_directory_at(HANDLE current_handle, const char *dirname, HANDLE *out_handle) +{ + HMODULE ntdll = NULL; + PNTCF pNtCreateFile = NULL; + PRIUS pRtlInitUnicodeString = NULL; + HANDLE directory_handle = NULL; + int status = -1; + + if ((NULL == dirname) || (NULL == out_handle)) { + return -1; + } + + ntdll = LoadLibraryA("ntdll.dll"); + if (NULL == ntdll) { + return -1; + } + + pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); + pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); + if ((NULL == pNtCreateFile) || (NULL == pRtlInitUnicodeString)) { + goto done; + } + + directory_handle = win32_openat( + current_handle, + dirname, + pNtCreateFile, + pRtlInitUnicodeString, + win32_directory_anchor_access(), + FILE_ATTRIBUTE_DIRECTORY, + FILE_OPEN, + FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + if ((NULL == directory_handle) || (INVALID_HANDLE_VALUE == directory_handle)) { + goto done; + } + + *out_handle = directory_handle; + directory_handle = NULL; + status = 0; + +done: + if ((NULL != directory_handle) && (INVALID_HANDLE_VALUE != directory_handle)) { + CloseHandle(directory_handle); + } + if (NULL != ntdll) { + FreeLibrary(ntdll); + } + return status; +} + +static int win32_backup_read_exact(HANDLE src_handle, BYTE *buffer, DWORD bytes_to_read, LPVOID *backup_context) +{ + DWORD offset = 0; + + while (offset < bytes_to_read) { + DWORD bytes_read = 0; + + if (FALSE == BackupRead(src_handle, buffer + offset, bytes_to_read - offset, &bytes_read, FALSE, FALSE, backup_context)) { + return -1; + } + if (0 == bytes_read) { + return -1; + } + + offset += bytes_read; + } + + return 0; +} + +static int win32_backup_skip_stream(HANDLE src_handle, LARGE_INTEGER stream_size, LPVOID *backup_context) +{ + BYTE discard[8192]; + + while (stream_size.QuadPart > 0) { + DWORD want; + DWORD skipped_low = 0; + DWORD skipped_high = 0; + + if (stream_size.QuadPart > UINT32_MAX) { + want = UINT32_MAX; + } else { + want = (DWORD)stream_size.QuadPart; + } + + if (BackupSeek(src_handle, want, 0, &skipped_low, &skipped_high, backup_context)) { + ULARGE_INTEGER skipped; + + skipped.LowPart = skipped_low; + skipped.HighPart = skipped_high; + if (0 == skipped.QuadPart) { + return -1; + } + + stream_size.QuadPart -= (LONGLONG)skipped.QuadPart; + continue; + } + + want = (stream_size.QuadPart > (LONGLONG)sizeof(discard)) ? (DWORD)sizeof(discard) : (DWORD)stream_size.QuadPart; + if (0 != win32_backup_read_exact(src_handle, discard, want, backup_context)) { + return -1; + } + stream_size.QuadPart -= want; + } + + return 0; +} + +static int win32_copy_backup_stream_data(HANDLE src_handle, HANDLE dest_handle, LARGE_INTEGER stream_size, LPVOID *backup_context) +{ + BYTE buf[8192]; + + while (stream_size.QuadPart > 0) { + DWORD want = (stream_size.QuadPart > (LONGLONG)sizeof(buf)) ? (DWORD)sizeof(buf) : (DWORD)stream_size.QuadPart; + DWORD got = 0; + DWORD wrote; + + if (FALSE == BackupRead(src_handle, buf, want, &got, FALSE, FALSE, backup_context)) { + return -1; + } + if (0 == got) { + return -1; + } + + wrote = 0; + if ((FALSE == WriteFile(dest_handle, buf, got, &wrote, NULL)) || (wrote != got)) { + return -1; + } + + stream_size.QuadPart -= got; + } + + return 0; +} + +/** + * @brief Create an alternate data stream relative to an opened destination. + * + * Opening the stream from the destination handle keeps ADS copies bound to the + * quarantine file that getdest() already created, instead of reopening a + * basename that another process could replace in the quarantine directory. + * + * @param dest_handle Open handle for the quarantine destination file. + * @param stream_name Name returned by BackupRead(), such as ":ads:$DATA". + * @param[out] out_handle Open handle for the destination stream. + * @return 0 Stream was created. + * @return -1 Stream creation failed. + */ +static int win32_create_dest_stream_handle(HANDLE dest_handle, const char *stream_name, HANDLE *out_handle) +{ + HMODULE ntdll = NULL; + PNTCF pNtCreateFile = NULL; + PRIUS pRtlInitUnicodeString = NULL; + HANDLE stream_handle = NULL; + int status = -1; + + if ((NULL == dest_handle) || (INVALID_HANDLE_VALUE == dest_handle) || + (NULL == stream_name) || (NULL == out_handle)) { + return -1; + } + + ntdll = LoadLibraryA("ntdll.dll"); + if (NULL == ntdll) { + return -1; + } + + pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); + pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); + if ((NULL == pNtCreateFile) || (NULL == pRtlInitUnicodeString)) { + goto done; + } + + stream_handle = win32_openat( + dest_handle, + stream_name, + pNtCreateFile, + pRtlInitUnicodeString, + FILE_WRITE_DATA | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_CREATE, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + if ((NULL == stream_handle) || (INVALID_HANDLE_VALUE == stream_handle)) { + goto done; + } + + *out_handle = stream_handle; + stream_handle = NULL; + status = 0; + +done: + if ((NULL != stream_handle) && (INVALID_HANDLE_VALUE != stream_handle)) { + CloseHandle(stream_handle); + } + if (NULL != ntdll) { + FreeLibrary(ntdll); + } + return status; +} + +static int win32_copy_alternate_streams(HANDLE src_handle, HANDLE dest_handle) +{ + LPVOID backup_context = NULL; + const DWORD stream_id_size = (DWORD)offsetof(WIN32_STREAM_ID, cStreamName); + WIN32_STREAM_ID stream_id; + LARGE_INTEGER zero; + int status = -1; + + if ((NULL == src_handle) || (INVALID_HANDLE_VALUE == src_handle) || + (NULL == dest_handle) || (INVALID_HANDLE_VALUE == dest_handle)) { + return -1; + } + + zero.QuadPart = 0; + if (FALSE == SetFilePointerEx(src_handle, zero, NULL, FILE_BEGIN)) { + return -1; + } + + while (TRUE) { + WCHAR *stream_name_w = NULL; + char *stream_name_utf8 = NULL; + HANDLE dest_stream_handle = INVALID_HANDLE_VALUE; + DWORD bytes_read = 0; + + if (FALSE == BackupRead(src_handle, (BYTE *)&stream_id, stream_id_size, &bytes_read, FALSE, FALSE, &backup_context)) { + goto done; + } + + if (0 == bytes_read) { + status = 0; + goto done; + } + + if (bytes_read != stream_id_size) { + goto done; + } + + if (0 != stream_id.dwStreamNameSize) { + size_t stream_name_chars; + + if (0 != (stream_id.dwStreamNameSize % sizeof(WCHAR))) { + goto done; + } + + stream_name_chars = stream_id.dwStreamNameSize / sizeof(WCHAR); + if (stream_name_chars > (SIZE_MAX / sizeof(WCHAR)) - 1) { + goto done; + } + + stream_name_w = malloc((stream_name_chars + 1) * sizeof(WCHAR)); + if (NULL == stream_name_w) { + goto done; + } + + if (0 != win32_backup_read_exact(src_handle, (BYTE *)stream_name_w, stream_id.dwStreamNameSize, &backup_context)) { + free(stream_name_w); + goto done; + } + stream_name_w[stream_name_chars] = L'\0'; + } + + if ((BACKUP_ALTERNATE_DATA == stream_id.dwStreamId) && + (NULL != stream_name_w) && + (L'\0' != stream_name_w[0])) { + stream_name_utf8 = win32_utf16_to_utf8(stream_name_w); + if (NULL == stream_name_utf8) { + free(stream_name_w); + goto done; + } + + if (0 != win32_create_dest_stream_handle(dest_handle, stream_name_utf8, &dest_stream_handle) || + 0 != win32_copy_backup_stream_data(src_handle, dest_stream_handle, stream_id.Size, &backup_context)) { + if ((NULL != dest_stream_handle) && (INVALID_HANDLE_VALUE != dest_stream_handle)) { + CloseHandle(dest_stream_handle); + } + free(stream_name_utf8); + free(stream_name_w); + goto done; + } + + CloseHandle(dest_stream_handle); + free(stream_name_utf8); + } else if (0 != win32_backup_skip_stream(src_handle, stream_id.Size, &backup_context)) { + free(stream_name_w); + goto done; + } + + free(stream_name_w); + } + +done: + if (NULL != backup_context) { + DWORD bytes_read = 0; + (void)BackupRead(src_handle, NULL, 0, &bytes_read, TRUE, FALSE, &backup_context); + } + + return status; +} + +static int filecopy_to_fd(const action_source_t *source, const char *dest_path, int dest_fd) +{ + const char *src = NULL; + HANDLE src_handle = INVALID_HANDLE_VALUE; + HANDLE dest_handle = INVALID_HANDLE_VALUE; + int status = -1; + + if ((NULL == source) || (NULL == dest_path) || (dest_fd < 0)) { + return -1; + } + + src = (NULL != source->action_path) ? source->action_path : source->display_path; + src_handle = (HANDLE)source->handle; + if ((NULL == src) || (NULL == src_handle) || (INVALID_HANDLE_VALUE == src_handle)) { + return -1; + } + + dest_handle = (HANDLE)_get_osfhandle(dest_fd); + if ((NULL == dest_handle) || (INVALID_HANDLE_VALUE == dest_handle)) { + logg(LOGG_INFO, "filecopy_to_fd: Failed to get destination handle for '%s'.\n", dest_path); + goto done; + } + + if (0 != win32_copy_handle_data(src_handle, dest_handle)) { + logg(LOGG_INFO, "filecopy_to_fd: Failed copying unnamed stream for '%s'. Error: %lu\n", src, GetLastError()); + goto done; + } + + if (0 != win32_copy_alternate_streams(src_handle, dest_handle)) { + logg(LOGG_INFO, "filecopy_to_fd: Failed copying alternate data streams for '%s'. Error: %lu\n", src, GetLastError()); + goto done; + } + + if (0 != win32_copy_basic_info(src_handle, dest_handle)) { + logg(LOGG_INFO, "filecopy_to_fd: Failed copying basic file info for '%s'. Error: %lu\n", src, GetLastError()); + goto done; + } + + status = 0; + +done: + return status; +} + +static int win32_delete_handle(HANDLE file_handle) +{ + FILE_DISPOSITION_INFO file_info = {0}; + + if ((NULL == file_handle) || (INVALID_HANDLE_VALUE == file_handle)) { + return -1; + } + + file_info.DeleteFile = TRUE; + if (FALSE == SetFileInformationByHandle( + file_handle, + FileDispositionInfo, + &file_info, + sizeof(FILE_DISPOSITION_INFO))) { + return -1; + } + + return 0; +} + +static ACCESS_MASK win32_source_scan_desired_access(void) +{ + return FILE_GENERIC_READ | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE; +} + +/** + * @brief Check whether the selected action will remove the source file. + * + * @return true The source file must be deleted after a detection. + * @return false The source file is only copied or inspected. + */ +static bool win32_source_action_needs_delete_access(void) +{ + return (action == action_move) || (action == action_remove); +} + +static int win32_same_file_handle(HANDLE first_handle, HANDLE second_handle) +{ + BY_HANDLE_FILE_INFORMATION first_info; + BY_HANDLE_FILE_INFORMATION second_info; + + if ((NULL == first_handle) || (INVALID_HANDLE_VALUE == first_handle) || + (NULL == second_handle) || (INVALID_HANDLE_VALUE == second_handle)) { + SetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + if (FALSE == GetFileInformationByHandle(first_handle, &first_info)) { + return -1; + } + if (FALSE == GetFileInformationByHandle(second_handle, &second_info)) { + return -1; + } + + if ((first_info.dwVolumeSerialNumber != second_info.dwVolumeSerialNumber) || + (first_info.nFileIndexHigh != second_info.nFileIndexHigh) || + (first_info.nFileIndexLow != second_info.nFileIndexLow)) { + SetLastError(ERROR_FILE_NOT_FOUND); + return -1; + } + + return 0; +} + +static int win32_open_delete_handle_for_source( + const char *target, + HANDLE source_handle, + HANDLE *out_handle) +{ + HANDLE delete_handle = INVALID_HANDLE_VALUE; + int status = -1; + + if ((NULL == target) || (NULL == out_handle)) { + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + + if (0 != win32_open_existing_path( + target, + false, + DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + &delete_handle)) { + goto done; + } + + if ((NULL != source_handle) && (INVALID_HANDLE_VALUE != source_handle) && + (0 != win32_same_file_handle(source_handle, delete_handle))) { + goto done; + } + + *out_handle = delete_handle; + delete_handle = INVALID_HANDLE_VALUE; + status = 0; + +done: + if (INVALID_HANDLE_VALUE != delete_handle) { + CloseHandle(delete_handle); + } + return status; +} + +static int win32_delete_dest_name(const char *dest_name) +{ + HMODULE ntdll = NULL; + PNTCF pNtCreateFile = NULL; + PRIUS pRtlInitUnicodeString = NULL; + HANDLE delete_handle = NULL; + int status = -1; + + if ((NULL == dest_name) || (NULL == actarget_handle)) { + return -1; + } + + ntdll = LoadLibraryA("ntdll.dll"); + if (NULL == ntdll) { + return -1; + } + + pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); + pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); + if ((NULL == pNtCreateFile) || (NULL == pRtlInitUnicodeString)) { + goto done; + } + + delete_handle = win32_openat( + actarget_handle, + dest_name, + pNtCreateFile, + pRtlInitUnicodeString, + DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + if ((NULL == delete_handle) || (INVALID_HANDLE_VALUE == delete_handle)) { + goto done; + } + + status = win32_delete_handle(delete_handle); + +done: + if ((NULL != delete_handle) && (INVALID_HANDLE_VALUE != delete_handle)) { + CloseHandle(delete_handle); + } + if (NULL != ntdll) { + FreeLibrary(ntdll); + } + return status; +} + +static int win32_delete_dest_path(const char *dest_path) +{ + const char *slash; + const char *backslash; + const char *dest_name; + + if (NULL == dest_path) { + return -1; + } + + slash = strrchr(dest_path, '/'); + backslash = strrchr(dest_path, '\\'); + if ((NULL != slash) && ((NULL == backslash) || (slash > backslash))) { + dest_name = slash + 1; + } else if (NULL != backslash) { + dest_name = backslash + 1; + } else { + dest_name = dest_path; + } + + return win32_delete_dest_name(dest_name); +} + +static char *win32_parent_path_dup(const char *path) +{ + char *copy = NULL; + char *slash = NULL; + char *backslash = NULL; + char *last_sep = NULL; + size_t path_len = 0; + size_t root_len = 0; + + if (NULL == path) { + return NULL; + } + + copy = strdup(path); + if (NULL == copy) { + return NULL; + } + + path_len = strlen(copy); + root_len = win32_path_root_length(copy, path_len); + + slash = strrchr(copy, '/'); + backslash = strrchr(copy, '\\'); + last_sep = (slash > backslash) ? slash : backslash; + if (NULL == last_sep) { + free(copy); + return strdup("."); + } + + if ((0 != root_len) && ((size_t)(last_sep - copy) < root_len)) { + copy[root_len] = '\0'; + } else { + *last_sep = '\0'; + } + + return copy; +} + +static bool win32_path_is_separator(char c) +{ + return ('/' == c) || ('\\' == c); +} + +static bool win32_path_is_drive_letter(char c) +{ + return (('A' <= c) && ('Z' >= c)) || (('a' <= c) && ('z' >= c)); +} + +static bool win32_path_ascii_equal_ignore_case(char lhs, char rhs) +{ + if (('A' <= lhs) && ('Z' >= lhs)) { + lhs = (char)(lhs - 'A' + 'a'); + } + if (('A' <= rhs) && ('Z' >= rhs)) { + rhs = (char)(rhs - 'A' + 'a'); + } + + return lhs == rhs; +} + +static bool win32_path_match_ignore_case(const char *path, size_t path_len, size_t pos, const char *expected) +{ + size_t i = 0; + + if ((NULL == path) || (NULL == expected)) { + return false; + } + + while ('\0' != expected[i]) { + if ((pos + i >= path_len) || + !win32_path_ascii_equal_ignore_case(path[pos + i], expected[i])) { + return false; + } + i++; + } + + return true; +} + +static bool win32_path_has_extended_prefix(const char *path, size_t path_len) +{ + return (path_len >= 4) && + win32_path_is_separator(path[0]) && + win32_path_is_separator(path[1]) && + ('?' == path[2]) && + win32_path_is_separator(path[3]); +} + +static bool win32_path_has_extended_unc_prefix(const char *path, size_t path_len) +{ + return (path_len >= 8) && + win32_path_has_extended_prefix(path, path_len) && + (('U' == path[4]) || ('u' == path[4])) && + (('N' == path[5]) || ('n' == path[5])) && + (('C' == path[6]) || ('c' == path[6])) && + win32_path_is_separator(path[7]); +} + +static size_t win32_path_extended_volume_root_length(const char *path, size_t path_len) +{ + size_t pos = 4; + + if (!win32_path_has_extended_prefix(path, path_len) || + !win32_path_match_ignore_case(path, path_len, pos, "Volume{")) { + return 0; + } + pos += sizeof("Volume{") - 1; + + while ((pos < path_len) && + ('}' != path[pos]) && + !win32_path_is_separator(path[pos])) { + pos++; + } + + if ((pos >= path_len) || ('}' != path[pos])) { + return 0; + } + pos++; + + if ((pos < path_len) && win32_path_is_separator(path[pos])) { + return pos + 1; + } + + return path_len; +} + +static size_t win32_path_root_length(const char *path, size_t path_len) +{ + size_t pos = 0; + size_t volume_root_len = 0; + + if ((NULL == path) || (0 == path_len)) { + return 0; + } + + /* Extended drive root, such as "\\?\C:\". */ + if ((path_len >= 7) && + win32_path_is_separator(path[0]) && + win32_path_is_separator(path[1]) && + ('?' == path[2]) && + win32_path_is_separator(path[3]) && + win32_path_is_drive_letter(path[4]) && + (':' == path[5]) && + win32_path_is_separator(path[6])) { + return 7; + } + + /* Normal drive root, such as "C:\". */ + if ((path_len >= 3) && + win32_path_is_drive_letter(path[0]) && + (':' == path[1]) && + win32_path_is_separator(path[2])) { + return 3; + } + + /* + * Drive-qualified paths, such as "C:" or "C:dir". The root prefix is + * only the drive designator, but trimming must not remove it. + */ + if ((path_len >= 2) && + win32_path_is_drive_letter(path[0]) && + (':' == path[1])) { + return 2; + } + + volume_root_len = win32_path_extended_volume_root_length(path, path_len); + if (0 != volume_root_len) { + return volume_root_len; + } + + if ((path_len >= 2) && + win32_path_is_separator(path[0]) && + win32_path_is_separator(path[1])) { + pos = 2; + if (win32_path_has_extended_unc_prefix(path, path_len)) { + /* Extended UNC root, such as "\\?\UNC\server\share\". */ + pos = 8; + } else if ((path_len >= 4) && + win32_path_has_extended_prefix(path, path_len)) { + /* Generic extended namespace prefix, such as "\\?\". */ + return 4; + } + + /* Skip leading separators, including repeated slashes. */ + while ((pos < path_len) && win32_path_is_separator(path[pos])) { + pos++; + } + /* Skip the UNC server name in "\\server\share\". */ + while ((pos < path_len) && !win32_path_is_separator(path[pos])) { + pos++; + } + if (pos >= path_len) { + return path_len; + } + /* Skip separators between the server and share names. */ + while ((pos < path_len) && win32_path_is_separator(path[pos])) { + pos++; + } + /* Skip the UNC share name. */ + while ((pos < path_len) && !win32_path_is_separator(path[pos])) { + pos++; + } + if ((pos < path_len) && win32_path_is_separator(path[pos])) { + /* Preserve the separator that terminates "\\server\share\". */ + return pos + 1; + } + return path_len; + } + + /* Current-drive absolute root, such as "\Windows". */ + if (win32_path_is_separator(path[0])) { + return 1; + } + + return 0; +} + +static char *win32_trim_trailing_path_separators_dup(const char *path) +{ + char *trimmed = NULL; + size_t path_len = 0; + size_t root_len = 0; + size_t trim_len = 0; + + if (NULL == path) { + return NULL; + } + + path_len = strlen(path); + root_len = win32_path_root_length(path, path_len); + trim_len = path_len; + + while ((trim_len > root_len) && win32_path_is_separator(path[trim_len - 1])) { + trim_len--; + } + + trimmed = malloc(trim_len + 1); + if (NULL == trimmed) { + return NULL; + } + + memcpy(trimmed, path, trim_len); + trimmed[trim_len] = '\0'; + + return trimmed; +} + +static WCHAR *win32_normalize_full_path_w(const char *path) +{ + WCHAR *path_w = NULL; + WCHAR *extended_w = NULL; + WCHAR *normalized_w = NULL; + DWORD normalized_len = 0; + + path_w = win32_utf8_to_utf16(path); + if (NULL == path_w) { + return NULL; + } + + extended_w = win32_dup_extended_path_w(path_w); + free(path_w); + if (NULL == extended_w) { + return NULL; + } + + normalized_len = GetFullPathNameW(extended_w, 0, NULL, NULL); + if (0 == normalized_len) { + free(extended_w); + return NULL; + } + + normalized_w = malloc((size_t)normalized_len * sizeof(WCHAR)); + if (NULL == normalized_w) { + free(extended_w); + return NULL; + } + + if (0 == GetFullPathNameW(extended_w, normalized_len, normalized_w, NULL)) { + free(normalized_w); + free(extended_w); + return NULL; + } + + free(extended_w); + extended_w = win32_dup_nonextended_path_w(normalized_w); + free(normalized_w); + return extended_w; +} + +static WCHAR *win32_get_final_path_no_prefix_w(HANDLE handle) +{ + WCHAR *final_w = NULL; + WCHAR *trimmed_w = NULL; + DWORD final_len = 0; + DWORD copied_len = 0; + DWORD buffer_len = 0; + const WCHAR *body = NULL; + + final_len = GetFinalPathNameByHandleW(handle, NULL, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + if (0 == final_len) { + return NULL; + } + buffer_len = final_len + 1; + if (buffer_len <= final_len) { + return NULL; + } + + final_w = malloc((size_t)buffer_len * sizeof(WCHAR)); + if (NULL == final_w) { + return NULL; + } + + copied_len = GetFinalPathNameByHandleW(handle, final_w, buffer_len, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + if ((0 == copied_len) || (copied_len >= buffer_len)) { + free(final_w); + return NULL; + } + final_w[copied_len] = L'\0'; + + trimmed_w = win32_dup_nonextended_path_w(final_w); + free(final_w); + return trimmed_w; +} + +static int win32_reject_reparse_handle(HANDLE handle) +{ + FILE_ATTRIBUTE_TAG_INFO tag_info = {0}; + + if (0 == GetFileInformationByHandleEx( + handle, + FileAttributeTagInfo, + &tag_info, + sizeof(FILE_ATTRIBUTE_TAG_INFO))) { + return -1; + } + + if (0 != (tag_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + return -1; + } + + return 0; +} + +static int win32_validate_opened_path(HANDLE handle, const char *expected_path) +{ + WCHAR *expected_w = NULL; + WCHAR *actual_w = NULL; + int status = -1; + + expected_w = win32_normalize_full_path_w(expected_path); + if (NULL == expected_w) { + goto done; + } + + actual_w = win32_get_final_path_no_prefix_w(handle); + if (NULL == actual_w) { + goto done; + } + + /* + * Keep this validation conservative. GetFullPathNameW() may preserve an + * 8.3 alias while GetFinalPathNameByHandleW() reports the long path, so + * valid short-name aliases can be rejected. Failing quarantine setup is + * preferable to accepting a path spelling we cannot prove still names the + * opened object. + */ + if (0 != _wcsicmp(expected_w, actual_w)) { + goto done; + } + + if (0 != win32_reject_reparse_handle(handle)) { + goto done; + } + + status = 0; + +done: + if (NULL != expected_w) { + free(expected_w); + } + if (NULL != actual_w) { + free(actual_w); + } + return status; +} + +static int action_validate_actarget_path(void) +{ + /* + * Destination entries are created through actarget_handle, but users see + * actarget/name. Refuse success if actarget no longer names that handle. + */ + if ((NULL == actarget) || (NULL == actarget_handle) || + (INVALID_HANDLE_VALUE == actarget_handle)) { + errno = EINVAL; + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + + if (0 != win32_validate_opened_path(actarget_handle, actarget)) { + errno = EAGAIN; + SetLastError(ERROR_FILE_NOT_FOUND); + return -1; + } + + return 0; +} + +static int win32_open_existing_path(const char *path, bool is_directory, ACCESS_MASK desired_access, HANDLE *out_handle) +{ + WCHAR *path_w = NULL; + WCHAR *extended_path_w = NULL; + HANDLE handle = INVALID_HANDLE_VALUE; + DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT; + int status = -1; + + if ((NULL == path) || (NULL == out_handle)) { + return -1; + } + + path_w = win32_utf8_to_utf16(path); + if (NULL == path_w) { + return -1; + } + + extended_path_w = win32_dup_extended_path_w(path_w); + if (NULL == extended_path_w) { + goto done; + } + + if (true == is_directory) { + flags |= FILE_FLAG_BACKUP_SEMANTICS; + } + + handle = CreateFileW( + extended_path_w, + desired_access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + flags, + NULL); + if (INVALID_HANDLE_VALUE == handle) { + goto done; + } + + if (0 != win32_validate_opened_path(handle, path)) { + SetLastError(ERROR_ACCESS_DENIED); + CloseHandle(handle); + handle = INVALID_HANDLE_VALUE; + goto done; + } + + *out_handle = handle; + handle = INVALID_HANDLE_VALUE; + status = 0; + +done: + if (INVALID_HANDLE_VALUE != handle) { + CloseHandle(handle); + } + if (NULL != path_w) { + free(path_w); + } + if (NULL != extended_path_w) { + free(extended_path_w); + } + return status; +} + +/** + * @brief Open the Windows quarantine source with the requested access mask. + * + * @param path Source path to open. + * @param require_resolved_path Whether to validate the opened path. + * @param desired_access Windows access mask requested for the handle. + * @param out_handle Opened source handle on success. + * @return 0 Source handle opened. + * @return -1 Source handle could not be opened. + */ +static int win32_open_source_handle_with_access( + const char *path, + bool require_resolved_path, + ACCESS_MASK desired_access, + HANDLE *out_handle) +{ + WCHAR *path_w = NULL; + WCHAR *extended_path_w = NULL; + HANDLE handle = INVALID_HANDLE_VALUE; + int status = -1; + + if ((NULL == path) || (NULL == out_handle)) { + return -1; + } + + if (require_resolved_path) { + return win32_open_existing_path(path, false, desired_access, out_handle); + } + + path_w = win32_utf8_to_utf16(path); + if (NULL == path_w) { + return -1; + } + + extended_path_w = win32_dup_extended_path_w(path_w); + if (NULL == extended_path_w) { + goto done; + } + + handle = CreateFileW( + extended_path_w, + desired_access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (INVALID_HANDLE_VALUE == handle) { + goto done; + } + + *out_handle = handle; + handle = INVALID_HANDLE_VALUE; + status = 0; + +done: + if (INVALID_HANDLE_VALUE != handle) { + CloseHandle(handle); + } + if (NULL != path_w) { + free(path_w); + } + if (NULL != extended_path_w) { + free(extended_path_w); + } + return status; +} + +/** + * @brief Open a Windows quarantine source for scanning. + * + * Move/remove actions first try to retain DELETE access on the scan source. + * If that fails, fall back to a read-only scan handle so quarantine-action + * permission failures do not suppress detection. + * + * @param path Source path to open. + * @param require_resolved_path Whether to validate the opened path. + * @param out_handle Opened source handle on success. + * @param out_handle_can_delete Whether the opened handle has DELETE access. + * @return 0 Source handle opened. + * @return -1 Source handle could not be opened. + */ +static int win32_open_source_handle( + const char *path, + bool require_resolved_path, + HANDLE *out_handle, + bool *out_handle_can_delete) +{ + ACCESS_MASK desired_access = win32_source_scan_desired_access(); + + if ((NULL == out_handle) || (NULL == out_handle_can_delete)) { + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + + *out_handle = INVALID_HANDLE_VALUE; + *out_handle_can_delete = false; + + if (win32_source_action_needs_delete_access() && + (0 == win32_open_source_handle_with_access( + path, + require_resolved_path, + desired_access | DELETE, + out_handle))) { + *out_handle_can_delete = true; + return 0; + } + + return win32_open_source_handle_with_access( + path, + require_resolved_path, + desired_access, + out_handle); +} + /** * @brief An openat equivalent for Win32 with a check to NOFOLLOW soft-links. * @@ -126,6 +2187,7 @@ * @param pRtlInitUnicodeString A function pointer to the RtlInitUnicodeString Win32 Native API. * @param desiredAccess The DesiredAccess option for NtCreateFile * @param fileAttributes The FileAttributes option for NtCreateFile + * @param createDisposition The CreateDisposition option for NtCreateFile * @param createOptions The CreateOptions option for NtCreateFile * @param shareAccess The ShareAccess option for NtCreateFile * @return HANDLE A handle on success, NULL on failure. @@ -137,6 +2199,7 @@ PRIUS pRtlInitUnicodeString, ACCESS_MASK desiredAccess, ULONG fileAttributes, + ULONG createDisposition, ULONG createOptions, ULONG shareAccess) { @@ -178,16 +2241,32 @@ 0, // AllocationSize fileAttributes, // FileAttributes shareAccess, // ShareAccess - FILE_OPEN, // CreateDisposition - createOptions, // CreateOptions - NULL, // EaBuffer - 0); // EaLength + createDisposition, + createOptions, // CreateOptions + NULL, // EaBuffer + 0); // EaLength if (!NT_SUCCESS(ntStatus) || (NULL == next_handle)) { + switch (ntStatus) { + case STATUS_OBJECT_NAME_COLLISION: + case STATUS_OBJECT_NAME_EXISTS: + errno = EEXIST; + break; + case STATUS_ACCESS_DENIED: + errno = EACCES; + break; + default: + errno = EIO; + break; + } logg(LOGG_INFO, "win32_openat: Failed to open file '%s'. \nError: 0x%x \nioStatusBlock: 0x%x\n", filename, ntStatus, ioStatusBlock.Information); goto done; } logg(LOGG_DEBUG, "win32_openat: Opened file \"%s\"\n", filename); + if (FILE_CREATE == createDisposition) { + goto done; + } + if (0 == GetFileInformationByHandleEx( next_handle, // hFile, FileAttributeTagInfo, // FileInformationClass @@ -217,6 +2296,603 @@ return next_handle; } + +static int win32_create_dest_file(const char *dest_basename) +{ + HMODULE ntdll = NULL; + PNTCF pNtCreateFile = NULL; + PRIUS pRtlInitUnicodeString = NULL; + HANDLE dest_handle = NULL; + int fd = -1; + + if ((NULL == dest_basename) || (NULL == actarget_handle)) { + return -1; + } + + ntdll = LoadLibraryA("ntdll.dll"); + if (NULL == ntdll) { + return -1; + } + + pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); + pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); + if ((NULL == pNtCreateFile) || (NULL == pRtlInitUnicodeString)) { + FreeLibrary(ntdll); + return -1; + } + + dest_handle = win32_openat( + actarget_handle, + dest_basename, + pNtCreateFile, + pRtlInitUnicodeString, + FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_CREATE, + FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + if ((NULL == dest_handle) || (INVALID_HANDLE_VALUE == dest_handle)) { + FreeLibrary(ntdll); + return -1; + } + + fd = _open_osfhandle((intptr_t)dest_handle, _O_WRONLY | _O_BINARY); + if (fd < 0) { + CloseHandle(dest_handle); + (void)win32_delete_dest_name(dest_basename); + } + + FreeLibrary(ntdll); + return fd; +} +#endif + +void action_source_init(action_source_t *source) +{ + if (NULL == source) { + return; + } + + memset(source, 0, sizeof(*source)); + source->scan_fd = -1; +#ifdef _WIN32 + source->handle = INVALID_HANDLE_VALUE; +#endif +} + +static cl_error_t action_source_set_display_path(action_source_t *source, const char *display_path) +{ + source->display_path = strdup(display_path); + if (NULL == source->display_path) { + return CL_EMEM; + } + + return CL_SUCCESS; +} + +#ifndef _WIN32 +static cl_error_t action_source_absolute_path_dup(const char *path, char **absolute_path) +{ + char cwd[PATH_MAX + 1]; + + if ((NULL == path) || (NULL == absolute_path)) { + return CL_EARG; + } + + *absolute_path = NULL; + + if (cli_is_abspath(path)) { + *absolute_path = strdup(path); + } else { + if (NULL == getcwd(cwd, sizeof(cwd))) { + return CL_EOPEN; + } + + *absolute_path = cli_newfilepath(cwd, path); + } + + return (NULL == *absolute_path) ? CL_EMEM : CL_SUCCESS; +} + +static cl_error_t action_source_fallback_action_path_dup(const char *path, char **action_path) +{ + cl_error_t status; + + if ((NULL == path) || (NULL == action_path)) { + return CL_EARG; + } + + *action_path = NULL; + + status = cli_realpath(path, action_path); + if ((CL_SUCCESS == status) && (NULL != *action_path)) { + return CL_SUCCESS; + } + + if (NULL != *action_path) { + free(*action_path); + *action_path = NULL; + } + + if ((action == action_move) || (action == action_remove)) { + return (CL_SUCCESS == status) ? CL_EOPEN : status; + } + + return action_source_absolute_path_dup(path, action_path); +} + +static cl_error_t action_source_populate_posix( + action_source_t *source, + int fd, + const char *open_path, + bool open_path_is_resolved) +{ + cl_error_t status = CL_EOPEN; + + if (0 != action_fstat_nointr(fd, &source->statbuf)) { + goto done; + } + source->has_stat = true; + + if (!S_ISREG(source->statbuf.st_mode)) { + errno = EINVAL; + status = CL_EOPEN; + goto done; + } + + if (open_path_is_resolved) { + /* + * Descriptor path lookup can return another name for the same file + * when it has multiple hard links. Preserve the path that was + * explicitly resolved and securely opened for path-based actions. + */ + status = action_source_absolute_path_dup(open_path, &source->action_path); + if (CL_SUCCESS == status) { + cli_dbgmsg("action_source_populate_posix: Resolved action path for fd [%d] is: %s\n", + fd, source->action_path); + } + goto done; + } + + status = cli_get_filepath_from_filedesc(fd, &source->action_path); + if (CL_SUCCESS != status) { + /* + * Some supported POSIX targets cannot derive a path from an open fd, + * and Linux can also fail here when /proc/self/fd is unavailable. Fall + * back to an absolute version of the submitted display path only for + * those path-resolution failures. The opened fd remains the source for + * scan/copy bytes, and move/remove still verify the path against the + * recorded stat before unlinking. + */ + if ((CL_BREAK != status) && (CL_EOPEN != status)) { + goto done; + } + + status = action_source_fallback_action_path_dup(open_path, &source->action_path); + if (CL_SUCCESS != status) { + goto done; + } + } + + status = CL_SUCCESS; + +done: + return status; +} + +static cl_error_t action_source_open_posix_path(const char *open_path, bool require_resolved_path, int *fd) +{ + if ((NULL == open_path) || (NULL == fd)) { + return CL_EARG; + } + + *fd = -1; + + if (require_resolved_path) { + if (!cli_is_abspath(open_path)) { + return CL_EOPEN; + } + + if (0 != traverse_to(open_path, false, fd)) { + return CL_EOPEN; + } + } else { + *fd = safe_open(open_path, action_source_open_flags()); + if (*fd < 0) { + return CL_EOPEN; + } + } + + return CL_SUCCESS; +} +#else +static cl_error_t action_source_populate_win32( + action_source_t *source, + HANDLE source_handle, + bool source_handle_can_delete) +{ + HANDLE scan_handle = INVALID_HANDLE_VALUE; + cl_error_t status = CL_EOPEN; + + if (FALSE == DuplicateHandle( + GetCurrentProcess(), + source_handle, + GetCurrentProcess(), + &scan_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + goto done; + } + + source->scan_fd = _open_osfhandle((intptr_t)scan_handle, _O_RDONLY | _O_BINARY); + if (source->scan_fd < 0) { + CloseHandle(scan_handle); + goto done; + } + scan_handle = INVALID_HANDLE_VALUE; + + if (0 != action_fstat_nointr(source->scan_fd, &source->statbuf)) { + goto done; + } + source->has_stat = true; + + if (!S_ISREG(source->statbuf.st_mode)) { + errno = EINVAL; + status = CL_EOPEN; + goto done; + } + + status = cli_get_filepath_from_handle(source_handle, &source->action_path); + if (CL_SUCCESS != status) { + goto done; + } + + source->handle = source_handle; + source->handle_can_delete = source_handle_can_delete; + status = CL_SUCCESS; + +done: + if (INVALID_HANDLE_VALUE != scan_handle) { + CloseHandle(scan_handle); + } + return status; +} +#endif + +static cl_error_t action_source_open_path_impl(const char *display_path, const char *open_path, action_source_t *source, bool require_resolved_path) +{ + cl_error_t status = CL_EARG; +#ifndef _WIN32 + int fd = -1; +#else + HANDLE source_handle = INVALID_HANDLE_VALUE; + bool source_handle_can_delete = false; +#endif + + if ((NULL == display_path) || (NULL == open_path) || (NULL == source)) { + return CL_EARG; + } + + action_source_init(source); + + status = action_source_set_display_path(source, display_path); + if (CL_SUCCESS != status) { + goto done; + } + +#ifndef _WIN32 + status = action_source_open_posix_path(open_path, require_resolved_path, &fd); + if (CL_SUCCESS != status) { + goto done; + } + + status = action_source_populate_posix(source, fd, open_path, require_resolved_path); + if (CL_SUCCESS != status) { + goto done; + } + + source->scan_fd = fd; + fd = -1; +#else + if (0 != win32_open_source_handle( + open_path, + require_resolved_path, + &source_handle, + &source_handle_can_delete)) { + status = CL_EOPEN; + goto done; + } + + status = action_source_populate_win32(source, source_handle, source_handle_can_delete); + if (CL_SUCCESS != status) { + goto done; + } + source_handle = INVALID_HANDLE_VALUE; +#endif + +done: +#ifndef _WIN32 + if (-1 != fd) { + close(fd); + } +#else + if (INVALID_HANDLE_VALUE != source_handle) { + CloseHandle(source_handle); + } +#endif + if (CL_SUCCESS != status) { + action_source_close(source); + } + return status; +} + +cl_error_t action_source_open_path(const char *display_path, const char *open_path, action_source_t *source) +{ + return action_source_open_path_impl(display_path, open_path, source, true); +} + +cl_error_t action_source_open(const char *display_path, action_source_t *source) +{ + return action_source_open_path_impl(display_path, display_path, source, false); +} + +cl_error_t action_source_from_fd(const char *display_path, int fd, action_source_t *source) +{ + cl_error_t status = CL_EARG; +#ifndef _WIN32 + int dup_fd = -1; +#else + intptr_t source_osfhandle = -1; + HANDLE source_handle = INVALID_HANDLE_VALUE; + HANDLE dup_handle = INVALID_HANDLE_VALUE; +#endif + + if ((NULL == display_path) || (fd < 0) || (NULL == source)) { + return CL_EARG; + } + + action_source_init(source); + + status = action_source_set_display_path(source, display_path); + if (CL_SUCCESS != status) { + goto done; + } + +#ifndef _WIN32 + do { + dup_fd = dup(fd); + } while ((dup_fd < 0) && (EINTR == errno)); + if (dup_fd < 0) { + status = CL_EOPEN; + goto done; + } + + status = action_source_populate_posix(source, dup_fd, display_path, false); + if (CL_SUCCESS != status) { + goto done; + } + + source->scan_fd = dup_fd; + dup_fd = -1; +#else + source_osfhandle = _get_osfhandle(fd); + if (-1 == source_osfhandle) { + status = CL_EOPEN; + goto done; + } + source_handle = (HANDLE)source_osfhandle; + + if (FALSE == DuplicateHandle( + GetCurrentProcess(), + source_handle, + GetCurrentProcess(), + &dup_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + status = CL_EOPEN; + goto done; + } + + status = action_source_populate_win32(source, dup_handle, false); + if (CL_SUCCESS != status) { + goto done; + } + dup_handle = INVALID_HANDLE_VALUE; +#endif + +done: +#ifndef _WIN32 + if (-1 != dup_fd) { + close(dup_fd); + } +#else + if (INVALID_HANDLE_VALUE != dup_handle) { + CloseHandle(dup_handle); + } +#endif + if (CL_SUCCESS != status) { + action_source_close(source); + } + return status; +} + +void action_source_close(action_source_t *source) +{ + if (NULL == source) { + return; + } + + if (-1 != source->scan_fd) { + close(source->scan_fd); + } +#ifdef _WIN32 + if ((NULL != source->handle) && (INVALID_HANDLE_VALUE != source->handle)) { + CloseHandle((HANDLE)source->handle); + } +#endif + if (NULL != source->display_path) { + free(source->display_path); + } + if (NULL != source->action_path) { + free(source->action_path); + } + + action_source_init(source); +} + +static int getdest(const char *fullpath, char **newname) +{ + char *tmps, *filename; + const char *dest_basename; + int fd, i; + + tmps = strdup(fullpath); + if (!tmps) { + *newname = NULL; + return -1; + } + filename = basename(tmps); + + if (!(*newname = (char *)malloc(targlen + strlen(filename) + 6))) { + free(tmps); + return -1; + } + dest_basename = filename; + sprintf(*newname, "%s" PATHSEP "%s", actarget, dest_basename); + for (i = 1; i < 1000; i++) { +#ifndef _WIN32 + fd = action_openat_nointr(actarget_fd, dest_basename, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_BINARY, 0600); +#else + fd = win32_create_dest_file(dest_basename); +#endif + if (fd >= 0) { + if (0 != action_validate_actarget_path()) { + int validate_errno = errno; + + (void)action_close_dest_fd(&fd); +#ifndef _WIN32 + (void)action_unlinkat_nointr(actarget_fd, dest_basename, 0); +#else + (void)win32_delete_dest_name(dest_basename); +#endif + errno = validate_errno; + break; + } + free(tmps); + return fd; + } + if (errno != EEXIST) break; + sprintf(*newname, "%s" PATHSEP "%s.%03u", actarget, filename, i); + dest_basename = strrchr(*newname, *PATHSEP); + dest_basename = (NULL == dest_basename) ? *newname : dest_basename + 1; + } + free(tmps); + free(*newname); + *newname = NULL; + return -1; +} + +#ifndef _WIN32 +static int action_unlink_dest_at(const char *dest_path) +{ + const char *dest_basename; + + if ((NULL == dest_path) || (-1 == actarget_fd)) { + errno = EINVAL; + return -1; + } + + dest_basename = strrchr(dest_path, *PATHSEP); + dest_basename = (NULL == dest_basename) ? dest_path : dest_basename + 1; + + return action_unlinkat_nointr(actarget_fd, dest_basename, 0); +} + +static int action_link_source_to_dest(const action_source_t *source, char **newname, STATBUF *source_stat_out) +{ + char *tmps = NULL; + char *dest_path = NULL; + char *filename; + const char *dest_basename; + STATBUF dest_stat; + int status = -1; + int i; + + if ((NULL == source) || (NULL == source->action_path) || + (NULL == newname) || (-1 == actarget_fd) || + (false == source->has_stat) || !S_ISREG(source->statbuf.st_mode)) { + errno = EINVAL; + return -1; + } + + *newname = NULL; + + tmps = strdup(source->action_path); + if (NULL == tmps) { + return -1; + } + filename = basename(tmps); + + dest_path = (char *)malloc(targlen + strlen(filename) + 6); + if (NULL == dest_path) { + goto done; + } + + dest_basename = filename; + sprintf(dest_path, "%s" PATHSEP "%s", actarget, dest_basename); + for (i = 1; i < 1000; i++) { + if (0 == linkat(AT_FDCWD, source->action_path, actarget_fd, dest_basename, 0)) { + if (0 != action_fstatat_nointr(actarget_fd, dest_basename, &dest_stat, AT_SYMLINK_NOFOLLOW)) { + (void)action_unlink_dest_at(dest_path); + goto done; + } + + if (!S_ISREG(dest_stat.st_mode) || + dest_stat.st_dev != source->statbuf.st_dev || + dest_stat.st_ino != source->statbuf.st_ino) { + (void)action_unlink_dest_at(dest_path); + errno = EAGAIN; + goto done; + } + + if (0 != action_validate_actarget_path()) { + int validate_errno = errno; + + (void)action_unlink_dest_at(dest_path); + errno = validate_errno; + goto done; + } + + if (NULL != source_stat_out) { + *source_stat_out = source->statbuf; + } + *newname = dest_path; + dest_path = NULL; + status = 0; + goto done; + } + + if (EEXIST != errno) { + goto done; + } + + sprintf(dest_path, "%s" PATHSEP "%s.%03u", actarget, filename, i); + dest_basename = strrchr(dest_path, *PATHSEP); + dest_basename = (NULL == dest_basename) ? dest_path : dest_basename + 1; + } + +done: + if (NULL != dest_path) { + free(dest_path); + } + if (NULL != tmps) { + free(tmps); + } + + return status; +} #endif /** @@ -249,19 +2925,9 @@ int current_handle = -1; int next_handle = -1; #else - bool bNeedDeleteFileAccess = false; - - HMODULE ntdll = NULL; - PNTCF pNtCreateFile = NULL; - PRIUS pRtlInitUnicodeString = NULL; - - PHANDLE current_handle = NULL; - PHANDLE next_handle = NULL; - - ACCESS_MASK desiredAccess = STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_READ_EA; - ULONG fileAttributes = FILE_ATTRIBUTE_DIRECTORY; - ULONG createOptions = FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; - ULONG shareAccess = FILE_SHARE_READ; + HANDLE current_handle = NULL; + char *path_to_open = NULL; + bool is_directory = want_directory_handle; #endif if (NULL == directory || NULL == out_handle) { @@ -269,24 +2935,6 @@ goto done; } -#ifdef _WIN32 - ntdll = LoadLibraryA("ntdll.dll"); - if (NULL == ntdll) { - logg(LOGG_INFO, "traverse_to: failed to load ntdll!\n"); - goto done; - } - pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); - if (NULL == pNtCreateFile) { - logg(LOGG_INFO, "traverse_to: failed to get NtCreateFile proc address!\n"); - goto done; - } - pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); - if (NULL == pRtlInitUnicodeString) { - logg(LOGG_INFO, "traverse_to: failed to get pRtlInitUnicodeString proc address!\n"); - goto done; - } -#endif - tokenized_directory = strdup(directory); if (NULL == tokenized_directory) { logg(LOGG_INFO, "traverse_to: Failed to get copy of directory path to be tokenized!\n"); @@ -304,7 +2952,7 @@ * Open the root(/) directory, because it won't be the first token like a * drive letter (i.e. "C:") would be on Windows. */ - current_handle = open("/", O_RDONLY | O_NOFOLLOW); + current_handle = action_open_directory_nointr("/"); if (-1 == current_handle) { logg(LOGG_INFO, "traverse_to: Failed to open file descriptor for '/' directory.\n"); goto done; @@ -315,10 +2963,14 @@ tokens_count -= 1; } +#ifndef _WIN32 if (0 == tokens_count) { - logg(LOGG_INFO, "traverse_to: Failed to get copy of directory path to be tokenized!\n"); + status = 0; + *out_handle = current_handle; + current_handle = -1; goto done; } +#endif for (i = 0; i < tokens_count; i++) { if (0 == strlen(tokens[i])) { @@ -327,8 +2979,12 @@ } #ifndef _WIN32 + bool is_final_component; - next_handle = openat(current_handle, tokens[i], O_RDONLY | O_NOFOLLOW); + is_final_component = (false == want_directory_handle) && (i + 1 == tokens_count); + next_handle = is_final_component + ? action_openat_source_nointr(current_handle, tokens[i]) + : action_openat_directory_nointr(current_handle, tokens[i]); if (-1 == next_handle) { logg(LOGG_INFO, "traverse_to: Failed open %s\n", tokens[i]); goto done; @@ -338,51 +2994,43 @@ next_handle = -1; #else + (void)i; + break; +#endif - if (true != want_directory_handle) { - if (i == tokens_count - 1) { - /* Change createfile options for our target file instead of an intermediate directory. */ - desiredAccess = FILE_GENERIC_READ | DELETE; - fileAttributes = FILE_ATTRIBUTE_NORMAL; - createOptions = FILE_NON_DIRECTORY_FILE; - shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - } - } - if (i == 0) { - /* NtCreateFile requires the \???\ prefix on drive letters. Eg: \???\C:\ */ - size_t driveroot_len = strlen("\\??\\\\") + strlen(tokens[0]) + 1; - char *driveroot = malloc(driveroot_len); - snprintf(driveroot, driveroot_len + 1, "\\??\\%s\\", tokens[0]); - next_handle = win32_openat(current_handle, - driveroot, - pNtCreateFile, - pRtlInitUnicodeString, - desiredAccess, - fileAttributes, - createOptions, - shareAccess); - free(driveroot); - } else { - next_handle = win32_openat(current_handle, - tokens[i], - pNtCreateFile, - pRtlInitUnicodeString, - desiredAccess, - fileAttributes, - createOptions, - shareAccess); + logg(LOGG_DEBUG, "traverse_to: Handle opened for '%s' directory.\n", tokens[i]); + } + +#ifdef _WIN32 + if (true == want_directory_handle) { + path_to_open = win32_parent_path_dup(directory); + if (NULL == path_to_open) { + logg(LOGG_INFO, "traverse_to: Failed to determine parent directory for '%s'\n", directory); + goto done; } - if (NULL == next_handle) { - logg(LOGG_INFO, "traverse_to: Failed open %s\n", tokens[i]); + } else { + path_to_open = strdup(directory); + if (NULL == path_to_open) { + logg(LOGG_INFO, "traverse_to: Failed to copy path '%s'\n", directory); goto done; } - CloseHandle(current_handle); - current_handle = next_handle; - next_handle = NULL; -#endif + } - logg(LOGG_DEBUG, "traverse_to: Handle opened for '%s' directory.\n", tokens[i]); + if (0 != (is_directory + ? win32_open_existing_path( + path_to_open, + true, + win32_directory_anchor_access(), + ¤t_handle) + : win32_open_existing_path( + path_to_open, + false, + FILE_GENERIC_READ | READ_CONTROL | DELETE, + ¤t_handle))) { + logg(LOGG_INFO, "traverse_to: Failed open %s\n", path_to_open); + goto done; } +#endif status = 0; *out_handle = current_handle; @@ -396,6 +3044,9 @@ if ((-1 == status) && (NULL != current_handle)) { CloseHandle(current_handle); } + if (NULL != path_to_open) { + free(path_to_open); + } #endif if (NULL != tokenized_directory) { free(tokenized_directory); @@ -404,127 +3055,288 @@ return status; } +#ifndef _WIN32 +#define ACTION_PRIVATE_UNLINK_NAME_SIZE 96 + /** - * @brief Rename (move) a file from Source to Destination without following symlinks. - * - * This approach mitigates the possibility that one of the directories - * in the path has been replaced with a malicious symlink. - * - * @param source Source pathname. - * @param destination Destination pathname (including file name) - * @return 0 Rename succeeded. - * @return -1 Rename failed. + * @brief Compare two stat results to determine whether they name the same file. */ -static int traverse_rename(const char *source, const char *destination) +static bool action_stat_same_file(const STATBUF *first, const STATBUF *second) { - int status = -1; -#ifndef _WIN32 - cl_error_t ret; - int source_directory_fd = -1; - char *source_basename = NULL; -#else - FILE_RENAME_INFO *fileInfo = NULL; - HANDLE source_file_handle = NULL; - HANDLE destination_dir_handle = NULL; - WCHAR *destFilepathW = NULL; - int cchDestFilepath = 0; -#endif + return (first->st_dev == second->st_dev) && (first->st_ino == second->st_ino); +} - if (NULL == source || NULL == destination) { - logg(LOGG_INFO, "traverse_rename: Invalid arguments!\n"); - goto done; +/** + * @brief Check whether a stat result describes a private unlink directory. + */ +static bool action_stat_is_private_unlink_dir(const STATBUF *statbuf) +{ + return S_ISDIR(statbuf->st_mode) && + (statbuf->st_uid == geteuid()) && + (0 == (statbuf->st_mode & (S_IRWXG | S_IRWXO))); +} + +/** + * @brief Stat an opened private directory and the parent-relative name for it. + */ +static int action_stat_open_private_dir(int parent_fd, const char *name, int private_fd, STATBUF *fd_stat, STATBUF *path_stat) +{ + if ((parent_fd < 0) || (NULL == name) || (private_fd < 0) || (NULL == fd_stat) || (NULL == path_stat)) { + errno = EINVAL; + return -1; } -#ifndef _WIN32 - if (0 != traverse_to(source, true, &source_directory_fd)) { - logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for source directory!\n"); - goto done; + if (0 != action_fstat_nointr(private_fd, fd_stat)) { + return -1; } -#else - if (0 != traverse_to(source, false, &source_file_handle)) { - logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for source file!\n"); - goto done; + + if (0 != action_fstatat_nointr(parent_fd, name, path_stat, AT_SYMLINK_NOFOLLOW)) { + return -1; } - if (0 != traverse_to(destination, true, &destination_dir_handle)) { - logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for destination directory!\n"); - goto done; + + if (!action_stat_same_file(fd_stat, path_stat)) { + errno = EAGAIN; + return -1; } -#endif -#ifndef _WIN32 - ret = cli_basename(source, strlen(source), &source_basename); - if (CL_SUCCESS != ret) { - logg(LOGG_INFO, "traverse_rename: Failed to get basename of source path:%s\n\tError: %d\n", source, (int)ret); - goto done; + return 0; +} + +/** + * @brief Verify that an opened private unlink directory is still safely named. + */ +static int action_verify_private_unlink_dir(int parent_fd, const char *name, int private_fd, const STATBUF *created_stat) +{ + STATBUF fd_stat; + STATBUF path_stat; + + if (NULL == created_stat) { + errno = EINVAL; + return -1; } - if (0 != renameat(source_directory_fd, source_basename, -1, destination)) { - logg(LOGG_INFO, "traverse_rename: Failed to rename: %s\n\tto: %s\nError:%s\n", source, destination, strerror(errno)); - goto done; + if (0 != action_stat_open_private_dir(parent_fd, name, private_fd, &fd_stat, &path_stat)) { + return -1; } -#else - /* Convert destination filepath to a PWCHAR */ - cchDestFilepath = MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), NULL, 0); - destFilepathW = calloc(cchDestFilepath * sizeof(WCHAR), 1); - if (NULL == destFilepathW) { - logg(LOGG_INFO, "traverse_rename: failed to allocate memory for destination basename UTF16LE string\n"); - goto done; + + if (!action_stat_same_file(&fd_stat, created_stat) || + !action_stat_same_file(&path_stat, created_stat)) { + errno = EAGAIN; + return -1; } - if (0 == MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), destFilepathW, cchDestFilepath)) { - logg(LOGG_INFO, "traverse_rename: failed to allocate buffer for UTF16LE version of destination file basename.\n"); - goto done; + + /* + * mkdirat() returns no fd, so a hostile writable parent can rename the new + * directory before openat(). Refuse a replacement that was not created by + * this effective user or is accessible by group/other users. + */ + if (!action_stat_is_private_unlink_dir(&fd_stat) || + !action_stat_is_private_unlink_dir(&path_stat)) { + errno = EACCES; + return -1; } - fileInfo = calloc(1, sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR)); - if (NULL == fileInfo) { - logg(LOGG_INFO, "traverse_rename: failed to allocate memory for fileInfo struct\n"); - goto done; + return 0; +} + +/** + * @brief Remove a private unlink directory only if its name still matches its fd. + */ +static int action_unlink_private_unlink_dir(int parent_fd, const char *name, int private_fd) +{ + STATBUF fd_stat; + STATBUF path_stat; + + if (0 != action_stat_open_private_dir(parent_fd, name, private_fd, &fd_stat, &path_stat)) { + return -1; } - fileInfo->ReplaceIfExists = TRUE; - fileInfo->RootDirectory = NULL; - memcpy(fileInfo->FileName, destFilepathW, cchDestFilepath * sizeof(WCHAR)); - fileInfo->FileNameLength = cchDestFilepath; - if (FALSE == SetFileInformationByHandle( - source_file_handle, // FileHandle - FileRenameInfo, // FileInformationClass - fileInfo, // FileInformation - sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR))) { // Length + if (!action_stat_is_private_unlink_dir(&fd_stat) || + !action_stat_is_private_unlink_dir(&path_stat)) { + errno = EACCES; + return -1; + } - logg(LOGG_INFO, "traverse_rename: Failed to set file rename info for '%s' to '%s'.\nError: %d\n", source, destination, GetLastError()); - goto done; + return action_unlinkat_nointr(parent_fd, name, AT_REMOVEDIR); +} + +/** + * @brief Remove a just-created private unlink directory before its fd is open. + */ +static int action_unlink_created_private_unlink_dir(int parent_fd, const char *name, const STATBUF *created_stat) +{ + STATBUF path_stat; + + if ((parent_fd < 0) || (NULL == name) || (NULL == created_stat)) { + errno = EINVAL; + return -1; } -#endif - status = 0; + if (0 != action_fstatat_nointr(parent_fd, name, &path_stat, AT_SYMLINK_NOFOLLOW)) { + return -1; + } -done: + if (!action_stat_same_file(&path_stat, created_stat) || + !action_stat_is_private_unlink_dir(&path_stat)) { + errno = EAGAIN; + return -1; + } -#ifndef _WIN32 - if (NULL != source_basename) { - free(source_basename); + return action_unlinkat_nointr(parent_fd, name, AT_REMOVEDIR); +} + +/** + * @brief Create and open a private directory under an already validated parent. + * + * The private directory is used to capture a source basename with renameat() + * before verifying and unlinking it. Holding the directory fd keeps later + * verification and deletion bound to the directory object even if the private + * directory name is renamed by another process. + * + * @param parent_fd Validated parent directory fd. + * @param[out] name Buffer that receives the private directory basename. + * @param name_size Size of the name buffer. + * @param[out] private_fd Open fd for the private directory. + * @return 0 Directory was created and opened. + * @return -1 Directory creation/open failed. + */ +static int action_create_private_unlink_dir(int parent_fd, char *name, size_t name_size, int *private_fd) +{ + unsigned int i; + + if ((parent_fd < 0) || (NULL == name) || (0 == name_size) || (NULL == private_fd)) { + errno = EINVAL; + return -1; } - if (-1 != source_directory_fd) { - close(source_directory_fd); + *private_fd = -1; + name[0] = '\0'; + + for (i = 0; i < 1000; i++) { + STATBUF created_stat; + int rc; + + rc = snprintf( + name, + name_size, + ".clamav-unlink-%ld-%u-%u", + (long)getpid(), + cli_rndnum(0xffffff), + i); + if ((rc < 0) || ((size_t)rc >= name_size)) { + errno = ENAMETOOLONG; + return -1; + } + + if (0 == action_mkdirat_nointr(parent_fd, name, 0700)) { + if (0 != action_fstatat_nointr(parent_fd, name, &created_stat, AT_SYMLINK_NOFOLLOW)) { + return -1; + } + if (!action_stat_is_private_unlink_dir(&created_stat)) { + errno = EACCES; + return -1; + } + + *private_fd = action_openat_directory_nointr(parent_fd, name); + if (*private_fd < 0) { + int saved_errno = errno; + + (void)action_unlink_created_private_unlink_dir(parent_fd, name, &created_stat); + errno = saved_errno; + return -1; + } + if (0 != action_verify_private_unlink_dir(parent_fd, name, *private_fd, &created_stat)) { + int saved_errno = errno; + + (void)action_unlink_private_unlink_dir(parent_fd, name, *private_fd); + close(*private_fd); + *private_fd = -1; + errno = saved_errno; + return -1; + } + return 0; + } + + if (EEXIST != errno) { + return -1; + } } -#else - if (NULL != fileInfo) { - free(fileInfo); + + errno = EEXIST; + return -1; +} + +/** + * @brief Restore a captured replacement that should not be unlinked. + * + * The capture directory contains a basename that did not match the scanned + * source after renameat(). Restore without overwriting anything that may have + * appeared at the original basename while the action was deciding whether to + * unlink the captured entry. + * + * @param target_directory_fd Validated directory fd for the original basename. + * @param private_directory_fd Private capture directory fd. + * @param target_basename Basename shared by the original and captured path. + * @param captured_stat stat() result for the captured basename. + * @param supports_noreplace_restore Whether no-replace rename is available. + * @return 0 Captured entry was restored and removed from the + * private directory. + * @return -1 Restore failed or cannot be done safely. + */ +static int action_restore_captured_unlink_target( + int target_directory_fd, + int private_directory_fd, + const char *target_basename, + const STATBUF *captured_stat, + bool supports_noreplace_restore) +{ + int link_errno; + + if ((target_directory_fd < 0) || (private_directory_fd < 0) || + (NULL == target_basename) || (NULL == captured_stat)) { + errno = EINVAL; + return -1; } - if (NULL != destFilepathW) { - free(destFilepathW); + + /* + * linkat() restores regular files, symlinks, FIFOs, and other linkable + * non-directory entries without overwriting a new entry that may have + * appeared at the original basename. + */ + if (0 == linkat( + private_directory_fd, + target_basename, + target_directory_fd, + target_basename, + 0)) { + return action_unlinkat_nointr(private_directory_fd, target_basename, 0); } - if (NULL != source_file_handle) { - CloseHandle(source_file_handle); + link_errno = errno; + + if (EEXIST == link_errno) { + errno = link_errno; + return -1; } - if (NULL != destination_dir_handle) { - CloseHandle(destination_dir_handle); + + /* + * Directories cannot be hard-linked, and non-directory hard-link restores + * can be denied by policy such as Linux protected_hardlinks. Only use a + * no-replace rename fallback where the platform provides one; plain + * renameat() could overwrite a new entry that raced into the original + * basename. + */ + if (supports_noreplace_restore) { + return action_renameat_noreplace_nointr( + private_directory_fd, + target_basename, + target_directory_fd, + target_basename); } -#endif - return status; + errno = S_ISDIR(captured_stat->st_mode) ? ENOTSUP : link_errno; + return -1; } +#endif /** * @brief Unlink (delete) a target file without following symlinks. @@ -532,19 +3344,36 @@ * This approach mitigates the possibility that one of the directories * in the path has been replaced with a malicious symlink. * - * @param target A file to be deleted. - * @return 0 Unlink succeeded. - * @return -1 Unlink failed. + * @param target A file to be deleted. + * @param source_fd POSIX descriptor for the scanned source. + * @param expected_stat POSIX metadata for the scanned source. + * @param target_file_handle Windows handle for the scanned source. + * @param target_file_handle_can_delete Whether the Windows handle has delete access. + * @return 0 Unlink succeeded. + * @return -1 Unlink failed. */ -static int traverse_unlink(const char *target) +#ifndef _WIN32 +static int traverse_unlink(const char *target, int source_fd, const STATBUF *expected_stat) +#else +static int traverse_unlink( + const char *target, + HANDLE target_file_handle, + bool target_file_handle_can_delete) +#endif { int status = -1; cl_error_t ret; #ifndef _WIN32 int target_directory_fd = -1; + int private_directory_fd = -1; + char private_directory_name[ACTION_PRIVATE_UNLINK_NAME_SIZE] = {0}; + STATBUF current_stat; + STATBUF captured_stat; + int rc; + bool supports_noreplace_restore = false; #else - FILE_DISPOSITION_INFO fileInfo = {0}; - HANDLE target_file_handle = NULL; + HANDLE delete_handle = INVALID_HANDLE_VALUE; + bool close_delete_handle = true; #endif char *target_basename = NULL; @@ -553,44 +3382,145 @@ goto done; } +#if !defined(_WIN32) && (!defined(__FreeBSD__) || !defined(HAVE_FUNLINKAT)) + UNUSEDPARAM(source_fd); +#endif + #ifndef _WIN32 /* On posix, we want a file descriptor for the directory */ if (0 != traverse_to(target, true, &target_directory_fd)) { + goto done; + } #else - /* On Windows, we want a handle to the file, not the directory */ - if (0 != traverse_to(target, false, &target_file_handle)) { -#endif - logg(LOGG_INFO, "traverse_unlink: Failed to open file descriptor for target directory!\n"); + if (target_file_handle_can_delete) { + delete_handle = target_file_handle; + close_delete_handle = false; + } else { + if (0 != win32_open_delete_handle_for_source(target, target_file_handle, &delete_handle)) { + logg(LOGG_INFO, "traverse_unlink: Failed to open '%s' for delete. Error: %lu\n", target, GetLastError()); + goto done; + } + } + + if (0 != win32_delete_handle(delete_handle)) { + logg(LOGG_INFO, "traverse_unlink: Failed to delete '%s'. Error: %lu\n", target, GetLastError()); goto done; } +#endif +#ifndef _WIN32 ret = cli_basename(target, strlen(target), &target_basename); if (CL_SUCCESS != ret) { logg(LOGG_INFO, "traverse_unlink: Failed to get basename of target path: %s\n\tError: %d\n", target, (int)ret); goto done; } -#ifndef _WIN32 - if (0 != unlinkat(target_directory_fd, target_basename, 0)) { - logg(LOGG_INFO, "traverse_unlink: Failed to unlink: %s\nError:%s\n", target, strerror(errno)); - goto done; - } -#else - fileInfo.DeleteFileA = TRUE; - if (FALSE == SetFileInformationByHandle( - target_file_handle, // FileHandle - FileDispositionInfo, // FileInformationClass - &fileInfo, // FileInformation - sizeof(FILE_DISPOSITION_INFO))) { // Length + if (NULL == expected_stat) { + if (0 != action_unlinkat_nointr(target_directory_fd, target_basename, 0)) { + logg(LOGG_INFO, "traverse_unlink: Failed to unlink: %s\nError:%s\n", target, strerror(errno)); + goto done; + } + } else { +#if defined(__FreeBSD__) && defined(HAVE_FUNLINKAT) + if (source_fd >= 0) { + /* + * FreeBSD verifies atomically that target_basename still names + * source_fd before unlinking it. This avoids the private capture + * and no-replace restore required on other POSIX platforms. + */ + if (0 != action_funlinkat_nointr(target_directory_fd, target_basename, source_fd, 0)) { + int unlink_errno = errno; + + if (EDEADLK == unlink_errno) { + logg(LOGG_INFO, "traverse_unlink: Refusing to unlink '%s' because the source changed after validation.\n", target); + errno = EAGAIN; + } else { + logg(LOGG_INFO, "traverse_unlink: Failed to unlink '%s' through its opened descriptor: %s\n", target, strerror(unlink_errno)); + errno = unlink_errno; + } + goto done; + } - logg(LOGG_INFO, "traverse_unlink: Failed to set file disposition to 'DELETE' for '%s'.\n", target); - goto done; - } - if (FALSE == CloseHandle(target_file_handle)) { - logg(LOGG_INFO, "traverse_unlink: Failed to set close & delete file '%s'.\n", target); - goto done; + status = 0; + goto done; + } +#endif + if (0 != action_create_private_unlink_dir( + target_directory_fd, + private_directory_name, + sizeof(private_directory_name), + &private_directory_fd)) { + logg(LOGG_INFO, "traverse_unlink: Failed to create private unlink directory for '%s': %s\n", target, strerror(errno)); + goto done; + } + + supports_noreplace_restore = action_private_dir_supports_noreplace_rename(private_directory_fd); + if (!supports_noreplace_restore) { + /* + * This is intentionally conservative. Regular captured entries can + * usually be restored with linkat(), but the basename can still + * race from the checked regular file to a directory before the + * private rename. Without an atomic no-replace directory restore, + * refusing the action preserves the CLAM-2959 guarantee that a + * failed quarantine action does not remove or hide a replacement. + */ + logg(LOGG_INFO, "traverse_unlink: Refusing to capture '%s' because no-replace restore is unavailable.\n", target); + errno = ENOTSUP; + goto done; + } + + do { + rc = action_fstatat_nointr(target_directory_fd, target_basename, ¤t_stat, AT_SYMLINK_NOFOLLOW); + } while ((rc < 0) && (EINTR == errno)); + + if (0 != rc) { + logg(LOGG_INFO, "traverse_unlink: Failed to restat '%s' before capture: %s\n", target, strerror(errno)); + goto done; + } + + if (!S_ISREG(current_stat.st_mode) || + current_stat.st_dev != expected_stat->st_dev || + current_stat.st_ino != expected_stat->st_ino) { + errno = EAGAIN; + logg(LOGG_INFO, "traverse_unlink: Refusing to capture '%s' because the source changed after validation.\n", target); + goto done; + } + + if (0 != action_renameat_nointr(target_directory_fd, target_basename, private_directory_fd, target_basename)) { + logg(LOGG_INFO, "traverse_unlink: Failed to capture '%s' before unlink: %s\n", target, strerror(errno)); + goto done; + } + + do { + rc = action_fstatat_nointr(private_directory_fd, target_basename, &captured_stat, AT_SYMLINK_NOFOLLOW); + } while ((rc < 0) && (EINTR == errno)); + + if (0 != rc) { + logg(LOGG_INFO, "traverse_unlink: Failed to restat captured '%s' before unlink: %s\n", target, strerror(errno)); + goto done; + } + + if (!S_ISREG(captured_stat.st_mode) || + captured_stat.st_dev != expected_stat->st_dev || + captured_stat.st_ino != expected_stat->st_ino) { + if (0 != action_restore_captured_unlink_target( + target_directory_fd, + private_directory_fd, + target_basename, + &captured_stat, + supports_noreplace_restore)) { + logg(LOGG_INFO, "traverse_unlink: Failed to restore captured replacement for '%s': %s\n", target, strerror(errno)); + } + errno = EAGAIN; + logg(LOGG_INFO, "traverse_unlink: Refusing to unlink '%s' because the captured source does not match the scanned file.\n", target); + goto done; + } + + if (0 != action_unlinkat_nointr(private_directory_fd, target_basename, 0)) { + logg(LOGG_INFO, "traverse_unlink: Failed to unlink captured source for %s\nError:%s\n", target, strerror(errno)); + goto done; + } } - target_file_handle = NULL; #endif status = 0; @@ -602,85 +3532,301 @@ } #ifndef _WIN32 + if (-1 != private_directory_fd) { + if (('\0' != private_directory_name[0]) && + (0 != action_unlink_private_unlink_dir(target_directory_fd, private_directory_name, private_directory_fd)) && + (ENOENT != errno)) { + logg(LOGG_DEBUG, "traverse_unlink: Failed to remove private unlink directory '%s': %s\n", + private_directory_name, + strerror(errno)); + } + close(private_directory_fd); + } if (-1 != target_directory_fd) { close(target_directory_fd); } #else - if (NULL != target_file_handle) { - CloseHandle(target_file_handle); + if (close_delete_handle && (INVALID_HANDLE_VALUE != delete_handle)) { + CloseHandle(delete_handle); } #endif return status; } -static void action_move(const char *filename) +static const char *action_source_display_path(const action_source_t *source) { - char *nuname = NULL; - char *real_filename = NULL; - int fd = -1; - int copied = 0; + return ((NULL != source) && (NULL != source->display_path)) ? source->display_path : "(null)"; +} + +static const char *action_source_action_path(const action_source_t *source) +{ + return ((NULL != source) && (NULL != source->action_path)) ? source->action_path : NULL; +} + +static bool action_source_show_action_path(const action_source_t *source) +{ + const char *display_path = action_source_display_path(source); + const char *action_path = action_source_action_path(source); + + return (NULL != action_path) && (0 != strcmp(display_path, action_path)); +} + +static void action_move(const action_source_t *source) +{ + char *nuname = NULL; + int fd = -1; + const char *filename; + const char *action_filename; + bool show_action_path; +#ifndef _WIN32 + STATBUF source_stat; +#endif - if (NULL == filename) { + filename = action_source_display_path(source); + action_filename = action_source_action_path(source); + show_action_path = action_source_show_action_path(source); + + if ((NULL == source) || (NULL == action_filename)) { + logg(LOGG_ERROR, "Can't move file '%s'\n", filename); + notmoved++; goto done; } - fd = getdest(filename, &nuname); +#ifndef _WIN32 + if (0 == action_link_source_to_dest(source, &nuname, &source_stat)) { + if (0 != action_validate_actarget_path()) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't move file '%s' (real path: '%s'): quarantine destination '%s' is unavailable\n", filename, action_filename, actarget); + } else { + logg(LOGG_ERROR, "Can't move file '%s': quarantine destination '%s' is unavailable\n", filename, actarget); + } + (void)action_unlink_dest_at(nuname); + notmoved++; + goto done; + } + if (0 != traverse_unlink(action_filename, source->scan_fd, &source_stat)) { + int unlink_errno = errno; + if (show_action_path) { + logg(LOGG_ERROR, "Can't unlink '%s' (real path: '%s') after linking into quarantine: %s\n", filename, action_filename, strerror(unlink_errno)); + } else { + logg(LOGG_ERROR, "Can't unlink '%s' after linking into quarantine: %s\n", filename, strerror(unlink_errno)); + } + if (EAGAIN != unlink_errno) { + (void)action_unlink_dest_at(nuname); + } + notmoved++; + } else if (show_action_path) { + logg(LOGG_INFO, "%s (real path: '%s'): moved to '%s'\n", filename, action_filename, nuname); + } else { + logg(LOGG_INFO, "%s: moved to '%s'\n", filename, nuname); + } + goto done; + } +#endif + + fd = getdest(action_filename, &nuname); #ifndef _WIN32 - if (fd < 0 || (0 != traverse_rename(filename, nuname) && ((copied = 1)) && filecopy(filename, nuname))) { + if (fd < 0 || filecopy_to_fd(source, fd, &source_stat) || action_close_dest_fd(&fd)) { #else - if (fd < 0 || (((copied = 1)) && filecopy(filename, nuname))) { + if (fd < 0 || filecopy_to_fd(source, nuname, fd) || action_close_dest_fd(&fd)) { #endif - logg(LOGG_ERROR, "Can't move file %s to %s\n", filename, nuname); + if (NULL != nuname) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't move file '%s' (real path: '%s') to '%s'\n", filename, action_filename, nuname); + } else { + logg(LOGG_ERROR, "Can't move file '%s' to '%s'\n", filename, nuname); + } + } else { + if (show_action_path) { + logg(LOGG_ERROR, "Can't move file '%s' (real path: '%s'): quarantine destination '%s' is unavailable\n", filename, action_filename, actarget); + } else { + logg(LOGG_ERROR, "Can't move file '%s': quarantine destination '%s' is unavailable\n", filename, actarget); + } + } notmoved++; - if (nuname) traverse_unlink(nuname); + if (nuname) { +#ifndef _WIN32 + action_unlink_dest_at(nuname); +#else + if (fd >= 0) { + close(fd); + fd = -1; + } + (void)win32_delete_dest_path(nuname); +#endif + } } else { - if (copied && (0 != traverse_unlink(filename))) - logg(LOGG_ERROR, "Can't unlink '%s' after copy: %s\n", filename, strerror(errno)); - else - logg(LOGG_INFO, "%s: moved to '%s'\n", filename, nuname); + if (0 != action_validate_actarget_path()) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't move file '%s' (real path: '%s'): quarantine destination '%s' is unavailable\n", filename, action_filename, actarget); + } else { + logg(LOGG_ERROR, "Can't move file '%s': quarantine destination '%s' is unavailable\n", filename, actarget); + } + notmoved++; +#ifndef _WIN32 + action_unlink_dest_at(nuname); +#else + if (fd >= 0) { + close(fd); + fd = -1; + } + (void)win32_delete_dest_path(nuname); +#endif + goto done; + } +#ifndef _WIN32 + if (0 != traverse_unlink(action_filename, source->scan_fd, &source_stat)) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't unlink '%s' (real path: '%s') after copy: %s\n", filename, action_filename, strerror(errno)); + } else { + logg(LOGG_ERROR, "Can't unlink '%s' after copy: %s\n", filename, strerror(errno)); + } +#else + if (0 != traverse_unlink( + action_filename, + (HANDLE)source->handle, + source->handle_can_delete)) { + DWORD delete_error = GetLastError(); + if (show_action_path) { + logg(LOGG_ERROR, "Can't unlink '%s' (real path: '%s') after copy. Error: %lu\n", filename, action_filename, delete_error); + } else { + logg(LOGG_ERROR, "Can't unlink '%s' after copy. Error: %lu\n", filename, delete_error); + } +#endif + notmoved++; + } else { + if (show_action_path) { + logg(LOGG_INFO, "%s (real path: '%s'): moved to '%s'\n", filename, action_filename, nuname); + } else { + logg(LOGG_INFO, "%s: moved to '%s'\n", filename, nuname); + } + } } done: - if (NULL != real_filename) free(real_filename); if (fd >= 0) close(fd); if (NULL != nuname) free(nuname); return; } -static void action_copy(const char *filename) +static void action_copy(const action_source_t *source) { - char *nuname; - int fd = getdest(filename, &nuname); + char *nuname = NULL; + int fd = -1; + const char *filename; + const char *action_filename; + bool show_action_path; + + filename = action_source_display_path(source); + action_filename = action_source_action_path(source); + show_action_path = action_source_show_action_path(source); - if (fd < 0 || filecopy(filename, nuname)) { + if ((NULL == source) || (NULL == action_filename)) { logg(LOGG_ERROR, "Can't copy file '%s'\n", filename); notmoved++; - if (nuname) traverse_unlink(nuname); - } else + return; + } + + fd = getdest(action_filename, &nuname); + +#ifndef _WIN32 + if (fd < 0 || filecopy_to_fd(source, fd, NULL) || action_close_dest_fd(&fd)) { +#else + if (fd < 0 || filecopy_to_fd(source, nuname, fd) || action_close_dest_fd(&fd)) { +#endif + if (NULL != nuname) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't copy file '%s' (real path: '%s') to '%s'\n", filename, action_filename, nuname); + } else { + logg(LOGG_ERROR, "Can't copy file '%s' to '%s'\n", filename, nuname); + } + } else { + if (show_action_path) { + logg(LOGG_ERROR, "Can't copy file '%s' (real path: '%s'): quarantine destination '%s' is unavailable\n", filename, action_filename, actarget); + } else { + logg(LOGG_ERROR, "Can't copy file '%s': quarantine destination '%s' is unavailable\n", filename, actarget); + } + } + notmoved++; + if (nuname) { +#ifndef _WIN32 + action_unlink_dest_at(nuname); +#else + if (fd >= 0) { + close(fd); + fd = -1; + } + (void)win32_delete_dest_path(nuname); +#endif + } + } else if (0 != action_validate_actarget_path()) { + if (show_action_path) { + logg(LOGG_ERROR, "Can't copy file '%s' (real path: '%s'): quarantine destination '%s' is unavailable\n", filename, action_filename, actarget); + } else { + logg(LOGG_ERROR, "Can't copy file '%s': quarantine destination '%s' is unavailable\n", filename, actarget); + } + notmoved++; +#ifndef _WIN32 + action_unlink_dest_at(nuname); +#else + if (fd >= 0) { + close(fd); + fd = -1; + } + (void)win32_delete_dest_path(nuname); +#endif + } else if (show_action_path) { + logg(LOGG_INFO, "%s (real path: '%s'): copied to '%s'\n", filename, action_filename, nuname); + } else { logg(LOGG_INFO, "%s: copied to '%s'\n", filename, nuname); + } if (fd >= 0) close(fd); if (nuname) free(nuname); } -static void action_remove(const char *filename) +static void action_remove(const action_source_t *source) { - char *real_filename = NULL; + const char *filename; + const char *action_filename; + bool show_action_path; + + filename = action_source_display_path(source); + action_filename = action_source_action_path(source); + show_action_path = action_source_show_action_path(source); - if (NULL == filename) { + if ((NULL == source) || (NULL == action_filename)) { + logg(LOGG_ERROR, "Can't remove file '%s'\n", filename); + notremoved++; goto done; } - if (0 != traverse_unlink(filename)) { - logg(LOGG_ERROR, "Can't remove file '%s'\n", filename); +#ifndef _WIN32 + if ((false == source->has_stat) || + !S_ISREG(source->statbuf.st_mode) || + (0 != traverse_unlink(action_filename, source->scan_fd, &source->statbuf))) { +#else + if (0 != traverse_unlink( + action_filename, + (HANDLE)source->handle, + source->handle_can_delete)) { +#endif + if (show_action_path) { + logg(LOGG_ERROR, "Can't remove file '%s' (real path: '%s')\n", filename, action_filename); + } else { + logg(LOGG_ERROR, "Can't remove file '%s'\n", filename); + } notremoved++; } else { - logg(LOGG_INFO, "%s: Removed.\n", filename); + if (show_action_path) { + logg(LOGG_INFO, "%s (real path: '%s'): Removed.\n", filename, action_filename); + } else { + logg(LOGG_INFO, "%s: Removed.\n", filename); + } } done: - if (NULL != real_filename) free(real_filename); return; } @@ -701,21 +3847,100 @@ int actsetup(const struct optstruct *opts) { int move = optget(opts, "move")->enabled; + + action_cleanup(); + if (false == action_cleanup_registered) { + if (0 != atexit(action_cleanup)) { + logg(LOGG_INFO, "action_setup: Failed to register cleanup handler.\n"); + return 1; + } + action_cleanup_registered = true; + } + if (move || optget(opts, "copy")->enabled) { + const char *requested_actarget = optget(opts, move ? "move" : "copy")->strarg; #ifndef _WIN32 cl_error_t ret; + int actarget_parent_fd = -1; + char *actarget_basename = NULL; + char *resolved_actarget = NULL; + + ret = cli_realpath(requested_actarget, &resolved_actarget); + if (CL_SUCCESS != ret || NULL == resolved_actarget) { + logg(LOGG_INFO, "action_setup: Failed to get realpath of %s\n", requested_actarget); + if (NULL != resolved_actarget) { + free(resolved_actarget); + } + return 1; + } + actarget = resolved_actarget; +#else + actarget_normalized = win32_trim_trailing_path_separators_dup(requested_actarget); + if (NULL == actarget_normalized) { + logg(LOGG_INFO, "action_setup: Failed to normalize quarantine directory path %s\n", requested_actarget); + return 1; + } + actarget = actarget_normalized; #endif - actarget = optget(opts, move ? "move" : "copy")->strarg; + if (!isdir()) return 1; + targlen = strlen(actarget); #ifndef _WIN32 - ret = cli_realpath((const char *)actarget, &actarget); - if (CL_SUCCESS != ret || NULL == actarget) { - logg(LOGG_INFO, "action_setup: Failed to get realpath of %s\n", actarget); - return 0; + ret = cli_basename(actarget, strlen(actarget), &actarget_basename); + if ((CL_SUCCESS != ret) || + (0 != traverse_to(actarget, true, &actarget_parent_fd)) || + (-1 == (actarget_fd = action_openat_directory_nointr(actarget_parent_fd, actarget_basename)))) { + if (-1 != actarget_parent_fd) { + close(actarget_parent_fd); + } + if (NULL != actarget_basename) { + free(actarget_basename); + } + logg(LOGG_INFO, "action_setup: Failed to open quarantine directory handle for %s\n", actarget); + return 1; + } + close(actarget_parent_fd); + free(actarget_basename); + if (0 != action_setup_quarantine_lock()) { + action_cleanup(); + return 1; + } +#else + HANDLE actarget_parent_handle = NULL; + char *actarget_basename = NULL; + cl_error_t ret = CL_EARG; + size_t actarget_root_len = win32_path_root_length(actarget, strlen(actarget)); + + if ((0 != actarget_root_len) && (actarget_root_len == strlen(actarget))) { + if (0 != win32_open_existing_path( + actarget, + true, + win32_directory_anchor_access(), + &actarget_handle)) { + actarget_handle = INVALID_HANDLE_VALUE; + } + } else if (0 == traverse_to(actarget, true, &actarget_parent_handle)) { + ret = cli_basename(actarget, strlen(actarget), &actarget_basename); + if ((CL_SUCCESS == ret) && + (0 == win32_open_existing_directory_at(actarget_parent_handle, actarget_basename, &actarget_handle))) { + CloseHandle(actarget_parent_handle); + free(actarget_basename); + } else { + CloseHandle(actarget_parent_handle); + if (NULL != actarget_basename) { + free(actarget_basename); + } + actarget_handle = INVALID_HANDLE_VALUE; + } + } else { + actarget_handle = INVALID_HANDLE_VALUE; + } + + if ((NULL == actarget_handle) || (INVALID_HANDLE_VALUE == actarget_handle)) { + logg(LOGG_INFO, "action_setup: Failed to open quarantine directory handle for %s\n", actarget); + return 1; } #endif - if (!isdir()) return 1; action = move ? action_move : action_copy; - targlen = strlen(actarget); } else if (optget(opts, "remove")->enabled) action = action_remove; return 0; diff -Nru clamav-1.4.3+dfsg/common/actions.h clamav-1.4.6+dfsg/common/actions.h --- clamav-1.4.3+dfsg/common/actions.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/actions.h 2026-08-06 21:12:04.000000000 +0000 @@ -28,14 +28,80 @@ #ifndef ACTIONS_H #define ACTIONS_H +#include +#include +#include + +#include "clamav.h" #include "optparser.h" /** + * @brief Opened source object used for quarantine I/O. + * + * The source owns scan_fd and any platform-specific handle state. Callers scan + * scan_fd, then pass the same source to the selected action before closing it. + */ +typedef struct action_source { + char *display_path; + char *action_path; + int scan_fd; + STATBUF statbuf; + bool has_stat; +#ifdef _WIN32 + void *handle; + bool handle_can_delete; +#endif +} action_source_t; + +/** * @brief Callback function to perform the action requested when actsetup() was invoked. * - * @param filename + * @param source Open source object that was submitted for scanning. + */ +extern void (*action)(const action_source_t *); + +/** + * @brief Initialize an action source to an empty closed state. + * + * @param source Source object to initialize. + */ +void action_source_init(action_source_t *source); + +/** + * @brief Open a path for scan and later quarantine action. + * + * @param display_path Original path to use for scan output. + * @param source Source object to populate. + * @return cl_error_t CL_SUCCESS if the source is open. */ -extern void (*action)(const char *); +cl_error_t action_source_open(const char *display_path, action_source_t *source); + +/** + * @brief Open a resolved path for scan and later quarantine action. + * + * @param display_path Original path to use for scan output. + * @param open_path Path to open for scan and quarantine action. + * @param source Source object to populate. + * @return cl_error_t CL_SUCCESS if the source is open. + */ +cl_error_t action_source_open_path(const char *display_path, const char *open_path, action_source_t *source); + +/** + * @brief Duplicate an existing descriptor for later quarantine action. + * + * @param display_path Original path to use for scan output. + * @param fd Existing descriptor for the scan target. + * @param source Source object to populate. + * @return cl_error_t CL_SUCCESS if the source is open. + */ +cl_error_t action_source_from_fd(const char *display_path, int fd, action_source_t *source); + +/** + * @brief Close and reset an action source. + * + * @param source Source object to close. + */ +void action_source_close(action_source_t *source); /** * @brief Select the appropriate callback function based on the configuration options. @@ -48,4 +114,8 @@ extern unsigned int notremoved, notmoved; +#ifndef _WIN32 +int action_setup_quarantine_lock_at(int directory_fd, const char *directory_path, char **lockname_out); +#endif + #endif diff -Nru clamav-1.4.3+dfsg/common/clamdcom.c clamav-1.4.6+dfsg/common/clamdcom.c --- clamav-1.4.3+dfsg/common/clamdcom.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/clamdcom.c 2026-08-06 21:12:04.000000000 +0000 @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -172,25 +173,20 @@ #ifdef HAVE_FD_PASSING /* Issues a FILDES command and pass a FD to clamd * Returns >0 on success, 0 soft fail, -1 hard fail */ -int send_fdpass(int sockd, const char *filename) +int send_fdpass_fd(int sockd, int fd) { struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmsg; unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; char dummy[] = ""; - int fd; const char zFILDES[] = "zFILDES"; - if (filename) { - if ((fd = open(filename, O_RDONLY)) < 0) { - logg(LOGG_INFO, "%s: Failed to open file\n", filename); - return 0; - } - } else - fd = 0; + if (fd < 0) { + return 0; + } + if (sendln(sockd, zFILDES, sizeof(zFILDES))) { - close(fd); return -1; } @@ -208,61 +204,136 @@ *(int *)CMSG_DATA(cmsg) = fd; if (sendmsg(sockd, &msg, 0) == -1) { logg(LOGG_ERROR, "FD send failed: %s\n", strerror(errno)); - close(fd); return -1; } - close(fd); return 1; } + +/* Issues a FILDES command and pass a FD to clamd + * Returns >0 on success, 0 soft fail, -1 hard fail */ +int send_fdpass(int sockd, const char *filename) +{ + int fd; + int ret; + int close_fd = 0; + + if (filename) { + if ((fd = open(filename, O_RDONLY)) < 0) { + logg(LOGG_INFO, "%s: Failed to open file\n", filename); + return 0; + } + close_fd = 1; + } else + fd = 0; + ret = send_fdpass_fd(sockd, fd); + if (close_fd) { + close(fd); + } + return ret; +} #endif /* Issues an INSTREAM command to clamd and streams the given file * Returns >0 on success, 0 soft fail, -1 hard fail */ -int send_stream(int sockd, const char *filename, struct optstruct *clamdopts) +static int send_stream_fd_common(int sockd, int fd, const char *display_filename, struct optstruct *clamdopts, bool reject_over_limit) { uint32_t buf[BUFSIZ / sizeof(uint32_t)]; - int fd, len; + int len; unsigned long int todo = optget(clamdopts, "StreamMaxLength")->numarg; const char zINSTREAM[] = "zINSTREAM"; + STATBUF sb; - if (filename) { - if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) { - logg(LOGG_INFO, "%s: Failed to open file. ERROR\n", filename); - return 0; - } - } else { - /* Read stream from STDIN */ - fd = 0; + if (fd < 0) { + return 0; + } + + if (reject_over_limit && + (0 == FSTAT(fd, &sb)) && + S_ISREG(sb.st_mode) && + (sb.st_size > 0) && + ((uint64_t)sb.st_size > (uint64_t)todo)) { + logg(LOGG_ERROR, "%s: File size exceeds StreamMaxLength; refusing to send a truncated quarantine stream. ERROR\n", + display_filename ? display_filename : "STDIN"); + return 0; } if (sendln(sockd, zINSTREAM, sizeof(zINSTREAM))) { - close(fd); return -1; } + if (0 != fd) { + (void)lseek(fd, 0, SEEK_SET); + } + while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { + if (reject_over_limit && ((unsigned int)len > todo)) { + logg(LOGG_ERROR, "%s: File size exceeds StreamMaxLength; refusing to send a truncated quarantine stream. ERROR\n", + display_filename ? display_filename : "STDIN"); + return -1; + } if ((unsigned int)len > todo) len = todo; buf[0] = htonl(len); if (sendln(sockd, (const char *)buf, len + sizeof(uint32_t))) { - close(fd); return -1; } todo -= len; if (!todo) { - len = 0; + if (reject_over_limit) { + len = read(fd, &buf[1], 1); + if (len > 0) { + logg(LOGG_ERROR, "%s: File size exceeds StreamMaxLength; refusing to send a truncated quarantine stream. ERROR\n", + display_filename ? display_filename : "STDIN"); + return -1; + } + } else { + len = 0; + } break; } } - close(fd); if (len) { - logg(LOGG_ERROR, "Failed to read from %s.\n", filename ? filename : "STDIN"); - return 0; + logg(LOGG_ERROR, "Failed to read from %s.\n", display_filename ? display_filename : "STDIN"); + return reject_over_limit ? -1 : 0; } *buf = 0; sendln(sockd, (const char *)buf, 4); return 1; } +int send_stream_fd(int sockd, int fd, const char *display_filename, struct optstruct *clamdopts) +{ + return send_stream_fd_common(sockd, fd, display_filename, clamdopts, false); +} + +int send_stream_fd_action(int sockd, int fd, const char *display_filename, struct optstruct *clamdopts) +{ + return send_stream_fd_common(sockd, fd, display_filename, clamdopts, true); +} + +/* Issues an INSTREAM command to clamd and streams the given file + * Returns >0 on success, 0 soft fail, -1 hard fail */ +int send_stream(int sockd, const char *filename, struct optstruct *clamdopts) +{ + int fd; + int ret; + + if (filename) { + if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) { + logg(LOGG_INFO, "%s: Failed to open file. ERROR\n", filename); + return 0; + } + } else { + /* Read stream from STDIN */ + fd = 0; + } + + ret = send_stream_fd(sockd, fd, filename, clamdopts); + if (0 != fd) { + close(fd); + } + return ret; +} + /* Connects to clamd * Returns a FD or -1 on error */ int dconnect(struct optstruct *clamdopts) @@ -334,18 +405,13 @@ * This is used only in non IDSESSION mode * Returns the number of infected files or -1 on error * NOTE: filename may be NULL for STREAM scantype. */ -int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors, struct optstruct *clamdopts) +int dsresult(int sockd, int scantype, const char *filename, const action_source_t *action_source, bool apply_action, int *printok, int *errors, struct optstruct *clamdopts) { int infected = 0, len = 0, beenthere = 0; char *bol, *eol; struct RCVLN rcv; STATBUF sb; - - if (filename) { - if (1 == chkpath(filename, clamdopts)) { - goto done; - } - } + const char *display_filename = (NULL != action_source) ? action_source->display_path : filename; recvlninit(&rcv, sockd); @@ -375,12 +441,12 @@ case STREAM: /* NULL filename safe in send_stream() */ - len = send_stream(sockd, filename, clamdopts); + len = (NULL != action_source) ? send_stream_fd_action(sockd, action_source->scan_fd, display_filename, clamdopts) : send_stream(sockd, filename, clamdopts); break; #ifdef HAVE_FD_PASSING case FILDES: /* NULL filename safe in send_fdpass() */ - len = send_fdpass(sockd, filename); + len = (NULL != action_source) ? send_fdpass_fd(sockd, action_source->scan_fd) : send_fdpass(sockd, filename); break; #endif } @@ -434,15 +500,14 @@ last_filename[PATH_MAX] = '\0'; } } - if (filename) { + if (display_filename) { if (scantype >= STREAM) { - logg(LOGG_INFO, "%s%s FOUND\n", filename, colon); - if (action) action(filename); + logg(LOGG_INFO, "%s%s FOUND\n", display_filename, colon); + if (apply_action && action && (NULL != action_source)) action(action_source); } else { logg(LOGG_INFO, "%s FOUND\n", bol); *colon = '\0'; - if (action) - action(bol); + if (apply_action && action && (NULL != action_source)) action(action_source); } } } else if (!memcmp(eol - 7, " ERROR", 6)) { @@ -450,9 +515,9 @@ (*errors)++; if (printok) *printok = 0; - if (filename) { + if (display_filename) { if (scantype >= STREAM) - logg(LOGG_INFO, "%s%s\n", filename, colon); + logg(LOGG_INFO, "%s%s\n", display_filename, colon); else logg(LOGG_INFO, "%s\n", bol); } diff -Nru clamav-1.4.3+dfsg/common/clamdcom.h clamav-1.4.6+dfsg/common/clamdcom.h --- clamav-1.4.3+dfsg/common/clamdcom.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/clamdcom.h 2026-08-06 21:12:04.000000000 +0000 @@ -26,12 +26,16 @@ #include "clamav-config.h" #endif +#include + #if HAVE_SYS_PARAM_H #include #endif #include "misc.h" +struct action_source; + enum { CONT, MULTI, @@ -59,9 +63,12 @@ int chkpath(const char *path, struct optstruct *clamdopts); #ifdef HAVE_FD_PASSING +int send_fdpass_fd(int sockd, int fd); int send_fdpass(int sockd, const char *filename); #endif +int send_stream_fd(int sockd, int fd, const char *display_filename, struct optstruct *clamdopts); +int send_stream_fd_action(int sockd, int fd, const char *display_filename, struct optstruct *clamdopts); int send_stream(int sockd, const char *filename, struct optstruct *clamdopts); int dconnect(struct optstruct *clamdopts); -int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors, struct optstruct *clamdopts); +int dsresult(int sockd, int scantype, const char *filename, const struct action_source *action_source, bool apply_action, int *printok, int *errors, struct optstruct *clamdopts); #endif diff -Nru clamav-1.4.3+dfsg/common/output.c clamav-1.4.6+dfsg/common/output.c --- clamav-1.4.3+dfsg/common/output.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/output.c 2026-08-06 21:12:04.000000000 +0000 @@ -170,7 +170,7 @@ pthread_mutex_lock(&mdprintf_mutex); #endif while (todo > 0) { - ret = send(desc, buff, bytes, 0); + ret = send(desc, buff, todo, 0); if (ret < 0) { struct timeval tv; if (errno != EWOULDBLOCK) diff -Nru clamav-1.4.3+dfsg/common/scanmem.c clamav-1.4.6+dfsg/common/scanmem.c --- clamav-1.4.3+dfsg/common/scanmem.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/scanmem.c 2026-08-06 21:12:04.000000000 +0000 @@ -38,22 +38,25 @@ int sock; struct optstruct *clamdopts; -static inline int lookup_cache(filelist_t **list, const char *filename) +static inline bool lookup_cache(filelist_t **list, const char *filename, cl_error_t *result) { filelist_t *current = *list; while (current) { /* Cache hit */ if (!_stricmp(filename, current->filename)) { - return current->res; + if (NULL != result) { + *result = current->res; + } + return true; } current = current->next; } - return -1; + return false; } static inline void insert_cache(filelist_t **list, const char *filename, - int res) + cl_error_t res) { filelist_t *current = *list, *prev = NULL; @@ -89,6 +92,47 @@ } while (current); } +/** + * @brief Resolve a memory module path using the same sharing policy as action + * source opens. + * + * @param path Path to resolve. + * @param resolved_path Resolved path on success. Caller must free it. + * @return cl_error_t CL_SUCCESS if the path was resolved. + */ +static cl_error_t scanmem_resolve_action_path(const char *path, char **resolved_path) +{ + HANDLE handle = INVALID_HANDLE_VALUE; + cl_error_t status = CL_EARG; + + if ((NULL == path) || (NULL == resolved_path)) { + return CL_EARG; + } + + *resolved_path = NULL; + + handle = CreateFileA( + path, + FILE_GENERIC_READ | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (INVALID_HANDLE_VALUE == handle) { + status = CL_EOPEN; + goto done; + } + + status = cli_get_filepath_from_handle(handle, resolved_path); + +done: + if (INVALID_HANDLE_VALUE != handle) { + CloseHandle(handle); + } + return status; +} + static inline char *wc2mb(const wchar_t *wc, DWORD flags) { BOOL invalid = FALSE; @@ -529,22 +573,87 @@ return ret; } -int scanfile(const char *filename, scanmem_data *scan_data, struct mem_info *info) +/* + * filename is the display name for scan output. scan_open_path is the path to + * submit or open for scanning. action_target is the original on-disk module to + * quarantine when scanning a temporary dump of a packed module finds the + * infection. action_open_path is an optional resolved path to open for + * quarantine action; when action_open_path_required is true, action setup fails + * closed instead of opening action_target by its unresolved name. + */ +cl_error_t scanfile( + const char *filename, + const char *scan_open_path, + const char *action_target, + const char *action_open_path, + bool action_open_path_required, + scanmem_data *scan_data, + struct mem_info *info, + action_source_t *infected_action_source) { - int fd; + int fd = -1; int scantype; - int ret = CL_CLEAN; + cl_error_t status = CL_CLEAN; + int infected = 0; + const char *scan_path = (NULL != scan_open_path) ? scan_open_path : filename; + const char *action_display_filename = (NULL != action_target) ? action_target : filename; + bool action_target_is_scan_target = + ((NULL == action_target) || (0 == strcmp(action_target, filename))) && + ((NULL == action_open_path) || (0 == strcmp(action_open_path, scan_path))); + action_source_t action_source; + bool have_action_source = false; + bool action_source_open_failed = false; + bool scan_uses_action_source = false; + cl_error_t action_source_status = CL_SUCCESS; const char *virname = NULL; + int scan_errors_before = 0; + int scan_result = 0; + + action_source_init(&action_source); logg(LOGG_DEBUG, "Scanning %s\n", filename); - if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) == -1) { - logg(LOGG_WARNING, "Can't open file %s, %s\n", filename, strerror(errno)); - return -1; + if (action) { + if (NULL != action_open_path) { + action_source_status = action_source_open_path( + action_display_filename, + action_open_path, + &action_source); + } else if (action_open_path_required) { + action_source_status = CL_EOPEN; + } else { + action_source_status = action_source_open(action_display_filename, &action_source); + } + if (CL_SUCCESS != action_source_status) { + logg(LOGG_WARNING, "Can't open file %s for safe quarantine action: %s\n", action_display_filename, cl_strerror(action_source_status)); + action_source_open_failed = true; + } else { + have_action_source = true; + } + } + + if (have_action_source && action_target_is_scan_target) { + fd = action_source.scan_fd; + scan_uses_action_source = true; + } else if ((fd = safe_open(scan_path, O_RDONLY | O_BINARY)) == -1) { + logg(LOGG_WARNING, "Can't open file %s, %s\n", scan_path, strerror(errno)); + if (have_action_source) { + action_source_close(&action_source); + } + return CL_EOPEN; } if (info->d) { // clamdscan - if (optget(info->opts, "stream")->enabled) + if (scan_uses_action_source) { +#ifdef HAVE_FD_PASSING + if (optget(clamdopts, "LocalSocket")->enabled) { + scantype = FILDES; + } else +#endif + { + scantype = STREAM; + } + } else if (optget(info->opts, "stream")->enabled) scantype = STREAM; else if (optget(info->opts, "multiscan")->enabled) scantype = MULTI; @@ -555,24 +664,66 @@ if ((sock = dconnect(clamdopts)) < 0) { info->errors++; - return -1; + if (!scan_uses_action_source) { + close(fd); + } + if (have_action_source) { + action_source_close(&action_source); + } + return CL_EOPEN; } - if (dsresult(sock, scantype, filename, NULL, &info->errors, clamdopts) > 0) { + scan_errors_before = info->errors; + scan_result = dsresult(sock, scantype, scan_path, scan_uses_action_source ? &action_source : NULL, false, NULL, &info->errors, clamdopts); + if (scan_result > 0) { info->ifiles++; - ret = CL_VIRUS; + status = CL_VIRUS; + infected = 1; + } else if ((scan_result < 0) || (info->errors > scan_errors_before)) { + status = CL_EOPEN; } } else { // clamscan - ret = cl_scandesc(fd, filename, &virname, &info->blocks, info->engine, info->options); - if (ret == CL_VIRUS) { + status = cl_scandesc(fd, filename, &virname, &info->blocks, info->engine, info->options); + if (status == CL_VIRUS) { logg(LOGG_INFO, "%s: %s FOUND\n", filename, virname); info->ifiles++; + infected = 1; } else if (scan_data->printclean) { logg(LOGG_INFO, "%s: OK \n", filename); } } - close(fd); - return ret; + if (!scan_uses_action_source) { + close(fd); + } + fd = -1; + + if (infected && action) { + if (have_action_source) { + if (NULL != infected_action_source) { + *infected_action_source = action_source; + action_source_init(&action_source); + have_action_source = false; + } else { + action(&action_source); + } + } else if (action_source_open_failed) { + if (optget(info->opts, "remove")->enabled) { + notremoved++; + } else { + notmoved++; + } + logg(LOGG_ERROR, "Can't apply quarantine action for scan target '%s': safe source '%s' is unavailable: %s\n", + filename, + action_display_filename, + cl_strerror(action_source_status)); + } + } + + if (have_action_source) { + action_source_close(&action_source); + } + + return status; } int scanmem_cb(PROCESSENTRY32 ProcStruct, MODULEENTRY32 me32, void *data, struct mem_info *info) @@ -582,10 +733,20 @@ int isprocess = 0; char modulename[MAX_PATH] = ""; char expandmodule[MAX_PATH] = ""; + char *resolved_modulename = NULL; + const char *module_scan_path = modulename; + const char *module_action_open_path = NULL; + action_source_t deferred_action_source; + cl_error_t cached_result = CL_CLEAN; + cl_error_t resolve_status = CL_CLEAN; + bool cache_hit = false; + bool module_filter_enabled = false; + bool module_excluded = false; if (!scan_data) return 0; scan_data->res = CL_CLEAN; + action_source_init(&deferred_action_source); modulename[0] = 0; /* Special case, btw why I get \SystemRoot\ in process szExePath? @@ -607,11 +768,14 @@ modulename[MAX_PATH - 1] = 0; } - scan_data->res = lookup_cache(&scan_data->files, modulename); + cache_hit = lookup_cache(&scan_data->files, modulename, &cached_result); + if (cache_hit) { + scan_data->res = cached_result; + } isprocess = !_stricmp(ProcStruct.szExeFile, modulename) || !_stricmp(ProcStruct.szExeFile, me32.szModule); - if (scan_data->res == -1) { + if (!cache_hit) { if (isprocess) scan_data->processes++; else @@ -621,20 +785,65 @@ /* check for module exclusion */ scan_data->res = CL_CLEAN; - if (!(scan_data->exclude && chkpath(modulename, clamdopts))) - scan_data->res = scanfile(modulename, scan_data, info); + module_filter_enabled = info->d || scan_data->exclude; + module_excluded = module_filter_enabled && chkpath(modulename, clamdopts); - if ((scan_data->res != CL_VIRUS) && is_packed(modulename)) { + if (action && !module_excluded) { + resolve_status = scanmem_resolve_action_path(modulename, &resolved_modulename); + if ((CL_SUCCESS == resolve_status) && (NULL != resolved_modulename)) { + module_scan_path = resolved_modulename; + module_action_open_path = resolved_modulename; + if (module_filter_enabled) { + module_excluded = chkpath(resolved_modulename, clamdopts); + } + } else { + logg(LOGG_WARNING, "Can't resolve module path %s for safe quarantine action: %s\n", + modulename, + cl_strerror(resolve_status)); + } + } + + if (!module_excluded) + scan_data->res = scanfile( + modulename, + module_scan_path, + modulename, + module_action_open_path, + NULL != action, + scan_data, + info, + &deferred_action_source); + + if (!module_excluded && (CL_CLEAN == scan_data->res) && is_packed(module_scan_path)) { char *dumped = cli_gentemp(NULL); int fd = -1; if ((fd = dump_pe(dumped, ProcStruct, me32)) > 0) { close(fd); - scan_data->res = scanfile(dumped, scan_data, info); + scan_data->res = scanfile( + dumped, + dumped, + modulename, + module_action_open_path, + NULL != action, + scan_data, + info, + &deferred_action_source); DeleteFileA(dumped); } free(dumped); } - insert_cache(&scan_data->files, modulename, scan_data->res); + /* + * Keep caching clean results. Do not cache infected module results + * while a quarantine action is enabled: move/remove may need to retry + * after kill/unload or after an action failure, and action() does not + * report whether a copy/move/remove succeeded. This can duplicate + * --copy output for a module mapped into multiple processes, but it + * avoids suppressing later move/remove opportunities. + */ + if ((CL_CLEAN == scan_data->res) || + ((CL_VIRUS == scan_data->res) && (NULL == action))) { + insert_cache(&scan_data->files, modulename, scan_data->res); + } } if (scan_data->res == CL_VIRUS) { @@ -645,12 +854,22 @@ logg(LOGG_INFO, "Unloading module %s from %s\n", me32.szModule, modulename); if ((rc = unload_module(ProcStruct.th32ProcessID, me32.hModule)) == -1) /* CreateProcessThread() is not implemented */ - return 0; + goto done; } - if (action) - action(modulename); - return rc; + if (action && !cache_hit) { + if (-1 != deferred_action_source.scan_fd) { + action(&deferred_action_source); + } + } + } + +done: + if (-1 != deferred_action_source.scan_fd) { + action_source_close(&deferred_action_source); + } + if (NULL != resolved_modulename) { + free(resolved_modulename); } return rc; } diff -Nru clamav-1.4.3+dfsg/common/scanmem.h clamav-1.4.6+dfsg/common/scanmem.h --- clamav-1.4.3+dfsg/common/scanmem.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/common/scanmem.h 2026-08-06 21:12:04.000000000 +0000 @@ -22,6 +22,8 @@ #ifndef __SCANMEM_H #define __SCANMEM_H +#include + #ifndef TH32CS_SNAPMODULE32 #define TH32CS_SNAPMODULE32 0x00000010 #endif @@ -33,7 +35,7 @@ /* cache helpers */ typedef struct _filelist_t { char filename[MAX_PATH]; - int res; + cl_error_t res; struct _filelist_t *next; } filelist_t; @@ -48,7 +50,7 @@ typedef struct _scanmem_data_t { filelist_t *files; int printclean, kill, unload, exclude; - int res; + cl_error_t res; uint32_t processes, modules; } scanmem_data; diff -Nru clamav-1.4.3+dfsg/debian/.git-dpm clamav-1.4.6+dfsg/debian/.git-dpm --- clamav-1.4.3+dfsg/debian/.git-dpm 2025-06-29 09:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/.git-dpm 2026-09-05 19:12:04.000000000 +0000 @@ -1,8 +1,8 @@ # see git-dpm(1) from git-dpm package -a93a4e3db36cec1e2c2d1a6ddd4c4ac6df18cbca -a93a4e3db36cec1e2c2d1a6ddd4c4ac6df18cbca -0e1174622bdc4e0335b2f3c20411b0c6ddcc9aae -0e1174622bdc4e0335b2f3c20411b0c6ddcc9aae -clamav_1.4.3+dfsg.orig.tar.xz -9de4123ce7c983eb14b3b103f583628e279945a5 -33173124 +345e96d5f25dc00307b48d8febdac0f7b1622cc5 +345e96d5f25dc00307b48d8febdac0f7b1622cc5 +a14f8c57b30099f0db08ce9db9f3ac550248fe3c +a14f8c57b30099f0db08ce9db9f3ac550248fe3c +clamav_1.4.6+dfsg.orig.tar.xz +d076f78137f51afc0dbb7b67ec476c3c62487089 +27698332 diff -Nru clamav-1.4.3+dfsg/debian/README.Debian clamav-1.4.6+dfsg/debian/README.Debian --- clamav-1.4.3+dfsg/debian/README.Debian 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/README.Debian 2026-09-05 19:12:04.000000000 +0000 @@ -277,7 +277,11 @@ /etc/clamav/onupdateexecute.d, or /etc/clamav/virusevent.d directories, appropriate rules need to be added to the apparmor profile. - If you prefer to fully disable AppArmor confinement for + A common case is ScanOnAccess which for example you'd best allow via + a local overrides (see /etc/apparmor.d/local/README) + echo "capability sys_admin," >> /etc/apparmor.d/local/usr.sbin.clamd + + If you instead prefer to fully disable AppArmor confinement for clamav-daemon or freshclam, run respectively: aa-disable /usr/sbin/clamd diff -Nru clamav-1.4.3+dfsg/debian/changelog clamav-1.4.6+dfsg/debian/changelog --- clamav-1.4.3+dfsg/debian/changelog 2025-06-29 10:01:31.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/changelog 2026-09-05 19:13:32.000000000 +0000 @@ -1,3 +1,54 @@ +clamav (1.4.6+dfsg-1~deb13u1) trixie; urgency=medium + + [ Sebastian Andrzej Siewior ] + * Import 1.4.5 + - CVE-2026-20031 (Fixed an error handling bug in the HTML file parser) + - Fixes a few bugs scanning JPEG/ TIFF files (Closes: #1120998) + - CVE-2026-20217 ("Fixed a bug in the PESpin unpacker cleanup path") + - CVE-2026-20213 ("Fixed an integer overflow in PE rebuild size + calculations") + - CVE-2026-20216 ("Fixed an InstallShield archive extraction limit + bypass") + - CVE-2026-20214 ("Fixed an FSG unpacker loop underflow") + - CVE-2026-20243 ("Fixed ALZ parser size handling bugs") + - CVE-2026-20215 ("Fixed a 7z parser substream count overflow") + - CVE-2026-20244 ("Fixed 32-bit DMG parser size checks") + * Update apparmor profile for clamd (Closes: #1092882, #1123913). + * Use -DCMAKE_BUILD_TYPE=RelWithDebInfo by default (Closes: #1141347). + * Add Romanian debconf templates translation (Closes: #1103001). + * Mention in the README.Debian that clamAV AppArmor profiles do not allow + OnAccess scanning ("Closes: #1043428). + + [ Pino Toscano ] + * Make sure to ignore the not installed files on all the architectures. + * Limit systemd build dependencies as linux-any, as systemd is available only + on Linux. + * Simplify handling of Linux-only files by using dh-exec, rather than creating + install and manpages files during build: + - add the dh-exec build dependency + - mark the Linux-only files in install and manpages files + - simplify debian/rules accordingly + * Wrap the whole override_dh_installsystemd to run on Linux, rather than only + the first command in it. + + [ Pétur Ingi Egilsson ] + * clamav-daemon.postinst.in: honour "none" as a way to disable + the LogFile directive. + + [ Edmund Lodewijks ] + * Import 1.4.6 (Closes: #1143939) + - CVE-2026-20345 ("Fixed an indexing error while converting GPT + partition names") + - CVE-2026-20339 ("Fixed an integer overflow in the PESpin unpacker") + - CVE-2026-20346 ("Fixed an integer underflow in the PDF parser") + - CVE-2026-20347 ("Fixed undefined behavior and integer overflow in the + Mach-O parser") + - CVE-2026-20348 ("Fixed XAR parser size handling") + - Fixed thread-safety issues in the clamd STATS command that could + disclose process memory or crash the daemon + + -- Sebastian Andrzej Siewior Sat, 05 Sep 2026 21:13:32 +0200 + clamav (1.4.3+dfsg-1) unstable; urgency=medium * Import 1.4.3 diff -Nru clamav-1.4.3+dfsg/debian/clamav-base.postinst.in clamav-1.4.6+dfsg/debian/clamav-base.postinst.in --- clamav-1.4.3+dfsg/debian/clamav-base.postinst.in 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-base.postinst.in 2026-09-05 19:12:04.000000000 +0000 @@ -30,13 +30,8 @@ LOGDIR=/var/log/clamav user=clamav - # Set up the clamav user on new install + # Set up the clamav aliases on new install if [ -z "$2" ]; then - if ! id clamav; then - adduser --system --no-create-home --quiet \ - --disabled-password --disabled-login \ - --shell /bin/false --group --home /var/lib/clamav clamav - fi if [ -f /etc/aliases ] || [ -L /etc/aliases ]; then if ! grep -qi "^clamav" /etc/aliases; then echo "clamav: root" >> /etc/aliases @@ -47,8 +42,6 @@ fi fi fi - chown $user:$user $DATABASEDIR - chown $user:$user $LOGDIR ;; abort-upgrade|abort-remove|abort-deconfigure) ;; diff -Nru clamav-1.4.3+dfsg/debian/clamav-base.sysusers clamav-1.4.6+dfsg/debian/clamav-base.sysusers --- clamav-1.4.3+dfsg/debian/clamav-base.sysusers 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-base.sysusers 2026-09-05 19:12:04.000000000 +0000 @@ -0,0 +1 @@ +u! clamav - - /var/lib/clamav /bin/false diff -Nru clamav-1.4.3+dfsg/debian/clamav-base.tmpfiles clamav-1.4.6+dfsg/debian/clamav-base.tmpfiles --- clamav-1.4.3+dfsg/debian/clamav-base.tmpfiles 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-base.tmpfiles 2026-09-05 19:12:04.000000000 +0000 @@ -0,0 +1,2 @@ +d /var/lib/clamav 0755 clamav clamav +d /var/log/clamav 0755 clamav clamav diff -Nru clamav-1.4.3+dfsg/debian/clamav-daemon.install clamav-1.4.6+dfsg/debian/clamav-daemon.install --- clamav-1.4.3+dfsg/debian/clamav-daemon.install 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-daemon.install 2026-09-05 19:12:04.000000000 +0000 @@ -1,9 +1,10 @@ +#!/usr/bin/dh-exec debian/script usr/share/bug/clamav-daemon/ -debian/tmp/lib/systemd/system/clamav-daemon.service usr/lib/systemd/system/ -debian/tmp/lib/systemd/system/clamav-clamonacc.service usr/lib/systemd/system/ -debian/tmp/lib/systemd/system/clamav-daemon.socket usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-daemon.service usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-clamonacc.service usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-daemon.socket usr/lib/systemd/system/ debian/tmp/usr/bin/clamconf debian/tmp/usr/bin/clamdtop -debian/tmp/usr/sbin/clamonacc +[linux-any] debian/tmp/usr/sbin/clamonacc debian/tmp/usr/sbin/clamd debian/usr.sbin.clamd etc/apparmor.d/ diff -Nru clamav-1.4.3+dfsg/debian/clamav-daemon.logcheck.ignore.paranoid clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.paranoid --- clamav-1.4.3+dfsg/debian/clamav-daemon.logcheck.ignore.paranoid 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.paranoid 2026-09-05 19:12:04.000000000 +0000 @@ -1,6 +1,6 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: SelfCheck: Database status OK\.$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: Reading databases from .*$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: Database correctly reloaded \([0-9]+ signatures\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: SIGHUP caught: re-opening log file\.$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: No stats for Database check - forcing reload$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: SelfCheck: Database modification detected\. Forcing reload\.$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: SelfCheck: Database status OK\.$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: Reading databases from .*$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: Database correctly reloaded \([0-9]+ signatures\)$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: SIGHUP caught: re-opening log file\.$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: No stats for Database check - forcing reload$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: SelfCheck: Database modification detected\. Forcing reload\.$ diff -Nru clamav-1.4.3+dfsg/debian/clamav-daemon.logcheck.ignore.server clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.server --- clamav-1.4.3+dfsg/debian/clamav-daemon.logcheck.ignore.server 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-daemon.logcheck.ignore.server 2026-09-05 19:12:04.000000000 +0000 @@ -1 +1 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamd\[[0-9]+\]: .* (FOUND|OK)$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamd\[[0-9]+\]: .* (FOUND|OK)$ diff -Nru clamav-1.4.3+dfsg/debian/clamav-daemon.manpages clamav-1.4.6+dfsg/debian/clamav-daemon.manpages --- clamav-1.4.3+dfsg/debian/clamav-daemon.manpages 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-daemon.manpages 2026-09-05 19:12:04.000000000 +0000 @@ -1,5 +1,6 @@ +#!/usr/bin/dh-exec debian/tmp/usr/share/man/man1/clamconf.1 debian/tmp/usr/share/man/man1/clamdtop.1 debian/tmp/usr/share/man/man5/clamd.conf.5 debian/tmp/usr/share/man/man8/clamd.8 -debian/tmp/usr/share/man/man8/clamonacc.8 +[linux-any] debian/tmp/usr/share/man/man8/clamonacc.8 diff -Nru clamav-1.4.3+dfsg/debian/clamav-daemon.postinst.in clamav-1.4.6+dfsg/debian/clamav-daemon.postinst.in --- clamav-1.4.3+dfsg/debian/clamav-daemon.postinst.in 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-daemon.postinst.in 2026-09-05 19:12:04.000000000 +0000 @@ -99,7 +99,13 @@ db_get clamav-daemon/LogSyslog || true LogSyslog="$RET" db_get clamav-daemon/LogFile || true - if [ "$RET" != "" ]; then + # The template advertises "none" as a way to disable file logging. + # Treat it the same as an empty answer so all downstream + # `[ -n "$LogFile" ]` guards skip the directive write, the touch, + # the chown, and the logrotate snippet. Otherwise the literal + # string "none" lands in /etc/clamav/clamd.conf and clamd refuses + # to start with: ERROR: LogFile requires full path. + if [ "$RET" != "" ] && [ "$RET" != "none" ]; then LogFile="$RET" db_get clamav-daemon/LogTime || true LogTime="$RET" diff -Nru clamav-1.4.3+dfsg/debian/clamav-freshclam.install clamav-1.4.6+dfsg/debian/clamav-freshclam.install --- clamav-1.4.3+dfsg/debian/clamav-freshclam.install 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-freshclam.install 2026-09-05 19:12:04.000000000 +0000 @@ -1,10 +1,11 @@ +#!/usr/bin/dh-exec debian/clamav-freshclam-ifupdown etc/network/if-down.d/ debian/clamav-freshclam-ifupdown etc/network/if-up.d/ debian/clamav-freshclam-ifupdown etc/ppp/ip-down.d/ debian/clamav-freshclam-ifupdown etc/ppp/ip-up.d/ debian/script usr/share/bug/clamav-freshclam/ -debian/tmp/lib/systemd/system/clamav-freshclam-once.service usr/lib/systemd/system/ -debian/tmp/lib/systemd/system/clamav-freshclam-once.timer usr/lib/systemd/system/ -debian/tmp/lib/systemd/system/clamav-freshclam.service usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-freshclam-once.service usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-freshclam-once.timer usr/lib/systemd/system/ +[linux-any] debian/tmp/lib/systemd/system/clamav-freshclam.service usr/lib/systemd/system/ debian/tmp/usr/bin/freshclam debian/usr.bin.freshclam etc/apparmor.d/ diff -Nru clamav-1.4.3+dfsg/debian/clamav-freshclam.logcheck.ignore.server clamav-1.4.6+dfsg/debian/clamav-freshclam.logcheck.ignore.server --- clamav-1.4.3+dfsg/debian/clamav-freshclam.logcheck.ignore.server 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-freshclam.logcheck.ignore.server 2026-09-05 19:12:04.000000000 +0000 @@ -1,7 +1,7 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: ClamAV update process started at .*$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: Received signal: (wake up|re-opening log file)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: (bytecode|daily|main)\.c(l|v)d (is up to date|updated) \(version: [0-9]+, sigs: [0-9]+, f-level: [0-9]+, builder: \w+\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: Clamd successfully notified about the update\.$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: --------------------------------------$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: Database updated \([0-9]+ signatures\) from .* \(IP: [0-9.]+\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ freshclam\[[0-9]+\]: Downloading daily-[0-9]+.cdiff \[100%\] ?$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: ClamAV update process started at .*$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: Received signal: (wake up|re-opening log file)$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: (bytecode|daily|main)\.c(l|v)d (is up to date|updated) \(version: [0-9]+, sigs: [0-9]+, f-level: [0-9]+, builder: \w+\)$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: Clamd successfully notified about the update\.$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: --------------------------------------$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: Database updated \([0-9]+ signatures\) from .* \(IP: [0-9.]+\)$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ freshclam\[[0-9]+\]: Downloading daily-[0-9]+.cdiff \[100%\] ?$ diff -Nru clamav-1.4.3+dfsg/debian/clamav-freshclam.postinst.in clamav-1.4.6+dfsg/debian/clamav-freshclam.postinst.in --- clamav-1.4.3+dfsg/debian/clamav-freshclam.postinst.in 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-freshclam.postinst.in 2026-09-05 19:12:04.000000000 +0000 @@ -38,6 +38,23 @@ case "$1" in configure) + # Install Apparmor profile before starting the daemon + APP_PROFILE="/etc/apparmor.d/usr.bin.freshclam" + if [ -f "$APP_PROFILE" ]; then + # Add the local/ include + LOCAL_APP_PROFILE="/etc/apparmor.d/local/usr.bin.freshclam" + + test -e "$LOCAL_APP_PROFILE" || { + mkdir -p `dirname "$LOCAL_APP_PROFILE"` + install --mode 644 /dev/null "$LOCAL_APP_PROFILE" + } + + # Reload the profile, including any abstraction updates + if aa-enabled --quiet 2>/dev/null; then + apparmor_parser -r -T -W "$APP_PROFILE" || true + fi + fi + # Configure the hardcoded stuff dbowner=clamav udlogfile="$FRESHCLAMLOGFILE" diff -Nru clamav-1.4.3+dfsg/debian/clamav-milter.logcheck.ignore.paranoid clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.paranoid --- clamav-1.4.3+dfsg/debian/clamav-milter.logcheck.ignore.paranoid 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.paranoid 2026-09-05 19:12:04.000000000 +0000 @@ -1,4 +1,4 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: Loading new database$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: ClamAV: Protecting against [0-9]+ viruses$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: Loaded ClamAV [/: [:alnum:]]+ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: [[:alnum:]]+: clean message from +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: Loading new database$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: ClamAV: Protecting against [0-9]+ viruses$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: Loaded ClamAV [/: [:alnum:]]+ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: [[:alnum:]]+: clean message from diff -Nru clamav-1.4.3+dfsg/debian/clamav-milter.logcheck.ignore.server clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.server --- clamav-1.4.3+dfsg/debian/clamav-milter.logcheck.ignore.server 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/clamav-milter.logcheck.ignore.server 2026-09-05 19:12:04.000000000 +0000 @@ -1,2 +1,2 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: [_[:alnum:]-]+: [/.[:alnum:]-]+: [._[:alnum:]-]+ Intercepted virus from -^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ clamav-milter\[[[:digit:]]{,5}\]: Can't resolve LocalNet hostname unknown$ +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[0-9]+\]: [_[:alnum:]-]+: [/.[:alnum:]-]+: [._[:alnum:]-]+ Intercepted virus from +^(\w{3} [ :0-9]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ clamav-milter\[[[:digit:]]{,5}\]: Can't resolve LocalNet hostname unknown$ diff -Nru clamav-1.4.3+dfsg/debian/control clamav-1.4.6+dfsg/debian/control --- clamav-1.4.3+dfsg/debian/control 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/control 2026-09-05 19:13:08.000000000 +0000 @@ -7,13 +7,14 @@ Scott Kitterman , Sebastian Andrzej Siewior , Andreas Cadhalpun -Build-Depends: dpkg-dev (>= 1.22.5), automake, +Build-Depends: dpkg-dev (>= 1.22.5), automake, dh-sequence-installsysusers, bindgen, - cargo, + cargo-web, check, cmake, debhelper-compat (= 12), dh-apparmor, + dh-exec, dh-strip-nondeterminism, doxygen, libbz2-dev, @@ -25,15 +26,16 @@ libncurses-dev, libpcre2-dev, libssl-dev, - libsystemd-dev [linux-any], systemd-dev, + libsystemd-dev [linux-any], systemd-dev [linux-any], libxml2-dev, perl:native, pkg-config, po-debconf, python3-pytest, - rust-gdb, - rustfmt, - systemd, + rust-web-gdb, + rustfmt-web, + rustc-web, + systemd [linux-any], zlib1g-dev Standards-Version: 4.7.0 Rules-Requires-Root: no @@ -44,7 +46,7 @@ Package: clamav-base Architecture: all Multi-Arch: foreign -Depends: adduser, logrotate, ucf, ${misc:Depends} +Depends: logrotate, ucf, ${misc:Depends} Recommends: clamav Description: anti-virus utility for Unix - base package Clam AntiVirus is an anti-virus toolkit for Unix. The main purpose of diff -Nru clamav-1.4.3+dfsg/debian/libclamav12.symbols clamav-1.4.6+dfsg/debian/libclamav12.symbols --- clamav-1.4.3+dfsg/debian/libclamav12.symbols 2025-06-29 10:01:17.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/libclamav12.symbols 2026-09-05 19:12:04.000000000 +0000 @@ -3,10 +3,10 @@ *@CLAMAV_0.104.0 1.2.1 *@CLAMAV_1.0.0 1.2.1 *@CLAMAV_1.1.0 1.2.1 - *@CLAMAV_PRIVATE 1.4.3 + *@CLAMAV_PRIVATE 1.4.6 *@CLAMAV_PUBLIC 1.2.1 - cl_retflevel@CLAMAV_PUBLIC 1.4.3 + cl_retflevel@CLAMAV_PUBLIC 1.4.6 libfreshclam.so.3 libclamav12 #MINVER# * Build-Depends-Package: libclamav-dev - *@FRESHCLAM_PRIVATE 1.4.3 - *@FRESHCLAM_PUBLIC 1.4.3 + *@FRESHCLAM_PRIVATE 1.4.6 + *@FRESHCLAM_PUBLIC 1.4.6 diff -Nru clamav-1.4.3+dfsg/debian/not-installed clamav-1.4.6+dfsg/debian/not-installed --- clamav-1.4.3+dfsg/debian/not-installed 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/not-installed 2026-09-05 19:12:04.000000000 +0000 @@ -1,2 +1,2 @@ -usr/lib/x86_64-linux-gnu/libclamav_rust.a +usr/lib/*/libclamav_rust.a usr/share/doc/ClamAV/html/ diff -Nru clamav-1.4.3+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch clamav-1.4.6+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch --- clamav-1.4.3+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch 2025-06-29 09:41:34.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch 2026-09-05 19:12:04.000000000 +0000 @@ -1,4 +1,4 @@ -From a93a4e3db36cec1e2c2d1a6ddd4c4ac6df18cbca Mon Sep 17 00:00:00 2001 +From 345e96d5f25dc00307b48d8febdac0f7b1622cc5 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Mon, 10 Mar 2014 19:20:18 -0400 Subject: Change paths in sample conf file to match Debian diff -Nru clamav-1.4.3+dfsg/debian/po/ca.po clamav-1.4.6+dfsg/debian/po/ca.po --- clamav-1.4.3+dfsg/debian/po/ca.po 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/po/ca.po 2026-09-05 19:12:04.000000000 +0000 @@ -0,0 +1,1509 @@ +# Catalan translation of clamav's debconf messages +# Copyright © 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the clamav package. +# poc senderi , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: clamav\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-02-09 14:42+0000\n" +"PO-Revision-Date: 2025-02-18 22:05+0100\n" +"Last-Translator: poc senderi \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.2.2\n" + +#. Type: select +#. Choices +#: ../clamav-freshclam.templates:2001 +msgid "daemon" +msgstr "dimoni" + +#. Type: select +#. Choices +#: ../clamav-freshclam.templates:2001 +msgid "manual" +msgstr "manual" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "Virus database update method:" +msgstr "Mètode d'actualització de la base de dades de virus:" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "Please choose the method for virus database updates." +msgstr "" +"Trieu el mètode per a les actualitzacions de la base de dades de virus." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "" +" daemon: freshclam is running as a daemon all the time. You should choose\n" +" this option if you have a permanent network connection;\n" +" ifup.d: freshclam will be running as a daemon as long as your Internet\n" +" connection is up. Choose this one if you use a dialup Internet\n" +" connection and don't want freshclam to initiate new connections;\n" +" cron: freshclam is started from cron. Choose this if you want full " +"control\n" +" of when the database is updated;\n" +" manual: no automatic invocation of freshclam. This is not recommended,\n" +" as ClamAV's database is constantly updated." +msgstr "" +" dimoni: el «freshclam» s'executa com a dimoni permanentment. Heu de triar " +"aquesta opció si teniu una connexió de xarxa permanent;\n" +" ifup.d: el «freshclam» s'executarà com a dimoni mentre duri la connexió a " +"Internet. Trieu aquesta si utilitzeu una internet via trucada («dialup») i " +"no voleu que el «freshclam» iniciï noves connexions;\n" +" cron: el «freshclam» s'inicia des del «cron». Trieu aquesta si voleu un " +"control complet de cada quan s'actualitza la base de dades;\n" +" manual: sense invocació automàtica del «freshclam». Això no és recomanable, " +"atès que la base de dades de ClamAV s'actualitza constantment." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "Local database mirror site:" +msgstr "Lloc de la rèplica local de la base de dades:" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "Please select the closest local mirror site." +msgstr "Seleccioneu el lloc amb la rèplica local més propera." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "" +"Freshclam updates its database from a world wide network of mirror sites. " +"Please select the closest mirror. If you leave the default setting, an " +"attempt will be made to guess a nearby mirror." +msgstr "" +"El «freshclam» actualitza la base de dades des d'una àmplia xarxa mundial de " +"llocs replicats. Seleccioneu la rèplica més propera. Si deixeu la " +"configuració predeterminada, s'intentarà buscar una rèplica propera." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "HTTP proxy information (leave blank for none):" +msgstr "" +"Informació del servidor intermediari HTTP (deixeu-ho en blanc si no n'hi ha):" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "" +"If you need to use an HTTP proxy to access the outside world, enter the " +"proxy information here. Otherwise, leave this blank." +msgstr "" +"Si necessiteu utilitzar un servidor intermediari HTTP per accedir al món " +"exterior, introduïu la informació del servidor intermediari aquí. En cas " +"contrari, deixeu-ho en blanc." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "Please use URL syntax (\"http://host[:port]\") here." +msgstr "Utilitzeu aquí sintaxi d'URL («http://amfitrió[:port]»)." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "Proxy user information (leave blank for none):" +msgstr "" +"Informació de l'usuari del servidor intermediari (deixeu-ho en blanc si no " +"n'hi ha):" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "" +"If you need to supply a username and password to the proxy, enter it here. " +"Otherwise, leave this blank." +msgstr "" +"Si necessiteu proporcionar un nom d'usuari i una contrasenya al servidor " +"intermediari, introduïu-los aquí. En cas contrari, deixeu-ho en blanc." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "When entering user information, use the standard form of \"user:pass\"." +msgstr "" +"En introduir la informació de l'usuari, utilitzeu el format habitual «usuari:" +"clau»." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:6001 +msgid "Number of freshclam updates per day:" +msgstr "Nombre diari d'actualitzacions del «freshclam»:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "Network interface connected to the Internet:" +msgstr "Interfície de xarxa connectada a Internet:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"Please enter the name of the network interface connected to the Internet. " +"Example: eth0." +msgstr "" +"Introduïu el nom de la interfície de xarxa connectada a Internet. Per " +"exemple: «eth0»." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"If the daemon runs when the network is down, the log file will be filled " +"with entries like 'ERROR: Connection with database.clamav.net failed.', " +"making it easy to miss when freshclam really can't update the database." +msgstr "" +"Si el dimoni s'executa quan la xarxa està desconnectada, el fitxer de " +"registre s'omplirà amb entrades com ara «ERROR: La connexió amb «database." +"clamav.net» ha fallat». Això fa que sigui fàcil no adonar-se'n quan el " +"«freshclam» realment no ha pogut actualitzar la base de dades." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"You can leave this field blank and the daemon will be started from the " +"initialization scripts instead. You should then make sure the computer is " +"permanently connected to the Internet to avoid filling the log files." +msgstr "" +"Podeu deixar aquest camp en blanc i el dimoni s'iniciarà a partir dels " +"scripts d'inicialització. Heu d'assegurar-vos que l'ordinador estigui " +"connectat permanentment a Internet per evitar omplir els fitxers de registre." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"If the computer has multiple network interfaces connecting to the Internet " +"use a space-separated list of device names." +msgstr "" +"Si l'ordinador té diverses interfícies de xarxa connectades a Internet, " +"utilitzeu una llista amb els noms dels dispositius separats amb espais." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "Should clamd be notified after updates?" +msgstr "Cal notificar al «clamd» després de les actualitzacions?" + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "" +"Please confirm whether clamd should be notified to reload the database after " +"successful updates." +msgstr "" +"Confirmeu si el «clamd» ha de ser notificat per tornar a carregar la base de " +"dades després d'actualitzacions exitoses." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "" +"If you do not choose this option, clamd's database reloads will be notably " +"delayed (it performs this check every 6 hours by default), posing the risk " +"that a new virus may slip through even if the database is up to date. Do not " +"use this if you do not use clamd, as it will produce errors." +msgstr "" +"Si no trieu aquesta opció, les recàrregues de la base de dades del «clamd» " +"es retardaran notablement (aquesta comprovació es realitza per defecte cada " +"6 hores), la qual cosa suposa el risc que un nou virus pugui colar-se fins i " +"tot si la base de dades està actualitzada. No utilitzeu això si no utilitzeu " +"«clamd», ja que produirà errors." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:9001 +msgid "Do you want to download the bytecode database?" +msgstr "Voleu descarregar la base de dades de «bytecode»?" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:10001 +msgid "Private mirror for freshclam:" +msgstr "Rèplica privada per al «freshclam»:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:10001 +msgid "" +"This option allows you to easily point freshclam to private mirrors. If " +"PrivateMirror is set, freshclam does not attempt to use DNS to determine " +"whether its databases are out-of-date, instead it will use the If-Modified-" +"Since request or directly check the headers of the remote database files. " +"For each database, freshclam first attempts to download the CLD file. If " +"that fails, it tries to download the CVD file. This option overrides " +"DatabaseMirror, DNSDatabaseInfo and ScriptedUpdates. It can be used multiple " +"times to provide fall-back mirrors." +msgstr "" +"Aquesta opció us permet fàcilment fer que el «freshclam» apunti a rèpliques " +"privades. Si PrivateMirror està establert, el «freshclam» no intenta " +"utilitzar el DNS per a determinar si les seves bases de dades estan " +"obsoletes, en lloc d'això utilitzarà la sol·licitud If-Modified-Since o " +"directament comprovar les capçaleres dels fitxers remots de la base de " +"dades. Per a cada base de dades, el «freshclam» primer intenta descarregar " +"el fitxer CLD. Si això falla, intenta descarregar el fitxer CVD. Aquesta " +"opció substitueix DatabaseMirror, DNSDatabaseInfo i ScriptedUpdates. Es pot " +"utilitzar diverses vegades per proporcionar rèpliques de recanvi." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:11001 ../clamav-daemon.templates:22001 +#: ../clamav-milter.templates:32001 +msgid "Do you want to enable log rotation?" +msgstr "Voleu habilitar la rotació del registre?" + +#. Type: error +#. Description +#: ../clamav-base.templates:2001 +msgid "Mandatory numeric value" +msgstr "És obligatori un valor numèric" + +#. Type: error +#. Description +#: ../clamav-base.templates:2001 +msgid "This question requires a numeric answer." +msgstr "Aquesta pregunta requereix una resposta numèrica." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 ../clamav-milter.templates:2001 +msgid "Handle the configuration file automatically?" +msgstr "Voleu gestionar el fitxer de configuració automàticament?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 +msgid "Some options must be configured for clamav-daemon." +msgstr "Algunes opcions del «clamav-daemon» s'han de configurar." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 +msgid "" +"The ClamAV suite won't work if it isn't configured. If you do not configure " +"it automatically, you'll have to configure /etc/clamav/clamd.conf manually " +"or run 'dpkg-reconfigure clamav-daemon' later. In any case, manual changes " +"in /etc/clamav/clamd.conf will be respected." +msgstr "" +"La suite ClamAV no funcionarà si no està configurada. Si no la configureu " +"automàticament haureu de configurar «/etc/clamav/clamd.conf» manualment o " +"executar «dpkg-reconfigure clamav-daemon» més endavant. En qualsevol cas, es " +"respectaran els canvis manuals a «/etc/clamav/clamd.conf»." + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "Socket type:" +msgstr "Tipus de sòcol:" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "Please choose the type of socket clamd will be listening on." +msgstr "Trieu el tipus de sòcol que s'escoltarà." + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "" +"If you choose TCP, clamd can be accessed remotely. If you choose local UNIX " +"sockets, clamd can be accessed through a file. Local UNIX sockets are " +"recommended for security reasons." +msgstr "" +"Si trieu TCP, es podrà accedir al «clamd» de forma remota. Si trieu sòcols " +"locals d'UNIX, es podrà accedir al «clamd» a través d'un fitxer. Per raons " +"de seguretat, es recomanen els sòcols locals UNIX." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:4001 +msgid "Local (UNIX) socket clamd will listen on:" +msgstr "El sòcol local (UNIX) on el «clamd» escoltarà:" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:5001 +msgid "Gracefully handle left-over UNIX socket files?" +msgstr "Voleu gestionar els fitxers de sòcol UNIX que queden abandonats?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:6001 +msgid "Group owner of clamd local (UNIX) socket:" +msgstr "Propietari del sòcol (UNIX) del «clamd» local:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:7001 +msgid "Creation mode for clamd local (UNIX) socket:" +msgstr "Mode de creació per al sòcol (UNIX) del «clamd» local:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:8001 +msgid "TCP port clamd will listen on:" +msgstr "El port TCP on escoltarà el «clamd»:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:9001 +msgid "IP address clamd will listen on:" +msgstr "Adreça IP on escoltarà el «clamd»:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:9001 +msgid "" +"Enter \"any\" to listen on every IP address configured. If you want to " +"listen on a single address or host name, enter it here." +msgstr "" +"Introduïu «any» per escoltar en totes les adreces IP configurades. Si voleu " +"escoltar en una única adreça o nom d'amfitrió, introduïu-lo aquí." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:10001 +msgid "Do you want to enable mail scanning?" +msgstr "Voleu habilitar l'escaneig de correu?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:10001 +msgid "" +"This option enables scanning mail contents for viruses. You need this option " +"enabled if you want to use clamav-milter, or if you want to enable phishing " +"checks." +msgstr "" +"Aquesta opció permet escanejar el contingut del correu buscant-hi virus. " +"Necessiteu aquesta opció habilitada si voleu utilitzar el «clamav-milter», o " +"si voleu habilitar les comprovacions de «phishing»." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "Do you want to enable archive scanning?" +msgstr "Voleu habilitar l'escaneig d'arxius?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "" +"If archive scanning is enabled, the daemon will extract archives such as " +"bz2, tar.gz, deb and many more, to check their contents for viruses." +msgstr "" +"Si l'escaneig d'arxius està activat, el dimoni descomprimeix arxius com " +"«bz2», «tar.gz», «deb» i molts més, per comprovar el seu contingut buscant-" +"hi virus." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "" +"For more information about what archives are supported, see /usr/share/doc/" +"clamav-docs/clamdoc.pdf or the manpage clamscan(5)." +msgstr "" +"Per a més informació sobre quins arxius estan suportats, vegeu «/usr/share/" +"doc/clamav-docs/clamdoc.pdf» o la plana «clamscan(5)» del manual." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:12001 +msgid "Maximum stream length (unit Mb) allowed:" +msgstr "Longitud màxima permesa del flux (en Mb):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:12001 +msgid "You can set a limit on the stream length that can be scanned." +msgstr "Podeu establir un límit a la longitud del flux que es pot escanejar." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "Maximum directory depth that will be allowed:" +msgstr "Profunditat màxima del directori que es permetrà:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "" +"This value must be set if you want to allow the daemon to follow directory " +"symlinks." +msgstr "" +"S'ha d'establir aquest valor si voleu permetre que el dimoni segueixi els " +"enllaços simbòlics a directoris." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "Entering '0' will disable this limit." +msgstr "Si hi introduïu «0» es desactivarà aquest límit." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:14001 +msgid "Do you want the daemon to follow directory symlinks?" +msgstr "Voleu que el dimoni segueixi els enllaços simbòlics a directoris?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:15001 +msgid "Do you want the daemon to follow regular file symlinks?" +msgstr "Voleu que el dimoni segueixi enllaços simbòlics a fitxers normals?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:16001 +msgid "Timeout for stopping the thread-scanner (seconds):" +msgstr "" +"Temps d'espera per aturar l'escàner basat en fils d'execució (en segons):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:16001 +msgid "Entering '0' will disable the timeout." +msgstr "Si s'introdueix un «0» es desactivarà el temps d'espera." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:17001 +msgid "Number of threads for the daemon:" +msgstr "Nombre de fils d'execució del dimoni:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:18001 +msgid "Number of pending connections allowed:" +msgstr "Nombre de connexions pendents permeses:" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:19001 +msgid "Do you want to use the system logger?" +msgstr "Voleu utilitzar el registre del sistema?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:19001 +msgid "" +"It is possible to log the daemon activity to the system logger. This can be " +"done independently of whether you want to log activity to a special file." +msgstr "" +"És possible registrar l'activitat del dimoni al registre del sistema. Això " +"es pot fer independentment de si voleu registrar l'activitat a un fitxer " +"especial." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:20001 +msgid "Log file for clamav-daemon (enter none to disable):" +msgstr "" +"Fitxer de registre del «clamav-daemon» (introduïu «none» per a desactivar-" +"ho):" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:21001 +msgid "Do you want to log time information with each message?" +msgstr "Voleu registrar la informació del temps amb cada missatge?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:23001 +msgid "Maximum file size to scan:" +msgstr "Mida màxima del fitxer a explorar:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:23001 +msgid "A value of 0 disables the limit." +msgstr "Un valor de 0 inhabilita el límit." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:24001 +msgid "Do you want to permit the use of the ALLMATCHSCAN command?" +msgstr "Voleu permetre l'ús de l'ordre ALLMATCHSCAN?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:24001 +msgid "If set to no, clamd will reject any ALLMATCHSCAN command as invalid." +msgstr "" +"Si s'estableix a no, el «clamd» rebutjarà qualsevol ordre ALLMATCHSCAN com a " +"no vàlida." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:25001 +msgid "Do you want memory or nested map scans to dump the content to disk?" +msgstr "" +"Voleu que els escanejos en memòria o de mapes imbricats bolquin el contingut " +"al disc?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:25001 +msgid "" +"If you turn on this option, more data is written to disk and is available " +"when the LeaveTemporaryFiles option is enabled." +msgstr "" +"Si activeu aquesta opció, s'escriuran més dades al disc i estaran " +"disponibles quan l'opció LeaveTemporaryFiles estigui activada." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:26001 +msgid "Do you want to completely turn off authenticode verification?" +msgstr "Voleu desactivar completament la verificació «authenticode»?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:26001 +msgid "" +"Certain PE files contain an authenticode signature. By default the signature " +"chain in the PE file is checked against a database of trusted and revoked " +"certificates if the file being scanned is marked as a virus. If any " +"certificate in the chain validates against any trusted root, but does not " +"match any revoked certificate, the file is marked as whitelisted. If the " +"file does match a revoked certificate, the file is marked as virus." +msgstr "" +"Alguns fitxers PE contenen una signatura «authenticode». Per defecte, la " +"cadena de signatura del fitxer PE es comprova amb una base de dades de " +"certificats confiables i revocats, si el fitxer que s'està escanejant està " +"marcat com a virus. Si qualsevol certificat de la cadena valida contra " +"qualsevol arrel de confiança, però no coincideix amb cap certificat revocat, " +"el fitxer es marca com a acceptat. Si el fitxer coincideix amb un certificat " +"revocat, el fitxer es marca com a virus." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:27001 +msgid "Do you want to enable scanning within SWF files?" +msgstr "Voleu habilitar l'escaneig dins dels fitxers SWF?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:27001 +msgid "" +"If you turn off this option, the original files will still be scanned, but " +"without decoding and additional processing." +msgstr "" +"Si desactiveu aquesta opció, els fitxers originals s'escanejaran igualment, " +"però sense descodificar-los ni processaments addicionals." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:28001 +msgid "Maximum size of a file to check for embedded PE:" +msgstr "Mida màxima d'un fitxer per buscar-hi un PE incrustat:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:28001 +msgid "" +"Files larger than this value will skip the additional analysis step. Note: " +"disabling this limit or setting it too high may result in severe damage to " +"the system." +msgstr "" +"Els fitxers més grans que aquest valor ometran el pas d'anàlisi addicional. " +"Nota: desactivar aquest límit o establir-lo massa alt pot provocar danys " +"greus al sistema." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:29001 +msgid "Maximum size of a HTML file to normalize:" +msgstr "Mida màxima d'un fitxer HTML per normalitzar:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:29001 +msgid "" +"HTML files larger than this value will not be normalized or scanned. Note: " +"disabling this limit or setting it too high may result in severe damage to " +"the system." +msgstr "" +"Els fitxers HTML més grans que aquest valor no es normalitzaran ni " +"s'escanejaran. Nota: desactivar aquest límit o establir-lo massa alt pot " +"provocar danys greus al sistema." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:30001 +msgid "Maximum size of a normalized HTML file to scan:" +msgstr "Mida màxima d'un fitxer HTML normalitzat per explorar:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:30001 +msgid "" +"HTML files larger than this value after normalization will not be scanned. " +"Note: disabling this limit or setting it too high may result in severe " +"damage to the system." +msgstr "" +"Els fitxers HTML més grans que aquest valor després de la normalització no " +"s'escanejaran. Nota: desactivar aquest límit o establir-lo massa alt pot " +"provocar danys greus al sistema." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:31001 +msgid "Maximum size of a script file to normalize:" +msgstr "Mida màxima d'un script per normalitzar:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:31001 +msgid "" +"Script content larger than this value will not be normalized or scanned. " +"Note: disabling this limit or setting it too high may result in severe " +"damage to the system." +msgstr "" +"Els scripts més gran que aquest valor no es normalitzaran ni s'escanejaran. " +"Nota: desactivar aquest límit o establir-lo massa alt pot provocar danys " +"greus al sistema." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:32001 +msgid "Maximum size of a ZIP file to reanalyze type recognition:" +msgstr "" +"Mida màxima d'un fitxer ZIP per a tornar a analitzar el reconeixement de " +"tipus:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:32001 +msgid "" +"ZIP files larger than this value will skip the step to potentially reanalyze " +"as PE. Note: disabling this limit or setting it too high may result in " +"severe damage to the system." +msgstr "" +"Els fitxers ZIP més grans que aquest valor ometran el pas per a tornar a " +"analitzar-los potencialment com PE. Nota: desactivar aquest límit o establir-" +"lo massa alt pot provocar danys greus al sistema." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:33001 +msgid "Delay in seconds between daemon self checks:" +msgstr "Retard en segons entre les comprovacions automàtiques del dimoni:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:33001 +msgid "" +"During the SelfCheck the daemon checks if it needs to reload the virus " +"database. It also tries to repair problems caused by bugs in the daemon, " +"(that is, in some cases it's able to repair broken data structures)." +msgstr "" +"Durant el SelfCheck el dimoni comprova si necessita tornar a carregar la " +"base de dades de virus. També intenta reparar problemes causats per errors " +"en el dimoni (és a dir, en alguns casos és capaç de reparar estructures de " +"dades trencades)." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:34001 +msgid "User to run clamav-daemon as:" +msgstr "Usuari que executarà el «clamav-daemon»:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:34001 +msgid "" +"It is recommended to run the ClamAV programs as a non-privileged user. This " +"will work with most MTAs with a little tweaking, but if you want to use " +"clamd for filesystem scans, running as root is probably unavoidable. Please " +"see README.Debian in the clamav-base package for details." +msgstr "" +"Es recomana executar els programes ClamAV com a usuari no privilegiat. Això " +"funcionarà amb la majoria de MTA amb uns retocs, però si voleu utilitzar el " +"«clamd» per a analitzar el sistema de fitxers, l'execució com a superusuari " +"és probablement inevitable. Vegeu el README.Debian del paquet «clamav-base» " +"per a més detalls." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "Groups for clamav-daemon (space-separated):" +msgstr "Grups pel «clamav-daemon» (separats per espais):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "Please enter any extra groups for clamd." +msgstr "Introduïu qualsevol grup extra per al «clamd»." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "" +"By default, clamd runs as a non-privileged user. If you need clamd to be " +"able to access files owned by another user (e.g., in combination with an " +"MTA), then you will need to add clamd to the group for that piece of " +"software. Please see README.Debian in the clamav-base package for details." +msgstr "" +"Per defecte, el «clamd» s'executa com un usuari no privilegiat. Si " +"necessiteu que el «clamd» pugui accedir a fitxers propietat d'un altre " +"usuari (p. ex., en combinació amb un MTA), llavors haureu d'afegir el " +"«clamd» al grup que toqui per a aquest programari. Vegeu el README.Debian " +"del paquet «clamav-base» per a més detalls." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:36001 +msgid "Do you want to load bytecode from the database?" +msgstr "Voleu carregar «bytecode» de la base de dades?" + +#. Type: select +#. Choices +#: ../clamav-daemon.templates:37001 +msgid "TrustSigned" +msgstr "TrustSigned" + +#. Type: select +#. Choices +#: ../clamav-daemon.templates:37001 +msgid "Paranoid" +msgstr "Paranoic" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:37002 +msgid "Security level to apply to the bytecode:" +msgstr "Nivell de seguretat a aplicar al «bytecode»:" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:37002 +msgid "" +" - TrustSigned : trust bytecode loaded from signed virus database files,\n" +" but insert runtime safety checks for bytecode loaded\n" +" from unsigned sources\n" +" - Paranoid : always insert runtime checks" +msgstr "" +" - TrustSigned : confia en el «bytecode» carregat des de fitxers de base de " +"dades de virus signats, però insereix comprovacions de seguretat en temps " +"d'execució per al «bytecode» carregat de fonts no signades\n" +" - Paranoic: insereix sempre comprovacions en temps d'execució" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:38001 +msgid "Bytecode execution timeout in milliseconds:" +msgstr "Temps d'espera, en mil·lisegons, per l'execució de «bytecode»:" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:2001 +msgid "Some options must be configured for clamav-milter." +msgstr "Algunes opcions del «clamav-milter» s'han de configurar." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:2001 +msgid "" +"It won't work if it isn't configured. If you do not configure it " +"automatically, you'll have to configure /etc/clamav/clamav-milter.conf " +"manually or run \"dpkg-reconfigure clamav-milter\" later. In any case, " +"manual changes in /etc/clamav/clamav-milter.conf will be respected." +msgstr "" +"No funcionarà si no està configurat. Si no el configureu automàticament, " +"haureu de configurar manualment el «/etc/clamav/clamav-milter.conf» o " +"executar «dpkg-reconfigure clamav-milter» més endavant. En qualsevol cas, es " +"respectaran els canvis manuals a «/etc/clamav/clamav-milter.conf»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:3001 +msgid "Communication interface with Sendmail:" +msgstr "Interfície de comunicació amb el Sendmail:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:3001 +msgid "" +"Please choose the method that should be used by clamav-milter to communicate " +"with Sendmail. The following formats can be used:\n" +" - Unix domain socket: [[unix|local]:]/path/to/file\n" +" - IPv4 socket : inet:port@[hostname|ip-address]\n" +" - IPv6 socket : inet6:port@[hostname|ip-address]" +msgstr "" +"Trieu el mètode que ha d'utilitzar el «clamav-milter» per comunicar-se amb " +"el Sendmail. Es poden utilitzar els següents formats:\n" +" - Sòcol de domini Unix: [[unix:local]:]/camí/al/fitxer\n" +" - Sòcol IPv4: inet:port@[amfitrió|adreça_ip]\n" +" - Sòcol IPv6: inet6:port@[amfitrió|adreça_ip]" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:4001 +msgid "Remove stale socket after unclean shutdown?" +msgstr "Voleu eliminar el sòcol obsolet després d'una aturada no controlada?" + +#. Type: string +#. Description +#: ../clamav-milter.templates:5001 +msgid "Group owner of clamav-milter local (UNIX) socket:" +msgstr "Propietari del sòcol local (UNIX) del «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:6001 +msgid "Creation mode for clamav-milter local (UNIX) socket:" +msgstr "Mode de creació per al sòcol local (UNIX) del «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 +msgid "User to run clamav-milter as:" +msgstr "Usuari que executarà el «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 +msgid "" +"It is recommended to run the ClamAV programs as a non-privileged user. This " +"will work with most MTAs with a little tweaking." +msgstr "" +"Es recomana executar els programes ClamAV com a usuari no privilegiat. Això " +"funcionarà amb la majoria de MTA amb uns pocs retocs." + +#. Type: string +#. Description +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 ../clamav-milter.templates:8001 +msgid "Please see README.Debian in the clamav-base package for details." +msgstr "Vegeu el README.Debian del paquet «clamav-base» per als detalls." + +#. Type: string +#. Description +#: ../clamav-milter.templates:8001 +msgid "Groups for clamav-milter (space-separated):" +msgstr "Grups pel «clamav-milter» (separats per espais):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:8001 +msgid "" +"By default, clamav-milter runs as a non-privileged user. If you need clamav-" +"milter to be able to access files owned by another user (for instance when " +"it is used in combination with an MTA), the user running clamav-milter need " +"to be added to the relevant group(s)." +msgstr "" +"Per defecte, el «clamav-milter» s'executa com un usuari no privilegiat. Si " +"necessiteu que el «clamav-milter» pugui accedir a fitxers propietat d'un " +"altre usuari (per exemple, quan s'utilitza en combinació amb un MTA), " +"l'usuari que executa «clamav-milter» s'ha d'afegir al grup o grups " +"pertinents." + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "Wait timeout for data coming from clamd:" +msgstr "Temps d'espera per a les dades que arriben del «clamd»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "" +"Please enter the delay (in seconds) before clamav-milter times out when it " +"is waiting for incoming data from clamd." +msgstr "" +"Introduïu el retard (en segons) abans que el «clamav-milter» deixi d'esperar " +"les dades provinents del «clamd»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "Choosing \"0\" will disable this timeout." +msgstr "En triar «0» s'inhabilitarà aquest temps d'espera." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:10001 +msgid "Should clamav-milter stay in foreground (not forking)?" +msgstr "Cal que «clamav-milter» es mantingui en primer pla (no fer «fork»)?" + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "Chroot to directory:" +msgstr "Directori del «chroot»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "" +"Clamav-milter can run in a chroot jail. It will enter it after reading the " +"configuration file and before dropping root privileges." +msgstr "" +"El «clamav-milter» pot executar-se tancat en un «chroot». Hi entrarà després " +"de llegir el fitxer de configuració i abans de deixar anar els privilegis de " +"superusuari." + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "If this field is left empty, no chrooting will occur." +msgstr "Si aquest camp es deixa buit, no es farà el «chroot»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:12001 +msgid "PID file:" +msgstr "Fitxer PID:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:12001 +msgid "" +"Please specify the process identifier file location for clamav-milter's " +"listening daemon (main thread)." +msgstr "" +"Especifiqueu la ubicació del fitxer amb l'identificador de procés per al " +"dimoni del «clamav-milter» (fil principal)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:13001 +msgid "Temporary directory path:" +msgstr "Camí del directori temporal:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:13001 +msgid "" +"Please specify the directory for clamav-milter's files that are temporarily " +"buffered for scanning. If unset, $TMPDIR and $TEMP will be honored." +msgstr "" +"Especifiqueu el directori per als fitxers del «clamav-milter» usats " +"temporalment per a escanejar. Si no s'estableix, es tindran en compte " +"$TMPDIR i $TEMP." + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "Clamd socket to connect to for scanning:" +msgstr "Sòcol del «clamd» al qual connectar-se per escanejar:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "" +"Please specify the socket to use to connect to the ClamAV daemon for " +"scanning purposes. Possible choices are:\n" +" - a local unix socket using an absolute path, in \"unix:path\" format\n" +" (for example: unix:/var/run/clamd/clamd.socket);\n" +" - a local or remote TCP socket in \"tcp:host:port\" format (for example:\n" +" tcp:192.168.0.1). The \"host\" value can be either a hostname or an IP\n" +" address, and the \"port\" is only required for IPv6 addresses,\n" +" defaulting to 3310 otherwise." +msgstr "" +"Especifiqueu el sòcol que s'utilitzarà per a connectar-se al dimoni ClamAV " +"per a escanejar. Les opcions possibles són:\n" +" - un sòcol unix local utilitzant un camí absolut, en format «unix:" +"camí» (per exemple: «unix:/var/run/clamd/clamd.socket»);\n" +" - un sòcol TCP local o remot en format \"tcp:amfitrió:port\" (per exemple: " +"tcp:192.168.0.1). El valor «amfitrió» pot ser un nom d'amfitrió o una adreça " +"IP, i el «port» només és necessari per a les adreces IPv6, essent per " +"defecte a 3310." + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "" +"You may specify multiple choices, separated by spaces. In such case, the " +"clamd servers will be selected in a round-robin fashion." +msgstr "" +"Podeu especificar múltiples opcions, separades per espais. En aquest cas, " +"els servidors de «clamd» seran seleccionats de forma rotatòria." + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "Hosts excluded from scanning:" +msgstr "Amfitrions exclosos de l'escaneig:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "" +"Please specify, in CIDR notation (host(name)/mask), the hosts for which no " +"scanning should be performed on incoming mail. Multiple entries should be " +"separated by spaces. The \"local\" shortcut can be used to specify locally-" +"originated (non-SMTP) email." +msgstr "" +"Especifiqueu, en notació CIDR (amfitrió/màscara), els amfitrions per als " +"quals no s'ha de realitzar cap escaneig del correu entrant. Les entrades " +"múltiples s'han de separar per espais. La cadena «local» es pot utilitzar " +"per a especificar correu electrònic d'origen local (no SMTP)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "If this field is left empty, all incoming mail will be scanned." +msgstr "Si aquest camp es deixa buit, s'escanejarà tot el correu entrant." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "Mail addresses whitelist:" +msgstr "Llista blanca d'adreces de correu:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Please specify the path to a whitelist file, listing email addresses that " +"should cause scanning to be bypassed." +msgstr "" +"Especifiqueu el camí cap a un fitxer de llista blanca, llistant les adreces " +"de correu electrònic que s'haurien d'ignorar a l'hora d'escanejar." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Each line in this file should be a POSIX regular expression; lines starting " +"with \"#\", \":\" or \"!\" will be ignored as comments." +msgstr "" +"Cada línia d'aquest fitxer hauria de ser una expressió regular POSIX; les " +"línies que comencin amb «#», «:» o «!» s'ignoraran com a comentaris." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Lines may start with \"From:\" (with no space after the colon) to make the " +"whitelisting apply to matching sender addresses; otherwise, or with a \"To:" +"\" prefix, it affects recipient addresses." +msgstr "" +"Les línies poden començar amb «From:» (sense espai després de «:») per fer " +"que s'apliqui la llista blanca quan coincideixi l'adreça del remitent; en " +"cas contrari, o amb un prefix «To:», afecta a les adreces dels destinataris." + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Accept" +msgstr "Accepta" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Reject" +msgstr "Rebutja" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Defer" +msgstr "Ajorna" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 +msgid "Blackhole" +msgstr "Forat negre" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 +msgid "Quarantine" +msgstr "Quarantena" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "Action to perform on infected messages:" +msgstr "Acció a realitzar amb els missatges infectats:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "Please choose the action to perform on \"infected\" messages:" +msgstr "Trieu l'acció a realitzar amb els missatges «infectats»:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "" +" - Accept : accept the message for delivery;\n" +" - Reject : immediately refuse delivery (with a 5xx error);\n" +" - Defer : return a temporary failure message (4xx);\n" +" - Blackhole : accept the message then drop it;\n" +" - Quarantine: accept the message then quarantine it. With\n" +" Sendmail, the quarantine queue can be examined\n" +" with \"mailq -qQ\". With Postfix, such mails are placed\n" +" on hold." +msgstr "" +" - Accepta: accepta el missatge per a lliurar-lo;\n" +" - Rebutja: rebutja immediatament el lliurament (amb un error 5xx);\n" +" - Ajorna: retorna un missatge d'error temporal (4xx);\n" +" - Forat negre: accepta el missatge però per ignorar-lo;\n" +" - Quarantena: accepta el missatge i després el posa en quarantena. Amb el " +"Sendmail es pot examinar la cua de quarantena amb «mailq -qQ». Amb el " +"Postfix, aquests correus es deixen en espera." + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "Action to perform on error conditions:" +msgstr "Acció a realitzar en condicions d'error:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "" +"Please choose the action to perform on errors such as failure to allocate " +"data structures, no scanners available, network timeouts, unknown scanner " +"replies...:" +msgstr "" +"Trieu l'acció a realitzar quan hi ha errors com la impossibilitat d'ubicar " +"estructures de dades, que no hi ha escàners disponibles, temps d'espera de " +"xarxa esgotats, respostes d'escàner desconegudes...:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "" +" - Accept: accept the message for delivery;\n" +" - Reject: immediately refuse delivery (with a 5xx error);\n" +" - Defer : return a temporary failure message (4xx)." +msgstr "" +" - Accepta: accepta el missatge per a lliurar-lo;\n" +" - Rebutja: rebutja immediatament el lliurament (amb un error 5xx);\n" +" - Ajorna: retorna un missatge d'error temporal (4xx)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "Specific rejection reason for infected messages:" +msgstr "Motiu específic de rebuig dels missatges infectats:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "" +"Please specify the rejection reason that will be included in reject mails." +msgstr "Especifiqueu el motiu de rebuig que s'inclourà als correus de rebuig." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "This option is only useful together with \"OnInfected Reject\"." +msgstr "Aquesta opció només és útil juntament amb «OnInfected Reject»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +#, no-c-format +msgid "The \"%v\" string may be used to include the virus name." +msgstr "La cadena «%v» es pot utilitzar per incloure el nom del virus." + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Replace" +msgstr "Reemplaça" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Yes" +msgstr "Sí" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "No" +msgstr "No" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Add" +msgstr "Afegeix" + +#. Type: select +#. Description +#: ../clamav-milter.templates:20002 +msgid "Add headers to processed messages?" +msgstr "Voleu afegir capçaleres als missatges processats?" + +#. Type: select +#. Description +#: ../clamav-milter.templates:20002 +msgid "" +"If you choose this option, \"X-Virus-Scanned\" and \"X-Virus-Status\" " +"headers will be attached to each processed message, possibly replacing " +"existing similar headers." +msgstr "" +"Si trieu aquesta opció, les capçaleres «X-Virus-Scanned» i «X-Virus-Status» " +"s'adjuntaran a cada missatge processat, possiblement reemplaçant capçaleres " +"similars existents." + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "Log file for clamav-milter:" +msgstr "Fitxer de registre per al «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "" +"Specify the full path to the clamav-milter log file, which must be writable " +"for the clamav daemon. Enter none to disable." +msgstr "" +"Especifiqueu el camí complet al fitxer de registre del «clamav-milter», que " +"ha de ser modificable pel dimoni «clamav». Introduïu «none» per desactivar-" +"ho." + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "Logging via syslog is configured independently of this setting." +msgstr "" +"El registre via «syslog» es configura independentment d'aquest paràmetre." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:22001 +msgid "Disable log file locking?" +msgstr "Voleu desactivar el bloqueig de fitxers de registre?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:22001 +msgid "" +"By default the log file is locked for writing. The lock protects against " +"running clamav-milter multiple times. This option disables log file locking." +msgstr "" +"Per defecte el fitxer de registre està bloquejat per a escriptura. El " +"bloqueig protegeix contra l'execució múltiple de «clamav-milter». Aquesta " +"opció desactiva el bloqueig de fitxers de registre." + +#. Type: string +#. Description +#: ../clamav-milter.templates:23001 +msgid "Maximum size of the log file (MB):" +msgstr "Mida màxima del fitxer de registre (MB):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:23001 +msgid "" +"Please specify the maximum size for the log file. Using \"0\" will allow " +"that file to grow indefinitely." +msgstr "" +"Especifiqueu la mida màxima del fitxer de registre. Posar-hi un «0» farà que " +"aquest fitxer creixi indefinidament." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:24001 +msgid "Log time with each message?" +msgstr "Voleu registrar l'hora amb cada missatge?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:25001 +msgid "Use system logger?" +msgstr "Voleu utilitzar el registre del sistema?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:25001 +msgid "" +"Please choose whether you want to use the system logger (syslog). This " +"option can be used along with logging in a dedicated file." +msgstr "" +"Trieu si voleu utilitzar el registre del sistema («syslog»). Aquesta opció " +"es pot utilitzar juntament amb l'enregistrament en un fitxer dedicat." + +#. Type: string +#. Description +#: ../clamav-milter.templates:26001 +msgid "Type of syslog messages:" +msgstr "Tipus dels missatges del «syslog»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:26001 +msgid "" +"Please choose the type of syslog messages as detailed in the system logger's " +"documentation." +msgstr "" +"Trieu el tipus dels missatges del «syslog» tal com es detalla a la " +"documentació del registre del sistema." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:27001 +msgid "Enable verbose logging?" +msgstr "Voleu habilitar l'enregistrament detallat?" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Off" +msgstr "Desactivat" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Basic" +msgstr "Bàsic" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Full" +msgstr "Complet" + +#. Type: select +#. Description +#: ../clamav-milter.templates:28002 +msgid "Information to log on infected messages:" +msgstr "Informació a registrar dels missatges infectats:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:28002 +msgid "" +"Please choose the level of information that will be logged when infected " +"messages are found:\n" +" - Off : no logging;\n" +" - Basic: minimal information;\n" +" - Full : verbose information." +msgstr "" +"Trieu el nivell d'informació que es registrarà quan es trobin missatges " +"infectats:\n" +" - Desactivat: no es registra;\n" +" - Bàsic: informació mínima;\n" +" - Complet: informació detallada." + +#. Type: select +#. Description +#: ../clamav-milter.templates:29002 +msgid "Information to log if no threat is found:" +msgstr "Informació a registrar si no es detecta cap amenaça:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:29002 +msgid "" +"Please choose the level of information that will be logged when no threat is " +"found in a scanned message (this is useful in debugging but drastically " +"increases the log size):\n" +" - Off : no logging;\n" +" - Basic: minimal information;\n" +" - Full : verbose information." +msgstr "" +"Trieu el nivell d'informació que es registrarà quan no es trobi cap amenaça " +"en un missatge escanejat (això és útil per a depurar però augmenta " +"dràsticament la mida del registre):\n" +" - Desactivat: no es registra;\n" +" - Bàsic: informació mínima;\n" +" - Complet: Informació detallada." + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "Size limit for scanned messages (MB):" +msgstr "Mida màxima dels missatges escanejats (MB):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "" +"Please specify the maximum size for scanned messages. Messages bigger than " +"this limit will not be scanned." +msgstr "" +"Especifiqueu la mida màxima dels missatges escanejats. Els missatges més " +"grans que aquest límit no s'escanejaran." + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "" +"You should check that this value is lower than the value of " +"\"StreamMaxLength\" in the clamd.conf file." +msgstr "" +"Cal comprovar que aquest valor sigui inferior al valor de «StreamMaxLength» " +"al fitxer «clamd.conf»." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "Do you want clamav-milter to support multiple recipients?" +msgstr "Voleu que «clamav-milter» admeti múltiples destinataris?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "" +"This option affects the behaviour of LogInfected, LogClean and VirusAction " +"when a message with multiple recipients is scanned: If " +"SupportMultipleRecipients is off (the default) then one single log entry is " +"generated for the message and, in case the message is determined to be " +"malicious, the command indicated by VirusAction is executed just once. In " +"both cases only the last recipient is reported. If SupportMultipleRecipients " +"is on: then one line is logged for each recipient and the command indicated " +"by VirusAction is also executed once for each recipient." +msgstr "" +"Aquesta opció afecta el comportament de LogInfected, LogClean i VirusAction " +"quan s'escaneja un missatge amb múltiples destinataris: si " +"SupportMultipleRecipients està desactivat (per defecte) llavors es genera " +"una única entrada de registre per al missatge i, en cas que el missatge es " +"consideri maliciós, l'ordre indicada per VirusAction s'executarà una sola " +"vegada. En tots dos casos només s'informa de l'últim destinatari. Si " +"SupportMultipleRecipients està activat: en aquest es registra una línia per " +"a cada destinatari i l'ordre indicada per VirusAction també s'executa una " +"vegada per a cada destinatari." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "" +"Note: although it's probably a good idea to enable this option, the default " +"value is currently set to off for legacy reasons." +msgstr "" +"Nota: tot i que probablement és una bona idea habilitar aquesta opció, el " +"valor per defecte està actualment desactivat per raons antigues." diff -Nru clamav-1.4.3+dfsg/debian/po/ro.po clamav-1.4.6+dfsg/debian/po/ro.po --- clamav-1.4.3+dfsg/debian/po/ro.po 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/po/ro.po 2026-09-05 19:12:04.000000000 +0000 @@ -0,0 +1,1533 @@ +# Romanian translation of debconf templates debconf_clamav. +# Mesajele în limba română pentru șablonul debconf_clamav. +# Copyright © 2025 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the clamav package. +# +# Remus-Gabriel Chelu , 2025. +# +# Cronologia traducerii fișierului „debconf_clamav”: +# Traducerea inițială, făcută de R-GC, pentru versiunea clamav 1.4.2+dfsg-1. +# Actualizare a traducerii pentru versiunea Y, făcută de X, Y(anul). +# +msgid "" +msgstr "" +"Project-Id-Version: clamav 1.4.2+dfsg-1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-04-01 14:41+0000\n" +"PO-Revision-Date: 2025-04-07 18:51+0200\n" +"Last-Translator: Remus-Gabriel Chelu \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==0 || (n!=1 && n%100>=1 && " +"n%100<=19) ? 1 : 2);\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"X-Generator: Poedit 3.5\n" + +#. Type: select +#. Choices +#: ../clamav-freshclam.templates:2001 +msgid "daemon" +msgstr "demon" + +#. Type: select +#. Choices +#: ../clamav-freshclam.templates:2001 +msgid "manual" +msgstr "manuală" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "Virus database update method:" +msgstr "Metoda de actualizare a bazei de date de viruși:" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "Please choose the method for virus database updates." +msgstr "Alegeți metoda de actualizare a bazei de date de viruși." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:2002 +msgid "" +" daemon: freshclam is running as a daemon all the time. You should choose\n" +" this option if you have a permanent network connection;\n" +" ifup.d: freshclam will be running as a daemon as long as your Internet\n" +" connection is up. Choose this one if you use a dialup Internet\n" +" connection and don't want freshclam to initiate new connections;\n" +" cron: freshclam is started from cron. Choose this if you want full " +"control\n" +" of when the database is updated;\n" +" manual: no automatic invocation of freshclam. This is not recommended,\n" +" as ClamAV's database is constantly updated." +msgstr "" +" demon : «freshclam» rulează tot timpul ca un demon. Ar trebui să alegeți\n" +" această opțiune dacă aveți o conexiune permanentă la rețea;\n" +" ifup.d: «freshclam» va rula ca un demon atâta timp cât conexiunea dvs. la\n" +" Internet este activă. Alegeți această opțiune dacă utilizați o\n" +" conexiune dialup la Internet și nu doriți ca freshclam să inițieze\n" +" noi conexiuni;\n" +" cron : «freshclam» este pornit din «cron». Alegeți această opțiune dacă\n" +" doriți să aveți control deplin asupra momentului în care este\n" +" actualizată baza de date;\n" +" manual: nicio invocare automată a «freshclam». Această opțiune nu este\n" +" recomandată, deoarece baza de date a ClamAV este actualizată " +"constant." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "Local database mirror site:" +msgstr "Situl oglindă al bazei de date locale:" + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "Please select the closest local mirror site." +msgstr "Selectați cel mai apropiat sit oglindă local." + +#. Type: select +#. Description +#: ../clamav-freshclam.templates:3001 +msgid "" +"Freshclam updates its database from a world wide network of mirror sites. " +"Please select the closest mirror. If you leave the default setting, an " +"attempt will be made to guess a nearby mirror." +msgstr "" +"«freshclam» își actualizează baza de date de la o rețea mondială de situri " +"oglindă. Vă rugăm să selectați cea mai apropiată oglindă. Dacă lăsați " +"valoarea implicită, se va încerca să se ghicească o oglindă apropiată." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "HTTP proxy information (leave blank for none):" +msgstr "Informații privind proxy-ul HTTP (lăsați gol pentru niciunul):" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "" +"If you need to use an HTTP proxy to access the outside world, enter the " +"proxy information here. Otherwise, leave this blank." +msgstr "" +"Dacă aveți nevoie de un proxy HTTP pentru a accesa Internetul, introduceți " +"informațiile despre proxy aici. Altfel, lăsați gol acest câmp." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:4001 +msgid "Please use URL syntax (\"http://host[:port]\") here." +msgstr "Utilizați sintaxa de adresă URL („http://gazdă[:port]”) aici." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "Proxy user information (leave blank for none):" +msgstr "Informații privind utilizatorul proxy (lăsați gol pentru niciunul):" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "" +"If you need to supply a username and password to the proxy, enter it here. " +"Otherwise, leave this blank." +msgstr "" +"Dacă trebuie să furnizați un nume de utilizator și o parolă pentru proxy, " +"introduceți-le aici. În caz contrar, lăsați acest câmp gol." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:5001 +msgid "When entering user information, use the standard form of \"user:pass\"." +msgstr "" +"Atunci când introduceți informații despre utilizator, utilizați forma " +"standard „utilizator:parolă”." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:6001 +msgid "Number of freshclam updates per day:" +msgstr "Numărul de actualizări «freshclam» pe zi:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "Network interface connected to the Internet:" +msgstr "Interfața de rețea conectată la internet:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"Please enter the name of the network interface connected to the Internet. " +"Example: eth0." +msgstr "" +"Introduceți numele interfeței de rețea conectată la Internet. De exemplu: " +"eth0." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"If the daemon runs when the network is down, the log file will be filled " +"with entries like 'ERROR: Connection with database.clamav.net failed.', " +"making it easy to miss when freshclam really can't update the database." +msgstr "" +"Dacă demonul rulează atunci când rețeaua este căzută, fișierul jurnal va fi " +"plin cu intrări de genul „ERROR: Connection with database.clamav.net " +"failed.”, ceea ce va face cu ușurință să nu se observe când «freshclam» " +"chiar nu poate actualiza baza de date." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"You can leave this field blank and the daemon will be started from the " +"initialization scripts instead. You should then make sure the computer is " +"permanently connected to the Internet to avoid filling the log files." +msgstr "" +"Puteți lăsa acest câmp gol și demonul va fi pornit din scripturile de " +"inițializare. Trebuie să vă asigurați apoi că calculatorul este conectat " +"permanent la Internet pentru a evita umplerea fișierelor jurnal." + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:7001 +msgid "" +"If the computer has multiple network interfaces connecting to the Internet " +"use a space-separated list of device names." +msgstr "" +"Dacă calculatorul are mai multe interfețe de rețea conectate la Internet, " +"utilizați o listă de nume de dispozitive separate prin spații." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "Should clamd be notified after updates?" +msgstr "Trebuie să fie notificat clamd după actualizări?" + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "" +"Please confirm whether clamd should be notified to reload the database after " +"successful updates." +msgstr "" +"Vă rugăm să confirmați dacă «clamd» ar trebui să fie notificat pentru a " +"reîncărca baza de date după o actualizare reușită." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:8001 +msgid "" +"If you do not choose this option, clamd's database reloads will be notably " +"delayed (it performs this check every 6 hours by default), posing the risk " +"that a new virus may slip through even if the database is up to date. Do not " +"use this if you do not use clamd, as it will produce errors." +msgstr "" +"Dacă nu bifați această opțiune, reîncărcarea bazei de date a «clamd» va fi " +"mult întârziată (în mod implicit, această verificare se efectuează la " +"fiecare 6 ore), existând riscul ca un nou virus să se strecoare chiar dacă " +"baza de date este actualizată. Nu utilizați această opțiune dacă nu " +"utilizați «clamd», deoarece va produce erori." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:9001 +msgid "Do you want to download the bytecode database?" +msgstr "Doriți să descărcați baza de date „bytecode”?" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:10001 +msgid "Private mirror for freshclam:" +msgstr "Oglindă privată pentru «freshclam»:" + +#. Type: string +#. Description +#: ../clamav-freshclam.templates:10001 +msgid "" +"This option allows you to easily point freshclam to private mirrors. If " +"PrivateMirror is set, freshclam does not attempt to use DNS to determine " +"whether its databases are out-of-date, instead it will use the If-Modified-" +"Since request or directly check the headers of the remote database files. " +"For each database, freshclam first attempts to download the CLD file. If " +"that fails, it tries to download the CVD file. This option overrides " +"DatabaseMirror, DNSDatabaseInfo and ScriptedUpdates. It can be used multiple " +"times to provide fall-back mirrors." +msgstr "" +"Această opțiune vă permite să direcționați cu ușurință «freshclam» către " +"oglinzi private. Dacă opțiunea „PrivateMirror” este definită, «freshclam» nu " +"va încerca să utilizeze DNS pentru a determina dacă bazele sale de date sunt " +"învechite, ci va utiliza solicitarea „If-Modified-Since” sau va verifica " +"direct anteturile fișierelor bazelor de date de la distanță. Pentru fiecare " +"bază de date, «freshclam» încearcă mai întâi să descarce fișierul CLD. Dacă " +"nu reușește, încearcă să descarce fișierul CVD. Această opțiune înlocuiește " +"opțiunile „DatabaseMirror”, „DNSDatabaseInfo” și „ScriptedUpdates”. Aceasta " +"poate fi utilizată de mai multe ori pentru a furniza oglinzi de rezervă." + +#. Type: boolean +#. Description +#: ../clamav-freshclam.templates:11001 ../clamav-daemon.templates:22001 +#: ../clamav-milter.templates:32001 +msgid "Do you want to enable log rotation?" +msgstr "Doriți să activați rotirea jurnalelor?" + +#. Type: error +#. Description +#: ../clamav-base.templates:2001 +msgid "Mandatory numeric value" +msgstr "Valoare numerică obligatorie" + +#. Type: error +#. Description +#: ../clamav-base.templates:2001 +msgid "This question requires a numeric answer." +msgstr "Această întrebare necesită un răspuns numeric." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 ../clamav-milter.templates:2001 +msgid "Handle the configuration file automatically?" +msgstr "Doriți să se gestioneze automat fișierul de configurare?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 +msgid "Some options must be configured for clamav-daemon." +msgstr "Unele opțiuni trebuie să fie configurate pentru «clamav-daemon»." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:2001 +msgid "" +"The ClamAV suite won't work if it isn't configured. If you do not configure " +"it automatically, you'll have to configure /etc/clamav/clamd.conf manually " +"or run 'dpkg-reconfigure clamav-daemon' later. In any case, manual changes " +"in /etc/clamav/clamd.conf will be respected." +msgstr "" +"Suita ClamAV nu va funcționa dacă nu este configurată. Dacă nu o configurați " +"automat, va trebui să configurați manual „/etc/clamav/clamd.conf” sau să " +"executați mai târziu «dpkg-reconfigure clamav-daemon». În orice caz, " +"modificările manuale din „/etc/clamav/clamd.conf” vor fi respectate." + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "Socket type:" +msgstr "Tipul de soclu:" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "Please choose the type of socket clamd will be listening on." +msgstr "Alegeți tipul de soclu pe care va asculta «clamd»." + +#. Type: select +#. Description +#: ../clamav-daemon.templates:3001 +msgid "" +"If you choose TCP, clamd can be accessed remotely. If you choose local UNIX " +"sockets, clamd can be accessed through a file. Local UNIX sockets are " +"recommended for security reasons." +msgstr "" +"Dacă alegeți TCP, «clamd» poate fi accesat de la distanță. Dacă alegeți " +"socluri UNIX locale, «clamd» poate fi accesat prin intermediul unui fișier. " +"Soclurile UNIX locale sunt recomandate din motive de securitate." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:4001 +msgid "Local (UNIX) socket clamd will listen on:" +msgstr "Soclul local (UNIX) pe care «clamd» va asculta:" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:5001 +msgid "Gracefully handle left-over UNIX socket files?" +msgstr "Doriți să gestionați corespunzător fișierele de soclu UNIX rămase?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:6001 +msgid "Group owner of clamd local (UNIX) socket:" +msgstr "Grupul proprietar al soclului clamd local (UNIX):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:7001 +msgid "Creation mode for clamd local (UNIX) socket:" +msgstr "Modul de creare (permisiunile) pentru soclul clamd local (UNIX):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:8001 +msgid "TCP port clamd will listen on:" +msgstr "Portul TCP pe care «clamd» va asculta:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:9001 +msgid "IP address clamd will listen on:" +msgstr "Adresa IP la care «clamd» va asculta:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:9001 +msgid "" +"Enter \"any\" to listen on every IP address configured. If you want to " +"listen on a single address or host name, enter it here." +msgstr "" +"Introduceți „any” pentru a asculta la fiecare adresă IP configurată. Dacă " +"doriți să asculte la o singură adresă sau nume de gazdă, introduceți-l aici." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:10001 +msgid "Do you want to enable mail scanning?" +msgstr "Doriți să activați scanarea corespondenței?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:10001 +msgid "" +"This option enables scanning mail contents for viruses. You need this option " +"enabled if you want to use clamav-milter, or if you want to enable phishing " +"checks." +msgstr "" +"Această opțiune permite scanarea conținutului mesajelor pentru viruși. " +"Trebuie să activați această opțiune dacă doriți să utilizați «clamav-milter» " +"sau dacă doriți să activați verificarea „phishing-ului”." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "Do you want to enable archive scanning?" +msgstr "Doriți să activați scanarea arhivelor?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "" +"If archive scanning is enabled, the daemon will extract archives such as " +"bz2, tar.gz, deb and many more, to check their contents for viruses." +msgstr "" +"Dacă scanarea arhivelor este activată, demonul va extrage arhive precum bz2, " +"tar.gz, deb și multe altele, pentru a le verifica conținutul pentru viruși." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:11001 +msgid "" +"For more information about what archives are supported, see /usr/share/doc/" +"clamav-docs/clamdoc.pdf or the manpage clamscan(5)." +msgstr "" +"Pentru mai multe informații despre arhivele acceptate, consultați „/usr/" +"share/doc/clamav-docs/clamdoc.pdf” sau pagina de manual clamscan(5)." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:12001 +msgid "Maximum stream length (unit Mb) allowed:" +msgstr "Lungimea maximă permisă a fluxului (în Mo):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:12001 +msgid "You can set a limit on the stream length that can be scanned." +msgstr "Puteți stabili o limită pentru lungimea fluxului care poate fi scanat." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "Maximum directory depth that will be allowed:" +msgstr "Adâncimea maximă de sondare a directoarelor care va fi permisă:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "" +"This value must be set if you want to allow the daemon to follow directory " +"symlinks." +msgstr "" +"Această valoare trebuie să fie stabilită dacă doriți să permiteți demonului " +"să urmărească legăturile simbolice de directoare." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:13001 +msgid "Entering '0' will disable this limit." +msgstr "Introducerea cifrei „0” va dezactiva această limită." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:14001 +msgid "Do you want the daemon to follow directory symlinks?" +msgstr "Doriți ca demonul să urmărească legăturile simbolice de directoare?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:15001 +msgid "Do you want the daemon to follow regular file symlinks?" +msgstr "" +"Doriți ca demonul să urmărească legăturile simbolice ale fișierelor " +"obișnuite?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:16001 +msgid "Timeout for stopping the thread-scanner (seconds):" +msgstr "" +"Timpul de așteptare pentru oprirea scanerului cu fire de execuție (secunde):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:16001 +msgid "Entering '0' will disable the timeout." +msgstr "Introducerea cifrei „0” va dezactiva timpul de așteptare." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:17001 +msgid "Number of threads for the daemon:" +msgstr "Numărul de fire de execuție pentru demon:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:18001 +msgid "Number of pending connections allowed:" +msgstr "Numărul de conexiuni în așteptare permise:" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:19001 +msgid "Do you want to use the system logger?" +msgstr "Doriți să utilizați instrumentul de jurnalizare al sistemului?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:19001 +msgid "" +"It is possible to log the daemon activity to the system logger. This can be " +"done independently of whether you want to log activity to a special file." +msgstr "" +"Este posibil să înregistrați activitatea demonului în instrumentul de " +"jurnalizare al sistemului. Acest lucru se poate face independent de faptul " +"dacă doriți să înregistrați activitatea într-un fișier special." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:20001 +msgid "Log file for clamav-daemon (enter none to disable):" +msgstr "" +"Fișierul de jurnal pentru «clamav-daemon» (introduceți „none” pentru a " +"dezactiva):" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:21001 +msgid "Do you want to log time information with each message?" +msgstr "Doriți să înregistrați informațiile privind ora cu fiecare mesaj?" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:23001 +msgid "Maximum file size to scan:" +msgstr "Dimensiunea maximă a fișierului pentru scanare:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:23001 +msgid "A value of 0 disables the limit." +msgstr "O valoare de 0 dezactivează limita." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:24001 +msgid "Do you want to permit the use of the ALLMATCHSCAN command?" +msgstr "Doriți să permiteți utilizarea comenzii ALLMATCHSCAN?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:24001 +msgid "If set to no, clamd will reject any ALLMATCHSCAN command as invalid." +msgstr "" +"Dacă este definită la „nu”, «clamd» va respinge orice comandă ALLMATCHSCAN " +"ca fiind nevalidă." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:25001 +msgid "Do you want memory or nested map scans to dump the content to disk?" +msgstr "" +"Doriți scanări ale memoriei sau a tabelului cu conținutul imaginilor din " +"memorie pentru a descărca conținutul acestora pe disc?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:25001 +msgid "" +"If you turn on this option, more data is written to disk and is available " +"when the LeaveTemporaryFiles option is enabled." +msgstr "" +"Dacă activați această opțiune, mai multe date sunt scrise pe disc și sunt " +"disponibile atunci când opțiunea LeaveTemporaryFiles este activată." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:26001 +msgid "Do you want to completely turn off authenticode verification?" +msgstr "Doriți să dezactivați complet verificarea „authenticode”?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:26001 +msgid "" +"Certain PE files contain an authenticode signature. By default the signature " +"chain in the PE file is checked against a database of trusted and revoked " +"certificates if the file being scanned is marked as a virus. If any " +"certificate in the chain validates against any trusted root, but does not " +"match any revoked certificate, the file is marked as whitelisted. If the " +"file does match a revoked certificate, the file is marked as virus." +msgstr "" +"Anumite fișiere PE conțin o semnătură „authenticode”. În mod implicit, " +"lanțul de semnături din fișierul PE este verificat în raport cu o bază de " +"date de certificate de încredere, și sunt revocate dacă fișierul scanat este " +"marcat ca fiind un virus. Dacă un certificat din lanț este validat în raport " +"cu o rădăcină de încredere, și nu corespunde unui certificat revocat, " +"fișierul este marcat ca fiind pe lista albă. Dacă fișierul corespunde unui " +"certificat revocat, fișierul este marcat ca virus." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:27001 +msgid "Do you want to enable scanning within SWF files?" +msgstr "Doriți să activați scanarea în cadrul fișierelor SWF?" + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:27001 +msgid "" +"If you turn off this option, the original files will still be scanned, but " +"without decoding and additional processing." +msgstr "" +"Dacă dezactivați această opțiune, fișierele originale vor fi în continuare " +"scanate, dar fără decodificare și procesare suplimentară." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:28001 +msgid "Maximum size of a file to check for embedded PE:" +msgstr "" +"Dimensiunea maximă a unui fișier PE pentru verificarea conținutului său:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:28001 +msgid "" +"Files larger than this value will skip the additional analysis step. Note: " +"disabling this limit or setting it too high may result in severe damage to " +"the system." +msgstr "" +"Fișierele mai mari decât această valoare vor fi omise în etapa de analiză " +"suplimentară. Notă: dezactivarea acestei limite sau fixarea ei la un nivel " +"prea ridicat poate duce la deteriorarea gravă a sistemului." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:29001 +msgid "Maximum size of a HTML file to normalize:" +msgstr "Dimensiunea maximă a unui fișier HTML de normalizat:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:29001 +msgid "" +"HTML files larger than this value will not be normalized or scanned. Note: " +"disabling this limit or setting it too high may result in severe damage to " +"the system." +msgstr "" +"Fișierele HTML mai mari decât această valoare nu vor fi normalizate sau " +"scanate. Notă: dezactivarea acestei limite sau fixarea ei la o valoare prea " +"mare poate duce la deteriorarea gravă a sistemului." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:30001 +msgid "Maximum size of a normalized HTML file to scan:" +msgstr "Dimensiunea maximă a unui fișier HTML normalizat pentru scanare:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:30001 +msgid "" +"HTML files larger than this value after normalization will not be scanned. " +"Note: disabling this limit or setting it too high may result in severe " +"damage to the system." +msgstr "" +"Fișierele HTML mai mari decât această valoare după normalizare nu vor fi " +"scanate. Notă: dezactivarea acestei limite sau fixarea ei la o valoare prea " +"mare poate duce la deteriorarea gravă a sistemului." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:31001 +msgid "Maximum size of a script file to normalize:" +msgstr "Dimensiunea maximă a unui fișier script pentru normalizare:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:31001 +msgid "" +"Script content larger than this value will not be normalized or scanned. " +"Note: disabling this limit or setting it too high may result in severe " +"damage to the system." +msgstr "" +"Conținutul scripturilor mai mare decât această valoare nu va fi normalizat " +"sau scanat. Notă: dezactivarea acestei limite sau fixarea ei la o valoare " +"prea mare poate duce la deteriorarea gravă a sistemului." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:32001 +msgid "Maximum size of a ZIP file to reanalyze type recognition:" +msgstr "" +"Dimensiunea maximă a unui fișier ZIP pentru reanalizarea recunoașterii " +"tipului:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:32001 +msgid "" +"ZIP files larger than this value will skip the step to potentially reanalyze " +"as PE. Note: disabling this limit or setting it too high may result in " +"severe damage to the system." +msgstr "" +"Fișierele ZIP mai mari decât această valoare vor fi omise pentru a fi " +"reanalizate ca PE. Notă: dezactivarea acestei limite sau fixarea ei la un " +"nivel prea ridicat poate duce la deteriorarea gravă a sistemului." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:33001 +msgid "Delay in seconds between daemon self checks:" +msgstr "Întârzierea în secunde între autoverificările demonului:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:33001 +msgid "" +"During the SelfCheck the daemon checks if it needs to reload the virus " +"database. It also tries to repair problems caused by bugs in the daemon, " +"(that is, in some cases it's able to repair broken data structures)." +msgstr "" +"În timpul autoverificării, demonul verifică dacă trebuie să reîncarce baza " +"de date a virușilor. De asemenea, încearcă să repare problemele cauzate de " +"erori ale demonului (adică, în unele cazuri, este capabil să repare " +"structuri de date defecte)." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:34001 +msgid "User to run clamav-daemon as:" +msgstr "Utilizatorul cu care se execută «clamav-daemon»:" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:34001 +msgid "" +"It is recommended to run the ClamAV programs as a non-privileged user. This " +"will work with most MTAs with a little tweaking, but if you want to use " +"clamd for filesystem scans, running as root is probably unavoidable. Please " +"see README.Debian in the clamav-base package for details." +msgstr "" +"Se recomandă să executați programele ClamAV ca utilizator neprivilegiat. " +"Acest lucru va funcționa cu majoritatea MTA-urilor cu câteva ajustări, dar " +"dacă doriți să utilizați «clamd» pentru scanarea sistemului de fișiere, " +"rularea ca root este probabil inevitabilă. Vă rugăm să consultați " +"README.Debian din pachetul „clamav-base” pentru detalii." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "Groups for clamav-daemon (space-separated):" +msgstr "Grupuri pentru «clamav-daemon» (separate prin spații):" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "Please enter any extra groups for clamd." +msgstr "Introduceți orice grupuri suplimentare pentru «clamd»." + +#. Type: string +#. Description +#: ../clamav-daemon.templates:35001 +msgid "" +"By default, clamd runs as a non-privileged user. If you need clamd to be " +"able to access files owned by another user (e.g., in combination with an " +"MTA), then you will need to add clamd to the group for that piece of " +"software. Please see README.Debian in the clamav-base package for details." +msgstr "" +"În mod implicit, «clamd» rulează ca utilizator neprivilegiat. Dacă aveți " +"nevoie ca demonol «clamd» să poată accesa fișiere deținute de un alt " +"utilizator (de exemplu, în combinație cu un MTA), atunci va trebui să " +"adăugați clamd la grupul pentru acel software. Vă rugăm să consultați " +"README.Debian din pachetul „clamav-base” pentru detalii." + +#. Type: boolean +#. Description +#: ../clamav-daemon.templates:36001 +msgid "Do you want to load bytecode from the database?" +msgstr "Doriți să încărcați „bytecode”-ul din baza de date?" + +#. Type: select +#. Choices +#: ../clamav-daemon.templates:37001 +msgid "TrustSigned" +msgstr "Încredere în semnătură" + +#. Type: select +#. Choices +#: ../clamav-daemon.templates:37001 +msgid "Paranoid" +msgstr "Paranoic" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:37002 +msgid "Security level to apply to the bytecode:" +msgstr "Nivelul de securitate care se aplică bytecode-ului:" + +#. Type: select +#. Description +#: ../clamav-daemon.templates:37002 +msgid "" +" - TrustSigned : trust bytecode loaded from signed virus database files,\n" +" but insert runtime safety checks for bytecode loaded\n" +" from unsigned sources\n" +" - Paranoid : always insert runtime checks" +msgstr "" +" - Încredere în semnătură : încredere în bytecode-ul încărcat din fișiere " +"de\n" +" baze de date de viruși semnate, dar introduce\n" +" verificări de siguranță în timpul execuției " +"pentru\n" +" bytecode-ul încărcat din surse nesemnate\n" +" - Paranoic : introduce întotdeauna verificări în timpul " +"execuției" + +#. Type: string +#. Description +#: ../clamav-daemon.templates:38001 +msgid "Bytecode execution timeout in milliseconds:" +msgstr "Timpul de așteptare pentru execuția bytecode-ului în milisecunde:" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:2001 +msgid "Some options must be configured for clamav-milter." +msgstr "Unele opțiuni trebuie să fie configurate pentru «clamav-milter»." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:2001 +msgid "" +"It won't work if it isn't configured. If you do not configure it " +"automatically, you'll have to configure /etc/clamav/clamav-milter.conf " +"manually or run \"dpkg-reconfigure clamav-milter\" later. In any case, " +"manual changes in /etc/clamav/clamav-milter.conf will be respected." +msgstr "" +"Acesta nu va funcționa dacă nu este configurat. Dacă nu îl configurați " +"automat, va trebui să configurați manual „/etc/clamav/clamav-milter.conf” " +"sau să executați mai târziu «dpkg-reconfigure clamav-milter». În orice caz, " +"modificările manuale din „/etc/clamav/clamav-milter.conf” vor fi respectate." + +#. Type: string +#. Description +#: ../clamav-milter.templates:3001 +msgid "Communication interface with Sendmail:" +msgstr "Interfața de comunicare cu Sendmail:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:3001 +msgid "" +"Please choose the method that should be used by clamav-milter to communicate " +"with Sendmail. The following formats can be used:\n" +" - Unix domain socket: [[unix|local]:]/path/to/file\n" +" - IPv4 socket : inet:port@[hostname|ip-address]\n" +" - IPv6 socket : inet6:port@[hostname|ip-address]" +msgstr "" +"Vă rugăm să alegeți metoda care ar trebui să fie utilizată de «clamav-" +"milter» pentru a comunica cu Sendmail. Pot fi utilizate următoarele " +"formate:\n" +" - Soclu de domeniu Unix: [[unix|local]:]/ruta/către/fișier\n" +" - Soclu IPv4 : inet:port@[nume gazdă|adresă IP]\n" +" - Soclu IPv6 : inet6:port@[nume gazdă|adresă IP]" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:4001 +msgid "Remove stale socket after unclean shutdown?" +msgstr "Doriți să eliminați soclul vechi după o închidere necorespunzătoare?" + +#. Type: string +#. Description +#: ../clamav-milter.templates:5001 +msgid "Group owner of clamav-milter local (UNIX) socket:" +msgstr "Grupul proprietar al soclului (UNIX) local al «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:6001 +msgid "Creation mode for clamav-milter local (UNIX) socket:" +msgstr "" +"Modul de creare (permisiunile) pentru soclul (UNIX) local al «clamav-" +"milter»::" + +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 +msgid "User to run clamav-milter as:" +msgstr "Utilizatorul cu care se execută «clamav-milter»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 +msgid "" +"It is recommended to run the ClamAV programs as a non-privileged user. This " +"will work with most MTAs with a little tweaking." +msgstr "" +"Se recomandă să executați programele ClamAV ca utilizator neprivilegiat. " +"Acest lucru va funcționa cu majoritatea MTA-urilor cu câteva ajustări." + +#. Type: string +#. Description +#. Type: string +#. Description +#: ../clamav-milter.templates:7001 ../clamav-milter.templates:8001 +msgid "Please see README.Debian in the clamav-base package for details." +msgstr "" +"Vă rugăm să consultați README.Debian din pachetul „clamav-base” pentru " +"detalii." + +#. Type: string +#. Description +#: ../clamav-milter.templates:8001 +msgid "Groups for clamav-milter (space-separated):" +msgstr "Grupuri pentru clamav-milter (separate prin spații):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:8001 +msgid "" +"By default, clamav-milter runs as a non-privileged user. If you need clamav-" +"milter to be able to access files owned by another user (for instance when " +"it is used in combination with an MTA), the user running clamav-milter need " +"to be added to the relevant group(s)." +msgstr "" +"În mod implicit, «clamav-milter» rulează ca utilizator fără privilegii. Dacă " +"aveți nevoie ca programul «clamav-milter» să poată accesa fișiere deținute " +"de un alt utilizator (de exemplu, atunci când este utilizat în combinație cu " +"un MTA), utilizatorul care execută «clamav-milter» trebuie să fie adăugat la " +"grupul (grupurile) relevant(e)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "Wait timeout for data coming from clamd:" +msgstr "Timpul maxim de așteptare pentru datele provenite de la «clamd»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "" +"Please enter the delay (in seconds) before clamav-milter times out when it " +"is waiting for incoming data from clamd." +msgstr "" +"Vă rugăm să introduceți intervalul de timp (în secunde) înainte ca «clamav-" +"milter» să se oprească atunci când așteaptă date de la «clamd»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:9001 +msgid "Choosing \"0\" will disable this timeout." +msgstr "Dacă alegeți „0”, acest timp de așteptare va fi dezactivat." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:10001 +msgid "Should clamav-milter stay in foreground (not forking)?" +msgstr "Trebuie să rămână «clamav-milter» în prim-plan (să nu fie bifurcat)?" + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "Chroot to directory:" +msgstr "Directorul în care se execută «chroot»:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "" +"Clamav-milter can run in a chroot jail. It will enter it after reading the " +"configuration file and before dropping root privileges." +msgstr "" +"«clamav-milter» poate rula într-o celulă „chroot”. Acesta va intra în ea " +"după citirea fișierului de configurare și înainte de a renunța la " +"privilegiile de root." + +#. Type: string +#. Description +#: ../clamav-milter.templates:11001 +msgid "If this field is left empty, no chrooting will occur." +msgstr "" +"Dacă acest câmp este lăsat gol, nu va avea loc nicio operație «chroot»." + +#. Type: string +#. Description +#: ../clamav-milter.templates:12001 +msgid "PID file:" +msgstr "Fișierul pid" + +#. Type: string +#. Description +#: ../clamav-milter.templates:12001 +msgid "" +"Please specify the process identifier file location for clamav-milter's " +"listening daemon (main thread)." +msgstr "" +"Specificați locația fișierului identificator de proces pentru demonul de " +"ascultare al «clamav-milter» (firul principal)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:13001 +msgid "Temporary directory path:" +msgstr "Ruta directorului temporar:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:13001 +msgid "" +"Please specify the directory for clamav-milter's files that are temporarily " +"buffered for scanning. If unset, $TMPDIR and $TEMP will be honored." +msgstr "" +"Specificați directorul pentru fișierele clamav-milter care sunt stocate " +"temporar pentru scanare. Dacă nu este definit, vor fi respectate valorile " +"indicate în $TMPDIR și $TEMP." + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "Clamd socket to connect to for scanning:" +msgstr "Soclul de conectare al «clamd» pentru scanare:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "" +"Please specify the socket to use to connect to the ClamAV daemon for " +"scanning purposes. Possible choices are:\n" +" - a local unix socket using an absolute path, in \"unix:path\" format\n" +" (for example: unix:/var/run/clamd/clamd.socket);\n" +" - a local or remote TCP socket in \"tcp:host:port\" format (for example:\n" +" tcp:192.168.0.1). The \"host\" value can be either a hostname or an IP\n" +" address, and the \"port\" is only required for IPv6 addresses,\n" +" defaulting to 3310 otherwise." +msgstr "" +"Vă rugăm să specificați soclul care urmează să fie utilizat pentru " +"conectarea la demonul ClamAV în scopul scanării. Opțiunile posibile sunt:\n" +" - un soclu unix local utilizând o rută absolută, în formatul „unix:rută”\n" +" (de exemplu: unix:/var/run/clamd/clamd.socket);\n" +" - un soclu TCP local sau la distanță în formatul „tcp:gazdă:port” (de " +"exemplu:\n" +" tcp:192.168.0.1). Valoarea „gazdă” poate fi fie un nume de gazdă, fie o\n" +" adresă IP, iar valoarea „port” este necesară numai pentru adresele IPv6,\n" +" în caz contrar, valoarea implicită este 3310." + +#. Type: string +#. Description +#: ../clamav-milter.templates:14001 +msgid "" +"You may specify multiple choices, separated by spaces. In such case, the " +"clamd servers will be selected in a round-robin fashion." +msgstr "" +"Puteți specifica mai multe opțiuni, separate prin spații. În acest caz, " +"serverele clamd vor fi selectate în mod circular." + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "Hosts excluded from scanning:" +msgstr "Gazde excluse de la scanare:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "" +"Please specify, in CIDR notation (host(name)/mask), the hosts for which no " +"scanning should be performed on incoming mail. Multiple entries should be " +"separated by spaces. The \"local\" shortcut can be used to specify locally-" +"originated (non-SMTP) email." +msgstr "" +"Vă rugăm să specificați, în notație CIDR (gazdă(nume)/mască), gazdele pentru " +"care nu ar trebui efectuată nicio scanare a mesajelor primite. Intrările " +"multiple trebuie separate prin spații. Prescurtarea „local” poate fi " +"utilizată pentru a specifica mesaje de origine locală (non-SMTP)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:15001 +msgid "If this field is left empty, all incoming mail will be scanned." +msgstr "Dacă acest câmp este lăsat gol, toate mesajele primite vor fi scanate." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "Mail addresses whitelist:" +msgstr "Lista albă de adrese poștale:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Please specify the path to a whitelist file, listing email addresses that " +"should cause scanning to be bypassed." +msgstr "" +"Vă rugăm să specificați ruta către un fișier de listă albă, care enumeră " +"adresele de poștă electronică pentru care scanarea ar trebui să fie omisă." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Each line in this file should be a POSIX regular expression; lines starting " +"with \"#\", \":\" or \"!\" will be ignored as comments." +msgstr "" +"Fiecare linie din acest fișier trebuie să fie o expresie regulată POSIX; " +"liniile care încep cu „#”, „:” sau „!” vor fi interpretate ca comentarii." + +#. Type: string +#. Description +#: ../clamav-milter.templates:16001 +msgid "" +"Lines may start with \"From:\" (with no space after the colon) to make the " +"whitelisting apply to matching sender addresses; otherwise, or with a \"To:" +"\" prefix, it affects recipient addresses." +msgstr "" +"Liniile pot începe cu „From:” (fără spațiu după două puncte) pentru ca lista " +"albă să se aplice adreselor expeditorului care corespund; în caz contrar, " +"sau cu un prefix „To:”, aceasta afectează adresele destinatarului." + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Accept" +msgstr "Acceptare" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Reject" +msgstr "Respingere" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 ../clamav-milter.templates:18001 +msgid "Defer" +msgstr "Amânare" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 +msgid "Blackhole" +msgstr "Gaură neagră" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:17001 +msgid "Quarantine" +msgstr "Carantină" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "Action to perform on infected messages:" +msgstr "Acțiunea de efectuat asupra mesajelor infectate:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "Please choose the action to perform on \"infected\" messages:" +msgstr "Alegeți acțiunea de efectuat asupra mesajelor „infectate”:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:17002 +msgid "" +" - Accept : accept the message for delivery;\n" +" - Reject : immediately refuse delivery (with a 5xx error);\n" +" - Defer : return a temporary failure message (4xx);\n" +" - Blackhole : accept the message then drop it;\n" +" - Quarantine: accept the message then quarantine it. With\n" +" Sendmail, the quarantine queue can be examined\n" +" with \"mailq -qQ\". With Postfix, such mails are placed\n" +" on hold." +msgstr "" +" - Acceptare : acceptă mesajul pentru livrare;\n" +" - Respingere : refuză imediat livrarea (cu o eroare 5xx);\n" +" - Amânare : returnează un mesaj de eșec temporar (4xx);\n" +" - Gaură neagră : acceptă mesajul, apoi îl elimină;\n" +" - Carantină : acceptă mesajul apoi îl pune în carantină. Cu «sendmail»,\n" +" coada de carantină poate fi examinată cu «mailq -qQ».\n" +" Cu Postfix, astfel de mesaje sunt puse în așteptare." + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "Action to perform on error conditions:" +msgstr "Acțiunea de efectuat în caz de eroare:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "" +"Please choose the action to perform on errors such as failure to allocate " +"data structures, no scanners available, network timeouts, unknown scanner " +"replies...:" +msgstr "" +"Vă rugăm să alegeți acțiunea de efectuat în cazul unor erori cum ar fi " +"eșecul alocării structurilor de date, niciun scaner disponibil, depășiri de " +"timp în rețea, răspunsuri necunoscute ale scanerului...:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:18002 +msgid "" +" - Accept: accept the message for delivery;\n" +" - Reject: immediately refuse delivery (with a 5xx error);\n" +" - Defer : return a temporary failure message (4xx)." +msgstr "" +" - Acceptare : acceptă mesajul pentru livrare;\n" +" - Respingere : refuză imediat livrarea (cu o eroare 5xx);\n" +" - Amânare : returnează un mesaj de eșec temporar (4xx)." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "Specific rejection reason for infected messages:" +msgstr "Motivul specific de respingere pentru mesajele infectate:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "" +"Please specify the rejection reason that will be included in reject mails." +msgstr "" +"Vă rugăm să specificați motivul respingerii care va fi inclus în mesajele de " +"respingere." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +msgid "This option is only useful together with \"OnInfected Reject\"." +msgstr "Această opțiune este utilă numai împreună cu „OnInfected Reject”." + +#. Type: string +#. Description +#: ../clamav-milter.templates:19001 +#, no-c-format +msgid "The \"%v\" string may be used to include the virus name." +msgstr "Șirul „%v” poate fi utilizat pentru a include numele virusului." + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Replace" +msgstr "Înlocuiește" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Yes" +msgstr "Da" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "No" +msgstr "Nu" + +#. Type: select +#. Choices +#: ../clamav-milter.templates:20001 +msgid "Add" +msgstr "Adaugă" + +#. Type: select +#. Description +#: ../clamav-milter.templates:20002 +msgid "Add headers to processed messages?" +msgstr "Doriți adăugarea de antete la mesajele procesate?" + +#. Type: select +#. Description +#: ../clamav-milter.templates:20002 +msgid "" +"If you choose this option, \"X-Virus-Scanned\" and \"X-Virus-Status\" " +"headers will be attached to each processed message, possibly replacing " +"existing similar headers." +msgstr "" +"Dacă alegeți această opțiune, antetele „X-Virus-Scanned” și „X-Virus-Status” " +"vor fi atașate fiecărui mesaj procesat, eventual înlocuind antetele similare " +"existente." + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "Log file for clamav-milter:" +msgstr "Fișierul de jurnal pentru clamav-milter:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "" +"Specify the full path to the clamav-milter log file, which must be writable " +"for the clamav daemon. Enter none to disable." +msgstr "" +"Specificați ruta completă către fișierul de jurnal clamav-milter, care " +"trebuie să poată fi scris de către demonul «clamav». Introduceți „none” " +"pentru dezactivare." + +#. Type: string +#. Description +#: ../clamav-milter.templates:21001 +msgid "Logging via syslog is configured independently of this setting." +msgstr "" +"Înregistrarea prin syslog este configurată independent de această opțiune." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:22001 +msgid "Disable log file locking?" +msgstr "Doriți să dezactivați blocarea fișierului de jurnal?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:22001 +msgid "" +"By default the log file is locked for writing. The lock protects against " +"running clamav-milter multiple times. This option disables log file locking." +msgstr "" +"În mod implicit, fișierul de jurnal este blocat pentru scriere. Blocarea " +"protejează împotriva executării «clamav-milter» de mai multe ori. Această " +"opțiune dezactivează blocarea fișierului de jurnal." + +#. Type: string +#. Description +#: ../clamav-milter.templates:23001 +msgid "Maximum size of the log file (MB):" +msgstr "Dimensiunea maximă a fișierului de jurnal (în Mo):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:23001 +msgid "" +"Please specify the maximum size for the log file. Using \"0\" will allow " +"that file to grow indefinitely." +msgstr "" +"Vă rugăm să specificați dimensiunea maximă pentru fișierul jurnal. Dacă " +"utilizați „0”, fișierul va crește la nesfârșit." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:24001 +msgid "Log time with each message?" +msgstr "Doriți înregistrarea marcajului de timp cu fiecare mesaj?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:25001 +msgid "Use system logger?" +msgstr "Doriți să utilizați programul de jurnalizare al sistemului?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:25001 +msgid "" +"Please choose whether you want to use the system logger (syslog). This " +"option can be used along with logging in a dedicated file." +msgstr "" +"Vă rugăm să alegeți dacă doriți să utilizați programul de jurnalizare al " +"sistemului (syslog). Această opțiune poate fi utilizată împreună cu " +"jurnalizarea într-un fișier dedicat." + +#. Type: string +#. Description +#: ../clamav-milter.templates:26001 +msgid "Type of syslog messages:" +msgstr "Tipul mesajelor syslog:" + +#. Type: string +#. Description +#: ../clamav-milter.templates:26001 +msgid "" +"Please choose the type of syslog messages as detailed in the system logger's " +"documentation." +msgstr "" +"Vă rugăm să alegeți tipul de mesaje syslog conform documentației programului " +"de jurnalizare al sistemului." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:27001 +msgid "Enable verbose logging?" +msgstr "Activați jurnalizarea detaliată?" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Off" +msgstr "Dezactivat" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Basic" +msgstr "Bazic" + +#. Type: select +#. Choices +#. Type: select +#. Choices +#: ../clamav-milter.templates:28001 ../clamav-milter.templates:29001 +msgid "Full" +msgstr "Complet" + +#. Type: select +#. Description +#: ../clamav-milter.templates:28002 +msgid "Information to log on infected messages:" +msgstr "Informații pentru înregistrarea mesajelor infectate:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:28002 +msgid "" +"Please choose the level of information that will be logged when infected " +"messages are found:\n" +" - Off : no logging;\n" +" - Basic: minimal information;\n" +" - Full : verbose information." +msgstr "" +"Vă rugăm să alegeți nivelul de informații care vor fi înregistrate atunci " +"când sunt găsite mesaje infectate:\n" +" - Dezactivat : nicio înregistrare;\n" +" - Bazic : informații minime;\n" +" - Complet : informații detaliate." + +#. Type: select +#. Description +#: ../clamav-milter.templates:29002 +msgid "Information to log if no threat is found:" +msgstr "" +"Informații care trebuie înregistrate dacă nu se găsește nicio amenințare:" + +#. Type: select +#. Description +#: ../clamav-milter.templates:29002 +msgid "" +"Please choose the level of information that will be logged when no threat is " +"found in a scanned message (this is useful in debugging but drastically " +"increases the log size):\n" +" - Off : no logging;\n" +" - Basic: minimal information;\n" +" - Full : verbose information." +msgstr "" +"Vă rugăm să alegeți nivelul de informații care va fi înregistrat atunci când " +"nu se găsește nicio amenințare într-un mesaj scanat (acest lucru este util " +"în depanare, dar crește drastic dimensiunea jurnalului):\n" +" - Dezactivat : nicio înregistrare;\n" +" - Bazic : informații minime;\n" +" - Complet : informații detaliate." + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "Size limit for scanned messages (MB):" +msgstr "Dimensiunea maximă pentru mesajele scanate (în Mo):" + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "" +"Please specify the maximum size for scanned messages. Messages bigger than " +"this limit will not be scanned." +msgstr "" +"Vă rugăm să specificați dimensiunea maximă pentru mesajele scanate. Mesajele " +"mai mari decât această limită nu vor fi scanate." + +#. Type: string +#. Description +#: ../clamav-milter.templates:30001 +msgid "" +"You should check that this value is lower than the value of " +"\"StreamMaxLength\" in the clamd.conf file." +msgstr "" +"Trebuie să verificați dacă această valoare este mai mică decât valoarea " +"„StreamMaxLength” din fișierul clamd.conf." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "Do you want clamav-milter to support multiple recipients?" +msgstr "Doriți ca «clamav-milter» să permită mai mulți destinatari?" + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "" +"This option affects the behaviour of LogInfected, LogClean and VirusAction " +"when a message with multiple recipients is scanned: If " +"SupportMultipleRecipients is off (the default) then one single log entry is " +"generated for the message and, in case the message is determined to be " +"malicious, the command indicated by VirusAction is executed just once. In " +"both cases only the last recipient is reported. If SupportMultipleRecipients " +"is on: then one line is logged for each recipient and the command indicated " +"by VirusAction is also executed once for each recipient." +msgstr "" +"Această opțiune afectează comportamentul LogInfected, LogClean și " +"VirusAction atunci când este scanat un mesaj cu destinatari multipli: Dacă " +"opțiunea SupportMultipleRecipients este dezactivată (implicit), se generează " +"o singură intrare în jurnal pentru mesaj și, în cazul în care mesajul este " +"considerat rău intenționat, comanda indicată de VirusAction este executată o " +"singură dată. În ambele cazuri, este raportat doar ultimul destinatar. Dacă " +"opțiunea SupportMultipleRecipients este activată: atunci se înregistrează o " +"linie pentru fiecare destinatar, iar comanda indicată de VirusAction este " +"executată o singură dată pentru fiecare destinatar." + +#. Type: boolean +#. Description +#: ../clamav-milter.templates:31001 +msgid "" +"Note: although it's probably a good idea to enable this option, the default " +"value is currently set to off for legacy reasons." +msgstr "" +"Notă: deși este probabil o idee bună să activați această opțiune, valoarea " +"implicită este stabilită în prezent la „off” din motive istorice." diff -Nru clamav-1.4.3+dfsg/debian/rules clamav-1.4.6+dfsg/debian/rules --- clamav-1.4.3+dfsg/debian/rules 2025-06-29 10:00:50.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/rules 2026-09-05 19:12:04.000000000 +0000 @@ -12,6 +12,7 @@ #export ACLOCAL = aclocal include /usr/share/dpkg/pkg-info.mk export DEB_BUILD_MAINT_OPTIONS = hardening=+all +export DH_ALWAYS_EXCLUDE = *.orig # This is needed to work around arch-specific quirks in the test suite. DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) @@ -37,7 +38,7 @@ # Enable debug code, if nostrip was given. ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) INSTALL_PROGRAM += -s - DEBUG_OPTS = + DEBUG_OPTS = -DCMAKE_BUILD_TYPE=RelWithDebInfo else DEBUG_OPTS = -DCMAKE_BUILD_TYPE=Debug endif @@ -80,7 +81,7 @@ fi;\ done; \ # Check for library features which may have been upgraded. - if ! grep -q "CL_FLEVEL 213" libclamav/others.h ; then \ + if ! grep -q "CL_FLEVEL 216" libclamav/others.h ; then \ echo "cl_retflevel needs boosting in symbol file"; \ touch debian/exit; \ fi; @@ -103,7 +104,6 @@ # Update .po files for debconf. debconf-updatepo dh_auto_clean - rm -f debian/clamav-daemon.install.$(DEB_HOST_ARCH_OS) debian/clamav-daemon.manpages.$(DEB_HOST_ARCH_OS) rm -rf unit_tests/clamscan/__pycache__ rm -rf unit_tests/__pycache__ rm -rf unit_tests/.pytest_cache @@ -144,16 +144,13 @@ override_dh_auto_install-indep: override_dh_install: -# clamonacc is only built on linux architectures -ifneq (linux, $(DEB_HOST_ARCH_OS)) - grep -v 'clamonacc' debian/clamav-daemon.install > debian/clamav-daemon.install.$(DEB_HOST_ARCH_OS) - grep -v 'clamonacc' debian/clamav-daemon.manpages > debian/clamav-daemon.manpages.$(DEB_HOST_ARCH_OS) -endif dh_install - dh_apparmor -pclamav-freshclam --profile-name=usr.bin.freshclam + # freshclam's Apparmor profile is deployed in the custom postinst script dh_apparmor -pclamav-daemon --profile-name=usr.sbin.clamd override_dh_installinit: + # TODO: drop after moving to compat 13 + dh_installtmpfiles dh_installinit -pclamav-daemon # Don't change the postinst/postrm scripts for clamav-freshclam, as they need non-standard code. dh_installinit -pclamav-freshclam --noscripts @@ -163,8 +160,8 @@ override_dh_compress: dh_compress -Xexamples +ifeq (linux, $(DEB_HOST_ARCH_OS)) override_dh_installsystemd: -ifneq (linux, $(DEB_HOST_ARCH_OS)) - dh_installsystemd --name clamav-clamonacc --no-enable --no-start + dh_installsystemd -pclamav-daemon clamav-clamonacc.service --no-enable --no-start + dh_installsystemd --remaining-packages endif - dh_installsystemd --name clamav-daemon diff -Nru clamav-1.4.3+dfsg/debian/usr.sbin.clamd clamav-1.4.6+dfsg/debian/usr.sbin.clamd --- clamav-1.4.3+dfsg/debian/usr.sbin.clamd 2025-06-29 09:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/debian/usr.sbin.clamd 2026-09-05 19:12:04.000000000 +0000 @@ -19,6 +19,7 @@ @{PROC}/filesystems r, @{PROC}/[0-9]*/status r, + @{PROC}/[0-9]*/mountinfo r, /etc/clamav/clamd.conf r, @@ -40,8 +41,6 @@ /var/spool/p3scan/children/** r, - /var/spool/havp/** r, - # For amavisd-new integration /var/lib/amavis/tmp/** r, @@ -52,6 +51,8 @@ # For use with exim /var/spool/exim4/** r, + /sys/fs/cgroup/system.slice/cpu.max r, + # Allow home dir to be scanned @{HOME}/ r, @{HOME}/** r, diff -Nru clamav-1.4.3+dfsg/docs/man/clamd.8.in clamav-1.4.6+dfsg/docs/man/clamd.8.in --- clamav-1.4.3+dfsg/docs/man/clamd.8.in 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/docs/man/clamd.8.in 2026-08-06 21:12:04.000000000 +0000 @@ -35,10 +35,12 @@ Scan file or directory (recursively) with archive support enabled and don't stop the scanning when a virus is found. .TP \fBMULTISCAN file/directory\fR -Scan file in a standard way or scan directory (recursively) using multiple threads (to make the scanning faster on SMP machines). +Scan a directory recursively using multiple threads (to make the scanning faster on SMP machines). If the target is not a directory, clamd falls back to non-multiscan scanning behavior. .TP \fBALLMATCHSCAN file/directory\fR -ALLMATCHSCAN works just like SCAN except that it sets a mode where scanning continues after finding a match within a file. +It is mandatory to prefix this command with \fBn\fR or \fBz\fR. + +ALLMATCHSCAN works just like SCAN except that it sets a mode where scanning continues after finding a match within a file. This command may be disabled with \fBAllowAllMatchScan\fR in clamd.conf. If disabled, clamd replies with an ALLMATCHSCAN error. .TP \fBINSTREAM\fR It is mandatory to prefix this command with \fBn\fR or \fBz\fR. @@ -56,13 +58,12 @@ \fBSTATS\fR It is mandatory to newline terminate this command, or prefix with \fBn\fR or \fBz\fR, it is recommended to only use the \fBz\fR prefix. -Replies with statistics about the scan queue, contents of scan queue, and memory -usage. The exact reply format is subject to change in future releases. +Replies with statistics about the scan queue, contents of scan queue, and memory usage. The exact reply format is subject to change in future releases. .TP \fBIDSESSION, END\fR It is mandatory to prefix this command with \fBn\fR or \fBz\fR, and all commands inside IDSESSION must be prefixed. -Start/end a clamd session. Within a session multiple SCAN, INSTREAM, FILDES, VERSION, STATS commands can be sent on the same socket without opening new connections. Replies from clamd will be in the form ': ' where is the request number (in ascii, starting from 1) and is the usual clamd reply. +Start/end a clamd session. Within a session multiple SCAN, INSTREAM, FILDES, VERSION, VERSIONCOMMANDS, PING, and STATS commands can be sent on the same socket without opening new connections. CONTSCAN, MULTISCAN, ALLMATCHSCAN, RELOAD, and SHUTDOWN are not accepted inside an IDSESSION. Replies from clamd will be in the form ': ' where is the request number (in ascii, starting from 1) and is the usual clamd reply. The reply lines have same delimiter as the corresponding command had. Clamd will process the commands asynchronously, and reply as soon as it has finished processing. @@ -75,19 +76,16 @@ It is mandatory to prefix this command with either \fBn\fR or \fBz\fR. It is recommended to use \fBnVERSIONCOMMANDS\fR. -Print program and database versions, followed by "| COMMANDS:" and a -space-delimited list of supported commands. -Clamd <0.95 will recognize this as the VERSION command, and reply only with -their version, without the commands list. +Print program and database versions, followed by "| COMMANDS:" and a space-delimited list of supported commands. +Clamd <0.95 will recognize this as the VERSION command, and reply only with their version, without the commands list. -This command can be used as an easy way to check for IDSESSION support for -example. +This command can be used as an easy way to check for IDSESSION support for example. .LP .TP -\fBDEPRECATED COMMANDS\fR +\fBREMOVED COMMANDS\fR .TP \fBSTREAM\fR -Scan stream \- on this command clamd will return "PORT number" you should connect to and send data to scan. (\fBDEPRECATED\fR, use INSTREAM instead) +The legacy STREAM command is no longer supported. Use INSTREAM instead. .LP .TP \fBNOT SUPPORTED COMMANDS\fR diff -Nru clamav-1.4.3+dfsg/docs/man/clamdscan.1.in clamav-1.4.6+dfsg/docs/man/clamdscan.1.in --- clamav-1.4.3+dfsg/docs/man/clamdscan.1.in 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/docs/man/clamdscan.1.in 2026-08-06 21:12:04.000000000 +0000 @@ -43,7 +43,7 @@ Wait up to 30 seconds for clamd to start. Optionally use alongside ping to set attempts [A] and interval [I] to check clamd. .TP \fB\-m, \-\-multiscan\fR -In the multiscan mode clamd will attempt to scan the directory contents in parallel using available threads. This option is especially useful on multiprocessor and multi-core systems. If you pass more than one file or directory in the command line, they are put in a queue and sent to clamd individually. This means, that single files are always scanned by a single thread. Similarly, clamdscan will wait for clamd to finish a directory scan (performed in multiscan mode) before sending request to scan another directory. This option can be combined with \-\-fdpass (see below). +Use multiscan mode. For local directory scans where the daemon opens paths directly, clamd attempts to scan directory contents in parallel using available threads. Single files are not affected. When this option is combined with \-\-stream, with \-\-fdpass on a local socket, or with a quarantine action, clamdscan walks the requested paths itself and submits individual file scans while still allowing clamd to process multiple files in parallel. .TP \fB\-z, \-\-allmatch\fR After a match, continue scanning within the file for additional matches. @@ -63,18 +63,51 @@ \fB\-\-reload\fR Request clamd to reload virus database. .TP -\fB\-\-allmatch\fR -Continue scanning within file after finding a match. -.TP \fB\-i, \-\-infected\fR Only print infected files .TP \fB\-\-fdpass\fR -Open the file and pass the opened file descriptor to clamd. This is useful if clamd is running as a different user or if clamd sees a different file system tree. This is faster than streaming the file to clamd. -Only available if connected to clamd via local(unix) socket. +Open the file and pass the opened file descriptor to clamd. This is useful if clamd is running as a different user or if clamd sees a different filesystem tree. This is faster than streaming the file to clamd. +Only available if connected to clamd via Unix/local socket. .TP \fB\-\-stream\fR -Forces file streaming to clamd. This is generally not needed as clamdscan detects automatically if streaming is required. This option only exists for debugging and testing purposes, in all other cases \-\-fdpass is preferred. +Force clamdscan to send file contents to clamd instead of asking clamd to open file paths. This is generally not needed because clamdscan detects automatically if sending file contents is required. This option mostly exists for debugging and testing. In other local-socket cases, \-\-fdpass is usually preferred. + +.SH "OPTION INTERACTIONS" +.LP +clamdscan behavior depends first on the socket type, and then on command-line options. +.TP +\fBUnix/local socket\fR +By default, clamdscan asks the local daemon to open the paths you provide. The daemon must be able to see those paths and have permission to read them. +.RS +.IP \(bu 2 +With \-\-fdpass, clamdscan opens each file itself and passes the open file to the daemon. This is useful when the daemon runs as a different user or sees a different filesystem view. This option only works with a Unix/local socket and fd-passing support. +.IP \(bu 2 +With \-\-stream, clamdscan sends file contents to the daemon instead of asking the daemon to open paths. +.IP \(bu 2 +With \-\-multiscan, directory scans can use multiple daemon worker threads. If \-\-stream, \-\-fdpass, or a quarantine action is also used, clamdscan walks the requested paths itself and submits individual file scans while still allowing the daemon to process multiple files in parallel. +.IP \(bu 2 +\-\-allmatch is only effective when clamdscan is asking the daemon to open paths directly and is not using \-\-multiscan, \-\-stream, or \-\-fdpass. +.RE +.TP +\fBTCP socket\fR +When the daemon is remote, clamdscan sends file contents instead of local paths because client paths may not exist on the daemon host. When the daemon is local and clamdscan can determine that it is local, clamdscan may ask the daemon to open local paths directly. +.RS +.IP \(bu 2 +\-\-stream forces clamdscan to send file contents, even when the daemon is local. +.IP \(bu 2 +\-\-fdpass is not available over TCP. Use either \-\-stream or \-\-fdpass for a scan, based on the socket type and how the daemon can access the files. +.IP \(bu 2 +With \-\-multiscan, local directory scans may use multiple daemon worker threads. Remote scans, \-\-stream scans, and scans with quarantine actions are handled as individual file scans, while still allowing the daemon to process multiple files in parallel. +.IP \(bu 2 +\-\-allmatch is only effective when clamdscan is asking a local daemon to open paths directly and is not using \-\-multiscan or \-\-stream. +.RE +.TP +\fBOption guidance\fR +\-\-allmatch is not useful with \-\-multiscan; use it only for scans where clamdscan is asking a local daemon to open paths directly. For quarantine, choose one action for a scan: \-\-move, \-\-copy, or \-\-remove. +.TP +\fBQuarantine actions with multiscan\fR +Quarantine actions such as \-\-move, \-\-copy, and \-\-remove are performed by clamdscan, not by clamd. For directory scans with quarantine actions enabled, clamdscan resolves the action path for each file before requesting the scan. When \-\-multiscan is also enabled, clamdscan submits individual file scans so it can preserve the scan result to action-path association while still allowing clamd to process multiple files in parallel. .SH "EXAMPLES" .LP diff -Nru clamav-1.4.3+dfsg/libclamav/7z/7zIn.c clamav-1.4.6+dfsg/libclamav/7z/7zIn.c --- clamav-1.4.3+dfsg/libclamav/7z/7zIn.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/7z/7zIn.c 2026-08-06 21:12:04.000000000 +0000 @@ -768,6 +768,8 @@ UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; + if (*numUnpackStreams > UINT32_MAX - numStreams) + return SZ_ERROR_FAIL; *numUnpackStreams += numStreams; } continue; diff -Nru clamav-1.4.3+dfsg/libclamav/bytecode_api.h clamav-1.4.6+dfsg/libclamav/bytecode_api.h --- clamav-1.4.3+dfsg/libclamav/bytecode_api.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/bytecode_api.h 2026-08-06 21:12:04.000000000 +0000 @@ -196,6 +196,9 @@ FUNC_LEVEL_1_4_1 = 211, /**< LibClamAV release 1.4.1 */ FUNC_LEVEL_1_4_2 = 212, /**< LibClamAV release 1.4.2 */ FUNC_LEVEL_1_4_3 = 213, /**< LibClamAV release 1.4.3 */ + FUNC_LEVEL_1_4_4 = 214, /**< LibClamAV release 1.4.4 */ + FUNC_LEVEL_1_4_5 = 215, /**< LibClamAV release 1.4.5 */ + FUNC_LEVEL_1_4_6 = 216, /**< LibClamAV release 1.4.6 */ }; /** diff -Nru clamav-1.4.3+dfsg/libclamav/dmg.c clamav-1.4.6+dfsg/libclamav/dmg.c --- clamav-1.4.3+dfsg/libclamav/dmg.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/dmg.c 2026-08-06 21:12:04.000000000 +0000 @@ -135,7 +135,13 @@ cli_dbgmsg("cli_scandmg: The embedded XML is way larger than necessary, and probably corrupt or tampered with.\n"); return CL_EFORMAT; } - if ((hdr.xmlOffset > (uint64_t)maplen) || (hdr.xmlLength > (uint64_t)maplen) || (hdr.xmlOffset + hdr.xmlLength) > (uint64_t)maplen) { + /* + * Keep the XML range check in subtraction form. Once offset and length are + * each known to be no larger than the map, `offset <= maplen - length` + * proves that the full range is contained without ever forming a possibly + * overflowing offset + length sum. + */ + if ((hdr.xmlOffset > (uint64_t)maplen) || (hdr.xmlLength > (uint64_t)maplen) || (hdr.xmlOffset > (uint64_t)maplen - hdr.xmlLength)) { cli_dbgmsg("cli_scandmg: XML out of range for this file\n"); return CL_EFORMAT; } @@ -455,6 +461,7 @@ size_t base64_len, buff_size, decoded_len; uint8_t *decoded; const uint8_t mish_magic[4] = {0x6d, 0x69, 0x73, 0x68}; + uint64_t expected_len; UNUSEDPARAM(ctx); @@ -463,7 +470,13 @@ dmg_parsemsg("dmg_decode_mish: len of encoded block %u is %lu\n", *mishblocknum, base64_len); /* speed vs memory, could walk the encoded data and skip whitespace in calculation */ - buff_size = 3 * base64_len / 4 + 4; + buff_size = (base64_len / 4) * 3 + 4; + if (base64_len % 4) { + if (buff_size > SIZE_MAX - 3) { + return CL_EFORMAT; + } + buff_size += 3; + } dmg_parsemsg("dmg_decode_mish: buffer for mish block %u is %lu\n", *mishblocknum, (unsigned long)buff_size); decoded = cli_max_malloc(buff_size); if (!decoded) @@ -502,13 +515,19 @@ mish_set->mish->startSector, mish_set->mish->sectorCount, mish_set->mish->dataOffset, mish_set->mish->blockDataCount); - /* decoded length should be mish block + blockDataCount * 40 */ - if (decoded_len < (sizeof(struct dmg_mish_block) + mish_set->mish->blockDataCount * sizeof(struct dmg_block_data))) { + /* + * The decoded mish block must contain the fixed header followed by one + * stripe record per blockDataCount. Calculate this requirement in a wide + * integer domain, then compare decoded_len against that exact byte count. + */ + expected_len = (uint64_t)sizeof(struct dmg_mish_block) + + (uint64_t)mish_set->mish->blockDataCount * (uint64_t)sizeof(struct dmg_block_data); + if ((uint64_t)decoded_len < expected_len) { cli_dbgmsg("dmg_decode_mish: mish block %u too small\n", *mishblocknum); free(decoded); mish_set->mish = NULL; return CL_EFORMAT; - } else if (decoded_len > (sizeof(struct dmg_mish_block) + mish_set->mish->blockDataCount * sizeof(struct dmg_block_data))) { + } else if ((uint64_t)decoded_len > expected_len) { cli_dbgmsg("dmg_decode_mish: mish block %u bigger than needed, continuing\n", *mishblocknum); } @@ -516,11 +535,28 @@ return CL_CLEAN; } -/* Comparator for stripe sorting */ +/** + * @brief Compare DMG stripe entries by start sector for sorting. + * + * The sort only needs the sign of the comparison result, so compare the + * 64-bit sector numbers directly and return -1, 0, or 1. This preserves the + * full ordering across the entire uint64_t range: no intermediate subtraction + * is needed, so there is no unsigned wrap and no truncation to the comparator's + * int return type. + * + * @param stripe_a First DMG stripe entry. + * @param stripe_b Second DMG stripe entry. + * @return Negative if `stripe_a` starts first, positive if `stripe_b` starts + * first, or zero if both start at the same sector. + */ static int cmp_mish_stripes(const void *stripe_a, const void *stripe_b) { const struct dmg_block_data *a = stripe_a, *b = stripe_b; - return a->startSector - b->startSector; + if (a->startSector < b->startSector) + return -1; + if (a->startSector > b->startSector) + return 1; + return 0; } /* Safely track sector sizes for output estimate */ @@ -969,8 +1005,13 @@ " count " STDu64 " source " STDu64 " length " STDu64 "\n", mishblocknum, i, blocklist[i].type, blocklist[i].startSector, blocklist[i].sectorCount, blocklist[i].dataOffset, blocklist[i].dataLength); + /* + * Stripes must reference data before the embedded XML. Check + * dataLength against the remaining space before xmlOffset so the range + * proof does not depend on dataOffset + dataLength wrapping cleanly. + */ if ((blocklist[i].dataOffset > xmlOffset) || - (blocklist[i].dataOffset + blocklist[i].dataLength > xmlOffset)) { + (blocklist[i].dataLength > xmlOffset - blocklist[i].dataOffset)) { cli_dbgmsg("dmg_handle_mish: invalid stripe offset and/or length\n"); return CL_EFORMAT; } diff -Nru clamav-1.4.3+dfsg/libclamav/gpt.c clamav-1.4.6+dfsg/libclamav/gpt.c --- clamav-1.4.3+dfsg/libclamav/gpt.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/gpt.c 2026-08-06 21:12:04.000000000 +0000 @@ -303,7 +303,7 @@ gpe.lastLBA = le64_to_host(gpe.lastLBA); gpe.attributes = le64_to_host(gpe.attributes); for (j = 0; j < 36; ++j) { - gpe.name[i] = le16_to_host(gpe.name[i]); + gpe.name[j] = le16_to_host(gpe.name[j]); } /* check that partition is not empty and within a valid location */ diff -Nru clamav-1.4.3+dfsg/libclamav/ishield.c clamav-1.4.6+dfsg/libclamav/ishield.c --- clamav-1.4.3+dfsg/libclamav/ishield.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/ishield.c 2026-08-06 21:12:04.000000000 +0000 @@ -658,10 +658,15 @@ if (file_size) { unsigned int j; cl_error_t cabret = CL_SUCCESS; + cl_error_t limitret; - if (ctx->engine->maxfilesize && file_csize > ctx->engine->maxfilesize) { - cli_dbgmsg("is_parse_hdr: skipping file due to size limits (%lu vs %lu)\n", (unsigned long int)file_csize, (unsigned long int)ctx->engine->maxfilesize); - break; + limitret = cli_checklimits("InstallShield", ctx, 0, 0, 0); + if (limitret != CL_SUCCESS) { + if (file_name != emptyname) + fmap_unneed_ptr(map, (void *)file_name, strlen(file_name) + 1); + if (dir_name != emptyname) + fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name) + 1); + return limitret; } for (j = 0; j < c->cabcnt && c->cabs[j].cabno != cabno; j++) { @@ -737,6 +742,7 @@ static cl_error_t is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) { cl_error_t ret = CL_SUCCESS; + cl_error_t abortret = CL_SUCCESS; const uint8_t *inbuf; uint8_t *outbuf; char *tempfile; @@ -801,17 +807,51 @@ zret = inflate(&z, 0); if (zret == Z_OK || zret == Z_STREAM_END || zret == Z_BUF_ERROR) { unsigned int umpd = IS_CABBUFSZ - z.avail_out; - if (cli_writen(ofd, outbuf, umpd) != umpd) + uint64_t writelen = umpd; + cl_error_t limitret; + + if (outsz > UINT64_MAX - writelen) { + cli_dbgmsg("ishield_extract_cab: output size overflow guard hit\n"); break; - outsz += umpd; - if (zret == Z_STREAM_END || z.avail_out == IS_CABBUFSZ /* FIXMEISHIELD: is the latter ok? */) { + } + + limitret = cli_checklimits("InstallShield", ctx, outsz + writelen, 0, 0); + if (limitret == CL_ETIMEOUT || limitret == CL_EMAXFILES) { + abortret = limitret; + break; + } + if (limitret == CL_EMAXSIZE) { + uint64_t allowed = writelen; + + if (ctx->engine->maxfilesize) { + uint64_t remaining = (outsz < ctx->engine->maxfilesize) ? (ctx->engine->maxfilesize - outsz) : 0; + if (allowed > remaining) + allowed = remaining; + } + + if (ctx->engine->maxscansize) { + uint64_t remaining_scan = (ctx->scansize < ctx->engine->maxscansize) ? (ctx->engine->maxscansize - ctx->scansize) : 0; + uint64_t remaining = (outsz < remaining_scan) ? (remaining_scan - outsz) : 0; + if (allowed > remaining) + allowed = remaining; + } + + cli_dbgmsg("ishield_extract_cab: trimming output file due to size limits (" STDu64 " vs " STDu64 ")\n", + outsz + writelen, + outsz + allowed); + writelen = allowed; + } + + if (writelen && cli_writen(ofd, outbuf, writelen) != writelen) + break; + outsz += writelen; + + if (writelen != umpd) { success = 1; break; } - if (ctx->engine->maxfilesize && z.total_out > ctx->engine->maxfilesize) { - cli_dbgmsg("ishield_extract_cab: trimming output file due to size limits (%lu vs %lu)\n", z.total_out, (unsigned long int)ctx->engine->maxfilesize); + if (zret == Z_STREAM_END || z.avail_out == IS_CABBUFSZ /* FIXMEISHIELD: is the latter ok? */) { success = 1; - outsz = size; break; } continue; @@ -837,5 +877,5 @@ if (!ctx->engine->keeptmp) if (cli_unlink(tempfile)) ret = CL_EUNLINK; free(tempfile); - return success ? ret : CL_BREAK; + return success ? ret : ((abortret != CL_SUCCESS) ? abortret : CL_BREAK); } diff -Nru clamav-1.4.3+dfsg/libclamav/libclamav.map clamav-1.4.6+dfsg/libclamav/libclamav.map --- clamav-1.4.3+dfsg/libclamav/libclamav.map 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/libclamav.map 2026-08-06 21:12:04.000000000 +0000 @@ -292,6 +292,7 @@ cli_getdsig; cli_infomsg_simple; cli_set_debug_flag; + cli_append_potentially_unwanted_if_heur_exceedsmax; fmap_dump_to_file; init_allow_list; init_domain_list; @@ -301,7 +302,9 @@ ffierror_fmt; cli_magic_scan_buff; cli_checklimits; + cli_checktimelimit; cli_matchmeta; + cli_newfilepath; __cli_strcasestr; __cli_strndup; diff -Nru clamav-1.4.3+dfsg/libclamav/macho.c clamav-1.4.6+dfsg/libclamav/macho.c --- clamav-1.4.3+dfsg/libclamav/macho.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/macho.c 2026-08-06 21:12:04.000000000 +0000 @@ -46,6 +46,11 @@ #define EC32(v, conv) (conv ? cbswap32(v) : v) #define EC64(v, conv) (conv ? cbswap64(v) : v) +#define MACHO_SECTION_TYPE_MASK 0x000000ff +#define MACHO_S_ZEROFILL 0x1 +#define MACHO_S_GB_ZEROFILL 0xc +#define MACHO_S_THREAD_LOCAL_ZEROFILL 0x12 + struct macho_hdr { uint32_t magic; uint32_t cpu_type; @@ -195,6 +200,52 @@ return vaddr - sects[i].rva + sects[i].raw; } +/** + * Calculate the raw section size implied by a Mach-O alignment exponent. + * + * Mach-O section alignment is encoded as log2(bytes). Reject malformed + * exponents and rounded sizes that cannot fit in cli_exe_section.rsz. + * Zero-fill sections do not occupy file bytes, so they have no raw size. + */ +static bool cli_macho_section_raw_size(uint64_t virtual_size, + uint32_t align_exponent, + uint32_t section_flags, + uint32_t *raw_size) +{ + uint64_t alignment; + uint64_t remainder; + uint64_t padding; + uint64_t rounded_size; + uint32_t section_type = section_flags & MACHO_SECTION_TYPE_MASK; + + if (align_exponent > 31) { + return false; + } + + if (section_type == MACHO_S_ZEROFILL || + section_type == MACHO_S_GB_ZEROFILL || + section_type == MACHO_S_THREAD_LOCAL_ZEROFILL) { + *raw_size = 0; + return true; + } + + if (virtual_size > UINT32_MAX) { + return false; + } + + alignment = (uint64_t)1 << align_exponent; + remainder = virtual_size % alignment; + padding = (alignment - remainder) % alignment; + rounded_size = virtual_size + padding; + + if (rounded_size > UINT32_MAX) { + return false; + } + + *raw_size = (uint32_t)rounded_size; + return true; +} + cl_error_t cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) { struct macho_hdr hdr; @@ -383,17 +434,26 @@ for (j = 0; j < nsects; j++) { if (m64) { + uint64_t section_size; + if (fmap_readn(map, §ion64, at, sizeof(section64)) != sizeof(section64)) { cli_dbgmsg("cli_scanmacho: Can't read section\n"); free(sections); RETURN_BROKEN; } at += sizeof(section64); + section_size = EC64(section64.size, conv); sections[sect].rva = EC64(section64.addr, conv); - sections[sect].vsz = EC64(section64.size, conv); sections[sect].raw = EC32(section64.offset, conv); - section64.align = 1 << EC32(section64.align, conv); - sections[sect].rsz = sections[sect].vsz + (section64.align - (sections[sect].vsz % section64.align)) % section64.align; /* most likely we can assume it's the same as .vsz */ + if (!cli_macho_section_raw_size(section_size, + EC32(section64.align, conv), + EC32(section64.flags, conv), + §ions[sect].rsz)) { + cli_dbgmsg("cli_scanmacho: Section alignment or size is malformed\n"); + free(sections); + RETURN_BROKEN; + } + sections[sect].vsz = (uint32_t)section_size; strncpy(name, section64.sectname, sizeof(name)); name[sizeof(name) - 1] = '\0'; } else { @@ -406,13 +466,14 @@ sections[sect].rva = EC32(section.addr, conv); sections[sect].vsz = EC32(section.size, conv); sections[sect].raw = EC32(section.offset, conv); - if (EC32(section.align, conv) >= 32) { - cli_dbgmsg("cli_scanmacho: Section aligned is malformed\n"); + if (!cli_macho_section_raw_size(sections[sect].vsz, + EC32(section.align, conv), + EC32(section.flags, conv), + §ions[sect].rsz)) { + cli_dbgmsg("cli_scanmacho: Section alignment or size is malformed\n"); free(sections); RETURN_BROKEN; } - section.align = 1 << EC32(section.align, conv); - sections[sect].rsz = sections[sect].vsz + (section.align - (sections[sect].vsz % section.align)) % section.align; strncpy(name, section.sectname, sizeof(name)); name[sizeof(name) - 1] = '\0'; } diff -Nru clamav-1.4.3+dfsg/libclamav/mpool.c clamav-1.4.6+dfsg/libclamav/mpool.c --- clamav-1.4.3+dfsg/libclamav/mpool.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/mpool.c 2026-08-06 21:12:04.000000000 +0000 @@ -562,8 +562,8 @@ const struct MPMAP *mpm; const mpool_t *mp; - /* checking refcount is not necessary, but safer */ - if (!eng || !eng->refcount) + /* The caller must retain a reference while statistics are collected. */ + if (!eng) return -1; mp = eng->mempool; if (!mp) diff -Nru clamav-1.4.3+dfsg/libclamav/mpool.h clamav-1.4.6+dfsg/libclamav/mpool.h --- clamav-1.4.3+dfsg/libclamav/mpool.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/mpool.h 2026-08-06 21:12:04.000000000 +0000 @@ -47,6 +47,13 @@ char *cli_mpool_virname(mpool_t *mpool, const char *virname, unsigned int official); uint16_t *cli_mpool_hex2ui(mpool_t *mpool, const char *hex); void mpool_flush(mpool_t *mpool); + +/** + * @brief Get memory usage statistics for an engine's memory pool. + * + * The caller must retain a reference to the engine for the duration of the + * call. + */ int mpool_getstats(const struct cl_engine *engine, size_t *used, size_t *total); #define MPOOL_MALLOC(a, b) mpool_malloc(a, b) diff -Nru clamav-1.4.3+dfsg/libclamav/ole2_extract.c clamav-1.4.6+dfsg/libclamav/ole2_extract.c --- clamav-1.4.3+dfsg/libclamav/ole2_extract.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/ole2_extract.c 2026-08-06 21:12:04.000000000 +0000 @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H #include #endif @@ -2058,15 +2059,43 @@ encryption_verifier_t *verifier) { uint8_t *buffer = NULL; + uint8_t *heapBuffer = NULL; + uint8_t stackBuffer[128] = {0}; size_t bufLen = 0; + size_t passwordLen = 0; cl_error_t ret = CL_ERROR; uint32_t i = 0; + size_t j = 0; uint8_t sha1[sizeof(uint32_t) + SHA1_HASH_SIZE + sizeof(uint32_t)] = {0}; uint8_t *sha1Dst = &(sha1[sizeof(uint32_t)]); uint8_t buf1[64]; uint8_t buf2[64]; uint8_t doubleSha[SHA1_HASH_SIZE * 2]; - uint32_t tmp = 0; + uint32_t tmp = 0; + EVP_MD_CTX *sha1_ctx = NULL; + +#if OPENSSL_VERSION_MAJOR >= 3 + OSSL_LIB_CTX *ossl_ctx = NULL; + EVP_MD *sha1_md = NULL; +#else + const EVP_MD *sha1_md = NULL; +#endif + +#define SHA1_HASH_WITH_CTX(data, data_len, out) \ + do { \ + if (!EVP_DigestInit_ex(sha1_ctx, sha1_md, NULL) || \ + !EVP_DigestUpdate(sha1_ctx, (data), (data_len)) || \ + !EVP_DigestFinal_ex(sha1_ctx, (out), NULL)) { \ + cli_errmsg("ole2: SHA1 hash computation failed in generate_key_aes.\n"); \ + goto done; \ + } \ + } while (0) + + if (NULL == password || NULL == key || NULL == verifier) { + cli_errmsg("ole2: Invalid arguments to generate_key_aes\n"); + ret = CL_ENULLARG; + goto done; + } if (!key_length_valid_aes_bits(key->key_length_bits)) { cli_errmsg("ole2: Invalid key length '0x%x'\n", key->key_length_bits / 8); @@ -2075,15 +2104,56 @@ memset(key->key, 0, key->key_length_bits / 8); - bufLen = verifier->salt_size + (strlen(password) * 2); + passwordLen = strlen(password); + if (passwordLen > ((SIZE_MAX - verifier->salt_size) / 2)) { + cli_errmsg("ole2: Password length overflow\n"); + ret = CL_EARG; + goto done; + } + bufLen = verifier->salt_size + (passwordLen * 2); + + if (bufLen <= sizeof(stackBuffer)) { + buffer = stackBuffer; + } else { + heapBuffer = calloc(bufLen, 1); + if (NULL == heapBuffer) { + cli_errmsg("ole2: calloc failed\n"); + ret = CL_EMEM; + goto done; + } + buffer = heapBuffer; + } + +#if OPENSSL_VERSION_MAJOR >= 3 + ossl_ctx = OSSL_LIB_CTX_new(); + if (NULL == ossl_ctx) { + cli_errmsg("ole2: Failed to create OpenSSL library context\n"); + ret = CL_EMEM; + goto done; + } + sha1_md = EVP_MD_fetch(ossl_ctx, "SHA1", "-fips"); +#else + sha1_md = EVP_get_digestbyname("sha1"); +#endif + if (NULL == sha1_md) { + cli_errmsg("ole2: Failed to initialize SHA1 digest\n"); + ret = CL_EARG; + goto done; + } - buffer = calloc(bufLen, 1); - if (NULL == buffer) { - cli_errmsg("ole2: calloc failed\n"); + sha1_ctx = EVP_MD_CTX_new(); + if (NULL == sha1_ctx) { + cli_errmsg("ole2: Failed to allocate SHA1 context\n"); ret = CL_EMEM; goto done; } +#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW + if (OPENSSL_VERSION_NUMBER < 0x30000000L) { + EVP_MD_CTX_set_flags(sha1_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + } +#endif + tmp = verifier->salt_size; if (verifier->salt_size > sizeof(verifier->salt)) { cli_dbgmsg("ole2: Invalid salt length '0x%x'\n", verifier->salt_size); @@ -2092,22 +2162,22 @@ memcpy(buffer, verifier->salt, tmp); /*Convert to UTF16-LE*/ - for (i = 0; i < (uint32_t)strlen(password); i++) { - buffer[verifier->salt_size + (i * 2)] = password[i]; + for (j = 0; j < passwordLen; j++) { + buffer[verifier->salt_size + (j * 2)] = (uint8_t)password[j]; } - (void)cl_sha1(buffer, bufLen, sha1Dst, NULL); + SHA1_HASH_WITH_CTX(buffer, bufLen, sha1Dst); for (i = 0; i < GENERATE_KEY_AES_ITERATIONS; i++) { uint32_t eye = ole2_endian_convert_32(i); memcpy(sha1, &eye, sizeof(eye)); - (void)cl_sha1(sha1, SHA1_HASH_SIZE + sizeof(uint32_t), sha1Dst, NULL); + SHA1_HASH_WITH_CTX(sha1, SHA1_HASH_SIZE + sizeof(uint32_t), sha1Dst); } memset(&(sha1Dst[SHA1_HASH_SIZE]), 0, sizeof(uint32_t)); - (void)cl_sha1(sha1Dst, SHA1_HASH_SIZE + sizeof(uint32_t), sha1Dst, NULL); + SHA1_HASH_WITH_CTX(sha1Dst, SHA1_HASH_SIZE + sizeof(uint32_t), sha1Dst); memset(buf1, 0x36, sizeof(buf1)); for (i = 0; i < SHA1_HASH_SIZE; i++) { @@ -2115,14 +2185,14 @@ } // now sha1 buf1 - (void)cl_sha1(buf1, sizeof(buf1), doubleSha, NULL); + SHA1_HASH_WITH_CTX(buf1, sizeof(buf1), doubleSha); memset(buf2, 0x5c, sizeof(buf2)); for (i = 0; i < SHA1_HASH_SIZE; i++) { buf2[i] = buf2[i] ^ sha1Dst[i]; } - (void)cl_sha1(buf2, sizeof(buf2), &(doubleSha[SHA1_HASH_SIZE]), NULL); + SHA1_HASH_WITH_CTX(buf2, sizeof(buf2), &(doubleSha[SHA1_HASH_SIZE])); tmp = key->key_length_bits / 8; if (tmp > sizeof(key->key)) { @@ -2132,8 +2202,22 @@ memcpy(key->key, doubleSha, tmp); ret = CL_SUCCESS; + done: - CLI_FREE_AND_SET_NULL(buffer); +#undef SHA1_HASH_WITH_CTX + + CLI_FREE_AND_SET_NULL(heapBuffer); + if (NULL != sha1_ctx) { + EVP_MD_CTX_free(sha1_ctx); + } +#if OPENSSL_VERSION_MAJOR >= 3 + if (NULL != sha1_md) { + EVP_MD_free(sha1_md); + } + if (NULL != ossl_ctx) { + OSSL_LIB_CTX_free(ossl_ctx); + } +#endif return ret; } @@ -2263,8 +2347,9 @@ size_t remainingBytes, encryption_key_t *encryptionKey) { - bool bRet = false; - size_t idx = 0; + bool bRet = false; + size_t idx = 0; + size_t csp_name_max_u16 = 0; encryption_key_t key; bool bAES = false; @@ -2400,21 +2485,20 @@ goto done; } - while (true) { - // Check if we've gone past the end of the buffer without finding the end of the CSPName string. - if ((idx + 1) * sizeof(uint16_t) > remainingBytes) { - cli_dbgmsg("ole2: CSPName is missing null terminator before end of buffer.\n"); - goto done; - } - // Check if we've found the end of the CSPName string. + csp_name_max_u16 = remainingBytes / sizeof(*encryptionInfo_CSPName); + + for (idx = 0; idx < csp_name_max_u16; idx++) { if (encryptionInfo_CSPName[idx] == 0) { break; } - // Found another character in the CSPName string, keep going. - idx++; } - CSPName_length = (idx + 1) * sizeof(uint16_t); + if (idx == csp_name_max_u16) { + cli_dbgmsg("ole2: CSPName is missing null terminator before end of buffer.\n"); + goto done; + } + + CSPName_length = (idx + 1) * sizeof(*encryptionInfo_CSPName); encryptionVerifierPtr = (uint8_t *)encryptionInfo_CSPName + CSPName_length; remainingBytes -= CSPName_length; @@ -2423,6 +2507,7 @@ cli_dbgmsg("ole2: No encryption_verifier_t\n"); goto done; } + copy_encryption_verifier(&encryptionVerifier, encryptionVerifierPtr); key.key_length_bits = encryptionInfo.encryptionInfo.keySize; diff -Nru clamav-1.4.3+dfsg/libclamav/others.h clamav-1.4.6+dfsg/libclamav/others.h --- clamav-1.4.3+dfsg/libclamav/others.h 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/others.h 2026-08-06 21:12:04.000000000 +0000 @@ -69,7 +69,7 @@ * in re-enabling affected modules. */ -#define CL_FLEVEL 213 +#define CL_FLEVEL 216 #define CL_FLEVEL_DCONF CL_FLEVEL #define CL_FLEVEL_SIGTOOL CL_FLEVEL @@ -1255,7 +1255,7 @@ * @brief Attempt to get a filename from an open file descriptor. * * Caller is responsible for free'ing the filename. - * Should work on Linux, macOS, Windows. + * Should work on Linux, FreeBSD when F_KINFO is available, macOS, Windows. * * @param desc File descriptor * @param[out] filepath Will be set to file path if found, or NULL. diff -Nru clamav-1.4.3+dfsg/libclamav/others_common.c clamav-1.4.6+dfsg/libclamav/others_common.c --- clamav-1.4.3+dfsg/libclamav/others_common.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/others_common.c 2026-08-06 21:12:04.000000000 +0000 @@ -41,6 +41,9 @@ #endif #include #include +#ifdef __FreeBSD__ +#include +#endif #ifdef HAVE_PWD_H #include #endif @@ -1492,6 +1495,31 @@ goto done; } +#elif defined(__FreeBSD__) && defined(F_KINFO) + + struct kinfo_file file_info; + + if (NULL == filepath) { + cli_errmsg("cli_get_filepath_from_filedesc: Invalid args.\n"); + goto done; + } + + memset(&file_info, 0, sizeof(file_info)); + file_info.kf_structsize = sizeof(file_info); + + if ((fcntl(desc, F_KINFO, &file_info) < 0) || ('\0' == file_info.kf_path[0])) { + cli_dbgmsg("cli_get_filepath_from_filedesc: Failed to resolve filename for descriptor %d\n", desc); + status = CL_EOPEN; + goto done; + } + + evaluated_filepath = CLI_STRNDUP(file_info.kf_path, CLI_STRNLEN(file_info.kf_path, sizeof(file_info.kf_path))); + if (NULL == evaluated_filepath) { + cli_errmsg("cli_get_filepath_from_filedesc: Failed to allocate memory to store filename\n"); + status = CL_EMEM; + goto done; + } + #elif C_DARWIN char fname[PATH_MAX]; @@ -1554,10 +1582,6 @@ #ifdef _WIN32 HANDLE hFile = INVALID_HANDLE_VALUE; wchar_t *wpath = NULL; - WIN32_FILE_ATTRIBUTE_DATA attrs; - -#elif C_DARWIN - int fd = -1; #endif cli_dbgmsg("Checking realpath of %s\n", file_name); @@ -1590,34 +1614,18 @@ status = cli_get_filepath_from_handle(hFile, &real_file_path); -#elif C_DARWIN - - /* Using the filepath from filedesc method on macOS because - realpath will fail to check the realpath of a symbolic link if - the link doesn't point to anything. - Plus, we probably don't wan tot follow the link in this case anyways, - so this will check the realpath of the link, and not of the thing the - link points to. */ - fd = open(file_name, O_RDONLY | O_SYMLINK); - if (fd == -1) { - char err[128]; - cli_strerror(errno, err, sizeof(err)); - if (errno == EACCES) { - status = CL_EACCES; - } else { - status = CL_EOPEN; - } - cli_dbgmsg("Can't open file %s: %s\n", file_name, err); - goto done; - } - - status = cli_get_filepath_from_filedesc(fd, &real_file_path); - #else + /* + * On POSIX, cli_realpath() is used for canonical resolved paths such as + * quarantine action_path values and the quarantine destination root. + * Do not use the old macOS O_SYMLINK/F_GETPATH approach here: that returns + * the symlink's own path, not the resolved target path, which breaks the + * dual-path scan/quarantine design. + */ real_file_path = realpath(file_name, NULL); if (NULL == real_file_path) { - status = CL_EMEM; + status = (errno == EACCES) ? CL_EACCES : CL_EOPEN; goto done; } @@ -1636,10 +1644,6 @@ if (NULL != wpath) { free(wpath); } -#elif C_DARWIN - if (fd != -1) { - close(fd); - } #endif return status; diff -Nru clamav-1.4.3+dfsg/libclamav/pdf.c clamav-1.4.6+dfsg/libclamav/pdf.c --- clamav-1.4.3+dfsg/libclamav/pdf.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/pdf.c 2026-08-06 21:12:04.000000000 +0000 @@ -2680,6 +2680,8 @@ start = ++q; len -= 1; } + if (len <= 0) + return NULL; q = memchr(q + 1, '>', len - 1); if (!q) return NULL; diff -Nru clamav-1.4.3+dfsg/libclamav/pe.c clamav-1.4.6+dfsg/libclamav/pe.c --- clamav-1.4.3+dfsg/libclamav/pe.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/pe.c 2026-08-06 21:12:04.000000000 +0000 @@ -3753,7 +3753,7 @@ } sections[0].rva = newedi; - for (t = 0; t <= (uint32_t)sectcnt - 1; t++) + for (t = 0; t < (uint32_t)sectcnt; t++) sections[t + 1].rva = (((support[t * 2] | (support[t * 2 + 1] << 8)) - 2) << 12) - EC32(peinfo->pe_opt.opt32.ImageBase); if (!peinfo->sections[i + 1].rsz || !(src = fmap_need_off_once(map, peinfo->sections[i + 1].raw, ssize))) { diff -Nru clamav-1.4.3+dfsg/libclamav/rebuildpe.c clamav-1.4.6+dfsg/libclamav/rebuildpe.c --- clamav-1.4.3+dfsg/libclamav/rebuildpe.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/rebuildpe.c 2026-08-06 21:12:04.000000000 +0000 @@ -50,6 +50,15 @@ #define PEALIGN(o, a) (((a)) ? (((o) / (a)) * (a)) : (o)) #define PESALIGN(o, a) (((a)) ? (((o) / (a) + ((o) % (a) != 0)) * (a)) : (o)) +static uint64_t pesalign_u64(uint64_t offset, uint32_t alignment) +{ + if (!alignment) { + return offset; + } + + return ((offset / alignment) + ((offset % alignment) != 0)) * alignment; +} + struct IMAGE_PE_HEADER { uint32_t Signature; /* FILE HEADER */ @@ -127,6 +136,8 @@ int cli_rebuildpe_align(char *buffer, struct cli_exe_section *sections, int sects, uint32_t base, uint32_t ep, uint32_t ResRva, uint32_t ResSize, int file, uint32_t align) { uint32_t datasize = 0, rawbase = PESALIGN(0x148 + 0x80 + 0x28 * sects, 0x200); + uint64_t packed_datasize = 0; + uint64_t total_allocation; char *pefile = NULL, *curpe; struct IMAGE_PE_HEADER *fakepe; int i, gotghost = (sections[0].rva > PESALIGN(rawbase, 0x1000)); @@ -136,17 +147,24 @@ if (sects + gotghost > 96) return 0; - if (!align) - for (i = 0; i < sects; i++) - datasize += PESALIGN(sections[i].rsz, 0x200); - else - for (i = 0; i < sects; i++) - datasize += PESALIGN(PESALIGN(sections[i].rsz, align), 0x200); + if (!align) { + for (i = 0; i < sects; i++) { + packed_datasize += pesalign_u64(sections[i].rsz, 0x200); + } + } else { + for (i = 0; i < sects; i++) { + packed_datasize += pesalign_u64(pesalign_u64(sections[i].rsz, align), 0x200); + } + } + + if (packed_datasize > CLI_MAX_ALLOCATION) + return 0; - if (datasize > CLI_MAX_ALLOCATION) + total_allocation = rawbase + packed_datasize; + if (total_allocation > CLI_MAX_ALLOCATION) return 0; - pefile = (char *)cli_max_calloc(rawbase + datasize, 1); + pefile = (char *)cli_max_calloc((size_t)total_allocation, 1); if (!pefile) return 0; diff -Nru clamav-1.4.3+dfsg/libclamav/spin.c clamav-1.4.6+dfsg/libclamav/spin.c --- clamav-1.4.3+dfsg/libclamav/spin.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/spin.c 2026-08-06 21:12:04.000000000 +0000 @@ -62,6 +62,64 @@ #include "packlibs.h" #include "spin.h" +/** + * @brief Add a section size to the rebuilt PESpin image size. + * + * @return 0 if the size was added, 1 if the rebuilt image would exceed + * CLI_MAX_ALLOCATION. + */ +static int spin_add_blob_size(uint64_t *blobsz, uint32_t size) +{ + if (*blobsz > (uint64_t)CLI_MAX_ALLOCATION || + (uint64_t)size > (uint64_t)CLI_MAX_ALLOCATION - *blobsz) { + cli_dbgmsg("spin: rebuilt section data exceeds allocation limit\n"); + return 1; + } + + *blobsz += size; + return 0; +} + +/** + * @brief Replace an already-counted section size in the rebuilt PESpin image. + * + * @return 0 if the size was replaced, 1 if the previous size was not counted + * or the rebuilt image would exceed CLI_MAX_ALLOCATION. + */ +static int spin_replace_blob_size(uint64_t *blobsz, uint32_t old_size, uint32_t new_size) +{ + uint64_t adjusted_blobsz; + + if (*blobsz < old_size) { + cli_dbgmsg("spin: rebuilt section data accounting underflow\n"); + return 1; + } + + adjusted_blobsz = *blobsz - old_size; + if (adjusted_blobsz > (uint64_t)CLI_MAX_ALLOCATION || + (uint64_t)new_size > (uint64_t)CLI_MAX_ALLOCATION - adjusted_blobsz) { + cli_dbgmsg("spin: rebuilt section data exceeds allocation limit\n"); + return 1; + } + + *blobsz = adjusted_blobsz + new_size; + return 0; +} + +/** + * @brief Free PESpin section buffers that are marked as grown in the bitmap. + */ +static void spin_free_grown_sections(char **sects, int sectcnt, uint32_t bitmap) +{ + int j; + + for (j = 0; j < sectcnt; j++) { + if (bitmap & 1) + free(sects[j]); + bitmap >>= 1; + } +} + static char exec86(uint8_t aelle, uint8_t cielle, char *curremu, int *retval) { int len = 0; @@ -143,7 +201,7 @@ int i; while (size) { - eax ^= *src++ << 8 & 0xff00; + eax ^= ((uint32_t)(uint8_t)*src++ << 8) & 0xff00; eax = eax >> 3 & 0x1fffffff; for (i = 0; i < 4; i++) { uint32_t swap; @@ -164,7 +222,8 @@ { char *curr, *emu, *ep, *spinned; char **sects; - int blobsz = 0, j; + uint64_t blobsz = 0; + int j; uint32_t key32, bitmap, bitman; uint32_t len; uint8_t key8; @@ -402,12 +461,16 @@ len = 0; for (j = 0; j < sectcnt; j++) { if (bitmap & 1) { + if (spin_add_blob_size(&blobsz, sections[j].vsz)) { + len = 1; + break; + } + if ((sects[j] = (char *)cli_max_malloc(sections[j].vsz)) == NULL) { cli_dbgmsg("spin: malloc(%u) failed\n", sections[j].vsz); len = 1; break; } - blobsz += sections[j].vsz; memset(sects[j], 0, sections[j].vsz); cli_dbgmsg("spin: Growing sect%d: was %x will be %x\n", j, sections[j].rsz, sections[j].vsz); if (cli_unfsg(src + sections[j].raw, sects[j], sections[j].rsz, sections[j].vsz, NULL, NULL) == -1) { @@ -415,7 +478,11 @@ cli_dbgmsg("spin: Unpack failure\n"); } } else { - blobsz += sections[j].rsz; + if (spin_add_blob_size(&blobsz, sections[j].rsz)) { + len = 1; + break; + } + sects[j] = src + sections[j].raw; cli_dbgmsg("spin: Not growing sect%d\n", j); } @@ -425,12 +492,7 @@ cli_dbgmsg("spin: decompression complete\n"); if (len) { - int t; - for (t = 0; t < j; t++) { - if (bitman & 1) - free(sects[t]); - bitman = bitman >> 1 & 0x7fffffff; - } + spin_free_grown_sections(sects, j, bitman); free(sects); return 1; } @@ -444,7 +506,7 @@ break; } - if (j != sectcnt && ((bitman & (1 << j)) == 0)) { /* FIXME: not really sure either the res sect is lamed or just compressed, but this'll save some major headaches */ + if (j != sectcnt && j < 32 && ((bitman & ((uint32_t)1 << j)) == 0)) { /* FIXME: not really sure either the res sect is lamed or just compressed, but this'll save some major headaches */ cli_dbgmsg("spin: Resources (sect%d) appear to be compressed\n\tuncompressed offset %x, len %x\n\tcompressed offset %x, len %x\n", j, sections[j].rva, key32 - sections[j].rva, key32, sections[j].vsz - (key32 - sections[j].rva)); if ((curr = (char *)cli_max_malloc(sections[j].vsz)) != NULL) { @@ -454,26 +516,34 @@ free(curr); cli_dbgmsg("spin: Failed to grow resources, continuing anyway\n"); - blobsz += sections[j].rsz; } else { - sects[j] = curr; - bitman |= 1 << j; - cli_dbgmsg("spin: Resources grown\n"); - blobsz += sections[j].vsz; + if (spin_replace_blob_size(&blobsz, sections[j].rsz, sections[j].vsz)) { + free(curr); + len = 1; + } else { + sects[j] = curr; + bitman |= (uint32_t)1 << j; + cli_dbgmsg("spin: Resources grown\n"); + } } } else { /* malloc failed but i'm too deep into this crap to quit without leaking more :( */ cli_dbgmsg("spin: memory allocation failed, continuing anyway\n"); - blobsz += sections[j].rsz; } } else { cli_dbgmsg("spin: No res?!\n"); } } + if (len) { + spin_free_grown_sections(sects, sectcnt, bitman); + free(sects); + return 1; + } + bitmap = bitman; /* save as a free() bitmap */ - if ((ep = (char *)cli_max_malloc(blobsz)) != NULL) { + if ((ep = (char *)cli_max_malloc((size_t)blobsz)) != NULL) { struct cli_exe_section *rebhlp; if ((rebhlp = (struct cli_exe_section *)cli_max_malloc(sizeof(struct cli_exe_section) * (sectcnt))) != NULL) { char *to = ep; @@ -505,11 +575,7 @@ } cli_dbgmsg("spin: free bitmap is %x\n", bitman); - for (j = 0; j < sectcnt; j++) { - if (bitmap & 1) - free(sects[j]); - bitman = bitman >> 1 & 0x7fffffff; - } + spin_free_grown_sections(sects, sectcnt, bitmap); free(sects); return 1; /* :( */ } diff -Nru clamav-1.4.3+dfsg/libclamav/xar.c clamav-1.4.6+dfsg/libclamav/xar.c --- clamav-1.4.3+dfsg/libclamav/xar.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/xar.c 2026-08-06 21:12:04.000000000 +0000 @@ -34,6 +34,8 @@ #include "inflate64.h" #include "lzma_iface.h" +#define XAR_TOC_INFLATE_CHUNK_SIZE (64 * 1024) + /* xar_cleanup_temp_file - cleanup after cli_gentempfd parameters: @@ -408,6 +410,124 @@ return memcmp(result, expected, len); } +static cl_error_t xar_inflate_toc(cli_ctx *ctx, const unsigned char *compressed_toc, size_t compressed_length, + char **toc_out, size_t *toc_length_out) +{ + cl_error_t ret = CL_SUCCESS; + z_stream strm; + char *toc = NULL; + size_t capacity = XAR_TOC_INFLATE_CHUNK_SIZE; + size_t toc_length = 0; + bool inflate_initialized = false; + + memset(&strm, 0, sizeof(strm)); + + if (compressed_length > UINT_MAX) { + cli_dbgmsg("cli_scanxar: Compressed TOC is too large for zlib.\n"); + return CL_EFORMAT; + } + + toc = cli_max_malloc(capacity); + if (toc == NULL) { + cli_dbgmsg("cli_scanxar: Failed to allocate the initial TOC buffer.\n"); + return CL_EMEM; + } + + strm.next_in = (unsigned char *)compressed_toc; + strm.avail_in = (uInt)compressed_length; + + if (inflateInit(&strm) != Z_OK) { + cli_dbgmsg("cli_scanxar: inflateInit failed.\n"); + ret = CL_EFORMAT; + goto done; + } + inflate_initialized = true; + + while (true) { + uInt avail_in_before; + uInt output_available; + size_t produced; + int zret; + + output_available = (uInt)(capacity - toc_length - 1); + strm.next_out = (unsigned char *)toc + toc_length; + strm.avail_out = output_available; + avail_in_before = strm.avail_in; + + zret = inflate(&strm, Z_NO_FLUSH); + produced = output_available - strm.avail_out; + + if (toc_length > SIZE_MAX - produced) { + cli_dbgmsg("cli_scanxar: Decompressed TOC length overflow.\n"); + ret = CL_EFORMAT; + goto done; + } + toc_length += produced; + + ret = cli_checklimits("cli_scanxar", ctx, toc_length, 0, 0); + if (ret != CL_SUCCESS) { + goto done; + } + + if (zret == Z_STREAM_END) { + break; + } + if (zret != Z_OK) { + cli_dbgmsg("cli_scanxar: inflate failed with status %d.\n", zret); + ret = CL_EFORMAT; + goto done; + } + if (produced == 0 && strm.avail_in == avail_in_before) { + cli_dbgmsg("cli_scanxar: inflate made no progress before reaching the end of the TOC stream.\n"); + ret = CL_EFORMAT; + goto done; + } + + if (strm.avail_out == 0) { + char *new_toc; + size_t new_capacity; + + if (capacity == CLI_MAX_ALLOCATION) { + cli_dbgmsg("cli_scanxar: Decompressed TOC exceeds the internal allocation limit.\n"); + ret = CL_EFORMAT; + goto done; + } + + new_capacity = capacity + XAR_TOC_INFLATE_CHUNK_SIZE; + if (new_capacity < capacity || new_capacity > CLI_MAX_ALLOCATION) { + new_capacity = CLI_MAX_ALLOCATION; + } + + new_toc = cli_max_realloc(toc, new_capacity); + if (new_toc == NULL) { + cli_dbgmsg("cli_scanxar: Failed to grow the TOC buffer.\n"); + ret = CL_EMEM; + goto done; + } + toc = new_toc; + capacity = new_capacity; + } + } + + if (inflateEnd(&strm) != Z_OK) { + cli_dbgmsg("cli_scanxar: inflateEnd failed.\n"); + ret = CL_EFORMAT; + goto done; + } + inflate_initialized = false; + + toc[toc_length] = '\0'; + *toc_out = toc; + *toc_length_out = toc_length; + toc = NULL; + +done: + if (inflate_initialized) + inflateEnd(&strm); + free(toc); + return ret; +} + /* cli_scanxar - scan an xar archive. Parameters: @@ -427,7 +547,8 @@ size_t length, offset, size, at; int encoding; z_stream strm; - char *toc, *tmpname = NULL; + char *toc = NULL, *tmpname = NULL; + size_t toc_length = 0; xmlTextReaderPtr reader = NULL; int a_hash, e_hash; unsigned char *a_cksum = NULL, *e_cksum = NULL; @@ -435,8 +556,6 @@ char e_hash_result[SHA1_HASH_SIZE]; char a_hash_result[SHA1_HASH_SIZE]; - memset(&strm, 0x00, sizeof(z_stream)); - /* retrieve xar header */ if (fmap_readn(ctx->fmap, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) { cli_dbgmsg("cli_scanxar: Invalid header, too short.\n"); @@ -463,46 +582,35 @@ /* cli_dbgmsg("hdr.toc_length_decompressed %lu\n", hdr.toc_length_decompressed); */ /* cli_dbgmsg("hdr.chksum_alg %i\n", hdr.chksum_alg); */ - /* Uncompress TOC */ - strm.next_in = (unsigned char *)fmap_need_off_once(ctx->fmap, hdr.size, hdr.toc_length_compressed); - if (strm.next_in == NULL) { - cli_dbgmsg("cli_scanxar: fmap_need_off_once fails on TOC.\n"); - return CL_EREAD; - } - strm.avail_in = hdr.toc_length_compressed; - toc = cli_max_malloc(hdr.toc_length_decompressed + 1); - if (toc == NULL) { - cli_dbgmsg("cli_scanxar: cli_max_malloc fails on TOC decompress buffer.\n"); - return CL_EMEM; + /* Check time and file-count limits before inflating. Size limits are + * enforced against the actual decompressed TOC length below. */ + rc = cli_checklimits("cli_scanxar", ctx, 0, 0, 0); + if (rc != CL_SUCCESS) { + return rc; } - toc[hdr.toc_length_decompressed] = '\0'; - strm.avail_out = hdr.toc_length_decompressed; - strm.next_out = (unsigned char *)toc; - rc = inflateInit(&strm); - if (rc != Z_OK) { - cli_dbgmsg("cli_scanxar:inflateInit error %i \n", rc); - rc = CL_EFORMAT; - goto exit_toc; + + if (hdr.toc_length_compressed > SIZE_MAX) { + cli_dbgmsg("cli_scanxar: Compressed TOC length cannot be represented safely.\n"); + return CL_EFORMAT; } - rc = inflate(&strm, Z_SYNC_FLUSH); - if (rc != Z_OK && rc != Z_STREAM_END) { - inflateEnd(&strm); - cli_dbgmsg("cli_scanxar:inflate error %i \n", rc); - rc = CL_EFORMAT; - goto exit_toc; + + /* Uncompress TOC */ + { + const unsigned char *compressed_toc = fmap_need_off_once(ctx->fmap, hdr.size, (size_t)hdr.toc_length_compressed); + + if (compressed_toc == NULL) { + cli_dbgmsg("cli_scanxar: fmap_need_off_once fails on TOC.\n"); + return CL_EREAD; + } + rc = xar_inflate_toc(ctx, compressed_toc, (size_t)hdr.toc_length_compressed, &toc, &toc_length); } - rc = inflateEnd(&strm); - if (rc != Z_OK) { - cli_dbgmsg("cli_scanxar:inflateEnd error %i \n", rc); - rc = CL_EFORMAT; - goto exit_toc; + if (rc != CL_SUCCESS) { + return rc; } - if (hdr.toc_length_decompressed != strm.total_out) { - cli_dbgmsg("TOC decompress length %" PRIu64 " does not match amount decompressed %lu\n", - hdr.toc_length_decompressed, strm.total_out); - toc[strm.total_out] = '\0'; - hdr.toc_length_decompressed = strm.total_out; + if (hdr.toc_length_decompressed != toc_length) { + cli_dbgmsg("TOC declared decompress length %" PRIu64 " does not match amount decompressed %zu\n", + hdr.toc_length_decompressed, toc_length); } /* cli_dbgmsg("cli_scanxar: TOC xml:\n%s\n", toc); */ @@ -512,7 +620,7 @@ /* scan the xml */ cli_dbgmsg("cli_scanxar: scanning xar TOC xml in memory.\n"); - rc = cli_magic_scan_buff(toc, hdr.toc_length_decompressed, ctx, NULL, LAYER_ATTRIBUTES_NONE); + rc = cli_magic_scan_buff(toc, toc_length, ctx, NULL, LAYER_ATTRIBUTES_NONE); if (rc != CL_SUCCESS) { goto exit_toc; } @@ -523,7 +631,7 @@ cli_dbgmsg("cli_scanxar: Can't create temporary file for TOC.\n"); goto exit_toc; } - if (cli_writen(fd, toc, hdr.toc_length_decompressed) == (size_t)-1) { + if (cli_writen(fd, toc, toc_length) == (size_t)-1) { cli_dbgmsg("cli_scanxar: cli_writen error writing TOC.\n"); rc = CL_EWRITE; xar_cleanup_temp_file(ctx, fd, tmpname); @@ -535,7 +643,7 @@ goto exit_toc; } - reader = xmlReaderForMemory(toc, hdr.toc_length_decompressed, "noname.xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS); + reader = xmlReaderForMemory(toc, toc_length, "noname.xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS); if (reader == NULL) { cli_dbgmsg("cli_scanxar: xmlReaderForMemory error for TOC\n"); goto exit_toc; diff -Nru clamav-1.4.3+dfsg/libclamav/xlm_extract.c clamav-1.4.6+dfsg/libclamav/xlm_extract.c --- clamav-1.4.3+dfsg/libclamav/xlm_extract.c 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav/xlm_extract.c 2026-08-06 21:12:04.000000000 +0000 @@ -4044,7 +4044,9 @@ goto done; } - double val = *(double *)&data[data_pos + 1]; + double val; + /* Avoid unaligned double loads (may SIGBUS on 32-bit ARM). */ + memcpy(&val, &data[data_pos + 1], sizeof(val)); len = fprintf(out_file, " %f", val); if (len < 0) { diff -Nru clamav-1.4.3+dfsg/libclamav_rust/Cargo.toml clamav-1.4.6+dfsg/libclamav_rust/Cargo.toml --- clamav-1.4.3+dfsg/libclamav_rust/Cargo.toml 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/Cargo.toml 2026-08-06 21:12:04.000000000 +0000 @@ -12,7 +12,7 @@ sha2 = "0.10" tempfile = "3" thiserror = "1" -image = "0.24" +image = "0.25" rustdct = "0.7" transpose = "0.2" num-traits = "0.2" @@ -22,11 +22,13 @@ bindgen = "0.65" onenote_parser = { git = "https://github.com/Cisco-Talos/onenote.rs.git", branch = "CLAM-2329-new-from-slice" } hex-literal = "0.4" -inflate = "0.4" bzip2-rs = "0.1" byteorder = "1.5" delharc = "0.6" +[features] +not_ready = [] + [lib] crate-type = ["staticlib"] name = "clamav_rust" diff -Nru clamav-1.4.3+dfsg/libclamav_rust/build.rs clamav-1.4.6+dfsg/libclamav_rust/build.rs --- clamav-1.4.3+dfsg/libclamav_rust/build.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/build.rs 2026-08-06 21:12:04.000000000 +0000 @@ -48,6 +48,7 @@ "cli_infomsg_simple", "cli_errmsg", "cli_append_virus", + "cli_append_potentially_unwanted_if_heur_exceedsmax", "lsig_increment_subsig_match", "cli_versig2", "cli_getdsig", diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/alz.rs clamav-1.4.6+dfsg/libclamav_rust/src/alz.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/alz.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/alz.rs 2026-08-06 21:12:04.000000000 +0000 @@ -30,11 +30,12 @@ )] */ +use std::convert::TryFrom; use std::io::{Cursor, Read}; use byteorder::{LittleEndian, ReadBytesExt}; use bzip2_rs::DecoderReader; -use inflate::InflateStream; +use flate2::read::DeflateDecoder; use log::debug; /// File header @@ -46,6 +47,11 @@ /// End of Central directory header const ALZ_END_OF_CENTRAL_DIRECTORY_HEADER: u32 = 0x025a_4c43; +const ALZ_COMP_NOCOMP: u8 = 0; +const ALZ_COMP_BZIP2: u8 = 1; +const ALZ_COMP_DEFLATE: u8 = 2; +const MIN_SCANNED_FILE_SIZE: usize = 5; + /// Error enumerates all possible errors returned by this library. #[derive(thiserror::Error, Debug)] pub enum Error { @@ -61,6 +67,15 @@ #[error("Failed to extract file")] Extract, + #[error("Failed to allocate extracted file")] + Alloc, + + #[error("Extracted file exceeds scan limits")] + ScanLimitExceeded(u64), + + #[error("Stopped ALZ archive traversal")] + Stop, + #[error("Failed to read field: {0}")] Read(&'static str), } @@ -95,6 +110,7 @@ enc_chk: [u8; ALZ_ENCR_HEADER_LEN as usize], start_of_compressed_data: u64, + compressed_data_is_within_bounds: bool, } #[allow(dead_code)] @@ -130,6 +146,36 @@ 0 != ((AlzFileAttribute::Hidden as u8) & self.head.file_attribute) } + const fn scan_limit_size_hint(&self) -> u64 { + if self.compressed_size == 0 { + return 0; + } + + let size_hint = if self.compression_method == ALZ_COMP_NOCOMP { + self.compressed_size + } else if self.uncompressed_size <= MIN_SCANNED_FILE_SIZE as u64 { + MIN_SCANNED_FILE_SIZE as u64 + 1 + } else { + self.uncompressed_size + }; + + if size_hint == 0 && self.compressed_size > 0 { + 1 + } else { + size_hint + } + } + + const fn is_known_scan_limit_exempt(&self) -> bool { + self.compressed_size == 0 + || (self.compression_method == ALZ_COMP_NOCOMP + && self.compressed_size <= MIN_SCANNED_FILE_SIZE as u64) + } + + const fn has_valid_compressed_data_bounds(&self) -> bool { + self.compressed_data_is_within_bounds + } + fn _dump(&self) { println!( "self.start_of_compressed_data = {}", @@ -192,6 +238,7 @@ file_name: String::new(), enc_chk: [0; ALZ_ENCR_HEADER_LEN as usize], start_of_compressed_data: 0, + compressed_data_is_within_bounds: true, } } @@ -273,16 +320,20 @@ } } - #[allow(clippy::cast_possible_truncation)] - let idx0: usize = cursor.position() as usize; - let idx1: usize = idx0 + self.head.file_name_length as usize; + let idx0: usize = usize::try_from(cursor.position()) + .map_err(|_| Error::Parse("Invalid file name offset"))?; + let idx1: usize = idx0 + .checked_add(usize::from(self.head.file_name_length)) + .ok_or(Error::Parse("Invalid file name length"))?; if idx1 > cursor.get_ref().len() { return Err(Error::Parse("Invalid file name length")); } let filename = &cursor.get_ref().as_slice()[idx0..idx1]; - cursor.set_position(idx1 as u64); + cursor.set_position( + u64::try_from(idx1).map_err(|_| Error::Parse("Invalid file name length"))?, + ); self.file_name = String::from_utf8_lossy(filename).into_owned(); @@ -293,11 +344,16 @@ } self.start_of_compressed_data = cursor.position(); - cursor.set_position(self.start_of_compressed_data + self.compressed_size); + let end_of_compressed_data = self + .start_of_compressed_data + .checked_add(self.compressed_size) + .ok_or(Error::Parse("Invalid compressed data length"))?; + + self.compressed_data_is_within_bounds = end_of_compressed_data + <= u64::try_from(cursor.get_ref().len()) + .map_err(|_| Error::Parse("Invalid compressed data length"))?; - if self.start_of_compressed_data + self.compressed_size > cursor.get_ref().len() as u64 { - return Err(Error::Parse("Invalid compressed data length")); - } + cursor.set_position(end_of_compressed_data); Ok(()) } @@ -313,130 +369,239 @@ )); } + self.check_compression_supported() + } + + fn check_compression_supported(&self) -> Result<(), Error> { + match self.compression_method { + ALZ_COMP_NOCOMP | ALZ_COMP_BZIP2 | ALZ_COMP_DEFLATE => {} + _ => return Err(Error::UnsupportedFeature("Compression Method Unsupported")), + } + Ok(()) } /* * This has no header/checksum validation. */ + fn extract_file_deflate_reader( + &mut self, + decompressor: &mut R, + files: &mut Vec, + max_extracted_size: u64, + ) -> Result<(), Error> { + let mut out: Vec = Vec::::new(); + let mut buffer = [0u8; 8192]; + + loop { + let len = match decompressor.read(&mut buffer) { + Ok(len) => len, + Err(_) => { + debug!("Unable to decompress deflate data"); + if out.is_empty() { + return Err(Error::Extract); + } + + self.push_file(out, files)?; + return Err(Error::Extract); + } + }; + if len == 0 { + break; + } + + if let Some(needed) = + self.append_output(&mut out, &buffer[..len], max_extracted_size)? + { + self.push_file(out, files)?; + return Err(Error::ScanLimitExceeded(needed)); + } + } + + self.push_file(out, files) + } + + /* + * This has no header/checksum validation. + */ fn extract_file_deflate( &mut self, cursor: &std::io::Cursor<&Vec>, files: &mut Vec, + max_extracted_size: u64, ) -> Result<(), Error> { - #[allow(clippy::cast_possible_truncation)] - let start: usize = self.start_of_compressed_data as usize; - #[allow(clippy::cast_possible_truncation)] - let end: usize = start + self.compressed_size as usize; - if end >= cursor.get_ref().len() { - return Err(Error::Extract); - } - let data: &[u8] = &cursor.get_ref().as_slice()[start..end]; + let start: usize = + usize::try_from(self.start_of_compressed_data).map_err(|_| Error::Extract)?; + let len: usize = usize::try_from(self.compressed_size).map_err(|_| Error::Extract)?; + let end: usize = start.checked_add(len).ok_or(Error::Extract)?; + let data: &[u8] = cursor + .get_ref() + .as_slice() + .get(start..end) + .ok_or(Error::Extract)?; - let mut inflater = InflateStream::new(); - let mut out: Vec = Vec::::new(); - let mut n: usize = 0; + let mut decompressor = DeflateDecoder::new(data); + self.extract_file_deflate_reader(&mut decompressor, files, max_extracted_size) + } - while n < data.len() { - let res = inflater.update(&data[n..]); - if let Ok((num_bytes_read, result)) = res { - n += num_bytes_read; - out.extend(result.iter().copied()); - } else { - return Err(Error::Extract); - } + fn append_output( + &self, + out: &mut Vec, + buffer: &[u8], + max_extracted_size: u64, + ) -> Result, Error> { + let needed = out.len().checked_add(buffer.len()).ok_or(Error::Extract)?; + let needed_u64 = u64::try_from(needed).map_err(|_| Error::Extract)?; + + if needed_u64 > max_extracted_size { + let current = u64::try_from(out.len()).map_err(|_| Error::Extract)?; + let remaining = max_extracted_size.saturating_sub(current); + let copy_len = usize::try_from(remaining) + .unwrap_or(usize::MAX) + .min(buffer.len()); + + out.try_reserve(copy_len).map_err(|_| Error::Alloc)?; + out.extend_from_slice(&buffer[..copy_len]); + + return Ok(Some(needed_u64)); } - self.write_file(&out, files); + out.try_reserve(buffer.len()).map_err(|_| Error::Alloc)?; + out.extend_from_slice(buffer); - Ok(()) + Ok(None) } - fn write_file(&mut self, buffer: &[u8], files: &mut Vec) { + fn push_file(&mut self, data: Vec, files: &mut Vec) -> Result<(), Error> { + if data.is_empty() { + return Ok(()); + } + + let mut name = String::new(); + name.try_reserve(self.file_name.len()) + .map_err(|_| Error::Alloc)?; + name.push_str(&self.file_name); + let extracted_file: ExtractedFile = ExtractedFile { - name: Some(self.file_name.to_string()), - data: buffer.to_vec(), + name: Some(name), + data, }; - if 0 != extracted_file.data.len() { - files.push(extracted_file); - } + files.try_reserve(1).map_err(|_| Error::Alloc)?; + files.push(extracted_file); + + Ok(()) + } + + fn write_file(&mut self, buffer: &[u8], files: &mut Vec) -> Result<(), Error> { + let mut data: Vec = Vec::new(); + data.try_reserve_exact(buffer.len()) + .map_err(|_| Error::Alloc)?; + data.extend_from_slice(buffer); + + self.push_file(data, files) } fn extract_file_nocomp( &mut self, - cursor: &mut std::io::Cursor<&Vec>, + cursor: &std::io::Cursor<&Vec>, files: &mut Vec, + max_extracted_size: u64, ) -> Result<(), Error> { - #[allow(clippy::cast_possible_truncation)] - let idx0: usize = self.start_of_compressed_data as usize; + let idx0: usize = + usize::try_from(self.start_of_compressed_data).map_err(|_| Error::Extract)?; - let mut len = self.compressed_size; if self.compressed_size != self.uncompressed_size { - debug!("Uncompressed file has different lengths for compressed vs uncompressed, using the shorter"); - if self.compressed_size > self.uncompressed_size { - len = self.uncompressed_size; - } + debug!("Uncompressed file has different lengths for compressed vs uncompressed, using the stored size"); } - #[allow(clippy::cast_possible_truncation)] - let idx1: usize = idx0 + len as usize; - if idx1 > cursor.get_ref().len() { - debug!("Invalid data length"); - return Err(Error::Extract); - } + let len: usize = usize::try_from(self.compressed_size).map_err(|_| Error::Extract)?; + let idx1: usize = idx0.checked_add(len).ok_or(Error::Extract)?; - let contents = &cursor.get_ref().as_slice()[idx0..idx1]; - cursor.set_position(idx1 as u64); + let contents = cursor + .get_ref() + .as_slice() + .get(idx0..idx1) + .ok_or(Error::Extract)?; - self.write_file(contents, files); - Ok(()) + let contents_len = u64::try_from(contents.len()).map_err(|_| Error::Extract)?; + if contents_len > max_extracted_size { + let copy_len = usize::try_from(max_extracted_size) + .unwrap_or(usize::MAX) + .min(contents.len()); + self.write_file(&contents[..copy_len], files)?; + return Err(Error::ScanLimitExceeded(contents_len)); + } + + self.write_file(contents, files) } fn extract_file_bzip2( &mut self, cursor: &std::io::Cursor<&Vec>, files: &mut Vec, + max_extracted_size: u64, ) -> Result<(), Error> { - #[allow(clippy::cast_possible_truncation)] - let idx0: usize = self.start_of_compressed_data as usize; - #[allow(clippy::cast_possible_truncation)] - let idx1: usize = idx0 + self.compressed_size as usize; - - let contents = &cursor.get_ref().as_slice()[idx0..idx1]; + let idx0: usize = + usize::try_from(self.start_of_compressed_data).map_err(|_| Error::Extract)?; + let len: usize = usize::try_from(self.compressed_size).map_err(|_| Error::Extract)?; + let idx1: usize = idx0.checked_add(len).ok_or(Error::Extract)?; + + let contents = cursor + .get_ref() + .as_slice() + .get(idx0..idx1) + .ok_or(Error::Extract)?; - /* - * Create vector of the needed capacity. - */ let mut out: Vec = Vec::new(); - for _i in 0..self.uncompressed_size { - out.push(0); + let mut decompressor = DecoderReader::new(contents); + let mut buffer = [0u8; 8192]; + loop { + let len = match decompressor.read(&mut buffer) { + Ok(len) => len, + Err(_) => { + debug!("Unable to decompress bz2 data"); + if out.is_empty() { + return Err(Error::Extract); + } + + self.push_file(out, files)?; + return Err(Error::Extract); + } + }; + if len == 0 { + break; + } + + if let Some(needed) = + self.append_output(&mut out, &buffer[..len], max_extracted_size)? + { + self.push_file(out, files)?; + return Err(Error::ScanLimitExceeded(needed)); + } } - let mut decompressor = DecoderReader::new(contents); - let ret = decompressor.read_exact(&mut out); - if ret.is_err() { - debug!("Unable to decompress bz2 data"); - return Err(Error::Extract); + if let Ok(uncompressed_size) = usize::try_from(self.uncompressed_size) { + if out.len() != uncompressed_size { + debug!( + "Bzip2 file has different lengths for declared vs decompressed data, using the decompressed size" + ); + } } - self.write_file(&out, files); - Ok(()) + self.push_file(out, files) } fn extract_file( &mut self, cursor: &mut std::io::Cursor<&Vec>, files: &mut Vec, + max_extracted_size: u64, ) -> Result<(), Error> { - const ALZ_COMP_NOCOMP: u8 = 0; - const ALZ_COMP_BZIP2: u8 = 1; - const ALZ_COMP_DEFLATE: u8 = 2; - match self.compression_method { - ALZ_COMP_NOCOMP => self.extract_file_nocomp(cursor, files), - ALZ_COMP_BZIP2 => self.extract_file_bzip2(cursor, files), - ALZ_COMP_DEFLATE => self.extract_file_deflate(cursor, files), + ALZ_COMP_NOCOMP => self.extract_file_nocomp(cursor, files, max_extracted_size), + ALZ_COMP_BZIP2 => self.extract_file_bzip2(cursor, files, max_extracted_size), + ALZ_COMP_DEFLATE => self.extract_file_deflate(cursor, files, max_extracted_size), _ => Err(Error::Extract), } } @@ -448,9 +613,43 @@ pub data: Vec, } +impl ExtractedFile { + const fn counts_toward_scan_limits(&self) -> bool { + self.data.len() > MIN_SCANNED_FILE_SIZE + } +} + +pub struct AlzFileMetadata<'a> { + pub file_name: &'a str, + pub compressed_size: u64, + pub uncompressed_size: u64, + pub is_directory: bool, + pub is_encrypted: bool, + pub file_crc: u32, + pub filepos: usize, +} + +pub struct AlzExtractionLimits { + pub max_file_size: u64, + pub max_total_size: u64, + pub max_files_remaining: usize, +} + +pub enum AlzExtractionDecision { + Extract(AlzExtractionLimits), + Skip, + Stop, +} + #[derive(Default)] pub struct Alz { pub embedded_files: Vec, + pub file_limit_exceeded_size: Option, + pub total_limit_exceeded_size: Option, + pub file_count_limit_exceeded: bool, + extracted_size: u64, + scan_counted_files: usize, + parse_error: bool, } impl<'aa> Alz { @@ -462,29 +661,169 @@ .map_or(false, |n| ALZ_FILE_HEADER == n) } - fn parse_local_fileheader(&mut self, cursor: &mut std::io::Cursor<&Vec>) -> bool { + fn parse_local_fileheader( + &mut self, + cursor: &mut std::io::Cursor<&Vec>, + filepos: &mut usize, + should_extract: &mut F, + ) -> Result<(), Error> + where + F: FnMut(&AlzFileMetadata<'_>) -> AlzExtractionDecision, + { let mut local_fileheader = AlzLocalFileHeader::new(); - if let Err(err) = local_fileheader.parse(cursor) { - debug!("{err}"); - return false; - } + local_fileheader.parse(cursor)?; + + let metadata_filepos = *filepos; + *filepos = metadata_filepos.saturating_add(1); - if let Err(err) = local_fileheader.is_supported() { - debug!("{err}"); - return false; + /* The is_file flag doesn't appear to always be set, so we'll just assume it's a file if + * it's not marked as a directory.*/ + let metadata = AlzFileMetadata { + file_name: &local_fileheader.file_name, + compressed_size: local_fileheader.compressed_size, + uncompressed_size: local_fileheader.uncompressed_size, + is_directory: local_fileheader.is_directory(), + is_encrypted: local_fileheader.is_encrypted(), + file_crc: local_fileheader.file_crc, + filepos: metadata_filepos, + }; + + let extraction_decision = should_extract(&metadata); + if matches!(extraction_decision, AlzExtractionDecision::Stop) { + return Err(Error::Stop); } if !local_fileheader.is_directory() { - /* The is_file flag doesn't appear to always be set, so we'll just assume it's a file if - * it's not marked as a directory.*/ - let res2 = local_fileheader.extract_file(cursor, &mut self.embedded_files); - if res2.is_err() { - return false; + let AlzExtractionDecision::Extract(limits) = extraction_decision else { + if !local_fileheader.has_valid_compressed_data_bounds() { + return Err(Error::Parse("Invalid compressed data length")); + } + + return Ok(()); + }; + + let support_error = local_fileheader.is_supported().err(); + if let Some(err) = support_error { + if !local_fileheader.has_valid_compressed_data_bounds() { + return Err(Error::Parse("Invalid compressed data length")); + } + + debug!("{err}"); + return Ok(()); + } + + let base_extracted_size = self.extracted_size; + let max_total_remaining = limits.max_total_size.saturating_sub(base_extracted_size); + let max_extracted_size = limits.max_file_size.min(max_total_remaining); + let files_start = self.embedded_files.len(); + + if self.scan_counted_files >= limits.max_files_remaining + && !local_fileheader.is_known_scan_limit_exempt() + { + debug!( + "ALZ file {:?} skipped because the file count limit was reached.", + local_fileheader.file_name + ); + self.file_count_limit_exceeded = true; + return Err(Error::Stop); } + + if !local_fileheader.has_valid_compressed_data_bounds() { + return Err(Error::Parse("Invalid compressed data length")); + } + + let max_extracted_size = if local_fileheader.is_known_scan_limit_exempt() { + local_fileheader.compressed_size + } else if max_extracted_size <= MIN_SCANNED_FILE_SIZE as u64 { + 0 + } else { + max_extracted_size + }; + + if max_extracted_size == 0 { + debug!( + "ALZ file {:?} skipped because the extraction size budget is exhausted.", + local_fileheader.file_name + ); + + let needed = local_fileheader.scan_limit_size_hint(); + if needed > limits.max_file_size + && self + .file_limit_exceeded_size + .map_or(true, |current| current < needed) + { + self.file_limit_exceeded_size = Some(needed); + } + + let total_needed = base_extracted_size.saturating_add(needed); + if total_needed > limits.max_total_size + && self + .total_limit_exceeded_size + .map_or(true, |current| current < total_needed) + { + self.total_limit_exceeded_size = Some(total_needed); + } + + return Ok(()); + } + + match local_fileheader.extract_file( + cursor, + &mut self.embedded_files, + max_extracted_size, + ) { + Ok(()) => {} + Err(Error::ScanLimitExceeded(needed)) => { + debug!( + "ALZ file {:?} exceeded extraction size limits. Scanning truncated content.", + local_fileheader.file_name + ); + if needed > limits.max_file_size + && self + .file_limit_exceeded_size + .map_or(true, |current| current < needed) + { + self.file_limit_exceeded_size = Some(needed); + } + + let total_needed = base_extracted_size.saturating_add(needed); + if total_needed > limits.max_total_size + && self + .total_limit_exceeded_size + .map_or(true, |current| current < total_needed) + { + self.total_limit_exceeded_size = Some(total_needed); + } + } + Err(Error::Extract) => { + debug!( + "Failed to extract ALZ file {:?}. Continuing with next entry.", + local_fileheader.file_name + ); + } + Err(err) => return Err(err), + } + + for file in &self.embedded_files[files_start..] { + if !file.counts_toward_scan_limits() { + continue; + } + + self.scan_counted_files = self.scan_counted_files.saturating_add(1); + + let Ok(file_size) = u64::try_from(file.data.len()) else { + self.extracted_size = u64::MAX; + break; + }; + + self.extracted_size = self.extracted_size.saturating_add(file_size); + } + } else if !local_fileheader.has_valid_compressed_data_bounds() { + return Err(Error::Parse("Invalid compressed data length")); } - true + Ok(()) } #[allow(clippy::unused_self)] @@ -503,16 +842,42 @@ pub const fn new() -> Self { Self { embedded_files: Vec::new(), + file_limit_exceeded_size: None, + total_limit_exceeded_size: None, + file_count_limit_exceeded: false, + extracted_size: 0, + scan_counted_files: 0, + parse_error: false, } } + pub const fn has_parse_error(&self) -> bool { + self.parse_error + } + /// # Errors /// Will return `Error::Parse` if file headers are not correct or are inconsistent. pub fn from_bytes(bytes: &'aa [u8]) -> Result { + Self::from_bytes_with_filter(bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: usize::MAX, + }) + }) + } + + /// # Errors + /// Will return `Error::Parse` if file headers are not correct or are inconsistent. + pub fn from_bytes_with_filter(bytes: &'aa [u8], mut should_extract: F) -> Result + where + F: FnMut(&AlzFileMetadata<'_>) -> AlzExtractionDecision, + { let binding = bytes.to_vec(); let mut cursor = Cursor::new(&binding); let mut alz: Self = Self::new(); + let mut filepos: usize = 1; if !alz.is_alz(&mut cursor) { return Err(Error::Parse("No ALZ file header")); @@ -531,9 +896,22 @@ match sig { ALZ_LOCAL_FILE_HEADER => { - if alz.parse_local_fileheader(&mut cursor) { - continue; + match alz.parse_local_fileheader(&mut cursor, &mut filepos, &mut should_extract) + { + Ok(()) => {} + Err(Error::Stop) => break, + Err(Error::Alloc) => return Err(Error::Alloc), + Err(err) => { + if filepos == 1 { + return Err(err); + } + + debug!("Failed to parse ALZ local file header: {err}"); + alz.parse_error = true; + break; + } } + continue; } ALZ_CENTRAL_DIRECTORY_HEADER => { if alz.parse_central_directoryheader(&mut cursor) { @@ -546,7 +924,14 @@ } _ => { #[allow(clippy::uninlined_format_args)] - return Err(Error::UnrecognizedSig(format!("{:x}", sig))); + let err = Error::UnrecognizedSig(format!("{:x}", sig)); + if filepos == 1 { + return Err(err); + } + + debug!("Failed to parse ALZ archive: {err}"); + alz.parse_error = true; + break; } } } @@ -554,3 +939,983 @@ Ok(alz) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::io::Write; + + fn append_local_file( + alz: &mut Vec, + name: &str, + compression_method: u8, + uncompressed_size: u8, + data: &[u8], + ) { + append_local_entry( + alz, + name, + AlzFileAttribute::File as u8, + 0x10, + compression_method, + uncompressed_size, + data, + ); + } + + fn append_local_entry( + alz: &mut Vec, + name: &str, + file_attribute: u8, + file_descriptor: u8, + compression_method: u8, + uncompressed_size: u8, + data: &[u8], + ) { + let compressed_size = u8::try_from(data.len()).unwrap(); + append_local_entry_with_sizes( + alz, + name, + file_attribute, + file_descriptor, + compression_method, + compressed_size, + uncompressed_size, + data, + ); + } + + fn append_local_entry_with_sizes( + alz: &mut Vec, + name: &str, + file_attribute: u8, + file_descriptor: u8, + compression_method: u8, + compressed_size: u8, + uncompressed_size: u8, + data: &[u8], + ) { + let name = name.as_bytes(); + let name_len = u16::try_from(name.len()).unwrap(); + + alz.extend_from_slice(&ALZ_LOCAL_FILE_HEADER.to_le_bytes()); + alz.extend_from_slice(&name_len.to_le_bytes()); + alz.push(file_attribute); + alz.extend_from_slice(&0u32.to_le_bytes()); + alz.push(file_descriptor); + alz.push(0); + alz.push(compression_method); + alz.push(0); + alz.extend_from_slice(&0u32.to_le_bytes()); + alz.push(compressed_size); + alz.push(uncompressed_size); + alz.extend_from_slice(name); + if file_descriptor & 0x01 != 0 { + alz.extend_from_slice(&[0; ALZ_ENCR_HEADER_LEN as usize]); + } + alz.extend_from_slice(data); + } + + fn extraction_limits() -> AlzExtractionLimits { + AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: usize::MAX, + } + } + + fn raw_deflate(data: &[u8]) -> Vec { + let mut encoder = + flate2::write::DeflateEncoder::new(Vec::new(), flate2::Compression::default()); + encoder.write_all(data).unwrap(); + encoder.finish().unwrap() + } + + fn bzip2_truncated_after_output() -> Vec { + vec![ + 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xe5, 0x69, 0x95, 0xee, + 0x00, 0x00, 0x01, 0x17, 0x80, 0x00, 0x02, 0x02, 0x00, 0x44, 0x00, 0x2e, 0x24, 0x9c, + 0x20, 0x20, 0x00, 0x31, 0x4c, 0x00, 0x01, 0x4d, 0x31, 0x32, 0x7a, 0x9b, 0x41, 0xa9, + 0x5d, 0x57, 0xa3, 0xe0, 0x0b, 0x2c, 0x6f, 0x98, 0x2e, 0xe4, 0x8a, 0x70, 0xa1, + ] + } + + #[test] + fn extraction_error_does_not_stop_later_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_BZIP2: u8 = 1; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "bad.bz2", ALZ_COMP_BZIP2, 1, &[0]); + append_local_file(&mut bytes, "good.txt", ALZ_COMP_NOCOMP, 4, b"good"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(extraction_limits()) + }) + .unwrap(); + + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("good.txt")); + assert_eq!(alz.embedded_files[0].data, b"good"); + } + + #[test] + fn bzip2_error_preserves_output_produced_before_error() { + const ALZ_COMP_BZIP2: u8 = 1; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file( + &mut bytes, + "truncated.bz2", + ALZ_COMP_BZIP2, + 18, + &bzip2_truncated_after_output(), + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(extraction_limits()) + }) + .unwrap(); + + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("truncated.bz2")); + assert_eq!(alz.embedded_files[0].data, b"Eicar-Test-Payload"); + } + + #[test] + fn deflate_error_preserves_output_produced_before_error() { + struct ErrorAfterOutput { + output: Option>, + } + + let payload = vec![b'A'; 9000]; + let mut reader = ErrorAfterOutput { + output: Some(payload.clone()), + }; + impl Read for ErrorAfterOutput { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let Some(output) = self.output.take() else { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "corrupt deflate stream", + )); + }; + + let len = output.len().min(buf.len()); + buf[..len].copy_from_slice(&output[..len]); + self.output = if len < output.len() { + Some(output[len..].to_vec()) + } else { + None + }; + + Ok(len) + } + } + + let mut header = AlzLocalFileHeader::new(); + header.file_name = "corrupt.deflate".to_owned(); + let mut files = Vec::new(); + + assert!(matches!( + header.extract_file_deflate_reader(&mut reader, &mut files, u64::MAX), + Err(Error::Extract) + )); + + assert_eq!(files.len(), 1); + assert_eq!(files[0].name.as_deref(), Some("corrupt.deflate")); + assert_eq!(files[0].data, payload); + } + + #[test] + fn later_parse_error_preserves_earlier_extracted_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "good.txt", ALZ_COMP_NOCOMP, 4, b"good"); + bytes.extend_from_slice(&ALZ_LOCAL_FILE_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(extraction_limits()) + }) + .unwrap(); + + assert!(alz.has_parse_error()); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("good.txt")); + assert_eq!(alz.embedded_files[0].data, b"good"); + } + + #[test] + fn invalid_payload_bounds_reports_metadata_before_parse_error() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_entry_with_sizes( + &mut bytes, + "secret.txt", + AlzFileAttribute::File as u8, + 0x11, + ALZ_COMP_NOCOMP, + 10, + 10, + b"x", + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |entry| { + metadata.push(( + entry.file_name.to_owned(), + entry.filepos, + entry.is_encrypted, + )); + AlzExtractionDecision::Extract(extraction_limits()) + }) + .unwrap(); + + assert_eq!(metadata, vec![("secret.txt".to_owned(), 1, true)]); + assert!(alz.has_parse_error()); + assert!(alz.embedded_files.is_empty()); + } + + #[test] + fn deflate_limit_uses_decompressed_size_not_header() { + const ALZ_COMP_DEFLATE: u8 = 2; + let payload = vec![b'A'; 1024]; + let compressed = raw_deflate(&payload); + assert!(compressed.len() <= u8::MAX.into()); + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "big.txt", ALZ_COMP_DEFLATE, 1, &compressed); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: 64, + max_total_size: u64::MAX, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.file_limit_exceeded_size, Some(payload.len() as u64)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("big.txt")); + assert_eq!(alz.embedded_files[0].data.as_slice(), &payload[..64]); + } + + #[test] + fn total_limit_does_not_set_per_file_limit() { + const ALZ_COMP_NOCOMP: u8 = 0; + let payload = vec![b'A'; 60]; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file( + &mut bytes, + "a", + ALZ_COMP_NOCOMP, + payload.len() as u8, + &payload, + ); + append_local_file( + &mut bytes, + "b", + ALZ_COMP_NOCOMP, + payload.len() as u8, + &payload, + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: 64, + max_total_size: 100, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.file_limit_exceeded_size, None); + assert_eq!(alz.total_limit_exceeded_size, Some(120)); + assert_eq!(alz.embedded_files.len(), 2); + assert_eq!(alz.embedded_files[0].data.len(), 60); + assert_eq!(alz.embedded_files[1].data.len(), 40); + } + + #[test] + fn exhausted_total_limit_skips_later_extraction() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn exhausted_total_limit_uses_stored_size_for_nocomp() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 0, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn exhausted_total_limit_records_compressed_entry_with_zero_declared_size() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_DEFLATE: u8 = 2; + + let compressed = raw_deflate(b"second"); + assert!(compressed.len() <= u8::MAX.into()); + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_DEFLATE, 0, &compressed); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn exhausted_total_limit_does_not_charge_empty_compressed_entry_by_declared_size() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_DEFLATE: u8 = 2; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "empty.deflate", ALZ_COMP_DEFLATE, 6, b""); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, None); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn tiny_stored_file_bypasses_partial_size_budget() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "tiny.txt", ALZ_COMP_NOCOMP, 5, b"tiny!"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: 4, + max_total_size: 4, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.file_limit_exceeded_size, None); + assert_eq!(alz.total_limit_exceeded_size, None); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("tiny.txt")); + assert_eq!(alz.embedded_files[0].data, b"tiny!"); + } + + #[test] + fn total_limit_skips_extraction_when_remaining_budget_is_tiny() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 10, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn total_limit_records_compressed_entry_when_remaining_budget_is_tiny() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_DEFLATE: u8 = 2; + + let compressed = raw_deflate(b"second"); + assert!(compressed.len() <= u8::MAX.into()); + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_DEFLATE, 1, &compressed); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 10, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn exhausted_total_limit_does_not_record_unsupported_method() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_UNSUPPORTED: u8 = 99; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file( + &mut bytes, + "unsupported.bin", + ALZ_COMP_UNSUPPORTED, + 6, + b"second", + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, None); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn unsupported_method_with_invalid_payload_bounds_reports_parse_error() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_UNSUPPORTED: u8 = 99; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_entry_with_sizes( + &mut bytes, + "unsupported.bin", + AlzFileAttribute::File as u8, + 0x10, + ALZ_COMP_UNSUPPORTED, + 10, + 10, + b"x", + ); + append_local_file(&mut bytes, "later.txt", ALZ_COMP_NOCOMP, 6, b"later!"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(extraction_limits()) + }) + .unwrap(); + + assert_eq!(metadata_names, vec!["unsupported.bin".to_owned()]); + assert!(alz.has_parse_error()); + assert!(alz.embedded_files.is_empty()); + } + + #[test] + fn queued_file_limit_ignores_unsupported_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_entry( + &mut bytes, + "encrypted.bin", + AlzFileAttribute::File as u8, + 0x11, + ALZ_COMP_NOCOMP, + 6, + b"second", + ); + append_local_entry( + &mut bytes, + "descriptor.bin", + AlzFileAttribute::File as u8, + 0x18, + ALZ_COMP_NOCOMP, + 5, + b"third", + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec![ + "first.txt".to_owned(), + "encrypted.bin".to_owned(), + "descriptor.bin".to_owned() + ] + ); + assert!(!alz.file_count_limit_exceeded); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn total_limit_ignores_tiny_members() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "tiny1.txt", ALZ_COMP_NOCOMP, 1, b"t"); + append_local_file(&mut bytes, "tiny2.txt", ALZ_COMP_NOCOMP, 1, b"u"); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let alz = Alz::from_bytes_with_filter(&bytes, |_| { + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: 6, + max_files_remaining: usize::MAX, + }) + }) + .unwrap(); + + assert_eq!(alz.total_limit_exceeded_size, Some(12)); + assert_eq!(alz.embedded_files.len(), 3); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("tiny1.txt")); + assert_eq!(alz.embedded_files[0].data, b"t"); + assert_eq!(alz.embedded_files[1].name.as_deref(), Some("tiny2.txt")); + assert_eq!(alz.embedded_files[1].data, b"u"); + assert_eq!(alz.embedded_files[2].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[2].data, b"first!"); + } + + #[test] + fn queued_file_limit_skips_later_extraction() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + append_local_file(&mut bytes, "third.txt", ALZ_COMP_NOCOMP, 6, b"third!"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec!["first.txt".to_owned(), "second.txt".to_owned()] + ); + assert!(alz.file_count_limit_exceeded); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn queued_file_limit_stops_before_later_invalid_payload_bounds() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_entry_with_sizes( + &mut bytes, + "truncated.txt", + AlzFileAttribute::File as u8, + 0x10, + ALZ_COMP_NOCOMP, + 10, + 10, + b"x", + ); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec!["first.txt".to_owned(), "truncated.txt".to_owned()] + ); + assert!(alz.file_count_limit_exceeded); + assert!(!alz.has_parse_error()); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn queued_file_limit_ignores_tiny_members() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "tiny.txt", ALZ_COMP_NOCOMP, 1, b"t"); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec![ + "tiny.txt".to_owned(), + "first.txt".to_owned(), + "second.txt".to_owned() + ] + ); + assert!(alz.file_count_limit_exceeded); + assert_eq!(alz.embedded_files.len(), 2); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("tiny.txt")); + assert_eq!(alz.embedded_files[0].data, b"t"); + assert_eq!(alz.embedded_files[1].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[1].data, b"first!"); + } + + #[test] + fn queued_file_limit_allows_tiny_current_member() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "tiny.txt", ALZ_COMP_NOCOMP, 1, b"t"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec!["first.txt".to_owned(), "tiny.txt".to_owned()] + ); + assert!(!alz.file_count_limit_exceeded); + assert_eq!(alz.embedded_files.len(), 2); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + assert_eq!(alz.embedded_files[1].name.as_deref(), Some("tiny.txt")); + assert_eq!(alz.embedded_files[1].data, b"t"); + } + + #[test] + fn queued_file_limit_does_not_trust_compressed_tiny_hint() { + const ALZ_COMP_NOCOMP: u8 = 0; + const ALZ_COMP_DEFLATE: u8 = 2; + + let compressed = raw_deflate(b"second"); + assert!(compressed.len() <= u8::MAX.into()); + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 6, b"first!"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_DEFLATE, 0, &compressed); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Extract(AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: 1, + }) + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec!["first.txt".to_owned(), "second.txt".to_owned()] + ); + assert!(alz.file_count_limit_exceeded); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first!"); + } + + #[test] + fn stop_decision_stops_archive_traversal() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 5, b"first"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Stop + }) + .unwrap(); + + assert!(alz.embedded_files.is_empty()); + assert_eq!(metadata_names, vec!["first.txt".to_owned()]); + } + + #[test] + fn stop_decision_runs_for_directory_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_entry( + &mut bytes, + "dir/", + AlzFileAttribute::Directory as u8, + 0x10, + ALZ_COMP_NOCOMP, + 0, + b"", + ); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 5, b"first"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + AlzExtractionDecision::Stop + }) + .unwrap(); + + assert!(alz.embedded_files.is_empty()); + assert_eq!(metadata_names, vec!["dir/".to_owned()]); + } + + #[test] + fn stop_decision_preserves_earlier_extracted_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 5, b"first"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_names = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_names.push(metadata.file_name.to_owned()); + if metadata.file_name == "second.txt" { + AlzExtractionDecision::Stop + } else { + AlzExtractionDecision::Extract(extraction_limits()) + } + }) + .unwrap(); + + assert_eq!( + metadata_names, + vec!["first.txt".to_owned(), "second.txt".to_owned()] + ); + assert_eq!(alz.embedded_files.len(), 1); + assert_eq!(alz.embedded_files[0].name.as_deref(), Some("first.txt")); + assert_eq!(alz.embedded_files[0].data, b"first"); + } + + #[test] + fn metadata_file_positions_are_one_based_and_include_skipped_entries() { + const ALZ_COMP_NOCOMP: u8 = 0; + + let mut bytes = Vec::new(); + bytes.extend_from_slice(&ALZ_FILE_HEADER.to_le_bytes()); + bytes.extend_from_slice(&0u32.to_le_bytes()); + append_local_entry( + &mut bytes, + "dir/", + AlzFileAttribute::Directory as u8, + 0x10, + ALZ_COMP_NOCOMP, + 0, + b"", + ); + append_local_entry( + &mut bytes, + "encrypted.bin", + AlzFileAttribute::File as u8, + 0x11, + ALZ_COMP_NOCOMP, + 0, + b"", + ); + append_local_file(&mut bytes, "first.txt", ALZ_COMP_NOCOMP, 5, b"first"); + append_local_file(&mut bytes, "second.txt", ALZ_COMP_NOCOMP, 6, b"second"); + bytes.extend_from_slice(&ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_le_bytes()); + + let mut metadata_positions = Vec::new(); + let alz = Alz::from_bytes_with_filter(&bytes, |metadata| { + metadata_positions.push(( + metadata.file_name.to_owned(), + metadata.filepos, + metadata.is_encrypted, + metadata.is_directory, + )); + AlzExtractionDecision::Skip + }) + .unwrap(); + + assert!(alz.embedded_files.is_empty()); + assert_eq!( + metadata_positions, + vec![ + ("dir/".to_owned(), 1, false, true), + ("encrypted.bin".to_owned(), 2, true, false), + ("first.txt".to_owned(), 3, false, false), + ("second.txt".to_owned(), 4, false, false), + ] + ); + } +} diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/css_image_extract.rs clamav-1.4.6+dfsg/libclamav_rust/src/css_image_extract.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/css_image_extract.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/css_image_extract.rs 2026-08-06 21:12:04.000000000 +0000 @@ -23,7 +23,7 @@ use std::{ffi::CStr, os::raw::c_char}; use base64::{engine::general_purpose as base64_engine_standard, Engine as _}; -use log::{debug, error, warn}; +use log::{debug, warn}; use unicode_segmentation::UnicodeSegmentation; use crate::{ @@ -66,10 +66,15 @@ 'outer: loop { // Find occurrence of "url" with if let Some(pos) = self.remaining.find("url") { - (_, self.remaining) = self.remaining.split_at(pos + "url".len()); - // Found 'url'. + // Found 'url'. Get the stuff after it. + if let Some((_, rest)) = self.remaining.split_at_checked(pos + "url".len()) { + self.remaining = rest; + } else { + // Split failed. + self.remaining = ""; + return None; + } } else { - // No occurrence of "url" // No more 'url's. self.remaining = ""; return None; @@ -78,8 +83,14 @@ // Skip whitespace until we find '(' for (pos, c) in self.remaining.grapheme_indices(true) { if c == "(" { - // Found left-paren. - (_, self.remaining) = self.remaining.split_at(pos + 1); + // Found left-paren. Get the stuff after it. + self.remaining = + if let Some((_, rest)) = self.remaining.split_at_checked(pos + 1) { + rest + } else { + // Split failed. Was not whitespace or '(', and maybe not a legal char. + continue 'outer; + }; break; } else if c.contains(char::is_whitespace) { // Skipping whitespace. @@ -103,7 +114,13 @@ depth -= 1; } else { // Found right-paren. - let (contents, remaining) = self.remaining.split_at(pos); + let (contents, remaining) = + if let Some((c, r)) = self.remaining.split_at_checked(pos) { + (c, r) + } else { + // Split failed. + continue; + }; url_parameter = Some(contents); // Set the remaining bytes so we can look for more later. @@ -123,65 +140,14 @@ // Strip optional whitespace and quotes from front and back. - // Trim off whitespace at beginning - for (pos, c) in url_parameter.grapheme_indices(true) { - if c.contains(char::is_whitespace) { - // Skipping whitespace before url contents. - continue; - } else { - (_, url_parameter) = url_parameter.split_at(pos); - break; - } - } + // Trim off whitespace at beginning and end. + url_parameter = url_parameter.trim(); - // Trim off whitespace at end - for (pos, c) in url_parameter.graphemes(true).rev().enumerate() { - if c.contains(char::is_whitespace) { - // Skipping whitespace after url contents. - continue; - } else { - (url_parameter, _) = url_parameter.split_at(url_parameter.len() - pos); - break; - } - } + // Trim off " at beginning and end. + url_parameter = url_parameter.trim_matches('"'); - // Trim off " at beginning. - let c = url_parameter.graphemes(true).next(); - if let Some(c) = c { - if c == "\"" { - (_, url_parameter) = url_parameter.split_at(1); - } - }; - - // Trim off " at end. - let c = url_parameter.graphemes(true).next_back(); - if let Some(c) = c { - if c == "\"" { - (url_parameter, _) = url_parameter.split_at(url_parameter.len() - 1); - } - }; - - // Trim off whitespace at beginning. - for (pos, c) in url_parameter.grapheme_indices(true) { - if c.contains(char::is_whitespace) { - // Skipping whitespace before url contents. - continue; - } else { - (_, url_parameter) = url_parameter.split_at(pos); - break; - } - } - - // Trim off whitespace at end. - for (pos, c) in url_parameter.graphemes(true).rev().enumerate() { - if c.contains(char::is_whitespace) { - // Skipping whitespace after url contents. - continue; - } else { - (url_parameter, _) = url_parameter.split_at(url_parameter.len() - pos); - break; - } - } + // Trim off more whitespace at beginning and end which had been inside the quotes. + url_parameter = url_parameter.trim(); // Check for embedded image data for the "url" if !url_parameter.starts_with("data:") { @@ -190,7 +156,12 @@ } // Found "data:" - (_, url_parameter) = url_parameter.split_at("data:".len()); + if let Some((_, rest)) = url_parameter.split_at_checked("data:".len()) { + url_parameter = rest; + } else { + // Split failed. Let's move along. + continue; + } // The exact image type doesn't matter at all to a browser. // They really don't care if it's "image/gif" or "blah blah blah". @@ -198,8 +169,13 @@ // Find contents after ";" if let Some(pos) = url_parameter.find(';') { - (_, url_parameter) = url_parameter.split_at(pos + ";".len()); - // Found ";" + // Found ";". Get the stuff after it. + if let Some((_, rest)) = url_parameter.split_at_checked(pos + ";".len()) { + url_parameter = rest; + } else { + // Split failed. Something in this data appears to be malformed. Let's move along. + continue 'outer; + } } else { // No occurrence of ";" in the url() parameter. continue 'outer; @@ -209,7 +185,12 @@ for (pos, c) in url_parameter.grapheme_indices(true) { if c == "b" { // Found 'b'. - (_, url_parameter) = url_parameter.split_at(pos + 1); + if let Some((_, rest)) = url_parameter.split_at_checked(pos + 1) { + url_parameter = rest; + } else { + // Split failed. Was not whitespace or 'b', and maybe not a legal char. + continue 'outer; + } break; } else if c.contains(char::is_whitespace) { // Skipping whitespace. @@ -227,13 +208,23 @@ } // Found "base64" - (_, url_parameter) = url_parameter.split_at("ase64".len()); + if let Some((_, rest)) = url_parameter.split_at_checked("ase64".len()) { + url_parameter = rest; + } else { + // Split failed. Something in this data appears to be malformed. Let's move along. + continue 'outer; + } // Skip whitespace until we find ',' for (pos, c) in url_parameter.grapheme_indices(true) { if c == "," { - // Found ','. - (_, url_parameter) = url_parameter.split_at(pos + 1); + // Found ','. Get the stuff after it. + if let Some((_, rest)) = url_parameter.split_at_checked(pos + 1) { + url_parameter = rest; + } else { + // Split failed. Was not whitespace or ',', and maybe not a legal char. + continue 'outer; + } break; } else if c.contains(char::is_whitespace) { // Skipping whitespace. @@ -245,15 +236,7 @@ } // Trim off whitespace at beginning. - for (pos, c) in url_parameter.grapheme_indices(true) { - if c.contains(char::is_whitespace) { - // Skipping whitespace before url contents. - continue; - } else { - (_, url_parameter) = url_parameter.split_at(pos); - break; - } - } + url_parameter = url_parameter.trim_start(); debug!("Found base64'd image data CSS url() function args."); return Some(url_parameter); diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/evidence.rs clamav-1.4.6+dfsg/libclamav_rust/src/evidence.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/evidence.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/evidence.rs 2026-08-06 21:12:04.000000000 +0000 @@ -22,7 +22,7 @@ use std::{collections::HashMap, ffi::CStr, mem::ManuallyDrop, os::raw::c_char}; -use log::{debug, error, warn}; +use log::{debug, warn}; use crate::{ffi_util::FFIError, rrf_call, sys, validate_str_param}; diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/fmap.rs clamav-1.4.6+dfsg/libclamav_rust/src/fmap.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/fmap.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/fmap.rs 2026-08-06 21:12:04.000000000 +0000 @@ -22,7 +22,7 @@ use std::convert::TryFrom; -use log::{debug, error}; +use log::debug; use crate::{sys, util::str_from_ptr}; diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/onenote.rs clamav-1.4.6+dfsg/libclamav_rust/src/onenote.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/onenote.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/onenote.rs 2026-08-06 21:12:04.000000000 +0000 @@ -27,7 +27,7 @@ }; use hex_literal::hex; -use log::{debug, error}; +use log::debug; use onenote_parser; /// Error enumerates all possible errors returned by this library. diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/scanners.rs clamav-1.4.6+dfsg/libclamav_rust/src/scanners.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/scanners.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/scanners.rs 2026-08-06 21:12:04.000000000 +0000 @@ -21,6 +21,7 @@ */ use std::{ + convert::TryFrom, ffi::{c_char, CString}, io::Read, panic, @@ -33,14 +34,19 @@ use log::{debug, error, warn}; use crate::{ - alz::Alz, + alz::{Alz, AlzExtractionDecision, AlzExtractionLimits, Error as AlzError}, ctx, onenote::OneNote, sys::{ - cl_error_t, cl_error_t_CL_EFORMAT, cl_error_t_CL_ERROR, cl_error_t_CL_SUCCESS, cli_ctx, - cli_magic_scan_buff, + cl_error_t, cl_error_t_CL_EFORMAT, cl_error_t_CL_EMAXFILES, cl_error_t_CL_EMAXSIZE, + cl_error_t_CL_EMEM, cl_error_t_CL_ERROR, cl_error_t_CL_SUCCESS, cl_error_t_CL_VIRUS, + cli_ctx, cli_magic_scan_buff, + }, + util::{ + append_potentially_unwanted_if_heur_exceedsmax, check_scan_limits, check_scan_time_limit, + scan_archive_metadata, HEURISTICS_LIMITS_EXCEEDED_MAX_FILES, + HEURISTICS_LIMITS_EXCEEDED_MAX_SCAN_SIZE, }, - util::{check_scan_limits, scan_archive_metadata}, }; /// Rust wrapper of libclamav's cli_magic_scan_buff() function. @@ -307,6 +313,101 @@ cl_error_t_CL_SUCCESS } +unsafe fn alz_extraction_limits(ctx: *mut cli_ctx) -> AlzExtractionLimits { + if ctx.is_null() || (*ctx).engine.is_null() { + return AlzExtractionLimits { + max_file_size: u64::MAX, + max_total_size: u64::MAX, + max_files_remaining: usize::MAX, + }; + } + + let engine = &*(*ctx).engine; + let max_files_remaining = if engine.maxfiles == 0 { + usize::MAX + } else { + usize::try_from(engine.maxfiles.saturating_sub((*ctx).scannedfiles)).unwrap_or(usize::MAX) + }; + + AlzExtractionLimits { + max_file_size: if engine.maxfilesize == 0 { + u64::MAX + } else { + engine.maxfilesize + }, + max_total_size: if engine.maxscansize == 0 { + u64::MAX + } else { + engine.maxscansize.saturating_sub((*ctx).scansize) + }, + max_files_remaining, + } +} + +fn handle_alz_metadata_scan_result( + file_name: &str, + metadata_ret: cl_error_t, + alz_metadata_ret: &mut cl_error_t, +) -> bool { + match metadata_ret { + ret if ret == cl_error_t_CL_SUCCESS => true, + ret if ret == cl_error_t_CL_EFORMAT => { + debug!( + "ALZ file {:?} metadata scan failed with {}. Continuing extraction.", + file_name, metadata_ret + ); + true + } + ret if ret == cl_error_t_CL_VIRUS => { + *alz_metadata_ret = metadata_ret; + debug!( + "ALZ file {:?} metadata did not pass scan checks. Skipping extraction.", + file_name + ); + false + } + _ => { + *alz_metadata_ret = metadata_ret; + debug!( + "ALZ file {:?} metadata scan failed with {}. Aborting extraction.", + file_name, metadata_ret + ); + false + } + } +} + +fn handle_alz_metadata_limit_result( + limit_ret: cl_error_t, + alz_metadata_ret: &mut cl_error_t, +) -> bool { + match limit_ret { + ret if ret == cl_error_t_CL_SUCCESS => true, + ret if ret == cl_error_t_CL_EMAXFILES => false, + _ => { + *alz_metadata_ret = limit_ret; + false + } + } +} + +fn alz_metadata_size(size: u64) -> Option { + usize::try_from(size).ok() +} + +fn handle_alz_metadata_directory_limit_result( + limit_ret: cl_error_t, + alz_metadata_ret: &mut cl_error_t, +) -> bool { + match limit_ret { + ret if ret == cl_error_t_CL_SUCCESS => true, + _ => { + *alz_metadata_ret = limit_ret; + false + } + } +} + /// Scan an Alz file for attachments /// /// # Safety @@ -333,14 +434,101 @@ } }; - let alz = match Alz::from_bytes(file_bytes) { - Ok(x) => x, - Err(err) => { - error!("Failed to parse Alz file: {}", err.to_string()); - return cl_error_t_CL_ERROR; + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + let alz_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + Alz::from_bytes_with_filter(file_bytes, |metadata| { + if alz_metadata_ret != cl_error_t_CL_SUCCESS { + return AlzExtractionDecision::Stop; + } + + if metadata.is_directory { + let limit_ret = check_scan_time_limit(ctx); + if !handle_alz_metadata_directory_limit_result(limit_ret, &mut alz_metadata_ret) { + debug!("Exceeded scan limits. Bailing out."); + return AlzExtractionDecision::Stop; + } + + return AlzExtractionDecision::Skip; + } + + let limit_ret = check_scan_limits("ALZ", ctx, 0, 0, 0); + if !handle_alz_metadata_limit_result(limit_ret, &mut alz_metadata_ret) { + debug!("Exceeded scan limits. Bailing out."); + return AlzExtractionDecision::Stop; + } + + match ( + alz_metadata_size(metadata.compressed_size), + alz_metadata_size(metadata.uncompressed_size), + ) { + (Some(compressed_size), Some(uncompressed_size)) => { + let metadata_ret = scan_archive_metadata( + ctx, + metadata.file_name, + compressed_size, + uncompressed_size, + metadata.is_encrypted, + metadata.filepos, + metadata.file_crc as i32, + ); + if !handle_alz_metadata_scan_result( + metadata.file_name, + metadata_ret, + &mut alz_metadata_ret, + ) { + return AlzExtractionDecision::Stop; + } + } + _ => { + debug!( + "ALZ file {:?} metadata size does not fit platform size_t. Skipping metadata scan.", + metadata.file_name + ); + } + } + + AlzExtractionDecision::Extract(alz_extraction_limits(ctx)) + }) + })); + + let alz = match alz_result { + Ok(Ok(x)) => x, + Ok(Err(AlzError::Alloc)) => { + debug!("Failed to allocate memory when parsing ALZ archive"); + return cl_error_t_CL_EMEM; + } + Ok(Err(err)) => { + debug!("Failed to parse Alz file: {}", err.to_string()); + return cl_error_t_CL_EFORMAT; + } + Err(_) => { + debug!("Panic occurred when trying to parse ALZ archive"); + return cl_error_t_CL_EFORMAT; } }; + if alz_metadata_ret != cl_error_t_CL_SUCCESS { + return alz_metadata_ret; + } + + if let Some(needed) = alz.file_limit_exceeded_size { + let ret = check_scan_limits("ALZ", ctx, needed, 0, 0); + if ret != cl_error_t_CL_SUCCESS && ret != cl_error_t_CL_EMAXSIZE { + return ret; + } + } + + if alz.total_limit_exceeded_size.is_some() { + append_potentially_unwanted_if_heur_exceedsmax( + ctx, + HEURISTICS_LIMITS_EXCEEDED_MAX_SCAN_SIZE, + ); + } + + if alz.file_count_limit_exceeded { + append_potentially_unwanted_if_heur_exceedsmax(ctx, HEURISTICS_LIMITS_EXCEEDED_MAX_FILES); + } + for i in 0..alz.embedded_files.len() { let ret = magic_scan( ctx, @@ -352,5 +540,129 @@ } } + if alz.has_parse_error() { + return cl_error_t_CL_EFORMAT; + } + cl_error_t_CL_SUCCESS } +#[cfg(test)] +mod tests { + use super::*; + use crate::sys::cl_error_t_CL_ETIMEOUT; + + #[test] + fn alz_metadata_scan_success_continues() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(handle_alz_metadata_scan_result( + "entry", + cl_error_t_CL_SUCCESS, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_SUCCESS); + } + + #[test] + fn alz_metadata_scan_format_error_continues() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(handle_alz_metadata_scan_result( + "entry", + cl_error_t_CL_EFORMAT, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_SUCCESS); + } + + #[test] + fn alz_metadata_scan_virus_stops() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(!handle_alz_metadata_scan_result( + "entry", + cl_error_t_CL_VIRUS, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_VIRUS); + } + + #[test] + fn alz_metadata_scan_hard_error_stops() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(!handle_alz_metadata_scan_result( + "entry", + cl_error_t_CL_EMEM, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_EMEM); + } + + #[test] + fn alz_metadata_limit_success_continues() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(handle_alz_metadata_limit_result( + cl_error_t_CL_SUCCESS, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_SUCCESS); + } + + #[test] + fn alz_metadata_limit_failure_stops_without_terminal_status() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(!handle_alz_metadata_limit_result( + cl_error_t_CL_EMAXFILES, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_SUCCESS); + } + + #[test] + fn alz_metadata_limit_hard_failure_stops_with_terminal_status() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(!handle_alz_metadata_limit_result( + cl_error_t_CL_ETIMEOUT, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_ETIMEOUT); + } + + #[test] + fn alz_metadata_directory_limit_success_continues() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(handle_alz_metadata_directory_limit_result( + cl_error_t_CL_SUCCESS, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_SUCCESS); + } + + #[test] + fn alz_metadata_directory_limit_hard_failure_stops_with_terminal_status() { + let mut alz_metadata_ret = cl_error_t_CL_SUCCESS; + + assert!(!handle_alz_metadata_directory_limit_result( + cl_error_t_CL_ETIMEOUT, + &mut alz_metadata_ret, + )); + assert_eq!(alz_metadata_ret, cl_error_t_CL_ETIMEOUT); + } + + #[test] + fn alz_metadata_size_rejects_platform_overflow() { + assert_eq!(alz_metadata_size(42), Some(42usize)); + assert_eq!(alz_metadata_size(usize::MAX as u64), Some(usize::MAX)); + + #[cfg(target_pointer_width = "32")] + assert_eq!(alz_metadata_size(u64::from(u32::MAX) + 1), None); + + #[cfg(target_pointer_width = "64")] + assert_eq!(alz_metadata_size(u64::MAX), Some(usize::MAX)); + } +} diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/sys.rs clamav-1.4.6+dfsg/libclamav_rust/src/sys.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/sys.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/sys.rs 2026-08-06 21:12:04.000000000 +0000 @@ -796,6 +796,12 @@ ) -> cl_error_t; } extern "C" { + pub fn cli_append_potentially_unwanted_if_heur_exceedsmax( + ctx: *mut cli_ctx, + vname: *mut ::std::os::raw::c_char, + ); +} +extern "C" { pub fn cli_warnmsg(str_: *const ::std::os::raw::c_char, ...); } extern "C" { diff -Nru clamav-1.4.3+dfsg/libclamav_rust/src/util.rs clamav-1.4.6+dfsg/libclamav_rust/src/util.rs --- clamav-1.4.3+dfsg/libclamav_rust/src/util.rs 2025-06-17 01:41:15.000000000 +0000 +++ clamav-1.4.6+dfsg/libclamav_rust/src/util.rs 2026-08-06 21:12:04.000000000 +0000 @@ -22,10 +22,14 @@ use std::{ffi::CStr, fs::File}; -use log::error; +use log::{debug, error}; use crate::sys; +extern "C" { + fn cli_checktimelimit(ctx: *mut sys::cli_ctx) -> sys::cl_error_t; +} + /// Obtain a std::fs::File from an i32 in a platform-independent manner. /// /// On Unix-like platforms, this is done with File::from_raw_fd(). @@ -85,7 +89,7 @@ let module_name = match std::ffi::CString::new(module_name) { Ok(name) => name, Err(_) => { - error!("Invalid module_name: {}", module_name); + error!("Invalid module_name: {:?}", module_name); return sys::cl_error_t_CL_EFORMAT; } }; @@ -93,6 +97,44 @@ unsafe { sys::cli_checklimits(module_name.as_ptr(), ctx, need1, need2, need3) } } +/// Check only the scan time limit in case we need to abort the scan. +/// +/// # Safety +/// +/// ctx must be a valid pointer to a clamav scan context structure +/// +pub unsafe fn check_scan_time_limit(ctx: *mut sys::cli_ctx) -> sys::cl_error_t { + unsafe { cli_checktimelimit(ctx) } +} + +pub const HEURISTICS_LIMITS_EXCEEDED_MAX_SCAN_SIZE: &[u8] = + b"Heuristics.Limits.Exceeded.MaxScanSize\0"; +pub const HEURISTICS_LIMITS_EXCEEDED_MAX_FILES: &[u8] = b"Heuristics.Limits.Exceeded.MaxFiles\0"; + +/// Append an exceeds-max heuristic alert or metadata entry. +/// +/// The C evidence store retains the original `virname` pointer, so the alert +/// name must have static lifetime rather than temporary Rust string storage. +/// +/// # Safety +/// +/// ctx must be a valid pointer to a clamav scan context structure. +/// virname must point to a static NUL-terminated C string. +/// +pub unsafe fn append_potentially_unwanted_if_heur_exceedsmax( + ctx: *mut sys::cli_ctx, + virname: &'static [u8], +) { + debug_assert_eq!(virname.last(), Some(&0)); + + unsafe { + sys::cli_append_potentially_unwanted_if_heur_exceedsmax( + ctx, + virname.as_ptr().cast_mut().cast(), + ); + } +} + /// Scan archive metadata. /// /// # Safety @@ -111,7 +153,7 @@ let module_name = match std::ffi::CString::new(filename) { Ok(name) => name, Err(_) => { - error!("Invalid module_name: {}", filename); + debug!("Invalid archive metadata filename: {:?}", filename); return sys::cl_error_t_CL_EFORMAT; } }; diff -Nru clamav-1.4.3+dfsg/unit_tests/CMakeLists.txt clamav-1.4.6+dfsg/unit_tests/CMakeLists.txt --- clamav-1.4.3+dfsg/unit_tests/CMakeLists.txt 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/CMakeLists.txt 2026-08-06 21:12:04.000000000 +0000 @@ -70,7 +70,10 @@ # check_clamd is used by the clamd tests add_executable(check_clamd) target_sources(check_clamd - PRIVATE check_clamd.c checks.h) + PRIVATE + check_clamd.c + checks.h + ../clamd/thrmgr.c) target_link_libraries(check_clamd PRIVATE ClamAV::libclamav diff -Nru clamav-1.4.3+dfsg/unit_tests/check_clamav.c clamav-1.4.6+dfsg/unit_tests/check_clamav.c --- clamav-1.4.3+dfsg/unit_tests/check_clamav.c 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/check_clamav.c 2026-08-06 21:12:04.000000000 +0000 @@ -10,7 +10,11 @@ #include #include #include +#include #include +#if HAVE_UNISTD_H +#include +#endif #ifdef HAVE_SYS_MMAN_H #include #endif @@ -27,6 +31,7 @@ #include "dsig.h" #include "fpu.h" #include "entconv.h" +#include "actions.h" #include "checks.h" @@ -528,6 +533,157 @@ } END_TEST +#ifndef _WIN32 +START_TEST(test_action_setup_quarantine_lock_uses_validated_directory_handle) +{ + char *parent_dir = NULL; + char *validated_path = NULL; + char *validated_saved = NULL; + char *replacement_lock = NULL; + char *lockname = NULL; + int validated_fd = -1; + struct stat lock_stat = {0}; + + parent_dir = cli_gentemp(NULL); + ck_assert_msg(NULL != parent_dir, "cli_gentemp failed"); + ck_assert_msg(0 == mkdir(parent_dir, 0700), "mkdir(%s) failed", parent_dir); + + validated_path = cli_newfilepath(parent_dir, "quarantine"); + validated_saved = cli_newfilepath(parent_dir, "quarantine-original"); + ck_assert_msg((NULL != validated_path) && (NULL != validated_saved), "Failed to allocate quarantine paths"); + + ck_assert_msg(0 == mkdir(validated_path, 0700), "mkdir(%s) failed", validated_path); + + validated_fd = open(validated_path, O_RDONLY | O_NOFOLLOW); + ck_assert_msg(-1 != validated_fd, "open(%s) failed: %s", validated_path, strerror(errno)); + + ck_assert_msg(0 == rename(validated_path, validated_saved), "rename(%s, %s) failed: %s", + validated_path, validated_saved, strerror(errno)); + ck_assert_msg(0 == mkdir(validated_path, 0700), "mkdir(%s) replacement failed: %s", + validated_path, strerror(errno)); + + ck_assert_msg(0 == action_setup_quarantine_lock_at(validated_fd, validated_path, &lockname), + "action_setup_quarantine_lock_at failed"); + ck_assert_msg(NULL != lockname, "action_setup_quarantine_lock_at did not return a lock name"); + + ck_assert_msg(0 == fstatat(validated_fd, lockname, &lock_stat, AT_SYMLINK_NOFOLLOW), + "fstatat(validated_fd, %s) failed: %s", lockname, strerror(errno)); + ck_assert_msg(S_ISREG(lock_stat.st_mode), "Expected quarantine lock to be a regular file"); + + replacement_lock = cli_newfilepath(validated_path, lockname); + ck_assert_msg(NULL != replacement_lock, "Failed to allocate replacement lock path"); + ck_assert_msg(0 != access(replacement_lock, F_OK), + "Lock file was created in the replacement quarantine path"); + + ck_assert_msg(0 == unlinkat(validated_fd, lockname, 0), "unlinkat(validated_fd, %s) failed: %s", + lockname, strerror(errno)); + free(lockname); + lockname = NULL; + + close(validated_fd); + validated_fd = -1; + + cli_rmdirs(parent_dir); + free(replacement_lock); + free(validated_saved); + free(validated_path); + free(parent_dir); +} +END_TEST + +START_TEST(test_action_source_open_relative_path_stores_absolute_action_path) +{ + char *parent_dir = NULL; + char *file_path = NULL; + int fd = -1; + action_source_t source; + + action_source_init(&source); + + parent_dir = cli_gentemp("."); + ck_assert_msg(NULL != parent_dir, "cli_gentemp failed"); + ck_assert_msg(0 == mkdir(parent_dir, 0700), "mkdir(%s) failed: %s", parent_dir, strerror(errno)); + + file_path = cli_newfilepath(parent_dir, "payload"); + ck_assert_msg(NULL != file_path, "Failed to allocate payload path"); + + fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); + ck_assert_msg(-1 != fd, "open(%s) failed: %s", file_path, strerror(errno)); + ck_assert_msg(4 == write(fd, "test", 4), "write(%s) failed: %s", file_path, strerror(errno)); + close(fd); + fd = -1; + + ck_assert_msg(CL_SUCCESS == action_source_open(file_path, &source), + "action_source_open(%s) failed", file_path); + ck_assert_msg(NULL != source.action_path, "action_source_open did not populate action_path"); + ck_assert_msg('/' == source.action_path[0], + "Expected absolute action_path for relative source path, got '%s'", source.action_path); + + action_source_close(&source); + + ck_assert_msg(0 == unlink(file_path), "unlink(%s) failed: %s", file_path, strerror(errno)); + free(file_path); + file_path = NULL; + ck_assert_msg(0 == rmdir(parent_dir), "rmdir(%s) failed: %s", parent_dir, strerror(errno)); + free(parent_dir); + parent_dir = NULL; +} +END_TEST + +START_TEST(test_action_source_open_path_rejects_replaced_symlink) +{ + char *parent_dir = NULL; + char *file_path = NULL; + char *replacement_path = NULL; + char *resolved_path = NULL; + int fd = -1; + action_source_t source; + + action_source_init(&source); + + parent_dir = cli_gentemp(NULL); + ck_assert_msg(NULL != parent_dir, "cli_gentemp failed"); + ck_assert_msg(0 == mkdir(parent_dir, 0700), "mkdir(%s) failed: %s", parent_dir, strerror(errno)); + + file_path = cli_newfilepath(parent_dir, "payload"); + replacement_path = cli_newfilepath(parent_dir, "replacement"); + ck_assert_msg((NULL != file_path) && (NULL != replacement_path), "Failed to allocate test paths"); + + fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); + ck_assert_msg(-1 != fd, "open(%s) failed: %s", file_path, strerror(errno)); + ck_assert_msg(7 == write(fd, "payload", 7), "write(%s) failed: %s", file_path, strerror(errno)); + close(fd); + fd = -1; + + ck_assert_msg(CL_SUCCESS == cli_realpath(file_path, &resolved_path), + "cli_realpath(%s) failed", file_path); + + fd = open(replacement_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); + ck_assert_msg(-1 != fd, "open(%s) failed: %s", replacement_path, strerror(errno)); + ck_assert_msg(11 == write(fd, "replacement", 11), "write(%s) failed: %s", replacement_path, strerror(errno)); + close(fd); + fd = -1; + + ck_assert_msg(0 == unlink(file_path), "unlink(%s) failed: %s", file_path, strerror(errno)); + ck_assert_msg(0 == symlink(replacement_path, file_path), "symlink(%s, %s) failed: %s", + replacement_path, file_path, strerror(errno)); + + ck_assert_msg(CL_SUCCESS != action_source_open_path(file_path, resolved_path, &source), + "action_source_open_path accepted a resolved path that had been replaced by a symlink"); + + action_source_close(&source); + + ck_assert_msg(0 == unlink(file_path), "unlink(%s) symlink failed: %s", file_path, strerror(errno)); + ck_assert_msg(0 == unlink(replacement_path), "unlink(%s) failed: %s", replacement_path, strerror(errno)); + free(resolved_path); + free(replacement_path); + free(file_path); + ck_assert_msg(0 == rmdir(parent_dir), "rmdir(%s) failed: %s", parent_dir, strerror(errno)); + free(parent_dir); +} +END_TEST +#endif + static char **testfiles = NULL; static unsigned testfiles_n = 0; @@ -1324,6 +1480,11 @@ tcase_add_test(tc_cl, test_cl_statchkdir); tcase_add_test(tc_cl, test_cl_settempdir); tcase_add_test(tc_cl, test_cl_strerror); +#ifndef _WIN32 + tcase_add_test(tc_cl, test_action_setup_quarantine_lock_uses_validated_directory_handle); + tcase_add_test(tc_cl, test_action_source_open_relative_path_stores_absolute_action_path); + tcase_add_test(tc_cl, test_action_source_open_path_rejects_replaced_symlink); +#endif suite_add_tcase(s, tc_cl_scan); tcase_add_checked_fixture(tc_cl_scan, engine_setup, engine_teardown); diff -Nru clamav-1.4.3+dfsg/unit_tests/check_clamd.c clamav-1.4.6+dfsg/unit_tests/check_clamd.c --- clamav-1.4.3+dfsg/unit_tests/check_clamd.c 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/check_clamd.c 2026-08-06 21:12:04.000000000 +0000 @@ -62,6 +62,14 @@ // common #include "fdpassing.h" +#include "output.h" + +// clamd +#include "clamd/thrmgr.h" + +/* Globals used by the thread manager's job-group shutdown checks. */ +pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; +int progexit = 0; static int conn_tcp(int port) { @@ -132,6 +140,45 @@ #endif } +static void close_socket(int socket_fd) +{ +#ifndef _WIN32 + close(socket_fd); +#else + closesocket(socket_fd); +#endif +} + +static void create_tcp_socket_pair(int sockets[2]) +{ + struct sockaddr_in address; + socklen_t address_len = sizeof(address); + int listener; + + listener = socket(AF_INET, SOCK_STREAM, 0); + ck_assert_msg(listener != -1, "Unable to create listener socket: %s\n", strerror(errno)); + + memset(&address, 0, sizeof(address)); + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + address.sin_port = 0; + + ck_assert_msg(bind(listener, (struct sockaddr *)&address, sizeof(address)) != -1, + "Unable to bind listener socket: %s\n", strerror(errno)); + ck_assert_msg(getsockname(listener, (struct sockaddr *)&address, &address_len) != -1, + "Unable to get listener socket address: %s\n", strerror(errno)); + ck_assert_msg(listen(listener, 1) != -1, "Unable to listen on socket: %s\n", strerror(errno)); + + sockets[0] = socket(AF_INET, SOCK_STREAM, 0); + ck_assert_msg(sockets[0] != -1, "Unable to create client socket: %s\n", strerror(errno)); + ck_assert_msg(connect(sockets[0], (struct sockaddr *)&address, address_len) != -1, + "Unable to connect client socket: %s\n", strerror(errno)); + + sockets[1] = accept(listener, NULL, NULL); + ck_assert_msg(sockets[1] != -1, "Unable to accept socket connection: %s\n", strerror(errno)); + close_socket(listener); +} + #ifndef REPO_VERSION #define REPO_VERSION VERSION #endif @@ -573,7 +620,7 @@ const char end[] = "zEND"; const char ping[] = "zPING"; - int dummyfd, i, killed = 0; + int dummyfd, i; conn_setup(); dummyfd = open(SCANFILE, O_RDONLY); ck_assert_msg(dummyfd != -1, "failed to open %s: %s\n", SCANFILE, strerror(errno)); @@ -581,14 +628,11 @@ ck_assert_msg(send(sockd, idsession, sizeof(idsession), 0) == sizeof(idsession), "send IDSESSION failed\n"); for (i = 0; i < 1024; i++) { if (sendmsg_fd(sockd, fildes, sizeof(fildes), dummyfd, 1) == -1) { - killed = 1; break; } } close(dummyfd); - if (send(sockd, end, sizeof(end), 0) == -1) { - killed = 1; - } + (void)send(sockd, end, sizeof(end), 0); conn_teardown(); conn_setup(); @@ -854,10 +898,530 @@ } END_TEST +struct stats_filename_test_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + int stage; +}; + +static void stats_filename_test_handler(void *data) +{ + struct stats_filename_test_state *state = data; + char filename[64] = "task-filename-before-stack-reuse"; + + thrmgr_setactivetask(filename, "TEST"); + + pthread_mutex_lock(&state->mutex); + state->stage = 1; + pthread_cond_broadcast(&state->cond); + while (state->stage < 2) + pthread_cond_wait(&state->cond, &state->mutex); + + strcpy(filename, "task-filename-after-stack-reuse"); + state->stage = 3; + pthread_cond_broadcast(&state->cond); + while (state->stage < 4) + pthread_cond_wait(&state->cond, &state->mutex); + pthread_mutex_unlock(&state->mutex); + + thrmgr_setactivetask(NULL, NULL); + + pthread_mutex_lock(&state->mutex); + state->stage = 5; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); +} + +START_TEST(test_stats_owns_task_filename) +{ + struct stats_filename_test_state state; + threadpool_t *threadpool; + char *stats; + size_t stats_len; + int sockets[2]; + + memset(&state, 0, sizeof(state)); + ck_assert_int_eq(pthread_mutex_init(&state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&state.cond, NULL), 0); + + threadpool = thrmgr_new(1, 60, 1, stats_filename_test_handler); + ck_assert_ptr_nonnull(threadpool); + ck_assert_int_ne(thrmgr_dispatch(threadpool, &state), 0); + + pthread_mutex_lock(&state.mutex); + while (state.stage < 1) + pthread_cond_wait(&state.cond, &state.mutex); + state.stage = 2; + pthread_cond_broadcast(&state.cond); + while (state.stage < 3) + pthread_cond_wait(&state.cond, &state.mutex); + pthread_mutex_unlock(&state.mutex); + + create_tcp_socket_pair(sockets); + ck_assert_int_eq(thrmgr_printstats(sockets[1], '\n'), 0); + close_socket(sockets[1]); + stats = recvfull(sockets[0], &stats_len); + close_socket(sockets[0]); + + ck_assert_msg(strstr(stats, "task-filename-before-stack-reuse") != NULL, + "STATS did not retain its owned task filename:\n%s", stats); + ck_assert_msg(strstr(stats, "task-filename-after-stack-reuse") == NULL, + "STATS read the task filename from reused caller storage:\n%s", stats); + free(stats); + + pthread_mutex_lock(&state.mutex); + state.stage = 4; + pthread_cond_broadcast(&state.cond); + while (state.stage < 5) + pthread_cond_wait(&state.cond, &state.mutex); + pthread_mutex_unlock(&state.mutex); + + thrmgr_destroy(threadpool); + pthread_cond_destroy(&state.cond); + pthread_mutex_destroy(&state.mutex); +} +END_TEST + +struct stats_slow_client_test_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + const char *filename; + int stage; +}; + +struct stats_print_thread_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + int socket_fd; + int result; + int started; + int done; +}; + +struct stats_pool_create_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + threadpool_t *threadpool; + int started; + int done; +}; + +static void stats_slow_client_test_handler(void *data) +{ + struct stats_slow_client_test_state *state = data; + + thrmgr_setactivetask(state->filename, "TEST"); + + pthread_mutex_lock(&state->mutex); + state->stage = 1; + pthread_cond_broadcast(&state->cond); + while (state->stage < 2) + pthread_cond_wait(&state->cond, &state->mutex); + pthread_mutex_unlock(&state->mutex); + + thrmgr_setactivetask(NULL, NULL); + + pthread_mutex_lock(&state->mutex); + state->stage = 3; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); +} + +static void stats_noop_handler(void *data) +{ + UNUSEDPARAM(data); +} + +static void *stats_print_thread(void *data) +{ + struct stats_print_thread_state *state = data; + + pthread_mutex_lock(&state->mutex); + state->started = 1; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); + + state->result = thrmgr_printstats(state->socket_fd, '\n'); + close_socket(state->socket_fd); + + pthread_mutex_lock(&state->mutex); + state->done = 1; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); + return NULL; +} + +static void *stats_pool_create_thread(void *data) +{ + struct stats_pool_create_state *state = data; + + pthread_mutex_lock(&state->mutex); + state->started = 1; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); + + state->threadpool = thrmgr_new(1, 60, 1, stats_noop_handler); + + pthread_mutex_lock(&state->mutex); + state->done = 1; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); + return NULL; +} + +START_TEST(test_stats_write_does_not_hold_pool_lock) +{ + struct stats_slow_client_test_state scan_state; + struct stats_print_thread_state print_state; + struct stats_pool_create_state pool_state; + threadpool_t *threadpool; + pthread_t print_thread; + pthread_t pool_thread; + struct timeval now; + struct timespec deadline; + char first_byte; + char *filename; + char *stats; + char *stats_tail; + size_t filename_size = (1024 * 1024) + 123; + size_t stats_len; + size_t stats_tail_len; + short int saved_send_timeout; + int send_buffer_size = 4096; + int socket_flags; + int sockets[2]; + int print_completed_before_drain; + int pool_created_before_drain; + int stats_contains_filename; + int stats_has_end_marker; + int recv_result; + + filename = malloc(filename_size + 1); + ck_assert_ptr_nonnull(filename); + memset(filename, 'A', filename_size); + filename[filename_size] = '\0'; + + memset(&scan_state, 0, sizeof(scan_state)); + scan_state.filename = filename; + ck_assert_int_eq(pthread_mutex_init(&scan_state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&scan_state.cond, NULL), 0); + + threadpool = thrmgr_new(1, 60, 1, stats_slow_client_test_handler); + ck_assert_ptr_nonnull(threadpool); + ck_assert_int_ne(thrmgr_dispatch(threadpool, &scan_state), 0); + + pthread_mutex_lock(&scan_state.mutex); + while (scan_state.stage < 1) + pthread_cond_wait(&scan_state.cond, &scan_state.mutex); + pthread_mutex_unlock(&scan_state.mutex); + + create_tcp_socket_pair(sockets); + ck_assert_int_eq(setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, + (const char *)&send_buffer_size, sizeof(send_buffer_size)), + 0); + + /* Match clamd's accepted client sockets and force mdprintf() to retry + * after a partial, nonblocking send. */ + socket_flags = fcntl(sockets[1], F_GETFL, 0); + ck_assert_int_ne(socket_flags, -1); + ck_assert_int_ne(fcntl(sockets[1], F_SETFL, socket_flags | O_NONBLOCK), -1); + + memset(&print_state, 0, sizeof(print_state)); + print_state.socket_fd = sockets[1]; + ck_assert_int_eq(pthread_mutex_init(&print_state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&print_state.cond, NULL), 0); + + /* Keep the writer waiting longer than the pool-creation deadline so a + * send timeout cannot make the lock test pass. */ + saved_send_timeout = mprintf_send_timeout; + mprintf_send_timeout = 900; + ck_assert_int_eq(pthread_create(&print_thread, NULL, stats_print_thread, &print_state), 0); + + recv_result = recv(sockets[0], &first_byte, 1, 0); + ck_assert_int_eq(recv_result, 1); + + pthread_mutex_lock(&print_state.mutex); + print_completed_before_drain = print_state.done; + pthread_mutex_unlock(&print_state.mutex); + + memset(&pool_state, 0, sizeof(pool_state)); + ck_assert_int_eq(pthread_mutex_init(&pool_state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&pool_state.cond, NULL), 0); + ck_assert_int_eq(pthread_create(&pool_thread, NULL, stats_pool_create_thread, &pool_state), 0); + + pthread_mutex_lock(&pool_state.mutex); + while (!pool_state.started) + pthread_cond_wait(&pool_state.cond, &pool_state.mutex); + pthread_mutex_unlock(&pool_state.mutex); + + gettimeofday(&now, NULL); + deadline.tv_sec = now.tv_sec; + deadline.tv_nsec = now.tv_usec * 1000 + 500000000; + if (deadline.tv_nsec >= 1000000000) { + deadline.tv_sec++; + deadline.tv_nsec -= 1000000000; + } + + pthread_mutex_lock(&pool_state.mutex); + while (!pool_state.done) { + if (ETIMEDOUT == pthread_cond_timedwait(&pool_state.cond, &pool_state.mutex, &deadline)) + break; + } + pool_created_before_drain = pool_state.done; + pthread_mutex_unlock(&pool_state.mutex); + + stats_tail = recvfull(sockets[0], &stats_tail_len); + close_socket(sockets[0]); + + ck_assert_int_eq(pthread_join(print_thread, NULL), 0); + ck_assert_int_eq(pthread_join(pool_thread, NULL), 0); + mprintf_send_timeout = saved_send_timeout; + ck_assert_int_eq(print_state.result, 0); + ck_assert_ptr_nonnull(pool_state.threadpool); + + stats_len = stats_tail_len + 1; + stats = malloc(stats_len + 1); + ck_assert_ptr_nonnull(stats); + stats[0] = first_byte; + memcpy(stats + 1, stats_tail, stats_tail_len); + stats[stats_len] = '\0'; + free(stats_tail); + + stats_contains_filename = strstr(stats, filename) != NULL; + stats_has_end_marker = stats_len >= 4 && memcmp(stats + stats_len - 4, "END\n", 4) == 0; + free(stats); + + pthread_cond_destroy(&print_state.cond); + pthread_mutex_destroy(&print_state.mutex); + + thrmgr_destroy(pool_state.threadpool); + pthread_cond_destroy(&pool_state.cond); + pthread_mutex_destroy(&pool_state.mutex); + + pthread_mutex_lock(&scan_state.mutex); + scan_state.stage = 2; + pthread_cond_broadcast(&scan_state.cond); + while (scan_state.stage < 3) + pthread_cond_wait(&scan_state.cond, &scan_state.mutex); + pthread_mutex_unlock(&scan_state.mutex); + + thrmgr_destroy(threadpool); + pthread_cond_destroy(&scan_state.cond); + pthread_mutex_destroy(&scan_state.mutex); + free(filename); + + ck_assert_msg(!print_completed_before_drain, + "STATS did not block on the intentionally non-reading client"); + ck_assert_msg(pool_created_before_drain, + "STATS held the global pool lock while writing to a slow client"); + ck_assert_msg(stats_contains_filename, + "STATS response did not include the complete active task filename"); + ck_assert_msg(stats_has_end_marker, + "STATS response was truncated or contained data after its END marker"); +} +END_TEST + +struct stats_worker_retirement_test_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned handled; +}; + +static void stats_worker_retirement_test_handler(void *data) +{ + struct stats_worker_retirement_test_state *state = data; + + pthread_mutex_lock(&state->mutex); + state->handled++; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); +} + +static void stats_test_sleep_millisecond(void) +{ +#ifdef _WIN32 + Sleep(1); +#else + struct timespec delay = { .tv_sec = 0, .tv_nsec = 1000000L }; + nanosleep(&delay, NULL); +#endif +} + +START_TEST(test_stats_does_not_strand_work_during_worker_retirement) +{ + struct stats_worker_retirement_test_state state; + struct stats_print_thread_state print_state; + struct task_desc *desc; + threadpool_t *threadpool; + pthread_t print_thread; + char *stats; + size_t stats_len; + unsigned i; + int sockets[2]; + int worker_is_retiring = 0; + int second_job_handled = 0; + + memset(&state, 0, sizeof(state)); + ck_assert_int_eq(pthread_mutex_init(&state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&state.cond, NULL), 0); + + threadpool = thrmgr_new(1, 1, 2, stats_worker_retirement_test_handler); + ck_assert_ptr_nonnull(threadpool); + ck_assert_int_ne(thrmgr_dispatch(threadpool, &state), 0); + + pthread_mutex_lock(&state.mutex); + while (state.handled < 1) + pthread_cond_wait(&state.cond, &state.mutex); + pthread_mutex_unlock(&state.mutex); + + /* Wait until the worker has returned to its timed idle wait, then hold + * its task descriptor so STATS retains pools_lock while snapshotting it. */ + pthread_mutex_lock(&threadpool->pool_mutex); + while (threadpool->thr_idle < 1) + pthread_cond_wait(&threadpool->idle_cond, &threadpool->pool_mutex); + desc = threadpool->tasks; + ck_assert_ptr_nonnull(desc); + ck_assert_int_eq(pthread_mutex_lock(&desc->mutex), 0); + pthread_mutex_unlock(&threadpool->pool_mutex); + + create_tcp_socket_pair(sockets); + memset(&print_state, 0, sizeof(print_state)); + print_state.socket_fd = sockets[1]; + ck_assert_int_eq(pthread_mutex_init(&print_state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&print_state.cond, NULL), 0); + ck_assert_int_eq(pthread_create(&print_thread, NULL, stats_print_thread, &print_state), 0); + + pthread_mutex_lock(&print_state.mutex); + while (!print_state.started) + pthread_cond_wait(&print_state.cond, &print_state.mutex); + pthread_mutex_unlock(&print_state.mutex); + + /* Once idle is zero but the sole worker is still alive, its timeout has + * fired and it is waiting for the global STATS lock before retiring. */ + for (i = 0; i < 5000; i++) { + pthread_mutex_lock(&threadpool->pool_mutex); + worker_is_retiring = threadpool->thr_alive == 1 && threadpool->thr_idle == 0; + pthread_mutex_unlock(&threadpool->pool_mutex); + if (worker_is_retiring) + break; + stats_test_sleep_millisecond(); + } + ck_assert_msg(worker_is_retiring, + "Worker did not reach the retirement checkpoint while STATS held the pool list lock"); + + /* The dispatcher sees the retiring worker as alive and therefore does + * not create a replacement. The worker must recheck the queue before it + * commits to exit. */ + ck_assert_int_ne(thrmgr_dispatch(threadpool, &state), 0); + ck_assert_int_eq(pthread_mutex_unlock(&desc->mutex), 0); + + for (i = 0; i < 5000; i++) { + pthread_mutex_lock(&state.mutex); + second_job_handled = state.handled == 2; + pthread_mutex_unlock(&state.mutex); + if (second_job_handled) + break; + stats_test_sleep_millisecond(); + } + + stats = recvfull(sockets[0], &stats_len); + close_socket(sockets[0]); + ck_assert_int_eq(pthread_join(print_thread, NULL), 0); + + ck_assert_msg(second_job_handled, + "Work dispatched during worker retirement remained queued without a worker"); + ck_assert_int_eq(print_state.result, 0); + ck_assert_ptr_nonnull(stats); + ck_assert_msg(stats_len >= 4 && memcmp(stats + stats_len - 4, "END\n", 4) == 0, + "STATS response was truncated during worker retirement:\n%s", stats); + free(stats); + + thrmgr_destroy(threadpool); + pthread_cond_destroy(&print_state.cond); + pthread_mutex_destroy(&print_state.mutex); + pthread_cond_destroy(&state.cond); + pthread_mutex_destroy(&state.mutex); +} +END_TEST + +struct stats_queue_churn_test_state { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned handled; +}; + +static void stats_queue_churn_test_handler(void *data) +{ + struct stats_queue_churn_test_state *state = data; + + /* Keep the queue active long enough for repeated snapshots to overlap + * with work-item removal. */ +#ifdef _WIN32 + Sleep(1); +#else + struct timespec delay = { .tv_sec = 0, .tv_nsec = 1000000L }; + nanosleep(&delay, NULL); +#endif + + pthread_mutex_lock(&state->mutex); + state->handled++; + pthread_cond_broadcast(&state->cond); + pthread_mutex_unlock(&state->mutex); +} + +START_TEST(test_stats_while_queue_is_changing) +{ + enum { + STATS_QUEUE_CHURN_JOBS = 256, + STATS_QUEUE_CHURN_SNAPSHOTS = 64 + }; + struct stats_queue_churn_test_state state; + threadpool_t *threadpool; + unsigned i; + + memset(&state, 0, sizeof(state)); + ck_assert_int_eq(pthread_mutex_init(&state.mutex, NULL), 0); + ck_assert_int_eq(pthread_cond_init(&state.cond, NULL), 0); + + threadpool = thrmgr_new(1, 60, STATS_QUEUE_CHURN_JOBS * 2, + stats_queue_churn_test_handler); + ck_assert_ptr_nonnull(threadpool); + + for (i = 0; i < STATS_QUEUE_CHURN_JOBS; i++) + ck_assert_int_ne(thrmgr_dispatch(threadpool, &state), 0); + + for (i = 0; i < STATS_QUEUE_CHURN_SNAPSHOTS; i++) { + char *stats; + size_t stats_len; + int sockets[2]; + + create_tcp_socket_pair(sockets); + ck_assert_int_eq(thrmgr_printstats(sockets[1], '\n'), 0); + close_socket(sockets[1]); + stats = recvfull(sockets[0], &stats_len); + close_socket(sockets[0]); + + ck_assert_ptr_nonnull(stats); + ck_assert_msg(stats_len >= 4 && memcmp(stats + stats_len - 4, "END\n", 4) == 0, + "STATS response was truncated while the work queue changed:\n%s", stats); + free(stats); + } + + pthread_mutex_lock(&state.mutex); + while (state.handled < STATS_QUEUE_CHURN_JOBS) + pthread_cond_wait(&state.cond, &state.mutex); + pthread_mutex_unlock(&state.mutex); + + thrmgr_destroy(threadpool); + pthread_cond_destroy(&state.cond); + pthread_mutex_destroy(&state.mutex); +} +END_TEST + static Suite *test_clamd_suite(void) { Suite *s = suite_create("clamd"); - TCase *tc_commands, *tc_stress; + TCase *tc_commands, *tc_stress, *tc_thrmgr; tc_commands = tcase_create("clamd commands"); suite_add_tcase(s, tc_commands); tcase_add_unchecked_fixture(tc_commands, commands_setup, commands_teardown); @@ -887,6 +1451,13 @@ tcase_add_test(tc_stress, test_connections); // Disabled on Windows because test uses fork() instead of threads, and needs to be rewritten. #endif #endif + tc_thrmgr = tcase_create("thread manager"); + suite_add_tcase(s, tc_thrmgr); + tcase_add_test(tc_thrmgr, test_stats_owns_task_filename); + tcase_add_test(tc_thrmgr, test_stats_write_does_not_hold_pool_lock); + tcase_add_test(tc_thrmgr, test_stats_does_not_strand_work_during_worker_retirement); + tcase_add_test(tc_thrmgr, test_stats_while_queue_is_changing); + return s; } diff -Nru clamav-1.4.3+dfsg/unit_tests/clamd_test.py clamav-1.4.6+dfsg/unit_tests/clamd_test.py --- clamav-1.4.3+dfsg/unit_tests/clamd_test.py 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/clamd_test.py 2026-08-06 21:12:04.000000000 +0000 @@ -7,12 +7,14 @@ import os from pathlib import Path import platform +import re import socket import subprocess import shutil import sys import time import unittest +import hashlib from zipfile import ZIP_DEFLATED, ZipFile import testcase @@ -254,6 +256,25 @@ if expected_err != [] or unexpected_err != []: self.verify_output(output.err, expected=expected_err, unexpected=unexpected_err) + @staticmethod + def _create_file_symlink(link_path: Path, target_path: Path): + try: + os.symlink(target_path, link_path) + return + except OSError: + if operating_system != 'windows': + raise + + completed = subprocess.run( + ['cmd', '/c', 'mklink', str(link_path), str(target_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + if completed.returncode != 0: + raise OSError('Failed to create file symlink: {}'.format(completed.stdout.strip())) + def test_clamd_00_version(self): ''' verify that clamd -v returns the version @@ -404,6 +425,194 @@ time.sleep(5) + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_clamd_05a_quarantine_copy_uses_real_source_path(self): + self.step_name('Testing clamdscan --copy keeps the display path while quarantining the real source path') + + payload = b'CLAM-2976 clamd symlink quarantine payload\n' + payload_path = TC.path_tmp / 'clamd-link-target' + payload_path.write_bytes(payload) + + link_path = TC.path_tmp / 'clamd-link-source' + try: + self._create_file_symlink(link_path, payload_path) + except OSError: + self.skipTest('File symlink creation is not permitted in this test environment.') + + quarantine_dir = TC.path_tmp / 'clamd-link-quarantine' + quarantine_dir.mkdir() + + db_dir = TC.path_tmp / 'clamd-link-db' + db_dir.mkdir() + (db_dir / 'trigger.hdb').write_text( + '{}:{}:{}\n'.format( + hashlib.sha256(payload).hexdigest(), + len(payload), + 'CLAM-2976-CLAMD-SOURCE-LINK', + ) + ) + + config = ''' + Foreground yes + PidFile {pid} + DatabaseDirectory {dbdir} + LogFileMaxSize 0 + LogTime yes + LogClean yes + LogVerbose yes + ExitOnOOM yes + DetectPUA yes + ScanPDF yes + CommandReadTimeout 1 + MaxQueue 800 + MaxConnectionQueueLength 1024 + FollowFileSymlinks yes + '''.format(pid=TC.clamd_pid, dbdir=db_dir) + if operating_system == 'windows': + config += ''' + TCPSocket {socket} + TCPAddr localhost + '''.format(socket=TC.clamd_port_num) + else: + config += ''' + LocalSocket {localsocket} + '''.format(localsocket=TC.clamd_socket) + + clamd_config = TC.path_tmp / 'clamd-follow-links.conf' + clamd_config.write_text(config) + + self.start_clamd(clamd_config=clamd_config) + + poll = self.proc.poll() + assert poll == None + + output = self.execute_command('{clamdscan} --ping 5 --wait --copy={quarantine_dir} -c {clamd_config} {link_path}'.format( + clamdscan=TC.clamdscan, + quarantine_dir=quarantine_dir, + clamd_config=clamd_config, + link_path=link_path, + )) + + assert output.ec == 1 + self.verify_output( + output.out, + expected=[ + re.escape('{}:'.format(link_path)), + 'FOUND', + ], + unexpected=[ + re.escape('{}:'.format(payload_path)), + ], + ) + self.verify_output( + output.err, + unexpected=[ + re.escape("Can't copy file '{}'".format(link_path)), + ], + ) + self.assertTrue(payload_path.exists(), 'Expected the symlink target to remain in place after the quarantine copy.') + self.assertTrue(link_path.exists(), 'Expected the symlink source to remain in place after the quarantine copy.') + quarantined_path = quarantine_dir / payload_path.name + self.assertFalse((quarantine_dir / link_path.name).exists(), 'Expected clamdscan quarantine copy to avoid naming the quarantine file after the symlink.') + self.assertTrue(quarantined_path.exists(), 'Expected clamdscan quarantine copy to use the resolved source basename.') + self.assertEqual(payload_path.read_bytes(), quarantined_path.read_bytes(), 'Expected the quarantined file to contain the target file bytes.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_clamd_05b_quarantine_copy_modes_use_real_source_path(self): + self.step_name('Testing clamdscan --copy source binding across scan modes') + + parent_dir = TC.path_tmp / 'clamd-mode-link' + parent_dir.mkdir() + payload = b'CLAM-2959 clamdscan quarantine mode payload\n' + payload_path = parent_dir / 'payload.bin' + payload_path.write_bytes(payload) + + link_path = parent_dir / 'payload-link' + try: + self._create_file_symlink(link_path, payload_path) + except OSError: + self.skipTest('File symlink creation is not permitted in this test environment.') + + db_dir = TC.path_tmp / 'clamd-mode-db' + db_dir.mkdir() + (db_dir / 'trigger.hdb').write_text( + '{}:{}:{}\n'.format( + hashlib.sha256(payload).hexdigest(), + len(payload), + 'CLAM-2959-CLAMDSCAN-MODE-LINK', + ) + ) + + config = ''' + Foreground yes + PidFile {pid} + DatabaseDirectory {dbdir} + LogFileMaxSize 0 + LogTime yes + LogClean yes + LogVerbose yes + ExitOnOOM yes + DetectPUA yes + ScanPDF yes + CommandReadTimeout 1 + MaxQueue 800 + MaxConnectionQueueLength 1024 + FollowFileSymlinks yes + '''.format(pid=TC.clamd_pid, dbdir=db_dir) + if operating_system == 'windows': + config += ''' + TCPSocket {socket} + TCPAddr localhost + '''.format(socket=TC.clamd_port_num) + else: + config += ''' + LocalSocket {localsocket} + '''.format(localsocket=TC.clamd_socket) + + clamd_config = TC.path_tmp / 'clamd-mode-link.conf' + clamd_config.write_text(config) + + self.start_clamd(clamd_config=clamd_config) + + poll = self.proc.poll() + assert poll == None + + mode_args = [ + ('default', ''), + ('stream', '--stream'), + ('multiscan', '--multiscan'), + ] + if TC.has_fdpass_support: + mode_args.append(('fdpass', '--fdpass')) + + for mode_name, arg_variation in mode_args: + quarantine_dir = TC.path_tmp / 'clamd-mode-quarantine-{}'.format(mode_name) + quarantine_dir.mkdir() + + output = self.execute_command('{clamdscan} --ping 5 --wait {arg_variation} --copy={quarantine_dir} -c {clamd_config} {link_path}'.format( + clamdscan=TC.clamdscan, + arg_variation=arg_variation, + quarantine_dir=quarantine_dir, + clamd_config=clamd_config, + link_path=link_path, + )) + + assert output.ec == 1 + self.verify_output( + output.out, + expected=[ + re.escape('{}:'.format(link_path)), + 'FOUND', + ], + unexpected=[ + re.escape('{}:'.format(payload_path)), + ], + ) + quarantined_path = quarantine_dir / payload_path.name + self.assertFalse((quarantine_dir / link_path.name).exists(), 'Expected {} mode to avoid naming the quarantine file after the symlink.'.format(mode_name)) + self.assertTrue(quarantined_path.exists(), 'Expected {} mode to quarantine using the resolved source basename.'.format(mode_name)) + self.assertEqual(payload_path.read_bytes(), quarantined_path.read_bytes(), 'Expected {} mode to copy the target file bytes.'.format(mode_name)) + def test_clamd_06_HeuristicScanPrecedence_off(self): ''' Verify that HeuristicScanPrecedence off works as expected (default) diff -Nru clamav-1.4.3+dfsg/unit_tests/clamscan/alz_test.py clamav-1.4.6+dfsg/unit_tests/clamscan/alz_test.py --- clamav-1.4.3+dfsg/unit_tests/clamscan/alz_test.py 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/clamscan/alz_test.py 2026-08-06 21:12:04.000000000 +0000 @@ -4,12 +4,58 @@ Run clamscan tests. """ +import hashlib import sys +import zlib sys.path.append('../unit_tests') import testcase +ALZ_FILE_HEADER = 0x015A4C41 +ALZ_LOCAL_FILE_HEADER = 0x015A4C42 +ALZ_END_OF_CENTRAL_DIRECTORY_HEADER = 0x025A4C43 +ALZ_ATTR_DIRECTORY = 0x10 +ALZ_ATTR_FILE = 0x20 +ALZ_COMP_NOCOMP = 0 +ALZ_COMP_BZIP2 = 1 +ALZ_COMP_DEFLATE = 2 +ALZ_ENCR_HEADER_LEN = 12 + + +def append_alz_file( + alz, + name, + compression_method, + uncompressed_size, + data, + file_attribute=ALZ_ATTR_FILE, + file_descriptor=0x10, +): + name = name.encode('utf-8') + + alz.extend(ALZ_LOCAL_FILE_HEADER.to_bytes(4, 'little')) + alz.extend(len(name).to_bytes(2, 'little')) + alz.append(file_attribute) + alz.extend((0).to_bytes(4, 'little')) # file time/date + alz.append(file_descriptor) + alz.append(0) # unknown + alz.append(compression_method) + alz.append(0) # unknown + alz.extend((0).to_bytes(4, 'little')) # crc + alz.append(len(data)) + alz.append(uncompressed_size) + alz.extend(name) + if file_descriptor & 0x01: + alz.extend(b'\x00' * ALZ_ENCR_HEADER_LEN) + alz.extend(data) + + +def raw_deflate(data): + compressor = zlib.compressobj(wbits=-15) + return compressor.compress(data) + compressor.flush() + + class TC(testcase.TestCase): @classmethod def setUpClass(cls): @@ -116,6 +162,284 @@ ] self.verify_output(output.out, expected=expected_results) + def test_extraction_error_does_not_abort_archive_scan(self): + self.step_name('Test alz scan continues after a malformed member') + + payload = b'alz-later-member' + testfile = TC.path_tmp / 'bad-then-good.alz' + path_db = TC.path_tmp / 'bad-then-good.hdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file(alz, 'bad.bz2', ALZ_COMP_BZIP2, 1, b'\x00') + append_alz_file(alz, 'good.txt', ALZ_COMP_NOCOMP, len(payload), payload) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + + testfile.write_bytes(alz) + path_db.write_text( + '{}:{}:ALZ_LATER_FILE\n'.format(hashlib.sha1(payload).hexdigest(), len(payload)) + ) + + command = '{valgrind} {valgrind_args} {clamscan} -d {path_db} {testfile}'.format( + valgrind=TC.valgrind, valgrind_args=TC.valgrind_args, clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_LATER_FILE.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) + + def test_later_parse_error_does_not_skip_earlier_member_scan(self): + self.step_name('Test alz scan checks earlier members before later parse errors') + + payload = b'alz-earlier-member' + testfile = TC.path_tmp / 'good-then-bad-header.alz' + path_db = TC.path_tmp / 'good-then-bad-header.hdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file(alz, 'good.txt', ALZ_COMP_NOCOMP, len(payload), payload) + alz.extend(ALZ_LOCAL_FILE_HEADER.to_bytes(4, 'little')) + + testfile.write_bytes(alz) + path_db.write_text( + '{}:{}:ALZ_EARLIER_FILE\n'.format(hashlib.sha1(payload).hexdigest(), len(payload)) + ) + + command = '{valgrind} {valgrind_args} {clamscan} -d {path_db} {testfile}'.format( + valgrind=TC.valgrind, valgrind_args=TC.valgrind_args, clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_EARLIER_FILE.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) + + def test_deflate_limit_uses_decompressed_size(self): + self.step_name('Test alz deflate scan limits use decompressed output size') + + truncated_payload = b'A' * 64 + payload = b'A' * 4096 + compressed = raw_deflate(payload) + assert len(compressed) <= 255 + + testfile = TC.path_tmp / 'deflate-limit.alz' + path_db = TC.path_tmp / 'deflate-limit.hdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file(alz, 'x', ALZ_COMP_DEFLATE, 1, compressed) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + assert len(alz) <= 64 + + testfile.write_bytes(alz) + path_db.write_text( + '{}:{}:ALZ_DEFLATE_LIMIT\n'.format( + hashlib.sha1(truncated_payload).hexdigest(), + len(truncated_payload), + ) + ) + + command = ( + '{valgrind} {valgrind_args} {clamscan} --max-filesize=64 ' + '--max-scansize=4096 -d {path_db} {testfile}' + ).format( + valgrind=TC.valgrind, + valgrind_args=TC.valgrind_args, + clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_DEFLATE_LIMIT.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) + + def test_inflated_header_size_does_not_skip_extraction(self): + self.step_name('Test alz scan ignores inflated header size for extraction gating') + + payload = b'alz-small-hit' + testfile = TC.path_tmp / 'inflated-header-size.alz' + path_db = TC.path_tmp / 'inflated-header-size.hdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file(alz, 'x', ALZ_COMP_NOCOMP, 80, payload) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + + testfile.write_bytes(alz) + path_db.write_text( + '{}:{}:ALZ_INFLATED_HEADER_SIZE\n'.format( + hashlib.sha1(payload).hexdigest(), + len(payload), + ) + ) + + command = ( + '{valgrind} {valgrind_args} {clamscan} --max-filesize=64 ' + '--max-scansize=1024 -d {path_db} {testfile}' + ).format( + valgrind=TC.valgrind, + valgrind_args=TC.valgrind_args, + clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_INFLATED_HEADER_SIZE.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) + + def test_total_limit_does_not_report_max_file_size(self): + self.step_name('Test alz archive total limit is not reported as max file size') + + payload = b'A' * 60 + testfile = TC.path_tmp / 'total-limit.alz' + path_db = TC.path_tmp / 'total-limit.hdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file(alz, 'a', ALZ_COMP_NOCOMP, len(payload), payload) + append_alz_file(alz, 'b', ALZ_COMP_NOCOMP, len(payload), payload) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + assert len(alz) <= 200 + max_scansize = len(alz) + 100 + assert max_scansize < len(alz) + (len(payload) * 2) + + testfile.write_bytes(alz) + path_db.write_text( + '{}:{}:ALZ_UNUSED\n'.format( + hashlib.sha1(b'not-present').hexdigest(), + len(b'not-present'), + ) + ) + + command = ( + '{valgrind} {valgrind_args} {clamscan} --alert-exceeds-max=yes ' + '--max-filesize=200 --max-scansize={max_scansize} -d {path_db} {testfile}' + ).format( + valgrind=TC.valgrind, + valgrind_args=TC.valgrind_args, + clamscan=TC.clamscan, + max_scansize=max_scansize, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + expected_results = [ + 'Heuristics.Limits.Exceeded.MaxScanSize FOUND', + ] + unexpected_results = [ + 'Heuristics.Limits.Exceeded.MaxFileSize FOUND', + ] + self.verify_output(output.out, expected=expected_results, unexpected=unexpected_results) + def test_metadata_filepos_counts_skipped_entries_from_one(self): + self.step_name('Test alz metadata file position counts skipped entries from one') + payload = b'alz-filepos-member' + testfile = TC.path_tmp / 'filepos-skipped.alz' + path_db = TC.path_tmp / 'filepos-skipped.cdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file( + alz, + 'dir/', + ALZ_COMP_NOCOMP, + 0, + b'', + file_attribute=ALZ_ATTR_DIRECTORY, + ) + append_alz_file( + alz, + 'encrypted.bin', + ALZ_COMP_NOCOMP, + 0, + b'', + file_descriptor=0x11, + ) + append_alz_file(alz, 'good.txt', ALZ_COMP_NOCOMP, len(payload), payload) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + + testfile.write_bytes(alz) + path_db.write_text('ALZ_FILEPOS_TEST:CL_TYPE_ALZ:*:good.txt:*:*:0:3:*:*\n') + + command = '{valgrind} {valgrind_args} {clamscan} -d {path_db} {testfile}'.format( + valgrind=TC.valgrind, valgrind_args=TC.valgrind_args, clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_FILEPOS_TEST.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) + + def test_encrypted_metadata_matches_before_extraction_skip(self): + self.step_name('Test alz encrypted entries are matched before extraction skip') + + testfile = TC.path_tmp / 'encrypted-metadata.alz' + path_db = TC.path_tmp / 'encrypted-metadata.cdb' + + alz = bytearray() + alz.extend(ALZ_FILE_HEADER.to_bytes(4, 'little')) + alz.extend((0).to_bytes(4, 'little')) + append_alz_file( + alz, + 'encrypted.bin', + ALZ_COMP_NOCOMP, + 0, + b'', + file_descriptor=0x11, + ) + alz.extend(ALZ_END_OF_CENTRAL_DIRECTORY_HEADER.to_bytes(4, 'little')) + + testfile.write_bytes(alz) + path_db.write_text( + 'ALZ_ENCRYPTED_METADATA_TEST:CL_TYPE_ALZ:*:encrypted.bin:*:*:1:1:*:*\n' + ) + + command = '{valgrind} {valgrind_args} {clamscan} -d {path_db} {testfile}'.format( + valgrind=TC.valgrind, valgrind_args=TC.valgrind_args, clamscan=TC.clamscan, + path_db=path_db, + testfile=testfile, + ) + output = self.execute_command(command) + + assert output.ec == 1 # virus + + expected_results = [ + 'ALZ_ENCRYPTED_METADATA_TEST.UNOFFICIAL FOUND', + ] + self.verify_output(output.out, expected=expected_results) diff -Nru clamav-1.4.3+dfsg/unit_tests/clamscan/quarantine_toctou_test.py clamav-1.4.6+dfsg/unit_tests/clamscan/quarantine_toctou_test.py --- clamav-1.4.3+dfsg/unit_tests/clamscan/quarantine_toctou_test.py 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/clamscan/quarantine_toctou_test.py 2026-08-06 21:12:04.000000000 +0000 @@ -0,0 +1,907 @@ +# Copyright (C) 2026 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + +"""Regression test for quarantine destination TOCTOU handling.""" + +import errno +import hashlib +import os +from pathlib import Path +import platform +import shutil +import subprocess +import sys +import threading +import time +import unittest + +sys.path.append('../unit_tests') +import testcase + + +operating_system = platform.platform().split('-')[0].lower() + + +class TC(testcase.TestCase): + @classmethod + def setUpClass(cls): + super(TC, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TC, cls).tearDownClass() + + def setUp(self): + super(TC, self).setUp() + + def tearDown(self): + super(TC, self).tearDown() + self.verify_valgrind_log() + + @staticmethod + def _write_hdb_signature(sig_path: Path, payload: bytes, signature_name: str): + sig_path.write_text( + '{}:{}:{}\n'.format( + hashlib.sha256(payload).hexdigest(), + len(payload), + signature_name, + ) + ) + + @staticmethod + def _write_padding_hdb(sig_path: Path, count: int): + with sig_path.open('w') as handle: + for i in range(count): + pad = 'padding-entry-{:05d}'.format(i).encode('utf-8') + handle.write( + '{}:{}:Padding-{:05d}\n'.format( + hashlib.sha256(pad).hexdigest(), + len(pad), + i, + ) + ) + + @staticmethod + def _watch_debug_output(stream, milestone_lines, matched_event, collected_lines): + try: + for line in iter(stream.readline, ''): + collected_lines.append(line) + if not matched_event.is_set(): + for milestone in milestone_lines: + if milestone in line: + matched_event.set() + break + finally: + stream.close() + + @staticmethod + def _quarantine_lock_exists(quarantine_dir: Path): + try: + return any(entry.name.startswith('.clamav-quarantine-lock.') for entry in quarantine_dir.iterdir()) + except FileNotFoundError: + return False + except NotADirectoryError: + return False + + @staticmethod + def _can_create_directory_symlink(parent_dir: Path): + target = parent_dir / 'symlink-target' + link = parent_dir / 'symlink-link' + + target.mkdir() + try: + TC._create_directory_redirect(link, target) + except OSError: + return False + else: + TC._remove_directory_redirect(link) + return True + finally: + target.rmdir() + + @staticmethod + def _create_directory_redirect(link_path: Path, target_path: Path): + try: + os.symlink(target_path, link_path, target_is_directory=True) + return + except OSError: + if operating_system != 'windows': + raise + + completed = subprocess.run( + ['cmd', '/c', 'mklink', '/J', str(link_path), str(target_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + if completed.returncode != 0: + raise OSError('Failed to create directory redirect: {}'.format(completed.stdout.strip())) + + @staticmethod + def _remove_directory_redirect(link_path: Path): + if not link_path.exists(): + return + + if operating_system == 'windows' and not link_path.is_symlink(): + subprocess.run( + ['cmd', '/c', 'rmdir', str(link_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + return + + link_path.unlink() + + @staticmethod + def _can_create_file_symlink(parent_dir: Path): + target = parent_dir / 'symlink-file-target' + link = parent_dir / 'symlink-file-link' + + target.write_bytes(b'CLAM-2976 file symlink probe\n') + try: + TC._create_file_redirect(link, target) + except OSError: + return False + else: + link.unlink() + return True + finally: + if target.exists(): + target.unlink() + + @staticmethod + def _create_file_redirect(link_path: Path, target_path: Path): + try: + os.symlink(target_path, link_path) + return + except OSError: + if operating_system != 'windows': + raise + + completed = subprocess.run( + ['cmd', '/c', 'mklink', str(link_path), str(target_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + if completed.returncode != 0: + raise OSError('Failed to create file redirect: {}'.format(completed.stdout.strip())) + + @staticmethod + def _write_xattr(file_path: Path, attr_name: str, attr_value: str): + subprocess.run( + ['xattr', '-w', attr_name, attr_value, str(file_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=True, + ) + + @staticmethod + def _read_xattr(file_path: Path, attr_name: str): + completed = subprocess.run( + ['xattr', '-p', attr_name, str(file_path)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=True, + ) + return completed.stdout.rstrip('\n') + + def _exercise_quarantine_directory_replacement(self, action_mode: str): + assert action_mode in ('copy', 'move') + + db_dir = TC.path_tmp / ('db-{}'.format(action_mode)) + db_dir.mkdir() + + payload = b'CLAM-2959 quarantine TOCTOU payload\n' + scan_dir = TC.path_tmp / ('scanme-{}'.format(action_mode)) + scan_dir.mkdir() + payload_path = scan_dir / 'backdoor' + payload_path.write_bytes(payload) + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2959-TOCTOU') + # Pad the database a bit so we have a more reliable window to replace the + # quarantine directory after argument setup but before the copy/move action. + self._write_padding_hdb(db_dir / 'padding.hdb', 500000) + + parent_dir = TC.path_tmp / ('srv-{}'.format(action_mode)) + parent_dir.mkdir() + if not self._can_create_directory_symlink(parent_dir): + self.skipTest('Directory symlink creation is not permitted in this test environment.') + quarantine_dir = parent_dir / 'quarantine' + quarantine_dir.mkdir() + + redirect_dir = TC.path_tmp / ('redirect-{}'.format(action_mode)) + redirect_dir.mkdir() + + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend( + [ + str(TC.clamscan), + '--debug', + '-d', + str(db_dir), + '--{}={}'.format(action_mode, quarantine_dir), + str(scan_dir), + ] + ) + + milestone_lines = ['{} loaded'.format(db_dir / 'trigger.hdb')] + if operating_system == 'windows': + milestone_lines.append('{} loaded'.format(str(db_dir / 'trigger.hdb')).replace('/', '\\')) + + self.log.info('Starting clamscan command: %s', ' '.join(command)) + proc = subprocess.Popen( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + preexec_fn=os.setsid if operating_system != 'windows' else None, + ) + output_lines = [] + saw_db_load_event = threading.Event() + output_thread = threading.Thread( + target=self._watch_debug_output, + args=(proc.stdout, milestone_lines, saw_db_load_event, output_lines), + daemon=True, + ) + output_thread.start() + + try: + swapped = False + replacement_blocked = False + saw_setup_event = False + deadline = time.time() + 10 + + while time.time() < deadline and proc.poll() is None: + if operating_system == 'windows': + saw_setup_event = saw_db_load_event.is_set() + else: + # POSIX action setup creates this lock in the validated + # destination. Watching the filesystem avoids depending on + # debug stdout timing, which is fragile under Valgrind. + saw_setup_event = self._quarantine_lock_exists(quarantine_dir) + + if not saw_setup_event: + time.sleep(0.01) + continue + + try: + quarantine_dir.rmdir() + self._create_directory_redirect(quarantine_dir, redirect_dir) + swapped = True + self.log.info('Replaced quarantine directory with symlink to %s', redirect_dir) + break + except FileNotFoundError: + pass + except OSError as err: + if err.errno == errno.ENOTEMPTY: + replacement_blocked = True + self.log.info('Quarantine directory replacement was blocked while clamscan was running.') + break + time.sleep(0.01) + + proc.wait(timeout=60) + finally: + if proc.poll() is None: + proc.terminate() + proc.wait(timeout=10) + output_thread.join(timeout=10) + + stdout = ''.join(output_lines) + self.log.info('clamscan stdout:\n%s', stdout) + + return { + 'payload_path': payload_path, + 'quarantine_dir': quarantine_dir, + 'redirect_dir': redirect_dir, + 'saw_setup_event': saw_setup_event, + 'saw_db_load_event': saw_db_load_event, + 'swapped': swapped, + 'replacement_blocked': replacement_blocked, + 'returncode': proc.returncode, + 'stdout': stdout, + } + + def _exercise_source_link_quarantine(self, action_mode: str): + assert action_mode in ('copy', 'move', 'remove') + + parent_dir = TC.path_tmp / ('src-link-{}'.format(action_mode)) + parent_dir.mkdir() + if not self._can_create_file_symlink(parent_dir): + self.skipTest('File symlink creation is not permitted in this test environment.') + + db_dir = TC.path_tmp / ('db-src-link-{}'.format(action_mode)) + db_dir.mkdir() + + payload = b'CLAM-2976 quarantine source link payload\n' + payload_path = parent_dir / 'payload.bin' + payload_path.write_bytes(payload) + + link_path = parent_dir / 'payload-link' + self._create_file_redirect(link_path, payload_path) + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2976-SOURCE-LINK') + + quarantine_dir = None + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend( + [ + str(TC.clamscan), + '--debug', + '--follow-file-symlinks=2', + '-d', + str(db_dir), + ] + ) + + if action_mode == 'remove': + command.append('--remove=yes') + else: + quarantine_dir = TC.path_tmp / ('quarantine-src-link-{}'.format(action_mode)) + quarantine_dir.mkdir() + command.append('--{}={}'.format(action_mode, quarantine_dir)) + + command.append(str(link_path)) + + self.log.info('Starting clamscan command: %s', ' '.join(command)) + completed = subprocess.run( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + self.log.info('clamscan stdout:\n%s', completed.stdout) + + return { + 'payload_path': payload_path, + 'link_path': link_path, + 'quarantine_dir': quarantine_dir, + 'returncode': completed.returncode, + 'stdout': completed.stdout, + } + + def _exercise_source_hardlink_quarantine(self, action_mode: str): + assert action_mode in ('move', 'remove') + + parent_dir = TC.path_tmp / ('src-hardlink-{}'.format(action_mode)) + parent_dir.mkdir() + + db_dir = TC.path_tmp / ('db-src-hardlink-{}'.format(action_mode)) + db_dir.mkdir() + + payload = b'CLAM-2959 quarantine source hard-link payload\n' + other_link_path = parent_dir / 'other-link.bin' + other_link_path.write_bytes(payload) + + submitted_path = parent_dir / 'submitted-link.bin' + try: + os.link(other_link_path, submitted_path) + except OSError as err: + self.skipTest('Hard-link creation is not permitted in this test environment: {}'.format(err)) + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2959-SOURCE-HARDLINK') + + quarantine_dir = None + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend([str(TC.clamscan), '--debug', '-d', str(db_dir)]) + if action_mode == 'remove': + command.append('--remove=yes') + else: + quarantine_dir = TC.path_tmp / 'quarantine-src-hardlink-move' + quarantine_dir.mkdir() + command.append('--move={}'.format(quarantine_dir)) + command.append(str(submitted_path)) + + self.log.info('Starting clamscan command: %s', ' '.join(command)) + completed = subprocess.run( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + self.log.info('clamscan stdout:\n%s', completed.stdout) + + return { + 'payload': payload, + 'submitted_path': submitted_path, + 'other_link_path': other_link_path, + 'quarantine_dir': quarantine_dir, + 'returncode': completed.returncode, + 'stdout': completed.stdout, + } + + def _exercise_source_link_replacement_quarantine(self, action_mode: str, attempt: int): + assert action_mode in ('copy', 'move', 'remove') + + parent_dir = TC.path_tmp / ('src-replace-{}-{}'.format(action_mode, attempt)) + parent_dir.mkdir() + if not self._can_create_file_symlink(parent_dir): + self.skipTest('File symlink creation is not permitted in this test environment.') + + db_dir = TC.path_tmp / ('db-src-replace-{}-{}'.format(action_mode, attempt)) + db_dir.mkdir() + + payload = b'CLAM-2959 quarantine source replacement payload\n' + (b'A' * (32 * 1024 * 1024)) + payload_path = parent_dir / 'payload.bin' + payload_path.write_bytes(payload) + + decoy = b'CLAM-2959 quarantine source replacement decoy\n' + decoy_path = parent_dir / 'decoy.bin' + decoy_path.write_bytes(decoy) + + link_path = parent_dir / 'payload-link' + self._create_file_redirect(link_path, payload_path) + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2959-SOURCE-REPLACEMENT') + + quarantine_dir = None + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend( + [ + str(TC.clamscan), + '--debug', + '--follow-file-symlinks=2', + '-d', + str(db_dir), + ] + ) + + if action_mode == 'remove': + command.append('--remove=yes') + else: + quarantine_dir = TC.path_tmp / ('quarantine-src-replace-{}-{}'.format(action_mode, attempt)) + quarantine_dir.mkdir() + command.append('--{}={}'.format(action_mode, quarantine_dir)) + + command.append(str(link_path)) + + milestone_lines = [ + 'action_source_populate_posix: Resolved action path for fd', + 'cli_get_filepath_from_filedesc: File path for fd', + 'cli_get_filepath_from_handle: File path for handle', + ] + + self.log.info('Starting clamscan command: %s', ' '.join(command)) + proc = subprocess.Popen( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + preexec_fn=os.setsid if operating_system != 'windows' else None, + ) + output_lines = [] + saw_scan_event = threading.Event() + output_thread = threading.Thread( + target=self._watch_debug_output, + args=(proc.stdout, milestone_lines, saw_scan_event, output_lines), + daemon=True, + ) + output_thread.start() + + try: + swapped = False + deadline = time.time() + 10 + + while time.time() < deadline and proc.poll() is None: + if not saw_scan_event.is_set(): + time.sleep(0.01) + continue + + try: + link_path.unlink() + self._create_file_redirect(link_path, decoy_path) + swapped = True + self.log.info('Replaced source symlink with symlink to %s', decoy_path) + break + except FileNotFoundError: + pass + except OSError: + time.sleep(0.01) + + proc.wait(timeout=90) + finally: + if proc.poll() is None: + proc.terminate() + proc.wait(timeout=10) + output_thread.join(timeout=10) + + stdout = ''.join(output_lines) + self.log.info('clamscan stdout:\n%s', stdout) + + return { + 'payload': payload, + 'decoy': decoy, + 'payload_path': payload_path, + 'decoy_path': decoy_path, + 'link_path': link_path, + 'quarantine_dir': quarantine_dir, + 'swapped': swapped, + 'returncode': proc.returncode, + 'stdout': stdout, + } + + def _exercise_source_link_replacement_until_infected(self, action_mode: str): + result = None + for attempt in range(6): + result = self._exercise_source_link_replacement_quarantine(action_mode, attempt) + if result['swapped'] and result['returncode'] == 1: + return result + + self.fail( + 'Failed to hit the source replacement race window for clamscan --{}; last return code was {}.'.format( + action_mode, + None if result is None else result['returncode'], + ) + ) + + def _exercise_search_only_quarantine_directory(self, action_mode: str): + assert action_mode in ('copy', 'move') + + db_dir = TC.path_tmp / ('db-search-only-{}'.format(action_mode)) + db_dir.mkdir() + + payload = 'CLAM-2959 search-only quarantine payload {}\n'.format(action_mode).encode('utf-8') + scan_dir = TC.path_tmp / ('scanme-search-only-{}'.format(action_mode)) + scan_dir.mkdir() + payload_path = scan_dir / 'backdoor' + payload_path.write_bytes(payload) + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2959-SEARCH-ONLY-{}'.format(action_mode.upper())) + + quarantine_dir = TC.path_tmp / ('quarantine-search-only-{}'.format(action_mode)) + quarantine_dir.mkdir() + + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend( + [ + str(TC.clamscan), + '--debug', + '-d', + str(db_dir), + '--{}={}'.format(action_mode, quarantine_dir), + str(scan_dir), + ] + ) + + try: + quarantine_dir.chmod(0o300) + self.log.info('Starting clamscan command: %s', ' '.join(command)) + completed = subprocess.run( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + finally: + quarantine_dir.chmod(0o700) + + self.log.info('clamscan stdout:\n%s', completed.stdout) + + return { + 'payload': payload, + 'payload_path': payload_path, + 'quarantine_dir': quarantine_dir, + 'returncode': completed.returncode, + 'stdout': completed.stdout, + } + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_directory_replacement_does_not_redirect_copy_target(self): + self.step_name('Test quarantine destination TOCTOU resistance for clamscan --copy') + result = self._exercise_quarantine_directory_replacement('copy') + + payload_path = result['payload_path'] + quarantine_dir = result['quarantine_dir'] + redirect_dir = result['redirect_dir'] + stdout = result['stdout'] + + assert result['saw_setup_event'], 'Failed to observe clamscan setup before attempting the directory replacement.' + assert (result['swapped'] or result['replacement_blocked']), 'Failed to replace or pin the quarantine directory during the test window.' + assert result['returncode'] == 1, 'Expected a virus-found exit code from clamscan.' + + redirected_payload = redirect_dir / payload_path.name + quarantined_payload = quarantine_dir / payload_path.name + copy_succeeded = ": copied to '" in stdout + self.assertFalse( + redirected_payload.exists(), + 'Quarantine copy was redirected through the replaced directory entry.', + ) + if copy_succeeded: + self.assertTrue( + quarantined_payload.exists(), + 'Expected a reported successful quarantine copy to create the destination file.', + ) + else: + self.assertIn( + "Can't copy file", + stdout, + 'Expected clamscan to either quarantine successfully or fail safely once the directory entry was replaced.', + ) + self.assertFalse( + quarantined_payload.exists(), + 'Expected safe failure to avoid creating a destination file after the directory entry was replaced.', + ) + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_directory_replacement_does_not_redirect_move_target(self): + self.step_name('Test quarantine destination TOCTOU resistance for clamscan --move') + result = self._exercise_quarantine_directory_replacement('move') + + payload_path = result['payload_path'] + quarantine_dir = result['quarantine_dir'] + redirect_dir = result['redirect_dir'] + stdout = result['stdout'] + + assert result['saw_setup_event'], 'Failed to observe clamscan setup before attempting the directory replacement.' + assert (result['swapped'] or result['replacement_blocked']), 'Failed to replace or pin the quarantine directory during the test window.' + assert result['returncode'] == 1, 'Expected a virus-found exit code from clamscan.' + + redirected_payload = redirect_dir / payload_path.name + quarantined_payload = quarantine_dir / payload_path.name + move_succeeded = ": moved to '" in stdout + self.assertFalse( + redirected_payload.exists(), + 'Quarantine move was redirected through the replaced directory entry.', + ) + if move_succeeded: + self.assertFalse( + payload_path.exists(), + 'Expected clamscan --move to remove the source file after quarantining it.', + ) + self.assertTrue( + quarantined_payload.exists(), + 'Expected a reported successful quarantine move to create the destination file.', + ) + else: + self.assertIn( + "Can't move file", + stdout, + 'Expected clamscan to either quarantine successfully or fail safely once the directory entry was replaced.', + ) + self.assertTrue( + payload_path.exists(), + 'Expected safe failure to leave the source file in place when the quarantine destination is unavailable.', + ) + self.assertFalse( + quarantined_payload.exists(), + 'Expected safe failure to avoid creating a destination file after the directory entry was replaced.', + ) + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_copy_uses_real_source_path_for_symlink_source(self): + self.step_name('Test quarantine copy uses the real source path for symlink sources') + result = self._exercise_source_link_quarantine('copy') + + payload_path = result['payload_path'] + link_path = result['link_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertIn('{}:'.format(link_path), result['stdout'], 'Expected clamscan to report the unresolved source path.') + self.assertNotIn('{}:'.format(payload_path), result['stdout'], 'Expected clamscan to avoid reporting the resolved target path.') + self.assertTrue(payload_path.exists(), 'Expected the symlink target to remain in place after the quarantine copy.') + self.assertTrue(link_path.exists(), 'Expected the symlink source to remain in place after the quarantine copy.') + self.assertFalse((result['quarantine_dir'] / link_path.name).exists(), 'Expected quarantine copy to avoid naming the destination after the symlink.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine copy to use the resolved source basename.') + self.assertEqual(payload_path.read_bytes(), quarantined_path.read_bytes(), 'Expected the quarantined file to contain the target file bytes.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_move_uses_real_source_path_for_symlink_source(self): + self.step_name('Test quarantine move uses the real source path for symlink sources') + result = self._exercise_source_link_quarantine('move') + + payload_path = result['payload_path'] + link_path = result['link_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertIn('{}:'.format(link_path), result['stdout'], 'Expected clamscan to report the unresolved source path.') + self.assertNotIn('{}:'.format(payload_path), result['stdout'], 'Expected clamscan to avoid reporting the resolved target path.') + self.assertFalse(payload_path.exists(), 'Expected the quarantine move to unlink the resolved target path.') + self.assertTrue(link_path.is_symlink(), 'Expected the original symlink entry to remain in place after the quarantine move.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine move to use the resolved source basename.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_remove_uses_real_source_path_for_symlink_source(self): + self.step_name('Test quarantine remove uses the real source path for symlink sources') + result = self._exercise_source_link_quarantine('remove') + + payload_path = result['payload_path'] + link_path = result['link_path'] + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertIn('{}:'.format(link_path), result['stdout'], 'Expected clamscan to report the unresolved source path.') + self.assertNotIn('{}:'.format(payload_path), result['stdout'], 'Expected clamscan to avoid reporting the resolved target path.') + self.assertFalse(payload_path.exists(), 'Expected quarantine removal to unlink the resolved target path.') + self.assertTrue(link_path.is_symlink(), 'Expected the original symlink entry to remain in place after the quarantine remove.') + + @unittest.skipIf(operating_system == 'windows', 'This test covers POSIX descriptor path resolution.') + def test_quarantine_move_unlinks_submitted_hardlink(self): + self.step_name('Test quarantine move unlinks the submitted hard-link name') + result = self._exercise_source_hardlink_quarantine('move') + + submitted_path = result['submitted_path'] + other_link_path = result['other_link_path'] + quarantined_path = result['quarantine_dir'] / submitted_path.name + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertFalse(submitted_path.exists(), 'Expected quarantine move to unlink the submitted hard-link name.') + self.assertTrue(other_link_path.exists(), 'Expected quarantine move to preserve the other hard-link name.') + self.assertEqual(result['payload'], other_link_path.read_bytes(), 'Expected the remaining hard link to retain the source bytes.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine move to create the destination file.') + self.assertEqual(result['payload'], quarantined_path.read_bytes(), 'Expected the quarantined file to contain the source bytes.') + + @unittest.skipIf(operating_system == 'windows', 'This test covers POSIX descriptor path resolution.') + def test_quarantine_remove_unlinks_submitted_hardlink(self): + self.step_name('Test quarantine remove unlinks the submitted hard-link name') + result = self._exercise_source_hardlink_quarantine('remove') + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertFalse(result['submitted_path'].exists(), 'Expected quarantine remove to unlink the submitted hard-link name.') + self.assertTrue(result['other_link_path'].exists(), 'Expected quarantine remove to preserve the other hard-link name.') + self.assertEqual(result['payload'], result['other_link_path'].read_bytes(), 'Expected the remaining hard link to retain the source bytes.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_copy_does_not_act_on_replaced_source_link(self): + self.step_name('Test quarantine copy stays bound to the opened source object') + result = self._exercise_source_link_replacement_until_infected('copy') + + payload_path = result['payload_path'] + decoy_path = result['decoy_path'] + link_path = result['link_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertTrue(link_path.is_symlink(), 'Expected the source path to remain a symlink after replacement.') + self.assertTrue(decoy_path.exists(), 'Expected the replacement decoy to remain in place.') + self.assertEqual(result['decoy'], decoy_path.read_bytes(), 'Expected quarantine copy not to modify the replacement decoy.') + self.assertTrue(payload_path.exists(), 'Expected quarantine copy to leave the opened source file in place.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine copy to create a copy of the opened source file.') + self.assertEqual(result['payload'], quarantined_path.read_bytes(), 'Expected the quarantine copy to contain the opened source bytes.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_move_does_not_act_on_replaced_source_link(self): + self.step_name('Test quarantine move stays bound to the opened source object') + result = self._exercise_source_link_replacement_until_infected('move') + + payload_path = result['payload_path'] + decoy_path = result['decoy_path'] + link_path = result['link_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertTrue(link_path.is_symlink(), 'Expected the source path to remain a symlink after replacement.') + self.assertTrue(decoy_path.exists(), 'Expected the replacement decoy to remain in place.') + self.assertEqual(result['decoy'], decoy_path.read_bytes(), 'Expected quarantine move not to modify the replacement decoy.') + self.assertFalse(payload_path.exists(), 'Expected quarantine move to unlink the opened source file.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine move to create a copy of the opened source file.') + self.assertEqual(result['payload'], quarantined_path.read_bytes(), 'Expected the quarantine move to preserve the opened source bytes.') + + @unittest.skipIf(not hasattr(os, 'symlink'), 'This platform does not support symlink creation in the test environment.') + def test_quarantine_remove_does_not_act_on_replaced_source_link(self): + self.step_name('Test quarantine remove stays bound to the opened source object') + result = self._exercise_source_link_replacement_until_infected('remove') + + payload_path = result['payload_path'] + decoy_path = result['decoy_path'] + link_path = result['link_path'] + + self.assertTrue(link_path.is_symlink(), 'Expected the source path to remain a symlink after replacement.') + self.assertTrue(decoy_path.exists(), 'Expected the replacement decoy to remain in place.') + self.assertEqual(result['decoy'], decoy_path.read_bytes(), 'Expected quarantine remove not to modify the replacement decoy.') + self.assertFalse(payload_path.exists(), 'Expected quarantine remove to unlink the opened source file.') + + @unittest.skipIf(operating_system == 'windows', 'This test uses POSIX directory permissions.') + def test_quarantine_copy_allows_search_only_destination_dir(self): + self.step_name('Test quarantine copy allows a write/search-only destination directory') + result = self._exercise_search_only_quarantine_directory('copy') + + payload_path = result['payload_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertTrue(payload_path.exists(), 'Expected quarantine copy to leave the source file in place.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine copy to create the destination file.') + self.assertEqual(result['payload'], quarantined_path.read_bytes(), 'Expected the quarantined copy to contain the source bytes.') + + @unittest.skipIf(operating_system == 'windows', 'This test uses POSIX directory permissions.') + def test_quarantine_move_allows_search_only_destination_dir(self): + self.step_name('Test quarantine move allows a write/search-only destination directory') + result = self._exercise_search_only_quarantine_directory('move') + + payload_path = result['payload_path'] + quarantined_path = result['quarantine_dir'] / payload_path.name + + self.assertEqual(1, result['returncode'], 'Expected a virus-found exit code from clamscan.') + self.assertFalse(payload_path.exists(), 'Expected quarantine move to unlink the source file.') + self.assertTrue(quarantined_path.exists(), 'Expected quarantine move to create the destination file.') + self.assertEqual(result['payload'], quarantined_path.read_bytes(), 'Expected the quarantined copy to contain the source bytes.') + + @unittest.skipUnless(operating_system in ('darwin', 'macos'), 'This test requires macOS copyfile semantics.') + def test_quarantine_copy_preserves_xattr(self): + self.step_name('Test quarantine copy preserves macOS xattrs') + + if shutil.which('xattr') is None: + self.skipTest('The xattr command is not available in this test environment.') + + db_dir = TC.path_tmp / 'db-xattr' + db_dir.mkdir() + + payload = b'CLAM-2959 quarantine xattr payload\n' + scan_dir = TC.path_tmp / 'scanme-xattr' + scan_dir.mkdir() + payload_path = scan_dir / 'backdoor' + payload_path.write_bytes(payload) + self._write_xattr(payload_path, 'com.clamav.test', 'preserve-me') + + self._write_hdb_signature(db_dir / 'trigger.hdb', payload, 'CLAM-2959-XATTR') + + quarantine_dir = TC.path_tmp / 'quarantine-xattr' + quarantine_dir.mkdir() + + command = [] + if str(TC.valgrind): + command.append(str(TC.valgrind)) + if TC.valgrind_args: + command.extend(TC.valgrind_args.split()) + command.extend( + [ + str(TC.clamscan), + '--debug', + '-d', + str(db_dir), + '--copy={}'.format(quarantine_dir), + str(scan_dir), + ] + ) + + self.log.info('Starting clamscan command: %s', ' '.join(command)) + completed = subprocess.run( + command, + cwd=str(TC.path_tmp), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=False, + ) + self.log.info('clamscan stdout:\n%s', completed.stdout) + + quarantined_path = quarantine_dir / payload_path.name + self.assertEqual(1, completed.returncode, 'Expected a virus-found exit code from clamscan.') + self.assertTrue(quarantined_path.exists(), 'Expected clamscan to create the quarantined copy.') + self.assertEqual( + 'preserve-me', + self._read_xattr(quarantined_path, 'com.clamav.test'), + 'Expected the quarantined copy to preserve the source extended attribute.', + ) diff -Nru clamav-1.4.3+dfsg/unit_tests/clamscan/xar_test.py clamav-1.4.6+dfsg/unit_tests/clamscan/xar_test.py --- clamav-1.4.3+dfsg/unit_tests/clamscan/xar_test.py 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/clamscan/xar_test.py 2026-08-06 21:12:04.000000000 +0000 @@ -0,0 +1,153 @@ +# Copyright (C) 2026 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + +""" +Run clamscan XAR tests. +""" + +import hashlib +import re +import struct +import sys +import zlib +from pathlib import Path + +sys.path.append(str(Path(__file__).resolve().parents[1])) +import testcase + + +class TC(testcase.TestCase): + @classmethod + def setUpClass(cls): + super(TC, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TC, cls).tearDownClass() + + def setUp(self): + super(TC, self).setUp() + + def tearDown(self): + super(TC, self).tearDown() + self.verify_valgrind_log() + + def make_xar( + self, + name, + toc_length_decompressed, + toc=b'', + truncate_stream=False, + pad_compressed_to=None, + ): + compressed_toc = zlib.compress(toc) + if truncate_stream: + compressed_toc = compressed_toc[:-4] + if pad_compressed_to is not None: + assert len(compressed_toc) <= pad_compressed_to + compressed_toc += bytes(pad_compressed_to - len(compressed_toc)) + + testfile = TC.path_tmp / name + testfile.write_bytes( + struct.pack( + '>IHHQQI', + 0x78617221, + 28, + 0, + len(compressed_toc), + toc_length_decompressed, + 0, + ) + compressed_toc + ) + return testfile + + def scan_xar(self, testfile, limits, path_db=None): + if path_db is None: + path_db = TC.path_source / 'unit_tests' / 'input' / 'clamav.hdb' + + command = ( + '{valgrind} {valgrind_args} {clamscan} {limits} ' + '-d {path_db} {testfile}' + ).format( + valgrind=TC.valgrind, + valgrind_args=TC.valgrind_args, + clamscan=TC.clamscan, + limits=limits, + path_db=path_db, + testfile=testfile, + ) + return self.execute_command(command) + + def test_declared_large_actual_small_toc_is_scanned(self): + self.step_name('Test XAR limits use the actual TOC size') + + for name, declared_length in ( + ('allocation-limit-toc.xar', 1024 * 1024 * 1024), + ('overflow-toc.xar', (1 << 64) - 1), + ): + with self.subTest(declared_length=declared_length): + testfile = self.make_xar( + name, + declared_length, + pad_compressed_to=44, + ) + assert testfile.stat().st_size == 72 + output = self.scan_xar( + testfile, + '--alert-exceeds-max=yes --max-filesize=1M --max-scansize=1M', + ) + + assert output.ec == 0 + self.verify_output( + output.out, + expected=[re.escape('{}: OK'.format(testfile))], + unexpected=[ + 'Heuristics.Limits.Exceeded', + "Can't allocate memory ERROR", + ], + ) + + def test_declared_small_actual_large_toc_obeys_scan_limits(self): + self.step_name('Test XAR limits stop actual TOC output') + + actual_toc = b'' + (b' ' * (2 * 1024 * 1024)) + b'' + testfile = self.make_xar( + 'actual-oversized-toc.xar', + 1, + toc=actual_toc, + ) + output = self.scan_xar( + testfile, + '--alert-exceeds-max=yes --max-filesize=1M --max-scansize=1M', + ) + + assert output.ec == 1 + self.verify_output( + output.out, + expected=['Heuristics.Limits.Exceeded.MaxScanSize FOUND'], + unexpected=["Can't allocate memory ERROR"], + ) + + def test_incomplete_toc_stream_is_not_scanned(self): + self.step_name('Test XAR requires a complete TOC stream') + + toc = b'' + path_db = TC.path_tmp / 'xar-toc.hdb' + path_db.write_text( + '{}:{}:XAR_TOC_TEST\n'.format( + hashlib.md5(toc).hexdigest(), + len(toc), + ) + ) + testfile = self.make_xar( + 'incomplete-toc.xar', + len(toc), + toc=toc, + truncate_stream=True, + ) + output = self.scan_xar(testfile, '', path_db=path_db) + + assert output.ec == 0 + self.verify_output( + output.out, + unexpected=['XAR_TOC_TEST.UNOFFICIAL FOUND'], + ) diff -Nru clamav-1.4.3+dfsg/unit_tests/valgrind.supp clamav-1.4.6+dfsg/unit_tests/valgrind.supp --- clamav-1.4.3+dfsg/unit_tests/valgrind.supp 2025-06-17 01:41:16.000000000 +0000 +++ clamav-1.4.6+dfsg/unit_tests/valgrind.supp 2026-08-06 21:12:04.000000000 +0000 @@ -376,3 +376,12 @@ fun:start_thread fun:clone } +{ + + Memcheck:Cond + ... + fun:read_header_info<*::io::cursor::Cursor<&[u8]>> + ... + fun:fuzzy_hash_calculate_image + ... +}

= rav1e_config(p).new_context()?; + let mut frame = ctx.new_frame(); + + init(&mut frame)?; + ctx.send_frame(frame)?; + ctx.flush(); + + let mut out = Vec::new(); + loop { + match ctx.receive_packet() { + Ok(mut packet) => match packet.frame_type { + FrameType::KEY => { + out.append(&mut packet.data); + }, + _ => continue, + }, + Err(EncoderStatus::Encoded) | + Err(EncoderStatus::LimitReached) => break, + Err(err) => Err(err)?, + } + } + Ok(out) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/dirtyalpha.rs clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/dirtyalpha.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/dirtyalpha.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/dirtyalpha.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,135 @@ +use imgref::{Img, ImgRef}; +use rgb::{ComponentMap, RGB, RGBA8}; + +#[inline] +fn weighed_pixel(px: RGBA8) -> (u16, RGB) { + if px.a == 0 { + return (0, RGB::new(0, 0, 0)); + } + let weight = 256 - u16::from(px.a); + (weight, RGB::new( + u32::from(px.r) * u32::from(weight), + u32::from(px.g) * u32::from(weight), + u32::from(px.b) * u32::from(weight))) +} + +/// Clear/change RGB components of fully-transparent RGBA pixels to make them cheaper to encode with AV1 +pub(crate) fn blurred_dirty_alpha(img: ImgRef) -> Option>> { + // get dominant visible transparent color (excluding opaque pixels) + let mut sum = RGB::new(0, 0, 0); + let mut weights = 0; + + // Only consider colors around transparent images + // (e.g. solid semitransparent area doesn't need to contribute) + loop9::loop9_img(img, |_, _, top, mid, bot| { + if mid.curr.a == 255 || mid.curr.a == 0 { + return; + } + if chain(&top, &mid, &bot).any(|px| px.a == 0) { + let (w, px) = weighed_pixel(mid.curr); + weights += u64::from(w); + sum += px.map(u64::from); + } + }); + if weights == 0 { + return None; // opaque image + } + + let neutral_alpha = RGBA8::new((sum.r / weights) as u8, (sum.g / weights) as u8, (sum.b / weights) as u8, 0); + let img2 = bleed_opaque_color(img, neutral_alpha); + Some(blur_transparent_pixels(img2.as_ref())) +} + +/// copy color from opaque pixels to transparent pixels +/// (so that when edges get crushed by compression, the distortion will be away from visible edge) +fn bleed_opaque_color(img: ImgRef, bg: RGBA8) -> Img> { + let mut out = Vec::with_capacity(img.width() * img.height()); + loop9::loop9_img(img, |_, _, top, mid, bot| { + out.push(if mid.curr.a == 255 { + mid.curr + } else { + let (weights, sum) = chain(&top, &mid, &bot) + .map(|c| weighed_pixel(*c)) + .fold((0u32, RGB::new(0,0,0)), |mut sum, item| { + sum.0 += u32::from(item.0); + sum.1 += item.1; + sum + }); + if weights == 0 { + bg + } else { + let mut avg = sum.map(|c| (c / weights) as u8); + if mid.curr.a == 0 { + avg.with_alpha(0) + } else { + // also change non-transparent colors, but only within range where + // rounding caused by premultiplied alpha would land on the same color + avg.r = clamp(avg.r, premultiplied_minmax(mid.curr.r, mid.curr.a)); + avg.g = clamp(avg.g, premultiplied_minmax(mid.curr.g, mid.curr.a)); + avg.b = clamp(avg.b, premultiplied_minmax(mid.curr.b, mid.curr.a)); + avg.with_alpha(mid.curr.a) + } + } + }); + }); + Img::new(out, img.width(), img.height()) +} + +/// ensure there are no sharp edges created by the cleared alpha +fn blur_transparent_pixels(img: ImgRef) -> Img> { + let mut out = Vec::with_capacity(img.width() * img.height()); + loop9::loop9_img(img, |_, _, top, mid, bot| { + out.push(if mid.curr.a == 255 { + mid.curr + } else { + let sum: RGB = chain(&top, &mid, &bot).map(|px| px.rgb().map(u16::from)).sum(); + let mut avg = sum.map(|c| (c / 9) as u8); + if mid.curr.a == 0 { + avg.with_alpha(0) + } else { + // also change non-transparent colors, but only within range where + // rounding caused by premultiplied alpha would land on the same color + avg.r = clamp(avg.r, premultiplied_minmax(mid.curr.r, mid.curr.a)); + avg.g = clamp(avg.g, premultiplied_minmax(mid.curr.g, mid.curr.a)); + avg.b = clamp(avg.b, premultiplied_minmax(mid.curr.b, mid.curr.a)); + avg.with_alpha(mid.curr.a) + } + }); + }); + Img::new(out, img.width(), img.height()) +} + +#[inline(always)] +fn chain<'a, T>(top: &'a loop9::Triple, mid: &'a loop9::Triple, bot: &'a loop9::Triple) -> impl Iterator + 'a { + top.iter().chain(mid.iter()).chain(bot.iter()) +} + +#[inline] +fn clamp(px: u8, (min, max): (u8, u8)) -> u8 { + px.max(min).min(max) +} + +/// safe range to change px color given its alpha +/// (mostly-transparent colors tolerate more variation) +#[inline] +fn premultiplied_minmax(px: u8, alpha: u8) -> (u8, u8) { + let alpha = u16::from(alpha); + let rounded = u16::from(px) * alpha / 255 * 255; + + // leave some spare room for rounding + let low = ((rounded + 16) / alpha) as u8; + let hi = ((rounded + 239) / alpha) as u8; + + (low.min(px), hi.max(px)) +} + +#[test] +fn preminmax() { + assert_eq!((100, 100), premultiplied_minmax(100, 255)); + assert_eq!((78, 100), premultiplied_minmax(100, 10)); + assert_eq!(100 * 10 / 255, 78 * 10 / 255); + assert_eq!(100 * 10 / 255, 100 * 10 / 255); + assert_eq!((8, 119), premultiplied_minmax(100, 2)); + assert_eq!((16, 239), premultiplied_minmax(100, 1)); + assert_eq!((15, 255), premultiplied_minmax(255, 1)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +use quick_error::quick_error; + +#[derive(Debug)] +#[doc(hidden)] +pub struct EncodingErrorDetail; // maybe later + +quick_error! { + /// Failures enum + #[derive(Debug)] + #[non_exhaustive] + pub enum Error { + /// Slices given to `encode_raw_planes` must be `width * height` large. + TooFewPixels { + display("Provided buffer is smaller than width * height") + } + Unsupported(msg: &'static str) { + display("Not supported: {}", msg) + } + EncodingError(e: EncodingErrorDetail) { + display("Encoding error reported by rav1e") + from(_e: rav1e::InvalidConfig) -> (EncodingErrorDetail) + from(_e: rav1e::EncoderStatus) -> (EncodingErrorDetail) + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/ravif/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ravif/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,143 @@ +//! ```rust +//! use ravif::*; +//! # fn doit(pixels: &[RGBA8], width: usize, height: usize) -> Result<(), Error> { +//! let res = Encoder::new() +//! .with_quality(70.) +//! .with_speed(4) +//! .encode_rgba(Img::new(pixels, width, height))?; +//! std::fs::write("hello.avif", res.avif_file); +//! # Ok(()) } + +mod av1encoder; + +mod error; +pub use av1encoder::ColorModel; +pub use error::Error; + +#[doc(hidden)] +#[deprecated = "Renamed to `ColorModel`"] +pub type ColorSpace = ColorModel; + +pub use av1encoder::{AlphaColorMode, BitDepth, EncodedImage, Encoder}; +#[doc(inline)] +pub use rav1e::prelude::MatrixCoefficients; + +mod dirtyalpha; + +#[doc(no_inline)] +pub use imgref::Img; +#[doc(no_inline)] +pub use rgb::{RGB8, RGBA8}; + +#[cfg(not(feature = "threading"))] +mod rayoff { + pub fn current_num_threads() -> usize { + std::thread::available_parallelism().map(|v| v.get()).unwrap_or(1) + } + + pub fn join(a: impl FnOnce() -> A, b: impl FnOnce() -> B) -> (A, B) { + (a(), b()) + } +} + +#[test] +fn encode8_with_alpha() { + let img = imgref::ImgVec::new((0..200).flat_map(|y| (0..256).map(move |x| { + RGBA8::new(x as u8, y as u8, 255, (x + y) as u8) + })).collect(), 256, 200); + + let enc = Encoder::new() + .with_quality(22.0) + .with_bit_depth(BitDepth::Eight) + .with_speed(1) + .with_alpha_quality(22.0) + .with_alpha_color_mode(AlphaColorMode::UnassociatedDirty) + .with_num_threads(Some(2)); + let EncodedImage { avif_file, color_byte_size, alpha_byte_size , .. } = enc.encode_rgba(img.as_ref()).unwrap(); + assert!(color_byte_size > 50 && color_byte_size < 1000); + assert!(alpha_byte_size > 50 && alpha_byte_size < 1000); // the image must have alpha + + let parsed = avif_parse::read_avif(&mut avif_file.as_slice()).unwrap(); + assert!(parsed.alpha_item.is_some()); + assert!(parsed.primary_item.len() > 100); + assert!(parsed.primary_item.len() < 1000); + + let md = parsed.primary_item_metadata().unwrap(); + assert_eq!(md.max_frame_width.get(), 256); + assert_eq!(md.max_frame_height.get(), 200); + assert_eq!(md.bit_depth, 8); +} + +#[test] +fn encode8_opaque() { + let img = imgref::ImgVec::new((0..101).flat_map(|y| (0..129).map(move |x| { + RGBA8::new(255, 100 + x as u8, y as u8, 255) + })).collect(), 129, 101); + + let enc = Encoder::new() + .with_quality(33.0) + .with_speed(10) + .with_alpha_quality(33.0) + .with_bit_depth(BitDepth::Auto) + .with_alpha_color_mode(AlphaColorMode::UnassociatedDirty) + .with_num_threads(Some(1)); + let EncodedImage { avif_file, color_byte_size, alpha_byte_size , .. } = enc.encode_rgba(img.as_ref()).unwrap(); + assert_eq!(0, alpha_byte_size); // the image must not have alpha + assert!(color_byte_size > 50 && color_byte_size < 1000); + + let parsed1 = avif_parse::read_avif(&mut avif_file.as_slice()).unwrap(); + assert_eq!(None, parsed1.alpha_item); + + let md = parsed1.primary_item_metadata().unwrap(); + assert_eq!(md.max_frame_width.get(), 129); + assert_eq!(md.max_frame_height.get(), 101); + assert!(md.still_picture); + assert_eq!(md.bit_depth, 10); + + let img = img.map_buf(|b| b.into_iter().map(|px| px.rgb()).collect::>()); + + let enc = Encoder::new() + .with_quality(33.0) + .with_speed(10) + .with_bit_depth(BitDepth::Ten) + .with_alpha_quality(33.0) + .with_alpha_color_mode(AlphaColorMode::UnassociatedDirty) + .with_num_threads(Some(1)); + + let EncodedImage { avif_file, color_byte_size, alpha_byte_size , .. } = enc.encode_rgb(img.as_ref()).unwrap(); + assert_eq!(0, alpha_byte_size); // the image must not have alpha + assert!(color_byte_size > 50 && color_byte_size < 1000); + + let parsed2 = avif_parse::read_avif(&mut avif_file.as_slice()).unwrap(); + + assert_eq!(parsed1.alpha_item, parsed2.alpha_item); + assert_eq!(parsed1.primary_item, parsed2.primary_item); // both are the same pixels +} + +#[test] +fn encode8_cleans_alpha() { + let img = imgref::ImgVec::new((0..200).flat_map(|y| (0..256).map(move |x| { + RGBA8::new((((x/ 5 + y ) & 0xF) << 4) as u8, (7 * x + y / 2) as u8, ((x * y) & 0x3) as u8, ((x + y) as u8 & 0x7F).saturating_sub(100)) + })).collect(), 256, 200); + + let enc = Encoder::new() + .with_quality(66.0) + .with_speed(6) + .with_alpha_quality(88.0) + .with_alpha_color_mode(AlphaColorMode::UnassociatedDirty) + .with_num_threads(Some(1)); + + let dirty = enc + .encode_rgba(img.as_ref()) + .unwrap(); + + let clean = enc + .with_alpha_color_mode(AlphaColorMode::UnassociatedClean) + .encode_rgba(img.as_ref()) + .unwrap(); + + assert_eq!(clean.alpha_byte_size, dirty.alpha_byte_size); // same alpha on both + assert!(clean.alpha_byte_size > 200 && clean.alpha_byte_size < 1000); + assert!(clean.color_byte_size > 2000 && clean.color_byte_size < 6000); + assert!(clean.color_byte_size < dirty.color_byte_size / 2); // significant reduction in color data +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rayon/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"5c786211c556fd7f0a58c16d034d70bafe221c8c084d7af1d601c85053cec6ee","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"5dada1ceff462280be5af52131dbc529cb26bc6eb04d3cf2403ac234a0725fff","RELEASES.md":"2287b9d2894288c931aab43c26bef2fc76f97cef4accbb6cc9960680efaa7311","src/array.rs":"0e1524d222baa8b64f67689b0dea3115f3befb8cc3b5aee9ace169c57b2d29d2","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"3978222720a2df20be7fd0856d8515b6f9fa40f6556662bd3c0726b1392970ca","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"f76e6727ae8bd0dc8fff5f4a79df3fc598daf5d7371bdf8b2e730fba4ba82719","src/compile_fail/cannot_zip_filtered_data.rs":"3588fcf72e804ea867ea525b6dfa7a3d45fe14e28088e849fa9ddb029acc8a7a","src/compile_fail/cell_par_iter.rs":"ebf8804993c103f9d8228aba0bb2a5f0aadb957de9f1eb59cf546dbace285201","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"39ab32af552c2b35e67593b54da146d8edd8e022dbadcf7a81983983a065bbc2","src/compile_fail/no_send_par_iter.rs":"b241446439c659f35060df12ba91590ea4267f373ddc688e4ffc203321db24b3","src/compile_fail/rc_par_iter.rs":"938776b08612e35c85b99962024d54af5a8c87d45a050a76375d16ef6fe4299f","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/blocks.rs":"851cd78b26d9ae0b789566f2fe018502c80ff6352b4a06f71f14326d78759074","src/iter/chain.rs":"9a79215e5f40619b023a6cc4111dd13644fa290397f01836a9f6cc1a3df5355a","src/iter/chunks.rs":"fa7242ce8e84b0f5c2d1c0116ad635ba149db988c903863bd62d64ff51065130","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"9afcf4c6cf6bbfe22aed42e5bb5a0dcbd4d7c9b060d80d3b01fad665b46e4952","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"7f1d1f4e90f046ef2fd35736850aab0c1a92395cf83175f93f6bdac74c48f5b3","src/iter/filter.rs":"e48f317ee4d66dea6f19ac2607c6f764d20c023d847b66c6c01826e6a46f96ab","src/iter/filter_map.rs":"2530b726b27fe3a678a34722b1baf8e223a65a0770fa8ed5dca13786ea454580","src/iter/find.rs":"896ddb05b2fa7368462e0ff2a73982ced5f93266c0e0e8c27bb3fc4ec737af21","src/iter/find_first_last/mod.rs":"3759a42531b5593f4a19196a5cc38b4afc322b12ec50beb3c0bb1389de4b14ca","src/iter/find_first_last/test.rs":"fe11970bbe0eb07aee1bd44c3b0cdcdae3d0630269d6530658cadd7f17724e0b","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/fold_chunks.rs":"2c60b969fb5a148b092bd92619b13ee669ff82d008f36dae5f4f908eb277f1d8","src/iter/fold_chunks_with.rs":"d1bd686202c21a54b60cbe7c7db30a09c35ec35fb544c18966c8e8606ac25490","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"46d4e004a71fe83368c59dc85e9eca9bc813b40bf787b971a3e74efef3975c78","src/iter/inspect.rs":"d502b6e435a44f34ba49dfe46aa809a1bad3dbaefa048540a98e3026437b1016","src/iter/interleave.rs":"b3746c549cede5b978392f10305bd44fe12fa0566cd0be9c11587ed70eb92b19","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"5159ed82c624481808d94714a3c3151c431dd50d4dd27d4566c82de01be08b7d","src/iter/map.rs":"f778f1bd0a71c962375d2ce886b40ac365afed4a032e2b9dd6c385712d3d75eb","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"fd42fc5b56e05f1f18724472cd25938c05f78b463d2106df0d2fd48b3f200843","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"344c6233e6f799a95b1df517429ee53c817dd227be3c351a7ccc725c57f9f962","src/iter/plumbing/README.md":"da11d90143745b30efe99934bb5d8267d7b205c8096d0936ddb1bbba0b13ea17","src/iter/plumbing/mod.rs":"cb6402a297ab7e43badd9dc6ec76f604525f5365d27e82ba829fb73b009f2ae2","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"eaddbf216b068d33cb92f594cf57522f6ea1e2d7699887a086484843bdec3585","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"8ac3dd56f306c40b86a4da32cf7f4ceee58a9c0f33dcad8b2b09fb74150bf5b4","src/iter/skip_any.rs":"e827e1658aea906ab1045533d97476a91886dc6c41ab1fe9b6147f90385e45b8","src/iter/skip_any_while.rs":"88e8f5aea16cde70ae41f5eb32749e955861a476766ff678b8bbfca96ed80803","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"a8e0af1c831f843100ce1e1d8ff51a8d01a2935bdfbee74b5e7a65faf93a508c","src/iter/sum.rs":"073a886b8d6b0d7ca5621449a20e9980c90c6d39de56f074371fb075d9df2bed","src/iter/take.rs":"c3f8e46dca9bd89c26c15a2ecbd013ee3dfef4b3975c73c23849b03fb7493fc7","src/iter/take_any.rs":"51f5b39c3fb608fcf7d7b35592a28d95250d9cbb28dbc13a0dc01d22aa0023f9","src/iter/take_any_while.rs":"8327c019b4047d567d8fdae975049c9bc1e4422dddffd3196b62c938d1f5e1fc","src/iter/test.rs":"ae4de120904370fa197f950350b07db01da9f292769342616a516c9786de283f","src/iter/try_fold.rs":"d4f40a00995273b8803031da4a4b139a5f462a174ef1d3c8ba54524b47ab8180","src/iter/try_reduce.rs":"12317a649f777e76e6ae610d205104d7946fbe45804fbf1caa0843118531baed","src/iter/try_reduce_with.rs":"9171563fc22110d7a359f19de7ca66a6823d8f712099d05d01560795781fdeec","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"0362185a002cdda0e73b13237017ddc3d5e72390bba6cb2e2f021e947ed861dc","src/iter/walk_tree.rs":"668e687fe7761008ea95d95f5e05bba6e63053ac90aa4677a619439801f2350d","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"b15e418daeb2feb85d3d993b307a47018f44746cc9669f15d6bee6c7840b0645","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"027d4a42a3728ac6819c1fc2983d762ea66e2e29edc7ec7df2435884ad75bd6f","src/math.rs":"040e82a4ba7a6680eb65b65f4d1fc3dc477d902855d8651105b138ae2e71c8e8","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"e88bd691f0ce5b82f6d185df30180b143856cfde53974e1d8cf2a9d5abb2a867","src/range_inclusive.rs":"130a58852281195b979c5a2875349e99b7c72185e8da645addaacca33b7394de","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunk_by.rs":"bca36aa0920039d398b4f8e218ffe61bf657c2a782ed37d08680c94567e012f9","src/slice/chunks.rs":"8a2066ddda9f0cf00f2b284e211311ca26b33e9a8bdc2ae201369f5bae4fb41b","src/slice/mergesort.rs":"effe59ecc40b330c364a3da868182b72b487025d9ba0256079f8a284b85a05ef","src/slice/mod.rs":"d16808e3820166032bd32cc678ce80b01bd8c9420ab27d1717e4b72b4694d843","src/slice/quicksort.rs":"082eb0acb08b675607b0d5a6e99f40bebf924dad6f53c848fc3c2458cc1a48e5","src/slice/rchunks.rs":"23229976840da07e8fff6657ca626810ed380682719e4d1f0693ac08839e1b7c","src/slice/test.rs":"6789b33d62a913770d5b60d26eb587a4243c15b2a1c6f0a6f613806576943694","src/split_producer.rs":"b2633e62bf87ccdc81d0d738de8f184f5892129fc31e81bc891e978b7179e695","src/str.rs":"f8720e1a167a186169797dd4342cde7be45d0ded453c461c42a1331e1c9f6274","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"c80653f3040c07e04fa293fa0359e1f8e7faad13d67899e78780e855b6f9f63a","tests/chars.rs":"6e1aeda8aa604f15965aa3c735da07f2145bd06079abb684b70598c86d99a263","tests/clones.rs":"6088be680e6b25d919ae4a23c1185202870b83789fedaed3cbf2d9e8fb612212","tests/collect.rs":"3ae066cd89eacc9d171ad99ec73335e8040748370e3a3f46845d5af12ce30cc2","tests/cross-pool.rs":"d2ce3b9013f77c955aa02313b27436c5bf760ab0e6a1e7d768effae69b5bdbfe","tests/debug.rs":"5c77126f8145bca24d76022649d84d5d525d90c7fcb3a8d3c0cd1ac05439cf17","tests/drain_vec.rs":"305ca40ba41ed3b459a334386cd742c66586d62aadfb624278aabdf10b872a12","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"2ca857b37b740528b2e8395b479a409227383b46e0ed012286dcdd1330dacd70","tests/named-threads.rs":"9bd7ea27b4f6cf9e3b3486311747e15a3beb9b9d4e48f115d66ed8288ca19d38","tests/octillion.rs":"756d3789300d6eb4d5f7690937e06f87714b6b0a62ac812f72b622bb6974ccd2","tests/par_bridge_recursion.rs":"6e7030de6d97d1db1c335f676dd2a6348cde2873520df290c4a16bf949c06f00","tests/producer_split_at.rs":"17caad52fb7c9b3e09a2a138e402db39d1d3a96f2305461cbe36c45f7b85f8d5","tests/sort-panic-safe.rs":"ee4093d5367e0a6dae086db71b5d25c4d37773b985575a41f30c72b151e4072d","tests/str.rs":"34aac04413ad0370e6abc66ccc21b00c07655f82d046e47134c6ae0a9c4642e1"},"package":"b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ff97d4add5030139e1f42b5aaca9bfc3f74f5cd746853e15f96ebcab07c34296","Cargo.toml":"5c786211c556fd7f0a58c16d034d70bafe221c8c084d7af1d601c85053cec6ee","Cargo.toml.orig":"81fde7efd7f502454cc0329eeebb59c9c61b96c80c8b2a56a73fc139556f2db5","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"5dada1ceff462280be5af52131dbc529cb26bc6eb04d3cf2403ac234a0725fff","RELEASES.md":"2287b9d2894288c931aab43c26bef2fc76f97cef4accbb6cc9960680efaa7311","src/array.rs":"0e1524d222baa8b64f67689b0dea3115f3befb8cc3b5aee9ace169c57b2d29d2","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"3978222720a2df20be7fd0856d8515b6f9fa40f6556662bd3c0726b1392970ca","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"f76e6727ae8bd0dc8fff5f4a79df3fc598daf5d7371bdf8b2e730fba4ba82719","src/compile_fail/cannot_zip_filtered_data.rs":"3588fcf72e804ea867ea525b6dfa7a3d45fe14e28088e849fa9ddb029acc8a7a","src/compile_fail/cell_par_iter.rs":"ebf8804993c103f9d8228aba0bb2a5f0aadb957de9f1eb59cf546dbace285201","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"39ab32af552c2b35e67593b54da146d8edd8e022dbadcf7a81983983a065bbc2","src/compile_fail/no_send_par_iter.rs":"b241446439c659f35060df12ba91590ea4267f373ddc688e4ffc203321db24b3","src/compile_fail/rc_par_iter.rs":"938776b08612e35c85b99962024d54af5a8c87d45a050a76375d16ef6fe4299f","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/blocks.rs":"851cd78b26d9ae0b789566f2fe018502c80ff6352b4a06f71f14326d78759074","src/iter/chain.rs":"9a79215e5f40619b023a6cc4111dd13644fa290397f01836a9f6cc1a3df5355a","src/iter/chunks.rs":"fa7242ce8e84b0f5c2d1c0116ad635ba149db988c903863bd62d64ff51065130","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"9afcf4c6cf6bbfe22aed42e5bb5a0dcbd4d7c9b060d80d3b01fad665b46e4952","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"7f1d1f4e90f046ef2fd35736850aab0c1a92395cf83175f93f6bdac74c48f5b3","src/iter/filter.rs":"e48f317ee4d66dea6f19ac2607c6f764d20c023d847b66c6c01826e6a46f96ab","src/iter/filter_map.rs":"2530b726b27fe3a678a34722b1baf8e223a65a0770fa8ed5dca13786ea454580","src/iter/find.rs":"896ddb05b2fa7368462e0ff2a73982ced5f93266c0e0e8c27bb3fc4ec737af21","src/iter/find_first_last/mod.rs":"3759a42531b5593f4a19196a5cc38b4afc322b12ec50beb3c0bb1389de4b14ca","src/iter/find_first_last/test.rs":"fe11970bbe0eb07aee1bd44c3b0cdcdae3d0630269d6530658cadd7f17724e0b","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/fold_chunks.rs":"2c60b969fb5a148b092bd92619b13ee669ff82d008f36dae5f4f908eb277f1d8","src/iter/fold_chunks_with.rs":"d1bd686202c21a54b60cbe7c7db30a09c35ec35fb544c18966c8e8606ac25490","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"46d4e004a71fe83368c59dc85e9eca9bc813b40bf787b971a3e74efef3975c78","src/iter/inspect.rs":"d502b6e435a44f34ba49dfe46aa809a1bad3dbaefa048540a98e3026437b1016","src/iter/interleave.rs":"b3746c549cede5b978392f10305bd44fe12fa0566cd0be9c11587ed70eb92b19","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"5159ed82c624481808d94714a3c3151c431dd50d4dd27d4566c82de01be08b7d","src/iter/map.rs":"f778f1bd0a71c962375d2ce886b40ac365afed4a032e2b9dd6c385712d3d75eb","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"fd42fc5b56e05f1f18724472cd25938c05f78b463d2106df0d2fd48b3f200843","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"344c6233e6f799a95b1df517429ee53c817dd227be3c351a7ccc725c57f9f962","src/iter/plumbing/README.md":"da11d90143745b30efe99934bb5d8267d7b205c8096d0936ddb1bbba0b13ea17","src/iter/plumbing/mod.rs":"cb6402a297ab7e43badd9dc6ec76f604525f5365d27e82ba829fb73b009f2ae2","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"eaddbf216b068d33cb92f594cf57522f6ea1e2d7699887a086484843bdec3585","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"8ac3dd56f306c40b86a4da32cf7f4ceee58a9c0f33dcad8b2b09fb74150bf5b4","src/iter/skip_any.rs":"e827e1658aea906ab1045533d97476a91886dc6c41ab1fe9b6147f90385e45b8","src/iter/skip_any_while.rs":"88e8f5aea16cde70ae41f5eb32749e955861a476766ff678b8bbfca96ed80803","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"a8e0af1c831f843100ce1e1d8ff51a8d01a2935bdfbee74b5e7a65faf93a508c","src/iter/sum.rs":"073a886b8d6b0d7ca5621449a20e9980c90c6d39de56f074371fb075d9df2bed","src/iter/take.rs":"c3f8e46dca9bd89c26c15a2ecbd013ee3dfef4b3975c73c23849b03fb7493fc7","src/iter/take_any.rs":"51f5b39c3fb608fcf7d7b35592a28d95250d9cbb28dbc13a0dc01d22aa0023f9","src/iter/take_any_while.rs":"8327c019b4047d567d8fdae975049c9bc1e4422dddffd3196b62c938d1f5e1fc","src/iter/test.rs":"ae4de120904370fa197f950350b07db01da9f292769342616a516c9786de283f","src/iter/try_fold.rs":"d4f40a00995273b8803031da4a4b139a5f462a174ef1d3c8ba54524b47ab8180","src/iter/try_reduce.rs":"12317a649f777e76e6ae610d205104d7946fbe45804fbf1caa0843118531baed","src/iter/try_reduce_with.rs":"9171563fc22110d7a359f19de7ca66a6823d8f712099d05d01560795781fdeec","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"0362185a002cdda0e73b13237017ddc3d5e72390bba6cb2e2f021e947ed861dc","src/iter/walk_tree.rs":"668e687fe7761008ea95d95f5e05bba6e63053ac90aa4677a619439801f2350d","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"b15e418daeb2feb85d3d993b307a47018f44746cc9669f15d6bee6c7840b0645","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"027d4a42a3728ac6819c1fc2983d762ea66e2e29edc7ec7df2435884ad75bd6f","src/math.rs":"040e82a4ba7a6680eb65b65f4d1fc3dc477d902855d8651105b138ae2e71c8e8","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"e88bd691f0ce5b82f6d185df30180b143856cfde53974e1d8cf2a9d5abb2a867","src/range_inclusive.rs":"130a58852281195b979c5a2875349e99b7c72185e8da645addaacca33b7394de","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunk_by.rs":"bca36aa0920039d398b4f8e218ffe61bf657c2a782ed37d08680c94567e012f9","src/slice/chunks.rs":"8a2066ddda9f0cf00f2b284e211311ca26b33e9a8bdc2ae201369f5bae4fb41b","src/slice/mergesort.rs":"effe59ecc40b330c364a3da868182b72b487025d9ba0256079f8a284b85a05ef","src/slice/mod.rs":"d16808e3820166032bd32cc678ce80b01bd8c9420ab27d1717e4b72b4694d843","src/slice/quicksort.rs":"082eb0acb08b675607b0d5a6e99f40bebf924dad6f53c848fc3c2458cc1a48e5","src/slice/rchunks.rs":"23229976840da07e8fff6657ca626810ed380682719e4d1f0693ac08839e1b7c","src/slice/test.rs":"6789b33d62a913770d5b60d26eb587a4243c15b2a1c6f0a6f613806576943694","src/split_producer.rs":"b2633e62bf87ccdc81d0d738de8f184f5892129fc31e81bc891e978b7179e695","src/str.rs":"f8720e1a167a186169797dd4342cde7be45d0ded453c461c42a1331e1c9f6274","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"c80653f3040c07e04fa293fa0359e1f8e7faad13d67899e78780e855b6f9f63a","tests/chars.rs":"6e1aeda8aa604f15965aa3c735da07f2145bd06079abb684b70598c86d99a263","tests/clones.rs":"6088be680e6b25d919ae4a23c1185202870b83789fedaed3cbf2d9e8fb612212","tests/collect.rs":"3ae066cd89eacc9d171ad99ec73335e8040748370e3a3f46845d5af12ce30cc2","tests/cross-pool.rs":"d2ce3b9013f77c955aa02313b27436c5bf760ab0e6a1e7d768effae69b5bdbfe","tests/debug.rs":"5c77126f8145bca24d76022649d84d5d525d90c7fcb3a8d3c0cd1ac05439cf17","tests/drain_vec.rs":"305ca40ba41ed3b459a334386cd742c66586d62aadfb624278aabdf10b872a12","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"2ca857b37b740528b2e8395b479a409227383b46e0ed012286dcdd1330dacd70","tests/named-threads.rs":"9bd7ea27b4f6cf9e3b3486311747e15a3beb9b9d4e48f115d66ed8288ca19d38","tests/octillion.rs":"756d3789300d6eb4d5f7690937e06f87714b6b0a62ac812f72b622bb6974ccd2","tests/par_bridge_recursion.rs":"6e7030de6d97d1db1c335f676dd2a6348cde2873520df290c4a16bf949c06f00","tests/producer_split_at.rs":"17caad52fb7c9b3e09a2a138e402db39d1d3a96f2305461cbe36c45f7b85f8d5","tests/sort-panic-safe.rs":"ee4093d5367e0a6dae086db71b5d25c4d37773b985575a41f30c72b151e4072d","tests/str.rs":"34aac04413ad0370e6abc66ccc21b00c07655f82d046e47134c6ae0a9c4642e1"},"package":"b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rayon/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7543ed40c9a017dee32b3dc72b3ae819820e8366" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rayon/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rayon/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +[package] +name = "rayon" +version = "1.10.0" +authors = ["Niko Matsakis ", + "Josh Stone "] +description = "Simple work-stealing parallelism for Rust" +rust-version = "1.63" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rayon-rs/rayon" +documentation = "https://docs.rs/rayon/" +readme = "README.md" +keywords = ["parallel", "thread", "concurrency", "join", "performance"] +categories = ["concurrency"] +exclude = ["/ci/*", "/scripts/*", "/.github/*"] + +[workspace] +members = ["rayon-demo", "rayon-core"] +exclude = ["ci"] + +[dependencies] +rayon-core = { version = "1.12.1", path = "rayon-core" } +wasm_sync = { version = "0.1.0", optional = true } + +# This is a public dependency! +[dependencies.either] +version = "1.0" +default-features = false + +[features] +# This feature switches to a spin-lock implementation on the browser's +# main thread to avoid the forbidden `atomics.wait`. +# +# Only useful on the `wasm32-unknown-unknown` target. +web_spin_lock = ["dep:wasm_sync", "rayon-core/web_spin_lock"] + +[dev-dependencies] +rand = "0.8" +rand_xorshift = "0.3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"60f04aab82c6489c779cf19535fddf0ec1a673edc07f523c66c10996806d2fbe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"7281273bea1d5fdc57731513cf9f0e3b911d06ac9905b03a8375a1324951c35b","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/broadcast/mod.rs":"2c9a84e7e6e5e8d8e23e28d6f2703825d7d6af59f0a16bc6125d5f0d25bd7598","src/broadcast/test.rs":"fe50fc868e67d855a9f71e078b0c3a7780e789652abb4b586accb4ccf035e872","src/compile_fail/mod.rs":"4d70256295bd64691a8c1994b323559cda1888e85f0b45ca55711541c257dcb6","src/compile_fail/quicksort_race1.rs":"35f498cda38f4eb6e00117f78ed68e0fe5a3fa61c25303d9c08a19bda345bc6c","src/compile_fail/quicksort_race2.rs":"cbb40030c7867cae34bb373b6ec5d97c2ac6de39bc917f47879b30eb423924bc","src/compile_fail/quicksort_race3.rs":"8403643e64c969306b1a9b1243378e6ccdd313b57e1878dbd31393618082fd35","src/compile_fail/rc_return.rs":"197894803d8df58fc8005d90c86b90cd98f1972f1a4b57438516a565df35903f","src/compile_fail/rc_upvar.rs":"42d110429621f407ef0dada1306dab116583d2c782a99894204dd8e0ccd2312f","src/compile_fail/scope_join_bad.rs":"892959949f77cadfc07458473e7a290301182027ca64428df5a8ce887be0892b","src/job.rs":"06de0c2add2e303b6383bf11f5f0d75775c1efe6aa7bc16de3992117f1012f09","src/join/mod.rs":"7638c0fc1da1a2d2b14673c8a2e0f87d26c24232cebee26fd334bdc2caa80886","src/join/test.rs":"157db5306e8df89a8eea19dbba499f26c2f44d9803cb36a796c852a9a695821e","src/latch.rs":"3f5c73cc6998d7cea177c19a3c7ce0d4a5667c65d77f744a2159872f09e8fba6","src/lib.rs":"d34f6cbaba40293d3b3e095bd2eae989cce3467fe686835a37e80652ca8133df","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/registry.rs":"bcfedc6d51eade2bedc30271ab8b21e98700e45f74bd8967d02ae6fe17f73a94","src/scope/mod.rs":"421a5561093928b1d0081d34c2bff78377055d8f6de0689088f52fe476d3a56a","src/scope/test.rs":"d4f068cae4ee4483b41bd3054582d96e74ced46eb57361e7510ef62d4318d340","src/sleep/README.md":"e1ac1a5556cf257f38b7654feb0615c208d9186fefbe52a584d4fe6545d7c373","src/sleep/counters.rs":"e9eccc7d76d17415156c12d30cc7bf89a5c64ca5742965bb4e6c1ce23c2782e9","src/sleep/mod.rs":"7576bc0a54c30f35b10c63a6fd23f2e33774ba994352634ea1ca7865818fb2a4","src/spawn/mod.rs":"087d2a3e5fd5dd22a780c14d71509f9eea0bac92ccfa35d9933c0b39b3e269e1","src/spawn/test.rs":"a28f8943f28a4cef642b6429c538b1df879c9eb1db9927ce69b97c686bf81173","src/test.rs":"7d0dee06fcf41bddf77449a85cece44133f966a0622a31cf3ed110fbe83e094e","src/thread_pool/mod.rs":"4c85b46eb8ba05631b658996f0d6c64247a05575c89621e0a54a1fc056cc447f","src/thread_pool/test.rs":"657b1938993eb98fb5f3fd1d02a77728e37d0e833390b4ba82926b9107ce3170","src/unwind.rs":"7baa4511467d008b14856ea8de7ced92b9251c9df4854f69c81f7efc3cf0cd6c","tests/double_init_fail.rs":"8c208ce45e83ab1dfc5890353d5b2f06fc8005684ae622827a65d05abb35a072","tests/init_zero_threads.rs":"5c7f7e0e13e9ead3733253e30d6b52ac5ee66fd6c105999d096bdf31cfccaf95","tests/scope_join.rs":"56f570c4b6a01704aacf93e7f17f89fe0f40f46ed6f9ede517abfe9adaf91f83","tests/scoped_threadpool.rs":"24d1293fe65ad5f194bbff9d1ef0486c3440d0a3783f04eaaaae4929adef5cb8","tests/simple_panic.rs":"916d40d36c1a0fad3e1dfb31550f0672641feab4b03d480f039143dbe2f2445f","tests/stack_overflow_crash.rs":"87b962c66f301ac44f808d992d4e8b861305db0c282f256761a5075c9f018243","tests/use_current_thread.rs":"fe1b981e77e422e616c09502731a70fb2f1c023d2386ef32c9d47e5a6f5bc162"},"package":"1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"746073b9ca90eedf6802af7f56e7aab9f37642f56b017d04a7a9a933ca43ae16","Cargo.toml":"60f04aab82c6489c779cf19535fddf0ec1a673edc07f523c66c10996806d2fbe","Cargo.toml.orig":"a9d3f43b19ddbac10f441a0ca8be36b8a0662c042e4592331df2670183b512f4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"7281273bea1d5fdc57731513cf9f0e3b911d06ac9905b03a8375a1324951c35b","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/broadcast/mod.rs":"2c9a84e7e6e5e8d8e23e28d6f2703825d7d6af59f0a16bc6125d5f0d25bd7598","src/broadcast/test.rs":"fe50fc868e67d855a9f71e078b0c3a7780e789652abb4b586accb4ccf035e872","src/compile_fail/mod.rs":"4d70256295bd64691a8c1994b323559cda1888e85f0b45ca55711541c257dcb6","src/compile_fail/quicksort_race1.rs":"35f498cda38f4eb6e00117f78ed68e0fe5a3fa61c25303d9c08a19bda345bc6c","src/compile_fail/quicksort_race2.rs":"cbb40030c7867cae34bb373b6ec5d97c2ac6de39bc917f47879b30eb423924bc","src/compile_fail/quicksort_race3.rs":"8403643e64c969306b1a9b1243378e6ccdd313b57e1878dbd31393618082fd35","src/compile_fail/rc_return.rs":"197894803d8df58fc8005d90c86b90cd98f1972f1a4b57438516a565df35903f","src/compile_fail/rc_upvar.rs":"42d110429621f407ef0dada1306dab116583d2c782a99894204dd8e0ccd2312f","src/compile_fail/scope_join_bad.rs":"892959949f77cadfc07458473e7a290301182027ca64428df5a8ce887be0892b","src/job.rs":"06de0c2add2e303b6383bf11f5f0d75775c1efe6aa7bc16de3992117f1012f09","src/join/mod.rs":"7638c0fc1da1a2d2b14673c8a2e0f87d26c24232cebee26fd334bdc2caa80886","src/join/test.rs":"157db5306e8df89a8eea19dbba499f26c2f44d9803cb36a796c852a9a695821e","src/latch.rs":"3f5c73cc6998d7cea177c19a3c7ce0d4a5667c65d77f744a2159872f09e8fba6","src/lib.rs":"d34f6cbaba40293d3b3e095bd2eae989cce3467fe686835a37e80652ca8133df","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/registry.rs":"bcfedc6d51eade2bedc30271ab8b21e98700e45f74bd8967d02ae6fe17f73a94","src/scope/mod.rs":"421a5561093928b1d0081d34c2bff78377055d8f6de0689088f52fe476d3a56a","src/scope/test.rs":"d4f068cae4ee4483b41bd3054582d96e74ced46eb57361e7510ef62d4318d340","src/sleep/README.md":"e1ac1a5556cf257f38b7654feb0615c208d9186fefbe52a584d4fe6545d7c373","src/sleep/counters.rs":"e9eccc7d76d17415156c12d30cc7bf89a5c64ca5742965bb4e6c1ce23c2782e9","src/sleep/mod.rs":"7576bc0a54c30f35b10c63a6fd23f2e33774ba994352634ea1ca7865818fb2a4","src/spawn/mod.rs":"087d2a3e5fd5dd22a780c14d71509f9eea0bac92ccfa35d9933c0b39b3e269e1","src/spawn/test.rs":"a28f8943f28a4cef642b6429c538b1df879c9eb1db9927ce69b97c686bf81173","src/test.rs":"7d0dee06fcf41bddf77449a85cece44133f966a0622a31cf3ed110fbe83e094e","src/thread_pool/mod.rs":"4c85b46eb8ba05631b658996f0d6c64247a05575c89621e0a54a1fc056cc447f","src/thread_pool/test.rs":"657b1938993eb98fb5f3fd1d02a77728e37d0e833390b4ba82926b9107ce3170","src/unwind.rs":"7baa4511467d008b14856ea8de7ced92b9251c9df4854f69c81f7efc3cf0cd6c","tests/double_init_fail.rs":"8c208ce45e83ab1dfc5890353d5b2f06fc8005684ae622827a65d05abb35a072","tests/init_zero_threads.rs":"5c7f7e0e13e9ead3733253e30d6b52ac5ee66fd6c105999d096bdf31cfccaf95","tests/scope_join.rs":"56f570c4b6a01704aacf93e7f17f89fe0f40f46ed6f9ede517abfe9adaf91f83","tests/scoped_threadpool.rs":"24d1293fe65ad5f194bbff9d1ef0486c3440d0a3783f04eaaaae4929adef5cb8","tests/simple_panic.rs":"916d40d36c1a0fad3e1dfb31550f0672641feab4b03d480f039143dbe2f2445f","tests/stack_overflow_crash.rs":"87b962c66f301ac44f808d992d4e8b861305db0c282f256761a5075c9f018243","tests/use_current_thread.rs":"fe1b981e77e422e616c09502731a70fb2f1c023d2386ef32c9d47e5a6f5bc162"},"package":"1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7df6d5b8493a5fdb257565cab26dacdfe08ec8aa" + }, + "path_in_vcs": "rayon-core" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rayon-core/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rayon-core/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +[package] +name = "rayon-core" +version = "1.12.1" +authors = ["Niko Matsakis ", + "Josh Stone "] +description = "Core APIs for Rayon" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rayon-rs/rayon" +documentation = "https://docs.rs/rayon/" +rust-version = "1.63" +edition = "2021" +links = "rayon-core" +build = "build.rs" +readme = "README.md" +keywords = ["parallel", "thread", "concurrency", "join", "performance"] +categories = ["concurrency"] + +# Some dependencies may not be their latest version, in order to support older rustc. +[dependencies] +crossbeam-deque = "0.8.1" +crossbeam-utils = "0.8.0" +wasm_sync = { version = "0.1.0", optional = true } + +[features] + +# This feature switches to a spin-lock implementation on the browser's +# main thread to avoid the forbidden `atomics.wait`. +# +# Only useful on the `wasm32-unknown-unknown` target. +web_spin_lock = ["dep:wasm_sync"] + +[dev-dependencies] +rand = "0.8" +rand_xorshift = "0.3" +scoped-tls = "1.0" + +[target.'cfg(unix)'.dev-dependencies] +libc = "0.2" + +[[test]] +name = "stack_overflow_crash" +path = "tests/stack_overflow_crash.rs" + +# NB: having one [[test]] manually defined means we need to declare them all + +[[test]] +name = "double_init_fail" +path = "tests/double_init_fail.rs" + +[[test]] +name = "init_zero_threads" +path = "tests/init_zero_threads.rs" + +[[test]] +name = "scope_join" +path = "tests/scope_join.rs" + +[[test]] +name = "simple_panic" +path = "tests/simple_panic.rs" + +[[test]] +name = "scoped_threadpool" +path = "tests/scoped_threadpool.rs" + +[[test]] +name = "use_current_thread" +path = "tests/use_current_thread.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"83951c87d85883eca89c05b8295fda12164b4496af8a03afed8604eb3489074e","Cargo.toml":"6a0110ee2962d5e45a14182189ab79d27557a7d83d933e91f2b5f09081cae496","Cross.toml":"4a11d6c63ecc919016b59fa0fe23674eb05682fb91ffbe677a4a7077e9e684ff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"984b116bf94decdcb0fcdeb14641b332c9fe40da63e5a256dd39eb91a2e13387","UNICODE.md":"845fca1982e82e190109a784952579fce54faea120b702b7efd61164a12f601f","bench/README.md":"0aee42206b0e5edcb400a11faa2c536f512bcc6086e5ffdda001b9bfe4d19808","record/README.md":"02e6f85f8a43f18540e4a52a75d1001494df7aceac3873e9a13e3ceba190206d","record/compile-test/2023-04-19_1.7.3.csv":"460059ba2f10456175ff92bd75d4a365b14a1843e2b46e7b285d58da59e6d3ca","record/compile-test/2023-04-20_master.csv":"6b94df278e4ed82a3fd0d4bfe92a4614714e00435e983c7649ee9f54925f906e","record/compile-test/2023-07-05.csv":"cf00b4981b8c12980113810dba40e2063a8400354ad4dab16f7c212ff0b5db74","record/compile-test/README.md":"ba2b606993edd8d705ad1677ec954862614e52b028407e1908bb5dfb07767f2d","record/old-bench-log/01-lazy-dfa/dynamic":"dec9f74b8835403c71edc0c2d93bbdde0f5a0e37d46585e416c80496d5b14497","record/old-bench-log/01-lazy-dfa/dynamic-no-lazy-dfa":"c0ce02bef9ada8cd55672f0a9c3c5fc64f71e08bfb2b45978082a140b4fc111f","record/old-bench-log/01-lazy-dfa/native":"9de61ff787e36f5c6f1eaec68b8bb0583e57b0aad23712afe8c0048988c761b8","record/old-bench-log/01-lazy-dfa/nfa":"38c0be44a00b2caef17101bc425410fec2958e4df6da25d2ba5b6664f8bccad9","record/old-bench-log/01-lazy-dfa/pcre":"3b38026c24e4ca487ff62de83cc093ccb46b918f4875663249ff84ce27636942","record/old-bench-log/02-set/dynamic":"8ef5c00f0ac42e5f008e4b6337669527b48fba38df94c50d3e683c6aac66a48c","record/old-bench-log/03-bytes/onig":"f32347a6e0f25f46ad1b0aa736c29eca47c25f90d32c8823ea0d14204859a35b","record/old-bench-log/03-bytes/pcre":"b90982575c0ad55617b2ce50c2e9853d090502bf07e1eb19edf9009d3c9f2987","record/old-bench-log/03-bytes/rust":"b1e70e5ae48a9c726d8cd8a98019c0efe5a1095563c61cf0ac75e24de32461b4","record/old-bench-log/03-bytes/rust-bytes":"fbf0e6cb8102c7ca8e59bd459bb0ae7f1feaf8103def70b8d4793c59e68e8736","record/old-bench-log/04/onig":"4e34e2ede0a806b8ee540e63e4babee38049e5a8ab3be99c4f5d8b02bbc653fd","record/old-bench-log/04/pcre1-jit":"736c4941e991ef94f76379cf2187d0ea2a41b052cf80c94d0dd0c9ea758a6491","record/old-bench-log/04/pcre2-jit":"00e7bbf7749904fca8dff9b441d15bbe670f37b427e385ddf740f7a49de3b1fb","record/old-bench-log/04/re2":"b8b8595f6b68da127b56dc7c61a9fd15548251fda1be9d2c50c2d48382e887b6","record/old-bench-log/04/rust":"c5a6b918e815294f0c4e3d37267c444d49692ff131c5a08f7462c24d0721fcec","record/old-bench-log/04/tcl":"c4d8d12b8cf48ff2017549e95e49dc95a90ea15483834cd70d2d7d7c237bbd32","record/old-bench-log/05/onig":"70a4da9aafaefa6493cd09d3a529dd5d2d9eacf390bb093681bc7be28a1f926c","record/old-bench-log/05/onig-vs-rust":"b942a79735b7330241437776c15b18f4db3eff01d3e6c35494f4a8732e74a23a","record/old-bench-log/05/pcre1":"b29b7efbe79b55ce0aaf24bbbecc376a865fa219a68d96124e3d95951cdb47f4","record/old-bench-log/05/pcre1-vs-rust":"a458e5c62f0500898e08757753c10981551649656432ec096f0c82b414ef8d82","record/old-bench-log/05/pcre2":"faa93937c3490cfdff88c32dc04e57f2ae881923b87781e5fe876535fd690770","record/old-bench-log/05/pcre2-vs-rust":"bf9faa6a679dd98e9452e52c0941d2eb84dcf0b6632c15507f8334ed7bc309da","record/old-bench-log/05/re2":"692866b28e1bc368c7a59f519b8dfe1da50a135946ce153298a0ab228a5ee59d","record/old-bench-log/05/re2-vs-rust":"55e4cb14c397574751aebe38068c429a4580a5e309857b2715047944903dca58","record/old-bench-log/05/rust":"aac6acda9f63e51613712d0a33bb7fb46dfc7adc425f76b9b71195be8c8a42e7","record/old-bench-log/05/tcl":"f03e39eccd3252162cc6099bb0426014df669d299ba0ef79e89b8401886a5172","record/old-bench-log/05/tcl-vs-rust":"ae6ac4668573bf5488cc235c5da16ad9358d07b7644207d9bcea88ba6f5514a6","record/old-bench-log/06/dphobos-dmd":"473328306be335a0320c690d9c2dbefdf7f2f5a80e4ca69443c7ed2e81bb093f","record/old-bench-log/06/dphobos-dmd-ct":"60341c736382a6db21d9889369ea4617c521acbf30d4b3bf38bcd17f4f85b9b1","record/old-bench-log/06/dphobos-ldc":"ae60c2bed84afb89ae43615f26de4cc5d0042e179089b639507378518eed3252","record/old-bench-log/06/dphobos-ldc-ct":"a157ef450793b73de3a816fab1d93a6d11e90a817082bae5e3da02a66fcc833f","record/old-bench-log/06/pcre1":"ad10fd7db732e8670dd3d4eedb05f48f547b4782495aaadff8ec25a6ea1992a0","record/old-bench-log/06/pcre2":"f789a73bd41a0bc401bdebe7f10a03a8aa587de48643d88507d16181a8fa39d3","record/old-bench-log/06/re2":"203c273a110d71f5edf722630202a6142c39d6b7a9951686adf8b9c20c5db278","record/old-bench-log/06/rust":"6a642a16cd279c99ef5a580a25fb3a63ac6239cd73df9261c02912fa08145753","record/old-bench-log/07/boost":"255bc652c4d9e9d20aa9b22d8d86e952e7ec6c8b9fcde0c3d6e38c967e04d40e","record/old-bench-log/07/dphobos-dmd":"fb3ac60037050858611145ca3e71412164688dcdec52c022787d33304e022260","record/old-bench-log/07/dphobos-dmd-ct":"40a5088441f8ffe3dae0abaf31c105cedfbe3b56c06772f075947d504976d2ed","record/old-bench-log/07/oniguruma":"ae0cd60adb15845eb9ef706111d4ee0e6ad5a58f0276b787d68bd7d637f8f7c6","record/old-bench-log/07/pcre1":"a812d065ec248249f9bb3d6d970f15c18d342f6b443265ad4b07fa91b73575cc","record/old-bench-log/07/pcre2":"88230663eccd0b382cf5be81ce1ae6cfa3fa835a65a31c1eba4369d2e8de5d27","record/old-bench-log/07/re2":"e330ef21ce44351afc3c43821d862e9c625877606569f3af0ddbadcd7b21c602","record/old-bench-log/07/rust":"d8c6bd5c46f5df9d0ac222f7be7793527a8137d273c8826b3715c67e16209aac","record/old-bench-log/07/rust-bytes":"e21d02fa2ef1e5ed7204920b33ed24c9fb620e068ed47ed6879b72e76369a27e","record/old-bench-log/07/stdcpp":"9df02d89dc8232c700b8cf8bc6f1ece3ca7af84ab52e67a660039d6c9168aed4","record/old-bench-log/07/stdcpp-libcxx":"f90849a0b5dc11dc0280ad97886e92e1d91c080403ad7a4ecd638a26fe5e8c5e","record/old-bench-log/07/tcl":"7f6e347bb507f9c00ff664d3e627c0a9cf842b416eeb2af9f3b6cccd041c58e4","record/old-bench-log/08-new-memmem/rust-after-01":"646c7d50aea9c560a35eb60116f301f4fb8d4b03fd5814d8b24adffd070332e3","record/old-bench-log/08-new-memmem/rust-after-02":"14e7fb6c6faa85a8f90617528cef79ae382aeba07c2e5c253c68445902b060ba","record/old-bench-log/08-new-memmem/rust-before-01":"7e3b58de0f502c1a1bf6d27e0e85c654b1189716f7374cec4ed4dd365b13101f","record/old-bench-log/08-new-memmem/rust-before-02":"ab6d09529eeeca7ff0da945d59701dbbcfdec5e05581bb9bf154779d12a35e53","record/old-bench-log/09-new-baseline/pcre2":"28df8e2762f267d1ea628906a6e4bbc21f99e6a445bd322c86d0ca483b21b5b3","record/old-bench-log/09-new-baseline/re2":"421437193cc3f159c178479f98bde8dbe27883ec7757b1ddd8d745862f5899ff","record/old-bench-log/09-new-baseline/rust":"6f932a769171b6cdb717c9d01e44a70762ef660c4045b9d2bb3797a9bdf65405","record/old-bench-log/09-new-baseline/rust-bytes":"9c5acd5c1eeac9acfe76d03588041f9b6d65b4351085c3510888ceeb83e8a7b5","record/old-bench-log/10-last-frontier/rust-after-literal.log":"02baef9b3b49acbbff43e81f48ea5a9287e30ff4fc298a3f3b48991d8374aabf","record/old-bench-log/10-last-frontier/rust-before-literal.log":"e5a3bcc2b9e93cf3cb27bc9e6305b3bc03215751bbeef2a70fb25577d6b42874","record/old-bench-log/10-last-frontier/rust-bytes-after-literal.log":"29834c7a5396ac61acedd07c0b7ca60716865ec3e70f35fbaa7826a2309a79d9","record/old-bench-log/10-last-frontier/rust-bytes-before-literal.log":"4e7468a3e8629814bd4af91e2a8eb42d0899d352b5dff3058b801aa637046be2","record/old-bench-log/11-regex-1.7.3/rust":"d7cc18a62070ea7a999e1ba2458f26cf94595f1af276c2b3e96cee638eccf3f0","record/old-bench-log/11-regex-1.7.3/rust-bytes":"64c7458020139bd7a03d1cb0927b741e6972377b686626563acb86fbc66414ca","record/old-bench-log/12-regex-1.8.1/rust":"a538c42e77e20956e81fb5a4e2e1e7d3fdf60da019d7e3df52d93f57367a3fbd","record/old-bench-log/12-regex-1.8.1/rust-bytes":"fbb00fdf8f039ce312f5346a67dddaa5e129280a93a90d7aaf6b5a9a71d2f212","record/old-bench-log/13-regex-1.9.0/rust":"0ef62700ba3fc24887af74b7942490c90b4cd2814b8fda200f7376e43391bfce","record/old-bench-log/13-regex-1.9.0/rust-bytes":"676d501d4667f0a945c88ebb56839176dd3a5a6b45af7708b1e870bf26d12603","record/old-bench-log/README.md":"d359f536fb4b8c1af9af3465a027c3522f62c3871aad44645a955b650d7deec0","record/old-bench-log/old/01-before":"c2ea2750fca8ac1742003fe2106e9422d49e92967d3fe0267f24b7ec830b07e3","record/old-bench-log/old/02-new-syntax-crate":"27fd8b3d35cf08d434035ff7d9f2e9e3c94a167e45ba655567c73ae96830f1d8","record/old-bench-log/old/03-new-syntax-crate":"d942a2b95c3a2d8f85f3f17934f258bdc84baa33e91986e8a6810ca8d6e9cc50","record/old-bench-log/old/04-fixed-benchmark":"0da29ef39ac07ece411c151ab479a76944946aba992547b15d90ec2d5484e85c","record/old-bench-log/old/05-thread-caching":"e364d87131e43187d6757426839789d1b6b47b3f3af21280daa9193d5ab19f64","record/old-bench-log/old/06-major-dynamic":"3bc2b8fd2714ae9f19b2e4f4219654982522daf01b5d3055b4aec0458afeaf13","record/old-bench-log/old/06-major-macro":"d5617ed23e71d5298ed4d629eee257e401c352fd1c91a2048dfeb1677527d4e7","record/old-bench-log/old/07-prefix-improvements":"9277d1392c85a38db215a9b69e3b0cd4a9901f8f1c72c706ca262e5f099b8819","record/old-bench-log/old/08-case-fixes":"f97cd3675cf5c967e4ca8841f2368e9eadf538b542bfe3035d31492afc5934bf","record/old-bench-log/old/09-before-compiler-rewrite":"b928686819dbd9aeaa6639b01b63a48428653f2f676a4e15d61cddec421e0389","record/old-bench-log/old/10-compiler-rewrite":"697b295ee377a5cb287d403593bfb8c078270b4e19e8d61d0b95b06ee7c903ab","record/old-bench-log/old/11-compiler-rewrite":"3f0ba494a0d82e7419285a9686474dc7763d4da0dd3faaa3bec3f624bbede481","record/old-bench-log/old/12-executor":"962e182f9a1cfddb8c0cd2d8c4681febef1430082c9a38e5373c9117b853e65e","record/old-bench-log/old/12-executor-bytes":"e01a1e878b44c80724e9bf09bb11210eeb8f01518ac7f0e3e7f2ee241281e500","record/old-bench-log/old/13-cache-byte-range-suffixes":"1d67d58a39f9177a79c26f3c6c2a1caaf51f085ce137711ab9ba74071c14680c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/builders.rs":"6dbff8c7ff7febe031dbef3eafe1f02a15112ff1ffd889761a21c10b0dd84f03","src/bytes.rs":"cce2b7012f5896cf82fc3086bf8128dc9efe2b69bf6917d041c1a171eabacdc0","src/error.rs":"4ac8361e900627a87a2ac78e5d475be17c455fe6850d1515bf5b874837c4ae25","src/find_byte.rs":"e17cd3b765467685946707840b92ea4e37d3c11081fbf316174a15858cd4bd99","src/lib.rs":"1be6ce04d4fce06a7e46bc006bbf536f5a7f82d97dc71e7f7489a6d2610f790b","src/pattern.rs":"5f37755a7c16902d861377645f57a20314961f86298d4b35ae6e1058ca4e9801","src/regex/bytes.rs":"4f972859085728abd44c33a04e5734059483822f88c68a9d68c30643143f123c","src/regex/mod.rs":"c220b6dd7a5e1945f8e743d1dcd796c5f782c91b0c34eb9915c588174a517fe8","src/regex/string.rs":"787f776b2e400e1984ce12c0054ac334a532bcb091ddc02d4fdae0ed131551ec","src/regexset/bytes.rs":"6290dd81f47fb6cdbaa358be2340398a2a640320373d334e4c977bf30b5a9220","src/regexset/mod.rs":"c220b6dd7a5e1945f8e743d1dcd796c5f782c91b0c34eb9915c588174a517fe8","src/regexset/string.rs":"977bc167c48c7c99187599c5071ca197e61a56359d32a26b9dbc1b58a5ef1c4d","test":"c0122c20a2c9b7ba6e9a8aaeb2b7d9910315ef31063539949f28d9501ef3193c","testdata/README.md":"c0514501526560d7f6171eb6d982ad61b4527760cb38a4bfbe8e28036ff37b95","testdata/anchored.toml":"7a1b5cd81deed2099796a451bf764a3f9bd21f0d60c0fa46accd3a35666866f2","testdata/bytes.toml":"1d84179165fd25f3b94bd2bfbeb43fc8a162041f7bf98b717e0f85cef7fb652b","testdata/crazy.toml":"a146e2d2e23f1a57168979d9b1fc193c2ba38dca66294b61140d6d2a2958ec86","testdata/crlf.toml":"d19cf22756434d145dd20946c00af01c102a556a252070405c3c8294129d9ece","testdata/earliest.toml":"d561e643623ee1889b5b049fdcf3c7cb71b0c746d7eb822ddbd09d0acda2620b","testdata/empty.toml":"738dbe92fbd8971385a1cf3affb0e956e5b692c858b9b48439d718f10801c08e","testdata/expensive.toml":"5ce2f60209c99cdd2cdcb9d3069d1d5ca13d5e08a85e913efe57267b2f5f0e9d","testdata/flags.toml":"9a7e001808195c84f2a7d3e18bc0a82c7386e60f03a616e99af00c3f7f2c3fd4","testdata/fowler/basic.toml":"a82c7e233451cd7cfe0c3d817f3a1ab44478bb81ae62432efdd515fa8370275e","testdata/fowler/dat/README":"e53d6c37b5931cb26dc9ae4c40358eea63f7a469c4db6ca816c072a8ced6a61a","testdata/fowler/dat/basic.dat":"b1126dda59075c08f574987090273c9977790115f1e1941d0708c0b82b256905","testdata/fowler/dat/nullsubexpr.dat":"e5cd4145dffa8bc66f2d39079950b2bb7bae21a521514b83b557b92f4a871a9e","testdata/fowler/dat/repetition.dat":"2b8b2b191229a804fba49e6b888d8194bf488f7744057b550da9d95a2aa6617a","testdata/fowler/nullsubexpr.toml":"cd812e7e8fa0469253b34f0db93b5883c9d8b9740fc4f7825a38e7df880a4eed","testdata/fowler/repetition.toml":"8c09164f064b3db81309c53483863bdcec493781644de162416e9f485e772615","testdata/iter.toml":"6875460302974a5b3073a7304a865c45aba9653c54afea2c4d26e1ea248a81f7","testdata/leftmost-all.toml":"903bfbeff888b7664296f4d5aa367ce53d1dafe249ab0a3359223ae94d596396","testdata/line-terminator.toml":"02148068137b69d95587966917bdf0697bf7eb41ad6d47387f2eb30f67d04fd9","testdata/misc.toml":"32c9591655c6fb118dfefcb4de49a04820a63cb960533dfc2538cdaabf4f4047","testdata/multiline.toml":"eb07cf5427e6ddbcf61f4cc64c2d74ff41b5ef75ef857959651b20196f3cd157","testdata/no-unicode.toml":"d209da04506900fd5f69e48170cddaad0702355ac6176c3a75ab3ff96974457c","testdata/overlapping.toml":"5d96497a7233566d40b05ba22047e483fa8662e45515a9be86da45cf6c28703a","testdata/regex-lite.toml":"fecca7cc8c9cea2e1f84f846a89fd9b3ca7011c83698211a2eeda8924deb900c","testdata/regression.toml":"6006ef4fcfbfd7155ce5ce8b8427904f7261c5549396f20cb065c0294733686d","testdata/set.toml":"dfd265dc1aee80026e881616840df0236ae9abf12467d7ec0e141a52c236128c","testdata/substring.toml":"48122d9f3477ed81f95e3ad42c06e9bb25f849b66994601a75ceae0693b81866","testdata/unicode.toml":"7e4b013039b0cdd85fa73f32d15d096182fe901643d4e40c0910087a736cd46d","testdata/utf8.toml":"2eabce0582bcacb2073e08bbe7ca413f096d14d06e917b107949691e24f84b20","testdata/word-boundary-special.toml":"7d0ea2f796478d1ca2a6954430cb1cfbd04031a182f8611cb50a7c73e443ce33","testdata/word-boundary.toml":"51bc1c498ab825420340a2dd3e6623de4054937ba6d5020ff8cd14b1c1e45271","tests/fuzz/mod.rs":"7b01a803e1c0b5a45c062d493723553f263c57e269eade1475eb789694635d5c","tests/fuzz/testdata/crash-7eb3351f0965e5d6c1cb98aa8585949ef96531ff":"be4f42497ac9358eb020bf17cd8fdb9743691824e01d744504613ea2bfb2f663","tests/fuzz/testdata/crash-8760b19b25d74e3603d4c643e9c7404fdd3631f9":"19df9a1e1b5a3c0f31cc038b9f2991b161d8577b4a0c8b2fc391cdfecdb6dd85","tests/fuzz/testdata/crash-cd33b13df59ea9d74503986f9d32a270dd43cc04":"2fde1668e9e3e60943c28d97c01c90dd3d3882f48475f060ccaf961c228069e8","tests/fuzz/testdata/minimized-from-8760b19b25d74e3603d4c643e9c7404fdd3631f9":"c9e00f7a31453708560900aa51e358dd5551df494439860594be97bb1fb933ba","tests/fuzz/testdata/slow-unit-3ab758ea520027fefd3f00e1384d9aeef155739e":"4433011f7af46e855e843635cf24a49713bd5705f67176ed928f04d24eda1857","tests/fuzz/testdata/slow-unit-5345fccadf3812c53c3ccc7af5aa2741b7b2106c":"95782a847fc64e9cccdf76e9540b0d16ce80db5d05157a88b958b763f9b8479b","tests/fuzz/testdata/slow-unit-6bd643eec330166e4ada91da2d3f284268481085":"8ddff12288f6f20cc9d65db76bd8187834f64f844aad48a340d082555ad5cb56","tests/fuzz/testdata/slow-unit-93c73a43581f205f9aaffd9c17e52b34b17becd0":"eea6919a75fde163634b890e2253a0918cf0ba092357fa617f368bbfa131ba30","tests/fuzz/testdata/slow-unit-9ca9cc9929fee1fcbb847a78384effb8b98ea18a":"a806f73b900046977267acceb83b105bac7ee21ede2edc2927afe1e1f0149f00","tests/fuzz/testdata/slow-unit-b8a052f4254802edbe5f569b6ce6e9b6c927e9d6":"9540cf58241cde3bc0db8364e0ccff67ff1ff9721c85b0d2ca27354c0cbf2650","tests/lib.rs":"9bffc95568c09ac95b6a3e7ca64b6e858a0552d0c0b0fca2c447da3b9c0a45a2","tests/misc.rs":"5ac5858325451e1d70f308ca0bcead5a354d095a7473800c11065231c319c456","tests/regression.rs":"3490aac99fdbf3f0949ba1f338d5184a84b505ebd96d0b6d6145c610587aa60b","tests/regression_fuzz.rs":"57e0bcba0fdfa7797865e35ae547cd7fe1c6132b80a7bfdfb06eb053a568b00d","tests/replace.rs":"78ff9bf7f78783ad83a78041bb7ee0705c7efc85b4d12301581d0ce5b2a59325","tests/searcher.rs":"04152e5c86431deec0c196d2564a11bc4ec36f14c77e8c16a2f9d1cbc9fc574e","tests/suite_bytes.rs":"7697b04e5b181aa78b3654bd2dbe1c792d9626197573ed8c649f1da8b481817d","tests/suite_bytes_set.rs":"d970168fab57a9edc60ff26a2bb7d0cc714d4298e4ee9eadba9da44a6569f2bb","tests/suite_string.rs":"1be0cf8922171f8323f99e8ecedbbf1846d339620d0dc2fd490901cbbbd2622e","tests/suite_string_set.rs":"22743107206d913521f9adb728482aed3a9625ff7b15a83df057bbf1f7050e03"},"package":"c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"08e5484724f13b0aa4cd80da16b83424e17dd9cd7b0c8e24ac4c133636eb6b91",".vim/coc-settings.json":"87b0e2edd6fc8170b3f918bfbf92a78cd77a15033f718a8733c6d6277bf3e1fe","CHANGELOG.md":"83951c87d85883eca89c05b8295fda12164b4496af8a03afed8604eb3489074e","Cargo.toml":"6a0110ee2962d5e45a14182189ab79d27557a7d83d933e91f2b5f09081cae496","Cargo.toml.orig":"c1ca4e5da2342ba5e4ef8afa8830a1938be0a8d36e6ee96bce35235ae6905cd0","Cross.toml":"4a11d6c63ecc919016b59fa0fe23674eb05682fb91ffbe677a4a7077e9e684ff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"984b116bf94decdcb0fcdeb14641b332c9fe40da63e5a256dd39eb91a2e13387","UNICODE.md":"845fca1982e82e190109a784952579fce54faea120b702b7efd61164a12f601f","bench/README.md":"0aee42206b0e5edcb400a11faa2c536f512bcc6086e5ffdda001b9bfe4d19808","record/README.md":"02e6f85f8a43f18540e4a52a75d1001494df7aceac3873e9a13e3ceba190206d","record/compile-test/2023-04-19_1.7.3.csv":"460059ba2f10456175ff92bd75d4a365b14a1843e2b46e7b285d58da59e6d3ca","record/compile-test/2023-04-20_master.csv":"6b94df278e4ed82a3fd0d4bfe92a4614714e00435e983c7649ee9f54925f906e","record/compile-test/2023-07-05.csv":"cf00b4981b8c12980113810dba40e2063a8400354ad4dab16f7c212ff0b5db74","record/compile-test/README.md":"ba2b606993edd8d705ad1677ec954862614e52b028407e1908bb5dfb07767f2d","record/old-bench-log/.gitignore":"613306d0912cda4c64f06418e3ffa91ef73ea6e19bc2527211a551b6fa23790f","record/old-bench-log/01-lazy-dfa/dynamic":"dec9f74b8835403c71edc0c2d93bbdde0f5a0e37d46585e416c80496d5b14497","record/old-bench-log/01-lazy-dfa/dynamic-no-lazy-dfa":"c0ce02bef9ada8cd55672f0a9c3c5fc64f71e08bfb2b45978082a140b4fc111f","record/old-bench-log/01-lazy-dfa/native":"9de61ff787e36f5c6f1eaec68b8bb0583e57b0aad23712afe8c0048988c761b8","record/old-bench-log/01-lazy-dfa/nfa":"38c0be44a00b2caef17101bc425410fec2958e4df6da25d2ba5b6664f8bccad9","record/old-bench-log/01-lazy-dfa/pcre":"3b38026c24e4ca487ff62de83cc093ccb46b918f4875663249ff84ce27636942","record/old-bench-log/02-set/dynamic":"8ef5c00f0ac42e5f008e4b6337669527b48fba38df94c50d3e683c6aac66a48c","record/old-bench-log/03-bytes/onig":"f32347a6e0f25f46ad1b0aa736c29eca47c25f90d32c8823ea0d14204859a35b","record/old-bench-log/03-bytes/pcre":"b90982575c0ad55617b2ce50c2e9853d090502bf07e1eb19edf9009d3c9f2987","record/old-bench-log/03-bytes/rust":"b1e70e5ae48a9c726d8cd8a98019c0efe5a1095563c61cf0ac75e24de32461b4","record/old-bench-log/03-bytes/rust-bytes":"fbf0e6cb8102c7ca8e59bd459bb0ae7f1feaf8103def70b8d4793c59e68e8736","record/old-bench-log/04/onig":"4e34e2ede0a806b8ee540e63e4babee38049e5a8ab3be99c4f5d8b02bbc653fd","record/old-bench-log/04/pcre1-jit":"736c4941e991ef94f76379cf2187d0ea2a41b052cf80c94d0dd0c9ea758a6491","record/old-bench-log/04/pcre2-jit":"00e7bbf7749904fca8dff9b441d15bbe670f37b427e385ddf740f7a49de3b1fb","record/old-bench-log/04/re2":"b8b8595f6b68da127b56dc7c61a9fd15548251fda1be9d2c50c2d48382e887b6","record/old-bench-log/04/rust":"c5a6b918e815294f0c4e3d37267c444d49692ff131c5a08f7462c24d0721fcec","record/old-bench-log/04/tcl":"c4d8d12b8cf48ff2017549e95e49dc95a90ea15483834cd70d2d7d7c237bbd32","record/old-bench-log/05/onig":"70a4da9aafaefa6493cd09d3a529dd5d2d9eacf390bb093681bc7be28a1f926c","record/old-bench-log/05/onig-vs-rust":"b942a79735b7330241437776c15b18f4db3eff01d3e6c35494f4a8732e74a23a","record/old-bench-log/05/pcre1":"b29b7efbe79b55ce0aaf24bbbecc376a865fa219a68d96124e3d95951cdb47f4","record/old-bench-log/05/pcre1-vs-rust":"a458e5c62f0500898e08757753c10981551649656432ec096f0c82b414ef8d82","record/old-bench-log/05/pcre2":"faa93937c3490cfdff88c32dc04e57f2ae881923b87781e5fe876535fd690770","record/old-bench-log/05/pcre2-vs-rust":"bf9faa6a679dd98e9452e52c0941d2eb84dcf0b6632c15507f8334ed7bc309da","record/old-bench-log/05/re2":"692866b28e1bc368c7a59f519b8dfe1da50a135946ce153298a0ab228a5ee59d","record/old-bench-log/05/re2-vs-rust":"55e4cb14c397574751aebe38068c429a4580a5e309857b2715047944903dca58","record/old-bench-log/05/rust":"aac6acda9f63e51613712d0a33bb7fb46dfc7adc425f76b9b71195be8c8a42e7","record/old-bench-log/05/tcl":"f03e39eccd3252162cc6099bb0426014df669d299ba0ef79e89b8401886a5172","record/old-bench-log/05/tcl-vs-rust":"ae6ac4668573bf5488cc235c5da16ad9358d07b7644207d9bcea88ba6f5514a6","record/old-bench-log/06/dphobos-dmd":"473328306be335a0320c690d9c2dbefdf7f2f5a80e4ca69443c7ed2e81bb093f","record/old-bench-log/06/dphobos-dmd-ct":"60341c736382a6db21d9889369ea4617c521acbf30d4b3bf38bcd17f4f85b9b1","record/old-bench-log/06/dphobos-ldc":"ae60c2bed84afb89ae43615f26de4cc5d0042e179089b639507378518eed3252","record/old-bench-log/06/dphobos-ldc-ct":"a157ef450793b73de3a816fab1d93a6d11e90a817082bae5e3da02a66fcc833f","record/old-bench-log/06/pcre1":"ad10fd7db732e8670dd3d4eedb05f48f547b4782495aaadff8ec25a6ea1992a0","record/old-bench-log/06/pcre2":"f789a73bd41a0bc401bdebe7f10a03a8aa587de48643d88507d16181a8fa39d3","record/old-bench-log/06/re2":"203c273a110d71f5edf722630202a6142c39d6b7a9951686adf8b9c20c5db278","record/old-bench-log/06/rust":"6a642a16cd279c99ef5a580a25fb3a63ac6239cd73df9261c02912fa08145753","record/old-bench-log/07/boost":"255bc652c4d9e9d20aa9b22d8d86e952e7ec6c8b9fcde0c3d6e38c967e04d40e","record/old-bench-log/07/dphobos-dmd":"fb3ac60037050858611145ca3e71412164688dcdec52c022787d33304e022260","record/old-bench-log/07/dphobos-dmd-ct":"40a5088441f8ffe3dae0abaf31c105cedfbe3b56c06772f075947d504976d2ed","record/old-bench-log/07/oniguruma":"ae0cd60adb15845eb9ef706111d4ee0e6ad5a58f0276b787d68bd7d637f8f7c6","record/old-bench-log/07/pcre1":"a812d065ec248249f9bb3d6d970f15c18d342f6b443265ad4b07fa91b73575cc","record/old-bench-log/07/pcre2":"88230663eccd0b382cf5be81ce1ae6cfa3fa835a65a31c1eba4369d2e8de5d27","record/old-bench-log/07/re2":"e330ef21ce44351afc3c43821d862e9c625877606569f3af0ddbadcd7b21c602","record/old-bench-log/07/rust":"d8c6bd5c46f5df9d0ac222f7be7793527a8137d273c8826b3715c67e16209aac","record/old-bench-log/07/rust-bytes":"e21d02fa2ef1e5ed7204920b33ed24c9fb620e068ed47ed6879b72e76369a27e","record/old-bench-log/07/stdcpp":"9df02d89dc8232c700b8cf8bc6f1ece3ca7af84ab52e67a660039d6c9168aed4","record/old-bench-log/07/stdcpp-libcxx":"f90849a0b5dc11dc0280ad97886e92e1d91c080403ad7a4ecd638a26fe5e8c5e","record/old-bench-log/07/tcl":"7f6e347bb507f9c00ff664d3e627c0a9cf842b416eeb2af9f3b6cccd041c58e4","record/old-bench-log/08-new-memmem/rust-after-01":"646c7d50aea9c560a35eb60116f301f4fb8d4b03fd5814d8b24adffd070332e3","record/old-bench-log/08-new-memmem/rust-after-02":"14e7fb6c6faa85a8f90617528cef79ae382aeba07c2e5c253c68445902b060ba","record/old-bench-log/08-new-memmem/rust-before-01":"7e3b58de0f502c1a1bf6d27e0e85c654b1189716f7374cec4ed4dd365b13101f","record/old-bench-log/08-new-memmem/rust-before-02":"ab6d09529eeeca7ff0da945d59701dbbcfdec5e05581bb9bf154779d12a35e53","record/old-bench-log/09-new-baseline/pcre2":"28df8e2762f267d1ea628906a6e4bbc21f99e6a445bd322c86d0ca483b21b5b3","record/old-bench-log/09-new-baseline/re2":"421437193cc3f159c178479f98bde8dbe27883ec7757b1ddd8d745862f5899ff","record/old-bench-log/09-new-baseline/rust":"6f932a769171b6cdb717c9d01e44a70762ef660c4045b9d2bb3797a9bdf65405","record/old-bench-log/09-new-baseline/rust-bytes":"9c5acd5c1eeac9acfe76d03588041f9b6d65b4351085c3510888ceeb83e8a7b5","record/old-bench-log/10-last-frontier/rust-after-literal.log":"02baef9b3b49acbbff43e81f48ea5a9287e30ff4fc298a3f3b48991d8374aabf","record/old-bench-log/10-last-frontier/rust-before-literal.log":"e5a3bcc2b9e93cf3cb27bc9e6305b3bc03215751bbeef2a70fb25577d6b42874","record/old-bench-log/10-last-frontier/rust-bytes-after-literal.log":"29834c7a5396ac61acedd07c0b7ca60716865ec3e70f35fbaa7826a2309a79d9","record/old-bench-log/10-last-frontier/rust-bytes-before-literal.log":"4e7468a3e8629814bd4af91e2a8eb42d0899d352b5dff3058b801aa637046be2","record/old-bench-log/11-regex-1.7.3/rust":"d7cc18a62070ea7a999e1ba2458f26cf94595f1af276c2b3e96cee638eccf3f0","record/old-bench-log/11-regex-1.7.3/rust-bytes":"64c7458020139bd7a03d1cb0927b741e6972377b686626563acb86fbc66414ca","record/old-bench-log/12-regex-1.8.1/rust":"a538c42e77e20956e81fb5a4e2e1e7d3fdf60da019d7e3df52d93f57367a3fbd","record/old-bench-log/12-regex-1.8.1/rust-bytes":"fbb00fdf8f039ce312f5346a67dddaa5e129280a93a90d7aaf6b5a9a71d2f212","record/old-bench-log/13-regex-1.9.0/rust":"0ef62700ba3fc24887af74b7942490c90b4cd2814b8fda200f7376e43391bfce","record/old-bench-log/13-regex-1.9.0/rust-bytes":"676d501d4667f0a945c88ebb56839176dd3a5a6b45af7708b1e870bf26d12603","record/old-bench-log/README.md":"d359f536fb4b8c1af9af3465a027c3522f62c3871aad44645a955b650d7deec0","record/old-bench-log/old/01-before":"c2ea2750fca8ac1742003fe2106e9422d49e92967d3fe0267f24b7ec830b07e3","record/old-bench-log/old/02-new-syntax-crate":"27fd8b3d35cf08d434035ff7d9f2e9e3c94a167e45ba655567c73ae96830f1d8","record/old-bench-log/old/03-new-syntax-crate":"d942a2b95c3a2d8f85f3f17934f258bdc84baa33e91986e8a6810ca8d6e9cc50","record/old-bench-log/old/04-fixed-benchmark":"0da29ef39ac07ece411c151ab479a76944946aba992547b15d90ec2d5484e85c","record/old-bench-log/old/05-thread-caching":"e364d87131e43187d6757426839789d1b6b47b3f3af21280daa9193d5ab19f64","record/old-bench-log/old/06-major-dynamic":"3bc2b8fd2714ae9f19b2e4f4219654982522daf01b5d3055b4aec0458afeaf13","record/old-bench-log/old/06-major-macro":"d5617ed23e71d5298ed4d629eee257e401c352fd1c91a2048dfeb1677527d4e7","record/old-bench-log/old/07-prefix-improvements":"9277d1392c85a38db215a9b69e3b0cd4a9901f8f1c72c706ca262e5f099b8819","record/old-bench-log/old/08-case-fixes":"f97cd3675cf5c967e4ca8841f2368e9eadf538b542bfe3035d31492afc5934bf","record/old-bench-log/old/09-before-compiler-rewrite":"b928686819dbd9aeaa6639b01b63a48428653f2f676a4e15d61cddec421e0389","record/old-bench-log/old/10-compiler-rewrite":"697b295ee377a5cb287d403593bfb8c078270b4e19e8d61d0b95b06ee7c903ab","record/old-bench-log/old/11-compiler-rewrite":"3f0ba494a0d82e7419285a9686474dc7763d4da0dd3faaa3bec3f624bbede481","record/old-bench-log/old/12-executor":"962e182f9a1cfddb8c0cd2d8c4681febef1430082c9a38e5373c9117b853e65e","record/old-bench-log/old/12-executor-bytes":"e01a1e878b44c80724e9bf09bb11210eeb8f01518ac7f0e3e7f2ee241281e500","record/old-bench-log/old/13-cache-byte-range-suffixes":"1d67d58a39f9177a79c26f3c6c2a1caaf51f085ce137711ab9ba74071c14680c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/builders.rs":"6dbff8c7ff7febe031dbef3eafe1f02a15112ff1ffd889761a21c10b0dd84f03","src/bytes.rs":"cce2b7012f5896cf82fc3086bf8128dc9efe2b69bf6917d041c1a171eabacdc0","src/error.rs":"4ac8361e900627a87a2ac78e5d475be17c455fe6850d1515bf5b874837c4ae25","src/find_byte.rs":"e17cd3b765467685946707840b92ea4e37d3c11081fbf316174a15858cd4bd99","src/lib.rs":"1be6ce04d4fce06a7e46bc006bbf536f5a7f82d97dc71e7f7489a6d2610f790b","src/pattern.rs":"5f37755a7c16902d861377645f57a20314961f86298d4b35ae6e1058ca4e9801","src/regex/bytes.rs":"4f972859085728abd44c33a04e5734059483822f88c68a9d68c30643143f123c","src/regex/mod.rs":"c220b6dd7a5e1945f8e743d1dcd796c5f782c91b0c34eb9915c588174a517fe8","src/regex/string.rs":"787f776b2e400e1984ce12c0054ac334a532bcb091ddc02d4fdae0ed131551ec","src/regexset/bytes.rs":"6290dd81f47fb6cdbaa358be2340398a2a640320373d334e4c977bf30b5a9220","src/regexset/mod.rs":"c220b6dd7a5e1945f8e743d1dcd796c5f782c91b0c34eb9915c588174a517fe8","src/regexset/string.rs":"977bc167c48c7c99187599c5071ca197e61a56359d32a26b9dbc1b58a5ef1c4d","test":"c0122c20a2c9b7ba6e9a8aaeb2b7d9910315ef31063539949f28d9501ef3193c","testdata/README.md":"c0514501526560d7f6171eb6d982ad61b4527760cb38a4bfbe8e28036ff37b95","testdata/anchored.toml":"7a1b5cd81deed2099796a451bf764a3f9bd21f0d60c0fa46accd3a35666866f2","testdata/bytes.toml":"1d84179165fd25f3b94bd2bfbeb43fc8a162041f7bf98b717e0f85cef7fb652b","testdata/crazy.toml":"a146e2d2e23f1a57168979d9b1fc193c2ba38dca66294b61140d6d2a2958ec86","testdata/crlf.toml":"d19cf22756434d145dd20946c00af01c102a556a252070405c3c8294129d9ece","testdata/earliest.toml":"d561e643623ee1889b5b049fdcf3c7cb71b0c746d7eb822ddbd09d0acda2620b","testdata/empty.toml":"738dbe92fbd8971385a1cf3affb0e956e5b692c858b9b48439d718f10801c08e","testdata/expensive.toml":"5ce2f60209c99cdd2cdcb9d3069d1d5ca13d5e08a85e913efe57267b2f5f0e9d","testdata/flags.toml":"9a7e001808195c84f2a7d3e18bc0a82c7386e60f03a616e99af00c3f7f2c3fd4","testdata/fowler/basic.toml":"a82c7e233451cd7cfe0c3d817f3a1ab44478bb81ae62432efdd515fa8370275e","testdata/fowler/dat/README":"e53d6c37b5931cb26dc9ae4c40358eea63f7a469c4db6ca816c072a8ced6a61a","testdata/fowler/dat/basic.dat":"b1126dda59075c08f574987090273c9977790115f1e1941d0708c0b82b256905","testdata/fowler/dat/nullsubexpr.dat":"e5cd4145dffa8bc66f2d39079950b2bb7bae21a521514b83b557b92f4a871a9e","testdata/fowler/dat/repetition.dat":"2b8b2b191229a804fba49e6b888d8194bf488f7744057b550da9d95a2aa6617a","testdata/fowler/nullsubexpr.toml":"cd812e7e8fa0469253b34f0db93b5883c9d8b9740fc4f7825a38e7df880a4eed","testdata/fowler/repetition.toml":"8c09164f064b3db81309c53483863bdcec493781644de162416e9f485e772615","testdata/iter.toml":"6875460302974a5b3073a7304a865c45aba9653c54afea2c4d26e1ea248a81f7","testdata/leftmost-all.toml":"903bfbeff888b7664296f4d5aa367ce53d1dafe249ab0a3359223ae94d596396","testdata/line-terminator.toml":"02148068137b69d95587966917bdf0697bf7eb41ad6d47387f2eb30f67d04fd9","testdata/misc.toml":"32c9591655c6fb118dfefcb4de49a04820a63cb960533dfc2538cdaabf4f4047","testdata/multiline.toml":"eb07cf5427e6ddbcf61f4cc64c2d74ff41b5ef75ef857959651b20196f3cd157","testdata/no-unicode.toml":"d209da04506900fd5f69e48170cddaad0702355ac6176c3a75ab3ff96974457c","testdata/overlapping.toml":"5d96497a7233566d40b05ba22047e483fa8662e45515a9be86da45cf6c28703a","testdata/regex-lite.toml":"fecca7cc8c9cea2e1f84f846a89fd9b3ca7011c83698211a2eeda8924deb900c","testdata/regression.toml":"6006ef4fcfbfd7155ce5ce8b8427904f7261c5549396f20cb065c0294733686d","testdata/set.toml":"dfd265dc1aee80026e881616840df0236ae9abf12467d7ec0e141a52c236128c","testdata/substring.toml":"48122d9f3477ed81f95e3ad42c06e9bb25f849b66994601a75ceae0693b81866","testdata/unicode.toml":"7e4b013039b0cdd85fa73f32d15d096182fe901643d4e40c0910087a736cd46d","testdata/utf8.toml":"2eabce0582bcacb2073e08bbe7ca413f096d14d06e917b107949691e24f84b20","testdata/word-boundary-special.toml":"7d0ea2f796478d1ca2a6954430cb1cfbd04031a182f8611cb50a7c73e443ce33","testdata/word-boundary.toml":"51bc1c498ab825420340a2dd3e6623de4054937ba6d5020ff8cd14b1c1e45271","tests/fuzz/mod.rs":"7b01a803e1c0b5a45c062d493723553f263c57e269eade1475eb789694635d5c","tests/fuzz/testdata/crash-7eb3351f0965e5d6c1cb98aa8585949ef96531ff":"be4f42497ac9358eb020bf17cd8fdb9743691824e01d744504613ea2bfb2f663","tests/fuzz/testdata/crash-8760b19b25d74e3603d4c643e9c7404fdd3631f9":"19df9a1e1b5a3c0f31cc038b9f2991b161d8577b4a0c8b2fc391cdfecdb6dd85","tests/fuzz/testdata/crash-cd33b13df59ea9d74503986f9d32a270dd43cc04":"2fde1668e9e3e60943c28d97c01c90dd3d3882f48475f060ccaf961c228069e8","tests/fuzz/testdata/minimized-from-8760b19b25d74e3603d4c643e9c7404fdd3631f9":"c9e00f7a31453708560900aa51e358dd5551df494439860594be97bb1fb933ba","tests/fuzz/testdata/slow-unit-3ab758ea520027fefd3f00e1384d9aeef155739e":"4433011f7af46e855e843635cf24a49713bd5705f67176ed928f04d24eda1857","tests/fuzz/testdata/slow-unit-5345fccadf3812c53c3ccc7af5aa2741b7b2106c":"95782a847fc64e9cccdf76e9540b0d16ce80db5d05157a88b958b763f9b8479b","tests/fuzz/testdata/slow-unit-6bd643eec330166e4ada91da2d3f284268481085":"8ddff12288f6f20cc9d65db76bd8187834f64f844aad48a340d082555ad5cb56","tests/fuzz/testdata/slow-unit-93c73a43581f205f9aaffd9c17e52b34b17becd0":"eea6919a75fde163634b890e2253a0918cf0ba092357fa617f368bbfa131ba30","tests/fuzz/testdata/slow-unit-9ca9cc9929fee1fcbb847a78384effb8b98ea18a":"a806f73b900046977267acceb83b105bac7ee21ede2edc2927afe1e1f0149f00","tests/fuzz/testdata/slow-unit-b8a052f4254802edbe5f569b6ce6e9b6c927e9d6":"9540cf58241cde3bc0db8364e0ccff67ff1ff9721c85b0d2ca27354c0cbf2650","tests/lib.rs":"9bffc95568c09ac95b6a3e7ca64b6e858a0552d0c0b0fca2c447da3b9c0a45a2","tests/misc.rs":"5ac5858325451e1d70f308ca0bcead5a354d095a7473800c11065231c319c456","tests/regression.rs":"3490aac99fdbf3f0949ba1f338d5184a84b505ebd96d0b6d6145c610587aa60b","tests/regression_fuzz.rs":"57e0bcba0fdfa7797865e35ae547cd7fe1c6132b80a7bfdfb06eb053a568b00d","tests/replace.rs":"78ff9bf7f78783ad83a78041bb7ee0705c7efc85b4d12301581d0ce5b2a59325","tests/searcher.rs":"04152e5c86431deec0c196d2564a11bc4ec36f14c77e8c16a2f9d1cbc9fc574e","tests/suite_bytes.rs":"7697b04e5b181aa78b3654bd2dbe1c792d9626197573ed8c649f1da8b481817d","tests/suite_bytes_set.rs":"d970168fab57a9edc60ff26a2bb7d0cc714d4298e4ee9eadba9da44a6569f2bb","tests/suite_string.rs":"1be0cf8922171f8323f99e8ecedbbf1846d339620d0dc2fd490901cbbbd2622e","tests/suite_string_set.rs":"22743107206d913521f9adb728482aed3a9625ff7b15a83df057bbf1f7050e03"},"package":"c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "aa2d8bd8be283471b17b4ab6faeae5b751553572" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex/.vim/coc-settings.json clamav-1.4.6+dfsg/.cargo/vendor/regex/.vim/coc-settings.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex/.vim/coc-settings.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex/.vim/coc-settings.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "rust-analyzer.linkedProjects": [ + "fuzz/Cargo.toml", + "Cargo.toml" + ] +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/regex/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/regex/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,261 @@ +[package] +name = "regex" +version = "1.10.4" #:version +authors = ["The Rust Project Developers", "Andrew Gallant "] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-lang/regex" +documentation = "https://docs.rs/regex" +homepage = "https://github.com/rust-lang/regex" +description = """ +An implementation of regular expressions for Rust. This implementation uses +finite automata and guarantees linear time matching on all inputs. +""" +categories = ["text-processing"] +autotests = false +exclude = ["/scripts/*", "/.github/*"] +edition = "2021" +rust-version = "1.65" + +[workspace] +members = [ + "regex-automata", + "regex-capi", + "regex-cli", + "regex-lite", + "regex-syntax", + "regex-test", +] + +# Features are documented in the "Crate features" section of the crate docs: +# https://docs.rs/regex/*/#crate-features +[features] +default = ["std", "perf", "unicode", "regex-syntax/default"] + +# ECOSYSTEM FEATURES + +# The 'std' feature permits the regex crate to use the standard library. This +# is intended to support future use cases where the regex crate may be able +# to compile without std, and instead just rely on 'core' and 'alloc' (for +# example). Currently, this isn't supported, and removing the 'std' feature +# will prevent regex from compiling. +std = [ + "aho-corasick?/std", + "memchr?/std", + "regex-automata/std", + "regex-syntax/std", +] +# This feature enables the 'log' crate to emit messages. This is usually +# only useful for folks working on the regex crate itself, but can be useful +# if you're trying hard to do some performance hacking on regex patterns +# themselves. Note that you'll need to pair this with a crate like 'env_logger' +# to actually emit the log messages somewhere. +logging = [ + "aho-corasick?/logging", + "memchr?/logging", + "regex-automata/logging", +] +# The 'use_std' feature is DEPRECATED. It will be removed in regex 2. Until +# then, it is an alias for the 'std' feature. +use_std = ["std"] + + +# PERFORMANCE FEATURES + +# Enables all default performance features. Note that this specifically does +# not include perf-dfa-full, because it leads to higher compile times and +# bigger binaries, and the runtime performance improvement is not obviously +# worth it. +perf = [ + "perf-cache", + "perf-dfa", + "perf-onepass", + "perf-backtrack", + "perf-inline", + "perf-literal", +] +# Enables use of a lazy DFA when possible. +perf-dfa = ["regex-automata/hybrid"] +# Enables use of a fully compiled DFA when possible. +perf-dfa-full = ["regex-automata/dfa-build", "regex-automata/dfa-search"] +# Enables use of the one-pass regex matcher, which speeds up capture searches +# even beyond the backtracker. +perf-onepass = ["regex-automata/dfa-onepass"] +# Enables use of a bounded backtracker, which speeds up capture searches. +perf-backtrack = ["regex-automata/nfa-backtrack"] +# Enables aggressive use of inlining. +perf-inline = ["regex-automata/perf-inline"] +# Enables literal optimizations. +perf-literal = [ + "dep:aho-corasick", + "dep:memchr", + "regex-automata/perf-literal", +] +# Enables fast caching. (If disabled, caching is still used, but is slower.) +# Currently, this feature has no effect. It used to remove the thread_local +# dependency and use a slower internal cache, but now the default cache has +# been improved and thread_local is no longer a dependency at all. +perf-cache = [] + + +# UNICODE DATA FEATURES + +# Enables all Unicode features. This expands if new Unicode features are added. +unicode = [ + "unicode-age", + "unicode-bool", + "unicode-case", + "unicode-gencat", + "unicode-perl", + "unicode-script", + "unicode-segment", + "regex-automata/unicode", + "regex-syntax/unicode", +] +# Enables use of the `Age` property, e.g., `\p{Age:3.0}`. +unicode-age = [ + "regex-automata/unicode-age", + "regex-syntax/unicode-age", +] +# Enables use of a smattering of boolean properties, e.g., `\p{Emoji}`. +unicode-bool = [ + "regex-automata/unicode-bool", + "regex-syntax/unicode-bool", +] +# Enables Unicode-aware case insensitive matching, e.g., `(?i)β`. +unicode-case = [ + "regex-automata/unicode-case", + "regex-syntax/unicode-case", +] +# Enables Unicode general categories, e.g., `\p{Letter}` or `\pL`. +unicode-gencat = [ + "regex-automata/unicode-gencat", + "regex-syntax/unicode-gencat", +] +# Enables Unicode-aware Perl classes corresponding to `\w`, `\s` and `\d`. +unicode-perl = [ + "regex-automata/unicode-perl", + "regex-automata/unicode-word-boundary", + "regex-syntax/unicode-perl", +] +# Enables Unicode scripts and script extensions, e.g., `\p{Greek}`. +unicode-script = [ + "regex-automata/unicode-script", + "regex-syntax/unicode-script", +] +# Enables Unicode segmentation properties, e.g., `\p{gcb=Extend}`. +unicode-segment = [ + "regex-automata/unicode-segment", + "regex-syntax/unicode-segment", +] + + +# UNSTABLE FEATURES (requires Rust nightly) + +# A blanket feature that governs whether unstable features are enabled or not. +# Unstable features are disabled by default, and typically rely on unstable +# features in rustc itself. +unstable = ["pattern"] + +# Enable to use the unstable pattern traits defined in std. This is enabled +# by default if the unstable feature is enabled. +pattern = [] + +# For very fast multi-prefix literal matching. +[dependencies.aho-corasick] +version = "1.0.0" +optional = true +default-features = false + +# For skipping along search text quickly when a leading byte is known. +[dependencies.memchr] +version = "2.6.0" +optional = true +default-features = false + +# For the actual regex engines. +[dependencies.regex-automata] +path = "regex-automata" +version = "0.4.4" +default-features = false +features = ["alloc", "syntax", "meta", "nfa-pikevm"] + +# For parsing regular expressions. +[dependencies.regex-syntax] +path = "regex-syntax" +version = "0.8.2" +default-features = false + +[dev-dependencies] +# For examples. +once_cell = "1.17.1" +# For property based tests. +quickcheck = { version = "1.0.3", default-features = false } +# To check README's example +doc-comment = "0.3" +# For easy error handling in integration tests. +anyhow = "1.0.69" +# A library for testing regex engines. +regex-test = { path = "regex-test", version = "0.1.0" } + +[dev-dependencies.env_logger] +# Note that this is currently using an older version because of the dependency +# tree explosion that happened in 0.10. +version = "0.9.3" +default-features = false +features = ["atty", "humantime", "termcolor"] + +# This test suite reads a whole boatload of tests from the top-level testdata +# directory, and then runs them against the regex crate API. +# +# regex-automata has its own version of them, and runs them against each +# internal regex engine individually. +# +# This means that if you're seeing a failure in this test suite, you should +# try running regex-automata's tests: +# +# cargo test --manifest-path regex-automata/Cargo.toml --test integration +# +# That *might* give you a more targeted test failure. i.e., "only the +# PikeVM fails this test." Which gives you a narrower place to search. If +# regex-automata's test suite passes, then the bug might be in the integration +# of the regex crate and regex-automata. But generally speaking, a failure +# in this test suite *should* mean there is a corresponding failure in +# regex-automata's test suite. +[[test]] +path = "tests/lib.rs" +name = "integration" + +[package.metadata.docs.rs] +# We want to document all features. +all-features = true +# Since this crate's feature setup is pretty complicated, it is worth opting +# into a nightly unstable option to show the features that need to be enabled +# for public API items. To do that, we set 'docsrs', and when that's enabled, +# we enable the 'doc_auto_cfg' feature. +# +# To test this locally, run: +# +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features +rustdoc-args = ["--cfg", "docsrs"] + +[profile.release] +debug = true + +[profile.bench] +debug = true + +[profile.dev] +# Running tests takes too long in debug mode, so we forcefully always build +# with optimizations. Unfortunate, but, ¯\_(ツ)_/¯. +# +# It's counter-intuitive that this needs to be set on dev *and* test, but +# it's because the tests that take a long time to run are run as integration +# tests in a separate crate. The test.opt-level setting won't apply there, so +# we need to set the opt-level across the entire build. +opt-level = 3 +debug = true + +[profile.test] +opt-level = 3 +debug = true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex/record/old-bench-log/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/regex/record/old-bench-log/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/regex/record/old-bench-log/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex/record/old-bench-log/.gitignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +tmp diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"a93c35709a289ecb41e79c498cfc7b518a66465171c714222ed80000f2717e86","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"61db25dbf26092fc80e8db89165692e55f9fb86b14e8451ebb28303f45932254","src/dfa/accel.rs":"2a045b0f6715e913d18d2212a7804fabaadfc3bcffad9382e35574d32eb0c492","src/dfa/automaton.rs":"c14707007bbb915fd5607424b0a4c8e53fa7daf6c7c1f4e3045d51ef15f9b202","src/dfa/dense.rs":"9158daeafa2e734337d7e536e8e7fad08e869a3a16eb37fb84e10d2de7d94703","src/dfa/determinize.rs":"91b9f69d28bdd064aa86716fe0772e4145050fd458bb7869a28660b4f7b64872","src/dfa/minimize.rs":"b5cadb462b9f24cd4aa7a665e75fb813cd06858a92b8986c9c5ae7fd9a60dfab","src/dfa/mod.rs":"ab1ac378d81bb5ea40a23cf903928adae4758e30f54646afde71869234965723","src/dfa/onepass.rs":"013f09b795955aefd07936994f08df4bc5b39698797f586b85171f778162aeab","src/dfa/regex.rs":"d16f0434a0b0f1341d6d5e0a162e6afa29411a786fb37b0e98bbcc0c6ba3cfec","src/dfa/remapper.rs":"ca096abc0f8e45c43a2adf3a7743b8857714ae7411a623edea41cc3ce906a169","src/dfa/search.rs":"79b9ab2b0636177bc26d1ad6f0059ca033decf74824cb5a36f1ac19f020d2713","src/dfa/sparse.rs":"6babcf1536224ea20f742c44fefe5fdbcc598690fa4521d0cd9aefbcd5b03918","src/dfa/special.rs":"c2e60de5b98e68c9c45aaffbc67a08f049831a764a1ed29d1d1db0fb68efdce5","src/dfa/start.rs":"46b1dbaf8e4518ddddda6bbe596621aae36f8ba694390483a22355d9d799be8e","src/hybrid/dfa.rs":"a6ed6d3268e4008f88c1469029a84391edfee7851df2912640763e4ba2188635","src/hybrid/error.rs":"37db2a9759721de4ca2c49e21ab74dd3d998b67c5ab0e65a62085b57ec1d7ba3","src/hybrid/id.rs":"6168aad5c81c627494ba0575a24d61fd0ae7efabaaceeadb8ff28472275e2813","src/hybrid/mod.rs":"ca21e89062bdb5a0998d5cd1bc78609af1f6b795533e5982be969c383ac0463a","src/hybrid/regex.rs":"47815d025526330291f4cd749b4dd79b1122ef208fe6f0a49715c70fc1ea47c8","src/hybrid/search.rs":"76067f3f8675013dcdf7e9c9cc4d9d33d1107fb2cbcd7adcc05cfd42177d90cc","src/lib.rs":"4e831d41057760c5f2f1274a206fa5a42f59dbca8f98ad3e782fe0fba0d6c37f","src/macros.rs":"3e4b39252bfa471fad384160a43f113ebfec7bec46a85d16f006622881dd2081","src/meta/error.rs":"710a6813314b1b11ace1b016a827067fff8b2624d47e15c7f52043bff5ab57da","src/meta/limited.rs":"98b6b2d19f67d4ce3ddb110e06045f22a040590262fde33614ab900bdd06b25b","src/meta/literal.rs":"52da98bb30995dedd22786e4728cb84e84c6093a284168bd91196b999dd0f6ec","src/meta/mod.rs":"f3b10b96fa08efaba3e4c9b81883cf40aac6e4c1f6ae55a497a534cf5805b46d","src/meta/regex.rs":"b0fab107d3f972db89568e14fec0199ba4cd8076cc5fd61c2582db42885f196e","src/meta/reverse_inner.rs":"945d6c2d4c7538e1609dbd430a096784d22abd33db58b1ba65c9c9af45a7d3c0","src/meta/stopat.rs":"acb6122e17d10a9b1b5e72d6030e6d95748227975bad0ff5cbbcc2587edfa6df","src/meta/strategy.rs":"c882c5c261de5fe58bc65251d2d407e4cb483b9b80c2bec5eba958ef90e0072d","src/meta/wrappers.rs":"3cb0717f87b7082cc75cb02148b8cde30cffbee689bdb6275abcf1416747ceb4","src/nfa/mod.rs":"1a731e217ed4053714500e84e58cc127f402e4e075f7d0e5b9aea715cd52405a","src/nfa/thompson/backtrack.rs":"041015ea153c1e485e9cf39ec60d1e51c7ab9e400ecd77cad2078af45775339b","src/nfa/thompson/builder.rs":"7adf6aba69171f6acd47fea0fec85ba589154fead83f2042a1c6fe9486aa4dbd","src/nfa/thompson/compiler.rs":"92b26a91a8e32fbafe9818de3f0aff9adde0fb2d61c3e1c2b28edd4813a98f25","src/nfa/thompson/error.rs":"78488c2fdb85f819f53cc30bb11c7f96169112da5dd14c351e5cc3bcccf0e10e","src/nfa/thompson/literal_trie.rs":"c2d1d09b44da4648db797386c2410cbf63337afef8cb62e6e78cf34786892a11","src/nfa/thompson/map.rs":"fcd17ce7359b5179ef2e809fc9152dfa0b6c61d3d849d8c502497e1d0d8b0fa9","src/nfa/thompson/mod.rs":"0651520debd6f023ae1a2c422806aab37f8491e5bb092e20dfdc4fe4179d695c","src/nfa/thompson/nfa.rs":"410c3745c159eb17bea18256ec03ee92e1fccca630f01a24618a75fffcf86866","src/nfa/thompson/pikevm.rs":"aaf792832d1bf15fad8a8f0b2e6597170361eb3cbcb9343eb5bd242ff346d750","src/nfa/thompson/range_trie.rs":"e4d249f8a154136e54abf5073b88e6e83d50b1d31ff3b47f71e1bff20b305508","src/util/alphabet.rs":"94cd73ce2f4e34e0ae0a146d3efdc85478263afdfefd6dc105e0abf0ec79d82b","src/util/captures.rs":"d2a118ba509b70e9922a10ea9f78771b14a521abb0ed4029be3ef6aeea44d032","src/util/determinize/mod.rs":"5e9e1f7dd060d69521b743afc2b900b21ad7942e17397084ac6563ea5dcf2fd9","src/util/determinize/state.rs":"4c19bbbb5969c2624e5a1569e4691ecf905f009e6a58b9acf81f2fd12f5facdb","src/util/empty.rs":"13ec7d6cbd1520db5b4c1dae294f4419fa88d39d2bfc16f4ef258473d609f91c","src/util/escape.rs":"5b2731b41a55cb50ab688132bb5640dbd51f14f141adaa864b9db7f0aa092c74","src/util/int.rs":"b863a62f8ba1edf24858416fc01f15b38bee7af2494ebeb037e1acbf0319415e","src/util/interpolate.rs":"5e4e6b6fb6e5a7603e393bf05c609735d86a7d1f54c2436e42111b4e1409b6dd","src/util/iter.rs":"58ae97b4156d7160a46b909f4635d88d10354d9d892d2fcb4c5e18e24cf38f14","src/util/lazy.rs":"e16b3ed139210ca546fc302c463ce52a5dcfa77382f07c9097400ed8cddf78c8","src/util/look.rs":"fbfcaace79d0c6ad3698c9d6c025cb952f2e00cf88a48cf690d087fa73466689","src/util/memchr.rs":"573109ce4983907083ae0b29a084a324b9b53da369b4d96f7f3a21fd5c8eb5c9","src/util/mod.rs":"6c828a493f0f88c8b515aee4f8faf91ba653eb07e8fc3c23c0524553410803f9","src/util/pool.rs":"da1fad31f2fdf15cf3a6a605ece8d6162d8f6c42770c160af4c0fbf4ef148aa5","src/util/prefilter/aho_corasick.rs":"c54fa95f4d9e7ab53e2c6463a43f8953df6a440997fc9cd528f225db0dd32582","src/util/prefilter/byteset.rs":"1c80fa432acc23223a75a5181e37c40034764dffe42410e4b77af6f24f48bd5c","src/util/prefilter/memchr.rs":"36c6fe6354b2e729db6830166dd4862e439bc48c9e59258d88e4b6c5654e20ef","src/util/prefilter/memmem.rs":"6f6ed9450b14abf3e4a33d395337e51fbaa9743a0a16aac0009f7680aa60c500","src/util/prefilter/mod.rs":"b171a46c74678c77d659174284819939c656ccb3cc7661246fdeb47a042048f7","src/util/prefilter/teddy.rs":"ed54d26858b56e1c8c87e44afae5f63d81ab930787d79e671f3a3513f576e9cd","src/util/primitives.rs":"8a9cc19ef2e1ab183943cdc2d2f095b02252476e32b7e9fff4a06a251749b068","src/util/search.rs":"f37ff5193c7ae49356cc8f3167eeeab090a4754dfb9e5832ceb0b150f8f182fd","src/util/sparse_set.rs":"3d4aa30b6aa9fc875d36506487a5095dbe8ed528b89e4146a65c7e7497520a4d","src/util/start.rs":"73ebcf2550cea56f67b9048fa3dc91f3a8db9897fbd2400dd9941efb0cb4827e","src/util/syntax.rs":"720ac0d6600fad33f5967b5afe4e3de2096b857e4cda6fa16ba93b10a8230cab","src/util/unicode_data/mod.rs":"54c3e10bbc393e9881bfac3295815b160f59e69e2056bc29ee7cf0addd8e3cf7","src/util/unicode_data/perl_word.rs":"2e1a5d889598bd4e73af17d3a9f7d6b4cf2f6ab24920a5336e496bb255281e56","src/util/utf8.rs":"7a068009fdf07e693e521b1f0264725c0e6118dbe1eab55da9d0eab21785fcc1","src/util/wire.rs":"ad84c82b3035b5015929e1dfd27742f5842cf88740d8bf26ca656a5f17979df2","test":"39d79ce3532c31a51c0be89a2939816fad0e4868d2b03992c202cbe64dce9f6c","tests/dfa/api.rs":"cc28e366b6bcbfcf379265acd492a92c62743c3f20e7a2b273019679aa9e1291","tests/dfa/mod.rs":"924d8fff500b9b7b140082623023e78007058a87323151cd8e361462945e4f16","tests/dfa/onepass/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/dfa/onepass/suite.rs":"6d63ec5469e6876656ae607cdbe07e6a4e17ace7836b67435763c9b1d233438a","tests/dfa/regression.rs":"ebcf2645290286aa7531eb2b7951385e5ed8167532437aeca2ad2049768fd796","tests/dfa/suite.rs":"2812aa0167ee5e93eff3f7d45096a78c5f3a2440197a513b3cf0310286640f51","tests/fuzz/dense.rs":"3e1099a0cce61e85abc0ad81bc592e85f497f159ef0e5d1d32bac1936aa6f20c","tests/fuzz/mod.rs":"043773510e02f51def43ee0c2b8b867c53ecc8638c8a9233b2ac098de9c3ac1e","tests/fuzz/sparse.rs":"ba61db4927ab28953037a4b20317399c86d01b4d774e46c020ade19029215e25","tests/fuzz/testdata/deserialize_dense_crash-9486fb7c8a93b12c12a62166b43d31640c0208a9":"8961279a8237c3e318452024dd971b1d5a26b058260c297382a74daca1b7f0d1","tests/fuzz/testdata/deserialize_dense_minimized-from-9486fb7c8a93b12c12a62166b43d31640c0208a9":"c2d52e3dea78d3f159b5b521d433358a7fee45ce20ed1545067d461f45ef66b8","tests/fuzz/testdata/deserialize_sparse_crash-0da59c0434eaf35e5a6b470fa9244bb79c72b000":"5b2d273023de3fb04037eaf2e6b4f51cced4c5a08d2e6b44e4be540774f939b9","tests/fuzz/testdata/deserialize_sparse_crash-18cfc246f2ddfc3dfc92b0c7893178c7cf65efa9":"e2e22e2f46a9a75b5c876476442276cf675fe244c5cf918789e4f6b14078fbd9","tests/fuzz/testdata/deserialize_sparse_crash-61fd8e3003bf9d99f6c1e5a8488727eefd234b98":"24a12712e1f2ba0a40b5782707908a74dd19941dc372ef525d65a7134f91988c","tests/fuzz/testdata/deserialize_sparse_crash-a1b839d899ced76d5d7d0f78f9edb7a421505838":"a97f39b2febf9c73535681f7a86201e4b06d5a1ffcf135299c96c1cabfa9f6c4","tests/fuzz/testdata/deserialize_sparse_crash-c383ae07ec5e191422eadc492117439011816570":"44fe3ef878d35e2d51c2c17ff89bbbe3a4650e09d0cbbd48625c0f5e4dd0848b","tests/fuzz/testdata/deserialize_sparse_crash-d07703ceb94b10dcd9e4acb809f2051420449e2b":"d5534be36653b4af6cb94a7c63be58869bb8c204c5c63d67a4d6c986b44bb2e1","tests/fuzz/testdata/deserialize_sparse_crash-dbb8172d3984e7e7d03f4b5f8bb86ecd1460eff9":"77b844898610560afa09f2b8de73a85a0ba9a3b8cee4ff1bbf26b8c97ad4e8a2","tests/gen/README.md":"c3bfdf2f9ced501dd5bd75d01509a34e503efb2dff2f5f7b260580dde5519ed4","tests/gen/dense/mod.rs":"5ae1cfb46212a674118ada2f66f37b25188e84643d406b95eb4665d722344262","tests/gen/dense/multi_pattern_v2.rs":"29b1e9a799adecbdbe7cd05e9748f664c2b915b10b1d2f5d36cfb6453826d1d2","tests/gen/dense/multi_pattern_v2_fwd.bigendian.dfa":"8421d5a1bfc0b6c3bdc8fc90dff591a046b0aaf8e06ef7de7cc293004a35d061","tests/gen/dense/multi_pattern_v2_fwd.littleendian.dfa":"dcf2fd5fd49f5f53cf1ec66f61623402f39401cb3aea30d6677b98bb1e9541bf","tests/gen/dense/multi_pattern_v2_rev.bigendian.dfa":"73c4f20d984e544dfa4cf05f3009d0a9b52fa84bc97b501ea0ccd179e2def4bc","tests/gen/dense/multi_pattern_v2_rev.littleendian.dfa":"74471209f05754e8e20c8a0222a5877b1b15b8b8f33cd8cac89ea65f708b4aff","tests/gen/mod.rs":"043773510e02f51def43ee0c2b8b867c53ecc8638c8a9233b2ac098de9c3ac1e","tests/gen/sparse/mod.rs":"5ae1cfb46212a674118ada2f66f37b25188e84643d406b95eb4665d722344262","tests/gen/sparse/multi_pattern_v2.rs":"e00fb2a510a215460aab84573196b1f51bb65884ff494c2382534c04f6fdbfe9","tests/gen/sparse/multi_pattern_v2_fwd.bigendian.dfa":"3287956bd2003cd69653b125f82aade95d99adbb20229bfdbb4958b8877c0a0b","tests/gen/sparse/multi_pattern_v2_fwd.littleendian.dfa":"bdf285901eaaac4596380115c5bbb20ab2f42f593d8d9e9238a00ed69863f9c9","tests/gen/sparse/multi_pattern_v2_rev.bigendian.dfa":"e466dc085dd68b2d2220932a0e4d28759edd161c1fdad652240aa3825fd85268","tests/gen/sparse/multi_pattern_v2_rev.littleendian.dfa":"80358d0c26c1cc7284065b0075f5b8804d83e673a8a8c8327f93a1c1ff455399","tests/hybrid/api.rs":"bd4862275c52f94c6f6737bf174c97e3de30f8075ca23f43c129c72a0d0afed7","tests/hybrid/mod.rs":"4856a49a4d9b5e9e079c2719a5e75c32408b37e9b76cbdea057b388a3537af6d","tests/hybrid/suite.rs":"688972275c5ef38cdc5112a1e6e54ccd2bf8290008ae2b17344c6c81e17e3a5a","tests/lib.rs":"9775b3c62fb338ea5c1bd3513a6589eff4b5c8d35c599439d9363dbf98c6f8d4","tests/meta/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/meta/suite.rs":"4c441f9df82508a5e60dd08f266183f772fc9b2b236fbf69cab87650ecf3b424","tests/nfa/mod.rs":"49055c358e38d97e42acb1602c671f97dddf24cafe089490f0e79ed208d74d9b","tests/nfa/thompson/backtrack/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/nfa/thompson/backtrack/suite.rs":"4e7baff70fc98b98b8297c6fd6d5818beb20343379e16cdb95bee46207ac4bd6","tests/nfa/thompson/mod.rs":"de9f5bcea1a8d1f03c85c55ad8c0747877d69e344fcd6c6886b0a402f0661291","tests/nfa/thompson/pikevm/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/nfa/thompson/pikevm/suite.rs":"263837ebf5b2e1906a06237982ea875386d83567e399b4ec1f669f10b1422599"},"package":"86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"6ffcbdc39d2a8985f9e53e2a33bcabd4d405d11a73d8e8760acff41eb3ac0d84","Cargo.toml":"a93c35709a289ecb41e79c498cfc7b518a66465171c714222ed80000f2717e86","Cargo.toml.orig":"c11eceb3efbbb8eda41565f3b9dbd2ef5870e8e263711975a89c29cd0ee76fbd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"61db25dbf26092fc80e8db89165692e55f9fb86b14e8451ebb28303f45932254","src/dfa/accel.rs":"2a045b0f6715e913d18d2212a7804fabaadfc3bcffad9382e35574d32eb0c492","src/dfa/automaton.rs":"c14707007bbb915fd5607424b0a4c8e53fa7daf6c7c1f4e3045d51ef15f9b202","src/dfa/dense.rs":"9158daeafa2e734337d7e536e8e7fad08e869a3a16eb37fb84e10d2de7d94703","src/dfa/determinize.rs":"91b9f69d28bdd064aa86716fe0772e4145050fd458bb7869a28660b4f7b64872","src/dfa/minimize.rs":"b5cadb462b9f24cd4aa7a665e75fb813cd06858a92b8986c9c5ae7fd9a60dfab","src/dfa/mod.rs":"ab1ac378d81bb5ea40a23cf903928adae4758e30f54646afde71869234965723","src/dfa/onepass.rs":"013f09b795955aefd07936994f08df4bc5b39698797f586b85171f778162aeab","src/dfa/regex.rs":"d16f0434a0b0f1341d6d5e0a162e6afa29411a786fb37b0e98bbcc0c6ba3cfec","src/dfa/remapper.rs":"ca096abc0f8e45c43a2adf3a7743b8857714ae7411a623edea41cc3ce906a169","src/dfa/search.rs":"79b9ab2b0636177bc26d1ad6f0059ca033decf74824cb5a36f1ac19f020d2713","src/dfa/sparse.rs":"6babcf1536224ea20f742c44fefe5fdbcc598690fa4521d0cd9aefbcd5b03918","src/dfa/special.rs":"c2e60de5b98e68c9c45aaffbc67a08f049831a764a1ed29d1d1db0fb68efdce5","src/dfa/start.rs":"46b1dbaf8e4518ddddda6bbe596621aae36f8ba694390483a22355d9d799be8e","src/hybrid/dfa.rs":"a6ed6d3268e4008f88c1469029a84391edfee7851df2912640763e4ba2188635","src/hybrid/error.rs":"37db2a9759721de4ca2c49e21ab74dd3d998b67c5ab0e65a62085b57ec1d7ba3","src/hybrid/id.rs":"6168aad5c81c627494ba0575a24d61fd0ae7efabaaceeadb8ff28472275e2813","src/hybrid/mod.rs":"ca21e89062bdb5a0998d5cd1bc78609af1f6b795533e5982be969c383ac0463a","src/hybrid/regex.rs":"47815d025526330291f4cd749b4dd79b1122ef208fe6f0a49715c70fc1ea47c8","src/hybrid/search.rs":"76067f3f8675013dcdf7e9c9cc4d9d33d1107fb2cbcd7adcc05cfd42177d90cc","src/lib.rs":"4e831d41057760c5f2f1274a206fa5a42f59dbca8f98ad3e782fe0fba0d6c37f","src/macros.rs":"3e4b39252bfa471fad384160a43f113ebfec7bec46a85d16f006622881dd2081","src/meta/error.rs":"710a6813314b1b11ace1b016a827067fff8b2624d47e15c7f52043bff5ab57da","src/meta/limited.rs":"98b6b2d19f67d4ce3ddb110e06045f22a040590262fde33614ab900bdd06b25b","src/meta/literal.rs":"52da98bb30995dedd22786e4728cb84e84c6093a284168bd91196b999dd0f6ec","src/meta/mod.rs":"f3b10b96fa08efaba3e4c9b81883cf40aac6e4c1f6ae55a497a534cf5805b46d","src/meta/regex.rs":"b0fab107d3f972db89568e14fec0199ba4cd8076cc5fd61c2582db42885f196e","src/meta/reverse_inner.rs":"945d6c2d4c7538e1609dbd430a096784d22abd33db58b1ba65c9c9af45a7d3c0","src/meta/stopat.rs":"acb6122e17d10a9b1b5e72d6030e6d95748227975bad0ff5cbbcc2587edfa6df","src/meta/strategy.rs":"c882c5c261de5fe58bc65251d2d407e4cb483b9b80c2bec5eba958ef90e0072d","src/meta/wrappers.rs":"3cb0717f87b7082cc75cb02148b8cde30cffbee689bdb6275abcf1416747ceb4","src/nfa/mod.rs":"1a731e217ed4053714500e84e58cc127f402e4e075f7d0e5b9aea715cd52405a","src/nfa/thompson/backtrack.rs":"041015ea153c1e485e9cf39ec60d1e51c7ab9e400ecd77cad2078af45775339b","src/nfa/thompson/builder.rs":"7adf6aba69171f6acd47fea0fec85ba589154fead83f2042a1c6fe9486aa4dbd","src/nfa/thompson/compiler.rs":"92b26a91a8e32fbafe9818de3f0aff9adde0fb2d61c3e1c2b28edd4813a98f25","src/nfa/thompson/error.rs":"78488c2fdb85f819f53cc30bb11c7f96169112da5dd14c351e5cc3bcccf0e10e","src/nfa/thompson/literal_trie.rs":"c2d1d09b44da4648db797386c2410cbf63337afef8cb62e6e78cf34786892a11","src/nfa/thompson/map.rs":"fcd17ce7359b5179ef2e809fc9152dfa0b6c61d3d849d8c502497e1d0d8b0fa9","src/nfa/thompson/mod.rs":"0651520debd6f023ae1a2c422806aab37f8491e5bb092e20dfdc4fe4179d695c","src/nfa/thompson/nfa.rs":"410c3745c159eb17bea18256ec03ee92e1fccca630f01a24618a75fffcf86866","src/nfa/thompson/pikevm.rs":"aaf792832d1bf15fad8a8f0b2e6597170361eb3cbcb9343eb5bd242ff346d750","src/nfa/thompson/range_trie.rs":"e4d249f8a154136e54abf5073b88e6e83d50b1d31ff3b47f71e1bff20b305508","src/util/alphabet.rs":"94cd73ce2f4e34e0ae0a146d3efdc85478263afdfefd6dc105e0abf0ec79d82b","src/util/captures.rs":"d2a118ba509b70e9922a10ea9f78771b14a521abb0ed4029be3ef6aeea44d032","src/util/determinize/mod.rs":"5e9e1f7dd060d69521b743afc2b900b21ad7942e17397084ac6563ea5dcf2fd9","src/util/determinize/state.rs":"4c19bbbb5969c2624e5a1569e4691ecf905f009e6a58b9acf81f2fd12f5facdb","src/util/empty.rs":"13ec7d6cbd1520db5b4c1dae294f4419fa88d39d2bfc16f4ef258473d609f91c","src/util/escape.rs":"5b2731b41a55cb50ab688132bb5640dbd51f14f141adaa864b9db7f0aa092c74","src/util/int.rs":"b863a62f8ba1edf24858416fc01f15b38bee7af2494ebeb037e1acbf0319415e","src/util/interpolate.rs":"5e4e6b6fb6e5a7603e393bf05c609735d86a7d1f54c2436e42111b4e1409b6dd","src/util/iter.rs":"58ae97b4156d7160a46b909f4635d88d10354d9d892d2fcb4c5e18e24cf38f14","src/util/lazy.rs":"e16b3ed139210ca546fc302c463ce52a5dcfa77382f07c9097400ed8cddf78c8","src/util/look.rs":"fbfcaace79d0c6ad3698c9d6c025cb952f2e00cf88a48cf690d087fa73466689","src/util/memchr.rs":"573109ce4983907083ae0b29a084a324b9b53da369b4d96f7f3a21fd5c8eb5c9","src/util/mod.rs":"6c828a493f0f88c8b515aee4f8faf91ba653eb07e8fc3c23c0524553410803f9","src/util/pool.rs":"da1fad31f2fdf15cf3a6a605ece8d6162d8f6c42770c160af4c0fbf4ef148aa5","src/util/prefilter/aho_corasick.rs":"c54fa95f4d9e7ab53e2c6463a43f8953df6a440997fc9cd528f225db0dd32582","src/util/prefilter/byteset.rs":"1c80fa432acc23223a75a5181e37c40034764dffe42410e4b77af6f24f48bd5c","src/util/prefilter/memchr.rs":"36c6fe6354b2e729db6830166dd4862e439bc48c9e59258d88e4b6c5654e20ef","src/util/prefilter/memmem.rs":"6f6ed9450b14abf3e4a33d395337e51fbaa9743a0a16aac0009f7680aa60c500","src/util/prefilter/mod.rs":"b171a46c74678c77d659174284819939c656ccb3cc7661246fdeb47a042048f7","src/util/prefilter/teddy.rs":"ed54d26858b56e1c8c87e44afae5f63d81ab930787d79e671f3a3513f576e9cd","src/util/primitives.rs":"8a9cc19ef2e1ab183943cdc2d2f095b02252476e32b7e9fff4a06a251749b068","src/util/search.rs":"f37ff5193c7ae49356cc8f3167eeeab090a4754dfb9e5832ceb0b150f8f182fd","src/util/sparse_set.rs":"3d4aa30b6aa9fc875d36506487a5095dbe8ed528b89e4146a65c7e7497520a4d","src/util/start.rs":"73ebcf2550cea56f67b9048fa3dc91f3a8db9897fbd2400dd9941efb0cb4827e","src/util/syntax.rs":"720ac0d6600fad33f5967b5afe4e3de2096b857e4cda6fa16ba93b10a8230cab","src/util/unicode_data/mod.rs":"54c3e10bbc393e9881bfac3295815b160f59e69e2056bc29ee7cf0addd8e3cf7","src/util/unicode_data/perl_word.rs":"2e1a5d889598bd4e73af17d3a9f7d6b4cf2f6ab24920a5336e496bb255281e56","src/util/utf8.rs":"7a068009fdf07e693e521b1f0264725c0e6118dbe1eab55da9d0eab21785fcc1","src/util/wire.rs":"ad84c82b3035b5015929e1dfd27742f5842cf88740d8bf26ca656a5f17979df2","test":"39d79ce3532c31a51c0be89a2939816fad0e4868d2b03992c202cbe64dce9f6c","tests/dfa/api.rs":"cc28e366b6bcbfcf379265acd492a92c62743c3f20e7a2b273019679aa9e1291","tests/dfa/mod.rs":"924d8fff500b9b7b140082623023e78007058a87323151cd8e361462945e4f16","tests/dfa/onepass/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/dfa/onepass/suite.rs":"6d63ec5469e6876656ae607cdbe07e6a4e17ace7836b67435763c9b1d233438a","tests/dfa/regression.rs":"ebcf2645290286aa7531eb2b7951385e5ed8167532437aeca2ad2049768fd796","tests/dfa/suite.rs":"2812aa0167ee5e93eff3f7d45096a78c5f3a2440197a513b3cf0310286640f51","tests/fuzz/dense.rs":"3e1099a0cce61e85abc0ad81bc592e85f497f159ef0e5d1d32bac1936aa6f20c","tests/fuzz/mod.rs":"043773510e02f51def43ee0c2b8b867c53ecc8638c8a9233b2ac098de9c3ac1e","tests/fuzz/sparse.rs":"ba61db4927ab28953037a4b20317399c86d01b4d774e46c020ade19029215e25","tests/fuzz/testdata/deserialize_dense_crash-9486fb7c8a93b12c12a62166b43d31640c0208a9":"8961279a8237c3e318452024dd971b1d5a26b058260c297382a74daca1b7f0d1","tests/fuzz/testdata/deserialize_dense_minimized-from-9486fb7c8a93b12c12a62166b43d31640c0208a9":"c2d52e3dea78d3f159b5b521d433358a7fee45ce20ed1545067d461f45ef66b8","tests/fuzz/testdata/deserialize_sparse_crash-0da59c0434eaf35e5a6b470fa9244bb79c72b000":"5b2d273023de3fb04037eaf2e6b4f51cced4c5a08d2e6b44e4be540774f939b9","tests/fuzz/testdata/deserialize_sparse_crash-18cfc246f2ddfc3dfc92b0c7893178c7cf65efa9":"e2e22e2f46a9a75b5c876476442276cf675fe244c5cf918789e4f6b14078fbd9","tests/fuzz/testdata/deserialize_sparse_crash-61fd8e3003bf9d99f6c1e5a8488727eefd234b98":"24a12712e1f2ba0a40b5782707908a74dd19941dc372ef525d65a7134f91988c","tests/fuzz/testdata/deserialize_sparse_crash-a1b839d899ced76d5d7d0f78f9edb7a421505838":"a97f39b2febf9c73535681f7a86201e4b06d5a1ffcf135299c96c1cabfa9f6c4","tests/fuzz/testdata/deserialize_sparse_crash-c383ae07ec5e191422eadc492117439011816570":"44fe3ef878d35e2d51c2c17ff89bbbe3a4650e09d0cbbd48625c0f5e4dd0848b","tests/fuzz/testdata/deserialize_sparse_crash-d07703ceb94b10dcd9e4acb809f2051420449e2b":"d5534be36653b4af6cb94a7c63be58869bb8c204c5c63d67a4d6c986b44bb2e1","tests/fuzz/testdata/deserialize_sparse_crash-dbb8172d3984e7e7d03f4b5f8bb86ecd1460eff9":"77b844898610560afa09f2b8de73a85a0ba9a3b8cee4ff1bbf26b8c97ad4e8a2","tests/gen/README.md":"c3bfdf2f9ced501dd5bd75d01509a34e503efb2dff2f5f7b260580dde5519ed4","tests/gen/dense/mod.rs":"5ae1cfb46212a674118ada2f66f37b25188e84643d406b95eb4665d722344262","tests/gen/dense/multi_pattern_v2.rs":"29b1e9a799adecbdbe7cd05e9748f664c2b915b10b1d2f5d36cfb6453826d1d2","tests/gen/dense/multi_pattern_v2_fwd.bigendian.dfa":"8421d5a1bfc0b6c3bdc8fc90dff591a046b0aaf8e06ef7de7cc293004a35d061","tests/gen/dense/multi_pattern_v2_fwd.littleendian.dfa":"dcf2fd5fd49f5f53cf1ec66f61623402f39401cb3aea30d6677b98bb1e9541bf","tests/gen/dense/multi_pattern_v2_rev.bigendian.dfa":"73c4f20d984e544dfa4cf05f3009d0a9b52fa84bc97b501ea0ccd179e2def4bc","tests/gen/dense/multi_pattern_v2_rev.littleendian.dfa":"74471209f05754e8e20c8a0222a5877b1b15b8b8f33cd8cac89ea65f708b4aff","tests/gen/mod.rs":"043773510e02f51def43ee0c2b8b867c53ecc8638c8a9233b2ac098de9c3ac1e","tests/gen/sparse/mod.rs":"5ae1cfb46212a674118ada2f66f37b25188e84643d406b95eb4665d722344262","tests/gen/sparse/multi_pattern_v2.rs":"e00fb2a510a215460aab84573196b1f51bb65884ff494c2382534c04f6fdbfe9","tests/gen/sparse/multi_pattern_v2_fwd.bigendian.dfa":"3287956bd2003cd69653b125f82aade95d99adbb20229bfdbb4958b8877c0a0b","tests/gen/sparse/multi_pattern_v2_fwd.littleendian.dfa":"bdf285901eaaac4596380115c5bbb20ab2f42f593d8d9e9238a00ed69863f9c9","tests/gen/sparse/multi_pattern_v2_rev.bigendian.dfa":"e466dc085dd68b2d2220932a0e4d28759edd161c1fdad652240aa3825fd85268","tests/gen/sparse/multi_pattern_v2_rev.littleendian.dfa":"80358d0c26c1cc7284065b0075f5b8804d83e673a8a8c8327f93a1c1ff455399","tests/hybrid/api.rs":"bd4862275c52f94c6f6737bf174c97e3de30f8075ca23f43c129c72a0d0afed7","tests/hybrid/mod.rs":"4856a49a4d9b5e9e079c2719a5e75c32408b37e9b76cbdea057b388a3537af6d","tests/hybrid/suite.rs":"688972275c5ef38cdc5112a1e6e54ccd2bf8290008ae2b17344c6c81e17e3a5a","tests/lib.rs":"9775b3c62fb338ea5c1bd3513a6589eff4b5c8d35c599439d9363dbf98c6f8d4","tests/meta/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/meta/suite.rs":"4c441f9df82508a5e60dd08f266183f772fc9b2b236fbf69cab87650ecf3b424","tests/nfa/mod.rs":"49055c358e38d97e42acb1602c671f97dddf24cafe089490f0e79ed208d74d9b","tests/nfa/thompson/backtrack/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/nfa/thompson/backtrack/suite.rs":"4e7baff70fc98b98b8297c6fd6d5818beb20343379e16cdb95bee46207ac4bd6","tests/nfa/thompson/mod.rs":"de9f5bcea1a8d1f03c85c55ad8c0747877d69e344fcd6c6886b0a402f0661291","tests/nfa/thompson/pikevm/mod.rs":"d08f4ecb8ec243be584944c9602af1ed3a48a8732dd11cd573b0d1d182171303","tests/nfa/thompson/pikevm/suite.rs":"263837ebf5b2e1906a06237982ea875386d83567e399b4ec1f669f10b1422599"},"package":"86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a5ae35153a6ec61e64cb297155f7d91c11b629c7" + }, + "path_in_vcs": "regex-automata" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/regex-automata/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-automata/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +[package] +name = "regex-automata" +version = "0.4.6" #:version +authors = ["The Rust Project Developers", "Andrew Gallant "] +description = "Automata construction and matching using regular expressions." +documentation = "https://docs.rs/regex-automata" +repository = "https://github.com/rust-lang/regex/tree/master/regex-automata" +readme = "README.md" +keywords = ["regex", "dfa", "automata", "automaton", "nfa"] +license = "MIT OR Apache-2.0" +categories = ["text-processing"] +edition = "2021" +autoexamples = false +rust-version = "1.65" + +[lib] +bench = false + +# This crate has many many many features. See the crate docs for a description +# of each and when you might want to use them. +[features] +default = ["std", "syntax", "perf", "unicode", "meta", "nfa", "dfa", "hybrid"] +std = ["regex-syntax?/std", "memchr?/std", "aho-corasick?/std", "alloc"] +alloc = [] +logging = ["dep:log", "aho-corasick?/logging", "memchr?/logging"] + +syntax = ["dep:regex-syntax", "alloc"] + +meta = ["syntax", "nfa-pikevm"] + +nfa = ["nfa-thompson", "nfa-pikevm", "nfa-backtrack"] +nfa-thompson = ["alloc"] +nfa-pikevm = ["nfa-thompson"] +nfa-backtrack = ["nfa-thompson"] + +dfa = ["dfa-build", "dfa-search", "dfa-onepass"] +dfa-build = ["nfa-thompson", "dfa-search"] +dfa-search = [] +dfa-onepass = ["nfa-thompson"] + +hybrid = ["alloc", "nfa-thompson"] + +perf = ["perf-inline", "perf-literal"] +perf-inline = [] +perf-literal = ["perf-literal-substring", "perf-literal-multisubstring"] +perf-literal-substring = ["aho-corasick?/perf-literal", "dep:memchr"] +perf-literal-multisubstring = ["std", "dep:aho-corasick"] + +# Enables all Unicode features. This expands if new Unicode features are added. +unicode = [ + "unicode-age", + "unicode-bool", + "unicode-case", + "unicode-gencat", + "unicode-perl", + "unicode-script", + "unicode-segment", + "unicode-word-boundary", + "regex-syntax?/unicode", +] +# Enables use of the `Age` property, e.g., `\p{Age:3.0}`. +unicode-age = ["regex-syntax?/unicode-age"] +# Enables use of a smattering of boolean properties, e.g., `\p{Emoji}`. +unicode-bool = ["regex-syntax?/unicode-bool"] +# Enables Unicode-aware case insensitive matching, e.g., `(?i)β`. +unicode-case = ["regex-syntax?/unicode-case"] +# Enables Unicode general categories, e.g., `\p{Letter}` or `\pL`. +unicode-gencat = ["regex-syntax?/unicode-gencat"] +# Enables Unicode-aware Perl classes corresponding to `\w`, `\s` and `\d`. +unicode-perl = ["regex-syntax?/unicode-perl"] +# Enables Unicode scripts and script extensions, e.g., `\p{Greek}`. +unicode-script = ["regex-syntax?/unicode-script"] +# Enables Unicode segmentation properties, e.g., `\p{gcb=Extend}`. +unicode-segment = ["regex-syntax?/unicode-segment"] +# Enables Unicode word boundary support. If this is enabled with unicode-perl, +# then data tables from regex-syntax are used. Otherwise, a new data table +# inside regex-automata will be included. +unicode-word-boundary = [] + +# These are strictly internal features that may be removed or changed in +# non-compatible ways. +internal-instrument = ["internal-instrument-pikevm"] +internal-instrument-pikevm = ["logging", "std"] + +[dependencies] +aho-corasick = { version = "1.0.0", optional = true, default-features = false } +log = { version = "0.4.14", optional = true } +memchr = { version = "2.6.0", optional = true, default-features = false } +regex-syntax = { path = "../regex-syntax", version = "0.8.2", optional = true, default-features = false } + +[dev-dependencies] +anyhow = "1.0.69" +bstr = { version = "1.3.0", default-features = false, features = ["std"] } +doc-comment = "0.3.3" +quickcheck = { version = "1.0.3", default-features = false } +regex-test = { path = "../regex-test", version = "0.1.0" } + +[dev-dependencies.env_logger] +version = "0.9.3" +default-features = false +features = ["atty", "humantime", "termcolor"] + +# We put these tests here because they are written primarily against the +# regex-automata API, and in particular use regex-automata features for +# conditional compilation. If we moved these up as tests on 'regex' proper, +# then we'd need to duplicate regex-automata's complex features on 'regex' too, +# which I really do not want to do. +[[test]] +path = "tests/lib.rs" +name = "integration" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"8de6616ac6125c712ba7084df4c47ca34ae2ed78a43446f8e676757415d500c5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"b2484aa7e66fb92d1378e9a7ce7605af18f77cb12c179866eaf92ba28cfec1d9","benches/bench.rs":"d2b6ae5b939abd6093064f144b981b7739d7f474ec0698a1268052fc92406635","src/ast/mod.rs":"700c2f779fccb529db7b444819d53c38f916b065d3d05a74282f929af581e8b1","src/ast/parse.rs":"89a3701a9a95fea692be925e97b7dcfc5af1ac41f20e8f054eafaeb391e8dec2","src/ast/print.rs":"99cb69ece252ef31e0be177fb3364797eb30b785f936532b8dcd8106e7be0738","src/ast/visitor.rs":"f0fdf758801fe70e6b299b73ab63196e814af95ef6eccad7ef4f72075743fcf6","src/debug.rs":"7a16cca02be9715fdc8c26a32279465774623cd12fab1ec59ac25a6e3047817f","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"01a67e3407b0d0d869119363e47a94d92158834bfe5936366c2e3f6f4ed13f36","src/hir/interval.rs":"74d75837d24ab9a3cff33b375b70694cdd3b9a4610c799137533f365755ba604","src/hir/literal.rs":"6a8108b8919fbfd9ab93072846124c51d2998489810fcd6e7a89fdccc45833e0","src/hir/mod.rs":"443cabf36618713c9cc850b5c23b2d35219795bdc1a358711c67b58ab9a5adcc","src/hir/print.rs":"ad51c515c933bfd67d307ba3d7e6ac59c9c5903b4f393a9f9a4785c92b88348d","src/hir/translate.rs":"b8bdc2fb2c295c784a34db7f0e09b450fe49240e3800e4cb4c5da78a20593736","src/hir/visitor.rs":"71ca9c93aa48a5ed445399659fa6455093a1bbd9ef44b66bc7095c1b08b2ec1f","src/lib.rs":"5ae457d402e49443bdb23b71353693dd3b0d263b57a6eeb9eb5b5dae5c901bdd","src/parser.rs":"6b2f4f27e3331a01a25b87c89368dd2e54396bd425dac57941f9c1ebfd238ac8","src/rank.rs":"ff3d58b0cc5ffa69e2e8c56fc7d9ef41dd399d59a639a253a51551b858cb5bbd","src/unicode.rs":"9829458ef321b3bc22c21eae4b22805b33f8b5e67022928ffd9a9e0287bc7c31","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"2a2599a4e406fbbd0efd16aa6ce385c3f97b87c34820d6686a9f9113a5231c67","src/unicode_tables/case_folding_simple.rs":"9583803d4a10486da372b76979dbd26349b40766229467238eff972c1d78e47b","src/unicode_tables/general_category.rs":"36a93ba1cdeed96a00ff29a5ab5afd2c578a89541bf4dd8b18478146cebda0aa","src/unicode_tables/grapheme_cluster_break.rs":"39c388e9805a8391d3d3e69d74d831ce4fb99aa7e13e52c64dd2bd16d4765301","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"a98ea4afe71c2947023ae12bd25c46bf4c7de48eeb40979eca5c96ba62cee02e","src/unicode_tables/perl_space.rs":"ea2b3b84b4a48334082dadc6c37d9fcc9c9ded84b40e8f5c9c9314898638967e","src/unicode_tables/perl_word.rs":"6f1156bd6af32151ecffea4abe07a38fa04b1fc1b227ec1a8dac5d5f08d9d74b","src/unicode_tables/property_bool.rs":"0bd64f6e3228eaecf47824e238bdf1f8a9eef113ace6e790a57f045a8106701c","src/unicode_tables/property_names.rs":"5ca25437927eb70c62adf7d038e99a601cfb8a718677fd6de832589664d3c481","src/unicode_tables/property_values.rs":"5b4cc02392d382cf7af60455fc87b9980e97409b62a4b8d6c5843190d2e2d21d","src/unicode_tables/script.rs":"ea1d771b6d0a4b12d143f9bad2ea9342a0887878cbbe3c11262b6eabedaf2dd4","src/unicode_tables/script_extension.rs":"beeb8349703d903ff861beb8401bfd2599e457dc25df872e69d6ad1615f8b5e9","src/unicode_tables/sentence_break.rs":"2befe2a27cc4e8aecb624e310ef9f371462470dd3b2f572cec1f5873a5e30aa9","src/unicode_tables/word_break.rs":"94679177731b515f0c360eff394286a1f99b59527bdbc826cbf51d32f9666187","src/utf8.rs":"e9a13623a94295b81969c5483de17219ff74bb20768be13c527010351245acbd","test":"c7de5fbc0010d9b5b758cd49956375a64b88601c068167fd366808950257f108"},"package":"adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"c38a723624dc0a0ccfbbd6beb9ae0a9eb59befd4e3fe5ff5addaebd08301bb35","Cargo.toml":"8de6616ac6125c712ba7084df4c47ca34ae2ed78a43446f8e676757415d500c5","Cargo.toml.orig":"31774666cb8b7047f83a370952457b610ec6ac80beb39492389bebf0473c0778","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"b2484aa7e66fb92d1378e9a7ce7605af18f77cb12c179866eaf92ba28cfec1d9","benches/bench.rs":"d2b6ae5b939abd6093064f144b981b7739d7f474ec0698a1268052fc92406635","src/ast/mod.rs":"700c2f779fccb529db7b444819d53c38f916b065d3d05a74282f929af581e8b1","src/ast/parse.rs":"89a3701a9a95fea692be925e97b7dcfc5af1ac41f20e8f054eafaeb391e8dec2","src/ast/print.rs":"99cb69ece252ef31e0be177fb3364797eb30b785f936532b8dcd8106e7be0738","src/ast/visitor.rs":"f0fdf758801fe70e6b299b73ab63196e814af95ef6eccad7ef4f72075743fcf6","src/debug.rs":"7a16cca02be9715fdc8c26a32279465774623cd12fab1ec59ac25a6e3047817f","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"01a67e3407b0d0d869119363e47a94d92158834bfe5936366c2e3f6f4ed13f36","src/hir/interval.rs":"74d75837d24ab9a3cff33b375b70694cdd3b9a4610c799137533f365755ba604","src/hir/literal.rs":"6a8108b8919fbfd9ab93072846124c51d2998489810fcd6e7a89fdccc45833e0","src/hir/mod.rs":"443cabf36618713c9cc850b5c23b2d35219795bdc1a358711c67b58ab9a5adcc","src/hir/print.rs":"ad51c515c933bfd67d307ba3d7e6ac59c9c5903b4f393a9f9a4785c92b88348d","src/hir/translate.rs":"b8bdc2fb2c295c784a34db7f0e09b450fe49240e3800e4cb4c5da78a20593736","src/hir/visitor.rs":"71ca9c93aa48a5ed445399659fa6455093a1bbd9ef44b66bc7095c1b08b2ec1f","src/lib.rs":"5ae457d402e49443bdb23b71353693dd3b0d263b57a6eeb9eb5b5dae5c901bdd","src/parser.rs":"6b2f4f27e3331a01a25b87c89368dd2e54396bd425dac57941f9c1ebfd238ac8","src/rank.rs":"ff3d58b0cc5ffa69e2e8c56fc7d9ef41dd399d59a639a253a51551b858cb5bbd","src/unicode.rs":"9829458ef321b3bc22c21eae4b22805b33f8b5e67022928ffd9a9e0287bc7c31","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"2a2599a4e406fbbd0efd16aa6ce385c3f97b87c34820d6686a9f9113a5231c67","src/unicode_tables/case_folding_simple.rs":"9583803d4a10486da372b76979dbd26349b40766229467238eff972c1d78e47b","src/unicode_tables/general_category.rs":"36a93ba1cdeed96a00ff29a5ab5afd2c578a89541bf4dd8b18478146cebda0aa","src/unicode_tables/grapheme_cluster_break.rs":"39c388e9805a8391d3d3e69d74d831ce4fb99aa7e13e52c64dd2bd16d4765301","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"a98ea4afe71c2947023ae12bd25c46bf4c7de48eeb40979eca5c96ba62cee02e","src/unicode_tables/perl_space.rs":"ea2b3b84b4a48334082dadc6c37d9fcc9c9ded84b40e8f5c9c9314898638967e","src/unicode_tables/perl_word.rs":"6f1156bd6af32151ecffea4abe07a38fa04b1fc1b227ec1a8dac5d5f08d9d74b","src/unicode_tables/property_bool.rs":"0bd64f6e3228eaecf47824e238bdf1f8a9eef113ace6e790a57f045a8106701c","src/unicode_tables/property_names.rs":"5ca25437927eb70c62adf7d038e99a601cfb8a718677fd6de832589664d3c481","src/unicode_tables/property_values.rs":"5b4cc02392d382cf7af60455fc87b9980e97409b62a4b8d6c5843190d2e2d21d","src/unicode_tables/script.rs":"ea1d771b6d0a4b12d143f9bad2ea9342a0887878cbbe3c11262b6eabedaf2dd4","src/unicode_tables/script_extension.rs":"beeb8349703d903ff861beb8401bfd2599e457dc25df872e69d6ad1615f8b5e9","src/unicode_tables/sentence_break.rs":"2befe2a27cc4e8aecb624e310ef9f371462470dd3b2f572cec1f5873a5e30aa9","src/unicode_tables/word_break.rs":"94679177731b515f0c360eff394286a1f99b59527bdbc826cbf51d32f9666187","src/utf8.rs":"e9a13623a94295b81969c5483de17219ff74bb20768be13c527010351245acbd","test":"c7de5fbc0010d9b5b758cd49956375a64b88601c068167fd366808950257f108"},"package":"adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d895bd984537538240e175cc55bc010307210468" + }, + "path_in_vcs": "regex-syntax" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/regex-syntax/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/regex-syntax/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,51 @@ +[package] +name = "regex-syntax" +version = "0.8.3" #:version +authors = ["The Rust Project Developers", "Andrew Gallant "] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/regex/tree/master/regex-syntax" +documentation = "https://docs.rs/regex-syntax" +description = "A regular expression parser." +workspace = ".." +edition = "2021" +rust-version = "1.65" + +# Features are documented in the "Crate features" section of the crate docs: +# https://docs.rs/regex-syntax/*/#crate-features +[features] +default = ["std", "unicode"] +std = [] +arbitrary = ["dep:arbitrary"] + +unicode = [ + "unicode-age", + "unicode-bool", + "unicode-case", + "unicode-gencat", + "unicode-perl", + "unicode-script", + "unicode-segment", +] +unicode-age = [] +unicode-bool = [] +unicode-case = [] +unicode-gencat = [] +unicode-perl = [] +unicode-script = [] +unicode-segment = [] + +[dependencies] +arbitrary = { version = "1.3.0", features = ["derive"], optional = true } + +[package.metadata.docs.rs] +# We want to document all features. +all-features = true +# Since this crate's feature setup is pretty complicated, it is worth opting +# into a nightly unstable option to show the features that need to be enabled +# for public API items. To do that, we set 'docsrs', and when that's enabled, +# we enable the 'doc_auto_cfg' feature. +# +# To test this locally, run: +# +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"95011466f65a672b5efccd6d8135f5e4540fa31f8694e6d12d48a962caa9cae3","Cargo.lock":"8a3d73549ab0285287dfa562af1bebd32ecd55e5911bf26f3e56217ba8b7ed2b","Cargo.toml":"30cd97165651f8bad01c0cde99b15a7260294f2a7ee231d2c8e9aa1fb9221fe6","Cargo.toml.orig":"72bd11f3af192108a5c0fe0b841fabcd717b9d32dd4981d79b464af540918fa5","LICENSE":"457b464bc0fba8a3d67d2458569104f5611869f0c1563a1a12d9c51a0bca9261","README.md":"b69a452a62f1d85cc25581feca75d9b3fc154d48cafdc248c8df5b8049ed2c8c","examples/example.rs":"c69042b49b60a486e249b9292ed9d59b06b8845873c5837910251172078e6083","examples/serde.rs":"7d2c63d0d9892d22a37a8fbc56e3f9860573a0454ebd15302b40a0f9984cf6e8","src/as_bytes.rs":"6a7291f2baebb1ff16b6644e325b7b48ae6b8a3a30348f70391227d4c6fac508","src/bytemuck_impl.rs":"6164ab623525b2803491c2941f824602bbec4c91ebf3955e1064a0320d8fe4ad","src/formats/abgr.rs":"b1b854400c4688808b09f2710181da63d50a1121fdfd736658963506595e2507","src/formats/argb.rs":"c11f6ba738c80a285c1b99ca746efeccea7938f8fd6dcbfb4a197bb7c6896382","src/formats/bgr.rs":"1cfcc068bbadbf5764672ebc1a73ce53d8c6312579589dd4f251251f018f2929","src/formats/bgra.rs":"29d4e597eb62dea123686d8bca4467cdb817a2d0aaae6d22ebaee0a9d172a57e","src/formats/gray.rs":"ed89fc396ae8e7453239dd63ac6ed476195ae96d97da86f4a10f92b8ec74ce45","src/formats/gray_a.rs":"8db0f5f55554497119fcbeab59bf74dbc60363d2ff996c65b2a7ee0deed29ccc","src/formats/gray_alpha.rs":"55eaff8c6fa3af38740a8bbcc25c8eb33f114262b913104ab3b5d4272b775561","src/formats/grb.rs":"13cf52ed06694c25f0393ae590f9ec33097dd020c45a0d2fb07ba820a5d19e34","src/formats/rgb.rs":"80510978bd421a79dd07f22aa572afdfd7c3fd199d53b98a3fedaf0056d08c1d","src/formats/rgba.rs":"4025fb76ec59984bc3abe7f296f099c7050aca0291ce1b5196d386aa28436653","src/inherent_impls.rs":"3e31884df3b62b6f3fa926a36fc0cc9aee55986575c9f30a5ffea81b46d14f04","src/legacy/alt.rs":"6472b33b23bd20ea39c9f24666b44a7ff47d8eb431466accecd5d9388d53578b","src/legacy/internal/convert/array.rs":"c56f532bde4b269bb512733192bb4176a9d5c2a83d505b522f769795853c4ed9","src/legacy/internal/convert/mod.rs":"b12ca3ea2c2f3e90b20bc6e6aab9db31c5c548d09ae6147ec7de8a13d8607317","src/legacy/internal/convert/tuple.rs":"4b4e118c939d8f0b472ea0c0736ece61c70a30d8cf384645262634ae94e30704","src/legacy/internal/ops.rs":"a28cda8cd2217a2b7f80b57727183275e54e8aac1ce8be0cb0737727c14aba0d","src/legacy/internal/pixel.rs":"049612c33a2e9b401ca4cfe364c090a4c1bdd05086cf5f0b3907c434fc4ee9ea","src/legacy/internal/rgb.rs":"b1315f3c7ea9272a45efe9f8648cb7ca1327686424f53e78b77a31d5b674f897","src/legacy/internal/rgba.rs":"ad18c35644be08d2bfac713121cbfb30b91d68f10d3955b939ff88be9ae19ba3","src/lib.rs":"0d5b569e9ff56aef7d87b80003471b80720016e12a8222f3821ea60e65436110"},"package":"0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "39276d5e2161a6c85cde118cd928559894d66ec1" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.0.1", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rgb" +version = "0.8.52" +dependencies = [ + "bytemuck", + "defmt 0.3.100", + "serde", + "serde_json", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.64" +name = "rgb" +version = "0.8.52" +authors = [ + "Kornel Lesiński ", + "James Forster ", +] +build = false +include = [ + "src/**/*", + "Cargo.toml", + "README.md", + "examples/*.rs", + "LICENSE", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +`struct RGB/RGBA/etc.` for sharing pixels between crates + convenience methods for color manipulation. +Allows no-copy high-level interoperability. Also adds common convenience methods and implements standard Rust traits to make `RGB`/`RGBA` pixels and slices first-class Rust objects.""" +homepage = "https://lib.rs/crates/rgb" +documentation = "https://docs.rs/rgb" +readme = "README.md" +keywords = [ + "rgb", + "rgba", + "bgra", + "pixel", + "color", +] +categories = [ + "graphics", + "rust-patterns", + "multimedia::images", +] +license = "MIT" +repository = "https://github.com/kornelski/rust-rgb" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +features = [ + "as-bytes", + "serde", +] +rustdoc-args = ["--generate-link-to-definition"] + +[badges.maintenance] +status = "actively-developed" + +[features] +argb = [] +as-bytes = ["bytemuck"] +bytemuck = ["dep:bytemuck"] +checked_fns = [] +default = [ + "as-bytes", + "argb", + "grb", +] +defmt-03 = ["dep:defmt"] +grb = [] +serde = ["dep:serde"] +unstable-experimental = [] + +[lib] +name = "rgb" +path = "src/lib.rs" + +[[example]] +name = "example" +path = "examples/example.rs" +required-features = ["as-bytes"] + +[[example]] +name = "serde" +path = "examples/serde.rs" +required-features = ["serde"] + +[dependencies.bytemuck] +version = "1.16" +optional = true + +[dependencies.defmt] +version = "0.3.8" +optional = true + +[dependencies.serde] +version = "1.0.200" +features = ["derive"] +optional = true +default-features = false + +[dev-dependencies.serde_json] +version = "1.0.100" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,58 @@ +[package] +name = "rgb" +version = "0.8.52" +authors = ["Kornel Lesiński ", "James Forster "] +include = ["src/**/*", "Cargo.toml", "README.md", "examples/*.rs", "LICENSE"] +description = "`struct RGB/RGBA/etc.` for sharing pixels between crates + convenience methods for color manipulation.\nAllows no-copy high-level interoperability. Also adds common convenience methods and implements standard Rust traits to make `RGB`/`RGBA` pixels and slices first-class Rust objects." +documentation = "https://docs.rs/rgb" +repository = "https://github.com/kornelski/rust-rgb" +homepage = "https://lib.rs/crates/rgb" +readme = "README.md" +keywords = ["rgb", "rgba", "bgra", "pixel", "color"] +license = "MIT" +categories = ["graphics", "rust-patterns", "multimedia::images"] +edition = "2021" +rust-version = "1.64" + +[features] +default = ["as-bytes", "argb", "grb"] +# safe as_bytes() casts require a marker trait for non-padded, non-pointery types. +as-bytes = ["bytemuck"] +# Preferred over as-bytes +bytemuck = ["dep:bytemuck"] +# Deprecated: all pixel types are enabled by default. No-op. +argb = [] +# Deprecated: all pixel types are enabled by default. No-op. +grb = [] +# Enable `checked_add` and `checked_sub` methods on `RGB` +checked_fns = [] +# Make pixels serializable +serde = ["dep:serde"] +# support for the `defmt` crate +defmt-03 = ["dep:defmt"] +# Preview of changes for v0.9. May cause semver breakage if enabled. +unstable-experimental = [] + +[badges] +maintenance = { status = "actively-developed" } + +[dependencies] +serde = { version = "1.0.200", optional = true, default-features = false, features = ["derive"] } +bytemuck = { version = "1.16", optional = true } +defmt = { version = "0.3.8", optional = true } + +[dev-dependencies] +serde_json = "1.0.100" + +[[example]] +name = "serde" +required-features = ["serde"] + +[[example]] +name = "example" +required-features = ["as-bytes"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +features = ["as-bytes", "serde"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/rgb/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Kornel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/README.md clamav-1.4.6+dfsg/.cargo/vendor/rgb/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +# `struct RGB` for [Rust](https://www.rust-lang.org) [![crate](https://img.shields.io/crates/v/rgb.svg)](https://lib.rs/crates/rgb) + +Operating on pixels as weakly-typed vectors of `u8` is error-prone and inconvenient. It's better to use vectors of pixel structs. However, Rust is so strongly typed that *your* RGB pixel struct is not compatible with *my* RGB pixel struct. So let's all use mine :P + +[xkcd: …there are 15 competing standards](https://xkcd.com/927/) + +## Installation + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +rgb = "0.8.51" +``` + +## Usage + +### `RGB` and `RGBA` structs + +The structs implement common Rust traits and a few convenience functions, e.g. `map` that repeats an operation on every subpixel: + +```rust +use rgb::*; // Laziest way to use traits which add extra methods to the structs + +let px = RGB { + r:255_u8, + g:0, + b:255, +}; +let inverted = px.map(|ch| 255 - ch); + +println!("{}", inverted); // Display: rgb(0,255,0) +assert_eq!(RGB8::new(0, 255, 0), inverted); +``` + +### Byte slices to pixel slices + +For interoperability with functions operating on generic arrays of bytes there are functions for safe casting to and from pixel slices. + +```rust +let raw = vec![0u8; width*height*3]; +let pixels: &[RGB8] = raw.as_rgb(); /// Safe casts without copying +let raw_again = pixels.as_bytes(); +``` + +Note: if you get an error about "no method named `as_bytes` found", add `use rgb::ComponentBytes`. If you're using a custom component type (`RGB`), implement `rgb::Pod` (plain old data) and `rgb::Zeroable` trait for the component (these traits are from [`bytemuck`](https://lib.rs/bytemuck) crate). + +---- + +## About colorspaces + +*Correct* color management is a complex problem, and this crate aims to be the lowest common denominator, so it's intentionally agnostic about it. + +However, this library supports any subpixel type for `RGB`, and `RGBA`, so you can use them with a newtype, e.g.: + +```rust +struct LinearLight(u16); +type LinearRGB = RGB; +``` + + +### `BGRA`, `ARGB`, `Gray`, etc. + +There are other color types in `rgb::alt::*`. There's also an optional `serde` feature that makes all types (de)serializable. + +## Roadmap to 1.0 + +The plan is to provide easy migration to v1.0. There will be a transitional v0.9 version released that will be mostly backwards-compatible with 0.8, and forwards-compatible with 1.0. + +Planned changes: + + * Types will be renamed to follow Rust's naming convention: `RGBA` → `Rgba`. The old names will continue to work as hidden aliases. + * The `Gray` and `GrayAlpha` types will change from tuple structs with `.0` to structs with named fields `.v` (value) and `.a` (alpha). Through a `Deref` trick both field names will work, but `.0` is going to be deprecated. + * `bytemuck::Pod` (conversions from/to raw bytes) will require color and alpha components to be the same type (i.e. it will work with `Rgba`, but not `Rgba`). Currently it's unsound if the alpha has a different size than color components. + * Many inherent methods will be moved to a new `Pixel` trait. + +## Migration from 0.8 to 0.9 + +1. Update to the latest version of 0.8, and fix all deprecation warnings. + + - rename `.alpha()` to `.with_alpha()` + - rename `.map_c()` to `.map_colors()` + +2. Change field access on `GrayAlpha` from `.0` and `.1` to `.v` and `.a` where possible. +3. Use the `bytemuck` crate for conversions from/to bytes instead of `ComponentBytes` trait. Disable the `as-bytes` feature if possible. +4. Don't enable `gbr` and `argb` features. All pixel types are enabled by default. +5. In generic code operating on pixels, add `Copy + 'static` bounds to the pixel types and/or their components. +6. Test your code with `rgb = { version = "0.8.46", features = ["unstable-experimental"] }`, which enables some of the future breaking changes on the older version. This feature flag is only for testing, and will be changed/removed in the future. +7. Avoid wildcard imports from `rgb::alt::*`, and avoid using `GRAY8`-`GRAYA16` type aliases. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/examples/example.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/example.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/examples/example.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/example.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +#[cfg(feature = "as-bytes")] +fn main() { + use rgb::ComponentSlice; + use rgb::prelude::*; + use rgb::Rgb; + + let px = Rgb { + r: 255_u8, + g: 0, + b: 100, + }; + assert_eq!(rgb::bytemuck::cast_slice::<_, u8>(&[px])[0], 255); + + let bigpx = Rgb:: { + r: 65535_u16, + g: 0, + b: 0, + }; + assert_eq!(bigpx.as_slice()[0], 65535); + + let px = Rgb::::new(255, 0, 255); + let inverted: Rgb = px.map(|ch| 255 - ch); + + println!("{inverted}"); // rgb(0,255,0) +} + +#[cfg(not(feature = "as-bytes"))] +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/examples/serde.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/serde.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/examples/serde.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/examples/serde.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use rgb::*; + +// Run using: cargo run --features=serde --example serde + +fn main() { + let color = Rgb { r:255_u8, g:0, b:100 }; + println!("{}", serde_json::to_string(&color).unwrap()); + + let color: Rgb = serde_json::from_str("{\"r\":10,\"g\":20,\"b\":30}").unwrap(); + println!("{}", color); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/as_bytes.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/as_bytes.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/as_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/as_bytes.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +use crate::{RGB, RGBA}; +use crate::alt::{Gray, GrayAlpha, BGR, BGRA}; +use crate::alt::{ARGB, ABGR}; +use crate::ComponentBytes; + +#[cfg(feature = "as-bytes")] +unsafe impl crate::Pod for RGB where T: crate::Pod {} +#[cfg(feature = "as-bytes")] +unsafe impl crate::Pod for BGR where T: crate::Pod {} +#[cfg(feature = "as-bytes")] +unsafe impl crate::Zeroable for RGB where T: crate::Zeroable {} +#[cfg(feature = "as-bytes")] +unsafe impl crate::Zeroable for BGR where T: crate::Zeroable {} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Zeroable for ABGR where T: crate::Zeroable, A: crate::Zeroable { + #[track_caller] + #[inline(always)] + fn zeroed() -> Self { + unsafe { + assert_no_padding::(); + core::mem::zeroed() + } + } +} + +#[track_caller] +const fn assert_no_padding() { + if core::mem::size_of::() + 3 * core::mem::size_of::() != core::mem::size_of::() { + panic!("type has padding"); + } +} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Pod for RGBA where T: crate::Pod, A: crate::Pod {} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Pod for BGRA where T: crate::Pod, A: crate::Pod {} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Zeroable for RGBA where T: crate::Zeroable, A: crate::Zeroable { + #[track_caller] + #[inline(always)] + fn zeroed() -> Self { + unsafe { + assert_no_padding::(); + core::mem::zeroed() + } + } +} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Pod for ARGB where T: crate::Pod, A: crate::Pod {} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Pod for ABGR where T: crate::Pod, A: crate::Pod {} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Zeroable for ARGB where T: crate::Zeroable, A: crate::Zeroable { + #[track_caller] + #[inline(always)] + fn zeroed() -> Self { + unsafe { + assert_no_padding::(); + core::mem::zeroed() + } + } +} + +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Zeroable for BGRA where T: crate::Zeroable, A: crate::Zeroable { + #[track_caller] + #[inline(always)] + fn zeroed() -> Self { + unsafe { + assert_no_padding::(); + core::mem::zeroed() + } + } +} + +#[cfg(feature = "as-bytes")] +unsafe impl crate::Pod for Gray where T: crate::Pod {} +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Pod for GrayAlpha where T: crate::Pod, A: crate::Pod {} +#[cfg(feature = "as-bytes")] +unsafe impl crate::Zeroable for Gray where T: crate::Zeroable {} +#[cfg(feature = "as-bytes")] +/// This is unsound. You can disable `as-bytes` feature, enable `bytemuck`, and use `bytemuck::cast_slice()` instead. +unsafe impl crate::Zeroable for GrayAlpha where T: crate::Zeroable, A: crate::Zeroable { + #[track_caller] + #[inline(always)] + fn zeroed() -> Self { + unsafe { + if core::mem::size_of::() + core::mem::size_of::() != core::mem::size_of::() { + panic!("type has padding"); + } + core::mem::zeroed() + } + } +} + +#[cfg(feature = "as-bytes")] +impl ComponentBytes for [Gray] {} + +#[cfg(feature = "as-bytes")] +impl ComponentBytes for [GrayAlpha] {} + +#[test] +#[allow(dead_code)] +fn shared_impl() { + struct SharedPixelBuffer { + data: [Pixel; 1], + } + + impl SharedPixelBuffer + where + [Pixel]: crate::ComponentBytes, + { + pub fn as_bytes(&self) -> &[u8] { + self.data.as_slice().as_bytes() + } + } + + let b = SharedPixelBuffer { + data: [crate::RGB8::new(0,0,0)], + }; + let _ = b.as_bytes(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/bytemuck_impl.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/bytemuck_impl.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/bytemuck_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/bytemuck_impl.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +use crate::{Abgr, Argb, Bgr, Bgra, Grb, Rgb, Rgba}; +use crate::formats::gray_a::GrayA; +use crate::formats::gray_alpha::GrayAlpha_v08; +use crate::formats::gray::Gray_v08; + +#[cfg(feature = "unstable-experimental")] +use crate::formats::gray::Gray_v09; + +macro_rules! bytemuck { + ($name:ident) => { + unsafe impl ::bytemuck::Zeroable for $name {} + unsafe impl ::bytemuck::Pod for $name {} + }; +} + +bytemuck!(Rgb); +bytemuck!(Bgr); +bytemuck!(Grb); +bytemuck!(Rgba); +bytemuck!(Argb); +bytemuck!(Bgra); +bytemuck!(Abgr); +bytemuck!(GrayA); + +bytemuck!(GrayAlpha_v08); +bytemuck!(Gray_v08); + +#[cfg(feature = "unstable-experimental")] +bytemuck!(Gray_v09); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/abgr.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/abgr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/abgr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/abgr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// An `Alpha + Blue + Green + Red` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Abgr; +/// +/// let pixel: Abgr = Abgr { a: 255, b: 0, g: 0, r: 0 }; +/// ``` +pub struct Abgr { + /// Alpha Component + pub a: A, + /// Blue Component + pub b: T, + /// Green Component + pub g: T, + /// Red Component + pub r: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/argb.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/argb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/argb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/argb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// An `Alpha + Red + Green + Blue` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Argb; +/// +/// let pixel: Argb = Argb { a: 255, r: 0, g: 0, b: 0 }; +/// ``` +pub struct Argb { + /// Alpha Component + pub a: A, + /// Red Component + pub r: T, + /// Green Component + pub g: T, + /// Blue Component + pub b: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/bgr.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/bgr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Blue + Green + Red` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Bgr; +/// +/// let pixel: Bgr = Bgr { b: 0, g: 0, r: 0 }; +/// ``` +pub struct Bgr { + /// Blue Component + pub b: T, + /// Green Component + pub g: T, + /// Red Component + pub r: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/bgra.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgra.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/bgra.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/bgra.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Blue + Green + Red + Alpha` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Bgra; +/// +/// let pixel: Bgra = Bgra { b: 0, g: 0, r: 0, a: 255 }; +/// ``` +pub struct Bgra { + /// Blue Component + pub b: T, + /// Green Component + pub g: T, + /// Red Component + pub r: T, + /// Alpha Component + pub a: A, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,100 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Grayscale` pixel (rgb crate v0.8) +#[allow(non_camel_case_types)] +pub struct Gray_v08( + /// Grayscale Component. This field will be renamed to `v`. + #[deprecated(note = "Please use .value() or .value_mut() instead. This field will be renamed to .v in the next major version")] + pub T, +); + +impl Gray_v08 { + /// Reads the `.0` field + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + #[allow(deprecated)] + pub fn value(self) -> T { + self.0 + } + + /// Exposes the `.0` field for writing + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + #[allow(deprecated)] + pub fn value_mut(&mut self) -> &mut T { + &mut self.0 + } + + /// Add alpha component to this pixel + #[allow(deprecated)] + pub fn with_alpha(self, add_alpha_value: T) -> crate::formats::gray_alpha::GrayAlpha_v08 { + crate::formats::gray_alpha::GrayAlpha_v08(self.0, add_alpha_value) + } +} + +#[cfg(feature = "unstable-experimental")] +/// A `Grayscale` pixel (rgb crate v0.9) +/// +/// This is the new gray pixel type as opposed to the legacy gray type +/// (`rgb::Gray`) which is kept for backwards-compatibility. +/// +/// # Examples +/// +/// ``` +/// use rgb::Gray; +/// +/// let pixel: Gray = Gray { v: 0 }; +/// ``` +#[allow(non_camel_case_types)] +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[doc(alias = "Luma")] +pub struct Gray_v09 { + /// Grayscale Component + pub v: T, +} + +#[cfg(feature = "unstable-experimental")] +impl core::ops::Deref for Gray_v08 { + type Target = Gray_v09; + + fn deref(&self) -> &Gray_v09 { + unsafe { + &*(self as *const Self as *const Gray_v09::) + } + } +} + +#[cfg(feature = "unstable-experimental")] +impl Gray_v09 { + /// Reads the `.v` field + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + pub fn value(self) -> T { + self.v + } + + /// Exposes the `.v` field for writing + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + pub fn value_mut(&mut self) -> &mut T { + &mut self.v + } + + /// Add alpha component to this pixel + pub fn with_alpha(self, add_alpha_value: T) -> crate::formats::gray_a::GrayA { + crate::formats::gray_a::GrayA { v: self.v, a: add_alpha_value } + } +} + +#[test] +#[cfg(feature = "unstable-experimental")] +fn swizzle() { + let g = Gray_v08(10u8); + assert_eq!(10, g.v); + assert_eq!(10, g.0); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray_a.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_a.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray_a.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_a.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Value (brightness) + Alpha` pixel (rgb crate v0.9) +/// +/// This pixel is commonly used for grayscale images. +pub struct GrayA { + /// Value - the brightness component. May be luma or luminance. + pub v: T, + /// Alpha Component + pub a: A, +} + +impl GrayA { + /// Reads the `.v` field + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + pub fn value(self) -> T { + self.v + } + + /// Exposes the `.v` field for writing + /// + /// This function isn't necessary, but it is forwards-compatible with the next major version of the RGB crate. + pub fn value_mut(&mut self) -> &mut T { + &mut self.v + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray_alpha.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_alpha.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/gray_alpha.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/gray_alpha.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,72 @@ +use crate::formats::gray_a::GrayA; +use core::ops::{Deref, DerefMut}; + +#[repr(C)] +#[cfg_attr(feature = "unstable-experimental", deprecated(note = "renamed to GrayA"))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A pixel for grayscale value + alpha components (rgb crate v0.8) +/// +/// Through a `Deref` hack it renames the fields from `.0` and `.1` +/// to `.v` (value) and `.a` (alpha) +#[allow(non_camel_case_types)] +pub struct GrayAlpha_v08( + /// Grayscale Component + /// + /// This field has been renamed to `.v` + #[deprecated(note = "Please use the .v field instaed (it's available through the magic of Deref to GrayA type)")] + pub T, + /// Alpha Component. This field has been renamed to `.a`. + #[deprecated(note = "Please use the .a field instead (it's available through the magic of Deref to GrayA type)")] + pub A, +); + +impl GrayAlpha_v08 { + /// Reads the `.v` field + /// + /// Please use the `.v` field directly whenever possible. This function isn't necessary, and exists only to ease migration between major versions of the RGB crate. + #[allow(deprecated)] + pub fn value(self) -> T { + self.0 + } + + /// Exposes the `.v` field for writing + /// + /// Please use the `.v` field directly whenever possible. This function isn't necessary, and exists only to ease migration between major versions of the RGB crate. + #[allow(deprecated)] + pub fn value_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl Deref for GrayAlpha_v08 { + type Target = GrayA; + + /// A trick that allows using `.v` and `.a` on the old `GrayAlpha` type. + fn deref(&self) -> &GrayA { + unsafe { + &*(self as *const Self).cast::>() + } + } +} + +impl DerefMut for GrayAlpha_v08 { + /// A trick that allows using `.v` and `.a` on the old `GrayAlpha` type. + fn deref_mut(&mut self) -> &mut GrayA { + unsafe { + &mut *(self as *mut Self).cast::>() + } + } +} + +#[test] +#[allow(deprecated)] +fn swizzle() { + let mut g = GrayAlpha_v08(10u8, 20u8); + assert_eq!(10, g.v); + assert_eq!(20, g.a); + g.a = 7; + assert_eq!(10, g.v); + assert_eq!(7, g.1); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/grb.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/grb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/grb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/grb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Green + Red + Blue` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Grb; +/// +/// let pixel: Grb = Grb { g: 0, r: 0, b: 0 }; +/// ``` +pub struct Grb { + /// Green Component + pub g: T, + /// Red Component + pub r: T, + /// Blue Component + pub b: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Red + Green + Blue` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Rgb; +/// +/// let pixel: Rgb = Rgb { r: 0, g: 0, b: 0 }; +/// ``` +pub struct Rgb { + /// Red Component + pub r: T, + /// Green Component + pub g: T, + /// Blue Component + pub b: T, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/rgba.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgba.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/formats/rgba.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/formats/rgba.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +#[repr(C)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt-03", derive(defmt::Format))] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// A `Red + Green + Blue + Alpha` pixel. +/// +/// # Examples +/// +/// ``` +/// use rgb::Rgba; +/// +/// let pixel: Rgba = Rgba { r: 0, g: 0, b: 0, a: 255 }; +/// ``` +pub struct Rgba { + /// Red Component + pub r: T, + /// Green Component + pub g: T, + /// Blue Component + pub b: T, + /// Alpha Component + pub a: A, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/inherent_impls.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/inherent_impls.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/inherent_impls.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/inherent_impls.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +use crate::{Abgr, Argb, Bgr, Bgra, Grb, Rgb, Rgba}; +use crate::formats::gray_a::GrayA; +use crate::formats::gray::Gray_v08; +#[cfg(feature = "unstable-experimental")] +use crate::formats::gray::Gray_v09; +use crate::formats::gray_alpha::GrayAlpha_v08; + +macro_rules! inherent_impls { + ($name:ident, $new_fn:ident, [$($field:tt $var:ident),*]) => { + impl $name { + #[doc=concat!("Creates a new [`", stringify!($name), "`] pixel type from its components.")] + /// + /// Alternatively, you can use struct literal syntax to + /// create the new pixel type: + ///```not_rust + #[doc=concat!("use rgb::", stringify!($name), ";")] + /// + #[doc=concat!("let pixel = ", stringify!($name), " {", stringify!($($field: $var),*), "};")] + ///``` + #[allow(deprecated)] + pub const fn $new_fn($($var: T),*) -> Self { + Self {$($field: $var),*} + } + } + } +} + +inherent_impls!(Rgb, new, [r red, g green, b blue]); +inherent_impls!(Bgr, new_bgr, [b blue, g green, r red]); +inherent_impls!(Grb, new_grb, [g green, r red, b blue]); + +inherent_impls!(Gray_v08, new, [0 value]); +#[cfg(feature = "unstable-experimental")] +inherent_impls!(Gray_v09, new, [v value]); + +inherent_impls!(Rgba, new, [r red, g green, b blue, a alpha]); +inherent_impls!(Argb, new_argb, [a alpha, r red, g green, b blue]); +inherent_impls!(Bgra, new_bgra, [b blue, g green, r red, a alpha]); +inherent_impls!(Abgr, new_abgr, [a alpha, b blue, g green, r red]); +inherent_impls!(GrayA, new, [v value, a alpha]); + +inherent_impls!(GrayAlpha_v08, new, [0 value, 1 alpha]); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/alt.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/alt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/alt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/alt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,301 @@ +use crate::legacy::internal::pixel::{ComponentMap, ColorComponentMap, ComponentSlice}; +use core::slice; + +pub use crate::formats::gray::Gray_v08 as Gray; +pub use crate::formats::gray_alpha::GrayAlpha_v08 as GrayAlpha; + +/// Renamed to `Bgra` +#[doc(hidden)] +pub use crate::formats::bgra::Bgra as BGRA; + +/// Renamed to `Bgr` +#[doc(hidden)] +pub use crate::formats::bgr::Bgr as BGR; + +/// Renamed to `Abgr` +#[doc(hidden)] +pub use crate::formats::abgr::Abgr as ABGR; + +/// Renamed to `Argb` +#[doc(hidden)] +pub use crate::formats::argb::Argb as ARGB; + +/// Renamed to `Grb` +#[doc(hidden)] +pub use crate::formats::grb::Grb as GRB; + +/// 8-bit BGR +pub type BGR8 = crate::formats::bgr::Bgr; + +/// 16-bit BGR in machine's native endian +pub type BGR16 = crate::formats::bgr::Bgr; + +/// 8-bit BGRA +pub type BGRA8 = crate::formats::bgra::Bgra; + +/// 8-bit ABGR, alpha is first. 0 = transparent, 255 = opaque. +pub type ABGR8 = crate::formats::abgr::Abgr; + +/// 8-bit ARGB, alpha is first. 0 = transparent, 255 = opaque. +pub type ARGB8 = crate::Argb; + +/// 16-bit BGR in machine's native endian +pub type BGRA16 = crate::formats::bgra::Bgra; + +/// 16-bit ABGR in machine's native endian. 0 = transparent, 65535 = opaque. +pub type ABGR16 = crate::formats::abgr::Abgr; + +/// 16-bit ARGB in machine's native endian. 0 = transparent, 65535 = opaque. +pub type ARGB16 = crate::Argb; + +/// 8-bit GRB +pub type GRB8 = crate::formats::grb::Grb; + +/// 8-bit gray +#[deprecated(note = "Refer to ::rgb::alt::Gray directly (this type alias will change in the next major version)")] +pub type GRAY8 = Gray; + +/// 16-bit gray in machine's native endian +#[deprecated(note = "Refer to ::rgb::alt::Gray directly (this type alias will change in the next major version)")] +pub type GRAY16 = Gray; + +/// 8-bit gray with alpha in machine's native endian +#[deprecated(note = "Refer to ::rgb::alt::GrayAlpha directly (this type alias will change in the next major version)")] +pub type GRAYA8 = GrayAlpha; + +/// 16-bit gray with alpha in machine's native endian +#[deprecated(note = "Refer to ::rgb::alt::GrayAlpha directly (this type alias will change in the next major version)")] +pub type GRAYA16 = GrayAlpha; + + +#[cfg(not(feature = "unstable-experimental"))] +impl core::ops::Deref for Gray { + type Target = T; + + #[inline(always)] + #[allow(deprecated)] + fn deref(&self) -> &T { + &self.0 + } +} + +impl From for Gray { + #[inline(always)] + fn from(component: T) -> Self { + Self(component) + } +} + +impl GrayAlpha { + /// Copy `Gray` component out of the `GrayAlpha` struct + #[inline(always)] + #[allow(deprecated)] + pub fn gray(&self) -> Gray { + Gray(self.0.clone()) + } +} + +impl GrayAlpha { + /// Provide a mutable view of only `Gray` component (leaving out alpha). + #[inline(always)] + pub fn gray_mut(&mut self) -> &mut Gray { + unsafe { &mut *(self as *mut Self).cast() } + } +} + +impl GrayAlpha { + /// Create a new `GrayAlpha` with the new alpha value, but same gray value + #[doc(hidden)] + #[deprecated(note = "use .with_alpha(a) instead; this will become a getter in the future")] + pub fn alpha(&self, a: A) -> Self { + self.with_alpha(a) + } + + /// Create a new `GrayAlpha` with the new alpha value, but same gray value + #[inline(always)] + #[allow(deprecated)] + pub fn with_alpha(&self, a: A) -> Self { + Self(self.0, a) + } + + /// Create a new `GrayAlpha` with a new alpha value created by the callback. + #[inline(always)] + #[allow(deprecated)] + pub fn map_alpha(&self, f: F) -> GrayAlpha + where F: FnOnce(A) -> B + { + GrayAlpha(self.0, f(self.1.clone())) + } + + /// Create new `GrayAlpha` with the same alpha value, but different `Gray` value + #[inline(always)] + #[allow(deprecated)] + pub fn map_gray(&self, f: F) -> GrayAlpha + where F: FnOnce(T) -> U, U: Clone, B: From + Clone { + GrayAlpha(f(self.0), self.1.clone().into()) + } +} + +impl ComponentMap, T, B> for Gray { + #[inline(always)] + #[allow(deprecated)] + fn map(&self, mut f: F) -> Gray where F: FnMut(T) -> B { + Gray(f(self.0)) + } +} + +impl ColorComponentMap, T, B> for Gray { + #[inline(always)] + #[allow(deprecated)] + fn map_colors(&self, mut f: F) -> Gray where F: FnMut(T) -> B { + Gray(f(self.0)) + } +} + +impl ComponentMap, T, B> for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn map(&self, mut f: F) -> GrayAlpha + where F: FnMut(T) -> B { + GrayAlpha(f(self.0), f(self.1)) + } +} + +impl ColorComponentMap, T, B> for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn map_colors(&self, mut f: F) -> GrayAlpha + where F: FnMut(T) -> B { + GrayAlpha(f(self.0), self.1) + } +} + +impl ComponentSlice for GrayAlpha { + #[inline(always)] + fn as_slice(&self) -> &[T] { + unsafe { + slice::from_raw_parts((self as *const Self).cast::(), 2) + } + } + + #[inline(always)] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + slice::from_raw_parts_mut((self as *mut Self).cast::(), 2) + } + } +} + +impl ComponentSlice for [GrayAlpha] { + #[inline] + fn as_slice(&self) -> &[T] { + unsafe { + slice::from_raw_parts(self.as_ptr().cast(), self.len() * 2) + } + } + + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr().cast::(), self.len() * 2) + } + } +} + +impl ComponentSlice for Gray { + #[inline(always)] + #[allow(deprecated)] + fn as_slice(&self) -> &[T] { + slice::from_ref(&self.0) + } + + #[inline(always)] + #[allow(deprecated)] + fn as_mut_slice(&mut self) -> &mut [T] { + slice::from_mut(&mut self.0) + } +} + +impl ComponentSlice for [Gray] { + #[inline] + fn as_slice(&self) -> &[T] { + unsafe { + slice::from_raw_parts(self.as_ptr().cast(), self.len()) + } + } + + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr().cast::(), self.len()) + } + } +} + +/// Assumes 255 is opaque +impl From> for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn from(other: Gray) -> Self { + Self(other.0, 0xFF) + } +} + +/// Assumes 65535 is opaque +impl From> for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn from(other: Gray) -> Self { + Self(other.0, 0xFFFF) + } +} + +#[test] +#[allow(deprecated)] +fn gray() { + let rgb: crate::RGB<_> = Gray(1).into(); + assert_eq!(rgb.r, 1); + assert_eq!(rgb.g, 1); + assert_eq!(rgb.b, 1); + + let rgba: crate::RGBA<_> = Gray(1u8).into(); + assert_eq!(rgba.r, 1); + assert_eq!(rgba.g, 1); + assert_eq!(rgba.b, 1); + assert_eq!(rgba.a, 255); + + let g: GRAY8 = 200.into(); + let g = g.map(|c| c / 2); + #[cfg(not(feature = "unstable-experimental"))] + assert_eq!(110, *g + 10); + #[cfg(not(feature = "unstable-experimental"))] + assert_eq!(110, 10 + Gray(100).as_ref()); + + let ga: GRAYA8 = GrayAlpha(1, 2); + assert_eq!(ga.gray(), Gray::new(1)); + let mut g2 = ga.clone(); + *g2.gray_mut() = Gray(3); + assert_eq!(g2.map_gray(|g| g + 1), GRAYA8::new(4, 2)); + assert_eq!(g2.map(|g| g + 1), GrayAlpha(4, 3)); + assert_eq!(g2.0, 3); + assert_eq!(g2.as_slice(), &[3, 2]); + assert_eq!(g2.as_mut_slice(), &[3, 2]); + assert_eq!(g2.with_alpha(13), GrayAlpha(3, 13)); + assert_eq!(g2.map_alpha(|x| x + 3), GrayAlpha(3, 5)); + + assert_eq!((&[Gray(1u16), Gray(2)][..]).as_slice(), &[1, 2]); + assert_eq!((&[GrayAlpha(1u16, 2), GrayAlpha(3, 4)][..]).as_slice(), &[1, 2, 3, 4]); + + let rgba: crate::RGBA<_> = ga.into(); + assert_eq!(rgba.r, 1); + assert_eq!(rgba.g, 1); + assert_eq!(rgba.b, 1); + assert_eq!(rgba.a, 2); + + let ga: GRAYA16 = GrayAlpha(1, 2); + let rgba: crate::RGBA = ga.into(); + assert_eq!(rgba.r, 1); + assert_eq!(rgba.g, 1); + assert_eq!(rgba.b, 1); + assert_eq!(rgba.a, 2); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/array.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/array.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/array.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/array.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,112 @@ +use crate::alt::ARGB; +use crate::alt::{BGR, BGRA}; +use crate::{RGB, RGBA}; + +impl From<[T; 3]> for RGB { + #[inline(always)] + fn from(other: [T; 3]) -> Self { + Self { + r: other[0], + g: other[1], + b: other[2], + } + } +} + +impl From> for [T; 3] { + #[inline(always)] + fn from(value: RGB) -> Self { + [value.r, value.g, value.b] + } +} + +impl From<[T; 4]> for RGBA { + #[inline(always)] + fn from(other: [T; 4]) -> Self { + Self { + r: other[0], + g: other[1], + b: other[2], + a: other[3], + } + } +} + +impl From> for [T; 4] { + #[inline(always)] + fn from(value: RGBA) -> Self { + [value.r, value.g, value.b, value.a] + } +} + +impl From<[T; 4]> for ARGB { + #[inline(always)] + fn from(other: [T; 4]) -> Self { + Self { + a: other[0], + r: other[1], + g: other[2], + b: other[3], + } + } +} + +impl Into<[T; 4]> for ARGB { + #[inline(always)] + fn into(self) -> [T; 4] { + [self.a, self.r, self.g, self.b] + } +} + +impl From<[T; 3]> for BGR { + #[inline(always)] + fn from(other: [T; 3]) -> Self { + Self { + b: other[0], + g: other[1], + r: other[2], + } + } +} + +impl From> for [T; 3] { + #[inline(always)] + fn from(value: BGR) -> Self { + [value.b, value.g, value.r] + } +} + +impl From<[T; 4]> for BGRA { + #[inline(always)] + fn from(other: [T; 4]) -> Self { + Self { + b: other[0], + g: other[1], + r: other[2], + a: other[3], + } + } +} + +impl From> for [T; 4] { + #[inline(always)] + fn from(value: BGRA) -> Self { + [value.b, value.g, value.r, value.a] + } +} + +#[test] +#[allow(deprecated)] +fn convert_array() { + use crate::alt::{BGR8, BGRA8}; + use crate::{RGB8, RGBA8}; + + assert_eq!(RGB8::from([1, 2, 3]), RGB8::new(1, 2, 3)); + assert_eq!(Into::<[u8; 3]>::into(RGB8::new(1, 2, 3)), [1, 2, 3]); + assert_eq!(RGBA8::from([1, 2, 3, 4]), RGBA8::new(1, 2, 3, 4)); + assert_eq!(Into::<[u8; 4]>::into(RGBA8::new(1, 2, 3, 4)), [1, 2, 3, 4]); + assert_eq!(BGR8::from([3, 2, 1]), BGR8::new(1, 2, 3)); + assert_eq!(Into::<[u8; 3]>::into(BGR8::new(1, 2, 3)), [3, 2, 1]); + assert_eq!(BGRA8::from([3, 2, 1, 4]), BGRA8::new(1, 2, 3, 4)); + assert_eq!(Into::<[u8; 4]>::into(BGRA8::new(1, 2, 3, 4)), [3, 2, 1, 4]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,504 @@ +use super::pixel::{ComponentSlice, ComponentMap}; +use crate::alt::{BGR, BGRA, GRB, Gray, GrayAlpha, ARGB, ABGR}; +use crate::{RGB, RGBA}; +use core::{mem, slice}; + +mod array; +mod tuple; + +/// Use [`::bytemuck::cast_slice()`] instead. +/// +/// Casts a slice of bytes into a slice of pixels, e.g. `[u8]` to `[RGB8]`. +/// +/// See also `FromSlice` +pub trait AsPixels { + /// Use [`::bytemuck::cast_slice()`] instead. + /// + /// Reinterpret the slice as a read-only/shared slice of pixels. + /// Multiple consecutive elements in the slice are intepreted as a single pixel + /// (depending on format, e.g. 3 for RGB, 4 for RGBA). + /// + /// Leftover elements are ignored if the slice isn't evenly divisible into pixels. + /// + /// Use this method only when the type is known from context. + /// See also `FromSlice`. + fn as_pixels(&self) -> &[PixelType]; + /// Use [`::bytemuck::cast_slice_mut()`] instead. + /// + /// Reinterpret the slice as a mutable/exclusive slice of pixels. + /// Multiple consecutive elements in the slice are intepreted as a single pixel + /// (depending on format, e.g. 3 for RGB, 4 for RGBA). + /// + /// Leftover elements are ignored if the slice isn't evenly divisible into pixels. + /// + /// Use this method only when the type is known from context. + /// See also `FromSlice`. + fn as_pixels_mut(&mut self) -> &mut [PixelType]; +} + +macro_rules! as_pixels_impl { + ($typ:ident, $elems:expr) => { + impl AsPixels<$typ> for [T] { + fn as_pixels(&self) -> &[$typ] { + unsafe { + slice::from_raw_parts(self.as_ptr() as *const _, self.len() / $elems) + } + } + + fn as_pixels_mut(&mut self) -> &mut [$typ] { + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() / $elems) + } + } + } + }; +} + +as_pixels_impl! {RGB, 3} +as_pixels_impl! {RGBA, 4} +as_pixels_impl! {BGR, 3} +as_pixels_impl! {BGRA, 4} +as_pixels_impl! {GRB, 3} +as_pixels_impl! {Gray, 1} +as_pixels_impl! {GrayAlpha, 2} +as_pixels_impl! {ARGB, 4} +as_pixels_impl! {ABGR, 4} + +/// Use [`::bytemuck::cast_slice()`] or [`::bytemuck::from_bytes()`] to convert +/// +/// Cast a slice of component values (bytes) as a slice of RGB/RGBA pixels +/// +/// If there's any incomplete pixel at the end of the slice it is ignored. +pub trait FromSlice { + /// Reinterpert slice as RGB pixels + fn as_rgb(&self) -> &[RGB]; + /// Reinterpert slice as RGBA pixels + fn as_rgba(&self) -> &[RGBA]; + /// Reinterpert slice as alpha-first ARGB pixels + fn as_argb(&self) -> &[ARGB]; + /// Reinterpert mutable slice as RGB pixels + fn as_rgb_mut(&mut self) -> &mut [RGB]; + /// Reinterpert mutable slice as RGBA pixels + fn as_rgba_mut(&mut self) -> &mut [RGBA]; + /// Reinterpert mutable slice as alpha-first ARGB pixels + fn as_argb_mut(&mut self) -> &mut [ARGB]; + + /// Reinterpert mutable slice as grayscale pixels + fn as_gray(&self) -> &[Gray]; + /// Reinterpert mutable slice as grayscale pixels with alpha + fn as_gray_alpha(&self) -> &[GrayAlpha]; + /// Reinterpert mutable slice as grayscale pixels + fn as_gray_mut(&mut self) -> &mut [Gray]; + /// Reinterpert mutable slice as grayscale pixels with alpha + fn as_gray_alpha_mut(&mut self) -> &mut [GrayAlpha]; + + /// Reinterpert slice as reverse-order BGR pixels + fn as_bgr(&self) -> &[BGR]; + /// Reinterpert slice as reverse-order BGRA pixels + fn as_bgra(&self) -> &[BGRA]; + /// Reinterpert slice as reverse-order ABGR pixels + fn as_abgr(&self) -> &[ABGR]; + /// Reinterpert ntable slice as reverse-order BGR pixels + fn as_bgr_mut(&mut self) -> &mut [BGR]; + /// Reinterpert mutable slice as reverse-order alpha-last BGRA pixels + fn as_bgra_mut(&mut self) -> &mut [BGRA]; + /// Reinterpert mutable slice as reverse-order alpha-first ABGR pixels + fn as_abgr_mut(&mut self) -> &mut [ABGR]; +} + +impl FromSlice for [T] { + #[inline] + fn as_rgb(&self) -> &[RGB] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_rgba(&self) -> &[RGBA] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_argb(&self) -> &[ARGB] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_rgb_mut(&mut self) -> &mut [RGB] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_rgba_mut(&mut self) -> &mut [RGBA] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_argb_mut(&mut self) -> &mut [ARGB] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_gray(&self) -> &[Gray] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_gray_alpha(&self) -> &[GrayAlpha] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_gray_mut(&mut self) -> &mut [Gray] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_gray_alpha_mut(&mut self) -> &mut [GrayAlpha] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_bgr(&self) -> &[BGR] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_abgr(&self) -> &[ABGR] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_bgra(&self) -> &[BGRA] { + unsafe { from_items_to_struct(self) } + } + + #[inline] + fn as_bgr_mut(&mut self) -> &mut [BGR] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_bgra_mut(&mut self) -> &mut [BGRA] { + unsafe { from_items_to_struct_mut(self) } + } + + #[inline] + fn as_abgr_mut(&mut self) -> &mut [ABGR] { + unsafe { from_items_to_struct_mut(self) } + } +} + +#[inline(always)] +unsafe fn from_items_to_struct(from: &[F]) -> &[T] { + debug_assert_eq!(0, mem::size_of::() % mem::size_of::()); + let len = from.len() / (mem::size_of::() / mem::size_of::()); + slice::from_raw_parts(from.as_ptr().cast::(), len) +} + +#[inline(always)] +unsafe fn from_items_to_struct_mut(from: &mut [F]) -> &mut [T] { + debug_assert_eq!(0, mem::size_of::() % mem::size_of::()); + let len = from.len() / (mem::size_of::() / mem::size_of::()); + slice::from_raw_parts_mut(from.as_mut_ptr().cast::(), len) +} + +macro_rules! rgb_impl_from { + ($typename:ident, $from:ty, $to:ty) => { + impl From<$typename<$from>> for $typename<$to> { + #[inline(always)] + fn from(other: $typename<$from>) -> Self { + other.map(core::convert::Into::into) + } + } + }; +} + +rgb_impl_from! {RGB, u8,i16} +rgb_impl_from! {RGB, u8,i32} +rgb_impl_from! {RGB, u8,u16} +rgb_impl_from! {RGB, u8,u32} +rgb_impl_from! {RGB, u16,i32} +rgb_impl_from! {RGB, u16,u32} +rgb_impl_from! {RGB, u16,u64} + +rgb_impl_from! {RGB, u8,f32} +rgb_impl_from! {RGB, u8,f64} +rgb_impl_from! {RGB, u16,f32} +rgb_impl_from! {RGB, u16,f64} + +rgb_impl_from! {RGB, i16,f32} +rgb_impl_from! {RGB, i16,f64} + +rgb_impl_from! {RGB, i32,f64} +rgb_impl_from! {RGB, f32,f64} + +rgb_impl_from! {RGBA, u16,i32} +rgb_impl_from! {RGBA, u16,u32} +rgb_impl_from! {RGBA, u16,u64} + +rgb_impl_from! {RGBA, u8,i16} +rgb_impl_from! {RGBA, u8,u16} +rgb_impl_from! {RGBA, u8,u32} +rgb_impl_from! {RGBA, u8,f32} +rgb_impl_from! {RGBA, u8,f64} +rgb_impl_from! {RGBA, u16,f32} +rgb_impl_from! {RGBA, u16,f64} + +rgb_impl_from! {RGBA, i16,f32} +rgb_impl_from! {RGBA, i16,f64} + +rgb_impl_from! {RGBA, i32,f64} +rgb_impl_from! {RGBA, f32,f64} + +macro_rules! reorder_impl_from { + (@rgb $t1:ident, $t2:ident) => { + reorder_impl_from!(@once $t1, $t2, r, g, b); + reorder_impl_from!(@once $t2, $t1, r, g, b); + }; + (@rgba $t1:ident, $t2:ident) => { + reorder_impl_from!(@once $t1, $t2, r, g, b, a); + reorder_impl_from!(@once $t2, $t1, r, g, b, a); + }; + (@once $t1:ident, $t2:ident, $($component:ident),+) => { + impl From<$t1> for $t2 where T: ::core::clone::Clone { + fn from(other: $t1) -> Self { + let $t1 { $($component),+ } = other; + Self { + $($component),+ + } + } + } + } +} + +reorder_impl_from!(@rgba RGBA, ARGB); +reorder_impl_from!(@rgba ABGR, ARGB); +reorder_impl_from!(@rgba BGRA, ARGB); +reorder_impl_from!(@rgba BGRA, ABGR); + +reorder_impl_from!(@rgb RGB, BGR); +reorder_impl_from!(@rgba BGRA, RGBA); +reorder_impl_from!(@rgba ABGR, RGBA); +reorder_impl_from!(@rgb RGB, GRB); + +impl From> for RGB { + #[inline(always)] + #[allow(deprecated)] + fn from(other: Gray) -> Self { + Self { + r: other.0.clone(), + g: other.0.clone(), + b: other.0, + } + } +} + +impl From> for RGBA { + #[inline(always)] + #[allow(deprecated)] + fn from(other: Gray) -> Self { + Self { + r: other.0.clone(), + g: other.0.clone(), + b: other.0, + a: 255, + } + } +} + +impl From> for RGBA { + #[inline(always)] + #[allow(deprecated)] + fn from(other: GrayAlpha) -> Self { + Self { + r: other.0.clone(), + g: other.0.clone(), + b: other.0, + a: other.1, + } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsRef for Gray { + #[inline(always)] + #[allow(deprecated)] + fn as_ref(&self) -> &T { + &self.0 + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsRef<[T]> for RGB { + #[inline(always)] + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsRef<[T; 3]> for RGB { + fn as_ref(&self) -> &[T; 3] { + unsafe { &*(self as *const Self).cast() } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsRef<[T]> for RGBA { + #[inline(always)] + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsRef<[T; 4]> for RGBA { + fn as_ref(&self) -> &[T; 4] { + unsafe { &*(self as *const Self).cast() } + } +} + +impl AsRef<[T; 4]> for ARGB { + fn as_ref(&self) -> &[T; 4] { + unsafe { &*(self as *const Self).cast() } + } +} + +impl AsRef<[T; 4]> for BGRA { + fn as_ref(&self) -> &[T; 4] { + unsafe { &*(self as *const Self).cast() } + } +} + +impl AsRef<[T; 4]> for ABGR { + fn as_ref(&self) -> &[T; 4] { + unsafe { &*(self as *const Self).cast() } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsRef for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn as_ref(&self) -> &T { + &self.0 + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsRef<[T; 2]> for GrayAlpha { + fn as_ref(&self) -> &[T; 2] { + unsafe { &*(self as *const Self).cast() } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsMut for Gray { + #[inline(always)] + #[allow(deprecated)] + fn as_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsMut<[T]> for RGB { + #[inline(always)] + fn as_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsMut<[T; 3]> for RGB { + fn as_mut(&mut self) -> &mut [T; 3] { + unsafe { &mut *(self as *mut Self).cast() } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsMut<[T]> for RGBA { + #[inline(always)] + fn as_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsMut<[T; 4]> for RGBA { + fn as_mut(&mut self) -> &mut [T; 4] { + unsafe { &mut *(self as *mut Self).cast() } + } +} + +#[cfg(not(feature = "unstable-experimental"))] +impl AsMut for GrayAlpha { + #[inline(always)] + #[allow(deprecated)] + fn as_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +#[cfg(feature = "unstable-experimental")] +impl AsMut<[T; 2]> for GrayAlpha { + fn as_mut(&mut self) -> &mut [T; 2] { + unsafe { &mut *(self as *mut Self).cast() } + } +} + +#[test] +fn argb_converts() { + let argb = ARGB { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc }; + let rgba = RGBA { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc }; + + assert_eq!(RGBA::from(argb), rgba); + assert_eq!(ARGB::from(rgba), argb); + assert_eq!(rgba.rgb(), argb.rgb()); + + let bgra = BGRA { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f }; + let abgr = ABGR { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f }; + + assert_eq!(BGRA::from(abgr), bgra); + assert_eq!(ABGR::from(bgra), abgr); +} + +#[test] +fn converts() { + assert_eq!([1,2].as_gray(), [Gray::new(1), Gray::new(2)]); + assert_eq!([3].as_gray_mut(), [Gray::new(3)]); + assert_eq!([1,2].as_gray_alpha(), [GrayAlpha::new(1, 2)]); + // excess bytes are ignored + assert_eq!([1,2,3].as_gray_alpha_mut(), [GrayAlpha::new(1, 2)]); + assert_eq!([1,2,3,4].as_gray_alpha_mut(), [GrayAlpha::new(1, 2), GrayAlpha::new(3, 4)]); + + assert_eq!(RGBA::new(1u8,2,3,255), RGB::new(1u8,2,3).into()); + assert_eq!(RGBA::new(1u16,2,3,65535), RGB::new(1u16,2,3).into()); + assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, BGR{r:1u8,g:2u8,b:3u8}.into()); + assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, RGB{r:1u8,g:2u8,b:3u8}.into()); + assert_eq!(RGBA {r:1u8,g:2,b:3,a:4u8}, BGRA{r:1u8,g:2u8,b:3u8,a:4u8}.into()); + assert_eq!(BGR {r:1u8,g:2,b:3u8}, RGB {r:1u8,g:2,b:3u8}.into()); + assert_eq!(RGB {r:1u16,g:0x5678,b:0xABCDu16}, BGR {r:1u16,g:0x5678,b:0xABCDu16}.into()); + assert_eq!(BGR {r:0x1234567u32,g:2,b:3u32}, RGB {r:0x1234567u32,g:2,b:3u32}.into()); + + assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_slice()); + assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_ref()); + assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_slice()); + assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_ref()); + + assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut_slice()); + assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut()); +} + + +#[test] +#[cfg(feature = "unstable-experimental")] +fn as_refs() { + let mut r = RGBA::new(1u8,2,3,4u8); + assert_eq!(&[1,2,3,4], AsRef::<[u8; 4]>::as_ref(&r)); + assert_eq!([1,2,3,4], *AsMut::<[u8; 4]>::as_mut(&mut r)); + + let mut r = GrayAlpha::new(1u8,4u8); + assert_eq!(&[1,4], AsRef::<[u8; 2]>::as_ref(&r)); + assert_eq!([1,4], *AsMut::<[u8; 2]>::as_mut(&mut r)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/tuple.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/tuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/tuple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/convert/tuple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ + +use crate::formats::gray::Gray_v08; +use crate::{Abgr, Argb, Bgr, Bgra, Grb, Rgb, Rgba, alt::GrayAlpha}; + +#[cfg(feature = "unstable-experimental")] +use crate::GrayA; +#[cfg(feature = "unstable-experimental")] +use crate::formats::gray::Gray_v09; + +macro_rules! tuple_conversion { + ($name:ident, 1, [$($bit:tt:$num:tt),*]) => { + impl From<$name> for (S,) where R: Into { + #[allow(deprecated)] + fn from(value: $name) -> Self { + ($(value.$bit.into()),*,) + } + } + }; + ($name:ident, 2, [$($bit:tt:$num:tt),*]) => { + impl From<$name> for (S, S) where R: Into { + #[allow(deprecated)] + fn from(value: $name) -> Self { + ($(value.$bit.into()),*) + } + } + impl From<(R, R)> for $name where R: Into { + #[allow(deprecated)] + fn from(value: (R, R)) -> Self { + Self{$($bit: value.$num.into()),*} + } + } + }; + ($name:ident, 3, [$($bit:tt:$num:tt),*]) => { + impl From<$name> for (S, S, S) where R: Into { + fn from(value: $name) -> Self { + ($(value.$bit.into()),*) + } + } + impl From<(R, R, R)> for $name where R: Into { + fn from(value: (R, R, R)) -> Self { + Self{$($bit: value.$num.into()),*} + } + } + }; + ($name:ident, 4, [$($bit:tt:$num:tt),*]) => { + impl From<$name> for (S, S, S, S) where R: Into { + fn from(value: $name) -> Self { + ($(value.$bit.into()),*) + } + } + impl From<(R, R, R, R)> for $name where R: Into { + fn from(value: (R, R, R, R)) -> Self { + Self{$($bit: value.$num.into()),*} + } + } + }; +} + + +tuple_conversion!(Rgb, 3, [r:0, g:1, b:2]); +tuple_conversion!(Bgr, 3, [b:0, g:1, r:2]); +tuple_conversion!(Grb, 3, [g:0, r:1, b:2]); +#[cfg(feature = "unstable-experimental")] +tuple_conversion!(Gray_v09, 1, [v:0]); + + +tuple_conversion!(Rgba, 4, [r:0, g:1, b:2, a:3]); +tuple_conversion!(Argb, 4, [a:0, r:1, g:2, b:3]); +tuple_conversion!(Bgra, 4, [b:0, g:1, r:2, a:3]); +tuple_conversion!(Abgr, 4, [a:0, b:1, g:2, r:3]); +#[cfg(feature = "unstable-experimental")] +tuple_conversion!(GrayA, 2, [v:0, a:1]); + +tuple_conversion!(Gray_v08, 1, [0:0]); +tuple_conversion!(GrayAlpha, 2, [0:0, 1:1]); + +#[test] +fn converts() { + assert_eq!((1,2,3), Rgb {r:1u8,g:2,b:3}.into()); + assert_eq!(Rgb {r:1u8,g:2,b:3}, (1,2,3).into()); + assert_eq!((1,2,3,4), Rgba {r:1,g:2,b:3,a:4}.into()); + assert_eq!(Rgba {r:1u8,g:2,b:3,a:4}, (1,2,3,4).into()); + assert_eq!(Bgra {r:1u8,g:2,b:3,a:4}, (3,2,1,4).into()); + assert_eq!(Bgr {r:1u8,g:2,b:3}, (3,2,1).into()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/ops.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/ops.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/ops.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/ops.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,498 @@ +use crate::formats::gray::Gray_v08 as Gray; +use super::pixel::ComponentMap; +use crate::alt::GrayAlpha; +use crate::alt::ARGB; +use crate::alt::GRB; +use crate::{RGB, RGBA}; +use core::iter::Sum; +use core::ops::{Sub, SubAssign, Add, AddAssign, Mul, MulAssign, Div, DivAssign}; + +#[cfg(feature = "checked_fns")] +macro_rules! impl_struct_checked { + ($ty:ident, $field_ty:ident, => $($field:tt)+) => { + impl $ty<$field_ty> + { + /// `px.checked_add(px)` + #[inline(always)] + #[allow(deprecated)] + pub fn checked_add(self, rhs: $ty<$field_ty>) -> Option { + Some($ty { + $( + $field: self.$field.checked_add(rhs.$field)?, + )+ + }) + } + + /// `px.checked_sub(px)` + #[inline(always)] + #[allow(deprecated)] + pub fn checked_sub(self, rhs: $ty<$field_ty>) -> Option { + Some($ty { + $( + $field: self.$field.checked_sub(rhs.$field)?, + )+ + }) + } + } + } +} + +#[cfg(not(feature = "checked_fns"))] +macro_rules! impl_struct_checked { + ($ty:ident, $field_ty:ident, => $($field:tt)+) => {}; +} + +macro_rules! impl_struct_ops_opaque { + ($ty:ident => $($field:tt)+) => { + /// `px + px` + impl Add for $ty { + type Output = $ty<::Output>; + + #[inline(always)] + #[allow(deprecated)] + fn add(self, other: $ty) -> Self::Output { + $ty { + $( + $field: self.$field + other.$field, + )+ + } + } + } + + /// `px + px` + impl AddAssign for $ty where + T: Add + Copy + { + #[inline(always)] + #[allow(deprecated)] + fn add_assign(&mut self, other: $ty) { + *self = Self { + $( + $field: self.$field + other.$field, + )+ + }; + } + } + + /// `px * px` + impl Mul for $ty { + type Output = $ty<::Output>; + + #[inline(always)] + #[allow(deprecated)] + fn mul(self, other: $ty) -> Self::Output { + $ty { + $( + $field: self.$field * other.$field, + )+ + } + } + } + + /// `px * px` + impl MulAssign for $ty where + T: Mul + Copy + { + #[inline(always)] + #[allow(deprecated)] + fn mul_assign(&mut self, other: $ty) { + *self = Self { + $( + $field: self.$field * other.$field, + )+ + }; + } + } + + /// `px - px` + impl Sub for $ty { + type Output = $ty<::Output>; + + #[inline(always)] + #[allow(deprecated)] + fn sub(self, other: $ty) -> Self::Output { + $ty { + $( + $field: self.$field - other.$field, + )+ + } + } + } + + /// `px - px` + impl SubAssign for $ty where + T: Sub + Copy + { + #[inline(always)] + #[allow(deprecated)] + fn sub_assign(&mut self, other: $ty) { + *self = Self { + $( + $field: self.$field - other.$field, + )+ + }; + } + } + + impl Sum<$ty> for $ty where T: Default + Add { + #[inline(always)] + fn sum>(iter: I) -> Self { + iter.fold($ty::default(), Add::add) + } + } + + impl_struct_checked!($ty, u8, => $($field)+); + impl_struct_checked!($ty, u16, => $($field)+); + impl_struct_checked!($ty, u32, => $($field)+); + impl_struct_checked!($ty, u64, => $($field)+); + impl_struct_checked!($ty, i8, => $($field)+); + impl_struct_checked!($ty, i16, => $($field)+); + impl_struct_checked!($ty, i32, => $($field)+); + impl_struct_checked!($ty, i64, => $($field)+); + }; +} + +macro_rules! impl_struct_ops_alpha { + ($ty:ident => $($field:tt)+) => { + /// `px + px` + impl Add for $ty { + type Output = $ty<::Output, ::Output>; + + #[inline(always)] + #[allow(deprecated)] + fn add(self, other: $ty) -> Self::Output { + $ty { + $( + $field: self.$field + other.$field, + )+ + } + } + } + + /// `px + px` + impl AddAssign for $ty where + T: Add + Copy, + A: Add + Copy + { + #[inline(always)] + #[allow(deprecated)] + fn add_assign(&mut self, other: $ty) { + *self = Self { + $( + $field: self.$field + other.$field, + )+ + }; + } + } + + /// `px - px` + impl Sub for $ty { + type Output = $ty<::Output, ::Output>; + + #[inline(always)] + #[allow(deprecated)] + fn sub(self, other: $ty) -> Self::Output { + $ty { + $( + $field: self.$field - other.$field, + )+ + } + } + } + + /// `px - px` + impl SubAssign for $ty where + T: Sub + Copy, + A: Sub + Copy + { + #[inline(always)] + #[allow(deprecated)] + fn sub_assign(&mut self, other: $ty) { + *self = Self { + $( + $field: self.$field - other.$field, + )+ + }; + } + } + + impl Sum<$ty> for $ty where T: Default + Add, A: Default + Add { + #[inline(always)] + fn sum>(iter: I) -> Self { + iter.fold($ty::default(), Add::add) + } + } + + impl_struct_checked!($ty, u8, => $($field)+); + impl_struct_checked!($ty, u16, => $($field)+); + impl_struct_checked!($ty, u32, => $($field)+); + impl_struct_checked!($ty, u64, => $($field)+); + impl_struct_checked!($ty, i8, => $($field)+); + impl_struct_checked!($ty, i16, => $($field)+); + impl_struct_checked!($ty, i32, => $($field)+); + impl_struct_checked!($ty, i64, => $($field)+); + }; +} + +macro_rules! impl_scalar { + ($ty:ident) => { + /// `px - 1` + impl Sub for $ty + where T: Copy + Sub + { + type Output = $ty<::Output>; + + #[inline(always)] + fn sub(self, r: T) -> Self::Output { + self.map(|l| l - r) + } + } + + /// `px - 1` + impl SubAssign for $ty + where T: Copy + Sub + { + #[inline(always)] + fn sub_assign(&mut self, r: T) { + *self = self.map(|l| l - r); + } + } + + /// `px + 1` + impl Add for $ty + where T: Copy + Add + { + type Output = $ty; + + #[inline(always)] + fn add(self, r: T) -> Self::Output { + self.map(|l| l + r) + } + } + + /// `px + 1` + impl AddAssign for $ty + where T: Copy + Add + { + #[inline(always)] + fn add_assign(&mut self, r: T) { + *self = self.map(|l| l + r); + } + } + + /// `px * 1` + impl Mul for $ty + where T: Copy + Mul + { + type Output = $ty; + + #[inline(always)] + fn mul(self, r: T) -> Self::Output { + self.map(|l| l * r) + } + } + + /// `px * 1` + impl MulAssign for $ty + where T: Copy + Mul + { + #[inline(always)] + fn mul_assign(&mut self, r: T) { + *self = self.map(|l| l * r); + } + } + + /// `px / 1` + impl Div for $ty + where T: Copy + Div + { + type Output = $ty; + + #[inline(always)] + fn div(self, r: T) -> Self::Output { + self.map(|l| l / r) + } + } + + /// `px * 1` + impl DivAssign for $ty + where T: Copy + Div + { + #[inline(always)] + fn div_assign(&mut self, r: T) { + *self = self.map(|l| l / r); + } + } + }; +} + +impl_scalar! {RGB} +impl_scalar! {RGBA} +impl_scalar! {ARGB} +impl_scalar! {GRB} +impl_scalar! {Gray} +impl_scalar! {GrayAlpha} + +impl_struct_ops_opaque! {RGB => r g b} +impl_struct_ops_opaque! {GRB => g r b} +impl_struct_ops_opaque! {Gray => 0} + +impl_struct_ops_alpha! {RGBA => r g b a} +impl_struct_ops_alpha! {ARGB => a r g b} +impl_struct_ops_alpha! {GrayAlpha => 0 1} + +#[cfg(test)] +mod test { + use super::*; + use core::num::Wrapping; + const WHITE_RGB: RGB = RGB::new(255, 255, 255); + const BLACK_RGB: RGB = RGB::new(0, 0, 0); + const RED_RGB: RGB = RGB::new(255, 0, 0); + const GREEN_RGB: RGB = RGB::new(0, 255, 0); + const BLUE_RGB: RGB = RGB::new(0, 0, 255); + + const WHITE_RGBA: RGBA = RGBA::new(255, 255, 255, 255); + const BLACK_RGBA: RGBA = RGBA::new(0, 0, 0, 0); + const RED_RGBA: RGBA = RGBA::new(255, 0, 0, 255); + const GREEN_RGBA: RGBA = RGBA::new(0, 255, 0, 0); + const BLUE_RGBA: RGBA = RGBA::new(0, 0, 255, 255); + + #[test] + fn test_add() { + assert_eq!(RGB::new(2,4,6), RGB::new(1,2,3) + RGB{r:1,g:2,b:3}); + assert_eq!(RGB::new(2.,4.,6.), RGB::new(1.,3.,5.) + 1.); + + assert_eq!(RGBA::new_alpha(2f32,4.,6.,8u32), RGBA::new_alpha(1f32,2.,3.,4u32) + RGBA{r:1f32,g:2.0,b:3.0,a:4u32}); + assert_eq!(RGBA::new(2i16,4,6,8), RGBA::new(1,3,5,7) + 1); + + assert_eq!(RGB::new(255, 255, 0), RED_RGB+GREEN_RGB); + assert_eq!(RGB::new(255, 0, 0), RED_RGB+RGB::new(0, 0, 0)); + assert_eq!(WHITE_RGB, BLACK_RGB + 255); + + assert_eq!(RGBA::new(255, 255, 0, 255), RED_RGBA+GREEN_RGBA); + assert_eq!(RGBA::new(255, 0, 0, 255), RED_RGBA+RGBA::new(0, 0, 0, 0)); + assert_eq!(WHITE_RGBA, BLACK_RGBA + 255); + } + + #[test] + #[cfg(feature = "checked_fns")] + fn test_checked_add() { + assert_eq!(WHITE_RGB.checked_add(WHITE_RGB), None); + assert_eq!(RGB::::new(255, 255, 255).checked_add(RGB::::new(255, 0, 0)), None); + assert_eq!(RGB::::new(255, 255, 255).checked_add(RGB::::new(0, 255, 0)), None); + assert_eq!(RGB::::new(255, 255, 255).checked_add(RGB::::new(0, 0, 255)), None); + assert_eq!(WHITE_RGBA.checked_add(BLACK_RGBA), Some(WHITE_RGBA)); + + assert_eq!(RGB::::new(-128, 2, 3).checked_add(RGB::::new(-1, 0, 0)), None); + assert_eq!(RGB::::new(2, -128, 3).checked_add(RGB::::new(0, -1, 0)), None); + assert_eq!(RGB::::new(2, 2, -128).checked_add(RGB::::new(0, 0, -1)), None); + assert_eq!(RGB::::new(2, 2, -128).checked_add(RGB::::new(0, 0, 1)), Some(RGB::::new(2, 2, -127))); + } + + #[test] + #[should_panic] + #[cfg(debug_assertions)] + fn test_add_overflow() { + assert_ne!(RGBA::new(255u8, 255, 0, 0), RED_RGBA + BLUE_RGBA); + } + + #[test] + fn test_sub() { + assert_eq!(RED_RGB, (WHITE_RGB - GREEN_RGB) - BLUE_RGB); + assert_eq!(BLACK_RGB, WHITE_RGB - 255); + + assert_eq!(RGBA::new(255, 255, 0, 0), WHITE_RGBA - BLUE_RGBA); + assert_eq!(BLACK_RGBA, WHITE_RGBA - 255); + } + + #[test] + #[cfg(feature = "checked_fns")] + fn test_checked_sub() { + assert_eq!(RGBA::::new(2,4,6,111).checked_sub(RGBA::::new(3,4,6,0)), None); + assert_eq!(RGB::::new(2,4,6).checked_sub(RGB::::new(2,5,6)), None); + assert_eq!(RGB::::new(2,4,6).checked_sub(RGB::::new(2,4,7)), None); + assert_eq!(RGB::::new(2,4,6).checked_sub(RGB::::new(2,4,6)), Some(BLACK_RGB)); + + assert_eq!(RGB::::new(-128,4,6).checked_sub(RGB::::new(1,4,7)), None); + assert_eq!(RGB::::new(2,-128,6).checked_sub(RGB::::new(2,1,7)), None); + assert_eq!(RGB::::new(2,4,-128).checked_sub(RGB::::new(2,4,1)), None); + assert_eq!(RGB::::new(2,4,6).checked_sub(RGB::::new(-2,4,6)), Some(RGB::::new(4,0,0))); + } + + #[test] + fn test_add_assign() { + let mut green_rgb = RGB::new(0, 255, 0); + green_rgb += RGB::new(255, 0, 255); + assert_eq!(WHITE_RGB, green_rgb); + + let mut black_rgb = RGB::new(0, 0, 0); + black_rgb += 255; + assert_eq!(WHITE_RGB, black_rgb); + + let mut green_rgba = RGBA::new(0, 255, 0, 0); + green_rgba += RGBA::new(255, 0, 255, 255); + assert_eq!(WHITE_RGBA, green_rgba); + + let mut black_rgba = RGBA::new(0, 0, 0, 0); + black_rgba += 255; + assert_eq!(WHITE_RGBA, black_rgba); + } + + #[test] + fn test_sub_assign() { + let mut green_rgb = RGB::new(0, 255, 0); + green_rgb -= RGB::new(0, 255, 0); + assert_eq!(BLACK_RGB, green_rgb); + + let mut white_rgb = RGB::new(255, 255, 255); + white_rgb -= 255; + assert_eq!(BLACK_RGB, white_rgb); + + let mut green_rgba = RGBA::new(0, 255, 0, 0); + green_rgba -= RGBA::new(0, 255, 0, 0); + assert_eq!(BLACK_RGBA, green_rgba); + + let mut white_rgba = RGBA::new(255, 255, 255, 255); + white_rgba -= 255; + assert_eq!(BLACK_RGBA, white_rgba); + } + + #[test] + fn test_mult() { + assert_eq!(RGB::new(0.5,1.5,2.5), RGB::new(1.,3.,5.) * 0.5); + assert_eq!(RGBA::new(2,4,6,8), RGBA::new(1,2,3,4) * 2); + assert_eq!(RGB::new(0.5,1.5,2.5) * RGB::new(1.,3.,5.), + RGB::new(0.5,4.5,12.5)); + } + + #[test] + fn test_mult_assign() { + let mut green_rgb = RGB::new(0u16, 255, 0); + green_rgb *= 1; + assert_eq!(RGB::new(0, 255, 0), green_rgb); + green_rgb *= 2; + assert_eq!(RGB::new(0, 255*2, 0), green_rgb); + + let mut rgb = RGB::new(0.5,1.5,2.5); + rgb *= RGB::new(1.,3.,5.); + assert_eq!(rgb, RGB::new(0.5,4.5,12.5)); + + let mut green_rgba = RGBA::new(0u16, 255, 0, 0); + green_rgba *= 1; + assert_eq!(RGBA::new(0, 255, 0, 0), green_rgba); + green_rgba *= 2; + assert_eq!(RGBA::new(0, 255*2, 0, 0), green_rgba); + } + + #[test] + fn sum() { + let s1 = [RGB::new(1u8,1,1), RGB::new(2,3,4)].iter().copied().sum::>(); + let s2 = [RGB::new(1u16,1,1), RGB::new(2,3,4)].iter().copied().sum::>(); + let s3 = [RGBA::new_alpha(1u16,1,1,Wrapping(1u16)), RGBA::new_alpha(2,3,4,Wrapping(5))].iter().copied().sum::>>(); + let s4 = [RGBA::new_alpha(1u16,1,1,1u16), RGBA::new_alpha(2,3,4,5)].iter().copied().sum::>(); + assert_eq!(s1, RGB::new(3, 4, 5)); + assert_eq!(s2, RGB::new(3, 4, 5)); + assert_eq!(s3, RGBA::new_alpha(3, 4, 5, Wrapping(6))); + assert_eq!(s4, RGBA::new_alpha(3, 4, 5, 6)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/pixel.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/pixel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/pixel.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/pixel.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,99 @@ +/// Casting the struct to slices of its components +pub trait ComponentSlice { + /// The components interpreted as an array, e.g. one `RGB` expands to 3 elements. + /// + /// It's implemented for individual pixels as well as slices of pixels. + fn as_slice(&self) -> &[T]; + + /// The components interpreted as a mutable array, e.g. one `RGB` expands to 3 elements. + /// + /// It's implemented for individual pixels as well as slices of pixels. + /// + /// If you get an error when calling this on an array, add `[..]` + /// + /// > use of unstable library feature 'array_methods' + /// + /// ```rust,ignore + /// arr[..].as_mut_slice() + /// ``` + fn as_mut_slice(&mut self) -> &mut [T]; +} + +/// Use [`::bytemuck::cast_slice()`] instead. +/// +/// Casting a slice of `RGB/A` values to a slice of `u8` +/// +/// If instead of `RGB8` you use `RGB`, and you want to cast from/to that custom type, +/// implement the `Plain` trait for it: +/// +/// ```rust +/// # #[derive(Copy, Clone)] +/// # struct MyCustomType; +/// unsafe impl rgb::Pod for MyCustomType {} +/// unsafe impl rgb::Zeroable for MyCustomType {} +/// ``` +/// +/// Plain types are not allowed to contain struct padding, booleans, chars, enums, references or pointers. +#[cfg(feature = "as-bytes")] +pub trait ComponentBytes where Self: ComponentSlice { + /// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first. + #[inline] + fn as_bytes(&self) -> &[u8] { + assert_ne!(0, core::mem::size_of::()); + let slice = self.as_slice(); + unsafe { + core::slice::from_raw_parts(slice.as_ptr().cast(), core::mem::size_of_val(slice)) + } + } + + /// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first. + #[inline] + fn as_bytes_mut(&mut self) -> &mut [u8] { + assert_ne!(0, core::mem::size_of::()); + let slice = self.as_mut_slice(); + unsafe { + core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), core::mem::size_of_val(slice)) + } + } +} + +/// Applying operation to every component +/// +/// ```rust +/// use rgb::prelude::*; +/// # let pixel = rgb::RGB::new(0u8,0,0); +/// let inverted = pixel.map(|c| 255 - c); +/// +/// // For simple math there are Add/Sub/Mul implementations: +/// let halved = pixel.map(|c| c / 2); +/// let doubled = pixel * 2; +/// ``` +pub trait ComponentMap { + /// Convenience function (equivalent of `self.iter().map().collect()`) for applying the same formula to every component. + /// + /// Note that it returns the pixel directly, not an Interator. + fn map(&self, f: Callback) -> DestPixel + where Callback: FnMut(SrcComponent) -> DestComponent; +} + +/// Same as `ComponentMap`, but doesn't change the alpha channel (if there's any alpha). +/// +/// Import via `use rgb::prelude::*;` instead of directly. +pub trait ColorComponentMap { + /// Convenience function for applying the same formula to every rgb/gray component, but skipping the alpha component. + /// + /// Note that it returns the pixel directly, not an Interator. + #[doc(alias = "map_colors_same")] + fn map_colors(&self, f: Callback) -> DestPixel + where Callback: FnMut(SrcComponent) -> DestComponent { + #[allow(deprecated)] + self.map_c(f) + } + + /// Alias of `map_colors` + #[deprecated(note = "renamed to map_colors")] + fn map_c(&self, f: Callback) -> DestPixel + where Callback: FnMut(SrcComponent) -> DestComponent { + self.map_colors(f) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgb.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgb.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgb.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgb.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,238 @@ +use super::pixel::{ComponentSlice, ComponentMap, ColorComponentMap}; +#[cfg(feature = "as-bytes")] +use super::pixel::{ComponentBytes}; +use crate::alt::GRB; +use crate::alt::{BGR, BGRA}; +use crate::{RGB, RGBA}; +use core::fmt; + +impl BGR { + /// Convenience function for creating a new pixel + /// Warning: The order of arguments is R,G,B + #[deprecated(note = "This function has a misleading order of arguments. Use BGR{} literal instead")] + pub const fn new(r: T, g: T, b: T) -> Self { + Self { b, g, r } + } +} + +macro_rules! impl_rgb { + ($RGB:ident) => { + impl $RGB { + /// Iterate over color components (R, G, and B) + #[inline(always)] + pub fn iter(&self) -> core::iter::Cloned> { + self.as_slice().iter().cloned() + } + } + + impl ComponentMap<$RGB, T, B> for $RGB { + #[inline(always)] + fn map(&self, mut f: F) -> $RGB + where F: FnMut(T) -> B { + $RGB { + r:f(self.r), + g:f(self.g), + b:f(self.b), + } + } + } + + impl ColorComponentMap<$RGB, T, B> for $RGB { + #[inline(always)] + fn map_colors(&self, mut f: F) -> $RGB + where F: FnMut(T) -> B { + $RGB { + r:f(self.r), + g:f(self.g), + b:f(self.b), + } + } + } + + impl ComponentSlice for $RGB { + #[inline(always)] + fn as_slice(&self) -> &[T] { + unsafe { + core::slice::from_raw_parts(self as *const Self as *const T, 3) + } + } + + #[inline(always)] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 3) + } + } + } + + impl ComponentSlice for [$RGB] { + #[inline] + fn as_slice(&self) -> &[T] { + unsafe { + core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 3) + } + } + + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 3) + } + } + } + + #[cfg(feature = "as-bytes")] + impl ComponentBytes for [$RGB] {} + }; +} + +macro_rules! impl_rgb_to_alpha { + ($RGB:ident, $RGBA:ident) => { + impl $RGB { + /// Convenience function for converting to RGBA + #[doc(hidden)] + #[deprecated(note = "use .with_alpha(a) instead; this will become a getter in the future")] + pub fn alpha(&self, a: T) -> $RGBA { + self.with_alpha(a) + } + + /// Convenience function for converting to RGBA + #[inline(always)] + #[doc(alias = "alpha")] + pub fn with_alpha(&self, a: T) -> $RGBA { + $RGBA { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + a, + } + } + + /// Convenience function for converting to RGBA with alpha channel of a different type than type of the pixels + #[inline(never)] + #[deprecated(note = "use .with_alpha(a) instead")] + pub fn new_alpha(&self, a: A) -> $RGBA { + $RGBA { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + a, + } + } + } + }; +} + +impl core::iter::FromIterator for RGB { + /// Takes exactly 3 elements from the iterator and creates a new instance. + /// Panics if there are fewer elements in the iterator. + #[inline(always)] + fn from_iter>(into_iter: I) -> Self { + let mut iter = into_iter.into_iter(); + Self { + r: iter.next().unwrap(), + g: iter.next().unwrap(), + b: iter.next().unwrap(), + } + } +} + +impl_rgb! {RGB} +impl_rgb_to_alpha! {RGB, RGBA} +impl_rgb! {BGR} +impl_rgb_to_alpha! {BGR, BGRA} +impl_rgb! {GRB} + +impl fmt::Display for RGB { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "rgb({},{},{})", self.r, self.g, self.b) + } +} + +impl fmt::UpperHex for RGB { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "RGB {{ #{:02X}{:02X}{:02X} }}", self.r, self.g, self.b) + } +} + +impl fmt::LowerHex for RGB { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "RGB {{ #{:02x}{:02x}{:02x} }}", self.r, self.g, self.b) + } +} + +impl fmt::Display for BGR { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "bgr({},{},{})", self.b, self.g, self.r) + } +} + +impl fmt::UpperHex for BGR { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "BGR {{ #{:02X}{:02X}{:02X} }}", self.b, self.g, self.r) + } +} + +impl fmt::LowerHex for BGR { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "BGR {{ #{:02x}{:02x}{:02x} }}", self.b, self.g, self.r) + } +} + +#[cfg(test)] +mod rgb_test { + use super::*; + + #[test] + fn grb_test() { + let grb = GRB {g:1,r:2,b:3}.map(|c| c * 2) + 1; + let rgb: crate::RGB8 = grb.into(); + assert_eq!(rgb, RGB::new(5,3,7)); + } + + #[test] + fn sanity_check() { + let neg = RGB::new(1,2,3i32).map(|x| -x); + assert_eq!(neg.r, -1); + assert_eq!(neg.g, -2); + assert_eq!(neg.b, -3); + + let mut px = RGB::new(3,4,5); + px.as_mut_slice()[1] = 111; + assert_eq!(111, px.g); + + assert_eq!(RGBA::new(250,251,252,253), RGB::new(250,251,252).with_alpha(253)); + + assert_eq!(RGB{r:1u8,g:2,b:3}, RGB::new(1u8,2,3)); + assert!(RGB{r:1u8,g:1,b:2} < RGB::new(2,1,1)); + + let mut h = std::collections::HashSet::new(); + h.insert(px); + assert!(h.contains(&RGB::new(3,111,5))); + assert!(!h.contains(&RGB::new(111,5,3))); + + + #[cfg(feature = "as-bytes")] + { + let v = vec![RGB::new(1u8,2,3), RGB::new(4,5,6)]; + assert_eq!(&[1,2,3,4,5,6], v.as_bytes()); + } + + assert_eq!(RGB::new(0u8,0,0), Default::default()); + } + + #[test] + #[allow(deprecated)] + fn test_fmt() { + let red_rgb = RGB::new(255, 0, 0); + let red_bgr = BGR::new(255, 0, 0); + assert_eq!("RGB { #FF0000 }", &format!("{:X}", red_rgb)); + assert_eq!("BGR { #0000FF }", &format!("{:X}", red_bgr)); + + assert_eq!("RGB { #ff0000 }", &format!("{:x}", red_rgb)); + assert_eq!("BGR { #0000ff }", &format!("{:x}", red_bgr)); + + assert_eq!("rgb(255,0,0)", &format!("{}", red_rgb)); + assert_eq!("bgr(0,0,255)", &format!("{}", red_bgr)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgba.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgba.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgba.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/legacy/internal/rgba.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,434 @@ +use super::pixel::{ComponentSlice, ComponentMap, ColorComponentMap}; +#[cfg(feature = "as-bytes")] +use super::pixel::{ComponentBytes}; +use crate::alt::{BGRA, ARGB, ABGR, BGR}; +use crate::{RGB, RGBA}; +use core::fmt; + +impl RGBA { + #[inline(always)] + /// Convenience function for creating a new pixel + /// The order of arguments is R,G,B,A + pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self { + Self { r, g, b, a } + } +} + +impl BGRA { + #[inline(always)] + /// Convenience function for creating a new pixel + /// Warning: The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use BGRA{} literal instead")] + pub const fn new(r: T, g: T, b: T, a: T) -> Self { + Self { b, g, r, a } + } +} + +/// ```rust,compile_fail +/// let r = rgb::BGRA::::zeroed(); +/// ``` +impl BGRA { + #[inline(always)] + /// Convenience function for creating a new pixel + /// Warning: The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use BGRA{} literal instead")] + pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self { + Self { b, g, r, a } + } +} + +impl ARGB { + #[inline(always)] + /// Convenience function for creating a new pixel + /// The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use ARGB{} literal instead")] + pub const fn new(r: T, g: T, b: T, a: T) -> Self { + Self { a, r, g, b } + } +} + +impl ARGB { + #[inline(always)] + /// Convenience function for creating a new pixel + /// The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use ARGB{} literal instead")] + pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self { + Self { a, r, g, b } + } +} + +impl ABGR { + #[inline(always)] + /// Convenience function for creating a new pixel + /// The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use ABGR{} literal instead")] + pub const fn new(r: T, g: T, b: T, a: T) -> Self { + Self { a, b, g, r } + } +} + +impl ABGR { + #[inline(always)] + /// Convenience function for creating a new pixel + /// The order of arguments is R,G,B,A + #[deprecated(note = "This function has a misleading order of arguments. Use ABGR{} literal instead")] + pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self { + Self { a, b, g, r } + } +} + +macro_rules! impl_rgba { + ($RGBA:ident) => { + impl $RGBA { + /// Iterate over all components (length=4) + #[inline(always)] + pub fn iter(&self) -> core::iter::Cloned> { + self.as_slice().iter().cloned() + } + } + + impl $RGBA { + /// Copy RGB components out of the RGBA struct + /// + /// Note: you can use `.into()` to convert between other types + #[inline(always)] + pub fn bgr(&self) -> BGR { + BGR { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + } + } + } + + impl $RGBA { + /// Create new RGBA with the same alpha value, but different RGB values + #[deprecated(note = "Renamed to map_colors()")] + pub fn map_rgb(&self, mut f: F) -> $RGBA + where F: FnMut(T) -> U, U: Clone, B: From + Clone + { + $RGBA { + r: f(self.r), + g: f(self.g), + b: f(self.b), + a: self.a.clone().into(), + } + } + + #[doc(hidden)] + #[deprecated(note = "use .with_alpha(a) instead")] + /// Create a new RGBA with the new alpha value, but same RGB values + pub fn alpha(&self, a: A) -> Self { + self.with_alpha(a) + } + + #[inline(always)] + /// Create a new RGBA with the new alpha value, but same RGB values + pub fn with_alpha(&self, a: A) -> Self { + Self { r: self.r, g: self.g, b: self.b, a } + } + + /// Create a new RGBA with a new alpha value created by the callback. + /// Allows changing of the type used for the alpha channel. + #[inline] + pub fn map_alpha(&self, f: F) -> $RGBA + where F: FnOnce(A) -> B { + $RGBA { + r: self.r, + g: self.g, + b: self.b, + a: f(self.a.clone()), + } + } + } + + impl ComponentMap<$RGBA, T, B> for $RGBA { + #[inline(always)] + fn map(&self, mut f: F) -> $RGBA + where F: FnMut(T) -> B { + $RGBA { + r: f(self.r), + g: f(self.g), + b: f(self.b), + a: f(self.a), + } + } + } + + impl ColorComponentMap<$RGBA, T, B> for $RGBA { + #[inline(always)] + fn map_colors(&self, mut f: F) -> $RGBA + where F: FnMut(T) -> B { + $RGBA { + r: f(self.r), + g: f(self.g), + b: f(self.b), + a: self.a, + } + } + } + + impl ComponentSlice for $RGBA { + #[inline(always)] + fn as_slice(&self) -> &[T] { + unsafe { + core::slice::from_raw_parts(self as *const Self as *const T, 4) + } + } + + #[inline(always)] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 4) + } + } + } + + impl ComponentSlice for [$RGBA] { + #[inline] + fn as_slice(&self) -> &[T] { + unsafe { + core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 4) + } + } + + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 4) + } + } + } + + #[cfg(feature = "as-bytes")] + impl ComponentBytes for [$RGBA] {} + }; +} + +macro_rules! impl_alpha_conv { + ($RGB:ident, $RGBA:ident) => { + /// Assumes 255 is opaque + impl From<$RGB> for $RGBA { + #[inline(always)] + fn from(other: $RGB) -> Self { + Self { + r: other.r, + g: other.g, + b: other.b, + a: 0xFF, + } + } + } + + /// Assumes 65535 is opaque + impl From<$RGB> for $RGBA { + #[inline(always)] + fn from(other: $RGB) -> Self { + Self { + r: other.r, + g: other.g, + b: other.b, + a: 0xFFFF, + } + } + } + }; +} + +impl RGBA { + /// Provide a mutable view of only RGB components (leaving out alpha). + /// Useful to change color without changing opacity. + #[inline(always)] + pub fn rgb_mut(&mut self) -> &mut RGB { + unsafe { &mut *(self as *mut Self).cast::>() } + } +} + +impl BGRA { + /// Provide a mutable view of only RGB components (leaving out alpha). + /// Useful to change color without changing opacity. + #[deprecated(note = "This function will change. Use bgr_mut()")] + pub fn rgb_mut(&mut self) -> &mut BGR { + unsafe { &mut *(self as *mut Self).cast::>() } + } + + /// Provide a mutable view of only RGB components (leaving out alpha). + /// Useful to change color without changing opacity. + #[inline(always)] + pub fn bgr_mut(&mut self) -> &mut BGR { + unsafe { &mut *(self as *mut Self).cast::>() } + } +} + +impl core::iter::FromIterator for RGBA { + #[inline(always)] + /// Takes exactly 4 elements from the iterator and creates a new instance. + /// Panics if there are fewer elements in the iterator. + fn from_iter>(into_iter: I) -> Self { + let mut iter = into_iter.into_iter(); + Self { + r: iter.next().unwrap(), + g: iter.next().unwrap(), + b: iter.next().unwrap(), + a: iter.next().unwrap(), + } + } +} + +impl RGBA { + /// Copy RGB components out of the RGBA struct + /// + /// Note: you can use `.into()` to convert between other types + #[inline(always)] + pub fn rgb(&self) -> RGB { + RGB { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + } + } +} + +impl ARGB { + /// Copy RGB components out of the ARGB struct + /// + /// Note: you can use `.into()` to convert between other types + #[inline(always)] + pub fn rgb(&self) -> RGB { + RGB { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + } + } +} + +impl BGRA { + /// Copy RGB components out of the RGBA struct + /// + /// Note: you can use `.into()` to convert between other types + #[deprecated(note = "This function will change. Use bgr()")] + pub fn rgb(&self) -> BGR { + BGR { + r: self.r.clone(), + g: self.g.clone(), + b: self.b.clone(), + } + } +} + +impl_rgba! {RGBA} +impl_rgba! {BGRA} +impl_rgba! {ARGB} +impl_rgba! {ABGR} + +impl_alpha_conv! {BGR, BGRA} +impl_alpha_conv! {RGB, BGRA} +impl_alpha_conv! {BGR, RGBA} +impl_alpha_conv! {RGB, RGBA} +impl_alpha_conv! {BGR, ABGR} +impl_alpha_conv! {RGB, ABGR} +impl_alpha_conv! {BGR, ARGB} +impl_alpha_conv! {RGB, ARGB} + +impl fmt::Display for RGBA { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "rgba({},{},{},{})", self.r, self.g, self.b, self.a) + } +} + +impl fmt::Display for BGRA { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "bgra({},{},{},{})", self.r, self.g, self.b, self.a) + } +} + +#[test] +fn rgba_test() { + let neg = RGBA::new(1,2,3i32,1000).map(|x| -x); + assert_eq!(neg.r, -1); + assert_eq!(neg.rgb().r, -1); + assert_eq!(neg.g, -2); + assert_eq!(neg.rgb().g, -2); + assert_eq!(neg.b, -3); + assert_eq!(neg.rgb().b, -3); + assert_eq!(neg.a, -1000); + assert_eq!(neg.map_alpha(|x| x+1).a, -999); + assert_eq!(neg, neg.as_slice().iter().copied().collect()); + assert!(neg < RGBA::new(0,0,0,0)); + + #[allow(deprecated)] + let neg = RGBA::new(1u8,2,3,4).map_rgb(|c| -(c as i16)); + assert_eq!(-1i16, neg.r); + assert_eq!(4i16, neg.a); + let neg = RGBA::new(1u8,2,3,4).map_colors(|c| -(c as i16)); + assert_eq!(-1i16, neg.r); + assert_eq!(4u8, neg.a); + + let mut px = RGBA{r:1,g:2,b:3,a:4}; + px.as_mut_slice()[3] = 100; + assert_eq!(1, px.rgb_mut().r); + assert_eq!(2, px.rgb_mut().g); + px.rgb_mut().b = 4; + assert_eq!(4, px.rgb_mut().b); + assert_eq!(100, px.a); + + #[cfg(feature = "as-bytes")] + { + let v = vec![RGBA::new(1u8,2,3,4), RGBA::new(5,6,7,8)]; + assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes()); + } +} + +#[test] +#[cfg(feature = "as-bytes")] +fn abgr_test() { + let abgr = ABGR {r:1,g:2,b:3,a:4}; + assert_eq!(4, abgr.as_slice()[0]); + use crate::AsPixels; + assert_eq!(abgr, [abgr].as_bytes().as_pixels()[0]); +} + +#[test] +#[allow(deprecated)] +fn bgra_test() { + let neg = BGRA::new(1, 2, 3i32, 1000).map(|x| -x); + let _ = neg.as_slice(); + + #[cfg(feature = "as-bytes")] + { + let _ = [neg].as_bytes(); + } + assert_eq!(neg.r, -1); + assert_eq!(neg.bgr().r, -1); + assert_eq!(neg.g, -2); + assert_eq!(neg.bgr().g, -2); + assert_eq!(neg.b, -3); + assert_eq!(neg.bgr().b, -3); + assert_eq!(neg.a, -1000); + assert_eq!(&[-3,-2,-1,-1000], neg.as_slice()); + assert!(neg < BGRA::new(0, 0, 0, 0)); + + let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_rgb(|c| -(c as i16)); + assert_eq!(-1i16, neg.r); + assert_eq!(4i16, neg.a); + #[allow(deprecated)] + let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_c(|c| -(c as i16)); + assert_eq!(-1i16, neg.r); + assert_eq!(4u8, neg.a); + + let mut px = BGRA{r:1,g:2,b:3,a:-9}.alpha(4); + px.as_mut_slice()[3] = 100; + assert_eq!(1, px.bgr_mut().r); + assert_eq!(2, px.bgr_mut().g); + px.bgr_mut().b = 4; + assert_eq!(4, px.bgr_mut().b); + assert_eq!(100, px.a); + + + #[cfg(feature = "as-bytes")] + { + let v = vec![BGRA::new(3u8, 2, 1, 4), BGRA::new(7, 6, 5, 8)]; + assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/rgb/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rgb/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,254 @@ +//! Basic struct for `RGB` and `RGBA` pixels. Packed, with red first, alpha last. +//! +//! This crate is intended to be the lowest common denominator for sharing `RGB`/`RGBA` bitmaps between other crates. +//! +//! The crate includes convenience functions for converting between the struct and bytes, +//! and overloaded operators that work on all channels at once. +//! +//! This crate intentionally doesn't implement color management (due to complexity of the problem), +//! but the structs can be parametrized to implement this if necessary. Other colorspaces are out of scope. +//! +#![cfg_attr(feature = "as-bytes", doc = "```rust")] +#![cfg_attr(not(feature = "as-bytes"), doc = "```ignore")] +//! # use rgb::*; +//! let pixel = RGB8 {r:0, g:100, b:255}; +//! +//! let pixel_rgba = pixel.alpha(255); +//! let pixel = pixel_rgba.rgb(); +//! +//! let pixels = vec![pixel; 100]; +//! /// Can be converted to a type-less slice without copying +//! let bytes: &[u8] = rgb::bytemuck::cast_slice(&pixels); +//! +//! use rgb::prelude::*; // Import pixel map trait +//! let half_bright = pixel.map(|channel| channel / 2); +//! let doubled = half_bright * 2; +//! # let _ = doubled; +//! ``` +#![doc(html_logo_url = "https://kornel.ski/rgb-logo.png")] +#![warn(missing_docs)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![no_std] + +// std is required to run unit tests +#[cfg(test)] +#[macro_use] extern crate std; +/// Re-export of the [`bytemuck` crate](https://lib.rs/bytemuck). [See docs](https://docs.rs/bytemuck). +/// +/// Use [`::bytemuck::cast_slice()`] or [`::bytemuck::from_bytes()`] to convert +/// pixels to/from `&[u8]`. +#[cfg(feature = "bytemuck")] +#[doc(alias = "ComponentSlice")] +#[doc(alias = "as_bytes")] +#[doc(alias = "Pod")] +pub use ::bytemuck; + +pub(crate) mod formats { + pub mod abgr; + pub mod argb; + pub mod bgr; + pub mod bgra; + pub mod gray; + pub mod gray_a; + pub mod gray_alpha; + pub mod grb; + pub mod rgb; + pub mod rgba; +} + +/// Use as `use rgb::prelude::*` +/// +/// The prelude will contain commonly used traits, and will be expanded in the future. +/// +/// Using a glob import is recommended for forward compatibility with the next major version of the crate. +pub mod prelude { + pub use crate::legacy::internal::pixel::ComponentMap; + pub use crate::legacy::internal::pixel::ColorComponentMap; +} + +pub use formats::abgr::Abgr; +pub use formats::argb::Argb; +pub use formats::bgr::Bgr; +pub use formats::bgra::Bgra; +#[cfg(not(feature = "unstable-experimental"))] +pub use formats::gray_alpha::GrayAlpha_v08 as GrayAlpha; +#[cfg(not(feature = "unstable-experimental"))] +pub use formats::gray::Gray_v08 as Gray; +pub use formats::grb::Grb; +pub use formats::rgb::Rgb; +pub use formats::rgba::Rgba; + +mod inherent_impls; + +pub(crate) mod legacy { + pub(crate) mod internal { + pub mod convert; + pub mod ops; + pub mod pixel; + pub mod rgb; + pub mod rgba; + } + /// BGR/BGRA alernative layouts & grayscale + /// + /// BGR might be useful for some Windows or OpenGL APIs. + pub mod alt; +} + +pub use legacy::alt; + +#[cfg(all(feature = "bytemuck", not(feature = "as-bytes")))] +mod bytemuck_impl; +#[cfg(feature = "as-bytes")] +mod as_bytes; + +/// Re-export from `bytemuck` crate +#[cfg(feature = "as-bytes")] +pub use ::bytemuck::Pod; +/// Re-export from `bytemuck` crate +#[cfg(feature = "as-bytes")] +pub use ::bytemuck::Zeroable; + +pub use crate::legacy::internal::convert::*; +pub use crate::legacy::internal::pixel::*; + +#[doc(hidden)] +/// Renamed to `Rgb` +pub use formats::rgb::Rgb as RGB; +#[doc(hidden)] +/// Renamed to `Rgba` +pub use formats::rgba::Rgba as RGBA; + +#[doc(hidden)] +/// Incompatible replacement for the `GrayAlpha` type +pub use formats::gray_a::GrayA; + +#[cfg(feature = "unstable-experimental")] +pub use formats::gray::Gray_v09 as Gray; + +/// 8-bit RGB +/// +/// The colorspace is technically undefined, but generally sRGB is assumed. +pub type RGB8 = RGB; + +/// 16-bit RGB in machine's native endian +/// +/// Be careful to perform byte-swapping when reading from files. +pub type RGB16 = RGB; + +/// 8-bit RGBA, alpha is last. 0 = transparent, 255 = opaque. +pub type RGBA8 = RGBA; + +/// 16-bit RGB in machine's native endian. 0 = transparent, 65535 = opaque. +/// +/// Alpha is last. +pub type RGBA16 = RGBA; + +#[test] +fn rgb_works() { + let rgb = RGB{r:0u8,g:128,b:255}.clone(); + assert_eq!(rgb.b, 255); + + assert_eq!(rgb, rgb.iter().map(|ch| ch).collect()); + + #[cfg(feature = "as-bytes")] + { + assert_eq!(0, [rgb].as_bytes()[0]); + assert_eq!(128, [rgb].as_bytes()[1]); + assert_eq!(255, [rgb].as_bytes()[2]); + } + + let rgb = RGB16{r:0u16,g:0x7F7F,b:65535}; + assert_eq!(rgb.b, 65535); + assert_eq!(rgb.as_slice()[1], 0x7F7F); + + #[cfg(feature = "as-bytes")] + { + assert_eq!(0, [rgb].as_bytes()[0]); + assert_eq!(0, [rgb].as_bytes()[1]); + assert_eq!(0x7F, [rgb].as_bytes()[2]); + assert_eq!(0x7F, [rgb].as_bytes()[3]); + assert_eq!(0xFF, [rgb].as_bytes()[4]); + assert_eq!(0xFF, [rgb].as_bytes()[5]); + } + + assert_eq!("rgb(1,2,3)", format!("{}", RGB::new(1,2,3))); +} + +#[test] +fn sub_floats() { + assert_eq!(RGBA{r:2.5_f64, g:-1.5, b:0., a:5.}, RGBA{r:3.5_f64, g:-0.5, b:-2., a:0.} - RGBA{r:1.0_f64, g:1., b:-2., a:-5.}); +} + +#[test] +fn into() { + let a:RGB8 = RGB{r:0,g:1,b:2}; + let b:RGB = a.into(); + let c:RGB = b.into(); + let d:RGB = a.into(); + assert_eq!(c, d); +} + +#[test] +fn rgba_works() { + let rgba = RGBA{r:0u8,g:128,b:255,a:33}.clone(); + assert_eq!(rgba.b, 255); + assert_eq!(rgba.a, 33); + + assert_eq!(rgba, rgba.iter().map(|ch| ch).collect()); + + assert_eq!("rgba(1,2,3,4)", format!("{}", RGBA::new(1,2,3,4))); + + assert_eq!(rgba - rgba, RGBA::new(0,0,0,0)); +} + +#[test] +fn bytes() { + let rgb = RGB8::new(1,2,3); + + #[cfg(feature = "as-bytes")] + { + let rgb_arr = [rgb]; + let rgb_bytes = rgb_arr.as_bytes(); + assert_eq!(&[1,2,3], rgb_bytes); + assert_eq!(rgb_bytes.as_rgba().len(), 0); + assert_eq!({let t: &[RGBA8] = rgb_bytes.as_pixels(); t}.len(), 0); + assert_eq!(rgb, rgb_bytes.into_iter().cloned().collect()); + assert_eq!(&[rgb], rgb_bytes.as_rgb()); + assert_eq!(&[rgb], rgb_bytes.as_pixels()); + } + let mut rgb2 = [rgb]; + assert_eq!(rgb2[..].as_mut_slice().as_rgb_mut(), &mut [rgb]); + assert_eq!(&mut [rgb], rgb2[..].as_mut_slice().as_pixels_mut()); + + + #[cfg(feature = "as-bytes")] + { + let rgba = RGBA8::new(1,2,3,4); + let mut rgba_arr = [rgba]; + let rgba_bytes = rgba_arr.as_bytes_mut(); + assert_eq!(&[1,2,3,4], rgba_bytes); + assert_eq!(&[rgba], rgba_bytes.as_rgba()); + rgba_bytes[3] = 99; + assert_eq!(RGBA8::new(1,2,3,99), rgba_arr.as_bytes().into_iter().cloned().collect()); + } + + let rgb = RGB16::new(1,2,3); + let rgb_slice = rgb.as_slice(); + assert_eq!(&[1,2,3], rgb_slice); + assert_eq!(rgb_slice.as_rgba(), &[]); + assert_eq!(&[rgb], rgb_slice.as_rgb()); + assert_eq!(rgb, rgb_slice.into_iter().cloned().collect()); + + let rgba = RGBA16::new(1,2,3,4); + let rgba_slice = rgba.as_slice(); + assert_eq!(&[1,2,3,4], rgba_slice); + assert_eq!(&[1,2,3], rgba_slice.as_rgb()[0].as_slice()); + assert_eq!(&[rgba], rgba_slice.as_rgba()); + assert_eq!(rgba, rgba_slice.iter().copied().collect()); + let mut rgba2 = [rgba]; + assert_eq!(rgba2[..].as_mut_slice().as_rgba_mut(), &mut [rgba]); + + let mut foo = vec![0u8; 8]; + foo.as_rgba_mut()[1] = RGBA::new(1,2,3,4); + assert_eq!(&[0u8,0,0,0,1,2,3,4], &foo[..]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CODE_OF_CONDUCT.md":"edca092fde496419a9f1ba640048aa0270b62dfea576cd3175f0b53e3c230470","Cargo.toml":"647814b27b6fc4fbef1df70d796b53b723e776b68467372044e4182763007379","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cac8197ac869d64a6efc26cab883a269392ae6db51f7453bca722f8f31d67c7c","src/lib.rs":"ddecafb5db609d0d8eebd19e4d98dc865e7e9282a4183421f9bd765c01a231c0"},"package":"08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"7fe00878e217385a2b89256f7a2d6bb1bdc9eac39365df004eeb373441b632c5","CODE_OF_CONDUCT.md":"edca092fde496419a9f1ba640048aa0270b62dfea576cd3175f0b53e3c230470","Cargo.toml":"647814b27b6fc4fbef1df70d796b53b723e776b68467372044e4182763007379","Cargo.toml.orig":"da35209ae338cf5c7d5303042f9d4eb8dffa0d8dc92d7817e9820a2b6d3b1380","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cac8197ac869d64a6efc26cab883a269392ae6db51f7453bca722f8f31d67c7c","src/lib.rs":"ddecafb5db609d0d8eebd19e4d98dc865e7e9282a4183421f9bd765c01a231c0"},"package":"08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "6fc9a706a9312ee801c7e77ca06c0782fa9eadef" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rustc-hash/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustc-hash/Cargo.toml.orig 2020-02-08 13:19:06.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "rustc-hash" +version = "1.1.0" +authors = ["The Rust Project Developers"] +description = "speed, non-cryptographic hash used in rustc" +license = "Apache-2.0/MIT" +readme = "README.md" +keywords = ["hash", "fxhash", "rustc"] +repository = "https://github.com/rust-lang-nursery/rustc-hash" + +[features] +std = [] +default = ["std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustdct/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustdct/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"21d58914e730a7d27ae1c513c1830c5f7eb7e7b3841740ac33a4d96d3f4f874d","Cargo.toml":"2a63f29a139ed4489c13613aaad9c36fea3ddff0314b33a2c5ab589680ec27ca","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"1bd9a4d41ef00c518cdfe4747a7b8da1d5204ac1519bac4db79ca816b2517a96","RELEASES.md":"e813cc1e56c3686d2c9348ae73a9e1a33ae9ff2f0ac2c165dc49ce0f3bd77ac0","benches/bench_dct_naive.rs":"44440d4ddcf7b3824839fe17a4317491027c55a488d8adcc72afa30973f1b51e","benches/bench_dct_planned.rs":"20893eaf375a47d036d72cef61a32fa7098c38c9dc1f7b54094805b036cd7619","benches/bench_dct_via_fft.rs":"55f77b61534863977a9fab643910886f9be001b25501a3dbd4821f2db7e6f4fa","examples/asmtest.rs":"d99a72b5247976384e63342540232c11e885a8ea817efc9bcafa6bcff4f32669","src/algorithm/mod.rs":"d2b00eec735184f4c87de552b6e7197b35abc9e433208b06bb6b28eb6e0588a3","src/algorithm/type1_convert_to_fft.rs":"d1bea808583e6ee0f7fb4e8ea3f7d4b102483466aacf51df69c267cb06ffff36","src/algorithm/type1_naive.rs":"65ad6ce687b7c1ea736c0dedf4264cefcccf42db1a144d9a9f8221127706a58c","src/algorithm/type2and3_butterflies.rs":"94319e93202520ec9cb52d495fe840c85d9a310bf72f8161e6a714d5668f824f","src/algorithm/type2and3_convert_to_fft.rs":"4ab2ed227c7ed32f3b6c79e807cfcefebe83352950b5963651ea56ca79a9dc9b","src/algorithm/type2and3_naive.rs":"32f8f3712b28af1c96003f43e09daa8571bdff4735d6758656fdba76bd9af4ce","src/algorithm/type2and3_splitradix.rs":"15e727cb7397e829884044932731b9db786cd3f66d242da4379e9025930e341d","src/algorithm/type4_convert_to_fft.rs":"14fec6e94af324452af697359504e357cc3a36cd9fc0ebde597923207f072fe0","src/algorithm/type4_convert_to_type3.rs":"bb52c2165d7d00d280fb67ae2298409ce482b6c9c80e72ea5b9e20a28c1030a1","src/algorithm/type4_naive.rs":"ab627d2ed08df22e6b273604f95e50fd23635dde3be4951257cd1f6815555a41","src/algorithm/type5_naive.rs":"94ba2f6a85b473cd027b8add689c357d400ced5400b9143e651ab80eefa64575","src/algorithm/type6and7_convert_to_fft.rs":"e5187d42ba1de755b8c77ef2be53442806d5116f30f2587839916fb2201e5595","src/algorithm/type6and7_naive.rs":"8ea6208d15d0c951336363d7f81e681a19f017c0e672dba899172e981b4a9486","src/algorithm/type8_naive.rs":"b681a0a2dd7a0c64d7ce77196dc24ec85e32e7539b0aa7bc7db4afa078150484","src/array_utils.rs":"a02671a1221ac3622a35d90c3574bd551ea7505e279896c74a883b33c2675dcd","src/common.rs":"18bdd77f5b7b3cb0ab5f84b965f79e6d5451afd99d8940e7200a6524d518c93b","src/lib.rs":"1437407e15889151676e19c1f11666e495a7245f383a4eaabb1dee08ee4bb429","src/mdct/mdct_naive.rs":"d2a2d33189a5f80ef6aca9671fad667e15bd87eff12b8842d6415b5871c86bf0","src/mdct/mdct_via_dct4.rs":"9ac420a3f4463432ccdcdcba6cd7e46e78ede7e8c864a27167a342a6375af7ed","src/mdct/mod.rs":"1d5bc72e0727ac88cd5bec1f3041d0f925e459e829f164b72e1071252043aea9","src/mdct/window_fn.rs":"9f0d5ed8ee5de3bcb4f7b8d3002fda2351f79a40e222cd57cda0a4d3b9044463","src/plan.rs":"234497f159fa348bb99166c55a1ff2844692db2e3efefd4fbac59c48d62e89c0","src/test_utils.rs":"531c2bbb01fcefd38b5ea8dda1d90da571904bb8eaa3abe3e1318bb89ddcb9bb","src/twiddles.rs":"fec377c84c11e30505f04057f815e11c820a23137fd9a1e380dd3dcfa3bbba9f","tests/common/known_data.rs":"c6e2eddc8cba82790f46a69e2f3784ee4c497cc23f864ddaad83b31ba97b1e9d","tests/common/macros.rs":"35d69f0632fe9f0997b5e45318f4aae0cef6eefe97b53d40e199bf46c0a35517","tests/common/mod.rs":"5dde96d1a424fed7389541217c50ae23c5767aa998c4cf80049c7f24008cc7d7","tests/common/reference_impls.rs":"221a44cdc1c98031a8c0bf17b89d52d068cb2a184752c6ecc94b796cdc12e2f9","tests/test_dct.rs":"cc10684907811aa3973300666aa109b38da7f301f1073500437ed7d245c653c9"},"package":"8b61555105d6a9bf98797c063c362a1d24ed8ab0431655e38f1cf51e52089551"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"e2157d804359ae9a73124362607d0b52dfb6cec6cb39041f0247352ef3fdd77b","Cargo.lock":"21d58914e730a7d27ae1c513c1830c5f7eb7e7b3841740ac33a4d96d3f4f874d","Cargo.toml":"2a63f29a139ed4489c13613aaad9c36fea3ddff0314b33a2c5ab589680ec27ca","Cargo.toml.orig":"0caf5071db589370ff5e3efce1dd660a93fcd58380f924f8ef183193fc08f2ee","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"1bd9a4d41ef00c518cdfe4747a7b8da1d5204ac1519bac4db79ca816b2517a96","RELEASES.md":"e813cc1e56c3686d2c9348ae73a9e1a33ae9ff2f0ac2c165dc49ce0f3bd77ac0","benches/bench_dct_naive.rs":"44440d4ddcf7b3824839fe17a4317491027c55a488d8adcc72afa30973f1b51e","benches/bench_dct_planned.rs":"20893eaf375a47d036d72cef61a32fa7098c38c9dc1f7b54094805b036cd7619","benches/bench_dct_via_fft.rs":"55f77b61534863977a9fab643910886f9be001b25501a3dbd4821f2db7e6f4fa","examples/asmtest.rs":"d99a72b5247976384e63342540232c11e885a8ea817efc9bcafa6bcff4f32669","src/algorithm/mod.rs":"d2b00eec735184f4c87de552b6e7197b35abc9e433208b06bb6b28eb6e0588a3","src/algorithm/type1_convert_to_fft.rs":"d1bea808583e6ee0f7fb4e8ea3f7d4b102483466aacf51df69c267cb06ffff36","src/algorithm/type1_naive.rs":"65ad6ce687b7c1ea736c0dedf4264cefcccf42db1a144d9a9f8221127706a58c","src/algorithm/type2and3_butterflies.rs":"94319e93202520ec9cb52d495fe840c85d9a310bf72f8161e6a714d5668f824f","src/algorithm/type2and3_convert_to_fft.rs":"4ab2ed227c7ed32f3b6c79e807cfcefebe83352950b5963651ea56ca79a9dc9b","src/algorithm/type2and3_naive.rs":"32f8f3712b28af1c96003f43e09daa8571bdff4735d6758656fdba76bd9af4ce","src/algorithm/type2and3_splitradix.rs":"15e727cb7397e829884044932731b9db786cd3f66d242da4379e9025930e341d","src/algorithm/type4_convert_to_fft.rs":"14fec6e94af324452af697359504e357cc3a36cd9fc0ebde597923207f072fe0","src/algorithm/type4_convert_to_type3.rs":"bb52c2165d7d00d280fb67ae2298409ce482b6c9c80e72ea5b9e20a28c1030a1","src/algorithm/type4_naive.rs":"ab627d2ed08df22e6b273604f95e50fd23635dde3be4951257cd1f6815555a41","src/algorithm/type5_naive.rs":"94ba2f6a85b473cd027b8add689c357d400ced5400b9143e651ab80eefa64575","src/algorithm/type6and7_convert_to_fft.rs":"e5187d42ba1de755b8c77ef2be53442806d5116f30f2587839916fb2201e5595","src/algorithm/type6and7_naive.rs":"8ea6208d15d0c951336363d7f81e681a19f017c0e672dba899172e981b4a9486","src/algorithm/type8_naive.rs":"b681a0a2dd7a0c64d7ce77196dc24ec85e32e7539b0aa7bc7db4afa078150484","src/array_utils.rs":"a02671a1221ac3622a35d90c3574bd551ea7505e279896c74a883b33c2675dcd","src/common.rs":"18bdd77f5b7b3cb0ab5f84b965f79e6d5451afd99d8940e7200a6524d518c93b","src/lib.rs":"1437407e15889151676e19c1f11666e495a7245f383a4eaabb1dee08ee4bb429","src/mdct/mdct_naive.rs":"d2a2d33189a5f80ef6aca9671fad667e15bd87eff12b8842d6415b5871c86bf0","src/mdct/mdct_via_dct4.rs":"9ac420a3f4463432ccdcdcba6cd7e46e78ede7e8c864a27167a342a6375af7ed","src/mdct/mod.rs":"1d5bc72e0727ac88cd5bec1f3041d0f925e459e829f164b72e1071252043aea9","src/mdct/window_fn.rs":"9f0d5ed8ee5de3bcb4f7b8d3002fda2351f79a40e222cd57cda0a4d3b9044463","src/plan.rs":"234497f159fa348bb99166c55a1ff2844692db2e3efefd4fbac59c48d62e89c0","src/test_utils.rs":"531c2bbb01fcefd38b5ea8dda1d90da571904bb8eaa3abe3e1318bb89ddcb9bb","src/twiddles.rs":"fec377c84c11e30505f04057f815e11c820a23137fd9a1e380dd3dcfa3bbba9f","tests/common/known_data.rs":"c6e2eddc8cba82790f46a69e2f3784ee4c497cc23f864ddaad83b31ba97b1e9d","tests/common/macros.rs":"35d69f0632fe9f0997b5e45318f4aae0cef6eefe97b53d40e199bf46c0a35517","tests/common/mod.rs":"5dde96d1a424fed7389541217c50ae23c5767aa998c4cf80049c7f24008cc7d7","tests/common/reference_impls.rs":"221a44cdc1c98031a8c0bf17b89d52d068cb2a184752c6ecc94b796cdc12e2f9","tests/test_dct.rs":"cc10684907811aa3973300666aa109b38da7f301f1073500437ed7d245c653c9"},"package":"8b61555105d6a9bf98797c063c362a1d24ed8ab0431655e38f1cf51e52089551"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustdct/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustdct/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustdct/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f13431b2adefe172f38f9dbbde51f2e86a0b6f2c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustdct/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rustdct/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rustdct/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustdct/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,21 @@ +[package] +name = "rustdct" +version = "0.7.1" +authors = ["Elliott Mahler "] +edition = "2018" + +description = "Compute Discrete Cosine Transforms (DCT) of any size in O(nlogn) time, in pure Rust." + +repository = "https://github.com/ejmahler/rust_dct" +documentation = "https://docs.rs/rustdct/" +readme = "README.md" + +keywords = ["dct", "mdct", "discrete", "cosine", "transform"] +categories = ["algorithms", "compression", "multimedia::encoding", "science"] +license = "MIT OR Apache-2.0" + +[dependencies] +rustfft = "6" + +[dev-dependencies] +rand = "0.8" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"73d2c2929433fb6171ad073931aec0ad4821705597c9641be52ec790cbddf580","Cargo.lock":"53fa9e70076373ab38777d636518d62c4bf324b33e0d469ea3d52b1dcd49fefe","Cargo.toml":"261a3b80061b1ed6ff80a089808f25db0dfac15f802c7af101c9b8f503cd4972","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"d4c507e5466eb425268d9a92e3081b0147c56c1a5cadb54190de9360906818c6","UpgradeGuide4to5.md":"0d5acdc5659f5850ed1d6905607d5390a808d90accfb629ece823387542423a7","benches/bench_check_neon_2to1024.rs":"362afd50417c3a3f29b02501136276d0ec45cb4ea748996b0714b0e9d07ff229","benches/bench_check_scalar_2to1024.rs":"5604b92a7c30b0c02c31ec8b1d45c1956d588f7e18e5a8d8dbc785301826d05f","benches/bench_check_sse_2to1024.rs":"aa783a7d83e8e7d07c6621ed8e417bc069f4a9f8bcd2130cc9f28b8afb645d63","benches/bench_compare_scalar_neon.rs":"00cc35f8d32c192f9c1e9f91c8104bfb07b0395e4b8edc1dd3748777bfb54f07","benches/bench_compare_scalar_sse_avx.rs":"f2a740d23bba4daeecd1d66a36e803127d9a072a6be7153b161b563559e1ca54","benches/bench_compare_scalar_wasm_simd.rs":"b5fa948bdc1b26f4db3bd2db50960b6412bc3c08337b83e04ba5ff736fac2c89","benches/bench_rustfft.rs":"3fc34cd8f46186cff4d8a00ebc57b2d97ff4074541da1a1e2b566edbf4d647df","benches/bench_rustfft_neon.rs":"f71ba691ff5d340687d9a06a49d100b1d38d30eda437365e794c8cd20528a59e","benches/bench_rustfft_scalar.rs":"291e72608cd9fd32f9a28eeafb7cc7ed4ee20cc28bdcfd96c2914f05af79e2b9","benches/bench_rustfft_sse.rs":"5f7b4c2b9d7010b1aaed3e71099512c06c7710ce7b20d28524b27a76a9d2becd","benches/bench_rustfft_wasm_simd.rs":"8dad46fadf18345bff9463a25f76e74be6890222766a8062effe00e11d8ac2b3","benches/compare_3n2m_strategies.rs":"8d109cf117e1a93997a171fc7377a4399adb3ab649c3e53c3846c3a2f95e347f","build.rs":"5305144a1faa5c5a23ec13c67d988b11269fe593c74b577113d6cb7f9630441c","examples/asmtest.rs":"14d45021d2688d1b3829c0deadc0dd6f561a3fe0621078af0e435ee9a6747440","examples/concurrency.rs":"7262f97bcf6076bc79d408d3b536882b88fceaed2dd0ba213dc6145121ff2f96","rustfmt.toml":"863fc34bc1c826a34085e4e6442fb194d758dc4b2d18d2254bbdc32c52dbbc69","src/algorithm/bluesteins_algorithm.rs":"f1526e8321efa181b0a2f4803b4fc0c2326798d626336cc6fdb384898dbf595f","src/algorithm/butterflies.rs":"ceaa3103b568be769b9f6c63b515c35f87e899025b245632bdbb3246a8b4c5ea","src/algorithm/dft.rs":"1d57669ec7bbc0574cdb697745deb41b10b3bd07201377062fcc1a73354f2d1e","src/algorithm/good_thomas_algorithm.rs":"a5551a256ef2d737d737146021e4a8d68f0abf74d86c37d923438b42c5ae46ba","src/algorithm/mixed_radix.rs":"ea2d845127710457ba82de65d2db1a0e66395d9f04db64b9fa5c97e39b5760dc","src/algorithm/mod.rs":"819414b469bf6e809b6a4b13f6a93933b901e322389b934a1980dfbf263794e9","src/algorithm/raders_algorithm.rs":"303985e85a33b9142fb004f93ee2785b20d2105aa8c718e72f04f3071ba30d50","src/algorithm/radix3.rs":"c9042f5a681b9e676e88ff06fc79c08a0b66e5435517a084617b2c898a62ff3c","src/algorithm/radix4.rs":"668f82c28b1b27d5d0967c1c491fd0cc009bb127ff110c139868ef6730032d89","src/array_utils.rs":"fec84a88c817c2204c76df7650e6ed5b273aec381531e2b110ba8c1646e0e572","src/avx/avx32_butterflies.rs":"42eb4221a48524bd6574c91cf33c8471153e57888c8d15928f578aee97dae781","src/avx/avx32_utils.rs":"c0dfcb66b58759a4174072a96f6fbcb9abb71e3400071ecb2cf7cfd175856dc6","src/avx/avx64_butterflies.rs":"efc1e1351719de555922777d694bff8b0fe1f42556a94ee099b58d018ceb1ca4","src/avx/avx64_utils.rs":"030889bff02fae40461a8754221653fad1f5462b9f25db6cec148bcde9fbbe6d","src/avx/avx_bluesteins.rs":"5f2a6f80190520a561f8e5617c0ce2d8a5d9c80aa43ed1f15721f53780094968","src/avx/avx_mixed_radix.rs":"59e3a04b1746ba0ce03fe654032ffa0ef47fd2dfad09cc9b71732bf443bb9ec7","src/avx/avx_planner.rs":"b58b424352e9b6d3658dea6762dc2f1babb464e6622c94b3cbd78a8aae5c181d","src/avx/avx_raders.rs":"5d07d660d7824899e44f68b07179bbbe94accd157b4210ed6cde720e83ab4d0e","src/avx/avx_vector.rs":"a4074a17d0a276df185a5364bb09aedb6fbfaeb79c22f6333475c7995a9b7196","src/avx/mod.rs":"e81311482a8496610c363f5edd5fb45e913bb2c7fe6d0ba5a7b2d22fd4e1957b","src/common.rs":"724421acdb95599e6ff4673945826bb980e13a1b388b2601b958b1b2c949aba3","src/fft_cache.rs":"ab1624bfa0ed41c0dfe9a90288b030ad8975498deb68938f4d31287cbbdee260","src/lib.rs":"c9e17d49cc8e35e463124303b4b047726d121d2e97e881e5535dda9a0e9ddf0e","src/math_utils.rs":"d75a3c777f4ad1dd31a1ad0319113873db0412f04ea5b2ee43a923c04d8df1e5","src/neon/mod.rs":"7792d5dc61447c817e5467ab97cfedadafb3da81e8dca735d662523dd8953c3f","src/neon/neon_butterflies.rs":"4a90eeb7c1adb0664e1c07f7f021fff63c6927643c263a83eb5d97e339121457","src/neon/neon_common.rs":"1a3e3b14353c67fe5f1a5278fbb3644aed4b18761a91b7a1a16b062a73c122e3","src/neon/neon_planner.rs":"d392521a142e310dc52b8ab6e27b21d159382c8cdb4b54ca071a3d9f9d0b0f0e","src/neon/neon_prime_butterflies.rs":"63f96050f09da2b188601d788436bd97cb6e5e918e47d3a6b5acee06838428df","src/neon/neon_radix4.rs":"5b6b4adf24af5069fa6e88a48f6a935bec058d4982585fba2437948860b4e6fd","src/neon/neon_utils.rs":"aad4cdfb71a63bd92b6b2bda28480f374bfd0b4f74e19a2a87435bfcacf2a899","src/neon/neon_vector.rs":"9dd5968879825047b5dd5b5816b52982f46607611a3ab3b9128f31cff5eb0d33","src/plan.rs":"7043f9e6f579c335d8add6a056f46cde1d6e78ed970e219884cc1cd3e7d9bd00","src/sse/mod.rs":"d9bdb78fdae7a24c7a93eef6ba2e19230fcc04d50e60f6f5d0742073ec1ee70d","src/sse/sse_butterflies.rs":"a8c18dec50e4bd190da14a79386f5758e44bfd1db712bb49e63d2f9b7d648a16","src/sse/sse_common.rs":"fec48e0cd0e9640da5176af59d56806ab69127fd6242da3b069161493a5bec12","src/sse/sse_planner.rs":"5439fceabfd7981cdfea19752f4bf9f067450c9562382de6bd904400c9cf3d99","src/sse/sse_prime_butterflies.rs":"695c81245049b05109187731840bec3a77de13d4e092538f1351cc0aecf96edd","src/sse/sse_radix4.rs":"245a6e52fb9931760eee92c9ba71067a2f054a2fa719bfefc79281af9930c065","src/sse/sse_utils.rs":"f3c88f88421a4de2f1df79b52ed7b3e1c2ff087924252213d5265a5bc0f02395","src/sse/sse_vector.rs":"a00caf4515f100c08299adf5c2603f7344db8d21fee4836a338c9957b2d04650","src/test_utils.rs":"0ae79dbb458884556f768d84ccc161398f19c3aa6f5f03e4a6584b9049725154","src/twiddles.rs":"0f3ec868e8a6b65eff80b761ab91acc92dbb7a8cbc99bafc5c5857b87ff33c03","src/wasm_simd/mod.rs":"f57f4c091f44ab97e38c307f5dc2d8cf26353375cceddb714d1308fb4698e403","src/wasm_simd/wasm_simd_butterflies.rs":"89e7988ddef25bdde512cf7a77404665655eb85bce3cd5375f489d30b1326644","src/wasm_simd/wasm_simd_common.rs":"2559587a4a13c7ef8175270a9864ab862727bc1b0e357e336984b0a35ba23a1b","src/wasm_simd/wasm_simd_planner.rs":"97aa0ee72780511fa300f4081b96268fc94e2d0fa773ae080c893086da9ec3e4","src/wasm_simd/wasm_simd_prime_butterflies.rs":"3a2cd790f7bc447a3751fee59736b79b29007bdd363fc9eaf830f4b9e3816ed3","src/wasm_simd/wasm_simd_radix4.rs":"3defd008e85ef6a1cc75639e58f63ad01d94ac3a0158740f695bffce556689b1","src/wasm_simd/wasm_simd_utils.rs":"8d901e8f9f27f57dfa7e48178b9073e7f62c9dba322ee15ce1f8706db5f13769","src/wasm_simd/wasm_simd_vector.rs":"19d04addf706ee919b7b4a0586e09a26850a9f59806f4741c5a7f8766196c6e3","tests/accuracy.rs":"f545ccfc9533ad17cdb74dcaf35148a5fde2562b376058b8cc91c869c86d7065","tools/gen_sse_butterflies.py":"8373f692f7ff33cfd7645e2a4b8d62b0d09caa2aa76dda03a5a8ccba2a322647","tools/genbutterflies.py":"ab3634b70851d95ce5fa9a78d4c506b39411446013320fda1a8f8fd26587e4dc","tools/p2comparison.py":"6e4d164cb78a021857663a2326ee18ba9176d818c217d8d9bc469635d23c5501","tools/p2comparison_neon.py":"4755b84536f6ad65b0416121af2792c5e128810625c1a0ab41cea326176ad00d","tools/p2comparison_wasm_simd.py":"fb755f0b78e41aac5c5320880b75c9b5eca89417d18e566ed4c4384c06adb796"},"package":"43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"290ade6d84e7f41bc697718643eae0b5643dd8e916b94bcd86fcf5979ff8b5ad",".github/workflows/run_test.yml":"0914cedf97a77294e9bd6b044f09ed111f8fca13495c8f8fcb0219f48d7a454f","CHANGELOG.md":"73d2c2929433fb6171ad073931aec0ad4821705597c9641be52ec790cbddf580","Cargo.lock":"53fa9e70076373ab38777d636518d62c4bf324b33e0d469ea3d52b1dcd49fefe","Cargo.toml":"261a3b80061b1ed6ff80a089808f25db0dfac15f802c7af101c9b8f503cd4972","Cargo.toml.orig":"e417722a786c8d7dcc06cf95be0c2b74f5dd8dadd04c66cbb8b58134e60d5934","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"d4c507e5466eb425268d9a92e3081b0147c56c1a5cadb54190de9360906818c6","UpgradeGuide4to5.md":"0d5acdc5659f5850ed1d6905607d5390a808d90accfb629ece823387542423a7","benches/bench_check_neon_2to1024.rs":"362afd50417c3a3f29b02501136276d0ec45cb4ea748996b0714b0e9d07ff229","benches/bench_check_scalar_2to1024.rs":"5604b92a7c30b0c02c31ec8b1d45c1956d588f7e18e5a8d8dbc785301826d05f","benches/bench_check_sse_2to1024.rs":"aa783a7d83e8e7d07c6621ed8e417bc069f4a9f8bcd2130cc9f28b8afb645d63","benches/bench_compare_scalar_neon.rs":"00cc35f8d32c192f9c1e9f91c8104bfb07b0395e4b8edc1dd3748777bfb54f07","benches/bench_compare_scalar_sse_avx.rs":"f2a740d23bba4daeecd1d66a36e803127d9a072a6be7153b161b563559e1ca54","benches/bench_compare_scalar_wasm_simd.rs":"b5fa948bdc1b26f4db3bd2db50960b6412bc3c08337b83e04ba5ff736fac2c89","benches/bench_rustfft.rs":"3fc34cd8f46186cff4d8a00ebc57b2d97ff4074541da1a1e2b566edbf4d647df","benches/bench_rustfft_neon.rs":"f71ba691ff5d340687d9a06a49d100b1d38d30eda437365e794c8cd20528a59e","benches/bench_rustfft_scalar.rs":"291e72608cd9fd32f9a28eeafb7cc7ed4ee20cc28bdcfd96c2914f05af79e2b9","benches/bench_rustfft_sse.rs":"5f7b4c2b9d7010b1aaed3e71099512c06c7710ce7b20d28524b27a76a9d2becd","benches/bench_rustfft_wasm_simd.rs":"8dad46fadf18345bff9463a25f76e74be6890222766a8062effe00e11d8ac2b3","benches/compare_3n2m_strategies.rs":"8d109cf117e1a93997a171fc7377a4399adb3ab649c3e53c3846c3a2f95e347f","build.rs":"5305144a1faa5c5a23ec13c67d988b11269fe593c74b577113d6cb7f9630441c","examples/asmtest.rs":"14d45021d2688d1b3829c0deadc0dd6f561a3fe0621078af0e435ee9a6747440","examples/concurrency.rs":"7262f97bcf6076bc79d408d3b536882b88fceaed2dd0ba213dc6145121ff2f96","rustfmt.toml":"863fc34bc1c826a34085e4e6442fb194d758dc4b2d18d2254bbdc32c52dbbc69","src/algorithm/bluesteins_algorithm.rs":"f1526e8321efa181b0a2f4803b4fc0c2326798d626336cc6fdb384898dbf595f","src/algorithm/butterflies.rs":"ceaa3103b568be769b9f6c63b515c35f87e899025b245632bdbb3246a8b4c5ea","src/algorithm/dft.rs":"1d57669ec7bbc0574cdb697745deb41b10b3bd07201377062fcc1a73354f2d1e","src/algorithm/good_thomas_algorithm.rs":"a5551a256ef2d737d737146021e4a8d68f0abf74d86c37d923438b42c5ae46ba","src/algorithm/mixed_radix.rs":"ea2d845127710457ba82de65d2db1a0e66395d9f04db64b9fa5c97e39b5760dc","src/algorithm/mod.rs":"819414b469bf6e809b6a4b13f6a93933b901e322389b934a1980dfbf263794e9","src/algorithm/raders_algorithm.rs":"303985e85a33b9142fb004f93ee2785b20d2105aa8c718e72f04f3071ba30d50","src/algorithm/radix3.rs":"c9042f5a681b9e676e88ff06fc79c08a0b66e5435517a084617b2c898a62ff3c","src/algorithm/radix4.rs":"668f82c28b1b27d5d0967c1c491fd0cc009bb127ff110c139868ef6730032d89","src/array_utils.rs":"fec84a88c817c2204c76df7650e6ed5b273aec381531e2b110ba8c1646e0e572","src/avx/avx32_butterflies.rs":"42eb4221a48524bd6574c91cf33c8471153e57888c8d15928f578aee97dae781","src/avx/avx32_utils.rs":"c0dfcb66b58759a4174072a96f6fbcb9abb71e3400071ecb2cf7cfd175856dc6","src/avx/avx64_butterflies.rs":"efc1e1351719de555922777d694bff8b0fe1f42556a94ee099b58d018ceb1ca4","src/avx/avx64_utils.rs":"030889bff02fae40461a8754221653fad1f5462b9f25db6cec148bcde9fbbe6d","src/avx/avx_bluesteins.rs":"5f2a6f80190520a561f8e5617c0ce2d8a5d9c80aa43ed1f15721f53780094968","src/avx/avx_mixed_radix.rs":"59e3a04b1746ba0ce03fe654032ffa0ef47fd2dfad09cc9b71732bf443bb9ec7","src/avx/avx_planner.rs":"b58b424352e9b6d3658dea6762dc2f1babb464e6622c94b3cbd78a8aae5c181d","src/avx/avx_raders.rs":"5d07d660d7824899e44f68b07179bbbe94accd157b4210ed6cde720e83ab4d0e","src/avx/avx_vector.rs":"a4074a17d0a276df185a5364bb09aedb6fbfaeb79c22f6333475c7995a9b7196","src/avx/mod.rs":"e81311482a8496610c363f5edd5fb45e913bb2c7fe6d0ba5a7b2d22fd4e1957b","src/common.rs":"724421acdb95599e6ff4673945826bb980e13a1b388b2601b958b1b2c949aba3","src/fft_cache.rs":"ab1624bfa0ed41c0dfe9a90288b030ad8975498deb68938f4d31287cbbdee260","src/lib.rs":"c9e17d49cc8e35e463124303b4b047726d121d2e97e881e5535dda9a0e9ddf0e","src/math_utils.rs":"d75a3c777f4ad1dd31a1ad0319113873db0412f04ea5b2ee43a923c04d8df1e5","src/neon/mod.rs":"7792d5dc61447c817e5467ab97cfedadafb3da81e8dca735d662523dd8953c3f","src/neon/neon_butterflies.rs":"4a90eeb7c1adb0664e1c07f7f021fff63c6927643c263a83eb5d97e339121457","src/neon/neon_common.rs":"1a3e3b14353c67fe5f1a5278fbb3644aed4b18761a91b7a1a16b062a73c122e3","src/neon/neon_planner.rs":"d392521a142e310dc52b8ab6e27b21d159382c8cdb4b54ca071a3d9f9d0b0f0e","src/neon/neon_prime_butterflies.rs":"63f96050f09da2b188601d788436bd97cb6e5e918e47d3a6b5acee06838428df","src/neon/neon_radix4.rs":"5b6b4adf24af5069fa6e88a48f6a935bec058d4982585fba2437948860b4e6fd","src/neon/neon_utils.rs":"aad4cdfb71a63bd92b6b2bda28480f374bfd0b4f74e19a2a87435bfcacf2a899","src/neon/neon_vector.rs":"9dd5968879825047b5dd5b5816b52982f46607611a3ab3b9128f31cff5eb0d33","src/plan.rs":"7043f9e6f579c335d8add6a056f46cde1d6e78ed970e219884cc1cd3e7d9bd00","src/sse/mod.rs":"d9bdb78fdae7a24c7a93eef6ba2e19230fcc04d50e60f6f5d0742073ec1ee70d","src/sse/sse_butterflies.rs":"a8c18dec50e4bd190da14a79386f5758e44bfd1db712bb49e63d2f9b7d648a16","src/sse/sse_common.rs":"fec48e0cd0e9640da5176af59d56806ab69127fd6242da3b069161493a5bec12","src/sse/sse_planner.rs":"5439fceabfd7981cdfea19752f4bf9f067450c9562382de6bd904400c9cf3d99","src/sse/sse_prime_butterflies.rs":"695c81245049b05109187731840bec3a77de13d4e092538f1351cc0aecf96edd","src/sse/sse_radix4.rs":"245a6e52fb9931760eee92c9ba71067a2f054a2fa719bfefc79281af9930c065","src/sse/sse_utils.rs":"f3c88f88421a4de2f1df79b52ed7b3e1c2ff087924252213d5265a5bc0f02395","src/sse/sse_vector.rs":"a00caf4515f100c08299adf5c2603f7344db8d21fee4836a338c9957b2d04650","src/test_utils.rs":"0ae79dbb458884556f768d84ccc161398f19c3aa6f5f03e4a6584b9049725154","src/twiddles.rs":"0f3ec868e8a6b65eff80b761ab91acc92dbb7a8cbc99bafc5c5857b87ff33c03","src/wasm_simd/mod.rs":"f57f4c091f44ab97e38c307f5dc2d8cf26353375cceddb714d1308fb4698e403","src/wasm_simd/wasm_simd_butterflies.rs":"89e7988ddef25bdde512cf7a77404665655eb85bce3cd5375f489d30b1326644","src/wasm_simd/wasm_simd_common.rs":"2559587a4a13c7ef8175270a9864ab862727bc1b0e357e336984b0a35ba23a1b","src/wasm_simd/wasm_simd_planner.rs":"97aa0ee72780511fa300f4081b96268fc94e2d0fa773ae080c893086da9ec3e4","src/wasm_simd/wasm_simd_prime_butterflies.rs":"3a2cd790f7bc447a3751fee59736b79b29007bdd363fc9eaf830f4b9e3816ed3","src/wasm_simd/wasm_simd_radix4.rs":"3defd008e85ef6a1cc75639e58f63ad01d94ac3a0158740f695bffce556689b1","src/wasm_simd/wasm_simd_utils.rs":"8d901e8f9f27f57dfa7e48178b9073e7f62c9dba322ee15ce1f8706db5f13769","src/wasm_simd/wasm_simd_vector.rs":"19d04addf706ee919b7b4a0586e09a26850a9f59806f4741c5a7f8766196c6e3","tests/accuracy.rs":"f545ccfc9533ad17cdb74dcaf35148a5fde2562b376058b8cc91c869c86d7065","tools/gen_sse_butterflies.py":"8373f692f7ff33cfd7645e2a4b8d62b0d09caa2aa76dda03a5a8ccba2a322647","tools/genbutterflies.py":"ab3634b70851d95ce5fa9a78d4c506b39411446013320fda1a8f8fd26587e4dc","tools/p2comparison.py":"6e4d164cb78a021857663a2326ee18ba9176d818c217d8d9bc469635d23c5501","tools/p2comparison_neon.py":"4755b84536f6ad65b0416121af2792c5e128810625c1a0ab41cea326176ad00d","tools/p2comparison_wasm_simd.py":"fb755f0b78e41aac5c5320880b75c9b5eca89417d18e566ed4c4384c06adb796"},"package":"43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c720147135788798f28e70be7fbfeefed294b54f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.github/workflows/run_test.yml clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.github/workflows/run_test.yml --- clamav-1.4.3+dfsg/.cargo/vendor/rustfft/.github/workflows/run_test.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustfft/.github/workflows/run_test.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,147 @@ +on: [pull_request] + +name: CI + +jobs: + check: + name: Check+Test default features + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + - 1.61 + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Run cargo check + run: cargo check + + - name: Run cargo test + run: cargo test + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install toolchain + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Print rustfmt version + run: cargo fmt -- --version + + - name: Run cargo fmt + run: cargo fmt -- --check + + check_no_features: + name: Check+Test no features + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + - 1.61 + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Run cargo check + run: cargo check --no-default-features + + - name: Run cargo test + run: cargo test --no-default-features + + check_arm64_neon: + name: Check and test Linux arm 64bit with neon + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + - 1.61 + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: aarch64-unknown-linux-gnu + + - name: Install cross + run: cargo install cross --version 0.2.5 --locked + + - name: Run cargo check + run: cross check --features neon --target aarch64-unknown-linux-gnu + + - name: Run cargo test for arm + run: cross test --release --features neon --target aarch64-unknown-linux-gnu + + check_x86: + name: Check and test Linux x86 32bit + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: i586-unknown-linux-gnu + + - name: Install cross + run: cargo install cross --version 0.2.5 --locked + + - name: Run cargo check + run: cross check --target i586-unknown-linux-gnu + + - name: Run cargo test for i586 + run: cross test --target i586-unknown-linux-gnu + + check_wasm32: + name: Check and test WebAssembly with SIMD + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + - 1.61 + steps: + - name: Checkout sources + uses: actions/checkout@v3 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: wasm32-unknown-unknown + - name: Install wasm-pack + uses: jetli/wasm-pack-action@v0.4.0 + with: + version: "latest" + - name: Run test suites with wasm-pack + run: wasm-pack test --node -- --features wasm_simd diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustfft/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rustfft/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rustfft/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustfft/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,50 @@ +[package] + +name = "rustfft" +version = "6.2.0" +authors = ["Allen Welkie ", "Elliott Mahler "] +edition = "2018" + +description = "High-performance FFT library written in pure Rust." +documentation = "https://docs.rs/rustfft/" +repository = "https://github.com/ejmahler/RustFFT" +keywords = ["fft", "dft", "discrete", "fourier", "transform"] +categories = ["algorithms", "compression", "multimedia::encoding", "science"] +license = "MIT OR Apache-2.0" + +[features] +default = ["avx", "sse", "neon"] + +# On x86_64, the "avx" feature enables compilation of AVX-acclerated code. +# Similarly, the "sse" feature enables compilation of SSE-accelerated code. +# Enabling these improves performance if the client CPU supports AVX or SSE, while disabling them reduces compile time and binary size. +# If both are enabled, RustFFT will use AVX if the CPU supports it. If not, it will check for SSE4.1. +# If neither instruction set is available, it will fall back to the scalar code. +# +# On AArch64, the "neon" feature enables compilation of Neon-accelerated code. +# +# On wasm32, the "wasm_simd" feature enables compilation of Wasm SIMD accelerated code. +# +# For all of the above features, on every platform other than the intended platform for the feature, these features do nothing, and RustFFT will behave like they are not set. +avx = [] +sse = [] +neon = [] +wasm_simd = [] + + +[dependencies] +num-complex = "0.4" +num-traits = "0.2" +num-integer = "^0.1.40" +strength_reduce = "0.2.4" +transpose = "0.2" +primal-check = "0.3.3" + +[dev-dependencies] +rand = "0.8" +paste = "1.0.9" +getrandom = {version = "^0.2", features = ["js"]} +wasm-bindgen-test = "^0.3.36" + +[build-dependencies] +version_check = "0.9" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustix/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustix/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CODE_OF_CONDUCT.md":"f210602311e3f74b32f46237fd55f4ce36d798e85e3db1432ec667f63a7ffc44","CONTRIBUTING.md":"3fd57de5c678db1c972da676a8231d2fde9820695ef1f0d53f1e55a3e81d9de0","COPYRIGHT":"377c2e7c53250cc5905c0b0532d35973392af16ffb9596a41d99d202cf3617c9","Cargo.lock":"ee9687adf0d568104c2d8e28fccc7042990eb62f3da28d4d94d1a9187149821c","Cargo.toml":"42d204101e647da4dde1220b6653dfa647b07a58143b5db4f893a32c871f696c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-Apache-2.0_WITH_LLVM-exception":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","ORG_CODE_OF_CONDUCT.md":"a62b69bf86e605ee1bcbb2f0a12ba79e4cebb6983a7b6491949750aecc4f2178","README.md":"cec45686b62cb75ef2f0c851939b7ddcb64678c27c18c7bca18d6f5cde2446d3","SECURITY.md":"4d75afb09dd28eb5982e3a1f768ee398d90204669ceef3240a16b31dcf04148a","benches/mod.rs":"e260e67273aa0a37cffdc5cd451699335b8ee656c17275a0d0f2b4563c6018ca","build.rs":"ca1a2e173b669f8e13b4e830f3b20530996fe2d60f22f2609ced1a7032affd0f","src/backend/libc/c.rs":"9c040c6f914607580d84fddc62fd6fd03cf14976085000116a603404dbc433d0","src/backend/libc/conv.rs":"a254fa84164286ee6be64f49b5bd5f7e2fd503ebd5ca9076dad4c2507a351dc2","src/backend/libc/event/epoll.rs":"93d3eb9e0e397afc3c44797b315ce92ff8b22f2372812b19cec9e063c55032c3","src/backend/libc/event/mod.rs":"ad30f99f7da0768c18fffac6ec71e658bfed2e44f0634f48c2e0ffe4677ec231","src/backend/libc/event/poll_fd.rs":"286268c0e94bc1716a61835ef3c6324e8f3feb96ae2491ad5ed919300e80070e","src/backend/libc/event/syscalls.rs":"f91bbe7d222987c89a2647817f6819dd536cbc4a685dfb794f403543c32df777","src/backend/libc/event/types.rs":"b966e0a3a018ca2ce507371be900fc73b2814cca450b784583207ad2df473f13","src/backend/libc/event/windows_syscalls.rs":"ebfac665c6676c4b803134ab8806be8aa2e96bdbc7799a19c544cd9069b35787","src/backend/libc/fs/dir.rs":"3c43768f9e56cb4297594c05d91a52be20029dd2b3e0b91f6b1a13f31e595fe2","src/backend/libc/fs/inotify.rs":"a027a718db8bf6ff9a778c2cfa706850b466240b0a2296d72b9834c0096968e8","src/backend/libc/fs/makedev.rs":"89c679a0ef18dd41b3c6223bce0f329ad35bf6cadbf16e47b33fad3f312ba4a6","src/backend/libc/fs/mod.rs":"3d28b803011b57da6315bb747daf0117218687c0cc610358f5dafddf0b7d44d3","src/backend/libc/fs/syscalls.rs":"89cdd809e0cd89fb4f85e2ba0716ecf857ccb66db69a7fc40a5e0a25b15b39d3","src/backend/libc/fs/types.rs":"cae37a0a3099b8e400a48927c60c15efe0d05d2e71f78577742f8f7cede62dfd","src/backend/libc/io/errno.rs":"bac592ece7b44692237a350ff4905bfad30fa042d1e8126e5229e02913fb1c9d","src/backend/libc/io/mod.rs":"746647bd864e4ec7717925b6d176cebdb392b7d015070244cc48d92780351dd6","src/backend/libc/io/syscalls.rs":"c93a7867fc13eecc953c6335fd79c37d4d1734d3a06e13e5d7e08bd985c66326","src/backend/libc/io/types.rs":"2efd39bb3df19a9db5496217284f3d2235ddb354fac81dd71861109a56bede0b","src/backend/libc/io/windows_syscalls.rs":"fab3fa099aa89cea56a6edc651dd37750e581534f4f45b04a7e425f130b08468","src/backend/libc/io_uring/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/io_uring/syscalls.rs":"5af8146d5971c833e6fd657f652c618b31f854e1b0811864fba9b658cb633e19","src/backend/libc/mm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/mm/syscalls.rs":"c04c61ad3d7f3b24d13f89144d7fa0a05658cea4763207f9250db4f9362de2fe","src/backend/libc/mm/types.rs":"55478e173b7d82e2c85934fc0dda79c29f46a305228df78f1e90c68ac9d3cfec","src/backend/libc/mod.rs":"087d2676df88510b089255053a4865e62c64172723588386fe8244d2f1a681c4","src/backend/libc/mount/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/mount/syscalls.rs":"d2d35f7ae989bb52722e28cdbd775243c5d7da9eb411e0b2b9632f2aa7c1533e","src/backend/libc/mount/types.rs":"bf1d541daa248aa023bf18aec7645f2f8c402ac4aa1df2f55b8a784057c2e113","src/backend/libc/net/addr.rs":"9bdc2febb20785bc26a820eaba52cb546c67c79cb547f08105087cd0f79d5861","src/backend/libc/net/ext.rs":"0dd64877abe1ba86b47a2ab34340e3f6cc7b53b22d0bb5e237daf6a82edd46b0","src/backend/libc/net/mod.rs":"562d23225d6dba8f095e3ca41af60dcf6cc40c2cf17bf028f90888f809e86f07","src/backend/libc/net/msghdr.rs":"6f8aba792b4adef5c5d3d4324a813a67a063a50d10437bb19bf7496666bd6de6","src/backend/libc/net/netdevice.rs":"c6c3cd11b0181a74243705438fbf0fedeb02d4201ff3ad9f45a084fbd57a9c21","src/backend/libc/net/read_sockaddr.rs":"61fc1c744b376d57a18d78d8f7ab469236c614f5fa7aeaf37a636e6a967b9066","src/backend/libc/net/send_recv.rs":"1450ca958431a5bf3a85cdeef88b387f30d5c1215de2c56d164ccda38f21b36c","src/backend/libc/net/sockopt.rs":"d53d52f1c55f522c1d0de5e446df3017757b08270c0a0b593a583fd6c56b0876","src/backend/libc/net/syscalls.rs":"1412f9deed57ac0909b0b1c3ac3e5fb7d5c31ab356212c9131e33378c342d2a5","src/backend/libc/net/write_sockaddr.rs":"bee221d0a1fedf4ddcff045faa2702c1f1e68b4d6c3f2f7b079d888e0ef9da56","src/backend/libc/param/auxv.rs":"1877fd1dac415b58a4ae824ef9abd8b49756f613f6915820223f2c586fb4d254","src/backend/libc/param/mod.rs":"5234b8f1bcb886cca6ea003d411d75eaeebe58deedd80e3441354bf46ed85d4d","src/backend/libc/pid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/pid/syscalls.rs":"49ea679b96c0741d048e82964038f9a931bc3cf3a0b59c7db3df89629b9c49e6","src/backend/libc/pipe/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/pipe/syscalls.rs":"8affde100f6a9dfc762b79d1e48be5c1039be414f8ef7d5a6acaba882a68d259","src/backend/libc/pipe/types.rs":"9826013bc5fa18acdcbf09c650b96ce301a18ec009139ebaf79162669b1fc2c8","src/backend/libc/prctl/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/prctl/syscalls.rs":"8a2684f444a7555098dce2b92270d81cefdae902716c6e5d59bd7b0657e8a29d","src/backend/libc/process/cpu_set.rs":"5fca2b47289a2bb6ba908c910a6d27ac78ac10ea21d3c0c018f72f8816c5b9d7","src/backend/libc/process/mod.rs":"806e26da8d1e7afae502987fcd650f4d348da147b8a2e74447affdca153e2e97","src/backend/libc/process/syscalls.rs":"f08a76a5f32e40a69c99261eeabb405a58476ef9e85ae142f2fce19679a42ec4","src/backend/libc/process/types.rs":"fb2caf34b17079aa72c04aed0f9a31d534ea8e8b73a80c758b748bf5e38df52b","src/backend/libc/process/wait.rs":"0cc556aed976b4bbb3965f74fd76b8216c755fce25043b7b21ce54afa07c9773","src/backend/libc/pty/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/pty/syscalls.rs":"566fc9a2cb2e38d7d7ac2405b22c0522369cae4a8f4fe18b55123ba94d3d5a95","src/backend/libc/rand/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/rand/syscalls.rs":"35ea6b6e0f8a7fb064fd5cb33a3a855cd161a6a00f93d76c861b2a2c66db85e7","src/backend/libc/rand/types.rs":"4eb0b4cdd0a9b089d1c9f6a25ad1ca97be28a38b7b07a705ec605b773f63f880","src/backend/libc/shm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/shm/syscalls.rs":"60d797d4e85e08e6330e6b8d80094356ce377e5484952f88ae2a6e49231c268c","src/backend/libc/shm/types.rs":"2206eac8ee74951b995e1e80f10bf235cc6b04e0a099f4adefce546378838233","src/backend/libc/system/mod.rs":"38563ea68829ca5a4b1b0695ac8a5c05718e85bdc88a36dc805efdfce45d3909","src/backend/libc/system/syscalls.rs":"c18c2942811ea93af3125b58d00a1da05c54e5ff438a3dc44cda53bc9d6fcf03","src/backend/libc/system/types.rs":"6871e16aee14fe2ae03cea798c3e509ffe44778a9c0e5608fd73e2e015876d7e","src/backend/libc/termios/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/termios/syscalls.rs":"f377dfbf501fbc3cdbc9e190dd650c8141c00c1593b8c62901ecf346a0c1a7c5","src/backend/libc/thread/futex.rs":"b666828653b12634bbd7fd709acf69641b648ec40962a1d4f904c5db14d2eff5","src/backend/libc/thread/mod.rs":"fa710053974d7f16a6c49242ee6c10a3b9e1143452b9daeaed8837302a679fff","src/backend/libc/thread/syscalls.rs":"435392788b133b83eaf73913a3adee5b244b471df316dec02469832cfdc71160","src/backend/libc/time/mod.rs":"38563ea68829ca5a4b1b0695ac8a5c05718e85bdc88a36dc805efdfce45d3909","src/backend/libc/time/syscalls.rs":"bf847e94cc156bdb553755baa88dac240db4dcaf690f303b0f205777c5a9cdfc","src/backend/libc/time/types.rs":"d0307994ffddd3f21f702d9ae4400750aecccfaf4a01268161dc4fd72de5c373","src/backend/libc/ugid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/ugid/syscalls.rs":"8edf91b8790add23902c9f5418da6b0723a371677f29f490e0c8af852f0f1a0c","src/backend/libc/winsock_c.rs":"502da2ed3cd6ca99bb7ee08b0b30e25c212632885cec965f9816366c6b931ac6","src/backend/linux_raw/arch/aarch64.rs":"2a255c9135bc8a321c180f52b88eb2b158bc9170cd222149caeae63c24587d44","src/backend/linux_raw/arch/arm.rs":"165bccb5883d0136e55d42091183765f83d86e9d37a7cb2cec9ae8af32774db6","src/backend/linux_raw/arch/mips.rs":"24af364aa93fd4b9917639d473336490a143f0d1723b09f388e72d534160ee51","src/backend/linux_raw/arch/mips32r6.rs":"e436a2ade34f2f7c58b8924462b07a2499dfc951e1e1318d51759444fb8b658e","src/backend/linux_raw/arch/mips64.rs":"897da9ddc877963ad59464d7f81dc59df8a7e91251e6adea14cfd946e2740a1c","src/backend/linux_raw/arch/mips64r6.rs":"3c08aea13c1139fb0dfbe74ca3d0147f007c3aa2eda641afb82c46f6aa4f6cd1","src/backend/linux_raw/arch/mod.rs":"37eaeea601d39be00d170856a31a8ec6a27b0d3ac22ab3ee642ab0e45dee237d","src/backend/linux_raw/arch/powerpc64.rs":"dfb001f8636a5e46d728900b0804fe6c374e5e18a6f0e76d7d62e0c07da74477","src/backend/linux_raw/arch/riscv64.rs":"41d33242d941030f46077dc2b1bc4c7913fe7630d693a5a7eef966bcf38f9d8b","src/backend/linux_raw/arch/thumb.rs":"2fd979ab421248c0a4c592bc0cefee63edc26528f469b71b63eaed35356e42e8","src/backend/linux_raw/arch/x86.rs":"fc72f595ec75768aee248d405f4958a7ba1db65ac9fe54b277cd003eab33316e","src/backend/linux_raw/arch/x86_64.rs":"e929036a1f3cf93ba538f4523b241605cc7b5e61f84ffe6d9d5cdbcb6f73e543","src/backend/linux_raw/c.rs":"db66abe9b91ce0f16dd71762744013046f29542a46a577454c9ff063e9cb649c","src/backend/linux_raw/conv.rs":"48a261b8dd6182ce876690cd4946d00c3697bcf7c3d89a46e3a3d6f50d39c2db","src/backend/linux_raw/event/epoll.rs":"a102c2d8d7d5d07a5d846f30672153269d1762d1d846be1786b22fcf095e8721","src/backend/linux_raw/event/mod.rs":"72e46b04637e2d1d2a6b97af616144995399e489d1fe916faf835d72fc8c64cd","src/backend/linux_raw/event/poll_fd.rs":"a5773464e9e30227b4046f029a27d3daf2c7bd0045e54565cf1a8ac2a0d61e81","src/backend/linux_raw/event/syscalls.rs":"44460b0045bb9d9f48b0baeb009a6b150a2902f9b733e8f6c5a36726b8db2d41","src/backend/linux_raw/event/types.rs":"0551b18f982e233a0a06d8a9c3dbb29de0c204dcd64dd6f7e88b6c96fa9a9be8","src/backend/linux_raw/fs/dir.rs":"3107b07276f171a5837bd37a9c1e05151ca21d59ae2b85afd2c6e59e721cdcf2","src/backend/linux_raw/fs/inotify.rs":"713ec3b85f281efca19bc4f495b7537e745fbf1d8c26592c80ceec6fd2ab59b5","src/backend/linux_raw/fs/makedev.rs":"c6b4505c4bcbbc2460e80f3097eb15e2c8ef38d6c6e7abd78e39c53c372139e2","src/backend/linux_raw/fs/mod.rs":"3d3a42bbf4d086f806d7d9f6e4b0a49a873dc27f4f03ffca0921f5536acc24e5","src/backend/linux_raw/fs/syscalls.rs":"5f34547e8d57b69aac600edf27893381d98c6d127a969d7b241bd9220137c649","src/backend/linux_raw/fs/types.rs":"4ee495127d88d3826f0277d2e62bb0e7553fe5e6693a153c48f2b74ba593cf36","src/backend/linux_raw/io/errno.rs":"befa94275b30e8262718e8c9e9662b08526ec55779861dab4e2e499daa3e097d","src/backend/linux_raw/io/mod.rs":"7ae2324427892cca6f5ab53858d847b165f790a72ec25f3d99fb15f0506c9f27","src/backend/linux_raw/io/syscalls.rs":"568e16751191c14bb37f7883b17cb577dc97e09d615d17849c0e7e10e3898f1b","src/backend/linux_raw/io/types.rs":"d0df5a62248e1ba19af0f89f86da7ba2312d97065c2814ddf6b08a4a0db23bad","src/backend/linux_raw/io_uring/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/io_uring/syscalls.rs":"0f7c9cb7ccddf5687e4b9e5b23558871a452a29ac6095a0184a06c47b9b18eb6","src/backend/linux_raw/mm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/mm/syscalls.rs":"4e469542c88ea15853d5022e7e1d4b8fc291265ca314766d60d9395dad927e19","src/backend/linux_raw/mm/types.rs":"b5bf9bf775d3771e79aa234788fa3d1f25009f3f51cd59c72efc4f5e2c7bd790","src/backend/linux_raw/mod.rs":"86f7c3b1d57e57a9e5b5dcc8ee24ded5054a917069bd9824f47952b10bca2221","src/backend/linux_raw/mount/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/mount/syscalls.rs":"8442c82814961f69c488222faabb82c44d2e7227b10faff919cbbd197bb47484","src/backend/linux_raw/mount/types.rs":"bf3dff5aad1cec9d998496230469958c836b76643f0ad17b0ea29b957357bcca","src/backend/linux_raw/net/addr.rs":"161ff30891526e309b1cf9514e9113227c6901c5c1bb346cb8fc3a53e43aa410","src/backend/linux_raw/net/mod.rs":"5640bbaf4963ac4575b0537173422ed6f6a43f34a8f6b656e7257fbbb13e5bcb","src/backend/linux_raw/net/msghdr.rs":"8b18974b81ee78af7a5c64733041dddaaa378a46cab8b984bff5b3b4be499751","src/backend/linux_raw/net/netdevice.rs":"a0354e44ae2f8402576b55470e48446dd655d77a69f27f814a298ab3e3a1afac","src/backend/linux_raw/net/read_sockaddr.rs":"7cb3c8bcc80c5eee8602323cd83f36c1784927d9dd0c40ded29af6fb09c57ece","src/backend/linux_raw/net/send_recv.rs":"6d5d2aec61a3c1b4a5fef1a8a487dc8e163da8988d1237541ed008baa01128cc","src/backend/linux_raw/net/sockopt.rs":"2b42cd181772ea78d1b5b64d03fd2939a5e1a0c49b84c943c9fe8707b6477344","src/backend/linux_raw/net/syscalls.rs":"0138662012ca89e063b3a03cf8fe17b97fbeb38a3d18c42938ae047a4a392105","src/backend/linux_raw/net/write_sockaddr.rs":"0efa4e17b4008da2cf2aada2d18acfccd31a3b49cf8ac5d608e77f3ea6627fec","src/backend/linux_raw/param/auxv.rs":"c9a582a02b4c87e26f6d5026c78e0c3a3ec8a025079cd3023e474d974b29268c","src/backend/linux_raw/param/init.rs":"f2275a2324a99be8d804fb3b7fdf86a43c7d428f660280b7e0e7d19c357f0200","src/backend/linux_raw/param/libc_auxv.rs":"9a7b4ba75a18cc384df1b7edc5525f76c147bb84fb67d3730ba2c5ae64ebdff3","src/backend/linux_raw/param/mod.rs":"2e6a1a1c00351b9c88bd615aa923f71d76208df5626dd9bea03067f28f81dc31","src/backend/linux_raw/pid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/pid/syscalls.rs":"eef6aa01830ddd510b83f507da2002c03e58318b73744be2c06ebbe33c4f194f","src/backend/linux_raw/pipe/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/pipe/syscalls.rs":"366c730fc3e991bddb9f5a15b8c3917a8e6ace6d1d5a9113b2749e476faf6f83","src/backend/linux_raw/pipe/types.rs":"cf53bcdcde5d0ee15e0e3566ceaad39fda44e69ed6f94a99fadd9be9b8be09cf","src/backend/linux_raw/prctl/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/prctl/syscalls.rs":"a18b224307e0d27bda9b7b85c75cd6c7ddfe39f5ce52efb7bb0bf0585b757343","src/backend/linux_raw/process/cpu_set.rs":"b31889f972676f57e3599375dfcd59dd72975977ef345d11c22d51f0d4a6400b","src/backend/linux_raw/process/mod.rs":"fb393c70a9c63ef9a6bf1fb5a2dc94f07d6b0b6987cc5231c15c607015dafd68","src/backend/linux_raw/process/syscalls.rs":"07c14d796a65d3958a9199dae00c8b864fda70e26b67815aff20edd20a985f2f","src/backend/linux_raw/process/types.rs":"6811ba822bc12a1a6336649151b4adb1f5d3365684a31c07f01953ea9547743d","src/backend/linux_raw/process/wait.rs":"921aee4b0048746087f52615a98edc2aa0fb4b53d6df44be4533098df55d1b05","src/backend/linux_raw/pty/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/pty/syscalls.rs":"ae09c4aecc0ae87b1ca58d82efc58007b9dddaae78460d615f48da19d1cd0f89","src/backend/linux_raw/rand/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/rand/syscalls.rs":"317cdaf243623329ee345131054e86a06a0863a9e90c5dba73e1ac3475ba6305","src/backend/linux_raw/rand/types.rs":"a21dbb1ab31eed6b59a57520be5a3c603c36d18ea74e67f7527f40835ba209a3","src/backend/linux_raw/reg.rs":"6bfb53575494f5de76d5112a7e4eb6d0c266b1af0a275aa33b9bc9e6e7a2f41c","src/backend/linux_raw/runtime/mod.rs":"b2cae8cce3822c3c92942f06ea0b68464040dcac33c6f0f7ee392c6269993347","src/backend/linux_raw/runtime/syscalls.rs":"dc7df0416919d1eef7e4919fc38836e2081903db286330d59b0119cc292155df","src/backend/linux_raw/runtime/tls.rs":"6316060560a112c2e9cd9807cdba6e8c91414113a04a739160929ae9a67bba1f","src/backend/linux_raw/shm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/shm/syscalls.rs":"3ebf91610b02de0312e1f0f0cc5d56e12b4d93794540087b3182cbdf3cb9c8db","src/backend/linux_raw/shm/types.rs":"b831b474aba7eb97167c9289f5257776a72b39134b44e67a0ecfcef2394dcd47","src/backend/linux_raw/system/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/system/syscalls.rs":"19a7ab17de906ec237f16a816da036723c1f55f605e8e4a26689343eb4cd76e7","src/backend/linux_raw/system/types.rs":"1ceab8d738a71043473b26e97fa3fd79d588a86d4774cbc9b9e1d4f1447a016e","src/backend/linux_raw/termios/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/termios/syscalls.rs":"25a0341ded4657a3a5389250c24b3310642785d386bc51f31696f98f4f1e770f","src/backend/linux_raw/thread/futex.rs":"0aa0f9f5be6a79de81e82c9f11f1bf8831f682a4b2f6cb29669e1591636f084e","src/backend/linux_raw/thread/mod.rs":"6ad4a4b90b9234e79900b27ebbe8837e3a7a36aec532912e3e253edce5225067","src/backend/linux_raw/thread/syscalls.rs":"9bc9a7360b6b8711b82bc6eff58dbcfc1d936f6e2cdf828084ed56036ade76d7","src/backend/linux_raw/time/mod.rs":"672724f55b7b7be6a7452bb1cc2d28b5f0aaa840a2856fe363acce624e1beefc","src/backend/linux_raw/time/syscalls.rs":"7dc6975bdc30e8fa02f3408b934957e65ebbca281c8c9806e5de9404845312fc","src/backend/linux_raw/time/types.rs":"5f49ee7b201976114c6555f0c5a81d3305e18e726e54edc5a5474641f3cdc278","src/backend/linux_raw/ugid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/ugid/syscalls.rs":"8c86d251db33b399a1d1cbb8e87afe650b78db84f444d3251309b7a0480b54f7","src/backend/linux_raw/vdso.rs":"056314f72c71d4b041739337ca2098afb7fe070f844327f462c293f43481b75b","src/backend/linux_raw/vdso_wrappers.rs":"0e01221cbc6f0a489e89b0cf2fa376c3826ead8491ee8510476b75e90784f39a","src/bitcast.rs":"e21c87c292c781b27256c6f5dcf9fd52dd69ed6e21016cbd67ac31a8219ebf8e","src/buffer.rs":"8211a52e4fdd6ad74dcaddb885db25fa616898f988fc79b43af24b89c32d8421","src/check_types.rs":"e52f710e1cfc12ca13a495f2b43c227b293ff295e1ce3ab332935b28a7579872","src/clockid.rs":"bd443c60868586c1a3114afacc95193de1d8cb99b7c9d710e0b3835596c74a24","src/cstr.rs":"41af2a4429fe6c67a8883f8a8f63d66c90df566abda74fd2b03bcef7b9f24218","src/event/eventfd.rs":"81cbd08f7bdf40a6ce1ca692b63da1dc8ba925282990668d9d68f1203e839fa1","src/event/kqueue.rs":"2f776485e16fe57639ad7454886e0ae761880b122976141ac05b4b2e7d82183a","src/event/mod.rs":"77f6c7051f70d4d5873787cf744e05b64519ba61d8da42298aeed27a906031f2","src/event/pause.rs":"cac3317286478565298a40788c1ce13c1b71543078a6f09655419de325022f6f","src/event/poll.rs":"899bbee8e565110b2581594e7aa5067a426f859f0a414935e2ce3a9732b6152a","src/event/port.rs":"4e51ff150e5d17cbd44aa64a38b99c15e26eaaf2e350768b5dcacdfde4fa5212","src/ffi.rs":"c2b8b38c02d72749aceb715c496726caba1f1fa989ad3856d0103a2fafed89ed","src/fs/abs.rs":"b671489378e14b708c784c4a673e6645741a869c7d1dd1918e28e1eb1a138829","src/fs/at.rs":"13f50b86575443db8b881ce525ce2c5d2f377e528c33258729f0c06037de9499","src/fs/constants.rs":"23923e0fce3221bdac371fe2d05028f30a87dba4f9b4a573b69dc2d6d39320b2","src/fs/copy_file_range.rs":"d3b644374390d482b2ff749a2459458872b57d0dcf9670368739b7833509a7c2","src/fs/cwd.rs":"9f429a79ace6e17455634da09216ee0ad3d067a4541518b3193ae6a8d9ff1e26","src/fs/dir.rs":"347a52f4ca9ac6321c52e802e97ec90d1b4c62ec955c8996fc17f8f5aed69966","src/fs/fadvise.rs":"1220e2cf5cf58fc7cc950d48738050a052c504f745ca67130daa6410e248230a","src/fs/fcntl.rs":"1d1ee1e0bc962779e1cc1b8b76f39c820746240557daa9e14b47b1799120dc39","src/fs/fcntl_apple.rs":"e2f23f038083621bcdecc98d02ce1023508afaecdb2ed0fba5c8b70f955301e5","src/fs/fcopyfile.rs":"ce565f61e1fbf2e31086077c2f1d01b6bb3b048915edda87fe9a4a4f5e8ff7e4","src/fs/fd.rs":"9b3ac2000bc00349cc224b0cf1d77515298d9ed99f75373d2a0cc709ef120d46","src/fs/getpath.rs":"28f6970fc1bbc37bb35c84724b59eac436ea7407a4522e18c2bdacb1fdd2edd9","src/fs/id.rs":"1b5c8a8baf9a9bb1f895f97189cea4e5982a0d35b192afeec6340a6c6222e0cb","src/fs/ioctl.rs":"c7c2db229daf7c9f0109fe7f45f05fa9a6a472950a2ad408c71514e6cb7c9d7b","src/fs/makedev.rs":"85520b484cb7c15ab71ea1c368578ea3b7e484d82f8510db92b6ce9f7ca341ae","src/fs/memfd_create.rs":"a8bf1dced54c7592e71da896021338d5092c1693d12cc42e79bac435fab2792b","src/fs/mod.rs":"b1e92f119ce8acbcc55597f5512727622bcd12d6d0ce9fdb2d9b1cfaa9e42a64","src/fs/mount.rs":"8f6ea2b997dd83c50c90291b9ada3ed77a9ce1ad701c9b0d533b5113b317be5b","src/fs/openat2.rs":"4a95c15dab533a41201b5fa25c8a212956b7571d58cad696bdaf45af8aef96db","src/fs/raw_dir.rs":"18ad797876d6230c38d4cacbed081c4028e03ace477d0520d9b226b40de942f0","src/fs/seek_from.rs":"a9efa0feb9ac789cf47667e91efee2e3f2dcde16cb3b7a928c99da640fa0e0d6","src/fs/sendfile.rs":"e3b2058741cf4b1698f34d84bb37130cf2b72806d522a16fe541e832cde136cb","src/fs/statx.rs":"613480f0f3277790281b4cfe866ce72e4efdadca691969f6ae5e3ba6fc33a84a","src/fs/sync.rs":"a3b23543834281f347b0f873bd38154d31d404871188ac08f2b20b9196234cfd","src/fs/xattr.rs":"5e222adb52caf69d949ab3f944fb2a482dd6ca3a47200532ca6e72d44cbe8334","src/io/close.rs":"2ddae17a2c9dc05fb2cefa134815699c2b3af2eef8026407b8d009cb3ceae6b8","src/io/dup.rs":"335e76f8ad5aa021e654f61e043058e964c2f9914c4785fc09bf6f49f4975290","src/io/errno.rs":"58a4d20ba0924e4d514e3c876fbe08982f1623187642ae14780815e65989c8c8","src/io/fcntl.rs":"41c1b370be55aaa68144dcc8a67b2d53504a5e6d8ee1bffabac2cc64c66a4043","src/io/ioctl.rs":"af4e736b6739cb1ff0477c1b818eeac789258863b79d12e441a08be99d49fb77","src/io/is_read_write.rs":"1bfb9ee5d58e0b29b44af12fe2668c7bccc841358698dcde47f1519ff9bb73b4","src/io/mod.rs":"75f1d0646be1d4c7c08b5887d8119b0103be8c25c43ccd4e0e97015508c0bb8f","src/io/read_write.rs":"f36488a87a35c37c004f5111e76aad3cf6c2c793f41f78f2daba7a84ecae9079","src/io_uring.rs":"b08662af4b1b205ef644ca7517688957cf54cab3fc693f6205165550a330a5cc","src/ioctl/bsd.rs":"32ba3399a0fe3f68bb458baafc2a21af9bff655865c7ea70990b7e98a26d3907","src/ioctl/linux.rs":"96df90bbc926783f387e8fe1656841d4c7a857fd4e9f41f95492f7dcece33074","src/ioctl/mod.rs":"ebb1e0865bed1b98917d4824082caf1445559a0a19f588094db90f46c224f780","src/ioctl/patterns.rs":"bd6e309c8b548dfe04aaffe805972582fb56a0b717c45b45447630bdf9b88433","src/lib.rs":"55f4fe027ab6e638b4613893dffc27a0c20b0bea6f185b76f401f34a480b78f9","src/maybe_polyfill/no_std/io/mod.rs":"77889bb5c5a4f2e50e38379cdaa5d0fef4b0cafc3da056735df01f6deae75747","src/maybe_polyfill/no_std/mod.rs":"ec94a4aab4bc475785e469d10fd6bc95667e1d47d958e9cff3a19049d88c8c80","src/maybe_polyfill/no_std/net/mod.rs":"1e94d21d455bb1da18a4fccb24b3d93ad42698e22dd888b78115d6266c80288a","src/maybe_polyfill/no_std/os/fd/mod.rs":"27ef0afbcb0695cbb15101070f417eb51e0ef85ae66ec967d95e80771d507c47","src/maybe_polyfill/no_std/os/fd/owned.rs":"d82bfeadf28087cc9afd10269f09a8b4125915dc3288b6427c79f5b4c58ab751","src/maybe_polyfill/no_std/os/fd/raw.rs":"f3648c7bd4a6ff94bd823ed9e0d99d398e02f24875cf9b25962736999e7c6943","src/maybe_polyfill/no_std/os/mod.rs":"27dab639a765827644005d5f2fcc7c825310606b889cc8dd83f54c9528350dc0","src/maybe_polyfill/no_std/os/windows/io/mod.rs":"5bbcc05c83fee5026dd744a994e0458469466d5be39081baa62df07753b92fd2","src/maybe_polyfill/no_std/os/windows/io/raw.rs":"4c32609a489dd938a49328b5637cb3bafb96437f2f9f269ab66d7d3cb90247f6","src/maybe_polyfill/no_std/os/windows/io/socket.rs":"c658f42f24eff44a661f2adfd24a11af80fe9897f3e2af4dc5d2c64808308d65","src/maybe_polyfill/no_std/os/windows/mod.rs":"fdb416f8f231a4e778b5f985b9ae712ece5e1a1402963ad1a5f6a8b9843795f4","src/maybe_polyfill/std/mod.rs":"7c16c86cc73e226e65ead598e4018238b22000a345040b706bf1e1b3eba115fc","src/mm/madvise.rs":"69481cd3354dbffe6cd93b234448e59de6d0fe6440bcf8b12f951f37745bc1dc","src/mm/mmap.rs":"3b0abe64a6a606ea41b06acfc1079bcde1542c17475951e5ed900b86c3e5988d","src/mm/mod.rs":"b3a6cb838986d45825b912355cedead761211a494ca6f89b2367a2d2157e340e","src/mm/msync.rs":"a9092be024ecbfa9c14edb935404513498b0da2ac6c99fc31fe4e58196a95f02","src/mm/userfaultfd.rs":"8073443bd181ff0b3ba4d0b1ae67370b4864035a0c8b4898cd709dc47c518ae7","src/mount/fsopen.rs":"1c54a02f04ee6710e2c5053c73361eecc499c24cd72c7c7c012dc57a4621e382","src/mount/mod.rs":"5f0c9df4727592695deb1cd63ae1de021b03dcd9d0d1b68e1f34d12a7136cb19","src/mount/mount_unmount.rs":"3805b63d4415d5838bdae34c6f6d50017d09b0d837de141961e66c7fb94dcc0a","src/mount/types.rs":"601ae3e10b7dc496fed7f3b40a80e81c6edd7bf13189d7be45c3212d4c684c39","src/net/mod.rs":"7899807c9ad9e3fdbfd8b3ce2a1c7053d4f46dd7fa76102f620c6042c2d6314f","src/net/netdevice.rs":"e617af6949ff494de8747f4728973eb3564e25a2057b3150a5f609f4ea619784","src/net/send_recv/mod.rs":"b00743069268f2671570f76a4ff08b5487a344e5a6a12e62d40c2be5c25ac22d","src/net/send_recv/msg.rs":"c8ecb0e45df2c6cf655f13025ea7880214e5c085cd9dcbfdfa912f5420a6f3a3","src/net/socket.rs":"c1865fee7c354a9cc810853844a86c5ab4ab93dcec5e6de2d76993550b412ce4","src/net/socket_addr_any.rs":"b5fe6f012c67d70e0e4885b9e5d6e463c282e12330a0579ea98bdf8fedbccd60","src/net/socketpair.rs":"56f4885c31d2664cd16e18a9a88792a4912fedd953cec36dba67e8581fd57921","src/net/sockopt.rs":"21d269c34992643d403d50e3071b646cd9ed05dc9bdc53fe2f795bb5df43fa60","src/net/types.rs":"bd3ee0cdb102e8cd1f2e0434639084b599a10561fc7f2aaa226d44bf892cef63","src/net/wsa.rs":"29856e6d0108be6b719f6ef973c5396e48ddd58ecd0c2db9ca3e2e0ba4eccb5b","src/param/auxv.rs":"8655993d7d480f340d8fa3efeb35135e0107510f6c3cfb160a9f6dc00ef577aa","src/param/init.rs":"a31c0e5cea61a1a999767fe74f87c0d59eeb6bce66578b842fe0e0c32be27a55","src/param/mod.rs":"c514216b96d9520c9ffc5662c97b24f1f36f56fe1f5f3c9f64175c8b35577288","src/path/arg.rs":"c0f0a7c2fe37192cf6f7b35ae0e17620b863b31e55efb7b2d9f31b5def56a749","src/path/dec_int.rs":"8ff8e14442c46f8e7a9b80d73973619b4271549b9defd538479bf8c2d93aa72e","src/path/mod.rs":"8355324af7eaa91dce30fc4ebdd161691f9d8bf7a61bde1dde27a1bcca15369b","src/pid.rs":"f1c486000c5b1311b2d720cee88f089c17ef9a171709673dd06e6f35f4ff98a3","src/pipe.rs":"9f269090dd0588dc8d3feba4f4a78b61891bce91d3c9b64cdbad9251b06a9e11","src/prctl.rs":"19aa584895874ea48b9bbe1bf695b81257b0281df64dfdd91e1b4bfa298661b7","src/process/chdir.rs":"911216459aa429fe9f125f1357d6900b43b0007835b85c719875d00f79a74664","src/process/chroot.rs":"2b5f6124eb19f26ad2705174f7ad50cdc0a5d15abd59ffcf55421228d82130b4","src/process/exit.rs":"48de66e5504a00cb375d8f415ce63b6225a3f5204268d40726a7d0fbba43f587","src/process/id.rs":"e0a26da426962dd5898fbc05700083a68399d5b669fd5f4afaac7b282e0178fd","src/process/ioctl.rs":"23ad0285671e8d7ca71a63c50655dbf732ccea8af11d754a0558e0236db37e76","src/process/kill.rs":"96d5ce432c19cf2b600d5248c681c117abf53ae94bbfca7e75ac533a40e3968e","src/process/membarrier.rs":"1c4c39b359d1d0e9bbe16352eedfca9278d9ef298ade8ec00e998617bbcbfed8","src/process/mod.rs":"4fda62909afcb081281bd9a8eaf770dc3dfc2111013231ae23b0a1e101582f48","src/process/pidfd.rs":"150413a9cc550ffc432b3279a368223fa9577544ef29e45edeff3b79ae316cab","src/process/pidfd_getfd.rs":"74c778b872be0b800870e4633606461fdc8493b259031e35f8f558768d960cc2","src/process/prctl.rs":"0130d05362a17a9282f3391189095e1f4f51fb56d7a5205906a0011842df4576","src/process/priority.rs":"f135482e71ea8aa0daf92b9f238051178a4c904070fa8409622f94155df3c544","src/process/procctl.rs":"75e9f7e5c66e6563aff133ff99b3a35c80a9f0a616d318a93a65be39ebc191ea","src/process/rlimit.rs":"10b79de3ced0e64059a94c879742d46a35a6176c776d8eed75031d5e6340283d","src/process/sched.rs":"6c976daf5b5a30aa9a33456d23a46f6f4d257642963eb142b55e13a53aec4c56","src/process/sched_yield.rs":"6565faa3928b66ddc74a65e893e15edfa4b9be4f7e5f5f68527501a7f6bc3350","src/process/umask.rs":"1a0f31a842303c978e3f05ec191e2b5e96104c09c6596473b42b1fac34898a50","src/process/wait.rs":"f9c73dde2a66dfbe448501f039396dd26c5d678e4f8cb61c1f78014b7b49fcd3","src/procfs.rs":"4d4812a8db6897dabc33269ff59bf6d7192a65be977e879613704e29a8b73505","src/pty.rs":"652c412e7280d0344b3f9bfe376c106a7f1b42b898b7af344e6e72da268e2bf0","src/rand/getrandom.rs":"0a5320eaf5dd4c6d9b1252c41ca286b40a9ce813eb469c89dba41e6258612740","src/rand/mod.rs":"e1fb7542f1958fe77673aa628bd92fef1b9addf79ba23df2398d1231cb61c148","src/runtime.rs":"958cdf1567c5758c73c197fc36d1feffb414a22a76a7a287afc84f330f2d2279","src/shm.rs":"b96fe8a05ee5d4536464a8843a776d43a938abaf22c772fc35b5373d95644a8d","src/signal.rs":"a294b49d487dafaa42e534f8b1d93e87bec135087676b2ba2ef865cf2fccdaf2","src/static_assertions.rs":"504cf66f0d5b8e335be02f9ae8b0a355abc98c2c82eec0098bdf0988e662e260","src/stdio.rs":"6f78cbc0d102eff9354fa1fdfd1b63a45ea159d0a9ac5d25ecf703383b847b55","src/system.rs":"e048eccf6f60ff49fa3312e7a01a9f641787c195c4db745f1f5a2f2c443d7e91","src/termios/ioctl.rs":"a1ac967f7811a482f8bb53847c37c8359f518cd26da9df7b816ba678a0139623","src/termios/mod.rs":"b44b7caa60b6f458657ed58a0e0eca41bb4e6d6be4b0f042bbb8ab7056cebe4b","src/termios/tc.rs":"9af4eb264bf23bc0b0ad1707fcca687020b20f0775a28209b237fbb72089d991","src/termios/tty.rs":"35a5fc2d26501e0e6dde1a755eeccf7b4f3b4702c5bac30e0953220808ef7034","src/termios/types.rs":"b5671eedf541754c54f680002bafed1adbabce172d09d7c4d31fdf9313ca18c8","src/thread/clock.rs":"83681fa00d5efa15c5b7cba10015a0c99d855c4ac78714e3989d91c999e5ba80","src/thread/futex.rs":"985f9a0dce1e2a4892ae7f26bd1bf119ceae3f9fa6b4707e166624fc1cee76d4","src/thread/id.rs":"bc4cf152388962303ea835b97acd64e499ecd15f94eaf6f133ff5a1a582377ba","src/thread/libcap.rs":"4c51b7df566d38dd0f85f81ef53279a745a39f0f4e1154791fd38438e2ca7db1","src/thread/mod.rs":"09b19f25ed1aa65f6605ed7deccc4bd945e3ae872a60275787f44944a73edf3f","src/thread/prctl.rs":"ebc89b731eb8fd1a8f82a50dbba849061476a4537bba8702b29db657d5287ffa","src/thread/setns.rs":"ea9142b1f3a5b3f329683be185f960c50e5c1636149e91fbf59e88a897fc607d","src/time/clock.rs":"e59a29f1bed8c31c3d5b6fad60f2d4fa6cab8dd8e86148bb3693a5e3a1ce735f","src/time/mod.rs":"43afee938c80d124d04d4ba190c03f4d21d1e3bfc154fff309211e4f6eabe940","src/time/timerfd.rs":"f17092b84553741aa2d2b44c6992b5d2c8c96cc2c2007fc9a2c6b2064485e53f","src/timespec.rs":"32a4d930cbc0f6dbd23153290db920671cf4ce65a4a127e176f897c1cde42d7d","src/ugid.rs":"6616c6e35b7e43aee5b150f1efae7a50711e0947943c9a96833dbe214ad9e85f","src/utils.rs":"9ae76f8a41d6cc350cdd58c9084b5c3a5a708eeecd769783debdbcbaef442182","src/weak.rs":"7e3169bc97e76fc4d52b040391a8df36b06536fc0f81cc6e8e71b951cb1fe54e"},"package":"70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3a15a4a9894d88e1982045f559b7055f56ac87e73203cfad46a17be8977a1960","CODE_OF_CONDUCT.md":"f210602311e3f74b32f46237fd55f4ce36d798e85e3db1432ec667f63a7ffc44","CONTRIBUTING.md":"3fd57de5c678db1c972da676a8231d2fde9820695ef1f0d53f1e55a3e81d9de0","COPYRIGHT":"377c2e7c53250cc5905c0b0532d35973392af16ffb9596a41d99d202cf3617c9","Cargo.lock":"ee9687adf0d568104c2d8e28fccc7042990eb62f3da28d4d94d1a9187149821c","Cargo.toml":"42d204101e647da4dde1220b6653dfa647b07a58143b5db4f893a32c871f696c","Cargo.toml.orig":"c302e0557e99de8b25558717c08b8d40de05abe98456444e20fc7e74cdd58cf1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-Apache-2.0_WITH_LLVM-exception":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","ORG_CODE_OF_CONDUCT.md":"a62b69bf86e605ee1bcbb2f0a12ba79e4cebb6983a7b6491949750aecc4f2178","README.md":"cec45686b62cb75ef2f0c851939b7ddcb64678c27c18c7bca18d6f5cde2446d3","SECURITY.md":"4d75afb09dd28eb5982e3a1f768ee398d90204669ceef3240a16b31dcf04148a","benches/mod.rs":"e260e67273aa0a37cffdc5cd451699335b8ee656c17275a0d0f2b4563c6018ca","build.rs":"ca1a2e173b669f8e13b4e830f3b20530996fe2d60f22f2609ced1a7032affd0f","src/backend/libc/c.rs":"9c040c6f914607580d84fddc62fd6fd03cf14976085000116a603404dbc433d0","src/backend/libc/conv.rs":"a254fa84164286ee6be64f49b5bd5f7e2fd503ebd5ca9076dad4c2507a351dc2","src/backend/libc/event/epoll.rs":"93d3eb9e0e397afc3c44797b315ce92ff8b22f2372812b19cec9e063c55032c3","src/backend/libc/event/mod.rs":"ad30f99f7da0768c18fffac6ec71e658bfed2e44f0634f48c2e0ffe4677ec231","src/backend/libc/event/poll_fd.rs":"286268c0e94bc1716a61835ef3c6324e8f3feb96ae2491ad5ed919300e80070e","src/backend/libc/event/syscalls.rs":"f91bbe7d222987c89a2647817f6819dd536cbc4a685dfb794f403543c32df777","src/backend/libc/event/types.rs":"b966e0a3a018ca2ce507371be900fc73b2814cca450b784583207ad2df473f13","src/backend/libc/event/windows_syscalls.rs":"ebfac665c6676c4b803134ab8806be8aa2e96bdbc7799a19c544cd9069b35787","src/backend/libc/fs/dir.rs":"3c43768f9e56cb4297594c05d91a52be20029dd2b3e0b91f6b1a13f31e595fe2","src/backend/libc/fs/inotify.rs":"a027a718db8bf6ff9a778c2cfa706850b466240b0a2296d72b9834c0096968e8","src/backend/libc/fs/makedev.rs":"89c679a0ef18dd41b3c6223bce0f329ad35bf6cadbf16e47b33fad3f312ba4a6","src/backend/libc/fs/mod.rs":"3d28b803011b57da6315bb747daf0117218687c0cc610358f5dafddf0b7d44d3","src/backend/libc/fs/syscalls.rs":"89cdd809e0cd89fb4f85e2ba0716ecf857ccb66db69a7fc40a5e0a25b15b39d3","src/backend/libc/fs/types.rs":"cae37a0a3099b8e400a48927c60c15efe0d05d2e71f78577742f8f7cede62dfd","src/backend/libc/io/errno.rs":"bac592ece7b44692237a350ff4905bfad30fa042d1e8126e5229e02913fb1c9d","src/backend/libc/io/mod.rs":"746647bd864e4ec7717925b6d176cebdb392b7d015070244cc48d92780351dd6","src/backend/libc/io/syscalls.rs":"c93a7867fc13eecc953c6335fd79c37d4d1734d3a06e13e5d7e08bd985c66326","src/backend/libc/io/types.rs":"2efd39bb3df19a9db5496217284f3d2235ddb354fac81dd71861109a56bede0b","src/backend/libc/io/windows_syscalls.rs":"fab3fa099aa89cea56a6edc651dd37750e581534f4f45b04a7e425f130b08468","src/backend/libc/io_uring/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/io_uring/syscalls.rs":"5af8146d5971c833e6fd657f652c618b31f854e1b0811864fba9b658cb633e19","src/backend/libc/mm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/mm/syscalls.rs":"c04c61ad3d7f3b24d13f89144d7fa0a05658cea4763207f9250db4f9362de2fe","src/backend/libc/mm/types.rs":"55478e173b7d82e2c85934fc0dda79c29f46a305228df78f1e90c68ac9d3cfec","src/backend/libc/mod.rs":"087d2676df88510b089255053a4865e62c64172723588386fe8244d2f1a681c4","src/backend/libc/mount/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/mount/syscalls.rs":"d2d35f7ae989bb52722e28cdbd775243c5d7da9eb411e0b2b9632f2aa7c1533e","src/backend/libc/mount/types.rs":"bf1d541daa248aa023bf18aec7645f2f8c402ac4aa1df2f55b8a784057c2e113","src/backend/libc/net/addr.rs":"9bdc2febb20785bc26a820eaba52cb546c67c79cb547f08105087cd0f79d5861","src/backend/libc/net/ext.rs":"0dd64877abe1ba86b47a2ab34340e3f6cc7b53b22d0bb5e237daf6a82edd46b0","src/backend/libc/net/mod.rs":"562d23225d6dba8f095e3ca41af60dcf6cc40c2cf17bf028f90888f809e86f07","src/backend/libc/net/msghdr.rs":"6f8aba792b4adef5c5d3d4324a813a67a063a50d10437bb19bf7496666bd6de6","src/backend/libc/net/netdevice.rs":"c6c3cd11b0181a74243705438fbf0fedeb02d4201ff3ad9f45a084fbd57a9c21","src/backend/libc/net/read_sockaddr.rs":"61fc1c744b376d57a18d78d8f7ab469236c614f5fa7aeaf37a636e6a967b9066","src/backend/libc/net/send_recv.rs":"1450ca958431a5bf3a85cdeef88b387f30d5c1215de2c56d164ccda38f21b36c","src/backend/libc/net/sockopt.rs":"d53d52f1c55f522c1d0de5e446df3017757b08270c0a0b593a583fd6c56b0876","src/backend/libc/net/syscalls.rs":"1412f9deed57ac0909b0b1c3ac3e5fb7d5c31ab356212c9131e33378c342d2a5","src/backend/libc/net/write_sockaddr.rs":"bee221d0a1fedf4ddcff045faa2702c1f1e68b4d6c3f2f7b079d888e0ef9da56","src/backend/libc/param/auxv.rs":"1877fd1dac415b58a4ae824ef9abd8b49756f613f6915820223f2c586fb4d254","src/backend/libc/param/mod.rs":"5234b8f1bcb886cca6ea003d411d75eaeebe58deedd80e3441354bf46ed85d4d","src/backend/libc/pid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/pid/syscalls.rs":"49ea679b96c0741d048e82964038f9a931bc3cf3a0b59c7db3df89629b9c49e6","src/backend/libc/pipe/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/pipe/syscalls.rs":"8affde100f6a9dfc762b79d1e48be5c1039be414f8ef7d5a6acaba882a68d259","src/backend/libc/pipe/types.rs":"9826013bc5fa18acdcbf09c650b96ce301a18ec009139ebaf79162669b1fc2c8","src/backend/libc/prctl/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/prctl/syscalls.rs":"8a2684f444a7555098dce2b92270d81cefdae902716c6e5d59bd7b0657e8a29d","src/backend/libc/process/cpu_set.rs":"5fca2b47289a2bb6ba908c910a6d27ac78ac10ea21d3c0c018f72f8816c5b9d7","src/backend/libc/process/mod.rs":"806e26da8d1e7afae502987fcd650f4d348da147b8a2e74447affdca153e2e97","src/backend/libc/process/syscalls.rs":"f08a76a5f32e40a69c99261eeabb405a58476ef9e85ae142f2fce19679a42ec4","src/backend/libc/process/types.rs":"fb2caf34b17079aa72c04aed0f9a31d534ea8e8b73a80c758b748bf5e38df52b","src/backend/libc/process/wait.rs":"0cc556aed976b4bbb3965f74fd76b8216c755fce25043b7b21ce54afa07c9773","src/backend/libc/pty/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/pty/syscalls.rs":"566fc9a2cb2e38d7d7ac2405b22c0522369cae4a8f4fe18b55123ba94d3d5a95","src/backend/libc/rand/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/rand/syscalls.rs":"35ea6b6e0f8a7fb064fd5cb33a3a855cd161a6a00f93d76c861b2a2c66db85e7","src/backend/libc/rand/types.rs":"4eb0b4cdd0a9b089d1c9f6a25ad1ca97be28a38b7b07a705ec605b773f63f880","src/backend/libc/shm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/libc/shm/syscalls.rs":"60d797d4e85e08e6330e6b8d80094356ce377e5484952f88ae2a6e49231c268c","src/backend/libc/shm/types.rs":"2206eac8ee74951b995e1e80f10bf235cc6b04e0a099f4adefce546378838233","src/backend/libc/system/mod.rs":"38563ea68829ca5a4b1b0695ac8a5c05718e85bdc88a36dc805efdfce45d3909","src/backend/libc/system/syscalls.rs":"c18c2942811ea93af3125b58d00a1da05c54e5ff438a3dc44cda53bc9d6fcf03","src/backend/libc/system/types.rs":"6871e16aee14fe2ae03cea798c3e509ffe44778a9c0e5608fd73e2e015876d7e","src/backend/libc/termios/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/termios/syscalls.rs":"f377dfbf501fbc3cdbc9e190dd650c8141c00c1593b8c62901ecf346a0c1a7c5","src/backend/libc/thread/futex.rs":"b666828653b12634bbd7fd709acf69641b648ec40962a1d4f904c5db14d2eff5","src/backend/libc/thread/mod.rs":"fa710053974d7f16a6c49242ee6c10a3b9e1143452b9daeaed8837302a679fff","src/backend/libc/thread/syscalls.rs":"435392788b133b83eaf73913a3adee5b244b471df316dec02469832cfdc71160","src/backend/libc/time/mod.rs":"38563ea68829ca5a4b1b0695ac8a5c05718e85bdc88a36dc805efdfce45d3909","src/backend/libc/time/syscalls.rs":"bf847e94cc156bdb553755baa88dac240db4dcaf690f303b0f205777c5a9cdfc","src/backend/libc/time/types.rs":"d0307994ffddd3f21f702d9ae4400750aecccfaf4a01268161dc4fd72de5c373","src/backend/libc/ugid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/libc/ugid/syscalls.rs":"8edf91b8790add23902c9f5418da6b0723a371677f29f490e0c8af852f0f1a0c","src/backend/libc/winsock_c.rs":"502da2ed3cd6ca99bb7ee08b0b30e25c212632885cec965f9816366c6b931ac6","src/backend/linux_raw/arch/aarch64.rs":"2a255c9135bc8a321c180f52b88eb2b158bc9170cd222149caeae63c24587d44","src/backend/linux_raw/arch/arm.rs":"165bccb5883d0136e55d42091183765f83d86e9d37a7cb2cec9ae8af32774db6","src/backend/linux_raw/arch/mips.rs":"24af364aa93fd4b9917639d473336490a143f0d1723b09f388e72d534160ee51","src/backend/linux_raw/arch/mips32r6.rs":"e436a2ade34f2f7c58b8924462b07a2499dfc951e1e1318d51759444fb8b658e","src/backend/linux_raw/arch/mips64.rs":"897da9ddc877963ad59464d7f81dc59df8a7e91251e6adea14cfd946e2740a1c","src/backend/linux_raw/arch/mips64r6.rs":"3c08aea13c1139fb0dfbe74ca3d0147f007c3aa2eda641afb82c46f6aa4f6cd1","src/backend/linux_raw/arch/mod.rs":"37eaeea601d39be00d170856a31a8ec6a27b0d3ac22ab3ee642ab0e45dee237d","src/backend/linux_raw/arch/powerpc64.rs":"dfb001f8636a5e46d728900b0804fe6c374e5e18a6f0e76d7d62e0c07da74477","src/backend/linux_raw/arch/riscv64.rs":"41d33242d941030f46077dc2b1bc4c7913fe7630d693a5a7eef966bcf38f9d8b","src/backend/linux_raw/arch/thumb.rs":"2fd979ab421248c0a4c592bc0cefee63edc26528f469b71b63eaed35356e42e8","src/backend/linux_raw/arch/x86.rs":"fc72f595ec75768aee248d405f4958a7ba1db65ac9fe54b277cd003eab33316e","src/backend/linux_raw/arch/x86_64.rs":"e929036a1f3cf93ba538f4523b241605cc7b5e61f84ffe6d9d5cdbcb6f73e543","src/backend/linux_raw/c.rs":"db66abe9b91ce0f16dd71762744013046f29542a46a577454c9ff063e9cb649c","src/backend/linux_raw/conv.rs":"48a261b8dd6182ce876690cd4946d00c3697bcf7c3d89a46e3a3d6f50d39c2db","src/backend/linux_raw/event/epoll.rs":"a102c2d8d7d5d07a5d846f30672153269d1762d1d846be1786b22fcf095e8721","src/backend/linux_raw/event/mod.rs":"72e46b04637e2d1d2a6b97af616144995399e489d1fe916faf835d72fc8c64cd","src/backend/linux_raw/event/poll_fd.rs":"a5773464e9e30227b4046f029a27d3daf2c7bd0045e54565cf1a8ac2a0d61e81","src/backend/linux_raw/event/syscalls.rs":"44460b0045bb9d9f48b0baeb009a6b150a2902f9b733e8f6c5a36726b8db2d41","src/backend/linux_raw/event/types.rs":"0551b18f982e233a0a06d8a9c3dbb29de0c204dcd64dd6f7e88b6c96fa9a9be8","src/backend/linux_raw/fs/dir.rs":"3107b07276f171a5837bd37a9c1e05151ca21d59ae2b85afd2c6e59e721cdcf2","src/backend/linux_raw/fs/inotify.rs":"713ec3b85f281efca19bc4f495b7537e745fbf1d8c26592c80ceec6fd2ab59b5","src/backend/linux_raw/fs/makedev.rs":"c6b4505c4bcbbc2460e80f3097eb15e2c8ef38d6c6e7abd78e39c53c372139e2","src/backend/linux_raw/fs/mod.rs":"3d3a42bbf4d086f806d7d9f6e4b0a49a873dc27f4f03ffca0921f5536acc24e5","src/backend/linux_raw/fs/syscalls.rs":"5f34547e8d57b69aac600edf27893381d98c6d127a969d7b241bd9220137c649","src/backend/linux_raw/fs/types.rs":"4ee495127d88d3826f0277d2e62bb0e7553fe5e6693a153c48f2b74ba593cf36","src/backend/linux_raw/io/errno.rs":"befa94275b30e8262718e8c9e9662b08526ec55779861dab4e2e499daa3e097d","src/backend/linux_raw/io/mod.rs":"7ae2324427892cca6f5ab53858d847b165f790a72ec25f3d99fb15f0506c9f27","src/backend/linux_raw/io/syscalls.rs":"568e16751191c14bb37f7883b17cb577dc97e09d615d17849c0e7e10e3898f1b","src/backend/linux_raw/io/types.rs":"d0df5a62248e1ba19af0f89f86da7ba2312d97065c2814ddf6b08a4a0db23bad","src/backend/linux_raw/io_uring/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/io_uring/syscalls.rs":"0f7c9cb7ccddf5687e4b9e5b23558871a452a29ac6095a0184a06c47b9b18eb6","src/backend/linux_raw/mm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/mm/syscalls.rs":"4e469542c88ea15853d5022e7e1d4b8fc291265ca314766d60d9395dad927e19","src/backend/linux_raw/mm/types.rs":"b5bf9bf775d3771e79aa234788fa3d1f25009f3f51cd59c72efc4f5e2c7bd790","src/backend/linux_raw/mod.rs":"86f7c3b1d57e57a9e5b5dcc8ee24ded5054a917069bd9824f47952b10bca2221","src/backend/linux_raw/mount/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/mount/syscalls.rs":"8442c82814961f69c488222faabb82c44d2e7227b10faff919cbbd197bb47484","src/backend/linux_raw/mount/types.rs":"bf3dff5aad1cec9d998496230469958c836b76643f0ad17b0ea29b957357bcca","src/backend/linux_raw/net/addr.rs":"161ff30891526e309b1cf9514e9113227c6901c5c1bb346cb8fc3a53e43aa410","src/backend/linux_raw/net/mod.rs":"5640bbaf4963ac4575b0537173422ed6f6a43f34a8f6b656e7257fbbb13e5bcb","src/backend/linux_raw/net/msghdr.rs":"8b18974b81ee78af7a5c64733041dddaaa378a46cab8b984bff5b3b4be499751","src/backend/linux_raw/net/netdevice.rs":"a0354e44ae2f8402576b55470e48446dd655d77a69f27f814a298ab3e3a1afac","src/backend/linux_raw/net/read_sockaddr.rs":"7cb3c8bcc80c5eee8602323cd83f36c1784927d9dd0c40ded29af6fb09c57ece","src/backend/linux_raw/net/send_recv.rs":"6d5d2aec61a3c1b4a5fef1a8a487dc8e163da8988d1237541ed008baa01128cc","src/backend/linux_raw/net/sockopt.rs":"2b42cd181772ea78d1b5b64d03fd2939a5e1a0c49b84c943c9fe8707b6477344","src/backend/linux_raw/net/syscalls.rs":"0138662012ca89e063b3a03cf8fe17b97fbeb38a3d18c42938ae047a4a392105","src/backend/linux_raw/net/write_sockaddr.rs":"0efa4e17b4008da2cf2aada2d18acfccd31a3b49cf8ac5d608e77f3ea6627fec","src/backend/linux_raw/param/auxv.rs":"c9a582a02b4c87e26f6d5026c78e0c3a3ec8a025079cd3023e474d974b29268c","src/backend/linux_raw/param/init.rs":"f2275a2324a99be8d804fb3b7fdf86a43c7d428f660280b7e0e7d19c357f0200","src/backend/linux_raw/param/libc_auxv.rs":"9a7b4ba75a18cc384df1b7edc5525f76c147bb84fb67d3730ba2c5ae64ebdff3","src/backend/linux_raw/param/mod.rs":"2e6a1a1c00351b9c88bd615aa923f71d76208df5626dd9bea03067f28f81dc31","src/backend/linux_raw/pid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/pid/syscalls.rs":"eef6aa01830ddd510b83f507da2002c03e58318b73744be2c06ebbe33c4f194f","src/backend/linux_raw/pipe/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/pipe/syscalls.rs":"366c730fc3e991bddb9f5a15b8c3917a8e6ace6d1d5a9113b2749e476faf6f83","src/backend/linux_raw/pipe/types.rs":"cf53bcdcde5d0ee15e0e3566ceaad39fda44e69ed6f94a99fadd9be9b8be09cf","src/backend/linux_raw/prctl/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/prctl/syscalls.rs":"a18b224307e0d27bda9b7b85c75cd6c7ddfe39f5ce52efb7bb0bf0585b757343","src/backend/linux_raw/process/cpu_set.rs":"b31889f972676f57e3599375dfcd59dd72975977ef345d11c22d51f0d4a6400b","src/backend/linux_raw/process/mod.rs":"fb393c70a9c63ef9a6bf1fb5a2dc94f07d6b0b6987cc5231c15c607015dafd68","src/backend/linux_raw/process/syscalls.rs":"07c14d796a65d3958a9199dae00c8b864fda70e26b67815aff20edd20a985f2f","src/backend/linux_raw/process/types.rs":"6811ba822bc12a1a6336649151b4adb1f5d3365684a31c07f01953ea9547743d","src/backend/linux_raw/process/wait.rs":"921aee4b0048746087f52615a98edc2aa0fb4b53d6df44be4533098df55d1b05","src/backend/linux_raw/pty/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/pty/syscalls.rs":"ae09c4aecc0ae87b1ca58d82efc58007b9dddaae78460d615f48da19d1cd0f89","src/backend/linux_raw/rand/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/rand/syscalls.rs":"317cdaf243623329ee345131054e86a06a0863a9e90c5dba73e1ac3475ba6305","src/backend/linux_raw/rand/types.rs":"a21dbb1ab31eed6b59a57520be5a3c603c36d18ea74e67f7527f40835ba209a3","src/backend/linux_raw/reg.rs":"6bfb53575494f5de76d5112a7e4eb6d0c266b1af0a275aa33b9bc9e6e7a2f41c","src/backend/linux_raw/runtime/mod.rs":"b2cae8cce3822c3c92942f06ea0b68464040dcac33c6f0f7ee392c6269993347","src/backend/linux_raw/runtime/syscalls.rs":"dc7df0416919d1eef7e4919fc38836e2081903db286330d59b0119cc292155df","src/backend/linux_raw/runtime/tls.rs":"6316060560a112c2e9cd9807cdba6e8c91414113a04a739160929ae9a67bba1f","src/backend/linux_raw/shm/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/shm/syscalls.rs":"3ebf91610b02de0312e1f0f0cc5d56e12b4d93794540087b3182cbdf3cb9c8db","src/backend/linux_raw/shm/types.rs":"b831b474aba7eb97167c9289f5257776a72b39134b44e67a0ecfcef2394dcd47","src/backend/linux_raw/system/mod.rs":"8aa966faf3853d1a93d0ed91f7e5f4a53539b0287b25a5bfe489fa1d07f7cfd7","src/backend/linux_raw/system/syscalls.rs":"19a7ab17de906ec237f16a816da036723c1f55f605e8e4a26689343eb4cd76e7","src/backend/linux_raw/system/types.rs":"1ceab8d738a71043473b26e97fa3fd79d588a86d4774cbc9b9e1d4f1447a016e","src/backend/linux_raw/termios/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/termios/syscalls.rs":"25a0341ded4657a3a5389250c24b3310642785d386bc51f31696f98f4f1e770f","src/backend/linux_raw/thread/futex.rs":"0aa0f9f5be6a79de81e82c9f11f1bf8831f682a4b2f6cb29669e1591636f084e","src/backend/linux_raw/thread/mod.rs":"6ad4a4b90b9234e79900b27ebbe8837e3a7a36aec532912e3e253edce5225067","src/backend/linux_raw/thread/syscalls.rs":"9bc9a7360b6b8711b82bc6eff58dbcfc1d936f6e2cdf828084ed56036ade76d7","src/backend/linux_raw/time/mod.rs":"672724f55b7b7be6a7452bb1cc2d28b5f0aaa840a2856fe363acce624e1beefc","src/backend/linux_raw/time/syscalls.rs":"7dc6975bdc30e8fa02f3408b934957e65ebbca281c8c9806e5de9404845312fc","src/backend/linux_raw/time/types.rs":"5f49ee7b201976114c6555f0c5a81d3305e18e726e54edc5a5474641f3cdc278","src/backend/linux_raw/ugid/mod.rs":"2c6478857a0751625edabd61acb841819bfba1093b1faeded15693c805d84952","src/backend/linux_raw/ugid/syscalls.rs":"8c86d251db33b399a1d1cbb8e87afe650b78db84f444d3251309b7a0480b54f7","src/backend/linux_raw/vdso.rs":"056314f72c71d4b041739337ca2098afb7fe070f844327f462c293f43481b75b","src/backend/linux_raw/vdso_wrappers.rs":"0e01221cbc6f0a489e89b0cf2fa376c3826ead8491ee8510476b75e90784f39a","src/bitcast.rs":"e21c87c292c781b27256c6f5dcf9fd52dd69ed6e21016cbd67ac31a8219ebf8e","src/buffer.rs":"8211a52e4fdd6ad74dcaddb885db25fa616898f988fc79b43af24b89c32d8421","src/check_types.rs":"e52f710e1cfc12ca13a495f2b43c227b293ff295e1ce3ab332935b28a7579872","src/clockid.rs":"bd443c60868586c1a3114afacc95193de1d8cb99b7c9d710e0b3835596c74a24","src/cstr.rs":"41af2a4429fe6c67a8883f8a8f63d66c90df566abda74fd2b03bcef7b9f24218","src/event/eventfd.rs":"81cbd08f7bdf40a6ce1ca692b63da1dc8ba925282990668d9d68f1203e839fa1","src/event/kqueue.rs":"2f776485e16fe57639ad7454886e0ae761880b122976141ac05b4b2e7d82183a","src/event/mod.rs":"77f6c7051f70d4d5873787cf744e05b64519ba61d8da42298aeed27a906031f2","src/event/pause.rs":"cac3317286478565298a40788c1ce13c1b71543078a6f09655419de325022f6f","src/event/poll.rs":"899bbee8e565110b2581594e7aa5067a426f859f0a414935e2ce3a9732b6152a","src/event/port.rs":"4e51ff150e5d17cbd44aa64a38b99c15e26eaaf2e350768b5dcacdfde4fa5212","src/ffi.rs":"c2b8b38c02d72749aceb715c496726caba1f1fa989ad3856d0103a2fafed89ed","src/fs/abs.rs":"b671489378e14b708c784c4a673e6645741a869c7d1dd1918e28e1eb1a138829","src/fs/at.rs":"13f50b86575443db8b881ce525ce2c5d2f377e528c33258729f0c06037de9499","src/fs/constants.rs":"23923e0fce3221bdac371fe2d05028f30a87dba4f9b4a573b69dc2d6d39320b2","src/fs/copy_file_range.rs":"d3b644374390d482b2ff749a2459458872b57d0dcf9670368739b7833509a7c2","src/fs/cwd.rs":"9f429a79ace6e17455634da09216ee0ad3d067a4541518b3193ae6a8d9ff1e26","src/fs/dir.rs":"347a52f4ca9ac6321c52e802e97ec90d1b4c62ec955c8996fc17f8f5aed69966","src/fs/fadvise.rs":"1220e2cf5cf58fc7cc950d48738050a052c504f745ca67130daa6410e248230a","src/fs/fcntl.rs":"1d1ee1e0bc962779e1cc1b8b76f39c820746240557daa9e14b47b1799120dc39","src/fs/fcntl_apple.rs":"e2f23f038083621bcdecc98d02ce1023508afaecdb2ed0fba5c8b70f955301e5","src/fs/fcopyfile.rs":"ce565f61e1fbf2e31086077c2f1d01b6bb3b048915edda87fe9a4a4f5e8ff7e4","src/fs/fd.rs":"9b3ac2000bc00349cc224b0cf1d77515298d9ed99f75373d2a0cc709ef120d46","src/fs/getpath.rs":"28f6970fc1bbc37bb35c84724b59eac436ea7407a4522e18c2bdacb1fdd2edd9","src/fs/id.rs":"1b5c8a8baf9a9bb1f895f97189cea4e5982a0d35b192afeec6340a6c6222e0cb","src/fs/ioctl.rs":"c7c2db229daf7c9f0109fe7f45f05fa9a6a472950a2ad408c71514e6cb7c9d7b","src/fs/makedev.rs":"85520b484cb7c15ab71ea1c368578ea3b7e484d82f8510db92b6ce9f7ca341ae","src/fs/memfd_create.rs":"a8bf1dced54c7592e71da896021338d5092c1693d12cc42e79bac435fab2792b","src/fs/mod.rs":"b1e92f119ce8acbcc55597f5512727622bcd12d6d0ce9fdb2d9b1cfaa9e42a64","src/fs/mount.rs":"8f6ea2b997dd83c50c90291b9ada3ed77a9ce1ad701c9b0d533b5113b317be5b","src/fs/openat2.rs":"4a95c15dab533a41201b5fa25c8a212956b7571d58cad696bdaf45af8aef96db","src/fs/raw_dir.rs":"18ad797876d6230c38d4cacbed081c4028e03ace477d0520d9b226b40de942f0","src/fs/seek_from.rs":"a9efa0feb9ac789cf47667e91efee2e3f2dcde16cb3b7a928c99da640fa0e0d6","src/fs/sendfile.rs":"e3b2058741cf4b1698f34d84bb37130cf2b72806d522a16fe541e832cde136cb","src/fs/statx.rs":"613480f0f3277790281b4cfe866ce72e4efdadca691969f6ae5e3ba6fc33a84a","src/fs/sync.rs":"a3b23543834281f347b0f873bd38154d31d404871188ac08f2b20b9196234cfd","src/fs/xattr.rs":"5e222adb52caf69d949ab3f944fb2a482dd6ca3a47200532ca6e72d44cbe8334","src/io/close.rs":"2ddae17a2c9dc05fb2cefa134815699c2b3af2eef8026407b8d009cb3ceae6b8","src/io/dup.rs":"335e76f8ad5aa021e654f61e043058e964c2f9914c4785fc09bf6f49f4975290","src/io/errno.rs":"58a4d20ba0924e4d514e3c876fbe08982f1623187642ae14780815e65989c8c8","src/io/fcntl.rs":"41c1b370be55aaa68144dcc8a67b2d53504a5e6d8ee1bffabac2cc64c66a4043","src/io/ioctl.rs":"af4e736b6739cb1ff0477c1b818eeac789258863b79d12e441a08be99d49fb77","src/io/is_read_write.rs":"1bfb9ee5d58e0b29b44af12fe2668c7bccc841358698dcde47f1519ff9bb73b4","src/io/mod.rs":"75f1d0646be1d4c7c08b5887d8119b0103be8c25c43ccd4e0e97015508c0bb8f","src/io/read_write.rs":"f36488a87a35c37c004f5111e76aad3cf6c2c793f41f78f2daba7a84ecae9079","src/io_uring.rs":"b08662af4b1b205ef644ca7517688957cf54cab3fc693f6205165550a330a5cc","src/ioctl/bsd.rs":"32ba3399a0fe3f68bb458baafc2a21af9bff655865c7ea70990b7e98a26d3907","src/ioctl/linux.rs":"96df90bbc926783f387e8fe1656841d4c7a857fd4e9f41f95492f7dcece33074","src/ioctl/mod.rs":"ebb1e0865bed1b98917d4824082caf1445559a0a19f588094db90f46c224f780","src/ioctl/patterns.rs":"bd6e309c8b548dfe04aaffe805972582fb56a0b717c45b45447630bdf9b88433","src/lib.rs":"55f4fe027ab6e638b4613893dffc27a0c20b0bea6f185b76f401f34a480b78f9","src/maybe_polyfill/no_std/io/mod.rs":"77889bb5c5a4f2e50e38379cdaa5d0fef4b0cafc3da056735df01f6deae75747","src/maybe_polyfill/no_std/mod.rs":"ec94a4aab4bc475785e469d10fd6bc95667e1d47d958e9cff3a19049d88c8c80","src/maybe_polyfill/no_std/net/mod.rs":"1e94d21d455bb1da18a4fccb24b3d93ad42698e22dd888b78115d6266c80288a","src/maybe_polyfill/no_std/os/fd/mod.rs":"27ef0afbcb0695cbb15101070f417eb51e0ef85ae66ec967d95e80771d507c47","src/maybe_polyfill/no_std/os/fd/owned.rs":"d82bfeadf28087cc9afd10269f09a8b4125915dc3288b6427c79f5b4c58ab751","src/maybe_polyfill/no_std/os/fd/raw.rs":"f3648c7bd4a6ff94bd823ed9e0d99d398e02f24875cf9b25962736999e7c6943","src/maybe_polyfill/no_std/os/mod.rs":"27dab639a765827644005d5f2fcc7c825310606b889cc8dd83f54c9528350dc0","src/maybe_polyfill/no_std/os/windows/io/mod.rs":"5bbcc05c83fee5026dd744a994e0458469466d5be39081baa62df07753b92fd2","src/maybe_polyfill/no_std/os/windows/io/raw.rs":"4c32609a489dd938a49328b5637cb3bafb96437f2f9f269ab66d7d3cb90247f6","src/maybe_polyfill/no_std/os/windows/io/socket.rs":"c658f42f24eff44a661f2adfd24a11af80fe9897f3e2af4dc5d2c64808308d65","src/maybe_polyfill/no_std/os/windows/mod.rs":"fdb416f8f231a4e778b5f985b9ae712ece5e1a1402963ad1a5f6a8b9843795f4","src/maybe_polyfill/std/mod.rs":"7c16c86cc73e226e65ead598e4018238b22000a345040b706bf1e1b3eba115fc","src/mm/madvise.rs":"69481cd3354dbffe6cd93b234448e59de6d0fe6440bcf8b12f951f37745bc1dc","src/mm/mmap.rs":"3b0abe64a6a606ea41b06acfc1079bcde1542c17475951e5ed900b86c3e5988d","src/mm/mod.rs":"b3a6cb838986d45825b912355cedead761211a494ca6f89b2367a2d2157e340e","src/mm/msync.rs":"a9092be024ecbfa9c14edb935404513498b0da2ac6c99fc31fe4e58196a95f02","src/mm/userfaultfd.rs":"8073443bd181ff0b3ba4d0b1ae67370b4864035a0c8b4898cd709dc47c518ae7","src/mount/fsopen.rs":"1c54a02f04ee6710e2c5053c73361eecc499c24cd72c7c7c012dc57a4621e382","src/mount/mod.rs":"5f0c9df4727592695deb1cd63ae1de021b03dcd9d0d1b68e1f34d12a7136cb19","src/mount/mount_unmount.rs":"3805b63d4415d5838bdae34c6f6d50017d09b0d837de141961e66c7fb94dcc0a","src/mount/types.rs":"601ae3e10b7dc496fed7f3b40a80e81c6edd7bf13189d7be45c3212d4c684c39","src/net/mod.rs":"7899807c9ad9e3fdbfd8b3ce2a1c7053d4f46dd7fa76102f620c6042c2d6314f","src/net/netdevice.rs":"e617af6949ff494de8747f4728973eb3564e25a2057b3150a5f609f4ea619784","src/net/send_recv/mod.rs":"b00743069268f2671570f76a4ff08b5487a344e5a6a12e62d40c2be5c25ac22d","src/net/send_recv/msg.rs":"c8ecb0e45df2c6cf655f13025ea7880214e5c085cd9dcbfdfa912f5420a6f3a3","src/net/socket.rs":"c1865fee7c354a9cc810853844a86c5ab4ab93dcec5e6de2d76993550b412ce4","src/net/socket_addr_any.rs":"b5fe6f012c67d70e0e4885b9e5d6e463c282e12330a0579ea98bdf8fedbccd60","src/net/socketpair.rs":"56f4885c31d2664cd16e18a9a88792a4912fedd953cec36dba67e8581fd57921","src/net/sockopt.rs":"21d269c34992643d403d50e3071b646cd9ed05dc9bdc53fe2f795bb5df43fa60","src/net/types.rs":"bd3ee0cdb102e8cd1f2e0434639084b599a10561fc7f2aaa226d44bf892cef63","src/net/wsa.rs":"29856e6d0108be6b719f6ef973c5396e48ddd58ecd0c2db9ca3e2e0ba4eccb5b","src/param/auxv.rs":"8655993d7d480f340d8fa3efeb35135e0107510f6c3cfb160a9f6dc00ef577aa","src/param/init.rs":"a31c0e5cea61a1a999767fe74f87c0d59eeb6bce66578b842fe0e0c32be27a55","src/param/mod.rs":"c514216b96d9520c9ffc5662c97b24f1f36f56fe1f5f3c9f64175c8b35577288","src/path/arg.rs":"c0f0a7c2fe37192cf6f7b35ae0e17620b863b31e55efb7b2d9f31b5def56a749","src/path/dec_int.rs":"8ff8e14442c46f8e7a9b80d73973619b4271549b9defd538479bf8c2d93aa72e","src/path/mod.rs":"8355324af7eaa91dce30fc4ebdd161691f9d8bf7a61bde1dde27a1bcca15369b","src/pid.rs":"f1c486000c5b1311b2d720cee88f089c17ef9a171709673dd06e6f35f4ff98a3","src/pipe.rs":"9f269090dd0588dc8d3feba4f4a78b61891bce91d3c9b64cdbad9251b06a9e11","src/prctl.rs":"19aa584895874ea48b9bbe1bf695b81257b0281df64dfdd91e1b4bfa298661b7","src/process/chdir.rs":"911216459aa429fe9f125f1357d6900b43b0007835b85c719875d00f79a74664","src/process/chroot.rs":"2b5f6124eb19f26ad2705174f7ad50cdc0a5d15abd59ffcf55421228d82130b4","src/process/exit.rs":"48de66e5504a00cb375d8f415ce63b6225a3f5204268d40726a7d0fbba43f587","src/process/id.rs":"e0a26da426962dd5898fbc05700083a68399d5b669fd5f4afaac7b282e0178fd","src/process/ioctl.rs":"23ad0285671e8d7ca71a63c50655dbf732ccea8af11d754a0558e0236db37e76","src/process/kill.rs":"96d5ce432c19cf2b600d5248c681c117abf53ae94bbfca7e75ac533a40e3968e","src/process/membarrier.rs":"1c4c39b359d1d0e9bbe16352eedfca9278d9ef298ade8ec00e998617bbcbfed8","src/process/mod.rs":"4fda62909afcb081281bd9a8eaf770dc3dfc2111013231ae23b0a1e101582f48","src/process/pidfd.rs":"150413a9cc550ffc432b3279a368223fa9577544ef29e45edeff3b79ae316cab","src/process/pidfd_getfd.rs":"74c778b872be0b800870e4633606461fdc8493b259031e35f8f558768d960cc2","src/process/prctl.rs":"0130d05362a17a9282f3391189095e1f4f51fb56d7a5205906a0011842df4576","src/process/priority.rs":"f135482e71ea8aa0daf92b9f238051178a4c904070fa8409622f94155df3c544","src/process/procctl.rs":"75e9f7e5c66e6563aff133ff99b3a35c80a9f0a616d318a93a65be39ebc191ea","src/process/rlimit.rs":"10b79de3ced0e64059a94c879742d46a35a6176c776d8eed75031d5e6340283d","src/process/sched.rs":"6c976daf5b5a30aa9a33456d23a46f6f4d257642963eb142b55e13a53aec4c56","src/process/sched_yield.rs":"6565faa3928b66ddc74a65e893e15edfa4b9be4f7e5f5f68527501a7f6bc3350","src/process/umask.rs":"1a0f31a842303c978e3f05ec191e2b5e96104c09c6596473b42b1fac34898a50","src/process/wait.rs":"f9c73dde2a66dfbe448501f039396dd26c5d678e4f8cb61c1f78014b7b49fcd3","src/procfs.rs":"4d4812a8db6897dabc33269ff59bf6d7192a65be977e879613704e29a8b73505","src/pty.rs":"652c412e7280d0344b3f9bfe376c106a7f1b42b898b7af344e6e72da268e2bf0","src/rand/getrandom.rs":"0a5320eaf5dd4c6d9b1252c41ca286b40a9ce813eb469c89dba41e6258612740","src/rand/mod.rs":"e1fb7542f1958fe77673aa628bd92fef1b9addf79ba23df2398d1231cb61c148","src/runtime.rs":"958cdf1567c5758c73c197fc36d1feffb414a22a76a7a287afc84f330f2d2279","src/shm.rs":"b96fe8a05ee5d4536464a8843a776d43a938abaf22c772fc35b5373d95644a8d","src/signal.rs":"a294b49d487dafaa42e534f8b1d93e87bec135087676b2ba2ef865cf2fccdaf2","src/static_assertions.rs":"504cf66f0d5b8e335be02f9ae8b0a355abc98c2c82eec0098bdf0988e662e260","src/stdio.rs":"6f78cbc0d102eff9354fa1fdfd1b63a45ea159d0a9ac5d25ecf703383b847b55","src/system.rs":"e048eccf6f60ff49fa3312e7a01a9f641787c195c4db745f1f5a2f2c443d7e91","src/termios/ioctl.rs":"a1ac967f7811a482f8bb53847c37c8359f518cd26da9df7b816ba678a0139623","src/termios/mod.rs":"b44b7caa60b6f458657ed58a0e0eca41bb4e6d6be4b0f042bbb8ab7056cebe4b","src/termios/tc.rs":"9af4eb264bf23bc0b0ad1707fcca687020b20f0775a28209b237fbb72089d991","src/termios/tty.rs":"35a5fc2d26501e0e6dde1a755eeccf7b4f3b4702c5bac30e0953220808ef7034","src/termios/types.rs":"b5671eedf541754c54f680002bafed1adbabce172d09d7c4d31fdf9313ca18c8","src/thread/clock.rs":"83681fa00d5efa15c5b7cba10015a0c99d855c4ac78714e3989d91c999e5ba80","src/thread/futex.rs":"985f9a0dce1e2a4892ae7f26bd1bf119ceae3f9fa6b4707e166624fc1cee76d4","src/thread/id.rs":"bc4cf152388962303ea835b97acd64e499ecd15f94eaf6f133ff5a1a582377ba","src/thread/libcap.rs":"4c51b7df566d38dd0f85f81ef53279a745a39f0f4e1154791fd38438e2ca7db1","src/thread/mod.rs":"09b19f25ed1aa65f6605ed7deccc4bd945e3ae872a60275787f44944a73edf3f","src/thread/prctl.rs":"ebc89b731eb8fd1a8f82a50dbba849061476a4537bba8702b29db657d5287ffa","src/thread/setns.rs":"ea9142b1f3a5b3f329683be185f960c50e5c1636149e91fbf59e88a897fc607d","src/time/clock.rs":"e59a29f1bed8c31c3d5b6fad60f2d4fa6cab8dd8e86148bb3693a5e3a1ce735f","src/time/mod.rs":"43afee938c80d124d04d4ba190c03f4d21d1e3bfc154fff309211e4f6eabe940","src/time/timerfd.rs":"f17092b84553741aa2d2b44c6992b5d2c8c96cc2c2007fc9a2c6b2064485e53f","src/timespec.rs":"32a4d930cbc0f6dbd23153290db920671cf4ce65a4a127e176f897c1cde42d7d","src/ugid.rs":"6616c6e35b7e43aee5b150f1efae7a50711e0947943c9a96833dbe214ad9e85f","src/utils.rs":"9ae76f8a41d6cc350cdd58c9084b5c3a5a708eeecd769783debdbcbaef442182","src/weak.rs":"7e3169bc97e76fc4d52b040391a8df36b06536fc0f81cc6e8e71b951cb1fe54e"},"package":"70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustix/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/rustix/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustix/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "14a88ef008f2e69e10aa31b75dc191b07b412bca" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/rustix/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/rustix/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/rustix/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/rustix/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,250 @@ +[package] +name = "rustix" +version = "0.38.34" +authors = [ + "Dan Gohman ", + "Jakub Konka ", +] +description = "Safe Rust bindings to POSIX/Unix/Linux/Winsock-like syscalls" +documentation = "https://docs.rs/rustix" +license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" +repository = "https://github.com/bytecodealliance/rustix" +edition = "2021" +keywords = ["api", "file", "network", "safe", "syscall"] +categories = ["os::unix-apis", "date-and-time", "filesystem", "network-programming"] +include = ["src", "build.rs", "Cargo.toml", "COPYRIGHT", "LICENSE*", "/*.md", "benches"] +rust-version = "1.63" + +[dependencies] +bitflags = { version = "2.4.0", default-features = false } +itoa = { version = "1.0.1", default-features = false, optional = true } + +# Special dependencies used in rustc-dep-of-std mode. +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } +compiler_builtins = { version = '0.1.49', optional = true } + +# The procfs feature needs once_cell. +# With Rust 1.70.0, we can switch to `core::cell::OnceCell`. +[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] +once_cell = { version = "1.5.2", optional = true } + +# Dependencies for platforms where linux_raw is supported, in addition to libc: +# +# On Linux on selected architectures, the linux_raw backend is supported, in +# addition to the libc backend. The linux_raw backend is used by default. The +# libc backend can be selected via adding `--cfg=rustix_use_libc` to +# `RUSTFLAGS` or enabling the `use-libc` cargo feature. +[target.'cfg(all(not(rustix_use_libc), not(miri), target_os = "linux", target_endian = "little", any(target_arch = "arm", all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "riscv64", all(rustix_use_experimental_asm, target_arch = "powerpc64"), all(rustix_use_experimental_asm, target_arch = "mips"), all(rustix_use_experimental_asm, target_arch = "mips32r6"), all(rustix_use_experimental_asm, target_arch = "mips64"), all(rustix_use_experimental_asm, target_arch = "mips64r6"), target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64"))))'.dependencies] +linux-raw-sys = { version = "0.4.12", default-features = false, features = ["general", "errno", "ioctl", "no_std", "elf"] } +libc_errno = { package = "errno", version = "0.3.8", default-features = false, optional = true } +libc = { version = "0.2.153", default-features = false, optional = true } + +# Dependencies for platforms where only libc is supported: +# +# On all other Unix-family platforms, and under Miri, we always use the libc +# backend, so enable its dependencies unconditionally. +[target.'cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = "linux", target_endian = "little", any(target_arch = "arm", all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "riscv64", all(rustix_use_experimental_asm, target_arch = "powerpc64"), all(rustix_use_experimental_asm, target_arch = "mips"), all(rustix_use_experimental_asm, target_arch = "mips32r6"), all(rustix_use_experimental_asm, target_arch = "mips64"), all(rustix_use_experimental_asm, target_arch = "mips64r6"), target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64")))))))'.dependencies] +libc_errno = { package = "errno", version = "0.3.8", default-features = false } +libc = { version = "0.2.153", default-features = false } + +# Additional dependencies for Linux with the libc backend: +# +# Some syscalls do not have libc wrappers, such as in `io_uring`. For these, +# the libc backend uses the linux-raw-sys ABI and `libc::syscall`. +[target.'cfg(all(any(target_os = "android", target_os = "linux"), any(rustix_use_libc, miri, not(all(target_os = "linux", target_endian = "little", any(target_arch = "arm", all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "riscv64", all(rustix_use_experimental_asm, target_arch = "powerpc64"), all(rustix_use_experimental_asm, target_arch = "mips"), all(rustix_use_experimental_asm, target_arch = "mips32r6"), all(rustix_use_experimental_asm, target_arch = "mips64"), all(rustix_use_experimental_asm, target_arch = "mips64r6"), target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64")))))))'.dependencies] +linux-raw-sys = { version = "0.4.12", default-features = false, features = ["general", "ioctl", "no_std"] } + +# For the libc backend on Windows, use the Winsock API in windows-sys. +[target.'cfg(windows)'.dependencies.windows-sys] +version = "0.52.0" +features = [ + "Win32_Foundation", + "Win32_Networking_WinSock", + "Win32_NetworkManagement_IpHelper", + "Win32_System_Threading" +] + +# For the libc backend on Windows, also use the errno crate, which has Windows +# support. +[target.'cfg(windows)'.dependencies.libc_errno] +version = "0.3.8" +package = "errno" +default-features = false + +[dev-dependencies] +tempfile = "3.5.0" +libc = "0.2.153" +libc_errno = { package = "errno", version = "0.3.8", default-features = false } +serial_test = "2.0.0" +memoffset = "0.9.0" +flate2 = "1.0" +static_assertions = "1.1.0" + +[target.'cfg(all(criterion, not(any(target_os = "emscripten", target_os = "wasi"))))'.dev-dependencies] +criterion = "0.4" + +[target.'cfg(windows)'.dev-dependencies] +ctor = "0.2.0" + +# Add Criterion configuration, as described here: +# +[[bench]] +name = "mod" +harness = false + +[package.metadata.docs.rs] +features = ["all-apis"] +rustdoc-args = ["--cfg", "doc_cfg"] +targets = [ + "x86_64-unknown-linux-gnu", + "i686-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-openbsd", + "x86_64-unknown-netbsd", + "x86_64-unknown-dragonfly", + "x86_64-unknown-illumos", + "x86_64-unknown-redox", + "x86_64-unknown-haiku", + "wasm32-unknown-emscripten", + "wasm32-wasi", +] + +[features] + +# By default, use `std` and use libc for aux values. +# +# It turns out to be bizarrely awkward to obtain the aux values reliably and +# efficiently on Linux from anywhere other than libc. We can do it, but most +# users are better served by just using libc for this. +default = ["std", "use-libc-auxv"] + +# This enables use of std. Disabling this enables `#![no_std]`, and requires +# Rust 1.64 or newer. +std = ["bitflags/std", "alloc", "libc?/std", "libc_errno?/std", "libc-extra-traits"] + +# Enable this to request the libc backend. +use-libc = ["libc_errno", "libc", "libc-extra-traits"] + +# Enable `extra_traits` in libc types, to provide `Debug`, `Hash`, and other +# trait impls for libc types. +libc-extra-traits = ["libc?/extra_traits"] + +# Enable `rustix::event::*`. +event = [] + +# Enable `rustix::fs::*`. +fs = [] + +# Enable `rustix::io_uring::*` (on platforms that support it). +io_uring = ["event", "fs", "net", "linux-raw-sys/io_uring"] + +# Enable `rustix::mount::*`. +mount = [] + +# Enable `rustix::net::*`. +net = ["linux-raw-sys/net", "linux-raw-sys/netlink", "linux-raw-sys/if_ether", "linux-raw-sys/xdp"] + +# Enable `rustix::thread::*`. +thread = ["linux-raw-sys/prctl"] + +# Enable `rustix::process::*`. +process = ["linux-raw-sys/prctl"] + +# Enable `rustix::shm::*`. +shm = ["fs"] + +# Enable `rustix::time::*`. +time = [] + +# Enable `rustix::param::*`. +param = ["fs"] + +# Enable this to enable `rustix::io::proc_self_*` (on Linux) and `ttyname`. +procfs = ["once_cell", "itoa", "fs"] + +# Enable `rustix::pty::*`. +pty = ["itoa", "fs"] + +# Enable `rustix::termios::*`. +termios = [] + +# Enable `rustix::mm::*`. +mm = [] + +# Enable `rustix::pipe::*`. +pipe = [] + +# Enable `rustix::rand::*`. +rand = [] + +# Enable `rustix::stdio::*`. +stdio = [] + +# Enable `rustix::system::*`. +system = ["linux-raw-sys/system"] + +# Enable `rustix::runtime::*`. This API is undocumented and unstable and +# experimental and not intended for general-purpose use. +runtime = ["linux-raw-sys/prctl"] + +# Enable all API features. +all-apis = [ + "event", + "fs", + "io_uring", + "mm", + "mount", + "net", + "param", + "pipe", + "process", + "procfs", + "pty", + "rand", + "runtime", + "shm", + "stdio", + "system", + "termios", + "thread", + "time", +] + +# When using the linux_raw backend, should we use libc for reading the aux +# vectors, instead of reading them ourselves from /proc/self/auxv? +use-libc-auxv = [] + +# Enable "use-explicitly-provided-auxv" mode, with a public +# `rustix::param::init` function that must be called before anything else in +# rustix. This is unstable and experimental and not intended for +# general-purpose use. +use-explicitly-provided-auxv = [] + +# OS compatibility features + +# Optimize for Linux 4.11 or later +linux_4_11 = [] + +# Enable all optimizations for the latest Linux versions. +linux_latest = ["linux_4_11"] + +# Enable features which depend on the Rust global allocator, such as functions +# that return owned strings or `Vec`s. +alloc = [] + +# This is used in the port of std to rustix. This is experimental and not meant +# for regular use. +rustc-dep-of-std = [ + "dep:core", + "dep:alloc", + "dep:compiler_builtins", + "linux-raw-sys/rustc-dep-of-std", + "bitflags/rustc-dep-of-std", + "compiler_builtins?/rustc-dep-of-std", +] + +# Obsolete and deprecated. +cc = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ryu/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/ryu/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"3b77e9629ab0087ab9592d75fb5dd6f80c43f9b519c89522999bac2bb6d1fc9a","Cargo.toml":"ec13c54a057c6910f5e1d41bdce15f363fe67e45e0022dbd4f96c7660ff86f57","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"86f0a92cf076f4983f99926607ea272c9650a5996fa3921fc5ca5abceb0f18db","benches/bench.rs":"703521c8cb9c6959ee305776a9971d24754b6fff5c1737741be04f956a3692e8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"e32f3fa7e994ff704796e58e115c5258e94a79a184d1608864772f2f2f5274fc","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"f2612785ebe510c935b979dc5f66f6b8c818ca8a4cf0364ce1fe1d41fea39592","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"bbf15472f4299942312e80a992cbc2f47f85f17ed193f24084534434dbfb26e7","src/d2s_small_table.rs":"db3bbe4002d816785b0ee233c330f19fa7002f31dab47dc6f67b266996fe3ae4","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"cb96f61d8c6c6c941803a7b629f2bf835e1a20ad9d3e5d3454a30ed3391c3515","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"ebc4c922a1c421ce54beb485fd01726e68f5a27213ea369ebdf2b536398c0737","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"fa914ec63b3f86cbdaf7933d7c44e1bc1f93c1239a29a5f86934680a7e957570","src/pretty/mantissa.rs":"40cb00efe1c3fab559ab58389bd519d556548aa18fb261a90dd48138911d039b","src/pretty/mod.rs":"eb0a8c78019f55a1767943821340e8b1278455e0d88bb4f63f4bd3dde340e387","src/s2d.rs":"c804518a771654e3786bde2b776c56e94e198ce6d3fe1e4e5e2f2a9cb9e607e3","src/s2f.rs":"11d528931ce1a01a93f39efb3fe99fdc3041b41fefafb2efd6a338d2a12b628c","tests/common_test.rs":"599781a637d9b9756858aabfe5c38a0734a550debd3d94774f33792b7b3c8240","tests/d2s_intrinsics_test.rs":"15d11b70810bf04f33f8b185bf7f010a436a4edb47fa4648b1a036568c2c5d15","tests/d2s_table_test.rs":"819c39cc94e3462138d3be337d06e7334de126642d34bf1394e03d2df9c0c90c","tests/d2s_test.rs":"d72aaf37c76a4042ecc12b7d6faf844696016bb72bb20d142ecab3bd6c87e29f","tests/exhaustive.rs":"f475ed9008a2cd86ce95abb577a4b01e9fed23fc16f7e217ccffb3b834005fa0","tests/f2s_test.rs":"ad9e6fe46e712c488b876428c144c79bdff0349b41c57eee5506fc3c9c156624","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"75c3a1044881718db65e05f25c9f6e1d005392dddb2e8dafb799668bb6a9a5c3","tests/s2f_test.rs":"1ec06646cb65229bfe866ec913901a0d8d736668f30b812fc4b00136a43f5142"},"package":"e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"bd2241a7541481cbc5a4d7be7bf8ce89f63e272da1351b7c584cbb87920dd2e2",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"a0d72d0cda08feaca92f161253169ffd70039eaff5e48877a07f8c78bc996183","Cargo.lock":"3b77e9629ab0087ab9592d75fb5dd6f80c43f9b519c89522999bac2bb6d1fc9a","Cargo.toml":"ec13c54a057c6910f5e1d41bdce15f363fe67e45e0022dbd4f96c7660ff86f57","Cargo.toml.orig":"431a917ae747ffbd8746227c84e983f258bdc7a9113dcb3bbfa578b572388bc1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"86f0a92cf076f4983f99926607ea272c9650a5996fa3921fc5ca5abceb0f18db","benches/bench.rs":"703521c8cb9c6959ee305776a9971d24754b6fff5c1737741be04f956a3692e8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"e32f3fa7e994ff704796e58e115c5258e94a79a184d1608864772f2f2f5274fc","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"f2612785ebe510c935b979dc5f66f6b8c818ca8a4cf0364ce1fe1d41fea39592","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"bbf15472f4299942312e80a992cbc2f47f85f17ed193f24084534434dbfb26e7","src/d2s_small_table.rs":"db3bbe4002d816785b0ee233c330f19fa7002f31dab47dc6f67b266996fe3ae4","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"cb96f61d8c6c6c941803a7b629f2bf835e1a20ad9d3e5d3454a30ed3391c3515","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"ebc4c922a1c421ce54beb485fd01726e68f5a27213ea369ebdf2b536398c0737","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"fa914ec63b3f86cbdaf7933d7c44e1bc1f93c1239a29a5f86934680a7e957570","src/pretty/mantissa.rs":"40cb00efe1c3fab559ab58389bd519d556548aa18fb261a90dd48138911d039b","src/pretty/mod.rs":"eb0a8c78019f55a1767943821340e8b1278455e0d88bb4f63f4bd3dde340e387","src/s2d.rs":"c804518a771654e3786bde2b776c56e94e198ce6d3fe1e4e5e2f2a9cb9e607e3","src/s2f.rs":"11d528931ce1a01a93f39efb3fe99fdc3041b41fefafb2efd6a338d2a12b628c","tests/common_test.rs":"599781a637d9b9756858aabfe5c38a0734a550debd3d94774f33792b7b3c8240","tests/d2s_intrinsics_test.rs":"15d11b70810bf04f33f8b185bf7f010a436a4edb47fa4648b1a036568c2c5d15","tests/d2s_table_test.rs":"819c39cc94e3462138d3be337d06e7334de126642d34bf1394e03d2df9c0c90c","tests/d2s_test.rs":"d72aaf37c76a4042ecc12b7d6faf844696016bb72bb20d142ecab3bd6c87e29f","tests/exhaustive.rs":"f475ed9008a2cd86ce95abb577a4b01e9fed23fc16f7e217ccffb3b834005fa0","tests/f2s_test.rs":"ad9e6fe46e712c488b876428c144c79bdff0349b41c57eee5506fc3c9c156624","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"75c3a1044881718db65e05f25c9f6e1d005392dddb2e8dafb799668bb6a9a5c3","tests/s2f_test.rs":"1ec06646cb65229bfe866ec913901a0d8d736668f30b812fc4b00136a43f5142"},"package":"e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ryu/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/ryu/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ryu/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8eb9f1c80645c88ebc584d947e85d66a9c059cb0" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ryu/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/ryu/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ryu/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/ryu/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ryu/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,113 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + - run: cargo test --features small + - run: cargo build --tests --features no-panic --release + if: matrix.rust == 'nightly' + + msrv: + name: Rust 1.36.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.36.0 + - run: cargo build + - run: cargo build --features small + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests --benches -- -Dclippy::all -Dclippy::pedantic + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 + + fuzz: + name: Fuzz + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz check diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/ryu/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/ryu/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/ryu/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/ryu/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +[package] +name = "ryu" +version = "1.0.17" # don't forget to update html_root_url +authors = ["David Tolnay "] +categories = ["value-formatting", "no-std", "no-std::no-alloc"] +description = "Fast floating point to string conversion" +documentation = "https://docs.rs/ryu" +edition = "2018" +exclude = ["performance.png", "chart/**"] +keywords = ["float"] +license = "Apache-2.0 OR BSL-1.0" +repository = "https://github.com/dtolnay/ryu" +rust-version = "1.36" + +[features] +# Use smaller lookup tables. Instead of storing every required power of +# 5, only store every 26th entry, and compute intermediate values with a +# multiplication. This reduces the lookup table size by about 10x (only +# one case, and only f64) at the cost of some performance. +small = [] + +[dependencies] +no-panic = { version = "0.1", optional = true } + +[dev-dependencies] +num_cpus = "1.8" +rand = "0.8" +rand_xorshift = "0.3" + +[lib] +doc-scrape-examples = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"684e99cc5938e7e51e1c5808214f9125ccfe66efa6ca5392303a7ee5337e1294","Cargo.toml":"68899251551903e2e1ba03c927f12e4c19fc8a15e8bd3756610f53f5ec075b48","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"fb77f0a9c53e473abe5103c8632ef9f0f2874d4fb3f17cb2d8c661aab9cee9d7","README.md":"68d5a7beebf814cffaaf6fe5758984fd06554b3bb5a49b2e13fc101522909b91","examples/readme.rs":"c6b1b458a130e091b1465040184759f1cc7d4e8de8d9cb893def0107238c2964","src/lib.rs":"3fb8bba1227724954c01cf98ec984bcf49ee74624faa74eb1bcea9018682751c"},"package":"94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "scopeguard" -version = "1.2.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -name = "scopeguard" -version = "1.2.0" -authors = ["bluss"] -description = """ -A RAII scope guard that will run a given closure when it goes out of scope, -even if the code between panics (assuming unwinding panic). - -Defines the macros `defer!`, `defer_on_unwind!`, `defer_on_success!` as -shorthands for guards with one of the implemented strategies. -""" -documentation = "https://docs.rs/scopeguard/" -readme = "README.md" -keywords = [ - "scope-guard", - "defer", - "panic", - "unwind", -] -categories = [ - "rust-patterns", - "no-std", -] -license = "MIT OR Apache-2.0" -repository = "https://github.com/bluss/scopeguard" - -[package.metadata.release] -no-dev-version = true - -[features] -default = ["use_std"] -use_std = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/LICENSE-APACHE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -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 - - http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/LICENSE-MIT 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Copyright (c) 2016-2019 Ulrik Sverdrup "bluss" and scopeguard developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/README.md clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -# scopeguard - -Rust crate for a convenient RAII scope guard that will run a given closure when -it goes out of scope, even if the code between panics (assuming unwinding panic). - -The `defer!` macro and `guard` are `no_std` compatible (require only `core`), -but the on unwinding / not on unwinding strategies require linking to `std`. -By default, the `use_std` crate feature is enabled. Disable the default features -for `no_std` support. - -Please read the [API documentation here](https://docs.rs/scopeguard/). - -Minimum supported Rust version: 1.20 - -[![build_status](https://github.com/bluss/scopeguard/actions/workflows/ci.yaml/badge.svg)](https://github.com/bluss/scopeguard/actions/workflows/ci.yaml) -[![crates](https://img.shields.io/crates/v/scopeguard.svg)](https://crates.io/crates/scopeguard) - -## How to use - -```rs -#[macro_use(defer)] -extern crate scopeguard; - -use scopeguard::guard; - -fn f() { - defer! { - println!("Called at return or panic"); - } - panic!(); -} - -use std::fs::File; -use std::io::Write; - -fn g() { - let f = File::create("newfile.txt").unwrap(); - let mut file = guard(f, |f| { - // write file at return or panic - let _ = f.sync_all(); - }); - // access the file through the scope guard itself - file.write_all(b"test me\n").unwrap(); -} -``` - -## Recent Changes - -- 1.2.0 - - - Use ManuallyDrop instead of mem::forget in into_inner. (by @willtunnels) - - Warn if the guard is not assigned to a variable and is dropped immediately - instead of at the scope's end. (by @sergey-v-galtsev) - -- 1.1.0 - - - Change macros (`defer!`, `defer_on_success!` and `defer_on_unwind!`) - to accept statements. (by @konsumlamm) - -- 1.0.0 - - - Change the closure type from `FnMut(&mut T)` to `FnOnce(T)`: - Passing the inner value by value instead of a mutable reference is a - breaking change, but allows the guard closure to consume it. (by @tormol) - - - Add `defer_on_success!`, `guard_on_success()` and `OnSuccess` - strategy, which triggers when scope is exited *without* panic. It's the - opposite to `defer_on_unwind!` / `guard_on_unwind()` / `OnUnwind`. - - - Add `ScopeGuard::into_inner()`, which "defuses" the guard and returns the - guarded value. (by @tormol) - - - Implement `Sync` for guards with non-`Sync` closures. - - - Require Rust 1.20 - -- 0.3.3 - - - Use `#[inline]` on a few more functions by @stjepang (#14) - - Add examples to crate documentation - -- 0.3.2 - - - Add crate categories - -- 0.3.1 - - - Add `defer_on_unwind!`, `Strategy` trait - - Rename `Guard` → `ScopeGuard` - - Add `ScopeGuard::with_strategy`. - - `ScopeGuard` now implements `Debug`. - - Require Rust 1.11 - -- 0.2.0 - - - Require Rust 1.6 - - Use `no_std` unconditionally - - No other changes - -- 0.1.2 - - - Add macro `defer!` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/examples/readme.rs clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/examples/readme.rs --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/examples/readme.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/examples/readme.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#[macro_use(defer)] -extern crate scopeguard; - -use scopeguard::guard; - -fn f() { - defer! { - println!("Called at return or panic"); - } - panic!(); -} - -use std::fs::File; -use std::io::Write; - -fn g() { - let f = File::create("newfile.txt").unwrap(); - let mut file = guard(f, |f| { - // write file at return or panic - let _ = f.sync_all(); - }); - // access the file through the scope guard itself - file.write_all(b"test me\n").unwrap(); -} - -fn main() { - f(); - g(); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/scopeguard/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/scopeguard/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,595 +0,0 @@ -#![cfg_attr(not(any(test, feature = "use_std")), no_std)] -#![doc(html_root_url = "https://docs.rs/scopeguard/1/")] - -//! A scope guard will run a given closure when it goes out of scope, -//! even if the code between panics. -//! (as long as panic doesn't abort) -//! -//! # Examples -//! -//! ## Hello World -//! -//! This example creates a scope guard with an example function: -//! -//! ``` -//! extern crate scopeguard; -//! -//! fn f() { -//! let _guard = scopeguard::guard((), |_| { -//! println!("Hello Scope Exit!"); -//! }); -//! -//! // rest of the code here. -//! -//! // Here, at the end of `_guard`'s scope, the guard's closure is called. -//! // It is also called if we exit this scope through unwinding instead. -//! } -//! # fn main() { -//! # f(); -//! # } -//! ``` -//! -//! ## `defer!` -//! -//! Use the `defer` macro to run an operation at scope exit, -//! either regular scope exit or during unwinding from a panic. -//! -//! ``` -//! #[macro_use(defer)] extern crate scopeguard; -//! -//! use std::cell::Cell; -//! -//! fn main() { -//! // use a cell to observe drops during and after the scope guard is active -//! let drop_counter = Cell::new(0); -//! { -//! // Create a scope guard using `defer!` for the current scope -//! defer! { -//! drop_counter.set(1 + drop_counter.get()); -//! } -//! -//! // Do regular operations here in the meantime. -//! -//! // Just before scope exit: it hasn't run yet. -//! assert_eq!(drop_counter.get(), 0); -//! -//! // The following scope end is where the defer closure is called -//! } -//! assert_eq!(drop_counter.get(), 1); -//! } -//! ``` -//! -//! ## Scope Guard with Value -//! -//! If the scope guard closure needs to access an outer value that is also -//! mutated outside of the scope guard, then you may want to use the scope guard -//! with a value. The guard works like a smart pointer, so the inner value can -//! be accessed by reference or by mutable reference. -//! -//! ### 1. The guard owns a file -//! -//! In this example, the scope guard owns a file and ensures pending writes are -//! synced at scope exit. -//! -//! ``` -//! extern crate scopeguard; -//! -//! use std::fs::*; -//! use std::io::{self, Write}; -//! # // Mock file so that we don't actually write a file -//! # struct MockFile; -//! # impl MockFile { -//! # fn create(_s: &str) -> io::Result { Ok(MockFile) } -//! # fn write_all(&self, _b: &[u8]) -> io::Result<()> { Ok(()) } -//! # fn sync_all(&self) -> io::Result<()> { Ok(()) } -//! # } -//! # use self::MockFile as File; -//! -//! fn try_main() -> io::Result<()> { -//! let f = File::create("newfile.txt")?; -//! let mut file = scopeguard::guard(f, |f| { -//! // ensure we flush file at return or panic -//! let _ = f.sync_all(); -//! }); -//! // Access the file through the scope guard itself -//! file.write_all(b"test me\n").map(|_| ()) -//! } -//! -//! fn main() { -//! try_main().unwrap(); -//! } -//! -//! ``` -//! -//! ### 2. The guard restores an invariant on scope exit -//! -//! ``` -//! extern crate scopeguard; -//! -//! use std::mem::ManuallyDrop; -//! use std::ptr; -//! -//! // This function, just for this example, takes the first element -//! // and inserts it into the assumed sorted tail of the vector. -//! // -//! // For optimization purposes we temporarily violate an invariant of the -//! // Vec, that it owns all of its elements. -//! // -//! // The safe approach is to use swap, which means two writes to memory, -//! // the optimization is to use a “hole” which uses only one write of memory -//! // for each position it moves. -//! // -//! // We *must* use a scope guard to run this code safely. We -//! // are running arbitrary user code (comparison operators) that may panic. -//! // The scope guard ensures we restore the invariant after successful -//! // exit or during unwinding from panic. -//! fn insertion_sort_first(v: &mut Vec) -//! where T: PartialOrd -//! { -//! struct Hole<'a, T: 'a> { -//! v: &'a mut Vec, -//! index: usize, -//! value: ManuallyDrop, -//! } -//! -//! unsafe { -//! // Create a moved-from location in the vector, a “hole”. -//! let value = ptr::read(&v[0]); -//! let mut hole = Hole { v: v, index: 0, value: ManuallyDrop::new(value) }; -//! -//! // Use a scope guard with a value. -//! // At scope exit, plug the hole so that the vector is fully -//! // initialized again. -//! // The scope guard owns the hole, but we can access it through the guard. -//! let mut hole_guard = scopeguard::guard(hole, |hole| { -//! // plug the hole in the vector with the value that was // taken out -//! let index = hole.index; -//! ptr::copy_nonoverlapping(&*hole.value, &mut hole.v[index], 1); -//! }); -//! -//! // run algorithm that moves the hole in the vector here -//! // move the hole until it's in a sorted position -//! for i in 1..hole_guard.v.len() { -//! if *hole_guard.value >= hole_guard.v[i] { -//! // move the element back and the hole forward -//! let index = hole_guard.index; -//! hole_guard.v.swap(index, index + 1); -//! hole_guard.index += 1; -//! } else { -//! break; -//! } -//! } -//! -//! // When the scope exits here, the Vec becomes whole again! -//! } -//! } -//! -//! fn main() { -//! let string = String::from; -//! let mut data = vec![string("c"), string("a"), string("b"), string("d")]; -//! insertion_sort_first(&mut data); -//! assert_eq!(data, vec!["a", "b", "c", "d"]); -//! } -//! -//! ``` -//! -//! -//! # Crate Features -//! -//! - `use_std` -//! + Enabled by default. Enables the `OnUnwind` and `OnSuccess` strategies. -//! + Disable to use `no_std`. -//! -//! # Rust Version -//! -//! This version of the crate requires Rust 1.20 or later. -//! -//! The scopeguard 1.x release series will use a carefully considered version -//! upgrade policy, where in a later 1.x version, we will raise the minimum -//! required Rust version. - -#[cfg(not(any(test, feature = "use_std")))] -extern crate core as std; - -use std::fmt; -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::ops::{Deref, DerefMut}; -use std::ptr; - -/// Controls in which cases the associated code should be run -pub trait Strategy { - /// Return `true` if the guard’s associated code should run - /// (in the context where this method is called). - fn should_run() -> bool; -} - -/// Always run on scope exit. -/// -/// “Always” run: on regular exit from a scope or on unwinding from a panic. -/// Can not run on abort, process exit, and other catastrophic events where -/// destructors don’t run. -#[derive(Debug)] -pub enum Always {} - -/// Run on scope exit through unwinding. -/// -/// Requires crate feature `use_std`. -#[cfg(feature = "use_std")] -#[derive(Debug)] -pub enum OnUnwind {} - -/// Run on regular scope exit, when not unwinding. -/// -/// Requires crate feature `use_std`. -#[cfg(feature = "use_std")] -#[derive(Debug)] -pub enum OnSuccess {} - -impl Strategy for Always { - #[inline(always)] - fn should_run() -> bool { - true - } -} - -#[cfg(feature = "use_std")] -impl Strategy for OnUnwind { - #[inline] - fn should_run() -> bool { - std::thread::panicking() - } -} - -#[cfg(feature = "use_std")] -impl Strategy for OnSuccess { - #[inline] - fn should_run() -> bool { - !std::thread::panicking() - } -} - -/// Macro to create a `ScopeGuard` (always run). -/// -/// The macro takes statements, which are the body of a closure -/// that will run when the scope is exited. -#[macro_export] -macro_rules! defer { - ($($t:tt)*) => { - let _guard = $crate::guard((), |()| { $($t)* }); - }; -} - -/// Macro to create a `ScopeGuard` (run on successful scope exit). -/// -/// The macro takes statements, which are the body of a closure -/// that will run when the scope is exited. -/// -/// Requires crate feature `use_std`. -#[cfg(feature = "use_std")] -#[macro_export] -macro_rules! defer_on_success { - ($($t:tt)*) => { - let _guard = $crate::guard_on_success((), |()| { $($t)* }); - }; -} - -/// Macro to create a `ScopeGuard` (run on unwinding from panic). -/// -/// The macro takes statements, which are the body of a closure -/// that will run when the scope is exited. -/// -/// Requires crate feature `use_std`. -#[cfg(feature = "use_std")] -#[macro_export] -macro_rules! defer_on_unwind { - ($($t:tt)*) => { - let _guard = $crate::guard_on_unwind((), |()| { $($t)* }); - }; -} - -/// `ScopeGuard` is a scope guard that may own a protected value. -/// -/// If you place a guard in a local variable, the closure can -/// run regardless how you leave the scope — through regular return or panic -/// (except if panic or other code aborts; so as long as destructors run). -/// It is run only once. -/// -/// The `S` parameter for [`Strategy`](trait.Strategy.html) determines if -/// the closure actually runs. -/// -/// The guard's closure will be called with the held value in the destructor. -/// -/// The `ScopeGuard` implements `Deref` so that you can access the inner value. -pub struct ScopeGuard -where - F: FnOnce(T), - S: Strategy, -{ - value: ManuallyDrop, - dropfn: ManuallyDrop, - // fn(S) -> S is used, so that the S is not taken into account for auto traits. - strategy: PhantomData S>, -} - -impl ScopeGuard -where - F: FnOnce(T), - S: Strategy, -{ - /// Create a `ScopeGuard` that owns `v` (accessible through deref) and calls - /// `dropfn` when its destructor runs. - /// - /// The `Strategy` decides whether the scope guard's closure should run. - #[inline] - #[must_use] - pub fn with_strategy(v: T, dropfn: F) -> ScopeGuard { - ScopeGuard { - value: ManuallyDrop::new(v), - dropfn: ManuallyDrop::new(dropfn), - strategy: PhantomData, - } - } - - /// “Defuse” the guard and extract the value without calling the closure. - /// - /// ``` - /// extern crate scopeguard; - /// - /// use scopeguard::{guard, ScopeGuard}; - /// - /// fn conditional() -> bool { true } - /// - /// fn main() { - /// let mut guard = guard(Vec::new(), |mut v| v.clear()); - /// guard.push(1); - /// - /// if conditional() { - /// // a condition maybe makes us decide to - /// // “defuse” the guard and get back its inner parts - /// let value = ScopeGuard::into_inner(guard); - /// } else { - /// // guard still exists in this branch - /// } - /// } - /// ``` - #[inline] - pub fn into_inner(guard: Self) -> T { - // Cannot move out of `Drop`-implementing types, - // so `ptr::read` the value and forget the guard. - let mut guard = ManuallyDrop::new(guard); - unsafe { - let value = ptr::read(&*guard.value); - // Drop the closure after `value` has been read, so that if the - // closure's `drop` function panics, unwinding still tries to drop - // `value`. - ManuallyDrop::drop(&mut guard.dropfn); - value - } - } -} - -/// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`. -#[inline] -#[must_use] -pub fn guard(v: T, dropfn: F) -> ScopeGuard -where - F: FnOnce(T), -{ - ScopeGuard::with_strategy(v, dropfn) -} - -/// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`. -/// -/// Requires crate feature `use_std`. -#[cfg(feature = "use_std")] -#[inline] -#[must_use] -pub fn guard_on_success(v: T, dropfn: F) -> ScopeGuard -where - F: FnOnce(T), -{ - ScopeGuard::with_strategy(v, dropfn) -} - -/// Create a new `ScopeGuard` owning `v` and with deferred closure `dropfn`. -/// -/// Requires crate feature `use_std`. -/// -/// ## Examples -/// -/// For performance reasons, or to emulate “only run guard on unwind” in -/// no-std environments, we can also use the default guard and simply manually -/// defuse it at the end of scope like the following example. (The performance -/// reason would be if the [`OnUnwind`]'s call to [std::thread::panicking()] is -/// an issue.) -/// -/// ``` -/// extern crate scopeguard; -/// -/// use scopeguard::ScopeGuard; -/// # fn main() { -/// { -/// let guard = scopeguard::guard((), |_| {}); -/// -/// // rest of the code here -/// -/// // we reached the end of scope without unwinding - defuse it -/// ScopeGuard::into_inner(guard); -/// } -/// # } -/// ``` -#[cfg(feature = "use_std")] -#[inline] -#[must_use] -pub fn guard_on_unwind(v: T, dropfn: F) -> ScopeGuard -where - F: FnOnce(T), -{ - ScopeGuard::with_strategy(v, dropfn) -} - -// ScopeGuard can be Sync even if F isn't because the closure is -// not accessible from references. -// The guard does not store any instance of S, so it is also irrelevant. -unsafe impl Sync for ScopeGuard -where - T: Sync, - F: FnOnce(T), - S: Strategy, -{ -} - -impl Deref for ScopeGuard -where - F: FnOnce(T), - S: Strategy, -{ - type Target = T; - - fn deref(&self) -> &T { - &*self.value - } -} - -impl DerefMut for ScopeGuard -where - F: FnOnce(T), - S: Strategy, -{ - fn deref_mut(&mut self) -> &mut T { - &mut *self.value - } -} - -impl Drop for ScopeGuard -where - F: FnOnce(T), - S: Strategy, -{ - fn drop(&mut self) { - // This is OK because the fields are `ManuallyDrop`s - // which will not be dropped by the compiler. - let (value, dropfn) = unsafe { (ptr::read(&*self.value), ptr::read(&*self.dropfn)) }; - if S::should_run() { - dropfn(value); - } - } -} - -impl fmt::Debug for ScopeGuard -where - T: fmt::Debug, - F: FnOnce(T), - S: Strategy, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct(stringify!(ScopeGuard)) - .field("value", &*self.value) - .finish() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::cell::Cell; - use std::panic::catch_unwind; - use std::panic::AssertUnwindSafe; - - #[test] - fn test_defer() { - let drops = Cell::new(0); - defer!(drops.set(1000)); - assert_eq!(drops.get(), 0); - } - - #[cfg(feature = "use_std")] - #[test] - fn test_defer_success_1() { - let drops = Cell::new(0); - { - defer_on_success!(drops.set(1)); - assert_eq!(drops.get(), 0); - } - assert_eq!(drops.get(), 1); - } - - #[cfg(feature = "use_std")] - #[test] - fn test_defer_success_2() { - let drops = Cell::new(0); - let _ = catch_unwind(AssertUnwindSafe(|| { - defer_on_success!(drops.set(1)); - panic!("failure") - })); - assert_eq!(drops.get(), 0); - } - - #[cfg(feature = "use_std")] - #[test] - fn test_defer_unwind_1() { - let drops = Cell::new(0); - let _ = catch_unwind(AssertUnwindSafe(|| { - defer_on_unwind!(drops.set(1)); - assert_eq!(drops.get(), 0); - panic!("failure") - })); - assert_eq!(drops.get(), 1); - } - - #[cfg(feature = "use_std")] - #[test] - fn test_defer_unwind_2() { - let drops = Cell::new(0); - { - defer_on_unwind!(drops.set(1)); - } - assert_eq!(drops.get(), 0); - } - - #[test] - fn test_only_dropped_by_closure_when_run() { - let value_drops = Cell::new(0); - let value = guard((), |()| value_drops.set(1 + value_drops.get())); - let closure_drops = Cell::new(0); - let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get())); - assert_eq!(value_drops.get(), 0); - assert_eq!(closure_drops.get(), 0); - drop(guard); - assert_eq!(value_drops.get(), 1); - assert_eq!(closure_drops.get(), 1); - } - - #[cfg(feature = "use_std")] - #[test] - fn test_dropped_once_when_not_run() { - let value_drops = Cell::new(0); - let value = guard((), |()| value_drops.set(1 + value_drops.get())); - let captured_drops = Cell::new(0); - let captured = guard((), |()| captured_drops.set(1 + captured_drops.get())); - let closure_drops = Cell::new(0); - let guard = guard_on_unwind(value, |value| { - drop(value); - drop(captured); - closure_drops.set(1 + closure_drops.get()) - }); - assert_eq!(value_drops.get(), 0); - assert_eq!(captured_drops.get(), 0); - assert_eq!(closure_drops.get(), 0); - drop(guard); - assert_eq!(value_drops.get(), 1); - assert_eq!(captured_drops.get(), 1); - assert_eq!(closure_drops.get(), 0); - } - - #[test] - fn test_into_inner() { - let dropped = Cell::new(false); - let value = guard(42, |_| dropped.set(true)); - let guard = guard(value, |_| dropped.set(true)); - let inner = ScopeGuard::into_inner(guard); - assert_eq!(dropped.get(), false); - assert_eq!(*inner, 42); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"b170a74720ee0374b2ccddca224b10b66352541307ddde5d05fadd5c55394976","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","build.rs":"56b4f43d4061c03fbdd4f6325f30439686b12679bace304223d30c03632a925e","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/de/format.rs":"c85071b016df643b161859682d21ce34fa0ebf2a3bdbeeea69859da48f5d934f","src/de/ignored_any.rs":"6480f2b2a83dc4764d01b2eec7309729eef2492eede2e5ee98d23a60b05198eb","src/de/impls.rs":"cd2781405d8f4568701a701e6b9946e5956eb201571118c8a49038928477779a","src/de/mod.rs":"e6250b9d385593a04ad984e7906acadf50cc8e6f5554f6ac0ed18af75512e57a","src/de/seed.rs":"045d890712a04eb33ffc5a021e5d948a63c89402b8ffeea749df2171b7484f8f","src/de/size_hint.rs":"fff83dc39d30e75e8e611991f9c5399188a1aad23a6462dbca2c8b62655cfedb","src/de/value.rs":"0fd511a288c20a1b768718f4baadf9c7d4146d276af6a71ba1d0f7679b28644a","src/integer128.rs":"29ef30b7d94507b34807090e68173767cdc7aff62edccd38affe69e75338dddc","src/lib.rs":"c8d451cfdd127bf606f42cd09e1df775f539dfbd95d0bf2aefb6a80841c85200","src/macros.rs":"0d4b392ed6fe529fda2c5439c8547fe9717e64f528bfd01f633bb725f98b53cd","src/private/de.rs":"9255ecf2d5c52f0f52b4e0dbf85bdd8c140bc2c1ac96086ee395589e0521aeb4","src/private/doc.rs":"b222decb40321190155209e1b8a5a52e3adfaa470047e379e664b71e0320655a","src/private/mod.rs":"b8f0c348621d91dd9da3db83d8877e70bc61ad0a2dc2d6fb57c6fc2c2cbafa26","src/private/ser.rs":"73577607e779e1b42713c51b9bc7136f99daccf473b4a641c99ceebe46708d47","src/ser/fmt.rs":"d1cfd9623605413e45a23ef778d97f0ac4da4adaed23739f1f9d7414b30e384b","src/ser/impls.rs":"0eebc159f7d3962c46c323e456afb679747ff57563e796c5fd92c64ed074ae70","src/ser/impossible.rs":"5c325da8e0370ab22abe1e15d8af1dc7a1707b127508f61e720cd7f0caa80593","src/ser/mod.rs":"a92d4ce0a6c68eb22a24a61574a5d2e9b0b463b284ff08e62298b8f7ae1a7464","src/std_error.rs":"25a07149e2e468747ffa5a58051c7f93d7b3c0fa0372f012a96c97ec8ab03b97"},"package":"ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"c9f5b12ad737f5f11be5a6909bc293a73ead2b784678d9ffe3499f325809934e","Cargo.toml":"b170a74720ee0374b2ccddca224b10b66352541307ddde5d05fadd5c55394976","Cargo.toml.orig":"d563f2b9f248519eb7b3779e06d22889ec9a2611173db741d250f33e55d0a7b4","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","build.rs":"56b4f43d4061c03fbdd4f6325f30439686b12679bace304223d30c03632a925e","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/de/format.rs":"c85071b016df643b161859682d21ce34fa0ebf2a3bdbeeea69859da48f5d934f","src/de/ignored_any.rs":"6480f2b2a83dc4764d01b2eec7309729eef2492eede2e5ee98d23a60b05198eb","src/de/impls.rs":"cd2781405d8f4568701a701e6b9946e5956eb201571118c8a49038928477779a","src/de/mod.rs":"e6250b9d385593a04ad984e7906acadf50cc8e6f5554f6ac0ed18af75512e57a","src/de/seed.rs":"045d890712a04eb33ffc5a021e5d948a63c89402b8ffeea749df2171b7484f8f","src/de/size_hint.rs":"fff83dc39d30e75e8e611991f9c5399188a1aad23a6462dbca2c8b62655cfedb","src/de/value.rs":"0fd511a288c20a1b768718f4baadf9c7d4146d276af6a71ba1d0f7679b28644a","src/integer128.rs":"29ef30b7d94507b34807090e68173767cdc7aff62edccd38affe69e75338dddc","src/lib.rs":"c8d451cfdd127bf606f42cd09e1df775f539dfbd95d0bf2aefb6a80841c85200","src/macros.rs":"0d4b392ed6fe529fda2c5439c8547fe9717e64f528bfd01f633bb725f98b53cd","src/private/de.rs":"9255ecf2d5c52f0f52b4e0dbf85bdd8c140bc2c1ac96086ee395589e0521aeb4","src/private/doc.rs":"b222decb40321190155209e1b8a5a52e3adfaa470047e379e664b71e0320655a","src/private/mod.rs":"b8f0c348621d91dd9da3db83d8877e70bc61ad0a2dc2d6fb57c6fc2c2cbafa26","src/private/ser.rs":"73577607e779e1b42713c51b9bc7136f99daccf473b4a641c99ceebe46708d47","src/ser/fmt.rs":"d1cfd9623605413e45a23ef778d97f0ac4da4adaed23739f1f9d7414b30e384b","src/ser/impls.rs":"0eebc159f7d3962c46c323e456afb679747ff57563e796c5fd92c64ed074ae70","src/ser/impossible.rs":"5c325da8e0370ab22abe1e15d8af1dc7a1707b127508f61e720cd7f0caa80593","src/ser/mod.rs":"a92d4ce0a6c68eb22a24a61574a5d2e9b0b463b284ff08e62298b8f7ae1a7464","src/std_error.rs":"25a07149e2e468747ffa5a58051c7f93d7b3c0fa0372f012a96c97ec8ab03b97"},"package":"ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "cc865ac5236c094275b10bff4fa41e561b3e359f" + }, + "path_in_vcs": "serde" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/serde/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/serde/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,69 @@ +[package] +name = "serde" +version = "1.0.200" +authors = ["Erick Tryzelaar ", "David Tolnay "] +build = "build.rs" +categories = ["encoding", "no-std", "no-std::no-alloc"] +description = "A generic serialization/deserialization framework" +documentation = "https://docs.rs/serde" +edition = "2018" +homepage = "https://serde.rs" +keywords = ["serde", "serialization", "no_std"] +license = "MIT OR Apache-2.0" +readme = "crates-io.md" +repository = "https://github.com/serde-rs/serde" +rust-version = "1.31" + +[dependencies] +serde_derive = { version = "1", optional = true, path = "../serde_derive" } + +[dev-dependencies] +serde_derive = { version = "1", path = "../serde_derive" } + +[lib] +doc-scrape-examples = false + +[package.metadata.playground] +features = ["derive", "rc"] + +[package.metadata.docs.rs] +features = ["derive", "rc", "unstable"] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] + +# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's +# version in lockstep with serde's, even if someone depends on the two crates +# separately with serde's "derive" feature disabled. Every serde_derive release +# is compatible with exactly one serde release because the generated code +# involves nonpublic APIs which are not bound by semver. +[target.'cfg(any())'.dependencies] +serde_derive = { version = "=1.0.200", path = "../serde_derive" } + + +### FEATURES ################################################################# + +[features] +default = ["std"] + +# Provide derive(Serialize, Deserialize) macros. +derive = ["serde_derive"] + +# Provide impls for common standard library types like Vec and HashMap. +# Requires a dependency on the Rust standard library. +std = [] + +# Provide impls for types that require unstable functionality. For tracking and +# discussion of unstable functionality please refer to this issue: +# +# https://github.com/serde-rs/serde/issues/812 +unstable = [] + +# Provide impls for types in the Rust core allocation and collections library +# including String, Box, Vec, and Cow. This is a subset of std but may +# be enabled without depending on all of std. +alloc = [] + +# Opt into impls for Rc and Arc. Serializing and deserializing these types +# does not preserve identity and may result in multiple copies of the same data. +# Be sure that this is what you want before enabling this feature. +rc = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"416528b93037fa61680b41abbc5c30fb74cde9b611d18c17ad4a9afd9daea154","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/bound.rs":"6c5c20785ac95af9480f8d0de35a7e844cc36a16012f6468db148acd03cb15c2","src/de.rs":"c221ab2b94a5d80dccff74a37f3448b3d695656552b452595dc289c73b12fb2b","src/dummy.rs":"9533dfee23f20d92ea75734c739022820c2787ded0d54f459feacdeb770ec912","src/fragment.rs":"6757cb4c3131d4300f093572efc273c4ab5a20e3e1efb54a311dcfa52d0bd6eb","src/internals/ast.rs":"7dc997e4090033bbd1d0bdd870e8bb87b096b7f66cfd02047f6b85ebdd569b12","src/internals/attr.rs":"6584c0a02de0d17993877303f3cc2c1bccf235257632220421f98082d82d387a","src/internals/case.rs":"10c8dda2b32d8c6c6b63cf09cdc63d02375af7e95ecefe8fecb34f93b65191bb","src/internals/check.rs":"d842eb9912fd29311060b67f3bc62c438eb7b5d86093355acb4de7eee02a0ef8","src/internals/ctxt.rs":"83a4e6fbe0e439d578478883594407e03f2f340541be479bdf0b04a202633a37","src/internals/mod.rs":"ed021ca635c18132a0e5c3d90f21b7f65def0a61e946421a30200b5b9ab6ad43","src/internals/receiver.rs":"fe8a480669511b5edcfe71f5dd290cf72ccec54c9016ec85f2ac59dce538077f","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"d619e88caa3c7a09b03014257f2b349ee922290062d9b97b4dd19d0e64532690","src/lib.rs":"423ee75604708f1b792f9396f7618a9b7b3a1690a07883f850e316f6f1a07146","src/pretend.rs":"7facc10a5b805564dd95735ae11118ec17ca6adcc49a59764e7c920e27b9fc4a","src/ser.rs":"a5638fa1b42b2a0d23cc12649f9180d4132f4cb7cf9edace1a1caed483f609e9","src/this.rs":"87818dc80cbb521b51938a653d09daf10aafc220bb10425948de82ad670fcb85"},"package":"856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f3bc0f112ff84d04e168f8a088c8a1cdae7bc3a435357d4581f082520e03436f","Cargo.toml":"416528b93037fa61680b41abbc5c30fb74cde9b611d18c17ad4a9afd9daea154","Cargo.toml.orig":"cfb62da45af613b82c93da8e04d905c911d5bdff2ca14e5cb244554a131acae3","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"731c044fc5f98b37a89e9049c9214267db98763309cb63146b45c029640f82a3","crates-io.md":"56e988ac4944c45f5bf5051e3827892ed8fb817853d99d9df1fff6621108e270","src/bound.rs":"6c5c20785ac95af9480f8d0de35a7e844cc36a16012f6468db148acd03cb15c2","src/de.rs":"c221ab2b94a5d80dccff74a37f3448b3d695656552b452595dc289c73b12fb2b","src/dummy.rs":"9533dfee23f20d92ea75734c739022820c2787ded0d54f459feacdeb770ec912","src/fragment.rs":"6757cb4c3131d4300f093572efc273c4ab5a20e3e1efb54a311dcfa52d0bd6eb","src/internals/ast.rs":"7dc997e4090033bbd1d0bdd870e8bb87b096b7f66cfd02047f6b85ebdd569b12","src/internals/attr.rs":"6584c0a02de0d17993877303f3cc2c1bccf235257632220421f98082d82d387a","src/internals/case.rs":"10c8dda2b32d8c6c6b63cf09cdc63d02375af7e95ecefe8fecb34f93b65191bb","src/internals/check.rs":"d842eb9912fd29311060b67f3bc62c438eb7b5d86093355acb4de7eee02a0ef8","src/internals/ctxt.rs":"83a4e6fbe0e439d578478883594407e03f2f340541be479bdf0b04a202633a37","src/internals/mod.rs":"ed021ca635c18132a0e5c3d90f21b7f65def0a61e946421a30200b5b9ab6ad43","src/internals/receiver.rs":"fe8a480669511b5edcfe71f5dd290cf72ccec54c9016ec85f2ac59dce538077f","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"d619e88caa3c7a09b03014257f2b349ee922290062d9b97b4dd19d0e64532690","src/lib.rs":"423ee75604708f1b792f9396f7618a9b7b3a1690a07883f850e316f6f1a07146","src/pretend.rs":"7facc10a5b805564dd95735ae11118ec17ca6adcc49a59764e7c920e27b9fc4a","src/ser.rs":"a5638fa1b42b2a0d23cc12649f9180d4132f4cb7cf9edace1a1caed483f609e9","src/this.rs":"87818dc80cbb521b51938a653d09daf10aafc220bb10425948de82ad670fcb85"},"package":"856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "cc865ac5236c094275b10bff4fa41e561b3e359f" + }, + "path_in_vcs": "serde_derive" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/serde_derive/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_derive/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +name = "serde_derive" +version = "1.0.200" +authors = ["Erick Tryzelaar ", "David Tolnay "] +categories = ["no-std", "no-std::no-alloc"] +description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" +documentation = "https://serde.rs/derive.html" +edition = "2015" +homepage = "https://serde.rs" +keywords = ["serde", "serialization", "no_std", "derive"] +license = "MIT OR Apache-2.0" +readme = "crates-io.md" +repository = "https://github.com/serde-rs/serde" +rust-version = "1.56" + +[features] +default = [] +deserialize_in_place = [] + +[lib] +name = "serde_derive" +proc-macro = true + +[dependencies] +proc-macro2 = { workspace = true, features = ["proc-macro"] } +quote = { workspace = true, features = ["proc-macro"] } +syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } + +[dev-dependencies] +serde = { version = "1", path = "../serde" } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"f8b789a2b436af04913166cb07fcd87927fb4a89c84332f82fd58f84cc3a4e0b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"f223b99630bae262eb2b88bb95d0f496db8f1ff4e94e43dbfc8d95d3a6c98d8f","build.rs":"9fa36e0b1bb7026b449a20986ae2f60b3046bcbcf3bf22b5c0e372eb892eaf57","src/de.rs":"c423a0534203713b89c3db544d7ea0988b4a913a0501d0d9cb170f6a66d23dd6","src/error.rs":"a9b5de0a82f95608b51b8e8875c7c49f94fb60b9f976fc6277aec0213926dec9","src/io/core.rs":"60ba28f67a9acaecf8964b611efba416b13f9f2bae4befc329fdf0e037293802","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"bd6106e5d8875c9ff1c1d57256b459a4f0992d14a0df1a5fffcd3d3cbdccee8c","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"db688e8112389998d0f91906f6857e28f9b510a8b4065ad476c8e8be2f77becf","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"9502805adbc3da059131d1fac0a802e17065b36cd7472606b3af24e3241d5cb8","src/lexical/errors.rs":"3d9f6de6245533bcb101dfd718cfed61d59dc293f6768cedae28aa13ace164f5","src/lexical/exponent.rs":"51f19443008e8884b15c7d5d4b1f1cfbd5673a9d1da02f1af39fcf20e315f01f","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"c70b57a727960beec258758a4d4a1050f8eaf3b4e60027c663a2bfb0246e0153","src/lexical/large_powers64.rs":"e7af83ce3159b5fc4669fc5a231e767d8af21bacaece52a0a48951198965b197","src/lexical/math.rs":"240804aa030849495fa03a83a0ee8539d5a5c8639b825f2d69d27b7567b06fb3","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"dd9f4357b8d5bead413844d4015176d484e907e1a393cf7f583de5c5ccafb2e3","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"4762af3612880b17468ff2a1bb800c8e99f08330ae439699dd53d8dc5463ad13","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"161e03a3d34254716ed88d6d3b7c7536f646e674263ca71b5930b99c1c06a4ca","src/macros.rs":"516f69976f433bcc5e48c32b3e29c2e0ab7b549810827d7a9c59171cdf11c1e2","src/map.rs":"aeb07107ba949330e72f4d669d46b215990f83aa4055e06d1da69f2a32ddf642","src/number.rs":"537be73fe2f1f4c654a41e0b6461493ca7e3c20265163b3fb3405d047c163c1a","src/raw.rs":"74f5937706324c9325acc42597ff0a226faeaae38d270ab61ba6283e37616c86","src/read.rs":"7e5928c7f71cfa3848966ab6cc0e6596fd0a3e15cf9f2c59675bf920340ab79f","src/ser.rs":"ee5b6cb04c2ff7058b52cb5d0383218f484505ce0896e5c7fd5076bd9d90952e","src/value/de.rs":"890d88303ce0036a5efd1c57378dab7f8c45dabd798cece2248c2d9db52fa011","src/value/from.rs":"add9687e35db3962729d986c8aa54785cadeb07b8b7121cd4075e3a37ecc73a1","src/value/index.rs":"1a0d59629ae16d6553686de8d7152abd470153f67f9a1b69741e480ba491cd67","src/value/mod.rs":"c1b08509df5ae1ffb5c5e148ac29791923c92eb9957935683739a95bef0007e9","src/value/partial_eq.rs":"655fd0bf3ab1d6669444a55ab849f43bb333032de8ca8f1ee95e1068da43ee22","src/value/ser.rs":"d59f959448de1f4115ed62359e7444081741215e7005bcf97f7584b5e31e3b15","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"8ee6e617ef62a090de49ac2a930130a6913ab5316100781543c7788f89ef99c2","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"dc8fa8d05e561ff256f8b09385291768c7f45e5ad6cb878ef9194757aa014386","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"a11f09bb003a3a024548008cf78bf76526ed71b00077d1989f45eb8cebc93b9c","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"89f604c5788bcb8dc82c82e252dc0da47257986e353c09d14e4ef3e58c455f2d","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1004.rs":"38d7e3b6c515b881078ebd21ca8063d2ca105cd319695d29538f879e37f091b5","tests/regression/issue520.rs":"f95b362e45c57b431720c48eb47f7ddddf4078195d6859df523dc32950ce980a","tests/regression/issue795.rs":"37ff26744b1f950dd212565c6e3f276268882f7724cc589ac8b21ca8bd608413","tests/regression/issue845.rs":"10d2895cd1412cb6630f0a59db367f79ee672edb501151c7581e9921b5a84b92","tests/regression/issue953.rs":"b2cddc761f5ca6639900c173765a8a5868528a896924e5e925db2696469208f7","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"43cd75d02297758365ce6175a62843fa84fb60f4cdb3c9ed3cbfb752db6fcc68","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"3732fd8f4e57b84efc07170cda5f9c5b2b17c707e23c1659222b5a46f652a8d8","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"eae626cf93c97abd105066e624ca4e8cb096784413b9d2564cf9414a8492bc4d","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"b0df8add5cf74e5df30eedd3ca347e4862c04a01c54d802ff45392f2032065b1","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"4fcd0a014fbce31c9266bab8527d6e6b6806a0e21d9e0275ce713137856073ce","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"20cf0d2898749f3c36780fc065f5049ee809e74cb6f0ef776f43f45e01596ee3","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"8df615998fa3057bb9ed865981a35cdbb771625337048f0ad3fba7734e607adf","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"b1985c89075ab48b2158bd1705ed766d37854b3d4620ab257cc8bc319d224f17","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"b2288742fa6a4a7eb65d2ae899bcfed8795b57bd04958da227d60928a8df26c5","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"4c103ca63ff15e2ca659242cc0eae0612bf050e7580da62f1cf50de8082aa7dc"},"package":"3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"8fce44cd269e995b71c0886daf01b6a82d18e89a1f72631f54fd264a7291dbac",".github/workflows/ci.yml":"bc756170e1fe1c2a078e55160c5a526171926b8c4d792ee481a9dcd1240d0383","CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"f8b789a2b436af04913166cb07fcd87927fb4a89c84332f82fd58f84cc3a4e0b","Cargo.toml.orig":"935c0548f11e41977691cd11e0aab14852d7a08a02b24bccddfdbad9b035ab8b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"f223b99630bae262eb2b88bb95d0f496db8f1ff4e94e43dbfc8d95d3a6c98d8f","build.rs":"9fa36e0b1bb7026b449a20986ae2f60b3046bcbcf3bf22b5c0e372eb892eaf57","src/de.rs":"c423a0534203713b89c3db544d7ea0988b4a913a0501d0d9cb170f6a66d23dd6","src/error.rs":"a9b5de0a82f95608b51b8e8875c7c49f94fb60b9f976fc6277aec0213926dec9","src/io/core.rs":"60ba28f67a9acaecf8964b611efba416b13f9f2bae4befc329fdf0e037293802","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"bd6106e5d8875c9ff1c1d57256b459a4f0992d14a0df1a5fffcd3d3cbdccee8c","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"db688e8112389998d0f91906f6857e28f9b510a8b4065ad476c8e8be2f77becf","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"9502805adbc3da059131d1fac0a802e17065b36cd7472606b3af24e3241d5cb8","src/lexical/errors.rs":"3d9f6de6245533bcb101dfd718cfed61d59dc293f6768cedae28aa13ace164f5","src/lexical/exponent.rs":"51f19443008e8884b15c7d5d4b1f1cfbd5673a9d1da02f1af39fcf20e315f01f","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"c70b57a727960beec258758a4d4a1050f8eaf3b4e60027c663a2bfb0246e0153","src/lexical/large_powers64.rs":"e7af83ce3159b5fc4669fc5a231e767d8af21bacaece52a0a48951198965b197","src/lexical/math.rs":"240804aa030849495fa03a83a0ee8539d5a5c8639b825f2d69d27b7567b06fb3","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"dd9f4357b8d5bead413844d4015176d484e907e1a393cf7f583de5c5ccafb2e3","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"4762af3612880b17468ff2a1bb800c8e99f08330ae439699dd53d8dc5463ad13","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"161e03a3d34254716ed88d6d3b7c7536f646e674263ca71b5930b99c1c06a4ca","src/macros.rs":"516f69976f433bcc5e48c32b3e29c2e0ab7b549810827d7a9c59171cdf11c1e2","src/map.rs":"aeb07107ba949330e72f4d669d46b215990f83aa4055e06d1da69f2a32ddf642","src/number.rs":"537be73fe2f1f4c654a41e0b6461493ca7e3c20265163b3fb3405d047c163c1a","src/raw.rs":"74f5937706324c9325acc42597ff0a226faeaae38d270ab61ba6283e37616c86","src/read.rs":"7e5928c7f71cfa3848966ab6cc0e6596fd0a3e15cf9f2c59675bf920340ab79f","src/ser.rs":"ee5b6cb04c2ff7058b52cb5d0383218f484505ce0896e5c7fd5076bd9d90952e","src/value/de.rs":"890d88303ce0036a5efd1c57378dab7f8c45dabd798cece2248c2d9db52fa011","src/value/from.rs":"add9687e35db3962729d986c8aa54785cadeb07b8b7121cd4075e3a37ecc73a1","src/value/index.rs":"1a0d59629ae16d6553686de8d7152abd470153f67f9a1b69741e480ba491cd67","src/value/mod.rs":"c1b08509df5ae1ffb5c5e148ac29791923c92eb9957935683739a95bef0007e9","src/value/partial_eq.rs":"655fd0bf3ab1d6669444a55ab849f43bb333032de8ca8f1ee95e1068da43ee22","src/value/ser.rs":"d59f959448de1f4115ed62359e7444081741215e7005bcf97f7584b5e31e3b15","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"8ee6e617ef62a090de49ac2a930130a6913ab5316100781543c7788f89ef99c2","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"dc8fa8d05e561ff256f8b09385291768c7f45e5ad6cb878ef9194757aa014386","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"a11f09bb003a3a024548008cf78bf76526ed71b00077d1989f45eb8cebc93b9c","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"89f604c5788bcb8dc82c82e252dc0da47257986e353c09d14e4ef3e58c455f2d","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1004.rs":"38d7e3b6c515b881078ebd21ca8063d2ca105cd319695d29538f879e37f091b5","tests/regression/issue520.rs":"f95b362e45c57b431720c48eb47f7ddddf4078195d6859df523dc32950ce980a","tests/regression/issue795.rs":"37ff26744b1f950dd212565c6e3f276268882f7724cc589ac8b21ca8bd608413","tests/regression/issue845.rs":"10d2895cd1412cb6630f0a59db367f79ee672edb501151c7581e9921b5a84b92","tests/regression/issue953.rs":"b2cddc761f5ca6639900c173765a8a5868528a896924e5e925db2696469208f7","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"43cd75d02297758365ce6175a62843fa84fb60f4cdb3c9ed3cbfb752db6fcc68","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"3732fd8f4e57b84efc07170cda5f9c5b2b17c707e23c1659222b5a46f652a8d8","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"eae626cf93c97abd105066e624ca4e8cb096784413b9d2564cf9414a8492bc4d","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"b0df8add5cf74e5df30eedd3ca347e4862c04a01c54d802ff45392f2032065b1","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"4fcd0a014fbce31c9266bab8527d6e6b6806a0e21d9e0275ce713137856073ce","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"20cf0d2898749f3c36780fc065f5049ee809e74cb6f0ef776f43f45e01596ee3","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"8df615998fa3057bb9ed865981a35cdbb771625337048f0ad3fba7734e607adf","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"b1985c89075ab48b2158bd1705ed766d37854b3d4620ab257cc8bc319d224f17","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"b2288742fa6a4a7eb65d2ae899bcfed8795b57bd04958da227d60928a8df26c5","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"4c103ca63ff15e2ca659242cc0eae0612bf050e7580da62f1cf50de8082aa7dc"},"package":"3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a3f62bb10ea870dafe3b49a77dc6c1713ca4b7e4" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/serde_json/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_json/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,138 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + test: + name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}} + runs-on: ${{matrix.os}}-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu, windows] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo test + - run: cargo test --features preserve_order --tests -- --skip ui --exact + - run: cargo test --features float_roundtrip --tests -- --skip ui --exact + - run: cargo test --features arbitrary_precision --tests -- --skip ui --exact + - run: cargo test --features float_roundtrip,arbitrary_precision --tests -- --skip ui --exact + - run: cargo test --features raw_value --tests -- --skip ui --exact + - run: cargo test --features unbounded_depth --tests -- --skip ui --exact + + build: + name: Rust ${{matrix.rust}} ${{matrix.os == 'windows' && '(windows)' || ''}} + runs-on: ${{matrix.os}}-latest + strategy: + fail-fast: false + matrix: + rust: [beta, 1.64.0, 1.56.1] + os: [ubuntu] + include: + - rust: stable + os: ubuntu + target: aarch64-unknown-none + - rust: stable + os: windows + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + targets: ${{matrix.target}} + - run: cargo check --manifest-path tests/crate/Cargo.toml + - run: cargo check --manifest-path tests/crate/Cargo.toml --features float_roundtrip + - run: cargo check --manifest-path tests/crate/Cargo.toml --features arbitrary_precision + - run: cargo check --manifest-path tests/crate/Cargo.toml --features raw_value + - run: cargo check --manifest-path tests/crate/Cargo.toml --features unbounded_depth + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,arbitrary_precision + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,raw_value + - run: cargo check --manifest-path tests/crate/Cargo.toml --features serde_json/preserve_order + if: matrix.rust != '1.56.1' + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,serde_json/preserve_order + if: matrix.rust != '1.56.1' + - name: Build without std + run: cargo check --manifest-path tests/crate/Cargo.toml --target ${{matrix.target}} --no-default-features --features alloc + if: matrix.target + + minimal: + name: Minimal versions + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + miri: + name: Miri + runs-on: ubuntu-latest + env: + MIRIFLAGS: -Zmiri-strict-provenance + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + - run: cargo miri test --features preserve_order,float_roundtrip,arbitrary_precision,raw_value + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + - run: cargo clippy --all-features --tests -- -Dclippy::all -Dclippy::pedantic + + doc: + name: Documentation + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + fuzz: + name: Fuzz + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz check + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/serde_json/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/serde_json/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/serde_json/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/serde_json/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +[package] +name = "serde_json" +version = "1.0.116" +authors = ["Erick Tryzelaar ", "David Tolnay "] +categories = ["encoding", "parser-implementations", "no-std"] +description = "A JSON serialization file format" +documentation = "https://docs.rs/serde_json" +edition = "2021" +keywords = ["json", "serde", "serialization"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/serde-rs/json" +rust-version = "1.56" + +[dependencies] +indexmap = { version = "2.2.1", optional = true } +itoa = "1.0" +ryu = "1.0" +serde = { version = "1.0.194", default-features = false } + +[dev-dependencies] +automod = "1.0.11" +indoc = "2.0.2" +ref-cast = "1.0.18" +rustversion = "1.0.13" +serde = { version = "1.0.194", features = ["derive"] } +serde_bytes = "0.11.10" +serde_derive = "1.0.166" +serde_stacker = "0.1.8" +trybuild = { version = "1.0.81", features = ["diff"] } + +[lib] +doc-scrape-examples = false + +[package.metadata.docs.rs] +features = ["preserve_order", "raw_value", "unbounded_depth"] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"] + +[package.metadata.playground] +features = ["raw_value"] + + +### FEATURES ################################################################# + +[features] +default = ["std"] + +std = ["serde/std"] + +# Provide integration for heap-allocated collections without depending on the +# rest of the Rust standard library. +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. +alloc = ["serde/alloc"] + +# Make serde_json::Map use a representation which maintains insertion order. +# This allows data to be read into a Value and written back to a JSON string +# while preserving the order of map keys in the input. +preserve_order = ["indexmap", "std"] + +# Use sufficient precision when parsing fixed precision floats from JSON to +# ensure that they maintain accuracy when round-tripped through JSON. This comes +# at an approximately 2x performance cost for parsing floats compared to the +# default best-effort precision. +# +# Unlike arbitrary_precision, this feature makes f64 -> JSON -> f64 produce +# output identical to the input. +float_roundtrip = [] + +# Use an arbitrary precision number representation for serde_json::Number. This +# allows JSON numbers of arbitrary size/precision to be read into a Number and +# written back to a JSON string without loss of precision. +# +# Unlike float_roundtrip, this feature makes JSON -> serde_json::Number -> JSON +# produce output identical to the input. +arbitrary_precision = [] + +# Provide a RawValue type that can hold unprocessed JSON during deserialization. +raw_value = [] + +# Provide a method disable_recursion_limit to parse arbitrarily deep JSON +# structures without any consideration for overflowing the stack. When using +# this feature, you will want to provide some other way to protect against stack +# overflows, such as by wrapping your Deserializer in the dynamically growing +# stack adapter provided by the serde_stacker crate. Additionally you will need +# to be careful around other recursive operations on the parsed result which may +# overflow the stack after deserialization has completed, including, but not +# limited to, Display and Debug and Drop impls. +unbounded_depth = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha1/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/sha1/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"7e9245847760fa99eaab7e4864a199148387aaa6121ac3dfbe189f0b684cf7d2","Cargo.toml":"cbfdd2dcaf34776f686caf30420c0a32a13d032fdd62495a054e65c3b0769132","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"b4eb00df6e2a4d22518fcaa6a2b4646f249b3a3c9814509b22bd2091f1392ff1","README.md":"8028a4064be59cba366c1bafa682002b52891a3cc2d2169d8f38064ba69773d1","benches/mod.rs":"2765aec429270711235d6cd4911d0c21658e2fa3dfbe24559f24e21b056b507c","src/compress.rs":"fcd99dc9c137e1fc05e47d406adfeeafccb31bed981e7c8bf480d765fb36e877","src/compress/aarch64.rs":"b1e66c2df53eaf84ccf7466aed47c0718fc3dbe1d1c565b65abd60e84b6fc5d4","src/compress/loongarch64_asm.rs":"0fd7d61b5ca7d7bce40cd9ce9012eb787da9f9df87595bfe00f8d882267d182e","src/compress/soft.rs":"bc6dda22b15acd76d97e202a8b251d9c68441d426a71600b2a61c36dd6f3a08e","src/compress/x86.rs":"9d2b4f240a311a84b351c136cccdc4dc00a7fc35703146ad51ed2d6e0aaef2d0","src/lib.rs":"c3409d489833cf896d611baf0ca0e5958629fc9e5f91a1144e789dc1858c513c","tests/data/sha1.blb":"b9c03b9e56e0a7b08a6d6867599a33cab1a55aec3f41fef910c133fc35dc2851","tests/mod.rs":"34bb42bf4679b3f23ffc2338356c8579c872026eef9989955a29ba44a432c3b5"},"package":"e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5bbef980c8535fb21ea8cb94312e7396f96ef794fbb9f0a4c8cba12e92eea2d4","CHANGELOG.md":"7e9245847760fa99eaab7e4864a199148387aaa6121ac3dfbe189f0b684cf7d2","Cargo.toml":"cbfdd2dcaf34776f686caf30420c0a32a13d032fdd62495a054e65c3b0769132","Cargo.toml.orig":"97b1e1c532a0b661b31bd58a608a2ce10ce23c8739c15f27121b2d71b0274b41","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"b4eb00df6e2a4d22518fcaa6a2b4646f249b3a3c9814509b22bd2091f1392ff1","README.md":"8028a4064be59cba366c1bafa682002b52891a3cc2d2169d8f38064ba69773d1","benches/mod.rs":"2765aec429270711235d6cd4911d0c21658e2fa3dfbe24559f24e21b056b507c","src/compress.rs":"fcd99dc9c137e1fc05e47d406adfeeafccb31bed981e7c8bf480d765fb36e877","src/compress/aarch64.rs":"b1e66c2df53eaf84ccf7466aed47c0718fc3dbe1d1c565b65abd60e84b6fc5d4","src/compress/loongarch64_asm.rs":"0fd7d61b5ca7d7bce40cd9ce9012eb787da9f9df87595bfe00f8d882267d182e","src/compress/soft.rs":"bc6dda22b15acd76d97e202a8b251d9c68441d426a71600b2a61c36dd6f3a08e","src/compress/x86.rs":"9d2b4f240a311a84b351c136cccdc4dc00a7fc35703146ad51ed2d6e0aaef2d0","src/lib.rs":"c3409d489833cf896d611baf0ca0e5958629fc9e5f91a1144e789dc1858c513c","tests/data/sha1.blb":"b9c03b9e56e0a7b08a6d6867599a33cab1a55aec3f41fef910c133fc35dc2851","tests/mod.rs":"34bb42bf4679b3f23ffc2338356c8579c872026eef9989955a29ba44a432c3b5"},"package":"e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha1/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/sha1/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha1/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "7aba4b52715f9cb17a90303bab55bd59471d65ae" + }, + "path_in_vcs": "sha1" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha1/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/sha1/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/sha1/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha1/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +[package] +name = "sha1" +version = "0.10.6" +description = "SHA-1 hash function" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/sha1" +repository = "https://github.com/RustCrypto/hashes" +keywords = ["crypto", "sha1", "hash", "digest"] +categories = ["cryptography", "no-std"] + +[dependencies] +digest = "0.10.7" +cfg-if = "1.0" + +[target.'cfg(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64"))'.dependencies] +cpufeatures = "0.2" +sha1-asm = { version = "0.5", optional = true } + +[dev-dependencies] +digest = { version = "0.10.7", features = ["dev"] } +hex-literal = "0.2.2" + +[features] +default = ["std"] +std = ["digest/std"] +oid = ["digest/oid"] # Enable OID support. WARNING: Bumps MSRV to 1.57 +asm = ["sha1-asm"] # WARNING: this feature SHOULD NOT be enabled by library crates +# Use assembly backend for LoongArch64 targets +# WARNING: Bumps MSRV to 1.72. This feature SHOULD NOT be enabled by library crates +loongarch64_asm = [] +compress = [] # Expose compress function +force-soft = [] # Force software implementation + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/sha2/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"b7b0a14409ac2880f86fe50d9584acc81f2346ebcb4e46a9e2235b54ac5b02ef","Cargo.toml":"5fdf94b86fc47d105d2f2cc55c6346d15e7f3d2d7ea92031b1ce2d24276e7778","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"b4eb00df6e2a4d22518fcaa6a2b4646f249b3a3c9814509b22bd2091f1392ff1","README.md":"b7af562922e4a631657acf264772d2af2b72a08d9bbc5fbcf56d9324f9027708","benches/mod.rs":"c32d9f91a541821ea988c14eee710963e623ef1edf69b02b41a29bc44e04ba95","src/consts.rs":"2f820349fa7cbf9fecc1d4aabbd1a721bb1badc3f32ef9e903826960b6f42523","src/core_api.rs":"73b160d98bfa6737688875ad73da5e3c2c93582604dc313d208200e12fdab676","src/lib.rs":"9d0ec0ba86a801bd9b2024f0b84ee322a26c7376a623dd61210e0eb9d6355aa1","src/sha256.rs":"78e84eea5d517554aa5a10860bf2ce5013ca26d529e78643cd59062546e0746f","src/sha256/aarch64.rs":"18121a25867a575fec8ef64da763693ece4e3e3e84da095254b8471234c6f1f8","src/sha256/loongarch64_asm.rs":"79e2d5e3c039581e2319f8789de9ed13a8dd819ebffd13532dbd83448c7ad662","src/sha256/soft.rs":"98e765a8e8dfa0af31f2b76570f212e6b3099522bf300e1554cbbd9fd5d02960","src/sha256/x86.rs":"70f1597f2029522b35bfd026df0a8908f086523ab2a80ba3ef35e6231b56353c","src/sha512.rs":"1b19c23c63e9cfca8b42fd9e108a8570dd03e22a37d4d6f499f2fa5e566cb2de","src/sha512/aarch64.rs":"2ed929329a0fa66180e4726d028713a49f99cc223e635078fc1f3252a44981e0","src/sha512/loongarch64_asm.rs":"58a7b54d95a0e037ba80570d96ffe0dd7c0014c7fcb45b90725e522cc4992d8a","src/sha512/soft.rs":"0183ad89418b886859d2afa9bf061bc92759ae337c1d26147b4300042e63ef42","src/sha512/x86.rs":"c7dd8bdf3212e1e8c4cc9cc6b380dc0468f79dcfd0f61a445d0d38cead45a03a","tests/data/sha224.blb":"59b185972521af418fd49a079de3d5f5bed74cd76d80473da51cab3faee6c7d0","tests/data/sha256.blb":"bb096934bb7e43e41ce143d211397afca6fcdfe243a39811688ea31aae6f800a","tests/data/sha384.blb":"e8fe66c07ba336fae2c0aa4c87cb768f41bd4ed318ee1a36fbde0a68581946ec","tests/data/sha512.blb":"1cc0e86571f2f4e3bc81438ce7b6c25c118d2d7437355240113f59cbb782c8d6","tests/data/sha512_224.blb":"b02dd46741db1034112e0888d0cdb233a21b9a82c319456f806bbaae49acf440","tests/data/sha512_256.blb":"95195b758e362d92ff0cebebac4cca696512ea5811b635243bc70e29164e5786","tests/mod.rs":"61be596fd9b45a8db345950ff2ed6f87eaf4d239ac156885f36e819da0597644"},"package":"793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"2427bb49dba598b8ac9f461245cb5484be8f81b54a3d4c35e0d6415a423d02b3","CHANGELOG.md":"b7b0a14409ac2880f86fe50d9584acc81f2346ebcb4e46a9e2235b54ac5b02ef","Cargo.toml":"5fdf94b86fc47d105d2f2cc55c6346d15e7f3d2d7ea92031b1ce2d24276e7778","Cargo.toml.orig":"d223cb4de934e2d0e5a62eb8005eb71f1d532a808e6f250617cbbe466bdc0620","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"b4eb00df6e2a4d22518fcaa6a2b4646f249b3a3c9814509b22bd2091f1392ff1","README.md":"b7af562922e4a631657acf264772d2af2b72a08d9bbc5fbcf56d9324f9027708","benches/mod.rs":"c32d9f91a541821ea988c14eee710963e623ef1edf69b02b41a29bc44e04ba95","src/consts.rs":"2f820349fa7cbf9fecc1d4aabbd1a721bb1badc3f32ef9e903826960b6f42523","src/core_api.rs":"73b160d98bfa6737688875ad73da5e3c2c93582604dc313d208200e12fdab676","src/lib.rs":"9d0ec0ba86a801bd9b2024f0b84ee322a26c7376a623dd61210e0eb9d6355aa1","src/sha256.rs":"78e84eea5d517554aa5a10860bf2ce5013ca26d529e78643cd59062546e0746f","src/sha256/aarch64.rs":"18121a25867a575fec8ef64da763693ece4e3e3e84da095254b8471234c6f1f8","src/sha256/loongarch64_asm.rs":"79e2d5e3c039581e2319f8789de9ed13a8dd819ebffd13532dbd83448c7ad662","src/sha256/soft.rs":"98e765a8e8dfa0af31f2b76570f212e6b3099522bf300e1554cbbd9fd5d02960","src/sha256/x86.rs":"70f1597f2029522b35bfd026df0a8908f086523ab2a80ba3ef35e6231b56353c","src/sha512.rs":"1b19c23c63e9cfca8b42fd9e108a8570dd03e22a37d4d6f499f2fa5e566cb2de","src/sha512/aarch64.rs":"2ed929329a0fa66180e4726d028713a49f99cc223e635078fc1f3252a44981e0","src/sha512/loongarch64_asm.rs":"58a7b54d95a0e037ba80570d96ffe0dd7c0014c7fcb45b90725e522cc4992d8a","src/sha512/soft.rs":"0183ad89418b886859d2afa9bf061bc92759ae337c1d26147b4300042e63ef42","src/sha512/x86.rs":"c7dd8bdf3212e1e8c4cc9cc6b380dc0468f79dcfd0f61a445d0d38cead45a03a","tests/data/sha224.blb":"59b185972521af418fd49a079de3d5f5bed74cd76d80473da51cab3faee6c7d0","tests/data/sha256.blb":"bb096934bb7e43e41ce143d211397afca6fcdfe243a39811688ea31aae6f800a","tests/data/sha384.blb":"e8fe66c07ba336fae2c0aa4c87cb768f41bd4ed318ee1a36fbde0a68581946ec","tests/data/sha512.blb":"1cc0e86571f2f4e3bc81438ce7b6c25c118d2d7437355240113f59cbb782c8d6","tests/data/sha512_224.blb":"b02dd46741db1034112e0888d0cdb233a21b9a82c319456f806bbaae49acf440","tests/data/sha512_256.blb":"95195b758e362d92ff0cebebac4cca696512ea5811b635243bc70e29164e5786","tests/mod.rs":"61be596fd9b45a8db345950ff2ed6f87eaf4d239ac156885f36e819da0597644"},"package":"793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/sha2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "28a7b0da94a581e71e85d264836e1c3f8343338e" + }, + "path_in_vcs": "sha2" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/sha2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/sha2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/sha2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/sha2/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,43 @@ +[package] +name = "sha2" +version = "0.10.8" +description = """ +Pure Rust implementation of the SHA-2 hash function family +including SHA-224, SHA-256, SHA-384, and SHA-512. +""" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/sha2" +repository = "https://github.com/RustCrypto/hashes" +keywords = ["crypto", "sha2", "hash", "digest"] +categories = ["cryptography", "no-std"] + +[dependencies] +digest = "0.10.7" +cfg-if = "1.0" + +[target.'cfg(any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86"))'.dependencies] +cpufeatures = "0.2" +sha2-asm = { version = "0.6.1", optional = true } + +[dev-dependencies] +digest = { version = "0.10.7", features = ["dev"] } +hex-literal = "0.2.2" + +[features] +default = ["std"] +std = ["digest/std"] +oid = ["digest/oid"] # Enable OID support. WARNING: Bumps MSRV to 1.57 +asm = ["sha2-asm"] # WARNING: this feature SHOULD NOT be enabled by library crates +# Use assembly backend for LoongArch64 targets +# WARNING: Bumps MSRV to 1.72. This feature SHOULD NOT be enabled by library crates +loongarch64_asm = [] +compress = [] # Expose compress functions +force-soft = [] # Force software implementation +asm-aarch64 = ["asm"] # DEPRECATED: use `asm` instead + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/shlex/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/shlex/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"879a16b3fef6fb3251fcac516fe73414109e3b7df5eb2ec4863a7551674038a0","Cargo.toml":"d7eb8c4bce681b4dd1dfc2c98c649754390775f38f4796d491948ddbb53aa2ef","LICENSE-APACHE":"553fffcd9b1cb158bc3e9edc35da85ca5c3b3d7d2e61c883ebcfa8a65814b583","LICENSE-MIT":"4455bf75a91154108304cb283e0fea9948c14f13e20d60887cf2552449dea3b1","README.md":"082e505bba5dffc5904af5602b45d01129173e617db62c81e6c11d71c964ea71","src/bytes.rs":"eadfffcdb7846d341ba451d6118d275b9d0f14a9554984ccfcdbe9a8d77ec5ee","src/lib.rs":"44c8fb929e1443f2446d26025a9bcfca0b329811bbc309b4a6afb8ec17d7de8d","src/quoting_warning.md":"566d6509211ddcd4afbd4f1117c5234567f6b6d01f5da60acfaef011362be045"},"package":"0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"5ba6bffcbe6628331b4b8ae50936c44d6260de2913c83f55e0c19fce366af72c",".github/workflows/test.yml":"cca05e7dbd8b0c65f5c8f5a30fb76fd11aaaaf9a3216b5d5b0ea387b3d94fffa","CHANGELOG.md":"879a16b3fef6fb3251fcac516fe73414109e3b7df5eb2ec4863a7551674038a0","Cargo.toml":"d7eb8c4bce681b4dd1dfc2c98c649754390775f38f4796d491948ddbb53aa2ef","Cargo.toml.orig":"aba3cfcd4981d79feac94eb673bcdd0754962edc0e2a0ce81a13d5285c5a3f3d","LICENSE-APACHE":"553fffcd9b1cb158bc3e9edc35da85ca5c3b3d7d2e61c883ebcfa8a65814b583","LICENSE-MIT":"4455bf75a91154108304cb283e0fea9948c14f13e20d60887cf2552449dea3b1","README.md":"082e505bba5dffc5904af5602b45d01129173e617db62c81e6c11d71c964ea71","src/bytes.rs":"eadfffcdb7846d341ba451d6118d275b9d0f14a9554984ccfcdbe9a8d77ec5ee","src/lib.rs":"44c8fb929e1443f2446d26025a9bcfca0b329811bbc309b4a6afb8ec17d7de8d","src/quoting_warning.md":"566d6509211ddcd4afbd4f1117c5234567f6b6d01f5da60acfaef011362be045"},"package":"0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/shlex/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/shlex/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/shlex/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4a0724b0b62ef715467875b040a890ce75a8a829" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/shlex/.github/workflows/test.yml clamav-1.4.6+dfsg/.cargo/vendor/shlex/.github/workflows/test.yml --- clamav-1.4.3+dfsg/.cargo/vendor/shlex/.github/workflows/test.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/shlex/.github/workflows/test.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +name: Rust + +on: + pull_request: + push: + +jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ATiltedTree/setup-rust@v1 + with: + rust-version: stable + - run: cargo check + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ATiltedTree/setup-rust@v1 + with: + rust-version: stable + - run: cargo test + + test_no_default_features: + name: Test (no default features) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ATiltedTree/setup-rust@v1 + with: + rust-version: stable + - run: cargo test --no-default-features diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/shlex/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/shlex/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/shlex/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/shlex/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +[package] +name = "shlex" +version = "1.3.0" +authors = [ + "comex ", + "Fenhl ", + "Adrian Taylor ", + "Alex Touchet ", + "Daniel Parks ", + "Garrett Berg ", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/comex/rust-shlex" +description = "Split a string into shell words, like Python's shlex." +categories = [ + "command-line-interface", + "parser-implementations" +] +rust-version = "1.46.0" + +[features] +std = [] +default = ["std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"4f762219d91ec3f7b6f4f25c6c4f4a83a5c3a0db1503827d9e1541c5fb8b62a1","Cargo.toml":"1df396cf8d69ee6f333bae303d4051c9f189167fa1ce07791becc5d3f2bd14fe","LICENSE.md":"42a35170233e83e18856792e748de4c1ce4a63b2afce9a370c89ef3fe23f9f2d","README.md":"a0568aab174ff15c2252898c7520ce0bd539cfb75d799238acd34dec44ee772c","src/hash.rs":"b5d0aea3ad486cccb67a156606e932b857cf0db5014393df50f290a495836d17","src/imp/avx2.rs":"46a83702bfe182278851d75f83b916a9fe0cc1ff5d1244d1912960ee1fcd82b2","src/imp/avx512.rs":"6e96adfe3099319529c486a186c71c85d92e93b29ea73558b84d65c618367858","src/imp/mod.rs":"9e6a1e69c40b03922b66a939b60e4217886a8aed3757af8d5a1e168c888121dd","src/imp/neon.rs":"2edad3b532b3384c83607a8adc6a1a46b4428708d02cb213f6afd333f60cfc99","src/imp/scalar.rs":"950c9f1202110da14d4ce725591fb2bdab36b73e500d2654e3a75c1a69a4ca5d","src/imp/sse2.rs":"fabefe43151e989a8a24910c682ae2661c30ee39363f0903311e6da60e192658","src/imp/ssse3.rs":"12f719d17bd9044c374f217312ea094625f22436e27bd12a28c60469f9448608","src/imp/wasm.rs":"3b49cde90bde87548e5169c061bf1abdde328710f75cde807d0921130aa232f1","src/lib.rs":"94525f007da93fbb09bbcdc164bc86a13a9526464203eb508ce65e5752c1a3f2"},"package":"d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"74e5cd1af8076838ee7edd99c631b6f77fa47aa9806bd7b0980ca6312c1df092",".github/workflows/build.yaml":"53a2052a410d31a006e582d1cf1ef26a32c6dd5fbff4258bb4d2f7a54a77bcb1",".github/workflows/fuzz.yaml":"4db54f5cfb4228537e489f6fa9f5e94955774395cd5519432dec8671c634e5ca",".github/workflows/publish.yaml":"57c5763d32dc0358795360a5c72beb007aac281a3a9cd5475ff4e22cfc5dea21",".rustfmt.toml":"bc44a62358fe8857bd97d33209253d6b073acf0c18383f50882113f9db4c7a9d","CHANGELOG.md":"4f762219d91ec3f7b6f4f25c6c4f4a83a5c3a0db1503827d9e1541c5fb8b62a1","Cargo.toml":"1df396cf8d69ee6f333bae303d4051c9f189167fa1ce07791becc5d3f2bd14fe","Cargo.toml.orig":"467d4ba12c259bb65824c7085c4fc5da4faf92a49b5ac99399e43b62d35878df","LICENSE.md":"42a35170233e83e18856792e748de4c1ce4a63b2afce9a370c89ef3fe23f9f2d","README.md":"a0568aab174ff15c2252898c7520ce0bd539cfb75d799238acd34dec44ee772c","src/hash.rs":"b5d0aea3ad486cccb67a156606e932b857cf0db5014393df50f290a495836d17","src/imp/avx2.rs":"46a83702bfe182278851d75f83b916a9fe0cc1ff5d1244d1912960ee1fcd82b2","src/imp/avx512.rs":"6e96adfe3099319529c486a186c71c85d92e93b29ea73558b84d65c618367858","src/imp/mod.rs":"9e6a1e69c40b03922b66a939b60e4217886a8aed3757af8d5a1e168c888121dd","src/imp/neon.rs":"2edad3b532b3384c83607a8adc6a1a46b4428708d02cb213f6afd333f60cfc99","src/imp/scalar.rs":"950c9f1202110da14d4ce725591fb2bdab36b73e500d2654e3a75c1a69a4ca5d","src/imp/sse2.rs":"fabefe43151e989a8a24910c682ae2661c30ee39363f0903311e6da60e192658","src/imp/ssse3.rs":"12f719d17bd9044c374f217312ea094625f22436e27bd12a28c60469f9448608","src/imp/wasm.rs":"3b49cde90bde87548e5169c061bf1abdde328710f75cde807d0921130aa232f1","src/lib.rs":"94525f007da93fbb09bbcdc164bc86a13a9526464203eb508ce65e5752c1a3f2"},"package":"d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "94f3f72eb7346d9e2bfe7e985a496582da409a63" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/build.yaml clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/build.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/build.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/build.yaml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,173 @@ +name: build + +on: + push: + branches-ignore: [main] + pull_request: + branches: [main] + +jobs: + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: clippy + override: true + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features + + test-doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + - uses: Swatinem/rust-cache@v1 + - run: cargo install cargo-deadlinks + - name: doc + env: + RUSTDOCFLAGS: --cfg doc_cfg + run: cargo deadlinks --ignore-fragments -- --all + + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + toolchain: stable + - os: macos-latest + target: x86_64-apple-darwin + toolchain: stable + # TODO: also aarch64 / M1 + - os: windows-latest + target: x86_64-pc-windows-gnu + toolchain: stable + - os: windows-latest + target: x86_64-pc-windows-msvc + toolchain: beta + # Test both windows-gnu and windows-msvc; use beta rust on one + - os: ubuntu-latest + deps: sudo apt-get update ; sudo apt install gcc-multilib + target: i686-unknown-linux-gnu + toolchain: nightly + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + toolchain: nightly + variant: minimal_versions + + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + target: ${{ matrix.target }} + toolchain: ${{ matrix.toolchain }} + override: true + - uses: Swatinem/rust-cache@v1 + - run: ${{ matrix.deps }} + - name: Maybe minimal versions + if: ${{ matrix.variant == 'minimal_versions' }} + run: cargo generate-lockfile -Z minimal-versions + + - name: Test + run: | + cargo test --lib --target ${{ matrix.target }} ${{ matrix.toolchain == 'nightly' && '--features=nightly' || '' }} + + env: + # Enables address sanitization if supported target and nightly. + RUSTFLAGS: | + ${{ + ( + matrix.toolchain == 'nightly' && ( + matrix.target == 'aarch64-apple-darwin' || + matrix.target == 'aarch64-fuchsia' || + matrix.target == 'aarch64-unknown-linux-gnu' || + matrix.target == 'x86_64-apple-darwin' || + matrix.target == 'x86_64-fuchsia' || + matrix.target == 'x86_64-unknown-freebsd' || + matrix.target == 'x86_64-unknown-linux-gnu' + ) + ) + && '-Z sanitizer=address' + || '' + }} + + test-cross: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + target: mips-unknown-linux-gnu + toolchain: stable + - os: ubuntu-latest + target: arm-unknown-linux-gnueabi + toolchain: stable + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + toolchain: stable + - os: ubuntu-latest + target: arm-unknown-linux-gnueabi + toolchain: nightly + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + toolchain: nightly + + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + target: ${{ matrix.target }} + toolchain: ${{ matrix.toolchain }} + override: true + + - uses: Swatinem/rust-cache@v1 + - name: Install cross + run: cargo install cross || true + - name: Test + run: | + cross test --no-fail-fast --target ${{ matrix.target }} ${{ matrix.toolchain == 'nightly' && '--features=nightly' || '' }} + + test-msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + target: x86_64-unknown-linux-gnu + toolchain: 1.36.0 # MSRV + - uses: Swatinem/rust-cache@v1 + - name: Test + run: cargo test --target=x86_64-unknown-linux-gnu --no-default-features --features=std + + test-no-std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + target: thumbv6m-none-eabi + override: true + - uses: Swatinem/rust-cache@v1 + - name: Build top-level only + run: cargo build --target=thumbv6m-none-eabi --no-default-features diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/fuzz.yaml clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/fuzz.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/fuzz.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/fuzz.yaml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +name: fuzz + +on: + schedule: + # Run every 24h + - cron: "0 0 * * *" + +defaults: + run: + working-directory: fuzz + +jobs: + fuzz: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + target: [avx2, sse2, ssse3] + + steps: + - uses: actions/checkout@v2 + - name: setup + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + + - uses: Swatinem/rust-cache@v1 + - run: cargo install cargo-fuzz + + - name: Download corpus artifact + run: | + wget https://nightly.link/mcountryman/simd-adler32/workflows/fuzz.yaml/main/corpus.zip + mkdir -p corpus + unzip corpus.zip -d corpus + + # keep going if artifact doesn't exist + continue-on-error: true + + - name: Run fuzz test (30m) + run: | + cargo fuzz run ${{ matrix.target }} -- -max_total_time=1800 + + - name: Archive artifacts + uses: actions/upload-artifact@v2 + if: failure() + with: + name: artifacts + path: fuzz/artifacts + + # big decision. do we store corpus from failed jobs? for now we don't.. + - uses: actions/upload-artifact@v2 + with: + name: corpus + path: | + fuzz/corpus/ + fuzz/corpus/${{ matrix.target }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/publish.yaml clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/publish.yaml --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.github/workflows/publish.yaml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.github/workflows/publish.yaml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,35 @@ +name: publish + +on: + push: + branches: [main] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Configure git user + run: | + git config user.name "GitHub Actions" + git config user.email noreply@github.com + + - name: Install cargo-release + uses: actions-rs/install@v0.1 + with: + crate: cargo-release + version: latest + + - name: Publish + run: | + cargo login ${{ secrets.CRATES_IO_TOKEN }} + cargo release --no-confirm --no-push -x + + - name: Push changes + uses: ad-m/github-push-action@master + with: + tags: true + force: true + branch: ${{ github.ref }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/.rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/.rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +max_width = 90 +tab_spaces = 2 \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/simd-adler32/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd-adler32/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +[package] +name = "simd-adler32" +authors = ["Marvin Countryman "] +license = "MIT" +version = "0.3.7" +edition = "2018" +keywords = ["simd", "avx2", "ssse3", "adler", "adler32"] +categories = ["algorithms", "no-std"] +repository = "https://github.com/mcountryman/simd-adler32" +description = "A SIMD-accelerated Adler-32 hash algorithm implementation." +exclude = ["bench"] + +[profile.release] +debug = true +opt-level = 2 + +[[bench]] +name = "alts" +path = "bench/alts.rs" +harness = false + +[[bench]] +name = "variants" +path = "bench/variants.rs" +harness = false + +[features] +default = ["std", "const-generics"] +std = [] +nightly = [] +const-generics = [] + +[dev-dependencies] +rand = "0.8" +criterion = "0.3" + +# competition +adler = "1.0.2" +adler32 = "1.2.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"50b2d207be467a8a75522908c5ce1d1298a2cb3f9ea8abe8b3f741d124b6e9c1","Cargo.toml":"42364d200c5cc7792960bdf10354a108b6c68ca49f2e1567967e2d5b1dba37a6","Cargo.toml.orig":"b41497677a5498040f2eb3fc089e3c2c38c413dca64f41dc57a115e26480461d","README.md":"e672b974ba905441c8eee630f10bc351f4e8e462c99d178b334ae3e48d8ca7f5","src/lib.rs":"7776fe38ba2018bdd2e744e42b0affa34966797ededdf381144bb92bb41e194c","tests/cold_for.rs":"930a9b0c072b7036d57ef9df3f5c24716e24b75d7a2aebf9d89ff8c69d68fadb"},"package":"95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "ca1a2f84aa386d758e98f8a609d990263932fb85" + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "simd_helpers" +version = "0.1.0" +authors = ["Luca Barbato "] +description = "Helpers to write more compact simd code" +readme = "README.md" +keywords = ["proc_macro", "simd"] +license = "MIT" +repository = "https://github.com/lu-zero/simd_helpers" + +[lib] +test = false +proc-macro = true +[dependencies.quote] +version = "1.0.2" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/Cargo.toml.orig 2019-10-06 16:07:58.000000000 +0000 @@ -0,0 +1,17 @@ +[package] +name = "simd_helpers" +version = "0.1.0" +authors = ["Luca Barbato "] +edition = "2018" +description = "Helpers to write more compact simd code" +repository = "https://github.com/lu-zero/simd_helpers" +readme = "README.md" +keywords = ["proc_macro", "simd"] +license = "MIT" + +[lib] +proc-macro = true +test = false + +[dependencies] +quote = "1.0.2" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/README.md clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/README.md 2019-10-06 16:05:23.000000000 +0000 @@ -0,0 +1,18 @@ +# Helpers to write more compact simd code + +## Implemented so far +- [x] `cold_for_target_arch` mark a function cold for certain arches only +- [ ] `cold_for_target_feature` + +## Example +``` toml +[dependencies] +simd_helpers = "0.1" +``` +``` rust +use simd_helpers::cold_for_target_arch; + +// On arm and power it is the main, impl for x86_64 there is a asm-optimized variant +#[cold_for_target_arch("x86_64")] +fn fallback_simple_impl() { ... } +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/src/lib.rs 2019-10-06 16:00:47.000000000 +0000 @@ -0,0 +1,23 @@ +extern crate proc_macro; + +use std::iter::FromIterator; + +use proc_macro::TokenStream; +use quote::quote; + +#[proc_macro_attribute] +pub fn cold_for_target_arch(attr: TokenStream, item: TokenStream) -> TokenStream { + let arch_list = attr.to_string(); + let mut out: Vec = arch_list.split(",").map(|a| { + let a = a.trim().split("\"").nth(1).expect("A ','-separated list of \"arguments\" expected"); + (quote! { + #[cfg_attr(target_arch = #a, cold)] + }).into() + }).collect(); + + out.push(item); + + TokenStream::from_iter(out.into_iter()) +} + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/tests/cold_for.rs clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/tests/cold_for.rs --- clamav-1.4.3+dfsg/.cargo/vendor/simd_helpers/tests/cold_for.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/simd_helpers/tests/cold_for.rs 2019-10-06 15:55:27.000000000 +0000 @@ -0,0 +1,6 @@ +use simd_helpers::cold_for_target_arch; + + +#[test] +#[cold_for_target_arch("x86", "x86_64")] +fn t() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"596bd9699b610b359a05ffa8a628186d640c1090c13f7b980c4a6552630ecdff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"d82015eae942ee5cf74ace8c3c260ee2c6b5bcbeeb87254d2c72622c747a708a","debug_metadata/README.md":"4d7f1c1b2c25ce2231ef71864d06e54323867459035b53bc9e00f66a0a44f82e","debug_metadata/smallvec.natvis":"3092ddebd8fffc3486536d7f27f8c5eae3a8a093d45cd8eeb3946ea2b0c35a15","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"2ee976afdac5673b05caefa2b74d16af9d3d759e27d71ff3c88ce2623483e601","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"e6484be3421287eba6002ba3bed318f656a17c7c1b041293c69f2eb56f74b375","tests/debugger_visualizer.rs":"185456ad253957fc0c9e904ff8a1135397ac991c29fa3c60f75d8d81f7463022","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"b5b59038441087cb207412675a613740ae0d50807179035ff781a0faeaea40ac",".github/workflows/main.yml":"dce151e591d6666ac0fa6014f41b946683fd8d4fa6d1828e127e400e0804027d","Cargo.toml":"596bd9699b610b359a05ffa8a628186d640c1090c13f7b980c4a6552630ecdff","Cargo.toml.orig":"6ff7fe9896c359c9b003eb29eefb639b4106070d1896541ed59d44cabf47d213","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"d82015eae942ee5cf74ace8c3c260ee2c6b5bcbeeb87254d2c72622c747a708a","debug_metadata/README.md":"4d7f1c1b2c25ce2231ef71864d06e54323867459035b53bc9e00f66a0a44f82e","debug_metadata/smallvec.natvis":"3092ddebd8fffc3486536d7f27f8c5eae3a8a093d45cd8eeb3946ea2b0c35a15","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"2ee976afdac5673b05caefa2b74d16af9d3d759e27d71ff3c88ce2623483e601","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"e6484be3421287eba6002ba3bed318f656a17c7c1b041293c69f2eb56f74b375","tests/debugger_visualizer.rs":"185456ad253957fc0c9e904ff8a1135397ac991c29fa3c60f75d8d81f7463022","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0089d0a15bee4792a575b9c51e9d7ace39b3957c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.github/workflows/main.yml clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.github/workflows/main.yml --- clamav-1.4.3+dfsg/.cargo/vendor/smallvec/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/smallvec/.github/workflows/main.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,110 @@ +name: CI + +on: + push: + branches: [v1] + pull_request: + workflow_dispatch: + merge_group: + types: [checks_requested] + +jobs: + ci: + name: Build/Test + strategy: + matrix: + toolchain: ["stable", "beta", "nightly", "1.36.0"] + os: [ubuntu-latest] + include: + - toolchain: stable + fuzz: 1 + - toolchain: beta + fuzz: 1 + - os: windows-latest + toolchain: nightly + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages for fuzzing + if: runner.os == 'Linux' && matrix.fuzz == 1 + run: sudo apt-get update -y && sudo apt-get install -y binutils-dev libunwind8-dev libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc libiberty-dev + + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + + - name: Cargo build + run: cargo build --verbose + + - name: Cargo test + if: matrix.toolchain != '1.36.0' + run: cargo test --verbose + + - name: Cargo test w/ serde + if: matrix.toolchain != '1.36.0' + run: cargo test --verbose --features serde + + - name: Cargo check w/o default features + if: matrix.toolchain == 'nightly' + run: cargo check --verbose --no-default-features + + - name: Cargo test w/ union + if: matrix.toolchain == 'beta' + run: cargo test --verbose --features union + + - name: Cargo test w/ debugger_visualizer + if: matrix.toolchain == 'nightly' + run: cargo test --test debugger_visualizer --verbose --features debugger_visualizer -- --test-threads=1 + + - name: Cargo test w/ debugger_visualizer and union + if: matrix.toolchain == 'nightly' + run: cargo test --test debugger_visualizer --verbose --features 'debugger_visualizer,union' -- --test-threads=1 + + - name: Cargo test all features + if: matrix.toolchain == 'nightly' + run: cargo test --verbose --all-features + + - name: Cargo bench + if: matrix.toolchain == 'nightly' + run: cargo bench --verbose bench + + - name: miri + if: matrix.toolchain == 'nightly' && matrix.os == 'ubuntu-latest' + run: bash ./scripts/run_miri.sh + + - name: fuzz + if: matrix.fuzz == 1 + working-directory: fuzz + run: ./travis-fuzz.sh + + no-std: + name: no_std + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + target: thumbv7m-none-eabi + - name: Cargo build + run: cargo build --verbose + + build_result: + name: Result + runs-on: ubuntu-latest + needs: + - "ci" + - "no-std" + + steps: + - name: Mark the job as successful + run: exit 0 + if: success() + - name: Mark the job as unsuccessful + run: exit 1 + if: "!success()" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/smallvec/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/smallvec/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/smallvec/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/smallvec/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +[package] +name = "smallvec" +version = "1.13.2" +edition = "2018" +authors = ["The Servo Project Developers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/servo/rust-smallvec" +description = "'Small vector' optimization: store up to a small number of items on the stack" +keywords = ["small", "vec", "vector", "stack", "no_std"] +categories = ["data-structures"] +readme = "README.md" +documentation = "https://docs.rs/smallvec/" + +[features] +const_generics = [] +const_new = ["const_generics"] +write = [] +union = [] +specialization = [] +may_dangle = [] +drain_filter = [] +drain_keep_rest = ["drain_filter"] + +# UNSTABLE FEATURES (requires Rust nightly) +# Enable to use the #[debugger_visualizer] attribute. +debugger_visualizer = [] + +[dependencies] +serde = { version = "1", optional = true, default-features = false } +arbitrary = { version = "1", optional = true } + +[dev_dependencies] +bincode = "1.0.1" +debugger_test = "0.1.0" +debugger_test_parser = "0.1.0" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"] + +[[test]] +name = "debugger_visualizer" +path = "tests/debugger_visualizer.rs" +required-features = ["debugger_visualizer"] +# Do not run these tests by default. These tests need to +# be run with the additional rustc flag `--test-threads=1` +# since each test causes a debugger to attach to the current +# test process. If multiple debuggers try to attach at the same +# time, the test will fail. +test = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/spin/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/spin/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"34b35704b01c68214b27cb20f0c4325b3ce6e40ce8fd5aa3d2b884697a27307b","Cargo.lock":"9d6481d9ffe412e6c4d9445d89c0fa3e33a14b61c56aa5c121d9f28656cacfe4","Cargo.toml":"d2a17df2fa85736364744ea8279c6aed7276cabcc63bca2d25667198504e4be7","LICENSE":"6ac8711fb340c62ce0a4ecd463342d3fa0e8e70de697c863a2e1c0c53006003c","README.md":"78f0456ba0f3fa490d2bf38d79c42b293d551a9951da5bef0e1e5043143abf78","benches/mutex.rs":"2fd79239798e88cab0fd982e04f91a44c7c63282f8703d85fbdd81a8a1e71917","examples/debug.rs":"0074651d78f8ed6d6c0274ae832c0d78de6c5c59423936f58e79cb3c98baea2c","script/doc-upload.cfg":"7383ee022197c1dade9a2e6888261def4a80df08ecb72b1b4db47d1e8a6ff8e0","src/barrier.rs":"f8569a601d870a713344747eb355e6d840db510a599709173ebd0ccba5fc4028","src/lazy.rs":"45cf9174ee607e8a9acfa652b95c9b0ac71d98e89e73b9850041c79c5f3a726e","src/lib.rs":"85fa19874da6518e7ccd0d8bd3a0549fba52afd820789797e0221af1ac62196a","src/mutex.rs":"530039838850a0e71f4af42b9a7cffa0f922874e8f00001d36d67876842ed68f","src/mutex/fair.rs":"74cf2a0b8ab8e7a95564d97e8a66fc5d3d2641dd655de56a94ae4a93458f82c3","src/mutex/spin.rs":"a11e42d58e87a195e5e2110b46bda766f5a62a0c0b75a2b163f1ce37745bf337","src/mutex/ticket.rs":"1711bb02de48cf92f950b8f31946d5003225542ab6521333be1f525b76710f26","src/once.rs":"e4289220d505b7a15e8f9fb3f0d032ee57df6a5ee1d50123d4187e1afc6fb98b","src/relax.rs":"919c345bf55c3b2f9a7d9cd4aec2b2b3db68b6dc40ee2e4de4f6f32027abc290","src/rwlock.rs":"ba3b3dd20cdcd97691f042bcdd6d352e52601db7dc0cc7053c01a5873754b196"},"package":"6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/spin/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/spin/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -# Unreleased - -### Added - -### Changed - -### Fixed - -# [0.9.8] - 2023-04-03 - -### Fixed - -- Unsoundness in `Once::try_call_once` caused by an `Err(_)` result - -# [0.9.7] - 2023-03-27 - -### Fixed - -- Relaxed accidentally restricted `Send`/`Sync` bounds for `Mutex` guards - -# [0.9.6] - 2023-03-13 - -### Fixed - -- Relaxed accidentally restricted `Send`/`Sync` bounds for `RwLock` guards - -# [0.9.5] - 2023-02-07 - -### Added - -- `FairMutex`, a new mutex implementation that reduces writer starvation. -- A MSRV policy: Rust 1.38 is currently required - -### Changed - -- The crate's CI now has full MIRI integration, further improving the confidence you can have in the implementation. - -### Fixed - -- Ensured that the crate's abstractions comply with stacked borrows rules. -- Unsoundness in the `RwLock` that could be triggered via a reader overflow -- Relaxed various `Send`/`Sync` bound requirements to make the crate more flexible - -# [0.9.4] - 2022-07-14 - -### Fixed - -- Fixed unsoundness in `RwLock` on reader overflow -- Relaxed `Send`/`Sync` bounds for `SpinMutex` and `TicketMutex` (doesn't affect `Mutex` itself) - -# [0.9.3] - 2022-04-17 - -### Added - -- Implemented `Default` for `Once` -- `Once::try_call_once` - -### Fixed - -- Fixed bug that caused `Once::call_once` to incorrectly fail - -# [0.9.2] - 2021-07-09 - -### Changed - -- Improved `Once` performance by reducing the memory footprint of internal state to one byte - -### Fixed - -- Improved performance of `Once` by relaxing ordering guarantees and removing redundant checks - -# [0.9.1] - 2021-06-21 - -### Added - -- Default type parameter on `Once` for better ergonomics - -# [0.9.0] - 2021-03-18 - -### Changed - -- Placed all major API features behind feature flags - -### Fixed - -- A compilation bug with the `lock_api` feature - -# [0.8.0] - 2021-03-15 - -### Added - -- `Once::get_unchecked` -- `RelaxStrategy` trait with type parameter on all locks to support switching between relax strategies - -### Changed - -- `lock_api1` feature is now named `lock_api` - -# [0.7.1] - 2021-01-12 - -### Fixed - -- Prevented `Once` leaking the inner value upon drop - -# [0.7.0] - 2020-10-18 - -### Added - -- `Once::initialized` -- `Once::get_mut` -- `Once::try_into_inner` -- `Once::poll` -- `RwLock`, `Mutex` and `Once` now implement `From` -- `Lazy` type for lazy initialization -- `TicketMutex`, an alternative mutex implementation -- `std` feature flag to enable thread yielding instead of spinning -- `Mutex::is_locked`/`SpinMutex::is_locked`/`TicketMutex::is_locked` -- `Barrier` - -### Changed - -- `Once::wait` now spins even if initialization has not yet started -- `Guard::leak` is now an associated function instead of a method -- Improved the performance of `SpinMutex` by relaxing unnecessarily conservative - ordering requirements - -# [0.6.0] - 2020-10-08 - -### Added - -- More dynamic `Send`/`Sync` bounds for lock guards -- `lock_api` compatibility -- `Guard::leak` methods -- `RwLock::reader_count` and `RwLock::writer_count` -- `Display` implementation for guard types - -### Changed - -- Made `Debug` impls of lock guards just show the inner type like `std` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/spin/Cargo.lock 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 @@ -1,623 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "ciborium" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" - -[[package]] -name = "ciborium-ll" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "3.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" -dependencies = [ - "bitflags", - "clap_lex", - "indexmap", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap", - "criterion-plot", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - -[[package]] -name = "js-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - -[[package]] -name = "plotters" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" - -[[package]] -name = "plotters-svg" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "portable-atomic" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f602a0d1e09a48e4f8e8b4d4042e32807c3676da31f2ecabeac9f96226ec6c45" - -[[package]] -name = "proc-macro2" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "regex" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.159" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.159" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.13", -] - -[[package]] -name = "serde_json" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "spin" -version = "0.9.8" -dependencies = [ - "criterion", - "lock_api", - "portable-atomic", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "unicode-ident" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" - -[[package]] -name = "web-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/spin/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -rust-version = "1.38" -name = "spin" -version = "0.9.8" -authors = [ - "Mathijs van de Nes ", - "John Ericson ", - "Joshua Barretto ", -] -description = "Spin-based synchronization primitives" -readme = "README.md" -keywords = [ - "spinlock", - "mutex", - "rwlock", -] -license = "MIT" -repository = "https://github.com/mvdnes/spin-rs.git" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", -] - -[[bench]] -name = "mutex" -harness = false -required-features = ["ticket_mutex"] - -[dependencies.lock_api_crate] -version = "0.4" -optional = true -package = "lock_api" - -[dependencies.portable-atomic] -version = "1" -optional = true -default-features = false - -[dev-dependencies.criterion] -version = "0.4" - -[features] -barrier = ["mutex"] -default = [ - "lock_api", - "mutex", - "spin_mutex", - "rwlock", - "once", - "lazy", - "barrier", -] -fair_mutex = ["mutex"] -lazy = ["once"] -lock_api = ["lock_api_crate"] -mutex = [] -once = [] -portable_atomic = ["portable-atomic"] -rwlock = [] -spin_mutex = ["mutex"] -std = [] -ticket_mutex = ["mutex"] -use_ticket_mutex = [ - "mutex", - "ticket_mutex", -] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/spin/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/spin/LICENSE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Mathijs van de Nes - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/README.md clamav-1.4.6+dfsg/.cargo/vendor/spin/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/spin/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -# spin-rs - -[![Crates.io version](https://img.shields.io/crates/v/spin.svg)](https://crates.io/crates/spin) -[![docs.rs](https://docs.rs/spin/badge.svg)](https://docs.rs/spin/) -[![Build Status](https://travis-ci.org/mvdnes/spin-rs.svg)](https://travis-ci.org/mvdnes/spin-rs) - -Spin-based synchronization primitives. - -This crate provides [spin-based](https://en.wikipedia.org/wiki/Spinlock) -versions of the primitives in `std::sync`. Because synchronization is done -through spinning, the primitives are suitable for use in `no_std` environments. - -Before deciding to use `spin`, we recommend reading -[this superb blog post](https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html) -by [@matklad](https://github.com/matklad/) that discusses the pros and cons of -spinlocks. If you have access to `std`, it's likely that the primitives in -`std::sync` will serve you better except in very specific circumstances. - -## Features - -- `Mutex`, `RwLock`, `Once`, `Lazy` and `Barrier` equivalents -- Support for `no_std` environments -- [`lock_api`](https://crates.io/crates/lock_api) compatibility -- Upgradeable `RwLock` guards -- Guards can be sent and shared between threads -- Guard leaking -- Ticket locks -- Different strategies for dealing with contention - -## Usage - -Include the following under the `[dependencies]` section in your `Cargo.toml` file. - -```toml -spin = "x.y" -``` - -## Example - -When calling `lock` on a `Mutex` you will get a guard value that provides access -to the data. When this guard is dropped, the mutex will become available again. - -```rust -extern crate spin; -use std::{sync::Arc, thread}; - -fn main() { - let counter = Arc::new(spin::Mutex::new(0)); - - let thread = thread::spawn({ - let counter = counter.clone(); - move || { - for _ in 0..100 { - *counter.lock() += 1; - } - } - }); - - for _ in 0..100 { - *counter.lock() += 1; - } - - thread.join().unwrap(); - - assert_eq!(*counter.lock(), 200); -} -``` - -## Feature flags - -The crate comes with a few feature flags that you may wish to use. - -- `mutex` enables the `Mutex` type. - -- `spin_mutex` enables the `SpinMutex` type. - -- `ticket_mutex` enables the `TicketMutex` type. - -- `use_ticket_mutex` switches to a ticket lock for the implementation of `Mutex`. This - is recommended only on targets for which ordinary spinning locks perform very badly - because it will change the implementation used by other crates that depend on `spin`. - -- `rwlock` enables the `RwLock` type. - -- `once` enables the `Once` type. - -- `lazy` enables the `Lazy` type. - -- `barrier` enables the `Barrier` type. - -- `lock_api` enables support for [`lock_api`](https://crates.io/crates/lock_api) - -- `std` enables support for thread yielding instead of spinning. - -- `portable_atomic` enables usage of the `portable-atomic` crate - to support platforms without native atomic operations (Cortex-M0, etc.). - The `portable_atomic_unsafe_assume_single_core` cfg or `critical-section` feature - of `portable-atomic` crate must also be set by the final binary crate. - - When using the cfg, this can be done by adapting the following snippet to the `.cargo/config` file: - ``` - [target.] - rustflags = [ "--cfg", "portable_atomic_unsafe_assume_single_core" ] - ``` - Note that this cfg is unsafe by nature, and enabling it for multicore systems is unsound. - - When using the `critical-section` feature, you need to implement the critical-section - implementation that sound for your system by implementing an unsafe trait. - See [the documentation for the `portable-atomic` crate](https://docs.rs/portable-atomic/latest/portable_atomic/#optional-cfg) - for more information. - -## Remarks - -It is often desirable to have a lock shared between threads. Wrapping the lock in an -`std::sync::Arc` is route through which this might be achieved. - -Locks provide zero-overhead access to their data when accessed through a mutable -reference by using their `get_mut` methods. - -The behaviour of these lock is similar to their namesakes in `std::sync`. they -differ on the following: - -- Locks will not be poisoned in case of failure. -- Threads will not yield to the OS scheduler when encounter a lock that cannot be - accessed. Instead, they will 'spin' in a busy loop until the lock becomes available. - -Many of the feature flags listed above are enabled by default. If you're writing a -library, we recommend disabling those that you don't use to avoid increasing compilation -time for your crate's users. You can do this like so: - -``` -[dependencies] -spin = { version = "x.y", default-features = false, features = [...] } -``` - -## Minimum Safe Rust Version (MSRV) - -This crate is guaranteed to compile on a Minimum Safe Rust Version (MSRV) of 1.38.0 and above. -This version will not be changed without a minor version bump. - -## License - -`spin` is distributed under the MIT License, (See `LICENSE`). diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/benches/mutex.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/benches/mutex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/benches/mutex.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/benches/mutex.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -#[macro_use] -extern crate criterion; - -use criterion::{Criterion, Bencher, black_box}; -use std::{ - ops::DerefMut, - sync::Arc, -}; - -trait Mutex: Send + Sync + 'static { - type Guard<'a>: DerefMut where Self: 'a; - fn new(x: T) -> Self; - fn lock(&self) -> Self::Guard<'_>; -} - -impl Mutex for spin::mutex::SpinMutex { - type Guard<'a> = spin::mutex::SpinMutexGuard<'a, T> where Self: 'a; - fn new(x: T) -> Self { spin::mutex::SpinMutex::new(x) } - fn lock(&self) -> Self::Guard<'_> { self.lock() } -} - -impl Mutex for spin::mutex::TicketMutex { - type Guard<'a> = spin::mutex::TicketMutexGuard<'a, T> where Self: 'a; - fn new(x: T) -> Self { spin::mutex::TicketMutex::new(x) } - fn lock(&self) -> Self::Guard<'_> { self.lock() } -} - -impl Mutex for std::sync::Mutex { - type Guard<'a> = std::sync::MutexGuard<'a, T> where Self: 'a; - fn new(x: T) -> Self { std::sync::Mutex::new(x) } - fn lock(&self) -> Self::Guard<'_> { self.lock().unwrap() } -} - -fn gen_create>(b: &mut Bencher) { - b.iter(|| { - let n = black_box(42); - M::new(n) - }); -} - -fn gen_lock_unlock>(b: &mut Bencher) { - let m = M::new(0); - b.iter(|| { - let mut m = m.lock(); - *m = m.wrapping_add(1); - drop(m); - }); -} - -fn gen_lock_unlock_read_contention>(b: &mut Bencher) { - let m = Arc::new(M::new(0)); - let thread = std::thread::spawn({ - let m = m.clone(); - move || { - while Arc::strong_count(&m) > 1 { - for _ in 0..1000 { - black_box(*m.lock()); - } - } - } - }); - b.iter(|| { - let mut m = m.lock(); - *m = m.wrapping_add(1); - drop(m); - }); - drop(m); - thread.join().unwrap(); -} - -fn gen_lock_unlock_write_contention>(b: &mut Bencher) { - let m = Arc::new(M::new(0)); - let thread = std::thread::spawn({ - let m = m.clone(); - move || { - while Arc::strong_count(&m) > 1 { - for _ in 0..1000 { - let mut m = m.lock(); - *m = m.wrapping_add(1); - drop(m); - } - } - } - }); - b.iter(|| { - let mut m = m.lock(); - *m = m.wrapping_add(1); - drop(m); - }); - drop(m); - thread.join().unwrap(); -} - -fn create(b: &mut Criterion) { - b.bench_function("create-spin-spinmutex", |b| gen_create::>(b)); - b.bench_function("create-spin-ticketmutex", |b| gen_create::>(b)); - b.bench_function("create-std", |b| gen_create::>(b)); -} - -fn lock_unlock(b: &mut Criterion) { - b.bench_function("lock_unlock-spin-spinmutex", |b| gen_lock_unlock::>(b)); - b.bench_function("lock_unlock-spin-ticketmutex", |b| gen_lock_unlock::>(b)); - b.bench_function("lock_unlock-std", |b| gen_lock_unlock::>(b)); -} - -fn lock_unlock_read_contention(b: &mut Criterion) { - b.bench_function("lock_unlock_read_contention-spin-spinmutex", |b| gen_lock_unlock_read_contention::>(b)); - b.bench_function("lock_unlock_read_contention-spin-ticketmutex", |b| gen_lock_unlock_read_contention::>(b)); - b.bench_function("lock_unlock_read_contention-std", |b| gen_lock_unlock_read_contention::>(b)); -} - -fn lock_unlock_write_contention(b: &mut Criterion) { - b.bench_function("lock_unlock_write_contention-spin-spinmutex", |b| gen_lock_unlock_write_contention::>(b)); - b.bench_function("lock_unlock_write_contention-spin-ticketmutex", |b| gen_lock_unlock_write_contention::>(b)); - b.bench_function("lock_unlock_write_contention-std", |b| gen_lock_unlock_write_contention::>(b)); -} - -criterion_group!( - mutex, - create, - lock_unlock, - lock_unlock_read_contention, - lock_unlock_write_contention, -); - -criterion_main!(mutex); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/examples/debug.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/examples/debug.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/examples/debug.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/examples/debug.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -extern crate spin; - -fn main() { - let mutex = spin::Mutex::new(42); - println!("{:?}", mutex); - { - let x = mutex.lock(); - println!("{:?}, {:?}", mutex, *x); - } - - let rwlock = spin::RwLock::new(42); - println!("{:?}", rwlock); - { - let x = rwlock.read(); - println!("{:?}, {:?}", rwlock, *x); - } - { - let x = rwlock.write(); - println!("{:?}, {:?}", rwlock, *x); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/script/doc-upload.cfg clamav-1.4.6+dfsg/.cargo/vendor/spin/script/doc-upload.cfg --- clamav-1.4.3+dfsg/.cargo/vendor/spin/script/doc-upload.cfg 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/script/doc-upload.cfg 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -PROJECT_NAME=spin-rs -DOCS_REPO=mvdnes/rust-docs.git -DOC_RUST_VERSION=stable diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/barrier.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/barrier.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/barrier.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/barrier.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,239 +0,0 @@ -//! Synchronization primitive allowing multiple threads to synchronize the -//! beginning of some computation. -//! -//! Implementation adapted from the 'Barrier' type of the standard library. See: -//! -//! -//! Copyright 2014 The Rust Project Developers. See the COPYRIGHT -//! file at the top-level directory of this distribution and at -//! . -//! -//! Licensed under the Apache License, Version 2.0 > or the MIT license -//! >, at your -//! option. This file may not be copied, modified, or distributed -//! except according to those terms. - -use crate::{mutex::Mutex, RelaxStrategy, Spin}; - -/// A primitive that synchronizes the execution of multiple threads. -/// -/// # Example -/// -/// ``` -/// use spin; -/// use std::sync::Arc; -/// use std::thread; -/// -/// let mut handles = Vec::with_capacity(10); -/// let barrier = Arc::new(spin::Barrier::new(10)); -/// for _ in 0..10 { -/// let c = barrier.clone(); -/// // The same messages will be printed together. -/// // You will NOT see any interleaving. -/// handles.push(thread::spawn(move|| { -/// println!("before wait"); -/// c.wait(); -/// println!("after wait"); -/// })); -/// } -/// // Wait for other threads to finish. -/// for handle in handles { -/// handle.join().unwrap(); -/// } -/// ``` -pub struct Barrier { - lock: Mutex, - num_threads: usize, -} - -// The inner state of a double barrier -struct BarrierState { - count: usize, - generation_id: usize, -} - -/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`] -/// have rendezvoused. -/// -/// [`wait`]: struct.Barrier.html#method.wait -/// [`Barrier`]: struct.Barrier.html -/// -/// # Examples -/// -/// ``` -/// use spin; -/// -/// let barrier = spin::Barrier::new(1); -/// let barrier_wait_result = barrier.wait(); -/// ``` -pub struct BarrierWaitResult(bool); - -impl Barrier { - /// Blocks the current thread until all threads have rendezvoused here. - /// - /// Barriers are re-usable after all threads have rendezvoused once, and can - /// be used continuously. - /// - /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that - /// returns `true` from [`is_leader`] when returning from this function, and - /// all other threads will receive a result that will return `false` from - /// [`is_leader`]. - /// - /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html - /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader - /// - /// # Examples - /// - /// ``` - /// use spin; - /// use std::sync::Arc; - /// use std::thread; - /// - /// let mut handles = Vec::with_capacity(10); - /// let barrier = Arc::new(spin::Barrier::new(10)); - /// for _ in 0..10 { - /// let c = barrier.clone(); - /// // The same messages will be printed together. - /// // You will NOT see any interleaving. - /// handles.push(thread::spawn(move|| { - /// println!("before wait"); - /// c.wait(); - /// println!("after wait"); - /// })); - /// } - /// // Wait for other threads to finish. - /// for handle in handles { - /// handle.join().unwrap(); - /// } - /// ``` - pub fn wait(&self) -> BarrierWaitResult { - let mut lock = self.lock.lock(); - lock.count += 1; - - if lock.count < self.num_threads { - // not the leader - let local_gen = lock.generation_id; - - while local_gen == lock.generation_id && lock.count < self.num_threads { - drop(lock); - R::relax(); - lock = self.lock.lock(); - } - BarrierWaitResult(false) - } else { - // this thread is the leader, - // and is responsible for incrementing the generation - lock.count = 0; - lock.generation_id = lock.generation_id.wrapping_add(1); - BarrierWaitResult(true) - } - } -} - -impl Barrier { - /// Creates a new barrier that can block a given number of threads. - /// - /// A barrier will block `n`-1 threads which call [`wait`] and then wake up - /// all threads at once when the `n`th thread calls [`wait`]. A Barrier created - /// with n = 0 will behave identically to one created with n = 1. - /// - /// [`wait`]: #method.wait - /// - /// # Examples - /// - /// ``` - /// use spin; - /// - /// let barrier = spin::Barrier::new(10); - /// ``` - pub const fn new(n: usize) -> Self { - Self { - lock: Mutex::new(BarrierState { - count: 0, - generation_id: 0, - }), - num_threads: n, - } - } -} - -impl BarrierWaitResult { - /// Returns whether this thread from [`wait`] is the "leader thread". - /// - /// Only one thread will have `true` returned from their result, all other - /// threads will have `false` returned. - /// - /// [`wait`]: struct.Barrier.html#method.wait - /// - /// # Examples - /// - /// ``` - /// use spin; - /// - /// let barrier = spin::Barrier::new(1); - /// let barrier_wait_result = barrier.wait(); - /// println!("{:?}", barrier_wait_result.is_leader()); - /// ``` - pub fn is_leader(&self) -> bool { - self.0 - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::mpsc::{channel, TryRecvError}; - use std::sync::Arc; - use std::thread; - - type Barrier = super::Barrier; - - fn use_barrier(n: usize, barrier: Arc) { - let (tx, rx) = channel(); - - let mut ts = Vec::new(); - for _ in 0..n - 1 { - let c = barrier.clone(); - let tx = tx.clone(); - ts.push(thread::spawn(move || { - tx.send(c.wait().is_leader()).unwrap(); - })); - } - - // At this point, all spawned threads should be blocked, - // so we shouldn't get anything from the port - assert!(match rx.try_recv() { - Err(TryRecvError::Empty) => true, - _ => false, - }); - - let mut leader_found = barrier.wait().is_leader(); - - // Now, the barrier is cleared and we should get data. - for _ in 0..n - 1 { - if rx.recv().unwrap() { - assert!(!leader_found); - leader_found = true; - } - } - assert!(leader_found); - - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn test_barrier() { - const N: usize = 10; - - let barrier = Arc::new(Barrier::new(N)); - - use_barrier(N, barrier.clone()); - - // use barrier twice to ensure it is reusable - use_barrier(N, barrier.clone()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/lazy.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lazy.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/lazy.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lazy.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -//! Synchronization primitives for lazy evaluation. -//! -//! Implementation adapted from the `SyncLazy` type of the standard library. See: -//! - -use crate::{once::Once, RelaxStrategy, Spin}; -use core::{cell::Cell, fmt, ops::Deref}; - -/// A value which is initialized on the first access. -/// -/// This type is a thread-safe `Lazy`, and can be used in statics. -/// -/// # Examples -/// -/// ``` -/// use std::collections::HashMap; -/// use spin::Lazy; -/// -/// static HASHMAP: Lazy> = Lazy::new(|| { -/// println!("initializing"); -/// let mut m = HashMap::new(); -/// m.insert(13, "Spica".to_string()); -/// m.insert(74, "Hoyten".to_string()); -/// m -/// }); -/// -/// fn main() { -/// println!("ready"); -/// std::thread::spawn(|| { -/// println!("{:?}", HASHMAP.get(&13)); -/// }).join().unwrap(); -/// println!("{:?}", HASHMAP.get(&74)); -/// -/// // Prints: -/// // ready -/// // initializing -/// // Some("Spica") -/// // Some("Hoyten") -/// } -/// ``` -pub struct Lazy T, R = Spin> { - cell: Once, - init: Cell>, -} - -impl fmt::Debug for Lazy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy") - .field("cell", &self.cell) - .field("init", &"..") - .finish() - } -} - -// We never create a `&F` from a `&Lazy` so it is fine -// to not impl `Sync` for `F` -// we do create a `&mut Option` in `force`, but this is -// properly synchronized, so it only happens once -// so it also does not contribute to this impl. -unsafe impl Sync for Lazy where Once: Sync {} -// auto-derived `Send` impl is OK. - -impl Lazy { - /// Creates a new lazy value with the given initializing - /// function. - pub const fn new(f: F) -> Self { - Self { - cell: Once::new(), - init: Cell::new(Some(f)), - } - } - /// Retrieves a mutable pointer to the inner data. - /// - /// This is especially useful when interfacing with low level code or FFI where the caller - /// explicitly knows that it has exclusive access to the inner data. Note that reading from - /// this pointer is UB until initialized or directly written to. - pub fn as_mut_ptr(&self) -> *mut T { - self.cell.as_mut_ptr() - } -} - -impl T, R: RelaxStrategy> Lazy { - /// Forces the evaluation of this lazy value and - /// returns a reference to result. This is equivalent - /// to the `Deref` impl, but is explicit. - /// - /// # Examples - /// - /// ``` - /// use spin::Lazy; - /// - /// let lazy = Lazy::new(|| 92); - /// - /// assert_eq!(Lazy::force(&lazy), &92); - /// assert_eq!(&*lazy, &92); - /// ``` - pub fn force(this: &Self) -> &T { - this.cell.call_once(|| match this.init.take() { - Some(f) => f(), - None => panic!("Lazy instance has previously been poisoned"), - }) - } -} - -impl T, R: RelaxStrategy> Deref for Lazy { - type Target = T; - - fn deref(&self) -> &T { - Self::force(self) - } -} - -impl Default for Lazy T, R> { - /// Creates a new lazy value using `Default` as the initializing function. - fn default() -> Self { - Self::new(T::default) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![deny(missing_docs)] - -//! This crate provides [spin-based](https://en.wikipedia.org/wiki/Spinlock) versions of the -//! primitives in `std::sync` and `std::lazy`. Because synchronization is done through spinning, -//! the primitives are suitable for use in `no_std` environments. -//! -//! # Features -//! -//! - `Mutex`, `RwLock`, `Once`/`SyncOnceCell`, and `SyncLazy` equivalents -//! -//! - Support for `no_std` environments -//! -//! - [`lock_api`](https://crates.io/crates/lock_api) compatibility -//! -//! - Upgradeable `RwLock` guards -//! -//! - Guards can be sent and shared between threads -//! -//! - Guard leaking -//! -//! - Ticket locks -//! -//! - Different strategies for dealing with contention -//! -//! # Relationship with `std::sync` -//! -//! While `spin` is not a drop-in replacement for `std::sync` (and -//! [should not be considered as such](https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html)) -//! an effort is made to keep this crate reasonably consistent with `std::sync`. -//! -//! Many of the types defined in this crate have 'additional capabilities' when compared to `std::sync`: -//! -//! - Because spinning does not depend on the thread-driven model of `std::sync`, guards ([`MutexGuard`], -//! [`RwLockReadGuard`], [`RwLockWriteGuard`], etc.) may be sent and shared between threads. -//! -//! - [`RwLockUpgradableGuard`] supports being upgraded into a [`RwLockWriteGuard`]. -//! -//! - Guards support [leaking](https://doc.rust-lang.org/nomicon/leaking.html). -//! -//! - [`Once`] owns the value returned by its `call_once` initializer. -//! -//! - [`RwLock`] supports counting readers and writers. -//! -//! Conversely, the types in this crate do not have some of the features `std::sync` has: -//! -//! - Locks do not track [panic poisoning](https://doc.rust-lang.org/nomicon/poisoning.html). -//! -//! ## Feature flags -//! -//! The crate comes with a few feature flags that you may wish to use. -//! -//! - `lock_api` enables support for [`lock_api`](https://crates.io/crates/lock_api) -//! -//! - `ticket_mutex` uses a ticket lock for the implementation of `Mutex` -//! -//! - `fair_mutex` enables a fairer implementation of `Mutex` that uses eventual fairness to avoid -//! starvation -//! -//! - `std` enables support for thread yielding instead of spinning - -#[cfg(any(test, feature = "std"))] -extern crate core; - -#[cfg(feature = "portable_atomic")] -extern crate portable_atomic; - -#[cfg(not(feature = "portable_atomic"))] -use core::sync::atomic; -#[cfg(feature = "portable_atomic")] -use portable_atomic as atomic; - -#[cfg(feature = "barrier")] -#[cfg_attr(docsrs, doc(cfg(feature = "barrier")))] -pub mod barrier; -#[cfg(feature = "lazy")] -#[cfg_attr(docsrs, doc(cfg(feature = "lazy")))] -pub mod lazy; -#[cfg(feature = "mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "mutex")))] -pub mod mutex; -#[cfg(feature = "once")] -#[cfg_attr(docsrs, doc(cfg(feature = "once")))] -pub mod once; -pub mod relax; -#[cfg(feature = "rwlock")] -#[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] -pub mod rwlock; - -#[cfg(feature = "mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "mutex")))] -pub use mutex::MutexGuard; -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub use relax::Yield; -pub use relax::{RelaxStrategy, Spin}; -#[cfg(feature = "rwlock")] -#[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] -pub use rwlock::RwLockReadGuard; - -// Avoid confusing inference errors by aliasing away the relax strategy parameter. Users that need to use a different -// relax strategy can do so by accessing the types through their fully-qualified path. This is a little bit horrible -// but sadly adding a default type parameter is *still* a breaking change in Rust (for understandable reasons). - -/// A primitive that synchronizes the execution of multiple threads. See [`barrier::Barrier`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "barrier")] -#[cfg_attr(docsrs, doc(cfg(feature = "barrier")))] -pub type Barrier = crate::barrier::Barrier; - -/// A value which is initialized on the first access. See [`lazy::Lazy`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "lazy")] -#[cfg_attr(docsrs, doc(cfg(feature = "lazy")))] -pub type Lazy T> = crate::lazy::Lazy; - -/// A primitive that synchronizes the execution of multiple threads. See [`mutex::Mutex`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "mutex")))] -pub type Mutex = crate::mutex::Mutex; - -/// A primitive that provides lazy one-time initialization. See [`once::Once`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "once")] -#[cfg_attr(docsrs, doc(cfg(feature = "once")))] -pub type Once = crate::once::Once; - -/// A lock that provides data access to either one writer or many readers. See [`rwlock::RwLock`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "rwlock")] -#[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] -pub type RwLock = crate::rwlock::RwLock; - -/// A guard that provides immutable data access but can be upgraded to [`RwLockWriteGuard`]. See -/// [`rwlock::RwLockUpgradableGuard`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "rwlock")] -#[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] -pub type RwLockUpgradableGuard<'a, T> = crate::rwlock::RwLockUpgradableGuard<'a, T>; - -/// A guard that provides mutable data access. See [`rwlock::RwLockWriteGuard`] for documentation. -/// -/// A note for advanced users: this alias exists to avoid subtle type inference errors due to the default relax -/// strategy type parameter. If you need a non-default relax strategy, use the fully-qualified path. -#[cfg(feature = "rwlock")] -#[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] -pub type RwLockWriteGuard<'a, T> = crate::rwlock::RwLockWriteGuard<'a, T>; - -/// Spin synchronisation primitives, but compatible with [`lock_api`](https://crates.io/crates/lock_api). -#[cfg(feature = "lock_api")] -#[cfg_attr(docsrs, doc(cfg(feature = "lock_api")))] -pub mod lock_api { - /// A lock that provides mutually exclusive data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "mutex")] - #[cfg_attr(docsrs, doc(cfg(feature = "mutex")))] - pub type Mutex = lock_api_crate::Mutex, T>; - - /// A guard that provides mutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "mutex")] - #[cfg_attr(docsrs, doc(cfg(feature = "mutex")))] - pub type MutexGuard<'a, T> = lock_api_crate::MutexGuard<'a, crate::Mutex<()>, T>; - - /// A lock that provides data access to either one writer or many readers (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "rwlock")] - #[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] - pub type RwLock = lock_api_crate::RwLock, T>; - - /// A guard that provides immutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "rwlock")] - #[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] - pub type RwLockReadGuard<'a, T> = lock_api_crate::RwLockReadGuard<'a, crate::RwLock<()>, T>; - - /// A guard that provides mutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "rwlock")] - #[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] - pub type RwLockWriteGuard<'a, T> = lock_api_crate::RwLockWriteGuard<'a, crate::RwLock<()>, T>; - - /// A guard that provides immutable data access but can be upgraded to [`RwLockWriteGuard`] (compatible with [`lock_api`](https://crates.io/crates/lock_api)). - #[cfg(feature = "rwlock")] - #[cfg_attr(docsrs, doc(cfg(feature = "rwlock")))] - pub type RwLockUpgradableReadGuard<'a, T> = - lock_api_crate::RwLockUpgradableReadGuard<'a, crate::RwLock<()>, T>; -} - -/// In the event of an invalid operation, it's best to abort the current process. -#[cfg(feature = "fair_mutex")] -fn abort() -> ! { - #[cfg(not(feature = "std"))] - { - // Panicking while panicking is defined by Rust to result in an abort. - struct Panic; - - impl Drop for Panic { - fn drop(&mut self) { - panic!("aborting due to invalid operation"); - } - } - - let _panic = Panic; - panic!("aborting due to invalid operation"); - } - - #[cfg(feature = "std")] - { - std::process::abort(); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/fair.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/fair.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/fair.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/fair.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,735 +0,0 @@ -//! A spinning mutex with a fairer unlock algorithm. -//! -//! This mutex is similar to the `SpinMutex` in that it uses spinning to avoid -//! context switches. However, it uses a fairer unlock algorithm that avoids -//! starvation of threads that are waiting for the lock. - -use crate::{ - atomic::{AtomicUsize, Ordering}, - RelaxStrategy, Spin, -}; -use core::{ - cell::UnsafeCell, - fmt, - marker::PhantomData, - mem::ManuallyDrop, - ops::{Deref, DerefMut}, -}; - -// The lowest bit of `lock` is used to indicate whether the mutex is locked or not. The rest of the bits are used to -// store the number of starving threads. -const LOCKED: usize = 1; -const STARVED: usize = 2; - -/// Number chosen by fair roll of the dice, adjust as needed. -const STARVATION_SPINS: usize = 1024; - -/// A [spin lock](https://en.m.wikipedia.org/wiki/Spinlock) providing mutually exclusive access to data, but with a fairer -/// algorithm. -/// -/// # Example -/// -/// ``` -/// use spin; -/// -/// let lock = spin::mutex::FairMutex::<_>::new(0); -/// -/// // Modify the data -/// *lock.lock() = 2; -/// -/// // Read the data -/// let answer = *lock.lock(); -/// assert_eq!(answer, 2); -/// ``` -/// -/// # Thread safety example -/// -/// ``` -/// use spin; -/// use std::sync::{Arc, Barrier}; -/// -/// let thread_count = 1000; -/// let spin_mutex = Arc::new(spin::mutex::FairMutex::<_>::new(0)); -/// -/// // We use a barrier to ensure the readout happens after all writing -/// let barrier = Arc::new(Barrier::new(thread_count + 1)); -/// -/// for _ in (0..thread_count) { -/// let my_barrier = barrier.clone(); -/// let my_lock = spin_mutex.clone(); -/// std::thread::spawn(move || { -/// let mut guard = my_lock.lock(); -/// *guard += 1; -/// -/// // Release the lock to prevent a deadlock -/// drop(guard); -/// my_barrier.wait(); -/// }); -/// } -/// -/// barrier.wait(); -/// -/// let answer = { *spin_mutex.lock() }; -/// assert_eq!(answer, thread_count); -/// ``` -pub struct FairMutex { - phantom: PhantomData, - pub(crate) lock: AtomicUsize, - data: UnsafeCell, -} - -/// A guard that provides mutable data access. -/// -/// When the guard falls out of scope it will release the lock. -pub struct FairMutexGuard<'a, T: ?Sized + 'a> { - lock: &'a AtomicUsize, - data: *mut T, -} - -/// A handle that indicates that we have been trying to acquire the lock for a while. -/// -/// This handle is used to prevent starvation. -pub struct Starvation<'a, T: ?Sized + 'a, R> { - lock: &'a FairMutex, -} - -/// Indicates whether a lock was rejected due to the lock being held by another thread or due to starvation. -#[derive(Debug)] -pub enum LockRejectReason { - /// The lock was rejected due to the lock being held by another thread. - Locked, - - /// The lock was rejected due to starvation. - Starved, -} - -// Same unsafe impls as `std::sync::Mutex` -unsafe impl Sync for FairMutex {} -unsafe impl Send for FairMutex {} - -unsafe impl Sync for FairMutexGuard<'_, T> {} -unsafe impl Send for FairMutexGuard<'_, T> {} - -impl FairMutex { - /// Creates a new [`FairMutex`] wrapping the supplied data. - /// - /// # Example - /// - /// ``` - /// use spin::mutex::FairMutex; - /// - /// static MUTEX: FairMutex<()> = FairMutex::<_>::new(()); - /// - /// fn demo() { - /// let lock = MUTEX.lock(); - /// // do something with lock - /// drop(lock); - /// } - /// ``` - #[inline(always)] - pub const fn new(data: T) -> Self { - FairMutex { - lock: AtomicUsize::new(0), - data: UnsafeCell::new(data), - phantom: PhantomData, - } - } - - /// Consumes this [`FairMutex`] and unwraps the underlying data. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(42); - /// assert_eq!(42, lock.into_inner()); - /// ``` - #[inline(always)] - pub fn into_inner(self) -> T { - // We know statically that there are no outstanding references to - // `self` so there's no need to lock. - let FairMutex { data, .. } = self; - data.into_inner() - } - - /// Returns a mutable pointer to the underlying data. - /// - /// This is mostly meant to be used for applications which require manual unlocking, but where - /// storing both the lock and the pointer to the inner data gets inefficient. - /// - /// # Example - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(42); - /// - /// unsafe { - /// core::mem::forget(lock.lock()); - /// - /// assert_eq!(lock.as_mut_ptr().read(), 42); - /// lock.as_mut_ptr().write(58); - /// - /// lock.force_unlock(); - /// } - /// - /// assert_eq!(*lock.lock(), 58); - /// - /// ``` - #[inline(always)] - pub fn as_mut_ptr(&self) -> *mut T { - self.data.get() - } -} - -impl FairMutex { - /// Locks the [`FairMutex`] and returns a guard that permits access to the inner data. - /// - /// The returned value may be dereferenced for data access - /// and the lock will be dropped when the guard falls out of scope. - /// - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(0); - /// { - /// let mut data = lock.lock(); - /// // The lock is now locked and the data can be accessed - /// *data += 1; - /// // The lock is implicitly dropped at the end of the scope - /// } - /// ``` - #[inline(always)] - pub fn lock(&self) -> FairMutexGuard { - // Can fail to lock even if the spinlock is not locked. May be more efficient than `try_lock` - // when called in a loop. - let mut spins = 0; - while self - .lock - .compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed) - .is_err() - { - // Wait until the lock looks unlocked before retrying - while self.is_locked() { - R::relax(); - - // If we've been spinning for a while, switch to a fairer strategy that will prevent - // newer users from stealing our lock from us. - if spins > STARVATION_SPINS { - return self.starve().lock(); - } - spins += 1; - } - } - - FairMutexGuard { - lock: &self.lock, - data: unsafe { &mut *self.data.get() }, - } - } -} - -impl FairMutex { - /// Returns `true` if the lock is currently held. - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - #[inline(always)] - pub fn is_locked(&self) -> bool { - self.lock.load(Ordering::Relaxed) & LOCKED != 0 - } - - /// Force unlock this [`FairMutex`]. - /// - /// # Safety - /// - /// This is *extremely* unsafe if the lock is not held by the current - /// thread. However, this can be useful in some instances for exposing the - /// lock to FFI that doesn't know how to deal with RAII. - #[inline(always)] - pub unsafe fn force_unlock(&self) { - self.lock.fetch_and(!LOCKED, Ordering::Release); - } - - /// Try to lock this [`FairMutex`], returning a lock guard if successful. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(42); - /// - /// let maybe_guard = lock.try_lock(); - /// assert!(maybe_guard.is_some()); - /// - /// // `maybe_guard` is still held, so the second call fails - /// let maybe_guard2 = lock.try_lock(); - /// assert!(maybe_guard2.is_none()); - /// ``` - #[inline(always)] - pub fn try_lock(&self) -> Option> { - self.try_lock_starver().ok() - } - - /// Tries to lock this [`FairMutex`] and returns a result that indicates whether the lock was - /// rejected due to a starver or not. - #[inline(always)] - pub fn try_lock_starver(&self) -> Result, LockRejectReason> { - match self - .lock - .compare_exchange(0, LOCKED, Ordering::Acquire, Ordering::Relaxed) - .unwrap_or_else(|x| x) - { - 0 => Ok(FairMutexGuard { - lock: &self.lock, - data: unsafe { &mut *self.data.get() }, - }), - LOCKED => Err(LockRejectReason::Locked), - _ => Err(LockRejectReason::Starved), - } - } - - /// Indicates that the current user has been waiting for the lock for a while - /// and that the lock should yield to this thread over a newly arriving thread. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(42); - /// - /// // Lock the mutex to simulate it being used by another user. - /// let guard1 = lock.lock(); - /// - /// // Try to lock the mutex. - /// let guard2 = lock.try_lock(); - /// assert!(guard2.is_none()); - /// - /// // Wait for a while. - /// wait_for_a_while(); - /// - /// // We are now starved, indicate as such. - /// let starve = lock.starve(); - /// - /// // Once the lock is released, another user trying to lock it will - /// // fail. - /// drop(guard1); - /// let guard3 = lock.try_lock(); - /// assert!(guard3.is_none()); - /// - /// // However, we will be able to lock it. - /// let guard4 = starve.try_lock(); - /// assert!(guard4.is_ok()); - /// - /// # fn wait_for_a_while() {} - /// ``` - pub fn starve(&self) -> Starvation<'_, T, R> { - // Add a new starver to the state. - if self.lock.fetch_add(STARVED, Ordering::Relaxed) > (core::isize::MAX - 1) as usize { - // In the event of a potential lock overflow, abort. - crate::abort(); - } - - Starvation { lock: self } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the [`FairMutex`] mutably, and a mutable reference is guaranteed to be exclusive in - /// Rust, no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As - /// such, this is a 'zero-cost' operation. - /// - /// # Example - /// - /// ``` - /// let mut lock = spin::mutex::FairMutex::<_>::new(0); - /// *lock.get_mut() = 10; - /// assert_eq!(*lock.lock(), 10); - /// ``` - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - // We know statically that there are no other references to `self`, so - // there's no need to lock the inner mutex. - unsafe { &mut *self.data.get() } - } -} - -impl fmt::Debug for FairMutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - struct LockWrapper<'a, T: ?Sized + fmt::Debug>(Option>); - - impl fmt::Debug for LockWrapper<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match &self.0 { - Some(guard) => fmt::Debug::fmt(guard, f), - None => f.write_str(""), - } - } - } - - f.debug_struct("FairMutex") - .field("data", &LockWrapper(self.try_lock())) - .finish() - } -} - -impl Default for FairMutex { - fn default() -> Self { - Self::new(Default::default()) - } -} - -impl From for FairMutex { - fn from(data: T) -> Self { - Self::new(data) - } -} - -impl<'a, T: ?Sized> FairMutexGuard<'a, T> { - /// Leak the lock guard, yielding a mutable reference to the underlying data. - /// - /// Note that this function will permanently lock the original [`FairMutex`]. - /// - /// ``` - /// let mylock = spin::mutex::FairMutex::<_>::new(0); - /// - /// let data: &mut i32 = spin::mutex::FairMutexGuard::leak(mylock.lock()); - /// - /// *data = 1; - /// assert_eq!(*data, 1); - /// ``` - #[inline(always)] - pub fn leak(this: Self) -> &'a mut T { - // Use ManuallyDrop to avoid stacked-borrow invalidation - let mut this = ManuallyDrop::new(this); - // We know statically that only we are referencing data - unsafe { &mut *this.data } - } -} - -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for FairMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized + fmt::Display> fmt::Display for FairMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized> Deref for FairMutexGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - // We know statically that only we are referencing data - unsafe { &*self.data } - } -} - -impl<'a, T: ?Sized> DerefMut for FairMutexGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { - // We know statically that only we are referencing data - unsafe { &mut *self.data } - } -} - -impl<'a, T: ?Sized> Drop for FairMutexGuard<'a, T> { - /// The dropping of the MutexGuard will release the lock it was created from. - fn drop(&mut self) { - self.lock.fetch_and(!LOCKED, Ordering::Release); - } -} - -impl<'a, T: ?Sized, R> Starvation<'a, T, R> { - /// Attempts the lock the mutex if we are the only starving user. - /// - /// This allows another user to lock the mutex if they are starving as well. - pub fn try_lock_fair(self) -> Result, Self> { - // Try to lock the mutex. - if self - .lock - .lock - .compare_exchange( - STARVED, - STARVED | LOCKED, - Ordering::Acquire, - Ordering::Relaxed, - ) - .is_ok() - { - // We are the only starving user, lock the mutex. - Ok(FairMutexGuard { - lock: &self.lock.lock, - data: self.lock.data.get(), - }) - } else { - // Another user is starving, fail. - Err(self) - } - } - - /// Attempts to lock the mutex. - /// - /// If the lock is currently held by another thread, this will return `None`. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::FairMutex::<_>::new(42); - /// - /// // Lock the mutex to simulate it being used by another user. - /// let guard1 = lock.lock(); - /// - /// // Try to lock the mutex. - /// let guard2 = lock.try_lock(); - /// assert!(guard2.is_none()); - /// - /// // Wait for a while. - /// wait_for_a_while(); - /// - /// // We are now starved, indicate as such. - /// let starve = lock.starve(); - /// - /// // Once the lock is released, another user trying to lock it will - /// // fail. - /// drop(guard1); - /// let guard3 = lock.try_lock(); - /// assert!(guard3.is_none()); - /// - /// // However, we will be able to lock it. - /// let guard4 = starve.try_lock(); - /// assert!(guard4.is_ok()); - /// - /// # fn wait_for_a_while() {} - /// ``` - pub fn try_lock(self) -> Result, Self> { - // Try to lock the mutex. - if self.lock.lock.fetch_or(LOCKED, Ordering::Acquire) & LOCKED == 0 { - // We have successfully locked the mutex. - // By dropping `self` here, we decrement the starvation count. - Ok(FairMutexGuard { - lock: &self.lock.lock, - data: self.lock.data.get(), - }) - } else { - Err(self) - } - } -} - -impl<'a, T: ?Sized, R: RelaxStrategy> Starvation<'a, T, R> { - /// Locks the mutex. - pub fn lock(mut self) -> FairMutexGuard<'a, T> { - // Try to lock the mutex. - loop { - match self.try_lock() { - Ok(lock) => return lock, - Err(starve) => self = starve, - } - - // Relax until the lock is released. - while self.lock.is_locked() { - R::relax(); - } - } - } -} - -impl<'a, T: ?Sized, R> Drop for Starvation<'a, T, R> { - fn drop(&mut self) { - // As there is no longer a user being starved, we decrement the starver count. - self.lock.lock.fetch_sub(STARVED, Ordering::Release); - } -} - -impl fmt::Display for LockRejectReason { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - LockRejectReason::Locked => write!(f, "locked"), - LockRejectReason::Starved => write!(f, "starved"), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for LockRejectReason {} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawMutex for FairMutex<(), R> { - type GuardMarker = lock_api_crate::GuardSend; - - const INIT: Self = Self::new(()); - - fn lock(&self) { - // Prevent guard destructor running - core::mem::forget(Self::lock(self)); - } - - fn try_lock(&self) -> bool { - // Prevent guard destructor running - Self::try_lock(self).map(core::mem::forget).is_some() - } - - unsafe fn unlock(&self) { - self.force_unlock(); - } - - fn is_locked(&self) -> bool { - Self::is_locked(self) - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::mpsc::channel; - use std::sync::Arc; - use std::thread; - - type FairMutex = super::FairMutex; - - #[derive(Eq, PartialEq, Debug)] - struct NonCopy(i32); - - #[test] - fn smoke() { - let m = FairMutex::<_>::new(()); - drop(m.lock()); - drop(m.lock()); - } - - #[test] - fn lots_and_lots() { - static M: FairMutex<()> = FairMutex::<_>::new(()); - static mut CNT: u32 = 0; - const J: u32 = 1000; - const K: u32 = 3; - - fn inc() { - for _ in 0..J { - unsafe { - let _g = M.lock(); - CNT += 1; - } - } - } - - let (tx, rx) = channel(); - for _ in 0..K { - let tx2 = tx.clone(); - thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - }); - let tx2 = tx.clone(); - thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - }); - } - - drop(tx); - for _ in 0..2 * K { - rx.recv().unwrap(); - } - assert_eq!(unsafe { CNT }, J * K * 2); - } - - #[test] - fn try_lock() { - let mutex = FairMutex::<_>::new(42); - - // First lock succeeds - let a = mutex.try_lock(); - assert_eq!(a.as_ref().map(|r| **r), Some(42)); - - // Additional lock fails - let b = mutex.try_lock(); - assert!(b.is_none()); - - // After dropping lock, it succeeds again - ::core::mem::drop(a); - let c = mutex.try_lock(); - assert_eq!(c.as_ref().map(|r| **r), Some(42)); - } - - #[test] - fn test_into_inner() { - let m = FairMutex::<_>::new(NonCopy(10)); - assert_eq!(m.into_inner(), NonCopy(10)); - } - - #[test] - fn test_into_inner_drop() { - struct Foo(Arc); - impl Drop for Foo { - fn drop(&mut self) { - self.0.fetch_add(1, Ordering::SeqCst); - } - } - let num_drops = Arc::new(AtomicUsize::new(0)); - let m = FairMutex::<_>::new(Foo(num_drops.clone())); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - { - let _inner = m.into_inner(); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - } - assert_eq!(num_drops.load(Ordering::SeqCst), 1); - } - - #[test] - fn test_mutex_arc_nested() { - // Tests nested mutexes and access - // to underlying data. - let arc = Arc::new(FairMutex::<_>::new(1)); - let arc2 = Arc::new(FairMutex::<_>::new(arc)); - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - let lock = arc2.lock(); - let lock2 = lock.lock(); - assert_eq!(*lock2, 1); - tx.send(()).unwrap(); - }); - rx.recv().unwrap(); - } - - #[test] - fn test_mutex_arc_access_in_unwind() { - let arc = Arc::new(FairMutex::<_>::new(1)); - let arc2 = arc.clone(); - let _ = thread::spawn(move || -> () { - struct Unwinder { - i: Arc>, - } - impl Drop for Unwinder { - fn drop(&mut self) { - *self.i.lock() += 1; - } - } - let _u = Unwinder { i: arc2 }; - panic!(); - }) - .join(); - let lock = arc.lock(); - assert_eq!(*lock, 2); - } - - #[test] - fn test_mutex_unsized() { - let mutex: &FairMutex<[i32]> = &FairMutex::<_>::new([1, 2, 3]); - { - let b = &mut *mutex.lock(); - b[0] = 4; - b[2] = 5; - } - let comp: &[i32] = &[4, 2, 5]; - assert_eq!(&*mutex.lock(), comp); - } - - #[test] - fn test_mutex_force_lock() { - let lock = FairMutex::<_>::new(()); - ::std::mem::forget(lock.lock()); - unsafe { - lock.force_unlock(); - } - assert!(lock.try_lock().is_some()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/spin.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/spin.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/spin.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/spin.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,543 +0,0 @@ -//! A naïve spinning mutex. -//! -//! Waiting threads hammer an atomic variable until it becomes available. Best-case latency is low, but worst-case -//! latency is theoretically infinite. - -use crate::{ - atomic::{AtomicBool, Ordering}, - RelaxStrategy, Spin, -}; -use core::{ - cell::UnsafeCell, - fmt, - marker::PhantomData, - mem::ManuallyDrop, - ops::{Deref, DerefMut}, -}; - -/// A [spin lock](https://en.m.wikipedia.org/wiki/Spinlock) providing mutually exclusive access to data. -/// -/// # Example -/// -/// ``` -/// use spin; -/// -/// let lock = spin::mutex::SpinMutex::<_>::new(0); -/// -/// // Modify the data -/// *lock.lock() = 2; -/// -/// // Read the data -/// let answer = *lock.lock(); -/// assert_eq!(answer, 2); -/// ``` -/// -/// # Thread safety example -/// -/// ``` -/// use spin; -/// use std::sync::{Arc, Barrier}; -/// -/// let thread_count = 1000; -/// let spin_mutex = Arc::new(spin::mutex::SpinMutex::<_>::new(0)); -/// -/// // We use a barrier to ensure the readout happens after all writing -/// let barrier = Arc::new(Barrier::new(thread_count + 1)); -/// -/// # let mut ts = Vec::new(); -/// for _ in (0..thread_count) { -/// let my_barrier = barrier.clone(); -/// let my_lock = spin_mutex.clone(); -/// # let t = -/// std::thread::spawn(move || { -/// let mut guard = my_lock.lock(); -/// *guard += 1; -/// -/// // Release the lock to prevent a deadlock -/// drop(guard); -/// my_barrier.wait(); -/// }); -/// # ts.push(t); -/// } -/// -/// barrier.wait(); -/// -/// let answer = { *spin_mutex.lock() }; -/// assert_eq!(answer, thread_count); -/// -/// # for t in ts { -/// # t.join().unwrap(); -/// # } -/// ``` -pub struct SpinMutex { - phantom: PhantomData, - pub(crate) lock: AtomicBool, - data: UnsafeCell, -} - -/// A guard that provides mutable data access. -/// -/// When the guard falls out of scope it will release the lock. -pub struct SpinMutexGuard<'a, T: ?Sized + 'a> { - lock: &'a AtomicBool, - data: *mut T, -} - -// Same unsafe impls as `std::sync::Mutex` -unsafe impl Sync for SpinMutex {} -unsafe impl Send for SpinMutex {} - -unsafe impl Sync for SpinMutexGuard<'_, T> {} -unsafe impl Send for SpinMutexGuard<'_, T> {} - -impl SpinMutex { - /// Creates a new [`SpinMutex`] wrapping the supplied data. - /// - /// # Example - /// - /// ``` - /// use spin::mutex::SpinMutex; - /// - /// static MUTEX: SpinMutex<()> = SpinMutex::<_>::new(()); - /// - /// fn demo() { - /// let lock = MUTEX.lock(); - /// // do something with lock - /// drop(lock); - /// } - /// ``` - #[inline(always)] - pub const fn new(data: T) -> Self { - SpinMutex { - lock: AtomicBool::new(false), - data: UnsafeCell::new(data), - phantom: PhantomData, - } - } - - /// Consumes this [`SpinMutex`] and unwraps the underlying data. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::SpinMutex::<_>::new(42); - /// assert_eq!(42, lock.into_inner()); - /// ``` - #[inline(always)] - pub fn into_inner(self) -> T { - // We know statically that there are no outstanding references to - // `self` so there's no need to lock. - let SpinMutex { data, .. } = self; - data.into_inner() - } - - /// Returns a mutable pointer to the underlying data. - /// - /// This is mostly meant to be used for applications which require manual unlocking, but where - /// storing both the lock and the pointer to the inner data gets inefficient. - /// - /// # Example - /// ``` - /// let lock = spin::mutex::SpinMutex::<_>::new(42); - /// - /// unsafe { - /// core::mem::forget(lock.lock()); - /// - /// assert_eq!(lock.as_mut_ptr().read(), 42); - /// lock.as_mut_ptr().write(58); - /// - /// lock.force_unlock(); - /// } - /// - /// assert_eq!(*lock.lock(), 58); - /// - /// ``` - #[inline(always)] - pub fn as_mut_ptr(&self) -> *mut T { - self.data.get() - } -} - -impl SpinMutex { - /// Locks the [`SpinMutex`] and returns a guard that permits access to the inner data. - /// - /// The returned value may be dereferenced for data access - /// and the lock will be dropped when the guard falls out of scope. - /// - /// ``` - /// let lock = spin::mutex::SpinMutex::<_>::new(0); - /// { - /// let mut data = lock.lock(); - /// // The lock is now locked and the data can be accessed - /// *data += 1; - /// // The lock is implicitly dropped at the end of the scope - /// } - /// ``` - #[inline(always)] - pub fn lock(&self) -> SpinMutexGuard { - // Can fail to lock even if the spinlock is not locked. May be more efficient than `try_lock` - // when called in a loop. - while self - .lock - .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) - .is_err() - { - // Wait until the lock looks unlocked before retrying - while self.is_locked() { - R::relax(); - } - } - - SpinMutexGuard { - lock: &self.lock, - data: unsafe { &mut *self.data.get() }, - } - } -} - -impl SpinMutex { - /// Returns `true` if the lock is currently held. - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - #[inline(always)] - pub fn is_locked(&self) -> bool { - self.lock.load(Ordering::Relaxed) - } - - /// Force unlock this [`SpinMutex`]. - /// - /// # Safety - /// - /// This is *extremely* unsafe if the lock is not held by the current - /// thread. However, this can be useful in some instances for exposing the - /// lock to FFI that doesn't know how to deal with RAII. - #[inline(always)] - pub unsafe fn force_unlock(&self) { - self.lock.store(false, Ordering::Release); - } - - /// Try to lock this [`SpinMutex`], returning a lock guard if successful. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::SpinMutex::<_>::new(42); - /// - /// let maybe_guard = lock.try_lock(); - /// assert!(maybe_guard.is_some()); - /// - /// // `maybe_guard` is still held, so the second call fails - /// let maybe_guard2 = lock.try_lock(); - /// assert!(maybe_guard2.is_none()); - /// ``` - #[inline(always)] - pub fn try_lock(&self) -> Option> { - // The reason for using a strong compare_exchange is explained here: - // https://github.com/Amanieu/parking_lot/pull/207#issuecomment-575869107 - if self - .lock - .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) - .is_ok() - { - Some(SpinMutexGuard { - lock: &self.lock, - data: unsafe { &mut *self.data.get() }, - }) - } else { - None - } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the [`SpinMutex`] mutably, and a mutable reference is guaranteed to be exclusive in - /// Rust, no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As - /// such, this is a 'zero-cost' operation. - /// - /// # Example - /// - /// ``` - /// let mut lock = spin::mutex::SpinMutex::<_>::new(0); - /// *lock.get_mut() = 10; - /// assert_eq!(*lock.lock(), 10); - /// ``` - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - // We know statically that there are no other references to `self`, so - // there's no need to lock the inner mutex. - unsafe { &mut *self.data.get() } - } -} - -impl fmt::Debug for SpinMutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.try_lock() { - Some(guard) => write!(f, "Mutex {{ data: ") - .and_then(|()| (&*guard).fmt(f)) - .and_then(|()| write!(f, "}}")), - None => write!(f, "Mutex {{ }}"), - } - } -} - -impl Default for SpinMutex { - fn default() -> Self { - Self::new(Default::default()) - } -} - -impl From for SpinMutex { - fn from(data: T) -> Self { - Self::new(data) - } -} - -impl<'a, T: ?Sized> SpinMutexGuard<'a, T> { - /// Leak the lock guard, yielding a mutable reference to the underlying data. - /// - /// Note that this function will permanently lock the original [`SpinMutex`]. - /// - /// ``` - /// let mylock = spin::mutex::SpinMutex::<_>::new(0); - /// - /// let data: &mut i32 = spin::mutex::SpinMutexGuard::leak(mylock.lock()); - /// - /// *data = 1; - /// assert_eq!(*data, 1); - /// ``` - #[inline(always)] - pub fn leak(this: Self) -> &'a mut T { - // Use ManuallyDrop to avoid stacked-borrow invalidation - let mut this = ManuallyDrop::new(this); - // We know statically that only we are referencing data - unsafe { &mut *this.data } - } -} - -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for SpinMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized + fmt::Display> fmt::Display for SpinMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized> Deref for SpinMutexGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - // We know statically that only we are referencing data - unsafe { &*self.data } - } -} - -impl<'a, T: ?Sized> DerefMut for SpinMutexGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { - // We know statically that only we are referencing data - unsafe { &mut *self.data } - } -} - -impl<'a, T: ?Sized> Drop for SpinMutexGuard<'a, T> { - /// The dropping of the MutexGuard will release the lock it was created from. - fn drop(&mut self) { - self.lock.store(false, Ordering::Release); - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawMutex for SpinMutex<(), R> { - type GuardMarker = lock_api_crate::GuardSend; - - const INIT: Self = Self::new(()); - - fn lock(&self) { - // Prevent guard destructor running - core::mem::forget(Self::lock(self)); - } - - fn try_lock(&self) -> bool { - // Prevent guard destructor running - Self::try_lock(self).map(core::mem::forget).is_some() - } - - unsafe fn unlock(&self) { - self.force_unlock(); - } - - fn is_locked(&self) -> bool { - Self::is_locked(self) - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::mpsc::channel; - use std::sync::Arc; - use std::thread; - - type SpinMutex = super::SpinMutex; - - #[derive(Eq, PartialEq, Debug)] - struct NonCopy(i32); - - #[test] - fn smoke() { - let m = SpinMutex::<_>::new(()); - drop(m.lock()); - drop(m.lock()); - } - - #[test] - fn lots_and_lots() { - static M: SpinMutex<()> = SpinMutex::<_>::new(()); - static mut CNT: u32 = 0; - const J: u32 = 1000; - const K: u32 = 3; - - fn inc() { - for _ in 0..J { - unsafe { - let _g = M.lock(); - CNT += 1; - } - } - } - - let (tx, rx) = channel(); - let mut ts = Vec::new(); - for _ in 0..K { - let tx2 = tx.clone(); - ts.push(thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - })); - let tx2 = tx.clone(); - ts.push(thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - })); - } - - drop(tx); - for _ in 0..2 * K { - rx.recv().unwrap(); - } - assert_eq!(unsafe { CNT }, J * K * 2); - - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn try_lock() { - let mutex = SpinMutex::<_>::new(42); - - // First lock succeeds - let a = mutex.try_lock(); - assert_eq!(a.as_ref().map(|r| **r), Some(42)); - - // Additional lock fails - let b = mutex.try_lock(); - assert!(b.is_none()); - - // After dropping lock, it succeeds again - ::core::mem::drop(a); - let c = mutex.try_lock(); - assert_eq!(c.as_ref().map(|r| **r), Some(42)); - } - - #[test] - fn test_into_inner() { - let m = SpinMutex::<_>::new(NonCopy(10)); - assert_eq!(m.into_inner(), NonCopy(10)); - } - - #[test] - fn test_into_inner_drop() { - struct Foo(Arc); - impl Drop for Foo { - fn drop(&mut self) { - self.0.fetch_add(1, Ordering::SeqCst); - } - } - let num_drops = Arc::new(AtomicUsize::new(0)); - let m = SpinMutex::<_>::new(Foo(num_drops.clone())); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - { - let _inner = m.into_inner(); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - } - assert_eq!(num_drops.load(Ordering::SeqCst), 1); - } - - #[test] - fn test_mutex_arc_nested() { - // Tests nested mutexes and access - // to underlying data. - let arc = Arc::new(SpinMutex::<_>::new(1)); - let arc2 = Arc::new(SpinMutex::<_>::new(arc)); - let (tx, rx) = channel(); - let t = thread::spawn(move || { - let lock = arc2.lock(); - let lock2 = lock.lock(); - assert_eq!(*lock2, 1); - tx.send(()).unwrap(); - }); - rx.recv().unwrap(); - t.join().unwrap(); - } - - #[test] - fn test_mutex_arc_access_in_unwind() { - let arc = Arc::new(SpinMutex::<_>::new(1)); - let arc2 = arc.clone(); - let _ = thread::spawn(move || -> () { - struct Unwinder { - i: Arc>, - } - impl Drop for Unwinder { - fn drop(&mut self) { - *self.i.lock() += 1; - } - } - let _u = Unwinder { i: arc2 }; - panic!(); - }) - .join(); - let lock = arc.lock(); - assert_eq!(*lock, 2); - } - - #[test] - fn test_mutex_unsized() { - let mutex: &SpinMutex<[i32]> = &SpinMutex::<_>::new([1, 2, 3]); - { - let b = &mut *mutex.lock(); - b[0] = 4; - b[2] = 5; - } - let comp: &[i32] = &[4, 2, 5]; - assert_eq!(&*mutex.lock(), comp); - } - - #[test] - fn test_mutex_force_lock() { - let lock = SpinMutex::<_>::new(()); - ::std::mem::forget(lock.lock()); - unsafe { - lock.force_unlock(); - } - assert!(lock.try_lock().is_some()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/ticket.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/ticket.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex/ticket.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex/ticket.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,537 +0,0 @@ -//! A ticket-based mutex. -//! -//! Waiting threads take a 'ticket' from the lock in the order they arrive and gain access to the lock when their -//! ticket is next in the queue. Best-case latency is slightly worse than a regular spinning mutex, but worse-case -//! latency is infinitely better. Waiting threads simply need to wait for all threads that come before them in the -//! queue to finish. - -use crate::{ - atomic::{AtomicUsize, Ordering}, - RelaxStrategy, Spin, -}; -use core::{ - cell::UnsafeCell, - fmt, - marker::PhantomData, - ops::{Deref, DerefMut}, -}; - -/// A spin-based [ticket lock](https://en.wikipedia.org/wiki/Ticket_lock) providing mutually exclusive access to data. -/// -/// A ticket lock is analogous to a queue management system for lock requests. When a thread tries to take a lock, it -/// is assigned a 'ticket'. It then spins until its ticket becomes next in line. When the lock guard is released, the -/// next ticket will be processed. -/// -/// Ticket locks significantly reduce the worse-case performance of locking at the cost of slightly higher average-time -/// overhead. -/// -/// # Example -/// -/// ``` -/// use spin; -/// -/// let lock = spin::mutex::TicketMutex::<_>::new(0); -/// -/// // Modify the data -/// *lock.lock() = 2; -/// -/// // Read the data -/// let answer = *lock.lock(); -/// assert_eq!(answer, 2); -/// ``` -/// -/// # Thread safety example -/// -/// ``` -/// use spin; -/// use std::sync::{Arc, Barrier}; -/// -/// let thread_count = 1000; -/// let spin_mutex = Arc::new(spin::mutex::TicketMutex::<_>::new(0)); -/// -/// // We use a barrier to ensure the readout happens after all writing -/// let barrier = Arc::new(Barrier::new(thread_count + 1)); -/// -/// for _ in (0..thread_count) { -/// let my_barrier = barrier.clone(); -/// let my_lock = spin_mutex.clone(); -/// std::thread::spawn(move || { -/// let mut guard = my_lock.lock(); -/// *guard += 1; -/// -/// // Release the lock to prevent a deadlock -/// drop(guard); -/// my_barrier.wait(); -/// }); -/// } -/// -/// barrier.wait(); -/// -/// let answer = { *spin_mutex.lock() }; -/// assert_eq!(answer, thread_count); -/// ``` -pub struct TicketMutex { - phantom: PhantomData, - next_ticket: AtomicUsize, - next_serving: AtomicUsize, - data: UnsafeCell, -} - -/// A guard that protects some data. -/// -/// When the guard is dropped, the next ticket will be processed. -pub struct TicketMutexGuard<'a, T: ?Sized + 'a> { - next_serving: &'a AtomicUsize, - ticket: usize, - data: &'a mut T, -} - -unsafe impl Sync for TicketMutex {} -unsafe impl Send for TicketMutex {} - -impl TicketMutex { - /// Creates a new [`TicketMutex`] wrapping the supplied data. - /// - /// # Example - /// - /// ``` - /// use spin::mutex::TicketMutex; - /// - /// static MUTEX: TicketMutex<()> = TicketMutex::<_>::new(()); - /// - /// fn demo() { - /// let lock = MUTEX.lock(); - /// // do something with lock - /// drop(lock); - /// } - /// ``` - #[inline(always)] - pub const fn new(data: T) -> Self { - Self { - phantom: PhantomData, - next_ticket: AtomicUsize::new(0), - next_serving: AtomicUsize::new(0), - data: UnsafeCell::new(data), - } - } - - /// Consumes this [`TicketMutex`] and unwraps the underlying data. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::TicketMutex::<_>::new(42); - /// assert_eq!(42, lock.into_inner()); - /// ``` - #[inline(always)] - pub fn into_inner(self) -> T { - self.data.into_inner() - } - /// Returns a mutable pointer to the underying data. - /// - /// This is mostly meant to be used for applications which require manual unlocking, but where - /// storing both the lock and the pointer to the inner data gets inefficient. - /// - /// # Example - /// ``` - /// let lock = spin::mutex::SpinMutex::<_>::new(42); - /// - /// unsafe { - /// core::mem::forget(lock.lock()); - /// - /// assert_eq!(lock.as_mut_ptr().read(), 42); - /// lock.as_mut_ptr().write(58); - /// - /// lock.force_unlock(); - /// } - /// - /// assert_eq!(*lock.lock(), 58); - /// - /// ``` - #[inline(always)] - pub fn as_mut_ptr(&self) -> *mut T { - self.data.get() - } -} - -impl fmt::Debug for TicketMutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.try_lock() { - Some(guard) => write!(f, "Mutex {{ data: ") - .and_then(|()| (&*guard).fmt(f)) - .and_then(|()| write!(f, "}}")), - None => write!(f, "Mutex {{ }}"), - } - } -} - -impl TicketMutex { - /// Locks the [`TicketMutex`] and returns a guard that permits access to the inner data. - /// - /// The returned data may be dereferenced for data access - /// and the lock will be dropped when the guard falls out of scope. - /// - /// ``` - /// let lock = spin::mutex::TicketMutex::<_>::new(0); - /// { - /// let mut data = lock.lock(); - /// // The lock is now locked and the data can be accessed - /// *data += 1; - /// // The lock is implicitly dropped at the end of the scope - /// } - /// ``` - #[inline(always)] - pub fn lock(&self) -> TicketMutexGuard { - let ticket = self.next_ticket.fetch_add(1, Ordering::Relaxed); - - while self.next_serving.load(Ordering::Acquire) != ticket { - R::relax(); - } - - TicketMutexGuard { - next_serving: &self.next_serving, - ticket, - // Safety - // We know that we are the next ticket to be served, - // so there's no other thread accessing the data. - // - // Every other thread has another ticket number so it's - // definitely stuck in the spin loop above. - data: unsafe { &mut *self.data.get() }, - } - } -} - -impl TicketMutex { - /// Returns `true` if the lock is currently held. - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - #[inline(always)] - pub fn is_locked(&self) -> bool { - let ticket = self.next_ticket.load(Ordering::Relaxed); - self.next_serving.load(Ordering::Relaxed) != ticket - } - - /// Force unlock this [`TicketMutex`], by serving the next ticket. - /// - /// # Safety - /// - /// This is *extremely* unsafe if the lock is not held by the current - /// thread. However, this can be useful in some instances for exposing the - /// lock to FFI that doesn't know how to deal with RAII. - #[inline(always)] - pub unsafe fn force_unlock(&self) { - self.next_serving.fetch_add(1, Ordering::Release); - } - - /// Try to lock this [`TicketMutex`], returning a lock guard if successful. - /// - /// # Example - /// - /// ``` - /// let lock = spin::mutex::TicketMutex::<_>::new(42); - /// - /// let maybe_guard = lock.try_lock(); - /// assert!(maybe_guard.is_some()); - /// - /// // `maybe_guard` is still held, so the second call fails - /// let maybe_guard2 = lock.try_lock(); - /// assert!(maybe_guard2.is_none()); - /// ``` - #[inline(always)] - pub fn try_lock(&self) -> Option> { - let ticket = self - .next_ticket - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |ticket| { - if self.next_serving.load(Ordering::Acquire) == ticket { - Some(ticket + 1) - } else { - None - } - }); - - ticket.ok().map(|ticket| TicketMutexGuard { - next_serving: &self.next_serving, - ticket, - // Safety - // We have a ticket that is equal to the next_serving ticket, so we know: - // - that no other thread can have the same ticket id as this thread - // - that we are the next one to be served so we have exclusive access to the data - data: unsafe { &mut *self.data.get() }, - }) - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the [`TicketMutex`] mutably, and a mutable reference is guaranteed to be exclusive in - /// Rust, no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As - /// such, this is a 'zero-cost' operation. - /// - /// # Example - /// - /// ``` - /// let mut lock = spin::mutex::TicketMutex::<_>::new(0); - /// *lock.get_mut() = 10; - /// assert_eq!(*lock.lock(), 10); - /// ``` - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - // Safety: - // We know that there are no other references to `self`, - // so it's safe to return a exclusive reference to the data. - unsafe { &mut *self.data.get() } - } -} - -impl Default for TicketMutex { - fn default() -> Self { - Self::new(Default::default()) - } -} - -impl From for TicketMutex { - fn from(data: T) -> Self { - Self::new(data) - } -} - -impl<'a, T: ?Sized> TicketMutexGuard<'a, T> { - /// Leak the lock guard, yielding a mutable reference to the underlying data. - /// - /// Note that this function will permanently lock the original [`TicketMutex`]. - /// - /// ``` - /// let mylock = spin::mutex::TicketMutex::<_>::new(0); - /// - /// let data: &mut i32 = spin::mutex::TicketMutexGuard::leak(mylock.lock()); - /// - /// *data = 1; - /// assert_eq!(*data, 1); - /// ``` - #[inline(always)] - pub fn leak(this: Self) -> &'a mut T { - let data = this.data as *mut _; // Keep it in pointer form temporarily to avoid double-aliasing - core::mem::forget(this); - unsafe { &mut *data } - } -} - -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for TicketMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized + fmt::Display> fmt::Display for TicketMutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized> Deref for TicketMutexGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - self.data - } -} - -impl<'a, T: ?Sized> DerefMut for TicketMutexGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { - self.data - } -} - -impl<'a, T: ?Sized> Drop for TicketMutexGuard<'a, T> { - fn drop(&mut self) { - let new_ticket = self.ticket + 1; - self.next_serving.store(new_ticket, Ordering::Release); - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawMutex for TicketMutex<(), R> { - type GuardMarker = lock_api_crate::GuardSend; - - const INIT: Self = Self::new(()); - - fn lock(&self) { - // Prevent guard destructor running - core::mem::forget(Self::lock(self)); - } - - fn try_lock(&self) -> bool { - // Prevent guard destructor running - Self::try_lock(self).map(core::mem::forget).is_some() - } - - unsafe fn unlock(&self) { - self.force_unlock(); - } - - fn is_locked(&self) -> bool { - Self::is_locked(self) - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::mpsc::channel; - use std::sync::Arc; - use std::thread; - - type TicketMutex = super::TicketMutex; - - #[derive(Eq, PartialEq, Debug)] - struct NonCopy(i32); - - #[test] - fn smoke() { - let m = TicketMutex::<_>::new(()); - drop(m.lock()); - drop(m.lock()); - } - - #[test] - fn lots_and_lots() { - static M: TicketMutex<()> = TicketMutex::<_>::new(()); - static mut CNT: u32 = 0; - const J: u32 = 1000; - const K: u32 = 3; - - fn inc() { - for _ in 0..J { - unsafe { - let _g = M.lock(); - CNT += 1; - } - } - } - - let (tx, rx) = channel(); - for _ in 0..K { - let tx2 = tx.clone(); - thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - }); - let tx2 = tx.clone(); - thread::spawn(move || { - inc(); - tx2.send(()).unwrap(); - }); - } - - drop(tx); - for _ in 0..2 * K { - rx.recv().unwrap(); - } - assert_eq!(unsafe { CNT }, J * K * 2); - } - - #[test] - fn try_lock() { - let mutex = TicketMutex::<_>::new(42); - - // First lock succeeds - let a = mutex.try_lock(); - assert_eq!(a.as_ref().map(|r| **r), Some(42)); - - // Additional lock fails - let b = mutex.try_lock(); - assert!(b.is_none()); - - // After dropping lock, it succeeds again - ::core::mem::drop(a); - let c = mutex.try_lock(); - assert_eq!(c.as_ref().map(|r| **r), Some(42)); - } - - #[test] - fn test_into_inner() { - let m = TicketMutex::<_>::new(NonCopy(10)); - assert_eq!(m.into_inner(), NonCopy(10)); - } - - #[test] - fn test_into_inner_drop() { - struct Foo(Arc); - impl Drop for Foo { - fn drop(&mut self) { - self.0.fetch_add(1, Ordering::SeqCst); - } - } - let num_drops = Arc::new(AtomicUsize::new(0)); - let m = TicketMutex::<_>::new(Foo(num_drops.clone())); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - { - let _inner = m.into_inner(); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - } - assert_eq!(num_drops.load(Ordering::SeqCst), 1); - } - - #[test] - fn test_mutex_arc_nested() { - // Tests nested mutexes and access - // to underlying data. - let arc = Arc::new(TicketMutex::<_>::new(1)); - let arc2 = Arc::new(TicketMutex::<_>::new(arc)); - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - let lock = arc2.lock(); - let lock2 = lock.lock(); - assert_eq!(*lock2, 1); - tx.send(()).unwrap(); - }); - rx.recv().unwrap(); - } - - #[test] - fn test_mutex_arc_access_in_unwind() { - let arc = Arc::new(TicketMutex::<_>::new(1)); - let arc2 = arc.clone(); - let _ = thread::spawn(move || -> () { - struct Unwinder { - i: Arc>, - } - impl Drop for Unwinder { - fn drop(&mut self) { - *self.i.lock() += 1; - } - } - let _u = Unwinder { i: arc2 }; - panic!(); - }) - .join(); - let lock = arc.lock(); - assert_eq!(*lock, 2); - } - - #[test] - fn test_mutex_unsized() { - let mutex: &TicketMutex<[i32]> = &TicketMutex::<_>::new([1, 2, 3]); - { - let b = &mut *mutex.lock(); - b[0] = 4; - b[2] = 5; - } - let comp: &[i32] = &[4, 2, 5]; - assert_eq!(&*mutex.lock(), comp); - } - - #[test] - fn is_locked() { - let mutex = TicketMutex::<_>::new(()); - assert!(!mutex.is_locked()); - let lock = mutex.lock(); - assert!(mutex.is_locked()); - drop(lock); - assert!(!mutex.is_locked()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/mutex.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/mutex.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,340 +0,0 @@ -//! Locks that have the same behaviour as a mutex. -//! -//! The [`Mutex`] in the root of the crate, can be configured using the `ticket_mutex` feature. -//! If it's enabled, [`TicketMutex`] and [`TicketMutexGuard`] will be re-exported as [`Mutex`] -//! and [`MutexGuard`], otherwise the [`SpinMutex`] and guard will be re-exported. -//! -//! `ticket_mutex` is disabled by default. -//! -//! [`Mutex`]: ../struct.Mutex.html -//! [`MutexGuard`]: ../struct.MutexGuard.html -//! [`TicketMutex`]: ./struct.TicketMutex.html -//! [`TicketMutexGuard`]: ./struct.TicketMutexGuard.html -//! [`SpinMutex`]: ./struct.SpinMutex.html -//! [`SpinMutexGuard`]: ./struct.SpinMutexGuard.html - -#[cfg(feature = "spin_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "spin_mutex")))] -pub mod spin; -#[cfg(feature = "spin_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "spin_mutex")))] -pub use self::spin::{SpinMutex, SpinMutexGuard}; - -#[cfg(feature = "ticket_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "ticket_mutex")))] -pub mod ticket; -#[cfg(feature = "ticket_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "ticket_mutex")))] -pub use self::ticket::{TicketMutex, TicketMutexGuard}; - -#[cfg(feature = "fair_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "fair_mutex")))] -pub mod fair; -#[cfg(feature = "fair_mutex")] -#[cfg_attr(docsrs, doc(cfg(feature = "fair_mutex")))] -pub use self::fair::{FairMutex, FairMutexGuard, Starvation}; - -use crate::{RelaxStrategy, Spin}; -use core::{ - fmt, - ops::{Deref, DerefMut}, -}; - -#[cfg(all(not(feature = "spin_mutex"), not(feature = "use_ticket_mutex")))] -compile_error!("The `mutex` feature flag was used (perhaps through another feature?) without either `spin_mutex` or `use_ticket_mutex`. One of these is required."); - -#[cfg(all(not(feature = "use_ticket_mutex"), feature = "spin_mutex"))] -type InnerMutex = self::spin::SpinMutex; -#[cfg(all(not(feature = "use_ticket_mutex"), feature = "spin_mutex"))] -type InnerMutexGuard<'a, T> = self::spin::SpinMutexGuard<'a, T>; - -#[cfg(feature = "use_ticket_mutex")] -type InnerMutex = self::ticket::TicketMutex; -#[cfg(feature = "use_ticket_mutex")] -type InnerMutexGuard<'a, T> = self::ticket::TicketMutexGuard<'a, T>; - -/// A spin-based lock providing mutually exclusive access to data. -/// -/// The implementation uses either a ticket mutex or a regular spin mutex depending on whether the `spin_mutex` or -/// `ticket_mutex` feature flag is enabled. -/// -/// # Example -/// -/// ``` -/// use spin; -/// -/// let lock = spin::Mutex::new(0); -/// -/// // Modify the data -/// *lock.lock() = 2; -/// -/// // Read the data -/// let answer = *lock.lock(); -/// assert_eq!(answer, 2); -/// ``` -/// -/// # Thread safety example -/// -/// ``` -/// use spin; -/// use std::sync::{Arc, Barrier}; -/// -/// let thread_count = 1000; -/// let spin_mutex = Arc::new(spin::Mutex::new(0)); -/// -/// // We use a barrier to ensure the readout happens after all writing -/// let barrier = Arc::new(Barrier::new(thread_count + 1)); -/// -/// # let mut ts = Vec::new(); -/// for _ in (0..thread_count) { -/// let my_barrier = barrier.clone(); -/// let my_lock = spin_mutex.clone(); -/// # let t = -/// std::thread::spawn(move || { -/// let mut guard = my_lock.lock(); -/// *guard += 1; -/// -/// // Release the lock to prevent a deadlock -/// drop(guard); -/// my_barrier.wait(); -/// }); -/// # ts.push(t); -/// } -/// -/// barrier.wait(); -/// -/// let answer = { *spin_mutex.lock() }; -/// assert_eq!(answer, thread_count); -/// -/// # for t in ts { -/// # t.join().unwrap(); -/// # } -/// ``` -pub struct Mutex { - inner: InnerMutex, -} - -unsafe impl Sync for Mutex {} -unsafe impl Send for Mutex {} - -/// A generic guard that will protect some data access and -/// uses either a ticket lock or a normal spin mutex. -/// -/// For more info see [`TicketMutexGuard`] or [`SpinMutexGuard`]. -/// -/// [`TicketMutexGuard`]: ./struct.TicketMutexGuard.html -/// [`SpinMutexGuard`]: ./struct.SpinMutexGuard.html -pub struct MutexGuard<'a, T: 'a + ?Sized> { - inner: InnerMutexGuard<'a, T>, -} - -impl Mutex { - /// Creates a new [`Mutex`] wrapping the supplied data. - /// - /// # Example - /// - /// ``` - /// use spin::Mutex; - /// - /// static MUTEX: Mutex<()> = Mutex::new(()); - /// - /// fn demo() { - /// let lock = MUTEX.lock(); - /// // do something with lock - /// drop(lock); - /// } - /// ``` - #[inline(always)] - pub const fn new(value: T) -> Self { - Self { - inner: InnerMutex::new(value), - } - } - - /// Consumes this [`Mutex`] and unwraps the underlying data. - /// - /// # Example - /// - /// ``` - /// let lock = spin::Mutex::new(42); - /// assert_eq!(42, lock.into_inner()); - /// ``` - #[inline(always)] - pub fn into_inner(self) -> T { - self.inner.into_inner() - } -} - -impl Mutex { - /// Locks the [`Mutex`] and returns a guard that permits access to the inner data. - /// - /// The returned value may be dereferenced for data access - /// and the lock will be dropped when the guard falls out of scope. - /// - /// ``` - /// let lock = spin::Mutex::new(0); - /// { - /// let mut data = lock.lock(); - /// // The lock is now locked and the data can be accessed - /// *data += 1; - /// // The lock is implicitly dropped at the end of the scope - /// } - /// ``` - #[inline(always)] - pub fn lock(&self) -> MutexGuard { - MutexGuard { - inner: self.inner.lock(), - } - } -} - -impl Mutex { - /// Returns `true` if the lock is currently held. - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - #[inline(always)] - pub fn is_locked(&self) -> bool { - self.inner.is_locked() - } - - /// Force unlock this [`Mutex`]. - /// - /// # Safety - /// - /// This is *extremely* unsafe if the lock is not held by the current - /// thread. However, this can be useful in some instances for exposing the - /// lock to FFI that doesn't know how to deal with RAII. - #[inline(always)] - pub unsafe fn force_unlock(&self) { - self.inner.force_unlock() - } - - /// Try to lock this [`Mutex`], returning a lock guard if successful. - /// - /// # Example - /// - /// ``` - /// let lock = spin::Mutex::new(42); - /// - /// let maybe_guard = lock.try_lock(); - /// assert!(maybe_guard.is_some()); - /// - /// // `maybe_guard` is still held, so the second call fails - /// let maybe_guard2 = lock.try_lock(); - /// assert!(maybe_guard2.is_none()); - /// ``` - #[inline(always)] - pub fn try_lock(&self) -> Option> { - self.inner - .try_lock() - .map(|guard| MutexGuard { inner: guard }) - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the [`Mutex`] mutably, and a mutable reference is guaranteed to be exclusive in Rust, - /// no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As such, - /// this is a 'zero-cost' operation. - /// - /// # Example - /// - /// ``` - /// let mut lock = spin::Mutex::new(0); - /// *lock.get_mut() = 10; - /// assert_eq!(*lock.lock(), 10); - /// ``` - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.inner.get_mut() - } -} - -impl fmt::Debug for Mutex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.inner, f) - } -} - -impl Default for Mutex { - fn default() -> Self { - Self::new(Default::default()) - } -} - -impl From for Mutex { - fn from(data: T) -> Self { - Self::new(data) - } -} - -impl<'a, T: ?Sized> MutexGuard<'a, T> { - /// Leak the lock guard, yielding a mutable reference to the underlying data. - /// - /// Note that this function will permanently lock the original [`Mutex`]. - /// - /// ``` - /// let mylock = spin::Mutex::new(0); - /// - /// let data: &mut i32 = spin::MutexGuard::leak(mylock.lock()); - /// - /// *data = 1; - /// assert_eq!(*data, 1); - /// ``` - #[inline(always)] - pub fn leak(this: Self) -> &'a mut T { - InnerMutexGuard::leak(this.inner) - } -} - -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - &*self.inner - } -} - -impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawMutex for Mutex<(), R> { - type GuardMarker = lock_api_crate::GuardSend; - - const INIT: Self = Self::new(()); - - fn lock(&self) { - // Prevent guard destructor running - core::mem::forget(Self::lock(self)); - } - - fn try_lock(&self) -> bool { - // Prevent guard destructor running - Self::try_lock(self).map(core::mem::forget).is_some() - } - - unsafe fn unlock(&self) { - self.force_unlock(); - } - - fn is_locked(&self) -> bool { - self.inner.is_locked() - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/once.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/once.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/once.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/once.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,789 +0,0 @@ -//! Synchronization primitives for one-time evaluation. - -use crate::{ - atomic::{AtomicU8, Ordering}, - RelaxStrategy, Spin, -}; -use core::{cell::UnsafeCell, fmt, marker::PhantomData, mem::MaybeUninit}; - -/// A primitive that provides lazy one-time initialization. -/// -/// Unlike its `std::sync` equivalent, this is generalized such that the closure returns a -/// value to be stored by the [`Once`] (`std::sync::Once` can be trivially emulated with -/// `Once`). -/// -/// Because [`Once::new`] is `const`, this primitive may be used to safely initialize statics. -/// -/// # Examples -/// -/// ``` -/// use spin; -/// -/// static START: spin::Once = spin::Once::new(); -/// -/// START.call_once(|| { -/// // run initialization here -/// }); -/// ``` -pub struct Once { - phantom: PhantomData, - status: AtomicStatus, - data: UnsafeCell>, -} - -impl Default for Once { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for Once { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.get() { - Some(s) => write!(f, "Once {{ data: ") - .and_then(|()| s.fmt(f)) - .and_then(|()| write!(f, "}}")), - None => write!(f, "Once {{ }}"), - } - } -} - -// Same unsafe impls as `std::sync::RwLock`, because this also allows for -// concurrent reads. -unsafe impl Sync for Once {} -unsafe impl Send for Once {} - -mod status { - use super::*; - - // SAFETY: This structure has an invariant, namely that the inner atomic u8 must *always* have - // a value for which there exists a valid Status. This means that users of this API must only - // be allowed to load and store `Status`es. - #[repr(transparent)] - pub struct AtomicStatus(AtomicU8); - - // Four states that a Once can be in, encoded into the lower bits of `status` in - // the Once structure. - #[repr(u8)] - #[derive(Clone, Copy, Debug, PartialEq)] - pub enum Status { - Incomplete = 0x00, - Running = 0x01, - Complete = 0x02, - Panicked = 0x03, - } - impl Status { - // Construct a status from an inner u8 integer. - // - // # Safety - // - // For this to be safe, the inner number must have a valid corresponding enum variant. - unsafe fn new_unchecked(inner: u8) -> Self { - core::mem::transmute(inner) - } - } - - impl AtomicStatus { - #[inline(always)] - pub const fn new(status: Status) -> Self { - // SAFETY: We got the value directly from status, so transmuting back is fine. - Self(AtomicU8::new(status as u8)) - } - #[inline(always)] - pub fn load(&self, ordering: Ordering) -> Status { - // SAFETY: We know that the inner integer must have been constructed from a Status in - // the first place. - unsafe { Status::new_unchecked(self.0.load(ordering)) } - } - #[inline(always)] - pub fn store(&self, status: Status, ordering: Ordering) { - // SAFETY: While not directly unsafe, this is safe because the value was retrieved from - // a status, thus making transmutation safe. - self.0.store(status as u8, ordering); - } - #[inline(always)] - pub fn compare_exchange( - &self, - old: Status, - new: Status, - success: Ordering, - failure: Ordering, - ) -> Result { - match self - .0 - .compare_exchange(old as u8, new as u8, success, failure) - { - // SAFETY: A compare exchange will always return a value that was later stored into - // the atomic u8, but due to the invariant that it must be a valid Status, we know - // that both Ok(_) and Err(_) will be safely transmutable. - Ok(ok) => Ok(unsafe { Status::new_unchecked(ok) }), - Err(err) => Err(unsafe { Status::new_unchecked(err) }), - } - } - #[inline(always)] - pub fn get_mut(&mut self) -> &mut Status { - // SAFETY: Since we know that the u8 inside must be a valid Status, we can safely cast - // it to a &mut Status. - unsafe { &mut *((self.0.get_mut() as *mut u8).cast::()) } - } - } -} -use self::status::{AtomicStatus, Status}; - -impl Once { - /// Performs an initialization routine once and only once. The given closure - /// will be executed if this is the first time `call_once` has been called, - /// and otherwise the routine will *not* be invoked. - /// - /// This method will block the calling thread if another initialization - /// routine is currently running. - /// - /// When this function returns, it is guaranteed that some initialization - /// has run and completed (it may not be the closure specified). The - /// returned pointer will point to the result from the closure that was - /// run. - /// - /// # Panics - /// - /// This function will panic if the [`Once`] previously panicked while attempting - /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s - /// primitives. - /// - /// # Examples - /// - /// ``` - /// use spin; - /// - /// static INIT: spin::Once = spin::Once::new(); - /// - /// fn get_cached_val() -> usize { - /// *INIT.call_once(expensive_computation) - /// } - /// - /// fn expensive_computation() -> usize { - /// // ... - /// # 2 - /// } - /// ``` - pub fn call_once T>(&self, f: F) -> &T { - match self.try_call_once(|| Ok::(f())) { - Ok(x) => x, - Err(void) => match void {}, - } - } - - /// This method is similar to `call_once`, but allows the given closure to - /// fail, and lets the `Once` in a uninitialized state if it does. - /// - /// This method will block the calling thread if another initialization - /// routine is currently running. - /// - /// When this function returns without error, it is guaranteed that some - /// initialization has run and completed (it may not be the closure - /// specified). The returned reference will point to the result from the - /// closure that was run. - /// - /// # Panics - /// - /// This function will panic if the [`Once`] previously panicked while attempting - /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s - /// primitives. - /// - /// # Examples - /// - /// ``` - /// use spin; - /// - /// static INIT: spin::Once = spin::Once::new(); - /// - /// fn get_cached_val() -> Result { - /// INIT.try_call_once(expensive_fallible_computation).map(|x| *x) - /// } - /// - /// fn expensive_fallible_computation() -> Result { - /// // ... - /// # Ok(2) - /// } - /// ``` - pub fn try_call_once Result, E>(&self, f: F) -> Result<&T, E> { - if let Some(value) = self.get() { - Ok(value) - } else { - self.try_call_once_slow(f) - } - } - - #[cold] - fn try_call_once_slow Result, E>(&self, f: F) -> Result<&T, E> { - loop { - let xchg = self.status.compare_exchange( - Status::Incomplete, - Status::Running, - Ordering::Acquire, - Ordering::Acquire, - ); - - match xchg { - Ok(_must_be_state_incomplete) => { - // Impl is defined after the match for readability - } - Err(Status::Panicked) => panic!("Once panicked"), - Err(Status::Running) => match self.poll() { - Some(v) => return Ok(v), - None => continue, - }, - Err(Status::Complete) => { - return Ok(unsafe { - // SAFETY: The status is Complete - self.force_get() - }); - } - Err(Status::Incomplete) => { - // The compare_exchange failed, so this shouldn't ever be reached, - // however if we decide to switch to compare_exchange_weak it will - // be safer to leave this here than hit an unreachable - continue; - } - } - - // The compare-exchange succeeded, so we shall initialize it. - - // We use a guard (Finish) to catch panics caused by builder - let finish = Finish { - status: &self.status, - }; - let val = match f() { - Ok(val) => val, - Err(err) => { - // If an error occurs, clean up everything and leave. - core::mem::forget(finish); - self.status.store(Status::Incomplete, Ordering::Release); - return Err(err); - } - }; - unsafe { - // SAFETY: - // `UnsafeCell`/deref: currently the only accessor, mutably - // and immutably by cas exclusion. - // `write`: pointer comes from `MaybeUninit`. - (*self.data.get()).as_mut_ptr().write(val); - }; - // If there were to be a panic with unwind enabled, the code would - // short-circuit and never reach the point where it writes the inner data. - // The destructor for Finish will run, and poison the Once to ensure that other - // threads accessing it do not exhibit unwanted behavior, if there were to be - // any inconsistency in data structures caused by the panicking thread. - // - // However, f() is expected in the general case not to panic. In that case, we - // simply forget the guard, bypassing its destructor. We could theoretically - // clear a flag instead, but this eliminates the call to the destructor at - // compile time, and unconditionally poisons during an eventual panic, if - // unwinding is enabled. - core::mem::forget(finish); - - // SAFETY: Release is required here, so that all memory accesses done in the - // closure when initializing, become visible to other threads that perform Acquire - // loads. - // - // And, we also know that the changes this thread has done will not magically - // disappear from our cache, so it does not need to be AcqRel. - self.status.store(Status::Complete, Ordering::Release); - - // This next line is mainly an optimization. - return unsafe { Ok(self.force_get()) }; - } - } - - /// Spins until the [`Once`] contains a value. - /// - /// Note that in releases prior to `0.7`, this function had the behaviour of [`Once::poll`]. - /// - /// # Panics - /// - /// This function will panic if the [`Once`] previously panicked while attempting - /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s - /// primitives. - pub fn wait(&self) -> &T { - loop { - match self.poll() { - Some(x) => break x, - None => R::relax(), - } - } - } - - /// Like [`Once::get`], but will spin if the [`Once`] is in the process of being - /// initialized. If initialization has not even begun, `None` will be returned. - /// - /// Note that in releases prior to `0.7`, this function was named `wait`. - /// - /// # Panics - /// - /// This function will panic if the [`Once`] previously panicked while attempting - /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s - /// primitives. - pub fn poll(&self) -> Option<&T> { - loop { - // SAFETY: Acquire is safe here, because if the status is COMPLETE, then we want to make - // sure that all memory accessed done while initializing that value, are visible when - // we return a reference to the inner data after this load. - match self.status.load(Ordering::Acquire) { - Status::Incomplete => return None, - Status::Running => R::relax(), // We spin - Status::Complete => return Some(unsafe { self.force_get() }), - Status::Panicked => panic!("Once previously poisoned by a panicked"), - } - } - } -} - -impl Once { - /// Initialization constant of [`Once`]. - #[allow(clippy::declare_interior_mutable_const)] - pub const INIT: Self = Self { - phantom: PhantomData, - status: AtomicStatus::new(Status::Incomplete), - data: UnsafeCell::new(MaybeUninit::uninit()), - }; - - /// Creates a new [`Once`]. - pub const fn new() -> Self { - Self::INIT - } - - /// Creates a new initialized [`Once`]. - pub const fn initialized(data: T) -> Self { - Self { - phantom: PhantomData, - status: AtomicStatus::new(Status::Complete), - data: UnsafeCell::new(MaybeUninit::new(data)), - } - } - - /// Retrieve a pointer to the inner data. - /// - /// While this method itself is safe, accessing the pointer before the [`Once`] has been - /// initialized is UB, unless this method has already been written to from a pointer coming - /// from this method. - pub fn as_mut_ptr(&self) -> *mut T { - // SAFETY: - // * MaybeUninit always has exactly the same layout as T - self.data.get().cast::() - } - - /// Get a reference to the initialized instance. Must only be called once COMPLETE. - unsafe fn force_get(&self) -> &T { - // SAFETY: - // * `UnsafeCell`/inner deref: data never changes again - // * `MaybeUninit`/outer deref: data was initialized - &*(*self.data.get()).as_ptr() - } - - /// Get a reference to the initialized instance. Must only be called once COMPLETE. - unsafe fn force_get_mut(&mut self) -> &mut T { - // SAFETY: - // * `UnsafeCell`/inner deref: data never changes again - // * `MaybeUninit`/outer deref: data was initialized - &mut *(*self.data.get()).as_mut_ptr() - } - - /// Get a reference to the initialized instance. Must only be called once COMPLETE. - unsafe fn force_into_inner(self) -> T { - // SAFETY: - // * `UnsafeCell`/inner deref: data never changes again - // * `MaybeUninit`/outer deref: data was initialized - (*self.data.get()).as_ptr().read() - } - - /// Returns a reference to the inner value if the [`Once`] has been initialized. - pub fn get(&self) -> Option<&T> { - // SAFETY: Just as with `poll`, Acquire is safe here because we want to be able to see the - // nonatomic stores done when initializing, once we have loaded and checked the status. - match self.status.load(Ordering::Acquire) { - Status::Complete => Some(unsafe { self.force_get() }), - _ => None, - } - } - - /// Returns a reference to the inner value on the unchecked assumption that the [`Once`] has been initialized. - /// - /// # Safety - /// - /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized - /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused). - /// However, this can be useful in some instances for exposing the `Once` to FFI or when the overhead of atomically - /// checking initialization is unacceptable and the `Once` has already been initialized. - pub unsafe fn get_unchecked(&self) -> &T { - debug_assert_eq!( - self.status.load(Ordering::SeqCst), - Status::Complete, - "Attempted to access an uninitialized Once. If this was run without debug checks, this would be undefined behaviour. This is a serious bug and you must fix it.", - ); - self.force_get() - } - - /// Returns a mutable reference to the inner value if the [`Once`] has been initialized. - /// - /// Because this method requires a mutable reference to the [`Once`], no synchronization - /// overhead is required to access the inner value. In effect, it is zero-cost. - pub fn get_mut(&mut self) -> Option<&mut T> { - match *self.status.get_mut() { - Status::Complete => Some(unsafe { self.force_get_mut() }), - _ => None, - } - } - - /// Returns a mutable reference to the inner value - /// - /// # Safety - /// - /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized - /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused). - /// However, this can be useful in some instances for exposing the `Once` to FFI or when the overhead of atomically - /// checking initialization is unacceptable and the `Once` has already been initialized. - pub unsafe fn get_mut_unchecked(&mut self) -> &mut T { - debug_assert_eq!( - self.status.load(Ordering::SeqCst), - Status::Complete, - "Attempted to access an unintialized Once. If this was to run without debug checks, this would be undefined behavior. This is a serious bug and you must fix it.", - ); - self.force_get_mut() - } - - /// Returns a the inner value if the [`Once`] has been initialized. - /// - /// Because this method requires ownership of the [`Once`], no synchronization overhead - /// is required to access the inner value. In effect, it is zero-cost. - pub fn try_into_inner(mut self) -> Option { - match *self.status.get_mut() { - Status::Complete => Some(unsafe { self.force_into_inner() }), - _ => None, - } - } - - /// Returns a the inner value if the [`Once`] has been initialized. - /// # Safety - /// - /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized - /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused) - /// This can be useful, if `Once` has already been initialized, and you want to bypass an - /// option check. - pub unsafe fn into_inner_unchecked(self) -> T { - debug_assert_eq!( - self.status.load(Ordering::SeqCst), - Status::Complete, - "Attempted to access an unintialized Once. If this was to run without debug checks, this would be undefined behavior. This is a serious bug and you must fix it.", - ); - self.force_into_inner() - } - - /// Checks whether the value has been initialized. - /// - /// This is done using [`Acquire`](core::sync::atomic::Ordering::Acquire) ordering, and - /// therefore it is safe to access the value directly via - /// [`get_unchecked`](Self::get_unchecked) if this returns true. - pub fn is_completed(&self) -> bool { - // TODO: Add a similar variant for Relaxed? - self.status.load(Ordering::Acquire) == Status::Complete - } -} - -impl From for Once { - fn from(data: T) -> Self { - Self::initialized(data) - } -} - -impl Drop for Once { - fn drop(&mut self) { - // No need to do any atomic access here, we have &mut! - if *self.status.get_mut() == Status::Complete { - unsafe { - //TODO: Use MaybeUninit::assume_init_drop once stabilised - core::ptr::drop_in_place((*self.data.get()).as_mut_ptr()); - } - } - } -} - -struct Finish<'a> { - status: &'a AtomicStatus, -} - -impl<'a> Drop for Finish<'a> { - fn drop(&mut self) { - // While using Relaxed here would most likely not be an issue, we use SeqCst anyway. - // This is mainly because panics are not meant to be fast at all, but also because if - // there were to be a compiler bug which reorders accesses within the same thread, - // where it should not, we want to be sure that the panic really is handled, and does - // not cause additional problems. SeqCst will therefore help guarding against such - // bugs. - self.status.store(Status::Panicked, Ordering::SeqCst); - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::atomic::AtomicU32; - use std::sync::mpsc::channel; - use std::sync::Arc; - use std::thread; - - use super::*; - - #[test] - fn smoke_once() { - static O: Once = Once::new(); - let mut a = 0; - O.call_once(|| a += 1); - assert_eq!(a, 1); - O.call_once(|| a += 1); - assert_eq!(a, 1); - } - - #[test] - fn smoke_once_value() { - static O: Once = Once::new(); - let a = O.call_once(|| 1); - assert_eq!(*a, 1); - let b = O.call_once(|| 2); - assert_eq!(*b, 1); - } - - #[test] - fn stampede_once() { - static O: Once = Once::new(); - static mut RUN: bool = false; - - let (tx, rx) = channel(); - let mut ts = Vec::new(); - for _ in 0..10 { - let tx = tx.clone(); - ts.push(thread::spawn(move || { - for _ in 0..4 { - thread::yield_now() - } - unsafe { - O.call_once(|| { - assert!(!RUN); - RUN = true; - }); - assert!(RUN); - } - tx.send(()).unwrap(); - })); - } - - unsafe { - O.call_once(|| { - assert!(!RUN); - RUN = true; - }); - assert!(RUN); - } - - for _ in 0..10 { - rx.recv().unwrap(); - } - - for t in ts { - t.join().unwrap(); - } - } - - #[test] - fn get() { - static INIT: Once = Once::new(); - - assert!(INIT.get().is_none()); - INIT.call_once(|| 2); - assert_eq!(INIT.get().map(|r| *r), Some(2)); - } - - #[test] - fn get_no_wait() { - static INIT: Once = Once::new(); - - assert!(INIT.get().is_none()); - let t = thread::spawn(move || { - INIT.call_once(|| { - thread::sleep(std::time::Duration::from_secs(3)); - 42 - }); - }); - assert!(INIT.get().is_none()); - - t.join().unwrap(); - } - - #[test] - fn poll() { - static INIT: Once = Once::new(); - - assert!(INIT.poll().is_none()); - INIT.call_once(|| 3); - assert_eq!(INIT.poll().map(|r| *r), Some(3)); - } - - #[test] - fn wait() { - static INIT: Once = Once::new(); - - let t = std::thread::spawn(|| { - assert_eq!(*INIT.wait(), 3); - assert!(INIT.is_completed()); - }); - - for _ in 0..4 { - thread::yield_now() - } - - assert!(INIT.poll().is_none()); - INIT.call_once(|| 3); - - t.join().unwrap(); - } - - #[test] - fn panic() { - use std::panic; - - static INIT: Once = Once::new(); - - // poison the once - let t = panic::catch_unwind(|| { - INIT.call_once(|| panic!()); - }); - assert!(t.is_err()); - - // poisoning propagates - let t = panic::catch_unwind(|| { - INIT.call_once(|| {}); - }); - assert!(t.is_err()); - } - - #[test] - fn init_constant() { - static O: Once = Once::INIT; - let mut a = 0; - O.call_once(|| a += 1); - assert_eq!(a, 1); - O.call_once(|| a += 1); - assert_eq!(a, 1); - } - - static mut CALLED: bool = false; - - struct DropTest {} - - impl Drop for DropTest { - fn drop(&mut self) { - unsafe { - CALLED = true; - } - } - } - - #[test] - fn try_call_once_err() { - let once = Once::<_, Spin>::new(); - let shared = Arc::new((once, AtomicU32::new(0))); - - let (tx, rx) = channel(); - - let t0 = { - let shared = shared.clone(); - thread::spawn(move || { - let (once, called) = &*shared; - - once.try_call_once(|| { - called.fetch_add(1, Ordering::AcqRel); - tx.send(()).unwrap(); - thread::sleep(std::time::Duration::from_millis(50)); - Err(()) - }) - .ok(); - }) - }; - - let t1 = { - let shared = shared.clone(); - thread::spawn(move || { - rx.recv().unwrap(); - let (once, called) = &*shared; - assert_eq!( - called.load(Ordering::Acquire), - 1, - "leader thread did not run first" - ); - - once.call_once(|| { - called.fetch_add(1, Ordering::AcqRel); - }); - }) - }; - - t0.join().unwrap(); - t1.join().unwrap(); - - assert_eq!(shared.1.load(Ordering::Acquire), 2); - } - - // This is sort of two test cases, but if we write them as separate test methods - // they can be executed concurrently and then fail some small fraction of the - // time. - #[test] - fn drop_occurs_and_skip_uninit_drop() { - unsafe { - CALLED = false; - } - - { - let once = Once::<_>::new(); - once.call_once(|| DropTest {}); - } - - assert!(unsafe { CALLED }); - // Now test that we skip drops for the uninitialized case. - unsafe { - CALLED = false; - } - - let once = Once::::new(); - drop(once); - - assert!(unsafe { !CALLED }); - } - - #[test] - fn call_once_test() { - for _ in 0..20 { - use std::sync::atomic::AtomicUsize; - use std::sync::Arc; - use std::time::Duration; - let share = Arc::new(AtomicUsize::new(0)); - let once = Arc::new(Once::<_, Spin>::new()); - let mut hs = Vec::new(); - for _ in 0..8 { - let h = thread::spawn({ - let share = share.clone(); - let once = once.clone(); - move || { - thread::sleep(Duration::from_millis(10)); - once.call_once(|| { - share.fetch_add(1, Ordering::SeqCst); - }); - } - }); - hs.push(h); - } - for h in hs { - h.join().unwrap(); - } - assert_eq!(1, share.load(Ordering::SeqCst)); - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/relax.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/relax.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/relax.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/relax.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -//! Strategies that determine the behaviour of locks when encountering contention. - -/// A trait implemented by spinning relax strategies. -pub trait RelaxStrategy { - /// Perform the relaxing operation during a period of contention. - fn relax(); -} - -/// A strategy that rapidly spins while informing the CPU that it should power down non-essential components via -/// [`core::hint::spin_loop`]. -/// -/// Note that spinning is a 'dumb' strategy and most schedulers cannot correctly differentiate it from useful work, -/// thereby misallocating even more CPU time to the spinning process. This is known as -/// ['priority inversion'](https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html). -/// -/// If you see signs that priority inversion is occurring, consider switching to [`Yield`] or, even better, not using a -/// spinlock at all and opting for a proper scheduler-aware lock. Remember also that different targets, operating -/// systems, schedulers, and even the same scheduler with different workloads will exhibit different behaviour. Just -/// because priority inversion isn't occurring in your tests does not mean that it will not occur. Use a scheduler- -/// aware lock if at all possible. -pub struct Spin; - -impl RelaxStrategy for Spin { - #[inline(always)] - fn relax() { - // Use the deprecated spin_loop_hint() to ensure that we don't get - // a higher MSRV than we need to. - #[allow(deprecated)] - core::sync::atomic::spin_loop_hint(); - } -} - -/// A strategy that yields the current time slice to the scheduler in favour of other threads or processes. -/// -/// This is generally used as a strategy for minimising power consumption and priority inversion on targets that have a -/// standard library available. Note that such targets have scheduler-integrated concurrency primitives available, and -/// you should generally use these instead, except in rare circumstances. -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub struct Yield; - -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl RelaxStrategy for Yield { - #[inline(always)] - fn relax() { - std::thread::yield_now(); - } -} - -/// A strategy that rapidly spins, without telling the CPU to do any powering down. -/// -/// You almost certainly do not want to use this. Use [`Spin`] instead. It exists for completeness and for targets -/// that, for some reason, miscompile or do not support spin hint intrinsics despite attempting to generate code for -/// them (i.e: this is a workaround for possible compiler bugs). -pub struct Loop; - -impl RelaxStrategy for Loop { - #[inline(always)] - fn relax() {} -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/spin/src/rwlock.rs clamav-1.4.6+dfsg/.cargo/vendor/spin/src/rwlock.rs --- clamav-1.4.3+dfsg/.cargo/vendor/spin/src/rwlock.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/spin/src/rwlock.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1165 +0,0 @@ -//! A lock that provides data access to either one writer or many readers. - -use crate::{ - atomic::{AtomicUsize, Ordering}, - RelaxStrategy, Spin, -}; -use core::{ - cell::UnsafeCell, - fmt, - marker::PhantomData, - mem, - mem::ManuallyDrop, - ops::{Deref, DerefMut}, -}; - -/// A lock that provides data access to either one writer or many readers. -/// -/// This lock behaves in a similar manner to its namesake `std::sync::RwLock` but uses -/// spinning for synchronisation instead. Unlike its namespace, this lock does not -/// track lock poisoning. -/// -/// This type of lock allows a number of readers or at most one writer at any -/// point in time. The write portion of this lock typically allows modification -/// of the underlying data (exclusive access) and the read portion of this lock -/// typically allows for read-only access (shared access). -/// -/// The type parameter `T` represents the data that this lock protects. It is -/// required that `T` satisfies `Send` to be shared across tasks and `Sync` to -/// allow concurrent access through readers. The RAII guards returned from the -/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) -/// to allow access to the contained of the lock. -/// -/// An [`RwLockUpgradableGuard`](RwLockUpgradableGuard) can be upgraded to a -/// writable guard through the [`RwLockUpgradableGuard::upgrade`](RwLockUpgradableGuard::upgrade) -/// [`RwLockUpgradableGuard::try_upgrade`](RwLockUpgradableGuard::try_upgrade) functions. -/// Writable or upgradeable guards can be downgraded through their respective `downgrade` -/// functions. -/// -/// Based on Facebook's -/// [`folly/RWSpinLock.h`](https://github.com/facebook/folly/blob/a0394d84f2d5c3e50ebfd0566f9d3acb52cfab5a/folly/synchronization/RWSpinLock.h). -/// This implementation is unfair to writers - if the lock always has readers, then no writers will -/// ever get a chance. Using an upgradeable lock guard can *somewhat* alleviate this issue as no -/// new readers are allowed when an upgradeable guard is held, but upgradeable guards can be taken -/// when there are existing readers. However if the lock is that highly contended and writes are -/// crucial then this implementation may be a poor choice. -/// -/// # Examples -/// -/// ``` -/// use spin; -/// -/// let lock = spin::RwLock::new(5); -/// -/// // many reader locks can be held at once -/// { -/// let r1 = lock.read(); -/// let r2 = lock.read(); -/// assert_eq!(*r1, 5); -/// assert_eq!(*r2, 5); -/// } // read locks are dropped at this point -/// -/// // only one write lock may be held, however -/// { -/// let mut w = lock.write(); -/// *w += 1; -/// assert_eq!(*w, 6); -/// } // write lock is dropped here -/// ``` -pub struct RwLock { - phantom: PhantomData, - lock: AtomicUsize, - data: UnsafeCell, -} - -const READER: usize = 1 << 2; -const UPGRADED: usize = 1 << 1; -const WRITER: usize = 1; - -/// A guard that provides immutable data access. -/// -/// When the guard falls out of scope it will decrement the read count, -/// potentially releasing the lock. -pub struct RwLockReadGuard<'a, T: 'a + ?Sized> { - lock: &'a AtomicUsize, - data: *const T, -} - -/// A guard that provides mutable data access. -/// -/// When the guard falls out of scope it will release the lock. -pub struct RwLockWriteGuard<'a, T: 'a + ?Sized, R = Spin> { - phantom: PhantomData, - inner: &'a RwLock, - data: *mut T, -} - -/// A guard that provides immutable data access but can be upgraded to [`RwLockWriteGuard`]. -/// -/// No writers or other upgradeable guards can exist while this is in scope. New reader -/// creation is prevented (to alleviate writer starvation) but there may be existing readers -/// when the lock is acquired. -/// -/// When the guard falls out of scope it will release the lock. -pub struct RwLockUpgradableGuard<'a, T: 'a + ?Sized, R = Spin> { - phantom: PhantomData, - inner: &'a RwLock, - data: *const T, -} - -// Same unsafe impls as `std::sync::RwLock` -unsafe impl Send for RwLock {} -unsafe impl Sync for RwLock {} - -unsafe impl Send for RwLockWriteGuard<'_, T, R> {} -unsafe impl Sync for RwLockWriteGuard<'_, T, R> {} - -unsafe impl Send for RwLockReadGuard<'_, T> {} -unsafe impl Sync for RwLockReadGuard<'_, T> {} - -unsafe impl Send for RwLockUpgradableGuard<'_, T, R> {} -unsafe impl Sync for RwLockUpgradableGuard<'_, T, R> {} - -impl RwLock { - /// Creates a new spinlock wrapping the supplied data. - /// - /// May be used statically: - /// - /// ``` - /// use spin; - /// - /// static RW_LOCK: spin::RwLock<()> = spin::RwLock::new(()); - /// - /// fn demo() { - /// let lock = RW_LOCK.read(); - /// // do something with lock - /// drop(lock); - /// } - /// ``` - #[inline] - pub const fn new(data: T) -> Self { - RwLock { - phantom: PhantomData, - lock: AtomicUsize::new(0), - data: UnsafeCell::new(data), - } - } - - /// Consumes this `RwLock`, returning the underlying data. - #[inline] - pub fn into_inner(self) -> T { - // We know statically that there are no outstanding references to - // `self` so there's no need to lock. - let RwLock { data, .. } = self; - data.into_inner() - } - /// Returns a mutable pointer to the underying data. - /// - /// This is mostly meant to be used for applications which require manual unlocking, but where - /// storing both the lock and the pointer to the inner data gets inefficient. - /// - /// While this is safe, writing to the data is undefined behavior unless the current thread has - /// acquired a write lock, and reading requires either a read or write lock. - /// - /// # Example - /// ``` - /// let lock = spin::RwLock::new(42); - /// - /// unsafe { - /// core::mem::forget(lock.write()); - /// - /// assert_eq!(lock.as_mut_ptr().read(), 42); - /// lock.as_mut_ptr().write(58); - /// - /// lock.force_write_unlock(); - /// } - /// - /// assert_eq!(*lock.read(), 58); - /// - /// ``` - #[inline(always)] - pub fn as_mut_ptr(&self) -> *mut T { - self.data.get() - } -} - -impl RwLock { - /// Locks this rwlock with shared read access, blocking the current thread - /// until it can be acquired. - /// - /// The calling thread will be blocked until there are no more writers which - /// hold the lock. There may be other readers currently inside the lock when - /// this method returns. This method does not provide any guarantees with - /// respect to the ordering of whether contentious readers or writers will - /// acquire the lock first. - /// - /// Returns an RAII guard which will release this thread's shared access - /// once it is dropped. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// { - /// let mut data = mylock.read(); - /// // The lock is now locked and the data can be read - /// println!("{}", *data); - /// // The lock is dropped - /// } - /// ``` - #[inline] - pub fn read(&self) -> RwLockReadGuard { - loop { - match self.try_read() { - Some(guard) => return guard, - None => R::relax(), - } - } - } - - /// Lock this rwlock with exclusive write access, blocking the current - /// thread until it can be acquired. - /// - /// This function will not return while other writers or other readers - /// currently have access to the lock. - /// - /// Returns an RAII guard which will drop the write access of this rwlock - /// when dropped. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// { - /// let mut data = mylock.write(); - /// // The lock is now locked and the data can be written - /// *data += 1; - /// // The lock is dropped - /// } - /// ``` - #[inline] - pub fn write(&self) -> RwLockWriteGuard { - loop { - match self.try_write_internal(false) { - Some(guard) => return guard, - None => R::relax(), - } - } - } - - /// Obtain a readable lock guard that can later be upgraded to a writable lock guard. - /// Upgrades can be done through the [`RwLockUpgradableGuard::upgrade`](RwLockUpgradableGuard::upgrade) method. - #[inline] - pub fn upgradeable_read(&self) -> RwLockUpgradableGuard { - loop { - match self.try_upgradeable_read() { - Some(guard) => return guard, - None => R::relax(), - } - } - } -} - -impl RwLock { - // Acquire a read lock, returning the new lock value. - fn acquire_reader(&self) -> usize { - // An arbitrary cap that allows us to catch overflows long before they happen - const MAX_READERS: usize = core::usize::MAX / READER / 2; - - let value = self.lock.fetch_add(READER, Ordering::Acquire); - - if value > MAX_READERS * READER { - self.lock.fetch_sub(READER, Ordering::Relaxed); - panic!("Too many lock readers, cannot safely proceed"); - } else { - value - } - } - - /// Attempt to acquire this lock with shared read access. - /// - /// This function will never block and will return immediately if `read` - /// would otherwise succeed. Returns `Some` of an RAII guard which will - /// release the shared access of this thread when dropped, or `None` if the - /// access could not be granted. This method does not provide any - /// guarantees with respect to the ordering of whether contentious readers - /// or writers will acquire the lock first. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// { - /// match mylock.try_read() { - /// Some(data) => { - /// // The lock is now locked and the data can be read - /// println!("{}", *data); - /// // The lock is dropped - /// }, - /// None => (), // no cigar - /// }; - /// } - /// ``` - #[inline] - pub fn try_read(&self) -> Option> { - let value = self.acquire_reader(); - - // We check the UPGRADED bit here so that new readers are prevented when an UPGRADED lock is held. - // This helps reduce writer starvation. - if value & (WRITER | UPGRADED) != 0 { - // Lock is taken, undo. - self.lock.fetch_sub(READER, Ordering::Release); - None - } else { - Some(RwLockReadGuard { - lock: &self.lock, - data: unsafe { &*self.data.get() }, - }) - } - } - - /// Return the number of readers that currently hold the lock (including upgradable readers). - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - pub fn reader_count(&self) -> usize { - let state = self.lock.load(Ordering::Relaxed); - state / READER + (state & UPGRADED) / UPGRADED - } - - /// Return the number of writers that currently hold the lock. - /// - /// Because [`RwLock`] guarantees exclusive mutable access, this function may only return either `0` or `1`. - /// - /// # Safety - /// - /// This function provides no synchronization guarantees and so its result should be considered 'out of date' - /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. - pub fn writer_count(&self) -> usize { - (self.lock.load(Ordering::Relaxed) & WRITER) / WRITER - } - - /// Force decrement the reader count. - /// - /// # Safety - /// - /// This is *extremely* unsafe if there are outstanding `RwLockReadGuard`s - /// live, or if called more times than `read` has been called, but can be - /// useful in FFI contexts where the caller doesn't know how to deal with - /// RAII. The underlying atomic operation uses `Ordering::Release`. - #[inline] - pub unsafe fn force_read_decrement(&self) { - debug_assert!(self.lock.load(Ordering::Relaxed) & !WRITER > 0); - self.lock.fetch_sub(READER, Ordering::Release); - } - - /// Force unlock exclusive write access. - /// - /// # Safety - /// - /// This is *extremely* unsafe if there are outstanding `RwLockWriteGuard`s - /// live, or if called when there are current readers, but can be useful in - /// FFI contexts where the caller doesn't know how to deal with RAII. The - /// underlying atomic operation uses `Ordering::Release`. - #[inline] - pub unsafe fn force_write_unlock(&self) { - debug_assert_eq!(self.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED), 0); - self.lock.fetch_and(!(WRITER | UPGRADED), Ordering::Release); - } - - #[inline(always)] - fn try_write_internal(&self, strong: bool) -> Option> { - if compare_exchange( - &self.lock, - 0, - WRITER, - Ordering::Acquire, - Ordering::Relaxed, - strong, - ) - .is_ok() - { - Some(RwLockWriteGuard { - phantom: PhantomData, - inner: self, - data: unsafe { &mut *self.data.get() }, - }) - } else { - None - } - } - - /// Attempt to lock this rwlock with exclusive write access. - /// - /// This function does not ever block, and it will return `None` if a call - /// to `write` would otherwise block. If successful, an RAII guard is - /// returned. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// { - /// match mylock.try_write() { - /// Some(mut data) => { - /// // The lock is now locked and the data can be written - /// *data += 1; - /// // The lock is implicitly dropped - /// }, - /// None => (), // no cigar - /// }; - /// } - /// ``` - #[inline] - pub fn try_write(&self) -> Option> { - self.try_write_internal(true) - } - - /// Tries to obtain an upgradeable lock guard. - #[inline] - pub fn try_upgradeable_read(&self) -> Option> { - if self.lock.fetch_or(UPGRADED, Ordering::Acquire) & (WRITER | UPGRADED) == 0 { - Some(RwLockUpgradableGuard { - phantom: PhantomData, - inner: self, - data: unsafe { &*self.data.get() }, - }) - } else { - // We can't unflip the UPGRADED bit back just yet as there is another upgradeable or write lock. - // When they unlock, they will clear the bit. - None - } - } - - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows the `RwLock` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. - /// - /// # Examples - /// - /// ``` - /// let mut lock = spin::RwLock::new(0); - /// *lock.get_mut() = 10; - /// assert_eq!(*lock.read(), 10); - /// ``` - pub fn get_mut(&mut self) -> &mut T { - // We know statically that there are no other references to `self`, so - // there's no need to lock the inner lock. - unsafe { &mut *self.data.get() } - } -} - -impl fmt::Debug for RwLock { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.try_read() { - Some(guard) => write!(f, "RwLock {{ data: ") - .and_then(|()| (&*guard).fmt(f)) - .and_then(|()| write!(f, "}}")), - None => write!(f, "RwLock {{ }}"), - } - } -} - -impl Default for RwLock { - fn default() -> Self { - Self::new(Default::default()) - } -} - -impl From for RwLock { - fn from(data: T) -> Self { - Self::new(data) - } -} - -impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { - /// Leak the lock guard, yielding a reference to the underlying data. - /// - /// Note that this function will permanently lock the original lock for all but reading locks. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let data: &i32 = spin::RwLockReadGuard::leak(mylock.read()); - /// - /// assert_eq!(*data, 0); - /// ``` - #[inline] - pub fn leak(this: Self) -> &'rwlock T { - let this = ManuallyDrop::new(this); - // Safety: We know statically that only we are referencing data - unsafe { &*this.data } - } -} - -impl<'rwlock, T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'rwlock, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'rwlock, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized, R: RelaxStrategy> RwLockUpgradableGuard<'rwlock, T, R> { - /// Upgrades an upgradeable lock guard to a writable lock guard. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let upgradeable = mylock.upgradeable_read(); // Readable, but not yet writable - /// let writable = upgradeable.upgrade(); - /// ``` - #[inline] - pub fn upgrade(mut self) -> RwLockWriteGuard<'rwlock, T, R> { - loop { - self = match self.try_upgrade_internal(false) { - Ok(guard) => return guard, - Err(e) => e, - }; - - R::relax(); - } - } -} - -impl<'rwlock, T: ?Sized, R> RwLockUpgradableGuard<'rwlock, T, R> { - #[inline(always)] - fn try_upgrade_internal(self, strong: bool) -> Result, Self> { - if compare_exchange( - &self.inner.lock, - UPGRADED, - WRITER, - Ordering::Acquire, - Ordering::Relaxed, - strong, - ) - .is_ok() - { - let inner = self.inner; - - // Forget the old guard so its destructor doesn't run (before mutably aliasing data below) - mem::forget(self); - - // Upgrade successful - Ok(RwLockWriteGuard { - phantom: PhantomData, - inner, - data: unsafe { &mut *inner.data.get() }, - }) - } else { - Err(self) - } - } - - /// Tries to upgrade an upgradeable lock guard to a writable lock guard. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// let upgradeable = mylock.upgradeable_read(); // Readable, but not yet writable - /// - /// match upgradeable.try_upgrade() { - /// Ok(writable) => /* upgrade successful - use writable lock guard */ (), - /// Err(upgradeable) => /* upgrade unsuccessful */ (), - /// }; - /// ``` - #[inline] - pub fn try_upgrade(self) -> Result, Self> { - self.try_upgrade_internal(true) - } - - #[inline] - /// Downgrades the upgradeable lock guard to a readable, shared lock guard. Cannot fail and is guaranteed not to spin. - /// - /// ``` - /// let mylock = spin::RwLock::new(1); - /// - /// let upgradeable = mylock.upgradeable_read(); - /// assert!(mylock.try_read().is_none()); - /// assert_eq!(*upgradeable, 1); - /// - /// let readable = upgradeable.downgrade(); // This is guaranteed not to spin - /// assert!(mylock.try_read().is_some()); - /// assert_eq!(*readable, 1); - /// ``` - pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> { - // Reserve the read guard for ourselves - self.inner.acquire_reader(); - - let inner = self.inner; - - // Dropping self removes the UPGRADED bit - mem::drop(self); - - RwLockReadGuard { - lock: &inner.lock, - data: unsafe { &*inner.data.get() }, - } - } - - /// Leak the lock guard, yielding a reference to the underlying data. - /// - /// Note that this function will permanently lock the original lock. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let data: &i32 = spin::RwLockUpgradableGuard::leak(mylock.upgradeable_read()); - /// - /// assert_eq!(*data, 0); - /// ``` - #[inline] - pub fn leak(this: Self) -> &'rwlock T { - let this = ManuallyDrop::new(this); - // Safety: We know statically that only we are referencing data - unsafe { &*this.data } - } -} - -impl<'rwlock, T: ?Sized + fmt::Debug, R> fmt::Debug for RwLockUpgradableGuard<'rwlock, T, R> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized + fmt::Display, R> fmt::Display for RwLockUpgradableGuard<'rwlock, T, R> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized, R> RwLockWriteGuard<'rwlock, T, R> { - /// Downgrades the writable lock guard to a readable, shared lock guard. Cannot fail and is guaranteed not to spin. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let mut writable = mylock.write(); - /// *writable = 1; - /// - /// let readable = writable.downgrade(); // This is guaranteed not to spin - /// # let readable_2 = mylock.try_read().unwrap(); - /// assert_eq!(*readable, 1); - /// ``` - #[inline] - pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> { - // Reserve the read guard for ourselves - self.inner.acquire_reader(); - - let inner = self.inner; - - // Dropping self removes the UPGRADED bit - mem::drop(self); - - RwLockReadGuard { - lock: &inner.lock, - data: unsafe { &*inner.data.get() }, - } - } - - /// Downgrades the writable lock guard to an upgradable, shared lock guard. Cannot fail and is guaranteed not to spin. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let mut writable = mylock.write(); - /// *writable = 1; - /// - /// let readable = writable.downgrade_to_upgradeable(); // This is guaranteed not to spin - /// assert_eq!(*readable, 1); - /// ``` - #[inline] - pub fn downgrade_to_upgradeable(self) -> RwLockUpgradableGuard<'rwlock, T, R> { - debug_assert_eq!( - self.inner.lock.load(Ordering::Acquire) & (WRITER | UPGRADED), - WRITER - ); - - // Reserve the read guard for ourselves - self.inner.lock.store(UPGRADED, Ordering::Release); - - let inner = self.inner; - - // Dropping self removes the UPGRADED bit - mem::forget(self); - - RwLockUpgradableGuard { - phantom: PhantomData, - inner, - data: unsafe { &*inner.data.get() }, - } - } - - /// Leak the lock guard, yielding a mutable reference to the underlying data. - /// - /// Note that this function will permanently lock the original lock. - /// - /// ``` - /// let mylock = spin::RwLock::new(0); - /// - /// let data: &mut i32 = spin::RwLockWriteGuard::leak(mylock.write()); - /// - /// *data = 1; - /// assert_eq!(*data, 1); - /// ``` - #[inline] - pub fn leak(this: Self) -> &'rwlock mut T { - let mut this = ManuallyDrop::new(this); - // Safety: We know statically that only we are referencing data - unsafe { &mut *this.data } - } -} - -impl<'rwlock, T: ?Sized + fmt::Debug, R> fmt::Debug for RwLockWriteGuard<'rwlock, T, R> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized + fmt::Display, R> fmt::Display for RwLockWriteGuard<'rwlock, T, R> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { - type Target = T; - - fn deref(&self) -> &T { - // Safety: We know statically that only we are referencing data - unsafe { &*self.data } - } -} - -impl<'rwlock, T: ?Sized, R> Deref for RwLockUpgradableGuard<'rwlock, T, R> { - type Target = T; - - fn deref(&self) -> &T { - // Safety: We know statically that only we are referencing data - unsafe { &*self.data } - } -} - -impl<'rwlock, T: ?Sized, R> Deref for RwLockWriteGuard<'rwlock, T, R> { - type Target = T; - - fn deref(&self) -> &T { - // Safety: We know statically that only we are referencing data - unsafe { &*self.data } - } -} - -impl<'rwlock, T: ?Sized, R> DerefMut for RwLockWriteGuard<'rwlock, T, R> { - fn deref_mut(&mut self) -> &mut T { - // Safety: We know statically that only we are referencing data - unsafe { &mut *self.data } - } -} - -impl<'rwlock, T: ?Sized> Drop for RwLockReadGuard<'rwlock, T> { - fn drop(&mut self) { - debug_assert!(self.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED) > 0); - self.lock.fetch_sub(READER, Ordering::Release); - } -} - -impl<'rwlock, T: ?Sized, R> Drop for RwLockUpgradableGuard<'rwlock, T, R> { - fn drop(&mut self) { - debug_assert_eq!( - self.inner.lock.load(Ordering::Relaxed) & (WRITER | UPGRADED), - UPGRADED - ); - self.inner.lock.fetch_sub(UPGRADED, Ordering::AcqRel); - } -} - -impl<'rwlock, T: ?Sized, R> Drop for RwLockWriteGuard<'rwlock, T, R> { - fn drop(&mut self) { - debug_assert_eq!(self.inner.lock.load(Ordering::Relaxed) & WRITER, WRITER); - - // Writer is responsible for clearing both WRITER and UPGRADED bits. - // The UPGRADED bit may be set if an upgradeable lock attempts an upgrade while this lock is held. - self.inner - .lock - .fetch_and(!(WRITER | UPGRADED), Ordering::Release); - } -} - -#[inline(always)] -fn compare_exchange( - atomic: &AtomicUsize, - current: usize, - new: usize, - success: Ordering, - failure: Ordering, - strong: bool, -) -> Result { - if strong { - atomic.compare_exchange(current, new, success, failure) - } else { - atomic.compare_exchange_weak(current, new, success, failure) - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawRwLock for RwLock<(), R> { - type GuardMarker = lock_api_crate::GuardSend; - - const INIT: Self = Self::new(()); - - #[inline(always)] - fn lock_exclusive(&self) { - // Prevent guard destructor running - core::mem::forget(self.write()); - } - - #[inline(always)] - fn try_lock_exclusive(&self) -> bool { - // Prevent guard destructor running - self.try_write().map(|g| core::mem::forget(g)).is_some() - } - - #[inline(always)] - unsafe fn unlock_exclusive(&self) { - drop(RwLockWriteGuard { - inner: self, - data: &mut (), - phantom: PhantomData, - }); - } - - #[inline(always)] - fn lock_shared(&self) { - // Prevent guard destructor running - core::mem::forget(self.read()); - } - - #[inline(always)] - fn try_lock_shared(&self) -> bool { - // Prevent guard destructor running - self.try_read().map(|g| core::mem::forget(g)).is_some() - } - - #[inline(always)] - unsafe fn unlock_shared(&self) { - drop(RwLockReadGuard { - lock: &self.lock, - data: &(), - }); - } - - #[inline(always)] - fn is_locked(&self) -> bool { - self.lock.load(Ordering::Relaxed) != 0 - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawRwLockUpgrade for RwLock<(), R> { - #[inline(always)] - fn lock_upgradable(&self) { - // Prevent guard destructor running - core::mem::forget(self.upgradeable_read()); - } - - #[inline(always)] - fn try_lock_upgradable(&self) -> bool { - // Prevent guard destructor running - self.try_upgradeable_read() - .map(|g| core::mem::forget(g)) - .is_some() - } - - #[inline(always)] - unsafe fn unlock_upgradable(&self) { - drop(RwLockUpgradableGuard { - inner: self, - data: &(), - phantom: PhantomData, - }); - } - - #[inline(always)] - unsafe fn upgrade(&self) { - let tmp_guard = RwLockUpgradableGuard { - inner: self, - data: &(), - phantom: PhantomData, - }; - core::mem::forget(tmp_guard.upgrade()); - } - - #[inline(always)] - unsafe fn try_upgrade(&self) -> bool { - let tmp_guard = RwLockUpgradableGuard { - inner: self, - data: &(), - phantom: PhantomData, - }; - tmp_guard - .try_upgrade() - .map(|g| core::mem::forget(g)) - .is_ok() - } -} - -#[cfg(feature = "lock_api")] -unsafe impl lock_api_crate::RawRwLockDowngrade for RwLock<(), R> { - unsafe fn downgrade(&self) { - let tmp_guard = RwLockWriteGuard { - inner: self, - data: &mut (), - phantom: PhantomData, - }; - core::mem::forget(tmp_guard.downgrade()); - } -} - -#[cfg(feature = "lock_api1")] -unsafe impl lock_api::RawRwLockUpgradeDowngrade for RwLock<()> { - unsafe fn downgrade_upgradable(&self) { - let tmp_guard = RwLockUpgradableGuard { - inner: self, - data: &(), - phantom: PhantomData, - }; - core::mem::forget(tmp_guard.downgrade()); - } - - unsafe fn downgrade_to_upgradable(&self) { - let tmp_guard = RwLockWriteGuard { - inner: self, - data: &mut (), - phantom: PhantomData, - }; - core::mem::forget(tmp_guard.downgrade_to_upgradeable()); - } -} - -#[cfg(test)] -mod tests { - use std::prelude::v1::*; - - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::mpsc::channel; - use std::sync::Arc; - use std::thread; - - type RwLock = super::RwLock; - - #[derive(Eq, PartialEq, Debug)] - struct NonCopy(i32); - - #[test] - fn smoke() { - let l = RwLock::new(()); - drop(l.read()); - drop(l.write()); - drop((l.read(), l.read())); - drop(l.write()); - } - - // TODO: needs RNG - //#[test] - //fn frob() { - // static R: RwLock = RwLock::new(); - // const N: usize = 10; - // const M: usize = 1000; - // - // let (tx, rx) = channel::<()>(); - // for _ in 0..N { - // let tx = tx.clone(); - // thread::spawn(move|| { - // let mut rng = rand::thread_rng(); - // for _ in 0..M { - // if rng.gen_weighted_bool(N) { - // drop(R.write()); - // } else { - // drop(R.read()); - // } - // } - // drop(tx); - // }); - // } - // drop(tx); - // let _ = rx.recv(); - // unsafe { R.destroy(); } - //} - - #[test] - fn test_rw_arc() { - let arc = Arc::new(RwLock::new(0)); - let arc2 = arc.clone(); - let (tx, rx) = channel(); - - let t = thread::spawn(move || { - let mut lock = arc2.write(); - for _ in 0..10 { - let tmp = *lock; - *lock = -1; - thread::yield_now(); - *lock = tmp + 1; - } - tx.send(()).unwrap(); - }); - - // Readers try to catch the writer in the act - let mut children = Vec::new(); - for _ in 0..5 { - let arc3 = arc.clone(); - children.push(thread::spawn(move || { - let lock = arc3.read(); - assert!(*lock >= 0); - })); - } - - // Wait for children to pass their asserts - for r in children { - assert!(r.join().is_ok()); - } - - // Wait for writer to finish - rx.recv().unwrap(); - let lock = arc.read(); - assert_eq!(*lock, 10); - - assert!(t.join().is_ok()); - } - - #[test] - fn test_rw_access_in_unwind() { - let arc = Arc::new(RwLock::new(1)); - let arc2 = arc.clone(); - let _ = thread::spawn(move || -> () { - struct Unwinder { - i: Arc>, - } - impl Drop for Unwinder { - fn drop(&mut self) { - let mut lock = self.i.write(); - *lock += 1; - } - } - let _u = Unwinder { i: arc2 }; - panic!(); - }) - .join(); - let lock = arc.read(); - assert_eq!(*lock, 2); - } - - #[test] - fn test_rwlock_unsized() { - let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]); - { - let b = &mut *rw.write(); - b[0] = 4; - b[2] = 5; - } - let comp: &[i32] = &[4, 2, 5]; - assert_eq!(&*rw.read(), comp); - } - - #[test] - fn test_rwlock_try_write() { - use std::mem::drop; - - let lock = RwLock::new(0isize); - let read_guard = lock.read(); - - let write_result = lock.try_write(); - match write_result { - None => (), - Some(_) => assert!( - false, - "try_write should not succeed while read_guard is in scope" - ), - } - - drop(read_guard); - } - - #[test] - fn test_rw_try_read() { - let m = RwLock::new(0); - ::std::mem::forget(m.write()); - assert!(m.try_read().is_none()); - } - - #[test] - fn test_into_inner() { - let m = RwLock::new(NonCopy(10)); - assert_eq!(m.into_inner(), NonCopy(10)); - } - - #[test] - fn test_into_inner_drop() { - struct Foo(Arc); - impl Drop for Foo { - fn drop(&mut self) { - self.0.fetch_add(1, Ordering::SeqCst); - } - } - let num_drops = Arc::new(AtomicUsize::new(0)); - let m = RwLock::new(Foo(num_drops.clone())); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - { - let _inner = m.into_inner(); - assert_eq!(num_drops.load(Ordering::SeqCst), 0); - } - assert_eq!(num_drops.load(Ordering::SeqCst), 1); - } - - #[test] - fn test_force_read_decrement() { - let m = RwLock::new(()); - ::std::mem::forget(m.read()); - ::std::mem::forget(m.read()); - ::std::mem::forget(m.read()); - assert!(m.try_write().is_none()); - unsafe { - m.force_read_decrement(); - m.force_read_decrement(); - } - assert!(m.try_write().is_none()); - unsafe { - m.force_read_decrement(); - } - assert!(m.try_write().is_some()); - } - - #[test] - fn test_force_write_unlock() { - let m = RwLock::new(()); - ::std::mem::forget(m.write()); - assert!(m.try_read().is_none()); - unsafe { - m.force_write_unlock(); - } - assert!(m.try_read().is_some()); - } - - #[test] - fn test_upgrade_downgrade() { - let m = RwLock::new(()); - { - let _r = m.read(); - let upg = m.try_upgradeable_read().unwrap(); - assert!(m.try_read().is_none()); - assert!(m.try_write().is_none()); - assert!(upg.try_upgrade().is_err()); - } - { - let w = m.write(); - assert!(m.try_upgradeable_read().is_none()); - let _r = w.downgrade(); - assert!(m.try_upgradeable_read().is_some()); - assert!(m.try_read().is_some()); - assert!(m.try_write().is_none()); - } - { - let _u = m.upgradeable_read(); - assert!(m.try_upgradeable_read().is_none()); - } - - assert!(m.try_upgradeable_read().unwrap().try_upgrade().is_ok()); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"e58d6ca3bc691221bb37ea20808b6168e7120494124e9b0aa7080acff3236c57","Cargo.lock":"81f573ca2ff7a97a07356e6676fc8ec0cd5ad645d79453329147899c92b82e03","Cargo.toml":"5cddd84a243940e60e772ecba2f05b28b00cbd825d341d9e0b0881dcae7847dc","Cargo.toml.orig":"e0d471ba7acef517f26f4c34c4017d78436999bcfdbd9f11338df3fce732cc7f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5e05b024f653a5ce199e77cbbbd42fb5553562ec714b819421ed0c3e552a75d7","README.md":"750fc2d57412de57566289e567b5674a666cc7a8a054f8c7129b8553f9003de7","src/lib.rs":"4736941fa6c790367158082cb55e5fc89aba7c7f0a85405aada8271fbb5c87ad"},"package":"6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "30002b4228f7cdee309217b6bf6eee099dda0b00" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "stable_deref_trait" +version = "1.2.1" +authors = ["Robert Grosse "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +An unsafe marker trait for types like Box and Rc that dereference to a stable address even when moved, and hence can be used with libraries such as owning_ref and rental. +""" +documentation = "https://docs.rs/stable_deref_trait/1.2.1/stable_deref_trait" +readme = "README.md" +categories = [ + "memory-management", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/storyyeller/stable_deref_trait" + +[features] +alloc = [] +default = ["std"] +std = ["alloc"] + +[lib] +name = "stable_deref_trait" +path = "src/lib.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,17 @@ +[package] +name = "stable_deref_trait" +version = "1.2.1" +authors = ["Robert Grosse "] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/storyyeller/stable_deref_trait" +documentation = "https://docs.rs/stable_deref_trait/1.2.1/stable_deref_trait" +categories = ["memory-management", "no-std"] +description = """ +An unsafe marker trait for types like Box and Rc that dereference to a stable address even when moved, and hence can be used with libraries such as owning_ref and rental. +""" + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright (c) 2017 Robert Grosse + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/README.md clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +This crate defines an unsafe marker trait, StableDeref, for container types which deref to a fixed address which is valid even when the containing type is moved. For example, Box, Vec, Rc, Arc and String implement this trait. Additionally, it defines CloneStableDeref for types like Rc where clones deref to the same address. + +It is intended to be used by crates such as [owning_ref](https://crates.io/crates/owning_ref) and [rental](https://crates.io/crates/rental), as well as library authors who wish to make their code interoperable with such crates. For example, if you write a custom Vec type, you can implement StableDeref, and then users will be able to use your custom Vec type together with owning_ref and rental. + +no_std support can be enabled by disabling default features (specifically "std"). In this case, the trait will not be implemented for the std types mentioned above, but you can still use it for your own types. + +Enable the "alloc" feature (with default-features disabled) to have this trait be implemented for the above types from the built-in `alloc` crate, specifically +* `alloc::boxed::Box` +* `alloc::vec::Vec` +* `alloc::rc::Rc` +* `alloc::arc::Arc` +* `alloc::string::String` + +For example, this crate can be built with alloc support via the following command: +`cargo build --no-default-features --features alloc` + +Or added as a `Cargo.toml` dependency as follows: +``` +[dependencies.stable_deref_trait] +version = "" +default-features = false +features = [ "alloc" ] +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/stable_deref_trait/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/stable_deref_trait/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,202 @@ +// Copyright 2017 Robert Grosse + +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! +This module defines an unsafe marker trait, StableDeref, for container types that deref to a fixed address which is valid even when the containing type is moved. For example, Box, Vec, Rc, Arc and String implement this trait. Additionally, it defines CloneStableDeref for types like Rc where clones deref to the same address. + +It is intended to be used by crates such as [owning_ref](https://crates.io/crates/owning_ref) and [rental](https://crates.io/crates/rental), as well as library authors who wish to make their code interoperable with such crates. For example, if you write a custom Vec type, you can implement StableDeref, and then users will be able to use your custom type together with owning_ref and rental. + +no_std support can be enabled by disabling default features (specifically "std"). In this case, the trait will not be implemented for the std types mentioned above, but you can still use it for your own types. +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate core; + +#[cfg(feature = "alloc")] +extern crate alloc; + +use core::ops::Deref; + + +/** +An unsafe marker trait for types that deref to a stable address, even when moved. For example, this is implemented by Box, Vec, Rc, Arc and String, among others. Even when a Box is moved, the underlying storage remains at a fixed location. + +More specifically, implementors must ensure that the result of calling deref() is valid for the lifetime of the object, not just the lifetime of the borrow, and that the deref is valid even if the object is moved. Also, it must be valid even after invoking arbitrary &self methods or doing anything transitively accessible from &Self. If Self also implements DerefMut, the same restrictions apply to deref_mut() and it must remain valid if anything transitively accessible from the result of deref_mut() is mutated/called. Additionally, multiple calls to deref, (and deref_mut if implemented) must return the same address. No requirements are placed on &mut self methods other than deref_mut() and drop(), if applicable. + +Basically, it must be valid to convert the result of deref() to a pointer, and later dereference that pointer, as long as the original object is still live, even if it has been moved or &self methods have been called on it. If DerefMut is also implemented, it must be valid to get pointers from deref() and deref_mut() and dereference them while the object is live, as long as you don't simultaneously dereference both of them. + +Additionally, Deref and DerefMut implementations must not panic, but users of the trait are not allowed to rely on this fact (so that this restriction can be removed later without breaking backwards compatibility, should the need arise). + +Here are some examples to help illustrate the requirements for implementing this trait: + +``` +# use std::ops::Deref; +struct Foo(u8); +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { &self.0 } +} +``` + +Foo cannot implement StableDeref because the int will move when Foo is moved, invalidating the result of deref(). + +``` +# use std::ops::Deref; +struct Foo(Box); +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { &*self.0 } +} +``` + +Foo can safely implement StableDeref, due to the use of Box. + + +``` +# use std::ops::Deref; +# use std::ops::DerefMut; +# use std::rc::Rc; +#[derive(Clone)] +struct Foo(Rc); +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { &*self.0 } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { Rc::make_mut(&mut self.0) } +} +``` + +This is a simple implementation of copy-on-write: Foo's deref_mut will copy the underlying int if it is not uniquely owned, ensuring unique access at the point where deref_mut() returns. However, Foo cannot implement StableDeref because calling deref_mut(), followed by clone().deref() will result in mutable and immutable references to the same location. Note that if the DerefMut implementation were removed, Foo could safely implement StableDeref. Likewise, if the Clone implementation were removed, it would be safe to implement StableDeref, although Foo would not be very useful in that case, (without clones, the rc will always be uniquely owned). + + +``` +# use std::ops::Deref; +struct Foo; +impl Deref for Foo { + type Target = str; + fn deref(&self) -> &Self::Target { &"Hello" } +} +``` +Foo can safely implement StableDeref. It doesn't own the data being derefed, but the data is gaurenteed to live long enough, due to it being 'static. + +``` +# use std::ops::Deref; +# use std::cell::Cell; +struct Foo(Cell); +impl Deref for Foo { + type Target = str; + fn deref(&self) -> &Self::Target { + let b = self.0.get(); + self.0.set(!b); + if b { &"Hello" } else { &"World" } + } +} +``` +Foo cannot safely implement StableDeref, even though every possible result of deref lives long enough. In order to safely implement StableAddress, multiple calls to deref must return the same result. + +``` +# use std::ops::Deref; +# use std::ops::DerefMut; +struct Foo(Box<(u8, u8)>); +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { &self.0.deref().0 } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0.deref_mut().1 } +} +``` + +Foo cannot implement StableDeref because deref and deref_mut return different addresses. + + +*/ +pub unsafe trait StableDeref: Deref {} + +/** +An unsafe marker trait for types where clones deref to the same address. This has all the requirements of StableDeref, and additionally requires that after calling clone(), both the old and new value deref to the same address. For example, Rc and Arc implement CloneStableDeref, but Box and Vec do not. + +Note that a single type should never implement both DerefMut and CloneStableDeref. If it did, this would let you get two mutable references to the same location, by cloning and then calling deref_mut() on both values. +*/ +pub unsafe trait CloneStableDeref: StableDeref + Clone {} + +///////////////////////////////////////////////////////////////////////////// +// std types integration +///////////////////////////////////////////////////////////////////////////// + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use alloc::rc::Rc; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +use alloc::sync::Arc; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::borrow::Cow; + +#[cfg(feature = "std")] +use std::ffi::{CStr, CString, OsStr, OsString}; +#[cfg(feature = "std")] +use std::path::{Path, PathBuf}; +#[cfg(feature = "std")] +use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; + +use core::cell::{Ref, RefMut}; + + +#[cfg(feature = "alloc")] +unsafe impl StableDeref for Box {} +#[cfg(feature = "alloc")] +unsafe impl StableDeref for Vec {} +#[cfg(feature = "alloc")] +unsafe impl StableDeref for String {} +#[cfg(feature = "std")] +unsafe impl StableDeref for CString {} +#[cfg(feature = "std")] +unsafe impl StableDeref for OsString {} +#[cfg(feature = "std")] +unsafe impl StableDeref for PathBuf {} + +#[cfg(feature = "alloc")] +unsafe impl<'a> StableDeref for Cow<'a, str> {} +#[cfg(feature = "alloc")] +unsafe impl<'a, T: Clone> StableDeref for Cow<'a, [T]> {} +#[cfg(feature = "std")] +unsafe impl<'a> StableDeref for Cow<'a, Path> {} +#[cfg(feature = "std")] +unsafe impl<'a> StableDeref for Cow<'a, CStr> {} +#[cfg(feature = "std")] +unsafe impl<'a> StableDeref for Cow<'a, OsStr> {} + +#[cfg(feature = "alloc")] +unsafe impl StableDeref for Rc {} +#[cfg(feature = "alloc")] +unsafe impl CloneStableDeref for Rc {} +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +unsafe impl StableDeref for Arc {} +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +unsafe impl CloneStableDeref for Arc {} + +unsafe impl<'a, T: ?Sized> StableDeref for Ref<'a, T> {} +unsafe impl<'a, T: ?Sized> StableDeref for RefMut<'a, T> {} +#[cfg(feature = "std")] +unsafe impl<'a, T: ?Sized> StableDeref for MutexGuard<'a, T> {} +#[cfg(feature = "std")] +unsafe impl<'a, T: ?Sized> StableDeref for RwLockReadGuard<'a, T> {} +#[cfg(feature = "std")] +unsafe impl<'a, T: ?Sized> StableDeref for RwLockWriteGuard<'a, T> {} + +unsafe impl<'a, T: ?Sized> StableDeref for &'a T {} +unsafe impl<'a, T: ?Sized> CloneStableDeref for &'a T {} +unsafe impl<'a, T: ?Sized> StableDeref for &'a mut T {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"2a80bb7afb8a09be6edc8b8577963aa379d6271c0c69bff391424c5e1c30ec7f","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"ef31f30f87b3fe79c8d812bb48d6979d7837a42cafb68eb34843e6362a6a6779","RELEASES.md":"521f39813791dd8fa841faeca4483f7f282b9ccea4a50ee98c03dc150f77f20e","benches/strength_reduce_benchmarks.rs":"f06353806d67ba60fe2143c6f918c98036b92e91b19b2fbf1aceec99665cc4c1","src/lib.rs":"d952ce89a6f055eeea5999c11809c5fc08ebccc9b81f1ab6dbb19befe825c1ee","src/long_division.rs":"5acd73fc66fbafd3ecc3b9235bc6b84563f99c1b7d433d30bf1a5cf7af5bbe63","src/long_multiplication.rs":"447645bb90b630b94543d9f9379b93ae40806c6f90bafc7cd1cee1c45aad4930","tests/test_reduced_unsigned.rs":"ed6dc73e09bd323574dfbd7b60ac4731d2dcbaebde5bf82c6741a5f9b3e5f852"},"package":"fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"49ea4c58a69a8cbee088ade3bdb221ea873c330e26f03633e167b758417cd62e","Cargo.toml":"2a80bb7afb8a09be6edc8b8577963aa379d6271c0c69bff391424c5e1c30ec7f","Cargo.toml.orig":"4dbc73ee0e0cc4c762f5c31c91dfe0af34d56631e6ca73bdccb162bc0271a5ce","LICENSE-APACHE":"2e54cd84a645bea25943c75dd8ae67cb291e66a47a11578333c9b4b3b6b86c85","LICENSE-MIT":"8f5442dfa8e9169045697e386bc91d19f393c939635741fa2a665ec36ca6f0ad","README.md":"ef31f30f87b3fe79c8d812bb48d6979d7837a42cafb68eb34843e6362a6a6779","RELEASES.md":"521f39813791dd8fa841faeca4483f7f282b9ccea4a50ee98c03dc150f77f20e","benches/strength_reduce_benchmarks.rs":"f06353806d67ba60fe2143c6f918c98036b92e91b19b2fbf1aceec99665cc4c1","src/lib.rs":"d952ce89a6f055eeea5999c11809c5fc08ebccc9b81f1ab6dbb19befe825c1ee","src/long_division.rs":"5acd73fc66fbafd3ecc3b9235bc6b84563f99c1b7d433d30bf1a5cf7af5bbe63","src/long_multiplication.rs":"447645bb90b630b94543d9f9379b93ae40806c6f90bafc7cd1cee1c45aad4930","tests/test_reduced_unsigned.rs":"ed6dc73e09bd323574dfbd7b60ac4731d2dcbaebde5bf82c6741a5f9b3e5f852"},"package":"fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "5b0a43d9d672ee2ac4e471f201fb13417a0a0c71" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/strength_reduce/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/strength_reduce/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,19 @@ +[package] +name = "strength_reduce" +version = "0.2.4" +authors = ["Elliott Mahler "] + +description = "Faster integer division and modulus operations" + +license = "MIT OR Apache-2.0" + +repository = "http://github.com/ejmahler/strength_reduce" +documentation = "http://docs.rs/strength_reduce" +keywords = ["arithmetic", "strength", "reduction", "division", "modulus"] +categories = ["algorithms", "data-structures"] +readme = "README.md" + +[dev-dependencies] +proptest = "1.0.0" +num-bigint = "0.4" +rand = "0.8" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/syn/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"c683a33b5b98518b938d8b93561120cd52e75a8fdd955050f9719ddc6041ecf8","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"684c75ce029ed7c4ad57cb12fcecfee86d521699c3332c6c4c57af98f6e3b276","benches/file.rs":"0a0527c78d849148cbb6118b4d36f72da7d4add865ba1a410e0a1be9e8dbfe0e","benches/rust.rs":"77342ecd278686080c6390e84d70ecb4a31cc696d45dc4b8ddcc5ca65a25bcfb","src/attr.rs":"7dc328025f9def00f634b1de958a93ac2b2f3fdfb11411600861c556bc821262","src/bigint.rs":"0299829b2f7a1a798fe2f7bc1680e4a10f9b6f4a852d09af4da2deab466c4242","src/buffer.rs":"3add7b427ecb446250482be7fdd7c2ccb1d0ad9775b646a58ada9ab2075a2be3","src/custom_keyword.rs":"322114e36ae43a2f8605506fb4568efdbc2986853e2fee74bd10a4ca0fb60c69","src/custom_punctuation.rs":"2ae2339c29b1aff3ab16157d51a3a07bfca594aa38586981534fe07a62cdd9d1","src/data.rs":"921eecc6a9909004019922c2f8fe217f45f75556c8d7e59d731c43b825330539","src/derive.rs":"8bb147e2e4490ccd891d71c5889904fb2718a2204d4597e337b3a8926f0fd52c","src/discouraged.rs":"c246e96f7b25cc0af11944766e1ce176be8c396447bb696769b73c4d9bb5cfcf","src/drops.rs":"013385f1dd95663f1afab41abc1e2eea04181998644828935ca564c74d6462ae","src/error.rs":"1cf4643232ba10e12d5a4dd080b1371efc1fda08b928e7b2ae149fe4fedf89e7","src/export.rs":"b260cc49da1da3489e7755832bc8015cfad79e84f6c74e237f65ae25a2385e56","src/expr.rs":"0e76516c5d811e1020ad76a9c2eb06694225ea5db04b21ebe94839abce73f915","src/ext.rs":"ed143b029af286e62ceb4310286a4ce894792dd588465face042b4199b39d329","src/file.rs":"fed5e195883cbea7b764fcb1e53a95b0d6ab834618d6c67cb9ec70bfea90cdbf","src/gen/clone.rs":"6608b5a4071706ccc555cc28fe1fb00cd4e76aece530eb12abf38e0a6c74fd36","src/gen/debug.rs":"18c36796349a7da2020cce7e573e2717992557e4db23f5b5291dc98bc764c6f5","src/gen/eq.rs":"a58660b1ad0714460c32e2c6f0ad7cda75970ecddbb763ce2dd61ebe2f1790eb","src/gen/fold.rs":"353d75c6e9e22ffd670f6b6cf01f813c91bb00f08729efdef1ea9b1231fd4196","src/gen/hash.rs":"2baf9741453ed1fc8248d2081cd33b5d2283ce6f153779e5f1fbcb9f4686f3c2","src/gen/visit.rs":"d5a6488be780904ba2dad092899114d33672680a193e1fdd112244e85f0324e2","src/gen/visit_mut.rs":"4f92be7f2f10a335b3f917383dadaac1f0ffd9e9ed16a1d7ad5cab9f586aaed2","src/gen_helper.rs":"750caab67ba0ba11a95ea28cd38026485227bb4aa114cdb497472386f60fdb35","src/generics.rs":"628f5d7157106db018b6f901e6c85b5c40a9c4b3cdf2bb4787691d5f570f6bc0","src/group.rs":"f5911e9cf2dc2dffab546590167c48de30409cb7708aa3307d22be143df720e4","src/ident.rs":"f93f74d04776e749607e944e30ce4396ec146dce41c64710f4cd7f323b75dca4","src/item.rs":"f5ca9a2de9a4d1dbe638f671870a4feca6590dce279b34457069383dce8d4c3a","src/lib.rs":"6b93b0eb9a0bdfe185f12d2cf3f29519cff48d631f43afd0edfd63295b2afc63","src/lifetime.rs":"f77ac2f4ee9205c71db9c6b63e1b90eac4b5ecfa330c553b7bbbf5400a65150b","src/lit.rs":"c78011f24ae963ec95fdac63bd8b1f6d5e8b972b93b5d00d108eee50007cf99c","src/lookahead.rs":"376092f91a1c32e1b277db0a6790fdda151c9ec51bd971fe6a6545b5b9e73b5d","src/mac.rs":"deacf75bb99af8ea0d6a5ca54504b75b8cf9d814ad7d4148bb5d533c7f1e1aed","src/macros.rs":"e68e246752d67307f9afb5ada6c1d689ddc0b0d9a51d40ba6191427d1e1b8bdc","src/meta.rs":"969d8ccbdbc6ea2e4928a21831b791c57447b231e1373149e4c63b46f3951801","src/op.rs":"410a5cbc596afa81cfdf66c65ba2e21be7105b819a2a705dc0c0e6363ff1a715","src/parse.rs":"96a772c6e18f4d33f14cf8e021bd6f1ee338daded4b5d476fc8fcc5110a29bc1","src/parse_macro_input.rs":"4a753b2a6dbfefd6dc93852d66b4f6d73ebd6b8b9be74019fc476f429b9a892d","src/parse_quote.rs":"c9065c39465543f91828d207d73354372a5aeda1d8d76c6ce47ddb7c33677c66","src/pat.rs":"d1fb776758e2fd74b3ef14d205d28c62e4bfd4279b37b7ca30af2683b51f6045","src/path.rs":"c5a496bb7911685cbf14c8a4526f1821139409779b8d3145f6c7c67ebb067ba2","src/print.rs":"22910bf0521ab868ebd7c62601c55912d12cfb400c65723e08e5cfa3a2d111c0","src/punctuated.rs":"9ec8876d49cc4aa67cfda7d6b5abef83315ec86985cf8189c22af859fa8c6085","src/restriction.rs":"e3bfe3c43083640224557f2130a8ea543ad929df66cb511d5ad661f534e3ab6b","src/sealed.rs":"6ece3b3dcb30f6bb98b93d83759ca7712ee8592bef9c0511141039c38765db0e","src/span.rs":"0a48e375e5c9768f6f64174a91ba6a255f4b021e2fb3548d8494e617f142601b","src/spanned.rs":"4b9bd65f60ab81922adfd0be8f03b6d50e98da3a5f525f242f9639aec4beac79","src/stmt.rs":"f404d8baa742a40c76244eda6f1a8560851ce6db0edd0d030bfe3bc12a233f72","src/thread.rs":"1f1deb1272525ab2af9a36aac4bce8f65b0e315adb1656641fd7075662f49222","src/token.rs":"e6b2373fb0465158d267bd25eac16266bd4b492d7dbe8ae4b5405a841a1ac57d","src/tt.rs":"a58303a95d08d6bf3f3e09715b9b70a57b91b54774cfc1f00f2848034d2ff5c7","src/ty.rs":"e5f754d037bfc32a99dc5bddbba05c6b405e3b2655d95fdcab05d6d8cf17612d","src/verbatim.rs":"87cbe82a90f48efb57ffd09141042698b3e011a21d0d5412154d80324b0a5ef0","src/whitespace.rs":"9cdcbfe9045b259046329a795bc1105ab5a871471a6d3f7318d275ee53f7a825","tests/common/eq.rs":"e97dc41032ed84d8fd2b74c1d2292782fd5c0aca222d00f73f5c770cee3f6c29","tests/common/mod.rs":"9037196b3df17f651d112bc0d14c01b38e927292c0028e17bb3547eb67f90e4c","tests/common/parse.rs":"fff650bb98a9382beefbd22d2a89c0c8f90501dd6d58abc4d12b29cb4f647dc7","tests/debug/gen.rs":"3ca161a049fe72ff73ead99fbfe78335fdb2ac7c41085fe8cd0c9a0b29995151","tests/debug/mod.rs":"b56136586267ae1812a937b69215dd053ada2c21717771d89dcd3ce52bcb27f5","tests/macros/mod.rs":"64b0da858096e7cf0f772e66bc1787a867e45897d7677de580c0a1f35c0f6852","tests/regression.rs":"e9565ea0efecb4136f099164ffcfa26e1996b0a27fb9c6659e90ad9bdd42e7b6","tests/regression/issue1108.rs":"f32db35244a674e22ff824ca9e5bbec2184e287b59f022db68c418b5878a2edc","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"749acfef11cf128a027a67378cd00907a6cb946f884ba23aa2c67af0ac49dfcb","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"8982f6bc4e36510f924e288247473403e72697389ce9dda4e4b5ab0a8e49259f","tests/test_attribute.rs":"b35550a43bbd187bb330997ba36f90c65d8fc489135b1d32ef4547f145cb7612","tests/test_derive_input.rs":"99c4e6e45e3322ea9e269b309059c8a00fda1dcc03aed41f6e7d8c7e0a72fa2b","tests/test_expr.rs":"f7726efc959b860aa8aca6c51bc10c466cb1957774c1dfac24c3907cd8ea99a6","tests/test_generics.rs":"2fcc8575d695b568f3724b3b33d853b8fa6d9864eb816b5e3ca82420682e6155","tests/test_grouping.rs":"1bd63c8ca0b90bd493fb3f927079ab9ddf74d2a78da82db2f638e652d22305d5","tests/test_ident.rs":"d5850e817720e774cd397a46dbc5298c57933823c18e20805e84503fc9387e8f","tests/test_item.rs":"1b8412a5581adf93eaa215785a592f139af8511c954dee283d52dff2718a6cc2","tests/test_iterators.rs":"f4dacb5f3a8e0473dfb0d27f05270d41e79eddb4759b1fad3e88e379b4731e17","tests/test_lit.rs":"01b0acfe03cff16e7c1a45ceb7f4b637e5cbc6145840886ba981b7ed8e83691c","tests/test_meta.rs":"70fd75b42d1d913f05825c9e8280a4802e81de0b2343ad876850d2b7c588f0bf","tests/test_parse_buffer.rs":"8739e6b2aaf8d5b24e45a3cf7fc01b47c1a0699e0a388c453cff7687984c1ed6","tests/test_parse_quote.rs":"928176da6ebb449ef01a798f3352c9b181d3077c1266eb008df73876f4013c47","tests/test_parse_stream.rs":"f17e2feabbac87601d82fd7aa7bc31e879cf4349ce2c8c4aab420db2ab83bbd3","tests/test_pat.rs":"f6954a50e62a97ac2bc1ba0cb7a5a1fc53b7b01fb55ffe0176bee3fe1955d460","tests/test_path.rs":"d54350aa91508f8d301f5be3e3a34e03b0615b1a04e8fbbab9840da20161838b","tests/test_precedence.rs":"078113e6b7e2a86a97a600e6ddcc91b8e0a48e2a48d0f89b31374a730b969e14","tests/test_receiver.rs":"af64117acd66fbf42edc476f731ecd20c88009d9cb641dbd7a1d6384ae99ae73","tests/test_round_trip.rs":"a85054fff7721cf6cf2a8deb834b0e8912fc1843201cce1fbe738f92f1c2b401","tests/test_shebang.rs":"98e8a6690c04e0aad2893b747593620b51836fe704f50f5c6fe352609837138a","tests/test_size.rs":"b446868d55ae820196aad03dba3aa3529b727ac0465113c6fc66706423a73350","tests/test_stmt.rs":"bbc305ea888254798b6faf285187d8bc7a955e4402d9a497d4b9d361e0436691","tests/test_token_trees.rs":"d012da9c3c861073711b006bf6ffdc073821fb9fb0a08733628cdae57124d1f5","tests/test_ty.rs":"49fbb880891d4c2e21350e35b914d92aa9a056fbaad9c4afa5242802848fe9c4","tests/test_visibility.rs":"7bd239aef6f6d8173462dbd869064f3fdb9ba71644ac1f62c5d2fbb2568fb986","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"f3e0116a7b5e2df49af20c3259680490c7043a046ab7bd25e4b176e98bdf8029","Cargo.lock":"98db16fc8899b508330bf6c6adc721c2f2d60f8683eba448e217a17e3d35bd53","Cargo.toml":"2e4d3ff5d9e3d288b1b78798f3f55999f6cf19504508008c675b1f06e1e52a98","Cargo.toml.orig":"1152a76817f5a4267d9b96a329372671422874e181b83b8f22ea242e5585f4d6","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"84d8f027ce3c19ae9cf91e68207b0bc737b71aa25706ba575bef7d4cba6fc937","benches/file.rs":"6f2ae7748d1576cff48e4ef55d4e87e2f5bb7898a36aa99ea6dd6ed0f72a4e3c","benches/rust.rs":"53cb8accfda73e59a3efc78081e7c58a1010ae60c23ef8c43bb240550daa3e96","src/attr.rs":"f44ff3cb9d3bc34d7de9e3f1aba62ddb1c8973881d9db981623b112005d4ed53","src/bigint.rs":"0299829b2f7a1a798fe2f7bc1680e4a10f9b6f4a852d09af4da2deab466c4242","src/buffer.rs":"f95f513d3a68e5c851aa5c0f0d2922bfdbc882efc6ee501561cdd8e562afd8ec","src/classify.rs":"3c796df4c891034abc3008196d34ad62c22fcb9525a067890731a5a6bbc7b5fb","src/custom_keyword.rs":"322114e36ae43a2f8605506fb4568efdbc2986853e2fee74bd10a4ca0fb60c69","src/custom_punctuation.rs":"26b28164f0b2e5e80e7cf36a3ba6d2577d27442cce5e00a72f685b5ee6f51ecd","src/data.rs":"fa04dce757ca3dd1e350aaa84bbcf8b743c13a00b0983b980bf2919f91a22078","src/derive.rs":"f54f8cf9386a2d45186ff3c86ade5dae59e0e337b0198532449190ae8520cff8","src/discouraged.rs":"653c5d9e6c4e3c2359817dc343f145569a0c9562a707f4949c374c242955ce12","src/drops.rs":"e98da4aaafb5afc75919f9e2914326ad09bf16094a9407c60a05515a2e01dd00","src/error.rs":"cbf06fb7b000f2e6444fa224a062c493911a8f9fc5d386be6e52dadbb7658f34","src/export.rs":"b260cc49da1da3489e7755832bc8015cfad79e84f6c74e237f65ae25a2385e56","src/expr.rs":"fa766ce749ea31367e178f45a2dc8f8545b9467f7fc51e7a1fe72bbb0b9738dc","src/ext.rs":"57577c7e6b7b65cd27ac5aad66d47e63693762d8880cde088b20975ec845244d","src/file.rs":"9d04206da5eff88e92698b3f78c51082d615300cb11d93768250a3e97c40b078","src/fixup.rs":"7647cde30efdce96b1488ae805788c168d4499b464b7d421abc17ea8ffde66f2","src/gen/clone.rs":"7af00b0a240453d7aac178be1b6cdf9df3b33f1281da35e02f66ba7ba55d060c","src/gen/debug.rs":"59bc259fa9dc0c7ffe094df7ad8afc9c4e79b6d73a8f0fae8a2e435905866e7a","src/gen/eq.rs":"d7428672d82c1931fdefb8bda0425a25ebbe20e5e2736b18cfd1752b64e99f78","src/gen/fold.rs":"39b0a26cfdf0accaff6da108a2b6d8f93e83c63d0bf6a8d7af0900fc0f71b55b","src/gen/hash.rs":"6808bb0e47e7346a14fbec5f55430906efa172f46417c83c2f7c76ce8c9ceab6","src/gen/token.css":"3a5882d0b3aefbf56ca5d08c28c117e25ac2327eadf7242202d906b2ddb2232e","src/gen/visit.rs":"fe1443aa7953eaca10d6bf982396e627e31ce6b8aea8eb7cf949e0adeea5badb","src/gen/visit_mut.rs":"9948f0f07aefd8133dcc958e744c49f1da625d199f7707363b79f0373b2dcd6b","src/generics.rs":"a3f21805d9224dad98bd9442d7d66129cdb8772ca76eca73ffea7cefe8d1bfcf","src/group.rs":"61e067094aa930b6550dc3717a5aaeef7dabfdcf1a177f83fb636598fa7e4e72","src/ident.rs":"d6061030fadae9c7dc847e1ee46178d9657d782aad108c7197e8cafe765b3eaa","src/item.rs":"ad2d5f4621426420ba4dc0c1a82626b7b0979cb67c06fbcb16ee6abb025e7c80","src/lib.rs":"b05b11e6b5e597990b7316cbdf1750ef2d6911f0b926dda617f6ad1f99e82412","src/lifetime.rs":"ec748fdbdedeb75c4dbc4460653cf97fcf113207eea5b12fea9e1f6e1198beca","src/lit.rs":"b8e9d48ffabdcc27330010ef415078179f950b8a5cfd7c89516bcee0ee492e35","src/lookahead.rs":"b2837d80fa4466bb430b65d32b54d1bad5de9bb851550f916658347145c281b4","src/mac.rs":"fdce8291f71adef3f69975f229156dca2309ca232ed943061afaf96220908ab8","src/macros.rs":"2a6e895dfe1c3a9a7237b5e23358ca5d8967e2beae6d094dda68d3659f9a5c84","src/meta.rs":"969d8ccbdbc6ea2e4928a21831b791c57447b231e1373149e4c63b46f3951801","src/op.rs":"a61757370f802e44efa3c4a1057ae2cd26e64e273f7d76c06d5ffb49602319e2","src/parse.rs":"bbe69237d50ce5f9b5c029e851607c54ca6232cad0790551c2f5bb29e2f9657d","src/parse_macro_input.rs":"e4e22b63d0496d06a4ca17742a22467ed93f08a739081324773828bad63175ee","src/parse_quote.rs":"80eec7ce54c38f3bbd23acb70cd8a6649d7e1523c3977e3bf12849fd8c5cf16d","src/pat.rs":"b6c8c04c330a76dbe9cd35949026724fc3aeacf98e8c0a259cf2e16caff99071","src/path.rs":"2146bdf5e0eb6991232c8a09de3a30440727f439ab792a34f5313057c091a724","src/precedence.rs":"58420a5015003ecd4d7a4a0c87c168caa4c696e646355523d9eaae81fc5e1d54","src/print.rs":"22910bf0521ab868ebd7c62601c55912d12cfb400c65723e08e5cfa3a2d111c0","src/punctuated.rs":"711c1f9122f560530d40bdccbd8784b6c2c54067f0d753cce282a4d6ca933a37","src/restriction.rs":"a7152ec5a4ee4f55446019aa2b4d84f2238776f0e6ffc0c22adf3374b517fe56","src/scan_expr.rs":"e199c35e8bbf3e2c70901e1175df8dd446f4cb67b60100647f478f2dc31f6f12","src/sealed.rs":"6ece3b3dcb30f6bb98b93d83759ca7712ee8592bef9c0511141039c38765db0e","src/span.rs":"0a48e375e5c9768f6f64174a91ba6a255f4b021e2fb3548d8494e617f142601b","src/spanned.rs":"4b9bd65f60ab81922adfd0be8f03b6d50e98da3a5f525f242f9639aec4beac79","src/stmt.rs":"7a594d08cbedef4c6c0ed6ca9c331f4f087bd631a12938240180f7c53ada44e9","src/thread.rs":"1f1deb1272525ab2af9a36aac4bce8f65b0e315adb1656641fd7075662f49222","src/token.rs":"55f1ad3ba0edc43ae7b65a6fa6dc13fc1a99053d6300187a4cc48572b8f451f3","src/tt.rs":"ad478bef531007fac0e4af7ecae81f8fe66a5ce44532288156b7e3d4bfc45950","src/ty.rs":"b7daaf57dd96fc09448e45fc92f55b00f3b7ba99a00f3f2eb8a11f35e302af3c","src/verbatim.rs":"4aa06d0ce2f6b6c6aa657bc349ccc85005d2eb05494dfa1ac1fe9012916dcc3e","src/whitespace.rs":"9cdcbfe9045b259046329a795bc1105ab5a871471a6d3f7318d275ee53f7a825","tests/common/eq.rs":"bc4bce28319e376e782b0a5c297ca171682dd4c620d9d54c0ab70b63872e42e8","tests/common/mod.rs":"b752aa8f1faf8c6abf1286a12fb50b6c257ec1889d81bcdb3dc3257134695a89","tests/common/parse.rs":"f226bfa84803429c4ef203a09b30372db01298e14443089fb60c11e2112212db","tests/common/visit.rs":"a260ecd2ce7853cd3644e19aba08e8d358a656fd3fb0f1287cea40c59c9e62c9","tests/debug/gen.rs":"cdd89f1bf91fe215e06868fc93423d2f1872c812c3bfec93dc920bc105e20c09","tests/debug/mod.rs":"1259df940bbcaa968a837e402d6853f2efa38d2260e306d42f17f9e8ef74fae5","tests/macros/mod.rs":"d2294a79e341c623ae671dd363e99965d78dda7f340b0cc038267207adfacae2","tests/regression.rs":"e9565ea0efecb4136f099164ffcfa26e1996b0a27fb9c6659e90ad9bdd42e7b6","tests/regression/issue1108.rs":"f32db35244a674e22ff824ca9e5bbec2184e287b59f022db68c418b5878a2edc","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"4e2d370876192fc0514962e1eeb9e1e4a96e3805b1f87257ba4d1eeda8b1db73","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/snapshot/mod.rs":"4a101272c5abe6ca9f3501e0cacacee9a0ccf7ca773348a239e5b046d0316a7e","tests/test_asyncness.rs":"971d560d927d5a8494eaa7fce8f0d062d6971c17c4c464fcfc31570572b7d3d7","tests/test_attribute.rs":"8a4429b7cfe2360bb73beae54a62ae3255ebbd5181467a8608d6f858c2711728","tests/test_derive_input.rs":"c8f5dbac6482dadd0fab30d0b1fe3254869256c48ea68ea484cad7f7406c8568","tests/test_expr.rs":"055cb9b33a5bb6ed5dc67491e6f1ae794a53a5a091245debd464ef57144f5edb","tests/test_generics.rs":"5c9b34813a442311fdca36b56736dd15760e7f6d6a668f82673c21711e1aacd8","tests/test_grouping.rs":"fe3de6e8824f0722ab6450c6dfc374f6e0f8fe75c87c4dd56b2cb00a2197ed58","tests/test_ident.rs":"d5850e817720e774cd397a46dbc5298c57933823c18e20805e84503fc9387e8f","tests/test_item.rs":"f4119000784af2d65d5fd097830368a391c05b249f3df8c60613a98b16a322ca","tests/test_lit.rs":"4130efa425d14ed3ad9a1c2a00ef4b29782c9d1cf9e29ff9dddd3b23b2e3ddee","tests/test_meta.rs":"5b0fdee0decbd07476c9673403a662de385901b4bf60600c26ac879893f5bf9c","tests/test_parse_buffer.rs":"1c8cbbf457603bd0a83348079591f843f7ef0533a6275a0c76533e2d07dd321a","tests/test_parse_quote.rs":"85d90d2d51b82aab7c30159dd884f26c592ddb28ed31ef2baf371ee31349694c","tests/test_parse_stream.rs":"b6b533432173123d6d01d8d2cb33714bc50b30b16ffbb6116f93937221ad4594","tests/test_pat.rs":"dafa3e1f51812e8c852dc5210640a4adf6fff7cd0a0790ee17d2c4c115321846","tests/test_path.rs":"7a6763a262c41a9522068887702fe7cd4ff72b07da5253ac47761d73315b021d","tests/test_precedence.rs":"f0654b7bf85e2852f7229b14aaba7fcae87d9691f6fa91ab315bc6b0249ffccf","tests/test_punctuated.rs":"efed2c281b6965d71b065c7606631ba1989af6e7b5f5d1ca1033f8b968dc076c","tests/test_receiver.rs":"2053028236f95f3cb508ebf2eb606df43cae4f9f4dd27823661459ff6c54a39c","tests/test_round_trip.rs":"8b2ed3c4164247577953e3108cca67eed97761c90b9c0df31cbd50097ed1a047","tests/test_shebang.rs":"9bc24b1ee2947b06a279d2ed40039cb45bba6caf7cd40530d93f7e2355de53c6","tests/test_size.rs":"03efaf829b80b7db1f831474c1d3ce268914fc499d0e2a7eea03cad04a482974","tests/test_stmt.rs":"b3c120059d7b56388963b85234feb2e4d379e32a0bf7f29b6683eca000dd3919","tests/test_token_trees.rs":"c30b921a96739c9334ec2bdd06552729891e0251b9d8fbdf0b8f5cc897babee5","tests/test_ty.rs":"9bb5f632941451ca6b200100310b55e62a9956190df3efe28b80d42843e75362","tests/test_unparenthesize.rs":"e5c047819afd5f70fde1bdd095467b1291d0854641f21e8183e50919986d8ce7","tests/test_visibility.rs":"7d05f05b0782976369d21477ac9f4d35a7c7f36faa42127e3a9c12ada270baf8","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/syn/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8cfa32aed0dfdff00360cf5d2111b2e1ccbf2bfe" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2093 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "automod" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb4bd301db2e2ca1f5be131c24eb8ebf2d9559bc3744419e93baf8ddea7e670" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "aws-lc-rs" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "cc" +version = "1.2.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "insta" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983e3b24350c84ab8a65151f537d67afbbf7153bb9f1110e03e9fa9b07f67a5c" +dependencies = [ + "console", + "once_cell", + "similar", + "tempfile", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.179" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "reqwest" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.113" +dependencies = [ + "anyhow", + "automod", + "flate2", + "insta", + "proc-macro2", + "quote", + "rayon", + "ref-cast", + "reqwest", + "rustversion", + "syn-test-suite", + "tar", + "termcolor", + "unicode-ident", + "walkdir", +] + +[[package]] +name = "syn-test-suite" +version = "0.0.0+test" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d661992f60e67c8bdd9a7d6360d30d1301f5783abf7d59933844f656762eb5" + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.112", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,10 +11,11 @@ [package] edition = "2021" -rust-version = "1.60" +rust-version = "1.68" name = "syn" -version = "2.0.60" +version = "2.0.113" authors = ["David Tolnay "] +build = false include = [ "/benches/**", "/Cargo.toml", @@ -24,6 +25,11 @@ "/src/**", "/tests/**", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Parser for Rust source code" documentation = "https://docs.rs/syn" readme = "README.md" @@ -40,12 +46,16 @@ [package.metadata.docs.rs] all-features = true +targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ - "--cfg", - "doc_cfg", "--generate-link-to-definition", + "--generate-macro-expansion", + "--extend-css=src/gen/token.css", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] -targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] features = [ @@ -56,26 +66,164 @@ "extra-traits", ] +[features] +clone-impls = [] +default = [ + "derive", + "parsing", + "printing", + "clone-impls", + "proc-macro", +] +derive = [] +extra-traits = [] +fold = [] +full = [] +parsing = [] +printing = ["dep:quote"] +proc-macro = [ + "proc-macro2/proc-macro", + "quote?/proc-macro", +] +test = ["syn-test-suite/all-features"] +visit = [] +visit-mut = [] + [lib] -doc-scrape-examples = false +name = "syn" +path = "src/lib.rs" + +[[test]] +name = "regression" +path = "tests/regression.rs" + +[[test]] +name = "test_asyncness" +path = "tests/test_asyncness.rs" + +[[test]] +name = "test_attribute" +path = "tests/test_attribute.rs" + +[[test]] +name = "test_derive_input" +path = "tests/test_derive_input.rs" + +[[test]] +name = "test_expr" +path = "tests/test_expr.rs" + +[[test]] +name = "test_generics" +path = "tests/test_generics.rs" + +[[test]] +name = "test_grouping" +path = "tests/test_grouping.rs" + +[[test]] +name = "test_ident" +path = "tests/test_ident.rs" + +[[test]] +name = "test_item" +path = "tests/test_item.rs" + +[[test]] +name = "test_lit" +path = "tests/test_lit.rs" + +[[test]] +name = "test_meta" +path = "tests/test_meta.rs" + +[[test]] +name = "test_parse_buffer" +path = "tests/test_parse_buffer.rs" + +[[test]] +name = "test_parse_quote" +path = "tests/test_parse_quote.rs" + +[[test]] +name = "test_parse_stream" +path = "tests/test_parse_stream.rs" + +[[test]] +name = "test_pat" +path = "tests/test_pat.rs" + +[[test]] +name = "test_path" +path = "tests/test_path.rs" + +[[test]] +name = "test_precedence" +path = "tests/test_precedence.rs" + +[[test]] +name = "test_punctuated" +path = "tests/test_punctuated.rs" + +[[test]] +name = "test_receiver" +path = "tests/test_receiver.rs" + +[[test]] +name = "test_round_trip" +path = "tests/test_round_trip.rs" + +[[test]] +name = "test_shebang" +path = "tests/test_shebang.rs" + +[[test]] +name = "test_size" +path = "tests/test_size.rs" + +[[test]] +name = "test_stmt" +path = "tests/test_stmt.rs" + +[[test]] +name = "test_token_trees" +path = "tests/test_token_trees.rs" + +[[test]] +name = "test_ty" +path = "tests/test_ty.rs" + +[[test]] +name = "test_unparenthesize" +path = "tests/test_unparenthesize.rs" + +[[test]] +name = "test_visibility" +path = "tests/test_visibility.rs" + +[[test]] +name = "zzz_stable" +path = "tests/zzz_stable.rs" [[bench]] -name = "rust" -harness = false +name = "file" +path = "benches/file.rs" required-features = [ "full", "parsing", ] [[bench]] -name = "file" +name = "rust" +path = "benches/rust.rs" +harness = false required-features = [ "full", "parsing", ] [dependencies.proc-macro2] -version = "1.0.80" +version = "1.0.91" default-features = false [dependencies.quote] @@ -92,56 +240,33 @@ [dev-dependencies.automod] version = "1" -[dev-dependencies.flate2] -version = "1" - [dev-dependencies.insta] version = "1" -[dev-dependencies.rayon] -version = "1" - [dev-dependencies.ref-cast] version = "1" -[dev-dependencies.reqwest] -version = "0.12" -features = ["blocking"] - [dev-dependencies.rustversion] version = "1" [dev-dependencies.syn-test-suite] version = "0" -[dev-dependencies.tar] -version = "0.4.16" - [dev-dependencies.termcolor] version = "1" -[dev-dependencies.walkdir] -version = "2.3.2" +[target."cfg(not(miri))".dev-dependencies.flate2] +version = "1" -[features] -clone-impls = [] -default = [ - "derive", - "parsing", - "printing", - "clone-impls", - "proc-macro", -] -derive = [] -extra-traits = [] -fold = [] -full = [] -parsing = [] -printing = ["dep:quote"] -proc-macro = [ - "proc-macro2/proc-macro", - "quote?/proc-macro", -] -test = ["syn-test-suite/all-features"] -visit = [] -visit-mut = [] +[target."cfg(not(miri))".dev-dependencies.rayon] +version = "1" + +[target."cfg(not(miri))".dev-dependencies.reqwest] +version = "0.13" +features = ["blocking"] + +[target."cfg(not(miri))".dev-dependencies.tar] +version = "0.4.16" + +[target."cfg(not(miri))".dev-dependencies.walkdir] +version = "2.3.2" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/syn/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,95 @@ +[package] +name = "syn" +version = "2.0.113" +authors = ["David Tolnay "] +categories = ["development-tools::procedural-macro-helpers", "parser-implementations"] +description = "Parser for Rust source code" +documentation = "https://docs.rs/syn" +edition = "2021" +include = [ + "/benches/**", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src/**", + "/tests/**", +] +keywords = ["macros", "syn"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/syn" +rust-version = "1.68" + +[features] +default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] +derive = [] +full = [] +parsing = [] +printing = ["dep:quote"] +visit = [] +visit-mut = [] +fold = [] +clone-impls = [] +extra-traits = [] +proc-macro = ["proc-macro2/proc-macro", "quote?/proc-macro"] +test = ["syn-test-suite/all-features"] + +[dependencies] +proc-macro2 = { version = "1.0.91", default-features = false } +quote = { version = "1.0.35", optional = true, default-features = false } +unicode-ident = "1" + +[dev-dependencies] +anyhow = "1" +automod = "1" +insta = "1" +ref-cast = "1" +rustversion = "1" +syn-test-suite = { version = "0", path = "tests/features" } +termcolor = "1" + +[target.'cfg(not(miri))'.dev-dependencies] +flate2 = "1" +rayon = "1" +reqwest = { version = "0.13", features = ["blocking"] } +tar = "0.4.16" +walkdir = "2.3.2" + +[[bench]] +name = "rust" +harness = false +required-features = ["full", "parsing"] + +[[bench]] +name = "file" +required-features = ["full", "parsing"] + +[package.metadata.docs.rs] +all-features = true +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extend-css=src/gen/token.css", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", +] + +[package.metadata.playground] +features = ["full", "visit", "visit-mut", "fold", "extra-traits"] + +[workspace] +members = [ + "dev", + "examples/dump-syntax", + "examples/heapsize/example", + "examples/heapsize/heapsize", + "examples/heapsize/heapsize_derive", + "examples/lazy-static/example", + "examples/lazy-static/lazy-static", + "examples/trace-var/example", + "examples/trace-var/trace-var", + "tests/features", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/README.md clamav-1.4.6+dfsg/.cargo/vendor/syn/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/syn/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -46,8 +46,6 @@ [`syn::DeriveInput`]: https://docs.rs/syn/2.0/syn/struct.DeriveInput.html [parser functions]: https://docs.rs/syn/2.0/syn/parse/index.html -*Version requirement: Syn supports rustc 1.60 and up.* - [*Release notes*](https://github.com/dtolnay/syn/releases)
diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/benches/file.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/file.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/benches/file.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/file.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,11 +3,13 @@ #![feature(rustc_private, test)] #![recursion_limit = "1024"] #![allow( + clippy::elidable_lifetime_names, clippy::items_after_statements, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::missing_panics_doc, clippy::must_use_candidate, + clippy::needless_lifetimes, clippy::uninlined_format_args )] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/benches/rust.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/rust.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/benches/rust.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/benches/rust.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,9 +8,11 @@ #![allow( clippy::arc_with_non_send_sync, clippy::cast_lossless, + clippy::elidable_lifetime_names, clippy::let_underscore_untyped, clippy::manual_let_else, clippy::match_like_matches_macro, + clippy::needless_lifetimes, clippy::uninlined_format_args, clippy::unnecessary_wraps )] @@ -24,20 +26,24 @@ mod repo; use std::fs; +use std::path::Path; use std::time::{Duration, Instant}; #[cfg(not(syn_only))] mod tokenstream_parse { use proc_macro2::TokenStream; + use std::path::Path; use std::str::FromStr; - pub fn bench(content: &str) -> Result<(), ()> { + pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { TokenStream::from_str(content).map(drop).map_err(drop) } } mod syn_parse { - pub fn bench(content: &str) -> Result<(), ()> { + use std::path::Path; + + pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { syn::parse_file(content).map(drop).map_err(drop) } } @@ -52,45 +58,49 @@ extern crate rustc_session; extern crate rustc_span; - use rustc_data_structures::sync::Lrc; - use rustc_error_messages::FluentBundle; - use rustc_errors::{emitter::Emitter, translation::Translate, DiagCtxt, DiagInner}; + use crate::repo; + use rustc_errors::emitter::Emitter; + use rustc_errors::registry::Registry; + use rustc_errors::translation::Translator; + use rustc_errors::{DiagCtxt, DiagInner}; + use rustc_parse::lexer::StripTokens; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FilePathMapping, SourceMap}; - use rustc_span::{edition::Edition, FileName}; + use rustc_span::FileName; + use std::path::Path; + use std::sync::Arc; - pub fn bench(content: &str) -> Result<(), ()> { + pub fn bench(path: &Path, content: &str) -> Result<(), ()> { struct SilentEmitter; impl Emitter for SilentEmitter { - fn emit_diagnostic(&mut self, _diag: DiagInner) {} - fn source_map(&self) -> Option<&Lrc> { - None - } - } - - impl Translate for SilentEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {} + fn source_map(&self) -> Option<&SourceMap> { None } - fn fallback_fluent_bundle(&self) -> &FluentBundle { + fn translator(&self) -> &Translator { panic!("silent emitter attempted to translate a diagnostic"); } } - rustc_span::create_session_if_not_set_then(Edition::Edition2018, |_| { - let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let edition = repo::edition(path).parse().unwrap(); + rustc_span::create_session_if_not_set_then(edition, |_| { + let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(SilentEmitter); let handler = DiagCtxt::new(emitter); let sess = ParseSess::with_dcx(handler, source_map); - if let Err(diagnostic) = rustc_parse::parse_crate_from_source_str( - FileName::Custom("bench".to_owned()), - content.to_owned(), + let name = FileName::Custom("bench".to_owned()); + let mut parser = rustc_parse::new_parser_from_source_str( &sess, - ) { + name, + content.to_owned(), + StripTokens::ShebangAndFrontmatter, + ) + .unwrap(); + if let Err(diagnostic) = parser.parse_crate_mod() { diagnostic.cancel(); return Err(()); - }; + } Ok(()) }) } @@ -98,13 +108,15 @@ #[cfg(not(syn_only))] mod read_from_disk { - pub fn bench(content: &str) -> Result<(), ()> { + use std::path::Path; + + pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { let _ = content; Ok(()) } } -fn exec(mut codepath: impl FnMut(&str) -> Result<(), ()>) -> Duration { +fn exec(mut codepath: impl FnMut(&Path, &str) -> Result<(), ()>) -> Duration { let begin = Instant::now(); let mut success = 0; let mut total = 0; @@ -123,7 +135,7 @@ return; } let content = fs::read_to_string(path).unwrap(); - let ok = codepath(&content).is_ok(); + let ok = codepath(path, &content).is_ok(); success += ok as usize; total += 1; if !ok { @@ -143,7 +155,7 @@ [ $( $(#[$cfg])* - (stringify!($name), $name::bench as fn(&str) -> Result<(), ()>), + (stringify!($name), $name::bench as fn(&Path, &str) -> Result<(), ()>), )* ] }; @@ -153,7 +165,7 @@ { let mut lines = 0; let mut files = 0; - exec(|content| { + exec(|_path, content| { lines += content.lines().count(); files += 1; Ok(()) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/attr.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/attr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/attr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/attr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -169,7 +169,7 @@ /// }; /// assert_eq!(doc, attr); /// ``` - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Attribute { pub pound_token: Token![#], pub style: AttrStyle, @@ -218,7 +218,7 @@ /// # anyhow::Ok(()) /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args(&self) -> Result { self.parse_args_with(T::parse) } @@ -241,7 +241,7 @@ /// # anyhow::Ok(()) /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args_with(&self, parser: F) -> Result { match &self.meta { Meta::Path(path) => Err(crate::error::new2( @@ -387,7 +387,7 @@ /// # Ok(()) /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta) -> Result<()>, @@ -402,7 +402,7 @@ /// See /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_outer(input: ParseStream) -> Result> { let mut attrs = Vec::new(); while input.peek(Token![#]) { @@ -418,7 +418,7 @@ /// See /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_inner(input: ParseStream) -> Result> { let mut attrs = Vec::new(); parsing::parse_inner(input, &mut attrs)?; @@ -441,14 +441,14 @@ /// - `#![feature(proc_macro)]` /// - `//! # Example` /// - `/*! Please file an issue */` - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum AttrStyle { Outer, Inner(Token![!]), } } -ast_enum_of_structs! { +ast_enum! { /// Content of a compile-time structured attribute. /// /// ## Path @@ -469,7 +469,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Meta { Path(Path), @@ -483,7 +483,7 @@ ast_struct! { /// A structured list within an attribute, like `derive(Copy, Clone)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct MetaList { pub path: Path, pub delimiter: MacroDelimiter, @@ -493,7 +493,7 @@ ast_struct! { /// A name-value pair within an attribute, like `feature = "nightly"`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct MetaNameValue { pub path: Path, pub eq_token: Token![=], @@ -516,7 +516,7 @@ /// Error if this is a `Meta::List` or `Meta::NameValue`. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_path_only(&self) -> Result<&Path> { let error_span = match self { Meta::Path(path) => return Ok(path), @@ -528,7 +528,7 @@ /// Error if this is a `Meta::Path` or `Meta::NameValue`. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_list(&self) -> Result<&MetaList> { match self { Meta::List(meta) => Ok(meta), @@ -546,7 +546,7 @@ /// Error if this is a `Meta::Path` or `Meta::List`. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_name_value(&self) -> Result<&MetaNameValue> { match self { Meta::NameValue(meta) => Ok(meta), @@ -566,14 +566,14 @@ impl MetaList { /// See [`Attribute::parse_args`]. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args(&self) -> Result { self.parse_args_with(T::parse) } /// See [`Attribute::parse_args_with`]. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args_with(&self, parser: F) -> Result { let scope = self.delimiter.span().close(); crate::parse::parse_scoped(parser, scope, self.tokens.clone()) @@ -581,7 +581,7 @@ /// See [`Attribute::parse_nested_meta`]. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta) -> Result<()>, @@ -625,6 +625,24 @@ } } +impl From for Meta { + fn from(meta: Path) -> Meta { + Meta::Path(meta) + } +} + +impl From for Meta { + fn from(meta: MetaList) -> Meta { + Meta::List(meta) + } +} + +impl From for Meta { + fn from(meta: MetaNameValue) -> Meta { + Meta::NameValue(meta) + } +} + #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue}; @@ -635,6 +653,7 @@ use crate::parse::{Parse, ParseStream}; use crate::path::Path; use crate::{mac, token}; + use proc_macro2::Ident; use std::fmt::{self, Display}; pub(crate) fn parse_inner(input: ParseStream, attrs: &mut Vec) -> Result<()> { @@ -664,34 +683,45 @@ }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Meta { fn parse(input: ParseStream) -> Result { - let path = input.call(Path::parse_mod_style)?; + let path = parse_outermost_meta_path(input)?; parse_meta_after_path(path, input) } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for MetaList { fn parse(input: ParseStream) -> Result { - let path = input.call(Path::parse_mod_style)?; + let path = parse_outermost_meta_path(input)?; parse_meta_list_after_path(path, input) } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for MetaNameValue { fn parse(input: ParseStream) -> Result { - let path = input.call(Path::parse_mod_style)?; + let path = parse_outermost_meta_path(input)?; parse_meta_name_value_after_path(path, input) } } + // Unlike meta::parse_meta_path which accepts arbitrary keywords in the path, + // only the `unsafe` keyword is accepted as an attribute's outermost path. + fn parse_outermost_meta_path(input: ParseStream) -> Result { + if input.peek(Token![unsafe]) { + let unsafe_token: Token![unsafe] = input.parse()?; + Ok(Path::from(Ident::new("unsafe", unsafe_token.span))) + } else { + Path::parse_mod_style(input) + } + } + pub(crate) fn parse_meta_after_path(path: Path, input: ParseStream) -> Result { if input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) { parse_meta_list_after_path(path, input).map(Meta::List) - } else if input.peek(Token![=]) { + } else if input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) { parse_meta_name_value_after_path(path, input).map(Meta::NameValue) } else { Ok(Meta::Path(path)) @@ -757,11 +787,13 @@ #[cfg(feature = "printing")] mod printing { - use crate::attr::{AttrStyle, Attribute, MetaList, MetaNameValue}; + use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue}; + use crate::path; + use crate::path::printing::PathStyle; use proc_macro2::TokenStream; use quote::ToTokens; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Attribute { fn to_tokens(&self, tokens: &mut TokenStream) { self.pound_token.to_tokens(tokens); @@ -774,18 +806,29 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for Meta { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Meta::Path(path) => path::printing::print_path(tokens, path, PathStyle::Mod), + Meta::List(meta_list) => meta_list.to_tokens(tokens), + Meta::NameValue(meta_name_value) => meta_name_value.to_tokens(tokens), + } + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for MetaList { fn to_tokens(&self, tokens: &mut TokenStream) { - self.path.to_tokens(tokens); + path::printing::print_path(tokens, &self.path, PathStyle::Mod); self.delimiter.surround(tokens, self.tokens.clone()); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for MetaNameValue { fn to_tokens(&self, tokens: &mut TokenStream) { - self.path.to_tokens(tokens); + path::printing::print_path(tokens, &self.path, PathStyle::Mod); self.eq_token.to_tokens(tokens); self.value.to_tokens(tokens); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,11 +5,13 @@ // Syn, and caution should be used when editing it. The public-facing interface // is 100% safe but the implementation is fragile internally. +use crate::ext::TokenStreamExt as _; use crate::Lifetime; use proc_macro2::extra::DelimSpan; use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::cmp::Ordering; use std::marker::PhantomData; +use std::ptr; /// Internal type which is used instead of `TokenTree` to represent a token tree /// within a `TokenBuffer`. @@ -20,8 +22,9 @@ Ident(Ident), Punct(Punct), Literal(Literal), - // End entries contain the offset (negative) to the start of the buffer. - End(isize), + // End entries contain the offset (negative) to the start of the buffer, and + // offset (negative) to the matching Group entry. + End(isize, isize), } /// A buffer that can be efficiently traversed multiple times, unlike @@ -42,12 +45,15 @@ TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)), TokenTree::Group(group) => { let group_start_index = entries.len(); - entries.push(Entry::End(0)); // we replace this below + entries.push(Entry::End(0, 0)); // we replace this below Self::recursive_new(entries, group.stream()); let group_end_index = entries.len(); - entries.push(Entry::End(-(group_end_index as isize))); - let group_end_offset = group_end_index - group_start_index; - entries[group_start_index] = Entry::Group(group, group_end_offset); + let group_offset = group_end_index - group_start_index; + entries.push(Entry::End( + -(group_end_index as isize), + -(group_offset as isize), + )); + entries[group_start_index] = Entry::Group(group, group_offset); } } } @@ -56,7 +62,7 @@ /// Creates a `TokenBuffer` containing all the tokens from the input /// `proc_macro::TokenStream`. #[cfg(feature = "proc-macro")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] + #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] pub fn new(stream: proc_macro::TokenStream) -> Self { Self::new2(stream.into()) } @@ -66,7 +72,7 @@ pub fn new2(stream: TokenStream) -> Self { let mut entries = Vec::new(); Self::recursive_new(&mut entries, stream); - entries.push(Entry::End(-(entries.len() as isize))); + entries.push(Entry::End(-(entries.len() as isize), 0)); Self { entries: entries.into_boxed_slice(), } @@ -111,7 +117,7 @@ // object in global storage. struct UnsafeSyncEntry(Entry); unsafe impl Sync for UnsafeSyncEntry {} - static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0)); + static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0, 0)); Cursor { ptr: &EMPTY_ENTRY.0, @@ -128,8 +134,8 @@ // past it, unless `ptr == scope`, which means that we're at the edge of // our cursor's scope. We should only have `ptr != scope` at the exit // from None-delimited groups entered with `ignore_none`. - while let Entry::End(_) = unsafe { &*ptr } { - if ptr == scope { + while let Entry::End(..) = unsafe { &*ptr } { + if ptr::eq(ptr, scope) { break; } ptr = unsafe { ptr.add(1) }; @@ -154,7 +160,7 @@ /// If the cursor is looking at an `Entry::Group`, the bumped cursor will /// point at the first token in the group (with the same scope end). unsafe fn bump_ignore_group(self) -> Cursor<'a> { - unsafe { Cursor::create(self.ptr.offset(1), self.scope) } + unsafe { Cursor::create(self.ptr.add(1), self.scope) } } /// While the cursor is looking at a `None`-delimited group, move it to look @@ -176,53 +182,7 @@ /// scope. pub fn eof(self) -> bool { // We're at eof if we're at the end of our scope. - self.ptr == self.scope - } - - /// If the cursor is pointing at a `Group` with the given delimiter, returns - /// a cursor into that group and one pointing to the next `TokenTree`. - pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> { - // If we're not trying to enter a none-delimited group, we want to - // ignore them. We have to make sure to _not_ ignore them when we want - // to enter them, of course. For obvious reasons. - if delim != Delimiter::None { - self.ignore_none(); - } - - if let Entry::Group(group, end_offset) = self.entry() { - if group.delimiter() == delim { - let span = group.delim_span(); - let end_of_group = unsafe { self.ptr.add(*end_offset) }; - let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; - let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; - return Some((inside_of_group, span, after_group)); - } - } - - None - } - - pub(crate) fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> { - if let Entry::Group(group, end_offset) = self.entry() { - let delimiter = group.delimiter(); - let span = group.delim_span(); - let end_of_group = unsafe { self.ptr.add(*end_offset) }; - let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; - let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; - return Some((inside_of_group, delimiter, span, after_group)); - } - - None - } - - pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> { - if let Entry::Group(group, end_offset) = self.entry() { - let end_of_group = unsafe { self.ptr.add(*end_offset) }; - let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; - return Some((group.clone(), after_group)); - } - - None + ptr::eq(self.ptr, self.scope) } /// If the cursor is pointing at a `Ident`, returns it along with a cursor @@ -275,16 +235,64 @@ } } + /// If the cursor is pointing at a `Group` with the given delimiter, returns + /// a cursor into that group and one pointing to the next `TokenTree`. + pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> { + // If we're not trying to enter a none-delimited group, we want to + // ignore them. We have to make sure to _not_ ignore them when we want + // to enter them, of course. For obvious reasons. + if delim != Delimiter::None { + self.ignore_none(); + } + + if let Entry::Group(group, end_offset) = self.entry() { + if group.delimiter() == delim { + let span = group.delim_span(); + let end_of_group = unsafe { self.ptr.add(*end_offset) }; + let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; + let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; + return Some((inside_of_group, span, after_group)); + } + } + + None + } + + /// If the cursor is pointing at a `Group`, returns a cursor into the group + /// and one pointing to the next `TokenTree`. + pub fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> { + if let Entry::Group(group, end_offset) = self.entry() { + let delimiter = group.delimiter(); + let span = group.delim_span(); + let end_of_group = unsafe { self.ptr.add(*end_offset) }; + let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; + let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; + return Some((inside_of_group, delimiter, span, after_group)); + } + + None + } + + pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> { + if let Entry::Group(group, end_offset) = self.entry() { + let end_of_group = unsafe { self.ptr.add(*end_offset) }; + let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; + return Some((group.clone(), after_group)); + } + + None + } + /// Copies all remaining tokens visible from this cursor into a /// `TokenStream`. pub fn token_stream(self) -> TokenStream { - let mut tts = Vec::new(); + let mut tokens = TokenStream::new(); let mut cursor = self; while let Some((tt, rest)) = cursor.token_tree() { - tts.push(tt); + tokens.append(tt); cursor = rest; } - tts.into_iter().collect() + tokens } /// If the cursor is pointing at a `TokenTree`, returns it along with a @@ -300,7 +308,7 @@ Entry::Literal(literal) => (literal.clone().into(), 1), Entry::Ident(ident) => (ident.clone().into(), 1), Entry::Punct(punct) => (punct.clone().into(), 1), - Entry::End(_) => return None, + Entry::End(..) => return None, }; let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) }; @@ -309,13 +317,20 @@ /// Returns the `Span` of the current token, or `Span::call_site()` if this /// cursor points to eof. - pub fn span(self) -> Span { + pub fn span(mut self) -> Span { match self.entry() { Entry::Group(group, _) => group.span(), Entry::Literal(literal) => literal.span(), Entry::Ident(ident) => ident.span(), Entry::Punct(punct) => punct.span(), - Entry::End(_) => Span::call_site(), + Entry::End(_, offset) => { + self.ptr = unsafe { self.ptr.offset(*offset) }; + if let Entry::Group(group, _) = self.entry() { + group.span_close() + } else { + Span::call_site() + } + } } } @@ -324,24 +339,7 @@ #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn prev_span(mut self) -> Span { if start_of_buffer(self) < self.ptr { - self.ptr = unsafe { self.ptr.offset(-1) }; - if let Entry::End(_) = self.entry() { - // Locate the matching Group begin token. - let mut depth = 1; - loop { - self.ptr = unsafe { self.ptr.offset(-1) }; - match self.entry() { - Entry::Group(group, _) => { - depth -= 1; - if depth == 0 { - return group.span(); - } - } - Entry::End(_) => depth += 1, - Entry::Literal(_) | Entry::Ident(_) | Entry::Punct(_) => {} - } - } - } + self.ptr = unsafe { self.ptr.sub(1) }; } self.span() } @@ -354,7 +352,7 @@ self.ignore_none(); let len = match self.entry() { - Entry::End(_) => return None, + Entry::End(..) => return None, // Treat lifetimes as a single tt for the purposes of 'skip'. Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => { @@ -370,6 +368,16 @@ Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) }) } + + pub(crate) fn scope_delimiter(self) -> Delimiter { + match unsafe { &*self.scope } { + Entry::End(_, offset) => match unsafe { &*self.scope.offset(*offset) } { + Entry::Group(group, _) => group.delimiter(), + _ => Delimiter::None, + }, + _ => unreachable!(), + } + } } impl<'a> Copy for Cursor<'a> {} @@ -384,7 +392,7 @@ impl<'a> PartialEq for Cursor<'a> { fn eq(&self, other: &Self) -> bool { - self.ptr == other.ptr + ptr::eq(self.ptr, other.ptr) } } @@ -399,17 +407,17 @@ } pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool { - a.scope == b.scope + ptr::eq(a.scope, b.scope) } pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool { - start_of_buffer(a) == start_of_buffer(b) + ptr::eq(start_of_buffer(a), start_of_buffer(b)) } fn start_of_buffer(cursor: Cursor) -> *const Entry { unsafe { match &*cursor.scope { - Entry::End(offset) => cursor.scope.offset(*offset), + Entry::End(offset, _) => cursor.scope.offset(*offset), _ => unreachable!(), } } @@ -425,10 +433,3 @@ _ => cursor.span(), } } - -pub(crate) fn close_span_of_group(cursor: Cursor) -> Span { - match cursor.entry() { - Entry::Group(group, _) => group.span_close(), - _ => cursor.span(), - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/classify.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/classify.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/classify.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/classify.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,311 @@ +#[cfg(feature = "full")] +use crate::expr::Expr; +#[cfg(any(feature = "printing", feature = "full"))] +use crate::generics::TypeParamBound; +#[cfg(any(feature = "printing", feature = "full"))] +use crate::path::{Path, PathArguments}; +#[cfg(any(feature = "printing", feature = "full"))] +use crate::punctuated::Punctuated; +#[cfg(any(feature = "printing", feature = "full"))] +use crate::ty::{ReturnType, Type}; +#[cfg(feature = "full")] +use proc_macro2::{Delimiter, TokenStream, TokenTree}; +#[cfg(any(feature = "printing", feature = "full"))] +use std::ops::ControlFlow; + +#[cfg(feature = "full")] +pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool { + match expr { + Expr::Macro(expr) => !expr.mac.delimiter.is_brace(), + _ => requires_comma_to_be_match_arm(expr), + } +} + +#[cfg(feature = "full")] +pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool { + match expr { + Expr::If(_) + | Expr::Match(_) + | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc + | Expr::While(_) + | Expr::Loop(_) + | Expr::ForLoop(_) + | Expr::TryBlock(_) + | Expr::Const(_) => false, + + Expr::Array(_) + | Expr::Assign(_) + | Expr::Async(_) + | Expr::Await(_) + | Expr::Binary(_) + | Expr::Break(_) + | Expr::Call(_) + | Expr::Cast(_) + | Expr::Closure(_) + | Expr::Continue(_) + | Expr::Field(_) + | Expr::Group(_) + | Expr::Index(_) + | Expr::Infer(_) + | Expr::Let(_) + | Expr::Lit(_) + | Expr::Macro(_) + | Expr::MethodCall(_) + | Expr::Paren(_) + | Expr::Path(_) + | Expr::Range(_) + | Expr::RawAddr(_) + | Expr::Reference(_) + | Expr::Repeat(_) + | Expr::Return(_) + | Expr::Struct(_) + | Expr::Try(_) + | Expr::Tuple(_) + | Expr::Unary(_) + | Expr::Yield(_) + | Expr::Verbatim(_) => true, + } +} + +#[cfg(feature = "printing")] +pub(crate) fn trailing_unparameterized_path(mut ty: &Type) -> bool { + loop { + match ty { + Type::BareFn(t) => match &t.output { + ReturnType::Default => return false, + ReturnType::Type(_, ret) => ty = ret, + }, + Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) { + ControlFlow::Break(trailing_path) => return trailing_path, + ControlFlow::Continue(t) => ty = t, + }, + Type::Path(t) => match last_type_in_path(&t.path) { + ControlFlow::Break(trailing_path) => return trailing_path, + ControlFlow::Continue(t) => ty = t, + }, + Type::Ptr(t) => ty = &t.elem, + Type::Reference(t) => ty = &t.elem, + Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) { + ControlFlow::Break(trailing_path) => return trailing_path, + ControlFlow::Continue(t) => ty = t, + }, + + Type::Array(_) + | Type::Group(_) + | Type::Infer(_) + | Type::Macro(_) + | Type::Never(_) + | Type::Paren(_) + | Type::Slice(_) + | Type::Tuple(_) + | Type::Verbatim(_) => return false, + } + } + + fn last_type_in_path(path: &Path) -> ControlFlow { + match &path.segments.last().unwrap().arguments { + PathArguments::None => ControlFlow::Break(true), + PathArguments::AngleBracketed(_) => ControlFlow::Break(false), + PathArguments::Parenthesized(arg) => match &arg.output { + ReturnType::Default => ControlFlow::Break(false), + ReturnType::Type(_, ret) => ControlFlow::Continue(ret), + }, + } + } + + fn last_type_in_bounds( + bounds: &Punctuated, + ) -> ControlFlow { + match bounds.last().unwrap() { + TypeParamBound::Trait(t) => last_type_in_path(&t.path), + TypeParamBound::Lifetime(_) + | TypeParamBound::PreciseCapture(_) + | TypeParamBound::Verbatim(_) => ControlFlow::Break(false), + } + } +} + +/// Whether the expression's first token is the label of a loop/block. +#[cfg(all(feature = "printing", feature = "full"))] +pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool { + loop { + match expr { + Expr::Block(e) => return e.label.is_some(), + Expr::ForLoop(e) => return e.label.is_some(), + Expr::Loop(e) => return e.label.is_some(), + Expr::While(e) => return e.label.is_some(), + + Expr::Assign(e) => expr = &e.left, + Expr::Await(e) => expr = &e.base, + Expr::Binary(e) => expr = &e.left, + Expr::Call(e) => expr = &e.func, + Expr::Cast(e) => expr = &e.expr, + Expr::Field(e) => expr = &e.base, + Expr::Index(e) => expr = &e.expr, + Expr::MethodCall(e) => expr = &e.receiver, + Expr::Range(e) => match &e.start { + Some(start) => expr = start, + None => return false, + }, + Expr::Try(e) => expr = &e.expr, + + Expr::Array(_) + | Expr::Async(_) + | Expr::Break(_) + | Expr::Closure(_) + | Expr::Const(_) + | Expr::Continue(_) + | Expr::Group(_) + | Expr::If(_) + | Expr::Infer(_) + | Expr::Let(_) + | Expr::Lit(_) + | Expr::Macro(_) + | Expr::Match(_) + | Expr::Paren(_) + | Expr::Path(_) + | Expr::RawAddr(_) + | Expr::Reference(_) + | Expr::Repeat(_) + | Expr::Return(_) + | Expr::Struct(_) + | Expr::TryBlock(_) + | Expr::Tuple(_) + | Expr::Unary(_) + | Expr::Unsafe(_) + | Expr::Verbatim(_) + | Expr::Yield(_) => return false, + } + } +} + +/// Whether the expression's last token is `}`. +#[cfg(feature = "full")] +pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool { + loop { + match expr { + Expr::Async(_) + | Expr::Block(_) + | Expr::Const(_) + | Expr::ForLoop(_) + | Expr::If(_) + | Expr::Loop(_) + | Expr::Match(_) + | Expr::Struct(_) + | Expr::TryBlock(_) + | Expr::Unsafe(_) + | Expr::While(_) => return true, + + Expr::Assign(e) => expr = &e.right, + Expr::Binary(e) => expr = &e.right, + Expr::Break(e) => match &e.expr { + Some(e) => expr = e, + None => return false, + }, + Expr::Cast(e) => return type_trailing_brace(&e.ty), + Expr::Closure(e) => expr = &e.body, + Expr::Let(e) => expr = &e.expr, + Expr::Macro(e) => return e.mac.delimiter.is_brace(), + Expr::Range(e) => match &e.end { + Some(end) => expr = end, + None => return false, + }, + Expr::RawAddr(e) => expr = &e.expr, + Expr::Reference(e) => expr = &e.expr, + Expr::Return(e) => match &e.expr { + Some(e) => expr = e, + None => return false, + }, + Expr::Unary(e) => expr = &e.expr, + Expr::Verbatim(e) => return tokens_trailing_brace(e), + Expr::Yield(e) => match &e.expr { + Some(e) => expr = e, + None => return false, + }, + + Expr::Array(_) + | Expr::Await(_) + | Expr::Call(_) + | Expr::Continue(_) + | Expr::Field(_) + | Expr::Group(_) + | Expr::Index(_) + | Expr::Infer(_) + | Expr::Lit(_) + | Expr::MethodCall(_) + | Expr::Paren(_) + | Expr::Path(_) + | Expr::Repeat(_) + | Expr::Try(_) + | Expr::Tuple(_) => return false, + } + } + + fn type_trailing_brace(mut ty: &Type) -> bool { + loop { + match ty { + Type::BareFn(t) => match &t.output { + ReturnType::Default => return false, + ReturnType::Type(_, ret) => ty = ret, + }, + Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) { + ControlFlow::Break(trailing_brace) => return trailing_brace, + ControlFlow::Continue(t) => ty = t, + }, + Type::Macro(t) => return t.mac.delimiter.is_brace(), + Type::Path(t) => match last_type_in_path(&t.path) { + Some(t) => ty = t, + None => return false, + }, + Type::Ptr(t) => ty = &t.elem, + Type::Reference(t) => ty = &t.elem, + Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) { + ControlFlow::Break(trailing_brace) => return trailing_brace, + ControlFlow::Continue(t) => ty = t, + }, + Type::Verbatim(t) => return tokens_trailing_brace(t), + + Type::Array(_) + | Type::Group(_) + | Type::Infer(_) + | Type::Never(_) + | Type::Paren(_) + | Type::Slice(_) + | Type::Tuple(_) => return false, + } + } + } + + fn last_type_in_path(path: &Path) -> Option<&Type> { + match &path.segments.last().unwrap().arguments { + PathArguments::None | PathArguments::AngleBracketed(_) => None, + PathArguments::Parenthesized(arg) => match &arg.output { + ReturnType::Default => None, + ReturnType::Type(_, ret) => Some(ret), + }, + } + } + + fn last_type_in_bounds( + bounds: &Punctuated, + ) -> ControlFlow { + match bounds.last().unwrap() { + TypeParamBound::Trait(t) => match last_type_in_path(&t.path) { + Some(t) => ControlFlow::Continue(t), + None => ControlFlow::Break(false), + }, + TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) => { + ControlFlow::Break(false) + } + TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)), + } + } + + fn tokens_trailing_brace(tokens: &TokenStream) -> bool { + if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() { + last.delimiter() == Delimiter::Brace + } else { + false + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/custom_punctuation.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/custom_punctuation.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/custom_punctuation.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/custom_punctuation.rs 2006-07-24 01:21:28.000000000 +0000 @@ -31,6 +31,7 @@ /// /// ``` /// use proc_macro2::{TokenStream, TokenTree}; +/// use std::iter; /// use syn::parse::{Parse, ParseStream, Peek, Result}; /// use syn::punctuated::Punctuated; /// use syn::Expr; @@ -64,7 +65,7 @@ /// let mut tokens = TokenStream::new(); /// while !input.is_empty() && !input.peek(end) { /// let next: TokenTree = input.parse()?; -/// tokens.extend(Some(next)); +/// tokens.extend(iter::once(next)); /// } /// Ok(tokens) /// } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/data.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/data.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/data.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/data.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ use crate::attr::Attribute; -use crate::expr::Expr; +use crate::expr::{Expr, Index, Member}; use crate::ident::Ident; use crate::punctuated::{self, Punctuated}; use crate::restriction::{FieldMutability, Visibility}; @@ -8,7 +8,7 @@ ast_struct! { /// An enum variant. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Variant { pub attrs: Vec, @@ -31,7 +31,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Fields { /// Named fields of a struct or struct variant such as `Point { x: f64, /// y: f64 }`. @@ -48,7 +48,7 @@ ast_struct! { /// Named fields of a struct or struct variant such as `Point { x: f64, /// y: f64 }`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct FieldsNamed { pub brace_token: token::Brace, pub named: Punctuated, @@ -57,7 +57,7 @@ ast_struct! { /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct FieldsUnnamed { pub paren_token: token::Paren, pub unnamed: Punctuated, @@ -104,6 +104,47 @@ Fields::Unnamed(f) => f.unnamed.is_empty(), } } + + return_impl_trait! { + /// Get an iterator over the fields of a struct or variant as [`Member`]s. + /// This iterator can be used to iterate over a named or unnamed struct or + /// variant's fields uniformly. + /// + /// # Example + /// + /// The following is a simplistic [`Clone`] derive for structs. (A more + /// complete implementation would additionally want to infer trait bounds on + /// the generic type parameters.) + /// + /// ``` + /// # use quote::quote; + /// # + /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream { + /// let ident = &input.ident; + /// let members = input.fields.members(); + /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + /// quote! { + /// impl #impl_generics Clone for #ident #ty_generics #where_clause { + /// fn clone(&self) -> Self { + /// Self { + /// #(#members: self.#members.clone()),* + /// } + /// } + /// } + /// } + /// } + /// ``` + /// + /// For structs with named fields, it produces an expression like `Self { a: + /// self.a.clone() }`. For structs with unnamed fields, `Self { 0: + /// self.0.clone() }`. And for unit structs, `Self {}`. + pub fn members(&self) -> impl Iterator + Clone + '_ [Members] { + Members { + fields: self.iter(), + index: 0, + } + } + } } impl IntoIterator for Fields { @@ -139,7 +180,7 @@ ast_struct! { /// A field of a struct or enum variant. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Field { pub attrs: Vec, @@ -158,6 +199,43 @@ } } +pub struct Members<'a> { + fields: punctuated::Iter<'a, Field>, + index: u32, +} + +impl<'a> Iterator for Members<'a> { + type Item = Member; + + fn next(&mut self) -> Option { + let field = self.fields.next()?; + let member = match &field.ident { + Some(ident) => Member::Named(ident.clone()), + None => { + #[cfg(all(feature = "parsing", feature = "printing"))] + let span = crate::spanned::Spanned::span(&field.ty); + #[cfg(not(all(feature = "parsing", feature = "printing")))] + let span = proc_macro2::Span::call_site(); + Member::Unnamed(Index { + index: self.index, + span, + }) + } + }; + self.index += 1; + Some(member) + } +} + +impl<'a> Clone for Members<'a> { + fn clone(&self) -> Self { + Members { + fields: self.fields.clone(), + index: self.index, + } + } +} + #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; @@ -170,11 +248,13 @@ use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseStream}; use crate::restriction::{FieldMutability, Visibility}; + #[cfg(not(feature = "full"))] + use crate::scan_expr::scan_expr; use crate::token; use crate::ty::Type; use crate::verbatim; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Variant { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -198,7 +278,7 @@ let mut discriminant: Result = ahead.parse(); if discriminant.is_ok() { input.advance_to(&ahead); - } else if scan_lenient_discriminant(input).is_ok() { + } else if scan_expr(input).is_ok() { discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input))); } discriminant? @@ -216,86 +296,7 @@ } } - #[cfg(not(feature = "full"))] - pub(crate) fn scan_lenient_discriminant(input: ParseStream) -> Result<()> { - use crate::expr::Member; - use crate::lifetime::Lifetime; - use crate::lit::Lit; - use crate::lit::LitFloat; - use crate::op::{BinOp, UnOp}; - use crate::path::{self, AngleBracketedGenericArguments}; - use proc_macro2::Delimiter::{self, Brace, Bracket, Parenthesis}; - - let consume = |delimiter: Delimiter| { - Result::unwrap(input.step(|cursor| match cursor.group(delimiter) { - Some((_inside, _span, rest)) => Ok((true, rest)), - None => Ok((false, *cursor)), - })) - }; - - macro_rules! consume { - [$token:tt] => { - input.parse::>().unwrap().is_some() - }; - } - - let mut initial = true; - let mut depth = 0usize; - loop { - if initial { - if consume![&] { - input.parse::>()?; - } else if consume![if] || consume![match] || consume![while] { - depth += 1; - } else if input.parse::>()?.is_some() - || (consume(Brace) || consume(Bracket) || consume(Parenthesis)) - || (consume![async] || consume![const] || consume![loop] || consume![unsafe]) - && (consume(Brace) || break) - { - initial = false; - } else if consume![let] { - while !consume![=] { - if !((consume![|] || consume![ref] || consume![mut] || consume![@]) - || (consume![!] || input.parse::>()?.is_some()) - || (consume![..=] || consume![..] || consume![&] || consume![_]) - || (consume(Brace) || consume(Bracket) || consume(Parenthesis))) - { - path::parsing::qpath(input, true)?; - } - } - } else if input.parse::>()?.is_some() && !consume![:] { - break; - } else if input.parse::().is_err() { - path::parsing::qpath(input, true)?; - initial = consume![!] || depth == 0 && input.peek(token::Brace); - } - } else if input.is_empty() || input.peek(Token![,]) { - return Ok(()); - } else if depth > 0 && consume(Brace) { - if consume![else] && !consume(Brace) { - initial = consume![if] || break; - } else { - depth -= 1; - } - } else if input.parse::().is_ok() || (consume![..] | consume![=]) { - initial = true; - } else if consume![.] { - if input.parse::>()?.is_none() - && (input.parse::()?.is_named() && consume![::]) - { - AngleBracketedGenericArguments::do_parse(None, input)?; - } - } else if consume![as] { - input.parse::()?; - } else if !(consume(Brace) || consume(Bracket) || consume(Parenthesis)) { - break; - } - } - - Err(input.error("unsupported expression")) - } - - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FieldsNamed { fn parse(input: ParseStream) -> Result { let content; @@ -306,7 +307,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FieldsUnnamed { fn parse(input: ParseStream) -> Result { let content; @@ -319,7 +320,7 @@ impl Field { /// Parses a named (braced struct) field. - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_named(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; @@ -356,7 +357,7 @@ } /// Parses an unnamed (tuple struct) field. - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_unnamed(input: ParseStream) -> Result { Ok(Field { attrs: input.call(Attribute::parse_outer)?, @@ -375,9 +376,9 @@ use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant}; use crate::print::TokensOrDefault; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Variant { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(&self.attrs); @@ -390,7 +391,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldsNamed { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { @@ -399,7 +400,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldsUnnamed { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { @@ -408,7 +409,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Field { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(&self.attrs); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/derive.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/derive.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/derive.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/derive.rs 2006-07-24 01:21:28.000000000 +0000 @@ -8,7 +8,7 @@ ast_struct! { /// Data structure sent to a `proc_macro_derive` macro. - #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DeriveInput { pub attrs: Vec, pub vis: Visibility, @@ -26,7 +26,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub enum Data { Struct(DataStruct), Enum(DataEnum), @@ -36,7 +36,7 @@ ast_struct! { /// A struct input to a `proc_macro_derive` macro. - #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataStruct { pub struct_token: Token![struct], pub fields: Fields, @@ -46,7 +46,7 @@ ast_struct! { /// An enum input to a `proc_macro_derive` macro. - #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataEnum { pub enum_token: Token![enum], pub brace_token: token::Brace, @@ -56,7 +56,7 @@ ast_struct! { /// An untagged union input to a `proc_macro_derive` macro. - #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataUnion { pub union_token: Token![union], pub fields: FieldsNamed, @@ -76,7 +76,7 @@ use crate::restriction::Visibility; use crate::token; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for DeriveInput { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -213,7 +213,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for DeriveInput { fn to_tokens(&self, tokens: &mut TokenStream) { for attr in self.attrs.outer() { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/discouraged.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/discouraged.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/discouraged.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/discouraged.rs 2006-07-24 01:21:28.000000000 +0000 @@ -175,17 +175,17 @@ if !Rc::ptr_eq(&self_unexp, &fork_unexp) { match (fork_sp, self_sp) { // Unexpected set on the fork, but not on `self`, copy it over. - (Some(span), None) => { - self_unexp.set(Unexpected::Some(span)); + (Some((span, delimiter)), None) => { + self_unexp.set(Unexpected::Some(span, delimiter)); } // Unexpected unset. Use chain to propagate errors from fork. (None, None) => { fork_unexp.set(Unexpected::Chain(self_unexp)); // Ensure toplevel 'unexpected' tokens from the fork don't - // bubble up the chain by replacing the root `unexpected` + // propagate up the chain by replacing the root `unexpected` // pointer, only 'unexpected' tokens from existing group - // parsers should bubble. + // parsers should propagate. fork.unexpected .set(Some(Rc::new(Cell::new(Unexpected::None)))); } @@ -212,7 +212,7 @@ fn parse_any_delimiter(&self) -> Result<(Delimiter, DelimSpan, ParseBuffer)> { self.step(|cursor| { if let Some((content, delimiter, span, rest)) = cursor.any_group() { - let scope = crate::buffer::close_span_of_group(*cursor); + let scope = span.close(); let nested = crate::parse::advance_step_cursor(cursor, content); let unexpected = crate::parse::get_unexpected(self); let content = crate::parse::new_parse_buffer(scope, nested, unexpected); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/drops.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/drops.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/drops.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/drops.rs 2006-07-24 01:21:28.000000000 +0000 @@ -32,10 +32,10 @@ pub(crate) trait TrivialDrop {} impl TrivialDrop for iter::Empty {} -impl<'a, T> TrivialDrop for slice::Iter<'a, T> {} -impl<'a, T> TrivialDrop for slice::IterMut<'a, T> {} -impl<'a, T> TrivialDrop for option::IntoIter<&'a T> {} -impl<'a, T> TrivialDrop for option::IntoIter<&'a mut T> {} +impl TrivialDrop for slice::Iter<'_, T> {} +impl TrivialDrop for slice::IterMut<'_, T> {} +impl TrivialDrop for option::IntoIter<&T> {} +impl TrivialDrop for option::IntoIter<&mut T> {} #[test] fn test_needs_drop() { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,6 @@ #[cfg(feature = "parsing")] use crate::buffer::Cursor; +use crate::ext::{PunctExt as _, TokenStreamExt as _}; use crate::thread::ThreadBound; use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, @@ -185,7 +186,7 @@ /// When in doubt it's recommended to stick to `Error::new` (or /// `ParseStream::error`)! #[cfg(feature = "printing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] pub fn new_spanned(tokens: T, message: U) -> Self { return new_spanned(tokens.into_token_stream(), message.to_string()); @@ -223,10 +224,11 @@ /// [`compile_error!`]: std::compile_error! /// [`parse_macro_input!`]: crate::parse_macro_input! pub fn to_compile_error(&self) -> TokenStream { - self.messages - .iter() - .map(ErrorMessage::to_compile_error) - .collect() + let mut tokens = TokenStream::new(); + for msg in &self.messages { + ErrorMessage::to_compile_error(msg, &mut tokens); + } + tokens } /// Render the error as an invocation of [`compile_error!`]. @@ -273,53 +275,52 @@ } impl ErrorMessage { - fn to_compile_error(&self) -> TokenStream { + fn to_compile_error(&self, tokens: &mut TokenStream) { let (start, end) = match self.span.get() { Some(range) => (range.start, range.end), None => (Span::call_site(), Span::call_site()), }; // ::core::compile_error!($message) - TokenStream::from_iter([ - TokenTree::Punct({ - let mut punct = Punct::new(':', Spacing::Joint); - punct.set_span(start); - punct - }), - TokenTree::Punct({ - let mut punct = Punct::new(':', Spacing::Alone); - punct.set_span(start); - punct - }), - TokenTree::Ident(Ident::new("core", start)), - TokenTree::Punct({ - let mut punct = Punct::new(':', Spacing::Joint); - punct.set_span(start); - punct - }), - TokenTree::Punct({ - let mut punct = Punct::new(':', Spacing::Alone); - punct.set_span(start); - punct - }), - TokenTree::Ident(Ident::new("compile_error", start)), - TokenTree::Punct({ - let mut punct = Punct::new('!', Spacing::Alone); - punct.set_span(start); - punct - }), - TokenTree::Group({ - let mut group = Group::new(Delimiter::Brace, { - TokenStream::from_iter([TokenTree::Literal({ - let mut string = Literal::string(&self.message); - string.set_span(end); - string - })]) - }); - group.set_span(end); - group - }), - ]) + tokens.append(TokenTree::Punct(Punct::new_spanned( + ':', + Spacing::Joint, + start, + ))); + tokens.append(TokenTree::Punct(Punct::new_spanned( + ':', + Spacing::Alone, + start, + ))); + tokens.append(TokenTree::Ident(Ident::new("core", start))); + tokens.append(TokenTree::Punct(Punct::new_spanned( + ':', + Spacing::Joint, + start, + ))); + tokens.append(TokenTree::Punct(Punct::new_spanned( + ':', + Spacing::Alone, + start, + ))); + tokens.append(TokenTree::Ident(Ident::new("compile_error", start))); + tokens.append(TokenTree::Punct(Punct::new_spanned( + '!', + Spacing::Alone, + start, + ))); + tokens.append(TokenTree::Group({ + let mut group = Group::new( + Delimiter::Brace, + TokenStream::from({ + let mut string = Literal::string(&self.message); + string.set_span(end); + TokenTree::Literal(string) + }), + ); + group.set_span(end); + group + })); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/expr.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/expr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,18 @@ use crate::attr::Attribute; +#[cfg(all(feature = "parsing", feature = "full"))] +use crate::error::Result; +#[cfg(feature = "parsing")] +use crate::ext::IdentExt as _; #[cfg(feature = "full")] use crate::generics::BoundLifetimes; use crate::ident::Ident; -#[cfg(feature = "full")] +#[cfg(any(feature = "parsing", feature = "full"))] use crate::lifetime::Lifetime; use crate::lit::Lit; use crate::mac::Macro; use crate::op::{BinOp, UnOp}; +#[cfg(feature = "parsing")] +use crate::parse::ParseStream; #[cfg(feature = "full")] use crate::pat::Pat; use crate::path::{AngleBracketedGenericArguments, Path, QSelf}; @@ -101,7 +107,7 @@ /// A sign that you may not be choosing the right variable names is if you /// see names getting repeated in your code, like accessing /// `receiver.receiver` or `pat.pat` or `cond.cond`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Expr { /// A slice literal expression: `[a, b, c, d]`. @@ -198,6 +204,9 @@ /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. Range(ExprRange), + /// Address-of operation: `&raw const place` or `&raw mut place`. + RawAddr(ExprRawAddr), + /// A referencing operation: `&a` or `&mut a`. Reference(ExprReference), @@ -259,7 +268,7 @@ ast_struct! { /// A slice literal expression: `[a, b, c, d]`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprArray #full { pub attrs: Vec, pub bracket_token: token::Bracket, @@ -269,7 +278,7 @@ ast_struct! { /// An assignment expression: `a = compute()`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAssign #full { pub attrs: Vec, pub left: Box, @@ -280,7 +289,7 @@ ast_struct! { /// An async block: `async { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAsync #full { pub attrs: Vec, pub async_token: Token![async], @@ -291,7 +300,7 @@ ast_struct! { /// An await expression: `fut.await`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAwait #full { pub attrs: Vec, pub base: Box, @@ -302,7 +311,7 @@ ast_struct! { /// A binary operation: `a + b`, `a += b`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprBinary { pub attrs: Vec, pub left: Box, @@ -313,7 +322,7 @@ ast_struct! { /// A blocked scope: `{ ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBlock #full { pub attrs: Vec, pub label: Option
LifetimeParam> - /// over the lifetime parameters in `self.params`. - pub fn lifetimes(&self) -> Lifetimes { - Lifetimes(self.params.iter()) - } - - /// Returns an - /// Iterator<Item = &mut LifetimeParam> - /// over the lifetime parameters in `self.params`. - pub fn lifetimes_mut(&mut self) -> LifetimesMut { - LifetimesMut(self.params.iter_mut()) - } - - /// Returns an - /// Iterator<Item = &TypeParam> - /// over the type parameters in `self.params`. - pub fn type_params(&self) -> TypeParams { - TypeParams(self.params.iter()) - } - - /// Returns an - /// Iterator<Item = &mut TypeParam> - /// over the type parameters in `self.params`. - pub fn type_params_mut(&mut self) -> TypeParamsMut { - TypeParamsMut(self.params.iter_mut()) - } - - /// Returns an - /// Iterator<Item = &ConstParam> - /// over the constant parameters in `self.params`. - pub fn const_params(&self) -> ConstParams { - ConstParams(self.params.iter()) - } - - /// Returns an - /// Iterator<Item = &mut ConstParam> - /// over the constant parameters in `self.params`. - pub fn const_params_mut(&mut self) -> ConstParamsMut { - ConstParamsMut(self.params.iter_mut()) + return_impl_trait! { + /// Iterator over the lifetime parameters in `self.params`. + pub fn lifetimes(&self) -> impl Iterator [Lifetimes] { + Lifetimes(self.params.iter()) + } + } + + return_impl_trait! { + /// Iterator over the lifetime parameters in `self.params`. + pub fn lifetimes_mut(&mut self) -> impl Iterator [LifetimesMut] { + LifetimesMut(self.params.iter_mut()) + } + } + + return_impl_trait! { + /// Iterator over the type parameters in `self.params`. + pub fn type_params(&self) -> impl Iterator [TypeParams] { + TypeParams(self.params.iter()) + } + } + + return_impl_trait! { + /// Iterator over the type parameters in `self.params`. + pub fn type_params_mut(&mut self) -> impl Iterator [TypeParamsMut] { + TypeParamsMut(self.params.iter_mut()) + } + } + + return_impl_trait! { + /// Iterator over the constant parameters in `self.params`. + pub fn const_params(&self) -> impl Iterator [ConstParams] { + ConstParams(self.params.iter()) + } + } + + return_impl_trait! { + /// Iterator over the constant parameters in `self.params`. + pub fn const_params_mut(&mut self) -> impl Iterator [ConstParamsMut] { + ConstParamsMut(self.params.iter_mut()) + } } /// Initializes an empty `where`-clause if there is not one present already. @@ -176,6 +152,34 @@ predicates: Punctuated::new(), }) } + + /// Split a type's generics into the pieces required for impl'ing a trait + /// for that type. + /// + /// ``` + /// # use proc_macro2::{Span, Ident}; + /// # use quote::quote; + /// # + /// # let generics: syn::Generics = Default::default(); + /// # let name = Ident::new("MyType", Span::call_site()); + /// # + /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + /// quote! { + /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { + /// // ... + /// } + /// } + /// # ; + /// ``` + #[cfg(feature = "printing")] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { + ( + ImplGenerics(self), + TypeGenerics(self), + self.where_clause.as_ref(), + ) + } } pub struct Lifetimes<'a>(Iter<'a, GenericParam>); @@ -184,11 +188,7 @@ type Item = &'a LifetimeParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Lifetime(lifetime) = next { + if let GenericParam::Lifetime(lifetime) = self.0.next()? { Some(lifetime) } else { self.next() @@ -202,11 +202,7 @@ type Item = &'a mut LifetimeParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Lifetime(lifetime) = next { + if let GenericParam::Lifetime(lifetime) = self.0.next()? { Some(lifetime) } else { self.next() @@ -220,11 +216,7 @@ type Item = &'a TypeParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Type(type_param) = next { + if let GenericParam::Type(type_param) = self.0.next()? { Some(type_param) } else { self.next() @@ -238,11 +230,7 @@ type Item = &'a mut TypeParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Type(type_param) = next { + if let GenericParam::Type(type_param) = self.0.next()? { Some(type_param) } else { self.next() @@ -256,11 +244,7 @@ type Item = &'a ConstParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Const(const_param) = next { + if let GenericParam::Const(const_param) = self.0.next()? { Some(const_param) } else { self.next() @@ -274,11 +258,7 @@ type Item = &'a mut ConstParam; fn next(&mut self) -> Option { - let next = match self.0.next() { - Some(item) => item, - None => return None, - }; - if let GenericParam::Const(const_param) = next { + if let GenericParam::Const(const_param) = self.0.next()? { Some(const_param) } else { self.next() @@ -289,7 +269,7 @@ /// Returned by `Generics::split_for_impl`. #[cfg(feature = "printing")] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct ImplGenerics<'a>(&'a Generics); @@ -297,7 +277,7 @@ /// Returned by `Generics::split_for_impl`. #[cfg(feature = "printing")] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct TypeGenerics<'a>(&'a Generics); @@ -305,49 +285,16 @@ /// Returned by `TypeGenerics::as_turbofish`. #[cfg(feature = "printing")] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct Turbofish<'a>(&'a Generics); #[cfg(feature = "printing")] -impl Generics { - /// Split a type's generics into the pieces required for impl'ing a trait - /// for that type. - /// - /// ``` - /// # use proc_macro2::{Span, Ident}; - /// # use quote::quote; - /// # - /// # let generics: syn::Generics = Default::default(); - /// # let name = Ident::new("MyType", Span::call_site()); - /// # - /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - /// quote! { - /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { - /// // ... - /// } - /// } - /// # ; - /// ``` - #[cfg_attr( - doc_cfg, - doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) - )] - pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { - ( - ImplGenerics(self), - TypeGenerics(self), - self.where_clause.as_ref(), - ) - } -} - -#[cfg(feature = "printing")] macro_rules! generics_wrapper_impls { ($ty:ident) => { #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl<'a> Clone for $ty<'a> { fn clone(&self) -> Self { $ty(self.0) @@ -355,7 +302,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Debug for $ty<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter @@ -366,11 +313,11 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Eq for $ty<'a> {} #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> PartialEq for $ty<'a> { fn eq(&self, other: &Self) -> bool { self.0 == other.0 @@ -378,7 +325,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Hash for $ty<'a> { fn hash(&self, state: &mut H) { self.0.hash(state); @@ -397,14 +344,14 @@ #[cfg(feature = "printing")] impl<'a> TypeGenerics<'a> { /// Turn a type's generics like `` into a turbofish like `::`. - pub fn as_turbofish(&self) -> Turbofish { + pub fn as_turbofish(&self) -> Turbofish<'a> { Turbofish(self.0) } } ast_struct! { /// A set of bound lifetimes: `for<'a, 'b, 'c>`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BoundLifetimes { pub for_token: Token![for], pub lt_token: Token![<], @@ -450,18 +397,19 @@ ast_enum_of_structs! { /// A trait or lifetime used as a bound on a type parameter. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum TypeParamBound { Trait(TraitBound), Lifetime(Lifetime), + PreciseCapture(PreciseCapture), Verbatim(TokenStream), } } ast_struct! { /// A trait used as a bound on a type parameter. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TraitBound { pub paren_token: Option, pub modifier: TraitBoundModifier, @@ -475,7 +423,7 @@ ast_enum! { /// A modifier on a trait bound, currently only used for the `?` in /// `?Sized`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum TraitBoundModifier { None, Maybe(Token![?]), @@ -483,9 +431,37 @@ } ast_struct! { + /// Precise capturing bound: the 'use<…>' in `impl Trait + + /// use<'a, T>`. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + pub struct PreciseCapture #full { + pub use_token: Token![use], + pub lt_token: Token![<], + pub params: Punctuated, + pub gt_token: Token![>], + } +} + +#[cfg(feature = "full")] +ast_enum! { + /// Single parameter in a precise capturing bound. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + #[non_exhaustive] + pub enum CapturedParam { + /// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl + /// Trait + use<'a>`. + Lifetime(Lifetime), + /// A type parameter or const generic parameter in precise capturing + /// bound: `fn f() -> impl Trait + use` or `fn f() -> + /// impl Trait + use`. + Ident(Ident), + } +} + +ast_struct! { /// A `where` clause in a definition: `where T: Deserialize<'de>, D: /// 'static`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct WhereClause { pub where_token: Token![where], pub predicates: Punctuated, @@ -500,7 +476,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum WherePredicate { /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. @@ -513,7 +489,7 @@ ast_struct! { /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PredicateLifetime { pub lifetime: Lifetime, pub colon_token: Token![:], @@ -523,7 +499,7 @@ ast_struct! { /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PredicateType { /// Any lifetimes from a `for` binding pub lifetimes: Option, @@ -538,13 +514,17 @@ #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; - use crate::error::Result; + #[cfg(feature = "full")] + use crate::error; + use crate::error::{Error, Result}; use crate::ext::IdentExt as _; use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause, WherePredicate, }; + #[cfg(feature = "full")] + use crate::generics::{CapturedParam, PreciseCapture}; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::parse::{Parse, ParseStream}; @@ -554,7 +534,7 @@ use crate::ty::Type; use crate::verbatim; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Generics { fn parse(input: ParseStream) -> Result { if !input.peek(Token![<]) { @@ -617,7 +597,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for GenericParam { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -644,7 +624,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LifetimeParam { fn parse(input: ParseStream) -> Result { let has_colon; @@ -664,7 +644,7 @@ let mut bounds = Punctuated::new(); if has_colon { loop { - if input.peek(Token![,]) || input.peek(Token![>]) { + if input.is_empty() || input.peek(Token![,]) || input.peek(Token![>]) { break; } let value = input.parse()?; @@ -682,7 +662,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BoundLifetimes { fn parse(input: ParseStream) -> Result { Ok(BoundLifetimes { @@ -691,14 +671,7 @@ lifetimes: { let mut lifetimes = Punctuated::new(); while !input.peek(Token![>]) { - let attrs = input.call(Attribute::parse_outer)?; - let lifetime: Lifetime = input.parse()?; - lifetimes.push_value(GenericParam::Lifetime(LifetimeParam { - attrs, - lifetime, - colon_token: None, - bounds: Punctuated::new(), - })); + lifetimes.push_value(input.parse()?); if input.peek(Token![>]) { break; } @@ -711,7 +684,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![for]) { @@ -722,7 +695,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParam { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -732,11 +705,18 @@ let mut bounds = Punctuated::new(); if colon_token.is_some() { loop { - if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) { + if input.is_empty() + || input.peek(Token![,]) + || input.peek(Token![>]) + || input.peek(Token![=]) + { break; } - let value: TypeParamBound = input.parse()?; - bounds.push_value(value); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = true; + TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? + }); if !input.peek(Token![+]) { break; } @@ -763,13 +743,42 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParamBound { fn parse(input: ParseStream) -> Result { + let allow_precise_capture = true; + let allow_const = true; + Self::parse_single(input, allow_precise_capture, allow_const) + } + } + + impl TypeParamBound { + pub(crate) fn parse_single( + input: ParseStream, + #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool, + allow_const: bool, + ) -> Result { if input.peek(Lifetime) { return input.parse().map(TypeParamBound::Lifetime); } + #[cfg(feature = "full")] + { + if input.peek(Token![use]) { + let precise_capture: PreciseCapture = input.parse()?; + return if allow_precise_capture { + Ok(TypeParamBound::PreciseCapture(precise_capture)) + } else { + let msg = "`use<...>` precise capturing syntax is not allowed here"; + Err(error::new2( + precise_capture.use_token.span, + precise_capture.gt_token.span, + msg, + )) + }; + } + } + let begin = input.fork(); let content; @@ -779,32 +788,24 @@ (None, input) }; - let is_tilde_const = - cfg!(feature = "full") && content.peek(Token![~]) && content.peek2(Token![const]); - if is_tilde_const { - content.parse::()?; - content.parse::()?; - } - - let mut bound: TraitBound = content.parse()?; - bound.paren_token = paren_token; - - if is_tilde_const { - Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input))) - } else { + if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? { + bound.paren_token = paren_token; Ok(TypeParamBound::Trait(bound)) + } else { + Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input))) } } - } - impl TypeParamBound { pub(crate) fn parse_multiple( input: ParseStream, allow_plus: bool, + allow_precise_capture: bool, + allow_const: bool, ) -> Result> { let mut bounds = Punctuated::new(); loop { - bounds.push_value(input.parse()?); + let bound = Self::parse_single(input, allow_precise_capture, allow_const)?; + bounds.push_value(bound); if !(allow_plus && input.peek(Token![+])) { break; } @@ -814,7 +815,7 @@ || input.peek(Token![?]) || input.peek(Lifetime) || input.peek(token::Paren) - || input.peek(Token![~])) + || (allow_const && (input.peek(token::Bracket) || input.peek(Token![const])))) { break; } @@ -823,11 +824,40 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitBound { fn parse(input: ParseStream) -> Result { + let allow_const = false; + Self::do_parse(input, allow_const).map(Option::unwrap) + } + } + + impl TraitBound { + fn do_parse(input: ParseStream, allow_const: bool) -> Result> { + let mut lifetimes: Option = input.parse()?; + + let is_conditionally_const = cfg!(feature = "full") && input.peek(token::Bracket); + let is_unconditionally_const = cfg!(feature = "full") && input.peek(Token![const]); + if is_conditionally_const { + let conditionally_const; + let bracket_token = bracketed!(conditionally_const in input); + conditionally_const.parse::()?; + if !allow_const { + let msg = "`[const]` is not allowed here"; + return Err(Error::new(bracket_token.span.join(), msg)); + } + } else if is_unconditionally_const { + let const_token: Token![const] = input.parse()?; + if !allow_const { + let msg = "`const` is not allowed here"; + return Err(Error::new(const_token.span, msg)); + } + } + let modifier: TraitBoundModifier = input.parse()?; - let lifetimes: Option = input.parse()?; + if lifetimes.is_none() && matches!(modifier, TraitBoundModifier::Maybe(_)) { + lifetimes = input.parse()?; + } let mut path: Path = input.parse()?; if path.segments.last().unwrap().arguments.is_empty() @@ -839,16 +869,30 @@ path.segments.last_mut().unwrap().arguments = parenthesized; } - Ok(TraitBound { - paren_token: None, - modifier, - lifetimes, - path, - }) + if lifetimes.is_some() { + match modifier { + TraitBoundModifier::None => {} + TraitBoundModifier::Maybe(maybe) => { + let msg = "`for<...>` binder not allowed with `?` trait polarity modifier"; + return Err(Error::new(maybe.span, msg)); + } + } + } + + if is_conditionally_const || is_unconditionally_const { + Ok(None) + } else { + Ok(Some(TraitBound { + paren_token: None, + modifier, + lifetimes, + path, + })) + } } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitBoundModifier { fn parse(input: ParseStream) -> Result { if input.peek(Token![?]) { @@ -859,7 +903,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ConstParam { fn parse(input: ParseStream) -> Result { let mut default = None; @@ -883,11 +927,18 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for WhereClause { fn parse(input: ParseStream) -> Result { + let where_token: Token![where] = input.parse()?; + + if choose_generics_over_qpath(input) { + return Err(input + .error("generic parameters on `where` clauses are reserved for future use")); + } + Ok(WhereClause { - where_token: input.parse()?, + where_token, predicates: { let mut predicates = Punctuated::new(); loop { @@ -914,7 +965,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![where]) { @@ -925,7 +976,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for WherePredicate { fn parse(input: ParseStream) -> Result { if input.peek(Lifetime) && input.peek2(Token![:]) { @@ -972,8 +1023,15 @@ { break; } - let value = input.parse()?; - bounds.push_value(value); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = true; + TypeParamBound::parse_single( + input, + allow_precise_capture, + allow_const, + )? + }); if !input.peek(Token![+]) { break; } @@ -986,21 +1044,123 @@ } } } + + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for PreciseCapture { + fn parse(input: ParseStream) -> Result { + let use_token: Token![use] = input.parse()?; + let lt_token: Token![<] = input.parse()?; + let mut params = Punctuated::new(); + loop { + let lookahead = input.lookahead1(); + params.push_value( + if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(Token![Self]) + { + input.parse::()? + } else if lookahead.peek(Token![>]) { + break; + } else { + return Err(lookahead.error()); + }, + ); + let lookahead = input.lookahead1(); + params.push_punct(if lookahead.peek(Token![,]) { + input.parse::()? + } else if lookahead.peek(Token![>]) { + break; + } else { + return Err(lookahead.error()); + }); + } + let gt_token: Token![>] = input.parse()?; + Ok(PreciseCapture { + use_token, + lt_token, + params, + gt_token, + }) + } + } + + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for CapturedParam { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + if lookahead.peek(Lifetime) { + input.parse().map(CapturedParam::Lifetime) + } else if lookahead.peek(Ident) || input.peek(Token![Self]) { + input.call(Ident::parse_any).map(CapturedParam::Ident) + } else { + Err(lookahead.error()) + } + } + } + + pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool { + // Rust syntax has an ambiguity between generic parameters and qualified + // paths. In `impl :: Thing {}` this may either be a generic + // inherent impl `impl ::Thing` or a non-generic inherent impl + // for an associated type `impl ::Thing`. + // + // After `<` the following continuations can only begin generics, not a + // qualified path: + // + // `<` `>` - empty generic parameters + // `<` `#` - generic parameters with attribute + // `<` LIFETIME `>` - single lifetime parameter + // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list + // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds + // `<` (LIFETIME|IDENT) `=` - generic parameter with a default + // `<` const - generic const parameter + // + // The only truly ambiguous case is: + // + // `<` IDENT `>` `::` IDENT ... + // + // which we disambiguate in favor of generics because this is almost + // always the expected one in the context of real-world code. + input.peek(Token![<]) + && (input.peek2(Token![>]) + || input.peek2(Token![#]) + || (input.peek2(Lifetime) || input.peek2(Ident)) + && (input.peek3(Token![>]) + || input.peek3(Token![,]) + || input.peek3(Token![:]) && !input.peek3(Token![::]) + || input.peek3(Token![=])) + || input.peek2(Token![const])) + } + + #[cfg(feature = "full")] + pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool { + let input = input.fork(); + input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where` + choose_generics_over_qpath(&input) + } } #[cfg(feature = "printing")] -mod printing { +pub(crate) mod printing { use crate::attr::FilterAttrs; + #[cfg(feature = "full")] + use crate::expr; + use crate::expr::Expr; + #[cfg(feature = "full")] + use crate::fixup::FixupContext; use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics, TypeParam, WhereClause, }; + #[cfg(feature = "full")] + use crate::generics::{CapturedParam, PreciseCapture}; use crate::print::TokensOrDefault; + use crate::token; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Generics { fn to_tokens(&self, tokens: &mut TokenStream) { if self.params.is_empty() { @@ -1141,7 +1301,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BoundLifetimes { fn to_tokens(&self, tokens: &mut TokenStream) { self.for_token.to_tokens(tokens); @@ -1151,7 +1311,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LifetimeParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -1163,7 +1323,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -1179,7 +1339,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitBound { fn to_tokens(&self, tokens: &mut TokenStream) { let to_tokens = |tokens: &mut TokenStream| { @@ -1194,7 +1354,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitBoundModifier { fn to_tokens(&self, tokens: &mut TokenStream) { match self { @@ -1204,7 +1364,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ConstParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -1214,12 +1374,12 @@ self.ty.to_tokens(tokens); if let Some(default) = &self.default { TokensOrDefault(&self.eq_token).to_tokens(tokens); - default.to_tokens(tokens); + print_const_argument(default, tokens); } } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for WhereClause { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.predicates.is_empty() { @@ -1229,7 +1389,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PredicateLifetime { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetime.to_tokens(tokens); @@ -1238,7 +1398,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PredicateType { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetimes.to_tokens(tokens); @@ -1247,4 +1407,75 @@ self.bounds.to_tokens(tokens); } } + + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for PreciseCapture { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.use_token.to_tokens(tokens); + self.lt_token.to_tokens(tokens); + + // Print lifetimes before types and consts, regardless of their + // order in self.params. + let mut trailing_or_empty = true; + for param in self.params.pairs() { + if let CapturedParam::Lifetime(_) = **param.value() { + param.to_tokens(tokens); + trailing_or_empty = param.punct().is_some(); + } + } + for param in self.params.pairs() { + if let CapturedParam::Ident(_) = **param.value() { + if !trailing_or_empty { + ::default().to_tokens(tokens); + trailing_or_empty = true; + } + param.to_tokens(tokens); + } + } + + self.gt_token.to_tokens(tokens); + } + } + + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for CapturedParam { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens), + CapturedParam::Ident(ident) => ident.to_tokens(tokens), + } + } + } + + pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) { + match expr { + Expr::Lit(expr) => expr.to_tokens(tokens), + + Expr::Path(expr) + if expr.attrs.is_empty() + && expr.qself.is_none() + && expr.path.get_ident().is_some() => + { + expr.to_tokens(tokens); + } + + #[cfg(feature = "full")] + Expr::Block(expr) => expr.to_tokens(tokens), + + #[cfg(not(feature = "full"))] + Expr::Verbatim(expr) => expr.to_tokens(tokens), + + // ERROR CORRECTION: Add braces to make sure that the + // generated code is valid. + _ => token::Brace::default().surround(tokens, |tokens| { + #[cfg(feature = "full")] + expr::printing::print_expr(expr, tokens, FixupContext::new_stmt()); + + #[cfg(not(feature = "full"))] + expr.to_tokens(tokens); + }), + } + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/group.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/group.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/group.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/group.rs 2006-07-24 01:21:28.000000000 +0000 @@ -82,7 +82,7 @@ ) -> Result<(DelimSpan, ParseBuffer<'a>)> { input.step(|cursor| { if let Some((content, span, rest)) = cursor.group(delimiter) { - let scope = crate::buffer::close_span_of_group(*cursor); + let scope = span.close(); let nested = crate::parse::advance_step_cursor(cursor, content); let unexpected = crate::parse::get_unexpected(input); let content = crate::parse::new_parse_buffer(scope, nested, unexpected); @@ -142,12 +142,13 @@ /// # } /// ``` #[macro_export] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! parenthesized { ($content:ident in $cursor:expr) => { match $crate::__private::parse_parens(&$cursor) { $crate::__private::Ok(parens) => { $content = parens.content; + _ = $content; parens.token } $crate::__private::Err(error) => { @@ -220,12 +221,13 @@ /// # } /// ``` #[macro_export] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! braced { ($content:ident in $cursor:expr) => { match $crate::__private::parse_braces(&$cursor) { $crate::__private::Ok(braces) => { $content = braces.content; + _ = $content; braces.token } $crate::__private::Err(error) => { @@ -275,12 +277,13 @@ /// # } /// ``` #[macro_export] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! bracketed { ($content:ident in $cursor:expr) => { match $crate::__private::parse_brackets(&$cursor) { $crate::__private::Ok(brackets) => { $content = brackets.content; + _ = $content; brackets.token } $crate::__private::Err(error) => { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/ident.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ident.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/ident.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ident.rs 2006-07-24 01:21:28.000000000 +0000 @@ -72,7 +72,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Ident { fn parse(input: ParseStream) -> Result { input.step(|cursor| { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/item.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/item.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/item.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/item.rs 2006-07-24 01:21:28.000000000 +0000 @@ -25,7 +25,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Item { /// A constant item: `const MAX: u16 = 65535`. @@ -100,7 +100,7 @@ ast_struct! { /// A constant item: `const MAX: u16 = 65535`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemConst { pub attrs: Vec, pub vis: Visibility, @@ -117,7 +117,7 @@ ast_struct! { /// An enum definition: `enum Foo { A(A), B(B) }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemEnum { pub attrs: Vec, pub vis: Visibility, @@ -131,7 +131,7 @@ ast_struct! { /// An `extern crate` item: `extern crate serde`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemExternCrate { pub attrs: Vec, pub vis: Visibility, @@ -145,7 +145,7 @@ ast_struct! { /// A free-standing function: `fn process(n: usize) -> Result<()> { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemFn { pub attrs: Vec, pub vis: Visibility, @@ -156,7 +156,7 @@ ast_struct! { /// A block of foreign items: `extern "C" { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemForeignMod { pub attrs: Vec, pub unsafety: Option, @@ -169,7 +169,7 @@ ast_struct! { /// An impl block providing trait or associated items: `impl Trait /// for Data { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemImpl { pub attrs: Vec, pub defaultness: Option, @@ -187,7 +187,7 @@ ast_struct! { /// A macro invocation, which includes `macro_rules!` definitions. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemMacro { pub attrs: Vec, /// The `example` in `macro_rules! example { ... }`. @@ -199,7 +199,7 @@ ast_struct! { /// A module or module declaration: `mod m` or `mod m { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemMod { pub attrs: Vec, pub vis: Visibility, @@ -213,7 +213,7 @@ ast_struct! { /// A static item: `static BIKE: Shed = Shed(42)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemStatic { pub attrs: Vec, pub vis: Visibility, @@ -230,7 +230,7 @@ ast_struct! { /// A struct definition: `struct Foo { x: A }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemStruct { pub attrs: Vec, pub vis: Visibility, @@ -244,7 +244,7 @@ ast_struct! { /// A trait definition: `pub trait Iterator { ... }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemTrait { pub attrs: Vec, pub vis: Visibility, @@ -263,7 +263,7 @@ ast_struct! { /// A trait alias: `pub trait SharableIterator = Iterator + Sync`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemTraitAlias { pub attrs: Vec, pub vis: Visibility, @@ -278,7 +278,7 @@ ast_struct! { /// A type alias: `type Result = std::result::Result`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemType { pub attrs: Vec, pub vis: Visibility, @@ -293,7 +293,7 @@ ast_struct! { /// A union definition: `union Foo { x: A, y: B }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemUnion { pub attrs: Vec, pub vis: Visibility, @@ -306,7 +306,7 @@ ast_struct! { /// A use declaration: `use std::collections::HashMap`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemUse { pub attrs: Vec, pub vis: Visibility, @@ -429,7 +429,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum UseTree { /// A path prefix of imports in a `use` item: `std::...`. Path(UsePath), @@ -450,7 +450,7 @@ ast_struct! { /// A path prefix of imports in a `use` item: `std::...`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UsePath { pub ident: Ident, pub colon2_token: Token![::], @@ -460,7 +460,7 @@ ast_struct! { /// An identifier imported by a `use` item: `HashMap`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseName { pub ident: Ident, } @@ -468,7 +468,7 @@ ast_struct! { /// An renamed identifier imported by a `use` item: `HashMap as Map`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseRename { pub ident: Ident, pub as_token: Token![as], @@ -478,7 +478,7 @@ ast_struct! { /// A glob import in a `use` item: `*`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseGlob { pub star_token: Token![*], } @@ -486,7 +486,7 @@ ast_struct! { /// A braced group of imports in a `use` item: `{A, B, C}`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseGroup { pub brace_token: token::Brace, pub items: Punctuated, @@ -501,7 +501,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ForeignItem { /// A foreign function in an `extern` block. @@ -541,7 +541,7 @@ ast_struct! { /// A foreign function in an `extern` block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemFn { pub attrs: Vec, pub vis: Visibility, @@ -552,7 +552,7 @@ ast_struct! { /// A foreign static item in an `extern` block: `static ext: u8`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemStatic { pub attrs: Vec, pub vis: Visibility, @@ -567,7 +567,7 @@ ast_struct! { /// A foreign type in an `extern` block: `type void`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemType { pub attrs: Vec, pub vis: Visibility, @@ -580,7 +580,7 @@ ast_struct! { /// A macro invocation within an extern block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemMacro { pub attrs: Vec, pub mac: Macro, @@ -596,7 +596,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum TraitItem { /// An associated constant within the definition of a trait. @@ -636,7 +636,7 @@ ast_struct! { /// An associated constant within the definition of a trait. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemConst { pub attrs: Vec, pub const_token: Token![const], @@ -651,7 +651,7 @@ ast_struct! { /// An associated function within the definition of a trait. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemFn { pub attrs: Vec, pub sig: Signature, @@ -662,7 +662,7 @@ ast_struct! { /// An associated type within the definition of a trait. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemType { pub attrs: Vec, pub type_token: Token![type], @@ -677,7 +677,7 @@ ast_struct! { /// A macro invocation within the definition of a trait. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemMacro { pub attrs: Vec, pub mac: Macro, @@ -693,7 +693,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ImplItem { /// An associated constant within an impl block. @@ -733,7 +733,7 @@ ast_struct! { /// An associated constant within an impl block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemConst { pub attrs: Vec, pub vis: Visibility, @@ -751,7 +751,7 @@ ast_struct! { /// An associated function within an impl block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemFn { pub attrs: Vec, pub vis: Visibility, @@ -763,7 +763,7 @@ ast_struct! { /// An associated type within an impl block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemType { pub attrs: Vec, pub vis: Visibility, @@ -779,7 +779,7 @@ ast_struct! { /// A macro invocation within an impl block. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemMacro { pub attrs: Vec, pub mac: Macro, @@ -790,7 +790,7 @@ ast_struct! { /// A function signature in a trait or implementation: `unsafe fn /// initialize(&self)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Signature { pub constness: Option, pub asyncness: Option, @@ -819,7 +819,7 @@ ast_enum_of_structs! { /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum FnArg { /// The `self` argument of an associated method. Receiver(Receiver), @@ -837,7 +837,7 @@ /// is written in shorthand such as `self` or `&self` or `&mut self`. In the /// shorthand case, the type in `ty` is reconstructed as one of `Self`, /// `&Self`, or `&mut Self`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Receiver { pub attrs: Vec, pub reference: Option<(Token![&], Option)>, @@ -866,7 +866,7 @@ /// // ^^^ /// } /// ``` - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Variadic { pub attrs: Vec, pub pat: Option<(Box, Token![:])>, @@ -877,7 +877,7 @@ ast_enum! { /// The mutability of an `Item::Static` or `ForeignItem::Static`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum StaticMutability { Mut(Token![mut]), @@ -887,7 +887,7 @@ ast_enum! { /// Unused, but reserved for RFC 3323 restrictions. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ImplRestriction {} @@ -909,7 +909,7 @@ use crate::error::{Error, Result}; use crate::expr::Expr; use crate::ext::IdentExt as _; - use crate::generics::{Generics, TypeParamBound}; + use crate::generics::{self, Generics, TypeParamBound}; use crate::ident::Ident; use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, @@ -921,7 +921,7 @@ }; use crate::lifetime::Lifetime; use crate::lit::LitStr; - use crate::mac::{self, Macro, MacroDelimiter}; + use crate::mac::{self, Macro}; use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{Pat, PatType, PatWild}; @@ -934,7 +934,7 @@ use crate::verbatim; use proc_macro2::TokenStream; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Item { fn parse(input: ParseStream) -> Result { let begin = input.fork(); @@ -952,7 +952,8 @@ let vis: Visibility = ahead.parse()?; let lookahead = ahead.lookahead1(); - let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { + let allow_safe = false; + let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) { let vis: Visibility = input.parse()?; let sig: Signature = input.parse()?; if input.peek(Token![;]) { @@ -1205,7 +1206,11 @@ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) { break; } - bounds.push_value(input.parse::()?); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = true; + TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? + }); if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) { break; } @@ -1227,7 +1232,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -1281,7 +1286,7 @@ Ok(Item::Verbatim(verbatim::between(&begin, input))) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemExternCrate { fn parse(input: ParseStream) -> Result { Ok(ItemExternCrate { @@ -1314,7 +1319,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemUse { fn parse(input: ParseStream) -> Result { let allow_crate_root_in_path = false; @@ -1348,7 +1353,7 @@ })) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for UseTree { fn parse(input: ParseStream) -> Result { let allow_crate_root_in_path = false; @@ -1411,14 +1416,16 @@ &content, allow_crate_root_in_path && !this_tree_starts_with_crate_root, )? { - Some(tree) => items.push_value(tree), - None => has_any_crate_root_in_path = true, + Some(tree) if !has_any_crate_root_in_path => items.push_value(tree), + _ => has_any_crate_root_in_path = true, } if content.is_empty() { break; } let comma: Token![,] = content.parse()?; - items.push_punct(comma); + if !has_any_crate_root_in_path { + items.push_punct(comma); + } } if has_any_crate_root_in_path { Ok(None) @@ -1430,7 +1437,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemStatic { fn parse(input: ParseStream) -> Result { Ok(ItemStatic { @@ -1448,7 +1455,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -1483,34 +1490,52 @@ } } - fn peek_signature(input: ParseStream) -> bool { + fn peek_signature(input: ParseStream, allow_safe: bool) -> bool { let fork = input.fork(); fork.parse::>().is_ok() && fork.parse::>().is_ok() - && fork.parse::>().is_ok() + && ((allow_safe + && token::parsing::peek_keyword(fork.cursor(), "safe") + && token::parsing::keyword(&fork, "safe").is_ok()) + || fork.parse::>().is_ok()) && fork.parse::>().is_ok() && fork.peek(Token![fn]) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Signature { fn parse(input: ParseStream) -> Result { - let constness: Option = input.parse()?; - let asyncness: Option = input.parse()?; - let unsafety: Option = input.parse()?; - let abi: Option = input.parse()?; - let fn_token: Token![fn] = input.parse()?; - let ident: Ident = input.parse()?; - let mut generics: Generics = input.parse()?; + let allow_safe = false; + parse_signature(input, allow_safe).map(Option::unwrap) + } + } - let content; - let paren_token = parenthesized!(content in input); - let (inputs, variadic) = parse_fn_args(&content)?; + fn parse_signature(input: ParseStream, allow_safe: bool) -> Result> { + let constness: Option = input.parse()?; + let asyncness: Option = input.parse()?; + let unsafety: Option = input.parse()?; + let safe = allow_safe + && unsafety.is_none() + && token::parsing::peek_keyword(input.cursor(), "safe"); + if safe { + token::parsing::keyword(input, "safe")?; + } + let abi: Option = input.parse()?; + let fn_token: Token![fn] = input.parse()?; + let ident: Ident = input.parse()?; + let mut generics: Generics = input.parse()?; - let output: ReturnType = input.parse()?; - generics.where_clause = input.parse()?; + let content; + let paren_token = parenthesized!(content in input); + let (inputs, variadic) = parse_fn_args(&content)?; + + let output: ReturnType = input.parse()?; + generics.where_clause = input.parse()?; - Ok(Signature { + Ok(if safe { + None + } else { + Some(Signature { constness, asyncness, unsafety, @@ -1523,10 +1548,10 @@ variadic, output, }) - } + }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemFn { fn parse(input: ParseStream) -> Result { let outer_attrs = input.call(Attribute::parse_outer)?; @@ -1555,7 +1580,7 @@ }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FnArg { fn parse(input: ParseStream) -> Result { let allow_variadic = false; @@ -1588,7 +1613,7 @@ // test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs // because the rest of the test case is valuable. if input.peek(Ident) && input.peek2(Token![<]) { - let span = input.fork().parse::()?.span(); + let span = input.span(); return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType { attrs, pat: Box::new(Pat::Wild(PatWild { @@ -1622,7 +1647,7 @@ }))) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Receiver { fn parse(input: ParseStream) -> Result { let reference = if input.peek(Token![&]) { @@ -1736,7 +1761,7 @@ Ok((args, variadic)) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemMod { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; @@ -1785,7 +1810,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemForeignMod { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; @@ -1810,7 +1835,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); @@ -1819,35 +1844,55 @@ let vis: Visibility = ahead.parse()?; let lookahead = ahead.lookahead1(); - let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { + let allow_safe = true; + let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) { let vis: Visibility = input.parse()?; - let sig: Signature = input.parse()?; - if input.peek(token::Brace) { + let sig = parse_signature(input, allow_safe)?; + let has_safe = sig.is_none(); + let has_body = input.peek(token::Brace); + let semi_token: Option = if has_body { let content; braced!(content in input); content.call(Attribute::parse_inner)?; content.call(Block::parse_within)?; - + None + } else { + Some(input.parse()?) + }; + if has_safe || has_body { Ok(ForeignItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(ForeignItem::Fn(ForeignItemFn { attrs: Vec::new(), vis, - sig, - semi_token: input.parse()?, + sig: sig.unwrap(), + semi_token: semi_token.unwrap(), })) } - } else if lookahead.peek(Token![static]) { + } else if lookahead.peek(Token![static]) + || ((ahead.peek(Token![unsafe]) + || token::parsing::peek_keyword(ahead.cursor(), "safe")) + && ahead.peek2(Token![static])) + { let vis = input.parse()?; + let unsafety: Option = input.parse()?; + let safe = + unsafety.is_none() && token::parsing::peek_keyword(input.cursor(), "safe"); + if safe { + token::parsing::keyword(input, "safe")?; + } let static_token = input.parse()?; let mutability = input.parse()?; let ident = input.parse()?; let colon_token = input.parse()?; let ty = input.parse()?; - if input.peek(Token![=]) { + let has_value = input.peek(Token![=]); + if has_value { input.parse::()?; input.parse::()?; - input.parse::()?; + } + let semi_token: Token![;] = input.parse()?; + if unsafety.is_some() || safe || has_value { Ok(ForeignItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(ForeignItem::Static(ForeignItemStatic { @@ -1858,7 +1903,7 @@ ident, colon_token, ty, - semi_token: input.parse()?, + semi_token, })) } } else if lookahead.peek(Token![type]) { @@ -1889,7 +1934,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemFn { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -1905,7 +1950,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemStatic { fn parse(input: ParseStream) -> Result { Ok(ForeignItemStatic { @@ -1921,7 +1966,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemType { fn parse(input: ParseStream) -> Result { Ok(ForeignItemType { @@ -1970,7 +2015,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -1988,7 +2033,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemType { fn parse(input: ParseStream) -> Result { Ok(ItemType { @@ -2042,7 +2087,7 @@ })) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemStruct { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2066,7 +2111,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemEnum { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2090,7 +2135,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemUnion { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2141,7 +2186,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemTrait { fn parse(input: ParseStream) -> Result { let outer_attrs = input.call(Attribute::parse_outer)?; @@ -2182,7 +2227,11 @@ if input.peek(Token![where]) || input.peek(token::Brace) { break; } - supertraits.push_value(input.parse()?); + supertraits.push_value({ + let allow_precise_capture = false; + let allow_const = true; + TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? + }); if input.peek(Token![where]) || input.peek(token::Brace) { break; } @@ -2216,7 +2265,7 @@ }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemTraitAlias { fn parse(input: ParseStream) -> Result { let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?; @@ -2250,7 +2299,11 @@ if input.peek(Token![where]) || input.peek(Token![;]) { break; } - bounds.push_value(input.parse()?); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = false; + TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? + }); if input.peek(Token![where]) || input.peek(Token![;]) { break; } @@ -2272,7 +2325,7 @@ }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); @@ -2282,7 +2335,8 @@ let ahead = input.fork(); let lookahead = ahead.lookahead1(); - let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { + let allow_safe = false; + let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) { input.parse().map(TraitItem::Fn) } else if lookahead.peek(Token![const]) { let const_token: Token![const] = ahead.parse()?; @@ -2357,7 +2411,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2394,7 +2448,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemFn { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; @@ -2423,7 +2477,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemType { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2480,7 +2534,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2498,7 +2552,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemImpl { fn parse(input: ParseStream) -> Result { let allow_verbatim_impl = false; @@ -2513,15 +2567,7 @@ let unsafety: Option = input.parse()?; let impl_token: Token![impl] = input.parse()?; - let has_generics = input.peek(Token![<]) - && (input.peek2(Token![>]) - || input.peek2(Token![#]) - || (input.peek2(Ident) || input.peek2(Lifetime)) - && (input.peek3(Token![:]) - || input.peek3(Token![,]) - || input.peek3(Token![>]) - || input.peek3(Token![=])) - || input.peek2(Token![const])); + let has_generics = generics::parsing::choose_generics_over_qpath(input); let mut generics: Generics = if has_generics { input.parse()? } else { @@ -2535,7 +2581,6 @@ input.parse::()?; } - let begin = input.fork(); let polarity = if input.peek(Token![!]) && !input.peek2(token::Brace) { Some(input.parse::()?) } else { @@ -2573,13 +2618,14 @@ trait_ = None; } self_ty = input.parse()?; + } else if let Some(polarity) = polarity { + return Err(Error::new( + polarity.span, + "inherent impls cannot be negative", + )); } else { trait_ = None; - self_ty = if polarity.is_none() { - first_ty - } else { - Type::Verbatim(verbatim::between(&begin, input)) - }; + self_ty = first_ty; } generics.where_clause = input.parse()?; @@ -2610,7 +2656,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); @@ -2627,7 +2673,8 @@ None }; - let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { + let allow_safe = false; + let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) { let allow_omitted_body = true; if let Some(item) = parse_impl_item_fn(input, allow_omitted_body)? { Ok(ImplItem::Fn(item)) @@ -2705,7 +2752,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2742,7 +2789,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemFn { fn parse(input: ParseStream) -> Result { let allow_omitted_body = false; @@ -2783,7 +2830,7 @@ })) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemType { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2845,7 +2892,7 @@ })) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -2872,16 +2919,7 @@ } } - impl MacroDelimiter { - pub(crate) fn is_brace(&self) -> bool { - match self { - MacroDelimiter::Brace(_) => true, - MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false, - } - } - } - - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for StaticMutability { fn parse(input: ParseStream) -> Result { let mut_token: Option = input.parse()?; @@ -2903,12 +2941,14 @@ UsePath, UseRename, Variadic, }; use crate::mac::MacroDelimiter; + use crate::path; + use crate::path::printing::PathStyle; use crate::print::TokensOrDefault; use crate::ty::Type; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemExternCrate { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2924,7 +2964,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemUse { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2936,7 +2976,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemStatic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2952,7 +2992,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2967,7 +3007,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2980,7 +3020,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemMod { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -2999,7 +3039,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemForeignMod { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3012,7 +3052,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3027,7 +3067,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemEnum { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3042,7 +3082,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3068,7 +3108,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemUnion { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3081,7 +3121,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemTrait { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3103,7 +3143,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemTraitAlias { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3118,7 +3158,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemImpl { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3140,11 +3180,11 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); - self.mac.path.to_tokens(tokens); + path::printing::print_path(tokens, &self.mac.path, PathStyle::Mod); self.mac.bang_token.to_tokens(tokens); self.ident.to_tokens(tokens); match &self.mac.delimiter { @@ -3162,7 +3202,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UsePath { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); @@ -3171,14 +3211,14 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseName { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseRename { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); @@ -3187,14 +3227,14 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseGlob { fn to_tokens(&self, tokens: &mut TokenStream) { self.star_token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseGroup { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { @@ -3203,7 +3243,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3219,7 +3259,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3238,7 +3278,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3258,7 +3298,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3267,7 +3307,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3283,7 +3323,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3297,7 +3337,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3313,7 +3353,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3322,7 +3362,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3332,7 +3372,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemStatic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3346,7 +3386,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3359,7 +3399,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3368,7 +3408,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Signature { fn to_tokens(&self, tokens: &mut TokenStream) { self.constness.to_tokens(tokens); @@ -3392,7 +3432,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Receiver { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3425,7 +3465,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Variadic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -3438,7 +3478,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for StaticMutability { fn to_tokens(&self, tokens: &mut TokenStream) { match self { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -249,10 +249,11 @@ //! dynamic library libproc_macro from rustc toolchain. // Syn types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/syn/2.0.60")] -#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![doc(html_root_url = "https://docs.rs/syn/2.0.113")] +#![cfg_attr(docsrs, feature(doc_cfg), doc(auto_cfg = false))] #![deny(unsafe_op_in_unsafe_fn)] #![allow(non_camel_case_types)] +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] #![allow( clippy::bool_to_int_with_if, clippy::cast_lossless, @@ -263,8 +264,11 @@ clippy::derivable_impls, clippy::diverging_sub_expression, clippy::doc_markdown, + clippy::elidable_lifetime_names, + clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_auto_deref, + clippy::fn_params_excessive_bools, clippy::if_not_else, clippy::inherent_to_string, clippy::into_iter_without_iter, @@ -273,8 +277,8 @@ clippy::let_underscore_untyped, // https://github.com/rust-lang/rust-clippy/issues/10410 clippy::manual_assert, clippy::manual_let_else, + clippy::manual_map, clippy::match_like_matches_macro, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 clippy::missing_errors_doc, @@ -282,13 +286,17 @@ clippy::module_name_repetitions, clippy::must_use_candidate, clippy::needless_doctest_main, + clippy::needless_lifetimes, clippy::needless_pass_by_value, + clippy::needless_update, clippy::never_loop, clippy::range_plus_one, clippy::redundant_else, + clippy::ref_option, clippy::return_self_not_must_use, clippy::similar_names, clippy::single_match_else, + clippy::struct_excessive_bools, clippy::too_many_arguments, clippy::too_many_lines, clippy::trivially_copy_pass_by_ref, @@ -300,6 +308,9 @@ clippy::used_underscore_binding, clippy::wildcard_imports, )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] + +extern crate self as syn; #[cfg(feature = "proc-macro")] extern crate proc_macro; @@ -317,15 +328,21 @@ #[cfg(any(feature = "full", feature = "derive"))] mod attr; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue}; mod bigint; #[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub mod buffer; +#[cfg(any( + all(feature = "parsing", feature = "full"), + all(feature = "printing", any(feature = "full", feature = "derive")), +))] +mod classify; + mod custom_keyword; mod custom_punctuation; @@ -333,13 +350,13 @@ #[cfg(any(feature = "full", feature = "derive"))] mod data; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant}; #[cfg(any(feature = "full", feature = "derive"))] mod derive; #[cfg(feature = "derive")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; mod drops; @@ -350,45 +367,49 @@ #[cfg(any(feature = "full", feature = "derive"))] mod expr; #[cfg(feature = "full")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] -pub use crate::expr::{Arm, Label, RangeLimits}; +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub use crate::expr::{Arm, Label, PointerMutability, RangeLimits}; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::expr::{ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprIndex, ExprLit, ExprMacro, ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue, Index, Member, }; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::expr::{ ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprGroup, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch, - ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, - ExprYield, + ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, + ExprWhile, ExprYield, }; -#[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] pub mod ext; #[cfg(feature = "full")] mod file; #[cfg(feature = "full")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::file::File; +#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] +mod fixup; + #[cfg(any(feature = "full", feature = "derive"))] mod generics; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause, WherePredicate, }; +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub use crate::generics::{CapturedParam, PreciseCapture}; #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics}; @@ -400,7 +421,7 @@ #[cfg(feature = "full")] mod item; #[cfg(feature = "full")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ImplRestriction, Item, @@ -428,12 +449,12 @@ #[cfg(any(feature = "full", feature = "derive"))] mod mac; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::mac::{Macro, MacroDelimiter}; #[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))) )] pub mod meta; @@ -441,11 +462,11 @@ #[cfg(any(feature = "full", feature = "derive"))] mod op; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::op::{BinOp, UnOp}; #[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub mod parse; #[cfg(all(feature = "parsing", feature = "proc-macro"))] @@ -457,7 +478,7 @@ #[cfg(feature = "full")] mod pat; #[cfg(feature = "full")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::pat::{ FieldPat, Pat, PatConst, PatIdent, PatLit, PatMacro, PatOr, PatParen, PatPath, PatRange, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, @@ -466,12 +487,18 @@ #[cfg(any(feature = "full", feature = "derive"))] mod path; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::path::{ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument, ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, }; +#[cfg(all( + any(feature = "full", feature = "derive"), + any(feature = "parsing", feature = "printing") +))] +mod precedence; + #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] mod print; @@ -480,21 +507,24 @@ #[cfg(any(feature = "full", feature = "derive"))] mod restriction; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::restriction::{FieldMutability, VisRestricted, Visibility}; mod sealed; +#[cfg(all(feature = "parsing", feature = "derive", not(feature = "full")))] +mod scan_expr; + mod span; #[cfg(all(feature = "parsing", feature = "printing"))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] pub mod spanned; #[cfg(feature = "full")] mod stmt; #[cfg(feature = "full")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::stmt::{Block, Local, LocalInit, Stmt, StmtMacro}; mod thread; @@ -505,7 +535,7 @@ #[cfg(any(feature = "full", feature = "derive"))] mod ty; #[cfg(any(feature = "full", feature = "derive"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, @@ -518,6 +548,7 @@ #[cfg(all(feature = "parsing", feature = "full"))] mod whitespace; +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/6176 mod gen { /// Syntax tree traversal to transform the nodes of an owned syntax tree. /// @@ -600,7 +631,7 @@ /// } /// ``` #[cfg(feature = "fold")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "fold")))] + #[cfg_attr(docsrs, doc(cfg(feature = "fold")))] #[rustfmt::skip] pub mod fold; @@ -719,7 +750,7 @@ /// } /// ``` #[cfg(feature = "visit")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "visit")))] + #[cfg_attr(docsrs, doc(cfg(feature = "visit")))] #[rustfmt::skip] pub mod visit; @@ -813,7 +844,7 @@ /// } /// ``` #[cfg(feature = "visit-mut")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "visit-mut")))] + #[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))] #[rustfmt::skip] pub mod visit_mut; @@ -832,22 +863,18 @@ #[cfg(feature = "extra-traits")] #[rustfmt::skip] mod hash; - - #[cfg(any(feature = "full", feature = "derive"))] - #[path = "../gen_helper.rs"] - mod helper; } #[cfg(feature = "fold")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "fold")))] +#[cfg_attr(docsrs, doc(cfg(feature = "fold")))] pub use crate::gen::fold; #[cfg(feature = "visit")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "visit")))] +#[cfg_attr(docsrs, doc(cfg(feature = "visit")))] pub use crate::gen::visit; #[cfg(feature = "visit-mut")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "visit-mut")))] +#[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))] pub use crate::gen::visit_mut; // Not public API. @@ -868,42 +895,16 @@ /// /// [`syn::parse2`]: parse2 /// -/// # Examples -/// -/// ``` -/// # extern crate proc_macro; -/// # -/// use proc_macro::TokenStream; -/// use quote::quote; -/// use syn::DeriveInput; -/// -/// # const IGNORE_TOKENS: &str = stringify! { -/// #[proc_macro_derive(MyMacro)] -/// # }; -/// pub fn my_macro(input: TokenStream) -> TokenStream { -/// // Parse the tokens into a syntax tree -/// let ast: DeriveInput = syn::parse(input).unwrap(); -/// -/// // Build the output, possibly using quasi-quotation -/// let expanded = quote! { -/// /* ... */ -/// }; -/// -/// // Convert into a token stream and return it -/// expanded.into() -/// } -/// ``` +/// This function enforces that the input is fully parsed. If there are any +/// unparsed tokens at the end of the stream, an error is returned. #[cfg(all(feature = "parsing", feature = "proc-macro"))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] pub fn parse(tokens: proc_macro::TokenStream) -> Result { parse::Parser::parse(T::parse, tokens) } /// Parse a proc-macro2 token stream into the chosen syntax tree node. /// -/// This function will check that the input is fully parsed. If there are -/// any unparsed tokens at the end of the stream, an error is returned. -/// /// This function parses a `proc_macro2::TokenStream` which is commonly useful /// when the input comes from a node of the Syn syntax tree, for example the /// body tokens of a [`Macro`] node. When in a procedural macro parsing the @@ -911,14 +912,20 @@ /// instead. /// /// [`syn::parse`]: parse() +/// +/// This function enforces that the input is fully parsed. If there are any +/// unparsed tokens at the end of the stream, an error is returned. #[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse2(tokens: proc_macro2::TokenStream) -> Result { parse::Parser::parse2(T::parse, tokens) } /// Parse a string of Rust code into the chosen syntax tree node. /// +/// This function enforces that the input is fully parsed. If there are any +/// unparsed tokens at the end of the stream, an error is returned. +/// /// # Hygiene /// /// Every span in the resulting syntax tree will be set to resolve at the macro @@ -939,13 +946,11 @@ /// # run().unwrap(); /// ``` #[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_str(s: &str) -> Result { parse::Parser::parse_str(T::parse, s) } -// FIXME the name parse_file makes it sound like you might pass in a path to a -// file, rather than the content. /// Parse the content of a file of Rust code. /// /// This is different from `syn::parse_str::(content)` in two ways: @@ -959,14 +964,11 @@ /// /// ```no_run /// use std::error::Error; -/// use std::fs::File; +/// use std::fs; /// use std::io::Read; /// /// fn run() -> Result<(), Box> { -/// let mut file = File::open("path/to/code.rs")?; -/// let mut content = String::new(); -/// file.read_to_string(&mut content)?; -/// +/// let content = fs::read_to_string("path/to/code.rs")?; /// let ast = syn::parse_file(&content)?; /// if let Some(shebang) = ast.shebang { /// println!("{}", shebang); @@ -979,7 +981,7 @@ /// # run().unwrap(); /// ``` #[cfg(all(feature = "parsing", feature = "full"))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "full"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] pub fn parse_file(mut content: &str) -> Result { // Strip the BOM if it is present const BOM: &str = "\u{feff}"; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lifetime.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -126,7 +126,7 @@ use crate::lifetime::Lifetime; use crate::parse::{Parse, ParseStream}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Lifetime { fn parse(input: ParseStream) -> Result { input.step(|cursor| { @@ -140,16 +140,15 @@ #[cfg(feature = "printing")] mod printing { + use crate::ext::PunctExt as _; use crate::lifetime::Lifetime; use proc_macro2::{Punct, Spacing, TokenStream}; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Lifetime { fn to_tokens(&self, tokens: &mut TokenStream) { - let mut apostrophe = Punct::new('\'', Spacing::Joint); - apostrophe.set_span(self.apostrophe); - tokens.append(apostrophe); + tokens.append(Punct::new_spanned('\'', Spacing::Joint, self.apostrophe)); self.ident.to_tokens(tokens); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lit.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lit.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,6 @@ #[cfg(feature = "parsing")] +use crate::ext::TokenStreamExt as _; +#[cfg(feature = "parsing")] use crate::lookahead; #[cfg(feature = "parsing")] use crate::parse::{Parse, Parser}; @@ -143,7 +145,7 @@ pub fn value(&self) -> String { let repr = self.repr.token.to_string(); - let (value, _suffix) = value::parse_lit_str(&repr); + let (value, _suffix) = value::parse_lit_str(&repr).unwrap(); String::from(value) } @@ -179,7 +181,7 @@ /// } /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse(&self) -> Result { self.parse_with(T::parse) } @@ -209,16 +211,17 @@ /// # } /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_with(&self, parser: F) -> Result { use proc_macro2::Group; // Token stream with every span replaced by the given one. fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream { - stream - .into_iter() - .map(|token| respan_token_tree(token, span)) - .collect() + let mut tokens = TokenStream::new(); + for token in stream { + tokens.append(respan_token_tree(token, span)); + } + tokens } // Token tree with every span replaced by the given one. @@ -284,7 +287,7 @@ pub fn value(&self) -> Vec { let repr = self.repr.token.to_string(); - let (value, _suffix) = value::parse_lit_byte_str(&repr); + let (value, _suffix) = value::parse_lit_byte_str(&repr).unwrap(); value } @@ -319,7 +322,7 @@ pub fn value(&self) -> CString { let repr = self.repr.token.to_string(); - let (value, _suffix) = value::parse_lit_c_str(&repr); + let (value, _suffix) = value::parse_lit_c_str(&repr).unwrap(); value } @@ -342,7 +345,7 @@ impl LitByte { pub fn new(value: u8, span: Span) -> Self { - let mut token = Literal::u8_suffixed(value); + let mut token = Literal::byte_character(value); token.set_span(span); LitByte { repr: Box::new(LitRepr { @@ -354,7 +357,7 @@ pub fn value(&self) -> u8 { let repr = self.repr.token.to_string(); - let (value, _suffix) = value::parse_lit_byte(&repr); + let (value, _suffix) = value::parse_lit_byte(&repr).unwrap(); value } @@ -389,7 +392,7 @@ pub fn value(&self) -> char { let repr = self.repr.token.to_string(); - let (value, _suffix) = value::parse_lit_char(&repr); + let (value, _suffix) = value::parse_lit_char(&repr).unwrap(); value } @@ -411,6 +414,7 @@ } impl LitInt { + #[track_caller] pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_int(repr) { Some(parse) => parse, @@ -482,6 +486,7 @@ } impl From for LitInt { + #[track_caller] fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_int(&repr) { @@ -505,6 +510,7 @@ } impl LitFloat { + #[track_caller] pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_float(repr) { Some(parse) => parse, @@ -554,6 +560,7 @@ } impl From for LitFloat { + #[track_caller] fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_float(&repr) { @@ -604,7 +611,7 @@ use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr}; use std::fmt::{self, Debug}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitStr") @@ -620,7 +627,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitByteStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitByteStr") @@ -636,7 +643,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitCStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitCStr") @@ -652,7 +659,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitByte { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitByte") @@ -668,7 +675,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitChar { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitChar") @@ -684,7 +691,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitInt { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitInt") @@ -700,7 +707,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitFloat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitFloat") @@ -716,7 +723,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitBool { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitBool") @@ -734,7 +741,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitRepr { fn clone(&self) -> Self { LitRepr { @@ -745,7 +752,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitIntRepr { fn clone(&self) -> Self { LitIntRepr { @@ -757,7 +764,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitFloatRepr { fn clone(&self) -> Self { LitFloatRepr { @@ -771,7 +778,7 @@ macro_rules! lit_extra_traits { ($ty:ident) => { #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $ty { fn clone(&self) -> Self { $ty { @@ -781,7 +788,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $ty { fn eq(&self, other: &Self) -> bool { self.repr.token.to_string() == other.repr.token.to_string() @@ -789,7 +796,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $ty { fn hash(&self, state: &mut H) where @@ -856,10 +863,13 @@ value, Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt, LitIntRepr, LitStr, }; - use crate::parse::{Parse, ParseStream}; - use proc_macro2::{Literal, Punct}; + use crate::parse::{Parse, ParseStream, Unexpected}; + use crate::token::{self, Token}; + use proc_macro2::{Literal, Punct, Span}; + use std::cell::Cell; + use std::rc::Rc; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Lit { fn parse(input: ParseStream) -> Result { input.step(|cursor| { @@ -930,7 +940,7 @@ )) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -941,7 +951,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitByteStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -952,7 +962,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitCStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -963,7 +973,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitByte { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -974,7 +984,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitChar { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -985,7 +995,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitInt { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -996,7 +1006,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitFloat { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -1007,7 +1017,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitBool { fn parse(input: ParseStream) -> Result { let head = input.fork(); @@ -1017,64 +1027,100 @@ } } } + + fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool { + let scope = Span::call_site(); + let unexpected = Rc::new(Cell::new(Unexpected::None)); + let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected); + peek(&buffer) + } + + macro_rules! impl_token { + ($display:literal $name:ty) => { + impl Token for $name { + fn peek(cursor: Cursor) -> bool { + fn peek(input: ParseStream) -> bool { + <$name as Parse>::parse(input).is_ok() + } + peek_impl(cursor, peek) + } + + fn display() -> &'static str { + $display + } + } + + impl token::private::Sealed for $name {} + }; + } + + impl_token!("literal" Lit); + impl_token!("string literal" LitStr); + impl_token!("byte string literal" LitByteStr); + impl_token!("C-string literal" LitCStr); + impl_token!("byte literal" LitByte); + impl_token!("character literal" LitChar); + impl_token!("integer literal" LitInt); + impl_token!("floating point literal" LitFloat); + impl_token!("boolean literal" LitBool); } #[cfg(feature = "printing")] mod printing { use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr}; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitByteStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitCStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitByte { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitChar { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitInt { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitFloat { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitBool { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.token()); @@ -1089,7 +1135,6 @@ LitIntRepr, LitRepr, LitStr, }; use proc_macro2::{Literal, Span}; - use std::ascii; use std::char; use std::ffi::CString; use std::ops::{Index, RangeFrom}; @@ -1098,49 +1143,67 @@ /// Interpret a Syn literal from a proc-macro2 literal. pub fn new(token: Literal) -> Self { let repr = token.to_string(); + Lit::from_str(token, &repr) + } + + #[cfg(fuzzing)] + #[doc(hidden)] + pub fn from_str_for_fuzzing(repr: &str) -> Self { + let token = Literal::u8_unsuffixed(0); + Lit::from_str(token, repr) + } - match byte(&repr, 0) { + fn from_str(token: Literal, repr: &str) -> Self { + match byte(repr, 0) { // "...", r"...", r#"..."# b'"' | b'r' => { - let (_, suffix) = parse_lit_str(&repr); - return Lit::Str(LitStr { - repr: Box::new(LitRepr { token, suffix }), - }); + if let Some((_, suffix)) = parse_lit_str(repr) { + return Lit::Str(LitStr { + repr: Box::new(LitRepr { token, suffix }), + }); + } } - b'b' => match byte(&repr, 1) { + b'b' => match byte(repr, 1) { // b"...", br"...", br#"...#" b'"' | b'r' => { - let (_, suffix) = parse_lit_byte_str(&repr); - return Lit::ByteStr(LitByteStr { - repr: Box::new(LitRepr { token, suffix }), - }); + if let Some((_, suffix)) = parse_lit_byte_str(repr) { + return Lit::ByteStr(LitByteStr { + repr: Box::new(LitRepr { token, suffix }), + }); + } } // b'...' b'\'' => { - let (_, suffix) = parse_lit_byte(&repr); - return Lit::Byte(LitByte { - repr: Box::new(LitRepr { token, suffix }), - }); + if let Some((_, suffix)) = parse_lit_byte(repr) { + return Lit::Byte(LitByte { + repr: Box::new(LitRepr { token, suffix }), + }); + } + } + _ => {} + }, + b'c' => match byte(repr, 1) { + // c"...", cr"...", cr#"..."# + b'"' | b'r' => { + if let Some((_, suffix)) = parse_lit_c_str(repr) { + return Lit::CStr(LitCStr { + repr: Box::new(LitRepr { token, suffix }), + }); + } } _ => {} }, - // c"...", cr"...", cr#"..."# - b'c' => { - let (_, suffix) = parse_lit_c_str(&repr); - return Lit::CStr(LitCStr { - repr: Box::new(LitRepr { token, suffix }), - }); - } // '...' b'\'' => { - let (_, suffix) = parse_lit_char(&repr); - return Lit::Char(LitChar { - repr: Box::new(LitRepr { token, suffix }), - }); + if let Some((_, suffix)) = parse_lit_char(repr) { + return Lit::Char(LitChar { + repr: Box::new(LitRepr { token, suffix }), + }); + } } b'0'..=b'9' | b'-' => { // 0, 123, 0xFF, 0o77, 0b11 - if let Some((digits, suffix)) = parse_lit_int(&repr) { + if let Some((digits, suffix)) = parse_lit_int(repr) { return Lit::Int(LitInt { repr: Box::new(LitIntRepr { token, @@ -1150,7 +1213,7 @@ }); } // 1.0, 1e-1, 1e+1 - if let Some((digits, suffix)) = parse_lit_float(&repr) { + if let Some((digits, suffix)) = parse_lit_float(repr) { return Lit::Float(LitFloat { repr: Box::new(LitFloatRepr { token, @@ -1173,7 +1236,7 @@ _ => {} } - panic!("unrecognized literal: `{}`", repr); + Lit::Verbatim(token) } pub fn suffix(&self) -> &str { @@ -1234,7 +1297,7 @@ } // Returns (content, suffix). - pub(crate) fn parse_lit_str(s: &str) -> (Box, Box) { + pub(crate) fn parse_lit_str(s: &str) -> Option<(Box, Box)> { match byte(s, 0) { b'"' => parse_lit_str_cooked(s), b'r' => parse_lit_str_raw(s), @@ -1242,10 +1305,7 @@ } } - // Clippy false positive - // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 - #[allow(clippy::needless_continue)] - fn parse_lit_str_cooked(mut s: &str) -> (Box, Box) { + fn parse_lit_str_cooked(mut s: &str) -> Option<(Box, Box)> { assert_eq!(byte(s, 0), b'"'); s = &s[1..]; @@ -1255,16 +1315,19 @@ b'"' => break, b'\\' => { let b = byte(s, 1); - s = &s[2..]; + s = s.get(2..)?; match b { b'x' => { - let (byte, rest) = backslash_x(s); + let (byte, rest) = backslash_x(s)?; s = rest; - assert!(byte <= 0x7F, "invalid \\x byte in string literal"); - char::from_u32(u32::from(byte)).unwrap() + if byte > 0x7F { + // invalid \x byte in string literal + return None; + } + char::from(byte) } b'u' => { - let (ch, rest) = backslash_u(s); + let (ch, rest) = backslash_u(s)?; s = rest; ch } @@ -1282,20 +1345,23 @@ _ => continue 'outer, } }, - b => panic!( - "unexpected byte '{}' after \\ character in string literal", - ascii::escape_default(b), - ), + _ => { + // unexpected byte after backslash + return None; + } } } b'\r' => { - assert_eq!(byte(s, 1), b'\n', "bare CR not allowed in string"); + if byte(s, 1) != b'\n' { + // bare carriage return not allowed in string + return None; + } s = &s[2..]; '\n' } _ => { let ch = next_chr(s); - s = &s[ch.len_utf8()..]; + s = s.get(ch.len_utf8()..)?; ch } }; @@ -1305,30 +1371,35 @@ assert!(s.starts_with('"')); let content = content.into_boxed_str(); let suffix = s[1..].to_owned().into_boxed_str(); - (content, suffix) + Some((content, suffix)) } - fn parse_lit_str_raw(mut s: &str) -> (Box, Box) { + fn parse_lit_str_raw(mut s: &str) -> Option<(Box, Box)> { assert_eq!(byte(s, 0), b'r'); s = &s[1..]; let mut pounds = 0; - while byte(s, pounds) == b'#' { - pounds += 1; + loop { + match byte(s, pounds) { + b'#' => pounds += 1, + b'"' => break, + _ => return None, + } } - assert_eq!(byte(s, pounds), b'"'); let close = s.rfind('"').unwrap(); - for end in s[close + 1..close + 1 + pounds].bytes() { - assert_eq!(end, b'#'); + for end in s.get(close + 1..close + 1 + pounds)?.bytes() { + if end != b'#' { + return None; + } } - let content = s[pounds + 1..close].to_owned().into_boxed_str(); + let content = s.get(pounds + 1..close)?.to_owned().into_boxed_str(); let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str(); - (content, suffix) + Some((content, suffix)) } // Returns (content, suffix). - pub(crate) fn parse_lit_byte_str(s: &str) -> (Vec, Box) { + pub(crate) fn parse_lit_byte_str(s: &str) -> Option<(Vec, Box)> { assert_eq!(byte(s, 0), b'b'); match byte(s, 1) { b'"' => parse_lit_byte_str_cooked(s), @@ -1337,10 +1408,7 @@ } } - // Clippy false positive - // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 - #[allow(clippy::needless_continue)] - fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec, Box) { + fn parse_lit_byte_str_cooked(mut s: &str) -> Option<(Vec, Box)> { assert_eq!(byte(s, 0), b'b'); assert_eq!(byte(s, 1), b'"'); s = &s[2..]; @@ -1354,10 +1422,10 @@ b'"' => break, b'\\' => { let b = byte(v, 1); - v = &v[2..]; + v = v.get(2..)?; match b { b'x' => { - let (b, rest) = backslash_x(v); + let (b, rest) = backslash_x(v)?; v = rest; b } @@ -1376,19 +1444,22 @@ continue 'outer; } }, - b => panic!( - "unexpected byte '{}' after \\ character in byte-string literal", - ascii::escape_default(b), - ), + _ => { + // unexpected byte after backslash + return None; + } } } b'\r' => { - assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string"); + if byte(v, 1) != b'\n' { + // bare carriage return not allowed in string + return None; + } v = &v[2..]; b'\n' } b => { - v = &v[1..]; + v = v.get(1..)?; b } }; @@ -1397,17 +1468,17 @@ assert_eq!(byte(v, 0), b'"'); let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); - (out, suffix) + Some((out, suffix)) } - fn parse_lit_byte_str_raw(s: &str) -> (Vec, Box) { + fn parse_lit_byte_str_raw(s: &str) -> Option<(Vec, Box)> { assert_eq!(byte(s, 0), b'b'); - let (value, suffix) = parse_lit_str_raw(&s[1..]); - (String::from(value).into_bytes(), suffix) + let (value, suffix) = parse_lit_str_raw(&s[1..])?; + Some((String::from(value).into_bytes(), suffix)) } // Returns (content, suffix). - pub(crate) fn parse_lit_c_str(s: &str) -> (CString, Box) { + pub(crate) fn parse_lit_c_str(s: &str) -> Option<(CString, Box)> { assert_eq!(byte(s, 0), b'c'); match byte(s, 1) { b'"' => parse_lit_c_str_cooked(s), @@ -1416,10 +1487,7 @@ } } - // Clippy false positive - // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 - #[allow(clippy::needless_continue)] - fn parse_lit_c_str_cooked(mut s: &str) -> (CString, Box) { + fn parse_lit_c_str_cooked(mut s: &str) -> Option<(CString, Box)> { assert_eq!(byte(s, 0), b'c'); assert_eq!(byte(s, 1), b'"'); s = &s[2..]; @@ -1433,17 +1501,23 @@ b'"' => break, b'\\' => { let b = byte(v, 1); - v = &v[2..]; + v = v.get(2..)?; match b { b'x' => { - let (b, rest) = backslash_x(v); - assert!(b != 0, "\\x00 is not allowed in C-string literal"); + let (b, rest) = backslash_x(v)?; + if b == 0 { + // \x00 is not allowed in C-string literal + return None; + } v = rest; b } b'u' => { - let (ch, rest) = backslash_u(v); - assert!(ch != '\0', "\\u{{0}} is not allowed in C-string literal"); + let (ch, rest) = backslash_u(v)?; + if ch == '\0' { + // \u{0} is not allowed in C-string literal + return None; + } v = rest; out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes()); continue 'outer; @@ -1462,19 +1536,22 @@ continue 'outer; } }, - b => panic!( - "unexpected byte '{}' after \\ character in byte literal", - ascii::escape_default(b), - ), + _ => { + // unexpected byte after backslash + return None; + } } } b'\r' => { - assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string"); + if byte(v, 1) != b'\n' { + // bare carriage return not allowed in string + return None; + } v = &v[2..]; b'\n' } b => { - v = &v[1..]; + v = v.get(1..)?; b } }; @@ -1483,30 +1560,32 @@ assert_eq!(byte(v, 0), b'"'); let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); - (CString::new(out).unwrap(), suffix) + let cstring = CString::new(out).ok()?; + Some((cstring, suffix)) } - fn parse_lit_c_str_raw(s: &str) -> (CString, Box) { + fn parse_lit_c_str_raw(s: &str) -> Option<(CString, Box)> { assert_eq!(byte(s, 0), b'c'); - let (value, suffix) = parse_lit_str_raw(&s[1..]); - (CString::new(String::from(value)).unwrap(), suffix) + let (value, suffix) = parse_lit_str_raw(&s[1..])?; + let cstring = CString::new(String::from(value)).ok()?; + Some((cstring, suffix)) } // Returns (value, suffix). - pub(crate) fn parse_lit_byte(s: &str) -> (u8, Box) { + pub(crate) fn parse_lit_byte(s: &str) -> Option<(u8, Box)> { assert_eq!(byte(s, 0), b'b'); assert_eq!(byte(s, 1), b'\''); // We're going to want to have slices which don't respect codepoint boundaries. - let mut v = s[2..].as_bytes(); + let mut v = &s.as_bytes()[2..]; let b = match byte(v, 0) { b'\\' => { let b = byte(v, 1); - v = &v[2..]; + v = v.get(2..)?; match b { b'x' => { - let (b, rest) = backslash_x(v); + let (b, rest) = backslash_x(v)?; v = rest; b } @@ -1517,41 +1596,47 @@ b'0' => b'\0', b'\'' => b'\'', b'"' => b'"', - b => panic!( - "unexpected byte '{}' after \\ character in byte literal", - ascii::escape_default(b), - ), + _ => { + // unexpected byte after backslash + return None; + } } } b => { - v = &v[1..]; + v = v.get(1..)?; b } }; - assert_eq!(byte(v, 0), b'\''); + if byte(v, 0) != b'\'' { + return None; + } + let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); - (b, suffix) + Some((b, suffix)) } // Returns (value, suffix). - pub(crate) fn parse_lit_char(mut s: &str) -> (char, Box) { + pub(crate) fn parse_lit_char(mut s: &str) -> Option<(char, Box)> { assert_eq!(byte(s, 0), b'\''); s = &s[1..]; let ch = match byte(s, 0) { b'\\' => { let b = byte(s, 1); - s = &s[2..]; + s = s.get(2..)?; match b { b'x' => { - let (byte, rest) = backslash_x(s); + let (byte, rest) = backslash_x(s)?; s = rest; - assert!(byte <= 0x7F, "invalid \\x byte in character literal"); - char::from_u32(u32::from(byte)).unwrap() + if byte > 0x7F { + // invalid \x byte in character literal + return None; + } + char::from(byte) } b'u' => { - let (ch, rest) = backslash_u(s); + let (ch, rest) = backslash_u(s)?; s = rest; ch } @@ -1562,24 +1647,28 @@ b'0' => '\0', b'\'' => '\'', b'"' => '"', - b => panic!( - "unexpected byte '{}' after \\ character in character literal", - ascii::escape_default(b), - ), + _ => { + // unexpected byte after backslash + return None; + } } } _ => { let ch = next_chr(s); - s = &s[ch.len_utf8()..]; + s = s.get(ch.len_utf8()..)?; ch } }; - assert_eq!(byte(s, 0), b'\''); + + if byte(s, 0) != b'\'' { + return None; + } + let suffix = s[1..].to_owned().into_boxed_str(); - (ch, suffix) + Some((ch, suffix)) } - fn backslash_x(s: &S) -> (u8, &S) + fn backslash_x(s: &S) -> Option<(u8, &S)> where S: Index, Output = S> + AsRef<[u8]> + ?Sized, { @@ -1591,23 +1680,23 @@ b'0'..=b'9' => b0 - b'0', b'a'..=b'f' => 10 + (b0 - b'a'), b'A'..=b'F' => 10 + (b0 - b'A'), - _ => panic!("unexpected non-hex character after \\x"), + _ => return None, }; ch += match b1 { b'0'..=b'9' => b1 - b'0', b'a'..=b'f' => 10 + (b1 - b'a'), b'A'..=b'F' => 10 + (b1 - b'A'), - _ => panic!("unexpected non-hex character after \\x"), + _ => return None, }; - (ch, &s[2..]) + Some((ch, &s[2..])) } - fn backslash_u(mut s: &S) -> (char, &S) + fn backslash_u(mut s: &S) -> Option<(char, &S)> where S: Index, Output = S> + AsRef<[u8]> + ?Sized, { if byte(s, 0) != b'{' { - panic!("{}", "expected { after \\u"); + return None; } s = &s[1..]; @@ -1623,26 +1712,25 @@ s = &s[1..]; continue; } - b'}' if digits == 0 => panic!("invalid empty unicode escape"), + b'}' if digits == 0 => return None, b'}' => break, - _ => panic!("unexpected non-hex character after \\u"), + _ => return None, }; if digits == 6 { - panic!("overlong unicode escape (must have at most 6 hex digits)"); + return None; } ch *= 0x10; ch += u32::from(digit); digits += 1; s = &s[1..]; } - assert!(byte(s, 0) == b'}'); + if byte(s, 0) != b'}' { + return None; + } s = &s[1..]; - if let Some(ch) = char::from_u32(ch) { - (ch, s) - } else { - panic!("character code {:x} is not a valid unicode character", ch); - } + let ch = char::from_u32(ch)?; + Some((ch, s)) } // Returns base 10 digits and suffix. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lookahead.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lookahead.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/lookahead.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/lookahead.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,9 +2,10 @@ use crate::error::{self, Error}; use crate::sealed::lookahead::Sealed; use crate::span::IntoSpans; -use crate::token::Token; +use crate::token::{CustomToken, Token}; use proc_macro2::{Delimiter, Span}; use std::cell::RefCell; +use std::fmt::{self, Display}; /// Support for checking the next token in a stream to decide how to parse. /// @@ -110,7 +111,18 @@ /// The error message will identify all of the expected token types that /// have been peeked against this lookahead instance. pub fn error(self) -> Error { - let comparisons = self.comparisons.borrow(); + let mut comparisons = self.comparisons.into_inner(); + comparisons.retain_mut(|display| { + if *display == "`)`" { + *display = match self.cursor.scope_delimiter() { + Delimiter::Parenthesis => "`)`", + Delimiter::Brace => "`}`", + Delimiter::Bracket => "`]`", + Delimiter::None => return false, + } + } + true + }); match comparisons.len() { 0 => { if self.cursor.eof() { @@ -128,14 +140,29 @@ error::new_at(self.scope, self.cursor, message) } _ => { - let join = comparisons.join(", "); - let message = format!("expected one of: {}", join); + let message = format!("expected one of: {}", CommaSeparated(&comparisons)); error::new_at(self.scope, self.cursor, message) } } } } +struct CommaSeparated<'a>(&'a [&'a str]); + +impl<'a> Display for CommaSeparated<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut first = true; + for &s in self.0 { + if !first { + f.write_str(", ")?; + } + f.write_str(s)?; + first = false; + } + Ok(()) + } +} + /// Types that can be parsed by looking at just one token. /// /// Use [`ParseStream::peek`] to peek one of these types in a parse stream @@ -150,6 +177,160 @@ type Token: Token; } +/// Pseudo-token used for peeking the end of a parse stream. +/// +/// This type is only useful as an argument to one of the following functions: +/// +/// - [`ParseStream::peek`][crate::parse::ParseBuffer::peek] +/// - [`ParseStream::peek2`][crate::parse::ParseBuffer::peek2] +/// - [`ParseStream::peek3`][crate::parse::ParseBuffer::peek3] +/// - [`Lookahead1::peek`] +/// +/// The peek will return `true` if there are no remaining tokens after that +/// point in the parse stream. +/// +/// # Example +/// +/// Suppose we are parsing attributes containing core::fmt inspired formatting +/// arguments: +/// +/// - `#[fmt("simple example")]` +/// - `#[fmt("interpolation e{}ample", self.x)]` +/// - `#[fmt("interpolation e{x}ample")]` +/// +/// and we want to recognize the cases where no interpolation occurs so that +/// more efficient code can be generated. +/// +/// The following implementation uses `input.peek(Token![,]) && +/// input.peek2(End)` to recognize the case of a trailing comma without +/// consuming the comma from the parse stream, because if it isn't a trailing +/// comma, that same comma needs to be parsed as part of `args`. +/// +/// ``` +/// use proc_macro2::TokenStream; +/// use quote::quote; +/// use syn::parse::{End, Parse, ParseStream, Result}; +/// use syn::{parse_quote, Attribute, LitStr, Token}; +/// +/// struct FormatArgs { +/// template: LitStr, // "...{}..." +/// args: TokenStream, // , self.x +/// } +/// +/// impl Parse for FormatArgs { +/// fn parse(input: ParseStream) -> Result { +/// let template: LitStr = input.parse()?; +/// +/// let args = if input.is_empty() +/// || input.peek(Token![,]) && input.peek2(End) +/// { +/// input.parse::>()?; +/// TokenStream::new() +/// } else { +/// input.parse()? +/// }; +/// +/// Ok(FormatArgs { +/// template, +/// args, +/// }) +/// } +/// } +/// +/// fn main() -> Result<()> { +/// let attrs: Vec = parse_quote! { +/// #[fmt("simple example")] +/// #[fmt("interpolation e{}ample", self.x)] +/// #[fmt("interpolation e{x}ample")] +/// }; +/// +/// for attr in &attrs { +/// let FormatArgs { template, args } = attr.parse_args()?; +/// let requires_fmt_machinery = +/// !args.is_empty() || template.value().contains(['{', '}']); +/// let out = if requires_fmt_machinery { +/// quote! { +/// ::core::write!(__formatter, #template #args) +/// } +/// } else { +/// quote! { +/// __formatter.write_str(#template) +/// } +/// }; +/// println!("{}", out); +/// } +/// Ok(()) +/// } +/// ``` +/// +/// Implementing this parsing logic without `peek2(End)` is more clumsy because +/// we'd need a parse stream actually advanced past the comma before being able +/// to find out whether there is anything after it. It would look something +/// like: +/// +/// ``` +/// # use proc_macro2::TokenStream; +/// # use syn::parse::{ParseStream, Result}; +/// # use syn::Token; +/// # +/// # fn parse(input: ParseStream) -> Result<()> { +/// use syn::parse::discouraged::Speculative as _; +/// +/// let ahead = input.fork(); +/// ahead.parse::>()?; +/// let args = if ahead.is_empty() { +/// input.advance_to(&ahead); +/// TokenStream::new() +/// } else { +/// input.parse()? +/// }; +/// # Ok(()) +/// # } +/// ``` +/// +/// or: +/// +/// ``` +/// # use proc_macro2::TokenStream; +/// # use syn::parse::{ParseStream, Result}; +/// # use syn::Token; +/// # +/// # fn parse(input: ParseStream) -> Result<()> { +/// use quote::ToTokens as _; +/// +/// let comma: Option = input.parse()?; +/// let mut args = TokenStream::new(); +/// if !input.is_empty() { +/// comma.to_tokens(&mut args); +/// input.parse::()?.to_tokens(&mut args); +/// } +/// # Ok(()) +/// # } +/// ``` +pub struct End; + +impl Copy for End {} + +impl Clone for End { + fn clone(&self) -> Self { + *self + } +} + +impl Peek for End { + type Token = Self; +} + +impl CustomToken for End { + fn peek(cursor: Cursor) -> bool { + cursor.eof() + } + + fn display() -> &'static str { + "`)`" // Lookahead1 error message will fill in the expected close delimiter + } +} + impl T, T: Token> Peek for F { type Token = T; } @@ -162,8 +343,6 @@ } } -pub(crate) fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool { - cursor.group(delimiter).is_some() -} - impl T, T: Token> Sealed for F {} + +impl Sealed for End {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/mac.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/mac.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/mac.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/mac.rs 2006-07-24 01:21:28.000000000 +0000 @@ -13,7 +13,7 @@ ast_struct! { /// A macro invocation: `println!("{}", mac)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Macro { pub path: Path, pub bang_token: Token![!], @@ -24,7 +24,7 @@ ast_enum! { /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum MacroDelimiter { Paren(Paren), Brace(Brace), @@ -40,6 +40,14 @@ MacroDelimiter::Bracket(token) => &token.span, } } + + #[cfg(all(feature = "full", any(feature = "parsing", feature = "printing")))] + pub(crate) fn is_brace(&self) -> bool { + match self { + MacroDelimiter::Brace(_) => true, + MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false, + } + } } impl Macro { @@ -126,7 +134,7 @@ /// } /// ``` #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_body(&self) -> Result { self.parse_body_with(T::parse) } @@ -134,7 +142,7 @@ /// Parse the tokens within the macro invocation's delimiters using the /// given parser. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_body_with(&self, parser: F) -> Result { let scope = self.delimiter.span().close(); crate::parse::parse_scoped(parser, scope, self.tokens.clone()) @@ -168,7 +176,7 @@ use crate::parse::{Parse, ParseStream}; use crate::path::Path; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Macro { fn parse(input: ParseStream) -> Result { let tokens; @@ -189,6 +197,8 @@ #[cfg(feature = "printing")] mod printing { use crate::mac::{Macro, MacroDelimiter}; + use crate::path; + use crate::path::printing::PathStyle; use crate::token; use proc_macro2::{Delimiter, TokenStream}; use quote::ToTokens; @@ -204,10 +214,10 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Macro { fn to_tokens(&self, tokens: &mut TokenStream) { - self.path.to_tokens(tokens); + path::printing::print_path(tokens, &self.path, PathStyle::Mod); self.bang_token.to_tokens(tokens); self.delimiter.surround(tokens, self.tokens.clone()); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/macros.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/macros.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/macros.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/macros.rs 2006-07-24 01:21:28.000000000 +0000 @@ -61,6 +61,9 @@ $(#[$enum_attr])* $pub $enum $name $body ast_enum_of_structs_impl!($name $body); + + #[cfg(feature = "printing")] + generate_to_tokens!(() tokens $name $body); }; } @@ -70,26 +73,13 @@ $( $(#[cfg $cfg_attr:tt])* $(#[doc $($doc_attr:tt)*])* - $variant:ident $( ($($member:ident)::+) )*, + $variant:ident $( ($member:ident) )*, )* } ) => { $($( - ast_enum_from_struct!($name::$variant, $($member)::+); + ast_enum_from_struct!($name::$variant, $member); )*)* - - #[cfg(feature = "printing")] - generate_to_tokens! { - () - tokens - $name { - $( - $(#[cfg $cfg_attr])* - $(#[doc $($doc_attr)*])* - $variant $($($member)::+)*, - )* - } - } }; } @@ -126,7 +116,7 @@ ($($arms:tt)*) $tokens:ident $name:ident { $(#[cfg $cfg_attr:tt])* $(#[doc $($doc_attr:tt)*])* - $variant:ident $member:ident, + $variant:ident($member:ident), $($next:tt)* } ) => { @@ -137,7 +127,7 @@ }; (($($arms:tt)*) $tokens:ident $name:ident {}) => { - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ::quote::ToTokens for $name { fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) { match self { @@ -174,3 +164,19 @@ (pub pub) => {}; (struct struct) => {}; } + +#[cfg(any(feature = "full", feature = "derive"))] +macro_rules! return_impl_trait { + ( + $(#[$attr:meta])* + $vis:vis fn $name:ident $args:tt -> $impl_trait:ty [$concrete:ty] $body:block + ) => { + #[cfg(not(docsrs))] + $(#[$attr])* + $vis fn $name $args -> $concrete $body + + #[cfg(docsrs)] + $(#[$attr])* + $vis fn $name $args -> $impl_trait $body + }; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/op.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/op.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/op.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/op.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,6 @@ ast_enum! { /// A binary operator: `+`, `+=`, `&`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum BinOp { /// The `+` operator (addition) @@ -64,7 +64,7 @@ ast_enum! { /// A unary operator: `*`, `!`, `-`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum UnOp { /// The `*` operator for dereferencing @@ -82,7 +82,7 @@ use crate::op::{BinOp, UnOp}; use crate::parse::{Parse, ParseStream}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BinOp { fn parse(input: ParseStream) -> Result { if input.peek(Token![+=]) { @@ -147,7 +147,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for UnOp { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); @@ -170,7 +170,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BinOp { fn to_tokens(&self, tokens: &mut TokenStream) { match self { @@ -206,7 +206,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UnOp { fn to_tokens(&self, tokens: &mut TokenStream) { match self { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -197,11 +197,12 @@ use std::marker::PhantomData; use std::mem; use std::ops::Deref; +use std::panic::{RefUnwindSafe, UnwindSafe}; use std::rc::Rc; use std::str::FromStr; pub use crate::error::{Error, Result}; -pub use crate::lookahead::{Lookahead1, Peek}; +pub use crate::lookahead::{End, Lookahead1, Peek}; /// Parsing interface implemented by all types that can be parsed in a default /// way from a token stream. @@ -262,10 +263,11 @@ impl<'a> Drop for ParseBuffer<'a> { fn drop(&mut self) { - if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(self.cursor()) { + if let Some((unexpected_span, delimiter)) = span_of_unexpected_ignoring_nones(self.cursor()) + { let (inner, old_span) = inner_unexpected(self); if old_span.is_none() { - inner.set(Unexpected::Some(unexpected_span)); + inner.set(Unexpected::Some(unexpected_span, delimiter)); } } } @@ -283,6 +285,9 @@ } } +impl<'a> UnwindSafe for ParseBuffer<'a> {} +impl<'a> RefUnwindSafe for ParseBuffer<'a> {} + /// Cursor state associated with speculative parsing. /// /// This type is the input of the closure provided to [`ParseStream::step`]. @@ -393,7 +398,7 @@ pub(crate) enum Unexpected { None, - Some(Span), + Some(Span, Delimiter), Chain(Rc>), } @@ -407,7 +412,7 @@ fn clone(&self) -> Self { match self { Unexpected::None => Unexpected::None, - Unexpected::Some(span) => Unexpected::Some(*span), + Unexpected::Some(span, delimiter) => Unexpected::Some(*span, *delimiter), Unexpected::Chain(next) => Unexpected::Chain(next.clone()), } } @@ -422,12 +427,12 @@ ret } -fn inner_unexpected(buffer: &ParseBuffer) -> (Rc>, Option) { +fn inner_unexpected(buffer: &ParseBuffer) -> (Rc>, Option<(Span, Delimiter)>) { let mut unexpected = get_unexpected(buffer); loop { match cell_clone(&unexpected) { Unexpected::None => return (unexpected, None), - Unexpected::Some(span) => return (unexpected, Some(span)), + Unexpected::Some(span, delimiter) => return (unexpected, Some((span, delimiter))), Unexpected::Chain(next) => unexpected = next, } } @@ -437,7 +442,7 @@ cell_clone(&buffer.unexpected).unwrap() } -fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option { +fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option<(Span, Delimiter)> { if cursor.eof() { return None; } @@ -450,7 +455,7 @@ if cursor.eof() { None } else { - Some(cursor.span()) + Some((cursor.span(), cursor.scope_delimiter())) } } @@ -497,7 +502,7 @@ /// } /// } /// ``` - pub fn call(&self, function: fn(ParseStream) -> Result) -> Result { + pub fn call(&'a self, function: fn(ParseStream<'a>) -> Result) -> Result { function(self) } @@ -727,8 +732,8 @@ /// } /// ``` pub fn parse_terminated( - &self, - parser: fn(ParseStream) -> Result, + &'a self, + parser: fn(ParseStream<'a>) -> Result, separator: P, ) -> Result> where @@ -739,10 +744,17 @@ Punctuated::parse_terminated_with(self, parser) } - /// Returns whether there are tokens remaining in this stream. + /// Returns whether there are no more tokens remaining to be parsed from + /// this stream. /// - /// This method returns true at the end of the content of a set of - /// delimiters, as well as at the very end of the complete macro input. + /// This method returns true upon reaching the end of the content within a + /// set of delimiters, as well as at the end of the tokens provided to the + /// outermost parsing entry point. + /// + /// This is equivalent to + /// .peek(syn::parse::End). + /// Use `.peek2(End)` or `.peek3(End)` to look for the end of a parse stream + /// further ahead than the current position. /// /// # Example /// @@ -1144,20 +1156,20 @@ fn check_unexpected(&self) -> Result<()> { match inner_unexpected(self).1 { - Some(span) => Err(Error::new(span, "unexpected token")), + Some((span, delimiter)) => Err(err_unexpected_token(span, delimiter)), None => Ok(()), } } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Box { fn parse(input: ParseStream) -> Result { input.parse().map(Box::new) } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if T::peek(input.cursor()) { @@ -1168,14 +1180,14 @@ } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TokenStream { fn parse(input: ParseStream) -> Result { input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty()))) } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TokenTree { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.token_tree() { @@ -1185,7 +1197,7 @@ } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Group { fn parse(input: ParseStream) -> Result { input.step(|cursor| { @@ -1199,7 +1211,7 @@ } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Punct { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.punct() { @@ -1209,7 +1221,7 @@ } } -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Literal { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.literal() { @@ -1229,24 +1241,24 @@ /// Parse a proc-macro2 token stream into the chosen syntax tree node. /// - /// This function will check that the input is fully parsed. If there are - /// any unparsed tokens at the end of the stream, an error is returned. + /// This function enforces that the input is fully parsed. If there are any + /// unparsed tokens at the end of the stream, an error is returned. fn parse2(self, tokens: TokenStream) -> Result; /// Parse tokens of source code into the chosen syntax tree node. /// - /// This function will check that the input is fully parsed. If there are - /// any unparsed tokens at the end of the stream, an error is returned. + /// This function enforces that the input is fully parsed. If there are any + /// unparsed tokens at the end of the stream, an error is returned. #[cfg(feature = "proc-macro")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))] + #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] fn parse(self, tokens: proc_macro::TokenStream) -> Result { self.parse2(proc_macro2::TokenStream::from(tokens)) } /// Parse a string of Rust code into the chosen syntax tree node. /// - /// This function will check that the input is fully parsed. If there are - /// any unparsed tokens at the end of the string, an error is returned. + /// This function enforces that the input is fully parsed. If there are any + /// unparsed tokens at the end of the string, an error is returned. /// /// # Hygiene /// @@ -1282,8 +1294,10 @@ let state = tokens_to_parse_buffer(&buf); let node = self(&state)?; state.check_unexpected()?; - if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { - Err(Error::new(unexpected_span, "unexpected token")) + if let Some((unexpected_span, delimiter)) = + span_of_unexpected_ignoring_nones(state.cursor()) + { + Err(err_unexpected_token(unexpected_span, delimiter)) } else { Ok(node) } @@ -1296,8 +1310,10 @@ let state = new_parse_buffer(scope, cursor, unexpected); let node = self(&state)?; state.check_unexpected()?; - if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { - Err(Error::new(unexpected_span, "unexpected token")) + if let Some((unexpected_span, delimiter)) = + span_of_unexpected_ignoring_nones(state.cursor()) + { + Err(err_unexpected_token(unexpected_span, delimiter)) } else { Ok(node) } @@ -1308,6 +1324,16 @@ f.__parse_scoped(scope, tokens) } +fn err_unexpected_token(span: Span, delimiter: Delimiter) -> Error { + let msg = match delimiter { + Delimiter::Parenthesis => "unexpected token, expected `)`", + Delimiter::Brace => "unexpected token, expected `}`", + Delimiter::Bracket => "unexpected token, expected `]`", + Delimiter::None => "unexpected token", + }; + Error::new(span, msg) +} + /// An empty syntax tree node that consumes no tokens when parsed. /// /// This is useful for attribute macros that want to ensure they are not @@ -1347,7 +1373,7 @@ } #[cfg(feature = "printing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Nothing { fn to_tokens(&self, tokens: &mut TokenStream) { let _ = tokens; @@ -1355,7 +1381,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Nothing { fn clone(&self) -> Self { *self @@ -1363,11 +1389,11 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Nothing {} #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Nothing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Nothing") @@ -1375,11 +1401,11 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for Nothing {} #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Nothing { fn eq(&self, _other: &Self) -> bool { true @@ -1387,7 +1413,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Nothing { fn hash(&self, _state: &mut H) {} } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse_macro_input.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_macro_input.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse_macro_input.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_macro_input.rs 2006-07-24 01:21:28.000000000 +0000 @@ -104,7 +104,7 @@ /// # } /// ``` #[macro_export] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] macro_rules! parse_macro_input { ($tokenstream:ident as $ty:ty) => { match $crate::parse::<$ty>($tokenstream) { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse_quote.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_quote.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/parse_quote.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/parse_quote.rs 2006-07-24 01:21:28.000000000 +0000 @@ -53,18 +53,29 @@ /// /// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]` /// or inner like `#![...]` +/// - [`Vec`] — parses multiple attributes, including mixed kinds in +/// any order /// - [`Punctuated`] — parses zero or more `T` separated by punctuation /// `P` with optional trailing punctuation +/// - [`Vec`] — parses arms separated by optional commas according to the +/// same grammar as the inside of a `match` expression /// - [`Vec`] — parses the same as `Block::parse_within` +/// - [`Pat`], [`Box`] — parses the same as +/// `Pat::parse_multi_with_leading_vert` +/// - [`Field`] — parses a named or unnamed struct field /// +/// [`Vec`]: Attribute +/// [`Vec`]: Arm /// [`Vec`]: Block::parse_within +/// [`Pat`]: Pat::parse_multi_with_leading_vert +/// [`Box`]: Pat::parse_multi_with_leading_vert /// /// # Panics /// /// Panics if the tokens fail to parse as the expected syntax tree type. The /// caller is responsible for ensuring that the input tokens are syntactically /// valid. -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] #[macro_export] macro_rules! parse_quote { ($($tt:tt)*) => { @@ -96,7 +107,7 @@ /// }; /// } /// ``` -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] #[macro_export] macro_rules! parse_quote_spanned { ($span:expr=> $($tt:tt)*) => { @@ -113,6 +124,7 @@ // Not public API. #[doc(hidden)] +#[track_caller] pub fn parse(token_stream: TokenStream) -> T { let parser = T::parse; match parser.parse2(token_stream) { @@ -139,7 +151,7 @@ #[cfg(any(feature = "full", feature = "derive"))] use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility}; #[cfg(feature = "full")] -use crate::{Block, Pat, Stmt}; +use crate::{Arm, Block, Pat, Stmt}; #[cfg(any(feature = "full", feature = "derive"))] impl ParseQuote for Attribute { @@ -153,6 +165,17 @@ } #[cfg(any(feature = "full", feature = "derive"))] +impl ParseQuote for Vec { + fn parse(input: ParseStream) -> Result { + let mut attrs = Vec::new(); + while !input.is_empty() { + attrs.push(ParseQuote::parse(input)?); + } + Ok(attrs) + } +} + +#[cfg(any(feature = "full", feature = "derive"))] impl ParseQuote for Field { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; @@ -208,3 +231,10 @@ Block::parse_within(input) } } + +#[cfg(feature = "full")] +impl ParseQuote for Vec { + fn parse(input: ParseStream) -> Result { + Arm::parse_multiple(input) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/pat.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/pat.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/pat.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/pat.rs 2006-07-24 01:21:28.000000000 +0000 @@ -21,7 +21,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Pat { /// A const block: `const { ... }`. @@ -106,7 +106,7 @@ /// /// It may also be a unit struct or struct variant (e.g. `None`), or a /// constant; these cannot be distinguished syntactically. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatIdent { pub attrs: Vec, pub by_ref: Option, @@ -118,7 +118,7 @@ ast_struct! { /// A pattern that matches any one of a set of cases. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatOr { pub attrs: Vec, pub leading_vert: Option, @@ -128,7 +128,7 @@ ast_struct! { /// A parenthesized pattern: `(A | B)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatParen { pub attrs: Vec, pub paren_token: token::Paren, @@ -138,7 +138,7 @@ ast_struct! { /// A reference pattern: `&mut var`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatReference { pub attrs: Vec, pub and_token: Token![&], @@ -149,7 +149,7 @@ ast_struct! { /// The dots in a tuple or slice pattern: `[0, 1, ..]`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatRest { pub attrs: Vec, pub dot2_token: Token![..], @@ -158,7 +158,7 @@ ast_struct! { /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatSlice { pub attrs: Vec, pub bracket_token: token::Bracket, @@ -168,7 +168,7 @@ ast_struct! { /// A struct or struct variant pattern: `Variant { x, y, .. }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatStruct { pub attrs: Vec, pub qself: Option, @@ -181,7 +181,7 @@ ast_struct! { /// A tuple pattern: `(a, b)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTuple { pub attrs: Vec, pub paren_token: token::Paren, @@ -191,7 +191,7 @@ ast_struct! { /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTupleStruct { pub attrs: Vec, pub qself: Option, @@ -203,7 +203,7 @@ ast_struct! { /// A type ascription pattern: `foo: f64`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatType { pub attrs: Vec, pub pat: Box, @@ -214,7 +214,7 @@ ast_struct! { /// A pattern that matches any value: `_`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatWild { pub attrs: Vec, pub underscore_token: Token![_], @@ -226,7 +226,7 @@ /// /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct FieldPat { pub attrs: Vec, pub member: Member, @@ -258,7 +258,7 @@ use crate::verbatim; use proc_macro2::TokenStream; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Pat { /// Parse a pattern that does _not_ involve `|` at the top level. /// @@ -382,7 +382,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PatType { fn parse(input: ParseStream) -> Result { Ok(PatType { @@ -417,7 +417,8 @@ } fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result { - let (qself, path) = path::parsing::qpath(input, true)?; + let expr_style = true; + let (qself, path) = path::parsing::qpath(input, expr_style)?; if qself.is_none() && input.peek(Token![!]) @@ -470,7 +471,13 @@ attrs: Vec::new(), by_ref: input.parse()?, mutability: input.parse()?, - ident: input.call(Ident::parse_any)?, + ident: { + if input.peek(Token![self]) { + input.call(Ident::parse_any)? + } else { + input.parse()? + } + }, subpat: { if input.peek(Token![@]) { let at_token: Token![@] = input.parse()?; @@ -805,10 +812,11 @@ PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path; + use crate::path::printing::PathStyle; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatIdent { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -822,7 +830,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatOr { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -831,7 +839,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatParen { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -841,7 +849,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatReference { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -851,7 +859,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatRest { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -859,7 +867,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatSlice { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -869,11 +877,11 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); - path::printing::print_path(tokens, &self.qself, &self.path); + path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); self.brace_token.surround(tokens, |tokens| { self.fields.to_tokens(tokens); // NOTE: We need a comma before the dot2 token if it is present. @@ -885,7 +893,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTuple { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -904,18 +912,18 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTupleStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); - path::printing::print_path(tokens, &self.qself, &self.path); + path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); }); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -925,7 +933,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatWild { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -933,7 +941,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldPat { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/path.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/path.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,7 +10,7 @@ ast_struct! { /// A path at which a named item is exported (e.g. `std::collections::HashMap`). - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Path { pub leading_colon: Option, pub segments: Punctuated, @@ -92,7 +92,7 @@ /// An error if this path is not a single ident, as defined in `get_ident`. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_ident(&self) -> Result<&Ident> { self.get_ident().ok_or_else(|| { crate::error::new2( @@ -106,7 +106,7 @@ ast_struct! { /// A segment of a path together with any path arguments on that segment. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PathSegment { pub ident: Ident, pub arguments: PathArguments, @@ -135,7 +135,7 @@ /// ## Parenthesized /// /// The `(A, B) -> C` in `Fn(A, B) -> C`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum PathArguments { None, /// The `<'a, T>` in `std::slice::iter<'a, T>`. @@ -170,7 +170,7 @@ ast_enum! { /// An individual generic argument, like `'a`, `T`, or `Item = T`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum GenericArgument { /// A lifetime argument. @@ -196,7 +196,7 @@ ast_struct! { /// Angle bracketed arguments of a path segment: the `` in `HashMap`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AngleBracketedGenericArguments { pub colon2_token: Option, pub lt_token: Token![<], @@ -208,7 +208,7 @@ ast_struct! { /// A binding (equality constraint) on an associated type: the `Item = u8` /// in `Iterator`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AssocType { pub ident: Ident, pub generics: Option, @@ -220,7 +220,7 @@ ast_struct! { /// An equality constraint on an associated constant: the `PANIC = false` in /// `Trait`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AssocConst { pub ident: Ident, pub generics: Option, @@ -231,7 +231,7 @@ ast_struct! { /// An associated type bound: `Iterator`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Constraint { pub ident: Ident, pub generics: Option, @@ -243,7 +243,7 @@ ast_struct! { /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) -> /// C`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ParenthesizedGenericArguments { pub paren_token: token::Paren, /// `(A, B)` @@ -270,7 +270,7 @@ /// ^~~~~~ ^ /// ty position = 0 /// ``` - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct QSelf { pub lt_token: Token![<], pub ty: Box, @@ -305,14 +305,14 @@ #[cfg(not(feature = "full"))] use crate::verbatim; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Path { fn parse(input: ParseStream) -> Result { Self::parse_helper(input, false) } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for GenericArgument { fn parse(input: ParseStream) -> Result { if input.peek(Lifetime) && !input.peek2(Token![+]) { @@ -377,8 +377,15 @@ if input.peek(Token![,]) || input.peek(Token![>]) { break; } - let value: TypeParamBound = input.parse()?; - bounds.push_value(value); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = true; + TypeParamBound::parse_single( + input, + allow_precise_capture, + allow_const, + )? + }); if !input.peek(Token![+]) { break; } @@ -443,7 +450,7 @@ /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments` /// parses optional leading `::`. #[cfg(feature = "full")] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "full"))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] pub fn parse_turbofish(input: ParseStream) -> Result { let colon2_token: Token![::] = input.parse()?; Self::do_parse(Some(colon2_token), input) @@ -477,7 +484,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for AngleBracketedGenericArguments { fn parse(input: ParseStream) -> Result { let colon2_token: Option = input.parse()?; @@ -485,7 +492,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ParenthesizedGenericArguments { fn parse(input: ParseStream) -> Result { let content; @@ -497,7 +504,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PathSegment { fn parse(input: ParseStream) -> Result { Self::parse_helper(input, false) @@ -521,7 +528,10 @@ input.parse()? }; - if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=]) + if !expr_style + && input.peek(Token![<]) + && !input.peek(Token![<=]) + && !input.peek(Token![<<=]) || input.peek(Token![::]) && input.peek3(Token![<]) { Ok(PathSegment { @@ -565,7 +575,7 @@ /// } /// } /// ``` - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_mod_style(input: ParseStream) -> Result { Ok(Path { leading_colon: input.parse()?, @@ -688,7 +698,7 @@ #[cfg(feature = "printing")] pub(crate) mod printing { - use crate::expr::Expr; + use crate::generics; use crate::path::{ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument, ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, @@ -696,74 +706,82 @@ use crate::print::TokensOrDefault; #[cfg(feature = "parsing")] use crate::spanned::Spanned; - use crate::token; #[cfg(feature = "parsing")] use proc_macro2::Span; use proc_macro2::TokenStream; use quote::ToTokens; use std::cmp; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + pub(crate) enum PathStyle { + Expr, + Mod, + AsWritten, + } + + impl Copy for PathStyle {} + + impl Clone for PathStyle { + fn clone(&self) -> Self { + *self + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Path { fn to_tokens(&self, tokens: &mut TokenStream) { - self.leading_colon.to_tokens(tokens); - self.segments.to_tokens(tokens); + print_path(tokens, self, PathStyle::AsWritten); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + pub(crate) fn print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle) { + path.leading_colon.to_tokens(tokens); + for segment in path.segments.pairs() { + print_path_segment(tokens, segment.value(), style); + segment.punct().to_tokens(tokens); + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PathSegment { fn to_tokens(&self, tokens: &mut TokenStream) { - self.ident.to_tokens(tokens); - self.arguments.to_tokens(tokens); + print_path_segment(tokens, self, PathStyle::AsWritten); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + fn print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle) { + segment.ident.to_tokens(tokens); + print_path_arguments(tokens, &segment.arguments, style); + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PathArguments { fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - PathArguments::None => {} - PathArguments::AngleBracketed(arguments) => { - arguments.to_tokens(tokens); - } - PathArguments::Parenthesized(arguments) => { - arguments.to_tokens(tokens); - } + print_path_arguments(tokens, self, PathStyle::AsWritten); + } + } + + fn print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle) { + match arguments { + PathArguments::None => {} + PathArguments::AngleBracketed(arguments) => { + print_angle_bracketed_generic_arguments(tokens, arguments, style); + } + PathArguments::Parenthesized(arguments) => { + print_parenthesized_generic_arguments(tokens, arguments, style); } } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for GenericArgument { #[allow(clippy::match_same_arms)] fn to_tokens(&self, tokens: &mut TokenStream) { match self { GenericArgument::Lifetime(lt) => lt.to_tokens(tokens), GenericArgument::Type(ty) => ty.to_tokens(tokens), - GenericArgument::Const(expr) => match expr { - Expr::Lit(expr) => expr.to_tokens(tokens), - - Expr::Path(expr) - if expr.attrs.is_empty() - && expr.qself.is_none() - && expr.path.get_ident().is_some() => - { - expr.to_tokens(tokens); - } - - #[cfg(feature = "full")] - Expr::Block(expr) => expr.to_tokens(tokens), - - #[cfg(not(feature = "full"))] - Expr::Verbatim(expr) => expr.to_tokens(tokens), - - // ERROR CORRECTION: Add braces to make sure that the - // generated code is valid. - _ => token::Brace::default().surround(tokens, |tokens| { - expr.to_tokens(tokens); - }), - }, + GenericArgument::Const(expr) => { + generics::printing::print_const_argument(expr, tokens); + } GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens), GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens), GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens), @@ -771,50 +789,62 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AngleBracketedGenericArguments { fn to_tokens(&self, tokens: &mut TokenStream) { - self.colon2_token.to_tokens(tokens); - self.lt_token.to_tokens(tokens); + print_angle_bracketed_generic_arguments(tokens, self, PathStyle::AsWritten); + } + } - // Print lifetimes before types/consts/bindings, regardless of their - // order in self.args. - let mut trailing_or_empty = true; - for param in self.args.pairs() { - match param.value() { - GenericArgument::Lifetime(_) => { - param.to_tokens(tokens); - trailing_or_empty = param.punct().is_some(); - } - GenericArgument::Type(_) - | GenericArgument::Const(_) - | GenericArgument::AssocType(_) - | GenericArgument::AssocConst(_) - | GenericArgument::Constraint(_) => {} + pub(crate) fn print_angle_bracketed_generic_arguments( + tokens: &mut TokenStream, + arguments: &AngleBracketedGenericArguments, + style: PathStyle, + ) { + if let PathStyle::Mod = style { + return; + } + + conditionally_print_turbofish(tokens, &arguments.colon2_token, style); + arguments.lt_token.to_tokens(tokens); + + // Print lifetimes before types/consts/bindings, regardless of their + // order in args. + let mut trailing_or_empty = true; + for param in arguments.args.pairs() { + match param.value() { + GenericArgument::Lifetime(_) => { + param.to_tokens(tokens); + trailing_or_empty = param.punct().is_some(); } - } - for param in self.args.pairs() { - match param.value() { - GenericArgument::Type(_) - | GenericArgument::Const(_) - | GenericArgument::AssocType(_) - | GenericArgument::AssocConst(_) - | GenericArgument::Constraint(_) => { - if !trailing_or_empty { - ::default().to_tokens(tokens); - } - param.to_tokens(tokens); - trailing_or_empty = param.punct().is_some(); + GenericArgument::Type(_) + | GenericArgument::Const(_) + | GenericArgument::AssocType(_) + | GenericArgument::AssocConst(_) + | GenericArgument::Constraint(_) => {} + } + } + for param in arguments.args.pairs() { + match param.value() { + GenericArgument::Type(_) + | GenericArgument::Const(_) + | GenericArgument::AssocType(_) + | GenericArgument::AssocConst(_) + | GenericArgument::Constraint(_) => { + if !trailing_or_empty { + ::default().to_tokens(tokens); } - GenericArgument::Lifetime(_) => {} + param.to_tokens(tokens); + trailing_or_empty = param.punct().is_some(); } + GenericArgument::Lifetime(_) => {} } - - self.gt_token.to_tokens(tokens); } + + arguments.gt_token.to_tokens(tokens); } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AssocType { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); @@ -824,17 +854,17 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AssocConst { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.eq_token.to_tokens(tokens); - self.value.to_tokens(tokens); + generics::printing::print_const_argument(&self.value, tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Constraint { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); @@ -844,21 +874,39 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ParenthesizedGenericArguments { fn to_tokens(&self, tokens: &mut TokenStream) { - self.paren_token.surround(tokens, |tokens| { - self.inputs.to_tokens(tokens); - }); - self.output.to_tokens(tokens); + print_parenthesized_generic_arguments(tokens, self, PathStyle::AsWritten); + } + } + + fn print_parenthesized_generic_arguments( + tokens: &mut TokenStream, + arguments: &ParenthesizedGenericArguments, + style: PathStyle, + ) { + if let PathStyle::Mod = style { + return; } + + conditionally_print_turbofish(tokens, &None, style); + arguments.paren_token.surround(tokens, |tokens| { + arguments.inputs.to_tokens(tokens); + }); + arguments.output.to_tokens(tokens); } - pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option, path: &Path) { + pub(crate) fn print_qpath( + tokens: &mut TokenStream, + qself: &Option, + path: &Path, + style: PathStyle, + ) { let qself = match qself { Some(qself) => qself, None => { - path.to_tokens(tokens); + print_path(tokens, path, style); return; } }; @@ -871,25 +919,36 @@ TokensOrDefault(&qself.as_token).to_tokens(tokens); path.leading_colon.to_tokens(tokens); for (i, segment) in segments.by_ref().take(pos).enumerate() { + print_path_segment(tokens, segment.value(), PathStyle::AsWritten); if i + 1 == pos { - segment.value().to_tokens(tokens); qself.gt_token.to_tokens(tokens); - segment.punct().to_tokens(tokens); - } else { - segment.to_tokens(tokens); } + segment.punct().to_tokens(tokens); } } else { qself.gt_token.to_tokens(tokens); path.leading_colon.to_tokens(tokens); } for segment in segments { - segment.to_tokens(tokens); + print_path_segment(tokens, segment.value(), style); + segment.punct().to_tokens(tokens); + } + } + + fn conditionally_print_turbofish( + tokens: &mut TokenStream, + colon2_token: &Option, + style: PathStyle, + ) { + match style { + PathStyle::Expr => TokensOrDefault(colon2_token).to_tokens(tokens), + PathStyle::Mod => unreachable!(), + PathStyle::AsWritten => colon2_token.to_tokens(tokens), } } #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] impl Spanned for QSelf { fn span(&self) -> Span { struct QSelfDelimiters<'a>(&'a QSelf); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/precedence.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/precedence.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/precedence.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/precedence.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,210 @@ +#[cfg(all(feature = "printing", feature = "full"))] +use crate::attr::{AttrStyle, Attribute}; +#[cfg(feature = "printing")] +use crate::expr::Expr; +#[cfg(all(feature = "printing", feature = "full"))] +use crate::expr::{ + ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprCall, ExprConst, ExprContinue, + ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLit, ExprLoop, ExprMacro, + ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, ExprReturn, ExprStruct, ExprTry, + ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield, +}; +use crate::op::BinOp; +#[cfg(all(feature = "printing", feature = "full"))] +use crate::ty::ReturnType; +use std::cmp::Ordering; + +// Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence +pub(crate) enum Precedence { + // return, break, closures + Jump, + // = += -= *= /= %= &= |= ^= <<= >>= + Assign, + // .. ..= + Range, + // || + Or, + // && + And, + // let + #[cfg(feature = "printing")] + Let, + // == != < > <= >= + Compare, + // | + BitOr, + // ^ + BitXor, + // & + BitAnd, + // << >> + Shift, + // + - + Sum, + // * / % + Product, + // as + Cast, + // unary - * ! & &mut + #[cfg(feature = "printing")] + Prefix, + // paths, loops, function calls, array indexing, field expressions, method calls + #[cfg(feature = "printing")] + Unambiguous, +} + +impl Precedence { + pub(crate) const MIN: Self = Precedence::Jump; + + pub(crate) fn of_binop(op: &BinOp) -> Self { + match op { + BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum, + BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product, + BinOp::And(_) => Precedence::And, + BinOp::Or(_) => Precedence::Or, + BinOp::BitXor(_) => Precedence::BitXor, + BinOp::BitAnd(_) => Precedence::BitAnd, + BinOp::BitOr(_) => Precedence::BitOr, + BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, + + BinOp::Eq(_) + | BinOp::Lt(_) + | BinOp::Le(_) + | BinOp::Ne(_) + | BinOp::Ge(_) + | BinOp::Gt(_) => Precedence::Compare, + + BinOp::AddAssign(_) + | BinOp::SubAssign(_) + | BinOp::MulAssign(_) + | BinOp::DivAssign(_) + | BinOp::RemAssign(_) + | BinOp::BitXorAssign(_) + | BinOp::BitAndAssign(_) + | BinOp::BitOrAssign(_) + | BinOp::ShlAssign(_) + | BinOp::ShrAssign(_) => Precedence::Assign, + } + } + + #[cfg(feature = "printing")] + pub(crate) fn of(e: &Expr) -> Self { + #[cfg(feature = "full")] + fn prefix_attrs(attrs: &[Attribute]) -> Precedence { + for attr in attrs { + if let AttrStyle::Outer = attr.style { + return Precedence::Prefix; + } + } + Precedence::Unambiguous + } + + match e { + #[cfg(feature = "full")] + Expr::Closure(e) => match e.output { + ReturnType::Default => Precedence::Jump, + ReturnType::Type(..) => prefix_attrs(&e.attrs), + }, + + #[cfg(feature = "full")] + Expr::Break(ExprBreak { expr, .. }) + | Expr::Return(ExprReturn { expr, .. }) + | Expr::Yield(ExprYield { expr, .. }) => match expr { + Some(_) => Precedence::Jump, + None => Precedence::Unambiguous, + }, + + Expr::Assign(_) => Precedence::Assign, + Expr::Range(_) => Precedence::Range, + Expr::Binary(e) => Precedence::of_binop(&e.op), + Expr::Let(_) => Precedence::Let, + Expr::Cast(_) => Precedence::Cast, + Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, + + #[cfg(feature = "full")] + Expr::Array(ExprArray { attrs, .. }) + | Expr::Async(ExprAsync { attrs, .. }) + | Expr::Await(ExprAwait { attrs, .. }) + | Expr::Block(ExprBlock { attrs, .. }) + | Expr::Call(ExprCall { attrs, .. }) + | Expr::Const(ExprConst { attrs, .. }) + | Expr::Continue(ExprContinue { attrs, .. }) + | Expr::Field(ExprField { attrs, .. }) + | Expr::ForLoop(ExprForLoop { attrs, .. }) + | Expr::Group(ExprGroup { attrs, .. }) + | Expr::If(ExprIf { attrs, .. }) + | Expr::Index(ExprIndex { attrs, .. }) + | Expr::Infer(ExprInfer { attrs, .. }) + | Expr::Lit(ExprLit { attrs, .. }) + | Expr::Loop(ExprLoop { attrs, .. }) + | Expr::Macro(ExprMacro { attrs, .. }) + | Expr::Match(ExprMatch { attrs, .. }) + | Expr::MethodCall(ExprMethodCall { attrs, .. }) + | Expr::Paren(ExprParen { attrs, .. }) + | Expr::Path(ExprPath { attrs, .. }) + | Expr::Repeat(ExprRepeat { attrs, .. }) + | Expr::Struct(ExprStruct { attrs, .. }) + | Expr::Try(ExprTry { attrs, .. }) + | Expr::TryBlock(ExprTryBlock { attrs, .. }) + | Expr::Tuple(ExprTuple { attrs, .. }) + | Expr::Unsafe(ExprUnsafe { attrs, .. }) + | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs), + + #[cfg(not(feature = "full"))] + Expr::Array(_) + | Expr::Async(_) + | Expr::Await(_) + | Expr::Block(_) + | Expr::Call(_) + | Expr::Const(_) + | Expr::Continue(_) + | Expr::Field(_) + | Expr::ForLoop(_) + | Expr::Group(_) + | Expr::If(_) + | Expr::Index(_) + | Expr::Infer(_) + | Expr::Lit(_) + | Expr::Loop(_) + | Expr::Macro(_) + | Expr::Match(_) + | Expr::MethodCall(_) + | Expr::Paren(_) + | Expr::Path(_) + | Expr::Repeat(_) + | Expr::Struct(_) + | Expr::Try(_) + | Expr::TryBlock(_) + | Expr::Tuple(_) + | Expr::Unsafe(_) + | Expr::While(_) => Precedence::Unambiguous, + + Expr::Verbatim(_) => Precedence::Unambiguous, + + #[cfg(not(feature = "full"))] + Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => unreachable!(), + } + } +} + +impl Copy for Precedence {} + +impl Clone for Precedence { + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for Precedence { + fn eq(&self, other: &Self) -> bool { + *self as u8 == *other as u8 + } +} + +impl PartialOrd for Precedence { + fn partial_cmp(&self, other: &Self) -> Option { + let this = *self as u8; + let other = *other as u8; + Some(this.cmp(&other)) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/punctuated.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/punctuated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/punctuated.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/punctuated.rs 2006-07-24 01:21:28.000000000 +0000 @@ -27,6 +27,8 @@ use crate::parse::{Parse, ParseStream}; #[cfg(feature = "parsing")] use crate::token::Token; +#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))] +use std::collections::VecDeque; #[cfg(feature = "extra-traits")] use std::fmt::{self, Debug}; #[cfg(feature = "extra-traits")] @@ -92,6 +94,29 @@ self.iter_mut().next_back() } + /// Borrows the element at the given index. + pub fn get(&self, index: usize) -> Option<&T> { + if let Some((value, _punct)) = self.inner.get(index) { + Some(value) + } else if index == self.inner.len() { + self.last.as_deref() + } else { + None + } + } + + /// Mutably borrows the element at the given index. + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + let inner_len = self.inner.len(); + if let Some((value, _punct)) = self.inner.get_mut(index) { + Some(value) + } else if index == inner_len { + self.last.as_deref_mut() + } else { + None + } + } + /// Returns an iterator over borrowed syntax tree nodes of type `&T`. pub fn iter(&self) -> Iter { Iter { @@ -263,7 +288,7 @@ /// Parsing continues until the end of this parse stream. The entire content /// of this parse stream must consist of `T` and `P`. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_terminated(input: ParseStream) -> Result where T: Parse, @@ -281,10 +306,10 @@ /// /// [`parse_terminated`]: Punctuated::parse_terminated #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] - pub fn parse_terminated_with( - input: ParseStream, - parser: fn(ParseStream) -> Result, + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + pub fn parse_terminated_with<'a>( + input: ParseStream<'a>, + parser: fn(ParseStream<'a>) -> Result, ) -> Result where P: Parse, @@ -315,7 +340,7 @@ /// is not followed by a `P`, even if there are remaining tokens in the /// stream. #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_separated_nonempty(input: ParseStream) -> Result where T: Parse, @@ -333,10 +358,10 @@ /// /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] - pub fn parse_separated_nonempty_with( - input: ParseStream, - parser: fn(ParseStream) -> Result, + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + pub fn parse_separated_nonempty_with<'a>( + input: ParseStream<'a>, + parser: fn(ParseStream<'a>) -> Result, ) -> Result where P: Token + Parse, @@ -358,7 +383,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Punctuated where T: Clone, @@ -378,7 +403,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for Punctuated where T: Eq, @@ -387,7 +412,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Punctuated where T: PartialEq, @@ -400,7 +425,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Punctuated where T: Hash, @@ -414,7 +439,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Punctuated { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut list = f.debug_list(); @@ -496,8 +521,13 @@ fn into_iter(self) -> Self::IntoIter { let mut elements = Vec::with_capacity(self.len()); - elements.extend(self.inner.into_iter().map(|pair| pair.0)); - elements.extend(self.last.map(|t| *t)); + + for (t, _) in self.inner { + elements.push(t); + } + if let Some(t) = self.last { + elements.push(*t); + } IntoIter { inner: elements.into_iter(), @@ -1007,7 +1037,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Pair<&T, &P> { pub fn cloned(self) -> Pair where @@ -1022,7 +1052,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Pair where T: Clone, @@ -1037,7 +1067,7 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Pair where T: Copy, @@ -1049,7 +1079,7 @@ type Output = T; fn index(&self, index: usize) -> &Self::Output { - if index == self.len() - 1 { + if index.checked_add(1) == Some(self.len()) { match &self.last { Some(t) => t, None => &self.inner[index].0, @@ -1062,7 +1092,7 @@ impl IndexMut for Punctuated { fn index_mut(&mut self, index: usize) -> &mut Self::Output { - if index == self.len() - 1 { + if index.checked_add(1) == Some(self.len()) { match &mut self.last { Some(t) => t, None => &mut self.inner[index].0, @@ -1073,13 +1103,43 @@ } } +#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))] +pub(crate) fn fold( + punctuated: Punctuated, + fold: &mut V, + mut f: F, +) -> Punctuated +where + V: ?Sized, + F: FnMut(&mut V, T) -> T, +{ + let Punctuated { inner, last } = punctuated; + + // Convert into VecDeque to prevent needing to allocate a new Vec<(T, P)> + // for the folded elements. + let mut inner = VecDeque::from(inner); + for _ in 0..inner.len() { + if let Some((t, p)) = inner.pop_front() { + inner.push_back((f(fold, t), p)); + } + } + + Punctuated { + inner: Vec::from(inner), + last: match last { + Some(t) => Some(Box::new(f(fold, *t))), + None => None, + }, + } +} + #[cfg(feature = "printing")] mod printing { use crate::punctuated::{Pair, Punctuated}; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Punctuated where T: ToTokens, @@ -1090,7 +1150,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Pair where T: ToTokens, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/restriction.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/restriction.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/restriction.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/restriction.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,7 +10,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Visibility { /// A public visibility level: `pub`. Public(Token![pub]), @@ -27,7 +27,7 @@ ast_struct! { /// A visibility level restricted to some path: `pub(self)` or /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct VisRestricted { pub pub_token: Token![pub], pub paren_token: token::Paren, @@ -38,7 +38,7 @@ ast_enum! { /// Unused, but reserved for RFC 3323 restrictions. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum FieldMutability { None, @@ -67,7 +67,7 @@ use crate::restriction::{VisRestricted, Visibility}; use crate::token; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Visibility { fn parse(input: ParseStream) -> Result { // Recognize an empty None-delimited group, as produced by a $:vis @@ -146,11 +146,13 @@ #[cfg(feature = "printing")] mod printing { + use crate::path; + use crate::path::printing::PathStyle; use crate::restriction::{VisRestricted, Visibility}; use proc_macro2::TokenStream; use quote::ToTokens; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Visibility { fn to_tokens(&self, tokens: &mut TokenStream) { match self { @@ -161,7 +163,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for VisRestricted { fn to_tokens(&self, tokens: &mut TokenStream) { self.pub_token.to_tokens(tokens); @@ -169,7 +171,7 @@ // TODO: If we have a path which is not "self" or "super" or // "crate", automatically add the "in" token. self.in_token.to_tokens(tokens); - self.path.to_tokens(tokens); + path::printing::print_path(tokens, &self.path, PathStyle::Mod); }); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/scan_expr.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/scan_expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/scan_expr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/scan_expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,268 @@ +use self::{Action::*, Input::*}; +use proc_macro2::{Delimiter, Ident, Spacing, TokenTree}; +use syn::parse::{ParseStream, Result}; +#[allow(unused_imports)] +//#[cfg_attr(not(test), expect(unused_imports))] // Rust 1.81+ +use syn::Token; +use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Type}; + +enum Input { + Keyword(&'static str), + Punct(&'static str), + ConsumeAny, + ConsumeBinOp, + ConsumeBrace, + ConsumeDelimiter, + ConsumeIdent, + ConsumeLifetime, + ConsumeLiteral, + ConsumeNestedBrace, + ExpectPath, + ExpectTurbofish, + ExpectType, + CanBeginExpr, + Otherwise, + Empty, +} + +enum Action { + SetState(&'static [(Input, Action)]), + IncDepth, + DecDepth, + Finish, +} + +static INIT: [(Input, Action); 28] = [ + (ConsumeDelimiter, SetState(&POSTFIX)), + (Keyword("async"), SetState(&ASYNC)), + (Keyword("break"), SetState(&BREAK_LABEL)), + (Keyword("const"), SetState(&CONST)), + (Keyword("continue"), SetState(&CONTINUE)), + (Keyword("for"), SetState(&FOR)), + (Keyword("if"), IncDepth), + (Keyword("let"), SetState(&PATTERN)), + (Keyword("loop"), SetState(&BLOCK)), + (Keyword("match"), IncDepth), + (Keyword("move"), SetState(&CLOSURE)), + (Keyword("return"), SetState(&RETURN)), + (Keyword("static"), SetState(&CLOSURE)), + (Keyword("unsafe"), SetState(&BLOCK)), + (Keyword("while"), IncDepth), + (Keyword("yield"), SetState(&RETURN)), + (Keyword("_"), SetState(&POSTFIX)), + (Punct("!"), SetState(&INIT)), + (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])), + (Punct("&"), SetState(&REFERENCE)), + (Punct("*"), SetState(&INIT)), + (Punct("-"), SetState(&INIT)), + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])), + (ConsumeLiteral, SetState(&POSTFIX)), + (ExpectPath, SetState(&PATH)), +]; + +static POSTFIX: [(Input, Action); 10] = [ + (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])), + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("."), SetState(&DOT)), + (Punct("?"), SetState(&POSTFIX)), + (ConsumeBinOp, SetState(&INIT)), + (Punct("="), SetState(&INIT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (ConsumeDelimiter, SetState(&POSTFIX)), + (Empty, Finish), +]; + +static ASYNC: [(Input, Action); 3] = [ + (Keyword("move"), SetState(&ASYNC)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeBrace, SetState(&POSTFIX)), +]; + +static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))]; + +static BREAK_LABEL: [(Input, Action); 2] = [ + (ConsumeLifetime, SetState(&BREAK_VALUE)), + (Otherwise, SetState(&BREAK_VALUE)), +]; + +static BREAK_VALUE: [(Input, Action); 3] = [ + (ConsumeNestedBrace, SetState(&IF_THEN)), + (CanBeginExpr, SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +static CLOSURE: [(Input, Action); 7] = [ + (Keyword("async"), SetState(&CLOSURE)), + (Keyword("move"), SetState(&CLOSURE)), + (Punct(","), SetState(&CLOSURE)), + (Punct(">"), SetState(&CLOSURE)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeLifetime, SetState(&CLOSURE)), + (ConsumeIdent, SetState(&CLOSURE)), +]; + +static CLOSURE_ARGS: [(Input, Action); 2] = [ + (Punct("|"), SetState(&CLOSURE_RET)), + (ConsumeAny, SetState(&CLOSURE_ARGS)), +]; + +static CLOSURE_RET: [(Input, Action); 2] = [ + (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])), + (Otherwise, SetState(&INIT)), +]; + +static CONST: [(Input, Action); 2] = [ + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeBrace, SetState(&POSTFIX)), +]; + +static CONTINUE: [(Input, Action); 2] = [ + (ConsumeLifetime, SetState(&POSTFIX)), + (Otherwise, SetState(&POSTFIX)), +]; + +static DOT: [(Input, Action); 3] = [ + (Keyword("await"), SetState(&POSTFIX)), + (ConsumeIdent, SetState(&METHOD)), + (ConsumeLiteral, SetState(&POSTFIX)), +]; + +static FOR: [(Input, Action); 2] = [ + (Punct("<"), SetState(&CLOSURE)), + (Otherwise, SetState(&PATTERN)), +]; + +static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)]; +static IF_THEN: [(Input, Action); 2] = + [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)]; + +static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))]; + +static PATH: [(Input, Action); 4] = [ + (Punct("!="), SetState(&INIT)), + (Punct("!"), SetState(&INIT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (Otherwise, SetState(&POSTFIX)), +]; + +static PATTERN: [(Input, Action); 15] = [ + (ConsumeDelimiter, SetState(&PATTERN)), + (Keyword("box"), SetState(&PATTERN)), + (Keyword("in"), IncDepth), + (Keyword("mut"), SetState(&PATTERN)), + (Keyword("ref"), SetState(&PATTERN)), + (Keyword("_"), SetState(&PATTERN)), + (Punct("!"), SetState(&PATTERN)), + (Punct("&"), SetState(&PATTERN)), + (Punct("..="), SetState(&PATTERN)), + (Punct(".."), SetState(&PATTERN)), + (Punct("="), SetState(&INIT)), + (Punct("@"), SetState(&PATTERN)), + (Punct("|"), SetState(&PATTERN)), + (ConsumeLiteral, SetState(&PATTERN)), + (ExpectPath, SetState(&PATTERN)), +]; + +static RANGE: [(Input, Action); 6] = [ + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("."), SetState(&DOT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (Empty, Finish), + (Otherwise, SetState(&INIT)), +]; + +static RAW: [(Input, Action); 3] = [ + (Keyword("const"), SetState(&INIT)), + (Keyword("mut"), SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +static REFERENCE: [(Input, Action); 3] = [ + (Keyword("mut"), SetState(&INIT)), + (Keyword("raw"), SetState(&RAW)), + (Otherwise, SetState(&INIT)), +]; + +static RETURN: [(Input, Action); 2] = [ + (CanBeginExpr, SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +pub(crate) fn scan_expr(input: ParseStream) -> Result<()> { + let mut state = INIT.as_slice(); + let mut depth = 0usize; + 'table: loop { + for rule in state { + if match rule.0 { + Input::Keyword(expected) => input.step(|cursor| match cursor.ident() { + Some((ident, rest)) if ident == expected => Ok((true, rest)), + _ => Ok((false, *cursor)), + })?, + Input::Punct(expected) => input.step(|cursor| { + let begin = *cursor; + let mut cursor = begin; + for (i, ch) in expected.chars().enumerate() { + match cursor.punct() { + Some((punct, _)) if punct.as_char() != ch => break, + Some((_, rest)) if i == expected.len() - 1 => { + return Ok((true, rest)); + } + Some((punct, rest)) if punct.spacing() == Spacing::Joint => { + cursor = rest; + } + _ => break, + } + } + Ok((false, begin)) + })?, + Input::ConsumeAny => input.parse::>()?.is_some(), + Input::ConsumeBinOp => input.parse::().is_ok(), + Input::ConsumeBrace | Input::ConsumeNestedBrace => { + (matches!(rule.0, Input::ConsumeBrace) || depth > 0) + && input.step(|cursor| match cursor.group(Delimiter::Brace) { + Some((_inside, _span, rest)) => Ok((true, rest)), + None => Ok((false, *cursor)), + })? + } + Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() { + Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)), + None => Ok((false, *cursor)), + })?, + Input::ConsumeIdent => input.parse::>()?.is_some(), + Input::ConsumeLifetime => input.parse::>()?.is_some(), + Input::ConsumeLiteral => input.parse::>()?.is_some(), + Input::ExpectPath => { + input.parse::()?; + true + } + Input::ExpectTurbofish => { + if input.peek(Token![::]) { + input.parse::()?; + } + true + } + Input::ExpectType => { + Type::without_plus(input)?; + true + } + Input::CanBeginExpr => Expr::peek(input), + Input::Otherwise => true, + Input::Empty => input.is_empty() || input.peek(Token![,]), + } { + state = match rule.1 { + Action::SetState(next) => next, + Action::IncDepth => (depth += 1, &INIT).1, + Action::DecDepth => (depth -= 1, &POSTFIX).1, + Action::Finish => return if depth == 0 { Ok(()) } else { break }, + }; + continue 'table; + } + } + return Err(input.error("unsupported expression")); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/stmt.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/stmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/stmt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/stmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -7,7 +7,7 @@ ast_struct! { /// A braced block containing Rust statements. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Block { pub brace_token: token::Brace, /// Statements in a block @@ -17,7 +17,7 @@ ast_enum! { /// A statement, usually ending in a semicolon. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum Stmt { /// A local (let) binding. Local(Local), @@ -38,8 +38,8 @@ } ast_struct! { - /// A local `let` binding: `let x: u64 = s.parse()?`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + /// A local `let` binding: `let x: u64 = s.parse()?;`. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Local { pub attrs: Vec, pub let_token: Token![let], @@ -55,7 +55,7 @@ /// /// `LocalInit` represents `= s.parse()?` in `let x: u64 = s.parse()?` and /// `= r else { return }` in `let Ok(x) = r else { return }`. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct LocalInit { pub eq_token: Token![=], pub expr: Box, @@ -69,7 +69,7 @@ /// Syntactically it's ambiguous which other kind of statement this macro /// would expand to. It can be any of local variable (`let`), item, or /// expression. - #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct StmtMacro { pub attrs: Vec, pub mac: Macro, @@ -80,8 +80,9 @@ #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; + use crate::classify; use crate::error::Result; - use crate::expr::{self, Expr, ExprBlock, ExprMacro}; + use crate::expr::{Expr, ExprBlock, ExprMacro}; use crate::ident::Ident; use crate::item; use crate::mac::{self, Macro}; @@ -146,7 +147,7 @@ /// } /// } /// ``` - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_within(input: ParseStream) -> Result> { let mut stmts = Vec::new(); loop { @@ -158,7 +159,7 @@ } let stmt = parse_stmt(input, AllowNoSemi(true))?; let requires_semicolon = match &stmt { - Stmt::Expr(stmt, None) => expr::requires_terminator(stmt), + Stmt::Expr(stmt, None) => classify::requires_semi_to_be_stmt(stmt), Stmt::Macro(stmt) => { stmt.semi_token.is_none() && !stmt.mac.delimiter.is_brace() } @@ -175,7 +176,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Block { fn parse(input: ParseStream) -> Result { let content; @@ -186,7 +187,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Stmt { fn parse(input: ParseStream) -> Result { let allow_nosemi = AllowNoSemi(false); @@ -207,7 +208,8 @@ if ahead.peek2(Ident) || ahead.peek2(Token![try]) { is_item_macro = true; } else if ahead.peek2(token::Brace) - && !(ahead.peek3(Token![.]) || ahead.peek3(Token![?])) + && !(ahead.peek3(Token![.]) && !ahead.peek3(Token![..]) + || ahead.peek3(Token![?])) { input.advance_to(&ahead); return stmt_mac(input, attrs, path).map(Stmt::Macro); @@ -297,8 +299,8 @@ let eq_token: Token![=] = eq_token; let expr: Expr = input.parse()?; - let diverge = if let Some(else_token) = input.parse()? { - let else_token: Token![else] = else_token; + let diverge = if !classify::expr_trailing_brace(&expr) && input.peek(Token![else]) { + let else_token: Token![else] = input.parse()?; let diverge = ExprBlock { attrs: Vec::new(), label: None, @@ -366,6 +368,7 @@ | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) + | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) @@ -400,7 +403,7 @@ if semi_token.is_some() { Ok(Stmt::Expr(e, semi_token)) - } else if allow_nosemi.0 || !expr::requires_terminator(&e) { + } else if allow_nosemi.0 || !classify::requires_semi_to_be_stmt(&e) { Ok(Stmt::Expr(e, None)) } else { Err(input.error("expected semicolon")) @@ -409,13 +412,16 @@ } #[cfg(feature = "printing")] -mod printing { - use crate::expr; +pub(crate) mod printing { + use crate::classify; + use crate::expr::{self, Expr}; + use crate::fixup::FixupContext; use crate::stmt::{Block, Local, Stmt, StmtMacro}; + use crate::token; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Block { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { @@ -424,14 +430,14 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Stmt { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Stmt::Local(local) => local.to_tokens(tokens), Stmt::Item(item) => item.to_tokens(tokens), Stmt::Expr(expr, semi) => { - expr.to_tokens(tokens); + expr::printing::print_expr(expr, tokens, FixupContext::new_stmt()); semi.to_tokens(tokens); } Stmt::Macro(mac) => mac.to_tokens(tokens), @@ -439,7 +445,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Local { fn to_tokens(&self, tokens: &mut TokenStream) { expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); @@ -447,17 +453,27 @@ self.pat.to_tokens(tokens); if let Some(init) = &self.init { init.eq_token.to_tokens(tokens); - init.expr.to_tokens(tokens); + expr::printing::print_subexpression( + &init.expr, + init.diverge.is_some() && classify::expr_trailing_brace(&init.expr), + tokens, + FixupContext::NONE, + ); if let Some((else_token, diverge)) = &init.diverge { else_token.to_tokens(tokens); - diverge.to_tokens(tokens); + match &**diverge { + Expr::Block(diverge) => diverge.to_tokens(tokens), + _ => token::Brace::default().surround(tokens, |tokens| { + expr::printing::print_expr(diverge, tokens, FixupContext::new_stmt()); + }), + } } } self.semi_token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for StmtMacro { fn to_tokens(&self, tokens: &mut TokenStream) { expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/token.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/token.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/token.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/token.rs 2006-07-24 01:21:28.000000000 +0000 @@ -98,10 +98,6 @@ #[cfg(feature = "parsing")] use crate::lifetime::Lifetime; #[cfg(feature = "parsing")] -use crate::lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr}; -#[cfg(feature = "parsing")] -use crate::lookahead; -#[cfg(feature = "parsing")] use crate::parse::{Parse, ParseStream}; use crate::span::IntoSpans; use proc_macro2::extra::DelimSpan; @@ -113,7 +109,7 @@ #[cfg(feature = "parsing")] use proc_macro2::{Literal, Punct, TokenTree}; #[cfg(feature = "printing")] -use quote::{ToTokens, TokenStreamExt}; +use quote::{ToTokens, TokenStreamExt as _}; #[cfg(feature = "extra-traits")] use std::cmp; #[cfg(feature = "extra-traits")] @@ -147,7 +143,7 @@ /// Support writing `token.span` rather than `token.spans[0]` on tokens that /// hold a single span. #[repr(transparent)] - #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482 + #[allow(unknown_lints, repr_transparent_non_zst_fields)] // False positive: https://github.com/rust-lang/rust/issues/115922 pub struct WithSpan { pub span: Span, } @@ -164,54 +160,10 @@ #[cfg(feature = "parsing")] impl private::Sealed for Ident {} -#[cfg(feature = "parsing")] -fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool { - use crate::parse::Unexpected; - use std::cell::Cell; - use std::rc::Rc; - - let scope = Span::call_site(); - let unexpected = Rc::new(Cell::new(Unexpected::None)); - let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected); - peek(&buffer) -} - -macro_rules! impl_token { - ($display:literal $name:ty) => { - #[cfg(feature = "parsing")] - impl Token for $name { - fn peek(cursor: Cursor) -> bool { - fn peek(input: ParseStream) -> bool { - <$name as Parse>::parse(input).is_ok() - } - peek_impl(cursor, peek) - } - - fn display() -> &'static str { - $display - } - } - - #[cfg(feature = "parsing")] - impl private::Sealed for $name {} - }; -} - -impl_token!("lifetime" Lifetime); -impl_token!("literal" Lit); -impl_token!("string literal" LitStr); -impl_token!("byte string literal" LitByteStr); -impl_token!("byte literal" LitByte); -impl_token!("character literal" LitChar); -impl_token!("integer literal" LitInt); -impl_token!("floating point literal" LitFloat); -impl_token!("boolean literal" LitBool); -impl_token!("group token" proc_macro2::Group); - macro_rules! impl_low_level_token { - ($display:literal $ty:ident $get:ident) => { + ($display:literal $($path:ident)::+ $get:ident) => { #[cfg(feature = "parsing")] - impl Token for $ty { + impl Token for $($path)::+ { fn peek(cursor: Cursor) -> bool { cursor.$get().is_some() } @@ -222,13 +174,15 @@ } #[cfg(feature = "parsing")] - impl private::Sealed for $ty {} + impl private::Sealed for $($path)::+ {} }; } impl_low_level_token!("punctuation token" Punct punct); impl_low_level_token!("literal" Literal literal); impl_low_level_token!("token" TokenTree token_tree); +impl_low_level_token!("group token" proc_macro2::Group any_group); +impl_low_level_token!("lifetime" Lifetime lifetime); #[cfg(feature = "parsing")] impl private::Sealed for T {} @@ -274,11 +228,11 @@ } #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self @@ -286,7 +240,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) @@ -294,11 +248,11 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true @@ -306,13 +260,13 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } #[cfg(feature = "printing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for $name { fn to_tokens(&self, tokens: &mut TokenStream) { printing::keyword($token, self.span, tokens); @@ -320,7 +274,7 @@ } #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for $name { fn parse(input: ParseStream) -> Result { Ok($name { @@ -370,7 +324,7 @@ ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => { $( #[cfg_attr(not(doc), repr(transparent))] - #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482 + #[allow(unknown_lints, repr_transparent_non_zst_fields)] // False positive: https://github.com/rust-lang/rust/issues/115922 #[doc = concat!('`', $token, '`')] /// /// Usage: @@ -401,11 +355,11 @@ } #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self @@ -413,7 +367,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) @@ -421,11 +375,11 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true @@ -433,7 +387,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } @@ -451,7 +405,7 @@ } #[cfg(feature = "printing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for $name { fn to_tokens(&self, tokens: &mut TokenStream) { printing::punct($token, &self.spans, tokens); @@ -459,7 +413,7 @@ } #[cfg(feature = "parsing")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for $name { fn parse(input: ParseStream) -> Result { Ok($name { @@ -508,11 +462,11 @@ } #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] + #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self @@ -520,7 +474,7 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) @@ -528,11 +482,11 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true @@ -540,13 +494,14 @@ } #[cfg(feature = "extra-traits")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] + #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } impl $name { #[cfg(feature = "printing")] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] pub fn surround(&self, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream), @@ -568,7 +523,7 @@ } #[cfg(feature = "printing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Underscore { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Ident::new("_", self.span)); @@ -576,7 +531,7 @@ } #[cfg(feature = "parsing")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Underscore { fn parse(input: ParseStream) -> Result { input.step(|cursor| { @@ -637,11 +592,11 @@ } #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Group {} #[cfg(feature = "clone-impls")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Group { fn clone(&self) -> Self { *self @@ -649,7 +604,7 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Group { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Group") @@ -657,11 +612,11 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for Group {} #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Group { fn eq(&self, _other: &Group) -> bool { true @@ -669,13 +624,14 @@ } #[cfg(feature = "extra-traits")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Group { fn hash(&self, _state: &mut H) {} } impl Group { #[cfg(feature = "printing")] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] pub fn surround(&self, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream), @@ -692,7 +648,7 @@ #[cfg(feature = "parsing")] impl Token for Paren { fn peek(cursor: Cursor) -> bool { - lookahead::is_delimiter(cursor, Delimiter::Parenthesis) + cursor.group(Delimiter::Parenthesis).is_some() } fn display() -> &'static str { @@ -703,7 +659,7 @@ #[cfg(feature = "parsing")] impl Token for Brace { fn peek(cursor: Cursor) -> bool { - lookahead::is_delimiter(cursor, Delimiter::Brace) + cursor.group(Delimiter::Brace).is_some() } fn display() -> &'static str { @@ -714,7 +670,7 @@ #[cfg(feature = "parsing")] impl Token for Bracket { fn peek(cursor: Cursor) -> bool { - lookahead::is_delimiter(cursor, Delimiter::Bracket) + cursor.group(Delimiter::Bracket).is_some() } fn display() -> &'static str { @@ -725,7 +681,7 @@ #[cfg(feature = "parsing")] impl Token for Group { fn peek(cursor: Cursor) -> bool { - lookahead::is_delimiter(cursor, Delimiter::None) + cursor.group(Delimiter::None).is_some() } fn display() -> &'static str { @@ -767,6 +723,7 @@ "override" pub struct Override "priv" pub struct Priv "pub" pub struct Pub + "raw" pub struct Raw "ref" pub struct Ref "return" pub struct Return "Self" pub struct SelfType @@ -945,6 +902,7 @@ [override] => { $crate::token::Override }; [priv] => { $crate::token::Priv }; [pub] => { $crate::token::Pub }; + [raw] => { $crate::token::Raw }; [ref] => { $crate::token::Ref }; [return] => { $crate::token::Return }; [Self] => { $crate::token::SelfType }; @@ -1099,8 +1057,9 @@ #[doc(hidden)] #[cfg(feature = "printing")] pub(crate) mod printing { + use crate::ext::PunctExt as _; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream}; - use quote::TokenStreamExt; + use quote::TokenStreamExt as _; #[doc(hidden)] pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) { @@ -1111,14 +1070,10 @@ let ch = chars.next_back().unwrap(); let span = spans.next_back().unwrap(); for (ch, span) in chars.zip(spans) { - let mut op = Punct::new(ch, Spacing::Joint); - op.set_span(*span); - tokens.append(op); + tokens.append(Punct::new_spanned(ch, Spacing::Joint, *span)); } - let mut op = Punct::new(ch, Spacing::Alone); - op.set_span(*span); - tokens.append(op); + tokens.append(Punct::new_spanned(ch, Spacing::Alone, *span)); } pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/tt.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/tt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/tt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/tt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,10 @@ -use proc_macro2::{Delimiter, TokenStream, TokenTree}; +use proc_macro2::{Delimiter, Spacing, TokenStream, TokenTree}; use std::hash::{Hash, Hasher}; pub(crate) struct TokenTreeHelper<'a>(pub &'a TokenTree); impl<'a> PartialEq for TokenTreeHelper<'a> { fn eq(&self, other: &Self) -> bool { - use proc_macro2::Spacing; - match (self.0, other.0) { (TokenTree::Group(g1), TokenTree::Group(g2)) => { match (g1.delimiter(), g2.delimiter()) { @@ -17,19 +15,7 @@ _ => return false, } - let s1 = g1.stream().into_iter(); - let mut s2 = g2.stream().into_iter(); - - for item1 in s1 { - let item2 = match s2.next() { - Some(item) => item, - None => return false, - }; - if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) { - return false; - } - } - s2.next().is_none() + TokenStreamHelper(&g1.stream()) == TokenStreamHelper(&g2.stream()) } (TokenTree::Punct(o1), TokenTree::Punct(o2)) => { o1.as_char() == o2.as_char() @@ -47,8 +33,6 @@ impl<'a> Hash for TokenTreeHelper<'a> { fn hash(&self, h: &mut H) { - use proc_macro2::Spacing; - match self.0 { TokenTree::Group(g) => { 0u8.hash(h); @@ -82,25 +66,30 @@ impl<'a> PartialEq for TokenStreamHelper<'a> { fn eq(&self, other: &Self) -> bool { - let left = self.0.clone().into_iter().collect::>(); - let right = other.0.clone().into_iter().collect::>(); - if left.len() != right.len() { - return false; - } - for (a, b) in left.into_iter().zip(right) { - if TokenTreeHelper(&a) != TokenTreeHelper(&b) { + let left = self.0.clone().into_iter(); + let mut right = other.0.clone().into_iter(); + + for item1 in left { + let item2 = match right.next() { + Some(item) => item, + None => return false, + }; + if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) { return false; } } - true + + right.next().is_none() } } impl<'a> Hash for TokenStreamHelper<'a> { fn hash(&self, state: &mut H) { - let tts = self.0.clone().into_iter().collect::>(); - tts.len().hash(state); - for tt in tts { + let tokens = self.0.clone().into_iter(); + + tokens.clone().count().hash(state); + + for tt in tokens { TokenTreeHelper(&tt).hash(state); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/ty.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ty.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/ty.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/ty.rs 2006-07-24 01:21:28.000000000 +0000 @@ -18,7 +18,7 @@ /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Type { /// A fixed size array type: `[T; n]`. @@ -91,7 +91,7 @@ ast_struct! { /// A fixed size array type: `[T; n]`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeArray { pub bracket_token: token::Bracket, pub elem: Box, @@ -102,7 +102,7 @@ ast_struct! { /// A bare function type: `fn(usize) -> bool`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeBareFn { pub lifetimes: Option, pub unsafety: Option, @@ -117,7 +117,7 @@ ast_struct! { /// A type contained within invisible delimiters. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeGroup { pub group_token: token::Group, pub elem: Box, @@ -127,7 +127,7 @@ ast_struct! { /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or /// a lifetime. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeImplTrait { pub impl_token: Token![impl], pub bounds: Punctuated, @@ -136,7 +136,7 @@ ast_struct! { /// Indication that a type should be inferred by the compiler: `_`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeInfer { pub underscore_token: Token![_], } @@ -144,7 +144,7 @@ ast_struct! { /// A macro in the type position. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeMacro { pub mac: Macro, } @@ -152,7 +152,7 @@ ast_struct! { /// The never type: `!`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeNever { pub bang_token: Token![!], } @@ -160,7 +160,7 @@ ast_struct! { /// A parenthesized type equivalent to the inner type. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeParen { pub paren_token: token::Paren, pub elem: Box, @@ -170,7 +170,7 @@ ast_struct! { /// A path like `std::slice::Iter`, optionally qualified with a /// self-type as in ` as SomeTrait>::Associated`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePath { pub qself: Option, pub path: Path, @@ -179,7 +179,7 @@ ast_struct! { /// A raw pointer type: `*const T` or `*mut T`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePtr { pub star_token: Token![*], pub const_token: Option, @@ -190,7 +190,7 @@ ast_struct! { /// A reference type: `&'a T` or `&'a mut T`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeReference { pub and_token: Token![&], pub lifetime: Option, @@ -201,7 +201,7 @@ ast_struct! { /// A dynamically sized slice type: `[T]`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeSlice { pub bracket_token: token::Bracket, pub elem: Box, @@ -211,7 +211,7 @@ ast_struct! { /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTraitObject { pub dyn_token: Option, pub bounds: Punctuated, @@ -220,7 +220,7 @@ ast_struct! { /// A tuple type: `(A, B, C, String)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTuple { pub paren_token: token::Paren, pub elems: Punctuated, @@ -229,7 +229,7 @@ ast_struct! { /// The binary interface of a function: `extern "C"`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Abi { pub extern_token: Token![extern], pub name: Option, @@ -238,7 +238,7 @@ ast_struct! { /// An argument in a function type: the `usize` in `fn(usize) -> bool`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareFnArg { pub attrs: Vec, pub name: Option<(Ident, Token![:])>, @@ -248,7 +248,7 @@ ast_struct! { /// The variadic argument of a function pointer like `fn(usize, ...)`. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareVariadic { pub attrs: Vec, pub name: Option<(Ident, Token![:])>, @@ -259,7 +259,7 @@ ast_enum! { /// Return type of a function signature. - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum ReturnType { /// Return type is not specified. /// @@ -292,7 +292,7 @@ use crate::verbatim; use proc_macro2::Span; - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Type { fn parse(input: ParseStream) -> Result { let allow_plus = true; @@ -307,7 +307,7 @@ /// contain a `+` character. /// /// This parser does not allow a `+`, while the default parser does. - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; let allow_group_generic = true; @@ -350,7 +350,7 @@ Path::parse_rest(input, &mut ty.path, false)?; return Ok(Type::Path(ty)); } else { - group.elem = Box::new(Type::Path(ty)); + *group.elem = Type::Path(ty); } } } @@ -402,7 +402,15 @@ })); while let Some(plus) = input.parse()? { bounds.push_punct(plus); - bounds.push_value(input.parse()?); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = false; + TypeParamBound::parse_single( + input, + allow_precise_capture, + allow_const, + )? + }); } bounds }, @@ -457,6 +465,7 @@ }) } other @ (TypeParamBound::Lifetime(_) + | TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_)) => other, } } @@ -469,7 +478,15 @@ bounds.push_value(first); while let Some(plus) = input.parse()? { bounds.push_punct(plus); - bounds.push_value(input.parse()?); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = false; + TypeParamBound::parse_single( + input, + allow_precise_capture, + allow_const, + )? + }); } bounds }, @@ -532,7 +549,11 @@ { break; } - bounds.push_value(input.parse()?); + bounds.push_value({ + let allow_precise_capture = false; + let allow_const = false; + TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? + }); } } return Ok(Type::TraitObject(TypeTraitObject { @@ -547,14 +568,14 @@ let dyn_span = dyn_token.span; let star_token: Option = input.parse()?; let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?; - return Ok(if star_token.is_some() { + Ok(if star_token.is_some() { Type::Verbatim(verbatim::between(&begin, input)) } else { Type::TraitObject(TypeTraitObject { dyn_token: Some(dyn_token), bounds, }) - }); + }) } else if lookahead.peek(token::Bracket) { let content; let bracket_token = bracketed!(content in input); @@ -589,7 +610,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeSlice { fn parse(input: ParseStream) -> Result { let content; @@ -600,7 +621,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeArray { fn parse(input: ParseStream) -> Result { let content; @@ -613,7 +634,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePtr { fn parse(input: ParseStream) -> Result { let star_token: Token![*] = input.parse()?; @@ -636,7 +657,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeReference { fn parse(input: ParseStream) -> Result { Ok(TypeReference { @@ -649,7 +670,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeBareFn { fn parse(input: ParseStream) -> Result { let args; @@ -669,7 +690,7 @@ if inputs.empty_or_trailing() && (args.peek(Token![...]) - || args.peek(Ident) + || (args.peek(Ident) || args.peek(Token![_])) && args.peek2(Token![:]) && args.peek3(Token![...])) { @@ -696,7 +717,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeNever { fn parse(input: ParseStream) -> Result { Ok(TypeNever { @@ -705,7 +726,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeInfer { fn parse(input: ParseStream) -> Result { Ok(TypeInfer { @@ -714,7 +735,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTuple { fn parse(input: ParseStream) -> Result { let content; @@ -747,7 +768,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeMacro { fn parse(input: ParseStream) -> Result { Ok(TypeMacro { @@ -756,7 +777,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePath { fn parse(input: ParseStream) -> Result { let expr_style = false; @@ -766,7 +787,7 @@ } impl ReturnType { - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) @@ -784,7 +805,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ReturnType { fn parse(input: ParseStream) -> Result { let allow_plus = true; @@ -792,7 +813,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTraitObject { fn parse(input: ParseStream) -> Result { let allow_plus = true; @@ -801,7 +822,7 @@ } impl TypeTraitObject { - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) @@ -823,18 +844,28 @@ input: ParseStream, allow_plus: bool, ) -> Result> { - let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; + let allow_precise_capture = false; + let allow_const = false; + let bounds = TypeParamBound::parse_multiple( + input, + allow_plus, + allow_precise_capture, + allow_const, + )?; let mut last_lifetime_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { - TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { + TypeParamBound::Trait(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { last_lifetime_span = Some(lifetime.ident.span()); } + TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => { + unreachable!() + } } } // Just lifetimes like `'a + 'b` is not a TraitObject. @@ -846,7 +877,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeImplTrait { fn parse(input: ParseStream) -> Result { let allow_plus = true; @@ -855,7 +886,7 @@ } impl TypeImplTrait { - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) @@ -863,17 +894,40 @@ pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result { let impl_token: Token![impl] = input.parse()?; - let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; - let mut last_lifetime_span = None; + let allow_precise_capture = true; + let allow_const = true; + let bounds = TypeParamBound::parse_multiple( + input, + allow_plus, + allow_precise_capture, + allow_const, + )?; + let mut last_nontrait_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { - TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { + TypeParamBound::Trait(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { - last_lifetime_span = Some(lifetime.ident.span()); + last_nontrait_span = Some(lifetime.ident.span()); + } + TypeParamBound::PreciseCapture(precise_capture) => { + #[cfg(feature = "full")] + { + last_nontrait_span = Some(precise_capture.gt_token.span); + } + #[cfg(not(feature = "full"))] + { + _ = precise_capture; + unreachable!(); + } + } + TypeParamBound::Verbatim(_) => { + // `[const] Trait` + at_least_one_trait = true; + break; } } } @@ -881,7 +935,7 @@ let msg = "at least one trait must be specified"; return Err(error::new2( impl_token.span, - last_lifetime_span.unwrap(), + last_nontrait_span.unwrap(), msg, )); } @@ -889,7 +943,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeGroup { fn parse(input: ParseStream) -> Result { let group = crate::group::parse_group(input)?; @@ -900,7 +954,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParen { fn parse(input: ParseStream) -> Result { let allow_plus = false; @@ -921,7 +975,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BareFnArg { fn parse(input: ParseStream) -> Result { let allow_self = false; @@ -992,7 +1046,7 @@ }) } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Abi { fn parse(input: ParseStream) -> Result { Ok(Abi { @@ -1002,7 +1056,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![extern]) { @@ -1018,6 +1072,7 @@ mod printing { use crate::attr::FilterAttrs; use crate::path; + use crate::path::printing::PathStyle; use crate::print::TokensOrDefault; use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, @@ -1025,9 +1080,9 @@ TypeTraitObject, TypeTuple, }; use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; + use quote::{ToTokens, TokenStreamExt as _}; - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeSlice { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { @@ -1036,7 +1091,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeArray { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { @@ -1047,7 +1102,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePtr { fn to_tokens(&self, tokens: &mut TokenStream) { self.star_token.to_tokens(tokens); @@ -1061,7 +1116,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeReference { fn to_tokens(&self, tokens: &mut TokenStream) { self.and_token.to_tokens(tokens); @@ -1071,7 +1126,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeBareFn { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetimes.to_tokens(tokens); @@ -1092,14 +1147,14 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeNever { fn to_tokens(&self, tokens: &mut TokenStream) { self.bang_token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTuple { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { @@ -1113,14 +1168,14 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePath { fn to_tokens(&self, tokens: &mut TokenStream) { - path::printing::print_path(tokens, &self.qself, &self.path); + path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::AsWritten); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTraitObject { fn to_tokens(&self, tokens: &mut TokenStream) { self.dyn_token.to_tokens(tokens); @@ -1128,7 +1183,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeImplTrait { fn to_tokens(&self, tokens: &mut TokenStream) { self.impl_token.to_tokens(tokens); @@ -1136,7 +1191,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeGroup { fn to_tokens(&self, tokens: &mut TokenStream) { self.group_token.surround(tokens, |tokens| { @@ -1145,7 +1200,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeParen { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { @@ -1154,21 +1209,21 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeInfer { fn to_tokens(&self, tokens: &mut TokenStream) { self.underscore_token.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeMacro { fn to_tokens(&self, tokens: &mut TokenStream) { self.mac.to_tokens(tokens); } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ReturnType { fn to_tokens(&self, tokens: &mut TokenStream) { match self { @@ -1181,7 +1236,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareFnArg { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -1193,7 +1248,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareVariadic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); @@ -1206,7 +1261,7 @@ } } - #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Abi { fn to_tokens(&self, tokens: &mut TokenStream) { self.extern_token.to_tokens(tokens); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/src/verbatim.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/src/verbatim.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/src/verbatim.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/src/verbatim.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ +use crate::ext::TokenStreamExt as _; use crate::parse::ParseStream; use proc_macro2::{Delimiter, TokenStream}; use std::cmp::Ordering; -use std::iter; pub(crate) fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream { let end = end.cursor(); @@ -26,7 +26,7 @@ } } - tokens.extend(iter::once(tt)); + tokens.append(tt); cursor = next; } tokens diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/eq.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/eq.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/eq.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/eq.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,19 +10,19 @@ use rustc_ast::ast::AngleBracketedArgs; use rustc_ast::ast::AnonConst; use rustc_ast::ast::Arm; -use rustc_ast::ast::AssocConstraint; -use rustc_ast::ast::AssocConstraintKind; +use rustc_ast::ast::AsmMacro; +use rustc_ast::ast::AssignOpKind; +use rustc_ast::ast::AssocItemConstraint; +use rustc_ast::ast::AssocItemConstraintKind; use rustc_ast::ast::AssocItemKind; use rustc_ast::ast::AttrArgs; -use rustc_ast::ast::AttrArgsEq; use rustc_ast::ast::AttrId; use rustc_ast::ast::AttrItem; use rustc_ast::ast::AttrKind; use rustc_ast::ast::AttrStyle; use rustc_ast::ast::Attribute; -use rustc_ast::ast::BareFnTy; use rustc_ast::ast::BinOpKind; -use rustc_ast::ast::BindingAnnotation; +use rustc_ast::ast::BindingMode; use rustc_ast::ast::Block; use rustc_ast::ast::BlockCheckMode; use rustc_ast::ast::BorrowKind; @@ -35,11 +35,15 @@ use rustc_ast::ast::ClosureBinder; use rustc_ast::ast::Const; use rustc_ast::ast::ConstItem; +use rustc_ast::ast::ConstItemRhs; use rustc_ast::ast::CoroutineKind; use rustc_ast::ast::Crate; use rustc_ast::ast::Defaultness; use rustc_ast::ast::Delegation; +use rustc_ast::ast::DelegationMac; use rustc_ast::ast::DelimArgs; +use rustc_ast::ast::EiiExternTarget; +use rustc_ast::ast::EiiImpl; use rustc_ast::ast::EnumDef; use rustc_ast::ast::Expr; use rustc_ast::ast::ExprField; @@ -48,8 +52,10 @@ use rustc_ast::ast::FieldDef; use rustc_ast::ast::FloatTy; use rustc_ast::ast::Fn; +use rustc_ast::ast::FnContract; use rustc_ast::ast::FnDecl; use rustc_ast::ast::FnHeader; +use rustc_ast::ast::FnPtrTy; use rustc_ast::ast::FnRetTy; use rustc_ast::ast::FnSig; use rustc_ast::ast::ForLoopKind; @@ -101,8 +107,12 @@ use rustc_ast::ast::MacStmtStyle; use rustc_ast::ast::MacroDef; use rustc_ast::ast::MatchKind; +use rustc_ast::ast::MetaItem; +use rustc_ast::ast::MetaItemInner; +use rustc_ast::ast::MetaItemKind; use rustc_ast::ast::MetaItemLit; use rustc_ast::ast::MethodCall; +use rustc_ast::ast::MgcaDisambiguation; use rustc_ast::ast::ModKind; use rustc_ast::ast::ModSpans; use rustc_ast::ast::Movability; @@ -111,6 +121,7 @@ use rustc_ast::ast::NodeId; use rustc_ast::ast::NormalAttr; use rustc_ast::ast::Param; +use rustc_ast::ast::Parens; use rustc_ast::ast::ParenthesizedArgs; use rustc_ast::ast::Pat; use rustc_ast::ast::PatField; @@ -118,12 +129,15 @@ use rustc_ast::ast::PatKind; use rustc_ast::ast::Path; use rustc_ast::ast::PathSegment; +use rustc_ast::ast::Pinnedness; use rustc_ast::ast::PolyTraitRef; use rustc_ast::ast::PreciseCapturingArg; use rustc_ast::ast::QSelf; use rustc_ast::ast::RangeEnd; use rustc_ast::ast::RangeLimits; use rustc_ast::ast::RangeSyntax; +use rustc_ast::ast::Recovered; +use rustc_ast::ast::Safety; use rustc_ast::ast::StaticItem; use rustc_ast::ast::Stmt; use rustc_ast::ast::StmtKind; @@ -133,17 +147,20 @@ use rustc_ast::ast::StructRest; use rustc_ast::ast::Term; use rustc_ast::ast::Trait; +use rustc_ast::ast::TraitAlias; use rustc_ast::ast::TraitBoundModifiers; +use rustc_ast::ast::TraitImplHeader; use rustc_ast::ast::TraitObjectSyntax; use rustc_ast::ast::TraitRef; use rustc_ast::ast::Ty; use rustc_ast::ast::TyAlias; -use rustc_ast::ast::TyAliasWhereClause; -use rustc_ast::ast::TyAliasWhereClauses; use rustc_ast::ast::TyKind; +use rustc_ast::ast::TyPat; +use rustc_ast::ast::TyPatKind; use rustc_ast::ast::UintTy; use rustc_ast::ast::UnOp; -use rustc_ast::ast::Unsafe; +use rustc_ast::ast::UnsafeBinderCastKind; +use rustc_ast::ast::UnsafeBinderTy; use rustc_ast::ast::UnsafeSource; use rustc_ast::ast::UseTree; use rustc_ast::ast::UseTreeKind; @@ -155,22 +172,22 @@ use rustc_ast::ast::WhereClause; use rustc_ast::ast::WhereEqPredicate; use rustc_ast::ast::WherePredicate; +use rustc_ast::ast::WherePredicateKind; use rustc_ast::ast::WhereRegionPredicate; -use rustc_ast::ptr::P; -use rustc_ast::token::{ - self, CommentKind, Delimiter, IdentIsRaw, Lit, Nonterminal, Token, TokenKind, -}; +use rustc_ast::ast::YieldKind; +use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Lit, Token, TokenKind}; use rustc_ast::tokenstream::{ - AttrTokenStream, AttrTokenTree, AttributesData, DelimSpacing, DelimSpan, LazyAttrTokenStream, + AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing, DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenTree, }; use rustc_data_structures::packed::Pu128; -use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{sym, Ident}; -use rustc_span::{ErrorGuaranteed, Span, Symbol, SyntaxContext, DUMMY_SP}; +use rustc_span::symbol::{sym, ByteSymbol, Ident, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, SyntaxContext, DUMMY_SP}; +use std::borrow::Cow; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; +use std::sync::Arc; use thin_vec::ThinVec; pub trait SpanlessEq { @@ -183,13 +200,7 @@ } } -impl SpanlessEq for P { - fn eq(&self, other: &Self) -> bool { - SpanlessEq::eq(&**self, &**other) - } -} - -impl SpanlessEq for Lrc { +impl SpanlessEq for Arc { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&**self, &**other) } @@ -248,6 +259,12 @@ } } +impl<'a, T: ?Sized + ToOwned + SpanlessEq> SpanlessEq for Cow<'a, T> { + fn eq(&self, other: &Self) -> bool { + ::eq(self, other) + } +} + impl SpanlessEq for Spanned { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&self.node, &other.node) @@ -295,6 +312,7 @@ }; } +spanless_eq_partial_eq!(()); spanless_eq_partial_eq!(bool); spanless_eq_partial_eq!(u8); spanless_eq_partial_eq!(u16); @@ -302,9 +320,11 @@ spanless_eq_partial_eq!(u128); spanless_eq_partial_eq!(usize); spanless_eq_partial_eq!(char); +spanless_eq_partial_eq!(str); spanless_eq_partial_eq!(String); spanless_eq_partial_eq!(Pu128); spanless_eq_partial_eq!(Symbol); +spanless_eq_partial_eq!(ByteSymbol); spanless_eq_partial_eq!(CommentKind); spanless_eq_partial_eq!(Delimiter); spanless_eq_partial_eq!(InlineAsmOptions); @@ -459,49 +479,54 @@ } spanless_eq_struct!(AngleBracketedArgs; span args); -spanless_eq_struct!(AnonConst; id value); +spanless_eq_struct!(AnonConst; id value !mgca_disambiguation); spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder); -spanless_eq_struct!(AssocConstraint; id ident gen_args kind span); -spanless_eq_struct!(AttrItem; path args tokens); +spanless_eq_struct!(AssocItemConstraint; id ident gen_args kind span); +spanless_eq_struct!(AttrItem; unsafety path args tokens); spanless_eq_struct!(AttrTokenStream; 0); spanless_eq_struct!(Attribute; kind id style span); -spanless_eq_struct!(AttributesData; attrs tokens); -spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl decl_span); -spanless_eq_struct!(BindingAnnotation; 0 1); -spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal); +spanless_eq_struct!(AttrsTarget; attrs tokens); +spanless_eq_struct!(BindingMode; 0 1); +spanless_eq_struct!(Block; stmts id rules span tokens); spanless_eq_struct!(Closure; binder capture_clause constness coroutine_kind movability fn_decl body !fn_decl_span !fn_arg_span); -spanless_eq_struct!(ConstItem; defaultness generics ty expr); +spanless_eq_struct!(ConstItem; defaultness ident generics ty rhs define_opaque); spanless_eq_struct!(Crate; attrs items spans id is_placeholder); -spanless_eq_struct!(Delegation; id qself path body); +spanless_eq_struct!(Delegation; id qself path ident rename body from_glob); +spanless_eq_struct!(DelegationMac; qself prefix suffixes body); spanless_eq_struct!(DelimArgs; dspan delim tokens); spanless_eq_struct!(DelimSpacing; open close); +spanless_eq_struct!(EiiExternTarget; extern_item_path impl_unsafe span); +spanless_eq_struct!(EiiImpl; node_id eii_macro_path impl_safety span inner_span is_default); spanless_eq_struct!(EnumDef; variants); spanless_eq_struct!(Expr; id kind span attrs !tokens); spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder); -spanless_eq_struct!(FieldDef; attrs id span vis ident ty is_placeholder); -spanless_eq_struct!(Fn; defaultness generics sig body); +spanless_eq_struct!(FieldDef; attrs id span vis safety ident ty default is_placeholder); +spanless_eq_struct!(Fn; defaultness ident generics sig contract define_opaque body eii_impls); +spanless_eq_struct!(FnContract; declarations requires ensures); spanless_eq_struct!(FnDecl; inputs output); -spanless_eq_struct!(FnHeader; constness coroutine_kind unsafety ext); +spanless_eq_struct!(FnHeader; constness coroutine_kind safety ext); +spanless_eq_struct!(FnPtrTy; safety ext generic_params decl decl_span); spanless_eq_struct!(FnSig; header decl span); -spanless_eq_struct!(ForeignMod; unsafety abi items); +spanless_eq_struct!(ForeignMod; extern_span safety abi items); spanless_eq_struct!(FormatArgPosition; index kind span); -spanless_eq_struct!(FormatArgs; span template arguments); +spanless_eq_struct!(FormatArgs; span template arguments uncooked_fmt_str is_source_literal); spanless_eq_struct!(FormatArgument; kind expr); spanless_eq_struct!(FormatOptions; width precision alignment fill sign alternate zero_pad debug_hex); spanless_eq_struct!(FormatPlaceholder; argument span format_trait format_options); spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind !colon_span); spanless_eq_struct!(Generics; params where_clause span); -spanless_eq_struct!(Impl; defaultness unsafety generics constness polarity of_trait self_ty items); -spanless_eq_struct!(InlineAsm; template template_strs operands clobber_abis options line_spans); +spanless_eq_struct!(Impl; generics constness of_trait self_ty items); +spanless_eq_struct!(InlineAsm; asm_macro template template_strs operands clobber_abis options line_spans); spanless_eq_struct!(InlineAsmSym; id qself path); -spanless_eq_struct!(Item; attrs id span vis ident kind !tokens); +spanless_eq_struct!(Item; attrs id span vis kind !tokens); spanless_eq_struct!(Label; ident); spanless_eq_struct!(Lifetime; id ident); spanless_eq_struct!(Lit; kind symbol suffix); -spanless_eq_struct!(Local; id pat ty kind span colon_sp attrs !tokens); +spanless_eq_struct!(Local; id super_ pat ty kind span colon_sp attrs !tokens); spanless_eq_struct!(MacCall; path args); spanless_eq_struct!(MacCallStmt; mac style attrs tokens); -spanless_eq_struct!(MacroDef; body macro_rules); +spanless_eq_struct!(MacroDef; body macro_rules eii_extern_target); +spanless_eq_struct!(MetaItem; unsafety path kind span); spanless_eq_struct!(MetaItemLit; symbol suffix kind span); spanless_eq_struct!(MethodCall; seg receiver args !span); spanless_eq_struct!(ModSpans; !inner_span !inject_use_span); @@ -512,50 +537,54 @@ spanless_eq_struct!(PatField; ident pat is_shorthand attrs id span is_placeholder); spanless_eq_struct!(Path; span segments tokens); spanless_eq_struct!(PathSegment; ident id args); -spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span); +spanless_eq_struct!(PolyTraitRef; bound_generic_params modifiers trait_ref span parens); spanless_eq_struct!(QSelf; ty path_span position); -spanless_eq_struct!(StaticItem; ty mutability expr); +spanless_eq_struct!(StaticItem; ident ty safety mutability expr define_opaque); spanless_eq_struct!(Stmt; id kind span); spanless_eq_struct!(StrLit; symbol suffix symbol_unescaped style span); spanless_eq_struct!(StructExpr; qself path fields rest); spanless_eq_struct!(Token; kind span); -spanless_eq_struct!(Trait; unsafety is_auto generics bounds items); +spanless_eq_struct!(Trait; constness safety is_auto ident generics bounds items); +spanless_eq_struct!(TraitAlias; constness ident generics bounds); spanless_eq_struct!(TraitBoundModifiers; constness asyncness polarity); +spanless_eq_struct!(TraitImplHeader; defaultness safety polarity trait_ref); spanless_eq_struct!(TraitRef; path ref_id); spanless_eq_struct!(Ty; id kind span tokens); -spanless_eq_struct!(TyAlias; defaultness generics where_clauses bounds ty); -spanless_eq_struct!(TyAliasWhereClause; !has_where_token span); -spanless_eq_struct!(TyAliasWhereClauses; before after !split); +spanless_eq_struct!(TyAlias; defaultness ident generics after_where_clause bounds ty); +spanless_eq_struct!(TyPat; id kind span tokens); +spanless_eq_struct!(UnsafeBinderTy; generic_params inner_ty); spanless_eq_struct!(UseTree; prefix kind span); spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder); spanless_eq_struct!(Visibility; kind span tokens); -spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds); +spanless_eq_struct!(WhereBoundPredicate; bound_generic_params bounded_ty bounds); spanless_eq_struct!(WhereClause; has_where_token predicates span); -spanless_eq_struct!(WhereEqPredicate; span lhs_ty rhs_ty); -spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds); +spanless_eq_struct!(WhereEqPredicate; lhs_ty rhs_ty); +spanless_eq_struct!(WherePredicate; attrs kind id span is_placeholder); +spanless_eq_struct!(WhereRegionPredicate; lifetime bounds); spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0)); -spanless_eq_enum!(AssocConstraintKind; Equality(term) Bound(bounds)); -spanless_eq_enum!(AssocItemKind; Const(0) Fn(0) Type(0) MacCall(0) Delegation(0)); -spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(0 1)); -spanless_eq_enum!(AttrArgsEq; Ast(0) Hir(0)); +spanless_eq_enum!(AsmMacro; Asm GlobalAsm NakedAsm); +spanless_eq_enum!(AssocItemConstraintKind; Equality(term) Bound(bounds)); +spanless_eq_enum!(AssocItemKind; Const(0) Fn(0) Type(0) MacCall(0) Delegation(0) DelegationMac(0)); +spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(eq_span expr)); spanless_eq_enum!(AttrStyle; Outer Inner); -spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2 3) Attributes(0)); +spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2 3) AttrsTarget(0)); spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt); spanless_eq_enum!(BlockCheckMode; Default Unsafe(0)); -spanless_eq_enum!(BorrowKind; Ref Raw); +spanless_eq_enum!(BorrowKind; Ref Raw Pin); spanless_eq_enum!(BoundAsyncness; Normal Async(0)); spanless_eq_enum!(BoundConstness; Never Always(0) Maybe(0)); spanless_eq_enum!(BoundPolarity; Positive Negative(0) Maybe(0)); -spanless_eq_enum!(ByRef; Yes(0) No); -spanless_eq_enum!(CaptureBy; Value(move_kw) Ref); +spanless_eq_enum!(ByRef; Yes(0 1) No); +spanless_eq_enum!(CaptureBy; Value(move_kw) Ref Use(use_kw)); spanless_eq_enum!(ClosureBinder; NotPresent For(span generic_params)); spanless_eq_enum!(Const; Yes(0) No); +spanless_eq_enum!(ConstItemRhs; TypeConst(0) Body(0)); spanless_eq_enum!(Defaultness; Default(0) Final); spanless_eq_enum!(Extern; None Implicit(0) Explicit(0 1)); spanless_eq_enum!(FloatTy; F16 F32 F64 F128); spanless_eq_enum!(FnRetTy; Default(0) Ty(0)); spanless_eq_enum!(ForLoopKind; For ForAwait); -spanless_eq_enum!(ForeignItemKind; Static(0 1 2) Fn(0) TyAlias(0) MacCall(0)); +spanless_eq_enum!(ForeignItemKind; Static(0) Fn(0) TyAlias(0) MacCall(0)); spanless_eq_enum!(FormatAlignment; Left Right Center); spanless_eq_enum!(FormatArgPositionKind; Implicit Number Named); spanless_eq_enum!(FormatArgsPiece; Literal(0) Placeholder(0)); @@ -566,11 +595,11 @@ spanless_eq_enum!(FormatTrait; Display Debug LowerExp UpperExp Octal Pointer Binary LowerHex UpperHex); spanless_eq_enum!(GenBlockKind; Async Gen AsyncGen); spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0)); -spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0)); -spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0)); -spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty kw_span default)); +spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0) ParenthesizedElided(0)); +spanless_eq_enum!(GenericBound; Trait(0) Outlives(0) Use(0 1)); +spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty span default)); spanless_eq_enum!(ImplPolarity; Positive Negative(0)); -spanless_eq_enum!(Inline; Yes No); +spanless_eq_enum!(Inline; Yes No(had_parse_error)); spanless_eq_enum!(InlineAsmRegOrRegClass; Reg(0) RegClass(0)); spanless_eq_enum!(InlineAsmTemplatePiece; String(0) Placeholder(operand_idx modifier span)); spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128); @@ -580,54 +609,67 @@ spanless_eq_enum!(LocalKind; Decl Init(0) InitElse(0 1)); spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces); spanless_eq_enum!(MatchKind; Prefix Postfix); +spanless_eq_enum!(MetaItemInner; MetaItem(0) Lit(0)); +spanless_eq_enum!(MetaItemKind; Word List(0) NameValue(0)); +spanless_eq_enum!(MgcaDisambiguation; AnonConst Direct); spanless_eq_enum!(ModKind; Loaded(0 1 2) Unloaded); spanless_eq_enum!(Movability; Static Movable); spanless_eq_enum!(Mutability; Mut Not); -spanless_eq_enum!(PatFieldsRest; Rest None); +spanless_eq_enum!(Parens; Yes No); +spanless_eq_enum!(PatFieldsRest; Rest(0) Recovered(0) None); +spanless_eq_enum!(Pinnedness; Not Pinned); spanless_eq_enum!(PreciseCapturingArg; Lifetime(0) Arg(0 1)); spanless_eq_enum!(RangeEnd; Included(0) Excluded); spanless_eq_enum!(RangeLimits; HalfOpen Closed); +spanless_eq_enum!(Recovered; No Yes(0)); +spanless_eq_enum!(Safety; Unsafe(0) Safe(0) Default); spanless_eq_enum!(StmtKind; Let(0) Item(0) Expr(0) Semi(0) Empty MacCall(0)); spanless_eq_enum!(StrStyle; Cooked Raw(0)); spanless_eq_enum!(StructRest; Base(0) Rest(0) None); spanless_eq_enum!(Term; Ty(0) Const(0)); spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2 3)); -spanless_eq_enum!(TraitObjectSyntax; Dyn DynStar None); +spanless_eq_enum!(TraitObjectSyntax; Dyn None); +spanless_eq_enum!(TyPatKind; Range(0 1 2) NotNull Or(0) Err(0)); spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128); spanless_eq_enum!(UnOp; Deref Not Neg); -spanless_eq_enum!(Unsafe; Yes(0) No); +spanless_eq_enum!(UnsafeBinderCastKind; Wrap Unwrap); spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided); -spanless_eq_enum!(UseTreeKind; Simple(0) Nested(0) Glob); +spanless_eq_enum!(UseTreeKind; Simple(0) Nested(items span) Glob); spanless_eq_enum!(VariantData; Struct(fields recovered) Tuple(0 1) Unit(0)); spanless_eq_enum!(VisibilityKind; Public Restricted(path id shorthand) Inherited); -spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0)); +spanless_eq_enum!(WherePredicateKind; BoundPredicate(0) RegionPredicate(0) EqPredicate(0)); +spanless_eq_enum!(YieldKind; Prefix(0) Postfix(0)); +spanless_eq_enum!(AssignOpKind; AddAssign SubAssign MulAssign DivAssign + RemAssign BitXorAssign BitAndAssign BitOrAssign ShlAssign ShrAssign); spanless_eq_enum!(CoroutineKind; Async(span closure_id return_impl_trait_id) Gen(span closure_id return_impl_trait_id) AsyncGen(span closure_id return_impl_trait_id)); spanless_eq_enum!(ExprKind; Array(0) ConstBlock(0) Call(0 1) MethodCall(0) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1) Let(0 1 2 3) If(0 1 2) While(0 1 2) ForLoop(pat iter body label kind) Loop(0 1 2) - Match(0 1 2) Closure(0) Block(0 1) Gen(0 1 2) Await(0 1) TryBlock(0) - Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1 2) Underscore - Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) - InlineAsm(0) OffsetOf(0 1) MacCall(0) Struct(0) Repeat(0 1) Paren(0) Try(0) - Yield(0) Yeet(0) Become(0) IncludedBytes(0) FormatArgs(0) Err(0) Dummy); + Match(0 1 2) Closure(0) Block(0 1) Gen(0 1 2 3) Await(0 1) Use(0 1) + TryBlock(0 1) Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1 2) + Underscore Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) + Ret(0) InlineAsm(0) OffsetOf(0 1) MacCall(0) Struct(0) Repeat(0 1) Paren(0) + Try(0) Yield(0) Yeet(0) Become(0) IncludedBytes(0) FormatArgs(0) + UnsafeBinderCast(0 1 2) Err(0) Dummy); spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr) InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const) Sym(sym) Label(block)); -spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0) Const(0) Fn(0) - Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1) - Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0) - Delegation(0)); +spanless_eq_enum!(ItemKind; ExternCrate(0 1) Use(0) Static(0) Const(0) Fn(0) + Mod(0 1 2) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1 2) Struct(0 1 2) + Union(0 1 2) Trait(0) TraitAlias(0) Impl(0) MacCall(0) MacroDef(0 1) + Delegation(0) DelegationMac(0)); spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0 1) CStr(0 1) Byte(0) Char(0) Int(0 1) Float(0 1) Bool(0) Err(0)); -spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2 3) TupleStruct(0 1 2) - Or(0) Path(0 1) Tuple(0) Box(0) Deref(0) Ref(0 1) Lit(0) Range(0 1 2) - Slice(0) Rest Never Paren(0) MacCall(0) Err(0)); -spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Ref(0 1) BareFn(0) Never - Tup(0) AnonStruct(0 1) AnonUnion(0 1) Path(0 1) TraitObject(0 1) - ImplTrait(0 1 2) Paren(0) Typeof(0) Infer ImplicitSelf MacCall(0) CVarArgs - Pat(0 1) Dummy Err(0)); +spanless_eq_enum!(PatKind; Missing Wild Ident(0 1 2) Struct(0 1 2 3) + TupleStruct(0 1 2) Or(0) Path(0 1) Tuple(0) Box(0) Deref(0) Ref(0 1 2) + Expr(0) Range(0 1 2) Slice(0) Rest Never Guard(0 1) Paren(0) MacCall(0) + Err(0)); +spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Ref(0 1) PinnedRef(0 1) + FnPtr(0) UnsafeBinder(0) Never Tup(0) Path(0 1) TraitObject(0 1) + ImplTrait(0 1) Paren(0) Infer ImplicitSelf MacCall(0) CVarArgs Pat(0 1) + Dummy Err(0)); impl SpanlessEq for Ident { fn eq(&self, other: &Self) -> bool { @@ -679,17 +721,6 @@ TokenKind::DotDotEq | TokenKind::DotDotDot => true, _ => false, }, - (TokenKind::Interpolated(this), TokenKind::Interpolated(other)) => { - let (this, this_span) = this.as_ref(); - let (other, other_span) = other.as_ref(); - SpanlessEq::eq(this_span, other_span) - && match (this, other) { - (Nonterminal::NtExpr(this), Nonterminal::NtExpr(other)) => { - SpanlessEq::eq(this, other) - } - _ => this == other, - } - } _ => self == other, } } @@ -697,16 +728,14 @@ impl SpanlessEq for TokenStream { fn eq(&self, other: &Self) -> bool { - let mut this_trees = self.trees(); - let mut other_trees = other.trees(); + let mut this_trees = self.iter(); + let mut other_trees = other.iter(); loop { - let this = match this_trees.next() { - None => return other_trees.next().is_none(), - Some(tree) => tree, + let Some(this) = this_trees.next() else { + return other_trees.next().is_none(); }; - let other = match other_trees.next() { - None => return false, - Some(tree) => tree, + let Some(other) = other_trees.next() else { + return false; }; if SpanlessEq::eq(this, other) { continue; @@ -744,7 +773,7 @@ match trees.next() { Some(TokenTree::Token( Token { - kind: TokenKind::Not, + kind: TokenKind::Bang, span: _, }, _spacing, @@ -752,11 +781,11 @@ _ => return false, } } - let stream = match trees.next() { - Some(TokenTree::Delimited(_span, _spacing, Delimiter::Bracket, stream)) => stream, - _ => return false, + let Some(TokenTree::Delimited(_span, _spacing, Delimiter::Bracket, stream)) = trees.next() + else { + return false; }; - let mut trees = stream.trees(); + let mut trees = stream.iter(); match trees.next() { Some(TokenTree::Token( Token { @@ -794,30 +823,10 @@ Ok(lit) => is_escaped_literal_meta_item_lit(&lit, unescaped), Err(_) => false, }, - Token { - kind: TokenKind::Interpolated(nonterminal), - span: _, - } => match &nonterminal.0 { - Nonterminal::NtExpr(expr) => match &expr.kind { - ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped), - _ => false, - }, - _ => false, - }, _ => false, } } -fn is_escaped_literal_attr_args(value: &AttrArgsEq, unescaped: Symbol) -> bool { - match value { - AttrArgsEq::Ast(expr) => match &expr.kind { - ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped), - _ => false, - }, - AttrArgsEq::Hir(lit) => is_escaped_literal_meta_item_lit(lit, unescaped), - } -} - fn is_escaped_literal_meta_item_lit(lit: &MetaItemLit, unescaped: Symbol) -> bool { match lit { MetaItemLit { @@ -878,9 +887,10 @@ SpanlessEq::eq(&path, &normal2.item.path) && match &normal2.item.args { AttrArgs::Empty | AttrArgs::Delimited(_) => false, - AttrArgs::Eq(_span, value) => { - is_escaped_literal_attr_args(value, *unescaped) - } + AttrArgs::Eq { eq_span: _, expr } => match &expr.kind { + ExprKind::Lit(lit) => is_escaped_lit(lit, *unescaped), + _ => false, + }, } } (AttrKind::Normal(_), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self), diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,28 +1,6 @@ #![allow(dead_code)] #![allow(clippy::module_name_repetitions, clippy::shadow_unrelated)] -use rayon::ThreadPoolBuilder; -use std::env; - pub mod eq; pub mod parse; - -/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it. -pub fn abort_after() -> usize { - match env::var("ABORT_AFTER_FAILURE") { - Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"), - Err(_) => usize::MAX, - } -} - -/// Configure Rayon threadpool. -pub fn rayon_init() { - let stack_size = match env::var("RUST_MIN_STACK") { - Ok(s) => s.parse().expect("failed to parse RUST_MIN_STACK"), - Err(_) => 20 * 1024 * 1024, - }; - ThreadPoolBuilder::new() - .stack_size(stack_size) - .build_global() - .unwrap(); -} +pub mod visit; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/parse.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/parse.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/parse.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/parse.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,27 +1,30 @@ extern crate rustc_ast; extern crate rustc_driver; extern crate rustc_expand; -extern crate rustc_parse as parse; +extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; use rustc_ast::ast; -use rustc_ast::ptr::P; +use rustc_parse::lexer::StripTokens; use rustc_session::parse::ParseSess; use rustc_span::FileName; use std::panic; -pub fn librustc_expr(input: &str) -> Option> { +pub fn librustc_expr(input: &str) -> Option> { match panic::catch_unwind(|| { let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(); let sess = ParseSess::new(locale_resources); - let e = parse::new_parser_from_source_str( + let name = FileName::Custom("test_precedence".to_string()); + let mut parser = rustc_parse::new_parser_from_source_str( &sess, - FileName::Custom("test_precedence".to_string()), + name, input.to_string(), + StripTokens::ShebangAndFrontmatter, ) - .parse_expr(); - match e { + .unwrap(); + let presult = parser.parse_expr(); + match presult { Ok(expr) => Some(expr), Err(diagnostic) => { diagnostic.emit(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/visit.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/visit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/common/visit.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/common/visit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,119 @@ +use proc_macro2::{Delimiter, Group, TokenStream, TokenTree}; +use std::mem; +use syn::visit_mut::{self, VisitMut}; +use syn::{Expr, File, Generics, LifetimeParam, MacroDelimiter, Stmt, StmtMacro, TypeParam}; + +pub struct FlattenParens { + discard_paren_attrs: bool, +} + +impl FlattenParens { + pub fn discard_attrs() -> Self { + FlattenParens { + discard_paren_attrs: true, + } + } + + pub fn combine_attrs() -> Self { + FlattenParens { + discard_paren_attrs: false, + } + } + + pub fn visit_token_stream_mut(tokens: &mut TokenStream) { + *tokens = mem::take(tokens) + .into_iter() + .flat_map(|tt| { + if let TokenTree::Group(group) = tt { + let delimiter = group.delimiter(); + let mut content = group.stream(); + Self::visit_token_stream_mut(&mut content); + if let Delimiter::Parenthesis = delimiter { + content + } else { + TokenStream::from(TokenTree::Group(Group::new(delimiter, content))) + } + } else { + TokenStream::from(tt) + } + }) + .collect(); + } +} + +impl VisitMut for FlattenParens { + fn visit_expr_mut(&mut self, e: &mut Expr) { + while let Expr::Paren(paren) = e { + let paren_attrs = mem::take(&mut paren.attrs); + *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER); + if !paren_attrs.is_empty() && !self.discard_paren_attrs { + let nested_attrs = match e { + Expr::Assign(e) => &mut e.attrs, + Expr::Binary(e) => &mut e.attrs, + Expr::Cast(e) => &mut e.attrs, + _ => unimplemented!(), + }; + assert!(nested_attrs.is_empty()); + *nested_attrs = paren_attrs; + } + } + visit_mut::visit_expr_mut(self, e); + } +} + +pub struct AsIfPrinted; + +impl VisitMut for AsIfPrinted { + fn visit_file_mut(&mut self, file: &mut File) { + file.shebang = None; + visit_mut::visit_file_mut(self, file); + } + + fn visit_generics_mut(&mut self, generics: &mut Generics) { + if generics.params.is_empty() { + generics.lt_token = None; + generics.gt_token = None; + } + if let Some(where_clause) = &generics.where_clause { + if where_clause.predicates.is_empty() { + generics.where_clause = None; + } + } + visit_mut::visit_generics_mut(self, generics); + } + + fn visit_lifetime_param_mut(&mut self, param: &mut LifetimeParam) { + if param.bounds.is_empty() { + param.colon_token = None; + } + visit_mut::visit_lifetime_param_mut(self, param); + } + + fn visit_stmt_mut(&mut self, stmt: &mut Stmt) { + if let Stmt::Expr(expr, semi) = stmt { + if let Expr::Macro(e) = expr { + if match e.mac.delimiter { + MacroDelimiter::Brace(_) => true, + MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => semi.is_some(), + } { + let Expr::Macro(expr) = mem::replace(expr, Expr::PLACEHOLDER) else { + unreachable!(); + }; + *stmt = Stmt::Macro(StmtMacro { + attrs: expr.attrs, + mac: expr.mac, + semi_token: *semi, + }); + } + } + } + visit_mut::visit_stmt_mut(self, stmt); + } + + fn visit_type_param_mut(&mut self, param: &mut TypeParam) { + if param.bounds.is_empty() { + param.colon_token = None; + } + visit_mut::visit_type_param_mut(self, param); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/debug/gen.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/gen.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/debug/gen.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/gen.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ // This file is @generated by syn-internal-codegen. // It is not intended for manual editing. -#![allow(repr_transparent_external_private_fields)] +#![allow(repr_transparent_non_zst_fields)] #![allow(clippy::match_wildcard_for_single_variants)] use super::{Lite, Present}; use ref_cast::RefCast; @@ -314,6 +314,27 @@ formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::CapturedParam::Lifetime(_val) => { + formatter.write_str("CapturedParam::Lifetime")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::CapturedParam::Ident(_val) => { + formatter.write_str("CapturedParam::Ident")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + _ => unreachable!(), + } + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ConstParam"); @@ -856,6 +877,15 @@ } formatter.finish() } + syn::Expr::RawAddr(_val) => { + let mut formatter = formatter.debug_struct("Expr::RawAddr"); + if !_val.attrs.is_empty() { + formatter.field("attrs", Lite(&_val.attrs)); + } + formatter.field("mutability", Lite(&_val.mutability)); + formatter.field("expr", Lite(&_val.expr)); + formatter.finish() + } syn::Expr::Reference(_val) => { let mut formatter = formatter.debug_struct("Expr::Reference"); if !_val.attrs.is_empty() { @@ -1513,6 +1543,17 @@ formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ExprRawAddr"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("mutability", Lite(&self.value.mutability)); + formatter.field("expr", Lite(&self.value.expr)); + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprReference"); @@ -3532,6 +3573,29 @@ formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::PointerMutability::Const(_val) => { + formatter.write_str("PointerMutability::Const")?; + Ok(()) + } + syn::PointerMutability::Mut(_val) => { + formatter.write_str("PointerMutability::Mut")?; + Ok(()) + } + } + } +} +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("PreciseCapture"); + if !self.value.params.is_empty() { + formatter.field("params", Lite(&self.value.params)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateLifetime"); @@ -4354,6 +4418,13 @@ formatter.field("ident", Lite(&_val.ident)); formatter.finish() } + syn::TypeParamBound::PreciseCapture(_val) => { + formatter.write_str("TypeParamBound::PreciseCapture")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } syn::TypeParamBound::Verbatim(_val) => { formatter.write_str("TypeParamBound::Verbatim")?; formatter.write_str("(`")?; @@ -5011,6 +5082,11 @@ formatter.write_str("Token![->]") } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Token![raw]") + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![ref]") diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/debug/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/debug/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/debug/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -82,7 +82,7 @@ } } -impl<'a, T> Debug for Lite<&'a T> +impl Debug for Lite<&T> where Lite: Debug, { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/macros/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/macros/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/macros/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/macros/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,3 @@ -#![allow(unused_macros, unused_macro_rules)] - -#[path = "../debug/mod.rs"] -pub mod debug; - -use std::str::FromStr; -use syn::parse::Result; - macro_rules! errorf { ($($tt:tt)*) => {{ use ::std::io::Write; @@ -13,81 +5,3 @@ write!(stderr.lock(), $($tt)*).unwrap(); }}; } - -macro_rules! punctuated { - ($($e:expr,)+) => {{ - let mut seq = ::syn::punctuated::Punctuated::new(); - $( - seq.push($e); - )+ - seq - }}; - - ($($e:expr),+) => { - punctuated!($($e,)+) - }; -} - -macro_rules! snapshot { - ($($args:tt)*) => { - snapshot_impl!(() $($args)*) - }; -} - -macro_rules! snapshot_impl { - (($expr:ident) as $t:ty, @$snapshot:literal) => { - let tokens = crate::macros::TryIntoTokens::try_into_tokens($expr).unwrap(); - let $expr: $t = syn::parse_quote!(#tokens); - let debug = crate::macros::debug::Lite(&$expr); - if !cfg!(miri) { - #[allow(clippy::needless_raw_string_hashes)] // https://github.com/mitsuhiko/insta/issues/389 - { - insta::assert_debug_snapshot!(debug, @$snapshot); - } - } - }; - (($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{ - let tokens = crate::macros::TryIntoTokens::try_into_tokens($($expr)*).unwrap(); - let syntax_tree: $t = syn::parse_quote!(#tokens); - let debug = crate::macros::debug::Lite(&syntax_tree); - if !cfg!(miri) { - #[allow(clippy::needless_raw_string_hashes)] - { - insta::assert_debug_snapshot!(debug, @$snapshot); - } - } - syntax_tree - }}; - (($($expr:tt)*) , @$snapshot:literal) => {{ - let syntax_tree = $($expr)*; - let debug = crate::macros::debug::Lite(&syntax_tree); - if !cfg!(miri) { - #[allow(clippy::needless_raw_string_hashes)] - { - insta::assert_debug_snapshot!(debug, @$snapshot); - } - } - syntax_tree - }}; - (($($expr:tt)*) $next:tt $($rest:tt)*) => { - snapshot_impl!(($($expr)* $next) $($rest)*) - }; -} - -pub trait TryIntoTokens { - #[allow(dead_code)] - fn try_into_tokens(self) -> Result; -} - -impl<'a> TryIntoTokens for &'a str { - fn try_into_tokens(self) -> Result { - let tokens = proc_macro2::TokenStream::from_str(self)?; - Ok(tokens) - } -} - -impl TryIntoTokens for proc_macro2::TokenStream { - fn try_into_tokens(self) -> Result { - Ok(self) - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/repo/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/repo/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/repo/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/repo/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,56 +6,290 @@ use anyhow::Result; use flate2::read::GzDecoder; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use rayon::ThreadPoolBuilder; use std::collections::BTreeSet; +use std::env; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; use tar::Archive; use walkdir::{DirEntry, WalkDir}; -const REVISION: &str = "b10cfcd65fd7f7b1ab9beb34798b2108de003452"; +// nightly-2025-08-14 +const REVISION: &str = "3672a55b7cfd0a12e7097197b6242872473ffaa7"; #[rustfmt::skip] static EXCLUDE_FILES: &[&str] = &[ - // TODO: explicit tail calls: `become _g()` - // https://github.com/dtolnay/syn/issues/1501 - "tests/ui/explicit-tail-calls/return-lifetime-sub.rs", - - // TODO: non-lifetime binders: `where for<'a, T> &'a Struct: Trait` - // https://github.com/dtolnay/syn/issues/1435 - "src/tools/rustfmt/tests/source/issue_5721.rs", - "src/tools/rustfmt/tests/source/non-lifetime-binders.rs", - "src/tools/rustfmt/tests/target/issue_5721.rs", - "src/tools/rustfmt/tests/target/non-lifetime-binders.rs", - "tests/rustdoc-json/non_lifetime_binders.rs", - "tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs", - "tests/rustdoc/non_lifetime_binders.rs", + // TODO: const traits: `pub const trait Trait {}` + // https://github.com/dtolnay/syn/issues/1887 + "src/tools/clippy/tests/ui/assign_ops.rs", + "src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.rs", + "src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs", + "src/tools/rust-analyzer/crates/test-utils/src/minicore.rs", + + // TODO: unsafe binders: `unsafe<'a> &'a T` + // https://github.com/dtolnay/syn/issues/1791 + "src/tools/rustfmt/tests/source/unsafe-binders.rs", + "src/tools/rustfmt/tests/target/unsafe-binders.rs", + "tests/mir-opt/gvn_on_unsafe_binder.rs", + "tests/rustdoc/auxiliary/unsafe-binder-dep.rs", + "tests/rustdoc/unsafe-binder.rs", + "tests/ui/unsafe-binders/cat-projection.rs", + + // TODO: unsafe fields: `struct S { unsafe field: T }` + // https://github.com/dtolnay/syn/issues/1792 + "src/tools/clippy/tests/ui/derive.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs", + "src/tools/rustfmt/tests/source/unsafe-field.rs", + "src/tools/rustfmt/tests/target/unsafe-field.rs", + "tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs", + + // TODO: guard patterns: `match expr { (A if f()) | (B if g()) => {} }` + // https://github.com/dtolnay/syn/issues/1793 + "src/tools/rustfmt/tests/target/guard_patterns.rs", + "tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs", + + // TODO: struct field default: `struct S { field: i32 = 1 }` + // https://github.com/dtolnay/syn/issues/1774 + "compiler/rustc_errors/src/markdown/parse.rs", + "compiler/rustc_session/src/config.rs", + "src/tools/clippy/tests/ui/exhaustive_items.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_default_values.rs", + "src/tools/rustfmt/tests/source/default-field-values.rs", + "src/tools/rustfmt/tests/target/default-field-values.rs", + "tests/ui/structs/default-field-values/auxiliary/struct_field_default.rs", + "tests/ui/structs/default-field-values/const-trait-default-field-value.rs", + "tests/ui/structs/default-field-values/field-references-param.rs", + "tests/ui/structs/default-field-values/support.rs", + "tests/ui/structs/default-field-values/use-normalized-ty-for-default-struct-value.rs", - // TODO: return type notation: `where T: Trait` + // TODO: return type notation: `where T: Trait` and `where T::method(..): Send` // https://github.com/dtolnay/syn/issues/1434 - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs", + "src/tools/rustfmt/tests/target/return-type-notation.rs", + "tests/rustdoc-json/return-type-notation.rs", + "tests/rustdoc/return-type-notation.rs", + "tests/ui/associated-type-bounds/all-generics-lookup.rs", + "tests/ui/associated-type-bounds/implied-from-self-where-clause.rs", "tests/ui/associated-type-bounds/return-type-notation/basic.rs", + "tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs", + "tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs", + "tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs", + "tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs", + "tests/ui/associated-type-bounds/return-type-notation/path-works.rs", + "tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs", + "tests/ui/async-await/return-type-notation/issue-110963-late.rs", + "tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs", + "tests/ui/async-await/return-type-notation/rtn-implied-in-supertrait.rs", + "tests/ui/async-await/return-type-notation/super-method-bound.rs", + "tests/ui/async-await/return-type-notation/supertrait-bound.rs", + "tests/ui/borrowck/alias-liveness/rtn-static.rs", "tests/ui/feature-gates/feature-gate-return_type_notation.rs", // TODO: lazy type alias syntax with where-clause in trailing position // https://github.com/dtolnay/syn/issues/1525 + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause.rs", + "src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs", + "src/tools/rustfmt/tests/source/type-alias-where-clauses.rs", + "src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs", + "src/tools/rustfmt/tests/target/type-alias-where-clauses.rs", "tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs", // TODO: gen blocks and functions // https://github.com/dtolnay/syn/issues/1526 "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", + "compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs", + "compiler/rustc_metadata/src/rmeta/decoder.rs", + "compiler/rustc_middle/src/ty/closure.rs", + "compiler/rustc_middle/src/ty/context.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/gen_blocks.rs", + "tests/ui/async-await/async-drop/assign-incompatible-types.rs", + "tests/ui/coroutine/async-gen-deduce-yield.rs", + "tests/ui/coroutine/async-gen-yield-ty-is-unit.rs", + "tests/ui/coroutine/async_gen_fn_iter.rs", + "tests/ui/coroutine/gen_block_is_fused_iter.rs", "tests/ui/coroutine/gen_block_is_iter.rs", "tests/ui/coroutine/gen_block_iterate.rs", + "tests/ui/coroutine/gen_fn_iter.rs", + "tests/ui/coroutine/gen_fn_lifetime_capture.rs", + "tests/ui/coroutine/other-attribute-on-gen.rs", + "tests/ui/coroutine/return-types-diverge.rs", + "tests/ui/higher-ranked/builtin-closure-like-bounds.rs", + "tests/ui/sanitizer/cfi/coroutine.rs", + + // TODO: postfix yield + // https://github.com/dtolnay/syn/issues/1890 + "tests/pretty/postfix-yield.rs", + "tests/ui/coroutine/postfix-yield.rs", + + // TODO: `!` as a pattern + // https://github.com/dtolnay/syn/issues/1546 + "tests/mir-opt/building/match/never_patterns.rs", + "tests/pretty/never-pattern.rs", + "tests/ui/rfcs/rfc-0000-never_patterns/always-read-in-closure-capture.rs", + "tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs", + "tests/ui/rfcs/rfc-0000-never_patterns/use-bindings.rs", + + // TODO: async trait bounds: `impl async Fn()` + // https://github.com/dtolnay/syn/issues/1628 + "src/tools/miri/tests/pass/async-closure-captures.rs", + "src/tools/miri/tests/pass/async-closure-drop.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_binder_bound.rs", + "src/tools/rustfmt/tests/target/asyncness.rs", + "tests/coverage/async_closure.rs", + "tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs", + "tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs", + "tests/ui/async-await/async-closures/auxiliary/foreign.rs", + "tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs", + "tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs", + "tests/ui/async-await/async-closures/brand.rs", + "tests/ui/async-await/async-closures/captures.rs", + "tests/ui/async-await/async-closures/clone-closure.rs", + "tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs", + "tests/ui/async-await/async-closures/debuginfo-by-move-body.rs", + "tests/ui/async-await/async-closures/drop.rs", + "tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs", + "tests/ui/async-await/async-closures/foreign.rs", + "tests/ui/async-await/async-closures/inline-body.rs", + "tests/ui/async-await/async-closures/mangle.rs", + "tests/ui/async-await/async-closures/moro-example.rs", + "tests/ui/async-await/async-closures/move-is-async-fn.rs", + "tests/ui/async-await/async-closures/mut-ref-reborrow.rs", + "tests/ui/async-await/async-closures/no-borrow-from-env.rs", + "tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs", + "tests/ui/async-await/async-closures/overlapping-projs.rs", + "tests/ui/async-await/async-closures/precise-captures.rs", + "tests/ui/async-await/async-closures/refd.rs", + "tests/ui/async-await/async-closures/signature-deduction.rs", + "tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs", + "tests/ui/async-await/async-fn/higher-ranked-async-fn.rs", + "tests/ui/async-await/async-fn/impl-trait.rs", + "tests/ui/async-await/async-fn/project.rs", + "tests/ui/async-await/async-fn/sugar.rs", + + // TODO: mutable by-reference bindings (mut ref) + // https://github.com/dtolnay/syn/issues/1629 + "src/tools/rustfmt/tests/source/mut_ref.rs", + "src/tools/rustfmt/tests/target/mut_ref.rs", + "tests/ui/mut/mut-ref.rs", + + // TODO: postfix match + // https://github.com/dtolnay/syn/issues/1630 + "src/tools/clippy/tests/ui/unnecessary_semicolon.rs", + "src/tools/rustfmt/tests/source/postfix-match/pf-match.rs", + "src/tools/rustfmt/tests/target/postfix-match/pf-match.rs", + "tests/pretty/postfix-match/simple-matches.rs", + "tests/ui/match/postfix-match/no-unused-parens.rs", + "tests/ui/match/postfix-match/pf-match-chain.rs", + "tests/ui/match/postfix-match/postfix-match.rs", + + // TODO: delegation: `reuse Trait::bar { Box::new(self.0) }` + // https://github.com/dtolnay/syn/issues/1580 + "tests/pretty/delegation.rs", + "tests/pretty/hir-delegation.rs", + "tests/ui/delegation/body-identity-glob.rs", + "tests/ui/delegation/body-identity-list.rs", + "tests/ui/delegation/explicit-paths-in-traits-pass.rs", + "tests/ui/delegation/explicit-paths-pass.rs", + "tests/ui/delegation/explicit-paths-signature-pass.rs", + "tests/ui/delegation/fn-header.rs", + "tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs", + "tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs", + "tests/ui/delegation/generics/impl-to-free-fn-pass.rs", + "tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs", + "tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs", + "tests/ui/delegation/generics/trait-method-to-other-pass.rs", + "tests/ui/delegation/glob-glob.rs", + "tests/ui/delegation/glob-override.rs", + "tests/ui/delegation/glob.rs", + "tests/ui/delegation/impl-trait.rs", + "tests/ui/delegation/list.rs", + "tests/ui/delegation/macro-inside-glob.rs", + "tests/ui/delegation/macro-inside-list.rs", + "tests/ui/delegation/method-call-priority.rs", + "tests/ui/delegation/parse.rs", + "tests/ui/delegation/rename.rs", + "tests/ui/delegation/self-coercion.rs", + + // TODO: for await + // https://github.com/dtolnay/syn/issues/1631 + "tests/ui/async-await/for-await-2015.rs", + "tests/ui/async-await/for-await-passthrough.rs", + "tests/ui/async-await/for-await.rs", + + // TODO: unparenthesized half-open range pattern inside slice pattern: `[1..]` + // https://github.com/dtolnay/syn/issues/1769 + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/range_pat.rs", + "tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs", - // TODO: struct literal in match guard - // https://github.com/dtolnay/syn/issues/1527 - "tests/ui/parser/struct-literal-in-match-guard.rs", + // TODO: pinned type sugar: `&pin const Self` + // https://github.com/dtolnay/syn/issues/1770 + "src/tools/rustfmt/tests/source/pin_sugar.rs", + "src/tools/rustfmt/tests/target/pin_sugar.rs", + "tests/pretty/pin-ergonomics-hir.rs", + "tests/pretty/pin-ergonomics.rs", + "tests/ui/pin-ergonomics/borrow.rs", + "tests/ui/pin-ergonomics/sugar-self.rs", + "tests/ui/pin-ergonomics/sugar.rs", + + // TODO: attributes on where-predicates + // https://github.com/dtolnay/syn/issues/1705 + "src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs", + + // TODO: super let + // https://github.com/dtolnay/syn/issues/1889 + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt.rs", + + // TODO: "ergonomic clones": `f(obj.use)`, `thread::spawn(use || f(obj))`, `async use` + // https://github.com/dtolnay/syn/issues/1802 + "tests/codegen-llvm/ergonomic-clones/closure.rs", + "tests/mir-opt/ergonomic-clones/closure.rs", + "tests/ui/ergonomic-clones/async/basic.rs", + "tests/ui/ergonomic-clones/closure/basic.rs", + "tests/ui/ergonomic-clones/closure/const-closure.rs", + "tests/ui/ergonomic-clones/closure/mutation.rs", + "tests/ui/ergonomic-clones/closure/nested.rs", + "tests/ui/ergonomic-clones/closure/once-move-out-on-heap.rs", + "tests/ui/ergonomic-clones/closure/with-binders.rs", + "tests/ui/ergonomic-clones/dotuse/basic.rs", + "tests/ui/ergonomic-clones/dotuse/block.rs", + + // TODO: contracts + // https://github.com/dtolnay/syn/issues/1892 + "tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs", + "tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs", + "tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs", + "tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs", + + // TODO: frontmatter + // https://github.com/dtolnay/syn/issues/1893 + "tests/ui/frontmatter/auxiliary/lib.rs", + "tests/ui/frontmatter/dot-in-infostring-non-leading.rs", + "tests/ui/frontmatter/escape.rs", + "tests/ui/frontmatter/frontmatter-inner-hyphens-1.rs", + "tests/ui/frontmatter/frontmatter-inner-hyphens-2.rs", + "tests/ui/frontmatter/frontmatter-non-lexible-tokens.rs", + "tests/ui/frontmatter/frontmatter-whitespace-3.rs", + "tests/ui/frontmatter/frontmatter-whitespace-4.rs", + "tests/ui/frontmatter/shebang.rs", + "tests/ui/unpretty/frontmatter.rs", + + // TODO: `|| .. .method()` + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_range_method_call.rs", + "src/tools/rustfmt/tests/source/issue-4808.rs", + + // Negative inherent impl: `impl !Box {}` + "src/tools/rustfmt/tests/source/negative-impl.rs", + "src/tools/rustfmt/tests/target/negative-impl.rs", - // Compile-fail expr parameter in const generic position: f::<1 + 2>() + // Compile-fail expr parameter in const generic position: `f::<1 + 2>()` "tests/ui/const-generics/early/closing-args-token.rs", "tests/ui/const-generics/early/const-expression-parameter.rs", // Compile-fail variadics in not the last position of a function parameter list + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_def_param.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_vararg.rs", "tests/ui/parser/variadic-ffi-syntactic-pass.rs", // Need at least one trait in impl Trait, no such type as impl 'static @@ -63,20 +297,24 @@ // Negative polarity trait bound: `where T: !Copy` "src/tools/rustfmt/tests/target/negative-bounds.rs", - - // Lifetime bound inside for<>: `T: ~const ?for<'a: 'b> Trait<'a>` - "tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs", + "tests/ui/traits/negative-bounds/supertrait.rs", // Const impl that is not a trait impl: `impl ~const T {}` - "tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs", + "tests/ui/traits/const-traits/syntax.rs", + + // Lifetimes and types out of order in angle bracketed path arguments + "tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs", // Deprecated anonymous parameter syntax in traits "src/tools/rustfmt/tests/source/trait.rs", "src/tools/rustfmt/tests/target/trait.rs", - "tests/ui/issues/issue-13105.rs", - "tests/ui/issues/issue-13775.rs", + "tests/pretty/hir-fn-params.rs", + "tests/rustdoc/anon-fn-params.rs", + "tests/rustdoc/auxiliary/ext-anon-fn-params.rs", + "tests/ui/fn/anonymous-parameters-trait-13105.rs", "tests/ui/issues/issue-34074.rs", "tests/ui/proc-macro/trait-fn-args-2015.rs", + "tests/ui/trait-bounds/anonymous-parameters-13775.rs", // Deprecated where-clause location "src/tools/rustfmt/tests/source/issue_4257.rs", @@ -87,10 +325,8 @@ "tests/rustdoc/generic-associated-types/gats.rs", // Deprecated trait object syntax with parenthesized generic arguments and no dyn keyword - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rs", "src/tools/rustfmt/tests/source/attrib.rs", "src/tools/rustfmt/tests/source/closure.rs", "src/tools/rustfmt/tests/source/existential_type.rs", @@ -115,25 +351,21 @@ "tests/pretty/closure-reform-pretty.rs", "tests/run-make/reproducible-build-2/reproducible-build.rs", "tests/run-make/reproducible-build/reproducible-build.rs", - "tests/ui/auxiliary/typeid-intrinsic-aux1.rs", - "tests/ui/auxiliary/typeid-intrinsic-aux2.rs", "tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs", "tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs", "tests/ui/lifetimes/bare-trait-object-borrowck.rs", "tests/ui/lifetimes/bare-trait-object.rs", "tests/ui/parser/bounds-obj-parens.rs", - // Invalid unparenthesized range pattern inside slice pattern: `[1..]` - "tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs", - // Various extensions to Rust syntax made up by rust-analyzer - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0131_existential_type.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_path.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/global_asm.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_abs_star.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0015_use_tree.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0029_range_forms.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs", @@ -143,19 +375,25 @@ "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0038_endless_inclusive_range.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs", + "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs", + "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs", + "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs", + "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs", + "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs", // Placeholder syntax for "throw expressions" "compiler/rustc_errors/src/translation.rs", + "compiler/rustc_expand/src/module.rs", + "compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs", "src/tools/clippy/tests/ui/needless_return.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yeet_expr.rs", "tests/pretty/yeet-expr.rs", "tests/ui/try-trait/yeet-for-option.rs", "tests/ui/try-trait/yeet-for-result.rs", // Edition 2015 code using identifiers that are now keywords // TODO: some of these we should probably parse - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rs", - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rs", + "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dyn_trait_type_weak.rs", "src/tools/rustfmt/tests/source/configs/indent_style/block_call.rs", "src/tools/rustfmt/tests/source/configs/use_try_shorthand/false.rs", "src/tools/rustfmt/tests/source/configs/use_try_shorthand/true.rs", @@ -168,6 +406,7 @@ "tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs", "tests/ui/editions/edition-keywords-2015-2015.rs", "tests/ui/editions/edition-keywords-2015-2018.rs", + "tests/ui/lint/keyword-idents/auxiliary/multi_file_submod.rs", "tests/ui/lint/lint_pre_expansion_extern_module_aux.rs", "tests/ui/macros/macro-comma-support-rpass.rs", "tests/ui/macros/try-macro.rs", @@ -178,9 +417,12 @@ "tests/ui/issues/issue-74564-if-expr-stack-overflow.rs", // Testing tools on invalid syntax + "src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs", "src/tools/rustfmt/tests/coverage/target/comments.rs", "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs", "src/tools/rustfmt/tests/parser/issue_4418.rs", + "src/tools/rustfmt/tests/parser/stashed-diag.rs", + "src/tools/rustfmt/tests/parser/stashed-diag2.rs", "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs", "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs", "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs", @@ -189,15 +431,13 @@ "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs", "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs", "src/tools/rustfmt/tests/target/type.rs", + "src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs", "tests/run-make/translation/test.rs", "tests/ui/generics/issue-94432-garbage-ice.rs", // Generated file containing a top-level expression, used with `include!` "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", - // Clippy lint lists represented as expressions - "src/tools/clippy/clippy_lints/src/lib.deprecated.rs", - // Not actually test cases "tests/ui/lint/expansion-time-include.rs", "tests/ui/macros/auxiliary/macro-comma-support.rs", @@ -219,6 +459,9 @@ // Inputs that used to crash rust-analyzer, but aren't necessarily supposed to parse "src/tools/rust-analyzer/crates/syntax/test_data/parser/fuzz-failures", "src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures", + + // Inputs that crash rustc, making no claim about whether they are valid Rust + "tests/crashes", ]; // Directories in which a .stderr implies the corresponding .rs is not expected @@ -292,6 +535,25 @@ } } +#[allow(dead_code)] +pub fn abort_after() -> usize { + match env::var("ABORT_AFTER_FAILURE") { + Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"), + Err(_) => usize::MAX, + } +} + +pub fn rayon_init() { + let stack_size = match env::var("RUST_MIN_STACK") { + Ok(s) => s.parse().expect("failed to parse RUST_MIN_STACK"), + Err(_) => 1024 * 1024 * if cfg!(debug_assertions) { 40 } else { 20 }, + }; + ThreadPoolBuilder::new() + .stack_size(stack_size) + .build_global() + .unwrap(); +} + pub fn clone_rust() { let needs_clone = match fs::read_to_string("tests/rust/COMMIT") { Err(_) => true, @@ -338,10 +600,9 @@ } fn download_and_unpack() -> Result<()> { - let url = format!( - "https://github.com/rust-lang/rust/archive/{}.tar.gz", - REVISION - ); + let url = format!("https://github.com/rust-lang/rust/archive/{REVISION}.tar.gz"); + errorf!("downloading {url}\n"); + let response = reqwest::blocking::get(url)?.error_for_status()?; let progress = Progress::new(response); let decoder = GzDecoder::new(progress); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/snapshot/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/snapshot/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/snapshot/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/snapshot/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,68 @@ +#![allow(unused_macros, unused_macro_rules)] + +use std::str::FromStr; +use syn::parse::Result; + +macro_rules! snapshot { + ($($args:tt)*) => { + snapshot_impl!(() $($args)*) + }; +} + +macro_rules! snapshot_impl { + (($expr:ident) as $t:ty, @$snapshot:literal) => { + let tokens = crate::snapshot::TryIntoTokens::try_into_tokens($expr).unwrap(); + let $expr: $t = syn::parse_quote!(#tokens); + let debug = crate::debug::Lite(&$expr); + if !cfg!(miri) { + #[allow(clippy::needless_raw_string_hashes)] // https://github.com/mitsuhiko/insta/issues/389 + { + insta::assert_debug_snapshot!(debug, @$snapshot); + } + } + }; + (($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{ + let tokens = crate::snapshot::TryIntoTokens::try_into_tokens($($expr)*).unwrap(); + let syntax_tree: $t = syn::parse_quote!(#tokens); + let debug = crate::debug::Lite(&syntax_tree); + if !cfg!(miri) { + #[allow(clippy::needless_raw_string_hashes)] + { + insta::assert_debug_snapshot!(debug, @$snapshot); + } + } + syntax_tree + }}; + (($($expr:tt)*) , @$snapshot:literal) => {{ + let syntax_tree = $($expr)*; + let debug = crate::debug::Lite(&syntax_tree); + if !cfg!(miri) { + #[allow(clippy::needless_raw_string_hashes)] + { + insta::assert_debug_snapshot!(debug, @$snapshot); + } + } + syntax_tree + }}; + (($($expr:tt)*) $next:tt $($rest:tt)*) => { + snapshot_impl!(($($expr)* $next) $($rest)*) + }; +} + +pub trait TryIntoTokens { + #[allow(dead_code)] + fn try_into_tokens(self) -> Result; +} + +impl TryIntoTokens for &str { + fn try_into_tokens(self) -> Result { + let tokens = proc_macro2::TokenStream::from_str(self)?; + Ok(tokens) + } +} + +impl TryIntoTokens for proc_macro2::TokenStream { + fn try_into_tokens(self) -> Result { + Ok(self) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_asyncness.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_asyncness.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_asyncness.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_asyncness.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use syn::{Expr, Item}; @@ -9,7 +15,7 @@ fn test_async_fn() { let input = "async fn process() {}"; - snapshot!(input as Item, @r###" + snapshot!(input as Item, @r#" Item::Fn { vis: Visibility::Inherited, sig: Signature { @@ -22,14 +28,14 @@ stmts: [], }, } - "###); + "#); } #[test] fn test_async_closure() { let input = "async || {}"; - snapshot!(input as Expr, @r###" + snapshot!(input as Expr, @r#" Expr::Closure { asyncness: Some, output: ReturnType::Default, @@ -39,5 +45,5 @@ }, }, } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_attribute.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_attribute.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_attribute.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_attribute.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use syn::parse::Parser; use syn::{Attribute, Meta}; @@ -10,7 +16,7 @@ fn test_meta_item_word() { let meta = test("#[foo]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::Path { segments: [ PathSegment { @@ -18,14 +24,14 @@ }, ], } - "###); + "#); } #[test] fn test_meta_item_name_value() { let meta = test("#[foo = 5]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::NameValue { path: Path { segments: [ @@ -38,14 +44,14 @@ lit: 5, }, } - "###); + "#); } #[test] fn test_meta_item_bool_value() { let meta = test("#[foo = true]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::NameValue { path: Path { segments: [ @@ -60,11 +66,11 @@ }, }, } - "###); + "#); let meta = test("#[foo = false]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::NameValue { path: Path { segments: [ @@ -79,14 +85,14 @@ }, }, } - "###); + "#); } #[test] fn test_meta_item_list_lit() { let meta = test("#[foo(5)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -98,14 +104,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } - "###); + "#); } #[test] fn test_meta_item_list_word() { let meta = test("#[foo(bar)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -117,14 +123,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar`), } - "###); + "#); } #[test] fn test_meta_item_list_name_value() { let meta = test("#[foo(bar = 5)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -136,14 +142,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar = 5`), } - "###); + "#); } #[test] fn test_meta_item_list_bool_value() { let meta = test("#[foo(bar = true)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -155,14 +161,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar = true`), } - "###); + "#); } #[test] fn test_meta_item_multiple() { let meta = test("#[foo(word, name = 5, list(name2 = 6), word2)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -174,14 +180,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } - "###); + "#); } #[test] fn test_bool_lit() { let meta = test("#[foo(true)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -193,14 +199,14 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`true`), } - "###); + "#); } #[test] fn test_negative_lit() { let meta = test("#[form(min = -1, max = 200)]"); - snapshot!(meta, @r###" + snapshot!(meta, @r#" Meta::List { path: Path { segments: [ @@ -212,7 +218,7 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`min = - 1 , max = 200`), } - "###); + "#); } fn test(input: &str) -> Meta { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_derive_input.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_derive_input.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_derive_input.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_derive_input.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,16 @@ #![allow( clippy::assertions_on_result_states, + clippy::elidable_lifetime_names, clippy::manual_let_else, + clippy::needless_lifetimes, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use quote::quote; use syn::{Data, DeriveInput}; @@ -17,7 +21,7 @@ struct Unit; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "Unit", @@ -27,7 +31,7 @@ semi_token: Some, }, } - "###); + "#); } #[test] @@ -40,7 +44,7 @@ } }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { attrs: [ Attribute { @@ -110,9 +114,9 @@ }, }, } - "###); + "#); - snapshot!(&input.attrs[0].meta, @r###" + snapshot!(&input.attrs[0].meta, @r#" Meta::List { path: Path { segments: [ @@ -124,7 +128,7 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`Debug , Clone`), } - "###); + "#); } #[test] @@ -136,7 +140,7 @@ } }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "MaybeUninit", @@ -177,7 +181,7 @@ }, }, } - "###); + "#); } #[test] @@ -197,7 +201,7 @@ } }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { attrs: [ Attribute { @@ -314,11 +318,11 @@ ], }, } - "###); + "#); let meta_items: Vec<_> = input.attrs.into_iter().map(|attr| attr.meta).collect(); - snapshot!(meta_items, @r###" + snapshot!(meta_items, @r#" [ Meta::NameValue { path: Path { @@ -340,7 +344,7 @@ ], }, ] - "###); + "#); } #[test] @@ -360,7 +364,7 @@ struct S; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { attrs: [ Attribute { @@ -386,9 +390,9 @@ semi_token: Some, }, } - "###); + "#); - snapshot!(&input.attrs[0].meta, @r###" + snapshot!(&input.attrs[0].meta, @r#" Meta::Path { segments: [ PathSegment { @@ -400,7 +404,7 @@ }, ], } - "###); + "#); } #[test] @@ -410,7 +414,7 @@ pub(in m) struct Z(pub(in m::n) u8); }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Restricted { in_token: Some, @@ -457,7 +461,7 @@ semi_token: Some, }, } - "###); + "#); } #[test] @@ -466,7 +470,7 @@ pub(crate) struct S; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Restricted { path: Path { @@ -484,7 +488,7 @@ semi_token: Some, }, } - "###); + "#); } #[test] @@ -493,7 +497,7 @@ pub(super) struct S; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Restricted { path: Path { @@ -511,7 +515,7 @@ semi_token: Some, }, } - "###); + "#); } #[test] @@ -520,7 +524,7 @@ pub(in super) struct S; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Restricted { in_token: Some, @@ -539,7 +543,7 @@ semi_token: Some, }, } - "###); + "#); } #[test] @@ -548,7 +552,7 @@ struct S; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -558,7 +562,7 @@ semi_token: Some, }, } - "###); + "#); let data = match input.data { Data::Struct(data) => data, @@ -577,7 +581,7 @@ } }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -619,14 +623,14 @@ }, }, } - "###); + "#); let data = match input.data { Data::Struct(data) => data, _ => panic!("expected a struct"), }; - snapshot!(data.fields.into_iter().collect::>(), @r###" + snapshot!(data.fields.into_iter().collect::>(), @r#" [ Field { vis: Visibility::Inherited, @@ -657,7 +661,7 @@ }, }, ] - "###); + "#); } #[test] @@ -666,7 +670,7 @@ struct S(i32, pub String); }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -704,14 +708,14 @@ semi_token: Some, }, } - "###); + "#); let data = match input.data { Data::Struct(data) => data, _ => panic!("expected a struct"), }; - snapshot!(data.fields.iter().collect::>(), @r###" + snapshot!(data.fields.iter().collect::>(), @r#" [ Field { vis: Visibility::Inherited, @@ -738,7 +742,7 @@ }, }, ] - "###); + "#); } #[test] @@ -748,7 +752,7 @@ struct S(crate::X); }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -777,5 +781,5 @@ semi_token: Some, }, } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_expr.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_expr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,34 +1,62 @@ -#![allow(clippy::single_element_loop, clippy::uninlined_format_args)] +#![cfg(not(miri))] +#![recursion_limit = "1024"] +#![feature(rustc_private)] +#![allow( + clippy::elidable_lifetime_names, + clippy::match_like_matches_macro, + clippy::needless_lifetimes, + clippy::single_element_loop, + clippy::too_many_lines, + clippy::uninlined_format_args, + clippy::unreadable_literal +)] #[macro_use] mod macros; +#[macro_use] +mod snapshot; + +mod common; +mod debug; -use proc_macro2::{Delimiter, Group}; +use crate::common::visit::{AsIfPrinted, FlattenParens}; +use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream}; use quote::{quote, ToTokens as _}; +use std::process::ExitCode; use syn::punctuated::Punctuated; -use syn::{parse_quote, token, Expr, ExprRange, ExprTuple, Stmt, Token}; +use syn::visit_mut::VisitMut as _; +use syn::{ + parse_quote, token, AngleBracketedGenericArguments, Arm, BinOp, Block, Expr, ExprArray, + ExprAssign, ExprAsync, ExprAwait, ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, + ExprClosure, ExprConst, ExprContinue, ExprField, ExprForLoop, ExprIf, ExprIndex, ExprLet, + ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprPath, ExprRange, ExprRawAddr, + ExprReference, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary, ExprUnsafe, + ExprWhile, ExprYield, GenericArgument, Label, Lifetime, Lit, LitInt, Macro, MacroDelimiter, + Member, Pat, PatWild, Path, PathArguments, PathSegment, PointerMutability, QSelf, RangeLimits, + ReturnType, Stmt, Token, Type, TypePath, UnOp, +}; #[test] fn test_expr_parse() { let tokens = quote!(..100u32); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Range { limits: RangeLimits::HalfOpen, end: Some(Expr::Lit { lit: 100u32, }), } - "###); + "#); let tokens = quote!(..100u32); - snapshot!(tokens as ExprRange, @r###" + snapshot!(tokens as ExprRange, @r#" ExprRange { limits: RangeLimits::HalfOpen, end: Some(Expr::Lit { lit: 100u32, }), } - "###); + "#); } #[test] @@ -36,7 +64,7 @@ // Must not parse as Expr::Field. let tokens = quote!(fut.await); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Await { base: Expr::Path { path: Path { @@ -48,13 +76,13 @@ }, }, } - "###); + "#); } #[rustfmt::skip] #[test] fn test_tuple_multi_index() { - let expected = snapshot!("tuple.0.0" as Expr, @r###" + let expected = snapshot!("tuple.0.0" as Expr, @r#" Expr::Field { base: Expr::Field { base: Expr::Path { @@ -74,7 +102,7 @@ index: 0, }), } - "###); + "#); for &input in &[ "tuple .0.0", @@ -104,7 +132,7 @@ let path = Group::new(Delimiter::None, quote!(f)); let tokens = quote!(#path()); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Call { func: Expr::Group { expr: Expr::Path { @@ -118,12 +146,12 @@ }, }, } - "###); + "#); let path = Group::new(Delimiter::None, quote! { #[inside] f }); let tokens = quote!(#[outside] #path()); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Call { attrs: [ Attribute { @@ -161,7 +189,7 @@ }, }, } - "###); + "#); } #[test] @@ -170,7 +198,7 @@ let mac = Group::new(Delimiter::None, quote!(m)); let tokens = quote!(#mac!()); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Macro { mac: Macro { path: Path { @@ -184,7 +212,7 @@ tokens: TokenStream(``), }, } - "###); + "#); } #[test] @@ -193,7 +221,7 @@ let s = Group::new(Delimiter::None, quote! { S }); let tokens = quote!(#s {}); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Struct { path: Path { segments: [ @@ -203,7 +231,7 @@ ], }, } - "###); + "#); } #[test] @@ -211,7 +239,7 @@ // mimics the token stream corresponding to `$expr.method()` where expr is `&self` let inner = Group::new(Delimiter::None, quote!(&self)); let tokens = quote!(#inner.method()); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::MethodCall { receiver: Expr::Group { expr: Expr::Reference { @@ -228,7 +256,7 @@ }, method: "method", } - "###); + "#); } #[test] @@ -236,7 +264,7 @@ // mimics the token stream corresponding to `match v { _ => $expr }` let expr = Group::new(Delimiter::None, quote! { #[a] () }); let tokens = quote!(match v { _ => #expr }); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Match { expr: Expr::Path { path: Path { @@ -269,11 +297,11 @@ }, ], } - "###); + "#); let expr = Group::new(Delimiter::None, quote!(loop {} + 1)); let tokens = quote!(match v { _ => #expr }); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Match { expr: Expr::Path { path: Path { @@ -303,7 +331,7 @@ }, ], } - "###); + "#); } // https://github.com/dtolnay/syn/issues/1019 @@ -311,7 +339,7 @@ fn test_closure_vs_rangefull() { #[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/4808 let tokens = quote!(|| .. .method()); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::MethodCall { receiver: Expr::Closure { output: ReturnType::Default, @@ -321,7 +349,7 @@ }, method: "method", } - "###); + "#); } #[test] @@ -331,7 +359,7 @@ } #[test] -fn test_ranges() { +fn test_range_kinds() { syn::parse_str::("..").unwrap(); syn::parse_str::("..hi").unwrap(); syn::parse_str::("lo..").unwrap(); @@ -349,6 +377,198 @@ } #[test] +fn test_range_precedence() { + snapshot!(".. .." as Expr, @r#" + Expr::Range { + limits: RangeLimits::HalfOpen, + end: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + } + "#); + + snapshot!(".. .. ()" as Expr, @r#" + Expr::Range { + limits: RangeLimits::HalfOpen, + end: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + end: Some(Expr::Tuple), + }), + } + "#); + + snapshot!("() .. .." as Expr, @r#" + Expr::Range { + start: Some(Expr::Tuple), + limits: RangeLimits::HalfOpen, + end: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + } + "#); + + snapshot!("() = .. + ()" as Expr, @r" + Expr::Binary { + left: Expr::Assign { + left: Expr::Tuple, + right: Expr::Range { + limits: RangeLimits::HalfOpen, + }, + }, + op: BinOp::Add, + right: Expr::Tuple, + } + "); + + // A range with a lower bound cannot be the upper bound of another range, + // and a range with an upper bound cannot be the lower bound of another + // range. + syn::parse_str::(".. x ..").unwrap_err(); + syn::parse_str::("x .. x ..").unwrap_err(); +} + +#[test] +fn test_range_attrs() { + // Attributes are not allowed on range expressions starting with `..` + syn::parse_str::("#[allow()] ..").unwrap_err(); + syn::parse_str::("#[allow()] .. hi").unwrap_err(); + + snapshot!("#[allow()] lo .. hi" as Expr, @r#" + Expr::Range { + start: Some(Expr::Path { + attrs: [ + Attribute { + style: AttrStyle::Outer, + meta: Meta::List { + path: Path { + segments: [ + PathSegment { + ident: "allow", + }, + ], + }, + delimiter: MacroDelimiter::Paren, + tokens: TokenStream(``), + }, + }, + ], + path: Path { + segments: [ + PathSegment { + ident: "lo", + }, + ], + }, + }), + limits: RangeLimits::HalfOpen, + end: Some(Expr::Path { + path: Path { + segments: [ + PathSegment { + ident: "hi", + }, + ], + }, + }), + } + "#); +} + +#[test] +fn test_ranges_bailout() { + syn::parse_str::(".. ?").unwrap_err(); + syn::parse_str::(".. .field").unwrap_err(); + + snapshot!("return .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + } + "); + + snapshot!("break .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Break { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + } + "); + + snapshot!("|| .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Closure { + output: ReturnType::Default, + body: Expr::Range { + limits: RangeLimits::HalfOpen, + }, + }, + } + "); + + snapshot!("return .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + member: Member::Named("field"), + } + "#); + + snapshot!("break .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Break { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + member: Member::Named("field"), + } + "#); + + snapshot!("|| .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Closure { + output: ReturnType::Default, + body: Expr::Range { + limits: RangeLimits::HalfOpen, + }, + }, + member: Member::Named("field"), + } + "#); + + snapshot!("return .. = ()" as Expr, @r" + Expr::Assign { + left: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + right: Expr::Tuple, + } + "); + + snapshot!("return .. += ()" as Expr, @r" + Expr::Binary { + left: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + op: BinOp::AddAssign, + right: Expr::Tuple, + } + "); +} + +#[test] fn test_ambiguous_label() { for stmt in [ quote! { @@ -382,7 +602,7 @@ let path = Group::new(Delimiter::None, quote!(a::b)); let tokens = quote!(if #path {}); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::If { cond: Expr::Group { expr: Expr::Path { @@ -403,10 +623,10 @@ stmts: [], }, } - "###); + "#); let tokens = quote!(#path {}); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Struct { path: Path { segments: [ @@ -420,10 +640,10 @@ ], }, } - "###); + "#); let tokens = quote!(#path :: c); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Path { path: Path { segments: [ @@ -441,11 +661,11 @@ ], }, } - "###); + "#); let nested = Group::new(Delimiter::None, quote!(a::b || true)); let tokens = quote!(if #nested && false {}); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::If { cond: Expr::Binary { left: Expr::Group { @@ -482,7 +702,7 @@ stmts: [], }, } - "###); + "#); } #[test] @@ -496,27 +716,27 @@ expr.elems.push_value(parse_quote!(continue)); // Must not parse to Expr::Paren - snapshot!(expr.to_token_stream() as Expr, @r###" + snapshot!(expr.to_token_stream() as Expr, @r#" Expr::Tuple { elems: [ Expr::Continue, Token![,], ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Expr, @r###" + snapshot!(expr.to_token_stream() as Expr, @r#" Expr::Tuple { elems: [ Expr::Continue, Token![,], ], } - "###); + "#); expr.elems.push_value(parse_quote!(continue)); - snapshot!(expr.to_token_stream() as Expr, @r###" + snapshot!(expr.to_token_stream() as Expr, @r#" Expr::Tuple { elems: [ Expr::Continue, @@ -524,10 +744,10 @@ Expr::Continue, ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Expr, @r###" + snapshot!(expr.to_token_stream() as Expr, @r#" Expr::Tuple { elems: [ Expr::Continue, @@ -536,5 +756,947 @@ Token![,], ], } - "###); + "#); +} + +#[test] +fn test_binop_associativity() { + // Left to right. + snapshot!("() + () + ()" as Expr, @r#" + Expr::Binary { + left: Expr::Binary { + left: Expr::Tuple, + op: BinOp::Add, + right: Expr::Tuple, + }, + op: BinOp::Add, + right: Expr::Tuple, + } + "#); + + // Right to left. + snapshot!("() += () += ()" as Expr, @r#" + Expr::Binary { + left: Expr::Tuple, + op: BinOp::AddAssign, + right: Expr::Binary { + left: Expr::Tuple, + op: BinOp::AddAssign, + right: Expr::Tuple, + }, + } + "#); + + // Parenthesization is required. + syn::parse_str::("() == () == ()").unwrap_err(); +} + +#[test] +fn test_assign_range_precedence() { + // Range has higher precedence as the right-hand of an assignment, but + // ambiguous precedence as the left-hand of an assignment. + snapshot!("() = () .. ()" as Expr, @r#" + Expr::Assign { + left: Expr::Tuple, + right: Expr::Range { + start: Some(Expr::Tuple), + limits: RangeLimits::HalfOpen, + end: Some(Expr::Tuple), + }, + } + "#); + + snapshot!("() += () .. ()" as Expr, @r#" + Expr::Binary { + left: Expr::Tuple, + op: BinOp::AddAssign, + right: Expr::Range { + start: Some(Expr::Tuple), + limits: RangeLimits::HalfOpen, + end: Some(Expr::Tuple), + }, + } + "#); + + syn::parse_str::("() .. () = ()").unwrap_err(); + syn::parse_str::("() .. () += ()").unwrap_err(); +} + +#[test] +fn test_chained_comparison() { + // https://github.com/dtolnay/syn/issues/1738 + let _ = syn::parse_str::("a = a < a <"); + let _ = syn::parse_str::("a = a .. a .."); + let _ = syn::parse_str::("a = a .. a +="); + + let err = syn::parse_str::("a < a < a").unwrap_err(); + assert_eq!("comparison operators cannot be chained", err.to_string()); + + let err = syn::parse_str::("a .. a .. a").unwrap_err(); + assert_eq!("unexpected token", err.to_string()); + + let err = syn::parse_str::("a .. a += a").unwrap_err(); + assert_eq!("unexpected token", err.to_string()); +} + +#[test] +fn test_fixup() { + for tokens in [ + quote! { 2 * (1 + 1) }, + quote! { 0 + (0 + 0) }, + quote! { (a = b) = c }, + quote! { (x as i32) < 0 }, + quote! { 1 + (x as i32) < 0 }, + quote! { (1 + 1).abs() }, + quote! { (lo..hi)[..] }, + quote! { (a..b)..(c..d) }, + quote! { (x > ..) > x }, + quote! { (&mut fut).await }, + quote! { &mut (x as i32) }, + quote! { -(x as i32) }, + quote! { if (S {}) == 1 {} }, + quote! { { (m! {}) - 1 } }, + quote! { match m { _ => ({}) - 1 } }, + quote! { if let _ = (a && b) && c {} }, + quote! { if let _ = (S {}) {} }, + quote! { if (S {}) == 0 && let Some(_) = x {} }, + quote! { break ('a: loop { break 'a 1 } + 1) }, + quote! { a + (|| b) + c }, + quote! { if let _ = ((break) - 1 || true) {} }, + quote! { if let _ = (break + 1 || true) {} }, + quote! { if break (break) {} }, + quote! { if break break {} {} }, + quote! { if return (..) {} }, + quote! { if return .. {} {} }, + quote! { if || (Struct {}) {} }, + quote! { if || (Struct {}).await {} }, + quote! { if break || Struct {}.await {} }, + quote! { if break 'outer 'block: {} {} }, + quote! { if ..'block: {} {} }, + quote! { if break ({}).await {} }, + quote! { (break)() }, + quote! { (..) = () }, + quote! { (..) += () }, + quote! { (1 < 2) == (3 < 4) }, + quote! { { (let _ = ()) } }, + quote! { (#[attr] thing).field }, + quote! { #[attr] (1 + 1) }, + quote! { #[attr] (x = 1) }, + quote! { #[attr] (x += 1) }, + quote! { #[attr] (1 as T) }, + quote! { (return #[attr] (x + ..)).field }, + quote! { (self.f)() }, + quote! { (return)..=return }, + quote! { 1 + (return)..=1 + return }, + quote! { .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. }, + ] { + let original: Expr = syn::parse2(tokens).unwrap(); + + let mut flat = original.clone(); + FlattenParens::combine_attrs().visit_expr_mut(&mut flat); + let reconstructed: Expr = match syn::parse2(flat.to_token_stream()) { + Ok(reconstructed) => reconstructed, + Err(err) => panic!("failed to parse `{}`: {}", flat.to_token_stream(), err), + }; + + assert!( + original == reconstructed, + "original: {}\n{:#?}\nreconstructed: {}\n{:#?}", + original.to_token_stream(), + crate::debug::Lite(&original), + reconstructed.to_token_stream(), + crate::debug::Lite(&reconstructed), + ); + } +} + +#[test] +fn test_permutations() -> ExitCode { + fn iter(depth: usize, f: &mut dyn FnMut(Expr)) { + let span = Span::call_site(); + + // Expr::Path + f(Expr::Path(ExprPath { + // `x` + attrs: Vec::new(), + qself: None, + path: Path::from(Ident::new("x", span)), + })); + if false { + f(Expr::Path(ExprPath { + // `x::` + attrs: Vec::new(), + qself: None, + path: Path { + leading_colon: None, + segments: Punctuated::from_iter([PathSegment { + ident: Ident::new("x", span), + arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { + colon2_token: Some(Token![::](span)), + lt_token: Token![<](span), + args: Punctuated::from_iter([GenericArgument::Type(Type::Path( + TypePath { + qself: None, + path: Path::from(Ident::new("T", span)), + }, + ))]), + gt_token: Token![>](span), + }), + }]), + }, + })); + f(Expr::Path(ExprPath { + // `::CONST` + attrs: Vec::new(), + qself: Some(QSelf { + lt_token: Token![<](span), + ty: Box::new(Type::Path(TypePath { + qself: None, + path: Path::from(Ident::new("T", span)), + })), + position: 1, + as_token: Some(Token![as](span)), + gt_token: Token![>](span), + }), + path: Path { + leading_colon: None, + segments: Punctuated::from_iter([ + PathSegment::from(Ident::new("Trait", span)), + PathSegment::from(Ident::new("CONST", span)), + ]), + }, + })); + } + + let Some(depth) = depth.checked_sub(1) else { + return; + }; + + // Expr::Assign + iter(depth, &mut |expr| { + iter(0, &mut |simple| { + f(Expr::Assign(ExprAssign { + // `x = $expr` + attrs: Vec::new(), + left: Box::new(simple.clone()), + eq_token: Token![=](span), + right: Box::new(expr.clone()), + })); + f(Expr::Assign(ExprAssign { + // `$expr = x` + attrs: Vec::new(), + left: Box::new(expr.clone()), + eq_token: Token![=](span), + right: Box::new(simple), + })); + }); + }); + + // Expr::Binary + iter(depth, &mut |expr| { + iter(0, &mut |simple| { + for op in [ + BinOp::Add(Token![+](span)), + //BinOp::Sub(Token![-](span)), + //BinOp::Mul(Token![*](span)), + //BinOp::Div(Token![/](span)), + //BinOp::Rem(Token![%](span)), + //BinOp::And(Token![&&](span)), + //BinOp::Or(Token![||](span)), + //BinOp::BitXor(Token![^](span)), + //BinOp::BitAnd(Token![&](span)), + //BinOp::BitOr(Token![|](span)), + //BinOp::Shl(Token![<<](span)), + //BinOp::Shr(Token![>>](span)), + //BinOp::Eq(Token![==](span)), + BinOp::Lt(Token![<](span)), + //BinOp::Le(Token![<=](span)), + //BinOp::Ne(Token![!=](span)), + //BinOp::Ge(Token![>=](span)), + //BinOp::Gt(Token![>](span)), + BinOp::ShlAssign(Token![<<=](span)), + ] { + f(Expr::Binary(ExprBinary { + // `x + $expr` + attrs: Vec::new(), + left: Box::new(simple.clone()), + op, + right: Box::new(expr.clone()), + })); + f(Expr::Binary(ExprBinary { + // `$expr + x` + attrs: Vec::new(), + left: Box::new(expr.clone()), + op, + right: Box::new(simple.clone()), + })); + } + }); + }); + + // Expr::Block + f(Expr::Block(ExprBlock { + // `{}` + attrs: Vec::new(), + label: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::Break + f(Expr::Break(ExprBreak { + // `break` + attrs: Vec::new(), + break_token: Token![break](span), + label: None, + expr: None, + })); + iter(depth, &mut |expr| { + f(Expr::Break(ExprBreak { + // `break $expr` + attrs: Vec::new(), + break_token: Token![break](span), + label: None, + expr: Some(Box::new(expr)), + })); + }); + + // Expr::Call + iter(depth, &mut |expr| { + f(Expr::Call(ExprCall { + // `$expr()` + attrs: Vec::new(), + func: Box::new(expr), + paren_token: token::Paren(span), + args: Punctuated::new(), + })); + }); + + // Expr::Cast + iter(depth, &mut |expr| { + f(Expr::Cast(ExprCast { + // `$expr as T` + attrs: Vec::new(), + expr: Box::new(expr), + as_token: Token![as](span), + ty: Box::new(Type::Path(TypePath { + qself: None, + path: Path::from(Ident::new("T", span)), + })), + })); + }); + + // Expr::Closure + iter(depth, &mut |expr| { + f(Expr::Closure(ExprClosure { + // `|| $expr` + attrs: Vec::new(), + lifetimes: None, + constness: None, + movability: None, + asyncness: None, + capture: None, + or1_token: Token![|](span), + inputs: Punctuated::new(), + or2_token: Token![|](span), + output: ReturnType::Default, + body: Box::new(expr), + })); + }); + + // Expr::Field + iter(depth, &mut |expr| { + f(Expr::Field(ExprField { + // `$expr.field` + attrs: Vec::new(), + base: Box::new(expr), + dot_token: Token![.](span), + member: Member::Named(Ident::new("field", span)), + })); + }); + + // Expr::If + iter(depth, &mut |expr| { + f(Expr::If(ExprIf { + // `if $expr {}` + attrs: Vec::new(), + if_token: Token![if](span), + cond: Box::new(expr), + then_branch: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + else_branch: None, + })); + }); + + // Expr::Let + iter(depth, &mut |expr| { + f(Expr::Let(ExprLet { + attrs: Vec::new(), + let_token: Token![let](span), + pat: Box::new(Pat::Wild(PatWild { + attrs: Vec::new(), + underscore_token: Token![_](span), + })), + eq_token: Token![=](span), + expr: Box::new(expr), + })); + }); + + // Expr::Range + f(Expr::Range(ExprRange { + // `..` + attrs: Vec::new(), + start: None, + limits: RangeLimits::HalfOpen(Token![..](span)), + end: None, + })); + iter(depth, &mut |expr| { + f(Expr::Range(ExprRange { + // `..$expr` + attrs: Vec::new(), + start: None, + limits: RangeLimits::HalfOpen(Token![..](span)), + end: Some(Box::new(expr.clone())), + })); + f(Expr::Range(ExprRange { + // `$expr..` + attrs: Vec::new(), + start: Some(Box::new(expr)), + limits: RangeLimits::HalfOpen(Token![..](span)), + end: None, + })); + }); + + // Expr::Reference + iter(depth, &mut |expr| { + f(Expr::Reference(ExprReference { + // `&$expr` + attrs: Vec::new(), + and_token: Token![&](span), + mutability: None, + expr: Box::new(expr), + })); + }); + + // Expr::Return + f(Expr::Return(ExprReturn { + // `return` + attrs: Vec::new(), + return_token: Token![return](span), + expr: None, + })); + iter(depth, &mut |expr| { + f(Expr::Return(ExprReturn { + // `return $expr` + attrs: Vec::new(), + return_token: Token![return](span), + expr: Some(Box::new(expr)), + })); + }); + + // Expr::Try + iter(depth, &mut |expr| { + f(Expr::Try(ExprTry { + // `$expr?` + attrs: Vec::new(), + expr: Box::new(expr), + question_token: Token![?](span), + })); + }); + + // Expr::Unary + iter(depth, &mut |expr| { + for op in [ + UnOp::Deref(Token![*](span)), + //UnOp::Not(Token![!](span)), + //UnOp::Neg(Token![-](span)), + ] { + f(Expr::Unary(ExprUnary { + // `*$expr` + attrs: Vec::new(), + op, + expr: Box::new(expr.clone()), + })); + } + }); + + if false { + // Expr::Array + f(Expr::Array(ExprArray { + // `[]` + attrs: Vec::new(), + bracket_token: token::Bracket(span), + elems: Punctuated::new(), + })); + + // Expr::Async + f(Expr::Async(ExprAsync { + // `async {}` + attrs: Vec::new(), + async_token: Token![async](span), + capture: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::Await + iter(depth, &mut |expr| { + f(Expr::Await(ExprAwait { + // `$expr.await` + attrs: Vec::new(), + base: Box::new(expr), + dot_token: Token![.](span), + await_token: Token![await](span), + })); + }); + + // Expr::Block + f(Expr::Block(ExprBlock { + // `'a: {}` + attrs: Vec::new(), + label: Some(Label { + name: Lifetime::new("'a", span), + colon_token: Token![:](span), + }), + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + iter(depth, &mut |expr| { + f(Expr::Block(ExprBlock { + // `{ $expr }` + attrs: Vec::new(), + label: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::from([Stmt::Expr(expr.clone(), None)]), + }, + })); + f(Expr::Block(ExprBlock { + // `{ $expr; }` + attrs: Vec::new(), + label: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::from([Stmt::Expr(expr, Some(Token![;](span)))]), + }, + })); + }); + + // Expr::Break + f(Expr::Break(ExprBreak { + // `break 'a` + attrs: Vec::new(), + break_token: Token![break](span), + label: Some(Lifetime::new("'a", span)), + expr: None, + })); + iter(depth, &mut |expr| { + f(Expr::Break(ExprBreak { + // `break 'a $expr` + attrs: Vec::new(), + break_token: Token![break](span), + label: Some(Lifetime::new("'a", span)), + expr: Some(Box::new(expr)), + })); + }); + + // Expr::Closure + f(Expr::Closure(ExprClosure { + // `|| -> T {}` + attrs: Vec::new(), + lifetimes: None, + constness: None, + movability: None, + asyncness: None, + capture: None, + or1_token: Token![|](span), + inputs: Punctuated::new(), + or2_token: Token![|](span), + output: ReturnType::Type( + Token![->](span), + Box::new(Type::Path(TypePath { + qself: None, + path: Path::from(Ident::new("T", span)), + })), + ), + body: Box::new(Expr::Block(ExprBlock { + attrs: Vec::new(), + label: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })), + })); + + // Expr::Const + f(Expr::Const(ExprConst { + // `const {}` + attrs: Vec::new(), + const_token: Token![const](span), + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::Continue + f(Expr::Continue(ExprContinue { + // `continue` + attrs: Vec::new(), + continue_token: Token![continue](span), + label: None, + })); + f(Expr::Continue(ExprContinue { + // `continue 'a` + attrs: Vec::new(), + continue_token: Token![continue](span), + label: Some(Lifetime::new("'a", span)), + })); + + // Expr::ForLoop + iter(depth, &mut |expr| { + f(Expr::ForLoop(ExprForLoop { + // `for _ in $expr {}` + attrs: Vec::new(), + label: None, + for_token: Token![for](span), + pat: Box::new(Pat::Wild(PatWild { + attrs: Vec::new(), + underscore_token: Token![_](span), + })), + in_token: Token![in](span), + expr: Box::new(expr.clone()), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + f(Expr::ForLoop(ExprForLoop { + // `'a: for _ in $expr {}` + attrs: Vec::new(), + label: Some(Label { + name: Lifetime::new("'a", span), + colon_token: Token![:](span), + }), + for_token: Token![for](span), + pat: Box::new(Pat::Wild(PatWild { + attrs: Vec::new(), + underscore_token: Token![_](span), + })), + in_token: Token![in](span), + expr: Box::new(expr), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + }); + + // Expr::Index + iter(depth, &mut |expr| { + f(Expr::Index(ExprIndex { + // `$expr[0]` + attrs: Vec::new(), + expr: Box::new(expr), + bracket_token: token::Bracket(span), + index: Box::new(Expr::Lit(ExprLit { + attrs: Vec::new(), + lit: Lit::Int(LitInt::new("0", span)), + })), + })); + }); + + // Expr::Loop + f(Expr::Loop(ExprLoop { + // `loop {}` + attrs: Vec::new(), + label: None, + loop_token: Token![loop](span), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + f(Expr::Loop(ExprLoop { + // `'a: loop {}` + attrs: Vec::new(), + label: Some(Label { + name: Lifetime::new("'a", span), + colon_token: Token![:](span), + }), + loop_token: Token![loop](span), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::Macro + f(Expr::Macro(ExprMacro { + // `m!()` + attrs: Vec::new(), + mac: Macro { + path: Path::from(Ident::new("m", span)), + bang_token: Token![!](span), + delimiter: MacroDelimiter::Paren(token::Paren(span)), + tokens: TokenStream::new(), + }, + })); + f(Expr::Macro(ExprMacro { + // `m! {}` + attrs: Vec::new(), + mac: Macro { + path: Path::from(Ident::new("m", span)), + bang_token: Token![!](span), + delimiter: MacroDelimiter::Brace(token::Brace(span)), + tokens: TokenStream::new(), + }, + })); + + // Expr::Match + iter(depth, &mut |expr| { + f(Expr::Match(ExprMatch { + // `match $expr {}` + attrs: Vec::new(), + match_token: Token![match](span), + expr: Box::new(expr.clone()), + brace_token: token::Brace(span), + arms: Vec::new(), + })); + f(Expr::Match(ExprMatch { + // `match x { _ => $expr }` + attrs: Vec::new(), + match_token: Token![match](span), + expr: Box::new(Expr::Path(ExprPath { + attrs: Vec::new(), + qself: None, + path: Path::from(Ident::new("x", span)), + })), + brace_token: token::Brace(span), + arms: Vec::from([Arm { + attrs: Vec::new(), + pat: Pat::Wild(PatWild { + attrs: Vec::new(), + underscore_token: Token![_](span), + }), + guard: None, + fat_arrow_token: Token![=>](span), + body: Box::new(expr.clone()), + comma: None, + }]), + })); + f(Expr::Match(ExprMatch { + // `match x { _ if $expr => {} }` + attrs: Vec::new(), + match_token: Token![match](span), + expr: Box::new(Expr::Path(ExprPath { + attrs: Vec::new(), + qself: None, + path: Path::from(Ident::new("x", span)), + })), + brace_token: token::Brace(span), + arms: Vec::from([Arm { + attrs: Vec::new(), + pat: Pat::Wild(PatWild { + attrs: Vec::new(), + underscore_token: Token![_](span), + }), + guard: Some((Token![if](span), Box::new(expr))), + fat_arrow_token: Token![=>](span), + body: Box::new(Expr::Block(ExprBlock { + attrs: Vec::new(), + label: None, + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })), + comma: None, + }]), + })); + }); + + // Expr::MethodCall + iter(depth, &mut |expr| { + f(Expr::MethodCall(ExprMethodCall { + // `$expr.method()` + attrs: Vec::new(), + receiver: Box::new(expr.clone()), + dot_token: Token![.](span), + method: Ident::new("method", span), + turbofish: None, + paren_token: token::Paren(span), + args: Punctuated::new(), + })); + f(Expr::MethodCall(ExprMethodCall { + // `$expr.method::()` + attrs: Vec::new(), + receiver: Box::new(expr), + dot_token: Token![.](span), + method: Ident::new("method", span), + turbofish: Some(AngleBracketedGenericArguments { + colon2_token: Some(Token![::](span)), + lt_token: Token![<](span), + args: Punctuated::from_iter([GenericArgument::Type(Type::Path( + TypePath { + qself: None, + path: Path::from(Ident::new("T", span)), + }, + ))]), + gt_token: Token![>](span), + }), + paren_token: token::Paren(span), + args: Punctuated::new(), + })); + }); + + // Expr::RawAddr + iter(depth, &mut |expr| { + f(Expr::RawAddr(ExprRawAddr { + // `&raw const $expr` + attrs: Vec::new(), + and_token: Token![&](span), + raw: Token![raw](span), + mutability: PointerMutability::Const(Token![const](span)), + expr: Box::new(expr), + })); + }); + + // Expr::Struct + f(Expr::Struct(ExprStruct { + // `Struct {}` + attrs: Vec::new(), + qself: None, + path: Path::from(Ident::new("Struct", span)), + brace_token: token::Brace(span), + fields: Punctuated::new(), + dot2_token: None, + rest: None, + })); + + // Expr::TryBlock + f(Expr::TryBlock(ExprTryBlock { + // `try {}` + attrs: Vec::new(), + try_token: Token![try](span), + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::Unsafe + f(Expr::Unsafe(ExprUnsafe { + // `unsafe {}` + attrs: Vec::new(), + unsafe_token: Token![unsafe](span), + block: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + + // Expr::While + iter(depth, &mut |expr| { + f(Expr::While(ExprWhile { + // `while $expr {}` + attrs: Vec::new(), + label: None, + while_token: Token![while](span), + cond: Box::new(expr.clone()), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + f(Expr::While(ExprWhile { + // `'a: while $expr {}` + attrs: Vec::new(), + label: Some(Label { + name: Lifetime::new("'a", span), + colon_token: Token![:](span), + }), + while_token: Token![while](span), + cond: Box::new(expr), + body: Block { + brace_token: token::Brace(span), + stmts: Vec::new(), + }, + })); + }); + + // Expr::Yield + f(Expr::Yield(ExprYield { + // `yield` + attrs: Vec::new(), + yield_token: Token![yield](span), + expr: None, + })); + iter(depth, &mut |expr| { + f(Expr::Yield(ExprYield { + // `yield $expr` + attrs: Vec::new(), + yield_token: Token![yield](span), + expr: Some(Box::new(expr)), + })); + }); + } + } + + let mut failures = 0; + macro_rules! fail { + ($($message:tt)*) => {{ + eprintln!($($message)*); + failures += 1; + return; + }}; + } + let mut assert = |mut original: Expr| { + let tokens = original.to_token_stream(); + let Ok(mut parsed) = syn::parse2::(tokens.clone()) else { + fail!( + "failed to parse: {}\n{:#?}", + tokens, + crate::debug::Lite(&original), + ); + }; + AsIfPrinted.visit_expr_mut(&mut original); + FlattenParens::combine_attrs().visit_expr_mut(&mut parsed); + if original != parsed { + fail!( + "before: {}\n{:#?}\nafter: {}\n{:#?}", + tokens, + crate::debug::Lite(&original), + parsed.to_token_stream(), + crate::debug::Lite(&parsed), + ); + } + let mut tokens_no_paren = tokens.clone(); + FlattenParens::visit_token_stream_mut(&mut tokens_no_paren); + if tokens.to_string() != tokens_no_paren.to_string() { + if let Ok(mut parsed2) = syn::parse2::(tokens_no_paren) { + FlattenParens::combine_attrs().visit_expr_mut(&mut parsed2); + if original == parsed2 { + fail!("redundant parens: {}", tokens); + } + } + } + }; + + iter(4, &mut assert); + if failures > 0 { + eprintln!("FAILURES: {failures}"); + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_generics.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_generics.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_generics.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_generics.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,21 @@ #![allow( + clippy::elidable_lifetime_names, clippy::manual_let_else, + clippy::needless_lifetimes, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use quote::quote; -use syn::{DeriveInput, ItemFn, TypeParamBound, WhereClause, WherePredicate}; +use syn::{ + parse_quote, DeriveInput, GenericParam, Generics, ItemFn, Lifetime, LifetimeParam, + TypeParamBound, WhereClause, WherePredicate, +}; #[test] fn test_split_for_impl() { @@ -16,7 +23,7 @@ struct S<'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug; }; - snapshot!(input as DeriveInput, @r###" + snapshot!(input as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -98,7 +105,7 @@ semi_token: Some, }, } - "###); + "#); let generics = input.generics; let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); @@ -126,23 +133,23 @@ } #[test] -fn test_ty_param_bound() { +fn test_type_param_bound() { let tokens = quote!('a); - snapshot!(tokens as TypeParamBound, @r###" + snapshot!(tokens as TypeParamBound, @r#" TypeParamBound::Lifetime { ident: "a", } - "###); + "#); let tokens = quote!('_); - snapshot!(tokens as TypeParamBound, @r###" + snapshot!(tokens as TypeParamBound, @r#" TypeParamBound::Lifetime { ident: "_", } - "###); + "#); let tokens = quote!(Debug); - snapshot!(tokens as TypeParamBound, @r###" + snapshot!(tokens as TypeParamBound, @r#" TypeParamBound::Trait(TraitBound { path: Path { segments: [ @@ -152,10 +159,10 @@ ], }, }) - "###); + "#); let tokens = quote!(?Sized); - snapshot!(tokens as TypeParamBound, @r###" + snapshot!(tokens as TypeParamBound, @r#" TypeParamBound::Trait(TraitBound { modifier: TraitBoundModifier::Maybe, path: Path { @@ -166,7 +173,43 @@ ], }, }) - "###); + "#); + + let tokens = quote!(for<'a> Trait); + snapshot!(tokens as TypeParamBound, @r#" + TypeParamBound::Trait(TraitBound { + lifetimes: Some(BoundLifetimes { + lifetimes: [ + GenericParam::Lifetime(LifetimeParam { + lifetime: Lifetime { + ident: "a", + }, + }), + ], + }), + path: Path { + segments: [ + PathSegment { + ident: "Trait", + }, + ], + }, + }) + "#); + + let tokens = quote!(for<> ?Trait); + let err = syn::parse2::(tokens).unwrap_err(); + assert_eq!( + "`for<...>` binder not allowed with `?` trait polarity modifier", + err.to_string(), + ); + + let tokens = quote!(?for<> Trait); + let err = syn::parse2::(tokens).unwrap_err(); + assert_eq!( + "`for<...>` binder not allowed with `?` trait polarity modifier", + err.to_string(), + ); } #[test] @@ -181,7 +224,7 @@ } }; - snapshot!(input as ItemFn, @r###" + snapshot!(input as ItemFn, @r#" ItemFn { vis: Visibility::Inherited, sig: Signature { @@ -251,7 +294,7 @@ stmts: [], }, } - "###); + "#); let where_clause = input.sig.generics.where_clause.as_ref().unwrap(); assert_eq!(where_clause.predicates.len(), 1); @@ -280,3 +323,34 @@ assert_eq!(input.predicates.len(), 0); } + +// Regression test for https://github.com/dtolnay/syn/issues/1718 +#[test] +#[allow(clippy::map_unwrap_or)] +fn no_opaque_drop() { + let mut generics = Generics::default(); + + let _ = generics + .lifetimes() + .next() + .map(|param| param.lifetime.clone()) + .unwrap_or_else(|| { + let lifetime: Lifetime = parse_quote!('a); + generics.params.insert( + 0, + GenericParam::Lifetime(LifetimeParam::new(lifetime.clone())), + ); + lifetime + }); +} + +#[test] +fn type_param_with_colon_and_no_bounds() { + let tokens = quote!(T:); + snapshot!(tokens as GenericParam, @r#" + GenericParam::Type(TypeParam { + ident: "T", + colon_token: Some, + }) + "#); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_grouping.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_grouping.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_grouping.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_grouping.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree}; use syn::Expr; @@ -25,7 +31,7 @@ assert_eq!(tokens.to_string(), "1i32 + 2i32 + 3i32 * 4i32"); - snapshot!(tokens as Expr, @r###" + snapshot!(tokens as Expr, @r#" Expr::Binary { left: Expr::Lit { lit: 1i32, @@ -49,5 +55,5 @@ }, }, } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_item.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_item.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_item.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_item.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use quote::quote; @@ -18,7 +24,7 @@ TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]); - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Fn { attrs: [ Attribute { @@ -42,44 +48,35 @@ stmts: [], }, } - "###); + "#); } #[test] fn test_negative_impl() { - // Rustc parses all of the following. - #[cfg(any())] impl ! {} let tokens = quote! { impl ! {} }; - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Impl { generics: Generics, self_ty: Type::Never, } - "###); + "#); - #[cfg(any())] - #[rustfmt::skip] - impl !Trait {} let tokens = quote! { impl !Trait {} }; - snapshot!(tokens as Item, @r###" - Item::Impl { - generics: Generics, - self_ty: Type::Verbatim(`! Trait`), - } - "###); + let err = syn::parse2::(tokens).unwrap_err(); + assert_eq!(err.to_string(), "inherent impls cannot be negative"); #[cfg(any())] impl !Trait for T {} let tokens = quote! { impl !Trait for T {} }; - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Impl { generics: Generics, trait_: Some(( @@ -102,20 +99,7 @@ }, }, } - "###); - - #[cfg(any())] - #[rustfmt::skip] - impl !! {} - let tokens = quote! { - impl !! {} - }; - snapshot!(tokens as Item, @r###" - Item::Impl { - generics: Generics, - self_ty: Type::Verbatim(`! !`), - } - "###); + "#); } #[test] @@ -129,7 +113,7 @@ TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]); - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Impl { generics: Generics, trait_: Some(( @@ -154,7 +138,7 @@ }, }, } - "###); + "#); } #[test] @@ -163,7 +147,7 @@ #[rustfmt::skip] let tokens = quote!(trait Trait where {}); - snapshot!(tokens as ItemTrait, @r###" + snapshot!(tokens as ItemTrait, @r#" ItemTrait { vis: Visibility::Inherited, ident: "Trait", @@ -171,11 +155,11 @@ where_clause: Some(WhereClause), }, } - "###); + "#); #[rustfmt::skip] let tokens = quote!(trait Trait: where {}); - snapshot!(tokens as ItemTrait, @r###" + snapshot!(tokens as ItemTrait, @r#" ItemTrait { vis: Visibility::Inherited, ident: "Trait", @@ -184,11 +168,11 @@ }, colon_token: Some, } - "###); + "#); #[rustfmt::skip] let tokens = quote!(trait Trait: Sized where {}); - snapshot!(tokens as ItemTrait, @r###" + snapshot!(tokens as ItemTrait, @r#" ItemTrait { vis: Visibility::Inherited, ident: "Trait", @@ -208,11 +192,11 @@ }), ], } - "###); + "#); #[rustfmt::skip] let tokens = quote!(trait Trait: Sized + where {}); - snapshot!(tokens as ItemTrait, @r###" + snapshot!(tokens as ItemTrait, @r#" ItemTrait { vis: Visibility::Inherited, ident: "Trait", @@ -233,7 +217,7 @@ Token![+], ], } - "###); + "#); } #[test] @@ -245,7 +229,7 @@ } }; - snapshot!(tokens as ItemTrait, @r###" + snapshot!(tokens as ItemTrait, @r#" ItemTrait { vis: Visibility::Inherited, ident: "Foo", @@ -258,7 +242,7 @@ }, ], } - "###); + "#); } #[test] @@ -277,7 +261,7 @@ let tokens = quote! { impl () {} }; - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Impl { generics: Generics { lt_token: Some, @@ -292,7 +276,7 @@ }, self_ty: Type::Tuple, } - "###); + "#); } #[test] @@ -301,7 +285,7 @@ fn f() -> impl Sized + {} }; - snapshot!(tokens as Item, @r###" + snapshot!(tokens as Item, @r#" Item::Fn { vis: Visibility::Inherited, sig: Signature { @@ -328,5 +312,5 @@ stmts: [], }, } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_iterators.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_iterators.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_iterators.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_iterators.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -#![allow(clippy::uninlined_format_args)] - -use syn::punctuated::{Pair, Punctuated}; -use syn::Token; - -#[macro_use] -mod macros; - -macro_rules! check_exact_size_iterator { - ($iter:expr) => {{ - let iter = $iter; - let size_hint = iter.size_hint(); - let len = iter.len(); - let count = iter.count(); - assert_eq!(len, count); - assert_eq!(size_hint, (count, Some(count))); - }}; -} - -#[test] -fn pairs() { - let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - - check_exact_size_iterator!(p.pairs()); - check_exact_size_iterator!(p.pairs_mut()); - check_exact_size_iterator!(p.into_pairs()); - - let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - - assert_eq!(p.pairs().next_back().map(Pair::into_value), Some(&4)); - assert_eq!( - p.pairs_mut().next_back().map(Pair::into_value), - Some(&mut 4) - ); - assert_eq!(p.into_pairs().next_back().map(Pair::into_value), Some(4)); -} - -#[test] -fn iter() { - let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - - check_exact_size_iterator!(p.iter()); - check_exact_size_iterator!(p.iter_mut()); - check_exact_size_iterator!(p.into_iter()); - - let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - - assert_eq!(p.iter().next_back(), Some(&4)); - assert_eq!(p.iter_mut().next_back(), Some(&mut 4)); - assert_eq!(p.into_iter().next_back(), Some(4)); -} - -#[test] -fn may_dangle() { - let p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - for element in &p { - if *element == 2 { - drop(p); - break; - } - } - - let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); - for element in &mut p { - if *element == 2 { - drop(p); - break; - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_lit.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_lit.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_lit.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_lit.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,7 @@ #![allow( + clippy::elidable_lifetime_names, clippy::float_cmp, + clippy::needless_lifetimes, clippy::needless_raw_string_hashes, clippy::non_ascii_literal, clippy::single_match_else, @@ -7,7 +9,9 @@ )] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree}; use quote::ToTokens; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_meta.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_meta.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_meta.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_meta.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,25 @@ #![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, clippy::shadow_unrelated, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] -mod macros; +mod snapshot; -use syn::{Meta, MetaList, MetaNameValue}; +mod debug; + +use quote::quote; +use syn::parse::{ParseStream, Parser as _, Result}; +use syn::{Meta, MetaList, MetaNameValue, Token}; #[test] fn test_parse_meta_item_word() { let input = "hello"; - snapshot!(input as Meta, @r###" + snapshot!(input as Meta, @r#" Meta::Path { segments: [ PathSegment { @@ -21,7 +27,7 @@ }, ], } - "###); + "#); } #[test] @@ -29,7 +35,7 @@ let input = "foo = 5"; let (inner, meta) = (input, input); - snapshot!(inner as MetaNameValue, @r###" + snapshot!(inner as MetaNameValue, @r#" MetaNameValue { path: Path { segments: [ @@ -42,9 +48,9 @@ lit: 5, }, } - "###); + "#); - snapshot!(meta as Meta, @r###" + snapshot!(meta as Meta, @r#" Meta::NameValue { path: Path { segments: [ @@ -57,9 +63,9 @@ lit: 5, }, } - "###); + "#); - assert_eq!(meta, inner.into()); + assert_eq!(meta, Meta::NameValue(inner)); } #[test] @@ -67,7 +73,7 @@ let input = "foo(5)"; let (inner, meta) = (input, input); - snapshot!(inner as MetaList, @r###" + snapshot!(inner as MetaList, @r#" MetaList { path: Path { segments: [ @@ -79,9 +85,9 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } - "###); + "#); - snapshot!(meta as Meta, @r###" + snapshot!(meta as Meta, @r#" Meta::List { path: Path { segments: [ @@ -93,9 +99,9 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } - "###); + "#); - assert_eq!(meta, inner.into()); + assert_eq!(meta, Meta::List(inner)); } #[test] @@ -103,7 +109,7 @@ let input = "foo(word, name = 5, list(name2 = 6), word2)"; let (inner, meta) = (input, input); - snapshot!(inner as MetaList, @r###" + snapshot!(inner as MetaList, @r#" MetaList { path: Path { segments: [ @@ -115,9 +121,9 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } - "###); + "#); - snapshot!(meta as Meta, @r###" + snapshot!(meta as Meta, @r#" Meta::List { path: Path { segments: [ @@ -129,15 +135,15 @@ delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } - "###); + "#); - assert_eq!(meta, inner.into()); + assert_eq!(meta, Meta::List(inner)); } #[test] fn test_parse_path() { let input = "::serde::Serialize"; - snapshot!(input as Meta, @r###" + snapshot!(input as Meta, @r#" Meta::Path { leading_colon: Some, segments: [ @@ -150,5 +156,25 @@ }, ], } - "###); + "#); +} + +#[test] +fn test_fat_arrow_after_meta() { + fn parse(input: ParseStream) -> Result<()> { + while !input.is_empty() { + let _: Meta = input.parse()?; + let _: Token![=>] = input.parse()?; + let brace; + syn::braced!(brace in input); + } + Ok(()) + } + + let input = quote! { + target_os = "linux" => {} + windows => {} + }; + + parse.parse2(input).unwrap(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_buffer.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_buffer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_buffer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_buffer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ #![allow(clippy::non_ascii_literal)] -use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree}; +use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, TokenStream, TokenTree}; +use std::panic; use syn::parse::discouraged::Speculative as _; use syn::parse::{Parse, ParseStream, Parser, Result}; use syn::{parenthesized, Token}; @@ -90,3 +91,14 @@ parse.parse2(tokens).unwrap(); } + +#[test] +#[cfg_attr(miri, ignore)] // https://github.com/rust-lang/miri/issues/4793 +fn test_unwind_safe() { + fn parse(input: ParseStream) -> Result { + let thread_result = panic::catch_unwind(|| input.parse()); + thread_result.unwrap() + } + + parse.parse_str("throw").unwrap(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_quote.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_quote.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_quote.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_quote.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use syn::punctuated::Punctuated; use syn::{parse_quote, Attribute, Field, Lit, Pat, Stmt, Token}; @@ -9,7 +15,7 @@ #[test] fn test_attribute() { let attr: Attribute = parse_quote!(#[test]); - snapshot!(attr, @r###" + snapshot!(attr, @r#" Attribute { style: AttrStyle::Outer, meta: Meta::Path { @@ -20,10 +26,10 @@ ], }, } - "###); + "#); let attr: Attribute = parse_quote!(#![no_std]); - snapshot!(attr, @r###" + snapshot!(attr, @r#" Attribute { style: AttrStyle::Inner, meta: Meta::Path { @@ -34,13 +40,13 @@ ], }, } - "###); + "#); } #[test] fn test_field() { let field: Field = parse_quote!(pub enabled: bool); - snapshot!(field, @r###" + snapshot!(field, @r#" Field { vis: Visibility::Public, ident: Some("enabled"), @@ -55,10 +61,10 @@ }, }, } - "###); + "#); let field: Field = parse_quote!(primitive::bool); - snapshot!(field, @r###" + snapshot!(field, @r#" Field { vis: Visibility::Inherited, ty: Type::Path { @@ -75,13 +81,13 @@ }, }, } - "###); + "#); } #[test] fn test_pat() { let pat: Pat = parse_quote!(Some(false) | None); - snapshot!(&pat, @r###" + snapshot!(&pat, @r#" Pat::Or { cases: [ Pat::TupleStruct { @@ -106,7 +112,7 @@ }, ], } - "###); + "#); let boxed_pat: Box = parse_quote!(Some(false) | None); assert_eq!(*boxed_pat, pat); @@ -115,7 +121,7 @@ #[test] fn test_punctuated() { let punctuated: Punctuated = parse_quote!(true | true); - snapshot!(punctuated, @r###" + snapshot!(punctuated, @r#" [ Lit::Bool { value: true, @@ -125,10 +131,10 @@ value: true, }, ] - "###); + "#); let punctuated: Punctuated = parse_quote!(true | true |); - snapshot!(punctuated, @r###" + snapshot!(punctuated, @r#" [ Lit::Bool { value: true, @@ -139,7 +145,7 @@ }, Token![|], ] - "###); + "#); } #[test] @@ -148,7 +154,7 @@ let _; true }; - snapshot!(stmts, @r###" + snapshot!(stmts, @r#" [ Stmt::Local { pat: Pat::Wild, @@ -162,5 +168,5 @@ None, ), ] - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_stream.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_stream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_parse_stream.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_parse_stream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -3,6 +3,7 @@ use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::quote; use syn::ext::IdentExt as _; +use syn::parse::discouraged::AnyDelimiter; use syn::parse::{ParseStream, Parser as _, Result}; use syn::{parenthesized, token, Ident, Lifetime, Token}; @@ -158,16 +159,27 @@ assert!(input.peek3(Token![static])); assert!(!input.peek2(Token![static])); - let _: Token![!] = input.parse()?; + let implicit = input.fork(); + let explicit = input.fork(); - assert!(input.peek(Token![=])); - assert!(input.peek2(Token![static])); - - let _: Token![=] = input.parse()?; + let _: Token![!] = implicit.parse()?; + assert!(implicit.peek(Token![=])); + assert!(implicit.peek2(Token![static])); + let _: Token![=] = implicit.parse()?; + assert!(implicit.peek(Token![static])); + + let (delimiter, _span, grouped) = explicit.parse_any_delimiter()?; + assert_eq!(delimiter, Delimiter::None); + assert!(grouped.peek(Token![!])); + assert!(grouped.peek2(Token![=])); + assert!(!grouped.peek3(Token![static])); + let _: Token![!] = grouped.parse()?; + assert!(grouped.peek(Token![=])); + assert!(!grouped.peek2(Token![static])); + let _: Token![=] = grouped.parse()?; + assert!(!grouped.peek(Token![static])); - assert!(input.peek(Token![static])); - - let _: Token![static] = input.parse()?; + let _: TokenStream = input.parse()?; Ok(()) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_pat.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_pat.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_pat.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_pat.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; @@ -51,7 +57,7 @@ let tokens = TokenStream::from_iter([TokenTree::Group(group)]); let pat = Pat::parse_single.parse2(tokens).unwrap(); - snapshot!(pat, @r###" + snapshot!(pat, @r#" Pat::TupleStruct { path: Path { segments: [ @@ -64,7 +70,7 @@ Pat::Wild, ], } - "###); + "#); } #[test] @@ -108,27 +114,27 @@ expr.elems.push_value(parse_quote!(_)); // Must not parse to Pat::Paren - snapshot!(expr.to_token_stream() as Pat, @r###" + snapshot!(expr.to_token_stream() as Pat, @r#" Pat::Tuple { elems: [ Pat::Wild, Token![,], ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Pat, @r###" + snapshot!(expr.to_token_stream() as Pat, @r#" Pat::Tuple { elems: [ Pat::Wild, Token![,], ], } - "###); + "#); expr.elems.push_value(parse_quote!(_)); - snapshot!(expr.to_token_stream() as Pat, @r###" + snapshot!(expr.to_token_stream() as Pat, @r#" Pat::Tuple { elems: [ Pat::Wild, @@ -136,10 +142,10 @@ Pat::Wild, ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Pat, @r###" + snapshot!(expr.to_token_stream() as Pat, @r#" Pat::Tuple { elems: [ Pat::Wild, @@ -148,5 +154,5 @@ Token![,], ], } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_path.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_path.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens}; @@ -17,7 +23,7 @@ TokenTree::Ident(Ident::new("rest", Span::call_site())), ]); - snapshot!(tokens.clone() as Expr, @r###" + snapshot!(tokens.clone() as Expr, @r#" Expr::Path { path: Path { segments: [ @@ -31,9 +37,9 @@ ], }, } - "###); + "#); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { path: Path { segments: [ @@ -47,58 +53,38 @@ ], }, } - "###); + "#); } #[test] fn print_incomplete_qpath() { // qpath with `as` token let mut ty: TypePath = parse_quote!(::Q); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self as A > :: Q`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self as A > ::`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self >`) - "###); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self as A > :: Q`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self as A > ::`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self >`)"); assert!(ty.path.segments.pop().is_none()); // qpath without `as` token let mut ty: TypePath = parse_quote!(::A::B); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self > :: A :: B`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self > :: A ::`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`< Self > ::`) - "###); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self > :: A :: B`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self > :: A ::`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`< Self > ::`)"); assert!(ty.path.segments.pop().is_none()); // normal path let mut ty: TypePath = parse_quote!(Self::A::B); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`Self :: A :: B`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`Self :: A ::`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(`Self ::`) - "###); - assert!(ty.path.segments.pop().is_some()); - snapshot!(ty.to_token_stream(), @r###" - TokenStream(``) - "###); + snapshot!(ty.to_token_stream(), @"TokenStream(`Self :: A :: B`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`Self :: A ::`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(`Self ::`)"); + assert!(ty.path.segments.pop().is_some()); + snapshot!(ty.to_token_stream(), @"TokenStream(``)"); assert!(ty.path.segments.pop().is_none()); } @@ -106,7 +92,7 @@ fn parse_parenthesized_path_arguments_with_disambiguator() { #[rustfmt::skip] let tokens = quote!(dyn FnOnce::() -> !); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::TraitObject { dyn_token: Some, bounds: [ @@ -126,5 +112,5 @@ }), ], } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_precedence.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_precedence.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_precedence.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_precedence.rs 2006-07-24 01:21:28.000000000 +0000 @@ -19,14 +19,17 @@ #![allow( clippy::blocks_in_conditions, clippy::doc_markdown, + clippy::elidable_lifetime_names, clippy::explicit_deref_methods, clippy::let_underscore_untyped, clippy::manual_assert, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::match_wildcard_for_single_variants, + clippy::needless_lifetimes, clippy::too_many_lines, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::unnecessary_box_returns )] extern crate rustc_ast; @@ -34,34 +37,34 @@ extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_span; -extern crate smallvec; -extern crate thin_vec; use crate::common::eq::SpanlessEq; use crate::common::parse; use quote::ToTokens; use rustc_ast::ast; -use rustc_ast::ptr::P; use rustc_ast_pretty::pprust; use rustc_span::edition::Edition; use std::fs; +use std::mem; use std::path::Path; use std::process; use std::sync::atomic::{AtomicUsize, Ordering}; +use syn::parse::Parser as _; #[macro_use] mod macros; -#[allow(dead_code)] mod common; - mod repo; +#[path = "../src/scan_expr.rs"] +mod scan_expr; + #[test] fn test_rustc_precedence() { - common::rayon_init(); + repo::rayon_init(); repo::clone_rust(); - let abort_after = common::abort_after(); + let abort_after = repo::abort_after(); if abort_after == 0 { panic!("skipping all precedence tests"); } @@ -99,8 +102,8 @@ } }); - let passed = passed.load(Ordering::Relaxed); - let failed = failed.load(Ordering::Relaxed); + let passed = passed.into_inner(); + let failed = failed.into_inner(); errorf!("\n===== Precedence Test Results =====\n"); errorf!("{} passed | {} failed\n", passed, failed); @@ -116,7 +119,8 @@ rustc_span::create_session_if_not_set_then(edition, |_| { for expr in exprs { - let source_code = expr.to_token_stream().to_string(); + let expr_tokens = expr.to_token_stream(); + let source_code = expr_tokens.to_string(); let librustc_ast = if let Some(e) = librustc_parse_and_rewrite(&source_code) { e } else { @@ -174,6 +178,16 @@ continue; } + if scan_expr::scan_expr.parse2(expr_tokens).is_err() { + failed += 1; + errorf!( + "\nFAIL {} - failed to scan expr\n{}\n", + path.display(), + source_code, + ); + continue; + } + passed += 1; } }); @@ -181,26 +195,23 @@ (passed, failed) } -fn librustc_parse_and_rewrite(input: &str) -> Option> { +fn librustc_parse_and_rewrite(input: &str) -> Option> { parse::librustc_expr(input).map(librustc_parenthesize) } -fn librustc_parenthesize(mut librustc_expr: P) -> P { +fn librustc_parenthesize(mut librustc_expr: Box) -> Box { use rustc_ast::ast::{ - AssocItem, AssocItemKind, Attribute, BinOpKind, Block, BorrowKind, BoundConstness, Expr, - ExprField, ExprKind, GenericArg, GenericBound, ItemKind, Local, LocalKind, Pat, Stmt, - StmtKind, StructExpr, StructRest, TraitBoundModifiers, Ty, - }; - use rustc_ast::mut_visit::{ - noop_flat_map_assoc_item, noop_visit_generic_arg, noop_visit_item_kind, noop_visit_local, - noop_visit_param_bound, MutVisitor, + AssocItem, AssocItemKind, Attribute, BinOpKind, Block, BoundConstness, Expr, ExprField, + ExprKind, GenericArg, GenericBound, Local, LocalKind, Pat, PolyTraitRef, Stmt, StmtKind, + StructExpr, StructRest, TraitBoundModifiers, Ty, }; + use rustc_ast::mut_visit::{walk_flat_map_assoc_item, MutVisitor}; + use rustc_ast::visit::{AssocCtxt, BoundKind}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; + use rustc_data_structures::smallvec::SmallVec; + use rustc_data_structures::thin_vec::ThinVec; use rustc_span::DUMMY_SP; - use smallvec::SmallVec; - use std::mem; use std::ops::DerefMut; - use thin_vec::ThinVec; struct FullyParenthesize; @@ -242,9 +253,8 @@ } fn noop_visit_expr(e: &mut Expr, vis: &mut T) { - use rustc_ast::mut_visit::{noop_visit_expr, visit_attrs}; match &mut e.kind { - ExprKind::AddrOf(BorrowKind::Raw, ..) => {} + ExprKind::Become(..) => {} ExprKind::Struct(expr) => { let StructExpr { qself, @@ -252,68 +262,68 @@ fields, rest, } = expr.deref_mut(); - vis.visit_qself(qself); + if let Some(qself) = qself { + vis.visit_qself(qself); + } vis.visit_path(path); fields.flat_map_in_place(|field| flat_map_field(field, vis)); if let StructRest::Base(rest) = rest { vis.visit_expr(rest); } - vis.visit_id(&mut e.id); - vis.visit_span(&mut e.span); - visit_attrs(&mut e.attrs, vis); } - _ => noop_visit_expr(e, vis), + _ => rustc_ast::mut_visit::walk_expr(vis, e), } } impl MutVisitor for FullyParenthesize { - fn visit_expr(&mut self, e: &mut P) { + fn visit_expr(&mut self, e: &mut Expr) { noop_visit_expr(e, self); match e.kind { ExprKind::Block(..) | ExprKind::If(..) | ExprKind::Let(..) => {} ExprKind::Binary(..) if contains_let_chain(e) => {} _ => { - let inner = mem::replace( - e, - P(Expr { - id: ast::DUMMY_NODE_ID, - kind: ExprKind::Dummy, - span: DUMMY_SP, - attrs: ThinVec::new(), - tokens: None, - }), - ); - e.kind = ExprKind::Paren(inner); + let inner = mem::replace(e, Expr::dummy()); + *e = Expr { + id: ast::DUMMY_NODE_ID, + kind: ExprKind::Paren(Box::new(inner)), + span: DUMMY_SP, + attrs: ThinVec::new(), + tokens: None, + }; } } } fn visit_generic_arg(&mut self, arg: &mut GenericArg) { match arg { + GenericArg::Lifetime(_lifetime) => {} + GenericArg::Type(arg) => self.visit_ty(arg), // Don't wrap unbraced const generic arg as that's invalid syntax. GenericArg::Const(anon_const) => { if let ExprKind::Block(..) = &mut anon_const.value.kind { noop_visit_expr(&mut anon_const.value, self); } } - _ => noop_visit_generic_arg(arg, self), } } - fn visit_param_bound(&mut self, bound: &mut GenericBound) { + fn visit_param_bound(&mut self, bound: &mut GenericBound, _ctxt: BoundKind) { match bound { - GenericBound::Trait( - _, - TraitBoundModifiers { - constness: BoundConstness::Maybe(_), - .. - }, - ) => {} - _ => noop_visit_param_bound(bound, self), + GenericBound::Trait(PolyTraitRef { + modifiers: + TraitBoundModifiers { + constness: BoundConstness::Maybe(_), + .. + }, + .. + }) + | GenericBound::Outlives(..) + | GenericBound::Use(..) => {} + GenericBound::Trait(ty) => self.visit_poly_trait_ref(ty), } } - fn visit_block(&mut self, block: &mut P) { + fn visit_block(&mut self, block: &mut Block) { self.visit_id(&mut block.id); block .stmts @@ -321,35 +331,24 @@ self.visit_span(&mut block.span); } - fn visit_local(&mut self, local: &mut P) { - match local.kind { - LocalKind::InitElse(..) => {} - _ => noop_visit_local(local, self), - } - } - - fn visit_item_kind(&mut self, item: &mut ItemKind) { - match item { - ItemKind::Const(const_item) - if !const_item.generics.params.is_empty() - || !const_item.generics.where_clause.predicates.is_empty() => {} - _ => noop_visit_item_kind(item, self), - } - } - - fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { - match &item.kind { - AssocItemKind::Const(const_item) - if !const_item.generics.params.is_empty() - || !const_item.generics.where_clause.predicates.is_empty() => - { - SmallVec::from([item]) + fn visit_local(&mut self, local: &mut Local) { + match &mut local.kind { + LocalKind::Decl => {} + LocalKind::Init(init) => { + self.visit_expr(init); + } + LocalKind::InitElse(init, els) => { + self.visit_expr(init); + self.visit_block(els); } - _ => noop_flat_map_assoc_item(item, self), } } - fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { + fn flat_map_assoc_item( + &mut self, + item: Box, + ctxt: AssocCtxt, + ) -> SmallVec<[Box; 1]> { match &item.kind { AssocItemKind::Const(const_item) if !const_item.generics.params.is_empty() @@ -357,18 +356,18 @@ { SmallVec::from([item]) } - _ => noop_flat_map_assoc_item(item, self), + _ => walk_flat_map_assoc_item(self, item, ctxt), } } // We don't want to look at expressions that might appear in patterns or // types yet. We'll look into comparing those in the future. For now // focus on expressions appearing in other places. - fn visit_pat(&mut self, pat: &mut P) { + fn visit_pat(&mut self, pat: &mut Pat) { let _ = pat; } - fn visit_ty(&mut self, ty: &mut P) { + fn visit_ty(&mut self, ty: &mut Ty) { let _ = ty; } @@ -384,7 +383,9 @@ fn syn_parenthesize(syn_expr: syn::Expr) -> syn::Expr { use syn::fold::{fold_expr, fold_generic_argument, Fold}; - use syn::{token, BinOp, Expr, ExprParen, GenericArgument, MetaNameValue, Pat, Stmt, Type}; + use syn::{ + token, BinOp, Expr, ExprParen, GenericArgument, Lit, MetaNameValue, Pat, Stmt, Type, + }; struct FullyParenthesize; @@ -462,6 +463,13 @@ fn fold_type(&mut self, ty: Type) -> Type { ty } + + fn fold_lit(&mut self, lit: Lit) -> Lit { + if let Lit::Verbatim(lit) = &lit { + panic!("unexpected verbatim literal: {lit}"); + } + lit + } } let mut folder = FullyParenthesize; @@ -487,7 +495,8 @@ } fn fold_stmt(&mut self, stmt: Stmt) -> Stmt { - if let Stmt::Expr(expr @ (Expr::Binary(_) | Expr::Cast(_)), None) = stmt { + if let Stmt::Expr(expr @ (Expr::Binary(_) | Expr::Call(_) | Expr::Cast(_)), None) = stmt + { Stmt::Expr( Expr::Paren(ExprParen { attrs: Vec::new(), diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_punctuated.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_punctuated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_punctuated.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_punctuated.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,92 @@ +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] + +use syn::punctuated::{Pair, Punctuated}; +use syn::Token; + +macro_rules! punctuated { + ($($e:expr,)+) => {{ + let mut seq = ::syn::punctuated::Punctuated::new(); + $( + seq.push($e); + )+ + seq + }}; + + ($($e:expr),+) => { + punctuated!($($e,)+) + }; +} + +macro_rules! check_exact_size_iterator { + ($iter:expr) => {{ + let iter = $iter; + let size_hint = iter.size_hint(); + let len = iter.len(); + let count = iter.count(); + assert_eq!(len, count); + assert_eq!(size_hint, (count, Some(count))); + }}; +} + +#[test] +fn pairs() { + let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + + check_exact_size_iterator!(p.pairs()); + check_exact_size_iterator!(p.pairs_mut()); + check_exact_size_iterator!(p.into_pairs()); + + let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + + assert_eq!(p.pairs().next_back().map(Pair::into_value), Some(&4)); + assert_eq!( + p.pairs_mut().next_back().map(Pair::into_value), + Some(&mut 4) + ); + assert_eq!(p.into_pairs().next_back().map(Pair::into_value), Some(4)); +} + +#[test] +fn iter() { + let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + + check_exact_size_iterator!(p.iter()); + check_exact_size_iterator!(p.iter_mut()); + check_exact_size_iterator!(p.into_iter()); + + let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + + assert_eq!(p.iter().next_back(), Some(&4)); + assert_eq!(p.iter_mut().next_back(), Some(&mut 4)); + assert_eq!(p.into_iter().next_back(), Some(4)); +} + +#[test] +fn may_dangle() { + let p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + for element in &p { + if *element == 2 { + drop(p); + break; + } + } + + let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); + for element in &mut p { + if *element == 2 { + drop(p); + break; + } + } +} + +#[test] +#[should_panic = "index out of bounds: the len is 0 but the index is 0"] +fn index_out_of_bounds() { + let p = Punctuated::::new(); + let _ = p[0].clone(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_receiver.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_receiver.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_receiver.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_receiver.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use syn::{parse_quote, TraitItemFn}; @@ -10,7 +16,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn by_value(self: Self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { @@ -23,7 +29,7 @@ }, }, }) - "###); + "#); } #[test] @@ -31,7 +37,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn by_mut(mut self: Self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { mutability: Some, colon_token: Some, @@ -45,7 +51,7 @@ }, }, }) - "###); + "#); } #[test] @@ -53,7 +59,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn by_ref(self: &Self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Reference { @@ -68,7 +74,7 @@ }, }, }) - "###); + "#); } #[test] @@ -76,7 +82,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn by_box(self: Box); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { @@ -102,7 +108,7 @@ }, }, }) - "###); + "#); } #[test] @@ -110,7 +116,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn by_pin(self: Pin); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { @@ -136,7 +142,7 @@ }, }, }) - "###); + "#); } #[test] @@ -144,7 +150,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn explicit_type(self: Pin); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { @@ -170,7 +176,7 @@ }, }, }) - "###); + "#); } #[test] @@ -178,7 +184,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn value_shorthand(self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { ty: Type::Path { path: Path { @@ -190,7 +196,7 @@ }, }, }) - "###); + "#); } #[test] @@ -198,7 +204,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn mut_value_shorthand(mut self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { mutability: Some, ty: Type::Path { @@ -211,7 +217,7 @@ }, }, }) - "###); + "#); } #[test] @@ -219,7 +225,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn ref_shorthand(&self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { reference: Some(None), ty: Type::Reference { @@ -234,7 +240,7 @@ }, }, }) - "###); + "#); } #[test] @@ -242,7 +248,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn ref_shorthand(&'a self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { reference: Some(Some(Lifetime { ident: "a", @@ -262,7 +268,7 @@ }, }, }) - "###); + "#); } #[test] @@ -270,7 +276,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn ref_mut_shorthand(&mut self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { reference: Some(None), mutability: Some, @@ -287,7 +293,7 @@ }, }, }) - "###); + "#); } #[test] @@ -295,7 +301,7 @@ let TraitItemFn { sig, .. } = parse_quote! { fn ref_mut_shorthand(&'a mut self); }; - snapshot!(&sig.inputs[0], @r###" + snapshot!(&sig.inputs[0], @r#" FnArg::Receiver(Receiver { reference: Some(Some(Lifetime { ident: "a", @@ -317,5 +323,5 @@ }, }, }) - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_round_trip.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_round_trip.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_round_trip.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_round_trip.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,11 +4,14 @@ #![feature(rustc_private)] #![allow( clippy::blocks_in_conditions, + clippy::elidable_lifetime_names, clippy::manual_assert, clippy::manual_let_else, clippy::match_like_matches_macro, + clippy::needless_lifetimes, clippy::uninlined_format_args )] +#![allow(mismatched_lifetime_syntaxes)] extern crate rustc_ast; extern crate rustc_ast_pretty; @@ -17,20 +20,21 @@ extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_expand; -extern crate rustc_parse as parse; +extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; use crate::common::eq::SpanlessEq; use quote::quote; use rustc_ast::ast::{ - AngleBracketedArg, AngleBracketedArgs, Crate, GenericArg, GenericParamKind, Generics, - WhereClause, + AngleBracketedArg, Crate, GenericArg, GenericArgs, GenericParamKind, Generics, }; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast_pretty::pprust; +use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_error_messages::{DiagMessage, LazyFallbackBundle}; use rustc_errors::{translation, Diag, PResult}; +use rustc_parse::lexer::StripTokens; use rustc_session::parse::ParseSess; use rustc_span::FileName; use std::borrow::Cow; @@ -44,16 +48,14 @@ #[macro_use] mod macros; -#[allow(dead_code)] mod common; - mod repo; #[test] fn test_round_trip() { - common::rayon_init(); + repo::rayon_init(); repo::clone_rust(); - let abort_after = common::abort_after(); + let abort_after = repo::abort_after(); if abort_after == 0 { panic!("skipping all round_trip tests"); } @@ -62,28 +64,41 @@ repo::for_each_rust_file(|path| test(path, &failed, abort_after)); - let failed = failed.load(Ordering::Relaxed); + let failed = failed.into_inner(); if failed > 0 { panic!("{} failures", failed); } } fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) { + let failed = || { + let prev_failed = failed.fetch_add(1, Ordering::Relaxed); + if prev_failed + 1 >= abort_after { + process::exit(1); + } + }; + let content = fs::read_to_string(path).unwrap(); - let start = Instant::now(); - let (krate, elapsed) = match syn::parse_file(&content) { - Ok(krate) => (krate, start.elapsed()), - Err(msg) => { + let (back, elapsed) = match panic::catch_unwind(|| { + let start = Instant::now(); + let result = syn::parse_file(&content); + let elapsed = start.elapsed(); + result.map(|krate| (quote!(#krate).to_string(), elapsed)) + }) { + Err(_) => { + errorf!("=== {}: syn panic\n", path.display()); + failed(); + return; + } + Ok(Err(msg)) => { errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg); - let prev_failed = failed.fetch_add(1, Ordering::Relaxed); - if prev_failed + 1 >= abort_after { - process::exit(1); - } + failed(); return; } + Ok(Ok(result)) => result, }; - let back = quote!(#krate).to_string(); + let edition = repo::edition(path).parse().unwrap(); rustc_span::create_session_if_not_set_then(edition, |_| { @@ -139,10 +154,7 @@ } }; if !equal { - let prev_failed = failed.fetch_add(1, Ordering::Relaxed); - if prev_failed + 1 >= abort_after { - process::exit(1); - } + failed(); } }); } @@ -151,7 +163,14 @@ static COUNTER: AtomicUsize = AtomicUsize::new(0); let counter = COUNTER.fetch_add(1, Ordering::Relaxed); let name = FileName::Custom(format!("test_round_trip{}", counter)); - parse::parse_crate_from_source_str(name, content, sess) + let mut parser = rustc_parse::new_parser_from_source_str( + sess, + name, + content, + StripTokens::ShebangAndFrontmatter, + ) + .unwrap(); + parser.parse_crate_mod() } fn translate_message(diagnostic: &Diag) -> Cow<'static, str> { @@ -194,21 +213,23 @@ struct NormalizeVisitor; impl MutVisitor for NormalizeVisitor { - fn visit_angle_bracketed_parameter_data(&mut self, e: &mut AngleBracketedArgs) { - #[derive(Ord, PartialOrd, Eq, PartialEq)] - enum Group { - Lifetimes, - TypesAndConsts, - Constraints, + fn visit_generic_args(&mut self, e: &mut GenericArgs) { + if let GenericArgs::AngleBracketed(e) = e { + #[derive(Ord, PartialOrd, Eq, PartialEq)] + enum Group { + Lifetimes, + TypesAndConsts, + Constraints, + } + e.args.sort_by_key(|arg| match arg { + AngleBracketedArg::Arg(arg) => match arg { + GenericArg::Lifetime(_) => Group::Lifetimes, + GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts, + }, + AngleBracketedArg::Constraint(_) => Group::Constraints, + }); } - e.args.sort_by_key(|arg| match arg { - AngleBracketedArg::Arg(arg) => match arg { - GenericArg::Lifetime(_) => Group::Lifetimes, - GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts, - }, - AngleBracketedArg::Constraint(_) => Group::Constraints, - }); - mut_visit::noop_visit_angle_bracketed_parameter_data(e, self); + mut_visit::walk_generic_args(self, e); } fn visit_generics(&mut self, e: &mut Generics) { @@ -223,12 +244,10 @@ Group::TypesAndConsts } }); - mut_visit::noop_visit_generics(e, self); - } - - fn visit_where_clause(&mut self, e: &mut WhereClause) { - if e.predicates.is_empty() { - e.has_where_token = false; + e.params + .flat_map_in_place(|param| self.flat_map_generic_param(param)); + if e.where_clause.predicates.is_empty() { + e.where_clause.has_where_token = false; } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_shebang.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_shebang.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_shebang.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_shebang.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,19 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; #[test] fn test_basic() { let content = "#!/usr/bin/env rustx\nfn main() {}"; let file = syn::parse_file(content).unwrap(); - snapshot!(file, @r###" + snapshot!(file, @r##" File { shebang: Some("#!/usr/bin/env rustx"), items: [ @@ -24,14 +30,14 @@ }, ], } - "###); + "##); } #[test] fn test_comment() { let content = "#!//am/i/a/comment\n[allow(dead_code)] fn main() {}"; let file = syn::parse_file(content).unwrap(); - snapshot!(file, @r###" + snapshot!(file, @r#" File { attrs: [ Attribute { @@ -63,5 +69,5 @@ }, ], } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_size.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_size.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_size.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_size.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,35 +1,53 @@ // Assumes proc-macro2's "span-locations" feature is off. -#![cfg(target_pointer_width = "64")] - use std::mem; use syn::{Expr, Item, Lit, Pat, Type}; -#[rustversion::attr(before(2022-11-24), ignore)] +#[rustversion::attr(before(2022-11-24), ignore = "requires nightly-2022-11-24 or newer")] +#[rustversion::attr( + since(2022-11-24), + cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") +)] #[test] fn test_expr_size() { assert_eq!(mem::size_of::(), 176); } -#[rustversion::attr(before(2022-09-09), ignore)] +#[rustversion::attr(before(2022-09-09), ignore = "requires nightly-2022-09-09 or newer")] +#[rustversion::attr( + since(2022-09-09), + cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") +)] #[test] fn test_item_size() { - assert_eq!(mem::size_of::(), 360); + assert_eq!(mem::size_of::(), 352); } -#[rustversion::attr(before(2023-04-29), ignore)] +#[rustversion::attr(before(2023-04-29), ignore = "requires nightly-2023-04-29 or newer")] +#[rustversion::attr( + since(2023-04-29), + cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") +)] #[test] fn test_type_size() { - assert_eq!(mem::size_of::(), 232); + assert_eq!(mem::size_of::(), 224); } -#[rustversion::attr(before(2023-04-29), ignore)] +#[rustversion::attr(before(2023-04-29), ignore = "requires nightly-2023-04-29 or newer")] +#[rustversion::attr( + since(2023-04-29), + cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") +)] #[test] fn test_pat_size() { assert_eq!(mem::size_of::(), 184); } -#[rustversion::attr(before(2023-12-20), ignore)] +#[rustversion::attr(before(2023-12-20), ignore = "requires nightly-2023-12-20 or newer")] +#[rustversion::attr( + since(2023-12-20), + cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") +)] #[test] fn test_lit_size() { assert_eq!(mem::size_of::(), 24); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_stmt.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_stmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_stmt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_stmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,15 @@ #![allow( clippy::assertions_on_result_states, + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, clippy::non_ascii_literal, clippy::uninlined_format_args )] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; @@ -16,21 +20,32 @@ fn test_raw_operator() { let stmt = syn::parse_str::("let _ = &raw const x;").unwrap(); - snapshot!(stmt, @r###" + snapshot!(stmt, @r#" Stmt::Local { pat: Pat::Wild, init: Some(LocalInit { - expr: Expr::Verbatim(`& raw const x`), + expr: Expr::RawAddr { + mutability: PointerMutability::Const, + expr: Expr::Path { + path: Path { + segments: [ + PathSegment { + ident: "x", + }, + ], + }, + }, + }, }), } - "###); + "#); } #[test] fn test_raw_variable() { let stmt = syn::parse_str::("let _ = &raw;").unwrap(); - snapshot!(stmt, @r###" + snapshot!(stmt, @r#" Stmt::Local { pat: Pat::Wild, init: Some(LocalInit { @@ -47,7 +62,7 @@ }, }), } - "###); + "#); } #[test] @@ -68,7 +83,7 @@ TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]), ))]); - snapshot!(tokens as Stmt, @r###" + snapshot!(tokens as Stmt, @r#" Stmt::Item(Item::Fn { vis: Visibility::Inherited, sig: Signature { @@ -81,11 +96,11 @@ stmts: [], }, }) - "###); + "#); let tokens = Group::new(Delimiter::None, quote!(let None = None)).to_token_stream(); let stmts = Block::parse_within.parse2(tokens).unwrap(); - snapshot!(stmts, @r###" + snapshot!(stmts, @r#" [ Stmt::Expr( Expr::Group { @@ -107,7 +122,7 @@ None, ), ] - "###); + "#); } #[test] @@ -116,7 +131,7 @@ let .. = 10; }; - snapshot!(tokens as Stmt, @r###" + snapshot!(tokens as Stmt, @r#" Stmt::Local { pat: Pat::Rest, init: Some(LocalInit { @@ -125,7 +140,7 @@ }, }), } - "###); + "#); } #[test] @@ -134,7 +149,7 @@ let Some(x) = None else { return 0; }; }; - snapshot!(tokens as Stmt, @r###" + snapshot!(tokens as Stmt, @r#" Stmt::Local { pat: Pat::TupleStruct { path: Path { @@ -176,7 +191,7 @@ }), }), } - "###); + "#); } #[test] @@ -190,7 +205,7 @@ } }; - snapshot!(tokens as Stmt, @r###" + snapshot!(tokens as Stmt, @r#" Stmt::Item(Item::Fn { vis: Visibility::Inherited, sig: Signature { @@ -260,7 +275,7 @@ ], }, }) - "###); + "#); } #[test] @@ -274,7 +289,7 @@ let stmts = Block::parse_within.parse2(tokens).unwrap(); - snapshot!(stmts, @r###" + snapshot!(stmts, @r#" [ Stmt::Expr( Expr::Loop { @@ -289,7 +304,7 @@ None, ), ] - "###); + "#); let tokens = quote! { 'a: loop {} @@ -298,7 +313,7 @@ let stmts = Block::parse_within.parse2(tokens).unwrap(); - snapshot!(stmts, @r###" + snapshot!(stmts, @r#" [ Stmt::Expr( Expr::Loop { @@ -318,5 +333,5 @@ None, ), ] - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_token_trees.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_token_trees.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_token_trees.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_token_trees.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::TokenStream; use quote::quote; @@ -17,11 +23,11 @@ } "; - snapshot!(input as TokenStream, @r###" + snapshot!(input as TokenStream, @r##" TokenStream( `# [derive (Debug , Clone)] pub struct Item { pub ident : Ident , pub attrs : Vec < Attribute >, }`, ) - "###); + "##); } #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_ty.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_ty.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_ty.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_ty.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; @@ -28,7 +34,7 @@ TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { path: Path { segments: [ @@ -51,7 +57,7 @@ ], }, } - "###); + "#); // mimics the token stream corresponding to `$ty::` let tokens = TokenStream::from_iter([ @@ -63,7 +69,7 @@ TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { path: Path { segments: [ @@ -87,7 +93,7 @@ ], }, } - "###); + "#); } #[test] @@ -100,7 +106,7 @@ TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { path: Path { segments: [ @@ -138,7 +144,7 @@ ], }, } - "###); + "#); } #[test] @@ -151,7 +157,7 @@ TokenTree::Ident(Ident::new("Item", Span::call_site())), ]); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { path: Path { segments: [ @@ -178,7 +184,7 @@ ], }, } - "###); + "#); let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })), @@ -187,7 +193,7 @@ TokenTree::Ident(Ident::new("Element", Span::call_site())), ]); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::Path { qself: Some(QSelf { ty: Type::Slice { @@ -212,13 +218,13 @@ ], }, } - "###); + "#); } #[test] fn test_trait_object() { let tokens = quote!(dyn for<'a> Trait<'a> + 'static); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::TraitObject { dyn_token: Some, bounds: [ @@ -253,10 +259,10 @@ }, ], } - "###); + "#); let tokens = quote!(dyn 'a + Trait); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::TraitObject { dyn_token: Some, bounds: [ @@ -275,7 +281,7 @@ }), ], } - "###); + "#); // None of the following are valid Rust types. syn::parse_str::("for<'a> dyn Trait<'a>").unwrap_err(); @@ -286,7 +292,7 @@ fn test_trailing_plus() { #[rustfmt::skip] let tokens = quote!(impl Trait +); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::ImplTrait { bounds: [ TypeParamBound::Trait(TraitBound { @@ -301,11 +307,11 @@ Token![+], ], } - "###); + "#); #[rustfmt::skip] let tokens = quote!(dyn Trait +); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::TraitObject { dyn_token: Some, bounds: [ @@ -321,11 +327,11 @@ Token![+], ], } - "###); + "#); #[rustfmt::skip] let tokens = quote!(Trait +); - snapshot!(tokens as Type, @r###" + snapshot!(tokens as Type, @r#" Type::TraitObject { bounds: [ TypeParamBound::Trait(TraitBound { @@ -340,7 +346,7 @@ Token![+], ], } - "###); + "#); } #[test] @@ -353,27 +359,27 @@ expr.elems.push_value(parse_quote!(_)); // Must not parse to Type::Paren - snapshot!(expr.to_token_stream() as Type, @r###" + snapshot!(expr.to_token_stream() as Type, @r#" Type::Tuple { elems: [ Type::Infer, Token![,], ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Type, @r###" + snapshot!(expr.to_token_stream() as Type, @r#" Type::Tuple { elems: [ Type::Infer, Token![,], ], } - "###); + "#); expr.elems.push_value(parse_quote!(_)); - snapshot!(expr.to_token_stream() as Type, @r###" + snapshot!(expr.to_token_stream() as Type, @r#" Type::Tuple { elems: [ Type::Infer, @@ -381,10 +387,10 @@ Type::Infer, ], } - "###); + "#); expr.elems.push_punct(::default()); - snapshot!(expr.to_token_stream() as Type, @r###" + snapshot!(expr.to_token_stream() as Type, @r#" Type::Tuple { elems: [ Type::Infer, @@ -393,5 +399,73 @@ Token![,], ], } - "###); + "#); +} + +#[test] +fn test_impl_trait_use() { + let tokens = quote! { + impl Sized + use<'_, 'a, A, Test> + }; + + snapshot!(tokens as Type, @r#" + Type::ImplTrait { + bounds: [ + TypeParamBound::Trait(TraitBound { + path: Path { + segments: [ + PathSegment { + ident: "Sized", + }, + ], + }, + }), + Token![+], + TypeParamBound::PreciseCapture(PreciseCapture { + params: [ + CapturedParam::Lifetime(Lifetime { + ident: "_", + }), + Token![,], + CapturedParam::Lifetime(Lifetime { + ident: "a", + }), + Token![,], + CapturedParam::Ident("A"), + Token![,], + CapturedParam::Ident("Test"), + ], + }), + ], + } + "#); + + let trailing = quote! { + impl Sized + use<'_,> + }; + + snapshot!(trailing as Type, @r#" + Type::ImplTrait { + bounds: [ + TypeParamBound::Trait(TraitBound { + path: Path { + segments: [ + PathSegment { + ident: "Sized", + }, + ], + }, + }), + Token![+], + TypeParamBound::PreciseCapture(PreciseCapture { + params: [ + CapturedParam::Lifetime(Lifetime { + ident: "_", + }), + Token![,], + ], + }), + ], + } + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_unparenthesize.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_unparenthesize.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_unparenthesize.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_unparenthesize.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,70 @@ +#![cfg(not(miri))] +#![recursion_limit = "1024"] +#![feature(rustc_private)] +#![allow( + clippy::elidable_lifetime_names, + clippy::manual_assert, + clippy::match_like_matches_macro, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] + +use crate::common::visit::{AsIfPrinted, FlattenParens}; +use quote::ToTokens as _; +use std::fs; +use std::panic; +use std::path::Path; +use std::sync::atomic::{AtomicUsize, Ordering}; +use syn::visit_mut::VisitMut as _; + +#[macro_use] +mod macros; + +mod common; +mod repo; + +#[test] +fn test_unparenthesize() { + repo::rayon_init(); + repo::clone_rust(); + + let failed = AtomicUsize::new(0); + + repo::for_each_rust_file(|path| test(path, &failed)); + + let failed = failed.into_inner(); + if failed > 0 { + panic!("{} failures", failed); + } +} + +fn test(path: &Path, failed: &AtomicUsize) { + let content = fs::read_to_string(path).unwrap(); + + match panic::catch_unwind(|| -> syn::Result<()> { + let mut before = syn::parse_file(&content)?; + FlattenParens::discard_attrs().visit_file_mut(&mut before); + let printed = before.to_token_stream(); + let mut after = syn::parse2::(printed.clone())?; + FlattenParens::discard_attrs().visit_file_mut(&mut after); + // Normalize features that we expect Syn not to print. + AsIfPrinted.visit_file_mut(&mut before); + if before != after { + errorf!("=== {}\n", path.display()); + if failed.fetch_add(1, Ordering::Relaxed) == 0 { + errorf!("BEFORE:\n{:#?}\nAFTER:\n{:#?}\n", before, after); + } + } + Ok(()) + }) { + Err(_) => { + errorf!("=== {}: syn panic\n", path.display()); + failed.fetch_add(1, Ordering::Relaxed); + } + Ok(Err(msg)) => { + errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg); + failed.fetch_add(1, Ordering::Relaxed); + } + Ok(Ok(())) => {} + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_visibility.rs clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_visibility.rs --- clamav-1.4.3+dfsg/.cargo/vendor/syn/tests/test_visibility.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn/tests/test_visibility.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,13 @@ -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::uninlined_format_args +)] #[macro_use] -mod macros; +mod snapshot; + +mod debug; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::quote; @@ -117,7 +123,7 @@ )), ]); - snapshot!(tokens as DeriveInput, @r###" + snapshot!(tokens as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -135,7 +141,7 @@ }, }, } - "###); + "#); } #[test] @@ -154,7 +160,7 @@ TokenTree::Punct(Punct::new(';', Spacing::Alone)), ]); - snapshot!(tokens as DeriveInput, @r###" + snapshot!(tokens as DeriveInput, @r#" DeriveInput { vis: Visibility::Inherited, ident: "S", @@ -181,5 +187,5 @@ semi_token: Some, }, } - "###); + "#); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"139a7e42e4c95f9730d4dfe05dd5e09ee59f713eacc310921a61d9fdfc0bdce0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ea9f2b6340b302b5608d2bedcda7e2d707f3eaebf4cc983c02d55071ead7096f","benches/file.rs":"3d737ef3878f6e242b003af9bd539e565f98439a12ee44d9548d84e3fdd7af0c","benches/rust.rs":"11ac9fe898a7bf1bd63e8a8cc9c08bd795b01f0248215cff99afaaf28ce87fab","build.rs":"b815649fd2929d3debd93a58f5da2fb8eba506047a6a5ba538347305828a87b0","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"4d15f35273d485261be4f1a765ae03abc1daee9fc9dac5fb4f9b624d6b22cb58","src/custom_keyword.rs":"5c706fc3611e73d16b8c019d7ecb848a86b1ccfcd9e556f80bb6e6a4abe058a8","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"75d2c2b5d6a01bf8a6fa2845e41663d8045a78b4b191f1a1bd7c93619d20017a","src/derive.rs":"ee24a202be2d36ccdff576dd9cd765e94b33ef2286946e6725d75b08e777d462","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/drops.rs":"013385f1dd95663f1afab41abc1e2eea04181998644828935ca564c74d6462ae","src/error.rs":"b30e738fdab7d10e126350e09f7ad907bf4dc14e684b9ed9eeea001c7ee356e0","src/export.rs":"0cf50d70c32d5fddba8b1193032df62e560237c113df3e86ba26b565cc82838e","src/expr.rs":"5eea3828f3291b0ce5463ed5f0c23fc8a39aeceae68a3247ae02ae467dd35a98","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"76e89fe155fedf43bc4a252af7e35319b82ce455f584bad8698fdc3f9b7f5d4e","src/gen/debug.rs":"4b05e474e864ce6bf1a5a6ab48ee6c0ecdf41a0d750237990cf2e31963bc1208","src/gen/eq.rs":"79f84836fdcd5cfa352f38055dab7c3246c7757650946c1c701234b11021652a","src/gen/fold.rs":"fcd6a05c8c8e0c36e7ede8593002528b553c8b648fbed452106fd6a8a8c9212a","src/gen/hash.rs":"575e8beae303c1eabda12bf76cbd82672268c502a8ebb8517aab18b40fdbc44e","src/gen/visit.rs":"ced9f6c17d2b3eb3553faab710cb2b3d44d6bca7d1862c8c5da09c3d45debecb","src/gen/visit_mut.rs":"966ea340c53461bf8a1c6bed3c882e4ab8b8907fd18ac35531266f7891ae5f46","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"b81ce0d3ea0f7accef4590d5181cecc4589395865abaea60b0470da727f17340","src/group.rs":"166f0fbb365471ffa3e4f554b72c2b460cbf7e3a1f9bec6c01ef6bbbcd751041","src/ident.rs":"2443e43561abea7eea577b141422258237a663499c839923d8a5ca6fea2470db","src/item.rs":"419c4d6135a7ca7b8f94b5ba038b6af8fcb3939ae807153a19e3c82e9b01e0b7","src/lib.rs":"de155fed49dffb1756ca8b76d82209fe8bc80c4dda6684f669e98835147869a5","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"667d90787fefac4d25e88509799e8423b9f87125027740c30644dd28adfab95d","src/lookahead.rs":"e2c2b6d55906421e83dab51463b58bc6dcb582f1bff9303c8b62afefb8d71e5f","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"936f503c2fcde602f05220954ecaf87625c6138d0af13d33d56c7b6530110084","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"7b2f8caddf25a5734cbcdf7cbf043cbf9afbc07b484966cd59ddfcec9f970fb3","src/parse_macro_input.rs":"a5d16859b782bb6a2754c1066468a2f1ea05b57390caa32175bb84064973be7b","src/parse_quote.rs":"d7d996f1382c68b5fbfd4b7327ce1d389cd43c3bb3c4f382a35994d0bb79d8ab","src/pat.rs":"b2de04ae6c01df50eab9d1c3908287aca8424adc2007b926c7bcf74d1f64d40a","src/path.rs":"58a4fb3b1ff76d32cfd84a3914f8cadbf55b363c1929222b362b7465385520ac","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"44c29523dee76605be2531674fe21ed2f1bbd02559aac8b7a49c70af23129ca1","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"601a6914f1e0bf97ae0d31d474a531d195b8c251a4ded11aa8746ac0018d367b","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"9befd22f8c8ac731b7f68008552a1335797a3ef19184190eec0e103e4ebe18a7","src/verbatim.rs":"96d4280e4556a1841b8dcb306bc35a94d18f71dceb63f3c27a4fe7f776191760","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/common/eq.rs":"e930fb0bdcec3e787986b56785b1db580e5a26a5131df2f2b91a6da37069de15","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"1b7f875344cb04a7dd3df62deac2f410a9d107c097986e68006d87465f5f5306","tests/debug/mod.rs":"3a6bb799f478101f71c84c6f1a854a58afe2f9db43c39017909346ca20262d94","tests/macros/mod.rs":"aff805b35cfd55aef6a1359ff747e4023afcb08d69d86aff4c19465d29dda088","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1108.rs":"adcc55a42239d344da74216ed85fc14153ddd6ca4dec4872d8339604ba78c185","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"159c2c4b6416d26ac42ffc35f6cb587c4c1e2b0f24de9aa42b0337a534d7d86d","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"62bb86aaaaf730187a46ff700a8e3b2d1a163039b109b6a483aa44ed2b6806fe","tests/test_expr.rs":"41eb343829ad36cdea40cd06d45a90765e7fe6f1e47dd550daf1b6096c3a7b44","tests/test_generics.rs":"54b7d2afc19aa6e9049585f4c8f7d3f0c29ac3bd11a2c769e9df76f18a4f5ecb","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"a3642c80066f1e7787becfd0278af90a6b7968d6c1249e25e81663aa454cfb2a","tests/test_iterators.rs":"9cf6fde17853ce7d5617e1de9ef901c47ca35c0f1c2dd668c0d0604d7b48598c","tests/test_lit.rs":"137cc9f882cca58f0f2c109535b7ad03c5a35a0aee0cbb9e98ad94710d64e265","tests/test_meta.rs":"65d4586d131f6cac66694ca5e936748ec4e7f7423af6d8da509240e6be14800b","tests/test_parse_buffer.rs":"68d857f776396d064fcc0023c37093c2fbf75ee68e8241d4014d00d1423c18e9","tests/test_parse_stream.rs":"bf1db6fab7ac396fa61012faccbe6ffbc9c3d795ed2900be75e91c5b09b0c62f","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"71092a5ae2c9143b92a8fe15a92d39958b3c28bd4d4275cfb2d22cbdd53ada07","tests/test_precedence.rs":"736eee861c4c7a3d7d4387d2fb1b5eced1541790d34974f72b0a5532797e73c3","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"c3c415413d5177a728c7cbbfb7ef44aebbc6a2c821dd56695156e9e33636fd57","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"6720d55569808244ab011364c39931f06aa509cd05f98ab908b0670e8501b3c8","tests/test_stmt.rs":"0601fc32131b5501dfcdc4b4248d46bf21e0a98a49eb19439e1a46869dfb30b7","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"f71d7f7f1c038aaabea8dd4c03c0d5752c76d570f8b4885a81659825bbb4d576","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3e7dfbd01486ec4277c4e4b988f9c7fc5dc3e51c9d8c7dc4fe425a48bbd9f090","Cargo.toml":"139a7e42e4c95f9730d4dfe05dd5e09ee59f713eacc310921a61d9fdfc0bdce0","Cargo.toml.orig":"19a1c09847e02f3b7d2d434fb4d8b52694e47bd1b9d04594b329c7866cccc013","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ea9f2b6340b302b5608d2bedcda7e2d707f3eaebf4cc983c02d55071ead7096f","benches/file.rs":"3d737ef3878f6e242b003af9bd539e565f98439a12ee44d9548d84e3fdd7af0c","benches/rust.rs":"11ac9fe898a7bf1bd63e8a8cc9c08bd795b01f0248215cff99afaaf28ce87fab","build.rs":"b815649fd2929d3debd93a58f5da2fb8eba506047a6a5ba538347305828a87b0","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"4d15f35273d485261be4f1a765ae03abc1daee9fc9dac5fb4f9b624d6b22cb58","src/custom_keyword.rs":"5c706fc3611e73d16b8c019d7ecb848a86b1ccfcd9e556f80bb6e6a4abe058a8","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"75d2c2b5d6a01bf8a6fa2845e41663d8045a78b4b191f1a1bd7c93619d20017a","src/derive.rs":"ee24a202be2d36ccdff576dd9cd765e94b33ef2286946e6725d75b08e777d462","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/drops.rs":"013385f1dd95663f1afab41abc1e2eea04181998644828935ca564c74d6462ae","src/error.rs":"b30e738fdab7d10e126350e09f7ad907bf4dc14e684b9ed9eeea001c7ee356e0","src/export.rs":"0cf50d70c32d5fddba8b1193032df62e560237c113df3e86ba26b565cc82838e","src/expr.rs":"5eea3828f3291b0ce5463ed5f0c23fc8a39aeceae68a3247ae02ae467dd35a98","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"76e89fe155fedf43bc4a252af7e35319b82ce455f584bad8698fdc3f9b7f5d4e","src/gen/debug.rs":"4b05e474e864ce6bf1a5a6ab48ee6c0ecdf41a0d750237990cf2e31963bc1208","src/gen/eq.rs":"79f84836fdcd5cfa352f38055dab7c3246c7757650946c1c701234b11021652a","src/gen/fold.rs":"fcd6a05c8c8e0c36e7ede8593002528b553c8b648fbed452106fd6a8a8c9212a","src/gen/hash.rs":"575e8beae303c1eabda12bf76cbd82672268c502a8ebb8517aab18b40fdbc44e","src/gen/visit.rs":"ced9f6c17d2b3eb3553faab710cb2b3d44d6bca7d1862c8c5da09c3d45debecb","src/gen/visit_mut.rs":"966ea340c53461bf8a1c6bed3c882e4ab8b8907fd18ac35531266f7891ae5f46","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"b81ce0d3ea0f7accef4590d5181cecc4589395865abaea60b0470da727f17340","src/group.rs":"166f0fbb365471ffa3e4f554b72c2b460cbf7e3a1f9bec6c01ef6bbbcd751041","src/ident.rs":"2443e43561abea7eea577b141422258237a663499c839923d8a5ca6fea2470db","src/item.rs":"419c4d6135a7ca7b8f94b5ba038b6af8fcb3939ae807153a19e3c82e9b01e0b7","src/lib.rs":"de155fed49dffb1756ca8b76d82209fe8bc80c4dda6684f669e98835147869a5","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"667d90787fefac4d25e88509799e8423b9f87125027740c30644dd28adfab95d","src/lookahead.rs":"e2c2b6d55906421e83dab51463b58bc6dcb582f1bff9303c8b62afefb8d71e5f","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"936f503c2fcde602f05220954ecaf87625c6138d0af13d33d56c7b6530110084","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"7b2f8caddf25a5734cbcdf7cbf043cbf9afbc07b484966cd59ddfcec9f970fb3","src/parse_macro_input.rs":"a5d16859b782bb6a2754c1066468a2f1ea05b57390caa32175bb84064973be7b","src/parse_quote.rs":"d7d996f1382c68b5fbfd4b7327ce1d389cd43c3bb3c4f382a35994d0bb79d8ab","src/pat.rs":"b2de04ae6c01df50eab9d1c3908287aca8424adc2007b926c7bcf74d1f64d40a","src/path.rs":"58a4fb3b1ff76d32cfd84a3914f8cadbf55b363c1929222b362b7465385520ac","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"44c29523dee76605be2531674fe21ed2f1bbd02559aac8b7a49c70af23129ca1","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"601a6914f1e0bf97ae0d31d474a531d195b8c251a4ded11aa8746ac0018d367b","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"9befd22f8c8ac731b7f68008552a1335797a3ef19184190eec0e103e4ebe18a7","src/verbatim.rs":"96d4280e4556a1841b8dcb306bc35a94d18f71dceb63f3c27a4fe7f776191760","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/common/eq.rs":"e930fb0bdcec3e787986b56785b1db580e5a26a5131df2f2b91a6da37069de15","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"1b7f875344cb04a7dd3df62deac2f410a9d107c097986e68006d87465f5f5306","tests/debug/mod.rs":"3a6bb799f478101f71c84c6f1a854a58afe2f9db43c39017909346ca20262d94","tests/macros/mod.rs":"aff805b35cfd55aef6a1359ff747e4023afcb08d69d86aff4c19465d29dda088","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1108.rs":"adcc55a42239d344da74216ed85fc14153ddd6ca4dec4872d8339604ba78c185","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"159c2c4b6416d26ac42ffc35f6cb587c4c1e2b0f24de9aa42b0337a534d7d86d","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"62bb86aaaaf730187a46ff700a8e3b2d1a163039b109b6a483aa44ed2b6806fe","tests/test_expr.rs":"41eb343829ad36cdea40cd06d45a90765e7fe6f1e47dd550daf1b6096c3a7b44","tests/test_generics.rs":"54b7d2afc19aa6e9049585f4c8f7d3f0c29ac3bd11a2c769e9df76f18a4f5ecb","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"a3642c80066f1e7787becfd0278af90a6b7968d6c1249e25e81663aa454cfb2a","tests/test_iterators.rs":"9cf6fde17853ce7d5617e1de9ef901c47ca35c0f1c2dd668c0d0604d7b48598c","tests/test_lit.rs":"137cc9f882cca58f0f2c109535b7ad03c5a35a0aee0cbb9e98ad94710d64e265","tests/test_meta.rs":"65d4586d131f6cac66694ca5e936748ec4e7f7423af6d8da509240e6be14800b","tests/test_parse_buffer.rs":"68d857f776396d064fcc0023c37093c2fbf75ee68e8241d4014d00d1423c18e9","tests/test_parse_stream.rs":"bf1db6fab7ac396fa61012faccbe6ffbc9c3d795ed2900be75e91c5b09b0c62f","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"71092a5ae2c9143b92a8fe15a92d39958b3c28bd4d4275cfb2d22cbdd53ada07","tests/test_precedence.rs":"736eee861c4c7a3d7d4387d2fb1b5eced1541790d34974f72b0a5532797e73c3","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"c3c415413d5177a728c7cbbfb7ef44aebbc6a2c821dd56695156e9e33636fd57","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"6720d55569808244ab011364c39931f06aa509cd05f98ab908b0670e8501b3c8","tests/test_stmt.rs":"0601fc32131b5501dfcdc4b4248d46bf21e0a98a49eb19439e1a46869dfb30b7","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"f71d7f7f1c038aaabea8dd4c03c0d5752c76d570f8b4885a81659825bbb4d576","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "bfa790b8e445dc67b7ab94d75adb1a92d6296c9a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/syn-1.0.109/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/syn-1.0.109/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,91 @@ +[package] +name = "syn" +version = "1.0.109" # don't forget to update html_root_url and syn.json +authors = ["David Tolnay "] +categories = ["development-tools::procedural-macro-helpers", "parser-implementations"] +description = "Parser for Rust source code" +documentation = "https://docs.rs/syn" +edition = "2018" +include = [ + "/benches/**", + "/build.rs", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src/**", + "/tests/**", +] +keywords = ["macros", "syn"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/syn" +rust-version = "1.31" + +[features] +default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] +derive = [] +full = [] +parsing = [] +printing = ["quote"] +visit = [] +visit-mut = [] +fold = [] +clone-impls = [] +extra-traits = [] +proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"] +test = ["syn-test-suite/all-features"] + +[dependencies] +proc-macro2 = { version = "1.0.46", default-features = false } +quote = { version = "1.0", optional = true, default-features = false } +unicode-ident = "1.0" + +[dev-dependencies] +anyhow = "1.0" +automod = "1.0" +flate2 = "1.0" +insta = "1.0" +rayon = "1.0" +ref-cast = "1.0" +regex = "1.0" +reqwest = { version = "0.11", features = ["blocking"] } +syn-test-suite = { version = "0", path = "tests/features" } +tar = "0.4.16" +termcolor = "1.0" +walkdir = "2.1" + +[lib] +doc-scrape-examples = false + +[[bench]] +name = "rust" +harness = false +required-features = ["full", "parsing"] + +[[bench]] +name = "file" +required-features = ["full", "parsing"] + +[package.metadata.docs.rs] +all-features = true +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "doc_cfg"] + +[package.metadata.playground] +features = ["full", "visit", "visit-mut", "fold", "extra-traits"] + +[workspace] +members = [ + "dev", + "examples/dump-syntax", + "examples/heapsize/example", + "examples/heapsize/heapsize", + "examples/heapsize/heapsize_derive", + "examples/lazy-static/example", + "examples/lazy-static/lazy-static", + "examples/trace-var/example", + "examples/trace-var/trace-var", + "json", + "tests/crates", + "tests/features", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"3b8847cb3011e8356a39d1fbf196515b6ca3d9ef88341e71c5dc2e395e2245e6","Cargo.toml":"3044a0c26c85859276218ba2d300f5635ab6a5a67b80a65cb56e21ee821e6eac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","README.md":"972f1c35ec653943e067fd2c3d09e78f593b2e9e1eafd5b9668bf3653513de3e","deny.toml":"cb4c35327cbf8a20a6b19ac3fdf2c47b665da1662c90e3eae8a3825f9b72596e","src/dir/imp/any.rs":"1f195acdc8d4c309b0aa281810be55663ac5c44945c93d80159dd868b4faf242","src/dir/imp/mod.rs":"4df49b0c0e25a436ceaf566cfc0ca3da6793a91e6e29774d5628a482848f630c","src/dir/imp/unix.rs":"a01a1c409643981b31e78ac0076074768602e2b7e381d061d0cdb287d42972fe","src/dir/mod.rs":"71633ec68270d8f63ed735df25167885903c113985b7eec14e1e7a31b22ad600","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"f6da9fcd93f11889670a251fdd8231b5f4614e5a971b7b183f52b44af68568d5","src/file/imp/other.rs":"9efa22cc67555bef747e1870e8deb74c3d57b4c0fed751b34f81eeff910b5a88","src/file/imp/unix.rs":"c194a625b4d97caba0369f080ea5b9f6f534a0f52f230df2e6df22212d072926","src/file/imp/windows.rs":"cff7a39a64651989eed59374724cc441312ba21598978cbe6bbd132d8a8b96a8","src/file/mod.rs":"aa09c71c2c53d148da2bb0ebf67aceac05aa4bf4be18d5fdbd9dcd8ab25dcf80","src/lib.rs":"f29a9148471ddaba51945d8f1094406572c42175e33ed599370b1cb9ff9831fa","src/spooled.rs":"d37ee1153be2338ac0e602df9814514a98a832495ceb5bbb894359474094aa89","src/util.rs":"926de4cbe958b26905646ff8e408eedebc1d498bd4e37f11f00fae740ed94eb2","tests/namedtempfile.rs":"87dd6a8bba2fdd77418ec2b50b8aec5e26d05a2f780182b4e9ff464b3404d47c","tests/spooled.rs":"331854b147626cc48dacb2c36d0be11758ab586324e04b7b39b216f65d5e8053","tests/tempdir.rs":"f5a86f56df6bb60aa5dfa136ce75f8d0f29c2e87546dccfe1fb680d209be525e","tests/tempfile.rs":"9a2f8142151a6aa2fd047aa3749f9982ece4b080a3ace0d3c58d6bdb3f883c81"},"package":"85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"42938b2fe6feac4e7b88129c71f3e658fed25d15ef842ddc2bfc38a96d53a249",".github/dependabot.yml":"514557e7c5180a3f89e89cdc98112fd32c362216ae8478bfac4dcfee874f330f",".github/workflows/ci.yml":"841d1cc5d4488e967ee4a6d09be106651cd560c5cf5ad7b9af1e5307929a73a5","CHANGELOG.md":"3b8847cb3011e8356a39d1fbf196515b6ca3d9ef88341e71c5dc2e395e2245e6","Cargo.toml":"3044a0c26c85859276218ba2d300f5635ab6a5a67b80a65cb56e21ee821e6eac","Cargo.toml.orig":"a3dd80122fa0ab29639e1b1adb641348ee9f22e46766b4b4056b12d92f04bfd5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","README.md":"972f1c35ec653943e067fd2c3d09e78f593b2e9e1eafd5b9668bf3653513de3e","deny.toml":"cb4c35327cbf8a20a6b19ac3fdf2c47b665da1662c90e3eae8a3825f9b72596e","src/dir/imp/any.rs":"1f195acdc8d4c309b0aa281810be55663ac5c44945c93d80159dd868b4faf242","src/dir/imp/mod.rs":"4df49b0c0e25a436ceaf566cfc0ca3da6793a91e6e29774d5628a482848f630c","src/dir/imp/unix.rs":"a01a1c409643981b31e78ac0076074768602e2b7e381d061d0cdb287d42972fe","src/dir/mod.rs":"71633ec68270d8f63ed735df25167885903c113985b7eec14e1e7a31b22ad600","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"f6da9fcd93f11889670a251fdd8231b5f4614e5a971b7b183f52b44af68568d5","src/file/imp/other.rs":"9efa22cc67555bef747e1870e8deb74c3d57b4c0fed751b34f81eeff910b5a88","src/file/imp/unix.rs":"c194a625b4d97caba0369f080ea5b9f6f534a0f52f230df2e6df22212d072926","src/file/imp/windows.rs":"cff7a39a64651989eed59374724cc441312ba21598978cbe6bbd132d8a8b96a8","src/file/mod.rs":"aa09c71c2c53d148da2bb0ebf67aceac05aa4bf4be18d5fdbd9dcd8ab25dcf80","src/lib.rs":"f29a9148471ddaba51945d8f1094406572c42175e33ed599370b1cb9ff9831fa","src/spooled.rs":"d37ee1153be2338ac0e602df9814514a98a832495ceb5bbb894359474094aa89","src/util.rs":"926de4cbe958b26905646ff8e408eedebc1d498bd4e37f11f00fae740ed94eb2","tests/namedtempfile.rs":"87dd6a8bba2fdd77418ec2b50b8aec5e26d05a2f780182b4e9ff464b3404d47c","tests/spooled.rs":"331854b147626cc48dacb2c36d0be11758ab586324e04b7b39b216f65d5e8053","tests/tempdir.rs":"f5a86f56df6bb60aa5dfa136ce75f8d0f29c2e87546dccfe1fb680d209be525e","tests/tempfile.rs":"9a2f8142151a6aa2fd047aa3749f9982ece4b080a3ace0d3c58d6bdb3f883c81"},"package":"85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "094c1151105ae4641f367d3ab50da7bbfad62eb4" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/tempfile/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tempfile/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,85 @@ +on: + push: + branches: + - master + pull_request: + branches: + - master + +name: CI +jobs: + deny: + name: Cargo deny + strategy: + matrix: + os: + - ubuntu-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 + timeout-minutes: 10 + + build_and_test: + name: OS Test + strategy: + fail-fast: false + matrix: + rust-version: + - nightly + - stable + - "1.63" + os: + - ubuntu-latest + - windows-latest + - macos-latest + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust-version }} + - name: Build + run: cargo build + - name: Test + run: cargo test + wasi: + name: WASI Test Build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@nightly + - name: Install Cargo WASI + run: cargo install cargo-wasi + - name: Build + run: cargo wasi build --features nightly + wasm: + name: WASM Test Build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown + - name: Build + run: cargo build --target wasm32-unknown-unknown + lint: + name: Clippy and fmt + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + - name: Check formatting + run: cargo fmt --check + - name: Check for clippy lints + run: cargo clippy diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tempfile/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/tempfile/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/tempfile/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tempfile/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +[package] +name = "tempfile" +version = "3.10.1" +authors = [ + "Steven Allen ", + "The Rust Project Developers", + "Ashley Mannix ", + "Jason White ", +] +documentation = "https://docs.rs/tempfile" +edition = "2021" +rust-version = "1.63" +homepage = "https://stebalien.com/projects/tempfile-rs/" +keywords = ["tempfile", "tmpfile", "filesystem"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/Stebalien/tempfile" +description = "A library for managing temporary files and directories." + +[dependencies] +cfg-if = "1" +fastrand = "2.0.1" + +[target.'cfg(any(unix, target_os = "wasi"))'.dependencies] +rustix = { version = "0.38.31", features = ["fs"] } + +[target.'cfg(windows)'.dependencies.windows-sys] +version = "0.52" +features = [ + "Win32_Storage_FileSystem", + "Win32_Foundation", +] + +[dev-dependencies] +doc-comment = "0.3" + +[features] +nightly = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"7df807832514d69476a436a1466ed9cefde6d73f8fff7829718096c8bf6bb88e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"106c5a937767d49503e1fc5eae1b924f57f15decd8583720a3c652483e348a64","build.rs":"e93f4e6f8b7d24c9b119a85ea134067d2c2a7f78e082c1ab1e541c41225d5a36","build/probe.rs":"3245569a228727091f335db44c7c2f729729b2dfac9f46c1143eb179439f223d","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"cf3c98abb2b9e06afa3c4aba0df14938417c3e330315863437561cbb3573888b","src/display.rs":"0adeeeb524c6bee06de179d54e82a43dc12d2c5b7f69f6fd268ba4611ebf5233","src/lib.rs":"6a823f259101ba3c28fc8824afbe6ce66c1c4ffa7bea183172b25b891dfa1695","src/provide.rs":"8007e22953bacfcc57bb7d12a03fbeb0acece5d2ec889cf55522a4e071d26df3","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"a8f038490fb881463c0e8c36557617c47cf2d181f16c00525d4d139c7964fade","tests/test_deprecated.rs":"7b80a10f090a3982da017556d3d71398abcead59afd8278c7b9d9b1f7b66c7b3","tests/test_display.rs":"91a6bf704fd78a5565330f438f30ae4088aa8bc7ac5e1412401e440072408c03","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"d35b11040ebc547467f52571051854e3e094d52b8e229fa3d44700d5f40959a2","tests/test_from.rs":"36bd22be7b048cd187a19076aeac1456040f20a0b677b01c6003998b63439ea1","tests/test_generics.rs":"adc61f0d5fe8d53796848d44fb0373be5eab19a1eeb6a7172bc6f0dd7b91199c","tests/test_lints.rs":"93d66ea5b6b91634ddf18a520b455f8bc65f3e9bbf90874e239f45ab15b0c125","tests/test_option.rs":"ac30d929c019d6c54d1c1792b09e43c18dc0e4123b82051ff9e5db5e63c15e43","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/fallback-impl-with-display.rs":"141a8efbabe3fdac584bec8a61e6cceb58a34a70b825f6277037bf9d591150eb","tests/ui/fallback-impl-with-display.stderr":"1b3dad712b97598fbee70125471de1a8106eb161d42ce1f790ae07be8c8984ba","tests/ui/from-backtrace-backtrace.rs":"0caac64486c0eb9c076553c0502d468fbc477602a9a2595165a1dcd95524e5ff","tests/ui/from-backtrace-backtrace.stderr":"e24156ae0828878f3282341732b6e032eaa8cb4b4db366a6b5437ed0731d40a7","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/invalid-input-impl-anyway.rs":"6de91f71ddf038dffa3b9da33763a2ec3a5aa0047528e19ba998d5efe3aada5b","tests/ui/invalid-input-impl-anyway.stderr":"fa2725053cd87fc37f87546b377e6e5eed95c45e2a960863303b21a1935fdddb","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-display.rs":"c1fd1bc0ec0fb103d7f7b128837f717d49485662839899d570b3c983f1332888","tests/ui/missing-display.stderr":"a8de0f1559da9320ee99ef334937d532d9e9f40a32ed7f8ce56fb465628bff96","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"c145dbdd39e145b5c6f26f8504fbf1e33efa2eada37e09900b39dd62667f22d7","tests/ui/source-enum-not-error.rs":"3add5e7b4503d964bcae0848904822e1473c1d08c5a146c2df5347314ce1b8df","tests/ui/source-enum-not-error.stderr":"aeba0a8a0084833e470b6be2250370809f53c279ad603232af5302b9de9f8cce","tests/ui/source-enum-unnamed-field-not-error.rs":"a98989e908b84a8e6e6dceef02af7bdd1098a444d229950f67ed4f54d55c62e7","tests/ui/source-enum-unnamed-field-not-error.stderr":"4f3d90525dd462e67f633e83b26acec75d9af3626e40d28ded2c2438e0c73192","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"b45eb66f078fec68d44feff1f8d6a676c341e9e9d9acb35daa58ec1ea20f9dae","tests/ui/source-struct-unnamed-field-not-error.rs":"eee605a9aafbb093666393e25cef4f7d7b8e90d518b9fadbdbed9685c66ccfcd","tests/ui/source-struct-unnamed-field-not-error.stderr":"10e408f71c1b61880b1d52739f222ec58a66be70a1df17e44c536fe0f9ffe2a6","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-not-error.rs":"f6315993e68bc71d6d4d39afa4d059695308ef785f92cc0d1df3e9ff55be2a9a","tests/ui/transparent-enum-not-error.stderr":"3a5fe056cd4566f402b03cb591394e0ba85bd74da53df3c8d50bda4a05c2e5ba","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-enum-unnamed-field-not-error.rs":"0c720567e9e0f87921055dfa9f607661725377633445e01a4b5048c7a7a50a85","tests/ui/transparent-enum-unnamed-field-not-error.stderr":"6d84e9a7f4e88daba12931a6c1508be60bb19125d06e44fa2fa205126d953bb1","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-not-error.rs":"fd814d3141c9182b1267b558d9daef8dd6e8b6462e1ad42b197f3a1c0703dce2","tests/ui/transparent-struct-not-error.stderr":"ac7634ea72096d8a5c1a91fd4f1b45ef870130a2698d9ae7c6530cec2f9799d5","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/transparent-struct-unnamed-field-not-error.rs":"fbff5874be44a5dcc347693d7929537256b187dfec467ed72c9968c095228d8d","tests/ui/transparent-struct-unnamed-field-not-error.stderr":"ea99d5422348c2588ad7374360e2a24649f040b9c5614c9308eff958f61960ec","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"78696bde4e120c993e7ee08293b3425948a9277d8cc1fcfff9e091456fad4cf3",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"74d83ef29374930174e8c15b0f33b0dfeaba245ee9f1d6ace99d30d410c48a00","Cargo.lock":"4a45f86280c4341e85edff983c6070dd3aea949c023a0781b4656d1c8d095e48","Cargo.toml":"d1bf4f0f23bdc256cff12a549cead72e38380adfa4d7b83b8de3ff39cb4e8abc","Cargo.toml.orig":"99d97fe73dd336d8eb954af8c3c75303689651b12dc9c007606ca5ae643ea3c9","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"1b665c5bcd24e6a8f052427ac09de48d74c04b7255e597e3d43ac7ca0a3a1e2f","build.rs":"82972a9e8b0c975f821e4cf018a7b348b54193be04b9396285bac0c3833293b1","build/probe.rs":"8df55471d6b75623d423b17ebbf493335ee66140d1ddd232c88db3e59f61298c","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"c4504c7db4639c5700882fd8133bf257d6755a9dad28b55b6daf02e1fb64be56","src/display.rs":"0e9f6faedf726e2d4b4a05c802bdaf536ec40d91fec6cc0a587e9f7378038a1c","src/lib.rs":"00366e9dde959056aee9329df4d6f9452c12a2f905df89f83e574bd43385490d","src/private.rs":"e23c4d1d1a8568f1cdfb02c43b03cc2fd4c33185bfe74b56c33c4591747fdec0","src/provide.rs":"a58cb09f60ad0181c7a47c0442c9d23b8e1f79f93a2b488db3b27c211e3f497f","src/var.rs":"a7390e29fe607bfccc690c2333e8d1b85923ece2eb62555dd07fa01f7b37e226","tests/compiletest.rs":"4e381aa8ca3eabb7ac14d1e0c3700b3223e47640547a6988cfa13ad68255f60f","tests/test_backtrace.rs":"b4b2ab8057b76a46491503da7326a2411df824eab34d7d4c853081f6887b6f2f","tests/test_display.rs":"fc628761216e2bcf8a08e4c2f1fdf63f794e2543e7f5e1a561f9dccbcff29e60","tests/test_error.rs":"eba9a2bae06e45365dc9f1be39d00e5cdee57127909c5f4b1f5558fe1dbb60ef","tests/test_expr.rs":"8d53ad09cadc513d1210fa7124e4f33f5db7bd5ec39b38861d08ddf4c0d64b70","tests/test_from.rs":"36bd22be7b048cd187a19076aeac1456040f20a0b677b01c6003998b63439ea1","tests/test_generics.rs":"219d0e2ad94f65134ca9b8b4735a211addbbff0dd6820a40a227fc6e5bf6960a","tests/test_lints.rs":"0f149c35b9ecf76cc966c6a0097de6ee300d9c54be8aa9a873c1d24e80b40396","tests/test_option.rs":"71606cb816c15d5373065579d8ab3c9206bb6f3738b0bfbea56511c43bcb05e7","tests/test_path.rs":"92f218304955022aec69d5ce09c9454cf62e17b05eb795c1ffb80d46fa42758c","tests/test_source.rs":"36a6de84484bdae8eae487ef41a93e5c71ae88d1c7e1194911295672db0b15ab","tests/test_transparent.rs":"c224b3030b7d3e3dc6851787255bea30ff063c4b3f7767a5d7b43b56959a8347","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"de94f6f66296e8202e6b7e385599ce0e70fb8d9c055c486aac7941a6f140f489","tests/ui/display-underscore.rs":"0cab8048b4a37a676b00c5f68414c235573c920423d9a2f4dfac887a6f805399","tests/ui/display-underscore.stderr":"bb11d3c000cbd110e3539cc3fee053f824f1bdd3a8b1d7ad9548f6ceae96e684","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"ba89e292892043fdc7dfefec13f0f8bc5f52b3ab03cd0278a019612ce34dcd85","tests/ui/duplicate-fmt.stderr":"65e78d22526d30a37e663ffe63aaa1c37576aba81c6a8dc5b9ee65cc00956872","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/expression-fallback.rs":"00fcfa22a9860feb3c737cc4eca44512de85412d2cce69a690afa9e4bdc8758b","tests/ui/expression-fallback.stderr":"f1901b1f0329e4ea0e7ad14fedfb9225aad105310d85eed4169598e624690dbd","tests/ui/fallback-impl-with-display.rs":"0b8ce57ba958008f90aaa078fa1066b47b8d4a5146b6a91ec7d8d96122f0637a","tests/ui/fallback-impl-with-display.stderr":"1b3dad712b97598fbee70125471de1a8106eb161d42ce1f790ae07be8c8984ba","tests/ui/from-backtrace-backtrace.rs":"0caac64486c0eb9c076553c0502d468fbc477602a9a2595165a1dcd95524e5ff","tests/ui/from-backtrace-backtrace.stderr":"e24156ae0828878f3282341732b6e032eaa8cb4b4db366a6b5437ed0731d40a7","tests/ui/from-not-source.rs":"a8dff2e92c21b1b97c48af89b7832bfb6b3bb4437a691bb882779e63fc792869","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/invalid-input-impl-anyway.rs":"6de91f71ddf038dffa3b9da33763a2ec3a5aa0047528e19ba998d5efe3aada5b","tests/ui/invalid-input-impl-anyway.stderr":"fa2725053cd87fc37f87546b377e6e5eed95c45e2a960863303b21a1935fdddb","tests/ui/lifetime.rs":"1da6748767b9a5b25ad7c013becb2e243b39c7c764cbdf00487794f6fc812890","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-display.rs":"c1fd1bc0ec0fb103d7f7b128837f717d49485662839899d570b3c983f1332888","tests/ui/missing-display.stderr":"dfaed229ae28069bac5791e714a9b5a3e32faddf8517291c4c4e0f4cc2f07e1a","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"0525bbaf69d6badec85ad92dfe0dc9a4dcabb28a859f4caac40a52f1d37d9e25","tests/ui/no-display.stderr":"631be2c6e38ac47c936741b479291668a9fa80524f8ba110e9c381c447a7a653","tests/ui/numbered-positional-tuple.rs":"7d000b1abcde04abcfe21bd592144e8cbcd953608895aef934d4655e2349e63a","tests/ui/numbered-positional-tuple.stderr":"58b2dde4578862b3d2ca9d8f309b05dbbce059e7b6bb8ad3096a702b0f63c5cf","tests/ui/raw-identifier.rs":"2593eb4bee6a2b20f36ccd08a7265f2e284a4f020f8381c325bb8fe630213e8d","tests/ui/raw-identifier.stderr":"0461c9c5a2f2630734822940d543df7f32cd4ed2e34bb323f6edbd13335dbf2f","tests/ui/same-from-type.rs":"6db0bcbe507f3204d6bc8d4cf382b9e36228bccaca01c199a89cd6df87bcae0c","tests/ui/same-from-type.stderr":"e0084050070564e7d22a13db8b401a145e4e3311ae5ac2f8f83b998cadd079a8","tests/ui/source-enum-not-error.rs":"3add5e7b4503d964bcae0848904822e1473c1d08c5a146c2df5347314ce1b8df","tests/ui/source-enum-not-error.stderr":"aeba0a8a0084833e470b6be2250370809f53c279ad603232af5302b9de9f8cce","tests/ui/source-enum-unnamed-field-not-error.rs":"a98989e908b84a8e6e6dceef02af7bdd1098a444d229950f67ed4f54d55c62e7","tests/ui/source-enum-unnamed-field-not-error.stderr":"579144cada6850a8a9b34f5ae4d36a5c19dfc4acf3dde78f57ffb5fe1a5e8da3","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"b45eb66f078fec68d44feff1f8d6a676c341e9e9d9acb35daa58ec1ea20f9dae","tests/ui/source-struct-unnamed-field-not-error.rs":"eee605a9aafbb093666393e25cef4f7d7b8e90d518b9fadbdbed9685c66ccfcd","tests/ui/source-struct-unnamed-field-not-error.stderr":"2da577e0cb8ea8c7f0a2ae69c0f7db908432217c6290a72abba46a8f539982be","tests/ui/struct-with-fmt.rs":"a681659e0c161c8dd7b9f42e3ac026759ed085948cfb42458247eb96a2122a69","tests/ui/struct-with-fmt.stderr":"e560ce1e6a696b404f729ec317d6793ccb2a72fe8a508f0adb807b3982c1c9ff","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-not-error.rs":"f6315993e68bc71d6d4d39afa4d059695308ef785f92cc0d1df3e9ff55be2a9a","tests/ui/transparent-enum-not-error.stderr":"3a5fe056cd4566f402b03cb591394e0ba85bd74da53df3c8d50bda4a05c2e5ba","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-enum-unnamed-field-not-error.rs":"0c720567e9e0f87921055dfa9f607661725377633445e01a4b5048c7a7a50a85","tests/ui/transparent-enum-unnamed-field-not-error.stderr":"6d84e9a7f4e88daba12931a6c1508be60bb19125d06e44fa2fa205126d953bb1","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-not-error.rs":"fd814d3141c9182b1267b558d9daef8dd6e8b6462e1ad42b197f3a1c0703dce2","tests/ui/transparent-struct-not-error.stderr":"ac7634ea72096d8a5c1a91fd4f1b45ef870130a2698d9ae7c6530cec2f9799d5","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/transparent-struct-unnamed-field-not-error.rs":"fbff5874be44a5dcc347693d7929537256b187dfec467ed72c9968c095228d8d","tests/ui/transparent-struct-unnamed-field-not-error.stderr":"ea99d5422348c2588ad7374360e2a24649f040b9c5614c9308eff958f61960ec","tests/ui/unconditional-recursion.rs":"a6cc8c97a95644b4c5979fbc2fc5e18bdb58ff1e8a8ab471c9e3bb64a8ddddc4","tests/ui/unconditional-recursion.stderr":"7349acab2499b55cd48d86b8c0ac65b080225f3d43d6582653259d7b9e085a52","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "72ae716e6d6a7f7fdabdc394018c745b4d39ca45" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,128 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.81.0, 1.76.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - name: Enable nightly-only tests + run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=thiserror_nightly_testing >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test --workspace --exclude thiserror_no_std_test + - run: cargo test --manifest-path tests/no-std/Cargo.toml + if: matrix.rust != '1.76.0' + - run: cargo test --no-default-features + - uses: actions/upload-artifact@v4 + if: matrix.rust == 'nightly' && always() + with: + name: Cargo.lock + path: Cargo.lock + continue-on-error: true + + msrv: + name: Rust 1.61.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@1.61.0 + with: + components: rust-src + - run: cargo check + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --tests --workspace -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,295 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +dependencies = [ + "serde_core", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-triple" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +dependencies = [ + "anyhow", + "ref-cast", + "rustversion", + "thiserror-impl", + "trybuild", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" + +[[package]] +name = "trybuild" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ded9fdb81f30a5708920310bfcd9ea7482ff9cba5f54601f7a19a877d5c2392" +dependencies = [ + "dissimilar", + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-sys" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,10 +11,16 @@ [package] edition = "2021" -rust-version = "1.56" +rust-version = "1.61" name = "thiserror" -version = "1.0.59" +version = "2.0.17" authors = ["David Tolnay "] +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "derive(Error)" documentation = "https://docs.rs/thiserror" readme = "README.md" @@ -23,16 +29,81 @@ "error-handling", "derive", ] -categories = ["rust-patterns"] +categories = [ + "rust-patterns", + "no-std", +] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/thiserror" [package.metadata.docs.rs] -rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] + +[features] +default = ["std"] +std = [] + +[lib] +name = "thiserror" +path = "src/lib.rs" + +[[test]] +name = "compiletest" +path = "tests/compiletest.rs" + +[[test]] +name = "test_backtrace" +path = "tests/test_backtrace.rs" + +[[test]] +name = "test_display" +path = "tests/test_display.rs" + +[[test]] +name = "test_error" +path = "tests/test_error.rs" + +[[test]] +name = "test_expr" +path = "tests/test_expr.rs" + +[[test]] +name = "test_from" +path = "tests/test_from.rs" + +[[test]] +name = "test_generics" +path = "tests/test_generics.rs" + +[[test]] +name = "test_lints" +path = "tests/test_lints.rs" + +[[test]] +name = "test_option" +path = "tests/test_option.rs" + +[[test]] +name = "test_path" +path = "tests/test_path.rs" + +[[test]] +name = "test_source" +path = "tests/test_source.rs" + +[[test]] +name = "test_transparent" +path = "tests/test_transparent.rs" [dependencies.thiserror-impl] -version = "=1.0.59" +version = "=2.0.17" [dev-dependencies.anyhow] version = "1.0.73" @@ -44,5 +115,5 @@ version = "1.0.13" [dev-dependencies.trybuild] -version = "1.0.81" +version = "1.0.108" features = ["diff"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +[package] +name = "thiserror" +version = "2.0.17" +authors = ["David Tolnay "] +categories = ["rust-patterns", "no-std"] +description = "derive(Error)" +documentation = "https://docs.rs/thiserror" +edition = "2021" +keywords = ["error", "error-handling", "derive"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" +rust-version = "1.61" + +[features] +default = ["std"] + +# Std feature enables support for formatting std::path::{Path, PathBuf} +# conveniently in an error message. +# +# #[derive(Error, Debug)] +# #[error("failed to create configuration file {path}")] +# pub struct MyError { +# pub path: PathBuf, +# pub source: std::io::Error, +# } +# +# Without std, this would need to be written #[error("... {}", path.display())]. +std = [] + +[dependencies] +thiserror-impl = { version = "=2.0.17", path = "impl" } + +[dev-dependencies] +anyhow = "1.0.73" +ref-cast = "1.0.18" +rustversion = "1.0.13" +trybuild = { version = "1.0.108", features = ["diff"] } + +[workspace] +members = ["impl", "tests/no-std"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/README.md clamav-1.4.6+dfsg/.cargo/vendor/thiserror/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -13,10 +13,10 @@ ```toml [dependencies] -thiserror = "1.0" +thiserror = "2" ``` -*Compiler support: requires rustc 1.56+* +*Compiler support: requires rustc 1.61+*
@@ -70,7 +70,7 @@ ```rust #[derive(Error, Debug)] pub enum Error { - #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] + #[error("invalid rdo_lookahead_frames {0} (expected < {max})", max = i32::MAX)] InvalidLookahead(u32), } ``` @@ -88,20 +88,18 @@ } ``` -- A `From` impl is generated for each variant containing a `#[from]` attribute. +- A `From` impl is generated for each variant that contains a `#[from]` + attribute. - Note that the variant must not contain any other fields beyond the source - error and possibly a backtrace. A backtrace is captured from within the `From` - impl if there is a field for it. + The variant using `#[from]` must not contain any other fields beyond the + source error (and possibly a backtrace — see below). Usually `#[from]` + fields are unnamed, but `#[from]` is allowed on a named field too. ```rust #[derive(Error, Debug)] pub enum MyError { - Io { - #[from] - source: io::Error, - backtrace: Backtrace, - }, + Io(#[from] io::Error), + Glob(#[from] globset::Error), } ``` @@ -125,7 +123,9 @@ ``` - The Error trait's `provide()` method is implemented to provide whichever field - has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`. + has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`. Using + `Backtrace` in errors requires a nightly compiler with Rust version 1.73 or + newer. ```rust use std::backtrace::Backtrace; @@ -140,7 +140,9 @@ - If a field is both a source (named `source`, or has `#[source]` or `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error trait's `provide()` method is forwarded to the source's `provide` so that both layers of the error - share the same backtrace. + share the same backtrace. The `#[backtrace]` attribute requires a nightly + compiler with Rust version 1.73 or newer. + ```rust #[derive(Error, Debug)] @@ -151,6 +153,20 @@ }, } ``` + +- For variants that use `#[from]` and also contain a `Backtrace` field, a + backtrace is captured from within the `From` impl. + + ```rust + #[derive(Error, Debug)] + pub enum MyError { + Io { + #[from] + source: io::Error, + backtrace: Backtrace, + }, + } + ``` - Errors may use `error(transparent)` to forward the source and Display methods straight through to an underlying error without adding an additional message. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/build/probe.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build/probe.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/build/probe.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build/probe.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,10 +2,11 @@ // member access API. If the current toolchain is able to compile it, then // thiserror is able to provide backtrace support. +#![no_std] #![feature(error_generic_member_access)] -use std::error::{Error, Request}; -use std::fmt::{self, Debug, Display}; +use core::error::{Error, Request}; +use core::fmt::{self, Debug, Display}; struct MyError(Thing); struct Thing; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/build.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/build.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,12 +1,32 @@ use std::env; use std::ffi::OsString; +use std::fs; +use std::io::ErrorKind; use std::iter; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; +use std::str; + +const PRIVATE: &str = "\ +#[doc(hidden)] +pub mod __private$$ { + #[doc(hidden)] + pub use crate::private::*; +} +"; fn main() { println!("cargo:rerun-if-changed=build/probe.rs"); + println!("cargo:rustc-check-cfg=cfg(error_generic_member_access)"); + println!("cargo:rustc-check-cfg=cfg(thiserror_nightly_testing)"); + println!("cargo:rustc-check-cfg=cfg(thiserror_no_backtrace_type)"); + + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap(); + let module = PRIVATE.replace("$$", &patch_version); + fs::write(out_dir.join("private.rs"), module).unwrap(); + let error_generic_member_access; let consider_rustc_bootstrap; if compile_probe(false) { @@ -49,6 +69,24 @@ if consider_rustc_bootstrap { println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); } + + // core::error::Error stabilized in Rust 1.81 + // https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror + let rustc = rustc_minor_version(); + if cfg!(not(feature = "std")) && rustc.map_or(false, |rustc| rustc < 81) { + println!("cargo:rustc-cfg=feature=\"std\""); + } + + let rustc = match rustc { + Some(rustc) => rustc, + None => return, + }; + + // std::backtrace::Backtrace stabilized in Rust 1.65 + // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#stabilized-apis + if rustc < 65 { + println!("cargo:rustc-cfg=thiserror_no_backtrace_type"); + } } fn compile_probe(rustc_bootstrap: bool) -> bool { @@ -65,8 +103,16 @@ let rustc = cargo_env_var("RUSTC"); let out_dir = cargo_env_var("OUT_DIR"); + let out_subdir = Path::new(&out_dir).join("probe"); let probefile = Path::new("build").join("probe.rs"); + if let Err(err) = fs::create_dir(&out_subdir) { + if err.kind() != ErrorKind::AlreadyExists { + eprintln!("Failed to create {}: {}", out_subdir.display(), err); + process::exit(1); + } + } + let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let rustc_workspace_wrapper = env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); @@ -88,7 +134,7 @@ .arg("--cap-lints=allow") .arg("--emit=dep-info,metadata") .arg("--out-dir") - .arg(out_dir) + .arg(&out_subdir) .arg(probefile); if let Some(target) = env::var_os("TARGET") { @@ -104,18 +150,47 @@ } } - match cmd.status() { + let success = match cmd.status() { Ok(status) => status.success(), Err(_) => false, + }; + + // Clean up to avoid leaving nondeterministic absolute paths in the dep-info + // file in OUT_DIR, which causes nonreproducible builds in build systems + // that treat the entire OUT_DIR as an artifact. + if let Err(err) = fs::remove_dir_all(&out_subdir) { + // libc::ENOTEMPTY + // Some filesystems (NFSv3) have timing issues under load where '.nfs*' + // dummy files can continue to get created for a short period after the + // probe command completes, breaking remove_dir_all. + // To be replaced with ErrorKind::DirectoryNotEmpty (Rust 1.83+). + const ENOTEMPTY: i32 = 39; + + if !(err.kind() == ErrorKind::NotFound + || (cfg!(target_os = "linux") && err.raw_os_error() == Some(ENOTEMPTY))) + { + eprintln!("Failed to clean up {}: {}", out_subdir.display(), err); + process::exit(1); + } + } + + success +} + +fn rustc_minor_version() -> Option { + let rustc = cargo_env_var("RUSTC"); + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; } + pieces.next()?.parse().ok() } fn cargo_env_var(key: &str) -> OsString { env::var_os(key).unwrap_or_else(|| { - eprintln!( - "Environment variable ${} is not set during execution of build script", - key, - ); + eprintln!("Environment variable ${key} is not set during execution of build script"); process::exit(1); }) } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/aserror.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/aserror.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/aserror.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/aserror.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -use std::error::Error; -use std::panic::UnwindSafe; +use core::error::Error; +use core::panic::UnwindSafe; #[doc(hidden)] pub trait AsDynError<'a>: Sealed { @@ -43,8 +43,8 @@ #[doc(hidden)] pub trait Sealed {} -impl<'a, T: Error + 'a> Sealed for T {} -impl<'a> Sealed for dyn Error + 'a {} -impl<'a> Sealed for dyn Error + Send + 'a {} -impl<'a> Sealed for dyn Error + Send + Sync + 'a {} -impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {} +impl Sealed for T {} +impl Sealed for dyn Error + '_ {} +impl Sealed for dyn Error + Send + '_ {} +impl Sealed for dyn Error + Send + Sync + '_ {} +impl Sealed for dyn Error + Send + Sync + UnwindSafe + '_ {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/display.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,9 @@ -use std::fmt::Display; +use core::fmt::Display; +#[cfg(feature = "std")] use std::path::{self, Path, PathBuf}; #[doc(hidden)] -pub trait AsDisplay<'a> { +pub trait AsDisplay<'a>: Sealed { // TODO: convert to generic associated type. // https://github.com/dtolnay/thiserror/pull/253 type Target: Display; @@ -12,7 +13,7 @@ impl<'a, T> AsDisplay<'a> for &T where - T: Display + 'a, + T: Display + ?Sized + 'a, { type Target = &'a T; @@ -21,6 +22,7 @@ } } +#[cfg(feature = "std")] impl<'a> AsDisplay<'a> for Path { type Target = path::Display<'a>; @@ -30,6 +32,7 @@ } } +#[cfg(feature = "std")] impl<'a> AsDisplay<'a> for PathBuf { type Target = path::Display<'a>; @@ -38,3 +41,42 @@ self.display() } } + +#[doc(hidden)] +pub trait Sealed {} +impl Sealed for &T {} +#[cfg(feature = "std")] +impl Sealed for Path {} +#[cfg(feature = "std")] +impl Sealed for PathBuf {} + +// Add a synthetic second impl of AsDisplay to prevent the "single applicable +// impl" rule from making too weird inference decision based on the single impl +// for &T, which could lead to code that compiles with thiserror's std feature +// off but breaks under feature unification when std is turned on by an +// unrelated crate. +#[cfg(not(feature = "std"))] +mod placeholder { + use super::{AsDisplay, Sealed}; + use core::fmt::{self, Display}; + + #[allow(dead_code)] + pub struct Placeholder; + + impl<'a> AsDisplay<'a> for Placeholder { + type Target = Self; + + #[inline] + fn as_display(&'a self) -> Self::Target { + Placeholder + } + } + + impl Display for Placeholder { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unreachable!() + } + } + + impl Sealed for Placeholder {} +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,8 +9,6 @@ //! This library provides a convenient derive macro for the standard library's //! [`std::error::Error`] trait. //! -//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html -//! //!
//! //! # Example @@ -40,14 +38,14 @@ //! # Details //! //! - Thiserror deliberately does not appear in your public API. You get the -//! same thing as if you had written an implementation of `std::error::Error` -//! by hand, and switching from handwritten impls to thiserror or vice versa -//! is not a breaking change. +//! same thing as if you had written an implementation of +//! [`std::error::Error`] by hand, and switching from handwritten impls to +//! thiserror or vice versa is not a breaking change. //! //! - Errors may be enums, structs with named fields, tuple structs, or unit //! structs. //! -//! - A `Display` impl is generated for your error if you provide +//! - A [`Display`] impl is generated for your error if you provide //! `#[error("...")]` messages on the struct or each variant of your enum, as //! shown above in the example. //! @@ -62,12 +60,12 @@ //! which may be arbitrary expressions. For example: //! //! ```rust -//! # use std::i32; +//! # use core::i32; //! # use thiserror::Error; //! # //! #[derive(Error, Debug)] //! pub enum Error { -//! #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] +//! #[error("invalid rdo_lookahead_frames {0} (expected < {max})", max = i32::MAX)] //! InvalidLookahead(u32), //! } //! ``` @@ -98,27 +96,39 @@ //! } //! ``` //! -//! - A `From` impl is generated for each variant containing a `#[from]` +//! - A [`From`] impl is generated for each variant that contains a `#[from]` //! attribute. //! -//! Note that the variant must not contain any other fields beyond the source -//! error and possibly a backtrace. A backtrace is captured from within the -//! `From` impl if there is a field for it. +//! The variant using `#[from]` must not contain any other fields beyond the +//! source error (and possibly a backtrace — see below). Usually +//! `#[from]` fields are unnamed, but `#[from]` is allowed on a named field +//! too. //! //! ```rust -//! # const IGNORE: &str = stringify! { +//! # use core::fmt::{self, Display}; +//! # use std::io; +//! # use thiserror::Error; +//! # +//! # mod globset { +//! # #[derive(thiserror::Error, Debug)] +//! # #[error("...")] +//! # pub struct Error; +//! # } +//! # //! #[derive(Error, Debug)] //! pub enum MyError { -//! Io { -//! #[from] -//! source: io::Error, -//! backtrace: Backtrace, -//! }, +//! Io(#[from] io::Error), +//! Glob(#[from] globset::Error), //! } -//! # }; +//! # +//! # impl Display for MyError { +//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +//! # unimplemented!() +//! # } +//! # } //! ``` //! -//! - The Error trait's `source()` method is implemented to return whichever +//! - The Error trait's [`source()`] method is implemented to return whichever //! field has a `#[source]` attribute or is named `source`, if any. This is //! for identifying the underlying lower level error that caused your error. //! @@ -129,7 +139,7 @@ //! std::error::Error` will work as a source. //! //! ```rust -//! # use std::fmt::{self, Display}; +//! # use core::fmt::{self, Display}; //! # use thiserror::Error; //! # //! #[derive(Error, Debug)] @@ -146,9 +156,10 @@ //! # } //! ``` //! -//! - The Error trait's `provide()` method is implemented to provide whichever +//! - The Error trait's [`provide()`] method is implemented to provide whichever //! field has a type named `Backtrace`, if any, as a -//! `std::backtrace::Backtrace`. +//! [`std::backtrace::Backtrace`]. Using `Backtrace` in errors requires a +//! nightly compiler with Rust version 1.73 or newer. //! //! ```rust //! # const IGNORE: &str = stringify! { @@ -164,8 +175,9 @@ //! //! - If a field is both a source (named `source`, or has `#[source]` or //! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error -//! trait's `provide()` method is forwarded to the source's `provide` so that -//! both layers of the error share the same backtrace. +//! trait's [`provide()`] method is forwarded to the source's `provide` so +//! that both layers of the error share the same backtrace. The `#[backtrace]` +//! attribute requires a nightly compiler with Rust version 1.73 or newer. //! //! ```rust //! # const IGNORE: &str = stringify! { @@ -179,7 +191,23 @@ //! # }; //! ``` //! -//! - Errors may use `error(transparent)` to forward the source and Display +//! - For variants that use `#[from]` and also contain a `Backtrace` field, a +//! backtrace is captured from within the `From` impl. +//! +//! ```rust +//! # const IGNORE: &str = stringify! { +//! #[derive(Error, Debug)] +//! pub enum MyError { +//! Io { +//! #[from] +//! source: io::Error, +//! backtrace: Backtrace, +//! }, +//! } +//! # }; +//! ``` +//! +//! - Errors may use `error(transparent)` to forward the source and [`Display`] //! methods straight through to an underlying error without adding an //! additional message. This would be appropriate for enums that need an //! "anything else" variant. @@ -226,10 +254,15 @@ //! - See also the [`anyhow`] library for a convenient single error type to use //! in application code. //! -//! [`anyhow`]: https://github.com/dtolnay/anyhow +//! [`anyhow`]: https://github.com/dtolnay/anyhow +//! [`source()`]: std::error::Error::source +//! [`provide()`]: std::error::Error::provide +//! [`Display`]: std::fmt::Display -#![doc(html_root_url = "https://docs.rs/thiserror/1.0.59")] +#![no_std] +#![doc(html_root_url = "https://docs.rs/thiserror/2.0.17")] #![allow( + clippy::elidable_lifetime_names, clippy::module_name_repetitions, clippy::needless_lifetimes, clippy::return_self_not_must_use, @@ -240,21 +273,19 @@ #[cfg(all(thiserror_nightly_testing, not(error_generic_member_access)))] compile_error!("Build script probe failed to compile."); +#[cfg(feature = "std")] +extern crate std; +#[cfg(feature = "std")] +extern crate std as core; + mod aserror; mod display; #[cfg(error_generic_member_access)] mod provide; +mod var; pub use thiserror_impl::*; -// Not public API. -#[doc(hidden)] -pub mod __private { - #[doc(hidden)] - pub use crate::aserror::AsDynError; - #[doc(hidden)] - pub use crate::display::AsDisplay; - #[cfg(error_generic_member_access)] - #[doc(hidden)] - pub use crate::provide::ThiserrorProvide; -} +mod private; + +include!(concat!(env!("OUT_DIR"), "/private.rs")); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/private.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/private.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/private.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/private.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +#[doc(hidden)] +pub use crate::aserror::AsDynError; +#[doc(hidden)] +pub use crate::display::AsDisplay; +#[cfg(error_generic_member_access)] +#[doc(hidden)] +pub use crate::provide::ThiserrorProvide; +#[doc(hidden)] +pub use crate::var::Var; +#[doc(hidden)] +pub use core::error::Error; +#[cfg(all(feature = "std", not(thiserror_no_backtrace_type)))] +#[doc(hidden)] +pub use std::backtrace::Backtrace; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/provide.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/provide.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/provide.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/provide.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -use std::error::{Error, Request}; +use core::error::{Error, Request}; #[doc(hidden)] pub trait ThiserrorProvide: Sealed { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/var.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/var.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/src/var.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/src/var.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use core::fmt::{self, Pointer}; + +pub struct Var<'a, T: ?Sized>(pub &'a T); + +impl<'a, T: Pointer + ?Sized> Pointer for Var<'a, T> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Pointer::fmt(self.0, formatter) + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/compiletest.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/compiletest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/compiletest.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/compiletest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -#[rustversion::attr(not(nightly), ignore)] -#[cfg_attr(miri, ignore)] +#[rustversion::attr(not(nightly), ignore = "requires nightly")] +#[cfg_attr(miri, ignore = "incompatible with miri")] #[test] fn ui() { let t = trybuild::TestCases::new(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_backtrace.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_backtrace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_backtrace.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_backtrace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +#![cfg(feature = "std")] #![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] use thiserror::Error; @@ -21,6 +22,11 @@ use std::sync::Arc; use thiserror::Error; + mod not_backtrace { + #[derive(Debug)] + pub struct Backtrace; + } + #[derive(Error, Debug)] #[error("...")] pub struct PlainBacktrace { @@ -36,6 +42,12 @@ #[derive(Error, Debug)] #[error("...")] + pub struct NotBacktrace { + backtrace: crate::structs::not_backtrace::r#Backtrace, + } + + #[derive(Error, Debug)] + #[error("...")] pub struct OptBacktrace { #[backtrace] backtrace: Option, @@ -270,5 +282,8 @@ } #[test] -#[cfg_attr(not(thiserror_nightly_testing), ignore)] +#[cfg_attr( + not(thiserror_nightly_testing), + ignore = "requires `--cfg=thiserror_nightly_testing`" +)] fn test_backtrace() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_deprecated.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_deprecated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_deprecated.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_deprecated.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#![deny(deprecated, clippy::all, clippy::pedantic)] - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[deprecated] - #[error("...")] - Deprecated, -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_display.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,12 @@ -#![allow(clippy::needless_raw_string_hashes, clippy::uninlined_format_args)] +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::needless_raw_string_hashes, + clippy::trivially_copy_pass_by_ref, + clippy::uninlined_format_args +)] -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use thiserror::Error; fn assert(expected: &str, value: T) { @@ -127,7 +133,7 @@ #[test] fn test_match() { #[derive(Error, Debug)] - #[error("{}: {0}", match .1 { + #[error("{intro}: {0}", intro = match .1 { Some(n) => format!("error occurred with {}", n), None => "there was an empty error".to_owned(), })] @@ -235,18 +241,44 @@ } #[test] -fn test_macro_rules() { +fn test_nested_tuple_field() { + #[derive(Debug)] + struct Inner(usize); + + #[derive(Error, Debug)] + #[error("{}", .0.0)] + struct Error(Inner); + + assert("0", Error(Inner(0))); +} + +#[test] +fn test_pointer() { + #[derive(Error, Debug)] + #[error("{field:p}")] + pub struct Struct { + field: Box, + } + + let s = Struct { + field: Box::new(-1), + }; + assert_eq!(s.to_string(), format!("{:p}", s.field)); +} + +#[test] +fn test_macro_rules_variant_from_call_site() { // Regression test for https://github.com/dtolnay/thiserror/issues/86 macro_rules! decl_error { ($variant:ident($value:ident)) => { - #[derive(Debug, Error)] + #[derive(Error, Debug)] pub enum Error0 { #[error("{0:?}")] $variant($value), } - #[derive(Debug, Error)] + #[derive(Error, Debug)] #[error("{0:?}")] pub enum Error1 { $variant($value), @@ -261,9 +293,33 @@ } #[test] +fn test_macro_rules_message_from_call_site() { + // Regression test for https://github.com/dtolnay/thiserror/issues/398 + + macro_rules! decl_error { + ($($errors:tt)*) => { + #[derive(Error, Debug)] + pub enum Error { + $($errors)* + } + }; + } + + decl_error! { + #[error("{0}")] + Unnamed(u8), + #[error("{x}")] + Named { x: u8 }, + } + + assert("0", Error::Unnamed(0)); + assert("0", Error::Named { x: 0 }); +} + +#[test] fn test_raw() { #[derive(Error, Debug)] - #[error("braced raw error: {r#fn}")] + #[error("braced raw error: {fn}")] struct Error { r#fn: &'static str, } @@ -275,7 +331,7 @@ fn test_raw_enum() { #[derive(Error, Debug)] enum Error { - #[error("braced raw error: {r#fn}")] + #[error("braced raw error: {fn}")] Braced { r#fn: &'static str }, } @@ -283,23 +339,21 @@ } #[test] -fn test_raw_conflict() { +fn test_keyword() { #[derive(Error, Debug)] - enum Error { - #[error("braced raw error: {r#func}, {func}", func = "U")] - Braced { r#func: &'static str }, - } + #[error("error: {type}", type = 1)] + struct Error; - assert("braced raw error: T, U", Error::Braced { r#func: "T" }); + assert("error: 1", Error); } #[test] -fn test_keyword() { +fn test_self() { #[derive(Error, Debug)] - #[error("error: {type}", type = 1)] + #[error("error: {self:?}")] struct Error; - assert("error: 1", Error); + assert("error: Error", Error); } #[test] @@ -356,3 +410,69 @@ assert(r#"raw brace right }"#, Error::BraceRight); assert(r#"raw brace right 2 \x7D"#, Error::BraceRight2); } + +mod util { + use core::fmt::{self, Octal}; + + pub fn octal(value: &T, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "0o{:o}", value) + } +} + +#[test] +fn test_fmt_path() { + fn unit(formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("unit=") + } + + fn pair(k: &i32, v: &i32, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "pair={k}:{v}") + } + + #[derive(Error, Debug)] + pub enum Error { + #[error(fmt = unit)] + Unit, + #[error(fmt = pair)] + Tuple(i32, i32), + #[error(fmt = pair)] + Entry { k: i32, v: i32 }, + #[error(fmt = crate::util::octal)] + I16(i16), + #[error(fmt = crate::util::octal::)] + I32 { n: i32 }, + #[error(fmt = core::fmt::Octal::fmt)] + I64(i64), + #[error("...{0}")] + Other(bool), + } + + assert("unit=", Error::Unit); + assert("pair=10:0", Error::Tuple(10, 0)); + assert("pair=10:0", Error::Entry { k: 10, v: 0 }); + assert("0o777", Error::I16(0o777)); + assert("0o777", Error::I32 { n: 0o777 }); + assert("777", Error::I64(0o777)); + assert("...false", Error::Other(false)); +} + +#[test] +fn test_fmt_path_inherited() { + #[derive(Error, Debug)] + #[error(fmt = crate::util::octal)] + pub enum Error { + I16(i16), + I32 { + n: i32, + }, + #[error(fmt = core::fmt::Octal::fmt)] + I64(i64), + #[error("...{0}")] + Other(bool), + } + + assert("0o777", Error::I16(0o777)); + assert("0o777", Error::I32 { n: 0o777 }); + assert("777", Error::I64(0o777)); + assert("...false", Error::Other(false)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use std::io; use thiserror::Error; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_expr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_expr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,8 @@ #![allow(clippy::iter_cloned_collect, clippy::uninlined_format_args)] -use std::fmt::Display; +use core::fmt::Display; +#[cfg(feature = "std")] +use std::path::PathBuf; use thiserror::Error; // Some of the elaborate cases from the rcc codebase, which is a C compiler in @@ -50,6 +52,7 @@ }, } +#[track_caller] fn assert(expected: &str, value: T) { assert_eq!(expected, value.to_string()); } @@ -86,3 +89,30 @@ }, ); } + +// Regression test for https://github.com/dtolnay/thiserror/issues/335 +#[cfg(feature = "std")] +#[test] +#[allow(non_snake_case)] +fn test_assoc_type_equality_constraint() { + pub trait Trait: Display { + type A; + } + + impl Trait for i32 { + type A = i32; + } + + #[derive(Error, Debug)] + #[error("{A} {b}", b = &0 as &dyn Trait)] + pub struct Error { + pub A: PathBuf, + } + + assert( + "... 0", + Error { + A: PathBuf::from("..."), + }, + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_generics.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_generics.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_generics.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_generics.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,7 @@ #![allow(clippy::needless_late_init, clippy::uninlined_format_args)] -use std::fmt::{self, Debug, Display}; +use core::fmt::{self, Debug, Display}; +use core::str::FromStr; use thiserror::Error; pub struct NoFormat; @@ -158,4 +159,47 @@ // #[derive(Error, Debug)] #[error(transparent)] -pub struct StructTransparentGeneric(E); +pub struct StructTransparentGeneric(pub E); + +// Should expand to: +// +// impl Display for AssociatedTypeError +// where +// T::Err: Display; +// +// impl Error for AssociatedTypeError +// where +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub enum AssociatedTypeError { + #[error("couldn't parse matrix")] + Other, + #[error("couldn't parse entry: {0}")] + EntryParseError(T::Err), +} + +// Regression test for https://github.com/dtolnay/thiserror/issues/345 +#[test] +fn test_no_bound_on_named_fmt() { + #[derive(Error, Debug)] + #[error("{thing}", thing = "...")] + struct Error { + thing: T, + } + + let error = Error { thing: DebugOnly }; + assert_eq!(error.to_string(), "..."); +} + +#[test] +fn test_multiple_bound() { + #[derive(Error, Debug)] + #[error("0x{thing:x} 0x{thing:X}")] + pub struct Error { + thing: T, + } + + let error = Error { thing: 0xFFi32 }; + assert_eq!(error.to_string(), "0xff 0xFF"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_lints.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_lints.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_lints.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_lints.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,6 +5,17 @@ pub use std::error::Error; #[test] +fn test_allow_attributes() { + #![deny(clippy::allow_attributes)] + + #[derive(Error, Debug)] + #[error("...")] + pub struct MyError(#[from] anyhow::Error); + + let _: MyError; +} + +#[test] fn test_unused_qualifications() { #![deny(unused_qualifications)] @@ -12,9 +23,76 @@ // std::error::Error is already imported in the caller's scope so it must // suppress unused_qualifications. - #[derive(Debug, Error)] + #[derive(Error, Debug)] #[error("...")] pub struct MyError; let _: MyError; } + +#[test] +fn test_needless_lifetimes() { + #![allow(dead_code)] + #![deny(clippy::elidable_lifetime_names, clippy::needless_lifetimes)] + + #[derive(Error, Debug)] + #[error("...")] + pub enum MyError<'a> { + A(#[from] std::io::Error), + B(&'a ()), + } + + let _: MyError; +} + +#[test] +fn test_deprecated() { + #![deny(deprecated)] + + #[derive(Error, Debug)] + #[deprecated] + #[error("...")] + pub struct DeprecatedStruct; + + #[derive(Error, Debug)] + #[error("{message} {}", .message)] + pub struct DeprecatedStructField { + #[deprecated] + message: String, + } + + #[derive(Error, Debug)] + #[deprecated] + pub enum DeprecatedEnum { + #[error("...")] + Variant, + } + + #[derive(Error, Debug)] + pub enum DeprecatedVariant { + #[deprecated] + #[error("...")] + Variant, + } + + #[derive(Error, Debug)] + pub enum DeprecatedFrom { + #[error(transparent)] + Variant( + #[from] + #[allow(deprecated)] + DeprecatedStruct, + ), + } + + #[allow(deprecated)] + let _: DeprecatedStruct; + #[allow(deprecated)] + let _: DeprecatedStructField; + #[allow(deprecated)] + let _ = DeprecatedEnum::Variant; + #[allow(deprecated)] + let _ = DeprecatedVariant::Variant; + #[allow(deprecated)] + let _ = DeprecatedFrom::Variant(DeprecatedStruct); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_option.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_option.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_option.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_option.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,4 @@ +#![cfg(feature = "std")] #![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] #[cfg(thiserror_nightly_testing)] @@ -9,39 +10,39 @@ #[error("...")] pub struct OptSourceNoBacktrace { #[source] - source: Option, + pub source: Option, } #[derive(Error, Debug)] #[error("...")] pub struct OptSourceAlwaysBacktrace { #[source] - source: Option, - backtrace: Backtrace, + pub source: Option, + pub backtrace: Backtrace, } #[derive(Error, Debug)] #[error("...")] pub struct NoSourceOptBacktrace { #[backtrace] - backtrace: Option, + pub backtrace: Option, } #[derive(Error, Debug)] #[error("...")] pub struct AlwaysSourceOptBacktrace { - source: anyhow::Error, + pub source: anyhow::Error, #[backtrace] - backtrace: Option, + pub backtrace: Option, } #[derive(Error, Debug)] #[error("...")] pub struct OptSourceOptBacktrace { #[source] - source: Option, + pub source: Option, #[backtrace] - backtrace: Option, + pub backtrace: Option, } } @@ -101,5 +102,8 @@ } #[test] -#[cfg_attr(not(thiserror_nightly_testing), ignore)] +#[cfg_attr( + not(thiserror_nightly_testing), + ignore = "requires `--cfg=thiserror_nightly_testing`" +)] fn test_option() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_path.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_path.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,7 @@ +#![cfg(feature = "std")] + +use core::fmt::Display; use ref_cast::RefCast; -use std::fmt::Display; use std::path::{Path, PathBuf}; use thiserror::Error; @@ -22,6 +24,21 @@ Read(PathBuf), } +#[derive(Error, Debug)] +#[error("{tail}")] +pub struct UnsizedError { + pub head: i32, + pub tail: str, +} + +#[derive(Error, Debug)] +pub enum BothError { + #[error("display:{0} debug:{0:?}")] + DisplayDebug(PathBuf), + #[error("debug:{0:?} display:{0}")] + DebugDisplay(PathBuf), +} + fn assert(expected: &str, value: T) { assert_eq!(expected, value.to_string()); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_source.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -63,3 +63,20 @@ #[error("Something")] Variant(#[from] io::Error) } + +#[test] +fn test_not_source() { + #[derive(Error, Debug)] + #[error("{source} ==> {destination}")] + pub struct NotSource { + r#source: char, + destination: char, + } + + let error = NotSource { + source: 'S', + destination: 'D', + }; + assert_eq!(error.to_string(), "S ==> D"); + assert!(error.source().is_none()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/test_transparent.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/test_transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -46,6 +46,24 @@ } #[test] +fn test_transparent_enum_with_default_message() { + #[derive(Error, Debug)] + #[error("this failed: {0}_{1}")] + enum Error { + This(i32, i32), + #[error(transparent)] + Other(anyhow::Error), + } + + let error = Error::This(-1, -1); + assert_eq!("this failed: -1_-1", error.to_string()); + + let error = Error::Other(anyhow!("inner").context("outer")); + assert_eq!("outer", error.to_string()); + assert_eq!("inner", error.source().unwrap().to_string()); +} + +#[test] fn test_anyhow() { #[derive(Error, Debug)] #[error(transparent)] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/concat-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/concat-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/concat-display.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/concat-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ -error: expected string literal +error: expected one of: string literal, `transparent`, `fmt` --> tests/ui/concat-display.rs:8:17 | -8 | #[error(concat!("invalid ", $what))] + 8 | #[error(concat!("invalid ", $what))] | ^^^^^^ ... 13 | error_type!(Error, "foo"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("{_}")] +pub struct Error; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/display-underscore.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +error: invalid format string: invalid argument name `_` + --> tests/ui/display-underscore.rs:4:11 + | +4 | #[error("{_}")] + | ^ invalid argument name in format string + | + = note: argument name cannot be a single underscore diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -5,4 +5,19 @@ #[error("...")] pub struct Error; +#[derive(Error, Debug)] +#[error(fmt = core::fmt::Octal::fmt)] +#[error(fmt = core::fmt::LowerHex::fmt)] +pub enum FmtFmt {} + +#[derive(Error, Debug)] +#[error(fmt = core::fmt::Octal::fmt)] +#[error(transparent)] +pub enum FmtTransparent {} + +#[derive(Error, Debug)] +#[error(fmt = core::fmt::Octal::fmt)] +#[error("...")] +pub enum FmtDisplay {} + fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/duplicate-fmt.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -3,3 +3,21 @@ | 5 | #[error("...")] | ^^^^^^^^^^^^^^^ + +error: duplicate #[error(fmt = ...)] attribute + --> tests/ui/duplicate-fmt.rs:10:1 + | +10 | #[error(fmt = core::fmt::LowerHex::fmt)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot have both #[error(transparent)] and #[error(fmt = ...)] + --> tests/ui/duplicate-fmt.rs:14:1 + | +14 | #[error(fmt = core::fmt::Octal::fmt)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot have both #[error(fmt = ...)] and a format arguments attribute + --> tests/ui/duplicate-fmt.rs:20:1 + | +20 | #[error("...")] + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("".yellow)] +pub struct ArgError; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/expression-fallback.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +error: expected `,`, found `.` + --> tests/ui/expression-fallback.rs:4:11 + | +4 | #[error("".yellow)] + | ^ expected `,` + +error: argument never used + --> tests/ui/expression-fallback.rs:4:12 + | +4 | #[error("".yellow)] + | -- ^^^^^^ argument never used + | | + | formatting specifier missing + | +help: format specifiers use curly braces, consider adding a format specifier + | +4 | #[error("{}".yellow)] + | ++ + +error[E0425]: cannot find value `yellow` in this scope + --> tests/ui/expression-fallback.rs:4:12 + | +4 | #[error("".yellow)] + | ^^^^^^ not found in this scope diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/fallback-impl-with-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/fallback-impl-with-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/fallback-impl-with-display.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/fallback-impl-with-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use thiserror::Error; #[derive(Error, Debug)] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/from-not-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/from-not-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/from-not-source.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/from-not-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,6 @@ use thiserror::Error; -#[derive(Debug, Error)] +#[derive(Error, Debug)] pub struct Error { #[source] source: std::io::Error, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/lifetime.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use core::fmt::Debug; use thiserror::Error; #[derive(Error, Debug)] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/missing-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/missing-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/missing-display.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/missing-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,19 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` --> tests/ui/missing-display.rs:4:10 | +3 | #[derive(Error, Debug)] + | ----- in this derive macro expansion 4 | pub enum MyError { - | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | ^^^^^^^ unsatisfied trait bound | - = help: the trait `std::fmt::Display` is not implemented for `MyError` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: the trait `std::fmt::Display` is not implemented for `MyError` + --> tests/ui/missing-display.rs:4:1 + | +4 | pub enum MyError { + | ^^^^^^^^^^^^^^^^ note: required by a bound in `std::error::Error` --> $RUST/core/src/error.rs | | pub trait Error: Debug + Display { | ^^^^^^^ required by this bound in `Error` + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,4 +9,10 @@ thread: NoDisplay, } +#[derive(Error, Debug)] +#[error("thread: {thread:o}")] +pub struct ErrorOctal { + thread: NoDisplay, +} + fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/no-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -13,8 +13,34 @@ note: the trait `std::fmt::Display` must be implemented --> $RUST/core/src/fmt/mod.rs | - | pub trait Display { - | ^^^^^^^^^^^^^^^^^ + | pub trait Display: PointeeSized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `as_display`, perhaps you need to implement it: candidate #1: `AsDisplay` + +error[E0277]: the trait bound `NoDisplay: Octal` is not satisfied + --> tests/ui/no-display.rs:13:9 + | +12 | #[derive(Error, Debug)] + | ----- in this derive macro expansion +13 | #[error("thread: {thread:o}")] + | ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `Octal` is not implemented for `NoDisplay` + --> tests/ui/no-display.rs:4:1 + | + 4 | struct NoDisplay; + | ^^^^^^^^^^^^^^^^ + = help: the following other types implement trait `Octal`: + &T + &mut T + NonZero + Saturating + Wrapping + i128 + i16 + i32 + and $N others + = note: required for `&NoDisplay` to implement `Octal` + = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] +pub struct Error(u32); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/numbered-positional-tuple.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: ambiguous reference to positional arguments by number in a tuple struct; change this to a named argument + --> tests/ui/numbered-positional-tuple.rs:4:61 + | +4 | #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] + | ^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("error: {r#fn}")] +pub struct Error { + r#fn: &'static str, +} + +fn main() { + let r#fn = "..."; + let _ = format!("error: {r#fn}"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/raw-identifier.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +error: invalid format string: raw identifiers are not supported + --> tests/ui/raw-identifier.rs:4:18 + | +4 | #[error("error: {r#fn}")] + | --^^ + | | + | raw identifier used here in format string + | help: remove the `r#` + | + = note: identifiers in format strings can be keywords and don't need to be prefixed with `r#` + +error: invalid format string: raw identifiers are not supported + --> tests/ui/raw-identifier.rs:11:30 + | +11 | let _ = format!("error: {r#fn}"); + | --^^ + | | + | raw identifier used here in format string + | help: remove the `r#` + | + = note: identifiers in format strings can be keywords and don't need to be prefixed with `r#` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("failed to open")] + OpenFile(#[from] std::io::Error), + #[error("failed to close")] + CloseFile(#[from] std::io::Error), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/same-from-type.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error[E0119]: conflicting implementations of trait `From` for type `Error` + --> tests/ui/same-from-type.rs:8:15 + | +6 | OpenFile(#[from] std::io::Error), + | ------- first implementation here +7 | #[error("failed to close")] +8 | CloseFile(#[from] std::io::Error), + | ^^^^^^^ conflicting implementation for `Error` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,11 @@ error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but its trait bounds were not satisfied - --> tests/ui/source-enum-unnamed-field-not-error.rs:9:14 + --> tests/ui/source-enum-unnamed-field-not-error.rs:9:12 | 4 | pub struct NotError; | ------------------- doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` ... 9 | Broken(#[source] NotError), - | ^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds + | ^^^^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `NotError: std::error::Error` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -1,11 +1,11 @@ error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its trait bounds were not satisfied - --> tests/ui/source-struct-unnamed-field-not-error.rs:8:26 + --> tests/ui/source-struct-unnamed-field-not-error.rs:8:24 | 4 | struct NotError; | --------------- method `as_dyn_error` not found for this struct because it doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` ... 8 | pub struct ErrorStruct(#[source] NotError); - | ^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds + | ^^^^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `NotError: std::error::Error` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(fmt = core::fmt::Octal::fmt)] +pub struct Error(i32); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/struct-with-fmt.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: #[error(fmt = ...)] is only supported in enums; for a struct, handwrite your own Display impl + --> tests/ui/struct-with-fmt.rs:4:1 + | +4 | #[error(fmt = core::fmt::Octal::fmt)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("{self}")] +pub struct Error; + +fn main() { + __FAIL__; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror/tests/ui/unconditional-recursion.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `__FAIL__` in this scope + --> tests/ui/unconditional-recursion.rs:8:5 + | +8 | __FAIL__; + | ^^^^^^^^ not found in this scope + +warning: function cannot return without recursing + --> tests/ui/unconditional-recursion.rs:4:9 + | +4 | #[error("{self}")] + | ^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose +note: the lint level is defined here + --> tests/ui/unconditional-recursion.rs:4:9 + | +4 | #[error("{self}")] + | ^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"c308d63d0649eee0125a2e26243ea20a62522442d8e89a461a4cebb33a387a99",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"8235e2cc9d8c083421b25e5e444b8a59000216254f1997a86ffa79ae7f02ff5f","Cargo.toml":"7df807832514d69476a436a1466ed9cefde6d73f8fff7829718096c8bf6bb88e","Cargo.toml.orig":"48ee054cee19760af0e46c14898e8f19012752af8d4d99be0aa0a5011fdbe921","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"106c5a937767d49503e1fc5eae1b924f57f15decd8583720a3c652483e348a64","build.rs":"e93f4e6f8b7d24c9b119a85ea134067d2c2a7f78e082c1ab1e541c41225d5a36","build/probe.rs":"3245569a228727091f335db44c7c2f729729b2dfac9f46c1143eb179439f223d","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"cf3c98abb2b9e06afa3c4aba0df14938417c3e330315863437561cbb3573888b","src/display.rs":"0adeeeb524c6bee06de179d54e82a43dc12d2c5b7f69f6fd268ba4611ebf5233","src/lib.rs":"6a823f259101ba3c28fc8824afbe6ce66c1c4ffa7bea183172b25b891dfa1695","src/provide.rs":"8007e22953bacfcc57bb7d12a03fbeb0acece5d2ec889cf55522a4e071d26df3","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"a8f038490fb881463c0e8c36557617c47cf2d181f16c00525d4d139c7964fade","tests/test_deprecated.rs":"7b80a10f090a3982da017556d3d71398abcead59afd8278c7b9d9b1f7b66c7b3","tests/test_display.rs":"91a6bf704fd78a5565330f438f30ae4088aa8bc7ac5e1412401e440072408c03","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"d35b11040ebc547467f52571051854e3e094d52b8e229fa3d44700d5f40959a2","tests/test_from.rs":"36bd22be7b048cd187a19076aeac1456040f20a0b677b01c6003998b63439ea1","tests/test_generics.rs":"adc61f0d5fe8d53796848d44fb0373be5eab19a1eeb6a7172bc6f0dd7b91199c","tests/test_lints.rs":"93d66ea5b6b91634ddf18a520b455f8bc65f3e9bbf90874e239f45ab15b0c125","tests/test_option.rs":"ac30d929c019d6c54d1c1792b09e43c18dc0e4123b82051ff9e5db5e63c15e43","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/fallback-impl-with-display.rs":"141a8efbabe3fdac584bec8a61e6cceb58a34a70b825f6277037bf9d591150eb","tests/ui/fallback-impl-with-display.stderr":"1b3dad712b97598fbee70125471de1a8106eb161d42ce1f790ae07be8c8984ba","tests/ui/from-backtrace-backtrace.rs":"0caac64486c0eb9c076553c0502d468fbc477602a9a2595165a1dcd95524e5ff","tests/ui/from-backtrace-backtrace.stderr":"e24156ae0828878f3282341732b6e032eaa8cb4b4db366a6b5437ed0731d40a7","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/invalid-input-impl-anyway.rs":"6de91f71ddf038dffa3b9da33763a2ec3a5aa0047528e19ba998d5efe3aada5b","tests/ui/invalid-input-impl-anyway.stderr":"fa2725053cd87fc37f87546b377e6e5eed95c45e2a960863303b21a1935fdddb","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-display.rs":"c1fd1bc0ec0fb103d7f7b128837f717d49485662839899d570b3c983f1332888","tests/ui/missing-display.stderr":"a8de0f1559da9320ee99ef334937d532d9e9f40a32ed7f8ce56fb465628bff96","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"c145dbdd39e145b5c6f26f8504fbf1e33efa2eada37e09900b39dd62667f22d7","tests/ui/source-enum-not-error.rs":"3add5e7b4503d964bcae0848904822e1473c1d08c5a146c2df5347314ce1b8df","tests/ui/source-enum-not-error.stderr":"aeba0a8a0084833e470b6be2250370809f53c279ad603232af5302b9de9f8cce","tests/ui/source-enum-unnamed-field-not-error.rs":"a98989e908b84a8e6e6dceef02af7bdd1098a444d229950f67ed4f54d55c62e7","tests/ui/source-enum-unnamed-field-not-error.stderr":"4f3d90525dd462e67f633e83b26acec75d9af3626e40d28ded2c2438e0c73192","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"b45eb66f078fec68d44feff1f8d6a676c341e9e9d9acb35daa58ec1ea20f9dae","tests/ui/source-struct-unnamed-field-not-error.rs":"eee605a9aafbb093666393e25cef4f7d7b8e90d518b9fadbdbed9685c66ccfcd","tests/ui/source-struct-unnamed-field-not-error.stderr":"10e408f71c1b61880b1d52739f222ec58a66be70a1df17e44c536fe0f9ffe2a6","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-not-error.rs":"f6315993e68bc71d6d4d39afa4d059695308ef785f92cc0d1df3e9ff55be2a9a","tests/ui/transparent-enum-not-error.stderr":"3a5fe056cd4566f402b03cb591394e0ba85bd74da53df3c8d50bda4a05c2e5ba","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-enum-unnamed-field-not-error.rs":"0c720567e9e0f87921055dfa9f607661725377633445e01a4b5048c7a7a50a85","tests/ui/transparent-enum-unnamed-field-not-error.stderr":"6d84e9a7f4e88daba12931a6c1508be60bb19125d06e44fa2fa205126d953bb1","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-not-error.rs":"fd814d3141c9182b1267b558d9daef8dd6e8b6462e1ad42b197f3a1c0703dce2","tests/ui/transparent-struct-not-error.stderr":"ac7634ea72096d8a5c1a91fd4f1b45ef870130a2698d9ae7c6530cec2f9799d5","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/transparent-struct-unnamed-field-not-error.rs":"fbff5874be44a5dcc347693d7929537256b187dfec467ed72c9968c095228d8d","tests/ui/transparent-struct-unnamed-field-not-error.stderr":"ea99d5422348c2588ad7374360e2a24649f040b9c5614c9308eff958f61960ec","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e7ad85ee6b135c5748d37ed1e8edda950336af77" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,106 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.56.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + components: rust-src + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - name: Enable nightly-only tests + run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=thiserror_nightly_testing >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test --all + + minimal: + name: Minimal versions + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked + + doc: + name: Documentation + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rust-src + - run: cargo clippy --tests --workspace -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cargo miri test + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56" +name = "thiserror" +version = "1.0.59" +authors = ["David Tolnay "] +description = "derive(Error)" +documentation = "https://docs.rs/thiserror" +readme = "README.md" +keywords = [ + "error", + "error-handling", + "derive", +] +categories = ["rust-patterns"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.thiserror-impl] +version = "=1.0.59" + +[dev-dependencies.anyhow] +version = "1.0.73" + +[dev-dependencies.ref-cast] +version = "1.0.18" + +[dev-dependencies.rustversion] +version = "1.0.13" + +[dev-dependencies.trybuild] +version = "1.0.81" +features = ["diff"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "thiserror" +version = "1.0.59" +authors = ["David Tolnay "] +categories = ["rust-patterns"] +description = "derive(Error)" +documentation = "https://docs.rs/thiserror" +edition = "2021" +keywords = ["error", "error-handling", "derive"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" +rust-version = "1.56" + +[dependencies] +thiserror-impl = { version = "=1.0.59", path = "impl" } + +[dev-dependencies] +anyhow = "1.0.73" +ref-cast = "1.0.18" +rustversion = "1.0.13" +trybuild = { version = "1.0.81", features = ["diff"] } + +[workspace] +members = ["impl"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/README.md clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,222 @@ +derive(Error) +============= + +[github](https://github.com/dtolnay/thiserror) +[crates.io](https://crates.io/crates/thiserror) +[docs.rs](https://docs.rs/thiserror) +[build status](https://github.com/dtolnay/thiserror/actions?query=branch%3Amaster) + +This library provides a convenient derive macro for the standard library's +[`std::error::Error`] trait. + +[`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html + +```toml +[dependencies] +thiserror = "1.0" +``` + +*Compiler support: requires rustc 1.56+* + +
+ +## Example + +```rust +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum DataStoreError { + #[error("data store disconnected")] + Disconnect(#[from] io::Error), + #[error("the data for key `{0}` is not available")] + Redaction(String), + #[error("invalid header (expected {expected:?}, found {found:?})")] + InvalidHeader { + expected: String, + found: String, + }, + #[error("unknown data store error")] + Unknown, +} +``` + +
+ +## Details + +- Thiserror deliberately does not appear in your public API. You get the same + thing as if you had written an implementation of `std::error::Error` by hand, + and switching from handwritten impls to thiserror or vice versa is not a + breaking change. + +- Errors may be enums, structs with named fields, tuple structs, or unit + structs. + +- A `Display` impl is generated for your error if you provide `#[error("...")]` + messages on the struct or each variant of your enum, as shown above in the + example. + + The messages support a shorthand for interpolating fields from the error. + + - `#[error("{var}")]` ⟶ `write!("{}", self.var)` + - `#[error("{0}")]` ⟶ `write!("{}", self.0)` + - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)` + - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)` + + These shorthands can be used together with any additional format args, which + may be arbitrary expressions. For example: + + ```rust + #[derive(Error, Debug)] + pub enum Error { + #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] + InvalidLookahead(u32), + } + ``` + + If one of the additional expression arguments needs to refer to a field of the + struct or enum, then refer to named fields as `.var` and tuple fields as `.0`. + + ```rust + #[derive(Error, Debug)] + pub enum Error { + #[error("first letter must be lowercase but was {:?}", first_char(.0))] + WrongCase(String), + #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)] + OutOfBounds { idx: usize, limits: Limits }, + } + ``` + +- A `From` impl is generated for each variant containing a `#[from]` attribute. + + Note that the variant must not contain any other fields beyond the source + error and possibly a backtrace. A backtrace is captured from within the `From` + impl if there is a field for it. + + ```rust + #[derive(Error, Debug)] + pub enum MyError { + Io { + #[from] + source: io::Error, + backtrace: Backtrace, + }, + } + ``` + +- The Error trait's `source()` method is implemented to return whichever field + has a `#[source]` attribute or is named `source`, if any. This is for + identifying the underlying lower level error that caused your error. + + The `#[from]` attribute always implies that the same field is `#[source]`, so + you don't ever need to specify both attributes. + + Any error type that implements `std::error::Error` or dereferences to `dyn + std::error::Error` will work as a source. + + ```rust + #[derive(Error, Debug)] + pub struct MyError { + msg: String, + #[source] // optional if field name is `source` + source: anyhow::Error, + } + ``` + +- The Error trait's `provide()` method is implemented to provide whichever field + has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`. + + ```rust + use std::backtrace::Backtrace; + + #[derive(Error, Debug)] + pub struct MyError { + msg: String, + backtrace: Backtrace, // automatically detected + } + ``` + +- If a field is both a source (named `source`, or has `#[source]` or `#[from]` + attribute) *and* is marked `#[backtrace]`, then the Error trait's `provide()` + method is forwarded to the source's `provide` so that both layers of the error + share the same backtrace. + + ```rust + #[derive(Error, Debug)] + pub enum MyError { + Io { + #[backtrace] + source: io::Error, + }, + } + ``` + +- Errors may use `error(transparent)` to forward the source and Display methods + straight through to an underlying error without adding an additional message. + This would be appropriate for enums that need an "anything else" variant. + + ```rust + #[derive(Error, Debug)] + pub enum MyError { + ... + + #[error(transparent)] + Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error + } + ``` + + Another use case is hiding implementation details of an error representation + behind an opaque error type, so that the representation is able to evolve + without breaking the crate's public API. + + ```rust + // PublicError is public, but opaque and easy to keep compatible. + #[derive(Error, Debug)] + #[error(transparent)] + pub struct PublicError(#[from] ErrorRepr); + + impl PublicError { + // Accessors for anything we do want to expose publicly. + } + + // Private and free to change across minor version of the crate. + #[derive(Error, Debug)] + enum ErrorRepr { + ... + } + ``` + +- See also the [`anyhow`] library for a convenient single error type to use in + application code. + + [`anyhow`]: https://github.com/dtolnay/anyhow + +
+ +## Comparison to anyhow + +Use thiserror if you care about designing your own dedicated error type(s) so +that the caller receives exactly the information that you choose in the event of +failure. This most often applies to library-like code. Use [Anyhow] if you don't +care what error type your functions return, you just want it to be easy. This is +common in application-like code. + +[Anyhow]: https://github.com/dtolnay/anyhow + +
+ +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/build/probe.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build/probe.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/build/probe.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build/probe.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +// This code exercises the surface area that we expect of the Error generic +// member access API. If the current toolchain is able to compile it, then +// thiserror is able to provide backtrace support. + +#![feature(error_generic_member_access)] + +use std::error::{Error, Request}; +use std::fmt::{self, Debug, Display}; + +struct MyError(Thing); +struct Thing; + +impl Debug for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +impl Display for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +impl Error for MyError { + fn provide<'a>(&'a self, request: &mut Request<'a>) { + request.provide_ref(&self.0); + } +} + +// Include in sccache cache key. +const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/build.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/build.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +use std::env; +use std::ffi::OsString; +use std::iter; +use std::path::Path; +use std::process::{self, Command, Stdio}; + +fn main() { + println!("cargo:rerun-if-changed=build/probe.rs"); + + let error_generic_member_access; + let consider_rustc_bootstrap; + if compile_probe(false) { + // This is a nightly or dev compiler, so it supports unstable features + // regardless of RUSTC_BOOTSTRAP. No need to rerun build script if + // RUSTC_BOOTSTRAP is changed. + error_generic_member_access = true; + consider_rustc_bootstrap = false; + } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { + if compile_probe(true) { + // This is a stable or beta compiler for which the user has set + // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script + // if they change it. + error_generic_member_access = true; + consider_rustc_bootstrap = true; + } else if rustc_bootstrap == "1" { + // This compiler does not support the generic member access API in + // the form that thiserror expects. No need to pay attention to + // RUSTC_BOOTSTRAP. + error_generic_member_access = false; + consider_rustc_bootstrap = false; + } else { + // This is a stable or beta compiler for which RUSTC_BOOTSTRAP is + // set to restrict the use of unstable features by this crate. + error_generic_member_access = false; + consider_rustc_bootstrap = true; + } + } else { + // Without RUSTC_BOOTSTRAP, this compiler does not support the generic + // member access API in the form that thiserror expects, but try again + // if the user turns on unstable features. + error_generic_member_access = false; + consider_rustc_bootstrap = true; + } + + if error_generic_member_access { + println!("cargo:rustc-cfg=error_generic_member_access"); + } + + if consider_rustc_bootstrap { + println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); + } +} + +fn compile_probe(rustc_bootstrap: bool) -> bool { + if env::var_os("RUSTC_STAGE").is_some() { + // We are running inside rustc bootstrap. This is a highly non-standard + // environment with issues such as: + // + // https://github.com/rust-lang/cargo/issues/11138 + // https://github.com/rust-lang/rust/issues/114839 + // + // Let's just not use nightly features here. + return false; + } + + let rustc = cargo_env_var("RUSTC"); + let out_dir = cargo_env_var("OUT_DIR"); + let probefile = Path::new("build").join("probe.rs"); + + let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); + let rustc_workspace_wrapper = + env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); + let mut rustc = rustc_wrapper + .into_iter() + .chain(rustc_workspace_wrapper) + .chain(iter::once(rustc)); + let mut cmd = Command::new(rustc.next().unwrap()); + cmd.args(rustc); + + if !rustc_bootstrap { + cmd.env_remove("RUSTC_BOOTSTRAP"); + } + + cmd.stderr(Stdio::null()) + .arg("--edition=2018") + .arg("--crate-name=thiserror") + .arg("--crate-type=lib") + .arg("--cap-lints=allow") + .arg("--emit=dep-info,metadata") + .arg("--out-dir") + .arg(out_dir) + .arg(probefile); + + if let Some(target) = env::var_os("TARGET") { + cmd.arg("--target").arg(target); + } + + // If Cargo wants to set RUSTFLAGS, use that. + if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + for arg in rustflags.split('\x1f') { + cmd.arg(arg); + } + } + } + + match cmd.status() { + Ok(status) => status.success(), + Err(_) => false, + } +} + +fn cargo_env_var(key: &str) -> OsString { + env::var_os(key).unwrap_or_else(|| { + eprintln!( + "Environment variable ${} is not set during execution of build script", + key, + ); + process::exit(1); + }) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/rust-toolchain.toml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/rust-toolchain.toml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/rust-toolchain.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/rust-toolchain.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2 @@ +[toolchain] +components = ["rust-src"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/aserror.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/aserror.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/aserror.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/aserror.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,50 @@ +use std::error::Error; +use std::panic::UnwindSafe; + +#[doc(hidden)] +pub trait AsDynError<'a>: Sealed { + fn as_dyn_error(&self) -> &(dyn Error + 'a); +} + +impl<'a, T: Error + 'a> AsDynError<'a> for T { + #[inline] + fn as_dyn_error(&self) -> &(dyn Error + 'a) { + self + } +} + +impl<'a> AsDynError<'a> for dyn Error + 'a { + #[inline] + fn as_dyn_error(&self) -> &(dyn Error + 'a) { + self + } +} + +impl<'a> AsDynError<'a> for dyn Error + Send + 'a { + #[inline] + fn as_dyn_error(&self) -> &(dyn Error + 'a) { + self + } +} + +impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a { + #[inline] + fn as_dyn_error(&self) -> &(dyn Error + 'a) { + self + } +} + +impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a { + #[inline] + fn as_dyn_error(&self) -> &(dyn Error + 'a) { + self + } +} + +#[doc(hidden)] +pub trait Sealed {} +impl<'a, T: Error + 'a> Sealed for T {} +impl<'a> Sealed for dyn Error + 'a {} +impl<'a> Sealed for dyn Error + Send + 'a {} +impl<'a> Sealed for dyn Error + Send + Sync + 'a {} +impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +use std::fmt::Display; +use std::path::{self, Path, PathBuf}; + +#[doc(hidden)] +pub trait AsDisplay<'a> { + // TODO: convert to generic associated type. + // https://github.com/dtolnay/thiserror/pull/253 + type Target: Display; + + fn as_display(&'a self) -> Self::Target; +} + +impl<'a, T> AsDisplay<'a> for &T +where + T: Display + 'a, +{ + type Target = &'a T; + + fn as_display(&'a self) -> Self::Target { + *self + } +} + +impl<'a> AsDisplay<'a> for Path { + type Target = path::Display<'a>; + + #[inline] + fn as_display(&'a self) -> Self::Target { + self.display() + } +} + +impl<'a> AsDisplay<'a> for PathBuf { + type Target = path::Display<'a>; + + #[inline] + fn as_display(&'a self) -> Self::Target { + self.display() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,260 @@ +//! [![github]](https://github.com/dtolnay/thiserror) [![crates-io]](https://crates.io/crates/thiserror) [![docs-rs]](https://docs.rs/thiserror) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//!
+//! +//! This library provides a convenient derive macro for the standard library's +//! [`std::error::Error`] trait. +//! +//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html +//! +//!
+//! +//! # Example +//! +//! ```rust +//! # use std::io; +//! use thiserror::Error; +//! +//! #[derive(Error, Debug)] +//! pub enum DataStoreError { +//! #[error("data store disconnected")] +//! Disconnect(#[from] io::Error), +//! #[error("the data for key `{0}` is not available")] +//! Redaction(String), +//! #[error("invalid header (expected {expected:?}, found {found:?})")] +//! InvalidHeader { +//! expected: String, +//! found: String, +//! }, +//! #[error("unknown data store error")] +//! Unknown, +//! } +//! ``` +//! +//!
+//! +//! # Details +//! +//! - Thiserror deliberately does not appear in your public API. You get the +//! same thing as if you had written an implementation of `std::error::Error` +//! by hand, and switching from handwritten impls to thiserror or vice versa +//! is not a breaking change. +//! +//! - Errors may be enums, structs with named fields, tuple structs, or unit +//! structs. +//! +//! - A `Display` impl is generated for your error if you provide +//! `#[error("...")]` messages on the struct or each variant of your enum, as +//! shown above in the example. +//! +//! The messages support a shorthand for interpolating fields from the error. +//! +//! - `#[error("{var}")]` ⟶ `write!("{}", self.var)` +//! - `#[error("{0}")]` ⟶ `write!("{}", self.0)` +//! - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)` +//! - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)` +//! +//! These shorthands can be used together with any additional format args, +//! which may be arbitrary expressions. For example: +//! +//! ```rust +//! # use std::i32; +//! # use thiserror::Error; +//! # +//! #[derive(Error, Debug)] +//! pub enum Error { +//! #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] +//! InvalidLookahead(u32), +//! } +//! ``` +//! +//! If one of the additional expression arguments needs to refer to a field of +//! the struct or enum, then refer to named fields as `.var` and tuple fields +//! as `.0`. +//! +//! ```rust +//! # use thiserror::Error; +//! # +//! # fn first_char(s: &String) -> char { +//! # s.chars().next().unwrap() +//! # } +//! # +//! # #[derive(Debug)] +//! # struct Limits { +//! # lo: usize, +//! # hi: usize, +//! # } +//! # +//! #[derive(Error, Debug)] +//! pub enum Error { +//! #[error("first letter must be lowercase but was {:?}", first_char(.0))] +//! WrongCase(String), +//! #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)] +//! OutOfBounds { idx: usize, limits: Limits }, +//! } +//! ``` +//! +//! - A `From` impl is generated for each variant containing a `#[from]` +//! attribute. +//! +//! Note that the variant must not contain any other fields beyond the source +//! error and possibly a backtrace. A backtrace is captured from within the +//! `From` impl if there is a field for it. +//! +//! ```rust +//! # const IGNORE: &str = stringify! { +//! #[derive(Error, Debug)] +//! pub enum MyError { +//! Io { +//! #[from] +//! source: io::Error, +//! backtrace: Backtrace, +//! }, +//! } +//! # }; +//! ``` +//! +//! - The Error trait's `source()` method is implemented to return whichever +//! field has a `#[source]` attribute or is named `source`, if any. This is +//! for identifying the underlying lower level error that caused your error. +//! +//! The `#[from]` attribute always implies that the same field is `#[source]`, +//! so you don't ever need to specify both attributes. +//! +//! Any error type that implements `std::error::Error` or dereferences to `dyn +//! std::error::Error` will work as a source. +//! +//! ```rust +//! # use std::fmt::{self, Display}; +//! # use thiserror::Error; +//! # +//! #[derive(Error, Debug)] +//! pub struct MyError { +//! msg: String, +//! #[source] // optional if field name is `source` +//! source: anyhow::Error, +//! } +//! # +//! # impl Display for MyError { +//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +//! # unimplemented!() +//! # } +//! # } +//! ``` +//! +//! - The Error trait's `provide()` method is implemented to provide whichever +//! field has a type named `Backtrace`, if any, as a +//! `std::backtrace::Backtrace`. +//! +//! ```rust +//! # const IGNORE: &str = stringify! { +//! use std::backtrace::Backtrace; +//! +//! #[derive(Error, Debug)] +//! pub struct MyError { +//! msg: String, +//! backtrace: Backtrace, // automatically detected +//! } +//! # }; +//! ``` +//! +//! - If a field is both a source (named `source`, or has `#[source]` or +//! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error +//! trait's `provide()` method is forwarded to the source's `provide` so that +//! both layers of the error share the same backtrace. +//! +//! ```rust +//! # const IGNORE: &str = stringify! { +//! #[derive(Error, Debug)] +//! pub enum MyError { +//! Io { +//! #[backtrace] +//! source: io::Error, +//! }, +//! } +//! # }; +//! ``` +//! +//! - Errors may use `error(transparent)` to forward the source and Display +//! methods straight through to an underlying error without adding an +//! additional message. This would be appropriate for enums that need an +//! "anything else" variant. +//! +//! ``` +//! # use thiserror::Error; +//! # +//! #[derive(Error, Debug)] +//! pub enum MyError { +//! # /* +//! ... +//! # */ +//! +//! #[error(transparent)] +//! Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error +//! } +//! ``` +//! +//! Another use case is hiding implementation details of an error +//! representation behind an opaque error type, so that the representation is +//! able to evolve without breaking the crate's public API. +//! +//! ``` +//! # use thiserror::Error; +//! # +//! // PublicError is public, but opaque and easy to keep compatible. +//! #[derive(Error, Debug)] +//! #[error(transparent)] +//! pub struct PublicError(#[from] ErrorRepr); +//! +//! impl PublicError { +//! // Accessors for anything we do want to expose publicly. +//! } +//! +//! // Private and free to change across minor version of the crate. +//! #[derive(Error, Debug)] +//! enum ErrorRepr { +//! # /* +//! ... +//! # */ +//! } +//! ``` +//! +//! - See also the [`anyhow`] library for a convenient single error type to use +//! in application code. +//! +//! [`anyhow`]: https://github.com/dtolnay/anyhow + +#![doc(html_root_url = "https://docs.rs/thiserror/1.0.59")] +#![allow( + clippy::module_name_repetitions, + clippy::needless_lifetimes, + clippy::return_self_not_must_use, + clippy::wildcard_imports +)] +#![cfg_attr(error_generic_member_access, feature(error_generic_member_access))] + +#[cfg(all(thiserror_nightly_testing, not(error_generic_member_access)))] +compile_error!("Build script probe failed to compile."); + +mod aserror; +mod display; +#[cfg(error_generic_member_access)] +mod provide; + +pub use thiserror_impl::*; + +// Not public API. +#[doc(hidden)] +pub mod __private { + #[doc(hidden)] + pub use crate::aserror::AsDynError; + #[doc(hidden)] + pub use crate::display::AsDisplay; + #[cfg(error_generic_member_access)] + #[doc(hidden)] + pub use crate::provide::ThiserrorProvide; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/provide.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/provide.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/src/provide.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/src/provide.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +use std::error::{Error, Request}; + +#[doc(hidden)] +pub trait ThiserrorProvide: Sealed { + fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>); +} + +impl ThiserrorProvide for T +where + T: Error + ?Sized, +{ + #[inline] + fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { + self.provide(request); + } +} + +#[doc(hidden)] +pub trait Sealed {} +impl Sealed for T {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/compiletest.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/compiletest.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/compiletest.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/compiletest.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +#[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(miri, ignore)] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_backtrace.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_backtrace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_backtrace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_backtrace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,274 @@ +#![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] + +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("...")] +pub struct Inner; + +#[cfg(thiserror_nightly_testing)] +#[derive(Error, Debug)] +#[error("...")] +pub struct InnerBacktrace { + backtrace: std::backtrace::Backtrace, +} + +#[cfg(thiserror_nightly_testing)] +pub mod structs { + use super::{Inner, InnerBacktrace}; + use std::backtrace::Backtrace; + use std::error::{self, Error}; + use std::sync::Arc; + use thiserror::Error; + + #[derive(Error, Debug)] + #[error("...")] + pub struct PlainBacktrace { + backtrace: Backtrace, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct ExplicitBacktrace { + #[backtrace] + backtrace: Backtrace, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct OptBacktrace { + #[backtrace] + backtrace: Option, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct ArcBacktrace { + #[backtrace] + backtrace: Arc, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct BacktraceFrom { + #[from] + source: Inner, + #[backtrace] + backtrace: Backtrace, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct CombinedBacktraceFrom { + #[from] + #[backtrace] + source: InnerBacktrace, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct OptBacktraceFrom { + #[from] + source: Inner, + #[backtrace] + backtrace: Option, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct ArcBacktraceFrom { + #[from] + source: Inner, + #[backtrace] + backtrace: Arc, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct AnyhowBacktrace { + #[backtrace] + source: anyhow::Error, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct BoxDynErrorBacktrace { + #[backtrace] + source: Box, + } + + #[test] + fn test_backtrace() { + let error = PlainBacktrace { + backtrace: Backtrace::capture(), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = ExplicitBacktrace { + backtrace: Backtrace::capture(), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = OptBacktrace { + backtrace: Some(Backtrace::capture()), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = ArcBacktrace { + backtrace: Arc::new(Backtrace::capture()), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = BacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + + let error = CombinedBacktraceFrom::from(InnerBacktrace { + backtrace: Backtrace::capture(), + }); + assert!(error::request_ref::(&error).is_some()); + + let error = OptBacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + + let error = ArcBacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + + let error = AnyhowBacktrace { + source: anyhow::Error::msg("..."), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = BoxDynErrorBacktrace { + source: Box::new(PlainBacktrace { + backtrace: Backtrace::capture(), + }), + }; + assert!(error::request_ref::(&error).is_some()); + } +} + +#[cfg(thiserror_nightly_testing)] +pub mod enums { + use super::{Inner, InnerBacktrace}; + use std::backtrace::Backtrace; + use std::error; + use std::sync::Arc; + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum PlainBacktrace { + #[error("...")] + Test { backtrace: Backtrace }, + } + + #[derive(Error, Debug)] + pub enum ExplicitBacktrace { + #[error("...")] + Test { + #[backtrace] + backtrace: Backtrace, + }, + } + + #[derive(Error, Debug)] + pub enum OptBacktrace { + #[error("...")] + Test { + #[backtrace] + backtrace: Option, + }, + } + + #[derive(Error, Debug)] + pub enum ArcBacktrace { + #[error("...")] + Test { + #[backtrace] + backtrace: Arc, + }, + } + + #[derive(Error, Debug)] + pub enum BacktraceFrom { + #[error("...")] + Test { + #[from] + source: Inner, + #[backtrace] + backtrace: Backtrace, + }, + } + + #[derive(Error, Debug)] + pub enum CombinedBacktraceFrom { + #[error("...")] + Test { + #[from] + #[backtrace] + source: InnerBacktrace, + }, + } + + #[derive(Error, Debug)] + pub enum OptBacktraceFrom { + #[error("...")] + Test { + #[from] + source: Inner, + #[backtrace] + backtrace: Option, + }, + } + + #[derive(Error, Debug)] + pub enum ArcBacktraceFrom { + #[error("...")] + Test { + #[from] + source: Inner, + #[backtrace] + backtrace: Arc, + }, + } + + #[test] + fn test_backtrace() { + let error = PlainBacktrace::Test { + backtrace: Backtrace::capture(), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = ExplicitBacktrace::Test { + backtrace: Backtrace::capture(), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = OptBacktrace::Test { + backtrace: Some(Backtrace::capture()), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = ArcBacktrace::Test { + backtrace: Arc::new(Backtrace::capture()), + }; + assert!(error::request_ref::(&error).is_some()); + + let error = BacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + + let error = CombinedBacktraceFrom::from(InnerBacktrace { + backtrace: Backtrace::capture(), + }); + assert!(error::request_ref::(&error).is_some()); + + let error = OptBacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + + let error = ArcBacktraceFrom::from(Inner); + assert!(error::request_ref::(&error).is_some()); + } +} + +#[test] +#[cfg_attr(not(thiserror_nightly_testing), ignore)] +fn test_backtrace() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_deprecated.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_deprecated.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_deprecated.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_deprecated.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +#![deny(deprecated, clippy::all, clippy::pedantic)] + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[deprecated] + #[error("...")] + Deprecated, +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,358 @@ +#![allow(clippy::needless_raw_string_hashes, clippy::uninlined_format_args)] + +use std::fmt::{self, Display}; +use thiserror::Error; + +fn assert(expected: &str, value: T) { + assert_eq!(expected, value.to_string()); +} + +#[test] +fn test_braced() { + #[derive(Error, Debug)] + #[error("braced error: {msg}")] + struct Error { + msg: String, + } + + let msg = "T".to_owned(); + assert("braced error: T", Error { msg }); +} + +#[test] +fn test_braced_unused() { + #[derive(Error, Debug)] + #[error("braced error")] + struct Error { + extra: usize, + } + + assert("braced error", Error { extra: 0 }); +} + +#[test] +fn test_tuple() { + #[derive(Error, Debug)] + #[error("tuple error: {0}")] + struct Error(usize); + + assert("tuple error: 0", Error(0)); +} + +#[test] +fn test_unit() { + #[derive(Error, Debug)] + #[error("unit error")] + struct Error; + + assert("unit error", Error); +} + +#[test] +fn test_enum() { + #[derive(Error, Debug)] + enum Error { + #[error("braced error: {id}")] + Braced { id: usize }, + #[error("tuple error: {0}")] + Tuple(usize), + #[error("unit error")] + Unit, + } + + assert("braced error: 0", Error::Braced { id: 0 }); + assert("tuple error: 0", Error::Tuple(0)); + assert("unit error", Error::Unit); +} + +#[test] +fn test_constants() { + #[derive(Error, Debug)] + #[error("{MSG}: {id:?} (code {CODE:?})")] + struct Error { + id: &'static str, + } + + const MSG: &str = "failed to do"; + const CODE: usize = 9; + + assert("failed to do: \"\" (code 9)", Error { id: "" }); +} + +#[test] +fn test_inherit() { + #[derive(Error, Debug)] + #[error("{0}")] + enum Error { + Some(&'static str), + #[error("other error")] + Other(&'static str), + } + + assert("some error", Error::Some("some error")); + assert("other error", Error::Other("...")); +} + +#[test] +fn test_brace_escape() { + #[derive(Error, Debug)] + #[error("fn main() {{}}")] + struct Error; + + assert("fn main() {}", Error); +} + +#[test] +fn test_expr() { + #[derive(Error, Debug)] + #[error("1 + 1 = {}", 1 + 1)] + struct Error; + assert("1 + 1 = 2", Error); +} + +#[test] +fn test_nested() { + #[derive(Error, Debug)] + #[error("!bool = {}", not(.0))] + struct Error(bool); + + #[allow(clippy::trivially_copy_pass_by_ref)] + fn not(bool: &bool) -> bool { + !*bool + } + + assert("!bool = false", Error(true)); +} + +#[test] +fn test_match() { + #[derive(Error, Debug)] + #[error("{}: {0}", match .1 { + Some(n) => format!("error occurred with {}", n), + None => "there was an empty error".to_owned(), + })] + struct Error(String, Option); + + assert( + "error occurred with 1: ...", + Error("...".to_owned(), Some(1)), + ); + assert( + "there was an empty error: ...", + Error("...".to_owned(), None), + ); +} + +#[test] +fn test_nested_display() { + // Same behavior as the one in `test_match`, but without String allocations. + #[derive(Error, Debug)] + #[error("{}", { + struct Msg<'a>(&'a String, &'a Option); + impl<'a> Display for Msg<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.1 { + Some(n) => write!(formatter, "error occurred with {}", n), + None => write!(formatter, "there was an empty error"), + }?; + write!(formatter, ": {}", self.0) + } + } + Msg(.0, .1) + })] + struct Error(String, Option); + + assert( + "error occurred with 1: ...", + Error("...".to_owned(), Some(1)), + ); + assert( + "there was an empty error: ...", + Error("...".to_owned(), None), + ); +} + +#[test] +fn test_void() { + #[allow(clippy::empty_enum)] + #[derive(Error, Debug)] + #[error("...")] + pub enum Error {} + + let _: Error; +} + +#[test] +fn test_mixed() { + #[derive(Error, Debug)] + #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)] + struct Error { + a: usize, + d: usize, + } + + assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 }); +} + +#[test] +fn test_ints() { + #[derive(Error, Debug)] + enum Error { + #[error("error {0}")] + Tuple(usize, usize), + #[error("error {0}", '?')] + Struct { v: usize }, + } + + assert("error 9", Error::Tuple(9, 0)); + assert("error ?", Error::Struct { v: 0 }); +} + +#[test] +fn test_trailing_comma() { + #[derive(Error, Debug)] + #[error( + "error {0}", + )] + #[rustfmt::skip] + struct Error(char); + + assert("error ?", Error('?')); +} + +#[test] +fn test_field() { + #[derive(Debug)] + struct Inner { + data: usize, + } + + #[derive(Error, Debug)] + #[error("{}", .0.data)] + struct Error(Inner); + + assert("0", Error(Inner { data: 0 })); +} + +#[test] +fn test_macro_rules() { + // Regression test for https://github.com/dtolnay/thiserror/issues/86 + + macro_rules! decl_error { + ($variant:ident($value:ident)) => { + #[derive(Debug, Error)] + pub enum Error0 { + #[error("{0:?}")] + $variant($value), + } + + #[derive(Debug, Error)] + #[error("{0:?}")] + pub enum Error1 { + $variant($value), + } + }; + } + + decl_error!(Repro(u8)); + + assert("0", Error0::Repro(0)); + assert("0", Error1::Repro(0)); +} + +#[test] +fn test_raw() { + #[derive(Error, Debug)] + #[error("braced raw error: {r#fn}")] + struct Error { + r#fn: &'static str, + } + + assert("braced raw error: T", Error { r#fn: "T" }); +} + +#[test] +fn test_raw_enum() { + #[derive(Error, Debug)] + enum Error { + #[error("braced raw error: {r#fn}")] + Braced { r#fn: &'static str }, + } + + assert("braced raw error: T", Error::Braced { r#fn: "T" }); +} + +#[test] +fn test_raw_conflict() { + #[derive(Error, Debug)] + enum Error { + #[error("braced raw error: {r#func}, {func}", func = "U")] + Braced { r#func: &'static str }, + } + + assert("braced raw error: T, U", Error::Braced { r#func: "T" }); +} + +#[test] +fn test_keyword() { + #[derive(Error, Debug)] + #[error("error: {type}", type = 1)] + struct Error; + + assert("error: 1", Error); +} + +#[test] +fn test_str_special_chars() { + #[derive(Error, Debug)] + pub enum Error { + #[error("brace left {{")] + BraceLeft, + #[error("brace left 2 \x7B\x7B")] + BraceLeft2, + #[error("brace left 3 \u{7B}\u{7B}")] + BraceLeft3, + #[error("brace right }}")] + BraceRight, + #[error("brace right 2 \x7D\x7D")] + BraceRight2, + #[error("brace right 3 \u{7D}\u{7D}")] + BraceRight3, + #[error( + "new_\ +line" + )] + NewLine, + #[error("escape24 \u{78}")] + Escape24, + } + + assert("brace left {", Error::BraceLeft); + assert("brace left 2 {", Error::BraceLeft2); + assert("brace left 3 {", Error::BraceLeft3); + assert("brace right }", Error::BraceRight); + assert("brace right 2 }", Error::BraceRight2); + assert("brace right 3 }", Error::BraceRight3); + assert("new_line", Error::NewLine); + assert("escape24 x", Error::Escape24); +} + +#[test] +fn test_raw_str() { + #[derive(Error, Debug)] + pub enum Error { + #[error(r#"raw brace left {{"#)] + BraceLeft, + #[error(r#"raw brace left 2 \x7B"#)] + BraceLeft2, + #[error(r#"raw brace right }}"#)] + BraceRight, + #[error(r#"raw brace right 2 \x7D"#)] + BraceRight2, + } + + assert(r#"raw brace left {"#, Error::BraceLeft); + assert(r#"raw brace left 2 \x7B"#, Error::BraceLeft2); + assert(r#"raw brace right }"#, Error::BraceRight); + assert(r#"raw brace right 2 \x7D"#, Error::BraceRight2); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,56 @@ +#![allow(dead_code)] + +use std::fmt::{self, Display}; +use std::io; +use thiserror::Error; + +macro_rules! unimplemented_display { + ($ty:ty) => { + impl Display for $ty { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } + } + }; +} + +#[derive(Error, Debug)] +struct BracedError { + msg: String, + pos: usize, +} + +#[derive(Error, Debug)] +struct TupleError(String, usize); + +#[derive(Error, Debug)] +struct UnitError; + +#[derive(Error, Debug)] +struct WithSource { + #[source] + cause: io::Error, +} + +#[derive(Error, Debug)] +struct WithAnyhow { + #[source] + cause: anyhow::Error, +} + +#[derive(Error, Debug)] +enum EnumError { + Braced { + #[source] + cause: io::Error, + }, + Tuple(#[source] io::Error), + Unit, +} + +unimplemented_display!(BracedError); +unimplemented_display!(TupleError); +unimplemented_display!(UnitError); +unimplemented_display!(WithSource); +unimplemented_display!(WithAnyhow); +unimplemented_display!(EnumError); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_expr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_expr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,88 @@ +#![allow(clippy::iter_cloned_collect, clippy::uninlined_format_args)] + +use std::fmt::Display; +use thiserror::Error; + +// Some of the elaborate cases from the rcc codebase, which is a C compiler in +// Rust. https://github.com/jyn514/rcc/blob/0.8.0/src/data/error.rs +#[derive(Error, Debug)] +pub enum CompilerError { + #[error("cannot shift {} by {maximum} or more bits (got {current})", if *.is_left { "left" } else { "right" })] + TooManyShiftBits { + is_left: bool, + maximum: u64, + current: u64, + }, + + #[error("#error {}", (.0).iter().copied().collect::>().join(" "))] + User(Vec<&'static str>), + + #[error("overflow while parsing {}integer literal", + if let Some(signed) = .is_signed { + if *signed { "signed "} else { "unsigned "} + } else { + "" + } + )] + IntegerOverflow { is_signed: Option }, + + #[error("overflow while parsing {}integer literal", match .is_signed { + Some(true) => "signed ", + Some(false) => "unsigned ", + None => "", + })] + IntegerOverflow2 { is_signed: Option }, +} + +// Examples drawn from Rustup. +#[derive(Error, Debug)] +pub enum RustupError { + #[error( + "toolchain '{name}' does not contain component {component}{}", + .suggestion + .as_ref() + .map_or_else(String::new, |s| format!("; did you mean '{}'?", s)), + )] + UnknownComponent { + name: String, + component: String, + suggestion: Option, + }, +} + +fn assert(expected: &str, value: T) { + assert_eq!(expected, value.to_string()); +} + +#[test] +fn test_rcc() { + assert( + "cannot shift left by 32 or more bits (got 50)", + CompilerError::TooManyShiftBits { + is_left: true, + maximum: 32, + current: 50, + }, + ); + + assert("#error A B C", CompilerError::User(vec!["A", "B", "C"])); + + assert( + "overflow while parsing signed integer literal", + CompilerError::IntegerOverflow { + is_signed: Some(true), + }, + ); +} + +#[test] +fn test_rustup() { + assert( + "toolchain 'nightly' does not contain component clipy; did you mean 'clippy'?", + RustupError::UnknownComponent { + name: "nightly".to_owned(), + component: "clipy".to_owned(), + suggestion: Some("clippy".to_owned()), + }, + ); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_from.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_from.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_from.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_from.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,64 @@ +#![allow(clippy::extra_unused_type_parameters)] + +use std::io; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorStruct { + #[from] + source: io::Error, +} + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorStructOptional { + #[from] + source: Option, +} + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorTuple(#[from] io::Error); + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorTupleOptional(#[from] Option); + +#[derive(Error, Debug)] +#[error("...")] +pub enum ErrorEnum { + Test { + #[from] + source: io::Error, + }, +} + +#[derive(Error, Debug)] +#[error("...")] +pub enum ErrorEnumOptional { + Test { + #[from] + source: Option, + }, +} + +#[derive(Error, Debug)] +#[error("...")] +pub enum Many { + Any(#[from] anyhow::Error), + Io(#[from] io::Error), +} + +fn assert_impl>() {} + +#[test] +fn test_from() { + assert_impl::(); + assert_impl::(); + assert_impl::(); + assert_impl::(); + assert_impl::(); + assert_impl::(); + assert_impl::(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_generics.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_generics.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_generics.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_generics.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,161 @@ +#![allow(clippy::needless_late_init, clippy::uninlined_format_args)] + +use std::fmt::{self, Debug, Display}; +use thiserror::Error; + +pub struct NoFormat; + +#[derive(Debug)] +pub struct DebugOnly; + +pub struct DisplayOnly; + +impl Display for DisplayOnly { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("display only") + } +} + +#[derive(Debug)] +pub struct DebugAndDisplay; + +impl Display for DebugAndDisplay { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("debug and display") + } +} + +// Should expand to: +// +// impl Display for EnumDebugField +// where +// E: Debug; +// +// impl Error for EnumDebugField +// where +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub enum EnumDebugGeneric { + #[error("{0:?}")] + FatalError(E), +} + +// Should expand to: +// +// impl Display for EnumFromGeneric; +// +// impl Error for EnumFromGeneric +// where +// EnumDebugGeneric: Error + 'static, +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub enum EnumFromGeneric { + #[error("enum from generic")] + Source(#[from] EnumDebugGeneric), +} + +// Should expand to: +// +// impl Display +// for EnumCompound +// where +// HasDisplay: Display, +// HasDebug: Debug; +// +// impl Error +// for EnumCompound +// where +// Self: Debug + Display; +// +#[derive(Error)] +pub enum EnumCompound { + #[error("{0} {1:?}")] + DisplayDebug(HasDisplay, HasDebug), + #[error("{0}")] + Display(HasDisplay, HasNeither), + #[error("{1:?}")] + Debug(HasNeither, HasDebug), +} + +impl Debug for EnumCompound { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("EnumCompound") + } +} + +#[test] +fn test_display_enum_compound() { + let mut instance: EnumCompound; + + instance = EnumCompound::DisplayDebug(DisplayOnly, DebugOnly); + assert_eq!(format!("{}", instance), "display only DebugOnly"); + + instance = EnumCompound::Display(DisplayOnly, NoFormat); + assert_eq!(format!("{}", instance), "display only"); + + instance = EnumCompound::Debug(NoFormat, DebugOnly); + assert_eq!(format!("{}", instance), "DebugOnly"); +} + +// Should expand to: +// +// impl Display for EnumTransparentGeneric +// where +// E: Display; +// +// impl Error for EnumTransparentGeneric +// where +// E: Error, +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub enum EnumTransparentGeneric { + #[error(transparent)] + Other(E), +} + +// Should expand to: +// +// impl Display for StructDebugGeneric +// where +// E: Debug; +// +// impl Error for StructDebugGeneric +// where +// Self: Debug + Display; +// +#[derive(Error, Debug)] +#[error("{underlying:?}")] +pub struct StructDebugGeneric { + pub underlying: E, +} + +// Should expand to: +// +// impl Error for StructFromGeneric +// where +// StructDebugGeneric: Error + 'static, +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub struct StructFromGeneric { + #[from] + pub source: StructDebugGeneric, +} + +// Should expand to: +// +// impl Display for StructTransparentGeneric +// where +// E: Display; +// +// impl Error for StructTransparentGeneric +// where +// E: Error, +// Self: Debug + Display; +// +#[derive(Error, Debug)] +#[error(transparent)] +pub struct StructTransparentGeneric(E); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_lints.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_lints.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_lints.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_lints.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +#![allow(clippy::mixed_attributes_style)] + +use thiserror::Error; + +pub use std::error::Error; + +#[test] +fn test_unused_qualifications() { + #![deny(unused_qualifications)] + + // Expansion of derive(Error) macro can't know whether something like + // std::error::Error is already imported in the caller's scope so it must + // suppress unused_qualifications. + + #[derive(Debug, Error)] + #[error("...")] + pub struct MyError; + + let _: MyError; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_option.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_option.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_option.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_option.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,105 @@ +#![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] + +#[cfg(thiserror_nightly_testing)] +pub mod structs { + use std::backtrace::Backtrace; + use thiserror::Error; + + #[derive(Error, Debug)] + #[error("...")] + pub struct OptSourceNoBacktrace { + #[source] + source: Option, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct OptSourceAlwaysBacktrace { + #[source] + source: Option, + backtrace: Backtrace, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct NoSourceOptBacktrace { + #[backtrace] + backtrace: Option, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct AlwaysSourceOptBacktrace { + source: anyhow::Error, + #[backtrace] + backtrace: Option, + } + + #[derive(Error, Debug)] + #[error("...")] + pub struct OptSourceOptBacktrace { + #[source] + source: Option, + #[backtrace] + backtrace: Option, + } +} + +#[cfg(thiserror_nightly_testing)] +pub mod enums { + use std::backtrace::Backtrace; + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum OptSourceNoBacktrace { + #[error("...")] + Test { + #[source] + source: Option, + }, + } + + #[derive(Error, Debug)] + pub enum OptSourceAlwaysBacktrace { + #[error("...")] + Test { + #[source] + source: Option, + backtrace: Backtrace, + }, + } + + #[derive(Error, Debug)] + pub enum NoSourceOptBacktrace { + #[error("...")] + Test { + #[backtrace] + backtrace: Option, + }, + } + + #[derive(Error, Debug)] + pub enum AlwaysSourceOptBacktrace { + #[error("...")] + Test { + source: anyhow::Error, + #[backtrace] + backtrace: Option, + }, + } + + #[derive(Error, Debug)] + pub enum OptSourceOptBacktrace { + #[error("...")] + Test { + #[source] + source: Option, + #[backtrace] + backtrace: Option, + }, + } +} + +#[test] +#[cfg_attr(not(thiserror_nightly_testing), ignore)] +fn test_option() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_path.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_path.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_path.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_path.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,37 @@ +use ref_cast::RefCast; +use std::fmt::Display; +use std::path::{Path, PathBuf}; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("failed to read '{file}'")] +struct StructPathBuf { + file: PathBuf, +} + +#[derive(Error, Debug, RefCast)] +#[repr(C)] +#[error("failed to read '{file}'")] +struct StructPath { + file: Path, +} + +#[derive(Error, Debug)] +enum EnumPathBuf { + #[error("failed to read '{0}'")] + Read(PathBuf), +} + +fn assert(expected: &str, value: T) { + assert_eq!(expected, value.to_string()); +} + +#[test] +fn test_display() { + let path = Path::new("/thiserror"); + let file = path.to_owned(); + assert("failed to read '/thiserror'", StructPathBuf { file }); + let file = path.to_owned(); + assert("failed to read '/thiserror'", EnumPathBuf::Read(file)); + assert("failed to read '/thiserror'", StructPath::ref_cast(path)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +use std::error::Error as StdError; +use std::io; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("implicit source")] +pub struct ImplicitSource { + source: io::Error, +} + +#[derive(Error, Debug)] +#[error("explicit source")] +pub struct ExplicitSource { + source: String, + #[source] + io: io::Error, +} + +#[derive(Error, Debug)] +#[error("boxed source")] +pub struct BoxedSource { + #[source] + source: Box, +} + +#[test] +fn test_implicit_source() { + let io = io::Error::new(io::ErrorKind::Other, "oh no!"); + let error = ImplicitSource { source: io }; + error.source().unwrap().downcast_ref::().unwrap(); +} + +#[test] +fn test_explicit_source() { + let io = io::Error::new(io::ErrorKind::Other, "oh no!"); + let error = ExplicitSource { + source: String::new(), + io, + }; + error.source().unwrap().downcast_ref::().unwrap(); +} + +#[test] +fn test_boxed_source() { + let source = Box::new(io::Error::new(io::ErrorKind::Other, "oh no!")); + let error = BoxedSource { source }; + error.source().unwrap().downcast_ref::().unwrap(); +} + +macro_rules! error_from_macro { + ($($variants:tt)*) => { + #[derive(Error)] + #[derive(Debug)] + pub enum MacroSource { + $($variants)* + } + } +} + +// Test that we generate impls with the proper hygiene +#[rustfmt::skip] +error_from_macro! { + #[error("Something")] + Variant(#[from] io::Error) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_transparent.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/test_transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,78 @@ +use anyhow::anyhow; +use std::error::Error as _; +use std::io; +use thiserror::Error; + +#[test] +fn test_transparent_struct() { + #[derive(Error, Debug)] + #[error(transparent)] + struct Error(ErrorKind); + + #[derive(Error, Debug)] + enum ErrorKind { + #[error("E0")] + E0, + #[error("E1")] + E1(#[from] io::Error), + } + + let error = Error(ErrorKind::E0); + assert_eq!("E0", error.to_string()); + assert!(error.source().is_none()); + + let io = io::Error::new(io::ErrorKind::Other, "oh no!"); + let error = Error(ErrorKind::from(io)); + assert_eq!("E1", error.to_string()); + error.source().unwrap().downcast_ref::().unwrap(); +} + +#[test] +fn test_transparent_enum() { + #[derive(Error, Debug)] + enum Error { + #[error("this failed")] + This, + #[error(transparent)] + Other(anyhow::Error), + } + + let error = Error::This; + assert_eq!("this failed", error.to_string()); + + let error = Error::Other(anyhow!("inner").context("outer")); + assert_eq!("outer", error.to_string()); + assert_eq!("inner", error.source().unwrap().to_string()); +} + +#[test] +fn test_anyhow() { + #[derive(Error, Debug)] + #[error(transparent)] + struct Any(#[from] anyhow::Error); + + let error = Any::from(anyhow!("inner").context("outer")); + assert_eq!("outer", error.to_string()); + assert_eq!("inner", error.source().unwrap().to_string()); +} + +#[test] +fn test_non_static() { + #[derive(Error, Debug)] + #[error(transparent)] + struct Error<'a> { + inner: ErrorKind<'a>, + } + + #[derive(Error, Debug)] + enum ErrorKind<'a> { + #[error("unexpected token: {:?}", token)] + Unexpected { token: &'a str }, + } + + let error = Error { + inner: ErrorKind::Unexpected { token: "error" }, + }; + assert_eq!("unexpected token: \"error\"", error.to_string()); + assert!(error.source().is_none()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error(#[error(transparent)] std::io::Error); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/bad-field-attr.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: #[error(transparent)] needs to go outside the enum or struct, not on an individual field + --> tests/ui/bad-field-attr.rs:5:18 + | +5 | pub struct Error(#[error(transparent)] std::io::Error); + | ^^^^^^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +use thiserror::Error; + +macro_rules! error_type { + ($name:ident, $what:expr) => { + // Use #[error("invalid {}", $what)] instead. + + #[derive(Error, Debug)] + #[error(concat!("invalid ", $what))] + pub struct $name; + }; +} + +error_type!(Error, "foo"); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/concat-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +error: expected string literal + --> tests/ui/concat-display.rs:8:17 + | +8 | #[error(concat!("invalid ", $what))] + | ^^^^^^ +... +13 | error_type!(Error, "foo"); + | ------------------------- in this macro invocation + | + = note: this error originates in the macro `error_type` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ErrorEnum { + Confusing { + #[source] + a: std::io::Error, + #[source] + b: anyhow::Error, + }, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-enum-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: duplicate #[source] attribute + --> tests/ui/duplicate-enum-source.rs:8:9 + | +8 | #[source] + | ^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("...")] +#[error("...")] +pub struct Error; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-fmt.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: only one #[error(...)] attribute is allowed + --> tests/ui/duplicate-fmt.rs:5:1 + | +5 | #[error("...")] + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub struct ErrorStruct { + #[source] + a: std::io::Error, + #[source] + b: anyhow::Error, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-struct-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: duplicate #[source] attribute + --> tests/ui/duplicate-struct-source.rs:7:5 + | +7 | #[source] + | ^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +#[error(transparent)] +pub struct Error(anyhow::Error); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/duplicate-transparent.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: duplicate #[error(transparent)] attribute + --> tests/ui/duplicate-transparent.rs:5:1 + | +5 | #[error(transparent)] + | ^^^^^^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,14 @@ +use std::fmt::{self, Display}; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error] +pub struct MyError; + +impl Display for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/fallback-impl-with-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,16 @@ +error: expected attribute arguments in parentheses: #[error(...)] + --> tests/ui/fallback-impl-with-display.rs:5:3 + | +5 | #[error] + | ^^^^^ + +error[E0119]: conflicting implementations of trait `std::fmt::Display` for type `MyError` + --> tests/ui/fallback-impl-with-display.rs:4:10 + | +4 | #[derive(Error, Debug)] + | ^^^^^ conflicting implementation for `MyError` +... +8 | impl Display for MyError { + | ------------------------ first implementation here + | + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +// https://github.com/dtolnay/thiserror/issues/163 + +use std::backtrace::Backtrace; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("...")] +pub struct Error( + #[from] + #[backtrace] + std::io::Error, + Backtrace, +); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-backtrace-backtrace.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: deriving From requires no fields other than source and backtrace + --> tests/ui/from-backtrace-backtrace.rs:9:5 + | +9 | #[from] + | ^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub struct Error { + #[source] + source: std::io::Error, + #[from] + other: anyhow::Error, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/from-not-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: #[from] is only supported on the source field, not any other field + --> tests/ui/from-not-source.rs:7:5 + | +7 | #[from] + | ^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error] +pub struct MyError; + +fn main() { + // No error on the following line. Thiserror emits an Error impl despite the + // bad attribute. + _ = &MyError as &dyn std::error::Error; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/invalid-input-impl-anyway.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: expected attribute arguments in parentheses: #[error(...)] + --> tests/ui/invalid-input-impl-anyway.rs:4:3 + | +4 | #[error] + | ^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +use std::fmt::Debug; +use thiserror::Error; + +#[derive(Error, Debug)] +#[error("error")] +struct Error<'a>(#[from] Inner<'a>); + +#[derive(Error, Debug)] +#[error("{0}")] +struct Inner<'a>(&'a str); + +#[derive(Error, Debug)] +enum Enum<'a> { + #[error("error")] + Foo(#[from] Generic<&'a str>), +} + +#[derive(Error, Debug)] +#[error("{0:?}")] +struct Generic(T); + +fn main() -> Result<(), Error<'static>> { + Err(Error(Inner("some text"))) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/lifetime.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +error: non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static + --> tests/ui/lifetime.rs:6:26 + | +6 | struct Error<'a>(#[from] Inner<'a>); + | ^^^^^^^^^ + +error: non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static + --> tests/ui/lifetime.rs:15:17 + | +15 | Foo(#[from] Generic<&'a str>), + | ^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum MyError { + First, + Second, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,13 @@ +error[E0277]: `MyError` doesn't implement `std::fmt::Display` + --> tests/ui/missing-display.rs:4:10 + | +4 | pub enum MyError { + | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `MyError` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `std::error::Error` + --> $RUST/core/src/error.rs + | + | pub trait Error: Debug + Display { + | ^^^^^^^ required by this bound in `Error` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("...")] + A(usize), + B(usize), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/missing-fmt.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: missing #[error("...")] display attribute + --> tests/ui/missing-fmt.rs:7:5 + | +7 | B(usize), + | ^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use thiserror::Error; + +#[derive(Debug)] +struct NoDisplay; + +#[derive(Error, Debug)] +#[error("thread: {thread}")] +pub struct Error { + thread: NoDisplay, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/no-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0599]: the method `as_display` exists for reference `&NoDisplay`, but its trait bounds were not satisfied + --> tests/ui/no-display.rs:7:9 + | +4 | struct NoDisplay; + | ---------------- doesn't satisfy `NoDisplay: std::fmt::Display` +... +7 | #[error("thread: {thread}")] + | ^^^^^^^^^^^^^^^^^^ method cannot be called on `&NoDisplay` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NoDisplay: std::fmt::Display` + which is required by `&NoDisplay: AsDisplay<'_>` +note: the trait `std::fmt::Display` must be implemented + --> $RUST/core/src/fmt/mod.rs + | + | pub trait Display { + | ^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_display`, perhaps you need to implement it: + candidate #1: `AsDisplay` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use thiserror::Error; + +#[derive(Debug)] +pub struct NotError; + +#[derive(Error, Debug)] +#[error("...")] +pub enum ErrorEnum { + Broken { source: NotError }, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but its trait bounds were not satisfied + --> tests/ui/source-enum-not-error.rs:9:14 + | +4 | pub struct NotError; + | ------------------- doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` +... +9 | Broken { source: NotError }, + | ^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NotError: std::error::Error` + which is required by `NotError: AsDynError<'_>` + `&NotError: std::error::Error` + which is required by `&NotError: AsDynError<'_>` +note: the trait `std::error::Error` must be implemented + --> $RUST/core/src/error.rs + | + | pub trait Error: Debug + Display { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: + candidate #1: `AsDynError` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use thiserror::Error; + +#[derive(Debug)] +pub struct NotError; + +#[derive(Error, Debug)] +#[error("...")] +pub enum ErrorEnum { + Broken(#[source] NotError), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-enum-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,22 @@ +error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but its trait bounds were not satisfied + --> tests/ui/source-enum-unnamed-field-not-error.rs:9:14 + | +4 | pub struct NotError; + | ------------------- doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` +... +9 | Broken(#[source] NotError), + | ^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NotError: std::error::Error` + which is required by `NotError: AsDynError<'_>` + `&NotError: std::error::Error` + which is required by `&NotError: AsDynError<'_>` +note: the trait `std::error::Error` must be implemented + --> $RUST/core/src/error.rs + | + | pub trait Error: Debug + Display { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: + candidate #1: `AsDynError` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,12 @@ +use thiserror::Error; + +#[derive(Debug)] +struct NotError; + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorStruct { + source: NotError, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its trait bounds were not satisfied + --> tests/ui/source-struct-not-error.rs:9:5 + | +4 | struct NotError; + | --------------- method `as_dyn_error` not found for this struct because it doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` +... +9 | source: NotError, + | ^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NotError: std::error::Error` + which is required by `NotError: AsDynError<'_>` +note: the trait `std::error::Error` must be implemented + --> $RUST/core/src/error.rs + | + | pub trait Error: Debug + Display { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: + candidate #1: `AsDynError` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +use thiserror::Error; + +#[derive(Debug)] +struct NotError; + +#[derive(Error, Debug)] +#[error("...")] +pub struct ErrorStruct(#[source] NotError); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/source-struct-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its trait bounds were not satisfied + --> tests/ui/source-struct-unnamed-field-not-error.rs:8:26 + | +4 | struct NotError; + | --------------- method `as_dyn_error` not found for this struct because it doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` +... +8 | pub struct ErrorStruct(#[source] NotError); + | ^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NotError: std::error::Error` + which is required by `NotError: AsDynError<'_>` +note: the trait `std::error::Error` must be implemented + --> $RUST/core/src/error.rs + | + | pub trait Error: Debug + Display { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: + candidate #1: `AsDynError` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +#[error("...")] +pub struct Error(anyhow::Error); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-display.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: cannot have both #[error(transparent)] and a display attribute + --> tests/ui/transparent-display.rs:5:1 + | +5 | #[error("...")] + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + Other(anyhow::Error, String), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-many.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +error: #[error(transparent)] requires exactly one field + --> tests/ui/transparent-enum-many.rs:5:5 + | +5 | / #[error(transparent)] +6 | | Other(anyhow::Error, String), + | |________________________________^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + Other { message: String }, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0599]: the method `as_dyn_error` exists for reference `&String`, but its trait bounds were not satisfied + --> tests/ui/transparent-enum-not-error.rs:5:13 + | +5 | #[error(transparent)] + | ^^^^^^^^^^^ method cannot be called on `&String` due to unsatisfied trait bounds + | + ::: $RUST/alloc/src/string.rs + | + | pub struct String { + | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` + | + = note: the following trait bounds were not satisfied: + `String: std::error::Error` + which is required by `String: AsDynError<'_>` + `&String: std::error::Error` + which is required by `&String: AsDynError<'_>` + `str: Sized` + which is required by `str: AsDynError<'_>` + `str: std::error::Error` + which is required by `str: AsDynError<'_>` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + Other(#[source] anyhow::Error), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: transparent variant can't contain #[source] + --> tests/ui/transparent-enum-source.rs:6:11 + | +6 | Other(#[source] anyhow::Error), + | ^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + Other(String), +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-enum-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +error[E0599]: the method `as_dyn_error` exists for reference `&String`, but its trait bounds were not satisfied + --> tests/ui/transparent-enum-unnamed-field-not-error.rs:5:13 + | +5 | #[error(transparent)] + | ^^^^^^^^^^^ method cannot be called on `&String` due to unsatisfied trait bounds + | + ::: $RUST/alloc/src/string.rs + | + | pub struct String { + | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` + | + = note: the following trait bounds were not satisfied: + `String: std::error::Error` + which is required by `String: AsDynError<'_>` + `&String: std::error::Error` + which is required by `&String: AsDynError<'_>` + `str: Sized` + which is required by `str: AsDynError<'_>` + `str: std::error::Error` + which is required by `str: AsDynError<'_>` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error { + inner: anyhow::Error, + what: String, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-many.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: #[error(transparent)] requires exactly one field + --> tests/ui/transparent-struct-many.rs:4:1 + | +4 | #[error(transparent)] + | ^^^^^^^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error { + message: String, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +error[E0599]: the method `as_dyn_error` exists for struct `String`, but its trait bounds were not satisfied + --> tests/ui/transparent-struct-not-error.rs:4:9 + | +4 | #[error(transparent)] + | ^^^^^^^^^^^ method cannot be called on `String` due to unsatisfied trait bounds + | + ::: $RUST/alloc/src/string.rs + | + | pub struct String { + | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` + | + = note: the following trait bounds were not satisfied: + `String: std::error::Error` + which is required by `String: AsDynError<'_>` + `str: Sized` + which is required by `str: AsDynError<'_>` + `str: std::error::Error` + which is required by `str: AsDynError<'_>` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error(#[source] anyhow::Error); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: transparent error struct can't contain #[source] + --> tests/ui/transparent-struct-source.rs:5:18 + | +5 | pub struct Error(#[source] anyhow::Error); + | ^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error(String); + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/transparent-struct-unnamed-field-not-error.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,18 @@ +error[E0599]: the method `as_dyn_error` exists for struct `String`, but its trait bounds were not satisfied + --> tests/ui/transparent-struct-unnamed-field-not-error.rs:4:9 + | +4 | #[error(transparent)] + | ^^^^^^^^^^^ method cannot be called on `String` due to unsatisfied trait bounds + | + ::: $RUST/alloc/src/string.rs + | + | pub struct String { + | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` + | + = note: the following trait bounds were not satisfied: + `String: std::error::Error` + which is required by `String: AsDynError<'_>` + `str: Sized` + which is required by `str: AsDynError<'_>` + `str: std::error::Error` + which is required by `str: AsDynError<'_>` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + What { + #[error("...")] + io: std::io::Error, + }, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-field-fmt.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant + --> tests/ui/unexpected-field-fmt.rs:6:9 + | +6 | #[error("...")] + | ^^^^^^^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +#[source] +pub struct Error; + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/unexpected-struct-source.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,5 @@ +error: not expected here; the #[source] attribute belongs on a specific field + --> tests/ui/unexpected-struct-source.rs:4:1 + | +4 | #[source] + | ^^^^^^^^^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,9 @@ +use thiserror::Error; + +#[derive(Error)] +pub union U { + msg: &'static str, + num: usize, +} + +fn main() {} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.stderr clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.stderr --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.stderr 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-1.0.59/tests/ui/union.stderr 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,8 @@ +error: union as errors are not supported + --> tests/ui/union.rs:4:1 + | +4 | / pub union U { +5 | | msg: &'static str, +6 | | num: usize, +7 | | } + | |_^ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"27f9696d64a97df170dc620366a6b6b0b162917a686511e6b878586b04846226","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"9b6cd6b1553483c99cd7e36aa422d37f4353c99b15da55534d28822f7fa7fd08","src/attr.rs":"99fca8c65a1907ee2f43f7ec28ce465bae22336c529bd7148738f9ce35375101","src/expand.rs":"2736a714372a4b81ac5438783dd2c0f656d624bec5cc4089af96ceecaeee011e","src/fmt.rs":"5d1cefc012403c2d4ff7ab2513c0ec559166df4271d5983a6463939b5ec8c3e1","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"5eea86c771e643328ad9bc3b881cce4bf9d50adae1b33e0d07645bdd9044003d","src/prop.rs":"5ba613e38430831259f20b258f33d57dcb783fbaeeb49e5faffa7b2a7be99e67","src/span.rs":"430460a4fa0d1fa9c627c1ddd575d2b101778fea84217591e1a93a5f6a2a0132","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"78a15909a6c73b0af1e41dbf57e007c84bfb04a42d319f0ed2768dd4b83d205f","Cargo.lock":"57f029938625a1b8f5367b0e77b7ba597f247a9e4e4434798877abc53abf85b3","Cargo.toml":"3fd47a39039f0e24b89690ec5d097ecad3cdce8640098080ae81c7ab005f9a36","Cargo.toml.orig":"17bba3282cbf8720d12d993fa0e97bf9eeb661354e02f1a8c0accb7461219437","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"c717fffeb2923b2840d58fd02923a1926a48fa8336039f57a9e94f9275ae7ec6","src/attr.rs":"d3c7fa9e8269973f140e5382f753664ac32bee44c09875f678100b890aea4d06","src/expand.rs":"adb4f42d79ce5996f8b8279e538ecccfda8e67b6e99a36560ad004fa2bcba118","src/fallback.rs":"b862dac9c70af839654287dfbd7612f1241249fde9251d01921ecede078e6cc0","src/fmt.rs":"64cee5b33e78b7e56adb583b682cea38bc88e739ddb48159ca2853a9113dac85","src/generics.rs":"03134b3882790f657a11700e5fb0b0ca744214a47d609febaabc14926d2d7e03","src/lib.rs":"ad95309747aaba0883cd6823d6555982a2aca055b355134f87a26c031b7f8d5e","src/prop.rs":"82fb29bd85b0e1163c32dca2ff874e1dfbece7f681b986c6fe618f29e34bdd26","src/scan_expr.rs":"d46ae7a3eaaa6476553db3164676ec71aa82bcd8a2e4cad59deb07893c79f1c8","src/unraw.rs":"d4ee6048f7722160c3d61f69378d2c8d17068a319a8e6a33c6f25ea673e88312","src/valid.rs":"5a4e781773cc9a2f3129f620fa4f201f71fd3265b8315ca138239bec3bf618fb"},"package":"3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "72ae716e6d6a7f7fdabdc394018c745b4d39ca45" + }, + "path_in_vcs": "impl" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,19 +11,35 @@ [package] edition = "2021" -rust-version = "1.56" +rust-version = "1.61" name = "thiserror-impl" -version = "1.0.59" +version = "2.0.17" authors = ["David Tolnay "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Implementation detail of the `thiserror` crate" +readme = false license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/thiserror" [package.metadata.docs.rs] -rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", +] [lib] +name = "thiserror_impl" +path = "src/lib.rs" proc-macro = true [dependencies.proc-macro2] @@ -33,4 +49,4 @@ version = "1.0.35" [dependencies.syn] -version = "2.0.46" +version = "2.0.87" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "thiserror-impl" +version = "2.0.17" +authors = ["David Tolnay "] +description = "Implementation detail of the `thiserror` crate" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" +rust-version = "1.61" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = "2.0.87" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/ast.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/ast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/ast.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/ast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,10 @@ use crate::attr::{self, Attrs}; use crate::generics::ParamsInScope; +use crate::unraw::{IdentUnraw, MemberUnraw}; use proc_macro2::Span; +use std::fmt::{self, Display}; use syn::{ - Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result, - Type, + Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type, }; pub enum Input<'a> { @@ -35,11 +36,21 @@ pub struct Field<'a> { pub original: &'a syn::Field, pub attrs: Attrs<'a>, - pub member: Member, + pub member: MemberUnraw, pub ty: &'a Type, pub contains_generic: bool, } +#[derive(Copy, Clone)] +pub enum ContainerKind { + Struct, + TupleStruct, + UnitStruct, + StructVariant, + TupleVariant, + UnitVariant, +} + impl<'a> Input<'a> { pub fn from_syn(node: &'a DeriveInput) -> Result { match &node.data { @@ -57,10 +68,10 @@ fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result { let mut attrs = attr::get(&node.attrs)?; let scope = ParamsInScope::new(&node.generics); - let span = attrs.span().unwrap_or_else(Span::call_site); - let fields = Field::multiple_from_syn(&data.fields, &scope, span)?; + let fields = Field::multiple_from_syn(&data.fields, &scope)?; if let Some(display) = &mut attrs.display { - display.expand_shorthand(&fields); + let container = ContainerKind::from_struct(data); + display.expand_shorthand(&fields, container)?; } Ok(Struct { attrs, @@ -75,19 +86,22 @@ fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result { let attrs = attr::get(&node.attrs)?; let scope = ParamsInScope::new(&node.generics); - let span = attrs.span().unwrap_or_else(Span::call_site); let variants = data .variants .iter() .map(|node| { - let mut variant = Variant::from_syn(node, &scope, span)?; - if let display @ None = &mut variant.attrs.display { - display.clone_from(&attrs.display); + let mut variant = Variant::from_syn(node, &scope)?; + if variant.attrs.display.is_none() + && variant.attrs.transparent.is_none() + && variant.attrs.fmt.is_none() + { + variant.attrs.display.clone_from(&attrs.display); + variant.attrs.transparent = attrs.transparent; + variant.attrs.fmt.clone_from(&attrs.fmt); } if let Some(display) = &mut variant.attrs.display { - display.expand_shorthand(&variant.fields); - } else if variant.attrs.transparent.is_none() { - variant.attrs.transparent = attrs.transparent; + let container = ContainerKind::from_variant(node); + display.expand_shorthand(&variant.fields, container)?; } Ok(variant) }) @@ -102,60 +116,70 @@ } impl<'a> Variant<'a> { - fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result { + fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result { let attrs = attr::get(&node.attrs)?; - let span = attrs.span().unwrap_or(span); Ok(Variant { original: node, attrs, ident: node.ident.clone(), - fields: Field::multiple_from_syn(&node.fields, scope, span)?, + fields: Field::multiple_from_syn(&node.fields, scope)?, }) } } impl<'a> Field<'a> { - fn multiple_from_syn( - fields: &'a Fields, - scope: &ParamsInScope<'a>, - span: Span, - ) -> Result> { + fn multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result> { fields .iter() .enumerate() - .map(|(i, field)| Field::from_syn(i, field, scope, span)) + .map(|(i, field)| Field::from_syn(i, field, scope)) .collect() } - fn from_syn( - i: usize, - node: &'a syn::Field, - scope: &ParamsInScope<'a>, - span: Span, - ) -> Result { + fn from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result { Ok(Field { original: node, attrs: attr::get(&node.attrs)?, - member: node.ident.clone().map(Member::Named).unwrap_or_else(|| { - Member::Unnamed(Index { + member: match &node.ident { + Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())), + None => MemberUnraw::Unnamed(Index { index: i as u32, - span, - }) - }), + span: Span::call_site(), + }), + }, ty: &node.ty, contains_generic: scope.intersects(&node.ty), }) } } -impl Attrs<'_> { - pub fn span(&self) -> Option { - if let Some(display) = &self.display { - Some(display.fmt.span()) - } else if let Some(transparent) = &self.transparent { - Some(transparent.span) - } else { - None +impl ContainerKind { + fn from_struct(node: &DataStruct) -> Self { + match node.fields { + Fields::Named(_) => ContainerKind::Struct, + Fields::Unnamed(_) => ContainerKind::TupleStruct, + Fields::Unit => ContainerKind::UnitStruct, } } + + fn from_variant(node: &syn::Variant) -> Self { + match node.fields { + Fields::Named(_) => ContainerKind::StructVariant, + Fields::Unnamed(_) => ContainerKind::TupleVariant, + Fields::Unit => ContainerKind::UnitVariant, + } + } +} + +impl Display for ContainerKind { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(match self { + ContainerKind::Struct => "struct", + ContainerKind::TupleStruct => "tuple struct", + ContainerKind::UnitStruct => "unit struct", + ContainerKind::StructVariant => "struct variant", + ContainerKind::TupleVariant => "tuple variant", + ContainerKind::UnitVariant => "unit variant", + }) + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/attr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/attr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/attr.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/attr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,20 @@ -use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; -use quote::{format_ident, quote, ToTokens}; +use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use quote::{format_ident, quote, quote_spanned, ToTokens}; use std::collections::BTreeSet as Set; use syn::parse::discouraged::Speculative; -use syn::parse::ParseStream; +use syn::parse::{End, ParseStream}; use syn::{ - braced, bracketed, parenthesized, token, Attribute, Error, Ident, Index, LitInt, LitStr, Meta, - Result, Token, + braced, bracketed, parenthesized, token, Attribute, Error, ExprPath, Ident, Index, LitFloat, + LitInt, LitStr, Meta, Result, Token, }; pub struct Attrs<'a> { pub display: Option>, - pub source: Option<&'a Attribute>, + pub source: Option>, pub backtrace: Option<&'a Attribute>, - pub from: Option<&'a Attribute>, + pub from: Option>, pub transparent: Option>, + pub fmt: Option>, } #[derive(Clone)] @@ -23,7 +24,21 @@ pub args: TokenStream, pub requires_fmt_machinery: bool, pub has_bonus_display: bool, + pub infinite_recursive: bool, pub implied_bounds: Set<(usize, Trait)>, + pub bindings: Vec<(Ident, TokenStream)>, +} + +#[derive(Copy, Clone)] +pub struct Source<'a> { + pub original: &'a Attribute, + pub span: Span, +} + +#[derive(Copy, Clone)] +pub struct From<'a> { + pub original: &'a Attribute, + pub span: Span, } #[derive(Copy, Clone)] @@ -32,6 +47,12 @@ pub span: Span, } +#[derive(Clone)] +pub struct Fmt<'a> { + pub original: &'a Attribute, + pub path: ExprPath, +} + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] pub enum Trait { Debug, @@ -52,6 +73,7 @@ backtrace: None, from: None, transparent: None, + fmt: None, }; for attr in input { @@ -62,7 +84,13 @@ if attrs.source.is_some() { return Err(Error::new_spanned(attr, "duplicate #[source] attribute")); } - attrs.source = Some(attr); + let span = (attr.pound_token.span) + .join(attr.bracket_token.span.join()) + .unwrap_or(attr.path().get_ident().unwrap().span()); + attrs.source = Some(Source { + original: attr, + span, + }); } else if attr.path().is_ident("backtrace") { attr.meta.require_path_only()?; if attrs.backtrace.is_some() { @@ -80,7 +108,13 @@ if attrs.from.is_some() { return Err(Error::new_spanned(attr, "duplicate #[from] attribute")); } - attrs.from = Some(attr); + let span = (attr.pound_token.span) + .join(attr.bracket_token.span.join()) + .unwrap_or(attr.path().get_ident().unwrap().span()); + attrs.from = Some(From { + original: attr, + span, + }); } } @@ -88,10 +122,17 @@ } fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> { - syn::custom_keyword!(transparent); + mod kw { + syn::custom_keyword!(transparent); + syn::custom_keyword!(fmt); + } attr.parse_args_with(|input: ParseStream| { - if let Some(kw) = input.parse::>()? { + let lookahead = input.lookahead1(); + let fmt = if lookahead.peek(LitStr) { + input.parse::()? + } else if lookahead.peek(kw::transparent) { + let kw: kw::transparent = input.parse()?; if attrs.transparent.is_some() { return Err(Error::new_spanned( attr, @@ -103,14 +144,27 @@ span: kw.span, }); return Ok(()); - } - - let fmt: LitStr = input.parse()?; + } else if lookahead.peek(kw::fmt) { + input.parse::()?; + input.parse::()?; + let path: ExprPath = input.parse()?; + if attrs.fmt.is_some() { + return Err(Error::new_spanned( + attr, + "duplicate #[error(fmt = ...)] attribute", + )); + } + attrs.fmt = Some(Fmt { + original: attr, + path, + }); + return Ok(()); + } else { + return Err(lookahead.error()); + }; - let ahead = input.fork(); - ahead.parse::>()?; - let args = if ahead.is_empty() { - input.advance_to(&ahead); + let args = if input.is_empty() || input.peek(Token![,]) && input.peek2(End) { + input.parse::>()?; TokenStream::new() } else { parse_token_expr(input, false)? @@ -124,7 +178,9 @@ args, requires_fmt_machinery, has_bonus_display: false, + infinite_recursive: false, implied_bounds: Set::new(), + bindings: Vec::new(), }; if attrs.display.is_some() { return Err(Error::new_spanned( @@ -140,19 +196,54 @@ fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result { let mut tokens = Vec::new(); while !input.is_empty() { + if input.peek(token::Group) { + let group: TokenTree = input.parse()?; + tokens.push(group); + begin_expr = false; + continue; + } + if begin_expr && input.peek(Token![.]) { if input.peek2(Ident) { input.parse::()?; begin_expr = false; continue; - } - if input.peek2(LitInt) { + } else if input.peek2(LitInt) { input.parse::()?; let int: Index = input.parse()?; - let ident = format_ident!("_{}", int.index, span = int.span); - tokens.push(TokenTree::Ident(ident)); + tokens.push({ + let ident = format_ident!("_{}", int.index, span = int.span); + TokenTree::Ident(ident) + }); begin_expr = false; continue; + } else if input.peek2(LitFloat) { + let ahead = input.fork(); + ahead.parse::()?; + let float: LitFloat = ahead.parse()?; + let repr = float.to_string(); + let mut indices = repr.split('.').map(syn::parse_str::); + if let (Some(Ok(first)), Some(Ok(second)), None) = + (indices.next(), indices.next(), indices.next()) + { + input.advance_to(&ahead); + tokens.push({ + let ident = format_ident!("_{}", first, span = float.span()); + TokenTree::Ident(ident) + }); + tokens.push({ + let mut punct = Punct::new('.', Spacing::Alone); + punct.set_span(float.span()); + TokenTree::Punct(punct) + }); + tokens.push({ + let mut literal = Literal::u32_unsuffixed(second.index); + literal.set_span(float.span()); + TokenTree::Literal(literal) + }); + begin_expr = false; + continue; + } } } @@ -210,13 +301,21 @@ impl ToTokens for Display<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { + if self.infinite_recursive { + let span = self.fmt.span(); + tokens.extend(quote_spanned! {span=> + #[warn(unconditional_recursion)] + fn _fmt() { _fmt() } + }); + } + let fmt = &self.fmt; let args = &self.args; // Currently `write!(f, "text")` produces less efficient code than // `f.write_str("text")`. We recognize the case when the format string // has no braces and no interpolated values, and generate simpler code. - tokens.extend(if self.requires_fmt_machinery { + let write = if self.requires_fmt_machinery { quote! { ::core::write!(__formatter, #fmt #args) } @@ -224,6 +323,18 @@ quote! { __formatter.write_str(#fmt) } + }; + + tokens.extend(if self.bindings.is_empty() { + write + } else { + let locals = self.bindings.iter().map(|(local, _value)| local); + let values = self.bindings.iter().map(|(_local, value)| value); + quote! { + match (#(#values,)*) { + (#(#locals,)*) => #write + } + } }); } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/expand.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/expand.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/expand.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/expand.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,19 +1,21 @@ use crate::ast::{Enum, Field, Input, Struct}; use crate::attr::Trait; +use crate::fallback; use crate::generics::InferredBounds; -use crate::span::MemberSpan; -use proc_macro2::TokenStream; +use crate::private; +use crate::unraw::MemberUnraw; +use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use std::collections::BTreeSet as Set; -use syn::{DeriveInput, GenericArgument, Member, PathArguments, Result, Token, Type}; +use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type}; pub fn derive(input: &DeriveInput) -> TokenStream { match try_expand(input) { Ok(expanded) => expanded, // If there are invalid attributes in the input, expand to an Error impl - // anyway to minimize spurious knock-on errors in other code that uses + // anyway to minimize spurious secondary errors in other code that uses // this type as an Error. - Err(error) => fallback(input, error), + Err(error) => fallback::expand(input, error), } } @@ -26,54 +28,28 @@ }) } -fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { - let ty = &input.ident; - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - - let error = error.to_compile_error(); - - quote! { - #error - - #[allow(unused_qualifications)] - impl #impl_generics std::error::Error for #ty #ty_generics #where_clause - where - // Work around trivial bounds being unstable. - // https://github.com/rust-lang/rust/issues/48214 - for<'workaround> #ty #ty_generics: ::core::fmt::Debug, - {} - - #[allow(unused_qualifications)] - impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { - fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::unreachable!() - } - } - } -} - fn impl_struct(input: Struct) -> TokenStream { - let ty = &input.ident; + let ty = call_site_ident(&input.ident); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut error_inferred_bounds = InferredBounds::new(); let source_body = if let Some(transparent_attr) = &input.attrs.transparent { let only_field = &input.fields[0]; if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); + error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); } let member = &only_field.member; Some(quote_spanned! {transparent_attr.span=> - std::error::Error::source(self.#member.as_dyn_error()) + ::thiserror::#private::Error::source(self.#member.as_dyn_error()) }) } else if let Some(source_field) = input.source_field() { let source = &source_field.member; if source_field.contains_generic { let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); + error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); } let asref = if type_is_option(source_field.ty) { - Some(quote_spanned!(source.member_span()=> .as_ref()?)) + Some(quote_spanned!(source.span()=> .as_ref()?)) } else { None }; @@ -88,8 +64,8 @@ }; let source_method = source_body.map(|body| { quote! { - fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { - use thiserror::__private::AsDynError as _; + fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { + use ::thiserror::#private::AsDynError as _; #body } } @@ -101,13 +77,13 @@ let body = if let Some(source_field) = input.source_field() { let source = &source_field.member; let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {source.member_span()=> + quote_spanned! {source.span()=> if let ::core::option::Option::Some(source) = &self.#source { source.thiserror_provide(#request); } } } else { - quote_spanned! {source.member_span()=> + quote_spanned! {source.span()=> self.#source.thiserror_provide(#request); } }; @@ -116,32 +92,32 @@ } else if type_is_option(backtrace_field.ty) { Some(quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }) } else { Some(quote! { - #request.provide_ref::(&self.#backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); }) }; quote! { - use thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide #self_provide } } else if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::(&self.#backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); } }; quote! { - fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { + fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) { #body } } @@ -178,6 +154,7 @@ let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); quote! { #[allow(unused_qualifications)] + #[automatically_derived] impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { #[allow(clippy::used_underscore_binding)] fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -188,18 +165,31 @@ }); let from_impl = input.from_field().map(|from_field| { + let span = from_field.attrs.from.unwrap().span; let backtrace_field = input.distinct_backtrace_field(); let from = unoptional_type(from_field.ty); - let body = from_initializer(from_field, backtrace_field); - quote! { - #[allow(unused_qualifications)] + let source_var = Ident::new("source", span); + let body = from_initializer(from_field, backtrace_field, &source_var); + let from_function = quote! { + fn from(#source_var: #from) -> Self { + #ty #body + } + }; + let from_impl = quote_spanned! {span=> + #[automatically_derived] impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { - #[allow(deprecated)] - fn from(source: #from) -> Self { - #ty #body - } + #from_function } - } + }; + Some(quote! { + #[allow( + deprecated, + unused_qualifications, + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + )] + #from_impl + }) }); if input.generics.type_params().next().is_some() { @@ -211,7 +201,8 @@ quote! { #[allow(unused_qualifications)] - impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { + #[automatically_derived] + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { #source_method #provide_method } @@ -221,7 +212,7 @@ } fn impl_enum(input: Enum) -> TokenStream { - let ty = &input.ident; + let ty = call_site_ident(&input.ident); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut error_inferred_bounds = InferredBounds::new(); @@ -231,11 +222,11 @@ if let Some(transparent_attr) = &variant.attrs.transparent { let only_field = &variant.fields[0]; if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); + error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); } let member = &only_field.member; let source = quote_spanned! {transparent_attr.span=> - std::error::Error::source(transparent.as_dyn_error()) + ::thiserror::#private::Error::source(transparent.as_dyn_error()) }; quote! { #ty::#ident {#member: transparent} => #source, @@ -244,10 +235,10 @@ let source = &source_field.member; if source_field.contains_generic { let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); + error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); } let asref = if type_is_option(source_field.ty) { - Some(quote_spanned!(source.member_span()=> .as_ref()?)) + Some(quote_spanned!(source.span()=> .as_ref()?)) } else { None }; @@ -265,8 +256,8 @@ } }); Some(quote! { - fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { - use thiserror::__private::AsDynError as _; + fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { + use ::thiserror::#private::AsDynError as _; #[allow(deprecated)] match self { #(#arms)* @@ -289,25 +280,25 @@ let source = &source_field.member; let varsource = quote!(source); let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {source.member_span()=> + quote_spanned! {source.span()=> if let ::core::option::Option::Some(source) = #varsource { source.thiserror_provide(#request); } } } else { - quote_spanned! {source.member_span()=> + quote_spanned! {source.span()=> #varsource.thiserror_provide(#request); } }; let self_provide = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }; quote! { @@ -316,7 +307,7 @@ #source: #varsource, .. } => { - use thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide #self_provide } @@ -328,19 +319,19 @@ let backtrace = &backtrace_field.member; let varsource = quote!(source); let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {backtrace.member_span()=> + quote_spanned! {backtrace.span()=> if let ::core::option::Option::Some(source) = #varsource { source.thiserror_provide(#request); } } } else { - quote_spanned! {backtrace.member_span()=> + quote_spanned! {backtrace.span()=> #varsource.thiserror_provide(#request); } }; quote! { #ty::#ident {#backtrace: #varsource, ..} => { - use thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide } } @@ -350,12 +341,12 @@ let body = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }; quote! { @@ -370,7 +361,7 @@ } }); Some(quote! { - fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { + fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) { #[allow(deprecated)] match self { #(#arms)* @@ -397,19 +388,23 @@ }; let arms = input.variants.iter().map(|variant| { let mut display_implied_bounds = Set::new(); - let display = match &variant.attrs.display { - Some(display) => { - display_implied_bounds.clone_from(&display.implied_bounds); - display.to_token_stream() - } - None => { - let only_field = match &variant.fields[0].member { - Member::Named(ident) => ident.clone(), - Member::Unnamed(index) => format_ident!("_{}", index), - }; - display_implied_bounds.insert((0, Trait::Display)); - quote!(::core::fmt::Display::fmt(#only_field, __formatter)) - } + let display = if let Some(display) = &variant.attrs.display { + display_implied_bounds.clone_from(&display.implied_bounds); + display.to_token_stream() + } else if let Some(fmt) = &variant.attrs.fmt { + let fmt_path = &fmt.path; + let vars = variant.fields.iter().map(|field| match &field.member { + MemberUnraw::Named(ident) => ident.to_local(), + MemberUnraw::Unnamed(index) => format_ident!("_{}", index), + }); + quote!(#fmt_path(#(#vars,)* __formatter)) + } else { + let only_field = match &variant.fields[0].member { + MemberUnraw::Named(ident) => ident.to_local(), + MemberUnraw::Unnamed(index) => format_ident!("_{}", index), + }; + display_implied_bounds.insert((0, Trait::Display)); + quote!(::core::fmt::Display::fmt(#only_field, __formatter)) }; for (field, bound) in display_implied_bounds { let field = &variant.fields[field]; @@ -427,6 +422,7 @@ let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); Some(quote! { #[allow(unused_qualifications)] + #[automatically_derived] impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { #use_as_display @@ -443,18 +439,31 @@ let from_impls = input.variants.iter().filter_map(|variant| { let from_field = variant.from_field()?; + let span = from_field.attrs.from.unwrap().span; let backtrace_field = variant.distinct_backtrace_field(); let variant = &variant.ident; let from = unoptional_type(from_field.ty); - let body = from_initializer(from_field, backtrace_field); - Some(quote! { - #[allow(unused_qualifications)] + let source_var = Ident::new("source", span); + let body = from_initializer(from_field, backtrace_field, &source_var); + let from_function = quote! { + fn from(#source_var: #from) -> Self { + #ty::#variant #body + } + }; + let from_impl = quote_spanned! {span=> + #[automatically_derived] impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { - #[allow(deprecated)] - fn from(source: #from) -> Self { - #ty::#variant #body - } + #from_function } + }; + Some(quote! { + #[allow( + deprecated, + unused_qualifications, + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + )] + #from_impl }) }); @@ -467,7 +476,8 @@ quote! { #[allow(unused_qualifications)] - impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { + #[automatically_derived] + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { #source_method #provide_method } @@ -476,14 +486,22 @@ } } +// Create an ident with which we can expand `impl Trait for #ident {}` on a +// deprecated type without triggering deprecation warning on the generated impl. +pub(crate) fn call_site_ident(ident: &Ident) -> Ident { + let mut ident = ident.clone(); + ident.set_span(ident.span().resolved_at(Span::call_site())); + ident +} + fn fields_pat(fields: &[Field]) -> TokenStream { let mut members = fields.iter().map(|field| &field.member).peekable(); match members.peek() { - Some(Member::Named(_)) => quote!({ #(#members),* }), - Some(Member::Unnamed(_)) => { + Some(MemberUnraw::Named(_)) => quote!({ #(#members),* }), + Some(MemberUnraw::Unnamed(_)) => { let vars = members.map(|member| match member { - Member::Unnamed(member) => format_ident!("_{}", member), - Member::Named(_) => unreachable!(), + MemberUnraw::Unnamed(index) => format_ident!("_{}", index), + MemberUnraw::Named(_) => unreachable!(), }); quote!((#(#vars),*)) } @@ -494,29 +512,33 @@ fn use_as_display(needs_as_display: bool) -> Option { if needs_as_display { Some(quote! { - use thiserror::__private::AsDisplay as _; + use ::thiserror::#private::AsDisplay as _; }) } else { None } } -fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream { +fn from_initializer( + from_field: &Field, + backtrace_field: Option<&Field>, + source_var: &Ident, +) -> TokenStream { let from_member = &from_field.member; let some_source = if type_is_option(from_field.ty) { - quote!(::core::option::Option::Some(source)) + quote!(::core::option::Option::Some(#source_var)) } else { - quote!(source) + quote!(#source_var) }; let backtrace = backtrace_field.map(|backtrace_field| { let backtrace_member = &backtrace_field.member; if type_is_option(backtrace_field.ty) { quote! { - #backtrace_member: ::core::option::Option::Some(std::backtrace::Backtrace::capture()), + #backtrace_member: ::core::option::Option::Some(::thiserror::#private::Backtrace::capture()), } } else { quote! { - #backtrace_member: ::core::convert::From::from(std::backtrace::Backtrace::capture()), + #backtrace_member: ::core::convert::From::from(::thiserror::#private::Backtrace::capture()), } } }); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/fallback.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fallback.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/fallback.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fallback.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,33 @@ +use crate::expand::call_site_ident; +use crate::private; +use proc_macro2::TokenStream; +use quote::quote; +use syn::DeriveInput; + +pub(crate) fn expand(input: &DeriveInput, error: syn::Error) -> TokenStream { + let ty = call_site_ident(&input.ident); + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + + let error = error.to_compile_error(); + + quote! { + #error + + #[allow(unused_qualifications)] + #[automatically_derived] + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #where_clause + where + // Work around trivial bounds being unstable. + // https://github.com/rust-lang/rust/issues/48214 + for<'workaround> #ty #ty_generics: ::core::fmt::Debug, + {} + + #[allow(unused_qualifications)] + #[automatically_derived] + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { + fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::unreachable!() + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/fmt.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,36 +1,41 @@ -use crate::ast::Field; +use crate::ast::{ContainerKind, Field}; use crate::attr::{Display, Trait}; -use proc_macro2::TokenTree; -use quote::{format_ident, quote_spanned}; -use std::collections::{BTreeSet as Set, HashMap as Map}; +use crate::private; +use crate::scan_expr::scan_expr; +use crate::unraw::{IdentUnraw, MemberUnraw}; +use proc_macro2::{Delimiter, TokenStream, TokenTree}; +use quote::{format_ident, quote, quote_spanned, ToTokens as _}; +use std::collections::{BTreeSet, HashMap}; +use std::iter; use syn::ext::IdentExt; -use syn::parse::{ParseStream, Parser}; -use syn::{Ident, Index, LitStr, Member, Result, Token}; +use syn::parse::discouraged::Speculative; +use syn::parse::{Error, ParseStream, Parser, Result}; +use syn::{Expr, Ident, Index, LitStr, Token}; impl Display<'_> { - // Transform `"error {var}"` to `"error {}", var`. - pub fn expand_shorthand(&mut self, fields: &[Field]) { + pub fn expand_shorthand(&mut self, fields: &[Field], container: ContainerKind) -> Result<()> { let raw_args = self.args.clone(); - let mut named_args = explicit_named_args.parse2(raw_args).unwrap(); - let mut member_index = Map::new(); + let FmtArguments { + named: user_named_args, + first_unnamed, + } = explicit_named_args.parse2(raw_args).unwrap(); + + let mut member_index = HashMap::new(); + let mut extra_positional_arguments_allowed = true; for (i, field) in fields.iter().enumerate() { member_index.insert(&field.member, i); + extra_positional_arguments_allowed &= matches!(&field.member, MemberUnraw::Named(_)); } let span = self.fmt.span(); let fmt = self.fmt.value(); let mut read = fmt.as_str(); let mut out = String::new(); - let mut args = self.args.clone(); let mut has_bonus_display = false; - let mut implied_bounds = Set::new(); - - let mut has_trailing_comma = false; - if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() { - if punct.as_char() == ',' { - has_trailing_comma = true; - } - } + let mut infinite_recursive = false; + let mut implied_bounds = BTreeSet::new(); + let mut bindings = Vec::new(); + let mut macro_named_args = BTreeSet::new(); self.requires_fmt_machinery = self.requires_fmt_machinery || fmt.contains('}'); @@ -45,129 +50,274 @@ } let next = match read.chars().next() { Some(next) => next, - None => return, + None => return Ok(()), }; let member = match next { '0'..='9' => { let int = take_int(&mut read); - let member = match int.parse::() { - Ok(index) => Member::Unnamed(Index { index, span }), - Err(_) => return, - }; - if !member_index.contains_key(&member) { - out += ∫ - continue; + if !extra_positional_arguments_allowed { + if let Some(first_unnamed) = &first_unnamed { + let msg = format!("ambiguous reference to positional arguments by number in a {container}; change this to a named argument"); + return Err(Error::new_spanned(first_unnamed, msg)); + } + } + match int.parse::() { + Ok(index) => MemberUnraw::Unnamed(Index { index, span }), + Err(_) => return Ok(()), } - member } 'a'..='z' | 'A'..='Z' | '_' => { - let mut ident = take_ident(&mut read); - ident.set_span(span); - Member::Named(ident) + if read.starts_with("r#") { + continue; + } + let repr = take_ident(&mut read); + if repr == "_" { + // Invalid. Let rustc produce the diagnostic. + out += repr; + continue; + } + let ident = IdentUnraw::new(Ident::new(repr, span)); + if user_named_args.contains(&ident) { + // Refers to a named argument written by the user, not to field. + out += repr; + continue; + } + MemberUnraw::Named(ident) } _ => continue, }; - if let Some(&field) = member_index.get(&member) { - let end_spec = match read.find('}') { - Some(end_spec) => end_spec, - None => return, - }; - let bound = match read[..end_spec].chars().next_back() { - Some('?') => Trait::Debug, - Some('o') => Trait::Octal, - Some('x') => Trait::LowerHex, - Some('X') => Trait::UpperHex, - Some('p') => Trait::Pointer, - Some('b') => Trait::Binary, - Some('e') => Trait::LowerExp, - Some('E') => Trait::UpperExp, - Some(_) | None => Trait::Display, - }; - implied_bounds.insert((field, bound)); - } - let local = match &member { - Member::Unnamed(index) => format_ident!("_{}", index), - Member::Named(ident) => ident.clone(), - }; - let mut formatvar = local.clone(); - if formatvar.to_string().starts_with("r#") { - formatvar = format_ident!("r_{}", formatvar); - } - if formatvar.to_string().starts_with('_') { - // Work around leading underscore being rejected by 1.40 and - // older compilers. https://github.com/rust-lang/rust/pull/66847 - formatvar = format_ident!("field_{}", formatvar); + let end_spec = match read.find('}') { + Some(end_spec) => end_spec, + None => return Ok(()), + }; + let mut bonus_display = false; + let bound = match read[..end_spec].chars().next_back() { + Some('?') => Trait::Debug, + Some('o') => Trait::Octal, + Some('x') => Trait::LowerHex, + Some('X') => Trait::UpperHex, + Some('p') => Trait::Pointer, + Some('b') => Trait::Binary, + Some('e') => Trait::LowerExp, + Some('E') => Trait::UpperExp, + Some(_) => Trait::Display, + None => { + bonus_display = true; + has_bonus_display = true; + Trait::Display + } + }; + infinite_recursive |= member == *"self" && bound == Trait::Display; + let field = match member_index.get(&member) { + Some(&field) => field, + None => { + out += &member.to_string(); + continue; + } + }; + implied_bounds.insert((field, bound)); + let formatvar_prefix = if bonus_display { + "__display" + } else if bound == Trait::Pointer { + "__pointer" + } else { + "__field" + }; + let mut formatvar = IdentUnraw::new(match &member { + MemberUnraw::Unnamed(index) => format_ident!("{}{}", formatvar_prefix, index), + MemberUnraw::Named(ident) => { + format_ident!("{}_{}", formatvar_prefix, ident.to_string()) + } + }); + while user_named_args.contains(&formatvar) { + formatvar = IdentUnraw::new(format_ident!("_{}", formatvar.to_string())); } + formatvar.set_span(span); out += &formatvar.to_string(); - if !named_args.insert(formatvar.clone()) { - // Already specified in the format argument list. + if !macro_named_args.insert(formatvar.clone()) { + // Already added to bindings by a previous use. continue; } - if !has_trailing_comma { - args.extend(quote_spanned!(span=> ,)); - } - args.extend(quote_spanned!(span=> #formatvar = #local)); - if read.starts_with('}') && member_index.contains_key(&member) { - has_bonus_display = true; - args.extend(quote_spanned!(span=> .as_display())); - } - has_trailing_comma = false; + let mut binding_value = match &member { + MemberUnraw::Unnamed(index) => format_ident!("_{}", index), + MemberUnraw::Named(ident) => ident.to_local(), + }; + binding_value.set_span(span.resolved_at(fields[field].member.span())); + let wrapped_binding_value = if bonus_display { + quote_spanned!(span=> #binding_value.as_display()) + } else if bound == Trait::Pointer { + quote!(::thiserror::#private::Var(#binding_value)) + } else { + binding_value.into_token_stream() + }; + bindings.push((formatvar.to_local(), wrapped_binding_value)); } out += read; self.fmt = LitStr::new(&out, self.fmt.span()); - self.args = args; self.has_bonus_display = has_bonus_display; + self.infinite_recursive = infinite_recursive; self.implied_bounds = implied_bounds; + self.bindings = bindings; + Ok(()) } } -fn explicit_named_args(input: ParseStream) -> Result> { - let mut named_args = Set::new(); +struct FmtArguments { + named: BTreeSet, + first_unnamed: Option, +} + +#[allow(clippy::unnecessary_wraps)] +fn explicit_named_args(input: ParseStream) -> Result { + let ahead = input.fork(); + if let Ok(set) = try_explicit_named_args(&ahead) { + input.advance_to(&ahead); + return Ok(set); + } + + let ahead = input.fork(); + if let Ok(set) = fallback_explicit_named_args(&ahead) { + input.advance_to(&ahead); + return Ok(set); + } + + input.parse::().unwrap(); + Ok(FmtArguments { + named: BTreeSet::new(), + first_unnamed: None, + }) +} + +fn try_explicit_named_args(input: ParseStream) -> Result { + let mut syn_full = None; + let mut args = FmtArguments { + named: BTreeSet::new(), + first_unnamed: None, + }; while !input.is_empty() { - if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) { + input.parse::()?; + if input.is_empty() { + break; + } + + let mut begin_unnamed = None; + if input.peek(Ident::peek_any) && input.peek2(Token![=]) && !input.peek2(Token![==]) { + let ident: IdentUnraw = input.parse()?; + input.parse::()?; + args.named.insert(ident); + } else { + begin_unnamed = Some(input.fork()); + } + + let ahead = input.fork(); + if *syn_full.get_or_insert_with(is_syn_full) && ahead.parse::().is_ok() { + input.advance_to(&ahead); + } else { + scan_expr(input)?; + } + + if let Some(begin_unnamed) = begin_unnamed { + if args.first_unnamed.is_none() { + args.first_unnamed = Some(between(&begin_unnamed, input)); + } + } + } + + Ok(args) +} + +fn fallback_explicit_named_args(input: ParseStream) -> Result { + let mut args = FmtArguments { + named: BTreeSet::new(), + first_unnamed: None, + }; + + while !input.is_empty() { + if input.peek(Token![,]) + && input.peek2(Ident::peek_any) + && input.peek3(Token![=]) + && !input.peek3(Token![==]) + { input.parse::()?; - let ident = input.call(Ident::parse_any)?; + let ident: IdentUnraw = input.parse()?; input.parse::()?; - named_args.insert(ident); + args.named.insert(ident); } else { input.parse::()?; } } - Ok(named_args) + Ok(args) +} + +fn is_syn_full() -> bool { + // Expr::Block contains syn::Block which contains Vec. In the + // current version of Syn, syn::Stmt is exhaustive and could only plausibly + // represent `trait Trait {}` in Stmt::Item which contains syn::Item. Most + // of the point of syn's non-"full" mode is to avoid compiling Item and the + // entire expansive syntax tree it comprises. So the following expression + // being parsed to Expr::Block is a reliable indication that "full" is + // enabled. + let test = quote!({ + trait Trait {} + }); + match syn::parse2(test) { + Ok(Expr::Verbatim(_)) | Err(_) => false, + Ok(Expr::Block(_)) => true, + Ok(_) => unreachable!(), + } } -fn take_int(read: &mut &str) -> String { - let mut int = String::new(); - for (i, ch) in read.char_indices() { +fn take_int<'a>(read: &mut &'a str) -> &'a str { + let mut int_len = 0; + for ch in read.chars() { match ch { - '0'..='9' => int.push(ch), - _ => { - *read = &read[i..]; - break; - } + '0'..='9' => int_len += 1, + _ => break, } } + let (int, rest) = read.split_at(int_len); + *read = rest; int } -fn take_ident(read: &mut &str) -> Ident { - let mut ident = String::new(); - let raw = read.starts_with("r#"); - if raw { - ident.push_str("r#"); - *read = &read[2..]; - } - for (i, ch) in read.char_indices() { +fn take_ident<'a>(read: &mut &'a str) -> &'a str { + let mut ident_len = 0; + for ch in read.chars() { match ch { - 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch), - _ => { - *read = &read[i..]; - break; + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident_len += 1, + _ => break, + } + } + let (ident, rest) = read.split_at(ident_len); + *read = rest; + ident +} + +fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream { + let end = end.cursor(); + let mut cursor = begin.cursor(); + let mut tokens = TokenStream::new(); + + while cursor < end { + let (tt, next) = cursor.token_tree().unwrap(); + + if end < next { + if let Some((inside, _span, _after)) = cursor.group(Delimiter::None) { + cursor = inside; + continue; } + if tokens.is_empty() { + tokens.extend(iter::once(tt)); + } + break; } + + tokens.extend(iter::once(tt)); + cursor = next; } - Ident::parse_any.parse_str(&ident).unwrap() + + tokens } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/generics.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/generics.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/generics.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/generics.rs 2006-07-24 01:21:28.000000000 +0000 @@ -25,11 +25,12 @@ fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) { if let Type::Path(ty) = ty { - if ty.qself.is_none() { - if let Some(ident) = ty.path.get_ident() { - if in_scope.names.contains(ident) { - *found = true; - } + if let Some(qself) = &ty.qself { + crawl(in_scope, &qself.ty, found); + } else { + let front = ty.path.segments.first().unwrap(); + if front.arguments.is_none() && in_scope.names.contains(&front.ident) { + *found = true; } } for segment in &ty.path.segments { @@ -57,7 +58,6 @@ } } - #[allow(clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8771 pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) { let ty = ty.to_token_stream(); let bound = bound.to_token_stream(); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,6 +2,7 @@ clippy::blocks_in_conditions, clippy::cast_lossless, clippy::cast_possible_truncation, + clippy::enum_glob_use, clippy::manual_find, clippy::manual_let_else, clippy::manual_map, @@ -14,19 +15,24 @@ clippy::too_many_lines, clippy::wrong_self_convention )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] extern crate proc_macro; mod ast; mod attr; mod expand; +mod fallback; mod fmt; mod generics; mod prop; -mod span; +mod scan_expr; +mod unraw; mod valid; use proc_macro::TokenStream; +use proc_macro2::{Ident, Span}; +use quote::{ToTokens, TokenStreamExt as _}; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(Error, attributes(backtrace, error, from, source))] @@ -34,3 +40,15 @@ let input = parse_macro_input!(input as DeriveInput); expand::derive(&input).into() } + +#[allow(non_camel_case_types)] +struct private; + +impl ToTokens for private { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(Ident::new( + concat!("__private", env!("CARGO_PKG_VERSION_PATCH")), + Span::call_site(), + )); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/prop.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/prop.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/prop.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/prop.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,7 +1,7 @@ use crate::ast::{Enum, Field, Struct, Variant}; -use crate::span::MemberSpan; +use crate::unraw::MemberUnraw; use proc_macro2::Span; -use syn::{Member, Type}; +use syn::Type; impl Struct<'_> { pub(crate) fn from_field(&self) -> Option<&Field> { @@ -38,10 +38,11 @@ pub(crate) fn has_display(&self) -> bool { self.attrs.display.is_some() || self.attrs.transparent.is_some() + || self.attrs.fmt.is_some() || self .variants .iter() - .any(|variant| variant.attrs.display.is_some()) + .any(|variant| variant.attrs.display.is_some() || variant.attrs.fmt.is_some()) || self .variants .iter() @@ -75,11 +76,11 @@ pub(crate) fn source_span(&self) -> Span { if let Some(source_attr) = &self.attrs.source { - source_attr.path().get_ident().unwrap().span() + source_attr.span } else if let Some(from_attr) = &self.attrs.from { - from_attr.path().get_ident().unwrap().span() + from_attr.span } else { - self.member.member_span() + self.member.span() } } } @@ -101,7 +102,7 @@ } for field in fields { match &field.member { - Member::Named(ident) if ident == "source" => return Some(field), + MemberUnraw::Named(ident) if ident == "source" => return Some(field), _ => {} } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/scan_expr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/scan_expr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/scan_expr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/scan_expr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,264 @@ +use self::{Action::*, Input::*}; +use proc_macro2::{Delimiter, Ident, Spacing, TokenTree}; +use syn::parse::{ParseStream, Result}; +use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Token, Type}; + +enum Input { + Keyword(&'static str), + Punct(&'static str), + ConsumeAny, + ConsumeBinOp, + ConsumeBrace, + ConsumeDelimiter, + ConsumeIdent, + ConsumeLifetime, + ConsumeLiteral, + ConsumeNestedBrace, + ExpectPath, + ExpectTurbofish, + ExpectType, + CanBeginExpr, + Otherwise, + Empty, +} + +enum Action { + SetState(&'static [(Input, Action)]), + IncDepth, + DecDepth, + Finish, +} + +static INIT: [(Input, Action); 28] = [ + (ConsumeDelimiter, SetState(&POSTFIX)), + (Keyword("async"), SetState(&ASYNC)), + (Keyword("break"), SetState(&BREAK_LABEL)), + (Keyword("const"), SetState(&CONST)), + (Keyword("continue"), SetState(&CONTINUE)), + (Keyword("for"), SetState(&FOR)), + (Keyword("if"), IncDepth), + (Keyword("let"), SetState(&PATTERN)), + (Keyword("loop"), SetState(&BLOCK)), + (Keyword("match"), IncDepth), + (Keyword("move"), SetState(&CLOSURE)), + (Keyword("return"), SetState(&RETURN)), + (Keyword("static"), SetState(&CLOSURE)), + (Keyword("unsafe"), SetState(&BLOCK)), + (Keyword("while"), IncDepth), + (Keyword("yield"), SetState(&RETURN)), + (Keyword("_"), SetState(&POSTFIX)), + (Punct("!"), SetState(&INIT)), + (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])), + (Punct("&"), SetState(&REFERENCE)), + (Punct("*"), SetState(&INIT)), + (Punct("-"), SetState(&INIT)), + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])), + (ConsumeLiteral, SetState(&POSTFIX)), + (ExpectPath, SetState(&PATH)), +]; + +static POSTFIX: [(Input, Action); 10] = [ + (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])), + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("."), SetState(&DOT)), + (Punct("?"), SetState(&POSTFIX)), + (ConsumeBinOp, SetState(&INIT)), + (Punct("="), SetState(&INIT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (ConsumeDelimiter, SetState(&POSTFIX)), + (Empty, Finish), +]; + +static ASYNC: [(Input, Action); 3] = [ + (Keyword("move"), SetState(&ASYNC)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeBrace, SetState(&POSTFIX)), +]; + +static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))]; + +static BREAK_LABEL: [(Input, Action); 2] = [ + (ConsumeLifetime, SetState(&BREAK_VALUE)), + (Otherwise, SetState(&BREAK_VALUE)), +]; + +static BREAK_VALUE: [(Input, Action); 3] = [ + (ConsumeNestedBrace, SetState(&IF_THEN)), + (CanBeginExpr, SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +static CLOSURE: [(Input, Action); 6] = [ + (Keyword("async"), SetState(&CLOSURE)), + (Keyword("move"), SetState(&CLOSURE)), + (Punct(","), SetState(&CLOSURE)), + (Punct(">"), SetState(&CLOSURE)), + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeLifetime, SetState(&CLOSURE)), +]; + +static CLOSURE_ARGS: [(Input, Action); 2] = [ + (Punct("|"), SetState(&CLOSURE_RET)), + (ConsumeAny, SetState(&CLOSURE_ARGS)), +]; + +static CLOSURE_RET: [(Input, Action); 2] = [ + (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])), + (Otherwise, SetState(&INIT)), +]; + +static CONST: [(Input, Action); 2] = [ + (Punct("|"), SetState(&CLOSURE_ARGS)), + (ConsumeBrace, SetState(&POSTFIX)), +]; + +static CONTINUE: [(Input, Action); 2] = [ + (ConsumeLifetime, SetState(&POSTFIX)), + (Otherwise, SetState(&POSTFIX)), +]; + +static DOT: [(Input, Action); 3] = [ + (Keyword("await"), SetState(&POSTFIX)), + (ConsumeIdent, SetState(&METHOD)), + (ConsumeLiteral, SetState(&POSTFIX)), +]; + +static FOR: [(Input, Action); 2] = [ + (Punct("<"), SetState(&CLOSURE)), + (Otherwise, SetState(&PATTERN)), +]; + +static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)]; +static IF_THEN: [(Input, Action); 2] = + [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)]; + +static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))]; + +static PATH: [(Input, Action); 4] = [ + (Punct("!="), SetState(&INIT)), + (Punct("!"), SetState(&INIT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (Otherwise, SetState(&POSTFIX)), +]; + +static PATTERN: [(Input, Action); 15] = [ + (ConsumeDelimiter, SetState(&PATTERN)), + (Keyword("box"), SetState(&PATTERN)), + (Keyword("in"), IncDepth), + (Keyword("mut"), SetState(&PATTERN)), + (Keyword("ref"), SetState(&PATTERN)), + (Keyword("_"), SetState(&PATTERN)), + (Punct("!"), SetState(&PATTERN)), + (Punct("&"), SetState(&PATTERN)), + (Punct("..="), SetState(&PATTERN)), + (Punct(".."), SetState(&PATTERN)), + (Punct("="), SetState(&INIT)), + (Punct("@"), SetState(&PATTERN)), + (Punct("|"), SetState(&PATTERN)), + (ConsumeLiteral, SetState(&PATTERN)), + (ExpectPath, SetState(&PATTERN)), +]; + +static RANGE: [(Input, Action); 6] = [ + (Punct("..="), SetState(&INIT)), + (Punct(".."), SetState(&RANGE)), + (Punct("."), SetState(&DOT)), + (ConsumeNestedBrace, SetState(&IF_THEN)), + (Empty, Finish), + (Otherwise, SetState(&INIT)), +]; + +static RAW: [(Input, Action); 3] = [ + (Keyword("const"), SetState(&INIT)), + (Keyword("mut"), SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +static REFERENCE: [(Input, Action); 3] = [ + (Keyword("mut"), SetState(&INIT)), + (Keyword("raw"), SetState(&RAW)), + (Otherwise, SetState(&INIT)), +]; + +static RETURN: [(Input, Action); 2] = [ + (CanBeginExpr, SetState(&INIT)), + (Otherwise, SetState(&POSTFIX)), +]; + +pub(crate) fn scan_expr(input: ParseStream) -> Result<()> { + let mut state = INIT.as_slice(); + let mut depth = 0usize; + 'table: loop { + for rule in state { + if match rule.0 { + Input::Keyword(expected) => input.step(|cursor| match cursor.ident() { + Some((ident, rest)) if ident == expected => Ok((true, rest)), + _ => Ok((false, *cursor)), + })?, + Input::Punct(expected) => input.step(|cursor| { + let begin = *cursor; + let mut cursor = begin; + for (i, ch) in expected.chars().enumerate() { + match cursor.punct() { + Some((punct, _)) if punct.as_char() != ch => break, + Some((_, rest)) if i == expected.len() - 1 => { + return Ok((true, rest)); + } + Some((punct, rest)) if punct.spacing() == Spacing::Joint => { + cursor = rest; + } + _ => break, + } + } + Ok((false, begin)) + })?, + Input::ConsumeAny => input.parse::>()?.is_some(), + Input::ConsumeBinOp => input.parse::().is_ok(), + Input::ConsumeBrace | Input::ConsumeNestedBrace => { + (matches!(rule.0, Input::ConsumeBrace) || depth > 0) + && input.step(|cursor| match cursor.group(Delimiter::Brace) { + Some((_inside, _span, rest)) => Ok((true, rest)), + None => Ok((false, *cursor)), + })? + } + Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() { + Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)), + None => Ok((false, *cursor)), + })?, + Input::ConsumeIdent => input.parse::>()?.is_some(), + Input::ConsumeLifetime => input.parse::>()?.is_some(), + Input::ConsumeLiteral => input.parse::>()?.is_some(), + Input::ExpectPath => { + input.parse::()?; + true + } + Input::ExpectTurbofish => { + if input.peek(Token![::]) { + input.parse::()?; + } + true + } + Input::ExpectType => { + Type::without_plus(input)?; + true + } + Input::CanBeginExpr => Expr::peek(input), + Input::Otherwise => true, + Input::Empty => input.is_empty() || input.peek(Token![,]), + } { + state = match rule.1 { + Action::SetState(next) => next, + Action::IncDepth => (depth += 1, &INIT).1, + Action::DecDepth => (depth -= 1, &POSTFIX).1, + Action::Finish => return if depth == 0 { Ok(()) } else { break }, + }; + continue 'table; + } + } + return Err(input.error("unsupported expression")); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/span.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/span.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/span.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/span.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -use proc_macro2::Span; -use syn::Member; - -pub trait MemberSpan { - fn member_span(&self) -> Span; -} - -impl MemberSpan for Member { - fn member_span(&self) -> Span { - match self { - Member::Named(ident) => ident.span(), - Member::Unnamed(index) => index.span, - } - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/unraw.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/unraw.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/unraw.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/unraw.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,142 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use quote::ToTokens; +use std::cmp::Ordering; +use std::fmt::{self, Display}; +use std::hash::{Hash, Hasher}; +use syn::ext::IdentExt as _; +use syn::parse::{Parse, ParseStream, Result}; +use syn::Index; + +#[derive(Clone)] +#[repr(transparent)] +pub struct IdentUnraw(Ident); + +impl IdentUnraw { + pub fn new(ident: Ident) -> Self { + IdentUnraw(ident) + } + + pub fn to_local(&self) -> Ident { + let unraw = self.0.unraw(); + let repr = unraw.to_string(); + if syn::parse_str::(&repr).is_err() { + if let "_" | "super" | "self" | "Self" | "crate" = repr.as_str() { + // Some identifiers are never allowed to appear as raw, like r#self and r#_. + } else { + return Ident::new_raw(&repr, Span::call_site()); + } + } + unraw + } + + pub fn set_span(&mut self, span: Span) { + self.0.set_span(span); + } +} + +impl Display for IdentUnraw { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0.unraw(), formatter) + } +} + +impl Eq for IdentUnraw {} + +impl PartialEq for IdentUnraw { + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(&self.0.unraw(), &other.0.unraw()) + } +} + +impl PartialEq for IdentUnraw { + fn eq(&self, other: &str) -> bool { + self.0 == other + } +} + +impl Ord for IdentUnraw { + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&self.0.unraw(), &other.0.unraw()) + } +} + +impl PartialOrd for IdentUnraw { + fn partial_cmp(&self, other: &Self) -> Option { + Some(Self::cmp(self, other)) + } +} + +impl Parse for IdentUnraw { + fn parse(input: ParseStream) -> Result { + input.call(Ident::parse_any).map(IdentUnraw::new) + } +} + +impl ToTokens for IdentUnraw { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.0.unraw().to_tokens(tokens); + } +} + +#[derive(Clone)] +pub enum MemberUnraw { + Named(IdentUnraw), + Unnamed(Index), +} + +impl MemberUnraw { + pub fn span(&self) -> Span { + match self { + MemberUnraw::Named(ident) => ident.0.span(), + MemberUnraw::Unnamed(index) => index.span, + } + } +} + +impl Display for MemberUnraw { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { + MemberUnraw::Named(this) => Display::fmt(this, formatter), + MemberUnraw::Unnamed(this) => Display::fmt(&this.index, formatter), + } + } +} + +impl Eq for MemberUnraw {} + +impl PartialEq for MemberUnraw { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (MemberUnraw::Named(this), MemberUnraw::Named(other)) => this == other, + (MemberUnraw::Unnamed(this), MemberUnraw::Unnamed(other)) => this == other, + _ => false, + } + } +} + +impl PartialEq for MemberUnraw { + fn eq(&self, other: &str) -> bool { + match self { + MemberUnraw::Named(this) => this == other, + MemberUnraw::Unnamed(_) => false, + } + } +} + +impl Hash for MemberUnraw { + fn hash(&self, hasher: &mut H) { + match self { + MemberUnraw::Named(ident) => ident.0.unraw().hash(hasher), + MemberUnraw::Unnamed(index) => index.hash(hasher), + } + } +} + +impl ToTokens for MemberUnraw { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + MemberUnraw::Named(ident) => ident.to_local().to_tokens(tokens), + MemberUnraw::Unnamed(index) => index.to_tokens(tokens), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/valid.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/valid.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl/src/valid.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl/src/valid.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,8 +1,6 @@ use crate::ast::{Enum, Field, Input, Struct, Variant}; use crate::attr::Attrs; -use quote::ToTokens; -use std::collections::BTreeSet as Set; -use syn::{Error, GenericArgument, Member, PathArguments, Result, Type}; +use syn::{Error, GenericArgument, PathArguments, Result, Type}; impl Input<'_> { pub(crate) fn validate(&self) -> Result<()> { @@ -25,11 +23,17 @@ } if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { return Err(Error::new_spanned( - source, + source.original, "transparent error struct can't contain #[source]", )); } } + if let Some(fmt) = &self.attrs.fmt { + return Err(Error::new_spanned( + fmt.original, + "#[error(fmt = ...)] is only supported in enums; for a struct, handwrite your own Display impl", + )); + } check_field_attrs(&self.fields)?; for field in &self.fields { field.validate()?; @@ -44,7 +48,10 @@ let has_display = self.has_display(); for variant in &self.variants { variant.validate()?; - if has_display && variant.attrs.display.is_none() && variant.attrs.transparent.is_none() + if has_display + && variant.attrs.display.is_none() + && variant.attrs.transparent.is_none() + && variant.attrs.fmt.is_none() { return Err(Error::new_spanned( variant.original, @@ -52,18 +59,6 @@ )); } } - let mut from_types = Set::new(); - for variant in &self.variants { - if let Some(from_field) = variant.from_field() { - let repr = from_field.ty.to_token_stream().to_string(); - if !from_types.insert(repr) { - return Err(Error::new_spanned( - from_field.original, - "cannot derive From because another variant has the same source type", - )); - } - } - } Ok(()) } } @@ -80,7 +75,7 @@ } if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { return Err(Error::new_spanned( - source, + source.original, "transparent variant can't contain #[source]", )); } @@ -95,9 +90,15 @@ impl Field<'_> { fn validate(&self) -> Result<()> { - if let Some(display) = &self.attrs.display { + if let Some(unexpected_display_attr) = if let Some(display) = &self.attrs.display { + Some(display.original) + } else if let Some(fmt) = &self.attrs.fmt { + Some(fmt.original) + } else { + None + } { return Err(Error::new_spanned( - display.original, + unexpected_display_attr, "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant", )); } @@ -108,13 +109,13 @@ fn check_non_field_attrs(attrs: &Attrs) -> Result<()> { if let Some(from) = &attrs.from { return Err(Error::new_spanned( - from, + from.original, "not expected here; the #[from] attribute belongs on a specific field", )); } if let Some(source) = &attrs.source { return Err(Error::new_spanned( - source, + source.original, "not expected here; the #[source] attribute belongs on a specific field", )); } @@ -124,14 +125,26 @@ "not expected here; the #[backtrace] attribute belongs on a specific field", )); } - if let Some(display) = &attrs.display { - if attrs.transparent.is_some() { + if attrs.transparent.is_some() { + if let Some(display) = &attrs.display { return Err(Error::new_spanned( display.original, "cannot have both #[error(transparent)] and a display attribute", )); } + if let Some(fmt) = &attrs.fmt { + return Err(Error::new_spanned( + fmt.original, + "cannot have both #[error(transparent)] and #[error(fmt = ...)]", + )); + } + } else if let (Some(display), Some(_)) = (&attrs.display, &attrs.fmt) { + return Err(Error::new_spanned( + display.original, + "cannot have both #[error(fmt = ...)] and a format arguments attribute", + )); } + Ok(()) } @@ -143,13 +156,19 @@ for field in fields { if let Some(from) = field.attrs.from { if from_field.is_some() { - return Err(Error::new_spanned(from, "duplicate #[from] attribute")); + return Err(Error::new_spanned( + from.original, + "duplicate #[from] attribute", + )); } from_field = Some(field); } if let Some(source) = field.attrs.source { if source_field.is_some() { - return Err(Error::new_spanned(source, "duplicate #[source] attribute")); + return Err(Error::new_spanned( + source.original, + "duplicate #[source] attribute", + )); } source_field = Some(field); } @@ -172,21 +191,21 @@ has_backtrace |= field.is_backtrace(); } if let (Some(from_field), Some(source_field)) = (from_field, source_field) { - if !same_member(from_field, source_field) { + if from_field.member != source_field.member { return Err(Error::new_spanned( - from_field.attrs.from, + from_field.attrs.from.unwrap().original, "#[from] is only supported on the source field, not any other field", )); } } if let Some(from_field) = from_field { let max_expected_fields = match backtrace_field { - Some(backtrace_field) => 1 + !same_member(from_field, backtrace_field) as usize, + Some(backtrace_field) => 1 + (from_field.member != backtrace_field.member) as usize, None => 1 + has_backtrace as usize, }; if fields.len() > max_expected_fields { return Err(Error::new_spanned( - from_field.attrs.from, + from_field.attrs.from.unwrap().original, "deriving From requires no fields other than source and backtrace", )); } @@ -202,14 +221,6 @@ Ok(()) } -fn same_member(one: &Field, two: &Field) -> bool { - match (&one.member, &two.member) { - (Member::Named(one), Member::Named(two)) => one == two, - (Member::Unnamed(one), Member::Unnamed(two)) => one.index == two.index, - _ => unreachable!(), - } -} - fn contains_non_static_lifetime(ty: &Type) -> bool { match ty { Type::Path(ty) => { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"73ffedc7d9ea9884fb2c5df48572c4d56fecbdda40a91488372a14c6e7b7837c","Cargo.toml":"27f9696d64a97df170dc620366a6b6b0b162917a686511e6b878586b04846226","Cargo.toml.orig":"714d78a9e61f97e43a7c009ce85b756478921bfe0fd9a18c54b5658555c6a8fe","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"9b6cd6b1553483c99cd7e36aa422d37f4353c99b15da55534d28822f7fa7fd08","src/attr.rs":"99fca8c65a1907ee2f43f7ec28ce465bae22336c529bd7148738f9ce35375101","src/expand.rs":"2736a714372a4b81ac5438783dd2c0f656d624bec5cc4089af96ceecaeee011e","src/fmt.rs":"5d1cefc012403c2d4ff7ab2513c0ec559166df4271d5983a6463939b5ec8c3e1","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"5eea86c771e643328ad9bc3b881cce4bf9d50adae1b33e0d07645bdd9044003d","src/prop.rs":"5ba613e38430831259f20b258f33d57dcb783fbaeeb49e5faffa7b2a7be99e67","src/span.rs":"430460a4fa0d1fa9c627c1ddd575d2b101778fea84217591e1a93a5f6a2a0132","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e7ad85ee6b135c5748d37ed1e8edda950336af77" + }, + "path_in_vcs": "impl" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56" +name = "thiserror-impl" +version = "1.0.59" +authors = ["David Tolnay "] +description = "Implementation detail of the `thiserror` crate" +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0.74" + +[dependencies.quote] +version = "1.0.35" + +[dependencies.syn] +version = "2.0.46" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +[package] +name = "thiserror-impl" +version = "1.0.59" +authors = ["David Tolnay "] +description = "Implementation detail of the `thiserror` crate" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/thiserror" +rust-version = "1.56" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = "2.0.46" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/ast.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/ast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/ast.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/ast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,161 @@ +use crate::attr::{self, Attrs}; +use crate::generics::ParamsInScope; +use proc_macro2::Span; +use syn::{ + Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result, + Type, +}; + +pub enum Input<'a> { + Struct(Struct<'a>), + Enum(Enum<'a>), +} + +pub struct Struct<'a> { + pub attrs: Attrs<'a>, + pub ident: Ident, + pub generics: &'a Generics, + pub fields: Vec>, +} + +pub struct Enum<'a> { + pub attrs: Attrs<'a>, + pub ident: Ident, + pub generics: &'a Generics, + pub variants: Vec>, +} + +pub struct Variant<'a> { + pub original: &'a syn::Variant, + pub attrs: Attrs<'a>, + pub ident: Ident, + pub fields: Vec>, +} + +pub struct Field<'a> { + pub original: &'a syn::Field, + pub attrs: Attrs<'a>, + pub member: Member, + pub ty: &'a Type, + pub contains_generic: bool, +} + +impl<'a> Input<'a> { + pub fn from_syn(node: &'a DeriveInput) -> Result { + match &node.data { + Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct), + Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum), + Data::Union(_) => Err(Error::new_spanned( + node, + "union as errors are not supported", + )), + } + } +} + +impl<'a> Struct<'a> { + fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result { + let mut attrs = attr::get(&node.attrs)?; + let scope = ParamsInScope::new(&node.generics); + let span = attrs.span().unwrap_or_else(Span::call_site); + let fields = Field::multiple_from_syn(&data.fields, &scope, span)?; + if let Some(display) = &mut attrs.display { + display.expand_shorthand(&fields); + } + Ok(Struct { + attrs, + ident: node.ident.clone(), + generics: &node.generics, + fields, + }) + } +} + +impl<'a> Enum<'a> { + fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result { + let attrs = attr::get(&node.attrs)?; + let scope = ParamsInScope::new(&node.generics); + let span = attrs.span().unwrap_or_else(Span::call_site); + let variants = data + .variants + .iter() + .map(|node| { + let mut variant = Variant::from_syn(node, &scope, span)?; + if let display @ None = &mut variant.attrs.display { + display.clone_from(&attrs.display); + } + if let Some(display) = &mut variant.attrs.display { + display.expand_shorthand(&variant.fields); + } else if variant.attrs.transparent.is_none() { + variant.attrs.transparent = attrs.transparent; + } + Ok(variant) + }) + .collect::>()?; + Ok(Enum { + attrs, + ident: node.ident.clone(), + generics: &node.generics, + variants, + }) + } +} + +impl<'a> Variant<'a> { + fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result { + let attrs = attr::get(&node.attrs)?; + let span = attrs.span().unwrap_or(span); + Ok(Variant { + original: node, + attrs, + ident: node.ident.clone(), + fields: Field::multiple_from_syn(&node.fields, scope, span)?, + }) + } +} + +impl<'a> Field<'a> { + fn multiple_from_syn( + fields: &'a Fields, + scope: &ParamsInScope<'a>, + span: Span, + ) -> Result> { + fields + .iter() + .enumerate() + .map(|(i, field)| Field::from_syn(i, field, scope, span)) + .collect() + } + + fn from_syn( + i: usize, + node: &'a syn::Field, + scope: &ParamsInScope<'a>, + span: Span, + ) -> Result { + Ok(Field { + original: node, + attrs: attr::get(&node.attrs)?, + member: node.ident.clone().map(Member::Named).unwrap_or_else(|| { + Member::Unnamed(Index { + index: i as u32, + span, + }) + }), + ty: &node.ty, + contains_generic: scope.intersects(&node.ty), + }) + } +} + +impl Attrs<'_> { + pub fn span(&self) -> Option { + if let Some(display) = &self.display { + Some(display.fmt.span()) + } else if let Some(transparent) = &self.transparent { + Some(transparent.span) + } else { + None + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/attr.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/attr.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/attr.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/attr.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,247 @@ +use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; +use quote::{format_ident, quote, ToTokens}; +use std::collections::BTreeSet as Set; +use syn::parse::discouraged::Speculative; +use syn::parse::ParseStream; +use syn::{ + braced, bracketed, parenthesized, token, Attribute, Error, Ident, Index, LitInt, LitStr, Meta, + Result, Token, +}; + +pub struct Attrs<'a> { + pub display: Option>, + pub source: Option<&'a Attribute>, + pub backtrace: Option<&'a Attribute>, + pub from: Option<&'a Attribute>, + pub transparent: Option>, +} + +#[derive(Clone)] +pub struct Display<'a> { + pub original: &'a Attribute, + pub fmt: LitStr, + pub args: TokenStream, + pub requires_fmt_machinery: bool, + pub has_bonus_display: bool, + pub implied_bounds: Set<(usize, Trait)>, +} + +#[derive(Copy, Clone)] +pub struct Transparent<'a> { + pub original: &'a Attribute, + pub span: Span, +} + +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub enum Trait { + Debug, + Display, + Octal, + LowerHex, + UpperHex, + Pointer, + Binary, + LowerExp, + UpperExp, +} + +pub fn get(input: &[Attribute]) -> Result { + let mut attrs = Attrs { + display: None, + source: None, + backtrace: None, + from: None, + transparent: None, + }; + + for attr in input { + if attr.path().is_ident("error") { + parse_error_attribute(&mut attrs, attr)?; + } else if attr.path().is_ident("source") { + attr.meta.require_path_only()?; + if attrs.source.is_some() { + return Err(Error::new_spanned(attr, "duplicate #[source] attribute")); + } + attrs.source = Some(attr); + } else if attr.path().is_ident("backtrace") { + attr.meta.require_path_only()?; + if attrs.backtrace.is_some() { + return Err(Error::new_spanned(attr, "duplicate #[backtrace] attribute")); + } + attrs.backtrace = Some(attr); + } else if attr.path().is_ident("from") { + match attr.meta { + Meta::Path(_) => {} + Meta::List(_) | Meta::NameValue(_) => { + // Assume this is meant for derive_more crate or something. + continue; + } + } + if attrs.from.is_some() { + return Err(Error::new_spanned(attr, "duplicate #[from] attribute")); + } + attrs.from = Some(attr); + } + } + + Ok(attrs) +} + +fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> { + syn::custom_keyword!(transparent); + + attr.parse_args_with(|input: ParseStream| { + if let Some(kw) = input.parse::>()? { + if attrs.transparent.is_some() { + return Err(Error::new_spanned( + attr, + "duplicate #[error(transparent)] attribute", + )); + } + attrs.transparent = Some(Transparent { + original: attr, + span: kw.span, + }); + return Ok(()); + } + + let fmt: LitStr = input.parse()?; + + let ahead = input.fork(); + ahead.parse::>()?; + let args = if ahead.is_empty() { + input.advance_to(&ahead); + TokenStream::new() + } else { + parse_token_expr(input, false)? + }; + + let requires_fmt_machinery = !args.is_empty(); + + let display = Display { + original: attr, + fmt, + args, + requires_fmt_machinery, + has_bonus_display: false, + implied_bounds: Set::new(), + }; + if attrs.display.is_some() { + return Err(Error::new_spanned( + attr, + "only one #[error(...)] attribute is allowed", + )); + } + attrs.display = Some(display); + Ok(()) + }) +} + +fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result { + let mut tokens = Vec::new(); + while !input.is_empty() { + if begin_expr && input.peek(Token![.]) { + if input.peek2(Ident) { + input.parse::()?; + begin_expr = false; + continue; + } + if input.peek2(LitInt) { + input.parse::()?; + let int: Index = input.parse()?; + let ident = format_ident!("_{}", int.index, span = int.span); + tokens.push(TokenTree::Ident(ident)); + begin_expr = false; + continue; + } + } + + begin_expr = input.peek(Token![break]) + || input.peek(Token![continue]) + || input.peek(Token![if]) + || input.peek(Token![in]) + || input.peek(Token![match]) + || input.peek(Token![mut]) + || input.peek(Token![return]) + || input.peek(Token![while]) + || input.peek(Token![+]) + || input.peek(Token![&]) + || input.peek(Token![!]) + || input.peek(Token![^]) + || input.peek(Token![,]) + || input.peek(Token![/]) + || input.peek(Token![=]) + || input.peek(Token![>]) + || input.peek(Token![<]) + || input.peek(Token![|]) + || input.peek(Token![%]) + || input.peek(Token![;]) + || input.peek(Token![*]) + || input.peek(Token![-]); + + let token: TokenTree = if input.peek(token::Paren) { + let content; + let delimiter = parenthesized!(content in input); + let nested = parse_token_expr(&content, true)?; + let mut group = Group::new(Delimiter::Parenthesis, nested); + group.set_span(delimiter.span.join()); + TokenTree::Group(group) + } else if input.peek(token::Brace) { + let content; + let delimiter = braced!(content in input); + let nested = parse_token_expr(&content, true)?; + let mut group = Group::new(Delimiter::Brace, nested); + group.set_span(delimiter.span.join()); + TokenTree::Group(group) + } else if input.peek(token::Bracket) { + let content; + let delimiter = bracketed!(content in input); + let nested = parse_token_expr(&content, true)?; + let mut group = Group::new(Delimiter::Bracket, nested); + group.set_span(delimiter.span.join()); + TokenTree::Group(group) + } else { + input.parse()? + }; + tokens.push(token); + } + Ok(TokenStream::from_iter(tokens)) +} + +impl ToTokens for Display<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let fmt = &self.fmt; + let args = &self.args; + + // Currently `write!(f, "text")` produces less efficient code than + // `f.write_str("text")`. We recognize the case when the format string + // has no braces and no interpolated values, and generate simpler code. + tokens.extend(if self.requires_fmt_machinery { + quote! { + ::core::write!(__formatter, #fmt #args) + } + } else { + quote! { + __formatter.write_str(#fmt) + } + }); + } +} + +impl ToTokens for Trait { + fn to_tokens(&self, tokens: &mut TokenStream) { + let trait_name = match self { + Trait::Debug => "Debug", + Trait::Display => "Display", + Trait::Octal => "Octal", + Trait::LowerHex => "LowerHex", + Trait::UpperHex => "UpperHex", + Trait::Pointer => "Pointer", + Trait::Binary => "Binary", + Trait::LowerExp => "LowerExp", + Trait::UpperExp => "UpperExp", + }; + let ident = Ident::new(trait_name, Span::call_site()); + tokens.extend(quote!(::core::fmt::#ident)); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/expand.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/expand.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/expand.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/expand.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,562 @@ +use crate::ast::{Enum, Field, Input, Struct}; +use crate::attr::Trait; +use crate::generics::InferredBounds; +use crate::span::MemberSpan; +use proc_macro2::TokenStream; +use quote::{format_ident, quote, quote_spanned, ToTokens}; +use std::collections::BTreeSet as Set; +use syn::{DeriveInput, GenericArgument, Member, PathArguments, Result, Token, Type}; + +pub fn derive(input: &DeriveInput) -> TokenStream { + match try_expand(input) { + Ok(expanded) => expanded, + // If there are invalid attributes in the input, expand to an Error impl + // anyway to minimize spurious knock-on errors in other code that uses + // this type as an Error. + Err(error) => fallback(input, error), + } +} + +fn try_expand(input: &DeriveInput) -> Result { + let input = Input::from_syn(input)?; + input.validate()?; + Ok(match input { + Input::Struct(input) => impl_struct(input), + Input::Enum(input) => impl_enum(input), + }) +} + +fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { + let ty = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + + let error = error.to_compile_error(); + + quote! { + #error + + #[allow(unused_qualifications)] + impl #impl_generics std::error::Error for #ty #ty_generics #where_clause + where + // Work around trivial bounds being unstable. + // https://github.com/rust-lang/rust/issues/48214 + for<'workaround> #ty #ty_generics: ::core::fmt::Debug, + {} + + #[allow(unused_qualifications)] + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { + fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::unreachable!() + } + } + } +} + +fn impl_struct(input: Struct) -> TokenStream { + let ty = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let mut error_inferred_bounds = InferredBounds::new(); + + let source_body = if let Some(transparent_attr) = &input.attrs.transparent { + let only_field = &input.fields[0]; + if only_field.contains_generic { + error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); + } + let member = &only_field.member; + Some(quote_spanned! {transparent_attr.span=> + std::error::Error::source(self.#member.as_dyn_error()) + }) + } else if let Some(source_field) = input.source_field() { + let source = &source_field.member; + if source_field.contains_generic { + let ty = unoptional_type(source_field.ty); + error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); + } + let asref = if type_is_option(source_field.ty) { + Some(quote_spanned!(source.member_span()=> .as_ref()?)) + } else { + None + }; + let dyn_error = quote_spanned! {source_field.source_span()=> + self.#source #asref.as_dyn_error() + }; + Some(quote! { + ::core::option::Option::Some(#dyn_error) + }) + } else { + None + }; + let source_method = source_body.map(|body| { + quote! { + fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { + use thiserror::__private::AsDynError as _; + #body + } + } + }); + + let provide_method = input.backtrace_field().map(|backtrace_field| { + let request = quote!(request); + let backtrace = &backtrace_field.member; + let body = if let Some(source_field) = input.source_field() { + let source = &source_field.member; + let source_provide = if type_is_option(source_field.ty) { + quote_spanned! {source.member_span()=> + if let ::core::option::Option::Some(source) = &self.#source { + source.thiserror_provide(#request); + } + } + } else { + quote_spanned! {source.member_span()=> + self.#source.thiserror_provide(#request); + } + }; + let self_provide = if source == backtrace { + None + } else if type_is_option(backtrace_field.ty) { + Some(quote! { + if let ::core::option::Option::Some(backtrace) = &self.#backtrace { + #request.provide_ref::(backtrace); + } + }) + } else { + Some(quote! { + #request.provide_ref::(&self.#backtrace); + }) + }; + quote! { + use thiserror::__private::ThiserrorProvide as _; + #source_provide + #self_provide + } + } else if type_is_option(backtrace_field.ty) { + quote! { + if let ::core::option::Option::Some(backtrace) = &self.#backtrace { + #request.provide_ref::(backtrace); + } + } + } else { + quote! { + #request.provide_ref::(&self.#backtrace); + } + }; + quote! { + fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { + #body + } + } + }); + + let mut display_implied_bounds = Set::new(); + let display_body = if input.attrs.transparent.is_some() { + let only_field = &input.fields[0].member; + display_implied_bounds.insert((0, Trait::Display)); + Some(quote! { + ::core::fmt::Display::fmt(&self.#only_field, __formatter) + }) + } else if let Some(display) = &input.attrs.display { + display_implied_bounds.clone_from(&display.implied_bounds); + let use_as_display = use_as_display(display.has_bonus_display); + let pat = fields_pat(&input.fields); + Some(quote! { + #use_as_display + #[allow(unused_variables, deprecated)] + let Self #pat = self; + #display + }) + } else { + None + }; + let display_impl = display_body.map(|body| { + let mut display_inferred_bounds = InferredBounds::new(); + for (field, bound) in display_implied_bounds { + let field = &input.fields[field]; + if field.contains_generic { + display_inferred_bounds.insert(field.ty, bound); + } + } + let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); + quote! { + #[allow(unused_qualifications)] + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { + #[allow(clippy::used_underscore_binding)] + fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + #body + } + } + } + }); + + let from_impl = input.from_field().map(|from_field| { + let backtrace_field = input.distinct_backtrace_field(); + let from = unoptional_type(from_field.ty); + let body = from_initializer(from_field, backtrace_field); + quote! { + #[allow(unused_qualifications)] + impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { + #[allow(deprecated)] + fn from(source: #from) -> Self { + #ty #body + } + } + } + }); + + if input.generics.type_params().next().is_some() { + let self_token = ::default(); + error_inferred_bounds.insert(self_token, Trait::Debug); + error_inferred_bounds.insert(self_token, Trait::Display); + } + let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics); + + quote! { + #[allow(unused_qualifications)] + impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { + #source_method + #provide_method + } + #display_impl + #from_impl + } +} + +fn impl_enum(input: Enum) -> TokenStream { + let ty = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let mut error_inferred_bounds = InferredBounds::new(); + + let source_method = if input.has_source() { + let arms = input.variants.iter().map(|variant| { + let ident = &variant.ident; + if let Some(transparent_attr) = &variant.attrs.transparent { + let only_field = &variant.fields[0]; + if only_field.contains_generic { + error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); + } + let member = &only_field.member; + let source = quote_spanned! {transparent_attr.span=> + std::error::Error::source(transparent.as_dyn_error()) + }; + quote! { + #ty::#ident {#member: transparent} => #source, + } + } else if let Some(source_field) = variant.source_field() { + let source = &source_field.member; + if source_field.contains_generic { + let ty = unoptional_type(source_field.ty); + error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); + } + let asref = if type_is_option(source_field.ty) { + Some(quote_spanned!(source.member_span()=> .as_ref()?)) + } else { + None + }; + let varsource = quote!(source); + let dyn_error = quote_spanned! {source_field.source_span()=> + #varsource #asref.as_dyn_error() + }; + quote! { + #ty::#ident {#source: #varsource, ..} => ::core::option::Option::Some(#dyn_error), + } + } else { + quote! { + #ty::#ident {..} => ::core::option::Option::None, + } + } + }); + Some(quote! { + fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { + use thiserror::__private::AsDynError as _; + #[allow(deprecated)] + match self { + #(#arms)* + } + } + }) + } else { + None + }; + + let provide_method = if input.has_backtrace() { + let request = quote!(request); + let arms = input.variants.iter().map(|variant| { + let ident = &variant.ident; + match (variant.backtrace_field(), variant.source_field()) { + (Some(backtrace_field), Some(source_field)) + if backtrace_field.attrs.backtrace.is_none() => + { + let backtrace = &backtrace_field.member; + let source = &source_field.member; + let varsource = quote!(source); + let source_provide = if type_is_option(source_field.ty) { + quote_spanned! {source.member_span()=> + if let ::core::option::Option::Some(source) = #varsource { + source.thiserror_provide(#request); + } + } + } else { + quote_spanned! {source.member_span()=> + #varsource.thiserror_provide(#request); + } + }; + let self_provide = if type_is_option(backtrace_field.ty) { + quote! { + if let ::core::option::Option::Some(backtrace) = backtrace { + #request.provide_ref::(backtrace); + } + } + } else { + quote! { + #request.provide_ref::(backtrace); + } + }; + quote! { + #ty::#ident { + #backtrace: backtrace, + #source: #varsource, + .. + } => { + use thiserror::__private::ThiserrorProvide as _; + #source_provide + #self_provide + } + } + } + (Some(backtrace_field), Some(source_field)) + if backtrace_field.member == source_field.member => + { + let backtrace = &backtrace_field.member; + let varsource = quote!(source); + let source_provide = if type_is_option(source_field.ty) { + quote_spanned! {backtrace.member_span()=> + if let ::core::option::Option::Some(source) = #varsource { + source.thiserror_provide(#request); + } + } + } else { + quote_spanned! {backtrace.member_span()=> + #varsource.thiserror_provide(#request); + } + }; + quote! { + #ty::#ident {#backtrace: #varsource, ..} => { + use thiserror::__private::ThiserrorProvide as _; + #source_provide + } + } + } + (Some(backtrace_field), _) => { + let backtrace = &backtrace_field.member; + let body = if type_is_option(backtrace_field.ty) { + quote! { + if let ::core::option::Option::Some(backtrace) = backtrace { + #request.provide_ref::(backtrace); + } + } + } else { + quote! { + #request.provide_ref::(backtrace); + } + }; + quote! { + #ty::#ident {#backtrace: backtrace, ..} => { + #body + } + } + } + (None, _) => quote! { + #ty::#ident {..} => {} + }, + } + }); + Some(quote! { + fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { + #[allow(deprecated)] + match self { + #(#arms)* + } + } + }) + } else { + None + }; + + let display_impl = if input.has_display() { + let mut display_inferred_bounds = InferredBounds::new(); + let has_bonus_display = input.variants.iter().any(|v| { + v.attrs + .display + .as_ref() + .map_or(false, |display| display.has_bonus_display) + }); + let use_as_display = use_as_display(has_bonus_display); + let void_deref = if input.variants.is_empty() { + Some(quote!(*)) + } else { + None + }; + let arms = input.variants.iter().map(|variant| { + let mut display_implied_bounds = Set::new(); + let display = match &variant.attrs.display { + Some(display) => { + display_implied_bounds.clone_from(&display.implied_bounds); + display.to_token_stream() + } + None => { + let only_field = match &variant.fields[0].member { + Member::Named(ident) => ident.clone(), + Member::Unnamed(index) => format_ident!("_{}", index), + }; + display_implied_bounds.insert((0, Trait::Display)); + quote!(::core::fmt::Display::fmt(#only_field, __formatter)) + } + }; + for (field, bound) in display_implied_bounds { + let field = &variant.fields[field]; + if field.contains_generic { + display_inferred_bounds.insert(field.ty, bound); + } + } + let ident = &variant.ident; + let pat = fields_pat(&variant.fields); + quote! { + #ty::#ident #pat => #display + } + }); + let arms = arms.collect::>(); + let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); + Some(quote! { + #[allow(unused_qualifications)] + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { + fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + #use_as_display + #[allow(unused_variables, deprecated, clippy::used_underscore_binding)] + match #void_deref self { + #(#arms,)* + } + } + } + }) + } else { + None + }; + + let from_impls = input.variants.iter().filter_map(|variant| { + let from_field = variant.from_field()?; + let backtrace_field = variant.distinct_backtrace_field(); + let variant = &variant.ident; + let from = unoptional_type(from_field.ty); + let body = from_initializer(from_field, backtrace_field); + Some(quote! { + #[allow(unused_qualifications)] + impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { + #[allow(deprecated)] + fn from(source: #from) -> Self { + #ty::#variant #body + } + } + }) + }); + + if input.generics.type_params().next().is_some() { + let self_token = ::default(); + error_inferred_bounds.insert(self_token, Trait::Debug); + error_inferred_bounds.insert(self_token, Trait::Display); + } + let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics); + + quote! { + #[allow(unused_qualifications)] + impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { + #source_method + #provide_method + } + #display_impl + #(#from_impls)* + } +} + +fn fields_pat(fields: &[Field]) -> TokenStream { + let mut members = fields.iter().map(|field| &field.member).peekable(); + match members.peek() { + Some(Member::Named(_)) => quote!({ #(#members),* }), + Some(Member::Unnamed(_)) => { + let vars = members.map(|member| match member { + Member::Unnamed(member) => format_ident!("_{}", member), + Member::Named(_) => unreachable!(), + }); + quote!((#(#vars),*)) + } + None => quote!({}), + } +} + +fn use_as_display(needs_as_display: bool) -> Option { + if needs_as_display { + Some(quote! { + use thiserror::__private::AsDisplay as _; + }) + } else { + None + } +} + +fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream { + let from_member = &from_field.member; + let some_source = if type_is_option(from_field.ty) { + quote!(::core::option::Option::Some(source)) + } else { + quote!(source) + }; + let backtrace = backtrace_field.map(|backtrace_field| { + let backtrace_member = &backtrace_field.member; + if type_is_option(backtrace_field.ty) { + quote! { + #backtrace_member: ::core::option::Option::Some(std::backtrace::Backtrace::capture()), + } + } else { + quote! { + #backtrace_member: ::core::convert::From::from(std::backtrace::Backtrace::capture()), + } + } + }); + quote!({ + #from_member: #some_source, + #backtrace + }) +} + +fn type_is_option(ty: &Type) -> bool { + type_parameter_of_option(ty).is_some() +} + +fn unoptional_type(ty: &Type) -> TokenStream { + let unoptional = type_parameter_of_option(ty).unwrap_or(ty); + quote!(#unoptional) +} + +fn type_parameter_of_option(ty: &Type) -> Option<&Type> { + let path = match ty { + Type::Path(ty) => &ty.path, + _ => return None, + }; + + let last = path.segments.last().unwrap(); + if last.ident != "Option" { + return None; + } + + let bracketed = match &last.arguments { + PathArguments::AngleBracketed(bracketed) => bracketed, + _ => return None, + }; + + if bracketed.args.len() != 1 { + return None; + } + + match &bracketed.args[0] { + GenericArgument::Type(arg) => Some(arg), + _ => None, + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/fmt.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/fmt.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/fmt.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/fmt.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,173 @@ +use crate::ast::Field; +use crate::attr::{Display, Trait}; +use proc_macro2::TokenTree; +use quote::{format_ident, quote_spanned}; +use std::collections::{BTreeSet as Set, HashMap as Map}; +use syn::ext::IdentExt; +use syn::parse::{ParseStream, Parser}; +use syn::{Ident, Index, LitStr, Member, Result, Token}; + +impl Display<'_> { + // Transform `"error {var}"` to `"error {}", var`. + pub fn expand_shorthand(&mut self, fields: &[Field]) { + let raw_args = self.args.clone(); + let mut named_args = explicit_named_args.parse2(raw_args).unwrap(); + let mut member_index = Map::new(); + for (i, field) in fields.iter().enumerate() { + member_index.insert(&field.member, i); + } + + let span = self.fmt.span(); + let fmt = self.fmt.value(); + let mut read = fmt.as_str(); + let mut out = String::new(); + let mut args = self.args.clone(); + let mut has_bonus_display = false; + let mut implied_bounds = Set::new(); + + let mut has_trailing_comma = false; + if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() { + if punct.as_char() == ',' { + has_trailing_comma = true; + } + } + + self.requires_fmt_machinery = self.requires_fmt_machinery || fmt.contains('}'); + + while let Some(brace) = read.find('{') { + self.requires_fmt_machinery = true; + out += &read[..brace + 1]; + read = &read[brace + 1..]; + if read.starts_with('{') { + out.push('{'); + read = &read[1..]; + continue; + } + let next = match read.chars().next() { + Some(next) => next, + None => return, + }; + let member = match next { + '0'..='9' => { + let int = take_int(&mut read); + let member = match int.parse::() { + Ok(index) => Member::Unnamed(Index { index, span }), + Err(_) => return, + }; + if !member_index.contains_key(&member) { + out += ∫ + continue; + } + member + } + 'a'..='z' | 'A'..='Z' | '_' => { + let mut ident = take_ident(&mut read); + ident.set_span(span); + Member::Named(ident) + } + _ => continue, + }; + if let Some(&field) = member_index.get(&member) { + let end_spec = match read.find('}') { + Some(end_spec) => end_spec, + None => return, + }; + let bound = match read[..end_spec].chars().next_back() { + Some('?') => Trait::Debug, + Some('o') => Trait::Octal, + Some('x') => Trait::LowerHex, + Some('X') => Trait::UpperHex, + Some('p') => Trait::Pointer, + Some('b') => Trait::Binary, + Some('e') => Trait::LowerExp, + Some('E') => Trait::UpperExp, + Some(_) | None => Trait::Display, + }; + implied_bounds.insert((field, bound)); + } + let local = match &member { + Member::Unnamed(index) => format_ident!("_{}", index), + Member::Named(ident) => ident.clone(), + }; + let mut formatvar = local.clone(); + if formatvar.to_string().starts_with("r#") { + formatvar = format_ident!("r_{}", formatvar); + } + if formatvar.to_string().starts_with('_') { + // Work around leading underscore being rejected by 1.40 and + // older compilers. https://github.com/rust-lang/rust/pull/66847 + formatvar = format_ident!("field_{}", formatvar); + } + out += &formatvar.to_string(); + if !named_args.insert(formatvar.clone()) { + // Already specified in the format argument list. + continue; + } + if !has_trailing_comma { + args.extend(quote_spanned!(span=> ,)); + } + args.extend(quote_spanned!(span=> #formatvar = #local)); + if read.starts_with('}') && member_index.contains_key(&member) { + has_bonus_display = true; + args.extend(quote_spanned!(span=> .as_display())); + } + has_trailing_comma = false; + } + + out += read; + self.fmt = LitStr::new(&out, self.fmt.span()); + self.args = args; + self.has_bonus_display = has_bonus_display; + self.implied_bounds = implied_bounds; + } +} + +fn explicit_named_args(input: ParseStream) -> Result> { + let mut named_args = Set::new(); + + while !input.is_empty() { + if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) { + input.parse::()?; + let ident = input.call(Ident::parse_any)?; + input.parse::()?; + named_args.insert(ident); + } else { + input.parse::()?; + } + } + + Ok(named_args) +} + +fn take_int(read: &mut &str) -> String { + let mut int = String::new(); + for (i, ch) in read.char_indices() { + match ch { + '0'..='9' => int.push(ch), + _ => { + *read = &read[i..]; + break; + } + } + } + int +} + +fn take_ident(read: &mut &str) -> Ident { + let mut ident = String::new(); + let raw = read.starts_with("r#"); + if raw { + ident.push_str("r#"); + *read = &read[2..]; + } + for (i, ch) in read.char_indices() { + match ch { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch), + _ => { + *read = &read[i..]; + break; + } + } + } + Ident::parse_any.parse_str(&ident).unwrap() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/generics.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/generics.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/generics.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/generics.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,83 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use std::collections::btree_map::Entry; +use std::collections::{BTreeMap as Map, BTreeSet as Set}; +use syn::punctuated::Punctuated; +use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause}; + +pub struct ParamsInScope<'a> { + names: Set<&'a Ident>, +} + +impl<'a> ParamsInScope<'a> { + pub fn new(generics: &'a Generics) -> Self { + ParamsInScope { + names: generics.type_params().map(|param| ¶m.ident).collect(), + } + } + + pub fn intersects(&self, ty: &Type) -> bool { + let mut found = false; + crawl(self, ty, &mut found); + found + } +} + +fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) { + if let Type::Path(ty) = ty { + if ty.qself.is_none() { + if let Some(ident) = ty.path.get_ident() { + if in_scope.names.contains(ident) { + *found = true; + } + } + } + for segment in &ty.path.segments { + if let PathArguments::AngleBracketed(arguments) = &segment.arguments { + for arg in &arguments.args { + if let GenericArgument::Type(ty) = arg { + crawl(in_scope, ty, found); + } + } + } + } + } +} + +pub struct InferredBounds { + bounds: Map, Punctuated)>, + order: Vec, +} + +impl InferredBounds { + pub fn new() -> Self { + InferredBounds { + bounds: Map::new(), + order: Vec::new(), + } + } + + #[allow(clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8771 + pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) { + let ty = ty.to_token_stream(); + let bound = bound.to_token_stream(); + let entry = self.bounds.entry(ty.to_string()); + if let Entry::Vacant(_) = entry { + self.order.push(ty); + } + let (set, tokens) = entry.or_default(); + if set.insert(bound.to_string()) { + tokens.push(bound); + } + } + + pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause { + let mut generics = generics.clone(); + let where_clause = generics.make_where_clause(); + for ty in &self.order { + let (_set, bounds) = &self.bounds[&ty.to_string()]; + where_clause.predicates.push(parse_quote!(#ty: #bounds)); + } + generics.where_clause.unwrap() + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,36 @@ +#![allow( + clippy::blocks_in_conditions, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::manual_find, + clippy::manual_let_else, + clippy::manual_map, + clippy::map_unwrap_or, + clippy::module_name_repetitions, + clippy::needless_pass_by_value, + clippy::range_plus_one, + clippy::single_match_else, + clippy::struct_field_names, + clippy::too_many_lines, + clippy::wrong_self_convention +)] + +extern crate proc_macro; + +mod ast; +mod attr; +mod expand; +mod fmt; +mod generics; +mod prop; +mod span; +mod valid; + +use proc_macro::TokenStream; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(Error, attributes(backtrace, error, from, source))] +pub fn derive_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + expand::derive(&input).into() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/prop.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/prop.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/prop.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/prop.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,147 @@ +use crate::ast::{Enum, Field, Struct, Variant}; +use crate::span::MemberSpan; +use proc_macro2::Span; +use syn::{Member, Type}; + +impl Struct<'_> { + pub(crate) fn from_field(&self) -> Option<&Field> { + from_field(&self.fields) + } + + pub(crate) fn source_field(&self) -> Option<&Field> { + source_field(&self.fields) + } + + pub(crate) fn backtrace_field(&self) -> Option<&Field> { + backtrace_field(&self.fields) + } + + pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> { + let backtrace_field = self.backtrace_field()?; + distinct_backtrace_field(backtrace_field, self.from_field()) + } +} + +impl Enum<'_> { + pub(crate) fn has_source(&self) -> bool { + self.variants + .iter() + .any(|variant| variant.source_field().is_some() || variant.attrs.transparent.is_some()) + } + + pub(crate) fn has_backtrace(&self) -> bool { + self.variants + .iter() + .any(|variant| variant.backtrace_field().is_some()) + } + + pub(crate) fn has_display(&self) -> bool { + self.attrs.display.is_some() + || self.attrs.transparent.is_some() + || self + .variants + .iter() + .any(|variant| variant.attrs.display.is_some()) + || self + .variants + .iter() + .all(|variant| variant.attrs.transparent.is_some()) + } +} + +impl Variant<'_> { + pub(crate) fn from_field(&self) -> Option<&Field> { + from_field(&self.fields) + } + + pub(crate) fn source_field(&self) -> Option<&Field> { + source_field(&self.fields) + } + + pub(crate) fn backtrace_field(&self) -> Option<&Field> { + backtrace_field(&self.fields) + } + + pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> { + let backtrace_field = self.backtrace_field()?; + distinct_backtrace_field(backtrace_field, self.from_field()) + } +} + +impl Field<'_> { + pub(crate) fn is_backtrace(&self) -> bool { + type_is_backtrace(self.ty) + } + + pub(crate) fn source_span(&self) -> Span { + if let Some(source_attr) = &self.attrs.source { + source_attr.path().get_ident().unwrap().span() + } else if let Some(from_attr) = &self.attrs.from { + from_attr.path().get_ident().unwrap().span() + } else { + self.member.member_span() + } + } +} + +fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { + for field in fields { + if field.attrs.from.is_some() { + return Some(field); + } + } + None +} + +fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { + for field in fields { + if field.attrs.from.is_some() || field.attrs.source.is_some() { + return Some(field); + } + } + for field in fields { + match &field.member { + Member::Named(ident) if ident == "source" => return Some(field), + _ => {} + } + } + None +} + +fn backtrace_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { + for field in fields { + if field.attrs.backtrace.is_some() { + return Some(field); + } + } + for field in fields { + if field.is_backtrace() { + return Some(field); + } + } + None +} + +// The #[backtrace] field, if it is not the same as the #[from] field. +fn distinct_backtrace_field<'a, 'b>( + backtrace_field: &'a Field<'b>, + from_field: Option<&Field>, +) -> Option<&'a Field<'b>> { + if from_field.map_or(false, |from_field| { + from_field.member == backtrace_field.member + }) { + None + } else { + Some(backtrace_field) + } +} + +fn type_is_backtrace(ty: &Type) -> bool { + let path = match ty { + Type::Path(ty) => &ty.path, + _ => return false, + }; + + let last = path.segments.last().unwrap(); + last.ident == "Backtrace" && last.arguments.is_empty() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/span.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/span.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/span.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/span.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,15 @@ +use proc_macro2::Span; +use syn::Member; + +pub trait MemberSpan { + fn member_span(&self) -> Span; +} + +impl MemberSpan for Member { + fn member_span(&self) -> Span { + match self { + Member::Named(ident) => ident.span(), + Member::Unnamed(index) => index.span, + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/valid.rs clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/valid.rs --- clamav-1.4.3+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/valid.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/thiserror-impl-1.0.59/src/valid.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,237 @@ +use crate::ast::{Enum, Field, Input, Struct, Variant}; +use crate::attr::Attrs; +use quote::ToTokens; +use std::collections::BTreeSet as Set; +use syn::{Error, GenericArgument, Member, PathArguments, Result, Type}; + +impl Input<'_> { + pub(crate) fn validate(&self) -> Result<()> { + match self { + Input::Struct(input) => input.validate(), + Input::Enum(input) => input.validate(), + } + } +} + +impl Struct<'_> { + fn validate(&self) -> Result<()> { + check_non_field_attrs(&self.attrs)?; + if let Some(transparent) = self.attrs.transparent { + if self.fields.len() != 1 { + return Err(Error::new_spanned( + transparent.original, + "#[error(transparent)] requires exactly one field", + )); + } + if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { + return Err(Error::new_spanned( + source, + "transparent error struct can't contain #[source]", + )); + } + } + check_field_attrs(&self.fields)?; + for field in &self.fields { + field.validate()?; + } + Ok(()) + } +} + +impl Enum<'_> { + fn validate(&self) -> Result<()> { + check_non_field_attrs(&self.attrs)?; + let has_display = self.has_display(); + for variant in &self.variants { + variant.validate()?; + if has_display && variant.attrs.display.is_none() && variant.attrs.transparent.is_none() + { + return Err(Error::new_spanned( + variant.original, + "missing #[error(\"...\")] display attribute", + )); + } + } + let mut from_types = Set::new(); + for variant in &self.variants { + if let Some(from_field) = variant.from_field() { + let repr = from_field.ty.to_token_stream().to_string(); + if !from_types.insert(repr) { + return Err(Error::new_spanned( + from_field.original, + "cannot derive From because another variant has the same source type", + )); + } + } + } + Ok(()) + } +} + +impl Variant<'_> { + fn validate(&self) -> Result<()> { + check_non_field_attrs(&self.attrs)?; + if self.attrs.transparent.is_some() { + if self.fields.len() != 1 { + return Err(Error::new_spanned( + self.original, + "#[error(transparent)] requires exactly one field", + )); + } + if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { + return Err(Error::new_spanned( + source, + "transparent variant can't contain #[source]", + )); + } + } + check_field_attrs(&self.fields)?; + for field in &self.fields { + field.validate()?; + } + Ok(()) + } +} + +impl Field<'_> { + fn validate(&self) -> Result<()> { + if let Some(display) = &self.attrs.display { + return Err(Error::new_spanned( + display.original, + "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant", + )); + } + Ok(()) + } +} + +fn check_non_field_attrs(attrs: &Attrs) -> Result<()> { + if let Some(from) = &attrs.from { + return Err(Error::new_spanned( + from, + "not expected here; the #[from] attribute belongs on a specific field", + )); + } + if let Some(source) = &attrs.source { + return Err(Error::new_spanned( + source, + "not expected here; the #[source] attribute belongs on a specific field", + )); + } + if let Some(backtrace) = &attrs.backtrace { + return Err(Error::new_spanned( + backtrace, + "not expected here; the #[backtrace] attribute belongs on a specific field", + )); + } + if let Some(display) = &attrs.display { + if attrs.transparent.is_some() { + return Err(Error::new_spanned( + display.original, + "cannot have both #[error(transparent)] and a display attribute", + )); + } + } + Ok(()) +} + +fn check_field_attrs(fields: &[Field]) -> Result<()> { + let mut from_field = None; + let mut source_field = None; + let mut backtrace_field = None; + let mut has_backtrace = false; + for field in fields { + if let Some(from) = field.attrs.from { + if from_field.is_some() { + return Err(Error::new_spanned(from, "duplicate #[from] attribute")); + } + from_field = Some(field); + } + if let Some(source) = field.attrs.source { + if source_field.is_some() { + return Err(Error::new_spanned(source, "duplicate #[source] attribute")); + } + source_field = Some(field); + } + if let Some(backtrace) = field.attrs.backtrace { + if backtrace_field.is_some() { + return Err(Error::new_spanned( + backtrace, + "duplicate #[backtrace] attribute", + )); + } + backtrace_field = Some(field); + has_backtrace = true; + } + if let Some(transparent) = field.attrs.transparent { + return Err(Error::new_spanned( + transparent.original, + "#[error(transparent)] needs to go outside the enum or struct, not on an individual field", + )); + } + has_backtrace |= field.is_backtrace(); + } + if let (Some(from_field), Some(source_field)) = (from_field, source_field) { + if !same_member(from_field, source_field) { + return Err(Error::new_spanned( + from_field.attrs.from, + "#[from] is only supported on the source field, not any other field", + )); + } + } + if let Some(from_field) = from_field { + let max_expected_fields = match backtrace_field { + Some(backtrace_field) => 1 + !same_member(from_field, backtrace_field) as usize, + None => 1 + has_backtrace as usize, + }; + if fields.len() > max_expected_fields { + return Err(Error::new_spanned( + from_field.attrs.from, + "deriving From requires no fields other than source and backtrace", + )); + } + } + if let Some(source_field) = source_field.or(from_field) { + if contains_non_static_lifetime(source_field.ty) { + return Err(Error::new_spanned( + &source_field.original.ty, + "non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static", + )); + } + } + Ok(()) +} + +fn same_member(one: &Field, two: &Field) -> bool { + match (&one.member, &two.member) { + (Member::Named(one), Member::Named(two)) => one == two, + (Member::Unnamed(one), Member::Unnamed(two)) => one.index == two.index, + _ => unreachable!(), + } +} + +fn contains_non_static_lifetime(ty: &Type) -> bool { + match ty { + Type::Path(ty) => { + let bracketed = match &ty.path.segments.last().unwrap().arguments { + PathArguments::AngleBracketed(bracketed) => bracketed, + _ => return false, + }; + for arg in &bracketed.args { + match arg { + GenericArgument::Type(ty) if contains_non_static_lifetime(ty) => return true, + GenericArgument::Lifetime(lifetime) if lifetime.ident != "static" => { + return true + } + _ => {} + } + } + false + } + Type::Reference(ty) => ty + .lifetime + .as_ref() + .map_or(false, |lifetime| lifetime.ident != "static"), + _ => false, // maybe implement later if there are common other cases + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGES.md":"ec8476c7358b3b2bdfdfda3ef1f236a5b312d052df47b6d48c2a13383e796a2a","Cargo.lock.msrv":"db0d1ac235bfe4cea82e711da68a92c6677c31362dd4f15b7216f8484848a151","Cargo.toml":"5ce1a9fb6017275d65a6fe3b5ab876e91232c3db859d08b854788fd921ab6109","LICENSE":"20c097d0de27e2adc179140a3d542091951a030699c7e1c78655f2a2d08d4e3e","README.md":"1c17af2aab3dcd95685672aecc5e5b7d1d608d41be9a8b22d327d06ebad0b72a","benches/lzw.rs":"ae9bd8a35ad6826ac204bb03bc6c07fc6070eb69c8f1baf20ed3222e515ca0a5","src/bytecast.rs":"fe162944a473d48d2502eab08f2fdb56e5b546d11cb25833454dd8d6395396ae","src/decoder/ifd.rs":"2f002d8f2905f8b6de1029a9ff28e1094323699ed0ac505d885f8a3106167546","src/decoder/image.rs":"205283e1fef0063c038c40cf0568103d70dbbbb9b8165ecf64795ba4a2458220","src/decoder/mod.rs":"0d05eab5f8841861adcd52fc2cc925e07fcebea714b30556fbef834260ab6ed7","src/decoder/stream.rs":"5dcfd4aeb04d2fca2dadc86b577accd8b5a87d8a92fe690bf98ca999192bf042","src/decoder/tag_reader.rs":"e95db23244da757588f0d885ebce18e189fafc52ac841682fb39371197b6f9d3","src/encoder/colortype.rs":"801eb6111d5c9fece5537a171b4aa3300d3d3f0f6242610ee819595146ea6928","src/encoder/compression/deflate.rs":"618158bf51516f954b995b59f75736e558d5ab6544105f17aec2d6cbaa265647","src/encoder/compression/lzw.rs":"dc3c8b1751929f4d9e79e1300dacd0723d9590bf9c3eeba4338bb7422595082d","src/encoder/compression/mod.rs":"315e989e0e4f1c0634bca86fb98e4fa0164906a6fe91cd7948640675275728c1","src/encoder/compression/packbits.rs":"5b6a8be41b17454f9530644537d4ccbe89656c22b170af0d76c121f1f0a5074b","src/encoder/compression/uncompressed.rs":"bcbfc2266785d2fbc6955f626691986f2e2aa9642af8ac2a06714ce03df71bc4","src/encoder/mod.rs":"ab873ee2b143dda7f51bb4f2022689e5241a50a8878e50d2a353f8139a0c70a4","src/encoder/tiff_value.rs":"df212aa92b53c2e8bdbe0638bce6e0ac477ade8d8b3494f287aceb4dda621ff1","src/encoder/writer.rs":"8c9b52bd5208f675e37bbb86fd5ce88753ac465d7a523559a9ca8cb18825bacc","src/error.rs":"ac5accb97593a056ea1843233b077500ba5fdf02e6b763056125d7b61df06d82","src/lib.rs":"6ec15b1e8f824b346520ec94dddb0604ee1a636c20dd96ece326f31351fd0c3c","src/tags.rs":"467f433a2bc3b3b0bf138ec2f9ad2dabd8f94086d4c89e52e11b395a9f2721c5","tests/benches/README.md":"61c5580a4c667cfe0cb2e63597f84b84e34a3424202d6e3e53954d4c273189f7","tests/benches/Transparency-lzw.tif":"b15297094106a33374672a6971ed1aaa5d2fbf3f3731c61af1107ba3e88af156","tests/benches/kodim02-lzw.tif":"9a9e3cf1c53e13a38f9d6409b0aae3fe214fea1b004ac3e848766b08bde38f66","tests/benches/kodim07-lzw.tif":"068beb46a3d186ed2fa65d5afbdbf1b34a02287b8d6c9e9c858728295ab277eb","tests/decode_bigtiff_images.rs":"5460b4c0be1588a6281c00a23ec1cb2a9b4cf3a5df5434da464ec30b888f6cd2","tests/decode_images.rs":"75bc4be6e060babb932a4a5c195802c364b4afc31b263c9d322ecc926f72c1d1","tests/decodedata-rgb-3c-8b.tiff":"88fb7908c4562ad3f3a1180c02115da71efc34a6d3b4f0573360113385cef33c","tests/encode_images.rs":"30e49f5aa2169fcb1ec59ffda95bcff4dd567ebb33eff3d81fae606d147cee59","tests/encode_images_with_compression.rs":"0a351c0096ee1db74214d12f1b1669b73419ddd915d4850400774ce2598c53cd","tests/fuzz_tests.rs":"742f4283cdc6c3f5d1ccf320ea6c0eb7f3f517cc831de801206c077a0518ec99"},"package":"ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ae473caf8d69d382da79d8c1cc3efaf5228c0e70c3899c2d312a0f75eee4af80",".github/workflows/rust.yml":"4bad0d1b4a94006a04daabd4337222932f25cf02472d63fc972c1dd94ad69e15","CHANGES.md":"003b22ad92652699ef5fd5ef677b87bbcc8c0c349c80a128b54d15a90f471b1c","Cargo.lock":"ab0b38a256ba8bc8ac4c7d23829e33823bc06269b45d9dba2d77c487410411b6","Cargo.toml":"2c30e90a09625a9ea561a4bbb7b69ee76ec3400e5a9b3aedc7f2578fd5135dec","Cargo.toml.orig":"170f7241d82f8f0da2b6f27ed94baa47acf7580f00d7c7873b5ea5f5cd946816","LICENSE":"20c097d0de27e2adc179140a3d542091951a030699c7e1c78655f2a2d08d4e3e","README.md":"c6ab90cfdcb820df38599e943d9bfb847832dcfc4ad8c935e5b5a801f846e26d","benches/lzw.rs":"ae9bd8a35ad6826ac204bb03bc6c07fc6070eb69c8f1baf20ed3222e515ca0a5","src/bytecast.rs":"de78962c9c8c08bd91e5cc5ce313712b174803e83bab0199ad2281536aa81251","src/decoder/cycles.rs":"c3195487f2bd7f1ffca002d1d26d8d02a50764b6b48807003ea2de5ea1fc4e39","src/decoder/ifd.rs":"f9d3e0da4e0dbdadf8639fa0f6e79a918debaf7e670305e57325e1da73ad3a79","src/decoder/image.rs":"458f4190bdc004f12810265cb1a26b429160718baaf5d2ccbcf87575cf7e0bf5","src/decoder/mod.rs":"f1e8ec7f87a858b1b3711eaeecbb6cfc75baa9b0e5c41cebf97ee2e63d4a683e","src/decoder/stream.rs":"74f309ea39b9ade66e040bd151197d86dcce80bace8ccd56511018221a05dc16","src/decoder/tag_reader.rs":"1daaa45d92844c523d4e8dbc0c870d8c27688e6f3e8d070c335344a66ea6ad74","src/directory.rs":"e1c236327d123365c629c1a45f51c7d8393b7ed5cc83097cd35baa5771f17bb9","src/encoder/colortype.rs":"b3568e750bccf3694677f1b52ece8f52c51e55e2182cc8a861e5a9607b6707ed","src/encoder/compression/deflate.rs":"d96e91ea01fddd5d060fcd3a53f55360163d2cd49a5dea32b1b6db3ccb5f14ba","src/encoder/compression/lzw.rs":"f2f8b279eb23521f9b7e0e87ddb04ce1773c1b8a9a9379dbf81a446311ae4b0c","src/encoder/compression/mod.rs":"c7384129421482cbd3400e12ce92756f674b12fa1fa35eaf56fb04d1cbef54cd","src/encoder/compression/packbits.rs":"2971d61100afe2772f52ac434be9bddcdc3103e82330dfd47cdbc7a808681f98","src/encoder/compression/uncompressed.rs":"2035d64bb2d30d7081b66b2469d00b5ba807ad6360dba4acf504673b7ff49795","src/encoder/mod.rs":"fd4ffddebdc8362cc1f951fe2a642b164f5c83a5018828309a5b60995273fe2a","src/encoder/tiff_value.rs":"5d2dd0e26d427d1ce14ac1326966f027407d6239d7fffe1d717a7339b1c04af5","src/encoder/writer.rs":"d25c3b767b2c42bbc5d06323e328f97844e1cda00e9eb3addaa20ee749ec6353","src/error.rs":"bd5852b0ee8a6ec14f87dc6a94c29e48fcd352d4eb9384357497f6ad6b8b4546","src/lib.rs":"ac9a4d87dc9a20ca2aab4ff48d1f15af7f1b38a27acee8ac1bb0c9114182e58e","src/tags.rs":"4b8ac94303edce91d4b1d00fbf28c4f634eda3a9b2bea0e348d1185389c35cca","tests/COPYRIGHT":"c341a79df284be8a0321dabda4aa1aeea053b55b4e0db827940c221fcaf29b7b","tests/benches/README.md":"61c5580a4c667cfe0cb2e63597f84b84e34a3424202d6e3e53954d4c273189f7","tests/benches/Transparency-lzw.tif":"b15297094106a33374672a6971ed1aaa5d2fbf3f3731c61af1107ba3e88af156","tests/benches/kodim02-lzw.tif":"9a9e3cf1c53e13a38f9d6409b0aae3fe214fea1b004ac3e848766b08bde38f66","tests/benches/kodim07-lzw.tif":"068beb46a3d186ed2fa65d5afbdbf1b34a02287b8d6c9e9c858728295ab277eb","tests/decode_bigtiff_images.rs":"5460b4c0be1588a6281c00a23ec1cb2a9b4cf3a5df5434da464ec30b888f6cd2","tests/decode_fp16_images.rs":"81bf11bb30fea7d3f45c8c4edb684f8ae5db22e5c6e9643bb6cfb22b28d7df09","tests/decode_geotiff_images.rs":"f77baa92a02d95296cc3d0af7c1ac1aa9a954e3667cff364f86d7f9c11ac2230","tests/decode_images.rs":"2db5febb48ea76bd4ddf11ff1eec8b80df28b887333782f85f10d01fa41c3b4a","tests/decodedata-rgb-3c-8b.tiff":"88fb7908c4562ad3f3a1180c02115da71efc34a6d3b4f0573360113385cef33c","tests/encode_images.rs":"acbbef1edf04b6be233123920b9137aacb5c2b27339bbba2112edfedcaa352e5","tests/encode_images_with_compression.rs":"72ab30b93ef520f39f45d0ff510be9f7432fc653064f65146767ac57b6c2a1bb","tests/fuzz_tests.rs":"742f4283cdc6c3f5d1ccf320ea6c0eb7f3f517cc831de801206c077a0518ec99","tests/predict.rs":"dbf8a5a8c301cdaa4282abd8ecf405a5d4ecf22dcbe343527e7fb293405bac92","tests/subsubifds.rs":"408f1fe35613866e623cc822c2b6197b2e8c68519def9dd61518d8f5473be052","tests/subsubifds.tif":"145292ca9f6df9c4a9a41381efccefc76e8fa7392e62118bbb6fc982c3d02168"},"package":"af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "695208cffe1ba8623fe4576584bcc87e13b63b65" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/tiff/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/.github/workflows/rust.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,94 @@ +name: Rust CI +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: ["1.74.0", stable, beta, nightly] + steps: + - uses: actions/checkout@v2 + + - uses: dtolnay/rust-toolchain@nightly + if: ${{ matrix.rust == '1.74.0' }} + - name: Generate Cargo.lock with minimal-version dependencies + if: ${{ matrix.rust == '1.74.0' }} + run: cargo -Zminimal-versions generate-lockfile + + - uses: dtolnay/rust-toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - name: build + run: cargo build -v + - name: test + if: ${{ matrix.rust != '1.74.0' }} + run: cargo test -v && cargo doc -v + + features: + runs-on: ubuntu-latest + strategy: + matrix: + feature: ["", deflate, jpeg, lzw, zstd, default, "default,zstd"] + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - name: Cargo check + run: cargo check --features "${{ matrix.feature }}" --no-default-features + + - name: Cargo clippy + if: ${{ matrix.feature != '' }} + run: cargo clippy --no-deps --all-features --all-targets -- -D warnings + + other_archs: + # github actions does not support 32-bit or big endian systems directly, but + # it does support QEMU. so we install qemu, then build and run the tests on + # emulated systems. NOTE: you can also use this approach to test locally. + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: [powerpc-unknown-linux-gnu, i686-unknown-linux-gnu] + steps: + - uses: actions/checkout@v4 + - name: Install or use cached cross-rs/cross + uses: baptiste0928/cargo-install@v2 + with: + crate: cross + - name: Cache Cargo Dependencies + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + key: ${{ matrix.arch }} + - name: Start Docker (required for cross-rs) + run: sudo systemctl start docker + - name: Cross-Run Tests using QEMU + run: cross test --target ${{ matrix.arch }} + + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - name: Run rustfmt check + run: cargo fmt -- --check + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - run: cargo clippy --all-features # TODO: enable "-- -D warnings" once all outstanding clippy lints are fixed diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/CHANGES.md clamav-1.4.6+dfsg/.cargo/vendor/tiff/CHANGES.md --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/CHANGES.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/CHANGES.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,3 +1,62 @@ +# Version 0.10.3 + +New features: +- Group 4 `fax` is now recognized as a compression type and decoded. +- A crate feature `fax` controls related dependencies, on by default. + +Changes: +- The presence of PhotometricInterpretation::WhiteIsZero now returns an error + if the color type can not be inverted by the library where they were + previously silently ignored. Please report any missing color types. + +Fixes: +- The PhotometricInterpretation::WhiteIsZero is now also applied to 1-bit + images, as well as 2-bit and 4-bit sample types where previously the presence + of this tag was ignored. + +# Version 0.10.2 + +Republished 0.10.1, fixing an accidentally removed method (`Decoder::find_tag_unsigned_vec`). + +# Version 0.10.1 + +New features: + - Added a dedicated `Directory` type (#277) + - Expose methods related to `Directory` publicly (#278) + - Implement writing directories (#281, #283) + - Add ICC (color profile) to the set of known tags (#287) + - Added `Decoder.inner()` to access the underlying reader (#289) + - Added methods for reading into a pre-allocated byte buffer (#285) + +Changes: + - No longer perform color conversion when decoding embedded JPEG. This fixes decoding for JPEG images with alpha channel. (#274) + - More lenient LZW decoding to match libtiff (#231) + +Fixes: + - Fixed seeking multiple times in a row (#279) + +# Version 0.10.0 + +New features: +- Added `ColorType::Multiband` and `ColorType::CMYKA`. +- Added `Value::Byte` and `Value::SignedByte` to represent `u8` and `i8` tags. +- Encoding can now use horizontal predictor. +- The `Decoder::tag_iter` method allows iterating over all tags in the image. +- Half precision floating point values are now supported during decoding. +- ZStandard compression has been added as an additional compression method + during decoding, but requires the `zstd` feature flag. + +Changes: +- Switched `u16` and `i16` values to be intepreted as `Value::Short` and + `Value::SignedShort` respectively. +- Changed JPEG compression to use the `zune-jpeg` crate instead of + `jpeg-decoder`. +- The `deflate`, `jpeg`, and `lzw` compression methods are now controlled by + (enabled by default) feature flags. + +Fixes: +- Fixed a bug in 1 bit-per-pixel decoding. + # Version 0.9.1 New features: diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,841 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags 1.3.2", + "textwrap", + "unicode-width", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.3", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tiff" +version = "0.10.3" +dependencies = [ + "crc32fast", + "criterion", + "fax", + "flate2", + "half 2.6.0", + "quick-error", + "weezl", + "zstd", + "zune-jpeg", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.3", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +dependencies = [ + "zune-core", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.lock.msrv clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock.msrv --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.lock.msrv 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.lock.msrv 1970-01-01 00:00:00.000000000 +0000 @@ -1,638 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" -dependencies = [ - "memchr", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap", - "unicode-width", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "csv" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "flate2" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jpeg-decoder" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "regex" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "syn" -version = "2.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tiff" -version = "0.9.0" -dependencies = [ - "criterion", - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -11,14 +11,20 @@ [package] edition = "2021" -rust-version = "1.61.0" +rust-version = "1.74.0" name = "tiff" -version = "0.9.1" +version = "0.10.3" authors = ["The image-rs Developers"] +build = false exclude = [ "tests/images/*", "tests/fuzz_images/*", ] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "TIFF decoding and encoding library in pure Rust" readme = "README.md" categories = [ @@ -29,20 +35,93 @@ repository = "https://github.com/image-rs/image-tiff" resolver = "2" +[features] +default = [ + "deflate", + "fax", + "jpeg", + "lzw", +] +deflate = ["dep:flate2"] +fax = ["dep:fax34"] +jpeg = ["dep:zune-jpeg"] +lzw = ["dep:weezl"] +zstd = ["dep:zstd"] + +[lib] +name = "tiff" +path = "src/lib.rs" + +[[test]] +name = "decode_bigtiff_images" +path = "tests/decode_bigtiff_images.rs" + +[[test]] +name = "decode_fp16_images" +path = "tests/decode_fp16_images.rs" + +[[test]] +name = "decode_geotiff_images" +path = "tests/decode_geotiff_images.rs" + +[[test]] +name = "decode_images" +path = "tests/decode_images.rs" + +[[test]] +name = "encode_images" +path = "tests/encode_images.rs" + +[[test]] +name = "encode_images_with_compression" +path = "tests/encode_images_with_compression.rs" + +[[test]] +name = "fuzz_tests" +path = "tests/fuzz_tests.rs" + +[[test]] +name = "predict" +path = "tests/predict.rs" + +[[test]] +name = "subsubifds" +path = "tests/subsubifds.rs" + [[bench]] name = "lzw" +path = "benches/lzw.rs" harness = false +[dependencies.fax34] +version = "0.2.6" +optional = true +package = "fax" + [dependencies.flate2] version = "1.0.20" +optional = true + +[dependencies.half] +version = "2.4.1" -[dependencies.jpeg] -version = "0.3.0" -default-features = false -package = "jpeg-decoder" +[dependencies.quick-error] +version = "2.0.1" [dependencies.weezl] -version = "0.1.0" +version = "0.1.10" +optional = true + +[dependencies.zstd] +version = "0.13" +optional = true + +[dependencies.zune-jpeg] +version = "0.4.17" +optional = true + +[dev-dependencies.crc32fast] +version = "1.5" [dev-dependencies.criterion] version = "0.3.1" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +[package] +name = "tiff" +version = "0.10.3" +edition = "2021" +resolver = "2" + +# note: when changed, also update test runner in `.github/workflows/rust.yml` +rust-version = "1.74.0" + +license = "MIT" +description = "TIFF decoding and encoding library in pure Rust" +authors = ["The image-rs Developers"] + +repository = "https://github.com/image-rs/image-tiff" +categories = ["multimedia::images", "multimedia::encoding"] + +exclude = ["tests/images/*", "tests/fuzz_images/*"] + +[dependencies] +half = { version = "2.4.1" } +quick-error = "2.0.1" + +# Rename to avoid confusion with the feature name. +fax34 = { package = "fax", version = "0.2.6", optional = true } +flate2 = { version = "1.0.20", optional = true } +weezl = { version = "0.1.10", optional = true } +zstd = { version = "0.13", optional = true } +zune-jpeg = { version = "0.4.17", optional = true } + +[dev-dependencies] +criterion = "0.3.1" +# We may already depend on this via flate2 +crc32fast = "1.5" + +[features] +default = ["deflate", "fax", "jpeg", "lzw"] + +# Compression algorithms +deflate = ["dep:flate2"] +fax = ["dep:fax34"] +jpeg = ["dep:zune-jpeg"] +lzw = ["dep:weezl"] +zstd = ["dep:zstd"] + +[[bench]] +name = "lzw" +harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/README.md clamav-1.4.6+dfsg/.cargo/vendor/tiff/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ # image-tiff -[![Build Status](https://github.com/image-rs/image-tiff/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-tiff/actions) +[![Build Status](https://github.com/image-rs/image-tiff/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/image-rs/image-tiff/actions) [![Documentation](https://docs.rs/tiff/badge.svg)](https://docs.rs/tiff) [![Further crate info](https://img.shields.io/crates/v/tiff.svg)](https://crates.io/crates/tiff) @@ -24,6 +24,7 @@ | `RGBPalette` | | | | `Mask` | | | | `CMYK` | CMYK(8\|16\|32\|64) | CMYK(32\|64) | +| `CMYKA` | CMYKA(8) | | | `YCbCr` | | | | `CIELab` | | | @@ -35,6 +36,9 @@ | LZW | ✓ | ✓ | | Deflate | ✓ | ✓ | | PackBits | ✓ | ✓ | +| Fax4 | ✓ | not yet | +| JPEG | ✓ | not yet | +| ZSTD | ✓ | not yet | ## Not yet supported diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/bytecast.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/bytecast.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/bytecast.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/bytecast.rs 2006-07-24 01:21:28.000000000 +0000 @@ -10,8 +10,13 @@ //! the unsafe code guidelines). //! //! TODO: Would like to use std-lib here. +// Until we implement predictors for f16, we don't need f16_as_ne_bytes. (Due to the macro we do +// not apply this directly to the functions). And rust-version is not new enough for `expect`. +#![allow(dead_code)] use std::{mem, slice}; +use half::f16; + macro_rules! integral_slice_as_bytes{($int:ty, $const:ident $(,$mut:ident)*) => { pub(crate) fn $const(slice: &[$int]) -> &[u8] { assert!(mem::align_of::<$int>() <= mem::size_of::<$int>()); @@ -31,4 +36,5 @@ integral_slice_as_bytes!(u64, u64_as_ne_bytes, u64_as_ne_mut_bytes); integral_slice_as_bytes!(i64, i64_as_ne_bytes, i64_as_ne_mut_bytes); integral_slice_as_bytes!(f32, f32_as_ne_bytes, f32_as_ne_mut_bytes); +integral_slice_as_bytes!(f16, f16_as_ne_bytes, f16_as_ne_mut_bytes); integral_slice_as_bytes!(f64, f64_as_ne_bytes, f64_as_ne_mut_bytes); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/cycles.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/cycles.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/cycles.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/cycles.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,169 @@ +use crate::{tags::IfdPointer, TiffError, TiffFormatError}; +use std::collections::HashMap; + +/// The IFD structure of a TIFF file should be limited to a forest of entries, and a tree when we +/// only consider having a primary IFD and its children. There is up to one primary child of a node +/// that is the `next` entry in an IFD itself. Since we offer iteration over this chain we want to +/// detect when a new edge would introduce a cycle, such that callers can be guaranteed to +/// terminate iteration at some point even in malicious images. +/// +/// However, we are not necessarily visiting the IFDs in their topological order. +/// +/// Since we only consider one child, we run union find to assign each pointer to a known chain. +/// Then, when we insert a new edge we check if they belong to the same component. +#[derive(Default, Debug)] +pub struct IfdCycles { + /// The root of each component union. + component_union: HashMap, + links: HashMap, + chains: HashMap, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +struct ComponentId(u64); + +impl IfdCycles { + pub fn new() -> Self { + IfdCycles::default() + } + + pub fn insert_next( + &mut self, + from: IfdPointer, + to: Option, + ) -> Result { + let to_offset = to.map_or(0, |p| p.0); + + // For some reason we got + match self.links.get(&from) { + Some(existing) if *existing == to_offset => return Ok(false), + // We got here twice with two different reads of the same IFD. That is .. unusual and + // we interpret it as a cycle. + Some(_) => return Err(TiffError::FormatError(TiffFormatError::CycleInOffsets)), + None => self.links.insert(from, to_offset), + }; + + self.ensure_node(from); + + if let Some(to) = to { + self.ensure_node(to); + + let parent = self.nominal_component(from); + let child = self.nominal_component(to); + + if parent == child { + return Err(TiffError::FormatError(TiffFormatError::CycleInOffsets)); + } + + self.component_union.insert(child, parent); + } + + Ok(true) + } + + fn ensure_node(&mut self, ifd: IfdPointer) { + self.chains.entry(ifd).or_insert_with(|| { + let id = ComponentId(self.component_union.len() as u64); + self.component_union.insert(id, id); + id + }); + } + + fn nominal_component(&mut self, node: IfdPointer) -> ComponentId { + let id = self.chains[&node]; + + let nomimal = { + let mut iter = id; + + loop { + let parent = self.component_union[&iter]; + + if parent == iter { + break parent; + } + + iter = parent; + } + }; + + if nomimal != id { + // Compress. + let mut iter = id; + + loop { + let parent = self.component_union[&iter]; + + if parent == iter { + break; + } + + self.component_union.insert(iter, nomimal); + iter = parent; + } + } + + nomimal + } +} + +#[test] +fn cycles_are_detected() { + let mut cycles = IfdCycles::new(); + + cycles + .insert_next(IfdPointer(0x20), Some(IfdPointer(0x800))) + .expect("non-existing link is valid"); + + cycles + .insert_next(IfdPointer(0x800), Some(IfdPointer(0x20))) + .expect_err("cycle must be detected"); +} + +#[test] +fn reflective_cycle() { + let mut cycles = IfdCycles::new(); + + cycles + .insert_next(IfdPointer(0x20), Some(IfdPointer(0x20))) + .expect_err("self-referential cycle must be detected"); +} + +#[test] +fn late_cycle() { + let mut cycles = IfdCycles::new(); + + cycles + .insert_next(IfdPointer(0x20), Some(IfdPointer(0x40))) + .expect("non-existing link is valid"); + + cycles + .insert_next(IfdPointer(0x60), Some(IfdPointer(0x80))) + .expect("non-existing link is valid"); + cycles + .insert_next(IfdPointer(0x80), Some(IfdPointer(0x20))) + .expect("non-existing link is valid"); + + cycles + .insert_next(IfdPointer(0x40), Some(IfdPointer(0x60))) + .expect_err("non-existing link is valid"); +} + +#[test] +fn odd_cycle() { + let mut cycles = IfdCycles::new(); + + cycles + .insert_next(IfdPointer(0x20), Some(IfdPointer(0x40))) + .expect("non-existing link is valid"); + + cycles + .insert_next(IfdPointer(0x60), Some(IfdPointer(0x80))) + .expect("non-existing link is valid"); + cycles + .insert_next(IfdPointer(0x80), Some(IfdPointer(0x20))) + .expect("non-existing link is valid"); + + cycles + .insert_next(IfdPointer(0x40), Some(IfdPointer(0x80))) + .expect_err("non-existing link is valid"); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/ifd.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/ifd.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/ifd.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/ifd.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,18 +1,17 @@ //! Function for reading TIFF tags use std::collections::HashMap; -use std::convert::{TryFrom, TryInto}; use std::io::{self, Read, Seek}; use std::mem; use std::str; -use super::stream::{ByteOrder, EndianReader, SmartReader}; -use crate::tags::{Tag, Type}; +use super::stream::{ByteOrder, EndianReader}; +use crate::tags::{IfdPointer, Tag, Type}; use crate::{TiffError, TiffFormatError, TiffResult}; use self::Value::{ Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig, - Short, Signed, SignedBig, Unsigned, UnsignedBig, + Short, Signed, SignedBig, SignedByte, SignedShort, Unsigned, UnsignedBig, }; #[allow(unused_qualifications)] @@ -21,6 +20,8 @@ pub enum Value { Byte(u8), Short(u16), + SignedByte(i8), + SignedShort(i16), Signed(i32), SignedBig(i64), Unsigned(u32), @@ -41,91 +42,117 @@ pub fn into_u8(self) -> TiffResult { match self { Byte(val) => Ok(val), - val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), + } + } + pub fn into_i8(self) -> TiffResult { + match self { + SignedByte(val) => Ok(val), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_u16(self) -> TiffResult { match self { + Byte(val) => Ok(val.into()), Short(val) => Ok(val), Unsigned(val) => Ok(u16::try_from(val)?), UnsignedBig(val) => Ok(u16::try_from(val)?), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), + } + } + + pub fn into_i16(self) -> TiffResult { + match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val), + Signed(val) => Ok(i16::try_from(val)?), + SignedBig(val) => Ok(i16::try_from(val)?), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_u32(self) -> TiffResult { match self { + Byte(val) => Ok(val.into()), Short(val) => Ok(val.into()), Unsigned(val) => Ok(val), UnsignedBig(val) => Ok(u32::try_from(val)?), Ifd(val) => Ok(val), IfdBig(val) => Ok(u32::try_from(val)?), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_i32(self) -> TiffResult { match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val.into()), Signed(val) => Ok(val), SignedBig(val) => Ok(i32::try_from(val)?), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_u64(self) -> TiffResult { match self { + Byte(val) => Ok(val.into()), Short(val) => Ok(val.into()), Unsigned(val) => Ok(val.into()), UnsignedBig(val) => Ok(val), Ifd(val) => Ok(val.into()), IfdBig(val) => Ok(val), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_i64(self) -> TiffResult { match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val.into()), Signed(val) => Ok(val.into()), SignedBig(val) => Ok(val), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_f32(self) -> TiffResult { match self { Float(val) => Ok(val), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_f64(self) -> TiffResult { match self { Double(val) => Ok(val), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), + } + } + + /// Turn this value into an `IfdPointer`. + /// + /// Notice that this does not take an argument, a 64-bit IFD is always allowed. If the + /// difference is crucial and you do not want to be permissive you're expected to filter this + /// out before. + /// + /// For compatibility the smaller sized tags should always be allowed i.e. you might use a + /// non-bigtiff's directory and its tag types and move it straight to a bigtiff. For instance + /// the SubIFD tag is defined as `LONG or IFD`: + /// + /// + pub fn into_ifd_pointer(self) -> TiffResult { + match self { + Unsigned(val) | Ifd(val) => Ok(IfdPointer(val.into())), + IfdBig(val) => Ok(IfdPointer(val)), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } pub fn into_string(self) -> TiffResult { match self { Ascii(val) => Ok(val), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -138,6 +165,8 @@ } Ok(new_vec) } + Byte(val) => Ok(vec![val.into()]), + Short(val) => Ok(vec![val.into()]), Unsigned(val) => Ok(vec![val]), UnsignedBig(val) => Ok(vec![u32::try_from(val)?]), Rational(numerator, denominator) => Ok(vec![numerator, denominator]), @@ -147,9 +176,7 @@ Ifd(val) => Ok(vec![val]), IfdBig(val) => Ok(vec![u32::try_from(val)?]), Ascii(val) => Ok(val.chars().map(u32::from).collect()), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -164,9 +191,7 @@ } Byte(val) => Ok(vec![val]), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -179,10 +204,9 @@ } Ok(new_vec) } + Byte(val) => Ok(vec![val.into()]), Short(val) => Ok(vec![val]), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -205,15 +229,15 @@ } Ok(new_vec) } + SignedByte(val) => Ok(vec![val.into()]), + SignedShort(val) => Ok(vec![val.into()]), Signed(val) => Ok(vec![val]), SignedBig(val) => Ok(vec![i32::try_from(val)?]), SRational(numerator, denominator) => Ok(vec![numerator, denominator]), SRationalBig(numerator, denominator) => { Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?]) } - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -227,9 +251,7 @@ Ok(new_vec) } Float(val) => Ok(vec![val]), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -243,9 +265,7 @@ Ok(new_vec) } Double(val) => Ok(vec![val]), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -258,6 +278,8 @@ } Ok(new_vec) } + Byte(val) => Ok(vec![val.into()]), + Short(val) => Ok(vec![val.into()]), Unsigned(val) => Ok(vec![val.into()]), UnsignedBig(val) => Ok(vec![val]), Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), @@ -265,9 +287,7 @@ Ifd(val) => Ok(vec![val.into()]), IfdBig(val) => Ok(vec![val]), Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()), - val => Err(TiffError::FormatError( - TiffFormatError::UnsignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } @@ -290,15 +310,26 @@ } Ok(new_vec) } + SignedByte(val) => Ok(vec![val.into()]), + SignedShort(val) => Ok(vec![val.into()]), Signed(val) => Ok(vec![val.into()]), SignedBig(val) => Ok(vec![val]), SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]), - val => Err(TiffError::FormatError( - TiffFormatError::SignedIntegerExpected(val), - )), + _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), } } + + pub fn into_ifd_vec(self) -> TiffResult> { + let vec = match self { + Unsigned(val) | Ifd(val) => return Ok(vec![IfdPointer(val.into())]), + IfdBig(val) => return Ok(vec![IfdPointer(val)]), + List(vec) => vec, + _ => return Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)), + }; + + vec.into_iter().map(Self::into_ifd_pointer).collect() + } } #[derive(Clone)] @@ -319,9 +350,9 @@ impl Entry { pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry { - let mut offset = offset.to_vec(); - offset.append(&mut vec![0; 4]); - Entry::new_u64(type_, count.into(), offset[..].try_into().unwrap()) + let mut entry_off = [0u8; 8]; + entry_off[..4].copy_from_slice(&offset); + Entry::new_u64(type_, count.into(), entry_off) } pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry { @@ -332,23 +363,35 @@ } } + pub fn field_type(&self) -> Type { + self.type_ + } + + pub fn count(&self) -> u64 { + self.count + } + + pub(crate) fn offset(&self) -> &[u8] { + &self.offset + } + /// Returns a mem_reader for the offset/value field - fn r(&self, byte_order: ByteOrder) -> SmartReader>> { - SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order) + fn r(&self, byte_order: ByteOrder) -> EndianReader>> { + EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order) } - pub fn val( + pub(crate) fn val( &self, limits: &super::Limits, bigtiff: bool, - reader: &mut SmartReader, + reader: &mut EndianReader, ) -> TiffResult { // Case 1: there are no values so we can return immediately. if self.count == 0 { return Ok(List(Vec::new())); } - let bo = reader.byte_order(); + let bo = reader.byte_order; let tag_size = match self.type_ { Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1, @@ -401,11 +444,11 @@ // 2b: the value is at most 4 bytes or doesn't fit in the offset field. return Ok(match self.type_ { - Type::BYTE => Unsigned(u32::from(self.offset[0])), - Type::SBYTE => Signed(i32::from(self.offset[0] as i8)), + Type::BYTE => Byte(self.offset[0]), + Type::SBYTE => SignedByte(self.offset[0] as i8), Type::UNDEFINED => Byte(self.offset[0]), - Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)), - Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)), + Type::SHORT => Short(self.r(bo).read_u16()?), + Type::SSHORT => SignedShort(self.r(bo).read_i16()?), Type::LONG => Unsigned(self.r(bo).read_u32()?), Type::SLONG => Signed(self.r(bo).read_i32()?), Type::FLOAT => Float(self.r(bo).read_f32()?), @@ -451,7 +494,7 @@ Type::SBYTE => return offset_to_sbytes(self.count as usize, self), Type::ASCII => { let mut buf = vec![0; self.count as usize]; - self.r(bo).read_exact(&mut buf)?; + buf.copy_from_slice(&self.offset[..self.count as usize]); if buf.is_ascii() && buf.ends_with(&[0]) { let v = str::from_utf8(&buf)?; let v = v.trim_matches(char::from(0)); @@ -480,7 +523,7 @@ let mut r = self.r(bo); let mut v = Vec::new(); for _ in 0..self.count { - v.push(Signed(i32::from(r.read_i16()?))); + v.push(SignedShort(r.read_i16()?)); } return Ok(List(v)); } @@ -533,17 +576,17 @@ // at a different endianess of file/computer. Type::BYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { let mut buf = [0; 1]; - reader.read_exact(&mut buf)?; - Ok(UnsignedBig(u64::from(buf[0]))) + reader.inner().read_exact(&mut buf)?; + Ok(Byte(buf[0])) }), Type::SBYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { - Ok(SignedBig(i64::from(reader.read_i8()?))) + Ok(SignedByte(reader.read_i8()?)) }), Type::SHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { - Ok(UnsignedBig(u64::from(reader.read_u16()?))) + Ok(Short(reader.read_u16()?)) }), Type::SSHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { - Ok(SignedBig(i64::from(reader.read_i16()?))) + Ok(SignedShort(reader.read_i16()?)) }), Type::LONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { Ok(Unsigned(reader.read_u32()?)) @@ -582,7 +625,7 @@ Type::UNDEFINED => { self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { let mut buf = [0; 1]; - reader.read_exact(&mut buf)?; + reader.inner().read_exact(&mut buf)?; Ok(Byte(buf[0])) }) } @@ -599,7 +642,7 @@ } let mut out = vec![0; n]; - reader.read_exact(&mut out)?; + reader.inner().read_exact(&mut out)?; // Strings may be null-terminated, so we trim anything downstream of the null byte if let Some(first) = out.iter().position(|&b| b == 0) { out.truncate(first); @@ -616,12 +659,12 @@ bo: ByteOrder, bigtiff: bool, limits: &super::Limits, - reader: &mut SmartReader, + reader: &mut EndianReader, decode_fn: F, ) -> TiffResult where R: Read + Seek, - F: Fn(&mut SmartReader) -> TiffResult, + F: Fn(&mut EndianReader) -> TiffResult, { let value_count = usize::try_from(value_count)?; if value_count > limits.decoding_buffer_size / mem::size_of::() { @@ -667,4 +710,6 @@ } /// Type representing an Image File Directory +#[doc(hidden)] +#[deprecated = "Use struct `tiff::Directory` instead which contains all fields relevant to an Image File Directory, including the offset to the next directory"] pub type Directory = HashMap; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/image.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/image.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/image.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/image.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,14 +1,17 @@ -use super::ifd::{Directory, Value}; -use super::stream::{ByteOrder, DeflateReader, LZWReader, PackBitsReader}; +use super::ifd::Value; +use super::stream::PackBitsReader; use super::tag_reader::TagReader; -use super::{fp_predict_f32, fp_predict_f64, DecodingBuffer, Limits}; -use super::{stream::SmartReader, ChunkType}; +use super::ChunkType; +use super::{predict_f16, predict_f32, predict_f64, ValueReader}; use crate::tags::{ CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, SampleFormat, Tag, }; -use crate::{ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError}; -use std::convert::TryFrom; +use crate::{ + ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError, +}; + use std::io::{self, Cursor, Read, Seek}; +use std::num::NonZeroUsize; use std::sync::Arc; #[derive(Debug)] @@ -28,10 +31,10 @@ impl TileAttributes { pub fn tiles_across(&self) -> usize { - (self.image_width + self.tile_width - 1) / self.tile_width + self.image_width.div_ceil(self.tile_width) } pub fn tiles_down(&self) -> usize { - (self.image_height + self.tile_length - 1) / self.tile_length + self.image_height.div_ceil(self.tile_length) } fn padding_right(&self) -> usize { (self.tile_width - self.image_width % self.tile_width) % self.tile_width @@ -65,9 +68,8 @@ pub width: u32, pub height: u32, pub bits_per_sample: u8, - #[allow(unused)] pub samples: u16, - pub sample_format: Vec, + pub sample_format: SampleFormat, pub photometric_interpretation: PhotometricInterpretation, pub compression_method: CompressionMethod, pub predictor: Predictor, @@ -82,17 +84,10 @@ impl Image { pub fn from_reader( - reader: &mut SmartReader, + decoder: &mut ValueReader, ifd: Directory, - limits: &Limits, - bigtiff: bool, ) -> TiffResult { - let mut tag_reader = TagReader { - reader, - limits, - ifd: &ifd, - bigtiff, - }; + let mut tag_reader = TagReader { decoder, ifd: &ifd }; let width = tag_reader.require_tag(Tag::ImageWidth)?.into_u32()?; let height = tag_reader.require_tag(Tag::ImageLength)?.into_u32()?; @@ -117,7 +112,7 @@ }; let jpeg_tables = if compression_method == CompressionMethod::ModernJPEG - && ifd.contains_key(&Tag::JPEGTables) + && ifd.contains(Tag::JPEGTables) { let vec = tag_reader .find_tag(Tag::JPEGTables)? @@ -155,9 +150,9 @@ return Err(TiffUnsupportedError::UnsupportedSampleFormat(sample_format).into()); } - sample_format + sample_format[0] } - None => vec![SampleFormat::Uint], + None => SampleFormat::Uint, }; let bits_per_sample: Vec = tag_reader @@ -172,8 +167,9 @@ )); } - // This library (and libtiff) do not support mixed sample formats. - if bits_per_sample.iter().any(|&b| b != bits_per_sample[0]) { + // This library (and libtiff) do not support mixed sample formats and zero bits per sample + // doesn't make sense. + if bits_per_sample.iter().any(|&b| b != bits_per_sample[0]) || bits_per_sample[0] == 0 { return Err(TiffUnsupportedError::InconsistentBitsPerSample(bits_per_sample).into()); } @@ -211,10 +207,10 @@ let strip_decoder; let tile_attributes; match ( - ifd.contains_key(&Tag::StripByteCounts), - ifd.contains_key(&Tag::StripOffsets), - ifd.contains_key(&Tag::TileByteCounts), - ifd.contains_key(&Tag::TileOffsets), + ifd.contains(Tag::StripByteCounts), + ifd.contains(Tag::StripOffsets), + ifd.contains(Tag::TileByteCounts), + ifd.contains(Tag::TileOffsets), ) { (true, true, false, false) => { chunk_type = ChunkType::Strip; @@ -331,6 +327,7 @@ }, PhotometricInterpretation::CMYK => match self.samples { 4 => Ok(ColorType::CMYK(self.bits_per_sample)), + 5 => Ok(ColorType::CMYKA(self.bits_per_sample)), _ => Err(TiffError::UnsupportedError( TiffUnsupportedError::InterpretationWithBits( self.photometric_interpretation, @@ -347,14 +344,22 @@ ), )), }, - PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero - if self.samples == 1 => - { - Ok(ColorType::Gray(self.bits_per_sample)) + // TODO: treatment of WhiteIsZero is not quite consistent with `invert_colors` that is + // later called when that interpretation is read. That function does not support + // Multiband as a color type and will error. It's unclear how to resolve that exactly. + PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero => { + match self.samples { + 1 => Ok(ColorType::Gray(self.bits_per_sample)), + _ => Ok(ColorType::Multiband { + bit_depth: self.bits_per_sample, + num_samples: self.samples, + }), + } } - // TODO: this is bad we should not fail at this point - _ => Err(TiffError::UnsupportedError( + PhotometricInterpretation::RGBPalette + | PhotometricInterpretation::TransparencyMask + | PhotometricInterpretation::CIELab => Err(TiffError::UnsupportedError( TiffUnsupportedError::InterpretationWithBits( self.photometric_interpretation, vec![self.bits_per_sample; self.samples as usize], @@ -363,23 +368,48 @@ } } + pub(crate) fn minimum_row_stride(&self, dims: (u32, u32)) -> Option { + let (width, height) = dims; + + let row_stride = u64::from(width) + .saturating_mul(self.samples_per_pixel() as u64) + .saturating_mul(self.bits_per_sample as u64) + .div_ceil(8); + + // Note: row stride should be smaller than the len if we have an actual buffer. If there + // are no pixels in the buffer (height _or_ width is 0) then the stride is not well defined + // and we return `None`. + (height > 0) + .then_some(row_stride as usize) + .and_then(NonZeroUsize::new) + } + fn create_reader<'r, R: 'r + Read>( reader: R, - photometric_interpretation: PhotometricInterpretation, compression_method: CompressionMethod, compressed_length: u64, - jpeg_tables: Option<&[u8]>, + // FIXME: these should be `expect` attributes or we choose another way of passing them. + #[cfg_attr(not(feature = "jpeg"), allow(unused_variables))] jpeg_tables: Option<&[u8]>, + #[cfg_attr(not(feature = "fax"), allow(unused_variables))] dimensions: (u32, u32), ) -> TiffResult> { Ok(match compression_method { CompressionMethod::None => Box::new(reader), - CompressionMethod::LZW => { - Box::new(LZWReader::new(reader, usize::try_from(compressed_length)?)) - } + #[cfg(feature = "lzw")] + CompressionMethod::LZW => Box::new(super::stream::LZWReader::new( + reader, + usize::try_from(compressed_length)?, + )), + #[cfg(feature = "zstd")] + CompressionMethod::ZSTD => Box::new(zstd::Decoder::new(reader)?), CompressionMethod::PackBits => Box::new(PackBitsReader::new(reader, compressed_length)), + #[cfg(feature = "deflate")] CompressionMethod::Deflate | CompressionMethod::OldDeflate => { - Box::new(DeflateReader::new(reader)) + Box::new(super::stream::DeflateReader::new(reader)) } + #[cfg(feature = "jpeg")] CompressionMethod::ModernJPEG => { + use zune_jpeg::zune_core; + if jpeg_tables.is_some() && compressed_length < 2 { return Err(TiffError::FormatError( TiffFormatError::InvalidTagValueType(Tag::JPEGTables), @@ -396,7 +426,7 @@ // bytes of the remaining JPEG data is removed because it follows `jpeg_tables`. // Similary, `jpeg_tables` ends with a `EOI` (HEX: `0xFFD9`) or __end of image__ marker, // this has to be removed as well (last two bytes of `jpeg_tables`). - let jpeg_reader = match jpeg_tables { + let mut jpeg_reader = match jpeg_tables { Some(jpeg_tables) => { let mut reader = reader.take(compressed_length); reader.read_exact(&mut [0; 2])?; @@ -409,40 +439,31 @@ None => Box::new(reader.take(compressed_length)), }; - let mut decoder = jpeg::Decoder::new(jpeg_reader); + let mut jpeg_data = Vec::new(); + jpeg_reader.read_to_end(&mut jpeg_data)?; - match photometric_interpretation { - PhotometricInterpretation::RGB => { - decoder.set_color_transform(jpeg::ColorTransform::RGB) - } - PhotometricInterpretation::WhiteIsZero => { - decoder.set_color_transform(jpeg::ColorTransform::None) - } - PhotometricInterpretation::BlackIsZero => { - decoder.set_color_transform(jpeg::ColorTransform::None) - } - PhotometricInterpretation::TransparencyMask => { - decoder.set_color_transform(jpeg::ColorTransform::None) - } - PhotometricInterpretation::CMYK => { - decoder.set_color_transform(jpeg::ColorTransform::CMYK) - } - PhotometricInterpretation::YCbCr => { - decoder.set_color_transform(jpeg::ColorTransform::YCbCr) - } - photometric_interpretation => { - return Err(TiffError::UnsupportedError( - TiffUnsupportedError::UnsupportedInterpretation( - photometric_interpretation, - ), - )); - } + let mut decoder = zune_jpeg::JpegDecoder::new(jpeg_data); + let mut options: zune_core::options::DecoderOptions = Default::default(); + + // Disable color conversion by setting the output colorspace to the input + // colorspace. + decoder.decode_headers()?; + if let Some(colorspace) = decoder.get_input_colorspace() { + options = options.jpeg_set_out_colorspace(colorspace); } + decoder.set_options(options); + let data = decoder.decode()?; Box::new(Cursor::new(data)) } + #[cfg(feature = "fax")] + CompressionMethod::Fax4 => Box::new(super::stream::Group4Reader::new( + dimensions, + reader, + compressed_length, + )?), method => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedCompressionMethod(method), @@ -541,28 +562,43 @@ pub(crate) fn expand_chunk( &self, - reader: impl Read, - mut buffer: DecodingBuffer, - output_width: usize, - byte_order: ByteOrder, + reader: &mut ValueReader, + buf: &mut [u8], + output_row_stride: usize, chunk_index: u32, - limits: &Limits, ) -> TiffResult<()> { - // Validate that the provided buffer is of the expected type. + let ValueReader { + reader, + bigtiff: _, + limits, + } = reader; + + let byte_order = reader.byte_order; + let reader = reader.inner(); + + // Validate that the color type is supported. let color_type = self.colortype()?; - match (color_type, &buffer) { - (ColorType::RGB(n), _) - | (ColorType::RGBA(n), _) - | (ColorType::CMYK(n), _) - | (ColorType::YCbCr(n), _) - | (ColorType::Gray(n), _) - if usize::from(n) == buffer.byte_len() * 8 => {} - (ColorType::Gray(n), DecodingBuffer::U8(_)) if n < 8 => match self.predictor { + match color_type { + ColorType::RGB(n) + | ColorType::RGBA(n) + | ColorType::CMYK(n) + | ColorType::CMYKA(n) + | ColorType::YCbCr(n) + | ColorType::Gray(n) + | ColorType::Multiband { + bit_depth: n, + num_samples: _, + } if n == 8 || n == 16 || n == 32 || n == 64 => {} + ColorType::Gray(n) + | ColorType::Multiband { + bit_depth: n, + num_samples: _, + } if n < 8 => match self.predictor { Predictor::None => {} Predictor::Horizontal => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::HorizontalPredictor(color_type), - )) + )); } Predictor::FloatingPoint => { return Err(TiffError::UnsupportedError( @@ -570,23 +606,25 @@ )); } }, - (type_, _) => { + type_ => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedColorType(type_), - )) + )); } } // Validate that the predictor is supported for the sample type. - match (self.predictor, &buffer) { - (Predictor::Horizontal, DecodingBuffer::F32(_)) - | (Predictor::Horizontal, DecodingBuffer::F64(_)) => { + match (self.predictor, self.sample_format) { + ( + Predictor::Horizontal, + SampleFormat::Int | SampleFormat::Uint | SampleFormat::IEEEFP, + ) => {} + (Predictor::Horizontal, _) => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::HorizontalPredictor(color_type), )); } - (Predictor::FloatingPoint, DecodingBuffer::F32(_)) - | (Predictor::FloatingPoint, DecodingBuffer::F64(_)) => {} + (Predictor::FloatingPoint, SampleFormat::IEEEFP) => {} (Predictor::FloatingPoint, _) => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::FloatingPointPredictor(color_type), @@ -605,7 +643,6 @@ return Err(TiffError::LimitsExceeded); } - let byte_len = buffer.byte_len(); let compression_method = self.compression_method; let photometric_interpretation = self.photometric_interpretation; let predictor = self.predictor; @@ -614,67 +651,82 @@ let chunk_dims = self.chunk_dimensions()?; let data_dims = self.chunk_data_dimensions(chunk_index)?; - let padding_right = chunk_dims.0 - data_dims.0; + let chunk_row_bits = (u64::from(chunk_dims.0) * u64::from(self.bits_per_sample)) + .checked_mul(samples as u64) + .ok_or(TiffError::LimitsExceeded)?; + let chunk_row_bytes: usize = chunk_row_bits.div_ceil(8).try_into()?; + + let data_row_bits = (u64::from(data_dims.0) * u64::from(self.bits_per_sample)) + .checked_mul(samples as u64) + .ok_or(TiffError::LimitsExceeded)?; + let data_row_bytes: usize = data_row_bits.div_ceil(8).try_into()?; + + // TODO: Should these return errors instead? + assert!(output_row_stride >= data_row_bytes); + assert!(buf.len() >= output_row_stride * (data_dims.1 as usize - 1) + data_row_bytes); let mut reader = Self::create_reader( reader, - photometric_interpretation, compression_method, *compressed_bytes, self.jpeg_tables.as_deref().map(|a| &**a), + chunk_dims, )?; - if output_width == data_dims.0 as usize && padding_right == 0 { - let total_samples = data_dims.0 as usize * data_dims.1 as usize * samples; - let tile = &mut buffer.as_bytes_mut()[..total_samples * byte_len]; + if output_row_stride == chunk_row_bytes { + let tile = &mut buf[..chunk_row_bytes * data_dims.1 as usize]; reader.read_exact(tile)?; - for row in 0..data_dims.1 as usize { - let row_start = row * output_width * samples; - let row_end = (row + 1) * output_width * samples; - let row = buffer.subrange(row_start..row_end); - super::fix_endianness_and_predict(row, samples, byte_order, predictor); + for row in tile.chunks_mut(chunk_row_bytes) { + super::fix_endianness_and_predict( + row, + color_type.bit_depth(), + samples, + byte_order, + predictor, + ); } if photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - super::invert_colors(&mut buffer.subrange(0..total_samples), color_type); + super::invert_colors(tile, color_type, self.sample_format)?; } - } else if padding_right > 0 && self.predictor == Predictor::FloatingPoint { + } else if chunk_row_bytes > data_row_bytes && self.predictor == Predictor::FloatingPoint { // The floating point predictor shuffles the padding bytes into the encoded output, so // this case is handled specially when needed. - let mut encoded = vec![0u8; chunk_dims.0 as usize * samples * byte_len]; - - for row in 0..data_dims.1 as usize { - let row_start = row * output_width * samples; - let row_end = row_start + data_dims.0 as usize * samples; - + let mut encoded = vec![0u8; chunk_row_bytes]; + for row in buf.chunks_mut(output_row_stride).take(data_dims.1 as usize) { reader.read_exact(&mut encoded)?; - match buffer.subrange(row_start..row_end) { - DecodingBuffer::F32(buf) => fp_predict_f32(&mut encoded, buf, samples), - DecodingBuffer::F64(buf) => fp_predict_f64(&mut encoded, buf, samples), + + let row = &mut row[..data_row_bytes]; + match color_type.bit_depth() { + 16 => predict_f16(&mut encoded, row, samples), + 32 => predict_f32(&mut encoded, row, samples), + 64 => predict_f64(&mut encoded, row, samples), _ => unreachable!(), } if photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - super::invert_colors(&mut buffer.subrange(row_start..row_end), color_type); + super::invert_colors(row, color_type, self.sample_format)?; } } } else { - for row in 0..data_dims.1 as usize { - let row_start = row * output_width * samples; - let row_end = row_start + data_dims.0 as usize * samples; - - let row = &mut buffer.as_bytes_mut()[(row_start * byte_len)..(row_end * byte_len)]; + for row in buf.chunks_mut(output_row_stride).take(data_dims.1 as usize) { + let row = &mut row[..data_row_bytes]; reader.read_exact(row)?; // Skip horizontal padding - if padding_right > 0 { - let len = u64::try_from(padding_right as usize * samples * byte_len)?; + if chunk_row_bytes > data_row_bytes { + let len = u64::try_from(chunk_row_bytes - data_row_bytes)?; io::copy(&mut reader.by_ref().take(len), &mut io::sink())?; } - let mut row = buffer.subrange(row_start..row_end); - super::fix_endianness_and_predict(row.copy(), samples, byte_order, predictor); + super::fix_endianness_and_predict( + row, + color_type.bit_depth(), + samples, + byte_order, + predictor, + ); if photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - super::invert_colors(&mut row, color_type); + super::invert_colors(row, color_type, self.sample_format)?; } } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,21 +1,22 @@ -use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; +use std::alloc::{Layout, LayoutError}; +use std::collections::BTreeMap; use std::io::{self, Read, Seek}; -use std::ops::Range; +use std::num::NonZeroUsize; +use crate::tags::{ + CompressionMethod, IfdPointer, PhotometricInterpretation, PlanarConfiguration, Predictor, + SampleFormat, Tag, Type, +}; use crate::{ - bytecast, ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError, + bytecast, ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, + UsageError, }; +use half::f16; -use self::ifd::Directory; use self::image::Image; -use crate::tags::{ - CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, SampleFormat, - Tag, Type, -}; - -use self::stream::{ByteOrder, EndianReader, SmartReader}; +use self::stream::{ByteOrder, EndianReader}; +mod cycles; pub mod ifd; mod image; mod stream; @@ -32,6 +33,8 @@ U32(Vec), /// A vector of 64 bit unsigned ints U64(Vec), + /// A vector of 16 bit IEEE floats (held in u16) + F16(Vec), /// A vector of 32 bit IEEE floats F32(Vec), /// A vector of 64 bit IEEE floats @@ -95,6 +98,14 @@ } } + fn new_f16(size: usize, limits: &Limits) -> TiffResult { + if size > limits.decoding_buffer_size / std::mem::size_of::() { + Err(TiffError::LimitsExceeded) + } else { + Ok(DecodingResult::F16(vec![f16::ZERO; size])) + } + } + fn new_i8(size: usize, limits: &Limits) -> TiffResult { if size > limits.decoding_buffer_size / std::mem::size_of::() { Err(TiffError::LimitsExceeded) @@ -127,12 +138,13 @@ } } - pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer { + pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer<'_> { match *self { DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]), DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]), DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]), DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]), + DecodingResult::F16(ref mut buf) => DecodingBuffer::F16(&mut buf[start..]), DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]), DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]), DecodingResult::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[start..]), @@ -153,6 +165,8 @@ U32(&'a mut [u32]), /// A slice of 64 bit unsigned ints U64(&'a mut [u64]), + /// A slice of 16 bit IEEE floats + F16(&'a mut [f16]), /// A slice of 32 bit IEEE floats F32(&'a mut [f32]), /// A slice of 64 bit IEEE floats @@ -168,57 +182,6 @@ } impl<'a> DecodingBuffer<'a> { - fn byte_len(&self) -> usize { - match *self { - DecodingBuffer::U8(_) => 1, - DecodingBuffer::U16(_) => 2, - DecodingBuffer::U32(_) => 4, - DecodingBuffer::U64(_) => 8, - DecodingBuffer::F32(_) => 4, - DecodingBuffer::F64(_) => 8, - DecodingBuffer::I8(_) => 1, - DecodingBuffer::I16(_) => 2, - DecodingBuffer::I32(_) => 4, - DecodingBuffer::I64(_) => 8, - } - } - - fn copy<'b>(&'b mut self) -> DecodingBuffer<'b> - where - 'a: 'b, - { - match *self { - DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(buf), - DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(buf), - DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(buf), - DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf), - DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf), - DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf), - DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(buf), - DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(buf), - DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(buf), - DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(buf), - } - } - - fn subrange<'b>(&'b mut self, range: Range) -> DecodingBuffer<'b> - where - 'a: 'b, - { - match *self { - DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[range]), - DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[range]), - DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[range]), - DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[range]), - DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[range]), - DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[range]), - DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[range]), - DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[range]), - DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[range]), - DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[range]), - } - } - fn as_bytes_mut(&mut self) -> &mut [u8] { match self { DecodingBuffer::U8(ref mut buf) => buf, @@ -229,12 +192,95 @@ DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf), DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf), DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf), + DecodingBuffer::F16(buf) => bytecast::f16_as_ne_mut_bytes(buf), DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf), DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf), } } } +/// Information on the byte buffer that should be supplied to the decoder. +/// +/// This is relevant for [`Decoder::read_image_bytes`] and [`Decoder::read_chunk_bytes`] where the +/// caller provided buffer must fit the expectations of the decoder to be filled with data from the +/// current image. +#[non_exhaustive] +pub struct BufferLayoutPreference { + /// Minimum byte size of the buffer to read image data. + pub len: usize, + /// Minimum number of bytes to represent a row of image data of the requested content. + pub row_stride: Option, +} + +/// The count and matching discriminant for a `DecodingBuffer`. +#[derive(Clone)] +enum DecodingExtent { + U8(usize), + U16(usize), + U32(usize), + U64(usize), + F16(usize), + F32(usize), + F64(usize), + I8(usize), + I16(usize), + I32(usize), + I64(usize), +} + +impl DecodingExtent { + fn to_result_buffer(&self, limits: &Limits) -> TiffResult { + match *self { + DecodingExtent::U8(count) => DecodingResult::new_u8(count, limits), + DecodingExtent::U16(count) => DecodingResult::new_u16(count, limits), + DecodingExtent::U32(count) => DecodingResult::new_u32(count, limits), + DecodingExtent::U64(count) => DecodingResult::new_u64(count, limits), + DecodingExtent::F16(count) => DecodingResult::new_f16(count, limits), + DecodingExtent::F32(count) => DecodingResult::new_f32(count, limits), + DecodingExtent::F64(count) => DecodingResult::new_f64(count, limits), + DecodingExtent::I8(count) => DecodingResult::new_i8(count, limits), + DecodingExtent::I16(count) => DecodingResult::new_i16(count, limits), + DecodingExtent::I32(count) => DecodingResult::new_i32(count, limits), + DecodingExtent::I64(count) => DecodingResult::new_i64(count, limits), + } + } + + fn preferred_layout(self) -> TiffResult { + fn overflow(_: LayoutError) -> TiffError { + TiffError::LimitsExceeded + } + + match self { + DecodingExtent::U8(count) => Layout::array::(count), + DecodingExtent::U16(count) => Layout::array::(count), + DecodingExtent::U32(count) => Layout::array::(count), + DecodingExtent::U64(count) => Layout::array::(count), + DecodingExtent::F16(count) => Layout::array::(count), + DecodingExtent::F32(count) => Layout::array::(count), + DecodingExtent::F64(count) => Layout::array::(count), + DecodingExtent::I8(count) => Layout::array::(count), + DecodingExtent::I16(count) => Layout::array::(count), + DecodingExtent::I32(count) => Layout::array::(count), + DecodingExtent::I64(count) => Layout::array::(count), + } + .map_err(overflow) + } + + fn assert_layout(self, buffer: usize) -> TiffResult<()> { + let needed_bytes = self.preferred_layout()?.size(); + if buffer < needed_bytes { + Err(TiffError::UsageError( + UsageError::InsufficientOutputBufferSize { + needed: needed_bytes, + provided: buffer, + }, + )) + } else { + Ok(()) + } + } +} + #[derive(Debug, Copy, Clone, PartialEq)] /// Chunk type of the internal representation pub enum ChunkType { @@ -244,6 +290,7 @@ /// Decoding limits #[derive(Clone, Debug)] +#[non_exhaustive] pub struct Limits { /// The maximum size of any `DecodingResult` in bytes, the default is /// 256MiB. If the entire image is decoded at once, then this will @@ -256,10 +303,6 @@ /// Maximum size for intermediate buffer which may be used to limit the amount of data read per /// segment even if the entire image is decoded at once. pub intermediate_buffer_size: usize, - /// The purpose of this is to prevent all the fields of the struct from - /// being public, as this would make adding new fields a major version - /// bump. - _non_exhaustive: (), } impl Limits { @@ -272,10 +315,9 @@ /// naturally, the machine running the program does not have infinite memory. pub fn unlimited() -> Limits { Limits { - decoding_buffer_size: usize::max_value(), - ifd_value_size: usize::max_value(), - intermediate_buffer_size: usize::max_value(), - _non_exhaustive: (), + decoding_buffer_size: usize::MAX, + ifd_value_size: usize::MAX, + intermediate_buffer_size: usize::MAX, } } } @@ -286,7 +328,6 @@ decoding_buffer_size: 256 * 1024 * 1024, intermediate_buffer_size: 128 * 1024 * 1024, ifd_value_size: 1024 * 1024, - _non_exhaustive: (), } } } @@ -299,91 +340,102 @@ where R: Read + Seek, { - reader: SmartReader, - bigtiff: bool, - limits: Limits, - next_ifd: Option, - ifd_offsets: Vec, - seen_ifds: HashSet, + /// There are grouped for borrow checker reasons. This allows us to implement methods that + /// borrow the stream access and the other fields mutably at the same time. + value_reader: ValueReader, + current_ifd: Option, + next_ifd: Option, + /// The IFDs we visited already in this chain of IFDs. + ifd_offsets: Vec, + /// Map from the ifd into the `ifd_offsets` ordered list. + seen_ifds: cycles::IfdCycles, image: Image, } -trait Wrapping { - fn wrapping_add(&self, other: Self) -> Self; -} - -impl Wrapping for u8 { - fn wrapping_add(&self, other: Self) -> Self { - u8::wrapping_add(*self, other) - } -} - -impl Wrapping for u16 { - fn wrapping_add(&self, other: Self) -> Self { - u16::wrapping_add(*self, other) - } +/// All the information needed to read and interpret byte slices from the underlying file, i.e. to +/// turn an entry of a tag into an `ifd::Value` or otherwise fetch arrays of similar types. Used +/// only as the type of the field [`Decoder::value_reader`] and passed to submodules. +#[derive(Debug)] +struct ValueReader { + reader: EndianReader, + bigtiff: bool, + limits: Limits, } -impl Wrapping for u32 { - fn wrapping_add(&self, other: Self) -> Self { - u32::wrapping_add(*self, other) - } +/// Reads a directory's tag values from an underlying stream. +pub struct IfdDecoder<'lt> { + inner: tag_reader::TagReader<'lt, dyn tag_reader::EntryDecoder + 'lt>, } -impl Wrapping for u64 { - fn wrapping_add(&self, other: Self) -> Self { - u64::wrapping_add(*self, other) - } -} - -impl Wrapping for i8 { - fn wrapping_add(&self, other: Self) -> Self { - i8::wrapping_add(*self, other) +fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: usize) { + match bit_depth { + 0..=8 => { + for i in samples..buf.len() { + buf[i] = buf[i].wrapping_add(buf[i - samples]); + } + } + 9..=16 => { + for i in (samples * 2..buf.len()).step_by(2) { + let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap()); + let p = u16::from_ne_bytes(buf[i - 2 * samples..][..2].try_into().unwrap()); + buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes()); + } + } + 17..=32 => { + for i in (samples * 4..buf.len()).step_by(4) { + let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap()); + let p = u32::from_ne_bytes(buf[i - 4 * samples..][..4].try_into().unwrap()); + buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes()); + } + } + 33..=64 => { + for i in (samples * 8..buf.len()).step_by(8) { + let v = u64::from_ne_bytes(buf[i..][..8].try_into().unwrap()); + let p = u64::from_ne_bytes(buf[i - 8 * samples..][..8].try_into().unwrap()); + buf[i..][..8].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes()); + } + } + _ => { + unreachable!("Caller should have validated arguments. Please file a bug.") + } } } -impl Wrapping for i16 { - fn wrapping_add(&self, other: Self) -> Self { - i16::wrapping_add(*self, other) +fn predict_f32(input: &mut [u8], output: &mut [u8], samples: usize) { + for i in samples..input.len() { + input[i] = input[i].wrapping_add(input[i - samples]); } -} -impl Wrapping for i32 { - fn wrapping_add(&self, other: Self) -> Self { - i32::wrapping_add(*self, other) + for (i, chunk) in output.chunks_mut(4).enumerate() { + chunk.copy_from_slice(&u32::to_ne_bytes(u32::from_be_bytes([ + input[i], + input[input.len() / 4 + i], + input[input.len() / 4 * 2 + i], + input[input.len() / 4 * 3 + i], + ]))); } } -impl Wrapping for i64 { - fn wrapping_add(&self, other: Self) -> Self { - i64::wrapping_add(*self, other) +fn predict_f16(input: &mut [u8], output: &mut [u8], samples: usize) { + for i in samples..input.len() { + input[i] = input[i].wrapping_add(input[i - samples]); } -} -fn rev_hpredict_nsamp(image: &mut [T], samples: usize) { - for col in samples..image.len() { - image[col] = image[col].wrapping_add(image[col - samples]); + for (i, chunk) in output.chunks_mut(2).enumerate() { + chunk.copy_from_slice(&u16::to_ne_bytes(u16::from_be_bytes([ + input[i], + input[input.len() / 2 + i], + ]))); } } -pub fn fp_predict_f32(input: &mut [u8], output: &mut [f32], samples: usize) { - rev_hpredict_nsamp(input, samples); - for i in 0..output.len() { - // TODO: use f32::from_be_bytes() when we can (version 1.40) - output[i] = f32::from_bits(u32::from_be_bytes([ - input[i], - input[input.len() / 4 + i], - input[input.len() / 4 * 2 + i], - input[input.len() / 4 * 3 + i], - ])); +fn predict_f64(input: &mut [u8], output: &mut [u8], samples: usize) { + for i in samples..input.len() { + input[i] = input[i].wrapping_add(input[i - samples]); } -} -pub fn fp_predict_f64(input: &mut [u8], output: &mut [f64], samples: usize) { - rev_hpredict_nsamp(input, samples); - for i in 0..output.len() { - // TODO: use f64::from_be_bytes() when we can (version 1.40) - output[i] = f64::from_bits(u64::from_be_bytes([ + for (i, chunk) in output.chunks_mut(8).enumerate() { + chunk.copy_from_slice(&u64::to_ne_bytes(u64::from_be_bytes([ input[i], input[input.len() / 8 + i], input[input.len() / 8 * 2 + i], @@ -392,128 +444,126 @@ input[input.len() / 8 * 5 + i], input[input.len() / 8 * 6 + i], input[input.len() / 8 * 7 + i], - ])); + ]))); } } fn fix_endianness_and_predict( - mut image: DecodingBuffer, + buf: &mut [u8], + bit_depth: u8, samples: usize, byte_order: ByteOrder, predictor: Predictor, ) { match predictor { Predictor::None => { - fix_endianness(&mut image, byte_order); + fix_endianness(buf, byte_order, bit_depth); } Predictor::Horizontal => { - fix_endianness(&mut image, byte_order); - match image { - DecodingBuffer::U8(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::U16(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::U32(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::U64(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::I8(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::I16(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::I32(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::I64(buf) => rev_hpredict_nsamp(buf, samples), - DecodingBuffer::F32(_) | DecodingBuffer::F64(_) => { - unreachable!("Caller should have validated arguments. Please file a bug.") - } - } + fix_endianness(buf, byte_order, bit_depth); + rev_hpredict_nsamp(buf, bit_depth, samples); } Predictor::FloatingPoint => { - let mut buffer_copy = image.as_bytes_mut().to_vec(); - match image { - DecodingBuffer::F32(buf) => fp_predict_f32(&mut buffer_copy, buf, samples), - DecodingBuffer::F64(buf) => fp_predict_f64(&mut buffer_copy, buf, samples), + let mut buffer_copy = buf.to_vec(); + match bit_depth { + 16 => predict_f16(&mut buffer_copy, buf, samples), + 32 => predict_f32(&mut buffer_copy, buf, samples), + 64 => predict_f64(&mut buffer_copy, buf, samples), _ => unreachable!("Caller should have validated arguments. Please file a bug."), } } } } -fn invert_colors_unsigned(buffer: &mut [T], max: T) -where - T: std::ops::Sub + std::ops::Sub + Copy, -{ - for datum in buffer.iter_mut() { - *datum = max - *datum - } -} - -fn invert_colors_fp(buffer: &mut [T], max: T) -where - T: std::ops::Sub + std::ops::Sub + Copy, -{ - for datum in buffer.iter_mut() { - // FIXME: assumes [0, 1) range for floats - *datum = max - *datum - } -} - -fn invert_colors(buf: &mut DecodingBuffer, color_type: ColorType) { - match (color_type, buf) { - (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { - invert_colors_unsigned(buffer, 0xffff_ffff_ffff_ffff); +fn invert_colors( + buf: &mut [u8], + color_type: ColorType, + sample_format: SampleFormat, +) -> TiffResult<()> { + match (color_type, sample_format) { + // Where pixels do not cross a byte boundary + (ColorType::Gray(1 | 2 | 4 | 8), SampleFormat::Uint) => { + for x in buf { + // Equivalent to both of the following: + // + // *x = 0xff - *x + // *x = !*x + // + // since -x = !x+1 + *x = !*x; + } } - (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => { - invert_colors_unsigned(buffer, 0xffff_ffff); + (ColorType::Gray(16), SampleFormat::Uint) => { + for x in buf.chunks_mut(2) { + let v = u16::from_ne_bytes(x.try_into().unwrap()); + x.copy_from_slice(&(0xffff - v).to_ne_bytes()); + } } - (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { - invert_colors_unsigned(buffer, 0xffff); + (ColorType::Gray(32), SampleFormat::Uint) => { + for x in buf.chunks_mut(4) { + let v = u32::from_ne_bytes(x.try_into().unwrap()); + x.copy_from_slice(&(0xffff_ffff - v).to_ne_bytes()); + } } - (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { - invert_colors_unsigned(buffer, 0xff); + (ColorType::Gray(64), SampleFormat::Uint) => { + for x in buf.chunks_mut(8) { + let v = u64::from_ne_bytes(x.try_into().unwrap()); + x.copy_from_slice(&(0xffff_ffff_ffff_ffff - v).to_ne_bytes()); + } } - (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => { - invert_colors_fp(buffer, 1.0); + (ColorType::Gray(32), SampleFormat::IEEEFP) => { + for x in buf.chunks_mut(4) { + let v = f32::from_ne_bytes(x.try_into().unwrap()); + x.copy_from_slice(&(1.0 - v).to_ne_bytes()); + } } - (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => { - invert_colors_fp(buffer, 1.0); + (ColorType::Gray(64), SampleFormat::IEEEFP) => { + for x in buf.chunks_mut(8) { + let v = f64::from_ne_bytes(x.try_into().unwrap()); + x.copy_from_slice(&(1.0 - v).to_ne_bytes()); + } + } + _ => { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnknownInterpretation, + )) } - _ => {} } + + Ok(()) } /// Fix endianness. If `byte_order` matches the host, then conversion is a no-op. -fn fix_endianness(buf: &mut DecodingBuffer, byte_order: ByteOrder) { +fn fix_endianness(buf: &mut [u8], byte_order: ByteOrder, bit_depth: u8) { match byte_order { - ByteOrder::LittleEndian => match buf { - DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} - DecodingBuffer::U16(b) => b.iter_mut().for_each(|v| *v = u16::from_le(*v)), - DecodingBuffer::I16(b) => b.iter_mut().for_each(|v| *v = i16::from_le(*v)), - DecodingBuffer::U32(b) => b.iter_mut().for_each(|v| *v = u32::from_le(*v)), - DecodingBuffer::I32(b) => b.iter_mut().for_each(|v| *v = i32::from_le(*v)), - DecodingBuffer::U64(b) => b.iter_mut().for_each(|v| *v = u64::from_le(*v)), - DecodingBuffer::I64(b) => b.iter_mut().for_each(|v| *v = i64::from_le(*v)), - DecodingBuffer::F32(b) => b - .iter_mut() - .for_each(|v| *v = f32::from_bits(u32::from_le(v.to_bits()))), - DecodingBuffer::F64(b) => b - .iter_mut() - .for_each(|v| *v = f64::from_bits(u64::from_le(v.to_bits()))), + ByteOrder::LittleEndian => match bit_depth { + 0..=8 => {} + 9..=16 => buf.chunks_exact_mut(2).for_each(|v| { + v.copy_from_slice(&u16::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), + 17..=32 => buf.chunks_exact_mut(4).for_each(|v| { + v.copy_from_slice(&u32::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), + _ => buf.chunks_exact_mut(8).for_each(|v| { + v.copy_from_slice(&u64::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), }, - ByteOrder::BigEndian => match buf { - DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} - DecodingBuffer::U16(b) => b.iter_mut().for_each(|v| *v = u16::from_be(*v)), - DecodingBuffer::I16(b) => b.iter_mut().for_each(|v| *v = i16::from_be(*v)), - DecodingBuffer::U32(b) => b.iter_mut().for_each(|v| *v = u32::from_be(*v)), - DecodingBuffer::I32(b) => b.iter_mut().for_each(|v| *v = i32::from_be(*v)), - DecodingBuffer::U64(b) => b.iter_mut().for_each(|v| *v = u64::from_be(*v)), - DecodingBuffer::I64(b) => b.iter_mut().for_each(|v| *v = i64::from_be(*v)), - DecodingBuffer::F32(b) => b - .iter_mut() - .for_each(|v| *v = f32::from_bits(u32::from_be(v.to_bits()))), - DecodingBuffer::F64(b) => b - .iter_mut() - .for_each(|v| *v = f64::from_bits(u64::from_be(v.to_bits()))), + ByteOrder::BigEndian => match bit_depth { + 0..=8 => {} + 9..=16 => buf.chunks_exact_mut(2).for_each(|v| { + v.copy_from_slice(&u16::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), + 17..=32 => buf.chunks_exact_mut(4).for_each(|v| { + v.copy_from_slice(&u32::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), + _ => buf.chunks_exact_mut(8).for_each(|v| { + v.copy_from_slice(&u64::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes()) + }), }, }; } impl Decoder { - /// Create a new decoder that decodes from the stream ```r``` pub fn new(mut r: R) -> TiffResult> { let mut endianess = Vec::with_capacity(2); (&mut r).take(2).read_to_end(&mut endianess)?; @@ -526,7 +576,7 @@ )) } }; - let mut reader = SmartReader::wrap(r, byte_order); + let mut reader = EndianReader::new(r, byte_order); let bigtiff = match reader.read_u16()? { 42 => false, @@ -551,30 +601,34 @@ )) } }; + let next_ifd = if bigtiff { Some(reader.read_u64()?) } else { Some(u64::from(reader.read_u32()?)) - }; + } + .map(IfdPointer); - let mut seen_ifds = HashSet::new(); - seen_ifds.insert(*next_ifd.as_ref().unwrap()); - let ifd_offsets = vec![*next_ifd.as_ref().unwrap()]; + let current_ifd = *next_ifd.as_ref().unwrap(); + let ifd_offsets = vec![current_ifd]; let mut decoder = Decoder { - reader, - bigtiff, - limits: Default::default(), + value_reader: ValueReader { + reader, + bigtiff, + limits: Default::default(), + }, next_ifd, ifd_offsets, - seen_ifds, + current_ifd: None, + seen_ifds: cycles::IfdCycles::new(), image: Image { ifd: None, width: 0, height: 0, bits_per_sample: 1, samples: 1, - sample_format: vec![SampleFormat::Uint], + sample_format: SampleFormat::Uint, photometric_interpretation: PhotometricInterpretation::BlackIsZero, compression_method: CompressionMethod::None, jpeg_tables: None, @@ -592,7 +646,7 @@ } pub fn with_limits(mut self, limits: Limits) -> Decoder { - self.limits = limits; + self.value_reader.limits = limits; self } @@ -604,6 +658,11 @@ self.image().colortype() } + /// The offset of the directory representing the current image. + pub fn ifd_pointer(&mut self) -> Option { + self.current_ifd + } + fn image(&self) -> &Image { &self.image } @@ -614,6 +673,8 @@ if ifd_index >= self.ifd_offsets.len() { // We possibly need to load in the next IFD if self.next_ifd.is_none() { + self.current_ifd = None; + return Err(TiffError::FormatError( TiffFormatError::ImageFileDirectoryNotFound, )); @@ -621,9 +682,9 @@ loop { // Follow the list until we find the one we want, or we reach the end, whichever happens first - let (_ifd, next_ifd) = self.next_ifd()?; + let ifd = self.next_ifd()?; - if next_ifd.is_none() { + if ifd.next().is_none() { break; } @@ -635,9 +696,10 @@ // If the index is within the list of ifds then we can load the selected image/IFD if let Some(ifd_offset) = self.ifd_offsets.get(ifd_index) { - let (ifd, _next_ifd) = Self::read_ifd(&mut self.reader, self.bigtiff, *ifd_offset)?; - - self.image = Image::from_reader(&mut self.reader, ifd, &self.limits, self.bigtiff)?; + let ifd = self.value_reader.read_directory(*ifd_offset)?; + self.next_ifd = ifd.next(); + self.current_ifd = Some(*ifd_offset); + self.image = Image::from_reader(&mut self.value_reader, ifd)?; Ok(()) } else { @@ -647,37 +709,35 @@ } } - fn next_ifd(&mut self) -> TiffResult<(Directory, Option)> { - if self.next_ifd.is_none() { + fn next_ifd(&mut self) -> TiffResult { + let Some(next_ifd) = self.next_ifd.take() else { return Err(TiffError::FormatError( TiffFormatError::ImageFileDirectoryNotFound, )); - } + }; - let (ifd, next_ifd) = Self::read_ifd( - &mut self.reader, - self.bigtiff, - self.next_ifd.take().unwrap(), - )?; + let ifd = self.value_reader.read_directory(next_ifd)?; - if let Some(next) = next_ifd { - if !self.seen_ifds.insert(next) { - return Err(TiffError::FormatError(TiffFormatError::CycleInOffsets)); - } - self.next_ifd = Some(next); - self.ifd_offsets.push(next); + // Ensure this walk does not get us into a cycle. + self.seen_ifds.insert_next(next_ifd, ifd.next())?; + + // Extend the list of known IFD offsets in this chain, if needed. + if self.ifd_offsets.last().copied() == self.current_ifd { + self.ifd_offsets.push(next_ifd); } - Ok((ifd, next_ifd)) + self.current_ifd = Some(next_ifd); + self.next_ifd = ifd.next(); + + Ok(ifd) } /// Reads in the next image. /// If there is no further image in the TIFF file a format error is returned. /// To determine whether there are more images call `TIFFDecoder::more_images` instead. pub fn next_image(&mut self) -> TiffResult<()> { - let (ifd, _next_ifd) = self.next_ifd()?; - - self.image = Image::from_reader(&mut self.reader, ifd, &self.limits, self.bigtiff)?; + let ifd = self.next_ifd()?; + self.image = Image::from_reader(&mut self.value_reader, ifd)?; Ok(()) } @@ -686,79 +746,84 @@ self.next_ifd.is_some() } - /// Returns the byte_order + /// Returns the byte_order of the file. pub fn byte_order(&self) -> ByteOrder { - self.reader.byte_order + self.value_reader.reader.byte_order } #[inline] pub fn read_ifd_offset(&mut self) -> Result { - if self.bigtiff { + if self.value_reader.bigtiff { self.read_long8() } else { self.read_long().map(u64::from) } } + /// Returns a mutable reference to the stream being decoded. + pub fn inner(&mut self) -> &mut R { + self.value_reader.reader.inner() + } + /// Reads a TIFF byte value #[inline] pub fn read_byte(&mut self) -> Result { let mut buf = [0; 1]; - self.reader.read_exact(&mut buf)?; + self.value_reader.reader.inner().read_exact(&mut buf)?; Ok(buf[0]) } /// Reads a TIFF short value #[inline] pub fn read_short(&mut self) -> Result { - self.reader.read_u16() + self.value_reader.reader.read_u16() } /// Reads a TIFF sshort value #[inline] pub fn read_sshort(&mut self) -> Result { - self.reader.read_i16() + self.value_reader.reader.read_i16() } /// Reads a TIFF long value #[inline] pub fn read_long(&mut self) -> Result { - self.reader.read_u32() + self.value_reader.reader.read_u32() } /// Reads a TIFF slong value #[inline] pub fn read_slong(&mut self) -> Result { - self.reader.read_i32() + self.value_reader.reader.read_i32() } /// Reads a TIFF float value #[inline] pub fn read_float(&mut self) -> Result { - self.reader.read_f32() + self.value_reader.reader.read_f32() } /// Reads a TIFF double value #[inline] pub fn read_double(&mut self) -> Result { - self.reader.read_f64() + self.value_reader.reader.read_f64() } #[inline] pub fn read_long8(&mut self) -> Result { - self.reader.read_u64() + self.value_reader.reader.read_u64() } #[inline] pub fn read_slong8(&mut self) -> Result { - self.reader.read_i64() + self.value_reader.reader.read_i64() } /// Reads a string #[inline] pub fn read_string(&mut self, length: usize) -> TiffResult { let mut out = vec![0; length]; - self.reader.read_exact(&mut out)?; + self.value_reader.reader.inner().read_exact(&mut out)?; // Strings may be null-terminated, so we trim anything downstream of the null byte if let Some(first) = out.iter().position(|&b| b == 0) { out.truncate(first); @@ -769,13 +834,13 @@ /// Reads a TIFF IFA offset/value field #[inline] pub fn read_offset(&mut self) -> TiffResult<[u8; 4]> { - if self.bigtiff { + if self.value_reader.bigtiff { return Err(TiffError::FormatError( TiffFormatError::InconsistentSizesEncountered, )); } let mut val = [0; 4]; - self.reader.read_exact(&mut val)?; + self.value_reader.reader.inner().read_exact(&mut val)?; Ok(val) } @@ -783,7 +848,7 @@ #[inline] pub fn read_offset_u64(&mut self) -> Result<[u8; 8], io::Error> { let mut val = [0; 8]; - self.reader.read_exact(&mut val)?; + self.value_reader.reader.inner().read_exact(&mut val)?; Ok(val) } @@ -795,7 +860,523 @@ #[inline] pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> { - self.reader.seek(io::SeekFrom::Start(offset)).map(|_| ()) + self.value_reader.reader.goto_offset(offset) + } + + /// Read a tag-entry map from a known offset. + /// + /// A TIFF [`Directory`], aka. image file directory aka. IFD, refers to a map from + /// tags–identified by a `u16`–to a typed vector of elements. It is encoded as a list + /// of ascending tag values with the offset and type of their corresponding values. The + /// semantic interpretations of a tag and its type requirements depend on the context of the + /// directory. The main image directories, those iterated over by the `Decoder` after + /// construction, are represented by [`Tag`] and [`ifd::Value`]. Other forms are EXIF and GPS + /// data as well as thumbnail Sub-IFD representations associated with each image file. + /// + /// This method allows the decoding of a directory from an arbitrary offset in the image file + /// with no specific semantic interpretation. Such an offset is usually found as the value of + /// a tag, e.g. [`Tag::SubIfd`], [`Tag::ExifDirectory`], [`Tag::GpsDirectory`] and recovered + /// from the associated value by [`ifd::Value::into_ifd_pointer`]. + /// + /// The library will not verify whether the offset overlaps any other directory or would form a + /// cycle with any other directory when calling this method. This will modify the position of + /// the reader, i.e. continuing with direct reads at a later point will require going back with + /// [`Self::goto_offset`]. + pub fn read_directory(&mut self, ptr: IfdPointer) -> TiffResult { + self.value_reader.read_directory(ptr) + } + + fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> { + if expected != self.image().chunk_type { + return Err(TiffError::UsageError(UsageError::InvalidChunkType( + expected, + self.image().chunk_type, + ))); + } + + Ok(()) + } + + /// The chunk type (Strips / Tiles) of the image + pub fn get_chunk_type(&self) -> ChunkType { + self.image().chunk_type + } + + /// Number of strips in image + pub fn strip_count(&mut self) -> TiffResult { + self.check_chunk_type(ChunkType::Strip)?; + let rows_per_strip = self.image().strip_decoder.as_ref().unwrap().rows_per_strip; + + if rows_per_strip == 0 { + return Ok(0); + } + + // rows_per_strip - 1 can never fail since we know it's at least 1 + let height = match self.image().height.checked_add(rows_per_strip - 1) { + Some(h) => h, + None => return Err(TiffError::IntSizeError), + }; + + let strips = match self.image().planar_config { + PlanarConfiguration::Chunky => height / rows_per_strip, + PlanarConfiguration::Planar => height / rows_per_strip * self.image().samples as u32, + }; + + Ok(strips) + } + + /// Number of tiles in image + pub fn tile_count(&mut self) -> TiffResult { + self.check_chunk_type(ChunkType::Tile)?; + Ok(u32::try_from(self.image().chunk_offsets.len())?) + } + + pub fn read_chunk_to_buffer( + &mut self, + mut buffer: DecodingBuffer, + chunk_index: u32, + output_width: usize, + ) -> TiffResult<()> { + let output_row_stride = (output_width as u64) + .saturating_mul(self.image.samples_per_pixel() as u64) + .saturating_mul(self.image.bits_per_sample as u64) + .div_ceil(8); + + self.read_chunk_to_bytes(buffer.as_bytes_mut(), chunk_index, output_row_stride) + } + + fn read_chunk_to_bytes( + &mut self, + buffer: &mut [u8], + chunk_index: u32, + output_row_stride: u64, + ) -> TiffResult<()> { + let offset = self.image.chunk_file_range(chunk_index)?.0; + self.goto_offset_u64(offset)?; + + self.image.expand_chunk( + &mut self.value_reader, + buffer, + output_row_stride.try_into()?, + chunk_index, + )?; + + Ok(()) + } + + fn result_buffer(&self, width: usize, height: usize) -> TiffResult { + self.result_extent(width, height)? + .to_result_buffer(&self.value_reader.limits) + } + + // FIXME: it's unusual for this method to take a `usize` dimension parameter since those would + // typically come from the image data. The preferred consistent representation should be `u32` + // and that would avoid some unusual casts `usize -> u64` with a `u64::from` instead. + fn result_extent(&self, width: usize, height: usize) -> TiffResult { + let bits_per_sample = self.image.bits_per_sample; + + // If samples take up more than one byte, we expand it to a full number (integer or float) + // and the number of samples in that integer type just counts the number in the underlying + // image itself. Otherwise, a row is represented as the byte slice of bitfields without + // expansion. + let row_samples = if bits_per_sample >= 8 { + width + } else { + ((width as u64) * bits_per_sample as u64) + .div_ceil(8) + .try_into() + .map_err(|_| TiffError::LimitsExceeded)? + }; + + let buffer_size = row_samples + .checked_mul(height) + .and_then(|x| x.checked_mul(self.image.samples_per_pixel())) + .ok_or(TiffError::LimitsExceeded)?; + + Ok(match self.image().sample_format { + SampleFormat::Uint => match bits_per_sample { + n if n <= 8 => DecodingExtent::U8(buffer_size), + n if n <= 16 => DecodingExtent::U16(buffer_size), + n if n <= 32 => DecodingExtent::U32(buffer_size), + n if n <= 64 => DecodingExtent::U64(buffer_size), + n => { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnsupportedBitsPerChannel(n), + )) + } + }, + SampleFormat::IEEEFP => match bits_per_sample { + 16 => DecodingExtent::F16(buffer_size), + 32 => DecodingExtent::F32(buffer_size), + 64 => DecodingExtent::F64(buffer_size), + n => { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnsupportedBitsPerChannel(n), + )) + } + }, + SampleFormat::Int => match bits_per_sample { + n if n <= 8 => DecodingExtent::I8(buffer_size), + n if n <= 16 => DecodingExtent::I16(buffer_size), + n if n <= 32 => DecodingExtent::I32(buffer_size), + n if n <= 64 => DecodingExtent::I64(buffer_size), + n => { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnsupportedBitsPerChannel(n), + )) + } + }, + format => { + return Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format]).into()) + } + }) + } + + /// Returns the layout preferred to read the specified chunk with [`Self::read_chunk_bytes`]. + /// + /// Returns the layout without being specific as to the underlying type for forward + /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of + /// channels of individual *bit* length and format each. + /// + /// See [`Self::colortype`] to describe the sample types. + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only + /// indicate the layout needed to read the first data plane. This will be fixed in a future + /// major version of `tiff`. + pub fn image_chunk_buffer_layout( + &mut self, + chunk_index: u32, + ) -> TiffResult { + let data_dims = self.image().chunk_data_dimensions(chunk_index)?; + let layout = self + .result_extent(data_dims.0 as usize, data_dims.1 as usize)? + .preferred_layout()?; + + let row_stride = self.image.minimum_row_stride(data_dims); + + Ok(BufferLayoutPreference { + len: layout.size(), + row_stride, + }) + } + + /// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector. + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only read + /// the first sample's plane. This will be fixed in a future major version of `tiff`. + pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult { + let data_dims = self.image().chunk_data_dimensions(chunk_index)?; + + let mut result = self.result_buffer(data_dims.0 as usize, data_dims.1 as usize)?; + + self.read_chunk_to_buffer(result.as_buffer(0), chunk_index, data_dims.0 as usize)?; + + Ok(result) + } + + /// Read the specified chunk (at index `chunk_index`) into an allocated buffer. + /// + /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a + /// call to [`Self::image_chunk_buffer_layout`]. Note that the alignment may be arbitrary, but + /// an alignment smaller than the preferred alignment may perform worse. + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only read + /// the first sample's plane. This will be fixed in a future major version of `tiff`. + pub fn read_chunk_bytes(&mut self, chunk_index: u32, buffer: &mut [u8]) -> TiffResult<()> { + let data_dims = self.image().chunk_data_dimensions(chunk_index)?; + + let extent = self.result_extent(data_dims.0 as usize, data_dims.1 as usize)?; + extent.assert_layout(buffer.len())?; + + let output_row_stride = u64::from(data_dims.0) + .saturating_mul(self.image.samples_per_pixel() as u64) + .saturating_mul(self.image.bits_per_sample as u64) + .div_ceil(8); + + self.read_chunk_to_bytes(buffer, chunk_index, output_row_stride)?; + + Ok(()) + } + + /// Returns the default chunk size for the current image. Any given chunk in the image is at most as large as + /// the value returned here. For the size of the data (chunk minus padding), use `chunk_data_dimensions`. + pub fn chunk_dimensions(&self) -> (u32, u32) { + self.image().chunk_dimensions().unwrap() + } + + /// Returns the size of the data in the chunk with the specified index. This is the default size of the chunk, + /// minus any padding. + pub fn chunk_data_dimensions(&self, chunk_index: u32) -> (u32, u32) { + self.image() + .chunk_data_dimensions(chunk_index) + .expect("invalid chunk_index") + } + + /// Returns the preferred buffer required to read the whole image with [`Self::read_image_bytes`]. + /// + /// Returns the layout without being specific as to the underlying type for forward + /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of + /// channels of individual *bit* length and format each. + /// + /// See [`Self::colortype`] to describe the sample types. + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only + /// indicate the layout needed to read the first data plane. This will be fixed in a future + /// major version of `tiff`. + pub fn image_buffer_layout(&mut self) -> TiffResult { + let data_dims @ (width, height) = (self.image.width, self.image.height); + + let layout = self + .result_extent(width as usize, height as usize)? + .preferred_layout()?; + + let row_stride = self.image.minimum_row_stride(data_dims); + + Ok(BufferLayoutPreference { + len: layout.size(), + row_stride, + }) + } + + /// Decodes the entire image and return it as a Vector + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only read + /// the first sample's plane. This will be fixed in a future major version of `tiff`. + pub fn read_image(&mut self) -> TiffResult { + let width = self.image().width; + let height = self.image().height; + + let mut result = self.result_buffer(width as usize, height as usize)?; + self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?; + + Ok(result) + } + + /// Decodes the entire image into a provided buffer. + /// + /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a + /// call to [`Self::image_buffer_layout`]. Note that the alignment may be arbitrary, but an + /// alignment smaller than the preferred alignment may perform worse. + /// + /// # Bugs + /// + /// When the image is stored as a planar configuration, this method will currently only read + /// the first sample's plane. This will be fixed in a future major version of `tiff`. + pub fn read_image_bytes(&mut self, buffer: &mut [u8]) -> TiffResult<()> { + let width = self.image().width; + let height = self.image().height; + + let extent = self.result_extent(width as usize, height as usize)?; + extent.assert_layout(buffer.len())?; + + if width == 0 || height == 0 { + return Ok(()); + } + + let chunk_dimensions = self.image().chunk_dimensions()?; + let chunk_dimensions = ( + chunk_dimensions.0.min(width), + chunk_dimensions.1.min(height), + ); + if chunk_dimensions.0 == 0 || chunk_dimensions.1 == 0 { + return Err(TiffError::FormatError( + TiffFormatError::InconsistentSizesEncountered, + )); + } + + let samples = self.image().samples_per_pixel(); + if samples == 0 { + return Err(TiffError::FormatError( + TiffFormatError::InconsistentSizesEncountered, + )); + } + + let output_row_bits = (width as u64 * self.image.bits_per_sample as u64) + .checked_mul(samples as u64) + .ok_or(TiffError::LimitsExceeded)?; + let output_row_stride: usize = output_row_bits.div_ceil(8).try_into()?; + + let chunk_row_bits = (chunk_dimensions.0 as u64 * self.image.bits_per_sample as u64) + .checked_mul(samples as u64) + .ok_or(TiffError::LimitsExceeded)?; + let chunk_row_bytes: usize = chunk_row_bits.div_ceil(8).try_into()?; + + let chunks_across = ((width - 1) / chunk_dimensions.0 + 1) as usize; + + if chunks_across > 1 && chunk_row_bits % 8 != 0 { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::MisalignedTileBoundaries, + )); + } + + let image_chunks = self.image().chunk_offsets.len() / self.image().strips_per_pixel(); + // For multi-band images, only the first band is read. + // Possible improvements: + // * pass requested band as parameter + // * collect bands to a RGB encoding result in case of RGB bands + for chunk in 0..image_chunks { + self.goto_offset_u64(self.image().chunk_offsets[chunk])?; + + let x = chunk % chunks_across; + let y = chunk / chunks_across; + let buffer_offset = + y * output_row_stride * chunk_dimensions.1 as usize + x * chunk_row_bytes; + self.image.expand_chunk( + &mut self.value_reader, + &mut buffer[buffer_offset..], + output_row_stride, + chunk as u32, + )?; + } + + Ok(()) + } + + /// Get the IFD decoder for our current image IFD. + fn image_ifd(&mut self) -> IfdDecoder<'_> { + IfdDecoder { + inner: tag_reader::TagReader { + decoder: &mut self.value_reader, + ifd: self.image.ifd.as_ref().unwrap(), + }, + } + } + + /// Prepare reading values for tags of a given directory. + /// + /// # Examples + /// + /// This method may be used to read the values of tags in directories that have been previously + /// read with [`Decoder::read_directory`]. + /// + /// ```no_run + /// use tiff::decoder::Decoder; + /// use tiff::tags::Tag; + /// + /// # use std::io::Cursor; + /// # let mut data = Cursor::new(vec![0]); + /// let mut decoder = Decoder::new(&mut data).unwrap(); + /// let sub_ifds = decoder.get_tag(Tag::SubIfd)?.into_ifd_vec()?; + /// + /// for ifd in sub_ifds { + /// let subdir = decoder.read_directory(ifd)?; + /// let subfile = decoder.read_directory_tags(&subdir).find_tag(Tag::SubfileType)?; + /// // omitted: handle the subfiles, e.g. thumbnails + /// } + /// + /// # Ok::<_, tiff::TiffError>(()) + /// ``` + pub fn read_directory_tags<'ifd>(&'ifd mut self, ifd: &'ifd Directory) -> IfdDecoder<'ifd> { + IfdDecoder { + inner: tag_reader::TagReader { + decoder: &mut self.value_reader, + ifd, + }, + } + } + + /// Tries to retrieve a tag from the current image directory. + /// Return `Ok(None)` if the tag is not present. + pub fn find_tag(&mut self, tag: Tag) -> TiffResult> { + self.image_ifd().find_tag(tag) + } + + /// Tries to retrieve a tag in the current image directory and convert it to the desired + /// unsigned type. + pub fn find_tag_unsigned>(&mut self, tag: Tag) -> TiffResult> { + self.image_ifd().find_tag_unsigned(tag) + } + + /// Tries to retrieve a vector of all a tag's values and convert them to the desired unsigned + /// type. + pub fn find_tag_unsigned_vec>( + &mut self, + tag: Tag, + ) -> TiffResult>> { + self.image_ifd().find_tag_unsigned_vec(tag) + } + + /// Tries to retrieve a tag from the current image directory and convert it to the desired + /// unsigned type. Returns an error if the tag is not present. + pub fn get_tag_unsigned>(&mut self, tag: Tag) -> TiffResult { + self.image_ifd().get_tag_unsigned(tag) + } + + /// Tries to retrieve a tag from the current image directory. + /// Returns an error if the tag is not present + pub fn get_tag(&mut self, tag: Tag) -> TiffResult { + self.image_ifd().get_tag(tag) + } + + pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_u32() + } + + pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_u64() + } + + /// Tries to retrieve a tag and convert it to the desired type. + pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_f32() + } + + /// Tries to retrieve a tag and convert it to the desired type. + pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_f64() + } + + /// Tries to retrieve a tag and convert it to the desired type. + pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_u32_vec() + } + + pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_u16_vec() + } + + pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_u64_vec() + } + + /// Tries to retrieve a tag and convert it to the desired type. + pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_f32_vec() + } + + /// Tries to retrieve a tag and convert it to the desired type. + pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_f64_vec() + } + + /// Tries to retrieve a tag and convert it to a 8bit vector. + pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_u8_vec() + } + + /// Tries to retrieve a tag and convert it to a ascii vector. + pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_string() + } + + pub fn tag_iter(&mut self) -> impl Iterator> + '_ { + self.image_ifd().tag_iter() + } +} + +impl ValueReader { + pub(crate) fn read_directory(&mut self, ptr: IfdPointer) -> Result { + Self::read_ifd(&mut self.reader, self.bigtiff, ptr) } /// Reads a IFD entry. @@ -806,7 +1387,7 @@ // Count 4 bytes // Value 4 bytes either a pointer the value itself fn read_entry( - reader: &mut SmartReader, + reader: &mut EndianReader, bigtiff: bool, ) -> TiffResult> { let tag = Tag::from_u16_exhaustive(reader.read_u16()?); @@ -823,13 +1404,13 @@ let mut offset = [0; 8]; let count = reader.read_u64()?; - reader.read_exact(&mut offset)?; + reader.inner().read_exact(&mut offset)?; ifd::Entry::new_u64(type_, count, offset) } else { let mut offset = [0; 4]; let count = reader.read_u32()?; - reader.read_exact(&mut offset)?; + reader.inner().read_exact(&mut offset)?; ifd::Entry::new(type_, count, offset) }; Ok(Some((tag, entry))) @@ -837,19 +1418,20 @@ /// Reads the IFD starting at the indicated location. fn read_ifd( - reader: &mut SmartReader, + reader: &mut EndianReader, bigtiff: bool, - ifd_location: u64, - ) -> TiffResult<(Directory, Option)> { - reader.goto_offset(ifd_location)?; + ifd_location: IfdPointer, + ) -> TiffResult { + reader.goto_offset(ifd_location.0)?; - let mut dir: Directory = HashMap::new(); + let mut entries: BTreeMap<_, _> = BTreeMap::new(); let num_tags = if bigtiff { reader.read_u64()? } else { reader.read_u16()?.into() }; + for _ in 0..num_tags { let (tag, entry) = match Self::read_entry(reader, bigtiff)? { Some(val) => val, @@ -857,7 +1439,8 @@ continue; } // Unknown data type in tag, skip }; - dir.insert(tag, entry); + + entries.insert(tag.to_u16(), entry); } let next_ifd = if bigtiff { @@ -866,27 +1449,17 @@ reader.read_u32()?.into() }; - let next_ifd = match next_ifd { - 0 => None, - _ => Some(next_ifd), - }; + let next_ifd = core::num::NonZeroU64::new(next_ifd); - Ok((dir, next_ifd)) + Ok(Directory { entries, next_ifd }) } +} +impl IfdDecoder<'_> { /// Tries to retrieve a tag. /// Return `Ok(None)` if the tag is not present. pub fn find_tag(&mut self, tag: Tag) -> TiffResult> { - let entry = match self.image().ifd.as_ref().unwrap().get(&tag) { - None => return Ok(None), - Some(entry) => entry.clone(), - }; - - Ok(Some(entry.val( - &self.limits, - self.bigtiff, - &mut self.reader, - )?)) + self.inner.find_tag(tag) } /// Tries to retrieve a tag and convert it to the desired unsigned type. @@ -941,6 +1514,7 @@ pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult { self.get_tag(tag)?.into_u32() } + pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult { self.get_tag(tag)?.into_u64() } @@ -963,6 +1537,7 @@ pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult> { self.get_tag(tag)?.into_u16_vec() } + pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult> { self.get_tag(tag)?.into_u64_vec() } @@ -986,197 +1561,17 @@ pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult { self.get_tag(tag)?.into_string() } +} - fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> { - if expected != self.image().chunk_type { - return Err(TiffError::UsageError(UsageError::InvalidChunkType( - expected, - self.image().chunk_type, - ))); - } - - Ok(()) - } - - /// The chunk type (Strips / Tiles) of the image - pub fn get_chunk_type(&self) -> ChunkType { - self.image().chunk_type - } - - /// Number of strips in image - pub fn strip_count(&mut self) -> TiffResult { - self.check_chunk_type(ChunkType::Strip)?; - let rows_per_strip = self.image().strip_decoder.as_ref().unwrap().rows_per_strip; - - if rows_per_strip == 0 { - return Ok(0); - } - - // rows_per_strip - 1 can never fail since we know it's at least 1 - let height = match self.image().height.checked_add(rows_per_strip - 1) { - Some(h) => h, - None => return Err(TiffError::IntSizeError), - }; - - let strips = match self.image().planar_config { - PlanarConfiguration::Chunky => height / rows_per_strip, - PlanarConfiguration::Planar => height / rows_per_strip * self.image().samples as u32, - }; - - Ok(strips) - } - - /// Number of tiles in image - pub fn tile_count(&mut self) -> TiffResult { - self.check_chunk_type(ChunkType::Tile)?; - Ok(u32::try_from(self.image().chunk_offsets.len())?) - } - - pub fn read_chunk_to_buffer( - &mut self, - mut buffer: DecodingBuffer, - chunk_index: u32, - output_width: usize, - ) -> TiffResult<()> { - let offset = self.image.chunk_file_range(chunk_index)?.0; - self.goto_offset_u64(offset)?; - - let byte_order = self.reader.byte_order; - - self.image.expand_chunk( - &mut self.reader, - buffer.copy(), - output_width, - byte_order, - chunk_index, - &self.limits, - )?; - - Ok(()) - } - - fn result_buffer(&self, width: usize, height: usize) -> TiffResult { - let buffer_size = match width - .checked_mul(height) - .and_then(|x| x.checked_mul(self.image().samples_per_pixel())) - { - Some(s) => s, - None => return Err(TiffError::LimitsExceeded), - }; - - let max_sample_bits = self.image().bits_per_sample; - match self - .image() - .sample_format - .first() - .unwrap_or(&SampleFormat::Uint) - { - SampleFormat::Uint => match max_sample_bits { - n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits), - n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits), - n if n <= 32 => DecodingResult::new_u32(buffer_size, &self.limits), - n if n <= 64 => DecodingResult::new_u64(buffer_size, &self.limits), - n => Err(TiffError::UnsupportedError( - TiffUnsupportedError::UnsupportedBitsPerChannel(n), - )), - }, - SampleFormat::IEEEFP => match max_sample_bits { - 32 => DecodingResult::new_f32(buffer_size, &self.limits), - 64 => DecodingResult::new_f64(buffer_size, &self.limits), - n => Err(TiffError::UnsupportedError( - TiffUnsupportedError::UnsupportedBitsPerChannel(n), - )), - }, - SampleFormat::Int => match max_sample_bits { - n if n <= 8 => DecodingResult::new_i8(buffer_size, &self.limits), - n if n <= 16 => DecodingResult::new_i16(buffer_size, &self.limits), - n if n <= 32 => DecodingResult::new_i32(buffer_size, &self.limits), - n if n <= 64 => DecodingResult::new_i64(buffer_size, &self.limits), - n => Err(TiffError::UnsupportedError( - TiffUnsupportedError::UnsupportedBitsPerChannel(n), - )), - }, - format => Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![*format]).into()), - } - } - - /// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector. - pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult { - let data_dims = self.image().chunk_data_dimensions(chunk_index)?; - - let mut result = self.result_buffer(data_dims.0 as usize, data_dims.1 as usize)?; - - self.read_chunk_to_buffer(result.as_buffer(0), chunk_index, data_dims.0 as usize)?; - - Ok(result) - } - - /// Returns the default chunk size for the current image. Any given chunk in the image is at most as large as - /// the value returned here. For the size of the data (chunk minus padding), use `chunk_data_dimensions`. - pub fn chunk_dimensions(&self) -> (u32, u32) { - self.image().chunk_dimensions().unwrap() - } - - /// Returns the size of the data in the chunk with the specified index. This is the default size of the chunk, - /// minus any padding. - pub fn chunk_data_dimensions(&self, chunk_index: u32) -> (u32, u32) { - self.image() - .chunk_data_dimensions(chunk_index) - .expect("invalid chunk_index") - } - - /// Decodes the entire image and return it as a Vector - pub fn read_image(&mut self) -> TiffResult { - let width = self.image().width; - let height = self.image().height; - let mut result = self.result_buffer(width as usize, height as usize)?; - if width == 0 || height == 0 { - return Ok(result); - } - - let chunk_dimensions = self.image().chunk_dimensions()?; - let chunk_dimensions = ( - chunk_dimensions.0.min(width), - chunk_dimensions.1.min(height), - ); - if chunk_dimensions.0 == 0 || chunk_dimensions.1 == 0 { - return Err(TiffError::FormatError( - TiffFormatError::InconsistentSizesEncountered, - )); - } - - let samples = self.image().samples_per_pixel(); - if samples == 0 { - return Err(TiffError::FormatError( - TiffFormatError::InconsistentSizesEncountered, - )); - } - - let chunks_across = ((width - 1) / chunk_dimensions.0 + 1) as usize; - let strip_samples = width as usize * chunk_dimensions.1 as usize * samples; - - let image_chunks = self.image().chunk_offsets.len() / self.image().strips_per_pixel(); - // For multi-band images, only the first band is read. - // Possible improvements: - // * pass requested band as parameter - // * collect bands to a RGB encoding result in case of RGB bands - for chunk in 0..image_chunks { - self.goto_offset_u64(self.image().chunk_offsets[chunk])?; - - let x = chunk % chunks_across; - let y = chunk / chunks_across; - let buffer_offset = y * strip_samples + x * chunk_dimensions.0 as usize * samples; - let byte_order = self.reader.byte_order; - self.image.expand_chunk( - &mut self.reader, - result.as_buffer(buffer_offset).copy(), - width as usize, - byte_order, - chunk as u32, - &self.limits, - )?; - } - - Ok(result) +impl<'l> IfdDecoder<'l> { + /// Returns an iterator over all tags in the current image, along with their values. + pub fn tag_iter(self) -> impl Iterator> + 'l { + self.inner + .ifd + .iter() + .map(|(tag, entry)| match self.inner.decoder.entry_val(entry) { + Ok(value) => Ok((tag, value)), + Err(err) => Err(err), + }) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/stream.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/stream.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/stream.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/stream.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,4 @@ //! All IO functionality needed for TIFF decoding - -use std::convert::TryFrom; use std::io::{self, BufRead, BufReader, Read, Seek, Take}; /// Byte order of the TIFF file. @@ -13,16 +11,35 @@ } /// Reader that is aware of the byte order. -pub trait EndianReader: Read { - /// Byte order that should be adhered to - fn byte_order(&self) -> ByteOrder; +#[derive(Debug)] +pub struct EndianReader { + reader: R, + pub(crate) byte_order: ByteOrder, +} + +impl EndianReader { + pub fn new(reader: R, byte_order: ByteOrder) -> Self { + Self { reader, byte_order } + } + + pub fn inner(&mut self) -> &mut R { + &mut self.reader + } + + pub fn goto_offset(&mut self, offset: u64) -> io::Result<()> + where + R: Seek, + { + self.reader.seek(io::SeekFrom::Start(offset))?; + Ok(()) + } /// Reads an u16 #[inline(always)] - fn read_u16(&mut self) -> Result { + pub fn read_u16(&mut self) -> Result { let mut n = [0u8; 2]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u16::from_le_bytes(n), ByteOrder::BigEndian => u16::from_be_bytes(n), }) @@ -30,10 +47,10 @@ /// Reads an i8 #[inline(always)] - fn read_i8(&mut self) -> Result { + pub fn read_i8(&mut self) -> Result { let mut n = [0u8; 1]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i8::from_le_bytes(n), ByteOrder::BigEndian => i8::from_be_bytes(n), }) @@ -41,10 +58,10 @@ /// Reads an i16 #[inline(always)] - fn read_i16(&mut self) -> Result { + pub fn read_i16(&mut self) -> Result { let mut n = [0u8; 2]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i16::from_le_bytes(n), ByteOrder::BigEndian => i16::from_be_bytes(n), }) @@ -52,10 +69,10 @@ /// Reads an u32 #[inline(always)] - fn read_u32(&mut self) -> Result { + pub fn read_u32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u32::from_le_bytes(n), ByteOrder::BigEndian => u32::from_be_bytes(n), }) @@ -63,10 +80,10 @@ /// Reads an i32 #[inline(always)] - fn read_i32(&mut self) -> Result { + pub fn read_i32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i32::from_le_bytes(n), ByteOrder::BigEndian => i32::from_be_bytes(n), }) @@ -74,10 +91,10 @@ /// Reads an u64 #[inline(always)] - fn read_u64(&mut self) -> Result { + pub fn read_u64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u64::from_le_bytes(n), ByteOrder::BigEndian => u64::from_be_bytes(n), }) @@ -85,10 +102,10 @@ /// Reads an i64 #[inline(always)] - fn read_i64(&mut self) -> Result { + pub fn read_i64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i64::from_le_bytes(n), ByteOrder::BigEndian => i64::from_be_bytes(n), }) @@ -96,10 +113,10 @@ /// Reads an f32 #[inline(always)] - fn read_f32(&mut self) -> Result { + pub fn read_f32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(f32::from_bits(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(f32::from_bits(match self.byte_order { ByteOrder::LittleEndian => u32::from_le_bytes(n), ByteOrder::BigEndian => u32::from_be_bytes(n), })) @@ -107,49 +124,53 @@ /// Reads an f64 #[inline(always)] - fn read_f64(&mut self) -> Result { + pub fn read_f64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(f64::from_bits(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(f64::from_bits(match self.byte_order { ByteOrder::LittleEndian => u64::from_le_bytes(n), ByteOrder::BigEndian => u64::from_be_bytes(n), })) } } -/// -/// # READERS -/// - -/// -/// ## Deflate Reader -/// +// +// # READERS +// +/// Type alias for the deflate Reader +#[cfg(feature = "deflate")] pub type DeflateReader = flate2::read::ZlibDecoder; -/// -/// ## LZW Reader -/// +// +// ## LZW Reader +// /// Reader that decompresses LZW streams +#[cfg(feature = "lzw")] pub struct LZWReader { reader: BufReader>, decoder: weezl::decode::Decoder, } +#[cfg(feature = "lzw")] impl LZWReader { /// Wraps a reader pub fn new(reader: R, compressed_length: usize) -> LZWReader { + let configuration = + weezl::decode::Configuration::with_tiff_size_switch(weezl::BitOrder::Msb, 8) + .with_yield_on_full_buffer(true); Self { reader: BufReader::with_capacity( (32 * 1024).min(compressed_length), reader.take(u64::try_from(compressed_length).unwrap()), ), - decoder: weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8), + decoder: configuration.build(), } } } +#[cfg(feature = "lzw")] impl Read for LZWReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { loop { @@ -182,10 +203,11 @@ } } -/// -/// ## PackBits Reader -/// +// +// ## PackBits Reader +// +/// Internal state machine for the PackBitsReader. enum PackBitsReaderState { Header, Literal, @@ -253,59 +275,103 @@ } } -/// -/// ## SmartReader Reader -/// - -/// Reader that is aware of the byte order. -#[derive(Debug)] -pub struct SmartReader -where - R: Read, -{ - reader: R, - pub byte_order: ByteOrder, -} - -impl SmartReader -where - R: Read, -{ - /// Wraps a reader - pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader { - SmartReader { reader, byte_order } - } - pub fn into_inner(self) -> R { - self.reader - } -} -impl SmartReader { - pub fn goto_offset(&mut self, offset: u64) -> io::Result<()> { - self.seek(io::SeekFrom::Start(offset)).map(|_| ()) - } -} - -impl EndianReader for SmartReader -where - R: Read, -{ - #[inline(always)] - fn byte_order(&self) -> ByteOrder { - self.byte_order +#[cfg(feature = "fax")] +pub struct Group4Reader { + decoder: fax34::decoder::Group4Decoder>>>, + line_buf: io::Cursor>, + height: u16, + width: u16, + y: u16, +} + +#[cfg(feature = "fax")] +impl Group4Reader { + pub fn new( + dimensions: (u32, u32), + reader: R, + compressed_length: u64, + ) -> crate::TiffResult { + let width = u16::try_from(dimensions.0)?; + let height = u16::try_from(dimensions.1)?; + + Ok(Self { + decoder: fax34::decoder::Group4Decoder::new( + io::BufReader::new(reader.take(compressed_length)).bytes(), + width, + )?, + line_buf: io::Cursor::new(Vec::with_capacity(width.into())), + width, + height, + y: 0, + }) } } -impl Read for SmartReader { - #[inline] +#[cfg(feature = "fax")] +impl Read for Group4Reader { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.reader.read(buf) - } -} + // Either we have not read any line or we are at the end of a line. + if self.line_buf.position() as usize == self.line_buf.get_ref().len() + && self.y < self.height + { + let next = self.decoder.advance().map_err(std::io::Error::other)?; + + match next { + fax34::decoder::DecodeStatus::End => (), + fax34::decoder::DecodeStatus::Incomplete => { + self.y += 1; + + // We known `transitions` yields exactly `self.width` items (per doc). + // FIXME: performance. We do not need an individual pixel iterator, filling + // memory especially for long runs can be much quicker. The `transitions` are + // the positions at which each run-length ends, i.e. the prefix sum of run + // lengths. Runs in fax4 start with white. + let transitions = fax34::decoder::pels(self.decoder.transition(), self.width); + + let buffer = self.line_buf.get_mut(); + buffer.resize(usize::from(self.width).div_ceil(8), 0u8); + + let target = &mut buffer[..]; + + // Note: it may seem strange to treat black as 0b1 and white as 0b0 despite all + // our streams by default decoding as-if PhotometricInterpretation::BlackIsMin. + // This is however consistent with libtiff. It seems that fax4's "White" + // differs from what libtiff thinks of as "White". For content, a line of data + // is in runlength encoding of white-black-white-black always starting with + // white. In libtiff, the loop always does both colors in one go and the + // structure is: + // + // ``` + // for (; runs < erun; runs += 2) + // // white run + // do { *lp++ = 0L; } while (…) + // // black run + // do { *lp++ = -1L; } while (…) + // ``` + // + // So indeed the Fax4::White run is implemented by filling with zeros. + let mut bits = transitions.map(|c| match c { + fax34::Color::Black => true, + fax34::Color::White => false, + }); + + // Assemble bits in MSB as per our library representation for buffer. + for byte in target { + let mut val = 0; + + for (idx, bit) in bits.by_ref().take(8).enumerate() { + val |= u8::from(bit) << (7 - idx % 8); + } + + *byte = val; + } + + self.line_buf.set_position(0); + } + } + } -impl Seek for SmartReader { - #[inline] - fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - self.reader.seek(pos) + self.line_buf.read(buf) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/tag_reader.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/tag_reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/decoder/tag_reader.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/decoder/tag_reader.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,26 +1,37 @@ -use std::convert::TryFrom; use std::io::{Read, Seek}; -use crate::tags::Tag; +use crate::{tags::Tag, Directory}; use crate::{TiffError, TiffFormatError, TiffResult}; -use super::ifd::{Directory, Value}; -use super::stream::SmartReader; -use super::Limits; - -pub(crate) struct TagReader<'a, R: Read + Seek> { - pub reader: &'a mut SmartReader, - pub ifd: &'a Directory, - pub limits: &'a Limits, - pub bigtiff: bool, +use super::ifd::{Entry, Value}; +use super::ValueReader; + +pub(crate) struct TagReader<'lt, R: EntryDecoder + ?Sized> { + pub(crate) decoder: &'lt mut R, + pub(crate) ifd: &'lt Directory, +} + +pub(crate) trait EntryDecoder { + /// Turn an entry into a value by fetching the required bytes in the stream. + fn entry_val(&mut self, entry: &Entry) -> TiffResult; +} + +impl EntryDecoder for ValueReader { + fn entry_val(&mut self, entry: &Entry) -> TiffResult { + entry.val(&self.limits, self.bigtiff, &mut self.reader) + } } -impl<'a, R: Read + Seek> TagReader<'a, R> { + +impl<'a, R: EntryDecoder + ?Sized> TagReader<'a, R> { pub(crate) fn find_tag(&mut self, tag: Tag) -> TiffResult> { - Ok(match self.ifd.get(&tag) { - Some(entry) => Some(entry.clone().val(self.limits, self.bigtiff, self.reader)?), - None => None, - }) + let entry = match self.ifd.get(tag) { + None => return Ok(None), + Some(entry) => entry.clone(), + }; + + self.decoder.entry_val(&entry).map(Some) } + pub(crate) fn require_tag(&mut self, tag: Tag) -> TiffResult { match self.find_tag(tag)? { Some(val) => Ok(val), @@ -29,6 +40,7 @@ )), } } + pub fn find_tag_uint_vec>(&mut self, tag: Tag) -> TiffResult>> { self.find_tag(tag)? .map(|v| v.into_u64_vec()) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/directory.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/directory.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/directory.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/directory.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,166 @@ +use core::fmt; +use std::{collections::BTreeMap, num::NonZeroU64}; + +use crate::{ + decoder::ifd::Entry, + tags::{IfdPointer, Tag}, +}; + +/// An Image File Directory (IFD). +/// +/// A directory is a map of [`Tag`]s to [`Value`](crate::decoder::ifd::Value)s. The values are +/// stored anywhere in the file, with the directory containing the offsets and length of the +/// associated values for each tag present in the directory. +/// +/// A directory can be created with with +/// [`Decoder::read_directory`](crate::decoder::Decoder::read_directory) or as an empty directory +/// to be extended with entries. A directory may be used with +/// [`Decoder::read_directory_tags`](crate::decoder::Decoder::read_directory_tags) to read the +/// values associated with tags from an underlying file. +#[doc(alias = "IFD")] +pub struct Directory { + /// There are at most `u16::MAX` entries in any single directory, the count is stored as a + /// 2-byte value. The order in the file is implied to be ascending by tag value (the decoder + /// does not mind unordered entries). + pub(crate) entries: BTreeMap, + pub(crate) next_ifd: Option, +} + +impl Directory { + /// Create a directory in an initial state without entries. Note that an empty directory can + /// not be encoded in a file, it must contain at least one entry. + pub fn empty() -> Self { + Directory { + entries: BTreeMap::new(), + next_ifd: None, + } + } + + /// Retrieve the value associated with a tag. + pub fn get(&self, tag: Tag) -> Option<&Entry> { + self.entries.get(&tag.to_u16()) + } + + /// Check if the directory contains a specified tag. + pub fn contains(&self, tag: Tag) -> bool { + self.entries.contains_key(&tag.to_u16()) + } + + /// Iterate over all known and unknown tags in this directory. + pub fn iter(&self) -> impl Iterator + '_ { + self.entries + .iter() + .map(|(k, v)| (Tag::from_u16_exhaustive(*k), v)) + } + + /// Insert additional entries into the directory. + /// + /// Note that a directory can contain at most `u16::MAX` values. There may be one entry that + /// does not fit into the directory. This entry is silently ignored (please check [`Self::len`] + /// to detect the condition). Providing a tag multiple times or a tag that already exists + /// within this directory overwrites the entry. + pub fn extend(&mut self, iter: impl IntoIterator) { + // Code size conscious extension, avoid monomorphic extensions with the assumption of these + // not being performance sensitive in practice. (Maybe we have a polymorphic interface for + // the crate usage in the future. + self.extend_inner(iter.into_iter().by_ref()) + } + + /// Get the number of entries. + pub fn len(&self) -> usize { + // The keys are `u16`. Since IFDs are required to have at least one entry this would have + // been a trivial thing to do in the specification by storing it minus one but alas. In + // BigTIFF the count is stored as 8-bit anyways. + self.entries.len() + } + + /// Check if there are any entries in this directory. Note that an empty directory can not be + /// encoded in the file, it must contain at least one entry. + pub fn is_empty(&self) -> bool { + self.entries.is_empty() + } + + /// Get the pointer to the next IFD, if it was defined. + pub fn next(&self) -> Option { + self.next_ifd.map(|n| IfdPointer(n.get())) + } + + pub fn set_next(&mut self, next: Option) { + self.next_ifd = next.and_then(|n| NonZeroU64::new(n.0)); + } + + fn extend_inner(&mut self, iter: &mut dyn Iterator) { + for (tag, entry) in iter { + // If the tag is already present, it will be overwritten. + let map_entry = self.entries.entry(tag.to_u16()); + + match map_entry { + std::collections::btree_map::Entry::Vacant(vacant_entry) => { + vacant_entry.insert(entry); + } + std::collections::btree_map::Entry::Occupied(mut occupied_entry) => { + occupied_entry.insert(entry); + } + } + } + } +} + +impl fmt::Debug for Directory { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Directory") + .field( + "entries", + &self.entries.iter().map(|(k, v)| (Tag::from_u16(*k), v)), + ) + .field("next_ifd", &self.next_ifd) + .finish() + } +} + +#[cfg(test)] +mod tests { + use super::Directory; + use crate::{decoder::ifd::Entry, tags::Tag}; + + #[test] + fn directory_multiple_entries() { + let mut dir = Directory::empty(); + assert_eq!(dir.len(), 0); + + dir.extend((0..=u16::MAX).map(|i| { + let tag = Tag::Unknown(1); + let entry = Entry::new_u64(crate::tags::Type::BYTE, i.into(), [0; 8]); + (tag, entry) + })); + + assert_eq!(dir.len(), 1, "Only one tag was ever modified"); + + assert_eq!( + dir.get(Tag::Unknown(1)) + .expect("tag 1 should be present after this chain") + .count(), + u16::MAX.into() + ); + } + + #[test] + fn iteration_order() { + let mut dir = Directory::empty(); + assert_eq!(dir.len(), 0); + + let fake_entry = Entry::new_u64(crate::tags::Type::BYTE, 0, [0; 8]); + dir.extend((0..32).map(|i| { + let tag = Tag::Unknown(i); + let entry = fake_entry.clone(); + (tag, entry) + })); + + let iter_order: Vec = dir.iter().map(|(tag, _e)| tag.to_u16()).collect(); + assert_eq!( + iter_order, + (0..32).collect::>(), + "Tags must be in ascending order according to the specification" + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/colortype.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/colortype.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/colortype.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/colortype.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,31 @@ use crate::tags::{PhotometricInterpretation, SampleFormat}; +macro_rules! integer_horizontal_predict { + () => { + fn horizontal_predict(row: &[Self::Inner], result: &mut Vec) { + let sample_size = Self::SAMPLE_FORMAT.len(); + + if row.len() < sample_size { + debug_assert!(false); + return; + } + + let (start, rest) = row.split_at(sample_size); + + result.extend_from_slice(start); + if result.capacity() - result.len() < rest.len() { + return; + } + + result.extend( + row.into_iter() + .zip(rest) + .map(|(prev, current)| current.wrapping_sub(*prev)), + ); + } + }; +} + /// Trait for different colortypes that can be encoded. pub trait ColorType { /// The type of each sample of this colortype @@ -10,6 +36,8 @@ const BITS_PER_SAMPLE: &'static [u16]; /// The value of the tiff tag `SampleFormat` const SAMPLE_FORMAT: &'static [SampleFormat]; + + fn horizontal_predict(row: &[Self::Inner], result: &mut Vec); } pub struct Gray8; @@ -18,6 +46,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint]; + + integer_horizontal_predict!(); } pub struct GrayI8; @@ -26,6 +56,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Int]; + + integer_horizontal_predict!(); } pub struct Gray16; @@ -34,6 +66,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[16]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint]; + + integer_horizontal_predict!(); } pub struct GrayI16; @@ -42,6 +76,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[16]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Int]; + + integer_horizontal_predict!(); } pub struct Gray32; @@ -50,6 +86,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint]; + + integer_horizontal_predict!(); } pub struct GrayI32; @@ -58,6 +96,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Int]; + + integer_horizontal_predict!(); } pub struct Gray32Float; @@ -66,6 +106,10 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP]; + + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct Gray64; @@ -74,6 +118,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint]; + + integer_horizontal_predict!(); } pub struct GrayI64; @@ -82,6 +128,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Int]; + + integer_horizontal_predict!(); } pub struct Gray64Float; @@ -90,6 +138,10 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; const BITS_PER_SAMPLE: &'static [u16] = &[64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP]; + + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct RGB8; @@ -98,6 +150,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 3]; + + integer_horizontal_predict!(); } pub struct RGB16; @@ -106,6 +160,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[16, 16, 16]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 3]; + + integer_horizontal_predict!(); } pub struct RGB32; @@ -114,6 +170,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 3]; + + integer_horizontal_predict!(); } pub struct RGB32Float; @@ -122,6 +180,9 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 3]; + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct RGB64; @@ -130,6 +191,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 3]; + + integer_horizontal_predict!(); } pub struct RGB64Float; @@ -138,6 +201,9 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 3]; + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct RGBA8; @@ -146,6 +212,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8, 8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct RGBA16; @@ -154,6 +222,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[16, 16, 16, 16]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct RGBA32; @@ -162,6 +232,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct RGBA32Float; @@ -170,6 +242,9 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 4]; + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct RGBA64; @@ -178,6 +253,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct RGBA64Float; @@ -186,6 +263,9 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 4]; + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct CMYK8; @@ -194,6 +274,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8, 8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct CMYK16; @@ -202,6 +284,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[16, 16, 16, 16]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct CMYK32; @@ -210,6 +294,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct CMYK32Float; @@ -218,6 +304,10 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[32, 32, 32, 32]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 4]; + + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct CMYK64; @@ -226,6 +316,8 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 4]; + + integer_horizontal_predict!(); } pub struct CMYK64Float; @@ -234,6 +326,10 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; const BITS_PER_SAMPLE: &'static [u16] = &[64, 64, 64, 64]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::IEEEFP; 4]; + + fn horizontal_predict(_: &[Self::Inner], _: &mut Vec) { + unreachable!() + } } pub struct YCbCr8; @@ -242,4 +338,16 @@ const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::YCbCr; const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8]; const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 3]; + + integer_horizontal_predict!(); +} + +pub struct CMYKA8; +impl ColorType for CMYKA8 { + type Inner = u8; + const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; + const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8, 8, 8]; + const SAMPLE_FORMAT: &'static [SampleFormat] = &[SampleFormat::Uint; 5]; + + integer_horizontal_predict!(); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/deflate.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/deflate.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/deflate.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/deflate.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,6 +1,5 @@ -use crate::{encoder::compression::*, tags::CompressionMethod}; +use crate::encoder::compression::*; use flate2::{write::ZlibEncoder, Compression as FlateCompression}; -use std::io::Write; /// The Deflate algorithm used to compress image data in TIFF files. #[derive(Debug, Clone, Copy)] @@ -12,21 +11,17 @@ /// It allows trading compression ratio for compression speed. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] +#[derive(Default)] pub enum DeflateLevel { /// The fastest possible compression mode. Fast = 1, /// The conserative choice between speed and ratio. + #[default] Balanced = 6, /// The best compression available with Deflate. Best = 9, } -impl Default for DeflateLevel { - fn default() -> Self { - DeflateLevel::Balanced - } -} - impl Deflate { /// Create a new deflate compressor with a specific level of compression. pub fn with_level(level: DeflateLevel) -> Self { diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/lzw.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/lzw.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/lzw.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/lzw.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,4 @@ -use crate::{encoder::compression::*, tags::CompressionMethod}; -use std::io::Write; +use crate::encoder::compression::*; use weezl::encode::Encoder as LZWEncoder; /// The LZW algorithm used to compress image data in TIFF files. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,13 +1,19 @@ use crate::tags::CompressionMethod; use std::io::{self, Write}; +#[cfg(feature = "deflate")] mod deflate; +#[cfg(feature = "lzw")] mod lzw; mod packbits; mod uncompressed; +#[cfg(feature = "deflate")] pub use self::deflate::{Deflate, DeflateLevel}; + +#[cfg(feature = "lzw")] pub use self::lzw::Lzw; + pub use self::packbits::Packbits; pub use self::uncompressed::Uncompressed; @@ -28,9 +34,12 @@ } /// An enum to store each compression algorithm. +#[non_exhaustive] pub enum Compressor { Uncompressed(Uncompressed), + #[cfg(feature = "lzw")] Lzw(Lzw), + #[cfg(feature = "deflate")] Deflate(Deflate), Packbits(Packbits), } @@ -46,7 +55,9 @@ fn write_to(&mut self, writer: &mut W, bytes: &[u8]) -> Result { match self { Compressor::Uncompressed(algorithm) => algorithm.write_to(writer, bytes), + #[cfg(feature = "lzw")] Compressor::Lzw(algorithm) => algorithm.write_to(writer, bytes), + #[cfg(feature = "deflate")] Compressor::Deflate(algorithm) => algorithm.write_to(writer, bytes), Compressor::Packbits(algorithm) => algorithm.write_to(writer, bytes), } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/packbits.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/packbits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/packbits.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/packbits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,5 @@ -use crate::{encoder::compression::*, tags::CompressionMethod}; -use std::io::{BufWriter, Error, ErrorKind, Write}; +use crate::encoder::compression::*; +use std::io::{BufWriter, Error, ErrorKind}; /// Compressor that uses the Packbits[^note] algorithm to compress bytes. /// diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/uncompressed.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/uncompressed.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/compression/uncompressed.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/compression/uncompressed.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,4 @@ -use crate::{encoder::compression::*, tags::CompressionMethod}; -use std::io::Write; +use crate::encoder::compression::*; /// The default algorithm which does not compress at all. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,18 +2,17 @@ use std::{ cmp, - collections::BTreeMap, - convert::{TryFrom, TryInto}, io::{self, Seek, Write}, marker::PhantomData, mem, - num::TryFromIntError, + num::{NonZeroU64, TryFromIntError}, }; use crate::{ - error::TiffResult, - tags::{CompressionMethod, ResolutionUnit, Tag}, - TiffError, TiffFormatError, + decoder::ifd::Entry, + error::{TiffResult, UsageError}, + tags::{CompressionMethod, IfdPointer, ResolutionUnit, SampleFormat, Tag, Type}, + Directory, TiffError, TiffFormatError, }; pub mod colortype; @@ -22,9 +21,62 @@ mod writer; use self::colortype::*; +use self::compression::Compression as Comp; use self::compression::*; use self::writer::*; +/// Type of prediction to prepare the image with. +/// +/// Image data can be very unpredictable, and thus very hard to compress. Predictors are simple +/// passes ran over the image data to prepare it for compression. This is mostly used for LZW +/// compression, where using [Predictor::Horizontal] we see a 35% improvement in compression +/// ratio over the unpredicted compression ! +/// +/// [Predictor::FloatingPoint] is currently not supported. +pub type Predictor = crate::tags::Predictor; +#[cfg(feature = "deflate")] +pub type DeflateLevel = compression::DeflateLevel; + +#[derive(Clone, Copy, PartialEq)] +pub enum Compression { + Uncompressed, + #[cfg(feature = "lzw")] + Lzw, + #[cfg(feature = "deflate")] + Deflate(DeflateLevel), + Packbits, +} + +impl Default for Compression { + fn default() -> Self { + Self::Uncompressed + } +} + +impl Compression { + fn tag(&self) -> CompressionMethod { + match self { + Compression::Uncompressed => CompressionMethod::None, + #[cfg(feature = "lzw")] + Compression::Lzw => CompressionMethod::LZW, + #[cfg(feature = "deflate")] + Compression::Deflate(_) => CompressionMethod::Deflate, + Compression::Packbits => CompressionMethod::PackBits, + } + } + + fn get_algorithm(&self) -> Compressor { + match self { + Compression::Uncompressed => compression::Uncompressed {}.get_algorithm(), + #[cfg(feature = "lzw")] + Compression::Lzw => compression::Lzw {}.get_algorithm(), + #[cfg(feature = "deflate")] + Compression::Deflate(level) => compression::Deflate::with_level(*level).get_algorithm(), + Compression::Packbits => compression::Packbits {}.get_algorithm(), + } + } +} + /// Encoder for Tiff and BigTiff files. /// /// With this type you can get a `DirectoryEncoder` or a `ImageEncoder` @@ -53,6 +105,10 @@ pub struct TiffEncoder { writer: TiffWriter, kind: PhantomData, + predictor: Predictor, + compression: Compression, + /// The offset of the last main image directory's `next` field. + last_ifd_chain: NonZeroU64, } /// Constructor functions to create standard Tiff files. @@ -81,40 +137,70 @@ impl TiffEncoder { /// Creates a new Tiff or BigTiff encoder, inferred from the return type. pub fn new_generic(writer: W) -> TiffResult { - let mut encoder = TiffEncoder { - writer: TiffWriter::new(writer), + let mut writer = TiffWriter::new(writer); + K::write_header(&mut writer)?; + + let last_ifd_chain = NonZeroU64::new(writer.previous_ifd_pointer::()) + .expect("Header is at a non-zero offset"); + + Ok(TiffEncoder { + writer, kind: PhantomData, - }; + predictor: Predictor::None, + compression: Compression::Uncompressed, + last_ifd_chain, + }) + } - K::write_header(&mut encoder.writer)?; + /// Set the predictor to use + /// + /// A predictor is used to simplify the file before writing it. This is very + /// useful when writing a file compressed using LZW as it can improve efficiency + pub fn with_predictor(mut self, predictor: Predictor) -> Self { + self.predictor = predictor; - Ok(encoder) + self + } + + /// Set the compression method to use + pub fn with_compression(mut self, compression: Compression) -> Self { + self.compression = compression; + + self } /// Create a [`DirectoryEncoder`] to encode an ifd directory. - pub fn new_directory(&mut self) -> TiffResult> { - DirectoryEncoder::new(&mut self.writer) + #[deprecated = "`image_directory` replaced the old behavior and clarifies the intent"] + #[doc(hidden)] + pub fn new_directory(&mut self) -> TiffResult> { + Self::chain_directory(&mut self.writer, &mut self.last_ifd_chain) } - /// Create an [`ImageEncoder`] to encode an image one slice at a time. - pub fn new_image( - &mut self, - width: u32, - height: u32, - ) -> TiffResult> { - let encoder = DirectoryEncoder::new(&mut self.writer)?; - ImageEncoder::new(encoder, width, height) + /// Create a [`DirectoryEncoder`] to encode an ifd directory. + /// + /// The caller is responsible for ensuring that the directory is a valid image in the main TIFF + /// IFD sequence. To encode additional directories that are not linked into the sequence, use + /// [`Self::extra_directory`][TiffEncoder::extra_directory]. + pub fn image_directory(&mut self) -> TiffResult> { + Self::chain_directory(&mut self.writer, &mut self.last_ifd_chain) + } + + /// Create a [`DirectoryEncoder`] to encode an ifd directory. + /// + /// The directory is not linked into the sequence of directories. For instance, encode Exif + /// directories or SubIfd directories with this method. + pub fn extra_directory(&mut self) -> TiffResult> { + Self::unchained_directory(&mut self.writer) } /// Create an [`ImageEncoder`] to encode an image one slice at a time. - pub fn new_image_with_compression( + pub fn new_image( &mut self, width: u32, height: u32, - compression: D, - ) -> TiffResult> { - let encoder = DirectoryEncoder::new(&mut self.writer)?; - ImageEncoder::with_compression(encoder, width, height, compression) + ) -> TiffResult> { + let encoder = Self::chain_directory(&mut self.writer, &mut self.last_ifd_chain)?; + ImageEncoder::new(encoder, width, height, self.compression, self.predictor) } /// Convenience function to write an entire image from memory. @@ -127,26 +213,22 @@ where [C::Inner]: TiffValue, { - let encoder = DirectoryEncoder::new(&mut self.writer)?; - let image: ImageEncoder = ImageEncoder::new(encoder, width, height)?; + let encoder = Self::chain_directory(&mut self.writer, &mut self.last_ifd_chain)?; + let image: ImageEncoder = + ImageEncoder::new(encoder, width, height, self.compression, self.predictor)?; image.write_data(data) } - /// Convenience function to write an entire image from memory with a given compression. - pub fn write_image_with_compression( - &mut self, - width: u32, - height: u32, - compression: D, - data: &[C::Inner], - ) -> TiffResult<()> - where - [C::Inner]: TiffValue, - { - let encoder = DirectoryEncoder::new(&mut self.writer)?; - let image: ImageEncoder = - ImageEncoder::with_compression(encoder, width, height, compression)?; - image.write_data(data) + fn chain_directory<'lt>( + writer: &'lt mut TiffWriter, + last_ifd_chain: &'lt mut NonZeroU64, + ) -> TiffResult> { + let last_ifd = *last_ifd_chain; + DirectoryEncoder::new(writer, Some(last_ifd), Some(last_ifd_chain)) + } + + fn unchained_directory(writer: &mut TiffWriter) -> TiffResult> { + DirectoryEncoder::new(writer, None, None) } } @@ -156,95 +238,163 @@ /// Encoding can silently fail while this is dropping. pub struct DirectoryEncoder<'a, W: 'a + Write + Seek, K: TiffKind> { writer: &'a mut TiffWriter, - dropped: bool, + /// The position of the previous directory's `next` field, if any. + chained_ifd_pos: Option, + /// An output to write the `next` field offset on completion. + write_chain: Option<&'a mut NonZeroU64>, + kind: PhantomData, // We use BTreeMap to make sure tags are written in correct order - ifd_pointer_pos: u64, - ifd: BTreeMap>, + directory: Directory, + dropped: bool, +} + +/// The offset of an encoded directory in the file. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct DirectoryOffset { + /// The start of the directory as a Tiff value. + /// + /// This is a bit of a wart in the strongly typed design of the encoder. The value _type_ must + /// itself know how to be represented in the Tiff file but that may differ based on endianess + /// as well as the offset size (`u32` or BigTIFF's `u64`). Thankfully we're allowed to + /// represent offsets with `LONG` or `IFD` in the usual case. + pub offset: K::OffsetType, + /// The start of the directory as a pure offset. + pub pointer: IfdPointer, + /// The offset of its sequence link field, in our private representation. + ifd_chain: NonZeroU64, + /// The kind of Tiff file the offset is for. + kind: PhantomData, } impl<'a, W: 'a + Write + Seek, K: TiffKind> DirectoryEncoder<'a, W, K> { - fn new(writer: &'a mut TiffWriter) -> TiffResult { - // the previous word is the IFD offset position - let ifd_pointer_pos = writer.offset() - mem::size_of::() as u64; + /// Construct a directory writer appending to data, assuming the writer is currently positioned + /// immediately after a previously written IFD to which to append. + fn new( + writer: &'a mut TiffWriter, + chained_ifd_pos: Option, + chain_into: Option<&'a mut NonZeroU64>, + ) -> TiffResult { writer.pad_word_boundary()?; // TODO: Do we need to adjust this for BigTiff? - Ok(DirectoryEncoder { + Ok(Self { writer, + chained_ifd_pos, + write_chain: chain_into, + kind: PhantomData, + directory: Directory::empty(), dropped: false, - ifd_pointer_pos, - ifd: BTreeMap::new(), }) } /// Write a single ifd tag. pub fn write_tag(&mut self, tag: Tag, value: T) -> TiffResult<()> { + // Encodes the value if necessary. In the current bytes all integers are taken as native + // endian and thus transparent but this keeps the interface generic. let mut bytes = Vec::with_capacity(value.bytes()); { let mut writer = TiffWriter::new(&mut bytes); value.write(&mut writer)?; } - self.ifd.insert( - tag.to_u16(), - DirectoryEntry { - data_type: ::FIELD_TYPE.to_u16(), + let entry = Self::write_value( + self.writer, + &DirectoryEntry { + data_type: ::FIELD_TYPE, count: value.count().try_into()?, data: bytes, }, - ); + )?; + + self.directory.extend([(tag, entry)]); Ok(()) } - fn write_directory(&mut self) -> TiffResult { - // Start by writing out all values - for &mut DirectoryEntry { - data: ref mut bytes, - .. - } in self.ifd.values_mut() - { - let data_bytes = mem::size_of::(); + /// Write some data to the tiff file, the offset of the data is returned. + /// + /// This could be used to write tiff strips. + pub fn write_data(&mut self, value: T) -> TiffResult { + let offset = self.writer.offset(); + value.write(self.writer)?; + Ok(offset) + } - if bytes.len() > data_bytes { - let offset = self.writer.offset(); - self.writer.write_bytes(bytes)?; - *bytes = vec![0; data_bytes]; - let mut writer = TiffWriter::new(bytes as &mut [u8]); - K::write_offset(&mut writer, offset)?; - } else { - while bytes.len() < data_bytes { - bytes.push(0); - } - } - } + /// Define the parent directory. + /// + /// Each directory has an offset based link to its successor, forming a linked list in the + /// file. The encoder writes its own offset into the parent's field when [`Self::finish`] is + /// called or it is dropped. This redefines the parent. An offset representation of the parent + /// must be acquired by finishing it with [`Self::finish_with_offsets`]. + pub fn set_parent(&mut self, offset: &DirectoryOffset) { + self.chained_ifd_pos = Some(offset.ifd_chain); + } + /// Write out the ifd directory itself. + pub fn finish(mut self) -> TiffResult<()> { + self.finish_internal()?; + Ok(()) + } + + pub fn finish_with_offsets(mut self) -> TiffResult> { + self.finish_internal() + } + + fn write_directory(&mut self) -> TiffResult { + // Start by turning all buffered unwritten values into entries. let offset = self.writer.offset(); + K::write_entry_count(self.writer, self.directory.len())?; - K::write_entry_count(self.writer, self.ifd.len())?; - for ( - tag, - DirectoryEntry { - data_type: field_type, - count, - data: offset, - }, - ) in self.ifd.iter() - { - self.writer.write_u16(*tag)?; - self.writer.write_u16(*field_type)?; - (*count).write(self.writer)?; - self.writer.write_bytes(offset)?; + let offset_bytes = mem::size_of::(); + for (tag, entry) in self.directory.iter() { + self.writer.write_u16(tag.to_u16())?; + self.writer.write_u16(entry.field_type().to_u16())?; + let count = K::convert_offset(entry.count())?; + count.write(self.writer)?; + self.writer.write_bytes(&entry.offset()[..offset_bytes])?; } Ok(offset) } - /// Write some data to the tiff file, the offset of the data is returned. - /// - /// This could be used to write tiff strips. - pub fn write_data(&mut self, value: T) -> TiffResult { - let offset = self.writer.offset(); - value.write(self.writer)?; - Ok(offset) + fn write_value( + writer: &mut TiffWriter, + value: &DirectoryEntry, + ) -> TiffResult { + let &DirectoryEntry { + data: ref bytes, + ref count, + data_type, + } = value; + + let in_entry_bytes = mem::size_of::(); + let mut offset_bytes = [0; 8]; + + if bytes.len() > in_entry_bytes { + let offset = writer.offset(); + writer.write_bytes(bytes)?; + + let offset = K::convert_offset(offset)?; + offset_bytes[..offset.bytes()].copy_from_slice(&offset.data()); + } else { + // Note: we have indicated our native byte order in the header, hence this + // corresponds to our byte order no matter the value type. + offset_bytes[..bytes.len()].copy_from_slice(bytes); + } + + // Undoing some hidden type. Offset is either u32 or u64. Due to the trait API being public + // and some oversight, we can not clone the `count: K::OffsetType` and thus not convert it. + // Instead, write it to a buffer... + let mut count_bytes = [0; 8]; + // Nominally Cow but we only expect `Cow::Borrowed`. + count_bytes[..count.bytes()].copy_from_slice(&count.data()); + + Ok(if in_entry_bytes == 4 { + let count = u32::from_ne_bytes(count_bytes[..4].try_into().unwrap()); + Entry::new(data_type, count, offset_bytes[..4].try_into().unwrap()) + } else { + debug_assert_eq!(in_entry_bytes, 8); + let count = u64::from_ne_bytes(count_bytes); + Entry::new_u64(data_type, count, offset_bytes) + }) } /// Provides the number of bytes written by the underlying TiffWriter during the last call. @@ -252,23 +402,40 @@ self.writer.last_written() } - fn finish_internal(&mut self) -> TiffResult<()> { + fn finish_internal(&mut self) -> TiffResult> { let ifd_pointer = self.write_directory()?; - let curr_pos = self.writer.offset(); + let offset = K::convert_offset(ifd_pointer)?; + + if let Some(prior) = self.chained_ifd_pos { + let curr_pos = self.writer.offset(); + + self.writer.goto_offset(prior.get())?; + // Note how we are not writing the `offset` type itself here as doing so would need to + // go through the `TiffValue` trait—the type is not constrained by much. But for the + // trait we need a `TiffWriter` which comes with a bunch of additional state such as + // compressor etc. that we have no need for. + K::write_offset(self.writer, ifd_pointer)?; + + self.writer.goto_offset(curr_pos)?; + } - self.writer.goto_offset(self.ifd_pointer_pos)?; - K::write_offset(self.writer, ifd_pointer)?; - self.writer.goto_offset(curr_pos)?; K::write_offset(self.writer, 0)?; - self.dropped = true; + let ifd_chain = NonZeroU64::new(self.writer.previous_ifd_pointer::()) + .expect("IFD chain field is at a non-zero offset"); - Ok(()) - } + if let Some(prior) = self.write_chain.take() { + *prior = ifd_chain; + } - /// Write out the ifd directory. - pub fn finish(mut self) -> TiffResult<()> { - self.finish_internal() + self.dropped = true; + + Ok(DirectoryOffset { + pointer: IfdPointer(ifd_pointer), + offset, + ifd_chain, + kind: PhantomData, + }) } } @@ -313,13 +480,7 @@ /// # } /// ``` /// You can also call write_data function wich will encode by strip and finish -pub struct ImageEncoder< - 'a, - W: 'a + Write + Seek, - C: ColorType, - K: TiffKind, - D: Compression = Uncompressed, -> { +pub struct ImageEncoder<'a, W: 'a + Write + Seek, C: ColorType, K: TiffKind> { encoder: DirectoryEncoder<'a, W, K>, strip_idx: u64, strip_count: u64, @@ -330,25 +491,30 @@ strip_offsets: Vec, strip_byte_count: Vec, dropped: bool, - compression: D, + compression: Compression, + predictor: Predictor, _phantom: ::std::marker::PhantomData, } -impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind, D: Compression> - ImageEncoder<'a, W, T, K, D> -{ - fn new(encoder: DirectoryEncoder<'a, W, K>, width: u32, height: u32) -> TiffResult - where - D: Default, - { - Self::with_compression(encoder, width, height, D::default()) +impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T, K> { + fn sanity_check(compression: Compression, predictor: Predictor) -> TiffResult<()> { + match (predictor, compression, T::SAMPLE_FORMAT[0]) { + (Predictor::Horizontal, _, SampleFormat::IEEEFP | SampleFormat::Void) => { + Err(TiffError::UsageError(UsageError::PredictorIncompatible)) + } + (Predictor::FloatingPoint, _, _) => { + Err(TiffError::UsageError(UsageError::PredictorUnavailable)) + } + _ => Ok(()), + } } - fn with_compression( + fn new( mut encoder: DirectoryEncoder<'a, W, K>, width: u32, height: u32, - compression: D, + compression: Compression, + predictor: Predictor, ) -> TiffResult { if width == 0 || height == 0 { return Err(TiffError::FormatError(TiffFormatError::InvalidDimensions( @@ -356,23 +522,26 @@ ))); } + Self::sanity_check(compression, predictor)?; + let row_samples = u64::from(width) * u64::try_from(::BITS_PER_SAMPLE.len())?; let row_bytes = row_samples * u64::from(::BYTE_LEN); // Limit the strip size to prevent potential memory and security issues. // Also keep the multiple strip handling 'oiled' let rows_per_strip = { - match D::COMPRESSION_METHOD { + match compression.tag() { CompressionMethod::PackBits => 1, // Each row must be packed separately. Do not compress across row boundaries - _ => (1_000_000 + row_bytes - 1) / row_bytes, + _ => 1_000_000_u64.div_ceil(row_bytes), } }; - let strip_count = (u64::from(height) + rows_per_strip - 1) / rows_per_strip; + let strip_count = u64::from(height).div_ceil(rows_per_strip); encoder.write_tag(Tag::ImageWidth, width)?; encoder.write_tag(Tag::ImageLength, height)?; - encoder.write_tag(Tag::Compression, D::COMPRESSION_METHOD.to_u16())?; + encoder.write_tag(Tag::Compression, compression.tag().to_u16())?; + encoder.write_tag(Tag::Predictor, predictor.to_u16())?; encoder.write_tag(Tag::BitsPerSample, ::BITS_PER_SAMPLE)?; let sample_format: Vec<_> = ::SAMPLE_FORMAT.iter().map(|s| s.to_u16()).collect(); @@ -401,6 +570,7 @@ strip_byte_count: Vec::new(), dropped: false, compression, + predictor, _phantom: ::std::marker::PhantomData, }) } @@ -433,7 +603,18 @@ } // Write the (possible compressed) data to the encoder. - let offset = self.encoder.write_data(value)?; + let offset = match self.predictor { + Predictor::None => self.encoder.write_data(value)?, + Predictor::Horizontal => { + let mut row_result = Vec::with_capacity(value.len()); + for row in value.chunks_exact(self.row_samples as usize) { + T::horizontal_predict(row, &mut row_result); + } + self.encoder.write_data(row_result.as_slice())? + } + _ => unimplemented!(), + }; + let byte_count = self.encoder.last_written() as usize; self.strip_offsets.push(K::convert_offset(offset)?); @@ -524,13 +705,13 @@ self.encoder.write_tag(Tag::RowsPerStrip, value)?; let value: u64 = value as u64; - self.strip_count = (self.height as u64 + value - 1) / value; + self.strip_count = (self.height as u64).div_ceil(value); self.rows_per_strip = value; Ok(()) } - fn finish_internal(&mut self) -> TiffResult<()> { + fn finish_internal(&mut self) -> TiffResult> { self.encoder .write_tag(Tag::StripOffsets, K::convert_slice(&self.strip_offsets))?; self.encoder.write_tag( @@ -549,13 +730,12 @@ /// Write out image and ifd directory. pub fn finish(mut self) -> TiffResult<()> { - self.finish_internal() + self.finish_internal()?; + Ok(()) } } -impl<'a, W: Write + Seek, C: ColorType, K: TiffKind, D: Compression> Drop - for ImageEncoder<'a, W, C, K, D> -{ +impl<'a, W: Write + Seek, C: ColorType, K: TiffKind> Drop for ImageEncoder<'a, W, C, K> { fn drop(&mut self) { if !self.dropped { let _ = self.finish_internal(); @@ -564,7 +744,7 @@ } struct DirectoryEntry { - data_type: u16, + data_type: Type, count: S, data: Vec, } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/tiff_value.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/tiff_value.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/tiff_value.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/tiff_value.rs 2006-07-24 01:21:28.000000000 +0000 @@ -15,7 +15,7 @@ /// Access this value as an contiguous sequence of bytes. /// If their is no trivial representation, allocate it on the heap. - fn data(&self) -> Cow<[u8]>; + fn data(&self) -> Cow<'_, [u8]>; /// Write this value to a TiffWriter. /// While the default implementation will work in all cases, it may require unnecessary allocations. @@ -34,7 +34,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(self) } } @@ -47,7 +47,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i8_as_ne_bytes(self)) } } @@ -60,7 +60,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u16_as_ne_bytes(self)) } } @@ -73,7 +73,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i16_as_ne_bytes(self)) } } @@ -86,7 +86,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u32_as_ne_bytes(self)) } } @@ -99,7 +99,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i32_as_ne_bytes(self)) } } @@ -112,7 +112,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u64_as_ne_bytes(self)) } } @@ -125,7 +125,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i64_as_ne_bytes(self)) } } @@ -138,7 +138,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { // We write using native endian so this should be safe Cow::Borrowed(bytecast::f32_as_ne_bytes(self)) } @@ -152,7 +152,7 @@ self.len() } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { // We write using native endian so this should be safe Cow::Borrowed(bytecast::f64_as_ne_bytes(self)) } @@ -171,7 +171,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(from_ref(self)) } } @@ -189,7 +189,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i8_as_ne_bytes(from_ref(self))) } } @@ -207,7 +207,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u16_as_ne_bytes(from_ref(self))) } } @@ -225,7 +225,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i16_as_ne_bytes(from_ref(self))) } } @@ -243,7 +243,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u32_as_ne_bytes(from_ref(self))) } } @@ -261,7 +261,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i32_as_ne_bytes(from_ref(self))) } } @@ -279,7 +279,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u64_as_ne_bytes(from_ref(self))) } } @@ -297,7 +297,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::i64_as_ne_bytes(from_ref(self))) } } @@ -315,7 +315,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::f32_as_ne_bytes(from_ref(self))) } } @@ -333,7 +333,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::f64_as_ne_bytes(from_ref(self))) } } @@ -351,7 +351,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u32_as_ne_bytes(from_ref(&self.0))) } } @@ -369,7 +369,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Borrowed(bytecast::u64_as_ne_bytes(from_ref(&self.0))) } } @@ -388,7 +388,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Owned({ let first_dword = bytecast::u32_as_ne_bytes(from_ref(&self.n)); let second_dword = bytecast::u32_as_ne_bytes(from_ref(&self.d)); @@ -411,7 +411,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Owned({ let first_dword = bytecast::i32_as_ne_bytes(from_ref(&self.n)); let second_dword = bytecast::i32_as_ne_bytes(from_ref(&self.d)); @@ -438,7 +438,7 @@ } } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { Cow::Owned({ if self.is_ascii() && !self.bytes().any(|b| b == 0) { let bytes: &[u8] = self.as_bytes(); @@ -450,7 +450,7 @@ } } -impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T { +impl TiffValue for &'_ T { const BYTE_LEN: u8 = T::BYTE_LEN; const FIELD_TYPE: Type = T::FIELD_TYPE; @@ -462,7 +462,7 @@ (*self).write(writer) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { T::data(self) } } @@ -484,7 +484,7 @@ Ok(()) } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { let mut buf: Vec = Vec::with_capacity(Self::BYTE_LEN as usize * self.len()); for x in self { buf.extend_from_slice(&x.data()); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/encoder/writer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/encoder/writer.rs 2006-07-24 01:21:28.000000000 +0000 @@ -69,6 +69,10 @@ self.offset } + pub(crate) fn previous_ifd_pointer(&self) -> u64 { + self.offset() - core::mem::size_of::() as u64 + } + pub fn last_written(&self) -> u64 { self.byte_count } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/error.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/error.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/error.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,294 +1,192 @@ -use std::error::Error; -use std::fmt; -use std::fmt::Display; use std::io; use std::str; use std::string; -use std::sync::Arc; -use jpeg::UnsupportedFeature; +use quick_error::quick_error; -use crate::decoder::{ifd::Value, ChunkType}; +use crate::decoder::ChunkType; use crate::tags::{ CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag, }; use crate::ColorType; -use crate::weezl::LzwError; - -/// Tiff error kinds. -#[derive(Debug)] -pub enum TiffError { - /// The Image is not formatted properly. - FormatError(TiffFormatError), - - /// The Decoder does not support features required by the image. - UnsupportedError(TiffUnsupportedError), - - /// An I/O Error occurred while decoding the image. - IoError(io::Error), - - /// The Limits of the Decoder is exceeded. - LimitsExceeded, - - /// An integer conversion to or from a platform size failed, either due to - /// limits of the platform size or limits of the format. - IntSizeError, - - /// The image does not support the requested operation - UsageError(UsageError), -} - -/// The image is not formatted properly. -/// -/// This indicates that the encoder producing the image might behave incorrectly or that the input -/// file has been corrupted. -/// -/// The list of variants may grow to incorporate errors of future features. Matching against this -/// exhaustively is not covered by interface stability guarantees. -#[derive(Debug, Clone, PartialEq)] -#[non_exhaustive] -pub enum TiffFormatError { - TiffSignatureNotFound, - TiffSignatureInvalid, - ImageFileDirectoryNotFound, - InconsistentSizesEncountered, - UnexpectedCompressedData { - actual_bytes: usize, - required_bytes: usize, - }, - InconsistentStripSamples { - actual_samples: usize, - required_samples: usize, - }, - InvalidDimensions(u32, u32), - InvalidTag, - InvalidTagValueType(Tag), - RequiredTagNotFound(Tag), - UnknownPredictor(u16), - UnknownPlanarConfiguration(u16), - ByteExpected(Value), - UnsignedIntegerExpected(Value), - SignedIntegerExpected(Value), - Format(String), - RequiredTagEmpty(Tag), - StripTileTagConflict, - CycleInOffsets, - JpegDecoder(JpegDecoderError), - SamplesPerPixelIsZero, -} - -impl fmt::Display for TiffFormatError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use self::TiffFormatError::*; - match *self { - TiffSignatureNotFound => write!(fmt, "TIFF signature not found."), - TiffSignatureInvalid => write!(fmt, "TIFF signature invalid."), - ImageFileDirectoryNotFound => write!(fmt, "Image file directory not found."), - InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."), - UnexpectedCompressedData { - actual_bytes, - required_bytes, - } => { - write!( - fmt, - "Decompression returned different amount of bytes than expected: got {}, expected {}.", - actual_bytes, required_bytes - ) - } - InconsistentStripSamples { - actual_samples, - required_samples, - } => { - write!( - fmt, - "Inconsistent elements in strip: got {}, expected {}.", - actual_samples, required_samples - ) - } - InvalidDimensions(width, height) => write!(fmt, "Invalid dimensions: {}x{}.", width, height), - InvalidTag => write!(fmt, "Image contains invalid tag."), - InvalidTagValueType(ref tag) => { - write!(fmt, "Tag `{:?}` did not have the expected value type.", tag) - } - RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag), - UnknownPredictor(ref predictor) => { - write!(fmt, "Unknown predictor “{}” encountered", predictor) - } - UnknownPlanarConfiguration(ref planar_config) => { - write!(fmt, "Unknown planar configuration “{}” encountered", planar_config) - } - ByteExpected(ref val) => write!(fmt, "Expected byte, {:?} found.", val), - UnsignedIntegerExpected(ref val) => { - write!(fmt, "Expected unsigned integer, {:?} found.", val) - } - SignedIntegerExpected(ref val) => { - write!(fmt, "Expected signed integer, {:?} found.", val) - } - Format(ref val) => write!(fmt, "Invalid format: {:?}.", val), - RequiredTagEmpty(ref val) => write!(fmt, "Required tag {:?} was empty.", val), - StripTileTagConflict => write!(fmt, "File should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found."), - CycleInOffsets => write!(fmt, "File contained a cycle in the list of IFDs"), - JpegDecoder(ref error) => write!(fmt, "{}", error), - SamplesPerPixelIsZero => write!(fmt, "Samples per pixel is zero"), +quick_error! { + /// Tiff error kinds. + #[derive(Debug)] + pub enum TiffError { + /// The Image is not formatted properly. + FormatError(err: TiffFormatError) { + display("format error: {err}") + from() + source(err) } - } -} - -/// The Decoder does not support features required by the image. -/// -/// This only captures known failures for which the standard either does not require support or an -/// implementation has been planned but not yet completed. Some variants may become unused over -/// time and will then get deprecated before being removed. -/// -/// The list of variants may grow. Matching against this exhaustively is not covered by interface -/// stability guarantees. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum TiffUnsupportedError { - FloatingPointPredictor(ColorType), - HorizontalPredictor(ColorType), - InconsistentBitsPerSample(Vec), - InterpretationWithBits(PhotometricInterpretation, Vec), - UnknownInterpretation, - UnknownCompressionMethod, - UnsupportedCompressionMethod(CompressionMethod), - UnsupportedSampleDepth(u8), - UnsupportedSampleFormat(Vec), - UnsupportedColorType(ColorType), - UnsupportedBitsPerChannel(u8), - UnsupportedPlanarConfig(Option), - UnsupportedDataType, - UnsupportedInterpretation(PhotometricInterpretation), - UnsupportedJpegFeature(UnsupportedFeature), -} - -impl fmt::Display for TiffUnsupportedError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use self::TiffUnsupportedError::*; - match *self { - FloatingPointPredictor(color_type) => write!( - fmt, - "Floating point predictor for {:?} is unsupported.", - color_type - ), - HorizontalPredictor(color_type) => write!( - fmt, - "Horizontal predictor for {:?} is unsupported.", - color_type - ), - InconsistentBitsPerSample(ref bits_per_sample) => { - write!(fmt, "Inconsistent bits per sample: {:?}.", bits_per_sample) - } - InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => write!( - fmt, - "{:?} with {:?} bits per sample is unsupported", - photometric_interpretation, bits_per_sample - ), - UnknownInterpretation => write!( - fmt, - "The image is using an unknown photometric interpretation." - ), - UnknownCompressionMethod => write!(fmt, "Unknown compression method."), - UnsupportedCompressionMethod(method) => { - write!(fmt, "Compression method {:?} is unsupported", method) - } - UnsupportedSampleDepth(samples) => { - write!(fmt, "{} samples per pixel is unsupported.", samples) - } - UnsupportedSampleFormat(ref formats) => { - write!(fmt, "Sample format {:?} is unsupported.", formats) - } - UnsupportedColorType(color_type) => { - write!(fmt, "Color type {:?} is unsupported", color_type) - } - UnsupportedBitsPerChannel(bits) => { - write!(fmt, "{} bits per channel not supported", bits) - } - UnsupportedPlanarConfig(config) => { - write!(fmt, "Unsupported planar configuration “{:?}”.", config) - } - UnsupportedDataType => write!(fmt, "Unsupported data type."), - UnsupportedInterpretation(interpretation) => { - write!( - fmt, - "Unsupported photometric interpretation \"{:?}\".", - interpretation - ) - } - UnsupportedJpegFeature(ref unsupported_feature) => { - write!(fmt, "Unsupported JPEG feature {:?}", unsupported_feature) - } + /// The Decoder does not support features required by the image. + UnsupportedError(err: TiffUnsupportedError) { + display("unsupported error: {err}") + from() + source(err) } - } -} - -/// User attempted to use the Decoder in a way that is incompatible with a specific image. -/// -/// For example: attempting to read a tile from a stripped image. -#[derive(Debug)] -pub enum UsageError { - InvalidChunkType(ChunkType, ChunkType), - InvalidChunkIndex(u32), -} - -impl fmt::Display for UsageError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::UsageError::*; - match *self { - InvalidChunkType(expected, actual) => { - write!( - fmt, - "Requested operation is only valid for images with chunk encoding of type: {:?}, got {:?}.", - expected, actual - ) - } - InvalidChunkIndex(index) => write!(fmt, "Image chunk index ({}) requested.", index), + /// An I/O Error occurred while decoding the image. + IoError(err: io::Error) { + display("{err}") + from() + source(err) + } + /// The Limits of the Decoder is exceeded. + LimitsExceeded { + display("decoder limits exceeded") + } + /// An integer conversion to or from a platform size failed. + IntSizeError { + display("platform or format size limits exceeded") + } + /// The image does not support the requested operation + UsageError(err: UsageError) { + display("usage error: {err}") + from() + source(err) } } } -impl fmt::Display for TiffError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - TiffError::FormatError(ref e) => write!(fmt, "Format error: {}", e), - TiffError::UnsupportedError(ref f) => write!( - fmt, - "The Decoder does not support the \ - image format `{}`", - f - ), - TiffError::IoError(ref e) => e.fmt(fmt), - TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"), - TiffError::IntSizeError => write!(fmt, "Platform or format size limits exceeded"), - TiffError::UsageError(ref e) => write!(fmt, "Usage error: {}", e), +quick_error! { + /// The image is not formatted properly. + /// + /// This indicates that the encoder producing the image might behave incorrectly or that the + /// input file has been corrupted. + #[derive(Debug, Clone, PartialEq)] + #[non_exhaustive] + pub enum TiffFormatError { + TiffSignatureNotFound { + display("TIFF signature not found") + } + TiffSignatureInvalid { + display("TIFF signature invalid") + } + ImageFileDirectoryNotFound { + display("image file directory not found") + } + InconsistentSizesEncountered { + display("inconsistent sizes encountered") + } + InvalidDimensions(width: u32, height: u32) { + display("invalid dimensions: {width}x{height}") + } + InvalidTag { + display("image contains invalid tag") + } + InvalidTagValueType(tag: Tag) { + display("tag `{tag:?}` did not have the expected value type") + } + RequiredTagNotFound(tag: Tag) { + display("required tag `{tag:?}` not found") + } + UnknownPredictor(pred: u16) { + display("unknown predictor “{pred}” encountered") + } + UnknownPlanarConfiguration(cfg: u16) { + display("unknown planar configuration “{cfg}”") + } + InvalidTypeForTag { + display("tag has invalid type") + } + StripTileTagConflict { + display("file should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found") + } + CycleInOffsets { + display("file contained a cycle in the list of IFDs") + } + SamplesPerPixelIsZero { + display("samples per pixel is zero") + } + CompressedDataCorrupt(message: String) { + display("compressed data is corrupt: {message}") } } } -impl Error for TiffError { - fn description(&self) -> &str { - match *self { - TiffError::FormatError(..) => "Format error", - TiffError::UnsupportedError(..) => "Unsupported error", - TiffError::IoError(..) => "IO error", - TiffError::LimitsExceeded => "Decoder limits exceeded", - TiffError::IntSizeError => "Platform or format size limits exceeded", - TiffError::UsageError(..) => "Invalid usage", +quick_error! { + /// The Decoder does not support features required by the image. + /// + /// This only captures known failures for which the standard either does not require support or an + /// implementation has been planned but not yet completed. Some variants may become unused over + /// time and will then get deprecated before being removed. + #[derive(Debug, Clone, PartialEq, Eq, Hash)] + #[non_exhaustive] + pub enum TiffUnsupportedError { + FloatingPointPredictor(color_type: ColorType) { + display("floating point predictor for {color_type:?} is unsupported") } - } - - fn cause(&self) -> Option<&dyn Error> { - match *self { - TiffError::IoError(ref e) => Some(e), - _ => None, + HorizontalPredictor(color_type: ColorType) { + display("horizontal predictor for {color_type:?} is unsupported") + } + InconsistentBitsPerSample(bits_per_sample: Vec) { + display("inconsistent bits per sample: {bits_per_sample:?}") + } + InterpretationWithBits(interpretation: PhotometricInterpretation, bits_per_sample: Vec) { + display("Photometric interpretation {interpretation:?} with bits per sample {bits_per_sample:?} is unsupported") + } + UnknownInterpretation { + display("unknown photometric interpretation") + } + UnknownCompressionMethod { + display("unknown compression method") + } + UnsupportedCompressionMethod(method: CompressionMethod) { + display("compression method {method:?} is unsupported") + } + UnsupportedSampleDepth(depth: u8) { + display("{depth} samples per pixel is unsupported") + } + UnsupportedSampleFormat(sample_format: Vec) { + display("sample format {sample_format:?} is unsupported") + } + UnsupportedColorType(color_type: ColorType) { + display("color type {color_type:?} is unsupported") + } + UnsupportedBitsPerChannel(bits_per_channel: u8) { + display("{bits_per_channel} bits per channel not supported") + } + UnsupportedPlanarConfig(planar: Option) { + display("unsupported planar configuration “{planar:?}”") + } + UnsupportedDataType { + display("unsupported data type.") + } + UnsupportedInterpretation(interpretation: PhotometricInterpretation) { + display("unsupported photometric interpretation \"{interpretation:?}\"") + } + MisalignedTileBoundaries { + display("tile rows are not aligned to byte boundaries") } } } -impl From for TiffError { - fn from(err: io::Error) -> TiffError { - TiffError::IoError(err) +quick_error! { + /// User attempted to use the Decoder in a way that is incompatible with a specific image. + /// + /// For example: attempting to read a tile from a stripped image. + #[derive(Debug)] + #[non_exhaustive] + pub enum UsageError { + InvalidChunkType(expected: ChunkType, actual: ChunkType) { + display("requested operation is only valid for images with chunk encoding of type {expected:?} but got {actual:?}") + } + InvalidChunkIndex(index: u32) { + display("invalid chunk index ({index}) requested") + } + PredictorCompressionMismatch { + display("requested predictor is not compatible with the requested compression") + } + PredictorIncompatible { + display("the requested predictor is not compatible with the image's format") + } + PredictorUnavailable { + display("the requested predictor is not available") + } + InsufficientOutputBufferSize { needed: usize, provided: usize } { + display("the borrowed output buffer is not large enough for the decoded data, needed {needed} but have {provided}") + } } } @@ -304,74 +202,23 @@ } } -impl From for TiffError { - fn from(err: TiffFormatError) -> TiffError { - TiffError::FormatError(err) - } -} - -impl From for TiffError { - fn from(err: TiffUnsupportedError) -> TiffError { - TiffError::UnsupportedError(err) - } -} - -impl From for TiffError { - fn from(err: UsageError) -> TiffError { - TiffError::UsageError(err) - } -} - impl From for TiffError { fn from(_err: std::num::TryFromIntError) -> TiffError { TiffError::IntSizeError } } -impl From for TiffError { - fn from(err: LzwError) -> TiffError { - match err { - LzwError::InvalidCode => TiffError::FormatError(TiffFormatError::Format(String::from( - "LZW compressed data corrupted", - ))), - } - } -} - -#[derive(Debug, Clone)] -pub struct JpegDecoderError { - inner: Arc, -} - -impl JpegDecoderError { - fn new(error: jpeg::Error) -> Self { - Self { - inner: Arc::new(error), - } - } -} - -impl PartialEq for JpegDecoderError { - fn eq(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.inner, &other.inner) - } -} - -impl Display for JpegDecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) - } -} - -impl From for TiffError { - fn from(error: JpegDecoderError) -> Self { - TiffError::FormatError(TiffFormatError::JpegDecoder(error)) +#[cfg(feature = "lzw")] +impl From for TiffError { + fn from(err: weezl::LzwError) -> TiffError { + TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string())) } } -impl From for TiffError { - fn from(error: jpeg::Error) -> Self { - JpegDecoderError::new(error).into() +#[cfg(feature = "jpeg")] +impl From for TiffError { + fn from(err: zune_jpeg::errors::DecodeErrors) -> Self { + TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string())) } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,19 +6,19 @@ //! # Related Links //! * - The TIFF specification -extern crate jpeg; -extern crate weezl; - mod bytecast; pub mod decoder; +mod directory; pub mod encoder; mod error; pub mod tags; +pub use self::directory::Directory; pub use self::error::{TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError}; /// An enumeration over supported color types and their bit depths #[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)] +#[non_exhaustive] pub enum ColorType { /// Pixel is grayscale Gray(u8), @@ -38,6 +38,27 @@ /// Pixel is CMYK CMYK(u8), + /// Pixel is CMYK with an alpha channel + CMYKA(u8), + /// Pixel is YCbCr YCbCr(u8), + + /// Pixel has multiple bands/channels + Multiband { bit_depth: u8, num_samples: u16 }, +} +impl ColorType { + fn bit_depth(&self) -> u8 { + match *self { + ColorType::Gray(b) + | ColorType::RGB(b) + | ColorType::Palette(b) + | ColorType::GrayA(b) + | ColorType::RGBA(b) + | ColorType::CMYK(b) + | ColorType::CMYKA(b) + | ColorType::YCbCr(b) + | ColorType::Multiband { bit_depth: b, .. } => b, + } + } } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/tags.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/tags.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/src/tags.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/src/tags.rs 2006-07-24 01:21:28.000000000 +0000 @@ -2,7 +2,7 @@ { // Permit arbitrary meta items, which include documentation. $( #[$enum_attr:meta] )* - $vis:vis enum $name:ident($ty:tt) $(unknown($unknown_doc:literal))* { + $vis:vis enum $name:ident($ty:tt) $(unknown(#[$unknown_meta:meta] $unknown_doc:ident))* { // Each of the `Name = Val,` permitting documentation. $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* } @@ -13,7 +13,7 @@ pub enum $name { $($(#[$ident_attr])* $tag,)* $( - #[doc = $unknown_doc] + #[$unknown_meta] Unknown($ty), )* } @@ -31,7 +31,7 @@ fn __to_inner_type(&self) -> $ty { match *self { $( $name::$tag => $val, )* - $( $name::Unknown(n) => { $unknown_doc; n }, )* + $( $name::Unknown($unknown_doc) => { $unknown_doc }, )* } } } @@ -39,7 +39,7 @@ tags!($name, $ty, $($unknown_doc)*); }; // For u16 tags, provide direct inherent primitive conversion methods. - ($name:tt, u16, $($unknown_doc:literal)*) => { + ($name:tt, u16, $($unknown_doc:ident)*) => { impl $name { #[inline(always)] pub fn from_u16(val: u16) -> Option { @@ -48,9 +48,8 @@ $( #[inline(always)] - pub fn from_u16_exhaustive(val: u16) -> Self { - $unknown_doc; - Self::__from_inner_type(val).unwrap_or_else(|_| $name::Unknown(val)) + pub fn from_u16_exhaustive($unknown_doc: u16) -> Self { + Self::__from_inner_type($unknown_doc).unwrap_or_else(|_| $name::Unknown($unknown_doc)) } )* @@ -68,7 +67,10 @@ // Note: These tags appear in the order they are mentioned in the TIFF reference tags! { /// TIFF tags -pub enum Tag(u16) unknown("A private or extension tag") { +pub enum Tag(u16) unknown( + /// A private or extension tag + unknown +) { // Baseline tags: Artist = 315, // grayscale images PhotometricInterpretation 1 or 3 @@ -78,7 +80,6 @@ // palette-color images (PhotometricInterpretation 3) ColorMap = 320, // TODO add support Compression = 259, // TODO add support for 2 and 32773 - Copyright = 33_432, DateTime = 306, ExtraSamples = 338, // TODO add support FillOrder = 266, // TODO add support @@ -114,6 +115,7 @@ TileLength = 323, TileOffsets = 324, TileByteCounts = 325, + SubIfd = 330, // Data Sample Format SampleFormat = 339, SMinSampleValue = 340, // TODO add support @@ -124,13 +126,35 @@ ModelPixelScaleTag = 33550, // (SoftDesk) ModelTransformationTag = 34264, // (JPL Carto Group) ModelTiepointTag = 33922, // (Intergraph) + // + // *Do note its typo in the Decimal id* + Copyright = 33_432, + // + ExifDirectory = 0x8769, + // + GpsDirectory = 0x8825, + // + IccProfile = 34675, GeoKeyDirectoryTag = 34735, // (SPOT) GeoDoubleParamsTag = 34736, // (SPOT) GeoAsciiParamsTag = 34737, // (SPOT) + ExifVersion = 0x9000, GdalNodata = 42113, // Contains areas with missing data } } +/// Identifies the offset of an IFD. +/// +/// This is represented as a 64-bit integer but only BigTIFF can utilize the bits. It is encoded +/// as 32-bit unsigned value ([`Type::LONG`]) in regular TIFF files and as 64-bit unsigned value +/// ([`Type::IFD8`]) in BigTIFF files. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +// We could be using `NonZeroU64` here but I find that this complicates semantics. This type +// represents the integer value stored as a value in a tag. The semantics of treating `0` as an end +// marker are imposed by the IFD. (It's unclear if Pointer tags such as Exif would allow `0` but in +// practice it just returns garbage and the validity does not matter greatly to us). +pub struct IfdPointer(pub u64); + tags! { /// The type of an IFD entry (a 2 byte field). pub enum Type(u16) { @@ -172,7 +196,10 @@ tags! { /// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html) /// for reference. -pub enum CompressionMethod(u16) unknown("A custom compression method") { +pub enum CompressionMethod(u16) unknown( + /// A custom compression method + unknown +) { None = 1, Huffman = 2, Fax3 = 3, @@ -184,6 +211,9 @@ Deflate = 8, OldDeflate = 0x80B2, PackBits = 0x8005, + + // Self-assigned by libtiff + ZSTD = 0xC350, } } @@ -209,8 +239,14 @@ tags! { pub enum Predictor(u16) { + /// No changes were made to the data None = 1, + /// The images' rows were processed to contain the difference of each pixel from the previous one. + /// + /// This means that instead of having in order `[r1, g1. b1, r2, g2 ...]` you will find + /// `[r1, g1, b1, r2-r1, g2-g1, b2-b1, r3-r2, g3-g2, ...]` Horizontal = 2, + /// Not currently supported FloatingPoint = 3, } } @@ -225,7 +261,10 @@ } tags! { -pub enum SampleFormat(u16) unknown("An unknown extension sample format") { +pub enum SampleFormat(u16) unknown( + /// An unknown extension sample format + unknown +) { Uint = 1, Int = 2, IEEEFP = 3, diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/COPYRIGHT clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/COPYRIGHT --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/COPYRIGHT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/COPYRIGHT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,4 @@ +subsubifd.tif: + url: https://data.kitware.com/api/v1/file/hashsum/sha512/372ca32735c8a8fdbe2286dabead9e779da63f10ba81eda84625e5273f76d74ca1a47a978f67e9c00c12f7f72009c7b2c07a641e643bb0c463812f4ae7f15d6e/download + credit: https://github.com/DigitalSlideArchive/tifftools/commit/4d00c70dbce828262f86c1431f7c66b1748965ac + license: CC0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_fp16_images.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_fp16_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_fp16_images.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_fp16_images.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,195 @@ +extern crate tiff; + +use tiff::decoder::{Decoder, DecodingResult}; +use tiff::ColorType; + +use std::fs::File; +use std::path::PathBuf; + +const TEST_IMAGE_DIR: &str = "./tests/images/"; + +/// Test a basic all white image +#[test] +fn test_white_ieee_fp16() { + let filenames = ["white-fp16.tiff"]; + + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (256, 256) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Gray(16) + ); + if let DecodingResult::F16(img) = decoder.read_image().unwrap() { + for p in img { + assert!(p == half::f16::from_f32_const(1.0)); + } + } else { + panic!("Wrong data type"); + } + } +} + +/// Test a single black pixel, to make sure scaling is ok +#[test] +fn test_one_black_pixel_ieee_fp16() { + let filenames = ["single-black-fp16.tiff"]; + + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (256, 256) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Gray(16) + ); + if let DecodingResult::F16(img) = decoder.read_image().unwrap() { + for (i, p) in img.iter().enumerate() { + if i == 0 { + assert!(p < &half::f16::from_f32_const(0.001)); + } else { + assert!(p == &half::f16::from_f32_const(1.0)); + } + } + } else { + panic!("Wrong data type"); + } + } +} + +/// Test white with horizontal differencing predictor +#[test] +fn test_pattern_horizontal_differencing_ieee_fp16() { + let filenames = ["white-fp16-pred2.tiff"]; + + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (256, 256) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Gray(16) + ); + if let DecodingResult::F16(img) = decoder.read_image().unwrap() { + // 0, 2, 5, 8, 12, 16, 255 are black + let black = [0, 2, 5, 8, 12, 16, 255]; + for (i, p) in img.iter().enumerate() { + if black.contains(&i) { + assert!(p < &half::f16::from_f32_const(0.001)); + } else { + assert!(p == &half::f16::from_f32_const(1.0)); + } + } + } else { + panic!("Wrong data type"); + } + } +} + +/// Test white with floating point predictor +#[test] +fn test_pattern_predictor_ieee_fp16() { + let filenames = ["white-fp16-pred3.tiff"]; + + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (256, 256) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Gray(16) + ); + if let DecodingResult::F16(img) = decoder.read_image().unwrap() { + // 0, 2, 5, 8, 12, 16, 255 are black + let black = [0, 2, 5, 8, 12, 16, 255]; + for (i, p) in img.iter().enumerate() { + if black.contains(&i) { + assert!(p < &half::f16::from_f32_const(0.001)); + } else { + assert!(p == &half::f16::from_f32_const(1.0)); + } + } + } else { + panic!("Wrong data type"); + } + } +} + +/// Test several random images +/// we'rell compare against a pnm file, that scales from 0 (for 0.0) to 65767 (for 1.0) +#[test] +fn test_predictor_ieee_fp16() { + // first parse pnm, skip the first 4 \n + let pnm_path = PathBuf::from(TEST_IMAGE_DIR).join("random-fp16.pgm"); + let pnm_bytes = std::fs::read(pnm_path).expect("Failed to read expected PNM file"); + + // PGM looks like this: + // --- + // P5 + // #Created with GIMP + // 16 16 + // 65535 + // ... + // --- + // get index of 4th \n + let byte_start = pnm_bytes + .iter() + .enumerate() + .filter(|(_, &v)| v == b'\n') + .map(|(i, _)| i) + .nth(3) + .expect("Must be 4 \\n's"); + + let pnm_values: Vec = pnm_bytes[(byte_start + 1)..] + .chunks(2) + .map(|slice| { + let bts = [slice[0], slice[1]]; + (u16::from_be_bytes(bts) as f32) / (u16::MAX as f32) + }) + .collect(); + assert!(pnm_values.len() == 256); + + let filenames = [ + "random-fp16-pred2.tiff", + "random-fp16-pred3.tiff", + "random-fp16.tiff", + ]; + + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (16, 16) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Gray(16) + ); + if let DecodingResult::F16(img) = decoder.read_image().unwrap() { + for (exp, found) in std::iter::zip(pnm_values.iter(), img.iter()) { + assert!((exp - found.to_f32()).abs() < 0.0001); + } + } else { + panic!("Wrong data type"); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_geotiff_images.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_geotiff_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_geotiff_images.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_geotiff_images.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +extern crate tiff; + +use tiff::decoder::{Decoder, DecodingResult}; +use tiff::tags::Tag; +use tiff::ColorType; + +use std::fs::File; +use std::path::PathBuf; + +const TEST_IMAGE_DIR: &str = "./tests/images"; + +#[test] +fn test_geo_tiff() { + let filenames = ["geo-5b.tif"]; + for filename in filenames.iter() { + let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + decoder = decoder.with_limits(tiff::decoder::Limits::unlimited()); + + assert_eq!( + decoder.dimensions().expect("Cannot get dimensions"), + (10, 10) + ); + assert_eq!( + decoder.colortype().expect("Cannot get colortype"), + ColorType::Multiband { + bit_depth: 16, + num_samples: 5 + } + ); + assert_eq!( + decoder + .get_tag_u64(Tag::StripOffsets) + .expect("Cannot get StripOffsets"), + 418 + ); + assert_eq!( + decoder + .get_tag_u64(Tag::RowsPerStrip) + .expect("Cannot get RowsPerStrip"), + 10 + ); + assert_eq!( + decoder + .get_tag_u64(Tag::StripByteCounts) + .expect("Cannot get StripByteCounts"), + 1000 + ); + assert_eq!( + decoder + .get_tag(Tag::ModelPixelScaleTag) + .expect("Cannot get pixel scale") + .into_f64_vec() + .expect("Cannot get pixel scale"), + vec![60.0, 60.0, 0.0] + ); + let DecodingResult::I16(data) = decoder.read_image().unwrap() else { + panic!("Cannot read band data") + }; + assert_eq!(data.len(), 500); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_images.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/decode_images.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/decode_images.rs 2006-07-24 01:21:28.000000000 +0000 @@ -4,6 +4,7 @@ use tiff::ColorType; use std::fs::File; +use std::io::{Read, Seek}; use std::path::PathBuf; const TEST_IMAGE_DIR: &str = "./tests/images/"; @@ -45,12 +46,12 @@ let img_file = File::open(path).expect("Cannot find test image!"); let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); assert_eq!(decoder.colortype().unwrap(), expected_type); - assert!(match decoder.read_image() { + assert!(matches!( + decoder.read_image(), Err(tiff::TiffError::UnsupportedError( tiff::TiffUnsupportedError::UnsupportedColorType(_), - )) => true, - _ => false, - }); + )) + )); } #[test] @@ -172,7 +173,7 @@ &s, "GraphicsMagick 1.2 unreleased Q16 http://www.GraphicsMagick.org/" ), - _ => assert!(false), + other => unreachable!("Expected Ascii tag from file, got {other:?}"), }; } } @@ -217,6 +218,11 @@ //} #[test] +fn test_tiled_gray_i1() { + test_image_sum_u8("tiled-gray-i1.tif", ColorType::Gray(1), 30531); +} + +#[test] fn test_tiled_rgb_u8() { test_image_sum_u8("tiled-rgb-u8.tif", ColorType::RGB(8), 39528948); } @@ -226,6 +232,54 @@ test_image_sum_u8("tiled-rect-rgb-u8.tif", ColorType::RGB(8), 62081032); } +#[test] +fn test_inner_access() { + let path = PathBuf::from(TEST_IMAGE_DIR).join("tiled-rect-rgb-u8.tif"); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); + + let c = decoder + .get_tag(tiff::tags::Tag::Compression) + .unwrap() + .into_u16() + .unwrap(); + assert_eq!(c, tiff::tags::CompressionMethod::None.to_u16()); + + // Because the image is uncompressed, reading the first tile directly with the inner reader + // should yield the same result as reading it with the decoder's read_chunk method. + let first_offset = decoder + .get_tag_u32_vec(tiff::tags::Tag::TileOffsets) + .unwrap() + .into_iter() + .next() + .unwrap(); + let first_byte_count = decoder + .get_tag_u32_vec(tiff::tags::Tag::TileByteCounts) + .unwrap() + .into_iter() + .next() + .unwrap(); + decoder + .inner() + .seek(std::io::SeekFrom::Start(first_offset as u64)) + .expect("Cannot seek to tile offset"); + let mut buf = vec![0; first_byte_count as usize]; + decoder + .inner() + .read_exact(&mut buf) + .expect("Cannot read tile data"); + let raw_sum: u64 = buf.into_iter().map(::from).sum(); + + match decoder.read_chunk(0).unwrap() { + DecodingResult::U8(chunk) => { + let sum: u64 = chunk.into_iter().map(::from).sum(); + assert_eq!(sum, raw_sum); + } + _ => panic!("Wrong bit depth"), + } +} + /* #[test] fn test_tiled_jpeg_rgb_u8() { test_image_sum_u8("tiled-jpeg-rgb-u8.tif", ColorType::RGB(8), 93031606); @@ -287,6 +341,11 @@ #[test] fn test_planar_rgb_u8() { + test_image_sum_u8("planar-rgb-u8.tif", ColorType::RGB(8), 15417630); +} + +#[test] +fn test_read_planar_bands() { // gdal_translate tiled-rgb-u8.tif planar-rgb-u8.tif -co INTERLEAVE=BAND -co COMPRESS=LZW -co PROFILE=BASELINE let file = "planar-rgb-u8.tif"; let expected_type = ColorType::RGB(8); @@ -323,8 +382,6 @@ } _ => panic!("Wrong bit depth"), } - - test_image_sum_u8(file, ColorType::RGB(8), 15417630); } #[test] @@ -343,7 +400,7 @@ match err { TiffError::FormatError(TiffFormatError::StripTileTagConflict) => {} - unexpected => panic!("Unexpected error {}", unexpected), + unexpected => panic!("Unexpected error {unexpected}"), } } @@ -361,7 +418,7 @@ match error { tiff::TiffError::LimitsExceeded => {} - unexpected => panic!("Unexpected error {}", unexpected), + unexpected => panic!("Unexpected error {unexpected}"), } } @@ -492,7 +549,7 @@ match error { TiffError::FormatError(TiffFormatError::CycleInOffsets) => {} - e => panic!("Unexpected error {:?}", e), + e => panic!("Unexpected error {e:?}"), } } @@ -510,3 +567,120 @@ fn test_predictor_3_gray_f32() { test_image_sum_f32("predictor-3-gray-f32.tif", ColorType::Gray(32), 20008.275); } + +#[test] +#[cfg(feature = "zstd")] +fn test_zstd_compression() { + // gdal_translate -co COMPRESS=ZSTD -co ZSTD_LEVEL=20 int16.tif int16_zstd.tif + test_image_sum_i16("int16_zstd.tif", ColorType::Gray(16), 354396); +} + +fn test_image_bytes( + file: &str, + expected: &[(ColorType, u32)], + // Represent all samples as little endian, ensuring check sums on all platforms. + normalize_byte_order: fn(&mut [u8]), +) { + let path = PathBuf::from(TEST_IMAGE_DIR).join(file); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + + let mut buffer = vec![0u8; 0]; + for (idx, &(expected_type, expected_crc)) in expected.iter().enumerate() { + if idx > 0 { + decoder + .next_image() + .expect("mismatched number of directories"); + } + + assert_eq!(decoder.colortype().unwrap(), expected_type); + let layout = decoder + .image_buffer_layout() + .expect("Cannot describe buffer layout"); + + buffer.resize(layout.len, 0u8); + decoder.read_image_bytes(&mut buffer).unwrap(); + normalize_byte_order(&mut buffer); + + // Well almost a crc.. + assert_eq!(crc32fast::hash(&buffer), expected_crc); + } +} + +fn byte_order_u16(bytes: &mut [u8]) { + for chunk in bytes.chunks_exact_mut(2) { + let n = u16::from_ne_bytes(chunk.try_into().unwrap()); + chunk.copy_from_slice(&n.to_le_bytes()); + } +} + +fn byte_order_u32(bytes: &mut [u8]) { + for chunk in bytes.chunks_exact_mut(4) { + let n = u32::from_ne_bytes(chunk.try_into().unwrap()); + chunk.copy_from_slice(&n.to_le_bytes()); + } +} + +fn byte_order_u64(bytes: &mut [u8]) { + for chunk in bytes.chunks_exact_mut(8) { + let n = u64::from_ne_bytes(chunk.try_into().unwrap()); + chunk.copy_from_slice(&n.to_le_bytes()); + } +} + +#[test] +fn bytes_cmyk_3c_8b() { + test_image_bytes( + "cmyk-3c-8b.tiff", + &[(ColorType::CMYK(8), 2935032230)], + |_| (), + ); +} + +#[test] +fn bytes_gray_16b() { + test_image_bytes( + "minisblack-1c-16b.tiff", + &[(ColorType::Gray(16), 3524597615)], + byte_order_u16, + ); +} + +#[test] +fn bytes_gray_32b() { + test_image_bytes( + "gradient-1c-32b.tiff", + &[(ColorType::Gray(32), 2257036530)], + byte_order_u32, + ); +} + +#[test] +fn bytes_gray_u64() { + test_image_bytes( + "gradient-1c-64b.tiff", + &[(ColorType::Gray(64), 2156547113)], + byte_order_u64, + ); +} + +#[test] +fn bytes_gray_f32() { + test_image_bytes( + "gradient-1c-32b-float.tiff", + &[(ColorType::Gray(32), 3232356730)], + byte_order_u32, + ); +} + +#[test] +#[cfg(feature = "fax")] +fn test_fax4() { + test_image_sum_u8("fax4.tiff", ColorType::Gray(1), 7802706); +} + +#[test] +#[cfg(feature = "fax")] +fn test_fax4_white_is_min() { + test_image_sum_u8("imagemagick_group4.tiff", ColorType::Gray(1), 3742820); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/encode_images.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/encode_images.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images.rs 2006-07-24 01:21:28.000000000 +0000 @@ -36,6 +36,47 @@ let mut decoder = Decoder::new(&mut file).unwrap(); assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); assert_eq!(decoder.dimensions().unwrap(), (100, 100)); + + let mut all_tags = decoder + .tag_iter() + .filter_map(Result::ok) + .collect::>(); + all_tags.sort_by_key(|(t, _)| t.to_u16()); + assert_eq!( + all_tags, + vec![ + (Tag::ImageWidth, ifd::Value::Unsigned(100)), + (Tag::ImageLength, ifd::Value::Unsigned(100)), + ( + Tag::BitsPerSample, + ifd::Value::List(vec![ + ifd::Value::Short(8), + ifd::Value::Short(8), + ifd::Value::Short(8) + ]) + ), + (Tag::Compression, ifd::Value::Short(1)), + (Tag::PhotometricInterpretation, ifd::Value::Short(2)), + (Tag::StripOffsets, ifd::Value::Unsigned(47)), + (Tag::SamplesPerPixel, ifd::Value::Short(3)), + (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)), + (Tag::StripByteCounts, ifd::Value::Unsigned(30000)), + (Tag::XResolution, ifd::Value::Rational(1, 1)), + (Tag::YResolution, ifd::Value::Rational(1, 1)), + (Tag::ResolutionUnit, ifd::Value::Short(1)), + (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())), + (Tag::Predictor, ifd::Value::Short(1)), + ( + Tag::SampleFormat, + ifd::Value::List(vec![ + ifd::Value::Short(1), + ifd::Value::Short(1), + ifd::Value::Short(1) + ]) + ), + ] + ); + assert_eq!( decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into()) @@ -75,6 +116,47 @@ let mut decoder = Decoder::new(&mut file).unwrap(); assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); assert_eq!(decoder.dimensions().unwrap(), (100, 100)); + + let mut all_tags = decoder + .tag_iter() + .filter_map(Result::ok) + .collect::>(); + all_tags.sort_by_key(|(t, _)| t.to_u16()); + assert_eq!( + all_tags, + vec![ + (Tag::ImageWidth, ifd::Value::Unsigned(100)), + (Tag::ImageLength, ifd::Value::Unsigned(100)), + ( + Tag::BitsPerSample, + ifd::Value::List(vec![ + ifd::Value::Short(8), + ifd::Value::Short(8), + ifd::Value::Short(8) + ]) + ), + (Tag::Compression, ifd::Value::Short(1)), + (Tag::PhotometricInterpretation, ifd::Value::Short(2)), + (Tag::StripOffsets, ifd::Value::UnsignedBig(27)), + (Tag::SamplesPerPixel, ifd::Value::Short(3)), + (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)), + (Tag::StripByteCounts, ifd::Value::UnsignedBig(30000)), + (Tag::XResolution, ifd::Value::Rational(1, 1)), + (Tag::YResolution, ifd::Value::Rational(1, 1)), + (Tag::ResolutionUnit, ifd::Value::Short(1)), + (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())), + (Tag::Predictor, ifd::Value::Short(1)), + ( + Tag::SampleFormat, + ifd::Value::List(vec![ + ifd::Value::Short(1), + ifd::Value::Short(1), + ifd::Value::Short(1) + ]) + ), + ] + ); + assert_eq!( decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into()) @@ -188,7 +270,9 @@ } test_roundtrip!(test_u8_roundtrip, U8, u8); +test_roundtrip!(test_i8_roundtrip, I8, i8); test_roundtrip!(test_u16_roundtrip, U16, u16); +test_roundtrip!(test_i16_roundtrip, I16, i16); test_roundtrip!(test_u32_roundtrip, U32, u32); test_roundtrip!(test_u64_roundtrip, U64, u64); test_roundtrip!(test_f32_roundtrip, F32, f32); @@ -200,6 +284,11 @@ } #[test] +fn test_gray_i8_roundtrip() { + test_i8_roundtrip::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); +} + +#[test] fn test_rgb_u8_roundtrip() { test_u8_roundtrip::("rgb-3c-8b.tiff", ColorType::RGB(8)); } @@ -210,11 +299,21 @@ } #[test] +fn test_cmyka_u8_roundtrip() { + test_u8_roundtrip::("cmyk-4c-8b.tiff", ColorType::CMYKA(8)); +} + +#[test] fn test_gray_u16_roundtrip() { test_u16_roundtrip::("minisblack-1c-16b.tiff", ColorType::Gray(16)); } #[test] +fn test_gray_i16_roundtrip() { + test_i16_roundtrip::("minisblack-1c-i16b.tiff", ColorType::Gray(16)); +} + +#[test] fn test_rgb_u16_roundtrip() { test_u16_roundtrip::("rgb-3c-16b.tiff", ColorType::RGB(16)); } @@ -522,8 +621,62 @@ let img2 = [i; 2 * 100]; match decoder.read_chunk(i as u32).unwrap() { DecodingResult::U8(data) => assert_eq!(&img2[..], &data[..]), - other => panic!("Incorrect strip type {:?}", other), + other => panic!("Incorrect strip type {other:?}"), } } } } + +#[test] +fn test_auxiliary_directory() { + const ARTIST: &str = "Auxiliary-tiff"; + + let mut data = Cursor::new(Vec::new()); + let mut tiff = TiffEncoder::new(&mut data).unwrap(); + + { + let mut image_encoder = tiff.new_image::(1, 1).unwrap(); + image_encoder.write_strip(&[1]).unwrap(); + } + + let exif = { + let mut extra = tiff.extra_directory().unwrap(); + extra.write_tag(Tag::Artist, ARTIST).unwrap(); + extra.finish_with_offsets().unwrap() + }; + + { + let mut image_encoder = tiff.new_image::(2, 1).unwrap(); + image_encoder.write_strip(&[1, 2]).unwrap(); + let encoder = image_encoder.encoder(); + encoder.write_tag(Tag::ExifDirectory, exif.offset).unwrap(); + } + + data.set_position(0); + let mut decoder = Decoder::new(&mut data).unwrap(); + + { + assert_eq!(decoder.dimensions().unwrap(), (1, 1)); + let _ = decoder.read_image().unwrap(); + } + + { + decoder.next_image().unwrap(); + assert_eq!(decoder.dimensions().unwrap(), (2, 1)); + let _ = decoder.read_image().unwrap(); + + let exif_location = decoder + .get_tag(Tag::ExifDirectory) + .expect("second directory missing Exif") + .into_ifd_pointer() + .expect("exif directory is not an IFD pointer"); + + let exif = decoder.read_directory(exif_location).unwrap(); + + let artist = decoder + .read_directory_tags(&exif) + .get_tag_ascii_string(Tag::Artist) + .expect("EXIF directory missing artist tag"); + assert_eq!(artist, ARTIST); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/encode_images_with_compression.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images_with_compression.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/encode_images_with_compression.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/encode_images_with_compression.rs 2006-07-24 01:21:28.000000000 +0000 @@ -6,7 +6,7 @@ encoder::{ colortype::{self, ColorType}, compression::*, - TiffEncoder, TiffValue, + Compression, TiffEncoder, TiffValue, }, }; @@ -18,15 +18,12 @@ fn reference_data(&self) -> &[::Inner]; fn generate_pixel(x: u32, y: u32) -> [::Inner; NUM_CHANNELS]; - fn compress( - &self, - encoder: &mut TiffEncoder, - compression: C, - ) where + fn compress(&self, encoder: &mut TiffEncoder) + where [::Inner]: TiffValue, { let image = encoder - .new_image_with_compression::(Self::WIDTH, Self::HEIGHT, compression) + .new_image::(Self::WIDTH, Self::HEIGHT) .unwrap(); image.write_data(self.reference_data()).unwrap(); } @@ -94,7 +91,7 @@ } } -fn encode_decode_with_compression(compression: C) { +fn encode_decode_with_compression(compression: Compression) { let mut data = Cursor::new(Vec::new()); let image_rgb = TestImageColor::generate(); @@ -103,9 +100,11 @@ // Encode tiff with compression { // Create a multipage image with 2 images - let mut encoder = TiffEncoder::new(&mut data).unwrap(); - image_rgb.compress(&mut encoder, compression.clone()); - image_grayscale.compress(&mut encoder, compression); + let mut encoder = TiffEncoder::new(&mut data) + .unwrap() + .with_compression(compression); + image_rgb.compress(&mut encoder); + image_grayscale.compress(&mut encoder); } // Decode tiff @@ -117,7 +116,7 @@ assert_eq!( match decoder.read_image() { Ok(DecodingResult::U16(image_data)) => image_data, - unexpected => panic!("Descoding RGB failed: {:?}", unexpected), + unexpected => panic!("Descoding RGB failed: {unexpected:?}"), }, image_rgb.reference_data() ); @@ -127,7 +126,7 @@ assert_eq!( match decoder.read_image() { Ok(DecodingResult::U8(image_data)) => image_data, - unexpected => panic!("Decoding grayscale failed: {:?}", unexpected), + unexpected => panic!("Decoding grayscale failed: {unexpected:?}"), }, image_grayscale.reference_data() ); @@ -136,22 +135,24 @@ #[test] fn encode_decode_without_compression() { - encode_decode_with_compression(Uncompressed::default()); + encode_decode_with_compression(Compression::Uncompressed); } #[test] +#[cfg(feature = "lzw")] fn encode_decode_with_lzw() { - encode_decode_with_compression(Lzw::default()); + encode_decode_with_compression(Compression::Lzw); } #[test] +#[cfg(feature = "deflate")] fn encode_decode_with_deflate() { - encode_decode_with_compression(Deflate::with_level(DeflateLevel::Fast)); - encode_decode_with_compression(Deflate::with_level(DeflateLevel::Balanced)); - encode_decode_with_compression(Deflate::with_level(DeflateLevel::Best)); + encode_decode_with_compression(Compression::Deflate(DeflateLevel::Fast)); + encode_decode_with_compression(Compression::Deflate(DeflateLevel::Balanced)); + encode_decode_with_compression(Compression::Deflate(DeflateLevel::Best)); } #[test] fn encode_decode_with_packbits() { - encode_decode_with_compression(Packbits::default()); + encode_decode_with_compression(Compression::Packbits); } diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/predict.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/predict.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/predict.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/predict.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,231 @@ +extern crate tiff; + +use tiff::decoder::{Decoder, DecodingResult}; +use tiff::encoder::{colortype, Predictor, TiffEncoder}; +use tiff::ColorType; + +use std::fs::File; +use std::io::{Cursor, Seek, SeekFrom}; +use std::path::PathBuf; + +const TEST_IMAGE_DIR: &str = "./tests/images/"; + +macro_rules! test_predict { + ($name:ident, $buffer:ident, $buffer_ty:ty) => { + fn $name>( + file: &str, + expected_type: ColorType, + ) { + let path = PathBuf::from(TEST_IMAGE_DIR).join(file); + let file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(file).expect("Cannot create decoder!"); + + assert_eq!(decoder.colortype().unwrap(), expected_type); + let image_data = match decoder.read_image().unwrap() { + DecodingResult::$buffer(res) => res, + _ => panic!("Wrong data type"), + }; + + let mut predicted = Vec::with_capacity(image_data.len()); + C::horizontal_predict(&image_data, &mut predicted); + + let sample_size = C::SAMPLE_FORMAT.len(); + + (0..sample_size).for_each(|i| { + assert_eq!(predicted[i], image_data[i]); + }); + + (sample_size..image_data.len()).for_each(|i| { + predicted[i] = predicted[i].wrapping_add(predicted[i - sample_size]); + assert_eq!(predicted[i], image_data[i]); + }); + } + }; +} + +test_predict!(test_u8_predict, U8, u8); +test_predict!(test_i8_predict, I8, i8); +test_predict!(test_u16_predict, U16, u16); +test_predict!(test_i16_predict, I16, i16); +test_predict!(test_u32_predict, U32, u32); +test_predict!(test_u64_predict, U64, u64); + +#[test] +fn test_gray_u8_predict() { + test_u8_predict::("minisblack-1c-8b.tiff", ColorType::Gray(8)); +} + +#[test] +fn test_gray_i8_predict() { + test_i8_predict::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); +} + +#[test] +fn test_rgb_u8_predict() { + test_u8_predict::("rgb-3c-8b.tiff", ColorType::RGB(8)); +} + +#[test] +fn test_cmyk_u8_predict() { + test_u8_predict::("cmyk-3c-8b.tiff", ColorType::CMYK(8)); +} + +#[test] +fn test_gray_u16_predict() { + test_u16_predict::("minisblack-1c-16b.tiff", ColorType::Gray(16)); +} + +#[test] +fn test_gray_i16_predict() { + test_i16_predict::("minisblack-1c-i16b.tiff", ColorType::Gray(16)); +} + +#[test] +fn test_rgb_u16_predict() { + test_u16_predict::("rgb-3c-16b.tiff", ColorType::RGB(16)); +} + +#[test] +fn test_cmyk_u16_predict() { + test_u16_predict::("cmyk-3c-16b.tiff", ColorType::CMYK(16)); +} + +#[test] +fn test_gray_u32_predict() { + test_u32_predict::("gradient-1c-32b.tiff", ColorType::Gray(32)); +} + +#[test] +fn test_rgb_u32_predict() { + test_u32_predict::("gradient-3c-32b.tiff", ColorType::RGB(32)); +} + +#[test] +fn test_gray_u64_predict() { + test_u64_predict::("gradient-1c-64b.tiff", ColorType::Gray(64)); +} + +#[test] +fn test_rgb_u64_predict() { + test_u64_predict::("gradient-3c-64b.tiff", ColorType::RGB(64)); +} + +#[test] +fn test_ycbcr_u8_predict() { + test_u8_predict::("tiled-jpeg-ycbcr.tif", ColorType::YCbCr(8)); +} + +macro_rules! test_predict_roundtrip { + ($name:ident, $buffer:ident, $buffer_ty:ty) => { + fn $name>( + file: &str, + expected_type: ColorType, + ) { + let path = PathBuf::from(TEST_IMAGE_DIR).join(file); + let img_file = File::open(path).expect("Cannot find test image!"); + let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); + assert_eq!(decoder.colortype().unwrap(), expected_type); + + let image_data = match decoder.read_image().unwrap() { + DecodingResult::$buffer(res) => res, + _ => panic!("Wrong data type"), + }; + + let mut file = Cursor::new(Vec::new()); + { + let mut tiff = TiffEncoder::new(&mut file) + .unwrap() + .with_predictor(Predictor::Horizontal); + + let (width, height) = decoder.dimensions().unwrap(); + tiff.write_image::(width, height, &image_data).unwrap(); + } + file.seek(SeekFrom::Start(0)).unwrap(); + { + let mut decoder = Decoder::new(&mut file).unwrap(); + if let DecodingResult::$buffer(img_res) = + decoder.read_image().expect("Decoding image failed") + { + assert_eq!(image_data, img_res); + } else { + panic!("Wrong data type"); + } + } + } + }; +} + +test_predict_roundtrip!(test_u8_predict_roundtrip, U8, u8); +test_predict_roundtrip!(test_i8_predict_roundtrip, I8, i8); +test_predict_roundtrip!(test_u16_predict_roundtrip, U16, u16); +test_predict_roundtrip!(test_i16_predict_roundtrip, I16, i16); +test_predict_roundtrip!(test_u32_predict_roundtrip, U32, u32); +test_predict_roundtrip!(test_u64_predict_roundtrip, U64, u64); + +#[test] +fn test_gray_u8_predict_roundtrip() { + test_u8_predict_roundtrip::("minisblack-1c-8b.tiff", ColorType::Gray(8)); +} + +#[test] +fn test_gray_i8_predict_roundtrip() { + test_i8_predict_roundtrip::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); +} + +#[test] +fn test_rgb_u8_predict_roundtrip() { + test_u8_predict_roundtrip::("rgb-3c-8b.tiff", ColorType::RGB(8)); +} + +#[test] +fn test_cmyk_u8_predict_roundtrip() { + test_u8_predict_roundtrip::("cmyk-3c-8b.tiff", ColorType::CMYK(8)); +} + +#[test] +fn test_gray_u16_predict_roundtrip() { + test_u16_predict_roundtrip::("minisblack-1c-16b.tiff", ColorType::Gray(16)); +} + +#[test] +fn test_gray_i16_predict_roundtrip() { + test_i16_predict_roundtrip::( + "minisblack-1c-i16b.tiff", + ColorType::Gray(16), + ); +} + +#[test] +fn test_rgb_u16_predict_roundtrip() { + test_u16_predict_roundtrip::("rgb-3c-16b.tiff", ColorType::RGB(16)); +} + +#[test] +fn test_cmyk_u16_predict_roundtrip() { + test_u16_predict_roundtrip::("cmyk-3c-16b.tiff", ColorType::CMYK(16)); +} + +#[test] +fn test_gray_u32_predict_roundtrip() { + test_u32_predict_roundtrip::("gradient-1c-32b.tiff", ColorType::Gray(32)); +} + +#[test] +fn test_rgb_u32_predict_roundtrip() { + test_u32_predict_roundtrip::("gradient-3c-32b.tiff", ColorType::RGB(32)); +} + +#[test] +fn test_gray_u64_predict_roundtrip() { + test_u64_predict_roundtrip::("gradient-1c-64b.tiff", ColorType::Gray(64)); +} + +#[test] +fn test_rgb_u64_predict_roundtrip() { + test_u64_predict_roundtrip::("gradient-3c-64b.tiff", ColorType::RGB(64)); +} + +#[test] +fn test_ycbcr_u8_predict_roundtrip() { + test_u8_predict_roundtrip::("tiled-jpeg-ycbcr.tif", ColorType::YCbCr(8)); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/subsubifds.rs clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/subsubifds.rs --- clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/subsubifds.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/subsubifds.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +use tiff::decoder::Decoder; + +// This file has the following IFD structure: +// +// ``` +// IFD -> IFD -> IFD +// |-> IFD +// |-> IFD -> IFD +// | \-> IFD -> IFD +// \-> IFD +// ``` +// +// where the main chain of IFD has 3 images, the second of which has several sub-IFDs and some have +// more nested IFDs. +const TEST_IMAGE_SUBIFD: &str = "./tests/subsubifds.tif"; +use std::fs::File; + +#[test] +fn decode_seek_chain() { + let file = File::open(TEST_IMAGE_SUBIFD).expect("Cannot open test image"); + let mut decoder = Decoder::new(file).expect("Invalid format to create decoder"); + + // Remember the offsets in the first iteration. + let offset0 = decoder.ifd_pointer().expect("First IFD pointer not found"); + decoder.next_image().unwrap(); + let offset1 = decoder.ifd_pointer().expect("Second IFD pointer not found"); + decoder.next_image().unwrap(); + let offset2 = decoder.ifd_pointer().expect("Third IFD pointer not found"); + assert!(!decoder.more_images()); + + // Ensure we can seek, to do this again. + decoder + .seek_to_image(0) + .expect("Failed to seek to first image"); + assert_eq!(Some(offset0), decoder.ifd_pointer()); + decoder.next_image().unwrap(); + assert_eq!(Some(offset1), decoder.ifd_pointer()); + decoder.next_image().unwrap(); + assert_eq!(Some(offset2), decoder.ifd_pointer()); + assert!(!decoder.more_images()); +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/tiff/tests/subsubifds.tif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/tiff/tests/subsubifds.tif differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"ba1670e87d405d529ed865529527f8ed4745dc9e546b2261a977f39f5e22fc0a","Cargo.toml":"1d9f89358780ead10a883bea408af7271561f074bedb8e5755c3136182c170f4","LICENSE-APACHE.md":"3ddf9be5c28fe27dad143a5dc76eea25222ad1dd68934a047064e56ed2fa40c5","LICENSE-MIT.md":"4736b5d379253afa45744afc79ddb475912b213e939bdf7cb97d9a8b6f700e5f","LICENSE-ZLIB.md":"682b4c81b85e83ce6cc6e1ace38fdd97aeb4de0e972bd2b44aa0916c54af8c96","README.md":"f2a59c75ef204e21173b2be150d183a946d0f10ad3a42d3e677d6f5507589aa4","benches/macros.rs":"b92679a63e1d39fd949c061fa97dfba933f3e1a6e6722e710cfe4fbfd6315ba9","benches/smallvec.rs":"977761721e1b419966441a767f9eed23b82e6f805e0d496b9905d225600fc050","compare_benchmarks.py":"899f3d88c95f0f02563f869fd683a9c95afb1a8c773edf2d0a8d3355f1ceb07c","gen-array-impls.sh":"6bb75d48b820112b7d0a67e09fb3c2386b2961de42f482635007435956f74b12","rustfmt.toml":"ebb19c2c422dcc6c0fe960e5a869b5a562739e40f248e28c43d48d9a63cebe7b","src-backup/arrayset.rs":"d7d524c9c0a20443f6f028ff0e37d246cd445a0660df496625d647ea302a5094","src/array.rs":"ae2bc64b339ff3e8a17684b25a180fbf04184cae26baf05fb8ed542005f6d9f5","src/array/const_generic_impl.rs":"d0f8ae529b5c9f92da0aa67d5ae24a6e7fc3287ce6d3e576794455de44502a4c","src/array/generated_impl.rs":"8c94c274aae0909b7de75beff4215af8dfc8635cce0c09d75eb57e577c3cca68","src/arrayvec.rs":"349395049164b38f6d8ad9fda8ed925855955cf348b087c796fb9113c1d25687","src/arrayvec_drain.rs":"d2df895c7438bbf3bcf2f68ab5e76ca2209f399ef8dde5d62532c9e176c620b5","src/lib.rs":"867817c74c52316ffdea3a7a7cdf8285cadebe63cf63fb966aafd8130f796db4","src/slicevec.rs":"e43991aff8197095fda62a1e6d3657fcb08e27e386e67f0496ac8228a56bd271","src/tinyvec.rs":"a58c5b8e52619476da195c060a867d99ee0881bdd9e8eeabad947ee949b858af","tests/arrayvec.rs":"e7c22cbcf8df2c0a5ae20a35c1a1327e86230db0ee6fbc25d3ff5000b0044ccc","tests/tinyvec.rs":"8f61a29426ac573999e6328a1bd74d7bc19884b3e38dcfda0a254dc91c1d2310"},"package":"87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"01f5abea7f9d3970ecbfd1c4838432e38bec4b39475404261282f5122a2bc6e3",".github/workflows/rust.yml":"9a5994262d1bf4271bff8825b296cef7755d4e6ca2b1fce524d9d5f264d98b9f","CHANGELOG.md":"ba1670e87d405d529ed865529527f8ed4745dc9e546b2261a977f39f5e22fc0a","Cargo.toml":"1d9f89358780ead10a883bea408af7271561f074bedb8e5755c3136182c170f4","Cargo.toml.orig":"4b4aae9d28f5332262faa75fac08e73013f2a64aa7a4e1151e8c0aa2ccc475bc","LICENSE-APACHE.md":"3ddf9be5c28fe27dad143a5dc76eea25222ad1dd68934a047064e56ed2fa40c5","LICENSE-MIT.md":"4736b5d379253afa45744afc79ddb475912b213e939bdf7cb97d9a8b6f700e5f","LICENSE-ZLIB.md":"682b4c81b85e83ce6cc6e1ace38fdd97aeb4de0e972bd2b44aa0916c54af8c96","README.md":"f2a59c75ef204e21173b2be150d183a946d0f10ad3a42d3e677d6f5507589aa4","benches/macros.rs":"b92679a63e1d39fd949c061fa97dfba933f3e1a6e6722e710cfe4fbfd6315ba9","benches/smallvec.rs":"977761721e1b419966441a767f9eed23b82e6f805e0d496b9905d225600fc050","compare_benchmarks.py":"899f3d88c95f0f02563f869fd683a9c95afb1a8c773edf2d0a8d3355f1ceb07c","gen-array-impls.sh":"6bb75d48b820112b7d0a67e09fb3c2386b2961de42f482635007435956f74b12","rustfmt.toml":"ebb19c2c422dcc6c0fe960e5a869b5a562739e40f248e28c43d48d9a63cebe7b","src-backup/arrayset.rs":"d7d524c9c0a20443f6f028ff0e37d246cd445a0660df496625d647ea302a5094","src/array.rs":"ae2bc64b339ff3e8a17684b25a180fbf04184cae26baf05fb8ed542005f6d9f5","src/array/const_generic_impl.rs":"d0f8ae529b5c9f92da0aa67d5ae24a6e7fc3287ce6d3e576794455de44502a4c","src/array/generated_impl.rs":"8c94c274aae0909b7de75beff4215af8dfc8635cce0c09d75eb57e577c3cca68","src/arrayvec.rs":"349395049164b38f6d8ad9fda8ed925855955cf348b087c796fb9113c1d25687","src/arrayvec_drain.rs":"d2df895c7438bbf3bcf2f68ab5e76ca2209f399ef8dde5d62532c9e176c620b5","src/lib.rs":"867817c74c52316ffdea3a7a7cdf8285cadebe63cf63fb966aafd8130f796db4","src/slicevec.rs":"e43991aff8197095fda62a1e6d3657fcb08e27e386e67f0496ac8228a56bd271","src/tinyvec.rs":"a58c5b8e52619476da195c060a867d99ee0881bdd9e8eeabad947ee949b858af","tests/arrayvec.rs":"e7c22cbcf8df2c0a5ae20a35c1a1327e86230db0ee6fbc25d3ff5000b0044ccc","tests/tinyvec.rs":"8f61a29426ac573999e6328a1bd74d7bc19884b3e38dcfda0a254dc91c1d2310"},"package":"87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6e326cc48208229d1f28abf74a3e06944c8f7bec" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.github/workflows/rust.yml clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.github/workflows/rust.yml --- clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/.github/workflows/rust.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/.github/workflows/rust.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,47 @@ +name: Rust + +on: + push: {} + pull_request: {} + +jobs: + build_test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.34.0 + - 1.36.0 + - stable + - beta + - nightly + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + default: true + - name: Build the crate on minimal version. + uses: actions-rs/cargo@v1 + with: + command: build + - name: Build the crate on 1.36 with features. + if: matrix.rust != '1.34.0' + uses: actions-rs/cargo@v1 + with: + command: build + # Using `extern crate alloc` is only possible after 1.36 + args: --features=alloc,std,grab_spare_slice + - name: Test on Stable/Beta + if: matrix.rust != '1.34.0' && matrix.rust != '1.36.0' + uses: actions-rs/cargo@v1 + with: + command: test + args: --features=alloc --features=grab_spare_slice --features=rustc_1_40 + - name: Test on Nightly with All Features + if: matrix.rust == 'nightly' + uses: actions-rs/cargo@v1 + with: + command: test + args: --all-features diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/tinyvec/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/tinyvec/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,94 @@ +[package] +name = "tinyvec" +description = "`tinyvec` provides 100% safe vec-like data structures." +version = "1.6.0" +authors = ["Lokathor "] +edition = "2018" +license = "Zlib OR Apache-2.0 OR MIT" +keywords = ["vec", "no_std", "no-std"] +categories = ["data-structures", "no-std"] +repository = "https://github.com/Lokathor/tinyvec" + +[dependencies] +tinyvec_macros = { version = "0.1", optional = true } +# Provides `Serialize` and `Deserialize` implementations +serde = { version = "1.0", optional = true, default-features = false } +# Provides derived `Arbitrary` implementations +arbitrary = { version = "1", optional = true } + +[features] +default = [] + +# Provide things that utilize the `alloc` crate, namely `TinyVec`. +alloc = ["tinyvec_macros"] + +# Provide things that require Rust's `std` module +std = ["alloc"] + +# (not part of Vec!) Extra methods to let you grab the slice of memory after the +# "active" portion of an `ArrayVec` or `SliceVec`. +grab_spare_slice = [] + +# features that require rustc 1.40 +# use Vec::append if possible in TinyVec::append - 1.37 +# DoubleEndedIterator::nth_back - 1.40 +rustc_1_40 = [] + +# features that require rustc 1.55 +# use const generics to implement Array for all array lengths +rustc_1_55 = ["rustc_1_40"] + +# features that require rustc 1.57 +# add try_reserve functions to types that heap allocate. +rustc_1_57 = ["rustc_1_55"] + +# allow use of nightly feature `slice_partition_dedup`, +# will become useless once that is stabilized: +# https://github.com/rust-lang/rust/issues/54279 +nightly_slice_partition_dedup = [] + +# EXPERIMENTAL: Not part of SemVer. It adds `core::fmt::Write` to `ArrayVec` +# and `SliceVec`. It works on Stable Rust, but Vec normally supports the +# `std::io::Write` trait instead of `core::fmt::Write`, so we're keeping it as +# an experimental impl only for now. +experimental_write_impl = [] + +# Some benchmarks are optimized away with the stable black_box function +# which is based on read_volatile. This feature requires inline assembly +# and thus a nightly compiler, but is only used in benchmarks. +real_blackbox = ["criterion/real_blackbox"] + +[package.metadata.docs.rs] +features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] +rustdoc-args = ["--cfg","docs_rs"] + +[package.metadata.playground] +features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] + +[profile.test] +opt-level = 3 + +[profile.bench] +debug = 2 + +[workspace] +members = ["fuzz"] + +[dev-dependencies] +criterion = "0.3.0" +serde_test = "1.0" +smallvec = "1" + +[[test]] +name = "tinyvec" +required-features = ["alloc", "std"] + +[[bench]] +name = "macros" +harness = false +required-features = ["alloc"] + +[[bench]] +name = "smallvec" +harness = false +required-features = ["alloc", "real_blackbox"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/toml/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/toml/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.lock":"f310922cd8870e9f05600a24ea667cf258fd2f9452e052c2e8c63ff9561be060","Cargo.toml":"c26985583d0c680bafc99c11b4a99f5c8e63942c63a33c17588a5e9d3b101ef4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"a915ead738822da2d74b883c7519d8e558299286bb823e26c7fdece901c3267e","examples/decode.rs":"5c1bb83eef7fdf41f7d7873db4681492ce181000669aadee8895ca21e85f0aed","examples/enum_external.rs":"360618cced5c6339afbbc8799df2c047aaeeb1fa7d840dc777c2ffd83871883e","examples/toml2json.rs":"b0256e8393f91633abaa5b5c1ce496b73efee14a81b51e4f242aae967eaf9548","src/datetime.rs":"fe76c72cc5da6bccbd75ae3c7cb6658e92877631a93af4b88dcf54be6b6aeaed","src/de.rs":"6955dc090b657169f95e899f125c7fa6a668c2ab9a07b8c1bf330854e7e37087","src/lib.rs":"d599207a47e5fef74a0eeeb12d412429c305554816a89193ebbb8242f9585681","src/macros.rs":"506f00f2c12dd973a074d3c3263b0a97288eab4bda431d76d7a2cc95c63be0e0","src/map.rs":"ffc5539c8884baea62ed0e2ea89b018797c5e2d285f778f1d0e124a69ec29ddc","src/ser.rs":"e7f1e703efc1d30b0aca55c8d3f6bd62bb163652e0680cd5aeea7bf7217ba90e","src/spanned.rs":"eb370fed2aae511150d7ece47d38c95f11519db8e0b0748524338943579fe876","src/tokens.rs":"62c38be95ac994e6ae42ff983ac3ed66d3924decfd10e929455bf9168d9a1410","src/value.rs":"185ddf60a8e85472449b03e73f7353c3374f20cc720e32cdc33c750c2871a08b","tests/enum_external_deserialize.rs":"32515d5fa80e36efed6006da6514b5054c5c903960d9d884866d608ce9d23c35"},"package":"f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"189385f6d0d43c8f3f6de72858a3e550a37cb273a656b83f82816c691ed0cb7c","Cargo.lock":"f310922cd8870e9f05600a24ea667cf258fd2f9452e052c2e8c63ff9561be060","Cargo.toml":"c26985583d0c680bafc99c11b4a99f5c8e63942c63a33c17588a5e9d3b101ef4","Cargo.toml.orig":"97c03aeb3e083a12e027ff54f0915b9165ab9b7df29ba16eb9517050058f81b9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"a915ead738822da2d74b883c7519d8e558299286bb823e26c7fdece901c3267e","examples/decode.rs":"5c1bb83eef7fdf41f7d7873db4681492ce181000669aadee8895ca21e85f0aed","examples/enum_external.rs":"360618cced5c6339afbbc8799df2c047aaeeb1fa7d840dc777c2ffd83871883e","examples/toml2json.rs":"b0256e8393f91633abaa5b5c1ce496b73efee14a81b51e4f242aae967eaf9548","src/datetime.rs":"fe76c72cc5da6bccbd75ae3c7cb6658e92877631a93af4b88dcf54be6b6aeaed","src/de.rs":"6955dc090b657169f95e899f125c7fa6a668c2ab9a07b8c1bf330854e7e37087","src/lib.rs":"d599207a47e5fef74a0eeeb12d412429c305554816a89193ebbb8242f9585681","src/macros.rs":"506f00f2c12dd973a074d3c3263b0a97288eab4bda431d76d7a2cc95c63be0e0","src/map.rs":"ffc5539c8884baea62ed0e2ea89b018797c5e2d285f778f1d0e124a69ec29ddc","src/ser.rs":"e7f1e703efc1d30b0aca55c8d3f6bd62bb163652e0680cd5aeea7bf7217ba90e","src/spanned.rs":"eb370fed2aae511150d7ece47d38c95f11519db8e0b0748524338943579fe876","src/tokens.rs":"62c38be95ac994e6ae42ff983ac3ed66d3924decfd10e929455bf9168d9a1410","src/value.rs":"185ddf60a8e85472449b03e73f7353c3374f20cc720e32cdc33c750c2871a08b","tests/enum_external_deserialize.rs":"32515d5fa80e36efed6006da6514b5054c5c903960d9d884866d608ce9d23c35"},"package":"f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/toml/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/toml/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/toml/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0c2004aaa5d273075809428d8d7e3fc595141ef5" + }, + "path_in_vcs": "crates/toml" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/toml/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/toml/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/toml/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/toml/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,52 @@ +[package] +name = "toml" +version = "0.5.11" +readme = "README.md" +license = "MIT/Apache-2.0" +keywords = ["encoding", "toml"] +categories = ["encoding", "parser-implementations", "parsing", "config"] +description = """ +A native Rust encoder and decoder of TOML-formatted files and streams. Provides +implementations of the standard Serialize/Deserialize traits for TOML data to +facilitate deserializing and serializing Rust structures. +""" +authors = ["Alex Crichton "] +repository = "https://github.com/toml-rs/toml" +homepage = "https://github.com/toml-rs/toml" +documentation = "https://docs.rs/toml" +edition = "2018" +rust-version = "1.48.0" +include = [ + "src/**/*", + "Cargo.toml", + "LICENSE*", + "README.md", + "examples/**/*", + "benches/**/*", + "tests/**/*" +] + +[package.metadata.release] +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, + {file="CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/toml-rs/toml_edit/compare/{{tag_name}}...HEAD", exactly=1}, +] + +[features] +default = [] + +# Use indexmap rather than BTreeMap as the map type of toml::Value. +# This allows data to be read into a Value and written back to a TOML string +# while preserving the order of map keys in the input. +preserve_order = ["indexmap"] + +[dependencies] +serde = "1.0.97" +indexmap = { version = "1.0", optional = true } + +[dev-dependencies] +serde_derive = "1.0" +serde_json = "1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/transpose/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/transpose/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"b79ee1a75092a80a0682f9efb29a38cfde4c7092cbbc1365c862f6ec71b00942","LICENSE-APACHE":"8797ef61538ec5ee9222ebef7ca4e0f3ec5761b145ca9943d358c450efb644dd","LICENSE-MIT":"5080149357fd0be590bdc10cf92165412bb4d61ce496284d56f2d12874ae3121","README.md":"e500f94a56b62d7c6e8dc8e07540d875ce20c92f582468de95662a28fe96e212","RELEASES.md":"23f9ce012a84fed117c644ffafb6b7519cd192c49f49fc16eee3d7698087b3d8","benches/transpose_benchmarks.rs":"87745b176ceadf9b02a173eb6b6b81103d5e2145c3647e5c3e3bf3a7f8dbbbf9","src/in_place.rs":"bb1724204a42c901bf7d4faa13a299663eb332dc143605c11dfd9545be6d8046","src/lib.rs":"bfd475ad17b2f050b1ee17ba57f82d6ea3fc3bd1485568a12560d214d5672914","src/out_of_place.rs":"c41e80f2a4253c9e3a37e6780f8da9e53134812a1a93a524ff67f6b157f56f08","tests/test_transpose.rs":"caad0cfa784d428dcb4b36d98dc5eac63b46b09fac0a9582f424a50e8b2d0f3c"},"package":"1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"0d09fb02095cd495b625f502ce02f2078eddadb5586d6dc4dd296762b895261b","Cargo.toml":"b79ee1a75092a80a0682f9efb29a38cfde4c7092cbbc1365c862f6ec71b00942","Cargo.toml.orig":"3874f1c78eb0e7b8848e94d1dd37c1bf5a1c22b5372fe2c9cd39670b7a33d42f","LICENSE-APACHE":"8797ef61538ec5ee9222ebef7ca4e0f3ec5761b145ca9943d358c450efb644dd","LICENSE-MIT":"5080149357fd0be590bdc10cf92165412bb4d61ce496284d56f2d12874ae3121","README.md":"e500f94a56b62d7c6e8dc8e07540d875ce20c92f582468de95662a28fe96e212","RELEASES.md":"23f9ce012a84fed117c644ffafb6b7519cd192c49f49fc16eee3d7698087b3d8","benches/transpose_benchmarks.rs":"87745b176ceadf9b02a173eb6b6b81103d5e2145c3647e5c3e3bf3a7f8dbbbf9","src/in_place.rs":"bb1724204a42c901bf7d4faa13a299663eb332dc143605c11dfd9545be6d8046","src/lib.rs":"bfd475ad17b2f050b1ee17ba57f82d6ea3fc3bd1485568a12560d214d5672914","src/out_of_place.rs":"c41e80f2a4253c9e3a37e6780f8da9e53134812a1a93a524ff67f6b157f56f08","tests/test_transpose.rs":"caad0cfa784d428dcb4b36d98dc5eac63b46b09fac0a9582f424a50e8b2d0f3c"},"package":"1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/transpose/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/transpose/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/transpose/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "134293e7f7f8e13d342ae625e479e6097b5525db" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/transpose/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/transpose/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/transpose/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/transpose/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,28 @@ +[package] +name = "transpose" +version = "0.2.3" +authors = ["Elliott Mahler "] + +description = "Utility for transposing multi-dimensional data" + +license = "MIT OR Apache-2.0" + +repository = "https://github.com/ejmahler/transpose" +documentation = "https://docs.rs/transpose" +keywords = ["array", "transpose", "2d"] +categories = ["algorithms", "data structures", "no-std"] +readme = "README.md" + +[dependencies] +strength_reduce = "^0.2.1" + +[dependencies.num-integer] +version = "0.1" +default-features = false + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "transpose_benchmarks" +harness = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/typenum/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/typenum/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"2425bc9c5bd25aa4da8ccd1b86a38104e8ed179e73dec9615411df5819bf7cfe","Cargo.toml":"2a3f25a700cb4af300da02a9b7edbd59ed99815e108b75e112243e7a6df41f16","LICENSE":"db11fec9946737df39ca3898d9cd8c10ec6f6c3a884a6802b0ad0b81b4e8f23a","LICENSE-APACHE":"516b24e051bf5630880ebbd55c40a25ce9552ebaf8970a53e8976eb70e522406","LICENSE-MIT":"a825bd853ab71619a4923d7b4311221427848070ff44d990da39b0b274c1683f","README.md":"5108073f635aa3508ec8769ca0d9a65a62a7ce7aa491f130b2a8684c2779ace0","build/generic_const_mappings.rs":"ec66497bf1ee1c9b1a33e10b18b49e8f727f1b651522fafe3399ec81ea1b0a5c","build/main.rs":"a8b67aeb1767dd05d4a3d32d1d29bf5712a6fe93830a7fca85ead9fd90625205","build/op.rs":"291c798ff02c1c1150f13027e6e5aba9849b4d56f2a9003040f55d2dcd3c826b","build/tests.rs":"4e74a95412d9a7ad1dfba36cced27e3f723ab474a4b695d97c6adc30c5850d44","clippy.toml":"493258e6a4be8bbb66ecbc4236d8f4964f867d4bcddd5f13897aa655a206af7b","rustfmt.toml":"4953048a8d16fba8736c5cdb65ce418e462317a79793f16f79023f571f3fd5ce","src/array.rs":"89cc461b5fb76e551db5028085cf6a016ed07f12595b1833c984100377c3fe53","src/bit.rs":"a658ddf3b93db9eeb8fb3eb659f67356de40d1bccf544672d650ae7be1d8e215","src/int.rs":"4adaadb711694426a6af1e7fbb54f33d668992ac0a674b77f0894a1a2213fda8","src/lib.rs":"0c16481a1b72fd5261de7a6ec7a607edba599af8ace035d0636f0d0723f41906","src/marker_traits.rs":"5a58d16edc16853b4b793a6b46068d926911273aa9dc57fd9dc64df77986b7dd","src/operator_aliases.rs":"c190f5bcf9f674c2f2bb56886a45ff548e5acb9320b406cbc45204ef3bac46d5","src/private.rs":"e2ab0e29eacdedfe4182aa0567ac8e9cb53680dc04e1d75e197321b4e1446111","src/type_operators.rs":"2ec5e77be5b545a0ac982e948088e46c81b6a7bd5b57528917640b1faa2f8ee0","src/uint.rs":"dbcef84d261a044fdc5d7ec81bc5c2113fab4cc5232cab985a5c2809c7f153bc","tests/test.rs":"92139fa86ffcacc1dff60e6fc36420c850d70dc814bd21dc18e87857553c6cea"},"package":"42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"885cbd4683c19dfcd241e7db4dfa967fb5b605de3fd8fa8d9c9482b125ab4072",".github/workflows/check.yml":"04e09eb28bae939493c0a5d59687021c7ea7ce0c58f155e954e420b075004899",".github/workflows/publish.yml":"6cc521b26bac9de4b0f622669b75b51cff5daf319e9960aad1f22de2bc002448","CHANGELOG.md":"2425bc9c5bd25aa4da8ccd1b86a38104e8ed179e73dec9615411df5819bf7cfe","Cargo.toml":"2a3f25a700cb4af300da02a9b7edbd59ed99815e108b75e112243e7a6df41f16","Cargo.toml.orig":"2358be6bdeccf890a31f5bf3a7b905470b6f5d8b4be1c8fb36363d4bd1484e50","LICENSE":"db11fec9946737df39ca3898d9cd8c10ec6f6c3a884a6802b0ad0b81b4e8f23a","LICENSE-APACHE":"516b24e051bf5630880ebbd55c40a25ce9552ebaf8970a53e8976eb70e522406","LICENSE-MIT":"a825bd853ab71619a4923d7b4311221427848070ff44d990da39b0b274c1683f","README.md":"5108073f635aa3508ec8769ca0d9a65a62a7ce7aa491f130b2a8684c2779ace0","build/generic_const_mappings.rs":"ec66497bf1ee1c9b1a33e10b18b49e8f727f1b651522fafe3399ec81ea1b0a5c","build/main.rs":"a8b67aeb1767dd05d4a3d32d1d29bf5712a6fe93830a7fca85ead9fd90625205","build/op.rs":"291c798ff02c1c1150f13027e6e5aba9849b4d56f2a9003040f55d2dcd3c826b","build/tests.rs":"4e74a95412d9a7ad1dfba36cced27e3f723ab474a4b695d97c6adc30c5850d44","clippy.toml":"493258e6a4be8bbb66ecbc4236d8f4964f867d4bcddd5f13897aa655a206af7b","rustfmt.toml":"4953048a8d16fba8736c5cdb65ce418e462317a79793f16f79023f571f3fd5ce","src/array.rs":"89cc461b5fb76e551db5028085cf6a016ed07f12595b1833c984100377c3fe53","src/bit.rs":"a658ddf3b93db9eeb8fb3eb659f67356de40d1bccf544672d650ae7be1d8e215","src/int.rs":"4adaadb711694426a6af1e7fbb54f33d668992ac0a674b77f0894a1a2213fda8","src/lib.rs":"0c16481a1b72fd5261de7a6ec7a607edba599af8ace035d0636f0d0723f41906","src/marker_traits.rs":"5a58d16edc16853b4b793a6b46068d926911273aa9dc57fd9dc64df77986b7dd","src/operator_aliases.rs":"c190f5bcf9f674c2f2bb56886a45ff548e5acb9320b406cbc45204ef3bac46d5","src/private.rs":"e2ab0e29eacdedfe4182aa0567ac8e9cb53680dc04e1d75e197321b4e1446111","src/type_operators.rs":"2ec5e77be5b545a0ac982e948088e46c81b6a7bd5b57528917640b1faa2f8ee0","src/uint.rs":"dbcef84d261a044fdc5d7ec81bc5c2113fab4cc5232cab985a5c2809c7f153bc","tests/test.rs":"92139fa86ffcacc1dff60e6fc36420c850d70dc814bd21dc18e87857553c6cea"},"package":"42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/typenum/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/typenum/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/typenum/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "b237efbb1da9646435274f63d7290cb7651b031f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/typenum/.github/workflows/check.yml clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/check.yml --- clamav-1.4.3+dfsg/.cargo/vendor/typenum/.github/workflows/check.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/check.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,96 @@ +on: + push: + branches: + - main + pull_request: + branches: + - main + +name: CI + +jobs: + all-succeeded: + name: All Succeeded + if: always() + runs-on: ubuntu-latest + needs: + - test-linux + - test-non-linux + - lint + + steps: + - name: Check if all jubs succeeded + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} + + test-linux: + name: Test Linux + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: + - stable + - beta + - nightly + mb_const_generics: + - "" + - "--features const-generics" + target: + - x86_64 + - i686 + - sparc64 + include: + - mb_const_generics: "" + rust: 1.37.0 + target: x86_64 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - uses: actions-rs/cargo@v1 + with: + use-cross: ${{ matrix.target != 'x86_64' }} + command: test + args: --verbose --features "strict" ${{ matrix.mb_const_generics }} --target ${{ matrix.target }}-unknown-linux-gnu + - uses: actions-rs/cargo@v1 + with: + use-cross: ${{ matrix.target != 'x86_64' }} + command: doc + args: --features "strict" ${{ matrix.mb_const_generics }} --target ${{ matrix.target }}-unknown-linux-gnu + + test-non-linux: + name: Test non-Linux + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - macos-latest + - windows-latest + rust: + - stable + mb_const_generics: + - "" + - "--features const-generics" + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - run: cargo test --verbose --features "strict" ${{ matrix.mb_const_generics }} + - run: cargo doc --features "strict" ${{ matrix.mb_const_generics }} + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt, clippy + - run: cargo fmt --all -- --check + - run: cargo clippy -- -D warnings + # Allow deprecated because we test the no_std feature. + - run: cargo clippy --all-features -- -D warnings -A deprecated diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/typenum/.github/workflows/publish.yml clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/publish.yml --- clamav-1.4.3+dfsg/.cargo/vendor/typenum/.github/workflows/publish.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/typenum/.github/workflows/publish.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,27 @@ +on: + push: + tags: + - 'v*' + +name: Publish + +jobs: + release: + name: GitHub Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: marvinpinto/action-automatic-releases@latest + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: false + + publish: + name: Crates.io Publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - uses: katyo/publish-crates@v1 + with: + registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/typenum/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/typenum/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/typenum/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/typenum/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,40 @@ +[package] +name = "typenum" +build = "build/main.rs" +version = "1.17.0" # remember to update html_root_url +authors = [ + "Paho Lurie-Gregg ", + "Andre Bogus ", +] +documentation = "https://docs.rs/typenum" +repository = "https://github.com/paholg/typenum" +readme = "README.md" +license = "MIT OR Apache-2.0" +description = """Typenum is a Rust library for type-level numbers evaluated at + compile time. It currently supports bits, unsigned integers, and signed + integers. It also provides a type-level array of type-level numbers, but its + implementation is incomplete.""" +categories = ["no-std"] +edition = "2018" +rust-version = "1.37.0" + +[dependencies] +scale-info = { version = "1.0", default-features = false, optional = true } + +[lib] +name = "typenum" + +[features] +no_std = [] # Deprecated +i128 = [] +strict = [] +force_unix_path_separator = [] # Deprecated +const-generics = [] +scale_info = ["scale-info/derive"] + +[package.metadata.docs.rs] +features = ["i128", "const-generics"] +rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.playground] +features = ["i128", "const-generics"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"7b10355305359d5feefb120329396a8823ce903cd66612d7d27612d51e6ceced","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-UNICODE":"68f5b9f5ea36881a0942ba02f558e9e1faf76cc09cb165ad801744c61b738844","README.md":"eff1f30712e93cc160101c25bf31738448c284b90636deb3e3a651cb9ad20dd1","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"2673969775cff349816e3fb30f62476a802523fe4940482288b75bd747cbe748","src/tables.rs":"ffe8e252eabccf261385865cb781b3d76c9f32f6f9503d00196a30fb92d80b29","tests/compare.rs":"62471ffb157744cac6faae1adafdbdf785349d7eb6dc2ff4b4941c9d618397f9","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"41fc751514b8bde658544d5fe7e100115d299d41897af855934b9f4ebda9d3a2","tests/fst/xid_start.fst":"ffa5e2bfe7dd5f6738fbe4b7a3e6e2083c9777191c54f8291a80d558ec4e2dd2","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"4524332c1e424cb987d7cee1f47a98aea9ed7b256303a3828eda5aa1d06da240","tests/tables/mod.rs":"e6949172d10fc4b2431ce7546269bfd4f9146454c8c3e31faf5e5d80c16a8ab6","tests/tables/tables.rs":"011404dab8a3958da6e18a1fe9406c191675e6f49bf30ce813e3d05f582e750b","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"3c1ca56062f1b3ffdf2ae2063d3fee8d362b90082778056181b5c95e2e242ad8"},"package":"3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"9a146c5bd0d70cd4353761f592d070682d89ecc9a0243c23c4e0056be2512eb8",".github/FUNDING.yml":"b017158736b3c9751a2d21edfce7fe61c8954e2fced8da8dd3013c2f3e295bd9",".github/workflows/ci.yml":"a84dda80829b61dc7da83d03e15f1e7c09f96ff90956ae8e6d0fd778fc17e2c6","Cargo.toml":"7b10355305359d5feefb120329396a8823ce903cd66612d7d27612d51e6ceced","Cargo.toml.orig":"78fc5b9a07bb19088caf7c689099266b707f958d2ed345dc2651a7e547f834f1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-UNICODE":"68f5b9f5ea36881a0942ba02f558e9e1faf76cc09cb165ad801744c61b738844","README.md":"eff1f30712e93cc160101c25bf31738448c284b90636deb3e3a651cb9ad20dd1","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"2673969775cff349816e3fb30f62476a802523fe4940482288b75bd747cbe748","src/tables.rs":"ffe8e252eabccf261385865cb781b3d76c9f32f6f9503d00196a30fb92d80b29","tests/compare.rs":"62471ffb157744cac6faae1adafdbdf785349d7eb6dc2ff4b4941c9d618397f9","tests/fst/.gitignore":"4f4a75ab06f09cddd09eafd3583e506101333812c171bf0bf0db0652d06f604d","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"41fc751514b8bde658544d5fe7e100115d299d41897af855934b9f4ebda9d3a2","tests/fst/xid_start.fst":"ffa5e2bfe7dd5f6738fbe4b7a3e6e2083c9777191c54f8291a80d558ec4e2dd2","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"4524332c1e424cb987d7cee1f47a98aea9ed7b256303a3828eda5aa1d06da240","tests/tables/mod.rs":"e6949172d10fc4b2431ce7546269bfd4f9146454c8c3e31faf5e5d80c16a8ab6","tests/tables/tables.rs":"011404dab8a3958da6e18a1fe9406c191675e6f49bf30ce813e3d05f582e750b","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"3c1ca56062f1b3ffdf2ae2063d3fee8d362b90082778056181b5c95e2e242ad8"},"package":"3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ff4d27c49422d8f9e0aa4bc799a02544a2a44baf" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.github/FUNDING.yml clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/FUNDING.yml --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/FUNDING.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +github: dtolnay diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + schedule: [cron: "40 1 * * *"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + + unicode: + name: latest Unicode + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - id: ucd-generate + run: echo "version=$(grep 'ucd-generate [0-9]\+\.[0-9]\+\.[0-9]\+' tests/tables/tables.rs --only-matching)" >> $GITHUB_OUTPUT + - run: cargo install ucd-generate + - run: curl https://www.unicode.org/Public/zipped/latest/UCD.zip --location --remote-name --silent --show-error --fail --retry 2 + - run: unzip UCD.zip -d UCD + - run: ucd-generate property-bool UCD --include XID_Start,XID_Continue > tests/tables/tables.rs + - run: ucd-generate property-bool UCD --include XID_Start,XID_Continue --fst-dir tests/fst + - run: ucd-generate property-bool UCD --include XID_Start,XID_Continue --trie-set > tests/trie/trie.rs + - run: cargo run --manifest-path generate/Cargo.toml + - run: sed --in-place 's/ucd-generate [0-9]\+\.[0-9]\+\.[0-9]\+/${{steps.ucd-generate.outputs.version}}/' tests/tables/tables.rs tests/trie/trie.rs + - run: git diff --exit-code + + test: + name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: [nightly, beta, stable, 1.70.0] + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust}} + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + - run: cargo check --benches + + msrv: + name: Rust 1.31.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.31.0 + - run: cargo check --manifest-path tests/crate/Cargo.toml + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests --benches --workspace -- -Dclippy::all -Dclippy::pedantic + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +[package] +name = "unicode-ident" +version = "1.0.12" +authors = ["David Tolnay "] +categories = ["development-tools::procedural-macro-helpers", "no-std", "no-std::no-alloc"] +description = "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31" +documentation = "https://docs.rs/unicode-ident" +edition = "2018" +keywords = ["unicode", "xid"] +license = "(MIT OR Apache-2.0) AND Unicode-DFS-2016" +repository = "https://github.com/dtolnay/unicode-ident" +rust-version = "1.31" + +[dev-dependencies] +criterion = { version = "0.5", default-features = false } +fst = "0.4" +rand = { version = "0.8", features = ["small_rng"] } +roaring = "0.10" +ucd-trie = { version = "0.1", default-features = false } +unicode-xid = "0.2.4" + +[[bench]] +name = "xid" +harness = false + +[workspace] +members = ["diagram", "generate"] + +[lib] +doc-scrape-examples = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/tests/fst/.gitignore clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/tests/fst/.gitignore --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-ident/tests/fst/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-ident/tests/fst/.gitignore 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +prop_list.rs diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"694aa78d7569404115da2f0e85f26445d51c8e4a107cce2c750563f997c4771e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"64d241ba25087bb059777c8944dd0ec41b31d9a21ba791e5321a5db4090741c1","benches/graphemes.rs":"88a9f672ea7a03cc15fae36ce544a6e7234e532359402483978858ccda47db3d","benches/unicode_words.rs":"42df2c8e9bfb54baf31c8327e27915683c25b90d55dc04311c28a0c2a9d185e3","benches/word_bounds.rs":"0453e37477134063178e104305b0a5f27ce74aa342234a6208095623c45de0d4","scripts/unicode.py":"482128cdce4f301ae6ec1fc1066adae4cb1c1e3875fe9521066d670b2b65a7e5","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"b5a32bdbb529e9417e8ada8d92656339b6ffb4e9bed8e6d32a0409c13a03050b","src/lib.rs":"572789173717edd0fe037ae656530663406951636c548e6793711b7d5caad910","src/sentence.rs":"8bb4b02358c4ccd4d8795c95bba68d8e1dec2cfb947feb2e93a93e5d562a7c4a","src/tables.rs":"e8874486fa10ea11da5cb7e7da9010032c923a047cc7528b0079396ee0901599","src/test.rs":"fb388c10395dbb0887e1ae1ef591dd01e531485c83b022bf4285cca1b3264410","src/testdata.rs":"858217baa2ac64f180ca65af2e1005e6deed3e4a4ad1ce615765a1ec009cfbb1","src/word.rs":"c1b018c849ace7fef20adcdd82caa22f3a0f9692c1f4dd7162b07aa2b4f88be8"},"package":"d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"853d772800fa73d72223662827c4e59f2f57174464bed36e79a3d72fbafc3bbd","COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"694aa78d7569404115da2f0e85f26445d51c8e4a107cce2c750563f997c4771e","Cargo.toml.orig":"ec25b66fd783754dccfac14d15ebd1472b2e3899f42106505392598730e7137d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"64d241ba25087bb059777c8944dd0ec41b31d9a21ba791e5321a5db4090741c1","benches/graphemes.rs":"88a9f672ea7a03cc15fae36ce544a6e7234e532359402483978858ccda47db3d","benches/unicode_words.rs":"42df2c8e9bfb54baf31c8327e27915683c25b90d55dc04311c28a0c2a9d185e3","benches/word_bounds.rs":"0453e37477134063178e104305b0a5f27ce74aa342234a6208095623c45de0d4","scripts/unicode.py":"482128cdce4f301ae6ec1fc1066adae4cb1c1e3875fe9521066d670b2b65a7e5","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"b5a32bdbb529e9417e8ada8d92656339b6ffb4e9bed8e6d32a0409c13a03050b","src/lib.rs":"572789173717edd0fe037ae656530663406951636c548e6793711b7d5caad910","src/sentence.rs":"8bb4b02358c4ccd4d8795c95bba68d8e1dec2cfb947feb2e93a93e5d562a7c4a","src/tables.rs":"e8874486fa10ea11da5cb7e7da9010032c923a047cc7528b0079396ee0901599","src/test.rs":"fb388c10395dbb0887e1ae1ef591dd01e531485c83b022bf4285cca1b3264410","src/testdata.rs":"858217baa2ac64f180ca65af2e1005e6deed3e4a4ad1ce615765a1ec009cfbb1","src/word.rs":"c1b018c849ace7fef20adcdd82caa22f3a0f9692c1f4dd7162b07aa2b4f88be8"},"package":"d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8b894ca626d886da0d0974f9760e217cbba99378" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/unicode-segmentation/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/unicode-segmentation/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,38 @@ +[package] + +name = "unicode-segmentation" +version = "1.11.0" +authors = ["kwantam ", "Manish Goregaokar "] + +edition = "2018" +homepage = "https://github.com/unicode-rs/unicode-segmentation" +repository = "https://github.com/unicode-rs/unicode-segmentation" + +license = "MIT/Apache-2.0" +keywords = ["text", "unicode", "grapheme", "word", "boundary"] +readme = "README.md" +description = """ +This crate provides Grapheme Cluster, Word and Sentence boundaries +according to Unicode Standard Annex #29 rules. +""" + +exclude = ["/.github", "/benches/texts", "/scripts/**.rs", "*.txt"] + +[features] +no_std = [] # This is a no-op, preserved for backward compatibility only. + +[dev-dependencies] +quickcheck = "0.7" +criterion = "0.3" + +[[bench]] +name = "graphemes" +harness = false + +[[bench]] +name = "unicode_words" +harness = false + +[[bench]] +name = "word_bounds" +harness = false \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/uuid/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/uuid/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"c0dd11744acbc58cd3dc221e331db2f6058f30fb49055376201213acda208c86","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"436bc5a105d8e57dcd8778730f3754f7bf39c14d2f530e4cde4bd2d17a83ec3d","README.md":"3121557f3207ddbcaf90d00f6b4635988e5d7d6ae084e84f59c785e28254cee9","src/builder.rs":"2d6e3bf66fc87e36c44b1a8c108dca70f01f6296ac0d50d0a788b69b5a3dff88","src/error.rs":"621799694111aab9d6e570290f4d1b341fe6be58d2b3425fa7891ada7575cab7","src/external.rs":"a0640bdb98de1c24fcc9851a438a5abe6f7e3acb195885c817a64fac25521b9d","src/external/arbitrary_support.rs":"7e7fbcc4b8af5878b71858a1f5fa31e85d84fc2fd159614f8d450ba1fe06ac28","src/external/borsh_support.rs":"b49d82a59653445ba26db46a1515294b1ab480c0671dbe5499dfd1fb02588b3b","src/external/serde_support.rs":"040b021b6814a822dcab26f572ff37ecb31d76958dd3b3c708ac8470b7e0e431","src/external/slog_support.rs":"53c6251e424bdc9b6ba35defb4c723d4d34d44053badbf98e1c7c3e7c83fbb5e","src/fmt.rs":"3bf88d68d838bef81380a1e669a86eee46f24a8113effbd7b4e92da714ec97c7","src/lib.rs":"d92276ee27bf3b9618d1d472a6488d279cbb63784369c3ad8e72c1099683a27d","src/macros.rs":"8fa9380a39e9952f6adc9eb858264fc09219a97215f4e54768d9e0ec7f520db7","src/md5.rs":"316d65b760ffa58beb6aa678be24359eb21a744e9e143bc99c11fe1907659245","src/parser.rs":"6d17d50bd5bfa207a50e1d8c57a83ec2275a73cd55dc6b2ec56eb3e990d16835","src/rng.rs":"b9f69610560aa5b5d9b2eaa16fb2239515bd163da126cf5c392e5fb9b0296c3e","src/sha1.rs":"e1a9657e11f1ed1ede33c0655f9c2641059b7c24f17be4ac425c930cc216e019","src/timestamp.rs":"2b50321ee768cd9c3ad5bdf1e4924e8e5deaa8d1a031d24dcfaf2fec44530429","src/v1.rs":"123c4b23d0458e77e6c3ed6235e0c786436e53f53d1c8074cf80d77c2ae40611","src/v3.rs":"b7d605c4d2f56a9e57bfe779ef2488fa612c7cb28568f68252093f48ac2edef4","src/v4.rs":"4f06567460871348df0ff2825e9faad9d950a9337e409cb2b568c86118addb97","src/v5.rs":"64e3feb673c8411954f930188e756803b90b57d13ec36652cd2c669e81654333","src/v6.rs":"2dd938c5bf6d1960f4fb7d179a6163c1cfd76ab24f98aaca85d0f74940184645","src/v7.rs":"e46924c0c9c9b1ac6746180d78cd3531920fbd8379f1629abdcec7914bae36c8","src/v8.rs":"8705405fef52e4706c7cf99f7ed231dde733b7cd08ced79be9e29c949be2280f"},"package":"a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"d66aa4b31cf67b5938ef9a273955bf3930cffd50ed6d9d457ba99251667ac852","Cargo.toml":"c0dd11744acbc58cd3dc221e331db2f6058f30fb49055376201213acda208c86","Cargo.toml.orig":"7552c9fb3ca0c8fe95337a6762b0682971939e783ebba13a81e1145bbfa8ac53","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"436bc5a105d8e57dcd8778730f3754f7bf39c14d2f530e4cde4bd2d17a83ec3d","README.md":"3121557f3207ddbcaf90d00f6b4635988e5d7d6ae084e84f59c785e28254cee9","src/builder.rs":"2d6e3bf66fc87e36c44b1a8c108dca70f01f6296ac0d50d0a788b69b5a3dff88","src/error.rs":"621799694111aab9d6e570290f4d1b341fe6be58d2b3425fa7891ada7575cab7","src/external.rs":"a0640bdb98de1c24fcc9851a438a5abe6f7e3acb195885c817a64fac25521b9d","src/external/arbitrary_support.rs":"7e7fbcc4b8af5878b71858a1f5fa31e85d84fc2fd159614f8d450ba1fe06ac28","src/external/borsh_support.rs":"b49d82a59653445ba26db46a1515294b1ab480c0671dbe5499dfd1fb02588b3b","src/external/serde_support.rs":"040b021b6814a822dcab26f572ff37ecb31d76958dd3b3c708ac8470b7e0e431","src/external/slog_support.rs":"53c6251e424bdc9b6ba35defb4c723d4d34d44053badbf98e1c7c3e7c83fbb5e","src/fmt.rs":"3bf88d68d838bef81380a1e669a86eee46f24a8113effbd7b4e92da714ec97c7","src/lib.rs":"d92276ee27bf3b9618d1d472a6488d279cbb63784369c3ad8e72c1099683a27d","src/macros.rs":"8fa9380a39e9952f6adc9eb858264fc09219a97215f4e54768d9e0ec7f520db7","src/md5.rs":"316d65b760ffa58beb6aa678be24359eb21a744e9e143bc99c11fe1907659245","src/parser.rs":"6d17d50bd5bfa207a50e1d8c57a83ec2275a73cd55dc6b2ec56eb3e990d16835","src/rng.rs":"b9f69610560aa5b5d9b2eaa16fb2239515bd163da126cf5c392e5fb9b0296c3e","src/sha1.rs":"e1a9657e11f1ed1ede33c0655f9c2641059b7c24f17be4ac425c930cc216e019","src/timestamp.rs":"2b50321ee768cd9c3ad5bdf1e4924e8e5deaa8d1a031d24dcfaf2fec44530429","src/v1.rs":"123c4b23d0458e77e6c3ed6235e0c786436e53f53d1c8074cf80d77c2ae40611","src/v3.rs":"b7d605c4d2f56a9e57bfe779ef2488fa612c7cb28568f68252093f48ac2edef4","src/v4.rs":"4f06567460871348df0ff2825e9faad9d950a9337e409cb2b568c86118addb97","src/v5.rs":"64e3feb673c8411954f930188e756803b90b57d13ec36652cd2c669e81654333","src/v6.rs":"2dd938c5bf6d1960f4fb7d179a6163c1cfd76ab24f98aaca85d0f74940184645","src/v7.rs":"e46924c0c9c9b1ac6746180d78cd3531920fbd8379f1629abdcec7914bae36c8","src/v8.rs":"8705405fef52e4706c7cf99f7ed231dde733b7cd08ced79be9e29c949be2280f"},"package":"a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/uuid/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/uuid/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/uuid/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0f2aaaeab9d20ce1f724e6b31b5b47639c2afa95" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/uuid/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/uuid/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/uuid/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/uuid/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,193 @@ +[package] +authors = [ + "Ashley Mannix", + "Christopher Armstrong", + "Dylan DPC", + "Hunar Roop Kahlon" +] +categories = [ + "data-structures", + "no-std", + "parser-implementations", + "wasm" +] +description = "A library to generate and parse UUIDs." +documentation = "https://docs.rs/uuid" +edition = "2018" +include = [ + "src", + "README.md", + "LICENSE-APACHE", + "LICENSE-MIT", +] +keywords = [ + "guid", + "unique", + "uuid" +] +license = "Apache-2.0 OR MIT" +homepage = "https://github.com/uuid-rs/uuid" +name = "uuid" +readme = "README.md" +repository = "https://github.com/uuid-rs/uuid" +version = "1.8.0" # remember to update html_root_url in lib.rs +rust-version = "1.60.0" + +[package.metadata.docs.rs] +rustc-args = ["--cfg", "uuid_unstable"] +rustdoc-args = ["--cfg", "uuid_unstable"] +targets = ["x86_64-unknown-linux-gnu"] +features = ["serde", "arbitrary", "slog", "borsh", "v1", "v3", "v4", "v5", "v6", "v7", "v8"] + +[package.metadata.playground] +features = ["serde", "v1", "v3", "v4", "v5", "v6", "v7", "v8"] + +[badges.is-it-maintained-issue-resolution] +repository = "uuid-rs/uuid" + +[badges.is-it-maintained-open-issues] +repository = "uuid-rs/uuid" + +[badges.maintenance] +status = "actively-developed" + +[features] +default = ["std"] +std = [] +macro-diagnostics = ["dep:uuid-macro-internal"] + +# NOTE: When adding new features, check the `ci.yml` workflow +# and include them where necessary (you can follow along with existing features) +v1 = ["atomic"] +v3 = ["md5"] +v4 = ["rng"] +v5 = ["sha1"] +v6 = ["atomic"] +v7 = ["atomic", "rng"] +v8 = [] + +js = ["dep:wasm-bindgen", "getrandom?/js"] + +rng = ["dep:getrandom"] +fast-rng = ["rng", "dep:rand"] + +sha1 = ["dep:sha1_smol"] +md5 = ["dep:md-5"] +atomic = ["dep:atomic"] + +borsh = ["dep:borsh", "dep:borsh-derive"] + +# Public: Used in trait impls on `Uuid` +[dependencies.bytemuck] +version = "1.14.0" +optional = true +features = ["derive"] + +# Public: Used in trait impls on `Uuid` +[dependencies.serde] +default-features = false +optional = true +version = "1.0.56" + +# Public: Used in trait impls on `Uuid` +[dependencies.slog] +optional = true +version = "2" + +# Public: Used in trait impls on `Uuid` +[dependencies.arbitrary] +optional = true +version = "1.1.3" + +# Public (unstable): Used in `zerocopy` derive +# Unstable: also need RUSTFLAGS="--cfg uuid_unstable" to work +# This feature may break between releases, or be removed entirely before +# stabilization. +# See: https://github.com/uuid-rs/uuid/issues/588 +[dependencies.zerocopy] +optional = true +version = "0.6" + +# Public: Used in trait impls on `Uuid` +[dependencies.borsh] +optional = true +version = "1" +default-features = false + +# Private +[dependencies.borsh-derive] +optional = true +version = "1" +default-features = false + +# Public +# Usage of `getrandom`'s pluggable randomness for custom targets is documented +# in `uuid`'s library docs +[dependencies.getrandom] +optional = true +version = "0.2" + +# Private +[dependencies.rand] +optional = true +version = "0.8" + +# Private +[dependencies.md-5] +default-features = false +optional = true +version = "0.10" + +# Private +[dependencies.sha1_smol] +default-features = false +optional = true +version = "1" + +# Public: Re-exported +[dependencies.uuid-macro-internal] +version = "1.8.0" +path = "macros" +optional = true + +# Private +[dependencies.atomic] +default-features = false +optional = true +version = "0.5" + +# Private +[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))'.dependencies.wasm-bindgen] +version = "0.2" +optional = true + +[dev-dependencies.bincode] +version = "1.0" + +[dev-dependencies.serde_derive] +version = "1.0.79" + +[dev-dependencies.serde_json] +version = "1.0" + +[dev-dependencies.serde_test] +version = "1.0.56" + +[target.'cfg(target = "wasm32-unknown-unknown")'.dev-dependencies.wasm-bindgen] +version = "0.2" + +[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))'.dev-dependencies.wasm-bindgen-test] +version = "0.3" + +[dev-dependencies.trybuild] +version = "1.0.52" + +[dev-dependencies.rustversion] +version = "1" + +[workspace] +members = [ + "macros", + "examples", + "tests/smoke-test", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"f2511e7b87b313a9e7ef621517bcfa6f5b2af77f0bfe5385ebf05071f777393e",".github/workflows/crate.yml":"c745087eb0c995fb2307e2f4d014200b3e12e09a912abe19a7afe2c3f9c1b9bf","CHANGELOG.md":"b5cf70fef7729f6cf06521643ba5ff2d77184792141a3424c54a81e1edc8f9e5","Cargo.lock":"ef05106642ccd0982d511e036bf70bc8fa6fc264998ada0e887f70f1ea0392db","Cargo.toml":"9bffbf5677947e2543d763aff435550fabd8b20833ef6ba7bb80851d9199b06d","Cargo.toml.orig":"68fba5a45fd2af5c1439f4eb228d4b0d79208defb118f947bd86f3fde7cc904e","LICENSE":"02b80951ce6c1dd25d7278977222a91b2f61a883ca272b0238c52a60a03ae90a","README.md":"08b4c9b0d20b49767ab7f5c8bdfb6304b69be80c97172af2c5e7a49d3350bd23","benches/bench.rs":"4147a34383a6618d483dc3a3f12cecb2c229f5c01391ece775f3eec260436d44","clippy.toml":"95793517e56cd171c5d00320e18a83c26d5ac6feafd0195a4f06208b790fecce","src/frame.rs":"95de4f00b7dc42003523a494f164e6a30431495eff1dc4206bae433c7050bb0c","src/lib.rs":"4544307f930a9b2389e8891ae27b9110271cdea0395585c4289cccecfe4be024","src/math.rs":"a81bb2281f19ba479861779a080aca093c7be995a27af252df382c32995679e8","src/pixel.rs":"56b4110a85fa6fe413d943db0f15fa9c97bca8b1371795191ae423ee844c4a38","src/plane.rs":"e517ad4dfe667fe90bf7ff79a5e015deaae99482e82bd3821cbdd8873a349fe0"},"package":"666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e01ef7d4fbde65ca4daaf8bf8d93eee17a1703cc" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.github/workflows/crate.yml clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.github/workflows/crate.yml --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/.github/workflows/crate.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/.github/workflows/crate.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,90 @@ +name: Crate + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo clippy + - name: Run tests + run: cargo test + - name: Install cargo-msrv + uses: taiki-e/install-action@v2 + with: + tool: cargo-msrv + - name: Validate minimum Rust version + run: | + cargo msrv verify + + test-wasm: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown + + - name: Install wasm-pack + uses: taiki-e/install-action@v2 + with: + tool: wasm-pack + + - name: Run tests + run: wasm-pack test --headless --chrome --firefox + + miri: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust nightly and miri + uses: dtolnay/rust-toolchain@nightly + with: + components: miri, rust-src + + - name: Run miri + env: + RUSTFLAGS: -Zrandomize-layout + MIRIFLAGS: -Zmiri-symbolic-alignment-check + run: cargo miri test + + code-coverage: + needs: [ miri, build ] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust stable and LLVM tools + uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@v2 + with: + tool: cargo-llvm-cov + + - name: Generate code coverage + run: cargo llvm-cov --lcov --output-path lcov.log + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.log + fail_ci_if_error: true diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/v_frame/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,39 @@ +## Version 0.3.8 + +- Eliminate unsound code +- Remove several unnecessary dependencies +- Internal refactoring + +## Version 0.3.7 + +- Add documentation for `Frame` struct +- Replace `hawktracer` with `tracing` crate + +## Version 0.3.6 + +- Revert changes in downsampling in 0.3.4 which changed its behavior + +## Version 0.3.5 + +- Bump num-derive to 0.4 + +## Version 0.3.4 + +- Fix cases of unsoundness (#14) +- Slight optimizations for downsampling + +## Version 0.3.3 + +- Add `row_cropped` and `row_slice_cropped` methods to get rows without padding +- Make `RowsIter` and `RowsIterMut` return rows without right-side padding for greater consistency/predictability +- Fix clippy lints + +## Version 0.3.1 + +- Add `rows_iter_mut` method to `Plane` + +## Version 0.2.6 + +- Split into separate repository +- Remove unused rayon dependency +- Fix some clippy lints diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,745 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", + "serde", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "criterion" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", + "tracing", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "v_frame" +version = "0.3.9" +dependencies = [ + "aligned-vec", + "criterion", + "num-traits", + "profiling", + "serde", + "tracing", + "wasm-bindgen", + "wasm-bindgen-test", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,80 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.80.0" +name = "v_frame" +version = "0.3.9" +authors = ["Luca Barbato "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Video Frame data structures, originally part of rav1e" +readme = "README.md" +license = "BSD-2-Clause" +repository = "https://github.com/rust-av/v_frame" + +[features] +profiling = ["dep:profiling"] +serialize = [ + "serde", + "aligned-vec/serde", +] +tracing = [ + "profiling", + "dep:tracing", + "profiling/profile-with-tracing", +] + +[lib] +name = "v_frame" +path = "src/lib.rs" + +[[bench]] +name = "bench" +path = "benches/bench.rs" +harness = false + +[dependencies.aligned-vec] +version = ">=0.5.0, <0.7" + +[dependencies.num-traits] +version = "0.2" + +[dependencies.profiling] +version = "1" +optional = true + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dependencies.tracing] +version = "0.1.40" +optional = true + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.6" + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies.criterion] +version = "0.6" +default-features = false + +[target.wasm32-unknown-unknown.dependencies.wasm-bindgen] +version = "0.2" + +[target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen-test] +version = "0.3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +[package] +name = "v_frame" +version = "0.3.9" +rust-version = "1.80.0" +description = "Video Frame data structures, originally part of rav1e" +license = "BSD-2-Clause" +authors = ["Luca Barbato "] +edition = "2021" +repository = "https://github.com/rust-av/v_frame" + +[features] +serialize = ["serde", "aligned-vec/serde"] +profiling = ["dep:profiling"] +tracing = ["profiling", "dep:tracing", "profiling/profile-with-tracing"] + +[dependencies] +num-traits = "0.2" +serde = { version = "1.0", features = ["derive"], optional = true } +aligned-vec = ">=0.5.0, <0.7" + +# Profiling dependencies +profiling = { version = "1", optional = true } +tracing = { version = "0.1.40", optional = true } + +[[bench]] +name = "bench" +harness = false + +# +# WebAssembly/wasm32 target support below +# +# There are two main WASM targets: +# - wasm32-unknown-unknown: Base WebAssembly standard, used in browsers +# - wasm32-wasi: Newer extension/standard, comes with basic std library, +# not supported in browsers (yet) +# +# Some things work in all WASM configurations, some work only on one of these two, +# some things don't work on wasm32 at all. +# +# wasm32-unknown-unknown requires wasm_bindgen and wasm_bindgen_test to work, +# but these can cause problems on wasm32-wasi. So we use either +# - target_arch = "wasm32" for things that (don't) work on all WebAssembly targets or +# - explicit targetting for wasm32-unknown-unknown or wasm32-wasi. +# In Cargo.toml, this is done via [target..dependencies] +# In code, this is done via cfg(all(target_arch = "wasm32", target_os = "wasi"/"unknown")) + +# The rayon feature does not work on any wasm32 target +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = "0.6" + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +criterion = { version = "0.6", default-features = false } + +# wasm-bindgen is only needed for wasm32-unknown-unknown and not other wasm32 targets +[target.wasm32-unknown-unknown.dependencies] +wasm-bindgen = "0.2" + +[target.wasm32-unknown-unknown.dev-dependencies] +wasm-bindgen-test = "0.3" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/v_frame/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2017-2022, the rav1e contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/README.md clamav-1.4.6+dfsg/.cargo/vendor/v_frame/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +# v_frame + +[![docs.rs](https://img.shields.io/docsrs/v_frame)](https://docs.rs/v_frame) +[![Crates.io](https://img.shields.io/crates/v/v_frame)](https://crates.io/crates/v_frame) +[![LICENSE](https://img.shields.io/crates/l/v_frame)](https://github.com/rust-av/v_frame/blob/main/LICENSE) +[![dependency status](https://deps.rs/repo/github/rust-av/v_frame/status.svg)](https://deps.rs/repo/github/rust-av/v_frame) +[![codecov](https://codecov.io/github/rust-av/v_frame/branch/main/graph/badge.svg?token=MKT1AZREF0)](https://codecov.io/github/rust-av/v_frame) + +Crate providing structs and utilities for handling YUV Frames and Planes. +Originally used by rav1e, now branched into its own crate for wider use +throughout Rust AV. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/benches/bench.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/benches/bench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/benches/bench.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/benches/bench.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,125 @@ +use std::hint::black_box; + +use criterion::{criterion_group, criterion_main, Criterion}; +use v_frame::frame::Frame; +use v_frame::pixel::{CastFromPrimitive, ChromaSampling}; +use v_frame::plane::Plane; + +fn frame(c: &mut Criterion) { + c.bench_function("frame new_with_padding padding=0", |b| { + b.iter(|| { + Frame::::new_with_padding( + black_box(640), + black_box(480), + black_box(ChromaSampling::Cs420), + black_box(0), + ) + }) + }); + + c.bench_function("frame new_with_padding padding!=0", |b| { + b.iter(|| { + Frame::::new_with_padding( + black_box(640), + black_box(480), + black_box(ChromaSampling::Cs420), + black_box(24), + ) + }) + }); +} + +fn plane(c: &mut Criterion) { + c.bench_function("plane new padding=0", |b| { + b.iter(|| { + Plane::::new( + black_box(640), + black_box(480), + black_box(1), + black_box(1), + black_box(0), + black_box(0), + ) + }) + }); + + c.bench_function("plane new padding!=0", |b| { + b.iter(|| { + Plane::::new( + black_box(640), + black_box(480), + black_box(1), + black_box(1), + black_box(24), + black_box(24), + ) + }) + }); + + let p8b = Plane::::new( + black_box(640), + black_box(480), + black_box(1), + black_box(1), + black_box(0), + black_box(0), + ); + + // We need to use PerIteration because we modify the Plane every iteration + let batch_size = criterion::BatchSize::PerIteration; + + c.bench_function("plane clone", |b| b.iter(|| p8b.clone())); + + c.bench_function("plane pad", |b| { + b.iter_batched_ref( + || p8b.clone(), + |p| p.pad(black_box(680), black_box(520)), + batch_size, + ) + }); + + let data_8b: Vec = vec![2; 640 * 480]; + c.bench_function("plane copy_from_raw_u8 8-bit", |b| { + b.iter_batched_ref( + || p8b.clone(), + |p| p.copy_from_raw_u8(black_box(&data_8b), black_box(640), black_box(1)), + batch_size, + ) + }); + + let p10b = Plane::::new( + black_box(640), + black_box(480), + black_box(1), + black_box(1), + black_box(0), + black_box(0), + ); + let data_10b: Vec = vec![2; 640 * 480 * 2]; + c.bench_function("plane copy_from_raw_u8 10-bit", |b| { + b.iter_batched_ref( + || p10b.clone(), + |p| p.copy_from_raw_u8(black_box(&data_10b), black_box(640), black_box(2)), + batch_size, + ) + }); + + c.bench_function("plane downsampled", |b| { + b.iter(|| p8b.downsampled(black_box(320), black_box(240))) + }); + + c.bench_function("plane downscale", |b| b.iter(|| p8b.downscale::<2>())); + + // This may seem silly to benchmark, but there is some math in the iterator + // that has been known to hinder compiler optimizations + c.bench_function("plane rows_iter", |b| { + b.iter(|| { + p8b.rows_iter() + .map(|r| r.iter().map(|v| u8::cast_from(*v) as u64).sum::()) + .collect::>() + }) + }); +} + +criterion_group!(benches, frame, plane); +criterion_main!(benches); diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/clippy.toml clamav-1.4.6+dfsg/.cargo/vendor/v_frame/clippy.toml --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/clippy.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/clippy.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +msrv = "1.64" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/frame.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/frame.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/frame.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/frame.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,67 @@ +// Copyright (c) 2018-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use crate::math::*; +use crate::pixel::*; +use crate::plane::*; + +#[cfg(feature = "serialize")] +use serde::{Deserialize, Serialize}; + +/// Represents a raw video frame +#[derive(Debug, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] +pub struct Frame { + /// Planes constituting the frame. + pub planes: [Plane; 3], +} + +impl Frame { + /// Creates a new frame with the given parameters. + /// + /// Allocates data for the planes. + pub fn new_with_padding( + width: usize, + height: usize, + chroma_sampling: ChromaSampling, + luma_padding: usize, + ) -> Self { + let luma_width = width.align_power_of_two(3); + let luma_height = height.align_power_of_two(3); + + let (chroma_decimation_x, chroma_decimation_y) = + chroma_sampling.get_decimation().unwrap_or((0, 0)); + let (chroma_width, chroma_height) = + chroma_sampling.get_chroma_dimensions(luma_width, luma_height); + let chroma_padding_x = luma_padding >> chroma_decimation_x; + let chroma_padding_y = luma_padding >> chroma_decimation_y; + + Frame { + planes: [ + Plane::new(luma_width, luma_height, 0, 0, luma_padding, luma_padding), + Plane::new( + chroma_width, + chroma_height, + chroma_decimation_x, + chroma_decimation_y, + chroma_padding_x, + chroma_padding_y, + ), + Plane::new( + chroma_width, + chroma_height, + chroma_decimation_x, + chroma_decimation_y, + chroma_padding_x, + chroma_padding_y, + ), + ], + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,89 @@ +// Copyright (c) 2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +// Safety lints +#![deny(bare_trait_objects)] +#![deny(clippy::as_ptr_cast_mut)] +#![deny(clippy::large_stack_arrays)] +// Performance lints +#![warn(clippy::inefficient_to_string)] +#![warn(clippy::invalid_upcast_comparisons)] +#![warn(clippy::iter_with_drain)] +#![warn(clippy::linkedlist)] +#![warn(clippy::mutex_integer)] +#![warn(clippy::naive_bytecount)] +#![warn(clippy::needless_bitwise_bool)] +#![warn(clippy::needless_collect)] +#![warn(clippy::or_fun_call)] +#![warn(clippy::stable_sort_primitive)] +#![warn(clippy::suboptimal_flops)] +#![warn(clippy::trivial_regex)] +#![warn(clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::unnecessary_join)] +#![warn(clippy::unused_async)] +#![warn(clippy::zero_sized_map_values)] +// Correctness lints +#![deny(clippy::case_sensitive_file_extension_comparisons)] +#![deny(clippy::copy_iterator)] +#![deny(clippy::expl_impl_clone_on_copy)] +#![deny(clippy::float_cmp)] +#![warn(clippy::imprecise_flops)] +#![deny(clippy::manual_instant_elapsed)] +#![deny(clippy::mem_forget)] +#![deny(clippy::path_buf_push_overwrite)] +#![deny(clippy::same_functions_in_if_condition)] +#![deny(clippy::unchecked_duration_subtraction)] +#![deny(clippy::unicode_not_nfc)] +// Clarity/formatting lints +#![warn(clippy::checked_conversions)] +#![warn(clippy::derive_partial_eq_without_eq)] +#![allow(clippy::enum_variant_names)] +#![warn(clippy::explicit_deref_methods)] +#![warn(clippy::filter_map_next)] +#![warn(clippy::flat_map_option)] +#![warn(clippy::fn_params_excessive_bools)] +#![warn(clippy::implicit_clone)] +#![warn(clippy::iter_not_returning_iterator)] +#![warn(clippy::iter_on_empty_collections)] +#![warn(clippy::macro_use_imports)] +#![warn(clippy::manual_clamp)] +#![warn(clippy::manual_let_else)] +#![warn(clippy::manual_ok_or)] +#![warn(clippy::manual_string_new)] +#![warn(clippy::map_flatten)] +#![warn(clippy::match_bool)] +#![warn(clippy::mut_mut)] +#![warn(clippy::needless_borrow)] +#![warn(clippy::needless_continue)] +#![warn(clippy::range_minus_one)] +#![warn(clippy::range_plus_one)] +#![warn(clippy::ref_binding_to_reference)] +#![warn(clippy::ref_option_ref)] +#![warn(clippy::trait_duplication_in_bounds)] +#![warn(clippy::unused_peekable)] +#![warn(clippy::unused_rounding)] +#![warn(clippy::unused_self)] +#![allow(clippy::upper_case_acronyms)] +#![warn(clippy::verbose_bit_mask)] +#![warn(clippy::verbose_file_reads)] +// Documentation lints +#![warn(clippy::doc_link_with_quotes)] +#![warn(clippy::doc_markdown)] +#![warn(clippy::missing_errors_doc)] +#![warn(clippy::missing_panics_doc)] + +pub mod frame; +pub mod math; +pub mod pixel; +pub mod plane; + +pub mod prelude { + pub use crate::math::*; + pub use crate::pixel::*; +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/math.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/math.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/math.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/math.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,136 @@ +// Copyright (c) 2017-2020, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use num_traits::PrimInt; +use std::mem::size_of; + +pub trait Fixed { + fn floor_log2(&self, n: usize) -> usize; + fn ceil_log2(&self, n: usize) -> usize; + fn align_power_of_two(&self, n: usize) -> usize; + fn align_power_of_two_and_shift(&self, n: usize) -> usize; +} + +impl Fixed for usize { + #[inline] + fn floor_log2(&self, n: usize) -> usize { + self & !((1 << n) - 1) + } + #[inline] + fn ceil_log2(&self, n: usize) -> usize { + (self + (1 << n) - 1).floor_log2(n) + } + #[inline] + fn align_power_of_two(&self, n: usize) -> usize { + self.ceil_log2(n) + } + #[inline] + fn align_power_of_two_and_shift(&self, n: usize) -> usize { + (self + (1 << n) - 1) >> n + } +} + +pub fn clamp(input: T, min: T, max: T) -> T { + if input < min { + min + } else if input > max { + max + } else { + input + } +} + +pub trait ILog: PrimInt { + // Integer binary logarithm of an integer value. + // Returns floor(log2(self)) + 1, or 0 if self == 0. + // This is the number of bits that would be required to represent self in two's + // complement notation with all of the leading zeros stripped. + // TODO: Mark const once trait functions can be constant + fn ilog(self) -> usize { + size_of::() * 8 - self.leading_zeros() as usize + } +} + +impl ILog for T where T: PrimInt {} + +#[inline(always)] +pub fn msb(x: i32) -> i32 { + debug_assert!(x > 0); + 31 ^ (x.leading_zeros() as i32) +} + +#[inline(always)] +pub const fn round_shift(value: i32, bit: usize) -> i32 { + (value + (1 << bit >> 1)) >> bit +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_floor_log2() { + assert_eq!(123usize.floor_log2(4), 112); + assert_eq!(16usize.floor_log2(4), 16); + assert_eq!(0usize.floor_log2(4), 0); + } + + #[test] + fn test_ceil_log2() { + assert_eq!(123usize.ceil_log2(4), 128); + assert_eq!(16usize.ceil_log2(4), 16); + assert_eq!(0usize.ceil_log2(4), 0); + } + + #[test] + fn test_align_power_of_two() { + assert_eq!(123usize.align_power_of_two(4), 128); + assert_eq!(16usize.align_power_of_two(4), 16); + assert_eq!(0usize.align_power_of_two(4), 0); + } + + #[test] + fn test_align_power_of_two_and_shift() { + assert_eq!(123usize.align_power_of_two_and_shift(4), 8); + assert_eq!(16usize.align_power_of_two_and_shift(4), 1); + assert_eq!(0usize.align_power_of_two_and_shift(4), 0); + } + + #[test] + fn test_clamp() { + assert_eq!(clamp(5, 0, 10), 5); + assert_eq!(clamp(-1, 0, 10), 0); + assert_eq!(clamp(11, 0, 10), 10); + } + + #[test] + fn test_ilog() { + assert_eq!(ILog::ilog(0i32), 0); + assert_eq!(ILog::ilog(1i32), 1); + assert_eq!(ILog::ilog(2i32), 2); + assert_eq!(ILog::ilog(3i32), 2); + assert_eq!(ILog::ilog(4i32), 3); + } + + #[test] + fn test_msb() { + assert_eq!(msb(1), 0); + assert_eq!(msb(2), 1); + assert_eq!(msb(3), 1); + assert_eq!(msb(4), 2); + } + + #[test] + fn test_round_shift() { + assert_eq!(round_shift(7, 2), 2); + assert_eq!(round_shift(8, 2), 2); + assert_eq!(round_shift(9, 2), 2); + assert_eq!(round_shift(10, 2), 3); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/pixel.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/pixel.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/pixel.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/pixel.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,316 @@ +// Copyright (c) 2017-2021, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +#[cfg(feature = "serialize")] +use serde::{Deserialize, Serialize}; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +use wasm_bindgen::prelude::*; + +use num_traits::{AsPrimitive, FromPrimitive, PrimInt, Signed}; + +use std::fmt; +use std::fmt::{Debug, Display}; +use std::mem::size_of; +use std::ops::AddAssign; + +/// Trait for casting between primitive types. +pub trait CastFromPrimitive: Copy + 'static { + /// Casts the given value into `Self`. + fn cast_from(v: T) -> Self; +} + +macro_rules! impl_cast_from_primitive { + ( $T:ty => $U:ty ) => { + impl CastFromPrimitive<$U> for $T { + #[inline(always)] + fn cast_from(v: $U) -> Self { v as Self } + } + }; + ( $T:ty => { $( $U:ty ),* } ) => { + $( impl_cast_from_primitive!($T => $U); )* + }; +} + +// casts to { u8, u16 } are implemented separately using Pixel, so that the +// compiler understands that CastFromPrimitive is always implemented +impl_cast_from_primitive!(u8 => { u32, u64, usize }); +impl_cast_from_primitive!(u8 => { i8, i64, isize }); +impl_cast_from_primitive!(u16 => { u32, u64, usize }); +impl_cast_from_primitive!(u16 => { i8, i64, isize }); +impl_cast_from_primitive!(i16 => { u32, u64, usize }); +impl_cast_from_primitive!(i16 => { i8, i64, isize }); +impl_cast_from_primitive!(i32 => { u32, u64, usize }); +impl_cast_from_primitive!(i32 => { i8, i64, isize }); + +pub trait RegisteredPrimitive: + PrimInt + + AsPrimitive + + AsPrimitive + + AsPrimitive + + AsPrimitive + + AsPrimitive + + AsPrimitive + + CastFromPrimitive + + CastFromPrimitive + + CastFromPrimitive + + CastFromPrimitive + + CastFromPrimitive + + CastFromPrimitive +{ +} + +impl RegisteredPrimitive for u8 {} +impl RegisteredPrimitive for u16 {} +impl RegisteredPrimitive for i16 {} +impl RegisteredPrimitive for i32 {} + +macro_rules! impl_cast_from_pixel_to_primitive { + ( $T:ty ) => { + impl CastFromPrimitive for $T { + #[inline(always)] + fn cast_from(v: T) -> Self { + v.as_() + } + } + }; +} + +impl_cast_from_pixel_to_primitive!(u8); +impl_cast_from_pixel_to_primitive!(i16); +impl_cast_from_pixel_to_primitive!(u16); +impl_cast_from_pixel_to_primitive!(i32); +impl_cast_from_pixel_to_primitive!(u32); + +/// Types that can be used as pixel types. +#[derive(PartialEq, Eq)] +pub enum PixelType { + /// 8 bits per pixel, stored in a `u8`. + U8, + /// 10 or 12 bits per pixel, stored in a `u16`. + U16, +} + +/// A type that can be used as a pixel type. +pub trait Pixel: + RegisteredPrimitive + Into + Into + Debug + Display + Send + Sync + 'static +{ + type Coeff: Coefficient; + + /// Returns a [`PixelType`] variant corresponding to this type. + /// + /// [`PixelType`]: enum.PixelType.html + fn type_enum() -> PixelType; + + /// Converts stride in pixels to stride in bytes. + #[inline] + fn to_asm_stride(in_stride: usize) -> isize { + (in_stride * size_of::()) as isize + } +} + +impl Pixel for u8 { + type Coeff = i16; + + #[inline] + fn type_enum() -> PixelType { + PixelType::U8 + } +} + +impl Pixel for u16 { + type Coeff = i32; + + #[inline] + fn type_enum() -> PixelType { + PixelType::U16 + } +} + +pub trait Coefficient: + RegisteredPrimitive + Into + AddAssign + Signed + Debug + 'static +{ + type Pixel: Pixel; +} + +impl Coefficient for i16 { + type Pixel = u8; +} +impl Coefficient for i32 { + type Pixel = u16; +} + +/// Chroma subsampling format +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] +#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen)] +#[repr(C)] +pub enum ChromaSampling { + /// Both vertically and horizontally subsampled. + #[default] + Cs420, + /// Horizontally subsampled. + Cs422, + /// Not subsampled. + Cs444, + /// Monochrome. + Cs400, +} + +impl FromPrimitive for ChromaSampling { + fn from_i64(n: i64) -> Option { + use ChromaSampling::*; + + match n { + n if n == Cs420 as i64 => Some(Cs420), + n if n == Cs422 as i64 => Some(Cs422), + n if n == Cs444 as i64 => Some(Cs444), + n if n == Cs400 as i64 => Some(Cs400), + _ => None, + } + } + + fn from_u64(n: u64) -> Option { + ChromaSampling::from_i64(n as i64) + } +} + +impl fmt::Display for ChromaSampling { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{}", + match self { + ChromaSampling::Cs420 => "4:2:0", + ChromaSampling::Cs422 => "4:2:2", + ChromaSampling::Cs444 => "4:4:4", + ChromaSampling::Cs400 => "Monochrome", + } + ) + } +} + +impl ChromaSampling { + /// Provides the amount to right shift the luma plane dimensions to get the + /// chroma plane dimensions. + /// Only values 0 or 1 are ever returned. + /// The plane dimensions must also be rounded up to accommodate odd luma plane + /// sizes. + /// Cs400 returns None, as there are no chroma planes. + pub const fn get_decimation(self) -> Option<(usize, usize)> { + use self::ChromaSampling::*; + match self { + Cs420 => Some((1, 1)), + Cs422 => Some((1, 0)), + Cs444 => Some((0, 0)), + Cs400 => None, + } + } + + /// Calculates the size of a chroma plane for this sampling type, given the luma plane dimensions. + pub const fn get_chroma_dimensions( + self, + luma_width: usize, + luma_height: usize, + ) -> (usize, usize) { + if let Some((ss_x, ss_y)) = self.get_decimation() { + ((luma_width + ss_x) >> ss_x, (luma_height + ss_y) >> ss_y) + } else { + (0, 0) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + use wasm_bindgen_test::*; + + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + wasm_bindgen_test_configure!(run_in_browser); + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn asm_stride() { + let tests = [(7, 7, 14), (12, 12, 24), (1234, 1234, 2468)]; + + for (in_stride, u8_bytes, u16_bytes) in tests { + assert_eq!(u8::to_asm_stride(in_stride), u8_bytes); + assert_eq!(u16::to_asm_stride(in_stride), u16_bytes); + } + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn type_enum() { + assert!(u8::type_enum() == PixelType::U8); + assert!(u16::type_enum() == PixelType::U16); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn chroma_sampling_from_int() { + let expected = [ + (-1, None), + (0, Some(ChromaSampling::Cs420)), + (1, Some(ChromaSampling::Cs422)), + (2, Some(ChromaSampling::Cs444)), + (3, Some(ChromaSampling::Cs400)), + (4, None), + ]; + + for (int, chroma_sampling) in expected { + let converted = ChromaSampling::from_i32(int); + assert_eq!(chroma_sampling, converted); + + let converted_uint = ChromaSampling::from_u32(int as u32); + assert_eq!(chroma_sampling, converted_uint); + } + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn display_chroma_sampling() { + use std::fmt::Write; + + let all_cs = [ + (ChromaSampling::Cs420, "4:2:0"), + (ChromaSampling::Cs422, "4:2:2"), + (ChromaSampling::Cs444, "4:4:4"), + (ChromaSampling::Cs400, "Monochrome"), + ]; + + for (cs, expected) in all_cs { + let mut s = String::new(); + write!(&mut s, "{cs}").expect("can display"); + assert_eq!(&s, expected); + } + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn chroma_sampling_dimensions() { + let tests = [ + ((1024, 768), ChromaSampling::Cs444, (1024, 768)), + ((1024, 768), ChromaSampling::Cs422, (512, 768)), + ((1024, 768), ChromaSampling::Cs420, (512, 384)), + ((1024, 768), ChromaSampling::Cs400, (0, 0)), + // Check odd width/height + ((1023, 768), ChromaSampling::Cs422, (512, 768)), + ((1023, 767), ChromaSampling::Cs420, (512, 384)), + ]; + + for (luma, cs, expected_chroma) in tests { + let chroma = cs.get_chroma_dimensions(luma.0, luma.1); + assert_eq!(chroma, expected_chroma); + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/plane.rs clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/plane.rs --- clamav-1.4.3+dfsg/.cargo/vendor/v_frame/src/plane.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/v_frame/src/plane.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1243 @@ +// Copyright (c) 2017-2021, The rav1e contributors. All rights reserved +// +// This source code is subject to the terms of the BSD 2 Clause License and +// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +// was not distributed with this source code in the LICENSE file, you can +// obtain it at www.aomedia.org/license/software. If the Alliance for Open +// Media Patent License 1.0 was not distributed with this source code in the +// PATENTS file, you can obtain it at www.aomedia.org/license/patent. + +use std::fmt::{Debug, Display, Formatter}; +use std::iter::{self, FusedIterator}; +use std::marker::PhantomData; +use std::mem::size_of; +use std::ops::{Index, IndexMut, Range}; + +use aligned_vec::{ABox, AVec, ConstAlign}; + +use crate::math::*; +use crate::pixel::*; + +#[cfg(feature = "serialize")] +use serde::{Deserialize, Serialize}; + +/// Plane-specific configuration. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] +pub struct PlaneConfig { + /// Data stride. + pub stride: usize, + /// Allocated height in pixels. + pub alloc_height: usize, + /// Width in pixels. + pub width: usize, + /// Height in pixels. + pub height: usize, + /// Decimator along the X axis. + /// + /// For example, for chroma planes in a 4:2:0 configuration this would be 1. + pub xdec: usize, + /// Decimator along the Y axis. + /// + /// For example, for chroma planes in a 4:2:0 configuration this would be 1. + pub ydec: usize, + /// Number of padding pixels on the right. + pub xpad: usize, + /// Number of padding pixels on the bottom. + pub ypad: usize, + /// X where the data starts. + pub xorigin: usize, + /// Y where the data starts. + pub yorigin: usize, +} + +impl PlaneConfig { + /// Stride alignment in bytes. + const STRIDE_ALIGNMENT_LOG2: usize = 6; + + #[inline] + pub fn new( + width: usize, + height: usize, + xdec: usize, + ydec: usize, + xpad: usize, + ypad: usize, + type_size: usize, + ) -> Self { + let xorigin = xpad.align_power_of_two(Self::STRIDE_ALIGNMENT_LOG2 + 1 - type_size); + let yorigin = ypad; + let stride = (xorigin + width + xpad) + .align_power_of_two(Self::STRIDE_ALIGNMENT_LOG2 + 1 - type_size); + let alloc_height = yorigin + height + ypad; + + PlaneConfig { + stride, + alloc_height, + width, + height, + xdec, + ydec, + xpad, + ypad, + xorigin, + yorigin, + } + } +} + +/// Absolute offset in pixels inside a plane +#[derive(Clone, Copy, Debug, Default)] +pub struct PlaneOffset { + pub x: isize, + pub y: isize, +} + +/// Backing buffer for the Plane data +/// +/// The buffer is padded and aligned according to the architecture-specific +/// SIMD constraints. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] +pub struct PlaneData { + #[cfg(not(target_arch = "wasm32"))] + data: ABox<[T], ConstAlign<{ 1 << 6 }>>, + #[cfg(target_arch = "wasm32")] + data: ABox<[T], ConstAlign<{ 1 << 3 }>>, +} + +unsafe impl Send for PlaneData {} +unsafe impl Sync for PlaneData {} + +impl std::ops::Deref for PlaneData { + type Target = [T]; + + fn deref(&self) -> &[T] { + self.data.as_ref() + } +} + +impl std::ops::DerefMut for PlaneData { + fn deref_mut(&mut self) -> &mut [T] { + self.data.as_mut() + } +} + +impl PlaneData { + #[cfg(target_arch = "wasm32")] + // FIXME: wasm32 allocator fails for alignment larger than 3 + const DATA_ALIGNMENT: usize = 1 << 3; + #[cfg(not(target_arch = "wasm32"))] + const DATA_ALIGNMENT: usize = 1 << 6; + + pub fn new(len: usize) -> Self { + Self { + data: AVec::from_iter( + Self::DATA_ALIGNMENT, + iter::repeat(T::cast_from(128)).take(len), + ) + .into_boxed_slice(), + } + } + + fn from_slice(data: &[T]) -> Self { + Self { + data: AVec::from_slice(Self::DATA_ALIGNMENT, data).into_boxed_slice(), + } + } +} + +/// One data plane of a frame. +/// +/// For example, a plane can be a Y luma plane or a U or V chroma plane. +#[derive(Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] +pub struct Plane { + // TODO: it is used by encoder to copy by plane and by tiling, make it + // private again once tiling is moved and a copy_plane fn is added. + // + pub data: PlaneData, + /// Plane configuration. + pub cfg: PlaneConfig, +} + +impl Debug for Plane +where + T: Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Plane {{ data: [{}, ...], cfg: {:?} }}", + self.data[0], self.cfg + ) + } +} + +impl Plane { + /// Allocates and returns a new plane. + pub fn new( + width: usize, + height: usize, + xdec: usize, + ydec: usize, + xpad: usize, + ypad: usize, + ) -> Self { + let cfg = PlaneConfig::new(width, height, xdec, ydec, xpad, ypad, size_of::()); + let data = PlaneData::new(cfg.stride * cfg.alloc_height); + + Plane { data, cfg } + } + + /// # Panics + /// + /// - If `len` is not a multiple of `stride` + pub fn from_slice(data: &[T], stride: usize) -> Self { + let len = data.len(); + + assert!(len % stride == 0); + + Self { + data: PlaneData::from_slice(data), + cfg: PlaneConfig { + stride, + alloc_height: len / stride, + width: stride, + height: len / stride, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 0, + yorigin: 0, + }, + } + } + + pub fn pad(&mut self, w: usize, h: usize) { + let xorigin = self.cfg.xorigin; + let yorigin = self.cfg.yorigin; + let stride = self.cfg.stride; + let alloc_height = self.cfg.alloc_height; + let width = (w + self.cfg.xdec) >> self.cfg.xdec; + let height = (h + self.cfg.ydec) >> self.cfg.ydec; + + if xorigin > 0 { + for y in 0..height { + let base = (yorigin + y) * stride; + let fill_val = self.data[base + xorigin]; + for val in &mut self.data[base..base + xorigin] { + *val = fill_val; + } + } + } + + if xorigin + width < stride { + for y in 0..height { + let base = (yorigin + y) * stride + xorigin + width; + let fill_val = self.data[base - 1]; + for val in &mut self.data[base..base + stride - (xorigin + width)] { + *val = fill_val; + } + } + } + + if yorigin > 0 { + let (top, bottom) = self.data.split_at_mut(yorigin * stride); + let src = &bottom[..stride]; + for y in 0..yorigin { + let dst = &mut top[y * stride..(y + 1) * stride]; + dst.copy_from_slice(src); + } + } + + if yorigin + height < self.cfg.alloc_height { + let (top, bottom) = self.data.split_at_mut((yorigin + height) * stride); + let src = &top[(yorigin + height - 1) * stride..]; + for y in 0..alloc_height - (yorigin + height) { + let dst = &mut bottom[y * stride..(y + 1) * stride]; + dst.copy_from_slice(src); + } + } + } + + /// Minimally test that the plane has been padded. + pub fn probe_padding(&self, w: usize, h: usize) -> bool { + let PlaneConfig { + xorigin, + yorigin, + stride, + alloc_height, + xdec, + ydec, + .. + } = self.cfg; + let width = (w + xdec) >> xdec; + let height = (h + ydec) >> ydec; + let corner = (yorigin + height - 1) * stride + xorigin + width - 1; + let corner_value = self.data[corner]; + + self.data[(yorigin + height) * stride - 1] == corner_value + && self.data[(alloc_height - 1) * stride + xorigin + width - 1] == corner_value + && self.data[alloc_height * stride - 1] == corner_value + } + + pub fn slice(&self, po: PlaneOffset) -> PlaneSlice<'_, T> { + PlaneSlice { + plane: self, + x: po.x, + y: po.y, + } + } + + pub fn mut_slice(&mut self, po: PlaneOffset) -> PlaneMutSlice<'_, T> { + PlaneMutSlice { + plane: self, + x: po.x, + y: po.y, + } + } + + #[inline] + fn index(&self, x: usize, y: usize) -> usize { + (y + self.cfg.yorigin) * self.cfg.stride + (x + self.cfg.xorigin) + } + + /// This version of the function crops off the padding on the right side of the image + #[inline] + pub fn row_range_cropped(&self, x: isize, y: isize) -> Range { + debug_assert!(self.cfg.yorigin as isize + y >= 0); + debug_assert!(self.cfg.xorigin as isize + x >= 0); + let base_y = (self.cfg.yorigin as isize + y) as usize; + let base_x = (self.cfg.xorigin as isize + x) as usize; + let base = base_y * self.cfg.stride + base_x; + let width = (self.cfg.width as isize - x) as usize; + base..base + width + } + + /// This version of the function includes the padding on the right side of the image + #[inline] + pub fn row_range(&self, x: isize, y: isize) -> Range { + debug_assert!(self.cfg.yorigin as isize + y >= 0); + debug_assert!(self.cfg.xorigin as isize + x >= 0); + let base_y = (self.cfg.yorigin as isize + y) as usize; + let base_x = (self.cfg.xorigin as isize + x) as usize; + let base = base_y * self.cfg.stride + base_x; + let width = self.cfg.stride - base_x; + base..base + width + } + + /// Returns the pixel at the given coordinates. + pub fn p(&self, x: usize, y: usize) -> T { + self.data[self.index(x, y)] + } + + /// Returns plane data starting from the origin. + pub fn data_origin(&self) -> &[T] { + &self.data[self.index(0, 0)..] + } + + /// Returns mutable plane data starting from the origin. + pub fn data_origin_mut(&mut self) -> &mut [T] { + let i = self.index(0, 0); + &mut self.data[i..] + } + + /// Copies data into the plane from a pixel array. + /// + /// # Panics + /// + /// - If `source_bytewidth` does not match the generic `T` of `Plane` + pub fn copy_from_raw_u8( + &mut self, + source: &[u8], + source_stride: usize, + source_bytewidth: usize, + ) { + let stride = self.cfg.stride; + + assert!(stride != 0); + assert!(source_stride != 0); + + for (self_row, source_row) in self + .data_origin_mut() + .chunks_exact_mut(stride) + .zip(source.chunks_exact(source_stride)) + { + match source_bytewidth { + 1 => { + for (self_pixel, source_pixel) in self_row.iter_mut().zip(source_row.iter()) { + *self_pixel = T::cast_from(*source_pixel); + } + } + 2 => { + assert!( + size_of::() == 2, + "source bytewidth ({}) cannot fit in Plane", + source_bytewidth + ); + + debug_assert!(T::type_enum() == PixelType::U16); + + // SAFETY: because of the assert it is safe to assume that T == u16 + let self_row: &mut [u16] = unsafe { std::mem::transmute(self_row) }; + // SAFETY: we reinterpret the slice of bytes as a slice of elements of + // [u8; 2] to allow for more efficient codegen with from_le_bytes + let source_row: &[[u8; 2]] = unsafe { + std::slice::from_raw_parts(source_row.as_ptr().cast(), source_row.len() / 2) + }; + + for (self_pixel, bytes) in self_row.iter_mut().zip(source_row) { + *self_pixel = u16::from_le_bytes(*bytes); + } + } + + _ => {} + } + } + } + + /// Copies data from a plane into a pixel array. + /// + /// # Panics + /// + /// - If `dest_bytewidth` does not match the generic `T` of `Plane` + pub fn copy_to_raw_u8(&self, dest: &mut [u8], dest_stride: usize, dest_bytewidth: usize) { + let stride = self.cfg.stride; + for (self_row, dest_row) in self + .data_origin() + .chunks_exact(stride) + .zip(dest.chunks_exact_mut(dest_stride)) + { + match dest_bytewidth { + 1 => { + for (self_pixel, dest_pixel) in + self_row[..self.cfg.width].iter().zip(dest_row.iter_mut()) + { + *dest_pixel = u8::cast_from(*self_pixel); + } + } + 2 => { + assert!( + size_of::() >= 2, + "dest bytewidth ({}) cannot fit in Plane", + dest_bytewidth + ); + + // SAFETY: we reinterpret the slice of bytes as a slice + // of [u8; 2] with half the elements + let dest_row: &mut [[u8; 2]] = unsafe { + std::slice::from_raw_parts_mut( + dest_row.as_mut_ptr().cast(), + dest_row.len() / 2, + ) + }; + + for (self_pixel, bytes) in self_row[..self.cfg.width].iter().zip(dest_row) { + *bytes = u16::cast_from(*self_pixel).to_le_bytes(); + } + } + + _ => {} + } + } + } + + /// Returns plane with half the resolution for width and height. + /// Downscaled with 2x2 box filter. + /// Padded to dimensions with `frame_width` and `frame_height`. + /// + /// # Panics + /// + /// - If the requested width and height are > half the input width or height + pub fn downsampled(&self, frame_width: usize, frame_height: usize) -> Plane { + let src = self; + let mut new = Plane::new( + (src.cfg.width + 1) / 2, + (src.cfg.height + 1) / 2, + src.cfg.xdec + 1, + src.cfg.ydec + 1, + src.cfg.xpad / 2, + src.cfg.ypad / 2, + ); + + let width = new.cfg.width; + let height = new.cfg.height; + + assert!(width * 2 <= src.cfg.stride - src.cfg.xorigin); + assert!(height * 2 <= src.cfg.alloc_height - src.cfg.yorigin); + + let data_origin = src.data_origin(); + for (row_idx, dst_row) in new + .mut_slice(PlaneOffset::default()) + .rows_iter_mut() + .enumerate() + .take(height) + { + let src_top_row = &data_origin[(src.cfg.stride * row_idx * 2)..][..(2 * width)]; + let src_bottom_row = + &data_origin[(src.cfg.stride * (row_idx * 2 + 1))..][..(2 * width)]; + + for ((dst, a), b) in dst_row + .iter_mut() + .zip(src_top_row.chunks_exact(2)) + .zip(src_bottom_row.chunks_exact(2)) + { + let sum = u32::cast_from(a[0]) + + u32::cast_from(a[1]) + + u32::cast_from(b[0]) + + u32::cast_from(b[1]); + let avg = (sum + 2) >> 2; + *dst = T::cast_from(avg); + } + } + + new.pad(frame_width, frame_height); + new + } + + /// Returns a plane downscaled from the source plane by a factor of `scale` (not padded) + pub fn downscale(&self) -> Plane { + let mut new_plane = Plane::new(self.cfg.width / SCALE, self.cfg.height / SCALE, 0, 0, 0, 0); + + self.downscale_in_place::(&mut new_plane); + + new_plane + } + + /// Downscales the source plane by a factor of `scale`, writing the result to `in_plane` (not padded) + /// + /// # Panics + /// + /// - If the current plane's width and height are not at least `SCALE` times the `in_plane`'s + #[cfg_attr(feature = "profiling", profiling::function(downscale_in_place))] + pub fn downscale_in_place(&self, in_plane: &mut Plane) { + let stride = in_plane.cfg.stride; + let width = in_plane.cfg.width; + let height = in_plane.cfg.height; + + if stride == 0 || self.cfg.stride == 0 { + panic!("stride cannot be 0"); + } + + assert!(width * SCALE <= self.cfg.stride - self.cfg.xorigin); + assert!(height * SCALE <= self.cfg.alloc_height - self.cfg.yorigin); + + // SAFETY: Bounds checks have been removed for performance reasons + unsafe { + let src = self; + let box_pixels = SCALE * SCALE; + let half_box_pixels = box_pixels as u32 / 2; // Used for rounding int division + + let data_origin = src.data_origin(); + let plane_data_mut_slice = &mut *in_plane.data; + + // Iter dst rows + for row_idx in 0..height { + let dst_row = plane_data_mut_slice.get_unchecked_mut(row_idx * stride..); + // Iter dst cols + for (col_idx, dst) in dst_row.get_unchecked_mut(..width).iter_mut().enumerate() { + macro_rules! generate_inner_loop { + ($x:ty) => { + let mut sum = half_box_pixels as $x; + // Sum box of size scale * scale + + // Iter src row + for y in 0..SCALE { + let src_row_idx = row_idx * SCALE + y; + let src_row = + data_origin.get_unchecked((src_row_idx * src.cfg.stride)..); + + // Iter src col + for x in 0..SCALE { + let src_col_idx = col_idx * SCALE + x; + sum += <$x>::cast_from(*src_row.get_unchecked(src_col_idx)); + } + } + + // Box average + let avg = sum as usize / box_pixels; + *dst = T::cast_from(avg); + }; + } + + // Use 16 bit precision if overflow would not happen + if T::type_enum() == PixelType::U8 + && SCALE as u128 * SCALE as u128 * (u8::MAX as u128) + + half_box_pixels as u128 + <= u16::MAX as u128 + { + generate_inner_loop!(u16); + } else { + generate_inner_loop!(u32); + } + } + } + } + } + + /// Iterates over the pixels in the plane, skipping the padding. + pub fn iter(&self) -> PlaneIter<'_, T> { + PlaneIter::new(self) + } + + /// Iterates over the lines of the plane + pub fn rows_iter(&self) -> RowsIter<'_, T> { + RowsIter { + plane: self, + x: 0, + y: 0, + } + } + + pub fn rows_iter_mut(&mut self) -> RowsIterMut<'_, T> { + RowsIterMut { + plane: self as *mut Plane, + x: 0, + y: 0, + phantom: PhantomData, + } + } + + /// Return a line + pub fn row(&self, y: isize) -> &[T] { + let range = self.row_range(0, y); + + &self.data[range] + } +} + +/// Iterator over plane pixels, skipping padding. +#[derive(Debug)] +pub struct PlaneIter<'a, T: Pixel> { + plane: &'a Plane, + y: usize, + x: usize, +} + +impl<'a, T: Pixel> PlaneIter<'a, T> { + /// Creates a new iterator. + pub fn new(plane: &'a Plane) -> Self { + Self { plane, y: 0, x: 0 } + } + + fn width(&self) -> usize { + self.plane.cfg.width + } + + fn height(&self) -> usize { + self.plane.cfg.height + } +} + +impl Iterator for PlaneIter<'_, T> { + type Item = T; + + fn next(&mut self) -> Option<::Item> { + if self.y == self.height() { + return None; + } + let pixel = self.plane.p(self.x, self.y); + if self.x == self.width() - 1 { + self.x = 0; + self.y += 1; + } else { + self.x += 1; + } + Some(pixel) + } +} + +impl FusedIterator for PlaneIter<'_, T> {} + +// A Plane, PlaneSlice, or PlaneRegion is assumed to include or be able to include +// padding on the edge of the frame +#[derive(Clone, Copy, Debug)] +pub struct PlaneSlice<'a, T: Pixel> { + pub plane: &'a Plane, + pub x: isize, + pub y: isize, +} + +// A RowsIter or RowsIterMut is assumed to crop the padding from the frame edges +pub struct RowsIter<'a, T: Pixel> { + plane: &'a Plane, + x: isize, + y: isize, +} + +impl<'a, T: Pixel> Iterator for RowsIter<'a, T> { + type Item = &'a [T]; + + fn next(&mut self) -> Option { + if self.plane.cfg.height as isize > self.y { + // cannot directly return self.ps.row(row) due to lifetime issue + let range = self.plane.row_range_cropped(self.x, self.y); + self.y += 1; + Some(&self.plane.data[range]) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.plane.cfg.height as isize - self.y; + debug_assert!(remaining >= 0); + let remaining = remaining as usize; + + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for RowsIter<'_, T> {} +impl FusedIterator for RowsIter<'_, T> {} + +impl<'a, T: Pixel> PlaneSlice<'a, T> { + #[allow(unused)] + pub fn as_ptr(&self) -> *const T { + self[0].as_ptr() + } + + pub fn rows_iter(&self) -> RowsIter<'_, T> { + RowsIter { + plane: self.plane, + x: self.x, + y: self.y, + } + } + + pub fn clamp(&self) -> PlaneSlice<'a, T> { + PlaneSlice { + plane: self.plane, + x: self.x.clamp( + -(self.plane.cfg.xorigin as isize), + self.plane.cfg.width as isize, + ), + y: self.y.clamp( + -(self.plane.cfg.yorigin as isize), + self.plane.cfg.height as isize, + ), + } + } + + pub fn subslice(&self, xo: usize, yo: usize) -> PlaneSlice<'a, T> { + PlaneSlice { + plane: self.plane, + x: self.x + xo as isize, + y: self.y + yo as isize, + } + } + + pub fn reslice(&self, xo: isize, yo: isize) -> PlaneSlice<'a, T> { + PlaneSlice { + plane: self.plane, + x: self.x + xo, + y: self.y + yo, + } + } + + /// A slice starting i pixels above the current one. + pub fn go_up(&self, i: usize) -> PlaneSlice<'a, T> { + PlaneSlice { + plane: self.plane, + x: self.x, + y: self.y - i as isize, + } + } + + /// A slice starting i pixels to the left of the current one. + pub fn go_left(&self, i: usize) -> PlaneSlice<'a, T> { + PlaneSlice { + plane: self.plane, + x: self.x - i as isize, + y: self.y, + } + } + + pub fn p(&self, add_x: usize, add_y: usize) -> T { + let new_y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize; + let new_x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize; + self.plane.data[new_y * self.plane.cfg.stride + new_x] + } + + /// Checks if `add_y` and `add_x` lies in the allocated bounds of the + /// underlying plane. + pub fn accessible(&self, add_x: usize, add_y: usize) -> bool { + let y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize; + let x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize; + y < self.plane.cfg.alloc_height && x < self.plane.cfg.stride + } + + /// Checks if -`sub_x` and -`sub_y` lies in the allocated bounds of the + /// underlying plane. + pub fn accessible_neg(&self, sub_x: usize, sub_y: usize) -> bool { + let y = self.y - sub_y as isize + self.plane.cfg.yorigin as isize; + let x = self.x - sub_x as isize + self.plane.cfg.xorigin as isize; + y >= 0 && x >= 0 + } + + /// This version of the function crops off the padding on the right side of the image + pub fn row_cropped(&self, y: usize) -> &[T] { + let y = (self.y + y as isize + self.plane.cfg.yorigin as isize) as usize; + let x = (self.x + self.plane.cfg.xorigin as isize) as usize; + let start = y * self.plane.cfg.stride + x; + let width = (self.plane.cfg.width as isize - self.x) as usize; + &self.plane.data[start..start + width] + } + + /// This version of the function includes the padding on the right side of the image + pub fn row(&self, y: usize) -> &[T] { + let y = (self.y + y as isize + self.plane.cfg.yorigin as isize) as usize; + let x = (self.x + self.plane.cfg.xorigin as isize) as usize; + let start = y * self.plane.cfg.stride + x; + let width = self.plane.cfg.stride - x; + &self.plane.data[start..start + width] + } +} + +impl Index for PlaneSlice<'_, T> { + type Output = [T]; + fn index(&self, index: usize) -> &Self::Output { + let range = self.plane.row_range(self.x, self.y + index as isize); + &self.plane.data[range] + } +} + +pub struct PlaneMutSlice<'a, T: Pixel> { + pub plane: &'a mut Plane, + pub x: isize, + pub y: isize, +} + +pub struct RowsIterMut<'a, T: Pixel> { + plane: *mut Plane, + x: isize, + y: isize, + phantom: PhantomData<&'a mut Plane>, +} + +impl<'a, T: Pixel> Iterator for RowsIterMut<'a, T> { + type Item = &'a mut [T]; + + fn next(&mut self) -> Option { + // SAFETY: there could not be a concurrent call using a mutable reference to the plane + let plane = unsafe { &mut *self.plane }; + if plane.cfg.height as isize > self.y { + // cannot directly return self.ps.row(row) due to lifetime issue + let range = plane.row_range_cropped(self.x, self.y); + self.y += 1; + Some(&mut plane.data[range]) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + // SAFETY: there could not be a concurrent call using a mutable reference to the plane + let plane = unsafe { &mut *self.plane }; + let remaining = plane.cfg.height as isize - self.y; + debug_assert!(remaining >= 0); + let remaining = remaining as usize; + + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for RowsIterMut<'_, T> {} +impl FusedIterator for RowsIterMut<'_, T> {} + +impl PlaneMutSlice<'_, T> { + #[allow(unused)] + pub fn rows_iter(&self) -> RowsIter<'_, T> { + RowsIter { + plane: self.plane, + x: self.x, + y: self.y, + } + } + + pub fn rows_iter_mut(&mut self) -> RowsIterMut<'_, T> { + RowsIterMut { + plane: self.plane as *mut Plane, + x: self.x, + y: self.y, + phantom: PhantomData, + } + } + + #[allow(unused)] + pub fn subslice(&mut self, xo: usize, yo: usize) -> PlaneMutSlice<'_, T> { + PlaneMutSlice { + plane: self.plane, + x: self.x + xo as isize, + y: self.y + yo as isize, + } + } +} + +impl Index for PlaneMutSlice<'_, T> { + type Output = [T]; + fn index(&self, index: usize) -> &Self::Output { + let range = self.plane.row_range(self.x, self.y + index as isize); + &self.plane.data[range] + } +} + +impl IndexMut for PlaneMutSlice<'_, T> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let range = self.plane.row_range(self.x, self.y + index as isize); + &mut self.plane.data[range] + } +} + +#[cfg(test)] +pub mod test { + use super::*; + + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + use wasm_bindgen_test::*; + + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + wasm_bindgen_test_configure!(run_in_browser); + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn copy_from_raw_u8() { + #[rustfmt::skip] + let mut plane = Plane::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ], 8); + + let input = vec![42u8; 64]; + + plane.copy_from_raw_u8(&input, 8, 1); + + println!("{:?}", &plane.data[..10]); + + assert_eq!(&input[..64], &plane.data[..64]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn copy_to_raw_u8() { + #[rustfmt::skip] + let plane = Plane::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ], 8); + + let mut output = vec![42u8; 64]; + + plane.copy_to_raw_u8(&mut output, 8, 1); + + println!("{:?}", &plane.data[..10]); + + assert_eq!(&output[..64], &plane.data[..64]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_downsample() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 9, + width: 4, + height: 4, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 2, + yorigin: 3, + }, + }; + let downsampled = plane.downsampled(4, 4); + + #[rustfmt::skip] + let expected = &[ + 5, 5, + 6, 6, + ]; + + let v: Vec<_> = downsampled.iter().collect(); + + assert_eq!(&expected[..], &v[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_downsample_odd() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 9, + width: 3, + height: 3, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 2, + yorigin: 3, + }, + }; + let downsampled = plane.downsampled(3, 3); + + #[rustfmt::skip] + let expected = &[ + 5, 5, + 6, 6, + ]; + + let v: Vec<_> = downsampled.iter().collect(); + assert_eq!(&expected[..], &v[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_downscale() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 4, 5, 0, 0, + 0, 0, 2, 3, 6, 7, 0, 0, + 0, 0, 8, 9, 7, 5, 0, 0, + 0, 0, 9, 8, 3, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 9, + width: 4, + height: 4, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 2, + yorigin: 3, + }, + }; + let downscaled = plane.downscale::<2>(); + + #[rustfmt::skip] + let expected = &[ + 2, 6, + 9, 4 + ]; + + let v: Vec<_> = downscaled.iter().collect(); + assert_eq!(&expected[..], &v[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_downscale_odd() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 1, 2, 3, 4, 1, 2, 3, 4, + 0, 0, 8, 7, 6, 5, 8, 7, + 6, 5, 8, 7, 6, 5, 8, 7, + 6, 5, 8, 7, 0, 0, 2, 3, + 4, 5, 0, 0, 9, 8, 7, 6, + 0, 0, 0, 0, 2, 3, 4, 5, + 0, 0, 0, 0, 2, 3, 4, 5, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 7, + width: 8, + height: 7, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 0, + yorigin: 0, + }, + }; + + let downscaled = plane.downscale::<3>(); + + #[rustfmt::skip] + let expected = &[ + 4, 5, + 3, 3 + ]; + + let v: Vec<_> = downscaled.iter().collect(); + assert_eq!(&expected[..], &v[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_downscale_odd_2() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 9, 8, 3, 1, 0, 1, 4, 5, 0, 0, + 0, 1, 4, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 2, 3, 6, 7, 0, 0, 0, 0, 0, + 0, 0, 8, 9, 7, 5, 0, 0, 0, 0, + 9, 8, 3, 1, 0, 1, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 3, 6, 7, 0, + 0, 0, 0, 0, 0, 0, 8, 9, 7, 5, + 0, 0, 0, 0, 9, 8, 3, 1, 0, 0 + ]), + cfg: PlaneConfig { + stride: 10, + alloc_height: 10, + width: 10, + height: 10, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 0, + yorigin: 0, + }, + }; + let downscaled = plane.downscale::<3>(); + + #[rustfmt::skip] + let expected = &[ + 3, 1, 2, + 4, 4, 1, + 0, 0, 4, + ]; + + let v: Vec<_> = downscaled.iter().collect(); + assert_eq!(&expected[..], &v[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_plane_pad() { + #[rustfmt::skip] + let mut plane = Plane:: { + data: PlaneData::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 9, + width: 4, + height: 4, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 2, + yorigin: 3, + }, + }; + plane.pad(4, 4); + + #[rustfmt::skip] + assert_eq!(&[ + 1, 1, 1, 2, 3, 4, 4, 4, + 1, 1, 1, 2, 3, 4, 4, 4, + 1, 1, 1, 2, 3, 4, 4, 4, + 1, 1, 1, 2, 3, 4, 4, 4, + 8, 8, 8, 7, 6, 5, 5, 5, + 9, 9, 9, 8, 7, 6, 6, 6, + 2, 2, 2, 3, 4, 5, 5, 5, + 2, 2, 2, 3, 4, 5, 5, 5, + 2, 2, 2, 3, 4, 5, 5, 5, + ], &plane.data[..]); + } + + #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)] + #[test] + fn test_pixel_iterator() { + #[rustfmt::skip] + let plane = Plane:: { + data: PlaneData::from_slice(&[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 0, 0, + 0, 0, 8, 7, 6, 5, 0, 0, + 0, 0, 9, 8, 7, 6, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]), + cfg: PlaneConfig { + stride: 8, + alloc_height: 9, + width: 4, + height: 4, + xdec: 0, + ydec: 0, + xpad: 0, + ypad: 0, + xorigin: 2, + yorigin: 3, + }, + }; + + let pixels: Vec = plane.iter().collect(); + + assert_eq!( + &[1, 2, 3, 4, 8, 7, 6, 5, 9, 8, 7, 6, 2, 3, 4, 5,][..], + &pixels[..] + ); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/version_check/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/version_check/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo-checksum.json 2026-08-06 21:12:25.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"f25d88044914cb3466df43bc39a199e1589dda1aad3226c9c7e7ac4d2f8751d0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"b7e650f3fce5c53249d1cdc608b54df156a97edd636cf9d23498d0cfe7aec63e","README.md":"ac2a0a360812436bd5798f5fe2affe7d6ed9eb7f15d6e4d73931e95b437560f2","src/channel.rs":"d2443d503d4cc469a171a51a26eca3ec0d2a58b5f7375a84542c36f1421766a8","src/date.rs":"09580a0a2008fad2ccbc43fb42a88f42221b98b01692702022a296dc9c86bf37","src/lib.rs":"760f0d29567ecaa61287088cf23cf74b3c0efbbcd3077cea5fb7c88359e96c7e","src/version.rs":"dba18a25983ec6e37b952f4cdc5219c9e5abba2c3a76cef87465e1fba6f8ac89"},"package":"49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"ea958d0b652c03c60b2e7f23e9aaede6435411c474936cf9e93393b17ddd2096",".github/workflows/ci.yml":"0d3ec0059cdc483d7d6d2aaeac4958e95b1a03ad1652f42a38d44cbfac5dcbca",".travis.yml":"d504e08178faaa3a096b0e94981846e9cc0eaf1926c47ef28a4096ae084ddb39","Cargo.toml":"f25d88044914cb3466df43bc39a199e1589dda1aad3226c9c7e7ac4d2f8751d0","Cargo.toml.orig":"4d6cb51ddf5230afa84b884def590b3958e5002f79ac4aecf25a4fd226ce3afa","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"b7e650f3fce5c53249d1cdc608b54df156a97edd636cf9d23498d0cfe7aec63e","README.md":"ac2a0a360812436bd5798f5fe2affe7d6ed9eb7f15d6e4d73931e95b437560f2","src/channel.rs":"d2443d503d4cc469a171a51a26eca3ec0d2a58b5f7375a84542c36f1421766a8","src/date.rs":"09580a0a2008fad2ccbc43fb42a88f42221b98b01692702022a296dc9c86bf37","src/lib.rs":"760f0d29567ecaa61287088cf23cf74b3c0efbbcd3077cea5fb7c88359e96c7e","src/version.rs":"dba18a25983ec6e37b952f4cdc5219c9e5abba2c3a76cef87465e1fba6f8ac89"},"package":"49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/version_check/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/version_check/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/version_check/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "736b788c9c32c93b545cb084eac6f94f31f2872c" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/version_check/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/version_check/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/version_check/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/version_check/.github/workflows/ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,42 @@ +name: CI + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + name: "${{ matrix.os.name }} ${{ matrix.test.name }} (${{ matrix.toolchain }})" + + strategy: + matrix: + os: + - { name: Linux, distro: ubuntu-latest } + - { name: Windows, distro: windows-latest } + - { name: macOS, distro: macOS-latest } + toolchain: [nightly, beta, stable] + include: + - os: { name: Linux, distro: ubuntu-latest } + toolchain: 1.0.0 + + runs-on: ${{ matrix.os.distro }} + + steps: + - name: Checkout Sources + uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.toolchain }} + override: true + + - name: Run Tests + uses: actions-rs/cargo@v1 + env: + FORCE_STATIC: 1 + KNOWN_CHANNEL: ${{ matrix.toolchain }} + with: + command: test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/version_check/.travis.yml clamav-1.4.6+dfsg/.cargo/vendor/version_check/.travis.yml --- clamav-1.4.3+dfsg/.cargo/vendor/version_check/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/version_check/.travis.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,6 @@ +language: rust +rust: + - 1.0.0 + - stable + - beta + - nightly diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/version_check/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/version_check/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/version_check/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/version_check/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,13 @@ +[package] +name = "version_check" +version = "0.9.4" +authors = ["Sergio Benitez "] +description = "Tiny crate to check the version of the installed/running rustc." +documentation = "https://docs.rs/version_check/" +repository = "https://github.com/SergioBenitez/version_check" +readme = "README.md" +keywords = ["version", "rustc", "minimum", "check"] +license = "MIT/Apache-2.0" +exclude = ["static"] + +[dependencies] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo-checksum.json 2026-08-06 21:12:26.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"009488b807b23328fe46f6eef637e16f791a3bb01e494bcbfc27767fa4558e59","Cargo.lock":"f71a2db991e963e3d670e63af583f67808a5c8110dbc143ca43f9ea5561f3189","Cargo.toml":"e44ba1682361d605e5e5549b0ffc3bac73694c9d0b137f67209c657b30e29806","Cargo.toml.orig":"064c751923c59463e2587ee85890cac5eca5059714087d62a95151df23e2bdf6","README.md":"b768b011583d6c3f7d47c57de28f7dd9ade631b286753435ae1ae9acab6ce557","examples/cli-command-no_std.rs":"56f3f5d08affa4f2211cbdcdf4ec865981502aaa5cdccbffb0b2084736330430","examples/cli-command.rs":"1e84ceae7a33d9c9e9340651b086f155d138eeb9d375c6a1678e3d282f3b668a","examples/hello-world-no_std.rs":"a0b3581ea43e8a1588de8619dee70ddb48a2360e84ef7c9c21b9d6cfbe350dda","examples/hello-world.rs":"634b4999d89675ffad329eea3eb006fad935806895507e0c3e7d770681a9089d","examples/http-proxy-no_std.rs":"9969f8c9747739be697329c563e32c352961655c600eedafb2fac11589216443","examples/http-proxy.rs":"a31e4c31203860ab96da3ca176ca99db7b88ea513ca7a20cc8955a57794367bc","src/command.rs":"3a74ae964950195610dc1b3bd1d669bcd903c23888f7356d476f1dadb796ea9f","src/ext/mod.rs":"4bc79c71442ac6c55dc4f8a0632b6d6805c0c9c74b22b56791a483ae447dac0c","src/ext/std.rs":"c35fd8bdafd24a6adef4f5a27e8e4bb421b0e50cebfe350868ded43980b1a06e","src/imports.rs":"b29d63727fd01b43e723b6ad5c41f8902f66927ceae366181f4a267949490f6a","src/lib.rs":"2db558cb84747a1178155997ff55c4cf87972a9fd0fdb7f0ed1c04f1c97d9f47","src/proxy.rs":"639a98c734bf2f2ee363b9cdf16c5534fda7fc7c9373652ef681f24c472fdd43","wit/deps/cli/command.wit":"f729a20e99a4601f90677e31a16e63f24ee32eef062b9305e94419428c8ff70b","wit/deps/cli/environment.wit":"5e58cd47b162e9f004bc9224a29c2ec3cf9e1a3d4c910154ce53742f828af91f","wit/deps/cli/exit.wit":"a0fae6014751dc95f45b1dbe530b7f4db99d5bd607ed8bbf879b22a906f4514c","wit/deps/cli/imports.wit":"a576c17e15ece40fe29eaeb73f416d6f46ac639f512d51ad20bb915b4686a4dd","wit/deps/cli/run.wit":"a7df5376da8230e0509fffbb8355641af0765cc5cff8064bbe58fef1cbbe63c1","wit/deps/cli/stdio.wit":"bc6e5e55963d9c49b91d9880d8e50e44a718c5a7b7211bb8cb5d4fcd552b13a8","wit/deps/cli/terminal.wit":"fc87cd0bc3f76ff7181d3666617a38ee10239f8e0344db2a52cb79f46c6b2d31","wit/deps/clocks/monotonic-clock.wit":"ab12521f4522c7bae48fb272fc90f7bf21f83bc3e6b86e400075826628fdcf23","wit/deps/clocks/timezone.wit":"aaabf8145758aa75222a5e18de29a912d5ebb5babc348884fd81b1fa90225adc","wit/deps/clocks/wall-clock.wit":"b7b63d7bbb6631bcc8ce7d25910d47308e6345104dc146513b76ff1d82e1d7a0","wit/deps/clocks/world.wit":"5f066526b320973195e083bc946874b36fc488f8ae5004119c9b5dcd83430660","wit/deps/filesystem/preopens.wit":"1c53bbc639e87efc67440332e186bcc617f1ab0f2a9789c339a69ed0da424358","wit/deps/filesystem/types.wit":"24413900954e7ca1438f3c9b326a6f799b748beab51a297ab687003578f66765","wit/deps/filesystem/world.wit":"70f31a63ada7aeb6be29380aae712406baf91dad72e73de39025e38f41a32cae","wit/deps/http/handler.wit":"1f66174b4058b102367e69ce8aa657b3e9dbc767f6ade960108faaa1731f0945","wit/deps/http/proxy.wit":"c8756768c033db884734f98858b0d448a3a2cb98d9e4584c705f1fc0418422f1","wit/deps/http/types.wit":"82ac209d799643a39309c40d108a9594bebb79312f383ffcf284f23011041e7e","wit/deps/io/error.wit":"ea8a48ed6aa970947f65e378a2e72b878b421d0594b5425349d1c033a138533f","wit/deps/io/poll.wit":"d6eafcf78f220dfc07c4f055019732cc30c526d6d0d0b24150325c5eeef5d041","wit/deps/io/streams.wit":"d4b8980637de85e47459a0144dc1a9b999bfcbfb6ab344f0eceadc5face6135b","wit/deps/io/world.wit":"5572ef45d90cd766282c171a6cc403b3b9567b73e63a413c4eba1b4ad05caf25","wit/deps/random/insecure-seed.wit":"466da73f3aa1065083dd15ffd1d55c8e69b6ec4dfc6c9c149e651a126f60f33c","wit/deps/random/insecure.wit":"0a132cde99268a502973ca112db9da45c0c32870c67d6b92bd3110636c1cd871","wit/deps/random/random.wit":"cebb42f292bada460ab424bb56caf392ad14d4d7dfae1b85dfbc55253c1b751f","wit/deps/random/world.wit":"7d825a7a1624f4a165f6c7abc9aaa77e25618a9fed0c56461df8826965920dc2","wit/deps/sockets/instance-network.wit":"1e4a5d97df44421503a169e1d514eca2cf160f545c44d320ce8a82f726a40cf8","wit/deps/sockets/ip-name-lookup.wit":"c87cc003ff2b92a0d74294418e0d62d12f42f913b94617f73cc09738a46e8fac","wit/deps/sockets/network.wit":"077f76c2f266b3211b0e3fbddf4fbfd9060be050954d44aad9b331419fbe3caf","wit/deps/sockets/tcp-create-socket.wit":"96a6a1a93b859127ee60273f0a77cda8d60930f7952174fb22469293b5da6a3a","wit/deps/sockets/tcp.wit":"ad16e21cae8b67e09f6541fafaf57c88242722871aced8e53aaf018ee63be086","wit/deps/sockets/udp-create-socket.wit":"c52b9bf91ef4e30e7ec08ad1fc9e77ef005a0a87648c5d2e416dd6e35369f08c","wit/deps/sockets/udp.wit":"b8cd7720349cf11278dd30c77799b0255bfc8cbfb2dc2a8dd333f658a88d147e","wit/deps/sockets/world.wit":"84e8071d91f63484a326b5a745728e1964edc55cc90796df7ba042b508325103","wit/wasi-crate.wit":"561b9308e635f442fcfbe3c4e783d0b4f2110f4c7bdadc8775170e2e119f7453"},"package":"0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "3da562c06214feafc14d37bf290671636caa6718" + }, + "path_in_vcs": "crates/wasip2" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +dependencies = [ + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +dependencies = [ + "bitflags", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,97 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.82.0" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "WASIp2 API bindings for Rust" +documentation = "https://docs.rs/wasip2" +readme = "README.md" +keywords = [ + "webassembly", + "wasm", +] +categories = [ + "no-std", + "wasm", +] +license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" +repository = "https://github.com/bytecodealliance/wasi-rs" + +[features] +bitflags = ["wit-bindgen/bitflags"] +default = [ + "std", + "bitflags", +] +rustc-dep-of-std = [ + "core", + "alloc", + "wit-bindgen/rustc-dep-of-std", +] +std = [] + +[lib] +name = "wasip2" +path = "src/lib.rs" + +[[example]] +name = "cli-command" +crate-type = ["cdylib"] +path = "examples/cli-command.rs" +required-features = ["std"] + +[[example]] +name = "cli-command-no_std" +crate-type = ["cdylib"] +path = "examples/cli-command-no_std.rs" + +[[example]] +name = "hello-world" +path = "examples/hello-world.rs" +required-features = ["std"] + +[[example]] +name = "hello-world-no_std" +path = "examples/hello-world-no_std.rs" + +[[example]] +name = "http-proxy" +crate-type = ["cdylib"] +path = "examples/http-proxy.rs" +required-features = ["std"] + +[[example]] +name = "http-proxy-no_std" +crate-type = ["cdylib"] +path = "examples/http-proxy-no_std.rs" + +[dependencies.alloc] +version = "1.0" +optional = true +package = "rustc-std-workspace-alloc" + +[dependencies.core] +version = "1.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.wit-bindgen] +version = "0.46.0" +default-features = false diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,48 @@ +[package] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +description = "WASIp2 API bindings for Rust" +categories = ["no-std", "wasm"] +keywords = ["webassembly", "wasm"] +documentation = "https://docs.rs/wasip2" +readme = "README.md" +license.workspace = true +edition.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +wit-bindgen = { workspace = true } + +# When built as part of libstd +core = { optional = true, workspace = true } +alloc = { optional = true, workspace = true } + +[features] +default = ["std", "bitflags"] +std = [] +bitflags = ["wit-bindgen/bitflags"] +# Unstable feature to support being a libstd dependency +rustc-dep-of-std = ["core", "alloc", "wit-bindgen/rustc-dep-of-std"] + +[[example]] +name = "cli-command-no_std" +crate-type = ["cdylib"] + +[[example]] +name = "cli-command" +crate-type = ["cdylib"] +required-features = ["std"] + +[[example]] +name = "hello-world" +required-features = ["std"] + +[[example]] +name = "http-proxy-no_std" +crate-type = ["cdylib"] + +[[example]] +name = "http-proxy" +crate-type = ["cdylib"] +required-features = ["std"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/wasip2/README.md clamav-1.4.6+dfsg/.cargo/vendor/wasip2/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/wasip2/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/wasip2/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,117 @@ +

(transform, Into::layout(PrivateToken)) + } + + pub(crate) trait HelpDispatchTransform: Sized + 'static { + fn transform_on>( + transform: &cicp::CicpTransform, + into: LayoutWithColor, + ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync); + } + + impl HelpDispatchTransform for u8 { + fn transform_on>( + transform: &cicp::CicpTransform, + into: LayoutWithColor, + ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) { + &**transform.select_transform_u8::(into) + } + } + + impl HelpDispatchTransform for u16 { + fn transform_on>( + transform: &cicp::CicpTransform, + into: LayoutWithColor, + ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) { + &**transform.select_transform_u16::(into) + } + } - impl SealedPixelWithColorType for Luma {} - impl SealedPixelWithColorType for LumaA {} + impl HelpDispatchTransform for f32 { + fn transform_on>( + transform: &cicp::CicpTransform, + into: LayoutWithColor, + ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) { + &**transform.select_transform_f32::(into) + } + } } /// A generalized pixel. @@ -249,6 +432,26 @@ /// See [gimp babl](http://gegl.org/babl/). const COLOR_MODEL: &'static str; + /// Returns true if the alpha channel is contained. + const HAS_ALPHA: bool = false; + + /// Retrieve the value of the alpha channel for this pixel. + /// + /// If there is no alpha channel, returns [Primitive::DEFAULT_MAX_VALUE]. + /// + /// ### Note for Pixel trait implementors + /// + /// While this is a provided method, it is a good idea to override it for efficiency + /// if your pixel type does have an alpha channel. + #[inline] + fn alpha(&self) -> Self::Subpixel { + if Self::HAS_ALPHA { + *self.to_luma_alpha().channels().last().unwrap() + } else { + Self::Subpixel::DEFAULT_MAX_VALUE + } + } + /// Returns the channels of this pixel as a 4 tuple. If the pixel /// has less than 4 channels the remainder is filled with the maximum value #[deprecated(since = "0.24.0", note = "Use `channels()` or `channels_mut()`")] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/src/utils/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image/src/utils/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/src/utils/mod.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/src/utils/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,6 @@ //! Utilities +use std::collections::TryReserveError; use std::iter::repeat; #[inline(always)] @@ -26,7 +27,7 @@ for ((shift, i), j_inv) in i.zip(j_inv) { let j = buf_len - j_inv; let pixel = (buf[i] & (mask << shift)) >> shift; - func(pixel, &mut buf[j..(j + channels)]) + func(pixel, &mut buf[j..(j + channels)]); } } @@ -53,7 +54,7 @@ // skip the pixels that can be neglected because scanlines should // start at byte boundaries if i % (row_len as usize) < (row_size as usize) { - let pixel = (v & mask << shift as usize) >> shift as usize; + let pixel = (v & (mask << shift as usize)) >> shift as usize; p.push(pixel * scaling_factor); } i += 1; @@ -66,7 +67,7 @@ #[allow(dead_code)] // When no image formats that use it are enabled pub(crate) fn check_dimension_overflow(width: u32, height: u32, bytes_per_pixel: u8) -> bool { - width as u64 * height as u64 > std::u64::MAX / bytes_per_pixel as u64 + u64::from(width) * u64::from(height) > u64::MAX / u64::from(bytes_per_pixel) } #[allow(dead_code)] @@ -92,6 +93,13 @@ } } +#[inline] +pub(crate) fn vec_try_with_capacity(capacity: usize) -> Result, TryReserveError> { + let mut vec = Vec::new(); + vec.try_reserve_exact(capacity)?; + Ok(vec) +} + #[cfg(test)] mod test { #[test] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/conversions.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/conversions.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/conversions.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/conversions.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -use image::buffer::ConvertBuffer; -use image::{ImageBuffer, Rgb, Rgba}; - -#[test] -fn test_rgbu8_to_rgbu16() { - // Create an all white image using Rgbs for pixel values - let image_u16 = - ImageBuffer::from_pixel(2, 2, image::Rgb::([u16::MAX, u16::MAX, u16::MAX])); - - // Create an all white image using Rgbs for pixel values and convert it - // to Rgbs. - let image_u8 = ImageBuffer::from_pixel(2, 2, image::Rgb::([u8::MAX, u8::MAX, u8::MAX])); - let image_converted: ImageBuffer, _> = image_u8.convert(); - - assert_eq!(image_u16, image_converted); -} - -#[test] -fn test_rgbau8_to_rgbau16() { - let image_u16 = ImageBuffer::from_pixel( - 2, - 2, - image::Rgba::([u16::MAX, u16::MAX, u16::MAX, u16::MAX]), - ); - - let image_u8 = ImageBuffer::from_pixel( - 2, - 2, - image::Rgba::([u8::MAX, u8::MAX, u8::MAX, u8::MAX]), - ); - let image_converted: ImageBuffer, _> = image_u8.convert(); - - assert_eq!(image_u16, image_converted); -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badbitcount.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badbitcount.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badplanes.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_badplanes.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_clrsUsed.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_clrsUsed.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_height.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_height.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_pal8oversizepal.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_pal8oversizepal.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_reallybig.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_reallybig.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_rletopdown.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_rletopdown.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_shortfile.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_shortfile.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_unusual_extend_buffer_usage.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_unusual_extend_buffer_usage.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_width.bad_bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Bad_width.bad_bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_1_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_1_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_4_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_4_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_8_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Core_8_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_1_Bit_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_4_Bit_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_8_Bit_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_R8_G8_B8_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_R5_G6_B5_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V4_24_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V4_24_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/V5_24_Bit.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/V5_24_Bit.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2color.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal2color.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rle.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rle.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rlecut.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rlecut.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rletrns.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal4rletrns.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8badindex.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8badindex.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8rle.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8rle.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v4.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v4.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v5.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/pal8v5.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-231.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-231.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-565.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16-565.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb16.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb24.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb24.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32-111110.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32-111110.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32bf.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgb32bf.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba16-1924.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba16-1924.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32-61754.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32-61754.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32.bmp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/bmp/images/rgba32.bmp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/exr/cropping - data window differs display window.exr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/cropping - data window differs display window.exr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/exr/cropping - uncropped original.exr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/cropping - uncropped original.exr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient - data window equals display window.exr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient - data window equals display window.exr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient.hdr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/exr/overexposed gradient.hdr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/acid2.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/acid2.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn0g04.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn0g04.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbbn3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbgn3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbgn3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbrn2c08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbrn2c08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbwn3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbwn3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbyn3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tbyn3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tm3n3p02.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tm3n3p02.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n0g08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n0g08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n2c08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n2c08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp0n3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp1n3p08.ff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/farbfeld/transparency/tp1n3p08.ff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/any-disposal.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/any-disposal.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/border_touching_layers.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/border_touching_layers.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/interlaced.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/interlaced.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/issue_1455_undersized.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/issue_1455_undersized.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-combine.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-combine.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-full-frame-replace.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/large-gif-anim-full-frame-replace.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/mixed-disposal.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/mixed-disposal.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/anim/oob.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/anim/oob.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/simple/alpha_gif_a.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/alpha_gif_a.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/simple/issue_1455_oversized.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/issue_1455_oversized.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/gif/simple/sample_1.gif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/gif/simple/sample_1.gif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/hdr/images/image1.hdr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/hdr/images/image1.hdr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/hdr/images/rgbr4x4.hdr and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/hdr/images/rgbr4x4.hdr differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/ico/images/Bad_smile-incorrect-image-length.bad_ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/Bad_smile-incorrect-image-length.bad_ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-24bpp-mask.ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-24bpp-mask.ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-32bpp-alpha.ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/bmp-32bpp-alpha.ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/ico/images/png-32bpp-alpha.ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/png-32bpp-alpha.ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/ico/images/smile.ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/ico/images/smile.ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/3.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/3.jpg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/cat.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/cat.jpg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/test.jpg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/jpg/progressive/test.jpg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/pbm/images/issue-794.pbm and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/pbm/images/issue-794.pbm differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/16bpc/basn6a16.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/16bpc/basn6a16.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/apng/ball.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/apng/ball.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/debug_triangle_corners_widescreen.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/debug_triangle_corners_widescreen.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#2026.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#2026.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#403.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/bugfixes/issue#403.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/interlaced/basi2c08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/interlaced/basi2c08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/acid2.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/acid2.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn0g04.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn0g04.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbbn3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbgn3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbgn3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbrn2c08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbrn2c08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbwn3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbwn3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbyn3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tbyn3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tm3n3p02.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tm3n3p02.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n0g08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n0g08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n2c08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n2c08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp0n3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp1n3p08.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/png/transparency/tp1n3p08.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/qoi/basic-test.qoi and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/qoi/basic-test.qoi differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/encoding/black_white.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/encoding/black_white.tga differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/LICENSE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -TrueVision TGA (a.k.a. Targa) 2.0 conformance suite - -Official format specification, sample images and utilitiesriginally been publicly available, free of -charge and under no specific licensing terms, from TrueVision, Inc.'s FTP -server at the following URL: - -ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version/ - -All of the material contained here is therefore copyright to TrueVision, Inc., -unless otherwise stated. - -But has been removed in the proceedings of Pinnacle Systems' acquisition of -TrueVision, Inc., as outdated. However, a back-up of these files is available -here: - -http://googlesites.inequation.org/tgautilities Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/cbw8.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/cbw8.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ccm8.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ccm8.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ctc24.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ctc24.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ubw8.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ubw8.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ucm8.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/ucm8.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc16.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc16.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc24.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc24.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc32.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tga/testsuite/utc32.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict.tiff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict.tiff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_cmyk.tiff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_cmyk.tiff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_packbits.tiff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/hpredict_packbits.tiff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/mandrill.tiff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/mandrill.tiff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/rgb-3c-16b.tiff and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/tiff/testsuite/rgb-3c-16b.tiff differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/anim.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/anim.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/lossy_alpha.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/extended_images/lossy_alpha.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/2-color.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/2-color.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/multi-color.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/multi-color.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/simple.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossless_images/simple.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-gray.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-gray.webp differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-rgb.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/images/webp/lossy_images/simple-rgb.webp differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/limits.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/limits.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,229 +0,0 @@ -//! Test enforcement of size and memory limits for various decoding APIs. -//! -//! We create an image, encode it with a given format, and then decode it with various APIs. -//! We expect each decoding API to return an error because the limits are too low.//! -//! The ones that do not return an error are buggy. -//! -//! There are several such buggy APIs in the crate. The tests for them are written but commented out. -//! Pull requests fixing these APIs are very welcome. -//! -//! It is possible that a maliciously crafted file coud bypass these checks -//! and cause a large allocation inside the decoder despite these limits. -//! These tests cannot catch that, but fuzzing can. -//! -//! These tests also don't cover animation (yet). Adding tests for that would be very welcome too. - -use std::io::Cursor; - -use image::{ - io::Limits, load_from_memory_with_format, ImageDecoder, ImageFormat, ImageOutputFormat, - RgbImage, -}; - -const WIDTH: u32 = 256; -const HEIGHT: u32 = 256; - -fn test_image(format: ImageOutputFormat) -> Vec { - let image = RgbImage::new(WIDTH, HEIGHT); - let mut bytes: Vec = Vec::new(); - image - .write_to(&mut Cursor::new(&mut bytes), format) - .unwrap(); - bytes -} - -/// Returns `Limits` with width/height smaller than the test image -fn width_height_limits() -> Limits { - let mut limits = Limits::no_limits(); - limits.max_image_width = Some(WIDTH / 2); - limits.max_image_height = Some(HEIGHT / 2); - limits -} - -/// Returns `Limits` with allocation limit smaller than the test image -fn allocation_limits() -> Limits { - let mut limits = Limits::no_limits(); - limits.max_alloc = Some(((WIDTH / 2) * (HEIGHT / 2) * 3).into()); // matches dimension limits for RGB images - limits -} - -/// Returns `Limits` that allow decoding this image without issues -fn permissive_limits() -> Limits { - let mut limits = Limits::no_limits(); - limits.max_image_width = Some(WIDTH); - limits.max_image_height = Some(HEIGHT); - limits.max_alloc = Some((WIDTH * HEIGHT * 5).into()); // `* 3`` would be an exact fit for RGB; `* 5`` allows some slack space - limits -} - -fn load_through_reader( - input: &[u8], - format: ImageFormat, - limits: Limits, -) -> Result { - let mut reader = image::io::Reader::new(Cursor::new(input)); - reader.set_format(format); - reader.limits(limits); - reader.decode() -} - -#[test] -#[cfg(feature = "gif")] -fn gif() { - use image::codecs::gif::GifDecoder; - - let image = test_image(ImageOutputFormat::Gif); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Gif).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::Gif, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Gif, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Gif, allocation_limits()).is_err()); // BROKEN! - - // GifDecoder - let mut decoder = GifDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // no tests for allocation limits because the caller is responsible for allocating the buffer in this case - - // Custom constructor on GifDecoder - #[allow(deprecated)] - { - assert!(GifDecoder::with_limits(Cursor::new(&image), width_height_limits()).is_err()); - // no tests for allocation limits because the caller is responsible for allocating the buffer in this case - } -} - -#[test] -#[cfg(feature = "png")] -fn png() { - use image::codecs::png::PngDecoder; - - let image = test_image(ImageOutputFormat::Png); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Png).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::Png, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Png, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Png, allocation_limits()).is_err()); - - // PngDecoder - let mut decoder = PngDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. - // Unlike many others, the `png` crate does natively support memory limits for auxiliary buffers, - // but they are not passed down from `set_limits` - only from the `with_limits` constructor. - // The proper fix is known to require an API break: https://github.com/image-rs/image/issues/2084 - - // Custom constructor on PngDecoder - assert!(PngDecoder::with_limits(Cursor::new(&image), width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} - -#[test] -#[cfg(feature = "jpeg")] -fn jpeg() { - use image::codecs::jpeg::JpegDecoder; - - let image = test_image(ImageOutputFormat::Jpeg(80)); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Jpeg).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::Jpeg, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Jpeg, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Jpeg, allocation_limits()).is_err()); - - // JpegDecoder - let mut decoder = JpegDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} - -#[test] -#[cfg(feature = "webp")] -fn webp() { - use image::codecs::webp::WebPDecoder; - - let image = test_image(ImageOutputFormat::WebP); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::WebP).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::WebP, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::WebP, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::WebP, allocation_limits()).is_err()); - - // WebPDecoder - let mut decoder = WebPDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} - -#[test] -#[cfg(feature = "tiff")] -fn tiff() { - use image::codecs::tiff::TiffDecoder; - - let image = test_image(ImageOutputFormat::Tiff); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Tiff).is_ok()); - - // check that the limits implementation is not overly restrictive - // The TIFF decoder is special - the `image` crate API does not play well with `tiff` crate API, - // so there is a copy from the buffer allocated by `tiff` to a buffer allocated by `image`. - // This results in memory usage overhead the size of the output buffer. - let mut tiff_permissive_limits = permissive_limits(); - tiff_permissive_limits.max_alloc = Some((WIDTH * HEIGHT * 10).into()); // `* 9` would be exactly three output buffers, `* 10`` has some slack space - load_through_reader(&image, ImageFormat::Tiff, tiff_permissive_limits).unwrap(); - - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Tiff, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Tiff, allocation_limits()).is_err()); - - // TiffDecoder - let mut decoder = TiffDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} - -#[test] -#[cfg(all(feature = "avif", feature = "avif-decoder"))] -fn avif() { - use image::codecs::avif::AvifDecoder; - - let image = test_image(ImageOutputFormat::Avif); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Avif).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::Avif, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Avif, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Avif, allocation_limits()).is_err()); - - // AvifDecoder - let mut decoder = AvifDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} - -#[test] -#[cfg(feature = "bmp")] -fn bmp() { - use image::codecs::bmp::BmpDecoder; - - let image = test_image(ImageOutputFormat::Bmp); - // sanity check that our image loads successfully without limits - assert!(load_from_memory_with_format(&image, ImageFormat::Bmp).is_ok()); - // check that the limits implementation is not overly restrictive - assert!(load_through_reader(&image, ImageFormat::Bmp, permissive_limits()).is_ok()); - // image::io::Reader - assert!(load_through_reader(&image, ImageFormat::Bmp, width_height_limits()).is_err()); - assert!(load_through_reader(&image, ImageFormat::Bmp, allocation_limits()).is_err()); - - // BmpDecoder - let mut decoder = BmpDecoder::new(Cursor::new(&image)).unwrap(); - assert!(decoder.set_limits(width_height_limits()).is_err()); - // No tests for allocation limits because the caller is responsible for allocating the buffer in this case. -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/limits_anim.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits_anim.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/limits_anim.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/limits_anim.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -//! Test enforcement of size and memory limits for animation decoding APIs. - -use image::{io::Limits, AnimationDecoder, ImageDecoder, ImageResult}; - -#[cfg(feature = "gif")] -use image::codecs::gif::GifDecoder; - -#[cfg(feature = "gif")] -fn gif_decode(data: &[u8], limits: Limits) -> ImageResult<()> { - let mut decoder = GifDecoder::new(data).unwrap(); - decoder.set_limits(limits)?; - { - let frames = decoder.into_frames(); - for result in frames { - result?; - } - } - Ok(()) -} - -/// Checks that the function returned `ImageError::Limits`, panics otherwise -#[track_caller] -fn assert_limit_error(res: ImageResult<()>) { - let err = res.expect_err("The input should have been rejected because it exceeds limits"); - match err { - image::ImageError::Limits(_) => (), // all good - _ => panic!("Decoding failed due to an error unrelated to limits"), - } -} - -/// Each frame is the size of the image, -/// so we can just output each raw GIF frame buffer as the final composited frame -/// with no additional scratch space -#[test] -#[cfg(feature = "gif")] -fn animated_full_frame_discard() { - let data = - std::fs::read("tests/images/gif/anim/large-gif-anim-full-frame-replace.gif").unwrap(); - - let mut limits_dimensions_too_small = Limits::default(); - limits_dimensions_too_small.max_image_width = Some(500); - limits_dimensions_too_small.max_image_height = Some(500); - assert_limit_error(gif_decode(&data, limits_dimensions_too_small)); - - let mut limits_memory_way_too_small = Limits::default(); - // Start with a ridiculously low memory allocation cap - limits_memory_way_too_small.max_alloc = Some(5); - assert_limit_error(gif_decode(&data, limits_memory_way_too_small)); - - let mut limits_memory_too_small = Limits::default(); - // 1000 * 1000 * 4 would be the exact size of the buffer for one RGBA frame. - // The decoder always peaks with at least two frames in memory at the same time. - // Set the limit a little higher than 1 frame than that it doesn't run into trivial checks - // for output frame size, and make it run into actual buffer allocation errors. - limits_memory_too_small.max_alloc = Some(1000 * 1000 * 5); - assert_limit_error(gif_decode(&data, limits_memory_too_small)); - - let mut limits_just_enough = Limits::default(); - limits_just_enough.max_image_height = Some(1000); - limits_just_enough.max_image_width = Some(1000); - limits_just_enough.max_alloc = Some(1000 * 1000 * 4 * 2); // 4 for RGBA, 2 for 2 buffers kept in memory simultaneously - - gif_decode(&data, limits_just_enough) - .expect("With these limits it should have decoded successfully"); -} - -/// The GIF frame does not cover the whole image, requiring additional scratch space -#[test] -#[cfg(feature = "gif")] -fn animated_frame_combine() { - let data = std::fs::read("tests/images/gif/anim/large-gif-anim-combine.gif").unwrap(); - - let mut limits_dimensions_too_small = Limits::default(); - limits_dimensions_too_small.max_image_width = Some(500); - limits_dimensions_too_small.max_image_height = Some(500); - assert_limit_error(gif_decode(&data, limits_dimensions_too_small)); - - let mut limits_memory_way_too_small = Limits::default(); - // Start with a ridiculously low memory allocation cap - limits_memory_way_too_small.max_alloc = Some(5); - assert_limit_error(gif_decode(&data, limits_memory_way_too_small)); - - let mut limits_memory_too_small = Limits::default(); - // 1000 * 1000 * 4 * would be the exact size of two buffers for an RGBA frame. - // In this mode the decoder uses 2 full frames (accumulated result and the output frame) - // plus the smaller frame size from the GIF format decoder that it composites onto the output frame. - // So two full frames are not actually enough for decoding here. - // Verify that this is caught. - limits_memory_too_small.max_alloc = Some(1000 * 1000 * 4 * 2); // 4 for RGBA, 2 for 2 buffers kept in memory simultaneously - assert_limit_error(gif_decode(&data, limits_memory_too_small)); - - let mut limits_enough = Limits::default(); - limits_enough.max_image_height = Some(1000); - limits_enough.max_image_width = Some(1000); - limits_enough.max_alloc = Some(1000 * 1000 * 4 * 3); // 4 for RGBA, 2 for 2 buffers kept in memory simultaneously - - gif_decode(&data, limits_enough) - .expect("With these limits it should have decoded successfully"); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/README.txt clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/README.txt --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/README.txt 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/README.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -This folder contains the reference renderings. To save space, they are saved as -PNG images. Since the decoder is not part of the test, the resulting png file -in `output` may differ. Thus a CRC checksum of the image data is saved in the -filename. - -Therefore it is ok to update the reference renderings with files from the -`output` dir, but it is not ok to add a new file instead. \ No newline at end of file Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2.bmp.da27594.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2.bmp.da27594.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rle.bmp.288e4371.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rle.bmp.288e4371.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8badindex.bmp.4500d02.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8badindex.bmp.4500d02.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8rle.bmp.38454155.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8rle.bmp.38454155.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v4.bmp.38454155.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v4.bmp.38454155.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v5.bmp.38454155.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/pal8v5.bmp.38454155.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-565.bmp.80839b35.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16-565.bmp.80839b35.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16.bmp.46dd68ad.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb16.bmp.46dd68ad.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb24.bmp.25bba0a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb24.bmp.25bba0a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32.bmp.25bba0a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32.bmp.25bba0a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32.bmp.e041b498.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/bmp/images/rgba32.bmp.e041b498.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/any-disposal.gif.ace8cccc.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/any-disposal.gif.ace8cccc.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/interlaced.gif.ad3a4823.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/interlaced.gif.ad3a4823.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/anim/oob.gif.da695a00.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/anim/oob.gif.da695a00.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/gif/simple/sample_1.gif.c33b036b.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/gif/simple/sample_1.gif.c33b036b.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.hdr.bd02cf8f.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.hdr.bd02cf8f.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.raw and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/image1.raw differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.hdr.72ffeca1.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.hdr.72ffeca1.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.raw and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/hdr/images/rgbr4x4.raw differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/ico/images/smile.ico.291e3bb0.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/ico/images/smile.ico.291e3bb0.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/3.jpg.79e90ab0.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/3.jpg.79e90ab0.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/cat.jpg.a1b69d49.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/cat.jpg.a1b69d49.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/test.jpg.f0362c80.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/jpg/progressive/test.jpg.f0362c80.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/pbm/images/issue-794.pbm.80cbc790.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/pbm/images/issue-794.pbm.80cbc790.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/16bpc/basn6a16.png.87be531.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/16bpc/basn6a16.png.87be531.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.1c840a9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.1c840a9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_01_01c840a9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_01_01c840a9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_04_26897da3.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_04_26897da3.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_05_123fe3c5.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_05_123fe3c5.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_06_69c299ea.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_06_69c299ea.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_07_765d3648.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_07_765d3648.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_08_e44a80f7.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_08_e44a80f7.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_09_dd6883db.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_09_dd6883db.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_10_3b68b97b.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_10_3b68b97b.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_12_0796c12e.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_12_0796c12e.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_13_bf335902.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_13_bf335902.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_14_ee765a97.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_14_ee765a97.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_15_56f89914.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_15_56f89914.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_16_cd899432.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_16_cd899432.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_17_0c3b039a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_17_0c3b039a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_18_611a8f5d.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_18_611a8f5d.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_19_d7316ce1.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_19_d7316ce1.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_20_1e8b755f.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/apng/ball.png.anim_20_1e8b755f.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/issue#403.png.b0818cef.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/bugfixes/issue#403.png.b0818cef.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/interlaced/basi2c08.png.7855b9bf.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/interlaced/basi2c08.png.7855b9bf.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/acid2.png.8de8ca3f.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/acid2.png.8de8ca3f.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbrn2c08.png.370ef89.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbrn2c08.png.370ef89.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n2c08.png.b426b350.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n2c08.png.b426b350.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n3p08.png.15493236.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp0n3p08.png.15493236.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ctc24.tga.b7096b3.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ctc24.tga.b7096b3.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc24.tga.b7096b3.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc24.tga.b7096b3.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc32.tga.134a83ba.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tga/testsuite/utc32.tga.134a83ba.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/anim.webp.f6449d24.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/anim.webp.f6449d24.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/lossy_alpha.webp.37efcff9.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/extended_images/lossy_alpha.webp.37efcff9.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/2-color.webp.d5b9a8bd.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/2-color.webp.d5b9a8bd.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/multi-color.webp.d98bd812.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/multi-color.webp.d98bd812.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/simple.webp.18d31ac3.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossless_images/simple.webp.18d31ac3.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-gray.webp.6b294f50.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-gray.webp.6b294f50.png differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-rgb.webp.4bb22be5.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference/webp/lossy_images/simple-rgb.webp.4bb22be5.png differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference_images.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/reference_images.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/reference_images.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,350 +0,0 @@ -//! Compares the decoding results with reference renderings. -use std::fs; -use std::io; -use std::path::PathBuf; -use std::u32; - -use crc32fast::Hasher as Crc32; -use image::DynamicImage; - -const BASE_PATH: [&str; 2] = [".", "tests"]; -const IMAGE_DIR: &str = "images"; -const OUTPUT_DIR: &str = "output"; -const REFERENCE_DIR: &str = "reference"; - -fn process_images(dir: &str, input_decoder: Option<&str>, func: F) -where - F: Fn(&PathBuf, PathBuf, &str), -{ - let base: PathBuf = BASE_PATH.iter().collect(); - let decoders = &[ - "tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "pbm", "webp", - ]; - for decoder in decoders { - let mut path = base.clone(); - path.push(dir); - path.push(decoder); - path.push("**"); - path.push( - "*.".to_string() - + match input_decoder { - Some(val) => val, - None => decoder, - }, - ); - let pattern = &*format!("{}", path.display()); - for path in glob::glob(pattern).unwrap().filter_map(Result::ok) { - func(&base, path, decoder) - } - } -} - -#[cfg(feature = "png")] -#[test] -fn render_images() { - process_images(IMAGE_DIR, None, |base, path, decoder| { - println!("render_images {}", path.display()); - let img = match image::open(&path) { - Ok(img) => img, - // Do not fail on unsupported error - // This might happen because the testsuite contains unsupported images - // or because a specific decoder included via a feature. - Err(image::ImageError::Unsupported(e)) => { - println!("UNSUPPORTED {}: {}", path.display(), e); - return; - } - Err(err) => panic!("decoding of {:?} failed with: {}", path, err), - }; - let mut crc = Crc32::new(); - crc.update(img.as_bytes()); - - let (filename, testsuite) = { - let mut path: Vec<_> = path.components().collect(); - (path.pop().unwrap(), path.pop().unwrap()) - }; - let mut out_path = base.clone(); - - out_path.push(OUTPUT_DIR); - out_path.push(decoder); - out_path.push(testsuite.as_os_str()); - fs::create_dir_all(&out_path).unwrap(); - out_path.push(format!( - "{}.{:x}.png", - filename.as_os_str().to_str().unwrap(), - crc.finalize(), - )); - img.save(out_path).unwrap(); - }) -} - -/// Describes a single test case of `check_references`. -struct ReferenceTestCase { - orig_filename: String, - crc: u32, - kind: ReferenceTestKind, -} - -enum ReferenceTestKind { - /// The test image is loaded using `image::open`, and the result is compared - /// against the reference image. - SingleImage, - - /// From the test image file, a single frame is extracted using a fitting animation decoder and - /// the result is compared against the reference image. - AnimatedFrame { - /// A zero-based frame number. - frame: usize, - }, -} - -impl std::str::FromStr for ReferenceTestCase { - type Err = &'static str; - - /// Construct `ReferenceTestCase` from the file name of a reference - /// image. - fn from_str(filename: &str) -> Result { - let mut filename_parts = filename.rsplitn(3, '.'); - - // Ignore the file extension - filename_parts.next().unwrap(); - - // The penultimate part of `filename_parts` represents the metadata, - // describing the test type and other details. - let meta_str = filename_parts.next().ok_or("missing metadata part")?; - let meta = meta_str.split('_').collect::>(); - let (crc, kind); - - if meta.len() == 1 { - // `CRC` - crc = parse_crc(meta[0]).ok_or("malformed CRC")?; - kind = ReferenceTestKind::SingleImage; - } else if meta.len() == 3 && meta[0] == "anim" { - // `anim_FRAME_CRC` - crc = parse_crc(meta[2]).ok_or("malformed CRC")?; - let frame: usize = meta[1].parse().map_err(|_| "malformed frame number")?; - kind = ReferenceTestKind::AnimatedFrame { - frame: frame.checked_sub(1).ok_or("frame number must be 1-based")?, - }; - } else { - return Err("unrecognized reference image metadata format"); - } - - // The remaining part represents the original file name - let orig_filename = filename_parts - .next() - .ok_or("missing original file name")? - .to_owned(); - - Ok(Self { - orig_filename, - crc, - kind, - }) - } -} - -/// Parse the given string as a hexadecimal CRC hash, used by `check_references`. -fn parse_crc(src: &str) -> Option { - u32::from_str_radix(src, 16).ok() -} - -#[test] -fn check_references() { - process_images(REFERENCE_DIR, Some("png"), |base, path, decoder| { - println!("check_references {}", path.display()); - - let ref_img = match image::open(&path) { - Ok(img) => img, - // Do not fail on unsupported error - // This might happen because the testsuite contains unsupported images - // or because a specific decoder included via a feature. - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => panic!("{}", err), - }; - - let (filename, testsuite) = { - let mut path: Vec<_> = path.components().collect(); - (path.pop().unwrap(), path.pop().unwrap()) - }; - - // Parse the file name to obtain the test case information - let filename_str = filename.as_os_str().to_str().unwrap(); - let case: ReferenceTestCase = filename_str.parse().unwrap(); - - let mut img_path = base.clone(); - img_path.push(IMAGE_DIR); - img_path.push(decoder); - img_path.push(testsuite.as_os_str()); - img_path.push(case.orig_filename); - - // Load the test image - let mut test_img = None; - - match case.kind { - ReferenceTestKind::AnimatedFrame { frame: frame_num } => { - let format = image::io::Reader::open(&img_path) - .unwrap() - .with_guessed_format() - .unwrap() - .format(); - - #[cfg(feature = "gif")] - if format == Some(image::ImageFormat::Gif) { - // Interpret the input file as an animation file - use image::AnimationDecoder; - let stream = io::BufReader::new(fs::File::open(&img_path).unwrap()); - let decoder = match image::codecs::gif::GifDecoder::new(stream) { - Ok(decoder) => decoder, - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => { - panic!("decoding of {:?} failed with: {}", img_path, err) - } - }; - - let mut frames = match decoder.into_frames().collect_frames() { - Ok(frames) => frames, - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => { - panic!("collecting frames of {:?} failed with: {}", img_path, err) - } - }; - - // Select a single frame - let frame = frames.drain(frame_num..).next().unwrap(); - - // Convert the frame to a`RgbaImage` - test_img = Some(DynamicImage::from(frame.into_buffer())); - } - - #[cfg(feature = "png")] - if format == Some(image::ImageFormat::Png) { - // Interpret the input file as an animation file - use image::AnimationDecoder; - let stream = io::BufReader::new(fs::File::open(&img_path).unwrap()); - let decoder = match image::codecs::png::PngDecoder::new(stream) { - Ok(decoder) => decoder.apng(), - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => { - panic!("decoding of {:?} failed with: {}", img_path, err) - } - }; - - let mut frames = match decoder.into_frames().collect_frames() { - Ok(frames) => frames, - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => { - panic!("collecting frames of {:?} failed with: {}", img_path, err) - } - }; - - // Select a single frame - let frame = frames.drain(frame_num..).next().unwrap(); - - // Convert the frame to a`RgbaImage` - test_img = Some(DynamicImage::from(frame.into_buffer())); - } - - if test_img.is_none() { - println!("Skipping - GIF codec is not enabled"); - return; - } - } - - ReferenceTestKind::SingleImage => { - // Read the input file as a single image - match image::open(&img_path) { - Ok(img) => test_img = Some(img), - // Do not fail on unsupported error - // This might happen because the testsuite contains unsupported images - // or because a specific decoder included via a feature. - Err(image::ImageError::Unsupported(_)) => return, - Err(err) => panic!("decoding of {:?} failed with: {}", img_path, err), - }; - } - } - - let test_img = match test_img.as_ref() { - Some(img) => img, - None => return, - }; - - let test_crc_actual = { - let mut hasher = Crc32::new(); - match test_img { - DynamicImage::ImageLuma8(_) - | DynamicImage::ImageLumaA8(_) - | DynamicImage::ImageRgb8(_) - | DynamicImage::ImageRgba8(_) => hasher.update(test_img.as_bytes()), - DynamicImage::ImageLuma16(_) - | DynamicImage::ImageLumaA16(_) - | DynamicImage::ImageRgb16(_) - | DynamicImage::ImageRgba16(_) => { - for v in test_img.as_bytes().chunks(2) { - hasher.update(&u16::from_ne_bytes(v.try_into().unwrap()).to_le_bytes()); - } - } - DynamicImage::ImageRgb32F(_) | DynamicImage::ImageRgba32F(_) => { - for v in test_img.as_bytes().chunks(4) { - hasher.update(&f32::from_ne_bytes(v.try_into().unwrap()).to_le_bytes()); - } - } - _ => panic!("Unsupported image format"), - } - hasher.finalize() - }; - - if test_crc_actual != case.crc { - panic!( - "{}: The decoded image's hash does not match (expected = {:08x}, actual = {:08x}).", - img_path.display(), - case.crc, - test_crc_actual - ); - } - - if ref_img.as_bytes() != test_img.as_bytes() { - panic!("Reference rendering does not match."); - } - }) -} - -#[cfg(feature = "hdr")] -#[test] -fn check_hdr_references() { - let mut ref_path: PathBuf = BASE_PATH.iter().collect(); - ref_path.push(REFERENCE_DIR); - ref_path.push("hdr"); - let mut path: PathBuf = BASE_PATH.iter().collect(); - path.push(IMAGE_DIR); - path.push("hdr"); - path.push("*"); - path.push("*.hdr"); - let pattern = &*format!("{}", path.display()); - for path in glob::glob(pattern).unwrap().filter_map(Result::ok) { - use std::path::Component::Normal; - let mut ref_path = ref_path.clone(); - // append 2 last components of image path to reference path - for c in path - .components() - .rev() - .take(2) - .collect::>() - .iter() - .rev() - { - match *c { - Normal(name) => ref_path.push(name), - _ => panic!(), - } - } - ref_path.set_extension("raw"); - println!("{}", ref_path.display()); - println!("{}", path.display()); - let decoder = - image::codecs::hdr::HdrDecoder::new(io::BufReader::new(fs::File::open(&path).unwrap())) - .unwrap(); - let decoded = decoder.read_image_hdr().unwrap(); - let reference = image::codecs::hdr::read_raw_file(&ref_path).unwrap(); - assert_eq!(decoded, reference); - } -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/ico/crash-981fee302fe0fc543ee48292cc3d6ace7e97e633.ico and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/ico/crash-981fee302fe0fc543ee48292cc3d6ace7e97e633.ico differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/jpg/oss-fuzz-36829.jpeg and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/jpg/oss-fuzz-36829.jpeg differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/bad-color-map.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/bad-color-map.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height2.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/flip-zero-height2.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/overfull-image.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/overfull-image.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap2.tga and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tga/sixteen-bit-gray-colormap2.tga differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/tiff/clusterfuzz-testcase-minimized-fuzzer_script_tiff-5026894169374720.tif and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/tiff/clusterfuzz-testcase-minimized-fuzzer_script_tiff-5026894169374720.tif differ Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression/webp/panic.webp and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression/webp/panic.webp differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/regression.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/regression.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -use std::{fs::File, io::BufReader, path::PathBuf}; - -const BASE_PATH: [&str; 2] = [".", "tests"]; -const IMAGE_DIR: &str = "images"; -const REGRESSION_DIR: &str = "regression"; - -fn process_images(dir: &str, input_decoder: Option<&str>, func: F) -where - F: Fn(PathBuf), -{ - let base: PathBuf = BASE_PATH.iter().collect(); - let decoders = &[ - "tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "pbm", "webp", "exr", - ]; - for decoder in decoders { - let mut path = base.clone(); - path.push(dir); - path.push(decoder); - path.push("**"); - path.push( - "*.".to_string() - + match input_decoder { - Some(val) => val, - None => decoder, - }, - ); - let pattern = &*format!("{}", path.display()); - for path in glob::glob(pattern).unwrap().filter_map(Result::ok) { - func(path) - } - } -} - -#[test] -fn check_regressions() { - process_images(REGRESSION_DIR, None, |path| { - let _ = image::open(path); - }) -} - -/// Check that BMP files with large values could cause OOM issues are rejected. -/// -/// The images are postfixed with `bad_bmp` to not be loaded by the other test. -#[test] -fn bad_bmps() { - let path: PathBuf = BASE_PATH - .iter() - .collect::() - .join(IMAGE_DIR) - .join("bmp/images") - .join("*.bad_bmp"); - - let pattern = &*format!("{}", path.display()); - for path in glob::glob(pattern).unwrap().filter_map(Result::ok) { - // Manually reading the file so we can use load() instead of open() - // We have to use load() so we can override the format - let im_file = BufReader::new(File::open(path).unwrap()); - let im = image::load(im_file, image::ImageFormat::Bmp); - assert!(im.is_err()); - } -} - -#[test] -fn bad_gif_oom() { - let data = [ - 71, 73, 70, 56, 55, 97, 0, 0, 0, 0, 0, 0, 0, 44, 255, 255, 219, 255, 172, 199, 199, 255, - 216, 255, 255, 0, 0, 48, 230, 2, 195, 195, 195, 195, 255, 239, 0, - ]; - - // The original code made a vec![0; very_large_number] which due to overcommit *does not* OOM. - // It then exits normally with an EOF when reading. - // - // So instead we look for a limits error (or an unsupported error, for the case that we're - // running these tests without gif being actually supported) - let error = image::load_from_memory(&data).unwrap_err(); - - assert!( - matches!(error, image::ImageError::Limits(_)) - | matches!(error, image::ImageError::Unsupported(_)) - ); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/save_jpeg.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/save_jpeg.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/save_jpeg.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/save_jpeg.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -//! Test saving "default" and specific quality jpeg. -#![cfg(all(feature = "jpeg", feature = "tiff"))] -extern crate image; - -use image::{ImageFormat, ImageOutputFormat}; -use std::io::Cursor; - -#[test] -fn jqeg_qualitys() { - let img = image::open("tests/images/tiff/testsuite/mandrill.tiff").unwrap(); - - let mut default = vec![]; - img.write_to(&mut Cursor::new(&mut default), ImageFormat::Jpeg) - .unwrap(); - assert_eq!(&[255, 216], &default[..2]); - - let mut small = vec![]; - img.write_to(&mut Cursor::new(&mut small), ImageOutputFormat::Jpeg(10)) - .unwrap(); - assert_eq!(&[255, 216], &small[..2]); - - assert!(small.len() < default.len()); - - let mut large = vec![]; - img.write_to(&mut Cursor::new(&mut large), ImageOutputFormat::Jpeg(99)) - .unwrap(); - assert_eq!(&[255, 216], &large[..2]); - - assert!(large.len() > default.len()); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image/tests/truncate_images.rs clamav-1.4.6+dfsg/.cargo/vendor/image/tests/truncate_images.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image/tests/truncate_images.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image/tests/truncate_images.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -//! Ensure truncated images are read without panics. - -use std::fs; -use std::io::Read; -use std::path::PathBuf; - -extern crate glob; -extern crate image; - -const BASE_PATH: [&str; 2] = [".", "tests"]; -const IMAGE_DIR: &str = "images"; - -fn process_images(dir: &str, input_decoder: Option<&str>, func: F) -where - F: Fn(PathBuf), -{ - let base: PathBuf = BASE_PATH.iter().collect(); - let decoders = &[ - "tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "farbfeld", "exr", - ]; - for decoder in decoders { - let mut path = base.clone(); - path.push(dir); - path.push(decoder); - path.push("*"); - path.push( - "*.".to_string() - + match input_decoder { - Some(val) => val, - None => decoder, - }, - ); - let pattern = &*format!("{}", path.display()); - for path in glob::glob(pattern).unwrap().filter_map(Result::ok) { - func(path) - } - } -} - -fn truncate_images(decoder: &str) { - process_images(IMAGE_DIR, Some(decoder), |path| { - println!("{:?}", path); - let fin = fs::File::open(&path).unwrap(); - let max_length = 1000; - let mut buf = Vec::with_capacity(max_length); - fin.take(max_length as u64).read_to_end(&mut buf).unwrap(); - for i in 0..buf.len() { - image::load_from_memory(&buf[..i + 1]).ok(); - } - }) -} - -#[test] -fn truncate_tga() { - truncate_images("tga") -} - -#[test] -fn truncate_tiff() { - truncate_images("tiff") -} - -#[test] -fn truncate_png() { - truncate_images("png") -} - -#[test] -fn truncate_gif() { - truncate_images("gif") -} - -#[test] -fn truncate_bmp() { - truncate_images("bmp") -} - -#[test] -fn truncate_ico() { - truncate_images("ico") -} - -#[test] -fn truncate_jpg() { - truncate_images("jpg") -} - -#[test] -fn truncate_hdr() { - truncate_images("hdr"); -} - -#[test] -fn truncate_farbfeld() { - truncate_images("farbfeld"); -} - -#[test] -fn truncate_exr() { - truncate_images("exr"); -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"0b5acdc5e994925d76cb7285f79bc3c5c958a564baa7c84e9c943cefcb1c998d","Cargo.lock":"baf1f3ef3366a6dcea3b88a0e411d0533916d2c03268c1532b6d114d0781923a","Cargo.toml":"c05cc68c768c57e79c581b2ad6c112759556df9689b83313e35d5943f2951262","Cargo.toml.orig":"578c495e6dcaaf3815a8ac5060b995b6d5ee32d78f69cefc75d5bc6124274a49","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"c77a4cf9da729987d0fe7ccd811e3bd27393914ddf3d23467c18cc22954513b3","README.md":"36eb220a060c9e4338203e65ed417c31c6044251d7f729b8d0d5bab6fb67cfbe","src/alpha_blending.rs":"2c8fb9bd4485dfe683ff5eb7bc9d3f2a962bdac500d144b6dba034c455e7f3bc","src/decoder.rs":"b2a424a9dee08909210f95497b5abcd48e3d85ebd831230b0c49f4237b0f7069","src/encoder.rs":"724d54d1f91f472211cc6595ae24a2975f878abb6d2ef03f2feb2d4f8259ea88","src/extended.rs":"1838299aefafaffca029942d0d337fe26cabf5a887c9f76e5b8fcbf577469a8a","src/huffman.rs":"5f1cf0c9a4a03f2ee84bb3756f6d0726c4724026b663fa25102d5d55850eb71f","src/lib.rs":"0bdc2014e7e01791abe8769119489d02b174b08f1f6950b1c3526d8fd060ece6","src/loop_filter.rs":"00400708c5c6e2115d5089a2c8ae0d5a442ed1e74b1f3448e00c6dafb218845e","src/lossless.rs":"dd14e7d8dd72c8ec76ffc27b4847d58b9ff83818dc1b25e3f4cf6169be89ea1f","src/lossless_transform.rs":"8396506ae0a0c621f3d81d4571019f46b60d361647a52b3314b6802fb904e036","src/mod.rs":"d244a8e2d409e4f175183c3d35d631153abdfb3f6f2d7b2739087649745dd45c","src/transform.rs":"5567ce2f86d849cf53fcbf397236102ab4e247be329dbb1ab9661321556e3e6e","src/vp8.rs":"91c1562d24627ae3e313b582d00fff874b16c444e9be845306f9583079e2e3c0","src/vp8_arithmetic_decoder.rs":"baf4ac638decf5b302118f1dfa22d4b568acabc6e60f4b4847324b30a10433cb","src/yuv.rs":"7f8f76dc0870fa08e3b9a7ab530c9933677c52f74b4230535cb541331d828128"},"package":"525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "08b57d473c90148dd4b37a075df365afc3dfcc2b" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,352 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" + +[[package]] +name = "bytemuck" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +dependencies = [ + "byteorder-lite", + "paste", + "png", + "quick-error", + "rand", + "webp", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libwebp-sys" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cd30df7c7165ce74a456e4ca9732c603e8dc5e60784558c1c6dc047f876733" +dependencies = [ + "cc", + "glob", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "webp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f53152f51fb5af0c08484c33d16cca96175881d1f3dec068c23b31a158c2d99" +dependencies = [ + "image", + "libwebp-sys", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.3", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.80.1" +name = "image-webp" +version = "0.2.4" +build = false +include = [ + "/src", + "LICENSE-APACHE", + "LICENSE-MIT", + "README.md", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "WebP encoding and decoding in pure Rust" +homepage = "https://github.com/image-rs/image-webp" +readme = "README.md" +categories = [ + "multimedia::images", + "multimedia::encoding", + "encoding", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/image-rs/image-webp" + +[features] +_benchmarks = [] + +[lib] +name = "image_webp" +path = "src/lib.rs" + +[dependencies.byteorder-lite] +version = "0.1.0" + +[dependencies.quick-error] +version = "2.0.1" + +[dev-dependencies.paste] +version = "1.0.14" + +[dev-dependencies.png] +version = "0.17.12" + +[dev-dependencies.rand] +version = "0.8.5" + +[dev-dependencies.webp] +version = "0.3.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +[package] +name = "image-webp" +version = "0.2.4" +edition = "2021" +license = "MIT OR Apache-2.0" +rust-version = "1.80.1" + +description = "WebP encoding and decoding in pure Rust" +homepage = "https://github.com/image-rs/image-webp" +repository = "https://github.com/image-rs/image-webp" +categories = ["multimedia::images", "multimedia::encoding", "encoding"] + +include = ["/src", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] + +[dependencies] +byteorder-lite = "0.1.0" +quick-error = "2.0.1" + +[dev-dependencies] +paste = "1.0.14" +png = "0.17.12" +rand = "0.8.5" +webp = "0.3.0" + +[features] +_benchmarks = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/LICENSE-MIT clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-MIT --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/LICENSE-MIT 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +MIT License + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/README.md clamav-1.4.6+dfsg/.cargo/vendor/image-webp/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +# image-webp + +[![crates.io](https://img.shields.io/crates/v/image-webp.svg)](https://crates.io/crates/image-webp) +[![Documentation](https://docs.rs/image-webp/badge.svg)](https://docs.rs/image-webp) +[![Build Status](https://github.com/image-rs/image-webp/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-webp/actions) + +This crate is an independent implementation of the WebP image format, written so +that the `image` crate can have a pure-Rust WebP backend for both encoding and +decoding. + +## Current Status + +* **Decoder:** Supports all WebP format features including both lossless and + lossy compression, alpha channel, and animation. Both the "simple" and + "extended" formats are handled, and it exposes methods to extract ICC, EXIF, + and XMP chunks. Decoding speed is generally in the range of **70-100%** of the + speed of libwebp. + +* **Encoder:** This crate only supports lossless encoding. The encoder + implementation is relatively basic which makes it very fast, but it doesn't + get as good compression ratios as libwebp can. Nonetheless, it often produces + smaller files than PNG, even when compared against the slowest/highest + compression options of PNG encoders. + +## Future possibilities + +* We continue to be interested in **optimizations** and **bug fixes** and hope + the bring the decoder closer to parity with libwebp. + +* Another potential area is **animation encoding**. Much of the groundwork is in + place for this, but it will require some additional work to implement. + +* We would like to add **lossy encoding** support, but this is a non-trivial + task and would require a lot of work. If you are interested in helping with + this, please get in touch! + +## Unsafe code + +Both this crate and all of its dependencies currently contain no unsafe code. + +NOTE: This isn't a guarantee that unsafe code will never be added. It may prove +necessary in the future to improve performance, but we will always strive to +minimize the use of unsafe code and ensure that it is well-tested and +documented. + +``` +$ cargo geiger + +Metric output format: x/y + x = unsafe code used by the build + y = total unsafe code found in the crate + +Symbols: + 🔒 = No `unsafe` usage found, declares #![forbid(unsafe_code)] + ❓ = No `unsafe` usage found, missing #![forbid(unsafe_code)] + ☢️ = `unsafe` usage found + +Functions Expressions Impls Traits Methods Dependency + +0/0 0/0 0/0 0/0 0/0 🔒 image-webp 0.2.3 +0/0 0/0 0/0 0/0 0/0 🔒 ├── byteorder-lite 0.1.0 +0/0 0/0 0/0 0/0 0/0 ❓ └── quick-error 2.0.1 + +0/0 0/0 0/0 0/0 0/0 +``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/alpha_blending.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/alpha_blending.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/alpha_blending.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/alpha_blending.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,130 @@ +//! Optimized alpha blending routines based on libwebp +//! +//! + +const fn channel_shift(i: u32) -> u32 { + i * 8 +} + +/// Blend a single channel of `src` over `dst`, given their alpha channel values. +/// `src` and `dst` are assumed to be NOT pre-multiplied by alpha. +fn blend_channel_nonpremult( + src: u32, + src_a: u8, + dst: u32, + dst_a: u8, + scale: u32, + shift: u32, +) -> u8 { + let src_channel = ((src >> shift) & 0xff) as u8; + let dst_channel = ((dst >> shift) & 0xff) as u8; + let blend_unscaled = + (u32::from(src_channel) * u32::from(src_a)) + (u32::from(dst_channel) * u32::from(dst_a)); + debug_assert!(u64::from(blend_unscaled) < (1u64 << 32) / u64::from(scale)); + ((blend_unscaled * scale) >> channel_shift(3)) as u8 +} + +/// Blend `src` over `dst` assuming they are NOT pre-multiplied by alpha. +fn blend_pixel_nonpremult(src: u32, dst: u32) -> u32 { + let src_a = ((src >> channel_shift(3)) & 0xff) as u8; + + if src_a == 0 { + dst + } else { + let dst_a = ((dst >> channel_shift(3)) & 0xff) as u8; + // Approximate integer arithmetic for: dst_factor_a = (dst_a * (255 - src_a)) / 255 + // libwebp used the following formula here: + //let dst_factor_a = (dst_a as u32 * (256 - src_a as u32)) >> 8; + // however, we've found that we can use a more precise approximation without losing performance: + let dst_factor_a = div_by_255(u32::from(dst_a) * (255 - u32::from(src_a))); + let blend_a = u32::from(src_a) + dst_factor_a; + let scale = (1u32 << 24) / blend_a; + + let blend_r = + blend_channel_nonpremult(src, src_a, dst, dst_factor_a as u8, scale, channel_shift(0)); + let blend_g = + blend_channel_nonpremult(src, src_a, dst, dst_factor_a as u8, scale, channel_shift(1)); + let blend_b = + blend_channel_nonpremult(src, src_a, dst, dst_factor_a as u8, scale, channel_shift(2)); + debug_assert!(u32::from(src_a) + dst_factor_a < 256); + + (u32::from(blend_r) << channel_shift(0)) + | (u32::from(blend_g) << channel_shift(1)) + | (u32::from(blend_b) << channel_shift(2)) + | (blend_a << channel_shift(3)) + } +} + +pub(crate) fn do_alpha_blending(buffer: [u8; 4], canvas: [u8; 4]) -> [u8; 4] { + // The original C code contained different shift functions for different endianness, + // but they didn't work when ported to Rust directly (and probably didn't work in C either). + // So instead we reverse the order of bytes on big-endian here, at the interface. + // `from_le_bytes` is a no-op on little endian (most systems) and a cheap shuffle on big endian. + blend_pixel_nonpremult(u32::from_le_bytes(buffer), u32::from_le_bytes(canvas)).to_le_bytes() +} + +/// Divides by 255, rounding to nearest (as opposed to down, like regular integer division does). +/// TODO: cannot output 256, so the output is effecitively u8. Plumb that through the code. +// +// Sources: +// https://arxiv.org/pdf/2202.02864 +// https://github.com/image-rs/image-webp/issues/119#issuecomment-2544007820 +#[inline] +const fn div_by_255(v: u32) -> u32 { + (((v + 0x80) >> 8) + v + 0x80) >> 8 +} + +#[cfg(test)] +mod tests { + use super::*; + + fn do_alpha_blending_reference(buffer: [u8; 4], canvas: [u8; 4]) -> [u8; 4] { + let canvas_alpha = f64::from(canvas[3]); + let buffer_alpha = f64::from(buffer[3]); + let blend_alpha_f64 = buffer_alpha + canvas_alpha * (1.0 - buffer_alpha / 255.0); + //value should be between 0 and 255, this truncates the fractional part + let blend_alpha: u8 = blend_alpha_f64 as u8; + + let blend_rgb: [u8; 3] = if blend_alpha == 0 { + [0, 0, 0] + } else { + let mut rgb = [0u8; 3]; + for i in 0..3 { + let canvas_f64 = f64::from(canvas[i]); + let buffer_f64 = f64::from(buffer[i]); + + let val = (buffer_f64 * buffer_alpha + + canvas_f64 * canvas_alpha * (1.0 - buffer_alpha / 255.0)) + / blend_alpha_f64; + //value should be between 0 and 255, this truncates the fractional part + rgb[i] = val as u8; + } + + rgb + }; + + [blend_rgb[0], blend_rgb[1], blend_rgb[2], blend_alpha] + } + + #[test] + #[ignore] // takes too long to run on CI. Run this locally when changing the function. + fn alpha_blending_optimization() { + for r1 in 0..u8::MAX { + for a1 in 11..u8::MAX { + for r2 in 0..u8::MAX { + for a2 in 11..u8::MAX { + let opt = do_alpha_blending([r1, 0, 0, a1], [r2, 0, 0, a2]); + let slow = do_alpha_blending_reference([r1, 0, 0, a1], [r2, 0, 0, a2]); + // libwebp doesn't do exact blending and so we don't either + for (o, s) in opt.iter().zip(slow.iter()) { + assert!( + o.abs_diff(*s) <= 3, + "Mismatch in results! opt: {opt:?}, slow: {slow:?}, blended values: [{r1}, 0, 0, {a1}], [{r2}, 0, 0, {a2}]" + ); + } + } + } + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,1030 @@ +use byteorder_lite::{LittleEndian, ReadBytesExt}; +use quick_error::quick_error; + +use std::collections::HashMap; +use std::io::{self, BufRead, Cursor, Read, Seek}; +use std::num::NonZeroU16; +use std::ops::Range; + +use crate::extended::{self, get_alpha_predictor, read_alpha_chunk, WebPExtendedInfo}; + +use super::lossless::LosslessDecoder; +use super::vp8::Vp8Decoder; + +quick_error! { + /// Errors that can occur when attempting to decode a WebP image + #[derive(Debug)] + #[non_exhaustive] + pub enum DecodingError { + /// An IO error occurred while reading the file + IoError(err: io::Error) { + from() + display("IO Error: {}", err) + source(err) + } + + /// RIFF's "RIFF" signature not found or invalid + RiffSignatureInvalid(err: [u8; 4]) { + display("Invalid RIFF signature: {err:x?}") + } + + /// WebP's "WEBP" signature not found or invalid + WebpSignatureInvalid(err: [u8; 4]) { + display("Invalid WebP signature: {err:x?}") + } + + /// An expected chunk was missing + ChunkMissing { + display("An expected chunk was missing") + } + + /// Chunk Header was incorrect or invalid in its usage + ChunkHeaderInvalid(err: [u8; 4]) { + display("Invalid Chunk header: {err:x?}") + } + + #[allow(deprecated)] + #[deprecated] + /// Some bits were invalid + ReservedBitSet { + display("Reserved bits set") + } + + /// The ALPH chunk preprocessing info flag was invalid + InvalidAlphaPreprocessing { + display("Alpha chunk preprocessing flag invalid") + } + + /// Invalid compression method + InvalidCompressionMethod { + display("Invalid compression method") + } + + /// Alpha chunk doesn't match the frame's size + AlphaChunkSizeMismatch { + display("Alpha chunk size mismatch") + } + + /// Image is too large, either for the platform's pointer size or generally + ImageTooLarge { + display("Image too large") + } + + /// Frame would go out of the canvas + FrameOutsideImage { + display("Frame outside image") + } + + /// Signature of 0x2f not found + LosslessSignatureInvalid(err: u8) { + display("Invalid lossless signature: {err:x?}") + } + + /// Version Number was not zero + VersionNumberInvalid(err: u8) { + display("Invalid lossless version number: {err}") + } + + /// Invalid color cache bits + InvalidColorCacheBits(err: u8) { + display("Invalid color cache bits: {err}") + } + + /// An invalid Huffman code was encountered + HuffmanError { + display("Invalid Huffman code") + } + + /// The bitstream was somehow corrupt + BitStreamError { + display("Corrupt bitstream") + } + + /// The transforms specified were invalid + TransformError { + display("Invalid transform") + } + + /// VP8's `[0x9D, 0x01, 0x2A]` magic not found or invalid + Vp8MagicInvalid(err: [u8; 3]) { + display("Invalid VP8 magic: {err:x?}") + } + + /// VP8 Decoder initialisation wasn't provided with enough data + NotEnoughInitData { + display("Not enough VP8 init data") + } + + /// At time of writing, only the YUV colour-space encoded as `0` is specified + ColorSpaceInvalid(err: u8) { + display("Invalid VP8 color space: {err}") + } + + /// LUMA prediction mode was not recognised + LumaPredictionModeInvalid(err: i8) { + display("Invalid VP8 luma prediction mode: {err}") + } + + /// Intra-prediction mode was not recognised + IntraPredictionModeInvalid(err: i8) { + display("Invalid VP8 intra prediction mode: {err}") + } + + /// Chroma prediction mode was not recognised + ChromaPredictionModeInvalid(err: i8) { + display("Invalid VP8 chroma prediction mode: {err}") + } + + /// Inconsistent image sizes + InconsistentImageSizes { + display("Inconsistent image sizes") + } + + /// The file may be valid, but this crate doesn't support decoding it. + UnsupportedFeature(err: String) { + display("Unsupported feature: {err}") + } + + /// Invalid function call or parameter + InvalidParameter(err: String) { + display("Invalid parameter: {err}") + } + + /// Memory limit exceeded + MemoryLimitExceeded { + display("Memory limit exceeded") + } + + /// Invalid chunk size + InvalidChunkSize { + display("Invalid chunk size") + } + + /// No more frames in image + NoMoreFrames { + display("No more frames") + } + } +} + +/// All possible RIFF chunks in a WebP image file +#[allow(clippy::upper_case_acronyms)] +#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)] +pub(crate) enum WebPRiffChunk { + RIFF, + WEBP, + VP8, + VP8L, + VP8X, + ANIM, + ANMF, + ALPH, + ICCP, + EXIF, + XMP, + Unknown([u8; 4]), +} + +impl WebPRiffChunk { + pub(crate) const fn from_fourcc(chunk_fourcc: [u8; 4]) -> Self { + match &chunk_fourcc { + b"RIFF" => Self::RIFF, + b"WEBP" => Self::WEBP, + b"VP8 " => Self::VP8, + b"VP8L" => Self::VP8L, + b"VP8X" => Self::VP8X, + b"ANIM" => Self::ANIM, + b"ANMF" => Self::ANMF, + b"ALPH" => Self::ALPH, + b"ICCP" => Self::ICCP, + b"EXIF" => Self::EXIF, + b"XMP " => Self::XMP, + _ => Self::Unknown(chunk_fourcc), + } + } + + pub(crate) const fn to_fourcc(self) -> [u8; 4] { + match self { + Self::RIFF => *b"RIFF", + Self::WEBP => *b"WEBP", + Self::VP8 => *b"VP8 ", + Self::VP8L => *b"VP8L", + Self::VP8X => *b"VP8X", + Self::ANIM => *b"ANIM", + Self::ANMF => *b"ANMF", + Self::ALPH => *b"ALPH", + Self::ICCP => *b"ICCP", + Self::EXIF => *b"EXIF", + Self::XMP => *b"XMP ", + Self::Unknown(fourcc) => fourcc, + } + } + + pub(crate) const fn is_unknown(self) -> bool { + matches!(self, Self::Unknown(_)) + } +} + +// enum WebPImage { +// Lossy(VP8Frame), +// Lossless(LosslessFrame), +// Extended(ExtendedImage), +// } + +enum ImageKind { + Lossy, + Lossless, + Extended(WebPExtendedInfo), +} + +struct AnimationState { + next_frame: u32, + next_frame_start: u64, + dispose_next_frame: bool, + previous_frame_width: u32, + previous_frame_height: u32, + previous_frame_x_offset: u32, + previous_frame_y_offset: u32, + canvas: Option>, +} +impl Default for AnimationState { + fn default() -> Self { + Self { + next_frame: 0, + next_frame_start: 0, + dispose_next_frame: true, + previous_frame_width: 0, + previous_frame_height: 0, + previous_frame_x_offset: 0, + previous_frame_y_offset: 0, + canvas: None, + } + } +} + +/// Number of times that an animation loops. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum LoopCount { + /// The animation loops forever. + Forever, + /// Each frame of the animation is displayed the specified number of times. + Times(NonZeroU16), +} + +/// WebP decoder configuration options +#[derive(Clone)] +#[non_exhaustive] +pub struct WebPDecodeOptions { + /// The upsampling method used in conversion from lossy yuv to rgb + /// + /// Defaults to `Bilinear`. + pub lossy_upsampling: UpsamplingMethod, +} + +impl Default for WebPDecodeOptions { + fn default() -> Self { + Self { + lossy_upsampling: UpsamplingMethod::Bilinear, + } + } +} + +/// Methods for upsampling the chroma values in lossy decoding +/// +/// The chroma red and blue planes are encoded in VP8 as half the size of the luma plane +/// Therefore we need to upsample these values up to fit each pixel in the image. +#[derive(Clone, Copy, Default)] +pub enum UpsamplingMethod { + /// Fancy upsampling + /// + /// Does bilinear interpolation using the 4 values nearest to the pixel, weighting based on the distance + /// from the pixel. + #[default] + Bilinear, + /// Simple upsampling, just uses the closest u/v value to the pixel when upsampling + /// + /// Matches the -nofancy option in dwebp. + /// Should be faster but may lead to slightly jagged edges. + Simple, +} + +/// WebP image format decoder. +pub struct WebPDecoder { + r: R, + memory_limit: usize, + + width: u32, + height: u32, + + kind: ImageKind, + animation: AnimationState, + + is_lossy: bool, + has_alpha: bool, + num_frames: u32, + loop_count: LoopCount, + loop_duration: u64, + + chunks: HashMap>, + + webp_decode_options: WebPDecodeOptions, +} + +impl WebPDecoder { + /// Create a new `WebPDecoder` from the reader `r`. The decoder performs many small reads, so the + /// reader should be buffered. + pub fn new(r: R) -> Result { + Self::new_with_options(r, WebPDecodeOptions::default()) + } + + /// Create a new `WebPDecoder` from the reader `r` with the options `WebPDecodeOptions`. The decoder + /// performs many small reads, so the reader should be buffered. + pub fn new_with_options( + r: R, + webp_decode_options: WebPDecodeOptions, + ) -> Result { + let mut decoder = Self { + r, + width: 0, + height: 0, + num_frames: 0, + kind: ImageKind::Lossy, + chunks: HashMap::new(), + animation: Default::default(), + memory_limit: usize::MAX, + is_lossy: false, + has_alpha: false, + loop_count: LoopCount::Times(NonZeroU16::new(1).unwrap()), + loop_duration: 0, + webp_decode_options, + }; + decoder.read_data()?; + Ok(decoder) + } + + fn read_data(&mut self) -> Result<(), DecodingError> { + let (WebPRiffChunk::RIFF, riff_size, _) = read_chunk_header(&mut self.r)? else { + return Err(DecodingError::ChunkHeaderInvalid(*b"RIFF")); + }; + + match &read_fourcc(&mut self.r)? { + WebPRiffChunk::WEBP => {} + fourcc => return Err(DecodingError::WebpSignatureInvalid(fourcc.to_fourcc())), + } + + let (chunk, chunk_size, chunk_size_rounded) = read_chunk_header(&mut self.r)?; + let start = self.r.stream_position()?; + + match chunk { + WebPRiffChunk::VP8 => { + let tag = self.r.read_u24::()?; + + let keyframe = tag & 1 == 0; + if !keyframe { + return Err(DecodingError::UnsupportedFeature( + "Non-keyframe frames".to_owned(), + )); + } + + let mut tag = [0u8; 3]; + self.r.read_exact(&mut tag)?; + if tag != [0x9d, 0x01, 0x2a] { + return Err(DecodingError::Vp8MagicInvalid(tag)); + } + + let w = self.r.read_u16::()?; + let h = self.r.read_u16::()?; + + self.width = u32::from(w & 0x3FFF); + self.height = u32::from(h & 0x3FFF); + if self.width == 0 || self.height == 0 { + return Err(DecodingError::InconsistentImageSizes); + } + + self.chunks + .insert(WebPRiffChunk::VP8, start..start + chunk_size); + self.kind = ImageKind::Lossy; + self.is_lossy = true; + } + WebPRiffChunk::VP8L => { + let signature = self.r.read_u8()?; + if signature != 0x2f { + return Err(DecodingError::LosslessSignatureInvalid(signature)); + } + + let header = self.r.read_u32::()?; + let version = header >> 29; + if version != 0 { + return Err(DecodingError::VersionNumberInvalid(version as u8)); + } + + self.width = (1 + header) & 0x3FFF; + self.height = (1 + (header >> 14)) & 0x3FFF; + self.chunks + .insert(WebPRiffChunk::VP8L, start..start + chunk_size); + self.kind = ImageKind::Lossless; + self.has_alpha = (header >> 28) & 1 != 0; + } + WebPRiffChunk::VP8X => { + let mut info = extended::read_extended_header(&mut self.r)?; + self.width = info.canvas_width; + self.height = info.canvas_height; + + let mut position = start + chunk_size_rounded; + let max_position = position + riff_size.saturating_sub(12); + self.r.seek(io::SeekFrom::Start(position))?; + + while position < max_position { + match read_chunk_header(&mut self.r) { + Ok((chunk, chunk_size, chunk_size_rounded)) => { + let range = position + 8..position + 8 + chunk_size; + position += 8 + chunk_size_rounded; + + if !chunk.is_unknown() { + self.chunks.entry(chunk).or_insert(range); + } + + if chunk == WebPRiffChunk::ANMF { + self.num_frames += 1; + if chunk_size < 24 { + return Err(DecodingError::InvalidChunkSize); + } + + self.r.seek_relative(12)?; + let duration = self.r.read_u32::()? & 0xffffff; + self.loop_duration = + self.loop_duration.wrapping_add(u64::from(duration)); + + // If the image is animated, the image data chunk will be inside the + // ANMF chunks, so we must inspect them to determine whether the + // image contains any lossy image data. VP8 chunks store lossy data + // and the spec says that lossless images SHOULD NOT contain ALPH + // chunks, so we treat both as indicators of lossy images. + if !self.is_lossy { + let (subchunk, ..) = read_chunk_header(&mut self.r)?; + if let WebPRiffChunk::VP8 | WebPRiffChunk::ALPH = subchunk { + self.is_lossy = true; + } + self.r.seek_relative(chunk_size_rounded as i64 - 24)?; + } else { + self.r.seek_relative(chunk_size_rounded as i64 - 16)?; + } + + continue; + } + + self.r.seek_relative(chunk_size_rounded as i64)?; + } + Err(DecodingError::IoError(e)) + if e.kind() == io::ErrorKind::UnexpectedEof => + { + break; + } + Err(e) => return Err(e), + } + } + self.is_lossy = self.is_lossy || self.chunks.contains_key(&WebPRiffChunk::VP8); + + // NOTE: We allow malformed images that have `info.icc_profile` set without a ICCP chunk, + // because this is relatively common. + if info.animation + && (!self.chunks.contains_key(&WebPRiffChunk::ANIM) + || !self.chunks.contains_key(&WebPRiffChunk::ANMF)) + || info.exif_metadata && !self.chunks.contains_key(&WebPRiffChunk::EXIF) + || info.xmp_metadata && !self.chunks.contains_key(&WebPRiffChunk::XMP) + || !info.animation + && self.chunks.contains_key(&WebPRiffChunk::VP8) + == self.chunks.contains_key(&WebPRiffChunk::VP8L) + { + return Err(DecodingError::ChunkMissing); + } + + // Decode ANIM chunk. + if info.animation { + match self.read_chunk(WebPRiffChunk::ANIM, 6) { + Ok(Some(chunk)) => { + let mut cursor = Cursor::new(chunk); + cursor.read_exact(&mut info.background_color_hint)?; + self.loop_count = match cursor.read_u16::()? { + 0 => LoopCount::Forever, + n => LoopCount::Times(NonZeroU16::new(n).unwrap()), + }; + self.animation.next_frame_start = + self.chunks.get(&WebPRiffChunk::ANMF).unwrap().start - 8; + } + Ok(None) => return Err(DecodingError::ChunkMissing), + Err(DecodingError::MemoryLimitExceeded) => { + return Err(DecodingError::InvalidChunkSize) + } + Err(e) => return Err(e), + } + } + + // If the image is animated, the image data chunk will be inside the ANMF chunks. We + // store the ALPH, VP8, and VP8L chunks (as applicable) of the first frame in the + // hashmap so that we can read them later. + if let Some(range) = self.chunks.get(&WebPRiffChunk::ANMF).cloned() { + let mut position = range.start + 16; + self.r.seek(io::SeekFrom::Start(position))?; + for _ in 0..2 { + let (subchunk, subchunk_size, subchunk_size_rounded) = + read_chunk_header(&mut self.r)?; + let subrange = position + 8..position + 8 + subchunk_size; + self.chunks.entry(subchunk).or_insert(subrange.clone()); + + position += 8 + subchunk_size_rounded; + if position + 8 > range.end { + break; + } + } + } + + self.has_alpha = info.alpha; + self.kind = ImageKind::Extended(info); + } + _ => return Err(DecodingError::ChunkHeaderInvalid(chunk.to_fourcc())), + }; + + Ok(()) + } + + /// Sets the maximum amount of memory that the decoder is allowed to allocate at once. + /// + /// TODO: Some allocations currently ignore this limit. + pub fn set_memory_limit(&mut self, limit: usize) { + self.memory_limit = limit; + } + + /// Get the background color specified in the image file if the image is extended and animated webp. + pub fn background_color_hint(&self) -> Option<[u8; 4]> { + if let ImageKind::Extended(info) = &self.kind { + Some(info.background_color_hint) + } else { + None + } + } + + /// Sets the background color if the image is an extended and animated webp. + pub fn set_background_color(&mut self, color: [u8; 4]) -> Result<(), DecodingError> { + if let ImageKind::Extended(info) = &mut self.kind { + info.background_color = Some(color); + Ok(()) + } else { + Err(DecodingError::InvalidParameter( + "Background color can only be set on animated webp".to_owned(), + )) + } + } + + /// Returns the (width, height) of the image in pixels. + pub fn dimensions(&self) -> (u32, u32) { + (self.width, self.height) + } + + /// Returns whether the image has an alpha channel. If so, the pixel format is Rgba8 and + /// otherwise Rgb8. + pub fn has_alpha(&self) -> bool { + self.has_alpha + } + + /// Returns true if the image is animated. + pub fn is_animated(&self) -> bool { + match &self.kind { + ImageKind::Lossy | ImageKind::Lossless => false, + ImageKind::Extended(extended) => extended.animation, + } + } + + /// Returns whether the image is lossy. For animated images, this is true if any frame is lossy. + pub fn is_lossy(&mut self) -> bool { + self.is_lossy + } + + /// Returns the number of frames of a single loop of the animation, or zero if the image is not + /// animated. + pub fn num_frames(&self) -> u32 { + self.num_frames + } + + /// Returns the number of times the animation should loop. + pub fn loop_count(&self) -> LoopCount { + self.loop_count + } + + /// Returns the total duration of one loop through the animation in milliseconds, or zero if the + /// image is not animated. + /// + /// This is the sum of the durations of all individual frames of the image. + pub fn loop_duration(&self) -> u64 { + self.loop_duration + } + + fn read_chunk( + &mut self, + chunk: WebPRiffChunk, + max_size: usize, + ) -> Result>, DecodingError> { + match self.chunks.get(&chunk) { + Some(range) => { + if range.end - range.start > max_size as u64 { + return Err(DecodingError::MemoryLimitExceeded); + } + + self.r.seek(io::SeekFrom::Start(range.start))?; + let mut data = vec![0; (range.end - range.start) as usize]; + self.r.read_exact(&mut data)?; + Ok(Some(data)) + } + None => Ok(None), + } + } + + /// Returns the raw bytes of the ICC profile, or None if there is no ICC profile. + pub fn icc_profile(&mut self) -> Result>, DecodingError> { + self.read_chunk(WebPRiffChunk::ICCP, self.memory_limit) + } + + /// Returns the raw bytes of the EXIF metadata, or None if there is no EXIF metadata. + pub fn exif_metadata(&mut self) -> Result>, DecodingError> { + self.read_chunk(WebPRiffChunk::EXIF, self.memory_limit) + } + + /// Returns the raw bytes of the XMP metadata, or None if there is no XMP metadata. + pub fn xmp_metadata(&mut self) -> Result>, DecodingError> { + self.read_chunk(WebPRiffChunk::XMP, self.memory_limit) + } + + /// Returns the number of bytes required to store the image or a single frame, or None if that + /// would take more than `usize::MAX` bytes. + pub fn output_buffer_size(&self) -> Option { + let bytes_per_pixel = if self.has_alpha() { 4 } else { 3 }; + (self.width as usize) + .checked_mul(self.height as usize)? + .checked_mul(bytes_per_pixel) + } + + /// Returns the raw bytes of the image. For animated images, this is the first frame. + /// + /// Fails with `ImageTooLarge` if `buf` has length different than `output_buffer_size()` + pub fn read_image(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> { + if Some(buf.len()) != self.output_buffer_size() { + return Err(DecodingError::ImageTooLarge); + } + + if self.is_animated() { + let saved = std::mem::take(&mut self.animation); + self.animation.next_frame_start = + self.chunks.get(&WebPRiffChunk::ANMF).unwrap().start - 8; + let result = self.read_frame(buf); + self.animation = saved; + result?; + } else if let Some(range) = self.chunks.get(&WebPRiffChunk::VP8L) { + let mut decoder = LosslessDecoder::new(range_reader(&mut self.r, range.clone())?); + + if self.has_alpha { + decoder.decode_frame(self.width, self.height, false, buf)?; + } else { + let mut data = vec![0; self.width as usize * self.height as usize * 4]; + decoder.decode_frame(self.width, self.height, false, &mut data)?; + for (rgba_val, chunk) in data.chunks_exact(4).zip(buf.chunks_exact_mut(3)) { + chunk.copy_from_slice(&rgba_val[..3]); + } + } + } else { + let range = self + .chunks + .get(&WebPRiffChunk::VP8) + .ok_or(DecodingError::ChunkMissing)?; + let reader = range_reader(&mut self.r, range.start..range.end)?; + let frame = Vp8Decoder::decode_frame(reader)?; + if u32::from(frame.width) != self.width || u32::from(frame.height) != self.height { + return Err(DecodingError::InconsistentImageSizes); + } + + if self.has_alpha() { + frame.fill_rgba(buf, self.webp_decode_options.lossy_upsampling); + + let range = self + .chunks + .get(&WebPRiffChunk::ALPH) + .ok_or(DecodingError::ChunkMissing)? + .clone(); + let alpha_chunk = read_alpha_chunk( + &mut range_reader(&mut self.r, range)?, + self.width as u16, + self.height as u16, + )?; + + for y in 0..frame.height { + for x in 0..frame.width { + let predictor: u8 = get_alpha_predictor( + x.into(), + y.into(), + frame.width.into(), + alpha_chunk.filtering_method, + buf, + ); + + let alpha_index = + usize::from(y) * usize::from(frame.width) + usize::from(x); + let buffer_index = alpha_index * 4 + 3; + + buf[buffer_index] = predictor.wrapping_add(alpha_chunk.data[alpha_index]); + } + } + } else { + frame.fill_rgb(buf, self.webp_decode_options.lossy_upsampling); + } + } + + Ok(()) + } + + /// Reads the next frame of the animation. + /// + /// The frame contents are written into `buf` and the method returns the duration of the frame + /// in milliseconds. If there are no more frames, the method returns + /// `DecodingError::NoMoreFrames` and `buf` is left unchanged. + /// + /// # Panics + /// + /// Panics if the image is not animated. + pub fn read_frame(&mut self, buf: &mut [u8]) -> Result { + assert!(self.is_animated()); + assert_eq!(Some(buf.len()), self.output_buffer_size()); + + if self.animation.next_frame == self.num_frames { + return Err(DecodingError::NoMoreFrames); + } + + let ImageKind::Extended(info) = &self.kind else { + unreachable!() + }; + + self.r + .seek(io::SeekFrom::Start(self.animation.next_frame_start))?; + + let anmf_size = match read_chunk_header(&mut self.r)? { + (WebPRiffChunk::ANMF, size, _) if size >= 32 => size, + _ => return Err(DecodingError::ChunkHeaderInvalid(*b"ANMF")), + }; + + // Read ANMF chunk + let frame_x = extended::read_3_bytes(&mut self.r)? * 2; + let frame_y = extended::read_3_bytes(&mut self.r)? * 2; + let frame_width = extended::read_3_bytes(&mut self.r)? + 1; + let frame_height = extended::read_3_bytes(&mut self.r)? + 1; + if frame_width > 16384 || frame_height > 16384 { + return Err(DecodingError::ImageTooLarge); + } + if frame_x + frame_width > self.width || frame_y + frame_height > self.height { + return Err(DecodingError::FrameOutsideImage); + } + let duration = extended::read_3_bytes(&mut self.r)?; + let frame_info = self.r.read_u8()?; + let use_alpha_blending = frame_info & 0b00000010 == 0; + let dispose = frame_info & 0b00000001 != 0; + + let clear_color = if self.animation.dispose_next_frame { + info.background_color + } else { + None + }; + + // Read normal bitstream now + let (chunk, chunk_size, chunk_size_rounded) = read_chunk_header(&mut self.r)?; + if chunk_size_rounded + 24 > anmf_size { + return Err(DecodingError::ChunkHeaderInvalid(chunk.to_fourcc())); + } + + let (frame, frame_has_alpha): (Vec, bool) = match chunk { + WebPRiffChunk::VP8 => { + let reader = (&mut self.r).take(chunk_size); + let raw_frame = Vp8Decoder::decode_frame(reader)?; + if u32::from(raw_frame.width) != frame_width + || u32::from(raw_frame.height) != frame_height + { + return Err(DecodingError::InconsistentImageSizes); + } + let mut rgb_frame = vec![0; frame_width as usize * frame_height as usize * 3]; + raw_frame.fill_rgb(&mut rgb_frame, self.webp_decode_options.lossy_upsampling); + (rgb_frame, false) + } + WebPRiffChunk::VP8L => { + let reader = (&mut self.r).take(chunk_size); + let mut lossless_decoder = LosslessDecoder::new(reader); + let mut rgba_frame = vec![0; frame_width as usize * frame_height as usize * 4]; + lossless_decoder.decode_frame(frame_width, frame_height, false, &mut rgba_frame)?; + (rgba_frame, true) + } + WebPRiffChunk::ALPH => { + if chunk_size_rounded + 32 > anmf_size { + return Err(DecodingError::ChunkHeaderInvalid(chunk.to_fourcc())); + } + + // read alpha + let next_chunk_start = self.r.stream_position()? + chunk_size_rounded; + let mut reader = (&mut self.r).take(chunk_size); + let alpha_chunk = + read_alpha_chunk(&mut reader, frame_width as u16, frame_height as u16)?; + + // read opaque + self.r.seek(io::SeekFrom::Start(next_chunk_start))?; + let (next_chunk, next_chunk_size, _) = read_chunk_header(&mut self.r)?; + if chunk_size + next_chunk_size + 32 > anmf_size { + return Err(DecodingError::ChunkHeaderInvalid(next_chunk.to_fourcc())); + } + + let frame = Vp8Decoder::decode_frame((&mut self.r).take(next_chunk_size))?; + + let mut rgba_frame = vec![0; frame_width as usize * frame_height as usize * 4]; + frame.fill_rgba(&mut rgba_frame, self.webp_decode_options.lossy_upsampling); + + for y in 0..frame.height { + for x in 0..frame.width { + let predictor: u8 = get_alpha_predictor( + x.into(), + y.into(), + frame.width.into(), + alpha_chunk.filtering_method, + &rgba_frame, + ); + + let alpha_index = + usize::from(y) * usize::from(frame.width) + usize::from(x); + let buffer_index = alpha_index * 4 + 3; + + rgba_frame[buffer_index] = + predictor.wrapping_add(alpha_chunk.data[alpha_index]); + } + } + + (rgba_frame, true) + } + _ => return Err(DecodingError::ChunkHeaderInvalid(chunk.to_fourcc())), + }; + + // fill starting canvas with clear color + if self.animation.canvas.is_none() { + self.animation.canvas = { + let mut canvas = vec![0; (self.width * self.height * 4) as usize]; + if let Some(color) = info.background_color.as_ref() { + canvas + .chunks_exact_mut(4) + .for_each(|c| c.copy_from_slice(color)) + } + Some(canvas) + } + } + extended::composite_frame( + self.animation.canvas.as_mut().unwrap(), + self.width, + self.height, + clear_color, + &frame, + frame_x, + frame_y, + frame_width, + frame_height, + frame_has_alpha, + use_alpha_blending, + self.animation.previous_frame_width, + self.animation.previous_frame_height, + self.animation.previous_frame_x_offset, + self.animation.previous_frame_y_offset, + ); + + self.animation.previous_frame_width = frame_width; + self.animation.previous_frame_height = frame_height; + self.animation.previous_frame_x_offset = frame_x; + self.animation.previous_frame_y_offset = frame_y; + + self.animation.dispose_next_frame = dispose; + self.animation.next_frame_start += anmf_size + 8; + self.animation.next_frame += 1; + + if self.has_alpha() { + buf.copy_from_slice(self.animation.canvas.as_ref().unwrap()); + } else { + for (b, c) in buf + .chunks_exact_mut(3) + .zip(self.animation.canvas.as_ref().unwrap().chunks_exact(4)) + { + b.copy_from_slice(&c[..3]); + } + } + + Ok(duration) + } + + /// Resets the animation to the first frame. + /// + /// # Panics + /// + /// Panics if the image is not animated. + pub fn reset_animation(&mut self) { + assert!(self.is_animated()); + + self.animation.next_frame = 0; + self.animation.next_frame_start = self.chunks.get(&WebPRiffChunk::ANMF).unwrap().start - 8; + self.animation.dispose_next_frame = true; + } + + /// Sets the upsampling method that is used in lossy decoding + pub fn set_lossy_upsampling(&mut self, upsampling_method: UpsamplingMethod) { + self.webp_decode_options.lossy_upsampling = upsampling_method; + } +} + +pub(crate) fn range_reader( + mut r: R, + range: Range, +) -> Result { + r.seek(io::SeekFrom::Start(range.start))?; + Ok(r.take(range.end - range.start)) +} + +pub(crate) fn read_fourcc(mut r: R) -> Result { + let mut chunk_fourcc = [0; 4]; + r.read_exact(&mut chunk_fourcc)?; + Ok(WebPRiffChunk::from_fourcc(chunk_fourcc)) +} + +pub(crate) fn read_chunk_header( + mut r: R, +) -> Result<(WebPRiffChunk, u64, u64), DecodingError> { + let chunk = read_fourcc(&mut r)?; + let chunk_size = r.read_u32::()?; + let chunk_size_rounded = chunk_size.saturating_add(chunk_size & 1); + Ok((chunk, chunk_size.into(), chunk_size_rounded.into())) +} + +#[cfg(test)] +mod tests { + use super::*; + const RGB_BPP: usize = 3; + + #[test] + fn add_with_overflow_size() { + let bytes = vec![ + 0x52, 0x49, 0x46, 0x46, 0xaf, 0x37, 0x80, 0x47, 0x57, 0x45, 0x42, 0x50, 0x6c, 0x64, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7e, 0x73, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, + 0x40, 0xfb, 0xff, 0xff, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x49, 0x54, 0x55, 0x50, 0x4c, 0x54, 0x59, 0x50, 0x45, 0x33, 0x37, 0x44, 0x4d, 0x46, + ]; + + let data = std::io::Cursor::new(bytes); + + let _ = WebPDecoder::new(data); + } + + #[test] + fn decode_2x2_single_color_image() { + // Image data created from imagemagick and output of xxd: + // $ convert -size 2x2 xc:#f00 red.webp + // $ xxd -g 1 red.webp | head + + const NUM_PIXELS: usize = 2 * 2 * RGB_BPP; + // 2x2 red pixel image + let bytes = [ + 0x52, 0x49, 0x46, 0x46, 0x3c, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, + 0x38, 0x20, 0x30, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x34, 0x25, 0xa0, 0x02, 0x74, 0xba, 0x01, 0xf8, 0x00, 0x03, + 0xb0, 0x00, 0xfe, 0xf0, 0xc4, 0x0b, 0xff, 0x20, 0xb9, 0x61, 0x75, 0xc8, 0xd7, 0xff, + 0x20, 0x3f, 0xe4, 0x07, 0xfc, 0x80, 0xff, 0xf8, 0xf2, 0x00, 0x00, 0x00, + ]; + + let mut data = [0; NUM_PIXELS]; + let mut decoder = WebPDecoder::new(std::io::Cursor::new(bytes)).unwrap(); + decoder.read_image(&mut data).unwrap(); + + // All pixels are the same value + let first_pixel = &data[..RGB_BPP]; + assert!(data.chunks_exact(3).all(|ch| ch.iter().eq(first_pixel))); + } + + #[test] + fn decode_3x3_single_color_image() { + // Test that any odd pixel "tail" is decoded properly + + const NUM_PIXELS: usize = 3 * 3 * RGB_BPP; + // 3x3 red pixel image + let bytes = [ + 0x52, 0x49, 0x46, 0x46, 0x3c, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, + 0x38, 0x20, 0x30, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x34, 0x25, 0xa0, 0x02, 0x74, 0xba, 0x01, 0xf8, 0x00, 0x03, + 0xb0, 0x00, 0xfe, 0xf0, 0xc4, 0x0b, 0xff, 0x20, 0xb9, 0x61, 0x75, 0xc8, 0xd7, 0xff, + 0x20, 0x3f, 0xe4, 0x07, 0xfc, 0x80, 0xff, 0xf8, 0xf2, 0x00, 0x00, 0x00, + ]; + + let mut data = [0; NUM_PIXELS]; + let mut decoder = WebPDecoder::new(std::io::Cursor::new(bytes)).unwrap(); + decoder.read_image(&mut data).unwrap(); + + // All pixels are the same value + let first_pixel = &data[..RGB_BPP]; + assert!(data.chunks_exact(3).all(|ch| ch.iter().eq(first_pixel))); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/encoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/encoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/encoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/encoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,855 @@ +//! Encoding of WebP images. +use std::collections::BinaryHeap; +use std::io::{self, Write}; +use std::slice::ChunksExact; + +use quick_error::quick_error; + +/// Color type of the image. +/// +/// Note that the WebP format doesn't have a concept of color type. All images are encoded as RGBA +/// and some decoders may treat them as such. This enum is used to indicate the color type of the +/// input data provided to the encoder, which can help improve compression ratio. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorType { + /// Opaque image with a single luminance byte per pixel. + L8, + /// Image with a luminance and alpha byte per pixel. + La8, + /// Opaque image with a red, green, and blue byte per pixel. + Rgb8, + /// Image with a red, green, blue, and alpha byte per pixel. + Rgba8, +} + +quick_error! { + /// Error that can occur during encoding. + #[derive(Debug)] + #[non_exhaustive] + pub enum EncodingError { + /// An IO error occurred. + IoError(err: io::Error) { + from() + display("IO error: {}", err) + source(err) + } + + /// The image dimensions are not allowed by the WebP format. + InvalidDimensions { + display("Invalid dimensions") + } + } +} + +struct BitWriter { + writer: W, + buffer: u64, + nbits: u8, +} + +impl BitWriter { + fn write_bits(&mut self, bits: u64, nbits: u8) -> io::Result<()> { + debug_assert!(nbits <= 64); + + self.buffer |= bits << self.nbits; + self.nbits += nbits; + + if self.nbits >= 64 { + self.writer.write_all(&self.buffer.to_le_bytes())?; + self.nbits -= 64; + self.buffer = bits.checked_shr(u32::from(nbits - self.nbits)).unwrap_or(0); + } + debug_assert!(self.nbits < 64); + Ok(()) + } + + fn flush(&mut self) -> io::Result<()> { + if self.nbits % 8 != 0 { + self.write_bits(0, 8 - self.nbits % 8)?; + } + if self.nbits > 0 { + self.writer + .write_all(&self.buffer.to_le_bytes()[..self.nbits as usize / 8]) + .unwrap(); + self.buffer = 0; + self.nbits = 0; + } + Ok(()) + } +} + +fn write_single_entry_huffman_tree(w: &mut BitWriter, symbol: u8) -> io::Result<()> { + w.write_bits(1, 2)?; + if symbol <= 1 { + w.write_bits(0, 1)?; + w.write_bits(u64::from(symbol), 1)?; + } else { + w.write_bits(1, 1)?; + w.write_bits(u64::from(symbol), 8)?; + } + Ok(()) +} + +fn build_huffman_tree( + frequencies: &[u32], + lengths: &mut [u8], + codes: &mut [u16], + length_limit: u8, +) -> bool { + assert_eq!(frequencies.len(), lengths.len()); + assert_eq!(frequencies.len(), codes.len()); + + if frequencies.iter().filter(|&&f| f > 0).count() <= 1 { + lengths.fill(0); + codes.fill(0); + return false; + } + + #[derive(Eq, PartialEq, Copy, Clone, Debug)] + struct Item(u32, u16); + impl Ord for Item { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + other.0.cmp(&self.0) + } + } + impl PartialOrd for Item { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + // Build a huffman tree + let mut internal_nodes = Vec::new(); + let mut nodes = BinaryHeap::from_iter( + frequencies + .iter() + .enumerate() + .filter(|(_, &frequency)| frequency > 0) + .map(|(i, &frequency)| Item(frequency, i as u16)), + ); + while nodes.len() > 1 { + let Item(frequency1, index1) = nodes.pop().unwrap(); + let mut root = nodes.peek_mut().unwrap(); + internal_nodes.push((index1, root.1)); + *root = Item( + frequency1 + root.0, + internal_nodes.len() as u16 + frequencies.len() as u16 - 1, + ); + } + + // Walk the tree to assign code lengths + lengths.fill(0); + let mut stack = Vec::new(); + stack.push((nodes.pop().unwrap().1, 0)); + while let Some((node, depth)) = stack.pop() { + let node = node as usize; + if node < frequencies.len() { + lengths[node] = depth as u8; + } else { + let (left, right) = internal_nodes[node - frequencies.len()]; + stack.push((left, depth + 1)); + stack.push((right, depth + 1)); + } + } + + // Limit the codes to length length_limit + let mut max_length = 0; + for &length in lengths.iter() { + max_length = max_length.max(length); + } + if max_length > length_limit { + let mut counts = [0u32; 16]; + for &length in lengths.iter() { + counts[length.min(length_limit) as usize] += 1; + } + + let mut total = 0; + for (i, count) in counts + .iter() + .enumerate() + .skip(1) + .take(length_limit as usize) + { + total += count << (length_limit as usize - i); + } + + while total > 1u32 << length_limit { + let mut i = length_limit as usize - 1; + while counts[i] == 0 { + i -= 1; + } + counts[i] -= 1; + counts[length_limit as usize] -= 1; + counts[i + 1] += 2; + total -= 1; + } + + // assign new lengths + let mut len = length_limit; + let mut indexes = frequencies.iter().copied().enumerate().collect::>(); + indexes.sort_unstable_by_key(|&(_, frequency)| frequency); + for &(i, frequency) in &indexes { + if frequency > 0 { + while counts[len as usize] == 0 { + len -= 1; + } + lengths[i] = len; + counts[len as usize] -= 1; + } + } + } + + // Assign codes + codes.fill(0); + let mut code = 0u32; + for len in 1..=length_limit { + for (i, &length) in lengths.iter().enumerate() { + if length == len { + codes[i] = (code as u16).reverse_bits() >> (16 - len); + code += 1; + } + } + code <<= 1; + } + assert_eq!(code, 2 << length_limit); + + true +} + +fn write_huffman_tree( + w: &mut BitWriter, + frequencies: &[u32], + lengths: &mut [u8], + codes: &mut [u16], +) -> io::Result<()> { + if !build_huffman_tree(frequencies, lengths, codes, 15) { + let symbol = frequencies + .iter() + .position(|&frequency| frequency > 0) + .unwrap_or(0); + return write_single_entry_huffman_tree(w, symbol as u8); + } + + let mut code_length_lengths = [0u8; 16]; + let mut code_length_codes = [0u16; 16]; + let mut code_length_frequencies = [0u32; 16]; + for &length in lengths.iter() { + code_length_frequencies[length as usize] += 1; + } + let single_code_length_length = !build_huffman_tree( + &code_length_frequencies, + &mut code_length_lengths, + &mut code_length_codes, + 7, + ); + + const CODE_LENGTH_ORDER: [usize; 19] = [ + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + ]; + + // Write the huffman tree + w.write_bits(0, 1)?; // normal huffman tree + w.write_bits(19 - 4, 4)?; // num_code_lengths - 4 + + for i in CODE_LENGTH_ORDER { + if i > 15 || code_length_frequencies[i] == 0 { + w.write_bits(0, 3)?; + } else if single_code_length_length { + w.write_bits(1, 3)?; + } else { + w.write_bits(u64::from(code_length_lengths[i]), 3)?; + } + } + + match lengths.len() { + 256 => { + w.write_bits(1, 1)?; // max_symbol is stored + w.write_bits(3, 3)?; // max_symbol_nbits / 2 - 2 + w.write_bits(254, 8)?; // max_symbol - 2 + } + 280 => w.write_bits(0, 1)?, + _ => unreachable!(), + } + + // Write the huffman codes + if !single_code_length_length { + for &len in lengths.iter() { + w.write_bits( + u64::from(code_length_codes[len as usize]), + code_length_lengths[len as usize], + )?; + } + } + + Ok(()) +} + +const fn length_to_symbol(len: u16) -> (u16, u8) { + let len = len - 1; + let highest_bit = len.ilog2() as u16; + let second_highest_bit = (len >> (highest_bit - 1)) & 1; + let extra_bits = highest_bit - 1; + let symbol = 2 * highest_bit + second_highest_bit; + (symbol, extra_bits as u8) +} + +#[inline(always)] +fn count_run( + pixel: &[u8], + it: &mut std::iter::Peekable>, + frequencies1: &mut [u32; 280], +) { + let mut run_length = 0; + while run_length < 4096 && it.peek() == Some(&pixel) { + run_length += 1; + it.next(); + } + if run_length > 0 { + if run_length <= 4 { + let symbol = 256 + run_length - 1; + frequencies1[symbol] += 1; + } else { + let (symbol, _extra_bits) = length_to_symbol(run_length as u16); + frequencies1[256 + symbol as usize] += 1; + } + } +} + +#[inline(always)] +fn write_run( + w: &mut BitWriter, + pixel: &[u8], + it: &mut std::iter::Peekable>, + codes1: &[u16; 280], + lengths1: &[u8; 280], +) -> io::Result<()> { + let mut run_length = 0; + while run_length < 4096 && it.peek() == Some(&pixel) { + run_length += 1; + it.next(); + } + if run_length > 0 { + if run_length <= 4 { + let symbol = 256 + run_length - 1; + w.write_bits(u64::from(codes1[symbol]), lengths1[symbol])?; + } else { + let (symbol, extra_bits) = length_to_symbol(run_length as u16); + w.write_bits( + u64::from(codes1[256 + symbol as usize]), + lengths1[256 + symbol as usize], + )?; + w.write_bits( + (run_length as u64 - 1) & ((1 << extra_bits) - 1), + extra_bits, + )?; + } + } + Ok(()) +} + +/// Allows fine-tuning some encoder parameters. +/// +/// Pass to [`WebPEncoder::set_params()`]. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct EncoderParams { + /// Use a predictor transform. Enabled by default. + pub use_predictor_transform: bool, +} + +impl Default for EncoderParams { + fn default() -> Self { + Self { + use_predictor_transform: true, + } + } +} + +/// Encode image data with the indicated color type. +/// +/// # Panics +/// +/// Panics if the image data is not of the indicated dimensions. +fn encode_frame( + writer: W, + data: &[u8], + width: u32, + height: u32, + color: ColorType, + params: EncoderParams, +) -> Result<(), EncodingError> { + let w = &mut BitWriter { + writer, + buffer: 0, + nbits: 0, + }; + + let (is_color, is_alpha, bytes_per_pixel) = match color { + ColorType::L8 => (false, false, 1), + ColorType::La8 => (false, true, 2), + ColorType::Rgb8 => (true, false, 3), + ColorType::Rgba8 => (true, true, 4), + }; + + assert_eq!( + (u64::from(width) * u64::from(height)).saturating_mul(bytes_per_pixel), + data.len() as u64 + ); + + if width == 0 || width > 16384 || height == 0 || height > 16384 { + return Err(EncodingError::InvalidDimensions); + } + + w.write_bits(0x2f, 8)?; // signature + w.write_bits(u64::from(width) - 1, 14)?; + w.write_bits(u64::from(height) - 1, 14)?; + + w.write_bits(u64::from(is_alpha), 1)?; // alpha used + w.write_bits(0x0, 3)?; // version + + // subtract green transform + w.write_bits(0b101, 3)?; + + // predictor transform + if params.use_predictor_transform { + w.write_bits(0b111001, 6)?; + w.write_bits(0x0, 1)?; // no color cache + write_single_entry_huffman_tree(w, 2)?; + for _ in 0..4 { + write_single_entry_huffman_tree(w, 0)?; + } + } + + // transforms done + w.write_bits(0x0, 1)?; + + // color cache + w.write_bits(0x0, 1)?; + + // meta-huffman codes + w.write_bits(0x0, 1)?; + + // expand to RGBA + let mut pixels = match color { + ColorType::L8 => data.iter().flat_map(|&p| [p, p, p, 255]).collect(), + ColorType::La8 => data + .chunks_exact(2) + .flat_map(|p| [p[0], p[0], p[0], p[1]]) + .collect(), + ColorType::Rgb8 => data + .chunks_exact(3) + .flat_map(|p| [p[0], p[1], p[2], 255]) + .collect(), + ColorType::Rgba8 => data.to_vec(), + }; + + // compute subtract green transform + for pixel in pixels.chunks_exact_mut(4) { + pixel[0] = pixel[0].wrapping_sub(pixel[1]); + pixel[2] = pixel[2].wrapping_sub(pixel[1]); + } + + // compute predictor transform + if params.use_predictor_transform { + let row_bytes = width as usize * 4; + for y in (1..height as usize).rev() { + let (prev, current) = + pixels[(y - 1) * row_bytes..][..row_bytes * 2].split_at_mut(row_bytes); + for (c, p) in current.iter_mut().zip(prev) { + *c = c.wrapping_sub(*p); + } + } + for i in (4..row_bytes).rev() { + pixels[i] = pixels[i].wrapping_sub(pixels[i - 4]); + } + pixels[3] = pixels[3].wrapping_sub(255); + } + + // compute frequencies + let mut frequencies0 = [0u32; 256]; + let mut frequencies1 = [0u32; 280]; + let mut frequencies2 = [0u32; 256]; + let mut frequencies3 = [0u32; 256]; + let mut it = pixels.chunks_exact(4).peekable(); + match color { + ColorType::L8 => { + frequencies0[0] = 1; + frequencies2[0] = 1; + frequencies3[0] = 1; + while let Some(pixel) = it.next() { + frequencies1[pixel[1] as usize] += 1; + count_run(pixel, &mut it, &mut frequencies1); + } + } + ColorType::La8 => { + frequencies0[0] = 1; + frequencies2[0] = 1; + while let Some(pixel) = it.next() { + frequencies1[pixel[1] as usize] += 1; + frequencies3[pixel[3] as usize] += 1; + count_run(pixel, &mut it, &mut frequencies1); + } + } + ColorType::Rgb8 => { + frequencies3[0] = 1; + while let Some(pixel) = it.next() { + frequencies0[pixel[0] as usize] += 1; + frequencies1[pixel[1] as usize] += 1; + frequencies2[pixel[2] as usize] += 1; + count_run(pixel, &mut it, &mut frequencies1); + } + } + ColorType::Rgba8 => { + while let Some(pixel) = it.next() { + frequencies0[pixel[0] as usize] += 1; + frequencies1[pixel[1] as usize] += 1; + frequencies2[pixel[2] as usize] += 1; + frequencies3[pixel[3] as usize] += 1; + count_run(pixel, &mut it, &mut frequencies1); + } + } + } + + // compute and write huffman codes + let mut lengths0 = [0u8; 256]; + let mut lengths1 = [0u8; 280]; + let mut lengths2 = [0u8; 256]; + let mut lengths3 = [0u8; 256]; + let mut codes0 = [0u16; 256]; + let mut codes1 = [0u16; 280]; + let mut codes2 = [0u16; 256]; + let mut codes3 = [0u16; 256]; + write_huffman_tree(w, &frequencies1, &mut lengths1, &mut codes1)?; + if is_color { + write_huffman_tree(w, &frequencies0, &mut lengths0, &mut codes0)?; + write_huffman_tree(w, &frequencies2, &mut lengths2, &mut codes2)?; + } else { + write_single_entry_huffman_tree(w, 0)?; + write_single_entry_huffman_tree(w, 0)?; + } + if is_alpha { + write_huffman_tree(w, &frequencies3, &mut lengths3, &mut codes3)?; + } else if params.use_predictor_transform { + write_single_entry_huffman_tree(w, 0)?; + } else { + write_single_entry_huffman_tree(w, 255)?; + } + write_single_entry_huffman_tree(w, 1)?; + + // Write image data + let mut it = pixels.chunks_exact(4).peekable(); + match color { + ColorType::L8 => { + while let Some(pixel) = it.next() { + w.write_bits( + u64::from(codes1[pixel[1] as usize]), + lengths1[pixel[1] as usize], + )?; + write_run(w, pixel, &mut it, &codes1, &lengths1)?; + } + } + ColorType::La8 => { + while let Some(pixel) = it.next() { + let len1 = lengths1[pixel[1] as usize]; + let len3 = lengths3[pixel[3] as usize]; + + let code = u64::from(codes1[pixel[1] as usize]) + | (u64::from(codes3[pixel[3] as usize]) << len1); + + w.write_bits(code, len1 + len3)?; + write_run(w, pixel, &mut it, &codes1, &lengths1)?; + } + } + ColorType::Rgb8 => { + while let Some(pixel) = it.next() { + let len1 = lengths1[pixel[1] as usize]; + let len0 = lengths0[pixel[0] as usize]; + let len2 = lengths2[pixel[2] as usize]; + + let code = u64::from(codes1[pixel[1] as usize]) + | (u64::from(codes0[pixel[0] as usize]) << len1) + | (u64::from(codes2[pixel[2] as usize]) << (len1 + len0)); + + w.write_bits(code, len1 + len0 + len2)?; + write_run(w, pixel, &mut it, &codes1, &lengths1)?; + } + } + ColorType::Rgba8 => { + while let Some(pixel) = it.next() { + let len1 = lengths1[pixel[1] as usize]; + let len0 = lengths0[pixel[0] as usize]; + let len2 = lengths2[pixel[2] as usize]; + let len3 = lengths3[pixel[3] as usize]; + + let code = u64::from(codes1[pixel[1] as usize]) + | (u64::from(codes0[pixel[0] as usize]) << len1) + | (u64::from(codes2[pixel[2] as usize]) << (len1 + len0)) + | (u64::from(codes3[pixel[3] as usize]) << (len1 + len0 + len2)); + + w.write_bits(code, len1 + len0 + len2 + len3)?; + write_run(w, pixel, &mut it, &codes1, &lengths1)?; + } + } + } + + w.flush()?; + Ok(()) +} + +const fn chunk_size(inner_bytes: usize) -> u32 { + if inner_bytes % 2 == 1 { + (inner_bytes + 1) as u32 + 8 + } else { + inner_bytes as u32 + 8 + } +} + +fn write_chunk(mut w: W, name: &[u8], data: &[u8]) -> io::Result<()> { + debug_assert!(name.len() == 4); + + w.write_all(name)?; + w.write_all(&(data.len() as u32).to_le_bytes())?; + w.write_all(data)?; + if data.len() % 2 == 1 { + w.write_all(&[0])?; + } + Ok(()) +} + +/// WebP Encoder. +pub struct WebPEncoder { + writer: W, + icc_profile: Vec, + exif_metadata: Vec, + xmp_metadata: Vec, + params: EncoderParams, +} + +impl WebPEncoder { + /// Create a new encoder that writes its output to `w`. + /// + /// Only supports "VP8L" lossless encoding. + pub fn new(w: W) -> Self { + Self { + writer: w, + icc_profile: Vec::new(), + exif_metadata: Vec::new(), + xmp_metadata: Vec::new(), + params: EncoderParams::default(), + } + } + + /// Set the ICC profile to use for the image. + pub fn set_icc_profile(&mut self, icc_profile: Vec) { + self.icc_profile = icc_profile; + } + + /// Set the EXIF metadata to use for the image. + pub fn set_exif_metadata(&mut self, exif_metadata: Vec) { + self.exif_metadata = exif_metadata; + } + + /// Set the XMP metadata to use for the image. + pub fn set_xmp_metadata(&mut self, xmp_metadata: Vec) { + self.xmp_metadata = xmp_metadata; + } + + /// Set the `EncoderParams` to use. + pub fn set_params(&mut self, params: EncoderParams) { + self.params = params; + } + + /// Encode image data with the indicated color type. + /// + /// # Panics + /// + /// Panics if the image data is not of the indicated dimensions. + pub fn encode( + mut self, + data: &[u8], + width: u32, + height: u32, + color: ColorType, + ) -> Result<(), EncodingError> { + let mut frame = Vec::new(); + encode_frame(&mut frame, data, width, height, color, self.params)?; + + // If the image has no metadata, it can be encoded with the "simple" WebP container format. + if self.icc_profile.is_empty() + && self.exif_metadata.is_empty() + && self.xmp_metadata.is_empty() + { + self.writer.write_all(b"RIFF")?; + self.writer + .write_all(&(chunk_size(frame.len()) + 4).to_le_bytes())?; + self.writer.write_all(b"WEBP")?; + write_chunk(&mut self.writer, b"VP8L", &frame)?; + } else { + let mut total_bytes = 22 + chunk_size(frame.len()); + if !self.icc_profile.is_empty() { + total_bytes += chunk_size(self.icc_profile.len()); + } + if !self.exif_metadata.is_empty() { + total_bytes += chunk_size(self.exif_metadata.len()); + } + if !self.xmp_metadata.is_empty() { + total_bytes += chunk_size(self.xmp_metadata.len()); + } + + let mut flags = 0; + if !self.xmp_metadata.is_empty() { + flags |= 1 << 2; + } + if !self.exif_metadata.is_empty() { + flags |= 1 << 3; + } + if let ColorType::La8 | ColorType::Rgba8 = color { + flags |= 1 << 4; + } + if !self.icc_profile.is_empty() { + flags |= 1 << 5; + } + + self.writer.write_all(b"RIFF")?; + self.writer.write_all(&total_bytes.to_le_bytes())?; + self.writer.write_all(b"WEBP")?; + + let mut vp8x = Vec::new(); + vp8x.write_all(&[flags])?; // flags + vp8x.write_all(&[0; 3])?; // reserved + vp8x.write_all(&(width - 1).to_le_bytes()[..3])?; // canvas width + vp8x.write_all(&(height - 1).to_le_bytes()[..3])?; // canvas height + write_chunk(&mut self.writer, b"VP8X", &vp8x)?; + + if !self.icc_profile.is_empty() { + write_chunk(&mut self.writer, b"ICCP", &self.icc_profile)?; + } + + write_chunk(&mut self.writer, b"VP8L", &frame)?; + + if !self.exif_metadata.is_empty() { + write_chunk(&mut self.writer, b"EXIF", &self.exif_metadata)?; + } + + if !self.xmp_metadata.is_empty() { + write_chunk(&mut self.writer, b"XMP ", &self.xmp_metadata)?; + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use rand::RngCore; + + use super::*; + + #[test] + fn write_webp() { + let mut img = vec![0; 256 * 256 * 4]; + rand::thread_rng().fill_bytes(&mut img); + + let mut output = Vec::new(); + WebPEncoder::new(&mut output) + .encode(&img, 256, 256, crate::ColorType::Rgba8) + .unwrap(); + + let mut decoder = crate::WebPDecoder::new(std::io::Cursor::new(output)).unwrap(); + let mut img2 = vec![0; 256 * 256 * 4]; + decoder.read_image(&mut img2).unwrap(); + assert_eq!(img, img2); + } + + #[test] + fn write_webp_exif() { + let mut img = vec![0; 256 * 256 * 3]; + rand::thread_rng().fill_bytes(&mut img); + + let mut exif = vec![0; 10]; + rand::thread_rng().fill_bytes(&mut exif); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_exif_metadata(exif.clone()); + encoder + .encode(&img, 256, 256, crate::ColorType::Rgb8) + .unwrap(); + + let mut decoder = crate::WebPDecoder::new(std::io::Cursor::new(output)).unwrap(); + + let mut img2 = vec![0; 256 * 256 * 3]; + decoder.read_image(&mut img2).unwrap(); + assert_eq!(img, img2); + + let exif2 = decoder.exif_metadata().unwrap(); + assert_eq!(Some(exif), exif2); + } + + #[test] + fn roundtrip_libwebp() { + roundtrip_libwebp_params(EncoderParams::default()); + roundtrip_libwebp_params(EncoderParams { + use_predictor_transform: false, + ..Default::default() + }); + } + + fn roundtrip_libwebp_params(params: EncoderParams) { + println!("Testing {params:?}"); + + let mut img = vec![0; 256 * 256 * 4]; + rand::thread_rng().fill_bytes(&mut img); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_params(params.clone()); + encoder + .encode(&img[..256 * 256 * 3], 256, 256, crate::ColorType::Rgb8) + .unwrap(); + let decoded = webp::Decoder::new(&output).decode().unwrap(); + assert_eq!(img[..256 * 256 * 3], *decoded); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_params(params.clone()); + encoder + .encode(&img, 256, 256, crate::ColorType::Rgba8) + .unwrap(); + let decoded = webp::Decoder::new(&output).decode().unwrap(); + assert_eq!(img, *decoded); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_params(params.clone()); + encoder.set_icc_profile(vec![0; 10]); + encoder + .encode(&img, 256, 256, crate::ColorType::Rgba8) + .unwrap(); + let decoded = webp::Decoder::new(&output).decode().unwrap(); + assert_eq!(img, *decoded); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_params(params.clone()); + encoder.set_exif_metadata(vec![0; 10]); + encoder + .encode(&img, 256, 256, crate::ColorType::Rgba8) + .unwrap(); + let decoded = webp::Decoder::new(&output).decode().unwrap(); + assert_eq!(img, *decoded); + + let mut output = Vec::new(); + let mut encoder = WebPEncoder::new(&mut output); + encoder.set_params(params); + encoder.set_xmp_metadata(vec![0; 7]); + encoder.set_icc_profile(vec![0; 8]); + encoder.set_icc_profile(vec![0; 9]); + encoder + .encode(&img, 256, 256, crate::ColorType::Rgba8) + .unwrap(); + let decoded = webp::Decoder::new(&output).decode().unwrap(); + assert_eq!(img, *decoded); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/extended.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/extended.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/extended.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/extended.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,327 @@ +use super::lossless::LosslessDecoder; +use crate::decoder::DecodingError; +use byteorder_lite::ReadBytesExt; +use std::io::{BufRead, Read}; + +use crate::alpha_blending::do_alpha_blending; + +#[derive(Debug, Clone)] +pub(crate) struct WebPExtendedInfo { + pub(crate) alpha: bool, + + pub(crate) canvas_width: u32, + pub(crate) canvas_height: u32, + + #[allow(unused)] + pub(crate) icc_profile: bool, + pub(crate) exif_metadata: bool, + pub(crate) xmp_metadata: bool, + pub(crate) animation: bool, + + pub(crate) background_color: Option<[u8; 4]>, + pub(crate) background_color_hint: [u8; 4], +} + +/// Composites a frame onto a canvas. +/// +/// Starts by filling the rectangle occupied by the previous frame with the background +/// color, if provided. Then copies or blends the frame onto the canvas. +#[allow(clippy::too_many_arguments)] +pub(crate) fn composite_frame( + canvas: &mut [u8], + canvas_width: u32, + canvas_height: u32, + clear_color: Option<[u8; 4]>, + frame: &[u8], + frame_offset_x: u32, + frame_offset_y: u32, + frame_width: u32, + frame_height: u32, + frame_has_alpha: bool, + frame_use_alpha_blending: bool, + previous_frame_width: u32, + previous_frame_height: u32, + previous_frame_offset_x: u32, + previous_frame_offset_y: u32, +) { + let frame_is_full_size = frame_offset_x == 0 + && frame_offset_y == 0 + && frame_width == canvas_width + && frame_height == canvas_height; + + if frame_is_full_size && !frame_use_alpha_blending { + if frame_has_alpha { + canvas.copy_from_slice(frame); + } else { + for (input, output) in frame.chunks_exact(3).zip(canvas.chunks_exact_mut(4)) { + output[..3].copy_from_slice(input); + output[3] = 255; + } + } + return; + } + + // clear rectangle occupied by previous frame + if let Some(clear_color) = clear_color { + match (frame_is_full_size, frame_has_alpha) { + (true, true) => { + for pixel in canvas.chunks_exact_mut(4) { + pixel.copy_from_slice(&clear_color); + } + } + (true, false) => { + for pixel in canvas.chunks_exact_mut(3) { + pixel.copy_from_slice(&clear_color[..3]); + } + } + (false, true) => { + for y in 0..previous_frame_height as usize { + for x in 0..previous_frame_width as usize { + let canvas_index = ((x + previous_frame_offset_x as usize) + + (y + previous_frame_offset_y as usize) * canvas_width as usize) + * 4; + + let output = &mut canvas[canvas_index..][..4]; + output.copy_from_slice(&clear_color); + } + } + } + (false, false) => { + for y in 0..previous_frame_height as usize { + for x in 0..previous_frame_width as usize { + // let frame_index = (x + y * frame_width as usize) * 4; + let canvas_index = ((x + previous_frame_offset_x as usize) + + (y + previous_frame_offset_y as usize) * canvas_width as usize) + * 3; + + let output = &mut canvas[canvas_index..][..3]; + output.copy_from_slice(&clear_color[..3]); + } + } + } + } + } + + let width = frame_width.min(canvas_width.saturating_sub(frame_offset_x)) as usize; + let height = frame_height.min(canvas_height.saturating_sub(frame_offset_y)) as usize; + + if frame_has_alpha && frame_use_alpha_blending { + for y in 0..height { + for x in 0..width { + let frame_index = (x + y * frame_width as usize) * 4; + let canvas_index = ((x + frame_offset_x as usize) + + (y + frame_offset_y as usize) * canvas_width as usize) + * 4; + + let input = &frame[frame_index..][..4]; + let output = &mut canvas[canvas_index..][..4]; + + let blended = + do_alpha_blending(input.try_into().unwrap(), output.try_into().unwrap()); + output.copy_from_slice(&blended); + } + } + } else if frame_has_alpha { + for y in 0..height { + let frame_index = (y * frame_width as usize) * 4; + let canvas_index = (frame_offset_x as usize + + (y + frame_offset_y as usize) * canvas_width as usize) + * 4; + + canvas[canvas_index..][..width * 4].copy_from_slice(&frame[frame_index..][..width * 4]); + } + } else { + for y in 0..height { + let index = (y * frame_width as usize) * 3; + let canvas_index = (frame_offset_x as usize + + (y + frame_offset_y as usize) * canvas_width as usize) + * 4; + let input = &frame[index..][..width * 3]; + let output = &mut canvas[canvas_index..][..width * 4]; + + for (input, output) in input.chunks_exact(3).zip(output.chunks_exact_mut(4)) { + output[..3].copy_from_slice(input); + output[3] = 255; + } + } + } +} + +pub(crate) fn get_alpha_predictor( + x: usize, + y: usize, + width: usize, + filtering_method: FilteringMethod, + image_slice: &[u8], +) -> u8 { + match filtering_method { + FilteringMethod::None => 0, + FilteringMethod::Horizontal => { + if x == 0 && y == 0 { + 0 + } else if x == 0 { + let index = (y - 1) * width + x; + image_slice[index * 4 + 3] + } else { + let index = y * width + x - 1; + image_slice[index * 4 + 3] + } + } + FilteringMethod::Vertical => { + if x == 0 && y == 0 { + 0 + } else if y == 0 { + let index = y * width + x - 1; + image_slice[index * 4 + 3] + } else { + let index = (y - 1) * width + x; + image_slice[index * 4 + 3] + } + } + FilteringMethod::Gradient => { + let (left, top, top_left) = match (x, y) { + (0, 0) => (0, 0, 0), + (0, y) => { + let above_index = (y - 1) * width + x; + let val = image_slice[above_index * 4 + 3]; + (val, val, val) + } + (x, 0) => { + let before_index = y * width + x - 1; + let val = image_slice[before_index * 4 + 3]; + (val, val, val) + } + (x, y) => { + let left_index = y * width + x - 1; + let left = image_slice[left_index * 4 + 3]; + let top_index = (y - 1) * width + x; + let top = image_slice[top_index * 4 + 3]; + let top_left_index = (y - 1) * width + x - 1; + let top_left = image_slice[top_left_index * 4 + 3]; + + (left, top, top_left) + } + }; + + let combination = i16::from(left) + i16::from(top) - i16::from(top_left); + i16::clamp(combination, 0, 255).try_into().unwrap() + } + } +} + +pub(crate) fn read_extended_header( + reader: &mut R, +) -> Result { + let chunk_flags = reader.read_u8()?; + + let icc_profile = chunk_flags & 0b00100000 != 0; + let alpha = chunk_flags & 0b00010000 != 0; + let exif_metadata = chunk_flags & 0b00001000 != 0; + let xmp_metadata = chunk_flags & 0b00000100 != 0; + let animation = chunk_flags & 0b00000010 != 0; + + // reserved bytes are ignored + let _reserved_bytes = read_3_bytes(reader)?; + + let canvas_width = read_3_bytes(reader)? + 1; + let canvas_height = read_3_bytes(reader)? + 1; + + //product of canvas dimensions cannot be larger than u32 max + if u32::checked_mul(canvas_width, canvas_height).is_none() { + return Err(DecodingError::ImageTooLarge); + } + + let info = WebPExtendedInfo { + icc_profile, + alpha, + exif_metadata, + xmp_metadata, + animation, + canvas_width, + canvas_height, + background_color_hint: [0; 4], + background_color: None, + }; + + Ok(info) +} + +pub(crate) fn read_3_bytes(reader: &mut R) -> Result { + let mut buffer: [u8; 3] = [0; 3]; + reader.read_exact(&mut buffer)?; + let value: u32 = + (u32::from(buffer[2]) << 16) | (u32::from(buffer[1]) << 8) | u32::from(buffer[0]); + Ok(value) +} + +#[derive(Debug)] +pub(crate) struct AlphaChunk { + _preprocessing: bool, + pub(crate) filtering_method: FilteringMethod, + pub(crate) data: Vec, +} + +#[derive(Debug, Copy, Clone)] +pub(crate) enum FilteringMethod { + None, + Horizontal, + Vertical, + Gradient, +} + +pub(crate) fn read_alpha_chunk( + reader: &mut R, + width: u16, + height: u16, +) -> Result { + let info_byte = reader.read_u8()?; + + let preprocessing = (info_byte & 0b00110000) >> 4; + let filtering = (info_byte & 0b00001100) >> 2; + let compression = info_byte & 0b00000011; + + let preprocessing = match preprocessing { + 0 => false, + 1 => true, + _ => return Err(DecodingError::InvalidAlphaPreprocessing), + }; + + let filtering_method = match filtering { + 0 => FilteringMethod::None, + 1 => FilteringMethod::Horizontal, + 2 => FilteringMethod::Vertical, + 3 => FilteringMethod::Gradient, + _ => unreachable!(), + }; + + let lossless_compression = match compression { + 0 => false, + 1 => true, + _ => return Err(DecodingError::InvalidCompressionMethod), + }; + + let data = if lossless_compression { + let mut decoder = LosslessDecoder::new(reader); + + let mut data = vec![0; usize::from(width) * usize::from(height) * 4]; + decoder.decode_frame(u32::from(width), u32::from(height), true, &mut data)?; + + let mut green = vec![0; usize::from(width) * usize::from(height)]; + for (rgba_val, green_val) in data.chunks_exact(4).zip(green.iter_mut()) { + *green_val = rgba_val[1]; + } + green + } else { + let mut framedata = vec![0; width as usize * height as usize]; + reader.read_exact(&mut framedata)?; + framedata + }; + + let chunk = AlphaChunk { + _preprocessing: preprocessing, + filtering_method, + data, + }; + + Ok(chunk) +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/huffman.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/huffman.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/huffman.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/huffman.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,248 @@ +//! Rudimentary utility for reading Canonical Huffman Codes. +//! Based off + +use std::io::BufRead; + +use crate::decoder::DecodingError; + +use super::lossless::BitReader; + +const MAX_ALLOWED_CODE_LENGTH: usize = 15; +const MAX_TABLE_BITS: u8 = 10; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum HuffmanTreeNode { + Branch(usize), //offset in vector to children + Leaf(u16), //symbol stored in leaf + Empty, +} + +#[derive(Clone, Debug)] +enum HuffmanTreeInner { + Single(u16), + Tree { + tree: Vec, + table: Vec, + table_mask: u16, + }, +} + +/// Huffman tree +#[derive(Clone, Debug)] +pub(crate) struct HuffmanTree(HuffmanTreeInner); + +impl Default for HuffmanTree { + fn default() -> Self { + Self(HuffmanTreeInner::Single(0)) + } +} + +impl HuffmanTree { + /// Builds a tree implicitly, just from code lengths + pub(crate) fn build_implicit(code_lengths: Vec) -> Result { + // Count symbols and build histogram + let mut num_symbols = 0; + let mut code_length_hist = [0; MAX_ALLOWED_CODE_LENGTH + 1]; + for &length in code_lengths.iter().filter(|&&x| x != 0) { + code_length_hist[usize::from(length)] += 1; + num_symbols += 1; + } + + // Handle special cases + if num_symbols == 0 { + return Err(DecodingError::HuffmanError); + } else if num_symbols == 1 { + let root_symbol = code_lengths.iter().position(|&x| x != 0).unwrap() as u16; + return Ok(Self::build_single_node(root_symbol)); + }; + + // Assign codes + let mut curr_code = 0; + let mut next_codes = [0; MAX_ALLOWED_CODE_LENGTH + 1]; + let max_code_length = code_length_hist.iter().rposition(|&x| x != 0).unwrap() as u16; + for code_len in 1..usize::from(max_code_length) + 1 { + next_codes[code_len] = curr_code; + curr_code = (curr_code + code_length_hist[code_len]) << 1; + } + + // Confirm that the huffman tree is valid + if curr_code != 2 << max_code_length { + return Err(DecodingError::HuffmanError); + } + + // Calculate table/tree parameters + let table_bits = max_code_length.min(u16::from(MAX_TABLE_BITS)); + let table_size = (1 << table_bits) as usize; + let table_mask = table_size as u16 - 1; + let tree_size = code_length_hist[table_bits as usize + 1..=max_code_length as usize] + .iter() + .sum::() as usize; + + // Populate decoding table + let mut tree = Vec::with_capacity(2 * tree_size); + let mut table = vec![0; table_size]; + for (symbol, &length) in code_lengths.iter().enumerate() { + if length == 0 { + continue; + } + + let code = next_codes[length as usize]; + next_codes[length as usize] += 1; + + if length <= table_bits { + let mut j = (u16::reverse_bits(code) >> (16 - length)) as usize; + let entry = (u32::from(length) << 16) | symbol as u32; + while j < table_size { + table[j] = entry; + j += 1 << length as usize; + } + } else { + let table_index = + ((u16::reverse_bits(code) >> (16 - length)) & table_mask) as usize; + let table_value = table[table_index]; + + debug_assert_eq!(table_value >> 16, 0); + + let mut node_index = if table_value == 0 { + let node_index = tree.len(); + table[table_index] = (node_index + 1) as u32; + tree.push(HuffmanTreeNode::Empty); + node_index + } else { + (table_value - 1) as usize + }; + + let code = usize::from(code); + for depth in (0..length - table_bits).rev() { + let node = tree[node_index]; + + let offset = match node { + HuffmanTreeNode::Empty => { + // Turns a node from empty into a branch and assigns its children + let offset = tree.len() - node_index; + tree[node_index] = HuffmanTreeNode::Branch(offset); + tree.push(HuffmanTreeNode::Empty); + tree.push(HuffmanTreeNode::Empty); + offset + } + HuffmanTreeNode::Leaf(_) => return Err(DecodingError::HuffmanError), + HuffmanTreeNode::Branch(offset) => offset, + }; + + node_index += offset + ((code >> depth) & 1); + } + + match tree[node_index] { + HuffmanTreeNode::Empty => { + tree[node_index] = HuffmanTreeNode::Leaf(symbol as u16); + } + HuffmanTreeNode::Leaf(_) => return Err(DecodingError::HuffmanError), + HuffmanTreeNode::Branch(_offset) => return Err(DecodingError::HuffmanError), + } + } + } + + Ok(Self(HuffmanTreeInner::Tree { + tree, + table, + table_mask, + })) + } + + pub(crate) const fn build_single_node(symbol: u16) -> Self { + Self(HuffmanTreeInner::Single(symbol)) + } + + pub(crate) fn build_two_node(zero: u16, one: u16) -> Self { + Self(HuffmanTreeInner::Tree { + tree: vec![ + HuffmanTreeNode::Leaf(zero), + HuffmanTreeNode::Leaf(one), + HuffmanTreeNode::Empty, + ], + table: vec![(1 << 16) | u32::from(zero), (1 << 16) | u32::from(one)], + table_mask: 0x1, + }) + } + + pub(crate) const fn is_single_node(&self) -> bool { + matches!(self.0, HuffmanTreeInner::Single(_)) + } + + #[inline(never)] + fn read_symbol_slowpath( + tree: &[HuffmanTreeNode], + mut v: usize, + start_index: usize, + bit_reader: &mut BitReader, + ) -> Result { + let mut depth = MAX_TABLE_BITS; + let mut index = start_index; + loop { + match &tree[index] { + HuffmanTreeNode::Branch(children_offset) => { + index += children_offset + (v & 1); + depth += 1; + v >>= 1; + } + HuffmanTreeNode::Leaf(symbol) => { + bit_reader.consume(depth)?; + return Ok(*symbol); + } + HuffmanTreeNode::Empty => return Err(DecodingError::HuffmanError), + } + } + } + + /// Reads a symbol using the bit reader. + /// + /// You must call call `bit_reader.fill()` before calling this function or it may erroroneosly + /// detect the end of the stream and return a bitstream error. + pub(crate) fn read_symbol( + &self, + bit_reader: &mut BitReader, + ) -> Result { + match &self.0 { + HuffmanTreeInner::Tree { + tree, + table, + table_mask, + } => { + let v = bit_reader.peek_full() as u16; + let entry = table[(v & table_mask) as usize]; + if entry >> 16 != 0 { + bit_reader.consume((entry >> 16) as u8)?; + return Ok(entry as u16); + } + + Self::read_symbol_slowpath( + tree, + (v >> MAX_TABLE_BITS) as usize, + ((entry & 0xffff) - 1) as usize, + bit_reader, + ) + } + HuffmanTreeInner::Single(symbol) => Ok(*symbol), + } + } + + /// Peek at the next symbol in the bitstream if it can be read with only a primary table lookup. + /// + /// Returns a tuple of the codelength and symbol value. This function may return wrong + /// information if there aren't enough bits in the bit reader to read the next symbol. + pub(crate) fn peek_symbol(&self, bit_reader: &BitReader) -> Option<(u8, u16)> { + match &self.0 { + HuffmanTreeInner::Tree { + table, table_mask, .. + } => { + let v = bit_reader.peek_full() as u16; + let entry = table[(v & table_mask) as usize]; + if entry >> 16 != 0 { + return Some(((entry >> 16) as u8, entry as u16)); + } + None + } + HuffmanTreeInner::Single(symbol) => Some((0, *symbol)), + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,29 @@ +//! Decoding and Encoding of WebP Images + +#![forbid(unsafe_code)] +#![deny(missing_docs)] +// Increase recursion limit for the `quick_error!` macro. +#![recursion_limit = "256"] +// Enable nightly benchmark functionality if "_benchmarks" feature is enabled. +#![cfg_attr(all(test, feature = "_benchmarks"), feature(test))] +#[cfg(all(test, feature = "_benchmarks"))] +extern crate test; + +pub use self::decoder::{ + DecodingError, LoopCount, UpsamplingMethod, WebPDecodeOptions, WebPDecoder, +}; +pub use self::encoder::{ColorType, EncoderParams, EncodingError, WebPEncoder}; + +mod alpha_blending; +mod decoder; +mod encoder; +mod extended; +mod huffman; +mod loop_filter; +mod lossless; +mod lossless_transform; +mod transform; +mod vp8_arithmetic_decoder; +mod yuv; + +pub mod vp8; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/loop_filter.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/loop_filter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/loop_filter.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/loop_filter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,437 @@ +//! Does loop filtering on webp lossy images + +#[inline] +fn c(val: i32) -> i32 { + val.clamp(-128, 127) +} + +//unsigned to signed +#[inline] +fn u2s(val: u8) -> i32 { + i32::from(val) - 128 +} + +//signed to unsigned +#[inline] +fn s2u(val: i32) -> u8 { + (c(val) + 128) as u8 +} + +#[inline] +const fn diff(val1: u8, val2: u8) -> u8 { + u8::abs_diff(val1, val2) +} + +/// Used in both the simple and normal filters described in 15.2 and 15.3 +/// +/// Adjusts the 2 middle pixels in a vertical loop filter +fn common_adjust_vertical( + use_outer_taps: bool, + pixels: &mut [u8], + point: usize, + stride: usize, +) -> i32 { + let p1 = u2s(pixels[point - 2 * stride]); + let p0 = u2s(pixels[point - stride]); + let q0 = u2s(pixels[point]); + let q1 = u2s(pixels[point + stride]); + + //value for the outer 2 pixels + let outer = if use_outer_taps { c(p1 - q1) } else { 0 }; + + let a = c(outer + 3 * (q0 - p0)); + + let b = (c(a + 3)) >> 3; + + let a = (c(a + 4)) >> 3; + + pixels[point] = s2u(q0 - a); + pixels[point - stride] = s2u(p0 + b); + + a +} + +/// Used in both the simple and normal filters described in 15.2 and 15.3 +/// +/// Adjusts the 2 middle pixels in a horizontal loop filter +fn common_adjust_horizontal(use_outer_taps: bool, pixels: &mut [u8]) -> i32 { + let p1 = u2s(pixels[2]); + let p0 = u2s(pixels[3]); + let q0 = u2s(pixels[4]); + let q1 = u2s(pixels[5]); + + //value for the outer 2 pixels + let outer = if use_outer_taps { c(p1 - q1) } else { 0 }; + + let a = c(outer + 3 * (q0 - p0)); + + let b = (c(a + 3)) >> 3; + + let a = (c(a + 4)) >> 3; + + pixels[4] = s2u(q0 - a); + pixels[3] = s2u(p0 + b); + + a +} + +#[inline] +fn simple_threshold_vertical( + filter_limit: i32, + pixels: &[u8], + point: usize, + stride: usize, +) -> bool { + i32::from(diff(pixels[point - stride], pixels[point])) * 2 + + i32::from(diff(pixels[point - 2 * stride], pixels[point + stride])) / 2 + <= filter_limit +} + +#[inline] +fn simple_threshold_horizontal(filter_limit: i32, pixels: &[u8]) -> bool { + assert!(pixels.len() >= 6); // one bounds check up front eliminates all subsequent checks in this function + i32::from(diff(pixels[3], pixels[4])) * 2 + i32::from(diff(pixels[2], pixels[5])) / 2 + <= filter_limit +} + +fn should_filter_vertical( + interior_limit: u8, + edge_limit: u8, + pixels: &[u8], + point: usize, + stride: usize, +) -> bool { + simple_threshold_vertical(i32::from(edge_limit), pixels, point, stride) + // this looks like an erroneous way to compute differences between 8 points, but isn't: + // there are actually only 6 diff comparisons required as per the spec: + // https://www.rfc-editor.org/rfc/rfc6386#section-20.6 + && diff(pixels[point - 4 * stride], pixels[point - 3 * stride]) <= interior_limit + && diff(pixels[point - 3 * stride], pixels[point - 2 * stride]) <= interior_limit + && diff(pixels[point - 2 * stride], pixels[point - stride]) <= interior_limit + && diff(pixels[point + 3 * stride], pixels[point + 2 * stride]) <= interior_limit + && diff(pixels[point + 2 * stride], pixels[point + stride]) <= interior_limit + && diff(pixels[point + stride], pixels[point]) <= interior_limit +} + +fn should_filter_horizontal(interior_limit: u8, edge_limit: u8, pixels: &[u8]) -> bool { + assert!(pixels.len() >= 8); // one bounds check up front eliminates all subsequent checks in this function + simple_threshold_horizontal(i32::from(edge_limit), pixels) + // this looks like an erroneous way to compute differences between 8 points, but isn't: + // there are actually only 6 diff comparisons required as per the spec: + // https://www.rfc-editor.org/rfc/rfc6386#section-20.6 + && diff(pixels[0], pixels[1]) <= interior_limit + && diff(pixels[1], pixels[2]) <= interior_limit + && diff(pixels[2], pixels[3]) <= interior_limit + && diff(pixels[7], pixels[6]) <= interior_limit + && diff(pixels[6], pixels[5]) <= interior_limit + && diff(pixels[5], pixels[4]) <= interior_limit +} + +#[inline] +fn high_edge_variance_vertical(threshold: u8, pixels: &[u8], point: usize, stride: usize) -> bool { + diff(pixels[point - 2 * stride], pixels[point - stride]) > threshold + || diff(pixels[point + stride], pixels[point]) > threshold +} + +#[inline] +fn high_edge_variance_horizontal(threshold: u8, pixels: &[u8]) -> bool { + diff(pixels[2], pixels[3]) > threshold || diff(pixels[5], pixels[4]) > threshold +} + +/// Part of the simple filter described in 15.2 in the specification +/// +/// Affects 4 pixels on an edge(2 each side) +pub(crate) fn simple_segment_vertical( + edge_limit: u8, + pixels: &mut [u8], + point: usize, + stride: usize, +) { + if simple_threshold_vertical(i32::from(edge_limit), pixels, point, stride) { + common_adjust_vertical(true, pixels, point, stride); + } +} + +/// Part of the simple filter described in 15.2 in the specification +/// +/// Affects 4 pixels on an edge(2 each side) +pub(crate) fn simple_segment_horizontal(edge_limit: u8, pixels: &mut [u8]) { + if simple_threshold_horizontal(i32::from(edge_limit), pixels) { + common_adjust_horizontal(true, pixels); + } +} + +/// Part of the normal filter described in 15.3 in the specification +/// +/// Filters on the 8 pixels on the edges between subblocks inside a macroblock +pub(crate) fn subblock_filter_vertical( + hev_threshold: u8, + interior_limit: u8, + edge_limit: u8, + pixels: &mut [u8], + point: usize, + stride: usize, +) { + if should_filter_vertical(interior_limit, edge_limit, pixels, point, stride) { + let hv = high_edge_variance_vertical(hev_threshold, pixels, point, stride); + + let a = (common_adjust_vertical(hv, pixels, point, stride) + 1) >> 1; + + if !hv { + pixels[point + stride] = s2u(u2s(pixels[point + stride]) - a); + pixels[point - 2 * stride] = s2u(u2s(pixels[point - 2 * stride]) + a); + } + } +} + +/// Part of the normal filter described in 15.3 in the specification +/// +/// Filters on the 8 pixels on the edges between subblocks inside a macroblock +pub(crate) fn subblock_filter_horizontal( + hev_threshold: u8, + interior_limit: u8, + edge_limit: u8, + pixels: &mut [u8], +) { + if should_filter_horizontal(interior_limit, edge_limit, pixels) { + let hv = high_edge_variance_horizontal(hev_threshold, pixels); + + let a = (common_adjust_horizontal(hv, pixels) + 1) >> 1; + + if !hv { + pixels[5] = s2u(u2s(pixels[5]) - a); + pixels[2] = s2u(u2s(pixels[2]) + a); + } + } +} + +/// Part of the normal filter described in 15.3 in the specification +/// +/// Filters on the 8 pixels on the vertical edges between macroblocks\ +/// The point passed in must be the first vertical pixel on the bottom macroblock +pub(crate) fn macroblock_filter_vertical( + hev_threshold: u8, + interior_limit: u8, + edge_limit: u8, + pixels: &mut [u8], + point: usize, + stride: usize, +) { + if should_filter_vertical(interior_limit, edge_limit, pixels, point, stride) { + if !high_edge_variance_vertical(hev_threshold, pixels, point, stride) { + // p0-3 are the pixels on the left macroblock from right to left + let p2 = u2s(pixels[point - 3 * stride]); + let p1 = u2s(pixels[point - 2 * stride]); + let p0 = u2s(pixels[point - stride]); + // q0-3 are the pixels on the right macroblock from left to right + let q0 = u2s(pixels[point]); + let q1 = u2s(pixels[point + stride]); + let q2 = u2s(pixels[point + 2 * stride]); + + let w = c(c(p1 - q1) + 3 * (q0 - p0)); + + let a = c((27 * w + 63) >> 7); + + pixels[point] = s2u(q0 - a); + pixels[point - stride] = s2u(p0 + a); + + let a = c((18 * w + 63) >> 7); + + pixels[point + stride] = s2u(q1 - a); + pixels[point - 2 * stride] = s2u(p1 + a); + + let a = c((9 * w + 63) >> 7); + + pixels[point + 2 * stride] = s2u(q2 - a); + pixels[point - 3 * stride] = s2u(p2 + a); + } else { + common_adjust_vertical(true, pixels, point, stride); + } + } +} + +/// Part of the normal filter described in 15.3 in the specification +/// +/// Filters on the 8 pixels on the horizontal edges between macroblocks\ +/// The pixels passed in must be a slice containing the 4 pixels on each macroblock +pub(crate) fn macroblock_filter_horizontal( + hev_threshold: u8, + interior_limit: u8, + edge_limit: u8, + pixels: &mut [u8], +) { + assert!(pixels.len() >= 8); + if should_filter_horizontal(interior_limit, edge_limit, pixels) { + if !high_edge_variance_horizontal(hev_threshold, pixels) { + // p0-3 are the pixels on the left macroblock from right to left + let p2 = u2s(pixels[1]); + let p1 = u2s(pixels[2]); + let p0 = u2s(pixels[3]); + // q0-3 are the pixels on the right macroblock from left to right + let q0 = u2s(pixels[4]); + let q1 = u2s(pixels[5]); + let q2 = u2s(pixels[6]); + + let w = c(c(p1 - q1) + 3 * (q0 - p0)); + + let a = c((27 * w + 63) >> 7); + + pixels[4] = s2u(q0 - a); + pixels[3] = s2u(p0 + a); + + let a = c((18 * w + 63) >> 7); + + pixels[5] = s2u(q1 - a); + pixels[2] = s2u(p1 + a); + + let a = c((9 * w + 63) >> 7); + + pixels[6] = s2u(q2 - a); + pixels[1] = s2u(p2 + a); + } else { + common_adjust_horizontal(true, pixels); + } + } +} + +#[cfg(all(test, feature = "_benchmarks"))] +mod benches { + use super::*; + use test::{black_box, Bencher}; + + #[rustfmt::skip] + const TEST_DATA: [u8; 8 * 8] = [ + 177, 192, 179, 181, 185, 174, 186, 193, + 185, 180, 175, 179, 175, 190, 189, 190, + 185, 181, 177, 190, 190, 174, 176, 188, + 192, 179, 186, 175, 190, 184, 190, 175, + 175, 183, 183, 190, 187, 186, 176, 181, + 183, 177, 182, 185, 183, 179, 178, 181, + 191, 183, 188, 181, 180, 193, 185, 180, + 177, 182, 177, 178, 179, 178, 191, 178, + ]; + + #[bench] + fn measure_horizontal_macroblock_filter(b: &mut Bencher) { + let hev_threshold = 5; + let interior_limit = 15; + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for y in 0..8 { + black_box(macroblock_filter_horizontal( + hev_threshold, + interior_limit, + edge_limit, + &mut data[y * stride..][..8], + )); + } + }); + } + + #[bench] + fn measure_vertical_macroblock_filter(b: &mut Bencher) { + let hev_threshold = 5; + let interior_limit = 15; + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for x in 0..8 { + black_box(macroblock_filter_vertical( + hev_threshold, + interior_limit, + edge_limit, + &mut data, + 4 * stride + x, + stride, + )); + } + }); + } + + #[bench] + fn measure_horizontal_subblock_filter(b: &mut Bencher) { + let hev_threshold = 5; + let interior_limit = 15; + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for y in 0usize..8 { + black_box(subblock_filter_horizontal( + hev_threshold, + interior_limit, + edge_limit, + &mut data[y * stride..][..8], + )) + } + }); + } + + #[bench] + fn measure_vertical_subblock_filter(b: &mut Bencher) { + let hev_threshold = 5; + let interior_limit = 15; + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for x in 0..8 { + black_box(subblock_filter_vertical( + hev_threshold, + interior_limit, + edge_limit, + &mut data, + 4 * stride + x, + stride, + )) + } + }); + } + + #[bench] + fn measure_simple_segment_horizontal_filter(b: &mut Bencher) { + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for y in 0usize..8 { + black_box(simple_segment_horizontal( + edge_limit, + &mut data[y * stride..][..8], + )) + } + }); + } + + #[bench] + fn measure_simple_segment_vertical_filter(b: &mut Bencher) { + let edge_limit = 15; + + let mut data = TEST_DATA.clone(); + let stride = 8; + + b.iter(|| { + for x in 0usize..16 { + black_box(simple_segment_vertical( + edge_limit, + &mut data, + 4 * stride + x, + stride, + )) + } + }); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lossless.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lossless.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,825 @@ +//! Decoding of lossless WebP images +//! +//! [Lossless spec](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification) + +use std::io::BufRead; +use std::mem; + +use crate::decoder::DecodingError; +use crate::lossless_transform::{ + apply_color_indexing_transform, apply_color_transform, apply_predictor_transform, + apply_subtract_green_transform, +}; + +use super::huffman::HuffmanTree; +use super::lossless_transform::TransformType; + +const CODE_LENGTH_CODES: usize = 19; +const CODE_LENGTH_CODE_ORDER: [usize; CODE_LENGTH_CODES] = [ + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +]; + +#[rustfmt::skip] +const DISTANCE_MAP: [(i8, i8); 120] = [ + (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), (-1, 2), + (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), (1, 3), (-1, 3), + (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), (-3, 2), (0, 4), (4, 0), + (1, 4), (-1, 4), (4, 1), (-4, 1), (3, 3), (-3, 3), (2, 4), (-2, 4), + (4, 2), (-4, 2), (0, 5), (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), + (1, 5), (-1, 5), (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), + (4, 4), (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), + (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), (-6, 2), + (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), (6, 3), (-6, 3), + (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), (-5, 5), (7, 1), (-7, 1), + (4, 6), (-4, 6), (6, 4), (-6, 4), (2, 7), (-2, 7), (7, 2), (-7, 2), + (3, 7), (-3, 7), (7, 3), (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), + (8, 0), (4, 7), (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), + (-6, 6), (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), + (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7) +]; + +const GREEN: usize = 0; +const RED: usize = 1; +const BLUE: usize = 2; +const ALPHA: usize = 3; +const DIST: usize = 4; + +const HUFFMAN_CODES_PER_META_CODE: usize = 5; + +type HuffmanCodeGroup = [HuffmanTree; HUFFMAN_CODES_PER_META_CODE]; + +const ALPHABET_SIZE: [u16; HUFFMAN_CODES_PER_META_CODE] = [256 + 24, 256, 256, 256, 40]; + +#[inline] +pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { + ((u32::from(size) + (1u32 << bits) - 1) >> bits) + .try_into() + .unwrap() +} + +const NUM_TRANSFORM_TYPES: usize = 4; + +//Decodes lossless WebP images +#[derive(Debug)] +pub(crate) struct LosslessDecoder { + bit_reader: BitReader, + transforms: [Option; NUM_TRANSFORM_TYPES], + transform_order: Vec, + width: u16, + height: u16, +} + +impl LosslessDecoder { + /// Create a new decoder + pub(crate) const fn new(r: R) -> Self { + Self { + bit_reader: BitReader::new(r), + transforms: [None, None, None, None], + transform_order: Vec::new(), + width: 0, + height: 0, + } + } + + /// Decodes a frame. + /// + /// In an alpha chunk the width and height are not included in the header, so they should be + /// provided by setting the `implicit_dimensions` argument. Otherwise that argument should be + /// `None` and the frame dimensions will be determined by reading the VP8L header. + pub(crate) fn decode_frame( + &mut self, + width: u32, + height: u32, + implicit_dimensions: bool, + buf: &mut [u8], + ) -> Result<(), DecodingError> { + if implicit_dimensions { + self.width = width as u16; + self.height = height as u16; + } else { + let signature = self.bit_reader.read_bits::(8)?; + if signature != 0x2f { + return Err(DecodingError::LosslessSignatureInvalid(signature)); + } + + self.width = self.bit_reader.read_bits::(14)? + 1; + self.height = self.bit_reader.read_bits::(14)? + 1; + if u32::from(self.width) != width || u32::from(self.height) != height { + return Err(DecodingError::InconsistentImageSizes); + } + + let _alpha_used = self.bit_reader.read_bits::(1)?; + let version_num = self.bit_reader.read_bits::(3)?; + if version_num != 0 { + return Err(DecodingError::VersionNumberInvalid(version_num)); + } + } + + let transformed_width = self.read_transforms()?; + let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4; + self.decode_image_stream( + transformed_width, + self.height, + true, + &mut buf[..transformed_size], + )?; + + let mut image_size = transformed_size; + let mut width = transformed_width; + for &trans_index in self.transform_order.iter().rev() { + let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap(); + match transform { + TransformType::PredictorTransform { + size_bits, + predictor_data, + } => apply_predictor_transform( + &mut buf[..image_size], + width, + self.height, + *size_bits, + predictor_data, + )?, + TransformType::ColorTransform { + size_bits, + transform_data, + } => { + apply_color_transform( + &mut buf[..image_size], + width, + *size_bits, + transform_data, + ); + } + TransformType::SubtractGreen => { + apply_subtract_green_transform(&mut buf[..image_size]); + } + TransformType::ColorIndexingTransform { + table_size, + table_data, + } => { + width = self.width; + image_size = usize::from(width) * usize::from(self.height) * 4; + apply_color_indexing_transform( + buf, + width, + self.height, + *table_size, + table_data, + ); + } + } + } + + Ok(()) + } + + /// Reads Image data from the bitstream + /// + /// Can be in any of the 5 roles described in the Specification. ARGB Image role has different + /// behaviour to the other 4. xsize and ysize describe the size of the blocks where each block + /// has its own entropy code + fn decode_image_stream( + &mut self, + xsize: u16, + ysize: u16, + is_argb_img: bool, + data: &mut [u8], + ) -> Result<(), DecodingError> { + let color_cache_bits = self.read_color_cache()?; + let color_cache = color_cache_bits.map(|bits| ColorCache { + color_cache_bits: bits, + color_cache: vec![[0; 4]; 1 << bits], + }); + + let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?; + self.decode_image_data(xsize, ysize, huffman_info, data) + } + + /// Reads transforms and their data from the bitstream + fn read_transforms(&mut self) -> Result { + let mut xsize = self.width; + + while self.bit_reader.read_bits::(1)? == 1 { + let transform_type_val = self.bit_reader.read_bits::(2)?; + + if self.transforms[usize::from(transform_type_val)].is_some() { + //can only have one of each transform, error + return Err(DecodingError::TransformError); + } + + self.transform_order.push(transform_type_val); + + let transform_type = match transform_type_val { + 0 => { + //predictor + + let size_bits = self.bit_reader.read_bits::(3)? + 2; + + let block_xsize = subsample_size(xsize, size_bits); + let block_ysize = subsample_size(self.height, size_bits); + + let mut predictor_data = + vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; + self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?; + + TransformType::PredictorTransform { + size_bits, + predictor_data, + } + } + 1 => { + //color transform + + let size_bits = self.bit_reader.read_bits::(3)? + 2; + + let block_xsize = subsample_size(xsize, size_bits); + let block_ysize = subsample_size(self.height, size_bits); + + let mut transform_data = + vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; + self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?; + + TransformType::ColorTransform { + size_bits, + transform_data, + } + } + 2 => { + //subtract green + + TransformType::SubtractGreen + } + 3 => { + let color_table_size = self.bit_reader.read_bits::(8)? + 1; + + let mut color_map = vec![0; usize::from(color_table_size) * 4]; + self.decode_image_stream(color_table_size, 1, false, &mut color_map)?; + + let bits = if color_table_size <= 2 { + 3 + } else if color_table_size <= 4 { + 2 + } else if color_table_size <= 16 { + 1 + } else { + 0 + }; + xsize = subsample_size(xsize, bits); + + Self::adjust_color_map(&mut color_map); + + TransformType::ColorIndexingTransform { + table_size: color_table_size, + table_data: color_map, + } + } + _ => unreachable!(), + }; + + self.transforms[usize::from(transform_type_val)] = Some(transform_type); + } + + Ok(xsize) + } + + /// Adjusts the color map since it's subtraction coded + fn adjust_color_map(color_map: &mut [u8]) { + for i in 4..color_map.len() { + color_map[i] = color_map[i].wrapping_add(color_map[i - 4]); + } + } + + /// Reads huffman codes associated with an image + fn read_huffman_codes( + &mut self, + read_meta: bool, + xsize: u16, + ysize: u16, + color_cache: Option, + ) -> Result { + let mut num_huff_groups = 1u32; + + let mut huffman_bits = 0; + let mut huffman_xsize = 1; + let mut huffman_ysize = 1; + let mut entropy_image = Vec::new(); + + if read_meta && self.bit_reader.read_bits::(1)? == 1 { + //meta huffman codes + huffman_bits = self.bit_reader.read_bits::(3)? + 2; + huffman_xsize = subsample_size(xsize, huffman_bits); + huffman_ysize = subsample_size(ysize, huffman_bits); + + let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4]; + self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?; + + entropy_image = data + .chunks_exact(4) + .map(|pixel| { + let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); + if u32::from(meta_huff_code) >= num_huff_groups { + num_huff_groups = u32::from(meta_huff_code) + 1; + } + meta_huff_code + }) + .collect::>(); + } + + let mut hufftree_groups = Vec::new(); + + for _i in 0..num_huff_groups { + let mut group: HuffmanCodeGroup = Default::default(); + for j in 0..HUFFMAN_CODES_PER_META_CODE { + let mut alphabet_size = ALPHABET_SIZE[j]; + if j == 0 { + if let Some(color_cache) = color_cache.as_ref() { + alphabet_size += 1 << color_cache.color_cache_bits; + } + } + + let tree = self.read_huffman_code(alphabet_size)?; + group[j] = tree; + } + hufftree_groups.push(group); + } + + let huffman_mask = if huffman_bits == 0 { + !0 + } else { + (1 << huffman_bits) - 1 + }; + + let info = HuffmanInfo { + xsize: huffman_xsize, + _ysize: huffman_ysize, + color_cache, + image: entropy_image, + bits: huffman_bits, + mask: huffman_mask, + huffman_code_groups: hufftree_groups, + }; + + Ok(info) + } + + /// Decodes and returns a single huffman tree + fn read_huffman_code(&mut self, alphabet_size: u16) -> Result { + let simple = self.bit_reader.read_bits::(1)? == 1; + + if simple { + let num_symbols = self.bit_reader.read_bits::(1)? + 1; + + let is_first_8bits = self.bit_reader.read_bits::(1)?; + let zero_symbol = self.bit_reader.read_bits::(1 + 7 * is_first_8bits)?; + + if zero_symbol >= alphabet_size { + return Err(DecodingError::BitStreamError); + } + + if num_symbols == 1 { + Ok(HuffmanTree::build_single_node(zero_symbol)) + } else { + let one_symbol = self.bit_reader.read_bits::(8)?; + if one_symbol >= alphabet_size { + return Err(DecodingError::BitStreamError); + } + Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol)) + } + } else { + let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; + + let num_code_lengths = 4 + self.bit_reader.read_bits::(4)?; + for i in 0..num_code_lengths { + code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = + self.bit_reader.read_bits(3)?; + } + + let new_code_lengths = + self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; + + HuffmanTree::build_implicit(new_code_lengths) + } + } + + /// Reads huffman code lengths + fn read_huffman_code_lengths( + &mut self, + code_length_code_lengths: Vec, + num_symbols: u16, + ) -> Result, DecodingError> { + let table = HuffmanTree::build_implicit(code_length_code_lengths)?; + + let mut max_symbol = if self.bit_reader.read_bits::(1)? == 1 { + let length_nbits = 2 + 2 * self.bit_reader.read_bits::(3)?; + let max_minus_two = self.bit_reader.read_bits::(length_nbits)?; + if max_minus_two > num_symbols - 2 { + return Err(DecodingError::BitStreamError); + } + 2 + max_minus_two + } else { + num_symbols + }; + + let mut code_lengths = vec![0; usize::from(num_symbols)]; + let mut prev_code_len = 8; //default code length + + let mut symbol = 0; + while symbol < num_symbols { + if max_symbol == 0 { + break; + } + max_symbol -= 1; + + self.bit_reader.fill()?; + let code_len = table.read_symbol(&mut self.bit_reader)?; + + if code_len < 16 { + code_lengths[usize::from(symbol)] = code_len; + symbol += 1; + if code_len != 0 { + prev_code_len = code_len; + } + } else { + let use_prev = code_len == 16; + let slot = code_len - 16; + let extra_bits = match slot { + 0 => 2, + 1 => 3, + 2 => 7, + _ => return Err(DecodingError::BitStreamError), + }; + let repeat_offset = match slot { + 0 | 1 => 3, + 2 => 11, + _ => return Err(DecodingError::BitStreamError), + }; + + let mut repeat = self.bit_reader.read_bits::(extra_bits)? + repeat_offset; + + if symbol + repeat > num_symbols { + return Err(DecodingError::BitStreamError); + } + + let length = if use_prev { prev_code_len } else { 0 }; + while repeat > 0 { + repeat -= 1; + code_lengths[usize::from(symbol)] = length; + symbol += 1; + } + } + } + + Ok(code_lengths) + } + + /// Decodes the image data using the huffman trees and either of the 3 methods of decoding + fn decode_image_data( + &mut self, + width: u16, + height: u16, + mut huffman_info: HuffmanInfo, + data: &mut [u8], + ) -> Result<(), DecodingError> { + let num_values = usize::from(width) * usize::from(height); + + let huff_index = huffman_info.get_huff_index(0, 0); + let mut tree = &huffman_info.huffman_code_groups[huff_index]; + let mut index = 0; + + let mut next_block_start = 0; + while index < num_values { + self.bit_reader.fill()?; + + if index >= next_block_start { + let x = index % usize::from(width); + let y = index / usize::from(width); + next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1)) + + y * usize::from(width) + + 1; + + let huff_index = huffman_info.get_huff_index(x as u16, y as u16); + tree = &huffman_info.huffman_code_groups[huff_index]; + + // Fast path: If all the codes each contain only a single + // symbol, then the pixel data isn't written to the bitstream + // and we can just fill the output buffer with the symbol + // directly. + if tree[..4].iter().all(|t| t.is_single_node()) { + let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; + if code < 256 { + let n = if huffman_info.bits == 0 { + num_values + } else { + next_block_start - index + }; + + let red = tree[RED].read_symbol(&mut self.bit_reader)?; + let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; + let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; + let value = [red as u8, code as u8, blue as u8, alpha as u8]; + + for i in 0..n { + data[index * 4 + i * 4..][..4].copy_from_slice(&value); + } + + if let Some(color_cache) = huffman_info.color_cache.as_mut() { + color_cache.insert(value); + } + + index += n; + continue; + } + } + } + + let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; + + //check code + if code < 256 { + //literal, so just use huffman codes and read as argb + let green = code as u8; + let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8; + let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8; + if self.bit_reader.nbits < 15 { + self.bit_reader.fill()?; + } + let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8; + + data[index * 4] = red; + data[index * 4 + 1] = green; + data[index * 4 + 2] = blue; + data[index * 4 + 3] = alpha; + + if let Some(color_cache) = huffman_info.color_cache.as_mut() { + color_cache.insert([red, green, blue, alpha]); + } + index += 1; + } else if code < 256 + 24 { + //backward reference, so go back and use that to add image data + let length_symbol = code - 256; + let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; + + let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; + let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; + let dist = Self::plane_code_to_distance(width, dist_code); + + if index < dist || num_values - index < length { + return Err(DecodingError::BitStreamError); + } + + if dist == 1 { + let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap(); + for i in 0..length { + data[index * 4 + i * 4..][..4].copy_from_slice(&value); + } + } else { + if index + length + 3 <= num_values { + let start = (index - dist) * 4; + data.copy_within(start..start + 16, index * 4); + + if length > 4 || dist < 4 { + for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) { + data.copy_within(start + i..start + i + 16, index * 4 + i); + } + } + } else { + for i in 0..length * 4 { + data[index * 4 + i] = data[index * 4 + i - dist * 4]; + } + } + + if let Some(color_cache) = huffman_info.color_cache.as_mut() { + for pixel in data[index * 4..][..length * 4].chunks_exact(4) { + color_cache.insert(pixel.try_into().unwrap()); + } + } + } + index += length; + } else { + //color cache, so use previously stored pixels to get this pixel + let color_cache = huffman_info + .color_cache + .as_mut() + .ok_or(DecodingError::BitStreamError)?; + let color = color_cache.lookup((code - 280).into()); + data[index * 4..][..4].copy_from_slice(&color); + index += 1; + + if index < next_block_start { + if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) { + if code >= 280 { + self.bit_reader.consume(bits)?; + data[index * 4..][..4] + .copy_from_slice(&color_cache.lookup((code - 280).into())); + index += 1; + } + } + } + } + } + + Ok(()) + } + + /// Reads color cache data from the bitstream + fn read_color_cache(&mut self) -> Result, DecodingError> { + if self.bit_reader.read_bits::(1)? == 1 { + let code_bits = self.bit_reader.read_bits::(4)?; + + if !(1..=11).contains(&code_bits) { + return Err(DecodingError::InvalidColorCacheBits(code_bits)); + } + + Ok(Some(code_bits)) + } else { + Ok(None) + } + } + + /// Gets the copy distance from the prefix code and bitstream + fn get_copy_distance( + bit_reader: &mut BitReader, + prefix_code: u16, + ) -> Result { + if prefix_code < 4 { + return Ok(usize::from(prefix_code + 1)); + } + let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); + let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; + + let bits = bit_reader.peek(extra_bits) as usize; + bit_reader.consume(extra_bits)?; + + Ok(offset + bits + 1) + } + + /// Gets distance to pixel + fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { + if plane_code > 120 { + plane_code - 120 + } else { + let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; + + let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); + if dist < 1 { + return 1; + } + dist.try_into().unwrap() + } + } +} + +#[derive(Debug, Clone)] +struct HuffmanInfo { + xsize: u16, + _ysize: u16, + color_cache: Option, + image: Vec, + bits: u8, + mask: u16, + huffman_code_groups: Vec, +} + +impl HuffmanInfo { + fn get_huff_index(&self, x: u16, y: u16) -> usize { + if self.bits == 0 { + return 0; + } + let position = + usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits); + let meta_huff_code: usize = usize::from(self.image[position]); + meta_huff_code + } +} + +#[derive(Debug, Clone)] +struct ColorCache { + color_cache_bits: u8, + color_cache: Vec<[u8; 4]>, +} + +impl ColorCache { + #[inline(always)] + fn insert(&mut self, color: [u8; 4]) { + let [r, g, b, a] = color; + let color_u32 = + (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24); + let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits); + self.color_cache[index as usize] = color; + } + + #[inline(always)] + fn lookup(&self, index: usize) -> [u8; 4] { + self.color_cache[index] + } +} + +#[derive(Debug, Clone)] +pub(crate) struct BitReader { + reader: R, + buffer: u64, + nbits: u8, +} + +impl BitReader { + const fn new(reader: R) -> Self { + Self { + reader, + buffer: 0, + nbits: 0, + } + } + + /// Fills the buffer with bits from the input stream. + /// + /// After this function, the internal buffer will contain 64-bits or have reached the end of + /// the input stream. + pub(crate) fn fill(&mut self) -> Result<(), DecodingError> { + debug_assert!(self.nbits < 64); + + let mut buf = self.reader.fill_buf()?; + if buf.len() >= 8 { + let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap()); + self.reader.consume(usize::from((63 - self.nbits) / 8)); + self.buffer |= lookahead << self.nbits; + self.nbits |= 56; + } else { + while !buf.is_empty() && self.nbits < 56 { + self.buffer |= u64::from(buf[0]) << self.nbits; + self.nbits += 8; + self.reader.consume(1); + buf = self.reader.fill_buf()?; + } + } + + Ok(()) + } + + /// Peeks at the next `num` bits in the buffer. + pub(crate) const fn peek(&self, num: u8) -> u64 { + self.buffer & ((1 << num) - 1) + } + + /// Peeks at the full buffer. + pub(crate) const fn peek_full(&self) -> u64 { + self.buffer + } + + /// Consumes `num` bits from the buffer returning an error if there are not enough bits. + pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> { + if self.nbits < num { + return Err(DecodingError::BitStreamError); + } + + self.buffer >>= num; + self.nbits -= num; + Ok(()) + } + + /// Convenience function to read a number of bits and convert them to a type. + pub(crate) fn read_bits>(&mut self, num: u8) -> Result { + debug_assert!(num as usize <= 8 * mem::size_of::()); + debug_assert!(num <= 32); + + if self.nbits < num { + self.fill()?; + } + let value = self.peek(num) as u32; + self.consume(num)?; + + value.try_into().map_err(|_| { + debug_assert!(false, "Value too large to fit in type"); + DecodingError::BitStreamError + }) + } +} + +#[cfg(test)] +mod test { + + use std::io::Cursor; + + use super::BitReader; + + #[test] + fn bit_read_test() { + //10011100 01000001 11100001 + let mut bit_reader = BitReader::new(Cursor::new(vec![0x9C, 0x41, 0xE1])); + + assert_eq!(bit_reader.read_bits::(3).unwrap(), 4); //100 + assert_eq!(bit_reader.read_bits::(2).unwrap(), 3); //11 + assert_eq!(bit_reader.read_bits::(6).unwrap(), 12); //001100 + assert_eq!(bit_reader.read_bits::(10).unwrap(), 40); //0000101000 + assert_eq!(bit_reader.read_bits::(3).unwrap(), 7); //111 + } + + #[test] + fn bit_read_error_test() { + //01101010 + let mut bit_reader = BitReader::new(Cursor::new(vec![0x6A])); + + assert_eq!(bit_reader.read_bits::(3).unwrap(), 2); //010 + assert_eq!(bit_reader.read_bits::(5).unwrap(), 13); //01101 + assert!(bit_reader.read_bits::(4).is_err()); //error + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lossless_transform.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless_transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/lossless_transform.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/lossless_transform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,716 @@ +use std::ops::Range; + +use crate::decoder::DecodingError; + +use super::lossless::subsample_size; + +#[derive(Debug, Clone)] +pub(crate) enum TransformType { + PredictorTransform { + size_bits: u8, + predictor_data: Vec, + }, + ColorTransform { + size_bits: u8, + transform_data: Vec, + }, + SubtractGreen, + ColorIndexingTransform { + table_size: u16, + table_data: Vec, + }, +} + +pub(crate) fn apply_predictor_transform( + image_data: &mut [u8], + width: u16, + height: u16, + size_bits: u8, + predictor_data: &[u8], +) -> Result<(), DecodingError> { + let block_xsize = usize::from(subsample_size(width, size_bits)); + let width = usize::from(width); + let height = usize::from(height); + + // Handle top and left borders specially. This involves ignoring mode and using specific + // predictors for each. + image_data[3] = image_data[3].wrapping_add(255); + apply_predictor_transform_1(image_data, 4..width * 4, width); + for y in 1..height { + for i in 0..4 { + image_data[y * width * 4 + i] = + image_data[y * width * 4 + i].wrapping_add(image_data[(y - 1) * width * 4 + i]); + } + } + + for y in 1..height { + for block_x in 0..block_xsize { + let block_index = (y >> size_bits) * block_xsize + block_x; + let predictor = predictor_data[block_index * 4 + 1]; + let start_index = (y * width + (block_x << size_bits).max(1)) * 4; + let end_index = (y * width + ((block_x + 1) << size_bits).min(width)) * 4; + + match predictor { + 0 => apply_predictor_transform_0(image_data, start_index..end_index, width), + 1 => apply_predictor_transform_1(image_data, start_index..end_index, width), + 2 => apply_predictor_transform_2(image_data, start_index..end_index, width), + 3 => apply_predictor_transform_3(image_data, start_index..end_index, width), + 4 => apply_predictor_transform_4(image_data, start_index..end_index, width), + 5 => apply_predictor_transform_5(image_data, start_index..end_index, width), + 6 => apply_predictor_transform_6(image_data, start_index..end_index, width), + 7 => apply_predictor_transform_7(image_data, start_index..end_index, width), + 8 => apply_predictor_transform_8(image_data, start_index..end_index, width), + 9 => apply_predictor_transform_9(image_data, start_index..end_index, width), + 10 => apply_predictor_transform_10(image_data, start_index..end_index, width), + 11 => apply_predictor_transform_11(image_data, start_index..end_index, width), + 12 => apply_predictor_transform_12(image_data, start_index..end_index, width), + 13 => apply_predictor_transform_13(image_data, start_index..end_index, width), + _ => {} + } + } + } + + Ok(()) +} +pub fn apply_predictor_transform_0(image_data: &mut [u8], range: Range, _width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start + 3; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(0xff); + i += 4; + } +} +pub fn apply_predictor_transform_1(image_data: &mut [u8], range: Range, _width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(image_data[i - 4]); + i += 1; + } +} +pub fn apply_predictor_transform_2(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(image_data[i - width * 4]); + i += 1; + } +} +pub fn apply_predictor_transform_3(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(image_data[i - width * 4 + 4]); + i += 1; + } +} +pub fn apply_predictor_transform_4(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(image_data[i - width * 4 - 4]); + i += 1; + } +} +pub fn apply_predictor_transform_5(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + + let mut prev: [u8; 4] = old[range.start - 4..][..4].try_into().unwrap(); + let top_right = &old[range.start - width * 4 + 4..]; + let top = &old[range.start - width * 4..]; + + for ((chunk, tr), t) in current + .chunks_exact_mut(4) + .zip(top_right.chunks_exact(4)) + .zip(top.chunks_exact(4)) + { + prev = [ + chunk[0].wrapping_add(average2_autovec(average2_autovec(prev[0], tr[0]), t[0])), + chunk[1].wrapping_add(average2_autovec(average2_autovec(prev[1], tr[1]), t[1])), + chunk[2].wrapping_add(average2_autovec(average2_autovec(prev[2], tr[2]), t[2])), + chunk[3].wrapping_add(average2_autovec(average2_autovec(prev[3], tr[3]), t[3])), + ]; + chunk.copy_from_slice(&prev); + } +} +pub fn apply_predictor_transform_6(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = + image_data[i].wrapping_add(average2(image_data[i - 4], image_data[i - width * 4 - 4])); + i += 1; + } +} +pub fn apply_predictor_transform_7(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + + let mut prev: [u8; 4] = old[range.start - 4..][..4].try_into().unwrap(); + let top = &old[range.start - width * 4..][..(range.end - range.start)]; + + let mut current_chunks = current.chunks_exact_mut(64); + let mut top_chunks = top.chunks_exact(64); + + for (current, top) in (&mut current_chunks).zip(&mut top_chunks) { + for (chunk, t) in current.chunks_exact_mut(4).zip(top.chunks_exact(4)) { + prev = [ + chunk[0].wrapping_add(average2_autovec(prev[0], t[0])), + chunk[1].wrapping_add(average2_autovec(prev[1], t[1])), + chunk[2].wrapping_add(average2_autovec(prev[2], t[2])), + chunk[3].wrapping_add(average2_autovec(prev[3], t[3])), + ]; + chunk.copy_from_slice(&prev); + } + } + for (chunk, t) in current_chunks + .into_remainder() + .chunks_exact_mut(4) + .zip(top_chunks.remainder().chunks_exact(4)) + { + prev = [ + chunk[0].wrapping_add(average2_autovec(prev[0], t[0])), + chunk[1].wrapping_add(average2_autovec(prev[1], t[1])), + chunk[2].wrapping_add(average2_autovec(prev[2], t[2])), + chunk[3].wrapping_add(average2_autovec(prev[3], t[3])), + ]; + chunk.copy_from_slice(&prev); + } +} +pub fn apply_predictor_transform_8(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(average2( + image_data[i - width * 4 - 4], + image_data[i - width * 4], + )); + i += 1; + } +} +pub fn apply_predictor_transform_9(image_data: &mut [u8], range: Range, width: usize) { + assert!(range.end <= image_data.len()); + let mut i = range.start; + while i < range.end { + image_data[i] = image_data[i].wrapping_add(average2( + image_data[i - width * 4], + image_data[i - width * 4 + 4], + )); + i += 1; + } +} +pub fn apply_predictor_transform_10(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + let mut prev: [u8; 4] = old[range.start - 4..][..4].try_into().unwrap(); + + let top_left = &old[range.start - width * 4 - 4..]; + let top = &old[range.start - width * 4..]; + let top_right = &old[range.start - width * 4 + 4..]; + + for (((chunk, tl), t), tr) in current + .chunks_exact_mut(4) + .zip(top_left.chunks_exact(4)) + .zip(top.chunks_exact(4)) + .zip(top_right.chunks_exact(4)) + { + prev = [ + chunk[0].wrapping_add(average2(average2(prev[0], tl[0]), average2(t[0], tr[0]))), + chunk[1].wrapping_add(average2(average2(prev[1], tl[1]), average2(t[1], tr[1]))), + chunk[2].wrapping_add(average2(average2(prev[2], tl[2]), average2(t[2], tr[2]))), + chunk[3].wrapping_add(average2(average2(prev[3], tl[3]), average2(t[3], tr[3]))), + ]; + chunk.copy_from_slice(&prev); + } +} +pub fn apply_predictor_transform_11(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + let top = &old[range.start - width * 4..]; + + let mut l = [ + i16::from(old[range.start - 4]), + i16::from(old[range.start - 3]), + i16::from(old[range.start - 2]), + i16::from(old[range.start - 1]), + ]; + let mut tl = [ + i16::from(old[range.start - width * 4 - 4]), + i16::from(old[range.start - width * 4 - 3]), + i16::from(old[range.start - width * 4 - 2]), + i16::from(old[range.start - width * 4 - 1]), + ]; + + for (chunk, top) in current.chunks_exact_mut(4).zip(top.chunks_exact(4)) { + let t = [ + i16::from(top[0]), + i16::from(top[1]), + i16::from(top[2]), + i16::from(top[3]), + ]; + + let mut predict_left = 0; + let mut predict_top = 0; + for i in 0..4 { + let predict = l[i] + t[i] - tl[i]; + predict_left += i16::abs(predict - l[i]); + predict_top += i16::abs(predict - t[i]); + } + + if predict_left < predict_top { + chunk.copy_from_slice(&[ + chunk[0].wrapping_add(l[0] as u8), + chunk[1].wrapping_add(l[1] as u8), + chunk[2].wrapping_add(l[2] as u8), + chunk[3].wrapping_add(l[3] as u8), + ]); + } else { + chunk.copy_from_slice(&[ + chunk[0].wrapping_add(t[0] as u8), + chunk[1].wrapping_add(t[1] as u8), + chunk[2].wrapping_add(t[2] as u8), + chunk[3].wrapping_add(t[3] as u8), + ]); + } + + tl = t; + l = [ + i16::from(chunk[0]), + i16::from(chunk[1]), + i16::from(chunk[2]), + i16::from(chunk[3]), + ]; + } +} +pub fn apply_predictor_transform_12(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + let mut prev: [u8; 4] = old[range.start - 4..][..4].try_into().unwrap(); + + let top_left = &old[range.start - width * 4 - 4..]; + let top = &old[range.start - width * 4..]; + + for ((chunk, tl), t) in current + .chunks_exact_mut(4) + .zip(top_left.chunks_exact(4)) + .zip(top.chunks_exact(4)) + { + prev = [ + chunk[0].wrapping_add(clamp_add_subtract_full( + i16::from(prev[0]), + i16::from(t[0]), + i16::from(tl[0]), + )), + chunk[1].wrapping_add(clamp_add_subtract_full( + i16::from(prev[1]), + i16::from(t[1]), + i16::from(tl[1]), + )), + chunk[2].wrapping_add(clamp_add_subtract_full( + i16::from(prev[2]), + i16::from(t[2]), + i16::from(tl[2]), + )), + chunk[3].wrapping_add(clamp_add_subtract_full( + i16::from(prev[3]), + i16::from(t[3]), + i16::from(tl[3]), + )), + ]; + chunk.copy_from_slice(&prev); + } +} +pub fn apply_predictor_transform_13(image_data: &mut [u8], range: Range, width: usize) { + let (old, current) = image_data[..range.end].split_at_mut(range.start); + let mut prev: [u8; 4] = old[range.start - 4..][..4].try_into().unwrap(); + + let top_left = &old[range.start - width * 4 - 4..][..(range.end - range.start)]; + let top = &old[range.start - width * 4..][..(range.end - range.start)]; + + for ((chunk, tl), t) in current + .chunks_exact_mut(4) + .zip(top_left.chunks_exact(4)) + .zip(top.chunks_exact(4)) + { + prev = [ + chunk[0].wrapping_add(clamp_add_subtract_half( + (i16::from(prev[0]) + i16::from(t[0])) / 2, + i16::from(tl[0]), + )), + chunk[1].wrapping_add(clamp_add_subtract_half( + (i16::from(prev[1]) + i16::from(t[1])) / 2, + i16::from(tl[1]), + )), + chunk[2].wrapping_add(clamp_add_subtract_half( + (i16::from(prev[2]) + i16::from(t[2])) / 2, + i16::from(tl[2]), + )), + chunk[3].wrapping_add(clamp_add_subtract_half( + (i16::from(prev[3]) + i16::from(t[3])) / 2, + i16::from(tl[3]), + )), + ]; + chunk.copy_from_slice(&prev); + } +} + +pub(crate) fn apply_color_transform( + image_data: &mut [u8], + width: u16, + size_bits: u8, + transform_data: &[u8], +) { + let block_xsize = usize::from(subsample_size(width, size_bits)); + let width = usize::from(width); + + for (y, row) in image_data.chunks_exact_mut(width * 4).enumerate() { + let row_transform_data_start = (y >> size_bits) * block_xsize * 4; + // the length of block_tf_data should be `block_xsize * 4`, so we could slice it with [..block_xsize * 4] + // but there is no point - `.zip()` runs until either of the iterators is consumed, + // so the extra slicing operation would be doing more work for no reason + let row_tf_data = &transform_data[row_transform_data_start..]; + + for (block, transform) in row + .chunks_mut(4 << size_bits) + .zip(row_tf_data.chunks_exact(4)) + { + let red_to_blue = transform[0]; + let green_to_blue = transform[1]; + let green_to_red = transform[2]; + + for pixel in block.chunks_exact_mut(4) { + let green = u32::from(pixel[1]); + let mut temp_red = u32::from(pixel[0]); + let mut temp_blue = u32::from(pixel[2]); + + temp_red += color_transform_delta(green_to_red as i8, green as i8); + temp_blue += color_transform_delta(green_to_blue as i8, green as i8); + temp_blue += color_transform_delta(red_to_blue as i8, temp_red as i8); + + pixel[0] = (temp_red & 0xff) as u8; + pixel[2] = (temp_blue & 0xff) as u8; + } + } + } +} + +pub(crate) fn apply_subtract_green_transform(image_data: &mut [u8]) { + for pixel in image_data.chunks_exact_mut(4) { + pixel[0] = pixel[0].wrapping_add(pixel[1]); + pixel[2] = pixel[2].wrapping_add(pixel[1]); + } +} + +pub(crate) fn apply_color_indexing_transform( + image_data: &mut [u8], + width: u16, + height: u16, + table_size: u16, + table_data: &[u8], +) { + assert!(table_size > 0); + if table_size > 16 { + // convert the table of colors into a Vec of color values that can be directly indexed + let mut table: Vec<[u8; 4]> = table_data + .chunks_exact(4) + // convince the compiler that each chunk is 4 bytes long, important for optimizations in the loop below + .map(|c| TryInto::<[u8; 4]>::try_into(c).unwrap()) + .collect(); + // pad the table to 256 values if it's smaller than that so we could index into it by u8 without bounds checks + // also required for correctness: WebP spec requires out-of-bounds indices to be treated as [0,0,0,0] + table.resize(256, [0; 4]); + // convince the compiler that the length of the table is 256 to avoid bounds checks in the loop below + let table: &[[u8; 4]; 256] = table.as_slice().try_into().unwrap(); + + for pixel in image_data.chunks_exact_mut(4) { + // Index is in G channel. + // WebP format encodes ARGB pixels, but we permute to RGBA immediately after reading from the bitstream. + pixel.copy_from_slice(&table[pixel[1] as usize]); + } + } else { + // table_size_u16 is 1 to 16 + let table_size = table_size as u8; + + // Dispatch to specialized implementation for each table size band for performance. + // Otherwise the compiler doesn't know the size of our copies + // and ends up calling out to memmove for every pixel even though a single load is sufficient. + if table_size <= 2 { + // Max 2 colors, 1 bit per pixel index -> W_BITS = 3 + const W_BITS_VAL: u8 = 3; + // EXP_ENTRY_SIZE is 4 bytes/pixel * (1 << W_BITS_VAL) pixels/entry + const EXP_ENTRY_SIZE_VAL: usize = 4 * (1 << W_BITS_VAL); // 4 * 8 = 32 + apply_color_indexing_transform_small_table::( + image_data, width, height, table_size, table_data, + ); + } else if table_size <= 4 { + // Max 4 colors, 2 bits per pixel index -> W_BITS = 2 + const W_BITS_VAL: u8 = 2; + const EXP_ENTRY_SIZE_VAL: usize = 4 * (1 << W_BITS_VAL); // 4 * 4 = 16 + apply_color_indexing_transform_small_table::( + image_data, width, height, table_size, table_data, + ); + } else { + // Max 16 colors (5 to 16), 4 bits per pixel index -> W_BITS = 1 + // table_size_u16 must be <= 16 here + const W_BITS_VAL: u8 = 1; + const EXP_ENTRY_SIZE_VAL: usize = 4 * (1 << W_BITS_VAL); // 4 * 2 = 8 + apply_color_indexing_transform_small_table::( + image_data, width, height, table_size, table_data, + ); + } + } +} + +// Helper function with const generics for W_BITS and EXP_ENTRY_SIZE +fn apply_color_indexing_transform_small_table( + image_data: &mut [u8], + width: u16, + height: u16, + table_size: u8, // Max 16 + table_data: &[u8], +) { + // As of Rust 1.87 we cannot use `const` here. The compiler can still optimize them heavily + // because W_BITS is a const generic for each instantiation of this function. + let pixels_per_packed_byte_u8: u8 = 1 << W_BITS; + let bits_per_entry_u8: u8 = 8 / pixels_per_packed_byte_u8; + let mask_u8: u8 = (1 << bits_per_entry_u8) - 1; + + // This is also effectively a compile-time constant for each instantiation. + let pixels_per_packed_byte_usize: usize = pixels_per_packed_byte_u8 as usize; + + // Verify that the passed EXP_ENTRY_SIZE matches our calculation based on W_BITS, just as a sanity check. + debug_assert_eq!( + EXP_ENTRY_SIZE, + 4 * pixels_per_packed_byte_usize, + "Mismatch in EXP_ENTRY_SIZE" + ); + + // Precompute the full lookup table. + // Each of the 256 possible packed byte values maps to an array of RGBA pixels. + // The array type uses the const generic EXP_ENTRY_SIZE. + let expanded_lookup_table_storage: Vec<[u8; EXP_ENTRY_SIZE]> = (0..256u16) + .map(|packed_byte_value_u16| { + let mut entry_pixels_array = [0u8; EXP_ENTRY_SIZE]; // Uses const generic + let packed_byte_value = packed_byte_value_u16 as u8; + + // Loop bound is effectively constant for each instantiation. + for pixel_sub_index in 0..pixels_per_packed_byte_usize { + let shift_amount = (pixel_sub_index as u8) * bits_per_entry_u8; + let k = (packed_byte_value >> shift_amount) & mask_u8; + + let color_source_array: [u8; 4] = if k < table_size { + let color_data_offset = usize::from(k) * 4; + table_data[color_data_offset..color_data_offset + 4] + .try_into() + .unwrap() + } else { + [0u8; 4] // WebP spec: out-of-bounds indices are [0,0,0,0] + }; + + let array_fill_offset = pixel_sub_index * 4; + entry_pixels_array[array_fill_offset..array_fill_offset + 4] + .copy_from_slice(&color_source_array); + } + entry_pixels_array + }) + .collect(); + + let expanded_lookup_table_array: &[[u8; EXP_ENTRY_SIZE]; 256] = + expanded_lookup_table_storage.as_slice().try_into().unwrap(); + + let packed_image_width_in_blocks = width.div_ceil(pixels_per_packed_byte_u8.into()) as usize; + + if width == 0 || height == 0 { + return; + } + + let final_block_expanded_size_bytes = + (width as usize * 4) - EXP_ENTRY_SIZE * (packed_image_width_in_blocks.saturating_sub(1)); + + let input_stride_bytes_packed = packed_image_width_in_blocks * 4; + let output_stride_bytes_expanded = width as usize * 4; + + let mut packed_indices_for_row: Vec = vec![0; packed_image_width_in_blocks]; + + for y_rev_idx in 0..height as usize { + let y = height as usize - 1 - y_rev_idx; + + let packed_row_input_global_offset = y * input_stride_bytes_packed; + let packed_argb_row_slice = + &image_data[packed_row_input_global_offset..][..input_stride_bytes_packed]; + + for (packed_argb_chunk, packed_idx) in packed_argb_row_slice + .chunks_exact(4) + .zip(packed_indices_for_row.iter_mut()) + { + *packed_idx = packed_argb_chunk[1]; + } + + let output_row_global_offset = y * output_stride_bytes_expanded; + let output_row_slice_mut = + &mut image_data[output_row_global_offset..][..output_stride_bytes_expanded]; + + let num_full_blocks = packed_image_width_in_blocks.saturating_sub(1); + + let (full_blocks_part, final_block_part) = + output_row_slice_mut.split_at_mut(num_full_blocks * EXP_ENTRY_SIZE); + + for (output_chunk_slice, &packed_index_byte) in full_blocks_part + .chunks_exact_mut(EXP_ENTRY_SIZE) // Uses const generic to avoid expensive memmove call + .zip(packed_indices_for_row.iter()) + { + let output_chunk_array: &mut [u8; EXP_ENTRY_SIZE] = + output_chunk_slice.try_into().unwrap(); + + let colors_data_array = &expanded_lookup_table_array[packed_index_byte as usize]; + + *output_chunk_array = *colors_data_array; + } + + if packed_image_width_in_blocks > 0 { + let final_packed_index_byte = packed_indices_for_row[packed_image_width_in_blocks - 1]; + let colors_data_full_array = + &expanded_lookup_table_array[final_packed_index_byte as usize]; + + final_block_part + .copy_from_slice(&colors_data_full_array[..final_block_expanded_size_bytes]); + } + } +} + +//predictor functions + +/// Get average of 2 bytes +fn average2(a: u8, b: u8) -> u8 { + ((u16::from(a) + u16::from(b)) / 2) as u8 +} + +/// Get average of 2 bytes, allows some predictors to be autovectorized by +/// keeping computation within lanes of `u8`. +/// +/// LLVM is capable of optimizing `average2` into this but not in all cases. +fn average2_autovec(a: u8, b: u8) -> u8 { + (a & b) + ((a ^ b) >> 1) +} + +/// Clamp add subtract full on one part +fn clamp_add_subtract_full(a: i16, b: i16, c: i16) -> u8 { + // Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. + #![allow(clippy::manual_clamp)] + (a + b - c).max(0).min(255) as u8 +} + +/// Clamp add subtract half on one part +fn clamp_add_subtract_half(a: i16, b: i16) -> u8 { + // Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. + #![allow(clippy::manual_clamp)] + (a + (a - b) / 2).max(0).min(255) as u8 +} + +/// Does color transform on 2 numbers +fn color_transform_delta(t: i8, c: i8) -> u32 { + (i32::from(t) * i32::from(c)) as u32 >> 5 +} + +#[cfg(all(test, feature = "_benchmarks"))] +mod benches { + use rand::Rng; + use test::{black_box, Bencher}; + + fn measure_predictor(b: &mut Bencher, predictor: fn(&mut [u8], std::ops::Range, usize)) { + let width = 256; + let mut data = vec![0u8; width * 8]; + rand::thread_rng().fill(&mut data[..]); + b.bytes = 4 * width as u64 - 4; + b.iter(|| { + predictor( + black_box(&mut data), + black_box(width * 4 + 4..width * 8), + black_box(width), + ) + }); + } + + #[bench] + fn predictor00(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_0); + } + #[bench] + fn predictor01(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_1); + } + #[bench] + fn predictor02(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_2); + } + #[bench] + fn predictor03(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_3); + } + #[bench] + fn predictor04(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_4); + } + #[bench] + fn predictor05(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_5); + } + #[bench] + fn predictor06(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_6); + } + #[bench] + fn predictor07(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_7); + } + #[bench] + fn predictor08(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_8); + } + #[bench] + fn predictor09(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_9); + } + #[bench] + fn predictor10(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_10); + } + #[bench] + fn predictor11(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_11); + } + #[bench] + fn predictor12(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_12); + } + #[bench] + fn predictor13(b: &mut Bencher) { + measure_predictor(b, super::apply_predictor_transform_13); + } + + #[bench] + fn color_transform(b: &mut Bencher) { + let width = 256; + let height = 256; + let size_bits = 3; + let mut data = vec![0u8; width * height * 4]; + let mut transform_data = vec![0u8; (width * height * 4) >> (size_bits * 2)]; + rand::thread_rng().fill(&mut data[..]); + rand::thread_rng().fill(&mut transform_data[..]); + b.bytes = 4 * width as u64 * height as u64; + b.iter(|| { + super::apply_color_transform( + black_box(&mut data), + black_box(width as u16), + black_box(size_bits), + black_box(&transform_data), + ); + }); + } + + #[bench] + fn subtract_green(b: &mut Bencher) { + let mut data = vec![0u8; 1024 * 4]; + rand::thread_rng().fill(&mut data[..]); + b.bytes = data.len() as u64; + b.iter(|| { + super::apply_subtract_green_transform(black_box(&mut data)); + }); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/mod.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/mod.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +//! Decoding and Encoding of WebP Images + +#[cfg(feature = "webp-encoder")] +pub use self::encoder::{WebPEncoder, WebPQuality}; + +#[cfg(feature = "webp-encoder")] +mod encoder; + +#[cfg(feature = "webp")] +pub use self::decoder::WebPDecoder; + +#[cfg(feature = "webp")] +mod decoder; +#[cfg(feature = "webp")] +mod extended; +#[cfg(feature = "webp")] +mod huffman; +#[cfg(feature = "webp")] +mod loop_filter; +#[cfg(feature = "webp")] +mod lossless; +#[cfg(feature = "webp")] +mod lossless_transform; +#[cfg(feature = "webp")] +mod transform; + +#[cfg(feature = "webp")] +pub mod vp8; diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/transform.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/transform.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/transform.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/transform.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,83 @@ +static CONST1: i64 = 20091; +static CONST2: i64 = 35468; + +pub(crate) fn idct4x4(block: &mut [i32]) { + // The intermediate results may overflow the types, so we stretch the type. + fn fetch(block: &[i32], idx: usize) -> i64 { + i64::from(block[idx]) + } + + // Perform one lenght check up front to avoid subsequent bounds checks in this function + assert!(block.len() >= 16); + + for i in 0usize..4 { + let a1 = fetch(block, i) + fetch(block, 8 + i); + let b1 = fetch(block, i) - fetch(block, 8 + i); + + let t1 = (fetch(block, 4 + i) * CONST2) >> 16; + let t2 = fetch(block, 12 + i) + ((fetch(block, 12 + i) * CONST1) >> 16); + let c1 = t1 - t2; + + let t1 = fetch(block, 4 + i) + ((fetch(block, 4 + i) * CONST1) >> 16); + let t2 = (fetch(block, 12 + i) * CONST2) >> 16; + let d1 = t1 + t2; + + block[i] = (a1 + d1) as i32; + block[4 + i] = (b1 + c1) as i32; + block[4 * 3 + i] = (a1 - d1) as i32; + block[4 * 2 + i] = (b1 - c1) as i32; + } + + for i in 0usize..4 { + let a1 = fetch(block, 4 * i) + fetch(block, 4 * i + 2); + let b1 = fetch(block, 4 * i) - fetch(block, 4 * i + 2); + + let t1 = (fetch(block, 4 * i + 1) * CONST2) >> 16; + let t2 = fetch(block, 4 * i + 3) + ((fetch(block, 4 * i + 3) * CONST1) >> 16); + let c1 = t1 - t2; + + let t1 = fetch(block, 4 * i + 1) + ((fetch(block, 4 * i + 1) * CONST1) >> 16); + let t2 = (fetch(block, 4 * i + 3) * CONST2) >> 16; + let d1 = t1 + t2; + + block[4 * i] = ((a1 + d1 + 4) >> 3) as i32; + block[4 * i + 3] = ((a1 - d1 + 4) >> 3) as i32; + block[4 * i + 1] = ((b1 + c1 + 4) >> 3) as i32; + block[4 * i + 2] = ((b1 - c1 + 4) >> 3) as i32; + } +} + +// 14.3 +pub(crate) fn iwht4x4(block: &mut [i32]) { + // Perform one length check up front to avoid subsequent bounds checks in this function + assert!(block.len() >= 16); + + for i in 0usize..4 { + let a1 = block[i] + block[12 + i]; + let b1 = block[4 + i] + block[8 + i]; + let c1 = block[4 + i] - block[8 + i]; + let d1 = block[i] - block[12 + i]; + + block[i] = a1 + b1; + block[4 + i] = c1 + d1; + block[8 + i] = a1 - b1; + block[12 + i] = d1 - c1; + } + + for block in block.chunks_exact_mut(4) { + let a1 = block[0] + block[3]; + let b1 = block[1] + block[2]; + let c1 = block[1] - block[2]; + let d1 = block[0] - block[3]; + + let a2 = a1 + b1; + let b2 = c1 + d1; + let c2 = a1 - b1; + let d2 = d1 - c1; + + block[0] = (a2 + 3) >> 3; + block[1] = (b2 + 3) >> 3; + block[2] = (c2 + 3) >> 3; + block[3] = (d2 + 3) >> 3; + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/vp8.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/vp8.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,2897 @@ +//! An implementation of the VP8 Video Codec +//! +//! This module contains a partial implementation of the +//! VP8 video format as defined in RFC-6386. +//! +//! It decodes Keyframes only. +//! VP8 is the underpinning of the WebP image format +//! +//! # Related Links +//! * [rfc-6386](http://tools.ietf.org/html/rfc6386) - The VP8 Data Format and Decoding Guide +//! * [VP8.pdf](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37073.pdf) - An overview of of the VP8 format + +use byteorder_lite::{LittleEndian, ReadBytesExt}; +use std::default::Default; +use std::io::Read; + +use crate::decoder::{DecodingError, UpsamplingMethod}; +use crate::yuv; + +use super::vp8_arithmetic_decoder::ArithmeticDecoder; +use super::{loop_filter, transform}; + +const MAX_SEGMENTS: usize = 4; +const NUM_DCT_TOKENS: usize = 12; + +// Prediction modes +const DC_PRED: i8 = 0; +const V_PRED: i8 = 1; +const H_PRED: i8 = 2; +const TM_PRED: i8 = 3; +const B_PRED: i8 = 4; + +const B_DC_PRED: i8 = 0; +const B_TM_PRED: i8 = 1; +const B_VE_PRED: i8 = 2; +const B_HE_PRED: i8 = 3; +const B_LD_PRED: i8 = 4; +const B_RD_PRED: i8 = 5; +const B_VR_PRED: i8 = 6; +const B_VL_PRED: i8 = 7; +const B_HD_PRED: i8 = 8; +const B_HU_PRED: i8 = 9; + +// Prediction mode enum +#[repr(i8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +enum LumaMode { + /// Predict DC using row above and column to the left. + #[default] + DC = DC_PRED, + + /// Predict rows using row above. + V = V_PRED, + + /// Predict columns using column to the left. + H = H_PRED, + + /// Propagate second differences. + TM = TM_PRED, + + /// Each Y subblock is independently predicted. + B = B_PRED, +} + +#[repr(i8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +enum ChromaMode { + /// Predict DC using row above and column to the left. + #[default] + DC = DC_PRED, + + /// Predict rows using row above. + V = V_PRED, + + /// Predict columns using column to the left. + H = H_PRED, + + /// Propagate second differences. + TM = TM_PRED, +} + +#[repr(i8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +enum IntraMode { + #[default] + DC = B_DC_PRED, + TM = B_TM_PRED, + VE = B_VE_PRED, + HE = B_HE_PRED, + LD = B_LD_PRED, + RD = B_RD_PRED, + VR = B_VR_PRED, + VL = B_VL_PRED, + HD = B_HD_PRED, + HU = B_HU_PRED, +} + +type Prob = u8; + +#[derive(Clone, Copy)] +pub(crate) struct TreeNode { + pub left: u8, + pub right: u8, + pub prob: Prob, + pub index: u8, +} + +impl TreeNode { + const UNINIT: TreeNode = TreeNode { + left: 0, + right: 0, + prob: 0, + index: 0, + }; + + const fn prepare_branch(t: i8) -> u8 { + if t > 0 { + (t as u8) / 2 + } else { + let value = -t; + 0x80 | (value as u8) + } + } + + pub(crate) const fn value_from_branch(t: u8) -> i8 { + (t & !0x80) as i8 + } +} + +const fn tree_nodes_from( + tree: [i8; N], + probs: [Prob; M], +) -> [TreeNode; M] { + if N != 2 * M { + panic!("invalid tree with probs"); + } + let mut nodes = [TreeNode::UNINIT; M]; + let mut i = 0; + while i < M { + nodes[i].left = TreeNode::prepare_branch(tree[2 * i]); + nodes[i].right = TreeNode::prepare_branch(tree[2 * i + 1]); + nodes[i].prob = probs[i]; + nodes[i].index = i as u8; + i += 1; + } + nodes +} + +const SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3]; + +const SEGMENT_TREE_NODE_DEFAULTS: [TreeNode; 3] = tree_nodes_from(SEGMENT_ID_TREE, [255; 3]); + +// Section 11.2 +// Tree for determining the keyframe luma intra prediction modes: +const KEYFRAME_YMODE_TREE: [i8; 8] = [-B_PRED, 2, 4, 6, -DC_PRED, -V_PRED, -H_PRED, -TM_PRED]; + +// Default probabilities for decoding the keyframe luma modes +const KEYFRAME_YMODE_PROBS: [Prob; 4] = [145, 156, 163, 128]; + +const KEYFRAME_YMODE_NODES: [TreeNode; 4] = + tree_nodes_from(KEYFRAME_YMODE_TREE, KEYFRAME_YMODE_PROBS); + +// Tree for determining the keyframe B_PRED mode: +const KEYFRAME_BPRED_MODE_TREE: [i8; 18] = [ + -B_DC_PRED, 2, -B_TM_PRED, 4, -B_VE_PRED, 6, 8, 12, -B_HE_PRED, 10, -B_RD_PRED, -B_VR_PRED, + -B_LD_PRED, 14, -B_VL_PRED, 16, -B_HD_PRED, -B_HU_PRED, +]; + +// Probabilities for the BPRED_MODE_TREE +const KEYFRAME_BPRED_MODE_PROBS: [[[Prob; 9]; 10]; 10] = [ + [ + [231, 120, 48, 89, 115, 113, 120, 152, 112], + [152, 179, 64, 126, 170, 118, 46, 70, 95], + [175, 69, 143, 80, 85, 82, 72, 155, 103], + [56, 58, 10, 171, 218, 189, 17, 13, 152], + [144, 71, 10, 38, 171, 213, 144, 34, 26], + [114, 26, 17, 163, 44, 195, 21, 10, 173], + [121, 24, 80, 195, 26, 62, 44, 64, 85], + [170, 46, 55, 19, 136, 160, 33, 206, 71], + [63, 20, 8, 114, 114, 208, 12, 9, 226], + [81, 40, 11, 96, 182, 84, 29, 16, 36], + ], + [ + [134, 183, 89, 137, 98, 101, 106, 165, 148], + [72, 187, 100, 130, 157, 111, 32, 75, 80], + [66, 102, 167, 99, 74, 62, 40, 234, 128], + [41, 53, 9, 178, 241, 141, 26, 8, 107], + [104, 79, 12, 27, 217, 255, 87, 17, 7], + [74, 43, 26, 146, 73, 166, 49, 23, 157], + [65, 38, 105, 160, 51, 52, 31, 115, 128], + [87, 68, 71, 44, 114, 51, 15, 186, 23], + [47, 41, 14, 110, 182, 183, 21, 17, 194], + [66, 45, 25, 102, 197, 189, 23, 18, 22], + ], + [ + [88, 88, 147, 150, 42, 46, 45, 196, 205], + [43, 97, 183, 117, 85, 38, 35, 179, 61], + [39, 53, 200, 87, 26, 21, 43, 232, 171], + [56, 34, 51, 104, 114, 102, 29, 93, 77], + [107, 54, 32, 26, 51, 1, 81, 43, 31], + [39, 28, 85, 171, 58, 165, 90, 98, 64], + [34, 22, 116, 206, 23, 34, 43, 166, 73], + [68, 25, 106, 22, 64, 171, 36, 225, 114], + [34, 19, 21, 102, 132, 188, 16, 76, 124], + [62, 18, 78, 95, 85, 57, 50, 48, 51], + ], + [ + [193, 101, 35, 159, 215, 111, 89, 46, 111], + [60, 148, 31, 172, 219, 228, 21, 18, 111], + [112, 113, 77, 85, 179, 255, 38, 120, 114], + [40, 42, 1, 196, 245, 209, 10, 25, 109], + [100, 80, 8, 43, 154, 1, 51, 26, 71], + [88, 43, 29, 140, 166, 213, 37, 43, 154], + [61, 63, 30, 155, 67, 45, 68, 1, 209], + [142, 78, 78, 16, 255, 128, 34, 197, 171], + [41, 40, 5, 102, 211, 183, 4, 1, 221], + [51, 50, 17, 168, 209, 192, 23, 25, 82], + ], + [ + [125, 98, 42, 88, 104, 85, 117, 175, 82], + [95, 84, 53, 89, 128, 100, 113, 101, 45], + [75, 79, 123, 47, 51, 128, 81, 171, 1], + [57, 17, 5, 71, 102, 57, 53, 41, 49], + [115, 21, 2, 10, 102, 255, 166, 23, 6], + [38, 33, 13, 121, 57, 73, 26, 1, 85], + [41, 10, 67, 138, 77, 110, 90, 47, 114], + [101, 29, 16, 10, 85, 128, 101, 196, 26], + [57, 18, 10, 102, 102, 213, 34, 20, 43], + [117, 20, 15, 36, 163, 128, 68, 1, 26], + ], + [ + [138, 31, 36, 171, 27, 166, 38, 44, 229], + [67, 87, 58, 169, 82, 115, 26, 59, 179], + [63, 59, 90, 180, 59, 166, 93, 73, 154], + [40, 40, 21, 116, 143, 209, 34, 39, 175], + [57, 46, 22, 24, 128, 1, 54, 17, 37], + [47, 15, 16, 183, 34, 223, 49, 45, 183], + [46, 17, 33, 183, 6, 98, 15, 32, 183], + [65, 32, 73, 115, 28, 128, 23, 128, 205], + [40, 3, 9, 115, 51, 192, 18, 6, 223], + [87, 37, 9, 115, 59, 77, 64, 21, 47], + ], + [ + [104, 55, 44, 218, 9, 54, 53, 130, 226], + [64, 90, 70, 205, 40, 41, 23, 26, 57], + [54, 57, 112, 184, 5, 41, 38, 166, 213], + [30, 34, 26, 133, 152, 116, 10, 32, 134], + [75, 32, 12, 51, 192, 255, 160, 43, 51], + [39, 19, 53, 221, 26, 114, 32, 73, 255], + [31, 9, 65, 234, 2, 15, 1, 118, 73], + [88, 31, 35, 67, 102, 85, 55, 186, 85], + [56, 21, 23, 111, 59, 205, 45, 37, 192], + [55, 38, 70, 124, 73, 102, 1, 34, 98], + ], + [ + [102, 61, 71, 37, 34, 53, 31, 243, 192], + [69, 60, 71, 38, 73, 119, 28, 222, 37], + [68, 45, 128, 34, 1, 47, 11, 245, 171], + [62, 17, 19, 70, 146, 85, 55, 62, 70], + [75, 15, 9, 9, 64, 255, 184, 119, 16], + [37, 43, 37, 154, 100, 163, 85, 160, 1], + [63, 9, 92, 136, 28, 64, 32, 201, 85], + [86, 6, 28, 5, 64, 255, 25, 248, 1], + [56, 8, 17, 132, 137, 255, 55, 116, 128], + [58, 15, 20, 82, 135, 57, 26, 121, 40], + ], + [ + [164, 50, 31, 137, 154, 133, 25, 35, 218], + [51, 103, 44, 131, 131, 123, 31, 6, 158], + [86, 40, 64, 135, 148, 224, 45, 183, 128], + [22, 26, 17, 131, 240, 154, 14, 1, 209], + [83, 12, 13, 54, 192, 255, 68, 47, 28], + [45, 16, 21, 91, 64, 222, 7, 1, 197], + [56, 21, 39, 155, 60, 138, 23, 102, 213], + [85, 26, 85, 85, 128, 128, 32, 146, 171], + [18, 11, 7, 63, 144, 171, 4, 4, 246], + [35, 27, 10, 146, 174, 171, 12, 26, 128], + ], + [ + [190, 80, 35, 99, 180, 80, 126, 54, 45], + [85, 126, 47, 87, 176, 51, 41, 20, 32], + [101, 75, 128, 139, 118, 146, 116, 128, 85], + [56, 41, 15, 176, 236, 85, 37, 9, 62], + [146, 36, 19, 30, 171, 255, 97, 27, 20], + [71, 30, 17, 119, 118, 255, 17, 18, 138], + [101, 38, 60, 138, 55, 70, 43, 26, 142], + [138, 45, 61, 62, 219, 1, 81, 188, 64], + [32, 41, 20, 117, 151, 142, 20, 21, 163], + [112, 19, 12, 61, 195, 128, 48, 4, 24], + ], +]; + +const KEYFRAME_BPRED_MODE_NODES: [[[TreeNode; 9]; 10]; 10] = { + let mut output = [[[TreeNode::UNINIT; 9]; 10]; 10]; + let mut i = 0; + while i < output.len() { + let mut j = 0; + while j < output[i].len() { + output[i][j] = + tree_nodes_from(KEYFRAME_BPRED_MODE_TREE, KEYFRAME_BPRED_MODE_PROBS[i][j]); + j += 1; + } + i += 1; + } + output +}; + +// Section 11.4 Tree for determining macroblock the chroma mode +const KEYFRAME_UV_MODE_TREE: [i8; 6] = [-DC_PRED, 2, -V_PRED, 4, -H_PRED, -TM_PRED]; + +// Probabilities for determining macroblock mode +const KEYFRAME_UV_MODE_PROBS: [Prob; 3] = [142, 114, 183]; + +const KEYFRAME_UV_MODE_NODES: [TreeNode; 3] = + tree_nodes_from(KEYFRAME_UV_MODE_TREE, KEYFRAME_UV_MODE_PROBS); + +// Section 13.4 +type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4]; +type TokenProbTreeNodes = [[[[TreeNode; NUM_DCT_TOKENS - 1]; 3]; 8]; 4]; + +// Probabilities that a token's probability will be updated +const COEFF_UPDATE_PROBS: TokenProbTables = [ + [ + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255], + [249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255], + [234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255], + [250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255], + [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + ], + [ + [ + [217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255], + [234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255], + ], + [ + [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + ], + [ + [ + [186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255], + [234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255], + [251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255], + ], + [ + [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + ], + [ + [ + [248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255], + [248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255], + [248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255], + [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + [ + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + ], + ], +]; + +// Section 13.5 +// Default Probabilities for tokens +const COEFF_PROBS: TokenProbTables = [ + [ + [ + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + ], + [ + [253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128], + [189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128], + [106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128], + ], + [ + [1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128], + [181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128], + [78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128], + ], + [ + [1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128], + [184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128], + [77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128], + ], + [ + [1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128], + [170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128], + [37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128], + ], + [ + [1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128], + [207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128], + [102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128], + ], + [ + [1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128], + [177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128], + [80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128], + ], + [ + [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + ], + ], + [ + [ + [198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62], + [131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1], + [68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128], + ], + [ + [1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128], + [184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128], + [81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128], + ], + [ + [1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128], + [99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128], + [23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128], + ], + [ + [1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128], + [109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128], + [44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128], + ], + [ + [1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128], + [94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128], + [22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128], + ], + [ + [1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128], + [124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128], + [35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128], + ], + [ + [1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128], + [121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128], + [45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128], + ], + [ + [1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128], + [203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128], + [137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128], + ], + ], + [ + [ + [253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128], + [175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128], + [73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128], + ], + [ + [1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128], + [239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128], + [155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128], + ], + [ + [1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128], + [201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128], + [69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128], + ], + [ + [1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128], + [223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128], + [141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128], + ], + [ + [1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128], + [190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128], + [149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + ], + [ + [1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128], + ], + [ + [1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128], + [213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128], + [55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128], + ], + [ + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], + ], + ], + [ + [ + [202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255], + [126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128], + [61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128], + ], + [ + [1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128], + [166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128], + [39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128], + ], + [ + [1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128], + [124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128], + [24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128], + ], + [ + [1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128], + [149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128], + [28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128], + ], + [ + [1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128], + [123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128], + [20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128], + ], + [ + [1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128], + [168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128], + [47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128], + ], + [ + [1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128], + [141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128], + [42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128], + ], + [ + [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + [238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], + ], + ], +]; + +const COEFF_PROB_NODES: TokenProbTreeNodes = { + let mut output = [[[[TreeNode::UNINIT; 11]; 3]; 8]; 4]; + let mut i = 0; + while i < output.len() { + let mut j = 0; + while j < output[i].len() { + let mut k = 0; + while k < output[i][j].len() { + output[i][j][k] = tree_nodes_from(DCT_TOKEN_TREE, COEFF_PROBS[i][j][k]); + k += 1; + } + j += 1; + } + i += 1; + } + output +}; + +// DCT Tokens +const DCT_0: i8 = 0; +const DCT_1: i8 = 1; +const DCT_2: i8 = 2; +const DCT_3: i8 = 3; +const DCT_4: i8 = 4; +const DCT_CAT1: i8 = 5; +const DCT_CAT2: i8 = 6; +const DCT_CAT3: i8 = 7; +const DCT_CAT4: i8 = 8; +const DCT_CAT5: i8 = 9; +const DCT_CAT6: i8 = 10; +const DCT_EOB: i8 = 11; + +const DCT_TOKEN_TREE: [i8; 22] = [ + -DCT_EOB, 2, -DCT_0, 4, -DCT_1, 6, 8, 12, -DCT_2, 10, -DCT_3, -DCT_4, 14, 16, -DCT_CAT1, + -DCT_CAT2, 18, 20, -DCT_CAT3, -DCT_CAT4, -DCT_CAT5, -DCT_CAT6, +]; + +const PROB_DCT_CAT: [[Prob; 12]; 6] = [ + [159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [165, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0], + [180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0], + [254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0], +]; + +const DCT_CAT_BASE: [u8; 6] = [5, 7, 11, 19, 35, 67]; +const COEFF_BANDS: [u8; 16] = [0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7]; + +#[rustfmt::skip] +const DC_QUANT: [i16; 128] = [ + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157, +]; + +#[rustfmt::skip] +const AC_QUANT: [i16; 128] = [ + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284, +]; + +const ZIGZAG: [u8; 16] = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15]; + +#[derive(Default, Clone, Copy)] +struct MacroBlock { + bpred: [IntraMode; 16], + complexity: [u8; 9], + luma_mode: LumaMode, + chroma_mode: ChromaMode, + segmentid: u8, + coeffs_skipped: bool, + non_zero_dct: bool, +} + +/// A Representation of the last decoded video frame +#[derive(Default, Debug, Clone)] +pub struct Frame { + /// The width of the luma plane + pub width: u16, + + /// The height of the luma plane + pub height: u16, + + /// The luma plane of the frame + pub ybuf: Vec, + + /// The blue plane of the frame + pub ubuf: Vec, + + /// The red plane of the frame + pub vbuf: Vec, + + /// Indicates whether this frame is a keyframe + pub keyframe: bool, + + version: u8, + + /// Indicates whether this frame is intended for display + pub for_display: bool, + + // Section 9.2 + /// The pixel type of the frame as defined by Section 9.2 + /// of the VP8 Specification + pub pixel_type: u8, + + // Section 9.4 and 15 + filter_type: bool, //if true uses simple filter // if false uses normal filter + filter_level: u8, + sharpness_level: u8, +} + +impl Frame { + const fn chroma_width(&self) -> u16 { + self.width.div_ceil(2) + } + + const fn buffer_width(&self) -> u16 { + let difference = self.width % 16; + if difference > 0 { + self.width + (16 - difference % 16) + } else { + self.width + } + } + + /// Fills an rgb buffer from the YUV buffers + pub(crate) fn fill_rgb(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) { + const BPP: usize = 3; + + match upsampling_method { + UpsamplingMethod::Bilinear => { + yuv::fill_rgb_buffer_fancy::( + buf, + &self.ybuf, + &self.ubuf, + &self.vbuf, + usize::from(self.width), + usize::from(self.height), + usize::from(self.buffer_width()), + ); + } + UpsamplingMethod::Simple => { + yuv::fill_rgb_buffer_simple::( + buf, + &self.ybuf, + &self.ubuf, + &self.vbuf, + usize::from(self.width), + usize::from(self.chroma_width()), + usize::from(self.buffer_width()), + ); + } + } + } + + /// Fills an rgba buffer from the YUV buffers + pub(crate) fn fill_rgba(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) { + const BPP: usize = 4; + + match upsampling_method { + UpsamplingMethod::Bilinear => { + yuv::fill_rgb_buffer_fancy::( + buf, + &self.ybuf, + &self.ubuf, + &self.vbuf, + usize::from(self.width), + usize::from(self.height), + usize::from(self.buffer_width()), + ); + } + UpsamplingMethod::Simple => { + yuv::fill_rgb_buffer_simple::( + buf, + &self.ybuf, + &self.ubuf, + &self.vbuf, + usize::from(self.width), + usize::from(self.chroma_width()), + usize::from(self.buffer_width()), + ); + } + } + } + /// Gets the buffer size + #[must_use] + pub fn get_buf_size(&self) -> usize { + self.ybuf.len() * 3 + } +} + +#[derive(Clone, Copy, Default)] +struct Segment { + ydc: i16, + yac: i16, + + y2dc: i16, + y2ac: i16, + + uvdc: i16, + uvac: i16, + + delta_values: bool, + + quantizer_level: i8, + loopfilter_level: i8, +} + +/// VP8 Decoder +/// +/// Only decodes keyframes +pub struct Vp8Decoder { + r: R, + b: ArithmeticDecoder, + + mbwidth: u16, + mbheight: u16, + macroblocks: Vec, + + frame: Frame, + + segments_enabled: bool, + segments_update_map: bool, + segment: [Segment; MAX_SEGMENTS], + + loop_filter_adjustments_enabled: bool, + ref_delta: [i32; 4], + mode_delta: [i32; 4], + + partitions: [ArithmeticDecoder; 8], + num_partitions: u8, + + segment_tree_nodes: [TreeNode; 3], + token_probs: Box, + + // Section 9.10 + prob_intra: Prob, + + // Section 9.11 + prob_skip_false: Option, + + top: Vec, + left: MacroBlock, + + // The borders from the previous macroblock, used for predictions + // See Section 12 + // Note that the left border contains the top left pixel + top_border_y: Vec, + left_border_y: Vec, + + top_border_u: Vec, + left_border_u: Vec, + + top_border_v: Vec, + left_border_v: Vec, +} + +impl Vp8Decoder { + /// Create a new decoder. + /// The reader must present a raw vp8 bitstream to the decoder + fn new(r: R) -> Self { + let f = Frame::default(); + let s = Segment::default(); + let m = MacroBlock::default(); + + Self { + r, + b: ArithmeticDecoder::new(), + + mbwidth: 0, + mbheight: 0, + macroblocks: Vec::new(), + + frame: f, + segments_enabled: false, + segments_update_map: false, + segment: [s; MAX_SEGMENTS], + + loop_filter_adjustments_enabled: false, + ref_delta: [0; 4], + mode_delta: [0; 4], + + partitions: [ + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ArithmeticDecoder::new(), + ], + + num_partitions: 1, + + segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS, + token_probs: Box::new(COEFF_PROB_NODES), + + // Section 9.10 + prob_intra: 0u8, + + // Section 9.11 + prob_skip_false: None, + + top: Vec::new(), + left: m, + + top_border_y: Vec::new(), + left_border_y: Vec::new(), + + top_border_u: Vec::new(), + left_border_u: Vec::new(), + + top_border_v: Vec::new(), + left_border_v: Vec::new(), + } + } + + fn update_token_probabilities(&mut self) -> Result<(), DecodingError> { + let mut res = self.b.start_accumulated_result(); + for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() { + for (j, js) in is.iter().enumerate() { + for (k, ks) in js.iter().enumerate() { + for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) { + if self.b.read_bool(*prob).or_accumulate(&mut res) { + let v = self.b.read_literal(8).or_accumulate(&mut res); + self.token_probs[i][j][k][t].prob = v; + } + } + } + } + } + self.b.check(res, ()) + } + + fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> { + if n > 1 { + let mut sizes = vec![0; 3 * n - 3]; + self.r.read_exact(sizes.as_mut_slice())?; + + for (i, s) in sizes.chunks(3).enumerate() { + let size = { s } + .read_u24::() + .expect("Reading from &[u8] can't fail and the chunk is complete"); + + let size = size as usize; + let mut buf = vec![[0; 4]; size.div_ceil(4)]; + let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); + self.r.read_exact(&mut bytes[..size])?; + self.partitions[i].init(buf, size)?; + } + } + + let mut buf = Vec::new(); + self.r.read_to_end(&mut buf)?; + let size = buf.len(); + let mut chunks = vec![[0; 4]; size.div_ceil(4)]; + chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf); + self.partitions[n - 1].init(chunks, size)?; + + Ok(()) + } + + fn read_quantization_indices(&mut self) -> Result<(), DecodingError> { + fn dc_quant(index: i32) -> i16 { + DC_QUANT[index.clamp(0, 127) as usize] + } + + fn ac_quant(index: i32) -> i16 { + AC_QUANT[index.clamp(0, 127) as usize] + } + + let mut res = self.b.start_accumulated_result(); + + let yac_abs = self.b.read_literal(7).or_accumulate(&mut res); + let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); + let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); + let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); + let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); + let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); + + let n = if self.segments_enabled { + MAX_SEGMENTS + } else { + 1 + }; + for i in 0usize..n { + let base = i32::from(if self.segments_enabled { + if self.segment[i].delta_values { + i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs) + } else { + i16::from(self.segment[i].quantizer_level) + } + } else { + i16::from(yac_abs) + }); + + self.segment[i].ydc = dc_quant(base + ydc_delta); + self.segment[i].yac = ac_quant(base); + + self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2; + // The intermediate result (max`284*155`) can be larger than the `i16` range. + self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16; + + self.segment[i].uvdc = dc_quant(base + uvdc_delta); + self.segment[i].uvac = ac_quant(base + uvac_delta); + + if self.segment[i].y2ac < 8 { + self.segment[i].y2ac = 8; + } + + if self.segment[i].uvdc > 132 { + self.segment[i].uvdc = 132; + } + } + + self.b.check(res, ()) + } + + fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> { + let mut res = self.b.start_accumulated_result(); + + if self.b.read_flag().or_accumulate(&mut res) { + for i in 0usize..4 { + self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); + } + + for i in 0usize..4 { + self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); + } + } + + self.b.check(res, ()) + } + + fn read_segment_updates(&mut self) -> Result<(), DecodingError> { + let mut res = self.b.start_accumulated_result(); + + // Section 9.3 + self.segments_update_map = self.b.read_flag().or_accumulate(&mut res); + let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res); + + if update_segment_feature_data { + let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res); + + for i in 0usize..MAX_SEGMENTS { + self.segment[i].delta_values = !segment_feature_mode; + } + + for i in 0usize..MAX_SEGMENTS { + self.segment[i].quantizer_level = + self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8; + } + + for i in 0usize..MAX_SEGMENTS { + self.segment[i].loopfilter_level = + self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8; + } + } + + if self.segments_update_map { + for i in 0usize..3 { + let update = self.b.read_flag().or_accumulate(&mut res); + + let prob = if update { + self.b.read_literal(8).or_accumulate(&mut res) + } else { + 255 + }; + self.segment_tree_nodes[i].prob = prob; + } + } + + self.b.check(res, ()) + } + + fn read_frame_header(&mut self) -> Result<(), DecodingError> { + let tag = self.r.read_u24::()?; + + self.frame.keyframe = tag & 1 == 0; + self.frame.version = ((tag >> 1) & 7) as u8; + self.frame.for_display = (tag >> 4) & 1 != 0; + + let first_partition_size = tag >> 5; + + if self.frame.keyframe { + let mut tag = [0u8; 3]; + self.r.read_exact(&mut tag)?; + + if tag != [0x9d, 0x01, 0x2a] { + return Err(DecodingError::Vp8MagicInvalid(tag)); + } + + let w = self.r.read_u16::()?; + let h = self.r.read_u16::()?; + + self.frame.width = w & 0x3FFF; + self.frame.height = h & 0x3FFF; + + self.top = init_top_macroblocks(self.frame.width as usize); + // Almost always the first macro block, except when non exists (i.e. `width == 0`) + self.left = self.top.first().copied().unwrap_or_default(); + + self.mbwidth = self.frame.width.div_ceil(16); + self.mbheight = self.frame.height.div_ceil(16); + + self.frame.ybuf = + vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16]; + self.frame.ubuf = + vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; + self.frame.vbuf = + vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; + + self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16]; + self.left_border_y = vec![129u8; 1 + 16]; + + // 8 pixels per macroblock + self.top_border_u = vec![127u8; 8 * self.mbwidth as usize]; + self.left_border_u = vec![129u8; 1 + 8]; + + self.top_border_v = vec![127u8; 8 * self.mbwidth as usize]; + self.left_border_v = vec![129u8; 1 + 8]; + } + + let size = first_partition_size as usize; + let mut buf = vec![[0; 4]; size.div_ceil(4)]; + let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); + self.r.read_exact(&mut bytes[..size])?; + + // initialise binary decoder + self.b.init(buf, size)?; + + let mut res = self.b.start_accumulated_result(); + if self.frame.keyframe { + let color_space = self.b.read_literal(1).or_accumulate(&mut res); + self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res); + + if color_space != 0 { + return Err(DecodingError::ColorSpaceInvalid(color_space)); + } + } + + self.segments_enabled = self.b.read_flag().or_accumulate(&mut res); + if self.segments_enabled { + self.read_segment_updates()?; + } + + self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res); + self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res); + self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res); + + self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res); + if self.loop_filter_adjustments_enabled { + self.read_loop_filter_adjustments()?; + } + + let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize; + self.b.check(res, ())?; + + self.num_partitions = num_partitions as u8; + self.init_partitions(num_partitions)?; + + self.read_quantization_indices()?; + + if !self.frame.keyframe { + // 9.7 refresh golden frame and altref frame + // FIXME: support this? + return Err(DecodingError::UnsupportedFeature( + "Non-keyframe frames".to_owned(), + )); + } + + // Refresh entropy probs ????? + let _ = self.b.read_literal(1); + + self.update_token_probabilities()?; + + let mut res = self.b.start_accumulated_result(); + let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res); + self.prob_skip_false = if mb_no_skip_coeff == 1 { + Some(self.b.read_literal(8).or_accumulate(&mut res)) + } else { + None + }; + self.b.check(res, ())?; + + if !self.frame.keyframe { + // 9.10 remaining frame data + self.prob_intra = 0; + + // FIXME: support this? + return Err(DecodingError::UnsupportedFeature( + "Non-keyframe frames".to_owned(), + )); + } else { + // Reset motion vectors + } + + Ok(()) + } + + fn read_macroblock_header(&mut self, mbx: usize) -> Result { + let mut mb = MacroBlock::default(); + let mut res = self.b.start_accumulated_result(); + + if self.segments_enabled && self.segments_update_map { + mb.segmentid = + (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8; + }; + + mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false { + self.b.read_bool(prob).or_accumulate(&mut res) + } else { + false + }; + + let inter_predicted = if !self.frame.keyframe { + self.b.read_bool(self.prob_intra).or_accumulate(&mut res) + } else { + false + }; + + if inter_predicted { + return Err(DecodingError::UnsupportedFeature( + "VP8 inter-prediction".to_owned(), + )); + } + + if self.frame.keyframe { + // intra prediction + let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res); + mb.luma_mode = + LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?; + + match mb.luma_mode.into_intra() { + // `LumaMode::B` - This is predicted individually + None => { + for y in 0usize..4 { + for x in 0usize..4 { + let top = self.top[mbx].bpred[12 + x]; + let left = self.left.bpred[y]; + let intra = self.b.read_with_tree( + &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize], + ); + let intra = intra.or_accumulate(&mut res); + let bmode = IntraMode::from_i8(intra) + .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?; + mb.bpred[x + y * 4] = bmode; + + self.top[mbx].bpred[12 + x] = bmode; + self.left.bpred[y] = bmode; + } + } + } + Some(mode) => { + for i in 0usize..4 { + mb.bpred[12 + i] = mode; + self.left.bpred[i] = mode; + } + } + } + + let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res); + mb.chroma_mode = ChromaMode::from_i8(chroma) + .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?; + } + + self.top[mbx].chroma_mode = mb.chroma_mode; + self.top[mbx].luma_mode = mb.luma_mode; + self.top[mbx].bpred = mb.bpred; + + self.b.check(res, mb) + } + + fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { + let stride = 1usize + 16 + 4; + let mw = self.mbwidth as usize; + let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y); + + match mb.luma_mode { + LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride), + LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride), + LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride), + LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0), + LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata), + } + + if mb.luma_mode != LumaMode::B { + for y in 0usize..4 { + for x in 0usize..4 { + let i = x + y * 4; + // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work). + let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); + let y0 = 1 + y * 4; + let x0 = 1 + x * 4; + + add_residue(&mut ws, rb, y0, x0, stride); + } + } + } + + self.left_border_y[0] = ws[16]; + + for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() { + *left = ws[(i + 1) * stride + 16]; + } + + for (top, &w) in self.top_border_y[mbx * 16..][..16] + .iter_mut() + .zip(&ws[16 * stride + 1..][..16]) + { + *top = w; + } + + for y in 0usize..16 { + for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16] + .iter_mut() + .zip(ws[(1 + y) * stride + 1..][..16].iter()) + { + *ybuf = ws; + } + } + } + + fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { + let stride = 1usize + 8; + + let mw = self.mbwidth as usize; + + //8x8 with left top border of 1 + let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u); + let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v); + + match mb.chroma_mode { + ChromaMode::DC => { + predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0); + predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0); + } + ChromaMode::V => { + predict_vpred(&mut uws, 8, 1, 1, stride); + predict_vpred(&mut vws, 8, 1, 1, stride); + } + ChromaMode::H => { + predict_hpred(&mut uws, 8, 1, 1, stride); + predict_hpred(&mut vws, 8, 1, 1, stride); + } + ChromaMode::TM => { + predict_tmpred(&mut uws, 8, 1, 1, stride); + predict_tmpred(&mut vws, 8, 1, 1, stride); + } + } + + for y in 0usize..2 { + for x in 0usize..2 { + let i = x + y * 2; + let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap(); + + let y0 = 1 + y * 4; + let x0 = 1 + x * 4; + add_residue(&mut uws, urb, y0, x0, stride); + + let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap(); + + add_residue(&mut vws, vrb, y0, x0, stride); + } + } + + set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx); + set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx); + + for y in 0usize..8 { + let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8; + let ws_index = (1 + y) * stride + 1; + + for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8] + .iter_mut() + .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut()) + .zip(uws[ws_index..][..8].iter()) + .zip(vws[ws_index..][..8].iter()) + { + *ub = uw; + *vb = vw; + } + } + } + + fn read_coefficients( + &mut self, + block: &mut [i32; 16], + p: usize, + plane: usize, + complexity: usize, + dcq: i16, + acq: i16, + ) -> Result { + // perform bounds checks once up front, + // so that the compiler doesn't have to insert them in the hot loop below + assert!(complexity <= 2); + + let first = if plane == 0 { 1usize } else { 0usize }; + let probs = &self.token_probs[plane]; + let decoder = &mut self.partitions[p]; + + let mut res = decoder.start_accumulated_result(); + + let mut complexity = complexity; + let mut has_coefficients = false; + let mut skip = false; + + for i in first..16usize { + let band = COEFF_BANDS[i] as usize; + let tree = &probs[band][complexity]; + + let token = decoder + .read_with_tree_with_first_node(tree, tree[skip as usize]) + .or_accumulate(&mut res); + + let mut abs_value = i32::from(match token { + DCT_EOB => break, + + DCT_0 => { + skip = true; + has_coefficients = true; + complexity = 0; + continue; + } + + literal @ DCT_1..=DCT_4 => i16::from(literal), + + category @ DCT_CAT1..=DCT_CAT6 => { + let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize]; + + let mut extra = 0i16; + + for t in probs.iter().copied() { + if t == 0 { + break; + } + let b = decoder.read_bool(t).or_accumulate(&mut res); + extra = extra + extra + i16::from(b); + } + + i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra + } + + c => panic!("unknown token: {c}"), + }); + + skip = false; + + complexity = if abs_value == 0 { + 0 + } else if abs_value == 1 { + 1 + } else { + 2 + }; + + if decoder.read_flag().or_accumulate(&mut res) { + abs_value = -abs_value; + } + + let zigzag = ZIGZAG[i] as usize; + block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq }); + + has_coefficients = true; + } + + decoder.check(res, has_coefficients) + } + + fn read_residual_data( + &mut self, + mb: &mut MacroBlock, + mbx: usize, + p: usize, + ) -> Result<[i32; 384], DecodingError> { + let sindex = mb.segmentid as usize; + let mut blocks = [0i32; 384]; + let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 }; + + if plane == 1 { + let complexity = self.top[mbx].complexity[0] + self.left.complexity[0]; + let mut block = [0i32; 16]; + let dcq = self.segment[sindex].y2dc; + let acq = self.segment[sindex].y2ac; + let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?; + + self.left.complexity[0] = if n { 1 } else { 0 }; + self.top[mbx].complexity[0] = if n { 1 } else { 0 }; + + transform::iwht4x4(&mut block); + + for k in 0usize..16 { + blocks[16 * k] = block[k]; + } + + plane = 0; + } + + for y in 0usize..4 { + let mut left = self.left.complexity[y + 1]; + for x in 0usize..4 { + let i = x + y * 4; + let block = &mut blocks[i * 16..][..16]; + let block: &mut [i32; 16] = block.try_into().unwrap(); + + let complexity = self.top[mbx].complexity[x + 1] + left; + let dcq = self.segment[sindex].ydc; + let acq = self.segment[sindex].yac; + + let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; + + if block[0] != 0 || n { + mb.non_zero_dct = true; + transform::idct4x4(block); + } + + left = if n { 1 } else { 0 }; + self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 }; + } + + self.left.complexity[y + 1] = left; + } + + plane = 2; + + for &j in &[5usize, 7usize] { + for y in 0usize..2 { + let mut left = self.left.complexity[y + j]; + + for x in 0usize..2 { + let i = x + y * 2 + if j == 5 { 16 } else { 20 }; + let block = &mut blocks[i * 16..][..16]; + let block: &mut [i32; 16] = block.try_into().unwrap(); + + let complexity = self.top[mbx].complexity[x + j] + left; + let dcq = self.segment[sindex].uvdc; + let acq = self.segment[sindex].uvac; + + let n = + self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; + if block[0] != 0 || n { + mb.non_zero_dct = true; + transform::idct4x4(block); + } + + left = if n { 1 } else { 0 }; + self.top[mbx].complexity[x + j] = if n { 1 } else { 0 }; + } + + self.left.complexity[y + j] = left; + } + } + + Ok(blocks) + } + + /// Does loop filtering on the macroblock + fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) { + let luma_w = self.mbwidth as usize * 16; + let chroma_w = self.mbwidth as usize * 8; + + let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb); + + if filter_level > 0 { + let mbedge_limit = (filter_level + 2) * 2 + interior_limit; + let sub_bedge_limit = (filter_level * 2) + interior_limit; + + // we skip subblock filtering if the coding mode isn't B_PRED and there's no DCT coefficient coded + let do_subblock_filtering = + mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct); + + //filter across left of macroblock + if mbx > 0 { + //simple loop filtering + if self.frame.filter_type { + for y in 0usize..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16; + + loop_filter::simple_segment_horizontal( + mbedge_limit, + &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], + ); + } + } else { + for y in 0usize..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16; + + loop_filter::macroblock_filter_horizontal( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], + ); + } + + for y in 0usize..8 { + let y0 = mby * 8 + y; + let x0 = mbx * 8; + + loop_filter::macroblock_filter_horizontal( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], + ); + loop_filter::macroblock_filter_horizontal( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], + ); + } + } + } + + //filter across vertical subblocks in macroblock + if do_subblock_filtering { + if self.frame.filter_type { + for x in (4usize..16 - 1).step_by(4) { + for y in 0..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16 + x; + + loop_filter::simple_segment_horizontal( + sub_bedge_limit, + &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], + ); + } + } + } else { + for x in (4usize..16 - 3).step_by(4) { + for y in 0..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16 + x; + + loop_filter::subblock_filter_horizontal( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], + ); + } + } + + for y in 0usize..8 { + let y0 = mby * 8 + y; + let x0 = mbx * 8 + 4; + + loop_filter::subblock_filter_horizontal( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], + ); + + loop_filter::subblock_filter_horizontal( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], + ); + } + } + } + + //filter across top of macroblock + if mby > 0 { + if self.frame.filter_type { + for x in 0usize..16 { + let y0 = mby * 16; + let x0 = mbx * 16 + x; + + loop_filter::simple_segment_vertical( + mbedge_limit, + &mut self.frame.ybuf[..], + y0 * luma_w + x0, + luma_w, + ); + } + } else { + //if bottom macroblock, can only filter if there is 3 pixels below + for x in 0usize..16 { + let y0 = mby * 16; + let x0 = mbx * 16 + x; + + loop_filter::macroblock_filter_vertical( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.ybuf[..], + y0 * luma_w + x0, + luma_w, + ); + } + + for x in 0usize..8 { + let y0 = mby * 8; + let x0 = mbx * 8 + x; + + loop_filter::macroblock_filter_vertical( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.ubuf[..], + y0 * chroma_w + x0, + chroma_w, + ); + loop_filter::macroblock_filter_vertical( + hev_threshold, + interior_limit, + mbedge_limit, + &mut self.frame.vbuf[..], + y0 * chroma_w + x0, + chroma_w, + ); + } + } + } + + //filter across horizontal subblock edges within the macroblock + if do_subblock_filtering { + if self.frame.filter_type { + for y in (4usize..16 - 1).step_by(4) { + for x in 0..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16 + x; + + loop_filter::simple_segment_vertical( + sub_bedge_limit, + &mut self.frame.ybuf[..], + y0 * luma_w + x0, + luma_w, + ); + } + } + } else { + for y in (4usize..16 - 3).step_by(4) { + for x in 0..16 { + let y0 = mby * 16 + y; + let x0 = mbx * 16 + x; + + loop_filter::subblock_filter_vertical( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.ybuf[..], + y0 * luma_w + x0, + luma_w, + ); + } + } + + for x in 0..8 { + let y0 = mby * 8 + 4; + let x0 = mbx * 8 + x; + + loop_filter::subblock_filter_vertical( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.ubuf[..], + y0 * chroma_w + x0, + chroma_w, + ); + + loop_filter::subblock_filter_vertical( + hev_threshold, + interior_limit, + sub_bedge_limit, + &mut self.frame.vbuf[..], + y0 * chroma_w + x0, + chroma_w, + ); + } + } + } + } + } + + //return values are the filter level, interior limit and hev threshold + fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) { + let segment = self.segment[macroblock.segmentid as usize]; + let mut filter_level = i32::from(self.frame.filter_level); + + // if frame level filter level is 0, we must skip loop filter + if filter_level == 0 { + return (0, 0, 0); + } + + if self.segments_enabled { + if segment.delta_values { + filter_level += i32::from(segment.loopfilter_level); + } else { + filter_level = i32::from(segment.loopfilter_level); + } + } + + filter_level = filter_level.clamp(0, 63); + + if self.loop_filter_adjustments_enabled { + filter_level += self.ref_delta[0]; + if macroblock.luma_mode == LumaMode::B { + filter_level += self.mode_delta[0]; + } + } + + let filter_level = filter_level.clamp(0, 63) as u8; + + //interior limit + let mut interior_limit = filter_level; + + if self.frame.sharpness_level > 0 { + interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 }; + + if interior_limit > 9 - self.frame.sharpness_level { + interior_limit = 9 - self.frame.sharpness_level; + } + } + + if interior_limit == 0 { + interior_limit = 1; + } + + //high edge variance threshold + let mut hev_threshold = 0; + + #[allow(clippy::collapsible_else_if)] + if self.frame.keyframe { + if filter_level >= 40 { + hev_threshold = 2; + } else if filter_level >= 15 { + hev_threshold = 1; + } + } else { + if filter_level >= 40 { + hev_threshold = 3; + } else if filter_level >= 20 { + hev_threshold = 2; + } else if filter_level >= 15 { + hev_threshold = 1; + } + } + + (filter_level, interior_limit, hev_threshold) + } + + /// Decodes the current frame + pub fn decode_frame(r: R) -> Result { + let decoder = Self::new(r); + decoder.decode_frame_() + } + + fn decode_frame_(mut self) -> Result { + self.read_frame_header()?; + + for mby in 0..self.mbheight as usize { + let p = mby % self.num_partitions as usize; + self.left = MacroBlock::default(); + + for mbx in 0..self.mbwidth as usize { + let mut mb = self.read_macroblock_header(mbx)?; + let blocks = if !mb.coeffs_skipped { + self.read_residual_data(&mut mb, mbx, p)? + } else { + if mb.luma_mode != LumaMode::B { + self.left.complexity[0] = 0; + self.top[mbx].complexity[0] = 0; + } + + for i in 1usize..9 { + self.left.complexity[i] = 0; + self.top[mbx].complexity[i] = 0; + } + + [0i32; 384] + }; + + self.intra_predict_luma(mbx, mby, &mb, &blocks); + self.intra_predict_chroma(mbx, mby, &mb, &blocks); + + self.macroblocks.push(mb); + } + + self.left_border_y = vec![129u8; 1 + 16]; + self.left_border_u = vec![129u8; 1 + 8]; + self.left_border_v = vec![129u8; 1 + 8]; + } + + //do loop filtering + for mby in 0..self.mbheight as usize { + for mbx in 0..self.mbwidth as usize { + let mb = self.macroblocks[mby * self.mbwidth as usize + mbx]; + self.loop_filter(mbx, mby, &mb); + } + } + + Ok(self.frame) + } +} + +impl LumaMode { + const fn from_i8(val: i8) -> Option { + Some(match val { + DC_PRED => Self::DC, + V_PRED => Self::V, + H_PRED => Self::H, + TM_PRED => Self::TM, + B_PRED => Self::B, + _ => return None, + }) + } + + const fn into_intra(self) -> Option { + Some(match self { + Self::DC => IntraMode::DC, + Self::V => IntraMode::VE, + Self::H => IntraMode::HE, + Self::TM => IntraMode::TM, + Self::B => return None, + }) + } +} + +impl ChromaMode { + const fn from_i8(val: i8) -> Option { + Some(match val { + DC_PRED => Self::DC, + V_PRED => Self::V, + H_PRED => Self::H, + TM_PRED => Self::TM, + _ => return None, + }) + } +} + +impl IntraMode { + const fn from_i8(val: i8) -> Option { + Some(match val { + B_DC_PRED => Self::DC, + B_TM_PRED => Self::TM, + B_VE_PRED => Self::VE, + B_HE_PRED => Self::HE, + B_LD_PRED => Self::LD, + B_RD_PRED => Self::RD, + B_VR_PRED => Self::VR, + B_VL_PRED => Self::VL, + B_HD_PRED => Self::HD, + B_HU_PRED => Self::HU, + _ => return None, + }) + } +} + +fn init_top_macroblocks(width: usize) -> Vec { + let mb_width = width.div_ceil(16); + + let mb = MacroBlock { + // Section 11.3 #3 + bpred: [IntraMode::DC; 16], + luma_mode: LumaMode::DC, + ..MacroBlock::default() + }; + + vec![mb; mb_width] +} + +fn create_border_luma(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] { + let stride = 1usize + 16 + 4; + let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)]; + + // A + { + let above = &mut ws[1..stride]; + if mby == 0 { + for above in above.iter_mut() { + *above = 127; + } + } else { + for (above, &top) in above[..16].iter_mut().zip(&top[mbx * 16..]) { + *above = top; + } + + if mbx == mbw - 1 { + for above in &mut above[16..] { + *above = top[mbx * 16 + 15]; + } + } else { + for (above, &top) in above[16..].iter_mut().zip(&top[mbx * 16 + 16..]) { + *above = top; + } + } + } + } + + for i in 17usize..stride { + ws[4 * stride + i] = ws[i]; + ws[8 * stride + i] = ws[i]; + ws[12 * stride + i] = ws[i]; + } + + // L + if mbx == 0 { + for i in 0usize..16 { + ws[(i + 1) * stride] = 129; + } + } else { + for (i, &left) in (0usize..16).zip(&left[1..]) { + ws[(i + 1) * stride] = left; + } + } + + // P + ws[0] = if mby == 0 { + 127 + } else if mbx == 0 { + 129 + } else { + left[0] + }; + + ws +} + +const CHROMA_BLOCK_SIZE: usize = (8 + 1) * (8 + 1); +// creates the left and top border for chroma prediction +fn create_border_chroma( + mbx: usize, + mby: usize, + top: &[u8], + left: &[u8], +) -> [u8; CHROMA_BLOCK_SIZE] { + let stride: usize = 1usize + 8; + let mut chroma_block = [0u8; CHROMA_BLOCK_SIZE]; + + // above + { + let above = &mut chroma_block[1..stride]; + if mby == 0 { + for above in above.iter_mut() { + *above = 127; + } + } else { + for (above, &top) in above.iter_mut().zip(&top[mbx * 8..]) { + *above = top; + } + } + } + + // left + if mbx == 0 { + for y in 0usize..8 { + chroma_block[(y + 1) * stride] = 129; + } + } else { + for (y, &left) in (0usize..8).zip(&left[1..]) { + chroma_block[(y + 1) * stride] = left; + } + } + + chroma_block[0] = if mby == 0 { + 127 + } else if mbx == 0 { + 129 + } else { + left[0] + }; + + chroma_block +} + +// set border +fn set_chroma_border( + left_border: &mut [u8], + top_border: &mut [u8], + chroma_block: &[u8], + mbx: usize, +) { + let stride = 1usize + 8; + // top left is top right of previous chroma block + left_border[0] = chroma_block[8]; + + // left border + for (i, left) in left_border[1..][..8].iter_mut().enumerate() { + *left = chroma_block[(i + 1) * stride + 8]; + } + + for (top, &w) in top_border[mbx * 8..][..8] + .iter_mut() + .zip(&chroma_block[8 * stride + 1..][..8]) + { + *top = w; + } +} + +fn avg3(left: u8, this: u8, right: u8) -> u8 { + let avg = (u16::from(left) + 2 * u16::from(this) + u16::from(right) + 2) >> 2; + avg as u8 +} + +fn avg2(this: u8, right: u8) -> u8 { + let avg = (u16::from(this) + u16::from(right) + 1) >> 1; + avg as u8 +} + +// Only 16 elements from rblock are used to add residue, so it is restricted to 16 elements +// to enable SIMD and other optimizations. +// +// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. +#[allow(clippy::manual_clamp)] +fn add_residue(pblock: &mut [u8], rblock: &[i32; 16], y0: usize, x0: usize, stride: usize) { + let mut pos = y0 * stride + x0; + for row in rblock.chunks(4) { + for (p, &a) in pblock[pos..][..4].iter_mut().zip(row.iter()) { + *p = (a + i32::from(*p)).max(0).min(255) as u8; + } + pos += stride; + } +} + +fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) { + for sby in 0usize..4 { + for sbx in 0usize..4 { + let i = sbx + sby * 4; + let y0 = sby * 4 + 1; + let x0 = sbx * 4 + 1; + + match modes[i] { + IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride), + IntraMode::VE => predict_bvepred(ws, x0, y0, stride), + IntraMode::HE => predict_bhepred(ws, x0, y0, stride), + IntraMode::DC => predict_bdcpred(ws, x0, y0, stride), + IntraMode::LD => predict_bldpred(ws, x0, y0, stride), + IntraMode::RD => predict_brdpred(ws, x0, y0, stride), + IntraMode::VR => predict_bvrpred(ws, x0, y0, stride), + IntraMode::VL => predict_bvlpred(ws, x0, y0, stride), + IntraMode::HD => predict_bhdpred(ws, x0, y0, stride), + IntraMode::HU => predict_bhupred(ws, x0, y0, stride), + } + + let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); + add_residue(ws, rb, y0, x0, stride); + } + } +} + +fn predict_vpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { + // This pass copies the top row to the rows below it. + let (above, curr) = a.split_at_mut(stride * y0); + let above_slice = &above[x0..]; + + for curr_chunk in curr.chunks_exact_mut(stride).take(size) { + for (curr, &above) in curr_chunk[1..].iter_mut().zip(above_slice) { + *curr = above; + } + } +} + +fn predict_hpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { + // This pass copies the first value of a row to the values right of it. + for chunk in a.chunks_exact_mut(stride).skip(y0).take(size) { + let left = chunk[x0 - 1]; + chunk[x0..].iter_mut().for_each(|a| *a = left); + } +} + +fn predict_dcpred(a: &mut [u8], size: usize, stride: usize, above: bool, left: bool) { + let mut sum = 0; + let mut shf = if size == 8 { 2 } else { 3 }; + + if left { + for y in 0usize..size { + sum += u32::from(a[(y + 1) * stride]); + } + + shf += 1; + } + + if above { + sum += a[1..=size].iter().fold(0, |acc, &x| acc + u32::from(x)); + + shf += 1; + } + + let dcval = if !left && !above { + 128 + } else { + (sum + (1 << (shf - 1))) >> shf + }; + + for y in 0usize..size { + a[1 + stride * (y + 1)..][..size] + .iter_mut() + .for_each(|a| *a = dcval as u8); + } +} + +// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. +#[allow(clippy::manual_clamp)] +fn predict_tmpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { + // The formula for tmpred is: + // X_ij = L_i + A_j - P (i, j=0, 1, 2, 3) + // + // |-----|-----|-----|-----|-----| + // | P | A0 | A1 | A2 | A3 | + // |-----|-----|-----|-----|-----| + // | L0 | X00 | X01 | X02 | X03 | + // |-----|-----|-----|-----|-----| + // | L1 | X10 | X11 | X12 | X13 | + // |-----|-----|-----|-----|-----| + // | L2 | X20 | X21 | X22 | X23 | + // |-----|-----|-----|-----|-----| + // | L3 | X30 | X31 | X32 | X33 | + // |-----|-----|-----|-----|-----| + // Diagram from p. 52 of RFC 6386 + + // Split at L0 + let (above, x_block) = a.split_at_mut(y0 * stride + (x0 - 1)); + let p = i32::from(above[(y0 - 1) * stride + x0 - 1]); + let above_slice = &above[(y0 - 1) * stride + x0..]; + + for y in 0usize..size { + let left_minus_p = i32::from(x_block[y * stride]) - p; + + // Add 1 to skip over L0 byte + x_block[y * stride + 1..][..size] + .iter_mut() + .zip(above_slice) + .for_each(|(cur, &abv)| *cur = (left_minus_p + i32::from(abv)).max(0).min(255) as u8); + } +} + +fn predict_bdcpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let mut v = 4; + + a[(y0 - 1) * stride + x0..][..4] + .iter() + .for_each(|&a| v += u32::from(a)); + + for i in 0usize..4 { + v += u32::from(a[(y0 + i) * stride + x0 - 1]); + } + + v >>= 3; + for chunk in a.chunks_exact_mut(stride).skip(y0).take(4) { + for ch in &mut chunk[x0..][..4] { + *ch = v as u8; + } + } +} + +fn topleft_pixel(a: &[u8], x0: usize, y0: usize, stride: usize) -> u8 { + a[(y0 - 1) * stride + x0 - 1] +} + +fn top_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8, u8, u8, u8, u8) { + let pos = (y0 - 1) * stride + x0; + let a_slice = &a[pos..pos + 8]; + let a0 = a_slice[0]; + let a1 = a_slice[1]; + let a2 = a_slice[2]; + let a3 = a_slice[3]; + let a4 = a_slice[4]; + let a5 = a_slice[5]; + let a6 = a_slice[6]; + let a7 = a_slice[7]; + + (a0, a1, a2, a3, a4, a5, a6, a7) +} + +fn left_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8) { + let l0 = a[y0 * stride + x0 - 1]; + let l1 = a[(y0 + 1) * stride + x0 - 1]; + let l2 = a[(y0 + 2) * stride + x0 - 1]; + let l3 = a[(y0 + 3) * stride + x0 - 1]; + + (l0, l1, l2, l3) +} + +fn edge_pixels( + a: &[u8], + x0: usize, + y0: usize, + stride: usize, +) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8) { + let pos = (y0 - 1) * stride + x0 - 1; + let a_slice = &a[pos..=pos + 4]; + let e0 = a[pos + 4 * stride]; + let e1 = a[pos + 3 * stride]; + let e2 = a[pos + 2 * stride]; + let e3 = a[pos + stride]; + let e4 = a_slice[0]; + let e5 = a_slice[1]; + let e6 = a_slice[2]; + let e7 = a_slice[3]; + let e8 = a_slice[4]; + + (e0, e1, e2, e3, e4, e5, e6, e7, e8) +} + +fn predict_bvepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let p = topleft_pixel(a, x0, y0, stride); + let (a0, a1, a2, a3, a4, ..) = top_pixels(a, x0, y0, stride); + let avg_1 = avg3(p, a0, a1); + let avg_2 = avg3(a0, a1, a2); + let avg_3 = avg3(a1, a2, a3); + let avg_4 = avg3(a2, a3, a4); + + let avg = [avg_1, avg_2, avg_3, avg_4]; + + let mut pos = y0 * stride + x0; + for _ in 0..4 { + a[pos..=pos + 3].copy_from_slice(&avg); + pos += stride; + } +} + +fn predict_bhepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let p = topleft_pixel(a, x0, y0, stride); + let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); + + let avgs = [ + avg3(p, l0, l1), + avg3(l0, l1, l2), + avg3(l1, l2, l3), + avg3(l2, l3, l3), + ]; + + let mut pos = y0 * stride + x0; + for avg in avgs { + for a_p in &mut a[pos..=pos + 3] { + *a_p = avg; + } + pos += stride; + } +} + +fn predict_bldpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); + + let avgs = [ + avg3(a0, a1, a2), + avg3(a1, a2, a3), + avg3(a2, a3, a4), + avg3(a3, a4, a5), + avg3(a4, a5, a6), + avg3(a5, a6, a7), + avg3(a6, a7, a7), + ]; + + let mut pos = y0 * stride + x0; + + for i in 0..4 { + a[pos..=pos + 3].copy_from_slice(&avgs[i..=i + 3]); + pos += stride; + } +} + +fn predict_brdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); + + let avgs = [ + avg3(e0, e1, e2), + avg3(e1, e2, e3), + avg3(e2, e3, e4), + avg3(e3, e4, e5), + avg3(e4, e5, e6), + avg3(e5, e6, e7), + avg3(e6, e7, e8), + ]; + let mut pos = y0 * stride + x0; + + for i in 0..4 { + a[pos..=pos + 3].copy_from_slice(&avgs[3 - i..7 - i]); + pos += stride; + } +} + +fn predict_bvrpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (_, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); + + a[(y0 + 3) * stride + x0] = avg3(e1, e2, e3); + a[(y0 + 2) * stride + x0] = avg3(e2, e3, e4); + a[(y0 + 3) * stride + x0 + 1] = avg3(e3, e4, e5); + a[(y0 + 1) * stride + x0] = avg3(e3, e4, e5); + a[(y0 + 2) * stride + x0 + 1] = avg2(e4, e5); + a[y0 * stride + x0] = avg2(e4, e5); + a[(y0 + 3) * stride + x0 + 2] = avg3(e4, e5, e6); + a[(y0 + 1) * stride + x0 + 1] = avg3(e4, e5, e6); + a[(y0 + 2) * stride + x0 + 2] = avg2(e5, e6); + a[y0 * stride + x0 + 1] = avg2(e5, e6); + a[(y0 + 3) * stride + x0 + 3] = avg3(e5, e6, e7); + a[(y0 + 1) * stride + x0 + 2] = avg3(e5, e6, e7); + a[(y0 + 2) * stride + x0 + 3] = avg2(e6, e7); + a[y0 * stride + x0 + 2] = avg2(e6, e7); + a[(y0 + 1) * stride + x0 + 3] = avg3(e6, e7, e8); + a[y0 * stride + x0 + 3] = avg2(e7, e8); +} + +fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); + + a[y0 * stride + x0] = avg2(a0, a1); + a[(y0 + 1) * stride + x0] = avg3(a0, a1, a2); + a[(y0 + 2) * stride + x0] = avg2(a1, a2); + a[y0 * stride + x0 + 1] = avg2(a1, a2); + a[(y0 + 1) * stride + x0 + 1] = avg3(a1, a2, a3); + a[(y0 + 3) * stride + x0] = avg3(a1, a2, a3); + a[(y0 + 2) * stride + x0 + 1] = avg2(a2, a3); + a[y0 * stride + x0 + 2] = avg2(a2, a3); + a[(y0 + 3) * stride + x0 + 1] = avg3(a2, a3, a4); + a[(y0 + 1) * stride + x0 + 2] = avg3(a2, a3, a4); + a[(y0 + 2) * stride + x0 + 2] = avg2(a3, a4); + a[y0 * stride + x0 + 3] = avg2(a3, a4); + a[(y0 + 3) * stride + x0 + 2] = avg3(a3, a4, a5); + a[(y0 + 1) * stride + x0 + 3] = avg3(a3, a4, a5); + a[(y0 + 2) * stride + x0 + 3] = avg3(a4, a5, a6); + a[(y0 + 3) * stride + x0 + 3] = avg3(a5, a6, a7); +} + +fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (e0, e1, e2, e3, e4, e5, e6, e7, _) = edge_pixels(a, x0, y0, stride); + + a[(y0 + 3) * stride + x0] = avg2(e0, e1); + a[(y0 + 3) * stride + x0 + 1] = avg3(e0, e1, e2); + a[(y0 + 2) * stride + x0] = avg2(e1, e2); + a[(y0 + 3) * stride + x0 + 2] = avg2(e1, e2); + a[(y0 + 2) * stride + x0 + 1] = avg3(e1, e2, e3); + a[(y0 + 3) * stride + x0 + 3] = avg3(e1, e2, e3); + a[(y0 + 2) * stride + x0 + 2] = avg2(e2, e3); + a[(y0 + 1) * stride + x0] = avg2(e2, e3); + a[(y0 + 2) * stride + x0 + 3] = avg3(e2, e3, e4); + a[(y0 + 1) * stride + x0 + 1] = avg3(e2, e3, e4); + a[(y0 + 1) * stride + x0 + 2] = avg2(e3, e4); + a[y0 * stride + x0] = avg2(e3, e4); + a[(y0 + 1) * stride + x0 + 3] = avg3(e3, e4, e5); + a[y0 * stride + x0 + 1] = avg3(e3, e4, e5); + a[y0 * stride + x0 + 2] = avg3(e4, e5, e6); + a[y0 * stride + x0 + 3] = avg3(e5, e6, e7); +} + +fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { + let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); + + a[y0 * stride + x0] = avg2(l0, l1); + a[y0 * stride + x0 + 1] = avg3(l0, l1, l2); + a[y0 * stride + x0 + 2] = avg2(l1, l2); + a[(y0 + 1) * stride + x0] = avg2(l1, l2); + a[y0 * stride + x0 + 3] = avg3(l1, l2, l3); + a[(y0 + 1) * stride + x0 + 1] = avg3(l1, l2, l3); + a[(y0 + 1) * stride + x0 + 2] = avg2(l2, l3); + a[(y0 + 2) * stride + x0] = avg2(l2, l3); + a[(y0 + 1) * stride + x0 + 3] = avg3(l2, l3, l3); + a[(y0 + 2) * stride + x0 + 1] = avg3(l2, l3, l3); + a[(y0 + 2) * stride + x0 + 2] = l3; + a[(y0 + 2) * stride + x0 + 3] = l3; + a[(y0 + 3) * stride + x0] = l3; + a[(y0 + 3) * stride + x0 + 1] = l3; + a[(y0 + 3) * stride + x0 + 2] = l3; + a[(y0 + 3) * stride + x0 + 3] = l3; +} + +#[cfg(all(test, feature = "_benchmarks"))] +mod benches { + use super::*; + use test::{black_box, Bencher}; + + const W: usize = 256; + const H: usize = 256; + + fn make_sample_image() -> Vec { + let mut v = Vec::with_capacity((W * H * 4) as usize); + for c in 0u8..=255 { + for k in 0u8..=255 { + v.push(c); + v.push(0); + v.push(0); + v.push(k); + } + } + v + } + + #[bench] + fn bench_predict_4x4(b: &mut Bencher) { + let mut v = black_box(make_sample_image()); + + let res_data = vec![1i32; W * H * 4]; + let modes = [ + IntraMode::TM, + IntraMode::VE, + IntraMode::HE, + IntraMode::DC, + IntraMode::LD, + IntraMode::RD, + IntraMode::VR, + IntraMode::VL, + IntraMode::HD, + IntraMode::HU, + IntraMode::TM, + IntraMode::VE, + IntraMode::HE, + IntraMode::DC, + IntraMode::LD, + IntraMode::RD, + ]; + + b.iter(|| { + black_box(predict_4x4(&mut v, W * 2, &modes, &res_data)); + }); + } + + #[bench] + fn bench_predict_bvepred(b: &mut Bencher) { + let mut v = make_sample_image(); + + b.iter(|| { + predict_bvepred(black_box(&mut v), 5, 5, W * 2); + }); + } + + #[bench] + fn bench_predict_bldpred(b: &mut Bencher) { + let mut v = black_box(make_sample_image()); + + b.iter(|| { + black_box(predict_bldpred(black_box(&mut v), 5, 5, W * 2)); + }); + } + + #[bench] + fn bench_predict_brdpred(b: &mut Bencher) { + let mut v = black_box(make_sample_image()); + + b.iter(|| { + black_box(predict_brdpred(black_box(&mut v), 5, 5, W * 2)); + }); + } + + #[bench] + fn bench_predict_bhepred(b: &mut Bencher) { + let mut v = black_box(make_sample_image()); + + b.iter(|| { + black_box(predict_bhepred(black_box(&mut v), 5, 5, W * 2)); + }); + } + + #[bench] + fn bench_top_pixels(b: &mut Bencher) { + let v = black_box(make_sample_image()); + + b.iter(|| { + black_box(top_pixels(black_box(&v), 5, 5, W * 2)); + }); + } + + #[bench] + fn bench_edge_pixels(b: &mut Bencher) { + let v = black_box(make_sample_image()); + + b.iter(|| { + black_box(edge_pixels(black_box(&v), 5, 5, W * 2)); + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_avg2() { + for i in 0u8..=255 { + for j in 0u8..=255 { + let ceil_avg = (f32::from(i) + f32::from(j)) / 2.0; + let ceil_avg = ceil_avg.ceil() as u8; + assert_eq!( + ceil_avg, + avg2(i, j), + "avg2({}, {}), expected {}, got {}.", + i, + j, + ceil_avg, + avg2(i, j) + ); + } + } + } + + #[test] + fn test_avg2_specific() { + assert_eq!( + 255, + avg2(255, 255), + "avg2(255, 255), expected 255, got {}.", + avg2(255, 255) + ); + assert_eq!(1, avg2(1, 1), "avg2(1, 1), expected 1, got {}.", avg2(1, 1)); + assert_eq!(2, avg2(2, 1), "avg2(2, 1), expected 2, got {}.", avg2(2, 1)); + } + + #[test] + fn test_avg3() { + for i in 0u8..=255 { + for j in 0u8..=255 { + for k in 0u8..=255 { + let floor_avg = + (2.0f32.mul_add(f32::from(j), f32::from(i)) + { f32::from(k) } + 2.0) / 4.0; + let floor_avg = floor_avg.floor() as u8; + assert_eq!( + floor_avg, + avg3(i, j, k), + "avg3({}, {}, {}), expected {}, got {}.", + i, + j, + k, + floor_avg, + avg3(i, j, k) + ); + } + } + } + } + + #[test] + fn test_edge_pixels() { + #[rustfmt::skip] + let im = vec![5, 6, 7, 8, 9, + 4, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 1, 0, 0, 0, 0]; + let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(&im, 1, 1, 5); + assert_eq!(e0, 1); + assert_eq!(e1, 2); + assert_eq!(e2, 3); + assert_eq!(e3, 4); + assert_eq!(e4, 5); + assert_eq!(e5, 6); + assert_eq!(e6, 7); + assert_eq!(e7, 8); + assert_eq!(e8, 9); + } + + #[test] + fn test_top_pixels() { + #[rustfmt::skip] + let im = vec![1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0]; + let (e0, e1, e2, e3, e4, e5, e6, e7) = top_pixels(&im, 0, 1, 8); + assert_eq!(e0, 1); + assert_eq!(e1, 2); + assert_eq!(e2, 3); + assert_eq!(e3, 4); + assert_eq!(e4, 5); + assert_eq!(e5, 6); + assert_eq!(e6, 7); + assert_eq!(e7, 8); + } + + #[test] + fn test_add_residue() { + let mut pblock = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let rblock = [ + -1, -2, -3, -4, 250, 249, 248, 250, -10, -18, -192, -17, -3, 15, 18, 9, + ]; + let expected: [u8; 16] = [0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 10, 29, 33, 25]; + + add_residue(&mut pblock, &rblock, 0, 0, 4); + + for (&e, &i) in expected.iter().zip(&pblock) { + assert_eq!(e, i); + } + } + + #[test] + fn test_predict_bhepred() { + #[rustfmt::skip] + let expected: Vec = vec![5, 0, 0, 0, 0, + 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1]; + + #[rustfmt::skip] + let mut im = vec![5, 0, 0, 0, 0, + 4, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 1, 0, 0, 0, 0]; + predict_bhepred(&mut im, 1, 1, 5); + for (&e, i) in expected.iter().zip(im) { + assert_eq!(e, i); + } + } + + #[test] + fn test_predict_brdpred() { + #[rustfmt::skip] + let expected: Vec = vec![5, 6, 7, 8, 9, + 4, 5, 6, 7, 8, + 3, 4, 5, 6, 7, + 2, 3, 4, 5, 6, + 1, 2, 3, 4, 5]; + + #[rustfmt::skip] + let mut im = vec![5, 6, 7, 8, 9, + 4, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 1, 0, 0, 0, 0]; + predict_brdpred(&mut im, 1, 1, 5); + for (&e, i) in expected.iter().zip(im) { + assert_eq!(e, i); + } + } + + #[test] + fn test_predict_bldpred() { + #[rustfmt::skip] + let mut im: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0]; + let avg_1 = 2u8; + let avg_2 = 3u8; + let avg_3 = 4u8; + let avg_4 = 5u8; + let avg_5 = 6u8; + let avg_6 = 7u8; + let avg_7 = 8u8; + + predict_bldpred(&mut im, 0, 1, 8); + + assert_eq!(im[8], avg_1); + assert_eq!(im[9], avg_2); + assert_eq!(im[10], avg_3); + assert_eq!(im[11], avg_4); + assert_eq!(im[16], avg_2); + assert_eq!(im[17], avg_3); + assert_eq!(im[18], avg_4); + assert_eq!(im[19], avg_5); + assert_eq!(im[24], avg_3); + assert_eq!(im[25], avg_4); + assert_eq!(im[26], avg_5); + assert_eq!(im[27], avg_6); + assert_eq!(im[32], avg_4); + assert_eq!(im[33], avg_5); + assert_eq!(im[34], avg_6); + assert_eq!(im[35], avg_7); + } + + #[test] + fn test_predict_bvepred() { + #[rustfmt::skip] + let mut im: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let avg_1 = 2u8; + let avg_2 = 3u8; + let avg_3 = 4u8; + let avg_4 = 5u8; + + predict_bvepred(&mut im, 1, 1, 9); + + assert_eq!(im[10], avg_1); + assert_eq!(im[11], avg_2); + assert_eq!(im[12], avg_3); + assert_eq!(im[13], avg_4); + assert_eq!(im[19], avg_1); + assert_eq!(im[20], avg_2); + assert_eq!(im[21], avg_3); + assert_eq!(im[22], avg_4); + assert_eq!(im[28], avg_1); + assert_eq!(im[29], avg_2); + assert_eq!(im[30], avg_3); + assert_eq!(im[31], avg_4); + assert_eq!(im[37], avg_1); + assert_eq!(im[38], avg_2); + assert_eq!(im[39], avg_3); + assert_eq!(im[40], avg_4); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/vp8_arithmetic_decoder.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8_arithmetic_decoder.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/vp8_arithmetic_decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/vp8_arithmetic_decoder.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,613 @@ +use crate::decoder::DecodingError; + +use super::vp8::TreeNode; + +#[must_use] +#[repr(transparent)] +pub(crate) struct BitResult { + value_if_not_past_eof: T, +} + +#[must_use] +pub(crate) struct BitResultAccumulator; + +impl BitResult { + const fn ok(value: T) -> Self { + Self { + value_if_not_past_eof: value, + } + } + + /// Instead of checking this result now, accumulate the burden of checking + /// into an accumulator. This accumulator must be checked in the end. + #[inline(always)] + pub(crate) fn or_accumulate(self, acc: &mut BitResultAccumulator) -> T { + let _ = acc; + self.value_if_not_past_eof + } +} + +impl BitResult { + fn err() -> Self { + Self { + value_if_not_past_eof: T::default(), + } + } +} + +#[cfg_attr(test, derive(Debug))] +pub(crate) struct ArithmeticDecoder { + chunks: Box<[[u8; 4]]>, + state: State, + final_bytes: [u8; 3], + final_bytes_remaining: i8, +} + +#[cfg_attr(test, derive(Debug))] +#[derive(Clone, Copy)] +struct State { + chunk_index: usize, + value: u64, + range: u32, + bit_count: i32, +} + +#[cfg_attr(test, derive(Debug))] +struct FastDecoder<'a> { + chunks: &'a [[u8; 4]], + uncommitted_state: State, + save_state: &'a mut State, +} + +impl ArithmeticDecoder { + pub(crate) fn new() -> ArithmeticDecoder { + let state = State { + chunk_index: 0, + value: 0, + range: 255, + bit_count: -8, + }; + ArithmeticDecoder { + chunks: Box::new([]), + state, + final_bytes: [0; 3], + final_bytes_remaining: Self::FINAL_BYTES_REMAINING_EOF, + } + } + + pub(crate) fn init(&mut self, mut buf: Vec<[u8; 4]>, len: usize) -> Result<(), DecodingError> { + let mut final_bytes = [0; 3]; + let final_bytes_remaining = if len == 4 * buf.len() { + 0 + } else { + // Pop the last chunk (which is partial), then get length. + let Some(last_chunk) = buf.pop() else { + return Err(DecodingError::NotEnoughInitData); + }; + let len_rounded_down = 4 * buf.len(); + let num_bytes_popped = len - len_rounded_down; + debug_assert!(num_bytes_popped <= 3); + final_bytes[..num_bytes_popped].copy_from_slice(&last_chunk[..num_bytes_popped]); + for i in num_bytes_popped..4 { + debug_assert_eq!(last_chunk[i], 0, "unexpected {last_chunk:?}"); + } + num_bytes_popped as i8 + }; + + let chunks = buf.into_boxed_slice(); + let state = State { + chunk_index: 0, + value: 0, + range: 255, + bit_count: -8, + }; + *self = Self { + chunks, + state, + final_bytes, + final_bytes_remaining, + }; + Ok(()) + } + + /// Start a span of reading operations from the buffer, without stopping + /// when the buffer runs out. For all valid webp images, the buffer will not + /// run out prematurely. Conversely if the buffer ends early, the webp image + /// cannot be correctly decoded and any intermediate results need to be + /// discarded anyway. + /// + /// Each call to `start_accumulated_result` must be followed by a call to + /// `check` on the *same* `ArithmeticDecoder`. + #[inline(always)] + pub(crate) fn start_accumulated_result(&mut self) -> BitResultAccumulator { + BitResultAccumulator + } + + /// Check that the read operations done so far were all valid. + #[inline(always)] + pub(crate) fn check( + &self, + acc: BitResultAccumulator, + value_if_not_past_eof: T, + ) -> Result { + // The accumulator does not store any state because doing so is + // too computationally expensive. Passing it around is a bit of + // formality (that is optimized out) to ensure we call `check` . + // Instead we check whether we have read past the end of the file. + let BitResultAccumulator = acc; + + if self.is_past_eof() { + Err(DecodingError::BitStreamError) + } else { + Ok(value_if_not_past_eof) + } + } + + fn keep_accumulating( + &self, + acc: BitResultAccumulator, + value_if_not_past_eof: T, + ) -> BitResult { + // The BitResult will be checked later by a different accumulator. + // Because it does not carry state, that is fine. + let BitResultAccumulator = acc; + + BitResult::ok(value_if_not_past_eof) + } + + // Do not inline this because inlining seems to worsen performance. + #[inline(never)] + pub(crate) fn read_bool(&mut self, probability: u8) -> BitResult { + if let Some(b) = self.fast().read_bool(probability) { + return BitResult::ok(b); + } + + self.cold_read_bool(probability) + } + + // Do not inline this because inlining seems to worsen performance. + #[inline(never)] + pub(crate) fn read_flag(&mut self) -> BitResult { + if let Some(b) = self.fast().read_flag() { + return BitResult::ok(b); + } + + self.cold_read_flag() + } + + // Do not inline this because inlining seems to worsen performance. + #[inline(never)] + pub(crate) fn read_literal(&mut self, n: u8) -> BitResult { + if let Some(v) = self.fast().read_literal(n) { + return BitResult::ok(v); + } + + self.cold_read_literal(n) + } + + // Do not inline this because inlining seems to worsen performance. + #[inline(never)] + pub(crate) fn read_optional_signed_value(&mut self, n: u8) -> BitResult { + if let Some(v) = self.fast().read_optional_signed_value(n) { + return BitResult::ok(v); + } + + self.cold_read_optional_signed_value(n) + } + + // This is generic and inlined just to skip the first bounds check. + #[inline] + pub(crate) fn read_with_tree(&mut self, tree: &[TreeNode; N]) -> BitResult { + let first_node = tree[0]; + self.read_with_tree_with_first_node(tree, first_node) + } + + // Do not inline this because inlining significantly worsens performance. + #[inline(never)] + pub(crate) fn read_with_tree_with_first_node( + &mut self, + tree: &[TreeNode], + first_node: TreeNode, + ) -> BitResult { + if let Some(v) = self.fast().read_with_tree(tree, first_node) { + return BitResult::ok(v); + } + + self.cold_read_with_tree(tree, usize::from(first_node.index)) + } + + // As a similar (but different) speedup to BitResult, the FastDecoder reads + // bits under an assumption and validates it at the end. + // + // The idea here is that for normal-sized webp images, the vast majority + // of bits are somewhere other than in the last four bytes. Therefore we + // can pretend the buffer has infinite size. After we are done reading, + // we check if we actually read past the end of `self.chunks`. + // If so, we backtrack (or rather we discard `uncommitted_state`) + // and try again with the slow approach. This might result in doing double + // work for those last few bytes -- in fact we even keep retrying the fast + // method to save an if-statement --, but more than make up for that by + // speeding up reading from the other thousands or millions of bytes. + fn fast(&mut self) -> FastDecoder<'_> { + FastDecoder { + chunks: &self.chunks, + uncommitted_state: self.state, + save_state: &mut self.state, + } + } + + const FINAL_BYTES_REMAINING_EOF: i8 = -0xE; + + fn load_from_final_bytes(&mut self) { + match self.final_bytes_remaining { + 1.. => { + self.final_bytes_remaining -= 1; + let byte = self.final_bytes[0]; + self.final_bytes.rotate_left(1); + self.state.value <<= 8; + self.state.value |= u64::from(byte); + self.state.bit_count += 8; + } + 0 => { + // libwebp seems to (sometimes?) allow bitstreams that read one byte past the end. + // This replicates that logic. + self.final_bytes_remaining -= 1; + self.state.value <<= 8; + self.state.bit_count += 8; + } + _ => { + self.final_bytes_remaining = Self::FINAL_BYTES_REMAINING_EOF; + } + } + } + + fn is_past_eof(&self) -> bool { + self.final_bytes_remaining == Self::FINAL_BYTES_REMAINING_EOF + } + + fn cold_read_bit(&mut self, probability: u8) -> BitResult { + if self.state.bit_count < 0 { + if let Some(chunk) = self.chunks.get(self.state.chunk_index).copied() { + let v = u32::from_be_bytes(chunk); + self.state.chunk_index += 1; + self.state.value <<= 32; + self.state.value |= u64::from(v); + self.state.bit_count += 32; + } else { + self.load_from_final_bytes(); + if self.is_past_eof() { + return BitResult::err(); + } + } + } + debug_assert!(self.state.bit_count >= 0); + + let probability = u32::from(probability); + let split = 1 + (((self.state.range - 1) * probability) >> 8); + let bigsplit = u64::from(split) << self.state.bit_count; + + let retval = if let Some(new_value) = self.state.value.checked_sub(bigsplit) { + self.state.range -= split; + self.state.value = new_value; + true + } else { + self.state.range = split; + false + }; + debug_assert!(self.state.range > 0); + + // Compute shift required to satisfy `self.state.range >= 128`. + // Apply that shift to `self.state.range` and `self.state.bitcount`. + // + // Subtract 24 because we only care about leading zeros in the + // lowest byte of `self.state.range` which is a `u32`. + let shift = self.state.range.leading_zeros().saturating_sub(24); + self.state.range <<= shift; + self.state.bit_count -= shift as i32; + debug_assert!(self.state.range >= 128); + + BitResult::ok(retval) + } + + #[cold] + #[inline(never)] + fn cold_read_bool(&mut self, probability: u8) -> BitResult { + self.cold_read_bit(probability) + } + + #[cold] + #[inline(never)] + fn cold_read_flag(&mut self) -> BitResult { + self.cold_read_bit(128) + } + + #[cold] + #[inline(never)] + fn cold_read_literal(&mut self, n: u8) -> BitResult { + let mut v = 0u8; + let mut res = self.start_accumulated_result(); + + for _ in 0..n { + let b = self.cold_read_flag().or_accumulate(&mut res); + v = (v << 1) + u8::from(b); + } + + self.keep_accumulating(res, v) + } + + #[cold] + #[inline(never)] + fn cold_read_optional_signed_value(&mut self, n: u8) -> BitResult { + let mut res = self.start_accumulated_result(); + let flag = self.cold_read_flag().or_accumulate(&mut res); + if !flag { + // We should not read further bits if the flag is not set. + return self.keep_accumulating(res, 0); + } + let magnitude = self.cold_read_literal(n).or_accumulate(&mut res); + let sign = self.cold_read_flag().or_accumulate(&mut res); + + let value = if sign { + -i32::from(magnitude) + } else { + i32::from(magnitude) + }; + self.keep_accumulating(res, value) + } + + #[cold] + #[inline(never)] + fn cold_read_with_tree(&mut self, tree: &[TreeNode], start: usize) -> BitResult { + let mut index = start; + let mut res = self.start_accumulated_result(); + + loop { + let node = tree[index]; + let prob = node.prob; + let b = self.cold_read_bit(prob).or_accumulate(&mut res); + let t = if b { node.right } else { node.left }; + let new_index = usize::from(t); + if new_index < tree.len() { + index = new_index; + } else { + let value = TreeNode::value_from_branch(t); + return self.keep_accumulating(res, value); + } + } + } +} + +impl FastDecoder<'_> { + fn commit_if_valid(self, value_if_not_past_eof: T) -> Option { + // If `chunk_index > self.chunks.len()`, it means we used zeroes + // instead of an actual chunk and `value_if_not_past_eof` is nonsense. + if self.uncommitted_state.chunk_index <= self.chunks.len() { + *self.save_state = self.uncommitted_state; + Some(value_if_not_past_eof) + } else { + None + } + } + + fn read_bool(mut self, probability: u8) -> Option { + let bit = self.fast_read_bit(probability); + self.commit_if_valid(bit) + } + + fn read_flag(mut self) -> Option { + let value = self.fast_read_flag(); + self.commit_if_valid(value) + } + + fn read_literal(mut self, n: u8) -> Option { + let value = self.fast_read_literal(n); + self.commit_if_valid(value) + } + + fn read_optional_signed_value(mut self, n: u8) -> Option { + let flag = self.fast_read_flag(); + if !flag { + // We should not read further bits if the flag is not set. + return self.commit_if_valid(0); + } + let magnitude = self.fast_read_literal(n); + let sign = self.fast_read_flag(); + let value = if sign { + -i32::from(magnitude) + } else { + i32::from(magnitude) + }; + self.commit_if_valid(value) + } + + fn read_with_tree(mut self, tree: &[TreeNode], first_node: TreeNode) -> Option { + let value = self.fast_read_with_tree(tree, first_node); + self.commit_if_valid(value) + } + + fn fast_read_bit(&mut self, probability: u8) -> bool { + let State { + mut chunk_index, + mut value, + mut range, + mut bit_count, + } = self.uncommitted_state; + + if bit_count < 0 { + let chunk = self.chunks.get(chunk_index).copied(); + // We ignore invalid data inside the `fast_` functions, + // but we increase `chunk_index` below, so we can check + // whether we read invalid data in `commit_if_valid`. + let chunk = chunk.unwrap_or_default(); + + let v = u32::from_be_bytes(chunk); + chunk_index += 1; + value <<= 32; + value |= u64::from(v); + bit_count += 32; + } + debug_assert!(bit_count >= 0); + + let probability = u32::from(probability); + let split = 1 + (((range - 1) * probability) >> 8); + let bigsplit = u64::from(split) << bit_count; + + let retval = if let Some(new_value) = value.checked_sub(bigsplit) { + range -= split; + value = new_value; + true + } else { + range = split; + false + }; + debug_assert!(range > 0); + + // Compute shift required to satisfy `range >= 128`. + // Apply that shift to `range` and `self.bitcount`. + // + // Subtract 24 because we only care about leading zeros in the + // lowest byte of `range` which is a `u32`. + let shift = range.leading_zeros().saturating_sub(24); + range <<= shift; + bit_count -= shift as i32; + debug_assert!(range >= 128); + + self.uncommitted_state = State { + chunk_index, + value, + range, + bit_count, + }; + retval + } + + fn fast_read_flag(&mut self) -> bool { + let State { + mut chunk_index, + mut value, + mut range, + mut bit_count, + } = self.uncommitted_state; + + if bit_count < 0 { + let chunk = self.chunks.get(chunk_index).copied(); + // We ignore invalid data inside the `fast_` functions, + // but we increase `chunk_index` below, so we can check + // whether we read invalid data in `commit_if_valid`. + let chunk = chunk.unwrap_or_default(); + + let v = u32::from_be_bytes(chunk); + chunk_index += 1; + value <<= 32; + value |= u64::from(v); + bit_count += 32; + } + debug_assert!(bit_count >= 0); + + let half_range = range / 2; + let split = range - half_range; + let bigsplit = u64::from(split) << bit_count; + + let retval = if let Some(new_value) = value.checked_sub(bigsplit) { + range = half_range; + value = new_value; + true + } else { + range = split; + false + }; + debug_assert!(range > 0); + + // Compute shift required to satisfy `range >= 128`. + // Apply that shift to `range` and `self.bitcount`. + // + // Subtract 24 because we only care about leading zeros in the + // lowest byte of `range` which is a `u32`. + let shift = range.leading_zeros().saturating_sub(24); + range <<= shift; + bit_count -= shift as i32; + debug_assert!(range >= 128); + + self.uncommitted_state = State { + chunk_index, + value, + range, + bit_count, + }; + retval + } + + fn fast_read_literal(&mut self, n: u8) -> u8 { + let mut v = 0u8; + for _ in 0..n { + let b = self.fast_read_flag(); + v = (v << 1) + u8::from(b); + } + v + } + + fn fast_read_with_tree(&mut self, tree: &[TreeNode], mut node: TreeNode) -> i8 { + loop { + let prob = node.prob; + let b = self.fast_read_bit(prob); + let i = if b { node.right } else { node.left }; + let Some(next_node) = tree.get(usize::from(i)) else { + return TreeNode::value_from_branch(i); + }; + node = *next_node; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_arithmetic_decoder_hello_short() { + let mut decoder = ArithmeticDecoder::new(); + let data = b"hel"; + let size = data.len(); + let mut buf = vec![[0u8; 4]; 1]; + buf.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&data[..]); + decoder.init(buf, size).unwrap(); + let mut res = decoder.start_accumulated_result(); + assert_eq!(false, decoder.read_flag().or_accumulate(&mut res)); + assert_eq!(true, decoder.read_bool(10).or_accumulate(&mut res)); + assert_eq!(false, decoder.read_bool(250).or_accumulate(&mut res)); + assert_eq!(1, decoder.read_literal(1).or_accumulate(&mut res)); + assert_eq!(5, decoder.read_literal(3).or_accumulate(&mut res)); + assert_eq!(64, decoder.read_literal(8).or_accumulate(&mut res)); + assert_eq!(185, decoder.read_literal(8).or_accumulate(&mut res)); + decoder.check(res, ()).unwrap(); + } + + #[test] + fn test_arithmetic_decoder_hello_long() { + let mut decoder = ArithmeticDecoder::new(); + let data = b"hello world"; + let size = data.len(); + let mut buf = vec![[0u8; 4]; (size + 3) / 4]; + buf.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&data[..]); + decoder.init(buf, size).unwrap(); + let mut res = decoder.start_accumulated_result(); + assert_eq!(false, decoder.read_flag().or_accumulate(&mut res)); + assert_eq!(true, decoder.read_bool(10).or_accumulate(&mut res)); + assert_eq!(false, decoder.read_bool(250).or_accumulate(&mut res)); + assert_eq!(1, decoder.read_literal(1).or_accumulate(&mut res)); + assert_eq!(5, decoder.read_literal(3).or_accumulate(&mut res)); + assert_eq!(64, decoder.read_literal(8).or_accumulate(&mut res)); + assert_eq!(185, decoder.read_literal(8).or_accumulate(&mut res)); + assert_eq!(31, decoder.read_literal(8).or_accumulate(&mut res)); + decoder.check(res, ()).unwrap(); + } + + #[test] + fn test_arithmetic_decoder_uninit() { + let mut decoder = ArithmeticDecoder::new(); + let mut res = decoder.start_accumulated_result(); + let _ = decoder.read_flag().or_accumulate(&mut res); + let result = decoder.check(res, ()); + assert!(result.is_err()); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/yuv.rs clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/yuv.rs --- clamav-1.4.3+dfsg/.cargo/vendor/image-webp/src/yuv.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/image-webp/src/yuv.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,452 @@ +//! Utilities for doing the YUV -> RGB conversion +//! The images are encoded in the Y'CbCr format as detailed here: +//! so need to be converted to RGB to be displayed +//! To do the YUV -> RGB conversion we need to first decide how to map the yuv values to the pixels +//! The y buffer is the same size as the pixel buffer so that maps 1-1 but the +//! u and v buffers are half the size of the pixel buffer so we need to scale it up +//! The simple way to upscale is just to take each u/v value and associate it with the 4 +//! pixels around it e.g. for a 4x4 image: +//! +//! |||||| +//! |yyyy| +//! |yyyy| +//! |yyyy| +//! |yyyy| +//! |||||| +//! +//! ||||||| +//! |uu|vv| +//! |uu|vv| +//! ||||||| +//! +//! Then each of the 2x2 pixels would match the u/v from the same quadrant +//! +//! However fancy upsampling is the default for libwebp which does a little more work to make the values smoother +//! It interpolates u and v so that for e.g. the pixel 1 down and 1 from the left the u value +//! would be (9*u0 + 3*u1 + 3*u2 + u3 + 8) / 16 and similar for the other pixels +//! The edges are mirrored, so for the pixel 1 down and 0 from the left it uses (9*u0 + 3*u2 + 3*u0 + u2 + 8) / 16 + +/// `_mm_mulhi_epu16` emulation +fn mulhi(v: u8, coeff: u16) -> i32 { + ((u32::from(v) * u32::from(coeff)) >> 8) as i32 +} + +/// This function has been rewritten to encourage auto-vectorization. +/// +/// Based on [src/dsp/yuv.h](https://github.com/webmproject/libwebp/blob/8534f53960befac04c9631e6e50d21dcb42dfeaf/src/dsp/yuv.h#L79) +/// from the libwebp source. +/// ```text +/// const YUV_FIX2: i32 = 6; +/// const YUV_MASK2: i32 = (256 << YUV_FIX2) - 1; +/// fn clip(v: i32) -> u8 { +/// if (v & !YUV_MASK2) == 0 { +/// (v >> YUV_FIX2) as u8 +/// } else if v < 0 { +/// 0 +/// } else { +/// 255 +/// } +/// } +/// ``` +// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. +#[allow(clippy::manual_clamp)] +fn clip(v: i32) -> u8 { + const YUV_FIX2: i32 = 6; + (v >> YUV_FIX2).max(0).min(255) as u8 +} + +#[inline(always)] +fn yuv_to_r(y: u8, v: u8) -> u8 { + clip(mulhi(y, 19077) + mulhi(v, 26149) - 14234) +} + +#[inline(always)] +fn yuv_to_g(y: u8, u: u8, v: u8) -> u8 { + clip(mulhi(y, 19077) - mulhi(u, 6419) - mulhi(v, 13320) + 8708) +} + +#[inline(always)] +fn yuv_to_b(y: u8, u: u8) -> u8 { + clip(mulhi(y, 19077) + mulhi(u, 33050) - 17685) +} + +/// Fills an rgb buffer with the image from the yuv buffers +/// Size of the buffer is assumed to be correct +/// BPP is short for bytes per pixel, allows both rgb and rgba to be decoded +pub(crate) fn fill_rgb_buffer_fancy( + buffer: &mut [u8], + y_buffer: &[u8], + u_buffer: &[u8], + v_buffer: &[u8], + width: usize, + height: usize, + buffer_width: usize, +) { + // buffer width is always even so don't need to do div_ceil + let chroma_buffer_width = buffer_width / 2; + let chroma_width = width.div_ceil(2); + + // fill top row first since it only uses the top u/v row + let top_row_y = &y_buffer[..width]; + let top_row_u = &u_buffer[..chroma_width]; + let top_row_v = &v_buffer[..chroma_width]; + let top_row_buffer = &mut buffer[..width * BPP]; + fill_row_fancy_with_1_uv_row::(top_row_buffer, top_row_y, top_row_u, top_row_v); + + let mut main_row_chunks = buffer[width * BPP..].chunks_exact_mut(width * BPP * 2); + // the y buffer iterator limits the end of the row iterator so we need this end index + let end_y_index = height * buffer_width; + let mut main_y_chunks = y_buffer[buffer_width..end_y_index].chunks_exact(buffer_width * 2); + let mut main_u_windows = u_buffer + .windows(chroma_buffer_width * 2) + .step_by(chroma_buffer_width); + let mut main_v_windows = v_buffer + .windows(chroma_buffer_width * 2) + .step_by(chroma_buffer_width); + + for (((row_buffer, y_rows), u_rows), v_rows) in (&mut main_row_chunks) + .zip(&mut main_y_chunks) + .zip(&mut main_u_windows) + .zip(&mut main_v_windows) + { + let (u_row_1, u_row_2) = u_rows.split_at(chroma_buffer_width); + let (v_row_1, v_row_2) = v_rows.split_at(chroma_buffer_width); + let (row_buf_1, row_buf_2) = row_buffer.split_at_mut(width * BPP); + let (y_row_1, y_row_2) = y_rows.split_at(buffer_width); + fill_row_fancy_with_2_uv_rows::( + row_buf_1, + &y_row_1[..width], + &u_row_1[..chroma_width], + &u_row_2[..chroma_width], + &v_row_1[..chroma_width], + &v_row_2[..chroma_width], + ); + fill_row_fancy_with_2_uv_rows::( + row_buf_2, + &y_row_2[..width], + &u_row_2[..chroma_width], + &u_row_1[..chroma_width], + &v_row_2[..chroma_width], + &v_row_1[..chroma_width], + ); + } + + let final_row_buffer = main_row_chunks.into_remainder(); + + // if the image has even height there will be one final row with only one u/v row matching it + if !final_row_buffer.is_empty() { + let final_y_row = main_y_chunks.remainder(); + + let chroma_height = height.div_ceil(2); + let start_chroma_index = (chroma_height - 1) * chroma_buffer_width; + + let final_u_row = &u_buffer[start_chroma_index..]; + let final_v_row = &v_buffer[start_chroma_index..]; + fill_row_fancy_with_1_uv_row::( + final_row_buffer, + &final_y_row[..width], + &final_u_row[..chroma_width], + &final_v_row[..chroma_width], + ); + } +} + +/// Fills a row with the fancy interpolation as detailed +fn fill_row_fancy_with_2_uv_rows( + row_buffer: &mut [u8], + y_row: &[u8], + u_row_1: &[u8], + u_row_2: &[u8], + v_row_1: &[u8], + v_row_2: &[u8], +) { + // need to do left pixel separately since it will only have one u/v value + { + let rgb1 = &mut row_buffer[0..3]; + let y_value = y_row[0]; + // first pixel uses the first u/v as the main one + let u_value = get_fancy_chroma_value(u_row_1[0], u_row_1[0], u_row_2[0], u_row_2[0]); + let v_value = get_fancy_chroma_value(v_row_1[0], v_row_1[0], v_row_2[0], v_row_2[0]); + set_pixel(rgb1, y_value, u_value, v_value); + } + + let rest_row_buffer = &mut row_buffer[BPP..]; + let rest_y_row = &y_row[1..]; + + // we do two pixels at a time since they share the same u/v values + let mut main_row_chunks = rest_row_buffer.chunks_exact_mut(BPP * 2); + let mut main_y_chunks = rest_y_row.chunks_exact(2); + + for (((((rgb, y_val), u_val_1), u_val_2), v_val_1), v_val_2) in (&mut main_row_chunks) + .zip(&mut main_y_chunks) + .zip(u_row_1.windows(2)) + .zip(u_row_2.windows(2)) + .zip(v_row_1.windows(2)) + .zip(v_row_2.windows(2)) + { + { + let rgb1 = &mut rgb[0..3]; + let y_value = y_val[0]; + // first pixel uses the first u/v as the main one + let u_value = get_fancy_chroma_value(u_val_1[0], u_val_1[1], u_val_2[0], u_val_2[1]); + let v_value = get_fancy_chroma_value(v_val_1[0], v_val_1[1], v_val_2[0], v_val_2[1]); + set_pixel(rgb1, y_value, u_value, v_value); + } + { + let rgb2 = &mut rgb[BPP..]; + let y_value = y_val[1]; + let u_value = get_fancy_chroma_value(u_val_1[1], u_val_1[0], u_val_2[1], u_val_2[0]); + let v_value = get_fancy_chroma_value(v_val_1[1], v_val_1[0], v_val_2[1], v_val_2[0]); + set_pixel(rgb2, y_value, u_value, v_value); + } + } + + let final_pixel = main_row_chunks.into_remainder(); + let final_y = main_y_chunks.remainder(); + + if let (rgb, [y_value]) = (final_pixel, final_y) { + let final_u_1 = *u_row_1.last().unwrap(); + let final_u_2 = *u_row_2.last().unwrap(); + + let final_v_1 = *v_row_1.last().unwrap(); + let final_v_2 = *v_row_2.last().unwrap(); + + let rgb1 = &mut rgb[0..3]; + // first pixel uses the first u/v as the main one + let u_value = get_fancy_chroma_value(final_u_1, final_u_1, final_u_2, final_u_2); + let v_value = get_fancy_chroma_value(final_v_1, final_v_1, final_v_2, final_v_2); + set_pixel(rgb1, *y_value, u_value, v_value); + } +} + +fn fill_row_fancy_with_1_uv_row( + row_buffer: &mut [u8], + y_row: &[u8], + u_row: &[u8], + v_row: &[u8], +) { + // doing left pixel first + { + let rgb1 = &mut row_buffer[0..3]; + let y_value = y_row[0]; + + let u_value = u_row[0]; + let v_value = v_row[0]; + set_pixel(rgb1, y_value, u_value, v_value); + } + + // two pixels at a time since they share the same u/v value + let mut main_row_chunks = row_buffer[BPP..].chunks_exact_mut(BPP * 2); + let mut main_y_row_chunks = y_row[1..].chunks_exact(2); + + for (((rgb, y_val), u_val), v_val) in (&mut main_row_chunks) + .zip(&mut main_y_row_chunks) + .zip(u_row.windows(2)) + .zip(v_row.windows(2)) + { + { + let rgb1 = &mut rgb[0..3]; + let y_value = y_val[0]; + // first pixel uses the first u/v as the main one + let u_value = get_fancy_chroma_value(u_val[0], u_val[1], u_val[0], u_val[1]); + let v_value = get_fancy_chroma_value(v_val[0], v_val[1], v_val[0], v_val[1]); + set_pixel(rgb1, y_value, u_value, v_value); + } + { + let rgb2 = &mut rgb[BPP..]; + let y_value = y_val[1]; + let u_value = get_fancy_chroma_value(u_val[1], u_val[0], u_val[1], u_val[0]); + let v_value = get_fancy_chroma_value(v_val[1], v_val[0], v_val[1], v_val[0]); + set_pixel(rgb2, y_value, u_value, v_value); + } + } + + let final_pixel = main_row_chunks.into_remainder(); + let final_y = main_y_row_chunks.remainder(); + + if let (rgb, [final_y]) = (final_pixel, final_y) { + let final_u = *u_row.last().unwrap(); + let final_v = *v_row.last().unwrap(); + + set_pixel(rgb, *final_y, final_u, final_v); + } +} + +#[inline] +fn get_fancy_chroma_value(main: u8, secondary1: u8, secondary2: u8, tertiary: u8) -> u8 { + let val0 = u16::from(main); + let val1 = u16::from(secondary1); + let val2 = u16::from(secondary2); + let val3 = u16::from(tertiary); + ((9 * val0 + 3 * val1 + 3 * val2 + val3 + 8) / 16) as u8 +} + +#[inline] +fn set_pixel(rgb: &mut [u8], y: u8, u: u8, v: u8) { + rgb[0] = yuv_to_r(y, v); + rgb[1] = yuv_to_g(y, u, v); + rgb[2] = yuv_to_b(y, u); +} + +/// Simple conversion, not currently used but could add a config to allow for using the simple +#[allow(unused)] +pub(crate) fn fill_rgb_buffer_simple( + buffer: &mut [u8], + y_buffer: &[u8], + u_buffer: &[u8], + v_buffer: &[u8], + width: usize, + chroma_width: usize, + buffer_width: usize, +) { + let u_row_twice_iter = u_buffer + .chunks_exact(buffer_width / 2) + .flat_map(|n| std::iter::repeat(n).take(2)); + let v_row_twice_iter = v_buffer + .chunks_exact(buffer_width / 2) + .flat_map(|n| std::iter::repeat(n).take(2)); + + for (((row, y_row), u_row), v_row) in buffer + .chunks_exact_mut(width * BPP) + .zip(y_buffer.chunks_exact(buffer_width)) + .zip(u_row_twice_iter) + .zip(v_row_twice_iter) + { + fill_rgba_row_simple::( + &y_row[..width], + &u_row[..chroma_width], + &v_row[..chroma_width], + row, + ); + } +} + +fn fill_rgba_row_simple( + y_vec: &[u8], + u_vec: &[u8], + v_vec: &[u8], + rgba: &mut [u8], +) { + // Fill 2 pixels per iteration: these pixels share `u` and `v` components + let mut rgb_chunks = rgba.chunks_exact_mut(BPP * 2); + let mut y_chunks = y_vec.chunks_exact(2); + let mut u_iter = u_vec.iter(); + let mut v_iter = v_vec.iter(); + + for (((rgb, y), &u), &v) in (&mut rgb_chunks) + .zip(&mut y_chunks) + .zip(&mut u_iter) + .zip(&mut v_iter) + { + let coeffs = [ + mulhi(v, 26149), + mulhi(u, 6419), + mulhi(v, 13320), + mulhi(u, 33050), + ]; + + let get_r = |y: u8| clip(mulhi(y, 19077) + coeffs[0] - 14234); + let get_g = |y: u8| clip(mulhi(y, 19077) - coeffs[1] - coeffs[2] + 8708); + let get_b = |y: u8| clip(mulhi(y, 19077) + coeffs[3] - 17685); + + let rgb1 = &mut rgb[0..3]; + rgb1[0] = get_r(y[0]); + rgb1[1] = get_g(y[0]); + rgb1[2] = get_b(y[0]); + + let rgb2 = &mut rgb[BPP..]; + rgb2[0] = get_r(y[1]); + rgb2[1] = get_g(y[1]); + rgb2[2] = get_b(y[1]); + } + + let remainder = rgb_chunks.into_remainder(); + if remainder.len() >= 3 { + if let (Some(&y), Some(&u), Some(&v)) = ( + y_chunks.remainder().iter().next(), + u_iter.next(), + v_iter.next(), + ) { + let coeffs = [ + mulhi(v, 26149), + mulhi(u, 6419), + mulhi(v, 13320), + mulhi(u, 33050), + ]; + + remainder[0] = clip(mulhi(y, 19077) + coeffs[0] - 14234); + remainder[1] = clip(mulhi(y, 19077) - coeffs[1] - coeffs[2] + 8708); + remainder[2] = clip(mulhi(y, 19077) + coeffs[3] - 17685); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fancy_grid() { + #[rustfmt::skip] + let y_buffer = [ + 77, 162, 202, 185, + 28, 13, 199, 182, + 135, 147, 164, 135, + 66, 27, 171, 130, + ]; + + #[rustfmt::skip] + let u_buffer = [ + 34, 101, + 123, 163 + ]; + + #[rustfmt::skip] + let v_buffer = [ + 97, 167, + 149, 23, + ]; + + let mut rgb_buffer = [0u8; 16 * 3]; + fill_rgb_buffer_fancy::<3>(&mut rgb_buffer, &y_buffer, &u_buffer, &v_buffer, 4, 4, 4); + + #[rustfmt::skip] + let upsampled_u_buffer = [ + 34, 51, 84, 101, + 56, 71, 101, 117, + 101, 112, 136, 148, + 123, 133, 153, 163, + ]; + + #[rustfmt::skip] + let upsampled_v_buffer = [ + 97, 115, 150, 167, + 110, 115, 126, 131, + 136, 117, 78, 59, + 149, 118, 55, 23, + ]; + + let mut upsampled_rgb_buffer = [0u8; 16 * 3]; + for (((rgb_val, y), u), v) in upsampled_rgb_buffer + .chunks_exact_mut(3) + .zip(y_buffer) + .zip(upsampled_u_buffer) + .zip(upsampled_v_buffer) + { + rgb_val[0] = yuv_to_r(y, v); + rgb_val[1] = yuv_to_g(y, u, v); + rgb_val[2] = yuv_to_b(y, u); + } + + assert_eq!(rgb_buffer, upsampled_rgb_buffer); + } + + #[test] + fn test_yuv_conversions() { + let (y, u, v) = (203, 40, 42); + + assert_eq!(yuv_to_r(y, v), 80); + assert_eq!(yuv_to_g(y, u, v), 255); + assert_eq!(yuv_to_b(y, u), 40); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"efd78dcd1b6ba0c3f9572000691596516b00d7b6235a7138b4c83f1730cc03ba",".github/workflows/cargo.yml":"0e6c3cc4cf21948563e3c89616a05b0c2aa0701c885259fb4f28f7f1c75d566a","Cargo.lock":"4693bbb746bf8b4d9f7ca829cefdd82144060b7cb077d1584286b3da3e1284e3","Cargo.toml":"9417cccfe77ebfdf6610d016476f9db1e50859ab75669d3cd072d162fe582be2","Cargo.toml.orig":"8ff0b1e81fab4295fae7bb840ff73e597ce3e8bb14cdaff0997418ac8d5849d4","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-CC0":"a2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499","README.md":"0d94d49740a7689931f1e6b71c8b7b6e15ca71c86525a59505063645d1ddd9f0","benches/iterbench.rs":"0140cd0bec660a1c4cbeabd414cb55a801f7c93768ed50e08fc488c4664f15bf","imgref.png":"af4304d48b9d18946d3eaf1d769565f85f3b3b4ffa51ddc534c6fa48eba9f9db","src/iter.rs":"e114b8f489b67fdbcac8c2b76aeb79c8e3ad2840d383d204deceea07601a5afd","src/lib.rs":"b73288ff86eb07a0aefee1ea2999a99d01a9525d3c1abf4c3cade4e670ff0819","src/ops.rs":"ed0f23cc5cf424578ac04f209e24ea12687ecdfc9fa0b0a505749284384d8a9d","src/traits.rs":"98362e18dc4361575592b9ce7178227d9e11e674363a93b3e1c9c9698e142638"},"package":"e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c987cc5333e2cf89e4e88e7d302bd2f2d9074f8f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/.github/workflows/cargo.yml clamav-1.4.6+dfsg/.cargo/vendor/imgref/.github/workflows/cargo.yml --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/.github/workflows/cargo.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/.github/workflows/cargo.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,31 @@ +name: CI + +on: + push: + pull_request: + branches: + # Branches from forks have the form 'user:branch-name' so we only run + # this job on pull_request events for branches that look like fork + # branches. Without this we would end up running this job twice for non + # forked PRs, once for the push and then once for opening the PR. + - '**:**' + +jobs: + test: + name: Test + strategy: + matrix: + rust: + - stable + - nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + - uses: actions-rs/cargo@v1 + with: + command: test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "imgref" +version = "1.12.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,59 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.61" +name = "imgref" +version = "1.12.0" +authors = ["Kornel Lesiński "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A basic 2-dimensional slice for safe and convenient handling of pixel buffers with width, height & stride" +homepage = "https://lib.rs/crates/imgref" +documentation = "https://docs.rs/imgref/" +readme = "README.md" +keywords = [ + "interoperability", + "stride", + "plane", + "frame", + "vec2d", +] +categories = [ + "rust-patterns", + "multimedia::images", +] +license = "CC0-1.0 OR Apache-2.0" +repository = "https://github.com/kornelski/imgref" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] + +[badges.maintenance] +status = "actively-developed" + +[features] +default = ["deprecated"] +deprecated = [] + +[lib] +name = "imgref" +path = "src/lib.rs" + +[[bench]] +name = "iterbench" +path = "benches/iterbench.rs" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,25 @@ +[package] +authors = ["Kornel Lesiński "] +categories = ["rust-patterns", "multimedia::images"] +description = "A basic 2-dimensional slice for safe and convenient handling of pixel buffers with width, height & stride" +documentation = "https://docs.rs/imgref/" +homepage = "https://lib.rs/crates/imgref" +keywords = ["interoperability", "stride", "plane", "frame", "vec2d"] +license = "CC0-1.0 OR Apache-2.0" +name = "imgref" +readme = "README.md" +repository = "https://github.com/kornelski/imgref" +version = "1.12.0" +edition = "2021" +rust-version = "1.61" + +[features] +default = ["deprecated"] +deprecated = [] + +[badges] +maintenance = { status = "actively-developed" } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/LICENSE-APACHE clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-APACHE --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-APACHE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://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. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/LICENSE-CC0 clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-CC0 --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/LICENSE-CC0 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/LICENSE-CC0 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/README.md clamav-1.4.6+dfsg/.cargo/vendor/imgref/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,63 @@ +# 2D slice of a an image + +This is a minimal struct that represents a 2-dimensional vector and rectangular slices of it. It's intended for describing image data, and regions of images (AKA bitmap descriptors, frames with a pitch or stride, planes). It's useful when working with image data, and can be used as the common struct for exchanging image pixels between crates. + +* [API Reference](https://docs.rs/imgref) +* [Installation](https://crates.io/crates/imgref) + +In graphics code it's very common to pass `width` and `height` along with a `Vec` or a slice of pixels — all as separate arguments. This gets very repetitive, and can lead to errors. + +Additionally, some graphics code requires use of `stride`, which allows defining sub-regions of images without copying. This is useful for slicing and tiling, and to support bitmaps that require padding (e.g. in video formats that round frame sizes to a multiple of a block size). + +This crate is a simple struct that adds dimensions to the underlying pixel buffer. This makes it easier to correctly keep track of the image size and allows passing images with just one function argument instead three or four. For convenience, it also implements efficient iterators for pixels/rows and indexing with `img[(x,y)]`. + +```rust +use imgref::*; + +fn main() { + let img = Img::new(vec![0; 1000], 50, 20); // 1000 pixels of a 50×20 image + + let new_image = some_image_processing_function(img.as_ref()); // Use imgvec.as_ref() instead of &imgvec for better efficiency + + println!("New size is {}×{}", new_image.width(), new_image.height()); + println!("And the top left pixel is {:?}", new_image[(0u32,0u32)]); + + let first_row_slice = &new_image[0]; + + for row in new_image.rows() { + … + } + for px in new_image.pixels() { + … + } + + // slice (x, y, width, height) by reference - no copy! + let fragment = img.sub_image(5, 5, 15, 15); + + // create a vec of pixels without stride, for compatibility with software + // that expects pixels without any "gaps" + let (vec, width, height) = fragment.to_contiguous_buf(); +} +``` + +## Type aliases + +Illustration: stride is width of the whole buffer. + +These are described in [more detail in the reference](https://docs.rs/imgref). + +### `ImgVec` + +It owns its pixels (held in a `Vec`). It's analogous to a 2-dimensional `Vec`. Use this type to create and return new images from functions. + +Don't use `&ImgVec`. Instead call `ImgVec.as_ref()` to get a reference (`ImgRef`) from it (explicit `.as_ref()` call is required, because Rust doesn't support [custom conversions](https://github.com/rust-lang/rfcs/pull/1524) yet.) + +### `ImgRef` + +`ImgRef` is a reference to pixels owned by some other `ImgVec` or a slice. It's analogous to a 2-dimensional `&[]`. + +Use this type to accept read-only images as arguments in functions. Note that `ImgRef` is a `Copy` type. Pass `ImgRef`, and *not* `&ImgRef`. + +### Requirements + +* Latest stable Rust (1.42+) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/benches/iterbench.rs clamav-1.4.6+dfsg/.cargo/vendor/imgref/benches/iterbench.rs --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/benches/iterbench.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/benches/iterbench.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,41 @@ +#![feature(test)] + +extern crate test; +use imgref::*; +use test::Bencher; + +#[bench] +fn iter_count(bench: &mut Bencher) { + let img = Img::new_stride(vec![0x11223344u32; 802*600], 800, 600, 802); + + bench.iter(|| { + img.pixels().count() + }); +} + +#[bench] +fn iter_sum(bench: &mut Bencher) { + let img = Img::new_stride(vec![0x11223344u32; 802*600], 800, 600, 802); + + bench.iter(|| { + img.pixels().map(|p| p as usize).sum::() + }); +} + +#[bench] +fn stride_ignorant_sum(bench: &mut Bencher) { + let img = Img::new_stride(vec![0x11223344u32; 802*600], 800, 600, 802); + + bench.iter(|| { + img.buf().iter().copied().map(|p| p as usize).sum::() + }); +} + +#[bench] +fn chunked_sum(bench: &mut Bencher) { + let img = Img::new_stride(vec![0x11223344u32; 802*600], 800, 600, 802); + + bench.iter(|| { + img.buf().chunks(img.stride()).flat_map(|row| row[0..img.width()].iter()).copied().map(|p| p as usize).sum::() + }); +} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/imgref/imgref.png and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/imgref/imgref.png differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/iter.rs clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/iter.rs --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/iter.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/iter.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,345 @@ +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::num::NonZeroUsize; +use core::slice; + +#[cfg(test)] +use alloc::vec; + +/// Rows of the image. Call `Img.rows()` to create it. +/// +/// Each element is a slice `width` pixels wide. Ignores padding, if there's any. +#[derive(Debug)] +#[must_use] +pub struct RowsIter<'a, T> { + pub(crate) inner: slice::Chunks<'a, T>, + pub(crate) width: usize, +} + +impl<'a, T: 'a> Iterator for RowsIter<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option { + match self.inner.next() { + Some(s) => { + // guaranteed during creation of chunks iterator + debug_assert!(s.len() >= self.width); + unsafe { + Some(s.get_unchecked(0..self.width)) + } + }, + None => None, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + match self.inner.nth(n) { + Some(s) => { + // guaranteed during creation of chunks iterator + debug_assert!(s.len() >= self.width); + unsafe { + Some(s.get_unchecked(0..self.width)) + } + }, + None => None, + } + } + + #[inline] + fn count(self) -> usize { + self.inner.count() + } +} + +impl ExactSizeIterator for RowsIter<'_, T> { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} + +impl FusedIterator for RowsIter<'_, T> {} + +impl<'a, T: 'a> DoubleEndedIterator for RowsIter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option { + match self.inner.next_back() { + Some(s) => { + // guaranteed during creation of chunks iterator + debug_assert!(s.len() >= self.width); + unsafe { + Some(s.get_unchecked(0..self.width)) + } + }, + None => None, + } + } +} + +/// Rows of the image. Call `Img.rows_mut()` to create it. +/// +/// Each element is a slice `width` pixels wide. Ignores padding, if there's any. +#[derive(Debug)] +#[must_use] +pub struct RowsIterMut<'a, T> { + pub(crate) width: usize, + pub(crate) inner: slice::ChunksMut<'a, T>, +} + +impl<'a, T: 'a> Iterator for RowsIterMut<'a, T> { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option { + match self.inner.next() { + Some(s) => Some(&mut s[0..self.width]), + None => None, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + match self.inner.nth(n) { + Some(s) => Some(&mut s[0..self.width]), + None => None, + } + } + + #[inline] + fn count(self) -> usize { + self.inner.count() + } +} + +impl ExactSizeIterator for RowsIterMut<'_, T> {} +impl FusedIterator for RowsIterMut<'_, T> {} + +impl<'a, T: 'a> DoubleEndedIterator for RowsIterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option { + match self.inner.next_back() { + Some(s) => Some(&mut s[0..self.width]), + None => None, + } + } +} + +/// Iterates over pixels in the (sub)image. Call `Img.pixels()` to create it. +/// +/// Ignores padding, if there's any. +#[must_use] +pub struct PixelsIter<'a, T: Copy> { + inner: PixelsRefIter<'a, T>, +} + +impl<'a, T: Copy + 'a> PixelsIter<'a, T> { + #[inline(always)] + #[track_caller] + pub(crate) fn new(img: super::ImgRef<'a, T>) -> Self { + Self { + inner: PixelsRefIter::new(img) + } + } +} + +impl<'a, T: Copy + 'a> Iterator for PixelsIter<'a, T> { + type Item = T; + + #[inline(always)] + fn next(&mut self) -> Option { + self.inner.next().copied() + } +} + +impl ExactSizeIterator for PixelsIter<'_, T> { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} + +/// Iterates over pixels in the (sub)image. Call `Img.pixels_ref()` to create it. +/// +/// Ignores padding, if there's any. +#[derive(Debug)] +#[must_use] +pub struct PixelsRefIter<'a, T> { + current: *const T, + current_line_end: *const T, + rows_left: usize, + width: NonZeroUsize, + pad: usize, + _dat: PhantomData<&'a [T]>, +} + +unsafe impl Send for PixelsRefIter<'_, T> where T: Send {} +unsafe impl Sync for PixelsRefIter<'_, T> where T: Sync {} + +impl<'a, T: 'a> PixelsRefIter<'a, T> { + #[inline] + #[track_caller] + pub(crate) fn new(img: super::ImgRef<'a, T>) -> Self { + let width = NonZeroUsize::new(img.width()).expect("width > 0"); + let height = img.height(); + let stride = img.stride(); + assert!(stride >= width.get()); + let pad = stride - width.get(); + debug_assert!(img.buf().len() + stride >= stride * height + width.get(), + "buffer len {} is less than {} (({}+{})x{})", img.buf().len(), + stride * height - pad, width, pad, height); + Self { + current: img.buf().as_ptr(), + current_line_end: img.buf()[width.get()..].as_ptr(), + width, + rows_left: height, + pad, + _dat: PhantomData, + } + } +} + +impl<'a, T: 'a> Iterator for PixelsRefIter<'a, T> { + type Item = &'a T; + + #[inline(always)] + fn next(&mut self) -> Option { + unsafe { + if self.current >= self.current_line_end { + if self.rows_left <= 1 { + return None; + } + self.rows_left -= 1; + self.current = self.current_line_end.add(self.pad); + self.current_line_end = self.current.add(self.width.get()); + } + let px = &*self.current; + self.current = self.current.add(1); + Some(px) + } + } + + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + fn size_hint(&self) -> (usize, Option) { + let this_line = unsafe { + self.current_line_end.offset_from(self.current) + }; + debug_assert!(this_line >= 0); + let len = this_line as usize + (self.rows_left - 1) * self.width.get(); + (len, Some(len)) + } +} + +impl ExactSizeIterator for PixelsRefIter<'_, T> { +} + +/// Iterates over pixels in the (sub)image. Call `Img.pixels_mut()` to create it. +/// +/// Ignores padding, if there's any. +#[derive(Debug)] +#[must_use] +pub struct PixelsIterMut<'a, T> { + current: *mut T, + current_line_end: *mut T, + y: usize, + width: NonZeroUsize, + pad: usize, + _dat: PhantomData<&'a mut [T]>, +} + +unsafe impl Send for PixelsIterMut<'_, T> where T: Send {} +unsafe impl Sync for PixelsIterMut<'_, T> where T: Sync {} + +impl<'a, T: 'a> PixelsIterMut<'a, T> { + #[inline] + #[track_caller] + pub(crate) fn new(img: &mut super::ImgRefMut<'a, T>) -> Self { + let width = NonZeroUsize::new(img.width()).expect("width > 0"); + let stride = img.stride(); + debug_assert!(!img.buf().is_empty() && img.buf().len() + stride >= stride * img.height() + width.get()); + Self { + current: img.buf_mut().as_mut_ptr(), + current_line_end: img.buf_mut()[width.get()..].as_mut_ptr(), + width, + y: img.height(), + pad: stride - width.get(), + _dat: PhantomData, + } + } +} + +impl<'a, T: 'a> Iterator for PixelsIterMut<'a, T> { + type Item = &'a mut T; + + #[inline(always)] + fn next(&mut self) -> Option { + unsafe { + if self.current >= self.current_line_end { + self.y -= 1; + if self.y == 0 { + return None; + } + self.current = self.current_line_end.add(self.pad); + self.current_line_end = self.current.add(self.width.get()); + } + let px = &mut *self.current; + self.current = self.current.add(1); + Some(px) + } + } +} + +#[test] +fn iter() { + let img = super::Img::new(vec![1u8, 2], 1, 2); + let mut it = img.pixels(); + assert_eq!(Some(1), it.next()); + assert_eq!(Some(2), it.next()); + assert_eq!(None, it.next()); + + let buf = [1u8; (16 + 3) * (8 + 1)]; + for width in 1..16 { + for height in 1..8 { + for pad in 0..3 { + let stride = width + pad; + let img = super::Img::new_stride(&buf[..stride * height + stride - width], width, height, stride); + assert_eq!(width * height, img.pixels().map(|a| a as usize).sum(), "{width}x{height}"); + assert_eq!(width * height, img.pixels().count(), "{width}x{height}"); + assert_eq!(height, img.rows().count()); + + let mut iter1 = img.pixels(); + let mut left = width * height; + while let Some(_px) = iter1.next() { + left -= 1; + assert_eq!(left, iter1.len()); + } + assert_eq!(0, iter1.len()); + iter1.next(); + assert_eq!(0, iter1.len()); + + let mut iter2 = img.rows(); + match iter2.next() { + Some(_) => { + assert_eq!(height - 1, iter2.size_hint().0); + assert_eq!(height - 1, iter2.filter(|_| true).count()); + }, + None => { + assert_eq!(height, 0); + }, + }; + } + } + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,972 @@ +//! In graphics code it's very common to pass `width` and `height` along with a `Vec` of pixels, +//! all as separate arguments. This is tedious, and can lead to errors. +//! +//! This crate is a simple struct that adds dimensions to the underlying buffer. This makes it easier to correctly keep track +//! of the image size and allows passing images with just one function argument instead three or four. +//! +//! Additionally, it has a concept of a `stride`, which allows defining sub-regions of images without copying, +//! as well as handling padding (e.g. buffers for video frames may require to be a multiple of 8, regardless of logical image size). +//! +//! For convenience, there are iterators over rows or all pixels of a (sub)image and +//! pixel-based indexing directly with `img[(x,y)]` (where `x`/`y` can be `u32` as well as `usize`). +//! +//! `Img` type has aliases for common uses: +//! +//! * Owned: `ImgVec` → `Img>` (use it in `struct`s and return types) +//! * Reference: `ImgRef` → `Img<&[T]>` (use it in function arguments) +//! * Mutable reference: `ImgRefMut` → `Img<&mut [T]>` +//! +//! It is assumed that the container is [one element per pixel](https://crates.io/crates/rgb/), e.g. `Vec`, +//! and _not_ a `Vec` where 4 `u8` elements are interpreted as one pixel. +//! +//! +//! ```rust +//! use imgref::*; +//! # fn some_image_processing_function(img: ImgRef) -> ImgVec { img.new_buf(img.buf().to_vec()) } +//! +//! fn main() { +//! let img = Img::new(vec![0; 1000], 50, 20); // 1000 pixels of a 50×20 image +//! +//! let new_image = some_image_processing_function(img.as_ref()); // Use imgvec.as_ref() instead of &imgvec for better efficiency +//! +//! println!("New size is {}×{}", new_image.width(), new_image.height()); +//! println!("And the top left pixel is {:?}", new_image[(0u32,0u32)]); +//! +//! let first_row_slice = &new_image[0]; +//! +//! for row in new_image.rows() { +//! // … +//! } +//! for px in new_image.pixels() { +//! // … +//! } +//! +//! // slice (x, y, width, height) by reference - no copy! +//! let fragment = img.sub_image(5, 5, 15, 15); +//! +//! // +//! let (vec, width, height) = fragment.to_contiguous_buf(); +//! } +//! ``` + +#![no_std] + +extern crate alloc; +#[cfg(test)] +extern crate std; + +use alloc::borrow::{Cow, ToOwned}; +use alloc::vec::Vec; +use core::slice; + +mod traits; + +mod iter; +mod ops; +pub use iter::*; + +/// Image owning its pixels. +/// +/// A 2D array of pixels. The pixels are oriented top-left first and rows are `stride` pixels wide. +/// +/// If size of the `buf` is larger than `width`*`height`, then any excess space is a padding (see `width_padded()`/`height_padded()`). +pub type ImgVec = Img>; + +/// Reference to pixels inside another image. +/// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`). +/// +/// Only `width` of pixels of every `stride` can be modified. The `buf` may be longer than `height`*`stride`, but the extra space should be ignored. +pub type ImgRef<'slice, Pixel> = Img<&'slice [Pixel]>; + +/// Same as `ImgRef`, but mutable +/// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`). +/// +pub type ImgRefMut<'slice, Pixel> = Img<&'slice mut [Pixel]>; + +/// Additional methods that depend on buffer size +/// +/// To use these methods you need: +/// +/// ```rust +/// use imgref::*; +/// ``` +pub trait ImgExt { + /// Maximum possible width of the data, including the stride. + /// + /// # Panics + /// + /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large. + #[cfg(feature = "deprecated")] + fn width_padded(&self) -> usize; + + /// Height in number of full strides. + /// If the underlying buffer is not an even multiple of strides, the last row is ignored. + /// + /// # Panics + /// + /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large. + #[cfg(feature = "deprecated")] + fn height_padded(&self) -> usize; + + /// Iterate over the entire buffer as rows, including all padding + /// + /// Rows will have up to `stride` width, but the last row may be shorter. + #[cfg(feature = "deprecated")] + fn rows_padded(&self) -> slice::Chunks<'_, Pixel>; + + /// Borrow the container + fn as_ref(&self) -> ImgRef<'_, Pixel>; +} + +/// Additional methods that depend on buffer size +/// +/// To use these methods you need: +/// +/// ```rust +/// use imgref::*; +/// ``` +pub trait ImgExtMut { + /// Iterate over the entire buffer as rows, including all padding + /// + /// Rows will have up to `stride` width, but the last row may be shorter. + #[cfg(feature = "deprecated")] + fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>; + + /// Borrow the container mutably + fn as_mut(&mut self) -> ImgRefMut<'_, Pixel>; +} + +/// Basic struct used for both owned (alias `ImgVec`) and borrowed (alias `ImgRef`) image fragments. +/// +/// Note: the fields are `pub` only because of borrow checker limitations. Please consider them as read-only. +#[derive(Debug, Copy, Clone)] +pub struct Img { + /// Storage for the pixels. Usually `Vec` or `&[Pixel]`. See `ImgVec` and `ImgRef`. + /// + /// Note that future version will make this field private. Use `.rows()` and `.pixels()` iterators where possible, or `buf()`/`buf_mut()`/`into_buf()`. + #[deprecated(note = "Don't access struct fields directly. Use buf(), buf_mut() or into_buf()")] + #[cfg(feature = "deprecated")] + pub buf: Container, + + #[cfg(not(feature = "deprecated"))] + buf: Container, + + /// Number of pixels to skip in the container to advance to the next row. + /// + /// Note: pixels between `width` and `stride` may not be usable, and may not even exist in the last row. + #[deprecated(note = "Don't access struct fields directly. Use stride()")] + #[cfg(feature = "deprecated")] + pub stride: usize, + + #[cfg(not(feature = "deprecated"))] + stride: usize, + + /// Width of the image in pixels. + /// + /// Note that this isn't same as the width of the row in the `buf`, see `stride` + #[deprecated(note = "Don't access struct fields directly. Use width()")] + #[cfg(feature = "deprecated")] + pub width: u32, + + #[cfg(not(feature = "deprecated"))] + width: u32, + + /// Height of the image in pixels. + #[deprecated(note = "Don't access struct fields directly. Use height()")] + #[cfg(feature = "deprecated")] + pub height: u32, + + #[cfg(not(feature = "deprecated"))] + height: u32, +} + +impl Img { + /// Width of the image in pixels. + /// + /// Note that this isn't same as the width of the row in image data, see `stride()` + #[inline(always)] + #[allow(deprecated)] + pub const fn width(&self) -> usize { self.width as usize } + + /// Height of the image in pixels. + #[inline(always)] + #[allow(deprecated)] + pub const fn height(&self) -> usize { self.height as usize } + + /// Number of _pixels_ to skip in the container to advance to the next row. + /// + /// Note the last row may have fewer pixels than the stride. + /// Some APIs use number of *bytes* for a stride. You may need to multiply this one by number of pixels. + #[inline(always)] + #[allow(deprecated)] + pub const fn stride(&self) -> usize { self.stride } + + /// Immutable reference to the pixel storage. Warning: exposes stride. Use `pixels()` or `rows()` instead. + /// + /// See also `into_contiguous_buf()`. + #[inline(always)] + #[allow(deprecated)] + pub const fn buf(&self) -> &Container { &self.buf } + + /// Mutable reference to the pixel storage. Warning: exposes stride. Use `pixels_mut()` or `rows_mut()` instead. + /// + /// See also `into_contiguous_buf()`. + #[inline(always)] + #[allow(deprecated)] + pub fn buf_mut(&mut self) -> &mut Container { &mut self.buf } + + /// Get the pixel storage by consuming the image. Be careful about stride — see `into_contiguous_buf()` for a safe version. + #[inline(always)] + #[allow(deprecated)] + pub fn into_buf(self) -> Container { self.buf } + + #[deprecated(note = "this was meant to be private, use new_buf() and/or rows()")] + #[cfg(feature = "deprecated")] + #[doc(hidden)] + pub fn rows_buf<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> { + self.rows_buf_internal(buf) + } + + #[inline] + #[track_caller] + fn rows_buf_internal<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> { + let stride = self.stride(); + debug_assert!(self.width() <= self.stride()); + debug_assert!(buf.len() >= self.width() * self.height()); + assert!(stride > 0); + let non_padded = &buf[0..stride * self.height() + self.width() - stride]; + RowsIter { + width: self.width(), + inner: non_padded.chunks(stride), + } + } +} + +impl ImgExt for Img where Container: AsRef<[Pixel]> { + #[inline(always)] + #[cfg(feature = "deprecated")] + fn width_padded(&self) -> usize { + self.stride() + } + + #[inline(always)] + #[cfg(feature = "deprecated")] + fn height_padded(&self) -> usize { + let len = self.buf().as_ref().len(); + assert_eq!(0, len % self.stride()); + len / self.stride() + } + + /// Iterate over the entire buffer as rows, including all padding + /// + /// Rows will have up to `stride` width, but the last row may be shorter. + #[inline(always)] + #[cfg(feature = "deprecated")] + fn rows_padded(&self) -> slice::Chunks<'_, Pixel> { + self.buf().as_ref().chunks(self.stride()) + } + + #[inline(always)] + #[allow(deprecated)] + fn as_ref(&self) -> ImgRef<'_, Pixel> { + Img { + buf: self.buf.as_ref(), + width: self.width, + height: self.height, + stride: self.stride, + } + } +} + +impl ImgExtMut for Img where Container: AsMut<[Pixel]> { + /// Iterate over the entire buffer as rows, including all padding + /// + /// Rows will have up to `stride` width, but the last row may be shorter. + /// + /// # Panics + /// + /// If stride is 0 + #[cfg(feature = "deprecated")] + fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel> { + let stride = self.stride(); + self.buf_mut().as_mut().chunks_mut(stride) + } + + #[inline(always)] + #[allow(deprecated)] + fn as_mut(&mut self) -> ImgRefMut<'_, Pixel> { + Img { + buf: self.buf.as_mut(), + width: self.width, + height: self.height, + stride: self.stride, + } + } +} + +#[inline] +fn sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize) { + let start = stride * top + left; + let full_strides_end = start + stride * height; + // when left > 0 and height is full, the last line is shorter than the stride + let end = if buf_len >= full_strides_end { + full_strides_end + } else { + debug_assert!(height > 0); + let min_strides_len = full_strides_end + width - stride; + debug_assert!(buf_len >= min_strides_len, "the buffer is too small to fit the subimage"); + // if can't use full buffer, then shrink to min required (last line having exact width) + min_strides_len + }; + (start, end, stride) +} + +impl<'slice, T> ImgRef<'slice, T> { + /// Make a reference for a part of the image, without copying any pixels. + /// + /// # Panics + /// + /// It will panic if `sub_image` is outside of the image area + /// (left + width must be <= container width, etc.) + #[inline] + #[must_use] + #[track_caller] + pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self { + assert!(top + height <= self.height()); + assert!(left + width <= self.width()); + let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf().len()); + let buf = &self.buf()[start..end]; + Self::new_stride(buf, width, height, stride) + } + + #[inline] + /// Iterate over whole rows of pixels as slices + /// + /// # Panics + /// + /// If stride is 0 + /// + /// See also `pixels()` + pub fn rows(&self) -> RowsIter<'slice, T> { + self.rows_buf_internal(self.buf()) + } + + /// Deprecated + /// + /// Note: it iterates **all** pixels in the underlying buffer, not just limited by width/height. + #[deprecated(note = "Size of this buffer is unpredictable. Use .rows() instead")] + #[cfg(feature = "deprecated")] + #[doc(hidden)] + pub fn iter(&self) -> slice::Iter<'slice, T> { + self.buf().iter() + } +} + +impl<'a, T: Clone> ImgRef<'a, T> { + /// Returns a reference to the buffer, width, height. Guarantees that the buffer is contiguous, + /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel. + /// + /// It will create a copy if the buffer isn't contiguous (width != stride). + /// For a more efficient version, see `into_contiguous_buf()` + #[allow(deprecated)] + #[must_use] + pub fn to_contiguous_buf(&self) -> (Cow<'a, [T]>, usize, usize) { + let width = self.width(); + let height = self.height(); + let stride = self.stride(); + if width == stride { + return (Cow::Borrowed(self.buf), width, height); + } + let mut buf = Vec::with_capacity(width * height); + for row in self.rows() { + buf.extend_from_slice(row); + } + (Cow::Owned(buf), width, height) + } +} + +impl<'slice, T> ImgRefMut<'slice, T> { + /// Turn this into immutable reference, and slice a subregion of it + #[inline] + #[allow(deprecated)] + #[must_use] + pub fn sub_image(&'slice self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'slice, T> { + self.as_ref().sub_image(left, top, width, height) + } + + /// Slices this image reference to produce another reference to a subregion of it. + /// + /// Note that mutable borrows are exclusive, so it's not possible to have more than + /// one mutable subimage at a time. + /// + /// ## Panics + /// + /// If the coordinates are out of bounds + #[inline] + #[allow(deprecated)] + #[must_use] + #[track_caller] + pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> { + assert!(top + height <= self.height()); + assert!(left + width <= self.width()); + let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len()); + let buf = &mut self.buf[start..end]; + ImgRefMut::new_stride(buf, width, height, stride) + } + + /// Transforms this image reference to refer to a subregion. + /// + /// This is identical in behavior to [`ImgRefMut::sub_image_mut()`], except that it returns an + /// [`ImgRefMut`] with the same lifetime, rather than a reborrow with a shorter lifetime. + /// + /// ## Panics + /// + /// If the coordinates are out of bounds + #[allow(deprecated)] + #[must_use] + #[track_caller] + pub fn into_sub_image_mut(self, left: usize, top: usize, width: usize, height: usize) -> Self { + assert!(top + height <= self.height()); + assert!(left + width <= self.width()); + let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len()); + let buf = &mut self.buf[start..end]; + ImgRefMut::new_stride(buf, width, height, stride) + } + + /// Make mutable reference immutable + #[inline] + #[must_use] + pub fn as_ref(&self) -> ImgRef<'_, T> { + self.new_buf(self.buf().as_ref()) + } +} + +impl<'slice, T: Copy> ImgRef<'slice, T> { + /// Iterate `width*height` pixels in the `Img`, ignoring padding area + /// + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// + /// # Panics + /// + /// if width is 0 + #[inline] + #[track_caller] + pub fn pixels(&self) -> PixelsIter<'slice, T> { + PixelsIter::new(*self) + } +} + +impl<'slice, T> ImgRef<'slice, T> { + /// Iterate `width*height` pixels in the `Img`, by reference, ignoring padding area + /// + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// + /// # Panics + /// + /// if width is 0 + #[inline] + pub fn pixels_ref(&self) -> PixelsRefIter<'slice, T> { + PixelsRefIter::new(*self) + } +} + +impl ImgRefMut<'_, T> { + /// # Panics + /// + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// + /// if width is 0 + #[inline] + pub fn pixels(&self) -> PixelsIter<'_, T> { + PixelsIter::new(self.as_ref()) + } +} + +impl ImgRefMut<'_, T> { + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// # Panics + /// + /// if width is 0 + #[inline] + pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> { + PixelsIterMut::new(self) + } +} + +impl ImgVec { + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// # Panics + /// + /// if width is 0 + #[inline] + pub fn pixels(&self) -> PixelsIter<'_, T> { + PixelsIter::new(self.as_ref()) + } +} + +impl ImgVec { + /// If you want to iterate in parallel, parallelize `rows()` instead. + /// # Panics + /// + /// if width is 0 + #[inline] + pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> { + PixelsIterMut::new(&mut self.as_mut()) + } +} + +impl ImgRefMut<'_, T> { + /// Iterate over whole rows as slices + /// + /// # Panics + /// + /// if stride is 0 + #[inline] + pub fn rows(&self) -> RowsIter<'_, T> { + self.rows_buf_internal(&self.buf()[..]) + } + + /// Iterate over whole rows as slices + /// + /// # Panics + /// + /// if stride is 0 + #[inline] + #[allow(deprecated)] + pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> { + let stride = self.stride(); + let width = self.width(); + let height = self.height(); + let non_padded = &mut self.buf[0..stride * height + width - stride]; + RowsIterMut { + width, + inner: non_padded.chunks_mut(stride), + } + } +} + +/// Deprecated. Use .`rows()` or .`pixels()` iterators which are more predictable +#[cfg(feature = "deprecated")] +impl IntoIterator for Img where Container: IntoIterator { + type Item = Container::Item; + type IntoIter = Container::IntoIter; + /// Deprecated. Use .`rows()` or .`pixels()` iterators which are more predictable + fn into_iter(self) -> Container::IntoIter { + self.into_buf().into_iter() + } +} + +impl ImgVec { + /// Create a mutable view into a region within the image. See `sub_image()` for read-only views. + /// + /// ## Panics + /// + /// If the coordinates are out of bounds + #[allow(deprecated)] + #[must_use] + #[track_caller] + pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> { + assert!(top + height <= self.height()); + assert!(left + width <= self.width()); + let start = self.stride * top + left; + let min_buf_size = if self.height > 0 { self.stride * height + width - self.stride } else {0}; + let buf = &mut self.buf[start .. start + min_buf_size]; + Img::new_stride(buf, width, height, self.stride) + } + + #[inline] + #[must_use] + /// Make a reference for a part of the image, without copying any pixels. + pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T> { + self.as_ref().sub_image(left, top, width, height) + } + + /// Make a reference to this image to pass it to functions without giving up ownership + /// + /// The reference should be passed by value (`ImgRef`, not `&ImgRef`). + /// + /// If you need a mutable reference, see `as_mut()` and `sub_image_mut()` + #[inline] + #[must_use] + pub fn as_ref(&self) -> ImgRef<'_, T> { + self.new_buf(self.buf().as_ref()) + } + + /// Make a mutable reference to the entire image + /// + /// The reference should be passed by value (`ImgRefMut`, not `&mut ImgRefMut`). + /// + /// See also `sub_image_mut()` and `rows_mut()` + #[inline] + pub fn as_mut(&mut self) -> ImgRefMut<'_, T> { + let width = self.width(); + let height = self.height(); + let stride = self.stride(); + Img::new_stride(self.buf_mut().as_mut(), width, height, stride) + } + + #[deprecated(note = "Size of this buffer may be unpredictable. Use .rows() instead")] + #[cfg(feature = "deprecated")] + #[doc(hidden)] + pub fn iter(&self) -> slice::Iter<'_, T> { + self.buf().iter() + } + + /// Iterate over rows of the image as slices + /// + /// Each slice is guaranteed to be exactly `width` pixels wide. + /// + /// This iterator is a good candidate for parallelization (e.g. rayon's `par_bridge()`) + #[inline] + pub fn rows(&self) -> RowsIter<'_, T> { + self.rows_buf_internal(self.buf()) + } + + /// Iterate over rows of the image as mutable slices + /// + /// Each slice is guaranteed to be exactly `width` pixels wide. + /// + /// This iterator is a good candidate for parallelization (e.g. rayon's `par_bridge()`) + #[inline] + #[allow(deprecated)] + pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> { + let stride = self.stride(); + let width = self.width(); + let height = self.height(); + let non_padded = &mut self.buf[0..stride * height + width - stride]; + RowsIterMut { + width, + inner: non_padded.chunks_mut(stride), + } + } +} + +impl Img { + /// Same as `new()`, except each row is located `stride` number of pixels after the previous one. + /// + /// Stride can be equal to `width` or larger. If it's larger, then pixels between end of previous row and start of the next are considered a padding, and may be ignored. + /// + /// The `Container` is usually a `Vec` or a slice. + /// + /// ## Panics + /// + /// If stride is 0. + #[inline] + #[allow(deprecated)] + #[track_caller] + pub fn new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self { + assert!(stride > 0); + assert!(stride >= width); + debug_assert!(height < u32::MAX as usize); + debug_assert!(width < u32::MAX as usize); + Self { + buf, + width: width as u32, + height: height as u32, + stride, + } + } + + /// Create new image with `Container` (which can be `Vec`, `&[]` or something else) with given `width` and `height` in pixels. + /// + /// Assumes the pixels in container are contiguous, layed out row by row with `width` pixels per row and at least `height` rows. + /// + /// If the container is larger than `width`×`height` pixels, the extra rows are a considered a padding and may be ignored. + #[inline] + pub fn new(buf: Container, width: usize, height: usize) -> Self { + Self::new_stride(buf, width, height, width) + } +} + +impl Img> { + /// Returns the buffer, width, height. Guarantees that the buffer is contiguous, + /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel. + /// + /// Efficiently performs operation in-place. For other containers use `pixels().collect()`. + #[allow(deprecated)] + #[must_use] + pub fn into_contiguous_buf(mut self) -> (Vec, usize, usize) { + let (_, w, h) = self.as_contiguous_buf(); + (self.buf, w, h) + } + + /// Returns a reference to the buffer, width, height. Guarantees that the buffer is contiguous, + /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel. + /// + /// Efficiently performs operation in-place. For other containers use `pixels().collect()`. + #[allow(deprecated)] + #[must_use] + pub fn as_contiguous_buf(&mut self) -> (&[T], usize, usize) { + let width = self.width(); + let height = self.height(); + let stride = self.stride(); + if width != stride { + for row in 1..height { + self.buf.copy_within(row * stride .. row * stride + width, row * width); + } + } + self.buf.truncate(width * height); + (&mut self.buf, width, height) + } +} + +impl Img { + /// A convenience method for creating an image of the same size and stride, but with a new buffer. + #[inline] + #[track_caller] + pub fn map_buf(self, callback: F) -> Img + where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>, F: FnOnce(OldContainer) -> NewContainer { + let width = self.width(); + let height = self.height(); + let stride = self.stride(); + let old_buf_len = self.buf().as_ref().len(); + #[allow(deprecated)] + let new_buf = callback(self.buf); + assert_eq!(old_buf_len, new_buf.as_ref().len()); + Img::new_stride(new_buf, width, height, stride) + } + + /// A convenience method for creating an image of the same size and stride, but with a new buffer. + #[inline] + #[track_caller] + pub fn new_buf(&self, new_buf: NewContainer) -> Img + where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> { + assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len()); + Img::new_stride(new_buf, self.width(), self.height(), self.stride()) + } +} + +impl From>> for Img> { + #[allow(deprecated)] + fn from(img: Img>) -> Self { + Self { + width: img.width, + height: img.height, + stride: img.stride, + buf: img.buf.into_owned(), + } + } +} + +impl From> for Img> { + #[allow(deprecated)] + fn from(img: ImgVec) -> Self { + Img { + width: img.width, + height: img.height, + stride: img.stride, + buf: img.buf.into(), + } + } +} + +impl<'a, T: Clone> From> for Img> { + #[allow(deprecated)] + fn from(img: ImgRef<'a, T>) -> Self { + Img { + buf: img.buf.into(), + width: img.width, + height: img.height, + stride: img.stride, + } + } +} + +impl Img> { + /// Convert underlying buffer to owned (e.g. slice to vec) + /// + /// See also `to_contiguous_buf().0.into_owned()` + #[allow(deprecated)] + #[must_use] + pub fn into_owned(self) -> ImgVec { + match self.buf { + Cow::Borrowed(_) => { + let tmp = self.as_ref(); + let (buf, w, h) = tmp.to_contiguous_buf(); + ImgVec::new(buf.into_owned(), w, h) + }, + Cow::Owned(buf) => Img { + buf, + width: self.width, + height: self.height, + stride: self.stride, + }, + } + } +} + +impl Img where T: ToOwned { + /// Convert underlying buffer to owned (e.g. slice to vec) + /// + /// See also `to_contiguous_buf().0.into_owned()` + #[allow(deprecated)] + pub fn to_owned(&self) -> Img { + Img { + buf: self.buf.to_owned(), + width: self.width, + height: self.height, + stride: self.stride, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::vec; + + mod with_opinionated_container { + use super::*; + + struct IDontDeriveAnything; + + #[test] + fn compiles() { + let _ = Img::new(IDontDeriveAnything, 1, 1); + } + } + + #[test] + fn with_vec() { + let bytes = vec![0u8;20]; + let old = Img::new_stride(bytes, 10,2,10); + let _ = old.new_buf(vec![6u16;20]); + } + + #[test] + fn zero() { + let bytes = vec![0u8]; + let mut img = Img::new_stride(bytes,0,0,1); + let _ = img.sub_image(0,0,0,0); + let _ = img.sub_image_mut(0,0,0,0); + let _ = img.as_ref(); + } + + #[test] + fn zero_width() { + let bytes = vec![0u8]; + let mut img = Img::new_stride(bytes,0,1,1); + let _ = img.sub_image(0,1,0,0); + let _ = img.sub_image_mut(0,0,0,1); + } + + #[test] + fn zero_height() { + let bytes = vec![0u8]; + let mut img = Img::new_stride(bytes,1,0,1); + assert_eq!(0, img.rows().count()); + let _ = img.sub_image(1,0,0,0); + let _ = img.sub_image_mut(0,0,1,0); + } + + #[test] + #[allow(deprecated)] + fn with_slice() { + let bytes = vec![0u8;20]; + let _ = Img::new_stride(bytes.as_slice(), 10,2,10); + let vec = ImgVec::new_stride(bytes, 10,2,10); + + #[cfg(feature = "deprecated")] + for _ in vec.iter() {} + + assert_eq!(2, vec.rows().count()); + for _ in *vec.as_ref().buf() {} + + #[cfg(feature = "deprecated")] + for _ in vec {} + } + + #[test] + fn sub() { + let img = Img::new_stride(vec![1,2,3,4, + 5,6,7,8, + 9], 3, 2, 4); + assert_eq!(img.buf()[img.stride()], 5); + assert_eq!(img.buf()[img.stride() + img.width()-1], 7); + + assert_eq!(img.pixels().count(), img.width() * img.height()); + assert_eq!(img.pixels().sum::(), 24); + + { + let refimg = img.as_ref(); + let refimg2 = refimg; // Test is Copy + + // sub-image with stride hits end of the buffer + let s1 = refimg.sub_image(1, 0, refimg.width()-1, refimg.height()); + let _ = s1.sub_image(1, 0, s1.width()-1, s1.height()); + + let subimg = refimg.sub_image(1, 1, 2, 1); + assert_eq!(subimg.pixels().count(), subimg.width() * subimg.height()); + + assert_eq!(subimg.buf()[0], 6); + assert_eq!(subimg.stride(), refimg2.stride()); + assert!(subimg.stride() * subimg.height() + subimg.width() - subimg.stride() <= subimg.buf().len()); + assert_eq!(refimg.buf()[0], 1); + assert_eq!(1, subimg.rows().count()); + } + + // 3 different methods for constructing mutable sub-images + let mut img_for_mut_1 = img.clone(); + let mut img_for_mut_2 = img.clone(); + let mut img_for_mut_3 = img; + for mut subimg in [ + img_for_mut_1.sub_image_mut(1, 1, 2, 1), + img_for_mut_2.as_mut().sub_image_mut(1, 1, 2, 1), + img_for_mut_3.as_mut().into_sub_image_mut(1, 1, 2, 1), + ] { + assert_eq!(1, subimg.rows().count()); + assert_eq!(1, subimg.rows_mut().count()); + assert_eq!(1, subimg.rows_mut().rev().count()); + assert_eq!(1, subimg.rows_mut().fuse().rev().count()); + assert_eq!(subimg.buf()[0], 6); + } + } + + #[test] + fn rows() { + let img = ImgVec::new_stride(vec![0u8; 10000], 10, 15, 100); + assert_eq!(img.height(), img.rows().count()); + assert_eq!(img.height(), img.rows().rev().count()); + assert_eq!(img.height(), img.rows().fuse().rev().count()); + } + + #[test] + fn mut_pixels() { + for y in 1..15 { + for x in 1..10 { + let mut img = ImgVec::new_stride(vec![0u8; 10000], x, y, 100); + assert_eq!(x*y, img.pixels_mut().count()); + assert_eq!(x*y, img.as_mut().pixels().count()); + assert_eq!(x*y, img.as_mut().pixels_mut().count()); + assert_eq!(x*y, img.as_mut().as_ref().pixels().count()); + } + } + } + + #[test] + fn into_contiguous_buf() { + for in_h in [1, 2, 3, 38, 39, 40, 41].iter().copied() { + for in_w in [1, 2, 3, 120, 121].iter().copied() { + for stride in [in_w, 121, 122, 166, 242, 243].iter().copied() { + let img = ImgVec::new_stride((0..10000).map(|x| x as u8).collect(), in_w, in_h, stride) + .map_buf(|x| x); + let pixels: Vec<_> = img.pixels().collect(); + let (buf, w, h) = img.into_contiguous_buf(); + assert_eq!(pixels, buf); + assert_eq!(in_w*in_h, buf.len()); + assert_eq!(10000, buf.capacity()); + assert_eq!(in_w, w); + assert_eq!(in_h, h); + } + } + } + + let img = ImgVec::new((0..55*33).map(|x| x as u8).collect(), 55, 33); + let pixels: Vec<_> = img.pixels().collect(); + let tmp = img.as_ref(); + let (buf, ..) = tmp.to_contiguous_buf(); + assert_eq!(&pixels[..], &buf[..]); + let (buf, ..) = img.into_contiguous_buf(); + assert_eq!(pixels, buf); + } +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/ops.rs clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/ops.rs --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/ops.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/ops.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,128 @@ +use super::Img; +use alloc::vec::Vec; +use core::ops; + +#[cfg(test)] +use alloc::vec; + +macro_rules! impl_imgref_index { + ($container:ty, $index:ty) => { + impl<'a, Pixel: Copy> ops::Index<($index, $index)> for Img<$container> { + type Output = Pixel; + + /// Read a pixel at `(x,y)` location (e.g. px = `img[(x,y)]`) + /// + /// Coordinates may be outside `width`/`height` if the buffer has enough padding. + /// The x coordinate can't exceed `stride`. + #[inline(always)] + #[cfg_attr(debug_assertions, track_caller)] + fn index(&self, index: ($index, $index)) -> &Self::Output { + let stride = self.stride(); + debug_assert_eq!(stride, stride as $index as usize); + debug_assert!(index.0 < stride as $index); + &self.buf()[(index.1 * (stride as $index) + index.0) as usize] + } + } + }; +} + +macro_rules! impl_imgref_index_mut { + ($container:ty, $index:ty) => { + impl<'a, Pixel: Copy> ops::IndexMut<($index, $index)> for Img<$container> { + /// Write a pixel at `(x,y)` location (e.g. `img[(x,y)] = px`) + /// + /// Coordinates may be outside `width`/`height` if the buffer has enough padding. + /// The x coordinate can't exceed `stride`. + #[inline(always)] + #[cfg_attr(debug_assertions, track_caller)] + fn index_mut(&mut self, index: ($index, $index)) -> &mut Self::Output { + let stride = self.stride(); + debug_assert_eq!(stride, stride as $index as usize); + debug_assert!(index.0 < stride as $index); + &mut self.buf_mut()[(index.1 * (stride as $index) + index.0) as usize] + } + } + }; +} + +impl_imgref_index! {&'a [Pixel], usize} +impl_imgref_index! {&'a [Pixel], u32} +impl_imgref_index! {&'a mut [Pixel], usize} +impl_imgref_index! {&'a mut [Pixel], u32} +impl_imgref_index_mut! {&'a mut [Pixel], usize} +impl_imgref_index_mut! {&'a mut [Pixel], u32} +impl_imgref_index! {Vec, usize} +impl_imgref_index! {Vec, u32} +impl_imgref_index_mut! {Vec, usize} +impl_imgref_index_mut! {Vec, u32} + +#[test] +fn index() { + let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3); + assert_eq!(1, img[(0u32,0u32)]); + assert_eq!(2, img.as_ref()[(1usize,0usize)]); + assert_eq!(3, img.as_ref()[(2u32,0u32)]); + assert_eq!(4, img[(0usize,1usize)]); + assert_eq!(8, img[(1usize,2usize)]); + assert_eq!(5, img.sub_image_mut(1,1,1,1)[(0usize,0usize)]); +} + +macro_rules! impl_imgref_row_index { + ($container:ty) => { + impl<'a, Pixel: Copy> ops::Index for Img<$container> { + type Output = [Pixel]; + + #[inline(always)] + /// Take n-th row as a slice. Same as `.rows().nth(n).unwrap()` + /// + /// Slice length is guaranteed to equal image width. + /// Row must be within image height. + fn index(&self, row: usize) -> &Self::Output { + let stride = self.stride(); + let width = self.width(); + let start = row * stride; + self.buf().get(start .. start + width).unwrap_or_else(|| index_fail(row)) + } + } + }; +} + +macro_rules! impl_imgref_row_index_mut { + ($container:ty) => { + impl<'a, Pixel: Copy> ops::IndexMut for Img<$container> { + #[inline(always)] + /// Take n-th row as a mutable slice. Same as `.rows().nth(n).unwrap()` + /// + /// Slice length is guaranteed to equal image width. + /// Row must be within image height. + fn index_mut(&mut self, row: usize) -> &mut Self::Output { + let stride = self.stride(); + let width = self.width(); + let start = row * stride; + self.buf_mut().get_mut(start .. start + width).unwrap_or_else(|| index_fail(row)) + } + } + }; +} + +impl_imgref_row_index! {&'a [Pixel]} +impl_imgref_row_index! {&'a mut [Pixel]} +impl_imgref_row_index_mut! {&'a mut [Pixel]} +impl_imgref_row_index! {Vec} +impl_imgref_row_index_mut! {Vec} + +#[cold] +fn index_fail(row: usize) -> ! { + panic!("row {row} is out of range") +} + +#[test] +fn index_by_row() { + let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3); + assert_eq!(&[1,2], &img[0]); + assert_eq!(&[4,5], &img[1]); + assert_eq!(&[1,2], &img.as_ref()[0]); + assert_eq!(&[4,5], &img.as_ref()[1]); + assert_eq!(&[1,2], &img.as_mut()[0]); + assert_eq!(&[4,5], &img.as_mut()[1]); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/traits.rs clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/traits.rs --- clamav-1.4.3+dfsg/.cargo/vendor/imgref/src/traits.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/imgref/src/traits.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,150 @@ +use crate::{ImgRef, ImgRefMut, ImgVec}; +use core::hash::{Hash, Hasher}; + +impl Hash for ImgRef<'_, T> { + #[allow(deprecated)] + #[inline] + fn hash(&self, state: &mut H) { + self.width.hash(state); + self.height.hash(state); + for row in self.rows() { + Hash::hash_slice(row, state); + } + } +} + +impl Hash for ImgRefMut<'_, T> { + #[allow(deprecated)] + #[inline] + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +impl Hash for ImgVec { + #[inline(always)] + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +impl<'b, T, U> PartialEq> for ImgRef<'_, T> where T: PartialEq { + #[allow(deprecated)] + #[inline] + fn eq(&self, other: &ImgRef<'b, U>) -> bool { + self.width == other.width && + self.height == other.height && + self.rows().zip(other.rows()).all(|(a,b)| a == b) + } +} + +impl<'b, T, U> PartialEq> for ImgRefMut<'_, T> where T: PartialEq { + #[allow(deprecated)] + #[inline] + fn eq(&self, other: &ImgRefMut<'b, U>) -> bool { + self.as_ref().eq(&other.as_ref()) + } +} + + +impl PartialEq> for ImgVec where T: PartialEq { + #[allow(deprecated)] + #[inline(always)] + fn eq(&self, other: &ImgVec) -> bool { + self.as_ref().eq(&other.as_ref()) + } +} + +impl<'a, T, U> PartialEq> for ImgVec where T: PartialEq { + #[allow(deprecated)] + #[inline(always)] + fn eq(&self, other: &ImgRef<'a, U>) -> bool { + self.as_ref().eq(other) + } +} + +impl PartialEq> for ImgRef<'_, T> where T: PartialEq { + #[allow(deprecated)] + #[inline(always)] + fn eq(&self, other: &ImgVec) -> bool { + self.eq(&other.as_ref()) + } +} + +impl<'b, T, U> PartialEq> for ImgRefMut<'_, T> where T: PartialEq { + #[allow(deprecated)] + #[inline(always)] + fn eq(&self, other: &ImgRef<'b, U>) -> bool { + self.as_ref().eq(other) + } +} + +impl<'b, T, U> PartialEq> for ImgRef<'_, T> where T: PartialEq { + #[allow(deprecated)] + #[inline(always)] + fn eq(&self, other: &ImgRefMut<'b, U>) -> bool { + self.eq(&other.as_ref()) + } +} + +impl Eq for ImgRefMut<'_, T> { +} + +impl Eq for ImgRef<'_, T> { +} + +impl Eq for ImgVec { +} + +#[test] +fn test_eq_hash() { + use alloc::vec; + + #[derive(Debug)] + struct Comparable(u16); + impl PartialEq for Comparable { + fn eq(&self, other: &u8) -> bool { self.0 == u16::from(*other) } + } + + let newtype = ImgVec::new(vec![Comparable(0), Comparable(1), Comparable(2), Comparable(3)], 2, 2); + let mut img1 = ImgVec::new(vec![0u8, 1, 2, 3], 2, 2); + let img_ne = ImgVec::new(vec![0u8, 1, 2, 3], 4, 1); + let img2 = ImgVec::new_stride(vec![0u8, 1, 255, 2, 3, 255], 2, 2, 3); + let mut img3 = ImgVec::new_stride(vec![0u8, 1, 255, 2, 3], 2, 2, 3); + + assert_eq!(newtype, img1); + equiv(&img1, &img2); + equiv(&img2, &img3); + equiv(&img1, &img3); + + assert_ne!(img1, img_ne); + assert_eq!(img1.as_ref(), img2); + assert_eq!(img2, img3.as_ref()); + equiv(&img1.as_ref(), &img3.as_ref()); + equiv(&img1.as_mut(), &img3.as_mut()); + assert_eq!(img2.as_ref(), img3.as_mut()); + + let mut map = HashSet::new(); + img3[(0usize, 0usize)] = 100; + assert_ne!(img1, img3); + assert!(map.insert(img1)); + assert!(map.insert(img3)); + assert!(map.insert(img_ne)); + assert!(!map.insert(img2)); +} + +#[cfg(test)] +use std::collections::HashSet; +#[cfg(test)] +use std::fmt::Debug; + +#[cfg(test)] +fn equiv(a: &A, b: &A) where A: Eq + PartialEq + Hash + Debug { + assert_eq!(a, b); + let mut map = HashSet::new(); + assert!(map.insert(a)); + assert!(!map.insert(b)); + assert!(!map.insert(a)); + assert!(map.remove(b)); + assert!(map.is_empty()); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"Cargo.toml":"1290d383adfdcd24f158a4619afb5547d633c83c0a1ab3b5c1ee0dabe4fb1f36","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.md":"f8b02aa7c20fc0f5bc13de9e9e78899ec8cdbc16c2db880a1d0bc14c25b07542","RELEASES.md":"85d9d9bc78e94df7ce90300bb94099b9ab2696d1b3f6b815c22761522878e679","benches/bench.rs":"3b2900abbc9e8a60af78b0395222ee75e86bc68519a0f38477387d1572eed397","benches/faststring.rs":"5fdd6cdb19d0557ed58f241e809a240cf8939d9e5b87a72d5f127f81ab98380b","build.rs":"558b4d0b9e9b3a44f7e1a2b69f7a7567ea721cd45cb54f4e458e850bf702f35c","src/arbitrary.rs":"bb8bda10f686abe57eef1446d3fc3fc6fb251f95629b28c20e620a4838c43db8","src/equivalent.rs":"2e6ae24ef09a09b917f4e2b0f6288f901878e42f5080f61b1bd1afdcc90aba87","src/lib.rs":"ea2cbe4f6cc2c4a75f42c9fc936503e6bee0f136c60f6811a2a9907ed8886443","src/macros.rs":"80c22f630e7f81e6fa663ca4c9e50cf5f332c8905d72d1338bd16f24eb353c2a","src/map.rs":"2e9cbfa240865cfd6b6b972bdbdb39283e6302dd2d0d72b3c2bfce4414bf5729","src/map/core.rs":"8422cd774c5db7d83cdeb0c5836c10f29caa1bee8d95b0d674b01b32e7ce80d8","src/map/core/raw.rs":"4e5fac4fecccc352268351d8b1f82b345067b5c029bba7e6ab88e8f8bc799c6a","src/mutable_keys.rs":"a919065b59000286eb11c7d46f6896bf0a1d484c9dac5e61d80bb8990c9fbedb","src/rayon/map.rs":"1a508c7c95c5d56113b851f7ce140d62ad541f1c6129352a7ec62d5bea7af4a1","src/rayon/mod.rs":"019e9379ccab57a299ab5b5a2c0efc7561b77a715a5afe8f797c7e8330c6206c","src/rayon/set.rs":"ba00e88e90fb7ab803589f99f24b595d60309e541aae3d01fdde21bff3840194","src/rustc.rs":"fe7a348c5a10a66880cb6c737593fe79d3b6de40f44ba0d7b89204aa95e14a3a","src/serde.rs":"d45ec8fb9c02594ca6f2e9b20764778b2b4193a24a52f1e233160a33efc6e683","src/serde_seq.rs":"c54a52fa607b6ccddda1e76e829778ca304c49b5f434edc5e582a5386c35d662","src/set.rs":"0a57affb623fa6b28df18cc14841e4f076cbd1da5c809635d202f865640af1ee","src/util.rs":"ab712bce71b54cf2763e6010e64bb5944d1d59ce15e2f2beffa7ceed204d6a68","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"1addbc6cbcb1aae5b8bde0fb0e18197d947e8f13244e4ae7ebf97bdda00eafea","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"3c8fb064503e5799b9755d860d137017964a6999a1a11a37440bace9ec06c41b",".github/workflows/ci.yml":"3412a9d9f6b548eec739bd7f0ceab5634cdeb8406dbce4d2c96a1a371c9f393c",".rustfmt.toml":"f1a22634bbffec62822faa208b352d302c19c2f70e29e57613b9df18d7c2fc36","Cargo.toml":"1290d383adfdcd24f158a4619afb5547d633c83c0a1ab3b5c1ee0dabe4fb1f36","Cargo.toml.orig":"8ae88af13ea9a909a5356107f9638eb0c4043c7bd89f27e7224e28a2c6ef58c1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.md":"f8b02aa7c20fc0f5bc13de9e9e78899ec8cdbc16c2db880a1d0bc14c25b07542","RELEASES.md":"85d9d9bc78e94df7ce90300bb94099b9ab2696d1b3f6b815c22761522878e679","benches/bench.rs":"3b2900abbc9e8a60af78b0395222ee75e86bc68519a0f38477387d1572eed397","benches/faststring.rs":"5fdd6cdb19d0557ed58f241e809a240cf8939d9e5b87a72d5f127f81ab98380b","build.rs":"558b4d0b9e9b3a44f7e1a2b69f7a7567ea721cd45cb54f4e458e850bf702f35c","src/arbitrary.rs":"bb8bda10f686abe57eef1446d3fc3fc6fb251f95629b28c20e620a4838c43db8","src/equivalent.rs":"2e6ae24ef09a09b917f4e2b0f6288f901878e42f5080f61b1bd1afdcc90aba87","src/lib.rs":"ea2cbe4f6cc2c4a75f42c9fc936503e6bee0f136c60f6811a2a9907ed8886443","src/macros.rs":"80c22f630e7f81e6fa663ca4c9e50cf5f332c8905d72d1338bd16f24eb353c2a","src/map.rs":"2e9cbfa240865cfd6b6b972bdbdb39283e6302dd2d0d72b3c2bfce4414bf5729","src/map/core.rs":"8422cd774c5db7d83cdeb0c5836c10f29caa1bee8d95b0d674b01b32e7ce80d8","src/map/core/raw.rs":"4e5fac4fecccc352268351d8b1f82b345067b5c029bba7e6ab88e8f8bc799c6a","src/mutable_keys.rs":"a919065b59000286eb11c7d46f6896bf0a1d484c9dac5e61d80bb8990c9fbedb","src/rayon/map.rs":"1a508c7c95c5d56113b851f7ce140d62ad541f1c6129352a7ec62d5bea7af4a1","src/rayon/mod.rs":"019e9379ccab57a299ab5b5a2c0efc7561b77a715a5afe8f797c7e8330c6206c","src/rayon/set.rs":"ba00e88e90fb7ab803589f99f24b595d60309e541aae3d01fdde21bff3840194","src/rustc.rs":"fe7a348c5a10a66880cb6c737593fe79d3b6de40f44ba0d7b89204aa95e14a3a","src/serde.rs":"d45ec8fb9c02594ca6f2e9b20764778b2b4193a24a52f1e233160a33efc6e683","src/serde_seq.rs":"c54a52fa607b6ccddda1e76e829778ca304c49b5f434edc5e582a5386c35d662","src/set.rs":"0a57affb623fa6b28df18cc14841e4f076cbd1da5c809635d202f865640af1ee","src/util.rs":"ab712bce71b54cf2763e6010e64bb5944d1d59ce15e2f2beffa7ceed204d6a68","tests/equivalent_trait.rs":"efe9393069e3cfc893d2c9c0343679979578e437fdb98a10baefeced027ba310","tests/macros_full_path.rs":"c33c86d7341581fdd08e2e6375a4afca507fa603540c54a3b9e51c4cd011cd71","tests/quick.rs":"1addbc6cbcb1aae5b8bde0fb0e18197d947e8f13244e4ae7ebf97bdda00eafea","tests/tests.rs":"f6dbeeb0e2950402b0e66ac52bf74c9e4197d3c5d9c0dde64a7998a2ef74d327"},"package":"bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "861fad73de14b7f08d2dc56ed83607aef621b42e" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,114 @@ +on: + push: + branches: [ master, indexmap-1.x ] + pull_request: + branches: [ master, indexmap-1.x ] + +name: Continuous integration + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - rust: 1.56.0 # MSRV + features: + - rust: stable + features: arbitrary + - rust: stable + features: quickcheck + - rust: stable + features: rayon + - rust: stable + features: rustc-rayon + - rust: stable + features: serde + - rust: stable + features: std + - rust: beta + features: + - rust: nightly + bench: test build benchmarks + - rust: nightly + features: test_low_transition_point + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + - name: Tests + run: | + cargo build --verbose --features "${{ matrix.features }}" + cargo doc --verbose --features "${{ matrix.features }}" + cargo test --verbose --features "${{ matrix.features }}" + cargo test --release --verbose --features "${{ matrix.features }}" + - name: Tests (serde) + if: matrix.features == 'serde' + run: | + cargo test --verbose -p test-serde + - name: Test run benchmarks + if: matrix.bench != '' + run: cargo test -v --benches + + nostd_build: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - rust: 1.56.0 + target: thumbv6m-none-eabi + - rust: stable + target: thumbv6m-none-eabi + + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + target: ${{ matrix.target }} + - name: Tests + run: | + cargo build -vv --target=${{ matrix.target }} + cargo build -v -p test-nostd --target=${{ matrix.target }} + + clippy: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - beta + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + components: clippy + - run: cargo clippy + + miri: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - nightly + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + components: miri + - run: cargo miri test diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.rustfmt.toml clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.rustfmt.toml --- clamav-1.4.3+dfsg/.cargo/vendor/indexmap/.rustfmt.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/indexmap/.rustfmt.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1 @@ +edition = "2021" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/indexmap/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/indexmap/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/indexmap/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/indexmap/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,65 @@ +[package] +name = "indexmap" +edition = "2021" +version = "1.9.3" +documentation = "https://docs.rs/indexmap/" +repository = "https://github.com/bluss/indexmap" +license = "Apache-2.0 OR MIT" +description = "A hash table with consistent order and fast iteration." +keywords = ["hashmap", "no_std"] +categories = ["data-structures", "no-std"] +rust-version = "1.56" + +[lib] +bench = false + +[build-dependencies] +autocfg = "1" + +[dependencies] +arbitrary = { version = "1.0", optional = true, default-features = false } +quickcheck = { version = "1.0", optional = true, default-features = false } +serde = { version = "1.0", optional = true, default-features = false } +rayon = { version = "1.4.1", optional = true } + +# Internal feature, only used when building as part of rustc, +# not part of the stable interface of this crate. +rustc-rayon = { package = "rustc-rayon", version = "0.5", optional = true } + +[dependencies.hashbrown] +version = "0.12" +default-features = false +features = ["raw"] + +[dev-dependencies] +itertools = "0.10" +rand = {version = "0.8", features = ["small_rng"] } +quickcheck = { version = "1.0", default-features = false } +fnv = "1.0" +lazy_static = "1.3" +fxhash = "0.2.1" +serde_derive = "1.0" + +[features] +# Serialization with serde 1.0 +serde-1 = ["serde"] + +# Force the use of `std`, bypassing target detection. +std = [] + +# for testing only, of course +test_low_transition_point = [] +test_debug = [] + +[profile.bench] +debug = true + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[package.metadata.docs.rs] +features = ["arbitrary", "quickcheck", "serde-1", "rayon"] + +[workspace] +members = ["test-nostd", "test-serde"] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/inflate/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"8f0a191c8735dfe7d93dee77ced9ef8f0bf042cadec929dbf1e9ad046a01f76b","LICENSE":"97d06daf5f54a5a5e12776d7f30613b30538c6c7ce4d326731084c27233c6b9b","README.md":"ec8db8252ec5b43d154fd0e013027faf66c3d1154c9c2dd5a1595d78f25d7cea","src/checksum.rs":"431ed529290c0cfab6faaea26fa62a051f0cd209b905acce4648128c6bee1474","src/lib.rs":"7f41f7d6b5ea11312d22a7e3bb20a88ccb1c6dfbd226555aeba4a0c86d389de7","src/reader.rs":"6e6d8b6fe1db5774425a5db47c1aeb730ff32860a577c364f618ceaaddf6eec0","src/utils.rs":"5f5599fe821dff39ff4c3456797a15fa7647765547d9e404e70f807e2ce93d66","src/writer.rs":"fa8f8c2330d6282c138303672982f39073e73bb2e6a4c43007805ebb13aa2528","tests/issue_14.zlib":"2f8841d57ed549cdd1a037ef2f24adaa79d6df84bc71dba1af5958005a8e7fb8","tests/test.rs":"3446fc69c26718134c006027bde175ca238b11e5097753cd0c54cc8843a5f4a9"},"package":"1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/inflate/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/Cargo.toml 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "inflate" -version = "0.4.5" -authors = ["nwin "] -description = "DEFLATE decoding" -keywords = ["deflate", "decompression", "compression", "piston"] -license = "MIT" -repository = "https://github.com/PistonDevelopers/inflate.git" -[dependencies.adler32] -version = "1.0.2" - -[features] -default = [] -unstable = [] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/inflate/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/LICENSE 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 PistonDevelopers - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/README.md clamav-1.4.6+dfsg/.cargo/vendor/inflate/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/README.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -# inflate -A [DEFLATE](http://www.gzip.org/zlib/rfc-deflate.html) decoder written in rust. - -This library provides functionality to decompress data compressed with the DEFLATE algorithm, -both with and without a [zlib](https://tools.ietf.org/html/rfc1950) header/trailer. - -# Examples -The easiest way to get `std::Vec` containing the decompressed bytes is to use either -`inflate::inflate_bytes` or `inflate::inflate_bytes_zlib` (depending on whether -the encoded data has zlib headers and trailers or not). The following example -decodes the DEFLATE encoded string "Hello, world" and prints it: - -```rust -use inflate::inflate_bytes; -use std::str::from_utf8; - -let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -let decoded = inflate_bytes(&encoded).unwrap(); -println!("{}", from_utf8(&decoded).unwrap()); // prints "Hello, world" -``` - -If you need more flexibility, then the library also provides an implementation -of `std::io::Writer` in `inflate::writer`. Below is an example using an -`inflate::writer::InflateWriter` to decode the DEFLATE encoded string "Hello, world": - -```rust -use inflate::InflateWriter; -use std::io::Write; -use std::str::from_utf8; - -let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -let mut decoder = InflateWriter::new(Vec::new()); -decoder.write(&encoded).unwrap(); -let decoded = decoder.finish().unwrap(); -println!("{}", from_utf8(&decoded).unwrap()); // prints "Hello, world" -``` - -Finally, if you need even more flexibility, or if you only want to depend on -`core`, you can use the `inflate::InflateStream` API. The below example -decodes an array of DEFLATE encoded bytes: - -```rust -use inflate::InflateStream; - -let data = [0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00]; -let mut inflater = InflateStream::new(); -let mut out = Vec::::new(); -let mut n = 0; -while n < data.len() { - let res = inflater.update(&data[n..]); - if let Ok((num_bytes_read, result)) = res { - n += num_bytes_read; - out.extend(result.iter().cloned()); - } else { - res.unwrap(); - } -} -``` diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/checksum.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/checksum.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/checksum.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/checksum.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -use adler32::RollingAdler32; - -pub fn adler32_from_bytes(bytes: &[u8; 4]) -> u32 { - (bytes[3] as u32) | ((bytes[2] as u32) << 8) | - ((bytes[1] as u32) << 16) | ((bytes[0] as u32) << 24) -} - -/// Whether we should validate the checksum, and what type of checksum it is. -pub enum ChecksumType { - /// No validation. - /// - /// For raw deflate streams or when we don't bother checking. - None, - /// Adler32 - /// - /// Used in the zlib format. - Adler32(RollingAdler32), -} - -pub struct Checksum { - checksum_type: ChecksumType, -} - -impl Checksum { - #[inline] - pub fn none() -> Checksum { - Checksum::new(ChecksumType::None) - } - - #[inline] - pub fn is_none(&self) -> bool { - match self.checksum_type { - ChecksumType::None => true, - _ => false, - } - } - - #[inline] - pub fn zlib() -> Checksum { - Checksum::new(ChecksumType::Adler32(RollingAdler32::new())) - } - - pub fn new(checksum_type: ChecksumType) -> Checksum { - Checksum { - checksum_type: checksum_type, - } - } - - #[inline] - pub fn update(&mut self, bytes: &[u8]) { - match self.checksum_type { - ChecksumType::None => (), - ChecksumType::Adler32(ref mut c) => { - c.update_buffer(bytes); - } - } - } - - pub fn check(&self, expected: u32) -> Result<(), String> { - match self.checksum_type { - ChecksumType::None => Ok(()), - ChecksumType::Adler32(ref c) => { - if c.hash() == expected { - Ok(()) - } else { - Err("Checksum mismatch!".to_owned()) - } - }, - } - - } - - #[inline] - pub fn current_value(&self) -> u32 { - match self.checksum_type { - ChecksumType::Adler32(ref c) => c.hash(), - _ => 0, - } - } - -} - -#[cfg(test)] -mod test { - use super::adler32_from_bytes; - - #[test] - fn adler32() { - let bytes = [0x00, 0x00, 0x01, 0x0b]; - assert_eq!(adler32_from_bytes(&bytes), 267); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/lib.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1039 +0,0 @@ -// Copyright 2014-2015 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A [DEFLATE](http://www.gzip.org/zlib/rfc-deflate.html) decoder written in rust. -//! -//! This library provides functionality to decompress data compressed with the DEFLATE algorithm, -//! both with and without a [zlib](https://tools.ietf.org/html/rfc1950) header/trailer. -//! -//! # Examples -//! The easiest way to get `std::Vec` containing the decompressed bytes is to use either -//! `inflate::inflate_bytes` or `inflate::inflate_bytes_zlib` (depending on whether -//! the encoded data has zlib headers and trailers or not). The following example -//! decodes the DEFLATE encoded string "Hello, world" and prints it: -//! -//! ```rust -//! use inflate::inflate_bytes; -//! use std::str::from_utf8; -//! -//! let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -//! let decoded = inflate_bytes(&encoded).unwrap(); -//! println!("{}", from_utf8(&decoded).unwrap()); // prints "Hello, world" -//! ``` -//! -//! If you need more flexibility, then the library also provides an implementation -//! of `std::io::Writer` in `inflate::writer`. Below is an example using an -//! `inflate::writer::InflateWriter` to decode the DEFLATE encoded string "Hello, world": -//! -//! ```rust -//! use inflate::InflateWriter; -//! use std::io::Write; -//! use std::str::from_utf8; -//! -//! let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -//! let mut decoder = InflateWriter::new(Vec::new()); -//! decoder.write(&encoded).unwrap(); -//! let decoded = decoder.finish().unwrap(); -//! println!("{}", from_utf8(&decoded).unwrap()); // prints "Hello, world" -//! ``` -//! -//! Finally, if you need even more flexibility, or if you only want to depend on -//! `core`, you can use the `inflate::InflateStream` API. The below example -//! decodes an array of DEFLATE encoded bytes: -//! -//! ```rust -//! use inflate::InflateStream; -//! -//! let data = [0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00]; -//! let mut inflater = InflateStream::new(); -//! let mut out = Vec::::new(); -//! let mut n = 0; -//! while n < data.len() { -//! let res = inflater.update(&data[n..]); -//! if let Ok((num_bytes_read, result)) = res { -//! n += num_bytes_read; -//! out.extend(result.iter().cloned()); -//! } else { -//! res.unwrap(); -//! } -//! } -//! ``` - -extern crate adler32; - -use std::cmp; -use std::slice; - -mod checksum; -use checksum::{Checksum, adler32_from_bytes}; - -mod writer; -pub use self::writer::{InflateWriter}; - -mod utils; -pub use self::utils::{inflate_bytes, inflate_bytes_zlib, inflate_bytes_zlib_no_checksum}; - -mod reader; -pub use self::reader::{DeflateDecoder, DeflateDecoderBuf}; - -static BIT_REV_U8: [u8; 256] = [ - 0b0000_0000, 0b1000_0000, 0b0100_0000, 0b1100_0000, - 0b0010_0000, 0b1010_0000, 0b0110_0000, 0b1110_0000, - 0b0001_0000, 0b1001_0000, 0b0101_0000, 0b1101_0000, - 0b0011_0000, 0b1011_0000, 0b0111_0000, 0b1111_0000, - - 0b0000_1000, 0b1000_1000, 0b0100_1000, 0b1100_1000, - 0b0010_1000, 0b1010_1000, 0b0110_1000, 0b1110_1000, - 0b0001_1000, 0b1001_1000, 0b0101_1000, 0b1101_1000, - 0b0011_1000, 0b1011_1000, 0b0111_1000, 0b1111_1000, - - 0b0000_0100, 0b1000_0100, 0b0100_0100, 0b1100_0100, - 0b0010_0100, 0b1010_0100, 0b0110_0100, 0b1110_0100, - 0b0001_0100, 0b1001_0100, 0b0101_0100, 0b1101_0100, - 0b0011_0100, 0b1011_0100, 0b0111_0100, 0b1111_0100, - - 0b0000_1100, 0b1000_1100, 0b0100_1100, 0b1100_1100, - 0b0010_1100, 0b1010_1100, 0b0110_1100, 0b1110_1100, - 0b0001_1100, 0b1001_1100, 0b0101_1100, 0b1101_1100, - 0b0011_1100, 0b1011_1100, 0b0111_1100, 0b1111_1100, - - - 0b0000_0010, 0b1000_0010, 0b0100_0010, 0b1100_0010, - 0b0010_0010, 0b1010_0010, 0b0110_0010, 0b1110_0010, - 0b0001_0010, 0b1001_0010, 0b0101_0010, 0b1101_0010, - 0b0011_0010, 0b1011_0010, 0b0111_0010, 0b1111_0010, - - 0b0000_1010, 0b1000_1010, 0b0100_1010, 0b1100_1010, - 0b0010_1010, 0b1010_1010, 0b0110_1010, 0b1110_1010, - 0b0001_1010, 0b1001_1010, 0b0101_1010, 0b1101_1010, - 0b0011_1010, 0b1011_1010, 0b0111_1010, 0b1111_1010, - - 0b0000_0110, 0b1000_0110, 0b0100_0110, 0b1100_0110, - 0b0010_0110, 0b1010_0110, 0b0110_0110, 0b1110_0110, - 0b0001_0110, 0b1001_0110, 0b0101_0110, 0b1101_0110, - 0b0011_0110, 0b1011_0110, 0b0111_0110, 0b1111_0110, - - 0b0000_1110, 0b1000_1110, 0b0100_1110, 0b1100_1110, - 0b0010_1110, 0b1010_1110, 0b0110_1110, 0b1110_1110, - 0b0001_1110, 0b1001_1110, 0b0101_1110, 0b1101_1110, - 0b0011_1110, 0b1011_1110, 0b0111_1110, 0b1111_1110, - - - 0b0000_0001, 0b1000_0001, 0b0100_0001, 0b1100_0001, - 0b0010_0001, 0b1010_0001, 0b0110_0001, 0b1110_0001, - 0b0001_0001, 0b1001_0001, 0b0101_0001, 0b1101_0001, - 0b0011_0001, 0b1011_0001, 0b0111_0001, 0b1111_0001, - - 0b0000_1001, 0b1000_1001, 0b0100_1001, 0b1100_1001, - 0b0010_1001, 0b1010_1001, 0b0110_1001, 0b1110_1001, - 0b0001_1001, 0b1001_1001, 0b0101_1001, 0b1101_1001, - 0b0011_1001, 0b1011_1001, 0b0111_1001, 0b1111_1001, - - 0b0000_0101, 0b1000_0101, 0b0100_0101, 0b1100_0101, - 0b0010_0101, 0b1010_0101, 0b0110_0101, 0b1110_0101, - 0b0001_0101, 0b1001_0101, 0b0101_0101, 0b1101_0101, - 0b0011_0101, 0b1011_0101, 0b0111_0101, 0b1111_0101, - - 0b0000_1101, 0b1000_1101, 0b0100_1101, 0b1100_1101, - 0b0010_1101, 0b1010_1101, 0b0110_1101, 0b1110_1101, - 0b0001_1101, 0b1001_1101, 0b0101_1101, 0b1101_1101, - 0b0011_1101, 0b1011_1101, 0b0111_1101, 0b1111_1101, - - - 0b0000_0011, 0b1000_0011, 0b0100_0011, 0b1100_0011, - 0b0010_0011, 0b1010_0011, 0b0110_0011, 0b1110_0011, - 0b0001_0011, 0b1001_0011, 0b0101_0011, 0b1101_0011, - 0b0011_0011, 0b1011_0011, 0b0111_0011, 0b1111_0011, - - 0b0000_1011, 0b1000_1011, 0b0100_1011, 0b1100_1011, - 0b0010_1011, 0b1010_1011, 0b0110_1011, 0b1110_1011, - 0b0001_1011, 0b1001_1011, 0b0101_1011, 0b1101_1011, - 0b0011_1011, 0b1011_1011, 0b0111_1011, 0b1111_1011, - - 0b0000_0111, 0b1000_0111, 0b0100_0111, 0b1100_0111, - 0b0010_0111, 0b1010_0111, 0b0110_0111, 0b1110_0111, - 0b0001_0111, 0b1001_0111, 0b0101_0111, 0b1101_0111, - 0b0011_0111, 0b1011_0111, 0b0111_0111, 0b1111_0111, - - 0b0000_1111, 0b1000_1111, 0b0100_1111, 0b1100_1111, - 0b0010_1111, 0b1010_1111, 0b0110_1111, 0b1110_1111, - 0b0001_1111, 0b1001_1111, 0b0101_1111, 0b1101_1111, - 0b0011_1111, 0b1011_1111, 0b0111_1111, 0b1111_1111 -]; - -#[derive(Clone, Copy)] -struct BitState { - n: u8, - v: u32, -} - -#[derive(Clone)] -struct BitStream<'a> { - bytes: slice::Iter<'a, u8>, - used: usize, - state: BitState, -} - -#[cfg(debug)] -macro_rules! debug { ($($x:tt)*) => (println!($($x)*)) } -#[cfg(not(debug))] -macro_rules! debug { ($($x:tt)*) => (()) } - -impl<'a> BitStream<'a> { - fn new(bytes: &'a [u8], state: BitState) -> BitStream<'a> { - BitStream { - bytes: bytes.iter(), - used: 0, - state: state, - } - } - - fn use_byte(&mut self) -> bool { - match self.bytes.next() { - Some(&b) => { - self.state.v |= (b as u32) << self.state.n; - self.state.n += 8; - self.used += 1; - true - } - None => false, - } - } - - fn need(&mut self, n: u8) -> bool { - if self.state.n < n { - if !self.use_byte() { - return false; - } - if n > 8 && self.state.n < n { - assert!(n <= 16); - if !self.use_byte() { - return false; - } - } - } - true - } - - fn take16(&mut self, n: u8) -> Option { - if self.need(n) { - self.state.n -= n; - let v = self.state.v & ((1 << n) - 1); - self.state.v >>= n; - Some(v as u16) - } else { - None - } - } - - fn take(&mut self, n: u8) -> Option { - assert!(n <= 8); - self.take16(n).map(|v: u16| v as u8) - } - - fn fill(&mut self) -> BitState { - while self.state.n + 8 <= 32 && self.use_byte() {} - self.state - } - - fn align_byte(&mut self) { - if self.state.n > 0 { - let n = self.state.n % 8; - self.take(n); - } - } - - fn trailing_bytes(&mut self) -> (u8, [u8; 4]) { - let mut len = 0; - let mut bytes = [0; 4]; - self.align_byte(); - while self.state.n >= 8 { - bytes[len as usize] = self.state.v as u8; - len += 1; - self.state.n -= 8; - self.state.v >>= 8; - } - (len, bytes) - } -} - -/// Generate huffman codes from the given set of lengths and run `$cb` on them except the first -/// code for each length. -/// -/// See also the [deflate specification](http://www.gzip.org/zlib/rfc-deflate.html#huffman) -/// for an explanation of the algorithm. -macro_rules! with_codes (($clens:expr, $max_bits:expr => $code_ty:ty, $cb:expr) => ({ - // Count the number of codes for each bit length. - let mut bl_count = [0 as $code_ty; ($max_bits+1)]; - for &bits in $clens.iter() { - if bits != 0 { - // This should be safe from overflow as the number of lengths read from the input - // is bounded by the number of bits the number of lengths is represented by in the - // deflate compressed data. - bl_count[bits as usize] += 1; - } - } - - // Compute the first code value for each bit length. - let mut next_code = [0 as $code_ty; ($max_bits+1)]; - let mut code = 0 as $code_ty; - // TODO use range_inclusive as soon as it is stable - //for bits in range_inclusive(1, $max_bits) { - for bits in 1..$max_bits + 1 { - code = try!( - code.checked_add(bl_count[bits as usize - 1]) - .ok_or_else(|| "Error generating huffman codes: Invalid set of code lengths") - ) << 1; - next_code[bits as usize] = code; - } - - // Compute the rest of the codes - for (i, &bits) in $clens.iter().enumerate() { - if bits != 0 { - let code = next_code[bits as usize]; - // If there is an overflow here, the given set of code lengths won't allow enough - // unique codes to be generated. - let new_code = try!( - code.checked_add(1) - .ok_or_else(|| "Error generating huffman codes: Invalid set of code lengths!") - ); - next_code[bits as usize] = new_code; - match $cb(i as $code_ty, code, bits) { - Ok(()) => (), - Err(err) => return Err(err) - } - } - } -})); - -struct CodeLengthReader { - patterns: Box<[u8; 128]>, - clens: Box<[u8; 19]>, - result: Vec, - num_lit: u16, - num_dist: u8, -} - -impl CodeLengthReader { - fn new(clens: Box<[u8; 19]>, num_lit: u16, num_dist: u8) -> Result { - // Fill in the 7-bit patterns that match each code. - let mut patterns = Box::new([0xffu8; 128]); - with_codes!(clens, 7 => u8, |i: u8, code: u8, bits| -> _ { - /*let base = match BIT_REV_U8.get((code << (8 - bits)) as usize) { - Some(&base) => base, - None => return Err("invalid length code".to_owned()) - }*/ - let base = BIT_REV_U8[(code << (8 - bits)) as usize]; - for rest in 0u8 .. 1u8 << (7 - bits) { - patterns[(base | (rest << bits)) as usize] = i; - } - Ok(()) - }); - - Ok(CodeLengthReader { - patterns: patterns, - clens: clens, - result: Vec::with_capacity(num_lit as usize + num_dist as usize), - num_lit: num_lit, - num_dist: num_dist, - }) - } - - fn read(&mut self, stream: &mut BitStream) -> Result { - let total_len = self.num_lit as usize + self.num_dist as usize; - while self.result.len() < total_len { - if !stream.need(7) { - return Ok(false); - } - let save = stream.clone(); - macro_rules! take (($n:expr) => (match stream.take($n) { - Some(v) => v, - None => { - *stream = save; - return Ok(false); - } - })); - let code = self.patterns[(stream.state.v & 0x7f) as usize]; - stream.take(match self.clens.get(code as usize) { - Some(&len) => len, - None => return Err("invalid length code".to_owned()), - }); - match code { - 0...15 => self.result.push(code), - 16 => { - let last = match self.result.last() { - Some(&v) => v, - // 16 appeared before anything else - None => return Err("invalid length code".to_owned()), - }; - for _ in 0..3 + take!(2) { - self.result.push(last); - } - } - 17 => { - for _ in 0..3 + take!(3) { - self.result.push(0); - } - } - 18 => { - for _ in 0..11 + take!(7) { - self.result.push(0); - } - } - _ => unreachable!(), - } - } - Ok(true) - } - - fn to_lit_and_dist(&self) -> Result<(DynHuffman16, DynHuffman16), String> { - let num_lit = self.num_lit as usize; - let lit = try!(DynHuffman16::new(&self.result[..num_lit])); - let dist = try!(DynHuffman16::new(&self.result[num_lit..])); - Ok((lit, dist)) - } -} - -struct Trie8bit { - data: [T; 16], - children: [Option>; 16], -} - -struct DynHuffman16 { - patterns: Box<[u16; 256]>, - rest: Vec>, -} - -impl DynHuffman16 { - fn new(clens: &[u8]) -> Result { - // Fill in the 8-bit patterns that match each code. - // Longer patterns go into the trie. - let mut patterns = Box::new([0xffffu16; 256]); - let mut rest = Vec::new(); - with_codes!(clens, 15 => u16, |i: u16, code: u16, bits: u8| -> _ { - let entry = i | ((bits as u16) << 12); - if bits <= 8 { - let base = match BIT_REV_U8.get((code << (8 - bits)) as usize) { - Some(&v) => v, - None => return Err("invalid length code".to_owned()) - }; - for rest in 0u8 .. 1 << (8 - bits) { - patterns[(base | (rest << (bits & 7))) as usize] = entry; - } - } else { - let low = match BIT_REV_U8.get((code >> (bits - 8)) as usize) { - Some(&v) => v, - None => return Err("invalid length code".to_owned()) - }; - let high = BIT_REV_U8[((code << (16 - bits)) & 0xff) as usize]; - let (min_bits, idx) = if patterns[low as usize] != 0xffff { - let bits_prev = (patterns[low as usize] >> 12) as u8; - (cmp::min(bits_prev, bits), patterns[low as usize] & 0x7ff) - } else { - rest.push(Trie8bit { - data: [0xffff; 16], - children: [ - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None - ] - }); - (bits, (rest.len() - 1) as u16) - }; - patterns[low as usize] = idx | 0x800 | ((min_bits as u16) << 12); - let trie_entry = match rest.get_mut(idx as usize) { - Some(v) => v, - None => return Err("invalid huffman code".to_owned()) - }; - if bits <= 12 { - for rest in 0u8 .. 1 << (12 - bits) { - trie_entry.data[(high | (rest << (bits - 8))) as usize] = entry; - } - } else { - let child = &mut trie_entry.children[(high & 0xf) as usize]; - if child.is_none() { - *child = Some(Box::new([0xffff; 16])); - } - let child = &mut **child.as_mut().unwrap(); - let high_top = high >> 4; - for rest in 0u8 .. 1 << (16 - bits) { - child[(high_top | (rest << (bits - 12))) as usize] = entry; - } - } - } - Ok(()) - }); - debug!("=== DYN HUFFMAN ==="); - for _i in 0..256 { - debug!("{:08b} {:04x}", _i, patterns[BIT_REV_U8[_i] as usize]); - } - debug!("==================="); - Ok(DynHuffman16 { - patterns: patterns, - rest: rest, - }) - } - - fn read<'a>(&self, stream: &mut BitStream<'a>) -> Result, u16)>, String> { - let has8 = stream.need(8); - let entry = self.patterns[(stream.state.v & 0xff) as usize]; - let bits = (entry >> 12) as u8; - - Ok(if !has8 { - if bits <= stream.state.n { - let save = stream.clone(); - stream.state.n -= bits; - stream.state.v >>= bits; - Some((save, entry & 0xfff)) - } else { - None - } - } else if bits <= 8 { - let save = stream.clone(); - stream.state.n -= bits; - stream.state.v >>= bits; - Some((save, entry & 0xfff)) - } else { - let has16 = stream.need(16); - let trie = match self.rest.get((entry & 0x7ff) as usize) { - Some(trie) => trie, - None => return Err("invalid entry in stream".to_owned()), - }; - let idx = stream.state.v >> 8; - let trie_entry = match trie.children[(idx & 0xf) as usize] { - Some(ref child) => child[((idx >> 4) & 0xf) as usize], - None => trie.data[(idx & 0xf) as usize], - }; - let trie_bits = (trie_entry >> 12) as u8; - if has16 || trie_bits <= stream.state.n { - let save = stream.clone(); - stream.state.n -= trie_bits; - stream.state.v >>= trie_bits; - Some((save, trie_entry & 0xfff)) - } else { - None - } - }) - } -} - -enum State { - ZlibMethodAndFlags, // CMF - ZlibFlags(/* CMF */ u8), // FLG, - Bits(BitsNext, BitState), - LenDist((BitsNext, BitState), /* len */ u16, /* dist */ u16), - Uncompressed(/* len */ u16), - CheckCRC(/* len */ u8, /* bytes */ [u8; 4]), - Finished -} - -use self::State::*; - -enum BitsNext { - BlockHeader, - BlockUncompressedLen, - BlockUncompressedNlen(/* len */ u16), - BlockDynHlit, - BlockDynHdist(/* hlit */ u8), - BlockDynHclen(/* hlit */ u8, /* hdist */ u8), - BlockDynClenCodeLengths(/* hlit */ u8, /* hdist */ u8, /* hclen */ u8, /* idx */ u8, /* clens */ Box<[u8; 19]>), - BlockDynCodeLengths(CodeLengthReader), - BlockDyn(/* lit/len */ DynHuffman16, /* dist */ DynHuffman16, /* prev_len */ u16) -} - -use self::BitsNext::*; - -pub struct InflateStream { - buffer: Vec, - pos: u16, - state: Option, - final_block: bool, - checksum: Checksum, - read_checksum: Option, -} - -impl InflateStream { - #[allow(dead_code)] - /// Create a new stream for decoding raw deflate encoded data. - pub fn new() -> InflateStream { - let state = Bits(BlockHeader, BitState { n: 0, v: 0 }); - let buffer = Vec::with_capacity(32 * 1024); - InflateStream::with_state_and_buffer(state, buffer, Checksum::none()) - } - - /// Create a new stream for decoding deflate encoded data with a zlib header and footer - pub fn from_zlib() -> InflateStream { - InflateStream::with_state_and_buffer(ZlibMethodAndFlags, Vec::new(), Checksum::zlib()) - } - - /// Create a new stream for decoding deflate encoded data with a zlib header and footer - /// - /// This version creates a decoder that does not checksum the data to validate it with the - /// checksum provided with the zlib wrapper. - pub fn from_zlib_no_checksum() -> InflateStream { - InflateStream::with_state_and_buffer(ZlibMethodAndFlags, Vec::new(), Checksum::none()) - } - - pub fn reset(&mut self) { - self.buffer.clear(); - self.pos = 0; - self.state = Some(Bits(BlockHeader, BitState { n: 0, v: 0 })); - self.final_block = false; - } - - pub fn reset_to_zlib(&mut self) { - self.reset(); - self.state = Some(ZlibMethodAndFlags); - } - - fn with_state_and_buffer(state: State, buffer: Vec, checksum: Checksum) - -> InflateStream { - InflateStream { - buffer: buffer, - pos: 0, - state: Some(state), - final_block: false, - checksum: checksum, - read_checksum: None, - } - } - - fn run_len_dist(&mut self, len: u16, dist: u16) -> Result, String> { - debug!("RLE -{}; {} (cap={} len={})", dist, len, - self.buffer.capacity(), self.buffer.len()); - if dist < 1 { - return Err("invalid run length in stream".to_owned()); - } - // `buffer_size` is used for validating `unsafe` below, handle with care - let buffer_size = self.buffer.capacity() as u16; - let len = if self.pos < dist { - // Handle copying from ahead, until we hit the end reading. - let pos_end = self.pos + len; - let (pos_end, left) = if pos_end < dist { - (pos_end, 0) - } else { - (dist, pos_end - dist) - }; - if dist > buffer_size { - return Err("run length distance is bigger than the window size".to_owned()); - } - let forward = buffer_size - dist; - if pos_end + forward > self.buffer.len() as u16 { - return Err("invalid run length in stream".to_owned()); - } - - for i in self.pos as usize..pos_end as usize { - self.buffer[i] = self.buffer[i + forward as usize]; - } - self.pos = pos_end; - left - } else { - len - }; - // Handle copying from before, until we hit the end writing. - let pos_end = self.pos + len; - let (pos_end, left) = if pos_end <= buffer_size { - (pos_end, None) - } else { - (buffer_size, Some(pos_end - buffer_size)) - }; - - if self.pos < dist && pos_end > self.pos { - return Err("invalid run length in stream".to_owned()); - } - - if self.buffer.len() < pos_end as usize { - // ensure the buffer length will not exceed the amount of allocated memory - assert!(pos_end <= buffer_size); - // ensure that the uninitialized chunk of memory will be fully overwritten - assert!(self.pos as usize <= self.buffer.len()); - unsafe { - self.buffer.set_len(pos_end as usize); - } - } - assert!(dist > 0); // validation against reading uninitialized memory - for i in self.pos as usize..pos_end as usize { - self.buffer[i] = self.buffer[i - dist as usize]; - } - self.pos = pos_end; - Ok(left) - } - - fn next_state(&mut self, data: &[u8]) -> Result { - macro_rules! ok_bytes (($n:expr, $state:expr) => ({ - self.state = Some($state); - Ok($n) - })); - let debug_byte = |_i, _b| debug!("[{:04x}] {:02x}", _i, _b); - macro_rules! push_or (($b:expr, $ret:expr) => (if self.pos < self.buffer.capacity() as u16 { - let b = $b; - debug_byte(self.pos, b); - if (self.pos as usize) < self.buffer.len() { - self.buffer[self.pos as usize] = b; - } else { - assert_eq!(self.pos as usize, self.buffer.len()); - self.buffer.push(b); - } - self.pos += 1; - } else { - return $ret; - })); - macro_rules! run_len_dist (($len:expr, $dist:expr => ($bytes:expr, $next:expr, $state:expr)) => ({ - let dist = $dist; - let left = try!(self.run_len_dist($len, dist)); - if let Some(len) = left { - return ok_bytes!($bytes, LenDist(($next, $state), len, dist)); - } - })); - match self.state.take().unwrap() { - ZlibMethodAndFlags => { - let b = match data.get(0) { - Some(&x) => x, - None => { - self.state = Some(ZlibMethodAndFlags); - return Ok(0); - } - }; - let (method, info) = (b & 0xF, b >> 4); - debug!("ZLIB CM=0x{:x} CINFO=0x{:x}", method, info); - - // CM = 8 (DEFLATE) is the only method defined by the ZLIB specification. - match method { - 8 => {/* DEFLATE */} - _ => return Err(format!("unknown ZLIB method CM=0x{:x}", method)) - } - - if info > 7 { - return Err(format!("invalid ZLIB info CINFO=0x{:x}", info)); - } - - self.buffer = Vec::with_capacity(1 << (8 + info)); - - ok_bytes!(1, ZlibFlags(b)) - } - ZlibFlags(cmf) => { - let b = match data.get(0) { - Some(&x) => x, - None => { - self.state = Some(ZlibFlags(cmf)); - return Ok(0); - } - }; - let (_check, dict, _level) = (b & 0x1F, (b & 0x20) != 0, b >> 6); - debug!("ZLIB FCHECK=0x{:x} FDICT={} FLEVEL=0x{:x}", _check, dict, _level); - - if (((cmf as u16) << 8) | b as u16) % 31 != 0 { - return Err(format!("invalid ZLIB checksum CMF=0x{:x} FLG=0x{:x}", cmf, b)); - } - - if dict { - return Err("unimplemented ZLIB FDICT=1".into()); - } - - ok_bytes!(1, Bits(BlockHeader, BitState { n: 0, v: 0 })) - } - Bits(next, state) => { - let mut stream = BitStream::new(data, state); - macro_rules! ok_state (($state:expr) => ({self.state = Some($state); Ok(stream.used)})); - macro_rules! ok (($next:expr) => (ok_state!(Bits($next, stream.fill())))); - macro_rules! take ( - ($n:expr => $next:expr) => (match stream.take($n) { - Some(v) => v, - None => return ok!($next) - }); - ($n:expr) => (take!($n => next)) - ); - macro_rules! take16 ( - ($n:expr => $next:expr) => (match stream.take16($n) { - Some(v) => v, - None => return ok!($next) - }); - ($n:expr) => (take16!($n => next)) - ); - macro_rules! len_dist ( - ($len:expr, $code:expr, $bits:expr => $next_early:expr, $next:expr) => ({ - let dist = 1 + if $bits == 0 { 0 } else { // new_base - 2 << $bits - } + (($code as u16 - if $bits == 0 { 0 } else { // old_base - $bits * 2 + 2 - }) << $bits) + take16!($bits => $next_early) as u16; - run_len_dist!($len, dist => (stream.used, $next, stream.state)); - }); - ($len:expr, $code:expr, $bits:expr) => ( - len_dist!($len, $code, $bits => next, next) - ) - ); - match next { - BlockHeader => { - if self.final_block { - let (len, bytes) = stream.trailing_bytes(); - return ok_state!(CheckCRC(len, bytes)); - } - let h = take!(3); - let (final_, block_type) = ((h & 1) != 0, (h >> 1) & 0b11); - - self.final_block = final_; - - match block_type { - 0 => { - // Skip to the next byte for an uncompressed block. - stream.align_byte(); - ok!(BlockUncompressedLen) - } - 1 => { - // Unwrap is safe because the data is valid. - let lit = DynHuffman16::new(&[ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 0-15 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 16-31 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 32-47 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 48-63 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 64-79 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 80-95 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 96-101 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 112-127 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128-143 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 144-159 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 160-175 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 176-191 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 192-207 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 208-223 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 224-239 - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 240-255 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 256-271 - 7, 7, 7, 7, 7, 7, 7, 7, // 272-279 - 8, 8, 8, 8, 8, 8, 8, 8, // 280-287 - ]).unwrap(); - let dist = DynHuffman16::new(&[ - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5 - ]).unwrap(); - ok!(BlockDyn(lit, dist, 0)) - } - 2 => ok!(BlockDynHlit), - _ => { - Err(format!("unimplemented DEFLATE block type 0b{:?}", - block_type)) - } - } - } - BlockUncompressedLen => { - let len = take16!(16); - ok_state!(Bits(BlockUncompressedNlen(len), stream.state)) - } - BlockUncompressedNlen(len) => { - let nlen = take16!(16); - assert_eq!(stream.state.n, 0); - if !len != nlen { - return Err(format!("invalid uncompressed block len: LEN: {:04x} NLEN: {:04x}", len, nlen)); - } - ok_state!(Uncompressed(len)) - } - BlockDynHlit => ok!(BlockDynHdist(take!(5) + 1)), - BlockDynHdist(hlit) => ok!(BlockDynHclen(hlit, take!(5) + 1)), - BlockDynHclen(hlit, hdist) => { - ok!(BlockDynClenCodeLengths(hlit, hdist, take!(4) + 4, 0, Box::new([0; 19]))) - } - BlockDynClenCodeLengths(hlit, hdist, hclen, i, mut clens) => { - let v = - match stream.take(3) { - Some(v) => v, - None => return ok!(BlockDynClenCodeLengths(hlit, hdist, hclen, i, clens)), - }; - clens[[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15][i as usize]] = v; - if i < hclen - 1 { - ok!(BlockDynClenCodeLengths(hlit, hdist, hclen, i + 1, clens)) - } else { - ok!(BlockDynCodeLengths(try!(CodeLengthReader::new(clens, hlit as u16 + 256, hdist)))) - } - } - BlockDynCodeLengths(mut reader) => { - let finished = try!(reader.read(&mut stream)); - if finished { - let (lit, dist) = try!(reader.to_lit_and_dist()); - ok!(BlockDyn(lit, dist, 0)) - } else { - ok!(BlockDynCodeLengths(reader)) - } - } - BlockDyn(huff_lit_len, huff_dist, mut prev_len) => { - macro_rules! next (($save_len:expr) => (BlockDyn(huff_lit_len, huff_dist, $save_len))); - loop { - let len = if prev_len != 0 { - let len = prev_len; - prev_len = 0; - len - } else { - let (save, code16) = match try!(huff_lit_len.read(&mut stream)) { - Some(data) => data, - None => return ok!(next!(0)), - }; - let code = code16 as u8; - debug!("{:09b}", code16); - match code16 { - 0...255 => { - push_or!(code, ok!({stream = save; next!(0)})); - continue; - } - 256...285 => {} - _ => return Err(format!("bad DEFLATE len code {}", code)), - } - - macro_rules! len (($code:expr, $bits:expr) => ( - 3 + if $bits == 0 { 0 } else { // new_base - 4 << $bits - } + ((if $code == 29 { - 256 - } else { - $code as u16 - } - if $bits == 0 { 0 } else { // old_base - $bits * 4 + 4 - } - 1) << $bits) + take!($bits => {stream = save; next!(0)}) as u16 - )); - match code { - 0 => { - return if self.final_block { - let (len, bytes) = stream.trailing_bytes(); - ok_state!(CheckCRC(len, bytes)) - } else { - ok!(BlockHeader) - } - } - 1...8 => len!(code, 0), - 9...12 => len!(code, 1), - 13...16 => len!(code, 2), - 17...20 => len!(code, 3), - 21...24 => len!(code, 4), - 25...28 => len!(code, 5), - 29 => len!(29, 0), - _ => return Err(format!("bad DEFLATE len code {}", code as u16 + 256)), - } - }; - - let (save, dist_code) = match try!(huff_dist.read(&mut stream)) { - Some(data) => data, - None => return ok!(next!(len)), - }; - debug!(" {:05b}", dist_code); - macro_rules! len_dist_case (($bits:expr) => ( - len_dist!(len, dist_code, $bits => {stream = save; next!(len)}, next!(0)) - )); - match dist_code { - 0...3 => len_dist_case!(0), - 4...5 => len_dist_case!(1), - 6...7 => len_dist_case!(2), - 8...9 => len_dist_case!(3), - 10...11 => len_dist_case!(4), - 12...13 => len_dist_case!(5), - 14...15 => len_dist_case!(6), - 16...17 => len_dist_case!(7), - 18...19 => len_dist_case!(8), - 20...21 => len_dist_case!(9), - 22...23 => len_dist_case!(10), - 24...25 => len_dist_case!(11), - 26...27 => len_dist_case!(12), - 28...29 => len_dist_case!(13), - _ => return Err(format!("bad DEFLATE dist code {}", dist_code)), - } - } - } - } - } - LenDist((next, state), len, dist) => { - run_len_dist!(len, dist => (0, next, state)); - ok_bytes!(0, Bits(next, state)) - } - Uncompressed(mut len) => { - for (i, &b) in data.iter().enumerate() { - if len == 0 { - return ok_bytes!(i, Bits(BlockHeader, BitState { n: 0, v: 0 })); - } - push_or!(b, ok_bytes!(i, Uncompressed(len))); - len -= 1; - } - ok_bytes!(data.len(), Uncompressed(len)) - } - CheckCRC(mut len, mut bytes) => { - if self.checksum.is_none() { - // TODO: inform caller of unused bytes - return ok_bytes!(0, Finished); - } - - // Get the checksum value from the end of the stream. - let mut used = 0; - while len < 4 && used < data.len() { - bytes[len as usize] = data[used]; - len += 1; - used += 1; - } - if len < 4 { - return ok_bytes!(used, CheckCRC(len, bytes)); - } - - self.read_checksum = Some(adler32_from_bytes(&bytes)); - ok_bytes!(used, Finished) - } - Finished => { - // TODO: inform caller of unused bytes - ok_bytes!(data.len(), Finished) - } - } - } - - /// Try to uncompress/decode the data in `data`. - /// - /// On success, returns how many bytes of the input data was decompressed, and a reference to - /// the buffer containing the decompressed data. - /// - /// This function may not uncompress all the provided data in one call, so it has to be called - /// repeatedly with the data that hasn't been decompressed yet as an input until the number of - /// bytes decoded returned is 0. (See the [top level crate documentation](index.html) - /// for an example.) - /// - /// # Errors - /// If invalid input data is encountered, a string describing what went wrong is returned. - pub fn update<'a>(&'a mut self, mut data: &[u8]) -> Result<(usize, &'a [u8]), String> { - let original_size = data.len(); - let original_pos = self.pos as usize; - let mut empty = false; - while !empty && - ((self.pos as usize) < self.buffer.capacity() || self.buffer.capacity() == 0) { - // next_state must be called at least once after the data is empty. - empty = data.is_empty(); - match self.next_state(data) { - Ok(n) => { - data = &data[n..]; - } - Err(m) => return Err(m), - } - } - let output = &self.buffer[original_pos..self.pos as usize]; - if self.pos as usize >= self.buffer.capacity() { - self.pos = 0; - } - - // Update the checksum.. - self.checksum.update(output); - // and validate if we are done decoding. - if let Some(c) = self.read_checksum { - try!(self.checksum.check(c)); - } - - Ok((original_size - data.len(), output)) - } - - /// Returns the calculated checksum value of the currently decoded data. - /// - /// Will return 0 for cases where the checksum is not validated. - pub fn current_checksum(&self) -> u32 { - self.checksum.current_value() - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/reader.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/reader.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/reader.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/reader.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,358 +0,0 @@ -use std::io::{self, BufRead, Read, BufReader, Error, ErrorKind, Write}; -use std::{cmp,mem}; - -use super::InflateStream; - -/// Workaround for lack of copy_from_slice on pre-1.9 rust. -#[inline] -fn copy_from_slice(mut to: &mut [u8], from: &[u8]) { - assert_eq!(to.len(), from.len()); - to.write_all(from).unwrap(); -} - -/// A DEFLATE decoder/decompressor. -/// -/// This structure implements a `Read` interface and takes a stream -/// of compressed data that implements the `BufRead` trait as input, -/// providing the decompressed data when read from. -/// -/// # Example -/// ``` -/// use std::io::Read; -/// use inflate::DeflateDecoderBuf; -/// -/// const TEST_STRING: &'static str = "Hello, world"; -/// let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -/// let mut decoder = DeflateDecoderBuf::new(&encoded[..]); -/// let mut output = Vec::new(); -/// let status = decoder.read_to_end(&mut output); -/// # let _ = status; -/// assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING); -/// ``` -pub struct DeflateDecoderBuf { - /// The inner reader instance - reader: R, - /// The raw decompressor - decompressor: InflateStream, - /// How many bytes of the decompressor's output buffer still need to be output. - pending_output_bytes: usize, - /// Total number of bytes read from the underlying reader. - total_in: u64, - /// Total number of bytes written in `read` calls. - total_out: u64, -} - -impl DeflateDecoderBuf { - /// Create a new `Deflatedecoderbuf` to read from a raw deflate stream. - pub fn new(reader: R) -> DeflateDecoderBuf { - DeflateDecoderBuf { - reader: reader, - decompressor: InflateStream::new(), - pending_output_bytes: 0, - total_in: 0, - total_out: 0, - } - } - - /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream. - pub fn from_zlib(reader: R) -> DeflateDecoderBuf { - DeflateDecoderBuf { - reader: reader, - decompressor: InflateStream::from_zlib(), - pending_output_bytes: 0, - total_in: 0, - total_out: 0, - } - } - - /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream. - /// without calculating and validating the checksum. - pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoderBuf { - DeflateDecoderBuf { - reader: reader, - decompressor: InflateStream::from_zlib_no_checksum(), - pending_output_bytes: 0, - total_in: 0, - total_out: 0, - } - } -} - -impl DeflateDecoderBuf { - /// Resets the decompressor, and replaces the current inner `BufRead` instance by `r`. - /// without doing any extra reallocations. - /// - /// Note that this function doesn't ensure that all data has been output. - #[inline] - pub fn reset(&mut self, r: R) -> R { - self.decompressor.reset(); - mem::replace(&mut self.reader, r) - } - - /// Resets the decoder, but continue to read from the same reader. - /// - /// Note that this function doesn't ensure that all data has been output. - #[inline] - pub fn reset_data(&mut self) { - self.decompressor.reset() - } - - /// Returns a reference to the underlying `BufRead` instance. - #[inline] - pub fn get_ref(&self) -> &R { - &self.reader - } - - /// Returns a mutable reference to the underlying `BufRead` instance. - /// - /// Note that mutation of the reader may cause surprising results if the decoder is going to - /// keep being used. - #[inline] - pub fn get_mut(&mut self) -> &mut R { - &mut self.reader - } - - /// Drops the decoder and return the inner `BufRead` instance. - /// - /// Note that this function doesn't ensure that all data has been output. - #[inline] - pub fn into_inner(self) -> R { - self.reader - } - - /// Returns the total bytes read from the underlying `BufRead` instance. - #[inline] - pub fn total_in(&self) -> u64 { - self.total_in - } - - /// Returns the total number of bytes output from this decoder. - #[inline] - pub fn total_out(&self) -> u64 { - self.total_out - } - - /// Returns the calculated checksum value of the currently decoded data. - /// - /// Will return 0 for cases where the checksum is not validated. - #[inline] - pub fn current_checksum(&self) -> u32 { - self.decompressor.current_checksum() - } -} - -impl Read for DeflateDecoderBuf { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let mut bytes_out = 0; - // If there is still data left to ouput from the last call to `update()`, that needs to be - // output first - if self.pending_output_bytes != 0 { - // Get the part of the buffer that has not been output yet. - // The decompressor sets `pos` to 0 when it reaches the end of it's internal buffer, - // so we have to check for that. - let start = if self.decompressor.pos != 0 { - self.decompressor.pos as usize - self.pending_output_bytes - } else { - self.decompressor.buffer.len() - self.pending_output_bytes - }; - - // Copy as much decompressed as possible to buf. - let bytes_to_copy = cmp::min(buf.len(), self.pending_output_bytes); - let pending_data = - &self.decompressor.buffer[start.. - start + bytes_to_copy]; - copy_from_slice(&mut buf[..bytes_to_copy],pending_data); - bytes_out += bytes_to_copy; - // This won't underflow since `bytes_to_copy` will be at most - // the same value as `pending_output_bytes`. - self.pending_output_bytes -= bytes_to_copy; - if self.pending_output_bytes != 0 { - self.total_out += bytes_out as u64; - // If there is still decompressed data left that didn't - // fit in `buf`, return what we read. - return Ok(bytes_out); - } - } - - // There is space in `buf` for more data, so try to read more. - let (input_bytes_read, remaining_bytes) = { - self.pending_output_bytes = 0; - let input = try!(self.reader.fill_buf()); - if input.len() == 0 { - self.total_out += bytes_out as u64; - //If there is nothing more to read, return. - return Ok(bytes_out); - } - let (input_bytes_read, data) = - match self.decompressor.update(&input) { - Ok(res) => res, - Err(m) => return Err(Error::new(ErrorKind::Other, m)) - }; - - // Space left in `buf` - let space_left = buf.len() - bytes_out; - let bytes_to_copy = cmp::min(space_left, data.len()); - - copy_from_slice(&mut buf[bytes_out..bytes_out + bytes_to_copy], &data[..bytes_to_copy]); - - bytes_out += bytes_to_copy; - - // Can't underflow as bytes_to_copy is bounded by data.len(). - (input_bytes_read, data.len() - bytes_to_copy) - - }; - - self.pending_output_bytes += remaining_bytes; - self.total_in += input_bytes_read as u64; - self.total_out += bytes_out as u64; - self.reader.consume(input_bytes_read); - - Ok(bytes_out) - } -} - - - -/// A DEFLATE decoder/decompressor. -/// -/// This structure implements a `Read` interface and takes a stream of compressed data that -/// implements the `Read` trait as input, -/// provoding the decompressed data when read from. -/// # Example -/// ``` -/// use std::io::Read; -/// use inflate::DeflateDecoder; -/// const TEST_STRING: &'static str = "Hello, world"; -/// let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -/// let mut decoder = DeflateDecoder::new(&encoded[..]); -/// let mut output = Vec::new(); -/// let status = decoder.read_to_end(&mut output); -/// # let _ = status; -/// assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING); -/// ``` -pub struct DeflateDecoder { - /// Inner DeflateDecoderBuf, with R wrapped in a `BufReader`. - inner: DeflateDecoderBuf> -} - -impl DeflateDecoder { - /// Create a new `Deflatedecoderbuf` to read from a raw deflate stream. - pub fn new(reader: R) -> DeflateDecoder { - DeflateDecoder { - inner: DeflateDecoderBuf::new(BufReader::new(reader)) - } - } - - /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream. - pub fn from_zlib(reader: R) -> DeflateDecoder { - DeflateDecoder { - inner: DeflateDecoderBuf::from_zlib(BufReader::new(reader)) - } - } - - /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream. - /// without calculating and validating the checksum. - pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoder { - DeflateDecoder { - inner: DeflateDecoderBuf::from_zlib_no_checksum(BufReader::new(reader)) - } - } - - /// Resets the decompressor, and replaces the current inner `BufRead` instance by `r`. - /// without doing any extra reallocations. - /// - /// Note that this function doesn't ensure that all data has been output. - #[inline] - pub fn reset(&mut self, r: R) -> R { - self.inner.reset(BufReader::new(r)).into_inner() - } - - /// Returns a reference to the underlying reader. - #[inline] - pub fn get_ref(&self) -> &R { - self.inner.get_ref().get_ref() - } - - /// Returns a mutable reference to the underlying reader. - /// - /// Note that mutation of the reader may cause surprising results if the decoder is going to - /// keep being used. - #[inline] - pub fn get_mut(&mut self) -> &mut R { - self.inner.get_mut().get_mut() - } - - /// Returns the total number of bytes output from this decoder. - #[inline] - pub fn into_inner(self) -> R { - self.inner.into_inner().into_inner() - } -} - -impl DeflateDecoder { - /// Resets the decoder, but continue to read from the same reader. - /// - /// Note that this function doesn't ensure that all data has been output. - #[inline] - pub fn reset_data(&mut self) { - self.inner.reset_data() - } - - /// Returns the total bytes read from the underlying reader. - #[inline] - pub fn total_in(&self) -> u64 { - self.inner.total_in - } - - /// Returns the total number of bytes output from this decoder. - #[inline] - pub fn total_out(&self) -> u64 { - self.inner.total_out - } - - /// Returns the calculated checksum value of the currently decoded data. - /// - /// Will return 0 for cases where the checksum is not validated. - #[inline] - pub fn current_checksum(&self) -> u32 { - self.inner.current_checksum() - } -} - -impl Read for DeflateDecoder { - #[inline] - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.inner.read(buf) - } -} - -#[cfg(test)] -mod test { - use super::{DeflateDecoder}; - use std::io::Read; - - #[test] - fn deflate_reader() { - const TEST_STRING: &'static str = "Hello, world"; - let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; - let mut decoder = DeflateDecoder::new(&encoded[..]); - let mut output = Vec::new(); - decoder.read_to_end(&mut output).unwrap(); - assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING); - assert_eq!(decoder.total_in(), encoded.len() as u64); - assert_eq!(decoder.total_out(), TEST_STRING.len() as u64); - } - - #[test] - fn zlib_reader() { - const TEST_STRING: &'static str = "Hello, zlib!"; - let encoded = vec![120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, - 76, 82, 4, 0, 27, 101, 4, 19]; - let mut decoder = DeflateDecoder::from_zlib(&encoded[..]); - let mut output = Vec::new(); - decoder.read_to_end(&mut output).unwrap(); - assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING); - assert_eq!(decoder.total_in(), encoded.len() as u64); - assert_eq!(decoder.total_out(), TEST_STRING.len() as u64); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/utils.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/utils.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/utils.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/utils.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/// Convenience functions for inflating DEFLATE compressed data. -/// -/// # Example -/// ``` -/// use inflate::inflate_bytes; -/// use std::str::from_utf8; -/// -/// let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -/// let decoded = inflate_bytes(&encoded).unwrap(); -/// println!("{}", from_utf8(&decoded).unwrap()); // prints "Hello, world" -/// ``` - -use InflateStream; - -fn inflate(inflater: &mut InflateStream, data: &[u8]) -> Result, String> { - let mut decoded = Vec::::new(); - - let mut n = 0; - loop { - let (num_bytes_read, bytes) = try!(inflater.update(&data[n..])); - if bytes.len() == 0 { - break; - } - n += num_bytes_read; - decoded.extend(bytes.iter().map(|v| *v)); - } - - Ok(decoded) -} - -/// Decompress the given slice of DEFLATE compressed data. -/// -/// Returns a `Vec` with the decompressed data or an error message. -pub fn inflate_bytes(data: &[u8]) -> Result, String> { - inflate(&mut InflateStream::new(), data) -} - -/// Decompress the given slice of DEFLATE compressed (with zlib headers and trailers) data. -/// -/// Returns a `Vec` with the decompressed data or an error message. -pub fn inflate_bytes_zlib(data: &[u8]) -> Result, String> { - inflate(&mut InflateStream::from_zlib(), data) -} - -/// Decompress the given slice of DEFLATE compressed (with zlib headers and trailers) data, -/// without calculating and validating the checksum. -/// -/// Returns a `Vec` with the decompressed data or an error message. -pub fn inflate_bytes_zlib_no_checksum(data: &[u8]) -> Result, String> { - inflate(&mut InflateStream::from_zlib_no_checksum(), data) -} - -#[cfg(test)] -mod test { - #[test] - fn inflate_bytes_with_zlib() { - use super::inflate_bytes_zlib; - use std::str::from_utf8; - - let encoded = [120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, - 76, 82, 4, 0, 27, 101, 4, 19]; - let decoded = inflate_bytes_zlib(&encoded).unwrap(); - assert!(from_utf8(&decoded).unwrap() == "Hello, zlib!"); - } - - #[test] - fn inflate_bytes_with_zlib_checksum_fail() { - use super::inflate_bytes_zlib; - - // The last 4 bytes are the checksum, we set them to 0 here to check that decoding fails - // if the checksum is wrong. - let encoded = [120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, - 76, 82, 4, 0, 0, 0, 0, 0]; - inflate_bytes_zlib(&encoded).unwrap_err(); - } - - #[test] - fn inflate_bytes_with_zlib_trailing() { - use super::inflate_bytes_zlib; - use std::str::from_utf8; - - // The additional 4 bytes should be ignored. - let encoded = [120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, - 76, 82, 4, 0, 27, 101, 4, 19, 0, 0, 0, 0]; - let decoded = inflate_bytes_zlib(&encoded).unwrap(); - assert!(from_utf8(&decoded).unwrap() == "Hello, zlib!"); - } - -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/writer.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/writer.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/src/writer.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/src/writer.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -use std::io::{Write, Error, ErrorKind}; -use std::io; -use InflateStream; - -/// A DEFLATE decoder. -/// -/// A struct implementing the `std::io::Write` trait that decompresses DEFLATE -/// encoded data into the given writer `w`. -/// -/// # Example -/// -/// ``` -/// use inflate::InflateWriter; -/// use std::io::Write; -/// -/// let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; -/// let mut decoder = InflateWriter::new(Vec::new()); -/// decoder.write(&encoded).unwrap(); -/// let decoded = decoder.finish().unwrap(); -/// println!("{}", std::str::from_utf8(&decoded).unwrap()); // prints "Hello, world" -/// ``` -pub struct InflateWriter { - inflater: InflateStream, - writer: W -} - -impl InflateWriter { - pub fn new(w: W) -> InflateWriter { - InflateWriter { inflater: InflateStream::new(), writer: w } - } - - pub fn from_zlib(w: W) -> InflateWriter { - InflateWriter { inflater: InflateStream::from_zlib(), writer: w } - } - - pub fn finish(mut self) -> io::Result { - try!(self.flush()); - Ok(self.writer) - } -} - -fn update<'a>(inflater: &'a mut InflateStream, buf: &[u8]) -> io::Result<(usize, &'a [u8])> { - match inflater.update(buf) { - Ok(res) => Ok(res), - Err(m) => return Err(Error::new(ErrorKind::Other, m)), - } -} -impl Write for InflateWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - let mut n = 0; - while n < buf.len() { - let (num_bytes_read, result) = try!(update(&mut self.inflater, &buf[n..])); - n += num_bytes_read; - try!(self.writer.write(result)); - } - Ok(n) - } - - fn flush(&mut self) -> io::Result<()> { - let (_, result) = try!(update(&mut self.inflater, &[])); - try!(self.writer.write(result)); - Ok(()) - } -} - -#[cfg(test)] -mod test { - use super::InflateWriter; - use std::io::Write; - - #[test] - fn inflate_writer() { - let encoded = [243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0]; - let mut decoder = InflateWriter::new(Vec::new()); - decoder.write(&encoded).unwrap(); - let decoded = decoder.finish().unwrap(); - assert!(String::from_utf8(decoded).unwrap() == "Hello, world"); - } - - #[test] - fn inflate_writer_from_zlib() { - let encoded = [120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19]; - let mut decoder = InflateWriter::from_zlib(Vec::new()); - decoder.write(&encoded).unwrap(); - let decoded = decoder.finish().unwrap(); - assert!(String::from_utf8(decoded).unwrap() == "Hello, zlib!"); - } -} Binary files /srv/release.debian.org/tmp/4JUg2RRa91/clamav-1.4.3+dfsg/.cargo/vendor/inflate/tests/issue_14.zlib and /srv/release.debian.org/tmp/KpvsfYPLZ3/clamav-1.4.6+dfsg/.cargo/vendor/inflate/tests/issue_14.zlib differ diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/inflate/tests/test.rs clamav-1.4.6+dfsg/.cargo/vendor/inflate/tests/test.rs --- clamav-1.4.3+dfsg/.cargo/vendor/inflate/tests/test.rs 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/inflate/tests/test.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,156 +0,0 @@ -extern crate inflate; - -fn get_test_file_data(name: &str) -> Vec { - use std::fs::File; - use std::io::Read; - let mut input = Vec::new(); - let mut f = File::open(name).unwrap(); - - f.read_to_end(&mut input).unwrap(); - input -} - -#[test] -/// See https://github.com/PistonDevelopers/inflate/issues/14 -fn issue_14() { - let test_data = get_test_file_data("tests/issue_14.zlib"); - let res = inflate::inflate_bytes_zlib(&test_data); - // This should fail as the file specifies code lengths that won't work. - assert!(res.is_err()); -} - -#[test] -/// Another input that produce invalid code lengths. -fn issue_16() { - let data = b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xadMCMMMM\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd9\xcb!\x0a"; - let mut stream = inflate::InflateStream::new(); - let res = stream.update(data); - assert!(res.is_err()); -} - -#[test] -/// Similar to 16 but with CLENS being invalid. -fn issue_17() { - let data = b"\xdd\xff\xff*M\x94ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\x01\x09\x00\x00\xf2\xf2MM\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*M\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00MMMM\xff\xffM\xff\x00;MM0*\x00\x00\x00\x00\x00\x00\x0a"; - let mut stream = inflate::InflateStream::new(); - let res = stream.update(data); - assert!(res.is_err()); -} - -#[test] -fn issue_30_realworld() { - // In this case, the LZ77 window size is misreported as 256B. The first two bytes should be - // e.g. [0x78, 0xda] to set the window size to a maximum value (32kiB). - let data = &[ - 0x8, 0xd7, 99, 100, 48, 158, 201, 128, 3, 196, 91, 158, 48, 231, 153, 127, 242, 75, - 226, 194, 227, 22, 184, 212, 48, 51, 72, 249, 98, 213, 57, 47, 180, 153, 225, 195, 133, - 148, 64, 230, 87, 247, 206, 53, 249, 111, 249, 201, 40, 122, 241, 137, 12, 166, 74, 70, - 172, 246, 255, 154, 150, 149, 186, 56, 14, 110, 109, 188, 229, 137, 217, 177, 139, 216, - 178, 166, 49, 50, 48, 252, 199, 175, 63, 222, 242, 68, 130, 238, 124, 199, 89, 88, 12, 221, - 159, 150, 190, 224, 50, 186, 95, 152, 208, 20, 213, 56, 207, 95, 112, 57, 17, 171, 87, 23, - 92, 78, 172, 113, 158, 143, 207, 255, 241, 150, 39, 126, 190, 190, 208, 118, 48, 19, 171, - 254, 139, 79, 100, 52, 217, 183, 136, 136, 163, 4, 4, 138, 253, 230, 60, 243, 83, 2, 153, - 25, 209, 253, 136, 0, 41, 129, 204, 230, 60, 40, 78, 96, 65, 230, 156, 252, 146, 200, 176, - 126, 254, 127, 6, 70, 92, 209, 57, 103, 253, 223, 147, 95, 18, 113, 250, 127, 225, 113, 11, - 87, 115, 134, 120, 203, 19, 88, 245, 31, 186, 165, 234, 106, 206, 64, 32, 252, 90, 246, 38, - 38, 232, 206, 199, 170, 127, 94, 112, 85, 203, 222, 68, 2, 241, 207, 200, 192, 192, 192, - 240, 255, 231, 180, 108, 204, 248, 103, 207, 154, 198, 128, 17, 255, 44, 104, 230, 253, - 103, 96, 96, 96, 96, 76, 93, 28, 151, 160, 59, 31, 18, 156, 115, 214, 255, 213, 84, 100, - 72, 93, 156, 136, 53, 84, 25, 41, 76, 255, 0, 17, 24, 113, 221]; - inflate::inflate_bytes_zlib(data); -} - -#[test] -fn issue_30_small() { - // Invalid data, but should not panic - // generated by cargo-fuzz - let data = &[0x08, 0xd7, 0x3a, 0xff, 0x3b, 0x8, 0xd7, 0xfd, 0xff, 0xff, 0xff]; - inflate::inflate_bytes_zlib(data); -} - -#[test] -// no checksum present at the end of the data stream (cargo-fuzz test-case) -fn no_checksum() { - let data = b"\x13\xff\xed\xff\xff\x12\xbfM\x00\x00\x00\x00\xd1"; - let mut stream = inflate::InflateStream::new(); - let res = stream.update(data); - // This is not an error, because the checksum may be included in the next - // call to `stream.update`. See issue #27. - assert!(res.is_ok()); -} - -#[test] -/// The first byte of the CRC is already read into the BitStream buffer. -fn issue_26() { - let data = &[120, 156, 189, 138, 65, 13, 0, 32, 16, 195, 64, 2, 22, 176, 128, 5, 44, 96, 1, 11, - 216, 103, 19, 176, 123, 118, 73, 155, 61, 218, 155, 54, 10, 136, 192, 170, 32, 130, 41, - 249, 36, 136, 96, 73, 62, 9, 34, 216, 146, 79, 130, 8, 142, 228, 147, 32, 130, 43, 249, 36, - 136, 224, 73, 62, 9, 32, 248, 250, 192, 22, 113, 123]; - let mut stream = inflate::InflateStream::from_zlib(); - let res = stream.update(data); - assert!(res.is_ok()); -} - -#[test] -/// InflateStream::update() should try to process bytes in the Bits state. -fn issue_38_update_bits() { - // compressed final block 011, literal 111111111=255, end 0000000 - let data = &[0b1111_1011, 0b0000_1111, 0b0000_0000]; - let bytes = inflate::inflate_bytes(data).unwrap(); - assert_eq!(bytes.len(), 1); -} - -#[test] -/// InflateStream::update() should try to process bytes in the LenDist state. -fn issue_38_update_lendist() { - // compressed final block 011, literal 00110000=0 x 32766, len 0000001=3, dist 00000=1, end 0000000 - let mut data = vec![0b0110_0011]; - data.extend(std::iter::repeat(0b0110_0000).take(32765)); - data.extend(vec![0b0000_0000, 0b0000_0010, 0b0000_00000]); - let bytes = inflate::inflate_bytes(&data).unwrap(); - assert_eq!(bytes.len(), 32769); -} - -#[test] -/// InflateStream::update() should return if it can't make progress -fn issue_38_update_no_progress() { - // compressed final block 011, 110010000 x 5, 110010000 truncated to 8 bits - let data = &[0b1001_1011, 0b0011_0000, 0b0110_0001, 0b1100_0010, 0b10000100, 0b0000_1001, 0b00010011]; - let bytes = inflate::inflate_bytes(data).unwrap(); - assert_eq!(bytes.len(), 5); -} - -#[test] -/// inflate() should loop until no data is produced. -fn issue_38_inflate() { - // compressed final block 011, literal 00110000=0 x 32769, end 0000000 - let mut data = vec![0b0110_0011]; - data.extend(std::iter::repeat(0b0110_0000).take(32768)); - data.extend(vec![0b0000_0000, 0b0000_0000]); - let bytes = inflate::inflate_bytes(&data).unwrap(); - assert_eq!(bytes.len(), 32769); -} - -#[test] -/// InflateStream::update() should handle end of input between uncompressed len and nlen. -fn issue_47_uncompressed() { - let len = 50; - let hilen = (len >> 8) as u8; - let lolen = (len & 0xff) as u8; - // uncompressed block 001 - let mut data = vec![0b001, lolen, hilen, !lolen, !hilen]; - data.extend(std::iter::repeat(0).take(len + 1)); - let mut stream = inflate::InflateStream::new(); - { - // Update with input to the end of len. - let (update_len, bytes) = stream.update(&data[..3]).unwrap(); - assert_eq!(update_len, 3); - assert_eq!(bytes, &[]); - } - { - // Update with remainder of input. - let (update_len, bytes) = stream.update(&data[3..]).unwrap(); - assert_eq!(update_len, data.len() - 3); - assert_eq!(bytes.len(), len); - } -} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"716395e84a31bfd72749edaf153a24ed89b77ee66e0d113c0bed19d4ffc39d54","Cargo.lock":"b4076e8e9b5e66a682d90e42f429c4043234ce213049158c775f6540c2b20536","Cargo.toml":"4ae7bfe2757403521e0f1e52c225ca891923ac1687418d8295d9fc628c6cbaee","Cargo.toml.orig":"044ed475b985944894a74afcdf4dabe81a761f8d8a3b4034a85090d83a42f135","LICENSE":"8eb4fb5a6505da473ee195f326007c8c7e28357e3e6a11e293ce2a480384030c","README.md":"95076987e5d60ca9c883a86f4c5e75f5143c74cbb4069a05c03c7c4f3c4b0575","examples/rename.rs":"bb4c1b881fb1760c67d289f4695f2fb41d16fe0b737f32802d34d94baf3409ee","src/lib.rs":"7ac9b005d8dae1bfa752ae41b9a69b5a275606af905200dc3f74d2a76272f5cc","tests/interpolate_name.rs":"4fe03330f7542c0b5546acb6ea9e6098af81e1ec6a2b3a6cea0ae5cbb93e6ed9","tests/interpolate_test.rs":"d5c889748ab8e63fd9e2072080d82cfdd8537a4004a0ea5fab1aceae7bd346e1"},"package":"c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a4b0f8cf45654fdd400fab0d50677db34cea8a0a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.lock clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.lock --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.lock 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "interpolate_name" +version = "0.2.4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.toml clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,42 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "interpolate_name" +version = "0.2.4" +authors = ["Luca Barbato "] +description = "Simple procedural macro attribute for repetitive tests" +readme = "README.md" +keywords = [ + "proc_macro", + "testing", +] +categories = ["development-tools::testing"] +license = "MIT" +repository = "https://github.com/lu-zero/interpolate_name" + +[lib] +test = false +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" +features = [ + "fold", + "full", +] diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.toml.orig clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml.orig --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/Cargo.toml.orig 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,20 @@ +[package] +name = "interpolate_name" +version = "0.2.4" +authors = ["Luca Barbato "] +description = "Simple procedural macro attribute for repetitive tests" +repository = "https://github.com/lu-zero/interpolate_name" +readme = "README.md" +keywords = ["proc_macro", "testing"] +categories = ["development-tools::testing"] +license = "MIT" +edition = "2018" + +[lib] +proc-macro = true +test = false + +[dependencies] +syn = { version = "2.0", features = ["fold", "full"] } +quote = "1.0" +proc-macro2 = "1.0" diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/LICENSE clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/LICENSE --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/LICENSE 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Luca Barbato + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/README.md clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/README.md --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/README.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,28 @@ +# Procedural macro attribute to do not repeat yourself while testing + +## Usage + +``` rust +#[macro_use] +extern crate interpolate_name; + +use interpolate_name::interpolate_test; + +#[interpolate_test(foo, "foo")] +#[interpolate_test(bar, "bar")] +#[interpolate_test(baz, "baz")] +fn testme(f: &str) { + println!("testing {}", f); +} +``` + +Produces + +``` +running 3 tests +test testme_baz ... ok +test testme_bar ... ok +test testme_foo ... ok +``` + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/examples/rename.rs clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/examples/rename.rs --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/examples/rename.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/examples/rename.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,10 @@ +use interpolate_name::interpolate_name; + +#[interpolate_name(one)] +fn t() { + +} + +fn main() { + t_one(); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/src/lib.rs clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/src/lib.rs --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,204 @@ +//! # interpolate_name +//! +//! `interpolate_name` consists in a set of procedural macro attributes +//! geared towards reduce the boilerplate while writing repetitive tests. +//! +//! - `interpolate_test`: a quick way to test the same function by passing specific +//! arguments and have a test entry for each of them. +//! - `interpolate_name`: a simple function renamer that can be combined +//! with macros to support more complex patterns. + +extern crate proc_macro; + +use syn::{parse_macro_input, Attribute, ItemFn}; + +use proc_macro2::{Ident, Span, TokenStream, TokenTree}; + +use quote::{quote_spanned, ToTokens}; + +fn fn_name(item: TokenStream) -> Ident { + let mut tokens = item.into_iter(); + let found = tokens + .find(|tok| { + if let TokenTree::Ident(word) = tok { + if word == "fn" { + true + } else { + false + } + } else { + false + } + }) + .is_some(); + + if !found { + panic!("the macro attribute applies only to functions") + } + + match tokens.next() { + Some(TokenTree::Ident(word)) => word, + _ => panic!("failed to find function name"), + } +} + +fn fn_attrs_name(item: TokenStream) -> (TokenStream, Ident) { + let mut tokens = item.into_iter(); + + let attrs = tokens + .by_ref() + .take_while(|tok| { + if let TokenTree::Ident(word) = tok { + if word == "fn" { + false + } else { + true + } + } else { + true + } + }) + .collect::>(); + + let name = match tokens.next() { + Some(TokenTree::Ident(word)) => word, + _ => panic!("the macro attribute applies only to functions"), + }; + + (TokenStream::from_iter(attrs.into_iter()), name) +} + +/// Rename the decorated function by appending `_` and the provided `specifier`. +/// +/// ``` no_run +/// use interpolate_name::interpolate_name; +/// +/// #[interpolate_name(spec)] +/// fn foo() {} +/// ``` +/// +/// produces: +/// ``` no_run +/// fn foo_spec() {} +/// ``` +#[proc_macro_attribute] +pub fn interpolate_name( + attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let tokens = TokenStream::from(attr).into_iter().collect::>(); + if tokens.len() != 1 { + panic!("expected #[interpolate_name(specifier)]"); + } + + let specifier = match &tokens[0] { + TokenTree::Literal(tt) => tt.to_string(), + TokenTree::Ident(tt) => tt.to_string(), + _ => panic!("expected #[interpolate_name(specifier)]"), + }; + + let item = TokenStream::from(item); + let (attrs, name) = fn_attrs_name(item.clone()); + let interpolated_name = Ident::new( + &format!("{}_{}", name.to_string(), specifier), + Span::call_site(), + ); + + let ret: TokenStream = quote_spanned! { + proc_macro2::Span::call_site() => + #attrs + fn #interpolated_name() { + #item + + return #name (); + } + } + .into(); + + ret.into() +} + +use std::iter::FromIterator; + +/// Generate a new test that calls the decorated function with the provided arguments. +/// +/// The test function name is the same as the called plus `_` and `specifier`. +/// Can decorate the same function multiple times. +/// +/// ``` no_run +/// use interpolate_name::interpolate_test; +/// +/// #[interpolate_test(some, "some", "arguments", 1)] +/// #[interpolate_test(name, "other", "arguments", 42)] +/// fn foo(a: &str, b: &str, c: usize) { +/// println!("{} {} {}", a, b,c); +/// } +/// ``` +/// +/// produces: +/// ``` no_run +/// #[test] +/// fn foo_some() { foo("some", "arguments", 1); } +/// #[test] +/// fn foo_name() { foo("other", "arguments", 42); } +/// ``` +#[proc_macro_attribute] +pub fn interpolate_test( + attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let tokens = TokenStream::from(attr).into_iter().collect::>(); + if tokens.len() < 3 { + panic!("expected #[interpolate_test(specifier, arguments)]"); + } + + let specifier = match &tokens[0] { + TokenTree::Literal(tt) => tt.to_string(), + TokenTree::Ident(tt) => tt.to_string(), + _ => panic!("expected #[interpolate_test(specifier, arguments)]"), + }; + + match &tokens[1] { + TokenTree::Punct(p) if p.as_char() == ',' => {} + _ => panic!("expected #[interpolate_test(specifier, arguments)]"), + } + + let args = TokenStream::from_iter(tokens.into_iter().skip(2)); + + let mut syn_item = parse_macro_input!(item as ItemFn); + let (mut interpolate_attrs, attrs): (Vec, Vec) = + syn_item.attrs.iter().cloned().partition(|attr| { + let found = if let Some(seg) = attr.path().segments.last() { + seg.ident == "interpolate_test" + } else { + false + }; + found + }); + let append_attrs = !interpolate_attrs.is_empty(); + if append_attrs { + interpolate_attrs.extend(attrs.iter().cloned()); + } + syn_item.attrs = interpolate_attrs; + let attrs = TokenStream::from_iter(attrs.iter().map(|it| it.into_token_stream())); + let item = TokenStream::from(syn_item.into_token_stream()); + let name = fn_name(item.clone()); + let interpolated_name = Ident::new( + &format!("{}_{}", name.to_string(), specifier), + Span::call_site(), + ); + + let ret: TokenStream = quote_spanned! { + proc_macro2::Span::call_site() => + #item + + #[test] + #attrs + fn #interpolated_name() { + return #name (#args); + } + } + .into(); + + ret.into() +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_name.rs clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_name.rs --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_name.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_name.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,11 @@ +use interpolate_name::interpolate_name; + + +#[allow(unnameable_test_items)] +#[interpolate_name(1)] +#[test] +fn t() { + +} + + diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_test.rs clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_test.rs --- clamav-1.4.3+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_test.rs 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/interpolate_name/tests/interpolate_test.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,24 @@ +use interpolate_name::interpolate_test; + +#[interpolate_test(foo, "foo")] +#[interpolate_test(bar, "bar")] +#[interpolate_test(baz, "baz")] +#[interpolate_test(124, "test_literal")] +fn testme(f: &str) { + println!("testing {}", f); +} + +#[interpolate_test(foo, "foo")] +#[interpolate_test(bar, "bar")] +#[interpolate_test(baz, "baz")] +#[interpolate_test(124, "test_literal")] +#[ignore] +fn testme_ignore(f: &str) { + println!("testing {}", f); +} + +#[cfg_attr(not(feature = "a"), interpolate_name::interpolate_test(a, "a"))] +#[cfg_attr(feature = "b", interpolate_name::interpolate_test(b, "b"))] +fn testme_variants(f: &str) { + println!("testing {}", f); +} diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.cargo-checksum.json clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo-checksum.json --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.cargo-checksum.json 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo-checksum.json 2026-08-06 21:12:24.000000000 +0000 @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"ed6c781d541c40d4a19eaecd794cadebb94b3f4d51e32367803542c88f0457ee","Cargo.toml":"6dcbab25126c0cdf64f5089156de0d4346914c6d47c557d370b8e20e039ca7d3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"3acfeb07424200ae70bf571ef63a96bae954c298bddf447c9bea0ea9394825cc","benches/bench1.rs":"bb06f39db0544b1380cd4929139ccf521a9eecab7ca3f910b9499f965ec0a047","benches/combinations.rs":"51523ee1ca438a56f14711f0b04ee943895062d35859fbe23a2714d2fca3289d","benches/combinations_with_replacement.rs":"11f29160652a2d90ce7ca4b1c339c4457888ab6867e2456ce1c62e3adf9be737","benches/extra/mod.rs":"6ca290d72302a1945078621610b5788060b0de29639decebbdc557a80044aa97","benches/extra/zipslices.rs":"40e9f68a7c00f8429193fca463caef18851fa49b33355cc136bad3ccc840d655","benches/fold_specialization.rs":"5a517bbe29d366a15f6f751660e17ab1aa3e7b21552a1983048c662e34f0d69e","benches/powerset.rs":"6fd9d69a3483b37dc2411f99fb4efa6131577696f2dbdc8d1de9e4d7642fe3a3","benches/tree_fold1.rs":"539232e74f9aaea295a42069ac5af707811e90dc1c71c6e0a9064ffc731999de","benches/tuple_combinations.rs":"16366158743307a0289fc1df423a3cec45009807d410a9fe9922d5b6f8b7d002","benches/tuples.rs":"5a620783ae203e9ff9623d10d2c7fe9911d8b6c811cbad7613afa30e390c759d","clippy.toml":"33ffb83bbddb772575b3aa565b7136a8158ee386c216ffc2588fed9e83fa3826","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"1b465ed6a417180913104bc95a545fd9d1a3d67d121871ab737ad87e31b8be37","src/adaptors/coalesce.rs":"a0073325d40f297d29101538d18a267aef81889a999338dc09cb43a31cb4ec8b","src/adaptors/map.rs":"241971e856e468d71323071fb4a09867fbcedb83877320be132dc03516fe60e8","src/adaptors/mod.rs":"7f3bd7d011a348ce5e4bea486ef2e6346b64c7fe27540334d56d3f147f981d59","src/adaptors/multi_product.rs":"bb43e6dce68c815c21006d5b01c56e038d54b0c3bb8ee6bb8a4de11e2952c7ad","src/combinations.rs":"fb25babb459389093f886721016c72bf9f00e51d02735f638d871bb3a447ffd0","src/combinations_with_replacement.rs":"463011a574facbdd84278386b533a90e4dd517f0417e05adb82d182049db1f50","src/concat_impl.rs":"03b1ed61cbed242c286c3c4c5c848dbd57e02ab83fcef264f3a592b58107f324","src/cons_tuples_impl.rs":"c253d03b861831c01d62cacc57b49715ee62f6171e69f6886bb5a6ca0863bc3a","src/diff.rs":"a7800e9ce7a87b53ebe2338481335751fb43d44fa6a1ca719aceaaab40e5c8fe","src/duplicates_impl.rs":"f62fe4b642f501f785721ce5a505cf622a771e457210726dd0fb8b30be7ebbbc","src/either_or_both.rs":"76b13fbfac6bc959b4c1d8b7c99ce51726e95f994ca5429477e523a3d3950e4a","src/exactly_one_err.rs":"aa50081f6a31b5109b30e3ed305e3ec2413c6908dedc8990ec5378a99cee2b39","src/extrema_set.rs":"2a25b0b86eed2fd5d05622d591a3085cab823973d450816c2c3b8cb76e9c187e","src/flatten_ok.rs":"fe209fd886ecd9cb98d99625aa0c7274af7e644eff4a10de15b4dec8bbbc934a","src/format.rs":"a8192d85c0f9de8e633c202456e3cde0f3bc50f19b6bd8a4b2cfa3ef5123de1a","src/free.rs":"dfc57b7f56a08d4986a96b679018b41346576a7a34b668e008cc01109e728750","src/group_map.rs":"f7b02c964f63505d3e36280cfdc1755e05287714201efe983dacf702eee61434","src/groupbylazy.rs":"4f2181c022a45ff8444597708861fc6863eceb6f7555ea81cf3eeba19b492971","src/grouping_map.rs":"cbc45ac563345c96f3ac50c78f73c83d870523436a7ab88c1c9a685d204461d3","src/impl_macros.rs":"4f829b458873bed556f1aff2ae4e88dbd576766e2b5bcc07ff3ac8756758e6f4","src/intersperse.rs":"b9717242495846a4a979c95d93d5681caccb7c07a0d889eab763ad3d49a46125","src/k_smallest.rs":"603eb34314c01769ff7f6def2a24cf7a7b38507e6f3658b7aafc23a3b2e9b322","src/kmerge_impl.rs":"a347b0f6fa7715afd8a54d85ce139ed5b14c9e58a16c2b3648f5b288fdb5375f","src/lazy_buffer.rs":"834f6ef7fdf9f00c8a6329beb38eaefb706847ceeec309c221dce705c2c1e05b","src/lib.rs":"fadb0045279aafe8e8cccb45fadc383c7b358197b83c9c38fba87ada4cb2f84a","src/merge_join.rs":"1016113f6c983a9498bae5dc0570190437e1357b3333f6e19ea95c88599a1225","src/minmax.rs":"96d3897c28c8c63284d4729becc9ada6855e0953cac6e1bd35cf6f38c50b0ec0","src/multipeek_impl.rs":"35162bca4456bfa20a08e8d40e4d1cc6783dc662778789fdcded60371e975122","src/pad_tail.rs":"04be2ca73abb85815b06b5524c99d6feb2919180c486a4646f9cc6c87462f67b","src/peek_nth.rs":"6a0a51f2f373ce14d3d58595c46464878a14976bf00841a7396c03f9f9ab07ac","src/peeking_take_while.rs":"2b1b77c8882be32cfd76e973d303aa62f73370efd470c60764add0cdcca524d5","src/permutations.rs":"97831e7e26904c3cae68c97e74f7c6981ceb2fb2f2217282a0e5e54083a565fc","src/powerset.rs":"e0ee6b1316b4dd314c1e81502b90ae8113e1cda12168322520c5a65410e584b2","src/process_results_impl.rs":"9ed7fa46c8316238272ef47577387a386c1a109b50377dd3caf4291b6587cb73","src/put_back_n_impl.rs":"821e047fecd6ca0036290029f4febe7638a3abf1faa05e1e747a3bf9d80ff464","src/rciter_impl.rs":"5b156082ef2d25a94a4ad01d94cba2813c4b3e72e212515a8ad0fc8588f8045d","src/repeatn.rs":"bfc8f9145c9d8a3ea651f012b7d5a8d2fbbcbefdee76eafd098d02e7c54cda90","src/size_hint.rs":"021e57aad7df8f1e70ef588e9e9b8a1695aab183b1098f1848561f96c5dc9bcb","src/sources.rs":"61637f32c2cea2290ecfc1980c0b2d0f68463839ac09bd81006f8258ab8ecaae","src/tee.rs":"665832aa547389a420c3441470ff2494249f0ed2841be0c6a578367fe9dbd381","src/tuple_impl.rs":"00a9b61942425fb477b9691c3348646c0f9f534ff94f6321027f38c61ce2478c","src/unique_impl.rs":"3b89cdd668b74cc0a0eabb1522489e2305a0d2d8da25d6a1884e8626bbdb5959","src/unziptuple.rs":"84b50e5d29b9ddbf21a46a1cc2fd7877729c7f7da9bdc8ae1966dbaf2d2f6f60","src/with_position.rs":"c8a9b3476b3b90986b004a8877c19ff54b4c6800c5ac7ca1458d914036dacfe9","src/zip_eq_impl.rs":"4a41dc6dfe99359585d50ce648bdc85f15276c602048872b1d152e90841d8cad","src/zip_longest.rs":"f7cf5fffc3ca053ee80b410a05b27de1a475021f6de3181aea981010d7e8453f","src/ziptuple.rs":"7f9df12bf6556f382bbd4ad8cf17eb8b60c1c47fadbce016141133ba0f3384a1","tests/adaptors_no_collect.rs":"f459f36d54f5d475b2b2e83f5a1c98109c15062756ae822fa379486f3eeed666","tests/flatten_ok.rs":"b7894874132918b8229c7150b2637511d8e3e14197d8eeb9382d46b2a514efa2","tests/macros_hygiene.rs":"522afa0106e3f11a5149e9218f89c2329e405546d2ef0ea756d6a27e8a0e9ca3","tests/merge_join.rs":"b08c4ee6529d234c68d411a413b8781455d18a1eab17872d1828bb75a4fcf79b","tests/peeking_take_while.rs":"4b1c394e44a9ef9bc0de707ae080b45803db722f79834c20f15b826d7c3f1f2e","tests/quick.rs":"6fcc0649b9270f024b169b1f499dd4cc7fecb0c9aec0dfc155b264916cc626e7","tests/specializations.rs":"fdd16dc663330033fedcc478609b393d4aa369dc07dc8cda31a75219fb793087","tests/test_core.rs":"32576ba90aa8e5db985b6e6ffe30e3046bc6a11d392db8f6b4bdd2ba48d9b24d","tests/test_std.rs":"f28a78a1912c950e7c37be1e82867e70dc585d60afecdebc7a97965194eee8e6","tests/tuples.rs":"014e4da776174bfe923270e2a359cd9c95b372fce4b952b8138909d6e2c52762","tests/zip.rs":"99af365fe6054ef1c6089d3e604e34da8fea66e55861ae4be9e7336ec8de4b56"},"package":"b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"c44891b3a83326c2d0434099194ceee3d75eb1f850a58f611b1c85a788938512",".codecov.yml":"27b445dc39fefbcb3c232623d6ce77ec15133d3fad6bde481b8d140614993b2a",".github/dependabot.yml":"7ae793ed2cfbb3d571f46e4c6ed9cfd374af472c44d38d7e9be82e91fccafcd4",".github/workflows/ci.yml":"c38c00e4e8b428fce92cfad22c26f9ff8dc99cb9045380071ba8bc759a7ec16e",".github/workflows/coverage.yml":"6dfc476a71ffa247ff4a79dfb2e51afc927ea644f5c781afaf5c3cd03b552537","CHANGELOG.md":"60ec9a1801e015e49f7fbb299b608ac730d5b1a3fb298e6cf7935c0695ddf7fe","CONTRIBUTING.md":"d5787d0fd4df15481e2e09a37234ac5dec22c007c890826991f633d890efa29e","Cargo.lock":"4422e732d4ce6f650afb53a1dcffb1e53c86dd066c3dcd66bc9620acd898b99e","Cargo.toml":"77735549383196a4156a2246dd1cd6742029b223679b3004531456d33562b0ce","Cargo.toml.orig":"1fb9c3c002924032d84c3a39dddfeb171724c413c1d5215d7a720598eb922a58","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"7dba3f55ea54eff2606f8b9f005e369cf9885dd972cb481432fce00234ee7750","benches/bench1.rs":"d632c8b839d7b318d1cb7b81b9c62570c77dcdf0696b8ce3d52067c79c930f78","benches/combinations.rs":"5b3bd243336d6b6bdc111d66218f3f0a4ecdb10fb72e90db79959e3d8bb2cf6f","benches/combinations_with_replacement.rs":"11f29160652a2d90ce7ca4b1c339c4457888ab6867e2456ce1c62e3adf9be737","benches/fold_specialization.rs":"66ab13fd8576a662afb59ef72c5565f5c3d27f7f30a976450ee5a14958654fa2","benches/k_smallest.rs":"c1bb2aa597def7f7c282d1196f9d70be6d10e1acbae03279c05bc8065544bb8e","benches/powerset.rs":"dc1fd729584147e5d8e4d19c6ca6f8706087d41c3c5beb7293d9ea43b4beab14","benches/specializations.rs":"daa989877d83ccd58e8de529184d50905b3d6fa60a9eeae917f38bd570d72fa4","benches/tree_reduce.rs":"fa4f22f042b76df89094ddf6e925ba42c4c3992f8195e719ed035f2e7cfa05bd","benches/tuple_combinations.rs":"16366158743307a0289fc1df423a3cec45009807d410a9fe9922d5b6f8b7d002","benches/tuples.rs":"5ab542aca40df4390de0ebf3819665df402d924a7dd6f4280e6ffc942bbd25c4","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"42c1b2fc148df52a050b013a57b577ad19911f1fe85b9525863df501979b5cd1","src/adaptors/coalesce.rs":"b57157c205ae077dd398740b61c7f49023aa80868abd8a071a6fe89ae6ecc9ad","src/adaptors/map.rs":"4952ee770cb54e98b2f649efd9c98f18951689358eb9b6bee10f139d056353ae","src/adaptors/mod.rs":"1e0cf7409c7291a923cf87f1c6d27cc57bd9f71ca52f7dd08a429aa994daa6ce","src/adaptors/multi_product.rs":"ad501e8ae4e5089b9d2f2be1f9a4713da6a2103b14daa759e09918409f88e321","src/combinations.rs":"9c4490bc4c7488fe9a8dba656a30493d90abb33006f7abbe3e266c237ffc986b","src/combinations_with_replacement.rs":"c7d6b7a122057e9aab075b2de41440ccd2973a6985fba75c2e93af13de55ef90","src/concat_impl.rs":"d61c00d43eca1193f135e25d3b6afd840c02ef1c573c29b264c47ee3429a45e8","src/cons_tuples_impl.rs":"7f46da33168107860b2b15d05d8edfe618e41bbc66ff0e16baf82d7373c4356d","src/diff.rs":"6e5ba3705a3a076d4fc360594014c90f1dfc597e61e8a629f96efa050e2433f5","src/duplicates_impl.rs":"1be37249b4566edc8da611ed9766ec851a526e7513bd13d80fe97482dcfcf7f3","src/either_or_both.rs":"cac278666b5d3c1fd103d97d15ce4c40960ea459441aeae83c6502087fd2ad8d","src/exactly_one_err.rs":"90b6204551161d27394af72107765dbfe3b51a77f4770c2e506fa4938985a184","src/extrema_set.rs":"11de200d853941716e9aa9a9b520b006704827c3c43a0c5f067906b0941e51d1","src/flatten_ok.rs":"62c18e5221a27949a00de49414306d6dfd601515817c1c8ae6189e3275756dd3","src/format.rs":"3ae6414043e0040f7358028c560437ea49afdbb2416df138a2410169e2619589","src/free.rs":"00ec21acee2ae2b30bf99e62472f9684c0a1719fbafc8dd2e4195ea8377c5b5d","src/group_map.rs":"c9da201137c6bb479b9308bfc38398b76950e39905f4ce8bc435c5318371522c","src/groupbylazy.rs":"5862629719258703aad47977ba1060f20fff15e962e18e6142758ebf6cd4a61c","src/grouping_map.rs":"3896c46ba4bd8ea886e5344a245658235626a104758d5ccecf223544a9ba471b","src/impl_macros.rs":"97fc5f39574805e0c220aa462cf1ae7dcac5c1082d6ee5500e7d71c120db5f88","src/intersperse.rs":"55031819e985c3184275e254c9600ecbe01e9fb49f198039c5da82a87ea5b90e","src/iter_index.rs":"1b0ff8376a4ad855d44db8c662450c777db84e0f4997b53ca575c65b107bb83b","src/k_smallest.rs":"a6840980e4c1aedd6987f93c904d362aa09a101537e447121fff58bb2473638d","src/kmerge_impl.rs":"3f999d55d7def904f71f2ca88b36707461f7f23b32966e0ccaf31d808886d843","src/lazy_buffer.rs":"baa01490fceb5a8dd7bd9c2634e19ce8a785bd1df352a9dd77d1344e3e0f8892","src/lib.rs":"e7f144351cca5018dc12270b4c33f0562afddb92452acfa85153cb276aebd6e9","src/merge_join.rs":"f2f257e63c84ed772b235229cc787ebe9ae009d7c80ed2087002a6b62c5e2133","src/minmax.rs":"0ec34b172ca8efc4aacb96f3e5771bdc5e8ac882876ee0f59d698c3924717c48","src/multipeek_impl.rs":"79eef0be49ad66f15d41808e72c03976c4f7cff5838b69d17975d3ece266f3f8","src/next_array.rs":"295924058891c08f9fe6313a1d9dd0042dcf60f0a514c6a6e009a1396d804fc9","src/pad_tail.rs":"e6bb5b086478600b0dbb8726cae8364bf83ab36d989ef467e1264eea43933b50","src/peek_nth.rs":"093f1a157b1c917f041af5244a5a46311affa2922126e36dc0ee2c501c79b58c","src/peeking_take_while.rs":"075ce13475c84e2cfdfaf1a7a0d0695332102c82a61914ed4c00a7d2634b1d34","src/permutations.rs":"b316084ee14e9e138d22f177367b3bfa24cb3e5e90ab20b9b00a9a23d653496f","src/powerset.rs":"7ab24fefc914b339dd92a6c8e639d0cad34479e09293b3346078856d6bc02d34","src/process_results_impl.rs":"6b5d82447eef4e87fef7b2a8e56b906ac7b000886a468ce421252f34ec86e371","src/put_back_n_impl.rs":"5a58d7a31c03029f0726e4d42de3be869580cf76b73c6d1ef70dd40c240b03a0","src/rciter_impl.rs":"081fd206ba4a601bd65e2f3b8d7c95e3e4a3564beb7c98944bd2e7986959c230","src/repeatn.rs":"dd9a5bf5a63ef9cc6ec5c8a6137c7ffba80f13568b6d001e189daaa29ffbaf39","src/size_hint.rs":"6022c2327ddc6df7e7b939eb60a93ee66ea9aa4d3aab49b9952e663ff4bff10b","src/sources.rs":"ef942af209ca1effcd28a95abedad8c45b659ae2a15b66c2158cb604f6e325f8","src/take_while_inclusive.rs":"1973a9f5322b3dae3b5ccded5912a08a8e2e975b9a5eac666192b118b230d305","src/tee.rs":"dad50ca162627cf0a67786f0993ef27d06cdefc14d412463e58c07824ef409d8","src/tuple_impl.rs":"0213261109e7c65746ccc22425d19141907bf7ea1e3dd4c40e9f278e6148e272","src/unique_impl.rs":"1efc280226f13ddd7dd5f7eedeec0093b704596652c942f3a0b2f8c90fa2e2f7","src/unziptuple.rs":"f3f6a2ee2658fa07db7592f2c344c2e3b1263a21fc75e1325f2be32c9dc1e750","src/with_position.rs":"9ca1eb195d04690b0c3a62a6c0eea349b8042e11c4ca4b80744f54103e1c7355","src/zip_eq_impl.rs":"3282b177e7dece5d3fbdc9b03563f209589a399ea45e70abf23ccca3b5512ac7","src/zip_longest.rs":"5572699564dd5717cc074b7733333ed238c2e9f3e6819d45e33e3a2dbda74478","src/ziptuple.rs":"d3a12221d39c8a5514574adb3ad2ccd1803d514b1cb09fbcd9253e3ddd628310","tests/adaptors_no_collect.rs":"7e6240878b1fc13b6384fdde0317d5d7ccca3e417b10a201ba61eb5255400fda","tests/flatten_ok.rs":"b7894874132918b8229c7150b2637511d8e3e14197d8eeb9382d46b2a514efa2","tests/laziness.rs":"89e6caec10da3d7aeadf9e30d5caf03cda36d07cee8415ff134b5b8e2a2cf144","tests/macros_hygiene.rs":"c2d517badf593c0ba9b70e987a6f8482ed8997547b2e88bbec70babd9b677aa2","tests/merge_join.rs":"5fb506b989f4a331d46cdec5775ea594656985134196099eaf8d3905bdddcdd5","tests/peeking_take_while.rs":"f834361c5520dda15eb9e9ebe87507c905462201412b21859d9f83dab91d0e0b","tests/quick.rs":"d463bf8712b32742c93bc2cf3993031aeaba1f5b0505ca0ecd347313c3da0582","tests/specializations.rs":"fefbdac83bb774186882e3d31be619c9ce1dbfc4191a99ed2ac90aa764737a8f","tests/test_core.rs":"9bbc6772e97a60d93d4021c184b9e4de1c0440a1c48b991a92edc189699fd20d","tests/test_std.rs":"b0e56deefe309b9c11804bd069c744b5caea7960cd4b68244531f6edf38b9741","tests/tuples.rs":"014e4da776174bfe923270e2a359cd9c95b372fce4b952b8138909d6e2c52762","tests/zip.rs":"457e34761d9bf2943a43abd9020d2b1a4492ebff9e4d94efe4c730652fbf62af"},"package":"2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.cargo_vcs_info.json clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo_vcs_info.json --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.cargo_vcs_info.json 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "a015a6831525ee1637df747d3f530a627d9741bf" + }, + "path_in_vcs": "" +} \ No newline at end of file diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.codecov.yml clamav-1.4.6+dfsg/.cargo/vendor/itertools/.codecov.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.codecov.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.codecov.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,7 @@ +coverage: + status: + project: + default: + target: auto + # Allow a tiny drop of overall project coverage in PR to reduce spurious failures. + threshold: 0.25% diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/dependabot.yml clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/dependabot.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/dependabot.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/workflows/ci.yml clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/ci.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/ci.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,101 @@ +name: CI + +on: + pull_request: + paths-ignore: + - "**.md" + merge_group: + paths-ignore: + - "**.md" + +jobs: + check: + runs-on: ubuntu-latest + strategy: + matrix: + features: + [ + "", + "--no-default-features", + "--no-default-features --features use_alloc", + "--all-targets --all-features", + ] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - run: RUSTFLAGS="--deny warnings" cargo clippy ${{ matrix.features }} + + doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: RUSTDOCFLAGS="-Dwarnings" cargo doc --all-features + + msrv: + runs-on: ubuntu-latest + env: + CARGO_NET_GIT_FETCH_WITH_CLI: true + steps: + - uses: actions/checkout@v4 + - uses: taiki-e/install-action@cargo-no-dev-deps + - uses: dtolnay/rust-toolchain@master + with: + # Here, it does not trigger a PR from dependabot. + toolchain: 1.63.0 + - run: cargo no-dev-deps check + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo test --all-features + + miri: + runs-on: ubuntu-latest + env: + CARGO_TERM_COLOR: always + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly + components: miri + - uses: taiki-e/install-action@nextest + - run: | + cargo miri nextest run --all-features + cargo miri test --doc + + check-format: + name: check format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - run: cargo fmt --check + + semver-checks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: obi1kenobi/cargo-semver-checks-action@v2.4 + with: + rust-toolchain: manual + feature-group: all-features + + # Used to signal to branch protections that all other jobs have succeeded. + all-jobs-succeed: + name: All checks succeeded + if: success() + runs-on: ubuntu-latest + needs: [check, msrv, test, check-format, doc] + steps: + - name: Mark the job as successful + run: exit 0 diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/workflows/coverage.yml clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/coverage.yml --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/.github/workflows/coverage.yml 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/.github/workflows/coverage.yml 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,34 @@ +on: + push: + branches: [master] + paths-ignore: + - "**.md" + pull_request: + paths-ignore: + - "**.md" + +name: Code Coverage + +jobs: + coverage: + name: coverage + runs-on: ubuntu-latest + steps: + - name: checkout source + uses: actions/checkout@v4 + + - name: Install nightly toolchain + uses: dtolnay/rust-toolchain@nightly + with: + components: llvm-tools-preview + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + + - name: Run llvm-cov + run: cargo llvm-cov --all-features --doctests --workspace --lcov --output-path lcov.info + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: lcov.info diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/CHANGELOG.md clamav-1.4.6+dfsg/.cargo/vendor/itertools/CHANGELOG.md --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/CHANGELOG.md 2025-06-17 01:41:33.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/CHANGELOG.md 2006-07-24 01:21:28.000000000 +0000 @@ -1,5 +1,192 @@ # Changelog +## 0.14.0 + +### Breaking +- Increased MSRV to 1.63.0 (#960) +- Removed generic parameter from `cons_tuples` (#988) + +### Added +- Added `array_combinations` (#991) +- Added `k_smallest_relaxed` and variants (#925) +- Added `next_array` and `collect_array` (#560) +- Implemented `DoubleEndedIterator` for `FilterOk` (#948) +- Implemented `DoubleEndedIterator` for `FilterMapOk` (#950) + +### Changed +- Allow `Q: ?Sized` in `Itertools::contains` (#971) +- Improved hygiene of `chain!` (#943) +- Improved `into_group_map_by` documentation (#1000) +- Improved `tree_reduce` documentation (#955) +- Improved discoverability of `merge_join_by` (#966) +- Improved discoverability of `take_while_inclusive` (#972) +- Improved documentation of `find_or_last` and `find_or_first` (#984) +- Prevented exponentially large type sizes in `tuple_combinations` (#945) +- Added `track_caller` attr for `asser_equal` (#976) + +### Notable Internal Changes +- Fixed clippy lints (#956, #987, #1008) +- Addressed warnings within doctests (#964) +- CI: Run most tests with miri (#961) +- CI: Speed up "cargo-semver-checks" action (#938) +- Changed an instance of `default_features` in `Cargo.toml` to `default-features` (#985) + +## 0.13.0 + +### Breaking +- Removed implementation of `DoubleEndedIterator` for `ConsTuples` (#853) +- Made `MultiProduct` fused and fixed on an empty iterator (#835, #834) +- Changed `iproduct!` to return tuples for maxi one iterator too (#870) +- Changed `PutBack::put_back` to return the old value (#880) +- Removed deprecated `repeat_call, Itertools::{foreach, step, map_results, fold_results}` (#878) +- Removed `TakeWhileInclusive::new` (#912) + +### Added +- Added `Itertools::{smallest_by, smallest_by_key, largest, largest_by, largest_by_key}` (#654, #885) +- Added `Itertools::tail` (#899) +- Implemented `DoubleEndedIterator` for `ProcessResults` (#910) +- Implemented `Debug` for `FormatWith` (#931) +- Added `Itertools::get` (#891) + +### Changed +- Deprecated `Itertools::group_by` (renamed `chunk_by`) (#866, #879) +- Deprecated `unfold` (use `std::iter::from_fn` instead) (#871) +- Optimized `GroupingMapBy` (#873, #876) +- Relaxed `Fn` bounds to `FnMut` in `diff_with, Itertools::into_group_map_by` (#886) +- Relaxed `Debug/Clone` bounds for `MapInto` (#889) +- Documented the `use_alloc` feature (#887) +- Optimized `Itertools::set_from` (#888) +- Removed badges in `README.md` (#890) +- Added "no-std" categories in `Cargo.toml` (#894) +- Fixed `Itertools::k_smallest` on short unfused iterators (#900) +- Deprecated `Itertools::tree_fold1` (renamed `tree_reduce`) (#895) +- Deprecated `GroupingMap::fold_first` (renamed `reduce`) (#902) +- Fixed `Itertools::k_smallest(0)` to consume the iterator, optimized `Itertools::k_smallest(1)` (#909) +- Specialized `Combinations::nth` (#914) +- Specialized `MergeBy::fold` (#920) +- Specialized `CombinationsWithReplacement::nth` (#923) +- Specialized `FlattenOk::{fold, rfold}` (#927) +- Specialized `Powerset::nth` (#924) +- Documentation fixes (#882, #936) +- Fixed `assert_equal` for iterators longer than `i32::MAX` (#932) +- Updated the `must_use` message of non-lazy `KMergeBy` and `TupleCombinations` (#939) + +### Notable Internal Changes +- Tested iterator laziness (#792) +- Created `CONTRIBUTING.md` (#767) + +## 0.12.1 + +### Added +- Documented iteration order guarantee for `Itertools::[tuple_]combinations` (#822) +- Documented possible panic in `iterate` (#842) +- Implemented `Clone` and `Debug` for `Diff` (#845) +- Implemented `Debug` for `WithPosition` (#859) +- Implemented `Eq` for `MinMaxResult` (#838) +- Implemented `From>` for `Option>` (#843) +- Implemented `PeekingNext` for `RepeatN` (#855) + +### Changed +- Made `CoalesceBy` lazy (#801) +- Optimized `Filter[Map]Ok::next`, `Itertools::partition`, `Unique[By]::next[_back]` (#818) +- Optimized `Itertools::find_position` (#837) +- Optimized `Positions::next[_back]` (#816) +- Optimized `ZipLongest::fold` (#854) +- Relaxed `Debug` bounds for `GroupingMapBy` (#860) +- Specialized `ExactlyOneError::fold` (#826) +- Specialized `Interleave[Shortest]::fold` (#849) +- Specialized `MultiPeek::fold` (#820) +- Specialized `PadUsing::[r]fold` (#825) +- Specialized `PeekNth::fold` (#824) +- Specialized `Positions::[r]fold` (#813) +- Specialized `PutBackN::fold` (#823) +- Specialized `RepeatN::[r]fold` (#821) +- Specialized `TakeWhileInclusive::fold` (#851) +- Specialized `ZipLongest::rfold` (#848) + +### Notable Internal Changes +- Added test coverage in CI (#847, #856) +- Added semver check in CI (#784) +- Enforced `clippy` in CI (#740) +- Enforced `rustdoc` in CI (#840) +- Improved specialization tests (#807) +- More specialization benchmarks (#806) + +## 0.12.0 + +### Breaking +- Made `take_while_inclusive` consume iterator by value (#709) +- Added `Clone` bound to `Unique` (#777) + +### Added +- Added `Itertools::try_len` (#723) +- Added free function `sort_unstable` (#796) +- Added `GroupMap::fold_with` (#778, #785) +- Added `PeekNth::{peek_mut, peek_nth_mut}` (#716) +- Added `PeekNth::{next_if, next_if_eq}` (#734) +- Added conversion into `(Option,Option)` to `EitherOrBoth` (#713) +- Added conversion from `Either` to `EitherOrBoth` (#715) +- Implemented `ExactSizeIterator` for `Tuples` (#761) +- Implemented `ExactSizeIterator` for `(Circular)TupleWindows` (#752) +- Made `EitherOrBoth` a shorthand for `EitherOrBoth` (#719) + +### Changed +- Added missing `#[must_use]` annotations on iterator adaptors (#794) +- Made `Combinations` lazy (#795) +- Made `Intersperse(With)` lazy (#797) +- Made `Permutations` lazy (#793) +- Made `Product` lazy (#800) +- Made `TupleWindows` lazy (#602) +- Specialized `Combinations::{count, size_hint}` (#729) +- Specialized `CombinationsWithReplacement::{count, size_hint}` (#737) +- Specialized `Powerset::fold` (#765) +- Specialized `Powerset::count` (#735) +- Specialized `TupleCombinations::{count, size_hint}` (#763) +- Specialized `TupleCombinations::fold` (#775) +- Specialized `WhileSome::fold` (#780) +- Specialized `WithPosition::fold` (#772) +- Specialized `ZipLongest::fold` (#774) +- Changed `{min, max}_set*` operations require `alloc` feature, instead of `std` (#760) +- Improved documentation of `tree_fold1` (#787) +- Improved documentation of `permutations` (#724) +- Fixed typo in documentation of `multiunzip` (#770) + +### Notable Internal Changes +- Improved specialization tests (#799, #786, #782) +- Simplified implementation of `Permutations` (#739, #748, #790) +- Combined `Merge`/`MergeBy`/`MergeJoinBy` implementations (#736) +- Simplified `Permutations::size_hint` (#739) +- Fix wrapping arithmetic in benchmarks (#770) +- Enforced `rustfmt` in CI (#751) +- Disallowed compile warnings in CI (#720) +- Used `cargo hack` to check MSRV (#754) + +## 0.11.0 + +### Breaking +- Make `Itertools::merge_join_by` also accept functions returning bool (#704) +- Implement `PeekingNext` transitively over mutable references (#643) +- Change `with_position` to yield `(Position, Item)` instead of `Position` (#699) + +### Added +- Add `Itertools::take_while_inclusive` (#616) +- Implement `PeekingNext` for `PeekingTakeWhile` (#644) +- Add `EitherOrBoth::{just_left, just_right, into_left, into_right, as_deref, as_deref_mut, left_or_insert, right_or_insert, left_or_insert_with, right_or_insert_with, insert_left, insert_right, insert_both}` (#629) +- Implement `Clone` for `CircularTupleWindows` (#686) +- Implement `Clone` for `Chunks` (#683) +- Add `Itertools::process_results` (#680) + +### Changed +- Use `Cell` instead of `RefCell` in `Format` and `FormatWith` (#608) +- CI tweaks (#674, #675) +- Document and test the difference between stable and unstable sorts (#653) +- Fix documentation error on `Itertools::max_set_by_key` (#692) +- Move MSRV metadata to `Cargo.toml` (#672) +- Implement `equal` with `Iterator::eq` (#591) + +## 0.10.5 + - Maintenance + ## 0.10.4 - Add `EitherOrBoth::or` and `EitherOrBoth::or_else` (#593) - Add `min_set`, `max_set` et al. (#613, #323) @@ -7,6 +194,9 @@ - Documentation fixes (#612, #625, #632, #633, #634, #638) - Code maintenance (#623, #624, #627, #630) +## 0.10.3 + - Maintenance + ## 0.10.2 - Add `Itertools::multiunzip` (#362, #565) - Add `intersperse` and `intersperse_with` free functions (#555) diff -Nru clamav-1.4.3+dfsg/.cargo/vendor/itertools/CONTRIBUTING.md clamav-1.4.6+dfsg/.cargo/vendor/itertools/CONTRIBUTING.md --- clamav-1.4.3+dfsg/.cargo/vendor/itertools/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ clamav-1.4.6+dfsg/.cargo/vendor/itertools/CONTRIBUTING.md 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,189 @@ +# Contributing to itertools + +We use stable Rust only. +Please check the minimum version of Rust we use in `Cargo.toml`. + +_If you are proposing a major change to CI or a new iterator adaptor for this crate, +then **please first file an issue** describing your proposal._ +[Usual concerns about new methods](https://github.com/rust-itertools/itertools/issues/413#issuecomment-657670781). + +To pass CI tests successfully, your code must be free of "compiler warnings" and "clippy warnings" and be "rustfmt" formatted. + +Note that small PRs are easier to review and therefore are more easily merged. + +## Write a new method/adaptor for `Itertools` trait +In general, the code logic should be tested with [quickcheck](https://crates.io/crates/quickcheck) tests in `tests/quick.rs` +which allow us to test properties about the code with randomly generated inputs. + +### Behind `use_std`/`use_alloc` feature? +If it needs the "std" (such as using hashes) then it should be behind the `use_std` feature, +or if it requires heap allocation (such as using vectors) then it should be behind the `use_alloc` feature. +Otherwise it should be able to run in `no_std` context. + +This mostly applies to your new module, each import from it, and to your new `Itertools` method. + +### Pick the right receiver +`self`, `&mut self` or `&self`? From [#710](https://github.com/rust-itertools/itertools/pull/710): + +- Take by value when: + - It transfers ownership to another iterator type, such as `filter`, `map`... + - It consumes the iterator completely, such as `count`, `last`, `max`... +- Mutably borrow when it consumes only part of the iterator, such as `find`, `all`, `try_collect`... +- Immutably borrow when there is no change, such as `size_hint`. + +### Laziness +Iterators are [lazy](https://doc.rust-lang.org/std/iter/index.html#laziness): + +- structs of iterator adaptors should have `#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]` ; +- structs of iterators should have `#[must_use = "iterators are lazy and do nothing unless consumed"]`. + +Those behaviors are **tested** in `tests/laziness.rs`. + +## Specialize `Iterator` methods +It might be more performant to specialize some methods. +However, each specialization should be thoroughly tested. + +Correctly specializing methods can be difficult, and _we do not require that you do it on your initial PR_. + +Most of the time, we want specializations of: + +- [`size_hint`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.size_hint): + It mostly allows allocation optimizations. + When always exact, it also enables to implement `ExactSizeIterator`. + See our private module `src/size_hint.rs` for helpers. +- [`fold`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold) + might make iteration faster than calling `next` repeatedly. +- [`count`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.count), + [`last`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.last), + [`nth`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.nth) + as we might be able to avoid iterating on every item with `next`. + +Additionally, + +- `for_each`, `reduce`, `max/min[_by[_key]]` and `partition` all rely on `fold` so you should specialize it instead. +- `all`, `any`, `find`, `find_map`, `cmp`, `partial_cmp`, `eq`, `ne`, `lt`, `le`, `gt`, `ge` and `position` all rely (by default) on `try_fold` + which we can not specialize on stable rust, so you might want to wait it stabilizes + or specialize each of them. +- `DoubleEndedIterator::{nth_back, rfold, rfind}`: similar reasoning. + +An adaptor might use the inner iterator specializations for its own specializations. + +They are **tested** in `tests/specializations.rs` and **benchmarked** in `benches/specializations.rs` +(build those benchmarks is slow so you might want to temporarily remove the ones you do not want to measure). + +## Additional implementations +### The [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html) implementation +All our iterators should implement `Debug`. + +When one of the field is not debuggable (such as _functions_), you must not derive `Debug`. +Instead, manually implement it and _ignore this field_ in our helper macro `debug_fmt_fields`. + +